From 8dbb1bb6057ff4d685b72bd2dbb53c932cd2202c Mon Sep 17 00:00:00 2001 From: zlaxy Date: Wed, 6 Feb 2019 00:49:12 +0300 Subject: [PATCH] init --- .gitignore | 28 + bml/MANIFEST | 93 + bml/MANIFEST.SKIP | 11 + bml/Makefile.PL | 36 + bml/doc/bml-notes.txt | 61 + bml/doc/docbook/BUILD.txt | 5 + bml/doc/docbook/appx.gfdl.xml | 450 + bml/doc/docbook/book.ent | 35 + bml/doc/docbook/book.xml | 15 + bml/doc/docbook/bookinfo.xml | 35 + bml/doc/docbook/build.pl | 88 + bml/doc/docbook/core.xml | 115 + bml/doc/docbook/flags.xml | 89 + bml/doc/docbook/index.xml | 8 + bml/doc/docbook/preface.xml | 64 + bml/doc/docbook/tutorial.xml | 552 + bml/lib/Apache/BML.pm | 2065 +++ bml/t/00_require.t | 40 + bml/t/10_simple.t | 210 + bml/t/20_render.t | 185 + bml/test/Pblocks/scheme.look | 8 + bml/test/_config.bml | 9 + bml/test/bml-profile.pl | 52 + bml/test/brads/_config.bml | 9 + bml/test/brads/scheme.look | 9 + bml/test/brads/test1.bml | 16 + bml/test/brads/test1.correct | 12 + bml/test/codeblocks/_config.bml | 9 + bml/test/codeblocks/carry-variables.bml | 6 + bml/test/codeblocks/carry-variables.correct | 6 + bml/test/codeblocks/complex1.bml | 15 + bml/test/codeblocks/complex1.correct | 4 + bml/test/codeblocks/complex2.bml | 28 + bml/test/codeblocks/complex2.correct | 6 + bml/test/codeblocks/re-expand.bml | 9 + bml/test/codeblocks/re-expand.correct | 9 + bml/test/codeblocks/scheme.look | 4 + bml/test/codeblocks/simple.bml | 12 + bml/test/codeblocks/simple.correct | 12 + bml/test/comments/_config.bml | 9 + bml/test/comments/basic.bml | 22 + bml/test/comments/basic.correct | 18 + bml/test/comments/rendered.bml | 13 + bml/test/comments/rendered.correct | 11 + bml/test/comments/scheme.look | 6 + bml/test/escape/_config.bml | 9 + bml/test/escape/ea.bml | 34 + bml/test/escape/ea.correct | 32 + bml/test/escape/eb.bml | 7 + bml/test/escape/eb.correct | 7 + bml/test/escape/eh.bml | 26 + bml/test/escape/eh.correct | 24 + bml/test/escape/eu.bml | 3 + bml/test/escape/eu.correct | 3 + bml/test/escape/scheme.look | 1 + bml/test/fake_root/_config.bml | 9 + bml/test/fake_root/bluewhite.look | 251 + bml/test/fake_root/bml-simple.bml | 14 + bml/test/fake_root/bml-simple.correct | 10 + bml/test/fake_root/bml-test.bml | 265 + bml/test/fake_root/bml-test.correct | 245 + bml/test/fake_root/global.look | 286 + bml/test/include/_config.bml | 9 + bml/test/include/loremipsum.txt | 31 + bml/test/include/plain.bml | 6 + bml/test/include/plain.correct | 2 + bml/test/include/scheme.look | 1 + bml/test/info/_config.bml | 9 + bml/test/info/localblocks.bml | 9 + bml/test/info/localblocks.correct | 3 + bml/test/info/package.bml | 9 + bml/test/info/package.correct | 2 + bml/test/info/scheme.look | 0 bml/test/newtest.pl | 82 + bml/test/recursion/_config.bml | 9 + bml/test/recursion/infinite.bml | 11 + bml/test/recursion/infinite.correct | 6 + bml/test/recursion/nested.bml | 1 + bml/test/recursion/nested.correct | 1 + bml/test/recursion/scheme.look | 7 + bml/test/syntax-errors/_config.bml | 9 + bml/test/syntax-errors/dangling-tagopen.bml | 1 + .../syntax-errors/dangling-tagopen.correct | 1 + bml/test/syntax-errors/no-close.bml | 2 + bml/test/syntax-errors/no-close.correct | 2 + bml/test/syntax-errors/onlyopen.bml | 7 + bml/test/syntax-errors/onlyopen.correct | 1 + bml/test/syntax-errors/scheme.look | 2 + bml/test/syntax-errors/spaces.bml | 12 + bml/test/syntax-errors/spaces.correct | 11 + bml/test/tutorial-example1/project.bml | 8 + bml/test/tutorial-example1/project.correct | 10 + bml/test/tutorial-example1/scheme.look | 6 + bml/test/tutorial-example2/index.bml | 27 + bml/test/tutorial-example2/index.correct | 27 + bml/test/tutorial-example2/scheme.look | 2 + bml/test/tutorial-example3/index.bml | 3 + bml/test/tutorial-example3/index.correct | 6 + bml/test/tutorial-example3/scheme.look | 6 + bml/test/tutorial-example4/index.bml | 9 + bml/test/tutorial-example4/index.correct | 9 + bml/test/tutorial-example4/scheme.look | 11 + bml/test/tutorial-example5/_config.bml | 9 + bml/test/tutorial-example5/readinglist.bml | 8 + .../tutorial-example5/readinglist.correct | 10 + bml/test/tutorial-example5/scheme.look | 11 + bml/test/tutorial-example6/index.bml | 4 + bml/test/tutorial-example6/index.correct | 4 + bml/test/tutorial-example6/scheme.look | 3 + bml/test/tutorial-example7/index.bml | 5 + bml/test/tutorial-example7/index.correct | 5 + bml/test/tutorial-example7/scheme.look | 3 + bml/test/tutorial1/_config.bml | 9 + bml/test/tutorial1/index.bml | 21 + bml/test/tutorial1/index.correct | 20 + bml/test/tutorial1/scheme.look | 2 + bml/test/tutorial2/_config.bml | 9 + bml/test/tutorial2/index.bml | 18 + bml/test/tutorial2/index.correct | 21 + bml/test/tutorial2/scheme.look | 13 + images/mood/charitycam/aliens/angry.gif | Bin 0 -> 1317 bytes images/mood/charitycam/aliens/anxious.gif | Bin 0 -> 1055 bytes images/mood/charitycam/aliens/artistic.gif | Bin 0 -> 2101 bytes images/mood/charitycam/aliens/awake.gif | Bin 0 -> 1034 bytes images/mood/charitycam/aliens/bitchy.gif | Bin 0 -> 1319 bytes images/mood/charitycam/aliens/blank.gif | Bin 0 -> 1277 bytes images/mood/charitycam/aliens/cold.gif | Bin 0 -> 1645 bytes images/mood/charitycam/aliens/confused.gif | Bin 0 -> 762 bytes images/mood/charitycam/aliens/determined.gif | Bin 0 -> 1221 bytes images/mood/charitycam/aliens/dirty.gif | Bin 0 -> 1252 bytes images/mood/charitycam/aliens/dorky.gif | Bin 0 -> 1073 bytes images/mood/charitycam/aliens/drunk.gif | Bin 0 -> 1701 bytes images/mood/charitycam/aliens/embarrased.gif | Bin 0 -> 594 bytes images/mood/charitycam/aliens/energetic.gif | Bin 0 -> 1937 bytes images/mood/charitycam/aliens/envious.gif | Bin 0 -> 992 bytes images/mood/charitycam/aliens/flirty.gif | Bin 0 -> 1024 bytes images/mood/charitycam/aliens/full.gif | Bin 0 -> 1261 bytes images/mood/charitycam/aliens/gloomy.gif | Bin 0 -> 874 bytes images/mood/charitycam/aliens/happy.gif | Bin 0 -> 1037 bytes images/mood/charitycam/aliens/high.gif | Bin 0 -> 763 bytes images/mood/charitycam/aliens/horny.gif | Bin 0 -> 2064 bytes images/mood/charitycam/aliens/hot.gif | Bin 0 -> 1433 bytes images/mood/charitycam/aliens/hungry.gif | Bin 0 -> 720 bytes .../mood/charitycam/aliens/indescribable.gif | Bin 0 -> 2433 bytes images/mood/charitycam/aliens/index.html | 80 + images/mood/charitycam/aliens/irate.gif | Bin 0 -> 855 bytes images/mood/charitycam/aliens/loved.gif | Bin 0 -> 1172 bytes images/mood/charitycam/aliens/nerdy.gif | Bin 0 -> 1360 bytes images/mood/charitycam/aliens/okay.gif | Bin 0 -> 1011 bytes images/mood/charitycam/aliens/restless.gif | Bin 0 -> 1919 bytes images/mood/charitycam/aliens/sad.gif | Bin 0 -> 2551 bytes images/mood/charitycam/aliens/sick.gif | Bin 0 -> 3064 bytes images/mood/charitycam/aliens/silly.gif | Bin 0 -> 1046 bytes images/mood/charitycam/aliens/sleepy.gif | Bin 0 -> 1096 bytes images/mood/charitycam/aliens/sore.gif | Bin 0 -> 2127 bytes images/mood/charitycam/aliens/stressed.gif | Bin 0 -> 1226 bytes images/mood/charitycam/aliens/surprised.gif | Bin 0 -> 1047 bytes images/mood/charitycam/aliens/thirsty.gif | Bin 0 -> 2627 bytes images/mood/charitycam/aliens/thoughtful.gif | Bin 0 -> 832 bytes images/mood/charitycam/aliens/working.gif | Bin 0 -> 1897 bytes images/mood/charitycam/bears/angry.gif | Bin 0 -> 1671 bytes images/mood/charitycam/bears/artistic.gif | Bin 0 -> 2259 bytes images/mood/charitycam/bears/awake.gif | Bin 0 -> 2749 bytes images/mood/charitycam/bears/blank.gif | Bin 0 -> 1502 bytes images/mood/charitycam/bears/cheerful.gif | Bin 0 -> 1707 bytes images/mood/charitycam/bears/cold.gif | Bin 0 -> 1359 bytes images/mood/charitycam/bears/curious.gif | Bin 0 -> 2608 bytes images/mood/charitycam/bears/determined.gif | Bin 0 -> 1541 bytes images/mood/charitycam/bears/dirty.gif | Bin 0 -> 2396 bytes images/mood/charitycam/bears/drunk.gif | Bin 0 -> 2700 bytes images/mood/charitycam/bears/envious.gif | Bin 0 -> 2831 bytes images/mood/charitycam/bears/excited.gif | Bin 0 -> 1196 bytes images/mood/charitycam/bears/full.gif | Bin 0 -> 3308 bytes images/mood/charitycam/bears/gloomy.gif | Bin 0 -> 2820 bytes images/mood/charitycam/bears/good.gif | Bin 0 -> 1512 bytes images/mood/charitycam/bears/happy.gif | Bin 0 -> 2512 bytes images/mood/charitycam/bears/high.gif | Bin 0 -> 2739 bytes images/mood/charitycam/bears/hopeful.gif | Bin 0 -> 1390 bytes images/mood/charitycam/bears/horny.gif | Bin 0 -> 1508 bytes images/mood/charitycam/bears/hot.gif | Bin 0 -> 1440 bytes images/mood/charitycam/bears/hungry.gif | Bin 0 -> 2634 bytes .../mood/charitycam/bears/indescribable.gif | Bin 0 -> 3824 bytes images/mood/charitycam/bears/index.html | 76 + images/mood/charitycam/bears/loved.gif | Bin 0 -> 2669 bytes images/mood/charitycam/bears/nerdy.gif | Bin 0 -> 1414 bytes images/mood/charitycam/bears/okay.gif | Bin 0 -> 1506 bytes images/mood/charitycam/bears/sad.gif | Bin 0 -> 2242 bytes images/mood/charitycam/bears/scared.gif | Bin 0 -> 1191 bytes images/mood/charitycam/bears/shocked.gif | Bin 0 -> 1198 bytes images/mood/charitycam/bears/sick.gif | Bin 0 -> 2499 bytes images/mood/charitycam/bears/silly.gif | Bin 0 -> 3017 bytes images/mood/charitycam/bears/stressed.gif | Bin 0 -> 1383 bytes images/mood/charitycam/bears/thirsty.gif | Bin 0 -> 2271 bytes images/mood/charitycam/bears/thoughtful.gif | Bin 0 -> 2847 bytes images/mood/charitycam/bears/tired.gif | Bin 0 -> 1587 bytes images/mood/charitycam/bears/working.gif | Bin 0 -> 1551 bytes images/mood/charitycam/blackbox/angry.gif | Bin 0 -> 363 bytes images/mood/charitycam/blackbox/artistic.gif | Bin 0 -> 569 bytes images/mood/charitycam/blackbox/bouncy.gif | Bin 0 -> 235 bytes images/mood/charitycam/blackbox/cold.gif | Bin 0 -> 362 bytes images/mood/charitycam/blackbox/crazy.gif | Bin 0 -> 342 bytes images/mood/charitycam/blackbox/curious.gif | Bin 0 -> 260 bytes .../mood/charitycam/blackbox/determined.gif | Bin 0 -> 215 bytes images/mood/charitycam/blackbox/devilish.gif | Bin 0 -> 243 bytes images/mood/charitycam/blackbox/dirty.gif | Bin 0 -> 324 bytes images/mood/charitycam/blackbox/drunk.gif | Bin 0 -> 317 bytes .../mood/charitycam/blackbox/embarrassed.gif | Bin 0 -> 254 bytes images/mood/charitycam/blackbox/envy.gif | Bin 0 -> 238 bytes images/mood/charitycam/blackbox/gloomy.gif | Bin 0 -> 284 bytes images/mood/charitycam/blackbox/green.gif | Bin 0 -> 303 bytes images/mood/charitycam/blackbox/happy.gif | Bin 0 -> 227 bytes images/mood/charitycam/blackbox/hot.gif | Bin 0 -> 889 bytes images/mood/charitycam/blackbox/hungry.gif | Bin 0 -> 457 bytes images/mood/charitycam/blackbox/index.html | 71 + images/mood/charitycam/blackbox/loved.gif | Bin 0 -> 273 bytes images/mood/charitycam/blackbox/nerdy.gif | Bin 0 -> 225 bytes images/mood/charitycam/blackbox/okay.gif | Bin 0 -> 202 bytes images/mood/charitycam/blackbox/peaceful.gif | Bin 0 -> 245 bytes images/mood/charitycam/blackbox/relaxed.gif | Bin 0 -> 188 bytes images/mood/charitycam/blackbox/sad.gif | Bin 0 -> 257 bytes images/mood/charitycam/blackbox/scared.gif | Bin 0 -> 239 bytes images/mood/charitycam/blackbox/sore.gif | Bin 0 -> 250 bytes images/mood/charitycam/blackbox/suprised.gif | Bin 0 -> 472 bytes images/mood/charitycam/blackbox/thirsty.gif | Bin 0 -> 362 bytes .../mood/charitycam/blackbox/thoughtful.gif | Bin 0 -> 287 bytes images/mood/charitycam/blackbox/tired.gif | Bin 0 -> 251 bytes images/mood/charitycam/blackbox/working.gif | Bin 0 -> 268 bytes images/mood/charitycam/faces-animated/1.gif | Bin 0 -> 2322 bytes images/mood/charitycam/faces-animated/10.gif | Bin 0 -> 2102 bytes images/mood/charitycam/faces-animated/11.gif | Bin 0 -> 2361 bytes images/mood/charitycam/faces-animated/12.gif | Bin 0 -> 2289 bytes images/mood/charitycam/faces-animated/13.gif | Bin 0 -> 2209 bytes images/mood/charitycam/faces-animated/14.gif | Bin 0 -> 2463 bytes images/mood/charitycam/faces-animated/15.gif | Bin 0 -> 2118 bytes images/mood/charitycam/faces-animated/16.gif | Bin 0 -> 2423 bytes images/mood/charitycam/faces-animated/17.gif | Bin 0 -> 2433 bytes images/mood/charitycam/faces-animated/18.gif | Bin 0 -> 2443 bytes images/mood/charitycam/faces-animated/19.gif | Bin 0 -> 2269 bytes images/mood/charitycam/faces-animated/2.gif | Bin 0 -> 2258 bytes images/mood/charitycam/faces-animated/20.gif | Bin 0 -> 2217 bytes images/mood/charitycam/faces-animated/21.gif | Bin 0 -> 2279 bytes images/mood/charitycam/faces-animated/22.gif | Bin 0 -> 2488 bytes images/mood/charitycam/faces-animated/23.gif | Bin 0 -> 2555 bytes images/mood/charitycam/faces-animated/24.gif | Bin 0 -> 2465 bytes images/mood/charitycam/faces-animated/25.gif | Bin 0 -> 2234 bytes images/mood/charitycam/faces-animated/26.gif | Bin 0 -> 2278 bytes images/mood/charitycam/faces-animated/27.gif | Bin 0 -> 2339 bytes images/mood/charitycam/faces-animated/28.gif | Bin 0 -> 2420 bytes images/mood/charitycam/faces-animated/29.gif | Bin 0 -> 2123 bytes images/mood/charitycam/faces-animated/3.gif | Bin 0 -> 2345 bytes images/mood/charitycam/faces-animated/30.gif | Bin 0 -> 2429 bytes images/mood/charitycam/faces-animated/31.gif | Bin 0 -> 2516 bytes images/mood/charitycam/faces-animated/32.gif | Bin 0 -> 2121 bytes images/mood/charitycam/faces-animated/33.gif | Bin 0 -> 2352 bytes images/mood/charitycam/faces-animated/34.gif | Bin 0 -> 2513 bytes images/mood/charitycam/faces-animated/4.gif | Bin 0 -> 2363 bytes images/mood/charitycam/faces-animated/5.gif | Bin 0 -> 2104 bytes images/mood/charitycam/faces-animated/6.gif | Bin 0 -> 2404 bytes images/mood/charitycam/faces-animated/7.gif | Bin 0 -> 2368 bytes images/mood/charitycam/faces-animated/8.gif | Bin 0 -> 2322 bytes images/mood/charitycam/faces-animated/9.gif | Bin 0 -> 2240 bytes .../mood/charitycam/faces-animated/index.html | 75 + images/mood/charitycam/faces/1.gif | Bin 0 -> 1607 bytes images/mood/charitycam/faces/10.gif | Bin 0 -> 1530 bytes images/mood/charitycam/faces/11.gif | Bin 0 -> 1604 bytes images/mood/charitycam/faces/12.gif | Bin 0 -> 1672 bytes images/mood/charitycam/faces/13.gif | Bin 0 -> 1532 bytes images/mood/charitycam/faces/14.gif | Bin 0 -> 1648 bytes images/mood/charitycam/faces/15.gif | Bin 0 -> 1517 bytes images/mood/charitycam/faces/16.gif | Bin 0 -> 1649 bytes images/mood/charitycam/faces/17.gif | Bin 0 -> 1622 bytes images/mood/charitycam/faces/18.gif | Bin 0 -> 1634 bytes images/mood/charitycam/faces/19.gif | Bin 0 -> 1594 bytes images/mood/charitycam/faces/2.gif | Bin 0 -> 1617 bytes images/mood/charitycam/faces/20.gif | Bin 0 -> 1530 bytes images/mood/charitycam/faces/21.gif | Bin 0 -> 1594 bytes images/mood/charitycam/faces/22.gif | Bin 0 -> 1648 bytes images/mood/charitycam/faces/23.gif | Bin 0 -> 1683 bytes images/mood/charitycam/faces/24.gif | Bin 0 -> 1611 bytes images/mood/charitycam/faces/25.gif | Bin 0 -> 1572 bytes images/mood/charitycam/faces/26.gif | Bin 0 -> 1516 bytes images/mood/charitycam/faces/27.gif | Bin 0 -> 1553 bytes images/mood/charitycam/faces/28.gif | Bin 0 -> 1617 bytes images/mood/charitycam/faces/29.gif | Bin 0 -> 1531 bytes images/mood/charitycam/faces/3.gif | Bin 0 -> 1572 bytes images/mood/charitycam/faces/30.gif | Bin 0 -> 1632 bytes images/mood/charitycam/faces/31.gif | Bin 0 -> 1659 bytes images/mood/charitycam/faces/32.gif | Bin 0 -> 1495 bytes images/mood/charitycam/faces/33.gif | Bin 0 -> 1588 bytes images/mood/charitycam/faces/34.gif | Bin 0 -> 1969 bytes images/mood/charitycam/faces/4.gif | Bin 0 -> 1602 bytes images/mood/charitycam/faces/5.gif | Bin 0 -> 1472 bytes images/mood/charitycam/faces/6.gif | Bin 0 -> 1619 bytes images/mood/charitycam/faces/7.gif | Bin 0 -> 1599 bytes images/mood/charitycam/faces/8.gif | Bin 0 -> 1621 bytes images/mood/charitycam/faces/9.gif | Bin 0 -> 1557 bytes images/mood/charitycam/faces/index.html | 75 + images/mood/charitycam/flowers/angry.gif | Bin 0 -> 1406 bytes images/mood/charitycam/flowers/artistic.gif | Bin 0 -> 2623 bytes images/mood/charitycam/flowers/blank.gif | Bin 0 -> 1524 bytes images/mood/charitycam/flowers/cold.gif | Bin 0 -> 1622 bytes images/mood/charitycam/flowers/confused.gif | Bin 0 -> 1943 bytes images/mood/charitycam/flowers/dirty.gif | Bin 0 -> 2852 bytes images/mood/charitycam/flowers/drunk.gif | Bin 0 -> 2029 bytes images/mood/charitycam/flowers/envious.gif | Bin 0 -> 2237 bytes images/mood/charitycam/flowers/excited.gif | Bin 0 -> 1907 bytes images/mood/charitycam/flowers/full.gif | Bin 0 -> 2405 bytes images/mood/charitycam/flowers/gloomy.gif | Bin 0 -> 2662 bytes images/mood/charitycam/flowers/goofy.gif | Bin 0 -> 2042 bytes images/mood/charitycam/flowers/happy.gif | Bin 0 -> 1895 bytes images/mood/charitycam/flowers/high.gif | Bin 0 -> 1928 bytes images/mood/charitycam/flowers/horny.gif | Bin 0 -> 1847 bytes images/mood/charitycam/flowers/hot.gif | Bin 0 -> 2876 bytes .../mood/charitycam/flowers/indescribable.gif | Bin 0 -> 2424 bytes images/mood/charitycam/flowers/index.html | 74 + images/mood/charitycam/flowers/loved.gif | Bin 0 -> 1964 bytes images/mood/charitycam/flowers/nerdy.gif | Bin 0 -> 1118 bytes images/mood/charitycam/flowers/okay.gif | Bin 0 -> 1711 bytes images/mood/charitycam/flowers/pissed.gif | Bin 0 -> 1623 bytes .../mood/charitycam/flowers/rejuvenated.gif | Bin 0 -> 3744 bytes images/mood/charitycam/flowers/restless.gif | Bin 0 -> 1295 bytes images/mood/charitycam/flowers/sad.gif | Bin 0 -> 2000 bytes images/mood/charitycam/flowers/scared.gif | Bin 0 -> 1084 bytes images/mood/charitycam/flowers/shocked.gif | Bin 0 -> 1411 bytes images/mood/charitycam/flowers/sick.gif | Bin 0 -> 2123 bytes images/mood/charitycam/flowers/silly.gif | Bin 0 -> 2670 bytes images/mood/charitycam/flowers/sore.gif | Bin 0 -> 2166 bytes images/mood/charitycam/flowers/stressed.gif | Bin 0 -> 1517 bytes images/mood/charitycam/flowers/thirsty.gif | Bin 0 -> 2604 bytes images/mood/charitycam/flowers/thoughtful.gif | Bin 0 -> 1932 bytes images/mood/charitycam/flowers/tired.gif | Bin 0 -> 1869 bytes images/mood/charitycam/frogs/angry.gif | Bin 0 -> 1410 bytes images/mood/charitycam/frogs/artistic.gif | Bin 0 -> 2369 bytes images/mood/charitycam/frogs/awake.gif | Bin 0 -> 2867 bytes images/mood/charitycam/frogs/blank.gif | Bin 0 -> 1298 bytes images/mood/charitycam/frogs/cold.gif | Bin 0 -> 1348 bytes images/mood/charitycam/frogs/confused.gif | Bin 0 -> 1351 bytes images/mood/charitycam/frogs/determined.gif | Bin 0 -> 1341 bytes images/mood/charitycam/frogs/dirty.gif | Bin 0 -> 3116 bytes images/mood/charitycam/frogs/drunk.gif | Bin 0 -> 1491 bytes images/mood/charitycam/frogs/embarrassed.gif | Bin 0 -> 1790 bytes images/mood/charitycam/frogs/energetic.gif | Bin 0 -> 1315 bytes images/mood/charitycam/frogs/envious.gif | Bin 0 -> 3072 bytes images/mood/charitycam/frogs/flirty.gif | Bin 0 -> 1552 bytes images/mood/charitycam/frogs/full.gif | Bin 0 -> 1878 bytes images/mood/charitycam/frogs/gloomy.gif | Bin 0 -> 1749 bytes images/mood/charitycam/frogs/happy.gif | Bin 0 -> 1315 bytes images/mood/charitycam/frogs/high.gif | Bin 0 -> 1383 bytes images/mood/charitycam/frogs/hopeful.gif | Bin 0 -> 1618 bytes images/mood/charitycam/frogs/horny.gif | Bin 0 -> 1314 bytes images/mood/charitycam/frogs/hungry.gif | Bin 0 -> 2651 bytes .../mood/charitycam/frogs/indescribable.gif | Bin 0 -> 2736 bytes images/mood/charitycam/frogs/index.html | 76 + images/mood/charitycam/frogs/loved.gif | Bin 0 -> 1388 bytes images/mood/charitycam/frogs/melancholy.gif | Bin 0 -> 2496 bytes images/mood/charitycam/frogs/nauseated.gif | Bin 0 -> 2527 bytes images/mood/charitycam/frogs/nerdy.gif | Bin 0 -> 1166 bytes images/mood/charitycam/frogs/okay.gif | Bin 0 -> 1299 bytes images/mood/charitycam/frogs/refreshed.gif | Bin 0 -> 3614 bytes images/mood/charitycam/frogs/sad.gif | Bin 0 -> 2596 bytes images/mood/charitycam/frogs/scared.gif | Bin 0 -> 1253 bytes images/mood/charitycam/frogs/sick.gif | Bin 0 -> 1254 bytes images/mood/charitycam/frogs/silly.gif | Bin 0 -> 2458 bytes images/mood/charitycam/frogs/stressed.gif | Bin 0 -> 1379 bytes images/mood/charitycam/frogs/thirsty.gif | Bin 0 -> 1426 bytes images/mood/charitycam/frogs/thoughtful.gif | Bin 0 -> 2658 bytes images/mood/charitycam/frogs/tired.gif | Bin 0 -> 1411 bytes images/mood/charitycam/goth_boy/angry.gif | Bin 0 -> 1106 bytes images/mood/charitycam/goth_boy/artistic.gif | Bin 0 -> 547 bytes images/mood/charitycam/goth_boy/awake.gif | Bin 0 -> 830 bytes images/mood/charitycam/goth_boy/blank.gif | Bin 0 -> 814 bytes images/mood/charitycam/goth_boy/bouncy.gif | Bin 0 -> 755 bytes images/mood/charitycam/goth_boy/cold.gif | Bin 0 -> 683 bytes images/mood/charitycam/goth_boy/confused.gif | Bin 0 -> 1514 bytes .../mood/charitycam/goth_boy/determined.gif | Bin 0 -> 1018 bytes images/mood/charitycam/goth_boy/devlish.gif | Bin 0 -> 1016 bytes images/mood/charitycam/goth_boy/dirty.gif | Bin 0 -> 1110 bytes images/mood/charitycam/goth_boy/drunk.gif | Bin 0 -> 1117 bytes .../mood/charitycam/goth_boy/embarrased.gif | Bin 0 -> 409 bytes images/mood/charitycam/goth_boy/envious.gif | Bin 0 -> 1054 bytes images/mood/charitycam/goth_boy/full.gif | Bin 0 -> 1150 bytes images/mood/charitycam/goth_boy/gloomy.gif | Bin 0 -> 1318 bytes images/mood/charitycam/goth_boy/happy.gif | Bin 0 -> 1007 bytes images/mood/charitycam/goth_boy/high.gif | Bin 0 -> 1106 bytes images/mood/charitycam/goth_boy/hot.gif | Bin 0 -> 609 bytes images/mood/charitycam/goth_boy/hungry.gif | Bin 0 -> 322 bytes images/mood/charitycam/goth_boy/index.html | 74 + images/mood/charitycam/goth_boy/loved.gif | Bin 0 -> 625 bytes images/mood/charitycam/goth_boy/nerdy.gif | Bin 0 -> 1060 bytes images/mood/charitycam/goth_boy/okay.gif | Bin 0 -> 1010 bytes images/mood/charitycam/goth_boy/sad.gif | Bin 0 -> 1859 bytes images/mood/charitycam/goth_boy/scared.gif | Bin 0 -> 499 bytes images/mood/charitycam/goth_boy/shocked.gif | Bin 0 -> 1183 bytes images/mood/charitycam/goth_boy/sick.gif | Bin 0 -> 1680 bytes images/mood/charitycam/goth_boy/silly.gif | Bin 0 -> 1569 bytes images/mood/charitycam/goth_boy/sleepy.gif | Bin 0 -> 1045 bytes images/mood/charitycam/goth_boy/stressed.gif | Bin 0 -> 692 bytes images/mood/charitycam/goth_boy/thirsty.gif | Bin 0 -> 1241 bytes .../mood/charitycam/goth_boy/thoughtful.gif | Bin 0 -> 1393 bytes images/mood/charitycam/goth_boy/tired.gif | Bin 0 -> 1014 bytes images/mood/charitycam/goth_boy/working.gif | Bin 0 -> 460 bytes images/mood/charitycam/goth_girl/angry.gif | Bin 0 -> 771 bytes images/mood/charitycam/goth_girl/artistic.gif | Bin 0 -> 751 bytes images/mood/charitycam/goth_girl/cold.gif | Bin 0 -> 2172 bytes images/mood/charitycam/goth_girl/curious.gif | Bin 0 -> 806 bytes .../mood/charitycam/goth_girl/determined.gif | Bin 0 -> 815 bytes images/mood/charitycam/goth_girl/devious.gif | Bin 0 -> 437 bytes images/mood/charitycam/goth_girl/dirty.gif | Bin 0 -> 1430 bytes images/mood/charitycam/goth_girl/drunk.gif | Bin 0 -> 723 bytes .../mood/charitycam/goth_girl/energetic.gif | Bin 0 -> 648 bytes images/mood/charitycam/goth_girl/envious.gif | Bin 0 -> 1044 bytes images/mood/charitycam/goth_girl/full.gif | Bin 0 -> 646 bytes images/mood/charitycam/goth_girl/gloomy.gif | Bin 0 -> 523 bytes images/mood/charitycam/goth_girl/happy.gif | Bin 0 -> 656 bytes images/mood/charitycam/goth_girl/high.gif | Bin 0 -> 1724 bytes images/mood/charitycam/goth_girl/hot.gif | Bin 0 -> 1929 bytes images/mood/charitycam/goth_girl/hungry.gif | Bin 0 -> 464 bytes images/mood/charitycam/goth_girl/index.html | 70 + images/mood/charitycam/goth_girl/loved.gif | Bin 0 -> 698 bytes images/mood/charitycam/goth_girl/nerdy.gif | Bin 0 -> 910 bytes images/mood/charitycam/goth_girl/okay.gif | Bin 0 -> 638 bytes images/mood/charitycam/goth_girl/sad.gif | Bin 0 -> 763 bytes images/mood/charitycam/goth_girl/scared.gif | Bin 0 -> 721 bytes images/mood/charitycam/goth_girl/sick.gif | Bin 0 -> 2383 bytes images/mood/charitycam/goth_girl/silly.gif | Bin 0 -> 1672 bytes images/mood/charitycam/goth_girl/sleepy.gif | Bin 0 -> 651 bytes images/mood/charitycam/goth_girl/stressed.gif | Bin 0 -> 734 bytes .../mood/charitycam/goth_girl/surprised.gif | Bin 0 -> 588 bytes images/mood/charitycam/goth_girl/thirsty.gif | Bin 0 -> 2232 bytes .../mood/charitycam/goth_girl/thoughtful.gif | Bin 0 -> 967 bytes images/mood/charitycam/goth_girl/working.gif | Bin 0 -> 572 bytes images/mood/charitycam/index.html | 53 + images/mood/charitycam/mice/angel.gif | Bin 0 -> 1066 bytes images/mood/charitycam/mice/angry.gif | Bin 0 -> 1168 bytes images/mood/charitycam/mice/artistic.gif | Bin 0 -> 2988 bytes images/mood/charitycam/mice/blank.gif | Bin 0 -> 403 bytes images/mood/charitycam/mice/bouncy.gif | Bin 0 -> 723 bytes images/mood/charitycam/mice/cold.gif | Bin 0 -> 769 bytes images/mood/charitycam/mice/curious.gif | Bin 0 -> 1177 bytes images/mood/charitycam/mice/determined.gif | Bin 0 -> 530 bytes images/mood/charitycam/mice/devilish.gif | Bin 0 -> 704 bytes images/mood/charitycam/mice/drunk.gif | Bin 0 -> 1986 bytes images/mood/charitycam/mice/embarrassed.gif | Bin 0 -> 552 bytes images/mood/charitycam/mice/envious.gif | Bin 0 -> 552 bytes images/mood/charitycam/mice/full.gif | Bin 0 -> 656 bytes images/mood/charitycam/mice/gloomy.gif | Bin 0 -> 663 bytes images/mood/charitycam/mice/happy.gif | Bin 0 -> 532 bytes images/mood/charitycam/mice/high.gif | Bin 0 -> 540 bytes images/mood/charitycam/mice/hot.gif | Bin 0 -> 1322 bytes images/mood/charitycam/mice/hungry.gif | Bin 0 -> 634 bytes images/mood/charitycam/mice/indescribable.gif | Bin 0 -> 692 bytes images/mood/charitycam/mice/index.html | 73 + images/mood/charitycam/mice/lethargic.gif | Bin 0 -> 470 bytes images/mood/charitycam/mice/loved.gif | Bin 0 -> 1177 bytes images/mood/charitycam/mice/nerdy.gif | Bin 0 -> 675 bytes images/mood/charitycam/mice/sad.gif | Bin 0 -> 1334 bytes images/mood/charitycam/mice/sick.gif | Bin 0 -> 601 bytes images/mood/charitycam/mice/silly.gif | Bin 0 -> 554 bytes images/mood/charitycam/mice/sleepy.gif | Bin 0 -> 776 bytes images/mood/charitycam/mice/sore.gif | Bin 0 -> 557 bytes images/mood/charitycam/mice/stressed.gif | Bin 0 -> 1948 bytes images/mood/charitycam/mice/surprised.gif | Bin 0 -> 640 bytes images/mood/charitycam/mice/thirsty.gif | Bin 0 -> 1421 bytes images/mood/charitycam/mice/thoughtful.gif | Bin 0 -> 672 bytes images/mood/charitycam/mice/worried.gif | Bin 0 -> 467 bytes images/mood/charitycam/stars/angry.gif | Bin 0 -> 2154 bytes images/mood/charitycam/stars/artistic.gif | Bin 0 -> 2381 bytes images/mood/charitycam/stars/awake.gif | Bin 0 -> 1777 bytes images/mood/charitycam/stars/bitchy.gif | Bin 0 -> 1755 bytes images/mood/charitycam/stars/blank.gif | Bin 0 -> 1789 bytes .../charitycam/stars/charitycam-star1.gif | Bin 0 -> 2386 bytes images/mood/charitycam/stars/cold.gif | Bin 0 -> 1186 bytes images/mood/charitycam/stars/confused.gif | Bin 0 -> 1545 bytes images/mood/charitycam/stars/crazy.gif | Bin 0 -> 916 bytes images/mood/charitycam/stars/determined.gif | Bin 0 -> 1226 bytes images/mood/charitycam/stars/devious.gif | Bin 0 -> 1655 bytes images/mood/charitycam/stars/dirty.gif | Bin 0 -> 2748 bytes images/mood/charitycam/stars/drunk.gif | Bin 0 -> 1496 bytes images/mood/charitycam/stars/embarrassed.gif | Bin 0 -> 947 bytes images/mood/charitycam/stars/energetic.gif | Bin 0 -> 1316 bytes images/mood/charitycam/stars/enthralled.gif | Bin 0 -> 1995 bytes images/mood/charitycam/stars/envious.gif | Bin 0 -> 1622 bytes images/mood/charitycam/stars/flirt.gif | Bin 0 -> 1910 bytes images/mood/charitycam/stars/gloomy.gif | Bin 0 -> 2269 bytes images/mood/charitycam/stars/happy.gif | Bin 0 -> 1839 bytes images/mood/charitycam/stars/high.gif | Bin 0 -> 882 bytes images/mood/charitycam/stars/hot.gif | Bin 0 -> 2099 bytes images/mood/charitycam/stars/hungry.gif | Bin 0 -> 1360 bytes .../mood/charitycam/stars/indescribable.gif | Bin 0 -> 2312 bytes images/mood/charitycam/stars/index.html | 81 + images/mood/charitycam/stars/lazy.gif | Bin 0 -> 1816 bytes images/mood/charitycam/stars/nerdy.gif | Bin 0 -> 1067 bytes images/mood/charitycam/stars/okay.gif | Bin 0 -> 1900 bytes images/mood/charitycam/stars/peaceful.gif | Bin 0 -> 1757 bytes images/mood/charitycam/stars/pessimistic.gif | Bin 0 -> 1602 bytes images/mood/charitycam/stars/sad.gif | Bin 0 -> 2445 bytes images/mood/charitycam/stars/scared.gif | Bin 0 -> 1049 bytes images/mood/charitycam/stars/sick.gif | Bin 0 -> 3220 bytes images/mood/charitycam/stars/silly.gif | Bin 0 -> 1326 bytes images/mood/charitycam/stars/sore.gif | Bin 0 -> 2003 bytes images/mood/charitycam/stars/stressed.gif | Bin 0 -> 1427 bytes images/mood/charitycam/stars/surprised.gif | Bin 0 -> 1299 bytes images/mood/charitycam/stars/thirsty.gif | Bin 0 -> 2510 bytes images/mood/charitycam/stars/thoughtful.gif | Bin 0 -> 1380 bytes images/mood/charitycam/stars/tired.gif | Bin 0 -> 1919 bytes images/mood/charitycam/stars/working.gif | Bin 0 -> 1095 bytes images/mood/charitycam/suns/angry.gif | Bin 0 -> 1559 bytes images/mood/charitycam/suns/artistic.gif | Bin 0 -> 2262 bytes images/mood/charitycam/suns/awake.gif | Bin 0 -> 3736 bytes images/mood/charitycam/suns/blah.gif | Bin 0 -> 1719 bytes images/mood/charitycam/suns/blank.gif | Bin 0 -> 1439 bytes images/mood/charitycam/suns/cold.gif | Bin 0 -> 1289 bytes images/mood/charitycam/suns/confused.gif | Bin 0 -> 2819 bytes images/mood/charitycam/suns/determined.gif | Bin 0 -> 1209 bytes images/mood/charitycam/suns/drunk.gif | Bin 0 -> 1918 bytes images/mood/charitycam/suns/energetic.gif | Bin 0 -> 1768 bytes images/mood/charitycam/suns/envious.gif | Bin 0 -> 2668 bytes images/mood/charitycam/suns/examinate.gif | Bin 0 -> 2975 bytes images/mood/charitycam/suns/full.gif | Bin 0 -> 1881 bytes images/mood/charitycam/suns/gloomy.gif | Bin 0 -> 3052 bytes images/mood/charitycam/suns/good.gif | Bin 0 -> 1465 bytes images/mood/charitycam/suns/happy.gif | Bin 0 -> 2827 bytes images/mood/charitycam/suns/high.gif | Bin 0 -> 1595 bytes images/mood/charitycam/suns/horny.gif | Bin 0 -> 1219 bytes images/mood/charitycam/suns/hot.gif | Bin 0 -> 2799 bytes images/mood/charitycam/suns/hungry.gif | Bin 0 -> 3335 bytes images/mood/charitycam/suns/indescribable.gif | Bin 0 -> 3669 bytes images/mood/charitycam/suns/index.html | 74 + images/mood/charitycam/suns/loved.gif | Bin 0 -> 2783 bytes images/mood/charitycam/suns/okay.gif | Bin 0 -> 2582 bytes images/mood/charitycam/suns/sad.gif | Bin 0 -> 2594 bytes images/mood/charitycam/suns/scared.gif | Bin 0 -> 1741 bytes images/mood/charitycam/suns/sick.gif | Bin 0 -> 2671 bytes images/mood/charitycam/suns/silly.gif | Bin 0 -> 3857 bytes images/mood/charitycam/suns/sore.gif | Bin 0 -> 2154 bytes images/mood/charitycam/suns/surprised.gif | Bin 0 -> 1768 bytes images/mood/charitycam/suns/thirsty.gif | Bin 0 -> 1227 bytes images/mood/charitycam/suns/thoughtful.gif | Bin 0 -> 3057 bytes images/mood/charitycam/suns/tired.gif | Bin 0 -> 1570 bytes images/mood/charitycam/suns/working.gif | Bin 0 -> 1143 bytes images/mood/classic/angry.gif | Bin 0 -> 94 bytes images/mood/classic/biggrin.gif | Bin 0 -> 899 bytes images/mood/classic/blah.gif | Bin 0 -> 92 bytes images/mood/classic/blush.gif | Bin 0 -> 99 bytes images/mood/classic/clean.pl | 27 + images/mood/classic/confused.gif | Bin 0 -> 112 bytes images/mood/classic/confused2.gif | Bin 0 -> 110 bytes images/mood/classic/cool.gif | Bin 0 -> 124 bytes images/mood/classic/devious.gif | Bin 0 -> 913 bytes images/mood/classic/dizzy.gif | Bin 0 -> 367 bytes images/mood/classic/drunk.gif | Bin 0 -> 114 bytes images/mood/classic/eek.gif | Bin 0 -> 1264 bytes images/mood/classic/energetic.gif | Bin 0 -> 313 bytes images/mood/classic/frown.gif | Bin 0 -> 94 bytes images/mood/classic/index.html | 62 + images/mood/classic/laugh.gif | Bin 0 -> 158 bytes images/mood/classic/sad.gif | Bin 0 -> 95 bytes images/mood/classic/shock.gif | Bin 0 -> 93 bytes images/mood/classic/sick.gif | Bin 0 -> 94 bytes images/mood/classic/smile.gif | Bin 0 -> 93 bytes images/mood/classic/thinking.gif | Bin 0 -> 129 bytes images/mood/classic/tired.gif | Bin 0 -> 108 bytes images/mood/classic/wink.gif | Bin 0 -> 91 bytes images/mood/ibrad/alien.gif | Bin 0 -> 94 bytes images/mood/ibrad/angry.gif | Bin 0 -> 154 bytes images/mood/ibrad/asleep.gif | Bin 0 -> 442 bytes images/mood/ibrad/biggrin.gif | Bin 0 -> 152 bytes images/mood/ibrad/bigsmile.gif | Bin 0 -> 140 bytes images/mood/ibrad/bigwink.gif | Bin 0 -> 135 bytes images/mood/ibrad/clam.gif | Bin 0 -> 807 bytes images/mood/ibrad/confused.gif | Bin 0 -> 110 bytes images/mood/ibrad/cool.gif | Bin 0 -> 124 bytes images/mood/ibrad/dead.gif | Bin 0 -> 890 bytes images/mood/ibrad/devil.gif | Bin 0 -> 96 bytes images/mood/ibrad/disbelief.gif | Bin 0 -> 1264 bytes images/mood/ibrad/disgruntled.gif | Bin 0 -> 983 bytes images/mood/ibrad/embarrassed.gif | Bin 0 -> 136 bytes images/mood/ibrad/erked.gif | Bin 0 -> 92 bytes images/mood/ibrad/flirty.gif | Bin 0 -> 923 bytes images/mood/ibrad/frown.gif | Bin 0 -> 94 bytes images/mood/ibrad/googlyeyes.gif | Bin 0 -> 367 bytes images/mood/ibrad/hot.gif | Bin 0 -> 1793 bytes images/mood/ibrad/index.html | 84 + images/mood/ibrad/laugh.gif | Bin 0 -> 158 bytes images/mood/ibrad/licklips.gif | Bin 0 -> 587 bytes images/mood/ibrad/lonely.gif | Bin 0 -> 348 bytes images/mood/ibrad/loved.gif | Bin 0 -> 379 bytes images/mood/ibrad/macfrown.gif | Bin 0 -> 113 bytes images/mood/ibrad/mactongue.gif | Bin 0 -> 161 bytes images/mood/ibrad/macwink.gif | Bin 0 -> 113 bytes images/mood/ibrad/naughty.gif | Bin 0 -> 343 bytes images/mood/ibrad/nerd.gif | Bin 0 -> 139 bytes images/mood/ibrad/ohcrap.gif | Bin 0 -> 880 bytes images/mood/ibrad/paranoid.gif | Bin 0 -> 657 bytes images/mood/ibrad/rolleyes.gif | Bin 0 -> 1784 bytes images/mood/ibrad/rollingeyes.gif | Bin 0 -> 223 bytes images/mood/ibrad/rotate.gif | Bin 0 -> 982 bytes images/mood/ibrad/sleep.gif | Bin 0 -> 608 bytes images/mood/ibrad/smile.gif | Bin 0 -> 93 bytes images/mood/ibrad/sql.txt | 98 + images/mood/ibrad/switching.gif | Bin 0 -> 2277 bytes images/mood/ibrad/talking.gif | Bin 0 -> 819 bytes images/mood/ibrad/tongue.gif | Bin 0 -> 338 bytes images/mood/ibrad/uhoh.gif | Bin 0 -> 1032 bytes images/mood/ibrad/unhappy.gif | Bin 0 -> 229 bytes images/mood/ibrad/upsidedown.gif | Bin 0 -> 876 bytes images/mood/ibrad/wink.gif | Bin 0 -> 970 bytes images/mood/ibrad/yawn.gif | Bin 0 -> 676 bytes images/mood/index.html | 56 + images/mood/moonsis/amused.gif | Bin 0 -> 448 bytes images/mood/moonsis/angelic.gif | Bin 0 -> 3099 bytes images/mood/moonsis/angry.gif | Bin 0 -> 420 bytes images/mood/moonsis/blue.gif | Bin 0 -> 1369 bytes images/mood/moonsis/calm.gif | Bin 0 -> 404 bytes images/mood/moonsis/cold.gif | Bin 0 -> 905 bytes images/mood/moonsis/confused.gif | Bin 0 -> 682 bytes images/mood/moonsis/content.gif | Bin 0 -> 475 bytes images/mood/moonsis/curious.gif | Bin 0 -> 627 bytes images/mood/moonsis/depressed.gif | Bin 0 -> 565 bytes images/mood/moonsis/dorknerdy.gif | Bin 0 -> 438 bytes images/mood/moonsis/drained.gif | Bin 0 -> 467 bytes images/mood/moonsis/drunk.gif | Bin 0 -> 1232 bytes images/mood/moonsis/embarrassed.gif | Bin 0 -> 1189 bytes images/mood/moonsis/energetic.gif | Bin 0 -> 783 bytes images/mood/moonsis/envious.gif | Bin 0 -> 1624 bytes images/mood/moonsis/exhausted.gif | Bin 0 -> 676 bytes images/mood/moonsis/filrty.gif | Bin 0 -> 544 bytes images/mood/moonsis/flirty.gif | Bin 0 -> 544 bytes images/mood/moonsis/full.gif | Bin 0 -> 2998 bytes images/mood/moonsis/grumpy.gif | Bin 0 -> 452 bytes images/mood/moonsis/happy.gif | Bin 0 -> 404 bytes images/mood/moonsis/high.gif | Bin 0 -> 644 bytes images/mood/moonsis/horny.gif | Bin 0 -> 672 bytes images/mood/moonsis/hot.gif | Bin 0 -> 2146 bytes images/mood/moonsis/hungry.gif | Bin 0 -> 1275 bytes images/mood/moonsis/hyper.gif | Bin 0 -> 658 bytes images/mood/moonsis/indescribable.gif | Bin 0 -> 1309 bytes images/mood/moonsis/index.html | 92 + images/mood/moonsis/lazyrelaxed.gif | Bin 0 -> 2216 bytes images/mood/moonsis/lonely.gif | Bin 0 -> 589 bytes images/mood/moonsis/loved.gif | Bin 0 -> 3295 bytes images/mood/moonsis/mischievous.gif | Bin 0 -> 801 bytes images/mood/moonsis/mischivious.gif | Bin 0 -> 801 bytes images/mood/moonsis/okay.gif | Bin 0 -> 399 bytes images/mood/moonsis/pensive.gif | Bin 0 -> 786 bytes images/mood/moonsis/pissedoff.gif | Bin 0 -> 578 bytes images/mood/moonsis/prepare.pl | 63 + images/mood/moonsis/relaxed.gif | Bin 0 -> 3917 bytes images/mood/moonsis/relieved.gif | Bin 0 -> 402 bytes images/mood/moonsis/restless.gif | Bin 0 -> 1061 bytes images/mood/moonsis/sad.gif | Bin 0 -> 708 bytes images/mood/moonsis/scared.gif | Bin 0 -> 414 bytes images/mood/moonsis/sick.gif | Bin 0 -> 2015 bytes images/mood/moonsis/silly.gif | Bin 0 -> 658 bytes images/mood/moonsis/sleepy.gif | Bin 0 -> 666 bytes images/mood/moonsis/sqlstuff.txt | 160 + images/mood/moonsis/stars/green/achy_sg.gif | Bin 0 -> 991 bytes .../mood/moonsis/stars/green/angelic_sg.gif | Bin 0 -> 1916 bytes images/mood/moonsis/stars/green/angry_sg.gif | Bin 0 -> 1607 bytes .../mood/moonsis/stars/green/artistic_sg.gif | Bin 0 -> 2373 bytes images/mood/moonsis/stars/green/awake_sg.gif | Bin 0 -> 1477 bytes images/mood/moonsis/stars/green/blank_sg.gif | Bin 0 -> 1512 bytes images/mood/moonsis/stars/green/bored_sg.gif | Bin 0 -> 1528 bytes images/mood/moonsis/stars/green/busy_sg.gif | Bin 0 -> 1546 bytes images/mood/moonsis/stars/green/cold_sg.gif | Bin 0 -> 1640 bytes .../mood/moonsis/stars/green/confused_sg.gif | Bin 0 -> 1644 bytes .../mood/moonsis/stars/green/dancing_sg.gif | Bin 0 -> 2051 bytes images/mood/moonsis/stars/green/dirty_sg.gif | Bin 0 -> 1845 bytes images/mood/moonsis/stars/green/drunk_sg.gif | Bin 0 -> 1669 bytes .../moonsis/stars/green/emberassed_sg.gif | Bin 0 -> 2360 bytes .../mood/moonsis/stars/green/envious_sg.gif | Bin 0 -> 2364 bytes .../mood/moonsis/stars/green/exhausted_sg.gif | Bin 0 -> 1584 bytes .../mood/moonsis/stars/green/festive_sg.gif | Bin 0 -> 1665 bytes images/mood/moonsis/stars/green/full_sg.gif | Bin 0 -> 1775 bytes images/mood/moonsis/stars/green/grumpy_sg.gif | Bin 0 -> 2294 bytes images/mood/moonsis/stars/green/happy_sg.gif | Bin 0 -> 2260 bytes images/mood/moonsis/stars/green/horny_sg.gif | Bin 0 -> 1642 bytes images/mood/moonsis/stars/green/hot_sg.gif | Bin 0 -> 1686 bytes images/mood/moonsis/stars/green/hungry_sg.gif | Bin 0 -> 1636 bytes images/mood/moonsis/stars/green/hyper_sg.gif | Bin 0 -> 1540 bytes .../moonsis/stars/green/indescribable_sg.gif | Bin 0 -> 633 bytes images/mood/moonsis/stars/green/index.html | 82 + .../moonsis/stars/green/indifferent_sg.gif | Bin 0 -> 1516 bytes images/mood/moonsis/stars/green/loved_sg.gif | Bin 0 -> 1726 bytes images/mood/moonsis/stars/green/mellow_sg.gif | Bin 0 -> 1499 bytes .../moonsis/stars/green/mischivious_sg.gif | Bin 0 -> 1795 bytes images/mood/moonsis/stars/green/nerdy_sg.gif | Bin 0 -> 1538 bytes .../mood/moonsis/stars/green/pensive_sg.gif | Bin 0 -> 2356 bytes images/mood/moonsis/stars/green/sad_sg.gif | Bin 0 -> 1580 bytes images/mood/moonsis/stars/green/sexy_sg.gif | Bin 0 -> 1693 bytes images/mood/moonsis/stars/green/sick_sg.gif | Bin 0 -> 1915 bytes images/mood/moonsis/stars/green/silly_sg.gif | Bin 0 -> 893 bytes .../mood/moonsis/stars/green/singing_sg.gif | Bin 0 -> 1639 bytes images/mood/moonsis/stars/green/sleepy_sg.gif | Bin 0 -> 1609 bytes images/mood/moonsis/stars/green/sore_sg.gif | Bin 0 -> 1642 bytes .../mood/moonsis/stars/green/stressed_sg.gif | Bin 0 -> 2852 bytes .../mood/moonsis/stars/green/thirsty_sg.gif | Bin 0 -> 1643 bytes .../mood/moonsis/stars/green/working_sg.gif | Bin 0 -> 2039 bytes images/mood/moonsis/stars/index.html | 45 + images/mood/moonsis/stars/purple/achy_sp.gif | Bin 0 -> 860 bytes .../mood/moonsis/stars/purple/angelic_sp.gif | Bin 0 -> 1904 bytes images/mood/moonsis/stars/purple/angry_sp.gif | Bin 0 -> 1567 bytes .../mood/moonsis/stars/purple/artistic_sp.gif | Bin 0 -> 2363 bytes images/mood/moonsis/stars/purple/awake_sp.gif | Bin 0 -> 1212 bytes images/mood/moonsis/stars/purple/blank_sp.gif | Bin 0 -> 1489 bytes images/mood/moonsis/stars/purple/bored_sp.gif | Bin 0 -> 1516 bytes images/mood/moonsis/stars/purple/cold_sp.gif | Bin 0 -> 1663 bytes .../mood/moonsis/stars/purple/confused_sp.gif | Bin 0 -> 1644 bytes .../mood/moonsis/stars/purple/content_sp.gif | Bin 0 -> 1207 bytes .../mood/moonsis/stars/purple/dancing_sp.gif | Bin 0 -> 2061 bytes images/mood/moonsis/stars/purple/dirty_sp.gif | Bin 0 -> 1816 bytes images/mood/moonsis/stars/purple/drunk_sp.gif | Bin 0 -> 1695 bytes .../moonsis/stars/purple/emberassed_sp.gif | Bin 0 -> 2367 bytes .../mood/moonsis/stars/purple/envious_sp.gif | Bin 0 -> 2387 bytes .../moonsis/stars/purple/exhausted_sp.gif | Bin 0 -> 1577 bytes .../mood/moonsis/stars/purple/festive_sp.gif | Bin 0 -> 1639 bytes images/mood/moonsis/stars/purple/full_sp.gif | Bin 0 -> 1739 bytes .../mood/moonsis/stars/purple/grumpy_sp.gif | Bin 0 -> 2252 bytes images/mood/moonsis/stars/purple/happy_sp.gif | Bin 0 -> 2222 bytes images/mood/moonsis/stars/purple/horny_sp.gif | Bin 0 -> 1657 bytes images/mood/moonsis/stars/purple/hot_sp.gif | Bin 0 -> 1629 bytes .../mood/moonsis/stars/purple/hungry_sp.gif | Bin 0 -> 1672 bytes images/mood/moonsis/stars/purple/hyper_sp.gif | Bin 0 -> 1515 bytes .../moonsis/stars/purple/indescribable_sp.gif | Bin 0 -> 624 bytes images/mood/moonsis/stars/purple/index.html | 82 + .../moonsis/stars/purple/indifferent_sp.gif | Bin 0 -> 672 bytes images/mood/moonsis/stars/purple/loved_sp.gif | Bin 0 -> 1703 bytes .../mood/moonsis/stars/purple/mellow_sp.gif | Bin 0 -> 1528 bytes .../moonsis/stars/purple/mischivious_sp.gif | Bin 0 -> 1796 bytes images/mood/moonsis/stars/purple/nerdy_sp.gif | Bin 0 -> 1527 bytes .../mood/moonsis/stars/purple/pensive_sp.gif | Bin 0 -> 2359 bytes images/mood/moonsis/stars/purple/sad_sp.gif | Bin 0 -> 1571 bytes images/mood/moonsis/stars/purple/sexy_sp.gif | Bin 0 -> 1671 bytes images/mood/moonsis/stars/purple/sick_sp.gif | Bin 0 -> 1864 bytes images/mood/moonsis/stars/purple/silly_sp.gif | Bin 0 -> 745 bytes .../mood/moonsis/stars/purple/singing_sp.gif | Bin 0 -> 1619 bytes .../mood/moonsis/stars/purple/sleepy_sp.gif | Bin 0 -> 1584 bytes images/mood/moonsis/stars/purple/sore_sp.gif | Bin 0 -> 1664 bytes .../mood/moonsis/stars/purple/stressed_sp.gif | Bin 0 -> 2739 bytes .../mood/moonsis/stars/purple/thirsty_sp.gif | Bin 0 -> 1601 bytes .../mood/moonsis/stars/purple/working_sp.gif | Bin 0 -> 2244 bytes images/mood/moonsis/stars/red/achy_sr.gif | Bin 0 -> 854 bytes images/mood/moonsis/stars/red/angelic_sr.gif | Bin 0 -> 1918 bytes images/mood/moonsis/stars/red/angry_sr.gif | Bin 0 -> 1602 bytes images/mood/moonsis/stars/red/artistic_sr.gif | Bin 0 -> 2386 bytes images/mood/moonsis/stars/red/awake_sr.gif | Bin 0 -> 1323 bytes images/mood/moonsis/stars/red/blank_sr.gif | Bin 0 -> 1533 bytes images/mood/moonsis/stars/red/bored_sr.gif | Bin 0 -> 1529 bytes images/mood/moonsis/stars/red/cold_sr.gif | Bin 0 -> 1684 bytes images/mood/moonsis/stars/red/confused_sr.gif | Bin 0 -> 1670 bytes images/mood/moonsis/stars/red/dancing_sr.gif | Bin 0 -> 2059 bytes images/mood/moonsis/stars/red/dirty_sr.gif | Bin 0 -> 1830 bytes images/mood/moonsis/stars/red/drunk_sr.gif | Bin 0 -> 1654 bytes .../mood/moonsis/stars/red/emberassed_sr.gif | Bin 0 -> 2316 bytes images/mood/moonsis/stars/red/envious_sr.gif | Bin 0 -> 2413 bytes .../mood/moonsis/stars/red/exhausted_sr.gif | Bin 0 -> 1594 bytes images/mood/moonsis/stars/red/festive_sr.gif | Bin 0 -> 1639 bytes images/mood/moonsis/stars/red/full_sr.gif | Bin 0 -> 1767 bytes images/mood/moonsis/stars/red/grumpy_sr.gif | Bin 0 -> 2285 bytes images/mood/moonsis/stars/red/happy_sr.gif | Bin 0 -> 2260 bytes images/mood/moonsis/stars/red/horny_sr.gif | Bin 0 -> 1672 bytes images/mood/moonsis/stars/red/hot_sr.gif | Bin 0 -> 1679 bytes images/mood/moonsis/stars/red/hungry_sr.gif | Bin 0 -> 1669 bytes images/mood/moonsis/stars/red/hyper_sr.gif | Bin 0 -> 1545 bytes .../moonsis/stars/red/indescribable_sr.gif | Bin 0 -> 616 bytes images/mood/moonsis/stars/red/index.html | 81 + .../mood/moonsis/stars/red/indifferent_sr.gif | Bin 0 -> 1532 bytes images/mood/moonsis/stars/red/loved_sr.gif | Bin 0 -> 1728 bytes images/mood/moonsis/stars/red/mellow_sr.gif | Bin 0 -> 1519 bytes .../mood/moonsis/stars/red/mischivious_sr.gif | Bin 0 -> 1799 bytes images/mood/moonsis/stars/red/nerdy_sr.gif | Bin 0 -> 1559 bytes images/mood/moonsis/stars/red/pensive_sr.gif | Bin 0 -> 2343 bytes images/mood/moonsis/stars/red/sad_sr.gif | Bin 0 -> 1588 bytes images/mood/moonsis/stars/red/sexy_sr.gif | Bin 0 -> 1699 bytes images/mood/moonsis/stars/red/sick_sr.gif | Bin 0 -> 1875 bytes images/mood/moonsis/stars/red/silly_sr.gif | Bin 0 -> 756 bytes images/mood/moonsis/stars/red/singing_sr.gif | Bin 0 -> 1635 bytes images/mood/moonsis/stars/red/sleepy_sr.gif | Bin 0 -> 1578 bytes images/mood/moonsis/stars/red/sore_sr.gif | Bin 0 -> 1660 bytes images/mood/moonsis/stars/red/stressed_sr.gif | Bin 0 -> 2853 bytes images/mood/moonsis/stars/red/thirsty_sr.gif | Bin 0 -> 1629 bytes images/mood/moonsis/stars/red/working_sr.gif | Bin 0 -> 2197 bytes images/mood/moonsis/stars/yellow/achy_sy.gif | Bin 0 -> 792 bytes .../mood/moonsis/stars/yellow/angelic_sy.gif | Bin 0 -> 1902 bytes images/mood/moonsis/stars/yellow/angry_sy.gif | Bin 0 -> 1562 bytes .../mood/moonsis/stars/yellow/artistic_sy.gif | Bin 0 -> 2338 bytes images/mood/moonsis/stars/yellow/awake_sy.gif | Bin 0 -> 1186 bytes images/mood/moonsis/stars/yellow/blank_sy.gif | Bin 0 -> 1508 bytes images/mood/moonsis/stars/yellow/bored_sy.gif | Bin 0 -> 1484 bytes images/mood/moonsis/stars/yellow/cold_sy.gif | Bin 0 -> 1628 bytes .../mood/moonsis/stars/yellow/confused_sy.gif | Bin 0 -> 1626 bytes .../mood/moonsis/stars/yellow/content_sy.gif | Bin 0 -> 1170 bytes .../mood/moonsis/stars/yellow/dancing_sy.gif | Bin 0 -> 2041 bytes images/mood/moonsis/stars/yellow/dirty_sy.gif | Bin 0 -> 1817 bytes images/mood/moonsis/stars/yellow/drunk_sy.gif | Bin 0 -> 1671 bytes .../moonsis/stars/yellow/emberassed_sy.gif | Bin 0 -> 2398 bytes .../mood/moonsis/stars/yellow/envious_sy.gif | Bin 0 -> 2451 bytes .../moonsis/stars/yellow/exhausted_sy.gif | Bin 0 -> 1542 bytes .../mood/moonsis/stars/yellow/festive_sy.gif | Bin 0 -> 1625 bytes images/mood/moonsis/stars/yellow/full_sy.gif | Bin 0 -> 1743 bytes .../mood/moonsis/stars/yellow/grumpy_sy.gif | Bin 0 -> 2569 bytes images/mood/moonsis/stars/yellow/happy_sy.gif | Bin 0 -> 2219 bytes images/mood/moonsis/stars/yellow/horny_sy.gif | Bin 0 -> 1614 bytes images/mood/moonsis/stars/yellow/hot_sy.gif | Bin 0 -> 1613 bytes .../mood/moonsis/stars/yellow/hungry_sy.gif | Bin 0 -> 1655 bytes images/mood/moonsis/stars/yellow/hyper_sy.gif | Bin 0 -> 1500 bytes .../moonsis/stars/yellow/indescribable_sy.gif | Bin 0 -> 559 bytes images/mood/moonsis/stars/yellow/index.html | 82 + .../moonsis/stars/yellow/indifferent_sy.gif | Bin 0 -> 577 bytes images/mood/moonsis/stars/yellow/loved_sy.gif | Bin 0 -> 1675 bytes .../mood/moonsis/stars/yellow/mellow_sy.gif | Bin 0 -> 1514 bytes .../moonsis/stars/yellow/mischivious_sy.gif | Bin 0 -> 1742 bytes images/mood/moonsis/stars/yellow/nerdy_sy.gif | Bin 0 -> 1518 bytes .../mood/moonsis/stars/yellow/pensive_sy.gif | Bin 0 -> 2323 bytes images/mood/moonsis/stars/yellow/sad_sy.gif | Bin 0 -> 1558 bytes images/mood/moonsis/stars/yellow/sexy_sy.gif | Bin 0 -> 1653 bytes images/mood/moonsis/stars/yellow/sick_sy.gif | Bin 0 -> 1826 bytes images/mood/moonsis/stars/yellow/silly_sy.gif | Bin 0 -> 739 bytes .../mood/moonsis/stars/yellow/singing_sy.gif | Bin 0 -> 1598 bytes .../mood/moonsis/stars/yellow/sleepy_sy.gif | Bin 0 -> 1598 bytes images/mood/moonsis/stars/yellow/sore_sy.gif | Bin 0 -> 1664 bytes .../mood/moonsis/stars/yellow/stressed_sy.gif | Bin 0 -> 2752 bytes .../mood/moonsis/stars/yellow/thirsty_sy.gif | Bin 0 -> 1619 bytes .../mood/moonsis/stars/yellow/working_sy.gif | Bin 0 -> 2247 bytes images/mood/moonsis/stressed.gif | Bin 0 -> 2743 bytes images/mood/moonsis/thoughtful.gif | Bin 0 -> 852 bytes images/mood/moonsis/tiredyawn.gif | Bin 0 -> 512 bytes images/mood/moonsis/upsidedown.gif | Bin 0 -> 593 bytes images/mood/moonsis/working.gif | Bin 0 -> 1556 bytes images/mood/moonsis/worried.gif | Bin 0 -> 618 bytes images/mood/neko/index.html | 42 + images/mood/neko/kaokitty/accomplished.gif | Bin 0 -> 1187 bytes images/mood/neko/kaokitty/aggravated.gif | Bin 0 -> 1767 bytes images/mood/neko/kaokitty/amused.gif | Bin 0 -> 1748 bytes images/mood/neko/kaokitty/angry.gif | Bin 0 -> 1771 bytes images/mood/neko/kaokitty/annoyed.gif | Bin 0 -> 1757 bytes images/mood/neko/kaokitty/anxious.gif | Bin 0 -> 1762 bytes images/mood/neko/kaokitty/apathetic.gif | Bin 0 -> 1739 bytes images/mood/neko/kaokitty/artistic.gif | Bin 0 -> 6325 bytes images/mood/neko/kaokitty/awake.gif | Bin 0 -> 2379 bytes images/mood/neko/kaokitty/bitchy.gif | Bin 0 -> 1773 bytes images/mood/neko/kaokitty/blah.gif | Bin 0 -> 1739 bytes images/mood/neko/kaokitty/blank.gif | Bin 0 -> 1256 bytes images/mood/neko/kaokitty/bored.gif | Bin 0 -> 1741 bytes images/mood/neko/kaokitty/bouncey.gif | Bin 0 -> 1308 bytes images/mood/neko/kaokitty/busy.gif | Bin 0 -> 1187 bytes images/mood/neko/kaokitty/calm.gif | Bin 0 -> 1304 bytes images/mood/neko/kaokitty/cheerful.gif | Bin 0 -> 1860 bytes images/mood/neko/kaokitty/chipper.gif | Bin 0 -> 1301 bytes images/mood/neko/kaokitty/cold.gif | Bin 0 -> 1393 bytes images/mood/neko/kaokitty/complacent.gif | Bin 0 -> 1832 bytes images/mood/neko/kaokitty/confused.gif | Bin 0 -> 2243 bytes images/mood/neko/kaokitty/contemplative.gif | Bin 0 -> 1888 bytes images/mood/neko/kaokitty/content.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/cranky.gif | Bin 0 -> 1768 bytes images/mood/neko/kaokitty/crappy.gif | Bin 0 -> 1286 bytes images/mood/neko/kaokitty/crazy.gif | Bin 0 -> 2335 bytes images/mood/neko/kaokitty/creative.gif | Bin 0 -> 6325 bytes images/mood/neko/kaokitty/crushed.gif | Bin 0 -> 1293 bytes images/mood/neko/kaokitty/curious.gif | Bin 0 -> 2183 bytes images/mood/neko/kaokitty/cynical.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/defensive.gif | Bin 0 -> 1715 bytes images/mood/neko/kaokitty/depressed.gif | Bin 0 -> 1288 bytes images/mood/neko/kaokitty/determined.gif | Bin 0 -> 1741 bytes images/mood/neko/kaokitty/devious.gif | Bin 0 -> 2005 bytes images/mood/neko/kaokitty/dirty.gif | Bin 0 -> 2046 bytes images/mood/neko/kaokitty/disappointed.gif | Bin 0 -> 1286 bytes images/mood/neko/kaokitty/discontent.gif | Bin 0 -> 1286 bytes images/mood/neko/kaokitty/distressed.gif | Bin 0 -> 1796 bytes images/mood/neko/kaokitty/ditzy.gif | Bin 0 -> 1350 bytes images/mood/neko/kaokitty/dorky.gif | Bin 0 -> 1818 bytes images/mood/neko/kaokitty/drained.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/drunk.gif | Bin 0 -> 1894 bytes images/mood/neko/kaokitty/ecstatic.gif | Bin 0 -> 1365 bytes images/mood/neko/kaokitty/eh.gif | Bin 0 -> 1739 bytes images/mood/neko/kaokitty/embarassed.gif | Bin 0 -> 1926 bytes images/mood/neko/kaokitty/energetic.gif | Bin 0 -> 1961 bytes images/mood/neko/kaokitty/enraged.gif | Bin 0 -> 1900 bytes images/mood/neko/kaokitty/enthralled.gif | Bin 0 -> 2263 bytes images/mood/neko/kaokitty/envious.gif | Bin 0 -> 1349 bytes images/mood/neko/kaokitty/exanimate.gif | Bin 0 -> 1293 bytes images/mood/neko/kaokitty/exausted.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/excited.gif | Bin 0 -> 1369 bytes images/mood/neko/kaokitty/flirty.gif | Bin 0 -> 1346 bytes images/mood/neko/kaokitty/frustrated.gif | Bin 0 -> 1822 bytes images/mood/neko/kaokitty/full.gif | Bin 0 -> 2362 bytes images/mood/neko/kaokitty/geeky.gif | Bin 0 -> 2439 bytes images/mood/neko/kaokitty/giddy.gif | Bin 0 -> 1299 bytes images/mood/neko/kaokitty/giggly.gif | Bin 0 -> 1307 bytes images/mood/neko/kaokitty/gloomy.gif | Bin 0 -> 1996 bytes images/mood/neko/kaokitty/good.gif | Bin 0 -> 2278 bytes images/mood/neko/kaokitty/grateful.gif | Bin 0 -> 1737 bytes images/mood/neko/kaokitty/groggy.gif | Bin 0 -> 1894 bytes images/mood/neko/kaokitty/grumpy.gif | Bin 0 -> 2012 bytes images/mood/neko/kaokitty/guilty.gif | Bin 0 -> 1728 bytes images/mood/neko/kaokitty/happy.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/high.gif | Bin 0 -> 1611 bytes images/mood/neko/kaokitty/hopeful.gif | Bin 0 -> 1756 bytes images/mood/neko/kaokitty/horny.gif | Bin 0 -> 1882 bytes images/mood/neko/kaokitty/hot.gif | Bin 0 -> 1943 bytes images/mood/neko/kaokitty/hungry.gif | Bin 0 -> 2537 bytes images/mood/neko/kaokitty/hungry2.gif | Bin 0 -> 2285 bytes images/mood/neko/kaokitty/hyper.gif | Bin 0 -> 1312 bytes images/mood/neko/kaokitty/impressed.gif | Bin 0 -> 1736 bytes images/mood/neko/kaokitty/indescribable.gif | Bin 0 -> 1256 bytes images/mood/neko/kaokitty/index.html | 182 + images/mood/neko/kaokitty/indifferent.gif | Bin 0 -> 1739 bytes images/mood/neko/kaokitty/infuriated.gif | Bin 0 -> 1447 bytes images/mood/neko/kaokitty/intimidated.gif | Bin 0 -> 1762 bytes images/mood/neko/kaokitty/irate.gif | Bin 0 -> 1798 bytes images/mood/neko/kaokitty/irritated.gif | Bin 0 -> 1297 bytes images/mood/neko/kaokitty/jubilant.gif | Bin 0 -> 1748 bytes images/mood/neko/kaokitty/kiss.gif | Bin 0 -> 1294 bytes images/mood/neko/kaokitty/kisses.gif | Bin 0 -> 1244 bytes images/mood/neko/kaokitty/lazy.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/lethargic.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/listless.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/lonely.gif | Bin 0 -> 1292 bytes images/mood/neko/kaokitty/love.gif | Bin 0 -> 532 bytes images/mood/neko/kaokitty/loved.gif | Bin 0 -> 2424 bytes images/mood/neko/kaokitty/mad.gif | Bin 0 -> 928 bytes images/mood/neko/kaokitty/melancholy.gif | Bin 0 -> 1292 bytes images/mood/neko/kaokitty/mellow.gif | Bin 0 -> 1832 bytes images/mood/neko/kaokitty/mischievous.gif | Bin 0 -> 2011 bytes images/mood/neko/kaokitty/moody.gif | Bin 0 -> 2230 bytes images/mood/neko/kaokitty/morose.gif | Bin 0 -> 1292 bytes images/mood/neko/kaokitty/musical.gif | Bin 0 -> 1430 bytes images/mood/neko/kaokitty/naughty.gif | Bin 0 -> 2013 bytes images/mood/neko/kaokitty/nauseated.gif | Bin 0 -> 796 bytes images/mood/neko/kaokitty/nerdy.gif | Bin 0 -> 1818 bytes images/mood/neko/kaokitty/nostalgic.gif | Bin 0 -> 1888 bytes images/mood/neko/kaokitty/numb.gif | Bin 0 -> 1126 bytes images/mood/neko/kaokitty/okay.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/optimistic.gif | Bin 0 -> 1756 bytes images/mood/neko/kaokitty/peaceful.gif | Bin 0 -> 1832 bytes images/mood/neko/kaokitty/pensive.gif | Bin 0 -> 1888 bytes images/mood/neko/kaokitty/pessimistic.gif | Bin 0 -> 1771 bytes images/mood/neko/kaokitty/pissed.gif | Bin 0 -> 1918 bytes images/mood/neko/kaokitty/pleased.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/predatory.gif | Bin 0 -> 2346 bytes images/mood/neko/kaokitty/productive.gif | Bin 0 -> 1187 bytes images/mood/neko/kaokitty/quiet.gif | Bin 0 -> 1723 bytes images/mood/neko/kaokitty/quixotic.gif | Bin 0 -> 1849 bytes images/mood/neko/kaokitty/recumbent.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/refreshed.gif | Bin 0 -> 2437 bytes images/mood/neko/kaokitty/rejected.gif | Bin 0 -> 1793 bytes images/mood/neko/kaokitty/rejuvenated.gif | Bin 0 -> 2437 bytes images/mood/neko/kaokitty/relaxed.gif | Bin 0 -> 1290 bytes images/mood/neko/kaokitty/relieved.gif | Bin 0 -> 2213 bytes images/mood/neko/kaokitty/restless.gif | Bin 0 -> 1736 bytes images/mood/neko/kaokitty/rushed.gif | Bin 0 -> 1684 bytes images/mood/neko/kaokitty/sad.gif | Bin 0 -> 1292 bytes images/mood/neko/kaokitty/satisfied.gif | Bin 0 -> 1300 bytes images/mood/neko/kaokitty/scared.gif | Bin 0 -> 1762 bytes images/mood/neko/kaokitty/shocked.gif | Bin 0 -> 1776 bytes images/mood/neko/kaokitty/sick.gif | Bin 0 -> 796 bytes images/mood/neko/kaokitty/silly.gif | Bin 0 -> 1849 bytes images/mood/neko/kaokitty/singing.gif | Bin 0 -> 1372 bytes images/mood/neko/kaokitty/sleepy.gif | Bin 0 -> 1443 bytes images/mood/neko/kaokitty/snow.gif | Bin 0 -> 1054 bytes images/mood/neko/kaokitty/sore.gif | Bin 0 -> 1909 bytes images/mood/neko/kaokitty/stressed.gif | Bin 0 -> 1796 bytes images/mood/neko/kaokitty/suprised.gif | Bin 0 -> 1776 bytes images/mood/neko/kaokitty/sympathetic.gif | Bin 0 -> 1762 bytes images/mood/neko/kaokitty/thankful.gif | Bin 0 -> 1746 bytes images/mood/neko/kaokitty/thirsty.gif | Bin 0 -> 2437 bytes images/mood/neko/kaokitty/thoughtful.gif | Bin 0 -> 1888 bytes images/mood/neko/kaokitty/tired.gif | Bin 0 -> 2762 bytes images/mood/neko/kaokitty/touched.gif | Bin 0 -> 1913 bytes images/mood/neko/kaokitty/uncomfortable.gif | Bin 0 -> 1762 bytes images/mood/neko/kaokitty/weird.gif | Bin 0 -> 2335 bytes images/mood/neko/kaokitty/working.gif | Bin 0 -> 1187 bytes images/mood/neko/kaokitty/worried.gif | Bin 0 -> 1762 bytes images/mood/niaha/index.html | 42 + images/mood/niaha/kitty/ankangry.gif | Bin 0 -> 398 bytes images/mood/niaha/kitty/ankangryb.gif | Bin 0 -> 398 bytes images/mood/niaha/kitty/ankangryg.gif | Bin 0 -> 398 bytes images/mood/niaha/kitty/ankangryp.gif | Bin 0 -> 399 bytes images/mood/niaha/kitty/ankangryr.gif | Bin 0 -> 398 bytes images/mood/niaha/kitty/ankawake.gif | Bin 0 -> 400 bytes images/mood/niaha/kitty/ankawakeb.gif | Bin 0 -> 400 bytes images/mood/niaha/kitty/ankawakeg.gif | Bin 0 -> 400 bytes images/mood/niaha/kitty/ankawakep.gif | Bin 0 -> 400 bytes images/mood/niaha/kitty/ankawaker.gif | Bin 0 -> 400 bytes images/mood/niaha/kitty/ankcreate.gif | Bin 0 -> 972 bytes images/mood/niaha/kitty/ankcreateb.gif | Bin 0 -> 972 bytes images/mood/niaha/kitty/ankcreateg.gif | Bin 0 -> 1220 bytes images/mood/niaha/kitty/ankcreatep.gif | Bin 0 -> 972 bytes images/mood/niaha/kitty/ankcreater.gif | Bin 0 -> 974 bytes images/mood/niaha/kitty/ankfood.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/ankfoodb.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/ankfoodg.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/ankfoodp.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/ankfoodr.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/ankgeek.gif | Bin 0 -> 347 bytes images/mood/niaha/kitty/ankgeekb.gif | Bin 0 -> 347 bytes images/mood/niaha/kitty/ankgeekg.gif | Bin 0 -> 343 bytes images/mood/niaha/kitty/ankgeekp.gif | Bin 0 -> 347 bytes images/mood/niaha/kitty/ankgeekr.gif | Bin 0 -> 347 bytes images/mood/niaha/kitty/ankhappy.gif | Bin 0 -> 330 bytes images/mood/niaha/kitty/ankhappyb.gif | Bin 0 -> 330 bytes images/mood/niaha/kitty/ankhappyg.gif | Bin 0 -> 330 bytes images/mood/niaha/kitty/ankhappyp.gif | Bin 0 -> 330 bytes images/mood/niaha/kitty/ankhappyr.gif | Bin 0 -> 328 bytes images/mood/niaha/kitty/ankhunt.gif | Bin 0 -> 322 bytes images/mood/niaha/kitty/ankhuntb.gif | Bin 0 -> 314 bytes images/mood/niaha/kitty/ankhuntg.gif | Bin 0 -> 314 bytes images/mood/niaha/kitty/ankhuntp.gif | Bin 0 -> 314 bytes images/mood/niaha/kitty/ankhuntr.gif | Bin 0 -> 314 bytes images/mood/niaha/kitty/ankhyper.gif | Bin 0 -> 390 bytes images/mood/niaha/kitty/ankhyperb.gif | Bin 0 -> 390 bytes images/mood/niaha/kitty/ankhyperg.gif | Bin 0 -> 390 bytes images/mood/niaha/kitty/ankhyperp.gif | Bin 0 -> 390 bytes images/mood/niaha/kitty/ankhyperr.gif | Bin 0 -> 390 bytes images/mood/niaha/kitty/ankitten.gif | Bin 0 -> 332 bytes images/mood/niaha/kitty/ankittenb.gif | Bin 0 -> 332 bytes images/mood/niaha/kitty/ankitteng.gif | Bin 0 -> 332 bytes images/mood/niaha/kitty/ankittenp.gif | Bin 0 -> 333 bytes images/mood/niaha/kitty/ankittenr.gif | Bin 0 -> 332 bytes images/mood/niaha/kitty/anksad.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/anksadb.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/anksadg.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/anksadp.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/anksadr.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/ankscared.gif | Bin 0 -> 419 bytes images/mood/niaha/kitty/ankscaredb.gif | Bin 0 -> 419 bytes images/mood/niaha/kitty/ankscaredg.gif | Bin 0 -> 419 bytes images/mood/niaha/kitty/ankscaredp.gif | Bin 0 -> 419 bytes images/mood/niaha/kitty/ankscaredr.gif | Bin 0 -> 419 bytes images/mood/niaha/kitty/anksleepy.gif | Bin 0 -> 593 bytes images/mood/niaha/kitty/anksleepyb.gif | Bin 0 -> 593 bytes images/mood/niaha/kitty/anksleepyg.gif | Bin 0 -> 593 bytes images/mood/niaha/kitty/anksleepyp.gif | Bin 0 -> 593 bytes images/mood/niaha/kitty/anksleepyr.gif | Bin 0 -> 593 bytes images/mood/niaha/kitty/ankthink.gif | Bin 0 -> 778 bytes images/mood/niaha/kitty/ankthinkb.gif | Bin 0 -> 778 bytes images/mood/niaha/kitty/ankthinkg.gif | Bin 0 -> 778 bytes images/mood/niaha/kitty/ankthinkp.gif | Bin 0 -> 779 bytes images/mood/niaha/kitty/ankthinkr.gif | Bin 0 -> 777 bytes images/mood/niaha/kitty/anktired.gif | Bin 0 -> 368 bytes images/mood/niaha/kitty/anktiredb.gif | Bin 0 -> 374 bytes images/mood/niaha/kitty/anktiredg.gif | Bin 0 -> 374 bytes images/mood/niaha/kitty/anktiredp.gif | Bin 0 -> 735 bytes images/mood/niaha/kitty/anktiredr.gif | Bin 0 -> 374 bytes images/mood/niaha/kitty/ankwink.gif | Bin 0 -> 320 bytes images/mood/niaha/kitty/ankwinkb.gif | Bin 0 -> 320 bytes images/mood/niaha/kitty/ankwinkg.gif | Bin 0 -> 320 bytes images/mood/niaha/kitty/ankwinkp.gif | Bin 0 -> 318 bytes images/mood/niaha/kitty/ankwinkr.gif | Bin 0 -> 320 bytes images/mood/niaha/kitty/index.html | 116 + images/mood/nolegs/aggravated.gif | Bin 0 -> 1224 bytes images/mood/nolegs/amused.gif | Bin 0 -> 1218 bytes images/mood/nolegs/angry.gif | Bin 0 -> 1187 bytes images/mood/nolegs/annoyed.gif | Bin 0 -> 1136 bytes images/mood/nolegs/bored.gif | Bin 0 -> 1062 bytes images/mood/nolegs/bounce.gif | Bin 0 -> 1188 bytes images/mood/nolegs/calm.gif | Bin 0 -> 1085 bytes images/mood/nolegs/clean.pl | 27 + images/mood/nolegs/complacent.gif | Bin 0 -> 1075 bytes images/mood/nolegs/confused.gif | Bin 0 -> 1060 bytes images/mood/nolegs/content.gif | Bin 0 -> 1083 bytes images/mood/nolegs/cranky.gif | Bin 0 -> 1078 bytes images/mood/nolegs/crappy.gif | Bin 0 -> 1041 bytes images/mood/nolegs/curious.gif | Bin 0 -> 1101 bytes images/mood/nolegs/depressed.gif | Bin 0 -> 1250 bytes images/mood/nolegs/determined.gif | Bin 0 -> 1165 bytes images/mood/nolegs/disappointed.gif | Bin 0 -> 1159 bytes images/mood/nolegs/discontent.gif | Bin 0 -> 1035 bytes images/mood/nolegs/ditzy.gif | Bin 0 -> 1290 bytes images/mood/nolegs/drained.gif | Bin 0 -> 1190 bytes images/mood/nolegs/drunk.gif | Bin 0 -> 1308 bytes images/mood/nolegs/energetic.gif | Bin 0 -> 1122 bytes images/mood/nolegs/enraged.gif | Bin 0 -> 1097 bytes images/mood/nolegs/enthralled.gif | Bin 0 -> 1167 bytes images/mood/nolegs/excited.gif | Bin 0 -> 1222 bytes images/mood/nolegs/exhausted.gif | Bin 0 -> 1343 bytes images/mood/nolegs/flirty.gif | Bin 0 -> 1115 bytes images/mood/nolegs/frustrated.gif | Bin 0 -> 1593 bytes images/mood/nolegs/giggly.gif | Bin 0 -> 1205 bytes images/mood/nolegs/gloomy.gif | Bin 0 -> 1162 bytes images/mood/nolegs/groggy.gif | Bin 0 -> 1050 bytes images/mood/nolegs/happy.gif | Bin 0 -> 1162 bytes images/mood/nolegs/high.gif | Bin 0 -> 1338 bytes images/mood/nolegs/horny.gif | Bin 0 -> 1056 bytes images/mood/nolegs/hyper.gif | Bin 0 -> 1179 bytes images/mood/nolegs/indescribable.gif | Bin 0 -> 948 bytes images/mood/nolegs/index.html | 114 + images/mood/nolegs/indifferent.gif | Bin 0 -> 1227 bytes images/mood/nolegs/infuriated.gif | Bin 0 -> 1098 bytes images/mood/nolegs/irate.gif | Bin 0 -> 1083 bytes images/mood/nolegs/jubilant.gif | Bin 0 -> 1105 bytes images/mood/nolegs/lazy.gif | Bin 0 -> 1093 bytes images/mood/nolegs/lethargic.gif | Bin 0 -> 1034 bytes images/mood/nolegs/listless.gif | Bin 0 -> 1213 bytes images/mood/nolegs/lonely.gif | Bin 0 -> 1035 bytes images/mood/nolegs/melancholy.gif | Bin 0 -> 1145 bytes images/mood/nolegs/mellow.gif | Bin 0 -> 1194 bytes images/mood/nolegs/mischievous.gif | Bin 0 -> 1284 bytes images/mood/nolegs/moody.gif | Bin 0 -> 927 bytes images/mood/nolegs/morose.gif | Bin 0 -> 1026 bytes images/mood/nolegs/nostalgic.gif | Bin 0 -> 1059 bytes images/mood/nolegs/okay.gif | Bin 0 -> 1099 bytes images/mood/nolegs/optimistic.gif | Bin 0 -> 1075 bytes images/mood/nolegs/peaceful.gif | Bin 0 -> 1127 bytes images/mood/nolegs/pensive.gif | Bin 0 -> 1199 bytes images/mood/nolegs/pessimistic.gif | Bin 0 -> 1084 bytes images/mood/nolegs/pissed.gif | Bin 0 -> 1157 bytes images/mood/nolegs/recumbent.gif | Bin 0 -> 1164 bytes images/mood/nolegs/refreshed.gif | Bin 0 -> 1050 bytes images/mood/nolegs/rejuvenated.gif | Bin 0 -> 1114 bytes images/mood/nolegs/relaxed.gif | Bin 0 -> 1053 bytes images/mood/nolegs/relieved.gif | Bin 0 -> 1048 bytes images/mood/nolegs/restless.gif | Bin 0 -> 1051 bytes images/mood/nolegs/sad.gif | Bin 0 -> 1180 bytes images/mood/nolegs/satisfied.gif | Bin 0 -> 1157 bytes images/mood/nolegs/scared.gif | Bin 0 -> 1153 bytes images/mood/nolegs/silly.gif | Bin 0 -> 1130 bytes images/mood/nolegs/sleepy.gif | Bin 0 -> 1134 bytes images/mood/nolegs/sore.gif | Bin 0 -> 1052 bytes images/mood/nolegs/sqlstuff.txt | 160 + images/mood/nolegs/stressed.gif | Bin 0 -> 1059 bytes images/mood/nolegs/thirsty.gif | Bin 0 -> 1122 bytes images/mood/nolegs/thoughtful.gif | Bin 0 -> 1055 bytes images/mood/nolegs/tired.gif | Bin 0 -> 1149 bytes images/mood/nolegs/touched.gif | Bin 0 -> 1209 bytes images/mood/nolegs/uncomfortable.gif | Bin 0 -> 1112 bytes images/mood/opiummmm/foxies/angry.gif | Bin 0 -> 210 bytes images/mood/opiummmm/foxies/awake.gif | Bin 0 -> 222 bytes images/mood/opiummmm/foxies/confused.gif | Bin 0 -> 195 bytes images/mood/opiummmm/foxies/determined.gif | Bin 0 -> 245 bytes images/mood/opiummmm/foxies/discontent.gif | Bin 0 -> 222 bytes images/mood/opiummmm/foxies/energetic.gif | Bin 0 -> 238 bytes images/mood/opiummmm/foxies/enthralled.gif | Bin 0 -> 225 bytes images/mood/opiummmm/foxies/happy.gif | Bin 0 -> 224 bytes images/mood/opiummmm/foxies/indescribable.gif | Bin 0 -> 201 bytes images/mood/opiummmm/foxies/index.html | 56 + images/mood/opiummmm/foxies/nerdy.gif | Bin 0 -> 653 bytes images/mood/opiummmm/foxies/okay.gif | Bin 0 -> 222 bytes images/mood/opiummmm/foxies/sad.gif | Bin 0 -> 216 bytes images/mood/opiummmm/foxies/scared.gif | Bin 0 -> 216 bytes images/mood/opiummmm/foxies/thoughtful.gif | Bin 0 -> 204 bytes images/mood/opiummmm/foxies/working.gif | Bin 0 -> 293 bytes images/mood/opiummmm/index.html | 42 + images/mood/palefaces/aggravated.gif | Bin 0 -> 862 bytes images/mood/palefaces/amused.gif | Bin 0 -> 863 bytes images/mood/palefaces/angry.gif | Bin 0 -> 866 bytes images/mood/palefaces/annoyed.gif | Bin 0 -> 862 bytes images/mood/palefaces/anxious.gif | Bin 0 -> 860 bytes images/mood/palefaces/artistic.gif | Bin 0 -> 1054 bytes images/mood/palefaces/awake.gif | Bin 0 -> 537 bytes images/mood/palefaces/bitchy.gif | Bin 0 -> 870 bytes images/mood/palefaces/blank.gif | Bin 0 -> 900 bytes images/mood/palefaces/bouncy.gif | Bin 0 -> 612 bytes images/mood/palefaces/busy.gif | Bin 0 -> 864 bytes images/mood/palefaces/cheerful.gif | Bin 0 -> 870 bytes images/mood/palefaces/cold.gif | Bin 0 -> 1335 bytes images/mood/palefaces/complacent.gif | Bin 0 -> 867 bytes images/mood/palefaces/confused.gif | Bin 0 -> 404 bytes images/mood/palefaces/cranky.gif | Bin 0 -> 556 bytes images/mood/palefaces/crushed.gif | Bin 0 -> 862 bytes images/mood/palefaces/curious.gif | Bin 0 -> 510 bytes images/mood/palefaces/cynical.gif | Bin 0 -> 865 bytes images/mood/palefaces/depressed.gif | Bin 0 -> 884 bytes images/mood/palefaces/determined.gif | Bin 0 -> 862 bytes images/mood/palefaces/dirty.gif | Bin 0 -> 665 bytes images/mood/palefaces/drunk.gif | Bin 0 -> 821 bytes images/mood/palefaces/ecstatic.gif | Bin 0 -> 577 bytes images/mood/palefaces/embarrassed.gif | Bin 0 -> 685 bytes images/mood/palefaces/energetic.gif | Bin 0 -> 422 bytes images/mood/palefaces/enraged.gif | Bin 0 -> 833 bytes images/mood/palefaces/enthralled.gif | Bin 0 -> 870 bytes images/mood/palefaces/envious.gif | Bin 0 -> 852 bytes images/mood/palefaces/exhausted.gif | Bin 0 -> 667 bytes images/mood/palefaces/frustrated.gif | Bin 0 -> 860 bytes images/mood/palefaces/full.gif | Bin 0 -> 564 bytes images/mood/palefaces/gloomy.gif | Bin 0 -> 852 bytes images/mood/palefaces/good.gif | Bin 0 -> 865 bytes images/mood/palefaces/groggy.gif | Bin 0 -> 1005 bytes images/mood/palefaces/grumpy.gif | Bin 0 -> 418 bytes images/mood/palefaces/happy.gif | Bin 0 -> 871 bytes images/mood/palefaces/high.gif | Bin 0 -> 483 bytes images/mood/palefaces/horny.gif | Bin 0 -> 493 bytes images/mood/palefaces/hot.gif | Bin 0 -> 1001 bytes images/mood/palefaces/hungry.gif | Bin 0 -> 863 bytes images/mood/palefaces/hyper.gif | Bin 0 -> 1121 bytes images/mood/palefaces/impressed.gif | Bin 0 -> 870 bytes images/mood/palefaces/indescribable.gif | Bin 0 -> 943 bytes images/mood/palefaces/index.html | 108 + images/mood/palefaces/lazy.gif | Bin 0 -> 603 bytes images/mood/palefaces/loved.gif | Bin 0 -> 808 bytes images/mood/palefaces/mischievous.gif | Bin 0 -> 433 bytes images/mood/palefaces/moody.gif | Bin 0 -> 485 bytes images/mood/palefaces/nerdy.gif | Bin 0 -> 672 bytes images/mood/palefaces/nostalgic.gif | Bin 0 -> 435 bytes images/mood/palefaces/okay.gif | Bin 0 -> 865 bytes images/mood/palefaces/predatory.gif | Bin 0 -> 865 bytes images/mood/palefaces/refreshed.gif | Bin 0 -> 681 bytes images/mood/palefaces/relaxed.gif | Bin 0 -> 624 bytes images/mood/palefaces/relieved.gif | Bin 0 -> 775 bytes images/mood/palefaces/rushed.gif | Bin 0 -> 714 bytes images/mood/palefaces/sad.gif | Bin 0 -> 860 bytes images/mood/palefaces/scared.gif | Bin 0 -> 407 bytes images/mood/palefaces/shocked.gif | Bin 0 -> 871 bytes images/mood/palefaces/sick.gif | Bin 0 -> 1856 bytes images/mood/palefaces/silly.gif | Bin 0 -> 1030 bytes images/mood/palefaces/sleepy.gif | Bin 0 -> 672 bytes images/mood/palefaces/sore.gif | Bin 0 -> 1219 bytes images/mood/palefaces/surprised.gif | Bin 0 -> 675 bytes images/mood/palefaces/thirsty.gif | Bin 0 -> 597 bytes images/mood/palefaces/thoughtful.gif | Bin 0 -> 863 bytes images/mood/palefaces/worried.gif | Bin 0 -> 862 bytes images/mood/punquinheads/blue/angelic.gif | Bin 0 -> 2006 bytes images/mood/punquinheads/blue/angry.gif | Bin 0 -> 1147 bytes images/mood/punquinheads/blue/artistic.gif | Bin 0 -> 1747 bytes images/mood/punquinheads/blue/awake.gif | Bin 0 -> 1668 bytes images/mood/punquinheads/blue/blah.gif | Bin 0 -> 960 bytes images/mood/punquinheads/blue/blank.gif | Bin 0 -> 347 bytes images/mood/punquinheads/blue/brainy.gif | Bin 0 -> 1412 bytes images/mood/punquinheads/blue/caffeinated.gif | Bin 0 -> 1148 bytes images/mood/punquinheads/blue/cheerful.gif | Bin 0 -> 967 bytes images/mood/punquinheads/blue/cold.gif | Bin 0 -> 635 bytes images/mood/punquinheads/blue/confused.gif | Bin 0 -> 1053 bytes images/mood/punquinheads/blue/curious.gif | Bin 0 -> 967 bytes images/mood/punquinheads/blue/determined.gif | Bin 0 -> 1067 bytes images/mood/punquinheads/blue/dirty.gif | Bin 0 -> 1206 bytes images/mood/punquinheads/blue/dizzy.gif | Bin 0 -> 1743 bytes images/mood/punquinheads/blue/embarrassed.gif | Bin 0 -> 960 bytes images/mood/punquinheads/blue/envious.gif | Bin 0 -> 613 bytes images/mood/punquinheads/blue/excited.gif | Bin 0 -> 970 bytes images/mood/punquinheads/blue/flirty.gif | Bin 0 -> 1117 bytes images/mood/punquinheads/blue/freakingout.gif | Bin 0 -> 1903 bytes images/mood/punquinheads/blue/full.gif | Bin 0 -> 1049 bytes images/mood/punquinheads/blue/giggly.gif | Bin 0 -> 1504 bytes images/mood/punquinheads/blue/gloomy.gif | Bin 0 -> 971 bytes images/mood/punquinheads/blue/groggy.gif | Bin 0 -> 508 bytes images/mood/punquinheads/blue/grossedout.gif | Bin 0 -> 977 bytes images/mood/punquinheads/blue/grumpy.gif | Bin 0 -> 1344 bytes images/mood/punquinheads/blue/happy.gif | Bin 0 -> 966 bytes images/mood/punquinheads/blue/hopeful.gif | Bin 0 -> 994 bytes images/mood/punquinheads/blue/hot.gif | Bin 0 -> 1602 bytes images/mood/punquinheads/blue/hungry.gif | Bin 0 -> 966 bytes images/mood/punquinheads/blue/hungry2.gif | Bin 0 -> 1263 bytes images/mood/punquinheads/blue/hyper.gif | Bin 0 -> 962 bytes .../mood/punquinheads/blue/indescribable.gif | Bin 0 -> 809 bytes images/mood/punquinheads/blue/index.html | 102 + images/mood/punquinheads/blue/indifferent.gif | Bin 0 -> 960 bytes images/mood/punquinheads/blue/lazy.gif | Bin 0 -> 1041 bytes images/mood/punquinheads/blue/loved.gif | Bin 0 -> 1115 bytes images/mood/punquinheads/blue/magical.gif | Bin 0 -> 1455 bytes images/mood/punquinheads/blue/mellow.gif | Bin 0 -> 446 bytes images/mood/punquinheads/blue/moody.gif | Bin 0 -> 969 bytes images/mood/punquinheads/blue/musical.gif | Bin 0 -> 1484 bytes images/mood/punquinheads/blue/naughty.gif | Bin 0 -> 579 bytes images/mood/punquinheads/blue/nerdy.gif | Bin 0 -> 1159 bytes images/mood/punquinheads/blue/okay.gif | Bin 0 -> 957 bytes images/mood/punquinheads/blue/rockin.gif | Bin 0 -> 1671 bytes images/mood/punquinheads/blue/sad.gif | Bin 0 -> 1133 bytes images/mood/punquinheads/blue/sick.gif | Bin 0 -> 1410 bytes images/mood/punquinheads/blue/silly.gif | Bin 0 -> 1023 bytes images/mood/punquinheads/blue/sleepy.gif | Bin 0 -> 1320 bytes images/mood/punquinheads/blue/smart.gif | Bin 0 -> 1608 bytes images/mood/punquinheads/blue/sneezy.gif | Bin 0 -> 1000 bytes images/mood/punquinheads/blue/sore.gif | Bin 0 -> 1358 bytes images/mood/punquinheads/blue/spooky.gif | Bin 0 -> 1867 bytes images/mood/punquinheads/blue/stressed.gif | Bin 0 -> 2530 bytes images/mood/punquinheads/blue/stupid.gif | Bin 0 -> 1056 bytes images/mood/punquinheads/blue/surprised.gif | Bin 0 -> 991 bytes images/mood/punquinheads/blue/thirsty.gif | Bin 0 -> 1012 bytes images/mood/punquinheads/blue/thoughtful.gif | Bin 0 -> 1201 bytes images/mood/punquinheads/blue/tired.gif | Bin 0 -> 958 bytes images/mood/punquinheads/blue/unfocused.gif | Bin 0 -> 1082 bytes images/mood/punquinheads/blue/working.gif | Bin 0 -> 1768 bytes images/mood/punquinheads/blue/worried.gif | Bin 0 -> 987 bytes images/mood/punquinheads/index.html | 43 + images/mood/punquinheads/pink/angelic.gif | Bin 0 -> 2080 bytes images/mood/punquinheads/pink/angry.gif | Bin 0 -> 1148 bytes images/mood/punquinheads/pink/artistic.gif | Bin 0 -> 1727 bytes images/mood/punquinheads/pink/awake.gif | Bin 0 -> 1651 bytes images/mood/punquinheads/pink/blah.gif | Bin 0 -> 952 bytes images/mood/punquinheads/pink/blank.gif | Bin 0 -> 782 bytes images/mood/punquinheads/pink/brainy.gif | Bin 0 -> 1433 bytes images/mood/punquinheads/pink/caffeinated.gif | Bin 0 -> 1170 bytes images/mood/punquinheads/pink/cheerful.gif | Bin 0 -> 960 bytes images/mood/punquinheads/pink/cold.gif | Bin 0 -> 591 bytes images/mood/punquinheads/pink/confused.gif | Bin 0 -> 1048 bytes images/mood/punquinheads/pink/curious.gif | Bin 0 -> 951 bytes images/mood/punquinheads/pink/determined.gif | Bin 0 -> 1021 bytes images/mood/punquinheads/pink/dirty.gif | Bin 0 -> 1262 bytes images/mood/punquinheads/pink/dizzy.gif | Bin 0 -> 1761 bytes images/mood/punquinheads/pink/embarrassed.gif | Bin 0 -> 960 bytes images/mood/punquinheads/pink/envious.gif | Bin 0 -> 566 bytes images/mood/punquinheads/pink/excited.gif | Bin 0 -> 993 bytes images/mood/punquinheads/pink/flirty.gif | Bin 0 -> 1117 bytes images/mood/punquinheads/pink/freakingout.gif | Bin 0 -> 1933 bytes images/mood/punquinheads/pink/full.gif | Bin 0 -> 1048 bytes images/mood/punquinheads/pink/giggly.gif | Bin 0 -> 1499 bytes images/mood/punquinheads/pink/gloomy.gif | Bin 0 -> 962 bytes images/mood/punquinheads/pink/groggy.gif | Bin 0 -> 489 bytes images/mood/punquinheads/pink/grossedout.gif | Bin 0 -> 970 bytes images/mood/punquinheads/pink/grumpy.gif | Bin 0 -> 1290 bytes images/mood/punquinheads/pink/happy.gif | Bin 0 -> 957 bytes images/mood/punquinheads/pink/hopeful.gif | Bin 0 -> 1027 bytes images/mood/punquinheads/pink/hot.gif | Bin 0 -> 1537 bytes images/mood/punquinheads/pink/hungry.gif | Bin 0 -> 1033 bytes images/mood/punquinheads/pink/hungry2.gif | Bin 0 -> 1300 bytes images/mood/punquinheads/pink/hyper.gif | Bin 0 -> 957 bytes .../mood/punquinheads/pink/indescribable.gif | Bin 0 -> 809 bytes images/mood/punquinheads/pink/index.html | 102 + images/mood/punquinheads/pink/indifferent.gif | Bin 0 -> 952 bytes images/mood/punquinheads/pink/lazy.gif | Bin 0 -> 1039 bytes images/mood/punquinheads/pink/loved.gif | Bin 0 -> 1115 bytes images/mood/punquinheads/pink/magical.gif | Bin 0 -> 1482 bytes images/mood/punquinheads/pink/mellow.gif | Bin 0 -> 425 bytes images/mood/punquinheads/pink/moody.gif | Bin 0 -> 961 bytes images/mood/punquinheads/pink/musical.gif | Bin 0 -> 1411 bytes images/mood/punquinheads/pink/naughty.gif | Bin 0 -> 532 bytes images/mood/punquinheads/pink/nerdy.gif | Bin 0 -> 1100 bytes images/mood/punquinheads/pink/okay.gif | Bin 0 -> 956 bytes images/mood/punquinheads/pink/rockin.gif | Bin 0 -> 1694 bytes images/mood/punquinheads/pink/sad.gif | Bin 0 -> 1087 bytes images/mood/punquinheads/pink/sick.gif | Bin 0 -> 1372 bytes images/mood/punquinheads/pink/silly.gif | Bin 0 -> 971 bytes images/mood/punquinheads/pink/sleepy.gif | Bin 0 -> 1270 bytes images/mood/punquinheads/pink/smart.gif | Bin 0 -> 1545 bytes images/mood/punquinheads/pink/sneezy.gif | Bin 0 -> 989 bytes images/mood/punquinheads/pink/sore.gif | Bin 0 -> 1299 bytes images/mood/punquinheads/pink/spooky.gif | Bin 0 -> 1867 bytes images/mood/punquinheads/pink/stressed.gif | Bin 0 -> 2520 bytes images/mood/punquinheads/pink/stupid.gif | Bin 0 -> 1089 bytes images/mood/punquinheads/pink/surprised.gif | Bin 0 -> 980 bytes images/mood/punquinheads/pink/thirsty.gif | Bin 0 -> 943 bytes images/mood/punquinheads/pink/thoughtful.gif | Bin 0 -> 1243 bytes images/mood/punquinheads/pink/tired.gif | Bin 0 -> 949 bytes images/mood/punquinheads/pink/unfocused.gif | Bin 0 -> 1111 bytes images/mood/punquinheads/pink/working.gif | Bin 0 -> 1841 bytes images/mood/punquinheads/pink/worried.gif | Bin 0 -> 972 bytes images/mood/roshi/index.html | 42 + images/mood/roshi/palefaces/aggravated.gif | Bin 0 -> 862 bytes images/mood/roshi/palefaces/amused.gif | Bin 0 -> 863 bytes images/mood/roshi/palefaces/angry.gif | Bin 0 -> 866 bytes images/mood/roshi/palefaces/annoyed.gif | Bin 0 -> 862 bytes images/mood/roshi/palefaces/anxious.gif | Bin 0 -> 860 bytes images/mood/roshi/palefaces/artistic.gif | Bin 0 -> 1054 bytes images/mood/roshi/palefaces/awake.gif | Bin 0 -> 537 bytes images/mood/roshi/palefaces/bitchy.gif | Bin 0 -> 870 bytes images/mood/roshi/palefaces/blank.gif | Bin 0 -> 900 bytes images/mood/roshi/palefaces/bouncy.gif | Bin 0 -> 612 bytes images/mood/roshi/palefaces/busy.gif | Bin 0 -> 864 bytes images/mood/roshi/palefaces/cheerful.gif | Bin 0 -> 870 bytes images/mood/roshi/palefaces/cold.gif | Bin 0 -> 1335 bytes images/mood/roshi/palefaces/complacent.gif | Bin 0 -> 867 bytes images/mood/roshi/palefaces/confused.gif | Bin 0 -> 404 bytes images/mood/roshi/palefaces/cranky.gif | Bin 0 -> 556 bytes images/mood/roshi/palefaces/crushed.gif | Bin 0 -> 862 bytes images/mood/roshi/palefaces/curious.gif | Bin 0 -> 510 bytes images/mood/roshi/palefaces/cynical.gif | Bin 0 -> 865 bytes images/mood/roshi/palefaces/depressed.gif | Bin 0 -> 884 bytes images/mood/roshi/palefaces/determined.gif | Bin 0 -> 862 bytes images/mood/roshi/palefaces/dirty.gif | Bin 0 -> 665 bytes images/mood/roshi/palefaces/drunk.gif | Bin 0 -> 821 bytes images/mood/roshi/palefaces/ecstatic.gif | Bin 0 -> 577 bytes images/mood/roshi/palefaces/embarrassed.gif | Bin 0 -> 685 bytes images/mood/roshi/palefaces/energetic.gif | Bin 0 -> 422 bytes images/mood/roshi/palefaces/enraged.gif | Bin 0 -> 833 bytes images/mood/roshi/palefaces/enthralled.gif | Bin 0 -> 870 bytes images/mood/roshi/palefaces/envious.gif | Bin 0 -> 852 bytes images/mood/roshi/palefaces/exhausted.gif | Bin 0 -> 667 bytes images/mood/roshi/palefaces/frustrated.gif | Bin 0 -> 860 bytes images/mood/roshi/palefaces/full.gif | Bin 0 -> 564 bytes images/mood/roshi/palefaces/gloomy.gif | Bin 0 -> 852 bytes images/mood/roshi/palefaces/good.gif | Bin 0 -> 865 bytes images/mood/roshi/palefaces/groggy.gif | Bin 0 -> 1005 bytes images/mood/roshi/palefaces/grumpy.gif | Bin 0 -> 418 bytes images/mood/roshi/palefaces/happy.gif | Bin 0 -> 871 bytes images/mood/roshi/palefaces/high.gif | Bin 0 -> 483 bytes images/mood/roshi/palefaces/horny.gif | Bin 0 -> 493 bytes images/mood/roshi/palefaces/hot.gif | Bin 0 -> 1001 bytes images/mood/roshi/palefaces/hungry.gif | Bin 0 -> 863 bytes images/mood/roshi/palefaces/hyper.gif | Bin 0 -> 1121 bytes images/mood/roshi/palefaces/impressed.gif | Bin 0 -> 870 bytes images/mood/roshi/palefaces/indescribable.gif | Bin 0 -> 943 bytes images/mood/roshi/palefaces/index.html | 108 + images/mood/roshi/palefaces/lazy.gif | Bin 0 -> 603 bytes images/mood/roshi/palefaces/loved.gif | Bin 0 -> 808 bytes images/mood/roshi/palefaces/mischievous.gif | Bin 0 -> 433 bytes images/mood/roshi/palefaces/moody.gif | Bin 0 -> 485 bytes images/mood/roshi/palefaces/nerdy.gif | Bin 0 -> 672 bytes images/mood/roshi/palefaces/nostalgic.gif | Bin 0 -> 435 bytes images/mood/roshi/palefaces/okay.gif | Bin 0 -> 865 bytes images/mood/roshi/palefaces/predatory.gif | Bin 0 -> 865 bytes images/mood/roshi/palefaces/refreshed.gif | Bin 0 -> 681 bytes images/mood/roshi/palefaces/relaxed.gif | Bin 0 -> 624 bytes images/mood/roshi/palefaces/relieved.gif | Bin 0 -> 775 bytes images/mood/roshi/palefaces/rushed.gif | Bin 0 -> 714 bytes images/mood/roshi/palefaces/sad.gif | Bin 0 -> 860 bytes images/mood/roshi/palefaces/scared.gif | Bin 0 -> 407 bytes images/mood/roshi/palefaces/shocked.gif | Bin 0 -> 871 bytes images/mood/roshi/palefaces/sick.gif | Bin 0 -> 1856 bytes images/mood/roshi/palefaces/silly.gif | Bin 0 -> 1030 bytes images/mood/roshi/palefaces/sleepy.gif | Bin 0 -> 672 bytes images/mood/roshi/palefaces/sore.gif | Bin 0 -> 1219 bytes images/mood/roshi/palefaces/surprised.gif | Bin 0 -> 675 bytes images/mood/roshi/palefaces/thirsty.gif | Bin 0 -> 597 bytes images/mood/roshi/palefaces/thoughtful.gif | Bin 0 -> 863 bytes images/mood/roshi/palefaces/worried.gif | Bin 0 -> 862 bytes images/mood/sam/aggravated.gif | Bin 0 -> 643 bytes images/mood/sam/amused.gif | Bin 0 -> 625 bytes images/mood/sam/angry.gif | Bin 0 -> 841 bytes images/mood/sam/annoyed.gif | Bin 0 -> 609 bytes images/mood/sam/anxious.gif | Bin 0 -> 588 bytes images/mood/sam/bored.gif | Bin 0 -> 851 bytes images/mood/sam/bouncy.gif | Bin 0 -> 859 bytes images/mood/sam/calm.gif | Bin 0 -> 560 bytes images/mood/sam/clean.pl | 27 + images/mood/sam/complacent.gif | Bin 0 -> 633 bytes images/mood/sam/confused.gif | Bin 0 -> 663 bytes images/mood/sam/content.gif | Bin 0 -> 592 bytes images/mood/sam/cranky.gif | Bin 0 -> 592 bytes images/mood/sam/crappy.gif | Bin 0 -> 616 bytes images/mood/sam/curious.gif | Bin 0 -> 645 bytes images/mood/sam/depressed.gif | Bin 0 -> 618 bytes images/mood/sam/determined.gif | Bin 0 -> 746 bytes images/mood/sam/disappointed.gif | Bin 0 -> 614 bytes images/mood/sam/discontent.gif | Bin 0 -> 592 bytes images/mood/sam/ditzy.gif | Bin 0 -> 935 bytes images/mood/sam/drained.gif | Bin 0 -> 704 bytes images/mood/sam/drunk.gif | Bin 0 -> 681 bytes images/mood/sam/embarrassed.gif | Bin 0 -> 1599 bytes images/mood/sam/energetic.gif | Bin 0 -> 893 bytes images/mood/sam/enfuriated.gif | Bin 0 -> 612 bytes images/mood/sam/enraged.gif | Bin 0 -> 625 bytes images/mood/sam/enthralled.gif | Bin 0 -> 612 bytes images/mood/sam/envious.gif | Bin 0 -> 1809 bytes images/mood/sam/exanimate.gif | Bin 0 -> 822 bytes images/mood/sam/excited.gif | Bin 0 -> 653 bytes images/mood/sam/exhausted.gif | Bin 0 -> 616 bytes images/mood/sam/flirty.gif | Bin 0 -> 560 bytes images/mood/sam/frustrated.gif | Bin 0 -> 623 bytes images/mood/sam/giggly.gif | Bin 0 -> 860 bytes images/mood/sam/gloomy.gif | Bin 0 -> 624 bytes images/mood/sam/groggy.gif | Bin 0 -> 592 bytes images/mood/sam/happy.gif | Bin 0 -> 569 bytes images/mood/sam/high.gif | Bin 0 -> 562 bytes images/mood/sam/hopeful.gif | Bin 0 -> 883 bytes images/mood/sam/horny.gif | Bin 0 -> 886 bytes images/mood/sam/hungry.gif | Bin 0 -> 667 bytes images/mood/sam/hyper.gif | Bin 0 -> 606 bytes images/mood/sam/indescribable.gif | Bin 0 -> 614 bytes images/mood/sam/index.html | 122 + images/mood/sam/indifferent.gif | Bin 0 -> 612 bytes images/mood/sam/infuriated.gif | Bin 0 -> 612 bytes images/mood/sam/irate.gif | Bin 0 -> 825 bytes images/mood/sam/jubilant.gif | Bin 0 -> 890 bytes images/mood/sam/lazy.gif | Bin 0 -> 577 bytes images/mood/sam/lethargic.gif | Bin 0 -> 594 bytes images/mood/sam/listless.gif | Bin 0 -> 595 bytes images/mood/sam/lonely.gif | Bin 0 -> 616 bytes images/mood/sam/melancholy.gif | Bin 0 -> 634 bytes images/mood/sam/mellow.gif | Bin 0 -> 596 bytes images/mood/sam/mischieveous.gif | Bin 0 -> 843 bytes images/mood/sam/mischievous.gif | Bin 0 -> 843 bytes images/mood/sam/moody.gif | Bin 0 -> 608 bytes images/mood/sam/morose.gif | Bin 0 -> 631 bytes images/mood/sam/nostalgic.gif | Bin 0 -> 623 bytes images/mood/sam/okay.gif | Bin 0 -> 589 bytes images/mood/sam/optimistic.gif | Bin 0 -> 866 bytes images/mood/sam/peaceful.gif | Bin 0 -> 585 bytes images/mood/sam/pensive.gif | Bin 0 -> 621 bytes images/mood/sam/pessimistic.gif | Bin 0 -> 615 bytes images/mood/sam/pissed.gif | Bin 0 -> 822 bytes images/mood/sam/recumbant.gif | Bin 0 -> 607 bytes images/mood/sam/refreshed.gif | Bin 0 -> 900 bytes images/mood/sam/rejuvenated.gif | Bin 0 -> 853 bytes images/mood/sam/relaxed.gif | Bin 0 -> 601 bytes images/mood/sam/relieved.gif | Bin 0 -> 663 bytes images/mood/sam/restless.gif | Bin 0 -> 626 bytes images/mood/sam/sad.gif | Bin 0 -> 606 bytes images/mood/sam/satisfied.gif | Bin 0 -> 622 bytes images/mood/sam/scared.gif | Bin 0 -> 540 bytes images/mood/sam/silly.gif | Bin 0 -> 870 bytes images/mood/sam/sleepy.gif | Bin 0 -> 616 bytes images/mood/sam/sore.gif | Bin 0 -> 625 bytes images/mood/sam/sqlstuff.txt | 160 + images/mood/sam/stressed.gif | Bin 0 -> 632 bytes images/mood/sam/thirsty.gif | Bin 0 -> 658 bytes images/mood/sam/thoughtful.gif | Bin 0 -> 592 bytes images/mood/sam/tired.gif | Bin 0 -> 693 bytes images/mood/sam/touched.gif | Bin 0 -> 644 bytes images/mood/sam/uncomfortable.gif | Bin 0 -> 605 bytes images/mood/square/b/aggravated.gif | Bin 0 -> 434 bytes images/mood/square/b/artistic.gif | Bin 0 -> 475 bytes images/mood/square/b/bored.gif | Bin 0 -> 405 bytes images/mood/square/b/cold.gif | Bin 0 -> 855 bytes images/mood/square/b/confused.gif | Bin 0 -> 451 bytes images/mood/square/b/content.gif | Bin 0 -> 426 bytes images/mood/square/b/cranky.gif | Bin 0 -> 493 bytes images/mood/square/b/curious.gif | Bin 0 -> 430 bytes images/mood/square/b/embarrassed.gif | Bin 0 -> 692 bytes images/mood/square/b/envious.gif | Bin 0 -> 718 bytes images/mood/square/b/evil.gif | Bin 0 -> 692 bytes images/mood/square/b/full.gif | Bin 0 -> 430 bytes images/mood/square/b/giggly.gif | Bin 0 -> 667 bytes images/mood/square/b/groggy.gif | Bin 0 -> 420 bytes images/mood/square/b/happy.gif | Bin 0 -> 760 bytes images/mood/square/b/hopeful.gif | Bin 0 -> 793 bytes images/mood/square/b/hot.gif | Bin 0 -> 835 bytes images/mood/square/b/hungry.gif | Bin 0 -> 753 bytes images/mood/square/b/hyper.gif | Bin 0 -> 1149 bytes images/mood/square/b/index.html | 71 + images/mood/square/b/loved.gif | Bin 0 -> 465 bytes images/mood/square/b/mellow.gif | Bin 0 -> 712 bytes images/mood/square/b/nerdy.gif | Bin 0 -> 1222 bytes images/mood/square/b/okay.gif | Bin 0 -> 406 bytes images/mood/square/b/prepare.pl | 64 + images/mood/square/b/sad.gif | Bin 0 -> 738 bytes images/mood/square/b/sick.gif | Bin 0 -> 830 bytes images/mood/square/b/silly.gif | Bin 0 -> 439 bytes images/mood/square/b/sleepy.gif | Bin 0 -> 424 bytes images/mood/square/b/stressed.gif | Bin 0 -> 619 bytes images/mood/square/b/tired.gif | Bin 0 -> 287 bytes images/mood/square/b/worried.gif | Bin 0 -> 514 bytes images/mood/square/index.html | 44 + images/mood/square/p/aggravated.gif | Bin 0 -> 434 bytes images/mood/square/p/artistic.gif | Bin 0 -> 475 bytes images/mood/square/p/bored.gif | Bin 0 -> 405 bytes images/mood/square/p/cold.gif | Bin 0 -> 855 bytes images/mood/square/p/confused.gif | Bin 0 -> 451 bytes images/mood/square/p/content.gif | Bin 0 -> 425 bytes images/mood/square/p/cranky.gif | Bin 0 -> 491 bytes images/mood/square/p/curious.gif | Bin 0 -> 429 bytes images/mood/square/p/embarrassed.gif | Bin 0 -> 692 bytes images/mood/square/p/envious.gif | Bin 0 -> 717 bytes images/mood/square/p/evil.gif | Bin 0 -> 691 bytes images/mood/square/p/full.gif | Bin 0 -> 430 bytes images/mood/square/p/giggly.gif | Bin 0 -> 666 bytes images/mood/square/p/groggy.gif | Bin 0 -> 420 bytes images/mood/square/p/happy.gif | Bin 0 -> 757 bytes images/mood/square/p/hopeful.gif | Bin 0 -> 788 bytes images/mood/square/p/hot.gif | Bin 0 -> 835 bytes images/mood/square/p/hungry.gif | Bin 0 -> 751 bytes images/mood/square/p/hyper.gif | Bin 0 -> 1144 bytes images/mood/square/p/index.html | 71 + images/mood/square/p/loved.gif | Bin 0 -> 464 bytes images/mood/square/p/mellow.gif | Bin 0 -> 712 bytes images/mood/square/p/nerdy.gif | Bin 0 -> 1222 bytes images/mood/square/p/okay.gif | Bin 0 -> 406 bytes images/mood/square/p/sad.gif | Bin 0 -> 739 bytes images/mood/square/p/sick.gif | Bin 0 -> 830 bytes images/mood/square/p/silly.gif | Bin 0 -> 438 bytes images/mood/square/p/sleepy.gif | Bin 0 -> 424 bytes images/mood/square/p/stressed.gif | Bin 0 -> 617 bytes images/mood/square/p/tired.gif | Bin 0 -> 287 bytes images/mood/square/p/worried.gif | Bin 0 -> 514 bytes images/mood/square/y/aggravated.gif | Bin 0 -> 433 bytes images/mood/square/y/artistic.gif | Bin 0 -> 475 bytes images/mood/square/y/bored.gif | Bin 0 -> 404 bytes images/mood/square/y/cold.gif | Bin 0 -> 855 bytes images/mood/square/y/confused.gif | Bin 0 -> 451 bytes images/mood/square/y/content.gif | Bin 0 -> 425 bytes images/mood/square/y/cranky.gif | Bin 0 -> 491 bytes images/mood/square/y/curious.gif | Bin 0 -> 428 bytes images/mood/square/y/embarrassed.gif | Bin 0 -> 691 bytes images/mood/square/y/envious.gif | Bin 0 -> 715 bytes images/mood/square/y/evil.gif | Bin 0 -> 691 bytes images/mood/square/y/full.gif | Bin 0 -> 430 bytes images/mood/square/y/giggly.gif | Bin 0 -> 665 bytes images/mood/square/y/groggy.gif | Bin 0 -> 420 bytes images/mood/square/y/happy.gif | Bin 0 -> 757 bytes images/mood/square/y/hopeful.gif | Bin 0 -> 787 bytes images/mood/square/y/hot.gif | Bin 0 -> 835 bytes images/mood/square/y/hungry.gif | Bin 0 -> 750 bytes images/mood/square/y/hyper.gif | Bin 0 -> 1144 bytes images/mood/square/y/index.html | 71 + images/mood/square/y/loved.gif | Bin 0 -> 464 bytes images/mood/square/y/mellow.gif | Bin 0 -> 712 bytes images/mood/square/y/nerdy.gif | Bin 0 -> 1222 bytes images/mood/square/y/okay.gif | Bin 0 -> 406 bytes images/mood/square/y/sad.gif | Bin 0 -> 737 bytes images/mood/square/y/sick.gif | Bin 0 -> 830 bytes images/mood/square/y/silly.gif | Bin 0 -> 438 bytes images/mood/square/y/sleepy.gif | Bin 0 -> 424 bytes images/mood/square/y/stressed.gif | Bin 0 -> 616 bytes images/mood/square/y/tired.gif | Bin 0 -> 287 bytes images/mood/square/y/worried.gif | Bin 0 -> 513 bytes images/mood/threnody/index.html | 42 + images/mood/threnody/mice/index.html | 78 + images/mood/threnody/mice/m-accomplished.gif | Bin 0 -> 1829 bytes images/mood/threnody/mice/m-angry.gif | Bin 0 -> 1351 bytes images/mood/threnody/mice/m-artistic.gif | Bin 0 -> 1433 bytes images/mood/threnody/mice/m-awake.gif | Bin 0 -> 1488 bytes images/mood/threnody/mice/m-blank.gif | Bin 0 -> 1253 bytes images/mood/threnody/mice/m-calm.gif | Bin 0 -> 1556 bytes images/mood/threnody/mice/m-cold.gif | Bin 0 -> 1337 bytes images/mood/threnody/mice/m-confused.gif | Bin 0 -> 1523 bytes images/mood/threnody/mice/m-curious.gif | Bin 0 -> 1822 bytes images/mood/threnody/mice/m-determined.gif | Bin 0 -> 1323 bytes images/mood/threnody/mice/m-devious.gif | Bin 0 -> 1343 bytes images/mood/threnody/mice/m-drunk.gif | Bin 0 -> 1233 bytes images/mood/threnody/mice/m-embarassed.gif | Bin 0 -> 1331 bytes images/mood/threnody/mice/m-energetic.gif | Bin 0 -> 1907 bytes images/mood/threnody/mice/m-enthralled.gif | Bin 0 -> 1320 bytes images/mood/threnody/mice/m-envious.gif | Bin 0 -> 1854 bytes images/mood/threnody/mice/m-gloomy.gif | Bin 0 -> 1603 bytes images/mood/threnody/mice/m-good.gif | Bin 0 -> 1263 bytes images/mood/threnody/mice/m-happy.gif | Bin 0 -> 1347 bytes images/mood/threnody/mice/m-high.gif | Bin 0 -> 1342 bytes images/mood/threnody/mice/m-horny.gif | Bin 0 -> 1353 bytes images/mood/threnody/mice/m-hot.gif | Bin 0 -> 1657 bytes images/mood/threnody/mice/m-hungry.gif | Bin 0 -> 1343 bytes images/mood/threnody/mice/m-indescribable.gif | Bin 0 -> 1330 bytes images/mood/threnody/mice/m-loved.gif | Bin 0 -> 1421 bytes images/mood/threnody/mice/m-mellow.gif | Bin 0 -> 1311 bytes images/mood/threnody/mice/m-nerdy.gif | Bin 0 -> 1620 bytes images/mood/threnody/mice/m-okay.gif | Bin 0 -> 1306 bytes images/mood/threnody/mice/m-optimistic.gif | Bin 0 -> 1461 bytes images/mood/threnody/mice/m-sad.gif | Bin 0 -> 1337 bytes images/mood/threnody/mice/m-scared.gif | Bin 0 -> 1326 bytes images/mood/threnody/mice/m-shocked.gif | Bin 0 -> 1242 bytes images/mood/threnody/mice/m-sick.gif | Bin 0 -> 1380 bytes images/mood/threnody/mice/m-thoughtful.gif | Bin 0 -> 1440 bytes images/mood/threnody/mice/m-tired.gif | Bin 0 -> 1213 bytes images/mood/threnody/mice/m-working.gif | Bin 0 -> 1356 bytes images/mood/threnody/mice/m-worried.gif | Bin 0 -> 1371 bytes images/mood/xenia/greyblack/aggravated.gif | Bin 0 -> 895 bytes images/mood/xenia/greyblack/amused.gif | Bin 0 -> 900 bytes images/mood/xenia/greyblack/angry.gif | Bin 0 -> 910 bytes images/mood/xenia/greyblack/bitchy.gif | Bin 0 -> 899 bytes images/mood/xenia/greyblack/blank.gif | Bin 0 -> 874 bytes images/mood/xenia/greyblack/cold.gif | Bin 0 -> 952 bytes images/mood/xenia/greyblack/confident.gif | Bin 0 -> 904 bytes images/mood/xenia/greyblack/confused.gif | Bin 0 -> 947 bytes images/mood/xenia/greyblack/crazy.gif | Bin 0 -> 929 bytes images/mood/xenia/greyblack/crushed.gif | Bin 0 -> 906 bytes images/mood/xenia/greyblack/dirty.gif | Bin 0 -> 933 bytes images/mood/xenia/greyblack/drunk.gif | Bin 0 -> 906 bytes images/mood/xenia/greyblack/ecstatic.gif | Bin 0 -> 908 bytes images/mood/xenia/greyblack/embarrassed.gif | Bin 0 -> 914 bytes images/mood/xenia/greyblack/energetic.gif | Bin 0 -> 902 bytes images/mood/xenia/greyblack/enthralled.gif | Bin 0 -> 899 bytes images/mood/xenia/greyblack/flirty.gif | Bin 0 -> 898 bytes images/mood/xenia/greyblack/happy.gif | Bin 0 -> 905 bytes images/mood/xenia/greyblack/high.gif | Bin 0 -> 900 bytes images/mood/xenia/greyblack/horny.gif | Bin 0 -> 943 bytes images/mood/xenia/greyblack/hot.gif | Bin 0 -> 990 bytes images/mood/xenia/greyblack/hungry.gif | Bin 0 -> 1012 bytes images/mood/xenia/greyblack/indescribable.gif | Bin 0 -> 907 bytes images/mood/xenia/greyblack/index.html | 77 + images/mood/xenia/greyblack/indifferent.gif | Bin 0 -> 899 bytes images/mood/xenia/greyblack/loved.gif | Bin 0 -> 954 bytes images/mood/xenia/greyblack/pensive.gif | Bin 0 -> 976 bytes images/mood/xenia/greyblack/rejected.gif | Bin 0 -> 968 bytes images/mood/xenia/greyblack/relaxed.gif | Bin 0 -> 895 bytes images/mood/xenia/greyblack/sad.gif | Bin 0 -> 902 bytes images/mood/xenia/greyblack/scared.gif | Bin 0 -> 918 bytes images/mood/xenia/greyblack/sick.gif | Bin 0 -> 904 bytes images/mood/xenia/greyblack/silly.gif | Bin 0 -> 907 bytes images/mood/xenia/greyblack/surprised.gif | Bin 0 -> 946 bytes images/mood/xenia/greyblack/thirsty.gif | Bin 0 -> 908 bytes images/mood/xenia/greyblack/thoughtful.gif | Bin 0 -> 979 bytes images/mood/xenia/greyblack/tired.gif | Bin 0 -> 938 bytes images/mood/xenia/index.html | 43 + images/mood/xenia/redblack/aggravated.gif | Bin 0 -> 896 bytes images/mood/xenia/redblack/amused.gif | Bin 0 -> 899 bytes images/mood/xenia/redblack/angry.gif | Bin 0 -> 911 bytes images/mood/xenia/redblack/bitchy.gif | Bin 0 -> 896 bytes images/mood/xenia/redblack/blank.gif | Bin 0 -> 874 bytes images/mood/xenia/redblack/cold.gif | Bin 0 -> 953 bytes images/mood/xenia/redblack/confident.gif | Bin 0 -> 900 bytes images/mood/xenia/redblack/confused.gif | Bin 0 -> 956 bytes images/mood/xenia/redblack/crazy.gif | Bin 0 -> 926 bytes images/mood/xenia/redblack/crushed.gif | Bin 0 -> 909 bytes images/mood/xenia/redblack/dirty.gif | Bin 0 -> 929 bytes images/mood/xenia/redblack/drunk.gif | Bin 0 -> 902 bytes images/mood/xenia/redblack/ecstatic.gif | Bin 0 -> 902 bytes images/mood/xenia/redblack/embarrassed.gif | Bin 0 -> 914 bytes images/mood/xenia/redblack/energetic.gif | Bin 0 -> 899 bytes images/mood/xenia/redblack/enthralled.gif | Bin 0 -> 901 bytes images/mood/xenia/redblack/exhausted.gif | Bin 0 -> 936 bytes images/mood/xenia/redblack/flirty.gif | Bin 0 -> 893 bytes images/mood/xenia/redblack/happy.gif | Bin 0 -> 902 bytes images/mood/xenia/redblack/high.gif | Bin 0 -> 901 bytes images/mood/xenia/redblack/horny.gif | Bin 0 -> 943 bytes images/mood/xenia/redblack/hot.gif | Bin 0 -> 985 bytes images/mood/xenia/redblack/hungry.gif | Bin 0 -> 1004 bytes images/mood/xenia/redblack/indescribable.gif | Bin 0 -> 901 bytes images/mood/xenia/redblack/index.html | 77 + images/mood/xenia/redblack/indifferent.gif | Bin 0 -> 899 bytes images/mood/xenia/redblack/loved.gif | Bin 0 -> 944 bytes images/mood/xenia/redblack/pensive.gif | Bin 0 -> 976 bytes images/mood/xenia/redblack/rejected.gif | Bin 0 -> 955 bytes images/mood/xenia/redblack/relaxed.gif | Bin 0 -> 890 bytes images/mood/xenia/redblack/sad.gif | Bin 0 -> 902 bytes images/mood/xenia/redblack/scared.gif | Bin 0 -> 919 bytes images/mood/xenia/redblack/sick.gif | Bin 0 -> 905 bytes images/mood/xenia/redblack/silly.gif | Bin 0 -> 905 bytes images/mood/xenia/redblack/surprised.gif | Bin 0 -> 947 bytes images/mood/xenia/redblack/thirsty.gif | Bin 0 -> 905 bytes images/mood/xenia/redblack/thoughtful.gif | Bin 0 -> 979 bytes livejournal/Inline/README.txt | 7 + livejournal/README.txt | 1 + livejournal/bin/api2html.pl | 93 + livejournal/bin/checkconfig.pl | 195 + livejournal/bin/cvsreport.pl | 15 + livejournal/bin/dbcheck.pl | 339 + livejournal/bin/dbselectd.pl | 392 + livejournal/bin/deleteusers.pl | 157 + livejournal/bin/dumpsql.pl | 167 + livejournal/bin/fingerd.pl | 144 + livejournal/bin/interdoc.pl | 128 + livejournal/bin/jmk | 3 + livejournal/bin/lj-inline.pl | 43 + livejournal/bin/ljblockwatcher.pl | 631 + livejournal/bin/ljmaint.pl | 139 + livejournal/bin/ljsysban.pl | 202 + livejournal/bin/ljubackup.pl | 1149 ++ livejournal/bin/ljumover.pl | 1336 ++ livejournal/bin/logsummarize.pl | 110 + livejournal/bin/mailgated.pl | 536 + livejournal/bin/maint/bday.pl | 86 + livejournal/bin/maint/captcha.pl | 361 + livejournal/bin/maint/clean_caches.pl | 207 + livejournal/bin/maint/generic.pl | 76 + livejournal/bin/maint/stats.pl | 530 + livejournal/bin/maint/statspics.pl | 122 + livejournal/bin/maint/synsuck.pl | 513 + livejournal/bin/maint/taskinfo.txt | 27 + livejournal/bin/moveucluster.pl | 1000 + livejournal/bin/moveuclusterd.pl | 2750 +++ livejournal/bin/qbufferd.pl | 253 + livejournal/bin/statserv.pl | 207 + livejournal/bin/truncate-cluster.pl | 33 + livejournal/bin/upgrading/base-data.sql | 1071 ++ livejournal/bin/upgrading/blobify_userpics.pl | 72 + livejournal/bin/upgrading/compress_cluster.pl | 77 + livejournal/bin/upgrading/d1d2-single.pl | 41 + livejournal/bin/upgrading/d4d5-global.pl | 320 + livejournal/bin/upgrading/d5d6-mkf.pl | 349 + livejournal/bin/upgrading/d6d7-userpics.pl | 352 + livejournal/bin/upgrading/deadphrases.dat | 207 + livejournal/bin/upgrading/en.dat | 4676 +++++ livejournal/bin/upgrading/import-includes.pl | 48 + livejournal/bin/upgrading/make_system.pl | 53 + .../bin/upgrading/migrate-phoneposts.pl | 323 + livejournal/bin/upgrading/migrate-userpics.pl | 318 + livejournal/bin/upgrading/migrate-userprop.pl | 162 + livejournal/bin/upgrading/moods.dat | 107 + livejournal/bin/upgrading/move0cluster.pl | 886 + livejournal/bin/upgrading/pop-clusterprops.pl | 84 + livejournal/bin/upgrading/pop-weekuu.pl | 68 + livejournal/bin/upgrading/s1style-rw.pl | 85 + livejournal/bin/upgrading/s1styles.dat | 7523 ++++++++ livejournal/bin/upgrading/s2layers.dat | 54 + .../upgrading/s2layers/classic/classic.jpg | Bin 0 -> 21054 bytes .../bin/upgrading/s2layers/classic/en.s2 | 16 + .../bin/upgrading/s2layers/classic/layout.s2 | 785 + .../bin/upgrading/s2layers/classic/themes.s2 | 419 + .../s2layers/cleansimple/cleansimple.jpg | Bin 0 -> 20049 bytes .../bin/upgrading/s2layers/cleansimple/en.s2 | 11 + .../upgrading/s2layers/cleansimple/layout.s2 | 932 + .../upgrading/s2layers/cleansimple/themes.s2 | 420 + livejournal/bin/upgrading/s2layers/core1.s2 | 2020 ++ .../digitalmultiplex/digitalmultiplex.jpg | Bin 0 -> 26558 bytes .../upgrading/s2layers/digitalmultiplex/en.s2 | 10 + .../s2layers/digitalmultiplex/layout.s2 | 1379 ++ .../bin/upgrading/s2layers/generator/en.s2 | 17 + .../s2layers/generator/generator.jpg | Bin 0 -> 10141 bytes .../upgrading/s2layers/generator/layout.s2 | 945 + .../upgrading/s2layers/generator/themes.s2 | 369 + .../bin/upgrading/s2layers/haven/haven.png | Bin 0 -> 16042 bytes .../bin/upgrading/s2layers/haven/layout.s2 | 1655 ++ .../bin/upgrading/s2layers/haven/themes.s2 | 392 + .../bin/upgrading/s2layers/i18nc/da1.s2 | 161 + .../bin/upgrading/s2layers/i18nc/de1.s2 | 147 + .../bin/upgrading/s2layers/i18nc/en1.s2 | 9 + .../bin/upgrading/s2layers/i18nc/eo1.s2 | 139 + .../bin/upgrading/s2layers/i18nc/fi1.s2 | 171 + .../bin/upgrading/s2layers/i18nc/fr1.s2 | 144 + .../bin/upgrading/s2layers/i18nc/ja1.s2 | 16 + .../bin/upgrading/s2layers/i18nc/ru1.s2 | 21 + .../bin/upgrading/s2layers/magazine/en.s2 | 14 + .../bin/upgrading/s2layers/magazine/layout.s2 | 699 + .../upgrading/s2layers/magazine/magazine.jpg | Bin 0 -> 17795 bytes .../bin/upgrading/s2layers/magazine/themes.s2 | 459 + .../bin/upgrading/s2layers/notepad/en.s2 | 14 + .../bin/upgrading/s2layers/notepad/layout.s2 | 605 + .../upgrading/s2layers/notepad/notepad.jpg | Bin 0 -> 20276 bytes livejournal/bin/upgrading/s2layers/policy.dat | 27 + .../bin/upgrading/s2layers/punquin/en.s2 | 11 + .../bin/upgrading/s2layers/punquin/layout.s2 | 699 + .../upgrading/s2layers/punquin/punquin.jpg | Bin 0 -> 12215 bytes .../bin/upgrading/s2layers/punquin/themes.s2 | 450 + .../s2layers/sturdygesture/layout.s2 | 850 + .../s2layers/sturdygesture/sturdygesture.jpg | Bin 0 -> 19735 bytes .../s2layers/sturdygesture/themes.s2 | 75 + .../upgrading/s2layers/tabularindent/en.s2 | 14 + .../s2layers/tabularindent/layout.s2 | 741 + .../s2layers/tabularindent/tabularindent.jpg | Bin 0 -> 19223 bytes .../s2layers/tabularindent/themes.s2 | 437 + .../upgrading/s2layers/variableflow/layout.s2 | 967 + .../s2layers/variableflow/preview.jpg | Bin 0 -> 23817 bytes .../bin/upgrading/s2style-wizard-update.pl | 73 + livejournal/bin/upgrading/support-upgrade.pl | 21 + livejournal/bin/upgrading/text.dat | 9 + livejournal/bin/upgrading/texttool.pl | 690 + livejournal/bin/upgrading/truncate_cluster.pl | 32 + .../bin/upgrading/update-db-general.pl | 2578 +++ livejournal/bin/upgrading/update-db.pl | 807 + livejournal/bin/weblog-summarize.pl | 74 + livejournal/bootstrap.pl | 40 + livejournal/cgi-bin/Apache/DebateSuicide.pm | 96 + livejournal/cgi-bin/Apache/LiveJournal.pm | 1508 ++ .../Apache/LiveJournal/Interface/AtomAPI.pm | 610 + .../Apache/LiveJournal/Interface/Blogger.pm | 232 + .../LiveJournal/Interface/FotoBilder.pm | 207 + .../Apache/LiveJournal/Interface/S2.pm | 124 + .../cgi-bin/Apache/LiveJournal/PalImg.pm | 152 + livejournal/cgi-bin/Apache/SendStats.pm | 148 + livejournal/cgi-bin/BlobClient.pm | 51 + livejournal/cgi-bin/BlobClient/Local.pm | 114 + livejournal/cgi-bin/BlobClient/Remote.pm | 164 + livejournal/cgi-bin/LJ/Blob.pm | 150 + livejournal/cgi-bin/LJ/Cache.pm | 291 + livejournal/cgi-bin/LJ/Captcha.pm | 423 + livejournal/cgi-bin/LJ/LDAP.pm | 94 + livejournal/cgi-bin/LJ/MemCache.pm | 111 + livejournal/cgi-bin/LJ/OpenID.pm | 189 + livejournal/cgi-bin/LJ/S2.pm | 2669 +++ livejournal/cgi-bin/LJ/S2/DayPage.pm | 239 + livejournal/cgi-bin/LJ/S2/EntryPage.pm | 377 + livejournal/cgi-bin/LJ/S2/FriendsPage.pm | 441 + livejournal/cgi-bin/LJ/S2/MonthPage.pm | 232 + livejournal/cgi-bin/LJ/S2/RecentPage.pm | 240 + livejournal/cgi-bin/LJ/S2/ReplyPage.pm | 139 + livejournal/cgi-bin/LJ/S2/YearPage.pm | 181 + livejournal/cgi-bin/LJ/SixDegrees.pm | 207 + livejournal/cgi-bin/LJ/SpellCheck.pm | 158 + livejournal/cgi-bin/LJ/TagGenerator.pm | 72 + livejournal/cgi-bin/LJ/TextMessage.pm | 2164 +++ livejournal/cgi-bin/LJ/User.pm | 682 + livejournal/cgi-bin/PaletteModify.pm | 122 + livejournal/cgi-bin/XML/Atom.pm | 75 + livejournal/cgi-bin/XML/Atom/Client.pm | 348 + livejournal/cgi-bin/XML/Atom/Content.pm | 157 + livejournal/cgi-bin/XML/Atom/Entry.pm | 131 + livejournal/cgi-bin/XML/Atom/ErrorHandler.pm | 21 + livejournal/cgi-bin/XML/Atom/Feed.pm | 256 + livejournal/cgi-bin/XML/Atom/Link.pm | 92 + livejournal/cgi-bin/XML/Atom/Person.pm | 120 + livejournal/cgi-bin/XML/Atom/Server.pm | 538 + livejournal/cgi-bin/XML/Atom/Thing.pm | 322 + livejournal/cgi-bin/XML/Atom/Util.pm | 106 + .../cgi-bin/XML/Parser/Encodings/koi8-r.enc | Bin 0 -> 1072 bytes .../cgi-bin/XML/Parser/Encodings/koi8-r.xml | 75 + .../XML/Parser/Encodings/windows-1251.enc | Bin 0 -> 1072 bytes .../XML/Parser/Encodings/windows-1251.xml | 54 + .../XML/Parser/Encodings/windows-1252.enc | Bin 0 -> 1072 bytes .../XML/Parser/Encodings/windows-1252.xml | 26 + .../XML/Parser/Encodings/windows-1255.enc | Bin 0 -> 1072 bytes livejournal/cgi-bin/XML/README.txt | 4 + livejournal/cgi-bin/bml/scheme/bluewhite.look | 263 + livejournal/cgi-bin/bml/scheme/global.look | 365 + livejournal/cgi-bin/bml/scheme/lynx.look | 55 + livejournal/cgi-bin/bml/scheme/opalcat.look | 225 + livejournal/cgi-bin/bml/scheme/woais.look | 198 + livejournal/cgi-bin/cleanhtml.pl | 1021 ++ livejournal/cgi-bin/communitylib.pl | 522 + livejournal/cgi-bin/conban.pl | 146 + livejournal/cgi-bin/confaq.pl | 164 + livejournal/cgi-bin/conmoodtheme.pl | 182 + livejournal/cgi-bin/conshared.pl | 222 + livejournal/cgi-bin/console.pl | 1665 ++ livejournal/cgi-bin/consuspend.pl | 421 + livejournal/cgi-bin/crumbs.pl | 90 + livejournal/cgi-bin/directorylib.pl | 649 + livejournal/cgi-bin/emailcheck.pl | 82 + livejournal/cgi-bin/fbupload.pl | 225 + livejournal/cgi-bin/htmlcontrols.pl | 365 + livejournal/cgi-bin/imageconf.pl | 119 + livejournal/cgi-bin/lj-bml-blocks.pl | 30 + livejournal/cgi-bin/lj-bml-init.pl | 53 + livejournal/cgi-bin/ljcmdbuffer.pl | 322 + livejournal/cgi-bin/ljdb.pl | 55 + livejournal/cgi-bin/ljdefaults.pl | 245 + livejournal/cgi-bin/ljemailgateway.pl | 647 + livejournal/cgi-bin/ljfeed.pl | 556 + livejournal/cgi-bin/ljlang.pl | 416 + livejournal/cgi-bin/ljlib.pl | 9400 ++++++++++ livejournal/cgi-bin/ljlinks.pl | 218 + livejournal/cgi-bin/ljmail.pl | 356 + livejournal/cgi-bin/ljmemories.pl | 543 + livejournal/cgi-bin/ljpoll.pl | 952 + livejournal/cgi-bin/ljprotocol.pl | 3287 ++++ livejournal/cgi-bin/ljtodo.pl | 45 + livejournal/cgi-bin/ljviews.pl | 2361 +++ livejournal/cgi-bin/modperl.pl | 33 + livejournal/cgi-bin/modperl_subs.pl | 137 + livejournal/cgi-bin/parsefeed.pl | 481 + livejournal/cgi-bin/portal.pl | 1141 ++ livejournal/cgi-bin/propparse.pl | 167 + livejournal/cgi-bin/redirect.dat | 24 + livejournal/cgi-bin/statslib.pl | 285 + livejournal/cgi-bin/supportlib.pl | 742 + livejournal/cgi-bin/synlib.pl | 35 + livejournal/cgi-bin/sysban.pl | 175 + livejournal/cgi-bin/taglib.pl | 1185 ++ livejournal/cgi-bin/talklib.pl | 3095 ++++ livejournal/cgi-bin/userpicmagic.txt | 3 + livejournal/cgi-bin/weblib.pl | 1762 ++ livejournal/cvs/multicvs.conf | 55 + .../doc/designnotes/multihomed_userprops.txt | 46 + livejournal/doc/ljconfig.pl.txt | 595 + livejournal/doc/notes/user-statusvis.txt | 36 + livejournal/doc/raw/appendices/gfdl.xml | 450 + livejournal/doc/raw/build/api/api2db.pl | 111 + livejournal/doc/raw/build/api/apidoc.conf | 19 + livejournal/doc/raw/build/caps/cap-local.pl | 15 + livejournal/doc/raw/build/caps/cap2db.pl | 167 + livejournal/doc/raw/build/chunk.xsl | 13 + .../doc/raw/build/console/console2db.pl | 39 + livejournal/doc/raw/build/db/db2ref.xsl | 87 + livejournal/doc/raw/build/db/dbschema.dtd | 23 + livejournal/doc/raw/build/db/dbschema.pl | 125 + livejournal/doc/raw/build/docbooklib.pl | 56 + livejournal/doc/raw/build/generate.pl | 185 + livejournal/doc/raw/build/hooks/hooks2db.pl | 404 + .../doc/raw/build/install/modulelist2db.pl | 112 + .../doc/raw/build/ljconfig/ljconfig2db.pl | 488 + livejournal/doc/raw/build/ljdocs2html.xsl | 141 + livejournal/doc/raw/build/nochunk.xsl | 11 + livejournal/doc/raw/build/priv/priv2db.pl | 53 + .../doc/raw/build/protocol/authinfo.ent.xml | 36 + .../raw/build/protocol/checkfriends.mode.xml | 109 + .../build/protocol/consolecommand.mode.xml | 176 + .../doc/raw/build/protocol/editevent.mode.xml | 184 + .../build/protocol/editfriendgroups.mode.xml | 119 + .../raw/build/protocol/editfriends.mode.xml | 147 + livejournal/doc/raw/build/protocol/flat2db.pl | 64 + .../raw/build/protocol/friendgroups.ent.xml | 21 + .../doc/raw/build/protocol/friendof.mode.xml | 122 + .../raw/build/protocol/friendslist.ent.xml | 29 + .../raw/build/protocol/getchallenge.mode.xml | 81 + .../raw/build/protocol/getdaycounts.mode.xml | 143 + .../doc/raw/build/protocol/getevents.mode.xml | 235 + .../build/protocol/getfriendgroups.mode.xml | 100 + .../raw/build/protocol/getfriends.mode.xml | 156 + .../doc/raw/build/protocol/login.mode.xml | 198 + .../doc/raw/build/protocol/moods.ent.xml | 15 + .../doc/raw/build/protocol/postevent.mode.xml | 178 + .../doc/raw/build/protocol/proplist2db.pl | 35 + .../raw/build/protocol/sessionexpire.mode.xml | 89 + .../build/protocol/sessiongenerate.mode.xml | 108 + .../doc/raw/build/protocol/syncitems.mode.xml | 259 + .../doc/raw/build/protocol/usejournal.ent.xml | 3 + .../raw/build/protocol/usejournals.ent.xml | 7 + .../doc/raw/build/protocol/xml-rpc2db.xsl | 129 + livejournal/doc/raw/build/protocol/xmlrpc.dtd | 41 + livejournal/doc/raw/build/protocol/xmlrpc.xml | 47 + livejournal/doc/raw/build/titlepage.xsl | 66 + livejournal/doc/raw/entities/authors.ent | 23 + livejournal/doc/raw/entities/books.ent | 30 + livejournal/doc/raw/entities/content.ent | 6 + livejournal/doc/raw/entities/entities.xml | 1 + livejournal/doc/raw/entities/lj.book.ent | 61 + livejournal/doc/raw/entities/ljp.book.ent | 68 + livejournal/doc/raw/http-interface.txt | 372 + livejournal/doc/raw/index.xml | 27 + livejournal/doc/raw/int/db/db2ref.xsl | 92 + livejournal/doc/raw/int/db/dbschema.dtd | 35 + livejournal/doc/raw/int/db/dbschema.pl | 126 + livejournal/doc/raw/int/db/schema.xml | 9 + .../doc/raw/int/programming-guidelines.xml | 204 + livejournal/doc/raw/int/protocol/Makefile | 14 + .../doc/raw/int/protocol/authinfo.ent.xml | 16 + .../raw/int/protocol/checkfriends.mode.xml | 42 + .../raw/int/protocol/consolecommand.mode.xml | 61 + .../doc/raw/int/protocol/editevent.mode.xml | 79 + .../int/protocol/editfriendgroups.mode.xml | 45 + .../doc/raw/int/protocol/editfriends.mode.xml | 59 + .../doc/raw/int/protocol/friendgroups.ent.xml | 21 + .../doc/raw/int/protocol/friendof.mode.xml | 29 + .../doc/raw/int/protocol/friendslist.ent.xml | 29 + .../raw/int/protocol/getdaycounts.mode.xml | 33 + .../doc/raw/int/protocol/getevents.mode.xml | 109 + .../raw/int/protocol/getfriendgroups.mode.xml | 22 + .../doc/raw/int/protocol/getfriends.mode.xml | 40 + .../doc/raw/int/protocol/login.mode.xml | 118 + .../doc/raw/int/protocol/moods.ent.xml | 15 + .../doc/raw/int/protocol/postevent.mode.xml | 74 + .../doc/raw/int/protocol/syncitems.mode.xml | 42 + livejournal/doc/raw/int/protocol/testbook.xml | 13 + .../doc/raw/int/protocol/to_docbook.xsl | 108 + .../doc/raw/int/protocol/usejournal.ent.xml | 3 + .../doc/raw/int/protocol/usejournals.ent.xml | 7 + livejournal/doc/raw/int/protocol/xmlrpc.dtd | 37 + livejournal/doc/raw/int/protocol/xmlrpc.xml | 41 + .../doc/raw/lj.book/admin/caps_list.xml | 52 + livejournal/doc/raw/lj.book/admin/console.xml | 50 + .../doc/raw/lj.book/admin/create_users.xml | 20 + .../doc/raw/lj.book/admin/creating_users.xml | 20 + livejournal/doc/raw/lj.book/admin/index.xml | 17 + livejournal/doc/raw/lj.book/admin/privs.xml | 29 + livejournal/doc/raw/lj.book/admin/sysban.xml | 55 + .../doc/raw/lj.book/customize/hooks.xml | 65 + .../doc/raw/lj.book/customize/images.xml | 18 + .../doc/raw/lj.book/customize/index.xml | 40 + .../doc/raw/lj.book/customize/layout.xml | 206 + .../doc/raw/lj.book/customize/limits.xml | 6 + .../doc/raw/lj.book/customize/local_cvs.xml | 82 + .../doc/raw/lj.book/customize/tasks.xml | 12 + .../doc/raw/lj.book/customize/text.xml | 48 + .../doc/raw/lj.book/features/index.xml | 10 + .../doc/raw/lj.book/features/support.xml | 20 + .../doc/raw/lj.book/features/topics.xml | 9 + livejournal/doc/raw/lj.book/index.xml | 27 + .../doc/raw/lj.book/install/apache_setup.xml | 117 + .../doc/raw/lj.book/install/finishing.xml | 52 + .../doc/raw/lj.book/install/general_setup.xml | 128 + livejournal/doc/raw/lj.book/install/index.xml | 35 + .../doc/raw/lj.book/install/ljconfig.caps.xml | 68 + .../raw/lj.book/install/ljconfig.dbinfo.xml | 46 + .../raw/lj.book/install/ljconfig.disabled.xml | 51 + .../raw/lj.book/install/ljconfig.helpurls.xml | 45 + .../doc/raw/lj.book/install/ljconfig.vars.xml | 11 + .../doc/raw/lj.book/install/ljconfig.xml | 34 + .../doc/raw/lj.book/install/mysql_setup.xml | 72 + .../doc/raw/lj.book/install/perl_setup.xml | 77 + livejournal/doc/raw/lj.book/install/reqs.xml | 46 + .../raw/lj.book/install/schedule_tasks.xml | 64 + livejournal/doc/raw/lj.book/intro/goat.xml | 32 + livejournal/doc/raw/lj.book/intro/index.xml | 21 + livejournal/doc/raw/lj.book/intro/story.xml | 26 + livejournal/doc/raw/lj.book/intro/what_is.xml | 24 + livejournal/doc/raw/lj.book/intro/why.xml | 295 + livejournal/doc/raw/lj.book/preface.xml | 71 + livejournal/doc/raw/ljp.book/api/index.xml | 9 + livejournal/doc/raw/ljp.book/bml/core.xml | 36 + livejournal/doc/raw/ljp.book/bml/flags.xml | 89 + livejournal/doc/raw/ljp.book/bml/index.xml | 21 + livejournal/doc/raw/ljp.book/csp/appx.faq.xml | 72 + livejournal/doc/raw/ljp.book/csp/auth.xml | 122 + livejournal/doc/raw/ljp.book/csp/blogger.xml | 36 + livejournal/doc/raw/ljp.book/csp/cs.xml | 151 + .../doc/raw/ljp.book/csp/flat/index.xml | 28 + livejournal/doc/raw/ljp.book/csp/index.xml | 33 + livejournal/doc/raw/ljp.book/csp/proplist.xml | 7 + livejournal/doc/raw/ljp.book/csp/versions.xml | 46 + .../doc/raw/ljp.book/csp/xml-rpc/index.xml | 23 + livejournal/doc/raw/ljp.book/db/index.xml | 22 + livejournal/doc/raw/ljp.book/db/reluser.xml | 49 + livejournal/doc/raw/ljp.book/index.xml | 21 + livejournal/doc/raw/ljp.book/int/bml_faq.xml | 103 + .../doc/raw/ljp.book/int/cap_classes.xml | 8 + livejournal/doc/raw/ljp.book/int/index.xml | 9 + .../doc/raw/ljp.book/prog-guide/database.xml | 74 + .../doc/raw/ljp.book/prog-guide/general.xml | 44 + .../doc/raw/ljp.book/prog-guide/index.xml | 14 + .../doc/raw/ljp.book/prog-guide/patches.xml | 12 + .../raw/ljp.book/prog-guide/performance.xml | 15 + .../raw/ljp.book/prog-guide/perl_style.xml | 15 + .../doc/raw/ljp.book/prog-guide/security.xml | 21 + .../doc/raw/ljp.book/styles/compare.xml | 105 + livejournal/doc/raw/ljp.book/styles/index.xml | 25 + .../doc/raw/ljp.book/styles/s1/design.xml | 10 + .../doc/raw/ljp.book/styles/s1/history.xml | 10 + .../doc/raw/ljp.book/styles/s1/index.xml | 15 + .../doc/raw/ljp.book/styles/s2/design.xml | 10 + .../doc/raw/ljp.book/styles/s2/history.xml | 10 + .../doc/raw/ljp.book/styles/s2/index.xml | 15 + livejournal/doc/raw/memcache-keys.txt | 78 + livejournal/doc/raw/mogile-keys.txt | 4 + livejournal/doc/raw/notes.txt | 25 + livejournal/doc/raw/s1/s1ref2db.pl | 87 + livejournal/doc/raw/s1/vars.dat | 2419 +++ livejournal/doc/raw/s1/views.dat | 55 + livejournal/doc/raw/s2/lj/build.pl | 320 + livejournal/doc/raw/s2/lj/dateformats.xml | 191 + livejournal/doc/raw/s2/lj/entities.xml | 38 + livejournal/doc/raw/s2/lj/faq.xml | 17 + livejournal/doc/raw/s2/lj/index.xml | 32 + livejournal/doc/raw/s2/lj/quickstart.xml | 277 + livejournal/doc/raw/s2/lj/s2onlj.xml | 204 + livejournal/doc/raw/s2/lj/siteapi.xml | 9 + livejournal/doc/todo.txt | 140 + livejournal/htdocs/500-error.html | 62 + livejournal/htdocs/_config.bml | 15 + livejournal/htdocs/accountstatus.bml | 94 + livejournal/htdocs/admin/capedit.bml | 104 + livejournal/htdocs/admin/clusterstatus.bml | 47 + livejournal/htdocs/admin/console/index.bml | 104 + .../htdocs/admin/console/reference.bml | 49 + livejournal/htdocs/admin/dbadmin.bml | 200 + livejournal/htdocs/admin/faq/faqedit.bml | 100 + livejournal/htdocs/admin/faq/faqedit_do.bml | 109 + livejournal/htdocs/admin/faq/index.bml | 67 + livejournal/htdocs/admin/faq/readcat.bml | 63 + livejournal/htdocs/admin/fileedit/index.bml | 150 + livejournal/htdocs/admin/memcache.bml | 170 + livejournal/htdocs/admin/memcache_view.bml | 275 + livejournal/htdocs/admin/mysql_status.bml | 129 + livejournal/htdocs/admin/priv/index.bml | 338 + livejournal/htdocs/admin/recent_comments.bml | 60 + livejournal/htdocs/admin/schema/index.bml | 278 + livejournal/htdocs/admin/spamreports.bml | 276 + livejournal/htdocs/admin/statushistory.bml | 122 + livejournal/htdocs/admin/topics/blank.bml | 1 + livejournal/htdocs/admin/topics/index.bml | 34 + livejournal/htdocs/admin/topics/links.bml | 30 + livejournal/htdocs/admin/topics/screen.html | 17 + livejournal/htdocs/admin/topics/screen_do.bml | 50 + .../admin/topics/screen_instructions.bml | 6 + .../htdocs/admin/topics/screen_links.bml | 106 + livejournal/htdocs/admin/topics/screentop.bml | 87 + .../htdocs/admin/topics/screentop.html | 18 + .../htdocs/admin/topics/screentop_do.bml | 49 + livejournal/htdocs/admin/topics/start.bml | 12 + livejournal/htdocs/admin/userlog.bml | 111 + livejournal/htdocs/allpics.bml | 184 + livejournal/htdocs/approve.bml | 112 + livejournal/htdocs/birthdays.bml | 92 + livejournal/htdocs/captcha/audio.bml | 35 + livejournal/htdocs/captcha/image.bml | 34 + livejournal/htdocs/changepassword.bml | 165 + livejournal/htdocs/community/create.bml | 269 + livejournal/htdocs/community/index.bml | 12 + livejournal/htdocs/community/join.bml | 134 + livejournal/htdocs/community/leave.bml | 68 + livejournal/htdocs/community/manage.bml | 189 + livejournal/htdocs/community/members.bml | 455 + livejournal/htdocs/community/moderate.bml | 425 + livejournal/htdocs/community/pending.bml | 135 + livejournal/htdocs/community/search.bml | 165 + livejournal/htdocs/community/sentinvites.bml | 208 + livejournal/htdocs/community/settings.bml | 252 + livejournal/htdocs/community/transfer.bml | 66 + livejournal/htdocs/create.bml | 620 + .../htdocs/customize/advanced/index.bml | 29 + .../htdocs/customize/advanced/layerbrowse.bml | 308 + .../htdocs/customize/advanced/layeredit.bml | 139 + .../htdocs/customize/advanced/layers.bml | 260 + .../htdocs/customize/advanced/layersource.bml | 78 + .../htdocs/customize/advanced/styles.bml | 465 + livejournal/htdocs/customize/index.bml | 361 + livejournal/htdocs/customize/layer.bml | 438 + livejournal/htdocs/customize/preview.bml | 39 + livejournal/htdocs/customize/themes.bml | 79 + livejournal/htdocs/customize/viewuser.bml | 159 + livejournal/htdocs/delcomment.bml | 174 + livejournal/htdocs/dev/userlist.bml | 85 + livejournal/htdocs/directory.bml | 380 + livejournal/htdocs/directorysearch.bml | 205 + livejournal/htdocs/doc/.placeholder | 3 + livejournal/htdocs/editinfo.bml | 886 + livejournal/htdocs/editjournal.bml | 413 + livejournal/htdocs/editpics.bml | 873 + livejournal/htdocs/edittags.bml | 124 + livejournal/htdocs/export.bml | 109 + livejournal/htdocs/export_comments.bml | 158 + livejournal/htdocs/export_do.bml | 203 + livejournal/htdocs/files/.placeholder | 1 + livejournal/htdocs/friends/add.bml | 209 + livejournal/htdocs/friends/edit.bml | 290 + livejournal/htdocs/friends/editgroups.bml | 425 + livejournal/htdocs/friends/filter.bml | 74 + livejournal/htdocs/friends/graph.bml | 27 + livejournal/htdocs/friends/index.bml | 34 + livejournal/htdocs/go.bml | 60 + livejournal/htdocs/img/addfriend.gif | Bin 0 -> 905 bytes livejournal/htdocs/img/anonymous.gif | Bin 0 -> 229 bytes livejournal/htdocs/img/blackdot.gif | Bin 0 -> 35 bytes livejournal/htdocs/img/bluedot.gif | Bin 0 -> 799 bytes livejournal/htdocs/img/bluewhite/bluefade.jpg | Bin 0 -> 1445 bytes livejournal/htdocs/img/bluewhite/bullet.gif | Bin 0 -> 116 bytes livejournal/htdocs/img/bluewhite/hline.gif | Bin 0 -> 79 bytes livejournal/htdocs/img/bluewhite/home.gif | Bin 0 -> 1300 bytes .../htdocs/img/bluewhite/hr_divdot.gif | Bin 0 -> 166 bytes livejournal/htdocs/img/bluewhite/linetop.gif | Bin 0 -> 117 bytes .../htdocs/img/bluewhite/sidebarfade.gif | Bin 0 -> 284 bytes .../htdocs/img/bluewhite/sidebarfade_line.gif | Bin 0 -> 428 bytes livejournal/htdocs/img/bluewhite/title.gif | Bin 0 -> 2906 bytes livejournal/htdocs/img/bluewhite/vline.gif | Bin 0 -> 115 bytes livejournal/htdocs/img/btn_addfriend.gif | Bin 0 -> 1006 bytes livejournal/htdocs/img/btn_del.gif | Bin 0 -> 907 bytes livejournal/htdocs/img/btn_dn.gif | Bin 0 -> 598 bytes livejournal/htdocs/img/btn_edit.gif | Bin 0 -> 380 bytes livejournal/htdocs/img/btn_edittags.gif | Bin 0 -> 364 bytes livejournal/htdocs/img/btn_freeze.gif | Bin 0 -> 1052 bytes livejournal/htdocs/img/btn_memories.gif | Bin 0 -> 406 bytes livejournal/htdocs/img/btn_next.gif | Bin 0 -> 604 bytes livejournal/htdocs/img/btn_prev.gif | Bin 0 -> 600 bytes livejournal/htdocs/img/btn_scr.gif | Bin 0 -> 138 bytes livejournal/htdocs/img/btn_search.gif | Bin 0 -> 1096 bytes livejournal/htdocs/img/btn_tellfriend.gif | Bin 0 -> 138 bytes livejournal/htdocs/img/btn_todo.gif | Bin 0 -> 151 bytes livejournal/htdocs/img/btn_unfreeze.gif | Bin 0 -> 1087 bytes livejournal/htdocs/img/btn_unscr.gif | Bin 0 -> 120 bytes livejournal/htdocs/img/btn_up.gif | Bin 0 -> 590 bytes livejournal/htdocs/img/captcha/2.png | Bin 0 -> 200 bytes livejournal/htdocs/img/captcha/3.png | Bin 0 -> 217 bytes livejournal/htdocs/img/captcha/4.png | Bin 0 -> 166 bytes livejournal/htdocs/img/captcha/5.png | Bin 0 -> 205 bytes livejournal/htdocs/img/captcha/6.png | Bin 0 -> 211 bytes livejournal/htdocs/img/captcha/7.png | Bin 0 -> 172 bytes livejournal/htdocs/img/captcha/8.png | Bin 0 -> 205 bytes livejournal/htdocs/img/captcha/9.png | Bin 0 -> 215 bytes livejournal/htdocs/img/captcha/a.png | Bin 0 -> 196 bytes livejournal/htdocs/img/captcha/b.png | Bin 0 -> 178 bytes .../htdocs/img/captcha/background1.png | Bin 0 -> 13205 bytes .../htdocs/img/captcha/background2.png | Bin 0 -> 6919 bytes .../htdocs/img/captcha/background3.png | Bin 0 -> 6965 bytes .../htdocs/img/captcha/background4.png | Bin 0 -> 5852 bytes .../htdocs/img/captcha/background5.png | Bin 0 -> 7314 bytes livejournal/htdocs/img/captcha/c.png | Bin 0 -> 176 bytes livejournal/htdocs/img/captcha/d.png | Bin 0 -> 181 bytes livejournal/htdocs/img/captcha/e.png | Bin 0 -> 192 bytes livejournal/htdocs/img/captcha/f.png | Bin 0 -> 136 bytes livejournal/htdocs/img/captcha/g.png | Bin 0 -> 208 bytes livejournal/htdocs/img/captcha/h.png | Bin 0 -> 149 bytes livejournal/htdocs/img/captcha/i.png | Bin 0 -> 95 bytes livejournal/htdocs/img/captcha/j.png | Bin 0 -> 133 bytes livejournal/htdocs/img/captcha/k.png | Bin 0 -> 180 bytes livejournal/htdocs/img/captcha/l.png | Bin 0 -> 91 bytes livejournal/htdocs/img/captcha/m.png | Bin 0 -> 156 bytes livejournal/htdocs/img/captcha/n.png | Bin 0 -> 148 bytes livejournal/htdocs/img/captcha/o.png | Bin 0 -> 179 bytes livejournal/htdocs/img/captcha/p.png | Bin 0 -> 189 bytes livejournal/htdocs/img/captcha/q.png | Bin 0 -> 190 bytes livejournal/htdocs/img/captcha/r.png | Bin 0 -> 130 bytes livejournal/htdocs/img/captcha/s.png | Bin 0 -> 195 bytes livejournal/htdocs/img/captcha/t.png | Bin 0 -> 145 bytes livejournal/htdocs/img/captcha/u.png | Bin 0 -> 148 bytes livejournal/htdocs/img/captcha/v.png | Bin 0 -> 205 bytes livejournal/htdocs/img/captcha/w.png | Bin 0 -> 233 bytes livejournal/htdocs/img/captcha/x.png | Bin 0 -> 193 bytes livejournal/htdocs/img/captcha/y.png | Bin 0 -> 208 bytes livejournal/htdocs/img/captcha/z.png | Bin 0 -> 157 bytes .../htdocs/img/colorpicker/crosshair.gif | Bin 0 -> 71 bytes .../htdocs/img/colorpicker/pointer.gif | Bin 0 -> 52 bytes .../htdocs/img/colorpicker/spectrum.png | Bin 0 -> 9193 bytes livejournal/htdocs/img/community.gif | Bin 0 -> 163 bytes livejournal/htdocs/img/corn_ne.gif | Bin 0 -> 102 bytes livejournal/htdocs/img/corn_nw.gif | Bin 0 -> 102 bytes livejournal/htdocs/img/corn_se.gif | Bin 0 -> 101 bytes livejournal/htdocs/img/corn_sw.gif | Bin 0 -> 100 bytes livejournal/htdocs/img/delcomment.gif | Bin 0 -> 907 bytes livejournal/htdocs/img/dot.gif | Bin 0 -> 807 bytes livejournal/htdocs/img/dot_green.gif | Bin 0 -> 152 bytes livejournal/htdocs/img/dot_red.gif | Bin 0 -> 154 bytes livejournal/htdocs/img/dot_yellow.gif | Bin 0 -> 154 bytes livejournal/htdocs/img/doublearrow.gif | Bin 0 -> 218 bytes livejournal/htdocs/img/globe.gif | Bin 0 -> 1068 bytes livejournal/htdocs/img/grey_gradbg.gif | Bin 0 -> 272 bytes livejournal/htdocs/img/help.gif | Bin 0 -> 558 bytes livejournal/htdocs/img/hourglass.gif | Bin 0 -> 823 bytes livejournal/htdocs/img/icon_private.gif | Bin 0 -> 120 bytes livejournal/htdocs/img/icon_protected.gif | Bin 0 -> 111 bytes livejournal/htdocs/img/imageplaceholder.png | Bin 0 -> 4426 bytes livejournal/htdocs/img/imageplaceholder2.png | Bin 0 -> 1026 bytes livejournal/htdocs/img/imageplaceholder3.png | Bin 0 -> 1280 bytes livejournal/htdocs/img/key.gif | Bin 0 -> 241 bytes livejournal/htdocs/img/knobs.gif | Bin 0 -> 233 bytes livejournal/htdocs/img/leftarrow.gif | Bin 0 -> 208 bytes livejournal/htdocs/img/level1.gif | Bin 0 -> 108 bytes livejournal/htdocs/img/level2.gif | Bin 0 -> 195 bytes livejournal/htdocs/img/level3.gif | Bin 0 -> 198 bytes livejournal/htdocs/img/level4.gif | Bin 0 -> 201 bytes livejournal/htdocs/img/level5.gif | Bin 0 -> 203 bytes livejournal/htdocs/img/memadd.gif | Bin 0 -> 426 bytes livejournal/htdocs/img/message-error.gif | Bin 0 -> 1669 bytes livejournal/htdocs/img/message-warning.gif | Bin 0 -> 2135 bytes livejournal/htdocs/img/nerd_small.jpg | Bin 0 -> 6770 bytes livejournal/htdocs/img/newsinfo.gif | Bin 0 -> 924 bytes livejournal/htdocs/img/opal/bullet.gif | Bin 0 -> 852 bytes livejournal/htdocs/img/opal/home.gif | Bin 0 -> 2033 bytes livejournal/htdocs/img/opal/home.jpg | Bin 0 -> 1597 bytes livejournal/htdocs/img/opal/pencil-line.gif | Bin 0 -> 1664 bytes livejournal/htdocs/img/opal/spiral1.jpg | Bin 0 -> 1793 bytes livejournal/htdocs/img/opal/spiral2.jpg | Bin 0 -> 2764 bytes livejournal/htdocs/img/opal/spiralbg.jpg | Bin 0 -> 2764 bytes livejournal/htdocs/img/openid-badge.gif | Bin 0 -> 227 bytes livejournal/htdocs/img/openid-inputicon.gif | Bin 0 -> 237 bytes livejournal/htdocs/img/openid-profile.gif | Bin 0 -> 211 bytes livejournal/htdocs/img/pencil.gif | Bin 0 -> 562 bytes livejournal/htdocs/img/poll/leftbar.gif | Bin 0 -> 115 bytes livejournal/htdocs/img/poll/mainbar.gif | Bin 0 -> 100 bytes livejournal/htdocs/img/poll/rightbar.gif | Bin 0 -> 117 bytes livejournal/htdocs/img/rightarrow.gif | Bin 0 -> 204 bytes .../htdocs/img/rte/post_button_bold.gif | Bin 0 -> 1256 bytes .../htdocs/img/rte/post_button_copy.gif | Bin 0 -> 767 bytes .../htdocs/img/rte/post_button_cut.gif | Bin 0 -> 832 bytes .../htdocs/img/rte/post_button_hyperlink.gif | Bin 0 -> 1236 bytes .../htdocs/img/rte/post_button_image.gif | Bin 0 -> 1310 bytes .../htdocs/img/rte/post_button_italic.gif | Bin 0 -> 1264 bytes .../htdocs/img/rte/post_button_list.gif | Bin 0 -> 798 bytes .../htdocs/img/rte/post_button_ljcut.gif | Bin 0 -> 834 bytes .../htdocs/img/rte/post_button_ljuser.gif | Bin 0 -> 816 bytes .../img/rte/post_button_numbered_list.gif | Bin 0 -> 788 bytes .../htdocs/img/rte/post_button_paste.gif | Bin 0 -> 766 bytes .../htdocs/img/rte/post_button_redo.gif | Bin 0 -> 817 bytes .../img/rte/post_button_text_larger.gif | Bin 0 -> 813 bytes .../img/rte/post_button_text_normal.gif | Bin 0 -> 818 bytes .../img/rte/post_button_text_smaller.gif | Bin 0 -> 813 bytes .../htdocs/img/rte/post_button_textcolor.gif | Bin 0 -> 1234 bytes .../htdocs/img/rte/post_button_underline.gif | Bin 0 -> 1247 bytes .../htdocs/img/rte/post_button_undo.gif | Bin 0 -> 815 bytes livejournal/htdocs/img/searchingdots.gif | Bin 0 -> 148 bytes .../htdocs/img/style/notepad/bottom-left.jpg | Bin 0 -> 924 bytes .../htdocs/img/style/notepad/bottom-line.jpg | Bin 0 -> 805 bytes .../htdocs/img/style/notepad/bottom-right.jpg | Bin 0 -> 696 bytes livejournal/htdocs/img/style/notepad/hr.gif | Bin 0 -> 1664 bytes .../htdocs/img/style/notepad/middle.jpg | Bin 0 -> 1402 bytes .../htdocs/img/style/notepad/side-left.jpg | Bin 0 -> 1533 bytes .../htdocs/img/style/notepad/side-right.jpg | Bin 0 -> 688 bytes .../htdocs/img/style/notepad/spacer.gif | Bin 0 -> 822 bytes livejournal/htdocs/img/style/notepad/tab.jpg | Bin 0 -> 1344 bytes .../htdocs/img/style/notepad/top-left.jpg | Bin 0 -> 868 bytes .../htdocs/img/style/notepad/top-right.jpg | Bin 0 -> 801 bytes .../htdocs/img/style/webley/bottom.png | Bin 0 -> 379 bytes livejournal/htdocs/img/style/webley/jwc.png | Bin 0 -> 2381 bytes livejournal/htdocs/img/style/webley/jwc0.png | Bin 0 -> 3640 bytes livejournal/htdocs/img/style/webley/jwc1.png | Bin 0 -> 3640 bytes livejournal/htdocs/img/style/webley/jwc10.png | Bin 0 -> 5553 bytes .../htdocs/img/style/webley/jwc100.png | Bin 0 -> 5966 bytes livejournal/htdocs/img/style/webley/jwc11.png | Bin 0 -> 5643 bytes livejournal/htdocs/img/style/webley/jwc12.png | Bin 0 -> 5824 bytes livejournal/htdocs/img/style/webley/jwc13.png | Bin 0 -> 5818 bytes livejournal/htdocs/img/style/webley/jwc14.png | Bin 0 -> 6771 bytes livejournal/htdocs/img/style/webley/jwc15.png | Bin 0 -> 7117 bytes livejournal/htdocs/img/style/webley/jwc16.png | Bin 0 -> 7286 bytes livejournal/htdocs/img/style/webley/jwc17.png | Bin 0 -> 7177 bytes livejournal/htdocs/img/style/webley/jwc18.png | Bin 0 -> 7127 bytes livejournal/htdocs/img/style/webley/jwc19.png | Bin 0 -> 7039 bytes livejournal/htdocs/img/style/webley/jwc2.png | Bin 0 -> 3923 bytes livejournal/htdocs/img/style/webley/jwc20.png | Bin 0 -> 6798 bytes livejournal/htdocs/img/style/webley/jwc21.png | Bin 0 -> 6576 bytes livejournal/htdocs/img/style/webley/jwc22.png | Bin 0 -> 6123 bytes livejournal/htdocs/img/style/webley/jwc23.png | Bin 0 -> 5716 bytes livejournal/htdocs/img/style/webley/jwc24.png | Bin 0 -> 5669 bytes livejournal/htdocs/img/style/webley/jwc25.png | Bin 0 -> 5555 bytes livejournal/htdocs/img/style/webley/jwc26.png | Bin 0 -> 5525 bytes livejournal/htdocs/img/style/webley/jwc27.png | Bin 0 -> 5453 bytes livejournal/htdocs/img/style/webley/jwc28.png | Bin 0 -> 5340 bytes livejournal/htdocs/img/style/webley/jwc29.png | Bin 0 -> 5157 bytes livejournal/htdocs/img/style/webley/jwc3.png | Bin 0 -> 4177 bytes livejournal/htdocs/img/style/webley/jwc30.png | Bin 0 -> 5210 bytes livejournal/htdocs/img/style/webley/jwc31.png | Bin 0 -> 5187 bytes livejournal/htdocs/img/style/webley/jwc32.png | Bin 0 -> 5099 bytes livejournal/htdocs/img/style/webley/jwc33.png | Bin 0 -> 5015 bytes livejournal/htdocs/img/style/webley/jwc34.png | Bin 0 -> 4812 bytes livejournal/htdocs/img/style/webley/jwc35.png | Bin 0 -> 5297 bytes livejournal/htdocs/img/style/webley/jwc36.png | Bin 0 -> 7336 bytes livejournal/htdocs/img/style/webley/jwc37.png | Bin 0 -> 7230 bytes livejournal/htdocs/img/style/webley/jwc38.png | Bin 0 -> 6324 bytes livejournal/htdocs/img/style/webley/jwc39.png | Bin 0 -> 7280 bytes livejournal/htdocs/img/style/webley/jwc4.png | Bin 0 -> 4284 bytes livejournal/htdocs/img/style/webley/jwc40.png | Bin 0 -> 7299 bytes livejournal/htdocs/img/style/webley/jwc41.png | Bin 0 -> 6970 bytes livejournal/htdocs/img/style/webley/jwc42.png | Bin 0 -> 5246 bytes livejournal/htdocs/img/style/webley/jwc43.png | Bin 0 -> 7689 bytes livejournal/htdocs/img/style/webley/jwc44.png | Bin 0 -> 7115 bytes livejournal/htdocs/img/style/webley/jwc45.png | Bin 0 -> 6063 bytes livejournal/htdocs/img/style/webley/jwc46.png | Bin 0 -> 7034 bytes livejournal/htdocs/img/style/webley/jwc47.png | Bin 0 -> 5304 bytes livejournal/htdocs/img/style/webley/jwc48.png | Bin 0 -> 5689 bytes livejournal/htdocs/img/style/webley/jwc49.png | Bin 0 -> 6758 bytes livejournal/htdocs/img/style/webley/jwc5.png | Bin 0 -> 4348 bytes livejournal/htdocs/img/style/webley/jwc50.png | Bin 0 -> 6937 bytes livejournal/htdocs/img/style/webley/jwc51.png | Bin 0 -> 6866 bytes livejournal/htdocs/img/style/webley/jwc52.png | Bin 0 -> 7003 bytes livejournal/htdocs/img/style/webley/jwc53.png | Bin 0 -> 5901 bytes livejournal/htdocs/img/style/webley/jwc54.png | Bin 0 -> 7462 bytes livejournal/htdocs/img/style/webley/jwc55.png | Bin 0 -> 7246 bytes livejournal/htdocs/img/style/webley/jwc56.png | Bin 0 -> 7168 bytes livejournal/htdocs/img/style/webley/jwc57.png | Bin 0 -> 5453 bytes livejournal/htdocs/img/style/webley/jwc58.png | Bin 0 -> 5484 bytes livejournal/htdocs/img/style/webley/jwc59.png | Bin 0 -> 5472 bytes livejournal/htdocs/img/style/webley/jwc6.png | Bin 0 -> 4921 bytes livejournal/htdocs/img/style/webley/jwc60.png | Bin 0 -> 5002 bytes livejournal/htdocs/img/style/webley/jwc61.png | Bin 0 -> 5040 bytes livejournal/htdocs/img/style/webley/jwc62.png | Bin 0 -> 6864 bytes livejournal/htdocs/img/style/webley/jwc63.png | Bin 0 -> 7053 bytes livejournal/htdocs/img/style/webley/jwc64.png | Bin 0 -> 5483 bytes livejournal/htdocs/img/style/webley/jwc65.png | Bin 0 -> 5304 bytes livejournal/htdocs/img/style/webley/jwc66.png | Bin 0 -> 5287 bytes livejournal/htdocs/img/style/webley/jwc67.png | Bin 0 -> 5491 bytes livejournal/htdocs/img/style/webley/jwc68.png | Bin 0 -> 6865 bytes livejournal/htdocs/img/style/webley/jwc69.png | Bin 0 -> 6560 bytes livejournal/htdocs/img/style/webley/jwc7.png | Bin 0 -> 5097 bytes livejournal/htdocs/img/style/webley/jwc70.png | Bin 0 -> 6875 bytes livejournal/htdocs/img/style/webley/jwc71.png | Bin 0 -> 6055 bytes livejournal/htdocs/img/style/webley/jwc72.png | Bin 0 -> 6501 bytes livejournal/htdocs/img/style/webley/jwc73.png | Bin 0 -> 5583 bytes livejournal/htdocs/img/style/webley/jwc74.png | Bin 0 -> 5816 bytes livejournal/htdocs/img/style/webley/jwc75.png | Bin 0 -> 7397 bytes livejournal/htdocs/img/style/webley/jwc76.png | Bin 0 -> 7048 bytes livejournal/htdocs/img/style/webley/jwc77.png | Bin 0 -> 7171 bytes livejournal/htdocs/img/style/webley/jwc78.png | Bin 0 -> 7503 bytes livejournal/htdocs/img/style/webley/jwc79.png | Bin 0 -> 6807 bytes livejournal/htdocs/img/style/webley/jwc8.png | Bin 0 -> 5321 bytes livejournal/htdocs/img/style/webley/jwc80.png | Bin 0 -> 7505 bytes livejournal/htdocs/img/style/webley/jwc81.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc82.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc83.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc84.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc85.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc86.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc87.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc88.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc89.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc9.png | Bin 0 -> 5500 bytes livejournal/htdocs/img/style/webley/jwc90.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc91.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc92.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc93.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc94.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc95.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc96.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc97.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc98.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/jwc99.png | Bin 0 -> 6577 bytes livejournal/htdocs/img/style/webley/left.png | Bin 0 -> 194 bytes livejournal/htdocs/img/style/webley/ll.png | Bin 0 -> 795 bytes livejournal/htdocs/img/style/webley/rb.png | Bin 0 -> 692 bytes livejournal/htdocs/img/style/webley/right.png | Bin 0 -> 191 bytes livejournal/htdocs/img/style/webley/top.png | Bin 0 -> 361 bytes livejournal/htdocs/img/style/webley/ul.png | Bin 0 -> 803 bytes livejournal/htdocs/img/style/webley/ur.png | Bin 0 -> 778 bytes livejournal/htdocs/img/syndicated.gif | Bin 0 -> 891 bytes livejournal/htdocs/img/talk/md01_alien.gif | Bin 0 -> 212 bytes livejournal/htdocs/img/talk/md02_skull.gif | Bin 0 -> 534 bytes livejournal/htdocs/img/talk/md05_sick.gif | Bin 0 -> 173 bytes .../htdocs/img/talk/md06_radioactive.gif | Bin 0 -> 998 bytes livejournal/htdocs/img/talk/md07_cool.gif | Bin 0 -> 909 bytes livejournal/htdocs/img/talk/md08_bulb.gif | Bin 0 -> 909 bytes .../htdocs/img/talk/md09_thumbdown.gif | Bin 0 -> 170 bytes livejournal/htdocs/img/talk/md10_thumbup.gif | Bin 0 -> 169 bytes livejournal/htdocs/img/talk/new.gif | Bin 0 -> 1055 bytes livejournal/htdocs/img/talk/none.gif | Bin 0 -> 134 bytes livejournal/htdocs/img/talk/sm01_smiley.gif | Bin 0 -> 93 bytes livejournal/htdocs/img/talk/sm02_wink.gif | Bin 0 -> 91 bytes livejournal/htdocs/img/talk/sm03_blush.gif | Bin 0 -> 99 bytes livejournal/htdocs/img/talk/sm04_shock.gif | Bin 0 -> 93 bytes livejournal/htdocs/img/talk/sm05_sad.gif | Bin 0 -> 95 bytes livejournal/htdocs/img/talk/sm06_angry.gif | Bin 0 -> 94 bytes livejournal/htdocs/img/talk/sm07_check.gif | Bin 0 -> 165 bytes livejournal/htdocs/img/talk/sm08_star.gif | Bin 0 -> 227 bytes livejournal/htdocs/img/talk/sm09_mail.gif | Bin 0 -> 96 bytes livejournal/htdocs/img/talk/sm10_eyes.gif | Bin 0 -> 247 bytes livejournal/htdocs/img/us_map.gif | Bin 0 -> 11901 bytes livejournal/htdocs/img/userinfo.gif | Bin 0 -> 258 bytes livejournal/htdocs/img/xml.gif | Bin 0 -> 429 bytes livejournal/htdocs/inc/account-codes | 1 + .../htdocs/inc/support-currentproblems | 1 + livejournal/htdocs/inc/support-links | 4 + livejournal/htdocs/inc/validationreminder | 3 + livejournal/htdocs/index.bml | 60 + livejournal/htdocs/interests.bml | 460 + livejournal/htdocs/js/browserdetect.js | 110 + livejournal/htdocs/js/colorpicker.js | 404 + livejournal/htdocs/js/commentmanage.js | 618 + livejournal/htdocs/js/entry.js | 233 + livejournal/htdocs/js/md5.js | 393 + livejournal/htdocs/js/richtext.js | 357 + livejournal/htdocs/js/tags.js | 201 + livejournal/htdocs/js/talkpost.js | 255 + livejournal/htdocs/js/x_core.js | 305 + livejournal/htdocs/js/xbDOM.js | 286 + livejournal/htdocs/js/xbDebug.js | 223 + livejournal/htdocs/js/xbStyle.js | 1349 ++ livejournal/htdocs/login.bml | 419 + livejournal/htdocs/logout.bml | 78 + livejournal/htdocs/lostinfo.bml | 207 + livejournal/htdocs/manage/emailpost.bml | 614 + livejournal/htdocs/manage/index.bml | 199 + livejournal/htdocs/manage/invites.bml | 147 + livejournal/htdocs/manage/links.bml | 68 + livejournal/htdocs/manage/moodthemes.bml | 453 + livejournal/htdocs/manage/pubkey.bml | 94 + livejournal/htdocs/manage/siteopts.bml | 243 + livejournal/htdocs/manage/tags.bml | 267 + livejournal/htdocs/meme.bml | 91 + livejournal/htdocs/misc/ack-devserver.bml | 4 + livejournal/htdocs/misc/interestdata.bml | 40 + livejournal/htdocs/misc/weblogs-change.bml | 36 + livejournal/htdocs/modify.bml | 493 + livejournal/htdocs/moodlist.bml | 269 + livejournal/htdocs/multisearch.bml | 161 + livejournal/htdocs/news.bml | 25 + livejournal/htdocs/openid/approve.bml | 83 + livejournal/htdocs/openid/index.bml | 61 + livejournal/htdocs/openid/login.bml | 89 + livejournal/htdocs/openid/options.bml | 96 + livejournal/htdocs/openid/server.bml | 20 + .../htdocs/palimg/colorpicker/longgrad.gif | Bin 0 -> 3144 bytes livejournal/htdocs/palimg/shadow/b.gif | Bin 0 -> 1149 bytes .../htdocs/palimg/shadow/bottomleft/bl.gif | Bin 0 -> 335 bytes .../htdocs/palimg/shadow/bottomleft/br.gif | Bin 0 -> 543 bytes .../htdocs/palimg/shadow/bottomleft/tl.gif | Bin 0 -> 334 bytes .../htdocs/palimg/shadow/bottomright/bl.gif | Bin 0 -> 518 bytes .../htdocs/palimg/shadow/bottomright/br.gif | Bin 0 -> 311 bytes .../htdocs/palimg/shadow/bottomright/tr.gif | Bin 0 -> 308 bytes livejournal/htdocs/palimg/shadow/l.gif | Bin 0 -> 1310 bytes livejournal/htdocs/palimg/shadow/r.gif | Bin 0 -> 1295 bytes livejournal/htdocs/palimg/shadow/t.gif | Bin 0 -> 1124 bytes .../htdocs/palimg/shadow/topleft/bl.gif | Bin 0 -> 334 bytes .../htdocs/palimg/shadow/topleft/tl.gif | Bin 0 -> 336 bytes .../htdocs/palimg/shadow/topleft/tr.gif | Bin 0 -> 543 bytes .../htdocs/palimg/shadow/topright/br.gif | Bin 0 -> 335 bytes .../htdocs/palimg/shadow/topright/tl.gif | Bin 0 -> 543 bytes .../htdocs/palimg/shadow/topright/tr.gif | Bin 0 -> 336 bytes .../htdocs/palimg/textures/brushed_metal.png | Bin 0 -> 9709 bytes livejournal/htdocs/palimg/textures/burlap.png | Bin 0 -> 6742 bytes .../htdocs/palimg/textures/camouflage.png | Bin 0 -> 11623 bytes livejournal/htdocs/palimg/textures/canvas.png | Bin 0 -> 47766 bytes livejournal/htdocs/palimg/textures/chalk.png | Bin 0 -> 2933 bytes livejournal/htdocs/palimg/textures/cork.png | Bin 0 -> 6260 bytes .../htdocs/palimg/textures/explosion.png | Bin 0 -> 7508 bytes livejournal/htdocs/palimg/textures/fibers.png | Bin 0 -> 16787 bytes livejournal/htdocs/palimg/textures/floral.png | Bin 0 -> 37553 bytes livejournal/htdocs/palimg/textures/ice.png | Bin 0 -> 9027 bytes livejournal/htdocs/palimg/textures/manila.png | Bin 0 -> 12328 bytes livejournal/htdocs/palimg/textures/marble.png | Bin 0 -> 7657 bytes livejournal/htdocs/palimg/textures/paper.png | Bin 0 -> 8438 bytes livejournal/htdocs/palimg/textures/ridge.png | Bin 0 -> 135 bytes livejournal/htdocs/palimg/textures/rough.png | Bin 0 -> 2207 bytes livejournal/htdocs/palimg/textures/stucco.png | Bin 0 -> 10688 bytes .../htdocs/palimg/textures/terracotta.png | Bin 0 -> 12739 bytes livejournal/htdocs/palimg/textures/type.png | Bin 0 -> 10932 bytes livejournal/htdocs/palimg/textures/wavy.png | Bin 0 -> 1496 bytes livejournal/htdocs/palimg/textures/weave.png | Bin 0 -> 4693 bytes livejournal/htdocs/palimg/textures/wood.png | Bin 0 -> 11582 bytes livejournal/htdocs/poll/create.bml | 708 + livejournal/htdocs/poll/index.bml | 117 + livejournal/htdocs/portal/alter.bml | 132 + livejournal/htdocs/portal/box.bml | 21 + livejournal/htdocs/portal/index.bml | 37 + livejournal/htdocs/portal/moz.bml | 22 + livejournal/htdocs/preview/entry.bml | 255 + livejournal/htdocs/protocol.dat | 741 + livejournal/htdocs/pubkey.bml | 55 + livejournal/htdocs/random.bml | 20 + livejournal/htdocs/register.bml | 126 + livejournal/htdocs/robots.txt | 13 + livejournal/htdocs/rte/blank.html | 7 + livejournal/htdocs/rte/palette.html | 126 + livejournal/htdocs/stats.bml | 219 + livejournal/htdocs/stats/.placeholder | 1 + livejournal/htdocs/stats/index.bml | 4 + livejournal/htdocs/styles/browse/index.html | 16 + .../htdocs/styles/browse/instructions.bml | 12 + livejournal/htdocs/styles/browse/links.bml | 55 + livejournal/htdocs/styles/browse/start.bml | 9 + .../htdocs/styles/browse/styleinfo.bml | 45 + livejournal/htdocs/styles/create.bml | 64 + livejournal/htdocs/styles/create_do.bml | 101 + livejournal/htdocs/styles/edit.bml | 66 + livejournal/htdocs/styles/edit_do.bml | 316 + livejournal/htdocs/styles/index.bml | 26 + livejournal/htdocs/styles/tags.css | 217 + livejournal/htdocs/support/act.bml | 169 + livejournal/htdocs/support/actmulti.bml | 82 + livejournal/htdocs/support/append_request.bml | 246 + livejournal/htdocs/support/changenotify.bml | 106 + livejournal/htdocs/support/encodings.bml | 19 + livejournal/htdocs/support/faq.bml | 95 + livejournal/htdocs/support/faqbrowse.bml | 141 + livejournal/htdocs/support/faqpop.bml | 40 + livejournal/htdocs/support/help.bml | 351 + livejournal/htdocs/support/highscores.bml | 107 + livejournal/htdocs/support/history.bml | 117 + livejournal/htdocs/support/index.bml | 57 + livejournal/htdocs/support/see_overrides.bml | 60 + livejournal/htdocs/support/see_request.bml | 720 + livejournal/htdocs/support/stock_answers.bml | 207 + livejournal/htdocs/support/submit.bml | 96 + livejournal/htdocs/support/submit_do.bml | 81 + livejournal/htdocs/syn/index.bml | 241 + livejournal/htdocs/syn/list.bml | 60 + livejournal/htdocs/syn/raw.bml | 17 + livejournal/htdocs/talkmulti.bml | 101 + livejournal/htdocs/talkpost.bml | 319 + livejournal/htdocs/talkpost_do.bml | 232 + livejournal/htdocs/talkread.bml | 608 + livejournal/htdocs/talkscreen.bml | 199 + livejournal/htdocs/todo/index.bml | 293 + livejournal/htdocs/todo/item.bml | 298 + livejournal/htdocs/tools/emailmanage.bml | 116 + livejournal/htdocs/tools/index.bml | 0 livejournal/htdocs/tools/memadd.bml | 335 + livejournal/htdocs/tools/memories.bml | 291 + livejournal/htdocs/tools/recent_comments.bml | 266 + livejournal/htdocs/tools/search.bml | 67 + livejournal/htdocs/tools/sixdegrees.bml | 45 + livejournal/htdocs/tools/tellafriend.bml | 157 + livejournal/htdocs/tools/textmessage.bml | 143 + livejournal/htdocs/translate/diff.bml | 156 + livejournal/htdocs/translate/edit.bml | 16 + livejournal/htdocs/translate/editpage.bml | 318 + .../htdocs/translate/help-severity.bml | 12 + livejournal/htdocs/translate/index.bml | 70 + livejournal/htdocs/translate/search.bml | 77 + livejournal/htdocs/translate/searchform.bml | 61 + livejournal/htdocs/translate/teams.bml | 65 + livejournal/htdocs/translate/welcome.bml | 7 + livejournal/htdocs/unsubscribe.bml | 58 + livejournal/htdocs/update.bml | 402 + livejournal/htdocs/userinfo.bml | 1059 ++ livejournal/htdocs/utf8convert.bml | 731 + livejournal/htdocs/view/index.bml | 235 + livejournal/logs/.placeholder | 1 + livejournal/sites/README | 3 + livejournal/src/historic/README | 4 + livejournal/src/historic/brad-log.cgi | 64 + livejournal/src/jbackup/jbackup.pl | 1029 ++ livejournal/src/utf8.pl | 142 + livejournal/src/xmlrpc-client/README.txt | 4 + livejournal/src/xmlrpc-client/journal.pl | 104 + livejournal/temp/.placeholder | 1 + livejournal/test/MANIFEST | 9 + livejournal/test/MANIFEST.SKIP | 11 + livejournal/test/Makefile.PL | 37 + livejournal/test/bin/ipl | 404 + livejournal/test/examples/example.test.pl | 40 + .../test/examples/moveuclusterd_tests.pl | 130 + livejournal/test/lib/LJ/Object.pm | 232 + livejournal/test/lib/LJ/Test/Assertions.pm | 676 + livejournal/test/lib/LJ/Test/Result.pm | 207 + livejournal/test/lib/LJ/Test/Unit.pm | 295 + livejournal/var/.placeholder | 1 + ljcom/.forward | 1 + ljcom/README-ljcom.txt | 22 + ljcom/bin/checkconfig-local.pl | 64 + ljcom/bin/db | 8 + ljcom/bin/fixtime | 10 + ljcom/bin/hkill | 21 + ljcom/bin/jmk.jar | Bin 0 -> 231020 bytes ljcom/bin/ljcontrib.pl | 114 + ljcom/bin/ljrpc | 164 + ljcom/bin/ljrpcd | 149 + ljcom/bin/ljstatscasterd | 167 + ljcom/bin/machine_config.pl | 662 + ljcom/bin/maint/aliases.pl | 13 + ljcom/bin/maint/clean_caches-local.pl | 14 + ljcom/bin/maint/dirsync.pl | 80 + ljcom/bin/maint/expiring.pl | 259 + ljcom/bin/maint/interests.pl | 84 + ljcom/bin/maint/ljadmin.pl | 215 + ljcom/bin/maint/moods.pl | 10 + ljcom/bin/maint/pay.pl | 713 + ljcom/bin/maint/stats-local.pl | 45 + ljcom/bin/maint/syncweb.pl | 247 + ljcom/bin/maint/taskinfo-local.txt | 56 + ljcom/bin/maint/xfers.pl | 54 + ljcom/bin/maint/xplanet.pl | 24 + ljcom/bin/makemoodindex.pl | 64 + ljcom/bin/mcvsui.pl | 803 + ljcom/bin/misc/fixuu.pl | 38 + ljcom/bin/multideb | 250 + ljcom/bin/mytop.pl | 1019 ++ ljcom/bin/no-emacs.sh | 7 + ljcom/bin/pay-batch | 9 + ljcom/bin/pkill | 20 + ljcom/bin/qkill | 18 + ljcom/bin/release.pl | 76 + ljcom/bin/renameuser.pl | 159 + ljcom/bin/rewrite-balancer.pl | 131 + ljcom/bin/rotate | 38 + ljcom/bin/screenshots.pl | 34 + ljcom/bin/sourceclean.pl | 37 + ljcom/bin/splitlog.pl | 88 + ljcom/bin/upgrading/base-data-local.sql | 31 + ljcom/bin/upgrading/be.dat | 5132 ++++++ ljcom/bin/upgrading/da.dat | 2906 +++ ljcom/bin/upgrading/de.dat | 5145 ++++++ ljcom/bin/upgrading/deadphrases-local.dat | 137 + ljcom/bin/upgrading/en_GB.dat | 691 + ljcom/bin/upgrading/en_LJ.dat | 2103 +++ ljcom/bin/upgrading/eo.dat | 3580 ++++ ljcom/bin/upgrading/es.dat | 3313 ++++ ljcom/bin/upgrading/et.dat | 13 + ljcom/bin/upgrading/fi.dat | 5137 ++++++ ljcom/bin/upgrading/fr.dat | 3983 ++++ ljcom/bin/upgrading/ga.dat | 2170 +++ ljcom/bin/upgrading/gd.dat | 1 + ljcom/bin/upgrading/gr.dat | 2850 +++ ljcom/bin/upgrading/he.dat | 1853 ++ ljcom/bin/upgrading/hi.dat | 1107 ++ ljcom/bin/upgrading/hu.dat | 3473 ++++ ljcom/bin/upgrading/is.dat | 2382 +++ ljcom/bin/upgrading/it.dat | 1047 ++ ljcom/bin/upgrading/ja.dat | 1181 ++ ljcom/bin/upgrading/la.dat | 31 + ljcom/bin/upgrading/lt.dat | 1564 ++ ljcom/bin/upgrading/lv.dat | 865 + ljcom/bin/upgrading/ms.dat | 1114 ++ ljcom/bin/upgrading/nb.dat | 889 + ljcom/bin/upgrading/nl.dat | 2934 +++ ljcom/bin/upgrading/nn.dat | 1 + ljcom/bin/upgrading/pl.dat | 4298 +++++ ljcom/bin/upgrading/pt.dat | 2430 +++ ljcom/bin/upgrading/pt_BR.dat | 36 + ljcom/bin/upgrading/ru.dat | 5240 ++++++ ljcom/bin/upgrading/s2layers-local.dat | 39 + .../bin/upgrading/s2layers/3column/layout.s2 | 1102 ++ .../bin/upgrading/s2layers/3column/themes.s2 | 233 + .../s2layers/anovelconundrum/layout.s2 | 999 + .../s2layers/anovelconundrum/themes.s2 | 179 + ljcom/bin/upgrading/s2layers/boxer/boxer.jpg | Bin 0 -> 12699 bytes ljcom/bin/upgrading/s2layers/boxer/layout.s2 | 1988 ++ ljcom/bin/upgrading/s2layers/boxer/themes.s2 | 225 + .../s2layers/component/component.jpg | Bin 0 -> 9585 bytes .../upgrading/s2layers/component/layout.s2 | 2806 +++ .../upgrading/s2layers/component/themes.s2 | 187 + .../bin/upgrading/s2layers/cuteness/layout.s2 | 1534 ++ .../s2layers/flexiblesquares/layout.s2 | 2076 +++ .../s2layers/flexiblesquares/themes.s2 | 615 + ljcom/bin/upgrading/s2layers/nebula/layout.s2 | 1690 ++ ljcom/bin/upgrading/s2layers/nebula/themes.s2 | 269 + ljcom/bin/upgrading/s2layers/opal/layout.s2 | 1625 ++ ljcom/bin/upgrading/s2layers/opal/opal.jpg | Bin 0 -> 13075 bytes ljcom/bin/upgrading/s2layers/opal/themes.s2 | 105 + .../s2layers/smoothsailing/layout.s2 | 2285 +++ .../s2layers/smoothsailing/themes.s2 | 612 + .../s2layers/tranquilityii/layout.s2 | 1341 ++ .../s2layers/tranquilityii/themes.s2 | 707 + .../upgrading/s2layers/unearthed/layout.s2 | 1556 ++ .../upgrading/s2layers/unearthed/themes.s2 | 118 + ljcom/bin/upgrading/sv.dat | 3248 ++++ ljcom/bin/upgrading/text-local.dat | 221 + ljcom/bin/upgrading/tr.dat | 1742 ++ ljcom/bin/upgrading/uk.dat | 3070 ++++ ljcom/bin/upgrading/update-db-local.pl | 659 + ljcom/bin/upgrading/zh.dat | 1376 ++ ljcom/bin/upgrading/zh_TR.dat | 1 + ljcom/bin/watch-nodes.pl | 91 + ljcom/cgi-bin/bml/scheme/dystopia.look | 623 + ljcom/cgi-bin/bml/scheme/ssl.look | 213 + ljcom/cgi-bin/console-local.pl | 838 + ljcom/cgi-bin/cracklib/README.txt | 10 + ljcom/cgi-bin/crumbs-local.pl | 48 + ljcom/cgi-bin/ljcom.pl | 1604 ++ ljcom/cgi-bin/ljlib-local.pl | 6 + ljcom/cgi-bin/modperl-ssl.pl | 41 + ljcom/cgi-bin/modperl_subs-local.pl | 23 + ljcom/cgi-bin/paylib.pl | 2946 +++ ljcom/cgi-bin/phonepost.pl | 321 + ljcom/cgi-bin/portal-local.pl | 125 + ljcom/cgi-bin/redirect-local.dat | 12 + ljcom/cvs/multicvs-local.conf | 13 + ljcom/doc/raw/build/style.css | 95 + ljcom/doc/raw/local/build-webslave.txt | 219 + ljcom/doc/raw/local/cabinets.txt | 53 + ljcom/doc/raw/local/goals-visualize.pl | 96 + ljcom/doc/raw/local/goals.dat | 47 + ljcom/doc/raw/local/hardware.dtd | 26 + ljcom/doc/raw/local/hardware.xml | 633 + ljcom/doc/raw/memcache-keys-local.txt | 4 + ljcom/htdocs/404-error.html | 65 + ljcom/htdocs/500-error.html | 65 + ljcom/htdocs/_config-local.bml | 4 + ljcom/htdocs/admin/abuse/index.bml | 30 + ljcom/htdocs/admin/abuse/query.bml | 10 + ljcom/htdocs/admin/abuse/send_mail.bml | 12 + ljcom/htdocs/admin/accounts/acctedit.bml | 309 + ljcom/htdocs/admin/accounts/delivernow.bml | 43 + ljcom/htdocs/admin/accounts/depositslip.bml | 88 + ljcom/htdocs/admin/accounts/enterbatch.bml | 115 + ljcom/htdocs/admin/accounts/enternew.bml | 371 + .../htdocs/admin/accounts/fraud_suspects.bml | 66 + ljcom/htdocs/admin/accounts/notes.html | 3 + ljcom/htdocs/admin/accounts/paiddetails.bml | 213 + ljcom/htdocs/admin/accounts/paidsearch.bml | 161 + ljcom/htdocs/admin/accounts/paidsummary.bml | 209 + ljcom/htdocs/admin/accounts/rr.bml | 199 + .../htdocs/admin/accounts/shipping_finish.bml | 82 + .../htdocs/admin/accounts/shipping_labels.bml | 193 + .../admin/accounts/unclaimed_payments.bml | 29 + .../htdocs/admin/accounts/xfer_remaining.bml | 8 + ljcom/htdocs/admin/codetrace.bml | 172 + ljcom/htdocs/admin/feedback/index.bml | 139 + ljcom/htdocs/admin/sendmail/query.bml | 230 + ljcom/htdocs/admin/sendmail/send.bml | 381 + ljcom/htdocs/admin/servers.bml | 151 + ljcom/htdocs/admin/support/index.bml | 70 + ljcom/htdocs/agecheck/altform.bml | 154 + ljcom/htdocs/agecheck/consent.bml | 58 + ljcom/htdocs/agecheck/index.bml | 177 + ljcom/htdocs/banners.bml | 250 + ljcom/htdocs/banners/firebindy1.gif | Bin 0 -> 11433 bytes ljcom/htdocs/bazaar/balance.bml | 110 + ljcom/htdocs/bazaar/details.bml | 97 + ljcom/htdocs/bazaar/gencoupon.bml | 46 + ljcom/htdocs/bazaar/index.bml | 43 + ljcom/htdocs/bazaar/status.bml | 112 + ljcom/htdocs/bazaar/vote.bml | 154 + ljcom/htdocs/betatest.bml | 87 + ljcom/htdocs/bots/index.bml | 28 + ljcom/htdocs/code/cache/html | 75 + ljcom/htdocs/code/cache/index.bml | 25 + ljcom/htdocs/code/clients/win32/index.bml | 18 + ljcom/htdocs/code/index.bml | 38 + ljcom/htdocs/code/mylj/ljsync-0.1.pl.txt | 287 + ljcom/htdocs/code/spellcheck/index.bml | 25 + ljcom/htdocs/code/textmessage/index.bml | 25 + ljcom/htdocs/comment_post.bml | 104 + ljcom/htdocs/comment_recv.bml | 102 + ljcom/htdocs/dev/mailtest.bml | 14 + ljcom/htdocs/dev/s2/2001-02-03.txt | 287 + ljcom/htdocs/dev/s2/goals.bml | 80 + ljcom/htdocs/dev/s2/index.bml | 19 + ljcom/htdocs/developer/embedding.bml | 470 + ljcom/htdocs/developer/exporting.bml | 155 + ljcom/htdocs/developer/index.bml | 52 + ljcom/htdocs/developer/lj-icons.zip | Bin 0 -> 1637 bytes ljcom/htdocs/developer/logo.gif | Bin 0 -> 7326 bytes ljcom/htdocs/developer/modeinfo.bml | 67 + ljcom/htdocs/developer/modelist.bml | 37 + ljcom/htdocs/developer/moods.txt | 105 + ljcom/htdocs/developer/protocol.bml | 154 + ljcom/htdocs/developer/rawmode.bml | 49 + ljcom/htdocs/developer/styles.bml | 51 + ljcom/htdocs/developer/time-problem.txt | 173 + ljcom/htdocs/developer/varinfo.bml | 79 + ljcom/htdocs/developer/varlist.bml | 34 + ljcom/htdocs/developer/versions.bml | 40 + ljcom/htdocs/developer/views.bml | 51 + ljcom/htdocs/developer/winamp.txt | 42 + ljcom/htdocs/doc/find/index.bml | 35 + ljcom/htdocs/doc/guide/index.bml | 11 + ljcom/htdocs/doc/guide/moodicons.bml | 98 + ljcom/htdocs/doc/guide/support.bml | 1676 ++ ljcom/htdocs/doc/index.bml | 35 + ljcom/htdocs/doc/internal/fcgi-acheck.bml | 9 + ljcom/htdocs/doc/pay/diskupgrades.bml | 85 + ljcom/htdocs/doc/tour/index.bml | 118 + ljcom/htdocs/download/index.bml | 452 + ljcom/htdocs/favicon.ico | Bin 0 -> 5222 bytes ljcom/htdocs/feedback/fotobilder.bml | 50 + ljcom/htdocs/feedback/index.bml | 25 + ljcom/htdocs/friends/popwithfriends.bml | 89 + ljcom/htdocs/img/2004_webbywinner.gif | Bin 0 -> 2619 bytes ljcom/htdocs/img/LJbanner1.gif | Bin 0 -> 4627 bytes ljcom/htdocs/img/LJbanner2.gif | Bin 0 -> 5022 bytes ljcom/htdocs/img/LJbanner3.gif | Bin 0 -> 2618 bytes ljcom/htdocs/img/LJbanner4.gif | Bin 0 -> 3001 bytes ljcom/htdocs/img/LJbanner5.gif | Bin 0 -> 2481 bytes ljcom/htdocs/img/LJbanner6.gif | Bin 0 -> 2630 bytes ljcom/htdocs/img/LJbanner7.gif | Bin 0 -> 2545 bytes ljcom/htdocs/img/LJbanner8.gif | Bin 0 -> 1821 bytes ljcom/htdocs/img/LJbanner9.gif | Bin 0 -> 2444 bytes ljcom/htdocs/img/LJbanner_metal.gif | Bin 0 -> 10901 bytes ljcom/htdocs/img/LJbanner_pastel.gif | Bin 0 -> 14923 bytes ljcom/htdocs/img/blue_check.gif | Bin 0 -> 160 bytes ljcom/htdocs/img/deletedphone.gif | Bin 0 -> 332 bytes ljcom/htdocs/img/downarrow.gif | Bin 0 -> 61 bytes ljcom/htdocs/img/download.gif | Bin 0 -> 588 bytes ljcom/htdocs/img/dys/5x5.gif | Bin 0 -> 45 bytes ljcom/htdocs/img/dys/b_blue.gif | Bin 0 -> 64 bytes ljcom/htdocs/img/dys/b_cyan.gif | Bin 0 -> 64 bytes ljcom/htdocs/img/dys/b_purp.gif | Bin 0 -> 64 bytes ljcom/htdocs/img/dys/bg.gif | Bin 0 -> 179 bytes ljcom/htdocs/img/dys/bg2.gif | Bin 0 -> 38891 bytes ljcom/htdocs/img/dys/bg_top.gif | Bin 0 -> 10247 bytes ljcom/htdocs/img/dys/corn_ne.gif | Bin 0 -> 102 bytes ljcom/htdocs/img/dys/corn_nw.gif | Bin 0 -> 102 bytes ljcom/htdocs/img/dys/corn_se.gif | Bin 0 -> 101 bytes ljcom/htdocs/img/dys/corn_sw.gif | Bin 0 -> 100 bytes ljcom/htdocs/img/dys/lg_crnrgif.gif | Bin 0 -> 130 bytes ljcom/htdocs/img/dys/login_but.gif | Bin 0 -> 347 bytes ljcom/htdocs/img/dys/loginbar.gif | Bin 0 -> 217 bytes ljcom/htdocs/img/dys/logo1.gif | Bin 0 -> 2733 bytes ljcom/htdocs/img/dys/logo2.gif | Bin 0 -> 3874 bytes ljcom/htdocs/img/dys/logo3-lang.gif | Bin 0 -> 2136 bytes ljcom/htdocs/img/dys/logo3.gif | Bin 0 -> 1717 bytes ljcom/htdocs/img/goat-hiring.png | Bin 0 -> 9440 bytes ljcom/htdocs/img/goat-hover.gif | Bin 0 -> 2381 bytes ljcom/htdocs/img/goat-irish.gif | Bin 0 -> 2157 bytes ljcom/htdocs/img/goat-lights.gif | Bin 0 -> 8080 bytes ljcom/htdocs/img/goat-newyear.gif | Bin 0 -> 2324 bytes ljcom/htdocs/img/goat-normal.gif | Bin 0 -> 1884 bytes ljcom/htdocs/img/goat-pee.gif | Bin 0 -> 2985 bytes ljcom/htdocs/img/goat-val.gif | Bin 0 -> 5266 bytes ljcom/htdocs/img/goat-xmas.gif | Bin 0 -> 2261 bytes ljcom/htdocs/img/goat.gif | Bin 0 -> 2668 bytes ljcom/htdocs/img/goat.jpg | Bin 0 -> 21823 bytes ljcom/htdocs/img/index.html | 3 + ljcom/htdocs/img/mood-local.tgz | Bin 0 -> 25056 bytes ljcom/htdocs/img/overlap.png | Bin 0 -> 7209 bytes ljcom/htdocs/img/overlap2.png | Bin 0 -> 7038 bytes ljcom/htdocs/img/paypal-buynow.gif | Bin 0 -> 873 bytes ljcom/htdocs/img/phonepost.gif | Bin 0 -> 234 bytes ljcom/htdocs/img/phonepost2.gif | Bin 0 -> 456 bytes ljcom/htdocs/img/schemethumb/dystopia.png | Bin 0 -> 35617 bytes ljcom/htdocs/img/schemethumb/lynx.png | Bin 0 -> 31153 bytes ljcom/htdocs/img/schemethumb/xcolibur.png | Bin 0 -> 24491 bytes ljcom/htdocs/img/style/3column/comments.gif | Bin 0 -> 973 bytes ljcom/htdocs/img/style/3column/editentry.gif | Bin 0 -> 1018 bytes ljcom/htdocs/img/style/3column/edittags.gif | Bin 0 -> 216 bytes .../htdocs/img/style/3column/leavecomment.gif | Bin 0 -> 1034 bytes ljcom/htdocs/img/style/3column/memories.gif | Bin 0 -> 982 bytes ljcom/htdocs/img/style/3column/permalink.gif | Bin 0 -> 973 bytes ljcom/htdocs/img/style/cuteness/bg-pink.gif | Bin 0 -> 12366 bytes .../img/style/cuteness/content-header.gif | Bin 0 -> 6271 bytes ljcom/htdocs/img/style/cuteness/entry-bg.gif | Bin 0 -> 654 bytes .../img/style/cuteness/entry-bottombg.gif | Bin 0 -> 1744 bytes .../img/style/cuteness/face-curious.gif | Bin 0 -> 1180 bytes ljcom/htdocs/img/style/cuteness/face-cute.gif | Bin 0 -> 678 bytes .../htdocs/img/style/cuteness/face-dizzy.gif | Bin 0 -> 1339 bytes ljcom/htdocs/img/style/cuteness/face-doll.gif | Bin 0 -> 1079 bytes .../htdocs/img/style/cuteness/face-happy.gif | Bin 0 -> 1065 bytes .../img/style/cuteness/face-japanese.gif | Bin 0 -> 909 bytes .../htdocs/img/style/cuteness/face-square.gif | Bin 0 -> 704 bytes ljcom/htdocs/img/style/cuteness/footerbg.gif | Bin 0 -> 669 bytes ljcom/htdocs/img/style/cuteness/menubg.gif | Bin 0 -> 1244 bytes ljcom/htdocs/img/style/cuteness/userpicbg.gif | Bin 0 -> 1776 bytes .../img/stylecontest2/3collumn_thumb.jpg | Bin 0 -> 5045 bytes .../stylecontest2/anovelconundrum_thumb.jpg | Bin 0 -> 2698 bytes .../stylecontest2/applyexternally_thumb.jpg | Bin 0 -> 2387 bytes ljcom/htdocs/img/stylecontest2/bob_thumb.jpg | Bin 0 -> 3217 bytes .../img/stylecontest2/colorplay_thumb.jpg | Bin 0 -> 2560 bytes .../img/stylecontest2/deardiary_thumb.jpg | Bin 0 -> 2844 bytes .../htdocs/img/stylecontest2/dinky_thumb.jpg | Bin 0 -> 4352 bytes .../img/stylecontest2/divified_thumb.jpg | Bin 0 -> 16003 bytes .../img/stylecontest2/drifting_thumb.jpg | Bin 0 -> 1893 bytes .../stylecontest2/flexiblesquares_thumb.jpg | Bin 0 -> 18652 bytes .../img/stylecontest2/geometrix_thumb.jpg | Bin 0 -> 2643 bytes .../img/stylecontest2/gradientstrip_thumb.jpg | Bin 0 -> 3902 bytes .../stylecontest2/mobiledevicestyle_thumb.jpg | Bin 0 -> 2265 bytes .../htdocs/img/stylecontest2/nebula_thumb.jpg | Bin 0 -> 7257 bytes .../img/stylecontest2/negatives_thumb.jpg | Bin 0 -> 3313 bytes .../img/stylecontest2/newsworthy_thumb.jpg | Bin 0 -> 3971 bytes .../img/stylecontest2/smoothsailing_thumb.jpg | Bin 0 -> 4037 bytes .../img/stylecontest2/solitude_thumb.jpg | Bin 0 -> 4879 bytes .../img/stylecontest2/statuesque_thumb.jpg | Bin 0 -> 2949 bytes .../superspecialballoons_thumb.jpg | Bin 0 -> 3457 bytes .../img/stylecontest2/texturized_thumb.jpg | Bin 0 -> 2399 bytes .../img/stylecontest2/tranquilityii_thumb.jpg | Bin 0 -> 3392 bytes .../stylecontest2/transmogrified_thumb.jpg | Bin 0 -> 5427 bytes .../img/stylecontest2/widelines_thumb.jpg | Bin 0 -> 2562 bytes ljcom/htdocs/img/tos-logo.png | Bin 0 -> 178622 bytes ljcom/htdocs/img/tour/clients.jpg | Bin 0 -> 72099 bytes ljcom/htdocs/img/tour/clients.png | Bin 0 -> 24923 bytes ljcom/htdocs/img/tour/comms.jpg | Bin 0 -> 35179 bytes ljcom/htdocs/img/tour/create.png | Bin 0 -> 31398 bytes ljcom/htdocs/img/tour/friends.jpg | Bin 0 -> 30903 bytes ljcom/htdocs/img/tour/intro.png | Bin 0 -> 34509 bytes ljcom/htdocs/img/tour/modify.png | Bin 0 -> 14186 bytes ljcom/htdocs/img/tour/profile.png | Bin 0 -> 25485 bytes ljcom/htdocs/img/tour/sitemap.png | Bin 0 -> 22496 bytes ljcom/htdocs/img/tour/support.png | Bin 0 -> 41225 bytes ljcom/htdocs/img/tour/update.png | Bin 0 -> 17928 bytes ljcom/htdocs/img/tshirt_banner.gif | Bin 0 -> 25710 bytes ljcom/htdocs/img/tshirt_goat.gif | Bin 0 -> 32642 bytes ljcom/htdocs/img/tshirt_goat2.gif | Bin 0 -> 20499 bytes .../img/tshirts/thumb/babydoll-black.jpg | Bin 0 -> 5143 bytes .../img/tshirts/thumb/babydoll-grey.jpg | Bin 0 -> 5144 bytes .../img/tshirts/thumb/babydoll-pink.jpg | Bin 0 -> 4878 bytes .../img/tshirts/thumb/babydoll-royalblue.jpg | Bin 0 -> 5638 bytes .../img/tshirts/thumb/babydoll-white.jpg | Bin 0 -> 4766 bytes .../htdocs/img/tshirts/thumb/hooded-black.jpg | Bin 0 -> 4334 bytes .../htdocs/img/tshirts/thumb/hooded-grey.jpg | Bin 0 -> 5167 bytes ljcom/htdocs/img/tshirts/thumb/long-black.jpg | Bin 0 -> 5202 bytes ljcom/htdocs/img/tshirts/thumb/long-grey.jpg | Bin 0 -> 4315 bytes .../img/tshirts/thumb/long-navyblue.jpg | Bin 0 -> 5312 bytes ljcom/htdocs/img/tshirts/thumb/long-white.jpg | Bin 0 -> 3968 bytes ljcom/htdocs/img/tshirts/thumb/polo-black.jpg | Bin 0 -> 4720 bytes ljcom/htdocs/img/tshirts/thumb/polo-grey.jpg | Bin 0 -> 4382 bytes .../img/tshirts/thumb/polo-navyblue.jpg | Bin 0 -> 4596 bytes ljcom/htdocs/img/tshirts/thumb/polo-white.jpg | Bin 0 -> 4154 bytes .../htdocs/img/tshirts/thumb/short-black.jpg | Bin 0 -> 5238 bytes .../img/tshirts/thumb/short-bluedusk.jpg | Bin 0 -> 4999 bytes ljcom/htdocs/img/tshirts/thumb/short-grey.jpg | Bin 0 -> 4873 bytes ljcom/htdocs/img/tshirts/thumb/short-leaf.jpg | Bin 0 -> 4709 bytes .../htdocs/img/tshirts/thumb/short-orange.jpg | Bin 0 -> 4756 bytes .../htdocs/img/tshirts/thumb/short-white.jpg | Bin 0 -> 4654 bytes .../img/tshirts/thumb/twillhat-black.jpg | Bin 0 -> 4915 bytes .../img/tshirts/thumb/twillhat-khaki.jpg | Bin 0 -> 4753 bytes .../img/tshirts/thumb/twillhat-navyblue.jpg | Bin 0 -> 5315 bytes ljcom/htdocs/img/uparrow.gif | Bin 0 -> 61 bytes ljcom/htdocs/img/webbylogo.gif | Bin 0 -> 2881 bytes ljcom/htdocs/inc/account-codes | 47 + ljcom/htdocs/inc/community | 56 + ljcom/htdocs/inc/foobar | 3 + ljcom/htdocs/inc/legal-tos | 553 + ljcom/htdocs/inc/resources-homonyms | 144 + ljcom/htdocs/inc/resources-index | 9 + ljcom/htdocs/inc/spam-warning | 21 + ljcom/htdocs/inc/validationreminder | 9 + ljcom/htdocs/index.bml | 225 + ljcom/htdocs/invite/claim.bml | 119 + ljcom/htdocs/invite/gen.bml | 211 + ljcom/htdocs/invite/index.bml | 80 + ljcom/htdocs/legal/coppa.bml | 3 + ljcom/htdocs/legal/disclaimer.bml | 45 + ljcom/htdocs/legal/dmca.bml | 86 + ljcom/htdocs/legal/index.bml | 36 + ljcom/htdocs/legal/principles.bml | 94 + ljcom/htdocs/legal/privacy.bml | 328 + ljcom/htdocs/legal/tos-mini.bml | 25 + ljcom/htdocs/legal/tos.bml | 67 + ljcom/htdocs/manage/files.bml | 679 + ljcom/htdocs/manage/phonepost.bml | 138 + ljcom/htdocs/misc/clusterlj/index.html | 66 + ljcom/htdocs/misc/clusterlj/ljarch.png | Bin 0 -> 4149 bytes ljcom/htdocs/misc/clusterlj/rev01.html | 201 + ljcom/htdocs/misc/clusterlj/rev02.html | 90 + .../htdocs/misc/clusterlj/usagepie-large.png | Bin 0 -> 11624 bytes ljcom/htdocs/misc/goals.html | 20 + ljcom/htdocs/misc/goals/goals-20020209.gif | Bin 0 -> 150529 bytes ljcom/htdocs/misc/goals/goals-20020209.html | 1 + ljcom/htdocs/misc/goals/goals-20020605.gif | Bin 0 -> 131547 bytes ljcom/htdocs/misc/goals/goals-20020605.html | 1 + ljcom/htdocs/misc/index.html | 1 + ljcom/htdocs/misc/ljlogo/lj.ico | Bin 0 -> 5222 bytes ljcom/htdocs/misc/ljlogo/lj_logo.svg | 108 + ljcom/htdocs/misc/ljlogo/lj_logo_bw.svg | 118 + ljcom/htdocs/misc/pkg-webslave.txt | 25 + ljcom/htdocs/misc/whereami.bml | 79 + ljcom/htdocs/news.bml | 50 + ljcom/htdocs/news/2000-11-23/index.bml | 91 + ljcom/htdocs/news/2000-11-23/now.gif | Bin 0 -> 7108 bytes ljcom/htdocs/news/2000-11-23/proposed.gif | Bin 0 -> 7271 bytes ljcom/htdocs/news/2004-01-qa.bml | 242 + ljcom/htdocs/news/index.bml | 5 + ljcom/htdocs/news/tshirt-poll.bml | 82 + .../paidaccounts/2004_december_promo.bml | 180 + ljcom/htdocs/paidaccounts/apply.bml | 97 + ljcom/htdocs/paidaccounts/buy.bml | 1 + ljcom/htdocs/paidaccounts/friends.bml | 125 + ljcom/htdocs/paidaccounts/index.bml | 50 + ljcom/htdocs/paidaccounts/joincommunity.bml | 55 + ljcom/htdocs/paidaccounts/newacct.bml | 49 + ljcom/htdocs/paidaccounts/pp_notify.bml | 111 + ljcom/htdocs/paidaccounts/status.bml | 53 + ljcom/htdocs/paidaccounts/thankyou.bml | 20 + ljcom/htdocs/paidaccounts/usepaypal.bml | 99 + ljcom/htdocs/paidaccounts/whyextra.bml | 26 + .../htdocs/palimg/anovelconundrum/dingbar.gif | Bin 0 -> 907 bytes ljcom/htdocs/pay/checkout.bml | 69 + ljcom/htdocs/pay/coupons.bml | 68 + ljcom/htdocs/pay/history.bml | 62 + ljcom/htdocs/pay/index.bml | 207 + ljcom/htdocs/pay/modify.bml | 973 + ljcom/htdocs/phonepost/about.bml | 9 + ljcom/htdocs/phonepost/encodings.bml | 29 + ljcom/htdocs/phonepost/index.bml | 56 + ljcom/htdocs/phonepost/numbers.bml | 90 + ljcom/htdocs/phonepost/ogg.bml | 28 + ljcom/htdocs/phonepost/transcribe.bml | 146 + ljcom/htdocs/poll/goatvote.bml | 270 + ljcom/htdocs/press/articles.bml | 24 + ljcom/htdocs/press/index.bml | 30 + ljcom/htdocs/press/staff.bml | 169 + ljcom/htdocs/rename/buy.bml | 5 + ljcom/htdocs/rename/index.bml | 38 + ljcom/htdocs/rename/use.bml | 365 + ljcom/htdocs/resources/homonyms.bml | 11 + ljcom/htdocs/resources/index.bml | 13 + ljcom/htdocs/resources/whowhom.bml | 11 + ljcom/htdocs/singles/index.bml | 34 + ljcom/htdocs/singles/mod.bml | 129 + ljcom/htdocs/singles/search.bml | 216 + ljcom/htdocs/site/about.bml | 150 + ljcom/htdocs/site/banners.bml | 250 + ljcom/htdocs/site/contract.bml | 40 + ljcom/htdocs/site/contributors.bml | 436 + ljcom/htdocs/site/free.bml | 21 + ljcom/htdocs/site/goat.bml | 19 + ljcom/htdocs/site/hardware.bml | 8 + ljcom/htdocs/site/index.bml | 255 + ljcom/htdocs/site/search.bml | 42 + ljcom/htdocs/site/software.bml | 15 + ljcom/htdocs/static/style/syn.css | 70 + ljcom/htdocs/stats/latest-img.bml | 39 + ljcom/htdocs/stats/latest-rss.bml | 111 + ljcom/htdocs/stats/latest.bml | 90 + ljcom/htdocs/stats/weblog-updates-xml.bml | 34 + ljcom/htdocs/store/index.bml | 32 + ljcom/htdocs/store/sizechart.bml | 135 + ljcom/htdocs/store/view.bml | 71 + ljcom/htdocs/suggestions/generator.bml | 155 + ljcom/htdocs/suggestions/index.bml | 21 + ljcom/htdocs/suggestions/prior.bml | 13 + ljcom/htdocs/suggestions/template.bml | 30 + ljcom/htdocs/template.bml | 13 + ljcom/htdocs/tools/xfer_remaining.bml | 181 + ljcom/sites/mrtg/index.cgi | 868 + ljcom/src/ibill-templates/generate.pl | 42 + ljcom/src/ibill-templates/template.html | 67 + ljcom/src/ljcom/myoverlap.pl | 48 + ljcom/src/mod_latency/mod_latency.c | 90 + ljcom/src/phonepost/README | 4 + ljcom/src/phonepost/agi-bin/livejournal | 167 + ljcom/src/phonepost/debian/README | 5 + .../debian/asterisk-deb-20030912.patch | 719 + ljcom/src/phonepost/doc/code | 54 + ljcom/src/phonepost/doc/overview | 35 + ljcom/src/phonepost/doc/script | 33 + ljcom/src/phonepost/etc/extensions.conf | 12 + ljcom/src/rewrite-balancer/README.txt | 19 + ljcom/src/rewrite-balancer/rewrite-balancer.c | 521 + ljcom/src/testfile | 18 + ljcom/ssldocs/_config.bml | 12 + ljcom/ssldocs/img/amex.jpg | Bin 0 -> 46539 bytes ljcom/ssldocs/img/dys/5x5.gif | Bin 0 -> 45 bytes ljcom/ssldocs/img/dys/b_blue.gif | Bin 0 -> 64 bytes ljcom/ssldocs/img/dys/b_cyan.gif | Bin 0 -> 64 bytes ljcom/ssldocs/img/dys/b_purp.gif | Bin 0 -> 64 bytes ljcom/ssldocs/img/dys/bg.gif | Bin 0 -> 179 bytes ljcom/ssldocs/img/dys/bg2.gif | Bin 0 -> 38891 bytes ljcom/ssldocs/img/dys/bg_top.gif | Bin 0 -> 10247 bytes ljcom/ssldocs/img/dys/corn_ne.gif | Bin 0 -> 102 bytes ljcom/ssldocs/img/dys/corn_nw.gif | Bin 0 -> 102 bytes ljcom/ssldocs/img/dys/corn_se.gif | Bin 0 -> 101 bytes ljcom/ssldocs/img/dys/corn_sw.gif | Bin 0 -> 100 bytes ljcom/ssldocs/img/dys/lg_crnrgif.gif | Bin 0 -> 130 bytes ljcom/ssldocs/img/dys/lock.gif | Bin 0 -> 141 bytes ljcom/ssldocs/img/dys/login_but.gif | Bin 0 -> 347 bytes ljcom/ssldocs/img/dys/loginbar.gif | Bin 0 -> 217 bytes ljcom/ssldocs/img/dys/logo1.gif | Bin 0 -> 2733 bytes ljcom/ssldocs/img/dys/logo2.gif | Bin 0 -> 3874 bytes ljcom/ssldocs/img/dys/logo3.gif | Bin 0 -> 1717 bytes ljcom/ssldocs/img/userinfo.gif | Bin 0 -> 258 bytes ljcom/ssldocs/img/visa.jpg | Bin 0 -> 33434 bytes ljcom/ssldocs/img/xc/allbars.gif | Bin 0 -> 231 bytes ljcom/ssldocs/img/xc/basic.css | 224 + ljcom/ssldocs/img/xc/extended.css | 161 + ljcom/ssldocs/img/xc/lock.gif | Bin 0 -> 141 bytes ljcom/ssldocs/img/xc/logocombined.gif | Bin 0 -> 3004 bytes ljcom/ssldocs/img/xc/normal-fonts.css | 4 + ljcom/ssldocs/img/xc/small-fonts.css | 4 + ljcom/ssldocs/index.bml | 35 + ljcom/ssldocs/pay/cc.bml | 194 + ljcom/ssldocs/pay/ccpay.bml | 660 + ljcom/ssldocs/pay/cvv2.bml | 17 + ljcom/ssldocs/pay/index.bml | 3 + local/bin/checkconfig.pl | 206 + local/bin/ljr-tools/clean_cached_comments.pl | 84 + local/bin/ljr-tools/copy_openid_infos.pl | 94 + local/bin/ljr-tools/delete_imported.pl | 113 + local/bin/ljr-tools/import_pics_for_user.pl | 26 + local/bin/ljr-tools/mass_update_journal.pl | 50 + local/bin/ljr-tools/mysql-convert-storable.pl | 53 + local/bin/ljr-tools/rlj2-ljrgate.pl | 128 + local/bin/ljrimport/Simple.pm | 4596 +++++ local/bin/ljrimport/icomments.pl | 647 + local/bin/ljrimport/ijournal.pl | 839 + local/bin/ljrimport/ipics.pl | 533 + local/bin/ljrimport/ljr-defaults.pl | 35 + local/bin/ljrimport/ljr-import.pl | 106 + local/bin/ljrimport/ljr-importdo.pl | 218 + local/bin/ljrimport/ljr-links.pl | 117 + local/bin/ljrimport/ljr-start.sh | 17 + local/bin/ljrimport/ljr-stop.sh | 12 + local/bin/maint/clean_challenges.pl | 21 + local/bin/maint/stats.pl | 548 + local/bin/maint/synsuck.pl | 655 + local/bin/maint/taskinfo.txt | 30 + local/bin/qbufferd.pl | 254 + local/bin/upgrading/en.dat | 5240 ++++++ local/bin/upgrading/en_LJ.dat | 2103 +++ local/bin/upgrading/ru.dat | 5072 +++++ local/bin/upgrading/s2layers-local.dat | 39 + .../bin/upgrading/s2layers/3column/layout.s2 | 1102 ++ .../bin/upgrading/s2layers/3column/themes.s2 | 233 + .../s2layers/anovelconundrum/layout.s2 | 999 + .../s2layers/anovelconundrum/themes.s2 | 179 + local/bin/upgrading/s2layers/boxer/boxer.jpg | Bin 0 -> 12699 bytes local/bin/upgrading/s2layers/boxer/layout.s2 | 1997 ++ local/bin/upgrading/s2layers/boxer/themes.s2 | 225 + .../s2layers/component/component.jpg | Bin 0 -> 9585 bytes .../upgrading/s2layers/component/layout.s2 | 2806 +++ .../upgrading/s2layers/component/themes.s2 | 187 + .../bin/upgrading/s2layers/cuteness/layout.s2 | 1507 ++ .../s2layers/flexiblesquares/layout.s2 | 2076 +++ .../s2layers/flexiblesquares/themes.s2 | 615 + local/bin/upgrading/s2layers/nebula/layout.s2 | 1690 ++ local/bin/upgrading/s2layers/nebula/themes.s2 | 269 + local/bin/upgrading/s2layers/opal/layout.s2 | 1625 ++ local/bin/upgrading/s2layers/opal/opal.jpg | Bin 0 -> 13075 bytes local/bin/upgrading/s2layers/opal/themes.s2 | 105 + .../s2layers/smoothsailing/layout.s2 | 2285 +++ .../s2layers/smoothsailing/themes.s2 | 612 + .../upgrading/s2layers/tranquility2/layout.s2 | 1342 ++ .../s2layers/tranquilityii/layout.s2 | 1341 ++ .../s2layers/tranquilityii/themes.s2 | 707 + .../upgrading/s2layers/unearthed/layout.s2 | 1555 ++ .../upgrading/s2layers/unearthed/themes.s2 | 118 + local/bin/upgrading/sb.dat | 25 + local/bin/upgrading/text-local.dat | 29 + local/bin/upgrading/texttool-overrides | 84 + local/bin/upgrading/texttool.pl | 758 + local/bin/upgrading/uk.dat | 15252 ++++++++++++++++ local/bin/upgrading/update-db-general.pl | 2587 +++ local/cgi-bin/Apache/BML.pm | 2068 +++ local/cgi-bin/Apache/LiveJournal.pm | 1618 ++ local/cgi-bin/CSS/Cleaner.pm | 152 + local/cgi-bin/Cache/Memcached.pm | 1164 ++ local/cgi-bin/Golem.pm | 94 + local/cgi-bin/Golem/dblib.pl | 746 + local/cgi-bin/Golem/loglib.pl | 197 + local/cgi-bin/Golem/netlib.pl | 330 + local/cgi-bin/Golem/proplib.pl | 393 + local/cgi-bin/Golem/textlib.pl | 222 + local/cgi-bin/HTMLCleaner.pm | 207 + local/cgi-bin/LJ/Auth.pm | 124 + local/cgi-bin/LJ/CSS/Cleaner.pm | 21 + local/cgi-bin/LJ/ConvUTF8.pm | 47 + local/cgi-bin/LJ/EmbedModule.pm | 466 + local/cgi-bin/LJ/Entry.pm | 1138 ++ local/cgi-bin/LJ/OpenID.pm | 184 + local/cgi-bin/LJ/S2.pm | 2739 +++ local/cgi-bin/LJ/S2/DayPage.pm | 232 + local/cgi-bin/LJ/S2/EntryPage.pm | 432 + local/cgi-bin/LJ/S2/FriendsPage.pm | 444 + local/cgi-bin/LJ/S2/MonthPage.pm | 224 + local/cgi-bin/LJ/S2/RecentPage.pm | 216 + local/cgi-bin/LJ/S2/ReplyPage.pm | 139 + local/cgi-bin/LJ/S2/YearPage.pm | 181 + local/cgi-bin/LJ/TextMessage.pm | 2164 +++ local/cgi-bin/LJ/User.pm | 3712 ++++ local/cgi-bin/LJR/Distributed.pm | 1458 ++ local/cgi-bin/LJR/GD.pm | 51 + local/cgi-bin/LJR/Gate.pm | 234 + local/cgi-bin/LJR/Viewuser.pm | 241 + local/cgi-bin/LJR/Viewuserstandalone.pm | 210 + local/cgi-bin/LJR/ljpoll-local.pl | 25 + local/cgi-bin/LJR/unicode.pm | 53 + local/cgi-bin/LJR/xmlrpc.pm | 28 + local/cgi-bin/LWPx/ParanoidAgent.pm | 585 + local/cgi-bin/Net/OpenID/Association.pm | 231 + local/cgi-bin/Net/OpenID/Consumer.pm | 952 + local/cgi-bin/bml/scheme/added.variables | 32 + local/cgi-bin/bml/scheme/bluewhite.look | 267 + local/cgi-bin/bml/scheme/dystopia.look | 622 + local/cgi-bin/bml/scheme/global.look | 379 + local/cgi-bin/bml/scheme/global.look.original | 370 + local/cgi-bin/bml/scheme/ljr.look | 374 + local/cgi-bin/bml/scheme/opalcat.look | 225 + local/cgi-bin/bml/scheme/redwhite.look | 267 + local/cgi-bin/bml/scheme/vari | 32 + local/cgi-bin/cleanhtml.pl | 1618 ++ local/cgi-bin/communitylib-local.pl | 75 + local/cgi-bin/communitylib.pl | 529 + local/cgi-bin/console-local.pl | 738 + local/cgi-bin/console.pl | 1647 ++ local/cgi-bin/consuspend.pl | 457 + local/cgi-bin/directorylib.pl | 650 + local/cgi-bin/emailcheck.pl | 90 + local/cgi-bin/ljcom.pl | 1559 ++ local/cgi-bin/ljdefaults.pl | 241 + local/cgi-bin/ljfeed.pl | 567 + local/cgi-bin/ljlang.pl | 418 + local/cgi-bin/ljlib-local.pl | 114 + local/cgi-bin/ljlib.pl | 5088 ++++++ local/cgi-bin/ljmail.pl | 356 + local/cgi-bin/ljpoll.pl | 953 + local/cgi-bin/ljprotocol.pl | 3478 ++++ local/cgi-bin/ljr_readconf.pl | 66 + local/cgi-bin/ljtextutil.pl | 616 + local/cgi-bin/ljviews.pl | 2389 +++ local/cgi-bin/modperl_subs.pl | 144 + local/cgi-bin/parsefeed.pl | 495 + local/cgi-bin/phonepost.pl | 321 + local/cgi-bin/taglib.pl | 1193 ++ local/cgi-bin/talklib.pl | 3306 ++++ local/cgi-bin/weblib.pl | 1870 ++ local/htdocs/.htaccess | 2 + local/htdocs/404-error.html | 9 + local/htdocs/_config-local.bml | 1 + local/htdocs/admin/console/index.bml | 104 + local/htdocs/admin/console/reference.bml | 60 + local/htdocs/admin/ljr/.htaccess | 2 + local/htdocs/admin/ljr/import-queue.bml | 147 + local/htdocs/admin/ljr/import-results.bml | 203 + local/htdocs/admin/memcache-keys.txt | 81 + local/htdocs/admin/memcache.bml | 171 + local/htdocs/admin/memcache_view.bml | 282 + local/htdocs/admin/netstat.bml | 56 + local/htdocs/admin/priv/index.bml | 339 + local/htdocs/bots/index.html | 12 + local/htdocs/changepassword.bml | 178 + local/htdocs/community/create.bml | 315 + local/htdocs/community/join.bml | 148 + local/htdocs/community/pending.bml | 135 + local/htdocs/community/settings.bml | 252 + local/htdocs/create.bml | 639 + .../htdocs/customize/advanced/layerbrowse.bml | 308 + local/htdocs/customize/advanced/layeredit.bml | 139 + local/htdocs/customize/advanced/layers.bml | 260 + local/htdocs/customize/advanced/styles.bml | 465 + local/htdocs/delcomment.bml | 165 + local/htdocs/developer/index.html | 7 + local/htdocs/directory.bml | 380 + local/htdocs/download/index.bml | 70 + local/htdocs/editinfo.bml | 911 + local/htdocs/edittags.bml | 126 + local/htdocs/export_comments.bml | 158 + local/htdocs/export_do.bml | 206 + local/htdocs/favicon-misha.ico | Bin 0 -> 1078 bytes local/htdocs/favicon-petya.ico | Bin 0 -> 5222 bytes local/htdocs/favicon.ico | Bin 0 -> 1078 bytes local/htdocs/friends/pipiskomer.bml | 65 + local/htdocs/friends/popwithfriends.bml | 96 + local/htdocs/go.bml | 67 + local/htdocs/guidelines.html | 97 + local/htdocs/img/blue_check.gif | Bin 0 -> 160 bytes local/htdocs/img/btn_addfriend.gif | Bin 0 -> 288 bytes local/htdocs/img/btn_edit.gif | Bin 0 -> 444 bytes local/htdocs/img/community-lj.gif | Bin 0 -> 163 bytes local/htdocs/img/community-npj.gif | Bin 0 -> 305 bytes local/htdocs/img/community.gif | Bin 0 -> 271 bytes local/htdocs/img/imported-profile.gif | Bin 0 -> 955 bytes .../bitospud/courier/black/accomplished.gif | Bin 0 -> 108 bytes .../mood/bitospud/courier/black/amused.gif | Bin 0 -> 102 bytes .../img/mood/bitospud/courier/black/angry.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/black/anxious.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/black/apathetic.gif | Bin 0 -> 92 bytes .../mood/bitospud/courier/black/artistic.gif | Bin 0 -> 129 bytes .../img/mood/bitospud/courier/black/awake.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/black/bitchy.gif | Bin 0 -> 115 bytes .../img/mood/bitospud/courier/black/blank.gif | Bin 0 -> 89 bytes .../mood/bitospud/courier/black/bouncy.gif | Bin 0 -> 113 bytes .../img/mood/bitospud/courier/black/busy.gif | Bin 0 -> 109 bytes .../img/mood/bitospud/courier/black/calm.gif | Bin 0 -> 104 bytes .../img/mood/bitospud/courier/black/cold.gif | Bin 0 -> 107 bytes .../bitospud/courier/black/complacent.gif | Bin 0 -> 116 bytes .../mood/bitospud/courier/black/confused.gif | Bin 0 -> 109 bytes .../img/mood/bitospud/courier/black/crazy.gif | Bin 0 -> 104 bytes .../mood/bitospud/courier/black/crushed.gif | Bin 0 -> 98 bytes .../mood/bitospud/courier/black/curious.gif | Bin 0 -> 102 bytes .../mood/bitospud/courier/black/cynical.gif | Bin 0 -> 114 bytes .../bitospud/courier/black/determined.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/black/devious.gif | Bin 0 -> 98 bytes .../bitospud/courier/black/disappointed.gif | Bin 0 -> 97 bytes .../mood/bitospud/courier/black/drained.gif | Bin 0 -> 95 bytes .../img/mood/bitospud/courier/black/drunk.gif | Bin 0 -> 108 bytes .../bitospud/courier/black/embarrassed.gif | Bin 0 -> 104 bytes .../mood/bitospud/courier/black/envious.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/black/exanimate.gif | Bin 0 -> 91 bytes .../mood/bitospud/courier/black/flirty.gif | Bin 0 -> 99 bytes .../img/mood/bitospud/courier/black/full.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/black/geeky.gif | Bin 0 -> 104 bytes .../img/mood/bitospud/courier/black/giddy.gif | Bin 0 -> 110 bytes .../mood/bitospud/courier/black/gloomy.gif | Bin 0 -> 107 bytes .../img/mood/bitospud/courier/black/good.gif | Bin 0 -> 108 bytes .../mood/bitospud/courier/black/groggy.gif | Bin 0 -> 113 bytes .../mood/bitospud/courier/black/grumpy.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/black/happy.gif | Bin 0 -> 93 bytes .../img/mood/bitospud/courier/black/horny.gif | Bin 0 -> 108 bytes .../img/mood/bitospud/courier/black/hot.gif | Bin 0 -> 98 bytes .../mood/bitospud/courier/black/hungry.gif | Bin 0 -> 101 bytes .../bitospud/courier/black/indescribable.gif | Bin 0 -> 100 bytes .../img/mood/bitospud/courier/black/loved.gif | Bin 0 -> 105 bytes .../mood/bitospud/courier/black/predatory.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/black/restless.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/black/sad.gif | Bin 0 -> 95 bytes .../mood/bitospud/courier/black/shocked.gif | Bin 0 -> 110 bytes .../img/mood/bitospud/courier/black/sick.gif | Bin 0 -> 101 bytes .../mood/bitospud/courier/black/sleepy.gif | Bin 0 -> 123 bytes .../img/mood/bitospud/courier/black/sore.gif | Bin 0 -> 110 bytes .../bitospud/courier/black/thoughtful.gif | Bin 0 -> 102 bytes .../img/mood/bitospud/courier/black/tired.gif | Bin 0 -> 100 bytes .../mood/bitospud/courier/black/working.gif | Bin 0 -> 130 bytes .../mood/bitospud/courier/black/worried.gif | Bin 0 -> 96 bytes .../bitospud/courier/red/accomplished.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/amused.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/angry.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/anxious.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/apathetic.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/artistic.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/awake.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/bitchy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/blank.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/bouncy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/busy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/calm.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/cold.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/complacent.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/confused.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/crazy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/crushed.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/curious.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/cynical.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/determined.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/devious.gif | Bin 0 -> 951 bytes .../bitospud/courier/red/disappointed.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/drained.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/drunk.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/embarrassed.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/envious.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/exanimate.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/flirty.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/full.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/geeky.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/giddy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/gloomy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/good.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/groggy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/grumpy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/happy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/horny.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/hot.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/hungry.gif | Bin 0 -> 951 bytes .../bitospud/courier/red/indescribable.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/loved.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/predatory.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/restless.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/sad.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/shocked.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/sick.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/sleepy.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/sore.gif | Bin 0 -> 951 bytes .../mood/bitospud/courier/red/thoughtful.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/tired.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/working.gif | Bin 0 -> 951 bytes .../img/mood/bitospud/courier/red/worried.gif | Bin 0 -> 951 bytes .../bitospud/courier/white/accomplished.gif | Bin 0 -> 108 bytes .../mood/bitospud/courier/white/amused.gif | Bin 0 -> 102 bytes .../img/mood/bitospud/courier/white/angry.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/white/anxious.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/white/apathetic.gif | Bin 0 -> 92 bytes .../mood/bitospud/courier/white/artistic.gif | Bin 0 -> 129 bytes .../img/mood/bitospud/courier/white/awake.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/white/bitchy.gif | Bin 0 -> 115 bytes .../img/mood/bitospud/courier/white/blank.gif | Bin 0 -> 89 bytes .../mood/bitospud/courier/white/bouncy.gif | Bin 0 -> 113 bytes .../img/mood/bitospud/courier/white/busy.gif | Bin 0 -> 109 bytes .../img/mood/bitospud/courier/white/calm.gif | Bin 0 -> 104 bytes .../img/mood/bitospud/courier/white/cold.gif | Bin 0 -> 107 bytes .../bitospud/courier/white/complacent.gif | Bin 0 -> 116 bytes .../mood/bitospud/courier/white/confused.gif | Bin 0 -> 109 bytes .../img/mood/bitospud/courier/white/crazy.gif | Bin 0 -> 104 bytes .../mood/bitospud/courier/white/crushed.gif | Bin 0 -> 98 bytes .../mood/bitospud/courier/white/curious.gif | Bin 0 -> 102 bytes .../mood/bitospud/courier/white/cynical.gif | Bin 0 -> 114 bytes .../bitospud/courier/white/determined.gif | Bin 0 -> 107 bytes .../mood/bitospud/courier/white/devious.gif | Bin 0 -> 98 bytes .../bitospud/courier/white/disappointed.gif | Bin 0 -> 97 bytes .../mood/bitospud/courier/white/drained.gif | Bin 0 -> 95 bytes .../img/mood/bitospud/courier/white/drunk.gif | Bin 0 -> 108 bytes .../bitospud/courier/white/embarrassed.gif | Bin 0 -> 104 bytes .../mood/bitospud/courier/white/envious.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/white/exanimate.gif | Bin 0 -> 91 bytes .../mood/bitospud/courier/white/flirty.gif | Bin 0 -> 99 bytes .../img/mood/bitospud/courier/white/full.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/white/geeky.gif | Bin 0 -> 104 bytes .../img/mood/bitospud/courier/white/giddy.gif | Bin 0 -> 110 bytes .../mood/bitospud/courier/white/gloomy.gif | Bin 0 -> 107 bytes .../img/mood/bitospud/courier/white/good.gif | Bin 0 -> 108 bytes .../mood/bitospud/courier/white/groggy.gif | Bin 0 -> 113 bytes .../mood/bitospud/courier/white/grumpy.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/white/happy.gif | Bin 0 -> 93 bytes .../img/mood/bitospud/courier/white/horny.gif | Bin 0 -> 108 bytes .../img/mood/bitospud/courier/white/hot.gif | Bin 0 -> 98 bytes .../mood/bitospud/courier/white/hungry.gif | Bin 0 -> 101 bytes .../bitospud/courier/white/indescribable.gif | Bin 0 -> 100 bytes .../img/mood/bitospud/courier/white/loved.gif | Bin 0 -> 105 bytes .../mood/bitospud/courier/white/predatory.gif | Bin 0 -> 109 bytes .../mood/bitospud/courier/white/restless.gif | Bin 0 -> 112 bytes .../img/mood/bitospud/courier/white/sad.gif | Bin 0 -> 95 bytes .../mood/bitospud/courier/white/shocked.gif | Bin 0 -> 110 bytes .../img/mood/bitospud/courier/white/sick.gif | Bin 0 -> 101 bytes .../mood/bitospud/courier/white/sleepy.gif | Bin 0 -> 123 bytes .../img/mood/bitospud/courier/white/sore.gif | Bin 0 -> 110 bytes .../bitospud/courier/white/thoughtful.gif | Bin 0 -> 102 bytes .../img/mood/bitospud/courier/white/tired.gif | Bin 0 -> 100 bytes .../mood/bitospud/courier/white/working.gif | Bin 0 -> 130 bytes .../mood/bitospud/courier/white/worried.gif | Bin 0 -> 96 bytes .../img/mood/charitycam/blackbox/angry.gif | Bin 0 -> 363 bytes .../img/mood/charitycam/blackbox/artistic.gif | Bin 0 -> 569 bytes .../img/mood/charitycam/blackbox/bouncy.gif | Bin 0 -> 235 bytes .../img/mood/charitycam/blackbox/cold.gif | Bin 0 -> 362 bytes .../img/mood/charitycam/blackbox/crazy.gif | Bin 0 -> 342 bytes .../img/mood/charitycam/blackbox/curious.gif | Bin 0 -> 260 bytes .../mood/charitycam/blackbox/determined.gif | Bin 0 -> 215 bytes .../img/mood/charitycam/blackbox/devilish.gif | Bin 0 -> 243 bytes .../img/mood/charitycam/blackbox/dirty.gif | Bin 0 -> 324 bytes .../img/mood/charitycam/blackbox/drunk.gif | Bin 0 -> 317 bytes .../mood/charitycam/blackbox/embarrassed.gif | Bin 0 -> 254 bytes .../img/mood/charitycam/blackbox/envy.gif | Bin 0 -> 238 bytes .../img/mood/charitycam/blackbox/gloomy.gif | Bin 0 -> 284 bytes .../img/mood/charitycam/blackbox/green.gif | Bin 0 -> 303 bytes .../img/mood/charitycam/blackbox/happy.gif | Bin 0 -> 227 bytes .../img/mood/charitycam/blackbox/hot.gif | Bin 0 -> 889 bytes .../img/mood/charitycam/blackbox/hungry.gif | Bin 0 -> 457 bytes .../img/mood/charitycam/blackbox/loved.gif | Bin 0 -> 273 bytes .../img/mood/charitycam/blackbox/nerdy.gif | Bin 0 -> 225 bytes .../img/mood/charitycam/blackbox/okay.gif | Bin 0 -> 202 bytes .../img/mood/charitycam/blackbox/peaceful.gif | Bin 0 -> 245 bytes .../img/mood/charitycam/blackbox/relaxed.gif | Bin 0 -> 188 bytes .../img/mood/charitycam/blackbox/sad.gif | Bin 0 -> 257 bytes .../img/mood/charitycam/blackbox/scared.gif | Bin 0 -> 239 bytes .../img/mood/charitycam/blackbox/sore.gif | Bin 0 -> 250 bytes .../img/mood/charitycam/blackbox/suprised.gif | Bin 0 -> 472 bytes .../img/mood/charitycam/blackbox/thirsty.gif | Bin 0 -> 362 bytes .../mood/charitycam/blackbox/thoughtful.gif | Bin 0 -> 287 bytes .../img/mood/charitycam/blackbox/tired.gif | Bin 0 -> 251 bytes .../img/mood/charitycam/blackbox/working.gif | Bin 0 -> 268 bytes .../img/mood/charitycam/goth_boy/angry.gif | Bin 0 -> 1106 bytes .../img/mood/charitycam/goth_boy/artistic.gif | Bin 0 -> 547 bytes .../img/mood/charitycam/goth_boy/awake.gif | Bin 0 -> 830 bytes .../img/mood/charitycam/goth_boy/bouncy.gif | Bin 0 -> 755 bytes .../img/mood/charitycam/goth_boy/cold.gif | Bin 0 -> 683 bytes .../img/mood/charitycam/goth_boy/confused.gif | Bin 0 -> 1514 bytes .../mood/charitycam/goth_boy/determined.gif | Bin 0 -> 1018 bytes .../img/mood/charitycam/goth_boy/devlish.gif | Bin 0 -> 1016 bytes .../img/mood/charitycam/goth_boy/dirty.gif | Bin 0 -> 1110 bytes .../img/mood/charitycam/goth_boy/drunk.gif | Bin 0 -> 1117 bytes .../mood/charitycam/goth_boy/embarrased.gif | Bin 0 -> 409 bytes .../img/mood/charitycam/goth_boy/envious.gif | Bin 0 -> 1054 bytes .../img/mood/charitycam/goth_boy/full.gif | Bin 0 -> 1150 bytes .../img/mood/charitycam/goth_boy/gloomy.gif | Bin 0 -> 1318 bytes .../img/mood/charitycam/goth_boy/happy.gif | Bin 0 -> 1007 bytes .../img/mood/charitycam/goth_boy/high.gif | Bin 0 -> 1106 bytes .../img/mood/charitycam/goth_boy/hot.gif | Bin 0 -> 609 bytes .../img/mood/charitycam/goth_boy/hungry.gif | Bin 0 -> 322 bytes .../img/mood/charitycam/goth_boy/loved.gif | Bin 0 -> 625 bytes .../img/mood/charitycam/goth_boy/nerdy.gif | Bin 0 -> 1060 bytes .../img/mood/charitycam/goth_boy/okay.gif | Bin 0 -> 1010 bytes .../img/mood/charitycam/goth_boy/sad.gif | Bin 0 -> 1859 bytes .../img/mood/charitycam/goth_boy/scared.gif | Bin 0 -> 499 bytes .../img/mood/charitycam/goth_boy/shocked.gif | Bin 0 -> 1183 bytes .../img/mood/charitycam/goth_boy/sick.gif | Bin 0 -> 1680 bytes .../img/mood/charitycam/goth_boy/silly.gif | Bin 0 -> 1569 bytes .../img/mood/charitycam/goth_boy/sleepy.gif | Bin 0 -> 1045 bytes .../img/mood/charitycam/goth_boy/stressed.gif | Bin 0 -> 692 bytes .../img/mood/charitycam/goth_boy/thirsty.gif | Bin 0 -> 1241 bytes .../mood/charitycam/goth_boy/thoughtful.gif | Bin 0 -> 1393 bytes .../img/mood/charitycam/goth_boy/tired.gif | Bin 0 -> 1014 bytes .../img/mood/charitycam/goth_boy/working.gif | Bin 0 -> 460 bytes .../img/mood/charitycam/goth_girl/angry.gif | Bin 0 -> 771 bytes .../mood/charitycam/goth_girl/artistic.gif | Bin 0 -> 751 bytes .../img/mood/charitycam/goth_girl/cold.gif | Bin 0 -> 2172 bytes .../img/mood/charitycam/goth_girl/curious.gif | Bin 0 -> 806 bytes .../mood/charitycam/goth_girl/determined.gif | Bin 0 -> 815 bytes .../img/mood/charitycam/goth_girl/devious.gif | Bin 0 -> 437 bytes .../img/mood/charitycam/goth_girl/dirty.gif | Bin 0 -> 1430 bytes .../img/mood/charitycam/goth_girl/drunk.gif | Bin 0 -> 723 bytes .../img/mood/charitycam/goth_girl/envious.gif | Bin 0 -> 1044 bytes .../img/mood/charitycam/goth_girl/full.gif | Bin 0 -> 646 bytes .../img/mood/charitycam/goth_girl/gloomy.gif | Bin 0 -> 523 bytes .../img/mood/charitycam/goth_girl/happy.gif | Bin 0 -> 656 bytes .../img/mood/charitycam/goth_girl/high.gif | Bin 0 -> 1724 bytes .../img/mood/charitycam/goth_girl/hot.gif | Bin 0 -> 1929 bytes .../img/mood/charitycam/goth_girl/hungry.gif | Bin 0 -> 464 bytes .../img/mood/charitycam/goth_girl/loved.gif | Bin 0 -> 698 bytes .../img/mood/charitycam/goth_girl/nerdy.gif | Bin 0 -> 910 bytes .../img/mood/charitycam/goth_girl/okay.gif | Bin 0 -> 638 bytes .../img/mood/charitycam/goth_girl/sad.gif | Bin 0 -> 763 bytes .../img/mood/charitycam/goth_girl/scared.gif | Bin 0 -> 721 bytes .../img/mood/charitycam/goth_girl/sick.gif | Bin 0 -> 2383 bytes .../img/mood/charitycam/goth_girl/silly.gif | Bin 0 -> 1672 bytes .../img/mood/charitycam/goth_girl/sleepy.gif | Bin 0 -> 651 bytes .../mood/charitycam/goth_girl/stressed.gif | Bin 0 -> 734 bytes .../mood/charitycam/goth_girl/surprised.gif | Bin 0 -> 588 bytes .../mood/charitycam/goth_girl/thoughtful.gif | Bin 0 -> 967 bytes .../img/mood/charitycam/goth_girl/working.gif | Bin 0 -> 572 bytes local/htdocs/img/mood/classic/angry.gif | Bin 0 -> 94 bytes local/htdocs/img/mood/classic/blah.gif | Bin 0 -> 92 bytes local/htdocs/img/mood/classic/blush.gif | Bin 0 -> 99 bytes local/htdocs/img/mood/classic/confused.gif | Bin 0 -> 112 bytes local/htdocs/img/mood/classic/devious.gif | Bin 0 -> 913 bytes local/htdocs/img/mood/classic/drunk.gif | Bin 0 -> 114 bytes local/htdocs/img/mood/classic/energetic.gif | Bin 0 -> 313 bytes local/htdocs/img/mood/classic/sad.gif | Bin 0 -> 95 bytes local/htdocs/img/mood/classic/shock.gif | Bin 0 -> 93 bytes local/htdocs/img/mood/classic/sick.gif | Bin 0 -> 94 bytes local/htdocs/img/mood/classic/smile.gif | Bin 0 -> 93 bytes local/htdocs/img/mood/classic/thinking.gif | Bin 0 -> 129 bytes local/htdocs/img/mood/classic/tired.gif | Bin 0 -> 108 bytes local/htdocs/img/mood/classic/wink.gif | Bin 0 -> 91 bytes .../htdocs/img/mood/growf/dwaggins/angry.gif | Bin 0 -> 997 bytes .../img/mood/growf/dwaggins/annoyed.gif | Bin 0 -> 976 bytes local/htdocs/img/mood/growf/dwaggins/blah.gif | Bin 0 -> 977 bytes .../htdocs/img/mood/growf/dwaggins/blank.gif | Bin 0 -> 975 bytes .../htdocs/img/mood/growf/dwaggins/blush.gif | Bin 0 -> 998 bytes .../htdocs/img/mood/growf/dwaggins/bouncy.gif | Bin 0 -> 1290 bytes .../img/mood/growf/dwaggins/confused.gif | Bin 0 -> 1016 bytes local/htdocs/img/mood/growf/dwaggins/cool.gif | Bin 0 -> 987 bytes .../img/mood/growf/dwaggins/determined.gif | Bin 0 -> 975 bytes .../img/mood/growf/dwaggins/devious.gif | Bin 0 -> 985 bytes .../htdocs/img/mood/growf/dwaggins/dirty.gif | Bin 0 -> 977 bytes .../htdocs/img/mood/growf/dwaggins/geeky.gif | Bin 0 -> 1020 bytes local/htdocs/img/mood/growf/dwaggins/high.gif | Bin 0 -> 998 bytes local/htdocs/img/mood/growf/dwaggins/hot.gif | Bin 0 -> 1003 bytes .../htdocs/img/mood/growf/dwaggins/hyper.gif | Bin 0 -> 993 bytes local/htdocs/img/mood/growf/dwaggins/idea.gif | Bin 0 -> 1026 bytes local/htdocs/img/mood/growf/dwaggins/sad.gif | Bin 0 -> 977 bytes .../img/mood/growf/dwaggins/shocked.gif | Bin 0 -> 997 bytes local/htdocs/img/mood/growf/dwaggins/sick.gif | Bin 0 -> 979 bytes .../htdocs/img/mood/growf/dwaggins/smile.gif | Bin 0 -> 978 bytes .../htdocs/img/mood/growf/dwaggins/snore.gif | Bin 0 -> 979 bytes .../img/mood/growf/dwaggins/surprised.gif | Bin 0 -> 974 bytes .../img/mood/growf/dwaggins/tearful.gif | Bin 0 -> 971 bytes .../htdocs/img/mood/growf/dwaggins/think.gif | Bin 0 -> 1013 bytes local/htdocs/img/mood/growf/dwaggins/up.gif | Bin 0 -> 980 bytes .../htdocs/img/mood/growf/dwaggins/weird.gif | Bin 0 -> 1003 bytes .../img/mood/growf/dwaggins/working.gif | Bin 0 -> 996 bytes .../htdocs/img/mood/growf/pengies/amused.gif | Bin 0 -> 489 bytes .../htdocs/img/mood/growf/pengies/annoyed.gif | Bin 0 -> 491 bytes .../htdocs/img/mood/growf/pengies/balloon.gif | Bin 0 -> 998 bytes local/htdocs/img/mood/growf/pengies/blank.gif | Bin 0 -> 936 bytes .../img/mood/growf/pengies/blushing.gif | Bin 0 -> 949 bytes .../htdocs/img/mood/growf/pengies/bouncy.gif | Bin 0 -> 701 bytes .../img/mood/growf/pengies/confused.gif | Bin 0 -> 961 bytes local/htdocs/img/mood/growf/pengies/cool.gif | Bin 0 -> 949 bytes .../img/mood/growf/pengies/determined.gif | Bin 0 -> 939 bytes .../htdocs/img/mood/growf/pengies/devious.gif | Bin 0 -> 958 bytes local/htdocs/img/mood/growf/pengies/drunk.gif | Bin 0 -> 949 bytes .../htdocs/img/mood/growf/pengies/envious.gif | Bin 0 -> 943 bytes local/htdocs/img/mood/growf/pengies/geeky.gif | Bin 0 -> 940 bytes local/htdocs/img/mood/growf/pengies/happy.gif | Bin 0 -> 941 bytes local/htdocs/img/mood/growf/pengies/hyper.gif | Bin 0 -> 990 bytes local/htdocs/img/mood/growf/pengies/idea.gif | Bin 0 -> 972 bytes local/htdocs/img/mood/growf/pengies/livid.gif | Bin 0 -> 526 bytes local/htdocs/img/mood/growf/pengies/sad.gif | Bin 0 -> 938 bytes local/htdocs/img/mood/growf/pengies/sick.gif | Bin 0 -> 949 bytes local/htdocs/img/mood/growf/pengies/sob.gif | Bin 0 -> 487 bytes local/htdocs/img/mood/growf/pengies/sweat.gif | Bin 0 -> 497 bytes .../img/mood/growf/pengies/thoughtful.gif | Bin 0 -> 959 bytes .../img/mood/growf/pengies/wideeyed.gif | Bin 0 -> 942 bytes local/htdocs/img/mood/growf/pengies/yawn.gif | Bin 0 -> 766 bytes .../img/mood/moonsis/stars/green/achy_sg.gif | Bin 0 -> 991 bytes .../mood/moonsis/stars/green/angelic_sg.gif | Bin 0 -> 1916 bytes .../img/mood/moonsis/stars/green/angry_sg.gif | Bin 0 -> 1607 bytes .../mood/moonsis/stars/green/artistic_sg.gif | Bin 0 -> 2373 bytes .../img/mood/moonsis/stars/green/awake_sg.gif | Bin 0 -> 1477 bytes .../img/mood/moonsis/stars/green/blank_sg.gif | Bin 0 -> 1512 bytes .../img/mood/moonsis/stars/green/bored_sg.gif | Bin 0 -> 1528 bytes .../img/mood/moonsis/stars/green/cold_sg.gif | Bin 0 -> 1640 bytes .../mood/moonsis/stars/green/confused_sg.gif | Bin 0 -> 1644 bytes .../img/mood/moonsis/stars/green/dirty_sg.gif | Bin 0 -> 1845 bytes .../img/mood/moonsis/stars/green/drunk_sg.gif | Bin 0 -> 1669 bytes .../moonsis/stars/green/emberassed_sg.gif | Bin 0 -> 2360 bytes .../mood/moonsis/stars/green/envious_sg.gif | Bin 0 -> 2364 bytes .../mood/moonsis/stars/green/exhausted_sg.gif | Bin 0 -> 1584 bytes .../img/mood/moonsis/stars/green/full_sg.gif | Bin 0 -> 1775 bytes .../mood/moonsis/stars/green/grumpy_sg.gif | Bin 0 -> 2294 bytes .../img/mood/moonsis/stars/green/happy_sg.gif | Bin 0 -> 2260 bytes .../img/mood/moonsis/stars/green/horny_sg.gif | Bin 0 -> 1642 bytes .../img/mood/moonsis/stars/green/hot_sg.gif | Bin 0 -> 1686 bytes .../mood/moonsis/stars/green/hungry_sg.gif | Bin 0 -> 1636 bytes .../img/mood/moonsis/stars/green/hyper_sg.gif | Bin 0 -> 1540 bytes .../moonsis/stars/green/indescribable_sg.gif | Bin 0 -> 633 bytes .../moonsis/stars/green/indifferent_sg.gif | Bin 0 -> 1516 bytes .../img/mood/moonsis/stars/green/loved_sg.gif | Bin 0 -> 1726 bytes .../mood/moonsis/stars/green/mellow_sg.gif | Bin 0 -> 1499 bytes .../moonsis/stars/green/mischivious_sg.gif | Bin 0 -> 1795 bytes .../img/mood/moonsis/stars/green/nerdy_sg.gif | Bin 0 -> 1538 bytes .../mood/moonsis/stars/green/pensive_sg.gif | Bin 0 -> 2356 bytes .../img/mood/moonsis/stars/green/sad_sg.gif | Bin 0 -> 1580 bytes .../img/mood/moonsis/stars/green/sexy_sg.gif | Bin 0 -> 1693 bytes .../img/mood/moonsis/stars/green/sick_sg.gif | Bin 0 -> 1915 bytes .../img/mood/moonsis/stars/green/silly_sg.gif | Bin 0 -> 893 bytes .../mood/moonsis/stars/green/singing_sg.gif | Bin 0 -> 1639 bytes .../mood/moonsis/stars/green/sleepy_sg.gif | Bin 0 -> 1609 bytes .../img/mood/moonsis/stars/green/sore_sg.gif | Bin 0 -> 1642 bytes .../mood/moonsis/stars/green/stressed_sg.gif | Bin 0 -> 2852 bytes .../mood/moonsis/stars/green/thirsty_sg.gif | Bin 0 -> 1643 bytes .../mood/moonsis/stars/green/working_sg.gif | Bin 0 -> 2039 bytes .../img/mood/moonsis/stars/purple/achy_sp.gif | Bin 0 -> 860 bytes .../mood/moonsis/stars/purple/angelic_sp.gif | Bin 0 -> 1904 bytes .../mood/moonsis/stars/purple/angry_sp.gif | Bin 0 -> 1567 bytes .../mood/moonsis/stars/purple/artistic_sp.gif | Bin 0 -> 2363 bytes .../mood/moonsis/stars/purple/awake_sp.gif | Bin 0 -> 1212 bytes .../mood/moonsis/stars/purple/blank_sp.gif | Bin 0 -> 1489 bytes .../mood/moonsis/stars/purple/bored_sp.gif | Bin 0 -> 1516 bytes .../img/mood/moonsis/stars/purple/cold_sp.gif | Bin 0 -> 1663 bytes .../mood/moonsis/stars/purple/confused_sp.gif | Bin 0 -> 1644 bytes .../mood/moonsis/stars/purple/dirty_sp.gif | Bin 0 -> 1816 bytes .../mood/moonsis/stars/purple/drunk_sp.gif | Bin 0 -> 1695 bytes .../moonsis/stars/purple/emberassed_sp.gif | Bin 0 -> 2367 bytes .../mood/moonsis/stars/purple/envious_sp.gif | Bin 0 -> 2387 bytes .../moonsis/stars/purple/exhausted_sp.gif | Bin 0 -> 1577 bytes .../img/mood/moonsis/stars/purple/full_sp.gif | Bin 0 -> 1739 bytes .../mood/moonsis/stars/purple/grumpy_sp.gif | Bin 0 -> 2252 bytes .../mood/moonsis/stars/purple/happy_sp.gif | Bin 0 -> 2222 bytes .../mood/moonsis/stars/purple/horny_sp.gif | Bin 0 -> 1657 bytes .../img/mood/moonsis/stars/purple/hot_sp.gif | Bin 0 -> 1629 bytes .../mood/moonsis/stars/purple/hungry_sp.gif | Bin 0 -> 1672 bytes .../mood/moonsis/stars/purple/hyper_sp.gif | Bin 0 -> 1515 bytes .../moonsis/stars/purple/indescribable_sp.gif | Bin 0 -> 624 bytes .../moonsis/stars/purple/indifferent_sp.gif | Bin 0 -> 672 bytes .../mood/moonsis/stars/purple/loved_sp.gif | Bin 0 -> 1703 bytes .../mood/moonsis/stars/purple/mellow_sp.gif | Bin 0 -> 1528 bytes .../moonsis/stars/purple/mischivious_sp.gif | Bin 0 -> 1796 bytes .../mood/moonsis/stars/purple/nerdy_sp.gif | Bin 0 -> 1527 bytes .../mood/moonsis/stars/purple/pensive_sp.gif | Bin 0 -> 2359 bytes .../img/mood/moonsis/stars/purple/sad_sp.gif | Bin 0 -> 1571 bytes .../img/mood/moonsis/stars/purple/sexy_sp.gif | Bin 0 -> 1671 bytes .../img/mood/moonsis/stars/purple/sick_sp.gif | Bin 0 -> 1864 bytes .../mood/moonsis/stars/purple/silly_sp.gif | Bin 0 -> 745 bytes .../mood/moonsis/stars/purple/singing_sp.gif | Bin 0 -> 1619 bytes .../mood/moonsis/stars/purple/sleepy_sp.gif | Bin 0 -> 1584 bytes .../img/mood/moonsis/stars/purple/sore_sp.gif | Bin 0 -> 1664 bytes .../mood/moonsis/stars/purple/stressed_sp.gif | Bin 0 -> 2739 bytes .../mood/moonsis/stars/purple/thirsty_sp.gif | Bin 0 -> 1601 bytes .../mood/moonsis/stars/purple/working_sp.gif | Bin 0 -> 2244 bytes .../img/mood/moonsis/stars/red/achy_sr.gif | Bin 0 -> 854 bytes .../img/mood/moonsis/stars/red/angelic_sr.gif | Bin 0 -> 1918 bytes .../img/mood/moonsis/stars/red/angry_sr.gif | Bin 0 -> 1602 bytes .../mood/moonsis/stars/red/artistic_sr.gif | Bin 0 -> 2386 bytes .../img/mood/moonsis/stars/red/awake_sr.gif | Bin 0 -> 1323 bytes .../img/mood/moonsis/stars/red/blank_sr.gif | Bin 0 -> 1533 bytes .../img/mood/moonsis/stars/red/bored_sr.gif | Bin 0 -> 1529 bytes .../img/mood/moonsis/stars/red/cold_sr.gif | Bin 0 -> 1684 bytes .../mood/moonsis/stars/red/confused_sr.gif | Bin 0 -> 1670 bytes .../img/mood/moonsis/stars/red/dirty_sr.gif | Bin 0 -> 1830 bytes .../img/mood/moonsis/stars/red/drunk_sr.gif | Bin 0 -> 1654 bytes .../mood/moonsis/stars/red/emberassed_sr.gif | Bin 0 -> 2316 bytes .../img/mood/moonsis/stars/red/envious_sr.gif | Bin 0 -> 2413 bytes .../mood/moonsis/stars/red/exhausted_sr.gif | Bin 0 -> 1594 bytes .../img/mood/moonsis/stars/red/full_sr.gif | Bin 0 -> 1767 bytes .../img/mood/moonsis/stars/red/grumpy_sr.gif | Bin 0 -> 2285 bytes .../img/mood/moonsis/stars/red/happy_sr.gif | Bin 0 -> 2260 bytes .../img/mood/moonsis/stars/red/horny_sr.gif | Bin 0 -> 1672 bytes .../img/mood/moonsis/stars/red/hot_sr.gif | Bin 0 -> 1679 bytes .../img/mood/moonsis/stars/red/hungry_sr.gif | Bin 0 -> 1669 bytes .../img/mood/moonsis/stars/red/hyper_sr.gif | Bin 0 -> 1545 bytes .../moonsis/stars/red/indescribable_sr.gif | Bin 0 -> 616 bytes .../mood/moonsis/stars/red/indifferent_sr.gif | Bin 0 -> 1532 bytes .../img/mood/moonsis/stars/red/loved_sr.gif | Bin 0 -> 1728 bytes .../img/mood/moonsis/stars/red/mellow_sr.gif | Bin 0 -> 1519 bytes .../mood/moonsis/stars/red/mischivious_sr.gif | Bin 0 -> 1799 bytes .../img/mood/moonsis/stars/red/nerdy_sr.gif | Bin 0 -> 1559 bytes .../img/mood/moonsis/stars/red/pensive_sr.gif | Bin 0 -> 2343 bytes .../img/mood/moonsis/stars/red/sad_sr.gif | Bin 0 -> 1588 bytes .../img/mood/moonsis/stars/red/sexy_sr.gif | Bin 0 -> 1699 bytes .../img/mood/moonsis/stars/red/sick_sr.gif | Bin 0 -> 1875 bytes .../img/mood/moonsis/stars/red/silly_sr.gif | Bin 0 -> 756 bytes .../img/mood/moonsis/stars/red/singing_sr.gif | Bin 0 -> 1635 bytes .../img/mood/moonsis/stars/red/sleepy_sr.gif | Bin 0 -> 1578 bytes .../img/mood/moonsis/stars/red/sore_sr.gif | Bin 0 -> 1660 bytes .../mood/moonsis/stars/red/stressed_sr.gif | Bin 0 -> 2853 bytes .../img/mood/moonsis/stars/red/thirsty_sr.gif | Bin 0 -> 1629 bytes .../img/mood/moonsis/stars/red/working_sr.gif | Bin 0 -> 2197 bytes .../img/mood/moonsis/stars/yellow/achy_sy.gif | Bin 0 -> 792 bytes .../mood/moonsis/stars/yellow/angelic_sy.gif | Bin 0 -> 1902 bytes .../mood/moonsis/stars/yellow/angry_sy.gif | Bin 0 -> 1562 bytes .../mood/moonsis/stars/yellow/artistic_sy.gif | Bin 0 -> 2338 bytes .../mood/moonsis/stars/yellow/awake_sy.gif | Bin 0 -> 1186 bytes .../mood/moonsis/stars/yellow/blank_sy.gif | Bin 0 -> 1508 bytes .../mood/moonsis/stars/yellow/bored_sy.gif | Bin 0 -> 1484 bytes .../img/mood/moonsis/stars/yellow/cold_sy.gif | Bin 0 -> 1628 bytes .../mood/moonsis/stars/yellow/confused_sy.gif | Bin 0 -> 1626 bytes .../mood/moonsis/stars/yellow/dirty_sy.gif | Bin 0 -> 1817 bytes .../mood/moonsis/stars/yellow/drunk_sy.gif | Bin 0 -> 1671 bytes .../moonsis/stars/yellow/emberassed_sy.gif | Bin 0 -> 2398 bytes .../mood/moonsis/stars/yellow/envious_sy.gif | Bin 0 -> 2451 bytes .../moonsis/stars/yellow/exhausted_sy.gif | Bin 0 -> 1542 bytes .../img/mood/moonsis/stars/yellow/full_sy.gif | Bin 0 -> 1743 bytes .../mood/moonsis/stars/yellow/grumpy_sy.gif | Bin 0 -> 2569 bytes .../mood/moonsis/stars/yellow/happy_sy.gif | Bin 0 -> 2219 bytes .../mood/moonsis/stars/yellow/horny_sy.gif | Bin 0 -> 1614 bytes .../img/mood/moonsis/stars/yellow/hot_sy.gif | Bin 0 -> 1613 bytes .../mood/moonsis/stars/yellow/hungry_sy.gif | Bin 0 -> 1655 bytes .../mood/moonsis/stars/yellow/hyper_sy.gif | Bin 0 -> 1500 bytes .../moonsis/stars/yellow/indescribable_sy.gif | Bin 0 -> 559 bytes .../moonsis/stars/yellow/indifferent_sy.gif | Bin 0 -> 577 bytes .../mood/moonsis/stars/yellow/loved_sy.gif | Bin 0 -> 1675 bytes .../mood/moonsis/stars/yellow/mellow_sy.gif | Bin 0 -> 1514 bytes .../moonsis/stars/yellow/mischivious_sy.gif | Bin 0 -> 1742 bytes .../mood/moonsis/stars/yellow/nerdy_sy.gif | Bin 0 -> 1518 bytes .../mood/moonsis/stars/yellow/pensive_sy.gif | Bin 0 -> 2323 bytes .../img/mood/moonsis/stars/yellow/sad_sy.gif | Bin 0 -> 1558 bytes .../img/mood/moonsis/stars/yellow/sexy_sy.gif | Bin 0 -> 1653 bytes .../img/mood/moonsis/stars/yellow/sick_sy.gif | Bin 0 -> 1826 bytes .../mood/moonsis/stars/yellow/silly_sy.gif | Bin 0 -> 739 bytes .../mood/moonsis/stars/yellow/singing_sy.gif | Bin 0 -> 1598 bytes .../mood/moonsis/stars/yellow/sleepy_sy.gif | Bin 0 -> 1598 bytes .../img/mood/moonsis/stars/yellow/sore_sy.gif | Bin 0 -> 1664 bytes .../mood/moonsis/stars/yellow/stressed_sy.gif | Bin 0 -> 2752 bytes .../mood/moonsis/stars/yellow/thirsty_sy.gif | Bin 0 -> 1619 bytes .../mood/moonsis/stars/yellow/working_sy.gif | Bin 0 -> 2247 bytes .../img/mood/neko/kaokitty/accomplished.gif | Bin 0 -> 1187 bytes .../img/mood/neko/kaokitty/aggravated.gif | Bin 0 -> 1767 bytes .../htdocs/img/mood/neko/kaokitty/amused.gif | Bin 0 -> 1748 bytes local/htdocs/img/mood/neko/kaokitty/angry.gif | Bin 0 -> 1771 bytes .../htdocs/img/mood/neko/kaokitty/annoyed.gif | Bin 0 -> 1757 bytes .../img/mood/neko/kaokitty/apathetic.gif | Bin 0 -> 1739 bytes .../img/mood/neko/kaokitty/artistic.gif | Bin 0 -> 6325 bytes local/htdocs/img/mood/neko/kaokitty/awake.gif | Bin 0 -> 2379 bytes .../htdocs/img/mood/neko/kaokitty/bitchy.gif | Bin 0 -> 1773 bytes local/htdocs/img/mood/neko/kaokitty/blah.gif | Bin 0 -> 1739 bytes local/htdocs/img/mood/neko/kaokitty/blank.gif | Bin 0 -> 1256 bytes local/htdocs/img/mood/neko/kaokitty/bored.gif | Bin 0 -> 1741 bytes .../htdocs/img/mood/neko/kaokitty/bouncey.gif | Bin 0 -> 1308 bytes local/htdocs/img/mood/neko/kaokitty/busy.gif | Bin 0 -> 1187 bytes local/htdocs/img/mood/neko/kaokitty/calm.gif | Bin 0 -> 1304 bytes .../img/mood/neko/kaokitty/cheerful.gif | Bin 0 -> 1860 bytes .../htdocs/img/mood/neko/kaokitty/chipper.gif | Bin 0 -> 1301 bytes local/htdocs/img/mood/neko/kaokitty/cold.gif | Bin 0 -> 1393 bytes .../img/mood/neko/kaokitty/complacent.gif | Bin 0 -> 1832 bytes .../img/mood/neko/kaokitty/confused.gif | Bin 0 -> 2243 bytes .../img/mood/neko/kaokitty/contemplative.gif | Bin 0 -> 1888 bytes .../htdocs/img/mood/neko/kaokitty/content.gif | Bin 0 -> 1746 bytes .../htdocs/img/mood/neko/kaokitty/cranky.gif | Bin 0 -> 1768 bytes .../htdocs/img/mood/neko/kaokitty/crappy.gif | Bin 0 -> 1286 bytes local/htdocs/img/mood/neko/kaokitty/crazy.gif | Bin 0 -> 2335 bytes .../img/mood/neko/kaokitty/creative.gif | Bin 0 -> 6325 bytes .../htdocs/img/mood/neko/kaokitty/crushed.gif | Bin 0 -> 1293 bytes .../htdocs/img/mood/neko/kaokitty/curious.gif | Bin 0 -> 2183 bytes .../htdocs/img/mood/neko/kaokitty/cynical.gif | Bin 0 -> 1746 bytes .../img/mood/neko/kaokitty/depressed.gif | Bin 0 -> 1288 bytes .../img/mood/neko/kaokitty/determined.gif | Bin 0 -> 1741 bytes .../htdocs/img/mood/neko/kaokitty/devious.gif | Bin 0 -> 2005 bytes local/htdocs/img/mood/neko/kaokitty/dirty.gif | Bin 0 -> 2046 bytes .../img/mood/neko/kaokitty/disappointed.gif | Bin 0 -> 1286 bytes .../img/mood/neko/kaokitty/discontent.gif | Bin 0 -> 1286 bytes local/htdocs/img/mood/neko/kaokitty/ditzy.gif | Bin 0 -> 1350 bytes local/htdocs/img/mood/neko/kaokitty/dorky.gif | Bin 0 -> 1818 bytes .../htdocs/img/mood/neko/kaokitty/drained.gif | Bin 0 -> 1290 bytes local/htdocs/img/mood/neko/kaokitty/drunk.gif | Bin 0 -> 1894 bytes .../img/mood/neko/kaokitty/ecstatic.gif | Bin 0 -> 1365 bytes .../img/mood/neko/kaokitty/energetic.gif | Bin 0 -> 1961 bytes .../htdocs/img/mood/neko/kaokitty/enraged.gif | Bin 0 -> 1900 bytes .../img/mood/neko/kaokitty/enthralled.gif | Bin 0 -> 2263 bytes .../htdocs/img/mood/neko/kaokitty/envious.gif | Bin 0 -> 1349 bytes .../img/mood/neko/kaokitty/exanimate.gif | Bin 0 -> 1293 bytes .../img/mood/neko/kaokitty/exausted.gif | Bin 0 -> 1290 bytes .../htdocs/img/mood/neko/kaokitty/excited.gif | Bin 0 -> 1369 bytes .../htdocs/img/mood/neko/kaokitty/flirty.gif | Bin 0 -> 1346 bytes .../img/mood/neko/kaokitty/frustrated.gif | Bin 0 -> 1822 bytes local/htdocs/img/mood/neko/kaokitty/full.gif | Bin 0 -> 2362 bytes local/htdocs/img/mood/neko/kaokitty/geeky.gif | Bin 0 -> 2439 bytes local/htdocs/img/mood/neko/kaokitty/giddy.gif | Bin 0 -> 1299 bytes .../htdocs/img/mood/neko/kaokitty/giggly.gif | Bin 0 -> 1307 bytes .../htdocs/img/mood/neko/kaokitty/gloomy.gif | Bin 0 -> 1996 bytes local/htdocs/img/mood/neko/kaokitty/good.gif | Bin 0 -> 2278 bytes .../img/mood/neko/kaokitty/grateful.gif | Bin 0 -> 1737 bytes .../htdocs/img/mood/neko/kaokitty/groggy.gif | Bin 0 -> 1894 bytes .../htdocs/img/mood/neko/kaokitty/grumpy.gif | Bin 0 -> 2012 bytes .../htdocs/img/mood/neko/kaokitty/guilty.gif | Bin 0 -> 1728 bytes local/htdocs/img/mood/neko/kaokitty/happy.gif | Bin 0 -> 1746 bytes local/htdocs/img/mood/neko/kaokitty/high.gif | Bin 0 -> 1611 bytes .../htdocs/img/mood/neko/kaokitty/hopeful.gif | Bin 0 -> 1756 bytes local/htdocs/img/mood/neko/kaokitty/horny.gif | Bin 0 -> 1882 bytes local/htdocs/img/mood/neko/kaokitty/hot.gif | Bin 0 -> 1943 bytes .../htdocs/img/mood/neko/kaokitty/hungry2.gif | Bin 0 -> 2285 bytes local/htdocs/img/mood/neko/kaokitty/hyper.gif | Bin 0 -> 1312 bytes .../img/mood/neko/kaokitty/impressed.gif | Bin 0 -> 1736 bytes .../img/mood/neko/kaokitty/indescribable.gif | Bin 0 -> 1256 bytes .../img/mood/neko/kaokitty/indifferent.gif | Bin 0 -> 1739 bytes .../img/mood/neko/kaokitty/infuriated.gif | Bin 0 -> 1447 bytes local/htdocs/img/mood/neko/kaokitty/irate.gif | Bin 0 -> 1798 bytes .../img/mood/neko/kaokitty/irritated.gif | Bin 0 -> 1297 bytes .../img/mood/neko/kaokitty/jubilant.gif | Bin 0 -> 1748 bytes local/htdocs/img/mood/neko/kaokitty/lazy.gif | Bin 0 -> 1290 bytes .../img/mood/neko/kaokitty/lethargic.gif | Bin 0 -> 1290 bytes .../img/mood/neko/kaokitty/listless.gif | Bin 0 -> 1290 bytes .../htdocs/img/mood/neko/kaokitty/lonely.gif | Bin 0 -> 1292 bytes local/htdocs/img/mood/neko/kaokitty/loved.gif | Bin 0 -> 2424 bytes .../img/mood/neko/kaokitty/melancholy.gif | Bin 0 -> 1292 bytes .../htdocs/img/mood/neko/kaokitty/mellow.gif | Bin 0 -> 1832 bytes .../img/mood/neko/kaokitty/mischievous.gif | Bin 0 -> 2011 bytes .../htdocs/img/mood/neko/kaokitty/morose.gif | Bin 0 -> 1292 bytes .../htdocs/img/mood/neko/kaokitty/naughty.gif | Bin 0 -> 2013 bytes .../img/mood/neko/kaokitty/nauseated.gif | Bin 0 -> 796 bytes local/htdocs/img/mood/neko/kaokitty/nerdy.gif | Bin 0 -> 1818 bytes .../img/mood/neko/kaokitty/nostalgic.gif | Bin 0 -> 1888 bytes local/htdocs/img/mood/neko/kaokitty/numb.gif | Bin 0 -> 1126 bytes local/htdocs/img/mood/neko/kaokitty/okay.gif | Bin 0 -> 1746 bytes .../img/mood/neko/kaokitty/optimistic.gif | Bin 0 -> 1756 bytes .../img/mood/neko/kaokitty/peaceful.gif | Bin 0 -> 1832 bytes .../htdocs/img/mood/neko/kaokitty/pensive.gif | Bin 0 -> 1888 bytes .../img/mood/neko/kaokitty/pessimistic.gif | Bin 0 -> 1771 bytes .../htdocs/img/mood/neko/kaokitty/pissed.gif | Bin 0 -> 1918 bytes .../htdocs/img/mood/neko/kaokitty/pleased.gif | Bin 0 -> 1746 bytes .../img/mood/neko/kaokitty/predatory.gif | Bin 0 -> 2346 bytes .../img/mood/neko/kaokitty/productive.gif | Bin 0 -> 1187 bytes .../img/mood/neko/kaokitty/quixotic.gif | Bin 0 -> 1849 bytes .../img/mood/neko/kaokitty/recumbent.gif | Bin 0 -> 1290 bytes .../img/mood/neko/kaokitty/refreshed.gif | Bin 0 -> 2437 bytes .../img/mood/neko/kaokitty/rejected.gif | Bin 0 -> 1793 bytes .../img/mood/neko/kaokitty/rejuvenated.gif | Bin 0 -> 2437 bytes .../htdocs/img/mood/neko/kaokitty/relaxed.gif | Bin 0 -> 1290 bytes .../img/mood/neko/kaokitty/relieved.gif | Bin 0 -> 2213 bytes .../img/mood/neko/kaokitty/restless.gif | Bin 0 -> 1736 bytes .../htdocs/img/mood/neko/kaokitty/rushed.gif | Bin 0 -> 1684 bytes local/htdocs/img/mood/neko/kaokitty/sad.gif | Bin 0 -> 1292 bytes .../img/mood/neko/kaokitty/satisfied.gif | Bin 0 -> 1300 bytes .../htdocs/img/mood/neko/kaokitty/scared.gif | Bin 0 -> 1762 bytes .../htdocs/img/mood/neko/kaokitty/shocked.gif | Bin 0 -> 1776 bytes local/htdocs/img/mood/neko/kaokitty/sick.gif | Bin 0 -> 796 bytes local/htdocs/img/mood/neko/kaokitty/silly.gif | Bin 0 -> 1849 bytes .../htdocs/img/mood/neko/kaokitty/sleepy.gif | Bin 0 -> 1443 bytes local/htdocs/img/mood/neko/kaokitty/sore.gif | Bin 0 -> 1909 bytes .../img/mood/neko/kaokitty/stressed.gif | Bin 0 -> 1796 bytes .../img/mood/neko/kaokitty/suprised.gif | Bin 0 -> 1776 bytes .../img/mood/neko/kaokitty/sympathetic.gif | Bin 0 -> 1762 bytes .../img/mood/neko/kaokitty/thankful.gif | Bin 0 -> 1746 bytes .../htdocs/img/mood/neko/kaokitty/thirsty.gif | Bin 0 -> 2437 bytes .../img/mood/neko/kaokitty/thoughtful.gif | Bin 0 -> 1888 bytes local/htdocs/img/mood/neko/kaokitty/tired.gif | Bin 0 -> 2762 bytes .../htdocs/img/mood/neko/kaokitty/touched.gif | Bin 0 -> 1913 bytes .../img/mood/neko/kaokitty/uncomfortable.gif | Bin 0 -> 1762 bytes local/htdocs/img/mood/neko/kaokitty/weird.gif | Bin 0 -> 2335 bytes .../htdocs/img/mood/neko/kaokitty/working.gif | Bin 0 -> 1187 bytes .../htdocs/img/mood/neko/kaokitty/worried.gif | Bin 0 -> 1762 bytes .../htdocs/img/mood/niaha/kitty/ankangry.gif | Bin 0 -> 398 bytes .../htdocs/img/mood/niaha/kitty/ankangryb.gif | Bin 0 -> 398 bytes .../htdocs/img/mood/niaha/kitty/ankangryg.gif | Bin 0 -> 398 bytes .../htdocs/img/mood/niaha/kitty/ankangryp.gif | Bin 0 -> 399 bytes .../htdocs/img/mood/niaha/kitty/ankawake.gif | Bin 0 -> 400 bytes .../htdocs/img/mood/niaha/kitty/ankawakeb.gif | Bin 0 -> 400 bytes .../htdocs/img/mood/niaha/kitty/ankawakeg.gif | Bin 0 -> 400 bytes .../htdocs/img/mood/niaha/kitty/ankawakep.gif | Bin 0 -> 400 bytes .../htdocs/img/mood/niaha/kitty/ankcreate.gif | Bin 0 -> 972 bytes .../img/mood/niaha/kitty/ankcreateb.gif | Bin 0 -> 972 bytes .../img/mood/niaha/kitty/ankcreateg.gif | Bin 0 -> 1220 bytes .../img/mood/niaha/kitty/ankcreatep.gif | Bin 0 -> 972 bytes local/htdocs/img/mood/niaha/kitty/ankfood.gif | Bin 0 -> 368 bytes .../htdocs/img/mood/niaha/kitty/ankfoodb.gif | Bin 0 -> 368 bytes .../htdocs/img/mood/niaha/kitty/ankfoodg.gif | Bin 0 -> 368 bytes .../htdocs/img/mood/niaha/kitty/ankfoodp.gif | Bin 0 -> 368 bytes local/htdocs/img/mood/niaha/kitty/ankgeek.gif | Bin 0 -> 347 bytes .../htdocs/img/mood/niaha/kitty/ankgeekb.gif | Bin 0 -> 347 bytes .../htdocs/img/mood/niaha/kitty/ankgeekg.gif | Bin 0 -> 343 bytes .../htdocs/img/mood/niaha/kitty/ankgeekp.gif | Bin 0 -> 347 bytes .../htdocs/img/mood/niaha/kitty/ankhappy.gif | Bin 0 -> 330 bytes .../htdocs/img/mood/niaha/kitty/ankhappyb.gif | Bin 0 -> 330 bytes .../htdocs/img/mood/niaha/kitty/ankhappyg.gif | Bin 0 -> 330 bytes .../htdocs/img/mood/niaha/kitty/ankhappyp.gif | Bin 0 -> 330 bytes local/htdocs/img/mood/niaha/kitty/ankhunt.gif | Bin 0 -> 322 bytes .../htdocs/img/mood/niaha/kitty/ankhuntb.gif | Bin 0 -> 314 bytes .../htdocs/img/mood/niaha/kitty/ankhuntg.gif | Bin 0 -> 314 bytes .../htdocs/img/mood/niaha/kitty/ankhuntp.gif | Bin 0 -> 314 bytes .../htdocs/img/mood/niaha/kitty/ankhyper.gif | Bin 0 -> 390 bytes .../htdocs/img/mood/niaha/kitty/ankhyperb.gif | Bin 0 -> 390 bytes .../htdocs/img/mood/niaha/kitty/ankhyperg.gif | Bin 0 -> 390 bytes .../htdocs/img/mood/niaha/kitty/ankhyperp.gif | Bin 0 -> 390 bytes .../htdocs/img/mood/niaha/kitty/ankitten.gif | Bin 0 -> 332 bytes .../htdocs/img/mood/niaha/kitty/ankittenb.gif | Bin 0 -> 332 bytes .../htdocs/img/mood/niaha/kitty/ankitteng.gif | Bin 0 -> 332 bytes .../htdocs/img/mood/niaha/kitty/ankittenp.gif | Bin 0 -> 333 bytes local/htdocs/img/mood/niaha/kitty/anksad.gif | Bin 0 -> 318 bytes local/htdocs/img/mood/niaha/kitty/anksadb.gif | Bin 0 -> 318 bytes local/htdocs/img/mood/niaha/kitty/anksadg.gif | Bin 0 -> 318 bytes local/htdocs/img/mood/niaha/kitty/anksadp.gif | Bin 0 -> 318 bytes .../htdocs/img/mood/niaha/kitty/ankscared.gif | Bin 0 -> 419 bytes .../img/mood/niaha/kitty/ankscaredb.gif | Bin 0 -> 419 bytes .../img/mood/niaha/kitty/ankscaredg.gif | Bin 0 -> 419 bytes .../img/mood/niaha/kitty/ankscaredp.gif | Bin 0 -> 419 bytes .../htdocs/img/mood/niaha/kitty/anksleepy.gif | Bin 0 -> 593 bytes .../img/mood/niaha/kitty/anksleepyb.gif | Bin 0 -> 593 bytes .../img/mood/niaha/kitty/anksleepyg.gif | Bin 0 -> 593 bytes .../img/mood/niaha/kitty/anksleepyp.gif | Bin 0 -> 593 bytes .../htdocs/img/mood/niaha/kitty/ankthink.gif | Bin 0 -> 778 bytes .../htdocs/img/mood/niaha/kitty/ankthinkb.gif | Bin 0 -> 778 bytes .../htdocs/img/mood/niaha/kitty/ankthinkg.gif | Bin 0 -> 778 bytes .../htdocs/img/mood/niaha/kitty/ankthinkp.gif | Bin 0 -> 779 bytes .../htdocs/img/mood/niaha/kitty/anktired.gif | Bin 0 -> 368 bytes .../htdocs/img/mood/niaha/kitty/anktiredb.gif | Bin 0 -> 374 bytes .../htdocs/img/mood/niaha/kitty/anktiredg.gif | Bin 0 -> 374 bytes .../htdocs/img/mood/niaha/kitty/anktiredp.gif | Bin 0 -> 735 bytes local/htdocs/img/mood/niaha/kitty/ankwink.gif | Bin 0 -> 320 bytes .../htdocs/img/mood/niaha/kitty/ankwinkb.gif | Bin 0 -> 320 bytes .../htdocs/img/mood/niaha/kitty/ankwinkg.gif | Bin 0 -> 320 bytes .../htdocs/img/mood/niaha/kitty/ankwinkp.gif | Bin 0 -> 318 bytes .../htdocs/img/mood/opiummmm/foxies/angry.gif | Bin 0 -> 210 bytes .../htdocs/img/mood/opiummmm/foxies/awake.gif | Bin 0 -> 222 bytes .../img/mood/opiummmm/foxies/confused.gif | Bin 0 -> 195 bytes .../img/mood/opiummmm/foxies/determined.gif | Bin 0 -> 245 bytes .../img/mood/opiummmm/foxies/discontent.gif | Bin 0 -> 222 bytes .../img/mood/opiummmm/foxies/energetic.gif | Bin 0 -> 238 bytes .../img/mood/opiummmm/foxies/enthralled.gif | Bin 0 -> 225 bytes .../htdocs/img/mood/opiummmm/foxies/happy.gif | Bin 0 -> 224 bytes .../mood/opiummmm/foxies/indescribable.gif | Bin 0 -> 201 bytes .../htdocs/img/mood/opiummmm/foxies/nerdy.gif | Bin 0 -> 653 bytes .../htdocs/img/mood/opiummmm/foxies/okay.gif | Bin 0 -> 222 bytes local/htdocs/img/mood/opiummmm/foxies/sad.gif | Bin 0 -> 216 bytes .../img/mood/opiummmm/foxies/scared.gif | Bin 0 -> 216 bytes .../img/mood/opiummmm/foxies/thoughtful.gif | Bin 0 -> 204 bytes .../img/mood/opiummmm/foxies/working.gif | Bin 0 -> 293 bytes .../img/mood/punquinheads/blue/angelic.gif | Bin 0 -> 2006 bytes .../img/mood/punquinheads/blue/angry.gif | Bin 0 -> 1147 bytes .../img/mood/punquinheads/blue/artistic.gif | Bin 0 -> 1747 bytes .../img/mood/punquinheads/blue/awake.gif | Bin 0 -> 1668 bytes .../img/mood/punquinheads/blue/blah.gif | Bin 0 -> 960 bytes .../img/mood/punquinheads/blue/blank.gif | Bin 0 -> 347 bytes .../img/mood/punquinheads/blue/cheerful.gif | Bin 0 -> 967 bytes .../img/mood/punquinheads/blue/cold.gif | Bin 0 -> 635 bytes .../img/mood/punquinheads/blue/confused.gif | Bin 0 -> 1053 bytes .../img/mood/punquinheads/blue/curious.gif | Bin 0 -> 967 bytes .../img/mood/punquinheads/blue/determined.gif | Bin 0 -> 1067 bytes .../img/mood/punquinheads/blue/dirty.gif | Bin 0 -> 1206 bytes .../img/mood/punquinheads/blue/dizzy.gif | Bin 0 -> 1743 bytes .../mood/punquinheads/blue/embarrassed.gif | Bin 0 -> 960 bytes .../img/mood/punquinheads/blue/envious.gif | Bin 0 -> 613 bytes .../img/mood/punquinheads/blue/excited.gif | Bin 0 -> 970 bytes .../img/mood/punquinheads/blue/flirty.gif | Bin 0 -> 1117 bytes .../img/mood/punquinheads/blue/full.gif | Bin 0 -> 1049 bytes .../img/mood/punquinheads/blue/giggly.gif | Bin 0 -> 1504 bytes .../img/mood/punquinheads/blue/gloomy.gif | Bin 0 -> 971 bytes .../img/mood/punquinheads/blue/groggy.gif | Bin 0 -> 508 bytes .../img/mood/punquinheads/blue/grumpy.gif | Bin 0 -> 1344 bytes .../img/mood/punquinheads/blue/happy.gif | Bin 0 -> 966 bytes .../img/mood/punquinheads/blue/hopeful.gif | Bin 0 -> 994 bytes .../htdocs/img/mood/punquinheads/blue/hot.gif | Bin 0 -> 1602 bytes .../img/mood/punquinheads/blue/hungry2.gif | Bin 0 -> 1263 bytes .../img/mood/punquinheads/blue/hyper.gif | Bin 0 -> 962 bytes .../mood/punquinheads/blue/indescribable.gif | Bin 0 -> 809 bytes .../mood/punquinheads/blue/indifferent.gif | Bin 0 -> 960 bytes .../img/mood/punquinheads/blue/lazy.gif | Bin 0 -> 1041 bytes .../img/mood/punquinheads/blue/loved.gif | Bin 0 -> 1115 bytes .../img/mood/punquinheads/blue/mellow.gif | Bin 0 -> 446 bytes .../img/mood/punquinheads/blue/moody.gif | Bin 0 -> 969 bytes .../img/mood/punquinheads/blue/naughty.gif | Bin 0 -> 579 bytes .../img/mood/punquinheads/blue/nerdy.gif | Bin 0 -> 1159 bytes .../img/mood/punquinheads/blue/okay.gif | Bin 0 -> 957 bytes .../htdocs/img/mood/punquinheads/blue/sad.gif | Bin 0 -> 1133 bytes .../img/mood/punquinheads/blue/sick.gif | Bin 0 -> 1410 bytes .../img/mood/punquinheads/blue/silly.gif | Bin 0 -> 1023 bytes .../img/mood/punquinheads/blue/sleepy.gif | Bin 0 -> 1320 bytes .../img/mood/punquinheads/blue/sore.gif | Bin 0 -> 1358 bytes .../img/mood/punquinheads/blue/stressed.gif | Bin 0 -> 2530 bytes .../img/mood/punquinheads/blue/surprised.gif | Bin 0 -> 991 bytes .../img/mood/punquinheads/blue/thirsty.gif | Bin 0 -> 1012 bytes .../img/mood/punquinheads/blue/thoughtful.gif | Bin 0 -> 1201 bytes .../img/mood/punquinheads/blue/tired.gif | Bin 0 -> 958 bytes .../img/mood/punquinheads/blue/working.gif | Bin 0 -> 1768 bytes .../img/mood/punquinheads/blue/worried.gif | Bin 0 -> 987 bytes .../img/mood/punquinheads/pink/angelic.gif | Bin 0 -> 2080 bytes .../img/mood/punquinheads/pink/angry.gif | Bin 0 -> 1148 bytes .../img/mood/punquinheads/pink/artistic.gif | Bin 0 -> 1727 bytes .../img/mood/punquinheads/pink/awake.gif | Bin 0 -> 1651 bytes .../img/mood/punquinheads/pink/blah.gif | Bin 0 -> 952 bytes .../img/mood/punquinheads/pink/blank.gif | Bin 0 -> 782 bytes .../img/mood/punquinheads/pink/cheerful.gif | Bin 0 -> 960 bytes .../img/mood/punquinheads/pink/cold.gif | Bin 0 -> 591 bytes .../img/mood/punquinheads/pink/confused.gif | Bin 0 -> 1048 bytes .../img/mood/punquinheads/pink/curious.gif | Bin 0 -> 951 bytes .../img/mood/punquinheads/pink/determined.gif | Bin 0 -> 1021 bytes .../img/mood/punquinheads/pink/dirty.gif | Bin 0 -> 1262 bytes .../img/mood/punquinheads/pink/dizzy.gif | Bin 0 -> 1761 bytes .../mood/punquinheads/pink/embarrassed.gif | Bin 0 -> 960 bytes .../img/mood/punquinheads/pink/envious.gif | Bin 0 -> 566 bytes .../img/mood/punquinheads/pink/excited.gif | Bin 0 -> 993 bytes .../img/mood/punquinheads/pink/flirty.gif | Bin 0 -> 1117 bytes .../img/mood/punquinheads/pink/full.gif | Bin 0 -> 1048 bytes .../img/mood/punquinheads/pink/giggly.gif | Bin 0 -> 1499 bytes .../img/mood/punquinheads/pink/gloomy.gif | Bin 0 -> 962 bytes .../img/mood/punquinheads/pink/groggy.gif | Bin 0 -> 489 bytes .../img/mood/punquinheads/pink/grumpy.gif | Bin 0 -> 1290 bytes .../img/mood/punquinheads/pink/happy.gif | Bin 0 -> 957 bytes .../img/mood/punquinheads/pink/hopeful.gif | Bin 0 -> 1027 bytes .../htdocs/img/mood/punquinheads/pink/hot.gif | Bin 0 -> 1537 bytes .../img/mood/punquinheads/pink/hungry2.gif | Bin 0 -> 1300 bytes .../img/mood/punquinheads/pink/hyper.gif | Bin 0 -> 957 bytes .../mood/punquinheads/pink/indescribable.gif | Bin 0 -> 809 bytes .../mood/punquinheads/pink/indifferent.gif | Bin 0 -> 952 bytes .../img/mood/punquinheads/pink/lazy.gif | Bin 0 -> 1039 bytes .../img/mood/punquinheads/pink/loved.gif | Bin 0 -> 1115 bytes .../img/mood/punquinheads/pink/mellow.gif | Bin 0 -> 425 bytes .../img/mood/punquinheads/pink/moody.gif | Bin 0 -> 961 bytes .../img/mood/punquinheads/pink/naughty.gif | Bin 0 -> 532 bytes .../img/mood/punquinheads/pink/nerdy.gif | Bin 0 -> 1100 bytes .../img/mood/punquinheads/pink/okay.gif | Bin 0 -> 956 bytes .../htdocs/img/mood/punquinheads/pink/sad.gif | Bin 0 -> 1087 bytes .../img/mood/punquinheads/pink/sick.gif | Bin 0 -> 1372 bytes .../img/mood/punquinheads/pink/silly.gif | Bin 0 -> 971 bytes .../img/mood/punquinheads/pink/sleepy.gif | Bin 0 -> 1270 bytes .../img/mood/punquinheads/pink/sore.gif | Bin 0 -> 1299 bytes .../img/mood/punquinheads/pink/stressed.gif | Bin 0 -> 2520 bytes .../img/mood/punquinheads/pink/surprised.gif | Bin 0 -> 980 bytes .../img/mood/punquinheads/pink/thirsty.gif | Bin 0 -> 943 bytes .../img/mood/punquinheads/pink/thoughtful.gif | Bin 0 -> 1243 bytes .../img/mood/punquinheads/pink/tired.gif | Bin 0 -> 949 bytes .../img/mood/punquinheads/pink/working.gif | Bin 0 -> 1841 bytes .../img/mood/punquinheads/pink/worried.gif | Bin 0 -> 972 bytes .../img/mood/roshi/palefaces/aggravated.gif | Bin 0 -> 862 bytes .../img/mood/roshi/palefaces/amused.gif | Bin 0 -> 863 bytes .../htdocs/img/mood/roshi/palefaces/angry.gif | Bin 0 -> 866 bytes .../img/mood/roshi/palefaces/annoyed.gif | Bin 0 -> 862 bytes .../img/mood/roshi/palefaces/anxious.gif | Bin 0 -> 860 bytes .../img/mood/roshi/palefaces/artistic.gif | Bin 0 -> 1054 bytes .../htdocs/img/mood/roshi/palefaces/awake.gif | Bin 0 -> 537 bytes .../img/mood/roshi/palefaces/bitchy.gif | Bin 0 -> 870 bytes .../htdocs/img/mood/roshi/palefaces/blank.gif | Bin 0 -> 900 bytes .../img/mood/roshi/palefaces/bouncy.gif | Bin 0 -> 612 bytes .../htdocs/img/mood/roshi/palefaces/busy.gif | Bin 0 -> 864 bytes .../img/mood/roshi/palefaces/cheerful.gif | Bin 0 -> 870 bytes .../htdocs/img/mood/roshi/palefaces/cold.gif | Bin 0 -> 1335 bytes .../img/mood/roshi/palefaces/complacent.gif | Bin 0 -> 867 bytes .../img/mood/roshi/palefaces/confused.gif | Bin 0 -> 404 bytes .../img/mood/roshi/palefaces/cranky.gif | Bin 0 -> 556 bytes .../img/mood/roshi/palefaces/crushed.gif | Bin 0 -> 862 bytes .../img/mood/roshi/palefaces/curious.gif | Bin 0 -> 510 bytes .../img/mood/roshi/palefaces/cynical.gif | Bin 0 -> 865 bytes .../img/mood/roshi/palefaces/depressed.gif | Bin 0 -> 884 bytes .../img/mood/roshi/palefaces/determined.gif | Bin 0 -> 862 bytes .../htdocs/img/mood/roshi/palefaces/dirty.gif | Bin 0 -> 665 bytes .../htdocs/img/mood/roshi/palefaces/drunk.gif | Bin 0 -> 821 bytes .../img/mood/roshi/palefaces/ecstatic.gif | Bin 0 -> 577 bytes .../img/mood/roshi/palefaces/embarrassed.gif | Bin 0 -> 685 bytes .../img/mood/roshi/palefaces/energetic.gif | Bin 0 -> 422 bytes .../img/mood/roshi/palefaces/enraged.gif | Bin 0 -> 833 bytes .../img/mood/roshi/palefaces/enthralled.gif | Bin 0 -> 870 bytes .../img/mood/roshi/palefaces/envious.gif | Bin 0 -> 852 bytes .../img/mood/roshi/palefaces/exhausted.gif | Bin 0 -> 667 bytes .../img/mood/roshi/palefaces/frustrated.gif | Bin 0 -> 860 bytes .../htdocs/img/mood/roshi/palefaces/full.gif | Bin 0 -> 564 bytes .../img/mood/roshi/palefaces/gloomy.gif | Bin 0 -> 852 bytes .../htdocs/img/mood/roshi/palefaces/good.gif | Bin 0 -> 865 bytes .../img/mood/roshi/palefaces/groggy.gif | Bin 0 -> 1005 bytes .../img/mood/roshi/palefaces/grumpy.gif | Bin 0 -> 418 bytes .../htdocs/img/mood/roshi/palefaces/happy.gif | Bin 0 -> 871 bytes .../htdocs/img/mood/roshi/palefaces/high.gif | Bin 0 -> 483 bytes .../htdocs/img/mood/roshi/palefaces/horny.gif | Bin 0 -> 493 bytes local/htdocs/img/mood/roshi/palefaces/hot.gif | Bin 0 -> 1001 bytes .../img/mood/roshi/palefaces/hungry.gif | Bin 0 -> 863 bytes .../htdocs/img/mood/roshi/palefaces/hyper.gif | Bin 0 -> 1121 bytes .../img/mood/roshi/palefaces/impressed.gif | Bin 0 -> 870 bytes .../mood/roshi/palefaces/indescribable.gif | Bin 0 -> 943 bytes .../htdocs/img/mood/roshi/palefaces/lazy.gif | Bin 0 -> 603 bytes .../htdocs/img/mood/roshi/palefaces/loved.gif | Bin 0 -> 808 bytes .../img/mood/roshi/palefaces/mischievous.gif | Bin 0 -> 433 bytes .../htdocs/img/mood/roshi/palefaces/moody.gif | Bin 0 -> 485 bytes .../htdocs/img/mood/roshi/palefaces/nerdy.gif | Bin 0 -> 672 bytes .../img/mood/roshi/palefaces/nostalgic.gif | Bin 0 -> 435 bytes .../htdocs/img/mood/roshi/palefaces/okay.gif | Bin 0 -> 865 bytes .../img/mood/roshi/palefaces/predatory.gif | Bin 0 -> 865 bytes .../img/mood/roshi/palefaces/refreshed.gif | Bin 0 -> 681 bytes .../img/mood/roshi/palefaces/relaxed.gif | Bin 0 -> 624 bytes .../img/mood/roshi/palefaces/relieved.gif | Bin 0 -> 775 bytes .../img/mood/roshi/palefaces/rushed.gif | Bin 0 -> 714 bytes local/htdocs/img/mood/roshi/palefaces/sad.gif | Bin 0 -> 860 bytes .../img/mood/roshi/palefaces/scared.gif | Bin 0 -> 407 bytes .../htdocs/img/mood/roshi/palefaces/sick.gif | Bin 0 -> 1856 bytes .../htdocs/img/mood/roshi/palefaces/silly.gif | Bin 0 -> 1030 bytes .../img/mood/roshi/palefaces/sleepy.gif | Bin 0 -> 672 bytes .../img/mood/roshi/palefaces/surprised.gif | Bin 0 -> 675 bytes .../img/mood/roshi/palefaces/thirsty.gif | Bin 0 -> 597 bytes .../img/mood/roshi/palefaces/thoughtful.gif | Bin 0 -> 863 bytes .../img/mood/roshi/palefaces/worried.gif | Bin 0 -> 862 bytes .../twotone/hamsters/accomplished_hammy.gif | Bin 0 -> 1159 bytes .../img/mood/twotone/hamsters/angry_hammy.gif | Bin 0 -> 1107 bytes .../mood/twotone/hamsters/artistic_hammy.gif | Bin 0 -> 1166 bytes .../img/mood/twotone/hamsters/awake_hammy.gif | Bin 0 -> 1122 bytes .../mood/twotone/hamsters/backflip_hammy.gif | Bin 0 -> 6440 bytes .../img/mood/twotone/hamsters/blank_hammy.gif | Bin 0 -> 1097 bytes .../mood/twotone/hamsters/boggle_hammy.gif | Bin 0 -> 426 bytes .../img/mood/twotone/hamsters/cold_hammy.gif | Bin 0 -> 1142 bytes .../mood/twotone/hamsters/cranky_hammy.gif | Bin 0 -> 1112 bytes .../img/mood/twotone/hamsters/crazy_hammy.gif | Bin 0 -> 1124 bytes .../mood/twotone/hamsters/creative_hammy.gif | Bin 0 -> 1234 bytes .../mood/twotone/hamsters/crying_hammy.gif | Bin 0 -> 1102 bytes .../mood/twotone/hamsters/curious_hammy.gif | Bin 0 -> 1136 bytes .../mood/twotone/hamsters/cynical_hammy.gif | Bin 0 -> 1106 bytes .../twotone/hamsters/determined_hammy.gif | Bin 0 -> 1111 bytes .../mood/twotone/hamsters/devious_hammy.gif | Bin 0 -> 1117 bytes .../img/mood/twotone/hamsters/dirty_hammy.gif | Bin 0 -> 1171 bytes .../img/mood/twotone/hamsters/drunk_hammy.gif | Bin 0 -> 1155 bytes .../twotone/hamsters/embarassed_hammy.gif | Bin 0 -> 1150 bytes .../twotone/hamsters/enthralled_hammy.gif | Bin 0 -> 1105 bytes .../mood/twotone/hamsters/envious_hammy.gif | Bin 0 -> 1124 bytes .../mood/twotone/hamsters/exanimate_hammy.gif | Bin 0 -> 1141 bytes .../img/mood/twotone/hamsters/full_hammy.gif | Bin 0 -> 1048 bytes .../mood/twotone/hamsters/furious_hammy.gif | Bin 0 -> 1175 bytes .../mood/twotone/hamsters/giggly_hammy.gif | Bin 0 -> 1146 bytes .../mood/twotone/hamsters/gloomy_hammy.gif | Bin 0 -> 1215 bytes .../mood/twotone/hamsters/grateful_hammy.gif | Bin 0 -> 1141 bytes .../mood/twotone/hamsters/guilty_hammy.gif | Bin 0 -> 1127 bytes .../mood/twotone/hamsters/hopeful_hammy.gif | Bin 0 -> 1135 bytes .../img/mood/twotone/hamsters/horny_hammy.gif | Bin 0 -> 1120 bytes .../img/mood/twotone/hamsters/hot_hammy.gif | Bin 0 -> 1171 bytes .../mood/twotone/hamsters/hungry_hammy.gif | Bin 0 -> 1111 bytes .../twotone/hamsters/indescribable_hammy.gif | Bin 0 -> 2645 bytes .../img/mood/twotone/hamsters/love_hammy.gif | Bin 0 -> 1177 bytes .../img/mood/twotone/hamsters/moody_hammy.gif | Bin 0 -> 1104 bytes .../img/mood/twotone/hamsters/nerdy_hammy.gif | Bin 0 -> 1152 bytes .../mood/twotone/hamsters/nostalgic_hammy.gif | Bin 0 -> 1140 bytes .../mood/twotone/hamsters/pensive_hammy.gif | Bin 0 -> 1125 bytes .../img/mood/twotone/hamsters/plain_hammy.gif | Bin 0 -> 1124 bytes .../mood/twotone/hamsters/predatory_hammy.gif | Bin 0 -> 396 bytes .../mood/twotone/hamsters/puzzled_hammy.gif | Bin 0 -> 1112 bytes .../mood/twotone/hamsters/quixotic_hammy.gif | Bin 0 -> 1229 bytes .../mood/twotone/hamsters/refreshed_hammy.gif | Bin 0 -> 1130 bytes .../twotone/hamsters/rejuvenated_hammy.gif | Bin 0 -> 1136 bytes .../mood/twotone/hamsters/relaxed_hammy.gif | Bin 0 -> 1116 bytes .../img/mood/twotone/hamsters/sad_hammy.gif | Bin 0 -> 1109 bytes .../mood/twotone/hamsters/scared_hammy.gif | Bin 0 -> 1131 bytes .../mood/twotone/hamsters/scrabble_hammy.gif | Bin 0 -> 1480 bytes .../img/mood/twotone/hamsters/sick_hammy.gif | Bin 0 -> 1130 bytes .../mood/twotone/hamsters/sleepy_hammy.gif | Bin 0 -> 1092 bytes .../mood/twotone/hamsters/smiling_hammy.gif | Bin 0 -> 1117 bytes .../img/mood/twotone/hamsters/sore_hammy.gif | Bin 0 -> 1155 bytes .../mood/twotone/hamsters/stressed_hammy.gif | Bin 0 -> 5379 bytes .../mood/twotone/hamsters/surprised_hammy.gif | Bin 0 -> 1114 bytes .../mood/twotone/hamsters/thirsty_hammy.gif | Bin 0 -> 1119 bytes .../twotone/hamsters/thoughtful_hammy.gif | Bin 0 -> 1180 bytes .../img/mood/twotone/hamsters/tired_hammy.gif | Bin 0 -> 1111 bytes .../img/mood/twotone/hamsters/wheel_hammy.gif | Bin 0 -> 3048 bytes .../mood/twotone/hamsters/wibble_hammy.gif | Bin 0 -> 751 bytes .../mood/twotone/hamsters/worried_hammy.gif | Bin 0 -> 1111 bytes local/htdocs/img/pencil.gif | Bin 0 -> 270 bytes local/htdocs/img/s2preview/boxer/boxer.jpg | Bin 0 -> 12699 bytes .../htdocs/img/s2preview/classic/classic.jpg | Bin 0 -> 21054 bytes .../img/s2preview/cleansimple/cleansimple.jpg | Bin 0 -> 20049 bytes .../img/s2preview/component/component.jpg | Bin 0 -> 9585 bytes .../digitalmultiplex/digitalmultiplex.jpg | Bin 0 -> 26558 bytes .../img/s2preview/generator/generator.jpg | Bin 0 -> 10141 bytes local/htdocs/img/s2preview/haven/haven.png | Bin 0 -> 16042 bytes .../img/s2preview/magazine/magazine.jpg | Bin 0 -> 17795 bytes .../htdocs/img/s2preview/notepad/notepad.jpg | Bin 0 -> 20276 bytes local/htdocs/img/s2preview/opal/opal.jpg | Bin 0 -> 13075 bytes .../htdocs/img/s2preview/punquin/punquin.jpg | Bin 0 -> 12215 bytes .../s2preview/sturdygesture/sturdygesture.jpg | Bin 0 -> 19735 bytes .../s2preview/tabularindent/tabularindent.jpg | Bin 0 -> 19223 bytes .../img/s2preview/variableflow/preview.jpg | Bin 0 -> 23817 bytes local/htdocs/img/userinfo-lj.gif | Bin 0 -> 258 bytes local/htdocs/img/userinfo-npj.gif | Bin 0 -> 140 bytes local/htdocs/img/userinfo.gif | Bin 0 -> 191 bytes local/htdocs/img/videoplaceholder.png | Bin 0 -> 656 bytes local/htdocs/import-enqueue.bml | 209 + local/htdocs/import-faq.bml | 81 + local/htdocs/import-queue.bml | 112 + local/htdocs/import.bml | 72 + local/htdocs/inc/legal-tos | 137 + local/htdocs/index.bml | 62 + local/htdocs/indexkoi.bml | 62 + local/htdocs/js/talkpost.js | 322 + local/htdocs/legal/guidelines.html | 97 + local/htdocs/legal/privacy.bml | 9 + local/htdocs/legal/tos-mini.html | 122 + local/htdocs/legal/tos.html | 137 + local/htdocs/legal/ustav.html | 90 + local/htdocs/lj-gate/index.bml | 305 + local/htdocs/lj-gate/lj-gate-faq.bml | 102 + local/htdocs/lj-gate/lj-gate-faq.html | 217 + local/htdocs/manage/siteopts.bml | 243 + local/htdocs/manage/tags.bml | 269 + local/htdocs/mobile/friends.bml | 96 + local/htdocs/mobile/index.bml | 42 + local/htdocs/mobile/login.bml | 70 + local/htdocs/mobile/post.bml | 105 + local/htdocs/modify.bml | 493 + local/htdocs/moodlist.bml | 269 + local/htdocs/news.bml | 23 + local/htdocs/openid/approve.bml | 83 + local/htdocs/openid/login.bml | 89 + local/htdocs/openid/options.bml | 96 + local/htdocs/paidaccounts/index.bml | 78 + local/htdocs/palimg/boxer/back.gif | Bin 0 -> 87 bytes local/htdocs/palimg/boxer/clear.gif | Bin 0 -> 43 bytes local/htdocs/palimg/boxer/forward.gif | Bin 0 -> 85 bytes local/htdocs/palimg/component/back.gif | Bin 0 -> 69 bytes local/htdocs/palimg/component/backarrow.gif | Bin 0 -> 86 bytes local/htdocs/palimg/component/bg.gif | Bin 0 -> 86 bytes local/htdocs/palimg/component/btn_edit.gif | Bin 0 -> 219 bytes .../htdocs/palimg/component/btn_memories.gif | Bin 0 -> 226 bytes local/htdocs/palimg/component/btn_tags.gif | Bin 0 -> 223 bytes .../palimg/component/btn_tellfriend.gif | Bin 0 -> 181 bytes local/htdocs/palimg/component/clear.gif | Bin 0 -> 43 bytes .../palimg/component/curve-bottom-left.gif | Bin 0 -> 56 bytes .../palimg/component/curve-bottom-right.gif | Bin 0 -> 57 bytes .../palimg/component/curve-top-left.gif | Bin 0 -> 58 bytes .../palimg/component/curve-top-right.gif | Bin 0 -> 57 bytes local/htdocs/palimg/component/forward.gif | Bin 0 -> 67 bytes .../htdocs/palimg/component/forwardarrow.gif | Bin 0 -> 86 bytes local/htdocs/palimg/component/top-bg.gif | Bin 0 -> 152 bytes local/htdocs/privacy.bml | 9 + local/htdocs/robots.txt | 28 + local/htdocs/robotsdisable.txt | 3 + local/htdocs/site/index.html | 174 + local/htdocs/site/sitemap.html | 177 + local/htdocs/stats.bml | 296 + local/htdocs/stats/.htaccess | 3 + local/htdocs/stats/latest-img.bml | 39 + local/htdocs/stats/latest-rss.bml | 111 + local/htdocs/stats/latest.bml | 90 + local/htdocs/stats/weblog-updates-xml.bml | 34 + local/htdocs/styles/create.bml | 21 + local/htdocs/styles/create_do.bml | 101 + local/htdocs/support/faq.bml | 64 + local/htdocs/support/index.html | 62 + local/htdocs/syn/index.bml | 355 + local/htdocs/talkmulti.bml | 95 + local/htdocs/talkpost.bml | 352 + local/htdocs/talkpost_do.bml | 286 + local/htdocs/talkread.bml | 668 + local/htdocs/talkscreen.bml | 199 + local/htdocs/tools/embedcontent.bml | 40 + local/htdocs/tools/memadd.bml | 321 + local/htdocs/tools/recent_comments.bml | 261 + local/htdocs/tools/search.bml | 46 + local/htdocs/tos-2006-06-06.html | 141 + local/htdocs/tos-2009-07-12.html | 130 + local/htdocs/tos-2013-02-11.html | 139 + local/htdocs/tos.html | 151 + local/htdocs/translatetoljruser.bml | 82 + local/htdocs/update.bml | 411 + local/htdocs/userinfo.bml | 1083 ++ local/htdocs/ustav.html | 90 + local/htdocs/zatychka.html | 1 + multicvs.conf | 55 + obsolete/bin/rlj2lj.pl | 405 + obsolete/cgi-bin/DBI/Role.pm.debug | 392 + obsolete/cgi-bin/LJ/Rewriteuser.pm | 133 + obsolete/htdocs/admin/redirectusers.bml | 113 + obsolete/htdocs/img/GJcommunity.gif | Bin 0 -> 163 bytes obsolete/htdocs/img/GJuserinfo.gif | Bin 0 -> 258 bytes obsolete/htdocs/img/NPJcommunity.gif | Bin 0 -> 305 bytes obsolete/htdocs/img/NPJuserinfo.gif | Bin 0 -> 140 bytes obsolete/htdocs/lj-gate/index.bml | 14 + obsolete/htdocs/lj-gate/rlj2lj.bml | 144 + obsolete/htdocs/lj-gate/rlj_delete.bml | 104 + obsolete/htdocs/paidaccounts/index.html | 10 + wcmtools/bin/apidoc.pl | 243 + wcmtools/bin/multicvs.pl | 268 + wcmtools/blobserver/lib/Apache/Blob.pm | 182 + wcmtools/blobserver/lib/modperl.pl | 16 + wcmtools/ddlockd/api/perl/DDLockClient.pm | 363 + wcmtools/ddlockd/api/perl/MANIFEST | 5 + wcmtools/ddlockd/api/perl/MANIFEST.SKIP | 11 + wcmtools/ddlockd/api/perl/Makefile.PL | 33 + wcmtools/ddlockd/api/perl/stresslock.pl | 57 + wcmtools/ddlockd/api/perl/t/00_require.t | 12 + wcmtools/ddlockd/api/perl/testlock.pl | 46 + wcmtools/ddlockd/server/ddlockd | 316 + wcmtools/dinsertd/server/dinsertd | 385 + wcmtools/diskchecker/diskchecker.pl | 269 + wcmtools/dmtpd/README.txt | 11 + wcmtools/dmtpd/api/perl/test.pl | 42 + wcmtools/dmtpd/server/dmtpd | 231 + wcmtools/gearman/dev/DMap.pm | 77 + wcmtools/gearman/dev/client.pl | 40 + wcmtools/gearman/dev/dmap-worker.pl | 76 + wcmtools/gearman/dev/dmap.pl | 13 + wcmtools/gearman/dev/test-gear.pl | 23 + wcmtools/gearman/dev/worker.pl | 76 + wcmtools/gearman/doc/overview.txt | 225 + wcmtools/gearman/lib/Gearman/Client.pm | 303 + wcmtools/gearman/lib/Gearman/JobStatus.pm | 20 + wcmtools/gearman/lib/Gearman/Objects.pm | 52 + wcmtools/gearman/lib/Gearman/Task.pm | 210 + wcmtools/gearman/lib/Gearman/Taskset.pm | 269 + wcmtools/gearman/lib/Gearman/Util.pm | 128 + wcmtools/gearman/lib/Gearman/Worker.pm | 366 + wcmtools/gearman/server/gearmand | 694 + wcmtools/gearman/t/00-use.t | 6 + wcmtools/gearman/t/10-all.t | 198 + wcmtools/gearman/t/worker.pl | 41 + wcmtools/lib/Apache/CompressClientFixup.pm | 55 + wcmtools/lib/DBI/Role.pm | 392 + wcmtools/lib/DBIx/StateKeeper.pm | 252 + wcmtools/lib/Danga-Daemon/Daemon.pm | 463 + wcmtools/lib/Danga-EXIF/EXIF.pm | 1100 ++ wcmtools/lib/Danga-Exceptions/MANIFEST | 4 + wcmtools/lib/Danga-Exceptions/MANIFEST.SKIP | 11 + wcmtools/lib/Danga-Exceptions/Makefile.PL | 33 + .../Danga-Exceptions/lib/Danga/Exceptions.pm | 1131 ++ wcmtools/lib/Danga-Exceptions/t/basic.t | 166 + wcmtools/lib/Danga-Socket/CHANGES | 56 + wcmtools/lib/Danga-Socket/MANIFEST | 9 + wcmtools/lib/Danga-Socket/MANIFEST.SKIP | 12 + wcmtools/lib/Danga-Socket/META.yml | 15 + wcmtools/lib/Danga-Socket/Makefile.PL | 35 + wcmtools/lib/Danga-Socket/Socket.pm | 1170 ++ wcmtools/lib/Danga-Socket/debian/changelog | 17 + wcmtools/lib/Danga-Socket/debian/compat | 1 + wcmtools/lib/Danga-Socket/debian/control | 13 + wcmtools/lib/Danga-Socket/debian/copyright | 26 + wcmtools/lib/Danga-Socket/debian/rules | 53 + wcmtools/lib/Danga-Socket/debian/watch | 3 + wcmtools/lib/Danga-Socket/t/00-use.t | 8 + wcmtools/lib/Danga-Socket/t/05-postloop.t | 24 + wcmtools/lib/Danga-Socket/t/10-events.t | 147 + wcmtools/lib/HTMLCleaner.pm | 119 + wcmtools/lib/LWPx-ParanoidAgent/ChangeLog | 21 + wcmtools/lib/LWPx-ParanoidAgent/MANIFEST | 7 + wcmtools/lib/LWPx-ParanoidAgent/Makefile.PL | 13 + .../lib/LWPx/ParanoidAgent.pm | 556 + .../lib/LWPx/Protocol/http_paranoid.pm | 428 + .../lib/LWPx/Protocol/https_paranoid.pm | 49 + wcmtools/lib/LWPx-ParanoidAgent/t/00-all.t | 207 + wcmtools/lib/MultiCVS.pm | 480 + wcmtools/lib/MySQL-BinLog/MANIFEST | 12 + wcmtools/lib/MySQL-BinLog/MANIFEST.SKIP | 11 + wcmtools/lib/MySQL-BinLog/Makefile.PL | 33 + wcmtools/lib/MySQL-BinLog/docs/log_event.h | 795 + wcmtools/lib/MySQL-BinLog/docs/log_event.ph | 101 + .../MySQL-BinLog/experiments/cpptokenizer.pl | 38 + wcmtools/lib/MySQL-BinLog/experiments/try.pl | 34 + wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog.pm | 244 + .../lib/Mysql/BinLog/Constants.pm | 105 + .../MySQL-BinLog/lib/Mysql/BinLog/Events.pm | 793 + .../MySQL-BinLog/lib/Mysql/BinLog/Header.pm | 158 + .../lib/MySQL-BinLog/lib/Mysql/BinLog/Net.pm | 207 + wcmtools/lib/S2/Color.pm | 162 + wcmtools/lib/S2/EXIF.pm | 135 + wcmtools/lib/SafeAgent.pm | 170 + wcmtools/memcached/AUTHORS | 2 + wcmtools/memcached/BUILD | 37 + wcmtools/memcached/CONTRIBUTORS | 48 + wcmtools/memcached/COPYING | 30 + wcmtools/memcached/ChangeLog | 178 + wcmtools/memcached/LICENSE | 30 + wcmtools/memcached/Makefile.am | 10 + wcmtools/memcached/NEWS | 1 + wcmtools/memcached/README | 22 + wcmtools/memcached/TODO | 8 + wcmtools/memcached/api/java/CHANGELOG.txt | 56 + wcmtools/memcached/api/java/PORTABILITY.txt | 18 + wcmtools/memcached/api/java/TODO.txt | 9 + .../com/danga/MemCached/MemCachedClient.java | 1219 ++ .../api/java/com/danga/MemCached/SockIO.java | 72 + wcmtools/memcached/api/java/dist.pl | 79 + wcmtools/memcached/api/java/memcachetest.java | 61 + wcmtools/memcached/api/perl/ChangeLog | 164 + wcmtools/memcached/api/perl/MANIFEST | 8 + wcmtools/memcached/api/perl/Makefile.PL | 13 + wcmtools/memcached/api/perl/Memcached.pm | 1164 ++ wcmtools/memcached/api/perl/README | 14 + wcmtools/memcached/api/perl/TODO | 3 + wcmtools/memcached/api/perl/t/use.t | 7 + wcmtools/memcached/api/php/ChangeLog | 45 + wcmtools/memcached/api/php/Documentation | 258 + .../memcached/api/php/MemCachedClient.inc.php | 1143 ++ wcmtools/memcached/api/php/dist.pl | 70 + wcmtools/memcached/api/python/ChangeLog | 16 + wcmtools/memcached/api/python/DISTNOTES | 3 + wcmtools/memcached/api/python/MANIFEST | 2 + wcmtools/memcached/api/python/PKG-INFO | 10 + wcmtools/memcached/api/python/memcache.py | 585 + wcmtools/memcached/api/python/setup.py | 12 + .../memcached/api/python/tests/pooltest.py | 28 + wcmtools/memcached/assoc.c | 186 + wcmtools/memcached/autogen.sh | 22 + wcmtools/memcached/configure.ac | 56 + wcmtools/memcached/doc/Makefile.am | 3 + wcmtools/memcached/doc/memcached.1 | 86 + wcmtools/memcached/doc/memory_management.txt | 83 + wcmtools/memcached/doc/protocol.txt | 389 + wcmtools/memcached/frontends/gtk2-perl/README | 2 + .../frontends/gtk2-perl/memcachedclient | 121 + wcmtools/memcached/items.c | 299 + wcmtools/memcached/memcached.c | 1554 ++ wcmtools/memcached/memcached.h | 212 + wcmtools/memcached/scripts/memcached-init | 59 + wcmtools/memcached/scripts/memcached-tool | 111 + wcmtools/memcached/scripts/start-memcached | 117 + wcmtools/memcached/slabs.c | 290 + wcmtools/memcached/test/stress-memcached.pl | 101 + wcmtools/memcached/website/_config.bml | 2 + wcmtools/memcached/website/apis.bml | 78 + wcmtools/memcached/website/download.bml | 18 + wcmtools/memcached/website/index.bml | 116 + wcmtools/memcached/website/memcached.css | 59 + wcmtools/memcached/website/memcached.look | 30 + wcmtools/memcached/website/news.bml | 44 + wcmtools/memcached/website/users.bml | 52 + wcmtools/mogilefs/api/perl/MANIFEST | 5 + wcmtools/mogilefs/api/perl/MANIFEST.SKIP | 14 + wcmtools/mogilefs/api/perl/META.yml | 13 + wcmtools/mogilefs/api/perl/Makefile.PL | 34 + wcmtools/mogilefs/api/perl/MogileFS.pm | 1317 ++ wcmtools/mogilefs/api/perl/debian/changelog | 5 + wcmtools/mogilefs/api/perl/debian/compat | 1 + wcmtools/mogilefs/api/perl/debian/control | 13 + wcmtools/mogilefs/api/perl/debian/copyright | 27 + wcmtools/mogilefs/api/perl/debian/rules | 53 + wcmtools/mogilefs/api/perl/debian/watch | 2 + wcmtools/mogilefs/api/perl/t/00use.t | 8 + wcmtools/mogilefs/devnotes/FIXME | 2 + wcmtools/mogilefs/devnotes/mounter.pl | 14 + wcmtools/mogilefs/devnotes/notes.txt | 46 + wcmtools/mogilefs/devnotes/perl-interface.txt | 102 + .../mogilefs/devnotes/sql-data-bradhome.txt | 13 + .../mogilefs/devnotes/sql-data-office.txt | 12 + .../mogilefs/devnotes/sql-data-simple.txt | 8 + wcmtools/mogilefs/devnotes/sql.txt | 154 + wcmtools/mogilefs/devnotes/todo.txt | 59 + wcmtools/mogilefs/server/MANIFEST | 5 + wcmtools/mogilefs/server/MANIFEST.SKIP | 13 + wcmtools/mogilefs/server/META.yml | 17 + wcmtools/mogilefs/server/Makefile.PL | 42 + wcmtools/mogilefs/server/conf/mogilefsd.conf | 10 + wcmtools/mogilefs/server/conf/mogstored.conf | 11 + wcmtools/mogilefs/server/debian/changelog | 5 + wcmtools/mogilefs/server/debian/compat | 1 + wcmtools/mogilefs/server/debian/control | 25 + wcmtools/mogilefs/server/debian/copyright | 27 + .../mogilefs/server/debian/mogilefsd.config | 26 + .../mogilefs/server/debian/mogilefsd.init | 91 + .../mogilefs/server/debian/mogilefsd.postinst | 33 + .../mogilefs/server/debian/mogilefsd.postrm | 15 + .../mogilefs/server/debian/mogilefsd.preinst | 24 + .../server/debian/mogilefsd.templates | 7 + .../mogilefs/server/debian/mogstored.config | 9 + .../mogilefs/server/debian/mogstored.init | 72 + .../mogilefs/server/debian/mogstored.postinst | 47 + .../mogilefs/server/debian/mogstored.postrm | 24 + .../server/debian/mogstored.templates | 5 + .../mogilefs/server/debian/po/POTFILES.in | 2 + .../mogilefs/server/debian/po/templates.pot | 64 + wcmtools/mogilefs/server/debian/rules | 80 + wcmtools/mogilefs/server/debian/watch | 2 + wcmtools/mogilefs/server/mogilefsd | 3037 +++ wcmtools/mogilefs/server/mogstored | 198 + wcmtools/mogilefs/utils/MANIFEST | 3 + wcmtools/mogilefs/utils/MANIFEST.SKIP | 13 + wcmtools/mogilefs/utils/Makefile.PL | 33 + wcmtools/mogilefs/utils/conf/mogtool.conf | 20 + wcmtools/mogilefs/utils/debian/changelog | 5 + wcmtools/mogilefs/utils/debian/compat | 1 + wcmtools/mogilefs/utils/debian/control | 13 + wcmtools/mogilefs/utils/debian/copyright | 25 + .../utils/debian/mogilefs-utils.postinst | 9 + .../utils/debian/mogilefs-utils.postrm | 9 + wcmtools/mogilefs/utils/debian/rules | 60 + wcmtools/mogilefs/utils/mogtool | 1316 ++ .../openid/perl/Net-OpenID-Consumer/ChangeLog | 127 + .../openid/perl/Net-OpenID-Consumer/MANIFEST | 9 + .../perl/Net-OpenID-Consumer/Makefile.PL | 17 + .../lib/Net/OpenID/Association.pm | 231 + .../lib/Net/OpenID/ClaimedIdentity.pm | 207 + .../lib/Net/OpenID/Consumer.pm | 947 + .../lib/Net/OpenID/VerifiedIdentity.pm | 268 + .../perl/Net-OpenID-Consumer/t/00-use.t | 9 + .../openid/perl/Net-OpenID-Server/ChangeLog | 60 + .../openid/perl/Net-OpenID-Server/MANIFEST | 7 + .../openid/perl/Net-OpenID-Server/Makefile.PL | 13 + .../lib/Net/OpenID/Server.pm | 1111 ++ .../openid/perl/Net-OpenID-Server/t/00-all.t | 130 + .../perl/Net-OpenID-Server/t/01-newproto.t | 318 + wcmtools/perlbal/CHANGES | 195 + wcmtools/perlbal/MANIFEST | 36 + wcmtools/perlbal/MANIFEST.SKIP | 14 + wcmtools/perlbal/META.yml | 16 + wcmtools/perlbal/Makefile.PL | 49 + wcmtools/perlbal/conf/nodelist.dat | 9 + wcmtools/perlbal/conf/perlbal.conf | 167 + wcmtools/perlbal/debian/changelog | 5 + wcmtools/perlbal/debian/compat | 1 + wcmtools/perlbal/debian/control | 30 + wcmtools/perlbal/debian/copyright | 25 + wcmtools/perlbal/debian/perlbal-doc.docs | 1 + wcmtools/perlbal/debian/perlbal.init | 73 + wcmtools/perlbal/debian/perlbal.postinst | 15 + wcmtools/perlbal/debian/perlbal.postrm | 12 + wcmtools/perlbal/debian/rules | 72 + wcmtools/perlbal/debian/watch | 2 + wcmtools/perlbal/doc/Classes.txt | 72 + wcmtools/perlbal/doc/Hooks.txt | 106 + wcmtools/perlbal/doc/README.txt | 10 + wcmtools/perlbal/doc/Reproxying.txt | 47 + wcmtools/perlbal/doc/todo.txt | 29 + wcmtools/perlbal/lib/Perlbal.pm | 864 + wcmtools/perlbal/lib/Perlbal/AIO.pm | 101 + wcmtools/perlbal/lib/Perlbal/BackendHTTP.pm | 570 + wcmtools/perlbal/lib/Perlbal/ClientHTTP.pm | 339 + .../perlbal/lib/Perlbal/ClientHTTPBase.pm | 480 + wcmtools/perlbal/lib/Perlbal/ClientManage.pm | 139 + wcmtools/perlbal/lib/Perlbal/ClientProxy.pm | 507 + wcmtools/perlbal/lib/Perlbal/HTTPHeaders.pm | 411 + .../perlbal/lib/Perlbal/Plugin/Highpri.pm | 124 + wcmtools/perlbal/lib/Perlbal/Plugin/Palimg.pm | 293 + wcmtools/perlbal/lib/Perlbal/Plugin/Queues.pm | 54 + wcmtools/perlbal/lib/Perlbal/Plugin/Stats.pm | 161 + wcmtools/perlbal/lib/Perlbal/Pool.pm | 328 + .../perlbal/lib/Perlbal/ReproxyManager.pm | 248 + wcmtools/perlbal/lib/Perlbal/Service.pm | 907 + wcmtools/perlbal/lib/Perlbal/Socket.pm | 279 + wcmtools/perlbal/lib/Perlbal/StatsListener.pm | 219 + wcmtools/perlbal/lib/Perlbal/TCPListener.pm | 95 + wcmtools/perlbal/lib/Perlbal/Test.pm | 134 + .../perlbal/lib/Perlbal/Test/WebClient.pm | 127 + .../perlbal/lib/Perlbal/Test/WebServer.pm | 114 + wcmtools/perlbal/perlbal | 76 + wcmtools/perlbal/t/00-use.t | 8 + wcmtools/perlbal/t/10-testharness.t | 10 + wcmtools/perlbal/t/12-headers.t | 38 + wcmtools/perlbal/t/15-webserver.t | 76 + wcmtools/perlbal/t/20-put.t | 108 + wcmtools/perlbal/t/30-reverseproxy.t | 51 + wcmtools/perlbal/test/helper-server.pl | 34 + wcmtools/s2/BUGS | 46 + wcmtools/s2/BUILD.txt | 4 + wcmtools/s2/S2.pm | 497 + wcmtools/s2/S2/BackendHTML.pm | 75 + wcmtools/s2/S2/BackendPerl.pm | 62 + wcmtools/s2/S2/Checker.pm | 367 + wcmtools/s2/S2/Compiler.pm | 48 + wcmtools/s2/S2/FilePos.pm | 37 + wcmtools/s2/S2/Indenter.pm | 43 + wcmtools/s2/S2/Layer.pm | 115 + wcmtools/s2/S2/Node.pm | 224 + wcmtools/s2/S2/NodeArguments.pm | 63 + wcmtools/s2/S2/NodeArrayLiteral.pm | 173 + wcmtools/s2/S2/NodeAssignExpr.pm | 101 + wcmtools/s2/S2/NodeClass.pm | 269 + wcmtools/s2/S2/NodeClassVarDecl.pm | 75 + wcmtools/s2/S2/NodeCondExpr.pm | 82 + wcmtools/s2/S2/NodeDeleteStmt.pm | 64 + wcmtools/s2/S2/NodeEqExpr.pm | 89 + wcmtools/s2/S2/NodeExpr.pm | 56 + wcmtools/s2/S2/NodeExprStmt.pm | 52 + wcmtools/s2/S2/NodeForeachStmt.pm | 134 + wcmtools/s2/S2/NodeFormals.pm | 135 + wcmtools/s2/S2/NodeFunction.pm | 393 + wcmtools/s2/S2/NodeIfStmt.pm | 144 + wcmtools/s2/S2/NodeIncExpr.pm | 88 + wcmtools/s2/S2/NodeLayerInfo.pm | 69 + wcmtools/s2/S2/NodeLogAndExpr.pm | 70 + wcmtools/s2/S2/NodeLogOrExpr.pm | 70 + wcmtools/s2/S2/NodeNamedType.pm | 53 + wcmtools/s2/S2/NodePrintStmt.pm | 82 + wcmtools/s2/S2/NodeProduct.pm | 101 + wcmtools/s2/S2/NodePropGroup.pm | 106 + wcmtools/s2/S2/NodeProperty.pm | 191 + wcmtools/s2/S2/NodePropertyPair.pm | 45 + wcmtools/s2/S2/NodeRange.pm | 78 + wcmtools/s2/S2/NodeRelExpr.pm | 106 + wcmtools/s2/S2/NodeReturnStmt.pm | 72 + wcmtools/s2/S2/NodeSet.pm | 101 + wcmtools/s2/S2/NodeStmt.pm | 60 + wcmtools/s2/S2/NodeStmtBlock.pm | 142 + wcmtools/s2/S2/NodeSum.pm | 124 + wcmtools/s2/S2/NodeTerm.pm | 666 + wcmtools/s2/S2/NodeText.pm | 59 + wcmtools/s2/S2/NodeType.pm | 56 + wcmtools/s2/S2/NodeUnaryExpr.pm | 84 + wcmtools/s2/S2/NodeUnnecessary.pm | 46 + wcmtools/s2/S2/NodeVarDecl.pm | 56 + wcmtools/s2/S2/NodeVarDeclStmt.pm | 94 + wcmtools/s2/S2/NodeVarRef.pm | 301 + wcmtools/s2/S2/OutputConsole.pm | 29 + wcmtools/s2/S2/OutputScalar.pm | 29 + wcmtools/s2/S2/Token.pm | 36 + wcmtools/s2/S2/TokenComment.pm | 40 + wcmtools/s2/S2/TokenIdent.pm | 57 + wcmtools/s2/S2/TokenIntegerLiteral.pm | 53 + wcmtools/s2/S2/TokenKeyword.pm | 50 + wcmtools/s2/S2/TokenPunct.pm | 90 + wcmtools/s2/S2/TokenStringLiteral.pm | 201 + wcmtools/s2/S2/TokenWhitespace.pm | 38 + wcmtools/s2/S2/Tokenizer.pm | 189 + wcmtools/s2/S2/Type.pm | 149 + wcmtools/s2/S2/Util.pm | 26 + wcmtools/s2/danga/s2/Backend.java | 32 + wcmtools/s2/danga/s2/BackendHTML.java | 69 + wcmtools/s2/danga/s2/BackendPerl.java | 67 + wcmtools/s2/danga/s2/BackendS2.java | 29 + wcmtools/s2/danga/s2/BufferedIndenter.java | 19 + wcmtools/s2/danga/s2/Checker.java | 367 + wcmtools/s2/danga/s2/DerItem.java | 22 + wcmtools/s2/danga/s2/FilePos.java | 24 + wcmtools/s2/danga/s2/Indenter.java | 49 + wcmtools/s2/danga/s2/Layer.java | 81 + wcmtools/s2/danga/s2/Node.java | 222 + wcmtools/s2/danga/s2/NodeArguments.java | 106 + wcmtools/s2/danga/s2/NodeArrayLiteral.java | 161 + wcmtools/s2/danga/s2/NodeAssignExpr.java | 87 + wcmtools/s2/danga/s2/NodeClass.java | 296 + wcmtools/s2/danga/s2/NodeClassVarDecl.java | 80 + wcmtools/s2/danga/s2/NodeCondExpr.java | 78 + wcmtools/s2/danga/s2/NodeDeleteStmt.java | 52 + wcmtools/s2/danga/s2/NodeEqExpr.java | 85 + wcmtools/s2/danga/s2/NodeExpr.java | 49 + wcmtools/s2/danga/s2/NodeExprStmt.java | 42 + wcmtools/s2/danga/s2/NodeForeachStmt.java | 136 + wcmtools/s2/danga/s2/NodeFormals.java | 148 + wcmtools/s2/danga/s2/NodeFunction.java | 364 + wcmtools/s2/danga/s2/NodeIfStmt.java | 169 + wcmtools/s2/danga/s2/NodeIncExpr.java | 70 + wcmtools/s2/danga/s2/NodeLayerInfo.java | 64 + wcmtools/s2/danga/s2/NodeLogAndExpr.java | 60 + wcmtools/s2/danga/s2/NodeLogOrExpr.java | 61 + wcmtools/s2/danga/s2/NodeNamedType.java | 48 + wcmtools/s2/danga/s2/NodePrintStmt.java | 66 + wcmtools/s2/danga/s2/NodeProduct.java | 89 + wcmtools/s2/danga/s2/NodeProperty.java | 189 + wcmtools/s2/danga/s2/NodePropertyPair.java | 40 + wcmtools/s2/danga/s2/NodeRange.java | 77 + wcmtools/s2/danga/s2/NodeRelExpr.java | 93 + wcmtools/s2/danga/s2/NodeReturnStmt.java | 63 + wcmtools/s2/danga/s2/NodeSet.java | 90 + wcmtools/s2/danga/s2/NodeStmt.java | 48 + wcmtools/s2/danga/s2/NodeStmtBlock.java | 152 + wcmtools/s2/danga/s2/NodeSum.java | 119 + wcmtools/s2/danga/s2/NodeTerm.java | 717 + wcmtools/s2/danga/s2/NodeText.java | 62 + wcmtools/s2/danga/s2/NodeType.java | 45 + wcmtools/s2/danga/s2/NodeUnaryExpr.java | 71 + wcmtools/s2/danga/s2/NodeUnnecessary.java | 31 + wcmtools/s2/danga/s2/NodeVarDecl.java | 55 + wcmtools/s2/danga/s2/NodeVarDeclStmt.java | 91 + wcmtools/s2/danga/s2/NodeVarRef.java | 356 + wcmtools/s2/danga/s2/Output.java | 22 + wcmtools/s2/danga/s2/OutputConsole.java | 38 + wcmtools/s2/danga/s2/OutputStringBuffer.java | 26 + wcmtools/s2/danga/s2/Scanner.java | 99 + wcmtools/s2/danga/s2/Token.java | 24 + wcmtools/s2/danga/s2/TokenComment.java | 35 + wcmtools/s2/danga/s2/TokenIdent.java | 82 + wcmtools/s2/danga/s2/TokenIntegerLiteral.java | 46 + wcmtools/s2/danga/s2/TokenKeyword.java | 70 + wcmtools/s2/danga/s2/TokenPunct.java | 247 + wcmtools/s2/danga/s2/TokenStringLiteral.java | 159 + wcmtools/s2/danga/s2/TokenWhitespace.java | 47 + wcmtools/s2/danga/s2/Tokenizer.java | 161 + wcmtools/s2/danga/s2/Type.java | 152 + wcmtools/s2/danga/s2/s2compile.java | 151 + wcmtools/s2/doc/database.txt | 47 + wcmtools/s2/doc/design_goals.txt | 58 + wcmtools/s2/doc/docbook/about.xml | 3 + wcmtools/s2/doc/docbook/appx.gfdl.xml | 411 + wcmtools/s2/doc/docbook/bookinfo.xml | 54 + wcmtools/s2/doc/docbook/caveats.xml | 6 + wcmtools/s2/doc/docbook/csp.xml | 172 + wcmtools/s2/doc/docbook/design.xml | 26 + wcmtools/s2/doc/docbook/entities.xml | 25 + wcmtools/s2/doc/docbook/faq.xml | 27 + wcmtools/s2/doc/docbook/history.xml | 10 + wcmtools/s2/doc/docbook/how.xml | 36 + wcmtools/s2/doc/docbook/index.xml | 27 + wcmtools/s2/doc/docbook/langref.xml | 654 + wcmtools/s2/doc/docbook/layers.xml | 154 + wcmtools/s2/doc/docbook/misc.xml | 8 + wcmtools/s2/doc/docbook/notes.txt | 29 + wcmtools/s2/doc/docbook/notes.xml | 10 + wcmtools/s2/doc/docbook/overview.xml | 7 + wcmtools/s2/doc/docbook/preface.xml | 10 + wcmtools/s2/doc/docbook/terms.xml | 24 + wcmtools/s2/doc/grammar.txt | 145 + wcmtools/s2/doc/language.txt | 45 + wcmtools/s2/doc/layerinfo.txt | 33 + wcmtools/s2/doc/layers.txt | 168 + wcmtools/s2/doc/overview.txt | 14 + wcmtools/s2/doc/properties.txt | 33 + wcmtools/s2/doc/versioning.txt | 17 + wcmtools/s2/makefile.jmk | 23 + wcmtools/s2/manifest.txt | 2 + wcmtools/s2/runtests.pl | 432 + wcmtools/s2/s2compile | 9 + wcmtools/s2/s2compile.pl | 192 + wcmtools/s2/tests/Arithmetic.s2 | 31 + wcmtools/s2/tests/Arithmetic.s2.out | 11 + wcmtools/s2/tests/Classes_1.s2 | 42 + wcmtools/s2/tests/Classes_1.s2.out | 1 + wcmtools/s2/tests/Classes_2.s2 | 44 + wcmtools/s2/tests/Classes_2.s2.out | 5 + wcmtools/s2/tests/Colors.s2 | 31 + wcmtools/s2/tests/Colors.s2.out | 2 + wcmtools/s2/tests/Colors_2b.s2 | 62 + wcmtools/s2/tests/Colors_2b.s2.out | 6 + wcmtools/s2/tests/Hello_World.s2 | 21 + wcmtools/s2/tests/Hello_World.s2.out | 7 + wcmtools/s2/tests/Obj_Interpolate.s2 | 51 + wcmtools/s2/tests/Obj_Interpolate.s2.out | 9 + wcmtools/s2/tests/Reserved_Idents.s2 | 28 + wcmtools/s2/tests/Reserved_Idents.s2.out | 1 + wcmtools/s2/tests/String_Object.s2 | 24 + wcmtools/s2/tests/String_Object.s2.out | 1 + wcmtools/s2/tests/arrayliterals.s2 | 47 + wcmtools/s2/tests/arrayliterals.s2.out | 5 + wcmtools/s2/tests/conditions.s2 | 87 + wcmtools/s2/tests/conditions.s2.out | 15 + wcmtools/s2/tests/defined.s2 | 40 + wcmtools/s2/tests/defined.s2.out | 4 + wcmtools/s2/tests/fail-syntax.s2 | 12 + wcmtools/s2/tests/fail-syntax.s2.err | 1 + wcmtools/s2/tests/if-assign.s2 | 17 + wcmtools/s2/tests/if-assign.s2.err | 1 + wcmtools/s2/tests/null-dispatch.s2 | 22 + wcmtools/s2/tests/null-dispatch.s2.err | 1 + wcmtools/s2/tests/null-dispatch.s2.out | 2 + wcmtools/s2/tests/null.s2 | 27 + wcmtools/s2/tests/null.s2.out | 4 + wcmtools/s2/tests/range.s2 | 18 + wcmtools/s2/tests/range.s2.out | 11 + wcmtools/s2/tests/readonly.s2 | 20 + wcmtools/s2/tests/readonly.s2.out | 1 + wcmtools/s2/tests/sizereverse.s2 | 31 + wcmtools/s2/tests/sizereverse.s2.out | 9 + wcmtools/s2/tests/super.s2 | 37 + wcmtools/s2/tests/super.s2.out | 5 + wcmtools/spud/bin/cmdshell | 100 + wcmtools/spud/bin/gatherer | 440 + wcmtools/spud/bin/plugins/config_generator.pl | 113 + wcmtools/spud/bin/plugins/memcached.pl | 63 + wcmtools/spud/bin/plugins/mogilefsd.pl | 64 + wcmtools/spud/bin/plugins/mogstored.pl | 74 + wcmtools/spud/bin/plugins/perlbal.pl | 65 + wcmtools/spud/bin/plugins/test.pl | 37 + wcmtools/spud/bin/replicator | 224 + wcmtools/spud/bin/rrd-storage | 132 + wcmtools/spud/bin/server | 465 + wcmtools/spud/bin/wrapper | 162 + wcmtools/spud/conf/authorized_keys | 1 + wcmtools/spud/conf/cmdshell.conf | 5 + wcmtools/spud/conf/sshd_config | 27 + wcmtools/spud/conf/stats-local.conf | 15 + wcmtools/spud/conf/stats.conf | 7 + wcmtools/spud/doc/README.txt | 67 + 4796 files changed, 506072 insertions(+) create mode 100644 .gitignore create mode 100755 bml/MANIFEST create mode 100755 bml/MANIFEST.SKIP create mode 100755 bml/Makefile.PL create mode 100755 bml/doc/bml-notes.txt create mode 100755 bml/doc/docbook/BUILD.txt create mode 100755 bml/doc/docbook/appx.gfdl.xml create mode 100755 bml/doc/docbook/book.ent create mode 100755 bml/doc/docbook/book.xml create mode 100755 bml/doc/docbook/bookinfo.xml create mode 100755 bml/doc/docbook/build.pl create mode 100755 bml/doc/docbook/core.xml create mode 100755 bml/doc/docbook/flags.xml create mode 100755 bml/doc/docbook/index.xml create mode 100755 bml/doc/docbook/preface.xml create mode 100755 bml/doc/docbook/tutorial.xml create mode 100755 bml/lib/Apache/BML.pm create mode 100755 bml/t/00_require.t create mode 100755 bml/t/10_simple.t create mode 100755 bml/t/20_render.t create mode 100755 bml/test/Pblocks/scheme.look create mode 100755 bml/test/_config.bml create mode 100755 bml/test/bml-profile.pl create mode 100755 bml/test/brads/_config.bml create mode 100755 bml/test/brads/scheme.look create mode 100755 bml/test/brads/test1.bml create mode 100755 bml/test/brads/test1.correct create mode 100755 bml/test/codeblocks/_config.bml create mode 100755 bml/test/codeblocks/carry-variables.bml create mode 100755 bml/test/codeblocks/carry-variables.correct create mode 100755 bml/test/codeblocks/complex1.bml create mode 100755 bml/test/codeblocks/complex1.correct create mode 100755 bml/test/codeblocks/complex2.bml create mode 100755 bml/test/codeblocks/complex2.correct create mode 100755 bml/test/codeblocks/re-expand.bml create mode 100755 bml/test/codeblocks/re-expand.correct create mode 100755 bml/test/codeblocks/scheme.look create mode 100755 bml/test/codeblocks/simple.bml create mode 100755 bml/test/codeblocks/simple.correct create mode 100755 bml/test/comments/_config.bml create mode 100755 bml/test/comments/basic.bml create mode 100755 bml/test/comments/basic.correct create mode 100755 bml/test/comments/rendered.bml create mode 100755 bml/test/comments/rendered.correct create mode 100755 bml/test/comments/scheme.look create mode 100755 bml/test/escape/_config.bml create mode 100755 bml/test/escape/ea.bml create mode 100755 bml/test/escape/ea.correct create mode 100755 bml/test/escape/eb.bml create mode 100755 bml/test/escape/eb.correct create mode 100755 bml/test/escape/eh.bml create mode 100755 bml/test/escape/eh.correct create mode 100755 bml/test/escape/eu.bml create mode 100755 bml/test/escape/eu.correct create mode 100755 bml/test/escape/scheme.look create mode 100755 bml/test/fake_root/_config.bml create mode 100755 bml/test/fake_root/bluewhite.look create mode 100755 bml/test/fake_root/bml-simple.bml create mode 100755 bml/test/fake_root/bml-simple.correct create mode 100755 bml/test/fake_root/bml-test.bml create mode 100755 bml/test/fake_root/bml-test.correct create mode 100755 bml/test/fake_root/global.look create mode 100755 bml/test/include/_config.bml create mode 100755 bml/test/include/loremipsum.txt create mode 100755 bml/test/include/plain.bml create mode 100755 bml/test/include/plain.correct create mode 100755 bml/test/include/scheme.look create mode 100755 bml/test/info/_config.bml create mode 100755 bml/test/info/localblocks.bml create mode 100755 bml/test/info/localblocks.correct create mode 100755 bml/test/info/package.bml create mode 100755 bml/test/info/package.correct create mode 100755 bml/test/info/scheme.look create mode 100755 bml/test/newtest.pl create mode 100755 bml/test/recursion/_config.bml create mode 100755 bml/test/recursion/infinite.bml create mode 100755 bml/test/recursion/infinite.correct create mode 100755 bml/test/recursion/nested.bml create mode 100755 bml/test/recursion/nested.correct create mode 100755 bml/test/recursion/scheme.look create mode 100755 bml/test/syntax-errors/_config.bml create mode 100755 bml/test/syntax-errors/dangling-tagopen.bml create mode 100755 bml/test/syntax-errors/dangling-tagopen.correct create mode 100755 bml/test/syntax-errors/no-close.bml create mode 100755 bml/test/syntax-errors/no-close.correct create mode 100755 bml/test/syntax-errors/onlyopen.bml create mode 100755 bml/test/syntax-errors/onlyopen.correct create mode 100755 bml/test/syntax-errors/scheme.look create mode 100755 bml/test/syntax-errors/spaces.bml create mode 100755 bml/test/syntax-errors/spaces.correct create mode 100755 bml/test/tutorial-example1/project.bml create mode 100755 bml/test/tutorial-example1/project.correct create mode 100755 bml/test/tutorial-example1/scheme.look create mode 100755 bml/test/tutorial-example2/index.bml create mode 100755 bml/test/tutorial-example2/index.correct create mode 100755 bml/test/tutorial-example2/scheme.look create mode 100755 bml/test/tutorial-example3/index.bml create mode 100755 bml/test/tutorial-example3/index.correct create mode 100755 bml/test/tutorial-example3/scheme.look create mode 100755 bml/test/tutorial-example4/index.bml create mode 100755 bml/test/tutorial-example4/index.correct create mode 100755 bml/test/tutorial-example4/scheme.look create mode 100755 bml/test/tutorial-example5/_config.bml create mode 100755 bml/test/tutorial-example5/readinglist.bml create mode 100755 bml/test/tutorial-example5/readinglist.correct create mode 100755 bml/test/tutorial-example5/scheme.look create mode 100755 bml/test/tutorial-example6/index.bml create mode 100755 bml/test/tutorial-example6/index.correct create mode 100755 bml/test/tutorial-example6/scheme.look create mode 100755 bml/test/tutorial-example7/index.bml create mode 100755 bml/test/tutorial-example7/index.correct create mode 100755 bml/test/tutorial-example7/scheme.look create mode 100755 bml/test/tutorial1/_config.bml create mode 100755 bml/test/tutorial1/index.bml create mode 100755 bml/test/tutorial1/index.correct create mode 100755 bml/test/tutorial1/scheme.look create mode 100755 bml/test/tutorial2/_config.bml create mode 100755 bml/test/tutorial2/index.bml create mode 100755 bml/test/tutorial2/index.correct create mode 100755 bml/test/tutorial2/scheme.look create mode 100644 images/mood/charitycam/aliens/angry.gif create mode 100644 images/mood/charitycam/aliens/anxious.gif create mode 100644 images/mood/charitycam/aliens/artistic.gif create mode 100644 images/mood/charitycam/aliens/awake.gif create mode 100644 images/mood/charitycam/aliens/bitchy.gif create mode 100644 images/mood/charitycam/aliens/blank.gif create mode 100644 images/mood/charitycam/aliens/cold.gif create mode 100644 images/mood/charitycam/aliens/confused.gif create mode 100644 images/mood/charitycam/aliens/determined.gif create mode 100644 images/mood/charitycam/aliens/dirty.gif create mode 100644 images/mood/charitycam/aliens/dorky.gif create mode 100644 images/mood/charitycam/aliens/drunk.gif create mode 100644 images/mood/charitycam/aliens/embarrased.gif create mode 100644 images/mood/charitycam/aliens/energetic.gif create mode 100644 images/mood/charitycam/aliens/envious.gif create mode 100644 images/mood/charitycam/aliens/flirty.gif create mode 100644 images/mood/charitycam/aliens/full.gif create mode 100644 images/mood/charitycam/aliens/gloomy.gif create mode 100644 images/mood/charitycam/aliens/happy.gif create mode 100644 images/mood/charitycam/aliens/high.gif create mode 100644 images/mood/charitycam/aliens/horny.gif create mode 100644 images/mood/charitycam/aliens/hot.gif create mode 100644 images/mood/charitycam/aliens/hungry.gif create mode 100644 images/mood/charitycam/aliens/indescribable.gif create mode 100644 images/mood/charitycam/aliens/index.html create mode 100644 images/mood/charitycam/aliens/irate.gif create mode 100644 images/mood/charitycam/aliens/loved.gif create mode 100644 images/mood/charitycam/aliens/nerdy.gif create mode 100644 images/mood/charitycam/aliens/okay.gif create mode 100644 images/mood/charitycam/aliens/restless.gif create mode 100644 images/mood/charitycam/aliens/sad.gif create mode 100644 images/mood/charitycam/aliens/sick.gif create mode 100644 images/mood/charitycam/aliens/silly.gif create mode 100644 images/mood/charitycam/aliens/sleepy.gif create mode 100644 images/mood/charitycam/aliens/sore.gif create mode 100644 images/mood/charitycam/aliens/stressed.gif create mode 100644 images/mood/charitycam/aliens/surprised.gif create mode 100644 images/mood/charitycam/aliens/thirsty.gif create mode 100644 images/mood/charitycam/aliens/thoughtful.gif create mode 100644 images/mood/charitycam/aliens/working.gif create mode 100644 images/mood/charitycam/bears/angry.gif create mode 100644 images/mood/charitycam/bears/artistic.gif create mode 100644 images/mood/charitycam/bears/awake.gif create mode 100644 images/mood/charitycam/bears/blank.gif create mode 100644 images/mood/charitycam/bears/cheerful.gif create mode 100644 images/mood/charitycam/bears/cold.gif create mode 100644 images/mood/charitycam/bears/curious.gif create mode 100644 images/mood/charitycam/bears/determined.gif create mode 100644 images/mood/charitycam/bears/dirty.gif create mode 100644 images/mood/charitycam/bears/drunk.gif create mode 100644 images/mood/charitycam/bears/envious.gif create mode 100644 images/mood/charitycam/bears/excited.gif create mode 100644 images/mood/charitycam/bears/full.gif create mode 100644 images/mood/charitycam/bears/gloomy.gif create mode 100644 images/mood/charitycam/bears/good.gif create mode 100644 images/mood/charitycam/bears/happy.gif create mode 100644 images/mood/charitycam/bears/high.gif create mode 100644 images/mood/charitycam/bears/hopeful.gif create mode 100644 images/mood/charitycam/bears/horny.gif create mode 100644 images/mood/charitycam/bears/hot.gif create mode 100644 images/mood/charitycam/bears/hungry.gif create mode 100644 images/mood/charitycam/bears/indescribable.gif create mode 100644 images/mood/charitycam/bears/index.html create mode 100644 images/mood/charitycam/bears/loved.gif create mode 100644 images/mood/charitycam/bears/nerdy.gif create mode 100644 images/mood/charitycam/bears/okay.gif create mode 100644 images/mood/charitycam/bears/sad.gif create mode 100644 images/mood/charitycam/bears/scared.gif create mode 100644 images/mood/charitycam/bears/shocked.gif create mode 100644 images/mood/charitycam/bears/sick.gif create mode 100644 images/mood/charitycam/bears/silly.gif create mode 100644 images/mood/charitycam/bears/stressed.gif create mode 100644 images/mood/charitycam/bears/thirsty.gif create mode 100644 images/mood/charitycam/bears/thoughtful.gif create mode 100644 images/mood/charitycam/bears/tired.gif create mode 100644 images/mood/charitycam/bears/working.gif create mode 100644 images/mood/charitycam/blackbox/angry.gif create mode 100644 images/mood/charitycam/blackbox/artistic.gif create mode 100644 images/mood/charitycam/blackbox/bouncy.gif create mode 100644 images/mood/charitycam/blackbox/cold.gif create mode 100644 images/mood/charitycam/blackbox/crazy.gif create mode 100644 images/mood/charitycam/blackbox/curious.gif create mode 100644 images/mood/charitycam/blackbox/determined.gif create mode 100644 images/mood/charitycam/blackbox/devilish.gif create mode 100644 images/mood/charitycam/blackbox/dirty.gif create mode 100644 images/mood/charitycam/blackbox/drunk.gif create mode 100644 images/mood/charitycam/blackbox/embarrassed.gif create mode 100644 images/mood/charitycam/blackbox/envy.gif create mode 100644 images/mood/charitycam/blackbox/gloomy.gif create mode 100644 images/mood/charitycam/blackbox/green.gif create mode 100644 images/mood/charitycam/blackbox/happy.gif create mode 100644 images/mood/charitycam/blackbox/hot.gif create mode 100644 images/mood/charitycam/blackbox/hungry.gif create mode 100644 images/mood/charitycam/blackbox/index.html create mode 100644 images/mood/charitycam/blackbox/loved.gif create mode 100644 images/mood/charitycam/blackbox/nerdy.gif create mode 100644 images/mood/charitycam/blackbox/okay.gif create mode 100644 images/mood/charitycam/blackbox/peaceful.gif create mode 100644 images/mood/charitycam/blackbox/relaxed.gif create mode 100644 images/mood/charitycam/blackbox/sad.gif create mode 100644 images/mood/charitycam/blackbox/scared.gif create mode 100644 images/mood/charitycam/blackbox/sore.gif create mode 100644 images/mood/charitycam/blackbox/suprised.gif create mode 100644 images/mood/charitycam/blackbox/thirsty.gif create mode 100644 images/mood/charitycam/blackbox/thoughtful.gif create mode 100644 images/mood/charitycam/blackbox/tired.gif create mode 100644 images/mood/charitycam/blackbox/working.gif create mode 100644 images/mood/charitycam/faces-animated/1.gif create mode 100644 images/mood/charitycam/faces-animated/10.gif create mode 100644 images/mood/charitycam/faces-animated/11.gif create mode 100644 images/mood/charitycam/faces-animated/12.gif create mode 100644 images/mood/charitycam/faces-animated/13.gif create mode 100644 images/mood/charitycam/faces-animated/14.gif create mode 100644 images/mood/charitycam/faces-animated/15.gif create mode 100644 images/mood/charitycam/faces-animated/16.gif create mode 100644 images/mood/charitycam/faces-animated/17.gif create mode 100644 images/mood/charitycam/faces-animated/18.gif create mode 100644 images/mood/charitycam/faces-animated/19.gif create mode 100644 images/mood/charitycam/faces-animated/2.gif create mode 100644 images/mood/charitycam/faces-animated/20.gif create mode 100644 images/mood/charitycam/faces-animated/21.gif create mode 100644 images/mood/charitycam/faces-animated/22.gif create mode 100644 images/mood/charitycam/faces-animated/23.gif create mode 100644 images/mood/charitycam/faces-animated/24.gif create mode 100644 images/mood/charitycam/faces-animated/25.gif create mode 100644 images/mood/charitycam/faces-animated/26.gif create mode 100644 images/mood/charitycam/faces-animated/27.gif create mode 100644 images/mood/charitycam/faces-animated/28.gif create mode 100644 images/mood/charitycam/faces-animated/29.gif create mode 100644 images/mood/charitycam/faces-animated/3.gif create mode 100644 images/mood/charitycam/faces-animated/30.gif create mode 100644 images/mood/charitycam/faces-animated/31.gif create mode 100644 images/mood/charitycam/faces-animated/32.gif create mode 100644 images/mood/charitycam/faces-animated/33.gif create mode 100644 images/mood/charitycam/faces-animated/34.gif create mode 100644 images/mood/charitycam/faces-animated/4.gif create mode 100644 images/mood/charitycam/faces-animated/5.gif create mode 100644 images/mood/charitycam/faces-animated/6.gif create mode 100644 images/mood/charitycam/faces-animated/7.gif create mode 100644 images/mood/charitycam/faces-animated/8.gif create mode 100644 images/mood/charitycam/faces-animated/9.gif create mode 100644 images/mood/charitycam/faces-animated/index.html create mode 100644 images/mood/charitycam/faces/1.gif create mode 100644 images/mood/charitycam/faces/10.gif create mode 100644 images/mood/charitycam/faces/11.gif create mode 100644 images/mood/charitycam/faces/12.gif create mode 100644 images/mood/charitycam/faces/13.gif create mode 100644 images/mood/charitycam/faces/14.gif create mode 100644 images/mood/charitycam/faces/15.gif create mode 100644 images/mood/charitycam/faces/16.gif create mode 100644 images/mood/charitycam/faces/17.gif create mode 100644 images/mood/charitycam/faces/18.gif create mode 100644 images/mood/charitycam/faces/19.gif create mode 100644 images/mood/charitycam/faces/2.gif create mode 100644 images/mood/charitycam/faces/20.gif create mode 100644 images/mood/charitycam/faces/21.gif create mode 100644 images/mood/charitycam/faces/22.gif create mode 100644 images/mood/charitycam/faces/23.gif create mode 100644 images/mood/charitycam/faces/24.gif create mode 100644 images/mood/charitycam/faces/25.gif create mode 100644 images/mood/charitycam/faces/26.gif create mode 100644 images/mood/charitycam/faces/27.gif create mode 100644 images/mood/charitycam/faces/28.gif create mode 100644 images/mood/charitycam/faces/29.gif create mode 100644 images/mood/charitycam/faces/3.gif create mode 100644 images/mood/charitycam/faces/30.gif create mode 100644 images/mood/charitycam/faces/31.gif create mode 100644 images/mood/charitycam/faces/32.gif create mode 100644 images/mood/charitycam/faces/33.gif create mode 100644 images/mood/charitycam/faces/34.gif create mode 100644 images/mood/charitycam/faces/4.gif create mode 100644 images/mood/charitycam/faces/5.gif create mode 100644 images/mood/charitycam/faces/6.gif create mode 100644 images/mood/charitycam/faces/7.gif create mode 100644 images/mood/charitycam/faces/8.gif create mode 100644 images/mood/charitycam/faces/9.gif create mode 100644 images/mood/charitycam/faces/index.html create mode 100644 images/mood/charitycam/flowers/angry.gif create mode 100644 images/mood/charitycam/flowers/artistic.gif create mode 100644 images/mood/charitycam/flowers/blank.gif create mode 100644 images/mood/charitycam/flowers/cold.gif create mode 100644 images/mood/charitycam/flowers/confused.gif create mode 100644 images/mood/charitycam/flowers/dirty.gif create mode 100644 images/mood/charitycam/flowers/drunk.gif create mode 100644 images/mood/charitycam/flowers/envious.gif create mode 100644 images/mood/charitycam/flowers/excited.gif create mode 100644 images/mood/charitycam/flowers/full.gif create mode 100644 images/mood/charitycam/flowers/gloomy.gif create mode 100644 images/mood/charitycam/flowers/goofy.gif create mode 100644 images/mood/charitycam/flowers/happy.gif create mode 100644 images/mood/charitycam/flowers/high.gif create mode 100644 images/mood/charitycam/flowers/horny.gif create mode 100644 images/mood/charitycam/flowers/hot.gif create mode 100644 images/mood/charitycam/flowers/indescribable.gif create mode 100644 images/mood/charitycam/flowers/index.html create mode 100644 images/mood/charitycam/flowers/loved.gif create mode 100644 images/mood/charitycam/flowers/nerdy.gif create mode 100644 images/mood/charitycam/flowers/okay.gif create mode 100644 images/mood/charitycam/flowers/pissed.gif create mode 100644 images/mood/charitycam/flowers/rejuvenated.gif create mode 100644 images/mood/charitycam/flowers/restless.gif create mode 100644 images/mood/charitycam/flowers/sad.gif create mode 100644 images/mood/charitycam/flowers/scared.gif create mode 100644 images/mood/charitycam/flowers/shocked.gif create mode 100644 images/mood/charitycam/flowers/sick.gif create mode 100644 images/mood/charitycam/flowers/silly.gif create mode 100644 images/mood/charitycam/flowers/sore.gif create mode 100644 images/mood/charitycam/flowers/stressed.gif create mode 100644 images/mood/charitycam/flowers/thirsty.gif create mode 100644 images/mood/charitycam/flowers/thoughtful.gif create mode 100644 images/mood/charitycam/flowers/tired.gif create mode 100644 images/mood/charitycam/frogs/angry.gif create mode 100644 images/mood/charitycam/frogs/artistic.gif create mode 100644 images/mood/charitycam/frogs/awake.gif create mode 100644 images/mood/charitycam/frogs/blank.gif create mode 100644 images/mood/charitycam/frogs/cold.gif create mode 100644 images/mood/charitycam/frogs/confused.gif create mode 100644 images/mood/charitycam/frogs/determined.gif create mode 100644 images/mood/charitycam/frogs/dirty.gif create mode 100644 images/mood/charitycam/frogs/drunk.gif create mode 100644 images/mood/charitycam/frogs/embarrassed.gif create mode 100644 images/mood/charitycam/frogs/energetic.gif create mode 100644 images/mood/charitycam/frogs/envious.gif create mode 100644 images/mood/charitycam/frogs/flirty.gif create mode 100644 images/mood/charitycam/frogs/full.gif create mode 100644 images/mood/charitycam/frogs/gloomy.gif create mode 100644 images/mood/charitycam/frogs/happy.gif create mode 100644 images/mood/charitycam/frogs/high.gif create mode 100644 images/mood/charitycam/frogs/hopeful.gif create mode 100644 images/mood/charitycam/frogs/horny.gif create mode 100644 images/mood/charitycam/frogs/hungry.gif create mode 100644 images/mood/charitycam/frogs/indescribable.gif create mode 100644 images/mood/charitycam/frogs/index.html create mode 100644 images/mood/charitycam/frogs/loved.gif create mode 100644 images/mood/charitycam/frogs/melancholy.gif create mode 100644 images/mood/charitycam/frogs/nauseated.gif create mode 100644 images/mood/charitycam/frogs/nerdy.gif create mode 100644 images/mood/charitycam/frogs/okay.gif create mode 100644 images/mood/charitycam/frogs/refreshed.gif create mode 100644 images/mood/charitycam/frogs/sad.gif create mode 100644 images/mood/charitycam/frogs/scared.gif create mode 100644 images/mood/charitycam/frogs/sick.gif create mode 100644 images/mood/charitycam/frogs/silly.gif create mode 100644 images/mood/charitycam/frogs/stressed.gif create mode 100644 images/mood/charitycam/frogs/thirsty.gif create mode 100644 images/mood/charitycam/frogs/thoughtful.gif create mode 100644 images/mood/charitycam/frogs/tired.gif create mode 100644 images/mood/charitycam/goth_boy/angry.gif create mode 100644 images/mood/charitycam/goth_boy/artistic.gif create mode 100644 images/mood/charitycam/goth_boy/awake.gif create mode 100644 images/mood/charitycam/goth_boy/blank.gif create mode 100644 images/mood/charitycam/goth_boy/bouncy.gif create mode 100644 images/mood/charitycam/goth_boy/cold.gif create mode 100644 images/mood/charitycam/goth_boy/confused.gif create mode 100644 images/mood/charitycam/goth_boy/determined.gif create mode 100644 images/mood/charitycam/goth_boy/devlish.gif create mode 100644 images/mood/charitycam/goth_boy/dirty.gif create mode 100644 images/mood/charitycam/goth_boy/drunk.gif create mode 100644 images/mood/charitycam/goth_boy/embarrased.gif create mode 100644 images/mood/charitycam/goth_boy/envious.gif create mode 100644 images/mood/charitycam/goth_boy/full.gif create mode 100644 images/mood/charitycam/goth_boy/gloomy.gif create mode 100644 images/mood/charitycam/goth_boy/happy.gif create mode 100644 images/mood/charitycam/goth_boy/high.gif create mode 100644 images/mood/charitycam/goth_boy/hot.gif create mode 100644 images/mood/charitycam/goth_boy/hungry.gif create mode 100644 images/mood/charitycam/goth_boy/index.html create mode 100644 images/mood/charitycam/goth_boy/loved.gif create mode 100644 images/mood/charitycam/goth_boy/nerdy.gif create mode 100644 images/mood/charitycam/goth_boy/okay.gif create mode 100644 images/mood/charitycam/goth_boy/sad.gif create mode 100644 images/mood/charitycam/goth_boy/scared.gif create mode 100644 images/mood/charitycam/goth_boy/shocked.gif create mode 100644 images/mood/charitycam/goth_boy/sick.gif create mode 100644 images/mood/charitycam/goth_boy/silly.gif create mode 100644 images/mood/charitycam/goth_boy/sleepy.gif create mode 100644 images/mood/charitycam/goth_boy/stressed.gif create mode 100644 images/mood/charitycam/goth_boy/thirsty.gif create mode 100644 images/mood/charitycam/goth_boy/thoughtful.gif create mode 100644 images/mood/charitycam/goth_boy/tired.gif create mode 100644 images/mood/charitycam/goth_boy/working.gif create mode 100644 images/mood/charitycam/goth_girl/angry.gif create mode 100644 images/mood/charitycam/goth_girl/artistic.gif create mode 100644 images/mood/charitycam/goth_girl/cold.gif create mode 100644 images/mood/charitycam/goth_girl/curious.gif create mode 100644 images/mood/charitycam/goth_girl/determined.gif create mode 100644 images/mood/charitycam/goth_girl/devious.gif create mode 100644 images/mood/charitycam/goth_girl/dirty.gif create mode 100644 images/mood/charitycam/goth_girl/drunk.gif create mode 100644 images/mood/charitycam/goth_girl/energetic.gif create mode 100644 images/mood/charitycam/goth_girl/envious.gif create mode 100644 images/mood/charitycam/goth_girl/full.gif create mode 100644 images/mood/charitycam/goth_girl/gloomy.gif create mode 100644 images/mood/charitycam/goth_girl/happy.gif create mode 100644 images/mood/charitycam/goth_girl/high.gif create mode 100644 images/mood/charitycam/goth_girl/hot.gif create mode 100644 images/mood/charitycam/goth_girl/hungry.gif create mode 100644 images/mood/charitycam/goth_girl/index.html create mode 100644 images/mood/charitycam/goth_girl/loved.gif create mode 100644 images/mood/charitycam/goth_girl/nerdy.gif create mode 100644 images/mood/charitycam/goth_girl/okay.gif create mode 100644 images/mood/charitycam/goth_girl/sad.gif create mode 100644 images/mood/charitycam/goth_girl/scared.gif create mode 100644 images/mood/charitycam/goth_girl/sick.gif create mode 100644 images/mood/charitycam/goth_girl/silly.gif create mode 100644 images/mood/charitycam/goth_girl/sleepy.gif create mode 100644 images/mood/charitycam/goth_girl/stressed.gif create mode 100644 images/mood/charitycam/goth_girl/surprised.gif create mode 100644 images/mood/charitycam/goth_girl/thirsty.gif create mode 100644 images/mood/charitycam/goth_girl/thoughtful.gif create mode 100644 images/mood/charitycam/goth_girl/working.gif create mode 100644 images/mood/charitycam/index.html create mode 100644 images/mood/charitycam/mice/angel.gif create mode 100644 images/mood/charitycam/mice/angry.gif create mode 100644 images/mood/charitycam/mice/artistic.gif create mode 100644 images/mood/charitycam/mice/blank.gif create mode 100644 images/mood/charitycam/mice/bouncy.gif create mode 100644 images/mood/charitycam/mice/cold.gif create mode 100644 images/mood/charitycam/mice/curious.gif create mode 100644 images/mood/charitycam/mice/determined.gif create mode 100644 images/mood/charitycam/mice/devilish.gif create mode 100644 images/mood/charitycam/mice/drunk.gif create mode 100644 images/mood/charitycam/mice/embarrassed.gif create mode 100644 images/mood/charitycam/mice/envious.gif create mode 100644 images/mood/charitycam/mice/full.gif create mode 100644 images/mood/charitycam/mice/gloomy.gif create mode 100644 images/mood/charitycam/mice/happy.gif create mode 100644 images/mood/charitycam/mice/high.gif create mode 100644 images/mood/charitycam/mice/hot.gif create mode 100644 images/mood/charitycam/mice/hungry.gif create mode 100644 images/mood/charitycam/mice/indescribable.gif create mode 100644 images/mood/charitycam/mice/index.html create mode 100644 images/mood/charitycam/mice/lethargic.gif create mode 100644 images/mood/charitycam/mice/loved.gif create mode 100644 images/mood/charitycam/mice/nerdy.gif create mode 100644 images/mood/charitycam/mice/sad.gif create mode 100644 images/mood/charitycam/mice/sick.gif create mode 100644 images/mood/charitycam/mice/silly.gif create mode 100644 images/mood/charitycam/mice/sleepy.gif create mode 100644 images/mood/charitycam/mice/sore.gif create mode 100644 images/mood/charitycam/mice/stressed.gif create mode 100644 images/mood/charitycam/mice/surprised.gif create mode 100644 images/mood/charitycam/mice/thirsty.gif create mode 100644 images/mood/charitycam/mice/thoughtful.gif create mode 100644 images/mood/charitycam/mice/worried.gif create mode 100644 images/mood/charitycam/stars/angry.gif create mode 100644 images/mood/charitycam/stars/artistic.gif create mode 100644 images/mood/charitycam/stars/awake.gif create mode 100644 images/mood/charitycam/stars/bitchy.gif create mode 100644 images/mood/charitycam/stars/blank.gif create mode 100644 images/mood/charitycam/stars/charitycam-star1.gif create mode 100644 images/mood/charitycam/stars/cold.gif create mode 100644 images/mood/charitycam/stars/confused.gif create mode 100644 images/mood/charitycam/stars/crazy.gif create mode 100644 images/mood/charitycam/stars/determined.gif create mode 100644 images/mood/charitycam/stars/devious.gif create mode 100644 images/mood/charitycam/stars/dirty.gif create mode 100644 images/mood/charitycam/stars/drunk.gif create mode 100644 images/mood/charitycam/stars/embarrassed.gif create mode 100644 images/mood/charitycam/stars/energetic.gif create mode 100644 images/mood/charitycam/stars/enthralled.gif create mode 100644 images/mood/charitycam/stars/envious.gif create mode 100644 images/mood/charitycam/stars/flirt.gif create mode 100644 images/mood/charitycam/stars/gloomy.gif create mode 100644 images/mood/charitycam/stars/happy.gif create mode 100644 images/mood/charitycam/stars/high.gif create mode 100644 images/mood/charitycam/stars/hot.gif create mode 100644 images/mood/charitycam/stars/hungry.gif create mode 100644 images/mood/charitycam/stars/indescribable.gif create mode 100644 images/mood/charitycam/stars/index.html create mode 100644 images/mood/charitycam/stars/lazy.gif create mode 100644 images/mood/charitycam/stars/nerdy.gif create mode 100644 images/mood/charitycam/stars/okay.gif create mode 100644 images/mood/charitycam/stars/peaceful.gif create mode 100644 images/mood/charitycam/stars/pessimistic.gif create mode 100644 images/mood/charitycam/stars/sad.gif create mode 100644 images/mood/charitycam/stars/scared.gif create mode 100644 images/mood/charitycam/stars/sick.gif create mode 100644 images/mood/charitycam/stars/silly.gif create mode 100644 images/mood/charitycam/stars/sore.gif create mode 100644 images/mood/charitycam/stars/stressed.gif create mode 100644 images/mood/charitycam/stars/surprised.gif create mode 100644 images/mood/charitycam/stars/thirsty.gif create mode 100644 images/mood/charitycam/stars/thoughtful.gif create mode 100644 images/mood/charitycam/stars/tired.gif create mode 100644 images/mood/charitycam/stars/working.gif create mode 100644 images/mood/charitycam/suns/angry.gif create mode 100644 images/mood/charitycam/suns/artistic.gif create mode 100644 images/mood/charitycam/suns/awake.gif create mode 100644 images/mood/charitycam/suns/blah.gif create mode 100644 images/mood/charitycam/suns/blank.gif create mode 100644 images/mood/charitycam/suns/cold.gif create mode 100644 images/mood/charitycam/suns/confused.gif create mode 100644 images/mood/charitycam/suns/determined.gif create mode 100644 images/mood/charitycam/suns/drunk.gif create mode 100644 images/mood/charitycam/suns/energetic.gif create mode 100644 images/mood/charitycam/suns/envious.gif create mode 100644 images/mood/charitycam/suns/examinate.gif create mode 100644 images/mood/charitycam/suns/full.gif create mode 100644 images/mood/charitycam/suns/gloomy.gif create mode 100644 images/mood/charitycam/suns/good.gif create mode 100644 images/mood/charitycam/suns/happy.gif create mode 100644 images/mood/charitycam/suns/high.gif create mode 100644 images/mood/charitycam/suns/horny.gif create mode 100644 images/mood/charitycam/suns/hot.gif create mode 100644 images/mood/charitycam/suns/hungry.gif create mode 100644 images/mood/charitycam/suns/indescribable.gif create mode 100644 images/mood/charitycam/suns/index.html create mode 100644 images/mood/charitycam/suns/loved.gif create mode 100644 images/mood/charitycam/suns/okay.gif create mode 100644 images/mood/charitycam/suns/sad.gif create mode 100644 images/mood/charitycam/suns/scared.gif create mode 100644 images/mood/charitycam/suns/sick.gif create mode 100644 images/mood/charitycam/suns/silly.gif create mode 100644 images/mood/charitycam/suns/sore.gif create mode 100644 images/mood/charitycam/suns/surprised.gif create mode 100644 images/mood/charitycam/suns/thirsty.gif create mode 100644 images/mood/charitycam/suns/thoughtful.gif create mode 100644 images/mood/charitycam/suns/tired.gif create mode 100644 images/mood/charitycam/suns/working.gif create mode 100644 images/mood/classic/angry.gif create mode 100644 images/mood/classic/biggrin.gif create mode 100644 images/mood/classic/blah.gif create mode 100644 images/mood/classic/blush.gif create mode 100755 images/mood/classic/clean.pl create mode 100644 images/mood/classic/confused.gif create mode 100644 images/mood/classic/confused2.gif create mode 100644 images/mood/classic/cool.gif create mode 100755 images/mood/classic/devious.gif create mode 100644 images/mood/classic/dizzy.gif create mode 100644 images/mood/classic/drunk.gif create mode 100644 images/mood/classic/eek.gif create mode 100644 images/mood/classic/energetic.gif create mode 100644 images/mood/classic/frown.gif create mode 100644 images/mood/classic/index.html create mode 100644 images/mood/classic/laugh.gif create mode 100644 images/mood/classic/sad.gif create mode 100644 images/mood/classic/shock.gif create mode 100644 images/mood/classic/sick.gif create mode 100644 images/mood/classic/smile.gif create mode 100644 images/mood/classic/thinking.gif create mode 100644 images/mood/classic/tired.gif create mode 100644 images/mood/classic/wink.gif create mode 100644 images/mood/ibrad/alien.gif create mode 100644 images/mood/ibrad/angry.gif create mode 100644 images/mood/ibrad/asleep.gif create mode 100644 images/mood/ibrad/biggrin.gif create mode 100644 images/mood/ibrad/bigsmile.gif create mode 100644 images/mood/ibrad/bigwink.gif create mode 100644 images/mood/ibrad/clam.gif create mode 100644 images/mood/ibrad/confused.gif create mode 100644 images/mood/ibrad/cool.gif create mode 100644 images/mood/ibrad/dead.gif create mode 100644 images/mood/ibrad/devil.gif create mode 100644 images/mood/ibrad/disbelief.gif create mode 100644 images/mood/ibrad/disgruntled.gif create mode 100644 images/mood/ibrad/embarrassed.gif create mode 100644 images/mood/ibrad/erked.gif create mode 100644 images/mood/ibrad/flirty.gif create mode 100644 images/mood/ibrad/frown.gif create mode 100644 images/mood/ibrad/googlyeyes.gif create mode 100644 images/mood/ibrad/hot.gif create mode 100644 images/mood/ibrad/index.html create mode 100644 images/mood/ibrad/laugh.gif create mode 100644 images/mood/ibrad/licklips.gif create mode 100644 images/mood/ibrad/lonely.gif create mode 100644 images/mood/ibrad/loved.gif create mode 100644 images/mood/ibrad/macfrown.gif create mode 100644 images/mood/ibrad/mactongue.gif create mode 100644 images/mood/ibrad/macwink.gif create mode 100644 images/mood/ibrad/naughty.gif create mode 100644 images/mood/ibrad/nerd.gif create mode 100644 images/mood/ibrad/ohcrap.gif create mode 100644 images/mood/ibrad/paranoid.gif create mode 100644 images/mood/ibrad/rolleyes.gif create mode 100644 images/mood/ibrad/rollingeyes.gif create mode 100644 images/mood/ibrad/rotate.gif create mode 100644 images/mood/ibrad/sleep.gif create mode 100644 images/mood/ibrad/smile.gif create mode 100755 images/mood/ibrad/sql.txt create mode 100644 images/mood/ibrad/switching.gif create mode 100644 images/mood/ibrad/talking.gif create mode 100644 images/mood/ibrad/tongue.gif create mode 100644 images/mood/ibrad/uhoh.gif create mode 100644 images/mood/ibrad/unhappy.gif create mode 100644 images/mood/ibrad/upsidedown.gif create mode 100644 images/mood/ibrad/wink.gif create mode 100644 images/mood/ibrad/yawn.gif create mode 100644 images/mood/index.html create mode 100644 images/mood/moonsis/amused.gif create mode 100644 images/mood/moonsis/angelic.gif create mode 100644 images/mood/moonsis/angry.gif create mode 100644 images/mood/moonsis/blue.gif create mode 100644 images/mood/moonsis/calm.gif create mode 100644 images/mood/moonsis/cold.gif create mode 100644 images/mood/moonsis/confused.gif create mode 100644 images/mood/moonsis/content.gif create mode 100644 images/mood/moonsis/curious.gif create mode 100644 images/mood/moonsis/depressed.gif create mode 100644 images/mood/moonsis/dorknerdy.gif create mode 100644 images/mood/moonsis/drained.gif create mode 100644 images/mood/moonsis/drunk.gif create mode 100644 images/mood/moonsis/embarrassed.gif create mode 100644 images/mood/moonsis/energetic.gif create mode 100644 images/mood/moonsis/envious.gif create mode 100644 images/mood/moonsis/exhausted.gif create mode 100644 images/mood/moonsis/filrty.gif create mode 100644 images/mood/moonsis/flirty.gif create mode 100644 images/mood/moonsis/full.gif create mode 100644 images/mood/moonsis/grumpy.gif create mode 100644 images/mood/moonsis/happy.gif create mode 100644 images/mood/moonsis/high.gif create mode 100644 images/mood/moonsis/horny.gif create mode 100644 images/mood/moonsis/hot.gif create mode 100644 images/mood/moonsis/hungry.gif create mode 100644 images/mood/moonsis/hyper.gif create mode 100644 images/mood/moonsis/indescribable.gif create mode 100644 images/mood/moonsis/index.html create mode 100644 images/mood/moonsis/lazyrelaxed.gif create mode 100644 images/mood/moonsis/lonely.gif create mode 100644 images/mood/moonsis/loved.gif create mode 100644 images/mood/moonsis/mischievous.gif create mode 100644 images/mood/moonsis/mischivious.gif create mode 100644 images/mood/moonsis/okay.gif create mode 100644 images/mood/moonsis/pensive.gif create mode 100644 images/mood/moonsis/pissedoff.gif create mode 100755 images/mood/moonsis/prepare.pl create mode 100644 images/mood/moonsis/relaxed.gif create mode 100644 images/mood/moonsis/relieved.gif create mode 100644 images/mood/moonsis/restless.gif create mode 100644 images/mood/moonsis/sad.gif create mode 100644 images/mood/moonsis/scared.gif create mode 100644 images/mood/moonsis/sick.gif create mode 100644 images/mood/moonsis/silly.gif create mode 100644 images/mood/moonsis/sleepy.gif create mode 100755 images/mood/moonsis/sqlstuff.txt create mode 100644 images/mood/moonsis/stars/green/achy_sg.gif create mode 100644 images/mood/moonsis/stars/green/angelic_sg.gif create mode 100644 images/mood/moonsis/stars/green/angry_sg.gif create mode 100644 images/mood/moonsis/stars/green/artistic_sg.gif create mode 100644 images/mood/moonsis/stars/green/awake_sg.gif create mode 100644 images/mood/moonsis/stars/green/blank_sg.gif create mode 100644 images/mood/moonsis/stars/green/bored_sg.gif create mode 100644 images/mood/moonsis/stars/green/busy_sg.gif create mode 100644 images/mood/moonsis/stars/green/cold_sg.gif create mode 100644 images/mood/moonsis/stars/green/confused_sg.gif create mode 100644 images/mood/moonsis/stars/green/dancing_sg.gif create mode 100644 images/mood/moonsis/stars/green/dirty_sg.gif create mode 100644 images/mood/moonsis/stars/green/drunk_sg.gif create mode 100644 images/mood/moonsis/stars/green/emberassed_sg.gif create mode 100644 images/mood/moonsis/stars/green/envious_sg.gif create mode 100644 images/mood/moonsis/stars/green/exhausted_sg.gif create mode 100644 images/mood/moonsis/stars/green/festive_sg.gif create mode 100644 images/mood/moonsis/stars/green/full_sg.gif create mode 100644 images/mood/moonsis/stars/green/grumpy_sg.gif create mode 100644 images/mood/moonsis/stars/green/happy_sg.gif create mode 100644 images/mood/moonsis/stars/green/horny_sg.gif create mode 100644 images/mood/moonsis/stars/green/hot_sg.gif create mode 100644 images/mood/moonsis/stars/green/hungry_sg.gif create mode 100644 images/mood/moonsis/stars/green/hyper_sg.gif create mode 100644 images/mood/moonsis/stars/green/indescribable_sg.gif create mode 100644 images/mood/moonsis/stars/green/index.html create mode 100644 images/mood/moonsis/stars/green/indifferent_sg.gif create mode 100644 images/mood/moonsis/stars/green/loved_sg.gif create mode 100644 images/mood/moonsis/stars/green/mellow_sg.gif create mode 100644 images/mood/moonsis/stars/green/mischivious_sg.gif create mode 100644 images/mood/moonsis/stars/green/nerdy_sg.gif create mode 100644 images/mood/moonsis/stars/green/pensive_sg.gif create mode 100644 images/mood/moonsis/stars/green/sad_sg.gif create mode 100644 images/mood/moonsis/stars/green/sexy_sg.gif create mode 100644 images/mood/moonsis/stars/green/sick_sg.gif create mode 100644 images/mood/moonsis/stars/green/silly_sg.gif create mode 100644 images/mood/moonsis/stars/green/singing_sg.gif create mode 100644 images/mood/moonsis/stars/green/sleepy_sg.gif create mode 100644 images/mood/moonsis/stars/green/sore_sg.gif create mode 100644 images/mood/moonsis/stars/green/stressed_sg.gif create mode 100644 images/mood/moonsis/stars/green/thirsty_sg.gif create mode 100644 images/mood/moonsis/stars/green/working_sg.gif create mode 100644 images/mood/moonsis/stars/index.html create mode 100644 images/mood/moonsis/stars/purple/achy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/angelic_sp.gif create mode 100644 images/mood/moonsis/stars/purple/angry_sp.gif create mode 100644 images/mood/moonsis/stars/purple/artistic_sp.gif create mode 100644 images/mood/moonsis/stars/purple/awake_sp.gif create mode 100644 images/mood/moonsis/stars/purple/blank_sp.gif create mode 100644 images/mood/moonsis/stars/purple/bored_sp.gif create mode 100644 images/mood/moonsis/stars/purple/cold_sp.gif create mode 100644 images/mood/moonsis/stars/purple/confused_sp.gif create mode 100644 images/mood/moonsis/stars/purple/content_sp.gif create mode 100644 images/mood/moonsis/stars/purple/dancing_sp.gif create mode 100644 images/mood/moonsis/stars/purple/dirty_sp.gif create mode 100644 images/mood/moonsis/stars/purple/drunk_sp.gif create mode 100644 images/mood/moonsis/stars/purple/emberassed_sp.gif create mode 100644 images/mood/moonsis/stars/purple/envious_sp.gif create mode 100644 images/mood/moonsis/stars/purple/exhausted_sp.gif create mode 100644 images/mood/moonsis/stars/purple/festive_sp.gif create mode 100644 images/mood/moonsis/stars/purple/full_sp.gif create mode 100644 images/mood/moonsis/stars/purple/grumpy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/happy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/horny_sp.gif create mode 100644 images/mood/moonsis/stars/purple/hot_sp.gif create mode 100644 images/mood/moonsis/stars/purple/hungry_sp.gif create mode 100644 images/mood/moonsis/stars/purple/hyper_sp.gif create mode 100644 images/mood/moonsis/stars/purple/indescribable_sp.gif create mode 100644 images/mood/moonsis/stars/purple/index.html create mode 100644 images/mood/moonsis/stars/purple/indifferent_sp.gif create mode 100644 images/mood/moonsis/stars/purple/loved_sp.gif create mode 100644 images/mood/moonsis/stars/purple/mellow_sp.gif create mode 100644 images/mood/moonsis/stars/purple/mischivious_sp.gif create mode 100644 images/mood/moonsis/stars/purple/nerdy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/pensive_sp.gif create mode 100644 images/mood/moonsis/stars/purple/sad_sp.gif create mode 100644 images/mood/moonsis/stars/purple/sexy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/sick_sp.gif create mode 100644 images/mood/moonsis/stars/purple/silly_sp.gif create mode 100644 images/mood/moonsis/stars/purple/singing_sp.gif create mode 100644 images/mood/moonsis/stars/purple/sleepy_sp.gif create mode 100644 images/mood/moonsis/stars/purple/sore_sp.gif create mode 100644 images/mood/moonsis/stars/purple/stressed_sp.gif create mode 100644 images/mood/moonsis/stars/purple/thirsty_sp.gif create mode 100644 images/mood/moonsis/stars/purple/working_sp.gif create mode 100644 images/mood/moonsis/stars/red/achy_sr.gif create mode 100644 images/mood/moonsis/stars/red/angelic_sr.gif create mode 100644 images/mood/moonsis/stars/red/angry_sr.gif create mode 100644 images/mood/moonsis/stars/red/artistic_sr.gif create mode 100644 images/mood/moonsis/stars/red/awake_sr.gif create mode 100644 images/mood/moonsis/stars/red/blank_sr.gif create mode 100644 images/mood/moonsis/stars/red/bored_sr.gif create mode 100644 images/mood/moonsis/stars/red/cold_sr.gif create mode 100644 images/mood/moonsis/stars/red/confused_sr.gif create mode 100644 images/mood/moonsis/stars/red/dancing_sr.gif create mode 100644 images/mood/moonsis/stars/red/dirty_sr.gif create mode 100644 images/mood/moonsis/stars/red/drunk_sr.gif create mode 100644 images/mood/moonsis/stars/red/emberassed_sr.gif create mode 100644 images/mood/moonsis/stars/red/envious_sr.gif create mode 100644 images/mood/moonsis/stars/red/exhausted_sr.gif create mode 100644 images/mood/moonsis/stars/red/festive_sr.gif create mode 100644 images/mood/moonsis/stars/red/full_sr.gif create mode 100644 images/mood/moonsis/stars/red/grumpy_sr.gif create mode 100644 images/mood/moonsis/stars/red/happy_sr.gif create mode 100644 images/mood/moonsis/stars/red/horny_sr.gif create mode 100644 images/mood/moonsis/stars/red/hot_sr.gif create mode 100644 images/mood/moonsis/stars/red/hungry_sr.gif create mode 100644 images/mood/moonsis/stars/red/hyper_sr.gif create mode 100644 images/mood/moonsis/stars/red/indescribable_sr.gif create mode 100644 images/mood/moonsis/stars/red/index.html create mode 100644 images/mood/moonsis/stars/red/indifferent_sr.gif create mode 100644 images/mood/moonsis/stars/red/loved_sr.gif create mode 100644 images/mood/moonsis/stars/red/mellow_sr.gif create mode 100644 images/mood/moonsis/stars/red/mischivious_sr.gif create mode 100644 images/mood/moonsis/stars/red/nerdy_sr.gif create mode 100644 images/mood/moonsis/stars/red/pensive_sr.gif create mode 100644 images/mood/moonsis/stars/red/sad_sr.gif create mode 100644 images/mood/moonsis/stars/red/sexy_sr.gif create mode 100644 images/mood/moonsis/stars/red/sick_sr.gif create mode 100644 images/mood/moonsis/stars/red/silly_sr.gif create mode 100644 images/mood/moonsis/stars/red/singing_sr.gif create mode 100644 images/mood/moonsis/stars/red/sleepy_sr.gif create mode 100644 images/mood/moonsis/stars/red/sore_sr.gif create mode 100644 images/mood/moonsis/stars/red/stressed_sr.gif create mode 100644 images/mood/moonsis/stars/red/thirsty_sr.gif create mode 100644 images/mood/moonsis/stars/red/working_sr.gif create mode 100644 images/mood/moonsis/stars/yellow/achy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/angelic_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/angry_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/artistic_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/awake_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/blank_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/bored_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/cold_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/confused_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/content_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/dancing_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/dirty_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/drunk_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/emberassed_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/envious_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/exhausted_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/festive_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/full_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/grumpy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/happy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/horny_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/hot_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/hungry_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/hyper_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/indescribable_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/index.html create mode 100644 images/mood/moonsis/stars/yellow/indifferent_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/loved_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/mellow_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/mischivious_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/nerdy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/pensive_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/sad_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/sexy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/sick_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/silly_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/singing_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/sleepy_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/sore_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/stressed_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/thirsty_sy.gif create mode 100644 images/mood/moonsis/stars/yellow/working_sy.gif create mode 100644 images/mood/moonsis/stressed.gif create mode 100644 images/mood/moonsis/thoughtful.gif create mode 100644 images/mood/moonsis/tiredyawn.gif create mode 100644 images/mood/moonsis/upsidedown.gif create mode 100644 images/mood/moonsis/working.gif create mode 100644 images/mood/moonsis/worried.gif create mode 100644 images/mood/neko/index.html create mode 100644 images/mood/neko/kaokitty/accomplished.gif create mode 100644 images/mood/neko/kaokitty/aggravated.gif create mode 100644 images/mood/neko/kaokitty/amused.gif create mode 100644 images/mood/neko/kaokitty/angry.gif create mode 100644 images/mood/neko/kaokitty/annoyed.gif create mode 100644 images/mood/neko/kaokitty/anxious.gif create mode 100644 images/mood/neko/kaokitty/apathetic.gif create mode 100644 images/mood/neko/kaokitty/artistic.gif create mode 100644 images/mood/neko/kaokitty/awake.gif create mode 100644 images/mood/neko/kaokitty/bitchy.gif create mode 100644 images/mood/neko/kaokitty/blah.gif create mode 100644 images/mood/neko/kaokitty/blank.gif create mode 100644 images/mood/neko/kaokitty/bored.gif create mode 100644 images/mood/neko/kaokitty/bouncey.gif create mode 100644 images/mood/neko/kaokitty/busy.gif create mode 100644 images/mood/neko/kaokitty/calm.gif create mode 100644 images/mood/neko/kaokitty/cheerful.gif create mode 100644 images/mood/neko/kaokitty/chipper.gif create mode 100644 images/mood/neko/kaokitty/cold.gif create mode 100644 images/mood/neko/kaokitty/complacent.gif create mode 100644 images/mood/neko/kaokitty/confused.gif create mode 100644 images/mood/neko/kaokitty/contemplative.gif create mode 100644 images/mood/neko/kaokitty/content.gif create mode 100644 images/mood/neko/kaokitty/cranky.gif create mode 100644 images/mood/neko/kaokitty/crappy.gif create mode 100644 images/mood/neko/kaokitty/crazy.gif create mode 100644 images/mood/neko/kaokitty/creative.gif create mode 100644 images/mood/neko/kaokitty/crushed.gif create mode 100644 images/mood/neko/kaokitty/curious.gif create mode 100644 images/mood/neko/kaokitty/cynical.gif create mode 100644 images/mood/neko/kaokitty/defensive.gif create mode 100644 images/mood/neko/kaokitty/depressed.gif create mode 100644 images/mood/neko/kaokitty/determined.gif create mode 100644 images/mood/neko/kaokitty/devious.gif create mode 100644 images/mood/neko/kaokitty/dirty.gif create mode 100644 images/mood/neko/kaokitty/disappointed.gif create mode 100644 images/mood/neko/kaokitty/discontent.gif create mode 100644 images/mood/neko/kaokitty/distressed.gif create mode 100644 images/mood/neko/kaokitty/ditzy.gif create mode 100644 images/mood/neko/kaokitty/dorky.gif create mode 100644 images/mood/neko/kaokitty/drained.gif create mode 100644 images/mood/neko/kaokitty/drunk.gif create mode 100644 images/mood/neko/kaokitty/ecstatic.gif create mode 100644 images/mood/neko/kaokitty/eh.gif create mode 100644 images/mood/neko/kaokitty/embarassed.gif create mode 100644 images/mood/neko/kaokitty/energetic.gif create mode 100644 images/mood/neko/kaokitty/enraged.gif create mode 100644 images/mood/neko/kaokitty/enthralled.gif create mode 100644 images/mood/neko/kaokitty/envious.gif create mode 100644 images/mood/neko/kaokitty/exanimate.gif create mode 100644 images/mood/neko/kaokitty/exausted.gif create mode 100644 images/mood/neko/kaokitty/excited.gif create mode 100644 images/mood/neko/kaokitty/flirty.gif create mode 100644 images/mood/neko/kaokitty/frustrated.gif create mode 100644 images/mood/neko/kaokitty/full.gif create mode 100644 images/mood/neko/kaokitty/geeky.gif create mode 100644 images/mood/neko/kaokitty/giddy.gif create mode 100644 images/mood/neko/kaokitty/giggly.gif create mode 100644 images/mood/neko/kaokitty/gloomy.gif create mode 100644 images/mood/neko/kaokitty/good.gif create mode 100644 images/mood/neko/kaokitty/grateful.gif create mode 100644 images/mood/neko/kaokitty/groggy.gif create mode 100644 images/mood/neko/kaokitty/grumpy.gif create mode 100644 images/mood/neko/kaokitty/guilty.gif create mode 100644 images/mood/neko/kaokitty/happy.gif create mode 100644 images/mood/neko/kaokitty/high.gif create mode 100644 images/mood/neko/kaokitty/hopeful.gif create mode 100644 images/mood/neko/kaokitty/horny.gif create mode 100644 images/mood/neko/kaokitty/hot.gif create mode 100644 images/mood/neko/kaokitty/hungry.gif create mode 100644 images/mood/neko/kaokitty/hungry2.gif create mode 100644 images/mood/neko/kaokitty/hyper.gif create mode 100644 images/mood/neko/kaokitty/impressed.gif create mode 100644 images/mood/neko/kaokitty/indescribable.gif create mode 100644 images/mood/neko/kaokitty/index.html create mode 100644 images/mood/neko/kaokitty/indifferent.gif create mode 100644 images/mood/neko/kaokitty/infuriated.gif create mode 100644 images/mood/neko/kaokitty/intimidated.gif create mode 100644 images/mood/neko/kaokitty/irate.gif create mode 100644 images/mood/neko/kaokitty/irritated.gif create mode 100644 images/mood/neko/kaokitty/jubilant.gif create mode 100644 images/mood/neko/kaokitty/kiss.gif create mode 100644 images/mood/neko/kaokitty/kisses.gif create mode 100644 images/mood/neko/kaokitty/lazy.gif create mode 100644 images/mood/neko/kaokitty/lethargic.gif create mode 100644 images/mood/neko/kaokitty/listless.gif create mode 100644 images/mood/neko/kaokitty/lonely.gif create mode 100644 images/mood/neko/kaokitty/love.gif create mode 100644 images/mood/neko/kaokitty/loved.gif create mode 100644 images/mood/neko/kaokitty/mad.gif create mode 100644 images/mood/neko/kaokitty/melancholy.gif create mode 100644 images/mood/neko/kaokitty/mellow.gif create mode 100644 images/mood/neko/kaokitty/mischievous.gif create mode 100644 images/mood/neko/kaokitty/moody.gif create mode 100644 images/mood/neko/kaokitty/morose.gif create mode 100644 images/mood/neko/kaokitty/musical.gif create mode 100644 images/mood/neko/kaokitty/naughty.gif create mode 100644 images/mood/neko/kaokitty/nauseated.gif create mode 100644 images/mood/neko/kaokitty/nerdy.gif create mode 100644 images/mood/neko/kaokitty/nostalgic.gif create mode 100644 images/mood/neko/kaokitty/numb.gif create mode 100644 images/mood/neko/kaokitty/okay.gif create mode 100644 images/mood/neko/kaokitty/optimistic.gif create mode 100644 images/mood/neko/kaokitty/peaceful.gif create mode 100644 images/mood/neko/kaokitty/pensive.gif create mode 100644 images/mood/neko/kaokitty/pessimistic.gif create mode 100644 images/mood/neko/kaokitty/pissed.gif create mode 100644 images/mood/neko/kaokitty/pleased.gif create mode 100644 images/mood/neko/kaokitty/predatory.gif create mode 100644 images/mood/neko/kaokitty/productive.gif create mode 100644 images/mood/neko/kaokitty/quiet.gif create mode 100644 images/mood/neko/kaokitty/quixotic.gif create mode 100644 images/mood/neko/kaokitty/recumbent.gif create mode 100644 images/mood/neko/kaokitty/refreshed.gif create mode 100644 images/mood/neko/kaokitty/rejected.gif create mode 100644 images/mood/neko/kaokitty/rejuvenated.gif create mode 100644 images/mood/neko/kaokitty/relaxed.gif create mode 100644 images/mood/neko/kaokitty/relieved.gif create mode 100644 images/mood/neko/kaokitty/restless.gif create mode 100644 images/mood/neko/kaokitty/rushed.gif create mode 100644 images/mood/neko/kaokitty/sad.gif create mode 100644 images/mood/neko/kaokitty/satisfied.gif create mode 100644 images/mood/neko/kaokitty/scared.gif create mode 100644 images/mood/neko/kaokitty/shocked.gif create mode 100644 images/mood/neko/kaokitty/sick.gif create mode 100644 images/mood/neko/kaokitty/silly.gif create mode 100644 images/mood/neko/kaokitty/singing.gif create mode 100644 images/mood/neko/kaokitty/sleepy.gif create mode 100644 images/mood/neko/kaokitty/snow.gif create mode 100644 images/mood/neko/kaokitty/sore.gif create mode 100644 images/mood/neko/kaokitty/stressed.gif create mode 100644 images/mood/neko/kaokitty/suprised.gif create mode 100644 images/mood/neko/kaokitty/sympathetic.gif create mode 100644 images/mood/neko/kaokitty/thankful.gif create mode 100644 images/mood/neko/kaokitty/thirsty.gif create mode 100644 images/mood/neko/kaokitty/thoughtful.gif create mode 100644 images/mood/neko/kaokitty/tired.gif create mode 100644 images/mood/neko/kaokitty/touched.gif create mode 100644 images/mood/neko/kaokitty/uncomfortable.gif create mode 100644 images/mood/neko/kaokitty/weird.gif create mode 100644 images/mood/neko/kaokitty/working.gif create mode 100644 images/mood/neko/kaokitty/worried.gif create mode 100644 images/mood/niaha/index.html create mode 100644 images/mood/niaha/kitty/ankangry.gif create mode 100644 images/mood/niaha/kitty/ankangryb.gif create mode 100644 images/mood/niaha/kitty/ankangryg.gif create mode 100644 images/mood/niaha/kitty/ankangryp.gif create mode 100644 images/mood/niaha/kitty/ankangryr.gif create mode 100644 images/mood/niaha/kitty/ankawake.gif create mode 100644 images/mood/niaha/kitty/ankawakeb.gif create mode 100644 images/mood/niaha/kitty/ankawakeg.gif create mode 100644 images/mood/niaha/kitty/ankawakep.gif create mode 100644 images/mood/niaha/kitty/ankawaker.gif create mode 100644 images/mood/niaha/kitty/ankcreate.gif create mode 100644 images/mood/niaha/kitty/ankcreateb.gif create mode 100644 images/mood/niaha/kitty/ankcreateg.gif create mode 100644 images/mood/niaha/kitty/ankcreatep.gif create mode 100644 images/mood/niaha/kitty/ankcreater.gif create mode 100644 images/mood/niaha/kitty/ankfood.gif create mode 100644 images/mood/niaha/kitty/ankfoodb.gif create mode 100644 images/mood/niaha/kitty/ankfoodg.gif create mode 100644 images/mood/niaha/kitty/ankfoodp.gif create mode 100644 images/mood/niaha/kitty/ankfoodr.gif create mode 100644 images/mood/niaha/kitty/ankgeek.gif create mode 100644 images/mood/niaha/kitty/ankgeekb.gif create mode 100644 images/mood/niaha/kitty/ankgeekg.gif create mode 100644 images/mood/niaha/kitty/ankgeekp.gif create mode 100644 images/mood/niaha/kitty/ankgeekr.gif create mode 100644 images/mood/niaha/kitty/ankhappy.gif create mode 100644 images/mood/niaha/kitty/ankhappyb.gif create mode 100644 images/mood/niaha/kitty/ankhappyg.gif create mode 100644 images/mood/niaha/kitty/ankhappyp.gif create mode 100644 images/mood/niaha/kitty/ankhappyr.gif create mode 100644 images/mood/niaha/kitty/ankhunt.gif create mode 100644 images/mood/niaha/kitty/ankhuntb.gif create mode 100644 images/mood/niaha/kitty/ankhuntg.gif create mode 100644 images/mood/niaha/kitty/ankhuntp.gif create mode 100644 images/mood/niaha/kitty/ankhuntr.gif create mode 100644 images/mood/niaha/kitty/ankhyper.gif create mode 100644 images/mood/niaha/kitty/ankhyperb.gif create mode 100644 images/mood/niaha/kitty/ankhyperg.gif create mode 100644 images/mood/niaha/kitty/ankhyperp.gif create mode 100644 images/mood/niaha/kitty/ankhyperr.gif create mode 100644 images/mood/niaha/kitty/ankitten.gif create mode 100644 images/mood/niaha/kitty/ankittenb.gif create mode 100644 images/mood/niaha/kitty/ankitteng.gif create mode 100644 images/mood/niaha/kitty/ankittenp.gif create mode 100644 images/mood/niaha/kitty/ankittenr.gif create mode 100644 images/mood/niaha/kitty/anksad.gif create mode 100644 images/mood/niaha/kitty/anksadb.gif create mode 100644 images/mood/niaha/kitty/anksadg.gif create mode 100644 images/mood/niaha/kitty/anksadp.gif create mode 100644 images/mood/niaha/kitty/anksadr.gif create mode 100644 images/mood/niaha/kitty/ankscared.gif create mode 100644 images/mood/niaha/kitty/ankscaredb.gif create mode 100644 images/mood/niaha/kitty/ankscaredg.gif create mode 100644 images/mood/niaha/kitty/ankscaredp.gif create mode 100644 images/mood/niaha/kitty/ankscaredr.gif create mode 100644 images/mood/niaha/kitty/anksleepy.gif create mode 100644 images/mood/niaha/kitty/anksleepyb.gif create mode 100644 images/mood/niaha/kitty/anksleepyg.gif create mode 100644 images/mood/niaha/kitty/anksleepyp.gif create mode 100644 images/mood/niaha/kitty/anksleepyr.gif create mode 100644 images/mood/niaha/kitty/ankthink.gif create mode 100644 images/mood/niaha/kitty/ankthinkb.gif create mode 100644 images/mood/niaha/kitty/ankthinkg.gif create mode 100644 images/mood/niaha/kitty/ankthinkp.gif create mode 100644 images/mood/niaha/kitty/ankthinkr.gif create mode 100644 images/mood/niaha/kitty/anktired.gif create mode 100644 images/mood/niaha/kitty/anktiredb.gif create mode 100644 images/mood/niaha/kitty/anktiredg.gif create mode 100644 images/mood/niaha/kitty/anktiredp.gif create mode 100644 images/mood/niaha/kitty/anktiredr.gif create mode 100644 images/mood/niaha/kitty/ankwink.gif create mode 100644 images/mood/niaha/kitty/ankwinkb.gif create mode 100644 images/mood/niaha/kitty/ankwinkg.gif create mode 100644 images/mood/niaha/kitty/ankwinkp.gif create mode 100644 images/mood/niaha/kitty/ankwinkr.gif create mode 100644 images/mood/niaha/kitty/index.html create mode 100644 images/mood/nolegs/aggravated.gif create mode 100644 images/mood/nolegs/amused.gif create mode 100644 images/mood/nolegs/angry.gif create mode 100644 images/mood/nolegs/annoyed.gif create mode 100644 images/mood/nolegs/bored.gif create mode 100644 images/mood/nolegs/bounce.gif create mode 100644 images/mood/nolegs/calm.gif create mode 100755 images/mood/nolegs/clean.pl create mode 100644 images/mood/nolegs/complacent.gif create mode 100644 images/mood/nolegs/confused.gif create mode 100644 images/mood/nolegs/content.gif create mode 100644 images/mood/nolegs/cranky.gif create mode 100644 images/mood/nolegs/crappy.gif create mode 100644 images/mood/nolegs/curious.gif create mode 100644 images/mood/nolegs/depressed.gif create mode 100644 images/mood/nolegs/determined.gif create mode 100644 images/mood/nolegs/disappointed.gif create mode 100644 images/mood/nolegs/discontent.gif create mode 100644 images/mood/nolegs/ditzy.gif create mode 100644 images/mood/nolegs/drained.gif create mode 100644 images/mood/nolegs/drunk.gif create mode 100644 images/mood/nolegs/energetic.gif create mode 100644 images/mood/nolegs/enraged.gif create mode 100644 images/mood/nolegs/enthralled.gif create mode 100644 images/mood/nolegs/excited.gif create mode 100644 images/mood/nolegs/exhausted.gif create mode 100644 images/mood/nolegs/flirty.gif create mode 100644 images/mood/nolegs/frustrated.gif create mode 100644 images/mood/nolegs/giggly.gif create mode 100644 images/mood/nolegs/gloomy.gif create mode 100644 images/mood/nolegs/groggy.gif create mode 100644 images/mood/nolegs/happy.gif create mode 100644 images/mood/nolegs/high.gif create mode 100644 images/mood/nolegs/horny.gif create mode 100644 images/mood/nolegs/hyper.gif create mode 100644 images/mood/nolegs/indescribable.gif create mode 100644 images/mood/nolegs/index.html create mode 100644 images/mood/nolegs/indifferent.gif create mode 100644 images/mood/nolegs/infuriated.gif create mode 100644 images/mood/nolegs/irate.gif create mode 100644 images/mood/nolegs/jubilant.gif create mode 100644 images/mood/nolegs/lazy.gif create mode 100644 images/mood/nolegs/lethargic.gif create mode 100644 images/mood/nolegs/listless.gif create mode 100644 images/mood/nolegs/lonely.gif create mode 100644 images/mood/nolegs/melancholy.gif create mode 100644 images/mood/nolegs/mellow.gif create mode 100644 images/mood/nolegs/mischievous.gif create mode 100644 images/mood/nolegs/moody.gif create mode 100644 images/mood/nolegs/morose.gif create mode 100644 images/mood/nolegs/nostalgic.gif create mode 100644 images/mood/nolegs/okay.gif create mode 100644 images/mood/nolegs/optimistic.gif create mode 100644 images/mood/nolegs/peaceful.gif create mode 100644 images/mood/nolegs/pensive.gif create mode 100644 images/mood/nolegs/pessimistic.gif create mode 100644 images/mood/nolegs/pissed.gif create mode 100644 images/mood/nolegs/recumbent.gif create mode 100644 images/mood/nolegs/refreshed.gif create mode 100644 images/mood/nolegs/rejuvenated.gif create mode 100644 images/mood/nolegs/relaxed.gif create mode 100644 images/mood/nolegs/relieved.gif create mode 100644 images/mood/nolegs/restless.gif create mode 100644 images/mood/nolegs/sad.gif create mode 100644 images/mood/nolegs/satisfied.gif create mode 100644 images/mood/nolegs/scared.gif create mode 100644 images/mood/nolegs/silly.gif create mode 100644 images/mood/nolegs/sleepy.gif create mode 100644 images/mood/nolegs/sore.gif create mode 100755 images/mood/nolegs/sqlstuff.txt create mode 100644 images/mood/nolegs/stressed.gif create mode 100644 images/mood/nolegs/thirsty.gif create mode 100644 images/mood/nolegs/thoughtful.gif create mode 100644 images/mood/nolegs/tired.gif create mode 100644 images/mood/nolegs/touched.gif create mode 100644 images/mood/nolegs/uncomfortable.gif create mode 100644 images/mood/opiummmm/foxies/angry.gif create mode 100644 images/mood/opiummmm/foxies/awake.gif create mode 100644 images/mood/opiummmm/foxies/confused.gif create mode 100644 images/mood/opiummmm/foxies/determined.gif create mode 100644 images/mood/opiummmm/foxies/discontent.gif create mode 100644 images/mood/opiummmm/foxies/energetic.gif create mode 100644 images/mood/opiummmm/foxies/enthralled.gif create mode 100644 images/mood/opiummmm/foxies/happy.gif create mode 100644 images/mood/opiummmm/foxies/indescribable.gif create mode 100644 images/mood/opiummmm/foxies/index.html create mode 100644 images/mood/opiummmm/foxies/nerdy.gif create mode 100644 images/mood/opiummmm/foxies/okay.gif create mode 100644 images/mood/opiummmm/foxies/sad.gif create mode 100644 images/mood/opiummmm/foxies/scared.gif create mode 100644 images/mood/opiummmm/foxies/thoughtful.gif create mode 100644 images/mood/opiummmm/foxies/working.gif create mode 100644 images/mood/opiummmm/index.html create mode 100644 images/mood/palefaces/aggravated.gif create mode 100644 images/mood/palefaces/amused.gif create mode 100644 images/mood/palefaces/angry.gif create mode 100644 images/mood/palefaces/annoyed.gif create mode 100644 images/mood/palefaces/anxious.gif create mode 100644 images/mood/palefaces/artistic.gif create mode 100644 images/mood/palefaces/awake.gif create mode 100644 images/mood/palefaces/bitchy.gif create mode 100644 images/mood/palefaces/blank.gif create mode 100644 images/mood/palefaces/bouncy.gif create mode 100644 images/mood/palefaces/busy.gif create mode 100644 images/mood/palefaces/cheerful.gif create mode 100644 images/mood/palefaces/cold.gif create mode 100644 images/mood/palefaces/complacent.gif create mode 100644 images/mood/palefaces/confused.gif create mode 100644 images/mood/palefaces/cranky.gif create mode 100644 images/mood/palefaces/crushed.gif create mode 100644 images/mood/palefaces/curious.gif create mode 100644 images/mood/palefaces/cynical.gif create mode 100644 images/mood/palefaces/depressed.gif create mode 100644 images/mood/palefaces/determined.gif create mode 100644 images/mood/palefaces/dirty.gif create mode 100644 images/mood/palefaces/drunk.gif create mode 100644 images/mood/palefaces/ecstatic.gif create mode 100644 images/mood/palefaces/embarrassed.gif create mode 100644 images/mood/palefaces/energetic.gif create mode 100644 images/mood/palefaces/enraged.gif create mode 100644 images/mood/palefaces/enthralled.gif create mode 100644 images/mood/palefaces/envious.gif create mode 100644 images/mood/palefaces/exhausted.gif create mode 100644 images/mood/palefaces/frustrated.gif create mode 100644 images/mood/palefaces/full.gif create mode 100644 images/mood/palefaces/gloomy.gif create mode 100644 images/mood/palefaces/good.gif create mode 100644 images/mood/palefaces/groggy.gif create mode 100644 images/mood/palefaces/grumpy.gif create mode 100644 images/mood/palefaces/happy.gif create mode 100644 images/mood/palefaces/high.gif create mode 100644 images/mood/palefaces/horny.gif create mode 100644 images/mood/palefaces/hot.gif create mode 100644 images/mood/palefaces/hungry.gif create mode 100644 images/mood/palefaces/hyper.gif create mode 100644 images/mood/palefaces/impressed.gif create mode 100644 images/mood/palefaces/indescribable.gif create mode 100644 images/mood/palefaces/index.html create mode 100644 images/mood/palefaces/lazy.gif create mode 100644 images/mood/palefaces/loved.gif create mode 100644 images/mood/palefaces/mischievous.gif create mode 100644 images/mood/palefaces/moody.gif create mode 100644 images/mood/palefaces/nerdy.gif create mode 100644 images/mood/palefaces/nostalgic.gif create mode 100644 images/mood/palefaces/okay.gif create mode 100644 images/mood/palefaces/predatory.gif create mode 100644 images/mood/palefaces/refreshed.gif create mode 100644 images/mood/palefaces/relaxed.gif create mode 100644 images/mood/palefaces/relieved.gif create mode 100644 images/mood/palefaces/rushed.gif create mode 100644 images/mood/palefaces/sad.gif create mode 100644 images/mood/palefaces/scared.gif create mode 100644 images/mood/palefaces/shocked.gif create mode 100644 images/mood/palefaces/sick.gif create mode 100644 images/mood/palefaces/silly.gif create mode 100644 images/mood/palefaces/sleepy.gif create mode 100644 images/mood/palefaces/sore.gif create mode 100644 images/mood/palefaces/surprised.gif create mode 100644 images/mood/palefaces/thirsty.gif create mode 100644 images/mood/palefaces/thoughtful.gif create mode 100644 images/mood/palefaces/worried.gif create mode 100644 images/mood/punquinheads/blue/angelic.gif create mode 100644 images/mood/punquinheads/blue/angry.gif create mode 100644 images/mood/punquinheads/blue/artistic.gif create mode 100644 images/mood/punquinheads/blue/awake.gif create mode 100644 images/mood/punquinheads/blue/blah.gif create mode 100644 images/mood/punquinheads/blue/blank.gif create mode 100644 images/mood/punquinheads/blue/brainy.gif create mode 100644 images/mood/punquinheads/blue/caffeinated.gif create mode 100644 images/mood/punquinheads/blue/cheerful.gif create mode 100644 images/mood/punquinheads/blue/cold.gif create mode 100644 images/mood/punquinheads/blue/confused.gif create mode 100644 images/mood/punquinheads/blue/curious.gif create mode 100644 images/mood/punquinheads/blue/determined.gif create mode 100644 images/mood/punquinheads/blue/dirty.gif create mode 100644 images/mood/punquinheads/blue/dizzy.gif create mode 100644 images/mood/punquinheads/blue/embarrassed.gif create mode 100644 images/mood/punquinheads/blue/envious.gif create mode 100644 images/mood/punquinheads/blue/excited.gif create mode 100644 images/mood/punquinheads/blue/flirty.gif create mode 100644 images/mood/punquinheads/blue/freakingout.gif create mode 100644 images/mood/punquinheads/blue/full.gif create mode 100644 images/mood/punquinheads/blue/giggly.gif create mode 100644 images/mood/punquinheads/blue/gloomy.gif create mode 100644 images/mood/punquinheads/blue/groggy.gif create mode 100644 images/mood/punquinheads/blue/grossedout.gif create mode 100644 images/mood/punquinheads/blue/grumpy.gif create mode 100644 images/mood/punquinheads/blue/happy.gif create mode 100644 images/mood/punquinheads/blue/hopeful.gif create mode 100644 images/mood/punquinheads/blue/hot.gif create mode 100644 images/mood/punquinheads/blue/hungry.gif create mode 100644 images/mood/punquinheads/blue/hungry2.gif create mode 100644 images/mood/punquinheads/blue/hyper.gif create mode 100644 images/mood/punquinheads/blue/indescribable.gif create mode 100644 images/mood/punquinheads/blue/index.html create mode 100644 images/mood/punquinheads/blue/indifferent.gif create mode 100644 images/mood/punquinheads/blue/lazy.gif create mode 100644 images/mood/punquinheads/blue/loved.gif create mode 100644 images/mood/punquinheads/blue/magical.gif create mode 100644 images/mood/punquinheads/blue/mellow.gif create mode 100644 images/mood/punquinheads/blue/moody.gif create mode 100644 images/mood/punquinheads/blue/musical.gif create mode 100644 images/mood/punquinheads/blue/naughty.gif create mode 100644 images/mood/punquinheads/blue/nerdy.gif create mode 100644 images/mood/punquinheads/blue/okay.gif create mode 100644 images/mood/punquinheads/blue/rockin.gif create mode 100644 images/mood/punquinheads/blue/sad.gif create mode 100644 images/mood/punquinheads/blue/sick.gif create mode 100644 images/mood/punquinheads/blue/silly.gif create mode 100644 images/mood/punquinheads/blue/sleepy.gif create mode 100644 images/mood/punquinheads/blue/smart.gif create mode 100644 images/mood/punquinheads/blue/sneezy.gif create mode 100644 images/mood/punquinheads/blue/sore.gif create mode 100644 images/mood/punquinheads/blue/spooky.gif create mode 100644 images/mood/punquinheads/blue/stressed.gif create mode 100644 images/mood/punquinheads/blue/stupid.gif create mode 100644 images/mood/punquinheads/blue/surprised.gif create mode 100644 images/mood/punquinheads/blue/thirsty.gif create mode 100644 images/mood/punquinheads/blue/thoughtful.gif create mode 100644 images/mood/punquinheads/blue/tired.gif create mode 100644 images/mood/punquinheads/blue/unfocused.gif create mode 100644 images/mood/punquinheads/blue/working.gif create mode 100644 images/mood/punquinheads/blue/worried.gif create mode 100644 images/mood/punquinheads/index.html create mode 100644 images/mood/punquinheads/pink/angelic.gif create mode 100644 images/mood/punquinheads/pink/angry.gif create mode 100644 images/mood/punquinheads/pink/artistic.gif create mode 100644 images/mood/punquinheads/pink/awake.gif create mode 100644 images/mood/punquinheads/pink/blah.gif create mode 100644 images/mood/punquinheads/pink/blank.gif create mode 100755 images/mood/punquinheads/pink/brainy.gif create mode 100755 images/mood/punquinheads/pink/caffeinated.gif create mode 100644 images/mood/punquinheads/pink/cheerful.gif create mode 100644 images/mood/punquinheads/pink/cold.gif create mode 100644 images/mood/punquinheads/pink/confused.gif create mode 100644 images/mood/punquinheads/pink/curious.gif create mode 100644 images/mood/punquinheads/pink/determined.gif create mode 100644 images/mood/punquinheads/pink/dirty.gif create mode 100644 images/mood/punquinheads/pink/dizzy.gif create mode 100644 images/mood/punquinheads/pink/embarrassed.gif create mode 100644 images/mood/punquinheads/pink/envious.gif create mode 100644 images/mood/punquinheads/pink/excited.gif create mode 100644 images/mood/punquinheads/pink/flirty.gif create mode 100644 images/mood/punquinheads/pink/freakingout.gif create mode 100644 images/mood/punquinheads/pink/full.gif create mode 100644 images/mood/punquinheads/pink/giggly.gif create mode 100644 images/mood/punquinheads/pink/gloomy.gif create mode 100644 images/mood/punquinheads/pink/groggy.gif create mode 100644 images/mood/punquinheads/pink/grossedout.gif create mode 100644 images/mood/punquinheads/pink/grumpy.gif create mode 100644 images/mood/punquinheads/pink/happy.gif create mode 100644 images/mood/punquinheads/pink/hopeful.gif create mode 100644 images/mood/punquinheads/pink/hot.gif create mode 100644 images/mood/punquinheads/pink/hungry.gif create mode 100644 images/mood/punquinheads/pink/hungry2.gif create mode 100644 images/mood/punquinheads/pink/hyper.gif create mode 100644 images/mood/punquinheads/pink/indescribable.gif create mode 100644 images/mood/punquinheads/pink/index.html create mode 100644 images/mood/punquinheads/pink/indifferent.gif create mode 100644 images/mood/punquinheads/pink/lazy.gif create mode 100644 images/mood/punquinheads/pink/loved.gif create mode 100644 images/mood/punquinheads/pink/magical.gif create mode 100644 images/mood/punquinheads/pink/mellow.gif create mode 100644 images/mood/punquinheads/pink/moody.gif create mode 100644 images/mood/punquinheads/pink/musical.gif create mode 100644 images/mood/punquinheads/pink/naughty.gif create mode 100644 images/mood/punquinheads/pink/nerdy.gif create mode 100644 images/mood/punquinheads/pink/okay.gif create mode 100644 images/mood/punquinheads/pink/rockin.gif create mode 100644 images/mood/punquinheads/pink/sad.gif create mode 100644 images/mood/punquinheads/pink/sick.gif create mode 100644 images/mood/punquinheads/pink/silly.gif create mode 100644 images/mood/punquinheads/pink/sleepy.gif create mode 100644 images/mood/punquinheads/pink/smart.gif create mode 100644 images/mood/punquinheads/pink/sneezy.gif create mode 100644 images/mood/punquinheads/pink/sore.gif create mode 100644 images/mood/punquinheads/pink/spooky.gif create mode 100644 images/mood/punquinheads/pink/stressed.gif create mode 100644 images/mood/punquinheads/pink/stupid.gif create mode 100644 images/mood/punquinheads/pink/surprised.gif create mode 100644 images/mood/punquinheads/pink/thirsty.gif create mode 100644 images/mood/punquinheads/pink/thoughtful.gif create mode 100644 images/mood/punquinheads/pink/tired.gif create mode 100644 images/mood/punquinheads/pink/unfocused.gif create mode 100644 images/mood/punquinheads/pink/working.gif create mode 100644 images/mood/punquinheads/pink/worried.gif create mode 100644 images/mood/roshi/index.html create mode 100644 images/mood/roshi/palefaces/aggravated.gif create mode 100644 images/mood/roshi/palefaces/amused.gif create mode 100644 images/mood/roshi/palefaces/angry.gif create mode 100644 images/mood/roshi/palefaces/annoyed.gif create mode 100644 images/mood/roshi/palefaces/anxious.gif create mode 100644 images/mood/roshi/palefaces/artistic.gif create mode 100644 images/mood/roshi/palefaces/awake.gif create mode 100644 images/mood/roshi/palefaces/bitchy.gif create mode 100644 images/mood/roshi/palefaces/blank.gif create mode 100644 images/mood/roshi/palefaces/bouncy.gif create mode 100644 images/mood/roshi/palefaces/busy.gif create mode 100644 images/mood/roshi/palefaces/cheerful.gif create mode 100644 images/mood/roshi/palefaces/cold.gif create mode 100644 images/mood/roshi/palefaces/complacent.gif create mode 100644 images/mood/roshi/palefaces/confused.gif create mode 100644 images/mood/roshi/palefaces/cranky.gif create mode 100644 images/mood/roshi/palefaces/crushed.gif create mode 100644 images/mood/roshi/palefaces/curious.gif create mode 100644 images/mood/roshi/palefaces/cynical.gif create mode 100644 images/mood/roshi/palefaces/depressed.gif create mode 100644 images/mood/roshi/palefaces/determined.gif create mode 100644 images/mood/roshi/palefaces/dirty.gif create mode 100644 images/mood/roshi/palefaces/drunk.gif create mode 100644 images/mood/roshi/palefaces/ecstatic.gif create mode 100644 images/mood/roshi/palefaces/embarrassed.gif create mode 100644 images/mood/roshi/palefaces/energetic.gif create mode 100644 images/mood/roshi/palefaces/enraged.gif create mode 100644 images/mood/roshi/palefaces/enthralled.gif create mode 100644 images/mood/roshi/palefaces/envious.gif create mode 100644 images/mood/roshi/palefaces/exhausted.gif create mode 100644 images/mood/roshi/palefaces/frustrated.gif create mode 100644 images/mood/roshi/palefaces/full.gif create mode 100644 images/mood/roshi/palefaces/gloomy.gif create mode 100644 images/mood/roshi/palefaces/good.gif create mode 100644 images/mood/roshi/palefaces/groggy.gif create mode 100644 images/mood/roshi/palefaces/grumpy.gif create mode 100644 images/mood/roshi/palefaces/happy.gif create mode 100644 images/mood/roshi/palefaces/high.gif create mode 100644 images/mood/roshi/palefaces/horny.gif create mode 100644 images/mood/roshi/palefaces/hot.gif create mode 100644 images/mood/roshi/palefaces/hungry.gif create mode 100644 images/mood/roshi/palefaces/hyper.gif create mode 100644 images/mood/roshi/palefaces/impressed.gif create mode 100644 images/mood/roshi/palefaces/indescribable.gif create mode 100644 images/mood/roshi/palefaces/index.html create mode 100644 images/mood/roshi/palefaces/lazy.gif create mode 100644 images/mood/roshi/palefaces/loved.gif create mode 100644 images/mood/roshi/palefaces/mischievous.gif create mode 100644 images/mood/roshi/palefaces/moody.gif create mode 100644 images/mood/roshi/palefaces/nerdy.gif create mode 100644 images/mood/roshi/palefaces/nostalgic.gif create mode 100644 images/mood/roshi/palefaces/okay.gif create mode 100644 images/mood/roshi/palefaces/predatory.gif create mode 100644 images/mood/roshi/palefaces/refreshed.gif create mode 100644 images/mood/roshi/palefaces/relaxed.gif create mode 100644 images/mood/roshi/palefaces/relieved.gif create mode 100644 images/mood/roshi/palefaces/rushed.gif create mode 100644 images/mood/roshi/palefaces/sad.gif create mode 100644 images/mood/roshi/palefaces/scared.gif create mode 100644 images/mood/roshi/palefaces/shocked.gif create mode 100644 images/mood/roshi/palefaces/sick.gif create mode 100644 images/mood/roshi/palefaces/silly.gif create mode 100644 images/mood/roshi/palefaces/sleepy.gif create mode 100644 images/mood/roshi/palefaces/sore.gif create mode 100644 images/mood/roshi/palefaces/surprised.gif create mode 100644 images/mood/roshi/palefaces/thirsty.gif create mode 100644 images/mood/roshi/palefaces/thoughtful.gif create mode 100644 images/mood/roshi/palefaces/worried.gif create mode 100644 images/mood/sam/aggravated.gif create mode 100644 images/mood/sam/amused.gif create mode 100644 images/mood/sam/angry.gif create mode 100644 images/mood/sam/annoyed.gif create mode 100644 images/mood/sam/anxious.gif create mode 100644 images/mood/sam/bored.gif create mode 100644 images/mood/sam/bouncy.gif create mode 100644 images/mood/sam/calm.gif create mode 100755 images/mood/sam/clean.pl create mode 100644 images/mood/sam/complacent.gif create mode 100644 images/mood/sam/confused.gif create mode 100644 images/mood/sam/content.gif create mode 100644 images/mood/sam/cranky.gif create mode 100644 images/mood/sam/crappy.gif create mode 100644 images/mood/sam/curious.gif create mode 100644 images/mood/sam/depressed.gif create mode 100644 images/mood/sam/determined.gif create mode 100644 images/mood/sam/disappointed.gif create mode 100644 images/mood/sam/discontent.gif create mode 100644 images/mood/sam/ditzy.gif create mode 100644 images/mood/sam/drained.gif create mode 100644 images/mood/sam/drunk.gif create mode 100644 images/mood/sam/embarrassed.gif create mode 100644 images/mood/sam/energetic.gif create mode 100644 images/mood/sam/enfuriated.gif create mode 100644 images/mood/sam/enraged.gif create mode 100644 images/mood/sam/enthralled.gif create mode 100644 images/mood/sam/envious.gif create mode 100644 images/mood/sam/exanimate.gif create mode 100644 images/mood/sam/excited.gif create mode 100644 images/mood/sam/exhausted.gif create mode 100644 images/mood/sam/flirty.gif create mode 100644 images/mood/sam/frustrated.gif create mode 100644 images/mood/sam/giggly.gif create mode 100644 images/mood/sam/gloomy.gif create mode 100644 images/mood/sam/groggy.gif create mode 100644 images/mood/sam/happy.gif create mode 100644 images/mood/sam/high.gif create mode 100644 images/mood/sam/hopeful.gif create mode 100644 images/mood/sam/horny.gif create mode 100644 images/mood/sam/hungry.gif create mode 100644 images/mood/sam/hyper.gif create mode 100644 images/mood/sam/indescribable.gif create mode 100644 images/mood/sam/index.html create mode 100644 images/mood/sam/indifferent.gif create mode 100644 images/mood/sam/infuriated.gif create mode 100644 images/mood/sam/irate.gif create mode 100644 images/mood/sam/jubilant.gif create mode 100644 images/mood/sam/lazy.gif create mode 100644 images/mood/sam/lethargic.gif create mode 100644 images/mood/sam/listless.gif create mode 100644 images/mood/sam/lonely.gif create mode 100644 images/mood/sam/melancholy.gif create mode 100644 images/mood/sam/mellow.gif create mode 100644 images/mood/sam/mischieveous.gif create mode 100644 images/mood/sam/mischievous.gif create mode 100644 images/mood/sam/moody.gif create mode 100644 images/mood/sam/morose.gif create mode 100644 images/mood/sam/nostalgic.gif create mode 100644 images/mood/sam/okay.gif create mode 100644 images/mood/sam/optimistic.gif create mode 100644 images/mood/sam/peaceful.gif create mode 100644 images/mood/sam/pensive.gif create mode 100644 images/mood/sam/pessimistic.gif create mode 100644 images/mood/sam/pissed.gif create mode 100644 images/mood/sam/recumbant.gif create mode 100644 images/mood/sam/refreshed.gif create mode 100644 images/mood/sam/rejuvenated.gif create mode 100644 images/mood/sam/relaxed.gif create mode 100644 images/mood/sam/relieved.gif create mode 100644 images/mood/sam/restless.gif create mode 100644 images/mood/sam/sad.gif create mode 100644 images/mood/sam/satisfied.gif create mode 100644 images/mood/sam/scared.gif create mode 100644 images/mood/sam/silly.gif create mode 100644 images/mood/sam/sleepy.gif create mode 100644 images/mood/sam/sore.gif create mode 100755 images/mood/sam/sqlstuff.txt create mode 100644 images/mood/sam/stressed.gif create mode 100644 images/mood/sam/thirsty.gif create mode 100644 images/mood/sam/thoughtful.gif create mode 100644 images/mood/sam/tired.gif create mode 100644 images/mood/sam/touched.gif create mode 100644 images/mood/sam/uncomfortable.gif create mode 100644 images/mood/square/b/aggravated.gif create mode 100644 images/mood/square/b/artistic.gif create mode 100644 images/mood/square/b/bored.gif create mode 100644 images/mood/square/b/cold.gif create mode 100644 images/mood/square/b/confused.gif create mode 100644 images/mood/square/b/content.gif create mode 100644 images/mood/square/b/cranky.gif create mode 100644 images/mood/square/b/curious.gif create mode 100644 images/mood/square/b/embarrassed.gif create mode 100644 images/mood/square/b/envious.gif create mode 100644 images/mood/square/b/evil.gif create mode 100644 images/mood/square/b/full.gif create mode 100644 images/mood/square/b/giggly.gif create mode 100644 images/mood/square/b/groggy.gif create mode 100644 images/mood/square/b/happy.gif create mode 100644 images/mood/square/b/hopeful.gif create mode 100644 images/mood/square/b/hot.gif create mode 100644 images/mood/square/b/hungry.gif create mode 100644 images/mood/square/b/hyper.gif create mode 100644 images/mood/square/b/index.html create mode 100644 images/mood/square/b/loved.gif create mode 100644 images/mood/square/b/mellow.gif create mode 100644 images/mood/square/b/nerdy.gif create mode 100644 images/mood/square/b/okay.gif create mode 100755 images/mood/square/b/prepare.pl create mode 100644 images/mood/square/b/sad.gif create mode 100644 images/mood/square/b/sick.gif create mode 100644 images/mood/square/b/silly.gif create mode 100644 images/mood/square/b/sleepy.gif create mode 100644 images/mood/square/b/stressed.gif create mode 100644 images/mood/square/b/tired.gif create mode 100644 images/mood/square/b/worried.gif create mode 100644 images/mood/square/index.html create mode 100644 images/mood/square/p/aggravated.gif create mode 100644 images/mood/square/p/artistic.gif create mode 100644 images/mood/square/p/bored.gif create mode 100644 images/mood/square/p/cold.gif create mode 100644 images/mood/square/p/confused.gif create mode 100644 images/mood/square/p/content.gif create mode 100644 images/mood/square/p/cranky.gif create mode 100644 images/mood/square/p/curious.gif create mode 100644 images/mood/square/p/embarrassed.gif create mode 100644 images/mood/square/p/envious.gif create mode 100644 images/mood/square/p/evil.gif create mode 100644 images/mood/square/p/full.gif create mode 100644 images/mood/square/p/giggly.gif create mode 100644 images/mood/square/p/groggy.gif create mode 100644 images/mood/square/p/happy.gif create mode 100644 images/mood/square/p/hopeful.gif create mode 100644 images/mood/square/p/hot.gif create mode 100644 images/mood/square/p/hungry.gif create mode 100644 images/mood/square/p/hyper.gif create mode 100644 images/mood/square/p/index.html create mode 100644 images/mood/square/p/loved.gif create mode 100644 images/mood/square/p/mellow.gif create mode 100644 images/mood/square/p/nerdy.gif create mode 100644 images/mood/square/p/okay.gif create mode 100644 images/mood/square/p/sad.gif create mode 100644 images/mood/square/p/sick.gif create mode 100644 images/mood/square/p/silly.gif create mode 100644 images/mood/square/p/sleepy.gif create mode 100644 images/mood/square/p/stressed.gif create mode 100644 images/mood/square/p/tired.gif create mode 100644 images/mood/square/p/worried.gif create mode 100644 images/mood/square/y/aggravated.gif create mode 100644 images/mood/square/y/artistic.gif create mode 100644 images/mood/square/y/bored.gif create mode 100644 images/mood/square/y/cold.gif create mode 100644 images/mood/square/y/confused.gif create mode 100644 images/mood/square/y/content.gif create mode 100644 images/mood/square/y/cranky.gif create mode 100644 images/mood/square/y/curious.gif create mode 100644 images/mood/square/y/embarrassed.gif create mode 100644 images/mood/square/y/envious.gif create mode 100644 images/mood/square/y/evil.gif create mode 100644 images/mood/square/y/full.gif create mode 100644 images/mood/square/y/giggly.gif create mode 100644 images/mood/square/y/groggy.gif create mode 100644 images/mood/square/y/happy.gif create mode 100644 images/mood/square/y/hopeful.gif create mode 100644 images/mood/square/y/hot.gif create mode 100644 images/mood/square/y/hungry.gif create mode 100644 images/mood/square/y/hyper.gif create mode 100644 images/mood/square/y/index.html create mode 100644 images/mood/square/y/loved.gif create mode 100644 images/mood/square/y/mellow.gif create mode 100644 images/mood/square/y/nerdy.gif create mode 100644 images/mood/square/y/okay.gif create mode 100644 images/mood/square/y/sad.gif create mode 100644 images/mood/square/y/sick.gif create mode 100644 images/mood/square/y/silly.gif create mode 100644 images/mood/square/y/sleepy.gif create mode 100644 images/mood/square/y/stressed.gif create mode 100644 images/mood/square/y/tired.gif create mode 100644 images/mood/square/y/worried.gif create mode 100644 images/mood/threnody/index.html create mode 100644 images/mood/threnody/mice/index.html create mode 100644 images/mood/threnody/mice/m-accomplished.gif create mode 100644 images/mood/threnody/mice/m-angry.gif create mode 100644 images/mood/threnody/mice/m-artistic.gif create mode 100644 images/mood/threnody/mice/m-awake.gif create mode 100644 images/mood/threnody/mice/m-blank.gif create mode 100644 images/mood/threnody/mice/m-calm.gif create mode 100644 images/mood/threnody/mice/m-cold.gif create mode 100644 images/mood/threnody/mice/m-confused.gif create mode 100644 images/mood/threnody/mice/m-curious.gif create mode 100644 images/mood/threnody/mice/m-determined.gif create mode 100644 images/mood/threnody/mice/m-devious.gif create mode 100644 images/mood/threnody/mice/m-drunk.gif create mode 100644 images/mood/threnody/mice/m-embarassed.gif create mode 100644 images/mood/threnody/mice/m-energetic.gif create mode 100644 images/mood/threnody/mice/m-enthralled.gif create mode 100644 images/mood/threnody/mice/m-envious.gif create mode 100644 images/mood/threnody/mice/m-gloomy.gif create mode 100644 images/mood/threnody/mice/m-good.gif create mode 100644 images/mood/threnody/mice/m-happy.gif create mode 100644 images/mood/threnody/mice/m-high.gif create mode 100644 images/mood/threnody/mice/m-horny.gif create mode 100644 images/mood/threnody/mice/m-hot.gif create mode 100644 images/mood/threnody/mice/m-hungry.gif create mode 100644 images/mood/threnody/mice/m-indescribable.gif create mode 100644 images/mood/threnody/mice/m-loved.gif create mode 100644 images/mood/threnody/mice/m-mellow.gif create mode 100644 images/mood/threnody/mice/m-nerdy.gif create mode 100644 images/mood/threnody/mice/m-okay.gif create mode 100644 images/mood/threnody/mice/m-optimistic.gif create mode 100644 images/mood/threnody/mice/m-sad.gif create mode 100644 images/mood/threnody/mice/m-scared.gif create mode 100644 images/mood/threnody/mice/m-shocked.gif create mode 100644 images/mood/threnody/mice/m-sick.gif create mode 100644 images/mood/threnody/mice/m-thoughtful.gif create mode 100644 images/mood/threnody/mice/m-tired.gif create mode 100644 images/mood/threnody/mice/m-working.gif create mode 100644 images/mood/threnody/mice/m-worried.gif create mode 100644 images/mood/xenia/greyblack/aggravated.gif create mode 100644 images/mood/xenia/greyblack/amused.gif create mode 100644 images/mood/xenia/greyblack/angry.gif create mode 100644 images/mood/xenia/greyblack/bitchy.gif create mode 100644 images/mood/xenia/greyblack/blank.gif create mode 100644 images/mood/xenia/greyblack/cold.gif create mode 100644 images/mood/xenia/greyblack/confident.gif create mode 100644 images/mood/xenia/greyblack/confused.gif create mode 100644 images/mood/xenia/greyblack/crazy.gif create mode 100644 images/mood/xenia/greyblack/crushed.gif create mode 100644 images/mood/xenia/greyblack/dirty.gif create mode 100644 images/mood/xenia/greyblack/drunk.gif create mode 100644 images/mood/xenia/greyblack/ecstatic.gif create mode 100644 images/mood/xenia/greyblack/embarrassed.gif create mode 100644 images/mood/xenia/greyblack/energetic.gif create mode 100644 images/mood/xenia/greyblack/enthralled.gif create mode 100644 images/mood/xenia/greyblack/flirty.gif create mode 100644 images/mood/xenia/greyblack/happy.gif create mode 100644 images/mood/xenia/greyblack/high.gif create mode 100644 images/mood/xenia/greyblack/horny.gif create mode 100644 images/mood/xenia/greyblack/hot.gif create mode 100644 images/mood/xenia/greyblack/hungry.gif create mode 100644 images/mood/xenia/greyblack/indescribable.gif create mode 100644 images/mood/xenia/greyblack/index.html create mode 100644 images/mood/xenia/greyblack/indifferent.gif create mode 100644 images/mood/xenia/greyblack/loved.gif create mode 100644 images/mood/xenia/greyblack/pensive.gif create mode 100644 images/mood/xenia/greyblack/rejected.gif create mode 100644 images/mood/xenia/greyblack/relaxed.gif create mode 100644 images/mood/xenia/greyblack/sad.gif create mode 100644 images/mood/xenia/greyblack/scared.gif create mode 100644 images/mood/xenia/greyblack/sick.gif create mode 100644 images/mood/xenia/greyblack/silly.gif create mode 100644 images/mood/xenia/greyblack/surprised.gif create mode 100644 images/mood/xenia/greyblack/thirsty.gif create mode 100644 images/mood/xenia/greyblack/thoughtful.gif create mode 100644 images/mood/xenia/greyblack/tired.gif create mode 100644 images/mood/xenia/index.html create mode 100644 images/mood/xenia/redblack/aggravated.gif create mode 100644 images/mood/xenia/redblack/amused.gif create mode 100644 images/mood/xenia/redblack/angry.gif create mode 100644 images/mood/xenia/redblack/bitchy.gif create mode 100644 images/mood/xenia/redblack/blank.gif create mode 100644 images/mood/xenia/redblack/cold.gif create mode 100644 images/mood/xenia/redblack/confident.gif create mode 100644 images/mood/xenia/redblack/confused.gif create mode 100644 images/mood/xenia/redblack/crazy.gif create mode 100644 images/mood/xenia/redblack/crushed.gif create mode 100644 images/mood/xenia/redblack/dirty.gif create mode 100644 images/mood/xenia/redblack/drunk.gif create mode 100644 images/mood/xenia/redblack/ecstatic.gif create mode 100644 images/mood/xenia/redblack/embarrassed.gif create mode 100644 images/mood/xenia/redblack/energetic.gif create mode 100644 images/mood/xenia/redblack/enthralled.gif create mode 100644 images/mood/xenia/redblack/exhausted.gif create mode 100644 images/mood/xenia/redblack/flirty.gif create mode 100644 images/mood/xenia/redblack/happy.gif create mode 100644 images/mood/xenia/redblack/high.gif create mode 100644 images/mood/xenia/redblack/horny.gif create mode 100644 images/mood/xenia/redblack/hot.gif create mode 100644 images/mood/xenia/redblack/hungry.gif create mode 100644 images/mood/xenia/redblack/indescribable.gif create mode 100644 images/mood/xenia/redblack/index.html create mode 100644 images/mood/xenia/redblack/indifferent.gif create mode 100644 images/mood/xenia/redblack/loved.gif create mode 100644 images/mood/xenia/redblack/pensive.gif create mode 100644 images/mood/xenia/redblack/rejected.gif create mode 100644 images/mood/xenia/redblack/relaxed.gif create mode 100644 images/mood/xenia/redblack/sad.gif create mode 100644 images/mood/xenia/redblack/scared.gif create mode 100644 images/mood/xenia/redblack/sick.gif create mode 100644 images/mood/xenia/redblack/silly.gif create mode 100644 images/mood/xenia/redblack/surprised.gif create mode 100644 images/mood/xenia/redblack/thirsty.gif create mode 100644 images/mood/xenia/redblack/thoughtful.gif create mode 100755 livejournal/Inline/README.txt create mode 100755 livejournal/README.txt create mode 100755 livejournal/bin/api2html.pl create mode 100755 livejournal/bin/checkconfig.pl create mode 100755 livejournal/bin/cvsreport.pl create mode 100755 livejournal/bin/dbcheck.pl create mode 100755 livejournal/bin/dbselectd.pl create mode 100755 livejournal/bin/deleteusers.pl create mode 100755 livejournal/bin/dumpsql.pl create mode 100755 livejournal/bin/fingerd.pl create mode 100755 livejournal/bin/interdoc.pl create mode 100755 livejournal/bin/jmk create mode 100755 livejournal/bin/lj-inline.pl create mode 100755 livejournal/bin/ljblockwatcher.pl create mode 100755 livejournal/bin/ljmaint.pl create mode 100755 livejournal/bin/ljsysban.pl create mode 100755 livejournal/bin/ljubackup.pl create mode 100755 livejournal/bin/ljumover.pl create mode 100755 livejournal/bin/logsummarize.pl create mode 100755 livejournal/bin/mailgated.pl create mode 100755 livejournal/bin/maint/bday.pl create mode 100755 livejournal/bin/maint/captcha.pl create mode 100755 livejournal/bin/maint/clean_caches.pl create mode 100755 livejournal/bin/maint/generic.pl create mode 100755 livejournal/bin/maint/stats.pl create mode 100755 livejournal/bin/maint/statspics.pl create mode 100755 livejournal/bin/maint/synsuck.pl create mode 100755 livejournal/bin/maint/taskinfo.txt create mode 100755 livejournal/bin/moveucluster.pl create mode 100755 livejournal/bin/moveuclusterd.pl create mode 100755 livejournal/bin/qbufferd.pl create mode 100755 livejournal/bin/statserv.pl create mode 100755 livejournal/bin/truncate-cluster.pl create mode 100755 livejournal/bin/upgrading/base-data.sql create mode 100755 livejournal/bin/upgrading/blobify_userpics.pl create mode 100755 livejournal/bin/upgrading/compress_cluster.pl create mode 100755 livejournal/bin/upgrading/d1d2-single.pl create mode 100755 livejournal/bin/upgrading/d4d5-global.pl create mode 100755 livejournal/bin/upgrading/d5d6-mkf.pl create mode 100755 livejournal/bin/upgrading/d6d7-userpics.pl create mode 100755 livejournal/bin/upgrading/deadphrases.dat create mode 100755 livejournal/bin/upgrading/en.dat create mode 100755 livejournal/bin/upgrading/import-includes.pl create mode 100755 livejournal/bin/upgrading/make_system.pl create mode 100755 livejournal/bin/upgrading/migrate-phoneposts.pl create mode 100755 livejournal/bin/upgrading/migrate-userpics.pl create mode 100755 livejournal/bin/upgrading/migrate-userprop.pl create mode 100755 livejournal/bin/upgrading/moods.dat create mode 100755 livejournal/bin/upgrading/move0cluster.pl create mode 100755 livejournal/bin/upgrading/pop-clusterprops.pl create mode 100755 livejournal/bin/upgrading/pop-weekuu.pl create mode 100755 livejournal/bin/upgrading/s1style-rw.pl create mode 100755 livejournal/bin/upgrading/s1styles.dat create mode 100755 livejournal/bin/upgrading/s2layers.dat create mode 100755 livejournal/bin/upgrading/s2layers/classic/classic.jpg create mode 100755 livejournal/bin/upgrading/s2layers/classic/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/classic/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/classic/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/cleansimple/cleansimple.jpg create mode 100755 livejournal/bin/upgrading/s2layers/cleansimple/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/cleansimple/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/cleansimple/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/core1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/digitalmultiplex/digitalmultiplex.jpg create mode 100755 livejournal/bin/upgrading/s2layers/digitalmultiplex/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/digitalmultiplex/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/generator/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/generator/generator.jpg create mode 100755 livejournal/bin/upgrading/s2layers/generator/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/generator/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/haven/haven.png create mode 100755 livejournal/bin/upgrading/s2layers/haven/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/haven/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/da1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/de1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/en1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/eo1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/fi1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/fr1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/ja1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/i18nc/ru1.s2 create mode 100755 livejournal/bin/upgrading/s2layers/magazine/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/magazine/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/magazine/magazine.jpg create mode 100755 livejournal/bin/upgrading/s2layers/magazine/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/notepad/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/notepad/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/notepad/notepad.jpg create mode 100755 livejournal/bin/upgrading/s2layers/policy.dat create mode 100755 livejournal/bin/upgrading/s2layers/punquin/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/punquin/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/punquin/punquin.jpg create mode 100755 livejournal/bin/upgrading/s2layers/punquin/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/sturdygesture/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/sturdygesture/sturdygesture.jpg create mode 100755 livejournal/bin/upgrading/s2layers/sturdygesture/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/tabularindent/en.s2 create mode 100755 livejournal/bin/upgrading/s2layers/tabularindent/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/tabularindent/tabularindent.jpg create mode 100755 livejournal/bin/upgrading/s2layers/tabularindent/themes.s2 create mode 100755 livejournal/bin/upgrading/s2layers/variableflow/layout.s2 create mode 100755 livejournal/bin/upgrading/s2layers/variableflow/preview.jpg create mode 100755 livejournal/bin/upgrading/s2style-wizard-update.pl create mode 100755 livejournal/bin/upgrading/support-upgrade.pl create mode 100755 livejournal/bin/upgrading/text.dat create mode 100755 livejournal/bin/upgrading/texttool.pl create mode 100755 livejournal/bin/upgrading/truncate_cluster.pl create mode 100755 livejournal/bin/upgrading/update-db-general.pl create mode 100755 livejournal/bin/upgrading/update-db.pl create mode 100755 livejournal/bin/weblog-summarize.pl create mode 100755 livejournal/bootstrap.pl create mode 100755 livejournal/cgi-bin/Apache/DebateSuicide.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal/Interface/AtomAPI.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal/Interface/Blogger.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal/Interface/FotoBilder.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal/Interface/S2.pm create mode 100755 livejournal/cgi-bin/Apache/LiveJournal/PalImg.pm create mode 100755 livejournal/cgi-bin/Apache/SendStats.pm create mode 100755 livejournal/cgi-bin/BlobClient.pm create mode 100755 livejournal/cgi-bin/BlobClient/Local.pm create mode 100755 livejournal/cgi-bin/BlobClient/Remote.pm create mode 100755 livejournal/cgi-bin/LJ/Blob.pm create mode 100755 livejournal/cgi-bin/LJ/Cache.pm create mode 100755 livejournal/cgi-bin/LJ/Captcha.pm create mode 100755 livejournal/cgi-bin/LJ/LDAP.pm create mode 100755 livejournal/cgi-bin/LJ/MemCache.pm create mode 100755 livejournal/cgi-bin/LJ/OpenID.pm create mode 100755 livejournal/cgi-bin/LJ/S2.pm create mode 100755 livejournal/cgi-bin/LJ/S2/DayPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/EntryPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/FriendsPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/MonthPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/RecentPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/ReplyPage.pm create mode 100755 livejournal/cgi-bin/LJ/S2/YearPage.pm create mode 100755 livejournal/cgi-bin/LJ/SixDegrees.pm create mode 100755 livejournal/cgi-bin/LJ/SpellCheck.pm create mode 100755 livejournal/cgi-bin/LJ/TagGenerator.pm create mode 100755 livejournal/cgi-bin/LJ/TextMessage.pm create mode 100755 livejournal/cgi-bin/LJ/User.pm create mode 100755 livejournal/cgi-bin/PaletteModify.pm create mode 100755 livejournal/cgi-bin/XML/Atom.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Client.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Content.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Entry.pm create mode 100755 livejournal/cgi-bin/XML/Atom/ErrorHandler.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Feed.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Link.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Person.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Server.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Thing.pm create mode 100755 livejournal/cgi-bin/XML/Atom/Util.pm create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.enc create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.xml create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.enc create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.xml create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.enc create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.xml create mode 100755 livejournal/cgi-bin/XML/Parser/Encodings/windows-1255.enc create mode 100755 livejournal/cgi-bin/XML/README.txt create mode 100755 livejournal/cgi-bin/bml/scheme/bluewhite.look create mode 100755 livejournal/cgi-bin/bml/scheme/global.look create mode 100755 livejournal/cgi-bin/bml/scheme/lynx.look create mode 100755 livejournal/cgi-bin/bml/scheme/opalcat.look create mode 100755 livejournal/cgi-bin/bml/scheme/woais.look create mode 100755 livejournal/cgi-bin/cleanhtml.pl create mode 100755 livejournal/cgi-bin/communitylib.pl create mode 100755 livejournal/cgi-bin/conban.pl create mode 100755 livejournal/cgi-bin/confaq.pl create mode 100755 livejournal/cgi-bin/conmoodtheme.pl create mode 100755 livejournal/cgi-bin/conshared.pl create mode 100755 livejournal/cgi-bin/console.pl create mode 100755 livejournal/cgi-bin/consuspend.pl create mode 100755 livejournal/cgi-bin/crumbs.pl create mode 100755 livejournal/cgi-bin/directorylib.pl create mode 100755 livejournal/cgi-bin/emailcheck.pl create mode 100755 livejournal/cgi-bin/fbupload.pl create mode 100755 livejournal/cgi-bin/htmlcontrols.pl create mode 100755 livejournal/cgi-bin/imageconf.pl create mode 100755 livejournal/cgi-bin/lj-bml-blocks.pl create mode 100755 livejournal/cgi-bin/lj-bml-init.pl create mode 100755 livejournal/cgi-bin/ljcmdbuffer.pl create mode 100755 livejournal/cgi-bin/ljdb.pl create mode 100755 livejournal/cgi-bin/ljdefaults.pl create mode 100755 livejournal/cgi-bin/ljemailgateway.pl create mode 100755 livejournal/cgi-bin/ljfeed.pl create mode 100755 livejournal/cgi-bin/ljlang.pl create mode 100755 livejournal/cgi-bin/ljlib.pl create mode 100755 livejournal/cgi-bin/ljlinks.pl create mode 100755 livejournal/cgi-bin/ljmail.pl create mode 100755 livejournal/cgi-bin/ljmemories.pl create mode 100755 livejournal/cgi-bin/ljpoll.pl create mode 100755 livejournal/cgi-bin/ljprotocol.pl create mode 100755 livejournal/cgi-bin/ljtodo.pl create mode 100755 livejournal/cgi-bin/ljviews.pl create mode 100755 livejournal/cgi-bin/modperl.pl create mode 100755 livejournal/cgi-bin/modperl_subs.pl create mode 100755 livejournal/cgi-bin/parsefeed.pl create mode 100755 livejournal/cgi-bin/portal.pl create mode 100755 livejournal/cgi-bin/propparse.pl create mode 100755 livejournal/cgi-bin/redirect.dat create mode 100755 livejournal/cgi-bin/statslib.pl create mode 100755 livejournal/cgi-bin/supportlib.pl create mode 100755 livejournal/cgi-bin/synlib.pl create mode 100755 livejournal/cgi-bin/sysban.pl create mode 100755 livejournal/cgi-bin/taglib.pl create mode 100755 livejournal/cgi-bin/talklib.pl create mode 100755 livejournal/cgi-bin/userpicmagic.txt create mode 100755 livejournal/cgi-bin/weblib.pl create mode 100755 livejournal/cvs/multicvs.conf create mode 100755 livejournal/doc/designnotes/multihomed_userprops.txt create mode 100755 livejournal/doc/ljconfig.pl.txt create mode 100755 livejournal/doc/notes/user-statusvis.txt create mode 100755 livejournal/doc/raw/appendices/gfdl.xml create mode 100755 livejournal/doc/raw/build/api/api2db.pl create mode 100755 livejournal/doc/raw/build/api/apidoc.conf create mode 100755 livejournal/doc/raw/build/caps/cap-local.pl create mode 100755 livejournal/doc/raw/build/caps/cap2db.pl create mode 100755 livejournal/doc/raw/build/chunk.xsl create mode 100755 livejournal/doc/raw/build/console/console2db.pl create mode 100755 livejournal/doc/raw/build/db/db2ref.xsl create mode 100755 livejournal/doc/raw/build/db/dbschema.dtd create mode 100755 livejournal/doc/raw/build/db/dbschema.pl create mode 100755 livejournal/doc/raw/build/docbooklib.pl create mode 100755 livejournal/doc/raw/build/generate.pl create mode 100755 livejournal/doc/raw/build/hooks/hooks2db.pl create mode 100755 livejournal/doc/raw/build/install/modulelist2db.pl create mode 100755 livejournal/doc/raw/build/ljconfig/ljconfig2db.pl create mode 100755 livejournal/doc/raw/build/ljdocs2html.xsl create mode 100755 livejournal/doc/raw/build/nochunk.xsl create mode 100755 livejournal/doc/raw/build/priv/priv2db.pl create mode 100755 livejournal/doc/raw/build/protocol/authinfo.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/checkfriends.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/consolecommand.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/editevent.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/editfriendgroups.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/editfriends.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/flat2db.pl create mode 100755 livejournal/doc/raw/build/protocol/friendgroups.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/friendof.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/friendslist.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/getchallenge.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/getdaycounts.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/getevents.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/getfriendgroups.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/getfriends.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/login.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/moods.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/postevent.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/proplist2db.pl create mode 100755 livejournal/doc/raw/build/protocol/sessionexpire.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/sessiongenerate.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/syncitems.mode.xml create mode 100755 livejournal/doc/raw/build/protocol/usejournal.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/usejournals.ent.xml create mode 100755 livejournal/doc/raw/build/protocol/xml-rpc2db.xsl create mode 100755 livejournal/doc/raw/build/protocol/xmlrpc.dtd create mode 100755 livejournal/doc/raw/build/protocol/xmlrpc.xml create mode 100755 livejournal/doc/raw/build/titlepage.xsl create mode 100755 livejournal/doc/raw/entities/authors.ent create mode 100755 livejournal/doc/raw/entities/books.ent create mode 100755 livejournal/doc/raw/entities/content.ent create mode 100755 livejournal/doc/raw/entities/entities.xml create mode 100755 livejournal/doc/raw/entities/lj.book.ent create mode 100755 livejournal/doc/raw/entities/ljp.book.ent create mode 100755 livejournal/doc/raw/http-interface.txt create mode 100755 livejournal/doc/raw/index.xml create mode 100755 livejournal/doc/raw/int/db/db2ref.xsl create mode 100755 livejournal/doc/raw/int/db/dbschema.dtd create mode 100755 livejournal/doc/raw/int/db/dbschema.pl create mode 100755 livejournal/doc/raw/int/db/schema.xml create mode 100755 livejournal/doc/raw/int/programming-guidelines.xml create mode 100755 livejournal/doc/raw/int/protocol/Makefile create mode 100755 livejournal/doc/raw/int/protocol/authinfo.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/checkfriends.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/consolecommand.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/editevent.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/editfriendgroups.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/editfriends.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/friendgroups.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/friendof.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/friendslist.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/getdaycounts.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/getevents.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/getfriendgroups.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/getfriends.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/login.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/moods.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/postevent.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/syncitems.mode.xml create mode 100755 livejournal/doc/raw/int/protocol/testbook.xml create mode 100755 livejournal/doc/raw/int/protocol/to_docbook.xsl create mode 100755 livejournal/doc/raw/int/protocol/usejournal.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/usejournals.ent.xml create mode 100755 livejournal/doc/raw/int/protocol/xmlrpc.dtd create mode 100755 livejournal/doc/raw/int/protocol/xmlrpc.xml create mode 100755 livejournal/doc/raw/lj.book/admin/caps_list.xml create mode 100755 livejournal/doc/raw/lj.book/admin/console.xml create mode 100755 livejournal/doc/raw/lj.book/admin/create_users.xml create mode 100755 livejournal/doc/raw/lj.book/admin/creating_users.xml create mode 100755 livejournal/doc/raw/lj.book/admin/index.xml create mode 100755 livejournal/doc/raw/lj.book/admin/privs.xml create mode 100755 livejournal/doc/raw/lj.book/admin/sysban.xml create mode 100755 livejournal/doc/raw/lj.book/customize/hooks.xml create mode 100755 livejournal/doc/raw/lj.book/customize/images.xml create mode 100755 livejournal/doc/raw/lj.book/customize/index.xml create mode 100755 livejournal/doc/raw/lj.book/customize/layout.xml create mode 100755 livejournal/doc/raw/lj.book/customize/limits.xml create mode 100755 livejournal/doc/raw/lj.book/customize/local_cvs.xml create mode 100755 livejournal/doc/raw/lj.book/customize/tasks.xml create mode 100755 livejournal/doc/raw/lj.book/customize/text.xml create mode 100755 livejournal/doc/raw/lj.book/features/index.xml create mode 100755 livejournal/doc/raw/lj.book/features/support.xml create mode 100755 livejournal/doc/raw/lj.book/features/topics.xml create mode 100755 livejournal/doc/raw/lj.book/index.xml create mode 100755 livejournal/doc/raw/lj.book/install/apache_setup.xml create mode 100755 livejournal/doc/raw/lj.book/install/finishing.xml create mode 100755 livejournal/doc/raw/lj.book/install/general_setup.xml create mode 100755 livejournal/doc/raw/lj.book/install/index.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.caps.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.dbinfo.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.disabled.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.helpurls.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.vars.xml create mode 100755 livejournal/doc/raw/lj.book/install/ljconfig.xml create mode 100755 livejournal/doc/raw/lj.book/install/mysql_setup.xml create mode 100755 livejournal/doc/raw/lj.book/install/perl_setup.xml create mode 100755 livejournal/doc/raw/lj.book/install/reqs.xml create mode 100755 livejournal/doc/raw/lj.book/install/schedule_tasks.xml create mode 100755 livejournal/doc/raw/lj.book/intro/goat.xml create mode 100755 livejournal/doc/raw/lj.book/intro/index.xml create mode 100755 livejournal/doc/raw/lj.book/intro/story.xml create mode 100755 livejournal/doc/raw/lj.book/intro/what_is.xml create mode 100755 livejournal/doc/raw/lj.book/intro/why.xml create mode 100755 livejournal/doc/raw/lj.book/preface.xml create mode 100755 livejournal/doc/raw/ljp.book/api/index.xml create mode 100755 livejournal/doc/raw/ljp.book/bml/core.xml create mode 100755 livejournal/doc/raw/ljp.book/bml/flags.xml create mode 100755 livejournal/doc/raw/ljp.book/bml/index.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/appx.faq.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/auth.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/blogger.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/cs.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/flat/index.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/index.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/proplist.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/versions.xml create mode 100755 livejournal/doc/raw/ljp.book/csp/xml-rpc/index.xml create mode 100755 livejournal/doc/raw/ljp.book/db/index.xml create mode 100755 livejournal/doc/raw/ljp.book/db/reluser.xml create mode 100755 livejournal/doc/raw/ljp.book/index.xml create mode 100755 livejournal/doc/raw/ljp.book/int/bml_faq.xml create mode 100755 livejournal/doc/raw/ljp.book/int/cap_classes.xml create mode 100755 livejournal/doc/raw/ljp.book/int/index.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/database.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/general.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/index.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/patches.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/performance.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/perl_style.xml create mode 100755 livejournal/doc/raw/ljp.book/prog-guide/security.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/compare.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/index.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s1/design.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s1/history.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s1/index.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s2/design.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s2/history.xml create mode 100755 livejournal/doc/raw/ljp.book/styles/s2/index.xml create mode 100755 livejournal/doc/raw/memcache-keys.txt create mode 100755 livejournal/doc/raw/mogile-keys.txt create mode 100755 livejournal/doc/raw/notes.txt create mode 100755 livejournal/doc/raw/s1/s1ref2db.pl create mode 100755 livejournal/doc/raw/s1/vars.dat create mode 100755 livejournal/doc/raw/s1/views.dat create mode 100755 livejournal/doc/raw/s2/lj/build.pl create mode 100755 livejournal/doc/raw/s2/lj/dateformats.xml create mode 100755 livejournal/doc/raw/s2/lj/entities.xml create mode 100755 livejournal/doc/raw/s2/lj/faq.xml create mode 100755 livejournal/doc/raw/s2/lj/index.xml create mode 100755 livejournal/doc/raw/s2/lj/quickstart.xml create mode 100755 livejournal/doc/raw/s2/lj/s2onlj.xml create mode 100755 livejournal/doc/raw/s2/lj/siteapi.xml create mode 100755 livejournal/doc/todo.txt create mode 100755 livejournal/htdocs/500-error.html create mode 100755 livejournal/htdocs/_config.bml create mode 100755 livejournal/htdocs/accountstatus.bml create mode 100755 livejournal/htdocs/admin/capedit.bml create mode 100755 livejournal/htdocs/admin/clusterstatus.bml create mode 100755 livejournal/htdocs/admin/console/index.bml create mode 100755 livejournal/htdocs/admin/console/reference.bml create mode 100755 livejournal/htdocs/admin/dbadmin.bml create mode 100755 livejournal/htdocs/admin/faq/faqedit.bml create mode 100755 livejournal/htdocs/admin/faq/faqedit_do.bml create mode 100755 livejournal/htdocs/admin/faq/index.bml create mode 100755 livejournal/htdocs/admin/faq/readcat.bml create mode 100755 livejournal/htdocs/admin/fileedit/index.bml create mode 100755 livejournal/htdocs/admin/memcache.bml create mode 100755 livejournal/htdocs/admin/memcache_view.bml create mode 100755 livejournal/htdocs/admin/mysql_status.bml create mode 100755 livejournal/htdocs/admin/priv/index.bml create mode 100755 livejournal/htdocs/admin/recent_comments.bml create mode 100755 livejournal/htdocs/admin/schema/index.bml create mode 100755 livejournal/htdocs/admin/spamreports.bml create mode 100755 livejournal/htdocs/admin/statushistory.bml create mode 100755 livejournal/htdocs/admin/topics/blank.bml create mode 100755 livejournal/htdocs/admin/topics/index.bml create mode 100755 livejournal/htdocs/admin/topics/links.bml create mode 100755 livejournal/htdocs/admin/topics/screen.html create mode 100755 livejournal/htdocs/admin/topics/screen_do.bml create mode 100755 livejournal/htdocs/admin/topics/screen_instructions.bml create mode 100755 livejournal/htdocs/admin/topics/screen_links.bml create mode 100755 livejournal/htdocs/admin/topics/screentop.bml create mode 100755 livejournal/htdocs/admin/topics/screentop.html create mode 100755 livejournal/htdocs/admin/topics/screentop_do.bml create mode 100755 livejournal/htdocs/admin/topics/start.bml create mode 100755 livejournal/htdocs/admin/userlog.bml create mode 100755 livejournal/htdocs/allpics.bml create mode 100755 livejournal/htdocs/approve.bml create mode 100755 livejournal/htdocs/birthdays.bml create mode 100755 livejournal/htdocs/captcha/audio.bml create mode 100755 livejournal/htdocs/captcha/image.bml create mode 100755 livejournal/htdocs/changepassword.bml create mode 100755 livejournal/htdocs/community/create.bml create mode 100755 livejournal/htdocs/community/index.bml create mode 100755 livejournal/htdocs/community/join.bml create mode 100755 livejournal/htdocs/community/leave.bml create mode 100755 livejournal/htdocs/community/manage.bml create mode 100755 livejournal/htdocs/community/members.bml create mode 100755 livejournal/htdocs/community/moderate.bml create mode 100755 livejournal/htdocs/community/pending.bml create mode 100755 livejournal/htdocs/community/search.bml create mode 100755 livejournal/htdocs/community/sentinvites.bml create mode 100755 livejournal/htdocs/community/settings.bml create mode 100755 livejournal/htdocs/community/transfer.bml create mode 100755 livejournal/htdocs/create.bml create mode 100755 livejournal/htdocs/customize/advanced/index.bml create mode 100755 livejournal/htdocs/customize/advanced/layerbrowse.bml create mode 100755 livejournal/htdocs/customize/advanced/layeredit.bml create mode 100755 livejournal/htdocs/customize/advanced/layers.bml create mode 100755 livejournal/htdocs/customize/advanced/layersource.bml create mode 100755 livejournal/htdocs/customize/advanced/styles.bml create mode 100755 livejournal/htdocs/customize/index.bml create mode 100755 livejournal/htdocs/customize/layer.bml create mode 100755 livejournal/htdocs/customize/preview.bml create mode 100755 livejournal/htdocs/customize/themes.bml create mode 100755 livejournal/htdocs/customize/viewuser.bml create mode 100755 livejournal/htdocs/delcomment.bml create mode 100755 livejournal/htdocs/dev/userlist.bml create mode 100755 livejournal/htdocs/directory.bml create mode 100755 livejournal/htdocs/directorysearch.bml create mode 100755 livejournal/htdocs/doc/.placeholder create mode 100755 livejournal/htdocs/editinfo.bml create mode 100755 livejournal/htdocs/editjournal.bml create mode 100755 livejournal/htdocs/editpics.bml create mode 100755 livejournal/htdocs/edittags.bml create mode 100755 livejournal/htdocs/export.bml create mode 100755 livejournal/htdocs/export_comments.bml create mode 100755 livejournal/htdocs/export_do.bml create mode 100755 livejournal/htdocs/files/.placeholder create mode 100755 livejournal/htdocs/friends/add.bml create mode 100755 livejournal/htdocs/friends/edit.bml create mode 100755 livejournal/htdocs/friends/editgroups.bml create mode 100755 livejournal/htdocs/friends/filter.bml create mode 100755 livejournal/htdocs/friends/graph.bml create mode 100755 livejournal/htdocs/friends/index.bml create mode 100755 livejournal/htdocs/go.bml create mode 100755 livejournal/htdocs/img/addfriend.gif create mode 100755 livejournal/htdocs/img/anonymous.gif create mode 100755 livejournal/htdocs/img/blackdot.gif create mode 100755 livejournal/htdocs/img/bluedot.gif create mode 100755 livejournal/htdocs/img/bluewhite/bluefade.jpg create mode 100755 livejournal/htdocs/img/bluewhite/bullet.gif create mode 100755 livejournal/htdocs/img/bluewhite/hline.gif create mode 100755 livejournal/htdocs/img/bluewhite/home.gif create mode 100755 livejournal/htdocs/img/bluewhite/hr_divdot.gif create mode 100755 livejournal/htdocs/img/bluewhite/linetop.gif create mode 100755 livejournal/htdocs/img/bluewhite/sidebarfade.gif create mode 100755 livejournal/htdocs/img/bluewhite/sidebarfade_line.gif create mode 100755 livejournal/htdocs/img/bluewhite/title.gif create mode 100755 livejournal/htdocs/img/bluewhite/vline.gif create mode 100755 livejournal/htdocs/img/btn_addfriend.gif create mode 100755 livejournal/htdocs/img/btn_del.gif create mode 100755 livejournal/htdocs/img/btn_dn.gif create mode 100755 livejournal/htdocs/img/btn_edit.gif create mode 100755 livejournal/htdocs/img/btn_edittags.gif create mode 100755 livejournal/htdocs/img/btn_freeze.gif create mode 100755 livejournal/htdocs/img/btn_memories.gif create mode 100755 livejournal/htdocs/img/btn_next.gif create mode 100755 livejournal/htdocs/img/btn_prev.gif create mode 100755 livejournal/htdocs/img/btn_scr.gif create mode 100755 livejournal/htdocs/img/btn_search.gif create mode 100755 livejournal/htdocs/img/btn_tellfriend.gif create mode 100755 livejournal/htdocs/img/btn_todo.gif create mode 100755 livejournal/htdocs/img/btn_unfreeze.gif create mode 100755 livejournal/htdocs/img/btn_unscr.gif create mode 100755 livejournal/htdocs/img/btn_up.gif create mode 100755 livejournal/htdocs/img/captcha/2.png create mode 100755 livejournal/htdocs/img/captcha/3.png create mode 100755 livejournal/htdocs/img/captcha/4.png create mode 100755 livejournal/htdocs/img/captcha/5.png create mode 100755 livejournal/htdocs/img/captcha/6.png create mode 100755 livejournal/htdocs/img/captcha/7.png create mode 100755 livejournal/htdocs/img/captcha/8.png create mode 100755 livejournal/htdocs/img/captcha/9.png create mode 100755 livejournal/htdocs/img/captcha/a.png create mode 100755 livejournal/htdocs/img/captcha/b.png create mode 100755 livejournal/htdocs/img/captcha/background1.png create mode 100755 livejournal/htdocs/img/captcha/background2.png create mode 100755 livejournal/htdocs/img/captcha/background3.png create mode 100755 livejournal/htdocs/img/captcha/background4.png create mode 100755 livejournal/htdocs/img/captcha/background5.png create mode 100755 livejournal/htdocs/img/captcha/c.png create mode 100755 livejournal/htdocs/img/captcha/d.png create mode 100755 livejournal/htdocs/img/captcha/e.png create mode 100755 livejournal/htdocs/img/captcha/f.png create mode 100755 livejournal/htdocs/img/captcha/g.png create mode 100755 livejournal/htdocs/img/captcha/h.png create mode 100755 livejournal/htdocs/img/captcha/i.png create mode 100755 livejournal/htdocs/img/captcha/j.png create mode 100755 livejournal/htdocs/img/captcha/k.png create mode 100755 livejournal/htdocs/img/captcha/l.png create mode 100755 livejournal/htdocs/img/captcha/m.png create mode 100755 livejournal/htdocs/img/captcha/n.png create mode 100755 livejournal/htdocs/img/captcha/o.png create mode 100755 livejournal/htdocs/img/captcha/p.png create mode 100755 livejournal/htdocs/img/captcha/q.png create mode 100755 livejournal/htdocs/img/captcha/r.png create mode 100755 livejournal/htdocs/img/captcha/s.png create mode 100755 livejournal/htdocs/img/captcha/t.png create mode 100755 livejournal/htdocs/img/captcha/u.png create mode 100755 livejournal/htdocs/img/captcha/v.png create mode 100755 livejournal/htdocs/img/captcha/w.png create mode 100755 livejournal/htdocs/img/captcha/x.png create mode 100755 livejournal/htdocs/img/captcha/y.png create mode 100755 livejournal/htdocs/img/captcha/z.png create mode 100755 livejournal/htdocs/img/colorpicker/crosshair.gif create mode 100755 livejournal/htdocs/img/colorpicker/pointer.gif create mode 100755 livejournal/htdocs/img/colorpicker/spectrum.png create mode 100755 livejournal/htdocs/img/community.gif create mode 100755 livejournal/htdocs/img/corn_ne.gif create mode 100755 livejournal/htdocs/img/corn_nw.gif create mode 100755 livejournal/htdocs/img/corn_se.gif create mode 100755 livejournal/htdocs/img/corn_sw.gif create mode 100755 livejournal/htdocs/img/delcomment.gif create mode 100755 livejournal/htdocs/img/dot.gif create mode 100755 livejournal/htdocs/img/dot_green.gif create mode 100755 livejournal/htdocs/img/dot_red.gif create mode 100755 livejournal/htdocs/img/dot_yellow.gif create mode 100755 livejournal/htdocs/img/doublearrow.gif create mode 100755 livejournal/htdocs/img/globe.gif create mode 100755 livejournal/htdocs/img/grey_gradbg.gif create mode 100755 livejournal/htdocs/img/help.gif create mode 100755 livejournal/htdocs/img/hourglass.gif create mode 100755 livejournal/htdocs/img/icon_private.gif create mode 100755 livejournal/htdocs/img/icon_protected.gif create mode 100755 livejournal/htdocs/img/imageplaceholder.png create mode 100755 livejournal/htdocs/img/imageplaceholder2.png create mode 100755 livejournal/htdocs/img/imageplaceholder3.png create mode 100755 livejournal/htdocs/img/key.gif create mode 100755 livejournal/htdocs/img/knobs.gif create mode 100755 livejournal/htdocs/img/leftarrow.gif create mode 100755 livejournal/htdocs/img/level1.gif create mode 100755 livejournal/htdocs/img/level2.gif create mode 100755 livejournal/htdocs/img/level3.gif create mode 100755 livejournal/htdocs/img/level4.gif create mode 100755 livejournal/htdocs/img/level5.gif create mode 100755 livejournal/htdocs/img/memadd.gif create mode 100755 livejournal/htdocs/img/message-error.gif create mode 100755 livejournal/htdocs/img/message-warning.gif create mode 100755 livejournal/htdocs/img/nerd_small.jpg create mode 100755 livejournal/htdocs/img/newsinfo.gif create mode 100755 livejournal/htdocs/img/opal/bullet.gif create mode 100755 livejournal/htdocs/img/opal/home.gif create mode 100755 livejournal/htdocs/img/opal/home.jpg create mode 100755 livejournal/htdocs/img/opal/pencil-line.gif create mode 100755 livejournal/htdocs/img/opal/spiral1.jpg create mode 100755 livejournal/htdocs/img/opal/spiral2.jpg create mode 100755 livejournal/htdocs/img/opal/spiralbg.jpg create mode 100755 livejournal/htdocs/img/openid-badge.gif create mode 100755 livejournal/htdocs/img/openid-inputicon.gif create mode 100755 livejournal/htdocs/img/openid-profile.gif create mode 100755 livejournal/htdocs/img/pencil.gif create mode 100755 livejournal/htdocs/img/poll/leftbar.gif create mode 100755 livejournal/htdocs/img/poll/mainbar.gif create mode 100755 livejournal/htdocs/img/poll/rightbar.gif create mode 100755 livejournal/htdocs/img/rightarrow.gif create mode 100755 livejournal/htdocs/img/rte/post_button_bold.gif create mode 100755 livejournal/htdocs/img/rte/post_button_copy.gif create mode 100755 livejournal/htdocs/img/rte/post_button_cut.gif create mode 100755 livejournal/htdocs/img/rte/post_button_hyperlink.gif create mode 100755 livejournal/htdocs/img/rte/post_button_image.gif create mode 100755 livejournal/htdocs/img/rte/post_button_italic.gif create mode 100755 livejournal/htdocs/img/rte/post_button_list.gif create mode 100755 livejournal/htdocs/img/rte/post_button_ljcut.gif create mode 100755 livejournal/htdocs/img/rte/post_button_ljuser.gif create mode 100755 livejournal/htdocs/img/rte/post_button_numbered_list.gif create mode 100755 livejournal/htdocs/img/rte/post_button_paste.gif create mode 100755 livejournal/htdocs/img/rte/post_button_redo.gif create mode 100755 livejournal/htdocs/img/rte/post_button_text_larger.gif create mode 100755 livejournal/htdocs/img/rte/post_button_text_normal.gif create mode 100755 livejournal/htdocs/img/rte/post_button_text_smaller.gif create mode 100755 livejournal/htdocs/img/rte/post_button_textcolor.gif create mode 100755 livejournal/htdocs/img/rte/post_button_underline.gif create mode 100755 livejournal/htdocs/img/rte/post_button_undo.gif create mode 100755 livejournal/htdocs/img/searchingdots.gif create mode 100755 livejournal/htdocs/img/style/notepad/bottom-left.jpg create mode 100755 livejournal/htdocs/img/style/notepad/bottom-line.jpg create mode 100755 livejournal/htdocs/img/style/notepad/bottom-right.jpg create mode 100755 livejournal/htdocs/img/style/notepad/hr.gif create mode 100755 livejournal/htdocs/img/style/notepad/middle.jpg create mode 100755 livejournal/htdocs/img/style/notepad/side-left.jpg create mode 100755 livejournal/htdocs/img/style/notepad/side-right.jpg create mode 100755 livejournal/htdocs/img/style/notepad/spacer.gif create mode 100755 livejournal/htdocs/img/style/notepad/tab.jpg create mode 100755 livejournal/htdocs/img/style/notepad/top-left.jpg create mode 100755 livejournal/htdocs/img/style/notepad/top-right.jpg create mode 100755 livejournal/htdocs/img/style/webley/bottom.png create mode 100755 livejournal/htdocs/img/style/webley/jwc.png create mode 100755 livejournal/htdocs/img/style/webley/jwc0.png create mode 100755 livejournal/htdocs/img/style/webley/jwc1.png create mode 100755 livejournal/htdocs/img/style/webley/jwc10.png create mode 100755 livejournal/htdocs/img/style/webley/jwc100.png create mode 100755 livejournal/htdocs/img/style/webley/jwc11.png create mode 100755 livejournal/htdocs/img/style/webley/jwc12.png create mode 100755 livejournal/htdocs/img/style/webley/jwc13.png create mode 100755 livejournal/htdocs/img/style/webley/jwc14.png create mode 100755 livejournal/htdocs/img/style/webley/jwc15.png create mode 100755 livejournal/htdocs/img/style/webley/jwc16.png create mode 100755 livejournal/htdocs/img/style/webley/jwc17.png create mode 100755 livejournal/htdocs/img/style/webley/jwc18.png create mode 100755 livejournal/htdocs/img/style/webley/jwc19.png create mode 100755 livejournal/htdocs/img/style/webley/jwc2.png create mode 100755 livejournal/htdocs/img/style/webley/jwc20.png create mode 100755 livejournal/htdocs/img/style/webley/jwc21.png create mode 100755 livejournal/htdocs/img/style/webley/jwc22.png create mode 100755 livejournal/htdocs/img/style/webley/jwc23.png create mode 100755 livejournal/htdocs/img/style/webley/jwc24.png create mode 100755 livejournal/htdocs/img/style/webley/jwc25.png create mode 100755 livejournal/htdocs/img/style/webley/jwc26.png create mode 100755 livejournal/htdocs/img/style/webley/jwc27.png create mode 100755 livejournal/htdocs/img/style/webley/jwc28.png create mode 100755 livejournal/htdocs/img/style/webley/jwc29.png create mode 100755 livejournal/htdocs/img/style/webley/jwc3.png create mode 100755 livejournal/htdocs/img/style/webley/jwc30.png create mode 100755 livejournal/htdocs/img/style/webley/jwc31.png create mode 100755 livejournal/htdocs/img/style/webley/jwc32.png create mode 100755 livejournal/htdocs/img/style/webley/jwc33.png create mode 100755 livejournal/htdocs/img/style/webley/jwc34.png create mode 100755 livejournal/htdocs/img/style/webley/jwc35.png create mode 100755 livejournal/htdocs/img/style/webley/jwc36.png create mode 100755 livejournal/htdocs/img/style/webley/jwc37.png create mode 100755 livejournal/htdocs/img/style/webley/jwc38.png create mode 100755 livejournal/htdocs/img/style/webley/jwc39.png create mode 100755 livejournal/htdocs/img/style/webley/jwc4.png create mode 100755 livejournal/htdocs/img/style/webley/jwc40.png create mode 100755 livejournal/htdocs/img/style/webley/jwc41.png create mode 100755 livejournal/htdocs/img/style/webley/jwc42.png create mode 100755 livejournal/htdocs/img/style/webley/jwc43.png create mode 100755 livejournal/htdocs/img/style/webley/jwc44.png create mode 100755 livejournal/htdocs/img/style/webley/jwc45.png create mode 100755 livejournal/htdocs/img/style/webley/jwc46.png create mode 100755 livejournal/htdocs/img/style/webley/jwc47.png create mode 100755 livejournal/htdocs/img/style/webley/jwc48.png create mode 100755 livejournal/htdocs/img/style/webley/jwc49.png create mode 100755 livejournal/htdocs/img/style/webley/jwc5.png create mode 100755 livejournal/htdocs/img/style/webley/jwc50.png create mode 100755 livejournal/htdocs/img/style/webley/jwc51.png create mode 100755 livejournal/htdocs/img/style/webley/jwc52.png create mode 100755 livejournal/htdocs/img/style/webley/jwc53.png create mode 100755 livejournal/htdocs/img/style/webley/jwc54.png create mode 100755 livejournal/htdocs/img/style/webley/jwc55.png create mode 100755 livejournal/htdocs/img/style/webley/jwc56.png create mode 100755 livejournal/htdocs/img/style/webley/jwc57.png create mode 100755 livejournal/htdocs/img/style/webley/jwc58.png create mode 100755 livejournal/htdocs/img/style/webley/jwc59.png create mode 100755 livejournal/htdocs/img/style/webley/jwc6.png create mode 100755 livejournal/htdocs/img/style/webley/jwc60.png create mode 100755 livejournal/htdocs/img/style/webley/jwc61.png create mode 100755 livejournal/htdocs/img/style/webley/jwc62.png create mode 100755 livejournal/htdocs/img/style/webley/jwc63.png create mode 100755 livejournal/htdocs/img/style/webley/jwc64.png create mode 100755 livejournal/htdocs/img/style/webley/jwc65.png create mode 100755 livejournal/htdocs/img/style/webley/jwc66.png create mode 100755 livejournal/htdocs/img/style/webley/jwc67.png create mode 100755 livejournal/htdocs/img/style/webley/jwc68.png create mode 100755 livejournal/htdocs/img/style/webley/jwc69.png create mode 100755 livejournal/htdocs/img/style/webley/jwc7.png create mode 100755 livejournal/htdocs/img/style/webley/jwc70.png create mode 100755 livejournal/htdocs/img/style/webley/jwc71.png create mode 100755 livejournal/htdocs/img/style/webley/jwc72.png create mode 100755 livejournal/htdocs/img/style/webley/jwc73.png create mode 100755 livejournal/htdocs/img/style/webley/jwc74.png create mode 100755 livejournal/htdocs/img/style/webley/jwc75.png create mode 100755 livejournal/htdocs/img/style/webley/jwc76.png create mode 100755 livejournal/htdocs/img/style/webley/jwc77.png create mode 100755 livejournal/htdocs/img/style/webley/jwc78.png create mode 100755 livejournal/htdocs/img/style/webley/jwc79.png create mode 100755 livejournal/htdocs/img/style/webley/jwc8.png create mode 100755 livejournal/htdocs/img/style/webley/jwc80.png create mode 100755 livejournal/htdocs/img/style/webley/jwc81.png create mode 100755 livejournal/htdocs/img/style/webley/jwc82.png create mode 100755 livejournal/htdocs/img/style/webley/jwc83.png create mode 100755 livejournal/htdocs/img/style/webley/jwc84.png create mode 100755 livejournal/htdocs/img/style/webley/jwc85.png create mode 100755 livejournal/htdocs/img/style/webley/jwc86.png create mode 100755 livejournal/htdocs/img/style/webley/jwc87.png create mode 100755 livejournal/htdocs/img/style/webley/jwc88.png create mode 100755 livejournal/htdocs/img/style/webley/jwc89.png create mode 100755 livejournal/htdocs/img/style/webley/jwc9.png create mode 100755 livejournal/htdocs/img/style/webley/jwc90.png create mode 100755 livejournal/htdocs/img/style/webley/jwc91.png create mode 100755 livejournal/htdocs/img/style/webley/jwc92.png create mode 100755 livejournal/htdocs/img/style/webley/jwc93.png create mode 100755 livejournal/htdocs/img/style/webley/jwc94.png create mode 100755 livejournal/htdocs/img/style/webley/jwc95.png create mode 100755 livejournal/htdocs/img/style/webley/jwc96.png create mode 100755 livejournal/htdocs/img/style/webley/jwc97.png create mode 100755 livejournal/htdocs/img/style/webley/jwc98.png create mode 100755 livejournal/htdocs/img/style/webley/jwc99.png create mode 100755 livejournal/htdocs/img/style/webley/left.png create mode 100755 livejournal/htdocs/img/style/webley/ll.png create mode 100755 livejournal/htdocs/img/style/webley/rb.png create mode 100755 livejournal/htdocs/img/style/webley/right.png create mode 100755 livejournal/htdocs/img/style/webley/top.png create mode 100755 livejournal/htdocs/img/style/webley/ul.png create mode 100755 livejournal/htdocs/img/style/webley/ur.png create mode 100755 livejournal/htdocs/img/syndicated.gif create mode 100755 livejournal/htdocs/img/talk/md01_alien.gif create mode 100755 livejournal/htdocs/img/talk/md02_skull.gif create mode 100755 livejournal/htdocs/img/talk/md05_sick.gif create mode 100755 livejournal/htdocs/img/talk/md06_radioactive.gif create mode 100755 livejournal/htdocs/img/talk/md07_cool.gif create mode 100755 livejournal/htdocs/img/talk/md08_bulb.gif create mode 100755 livejournal/htdocs/img/talk/md09_thumbdown.gif create mode 100755 livejournal/htdocs/img/talk/md10_thumbup.gif create mode 100755 livejournal/htdocs/img/talk/new.gif create mode 100755 livejournal/htdocs/img/talk/none.gif create mode 100755 livejournal/htdocs/img/talk/sm01_smiley.gif create mode 100755 livejournal/htdocs/img/talk/sm02_wink.gif create mode 100755 livejournal/htdocs/img/talk/sm03_blush.gif create mode 100755 livejournal/htdocs/img/talk/sm04_shock.gif create mode 100755 livejournal/htdocs/img/talk/sm05_sad.gif create mode 100755 livejournal/htdocs/img/talk/sm06_angry.gif create mode 100755 livejournal/htdocs/img/talk/sm07_check.gif create mode 100755 livejournal/htdocs/img/talk/sm08_star.gif create mode 100755 livejournal/htdocs/img/talk/sm09_mail.gif create mode 100755 livejournal/htdocs/img/talk/sm10_eyes.gif create mode 100755 livejournal/htdocs/img/us_map.gif create mode 100755 livejournal/htdocs/img/userinfo.gif create mode 100755 livejournal/htdocs/img/xml.gif create mode 100755 livejournal/htdocs/inc/account-codes create mode 100755 livejournal/htdocs/inc/support-currentproblems create mode 100755 livejournal/htdocs/inc/support-links create mode 100755 livejournal/htdocs/inc/validationreminder create mode 100755 livejournal/htdocs/index.bml create mode 100755 livejournal/htdocs/interests.bml create mode 100755 livejournal/htdocs/js/browserdetect.js create mode 100755 livejournal/htdocs/js/colorpicker.js create mode 100755 livejournal/htdocs/js/commentmanage.js create mode 100755 livejournal/htdocs/js/entry.js create mode 100755 livejournal/htdocs/js/md5.js create mode 100755 livejournal/htdocs/js/richtext.js create mode 100755 livejournal/htdocs/js/tags.js create mode 100755 livejournal/htdocs/js/talkpost.js create mode 100755 livejournal/htdocs/js/x_core.js create mode 100755 livejournal/htdocs/js/xbDOM.js create mode 100755 livejournal/htdocs/js/xbDebug.js create mode 100755 livejournal/htdocs/js/xbStyle.js create mode 100755 livejournal/htdocs/login.bml create mode 100755 livejournal/htdocs/logout.bml create mode 100755 livejournal/htdocs/lostinfo.bml create mode 100755 livejournal/htdocs/manage/emailpost.bml create mode 100755 livejournal/htdocs/manage/index.bml create mode 100755 livejournal/htdocs/manage/invites.bml create mode 100755 livejournal/htdocs/manage/links.bml create mode 100755 livejournal/htdocs/manage/moodthemes.bml create mode 100755 livejournal/htdocs/manage/pubkey.bml create mode 100755 livejournal/htdocs/manage/siteopts.bml create mode 100755 livejournal/htdocs/manage/tags.bml create mode 100755 livejournal/htdocs/meme.bml create mode 100755 livejournal/htdocs/misc/ack-devserver.bml create mode 100755 livejournal/htdocs/misc/interestdata.bml create mode 100755 livejournal/htdocs/misc/weblogs-change.bml create mode 100755 livejournal/htdocs/modify.bml create mode 100755 livejournal/htdocs/moodlist.bml create mode 100755 livejournal/htdocs/multisearch.bml create mode 100755 livejournal/htdocs/news.bml create mode 100755 livejournal/htdocs/openid/approve.bml create mode 100755 livejournal/htdocs/openid/index.bml create mode 100755 livejournal/htdocs/openid/login.bml create mode 100755 livejournal/htdocs/openid/options.bml create mode 100755 livejournal/htdocs/openid/server.bml create mode 100755 livejournal/htdocs/palimg/colorpicker/longgrad.gif create mode 100755 livejournal/htdocs/palimg/shadow/b.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomleft/bl.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomleft/br.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomleft/tl.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomright/bl.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomright/br.gif create mode 100755 livejournal/htdocs/palimg/shadow/bottomright/tr.gif create mode 100755 livejournal/htdocs/palimg/shadow/l.gif create mode 100755 livejournal/htdocs/palimg/shadow/r.gif create mode 100755 livejournal/htdocs/palimg/shadow/t.gif create mode 100755 livejournal/htdocs/palimg/shadow/topleft/bl.gif create mode 100755 livejournal/htdocs/palimg/shadow/topleft/tl.gif create mode 100755 livejournal/htdocs/palimg/shadow/topleft/tr.gif create mode 100755 livejournal/htdocs/palimg/shadow/topright/br.gif create mode 100755 livejournal/htdocs/palimg/shadow/topright/tl.gif create mode 100755 livejournal/htdocs/palimg/shadow/topright/tr.gif create mode 100755 livejournal/htdocs/palimg/textures/brushed_metal.png create mode 100755 livejournal/htdocs/palimg/textures/burlap.png create mode 100755 livejournal/htdocs/palimg/textures/camouflage.png create mode 100755 livejournal/htdocs/palimg/textures/canvas.png create mode 100755 livejournal/htdocs/palimg/textures/chalk.png create mode 100755 livejournal/htdocs/palimg/textures/cork.png create mode 100755 livejournal/htdocs/palimg/textures/explosion.png create mode 100755 livejournal/htdocs/palimg/textures/fibers.png create mode 100755 livejournal/htdocs/palimg/textures/floral.png create mode 100755 livejournal/htdocs/palimg/textures/ice.png create mode 100755 livejournal/htdocs/palimg/textures/manila.png create mode 100755 livejournal/htdocs/palimg/textures/marble.png create mode 100755 livejournal/htdocs/palimg/textures/paper.png create mode 100755 livejournal/htdocs/palimg/textures/ridge.png create mode 100755 livejournal/htdocs/palimg/textures/rough.png create mode 100755 livejournal/htdocs/palimg/textures/stucco.png create mode 100755 livejournal/htdocs/palimg/textures/terracotta.png create mode 100755 livejournal/htdocs/palimg/textures/type.png create mode 100755 livejournal/htdocs/palimg/textures/wavy.png create mode 100755 livejournal/htdocs/palimg/textures/weave.png create mode 100755 livejournal/htdocs/palimg/textures/wood.png create mode 100755 livejournal/htdocs/poll/create.bml create mode 100755 livejournal/htdocs/poll/index.bml create mode 100755 livejournal/htdocs/portal/alter.bml create mode 100755 livejournal/htdocs/portal/box.bml create mode 100755 livejournal/htdocs/portal/index.bml create mode 100755 livejournal/htdocs/portal/moz.bml create mode 100755 livejournal/htdocs/preview/entry.bml create mode 100755 livejournal/htdocs/protocol.dat create mode 100755 livejournal/htdocs/pubkey.bml create mode 100755 livejournal/htdocs/random.bml create mode 100755 livejournal/htdocs/register.bml create mode 100755 livejournal/htdocs/robots.txt create mode 100755 livejournal/htdocs/rte/blank.html create mode 100755 livejournal/htdocs/rte/palette.html create mode 100755 livejournal/htdocs/stats.bml create mode 100755 livejournal/htdocs/stats/.placeholder create mode 100755 livejournal/htdocs/stats/index.bml create mode 100755 livejournal/htdocs/styles/browse/index.html create mode 100755 livejournal/htdocs/styles/browse/instructions.bml create mode 100755 livejournal/htdocs/styles/browse/links.bml create mode 100755 livejournal/htdocs/styles/browse/start.bml create mode 100755 livejournal/htdocs/styles/browse/styleinfo.bml create mode 100755 livejournal/htdocs/styles/create.bml create mode 100755 livejournal/htdocs/styles/create_do.bml create mode 100755 livejournal/htdocs/styles/edit.bml create mode 100755 livejournal/htdocs/styles/edit_do.bml create mode 100755 livejournal/htdocs/styles/index.bml create mode 100755 livejournal/htdocs/styles/tags.css create mode 100755 livejournal/htdocs/support/act.bml create mode 100755 livejournal/htdocs/support/actmulti.bml create mode 100755 livejournal/htdocs/support/append_request.bml create mode 100755 livejournal/htdocs/support/changenotify.bml create mode 100755 livejournal/htdocs/support/encodings.bml create mode 100755 livejournal/htdocs/support/faq.bml create mode 100755 livejournal/htdocs/support/faqbrowse.bml create mode 100755 livejournal/htdocs/support/faqpop.bml create mode 100755 livejournal/htdocs/support/help.bml create mode 100755 livejournal/htdocs/support/highscores.bml create mode 100755 livejournal/htdocs/support/history.bml create mode 100755 livejournal/htdocs/support/index.bml create mode 100755 livejournal/htdocs/support/see_overrides.bml create mode 100755 livejournal/htdocs/support/see_request.bml create mode 100755 livejournal/htdocs/support/stock_answers.bml create mode 100755 livejournal/htdocs/support/submit.bml create mode 100755 livejournal/htdocs/support/submit_do.bml create mode 100755 livejournal/htdocs/syn/index.bml create mode 100755 livejournal/htdocs/syn/list.bml create mode 100755 livejournal/htdocs/syn/raw.bml create mode 100755 livejournal/htdocs/talkmulti.bml create mode 100755 livejournal/htdocs/talkpost.bml create mode 100755 livejournal/htdocs/talkpost_do.bml create mode 100755 livejournal/htdocs/talkread.bml create mode 100755 livejournal/htdocs/talkscreen.bml create mode 100755 livejournal/htdocs/todo/index.bml create mode 100755 livejournal/htdocs/todo/item.bml create mode 100755 livejournal/htdocs/tools/emailmanage.bml create mode 100755 livejournal/htdocs/tools/index.bml create mode 100755 livejournal/htdocs/tools/memadd.bml create mode 100755 livejournal/htdocs/tools/memories.bml create mode 100755 livejournal/htdocs/tools/recent_comments.bml create mode 100755 livejournal/htdocs/tools/search.bml create mode 100755 livejournal/htdocs/tools/sixdegrees.bml create mode 100755 livejournal/htdocs/tools/tellafriend.bml create mode 100755 livejournal/htdocs/tools/textmessage.bml create mode 100755 livejournal/htdocs/translate/diff.bml create mode 100755 livejournal/htdocs/translate/edit.bml create mode 100755 livejournal/htdocs/translate/editpage.bml create mode 100755 livejournal/htdocs/translate/help-severity.bml create mode 100755 livejournal/htdocs/translate/index.bml create mode 100755 livejournal/htdocs/translate/search.bml create mode 100755 livejournal/htdocs/translate/searchform.bml create mode 100755 livejournal/htdocs/translate/teams.bml create mode 100755 livejournal/htdocs/translate/welcome.bml create mode 100755 livejournal/htdocs/unsubscribe.bml create mode 100755 livejournal/htdocs/update.bml create mode 100755 livejournal/htdocs/userinfo.bml create mode 100755 livejournal/htdocs/utf8convert.bml create mode 100755 livejournal/htdocs/view/index.bml create mode 100755 livejournal/logs/.placeholder create mode 100755 livejournal/sites/README create mode 100755 livejournal/src/historic/README create mode 100755 livejournal/src/historic/brad-log.cgi create mode 100755 livejournal/src/jbackup/jbackup.pl create mode 100755 livejournal/src/utf8.pl create mode 100755 livejournal/src/xmlrpc-client/README.txt create mode 100755 livejournal/src/xmlrpc-client/journal.pl create mode 100755 livejournal/temp/.placeholder create mode 100755 livejournal/test/MANIFEST create mode 100755 livejournal/test/MANIFEST.SKIP create mode 100755 livejournal/test/Makefile.PL create mode 100755 livejournal/test/bin/ipl create mode 100755 livejournal/test/examples/example.test.pl create mode 100755 livejournal/test/examples/moveuclusterd_tests.pl create mode 100755 livejournal/test/lib/LJ/Object.pm create mode 100755 livejournal/test/lib/LJ/Test/Assertions.pm create mode 100755 livejournal/test/lib/LJ/Test/Result.pm create mode 100755 livejournal/test/lib/LJ/Test/Unit.pm create mode 100755 livejournal/var/.placeholder create mode 100644 ljcom/.forward create mode 100644 ljcom/README-ljcom.txt create mode 100644 ljcom/bin/checkconfig-local.pl create mode 100755 ljcom/bin/db create mode 100755 ljcom/bin/fixtime create mode 100755 ljcom/bin/hkill create mode 100755 ljcom/bin/jmk.jar create mode 100755 ljcom/bin/ljcontrib.pl create mode 100755 ljcom/bin/ljrpc create mode 100755 ljcom/bin/ljrpcd create mode 100755 ljcom/bin/ljstatscasterd create mode 100755 ljcom/bin/machine_config.pl create mode 100644 ljcom/bin/maint/aliases.pl create mode 100644 ljcom/bin/maint/clean_caches-local.pl create mode 100644 ljcom/bin/maint/dirsync.pl create mode 100644 ljcom/bin/maint/expiring.pl create mode 100644 ljcom/bin/maint/interests.pl create mode 100644 ljcom/bin/maint/ljadmin.pl create mode 100644 ljcom/bin/maint/moods.pl create mode 100644 ljcom/bin/maint/pay.pl create mode 100644 ljcom/bin/maint/stats-local.pl create mode 100644 ljcom/bin/maint/syncweb.pl create mode 100644 ljcom/bin/maint/taskinfo-local.txt create mode 100644 ljcom/bin/maint/xfers.pl create mode 100644 ljcom/bin/maint/xplanet.pl create mode 100755 ljcom/bin/makemoodindex.pl create mode 100755 ljcom/bin/mcvsui.pl create mode 100755 ljcom/bin/misc/fixuu.pl create mode 100755 ljcom/bin/multideb create mode 100755 ljcom/bin/mytop.pl create mode 100755 ljcom/bin/no-emacs.sh create mode 100755 ljcom/bin/pay-batch create mode 100755 ljcom/bin/pkill create mode 100755 ljcom/bin/qkill create mode 100755 ljcom/bin/release.pl create mode 100755 ljcom/bin/renameuser.pl create mode 100755 ljcom/bin/rewrite-balancer.pl create mode 100755 ljcom/bin/rotate create mode 100755 ljcom/bin/screenshots.pl create mode 100755 ljcom/bin/sourceclean.pl create mode 100755 ljcom/bin/splitlog.pl create mode 100644 ljcom/bin/upgrading/base-data-local.sql create mode 100644 ljcom/bin/upgrading/be.dat create mode 100644 ljcom/bin/upgrading/da.dat create mode 100644 ljcom/bin/upgrading/de.dat create mode 100644 ljcom/bin/upgrading/deadphrases-local.dat create mode 100644 ljcom/bin/upgrading/en_GB.dat create mode 100644 ljcom/bin/upgrading/en_LJ.dat create mode 100644 ljcom/bin/upgrading/eo.dat create mode 100644 ljcom/bin/upgrading/es.dat create mode 100644 ljcom/bin/upgrading/et.dat create mode 100644 ljcom/bin/upgrading/fi.dat create mode 100644 ljcom/bin/upgrading/fr.dat create mode 100644 ljcom/bin/upgrading/ga.dat create mode 100644 ljcom/bin/upgrading/gd.dat create mode 100644 ljcom/bin/upgrading/gr.dat create mode 100644 ljcom/bin/upgrading/he.dat create mode 100644 ljcom/bin/upgrading/hi.dat create mode 100644 ljcom/bin/upgrading/hu.dat create mode 100644 ljcom/bin/upgrading/is.dat create mode 100644 ljcom/bin/upgrading/it.dat create mode 100644 ljcom/bin/upgrading/ja.dat create mode 100644 ljcom/bin/upgrading/la.dat create mode 100644 ljcom/bin/upgrading/lt.dat create mode 100644 ljcom/bin/upgrading/lv.dat create mode 100644 ljcom/bin/upgrading/ms.dat create mode 100644 ljcom/bin/upgrading/nb.dat create mode 100644 ljcom/bin/upgrading/nl.dat create mode 100644 ljcom/bin/upgrading/nn.dat create mode 100644 ljcom/bin/upgrading/pl.dat create mode 100644 ljcom/bin/upgrading/pt.dat create mode 100644 ljcom/bin/upgrading/pt_BR.dat create mode 100644 ljcom/bin/upgrading/ru.dat create mode 100644 ljcom/bin/upgrading/s2layers-local.dat create mode 100644 ljcom/bin/upgrading/s2layers/3column/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/3column/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/anovelconundrum/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/anovelconundrum/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/boxer/boxer.jpg create mode 100644 ljcom/bin/upgrading/s2layers/boxer/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/boxer/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/component/component.jpg create mode 100644 ljcom/bin/upgrading/s2layers/component/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/component/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/cuteness/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/flexiblesquares/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/flexiblesquares/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/nebula/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/nebula/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/opal/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/opal/opal.jpg create mode 100644 ljcom/bin/upgrading/s2layers/opal/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/smoothsailing/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/smoothsailing/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/tranquilityii/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/tranquilityii/themes.s2 create mode 100644 ljcom/bin/upgrading/s2layers/unearthed/layout.s2 create mode 100644 ljcom/bin/upgrading/s2layers/unearthed/themes.s2 create mode 100644 ljcom/bin/upgrading/sv.dat create mode 100644 ljcom/bin/upgrading/text-local.dat create mode 100644 ljcom/bin/upgrading/tr.dat create mode 100644 ljcom/bin/upgrading/uk.dat create mode 100644 ljcom/bin/upgrading/update-db-local.pl create mode 100644 ljcom/bin/upgrading/zh.dat create mode 100644 ljcom/bin/upgrading/zh_TR.dat create mode 100755 ljcom/bin/watch-nodes.pl create mode 100755 ljcom/cgi-bin/bml/scheme/dystopia.look create mode 100644 ljcom/cgi-bin/bml/scheme/ssl.look create mode 100644 ljcom/cgi-bin/console-local.pl create mode 100644 ljcom/cgi-bin/cracklib/README.txt create mode 100644 ljcom/cgi-bin/crumbs-local.pl create mode 100644 ljcom/cgi-bin/ljcom.pl create mode 100644 ljcom/cgi-bin/ljlib-local.pl create mode 100644 ljcom/cgi-bin/modperl-ssl.pl create mode 100644 ljcom/cgi-bin/modperl_subs-local.pl create mode 100644 ljcom/cgi-bin/paylib.pl create mode 100644 ljcom/cgi-bin/phonepost.pl create mode 100644 ljcom/cgi-bin/portal-local.pl create mode 100644 ljcom/cgi-bin/redirect-local.dat create mode 100644 ljcom/cvs/multicvs-local.conf create mode 100644 ljcom/doc/raw/build/style.css create mode 100644 ljcom/doc/raw/local/build-webslave.txt create mode 100755 ljcom/doc/raw/local/cabinets.txt create mode 100755 ljcom/doc/raw/local/goals-visualize.pl create mode 100644 ljcom/doc/raw/local/goals.dat create mode 100644 ljcom/doc/raw/local/hardware.dtd create mode 100644 ljcom/doc/raw/local/hardware.xml create mode 100644 ljcom/doc/raw/memcache-keys-local.txt create mode 100644 ljcom/htdocs/404-error.html create mode 100644 ljcom/htdocs/500-error.html create mode 100644 ljcom/htdocs/_config-local.bml create mode 100644 ljcom/htdocs/admin/abuse/index.bml create mode 100644 ljcom/htdocs/admin/abuse/query.bml create mode 100644 ljcom/htdocs/admin/abuse/send_mail.bml create mode 100644 ljcom/htdocs/admin/accounts/acctedit.bml create mode 100644 ljcom/htdocs/admin/accounts/delivernow.bml create mode 100644 ljcom/htdocs/admin/accounts/depositslip.bml create mode 100644 ljcom/htdocs/admin/accounts/enterbatch.bml create mode 100644 ljcom/htdocs/admin/accounts/enternew.bml create mode 100644 ljcom/htdocs/admin/accounts/fraud_suspects.bml create mode 100644 ljcom/htdocs/admin/accounts/notes.html create mode 100644 ljcom/htdocs/admin/accounts/paiddetails.bml create mode 100644 ljcom/htdocs/admin/accounts/paidsearch.bml create mode 100644 ljcom/htdocs/admin/accounts/paidsummary.bml create mode 100644 ljcom/htdocs/admin/accounts/rr.bml create mode 100644 ljcom/htdocs/admin/accounts/shipping_finish.bml create mode 100644 ljcom/htdocs/admin/accounts/shipping_labels.bml create mode 100644 ljcom/htdocs/admin/accounts/unclaimed_payments.bml create mode 100644 ljcom/htdocs/admin/accounts/xfer_remaining.bml create mode 100644 ljcom/htdocs/admin/codetrace.bml create mode 100644 ljcom/htdocs/admin/feedback/index.bml create mode 100644 ljcom/htdocs/admin/sendmail/query.bml create mode 100644 ljcom/htdocs/admin/sendmail/send.bml create mode 100644 ljcom/htdocs/admin/servers.bml create mode 100644 ljcom/htdocs/admin/support/index.bml create mode 100644 ljcom/htdocs/agecheck/altform.bml create mode 100644 ljcom/htdocs/agecheck/consent.bml create mode 100644 ljcom/htdocs/agecheck/index.bml create mode 100644 ljcom/htdocs/banners.bml create mode 100755 ljcom/htdocs/banners/firebindy1.gif create mode 100644 ljcom/htdocs/bazaar/balance.bml create mode 100644 ljcom/htdocs/bazaar/details.bml create mode 100644 ljcom/htdocs/bazaar/gencoupon.bml create mode 100644 ljcom/htdocs/bazaar/index.bml create mode 100644 ljcom/htdocs/bazaar/status.bml create mode 100644 ljcom/htdocs/bazaar/vote.bml create mode 100644 ljcom/htdocs/betatest.bml create mode 100644 ljcom/htdocs/bots/index.bml create mode 100644 ljcom/htdocs/code/cache/html create mode 100644 ljcom/htdocs/code/cache/index.bml create mode 100644 ljcom/htdocs/code/clients/win32/index.bml create mode 100644 ljcom/htdocs/code/index.bml create mode 100755 ljcom/htdocs/code/mylj/ljsync-0.1.pl.txt create mode 100644 ljcom/htdocs/code/spellcheck/index.bml create mode 100644 ljcom/htdocs/code/textmessage/index.bml create mode 100644 ljcom/htdocs/comment_post.bml create mode 100644 ljcom/htdocs/comment_recv.bml create mode 100644 ljcom/htdocs/dev/mailtest.bml create mode 100644 ljcom/htdocs/dev/s2/2001-02-03.txt create mode 100644 ljcom/htdocs/dev/s2/goals.bml create mode 100644 ljcom/htdocs/dev/s2/index.bml create mode 100644 ljcom/htdocs/developer/embedding.bml create mode 100644 ljcom/htdocs/developer/exporting.bml create mode 100644 ljcom/htdocs/developer/index.bml create mode 100644 ljcom/htdocs/developer/lj-icons.zip create mode 100644 ljcom/htdocs/developer/logo.gif create mode 100644 ljcom/htdocs/developer/modeinfo.bml create mode 100644 ljcom/htdocs/developer/modelist.bml create mode 100755 ljcom/htdocs/developer/moods.txt create mode 100644 ljcom/htdocs/developer/protocol.bml create mode 100644 ljcom/htdocs/developer/rawmode.bml create mode 100644 ljcom/htdocs/developer/styles.bml create mode 100644 ljcom/htdocs/developer/time-problem.txt create mode 100644 ljcom/htdocs/developer/varinfo.bml create mode 100644 ljcom/htdocs/developer/varlist.bml create mode 100755 ljcom/htdocs/developer/versions.bml create mode 100644 ljcom/htdocs/developer/views.bml create mode 100755 ljcom/htdocs/developer/winamp.txt create mode 100755 ljcom/htdocs/doc/find/index.bml create mode 100644 ljcom/htdocs/doc/guide/index.bml create mode 100644 ljcom/htdocs/doc/guide/moodicons.bml create mode 100644 ljcom/htdocs/doc/guide/support.bml create mode 100644 ljcom/htdocs/doc/index.bml create mode 100644 ljcom/htdocs/doc/internal/fcgi-acheck.bml create mode 100644 ljcom/htdocs/doc/pay/diskupgrades.bml create mode 100644 ljcom/htdocs/doc/tour/index.bml create mode 100644 ljcom/htdocs/download/index.bml create mode 100644 ljcom/htdocs/favicon.ico create mode 100644 ljcom/htdocs/feedback/fotobilder.bml create mode 100644 ljcom/htdocs/feedback/index.bml create mode 100644 ljcom/htdocs/friends/popwithfriends.bml create mode 100644 ljcom/htdocs/img/2004_webbywinner.gif create mode 100644 ljcom/htdocs/img/LJbanner1.gif create mode 100644 ljcom/htdocs/img/LJbanner2.gif create mode 100644 ljcom/htdocs/img/LJbanner3.gif create mode 100644 ljcom/htdocs/img/LJbanner4.gif create mode 100644 ljcom/htdocs/img/LJbanner5.gif create mode 100644 ljcom/htdocs/img/LJbanner6.gif create mode 100644 ljcom/htdocs/img/LJbanner7.gif create mode 100644 ljcom/htdocs/img/LJbanner8.gif create mode 100644 ljcom/htdocs/img/LJbanner9.gif create mode 100644 ljcom/htdocs/img/LJbanner_metal.gif create mode 100644 ljcom/htdocs/img/LJbanner_pastel.gif create mode 100644 ljcom/htdocs/img/blue_check.gif create mode 100644 ljcom/htdocs/img/deletedphone.gif create mode 100644 ljcom/htdocs/img/downarrow.gif create mode 100755 ljcom/htdocs/img/download.gif create mode 100755 ljcom/htdocs/img/dys/5x5.gif create mode 100755 ljcom/htdocs/img/dys/b_blue.gif create mode 100755 ljcom/htdocs/img/dys/b_cyan.gif create mode 100755 ljcom/htdocs/img/dys/b_purp.gif create mode 100755 ljcom/htdocs/img/dys/bg.gif create mode 100755 ljcom/htdocs/img/dys/bg2.gif create mode 100755 ljcom/htdocs/img/dys/bg_top.gif create mode 100644 ljcom/htdocs/img/dys/corn_ne.gif create mode 100644 ljcom/htdocs/img/dys/corn_nw.gif create mode 100644 ljcom/htdocs/img/dys/corn_se.gif create mode 100644 ljcom/htdocs/img/dys/corn_sw.gif create mode 100755 ljcom/htdocs/img/dys/lg_crnrgif.gif create mode 100755 ljcom/htdocs/img/dys/login_but.gif create mode 100755 ljcom/htdocs/img/dys/loginbar.gif create mode 100755 ljcom/htdocs/img/dys/logo1.gif create mode 100755 ljcom/htdocs/img/dys/logo2.gif create mode 100755 ljcom/htdocs/img/dys/logo3-lang.gif create mode 100755 ljcom/htdocs/img/dys/logo3.gif create mode 100644 ljcom/htdocs/img/goat-hiring.png create mode 100755 ljcom/htdocs/img/goat-hover.gif create mode 100755 ljcom/htdocs/img/goat-irish.gif create mode 100644 ljcom/htdocs/img/goat-lights.gif create mode 100644 ljcom/htdocs/img/goat-newyear.gif create mode 100755 ljcom/htdocs/img/goat-normal.gif create mode 100755 ljcom/htdocs/img/goat-pee.gif create mode 100644 ljcom/htdocs/img/goat-val.gif create mode 100644 ljcom/htdocs/img/goat-xmas.gif create mode 100644 ljcom/htdocs/img/goat.gif create mode 100644 ljcom/htdocs/img/goat.jpg create mode 100644 ljcom/htdocs/img/index.html create mode 100644 ljcom/htdocs/img/mood-local.tgz create mode 100644 ljcom/htdocs/img/overlap.png create mode 100644 ljcom/htdocs/img/overlap2.png create mode 100755 ljcom/htdocs/img/paypal-buynow.gif create mode 100644 ljcom/htdocs/img/phonepost.gif create mode 100644 ljcom/htdocs/img/phonepost2.gif create mode 100644 ljcom/htdocs/img/schemethumb/dystopia.png create mode 100644 ljcom/htdocs/img/schemethumb/lynx.png create mode 100644 ljcom/htdocs/img/schemethumb/xcolibur.png create mode 100644 ljcom/htdocs/img/style/3column/comments.gif create mode 100644 ljcom/htdocs/img/style/3column/editentry.gif create mode 100644 ljcom/htdocs/img/style/3column/edittags.gif create mode 100644 ljcom/htdocs/img/style/3column/leavecomment.gif create mode 100644 ljcom/htdocs/img/style/3column/memories.gif create mode 100644 ljcom/htdocs/img/style/3column/permalink.gif create mode 100644 ljcom/htdocs/img/style/cuteness/bg-pink.gif create mode 100644 ljcom/htdocs/img/style/cuteness/content-header.gif create mode 100644 ljcom/htdocs/img/style/cuteness/entry-bg.gif create mode 100644 ljcom/htdocs/img/style/cuteness/entry-bottombg.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-curious.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-cute.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-dizzy.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-doll.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-happy.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-japanese.gif create mode 100644 ljcom/htdocs/img/style/cuteness/face-square.gif create mode 100644 ljcom/htdocs/img/style/cuteness/footerbg.gif create mode 100644 ljcom/htdocs/img/style/cuteness/menubg.gif create mode 100644 ljcom/htdocs/img/style/cuteness/userpicbg.gif create mode 100644 ljcom/htdocs/img/stylecontest2/3collumn_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/anovelconundrum_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/applyexternally_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/bob_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/colorplay_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/deardiary_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/dinky_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/divified_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/drifting_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/flexiblesquares_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/geometrix_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/gradientstrip_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/mobiledevicestyle_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/nebula_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/negatives_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/newsworthy_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/smoothsailing_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/solitude_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/statuesque_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/superspecialballoons_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/texturized_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/tranquilityii_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/transmogrified_thumb.jpg create mode 100644 ljcom/htdocs/img/stylecontest2/widelines_thumb.jpg create mode 100644 ljcom/htdocs/img/tos-logo.png create mode 100644 ljcom/htdocs/img/tour/clients.jpg create mode 100644 ljcom/htdocs/img/tour/clients.png create mode 100644 ljcom/htdocs/img/tour/comms.jpg create mode 100644 ljcom/htdocs/img/tour/create.png create mode 100644 ljcom/htdocs/img/tour/friends.jpg create mode 100644 ljcom/htdocs/img/tour/intro.png create mode 100644 ljcom/htdocs/img/tour/modify.png create mode 100644 ljcom/htdocs/img/tour/profile.png create mode 100644 ljcom/htdocs/img/tour/sitemap.png create mode 100644 ljcom/htdocs/img/tour/support.png create mode 100644 ljcom/htdocs/img/tour/update.png create mode 100644 ljcom/htdocs/img/tshirt_banner.gif create mode 100644 ljcom/htdocs/img/tshirt_goat.gif create mode 100644 ljcom/htdocs/img/tshirt_goat2.gif create mode 100644 ljcom/htdocs/img/tshirts/thumb/babydoll-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/babydoll-grey.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/babydoll-pink.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/babydoll-royalblue.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/babydoll-white.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/hooded-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/hooded-grey.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/long-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/long-grey.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/long-navyblue.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/long-white.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/polo-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/polo-grey.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/polo-navyblue.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/polo-white.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-bluedusk.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-grey.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-leaf.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-orange.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/short-white.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/twillhat-black.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/twillhat-khaki.jpg create mode 100644 ljcom/htdocs/img/tshirts/thumb/twillhat-navyblue.jpg create mode 100644 ljcom/htdocs/img/uparrow.gif create mode 100755 ljcom/htdocs/img/webbylogo.gif create mode 100644 ljcom/htdocs/inc/account-codes create mode 100644 ljcom/htdocs/inc/community create mode 100644 ljcom/htdocs/inc/foobar create mode 100644 ljcom/htdocs/inc/legal-tos create mode 100644 ljcom/htdocs/inc/resources-homonyms create mode 100644 ljcom/htdocs/inc/resources-index create mode 100644 ljcom/htdocs/inc/spam-warning create mode 100644 ljcom/htdocs/inc/validationreminder create mode 100644 ljcom/htdocs/index.bml create mode 100644 ljcom/htdocs/invite/claim.bml create mode 100644 ljcom/htdocs/invite/gen.bml create mode 100644 ljcom/htdocs/invite/index.bml create mode 100644 ljcom/htdocs/legal/coppa.bml create mode 100644 ljcom/htdocs/legal/disclaimer.bml create mode 100644 ljcom/htdocs/legal/dmca.bml create mode 100644 ljcom/htdocs/legal/index.bml create mode 100644 ljcom/htdocs/legal/principles.bml create mode 100644 ljcom/htdocs/legal/privacy.bml create mode 100644 ljcom/htdocs/legal/tos-mini.bml create mode 100644 ljcom/htdocs/legal/tos.bml create mode 100644 ljcom/htdocs/manage/files.bml create mode 100644 ljcom/htdocs/manage/phonepost.bml create mode 100644 ljcom/htdocs/misc/clusterlj/index.html create mode 100644 ljcom/htdocs/misc/clusterlj/ljarch.png create mode 100644 ljcom/htdocs/misc/clusterlj/rev01.html create mode 100644 ljcom/htdocs/misc/clusterlj/rev02.html create mode 100644 ljcom/htdocs/misc/clusterlj/usagepie-large.png create mode 100644 ljcom/htdocs/misc/goals.html create mode 100644 ljcom/htdocs/misc/goals/goals-20020209.gif create mode 100644 ljcom/htdocs/misc/goals/goals-20020209.html create mode 100644 ljcom/htdocs/misc/goals/goals-20020605.gif create mode 100644 ljcom/htdocs/misc/goals/goals-20020605.html create mode 100644 ljcom/htdocs/misc/index.html create mode 100644 ljcom/htdocs/misc/ljlogo/lj.ico create mode 100644 ljcom/htdocs/misc/ljlogo/lj_logo.svg create mode 100644 ljcom/htdocs/misc/ljlogo/lj_logo_bw.svg create mode 100644 ljcom/htdocs/misc/pkg-webslave.txt create mode 100644 ljcom/htdocs/misc/whereami.bml create mode 100644 ljcom/htdocs/news.bml create mode 100644 ljcom/htdocs/news/2000-11-23/index.bml create mode 100644 ljcom/htdocs/news/2000-11-23/now.gif create mode 100644 ljcom/htdocs/news/2000-11-23/proposed.gif create mode 100644 ljcom/htdocs/news/2004-01-qa.bml create mode 100644 ljcom/htdocs/news/index.bml create mode 100644 ljcom/htdocs/news/tshirt-poll.bml create mode 100644 ljcom/htdocs/paidaccounts/2004_december_promo.bml create mode 100644 ljcom/htdocs/paidaccounts/apply.bml create mode 100644 ljcom/htdocs/paidaccounts/buy.bml create mode 100644 ljcom/htdocs/paidaccounts/friends.bml create mode 100644 ljcom/htdocs/paidaccounts/index.bml create mode 100644 ljcom/htdocs/paidaccounts/joincommunity.bml create mode 100644 ljcom/htdocs/paidaccounts/newacct.bml create mode 100644 ljcom/htdocs/paidaccounts/pp_notify.bml create mode 100644 ljcom/htdocs/paidaccounts/status.bml create mode 100644 ljcom/htdocs/paidaccounts/thankyou.bml create mode 100644 ljcom/htdocs/paidaccounts/usepaypal.bml create mode 100644 ljcom/htdocs/paidaccounts/whyextra.bml create mode 100644 ljcom/htdocs/palimg/anovelconundrum/dingbar.gif create mode 100644 ljcom/htdocs/pay/checkout.bml create mode 100644 ljcom/htdocs/pay/coupons.bml create mode 100644 ljcom/htdocs/pay/history.bml create mode 100644 ljcom/htdocs/pay/index.bml create mode 100644 ljcom/htdocs/pay/modify.bml create mode 100644 ljcom/htdocs/phonepost/about.bml create mode 100644 ljcom/htdocs/phonepost/encodings.bml create mode 100644 ljcom/htdocs/phonepost/index.bml create mode 100644 ljcom/htdocs/phonepost/numbers.bml create mode 100644 ljcom/htdocs/phonepost/ogg.bml create mode 100644 ljcom/htdocs/phonepost/transcribe.bml create mode 100644 ljcom/htdocs/poll/goatvote.bml create mode 100644 ljcom/htdocs/press/articles.bml create mode 100644 ljcom/htdocs/press/index.bml create mode 100644 ljcom/htdocs/press/staff.bml create mode 100644 ljcom/htdocs/rename/buy.bml create mode 100644 ljcom/htdocs/rename/index.bml create mode 100644 ljcom/htdocs/rename/use.bml create mode 100644 ljcom/htdocs/resources/homonyms.bml create mode 100644 ljcom/htdocs/resources/index.bml create mode 100644 ljcom/htdocs/resources/whowhom.bml create mode 100644 ljcom/htdocs/singles/index.bml create mode 100644 ljcom/htdocs/singles/mod.bml create mode 100644 ljcom/htdocs/singles/search.bml create mode 100644 ljcom/htdocs/site/about.bml create mode 100644 ljcom/htdocs/site/banners.bml create mode 100644 ljcom/htdocs/site/contract.bml create mode 100644 ljcom/htdocs/site/contributors.bml create mode 100644 ljcom/htdocs/site/free.bml create mode 100644 ljcom/htdocs/site/goat.bml create mode 100644 ljcom/htdocs/site/hardware.bml create mode 100644 ljcom/htdocs/site/index.bml create mode 100644 ljcom/htdocs/site/search.bml create mode 100644 ljcom/htdocs/site/software.bml create mode 100644 ljcom/htdocs/static/style/syn.css create mode 100644 ljcom/htdocs/stats/latest-img.bml create mode 100644 ljcom/htdocs/stats/latest-rss.bml create mode 100644 ljcom/htdocs/stats/latest.bml create mode 100644 ljcom/htdocs/stats/weblog-updates-xml.bml create mode 100644 ljcom/htdocs/store/index.bml create mode 100644 ljcom/htdocs/store/sizechart.bml create mode 100644 ljcom/htdocs/store/view.bml create mode 100755 ljcom/htdocs/suggestions/generator.bml create mode 100644 ljcom/htdocs/suggestions/index.bml create mode 100644 ljcom/htdocs/suggestions/prior.bml create mode 100644 ljcom/htdocs/suggestions/template.bml create mode 100644 ljcom/htdocs/template.bml create mode 100644 ljcom/htdocs/tools/xfer_remaining.bml create mode 100755 ljcom/sites/mrtg/index.cgi create mode 100755 ljcom/src/ibill-templates/generate.pl create mode 100755 ljcom/src/ibill-templates/template.html create mode 100755 ljcom/src/ljcom/myoverlap.pl create mode 100644 ljcom/src/mod_latency/mod_latency.c create mode 100644 ljcom/src/phonepost/README create mode 100755 ljcom/src/phonepost/agi-bin/livejournal create mode 100644 ljcom/src/phonepost/debian/README create mode 100644 ljcom/src/phonepost/debian/asterisk-deb-20030912.patch create mode 100644 ljcom/src/phonepost/doc/code create mode 100644 ljcom/src/phonepost/doc/overview create mode 100644 ljcom/src/phonepost/doc/script create mode 100644 ljcom/src/phonepost/etc/extensions.conf create mode 100644 ljcom/src/rewrite-balancer/README.txt create mode 100644 ljcom/src/rewrite-balancer/rewrite-balancer.c create mode 100644 ljcom/src/testfile create mode 100644 ljcom/ssldocs/_config.bml create mode 100644 ljcom/ssldocs/img/amex.jpg create mode 100755 ljcom/ssldocs/img/dys/5x5.gif create mode 100755 ljcom/ssldocs/img/dys/b_blue.gif create mode 100755 ljcom/ssldocs/img/dys/b_cyan.gif create mode 100755 ljcom/ssldocs/img/dys/b_purp.gif create mode 100755 ljcom/ssldocs/img/dys/bg.gif create mode 100755 ljcom/ssldocs/img/dys/bg2.gif create mode 100755 ljcom/ssldocs/img/dys/bg_top.gif create mode 100644 ljcom/ssldocs/img/dys/corn_ne.gif create mode 100644 ljcom/ssldocs/img/dys/corn_nw.gif create mode 100644 ljcom/ssldocs/img/dys/corn_se.gif create mode 100644 ljcom/ssldocs/img/dys/corn_sw.gif create mode 100755 ljcom/ssldocs/img/dys/lg_crnrgif.gif create mode 100644 ljcom/ssldocs/img/dys/lock.gif create mode 100755 ljcom/ssldocs/img/dys/login_but.gif create mode 100755 ljcom/ssldocs/img/dys/loginbar.gif create mode 100755 ljcom/ssldocs/img/dys/logo1.gif create mode 100755 ljcom/ssldocs/img/dys/logo2.gif create mode 100755 ljcom/ssldocs/img/dys/logo3.gif create mode 100644 ljcom/ssldocs/img/userinfo.gif create mode 100644 ljcom/ssldocs/img/visa.jpg create mode 100644 ljcom/ssldocs/img/xc/allbars.gif create mode 100644 ljcom/ssldocs/img/xc/basic.css create mode 100644 ljcom/ssldocs/img/xc/extended.css create mode 100644 ljcom/ssldocs/img/xc/lock.gif create mode 100644 ljcom/ssldocs/img/xc/logocombined.gif create mode 100644 ljcom/ssldocs/img/xc/normal-fonts.css create mode 100644 ljcom/ssldocs/img/xc/small-fonts.css create mode 100644 ljcom/ssldocs/index.bml create mode 100644 ljcom/ssldocs/pay/cc.bml create mode 100644 ljcom/ssldocs/pay/ccpay.bml create mode 100644 ljcom/ssldocs/pay/cvv2.bml create mode 100644 ljcom/ssldocs/pay/index.bml create mode 100755 local/bin/checkconfig.pl create mode 100755 local/bin/ljr-tools/clean_cached_comments.pl create mode 100755 local/bin/ljr-tools/copy_openid_infos.pl create mode 100755 local/bin/ljr-tools/delete_imported.pl create mode 100755 local/bin/ljr-tools/import_pics_for_user.pl create mode 100755 local/bin/ljr-tools/mass_update_journal.pl create mode 100755 local/bin/ljr-tools/mysql-convert-storable.pl create mode 100755 local/bin/ljr-tools/rlj2-ljrgate.pl create mode 100755 local/bin/ljrimport/Simple.pm create mode 100755 local/bin/ljrimport/icomments.pl create mode 100755 local/bin/ljrimport/ijournal.pl create mode 100755 local/bin/ljrimport/ipics.pl create mode 100755 local/bin/ljrimport/ljr-defaults.pl create mode 100755 local/bin/ljrimport/ljr-import.pl create mode 100755 local/bin/ljrimport/ljr-importdo.pl create mode 100755 local/bin/ljrimport/ljr-links.pl create mode 100755 local/bin/ljrimport/ljr-start.sh create mode 100755 local/bin/ljrimport/ljr-stop.sh create mode 100755 local/bin/maint/clean_challenges.pl create mode 100755 local/bin/maint/stats.pl create mode 100755 local/bin/maint/synsuck.pl create mode 100755 local/bin/maint/taskinfo.txt create mode 100755 local/bin/qbufferd.pl create mode 100755 local/bin/upgrading/en.dat create mode 100755 local/bin/upgrading/en_LJ.dat create mode 100755 local/bin/upgrading/ru.dat create mode 100755 local/bin/upgrading/s2layers-local.dat create mode 100755 local/bin/upgrading/s2layers/3column/layout.s2 create mode 100755 local/bin/upgrading/s2layers/3column/themes.s2 create mode 100755 local/bin/upgrading/s2layers/anovelconundrum/layout.s2 create mode 100755 local/bin/upgrading/s2layers/anovelconundrum/themes.s2 create mode 100755 local/bin/upgrading/s2layers/boxer/boxer.jpg create mode 100755 local/bin/upgrading/s2layers/boxer/layout.s2 create mode 100755 local/bin/upgrading/s2layers/boxer/themes.s2 create mode 100755 local/bin/upgrading/s2layers/component/component.jpg create mode 100755 local/bin/upgrading/s2layers/component/layout.s2 create mode 100755 local/bin/upgrading/s2layers/component/themes.s2 create mode 100755 local/bin/upgrading/s2layers/cuteness/layout.s2 create mode 100755 local/bin/upgrading/s2layers/flexiblesquares/layout.s2 create mode 100755 local/bin/upgrading/s2layers/flexiblesquares/themes.s2 create mode 100755 local/bin/upgrading/s2layers/nebula/layout.s2 create mode 100755 local/bin/upgrading/s2layers/nebula/themes.s2 create mode 100755 local/bin/upgrading/s2layers/opal/layout.s2 create mode 100755 local/bin/upgrading/s2layers/opal/opal.jpg create mode 100755 local/bin/upgrading/s2layers/opal/themes.s2 create mode 100755 local/bin/upgrading/s2layers/smoothsailing/layout.s2 create mode 100755 local/bin/upgrading/s2layers/smoothsailing/themes.s2 create mode 100755 local/bin/upgrading/s2layers/tranquility2/layout.s2 create mode 100755 local/bin/upgrading/s2layers/tranquilityii/layout.s2 create mode 100755 local/bin/upgrading/s2layers/tranquilityii/themes.s2 create mode 100755 local/bin/upgrading/s2layers/unearthed/layout.s2 create mode 100755 local/bin/upgrading/s2layers/unearthed/themes.s2 create mode 100644 local/bin/upgrading/sb.dat create mode 100755 local/bin/upgrading/text-local.dat create mode 100644 local/bin/upgrading/texttool-overrides create mode 100755 local/bin/upgrading/texttool.pl create mode 100644 local/bin/upgrading/uk.dat create mode 100755 local/bin/upgrading/update-db-general.pl create mode 100755 local/cgi-bin/Apache/BML.pm create mode 100755 local/cgi-bin/Apache/LiveJournal.pm create mode 100644 local/cgi-bin/CSS/Cleaner.pm create mode 100755 local/cgi-bin/Cache/Memcached.pm create mode 100644 local/cgi-bin/Golem.pm create mode 100644 local/cgi-bin/Golem/dblib.pl create mode 100644 local/cgi-bin/Golem/loglib.pl create mode 100644 local/cgi-bin/Golem/netlib.pl create mode 100644 local/cgi-bin/Golem/proplib.pl create mode 100644 local/cgi-bin/Golem/textlib.pl create mode 100644 local/cgi-bin/HTMLCleaner.pm create mode 100644 local/cgi-bin/LJ/Auth.pm create mode 100644 local/cgi-bin/LJ/CSS/Cleaner.pm create mode 100644 local/cgi-bin/LJ/ConvUTF8.pm create mode 100644 local/cgi-bin/LJ/EmbedModule.pm create mode 100644 local/cgi-bin/LJ/Entry.pm create mode 100755 local/cgi-bin/LJ/OpenID.pm create mode 100755 local/cgi-bin/LJ/S2.pm create mode 100755 local/cgi-bin/LJ/S2/DayPage.pm create mode 100755 local/cgi-bin/LJ/S2/EntryPage.pm create mode 100755 local/cgi-bin/LJ/S2/FriendsPage.pm create mode 100755 local/cgi-bin/LJ/S2/MonthPage.pm create mode 100755 local/cgi-bin/LJ/S2/RecentPage.pm create mode 100755 local/cgi-bin/LJ/S2/ReplyPage.pm create mode 100755 local/cgi-bin/LJ/S2/YearPage.pm create mode 100755 local/cgi-bin/LJ/TextMessage.pm create mode 100755 local/cgi-bin/LJ/User.pm create mode 100755 local/cgi-bin/LJR/Distributed.pm create mode 100644 local/cgi-bin/LJR/GD.pm create mode 100644 local/cgi-bin/LJR/Gate.pm create mode 100755 local/cgi-bin/LJR/Viewuser.pm create mode 100755 local/cgi-bin/LJR/Viewuserstandalone.pm create mode 100644 local/cgi-bin/LJR/ljpoll-local.pl create mode 100644 local/cgi-bin/LJR/unicode.pm create mode 100644 local/cgi-bin/LJR/xmlrpc.pm create mode 100755 local/cgi-bin/LWPx/ParanoidAgent.pm create mode 100755 local/cgi-bin/Net/OpenID/Association.pm create mode 100755 local/cgi-bin/Net/OpenID/Consumer.pm create mode 100755 local/cgi-bin/bml/scheme/added.variables create mode 100755 local/cgi-bin/bml/scheme/bluewhite.look create mode 100755 local/cgi-bin/bml/scheme/dystopia.look create mode 100755 local/cgi-bin/bml/scheme/global.look create mode 100755 local/cgi-bin/bml/scheme/global.look.original create mode 100755 local/cgi-bin/bml/scheme/ljr.look create mode 100755 local/cgi-bin/bml/scheme/opalcat.look create mode 100755 local/cgi-bin/bml/scheme/redwhite.look create mode 100755 local/cgi-bin/bml/scheme/vari create mode 100755 local/cgi-bin/cleanhtml.pl create mode 100755 local/cgi-bin/communitylib-local.pl create mode 100755 local/cgi-bin/communitylib.pl create mode 100755 local/cgi-bin/console-local.pl create mode 100755 local/cgi-bin/console.pl create mode 100755 local/cgi-bin/consuspend.pl create mode 100755 local/cgi-bin/directorylib.pl create mode 100755 local/cgi-bin/emailcheck.pl create mode 100755 local/cgi-bin/ljcom.pl create mode 100755 local/cgi-bin/ljdefaults.pl create mode 100755 local/cgi-bin/ljfeed.pl create mode 100755 local/cgi-bin/ljlang.pl create mode 100755 local/cgi-bin/ljlib-local.pl create mode 100755 local/cgi-bin/ljlib.pl create mode 100755 local/cgi-bin/ljmail.pl create mode 100755 local/cgi-bin/ljpoll.pl create mode 100755 local/cgi-bin/ljprotocol.pl create mode 100755 local/cgi-bin/ljr_readconf.pl create mode 100644 local/cgi-bin/ljtextutil.pl create mode 100755 local/cgi-bin/ljviews.pl create mode 100755 local/cgi-bin/modperl_subs.pl create mode 100755 local/cgi-bin/parsefeed.pl create mode 100755 local/cgi-bin/phonepost.pl create mode 100755 local/cgi-bin/taglib.pl create mode 100755 local/cgi-bin/talklib.pl create mode 100755 local/cgi-bin/weblib.pl create mode 100755 local/htdocs/.htaccess create mode 100755 local/htdocs/404-error.html create mode 100755 local/htdocs/_config-local.bml create mode 100755 local/htdocs/admin/console/index.bml create mode 100755 local/htdocs/admin/console/reference.bml create mode 100644 local/htdocs/admin/ljr/.htaccess create mode 100644 local/htdocs/admin/ljr/import-queue.bml create mode 100755 local/htdocs/admin/ljr/import-results.bml create mode 100755 local/htdocs/admin/memcache-keys.txt create mode 100755 local/htdocs/admin/memcache.bml create mode 100755 local/htdocs/admin/memcache_view.bml create mode 100755 local/htdocs/admin/netstat.bml create mode 100755 local/htdocs/admin/priv/index.bml create mode 100755 local/htdocs/bots/index.html create mode 100755 local/htdocs/changepassword.bml create mode 100755 local/htdocs/community/create.bml create mode 100755 local/htdocs/community/join.bml create mode 100755 local/htdocs/community/pending.bml create mode 100755 local/htdocs/community/settings.bml create mode 100755 local/htdocs/create.bml create mode 100755 local/htdocs/customize/advanced/layerbrowse.bml create mode 100755 local/htdocs/customize/advanced/layeredit.bml create mode 100755 local/htdocs/customize/advanced/layers.bml create mode 100755 local/htdocs/customize/advanced/styles.bml create mode 100755 local/htdocs/delcomment.bml create mode 100755 local/htdocs/developer/index.html create mode 100755 local/htdocs/directory.bml create mode 100644 local/htdocs/download/index.bml create mode 100755 local/htdocs/editinfo.bml create mode 100755 local/htdocs/edittags.bml create mode 100644 local/htdocs/export_comments.bml create mode 100755 local/htdocs/export_do.bml create mode 100755 local/htdocs/favicon-misha.ico create mode 100755 local/htdocs/favicon-petya.ico create mode 100755 local/htdocs/favicon.ico create mode 100755 local/htdocs/friends/pipiskomer.bml create mode 100755 local/htdocs/friends/popwithfriends.bml create mode 100755 local/htdocs/go.bml create mode 100755 local/htdocs/guidelines.html create mode 100755 local/htdocs/img/blue_check.gif create mode 100755 local/htdocs/img/btn_addfriend.gif create mode 100755 local/htdocs/img/btn_edit.gif create mode 100755 local/htdocs/img/community-lj.gif create mode 100755 local/htdocs/img/community-npj.gif create mode 100755 local/htdocs/img/community.gif create mode 100755 local/htdocs/img/imported-profile.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/accomplished.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/amused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/angry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/anxious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/apathetic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/artistic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/awake.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/bitchy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/blank.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/bouncy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/busy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/calm.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/cold.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/complacent.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/confused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/crazy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/crushed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/curious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/cynical.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/determined.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/devious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/disappointed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/drained.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/drunk.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/embarrassed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/envious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/exanimate.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/flirty.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/full.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/geeky.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/giddy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/gloomy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/good.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/groggy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/grumpy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/happy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/horny.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/hot.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/hungry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/indescribable.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/loved.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/predatory.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/restless.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/sad.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/shocked.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/sick.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/sleepy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/sore.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/thoughtful.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/tired.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/working.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/black/worried.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/accomplished.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/amused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/angry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/anxious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/apathetic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/artistic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/awake.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/bitchy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/blank.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/bouncy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/busy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/calm.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/cold.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/complacent.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/confused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/crazy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/crushed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/curious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/cynical.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/determined.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/devious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/disappointed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/drained.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/drunk.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/embarrassed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/envious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/exanimate.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/flirty.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/full.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/geeky.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/giddy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/gloomy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/good.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/groggy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/grumpy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/happy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/horny.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/hot.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/hungry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/indescribable.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/loved.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/predatory.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/restless.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/sad.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/shocked.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/sick.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/sleepy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/sore.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/thoughtful.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/tired.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/working.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/red/worried.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/accomplished.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/amused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/angry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/anxious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/apathetic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/artistic.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/awake.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/bitchy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/blank.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/bouncy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/busy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/calm.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/cold.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/complacent.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/confused.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/crazy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/crushed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/curious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/cynical.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/determined.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/devious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/disappointed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/drained.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/drunk.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/embarrassed.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/envious.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/exanimate.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/flirty.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/full.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/geeky.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/giddy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/gloomy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/good.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/groggy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/grumpy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/happy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/horny.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/hot.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/hungry.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/indescribable.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/loved.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/predatory.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/restless.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/sad.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/shocked.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/sick.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/sleepy.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/sore.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/thoughtful.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/tired.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/working.gif create mode 100755 local/htdocs/img/mood/bitospud/courier/white/worried.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/angry.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/artistic.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/bouncy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/cold.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/crazy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/curious.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/determined.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/devilish.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/dirty.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/drunk.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/embarrassed.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/envy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/gloomy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/green.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/happy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/hot.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/hungry.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/loved.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/nerdy.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/okay.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/peaceful.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/relaxed.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/sad.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/scared.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/sore.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/suprised.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/thirsty.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/thoughtful.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/tired.gif create mode 100755 local/htdocs/img/mood/charitycam/blackbox/working.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/angry.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/artistic.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/awake.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/bouncy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/cold.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/confused.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/determined.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/devlish.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/dirty.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/drunk.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/embarrased.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/envious.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/full.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/gloomy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/happy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/high.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/hot.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/hungry.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/loved.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/nerdy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/okay.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/sad.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/scared.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/shocked.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/sick.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/silly.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/sleepy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/stressed.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/thirsty.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/thoughtful.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/tired.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_boy/working.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/angry.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/artistic.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/cold.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/curious.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/determined.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/devious.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/dirty.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/drunk.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/envious.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/full.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/gloomy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/happy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/high.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/hot.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/hungry.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/loved.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/nerdy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/okay.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/sad.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/scared.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/sick.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/silly.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/sleepy.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/stressed.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/surprised.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/thoughtful.gif create mode 100755 local/htdocs/img/mood/charitycam/goth_girl/working.gif create mode 100755 local/htdocs/img/mood/classic/angry.gif create mode 100755 local/htdocs/img/mood/classic/blah.gif create mode 100755 local/htdocs/img/mood/classic/blush.gif create mode 100755 local/htdocs/img/mood/classic/confused.gif create mode 100755 local/htdocs/img/mood/classic/devious.gif create mode 100755 local/htdocs/img/mood/classic/drunk.gif create mode 100755 local/htdocs/img/mood/classic/energetic.gif create mode 100755 local/htdocs/img/mood/classic/sad.gif create mode 100755 local/htdocs/img/mood/classic/shock.gif create mode 100755 local/htdocs/img/mood/classic/sick.gif create mode 100755 local/htdocs/img/mood/classic/smile.gif create mode 100755 local/htdocs/img/mood/classic/thinking.gif create mode 100755 local/htdocs/img/mood/classic/tired.gif create mode 100755 local/htdocs/img/mood/classic/wink.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/angry.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/annoyed.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/blah.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/blank.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/blush.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/bouncy.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/confused.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/cool.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/determined.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/devious.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/dirty.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/geeky.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/high.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/hot.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/hyper.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/idea.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/sad.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/shocked.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/sick.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/smile.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/snore.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/surprised.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/tearful.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/think.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/up.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/weird.gif create mode 100755 local/htdocs/img/mood/growf/dwaggins/working.gif create mode 100755 local/htdocs/img/mood/growf/pengies/amused.gif create mode 100755 local/htdocs/img/mood/growf/pengies/annoyed.gif create mode 100755 local/htdocs/img/mood/growf/pengies/balloon.gif create mode 100755 local/htdocs/img/mood/growf/pengies/blank.gif create mode 100755 local/htdocs/img/mood/growf/pengies/blushing.gif create mode 100755 local/htdocs/img/mood/growf/pengies/bouncy.gif create mode 100755 local/htdocs/img/mood/growf/pengies/confused.gif create mode 100755 local/htdocs/img/mood/growf/pengies/cool.gif create mode 100755 local/htdocs/img/mood/growf/pengies/determined.gif create mode 100755 local/htdocs/img/mood/growf/pengies/devious.gif create mode 100755 local/htdocs/img/mood/growf/pengies/drunk.gif create mode 100755 local/htdocs/img/mood/growf/pengies/envious.gif create mode 100755 local/htdocs/img/mood/growf/pengies/geeky.gif create mode 100755 local/htdocs/img/mood/growf/pengies/happy.gif create mode 100755 local/htdocs/img/mood/growf/pengies/hyper.gif create mode 100755 local/htdocs/img/mood/growf/pengies/idea.gif create mode 100755 local/htdocs/img/mood/growf/pengies/livid.gif create mode 100755 local/htdocs/img/mood/growf/pengies/sad.gif create mode 100755 local/htdocs/img/mood/growf/pengies/sick.gif create mode 100755 local/htdocs/img/mood/growf/pengies/sob.gif create mode 100755 local/htdocs/img/mood/growf/pengies/sweat.gif create mode 100755 local/htdocs/img/mood/growf/pengies/thoughtful.gif create mode 100755 local/htdocs/img/mood/growf/pengies/wideeyed.gif create mode 100755 local/htdocs/img/mood/growf/pengies/yawn.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/achy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/angelic_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/angry_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/artistic_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/awake_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/blank_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/bored_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/cold_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/confused_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/dirty_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/drunk_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/emberassed_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/envious_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/exhausted_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/full_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/grumpy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/happy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/horny_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/hot_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/hungry_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/hyper_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/indescribable_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/indifferent_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/loved_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/mellow_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/mischivious_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/nerdy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/pensive_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/sad_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/sexy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/sick_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/silly_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/singing_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/sleepy_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/sore_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/stressed_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/thirsty_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/green/working_sg.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/achy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/angelic_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/angry_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/artistic_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/awake_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/blank_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/bored_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/cold_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/confused_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/dirty_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/drunk_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/emberassed_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/envious_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/exhausted_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/full_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/grumpy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/happy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/horny_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/hot_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/hungry_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/hyper_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/indescribable_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/indifferent_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/loved_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/mellow_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/mischivious_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/nerdy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/pensive_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/sad_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/sexy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/sick_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/silly_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/singing_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/sleepy_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/sore_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/stressed_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/thirsty_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/purple/working_sp.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/achy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/angelic_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/angry_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/artistic_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/awake_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/blank_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/bored_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/cold_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/confused_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/dirty_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/drunk_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/emberassed_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/envious_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/exhausted_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/full_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/grumpy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/happy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/horny_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/hot_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/hungry_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/hyper_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/indescribable_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/indifferent_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/loved_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/mellow_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/mischivious_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/nerdy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/pensive_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/sad_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/sexy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/sick_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/silly_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/singing_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/sleepy_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/sore_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/stressed_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/thirsty_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/red/working_sr.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/achy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/angelic_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/angry_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/artistic_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/awake_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/blank_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/bored_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/cold_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/confused_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/dirty_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/drunk_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/emberassed_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/envious_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/exhausted_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/full_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/grumpy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/happy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/horny_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/hot_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/hungry_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/hyper_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/indescribable_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/indifferent_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/loved_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/mellow_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/mischivious_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/nerdy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/pensive_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/sad_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/sexy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/sick_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/silly_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/singing_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/sleepy_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/sore_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/stressed_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/thirsty_sy.gif create mode 100755 local/htdocs/img/mood/moonsis/stars/yellow/working_sy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/accomplished.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/aggravated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/amused.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/angry.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/annoyed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/apathetic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/artistic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/awake.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/bitchy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/blah.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/blank.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/bored.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/bouncey.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/busy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/calm.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/cheerful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/chipper.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/cold.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/complacent.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/confused.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/contemplative.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/content.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/cranky.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/crappy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/crazy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/creative.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/crushed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/curious.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/cynical.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/depressed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/determined.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/devious.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/dirty.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/disappointed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/discontent.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/ditzy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/dorky.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/drained.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/drunk.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/ecstatic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/energetic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/enraged.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/enthralled.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/envious.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/exanimate.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/exausted.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/excited.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/flirty.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/frustrated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/full.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/geeky.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/giddy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/giggly.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/gloomy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/good.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/grateful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/groggy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/grumpy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/guilty.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/happy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/high.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/hopeful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/horny.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/hot.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/hungry2.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/hyper.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/impressed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/indescribable.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/indifferent.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/infuriated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/irate.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/irritated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/jubilant.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/lazy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/lethargic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/listless.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/lonely.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/loved.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/melancholy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/mellow.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/mischievous.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/morose.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/naughty.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/nauseated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/nerdy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/nostalgic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/numb.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/okay.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/optimistic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/peaceful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/pensive.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/pessimistic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/pissed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/pleased.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/predatory.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/productive.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/quixotic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/recumbent.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/refreshed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/rejected.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/rejuvenated.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/relaxed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/relieved.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/restless.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/rushed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/sad.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/satisfied.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/scared.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/shocked.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/sick.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/silly.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/sleepy.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/sore.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/stressed.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/suprised.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/sympathetic.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/thankful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/thirsty.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/thoughtful.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/tired.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/touched.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/uncomfortable.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/weird.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/working.gif create mode 100755 local/htdocs/img/mood/neko/kaokitty/worried.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankangry.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankangryb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankangryg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankangryp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankawake.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankawakeb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankawakeg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankawakep.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankcreate.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankcreateb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankcreateg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankcreatep.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankfood.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankfoodb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankfoodg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankfoodp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankgeek.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankgeekb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankgeekg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankgeekp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhappy.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhappyb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhappyg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhappyp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhunt.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhuntb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhuntg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhuntp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhyper.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhyperb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhyperg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankhyperp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankitten.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankittenb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankitteng.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankittenp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksad.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksadb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksadg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksadp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankscared.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankscaredb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankscaredg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankscaredp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksleepy.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksleepyb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksleepyg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anksleepyp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankthink.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankthinkb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankthinkg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankthinkp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anktired.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anktiredb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anktiredg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/anktiredp.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankwink.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankwinkb.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankwinkg.gif create mode 100755 local/htdocs/img/mood/niaha/kitty/ankwinkp.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/angry.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/awake.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/confused.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/determined.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/discontent.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/energetic.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/enthralled.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/happy.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/indescribable.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/nerdy.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/okay.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/sad.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/scared.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/thoughtful.gif create mode 100755 local/htdocs/img/mood/opiummmm/foxies/working.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/angelic.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/angry.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/artistic.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/awake.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/blah.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/blank.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/cheerful.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/cold.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/confused.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/curious.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/determined.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/dirty.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/dizzy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/embarrassed.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/envious.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/excited.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/flirty.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/full.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/giggly.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/gloomy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/groggy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/grumpy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/happy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/hopeful.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/hot.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/hungry2.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/hyper.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/indescribable.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/indifferent.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/lazy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/loved.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/mellow.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/moody.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/naughty.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/nerdy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/okay.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/sad.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/sick.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/silly.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/sleepy.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/sore.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/stressed.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/surprised.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/thirsty.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/thoughtful.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/tired.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/working.gif create mode 100755 local/htdocs/img/mood/punquinheads/blue/worried.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/angelic.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/angry.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/artistic.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/awake.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/blah.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/blank.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/cheerful.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/cold.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/confused.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/curious.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/determined.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/dirty.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/dizzy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/embarrassed.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/envious.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/excited.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/flirty.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/full.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/giggly.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/gloomy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/groggy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/grumpy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/happy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/hopeful.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/hot.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/hungry2.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/hyper.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/indescribable.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/indifferent.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/lazy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/loved.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/mellow.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/moody.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/naughty.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/nerdy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/okay.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/sad.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/sick.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/silly.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/sleepy.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/sore.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/stressed.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/surprised.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/thirsty.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/thoughtful.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/tired.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/working.gif create mode 100755 local/htdocs/img/mood/punquinheads/pink/worried.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/aggravated.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/amused.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/angry.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/annoyed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/anxious.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/artistic.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/awake.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/bitchy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/blank.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/bouncy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/busy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/cheerful.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/cold.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/complacent.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/confused.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/cranky.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/crushed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/curious.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/cynical.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/depressed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/determined.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/dirty.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/drunk.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/ecstatic.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/embarrassed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/energetic.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/enraged.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/enthralled.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/envious.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/exhausted.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/frustrated.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/full.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/gloomy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/good.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/groggy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/grumpy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/happy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/high.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/horny.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/hot.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/hungry.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/hyper.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/impressed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/indescribable.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/lazy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/loved.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/mischievous.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/moody.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/nerdy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/nostalgic.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/okay.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/predatory.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/refreshed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/relaxed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/relieved.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/rushed.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/sad.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/scared.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/sick.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/silly.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/sleepy.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/surprised.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/thirsty.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/thoughtful.gif create mode 100755 local/htdocs/img/mood/roshi/palefaces/worried.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/accomplished_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/angry_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/artistic_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/awake_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/backflip_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/blank_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/boggle_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/cold_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/cranky_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/crazy_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/creative_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/crying_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/curious_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/cynical_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/determined_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/devious_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/dirty_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/drunk_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/embarassed_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/enthralled_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/envious_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/exanimate_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/full_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/furious_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/giggly_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/gloomy_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/grateful_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/guilty_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/hopeful_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/horny_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/hot_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/hungry_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/indescribable_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/love_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/moody_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/nerdy_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/nostalgic_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/pensive_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/plain_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/predatory_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/puzzled_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/quixotic_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/refreshed_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/rejuvenated_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/relaxed_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/sad_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/scared_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/scrabble_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/sick_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/sleepy_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/smiling_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/sore_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/stressed_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/surprised_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/thirsty_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/thoughtful_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/tired_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/wheel_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/wibble_hammy.gif create mode 100755 local/htdocs/img/mood/twotone/hamsters/worried_hammy.gif create mode 100755 local/htdocs/img/pencil.gif create mode 100755 local/htdocs/img/s2preview/boxer/boxer.jpg create mode 100755 local/htdocs/img/s2preview/classic/classic.jpg create mode 100755 local/htdocs/img/s2preview/cleansimple/cleansimple.jpg create mode 100755 local/htdocs/img/s2preview/component/component.jpg create mode 100755 local/htdocs/img/s2preview/digitalmultiplex/digitalmultiplex.jpg create mode 100755 local/htdocs/img/s2preview/generator/generator.jpg create mode 100755 local/htdocs/img/s2preview/haven/haven.png create mode 100755 local/htdocs/img/s2preview/magazine/magazine.jpg create mode 100755 local/htdocs/img/s2preview/notepad/notepad.jpg create mode 100755 local/htdocs/img/s2preview/opal/opal.jpg create mode 100755 local/htdocs/img/s2preview/punquin/punquin.jpg create mode 100755 local/htdocs/img/s2preview/sturdygesture/sturdygesture.jpg create mode 100755 local/htdocs/img/s2preview/tabularindent/tabularindent.jpg create mode 100755 local/htdocs/img/s2preview/variableflow/preview.jpg create mode 100755 local/htdocs/img/userinfo-lj.gif create mode 100755 local/htdocs/img/userinfo-npj.gif create mode 100755 local/htdocs/img/userinfo.gif create mode 100644 local/htdocs/img/videoplaceholder.png create mode 100755 local/htdocs/import-enqueue.bml create mode 100755 local/htdocs/import-faq.bml create mode 100755 local/htdocs/import-queue.bml create mode 100755 local/htdocs/import.bml create mode 100755 local/htdocs/inc/legal-tos create mode 100755 local/htdocs/index.bml create mode 100755 local/htdocs/indexkoi.bml create mode 100755 local/htdocs/js/talkpost.js create mode 100755 local/htdocs/legal/guidelines.html create mode 100755 local/htdocs/legal/privacy.bml create mode 100755 local/htdocs/legal/tos-mini.html create mode 100755 local/htdocs/legal/tos.html create mode 100755 local/htdocs/legal/ustav.html create mode 100755 local/htdocs/lj-gate/index.bml create mode 100644 local/htdocs/lj-gate/lj-gate-faq.bml create mode 100755 local/htdocs/lj-gate/lj-gate-faq.html create mode 100755 local/htdocs/manage/siteopts.bml create mode 100755 local/htdocs/manage/tags.bml create mode 100644 local/htdocs/mobile/friends.bml create mode 100644 local/htdocs/mobile/index.bml create mode 100644 local/htdocs/mobile/login.bml create mode 100644 local/htdocs/mobile/post.bml create mode 100755 local/htdocs/modify.bml create mode 100755 local/htdocs/moodlist.bml create mode 100755 local/htdocs/news.bml create mode 100755 local/htdocs/openid/approve.bml create mode 100755 local/htdocs/openid/login.bml create mode 100755 local/htdocs/openid/options.bml create mode 100644 local/htdocs/paidaccounts/index.bml create mode 100755 local/htdocs/palimg/boxer/back.gif create mode 100755 local/htdocs/palimg/boxer/clear.gif create mode 100755 local/htdocs/palimg/boxer/forward.gif create mode 100755 local/htdocs/palimg/component/back.gif create mode 100755 local/htdocs/palimg/component/backarrow.gif create mode 100755 local/htdocs/palimg/component/bg.gif create mode 100755 local/htdocs/palimg/component/btn_edit.gif create mode 100755 local/htdocs/palimg/component/btn_memories.gif create mode 100755 local/htdocs/palimg/component/btn_tags.gif create mode 100755 local/htdocs/palimg/component/btn_tellfriend.gif create mode 100755 local/htdocs/palimg/component/clear.gif create mode 100755 local/htdocs/palimg/component/curve-bottom-left.gif create mode 100755 local/htdocs/palimg/component/curve-bottom-right.gif create mode 100755 local/htdocs/palimg/component/curve-top-left.gif create mode 100755 local/htdocs/palimg/component/curve-top-right.gif create mode 100755 local/htdocs/palimg/component/forward.gif create mode 100755 local/htdocs/palimg/component/forwardarrow.gif create mode 100755 local/htdocs/palimg/component/top-bg.gif create mode 100755 local/htdocs/privacy.bml create mode 100755 local/htdocs/robots.txt create mode 100755 local/htdocs/robotsdisable.txt create mode 100755 local/htdocs/site/index.html create mode 100755 local/htdocs/site/sitemap.html create mode 100755 local/htdocs/stats.bml create mode 100644 local/htdocs/stats/.htaccess create mode 100755 local/htdocs/stats/latest-img.bml create mode 100755 local/htdocs/stats/latest-rss.bml create mode 100755 local/htdocs/stats/latest.bml create mode 100755 local/htdocs/stats/weblog-updates-xml.bml create mode 100755 local/htdocs/styles/create.bml create mode 100755 local/htdocs/styles/create_do.bml create mode 100755 local/htdocs/support/faq.bml create mode 100755 local/htdocs/support/index.html create mode 100755 local/htdocs/syn/index.bml create mode 100755 local/htdocs/talkmulti.bml create mode 100755 local/htdocs/talkpost.bml create mode 100755 local/htdocs/talkpost_do.bml create mode 100755 local/htdocs/talkread.bml create mode 100755 local/htdocs/talkscreen.bml create mode 100644 local/htdocs/tools/embedcontent.bml create mode 100755 local/htdocs/tools/memadd.bml create mode 100755 local/htdocs/tools/recent_comments.bml create mode 100644 local/htdocs/tools/search.bml create mode 100755 local/htdocs/tos-2006-06-06.html create mode 100755 local/htdocs/tos-2009-07-12.html create mode 100755 local/htdocs/tos-2013-02-11.html create mode 100755 local/htdocs/tos.html create mode 100755 local/htdocs/translatetoljruser.bml create mode 100755 local/htdocs/update.bml create mode 100755 local/htdocs/userinfo.bml create mode 100755 local/htdocs/ustav.html create mode 100755 local/htdocs/zatychka.html create mode 100755 multicvs.conf create mode 100755 obsolete/bin/rlj2lj.pl create mode 100755 obsolete/cgi-bin/DBI/Role.pm.debug create mode 100755 obsolete/cgi-bin/LJ/Rewriteuser.pm create mode 100755 obsolete/htdocs/admin/redirectusers.bml create mode 100755 obsolete/htdocs/img/GJcommunity.gif create mode 100755 obsolete/htdocs/img/GJuserinfo.gif create mode 100755 obsolete/htdocs/img/NPJcommunity.gif create mode 100755 obsolete/htdocs/img/NPJuserinfo.gif create mode 100755 obsolete/htdocs/lj-gate/index.bml create mode 100755 obsolete/htdocs/lj-gate/rlj2lj.bml create mode 100755 obsolete/htdocs/lj-gate/rlj_delete.bml create mode 100755 obsolete/htdocs/paidaccounts/index.html create mode 100755 wcmtools/bin/apidoc.pl create mode 100755 wcmtools/bin/multicvs.pl create mode 100755 wcmtools/blobserver/lib/Apache/Blob.pm create mode 100755 wcmtools/blobserver/lib/modperl.pl create mode 100755 wcmtools/ddlockd/api/perl/DDLockClient.pm create mode 100755 wcmtools/ddlockd/api/perl/MANIFEST create mode 100755 wcmtools/ddlockd/api/perl/MANIFEST.SKIP create mode 100755 wcmtools/ddlockd/api/perl/Makefile.PL create mode 100755 wcmtools/ddlockd/api/perl/stresslock.pl create mode 100755 wcmtools/ddlockd/api/perl/t/00_require.t create mode 100755 wcmtools/ddlockd/api/perl/testlock.pl create mode 100755 wcmtools/ddlockd/server/ddlockd create mode 100755 wcmtools/dinsertd/server/dinsertd create mode 100755 wcmtools/diskchecker/diskchecker.pl create mode 100755 wcmtools/dmtpd/README.txt create mode 100755 wcmtools/dmtpd/api/perl/test.pl create mode 100755 wcmtools/dmtpd/server/dmtpd create mode 100755 wcmtools/gearman/dev/DMap.pm create mode 100755 wcmtools/gearman/dev/client.pl create mode 100755 wcmtools/gearman/dev/dmap-worker.pl create mode 100755 wcmtools/gearman/dev/dmap.pl create mode 100755 wcmtools/gearman/dev/test-gear.pl create mode 100755 wcmtools/gearman/dev/worker.pl create mode 100755 wcmtools/gearman/doc/overview.txt create mode 100755 wcmtools/gearman/lib/Gearman/Client.pm create mode 100755 wcmtools/gearman/lib/Gearman/JobStatus.pm create mode 100755 wcmtools/gearman/lib/Gearman/Objects.pm create mode 100755 wcmtools/gearman/lib/Gearman/Task.pm create mode 100755 wcmtools/gearman/lib/Gearman/Taskset.pm create mode 100755 wcmtools/gearman/lib/Gearman/Util.pm create mode 100755 wcmtools/gearman/lib/Gearman/Worker.pm create mode 100755 wcmtools/gearman/server/gearmand create mode 100755 wcmtools/gearman/t/00-use.t create mode 100755 wcmtools/gearman/t/10-all.t create mode 100755 wcmtools/gearman/t/worker.pl create mode 100755 wcmtools/lib/Apache/CompressClientFixup.pm create mode 100755 wcmtools/lib/DBI/Role.pm create mode 100755 wcmtools/lib/DBIx/StateKeeper.pm create mode 100755 wcmtools/lib/Danga-Daemon/Daemon.pm create mode 100755 wcmtools/lib/Danga-EXIF/EXIF.pm create mode 100755 wcmtools/lib/Danga-Exceptions/MANIFEST create mode 100755 wcmtools/lib/Danga-Exceptions/MANIFEST.SKIP create mode 100755 wcmtools/lib/Danga-Exceptions/Makefile.PL create mode 100755 wcmtools/lib/Danga-Exceptions/lib/Danga/Exceptions.pm create mode 100755 wcmtools/lib/Danga-Exceptions/t/basic.t create mode 100755 wcmtools/lib/Danga-Socket/CHANGES create mode 100755 wcmtools/lib/Danga-Socket/MANIFEST create mode 100755 wcmtools/lib/Danga-Socket/MANIFEST.SKIP create mode 100755 wcmtools/lib/Danga-Socket/META.yml create mode 100755 wcmtools/lib/Danga-Socket/Makefile.PL create mode 100755 wcmtools/lib/Danga-Socket/Socket.pm create mode 100755 wcmtools/lib/Danga-Socket/debian/changelog create mode 100755 wcmtools/lib/Danga-Socket/debian/compat create mode 100755 wcmtools/lib/Danga-Socket/debian/control create mode 100755 wcmtools/lib/Danga-Socket/debian/copyright create mode 100755 wcmtools/lib/Danga-Socket/debian/rules create mode 100755 wcmtools/lib/Danga-Socket/debian/watch create mode 100755 wcmtools/lib/Danga-Socket/t/00-use.t create mode 100755 wcmtools/lib/Danga-Socket/t/05-postloop.t create mode 100755 wcmtools/lib/Danga-Socket/t/10-events.t create mode 100755 wcmtools/lib/HTMLCleaner.pm create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/ChangeLog create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/MANIFEST create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/Makefile.PL create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/ParanoidAgent.pm create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/http_paranoid.pm create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/https_paranoid.pm create mode 100755 wcmtools/lib/LWPx-ParanoidAgent/t/00-all.t create mode 100755 wcmtools/lib/MultiCVS.pm create mode 100755 wcmtools/lib/MySQL-BinLog/MANIFEST create mode 100755 wcmtools/lib/MySQL-BinLog/MANIFEST.SKIP create mode 100755 wcmtools/lib/MySQL-BinLog/Makefile.PL create mode 100755 wcmtools/lib/MySQL-BinLog/docs/log_event.h create mode 100755 wcmtools/lib/MySQL-BinLog/docs/log_event.ph create mode 100755 wcmtools/lib/MySQL-BinLog/experiments/cpptokenizer.pl create mode 100755 wcmtools/lib/MySQL-BinLog/experiments/try.pl create mode 100755 wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog.pm create mode 100755 wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Constants.pm create mode 100755 wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Events.pm create mode 100755 wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Header.pm create mode 100755 wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Net.pm create mode 100755 wcmtools/lib/S2/Color.pm create mode 100755 wcmtools/lib/S2/EXIF.pm create mode 100755 wcmtools/lib/SafeAgent.pm create mode 100755 wcmtools/memcached/AUTHORS create mode 100755 wcmtools/memcached/BUILD create mode 100755 wcmtools/memcached/CONTRIBUTORS create mode 100755 wcmtools/memcached/COPYING create mode 100755 wcmtools/memcached/ChangeLog create mode 100755 wcmtools/memcached/LICENSE create mode 100755 wcmtools/memcached/Makefile.am create mode 100755 wcmtools/memcached/NEWS create mode 100755 wcmtools/memcached/README create mode 100755 wcmtools/memcached/TODO create mode 100755 wcmtools/memcached/api/java/CHANGELOG.txt create mode 100755 wcmtools/memcached/api/java/PORTABILITY.txt create mode 100755 wcmtools/memcached/api/java/TODO.txt create mode 100755 wcmtools/memcached/api/java/com/danga/MemCached/MemCachedClient.java create mode 100755 wcmtools/memcached/api/java/com/danga/MemCached/SockIO.java create mode 100755 wcmtools/memcached/api/java/dist.pl create mode 100755 wcmtools/memcached/api/java/memcachetest.java create mode 100755 wcmtools/memcached/api/perl/ChangeLog create mode 100755 wcmtools/memcached/api/perl/MANIFEST create mode 100755 wcmtools/memcached/api/perl/Makefile.PL create mode 100755 wcmtools/memcached/api/perl/Memcached.pm create mode 100755 wcmtools/memcached/api/perl/README create mode 100755 wcmtools/memcached/api/perl/TODO create mode 100755 wcmtools/memcached/api/perl/t/use.t create mode 100755 wcmtools/memcached/api/php/ChangeLog create mode 100755 wcmtools/memcached/api/php/Documentation create mode 100755 wcmtools/memcached/api/php/MemCachedClient.inc.php create mode 100755 wcmtools/memcached/api/php/dist.pl create mode 100755 wcmtools/memcached/api/python/ChangeLog create mode 100755 wcmtools/memcached/api/python/DISTNOTES create mode 100755 wcmtools/memcached/api/python/MANIFEST create mode 100755 wcmtools/memcached/api/python/PKG-INFO create mode 100755 wcmtools/memcached/api/python/memcache.py create mode 100755 wcmtools/memcached/api/python/setup.py create mode 100755 wcmtools/memcached/api/python/tests/pooltest.py create mode 100755 wcmtools/memcached/assoc.c create mode 100755 wcmtools/memcached/autogen.sh create mode 100755 wcmtools/memcached/configure.ac create mode 100755 wcmtools/memcached/doc/Makefile.am create mode 100755 wcmtools/memcached/doc/memcached.1 create mode 100755 wcmtools/memcached/doc/memory_management.txt create mode 100755 wcmtools/memcached/doc/protocol.txt create mode 100755 wcmtools/memcached/frontends/gtk2-perl/README create mode 100755 wcmtools/memcached/frontends/gtk2-perl/memcachedclient create mode 100755 wcmtools/memcached/items.c create mode 100755 wcmtools/memcached/memcached.c create mode 100755 wcmtools/memcached/memcached.h create mode 100755 wcmtools/memcached/scripts/memcached-init create mode 100755 wcmtools/memcached/scripts/memcached-tool create mode 100755 wcmtools/memcached/scripts/start-memcached create mode 100755 wcmtools/memcached/slabs.c create mode 100755 wcmtools/memcached/test/stress-memcached.pl create mode 100755 wcmtools/memcached/website/_config.bml create mode 100755 wcmtools/memcached/website/apis.bml create mode 100755 wcmtools/memcached/website/download.bml create mode 100755 wcmtools/memcached/website/index.bml create mode 100755 wcmtools/memcached/website/memcached.css create mode 100755 wcmtools/memcached/website/memcached.look create mode 100755 wcmtools/memcached/website/news.bml create mode 100755 wcmtools/memcached/website/users.bml create mode 100755 wcmtools/mogilefs/api/perl/MANIFEST create mode 100755 wcmtools/mogilefs/api/perl/MANIFEST.SKIP create mode 100755 wcmtools/mogilefs/api/perl/META.yml create mode 100755 wcmtools/mogilefs/api/perl/Makefile.PL create mode 100755 wcmtools/mogilefs/api/perl/MogileFS.pm create mode 100755 wcmtools/mogilefs/api/perl/debian/changelog create mode 100755 wcmtools/mogilefs/api/perl/debian/compat create mode 100755 wcmtools/mogilefs/api/perl/debian/control create mode 100755 wcmtools/mogilefs/api/perl/debian/copyright create mode 100755 wcmtools/mogilefs/api/perl/debian/rules create mode 100755 wcmtools/mogilefs/api/perl/debian/watch create mode 100755 wcmtools/mogilefs/api/perl/t/00use.t create mode 100755 wcmtools/mogilefs/devnotes/FIXME create mode 100755 wcmtools/mogilefs/devnotes/mounter.pl create mode 100755 wcmtools/mogilefs/devnotes/notes.txt create mode 100755 wcmtools/mogilefs/devnotes/perl-interface.txt create mode 100755 wcmtools/mogilefs/devnotes/sql-data-bradhome.txt create mode 100755 wcmtools/mogilefs/devnotes/sql-data-office.txt create mode 100755 wcmtools/mogilefs/devnotes/sql-data-simple.txt create mode 100755 wcmtools/mogilefs/devnotes/sql.txt create mode 100755 wcmtools/mogilefs/devnotes/todo.txt create mode 100755 wcmtools/mogilefs/server/MANIFEST create mode 100755 wcmtools/mogilefs/server/MANIFEST.SKIP create mode 100755 wcmtools/mogilefs/server/META.yml create mode 100755 wcmtools/mogilefs/server/Makefile.PL create mode 100755 wcmtools/mogilefs/server/conf/mogilefsd.conf create mode 100755 wcmtools/mogilefs/server/conf/mogstored.conf create mode 100755 wcmtools/mogilefs/server/debian/changelog create mode 100755 wcmtools/mogilefs/server/debian/compat create mode 100755 wcmtools/mogilefs/server/debian/control create mode 100755 wcmtools/mogilefs/server/debian/copyright create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.config create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.init create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.postinst create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.postrm create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.preinst create mode 100755 wcmtools/mogilefs/server/debian/mogilefsd.templates create mode 100755 wcmtools/mogilefs/server/debian/mogstored.config create mode 100755 wcmtools/mogilefs/server/debian/mogstored.init create mode 100755 wcmtools/mogilefs/server/debian/mogstored.postinst create mode 100755 wcmtools/mogilefs/server/debian/mogstored.postrm create mode 100755 wcmtools/mogilefs/server/debian/mogstored.templates create mode 100755 wcmtools/mogilefs/server/debian/po/POTFILES.in create mode 100755 wcmtools/mogilefs/server/debian/po/templates.pot create mode 100755 wcmtools/mogilefs/server/debian/rules create mode 100755 wcmtools/mogilefs/server/debian/watch create mode 100755 wcmtools/mogilefs/server/mogilefsd create mode 100755 wcmtools/mogilefs/server/mogstored create mode 100755 wcmtools/mogilefs/utils/MANIFEST create mode 100755 wcmtools/mogilefs/utils/MANIFEST.SKIP create mode 100755 wcmtools/mogilefs/utils/Makefile.PL create mode 100755 wcmtools/mogilefs/utils/conf/mogtool.conf create mode 100755 wcmtools/mogilefs/utils/debian/changelog create mode 100755 wcmtools/mogilefs/utils/debian/compat create mode 100755 wcmtools/mogilefs/utils/debian/control create mode 100755 wcmtools/mogilefs/utils/debian/copyright create mode 100755 wcmtools/mogilefs/utils/debian/mogilefs-utils.postinst create mode 100755 wcmtools/mogilefs/utils/debian/mogilefs-utils.postrm create mode 100755 wcmtools/mogilefs/utils/debian/rules create mode 100755 wcmtools/mogilefs/utils/mogtool create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/ChangeLog create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/MANIFEST create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/Makefile.PL create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/lib/Net/OpenID/Association.pm create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/lib/Net/OpenID/ClaimedIdentity.pm create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/lib/Net/OpenID/Consumer.pm create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/lib/Net/OpenID/VerifiedIdentity.pm create mode 100755 wcmtools/openid/perl/Net-OpenID-Consumer/t/00-use.t create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/ChangeLog create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/MANIFEST create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/Makefile.PL create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/t/00-all.t create mode 100755 wcmtools/openid/perl/Net-OpenID-Server/t/01-newproto.t create mode 100755 wcmtools/perlbal/CHANGES create mode 100755 wcmtools/perlbal/MANIFEST create mode 100755 wcmtools/perlbal/MANIFEST.SKIP create mode 100755 wcmtools/perlbal/META.yml create mode 100755 wcmtools/perlbal/Makefile.PL create mode 100755 wcmtools/perlbal/conf/nodelist.dat create mode 100755 wcmtools/perlbal/conf/perlbal.conf create mode 100755 wcmtools/perlbal/debian/changelog create mode 100755 wcmtools/perlbal/debian/compat create mode 100755 wcmtools/perlbal/debian/control create mode 100755 wcmtools/perlbal/debian/copyright create mode 100755 wcmtools/perlbal/debian/perlbal-doc.docs create mode 100755 wcmtools/perlbal/debian/perlbal.init create mode 100755 wcmtools/perlbal/debian/perlbal.postinst create mode 100755 wcmtools/perlbal/debian/perlbal.postrm create mode 100755 wcmtools/perlbal/debian/rules create mode 100755 wcmtools/perlbal/debian/watch create mode 100755 wcmtools/perlbal/doc/Classes.txt create mode 100755 wcmtools/perlbal/doc/Hooks.txt create mode 100755 wcmtools/perlbal/doc/README.txt create mode 100755 wcmtools/perlbal/doc/Reproxying.txt create mode 100755 wcmtools/perlbal/doc/todo.txt create mode 100755 wcmtools/perlbal/lib/Perlbal.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/AIO.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/BackendHTTP.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/ClientHTTP.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/ClientHTTPBase.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/ClientManage.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/ClientProxy.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/HTTPHeaders.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Plugin/Highpri.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Plugin/Palimg.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Plugin/Queues.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Plugin/Stats.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Pool.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/ReproxyManager.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Service.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Socket.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/StatsListener.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/TCPListener.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Test.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Test/WebClient.pm create mode 100755 wcmtools/perlbal/lib/Perlbal/Test/WebServer.pm create mode 100755 wcmtools/perlbal/perlbal create mode 100755 wcmtools/perlbal/t/00-use.t create mode 100755 wcmtools/perlbal/t/10-testharness.t create mode 100755 wcmtools/perlbal/t/12-headers.t create mode 100755 wcmtools/perlbal/t/15-webserver.t create mode 100755 wcmtools/perlbal/t/20-put.t create mode 100755 wcmtools/perlbal/t/30-reverseproxy.t create mode 100755 wcmtools/perlbal/test/helper-server.pl create mode 100755 wcmtools/s2/BUGS create mode 100755 wcmtools/s2/BUILD.txt create mode 100755 wcmtools/s2/S2.pm create mode 100755 wcmtools/s2/S2/BackendHTML.pm create mode 100755 wcmtools/s2/S2/BackendPerl.pm create mode 100755 wcmtools/s2/S2/Checker.pm create mode 100755 wcmtools/s2/S2/Compiler.pm create mode 100755 wcmtools/s2/S2/FilePos.pm create mode 100755 wcmtools/s2/S2/Indenter.pm create mode 100755 wcmtools/s2/S2/Layer.pm create mode 100755 wcmtools/s2/S2/Node.pm create mode 100755 wcmtools/s2/S2/NodeArguments.pm create mode 100755 wcmtools/s2/S2/NodeArrayLiteral.pm create mode 100755 wcmtools/s2/S2/NodeAssignExpr.pm create mode 100755 wcmtools/s2/S2/NodeClass.pm create mode 100755 wcmtools/s2/S2/NodeClassVarDecl.pm create mode 100755 wcmtools/s2/S2/NodeCondExpr.pm create mode 100755 wcmtools/s2/S2/NodeDeleteStmt.pm create mode 100755 wcmtools/s2/S2/NodeEqExpr.pm create mode 100755 wcmtools/s2/S2/NodeExpr.pm create mode 100755 wcmtools/s2/S2/NodeExprStmt.pm create mode 100755 wcmtools/s2/S2/NodeForeachStmt.pm create mode 100755 wcmtools/s2/S2/NodeFormals.pm create mode 100755 wcmtools/s2/S2/NodeFunction.pm create mode 100755 wcmtools/s2/S2/NodeIfStmt.pm create mode 100755 wcmtools/s2/S2/NodeIncExpr.pm create mode 100755 wcmtools/s2/S2/NodeLayerInfo.pm create mode 100755 wcmtools/s2/S2/NodeLogAndExpr.pm create mode 100755 wcmtools/s2/S2/NodeLogOrExpr.pm create mode 100755 wcmtools/s2/S2/NodeNamedType.pm create mode 100755 wcmtools/s2/S2/NodePrintStmt.pm create mode 100755 wcmtools/s2/S2/NodeProduct.pm create mode 100755 wcmtools/s2/S2/NodePropGroup.pm create mode 100755 wcmtools/s2/S2/NodeProperty.pm create mode 100755 wcmtools/s2/S2/NodePropertyPair.pm create mode 100755 wcmtools/s2/S2/NodeRange.pm create mode 100755 wcmtools/s2/S2/NodeRelExpr.pm create mode 100755 wcmtools/s2/S2/NodeReturnStmt.pm create mode 100755 wcmtools/s2/S2/NodeSet.pm create mode 100755 wcmtools/s2/S2/NodeStmt.pm create mode 100755 wcmtools/s2/S2/NodeStmtBlock.pm create mode 100755 wcmtools/s2/S2/NodeSum.pm create mode 100755 wcmtools/s2/S2/NodeTerm.pm create mode 100755 wcmtools/s2/S2/NodeText.pm create mode 100755 wcmtools/s2/S2/NodeType.pm create mode 100755 wcmtools/s2/S2/NodeUnaryExpr.pm create mode 100755 wcmtools/s2/S2/NodeUnnecessary.pm create mode 100755 wcmtools/s2/S2/NodeVarDecl.pm create mode 100755 wcmtools/s2/S2/NodeVarDeclStmt.pm create mode 100755 wcmtools/s2/S2/NodeVarRef.pm create mode 100755 wcmtools/s2/S2/OutputConsole.pm create mode 100755 wcmtools/s2/S2/OutputScalar.pm create mode 100755 wcmtools/s2/S2/Token.pm create mode 100755 wcmtools/s2/S2/TokenComment.pm create mode 100755 wcmtools/s2/S2/TokenIdent.pm create mode 100755 wcmtools/s2/S2/TokenIntegerLiteral.pm create mode 100755 wcmtools/s2/S2/TokenKeyword.pm create mode 100755 wcmtools/s2/S2/TokenPunct.pm create mode 100755 wcmtools/s2/S2/TokenStringLiteral.pm create mode 100755 wcmtools/s2/S2/TokenWhitespace.pm create mode 100755 wcmtools/s2/S2/Tokenizer.pm create mode 100755 wcmtools/s2/S2/Type.pm create mode 100755 wcmtools/s2/S2/Util.pm create mode 100755 wcmtools/s2/danga/s2/Backend.java create mode 100755 wcmtools/s2/danga/s2/BackendHTML.java create mode 100755 wcmtools/s2/danga/s2/BackendPerl.java create mode 100755 wcmtools/s2/danga/s2/BackendS2.java create mode 100755 wcmtools/s2/danga/s2/BufferedIndenter.java create mode 100755 wcmtools/s2/danga/s2/Checker.java create mode 100755 wcmtools/s2/danga/s2/DerItem.java create mode 100755 wcmtools/s2/danga/s2/FilePos.java create mode 100755 wcmtools/s2/danga/s2/Indenter.java create mode 100755 wcmtools/s2/danga/s2/Layer.java create mode 100755 wcmtools/s2/danga/s2/Node.java create mode 100755 wcmtools/s2/danga/s2/NodeArguments.java create mode 100755 wcmtools/s2/danga/s2/NodeArrayLiteral.java create mode 100755 wcmtools/s2/danga/s2/NodeAssignExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeClass.java create mode 100755 wcmtools/s2/danga/s2/NodeClassVarDecl.java create mode 100755 wcmtools/s2/danga/s2/NodeCondExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeDeleteStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeEqExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeExprStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeForeachStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeFormals.java create mode 100755 wcmtools/s2/danga/s2/NodeFunction.java create mode 100755 wcmtools/s2/danga/s2/NodeIfStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeIncExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeLayerInfo.java create mode 100755 wcmtools/s2/danga/s2/NodeLogAndExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeLogOrExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeNamedType.java create mode 100755 wcmtools/s2/danga/s2/NodePrintStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeProduct.java create mode 100755 wcmtools/s2/danga/s2/NodeProperty.java create mode 100755 wcmtools/s2/danga/s2/NodePropertyPair.java create mode 100755 wcmtools/s2/danga/s2/NodeRange.java create mode 100755 wcmtools/s2/danga/s2/NodeRelExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeReturnStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeSet.java create mode 100755 wcmtools/s2/danga/s2/NodeStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeStmtBlock.java create mode 100755 wcmtools/s2/danga/s2/NodeSum.java create mode 100755 wcmtools/s2/danga/s2/NodeTerm.java create mode 100755 wcmtools/s2/danga/s2/NodeText.java create mode 100755 wcmtools/s2/danga/s2/NodeType.java create mode 100755 wcmtools/s2/danga/s2/NodeUnaryExpr.java create mode 100755 wcmtools/s2/danga/s2/NodeUnnecessary.java create mode 100755 wcmtools/s2/danga/s2/NodeVarDecl.java create mode 100755 wcmtools/s2/danga/s2/NodeVarDeclStmt.java create mode 100755 wcmtools/s2/danga/s2/NodeVarRef.java create mode 100755 wcmtools/s2/danga/s2/Output.java create mode 100755 wcmtools/s2/danga/s2/OutputConsole.java create mode 100755 wcmtools/s2/danga/s2/OutputStringBuffer.java create mode 100755 wcmtools/s2/danga/s2/Scanner.java create mode 100755 wcmtools/s2/danga/s2/Token.java create mode 100755 wcmtools/s2/danga/s2/TokenComment.java create mode 100755 wcmtools/s2/danga/s2/TokenIdent.java create mode 100755 wcmtools/s2/danga/s2/TokenIntegerLiteral.java create mode 100755 wcmtools/s2/danga/s2/TokenKeyword.java create mode 100755 wcmtools/s2/danga/s2/TokenPunct.java create mode 100755 wcmtools/s2/danga/s2/TokenStringLiteral.java create mode 100755 wcmtools/s2/danga/s2/TokenWhitespace.java create mode 100755 wcmtools/s2/danga/s2/Tokenizer.java create mode 100755 wcmtools/s2/danga/s2/Type.java create mode 100755 wcmtools/s2/danga/s2/s2compile.java create mode 100755 wcmtools/s2/doc/database.txt create mode 100755 wcmtools/s2/doc/design_goals.txt create mode 100755 wcmtools/s2/doc/docbook/about.xml create mode 100755 wcmtools/s2/doc/docbook/appx.gfdl.xml create mode 100755 wcmtools/s2/doc/docbook/bookinfo.xml create mode 100755 wcmtools/s2/doc/docbook/caveats.xml create mode 100755 wcmtools/s2/doc/docbook/csp.xml create mode 100755 wcmtools/s2/doc/docbook/design.xml create mode 100755 wcmtools/s2/doc/docbook/entities.xml create mode 100755 wcmtools/s2/doc/docbook/faq.xml create mode 100755 wcmtools/s2/doc/docbook/history.xml create mode 100755 wcmtools/s2/doc/docbook/how.xml create mode 100755 wcmtools/s2/doc/docbook/index.xml create mode 100755 wcmtools/s2/doc/docbook/langref.xml create mode 100755 wcmtools/s2/doc/docbook/layers.xml create mode 100755 wcmtools/s2/doc/docbook/misc.xml create mode 100755 wcmtools/s2/doc/docbook/notes.txt create mode 100755 wcmtools/s2/doc/docbook/notes.xml create mode 100755 wcmtools/s2/doc/docbook/overview.xml create mode 100755 wcmtools/s2/doc/docbook/preface.xml create mode 100755 wcmtools/s2/doc/docbook/terms.xml create mode 100755 wcmtools/s2/doc/grammar.txt create mode 100755 wcmtools/s2/doc/language.txt create mode 100755 wcmtools/s2/doc/layerinfo.txt create mode 100755 wcmtools/s2/doc/layers.txt create mode 100755 wcmtools/s2/doc/overview.txt create mode 100755 wcmtools/s2/doc/properties.txt create mode 100755 wcmtools/s2/doc/versioning.txt create mode 100755 wcmtools/s2/makefile.jmk create mode 100755 wcmtools/s2/manifest.txt create mode 100755 wcmtools/s2/runtests.pl create mode 100755 wcmtools/s2/s2compile create mode 100755 wcmtools/s2/s2compile.pl create mode 100755 wcmtools/s2/tests/Arithmetic.s2 create mode 100755 wcmtools/s2/tests/Arithmetic.s2.out create mode 100755 wcmtools/s2/tests/Classes_1.s2 create mode 100755 wcmtools/s2/tests/Classes_1.s2.out create mode 100755 wcmtools/s2/tests/Classes_2.s2 create mode 100755 wcmtools/s2/tests/Classes_2.s2.out create mode 100755 wcmtools/s2/tests/Colors.s2 create mode 100755 wcmtools/s2/tests/Colors.s2.out create mode 100755 wcmtools/s2/tests/Colors_2b.s2 create mode 100755 wcmtools/s2/tests/Colors_2b.s2.out create mode 100755 wcmtools/s2/tests/Hello_World.s2 create mode 100755 wcmtools/s2/tests/Hello_World.s2.out create mode 100755 wcmtools/s2/tests/Obj_Interpolate.s2 create mode 100755 wcmtools/s2/tests/Obj_Interpolate.s2.out create mode 100755 wcmtools/s2/tests/Reserved_Idents.s2 create mode 100755 wcmtools/s2/tests/Reserved_Idents.s2.out create mode 100755 wcmtools/s2/tests/String_Object.s2 create mode 100755 wcmtools/s2/tests/String_Object.s2.out create mode 100755 wcmtools/s2/tests/arrayliterals.s2 create mode 100755 wcmtools/s2/tests/arrayliterals.s2.out create mode 100755 wcmtools/s2/tests/conditions.s2 create mode 100755 wcmtools/s2/tests/conditions.s2.out create mode 100755 wcmtools/s2/tests/defined.s2 create mode 100755 wcmtools/s2/tests/defined.s2.out create mode 100755 wcmtools/s2/tests/fail-syntax.s2 create mode 100755 wcmtools/s2/tests/fail-syntax.s2.err create mode 100755 wcmtools/s2/tests/if-assign.s2 create mode 100755 wcmtools/s2/tests/if-assign.s2.err create mode 100755 wcmtools/s2/tests/null-dispatch.s2 create mode 100755 wcmtools/s2/tests/null-dispatch.s2.err create mode 100755 wcmtools/s2/tests/null-dispatch.s2.out create mode 100755 wcmtools/s2/tests/null.s2 create mode 100755 wcmtools/s2/tests/null.s2.out create mode 100755 wcmtools/s2/tests/range.s2 create mode 100755 wcmtools/s2/tests/range.s2.out create mode 100755 wcmtools/s2/tests/readonly.s2 create mode 100755 wcmtools/s2/tests/readonly.s2.out create mode 100755 wcmtools/s2/tests/sizereverse.s2 create mode 100755 wcmtools/s2/tests/sizereverse.s2.out create mode 100755 wcmtools/s2/tests/super.s2 create mode 100755 wcmtools/s2/tests/super.s2.out create mode 100755 wcmtools/spud/bin/cmdshell create mode 100755 wcmtools/spud/bin/gatherer create mode 100755 wcmtools/spud/bin/plugins/config_generator.pl create mode 100755 wcmtools/spud/bin/plugins/memcached.pl create mode 100755 wcmtools/spud/bin/plugins/mogilefsd.pl create mode 100755 wcmtools/spud/bin/plugins/mogstored.pl create mode 100755 wcmtools/spud/bin/plugins/perlbal.pl create mode 100755 wcmtools/spud/bin/plugins/test.pl create mode 100755 wcmtools/spud/bin/replicator create mode 100755 wcmtools/spud/bin/rrd-storage create mode 100755 wcmtools/spud/bin/server create mode 100755 wcmtools/spud/bin/wrapper create mode 100755 wcmtools/spud/conf/authorized_keys create mode 100755 wcmtools/spud/conf/cmdshell.conf create mode 100755 wcmtools/spud/conf/sshd_config create mode 100755 wcmtools/spud/conf/stats-local.conf create mode 100755 wcmtools/spud/conf/stats.conf create mode 100755 wcmtools/spud/doc/README.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40caffa --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# CVS default ignores begin +tags +TAGS +.make.state +.nse_depinfo +*~ +#* +.#* +,* +_$* +*$ +*.old +*.bak +*.BAK +*.orig +*.rej +.del-* +*.a +*.olb +*.o +*.obj +*.so +*.exe +*.Z +*.elc +*.ln +core +# CVS default ignores end diff --git a/bml/MANIFEST b/bml/MANIFEST new file mode 100755 index 0000000..01cf479 --- /dev/null +++ b/bml/MANIFEST @@ -0,0 +1,93 @@ +bml-tester.pl +doc/bml-notes.txt +doc/docbook/appx.gfdl.xml +doc/docbook/book.ent +doc/docbook/book.xml +doc/docbook/bookinfo.xml +doc/docbook/build.pl +doc/docbook/BUILD.txt +doc/docbook/core.xml +doc/docbook/flags.xml +doc/docbook/index.xml +doc/docbook/preface.xml +doc/docbook/tutorial.xml +lib/Apache/BML.pm +Makefile.PL +MANIFEST +t/00_require.t +t/10_simple.t +t/20_render.t +test/bml-profile.pl +test/brads/_config.bml +test/brads/scheme.look +test/brads/test1.bml +test/brads/test1.correct +test/codeblocks/_config.bml +test/codeblocks/carry-variables.bml +test/codeblocks/carry-variables.correct +test/codeblocks/complex1.bml +test/codeblocks/complex1.correct +test/codeblocks/complex2.bml +test/codeblocks/complex2.correct +test/codeblocks/re-expand.bml +test/codeblocks/re-expand.correct +test/codeblocks/scheme.look +test/codeblocks/simple.bml +test/codeblocks/simple.correct +test/comments/_config.bml +test/comments/basic.bml +test/comments/basic.correct +test/comments/rendered.bml +test/comments/rendered.correct +test/comments/scheme.look +test/escape/_config.bml +test/escape/ea.bml +test/escape/ea.correct +test/escape/eb.bml +test/escape/eb.correct +test/escape/eh.bml +test/escape/eh.correct +test/escape/eu.bml +test/escape/eu.correct +test/escape/scheme.look +test/fake_root/_config.bml +test/fake_root/bluewhite.look +test/fake_root/bml-simple.bml +test/fake_root/bml-simple.correct +test/fake_root/bml-test.bml +test/fake_root/bml-test.correct +test/fake_root/global.look +test/include/_config.bml +test/include/loremipsum.txt +test/include/plain.bml +test/include/scheme.look +test/info/_config.bml +test/info/localblocks.bml +test/info/localblocks.correct +test/info/package.bml +test/info/package.correct +test/info/scheme.look +test/recursion/_config.bml +test/recursion/infinite.bml +test/recursion/infinite.correct +test/recursion/nested.bml +test/recursion/nested.correct +test/recursion/scheme.look +test/syntax-errors/_config.bml +test/syntax-errors/dangling-tagopen.bml +test/syntax-errors/dangling-tagopen.correct +test/syntax-errors/no-close.bml +test/syntax-errors/no-close.correct +test/syntax-errors/onlyopen.bml +test/syntax-errors/onlyopen.correct +test/syntax-errors/scheme.look +test/syntax-errors/spaces.bml +test/syntax-errors/spaces.correct +test/tutorial1/_config.bml +test/tutorial1/index.bml +test/tutorial1/index.correct +test/tutorial1/scheme.look +test/tutorial2/_config.bml +test/tutorial2/index.bml +test/tutorial2/index.correct +test/tutorial2/scheme.look diff --git a/bml/MANIFEST.SKIP b/bml/MANIFEST.SKIP new file mode 100755 index 0000000..ede9cda --- /dev/null +++ b/bml/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists diff --git a/bml/Makefile.PL b/bml/Makefile.PL new file mode 100755 index 0000000..c0713d9 --- /dev/null +++ b/bml/Makefile.PL @@ -0,0 +1,36 @@ +#!/usr/bin/perl +# +# Perl Makefile for BML +# $Id: Makefile.PL,v 1.1 2004/05/26 17:33:51 deveiant Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; +my $version = do { my @r = (q$Revision: 1.1 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + +my %config = ( + NAME => 'BML', + VERSION => "0." . $version, + AUTHOR => 'Brad Fitzpatrick ', + ABSTRACT => 'a server-side markup language', + PREREQ_PM => { + Apache => 0, + Apache::URI => 0, + Digest::MD5 => 0, + File::Spec => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag r$(VERSION_SYM)', + SUFFIX => ".bz2", + DIST_DEFAULT => 'all tardist', + COMPRESS => "bzip2", + }, + ); + + +WriteMakefile( %config ); diff --git a/bml/doc/bml-notes.txt b/bml/doc/bml-notes.txt new file mode 100755 index 0000000..6755122 --- /dev/null +++ b/bml/doc/bml-notes.txt @@ -0,0 +1,61 @@ +TEMPLATE FLAGS +============== +This documents the flags in braces at the beginning of .look +file block template definitions. The flags fall into one +of three classes: + +1) Varible definition types: + + F: full, mix of multi & single line property definitions: + + Single line string + template?> + + P: pipe delimited, properites are named DATA, where starts at + 1 and increases. + + + + D: one proprety, and it's named DATA + + + + +2) Static template definitions: + + S: static: output won't have more BML to expand, or properties to fill-in, + so don't try. + + R: less static: add pRoperties, but then don't BML expand. + +3) Controlling expansion vs. interpolation order: + + p: pre-parsed. BML-expand parameters first, then interpolate into + template. by default, parameters are interpolated first, then + everything is expanded. but if you use %%TITLE%% twice in your + PAGE, for example, and your .bml file defines TITLE=> with a + _CODE block, it will be run twice, so it's generally a good idea + to make PAGE definitions pre-parsed. also, then, you avoid + re-running most of your output through the BML expander a second + time. + + s: expand embedded parameterless static blocks in definition early. + so when the template file is read, any blocks of the form (=FOO=) + are expanded ahead of time. Useful in conjunction with the {S} + flag. consider: + + # Our image server: + IMGPREFIX=>{S}http://www.site.com:8080/ + + # Some block that has an image: + SPACER=>{Ss} + + The SPACER block isn't really static, but because {s} is used and IMGPREFIX + is static, then SPACER can also be static. + diff --git a/bml/doc/docbook/BUILD.txt b/bml/doc/docbook/BUILD.txt new file mode 100755 index 0000000..7301fe0 --- /dev/null +++ b/bml/doc/docbook/BUILD.txt @@ -0,0 +1,5 @@ +To build the BML documentation from these DocBook sources, you'll need +apidoc.pl from wcmtools here, and then run generate.pl. + +FIXME: better notes + diff --git a/bml/doc/docbook/appx.gfdl.xml b/bml/doc/docbook/appx.gfdl.xml new file mode 100755 index 0000000..268aec6 --- /dev/null +++ b/bml/doc/docbook/appx.gfdl.xml @@ -0,0 +1,450 @@ + +GNU Free Documentation License + + + + + + + Version 1.1, March 2000 + +
+ Copyright (C) 2000 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +
+ + + PREAMBLE + + The purpose of this License is to make a manual, textbook, + or other written document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by + others. + + This License is a kind of "copyleft", which means that + derivative works of the document must themselves be free in the + same sense. It complements the GNU General Public License, which + is a copyleft license designed for free software. + + We have designed this License in order to use it for manuals + for free software, because free software needs free documentation: + a free program should come with manuals providing the same + freedoms that the software does. But this License is not limited + to software manuals; it can be used for any textual work, + regardless of subject matter or whether it is published as a + printed book. We recommend this License principally for works + whose purpose is instruction or reference. + + + + APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work that + contains a notice placed by the copyright holder saying it can be + distributed under the terms of this License. The "Document", + below, refers to any such manual or work. Any member of the + public is a licensee, and is addressed as "you". + + A "Modified Version" of the Document means any work + containing the Document or a portion of it, either copied + verbatim, or with modifications and/or translated into another + language. + + A "Secondary Section" is a named appendix or a front-matter + section of the Document that deals exclusively with the + relationship of the publishers or authors of the Document to the + Document's overall subject (or to related matters) and contains + nothing that could fall directly within that overall subject. + (For example, if the Document is in part a textbook of + mathematics, a Secondary Section may not explain any mathematics.) + The relationship could be a matter of historical connection with + the subject or with related matters, or of legal, commercial, + philosophical, ethical or political position regarding + them. + + The "Invariant Sections" are certain Secondary Sections + whose titles are designated, as being those of Invariant Sections, + in the notice that says that the Document is released under this + License. + + The "Cover Texts" are certain short passages of text that + are listed, as Front-Cover Texts or Back-Cover Texts, in the + notice that says that the Document is released under this + License. + + A "Transparent" copy of the Document means a + machine-readable copy, represented in a format whose specification + is available to the general public, whose contents can be viewed + and edited directly and straightforwardly with generic text + editors or (for images composed of pixels) generic paint programs + or (for drawings) some widely available drawing editor, and that + is suitable for input to text formatters or for automatic + translation to a variety of formats suitable for input to text + formatters. A copy made in an otherwise Transparent file format + whose markup has been designed to thwart or discourage subsequent + modification by readers is not Transparent. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include + plain ASCII without markup, Texinfo input format, LaTeX input + format, SGML or XML using a publicly available DTD, and + standard-conforming simple HTML designed for human modification. + Opaque formats include PostScript, PDF, proprietary formats that + can be read and edited only by proprietary word processors, SGML + or XML for which the DTD and/or processing tools are not generally + available, and the machine-generated HTML produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page + itself, plus such following pages as are needed to hold, legibly, + the material this License requires to appear in the title page. + For works in formats which do not have any title page as such, + "Title Page" means the text near the most prominent appearance of + the work's title, preceding the beginning of the body of the + text. + + + + VERBATIM COPYING + + You may copy and distribute the Document in any medium, + either commercially or noncommercially, provided that this + License, the copyright notices, and the license notice saying this + License applies to the Document are reproduced in all copies, and + that you add no other conditions whatsoever to those of this + License. You may not use technical measures to obstruct or + control the reading or further copying of the copies you make or + distribute. However, you may accept compensation in exchange for + copies. If you distribute a large enough number of copies you + must also follow the conditions in section 3. + + You may also lend copies, under the same conditions stated + above, and you may publicly display copies. + + + + COPYING IN QUANTITY + + If you publish printed copies of the Document numbering more + than 100, and the Document's license notice requires Cover Texts, + you must enclose the copies in covers that carry, clearly and + legibly, all these Cover Texts: Front-Cover Texts on the front + cover, and Back-Cover Texts on the back cover. Both covers must + also clearly and legibly identify you as the publisher of these + copies. The front cover must present the full title with all + words of the title equally prominent and visible. You may add + other material on the covers in addition. Copying with changes + limited to the covers, as long as they preserve the title of the + Document and satisfy these conditions, can be treated as verbatim + copying in other respects. + + If the required texts for either cover are too voluminous to + fit legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a + machine-readable Transparent copy along with each Opaque copy, or + state in or with each Opaque copy a publicly-accessible + computer-network location containing a complete Transparent copy + of the Document, free of added material, which the general + network-using public has access to download anonymously at no + charge using public-standard network protocols. If you use the + latter option, you must take reasonably prudent steps, when you + begin distribution of Opaque copies in quantity, to ensure that + this Transparent copy will remain thus accessible at the stated + location until at least one year after the last time you + distribute an Opaque copy (directly or through your agents or + retailers) of that edition to the public. + + It is requested, but not required, that you contact the + authors of the Document well before redistributing any large + number of copies, to give them a chance to provide you with an + updated version of the Document. + + + + MODIFICATIONS + + You may copy and distribute a Modified Version of the + Document under the conditions of sections 2 and 3 above, provided + that you release the Modified Version under precisely this + License, with the Modified Version filling the role of the + Document, thus licensing distribution and modification of the + Modified Version to whoever possesses a copy of it. In addition, + you must do these things in the Modified Version: + + + Use in the Title Page + (and on the covers, if any) a title distinct from that of the + Document, and from those of previous versions (which should, if + there were any, be listed in the History section of the + Document). You may use the same title as a previous version if + the original publisher of that version gives permission. + + + List on the Title Page, + as authors, one or more persons or entities responsible for + authorship of the modifications in the Modified Version, + together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than + five). + + + State on the Title page + the name of the publisher of the Modified Version, as the + publisher. + + + Preserve all the + copyright notices of the Document. + + + Add an appropriate + copyright notice for your modifications adjacent to the other + copyright notices. + + + Include, immediately + after the copyright notices, a license notice giving the public + permission to use the Modified Version under the terms of this + License, in the form shown in the Addendum below. + + + Preserve in that license + notice the full lists of Invariant Sections and required Cover + Texts given in the Document's license notice. + + + Include an unaltered + copy of this License. + + + Preserve the section + entitled "History", and its title, and add to it an item stating + at least the title, year, new authors, and publisher of the + Modified Version as given on the Title Page. If there is no + section entitled "History" in the Document, create one stating + the title, year, authors, and publisher of the Document as given + on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. + + + Preserve the network + location, if any, given in the Document for public access to a + Transparent copy of the Document, and likewise the network + locations given in the Document for previous versions it was + based on. These may be placed in the "History" section. You + may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. + + + In any section entitled + "Acknowledgements" or "Dedications", preserve the section's + title, and preserve in the section all the substance and tone of + each of the contributor acknowledgements and/or dedications + given therein. + + + Preserve all the + Invariant Sections of the Document, unaltered in their text and + in their titles. Section numbers or the equivalent are not + considered part of the section titles. + + + Delete any section + entitled "Endorsements". Such a section may not be included in + the Modified Version. + + + Do not retitle any + existing section as "Endorsements" or to conflict in title with + any Invariant Section. + + + + If the Modified Version includes new front-matter sections + or appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option + designate some or all of these sections as invariant. To do this, + add their titles to the list of Invariant Sections in the Modified + Version's license notice. These titles must be distinct from any + other section titles. + + You may add a section entitled "Endorsements", provided it + contains nothing but endorsements of your Modified Version by + various parties--for example, statements of peer review or that + the text has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover + Text, and a passage of up to 25 words as a Back-Cover Text, to the + end of the list of Cover Texts in the Modified Version. Only one + passage of Front-Cover Text and one of Back-Cover Text may be + added by (or through arrangements made by) any one entity. If the + Document already includes a cover text for the same cover, + previously added by you or by arrangement made by the same entity + you are acting on behalf of, you may not add another; but you may + replace the old one, on explicit permission from the previous + publisher that added the old one. + + The author(s) and publisher(s) of the Document do not by + this License give permission to use their names for publicity for + or to assert or imply endorsement of any Modified Version. + + + + COMBINING DOCUMENTS + + You may combine the Document with other documents released + under this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination + all of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice. + + The combined work need only contain one copy of this + License, and multiple identical Invariant Sections may be replaced + with a single copy. If there are multiple Invariant Sections with + the same name but different contents, make the title of each such + section unique by adding at the end of it, in parentheses, the + name of the original author or publisher of that section if known, + or else a unique number. Make the same adjustment to the section + titles in the list of Invariant Sections in the license notice of + the combined work. + + In the combination, you must combine any sections entitled + "History" in the various original documents, forming one section + entitled "History"; likewise combine any sections entitled + "Acknowledgements", and any sections entitled "Dedications". You + must delete all sections entitled "Endorsements." + + + + COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and + other documents released under this License, and replace the + individual copies of this License in the various documents with a + single copy that is included in the collection, provided that you + follow the rules of this License for verbatim copying of each of + the documents in all other respects. + + You may extract a single document from such a collection, + and distribute it individually under this License, provided you + insert a copy of this License into the extracted document, and + follow this License in all other respects regarding verbatim + copying of that document. + + + + AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of + a storage or distribution medium, does not as a whole count as a + Modified Version of the Document, provided no compilation + copyright is claimed for the compilation. Such a compilation is + called an "aggregate", and this License does not apply to the + other self-contained works thus compiled with the Document, on + account of their being thus compiled, if they are not themselves + derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to + these copies of the Document, then if the Document is less than + one quarter of the entire aggregate, the Document's Cover Texts + may be placed on covers that surround only the Document within the + aggregate. Otherwise they must appear on covers around the whole + aggregate. + + + + TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires + special permission from their copyright holders, but you may + include translations of some or all Invariant Sections in addition + to the original versions of these Invariant Sections. You may + include a translation of this License provided that you also + include the original English version of this License. In case of + a disagreement between the translation and the original English + version of this License, the original English version will + prevail. + + + + TERMINATION + + You may not copy, modify, sublicense, or distribute the + Document except as expressly provided for under this License. Any + other attempt to copy, modify, sublicense or distribute the + Document is void, and will automatically terminate your rights + under this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full + compliance. + + + + FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised + versions of the GNU Free Documentation License from time to time. + Such new versions will be similar in spirit to the present + version, but may differ in detail to address new problems or + concerns. See http://www.gnu.org/copyleft/. + + Each version of the License is given a distinguishing + version number. If the Document specifies that a particular + numbered version of this License "or any later version" applies to + it, you have the option of following the terms and conditions + either of that specified version or of any later version that has + been published (not as a draft) by the Free Software Foundation. + If the Document does not specify a version number of this License, + you may choose any version ever published (not as a draft) by the + Free Software Foundation. + + + + How to use this License for your documents + + To use this License in a document you have written, include + a copy of the License in the document and put the following + copyright and license notices just after the title page: + +
+ Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +
+ + If you have no Invariant Sections, write "with no Invariant + Sections" instead of saying which ones are invariant. If you have + no Front-Cover Texts, write "no Front-Cover Texts" instead of + "Front-Cover Texts being LIST"; likewise for Back-Cover + Texts. + + If your document contains nontrivial examples of program + code, we recommend releasing these examples in parallel under your + choice of free software license, such as the GNU General Public + License, to permit their use in free software. +
+ +
\ No newline at end of file diff --git a/bml/doc/docbook/book.ent b/bml/doc/docbook/book.ent new file mode 100755 index 0000000..04403b9 --- /dev/null +++ b/bml/doc/docbook/book.ent @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version + 1.1 or any later version published by the Free Software + Foundation; with no invariant sections, nor Front-Cover/Back-Cover + Texts. + A copy of the license is included in + + +"> + + 1997 + 1998 + 1999 + 2000 + 2001 + 2002 + Brad Fitzpatrick + +'> \ No newline at end of file diff --git a/bml/doc/docbook/book.xml b/bml/doc/docbook/book.xml new file mode 100755 index 0000000..87c0f3c --- /dev/null +++ b/bml/doc/docbook/book.xml @@ -0,0 +1,15 @@ + + +%book; + +]> + + &bml.bookinfo; + &bml.preface; + &bml.tutorial; + &bml.flags; + &bml.core; + &bml.api.ref; + &appx.gfdl; + diff --git a/bml/doc/docbook/bookinfo.xml b/bml/doc/docbook/bookinfo.xml new file mode 100755 index 0000000..fee25db --- /dev/null +++ b/bml/doc/docbook/bookinfo.xml @@ -0,0 +1,35 @@ + + The Better Markup Language + BML + BML Manual Version 1.0 + + + Anyone's who's ever put together a large website or done a lot of server-side + programming will know how hard and annoying it is to keep a consistent look + through a site, and how painful it is to go back and change something globally + later, once their site is up. In addition, looking at HTML + code is ugly and HTML editors don't always do what you want them to. + + + BML was designed to address a lot of these problems. + BML is a server-side markup language that lets you define your own + BML blocks and use them as templates within your BML pages. + Your templates don't even have to be static. Because BML pages are + converted to HTML on the server when users request them, this also + enables you to embed live code within your BML pages, just like a + CGI script. + + + A lot is possible using BML. Whether you want to make a full blown + database driven website, enable a little dynamic content on your site, or just + make things on your site easier to maintain, BML can really help out. + + + The official website for BML is located at . + + + &bml.copyright; + &bml.legalnotice; + +The Better Markup Language +BML diff --git a/bml/doc/docbook/build.pl b/bml/doc/docbook/build.pl new file mode 100755 index 0000000..6aa89bc --- /dev/null +++ b/bml/doc/docbook/build.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; + +my $XSL_VERSION_RECOMMENDED = "1.45"; + +my $opt_clean; +my ($opt_myxsl, $opt_getxsl); +exit 1 unless GetOptions('clean' => \$opt_clean, + 'myxsl' => \$opt_myxsl, + 'getxsl' => \$opt_getxsl, + ); + +my $home = $ENV{'LJHOME'}; +require "$home/cgi-bin/ljlib.pl"; +$ENV{'SGML_CATALOG_FILES'} = $LJ::CATALOG_FILES || "/usr/share/sgml/docbook/dtd/xml/4.1/docbook.cat"; + +unless (-e $ENV{'SGML_CATALOG_FILES'}) { + die "Catalog files don't exist. Either set \$LJ::CATALOG_FILES, install docbook-xml (on Debian), or symlink $ENV{'SGML_CATALOG_FILES'} to XML DocBook 4.1's docbook.cat."; +} + +if ($opt_getxsl) { + chdir "$home/doc/raw/build" or die "Where is build dir?"; + unlink "xsl-docbook.tar.gz"; + my $fetched = 0; + my $url = "http://www.livejournal.org/misc/xsl-docbook.tar.gz"; + my @fetcher = ([ 'wget', "wget $url", ], + [ 'lynx', "lynx -source $url > xsl-docbook.tar.gz", ], + [ 'GET', "GET $url > xsl-docbook.tar.gz", ]); + foreach my $fet (@fetcher) { + next if $fetched; + print "Looking for $fet->[0] ...\n"; + next unless `which $fet->[0]`; + print "RUNNING: $fet->[1]\n"; + system($fet->[1]) + and die "Error running $fet->[0]. Interrupted?\n"; + $fetched = 1; + } + unless ($fetched) { + die "Couldn't find a program to download things from the web. I looked for:\n\t". + join(", ", map { $_->[0] } @fetcher) . "\n"; + } + system("tar", "zxvf", "xsl-docbook.tar.gz") + and die "Error extracting xsl-doxbook.tar.gz; have GNU tar?\n"; +} + +my $output_dir = "$home/htdocs/doc/bml"; +my $docraw_dir = "$home/doc/raw"; +my $XSL = "$docraw_dir/build/xsl-docbook"; +my $stylesheet = "$XSL/html/chunk.xsl"; +open (F, "$XSL/VERSION"); +my $XSL_VERSION; +{ + local $/ = undef; my $file = ; + $XSL_VERSION = $1 if $file =~ /VERSION.+\>(.+?)\ $docraw_dir/bml.book/api.gen.xml") + and die "Errror generating BML API reference.\n"; + +system("xsltproc --nonet --catalogs ". + "--stringparam use.id.as.filename '1' ". + "$stylesheet $docraw_dir/bml.book/book.xml") + and die "Error generating HTML.\n"; diff --git a/bml/doc/docbook/core.xml b/bml/doc/docbook/core.xml new file mode 100755 index 0000000..87afe81 --- /dev/null +++ b/bml/doc/docbook/core.xml @@ -0,0 +1,115 @@ + + + Core <abbrev>BML</abbrev> blocks + + Core <abbrev>BML</abbrev> blocks + + Core blocks are predefined blocks that are named with a leading underscore. + Most core blocks have a higher purpose than simple template use: + + + + _code + + <?_code _code?> blocks are perhaps the most useful feature of + BML outside of the ability to have global site templates. + These blocks allow template authors to embed pieces of executable Perl code + within the bml page that get executed on the server. + + + The code you write gets executed in its own package (namespace) called + BMLCodeBlock::. + Any variables you declare in one code block on a page without using + my are carried on to the next _code block. + + Because the BML parser must evaluate everything on the page before sending the + HTTP headers, make sure you don't print anything. + Any output printed to STDOUT will just be interpreted as + HTTP headers. How the _code blocks work is + that you need to return a value at the end. + Whatever value your code fragment returns is what the block evaluates to. + Usually what you end up doing is building a string, concatenating things to it + over and over, and then returning it at the end. + + + + _c - _comment + + Comment blocks are templates that do not get parsed into resultant text later, + and are useful when HTML style comments + (<!-- -->) are not desired. + + + + _info + + Information blocks can be used to include special information about the particular + BML page the block is contained in. + + <literal>_info</literal> directives + + package + Specify and load a required package + + + nocache + Specified page is dynamic, and shouldn't be cached + + + static + Specified page is static; ok to cache + + + noheaders + Turn off default BML headers + + + nocontent + Specify that page has no cacheable content + + + localblocks + Declare page specific BML blocks. + + + + + + _include + + Include blocks can be used to integrate a text file straight into a BML + file. Include files can be written in BML or plain text. + + + + _e* + + _e* are a variety of escape blocks, each with a different purpose: + + + _eh + Replace certain ASCII characters with their HTML entity counterparts + + + _eb + Replace certain ASCII characters that can trigger BML blocks (<?xml?>) with their HTML entity counterparts + + + _eu + Escape non-compliant ASCII characters in URLs + + + _ea + Escape text by passing through eh and then eb + + + + + + _ml + + Multi language blocks are used to interchange certain text blocks with the specified language-domain translation. + + + + \ No newline at end of file diff --git a/bml/doc/docbook/flags.xml b/bml/doc/docbook/flags.xml new file mode 100755 index 0000000..e55e5ed --- /dev/null +++ b/bml/doc/docbook/flags.xml @@ -0,0 +1,89 @@ + + BML Block Types + + This documents the flags in braces at the beginning of .look file block template definitions. + The flags fall into one of three classes: + + + + Varible definition types: + + F + + Full, mix of multi & single line property definitions: + Single line string +template?>]]> + + + + + P + + Pipe delimited, properites are named DATA<n>, where <n> starts at 1 and increases. + <?template DATA1|second arg|DATA3 template?> + + + + + D + + One property, and it's named DATA + <?template I am the DATA template?> + + + + + + Static template definitions: + + S + + Static: output won't have more BML to expand, or properties to fill-in, so don't try. + + + + R + + Less static: add pRoperties, but then don't BML expand. + + + + + Controlling expansion vs. interpolation order: + + p + + + Pre-parsed. + BML-expand parameters first, then interpolate into template. + By default, parameters are interpolated first, then everything is expanded. + But if you use %%TITLE%% twice in your PAGE, for example, and your .bml file defines TITLE=> with a _CODE block, it will be run twice, so it's generally a good idea to make PAGE definitions pre-parsed. + Also, then, you avoid re-running most of your output through the BML expander a second time. + + + + + s + + + Expand embedded parameterless static blocks in definition early. + When the template file is read, any blocks of the form <?foo?> are expanded ahead of time. + Useful in conjunction with the {S} flag. consider: + {S}http://www.site.com:8080/ + +# Some block that has an image: +SPACER=>{Ss}]]> + The SPACER block isn't really static, but because {s} is used and <?IMGPREFIX?> is static, then SPACER can also be static. + + + + + + \ No newline at end of file diff --git a/bml/doc/docbook/index.xml b/bml/doc/docbook/index.xml new file mode 100755 index 0000000..d8ce35c --- /dev/null +++ b/bml/doc/docbook/index.xml @@ -0,0 +1,8 @@ + + &bml.bookinfo; + &bml.preface; + &bml.tutorial; + &bml.flags; + &bml.core; + &bml.api.ref; + diff --git a/bml/doc/docbook/preface.xml b/bml/doc/docbook/preface.xml new file mode 100755 index 0000000..d58519d --- /dev/null +++ b/bml/doc/docbook/preface.xml @@ -0,0 +1,64 @@ + + + + Preface + + This is a comprehensive manual aimed towards people wishing to + use BML for their website needs. + Some of the topics covered include setting up BML for + a website, writing a custom BML scheme, and + customization & optimization of a BML installation. + + + Target Audience + + This book was written for anyone interested in installing and using + BML for their own purposes, and for people who are + just generally interested in how BML works. + + + + Readers of this book should be familiar with administering a web + site, and have at least a brief knowledge of HTML. + + Organization + The Manual is organized into certain chapters: + + + + + + A tutorial covering the basics of BML, and + explaining how to write a BML document. + + + + + + A reference to BML block flags. + + + + + + A reference to the core BML blocks. + + + + + + An application programming interface reference. + + + + + + Versions + + An online version of this book can be found at: + . + To compile these pages for your own, refer to: + /doc/raw/notes.txt in CVS. + + + \ No newline at end of file diff --git a/bml/doc/docbook/tutorial.xml b/bml/doc/docbook/tutorial.xml new file mode 100755 index 0000000..9865fb2 --- /dev/null +++ b/bml/doc/docbook/tutorial.xml @@ -0,0 +1,552 @@ + + + + A Brief Tutorial + + + A Brief Tutorial + + + The goal of using BML is to become a smarter, lazier + webmaster. The qualities that define a BML author should + be the same as a good Perl programmer: laziness, impatience, + and hubris. + + +
+ Introducing <abbrev>BML</abbrev> + + +
+ Blocks + + BML is essentially a simple macro language. Macros are + called blocks in BML. Blocks are + defined in look files + and are invoked in BML files. + Blocks accept parameters and are divided into + several types according to how parameters are + transmitted and how the definition of the block is able to make use of + them. Definitions of blocks are essentially chunks of + HTML with potentially more recursive + BML block invocations inside them. + + + + BML lookup file + The Alabaster Project + +greeting<= +

Welcome to , a joint effort between the citizens of earth +and Spumco, Inc.

+<=greeting +]]>
+
+ + The "project" and "greeting" constructs in the above example lookup file are + blocks, and can be used to insert their respective content into HTML + output. The "project" block is a single-line block that consists of + everything immediately following the name of the block and the + => up to the end of the line. The "greeting" + block is a multiline block, and contains all the lines immediately + following the greeting<= line and preceding + the <=greeting one. + +
+ + +
+ BML Files + + A BML file is simply an HTML file with + some BML block invocations in it. Each such invocation + specifies the name of the block and the parameters, if any, to pass to it. + The ultimate result of a block's invocation at runtime is HTML + which is put in the outgoing stream exactly at the place where the block's + invocation resided in the BML file. + + + + BML file + + <?project project?> + +

+ + + + +]]>
+
+ + Given the lookup file from the previous example, the BML file above + would yield output like: + + + Output + + The Alabaster Project + +

The Alabaster Project

+ +

Welcome to The Alabaster Project, a joint effort between the citizens of earth +and Spumco, Inc.

+ + + +]]>
+
+ + The block invocations in the BML + lookup file example above do not contain parameters, but even + so are still a powerful way of building a document out of aggregate + parts. Adding parameters, of course, increases this usefulness. +
+
+ + +
+ Block Parameters + +
+ The <varname>DATA</varname> Block Parameter + Sometimes the insertion of simple static content into the output + will not suffice for projects of moderate complexity. A designer + frequently wishes to repeat certain elements throughout the page, + keeping a consistent structure and look-and-feel. BML provides this + functionality by allowing you to declare blocks which take parameters, + which can then be used in building the content inserted into the + document. + + The simplest parameter-accepting block is one you've seen already in + the above examples. Unless otherwise designated, all blocks accept one + parameter, which is put into a variable called + DATA. This parameter can then be interpolated + into the resulting output with a placeholder that looks like: + %%DATA%%. + + + Lookup file with DATA blocks +

%%DATA%%

+subheading=>

%%DATA%%

+]]>
+
+ + This lookup file defines two blocks, one called + heading which creates level-one heading HTML, and + another called subhead, which creates level-two + headings. + + These could be used like so: + + + BML file using parameterized blocks + + Hansel and Grendel Go to Finishing School + +]]> +]]> +Our story begins at a point in the Universe not unlike where you are now + sitting, drinking your government-sanctioned stimulant, dreaming of the + day when you, too, will own your own personalized luxury home on 0.3 acres + of land, with a stunning view of, well, the neighbor's personalized luxury + home on 0.3 acres of land. Except this point in the Universe is much more + exciting, fine-smelling, and generally a better place to be than + yours.

+]]> +]]> +So, anyway, at this particular point in the Universe, on a day not + entirely unlike today, two entirely unrelated mythological pantheons + collided, resulting in a fast friendship between a Little Boy Bound to be + Eaten by the Architypal Crone and a Faceless Beast That Waits for the Hero + to Dispatch It. Which, as you might have guessed, was not the intention of + the various storytellers involved, but that's what happens when people + stop reading all the really cool stories and start checking the Financial + Section every 12 minutes. There's only so much space to go around in the + collective consciousness, you know...

+ + + ]]>
+
+ + which would result in output like: + + + Parameterized Output: Named Parameters + + Hansel and Grendel Go to Finishing School + +]]> +Hansel and Grendel Go to Finishing School heading]]> +Our story begins at a point in the Universe not unlike where you are now + sitting, drinking your government-sanctioned stimulant, dreaming of the + day when you, too, will own your own personalized luxury home on 0.3 acres + of land, with a stunning view of, well, the neighbor's personalized luxury + home on 0.3 acres of land. Except this point in the Universe is much more + exciting, fine-smelling, and generally a better place to be than + yours.

+ +]]> +No, Really, It Is Much Finer]]> +So, anyway, at this particular point in the Universe, on a day not + entirely unlike today, two entirely unrelated mythological pantheons + collided, resulting in a fast friendship between a Little Boy Bound to be + Eaten by the Architypal Crone and a Faceless Beast That Waits for the Hero + to Dispatch It. Which, as you might have guessed, was not the intention of + the various storytellers involved, but that's what happens when people + stop reading all the really cool stories and start checking the Financial + Section every 12 minutes. There's only so much space to go around in the + collective consciousness, you know...

+ + +]]>
+
+ + By this point, you might be saying, "But wait! I'd much rather type + '<h1> ... </h1>' than + '<?heading ... heading?>'!" If you were + absolutely confident that headings would always be expressed with + <h1> tags, and subheadings with + <h2> tags, it might be more efficent to + leave them as static HTML. If, however, someone wants all headings and + subheadings to change throughout the site, having the definition of them + expressed as a block makes changing them everywhere a simple matter of + changing the block that defines them: + + + Alternate Heading Block +

%%DATA%%

+subhead<= + +
+

%%DATA%%

+<=subhead +]]>
+
+ + Instead of a fairly complex search-and-replace session over multiple + files, you instead need only change the definition of what a heading means + in one place, and see it reflected throughout your site. Note that + multiline blocks can also use the DATA + parameter. + + The examples above are admittedly contrived, and could probably be + accomplished using CSS, but it should serve to + demonstrate a use which is orthogonal to the role played by style + systems. +
+ + +
+ Block Flags and Passing Multiple Parameters + + Many tasks will not be able to be accomplished with blocks that have + only one parameter, so BML provides another kind of block that can be + passed multiple parameters. Up 'til now, we've been using blocks with an + implied parameter, but we'll need to tell BML that the block we're + defining is different. This is accomplished by specifying one or more + flags when declaring the block. Flags are single + letters that are placed inside curly braces ({}) at + the beginning of the block definition. For example, the flag that + corresponds to the full block type (which we'll be using for blocks that + can accept multiple parameters) is designated with an + {F} flag: + + + Block Definitions with Flags + {D}%%DATA%% + +topiclink=>{F}%%linktext%% + +section<={F} +
+

%%heading%%

+

%%body%%

+
+<=section +]]> +
+
+ + As you can see, two of the blocks declared above have an + {F} flag, and one has a {D} + flag. The {D} flag stands for 'data', which is the + default block type we're already familiar with, so the flag part could + have been omitted. There are other block types which specify other + attributes and behaviors, but for now we'll focus on the + {F} type. + + In the above example, two {F} blocks are defined, + a single-line one and a multi-line one. Both expect multiple parameters + which they use to fill in parts of the HTML fragments they are responsible + for creating. They also use placeholders like {D} + blocks do, but they have unique names that will serve as the label given + with the parameter that belongs there when calling it from a BML + file. + + Calling an {F} block necessarily looks a bit + different than the simple references made to {D} + blocks. Calls to a block which requires multiple parameters uses the same + syntax as that used for declaring blocks: + + + BML File + listrules +heading=>Rules of the Lists +body<= +There are many considerations when engaging in mounted combat at a tourney, not +the least of which is obeying the convoluted and sometimes confusing localized +Rules of the Lists. +<=body +section?> +]]> + + + In the above example, the section block is being + called with three parameters, two of which are single-line parameters + (id and heading), and a third + multi-line one (body). The output rendered by combining + the above BML file with the previous lookup file would look something + like: + + + Example output + + +

Rules of the Lists

+

There are many considerations when engaging in mounted combat at a tourney, not +the least of which is obeying the convoluted and sometimes confusing localized +Rules of the Lists. +

+ +]]> +
+
+
+ +
+ Parameterized Output: Positional Parameters + + In addition to the named parameters introduced above, BML also + supports positional parameters. Like with named parameters, a block with + positional parameters is designated with the use of a flag, this time the + {P} or "pipe-delimited" flag. Parameters in a + {P} block are represented with + %%DATA1%%, %%DATA2%%, etc. This can + be useful when a routine takes a lot of parameters, or when calling the + same block many times with tabular or list data. + + An example of this is building a list of links, each of which is an + item in a definition list: + + + Block Definitions with Positional Parameters + +{P}
%%data1%%
%%data3%%
+ +LINKLIST<= +{F} +

My Current Reading List

+
+%%items%% +
+

Last updated: %%date%%

+<=LINKLIST +]]> +
+
+ + + BML File using the 'listlist' and 'linkitem' blocks + +2004/10/14 +items<= + + + +<=items +linklist?> +]]> + + + + Combining the two files above would render output like this: + + + Example output + + My Current Reading List +
+
News of Brad
Brad's daily adventure
+
BoingBoing
A directory of wonderful things
+
WPGtR
Wow, this book comes with an onion!
+ +
+

Last updated: 2004/10/14

+]]> +
+
+
+
+ +
+ Static Blocks + + Sometimes the re-expansion of embedded BMl might not be what you + want. In that case, you can designate a block with a flag which will cause + it to stop or limit the re-expansion of embedded calls. + +
+ Fully-Static Blocks + + If you add the {S} flag to the block you're + defining, the contents of it will not be re-evaluated afterward. This is + mostly useful when you have blocks that you are sure will never contain + BML to be expanded or properties to fill in, and you want to save the + overhead of trying to re-evaluate them. + + + Look file with <literal>{S}</literal> block + +{S}Spumco, Inc. +]]> + + + + This defines the companyname block as + static. + + + BML File that calls the static block + +Welcome to +]]> + + + + Combining the two yields: + + + Example output + +Welcome to Spumco, Inc. +]]> + + +
+ +
+ Semi-static Blocks + + Sometimes you want a block which fits somewhere between the + fully-dynamic {D} blocks and the completely-static + behavior of {S} blocks. Enter the + {R} block flag, which expands + pRoperties like those passed to a + {D}, {F}, or {P} + block, but doesn't expand BML that might be inserted by one of + those. + + + Look file with <literal>{R}</literal> block + + + + + + + + + + + + + + + + + + Example output + + + + + + + +
+ + + +
+ +
+ A Full Example + + + + + + + + FooBar Enterprises - Page + + +

FooBar Enterprises - Page

+
+
Headers - What good are they?
+

+ This is just an introductory text. The normal way to include text like this + is to write it in Latin, but since I don't know Latin, you'll have to settle + with this little paragraph. +

+
Templates are for Wimps!
+

+ I'd rather have to edit all of my pages by hand when I decide to change the + unified look of my site! +

+ + + ]]>
+
+ + {D}
%%DATA%%
+ ]]>
+
+ + + ]]> + + + + +
+
\ No newline at end of file diff --git a/bml/lib/Apache/BML.pm b/bml/lib/Apache/BML.pm new file mode 100755 index 0000000..69ed4ec --- /dev/null +++ b/bml/lib/Apache/BML.pm @@ -0,0 +1,2065 @@ +#!/usr/bin/perl +# + +use strict; + +package BML::Request; + +use fields qw( + env blockref lang r blockflags BlockStack + file scratch IncludeOpen content_type clean_package package + filechanged scheme scheme_file IncludeStack etag location + most_recent_mod stop_flag want_last_modified cookies + ); + + +package Apache::BML; + +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED); +use Apache::File (); +use Apache::URI; +use Digest::MD5; +use File::Spec; +BEGIN { + $Apache::BML::HAVE_ZLIB = eval "use Compress::Zlib (); 1;"; +} + +# set per request: +use vars qw($cur_req); +use vars qw(%CodeBlockOpts); +# scalar hashrefs of versions below, minus the domain part: +my ($SchemeData, $SchemeFlags); + +# keyed by domain: +my $ML_SCOPE; # generally the $r->uri, auto set on each request (unless overridden) +my (%SchemeData, %SchemeFlags); # domain -> scheme -> key -> scalars (data has {s} blocks expanded) + +# safely global: +use vars qw(%FileModTime %LookItems); # LookItems: file -> template -> [ data, flags ] +use vars qw(%LookParent); # file -> parent file +use vars qw(%LookChild); # file -> child -> 1 + +my (%CodeBlockMade); + +use vars qw($conf_pl $conf_pl_look); # hashref, made empty before loading a .pl conf file +my %DenyConfig; # filename -> 1 +my %FileConfig; # filename -> hashref +my %FileLastStat; # filename -> time we last looked at its modtime + +use vars qw($base_recent_mod); + +# the request we're handling (Apache->request). using this way +# instead of just using Apache->request because when using +# Apache::FakeRequest and non-mod_perl env, I can't seem to get/set +# the value of Apache->request +use vars qw($r); + +# regexps to match open and close tokens. (but old syntax (=..=) is deprecated) +my ($TokenOpen, $TokenClose) = ('<\?', '\?>'); + +tie %BML::ML, 'BML::ML'; +tie %BML::COOKIE, 'BML::Cookie'; + +sub handler +{ + my $r = shift; + my $file; + + $Apache::BML::r = $r; + + # determine what file we're supposed to work with: + if (ref $r eq "Apache::FakeRequest") { + # for testing. FakeRequest's 'notes' method is busted, always returning + # true. + $file = $r->filename; + stat($file); + } elsif ($file = $r->notes("bml_filename")) { + # when another handler needs to invoke BML directly + stat($file); + } else { + # normal case + $file = $r->filename; + $r->finfo; + } + + unless (-e _) { + $r->log_error("File does not exist: $file"); + return NOT_FOUND; + } + + unless (-r _) { + $r->log_error("File permissions deny access: $file"); + return FORBIDDEN; + } + + my $modtime = (stat _)[9]; + + return FORBIDDEN if $file =~ /\b_config/; + + # create new request + my $req = $cur_req = fields::new('BML::Request'); + $req->{file} = $file; + $req->{r} = $r; + $req->{BlockStack} = [""]; + $req->{scratch} = {}; # _CODE blocks can play + $req->{cookies} = {}; + + # setup env + my $env = $req->{env} = {}; + + # walk up directories, looking for _config.bml files, populating env + my $dir = $file; + my $docroot = $r->document_root(); $docroot =~ s!/$!!; + my @dirconfs; + my %confwant; # file -> 1, if applicable config + + while ($dir) { + $dir =~ s!/[^/]*$!!; + my $conffile = "$dir/_config.bml"; + $confwant{$conffile} = 1; + push @dirconfs, load_conffile($conffile); + last if $dir eq $docroot; + } + + # we now have dirconfs in order from first to apply to last. + # but a later one may have a subconfig to override, so + # go through those first, keeping track of which configs + # are effective + my %eff_config; + + foreach my $cfile (@dirconfs) { + my $conf = $FileConfig{$cfile}; + next unless $conf; + $eff_config{$cfile} = $conf; + if ($conf->{'SubConfig'}) { + foreach my $sconf (keys %confwant) { + my $sc = $conf->{'SubConfig'}{$sconf}; + $eff_config{$cfile} = $sc if $sc; + } + } + } + + foreach my $cfile (@dirconfs) { + my $conf = $eff_config{$cfile}; + next unless $conf; + while (my ($k,$v) = each %$conf) { + next if exists $env->{$k} || $k eq "SubConfig"; + $env->{$k} = $v; + } + } + + # check if there are overrides in pnotes + # wrapped in eval because Apache::FakeRequest doesn't have + # pnotes support (as of 2004-04-26 at least) + eval { + if (my $or = $r->pnotes('BMLEnvOverride')) { + while (my ($k, $v) = each %$or) { + $env->{$k} = $v; + } + } + }; + + # environment loaded at this point + + if ($env->{'AllowOldSyntax'}) { + ($TokenOpen, $TokenClose) = ('(?:<\?|\(=)', '(?:\?>|=\))'); + } else { + ($TokenOpen, $TokenClose) = ('<\?', '\?>'); + } + + # Look for an alternate file, and if it exists, load it instead of the real + # one. + if ( exists $env->{TryAltExtension} ) { + my $ext = $env->{TryAltExtension}; + + # Trim a leading dot on the extension to allow '.lj' or 'lj' + $ext =~ s{^\.}{}; + + # If the file already has an extension, put the alt extension between it + # and the rest of the filename like Apache's content-negotiation. + if ( $file =~ m{(\.\S+)$} ) { + my $newfile = $file; + substr( $newfile, -(length $1), 0 ) = ".$ext"; + if ( -e $newfile ) { + $modtime = (stat _)[9]; + $file = $newfile; + } + } + + elsif ( -e "$file.$ext" ) { + $modtime = (stat _)[9]; + $file = "$file.$ext"; + } + } + + # Read the source of the file + unless (open F, $file) { + $r->log_error("Couldn't open $file for reading: $!"); + $Apache::BML::r = undef; # no longer valid + return SERVER_ERROR; + } + + my $bmlsource; + { local $/ = undef; $bmlsource = ; } + close F; + + # consider the file's mod time + note_mod_time($req, $modtime); + + # and all the config files: + note_mod_time($req, $Apache::BML::base_recent_mod); + + # if the file changed since we last looked at it, note that + if (!defined $FileModTime{$file} || $modtime > $FileModTime{$file}) { + $FileModTime{$file} = $modtime; + $req->{'filechanged'} = 1; + } + + # setup cookies + *BMLCodeBlock::COOKIE = *BML::COOKIE; + BML::reset_cookies(); + + # tied interface to BML::ml(); + *BMLCodeBlock::ML = *BML::ML; + + # let BML code blocks see input + %BMLCodeBlock::GET = (); + %BMLCodeBlock::POST = (); + %BMLCodeBlock::FORM = (); # whatever request method is + my %input_target = ( GET => [ \%BMLCodeBlock::GET ], + POST => [ \%BMLCodeBlock::POST ], ); + push @{$input_target{$r->method}}, \%BMLCodeBlock::FORM; + foreach my $id ([ [ $r->args ] => $input_target{'GET'} ], + [ [ $r->content ] => $input_target{'POST'} ]) + { + while (my ($k, $v) = splice @{$id->[0]}, 0, 2) { + foreach my $dest (@{$id->[1]}) { + $dest->{$k} .= "\0" if exists $dest->{$k}; + $dest->{$k} .= $v; + } + } + } + + if ($env->{'HOOK-startup'}) { + eval { + $env->{'HOOK-startup'}->(); + }; + return report_error($r, "Error running startup hook:
\n$@") + if $@; + } + + my $scheme = $r->notes('bml_use_scheme') || + $env->{'ForceScheme'} || + $BMLCodeBlock::GET{'usescheme'} || + $BML::COOKIE{'BMLschemepref'} || + $env->{'DefaultScheme'}; + unless (BML::set_scheme($scheme)) { + $scheme = $env->{'ForceScheme'} || + $env->{'DefaultScheme'}; + BML::set_scheme($scheme); + } + + my $uri = $r->uri; + BML::set_language_scope($uri); + my $lang = BML::decide_language(); + BML::set_language($lang); + + # print on the HTTP header + my $html = $env->{'_error'}; + + bml_decode($req, \$bmlsource, \$html, { DO_CODE => $env->{'AllowCode'} }) + unless $html; + + # force out any cookies we have set + BML::send_cookies($req); + + $r->register_cleanup(\&reset_codeblock) if $req->{'clean_package'}; + + # redirect, if set previously + if ($req->{'location'}) { + $r->header_out(Location => $req->{'location'}); + $Apache::BML::r = undef; # no longer valid + return REDIRECT; + } + + # see if we can save some bandwidth (though we already killed a bunch of CPU) + my $etag; + if (exists $req->{'etag'}) { + $etag = $req->{'etag'} if defined $req->{'etag'}; + } else { + $etag = Digest::MD5::md5_hex($html); + } + $etag = '"' . $etag . '"' if defined $etag; + + my $ifnonematch = $r->header_in("If-None-Match"); + if (defined $ifnonematch && defined $etag && $etag eq $ifnonematch) { + $Apache::BML::r = undef; # no longer valid + return HTTP_NOT_MODIFIED; + } + + my $rootlang = substr($req->{'lang'}, 0, 2); + unless ($env->{'NoHeaders'}) { + eval { + # this will fail while using Apache::FakeRequest, but that's okay. + $r->content_languages([ $rootlang ]); + }; + } + + my $modtime_http = modified_time($req); + + my $content_type = $req->{'content_type'} || + $env->{'DefaultContentType'} || + "text/html"; + + unless ($env->{'NoHeaders'}) + { + my $ims = $r->header_in("If-Modified-Since"); + if ($ims && ! $env->{'NoCache'} && + $ims eq $modtime_http) + { + $Apache::BML::r = undef; # no longer valid + return HTTP_NOT_MODIFIED; + } + + $r->content_type($content_type); + + if ($env->{'NoCache'}) { + $r->header_out("Cache-Control", "no-cache"); + $r->no_cache(1); + } + + $r->header_out("Last-Modified", $modtime_http) + if $env->{'Static'} || $req->{'want_last_modified'}; + + $r->header_out("Cache-Control", "private, proxy-revalidate"); + $r->header_out("ETag", $etag) if defined $etag; + + # gzip encoding + my $do_gzip = $env->{'DoGZIP'} && $Apache::BML::HAVE_ZLIB; + $do_gzip = 0 if $do_gzip && $content_type !~ m!^text/html!; + $do_gzip = 0 if $do_gzip && $r->header_in("Accept-Encoding") !~ /gzip/; + my $length = length($html); + $do_gzip = 0 if $length < 500; + if ($do_gzip) { + my $pre_len = $length; + $r->notes("bytes_pregzip" => $pre_len); + $html = Compress::Zlib::memGzip($html); + $length = length($html); + $r->header_out('Content-Encoding', 'gzip'); + $r->header_out('Vary', 'Accept-Encoding'); + } + $r->header_out('Content-length', $length); + + $r->send_http_header(); + } + + $r->print($html) unless $env->{'NoContent'} || $r->header_only; + + $Apache::BML::r = undef; # no longer valid + return OK; +} + +sub report_error +{ + my $r = shift; + my $err = shift; + + $r->content_type("text/html"); + $r->send_http_header(); + $r->print($err); + + return OK; # TODO: something else? +} + +sub file_dontcheck +{ + my $file = shift; + my $now = time; + return 1 if $FileLastStat{$file} > $now - 10; + my $realmod = (stat($file))[9]; + $FileLastStat{$file} = $now; + return 1 if $FileModTime{$file} && $realmod == $FileModTime{$file}; + $FileModTime{$file} = $realmod; + return 1 if ! $realmod; + return 0; +} + +sub load_conffile +{ + my ($ffile) = @_; # abs file to load + die "can't have dollar signs in filenames" if index($ffile, '$') != -1; + die "not absolute path" unless File::Spec->file_name_is_absolute($ffile); + my ($volume,$dirs,$file) = File::Spec->splitpath($ffile); + + # see which configs are denied + my $r = $Apache::BML::r; + if ($r->dir_config("BML_denyconfig") && ! %DenyConfig) { + my $docroot = $r->document_root(); + my $deny = $r->dir_config("BML_denyconfig"); + $deny =~ s/^\s+//; $deny =~ s/\s+$//; + my @denydir = split(/\s*\,\s*/, $deny); + foreach $deny (@denydir) { + $deny = dir_rel2abs($docroot, $deny); + $deny =~ s!/$!!; + $DenyConfig{"$deny/_config.bml"} = 1; + } + } + + return () if $DenyConfig{$ffile}; + + my $conf; + if (file_dontcheck($ffile) && ($FileConfig{$ffile} || ! $FileModTime{$ffile})) { + return () unless $FileModTime{$ffile}; # file doesn't exist + $conf = $FileConfig{$ffile}; + } + + if (!$conf && $file =~ /\.pl$/) { + return () unless -e $ffile; + my $conf = $conf_pl = {}; + do $ffile; + undef $conf_pl; + $FileConfig{$ffile} = $conf; + return ($ffile); + } + + unless ($conf) { + unless (open (C, $ffile)) { + Apache->log_error("Can't read config file: $file") + if -e $file; + return (); + } + + my $curr_sub; + $conf = {}; + my $sconf = $conf; + + my $save_config = sub { + return unless %$sconf; + + # expand $env vars and make paths absolute + foreach my $k (qw(LookRoot IncludePath)) { + next unless exists $sconf->{$k}; + $sconf->{$k} =~ s/\$(\w+)/$ENV{$1}/g; + $sconf->{$k} = dir_rel2abs($dirs, $sconf->{$k}); + } + + # same as above, but these can be multi-valued, and go into an arrayref + foreach my $k (qw(ExtraConfig)) { + next unless exists $sconf->{$k}; + $sconf->{$k} =~ s/\$(\w+)/$1 eq "HTTP_HOST" ? clean_http_host() : $ENV{$1}/eg; + $sconf->{$k} = [ map { dir_rel2abs($dirs, $_) } grep { $_ } + split(/\s*,\s*/, $sconf->{$k}) ]; + } + + # if child config, copy it to parent config + return unless $curr_sub; + foreach my $subdir (split(/\s*,\s*/, $curr_sub)) { + my $subfile = dir_rel2abs($dirs, "$subdir/_config.bml"); + $conf->{'SubConfig'}->{$subfile} = $sconf; + } + }; + + + while () { + chomp; + s/\#.*//; + next unless /(\S+)\s+(.+?)\s*$/; + my ($k, $v) = ($1, $2); + if ($k eq "SubConfig:") { + $save_config->(); + $curr_sub = $v; + $sconf = {%$sconf}; # clone config seen so far. SubConfig inherits those. + next; + } + + # automatically arrayref-ify certain options + $v = [ split(/\s*,\s*/, $v) ] + if $k eq "CookieDomain" && index($v,',') != -1; + + $sconf->{$k} = $v; + } + close C; + $save_config->(); + $FileConfig{$ffile} = $conf; + } + + my @files = ($ffile); + foreach my $cfile (@{$conf->{'ExtraConfig'} || []}) { + unshift @files, load_conffile($cfile); + } + + return @files; +} + +sub compile +{ + eval $_[0]; +} + +sub reset_codeblock +{ + my BML::Request $req = $Apache::BML::cur_req; + my $to_clean = $req->{clean_package}; + + no strict; + local $^W = 0; + my $package = "main::${to_clean}::"; + *stab = *{"main::"}; + while ($package =~ /(\w+?::)/g) + { + *stab = ${stab}{$1}; + } + while (my ($key,$val) = each(%stab)) + { + return if $DB::signal; + deleteglob ($key, $val); + } +} + +sub deleteglob +{ + no strict; + return if $DB::signal; + my ($key, $val, $all) = @_; + local(*entry) = $val; + my $fileno; + if ($key !~ /^_ +# $data - "Whatever" in the case of +# $option_ref - hash ref to %BMLEnv +sub bml_block +{ + my BML::Request $req = shift; + my ($type, $data, $option_ref, $elhash) = @_; + my $realtype = $type; + my $previous_block = $req->{'BlockStack'}->[-1]; + my $env = $req->{'env'}; + + # Bail out if we're over 200 frames deep + # :TODO: Make the max depth configurable? + if ( @{$req->{BlockStack}} > 200 ) { + my $stackSlice = join " -> ", @{$req->{BlockStack}}[0..10]; + return "[Error: Too deep recursion: $stackSlice]"; + } + + if (exists $req->{'blockref'}->{"$type/FOLLOW_${previous_block}"}) { + $realtype = "$type/FOLLOW_${previous_block}"; + } + + my $blockflags = $req->{'blockflags'}->{$realtype}; + + # executable perl code blocks + if ($type eq "_CODE") + { + return inline_error("_CODE block failed to execute by permission settings") + unless $option_ref->{'DO_CODE'}; + + %CodeBlockOpts = (); + + # this will be their package + my $md5_package = "BMLCodeBlock::" . Digest::MD5::md5_hex($req->{'file'}); + + # this will be their handler name + my $md5_handler = "handler_" . Digest::MD5::md5_hex($data); + + # we cache code blocks (of templates) also in each *.bml file's + # package, since we're too lazy (at the moment) to trace back + # each code block to its declaration file. + my $unique_key = $md5_package . $md5_handler; + + my $need_compile = ! $CodeBlockMade{$unique_key}; + + if ($need_compile) { + # compile (which just calls eval) then check for errors. + # we put it off to that sub, historically, to make it + # show up separate in profiling, but now we cache + # everything, so it pretty much never shows up. + compile(join('', + 'package ', + $md5_package, + ';', + "no strict;", + 'use vars qw(%ML %COOKIE %POST %GET %FORM);', + "*ML = *BML::ML;", + "*COOKIE = *BML::COOKIE;", + "*GET = *BMLCodeBlock::GET;", + "*POST = *BMLCodeBlock::POST;", + "*FORM = *BMLCodeBlock::FORM;", + 'sub ', $md5_handler, ' {', + $data, + "\n}")); + return "[Error: $@]" if $@; + + $CodeBlockMade{$unique_key} = 1; + } + + my $cv = \&{"${md5_package}::${md5_handler}"}; + $req->{clean_package} = $md5_package; + my $ret = eval { $cv->($req, $req->{'scratch'}, $elhash || {}) }; + if ($@) { + my $msg = $@; + if ($env->{'HOOK-codeerror'}) { + $ret = eval { + $env->{'HOOK-codeerror'}->($msg); + }; + return "[Error running codeerror hook]" if $@; + } else { + return "[Error: $msg]"; + } + } + + # don't call bml_decode if BML::noparse() told us not to, there's + # no data, or it looks like there are no BML tags + return $ret if $CodeBlockOpts{'raw'} or $ret eq "" or + (index($ret, " \@elements }); + } + elsif (index($blockflags, 'P') != -1) + { + my @itm = split(/\s*\|\s*/, $data); + my $ct = 0; + foreach (@itm) { + $ct++; + $element{"DATA$ct"} = $_; + push @elements, "DATA$ct"; + } + } + else + { + # single argument block (goes into DATA element) + $element{'DATA'} = $data; + push @elements, 'DATA'; + } + + # check built-in block types (those beginning with an underscore) + if (rindex($type, '_', 0) == 0) { + + # multi-linguality stuff + if ($type eq "_ML") + { + my $code = $data; + return $code + if $req->{'lang'} eq 'debug'; + my $getter = $req->{'env'}->{'HOOK-ml_getter'}; + return "[ml_getter not defined]" unless $getter; + $code = $req->{'r'}->uri . $code + if rindex($code, '.', 0) == 0; + return $getter->($req->{'lang'}, $code); + } + + # an _INFO block contains special internal information, like which + # look files to include + if ($type eq "_INFO") + { + if ($element{'PACKAGE'}) { $req->{'package'} = $element{'PACKAGE'}; } + if ($element{'NOCACHE'}) { $req->{'env'}->{'NoCache'} = 1; } + if ($element{'STATIC'}) { $req->{'env'}->{'Static'} = 1; } + if ($element{'NOHEADERS'}) { $req->{'env'}->{'NoHeaders'} = 1; } + if ($element{'NOCONTENT'}) { $req->{'env'}->{'NoContent'} = 1; } + if ($element{'LOCALBLOCKS'} && $req->{'env'}->{'AllowCode'}) { + my (%localblock, %localflags); + load_elements(\%localblock, $element{'LOCALBLOCKS'}); + # look for template types + foreach my $k (keys %localblock) { + if ($localblock{$k} =~ s/^\{([A-Za-z]+)\}//) { + $localflags{$k} = $1; + } + } + my @expandconstants; + foreach my $k (keys %localblock) { + $req->{'blockref'}->{$k} = \$localblock{$k}; + $req->{'blockflags'}->{$k} = $localflags{$k}; + if (index($localflags{$k}, 's') != -1) { push @expandconstants, $k; } + } + foreach my $k (@expandconstants) { + $localblock{$k} =~ s/$TokenOpen([a-zA-Z0-9\_]+?)$TokenClose/${$req->{'blockref'}->{uc($1)} || \""}/og; + } + } + return ""; + } + + if ($type eq "_INCLUDE") + { + my $code = 0; + $code = 1 if ($element{'CODE'}); + foreach my $sec (qw(CODE BML)) { + next unless $element{$sec}; + if ($req->{'IncludeStack'} && ! $req->{'IncludeStack'}->[-1]->{$sec}) { + return inline_error("Sub-include can't turn on $sec if parent include's $sec was off"); + } + } + unless ($element{'FILE'} =~ /^[a-zA-Z0-9-_\.]{1,255}$/) { + return inline_error("Invalid characters in include file name: $element{'FILE'} (code=$code)"); + } + + if ($req->{'IncludeOpen'}->{$element{'FILE'}}++) { + return inline_error("Recursion detected in includes"); + } + push @{$req->{'IncludeStack'}}, \%element; + my $isource = ""; + my $file = $element{'FILE'}; + + # first check if we have a DB-edit hook + my $hook = $req->{'env'}->{'HOOK-include_getter'}; + unless ($hook && $hook->($file, \$isource)) { + $file = $req->{'env'}->{'IncludePath'} . "/" . $file; + open (INCFILE, $file) || return inline_error("Could not open include file."); + { local $/ = undef; $isource = ; } + close INCFILE; + } + + if ($element{'BML'}) { + my $newhtml; + bml_decode($req, \$isource, \$newhtml, { DO_CODE => $code }); + $isource = $newhtml; + } + $req->{'IncludeOpen'}->{$element{'FILE'}}--; + pop @{$req->{'IncludeStack'}}; + return $isource; + } + + if ($type eq "_COMMENT" || $type eq "_C") { + return ""; + } + + if ($type eq "_EH") { + return BML::ehtml($element{'DATA'}); + } + + if ($type eq "_EB") { + return BML::ebml($element{'DATA'}); + } + + if ($type eq "_EU") { + return BML::eurl($element{'DATA'}); + } + + if ($type eq "_EA") { + return BML::eall($element{'DATA'}); + } + + return inline_error("Unknown core element '$type'"); + } + + $req->{'BlockStack'}->[-1] = $type; + + # traditional BML Block decoding ... properties of data get inserted + # into the look definition; then get BMLitized again + return inline_error("Undefined custom element '$type'") + unless defined $req->{'blockref'}->{$realtype}; + + my $preparsed = (index($blockflags, 'p') != -1); + + if ($preparsed) { + ## does block request pre-parsing of elements? + ## this is required for blocks with _CODE and AllowCode set to 0 + foreach my $k (@elements) { + my $decoded; + bml_decode($req, \$element{$k}, \$decoded, $option_ref, \%element); + $element{$k} = $decoded; + } + } + + # template has no variables or BML tags: + return ${$req->{'blockref'}->{$realtype}} if index($blockflags, 'S') != -1; + + my $expanded; + if ($preparsed) { + $expanded = ${$req->{'blockref'}->{$realtype}}; + } else { + $expanded = parsein(${$req->{'blockref'}->{$realtype}}, \%element); + } + + # {R} flag wants variable interpolation, but no expansion: + unless (index($blockflags, 'R') != -1) + { + my $out; + push @{$req->{'BlockStack'}}, ""; + my $opts = { %{$option_ref} }; + if ($preparsed) { + $opts->{'DO_CODE'} = $req->{'env'}->{'AllowTemplateCode'}; + } + + unless (index($expanded, "{'BlockStack'}}; + } + + $expanded = parsein($expanded, \%element) if $preparsed; + return $expanded; +} + +######## bml_decode +# +# turns BML source into expanded HTML source +# +# $inref scalar reference to BML source. $$inref gets destroyed. +# $outref scalar reference to where output is appended. +# $opts security flags +# $elhash optional elements hashref + +use vars qw(%re_decode); +sub bml_decode +{ + my BML::Request $req = shift; + my ($inref, $outref, $opts, $elhash) = @_; + + my $block = undef; # what are we in? + my $data = undef; # what is inside the current block? + my $depth = 0; # how many blocks we are deep of the *SAME* type. + my $re; # active regular expression for finding closing tag + + pos($$inref) = 0; + + EAT: + for (;;) + { + # currently not in a BML tag... looking for one! + if (! defined $block) { + if ($$inref =~ m/ + \G # start where last match left off + (?> # independent regexp: won't backtrack the .*? below. + (.*?) # $1 -> optional non-BML stuff before opening tag + $TokenOpen + (\w+) # $2 -> tag name + ) + (?: # CASE A: could be 1) immediate tag close, 2) tag close + # with data, or 3) slow path, below + ($TokenClose) | # A.1: $3 -> immediate tag close (depth 0) + (?: # A.2: simple close with data (data has no BML start tag of same tag) + ((?:.(?!$TokenOpen\2\b))+?) # $4 -> one or more chars without following opening BML tags + \b\2$TokenClose # matching closing tag + ) | + # A.3: final case: nothing, it's not the fast path. handle below. + ) # end case A + /gcosx) + { + $$outref .= $1; + $block = uc($2); + $data = $4 || ""; + + # fast path: immediate close or simple data (no opening BML). + if (defined $4 || $3) { + $$outref .= bml_block($req, $block, $data, $opts, $elhash); + return if $req->{'stop_flag'}; + $data = undef; + $block = undef; + next EAT; + } + + # slower (nesting) path. + # fast path (above) + # fast: ... foo?> + # slow (this path): ... foo?> + + $depth = 1; + + # prepare/find a cached regexp to continue using below + # continues below, finding an opening/close of existing tag + $re = $re_decode{$block} ||= + qr/($TokenClose) | # $1 -> immediate token closing + (?: + (.+?) # $2 -> non-BML part to push onto $data + (?: + ($TokenOpen$block\b) | # $3 -> increasing depth + (\b$block$TokenClose) # $4 -> decreasing depth + ) + )/isx; + + # falls through below. + + } else { + # no BML left? append it all and be done. + $$outref .= substr($$inref, pos($$inref)); + return; + } + } + + # continue with slow path. + + # the regexp prepared above looks out for these cases: (but not in + # this order) + # + # * Increasing depth: + # - some text, then another opening + # - closing the tag (if depth == 0, then we're done) + # + + if ($$inref =~ m/\G$re/gc) { + if ($1) { + # immediate close + $depth--; + $data .= $1 if $depth; # add closing token if we're still in another tag + } elsif ($3) { + # increasing depth of same block + $data .= $2; # data before opening bml tag + $data .= $3; # the opening tag itself + $depth++; + } elsif ($4) { + # decreasing depth of same block + $data .= $2; # data before closing tag + $depth--; + $data .= $4 if $depth; # add closing tag itself, if we're still in another tag + } + } else { + $$outref .= inline_error("BML block '$block' has no close"); + return; + } + + # handle finished blocks + if ($depth == 0) { + $$outref .= bml_block($req, $block, $data, $opts, $elhash); + return if $req->{'stop_flag'}; + $data = undef; + $block = undef; + } + } +} + +# takes a scalar with %%FIELDS%% mixed in and replaces +# them with their correct values from an anonymous hash, given +# by the second argument to this call +sub parsein +{ + my ($data, $hashref) = @_; + $data =~ s/%%(\w+)%%/$hashref->{uc($1)}/eg; + return $data; +} + +sub inline_error +{ + return "[Error: @_]"; +} + +# returns lower-cased, trimmed string +sub trim +{ + my $a = $_[0]; + $a =~ s/^\s*(.*?)\s*$/$1/s; + return $a; +} + +sub load_look_perl +{ + my ($file) = @_; + + $conf_pl_look = {}; + eval { do $file; }; + if ($@) { + print STDERR "Error evaluating BML block conf file $file: $@\n"; + return 0; + } + $LookItems{$file} = $conf_pl_look; + undef $conf_pl_look; + + return 1; +} + +sub load_look +{ + my $file = shift; + my BML::Request $req = shift; # optional + + my $dontcheck = file_dontcheck($file); + if ($dontcheck) { + return 0 unless $FileModTime{$file}; + note_mod_time($req, $FileModTime{$file}) if $req; + return 1; + } + note_mod_time($req, $FileModTime{$file}) if $req; + + if ($file =~ /\.pl$/) { + return load_look_perl($file); + } + + my $target = $LookItems{$file} = {}; + + foreach my $look ($file, keys %{$LookChild{$file}||{}}) { + delete $SchemeData->{$look}; + delete $SchemeFlags->{$look}; + } + + open (LOOK, $file); + my $look_file; + { local $/ = undef; $look_file = ; } + close LOOK; + load_elements($target, $look_file); + + # look for template types + while (my ($k, $v) = each %$target) { + if ($v =~ s/^\{([A-Za-z]+)\}//) { + $v = [ $v, $1 ]; + } else { + $v = [ $v ]; + } + $target->{$k} = $v; + } + + $LookParent{$file} = undef; + if ($target->{'_PARENT'}) { + my $parfile = file_rel2abs($file, $target->{'_PARENT'}->[0]); + if ($parfile && load_look($parfile)) { + $LookParent{$file} = $parfile; + $LookChild{$parfile}->{$file} = 1; + } + } + + return 1; +} + +# given a block of data, loads elements found into +sub load_elements +{ + my ($hashref, $data, $opts) = @_; + my $ol = $opts->{'declorder'}; + + my @lines = split(/\r?\n/, $data); + + while (@lines) { + my $line = shift @lines; + + # single line declaration: + # key=>value + if ($line =~ /^\s*(\w[\w\/]*)=>(.*)/) { + $hashref->{uc($1)} = $2; + push @$ol, uc($1); + next; + } + + # multi-line declaration: + # key<= + # line1 + # line2 + # <=key + if ($line =~ /^\s*(\w[\w\/]*)<=\s*$/) { + my $block = uc($1); + my $endblock = qr/^\s*<=$1\s*$/; + my $newblock = qr/^\s*$1<=\s*$/; + my $depth = 1; + my @out; + while (@lines) { + $line = shift @lines; + if ($line =~ /$newblock/) { + $depth++; + next; + } elsif ($line =~ /$endblock/) { + $depth--; + last unless $depth; + } + push @out, $line; + } + if ($depth == 0) { + $hashref->{$block} = join("\n", @out) . "\n"; + push @$ol, $block; + } + } + + } # end while (@lines) +} + +# given a file, checks it's modification time and sees if it's +# newer than anything else that compiles into what is the document +sub note_file_mod_time +{ + my ($req, $file) = @_; + note_mod_time($req, (stat($file))[9]); +} + +sub note_mod_time +{ + my BML::Request $req = shift; + my $mod_time = shift; + + if ($req) { + if ($mod_time > $req->{'most_recent_mod'}) { + $req->{'most_recent_mod'} = $mod_time; + } + } else { + if ($mod_time > $Apache::BML::base_recent_mod) { + $Apache::BML::base_recent_mod = $mod_time; + } + } +} + +# formatting +sub modified_time +{ + my BML::Request $req = shift; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($req->{'most_recent_mod'}); + my @day = qw{Sun Mon Tue Wed Thu Fri Sat}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + if ($year < 1900) { $year += 1900; } + + return sprintf("$day[$wday], %02d $month[$mon] $year %02d:%02d:%02d GMT", + $mday, $hour, $min, $sec); +} + +# both Cwd and File::Spec suck. they're portable, but they suck. +# these suck too (slow), but they do what i want. + +sub dir_rel2abs { + my ($dir, $rel) = @_; + return $rel if $rel =~ m!^/!; + my @dir = grep { $_ ne "" } split(m!/!, $dir); + my @rel = grep { $_ ne "" } split(m!/!, $rel); + while (@rel) { + $_ = shift @rel; + next if $_ eq "."; + if ($_ eq "..") { pop @dir; next; } + push @dir, $_; + } + return join('/', '', @dir); +} + +sub file_rel2abs { + my ($file, $rel) = @_; + return $rel if $rel =~ m!^/!; + $file =~ s!(.+/).*!$1!; + return dir_rel2abs($file, $rel); +} + +package BML; + +# returns false if remote browser can't handle the HttpOnly cookie atttribute +# (Microsoft extension to make cookies unavailable to scripts) +# it renders cookies useless on some browsers. by default, returns true. +sub http_only +{ + my $ua = BML::get_client_header("User-Agent"); + return 0 if $ua =~ /MSIE.+Mac_/; + return 1; +} + +sub fill_template +{ + my ($name, $vars) = @_; + return Apache::BML::parsein(${$Apache::BML::cur_req->{'blockref'}->{uc($name)}}, + $vars); +} + +sub get_scheme +{ + return $Apache::BML::cur_req->{'scheme'}; +} + +sub set_scheme +{ + my BML::Request $req = $Apache::BML::cur_req; + my $scheme = shift; + return 0 if $scheme =~ /\W/; + unless ($scheme) { + $scheme = $req->{'env'}->{'ForceScheme'} || + $req->{'env'}->{'DefaultScheme'}; + } + + my $file = "$req->{env}{LookRoot}/$scheme.look"; + + return 0 unless Apache::BML::load_look($file); + + $req->{'scheme'} = $scheme; + $req->{'scheme_file'} = $file; + + # now we have to combine both of these (along with the VARINIT) + # and then expand all the static stuff + unless (exists $SchemeData->{$file}) { + my $iter = $file; + my @files; + while ($iter) { + unshift @files, $iter; + $iter = $Apache::BML::LookParent{$iter}; + } + + my $sd = $SchemeData->{$file} = {}; + my $sf = $SchemeFlags->{$file} = {}; + + foreach my $file (@files) { + while (my ($k, $v) = each %{$Apache::BML::LookItems{$file}}) { + $sd->{$k} = $v->[0]; + $sf->{$k} = $v->[1]; + } + } + foreach my $k (keys %$sd) { + next unless index($sf->{$k}, 's') != -1; + $sd->{$k} =~ s/$TokenOpen([a-zA-Z0-9\_]+?)$TokenClose/$sd->{uc($1)}/og; + } + } + + # now, this request needs a copy of (well, references to) the + # data above. can't use that directly, since it might + # change using _INFO LOCALBLOCKS to declare new file-local blocks + $req->{'blockflags'} = { + '_INFO' => 'F', '_INCLUDE' => 'F', + }; + $req->{'blockref'} = {}; + foreach my $k (keys %{$SchemeData->{$file}}) { + $req->{'blockflags'}->{$k} = $SchemeFlags->{$file}->{$k}; + $req->{'blockref'}->{$k} = \$SchemeData->{$file}->{$k}; + } + + return 1; +} + +sub set_etag +{ + my $etag = shift; + $Apache::BML::cur_req->{'etag'} = $etag; +} + +# when CODE blocks need to look-up static values and such +sub get_template_def +{ + my $blockname = shift; + my $schemefile = $Apache::BML::cur_req->{'scheme_file'}; + return $SchemeData->{$schemefile}->{uc($blockname)}; +} + +sub parse_multipart +{ + my ($dest, $error, $max_size) = @_; + my $r = $Apache::BML::r; + my $err = sub { $$error = $_[0]; return 0; }; + + my $size = $r->header_in("Content-length"); + unless ($size) { + return $err->("No content-length header: can't parse"); + } + if ($max_size && $size > $max_size) { + return $err->("[toolarge] Upload too large"); + } + + my $sep; + unless ($r->header_in("Content-Type") =~ m!^multipart/form-data;\s*boundary=(\S+)!) { + return $err->("[unknowntype] Unknown content type"); + } + $sep = $1; + + my $content; + $r->read($content, $size); + my @lines = split(/\r\n/, $content); + my $line = shift @lines; + return $err->("[parse] Error parsing upload") unless $line eq "--$sep"; + + while (@lines) { + $line = shift @lines; + my %h; + while (defined $line && $line ne "") { + $line =~ /^(\S+?):\s*(.+)/; + $h{lc($1)} = $2; + $line = shift @lines; + } + while (defined $line && $line ne "--$sep") { + last if $line eq "--$sep--"; + $h{'body'} .= "\r\n" if $h{'body'}; + $h{'body'} .= $line; + $line = shift @lines; + } + if ($h{'content-disposition'} =~ /name="(\S+?)"/) { + my $name = $1 || $2; + $dest->{$name} = $h{'body'}; + } + } + + return 1; +} + +# FIXME: document the hooks +sub parse_multipart_interactive { + my ($r, $errref, $hooks) = @_; + + # subref to set $@ and $$errref, then return false + my $err = sub { $$errref = $@ = $_[0], return 0 }; + + my $run_hook = sub { + my $name = shift; + my $ret = eval { $hooks->{$name}->(@_) }; + if ($@) { + return $err->($@); + } + unless ($ret) { + return $err->("Hook: '$name' returned false"); + } + return 1; + }; + + # size hook is optional + my $size = $r->header_in("Content-length"); + if ($hooks->{size}) { + $run_hook->('size', $size) + or return 0; + } + + unless ($r->header_in("Content-Type") =~ m!^multipart/form-data;\s*boundary=(\S+)!) { + return $err->("No MIME boundary. Bogus Content-type? " . $r->header_in("Content-Type")); + } + my $sep = "--$1"; + my $seplen = length($sep) + 2; # plus \r\n + + my $window = ''; + my $to_read = $size; + my $max_read = 8192; + + my $seen_chunk = 0; # have we seen any chunk yet? + + my $state = 0; # what we last parsed + # 0 = nothing (looking for a separator) + # 1 = separator (looking for headers) + # 0 = headers (looking for data) + # 0 = data (looking for a separator) + + while (1) { + my $read = -1; + if ($to_read) { + $read = $r->read($window, + $to_read < $max_read ? $to_read : $max_read, + length($window)); + $to_read -= $read; + + # prevent loops. Opera, in particular, alerted us to + # this bug, since it doesn't upload proper MIME on + # reload and its Content-Length header is correct, + # but its body tiny + if ($read == 0) { + return $err->("No data from client. Possibly a refresh?"); + } + } + + # starting case, or data-reading case (looking for separator) + if ($state == 0) { + my $idx = index($window, $sep); + + # didn't find a separator. emit the previous data + # which we know for sure is data and not a possible + # new separator + if ($idx == -1) { + # bogus if we're done reading and didn't find what we're + # looking for: + if ($read == -1) { + return $err->("Couldn't find separator, no more data to read"); + } + + if ($seen_chunk) { + + # data hook is required + my $len = length($window) - $seplen; + $run_hook->('data', $len, substr($window, 0, $len, '')) + or return 0; + } + next; + } + + # we found a separator. emit the previous read's + # data and enddata. + if ($seen_chunk) { + my $len = $idx - 2; + if ($len > 0) { + + # data hook is required + $run_hook->('data', $len, substr($window, 0, $len)) + or return 0; + } + + # enddata hook is required + substr($window, 0, $idx, ''); + $run_hook->('enddata') + or return 0; + } + + # we're now looking for a header + $seen_chunk = 1; + $state = 1; + + # have we hit the end? + return 1 if $to_read <= 2 && length($window) <= $seplen + 4; + } + + # read a separator, looking for headers + if ($state == 1) { + my $idx = index($window, "\r\n\r\n"); + if ($idx == -1) { + if (length($window) > 8192) { + return $err->("Window too large: " . length($window) . " bytes > 8192"); + } + + # bogus if we're done reading and didn't find what we're + # looking for: + if ($read == -1) { + return $err->("Couldn't find headers, no more data to read"); + } + + next; + } + + # +4 is \r\n\r\n + my $header = substr($window, 0, $idx+4, ''); + my @lines = split(/\r\n/, $header); + + my %hdval; + my $lasthd; + foreach (@lines) { + if (/^(\S+?):\s*(.+)/) { + $lasthd = lc($1); + $hdval{$lasthd} = $2; + } elsif (/^\s+.+/) { + $hdval{$lasthd} .= $&; + } + } + + my ($name, $filename); + if ($hdval{'content-disposition'} =~ /\bNAME=\"(.+?)\"/i) { + $name = $1; + } + if ($hdval{'content-disposition'} =~ /\bFILENAME=\"(.+?)\"/i) { + $filename = $1; + } + + # newheaders hook is required + $run_hook->('newheaders', $name, $filename) + or return 0; + + $state = 0; + } + + } + return 1; +} + + +sub reset_cookies +{ + %BML::COOKIE_R = (); + %BML::COOKIE_M = (); + $BML::COOKIES_PARSED = 0; +} + +sub set_config +{ + my ($key, $val) = @_; + die "BML::set_config called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{$key} ||= $val; + #$Apache::BML::config->{$path}->{$key} = $val; +} + +sub noparse +{ + $Apache::BML::CodeBlockOpts{'raw'} = 1; + return $_[0]; +} + +sub decide_language +{ + my BML::Request $req = $Apache::BML::cur_req; + my $env = $req->{'env'}; + + # GET param 'uselang' takes priority + my $uselang = $BMLCodeBlock::GET{'uselang'}; + if (exists $env->{"Langs-$uselang"} || $uselang eq "debug") { + return $uselang; + } + + # next is their cookie preference + if ($BML::COOKIE{'langpref'} =~ m!^(\w{2,10})/(\d+)$!) { + if (exists $env->{"Langs-$1"}) { + # make sure the document says it was changed at least as new as when + # the user last set their current language, else their browser might + # show a cached (wrong language) version. + note_mod_time($req, $2); + return $1; + } + } + + # next is their browser's preference + my %lang_weight = (); + my @langs = split(/\s*,\s*/, lc($req->{'r'}->header_in("Accept-Language"))); + my $winner_weight = 0.0; + my $winner; + foreach (@langs) + { + # do something smarter in future. for now, ditch country code: + s/-\w+//; + + if (/(.+);q=(.+)/) { + $lang_weight{$1} = $2; + } else { + $lang_weight{$_} = 1.0; + } + if ($lang_weight{$_} > $winner_weight && defined $env->{"ISOCode-$_"}) { + $winner_weight = $lang_weight{$_}; + $winner = $env->{"ISOCode-$_"}; + } + } + return $winner if $winner; + + # next is the default language + return $req->{'env'}->{'DefaultLanguage'} if $req->{'env'}->{'DefaultLanguage'}; + + # lastly, english. + return "en"; +} + +sub register_language +{ + my ($langcode) = @_; + die "BML::register_language called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"Langs-$langcode"} ||= 1; +} + +sub register_isocode +{ + my ($isocode, $langcode) = @_; + next unless $isocode =~ /^\w{2,2}$/; + die "BML::register_isocode called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"ISOCode-$isocode"} ||= $langcode; +} + +# get/set the flag to send the Last-Modified header +sub want_last_modified +{ + $Apache::BML::cur_req->{'want_last_modified'} = $_[0] + if defined $_[0]; + return $Apache::BML::cur_req->{'want_last_modified'}; +} + +sub note_mod_time +{ + my $mod_time = shift; + Apache::BML::note_mod_time($Apache::BML::cur_req, $mod_time); +} + +sub redirect +{ + my $url = shift; + $Apache::BML::cur_req->{'location'} = $url; + finish_suppress_all(); + return; +} + +sub do_later +{ + my $subref = shift; + return 0 unless ref $subref eq "CODE"; + $Apache::BML::cur_req->{'r'}->register_cleanup($subref); + return 1; +} + +sub register_block +{ + my ($type, $flags, $def) = @_; + my $target = $Apache::BML::conf_pl_look; + die "BML::register_block called from non-lookfile context.\n" unless $target; + $type = uc($type); + + $target->{$type} = [ $def, $flags ]; + return 1; +} + +sub register_hook +{ + my ($name, $code) = @_; + die "BML::register_hook called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"HOOK-$name"} = $code; +} + +sub get_request +{ + # we do this, and not use $Apache::BML::r directly because some non-BML + # callers sometimes use %BML::COOKIE, so $Apache::BML::r isn't set. + # the cookie FETCH below calls this function to try and use Apache->request, + # else fall back to the global one (for use in profiling/debugging) + my $r; + eval { + $r = Apache->request; + }; + $r ||= $Apache::BML::r; + return $r; +} + +sub get_query_string +{ + return scalar($Apache::BML::r->args); +} + +sub get_uri +{ + return $Apache::BML::r->uri; +} + +sub get_method +{ + return $Apache::BML::r->method; +} + +sub get_path_info +{ + return $Apache::BML::r->path_info; +} + +sub get_remote_ip +{ + return $Apache::BML::r->connection()->remote_ip; +} + +sub get_remote_host +{ + return $Apache::BML::r->connection()->remote_host; +} + +sub get_remote_user +{ + return $Apache::BML::r->connection()->user; +} + +sub get_client_header +{ + my $hdr = shift; + return $Apache::BML::r->header_in($hdr); +} + +# +# class: web +# name: BML::self_link +# des: Takes the URI of the current page, and adds the current form data +# to the url, then adds any additional data to the url. +# returns: scalar; the full url +# args: newvars +# des-newvars: A hashref of information to add/override to the link. +# +sub self_link +{ + my $newvars = shift; + my $link = $Apache::BML::r->uri; + my $form = \%BMLCodeBlock::FORM; + + $link .= "?"; + foreach (keys %$newvars) { + if (! exists $form->{$_}) { $form->{$_} = ""; } + } + foreach (sort keys %$form) { + if (defined $newvars->{$_} && ! $newvars->{$_}) { next; } + my $val = $newvars->{$_} || $form->{$_}; + next unless $val; + $link .= BML::eurl($_) . "=" . BML::eurl($val) . "&"; + } + chop $link; + return $link; +} + +sub http_response +{ + my ($code, $msg) = @_; + + my $r = $Apache::BML::r; + $r->status($code); + $r->content_type('text/html'); + $r->print($msg); + finish_suppress_all(); + return; +} + +sub finish_suppress_all +{ + finish(); + suppress_headers(); + suppress_content(); +} + +sub suppress_headers +{ + # set any cookies that we have outstanding + send_cookies(); + $Apache::BML::cur_req->{'env'}->{'NoHeaders'} = 1; +} + +sub suppress_content +{ + $Apache::BML::cur_req->{'env'}->{'NoContent'} = 1; +} + +sub finish +{ + $Apache::BML::cur_req->{'stop_flag'} = 1; +} + +sub set_content_type +{ + $Apache::BML::cur_req->{'content_type'} = $_[0] if $_[0]; +} + +# +# class: web +# name: BML::set_status +# des: Takes a number to indicate a status (e.g. 404, 403, 410, 500, etc) and sets +# that to be returned to the client when the request finishes. +# returns: nothing +# args: status +# des-newvars: A number representing the status to return to the client. +# +sub set_status +{ + $Apache::BML::r->status($_[0]+0) if $_[0]; +} + +sub eall +{ + return ebml(ehtml($_[0])); +} + + +# escape html +sub ehtml +{ + my $a = $_[0]; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +sub ebml +{ + my $a = $_[0]; + my $ra = ref $a ? $a : \$a; + $$ra =~ s/\(=(\w)/\(= $1/g; # remove this eventually (old syntax) + $$ra =~ s/(\w)=\)/$1 =\)/g; # remove this eventually (old syntax) + $$ra =~ s/<\?/<?/g; + $$ra =~ s/\?>/?>/g; + return if ref $a; + return $a; +} + +sub get_language +{ + return $Apache::BML::cur_req->{'lang'}; +} + +sub get_language_default +{ + return $Apache::BML::cur_req->{'env'}->{'DefaultLanguage'} || "en"; +} + +sub set_language_scope { + $BML::ML_SCOPE = shift; +} + +sub set_language +{ + my ($lang, $getter) = @_; # getter is optional + my BML::Request $req = $Apache::BML::cur_req; + my $r = BML::get_request(); + $r->notes('langpref' => $lang); + + # don't rely on $req (the current BML request) being defined, as + # we allow callers to use this interface directly from non-BML + # requests. + if ($req) { + $req->{'lang'} = $lang; + $getter ||= $req->{'env'}->{'HOOK-ml_getter'}; + } + + no strict 'refs'; + if ($lang eq "debug") { + *{"BML::ml"} = sub { + return $_[0]; + }; + *{"BML::ML::FETCH"} = sub { + return $_[1]; + }; + } elsif ($getter) { + *{"BML::ml"} = sub { + my ($code, $vars) = @_; + $code = $BML::ML_SCOPE . $code + if rindex($code, '.', 0) == 0; + return $getter->($lang, $code, undef, $vars); + }; + *{"BML::ML::FETCH"} = sub { + my $code = $_[1]; + $code = $BML::ML_SCOPE . $code + if rindex($code, '.', 0) == 0; + return $getter->($lang, $code); + }; + }; + +} + +# multi-lang string +# note: sub is changed when BML::set_language is called +sub ml +{ + return "[ml_getter not defined]"; +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +sub randlist +{ + my @rlist = @_; + my $size = scalar(@rlist); + + my $i; + for ($i=0; $i<$size; $i++) + { + unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1); + } + return @rlist; +} + +sub page_newurl +{ + my $page = $_[0]; + my @pair = (); + foreach (sort grep { $_ ne "page" } keys %BMLCodeBlock::FORM) + { + push @pair, (eurl($_) . "=" . eurl($BMLCodeBlock::FORM{$_})); + } + push @pair, "page=$page"; + return $Apache::BML::r->uri . "?" . join("&", @pair); +} + +sub paging +{ + my ($listref, $page, $pagesize) = @_; + $page = 1 unless ($page && $page==int($page)); + my %self; + + $self{'itemcount'} = scalar(@{$listref}); + + $self{'pages'} = $self{'itemcount'} / $pagesize; + $self{'pages'} = $self{'pages'}==int($self{'pages'}) ? $self{'pages'} : (int($self{'pages'})+1); + + $page = 1 if $page < 1; + $page = $self{'pages'} if $page > $self{'pages'}; + $self{'page'} = $page; + + $self{'itemfirst'} = $pagesize * ($page-1) + 1; + $self{'itemlast'} = $self{'pages'}==$page ? $self{'itemcount'} : ($pagesize * $page); + + $self{'items'} = [ @{$listref}[($self{'itemfirst'}-1)..($self{'itemlast'}-1)] ]; + + unless ($page==1) { $self{'backlink'} = "<<<"; } + unless ($page==$self{'pages'}) { $self{'nextlink'} = ">>>"; } + + return %self; +} + +sub send_cookies { + my $req = shift() || $Apache::BML::cur_req; + foreach (values %{$req->{'cookies'}}) { + $req->{'r'}->err_headers_out->add("Set-Cookie" => $_); + } + $req->{'cookies'} = {}; + $req->{'env'}->{'SentCookies'} = 1; +} + +# $expires = 0 to expire when browser closes +# $expires = undef to delete cookie +sub set_cookie +{ + my ($name, $value, $expires, $path, $domain, $http_only) = @_; + + my BML::Request $req = $Apache::BML::cur_req; + my $e = $req->{'env'}; + $path = $e->{'CookiePath'} unless defined $path; + $domain = $e->{'CookieDomain'} unless defined $domain; + + # let the domain argument be an array ref, so callers can set + # cookies in both .foo.com and foo.com, for some broken old browsers. + if ($domain && ref $domain eq "ARRAY") { + foreach (@$domain) { + set_cookie($name, $value, $expires, $path, $_, $http_only); + } + return; + } + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($expires); + $year+=1900; + + my @day = qw{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + my $cookie = eurl($name) . "=" . eurl($value); + + # this logic is confusing potentially + unless (defined $expires && $expires==0) { + $cookie .= sprintf("; expires=$day[$wday], %02d-$month[$mon]-%04d %02d:%02d:%02d GMT", + $mday, $year, $hour, $min, $sec); + } + $cookie .= "; path=$path" if $path; + $cookie .= "; domain=$domain" if $domain; + $cookie .= "; HttpOnly" if $http_only && BML::http_only(); + + # send a cookie directly or cache it for sending later? + if ($e->{'SentCookies'}) { + $req->{'r'}->err_headers_out->add("Set-Cookie" => $cookie); + } else { + $req->{'cookies'}->{"$name:$domain"} = $cookie; + } + + if (defined $expires) { + $BML::COOKIE_R{$name} = $value; + } else { + delete $BML::COOKIE_R{$name}; + } +} + +# cookie support +package BML::Cookie; + +sub TIEHASH { + my $class = shift; + my $self = {}; + bless $self; + return $self; +} + +sub FETCH { + my ($t, $key) = @_; + # we do this, and not use $Apache::BML::r directly because some non-BML + # callers sometimes use %BML::COOKIE. + my $r = BML::get_request(); + unless ($BML::COOKIES_PARSED) { + foreach (split(/;\s+/, $r->header_in("Cookie"))) { + next unless ($_ =~ /(.*)=(.*)/); + my ($name, $value) = ($1, $2); + + # if the cookie already exists, we'll take the existing value as + # well as all new ones, and push them onto an arrayref in COOKIE_M + if (exists $BML::COOKIE_R{$name}) { + push @{$BML::COOKIE_M{$name}}, $BML::COOKIE_R{$name} + unless ref $BML::COOKIE_M{$name}; + + push @{$BML::COOKIE_M{$name}}, $value; + } + + $BML::COOKIE_R{BML::durl($name)} = BML::durl($value); + } + $BML::COOKIES_PARSED = 1; + } + + # return scalar value, or arrayref if key has [] appended + return $key =~ s/\[\]$// ? + $BML::COOKIE_M{$key} || [$BML::COOKIE_R{$key}] : $BML::COOKIE_R{$key}; +} + +sub STORE { + my ($t, $key, $val) = @_; + my $etime = 0; + my $http_only = 0; + ($val, $etime, $http_only) = @$val if ref $val eq "ARRAY"; + $etime = undef unless $val ne ""; + BML::set_cookie($key, $val, $etime, undef, undef, $http_only); +} + +sub DELETE { + my ($t, $key) = @_; + STORE($t, $key, undef); +} + +sub CLEAR { + my ($t) = @_; + foreach (keys %BML::COOKIE_R) { + STORE($t, $_, undef); + } +} + +sub EXISTS { + my ($t, $key) = @_; + return defined $BML::COOKIE_R{$key}; +} + +sub FIRSTKEY { + my ($t) = @_; + keys %BML::COOKIE_R; + return each %BML::COOKIE_R; +} + +sub NEXTKEY { + my ($t, $key) = @_; + return each %BML::COOKIE_R; +} + +# provide %BML::ML & %BMLCodeBlock::ML support: +package BML::ML; + +sub TIEHASH { + my $class = shift; + my $self = {}; + bless $self; + return $self; +} + +# note: sub is changed when BML::set_language is called. +sub FETCH { + return "[ml_getter not defined]"; +} + +# do nothing +sub CLEAR { } + +1; + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/bml/t/00_require.t b/bml/t/00_require.t new file mode 100755 index 0000000..24ccdb1 --- /dev/null +++ b/bml/t/00_require.t @@ -0,0 +1,40 @@ +#!/usr/bin/perl +# +# Test script for Apache::BML +# $Id: 00_require.t,v 1.1 2004/05/26 17:33:51 deveiant Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl 00_require.t' +# +# Please do not commit any changes you make to the module without a +# successful 'make test'! +# +package main; +use strict; + +BEGIN { $| = 1; } + +### Load up the test framework +use Test::SimpleUnit qw{:functions}; + +my ( + $manifest, + @modules, + @testSuite, + ); + +# Read the manifest and grok the list of modules out of it +$manifest = IO::File->new( "MANIFEST", "r" ) + or die "open: MANIFEST: $!"; +@modules = map { s{lib/(.+)\.pm$}{$1}; s{/}{::}g; $_ } grep { m{\.pm$} } $manifest->getlines; +chomp @modules; + +### Test suite (in the order they're run) +@testSuite = map { + { + name => "require ${_}", + test => eval qq{sub { assertNoException {require $_}; }}, + } +} @modules; + +runTests( @testSuite ); diff --git a/bml/t/10_simple.t b/bml/t/10_simple.t new file mode 100755 index 0000000..6a3a273 --- /dev/null +++ b/bml/t/10_simple.t @@ -0,0 +1,210 @@ +#!/usr/bin/perl +# +# Test script for Apache::BML -- Simple functions +# $Id: 10_simple.t,v 1.1 2004/05/26 17:33:51 deveiant Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl 00_require.t' +# +# Please do not commit any changes you make to the module without a +# successful 'make test'! +# +package main; +use strict; + +BEGIN { $| = 1; } + +### Load up the test framework +use Test::SimpleUnit qw{:functions}; +use Apache::BML qw{}; +use Apache::FakeRequest qw{}; +use Fcntl qw{O_CREAT O_TRUNC O_EXCL O_WRONLY}; +use File::Spec qw{}; + +my ( + @testSuite, + $Output, + $Errout, + $Pnotes, + $Request, + $DataPath, + $NonExistantFile, + $ForbiddenFile, + $ForbiddenConfigFile, + $EmptyFile, + ); + +$Pnotes = {}; +$Output = ''; +$Errout = ''; + +$DataPath = File::Spec->rel2abs( "test" ); +$NonExistantFile = "$DataPath/nonexistant.bml"; +$ForbiddenFile = "$DataPath/forbidden.bml"; +$ForbiddenConfigFile = "$DataPath/_config.bml"; +$EmptyFile = "$DataPath/empty.bml"; + + +# Overload Apache::FakeRequest's print to append output to a variable. +{ + no warnings 'redefine'; + *Apache::FakeRequest::print = sub { + my $r = shift; + $Output .= join('', @_) + }; + *Apache::FakeRequest::log_error = sub { + my $r - shift; + print STDERR @_, "\n"; $Errout .= join('', @_) + }; + *Apache::FakeRequest::pnotes = sub { + my ( $r, $key ) = @_; + return $Pnotes if !$key; + $Pnotes->{ $key } = shift if @_; + $Pnotes->{ $key }; + }; +} + + +# Define tests +@testSuite = ( + + { + name => 'setup', + func => sub { + $Output = ''; + $Errout = ''; + $Pnotes = {}; + }, + }, + + # Calling handler() with no args should error + { + name => 'No Args', + test => sub { + assertException { + Apache::BML::handler(); + }; + }, + }, + + + # Calling with a non-existant file should 404 + { + name => "Non-existant file", + test => sub { + my $request = new Apache::FakeRequest ( + filename => $NonExistantFile, + ); + my $res; + + assertNoException { + $res = Apache::BML::handler( $request ); + }; + + assertEquals( 404, $res ); + assertMatches( /does not exist/, $Errout ); + }, + }, + + { + name => 'teardown', + func => sub { + if ( -e $ForbiddenFile ) { + unlink $ForbiddenFile or die "unlink: $ForbiddenFile: $!"; + } + }, + }, + + # Calling with a file for which we have no permissions should 403 + { + name => "Non-readable file", + test => sub { + # Create an unreadable file + my $fh = new IO::File $ForbiddenFile, O_CREAT|O_WRONLY + or die "open: $ForbiddenFile: $!"; + close $fh; + chmod 0220, $ForbiddenFile + or die "chmod: $ForbiddenFile: $!"; + + my $request = new Apache::FakeRequest ( + filename => $ForbiddenFile, + ); + my $res; + + assertNoException { + $res = Apache::BML::handler( $request ); + }; + + assertEquals( 403, $res ); + assertMatches( /File permissions deny access/, $Errout ); + }, + }, + + { + name => 'teardown', + func => sub { + if ( -e $ForbiddenConfigFile ) { + unlink $ForbiddenConfigFile or die "unlink: $ForbiddenConfigFile: $!"; + } + }, + }, + + # _config files are forbidden + { + name => "Forbidden _config file", + test => sub { + # Create a readable _config file + my $fh = new IO::File $ForbiddenConfigFile, O_CREAT|O_WRONLY + or die "open: $ForbiddenConfigFile: $!"; + $fh->print(""); + close $fh; + + my $request = new Apache::FakeRequest ( + filename => $ForbiddenConfigFile, + ); + my $res; + + assertNoException { + $res = Apache::BML::handler( $request ); + }; + + assertEquals( 403, $res ); + }, + }, + + + { + name => 'teardown', + func => sub { + if ( -e $EmptyFile ) { + unlink $EmptyFile or die "unlink: $EmptyFile: $!"; + } + }, + }, + + + # Loading an empty file should be okay + { + name => "Empty file", + test => sub { + # Create an unreadable file + my $fh = new IO::File $EmptyFile, O_CREAT|O_WRONLY + or die "open: $EmptyFile: $!"; + $fh->print(""); + close $fh; + + my $request = new Apache::FakeRequest ( + filename => $EmptyFile, + ); + my $res; + + assertNoException { $res = Apache::BML::handler($request) }; + assertEquals 0, $res; + assertEquals '', $Output; + }, + } + + +); + +runTests( @testSuite ); diff --git a/bml/t/20_render.t b/bml/t/20_render.t new file mode 100755 index 0000000..77b08ec --- /dev/null +++ b/bml/t/20_render.t @@ -0,0 +1,185 @@ +#!/usr/bin/perl +# +# Test script for Apache::BML -- Simple functions +# $Id: 20_render.t,v 1.3 2004/07/03 00:13:26 deveiant Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl 00_require.t' +# +# Please do not commit any changes you make to the module without a +# successful 'make test'! +# +package main; +use strict; + +BEGIN { $| = 1; } + +use lib "lib"; + +### Load up the test framework +use Test::SimpleUnit qw{:functions}; +use Apache::BML qw{}; +use Apache::FakeRequest qw{}; +use Fcntl qw{O_CREAT O_TRUNC O_EXCL O_RDONLY O_WRONLY}; +use File::Spec qw{}; +use File::Basename qw{dirname basename}; +use Text::Diff qw{diff}; + + +##################################################################### +### G L O B A L V A R I A B L E S +##################################################################### +my ( + @testSuite, + $Request, + $TestDir, + @TestSubdirs, + ); + +$TestDir = File::Spec->rel2abs( "test" ); + +# The list of directories to search for .bml files. This is hard-coded instead +# of automatic so other tests can use the test/ directory for their data, too. +@TestSubdirs = qw[ tutorial1 tutorial2 brads recursion syntax-errors + codeblocks fake_root comments info escape include + tutorial-example* + ]; + + +##################################################################### +### C U S T O M A S S E R T I O N F U N C T I O N S +##################################################################### + +### FUNCTION: readFile( $file ) +### Read the specified I and return its contents as a single scalar. +sub readFile { + my ( $file ) = @_; + + my $fh = new IO::File $file, O_RDONLY + or die "open: $file: $!"; + return join '', $fh->getlines; +} + + +### FUNCTION: assertCorrect( $directory, $name, $output ) +### Load the "I.correct" file from the specified testing I and +### check that it is the same as the specified I after stripping off +### trailing whitespace from both. +sub assertCorrect { + my ( $dir, $name, $output ) = @_; + + my $path = File::Spec->catfile( $dir, "$name.correct" ); + if ( ! -e $path ) { + print "\n>>> WARNING: No .correct file for '$name': Creating one with \n", + ">>> the test output. You should verify the correctness of \n", + ">>> '$path' before trusting this test.\n\n"; + IO::File->new($path, O_WRONLY|O_CREAT)->print( $output ); + } + + my $correct = readFile( $path ); + + # Trim trailing whitespace off of both expected and correct + $correct =~ s{\s+$}{}; $correct .= "\n"; + $output =~ s{\s+$}{}; $output .= "\n"; + + my $diff = diff( \$correct, \$output ); + assert( $diff eq '', "Expected output from $name.correct, got:\n$diff" ); +} + + +##################################################################### +### A P A C H E : : F A K E R E Q U E S T M U N G I N G +##################################################################### + +# Overload Apache::FakeRequest's print to append output to a variable. +{ + package Apache::FakeRequest; + use vars qw{%Pnotes $Output $Errout}; + no warnings 'redefine'; + + %Pnotes = (); + $Output = $Errout = ''; + + sub Reset { + %Pnotes = (); + $Output = $Errout = ''; + } + + sub print { + my $r = shift; + $Output .= join('', @_) + } + sub log_error { + my $r - shift; + print STDERR @_, "\n"; $Errout .= join('', @_) + } + sub pnotes { + my ( $r, $key ) = @_; + $Pnotes{ $key } = shift if @_; + return $Pnotes{ $key }; + } + +} + + + +##################################################################### +### T E S T S +##################################################################### + +# Define tests +@testSuite = ( + + { + name => 'setup', + func => sub { + Apache::FakeRequest->Reset; + }, + }, + +); + +# Auto-generate tests for each test subdir +foreach my $subdir ( @TestSubdirs ) { + my $testpat = File::Spec->catdir( $TestDir, $subdir ); + + # Find all the .bml files, skipping those which start with underscores. + foreach my $bmlfile ( glob "$testpat/*.bml" ) { + next if $bmlfile =~ m{/_}; + ( my $name = $bmlfile ) =~ s{.*/(.*)\.bml$}{$1}; + my $testdir = dirname( $bmlfile ); + my $testname = basename( $testdir ); + + # Add a test to the suite for the .bml file + push @testSuite, + { + name => "$testname $name", + test => sub { + + #print "Testing dir: $testdir\n"; + my $request = new Apache::FakeRequest ( + document_root => $TestDir, + uri => "/$name.bml", + filename => "$bmlfile", + ); + my $res; + + $ENV{testlookroot} = $testdir; + + assertNoException { + local $SIG{ALRM} = sub { die "Timeout" }; + alarm 10; + $res = Apache::BML::handler($request) + }; + alarm 0; + assertEquals 0, $res; + assertCorrect( $testdir, $name, $Apache::FakeRequest::Output ); + + print STDERR $Apache::Request::Errout, "\n"; + }, + }; + } +} + + +runTests( @testSuite ); diff --git a/bml/test/Pblocks/scheme.look b/bml/test/Pblocks/scheme.look new file mode 100755 index 0000000..0698caf --- /dev/null +++ b/bml/test/Pblocks/scheme.look @@ -0,0 +1,8 @@ +oneline=>{P}Arg one: %%DATA1%%; Arg two: %%DATA2%% + +multiline<={P} +Arg one: %%DATA1%% +Arg two: %%DATA2%% +<=multiline + + diff --git a/bml/test/_config.bml b/bml/test/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/bml-profile.pl b/bml/test/bml-profile.pl new file mode 100755 index 0000000..6e7cdd3 --- /dev/null +++ b/bml/test/bml-profile.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use Apache; +use Apache::FakeRequest (); +use Apache::BML; +use Benchmark; + +my $benchmark = shift; # times to run new code +my $bold = shift; # times to run old code +$bold = $benchmark unless defined $bold; + +my $r = Apache::FakeRequest->new( + 'filename' => "$ENV{LJHOME}/fake_root/bml-test.bml", +# 'filename' => "$ENV{LJHOME}/htdocs/foo.bml", + 'document_root' => "$ENV{LJHOME}/fake_root", + 'method' => "GET", + 'args' => "", + 'content' => "", + 'uri' => '/bml-test.bml', +# 'uri' => '/foo.bml', + 'header_only' => $benchmark ? 1 : 0, + ); + +unless ($benchmark) { +# *Apache::BML::bml_decode = \&Apache::BML::bml_decode_OLD; +# *Apache::BML::load_elements = \&Apache::BML::load_elements_OLD; + my $stat = Apache::BML::handler($r); + die "bad init" unless $stat == 0; + exit 0; +} + +print "New code:\n"; +timethis($benchmark, sub { + my $stat = Apache::BML::handler($r); +}); + + +if ($bold) { + print "Old code:\n"; + *Apache::BML::bml_decode = \&Apache::BML::bml_decode_OLD; + *Apache::BML::load_elements = \&Apache::BML::load_elements_OLD; + timethis($bold, sub { + my $stat = Apache::BML::handler($r); + }); +} + + + + diff --git a/bml/test/brads/_config.bml b/bml/test/brads/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/brads/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/brads/scheme.look b/bml/test/brads/scheme.look new file mode 100755 index 0000000..96ee347 --- /dev/null +++ b/bml/test/brads/scheme.look @@ -0,0 +1,9 @@ +page<= +{F} +%%title%% + +%%body%% + + +<=page + diff --git a/bml/test/brads/test1.bml b/bml/test/brads/test1.bml new file mode 100755 index 0000000..61034f5 --- /dev/null +++ b/bml/test/brads/test1.bml @@ -0,0 +1,16 @@ +[foo]%%DATA%%[/foo] + +<=localblocks +_info?>Test1 +body<= + +Test of local block foo: + +Another test of local block foo: + +<=body +page?> diff --git a/bml/test/brads/test1.correct b/bml/test/brads/test1.correct new file mode 100755 index 0000000..31d2590 --- /dev/null +++ b/bml/test/brads/test1.correct @@ -0,0 +1,12 @@ + +Test1 + + +Test of local block foo: [foo][/foo] + +Another test of local block foo: [foo]with data this time[/foo] + + + + + diff --git a/bml/test/codeblocks/_config.bml b/bml/test/codeblocks/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/codeblocks/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/codeblocks/carry-variables.bml b/bml/test/codeblocks/carry-variables.bml new file mode 100755 index 0000000..83906ae --- /dev/null +++ b/bml/test/codeblocks/carry-variables.bml @@ -0,0 +1,6 @@ + + + + + + diff --git a/bml/test/codeblocks/carry-variables.correct b/bml/test/codeblocks/carry-variables.correct new file mode 100755 index 0000000..b8482f5 --- /dev/null +++ b/bml/test/codeblocks/carry-variables.correct @@ -0,0 +1,6 @@ +This should show up twice +This should show up twice + +This should only show up once. + + diff --git a/bml/test/codeblocks/complex1.bml b/bml/test/codeblocks/complex1.bml new file mode 100755 index 0000000..81a360a --- /dev/null +++ b/bml/test/codeblocks/complex1.bml @@ -0,0 +1,15 @@ + + +some_function(); + +_code?> + diff --git a/bml/test/codeblocks/complex1.correct b/bml/test/codeblocks/complex1.correct new file mode 100755 index 0000000..268e69e --- /dev/null +++ b/bml/test/codeblocks/complex1.correct @@ -0,0 +1,4 @@ +Returning from the first codeblock. + +This is from the first codeblock + diff --git a/bml/test/codeblocks/complex2.bml b/bml/test/codeblocks/complex2.bml new file mode 100755 index 0000000..41a7c06 --- /dev/null +++ b/bml/test/codeblocks/complex2.bml @@ -0,0 +1,28 @@ + $this || "default this", + that => $that || "default that", + }, $class; + } + + sub this { my $self = shift; $self->{this} = shift if @_; $self->{this} } + sub that { my $self = shift; $self->{that} = shift if @_; $self->{that} } + + sub msg { + my $self = shift; + return "[This: ". $self->this . ", That: ". $self->that . "]"; + } +_code?> + + +msg; +_code?> + + diff --git a/bml/test/codeblocks/complex2.correct b/bml/test/codeblocks/complex2.correct new file mode 100755 index 0000000..a0f7720 --- /dev/null +++ b/bml/test/codeblocks/complex2.correct @@ -0,0 +1,6 @@ + + + +[This: pony, That: not yours] + + diff --git a/bml/test/codeblocks/re-expand.bml b/bml/test/codeblocks/re-expand.bml new file mode 100755 index 0000000..6a62ef1 --- /dev/null +++ b/bml/test/codeblocks/re-expand.bml @@ -0,0 +1,9 @@ +Return a BML construct: +" _code?> + +Inside-out from above: + + +Recurse: +' exec?> + diff --git a/bml/test/codeblocks/re-expand.correct b/bml/test/codeblocks/re-expand.correct new file mode 100755 index 0000000..6f31f0e --- /dev/null +++ b/bml/test/codeblocks/re-expand.correct @@ -0,0 +1,9 @@ +Return a BML construct: +[Tag: Foo] + +Inside-out from above: +[This is it.] + +Recurse: +[Error: _CODE block failed to execute by permission settings] + diff --git a/bml/test/codeblocks/scheme.look b/bml/test/codeblocks/scheme.look new file mode 100755 index 0000000..3780cf4 --- /dev/null +++ b/bml/test/codeblocks/scheme.look @@ -0,0 +1,4 @@ +tag=>{D}[Tag: %%DATA%%] +exec=>{D} + + diff --git a/bml/test/codeblocks/simple.bml b/bml/test/codeblocks/simple.bml new file mode 100755 index 0000000..d2b197a --- /dev/null +++ b/bml/test/codeblocks/simple.bml @@ -0,0 +1,12 @@ +Immediate value/Simple string: + + +Immediate value/List: + + +Returned string: + + +Returned List: + + diff --git a/bml/test/codeblocks/simple.correct b/bml/test/codeblocks/simple.correct new file mode 100755 index 0000000..4eba236 --- /dev/null +++ b/bml/test/codeblocks/simple.correct @@ -0,0 +1,12 @@ +Immediate value/Simple string: +Foo + +Immediate value/List: +list + +Returned string: +Bar + +Returned List: +list + diff --git a/bml/test/comments/_config.bml b/bml/test/comments/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/comments/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/comments/basic.bml b/bml/test/comments/basic.bml new file mode 100755 index 0000000..01f240e --- /dev/null +++ b/bml/test/comments/basic.bml @@ -0,0 +1,22 @@ +Comment: + + +Comment full: + + +Embedded: + _c?> + +Embedded full: + _comment?> + +Multiline: + + +_c?> + + + + diff --git a/bml/test/comments/basic.correct b/bml/test/comments/basic.correct new file mode 100755 index 0000000..aa012fa --- /dev/null +++ b/bml/test/comments/basic.correct @@ -0,0 +1,18 @@ +Comment: + + +Comment full: + + +Embedded: + + +Embedded full: + + +Multiline: + + + + + diff --git a/bml/test/comments/rendered.bml b/bml/test/comments/rendered.bml new file mode 100755 index 0000000..4b46bf2 --- /dev/null +++ b/bml/test/comments/rendered.bml @@ -0,0 +1,13 @@ +Single line: + + +Multiline: + + +Indirect: + + diff --git a/bml/test/comments/rendered.correct b/bml/test/comments/rendered.correct new file mode 100755 index 0000000..ad7f490 --- /dev/null +++ b/bml/test/comments/rendered.correct @@ -0,0 +1,11 @@ +Single line: + + +Multiline: + + +Indirect: +(Indirect) + + + diff --git a/bml/test/comments/scheme.look b/bml/test/comments/scheme.look new file mode 100755 index 0000000..242bb0e --- /dev/null +++ b/bml/test/comments/scheme.look @@ -0,0 +1,6 @@ +user_comment=> +indirect<= +(Indirect) + +<=indirect + diff --git a/bml/test/escape/_config.bml b/bml/test/escape/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/escape/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/escape/ea.bml b/bml/test/escape/ea.bml new file mode 100755 index 0000000..21ba7f2 --- /dev/null +++ b/bml/test/escape/ea.bml @@ -0,0 +1,34 @@ +Escape HTML tags: + tag should be replaced with and the + tag with . _ea?> + +Escape a code example: +
{ $key } = shift if @_;
+		$Pnotes->{ $key };
+	};
+}
+_ea?>
+ +Escape old-style syntax: + + +Escape new-style syntax: +. _ea?> + + + diff --git a/bml/test/escape/ea.correct b/bml/test/escape/ea.correct new file mode 100755 index 0000000..816ed32 --- /dev/null +++ b/bml/test/escape/ea.correct @@ -0,0 +1,32 @@ +Escape HTML tags: +In structural HTML, the <b> tag should be replaced with <strong> and the +<i> tag with <em>. + +Escape a code example: +
# Overload Apache::FakeRequest's print to append output to a variable.
+{
+	no warnings 'redefine';
+	*Apache::FakeRequest::print = sub {
+		my $r = shift;
+		$Output .= join('', @_)
+	};
+	*Apache::FakeRequest::log_error = sub {
+		my $r - shift;
+		print STDERR @_, "\n"; $Errout .= join('', @_)
+	};
+	*Apache::FakeRequest::pnotes = sub {
+		my ( $r, $key ) = @_;
+		$Pnotes->{ $key } = shift if @_;
+		$Pnotes->{ $key };
+	};
+}
+ +Escape old-style syntax: +Tags in BML used to be like (= this =), but that format has since been +deprecated. + +Escape new-style syntax: +Now tags in BML look like: <?foo?>. + + + diff --git a/bml/test/escape/eb.bml b/bml/test/escape/eb.bml new file mode 100755 index 0000000..b40b3b0 --- /dev/null +++ b/bml/test/escape/eb.bml @@ -0,0 +1,7 @@ +Escape old-style syntax: + + +Escape new-style syntax: +. _eb?> + diff --git a/bml/test/escape/eb.correct b/bml/test/escape/eb.correct new file mode 100755 index 0000000..3c57018 --- /dev/null +++ b/bml/test/escape/eb.correct @@ -0,0 +1,7 @@ +Escape old-style syntax: +Tags in BML used to be like (= this =), but that format has since been +deprecated. + +Escape new-style syntax: +Now tags in BML look like: <?foo?>. + diff --git a/bml/test/escape/eh.bml b/bml/test/escape/eh.bml new file mode 100755 index 0000000..af43bde --- /dev/null +++ b/bml/test/escape/eh.bml @@ -0,0 +1,26 @@ +Escape HTML tags: + tag should be replaced with and the + tag with . _eh?> + +Escape a code example: +
{ $key } = shift if @_;
+		$Pnotes->{ $key };
+	};
+}
+_eh?>
+ + diff --git a/bml/test/escape/eh.correct b/bml/test/escape/eh.correct new file mode 100755 index 0000000..90f4e22 --- /dev/null +++ b/bml/test/escape/eh.correct @@ -0,0 +1,24 @@ +Escape HTML tags: +In structural HTML, the <b> tag should be replaced with <strong> and the +<i> tag with <em>. + +Escape a code example: +
# Overload Apache::FakeRequest's print to append output to a variable.
+{
+	no warnings 'redefine';
+	*Apache::FakeRequest::print = sub {
+		my $r = shift;
+		$Output .= join('', @_)
+	};
+	*Apache::FakeRequest::log_error = sub {
+		my $r - shift;
+		print STDERR @_, "\n"; $Errout .= join('', @_)
+	};
+	*Apache::FakeRequest::pnotes = sub {
+		my ( $r, $key ) = @_;
+		$Pnotes->{ $key } = shift if @_;
+		$Pnotes->{ $key };
+	};
+}
+ + diff --git a/bml/test/escape/eu.bml b/bml/test/escape/eu.bml new file mode 100755 index 0000000..fa056e5 --- /dev/null +++ b/bml/test/escape/eu.bml @@ -0,0 +1,3 @@ +Escaped URL characters: +http://www.fruit-jar.com/booklist?title= + diff --git a/bml/test/escape/eu.correct b/bml/test/escape/eu.correct new file mode 100755 index 0000000..3a2b04c --- /dev/null +++ b/bml/test/escape/eu.correct @@ -0,0 +1,3 @@ +Escaped URL characters: +http://www.fruit-jar.com/booklist?title=21+Things+to+do+with+Excess+%21%25%24%40%23%21%40%23%40%23+Punctuation + diff --git a/bml/test/escape/scheme.look b/bml/test/escape/scheme.look new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/bml/test/escape/scheme.look @@ -0,0 +1 @@ + diff --git a/bml/test/fake_root/_config.bml b/bml/test/fake_root/_config.bml new file mode 100755 index 0000000..8a49a63 --- /dev/null +++ b/bml/test/fake_root/_config.bml @@ -0,0 +1,9 @@ +LookRoot . +DefaultScheme bluewhite +DefaultLanguage en + +AllowCode 1 +AllowTemplateCode 1 + + + diff --git a/bml/test/fake_root/bluewhite.look b/bml/test/fake_root/bluewhite.look new file mode 100755 index 0000000..f7dfac7 --- /dev/null +++ b/bml/test/fake_root/bluewhite.look @@ -0,0 +1,251 @@ +# +# Welcome to GENERIC.LOOK for the WhiteBlue scheme +# +# by.... +# Brad Fitzpatrick +# brad@danga.com +# + +######################### little stuff + +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

%%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

%%DATA%% + +H2=>{D}

%%DATA%% +HEAD2=>{D}

%%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

%%DATA%% + +GRIN=><grin> +HR=>

*

+ +NEWLINE=>{D}
     +P=>{D}
%%DATA%% +P/FOLLOW_P=>{D}

%%DATA%% + +STANDOUTO<= +{D}

+%%DATA%% + +
+<=STANDOUTO + +STANDOUT<= +{D}

+ + + + + + + + + + + + + + +
+ + +
+ +%%DATA%% + + +
+ + +
+ +
+<=STANDOUT +SOERROR=>
%%data%%
+ +######################### choices stuff + +CHOICE=>{P}
%%DATA1%%
%%DATA3%% + +CHOICES<= +{F}

+ + + + +
+
+%%ITEMS%% +
+
+
+%%ITEMSB%% +
+
+<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{F} + + +%%TITLE%% +%%head%% + + + + + + + +
+ + + + + + + +
  +'; +} +return ""; +_code?> + + + "; + } + return ""; +_code?> +
+ +
+ + + + + + + + + + + + + + + + +
+ + +
+ + +"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name
"; + } else { + $$ret .= "$name
"; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name
"; + } else { + $$ret .= "{'uri'}\">$name
"; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
+ +
+
+
+ +
+ +
+%%BODY%% + +
 
+  + 
+ + + + + + +
+ + Privacy Policy - + COPPA
+ Legal Disclaimer - + Site Map
+
+
+ + + +<=PAGE + diff --git a/bml/test/fake_root/bml-simple.bml b/bml/test/fake_root/bml-simple.bml new file mode 100755 index 0000000..5fb1e46 --- /dev/null +++ b/bml/test/fake_root/bml-simple.bml @@ -0,0 +1,14 @@ +{D}

%%data%%

+<=localblocks +_info?> +Pre. + +[ h1?>] + +Mid. + + + +End. diff --git a/bml/test/fake_root/bml-simple.correct b/bml/test/fake_root/bml-simple.correct new file mode 100755 index 0000000..fb57ef1 --- /dev/null +++ b/bml/test/fake_root/bml-simple.correct @@ -0,0 +1,10 @@ + +Pre. + +[

User Links

Inner

] + +Mid. + +

+ +End. diff --git a/bml/test/fake_root/bml-test.bml b/bml/test/fake_root/bml-test.bml new file mode 100755 index 0000000..597ef3a --- /dev/null +++ b/bml/test/fake_root/bml-test.bml @@ -0,0 +1,265 @@ +{s}✔ +pef=>{s}☺ +h1=>{D}

%%data%%

+page<= +{F} +%%title%% + +%%body%% + +<=page +<=localblocks +_info?> + + +<=head +title=>Site Map +body<= + + + endbaz p?> + + = Paid Only Feature
+ = Enhanced for Paid Users + h1?> + + + + +
+ + +
+ + + + +
+ + + + +
+ + +Thanks go to for the initial version of this page. + +<=body +page?> diff --git a/bml/test/fake_root/bml-test.correct b/bml/test/fake_root/bml-test.correct new file mode 100755 index 0000000..495f9d1 --- /dev/null +++ b/bml/test/fake_root/bml-test.correct @@ -0,0 +1,245 @@ + +Site Map + +
foo +

bar +

baz
baznest endbaz + +✔ = Paid Only Feature
+☺ = Enhanced for Paid Users +

User Links

Inner

+

+ + + +
+ + +
+ +

Other Links

+ + +
+ + + + +
+ +

*

+Thanks go to userinfopinrad for the initial version of this page. + + + + diff --git a/bml/test/fake_root/global.look b/bml/test/fake_root/global.look new file mode 100755 index 0000000..1d57dea --- /dev/null +++ b/bml/test/fake_root/global.look @@ -0,0 +1,286 @@ +IMGPREFIX=>{S}/img +STATPREFIX=>{S}/stc +SITENAME=>{S}Foo.com +SITEROOT=>{S}http://www.lj.com/ + +SECURITYPRIVATE=>{Ss} +SECURITYPROTECTED=>{Ss} +LJUSER=>{DRs}userinfo%%data%% +LJCOMM=>{DRs}userinfo%%data%% +LJUSERF=>{DRs}userinfo%%data%% +HELP=>{DR}(help) +INERR=>{DR}%%data%% +SOERROR=>{DR}
%%data%%
+ +NEEDLOGIN<= + +go login. +p?> +<=NEEDLOGIN + +BADINPUT<= + + +<=BADINPUT + +REQUIREPOST<= +{S}As a security precaution, the page you're viewing requires a POST request, +not a GET. If you're trying to submit this form legitimately, please +contact us. +<=REQUIREPOST + +LOAD_PAGE_INFO<= + 'Home', + 'uri' => '/', + 'match' => "^/(index\\.bml)?(\\?.*)?\$", + 'children' => [ + { 'name' => 'Create Journal', + 'uri' => '/create.bml', }, + { 'name' => 'Update', + 'uri' => '/update.bml', + 'extra' => '/update.bml?mode=full', +# 'children' => [ +# { 'name' => 'Full Update', +# 'uri' => '/update.bml?mode=full', } +# ], + }, + { 'name' => 'Download', + 'uri' => '/download/', }, + ], + }, + { 'name' => 'LiveJournal', + 'children' => [ + { 'name' => 'News', + 'match' => '^/news\\.bml\$', + 'uri' => '/news.bml', }, + { 'name' => 'Paid Accounts', + 'uri' => '/paidaccounts/', + 'recursematch' => '^/paidaccounts/', + 'children' => [ + { 'name' => 'Is this safe?', + 'uri' => '/paidaccounts/whysafe.bml', }, + { 'name' => 'Progress', + 'uri' => '/paidaccounts/progress.bml', }, + ], + }, +# { 'name' => 'To-Do list', +# 'uri' => '/todo.bml', }, + { 'name' => 'Contributors', + 'uri' => '/contributors.bml', }, + ], + }, + { 'name' => 'Customize', + 'children' => [ + { 'name' => 'Modify Journal', + 'uri' => '/modify.bml', }, + { 'name' => 'Create Style', + 'uri' => '/createstyle.bml', }, + { 'name' => 'Edit Style', + 'uri' => '/editstyle.bml', }, + ], + }, + { 'name' => 'Find Users', + 'children' => [ + { 'name' => 'Random!', + 'uri' => '/random.bml', }, + { 'name' => 'By Region', + 'uri' => '/directory.bml', }, + { 'name' => 'By Interest', + 'uri' => '/interests.bml', }, + { 'name' => 'Search', + 'uri' => '/directorysearch.bml', } + ], }, + { 'name' => 'Edit ...', + 'children' => [ + { 'name' => 'Personal Info &', + 'uri' => '/editinfo.bml', }, + { 'name' => 'Settings', cont => 1, + 'uri' => '/editinfo.bml', }, + { 'name' => 'Your Friends', + 'uri' => '/editfriends.bml', }, + { 'name' => 'Old Entries', + 'uri' => '/editjournal.bml', }, + { 'name' => 'Your Pictures', + 'uri' => '/editpics.bml', }, + { 'name' => 'Your Password', + 'uri' => '/changepassword.bml', }, + ], + }, + { 'name' => 'Developer Area', + 'uri' => '/developer/', + 'match' => "^/developer/\$", + 'recursematch' => "^/developer/", + 'children' => [ + { 'name' => 'Style System', + 'uri' => '/developer/styles.bml', + 'children' => [ + { 'name' => 'View Types', + 'uri' => '/developer/views.bml', }, + { 'name' => 'Variable List', + 'uri' => '/developer/varlist.bml', }, + ], + }, + { 'name' => 'Embedding', + 'uri' => '/developer/embedding.bml', }, + { 'name' => 'Protocol', + 'uri' => '/developer/protocol.bml', + 'children' => [ + { 'name' => 'Mode List', + 'uri' => '/developer/modelist.bml', } + ], + }, + ], + }, + { 'name' => 'Need Help?', + 'children' => [ + { 'name' => 'Lost Password?', + 'uri' => '/lostinfo.bml', }, + { 'name' => 'Freq. Asked', + 'uri' => '/support/faq.bml', }, + { 'name' => 'Questions', + 'uri' => '/support/faq.bml', cont => 1, }, + { 'name' => 'Support Area', + 'uri' => '/support/', }, + ], + }, + ); + + my $remote = LJ::get_remote(); + my $remuser = $remote ? $remote->{'user'} : ""; + my $uri = BML::get_uri(); + if ($remuser ne "" && $uri ne "/logout.bml") + { + my $subdomain = $remuser; + $subdomain =~ s/_/-/g; + unshift @sidebar, { 'name' => "Hello, $remuser!", + 'children' => [ + { 'name' => 'Your Journal', + 'children' => [ + { 'name' => 'Recent', + 'uri' => "/users/$remuser/", }, + { 'name' => 'Calendar', + 'uri' => "/users/$remuser/calendar", }, + { 'name' => 'Friends', + 'uri' => "/users/$remuser/friends", + 'extra' => "/friendsfilter.bml", + }, + ], + }, + { 'name' => 'User Info', + 'uri' => "/userinfo.bml?user=$remuser", }, + { 'name' => 'Memories', + 'uri' => "/memories.bml?user=$remuser", }, + { 'name' => 'Logout', + 'uri' => '/logout.bml', }, + ] + }; + } elsif ($uri ne "/login.bml") { + unshift @sidebar, { 'name' => "Log In", + 'uri' => '/login.bml', } + } + +return ""; +_code?> +<=LOAD_PAGE_INFO + +AL=>{P}%%data2%% +AWAYLINK=>{P}%%data2%% + +H1=>{D}

%%data%%

+H2=>{D}

%%data%%

+ +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

%%data%% + +GRIN=>{S}<grin> +HR=>{S}


+ +NEWLINE=>{S}
     +P=>{D}

%%data%%

+ +STANDOUT<= +{D}
+
+%%data%% +
+
+<=STANDOUT + +BADCONTENT<= + + +<=BADCONTENT + +DE<= +%%data%% +<=DE + +EMCOLOR=>{S}#c0c0c0 +HOTCOLOR=>{S}#ff0000 +EMCOLORLITE=>{S}#e2e2e2 +screenedbarcolor=>{S}#d0d0d0 + +CHOICE=>{P}
%%data1%%
%%data3%% + +CHOICES<= +{F} + + + + +
+
+%%items%% +
+
+
+%%itemsb%% +
+
+<=CHOICES + +PAGE<= +{Fp} +%%title%%%%head%% + +%%body%% + + +<=PAGE + +CHALRESPJS<= + + +<=CHALRESPJS diff --git a/bml/test/include/_config.bml b/bml/test/include/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/include/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/include/loremipsum.txt b/bml/test/include/loremipsum.txt new file mode 100755 index 0000000..83a5dcf --- /dev/null +++ b/bml/test/include/loremipsum.txt @@ -0,0 +1,31 @@ +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque convallis +lacus vel dui. Nam nec augue in massa bibendum consectetuer. In porttitor +nulla. Integer volutpat placerat justo. Etiam interdum pulvinar risus. Sed ut mi +sit amet nulla euismod pulvinar. Phasellus sed turpis. Aliquam in leo in wisi +auctor feugiat. Quisque consequat ante id orci. Sed condimentum pede id +elit. Proin vitae nunc nec arcu ornare tincidunt. Ut mollis interdum +augue. Integer id felis. Nulla facilisis faucibus sapien. Praesent vehicula +luctus wisi. Sed volutpat augue nec lacus vulputate pretium. Suspendisse +potenti. Sed blandit semper tellus. + +Ut tortor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, +per inceptos hymenaeos. Phasellus id metus. Phasellus interdum lacinia +leo. Pellentesque a massa. Aliquam non justo. Proin enim metus, nonummy sit +amet, ornare eu, convallis vel, arcu. Pellentesque tempor rhoncus +mauris. Praesent malesuada pulvinar turpis. Vestibulum ante ipsum primis in +faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus nunc. Mauris +imperdiet mi nec libero. Maecenas purus velit, fringilla id, mattis sed, +pulvinar id, ligula. Vivamus vel erat vel diam cursus eleifend. + +Donec massa est, mollis ac, placerat iaculis, vehicula id, dolor. Quisque +malesuada diam vel pede. Suspendisse egestas. Sed imperdiet tellus non +magna. Etiam luctus, wisi ut fringilla pharetra, tortor lorem suscipit libero, +nec imperdiet ante dolor mollis wisi. Nulla feugiat, erat non viverra mattis, +massa dui molestie orci, vitae bibendum dolor orci id ligula. Quisque +lorem. Donec fringilla vehicula ante. Nam convallis, sapien vitae interdum +mattis, nisl diam egestas enim, ac posuere nisl elit ut purus. Nullam +nonummy. Nulla felis. Fusce cursus lorem quis enim. Suspendisse mattis luctus +magna. Morbi ligula lectus, bibendum ac, tempus ac, scelerisque ac, +pede. Praesent lobortis lectus a libero. Sed luctus, dui a porttitor congue, +neque metus facilisis orci, sit amet congue lorem ligula ut magna. Vivamus non +orci. diff --git a/bml/test/include/plain.bml b/bml/test/include/plain.bml new file mode 100755 index 0000000..6d8ee02 --- /dev/null +++ b/bml/test/include/plain.bml @@ -0,0 +1,6 @@ +Some Plain Text: +1 +code=>0 +file=>loremipsum.txt +_include?> diff --git a/bml/test/include/plain.correct b/bml/test/include/plain.correct new file mode 100755 index 0000000..9c9564e --- /dev/null +++ b/bml/test/include/plain.correct @@ -0,0 +1,2 @@ +Some Plain Text: +[Error: Could not open include file.] diff --git a/bml/test/include/scheme.look b/bml/test/include/scheme.look new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/bml/test/include/scheme.look @@ -0,0 +1 @@ + diff --git a/bml/test/info/_config.bml b/bml/test/info/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/info/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/info/localblocks.bml b/bml/test/info/localblocks.bml new file mode 100755 index 0000000..84f49d7 --- /dev/null +++ b/bml/test/info/localblocks.bml @@ -0,0 +1,9 @@ +[ %%DATA%% ] +braced=>{ %%DATA%% } +grouped=>( %%DATA%% ) +<=localblocks +_info?> + + bracketed?> braced?> bracketed?> diff --git a/bml/test/info/localblocks.correct b/bml/test/info/localblocks.correct new file mode 100755 index 0000000..5ce1ccc --- /dev/null +++ b/bml/test/info/localblocks.correct @@ -0,0 +1,3 @@ + + +[ { [ ( fish ) ] } ] diff --git a/bml/test/info/package.bml b/bml/test/info/package.bml new file mode 100755 index 0000000..1f408f6 --- /dev/null +++ b/bml/test/info/package.bml @@ -0,0 +1,9 @@ + +Foo +_info?> + diff --git a/bml/test/info/package.correct b/bml/test/info/package.correct new file mode 100755 index 0000000..139597f --- /dev/null +++ b/bml/test/info/package.correct @@ -0,0 +1,2 @@ + + diff --git a/bml/test/info/scheme.look b/bml/test/info/scheme.look new file mode 100755 index 0000000..e69de29 diff --git a/bml/test/newtest.pl b/bml/test/newtest.pl new file mode 100755 index 0000000..c30c03f --- /dev/null +++ b/bml/test/newtest.pl @@ -0,0 +1,82 @@ +#!/usr/bin/perl -w +package newtest; +use strict; +use warnings qw{all}; + +BEGIN { + use Term::Prompter qw{}; + use FindBin qw{$Bin}; + use Cwd qw{getcwd}; + use IO::File qw{}; + use Fcntl qw{O_WRONLY O_CREAT O_EXCL}; +} + +my ( + $prompter, + $olddir, + $testname, + $firstfile, + $ofh, + ); + +$olddir = getcwd(); +chdir $Bin; + +$prompter = new Term::Prompter; +$prompter->promptColor( 'cyan' ); + +# Prompt for the information about this test +$prompter->message( "This will create a new test subdirectory and create the \n", + "necessary files and links.\n" ); +$testname = $prompter->prompt( "Name of the test subdirectory:" ) + or exit 1; +$firstfile = $prompter->promptWithDefault( 'index.bml', "Name of the first BML test file" ); +$firstfile .= ".bml" unless $firstfile =~ m{\.bml$}; + +# Make the test directory, symlink the config, and add the new files to it +$prompter->message( "Creating '$testname' directory..." ); +mkdir $testname or die "mkdir: $testname: $!"; +symlink "../_config.bml", "$testname/_config.bml" + or die "symlink: _config.bml -> $testname/_config.bml: $!"; + +$prompter->message( "Creating BML file '$testname/$firstfile'..." ); +$ofh = new IO::File "$testname/$firstfile", O_WRONLY|O_CREAT|O_EXCL + or die "open: $testname/$firstfile: $!"; +$ofh->print( <<"EOF" ); + + + + + +EOF +$ofh->close; + +$prompter->message( "Creating lookfile '$testname/scheme.look'..." ); +$ofh = new IO::File "$testname/scheme.look", O_WRONLY|O_CREAT|O_EXCL + or die "open: $testname/scheme.look: $!"; +$ofh->print( <<"EOF" ); + +example=>{D}%%DATA%% + +EOF +$ofh->close; + +chdir( $olddir ); + +# Give instructions to the user +( my $correct = $firstfile ) =~ s{\.bml$}{.correct}; +$prompter->message( <<"EOF" ); + +Now you need to do three things to finish setting up the test: + +1. Edit $testname/scheme.look and add the blocks you're testing. +2. Edit $testname/$firstfile and add your test content. +3. When you're done, add '$testname' to the list of tests to run in the + \@TestSubdirs var in t/20_render.t. + +Then when you run the new test for the first time, it'll generate a comparison +test output file in $testname/$correct which you should verify for +correctness. + +EOF + diff --git a/bml/test/recursion/_config.bml b/bml/test/recursion/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/recursion/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/recursion/infinite.bml b/bml/test/recursion/infinite.bml new file mode 100755 index 0000000..d7052f3 --- /dev/null +++ b/bml/test/recursion/infinite.bml @@ -0,0 +1,11 @@ +Simple infinite recursion: + + +Complex infinite recursion: + + diff --git a/bml/test/recursion/infinite.correct b/bml/test/recursion/infinite.correct new file mode 100755 index 0000000..63aafd7 --- /dev/null +++ b/bml/test/recursion/infinite.correct @@ -0,0 +1,6 @@ +Simple infinite recursion: +[Error: Too deep recursion: RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG -> RTAG] + +Complex infinite recursion: +[Error: Too deep recursion: 1TAG -> 2TAG -> REDTAG -> BLUETAG -> 1TAG -> 2TAG -> REDTAG -> BLUETAG -> 1TAG -> 2TAG -> REDTAG] + diff --git a/bml/test/recursion/nested.bml b/bml/test/recursion/nested.bml new file mode 100755 index 0000000..9eabf29 --- /dev/null +++ b/bml/test/recursion/nested.bml @@ -0,0 +1 @@ + diff --git a/bml/test/recursion/nested.correct b/bml/test/recursion/nested.correct new file mode 100755 index 0000000..32dd382 --- /dev/null +++ b/bml/test/recursion/nested.correct @@ -0,0 +1 @@ +[outer: [inner: Foo]] diff --git a/bml/test/recursion/scheme.look b/bml/test/recursion/scheme.look new file mode 100755 index 0000000..334a238 --- /dev/null +++ b/bml/test/recursion/scheme.look @@ -0,0 +1,7 @@ +rtag=>{D} +outer=>{D}[outer: ] +inner=>{D}[inner: %%DATA%%] +1tag=>{D} +2tag=>{D} +redtag=>{D} +bluetag=>{D} diff --git a/bml/test/syntax-errors/_config.bml b/bml/test/syntax-errors/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/syntax-errors/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/syntax-errors/dangling-tagopen.bml b/bml/test/syntax-errors/dangling-tagopen.bml new file mode 100755 index 0000000..f88c508 --- /dev/null +++ b/bml/test/syntax-errors/dangling-tagopen.bml @@ -0,0 +1 @@ + diff --git a/bml/test/syntax-errors/no-close.correct b/bml/test/syntax-errors/no-close.correct new file mode 100755 index 0000000..26bacf0 --- /dev/null +++ b/bml/test/syntax-errors/no-close.correct @@ -0,0 +1,2 @@ +Tag vs Tga: +[Error: BML block 'TAG' has no close] \ No newline at end of file diff --git a/bml/test/syntax-errors/onlyopen.bml b/bml/test/syntax-errors/onlyopen.bml new file mode 100755 index 0000000..9bfc3bc --- /dev/null +++ b/bml/test/syntax-errors/onlyopen.bml @@ -0,0 +1,7 @@ + + diff --git a/bml/test/syntax-errors/onlyopen.correct b/bml/test/syntax-errors/onlyopen.correct new file mode 100755 index 0000000..a997754 --- /dev/null +++ b/bml/test/syntax-errors/onlyopen.correct @@ -0,0 +1 @@ +[Error: BML block 'TAG' has no close] \ No newline at end of file diff --git a/bml/test/syntax-errors/scheme.look b/bml/test/syntax-errors/scheme.look new file mode 100755 index 0000000..b740bef --- /dev/null +++ b/bml/test/syntax-errors/scheme.look @@ -0,0 +1,2 @@ +tag=>{D}[Tag: %%DATA%%] + diff --git a/bml/test/syntax-errors/spaces.bml b/bml/test/syntax-errors/spaces.bml new file mode 100755 index 0000000..aeef6c8 --- /dev/null +++ b/bml/test/syntax-errors/spaces.bml @@ -0,0 +1,12 @@ +Tag with spurious space: + + +Tag with leading padding: + + +Tag with padding on both sides: + + +Tag with trailing padding: + + diff --git a/bml/test/syntax-errors/spaces.correct b/bml/test/syntax-errors/spaces.correct new file mode 100755 index 0000000..ce60dbd --- /dev/null +++ b/bml/test/syntax-errors/spaces.correct @@ -0,0 +1,11 @@ +Tag with spurious space: +[Tag: Foo t ag?> + +Tag with leading padding: + + +Tag with trailing padding: +[Error: BML block 'TAG' has no close] \ No newline at end of file diff --git a/bml/test/tutorial-example1/project.bml b/bml/test/tutorial-example1/project.bml new file mode 100755 index 0000000..800203c --- /dev/null +++ b/bml/test/tutorial-example1/project.bml @@ -0,0 +1,8 @@ + + <?project project?> + +

+ + + + diff --git a/bml/test/tutorial-example1/project.correct b/bml/test/tutorial-example1/project.correct new file mode 100755 index 0000000..2c98f80 --- /dev/null +++ b/bml/test/tutorial-example1/project.correct @@ -0,0 +1,10 @@ + + The Alabaster Project + +

The Alabaster Project

+ +

Welcome to The Alabaster Project, a joint effort between the citizens of earth +and Spumco, Inc.

+ + + diff --git a/bml/test/tutorial-example1/scheme.look b/bml/test/tutorial-example1/scheme.look new file mode 100755 index 0000000..4d93c93 --- /dev/null +++ b/bml/test/tutorial-example1/scheme.look @@ -0,0 +1,6 @@ +project=>The Alabaster Project + +greeting<= +

Welcome to , a joint effort between the citizens of earth +and Spumco, Inc.

+<=greeting diff --git a/bml/test/tutorial-example2/index.bml b/bml/test/tutorial-example2/index.bml new file mode 100755 index 0000000..69ed462 --- /dev/null +++ b/bml/test/tutorial-example2/index.bml @@ -0,0 +1,27 @@ + + Hansel and Grendel Go to Finishing School + + + + +

Our story begins at a point in the Universe not unlike where you are now + sitting, drinking your government-sanctioned stimulant, dreaming of the + day when you, too, will own your own personalized luxury home on 0.3 acres + of land, with a stunning view of, well, the neighbor's personalized luxury + home on 0.3 acres of land. Except this point in the Universe is much more + exciting, fine-smelling, and generally a better place to be than + yours.

+ + + +

So, anyway, at this particular point in the Universe, on a day not + entirely unlike today, two entirely unrelated mythological pantheons + collided, resulting in a fast friendship between a Little Boy Bound to be + Eaten by the Architypal Crone and a Faceless Beast That Waits for the Hero + to Dispatch It. Which, as you might have guessed, was not the intention of + the various storytellers involved, but that's what happens when people + stop reading all the really cool stories and start checking the Financial + Section every 12 minutes. There's only so much space to go around in the + collective consciousness, you know...

+ + diff --git a/bml/test/tutorial-example2/index.correct b/bml/test/tutorial-example2/index.correct new file mode 100755 index 0000000..55dbf8b --- /dev/null +++ b/bml/test/tutorial-example2/index.correct @@ -0,0 +1,27 @@ + + Hansel and Grendel Go to Finishing School + + +

Hansel and Grendel Go to Finishing School

+ +

Our story begins at a point in the Universe not unlike where you are now + sitting, drinking your government-sanctioned stimulant, dreaming of the + day when you, too, will own your own personalized luxury home on 0.3 acres + of land, with a stunning view of, well, the neighbor's personalized luxury + home on 0.3 acres of land. Except this point in the Universe is much more + exciting, fine-smelling, and generally a better place to be than + yours.

+ +

No, Really, It Is Much Finer

+ +

So, anyway, at this particular point in the Universe, on a day not + entirely unlike today, two entirely unrelated mythological pantheons + collided, resulting in a fast friendship between a Little Boy Bound to be + Eaten by the Architypal Crone and a Faceless Beast That Waits for the Hero + to Dispatch It. Which, as you might have guessed, was not the intention of + the various storytellers involved, but that's what happens when people + stop reading all the really cool stories and start checking the Financial + Section every 12 minutes. There's only so much space to go around in the + collective consciousness, you know...

+ + diff --git a/bml/test/tutorial-example2/scheme.look b/bml/test/tutorial-example2/scheme.look new file mode 100755 index 0000000..819ed01 --- /dev/null +++ b/bml/test/tutorial-example2/scheme.look @@ -0,0 +1,2 @@ +heading=>

%%DATA%%

+subheading=>

%%DATA%%

diff --git a/bml/test/tutorial-example3/index.bml b/bml/test/tutorial-example3/index.bml new file mode 100755 index 0000000..7a103a2 --- /dev/null +++ b/bml/test/tutorial-example3/index.bml @@ -0,0 +1,3 @@ + + + diff --git a/bml/test/tutorial-example3/index.correct b/bml/test/tutorial-example3/index.correct new file mode 100755 index 0000000..352e072 --- /dev/null +++ b/bml/test/tutorial-example3/index.correct @@ -0,0 +1,6 @@ +

Lava Lamps

+ + +
+

Oil-based Lava Lamps (and Chickens)

+ diff --git a/bml/test/tutorial-example3/scheme.look b/bml/test/tutorial-example3/scheme.look new file mode 100755 index 0000000..e1b88e7 --- /dev/null +++ b/bml/test/tutorial-example3/scheme.look @@ -0,0 +1,6 @@ +heading=>

%%DATA%%

+subhead<= + +
+

%%DATA%%

+<=subhead diff --git a/bml/test/tutorial-example4/index.bml b/bml/test/tutorial-example4/index.bml new file mode 100755 index 0000000..e507f8a --- /dev/null +++ b/bml/test/tutorial-example4/index.bml @@ -0,0 +1,9 @@ +listrules +heading=>Rules of the Lists +body<= +There are many considerations when engaging in mounted combat at a tourney, not +the least of which is obeying the convoluted and sometimes confusing localized +Rules of the Lists. +<=body +section?> diff --git a/bml/test/tutorial-example4/index.correct b/bml/test/tutorial-example4/index.correct new file mode 100755 index 0000000..f03c7d1 --- /dev/null +++ b/bml/test/tutorial-example4/index.correct @@ -0,0 +1,9 @@ + +
+

Rules of the Lists

+

There are many considerations when engaging in mounted combat at a tourney, not +the least of which is obeying the convoluted and sometimes confusing localized +Rules of the Lists. +

+
+ diff --git a/bml/test/tutorial-example4/scheme.look b/bml/test/tutorial-example4/scheme.look new file mode 100755 index 0000000..ac9739f --- /dev/null +++ b/bml/test/tutorial-example4/scheme.look @@ -0,0 +1,11 @@ +smallcaps=>{D}%%DATA%% + +topiclink=>{F}%%linktext%% + +section<= +{F} +
+

%%heading%%

+

%%body%%

+
+<=section diff --git a/bml/test/tutorial-example5/_config.bml b/bml/test/tutorial-example5/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/tutorial-example5/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/tutorial-example5/readinglist.bml b/bml/test/tutorial-example5/readinglist.bml new file mode 100755 index 0000000..6af8ec1 --- /dev/null +++ b/bml/test/tutorial-example5/readinglist.bml @@ -0,0 +1,8 @@ +2004/10/14 +items<= + + + +<=items +linklist?> diff --git a/bml/test/tutorial-example5/readinglist.correct b/bml/test/tutorial-example5/readinglist.correct new file mode 100755 index 0000000..928fd3c --- /dev/null +++ b/bml/test/tutorial-example5/readinglist.correct @@ -0,0 +1,10 @@ + +

My Current Reading List

+
+
News of Brad
Brad's daily adventure
+
BoingBoing
A directory of wonderful things
+
WPGtR
Wow, this book comes with an onion!
+ +
+

Last updated: 2004/10/14

+ diff --git a/bml/test/tutorial-example5/scheme.look b/bml/test/tutorial-example5/scheme.look new file mode 100755 index 0000000..1c7091b --- /dev/null +++ b/bml/test/tutorial-example5/scheme.look @@ -0,0 +1,11 @@ +LINKITEM=>{P}
%%data1%%
%%data3%%
+ +LINKLIST<= +{F} +

My Current Reading List

+
+%%items%% +
+

Last updated: %%date%%

+<=LINKLIST + diff --git a/bml/test/tutorial-example6/index.bml b/bml/test/tutorial-example6/index.bml new file mode 100755 index 0000000..39b3eae --- /dev/null +++ b/bml/test/tutorial-example6/index.bml @@ -0,0 +1,4 @@ + +

Welcome to

+ + diff --git a/bml/test/tutorial-example6/index.correct b/bml/test/tutorial-example6/index.correct new file mode 100755 index 0000000..7e0b238 --- /dev/null +++ b/bml/test/tutorial-example6/index.correct @@ -0,0 +1,4 @@ + +

Welcome to Spumco, Inc.

+ + diff --git a/bml/test/tutorial-example6/scheme.look b/bml/test/tutorial-example6/scheme.look new file mode 100755 index 0000000..cc87987 --- /dev/null +++ b/bml/test/tutorial-example6/scheme.look @@ -0,0 +1,3 @@ + +companyname=>{S}Spumco, Inc. + diff --git a/bml/test/tutorial-example7/index.bml b/bml/test/tutorial-example7/index.bml new file mode 100755 index 0000000..1b7cc00 --- /dev/null +++ b/bml/test/tutorial-example7/index.bml @@ -0,0 +1,5 @@ + + + + + diff --git a/bml/test/tutorial-example7/index.correct b/bml/test/tutorial-example7/index.correct new file mode 100755 index 0000000..e097ee2 --- /dev/null +++ b/bml/test/tutorial-example7/index.correct @@ -0,0 +1,5 @@ + + +This is an example call to a block. + + diff --git a/bml/test/tutorial-example7/scheme.look b/bml/test/tutorial-example7/scheme.look new file mode 100755 index 0000000..4648201 --- /dev/null +++ b/bml/test/tutorial-example7/scheme.look @@ -0,0 +1,3 @@ + +example=>{D}%%DATA%% + diff --git a/bml/test/tutorial1/_config.bml b/bml/test/tutorial1/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/tutorial1/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/tutorial1/index.bml b/bml/test/tutorial1/index.bml new file mode 100755 index 0000000..9bde793 --- /dev/null +++ b/bml/test/tutorial1/index.bml @@ -0,0 +1,21 @@ + + + FooBar Enterprises - Page + + +

FooBar Enterprises - Page

+
+ +

+This is just an introductory text. The normal way to include text like this +is to write it in Latin, but since I don't know Latin, you'll have to settle +with this little paragraph. +

+ +

+I'd rather have to edit all of my pages by hand when I decide to change the +unified look of my site! +

+ + + diff --git a/bml/test/tutorial1/index.correct b/bml/test/tutorial1/index.correct new file mode 100755 index 0000000..fc70d30 --- /dev/null +++ b/bml/test/tutorial1/index.correct @@ -0,0 +1,20 @@ + + + FooBar Enterprises - Page + + +

FooBar Enterprises - Page

+
+
Headers - What good are they?
+

+This is just an introductory text. The normal way to include text like this +is to write it in Latin, but since I don't know Latin, you'll have to settle +with this little paragraph. +

+
Templates are for Wimps!
+

+I'd rather have to edit all of my pages by hand when I decide to change the +unified look of my site! +

+ + diff --git a/bml/test/tutorial1/scheme.look b/bml/test/tutorial1/scheme.look new file mode 100755 index 0000000..c8fc8d5 --- /dev/null +++ b/bml/test/tutorial1/scheme.look @@ -0,0 +1,2 @@ +header=>{D}
%%DATA%%
+ diff --git a/bml/test/tutorial2/_config.bml b/bml/test/tutorial2/_config.bml new file mode 100755 index 0000000..58220c3 --- /dev/null +++ b/bml/test/tutorial2/_config.bml @@ -0,0 +1,9 @@ +LookRoot $testlookroot +DefaultScheme scheme +DefaultLanguage en + +AllowOldSyntax 0 +AllowCode 1 +AllowTemplateCode 1 + + diff --git a/bml/test/tutorial2/index.bml b/bml/test/tutorial2/index.bml new file mode 100755 index 0000000..f45703e --- /dev/null +++ b/bml/test/tutorial2/index.bml @@ -0,0 +1,18 @@ +FooBar Enterprises - Page +body<= + +
+ +

+This is just an introductory text. The normal way to include text like this +is to write it in Latin, but since I don't know Latin, you'll have to settle +with this little paragraph. +

+ +

+I'd rather have to edit all of my pages by hand when I decide to change the +unified look of my site! +

+<=body +page?> diff --git a/bml/test/tutorial2/index.correct b/bml/test/tutorial2/index.correct new file mode 100755 index 0000000..bcb2ebd --- /dev/null +++ b/bml/test/tutorial2/index.correct @@ -0,0 +1,21 @@ + + + FooBar Enterprises - Page + + +

FooBar Enterprises - Page

+
+
Headers - What good are they?
+

+This is just an introductory text. The normal way to include text like this +is to write it in Latin, but since I don't know Latin, you'll have to settle +with this little paragraph. +

+
Templates are for Wimps!
+

+I'd rather have to edit all of my pages by hand when I decide to change the +unified look of my site! +

+ + + diff --git a/bml/test/tutorial2/scheme.look b/bml/test/tutorial2/scheme.look new file mode 100755 index 0000000..72ad853 --- /dev/null +++ b/bml/test/tutorial2/scheme.look @@ -0,0 +1,13 @@ +page<= +{F} + + %%title%% + + +%%body%% + + +<=page +header=>{D}
%%DATA%%
+h1=>{D}

%%DATA%%

+ diff --git a/images/mood/charitycam/aliens/angry.gif b/images/mood/charitycam/aliens/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..6678ff33e66a38a077e1c3f9c1601154654bd88b GIT binary patch literal 1317 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 XMT?$2?U-yB?W~*<6*Xl$!*2W=lEC=m literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/awake.gif b/images/mood/charitycam/aliens/awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..de94c03b1ca4ad8f95deadf876fb9e44eaef105e GIT binary patch literal 1034 zcmZ?wbhEHbRA$g+I3mNqkj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwN!ic6nphl2lccB&1p$qI;UlAPx00{J$sifJ+^i2vAuhb9Xs~_|9^%|1}Mm6 zQ2fvB=Nc01>=@u`q-Vg)2$WF#$--&GAj6=;%D~GY%^=Uf!10g4l0!zLz^SEKfKO|R z!-mAeoZ@;JGdv2F+Bo=?ENUtgosael8>iff2v9oFFJX|n?*#p#AFhkE^#%< zn*=OSU~FbBmGp@CmC(e(StOexl70E$Q&wKNny|SBPE8COm>beA9B@pyJay(VzJ_nc zEq6D>8uv0RT=SIufT~KK4x`0;7EVPKhXo6MzH6Qx={93WBJ)uWE`_a^@7~+HyN$!^ zywijQ3-^@savu>=h_6%nwLnO~Bx670w(>{wwmzRWi`C2Ff`i4IhXOY2`|a<% zZ*Dv`@%VfeK8J1c1=1c17});vZjlVWugP$*T##b{V+OCMfn(Uk&ait7!ltePEMg7~ z42*0N2OO9L4Hh^s3i1dvvVELrqKq7U6HTDe=fvf*$Wt`Yq0!OPEF~^_qohgDlpw9t g37Om-9jXn*q6rPtL0StRN#=U&w-ejYJZ!{#E-gK48AT^p+nT)HBeY_q6z+#YE405L- z+hUU2sy920+nlDnc@%Zp3eIA>4yVy#v3Na}uRV3&wt7Q7-Jz@fp-^aketu#9|4Iem z&r`Q4)cKh*l_F(@mdPUaO(8C$vsbyh+X5o*HLKT19MeBVZ|~J@%}f9c@l}pf9V$8BTc<_HvNeO zp)q zz9LCn>Ec0zFly;)&ST90Ol50dZ=Ai>CoF$N6JQ0u9O1zvFiG??biKOgw64`&9v8s$ zmLecK_N@O;tc*77#z-WM>vI#QaAMSSb1N2rC`!p^+Y7FisntA;Ay+dKG2BX4&C2Y8 zY82A7SXCa2$jlfe^eyu0>k}heT`(f?3&_vzPLCa0#=hGU7Acw<`((3bHsHu1Xj@=< z)yR~*AUf@QJy#-z?EGF~0D16o>R$2g`kz=Z(Zx|$Fk?{+LK2m-YBWDQhWEoD4ZT_`$uI!sZb7&*SAlDB7jPepjMk(q(TmG~O6%b_sunT~x_ z($LII=lL~j)#!h82;b^ZX>AOIQd&6d*9B|I2}><@KYtKsN9nt!RS$<8lysZ3?U{bq znUr%T!xLF7b4R?lwu%z@tFn%;Pai+SCebyc(I1L5~nZSdd();wsXFn?&hInzA2pu?PZ^os7u&aQa3KJbr@ z1Hs$feeSn9p5}*QW7dUC4<5hK;bAH9n%cmj{QZT8(^pz4k!S*{^>(7v_|&PJo7rxR+tkfDxu6=?hBamq9ky3H5-$G@JUJq4^d!COYccUaO#s)L& zBPR0z%Ehc?S}Z!f1^R0aVctT}ikAK)-qGKo7cn2vvMRmsjqAvLoG3tVk;t(w3`W9B zWCyruBPh(W-vKa1i}49er&8}=GSW0;Yte+jAy_dI4K2S`IO(vkih~gSijwPGjHOSW z5QN%rQbhmlgp=$H?_>jLEXRp)=*y8>+s{HDak2fyq=RsT7q4LN5}$Sm8j#-{#8gF5 z`vYJDu2Pry1xO)%F`$S literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/blank.gif b/images/mood/charitycam/aliens/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ad6a603154b737fab2b0b68f046a6d9340b7a7d GIT binary patch literal 1277 zcmZ?wbhEHbRA$g+xN64$1YU+wZmQ|-hN(f8*+GWIL6$&N9c5V@Wmz5OlpW<%n(SVk z9adeOT%GFCnjO?u9Nt|LF{L!MvpRKZb#YHi_RN;zDJ{iwIx?2^6fd1pzIJBm);ZP3 zmR6seGG)%pjsjt#kISUAlL5*YUN}k8PcGcJG{f+n1i(yYkxJy~mEN zy?JWKt#iAdU)%fY&ff3mj$ONU?%wT_ukM}ue(&D*=jYzPy7BY-z5majzkmPY=daiQ z|NZ+1aykQp;(u;G*N|Xm#{gF&Jp*P&kkC&SP9p|81|3!gUIu9fc?JfKe+;!8G8zI$ zTDjPT<90k~Sm4~Q5Vhrn<3@J=Zkq(1Js$)f9qE!Ne{f)8vpY|VEO#Bt$;D4Sqzn?~ zJozEOa-vJuwQtSGMMpa&6f^j?R2r-INn2!HXxPcr+Q}!<@+-n~V!NM|*YryT7oCoF z@=CS{t=;js?b;0en1awoCl`(lLK)jGY+U^2(iZ(st70Es)s5g1kSo}8!Kp1uG)HiK z#KlD~JGV>ecyxSdU}R$DPM;vbsO0ioP{~grk6WpTg+o9>N5Mehz(HXNy@U-8(ah|E zYJMFz7Bn8pWIGTl91yV3sf~j})2Bn>;Gs5w3x+@3&NBRLVG}=D<^6*;UJsX3buo+?+P0Noc@0; zaAZ+RV327t4=rHwx*1p@%sfwUL1LZqg_48JLMAija>$33G;+#wOnq1{?$MysBe+9B z)G6_=dLx?wSA#PvuSG~ByWkQHM%H({7nu2icuO3)q;&!qm^ckSG_V~I6=-Bo{34L# zWf#+Mm{Tku?Ete%3Iijn;!L=oG z#1}L;ac9j<5Gbm(3u)w>D|?-Rx!p}FjZH{L-~hwSEGac6b`gP9D-su7Nq0a=4cw!t JVWg)9YXJ7u_G$nC literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/cold.gif b/images/mood/charitycam/aliens/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..a304f2dafc4a17dcbed58de248940d271ab7dbe0 GIT binary patch literal 1645 zcmeH_?@JqZ9LK*&&UiUBjX_6jl^IQK{8`&&V7d*Go6$tunw)ObP+F7gSZAKt1;#Ki zqMpHK*^g%5Ss58q@tDwFC)*Bc@rv#AN(Z|wPp;eOvRKwd*w(aAh(htZb5HgUY|r}P z#f$gn(FZ=fyFFbU_CP&o1;5i^cS7)xA07%p`!1|KtiahLDUxQ$FiS=hIFeyWhUbtVFXi&51N8(VQHDd?>|*STUqzUJj@DFeioiOjuCJMR+;F=ORKTqGU0{ z@H`{t7%|UCxrBfcQXYy0DCMA3fN~zng_ML+axSF=8L=6}$%s>&LwpVic_b8&m`7p( zNqHnGMo2E8Ode$vBa}lZk5B>a&Oe{}?`1|M$6W*cFFU=i!)@&vm2$znjp+zLgBCTw z!9HLC0N(+(@M`PBZlc0UU3G8XoW#cs=A93Xj-%1W;M!2dS8O0YWqj_{m6`H-)4Mgk zXv<7`-j(QYk8K-=dT)JD?umbW!q;%@)8L5yNx9>7*Tul*(8 z)8O^rw%K0a1(h|KGR}6&je%36jl=9;cfhd(w%qZWJF4sRxo^M8T7LrGdAGTDy7>LQ z?`Yb+L(aKr%UcJvIE9`6=s+^GwB>LfR;zU<7u@%P>!r7CBi`e6%bmqKqovs~q?#-- zRiF9Mo2pK(7`_A1Fi?^1%~f^xp1loLcXZad9tLeoJGK`e{bDEZ z{Uh18)2eYzS>3mvo9ceXB+6#Wi5l#YTBE-@TT6JX zwpd9kzF3PLc^r*0#5KpSCe;EME8emn&=NMxJQr_ehcH9aD{FOA!NpBA?!@u>v6_Jm z5?G8=bFrqQdOlh-S4tGeBY?G)>WY0b9dy1nqa&R zeXx2i0AJ#)G2_93+A)>Ua^sZF<~4Vfbr=UNgU)klm!F7jtQU7A_j~)gmzS{0)7e5% z<H^O=9}f?xmuFX1L}^u}M`+sD{{008f6b89JkYcY&- zN{o9_q>y*Uy}ic9#sFymA^!_bMO0HmK~P09E-(WD0000X`2-0v00sao1pom68vrW+ z00jQfNF%D4nA*%Q<&x)t*+`maMQSM6mMa{;aczI|t?zvA|F?y3p%@Nz3x=cNXgZgQ zVr|i6KAp^ll$5-BmksR#ME!aj474y)Hb29R_;I3igO_PJane4A;b?jZ31bFzSa1$; zfqGGcV+((Id1#7p3{gZ02%ANba(YRDLynvY1)M?*MwvsQgRq0C3xuQ!wW~t0wWPWL zzW|yEp1QCLz`?o4$ia`rkIa$800Gs%v_iM3zt-7CzyZLts|AGI;lW2l%hbRL00;{0hVu{kbVcy(F(|ihyrE+%tagEU=Ide?5;gTwtzsBLOX28 zp)y4)0fCNG)^JgD>r|~rN>r|h6vhpq8w%1`!6Iizk~HGx_%u=yB#&YQ5E$*Tpn%h* zK7_7_001HR1PL+#1^_Gp0096W04V?f1pZJ+VXCc@-kpusn}>zhSCS{1PAaQ<()faN z+P)Tz@2DR7Bp`1{EbbP_g(8_W8Ws#k!$GY|6-(lRI<;1(jqEY%EjP|$)waxTFx*Hr zyX|H$nk4dE3Vz#>3M6ZEXKr9qiIid zP>4{dfC{6E1*Df1P)wmoe@KeEin5rCNtH;dyuiV;PYD3a0HO&?NxTcp&3Bm7)XkQ< zyV%T`ffh*s0p-hyfUnr*fXL&^=Gu1!i_8J%c;ZX;_W%j=-s05?v49k{0|%Nx1AtH< zI6?cCAykNj;emdM!k}oC&7Ze#MgtruQG+g<5|ad|AQLn%7O6#w2rQ5(a^*%(t`gAW s2BoH!LVFe&QSheAmp@LPNcxt~2@{@4uf;@QGwFf?SgS^DiXs94JFc=wLI3~& literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/determined.gif b/images/mood/charitycam/aliens/determined.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6d972fcdc45ba7997f7ffa8677f7ba150fe244d GIT binary patch literal 1221 zcmZY7|5K8800;2T1J8p9LL{MR(4aKIE6y+2wC44Igi7B?$y}MiLN9&PBk?q2ZG3qo zELha3xt*J+nPyg4SEr@Bhjff9>#SvGyS8cJYPMRt+RCok?8n{i-uHgL|A1F!wlXzM zw+yTVBTE3l02Kh^ZlQ6v*oX;@nAm7aG+|;BHs5I`W1`8Jh68|OX*edwP4iLVIPS#c zPNT|c%5ma3oh|qor}1KobEvb^fANfeXvpvPzmv;B37C)Y9evX}O>Txvy)H?TK!yMS z!dW;p2`m9C=06a;AL<-Pr}DDgT6jSSJzmjl(D`f(KF#TNKad~dCad(RiS2U7;*jmZ z*NGj<`em7`;izLLt{tZCxcu^ULhAP2P0BW=j}v&7H^+cbwe zmvQdfNvP%p+ks_zd2ek9qbWCkPW#3>`&6tCJZrP!f6oe^^AC7q0c3_Wh634*tps6X z<(SQtY=HqKG35cUC9ht2$HuQ>=}3_p2SCDb?gP8?&qojvp4#2+2otfs0iv6)wZ@rS z)hJn9?QLUlg58^y_solmriELm|%JUUnfzgb9G;3{CarDrTj!B2&s_d)BIY zyHDT1kL!{(9=f!H@|2OXBYS!6odWCEh=(|tg8bDE^I8|G!Re)qU*#g?pb9%JbwpID4;);c+fz{6 zN2)u{F1*(3J}Z{?Optn85uQ)p6QUjAiGhMk@sCv8zR zKBh3Z2?hP;Dxv+X@?b@OT7(t$&;}&`ycsX0^hJs`xW|CRcVW$wVy|gi?`SBKCvdEG z%k2zoSmie)mlb}=j2573PcK1RyducoIAukycg6|s4i2CY`LlGjSCIP$4j|Q$PV*I+ z6{bdrCI`)ZWudHiQJ0(hs_6bzjx?)qN>bjW9cIis(Rt$($J0AzlZK|o#g=1!WzqmV6Lp`}qTM~hK-Q_DO9xcKQZhh!t>=8VaOR^Izc3RRH z;Z`KQ2l18~L^37&JY-hZDgCCHcm+gZ^CqVuy5cxg^QFZ)DVq_yUF;E aC7n%4G3-p&dBx+dp5l@C^&|)aYyJgaSJ=n^ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/dirty.gif b/images/mood/charitycam/aliens/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..935aa36bfd284b6ffb15ea850c3ad2fe7b24da34 GIT binary patch literal 1252 zcmVW5u{{U$KA^!_bMO0HmK~P09E-(WD0000X`2-0v0000i0ssO4Apj@<00{m7 z0SFu@FoMAd1QQxe$WY`NxUghU4o0IM)yb4$P^nTka6sCV zWI_vAv2M_SVS|MUUI&5=n>9lQ3}=^yBsi392M$ojlEpwlf?SIN*Gk2!Rj-D(a3@G; z@Hb)Iq8lP>FzgoY*$ECBBK!*h z0thJZpiwv}l^#w+dEfy6L{Xps1`{SgK?fdw*Z~E6`4^l752ok=Q47pQz=<-3$X7%a zAkYAc9dLrP|Fu_nb5p+wrSAbO|2>9C`T=^h+KHl0as8>7oVm_XaNSeijq$a zRY1V5uEJE)PBR4r03rDV2{Hfx04xCj0RSNYDF6Tn{r~|86c{1Gz=Hz|Dn!WepuvU- zArgFukfOwk5ivqsDAA%uf*%2Rbm(zp$B_janoO8d<;s>AO|A@?5u*hPI49uTS)t=a z3mP{AXKGGxGzR_WJ)8Qey7${{EQ3=|~Tt=SeUT)1U5%%wX)LW98~@xIlnA+h4Q7A#1Z z;GjVQuLvn<;LumD=?p>TGM)gTbAkj0rXsAs;R0Q{nK4{Yoq4nC*9Ht6fGm*0g`E?U z>$LC}L-Gd=6evi*U;%6fpa%wqV4*^V)((>XW=`v%`ho@!yg#U*lOcr!0pbU!@PI)B z37I)FnC^gr`~ae5ClGu8#rIx+6inb5bq^F+!Ex?&S0I21=rlnB2q;iNfjCt_8~|NW zFq8)#05B8<3OM(gh$NQS0R?~wSeyhEbkL#)LoJXQ0W7w7B47|zfItH_dJrFu33g}W zkw0DlfkX+i$Ycc$IJaZ~I9AZW22a*BU|>Ds*g*pmj7Z{(0(9`*T?bWQ!DCN__Y?&K zoJdkb6l5>~0t6U<00Rk7uwMamiU=f|?sag1V+jzD0AL9?Fo94w`NYr!TItn*j9!L@ zT2>d_bP-JMVSt)^H_28JqNP%BQ+Xx}dMD{!FOdpj Or7m^4Dov{f1OPjG)7>}# literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/dorky.gif b/images/mood/charitycam/aliens/dorky.gif new file mode 100644 index 0000000000000000000000000000000000000000..2fd9a40afdc30dd95185b3c06f1a888194043e65 GIT binary patch literal 1073 zcmZ?wbhEHbRA$g+IKlt|*~t>c$%@6vn#I|Q#o3zGAY@pbZP}7-TU~5eS8CHz?9@{2 z)zSh)Ej@)^J=H-yEkP3-q88RAuIMS*JhN->@;S%Wu06JOMHbEtY9tFjP zElmQ-LQ4uBI<YGw#K6Gm35wSY9 z#9*=tJCB%7$cf5Ni;vEeHOqOhVd0_x4uO)YCnqPZ^yZP66DGlB+IXcyF*@x;*VUB) zTp|mMJQ5bXIKW?EAMwDzY{lI!@g}~x3ku#gGPBAY5tR_vV_zt&<>RnBbp0a^fj|Fr z0~UN>XP9nyIF`fm)uXi{YA${a3Fc^=wquNj9)>oVS-r5O6GM+J95^NXQG1+5{FZd7BmC z{NEYM-m*Pdmwx}Qu4CKF=hY|X)&Fb%`0eg=hx(rf+u|BuJDT5f7m_$0*CeoDxuKM9vq*f>3z%FDVFu7D@O2mxt^PB}2!!=wD;$qkg z3J$PvD+pX?k=6OJs8Tk9fiap{#^4^~$;czuCrTtuU<~4nsaVn{F`?yPm{O4B#6GbY zgC$NDU6u2bEDbkA&&m=ixm(U6!jL|vh;PC3xfS=WPnf~Th#arnqwzX?;?)`eu}q%N literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/drunk.gif b/images/mood/charitycam/aliens/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..63c46297b55eeaa06fb9a7f76be164365928d13f GIT binary patch literal 1701 zcmYk4ZBSEZ9>s6o0|}6bAW%pM1_YD{5!(cW%{wHDgg_M{orw(<+N>J5IHenhNx~H< zdxaF^Xx6(HgtW!kIIt!4rDi4=h=ghytY+M8Cxexmz-~7<>rAw}HGA0)JNuvCbLO1$ z@tIR2m+|;Vw*w`>vt9tb43#QFtzxOwEVY)UMbWWz>LRtONUJT{4b(=VJcBjr^*Et-Z-43GaaDh&{!C^HxyauP!;B*;WF35@EgcqkeRMdRUcJRFUMQ4@|5Rz^~-&TBWAnOr|gnMA}*6GfAn8?!myg z)SOxH=440dyEVhi{N&q?l=|xO7Os8&;BM^_BLDK)z5L>~#lo4y!y!>Kqt;?spB6$_L`Q2ytv#Z*>tGg4^t}?1lMP^&XvZPE0`9k;Eiu1|HnSnIwix_2WN||FhuQAIjTv`_@L!B+{4zzee(J@i=YV zHoqmoBb`3S7HEvTdkbfC-a7HX$iWe3FLKNiZ2pgZvZ0jpjirF75>78^o^4xxV4qDd zl*1c6ERlpjN-U3*H!k=_Bl6MLJX_bo3tG;@Dv2>5Fah|Ase3)2Y`;s%s_bWfyk)`n zDlM;7IcH2Q)f@2@KkG$FRgVLANQLg)`44L%V`dWWkVZr)(dXihad!dkL0~!{Brx2i z_>(&|G$A2pOppg~+wyTqdxi@=xMF~XPhtpG1cdz6LU9^j$`TKk%f>vk-K~e`M)xcU zB-DzZ=GkW%JYgR$S=nMAz4IjZ8JwJb6vDQT7WSnM_-J#aBTLibEyvdj38}Wf*gmJ` zxqXvVCNz!}R@}6-C+?$WxwE1)XbprtI_TNUS69t;+{sT9+(*AFD zSafy_py+?In;sLIGn0$6FY1qq`%)+caA5;WYD(Gti>*ib)H_1nqu*+yvn2xs^4_MK z8>{k>lDb3i`!faiFHsXX4JYnFleC*!e|X&a zwBUY(tC9VF?OmQ?bbEEjsTVaDS$~V#^#C- z7d)_Nhq(L3uryI%1%pp+Qr;QiHjSG6%LGNPrDJ!Aj$lwuBl`J;c7Mn0_=(zg#m z>o0{F^;r+kQM$1fY)a!24V@zSl!aP1Cu9RQJkz;oUB=#ty-O}SzK+{P-xv#?A22rv|>`_ zrD=zc9Xs~_(SM*~#sA!Xt|7tBjsdPldIrplKob;yvalKfX&oSD02#}`@=xG|=jy!{ zug~uOpP#dX-EV&3snJ9Ks};Je6twdDlc;jfHp%{}qV*8*)O z?q^-IVrOh=_X@L#HzM{2e&nC#FvU3TF0aJ7btiL~uP-WCRUgP(mSVuc#>QeO5tbcQ z)}L3|&ceoCEmEsrkTEV+QRmr;Wv<&u{18UR!m(wrknG^HtoPHy=nH<>2Mx+sYSg z^Y(*9ZB&}!7sihUcYgo9q4+@H^~_DFOiw}&nw}Gznacd8_C(8y25s9#Y#J9dUYtGB zXWXVyXguu!o2Ve?l$eXbN{zybtNrdICuE;i719el7!`QpKm(I`s*r?~NUN!s$7C&5 z0Y*eHvNOmsh%vAMgHct$z(Lcy^jWmDNQmy;P4ZQR&uN+@ck^ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/energetic.gif b/images/mood/charitycam/aliens/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..e5e853f7bebc0cd410034f2494de3d594aedc776 GIT binary patch literal 1937 zcmZ?wbhEHbRA$g+I3mlykj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwN!ic6nphl2lccB&1p$qI;UlAPx00{J$sifJ+^i2vAuhb9Xs})A?W}A{|uQ7 zAdtzR_@CR)H6+;CF~HSG&w!Z`D5&_8g_DgzmO+P=ftNv=L7stu;~#@Hhm1ynQ%kb| zpVkzI4T*<2#q}~~coZtNaqufy)Kn-sAMF=5PPr2ipmd^N!XTyNz=ek`lhqAlRx~6s zwX_>JrX5H)=)^i(iaqLtTE$s{^m z;%bsN30R=O*vwig=@IcOp^1gFNH#?z`|`o3th{nHVRH?fniw`PH>6!S;FxfE>da$& z4d0Ag?rw-R?qyiG<|+FDRh2xQ#^%q@*9kj$G&neZelEk8mnO+*UBWuy<%Y8Fa*i(} zIj-;37w}H7sa(pWs*v$PW?S*2d2?^?fB*fU!=uM<)f<^7ycBOJ7Sd>FtY^+WHlBaJ2X7}Xmqjkp0b3Z^L?ou9I6vLG_25*tUK7=+UXm%dn3VE< z-j89G5Lh;YS7^brnHm4YpG;w7M2|+=8}|M7ciuNQ z9-DZ4J`112Hu(Y>j|B{D|9Q7a2H)3YI9QH|!;76^c;fIQk#YD8Jq|e^K;n=O9EVI2 U=yAw68izwZ4oCCh5Y30y0IB%BmH+?% literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/envious.gif b/images/mood/charitycam/aliens/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..8446264d21efb2d7e4dd9585b88045d8f17710f3 GIT binary patch literal 992 zcmZ?wbhEHbRA$g+IKlu1|C0?hErGzv$;r#f3kZUOf}*0LlB1H7le4q4i-DlJy1J#M zr3VD20Kps(SPBGN*KXar_t?2}=dPW*cJJCfAb9`&{rC6Zf#CoD|3K3f|8x7fh6Fo1 z2DlpO889<~gnqKH8Ubk?kmVp}FmU{1VC0bT*s$PWGl#HN%!v&P54Q^_d(H9KxaerN zgmKoL6B`#FZxWO;Nl*w<@njWK4q5SF;Zk-!*|<0j%fO|lrx}=MT-cD<%sNppcURBN zh3Ra(;yNm-KMfA~PM7J)J1{{}vz1#>+Ul!-@bZgu#f=g+1T;Feuq#V$+VfMiIeNRe z-kK#38de@!8@DoP$A;@om$-yAJUC7|I5M}2R{6bMeMSG~rlyO1J`E2H4zY<&nzS^a zEVcD`+C{Ojh6fIe%+q+yPAFJ3z2<1vEa0=9WWvP4#=)a7VOIh(m#XB1oDU97Eho0- zPd`>W>)_KvYT_CJ2M!!$zRtTudpV!%i-TpLRB5{p7O$ za*Uo^xcFoe{QqzN{9ee!;eIu{!10E~%yJCk6PeeYfr(XuK@Mo}Tu@@Q zSO83{%xqdJ5e5yw#L6rabHhOC2&0g^SV+f3MWqN;s5of}n8Op@{} zE4eB3)U{1Lcvp`_&@$J4HCsKF37?jqm?zTPCF3Qi>a;9iu~+M@hJzt1WvycFo-);H zTNk9=keZda<^VUBCPM|oH>b$0X^&4$eRbgAo!!i9-C9pfU4Nh>nDM{pnJESh^IJLD HSs1JVen@|= literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/flirty.gif b/images/mood/charitycam/aliens/flirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..0371cde140e76a1a58ef728fd78fdb4f61607bfc GIT binary patch literal 1024 zcmZ?wbhEHbRA$g+I3mZukj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwNwLSd+gY;_Y9i<|Nm#m zWB?+?|J;7AA;Hd$0j@@R2F#2M3=E1tSvZXt!_GIMmWC zz^ApuVMF3!E(wF286Jg6ZJZ)%7BwA?&PV&jg!6PX1fLw|k6k8g2_Xly8DIH-4a-6Tny6E?p-w6HJ+u`l?rVB^K}JPO7$7FZo%;hCv? z#jo~OV-#DSsKX84#DWMe1%LTz3m6)ixOVfWg;;EKX6F}H*Vv(O@NEn4we@TAIkXvb zSe`tz_K69Ye&G9;o4j008Wu4A;9GfB{1}g2{Woqg2ZMmb_dnemneTiRZ>SP6nb6q4 zoSJf__EqkM29~Rl=JOb&Gp-3F1=Sw8=`PGO;jUYvZvz7(n*zffmW`qTkIL`#J~>z} z<}#Imk+WcW1GA8a31f?ySHe|av2`hn9TF1-4!AQeDZMhu=b6Y{kC3_(bF(J-&V1Tn zC6>@IJ>JdZz|53smJb{w*;tU{j{_tAgfQYy02Y73rYUzK0+delOB!X&IB+4cb+Wo~ z!iotCn_Aip9J5XoEL`r`%dG!|=VhR?3pblG!`BZ&&(6&?GW@Ycav@{DLeYgu9a^QU zSUCBlR1z!}F1|P~L*M01=NIjk4V*#}Cp;XPFL8-$z1W(-xc1)qg2z$@1rHXmwhHf4 zJ2Kn+V>26=|l63$aiISjt5y^a&BAw zdESS)IV`WwiN8=)sN3V%C?a4|a4(waIj?M7`3#SHOf8L_Tfa-O^3}A@uageA;K25u zw`FF~Ia7s$F0vsz4ze(*+*r^o8X+o^A@6IzP%k}Eoso$}qJe?=q2U4tMkT)u2g_9| z6&ACGsya9@-B*3kz#^0wve-driAe~vE^p@ID8?EQh9GavoljV=_o}EmsvUBRoD$A8 bWo87c#DUc59|RMg%}A-LoG^uvk--`ORl|e5 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/full.gif b/images/mood/charitycam/aliens/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..8890443eae98c7621f8f8c0a6ae5053525d85699 GIT binary patch literal 1261 zcmY+?e^8Tk90&04vpvtVUu?{=0m>N9)X0f&!%#PfdNvwvr0^)H3y?NJU`}YqlqN%Z z2E#Ndr=oc{V|ZKq2)&7jTCEu1gzM7D>FJT_uqf!t?8p+YgRtxR@p<2U{``FYc)!+a zGG%i85|9XnAn5W{=Z;!P#`p=k$3zfeU8>K3^aZn46oMzbu|(WvlXXGZchs zWs;Qo?4fuDW~>AdSV0905DPE>=(B)I7s|W?_69Czxf}Pk4FW+*`6PaB@fCK&(sh0;VJOi~pbJ{KBtU~6`Uq&D$Y=CTcyL7hGWp@-`O@Q9v@hDBCZ?%c0$A3h{pn(vj4 z`-Amq*590+P&q*l7rw|QZa&Ck=Y2#uLySY4Y0N_Ogv*vO+GL%?hrdXY=)psHz3xq4QE*C`gu?trpBW#q$Pr_4<_-6WF zpwf8j*18--2u3JXEEl)U)<7#cw>tD=-bK)tWQe)G_p2$GUY@pAn+^5+H2TG%1T|fu zs7Lt6XXD(V6Q34@i|+Omn&dyjoXH#KOS<|x??0K6OR<7bdfmkcsfvp*WT2Hs0giiS zkDo?@sofZ)=Y{p&FwagL7a`$=XzM;9;q6BSW9XLL*^#S$3fKAkeVDq7gkCpR*cC{A z=WYKxJPg4g{`#O_VH7m_716i@hYqfC^}~Y;F$hww+)bd-cd92Gv4xL78M3UunNqrb zR|y(hg1alUsiY?>Q;yqOw5O+{Ra@6%QL2x3d;JJ1C!v;%QbXIxhAsnyKG2Y5C{JhT zs4#5vk}bw$&&jfgo0t0?%2M4pT)D4CT!adPhW7WXYup(z1s}?bpx)|5?#}0K$-eD~ z8oj*fta0LLf&zm6)j|O*5I3K{wW$BA#r8if!^!_>(GNMqe`(Q=00D9OuFF5LkIBsn zG&7D2qG8c1LU*5VsX2$^#9e$UfiHMto?8+X3;)L@6IYf)D|JHKt9p_{|M zB$O$rG!OpGHV2)b05kFh%Vc;JhH#?n%tYh3^6Q?m=^xTf0J_bH;ww)$y_8(m(Iqmi z7gtbGYfLvgl&3_P{6{YZwUOU9Tn`hf@mQNuSs%ft-$^8uc9bJ({&LJUoqLZm_Fmt+ zwQoLbkHFlIg>CZ2;Y&Gda?WC67-2-t66JM{f#T^m(k+&>DyY;KA?w)ka?jKlBicE8 z>hliDW zbCVN`Kh~o&=~r}b(Qt=oFE1>p*zu&oO`vI;y#i~j$xFhT1!|yLSWCYJCuV~sC|8J+ z5G`dM4_l}sVHh{)3SWUF+i7vtCO`F*z=h{BovRkqWqSP(Zd^GmfOQ#vY9pd8JV{wS~a&P{k^Z~O#Bno7oR wNodTPF?7zzk3}9&&wRQ=^HPl^9zkF$(eB=k`Cp~THQh?cEm_{oMqrTkC$r<&<^TWy literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/gloomy.gif b/images/mood/charitycam/aliens/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..90d64856585d6ca56a3c0c3da67e22cbb1addbc7 GIT binary patch literal 874 zcmZ?wbhEHbRA$g+IKlu1|C0?hErGzv$;r#f3kZUOf}*0LlB1H7le4q4i-DlJy1J#M zr3VD20Kps(SPBGN*Kggs_t=ROr>~v6cI(=$d-v|WdHLr1`|m*T|NnoW>5Bik{aizW zogD*Qjr0td89_onSy+vLv<}E}kTV!K{xL9e$arj6aIl#}SS#klhJ}aQ1(dz!cx+sB zv|GYB>&}Udi;p)6N|_`m1gUtkiYbSzc(8COJD+S^oQ7rK($mun%rh=*NIZOoO)z&? z&&`F;{dmOmVibNF9P*tm)01~%!owz3E^#Nbl2?jqev93W6LthNI<>GXOK#f38K%>= z-77q(;6RAt_4OgE!?t=&V`Al0l+<9DwZZ8;uf#XCtp_6B#cxp-R#2$f;K;gK>{M3V z%$;v;PUI3%un0K7@U)57=uhtfE2f0~^Dc6^IoxJwWMuIZ&T&|%!aRvr&SSy{36r-M zIe4a|H3)1u$+}R|qT;|V#xIY#>iETO{yEV8UVhy@|GEbU4l+IA5Nr5D2t=jjVtS^LO86_nAv2LxdXMs6Mz~`~RgmWBJ*MM;Wm9;ta$Zb}Ml7!`c;R{Oz^F?CHLOlwTjyz<3&>OaRj;>V0?S*2d2@SbD?>ry6 z^Ru!bVw{nIpMez!88}237#SoK3KCeFn3XhKDmExMGB7eC6tXd}6Q__Hn1;j{q<|() z06Lb%U;!`M%I(vXbIjSml*JNVf=Y9ay_xV3Xw<~^D5;qi%H4sEZHl^d6O zOcvCWV(BbO_2}aX++-seyvTh9U+SkXo)@1S?Xcz5Q<3T&%BcMl%4O*E7k>Dvm6*0tN{z|P;USL literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/happy.gif b/images/mood/charitycam/aliens/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ffa17530b6fa9d6a6526bed1d15755c49d7b6a5f GIT binary patch literal 1037 zcmZ?wbhEHbRA$g+I3mZukj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwNwLSd+gY;_Y9i<|Nm#m zWB?+?|J;7AA;Hd$0j@@R2F#2M3=E1tSvZXt!_GIMmWC zz^ApuVMF3!E(wF286Jg6ZJZ)%7BwA?&PV&jg!6PX1fLw|k6k8g2_Xly8DIH-4a-6Tny6E?p-w6HJ+u`l?rVB^K}JPO7$7FZo%;hCv? z#jo~OV-#DSsKX84#DWMe1%LTz3m6)io`~|Ng;;EKX6F}H*Vv(O@NEn4we{=rIkXvb zSe`tz_K69Ye&G9;o4j008Wu4A;9GfB{1}g2{Woqg2ZMmb_dnemneTiRZ>SP6nb6q4 zoSJf__EqkM29~Rl=JOb&Gp-3F1=Sw8=`PGO;jUYvZvz7(n*zffmW`qTkIL`#J~>z} z<}#Imk+WcW1GA8a31f?ySHe|av2`hn9TF1-4!AQeDZMhu=h>Fq6M};xm$Iz#oVIkD z&#QndB%)snQD{SGbII3Vvq|X28A$UPyiN#!lo&AA_A07^h+9L%s6l%v30V# zal(oT3!7Tn4IHyh6f9is*vqW{gy&_TvkNzyGQ-yoLeI|4H8T9MMRFlyz(Uc5NgZ0H zt5`Vsq*M|t7B0RxFGJtuP3ITwmJOUj5+^(ynJ;mPYrWW-z_|9_`hv$&1_cimu(k^C zQ#&%-{9`j4mxxNj1_wQ6E@35y6%LJuqS+><2Yv<{hxCc+bMAs^YMq!RbTuj7Yy3Hx@D<<>b=a z=Hb6#Z}oRx;UklK9TJ->-%E?VPz|{E$K{!Wrb5PpeTTE(cNRXoSN}aWfsut-HB7Ei z#6sa-17n4|BeSG}g+Q9uSN3>jp@Q;zEKE5MBArD-60W*0s5Lpr@I80RJQfat1O_Ia z3CA0lSl8^BTcJ|9VJ>T^s)Ga5Bh?2DEJBG_7CQ(nF$rPT)qS}*im^t7A;{a)@+s@} n-X*Gz`iI;ir^RzknHj+<;gB|yDbV4-?CedM&m5!JSQxAU0TGFc literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/high.gif b/images/mood/charitycam/aliens/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..9374646b7e0936c52487cb4df69a493b382403b5 GIT binary patch literal 763 zcmVNk%w1VIu%70K@W5u{{U$KA^!_bMO0HmK~P09E-(WD0000X`2+lR$#Ufe z3Kb|!M9HD0O_w7hqP%%?1BaI;9a`YYbAtv98!Sv{IFxA53>h#emAO!*(+(VJ8a)b9 z0@Z{~Z)WwmRYO#%6C^nJdeAD%4RAG-g(}s8gtQJ61U*P016H$8p{4{Z^)3Xp3KSg3 zd9VTp40SC?hD^6G-o%OzAYe<70tS*3LWi~h+3th}4i+p>(13yB273!qm;k{-g$joy z)Rx@ULF)z&ZU>*hc_0M^0g?x(@Bp<}yAm3#Za_hK016sn6RaS?dh+8El+&J0ya0mt z3ZD^ruHgN;0^$=CBv`=SddQgSL$<%Z0E2|Y)p_R`ObJmSL4DpaAXxzc3W&i{3007Q z108taL2@2+Fq>@^Vz`oL7(lSlY!q}DK!)7;XCjIYY#`!7F?rRV0~54I!2liL)({02 ztmU0<0uu1yLw!+@Kmi9N(0~FINM`^A1eEw-L{cJFfC3LHaFqS2>^^M18r% zk^pF?sV164VvvCb$_ZfMoOI54L7NkRYuT* literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/horny.gif b/images/mood/charitycam/aliens/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..609e8f517408f52a84068b29994986647bb9ee92 GIT binary patch literal 2064 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/hungry.gif b/images/mood/charitycam/aliens/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4dad7d5010e6ab9a9546c03620a8f0ba595e74c GIT binary patch literal 720 zcmZ?wbhEHbRA$g+*v!DdkjcQoz>u9RQJkz;oUB=#ty-O}SzK+{m~V5`R2=gv9%{5Yb#$zhF!$=oCT^>a2%FmS@iEx0<37oI@e=RhHEYvv+_Ysgdi>y`?JB9Z?u#4vZm+uW z?n><0nWy+Zr(gTT_d&goXF5PUn{Gm z11S_48Tc5)8RUVXXdu9#x_WPg)vW4JzY~?R7L!!Lp;(}Ez9jd4#k%)3@Bcga9BP;$ zn$j%k6v*O&WC$w*JA*KTD%_Az%dX!g3eRI_SxidDFyug-(bZ|+rLZnZw@OLK6r07eT-@M8=*iSMv$Pk?*)T(A+pmQ|j(7T= zGjp{cnHIFerch+V5>4$RKQ?G&&9K;6^Zx*Jf(RG%iSf_rYfAy7T703V0ZJ zN*W~V+d8|tdwLscdgFRI`U<8@RbrT~D8W`asb|8B0+z+gmaka3Y6Yj{+F8BpJ2$b- R?quU+THRJwE6BiL4FK7}Aie+q literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/indescribable.gif b/images/mood/charitycam/aliens/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4c41bd185a3b1b9984435b73c198f1d9cc9bb4e GIT binary patch literal 2433 zcmZA3c~leE9tZF{$s|k?BH0KDATMDvY#I<1iuxu25fC+|f)P;zQ3S=BidF>CnPei= ztx=JpXiab_KDVe?BTAhBDr#+mB2pC^1gp|kaeK9=wKlk%*S`DDJ!k%ybME&u-}{@1 zsmXEiIYA%_w1B~t7M-P(>Xgwsb^Ic=a*;Z^NF84^BfdCGS)@~z>e7fs>e40ZiXvTU zQC4MX!4{&Zk|^4_VadK7Wykg!&!4bfbT)T)G(PS=|E#a$*ZcP$Kl}0Z>&LI%%l&fc zYu1zr(?3j9s3yb=ms6p^N58?08227Y18m?2{sjQ?Cx8%tnOO-V9{l7A7iLK;7Yx@7 zplyjBUj83wHKHDA3(F@W?~X;0nCyv+6T&k$=Ozyc8L6#4?F=$i1tyq@?LAE;QC>XJVJB$bTq+W3zeO}1LZs>Pp#YZ3#K5NxxD(H%i;}LN7$KT^iEz=avOhE zvPxTOAUw8M~<&y{~4p}JjNMm(lW zu#wb1ClBmeQ*e?-E_s&vD~aD3rN<3G(&9bMD+QenQ}Q_wb%;XcSQ&NWLKg@qe$X~o zAkmT#B9nJ7q{m9g$--s(w!pr9tv4Z-M(&^-olPoA!r20dF0O2c(govILbFnN&p+4r zj62|@fYLA6ER1GTdJM(bbp3x_N0A4hz1__kKjgb2Zhv(sOU$T+AA87n&k6!>xZ z$VJ`XoIY{?J4@pFfXTinQCoCB%i=6{=^D7ct(j(w!~i==Ua8kpXb0hYX_$N#{^S-- zf|{KcDRIdw_@yv4$Nn>&xg$Z#!3zoa-=})7RH2GK`0fS2xR(rv4rX|-Nmc>tA7p(M?RQ>>dQO(orYOb9Q8}5y;!kSU^j%ipB`%SkxSii_Dp)r~}JCSBN0&4S!$& zVyQ4}yU}HO%6(3*do@ZAe#h`0n0%imj=HnvUsq_0C<2v5c+@Y;V{O@A&?=$@V$D6 zp?p2hqvU}LPxSEg;-~FxeNtP#fs&wiSro>Jo`}zu*iX6pCRX{zXghy1OK3Yn<1Mh| z`1~vDgmO_NQm-p#CvN=lEaotnnBEfPtm^6A%TgJ#& z+bFbppV5Ub`RGS?tVItqZ3#UJBO;{CnqBB^%Q&oD!E#- zV$x908#sN=$9e}fBb*S;TwL4Eo#f-WHuqhd-?74O*0A@iDN+i7Q2F74;sNa-E5-7b zHRL@jmv@#NWM#c)^`NOE3wZmKpGA(EN0NLgZ7UkznO^sn^$+;gvF5c_>c;-Jtii?~ ziSRdV-W=0qfePtIfLzsxJr6gr{abTe$*QPZ4Vhi)YHZAs?lYMY)2ro*CL=wcA2H_} z`?21O=AcPmq@O?IIhsEV_yfkI<&G!ZJNOG-3*1-2$f z`2N~YKN|#=liHIovt?LccNgiHupSMPVPMx!i~AU&`KbKB&M<<;cM3DjmKC4u_sQ6E zSdz11|SE_oy`W z&L2ajf+W;;kPEEIww|ha%LPGy?-S$>-d(FVgK;khQo=aG56{kb4h9cYgV*SJlPLOK z@Z8X)^$(uIhS48B-ux+s(#+E-fT9+m9iB(ofEy4@fQSDArTK}EcL$5uE` zKhj;>?^moR$$FT1WLRaU1^wzg!j!o7Cp6#&*i+I+*wEo!4BnAJSnk4tY*On8WA}X>2EMTw6|wU)E`} z)t)c+jhQ##9I&4Mj4>+DZpNEaHcCFEka|4i5=%a!4i;ZGT&)r2tv;*YYWQ|HYGe*g ztFLR@ld?5@_T~Bm*S}QlN!yin@;^5YYECTdx_t8B&7)|ThEsFB?kZCd>K^~@Ka4#> wXBy^oIkI*qhpDP>V+tdkJ0P4qX$D^IJ|z;`aLRp3iZrrXKmC_px|=!SFUAM1j{pDw literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/index.html b/images/mood/charitycam/aliens/index.html new file mode 100644 index 0000000..60be41d --- /dev/null +++ b/images/mood/charitycam/aliens/index.html @@ -0,0 +1,80 @@ + + +
+ +•• click for background color •• + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
anxious.gif
artistic.gif
awake.gif
bitchy.gif
blank.gif
cold.gif
confused.gif
determined.gif
dirty.gif
dorky.gif
drunk.gif
embarrased.gif
energetic.gif
envious.gif
flirty.gif
full.gif
gloomy.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
indescribable.gif
irate.gif
loved.gif
nerdy.gif
okay.gif
restless.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
sore.gif
stressed.gif
surprised.gif
thirsty.gif
thoughtful.gif
working.gif
diff --git a/images/mood/charitycam/aliens/irate.gif b/images/mood/charitycam/aliens/irate.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ea1a3adec0a14f0ad1f67d204b21aca35dd86f8 GIT binary patch literal 855 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 VC?Kgcj2>D<+b4Tci6D^uzW}|tUA+JR literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/sick.gif b/images/mood/charitycam/aliens/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..db952ea397c6514d0b5b018d2be0481a17f648cc GIT binary patch literal 3064 zcmeIzZ&1>A9Ki7(e+4|y%sfNq#Hmxn&Y2bDFBIvU17;hk%Q`wfr}oJ=lZgQy=)i?~~8n=h5fE z>)zk=H(7K>{wqK%@Bn!J5>UB;S)2%N7KO{B2)GO$_tnCJ=#q~a0>Nvgf`jEHM|r%| z($bS?IYT61h{|5K14l)IwE8kma~VfgnR=!En4~VNS;T3UajuK9TBTftj3;U4ec8&B zDR>H5rAETkH^10p0_!c=H^%Cmsb8+UEesKvhJOcmicZ9lbsg7 zFAjxxzFI=#{Wm5J4IqFZ;AH^7tpNyJaFlfjLnM>Jj?-)8DdMn?U=MRN{fiL)v$QIQ zb!ez@Pq};8Xc7}e!QR#AqO0QJpaW-QWAG^Yrb37#Kw z)R#p#pR=(vdFMt$ z_cl)pg$UgH;Z=9r^*BFjri}inaj+Hx?+%U117@&7H*_d zE1flqrp70^aV89!BB>Ei<-!Od83)&5iBB7lCq22vHPv2=T2$r{JuryK39-V+kc1YY z6x}dgdnptKYpN^3+0RE5_1gtA9QG4zMYe(y!R(_eP2gnXF|WT?9cAc$u8#(^7*)(V3C ze-l7d&%#}5mjapSzNL?h;cM?7e9L`%fE5&@HnUKe!xUNfQlrhm>gZ5A)sWul1Q{T98isnXzOb4!e9Q&u&1zSdp@Z-G lPKT|W)As$zg-~rI0odK2R7vZ$&K`F63{hP)=0>a%{{`8WEWQ8$ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/silly.gif b/images/mood/charitycam/aliens/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fa7ec61e677544ef79d879f0316d6cd6ea72c08 GIT binary patch literal 1046 zcmZ?wbhEHbRA$g+I3mZukj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwNwLSd+gY;=M0wr|Nm#m zWB?+?|J;7AA;Hd$0j@@R2F#2M3=E1tSvZXt!_GIMmWC zz^ApuVMF3!E(wF286Jg6ZJZ)%7BwA?&PV&jg!6PX1fLw|k6k8g2_Xly8DIH-4a-6Tny6E?p-w6HJ+u`l?rVB^K}JPO7$7FZo%;hCv? z#jo~OV-#DSsKX84#DWN}-MQ)(I*yD?tS7SN&#c(cT*`OD+9#mEvFSGF4a+SN*YC;Z zuy9?s?s&gpfnFo$tH;sqXC^Z>vAsN6tkDy>|IY?72ZMmb4{MjpvGSFqFQ^bPnb6q4 zoSG6+ann?xu}Z{G;Q-q#)0P<_k0XyqcHH7MxERRNYRbsOBGJH5Abce301LCv2FG&c z%7n$NfvOG;Om|fuG_VNyG9>m1MU-A<<6Sdlu|r~_zyWv0C9RJpTRqz{dt!Lf%%vVOiDTo~~vgb|Mduy_#kqU6N$1{uoqm@U6q!j+ zHeLrtX3O$~T2N#*GAAwzsb(y@(7+0Sy}Xw_rBU)(|2x%y2FA2`pvXLObJ=WrIgvDAWLg6N5~Pte literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/sleepy.gif b/images/mood/charitycam/aliens/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..1d3f70fedac09e9fd7e1438439936e7a823105b4 GIT binary patch literal 1096 zcmV-O1h@M~Nk%w1VIu%70K@W5u{{U$KA^!_bMO0HmK~P09E-(WD0000X`2-0v0000i1ONg68vrN(00{m7 z0SE*jprC+(2niZY$Z+7nh7KVnd?=BkM1mJFX4F`5qd3>*iZpNLZ?rWX2@Wn zYR`c+vv%MBG^$h!6CQj8fK@2jq-Hg6?F!+6gRfz4ZrH0K?$)kV>pD;nb3%r(a<^`! znV2pF33e4IIN*{32MmBKXtrSCZ`TKcB~LzpfF*{P5K=>!P=Ryc1`ZZ1P|$$E;@B@2biFN_XF+Cm&ZSNEqQ?i z@Dxr@us{L)b_J^;C`hoNy>^y7U%KDEz=C`Q*@3s-P5`83A9xICRzQFPq9qUo2{_P! z2Oc!%K?f5+u-k+d+O!@95)72#1RMr%Aq5ZkSK^5dY!Ko=JgMcL0}!}3!2lifmJn-q zf%lt$1bEnxVG|@!zyS#~0HAdSOh5pM4njmC29Xt@09p!wRufAZL9mxt4ltFGVR`9= z!Ad2qmw^V(twfYb1Fl3I18czt*C2owOIpuvIz2_7_<@Swtl4k0dl_)sE%iV`VWWVjI_$Bq~wR&1DYphc1$ zQ>t9aQeuS(Fd@L4Nuecx3K}$Y*vWI}h6xfTti;Kor_r4pf~LfI^yr2S946GXSfOdt z4H_(Lr~tvG)uS9XWXNEFtI&lRz9KEkA*Tfk6CRv3Sk-FSuvj&aEeqj+gSi0G_Qb0p zuU@hhDm>`xK*3Z16EtvWJGOF$oMZVyklwQxIvg9Qr|G+^+#!PK}CDo~)n`9aXcTptW);6TFi2oz)%oS-0p_W%?k z*fenPAaUOY!R3Ar5P53$_1?M5odBV+@CfiJ)ZVTfK6?c+L7+ea3s3+bOcczPpnvQw zz?)|i_%{JukHux6e+(p6K!g&)br1y!IKUu%{dI_e1Pjr};d&H2z?***IIsbV3ni!? zd=5Y$;Q$>lClLh|`~{zL2NJLoU@2w*K>`IFkU#?pOn{yN6A&;#2Of5GB?g@ppa5J7 zET$7oD?#v-S`Iv>(gc_B6o5|{ykrw(7F_n-OQFp<;RF=~ARPlp+7wq~1{@IRoD>wG O=%I5$MrKL@0RTIXhO3$Y literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/sore.gif b/images/mood/charitycam/aliens/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..935d69ae86969e03fd68c7a4c438120ef5f2937a GIT binary patch literal 2127 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/surprised.gif b/images/mood/charitycam/aliens/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef1e860e51e335a3cfb937cccfffe07f5d25d37b GIT binary patch literal 1047 zcmZ?wbhEHbRA$g+I3mNqkj=mWB$6eHlNF1THH)(qi?cP0s|~BOHLJ6Mq-AxnVRf-( zOEwTWwN!ic6nphl2lccB&1p$qI;UlAPx00{J$sifJ+^i2vAuhb9Xs~_|9^%|1}Mm6 zQ2fvB=Nc01>=@u`q-Vg)2$WF#$--&GAj6=;%)rYa%^=Uf!10g4l0!zLz^SEKfKO|R z!-mAeoZ@;JGdv2F+Bo=?ENUtgosael8>iff2v9oFFJX|^THI@@J>)@Z0r#-3g9q!sD7VIm{<<;XnmjN@Gv3c;bCDXj|PWEmWS-Nn|llj53_X%ifjv+F|T2F`FklP z4O?!Z;0 zctDmlLe;^6$xD#E(S`l1h5(DE;8h22uU{FBo}!5kjgEmrOYTi6mNW^P7NwOsA&c9D zHLb}}ETLg$dYs3B**V*0CQJ%sV?mBdZu-XLT!{tQr?`Vx{+e^al;Ii+k8;Twfd$K3 zw}~lz+amRV@frgsPs)@DjZO`m_UaRs8iX6LY~~fx;7b6;*M1H~k3Io~OxBZ(QW^mh z8V)wGFiLnt{7PtI;VhF)5y`pS_?(qjZqBs1223wDt&lV+NVs8|zATk_g>7v`bK&D{ zGu;{{?D*XLSenUWLBR!+k|&%(;3#c*&F;Qqb5DWn&Zg5{C!51(i5>d>iJL_@V87i8 z78c&Va#y~CRbLp6y9O|_^7Cw&Q}sJnp^W5JlB>GW=4?&hMB2cDvXQ; Qn{FER?Pz`$S)0HWG?x&QzG literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/thirsty.gif b/images/mood/charitycam/aliens/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3de3f87646852d6c905a3df6926afb962c72d06 GIT binary patch literal 2627 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 Ym{VuqRn)s+&{JYc?SCkb{JJ*&9X#+T2><{9 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/aliens/thoughtful.gif b/images/mood/charitycam/aliens/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..de3acbff917699d68ebcc5356511fd3a33827d7c GIT binary patch literal 832 zcmZ?wbhEHbRA$g+IKsfdkjcQoz>u9RQJkz;oUB=#tyr9`SzK*covm4&4J0kAiw&!b zEnBjI$f+mWsioSjr`YR114B=BP)|$HoR;L4mX@tks+Z1b*}HVVlyKewN2NU*bGfUA+70W%}eM#Y~jtVTdu2Z$L!&S2p9$H2%TM(KXM(n*U-A`UM1=atmTSRt@5F>tZHzK5u1v7+}18M8YsvmQ2`U=MYc zy2>>rJAA#5ya`A3hgIIZ1;#U`c9}V`u=5J>*jhYvy0*C_eBRLmCQK}QIE5r`R8Ba= zc1Tpo{hO9(bNKEKVQGVc2Hk_45a!35#TmmFLI8VUc4o}78C99{K+VZl=tR&kdJH&|re9G7RWbzN{boqt360(M

rgBbz{! zAS;W>suiwkrXm7J(ap%f$G{4N3>+d1j0_tT3Kp<8iP>nlRBTXiWME`OqzhICcH$Ir z0~3%q13%EjOmG6a(B#O?A}nT8aiN*Ljf>T+#AD+l=N3-hD4qj`4M&?<&C8x-d|Y&- zOF6h|O@=@N>l8+-BXcx2s~nmx656+AW#E%@llUZm#c+OE=rYH(JE`PkK*pt|f;0Vi SZW*mQv@C3~Ux$+a-nfvAbpL3p1&-3Yb{s+B0DNYfl zfDQ0K7x;JL0VDvpZDzwQKFT09ikKQjN{uI`X4z%MlLYZj0)ap*i0>%N>USdb_lW!Z z`!_b+Ha0eZxc|KWpA`oXH&DJFhXW4Km>#>ywrb$!F>w{XWjCM;SOWkGFxeac`57P~ z33MqtM;(Q=VsuF)_l0WPs9bDaeP2En<0w%2PxTe*5zS^+o|-C4ah@e&k&YQ$18o9@ zdJ$s}6=70NhI%c=(lu~wGIPr_3-A10IrHw6)6@5B^+~XrO1#DMCUib5Fl3lF)Mivg zrc1b%as*AgEfKi+^Ke~^HbhsIL9cRIFE!5|?X-s7R9m_iwzE7*ksEC6$b=-{^ z&U#WPY5-A+09cQuaW4^o#m%eR3@qsF9DMdZMuxK+biWR8Eo z(~3eNWc-pZbRt`#?k>XrDNJ^0uDRI}HjHo5?yw1yE%lLtvUguF+-Dv#O+rcz3vtXpo6@usM`stg zdehBlAozC?%%;Z|{}qXbq!JnrZDh?vqfHdRnPvlqbvZMgyY^ORyJ7q*L;mz5dPyYtN3$#k2rtkt7xLxk8PJeLPUs z;?@l9G?}ePZhcYb{9R-skQNsx#dP!6MQJn`!VgVmS4xxAYEJYy=Vk#ke*3Pfc^~=^ z@kkd3_rQiyel_4u;s!Z^-q`>HD-c>EsN1wy5Vh~f;gw*3t6uX;5eBH1!ervKdcvLb z$$0n$)1ea5?^8APzw~1I*YgW{oP5@{b?Rnzh~SDO#L_|Z#@@& zyY}oGzUpqz(qUWt)XMV6lX!yRSsJ*sFxh+g$Ll=a1mfKeRR+p{sS2G$P`Gd%)R~@V zO8ammiP3@5u|yu?@Pdj&i&LLa8FG~xQm1`=<DmJ;&sPz zE0Sd+OF8k-BpAg4_C(NM!T@`Ngv<{x;Kriw=k|}WVbZ&am7O*v<{p~X=`PfyiYfS< z!v7oiHu)O7T$5UV{(Vx->};-d;JeSRgL8sU&ss6N#{THxzGpY53wvEoJh-*sA6*+U zGZ{o>E}`vZd@b^vPCD6vO+Afu7=@zmHO9zb+x~G0Lg<}Wsz6P~!&lx6l3Bfo%FBJ4 zZyTZ<4BcWw2S6=v2+Z00rfZt7Eozzqz9hGp7E+8>r-9(~NJE2AC5NpL;w|iW0~KTB`YxZ)fw3v3;@7Ku8RyTuZMhX4t>gLlVSa)vou=0N z_39DEQ7H&V;&gWUYE7QXDGEj#9b;r(4_7Ad2x<~{E%J*>_7quHbxdgtc`mRrVTdjixy6`b z8#gaIwHmdb3-LZEI`69`T@C#M_6za`UTZrmGktb+oqTz}l*gCMf7(hogAUa#jd+Xu zsP7M~G*5(U&Ky_q8fahIOGtxd}NaP-`PoTz3~qE`j&N@Mr}Oomc_i5j zurYC{j*UV~rY|~IMjNp$H9bt?x9B`DEp&Yy8(HMKrcW!@C6Hz>`Xwz-!Tt1@jkEyY zVDlKX0dSljn(ncyJdTs_f#aey8S(i#}&Us?z2ychqp!GT#E_w755Q yf)tIIGEw;|z_W31=7O3`&A5gO_m0b&3LK-Gs1e)QKx(?(SWH2Kqb?QzT>b<%qzoqj literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/angry.gif b/images/mood/charitycam/bears/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe8e9b2711315f9669a0f26d2c29e1324aba646c GIT binary patch literal 1671 zcmb`{c~BEq90%~X?t=^q(LkCX(AX}bK7yu?@YCz{#xPJV2&_(vXwk&A3qY49!UBLr zL$>G>hV#k8`IO=Oura;gm_BUG5I1H>m^LO%SBt)H(aamW=3DghEr$7a<9wI#;h1H> zmh=BF>sZ>N{T6QG)<{k~HzcCQb>#J=_qZqH~K#t3&*W z71y~s@|tXHRfWh>ygG27|6cRlppniK6nKn&XQ`rQbYCE8ME%u_NIUO1ms`LNW1xF) z=qb8*%>C2wp^4y)We%iTAFpy@@iu~>V}toDiqY2tY!gnK7%|a`68H|YXg?sm;tMJP zXw@UHhWC6HdL`gmcfozTar<1=!13�v^O=2Togr^~`vH>Pk93M3SboCOiF5Mu%fl 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 UcoVGOXPds_tPf%EEXl0<2Z6~C_W%F@ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/blank.gif b/images/mood/charitycam/bears/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e9fd9d1ed46cc0765fd94106b0a698806ce5297 GIT binary patch literal 1502 zcmZ?wbhEHbRAw+@xT?ee1W}3%$%+iwnheDt#L?oU*y5zw($X@;l3`Ai;hb!zwZ&dr zqZsxUI~`+SI94ohtR?7NwZOS*iF4JK*IG2MwOC&3@w(O%bZ<(~y*bIx*A~B@viJSk zmiKFW-fx}qe(#j;*NzIZiA9+ul?uV-sVPaRMd?5lyj;9o zo@ok|`K1cw`K3823OSkCsR||eU<*r7orLC`RNdUf%p8Seh@r`exef@XUVc$J*hS?) z3rkY-6be#{ax;sIGxPI6?sCk@Q2@KESRt_}RUx$^IY+9rII|3FGlnY}6o0aC8Zjs_ z=&&;IFi0|}F)(oaV{qjVF>E-{(8wVuW;0{Lg64J}X{(kQ1r5ytie@SuD+~^@_3$Z0 z9odn{+|tApw9G_fp^8VFvU9}^1BXK_oMwghWHvlJ?A>UX>BqpJ@Z5KiaK*op85^Gk zFvxofZCz>db143Q`ZOJL+FtW7$? zQU11dR~he(RX|~_bnatd=se_4`$w$L;mr4sm ziKuwa0jmaI4lDo7c>x=g8d)~K)Vt!FP}bBNuFP@&M)kJBTWqcF78VbhKR;cgnK8p} zuG2e?bM_aW?oM!EetC2A&Fl?+)s6Sw$}1U2D9ExT?t7eRd_a!rZ_$VMipS+0=D+*Q zC}lJ4ezequwz*|2nb#c}m|q=_Dpu+&V5noR+92=9EBZmU`F*5^TmpCQi#hD_6%0-_ zC+3j^j?~4#o00g{w^slmmEE9wf8fTl(WczvP8w0c=tY9~#*tuCR$P zdekv6u}Kw}IIvaKPB`cp?s#C~w6L@X_oAb_SQw|(FjlHei^@8n8W5NCU{1f5(M(3R z{IZ|PQ-xkmi*l}GQWIcm5zBh9ki(%)shUBDQ(1^}3-Dpvpi literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/cheerful.gif b/images/mood/charitycam/bears/cheerful.gif new file mode 100644 index 0000000000000000000000000000000000000000..28a3527d57928188fb546a99825427274962035f GIT binary patch literal 1707 zcmchWeN>Zm6vuzhUU}GqJUVj&7H)`}$dC;@AZn*)BNe4|q7)L!0~`aEq_n!O5J@?%E{o`{t zZQi&hCT$sr06#>7S78TAHy{A81F6(Arv#u(=79_z*v|(0Lx5sFy$C6fkcJQhAm+m} zCw&YsB#WDXyGaT~8Qu&9jsVd>2!JLm5Gm2x0XpGW|&Z`Y$%-htaX#*(r)N!8RY zmT>AEy71m_7IL(|-Vv`~)^9qz*;J5+_o!(LyaFb=q^=@b;lb6;kuGb|qLoP|(MwIS z_oAxE=yL1T%eU&n(*Jh%>FF375*WJ0o~rGYu_ z+Oj1B+zc%*rL6u$XnpB}a&&Q2y)M!_$*F$+;fo3qD_CXy_)U`En3nFJKSqsSKa!e; zkwBw1Dm!aYr8*`~ugkoVl$M{hk&ip3^n8PZ#1QClhff^ef;9`T$ZT-+#e6mV zu(%B;#W(IT0($tPz0wQOc_SCFxG&K9i&xrjsNn#IQT?^)n5>9yxt48H3oLkRo50i! z!QUjz*pP5!Ec8mpD!GP2jk7>VqyMfR~S3B?d|bX{)m($2@L`=eYbZGB+@DsewKI81yqER%!& z19xN&cmDs3JNe(Zzf($&;v{i{ig(v%?lu~$rM;R?@6nu!_ch_$%Q^0!mP2dO9~k*HpI1AZExZ*vn*oHHnzCIVU#=}xra^2uSN z?|II}O0wp93z_0*b#(dw3lGOEr^vEVwkWuYn>O<+aj|ALoLbJa4i_nWvRSBV-BFkK z@tQxsR7w7LOc!zna*Sr8$rZEMdGOL+mJJq+35p8c9Y>ddAvlhkPj9cSMHo*?)yKic z`ze`RsT^mp($D-{GHYg8Vi_wi37xSssa`8MH^tlFodQPT(r!Em@Z06Kk|#q`vT_D) zS(eT|TU=MMVr8>obByyTR=n!K(*|t-p@O7|{)v0ZZ2YU`CwD(P8hd8v9*gYr_3iR= z$iBjSwAybx&bn!HVA%+MWVSymo0M`>%GZ=23>=0m0#4B|d?~F*PjgdXI#df^Jyh9$7{*Rwf435jeUXfb1ZA;-bwIuOKbJ@(;|zpcaJ=F?*k`>wJ;2L4lF$M z{y2$qMr1i3)}kbLlKlQg8!IQH6&AoiM&vED$j5S%3@`l7Q8)BWOxhq+eT@dLodoD>@EO9k_2ulozj C=CkGi literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/cold.gif b/images/mood/charitycam/bears/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b349097cdd1832a950493de50fdfc8bb331ff36 GIT binary patch literal 1359 zcmZ?wbhEHbRAw+@xT?wk1W}3%*_sT+AjHw)q}bx5+0xQ7#gbu8l;NCgr?tgiTNxO( zMltLyb~?tuaI9G1SWD2kYJqdr66dNdueE4iYq7l6<8`ek=-!l|dvlVXuPuH*W$*j7 zE$`R%yx%(I{oX0xr%d_2cklOW$Nqo+egtG8)d0{m#sA!Xt|7tBjsdPldIrplK(iHp zvT(99s50m+Y{ookQ#7)9MM!N72! zWq0}OFo6vVUtQZC$Lg_wdqMu4UClrHDx^ZQnpgzXB5qvRuE(%m+90Ii!;W+(MkcKS ziNA?0PX*=Oif_D*RAl5??V_}Pw&53zTn*uwc zShzVhC~)k#culdI+r^@(LtbD-V%Lea8V%hdN*WDp$1irwVteCi@z8-S>BQoGQ#Okw zeyS1%i~HqnXk2w-NvTNb3apwj-_Itpasj)11;e4PHy@wet6dOzQ=vJEtKnJthpC(o z>c2kx9?2~EWF})<>L<;Hd6FBxN3uyZd}w5o*phyQp{0(2iA^f!=kgr+6b8peftbjZ zOC%R`%vw4l&Ee&|=B}ufY}18iYO=9E+qpDEr6aAuag~+hg7hW)7r(DsCno#g_4)&B f)d!ppiAC#dJSG<%;DD5DSVxo1XtE(X*;oSr4<7|o literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/curious.gif b/images/mood/charitycam/bears/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..8e6e3a63dc48547b0642569bd2eb211dcee088ce GIT binary patch literal 2608 zcmb_dYgAKL8a+3UoA3x;P#~bd1?1)M2#km**qZ=?3?fB3B1KGq0FhTnKnx(>kU$a< zi58St9w|^>)hSw0YNabtYO8HEDk56sRTO-TMu+-ntu(>uYG>x}oOOSkb?!Oe-fMl| z-aB%``qjZ4R}cVhxB|mUat3M6AlnNFjUQFYa+b2Zq*7^JFlbEjZ_H*L6GrzXfdL`w z0st3;$OUQqInU zHvP(7#E}n!LK9A5FWC^W-Y@NO+$&71AX_9)plkk0G3)TN;r|>c&FxvgX|p#2)ks@4 z)hsGvH+2#IhL}}}aztR77JF&A5}cW=ziEPPQZJswsS`zScF1Dat%=rKrdsGV>p}&l zc2nPWvO@`_i@Yi6DGW9A`j;16YL0!K64LpC61FwS(Ksp3<@s>r7~IO`^L8ij#?VL^lDPo~mmRWm?3!!x1GiChQcx zOI%oKsqdgTB`YD$j+A>4jC4`7)q9>P#1blDg(qBoMCGP>G+^ghElEMT+qP!#A=ox% zhZTwYm^WI~bl|q@hOUk?aqCHn!3UpETn9`KG9d^!znM?S;t5e+E+>g zEk8GxD@fyUa?m0n7tPPh5&5F%Mvlnvw-8O`8c)+vULMNH6D>Rva&ovRpOcnts3J66 z4a?_?1iZ|wLNtKE@JGY4I09aw2;E%FO;6vJ0*!t!RG8Y&X8vqNrc_^PN$mI!zy!<>PFJ?{- zy1+|_as*tIyDKfnzDUU1xq$pXEdS6A*`OP{f9ocay37+1YbB(`E0)XgNrP^dvKnWV zQ|BeHPs&i#yDneXIEC$<^E}ah4kE#E;oZ;LC5L@%Eq2{UJ2Wa3%Zg$PCvcLzV0i96 z+6mJT01!=Gcf3ht<*7lFRtfy^CXXnMDJG$G2UR~Hp)B65W88~7$!iInRZx1wH)P=Q zcobsF#uC)voU}g~+Jb9N&)|^ts+_o_!^h*lvbON^<};sGeHtt*>CO3QMnizT(=Lx{ zpNR>G*|L5O=VXS3P3&fGa3fp(!`~0IHYc(%+$2)sREc0GVhFT@6eRufN#og6M~ zknO1vNczAl0o&u9x~mOu?yI+|eJdGk^|t66qGEdOv#%)Ao5o)i-Z^-etB5aN^;D)k zOxK@oZy@3dZ6T>%rKK!N!R~A%v5_f?ZMx14ZV=%RDS)MGYc39mnrhxX)xEWWSAMa% zvFzvR8FIDDkqp?D&1bgpSfHaRfNR^{$+VGP?P~W8f6(1|Wbck1BAN8(c>uuP5En)t zHOxa)FPllCF1AnZM+}WIcU@H%^^_B#FmX<4?6*vdtaS>j8j9irF|=f3Yw~K1_}hB# zZENu0UN@tU>W&(G^m~RE?^y1K^Lw?2TGBrL(p!o8sH7ZHvHEXk#KiRiFA8PIJvY{hv!qxF` zXA=IME?x2?bb_T+hiIO{?zAH@`m?>!4@u1)x~%~f#Z9+b-c-xVua!#ci6LF@>}h0G zz0i9l)T+mbm!Jk)^Q?(4%YQY0#ypL4Ux+7+^Dr?+IlS#2gzNkHy$I!UD^(~|*j10q*s z77Q2ItjKh!-_e8FdCk4sb9DdEj&Op}LVpieGB7uog!}J9;g4%@G1by0q(P~c$jq0n zkv8ygB7&}5F7IN9;e8e^NrPQ)gR?6^5zpG7G>`mqa4znI7ct0}jw-Ha#I~(}r-JG= z*IETd6;#Mg*_y}>mN7U#^0@SA5R`zc>s_@*1HgjoeWLrU;Rfr(iHh4a%s+LGfAd`O z8Tj$N8$V1w789)QI~oi?pJHKS;o+F5xqAg^;2jAM5rvB($h~gaHY*nRTw%5<(E;-y znf!xzG%v2#MNInauJ6!B_RfkLA|;&uwRO{SNKiOE6$FFhO-&$pD6<+p~}wh(Y5lq@6Ml>`OTlW)MCek($IFqOjO{|2H5ilp!b=?6ZnpbnGR3h_uPwW%3e@Bab|*R% zxqeAa=J&hFMhkiZ`E7ADHo6=h?^`{or0Y5mL$lFwa-T^A_+X*g%V;<=#gPrfQ3yW5 zJw!iStUk=n``q@x-|}v8;q9>PJ@OTk`>6{K&}hnJEI(v*zbYxL;*A?Zkh}NHwo;=8 PXWMGmnDW|$m@JJ>e>4)REJ{;5}2i9apHe)f@l0h35*$qH9 zM(xHEdR5e36|GklZpQu0c(}PD#$1swqE8s95ll8?v--B#W_-4}V)mMTwoU)W+}*Y4 z^Z%DsmigWxZhPXMs0iNnpa2dLvYId#-Y1Gt3`VmMkq}OoDPXBg3JYXeSwe*XMI>+z zCWK{Di826&cOy#cZ8ppoE}o{rs1!z|%B4pbA`!xJM38A!!K|%OGPzQLip1G)5Qh^8 zM~M*ynyrNQ>WjS!JEJuF0Rzi@=>vk+7Q z3qFVnkSy-UZGcQ6S|ZA|8fFWnuw1CfLNN@LNf)^yBocUu3xg4b5EkYMB%V1KdSuD@ zKa_y^j${`ESYVwEfB+o?0zg>++bLeVcq9VJ#?^map1iITck+%2*2>2_wI0j)4=9&e zcPqU%7P} zN((s7Hv;CT@yvs=s@eaNpG;dXKNp}P7b1M z@1`+xTXo5N=%V6qXi4oKhz5dI2QzMM=1x?TJbgb&buUVyK>Ceb^h++`dHMeI_;0s# z^lFH#1?}j)gEy2_<32{Oxw^Le3Af;$v+sprEqE^3jTbH@8FY(DY zG5L1xmeJ$O9*4nV?S-oX)ye`3M4`r=I=Opf)%B+Zzs^tf=UNUn)GPO$8(_rG3oSzO zydV7;IF!yg7*7|2qEZ@fxjTdw0s`4nUad*@PLsRkQRfT|XPhE0PV%V3_vi-kNOc2Q zwd2tm@{CeR)6&w^5$6jE_fN(SK|_8zHiJEFtk2)ZYc!r~;x#q8xKXYD<>N%yTPMQz z?}=~=RJW@&6laeu23>7&nd6F0xIwNiUQAnSjp#wZ~Uo$u2X;dMYfy#vYC}^(lPS6)QN2 zYV}t>9gusNaprkQm+dt#e@D(*6Ck&K7RWES^qTPG26=A!&J^@gLvVSqvb|3;!~2dA z;1##U1nxVflvUwsLyML`B*gkg=VR*c%N;`ZF=|)iHB`bkQl5#WAzhga7}%Y9r07JF z4`p;vb^Y*Ta>>rHFiY`o6PNtNhPX44FDboSA3XUXl}mg+bj6Zsic>|5%y_dnG?>w4 zX?u!pXkST~SIo`+UZ~xwUKpMviglkC&izz+<_HP>S*<2bH*{n?EN9<_-a1b~$4DWG z?YWM(a+%6w>$~c(rKDdmMP~5h!#m8JeoYTco-|fEe7L*O3{Gqf(REbP^BPzL@s`SMVILVd+*4{PR|{{kF|Kv@6) literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/dirty.gif b/images/mood/charitycam/bears/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..902e85ed1509314b395311cccdd0c90689d15a60 GIT binary patch literal 2396 zcmdtjdr(t%7Qpe}&Ew`K5C|~@5+o#mAyS|~MTycj35Yx_24po@u)##YA~Y%$gcffw z@)9s$-WM-Qs@ZG;FE#%6cq zmU1}XcFW;0y?IuEwenBt3G{oAZ^dBKyo?pCLLzTRc1wp}FpQ;g!^Xbc-44~c*-A6S ze>LI&U|a4K#SZPN3EnjuL^9`%l!kEv?Zc^VSUeRjv@fC=Z&=fL0Q{#_sAH ze}u`7fl{s1=qbLXi+wz%YKtY&KQ(T1Y zXnL2Ezn1S6pbMWSqlXZfJ);`hu4bfQ@B&IUS&(&J#mZne6;jg+X0TLJh8jaH?hyi4 zSNqvQ=beG-d<4HF0ZbGz%D^{avQpk`hil3DFkTY@WT;yRVwGH zjsWuNOo_*?6A=X<=_q5i7V2p^Q1GFD5x4S)Zb4X=NRc;AzF$# z_+c758az1!8qipKi;zHzk(lKqQmizynjw~|XrTd#r=8b#aMFIn8zBNjaYPBA8!;BT zSH2J^U8X0YGmzLKJnNOsmX~gTL5)hpB^u9!+r%}N+c4x>b!5!9b1I4GW%;q4Lz5dy z_HORnkTwjNW#`>i9NW|o#YjyftM(*TxaV$6itLF~2*EqqCtB;>VAMnCcjK8yMO1#F z-RFx8iIlL{6j#xpS?G*8`yRJ%u9}pfZO3~~TX=1FI{H9%^9EO!UzUFSq0Egq?3t>( za=TUlh}~PuyT5w=FtyvZ=P6h8M|xeCV2Dnk{HB`!i8%bXhC@hZIc!B^^Q68%KY&PU z&`ju+YvLU76Z=lkIT)*>{E4so{Pd>>a_#4wKMM%nk4LzhL$quW+;==cUZ~Zgb47@| z+#uc~yQ>ks?-3$JjnNwYIjXs9pL7s55a;gn)qy84{(Xn|rMgAY148cG7Kwk}&t*4G zMiSB|PTV{4)nm4Y{&T8YXZ^tqN^l9dV{v5KyFgDru#p|_L?yZY*aWPEM)L`#ho;6oSqcn#h2>Q==^?ySST6{GC z{EHlA8is#)o-6Ga3divdPsjV!FO>JKwpNxHzk2ZZ`xBo#$ytNV5V@-BUYnw^Ka+Ib zZROw6C`QNkU&k*EFo4glEqQ->ro>vlTNS^Ci=gT^@tE7ob6FW$ZQiR7o?jHaN+_s- zUParZdC?mTQo?ItnA3@Wmf^%k&_a-6;1t+emZQ%&mt-XpSb!n}tT}^g0VK$mmI+|B zt9q-?WOFe5xXKL#n!@CHV%E#(qaT<>Z3u?vY+hg)_R(yDirYC?hl_yB&wN;Yh z6iRhu@t53FHjVBm2!>zE${i16DB(;S{l(l()Xt>v^cYip#5;7I>$!KYwM^jC_i1C! zoEq==2=a;0iH}fNH491gSMP{19c?-nT^E-kz%Z(>$#sHG)5ni4b-c%Zl!VMYe5)Jt Kn7IbcwtoQUN~R?M literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/drunk.gif b/images/mood/charitycam/bears/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..948a5ad26e2ab3577de1530e8d1c054e307ebdf9 GIT binary patch literal 2700 zcmb`IYg7|w9>ynR5++8R0{(& z3un~}7u3(EGoMe7zJC3BWJUA;vy7uCug#-F<6@a~R;ZsZ4UIAmrn~@get}s1F|o?M7FQYD%WQKEm$GzEVHCzuxs57(MxVqxI$w4`njengSj~Qp zkQ%JSgYGO1-0~>F#F4?@dE+f_3;_Z(^GrIGfA~p~4mK$>PnlYn?*0PIyjHfORfp0b3U5xxl(| z@y7+hza$JdggfKzWx{9pCVZ5drc}p8KlpgBbJ0IofQ$6OvBOFEB&5Y}!0yMxDNm?9 zc^w0$Zby=_DUOG8doDRKGKNX=C@E1p)IsJ~d9dvxIvt4nCkrtW^XhdRUm$@6*_;d>oSu^li*iITHzzxrm&+A!vfw-k56%%~$$VjW zCr4&{D}_^eD^Js4fe7Y^WUC)ZI9WVc%;9Dlr$~%jnK@!vt{{Uih5cx>^)Qpq$rVUt zaBKlDEtQv>VccP9W@#3Y4$E@#;DVgItTZ@FkjaCkIje%w|F-l$c6dJ796=V$eKVBH z$wvOX_07r6Sanoj6qNEru$Y&dEs#hAIieL`^sFp+)t3b3>2MPUNE zw?_${D0Z~qaDyd4tTu}18cgj=td}eCfr7;n`De@u$itKxU!AL*(t77K0#gb-Xl8RV z{i{eV6YASo^`k3d4E8|6c+9-n^vHPs-fS13MKKjbF}=kXqMc+cB07m(PO%D% zcz?d9DDG?s8U$Ii$RGG1s+nsi)+gz&L;LFd3&c-g6yB`Izd~Kcue>xc=1|SFq-7?y$ z_-=!CEe-^=Gvy9gm;>1o#hh|CHNUIM>AgWz-fzFIL2xd5D!0aA^qh0v%T|IO+Ol}# zZta#Lh*2rRf!%f6h4!vx-;t!QjV>U-fHq^rhDglTsx;tV@vZHonkAz*MWNG%EvAY z;hK)@X7^It4mox6y4|x)kJLK2r#w8~*B%+uf8reb8iGA}PPiJIKZ@4aa7HlxC|ZZ` z$q=OyvT@$hr<-9^5KR4QZag-GRAX)UXEX=zhSfN%_c~8K4PR*_?j}+Zx#3E)k2SFn z@$VT@`e)9TAj%L^%tjoMHQ9L|ebm1=f1bdZllSgQj7|^+q{k59V1fqWnC$&@KTZnm zjyJ>)*aE=P&3GToDc(-k>sRBmcOMgeKD;%!Ua!PhQ5W&wBEJA~ucb_2Fq|-~ z*kny3qi2^345gGTnxW7_)necoTSQ)Z;zReDLQDJb;hiWof3^xGwV#n=T0&ECMmo6F zULsn%f^t5Pf!n;8FkChGec*vw5JOuzh6VQ;Je7}Uc7*%1b~n2Dy_hL9jR=~9P;!E@ z0TpH6L}y2n0C|dN(|1LoqT}89g3-eV)FQv{i5ifv?ZqaXOYE(R66)xXbD9qI(feMc zA??QkdEZeFB0+)eEHm)wJa>|w`$4)`+g{7N>b9rpp{$R=6A1~j$Nc^&ig SwD6O#w{8i4qN7m2=6?g65(Ojx literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/envious.gif b/images/mood/charitycam/bears/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..a479d5047c3eb2b5dfb528d0ceef086fcedda8a8 GIT binary patch literal 2831 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/excited.gif b/images/mood/charitycam/bears/excited.gif new file mode 100644 index 0000000000000000000000000000000000000000..7386dae45a01f07b33a9537dc46224e7a980045e GIT binary patch literal 1196 zcmZ?wbhEHbRAw+@xT?$m1W}3%$%+iwnheDt#L?oU*y5zw($X@;l3`Ai;hb!zwZ&dr zqZsxUI~`+SI94ohtR?7NwZOS*iF4JK*IG2M^>|(D3A#5W=-!;<=WC1KPucr^ZOi+$ zJ@2t6VEh_};`BrRD%nY3)t;KV~YQuq6-dM(jnA3u5SvRHfF1UN4IQQ&Mb}kQ* zhzAE)`Q)59#NISEx9+Jv?PVbuQP4hF;ES4EV1h#fr@Cp&2_D4*H}CKeUt7sq0&x8`4CD|NT9IMDp@;UdkHh;wtC-f$eV?K%1) z@n8ensm1Q+AI$mMwCl3%O_u}%ho9`buk75M#vtqR%T6jbNIdSID5(pZF}47 z7ncN8Vwrz`HIHXoBucC6yAc{ z5u!%hW7^anEfdH&@b_7C2Jem^AZG+%el;&|nF>e9Q#L zFy@4S>Fg2?4nizqL7b{=&l??yKGJtB>Qyg#{OG! zGx(|hT!->&Dk~h)Pb_g{)HtD0;BaJt|HP~JGf z46B$$L1S~fK*h(Z2MG^z?=-TiWLzi^&u>2{@ZjHDD}@6s2c?`G+5{4`uQ%};u}?5y zY+^Y##n@b9#)br@i(%r+)D)~7n|hd)PSl-^+Vb`yTPiq?-`}07nIhpghv^l^KHG?= z;5a@sS^a!M%@-zqnd#LX2ND`S@Mm8?Rkgrw7GsgXt#WsM`MNzHZ`@e>Pi_LE_3v+z zZpz_)0hP_azCWBEnZKd8;6N2)nS)$DuPB3T!yC;A*~n1IFAMTzD=r*lfAY}n8pFEC zuL^~SeK{UwbIonLox3gZ8bg!4{rC!rxh@=iTA8j?e&P8 hCe_Mv_NO>g#j};q=W!GqeLlbb7iY!-W?<}E0|1CYy@3D# literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/full.gif b/images/mood/charitycam/bears/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ad6ef35c63f2efa57edd7b63ff125d91acaf926 GIT binary patch literal 3308 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 aHUjf$sbvCFJ-YOdN~>loed2YcBmNE7sa56x literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/gloomy.gif b/images/mood/charitycam/bears/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a27bcb4318d74225171ce58e30143004d7134b0 GIT binary patch literal 2820 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 Wg6r5fa-p$ncI@HmJC-;IeDOC+?pKZg literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/happy.gif b/images/mood/charitycam/bears/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b594512ba16dc56f1cab9db3be3abf002d305ba4 GIT binary patch literal 2512 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 aDEaony$zagFFx-4d*-Dl3{Nrutp61#eKyqq literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/hopeful.gif b/images/mood/charitycam/bears/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd4ff0a1ba841d4d4261214d611d301d3f3b8370 GIT binary patch literal 1390 zcmdVYe^8Ql0LSs~^YA!+2&L$ZOcC-IPs8TCEUlY+By^#7iPWsr7Uotiw%`UTf;S(H z5(~SQOiG2WqS&!OzX+MrNqt+C)osyd!(YZ&*qWthgqH$fnNd zQ;Ti^unfSEI^e$Ecg}r%vcrHn49PAGM>*FbqugHIe&=UX(ga9xA7YG2LErA`h zup|{$2_Zp@4Mu6f02H`(qlT8<^mIQXLfp!e zc%o`nQr7M6B|X9v}P!?(M3rH<2$L0O$Yl4RP^w?b5$ zY>~&nj@-E6t2sNkOVlVkGGBSYZEpbV<)~PgNDOCVKs`Q}cQmGJew{ z$kLOPo7_iN7M7Z)C$7%30HhOiR^xi0eH5lyzIV_GkVB=s{O5gs6BT$FxkeYgjdP|v zB;he}?0T_xOy@*%L~2eeCc@ExhqB|A%2Ev=$zH)ZZBXVs}UBifyY0 zzSVXQAArKO(kgnG)-EkSG*jb(UedA37Q8tA+1XOAYQS3J^hW!Idq1jbgD;sy?RCv^ zmsuD$Qdz3h?G!Y$rC$r^NKrBxq+Q2Cb);zI8?nMx=FEN4eVx6h0sAaOF;~lr+VVLA z5eGvMoVX?s8qVnw9z;HA{Nnp3GR5;k2>LfDrVmui{}0rS$1>%e5u*>(oD_qD=?HU! zJhT@-(}N;p-lFnO{bkf^9w)B!8*Do)oR8Q3fFIGa{yK~kkt&FGnw@nVBVYc(Oe}hr zzIRdeyYT%bL-6XNU&l_h`KYWMH$LQo}5!riYc1O1JsoI*(eLON$#rW>2_mOu2~LKx$^U&%_Yq}pPq!J_E>qiRx?vq z{Q!-8V@cE&(|Z2Ag~}uZ)WNIC+1AD{H_tX!9>~4WK@B$NOHk?1x_6Ac(L)N`s=$D3 f1R1@c5cfIP3A^cm@{5;HTy^o%pff{?0kGvCpx7f} literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/horny.gif b/images/mood/charitycam/bears/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..df98831866ae84bc0157e7753828fa049eecdf4f GIT binary patch literal 1508 zcmb`EYfO_@7{|}smeLl))(hbx^0rnj0~+XX0$wOZoK$5UDl*KVr50M~jlSF}I^LF7 zE~d_IcBKh*DJl`BBwZYr8JR62l1vHSDmcKRQ7(p2vp8`MTwx!UZP~XyIUi1*^PJ!R zmpmV)?Tk+ltpgnJfC;>nO$TB+D2f2c;vr!GU_3g;i@-3LayU<-Dez7#qb#GO<-=N4DO|29l^=%XvLXpwqFM?p`Mc6T zbR^LVkxUMY|AdM~3hrN5wn|g5WK`}AERiT-wM3(kA&5++T=Yto%i$$21Qux|u%tpP z4=F`tWlPEbvIO)u1TqIOL6i@mfMCD^fV2S8NNc1*o3oloS-Z+280TSR+UIq1g0m?# zD=e2-#j)aPCv7`YT|(x;z> z)8ee;Rlt`fNFX$~ULJQqet|n|YTfmFHn5}Owvf)tY#{pj+XtJXNi<<9D*ef+e^l$k z89e5}?$q6|Q47i@KGoe>v_@L|!{{w~Nq#=kBUnxYASe zVkpvMhQqMzYyQO1c>7rQTjES-uxCDi$E${1DJAC0g);oljG?5BNsm?YPgJd&MnS0O zLHM!G;)yWwo%(}r-9op^eSir&a;w6Bzv&h}-8S?|%_P~J$q(bdhDhOi~en!mAS)EV3>od&I1xt;|R#_^{G`GESoi*tTO^&9z z4c|y{%cG}T&Yj#&nc_mwe=VFDi#kvpi59rkVsuy6`iCZB7PSLUW5l!SS_F`t8UotAk>6Jy_#rMSvUhG;=NQM*tvLIU%5IIhJ^9*FF|{idpO0 z6QXgWK7I^A*Pw=l8rE>K>d>#&IibMBmYJyo1X6oglz&X5olET67MpkUVjzC>imzw- z#vH`f<5s+2^t*L4g3h%uYtpyc!R~;ZTC)MQaO!b*oPd>f1VO*A_e;zQv*lw}8tzh= zz|MetE>E!U?-h3FPiC$sJszs;D1JmdzB@i1V81-O7%8`;ck`6wf#h4GKMGO&)bM4u z%AVesJT?O}&I@n~+EOdW;=+KE( zkh#*Qo@vfjI-Y%$lkXlm6{$4ph{0Ef*BcM;&xaN+n}5?#fCUz|6p)$Th1XKPn><(l P0UvkXupy8Nz?MG%7Hv17 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/hot.gif b/images/mood/charitycam/bears/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fd798f2b6620259d42ac339e6678e0e5e4d6b91 GIT binary patch literal 1440 zcmV;R1z-9{Nk%w1VIu%C0K^Xf00015Apm0`0Bb1#b149GDF}o@A%sFHgoK2YIRKnm zF`R2ct#eAXS^&LsLc{<7|3X5>a}dsZ5YBrT(tk15ggM59QrM19|NkNXgoNg&bMLK; z@1&^jy_EOX#>4;sA^!_bMO0HmK~P09E-(WD0000X`2-0v01p5x1poj582~Z>00{m7 z9|*+oAj5|T1Q7~^ps-*5v|^^;!- z;CP>3Kf3s00-Ggf!I7I0fa8)c0(qnbfDK?_2T;C9fd&^~iDd;oTCjnI_x-oP01Z%Z zK?hTQsR0E|F5qF9R5HLGa0!0M<^T+M=|PwmvUg^k{@He?1;O2iCX^aX2xy=hG$4SN z9YnbSnSU<&-vv!Zn%DyefTt*+g68-Dek3;FK%$^tz@?}J0$JvngByIQCYw3_wIh-D zH2_|gywWPbXGJE~W35asDP*v;HE_YQ7m!)2vjZ@TDSpuc*8!F~(ndg*UuHRAVwG-i zL28Lbfa-kBeiW^T9gM5q01XUeN8liD9|yz2!1{n}b1;N?VX4BB1cX z3^$B`gAPX=F~ky23{gM;03rDV2{Hf=04xOn000>PG5`Pw{s12c6qrFE27@0SKzMNQ zL579{1%CKYP~k!h2_axOnBif^h!Qb;T=)S41dSgvB#d}c;=~LZH*)M)@WVou5h==) z>F~kCl`K!T+z0?ehoTrK-UM0k;LfKeFYX+u@~6>_9k4ou2y)^;s2hI*{fd!bN0UZ1 z3T!#H;fDbP27Eo)up`_7HU~}|;Gpk-q#J!|j+N$_^5vz6~IB zV%({HkFKmhL4*kvKzqOq;PM3u5t>sTIA8z;p|Pp{d*~pPLU)h?3tSMo0kM1XCo60R zS-=2$_lP$LJx~Dszyb$cut9s`b+ADN{P`DA0iVIBTMocLlVA>T=8si= zY37+)qG&;E-Cg;k2JOxHpau;H&}0WdZZM^lem-~smxOZnzyZbAh+Xk ucO`o9=dpGW%f>}@4o!@s~`dZ2aJHf0tsv|zyv>V@W2WN1OPjAlTK#< literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/hungry.gif b/images/mood/charitycam/bears/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e711147cc2cc2822da3d720f37f134913ca049a GIT binary patch literal 2634 zcmd6p|8o;{8pk(DL(@%w&{hagY&S_uHf>2ZMPade$x^;#Q<<`$a;tKsTdKGf(M1ke zl+dn#Wx=$pmCohPlr~zRaZ1}LDzRxT+b>CTu}a`Zg;x2do;IzhIF@p8ZX9p!AGmww zHShU6^ZESn{P20rJge+0m!g|=fCczz2uPGh0YDl6Q3EKf!4L>XVM3!IaEOEe5>itT zKoKwvDQFm=VGWI_X+%S#2_PCnXdGc+fPobZ3Ncs$n1$3VtY#4fi)h$HiyE?!x4@^I1=SJjz={-2Jtw|6A2KWKzS18NrWd+o}~p85Ku_K zH3FVUSin(%Km`&O$V6fSg$fiV(1<`M5_e-7Hx9W8)J>}0BX(uu^qG~s1%Z{ms}y)5A)G(H0Ik+6?Md=%uPU>}_T@zJP{ z#(Xs4V=y0s`xw&4;=aUtmh^E67#~mhc-l__ehTr^u%9OU4C-evKZE-j!p~xU7WcD+ zpTqnd>F4MGp$?ExfI$Nc7GUrILj)Kyz+wRw53q>?72xmyM+W!=bbx09fq)1AA_<8U zEYh&Zs6_@58BAmektIcz5;IkceuxNxMB76ce!c!5R zj__l}LB z$Bem=F|TjT$BhMqpJLQcG4T!n++j7nzkam;yGl$2-BGStv3}ihTgeK`BC|}Am=XFp zDa8T|0eJub0(S!j08mT;e@V$$8r>&PPD%q8A1v8~B_GhG~q z!7YVX#wqb|uVwCI!Mdy6>w1ffI{Ww)q-@5T#%124*ViQXx(?^P8`rN{4*)kmYe>H< z+IY{BYek^-n%KPT_2K4=&Gwx2XUdEY5V(5s(T4X@Z{HZHKmCp<<~+1twbhtRr)}II zU-H(4us9utpxL zKR>j2?)N#x_BDFP!<+AYwcNJm;OWhd?jhkdzhF+9I`=Lyt#LdWk;KG9xdR4SUC+278p<5V5v&LpSVVeC+DjVlT$c0DCrlD>!^D^BjbHKEM!GWRHQPshJdrez4x8^?x<)3ej|hP947 zPvL~pFy)I9gQok05y`HylYN&|U9ICajj!aT_UqawEh+gcTC5Uzisi|#RmQf_esA++ z-TutI;X#M)krwlE1=x~I>>VHT zYa6D7J#FIy3t1j>7`o!4y|S!}Z+eW)^}lqh_Lz&61`n4ysPjzrfD1RY#%*8<`0>JX z(_vTl%x~YuK>eQ1;X#wD*X~F!DD~K?mT7gxp}DJra(I6kS<~2+bvraOb<+Lv;JgJN zJ3?U8S)l)T*kaG9GUxZtT71zH{6q)d-^o3okW9fEEU`=`P{Pd*k>G>*K$k5hWb>e!{+e1cAQM+8}b<{4iX;*JbnzixlEZlt7DLs&0q+WYW86I2IDBY-Pl0y>okoMDm|*suFJI{14r%UmxFmaJr##ih(amlOI{<7~fjMdj?Evcjc+fR1D*%((tnu5Nu;tQP-86_wOiyf>pw5v zGI~57Zg_C0;pnan6>@}{s=(tHMt?9jd@~Y6;DX%`g4>V0v;1~iZAsRs;9(h literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/indescribable.gif b/images/mood/charitycam/bears/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..b24559e26125aa061e1578b175f271b6b4637397 GIT binary patch literal 3824 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/index.html b/images/mood/charitycam/bears/index.html new file mode 100644 index 0000000..4b193f1 --- /dev/null +++ b/images/mood/charitycam/bears/index.html @@ -0,0 +1,76 @@ + + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
awake.gif
blank.gif
cheerful.gif
cold.gif
curious.gif
determined.gif
dirty.gif
drunk.gif
envious.gif
excited.gif
full.gif
gloomy.gif
good.gif
happy.gif
high.gif
hopeful.gif
horny.gif
hot.gif
hungry.gif
indescribable.gif
loved.gif
nerdy.gif
okay.gif
sad.gif
scared.gif
shocked.gif
sick.gif
silly.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
working.gif
diff --git a/images/mood/charitycam/bears/loved.gif b/images/mood/charitycam/bears/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..2c172c749d2e9f32d2c969a22850150708490385 GIT binary patch literal 2669 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/okay.gif b/images/mood/charitycam/bears/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..24e17e2e728e05a3518a717080e69518260f0ebc GIT binary patch literal 1506 zcmZ?wbhEHbRAw+@xT?ee1W}3%$%+iwnheDt#L?oU*y5zw($X@;l3`Ai;hb!zwZ&dr zqZsxUI~`+SI94ohtR?7NwZOS*iF4JK*IG2MwOC&3@w(O%bZ<(~y*bIx*A~B@viJSk zmiKFW-fx}qe(#j;*NzIZiA9+ul?uV-sVPaRMd?5lyj;9o zo@ok|`K1cw`K3823OSkCsR||eU<*r7orLC`RNdUf%p8Seh@r`exef@XUVc$J*hS?) z3rkY-6be#{ax;sIGxPI6?sCk@Q2@KESRt_}RUx$^IY+9rII|3FGlnY}6o0aC8Zjs_ z=&&;IFi0|}F)(oaV{qjVF>E-{(8wVuW;0{Lg64J}X{(kQ1r5ytie@SuD+~^@_3$Z0 z9odn{+|tApw9G_fp^8VFvU9}^1BXK_oMwghWHvlJ?A>UX>BqpJ@Z5KiaK*op85^Gk zFvxofZCz>db143Q`ZOJL+FtW7$? zQU11dR~heRs_oC~N8sSLV2Xqk3E6Ew)y73yTNMpP#PL%$VUf z*XbR{Ir|GwcPBV7zr4BmcJ>Cp>c)F-<&_L16l7Tv_dU)uJ|M^Rx9G$B?{yva4R&{* zGiNLaulsPZZEhJ$=JkdKmRHLev(I*_9Af+-_=2&X#WdtVInTaw#mWZVBMXb=Y926h zd{ivI#<2h5QN_~BjVF`}!XLKXDLl6J8bhyx>4by*k`>F9S{%|GW;;n{FdV9rxWXpF z=vl|W#3of>;=oo_JK>;bxZ{O|)56jo+>4IxVqu(C!`i7bEh_7PYCv4lgFF4&Sq+YC z5_@i{P6+i{5}n2Smve>#he+0og&j%?fs1;Kc4aK?;}a18W(Guba{;4UV>G%S43Fqe gZxPE{kDQ0KNJK}+%+Y^#NS}2f~O^2HGsd!E*C9-q@swkx0ae9mL}LDQR1eF zEhTOk%4&H|ZnWi(EDA~8Zr5CG6LAy6QZd_Gv>#`7yLq&`vorm-f85;6J%2oZJ)fCp z=JmXvxE-;PlpJ3m3>YT^Z`axyW<*OgXvuN`*)l@0SSeNuWo0GZ8%XaI7$ii4gkq?PH`F9e%af*+xt318Rj##mO01nV)-JhKD_=1T4g7McKeE|Q zdaof9V)pEgqA_E_LP!vhZOnTW>JSEyfj`*+2w*)x008(KAQxUUW~LpjguA$HRmj*? zRgTy#5`~5a!;to{rS0gWh#F6y^nrHzV3in|bUqxT_G29P&AG}P!%L*-O}y!XX8qvK zO7gx>003{U%Q=+&$&jh@7yw~;j@L8Sx`Y<7ziPy)efv}E9+M}qHlTfUTgw}~Z z(2z1ODt4+t>6PdN1_|F{H*~Am@>%bR9{tq1?Q36eEdYt5Z@49B%65i_Am6X`a+ZvK zX?fTf;F*6C)ItNh`0sA`Nv8Ypu^7h*)U471pBiz96rl*zV>))r%RHo64w62`9($a1 z?tz(yhGBaZPTT$^bv0h8TS9UAkk>J+xx75xOkb&$*ljV$FgK8BtVia@Es?_4Q`o-S zTxXN8LbnpptYY1dkkL77lMNZA4_#h(!e9Y#cEP=B*Q0iC{Ec)GGy+OH>|*F?DVGF8 zAC(06j_Q#s5mhOWfk`{gA!9u}mzVm|fa8DDKLk2S<%#q%g3RJ`ELtr)ODD80iIGHQ zGnVNb{zQ)qY}F+~2!8WmL?G)WO`3h68eGAvB;JFuj;H#4$~w|WS5RvY>r0|;V*C+- zqr`yv^!OKN^HHdHW1cjiV!VM^jhIZW1D_YK-bfw0w3uFj;zpiIP-rIQZ^$&>KG2gHA^N_ED z&kSU!Fyy{n`J50FqVzeZVA%kMR+j`T*_XTbWw-@6`fh-?v>`5Gnm*gQm0~ZkcZinb zSkI!s*QCf|CP^f^>%3(bU%}Emf;i&rp=kU>bLRLJa=}G}I?^5tb{)>TDa`o|zT#K- zJSQ9cwepCWa5L9*eZ}PhsojeFaM5{>~YT`CA{Sb>p2^|p%Eu$Aww=K0ILzOacT>PUs8+`K1era~G z4ZiR#JfUn~>!*dk!$+SvXm%hdsTUM62Z&=u?Ge%K*O1KFo>V^N9n3j3Qme0@3SPy#NqE+;bM#%I~7_&KB*!5wLC+z`G zrU!xWTyqBT>b#OcP9upSb{mZJk8R0=%7|B+A6CtQy3y6&cA4qO&^rxNdr?4~d-Zr? z1E;p1bvmQ?j^|e%ux((QJVU)?s&NabrWYbwWP0RJO>A58jNg-Acq?y99>ED(KPM=v zx5?)`YnxAIY!Cdfk=k@v+{Dj1t+&aGE;Q~aCypKHh>#H2s))sf&s8k^lU8?X5V}nf zzki=&V@gNbyZry(%`48}Q08BoPixZ6!g@(F3nAp6N;_xU4u?CqfrytrsK`1-4Y zqy02ofmwa+*|={KL$w{eSvnswyEr~7iYocRxZAu()d{+E$Q{2aT>6Ht$y&a$IkSqF zwOYDzn58QsWqKl@Ms-~pxiSK!}S5P^`T6z4$AuE1?Wt9?cURMcfFtZGuh|R v7tSWPacz%dcy+EWIbM$4k3uarP~H7HY|Urk6F-;HU+1-+a&oo(^MCmd`FWLk literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/scared.gif b/images/mood/charitycam/bears/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..50871f5c81ce965ac65ac12d375321bb0f51d6c4 GIT binary patch literal 1191 zcmZ?wbhEHbRAw+@xT?ee1W}3%$%+iwnheDt#L?oU*y5zw($X@;l3`Ai;hb!zwZ&dr zqZsxUI~`+SI94ohtR?7NwZOS*iF4JK*Lu9J^#t9U5_E4)^7FOD@2Bj2zqaN5+Mf4Y zr@Y@g<@>c`{}~wm|NnmkWDoTL&{)O)+E-{(8wVuW;0{Lg64K+1_lp}!UN9iJnT__J}5Fb2q>y?{gE(Y zcJGmrE%?GAq{6_c5M#A|tSH+nei4i)WifSRXpbDBJY=nGa+0$HyXJ?i}|HY8~g}W;4+^H^;K= z$ujW=e;@2|W?^IQI$!<3W8VAH%RJMH zY)|amq`Bl)-ma(HBAIowt{h;sh*P-R!SSr3F_SB{p^^PlWWlU9r?Ll)tP%mH2Uu^H z7BI4Gb_`fJ#V^i4E$E%7Tbu*3l>)rcrDS0G+b%7 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/shocked.gif b/images/mood/charitycam/bears/shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..f4497e50dc7694b4afbbf037f46fe3f3c47eec32 GIT binary patch literal 1198 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 ZW!!kYrd&~GzV5Zvg<+wSOykD0_8)Z+fdv2n literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/stressed.gif b/images/mood/charitycam/bears/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b7ac1a6c0f1817f164650a44fb93be0289f3b056 GIT binary patch literal 1383 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 SIAW+%nN0^NV~q74{QRFk@>di9 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/tired.gif b/images/mood/charitycam/bears/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..d508794e8225298f3f111b8b5eafb8b343cdc027 GIT binary patch literal 1587 zcmb`GX;70_6o&6dLK3zZ79}9a4Ok%#V4ze5m1dDuq<~a0DrAL30trblY(fGb7?rV1 zrO0MUC}KddR7Zq%Z~`)5Yqf}gK&t|E!HyNRieM`=&~`d)|MtxNap&A~-}m|Pp0J3} zje%Sb;17n}fvMOOz^8yzDo`vQ0?MSIOe%_^<$<7<#q#OS^4G(?J&Qj7 zf0<+{3s%t~@jFx>C$w_m!_o&<$N($0y7mt zC{34S`$D*#n{9ekLY{E3D}ds3$W6~)`lR4Wgiyxirpv?igI?Fjm9$ZP4dn*yGyEnVDed|W130^)L9z={NLMR?);0`{>y?z<_NI@ZEV z*&H3wniDxww2t%#M8~~*ykjm(rdpzt!n|qFh&EoWVG?v56W4J4n5<%WAn+w_-9Ec; z*}h+*rm^SdJxOC53bXYSpP%U?-pWHOF~L_0mYpmt`E{16{0J@-CEv8N?pGgt`|7kN zf5Zoj6}W9R8o`W4S1rQx`al7NHoHn=Uoyie#&8Uyc^DC3A9CRJ)fHsS-Bus=$}u3y z=hSz)5tsTYM4RCgZ&cHw+dT>!uVWkXR^^Q&gyrXNC&V%>L~i-7Z7m+egxsvWo5N;? zB_`PjU^31uDB{OTCr(&A&RPA8f*aL`fEqWoT7yeS24i@q%|nh@#*3=c=qIn59I!b@ zLLXM=ylB$YiI5|jJYH}Uf^*`4$94S4rsJxR!e-mZhU(R^O@`{o*yaX12a;)D{z?SK zl!%poCc>8B;#IHfDk9jsZ`HNxS+>@$#8R*46O1F4e!+w7{q>Avj$2k>voqWywAhel zhd{Lv9Q8?B?=r4yj4BRDn^cnAdrGhymJ!2S^{0z;?xL9=S`p?pBu4*bxp7bwbBeNA zLWbNz^juOWapYN7bIhl~_$br*p54`E-&_5jL7BR%E#$=cpVz+j>P9Rb=#?D(+C3n6 z1IGX;w1GklE`FTe@nnMJ=A|%@M!AS}^|hHNRaGyF`|ws|!X5jJo!9Y}3Encm!e5j4 zsoF_<1W2=h1&7Dt+xpBfW>K7PYN;qV>DnftZ=vrZaO-wR`|Uh6*zY~&`y4*tkeR64wWsu!@*<4>)T>c_q#=yiTpO7@;3sS3&kr1z4K0;qh>) zt7M&i4HF?uhEJB+I9HW#ix_*S((&M;a~EUGDr^h~TcbMF36XO^|*3kD+Wt_RtkZ3|jV$fn-`pkPm) literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/bears/working.gif b/images/mood/charitycam/bears/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..25cc57c28544e9f5531344708ab42d074a6efd1a GIT binary patch literal 1551 zcmZ?wbhEHbRAw+@xT?hf1W}3%$%+iwnheDt#NqGfmzS3}#gd`LNwLLAb54}u)+mOZ zRSa{ooz@n6?JagX!ocvKf#F!Oz`1H5k~mjwd1n&CwHD25Etbbxg0A&=UF!+DHznxa zoaE8J;WME*Z z;GB_Ilvz@#5L}*`l9XDM4phO*#mnWHrcjw*s!*O^nvvA8h64?a9D-stGbSjs zwDU+?wah4BXc5u0Q|MSBaFD%6Kq>0TkB5g_nwWx?nRqNz@n};Hp76t8omd!8quJ|UHHT8y@ za@@aBy{+&TTWhw3#e$a4PuJ*H%<#MGl*fC{`@+-L2@K3HZ*G2Hy}|Ex5M z2bwt#)f~TE*I>(9#mlDRVZczI&-s)2iu?59pD)!9GX6d4E?ss@FvO{m?bG%9^=nMk zCvgcZIv`i0!r&3$%=%=xB8Rv_#EhCPo*@@F-!xue=wzFaz|_SZ`b9dHZO@NKtZyf} zU+FCZJEWnKeIWLz1G`U|0mDRVDFcVevP&vL+28#=esHqYp%;#vY6TA%-Gg6+ zIc9Is{{@$o71*nX~U#4tyRmJlA>O&Pz(_RCI)K&AUI4_ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/angry.gif b/images/mood/charitycam/blackbox/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..46f88be76e0c3d5005e6848f35952dcb651100d2 GIT binary patch literal 363 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fEiK269sAF~@E;5m|8x7fh6Fo12DlpO889<~ z)cs`PG-6<5&|zd?WDsJIW?*1xzHq{GwV=~88_S~!D`Mr$s>DyWzIicAGwV>vuY+NE z53An)ci>I*&=Ip_nHH4d!NkD0!bD1xLFL@?vfn%`8=5o{HmKSke(>q?oxf&lQ@`Du zyXMgOf_$llo8NwxB*rvX<;SqH#$>cbbu#qjCL}dSbw^H#YV}N=@ zk=z9|9_p^v3nw&N7ko)dettFKcx{+w-PB`ib*!p#r}d@Pu6noZ`R-Nui{=-&Ye@CG z^Bz1VqRZIeP@*-Ji(!&_$>~-$rpQJSg9p$&!DKN=;U zgV9oN29^lEFBzK}&dxGtT$96jAdPX3ec~w*kIm_R^R?RDG=6Jh_Zz_ZQ{HsRj2>-L<@sduDgV$Dli>%aa@+jx+)} zl8u3nfrEhy=tw07agH7V#{~yjS@`*Mc1&0Rc4WfF956sYg^ey^PnXqb^l&R6&V literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/cold.gif b/images/mood/charitycam/blackbox/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..6029155aa16fb82fa735b646f62fc3be5004628d GIT binary patch literal 362 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+PjvaGy`v0GS;XfEC{^#~{4GDI33~)8lGhk)} zsr$*o$;QCOpaaq*%pk+Sz|t7tk+^DacvRQ!i=xj{=eRYdTjoB!J}bAaFWY$BS##=J+dCR+YFiT93mYZxUiE@>}viRGgE2I*(Pd{H7m!Dh_n%SIG*q8!zS3_HJAH(GOjOymr#Eysw0htRJ Q7cSJ9o3?yK8qjIh0JA5K2LJ#7 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/crazy.gif b/images/mood/charitycam/blackbox/crazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..8fbc7cc5e49a2eca6052125969f82162c2d1c6f5 GIT binary patch literal 342 zcmZ?wbhEHb6k(8KSj5Hv2LBZm6^o0Dj~zSqpMl{&7%2Yd_Hzvhc6JPKHPSO+W(2BJ z{K>*9!obF$1JVQ1&cIT9;e_Yvy%w*}?*5;k(U-E5*JahZ*A9ZtI_JMwGc-(izpL){ zjs*r90yjz;A_8Wb_$BO!F0#^PS{j&mMzfJKuknD%ohMQY8Vn+JfR|hq54?&dMMF)WQkWB70$mz>_u8!gSeZ%w*)bm)^P9 zaL%<;`wISuZgPwkMCf1x>fi+HkiO89_-YD6$mErL3fmi>gt4+^t;@+4dBl|sw80tx Dg6VRo literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/curious.gif b/images/mood/charitycam/blackbox/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f9225244607b602e19b7e2c09c793a60200d055 GIT binary patch literal 260 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0;ai6#sMkxrPKgI|jHK=@~FHg4F$F z;WT1kW6)t@U}6wpkYZq9iM?<_bJYxs;ImKP&R}gz{x)?**|IkpJOw(Z*QegUroiBE z;lJH|zvJ3c-Hi?B%5Au&?0#nGIYnx|x5L7OJD*kr<_GrFMoqj>ys<__U|GPknQPxU z&i~<1x8M8M|9U|b8+m{>3IJ_%3Fz_6o~rcvY&(O4K;NPtl?khsIX>uot+gY5&$bn7 u&*=wP;F^6;Gyx&!K zd&dF;362{j4UGYv!V>BmRQo!$nWkTP7R>bdZqvqB*92Hw4#qz(Jh9Db|3Rn36?NRt y8TM416}z^xptd^Sua&W_O(fB^r?*#4MG(maoIn>aF>nK2z#af}fkB%agEas{r%m_( literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/devilish.gif b/images/mood/charitycam/blackbox/devilish.gif new file mode 100644 index 0000000000000000000000000000000000000000..259b61eaa869666748474a17bb602dae83160386 GIT binary patch literal 243 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fEiK269sAF~@E;5m|8x7fh6Fo12DlpO889<~ z)cs^(HDX|6&;e-zX=h;RxNyRA^evL^JEOz4^1pFNLp{(KRihNNZ7yJT0b c5=3$wJA(kwjm$vDacr28xn#|jI~)ww09Yql!~g&Q literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/dirty.gif b/images/mood/charitycam/blackbox/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..32baee37ddc8214f07e74a7b8a84bd04be490de5 GIT binary patch literal 324 zcmZ?wbhEHb6k(8KSj5Hv1d57^$;rtrEiK269s3UhivPL&TtkAL9RpmA^bD98LF#_8 zaHcS@G3YQdFfj--NHZ|76ka%C*}A|Y-FxlzOQE?c5?yL1mcHrSHpAgeN$ld5Kywb%FahFM|k7oTJoNTnRV z`@ZmI?)}vdEnS-!o0~;ly*s1YcS=$uw5ylbI$)8YMpTgQY$%u>vU=PoeMFq+GtSjg$XRuz_WDIkY$ z-u)NbGX5woPhAi))2x4`-HQCPt=rGPDf_VYx?gJpV`HO2SX+CAnyzSa|~K*w_x+(><_bM^0H27sBdcU2xx0>2ij~6 E0KnvTYybcN literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/embarrassed.gif b/images/mood/charitycam/blackbox/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..e8b12a66332726ada9156db31cc772868cd1efd6 GIT binary patch literal 254 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0_McKLjZL=k{|A33hf2a5d61U}glV z`^mz|#=yp)!^ptHAOM66EPeq!p4n5CUY~7ea1iKQ^rJFi)iTEiov*ca$XCdi@oihd z%WiexjcD{omev%RCI{*Lx literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/envy.gif b/images/mood/charitycam/blackbox/envy.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa7b339b15157b3a7ad3bcd2c5c8fb9a15c282ff GIT binary patch literal 238 zcmZ?wbhEHb6k(8KSj5Hv1OkQv$slkH2>vrL{09TY|J;7AA;Hd$0j@@R2F#2=b&5Y( zSW_6-7<53IK-w8t@-Ce4T)o%g_1WG36EynfILyhI#U-M+r$A@B6T^)kYp|bnPx8Ru+&Jg@)6KnJ3WeXea^ilGY+JVK zu$QiR%>8{#){PC#`9k%M9i5#jJ-y0;NcJ-`ure?MAp;BR1s>0I7KF>#!Q$9txEL52 oI2kyAdZaGQFjQGPU8rdL^2-l$XIO9vE7mNvSP;bHCCFe60MjU2RsaA1 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/green.gif b/images/mood/charitycam/blackbox/green.gif new file mode 100644 index 0000000000000000000000000000000000000000..896e9dc44e94f2d61e772727c887f52a47b84601 GIT binary patch literal 303 zcmZ?wbhEHb6k(8KSj5Hv0xb-Rii*j}$;XZz`_I7e9}E=#bNji51UowhxEkphFf#&` zDgI<(m1AII&;jWIX=h+bzi`5H^9a0 zzr%b7hs~_bdpb{-Tl|@|Karmy)vDIB^K?az(9~wVPpj8si;$ zJkz}~uetx!iRe4Gw6>{qbSeuX+0DWr%D}_G478imz{7dv9P`&}l@TsuVGx4Kau}TO zT)NWYItQ{OA5fA7sFn9Zi>J0}QPS>GzWJ`M$SQb%Dwu#OI4-bwF6Xt#mSM0408e3C A-T(jq literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/happy.gif b/images/mood/charitycam/blackbox/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..0782a8ba3310d2ac091dda1ef02b9c5e396b63dd GIT binary patch literal 227 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fE&q=lJN6$26#sMkxrPKgI|jHK=@~FHg4F$F zVHIIuW6%L<0%>PpDZX&RbM;<}*JpSCPtfQ~*~#g$YTarFK_{K_U$hwTB*jXYZSB^)7Hiu{^EUCsrXolR4=c{o!0Nt3DfQs9QzS{ zeB0;Zs`}E{a_8)}M1$yV#-1J#!;GxS;cCi)NbX=|5N6+96NUGzmwDdmjD0%GXOD&f&m~~ z@jthpYe=xOV}PrXo&hr>NdHe3PB{i{1|22_CI$fp2?hq1hJurpmu5)Zo_a0v@WhhI z6_N9&2R$xqTVxi}`J(J|$oaX|lPAp*5XoAbb?{<`v7p4f3ol;06p2`WV~wK#L&^So z2Ibruv(GF#Ns z8rK{%n{m#(n5>11773y_ijhHxK@#YwnFS{``S%w0Or7>rK2`RlBVXF~*rhucrh2P> zywIp}Y^B)WET!o4DN#92a>*y1y>D0@nH#*w>z)czbJ^*qTqc-*kx{mD*DfJc*TRCZwZL=cwVBV)O}+H?-gez)SH3t? z9;utMIypx#XUXYbUnSa?W_woa;3toOsb|jzd1kS+tuUE2Lux_OnzGY-*%~cve1JWwzdM(sWNVnUgnUSD5KMEh|+jU-QtW z{nC%hFD?B`g0hd!{32u?bW!{fL*&}l0}gAW)&@70oqj9D!st+;qu0E@VN2CqK9+rr zO*MY{b6AU*64%Y&y}z=$vADdjw6wmWy|lHvq_eN2yqII^)c*X0iA9rVvvwvdWL&f) zA#eGL6{t>Q07kJC&}p*^PL?j)yZw>wdC8Lws=}F_aWmE^zbu`)V@;^fsVhb@obTUm zZp>KW-Krty8;~LMu1Zz>#pTZvBj$<~rB34DdGJBeN6dq#X-m~vJ8mY{9X5XTySabt zk(1}x@vyqOj60)(g{88+vbLPHtF5D=IisPmyRL<4TGNavv#0mYXPrE&f@Ases-Brs aXD?Y)GdGhlf9sa*&6{g?@7V*2WNQG}eQ%in literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/hungry.gif b/images/mood/charitycam/blackbox/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..41e5fe9c9136afecaa8923931f2071e236c1ffa0 GIT binary patch literal 457 zcmZ?wbhEHb6k(8KSj5Hv1d57^$slkH2>vrL{09TY|J;7AA;Hd$0j@@R2F#2gbw61+ zQyAD7beI^p7zBWjfyFCef@k(rrPpUWIT$qBo;+vFShdLULF4g-$5v=AD4Dfgy@1D9 z;Q(9I+6wc>T`ROi`qrtOdKq#vEL3#UiZ!mgZ@oyDQJ8JNc1x5jBf@x)n}ivpfW|im zcqFQA4GlZ|eVP37(g&(l(T`x!(@mFckA46Dzyf~<4XOU)5{gHU6ij1u zDA8KW#WYtn;q==)<{QsN3oJ@b-_8!(;97k5L1}ftGUh9fR$P}BfB(ILEg+VawI;DC zr==~nF{-;gyQ)63qkl^LG$F?DxpU?>&Q4goWC@!flD9!&0C87Kzzj`Q(?gGJHtwH# zyfOAi>I%)c^p{y{)avzY59eAws(21`mw+?SUGBV!M{~+x?(%1ZxQkN+;;yppXWI^D ze|liUzT#;3dbz&quivvJ$FQ=-)ig#mx3tDIc*nK0C3XbX^-k`e7Srw>K96z!e5-^d LOP2`)9cB#xhnTjk literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/index.html b/images/mood/charitycam/blackbox/index.html new file mode 100644 index 0000000..dbec997 --- /dev/null +++ b/images/mood/charitycam/blackbox/index.html @@ -0,0 +1,71 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
bouncy.gif
cold.gif
crazy.gif
curious.gif
determined.gif
devilish.gif
dirty.gif
drunk.gif
embarrassed.gif
envy.gif
gloomy.gif
green.gif
happy.gif
hot.gif
hungry.gif
loved.gif
nerdy.gif
okay.gif
peaceful.gif
relaxed.gif
sad.gif
scared.gif
sore.gif
suprised.gif
thirsty.gif
thoughtful.gif
tired.gif
working.gif
diff --git a/images/mood/charitycam/blackbox/loved.gif b/images/mood/charitycam/blackbox/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..8658049dcf36a7e49a2ed528a8546333dc7b9fe5 GIT binary patch literal 273 zcmZ?wbhEHb6k(8KSj5Hv1d57^PXGTWCnp~}cI-a`!+$VP{Lk&@8WQa67~pE8XTZz| zQumXEGlhYTL5GQfi9vutf`Nf0<-&=`u9e1@Ppv&S_j}`wADwBd)~zuSD9}0mKH+|a z9}nY&|N9j3*)^p4k2)k=cUEd|UgVH4M{24|L#UUo)9iDvjil`A7+F)SEcL>A^7C)s zwM?o^RW{MT_wgTNLz9hHYg?Njip5+&iv@rddlgLZ%$}$AK6CusD|ahQ`ai%Ue2!|}tpk7xYy0z?=eytZLj z!+Pgy*B%Mh7sl^qoqQ_%K*wRK#goGHBVI*r@(dL`TUZ{?vv@20=)&tC=l}HavlV_9 z*Nd;_)vK*6scx!kY0x+7Ht6jZ=`x%&d9up1>B@pgE@5HdVc=$90=k6rLQ6u{+@edX Hl^Lu7B6(Ed literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/okay.gif b/images/mood/charitycam/blackbox/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..d210e014fb441ae803370c7f7603a88eadcbf6d1 GIT binary patch literal 202 zcmZ?wbhEHb6k(8KSj5Hv1d57^$;rtrEiK269s3UhivPL&TtkAL9RpmA^bD98LF#_8 zu%$AK6CusD|ahQ`ai%UdtPl3*MriA-DbXiK?F*Dvf zk}56H?S5b#y8+(>{{;a~Icjrvtz7tPH|xy1Iu?IquN9oUeM#n9*3O5fU+?IhFaP0S j=U>VCzoAj3xkXtJ$yzoBeg+N(pi5X-4Lp)lIvA`01xHFK literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/peaceful.gif b/images/mood/charitycam/blackbox/peaceful.gif new file mode 100644 index 0000000000000000000000000000000000000000..65e30cda02a8bf713d30964e1855f108af959cc3 GIT binary patch literal 245 zcmZ?wbhEHb6k(8K*v!cQ1d57^PEP-mlar4fV>ou~*nb9w|Nou-g8@hy2>`_u|8x7f zh6Fo12DlpO889;fWfgz2u%<9@GU$L*f{bNgNj5m?xq7d~>$AK6CusED37C^Hi!a1* zPl3*MXNDU;)?PPx@ZTX`!C^CN^PbMv6*Avym>5G|d3(jUEt{}HCZq8h%eURN|9IF` zzQ0nvf9=sM>pdmbySLUjtY5yTt)a0=rKMF_5XoLP23DZ;{6KrfC!DbC-#h))k;^X@ Ti1(#r&dXTU$9BC)kii-N17BP3 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/relaxed.gif b/images/mood/charitycam/blackbox/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f39d516a2c9e281813ec79206c876736ee5a1eb GIT binary patch literal 188 zcmZ?wbhEHb6k(8KSj5Hv1d57^PXGTWCnp~}cI-a`!+$VP{Lk&@8WQa67~pE8XTZz| zQumXEHHCqVK?kG>q@95!@4^Ys)q5>opWXdGL8I@E!<>v+d?JQ>3UszRGu-&G_PWV~ z{|@mA4x3q<_jI0C7x*)4e%?Cm%a@>_3PH0*e2+{aizWogD*Qjr0td8G*_a zf3mQqFt9P`fb@X0Gq7Y|IN`Z^uf^-LyZ^xbiolQD}=#Bfi6&UWU6`#WqoO5QOu z-8+(MEmPn&H^7NSCI5WFc}a&b#@#R9tI1y5wtbCxxWg^ey^PnXqb^P;F^z%J%dn8yn7$nMllM^^gKdlOSbS}c-*fI-=@5e*icH7?9x3yV)KY#NP(f|8y z7dKk{z1{q|pwX$Gt)!_`SKp}HptoD3D}K`C7L{q!vIxVIJP@PAQYE}MP7hTnz38UUm(UJ(EQ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/suprised.gif b/images/mood/charitycam/blackbox/suprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..03c691acfb05ab077678aeef91817d842aa84365 GIT binary patch literal 472 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0;ai6#sMkxrPKgI|jHK=@~FHg4F$F zVdY|AW6%L<0%>Pp$+&RBbM;<}*JpSCPtfQ~*~#g=YTarFUMHRNU$hw-k!au+-lmn{4?E$HaF zSw}>bT%*!wN@>4b`SeR>Oq*{43&H|~7R3u50!ug#NGZ5HyQkuDFQZ~k+N70R=gp4X Sl*ExH){tL;RTph6vIYQ+vzovF literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/thirsty.gif b/images/mood/charitycam/blackbox/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..09ebfb201439c0ef5076d1b9ac69353c7d5b0357 GIT binary patch literal 362 zcmZ?wbhEHb6k(8K*v!cQ2LBoU|5sF0OioU2`Tzgev19)kfC3-@k%p5%5yk)9ey$_gMa6iFeGi&pn&eP%?e`f7ZnwMFmK>b0GFFB>b& zj`+n_U=hIetm|f;>E4*v{D101^qpH;+f+I_l?9RPW?>Lz;9+0}+RYPi!e!+g)%kOG z|Bq!sIF5xu2&jMssDMA=wpaaqb($2t=b>W2P>b(}P&+h)8pwTzSVNS*@E)m5&1v=ZA67KKNWhr^b z%y{oes<;X>rlS@ zv1JwCzFO9@hWaLN;X23mjt-UX9%Vr!>zNr?8JK~Pfra$~N9D5~gu~du;@D)k7#JBi r890D?*s){(85sV9f#QE|Ki808XU70nBRvCVMv%In zEUYOEYz#UeO(5+IETtDtc&^@S;eW98+`aTxCD&<}I;H0B+PA{tOiAo~m(}k>)AIZL9URcvO)ddXfr??pLFfAz+Qartal z6pugmJ-s%?zof~xrNOm}vAbK%)o-1HC~Xx8UP@nU_k%? literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/blackbox/working.gif b/images/mood/charitycam/blackbox/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ed0f630783a4344afd9da7068edeaf4f1f4bf90 GIT binary patch literal 268 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2|-|0ULDE{a6a}5c0b_{Se(lcOY1gZPU z!pgz4J_ z&Y%AxsKFtso{_n=y^XC&q`pz3yk=sQ^pvU7rq7ruh~yM*1`Y;BAY@=+n&5(PAsYiP b12b5dd4hxxLYxaI&I%T1nIPe*#9$2onRr&5 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/1.gif b/images/mood/charitycam/faces-animated/1.gif new file mode 100644 index 0000000000000000000000000000000000000000..619b9f30cb44e73a8ef936f8a21781a684cc980d GIT binary patch literal 2322 zcmeH_|8Emz9LJw-W3>B%Wqh$fC!7>nyN#^f5E_W$?F-{pa1;XbQsYF`rZJqz zCKtXQ0q21j58WgUbKBu892tz74YmRk4;XMDKhyz%LjeyBI;-u%fw!Kk0S@_yc* z-6nafZWb)=#lykn__#P62q_4~5K<9>A;nayTeo>-f>B9^C0N10&+;VC2U#J=@1TYLG0K)+-XiP|@ zCDn*fBG4gVLO@GEM}Ud2EaE~aB-la`Bu0=NMY4<(1?f5hFt7q(0B(>e033h-FboYt zNlE4VnXIp=YoVIFVRIMKOT4uHL$(O17#w4V9nQkH(Sn6*e&l)-*@wFnOe=6 zYVQ4!wA&fjPizl+3I{w@(S~d)ZlLZ)RbIi#VeM0t)`k0g^=o@pY|0Cqt+kw(o;j*~ z1+!~pELFYaC~d>%uh}qVt~qdY^Ha;Lcekd*R!9$jy&6hcHFnW^w+gm8PWn>pFRmUr zYf94Sy^Gpw-6d-ewJqJ2+jlIj&ra8M7mY8zkK)bO2dDmIZxW981v`(0OR}Uc58Ym?XXW-ZvLhC5^R#z(2xrsm{tf1&;w~bqts{ zO`Pky?Z<~DJ&P*p^4iYyyE1Pdz59H^$Wn3B*t~{>`mwuq`npYML`ojvI$(Ddj4T~< zds+Rt6jMQ7yYSU1bBejWWe!)-aC+LyPX>J1=|xg3^Kiip+;$`@ydl2DQ`Q6tvq)HsLys+xt;Kj1_uS@wx>u3E5H0ttz literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/10.gif b/images/mood/charitycam/faces-animated/10.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ba8007c45448035a350e2d6773c34bf1b78aff5 GIT binary patch literal 2102 zcmeIw|5FrY90%~v-EkZ&U+y3_K(67~K|IN$gT{_8GsG=|U=DYh)0a)_)OF}&@=nCa zTA4$JTQU>2nTm3C7{i1D#X6H_Y&pQtRi?pd+NR0WjVZA$AhQE!h^OVJ{(|}?-}9RH zFV7Fp%=5h0R#z4lZOsH5%(a3V3@{ACalmo434#Eez;FTw0wZh~LEwZ9w>fZ|jR1#= zBuN{P4xk)3NjOLw=^{wV;i4QA?Vx-PiXwq_0ZrmGr8dFPu$ClUq>G{`npDv~m5XLb zm5-r(G)*%;hV=o*0LwU7mydNZEX8mxhEtm+IhsNM2*Y`b<$NqptGHg83;B3~=@pp} z^6|Yagm@5m5PLxuR5m3g+AaR1s3bG(bf+%yM%!>*qD!dd~A|qaw1u4=iqa{j2P*5m> z1QkLOj}#Um6^9TnNs=PUiX+2q_3fkea3cxS#*<1+q|FO~s}s%bo6u zf;_uUqh6hLFDkYGT45D{79N6JfS5&yi#1#A?ar3QcU$SZhd-(Zthocd;PixRusN#%`fQI8)6@s3STR4Go>7@ zKA4hKu%;@`m}It;d0Gy;+X@VNY?I;jI8(-BRUNZ8H3y8DpWMCu>8+jXOIxD!cfMx7 z;`3G)TiWchF15I>|FU=TWn9z&XCXs5Hhjn{_hJ41-S(nB1B`YO(j#$>@Rbp&yb*H60z3(Tzq(g$qeh zW9Kk1y>(>jgXKlj(=fg`4;C$?J>Jxi{S1`3?m&YTtnN!CyuH-k6RsE9&GL19C!aC* zXFwYp&>#O!qiq^K)|fK!du3V)?bmn$-?Z|LITM=a>#0j;f~onN%bZ&X-gT<#y+ zExv7G&EEMAtv=rVVQ2bP=ZfIA0kQIXv%hn=B|5?Fj;UR|y5Y#-_T6JUSn%}|M}w?VIiW-3@rpL zv*D;4Ps|P*zI|hMBr9#)KWfoO{j)|5#Hee`zQ4x*`5GJky){OHT}x}cvTFzoX6;#R QYTwLI^dE5>%K%FL2C`h@WB>pF literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/11.gif b/images/mood/charitycam/faces-animated/11.gif new file mode 100644 index 0000000000000000000000000000000000000000..760dc949ee344a1a73a8f96c1ab991b4eb179471 GIT binary patch literal 2361 zcmeH`+fNi%0Ef@QG6IXvf>aqVu*;x9Wd|f)rq(v>a+d*Dyo~i02GJ5m3|huCwM_=( z;<#wh(Uu?+(KL42K*7O6Q>GOKM=mjSZG+&}rW)2tl#Lpt?M6Kv`qV$6Y5U8UFX!!? zhx27-XOOQmF~A0X8vs*75Ci~p3RE8k0EVInjsb!I1c~7|4gjHppahDN0FVfRqd1|1 z;Uq?oIOza@ngXE^gaRmqqBH=sZVYqaBu$bGiZU3+VmONtoNgRv34$d^jwC6SEahy!E3d^|x>IRqx zU|xVh0HAI}KjVG`hX9AV5dxw(M0Jx8BOpdX!~rpfkDwqlauTEkFDpWphm39!astouqK+U+yeRX$EC{kF%A%wQ zf+C8l4lgUBtVpsdDY7gp`XJOKNfQ*epn4=lQxr{AJ*o^yQ)jWR952t|84WY*m zJ<#j*`g}gM-x^q}gdss<>=|o&sz|kNverdzPEV{9& z_y(v<%{m(O_UHG;8~O|S$`DuiuIvy5AuRcY=7>{^b9cxE`QE`(8OLMog^}r3s|_Hm zsJOl=&7NgleK^Tb(d$~c@#ZGx+?C#-KoIcqDd)-%D(hmGnYCtPRd{^Bncti51{eW& z@odiU!`Xaf(4l1o1uZiJo5L){!wDcIvFK90HSmBb<>V~m+M@49AAUR&l&>?qSD16L zbVpZlsa&;cG#&wIuf9qDX@xS}bxb&By`7)DwS|0s%)EMY(!H)a*WS|ZoS*-mh&i!HbWdP)$hLbqK@Cw4dTbqKPp3t$i0g21<#+O_ zpvc`>O^KOf^`Qyhs#ii{miIrl?C*M3IApsLcgR)ok@?mZ_RW#Pp(Ursti7Qtj%3x$ z?Hj%6O8okfxo1Ic;jiaytsvlP=&X^E#>Acc@tWD2CP(j|>5Qrzj9Jcu`-{6Rw1$aIg8HDORk+$bl6>Odhwbw$-JOV zO&+p!ez31*UimNfHMaAI_XkJsYhIcWwQUbm71S7!7P7c?>yQ(MP} z^WK?weygC?HaSxCN$F%t(x0vt|Oj!~o@NW|ky=g7%2>dp)lNI z30@YqS>{A2IOgOs7folzqD`oR)y2%-hGwp2fn;ZN(}qPhJhS-j{BeK6;y!uuf_ z9QOdYmBnb}6$qo7AlxM3AqbCRlJo-j00e>%l$|8JB?x zCqfE5LT-dSk|ZFcTq+MlBnF-Z@jOi`(r(#kttlz4+?bn{9idYGo+@jibKxvxs6YkF zU@bt@Q?NxR=LcU|yH%(jGM&E~m+myITvWGX=g>*Z;YHYj+0vk~D@C8U#?oLIEIRP_ z?Cs9L2mPffslBt zJ*LK=yElD&d`0i%>EfD0J5QH?wBp)_v0pswTi<-^MC$H|Zfs3XdhvJFclpE@?Z1q_ z^ZTia_zN`yoBc_x)t_a&D%9Rzv1+Do%s%cK%AL4&G`)J*{AFI3h#8NhUpRMhU&SYx zgP&JU-*MHyP*yAKA7~r%|CWF3wxiWi|5sCbN#uLS4FKMB|I&_f zLxQ^KX>+&bZnzgzC$&qG6AGVX_4VI_16OKR6}~arG~HHcp69>$ZI$Y6%;lelm0X`v zN4@E2>sl%`&y7duujd@w)?zKTC2qB>c*owp*LNIo@p_vt3EpYDv`?a!1GfnwS%!B4+c9I6>Szz)$gufbqK5Y z6*{$R8d5q`Y6Be6UzJBL8!B|BK+@}br>`vCRyK5bVb=bh4z*gB(xb1?{Sh&Er=!|- zD5-w$Im_afv*J9D>FP{}Mq@Gc=o_E3kHm$}_+5)jCxc9UjZW1W*|Wgh1EwiQW9&#* zhil>5Cda2q!6!j=#0Zr(rXzw=ov~JzcyNia&Y^Nh1ASjv)T1+MUH-)j3EKE!=+oy^ z7PJrNLjb=2@|9^_jfj>b!@uKUQ+OKPRo8Z0pV1^_g$oqC4XZ u|H?f|$vy4=+@JH@zyELM{@SBxCHFl+YIXnYjq>&Hs(;v0w5-MqQ1B12uSa_T literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/13.gif b/images/mood/charitycam/faces-animated/13.gif new file mode 100644 index 0000000000000000000000000000000000000000..967e5c1d9a19f7f208d688eaeb8a8f3383f3de3e GIT binary patch literal 2209 zcmeIwZ)_7~90%~Hw6xt;-0e@spLVveQO5sULEH|b*Y;o=Iy@YS*cch)aH6Ig;2@_% zH;=$3HWZL>7y=y!TNXJp5It0s9xSZDj%>WSA;j#+1k8;vM>s&qe%@aC!uKZf%O}6* zdGX{)e$VqQt5{l6y2gvEDYJ*cDLVznf$oPZNdpR?)M`CM}!}z`~-y)w4b7J zDuUAt5s4BJib52PXbOu&5JO`OgUUi7HbO-yh8+`S=_ogbjhP~>jF5tmhLDaB*fHIW zgBv&e1egdyA!wC|=tKl?3JA);X~WzTG*A(s8Hkvoz?k=NyorhNY)oKGyb$F@h8N8q z6(m+rBb>|%GArr~2TTm2F+D06tO%^YaVW;&f`9}ONfP2YO5|8sMv8(o9T^4!Fxdex z05=$Z022;C0MGyt00w}SI8hQrnG@xhq;QhTNs7n;CuyRf#$-j1RYBHbvc@a=7!_hN z@QNlVx}X|@s!N(7XkZdeI*0~HhAwlU#Q-<}v-6;f00Mvrh6Es~vZBhWCab!tXsQaT ztjn6NXqu|&V|0*B2FL&kfC`3gE(&M>I)DLVfBdxmf3YOCY}>(aY6i@%U>oweUQ-#k$D%|@$b z?N<}A#7hm=MlW(TiRmW~8N58$UVfNtgsU?H51YN;ZM}26si1f7?aB?vR)P8O>(8O> z@mrT`mVY^|wTLy2&dhNl^y`yr8T{S5H{#X@yE!T~`Q<}bKHSRvwPE0=9!tr@(KctM zw`QLsJ&BUr1_r(#wZ;<x>-rUfCG;MC%^-to6JhFeT@6pJv&fkQkPG{OX>yNao zA9(Qg>grn^ePIVyeWc}e<8Hlgb+%#WpM7^Y8MJ1;ShT9iYrlFfdzWPqKY1DzC*NdO ztXj=B4fwd6GkwL|9GRZv+PWWquj3|sJSmlzF{5|5%v(F`vy5|Uf9cdM|bGDq?Cs@#8^I+-u^>^g%{NjTN zs(Qh}&QSXFGw7OkZ+*NGxtzJ(?%LtU4p-rgHPznA{;9mTK9Lo&jvFkcr<5m7T<|oU zuI`GS3hg;CIlCaftkG&K#cfzPxAlUDwN>2eO#B?|a+nj>e7(52)0!FfwQl!p>Irsx zYJJ6B&g@A(lE1ukFzLvt>kT>!hLhpU7lyEqBg==A9gc0YcUzw!hm%%}#DZrh6q01e zF{1ij`J=0VgY@x%d=(Zk8aW2YJ8!lyC*pU1fEzZK&rC+ud7Pp16s2Lq{D Q(s9eBd1o7{NQ4&u4d!NC761SM literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/14.gif b/images/mood/charitycam/faces-animated/14.gif new file mode 100644 index 0000000000000000000000000000000000000000..6180a06a8ca13867d4e8ad0919d01a5b6dfec064 GIT binary patch literal 2463 zcmeH``%e^C7>3VYfJH!Hmxxst7Fb|FgudpPK#!P3oH`U(We1 zCtptT78T=J*{h<#Z1Ca=@W}#z&0>MrAvT*2y9Ke?5W5|MA$AN!>6@8Wg!)I21wPBuS7I zP7ye4rb*mQ5)?_eDUzmqqTMu2yWNbNMF@r>eb6LJlN?PkG{w2y97VG*!WP)Wx;d8O z85$xmZUG)xT43D*ON*>q;urt~0C<~Sz);RjNdPEz#0xAM0A37(^9%zR7UKmV2tX78 zd}ozrw)*Lg{jWeG}=WJQKiff079vZ6|=B6$@_QxsK^y{fFKimECw z>Rwe-Ro&~=;lKXZ6{8207A`Hz&s$uGrlgq+aNn2-b07+?fLR7$0Cq4F8ssHt3Y>uq z-8wY4v*OZ@_{7Q0bI)29G`Bwv$(QK^ZtBH#K z`Vf=Zrrn*@?qBxuXHC28Ia6lM zY>Rj^>)F@NiGELXOV-END+any<`p50rum8R=8Gr#RK<5-DuLO-rWlh@4slz>wmVdDF z)K9n1f!6oh{J_Y<@4~+AJz3TW{_GDQU7o(G_m9>2lb-UMiVep3&x@;oxiu*HaBih1 zI31W;)4pk6nOoIhNmS_LNLY(s*L_!=qhN5TC$)FnRg#+C7ZB)ds))UtaJ)6v;ukU2 zu`s26hRYK?O^Y4eCEjfKENWY>H84SXkX4t`rQKeTQfIEr4=#LuJt(z&WQiy0th0AYToIv9)o}R^k2hq zq{r;YBsLYVt9sWM7(MTzBd>RCva>rhXKc)5Eyal9&kt1`?O4BPe5}Xl7qR$Efw6zg z7@S>GZ?=_=Kkl>QV`DD=z|gec3XGjYJ^oQuz;q4m2Rno86>K-KOlnOlEY7%p!5q1g zHkg8()xhvhT-UP_Ke?q<>kc0CD;( a6nafl*<;n4M;jBLY2=6ZXZO3yIrhQ<$D%i(ks-vd7~`{{a2PJ$dE% z^+}$*cRp1}W!u)H$5E&SDPusG5i=4BgMuIxMg>V3NrFHWi70}k35q5uD?wXHnjx($ z#n>r^rV(vLR@%TYh_xD67VV^ICqvt5*15{=wA#5k+r2*4>r=L!4>);Yl}~0k$?gT#3wAHZAvZ_z zJmP&Q5I|mz_Hj-@K*1oAWE2V^00jnM05C#`08o$s6o3_g0bl`~0nR5V+<_n$5V=6m z$4Ne3bPFOcNNz9J~3h@#sdLA38f)~KR`NN;^wHeo@V?}I(f#Qe7w0Ng&k)HXFZ#&1K&$hm#r^%&rorP`fSI! z)LkB9=JNxF^+%F4diB-4=b|@QTKCR4j;q7M^CwqsX)fI`T2Y)L}yEtN-yZG^j`Xi;;2j*r=`YZcH^P6A% z-Z7;yBuyN=*&_*KJ9|eR=bcS)Ls_OwcgMUa{D@)?}cTCM~fQy_x$wL#JyCjkyi;14p@|hjNhT68~^<%w^-t_)hMq$eOth*ip$?%%Nb`27F? literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/16.gif b/images/mood/charitycam/faces-animated/16.gif new file mode 100644 index 0000000000000000000000000000000000000000..25a39bc432f37ee5a8b359ee798e2746653bd2d3 GIT binary patch literal 2423 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/19.gif b/images/mood/charitycam/faces-animated/19.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4ffa5c6c3d83469c8a1aa43094e7915427b8e6d GIT binary patch literal 2269 zcmeIw|4$Ql7zgmDSm|+s7Hyn-JE#hw5eQH)h}4w|o?lSd&TNab8QUP0sKirHm)%T7 zI3QwnAUZfTBJQS3Op0!aJ7WxRFc@(w0&$$W1y|H1TN9Ngo-Xs*v7h$C{()sadF7qw zlYD;qeBShib$P4aPlR-M)(!fQIub0PBPk#)q=nL1z(!hZBxTbV3Tzh24i-C5c2Z}v zTWk)>?w}lY8#r`!pedk9J45LljKf0P9E^=-?2KFIU_2D%;H3bl^9lZ^P)#5NN(Qe=4FPL zJc3Whin2#gXu9?LjB130<0qP!1E5D2(k!@q$5=s0y3pa zT+k1i3aHZnQD;GoLe$w&b70VoNTbFe>h#@%$SQ*97X&{qE27UY_!L17@G|l~Z8l{T zWK~cCf)W%ILlrTA7(~=ipV@DIHUIVkR-Ct`cq_BEu&g*cBXf>H zzhixFjL3#=NHc%|5?}=Y@e+z7;!}It`i>A$3%3vVOi3HtmTunm6~9@`s<^SMYI3wo zTDkjnSK;~asLsr7S1wHrKW>T1X&(@5M^Yj?GTy4b zk`o}lfy)-j=A)$LwT#RjZ@B^HFTPhFJJ8m8Vau7EsyiXRVJ;A9TZNe~$5ZGd!`V3> z?{8g3f4Xw_)6jRvQ%VnD{#eD15m$-l$NevMzJ2-pNatw&NJXmOwNA|Y=*3k3_<3_i ze&w~6JI9w!RIMJ0AqL0QQh<8$#2@4DmB|Mlt!zp4pNx&I)cIVH7@UugFR{e>rZi$eZ~c`LQJ2_IJswF z;U;+6m}263Po*3+KOJh#Eh%&ML{=ub<`*t8&{T852g51#)92{u{0^b_+KIhI&hX@K zVD0?ZwXRI_>g(n@qcOhB*_#$saM(oEI9;Z=vZTX?=s2_U?3yTxv$`U-%WE*jJDrD; z_qE@>DG%92MPNdB>{gjrRbV>ywLe}j_UgX?ijrG@ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/2.gif b/images/mood/charitycam/faces-animated/2.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a310652f5277a0a2ab063cea496b036def54c55 GIT binary patch literal 2258 zcmeH_YfKbZ7>2)DSU3n)&{0rfcNWlyyWnzh3uqe#T`rbP)ne*YV-Y6}G|H$%yPC1x z1=_(|Dr4F;;zR_Rc3QO2PGXIXD_RS6K+)Pxy(M&t(KK#Upm8ycrwhOOyZ@T{esA7< z=g)ahPM*^8lKg`8R>*{>ewYwKfF?x3#E_&N>;NvHfTR#F7DyHW z2fzaeK=O#DTny!!I00>^8H#3I3}gd1|%a=CP4vE zff6au0Ca#LKnMT>!U$oK95+Sjb_!E=Y`0^V3%eMFVO3U;c`m@wI>TxVZ7?*ZY0NN~ zVKK{Mj>8;}c^(VGxJ7xq1Vn}x89@r06+})5w;AJAAhV*(NwOd*tf+93%E>A(2f`^R z8n0;K6jVtO1ELy`R8>($T@z4#mW^OQ52-p<46FpP62fW_2ZC4);Xv3})5D|bAq{I7 z>o{l_1|A@^5$5N=@SAS-D)z{$s0t*f%rp z-5ZC92y>IEX7c=kQ;i?(OLVNRJhVtR?IAPY`p&zCAa0rbaanRg$A^;=v5u$I#bxfO|m2xH}B(%Rj@AVlGQO};=A)qbp&k{|^ zEj)T#n)Aod?-9<;bG?5p9VRLhZ5N0gQ-}JuAj?{4GZWD1KPp5l-t65qlvyO(>MIDC zK2(08H?_rqO313A(&98((}lR|W^0dckU;0MtE;Vh9nzY# z-H`>I{PxG)rIgT|a49;;dtgnfm^9pD+2z>LYjbC9MF+S4da}pbIP}CFlkBYW@_UyT zlu;i<=JeX=owbH_*U(sxbz2ot9Fde%)Vp)tt<|aWlBu=5RO9HAxz_bXEre(A=koiX zmaN-yX_~u^H7KF(iSKaNOsd)DPrd$5-J2V$%-b$+I-HL>=j64))+n!6v@{H4bRJlh zf6Q0c9P%J)Lz&NKilyEwKe6G)v1sa?W$Y{e&h)bmPy8#f4T&52h_bI|N1gfYq{p-3 z!l~FVZf1H`RJ54Ct$$c}+~VoG<|ZlUK-by3ueRD_<`iX{XP~rXcZ?;k>bxmfINSMI zO6472^z`}x@8Ld|eam^1@BX8U@wu<%oTfgn$WRhGjtpzg9>+*up1yIUKmUH$$d$!U zAJ(5vi_9DyczMbu_1Z$~@loVn&_AjX#6RIiVYt&@!2LgmyZb)^_mN>V0e8-$ha*?h T&c}@oeMmFFA zybut5GB1V&UgmvaKA;2wi1#6*5M*_duqGNPNR*Kn)+Gf=iY}?hz^9>rfsVqWuJQ=+ zNEZ+ikS-!5YHC2&Bwh0%17llO)Ucu|3X*jsBNRqRL7FP7s)|&EG=y~HNKfOR3)oSN zYw_zV3k%$fvoo_Ij9&ozACZ=9=maNbyhbv-2w4{ys>*_z!AMJI}D^vsT2_w=r>cI!Lt9ltr<@mk&d zolA+ANUy5$|RJCP`QvTUL^a=(4v7k{OhJ};Si zqP$&xxQLcZ zlf9P4w8|vMs}*j*yUF3ADVCm_{r1|TTLsZwID=VY)saBlrF945{QF{)8MiWb z)HD=wN^DrU_&dieLfA^bhh+`eclV~a{%mpvxOcWwVMF|lmHirXm* znXDkJu=<-@8wVdoAI;CC<%EN23Feuz)2oBfIa(01@6Ynj+PW8%WA>uQ?dHnWQcpd0 zuq7cXwcbjXN{vGwL=s}%p}Y9`1G5kJ#qP*_#XV!i!A+Zp)5CYp#N}B#ytXwrD;lu# z2@eWBT{HUGnbf5Z!h2%gOsg^5R;A?Dn@&!Xf_|!WeP4>yk`c1ik1pREo09&e=R#!N z?ue-`3{)4+cs#thaB6Z^&o9{EPY-^b5;=VkyO@*}B>e|^mnK~JZ6f9##OBr>$={jr z#AmV&a`(Tp?Q@QW(vEEz>rd}GJ9fo+VZ@*RyzCsmI_LV9bJrX{pFL+;s9hZ|$FP5k rY&Jwrdn)q(T;#L=J(1tv(mN?~b|}LT*^>CJbG+Yqy*0bc&^PyQ#`skc literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/21.gif b/images/mood/charitycam/faces-animated/21.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f3d938dfdfeb86b1c2b60fa63584e92df5961d1 GIT binary patch literal 2279 zcmeH`TTB#J7=Zs-7T86$Tmr5;z``Pn;C&HV)OpxNWEqQ9DPu2*t%Jr}M=SM~p++JJ5Cj2WBM6%fYz72D+H52VHj*$lk|5kRo0}v(ZU8qydH_5& zH${3VH|3dtGVpk4ilP|+n)J{l#R6~uJOJaS84u05Y1YHA6vKHKj$-)&04MmxgqMU?S5wQ~DWQCIvZx~hh zsLIPaCt+T|yrl6_%tw(F)g%cE0v5%XC@BI`1*Ak3O+cEcXp*7}NEeitfMSB8i%LvX zuxK1qEUGa{#gegVSkiPEVOhhnj^!AR>Npxx5mJ$&DvF9!0}UY!sk)+JL!@IA!w6#~ zh83)<8dkBcX;{O$u45hJ7&e#~>NEb`3%Ky4mloH(yvVnFamnntamG&o*Pmu9k48*H;C=0no^4C(&mCIsAz>{LGM~R;$Qkv#gfk6>b#>a zZ$kUV_O?jRQs=x??T*o*Q%gQ9D%(_V?w=Gq)LDM}V#9T}`26OPGj(?c$+BgQUwP;0 z)<}NUk@AX5rM0K3BZa}%(MoGto-;eO=AE_u?>R~vcW1u%LT$nPwvLSA^xk;0(|j`7 zQL^S>*ck!ndTUquKBE5SRUP)N_#_xu{)0GJao>Jndx|$<#s^iMzCEcqBc1)V4i`VW zEMdlQU{!p0y+1#r?@Cti@TRJE?fvp8(^r3)dZbPs*xDU>u-mt-{{%qqg-hnkA3v=5 zuBGQmoOjVi-(zT7dAeiy>h7DF#WRawpsK-jYZcUa0Ie$kdsl$id%HN`i+?0c`zd$J zS^_=S!kB1RBx3;WXz|saFEFjPpaVNCqlwuqtzIjnC!O`zk2FlXRlja5&Enj$+hTG@ zs!ep>yVApv-2EA&`SxwY-F-Q44C_I2Yk+CaqmHfcTUN#z-Yf`N>ie?mk*}$37uOI< zNGZ)<=~|XB+UG1us_ozZ+LK^k_TmTKO^#QZQ;A5}n|?8}*L+tx{!QkPKX+$#OOw59 zL%?gAS{nK_vOn2$aLVk;l2_Ny3j6w(j7O76V3nZ q++uWI@T~LydFPk^bDdN3lAd9*SMDpT@)?|7K;*MEEhq%A@;H=S7YHeS962RS}09+WO{KOl`k9d zl53jbre?#2l$M)01{+!07DBcv6}gfPwoR$AYR%NDVZzqJV+5FO;B`@VuBP&ViW~5 z4Ge`dEU*mDaj;)PyhL*XO9?C|vYf>7BF8HXuK`#9 zHUM(KFy!~!IDs4p90duTWDrT-Xh~CuVGzS1*6Gb5o|jlrW(1ja5M@q~c~Rjcg_jgg zR(VKfFb0!ECL}MA;Qo&gh+%a zglNlV5pr-6UJ^xFk`z%=1zD98RaG@n(gax(6irkNLDfaoPz7C9ksw-vibUBKRV1mV zDw~RGh?*{%x@hU5ZHk&H>DCPlBxy+0ZOJet+mdxlHf-5IH%=2dC=M1f(*z7h`kPb+>?r@r*_rE-d5H)EbF_fW2R7(atN`n z#XE6Y$>L+a$<-6)c?RViJ#$`*CowJQ;)@ygY~0+kN!V94Wp3lrE2n?xbHyc3TQpK| z%6q!v+2gyXwfyFe#3gxCJE{uaIQiC!f$e!S(hAuk_RGGK^zt`$5f z>EYJu-lA0sp!BrcGS7?zPZ(YBkXwm(wsOhwYvFiC}qjAf|%G$ z-@3Wc9$#~R?tz#REwR+MusQMGk(H$%XOPf4{=KiBZW`yVn(aFvcQ1+yeE2~@V~j7g zy6e+ep`j)4PTiFlw#sSR>RiYq=oD>71%H5{22Uwr45)#-Jmx;9~!)X;gV zFe8K|+}8bYqkHO(2ehaC<<25}%BeN$mv-y*Q|m_03KQC|o!fNBFQY%S zE(nYbZ>@Y{%-m6Vz3;rVHc)?|qbZ^O;_jYH^*_Fuk?i}MPU9S%vj5lVf1UozItBkp fr(4J3{?h3MX8+jvd}3hi!qycDhs+tS7?}Mh*+L8U literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/23.gif b/images/mood/charitycam/faces-animated/23.gif new file mode 100644 index 0000000000000000000000000000000000000000..63e2233d128a2288662dd63cb4d219ab34de9543 GIT binary patch literal 2555 zcmeH`eNYtV9mk)Omt%SB!3vTKi+2GN)&xUtNjbz#4|#boh&?v6P{yr?WwOLr%7R+k z*)~dL=Ztt+6cgP#sWIvLl7x9oY~yU(8RgbWB4$m})^w*fMm8;J=*DR}Q%^cRUDJR1 zfBtNK^Lf6%x0&Bx&lj#~3D@;51y$f*bKvt}2*3b}p#V$Jz%AVjSc+mvnj&bDVraLA z6yPWzP>etWNE46-JVS5{>B7^%9ZC!kSyBKH0M3OVIf8=jjHD!jh6K%#3`Z~`$x0M0 zFpR)LmW4oolmuy>V_ifjki0|*5+zC$T)kT4L`jg`$51K&HUJJFZGyHSP&h*630DzM z%K}gZ5(%^_u(HUg0*yol38WzbL!wQIF(Gg9g2hV~PykR!Ak#phf$Ay?R2Co-=rlkq z&{+yGtj+?B13E_|2rLR1G_Y7;Lc)ZU0f8Y9mH;pWm?KggfqBZ|fg_TR$XFbMA%l4u z3oI5mjS>*c%MhvpZ?X_W9&@}S2o{t~UUUQrOQNPgN8zy|Vnv}e#Og9_%B(3fHeymT z=dMi!S}N~itAeTVjwTwKXlas#L>mJK6SmD^S!QL#$R?{`7P)G1vdyVB)ND>q@j8}F zEUK!i$r@6Tj&w~nbk)!mOP6gOnJQN0l%`-^#YndmJtb?lhHMjI!_<(8G)vc0nr#ZQd(Jp)cf0${H= z+n*ly1LfcGIdGKYXEu+5MHR^qO>k&;HVN`CS(~ z?)KLWG$sazw{5<5`aoN?@AbWn7kcllJ9xV^zqaR4dGpD4elXwPAJ5FOr~i6(JWUOk z-fXBRpWDPuw(O}GNmM*m#TnVf-GM~y<(aMzev}$54}SHTRlhI_nwq|o#Z6?y+QL^O zFQ(IyGaDPoCEqrDDXES1Z={MKrpIEY|)jji9B z=(si&8LQZrTX)fZ|58=Bsk}E_zhkcb={IIt52Y8ra<8%?QIWPW#H}vxd;0n=#(wt0 z$Ul-j`PJ3Y6(>vgr3bI=c&|NiWqWyk&A>oiU+vZSPc8=hFZo6y550O%qNpp<(OmoE zP%E))mtP;Nn_OQ2OMd!5#Jlpu_TObKe|$pB58NJ^J2w`d=;VlFh1-S`{#ako>#wTx z<*Xd9JlYz3>hxO~HK#hy5p|b0Z~9r-o)FLbM@l}Ei}%Fux>T?~Kzgm;lR@S>J z&FVFy!?J&8V1MS4uLnX+^djoGC%tReyO~8trBKV_*T&K=)t;Rh`mO(o%lqWJxxwh~ zv(xjGhNatg6vDFS=XYilUGJOSQ@x?Dz#Dop7EF3dZz@L`q^Jn*+o+rxUGicq*;f6% z!v$Fncb+L|T$CAzG#t##+uvL~9OE*Idj>m3mp$9qm7qGe}e zQ;QF65gV)eZwBQh4-Q^!@Gg(P8O`ZNV&vQ2z*=#4o_gek(cFr~)l(ktktQWCCtkgJ zQQ1Un${YCgV8pYzWN_qq<=&`w#h1Ghdter)pA-(Gpcx%COUuwr3eGh+*X zKl6HG!THt8Z!dhx%;ifrDl^jm*KZlF-|qX;Z(sWD|JiTdU(9dE9!Y-gw~t@DGO&<) T_=CxXPfmYYR^Q_BfcpOcPw61u literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/24.gif b/images/mood/charitycam/faces-animated/24.gif new file mode 100644 index 0000000000000000000000000000000000000000..d72e561e840c6c88238c15308110a4a2501269f2 GIT binary patch literal 2465 zcmeH`?Qhjo9LLYy-F6GxSQ%sM9)NXhjEfU)?Y}57VkNjyh70upR^pVt z@XnP7N0pH^f=N||bQ-ZpCKZiq0&H9cgX`p>8l4Rcv}lOcIPI1gYI$ekAK(l9<&%?d zPEJm~FMgle6*Wunra9nV;9LdXzyP2Sga>f|(EzX*L*qO}0zg9$5yS}$XCa6OfQJAN z!z4yfI9W>&G(piMP0<`f&@9Pt6wA>pPq94Bu?)d56aaD%lL3e!NE`qMATEl!!Jvzg zLXdC?O5%BuBn^tSNP(qgmQ+MuRXD*C01!POAR>qafCNF_FERv4Fe1aSgrX9LDF7%C zqynHKhz5WTfCj@l3@Zq#;iNzi5=ja)C(yje@ES?#G@~FCQZjEHcqoK zmWwl-!LSCynJjN`oWb!X&$|TSlB7$K4n?~(<*{Nnr(*mvvr_aYBq2rcy9zr7gSBwG)+)dRgf)FF(k#5Ra@5# z-E>vkHbprmYH>+7MAeiuQ_?L_bOgZ>MOP5qyIFE1$&qDOl3ZD~1jQ0nOI9sOvt-Sd zbw^cQMR7IV)pb*jnQ}a)#cereDREnkTZ&;ThNHwBCGOrm4M#N{&2)6z)ht)H48t-^ z%d}l5X1RuA+pZT~*S))c|LUM_$|KdQS5-wCs>2IIexFwcolKk(23J9;5BR_=a1Q{` z9dKky{?G@Fk+mPK)5%+%YZk2jFqxF0q{ol0J+@k*HEd1KLmi2}Z{95#8*FcAJ+tPYa>_OyukR^L8qN+k550*0xFtO&*dRc! zhLz5lXk`27t?O0iv&x!2ZP^DE&nyTvY)4+L`eWDLyu};Jw?xGQ@PZAomYxiz@q^0d z!{fVq#W(xVWt)duj-ALl-h95dCD`3OHM6}T`TKK)H!t>G9^Uxf?&}95)0*GkkNtMY z__&gYW&}R#za2jQM1Nr#^8%go{G#>8>ZWJ-I}4UJ9X|P3jrxFXzISBRo=-m9o2?KB z?o|4OvwJefuDq>&eWmn|zMn$9D?56{VG6ATzhd3R7n?VSwiFWc&aEqXt>i7K>vVYN zO7f0r{LPg+vmW1=eHsESuYB|J0vSZh^tA5L84uiQuccOw*SrP+(9q6*(KRv_7%H7x zkE~zb%emyCh*(sT%4Q7k+-LFBNM&>01%HGdOqb`4IV%est1H;8TGtuSg+wXI#(p0qd-2BwJ-KiZj9b)QSvOWaT z%5Ep+rl*y*4xyc)a5&gMejz3JZfFCP43~yLqW_ojXmRc{U4t3B3JSF=JBzkP5^EMk z%O6ch>#9r65}rMk)U*orT}nB;wDQur^m33?o!+I5Zu{uFPcHf8drx2q@bY7ezikUF zoVX@rKR0oGcgfL-G4cMNCvNP0xM1?8H0P1Y@AqfFKKVn&+W1S>vw_6FD-`e)D*j)g q{}uW#D|F946iO*NbyuNJuf1No@Uz6WN1vM<>w3yu@|DjA9{dYN?d9(P literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/25.gif b/images/mood/charitycam/faces-animated/25.gif new file mode 100644 index 0000000000000000000000000000000000000000..48b2998038bdd28681dac986d4c5df9dc688820b GIT binary patch literal 2234 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 CGJhoi literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/28.gif b/images/mood/charitycam/faces-animated/28.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b43b1dfd4d8dfd6baccdd5c89ed3e6ca3208149 GIT binary patch literal 2420 zcmeH`?^6_I9Ke?!XM2FMfZ*a#atP=tM;wu{qcyN9;0n#Tf#NC+x-=PE4Z7kuvpR!% z_#;;*Z40HfL2}bNmXcgWatlwrMD3!{&Y@_-vX(Mu)fyjj9G{kV{Rz$FGoSg)cfK#4 zd0sr9@&#qZ#EL112LXeKeOxvu;>J*dKnOQMq9|p9;WUae_TX}p_R>qxZZGX67%#!% zIFF({hEZOUA}E?5X@X)2k|Ys|#25ylX^f%W42!TV!tsb8AOepIyt|wv8Ioownjt8kG+-IP zae(ImF93lDf_;f!;%r2j^UJn*zsyStFRHw#@UqHFs$e5)oT%}VCdj%V>4Iztk|?5* zj4BGMsHm!mp^usYE2xZe$0Z`0P#0r@(WWlfnA|{Afa0~!VF!tg8OUDJ{pPyg- z!rW5d{KEW#m?-;guD@fQg~%Y17llM2k0Ub?1bv7cbY@JywZzMYwvSKA{o|X?d7q<{ zjE=AUq&{H^(da+_W=Ba&+@eEAMh9JU{o^)1`1$bHPt0x}y`H|HY0}ivjrWERK2`qw zb}aL`S8rvKiG}Th>z);U?V9vnQbr+`*-<)oTgINfIp5cChv=6p_Y;>d%uIjsMJ2fJ zt8~877JKTBHT}@j99Yxvd7!Lra_^<3pDzDk-EFOANHlWV*A67_ z=C*d%bmpF3K%Lm{&T6X*6!t7hNY~Zo1N|Cx`B2f|?uTyn1F?GVjlk+XtNF<(JN2`! zrZ2NUtekx3LjHk$4O?1qZ{aCy$aDYX=?k8ZitEo#57hUJ!^^LCiiHE$JImtRyGs0c zqS$#cJAQdj5Q&bh52dGdt#MASxYALXzwGwrO*wtNB~z2)M^-v_VWT~41KzTFL3;U- zk$vpR`p&kPR~o=~$@ob0wxpi(S<7%9-%DleKel3CTv{)EG4GRAN6+QTO?P%2IGXVC z!j6L*g6C2f6|5e>XVqp-^Bh0FvNg4~;o4~0i^uu~0uSp}ZJK|$Fk7*%KozSBA>4$YEYu%W(1C9#U_s29XXSD{eJ(M z*yQO=Eivy`(DNL9an;V;ecNejW=}#=Y4l?m_5EMKEG%Z`5nptf(@|97%aMF*cIYj) zQ-`>X#|z&$jXu-jDSfl!=+^8+e&@$|tpmZpmh#L?h+|@FR2j~8U2D?c-<}nh`}UmL z7)L@;|DB5R;g*;Q6&t)E{3S6dG->`|Q)$rgpz^H=GY)kGzb&fX6?BXr{qE0DMd_Iq z=N#@q^Htxrsy*G~R}HU=N;u*H!)vd;27Xv?_ncvD05?w<*|GWeM%E?1-g|BBlyzQ)s;H=c*Mi!$WIw9qQ7!+=TBOy0BC0y AyZ`_I literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/29.gif b/images/mood/charitycam/faces-animated/29.gif new file mode 100644 index 0000000000000000000000000000000000000000..0dc9b5a2bda37acd74e7827250d60760e69a5dbb GIT binary patch literal 2123 zcmeIw|4-C*9LMp`c`Y1>mji(l5!b^nob@E=s=-MoAXnXGc&DJI4x?6#U`ZsV$+Eav zjDiJmqh=Cq)Cg9?fKJ76bJEf26(OEaVS);i6itL_(#A6+%`({X(o&XUI9r(I$8j9Z^0fU(#4rKFWq`#ITz3;XM(P-) z23riHGaZH?H4Tdu~*5Cyox^V?yDuN3*C1I3|hXtAwXkOyOBE!oR ztA;rZ;5vdE2w@@wL`di+O`L`}ZQ=|h7)Y@&%)u}ZXEv= z&~;!Kz=8mdLm+fR=!GT$Ar7IvB!ppAP*gE038o~Ps$ywEG;R}BT~wi87GXIc~}J>Xu?N;5ZXTO-nVPYC_f0 zG}Y2Y%TS=9nwkY|aSQ4eG;9!>a6F5b<9u-9%3x*1vXV$}L4JYLVgK6q97$RL`ar+| z93ThG1;F(JY)zWxA5A~8*OhuEclcb#z&_9OpFTU4czD@<*I!R=?!Ev1@z=PYhu`^; zO8w}7b4$+1mTli;FIrUBOHaN=Wm9KD9j)lZ_PJ|X?$p#5Y-(^$T6!<=HQjyPzyEC2 z^ST?|AI_;b)wli1t?R$|%TqQ!<@!UBNul+@gRAG_DMyr!g7Vx4*Vgou5S8y{Wwh-0 zE^?^ySdH9Yak|vGVa~_6K(%<^yU?AJ(S;^w?OsSuhy_nFpP#Pzq;USw+1rs<*BNZ&{UGd@^*Swly_*>ez;S=i=63DP^l8w=<*X=BY0N zD?D2t-|9UWeX-<^o@P(`^l9CF%;ANHCZ@E#`Rup18k4(5_MK_C7-?B^O*w?RHmyH8 z<_jjKTla6*uD|l>F~9q(8>lC%=-b2Vwm&tFzg^py7MevjY#MZU^Yd=+bU#L0d=>Q# z0C~3Xh$~M_x|or>ZN>LabV6|?$$xTW8oK2k@QI6)qQEpJ>uml?e&iw6Ubz_(brVOXtQeqt70dpCv?nHxZ>R2 zDeYr-ov6c8+?Kh4+bqmDT3y=YDf$5`K_)-_897x+4n%7M1bb=8BYuWfhQjEx-) zOf%QKBpDlUxPy+e^wrf@QQrq^9}mxH8k?V!m@qT+Fqq5T*^~G>@O^nob)$o>yxw{>oA`C~vSVrBdx~ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/3.gif b/images/mood/charitycam/faces-animated/3.gif new file mode 100644 index 0000000000000000000000000000000000000000..3dc1db408933bbac1a7b630964ab875e2189518a GIT binary patch literal 2345 zcmeIx|4-Cr9Ki8%BJ>coo-&T1lH-fqO+2XL=FMra3LM2Pc;b)>46KS;jLxdl-7idv zqI8Lp&Y`LCYju9<253=~W?-aK(TYwh&gG(H?qM3Ob80i^?80;3+=3@5Mvfd@#8AaR1iNjg9UEd-4q66#@57mvCW zpC^QR0Ok>JRK!pTLp2Nq1jZAXKwuJ0a3n60m_*_dh08%gCU8JvDv2u;u8^2U2Nar6 zDMF`7JxBrucJhde#Rv`~7=mVqAQzxmnqbHvO9myJQV@^oM1j)>JQzR&dVtgknk5;| zLNPqW@-!#VoH&3NgFH(rEUB`j##1Usg?L(FX`Kz~90hn9@IfHZiWpP`IwS@)onlxP z7DQMO5J`e%8Rl8sxFHGfmty0;U-NAgJrs4r!Vc z&u}8kN{k>65M@@B8AW7(WMOrg(-l@yEu5@bcv+QLRc16%(j)%Nyb>A^Qg~hEfX0Ck4^&wV394qTvKA5m;1!)$3|;|(stcMfT0*)UGQ^N6g@6cj z5f~N;7&0&=V9L6tahfJ*nxyNjuJeY$n5KmVKs2n=s-|m-sp^IX3{5u&7$z_VKHNWP zT;`AuvJ2afx8tW2v-u6xkC=iN1B zt;^_p8*8IRCSK^AMIGv>yvnB>%Z#iEhmqt0|H6L9iL&-}S7yItcb+&VpWC!M<(Ie8 zmlUtfTcjK>p0xOE-_z@pPie=C&n&+$&g*_7t*+aaUNiMnlXtW>}KaaY)y%w2aHi|*yTx2DVXMgO*r z*2|-J-^=cP;hpRGIijtreokfCge4buG5#T$i&pLoYZK}lBI3?WfBk3E&3@LKGi_M( zt!thg2WQTYLgya3e66u>a0KK(I4&}M(vnxXSI$@Ok8 zd%8T|J89kZi|)4m7RBy=+GkHaaicHKy{*J$i)>H(Eh*}wyYrl>==yU*-kka@E4Fm$ zjV6C$VRcW3xA;o`AbYvf9${a47rT}E_E)QFob`t5E8QR8g!ug->}tD10r^ZkYOE81_^c6#?a@`{c$CAWk}8gSNut)-v-T6?sN&cln2 zN~gaZ48!N6K6fAKaO87`HXXIc2mJe%d!-8vms~lS22*3YeyAi zZZA4=z2#!36z*y8CpJ{u>Q6~kj;@jKM{nO!+FaLA7xOSGABhc5ux)8?KHYa7!IF_J zCmTjZ9qT|!XLQ9Bt=bMJH)PBSAK}kxfMe$|P1Rwea%c6yNd*;MG4snmLt}EPJ0P1o zKBWgvSbw)OGNBsEjEuiqby5vqyEm)J9Y3b(l7INKHQyKHu6TZPex>+aEBWNn^IPSc zC$wh8aVuWjF5V-y{!sMIqjeF>z8z}J4h#Ex33jW5r2k9!kC*W9-&Vrf8*z&UN=Uk5 Wl~7q;*t@9m(c0S!HjhFeXzE|%=Jh!M literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/30.gif b/images/mood/charitycam/faces-animated/30.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a94313fafac8305b188a2654818500bdcd00e8 GIT binary patch literal 2429 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 Trk#Lu+180)&h{2#FksEUob3M> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/33.gif b/images/mood/charitycam/faces-animated/33.gif new file mode 100644 index 0000000000000000000000000000000000000000..8343acc7a72000ffd434e9b335d9a3fecf60eb75 GIT binary patch literal 2352 zcmeH``%e^C6vr>@E-!a^MI1${!=n}*&=pxDt?8~HIy`F71%s9~fMnICX-9(T58G&= zg96eKw^qkTZ5gfAIw+tW(Q1bx3QSikI4V{r6>2+8Y8yMoN1evgvHsNmplN&ax%ZxX zlk+|2CilBAZ^4|bipeM)Jq#dY;JA$-3^0cSbKtnsfjgZzLT-e7q{Bgy1W7vFq|@yt zJZ`7g>!iHSh1uC2H|h0|K97f@NS}evgJBFpq7CB^k`U4m(h&k=1Dj1l7?_>la7u^- zf|MK{AidzBbPokyN}?E`eID9NF%+dDq?(atHiMCDewJ@GB;ct82AFY!gP8#2c&dmw z07pQW0mr~;0|M6wql^P=q>hn*yH(N&Zuhfd;PrsdfZ`~I_c1`ynz0&CD)>~OG@5oZ z28@Sg4ZJ*0iK5TwOlN#LOR+S~8?cPPFak@9v>*z!Xlw!}3OvmN!+|Ktq6DI>N;EIA zyv*bk6|vaYIP5ru4VBx~3g_gy$V-uI$_#v8uLu_-@0(l*wE0 ztnGJ(XRhq?Hjbu7Z|mD(cP8ca&@COyTIXCG`aY&F%3ic*d{&)lA(=u}wJsmHbgOmZ z{6+D;`}s>tN{_C;b1SAg>T+$!jBhIkH`X_eeY3si&^jV=SNzL!AEO`El&3C_+dP4& z9i+|?QuEYKwKC?+2x zVRqLx%h8lIOP(*EGW$t)X9ThRur;hMtFm{+lKoj;$rU?Y@h9hfFv&L2d!>Z0=nh*M zp1iqqq(7-~IPu*0O=0^6QkrjW8c6v9&1xn(`#Zmz@&26Zb8$<{I>M6Hk-r6}L{@h0 zO>QdgiQjOvYc#@sy0~&6>AlQ4OLF6-nEEj-fAlCd%<56DenL-WzL)!&dX zqtG?Ro?Yo5n4Dt`-qkDx^%vOJ-?m$(Y)viwD)?kWUS9qD=pZt!}U!^^PA4re^k%D@uwjGfmd>(U%J*RTUMXkigqRO~lzp83AI}+STu-!Eo`O}mylR{!Mdf%aO{@~C6HWFd) zHd%N6Tpz!?IV0lu;KtTo;?Vw{Mhr{CT_|ME{MvD^){IzA?KyZO?Sw)y-Eg7B{FfVwHW+S*y;=C+dfBG;glh>FGkWPy2PXmo literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/34.gif b/images/mood/charitycam/faces-animated/34.gif new file mode 100644 index 0000000000000000000000000000000000000000..49351592a2b86bd08e7d12e1d135757642b53afa GIT binary patch literal 2513 zcmeH`Z*Ual9mk)${JRZAAxjX$LUK$N@(0!=(z=Yw+$LWBJf@i(Po`WM9tp8LMg^B- z0JoN@cMBxJMT}uHM9nrK2_6)Mm8MKK%v8Fe6%tm1#Xw8PqeIOx?dUisj=)*Ad-jbl zedQbdJfG(~zvsm>^SpSz)wNaps*QPI1^DU;_y&psfJ#DBG))6QQxxMIXohBz&@5nh zM~bB>j-fbb;8-pR&+$oEf#Mt?#UYxZqcqCdL#Lmr-0nwv25B$5j;9a6(14ifs+sGO<-+ zYoZ;&c7)ivWE+y~pd?X~Xh|Zfs>_<;s6-4k;-Dun3?pKyx~b__#Belq!!+Z%VjFV8 za8ijGx@~HytH0BtK#pCfrB4OM1|3BjQpI&=b zy}uDv3Jv~pt~ABvyuf=ql`02Uz;YLGfkmJM0MA|U4#jvbtbO1K೼Qbf)eBH?A zvV}Esubz0~RIbqK-V+$A+P7fU(-qxAHB0vuH=p)T)@I+cu(|EpwPsTH8q-}E{%14g zudZ)u8ND_T-Zg7Md-nD-mxMK0xj!A9%71ns`=0xQ`6Z`d&)WLg3;4qAd$ZY}^^T5= zmagpdtz(#xIZLUtE?3@?!);x1_RAURFt~<&W)>Q9Z&?9W)#Vqw^~W7q^X0(r;HKO!YX(kk`tvjYGJCFj zws?ULboxK-8F}`jdBNJl#W_doUKwybl_vcCm9&(WyOZuF5E}8%+7=u-b-i-?Dj_qNQ;_=}Fd)moMR;>~xey=`4vtNZWvZS%I5MSA1yp4Q%tNB4K{^PZoh?d&dI z{K9CNO!aqG)Xs169GECtTGRSo>V{vIvl|a|R!l7G2l4kZGjDl8(U2ZU$-3f6$y^u$ zgCK3SC$M{t@7C0=dslxQs&s)yAIzB`;p4ucZEpDb$-wU)FFn2TA6vPxoB2Y~uxjqj zT^TCvD(I62SFm(r<<)Z>{9?lWXx|!GxVbS<;qPuR&let^@`g*^Z$w!?`LMLIJ@w(? z=GMvFV+FMZJ-gSuv@C7j)HpYGw!6}mqn2l~coOnG!LeNp*==JW2fn*2Yd9@^JN zEexJ*Sa~_+=|leeR+MymmXM1V_tfXCdpGMV-=_6}JvqU7&-rumcYhv^zPL8k?Ro56 zLj_g*$j7%n>3!<>?U}ykKf4_p=-}?$7(V#i9p6L4$M5`GJMr1rf8KbPOJu$ML46|X za(%mBnNGi!{MfG_`}ITa*Xr-ouP1*qp6r(~^V<&Yh3kU{KVEg?&Hned`v7?Oe~Vk! AoB#j- literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/4.gif b/images/mood/charitycam/faces-animated/4.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fb33701f091087f0ef2a1db6ac7b3f0fcc495eb GIT binary patch literal 2363 zcmeIx|5FrY90%~_IAr-EtU}|F5bOowi6DoOTxx^M7hxg8)h4@~MAwpBbA+|hR%Z|w z4`fBbRYW(&YMxQbRs6D1)=nqTN`O0}wovK%Wt_Rm$vHxEsf=s2pZX7)>Y3Mk=JU)v z&&=~Y^Sl=p7v{KDCPL|u(GNWyFa#qIY=cb*ir5@Bn*(;C4yVhBx*QJ7=`!Ii7v_3Y z2^e$0xC3!J5w{B=F@(ZU9CKkf1)D2~g_t=A40q$08^_&*+2ABjm?#1x-6otQ2+D0v z-L#va-EIaWDUvYJq?@MP3`H^o%~B*sQ5?x|6m3?XCRv)~Xo_V>o}oFK78nyF&z_ni&KIK?zVA1i|A_OIUo-#h4jOj}+~)g!ILn^B|$`;jiyp+P=7L zUge#h`peTilM)vlTZWV8UpRQ`=s-@ zZ*mc5LkYHSQgVrqv$FX%od4p%j-pB|AFe$S(}mY%ZmS7F^Dc$A=Up7SkXkS!>A=)& z8Q0Fjy*u7Ny!!C06=ltlt<~j?(-&`8)(cy1D^m+wH`Sl|#L}F*;+v0=lS$;z@v_$Z z+UMr|cKXNC?2L}F%WGO^k$sI@N2Q3NjFPt5wU&gw+3SD!A|r0J+c&sk_4&q|efuca zNNL;rS!>#;ms79}T|aH!I$)yUy4wgekDo2rAXxn99$MG$Z1SJrzw?Uf^kw`VD_ zOSsJL*gYRW!SQ7SNfEd015+$;2kJ>wPUc0P9J80lWk)U9@l-bqS?JVp!UBg!cK6LX zmYh`>HQjrw-`Qo|-kT{}M<8cc?B4$LPV4qnX%$sR`;u1mD+SQLFdecN$C-F(x0#8lSGfn@m$zK_ LbQle>LUaEF(nsP4 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/5.gif b/images/mood/charitycam/faces-animated/5.gif new file mode 100644 index 0000000000000000000000000000000000000000..222a5eeb5782633dac45e038ad0d61512c66c5ef GIT binary patch literal 2104 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/8.gif b/images/mood/charitycam/faces-animated/8.gif new file mode 100644 index 0000000000000000000000000000000000000000..019a12a8052d922f180559326edde96e4300bd9d GIT binary patch literal 2322 zcmeH`|4$QV9LJ9qqy^lnd@G8PBHs#ySPapkF<3?5G+IwlXp{k`LOfg;xA^VMB61+G zV?sT@Y+fcoZi@CMpl71>}P*>O%u-g>7O@i&R6ZSh15l8(vroeW9z`%(B)Cn*Y z;20oOaK_AVW{x8$(JJ_Da?lo3oIwRs7!qShoFNHTg~C~i;3xu+I3NjD%&>ljlUQ0}8HuB1 zo)KAA;su#yWsdc;oS)-lK>#EPC=$>VU?@P-fMEgx16U@&@&Q%|azcRT0sN9*$y~VK#FDPom3qaugf~c^f!l_7rl>jFKPEvRgyhH-(sVD#yi3gGZWFE)@@bkbg z0EL$%Nft%PuTC!lQ38?#WD&>`@Qc8&u5!>H009}OB@hS(gFrx@c>!#k}@=@1YDNv9vF@&}UyU)s(j_W=P+a zR8o7>ko;ZoyQz+zjMCwO_L%flk%d-5FJvd#CX2i{~MzH8tx<)#m+&pLOzNahIt!TvJtb^?;=e+U$+! zwyozv-kUe#T9V)LTI031{Tmd@!P5gZHh#S4>9&Wy*oiUk zuAzpGE61|FJRT8~G{;bOuHw?hhre%*if^B``<)jLTe#}50rQJwD7 zxjyqr3MrmZV{om=a`z8L%$UJk+md={Vn7=flkwnW6I-{tC({i*@*V4Q@AqY}4C0;r z`k29^^|k)&O+VAy;A^5UYeo*1=fl2~i9Hi@8@1ZX+o;Dk2KdAR;^}TLuVM1ADW9alN7LRtSr4!QVEc>9sut$5Zeioi& zc=Pjxzqk#W`OzKcZ>^mF_}OhoQTF8Mx((YW@08Va@S2S~ALor$9GG?ScJ)yX8ryn8 va1{Ja{|Ht8xny*|Fg!KN=Ah3N8E-1YPId literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces-animated/9.gif b/images/mood/charitycam/faces-animated/9.gif new file mode 100644 index 0000000000000000000000000000000000000000..42e4e47df74237c8ecbfeca4b9f55ec3390a052a GIT binary patch literal 2240 zcmeH`|4-C*7{?3T!2#192<#T`)WZQ5?ihzGp;4EkDqjjwtcav>?!3yJsW_!3GwGaw zMMN&!u~kG@H{z&Yg69xdb2@&L8(5Y}wv<<(=op z=Sf~qSw(3vvSudahV&sQ8VdqDAqa*bPZW#AW3wVKVnJamj#vrQN@6w!w=o2QVlYj3 zXcD#BFsBoPVH8GC4}!xm?(q=MKnMgO5d`y~7=qylhM`Cqiedyopg4gMC`DomO%M!DP&i5B6oXSFMN>4xkR)VbA&X$OiU`bGtct}7tTqkt$WA9fVU9*a z7_Q?OU~rj20fhky2Q&dlQfFx0#u7G`wDFXOXPg4<6c}fSaf+-{3cwK#R(M$D5j6yB z0t`YPT|{&dCwiB0LccZ07tTXw3&cFa{|qW7(T%091SEYA~A|c0+G>VM$~CeXEdJU zcrGNeg2aYIP7p#;C;(VF#L5z@NSq=CRGC*~)`$cQh0_!cD4d~4swx<&%!v_BQaA~4 zlFmsgFROec!UH8FD}tg30I(_usDM)euK-@vIaOyhJ)jvZ&^b-#HG>115CMV$LMjkd zLx|{tsz>LLrVE-L(hLFU5->!~kfH!JqRBwh6ky1}hyX(Y&ougX#%UxkSzNPxVM+Dk z!u*1`nCKPGKTU~+&=BN`fnp#Blo$Pwr%-F6z5D@ten*Zach#Bdq4+7beBYQ4Z87b% znF&`x%-JLzHu`kXy$H|i`D=YIBb){`>hB|y-zkB!U(Y~Dg1EI{|g*Tg< za(oLK?&9Gs>zCH0x~z^_3lE15EjgKgGb?5oO^>a960XnNyIdGt?U4r4K8%0G#B3|L zHIk7(aA2~@|4~Oq3Q<2YI52zRn76{8`p4Bh_q$vR7F)B#pA*_<4y>(&$A`*$W*4l> ztr)MrUweG!tASPSd8RgNtyr~v5RXrNskGyGu(_!HYHn>`>KS~-+QMby@0&bg9+jIDUQ?r>!~fX z%X4dv^tTL8TiLYcW=f@ZP3sG*dsEAE7mPxS++SQ9!0Na0jY-?e3sQ#DU*G!B8&~CZ z4yQHuo=JHAoonNM_d!bvHs|oJmLyYIQHnYJwO|hvS5e$K95~eDPikHJy+1tX(;trP zh70D5ol9NHrYwXKU7Og9gS!gDoomh69Ullq6}#=0C*7S_~Ybh&u1X(%#ZpJ@Ef8+W;JY|)Mf z^p( + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.gif
10.gif
11.gif
12.gif
13.gif
14.gif
15.gif
16.gif
17.gif
18.gif
19.gif
2.gif
20.gif
21.gif
22.gif
23.gif
24.gif
25.gif
26.gif
27.gif
28.gif
29.gif
3.gif
30.gif
31.gif
32.gif
33.gif
34.gif
4.gif
5.gif
6.gif
7.gif
8.gif
9.gif
diff --git a/images/mood/charitycam/faces/1.gif b/images/mood/charitycam/faces/1.gif new file mode 100644 index 0000000000000000000000000000000000000000..92e132cd5ad46863869f452cab5e4eae57e0b548 GIT binary patch literal 1607 zcmd6m|4$Ql7{@<_LW`naJE;ePaDqaOIu3QA0~dONV8yLeRID+6sT$p>n^YIKb6b() zo7@nVi(keiQ(QOAyhS%InPy#zU~%d$kj9OF>bOXc1Oos32?9gf*R4JvarT z<|lm$7t@4zBxvB&ppVwVaS&7pt0FDPK}qni0jJMTcql8W^0LB4WJYpg1jrg6U_prM zydu$piy#Fb%X=7(3Q`z}BTVIDz$pU7h%^skTwx^;6kuhUmxKVz`x(v`RM`k{vKo{i zY(RM6Wzol~j0C|5#5Isr5Ea%(%S;#y8WUk$ex9OTxHIBmDS{+09D)*ou$a-yMq+*r zXpwdLM3M#}Mw1@d&oRcBiVCr~%8K%2ndB#23eBsuz`6Y3t(D_)8u?m`J{eggsk~{&`&*->I#Yhzq zz;NjQbcknW6GA4ma5B{7pD42eO0;HHT{_d(m~0v!86LG_#F`$bDIw>h>p9h@Cen*` zwPwH6YTfUy*mHOB`fm#sUAwlUy_2Xux;K5)f_=7GXg1y2apBJV#zW7Gw~fxb)lF2L z&UrVn+1gRKzlSI*_F9^41zw?WTTgjgT3+opt?mcz>2oa?N*nkEuL>I+@AuB6X0=wV z4J~+fPx}0XSab5jY1KcnZ}#L<8KsG3dbl&|BA#k1`oWvNX!yQ&-ubq&-b71}4UfG2 zPxACEFEfFt^7S)c@JuyF1A`Qr(q#VGeYxd>In*(;sVKd@FMD}?>2p(l#x$<<@A7l| z4%~4RwL45bpWICQxM8pEg?o=4d4=-yrp~js&9~+XL))KZG}EUGmL*&$BwssbcNSLs zI}#0;G?vsR9s9k8F+-PN+Y;O3{J9ku&L&LzLHYb5u0;^t6-m1qs!q5T`9)KvRK&TLfj zc&tCyR@<47Iy`_iPQ`ANB?l@{jhRY#e8xLt#TYit5zXrB&vBSkyJJ%-F_@9`=TQF) zcjoX4ta1I0;e%JY8j^Bq2Z+JBYk3k&D=qDslD4LNn+;oR8t&{KUP{IC`MmlY`Co;e zwii8f+glC`19uy)=dI~IXx>~sj?C#T6ThuqJaqqBDskxyG301?Y)>ibXQ`B&hgZsf za{RT3TD9f6wZA?8oN%7F?_%Q*wJo$WU3^ z-mcbcK4i0`y9_b(qu(NG5>V~5(mu3zzDkFD2=zn6J8w1oThYFsQSzJyTSKuy!U zZoD(sz2(SR3+c9!vvw{WtgTL1hS}Gdx;GLj_G7($v5f79Z7n!`imW7dA917}UohWY znQ=AmKz06-k*ePnOOhFtY|WmDp_1aU#=JUb*&kG5t8Gf!sfS&bId5EiGC2G2ZQG5! sL%n&9?^nI<{|+8r@iyaJMZWD zB_u1NN;D?Rv8Wu2sGwMwjj0*$f{jdML0pg`jgHQp=TfV&f6AmMwc4MY< zWN7@1zFItL^3wW56LH{9K&Io*nl~NE^=c=^&f*(-iPGDPs}t!rFQ#6-(s5x^>u>3m z$0o~@QgU|qo;{P#7*?)1lqtWq-aS}k)L(a+t;MIci56$4gXj`AHa&4K`Fdu%jYY-j zM4Zm#7;~PXmm0mDDfYt;$AZ;2ezI&m*i~6M-rp#!->|NxPcAcE z*-mXaoF8YLHLpyi`V!Z=S6sl3E!-T~H89zgSuxsY&Ntg8Gg_Uu;jX#u!=;6c9W(pl zrp`A7w;miB`HCoMNX&KwUL5`Sh{0N&`iO6Ab5ptl4wwrNet?>W$*KQ2yM1xL!MgLf*_r;u pr&YImg8vj@HK)HdG7eOT3J-lVJ!9*-#n*Jwu791M&(7%75@16hv literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/11.gif b/images/mood/charitycam/faces/11.gif new file mode 100644 index 0000000000000000000000000000000000000000..b31be12ecd68bed56aa5a7e325c11b72b979c23d GIT binary patch literal 1604 zcmcIj{ZG|a7(N%UT*uYogh3g|M^RC+$Yiq!EZ2&NQVilpb>O73OS@gXk8N|i6BWG z$-yu{Q9#!LMYEDDSW^=GKEEO>D6kBRrCGn}r%9T`NgUv+pvasgu_8o3j~|*48h(M{ zd7ASomS6L76bmirQA|rVyl60nWvIH2bPJNe@;t*aBux_(^g~rrpa+_=&QgpaX}YMQ zR#5k8f&w+K%FBKgmHj@|qHq#=p;xyQUh*oY$nX*?$ed`1s;+8K_iBpj(M^gVq2|%2 z=C=) z3t3UeDM)dUWW9h?0j>eu3kV2Ek!GNx2^0-E5i-0FsU{c$BV~X?oQ4=>y?`O44sZh{ z0ig>bM3O}rqER5KGzX_{(f_seW26TVsJV(b@S=zSoB&y#MaCfx7->ztjv;>`qKXEB z5mO~u(a`?Fa<|+4()#}?i2o2GOcu^rTyt}j@4CDl(*p*vFvW@!p4q@ti?k$^^T~Z!do}LUl#3%q9y07u7;~4 zuWx>yJJh8#h0Q(xB|Uk*zA5^Chc8JZ#R+(C40<@nbP#I zhsOp!vR^y0)j9E`F23R8{n@sn4&Ke5DYs$7!IHLm=ljJSs}|iW9?4(#@alo}A5izK z{>Xy|IeIVSLQFi zv@NwSsw^qMQ`SLr-2HSz&hELc8cCKK$eposwTt2o#XSm+KRLwA$Q&;?5?NIK;K+QeHFPDuHFLP@O!BQI zhi9C5JaKytIAU`LyfgZsDe2jC*YuF|g2ei~M|H5!Uhe}t+y*GYAcKqmm zV7|+S4MuDS6QPS{tO@0n*;U6<8^U+lT~eeYv-xbUP0wB_O{+Q_OdJSp!Cc{cx>wEK z6I8XuCYHC?EyzuL+B>KEWb^6>!KrQE5aVm_v8|1?{ZW6p@_Emu3O4>EG3&bPXqxFN zWDTnI!sL8+al&BQmC%IV&2t|&Cqz^}PiRX1I<2%n{)@8N?9%S>^LYygejXkSON?;k z6ebnc4lZc7&kji)`Ko0wwdBdHjbZDUt)t=6mKD9p{kK{ghkG}c-VNWT&HMYrhpt&U zVHf|ZJ+`nnZOy9KtmB_}Hhp>I=5sUy7+Mk%e%w<7kl#LmtTI*$NM}_ z@)m9&*L+-?0207k2n0b8U9N!BN#VE#0KdZ#a5(&S`xMU;DC*~V=x|JN9ED+l_ng6T zQ6hFbiK0_18{jxU%ZeOFAV`2^Jv0q@o1H#FVSbtx8HSQdD9S^Ul1OMYb{uySL_m6lVSFSx zMNu4vnNie55Dpy20H6_s$1o2;kQ$8>$01F#D9Rv+pCmaH#Q}gMNdUkhh#f(ow4f9M zKm@=giBgp3MAjTIGmtg=8CrZ#poC^dWM~Nmii8fkXqPU)i##_aC3CD_N;We-n(|Sk zizFNb?x&@h2^WFe37p3<7DH(iVNirZq$6mc;Bzvh=&=h(Lgd1L7Dk0Q4qsf02~qr8V>+o zuXjHDzq2G!DFeU_GUhj%{}aX#2pU!K>$S$@!lQ{BPFJM&EatSysL|MGQX#~ctcJI7VadTPZv3E* zD(epp%RY9Y^bBE*OjX}c-#oCsJ96}NFHnRpZ3V(W@txRh^_GUac?DZ1f)`#)ubm7I z-cmc>oD^j$IT|-)n1iwKsUdGg{Upo(s!04tr%t$?C_-mPW78SZkTRwJhrPM+%$mpPi)g zi<5@7c>LgdiJ`hbLT>D@ zzL+$v&wV$mD9voPZr;0XuuQH_bN4C^wA?dTjh2(MBl=ENW=GhO%M%4^v@^3^ojcLj zrrW42A3c;Ds_ckZeLLx|YikF!?U7|=jRm2f%+6lYn#RlW8-k+pZQ7iS=ce;@6^+Hq zhnsgImGs^>(K_;B-$-~#PuQhOyBx--=|kv9<}*?JlEB; yW4HBsP<*vKC2=I8VQ$v6jB!sEeL$xC_Ki9?zUUW=rry}L`zN9IhP)$K8tY$fLt;w+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/13.gif b/images/mood/charitycam/faces/13.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8b304868faca149e19ddddc3654416f076b27c4 GIT binary patch literal 1532 zcmds0{ZG_(81KPxhzj1FD9EA5aZ+4FQhbR}bvdvnc)D4HEv^zptisrKA`zq$7e)b3 zTp6cqIS89b7o(0Yipxr7vQUEWbjn^*w;5s==XBL%xTMZ(%d_w8&)D~) ze7?mSH{=)Wa$|1n8DPkCO+y|?Qo%3-Jta}%IYU!HQ#giFCEieY&;`>_!H^<6#nN_~ zvID395in(vzyM?bN#KcS1OxyQOdLS`5Ay&V01LnX(9sm2GL&@zAQBq@hU1thA`*<} zFT$5VR^P932G7Fh!llspw^jX^5I0 zQ8htPd0F8kiH#rzUC~GvLD+Fa)gzpMhJs?~qN?x`g_ANTN@$#HA}Wy;K-41)FVGxK zP*K8&irZXh2Z7;0(oMuKC>k#ZNrprFNCv9cM1`k=3MWRfq7p9L&~#apD1sz$0(IFj z8z3IL3waO}BPg1j1iY*^+~W=E139UVpf|81VKO)0reFDCU3FMs)F=YCsV=J@f! z6mR2D#B*mxmotCgSo8EZ*~j|D;=jr*Uh6T}y5q?&6phrx+mcqWqa)Klw2cU4*Zrp`2LBi zw>rztIwJ+Iwov|(PfNY(+pP~5EK4}IsJN`aH8kL9d&A)^>B&De=09SqDgSn+Z||+K zFPa9a=lNNIbiM5NdykyeyE9u!leq7^Y;Sq3@;-4ic12gi<5iFT2FHqyuurZSX?{-} z!Jj=)d+pU{vnCvc2d#~dhVNz_#0R^#-tZEV9I%|cRv4e!Ku`1D*m*IwRIWVSo^7SJ zhO64P6(t<1U-JD1XV7|~w@|2bgpykqE5!>N(o5r=8)sBqo^#6oL0@pK8S0LmTX9c` z&uBSsiJOygPxM(T>DB~%pnGg)?g$Z^ly|po{jAwTlYH$f1$x_@gdD8UI{*A=Yn*dQ zozGLfY_*@Ug*^`z)gG9fYINu6zjlmY*W+Aq>pUN&wNDJUE$Cjk+MRK6R9SMUtY+Hp z*f)DT_T$=|_$xUvw=FwQmNloH6K8!@TAUVhR%zefl=^jMOM2BrW{3ZAo@c3aF@0>u z;oYf4?Y^eSc>j){ez~#Zv(Ch^slYpJrALy359NwL=dw!+Po}&y*}1g$&Ftbubt^CU zYw4UdaoJB3D{o{C4Q)+1bRyYzed&iyo(|8JC)-ZB8EP6=IiSk8PBvne}yPdJ>h z*J|+;`a_epjGZ->nfQ;EK)96)DaA*RudJuNC3oJX7S@FvSKK?B!&g%(LzZ}VdB3Nx z{2bSKb^i9d`;W{ky0oifG2VCQTGzVVC!xh9>;H+p)gNcY)@<3G=%3r)FyD@?`4{P6 BZ(0BV literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/14.gif b/images/mood/charitycam/faces/14.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2774578a4db6a12a4ef370980576c621eef32fa GIT binary patch literal 1648 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/17.gif b/images/mood/charitycam/faces/17.gif new file mode 100644 index 0000000000000000000000000000000000000000..1684c2007961e6cc881fdb6fbc23da68f4f5b7d9 GIT binary patch literal 1622 zcmb_bi%%3s9G>GmJQTb`tR9Hqtq>l%3MZ~mO}YYt9FOo=jkb1!k0xuijf+@mvuW|f zx8aP_{%b?X_zP?9Or@%Wf+HPB9dfbi?PgIC<+t>Xd1vUU@^K5 zcpeA>AczT`B!Q{|ng%QjSPsQ-z{r5H3U&a1IV4%eNa&{^@IVBcsQbSOOv98!iRXAl zQv8@7LomdJKn?N~#}W+Vr=bp^Y|_?E$)Ipj=T#CT2-FW16Uv4mYAPoytRyp{Nb#EW z0+J%}B1f~7pCoYtM=;ETLId&)2UXLMG(U<|c#<`E)iTt11)T_B zLP_UH#t>AElWCk}tN@}81&t+W>j;XPDX2OpTMXn?Q#YUqHARJjYVwL`i zQk+3^I>kbZw7QI-b%HiYM)OlDP8t^WQxeTsO&SaaU$^T2wtHVqvH>sx7ECx!{0ZC% zK`0`ARZoY!$1!`!A3J_)KZGBf=9p52v|TIPolieXN-v+Azo)Bp-jl%krngSkuTy3| zd)v3}Xvw;)>uK&@>i(so;(MXJo&}rEx_`(E4V_%sQV^AUx4XNltr>d}%5R|(0{K_l zh6Y#mAMt-Oet2;4iQ|`whx?l|H+MxhBX2pMfzBuGzPzj1KZgbTZ|=#7wE@a_T!3<4 zxud&$x7vftnd&=FN0nI_YkRWSJ#csRv3cjKuTMFg{dr2!;nPUck;c?T9cQT*bn7aAO^gR4T!N`Fa z7~KUT0>!)kiBDhMU71$Vh^z^#{DkAlM;vc# z$enIao_iaO7P^D(`CY+lD^e!m<+hQMgZ3OLtGqe!Q)l(w1aez+N5Y!*gP<;aRfXGC z*gAqIugz$6?S$7i+hQPUh- zYaWY7ufN*neGk8OC-J-fUCy4XHG_G!ic~L)M_kw*ig7%D+E^WURWU@~%`LC8eVx=h zkifNVYKYr5XY7Wz5#Mf)ugSv83ZGxkyk(yr96T6{H3hG)8rhsV?VX!zha-LJf*yR% z(QPvZ(8x31X^TU6Lle?L+;%iJI(I}adC<^T>brcKh)L-=lX`Qh_WO+D^ew-xXvUeW z!JjM!>rw*V#K881%cJ)l7iSiE y8)oG?AMPr7v^4F*JvqeIw!&%ID{MBf3@qc*+$lZov0ok@uMaDJG}$o;Ec+Kp6X{F< literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/18.gif b/images/mood/charitycam/faces/18.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f54099afeb6a556eca75686e8a63cb3b9b65802 GIT binary patch literal 1634 zcmd5*{ZCU@7(S&14j}G;R<4NHTY*wVq{K|`#0;)bpz7=zCAGgoS_^0mp!i2HufmsTe~7W(=YW9CX4)DGZU- zqk{q)k<^V(P*@_Ev24NMq>~&KwGlsq!G<6pB{+(oB_ohHa5Djis%dtavBY47XMv~P zY8QtfD1qCYa8bZhyjqbt5LGgXISIH>f~S&hD&iz=RaTL}?*fTYoFwTcvJEGF97q-r z>A1>qkr+?FjiO2b;t}5IfS?=vTvBEuJjGeCi@`~OfFi`zu7DH#4)C!cn?a&MqWn%0 zR2AGruwlu8eH;b>K`a1KUo0R%M2h)&zo2TmAi#m&7MIz$NP|o}EI8mI3Qu?z#|4rQ z2}nfdaD>N6QH>5kT!{u{h{_NVL2*OS2?0k`VnmJtpILTNf`cSf11{oXal}pHB5|u8 zIP7y`kW>*hKm-aO6j|_FoGjtgC}a$YC`2WQ2cr^|@KKPALn4y&QxI{2!a|USAWAA0 zh|mxv5Tj+0O2(Z4Nq`7IAf~Q(Tu~9g6^+pmKml;d0ZR~w8!#6|jQXrB2%%6Yq~iZ) z(64kFgeFkgtfkpMQH=q4GYT4pJR_aBv6tJj*H*ahO3C2hi*({C`)KMXI(&DcbQ4bf zJEh~%v6NIy$|m+dx+SD$6jt^0Xx4Y-H*U#!T|43M)E$2_BU_*O;9K^ytry-e9@}VQ zXzz?z|OEa~_-;+GKn?ZROEQp+Vn&?4U4a3G+>! z0qrkkpZ{1ox8S?94S$|1GK=%jwdW0w{C`a@sX9{-wCu)3HC4Wn3&v~5$Fhs>^e_in z_MV$(e5?H>R6h-mdpm>$9edaP6HO!82E)Lj)taL%*m(F!Pk&n9`hFs%SBwk{cfMir zpb=~un(kV0J@jxqW9gIMHEGL2p3D!m_eOBdCV)^c$D{oVE8xM3=y1yTpQ+{ukqfXE5>rKnMmlIZuz2vE4l*{0% zkX2&;bYo@f!sgB$sNJBQ8?ss^j5|CIvhw=LA&oY>ta=H0w(gl&kyTxtl3{*sx8`>& zzSNaE;|*V~$e6$W*9xV`pxH!)CsG&m-u6|R+bh!Nd$Q(l-an!v z%34E?)liX!D&CoBrzLvTbhmQfX`0 zWnb1!IZl|q$<}>NdmC~xYtH}Cv5IxI-T2LPLFmuCNuO>RJ)%33`IN3%y7ttyYK;c1 zy*~@(UUF&NbVD4@stHu3tY(EGD=GZpaqD>b9dS6H4Ys!~sre+_V1Lk(ulu+ft^E(I C*M?mH literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/19.gif b/images/mood/charitycam/faces/19.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a8c80de41a55797972d84a53f5e07ca6ab6c670 GIT binary patch literal 1594 zcmd5*3r`eR6uwX%%djY2hSvhK!mh~j(1l5@2B+Pn!0?g^qphz|5bfBe8itxw?Y2Q& zhlkpXt0+#B7L-x3)fL5-ZAc3aRjH;cXxdKF5Zon=k8Z2Rq|-Fb?FITHdUJAf?z!K0 zzVF=R(&eSgme-qr3H%8Ggb)CL0pJrwl%OTBjHbvm0aV%PWJxOy7z(GX0BS6`$aR9xcEtEX7a+N#ZjY^m<5$wo)Emf?f^bWloe>L6cOGancwG70rqf zNPX6lCUHVQRCtQ@IXxo9J82G47=lu0QDArvC(0}um*WVU1O)U3p(mh8zM!ZCkh&az zk_ts%fR$CnholwB;}bmuh9f6XR-xqca-x%BJ*+T?go5JZBrhZ2v-4YVLS%Sy&W|^M zD5_INEKTqRogM^MISCylG`Ofh!OIXNN78dSbb3gD%M4E-Enc>wM;5(M@IY3a*-;;- ztcViQ86F;3@ZV0B{rJ&KRBf6LuX0N1{^8E_ILWk6g2G{O)yq>aw-RbIZ3_ z%8yzqiC6Ar{95HG{>Ito4sZXdzhQTE=04@Y4?Rb}t;QzsN3ZuR-i&<|GWyW>*~-HM zbz4HGx^Pl5F88~#RxYUuk2UCd$ASGR1#g@?7jnAzpq^YhB|gd-`?Rq1<8)odbXRj{ zW5>Ceg6Xvj&GpyBJ#o76;U(_6`xD{0Z|1B!`2A>k6K1$rH|mNvpLyJQc0*T1dHl`H zHRr2Nic^l3sJl{D?^5%jkaVFvj#$+V>K(4b^X9Lfzxuns?V&{B#=)sO3$BHl^u{D} zQOWu2ybs(q)g2Zs929eZ4{%nkdCV~?nXqC3?b-o0J6yzlSb_QxhHHGkV= zqr)5J2kFn_IB#-tHDXCE7w_O3z;_ib)%?7eyOa*@`0K8^!(eUQKFry@OpHFO6H7o8KH7 zlX}JRLej=9E< zyGFZVy{)J;{-Y?%MA}pNz;Nu2ZIk}Kgp2b+T>KF_^vG>Nn zzk*>G6Iu5QF$X;?IGL9bZvCbS^YDY@LRRNB5y#aKh<*MiK98;0v@5}jI>QeWuIKI zLQFe-$=_k#Wj92=xTv#U$i8rA8q2xzbEuT4Q;(FTw+_`rB=dFY*A0?5-kN@P*Rxy9 zO;?aS~mQ1~xYTzHlM literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/2.gif b/images/mood/charitycam/faces/2.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2b3a6965f5ce0a5d2047bb3a6db1c0300d090a6 GIT binary patch literal 1617 zcmdT@`%e^C6uvAA%%b8#CdCRav+MHeE)O5s3QA-UaJ%3JRMhdU4AxrfDk-g!k@Av} zM|_N{RqB|PA~42OY=;U~J1h?c$M`CCjjh#;Ms4dR#rjy1#@h>~Klmqfa&mI+J?H!G zcfZV?|3UVwlyy-c3cP~g&4*!_$z&o)(yJ&QS$5F0EQ+X!!U2E>0ETgJ0!vaBk56WJ z2QUGg!f*#h$#&TzD^QUXN%Bg9BJf_G^{~8;7oo^Qo`W1M(UeG`!Y6#LSct?oX1H>TA&5vF%vWa8W4~G3;=e3LmY4b9g0B=SjIGwW8!=O2xA2ffcT$W z8Oa?JZ33gi5KxdNp`GxUOwfWu0z+(GFiMEvJYXTmK-K{n(qktTJK6yh5Fnxh7>0NO zL0E7cagA<_<+qY7$)X^VCK3lYHZ}kiD6yi*2t3WP=*C_saUztVgQTGZeZ1o3JW%l3 z2@-lBlza*&dss?!yz^(c}c<|I(P(!qEDbX1m`Ih@(O2X ze27g(v>w?Z5XdUY$59Lvy-+|0$qFkuEEH|BOEk|Q0iq9K5fE}7*6xrQK|nlX!;ts* zIN8feZ@Q3`y^_Z#BB=^$K~5$x+)h|ff!syzAfM3hp^TZ)-QE3`DgU2^enjmDKo2mF zN*;X^=@n5|2DTe7?0csdLCFO>cc{?Z8MT_UD{W< z{G9*|cPwXbY6qkKo6{{jy}GOP#K}Ev*#UQ}i)UK3EonO~9o1@VVN`BK~@kKZ>t=Eti_^sX_gfy<@FFLy-p5Dk&sRPy6q1a`~ zB&W(s{o3k^ct2;s!RgUm&SUD}(leErBZq8@T}x`u)xEg?AhYY&hs#$Ll>BiM+x2c< zT(3=IjxGLkiF-wVZ3tmIeU^_&>o)nCaeDS zeRxAL)?@0@o4<$xyWem5Ufqk4%*SWaXMopn7iPvRm^>3)&A${`*25?#@2z#afv^;RCkQWBUR4ArlTdxX zc3SiGs<4!YL|;hS*8INEYYX(DpJ(7sKXo{s=hmj@=2uVXm{S=;t zjkDb<+1z&Y*LT`PaO6HWcL pkd($k_xwtKZi7iyo-e{^MeqX|s^s>Q^FFfsOIE0Nt{slOoa4P@+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/20.gif b/images/mood/charitycam/faces/20.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f5c3610c303199fc69045646ee298fb7d585688 GIT binary patch literal 1530 zcmdT@|4$T06n_hM$Ds#BJg#tDLH15Ty~XoOT@>3KtDYR_X^PsVX^gN)(e@OmO|#Y1 z6IMK`UC^TGqE?`5OH$iIY|^f_$*EgKnkJ`c6E^(;ZPzae%?dVAvrVQeKlv|o@-j2; zGoSZ)Z}Mi=1Op|@YVsi;o*+<-p(u(ZVE{M)4`6H%hRIW|3P1pm2J(UdfNcs41F!%h zKny^6fnbmgM4LhkLW1XbhUOWHp>UKCXwsp^7>06C1V-Y3w3w#Knkwlkr$_`v074?t zd8E@w!$l4x0cZ+zEv9QC$C3zfNGAy#a0hTGZLD-CXkihat zK{6Mka8hE$SXeLw4H1#yk*EqZhh$w768KbhBxyX&>Y}3Za+su9BYRBaLSZ$b$YBAu zIgqFzA%QqaGAa~g#Ki=XmN`LVc#)(LD`kbHNJ@9e&@z+U~i*;Y(+t z?rLgyYsHKcf!3RU^_sHoj9lMRRJEgf^w9nOlxn)Y=|FUbd(DQ*V4r$@dLrp-{?6kw za_XFwJOAiuS#@AqzNh?f-;ZtM{@_vPlL=EL`Eor&7E-5SN zTJG!TdZRh66~4;Z^A|n=%PH&Sa@V1!H%80YlELzvj#Y!@1>V8ztL_iSdPl1UZZ|L+ ziLrsCbYkm_)#K7nAGI$7QB=YB1gT#-Y`7rF*Bi&Ms%{lz)6dWQG!ixhUQ-06MCQk0e*uQb_yx`+=| z^t{&z3oO2YVJ8>I$~_-g>)NXS7J98-yVn`ov11L&bGA5gKz$Qx~sv5*Q~wh?@X9cV#>TP(4{nXDuOFX`Se$zwMN+ITD(YhM%79X{2}(;bC?(!sb-T{p=RNhO=Vc+aTS}o58FM}7cTeR@fu3N5>P>=ka42!;MbS*hsdKgT z5EadVO4OYRDog0l#C7S0nLnJ2DPPV_Crdc9EV^9czPRNuCUaSnXHO;j#lK*meDcY2 z&-1)r@6VG@u7WCGx{S#N+2Ah-UJ4Aua2&VW?F2!PBuP;eP1A~^Xed-wk!3}aRFt9! z1p)HB003g36anx8Kmb4kzyiQ0xj0QT2rx}TRKz9-3bAqAi(&Q`);OvdhNLft97kRX z=_PT1Lj}sbByn-5L8wBJ5qOG=vLZ*aFaeXBGGs{xN{}Jwgs9S9N)r^yP9mWy$Ocu7TXd~r=v)F{Ivl)^>PDHLRh5fX^$r4U4sWIKjab^=No`V<)s zA|V&oSW$~gP*&q4!=qD9L=%BDr;v0M;0Zy56cYzn8~_RJqgSKO0j>cI0!;gFl*t9h zLxxQz%OxvCLz+oelHveBLuUX$3p8ak_vo~cAfeq0aXZ9tlnDT)U1R`M0H)z+#*&1b z|3{JYcPa+JT~L_pDfv$n86dcr?g(7#y%{!T>~1`7&Wo5R%RQ_4 z^>SCh-VrclFFEFE+JCFN$yLPE#jcdTC%BgF*zfqY2(1p7A8+9#CRyXv|z)5#UxYQi@js8459K6}sBcER2&AMEXH^c|}=}&8? zzHb?Idz=kNS(vkD%PVIcWQSo2n|tSkui*>7BlmXY>8`s$a{Zo#CooIFFqo0CGo!2B z=(^(WJ$#_E=9U9UKE7yOAEpns=6B!D=}Zk**mnBcD_m`+;3?OBYj?m*YZEqSRo(h`-Zoho93l+kENbX z`Xe31-vp|K!t1ifOcHscS^cB{cCyNSFI^JJe7DT%^g{INoQ`T&5sy! zpTWIg;80mbYGajL)IFnM(D$yt_=$US{h>chsRQ2)OWhg18#>&GMRa=1d(fR?oS&a1 zVV+1!kuhb}<(fHF&rNOCZGS%2yLt@fP*v99ocnJzSUmxEn{P@sZKxisvCVOXM{|Ye zHRZOD>F{ma0aI+mv28N%Nbc(DJvzR6u-LzqvvsE({OIn3jkd5MmX;gNi0SR8{a#^R z`7oiES|^TUh2MrQb-w8cVFm}+_ax$^uRZ#Ce06%+gv_vcsh_RMnc6bm?^G?$U7E>i zsdPVDG^^5=Q$Dk7aIyEysIsgCw literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/22.gif b/images/mood/charitycam/faces/22.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff2eae5aaf4db38822b43112301ba53f23c6895e GIT binary patch literal 1648 zcmcIj`%e^C7`?13thl}q*Hw`n^X1%o&po-{ z_nn)wBs(*!*Z~~iPY5JQl4V(uWuD^%o@XeEz%UF&X@a0|97j3GO83r{X zO+$);BuN+;!)yRx00;)Q*{uIzXfmMyZ~$lk@BrulK!X5)2!I5D3;+cH4c-ouL2#mw zz#)pT061;dpd?@@0)q-m;i|-vIHJll&pLUIphyHlQBfpS6?L80G!{Y*LIy$_LJGr7 z5Mr8!LTF5bX@k&&q5wj`vPQB%mVu@LT?aT02m;WwaYR6fb3714pr}C8DUvcaIh=yP zL;$ORVvu1WPCyJdQZycja}1=(puhwbPFFZh;etV4S7jBop@u?(O$}nGQ)UH$V*f2IPT`1CV`fzLIiDTX?g39{}aXhWex%05ikr3j340um<58{qoOkJ-T7?x z`xTZ6uJ-PeDeqbEXB&#Z4Re?E;Shak%=yB;jKN#wm$Ag`wLhgE@f6>WThSC{-<^-= z_vD?%=5EfvGFEuUYyUZ^qv`nNW#1INSW6^-o?PMEkX3l-X^q2udglYGdG5-(1v{R{ zUCAFcmiL)*CloGiJA7>VVt;B<>G|xmO{K4&4?fOrK(h{8yQu5lzPJUgXzIjp;n+~o z*~|l*W%O>{V*hgs|7vD(<5q`@9jF=X7`^S`$DV=bt!8Uve_~cc`IU&mgC!C1dl%YP zY!|=l`SnXnyCouSNi9nCF2W-dSBjq2n1R<`5)7MXU1|(5hh4RAhg&^e1tI29+t!CW zuNHi34;_0m+|zlYGWU~~{l#;rj<|ExnFCc*i~YytgjvHkd|N8YR(D75>ul|ezM9b# z2*0tv*FKZ&Yjr2z5Nce9tA}^6v32g=o*AFos28WLD?( zrDWUXNtT$3DW<_o`!Y%`j(w?tFmIE6pxYV}Sp!VgXAxsY+^mK}IVt1&diz&aMb_hv z^AFQ|QrotOJ}{@+2e1-#emvE0(RBJSQ(aw+3fnVy5>EvHn2#*=Q!h8|KfIZ;P1{jwrFnpsgjBDc?k*hs&Y5SM7_?r z=^rjVvfcaJDR<1?{A*Ql&F+Sr8I`rcJ;SAE;`OH&zF)oy1M^>Ym$W5~_cn}}g0X3> PJGNP4LZ3|;59a>^jl;q$ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/23.gif b/images/mood/charitycam/faces/23.gif new file mode 100644 index 0000000000000000000000000000000000000000..d969c6ae97dcf113fe08b6474d6ccf5723f14ddf GIT binary patch literal 1683 zcmbVL|5Fv$6~FKCfVT(;Z#6tfR)LVlD`=iBT9s~RkuM98Slkda(d{5~Tx0BvYqU{k zt?!w~ii&Yjk|Eo)^F+JaY9`kNW-^;E^WZIt_9aWwq)E3;(=jF3YLO@V4!K5X__3vxRzxb26k+0TNcu>ZMr7Hj)`rA zT@z!+wGHfpF0x$( zS&S%C9@Yh!QV`9Fq=hBJ6Lg2Cc|vnI+p!Esg&d(+j3kSy%^RL#U|Gcs0RgX5B4PxE zgFLDD6p1vk#>kXx2^2$$HYZpNB@-l1nEs`%C}7^gmhR{p)?_R*2E$=aa7Dla8goDe z6r!O>(;_2bm9}{Xi!>HAj3D9=HYt+>G*CPpViBkiAQIS=fK|#B2#X^;9`FQ^NEI6d z7QlQ#5?CDI05BjhA*YFeApquq%>WIOt^^Rnxhi3cz+iv^0Ygz74NMVe3{V+h@W7QM zT?IOi9BclZqA6MwWE+qUC)fnE0dNFy-kYWcfJ;-Ffh+=Wmf`Y@>>1Of!2%2^`RL=qXQZK|%JI3lAU$q}GJ6TAW~OLsZwBmE&I$Mht> z3&O`?T{0D3N3`cye%pc!e4#~O1y9F@W;(ntv5pwSK!#;nNJFwH>xwS%680Y&a53RP zlCpH<=|(!82LG2;d7%IRv!HICJ^v@zFb01j9%@59?{sU+%Xh5n%;X6d_76Qj7f4Pm zT*7vZrItUvx-<22s-e52dpuP1KqZ@sgI|M%y{$)5@xY7uA^xMs*IwQF*tuXiv%PvM zxBPpn2IpYtZpG#2#s8>V&M6B|HgsJ&`me5;k=m^{dVU#MTelHCb9v84qX$oaKHl5& z!h6-bvsbS_Gr8;Nx3NI-k@iYAtJ%eUh0FgK zf07LpTuXwS%7IWh1%o-GmZ( zuBNwt&E#NTXYR4@CNc%dIjN;OdFZP%rK7(Uw^O?=5pY(1H)V9aItf}moNjyTer9m+IF2CU54}P;= zt$m}0eKJ@JOO9t29iK~Q)-vpwWw+!=L2dAGKM~$FQ<`5@p#F2^h6_)iyTQ`88}rK# zzn0p(aQ0rLBlf$>-lwY{zQaxz6%EGkhfl0QVd~l4Rn3dHP6xXhzWMOuFtz^PmbL|t zT?q`3O9$DB`cvtl8x=j*uD6tT?I<|a*u1E7f2d@CvUI8pL}!TaKb20jlKp!V8%ujb zquC!VcsbKl)p#YAT(Ty*|JH^>Y}L)Ox{+IX58CnvYSGs-b4{h~p;gJspQ3#?i%$$B rrZxrwpy9QHpImt9o6kLD6?65aEs;(2y(bFeg;ggjdg>OHfQJ79J~Y`E literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/24.gif b/images/mood/charitycam/faces/24.gif new file mode 100644 index 0000000000000000000000000000000000000000..7570761ebec0c505f73922158fc0383830a7eb86 GIT binary patch literal 1611 zcmc(ek5ANg7{T9I{g;xq!pYIoF`FRFf@@23JSSy1IX2Z{ECl^Ca(+ z&zm=IdF8qi@1`7(12i4zx*iUP^+-fBsvu}Quk*aZvKq(f9H+6YOw&5cN))9rjLtAB zO*0tA;ka(-6s41-h~qLr=zc%v@#uz*VF(1NUa#i$atNY%JgnWWx!n?igpCG4Xc(65 zb{>W`yPbd_5r!i$Od2DG0>c~x@em|HkOV<605||N01N;u02}~300IDE07L*H0K@=@ z10Vq)1E2t)0-yn)6F%LCYhI6LHw>W|1XKuU5YTCZ)~{h+8Uic?NI&NH`$Ul;c+yMz zR9(Xv5*JvHpP<7+SXE_JkI1?tE36=SaK=YaoFFs2!iQDN$N5NwViY%~1Bd{2-RLVObR><9D|fL5H%clHPw1Y>FMMI5FM)ZU5#sV(lLcG>r70 z^10rvSTh6{LB=7d5)2f*}_JPn)r>(SjMmM3y3SHk#nV$7bSB;eC zWLg&ef@WUZ4z_*0e&JW0UESUpvDWI^7dl~q_txGwLHOukSziCt$#PeC>U>8~6J!gx%&8??&@HtumZIiVv?hAQ_QyI?(t?&r zlWiet+6{$1dRT2OU3#}I9Ua{=1g)9wYfHPHc-P#tC~InPuG4beE<{yNz({`0Kkt90DMQHh!h2d!^pCb zZ6lII6onWDu`Ch0Ms}a2Epk+d^kxxRTpoBqHL6)qbpsKPZ z1$EOf!3IM!D3bD#K3&o&g0d8gbdfYk;{ox3ux%-(DkxwA7@$dEUD9M;k~mRhg9!OIpW0(OX%xu8zcwvPoLYm+pvyn#3D zAOMesO*#k@Ie;L+MS#O)BZrBQjkocJFO%2SI?561s;iXrsS3N-AkVnx_5SOv7o0<+c#35 z6{uT!j=S2ZS=GG@Llb8=Zkl^4cdUQ$?r#zkhTfikqHJSA;K<0M#FKd&x-M@${d;?P zQ_q3N{+=!^F1cXEwUvV_9nI0ZR$jm2eKL|Vds*s0C@c0&Mw&SL=o#gcz)5OGU(NW# zm4{06H}*WsKjr#p{Be5yBevq}(eCN3qnqr1Q;t)M=X1r|@AVB>lg}*(O_^9&)|Ql2 zakwOuCGJZtt{$y^()etUJ+<(KzajSfbX~lEw&U@c8NDBj+g}p(@b>;>^u|{qa1Yl` z>i+X?VpYeD*5OGD_?Q*L^|x}&Z;!nnb*b(_yX2lVx~lE1z41?n0+ZWo;yl-r>K^P~ zJN2P!n^+!oeEhcj!lcwX-LofqV?p#t<*}OHuE_&wyXWO_F@OKGthdka9Dh`BIJ4T; zHAPan>gEda+@Nu!wmdbE9h;UtoD?^)F>{VHx65n_MU68Xo$uVwJdu#67etRKx|tLm z<9r!vsa>`6iRfK=^S7bSDYraBom;p?k*fMYwkxkca&RQ$v(-yiZ#%hTNhC+U*puLo zZS?Q;?n*3ZM2p(Wf9zUY+Fy>EgqyAI&I`#IQ~OINEFgVT^Ez!$Y2URgmCczu36^X94!+b5kr`(Bc_wleBNPvmLQA6L&yPv;eg5l>srwpoQguW3MYn0N1#7av@iGdHEZ z;6`b3WP^8X&EB;3O-~}34Wota?yUt`x83!LQBHDu%=GNdy-&L<(>Le##7|)3qG}F& zd3p8R@5(=I7+JR>Zar6uX1<2zOSyr(7YW68(*8PKn(&3DFB^EkR~@<&>xe-!{{si3 Btt9{e literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/26.gif b/images/mood/charitycam/faces/26.gif new file mode 100644 index 0000000000000000000000000000000000000000..344fdbd7bf211c45547316a725c93c110134e4f8 GIT binary patch literal 1516 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 Z4K~#ni?@vwN*Uiz{vfyVMsN_e@IOu6p?3fP literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/29.gif b/images/mood/charitycam/faces/29.gif new file mode 100644 index 0000000000000000000000000000000000000000..f85d7c755b0b3b58bfe051da77b68bd6856e8222 GIT binary patch literal 1531 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/30.gif b/images/mood/charitycam/faces/30.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee1935673ce7cc09d343dd60ef1b068f294a8442 GIT binary patch literal 1632 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/32.gif b/images/mood/charitycam/faces/32.gif new file mode 100644 index 0000000000000000000000000000000000000000..9785184c8207dbda70540ed5be6bb225e3bfe3f2 GIT binary patch literal 1495 zcmZ?wbhEHblxL7<`2L^aKM=^u{1+7X_j&%mH;ev$X#4xF|L?oTzwfI5zAgRxI`!}C z_`k0v{(Tw#_j$nIXW#xlbNu_H;P0c%zxTiVd1m$Jk@TN?Zhx+S{B!C3pY!j2AAkLO z|I6Qdp8xv#>(};YzgidneEt2Wz3mSlukRZke$VOtcK-F3_4hw*zVYU=@M{K!R|n?5 zT7K>MIl-rkFFsm${=xh+_vf9yHT&4*J;Il#9k|TEaB+3n#i{$wP2O{Qz0Qe^LMQsR z9q-$Aa7zFFj&=Lm*X~*>yvsFmXZMV4P0O~jFmL()f6IKCEnSn={rR(QrtG?!d246! zuPC3nf`xf``HUr{Qy26~%`codC%ANFsA;VNQ_Er|XSPj9Z|+ZP?yBMHN~&v# zt89!ZYbfTaiz==R%PY_1D+|dkjdLqX&j_dHpb8SF4^?S+lSQ@Ffg*Q3MhC8I38l+5Q%uOK617?woGG z6m9bVxxphw29svCg@R`ibtXEsT$mP7$m}IyX~O<%Lt$|`=R^q~6+sS#Jx`d$+*P+- z5x4uX;HYSz3*!-i;Dm#$k_8@ax7uXnmfUPtsJrpdfkz_Y03)Zyh67!E0RfJD9yW~! z+7wD2IIwD*m~fci^@sO%Vl@G)d7$&@AtaWl&ct=t8;j@6!7c13g zM5J&kaYSXU-QX-7m7sWmjVE@>C68)`OP7|kJxJ7y*Lx#yR6M06J+N5m?InB3iJQOhLwsa9=kqy{N;4lcHFLiD?!;|9^Fw?=mTgFkn^S=z zdl1{thRfV1t-d&Ns05T8;xhbE;M&9`*W$Y4;kyIz44MXohxxo?1dqvhT=j~S$b2%J zP4ee9M)o8RMYBZ?l_wnaQ_4~z-Z?TdGFb0oXJuiq_S6v*V6YCkr04_^lb^67@OWC* q2@ff)7Kug2PgTim+N9i}vgp|1l?wz#CpISt758)`7%dI~DFy&t9rPFg literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/33.gif b/images/mood/charitycam/faces/33.gif new file mode 100644 index 0000000000000000000000000000000000000000..b8fab881089c52e6484c1c4a574d1da6cfe35ee1 GIT binary patch literal 1588 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/4.gif b/images/mood/charitycam/faces/4.gif new file mode 100644 index 0000000000000000000000000000000000000000..57bec9513713dd7d8ef247fc2d2724ef02c2d7e5 GIT binary patch literal 1602 zcmd5*{ZG_(9PYuP^}Qf!6%`JVampCyQ0ZjJS(TSgR4NXv7~wh$u1=9UbyhP@JI`t3 zPOMY6>O}W-H%1*pyE$iQO`xAVW)=eN)2$@6)h-&-yVa<{%M!2+(bk!$f&xai491WV z8dstQ$+NPly9gYo8It8`PLMSd!wI(sqd5_R5f6p~SrsG|Cn#Q2AQ&Y`+Jg}Y>V^@Q zB%2H?kQ7Uh49fvkvw>`?T1*0lDCvqCU!#hmDvAbxVwy1w!wtihBt;Ma&r608BM1t| zNsg05QN=KVBpHSgq&Qcx2!a+xO_rk^2Uu33C=SC&w;M;}(l81^u&UUa8q-u;6jUG? z0xxr{#LxoI0Zp-0*`i2R0a0DGHN^s=t}41BYaA=E4A0PpilnnNugjLm$r^}qv`FGK5LAZZ zXp%J)OA&P)SQ;<^ukwsY5wsy&I*4kLDYC!-7ELmMS3EAvkmE-~=2Z%(b;ZzR-H1Dv z%y|4VuK+Hdfo6iJDMd9^Q(48t#TX747!zS4=H^v|G7-i?*cc|nJUkC$;cyuG-;e8s z(*Z#jpxjqZUvw&H?|p)17OY1rPW@H7&6$yM z?NGrY4AD(t!$>tN%3JQM@N19WT2A87m{OENK8acG6G}QOmu|xY;>RoRpj!2ua>ECL9 z=Y4Tf(Tr9mMnS{jc7L-YC8r@&+gjLs-|2-qf~^UG=%~5Kx#N8o zzCt(lceb)s<$E(tt10%=C2e(4n%IDEPhQ7R4qa zoW2#^aK8TRqpK}>|16)j&)3$Mc{lHu)fWf{`H`{Tt^dr_8=soV>5Ib->Wq&jg(#6WyuZ=^x+m+*on@_J;>T zO+VC?PAu%X+qHRD*Wb4S!xmkRUYtLp*B=ON>1iw;mb3KZb4FYkO*%KAn0ZtF(^(es1T^ z^s33n1Gz??agg5g(kJBqT2y=~Pk81e1kmrflDh$Y(lfbLN;ou$O`UT&KazSi@4au1 zCX`J%+(nkm-q+t!k{LjK@Wl6fCnuMz56wRB3g-ICa{XJlU}|H}c$pWP yRbTwZx?pGb=*@lUk(pzbysQ|Q`O$-lz{CaZZe$eYo&9|EPH$`XxXVdSXx4w(=AvK# literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/5.gif b/images/mood/charitycam/faces/5.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb7368639e1f70524b2dd828ce1d78bb9121f670 GIT binary patch literal 1472 zcmeH`|4$Ql7{@=QrTu_Kj)L^iPB;a$3Db2b<3JZE6zk0xT5*Bf7hvbmS+`M+MY1zX zORuG969JEX?UK4#e)1B?yvP!ofI^4UbdZ>v-4D0bxZGG=F3WUvKP;Mn|xB(ym zpaAdyK>r&j!B7#_!_g!w@hVABBCn+4a)J}13@`Cnj*g3QB`Kt6icwOkhos$hGR_LJ zpc1${;)$lBvfV}`xRek{DoK^0Se{KpXiiC}G|5Q3;&IbrTuwzLitr>kQ4!Rvs75>- z&k8IVp$SG2vNEqId^Qa`VlRU{RBgXAHx?pi}F*pCO|C#{ymresf7}PyAdioPBPz5Cg7UyhiDWKnf@5$wk z^V4Gp)-ZnR=kONGo-@d~KW1-#-t2qSd2I;Z-`46Y{5w4re5vGlXJNV59o%HDC#LqL zZ`F@aJ$pP{wQeuVw3v3Cxwm>M5HfCUc<0($?2TY(i`Hv2nsiR{c}-Qgh;r1iQ!m#x z9NwV|6jy4eA6fzfw?7V>>*@ykZ2WZf;k8DLc3g0^J15F&zn!1U+zdBa9{E;7VN*kg zu}tIWE8L=Yy!yIJo4k1a;0<=8-?4vUAL{FyaJ7Az^zS*n@XO@R9lkuh@qn%cXxMRN z?Cykj+oY*x^N$PTH@(#>%_Bc`TfYhxOzzH`?oy-2Rxe&|5_kSuvAhfUwC3n?=eTvS zc5D5>@X-T9SMq`dB~OG)raeWE@3lJ7On%ARS2N3j;_^&>Mb|!kI*8hn8bh8d6oy)V zEZx6-c(&iL{al~6pyGsYw9p!h-G$Y=gL#`SVfX#8_Uc-fac?eE@oTGp+RgQMI<=cg zY_yHm&Q%49o1E+UJsZLdiMm?HZ|GlGSPZoF%zX1;$Y!k8>WduhKx3$y@BytZ21ul) zwawT7uugE&=olF#&K|1#VfqsT5nOETJ9muz-eG?C!K48j z=F;pl@2@S5Sq5}*^or%yTXTlWGgTi+=zH_)dcOm0oGAUyI=NDM`ru-V7PGkhI?c>u z*3^r*GXBT-(n@*b#z}|y(BNkxIWRaE^4~SF?Iqo7!@rrHWUjZL^@QiTzlI&&Wa8uz z?_N{aomaX;I(#70uhD?!C3?jBTv_jdfv)+TAN<~b;!Wp~o)*xIBA}VW(yrsx!WS)l SjhQ)@A?6B|mR6SKgns~UVajv> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/6.gif b/images/mood/charitycam/faces/6.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0da42c3bbf9442e2ed9b4eb6793554f68e4e7b3 GIT binary patch literal 1619 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/faces/8.gif b/images/mood/charitycam/faces/8.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e5c1968ab04c5f168b60e350d91e7f5aa713544 GIT binary patch literal 1621 zcmd6m|4-C*7{_}caHr>X+yGBSq;QC*r{VBRylIxBDoDYNRfBMlB~oU@GJ_U3wYu=7 z2;#>Gu4bs6ahgUpsBVlp$@X!_gaVT_4wuH6rD4(JT(Yd0?+FZs**%gl)!Oel8i!#G|hyN4Tp`Gfn|}Z>XO7z6kr&c=Pd|LMd4{$;y4HZ z5=A5kC>Dw10LNvYPYVQ?7>36KT`oI@p)iFg(jo~X7>EV~NB{`%2FoCxLmZ1@f}xEt zrH}-o!x~9MiJ%q?SVT|{1_U3j1bi^y6MZ<6B_xTEp*h@xpn^C?50eHNj4CoxArb-N zS)^;aELkd4MF9#x0ldo6nk33Jg$!NfSc&IAEK!3dl*Jf;u12A(Ndhu7CQQ*32}Qs$ zbeJS$z#&bELWv@RNQWq@BSVz{C-SVWh?*=!p@?)P=0=u@OamE^W5O&=Nq`l3hKyYq zN|+)@B7iIf2tuq3hGiK+P!OV36yRi5K{%@g1tda~1SUo*tYnb@xoD&rh!zk==waRr z(9s}`>_KEPmgp1Bpeg%gD{LA;T@66fh;m`Zk~Ji0NY*S#jY?4F08%tdRy76EB!yx^ zkPN7*K(rLqlp#xnqmp8XGE!8Lh9o1XS_(u8#4s!piNyB*eDJ^L z*f4AY^S|VL`4b^K!aj1OZ~Nl%aBJcrZ`}cY>w?gUF8tBv_A{f2?yK0Rf89~%XK(4U z^V7retE;~RKM_*I)@*Zc0+F^zq-2*|)9re`Z!)p9YVh!IOXBwP8;-qs(mi_3xyWBt zD)crq&nKL3UGj2gYue8&E$_c~IeDZgHDlA!7oi^K`#E!<>?Gc?s>ZV@|FPP&sBBs9x{9LH7uGZm{E>h~UfKG3 z5#O+^b#feHhkx(}nyayMp<=&l-hz{_R((IaaPL6Hjq<_4sZM{V zE7Y7+nX<#_PjH4#t&krN%*(r7|MY%npdl3JP^W90Et23SeOG%9c9uRr?kcs{SGyj1 zj)UeT{DYq6vCK8klkJPy*(X`=g%TZ)-OKGqT=fGvt*vucJUFpA|7&^uR%ZEh(`MJY z2h%OCCU3!<2yZyj$2!9j+cP`E9X}#9ZyRV9vyL2?m1sj1&Vj_r{?+l2d~UsHS}~K%U(Wz zZGvM+Oev{7IFYmDX70k)KUaQ+)pz+*j^*V!vTF;*mgig|$h6A6Wr+zl`m0i__H^LH z;=04#V;S5yUX*dP;lP+D_1hWsOy3aRk;(MiW*60`KU34&Qt~f!$EUW;))n`qg+tgz zY;dmcR=}~gu>7^ti}yF(Yft=5_|-OYcbjkL`mTQtB+c!x=NB!zSnn?Op5N;p%Q;$~ zAF*dI2~DjkAW~DCvrY+ACw{`ee;n`2%W|yf&2tl3b@zYo%cs1E@arbxO8p; zb=lhvTpYLuNAH>)#CBW|wXe)x!EDa$k+{uz7o`~mOtCU5Eb zl6nxiNd0EQ%Kf?!FK!f}QmXdI{fe!}ZDG0epZ75k#v?Nwk zdBss}C|izZ&+G>k%he%IbCwb@gfP@B7BG%%xdwz`DOP!;m;O4IuNyKVQ!uD zU?kL$Ui8kzeV>eXw5R4a#`=zh)Yw;ES+p|ogU3HKcNg?yH6N8tp9ox$*6Hg~)N`{3 zM}qao?tMFP`pqLd8yXWY6*bOEK$qul?=6}YiAk&2^`!Oj_11G6H}8J*cgCEgw2uA- z^LEWWwqkenYrFf@%9@gLFuwRmUujZme%fRf5&;SktzI9j|$i zGav^LBs%Ge#}`1Ongb2eNWWeLyTQHu{l(0h1=txFR zu56lM z)P`5ye5M8B9)jB)-!00I$4d_;w`ZRZ)oj2EU+jp-JNxPKyxGq|d&9usD*wjwJ3Kx9 zv}aSTS*JIhZOb~osJ11u`^VZFtzVS|zFB&-rMfv=IlJoit*-BLHY~~6_D4$VU`#Yp z5EX?KAO!{8NmA9&+oMHM-ahJ$pzlff+KQdOC9FO(NGI%iTD_-#_juyQ_T1_}LE` + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.gif
10.gif
11.gif
12.gif
13.gif
14.gif
15.gif
16.gif
17.gif
18.gif
19.gif
2.gif
20.gif
21.gif
22.gif
23.gif
24.gif
25.gif
26.gif
27.gif
28.gif
29.gif
3.gif
30.gif
31.gif
32.gif
33.gif
34.gif
4.gif
5.gif
6.gif
7.gif
8.gif
9.gif
diff --git a/images/mood/charitycam/flowers/angry.gif b/images/mood/charitycam/flowers/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..3dbb5bf7dae1b1668d6b39c9a331ac853d53cd0c GIT binary patch literal 1406 zcmZ|NYfw{16ae5$6CrOxOhUv2ZU{nvs1OiB1sk5C6)Tz+1sw@7z>Or4JVZ#SJQ5P* z>6A)9kYG{p0mV_PMFj*A5UfTXwv0w7Fx4UhwbkmhLN9d2{_4)z*`3{U_Uw;u^Oh)H zkdOs%fjhv`AjTggir`QZl^T>rL)7SqIvr4~0V*`e3LVZ=4xA|lnk#^-HDt3XEG*1Z zQ^>5TxC;PbWoL}}UDu`ezAv_p9{t%W8ntTXei2#!RL(6HFD^DO!jCf-vD+gByTU_v zL~_^pAZ(V7-XYOkc;&zoSo#LAVgUq84?w3<&$pz_v>)O;P)VO1X}KIm#C0(Ed^!kujH9JGW36s1O@wR0yX6t9Olkz5u`9Sy*-J9MJuqXll5+`moAC0WJj74 z-N}(c(pBq?sBBh#V^0#9LZ>q;eRPaF!K6we(S{~1(=M7^td=b;6#y69(WZ^Dt}&piOoY%*;s1{ujq{o~MTYo-g zU(o)xfqs3`-HaO_@s6^$bvV|{Nm#kZZc1o>n_Sw~H*_p6viRV54wA|nWt-A~-KP7vnGL?3FI+=<`fvGhoCs0X>7RpETV%Q&Dv=cx9KGy961P);k)R7= zqXl+x*bg#NYLl~1xHUFu&whZBS(cTJQm~Gkx)HYwqqqMmrKB6pcPErUaU@#5OCNo# zmqsbg{?da`hR0}O8ZTWKV*{{_5p+AdR6?40IXlox=k7Ku^063it=nGyn;&Wo1-;zp zhE9D^rH32la6SLRQ-gts*m^PXx0o`Az=gJ(6OSKshv$&i#2d}wTm1nefo3)r3p8j;hDK&`pPiJ#pw~WVcH`$aa z_@p$h^F0#sIuIpgS>CR`J}UsG+eGiIA1M-2-Ci}ni)^qKZr^S0tNW~@{rz8Wf1i2w zpaUiXkZf+lL{OpGw(j;OvlbJ;1M>*ZG!V;#g)Cf&N|R@Z6=0|gk_uIjTn38dhcXpV zN~#JBPZcU4RVK*w@$p>;f)R31CRc$6Af-wHC8xzEZ$df>cNe!jUXjfQJ;&VIf>6TW%wjiWMSAm7(6CM2&I7n W`NyE>-~J+@l>gs$om`OuZ2Sivx){p< literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/artistic.gif b/images/mood/charitycam/flowers/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..706cb4b60f1617cad00c13aeeb14cbe38647c08e GIT binary patch literal 2623 zcmds&X*AneAIJYB2#GYCs-pgulGa-7Sf84RrIt>sN-JYaXh>8LD+Aj@00;meJr1bN1{w>29spLDjr#U1Do`>bPy&HvdIizal1SW?q$=Ws zJpeEsF+LMGz9|rFrf+U;692m8Kdzda@M8`hC+%$A988T&AX1W$<{DJq6i@~XwhFeM z0my7j?!9z|{sXPLE_ALf+@O!mn24@xkmutcjqSDd*rog<+H~K+{kg6K!~s`)fZHs& zWp=GF?WK7%{@RXF!=c#pg46{_DQH|Nw=fSLl@5kOc{Do7RiKmTq>SU0)@d~i%ll9@eyBP-q;QqbI|LWOF!fX0dXTcnlw zG?j+(=l9OSO?cNDhetcU3a)!m*x>av)m6t|sP@TkHb^lIwy}DSId@avZU=#Hz50gn zSi?+T-6C2nR&_)6m$ZG6&7Z&)8*3c+^806MkiSC0$Z3!(WwXPK42PL{6?2H`nIr|x zza!)-n2fpqG3T{Q+x(R9Ras%@4Au~LTOb{+iIMAn4A=E3uWC3S6~`rBcJUn$U^QTg z4a3$bYq?YILnKht;#X;W{HI?_f}!7TVd3K)dQK}jC43u;EEFP&e>Ps5mS2!5!J@P* z8^tRK*NxoKUPP>7xk9eM$Rx-NmD3)@kO5k$M;Yaxi+N*!HgJ*AaLobkTC zC4=MF>q`+QDXu!x3Vqkd2j2`+?Y=f!>YHC!#G;NQXhpyg<-=nU%C;GKy0I^LUCKt% zi7+3L53QW)PDsM4xkt~^NR`&U36#+0{X7eeL;0GlP!zt;1PQb6`#Za`RLcsM z0%!gEVLQd^-Kkn!-xjpg8cyNWJ8o-;Gc=r#AI|lFn2gBB9$bR8B&w_BRV-YP0{+|yJ5fcxrA1g#y3A}0dNx#SX%t~ z@)cJzO>#3A{X#=O<5s+7gjg#nuu|R9=+ktAtHq;|F(7L6e5*J9g*9Pib~+``eDjZ0 z&d0?UgBf4@w~;4`QYwq%yA_+q=m6j4J}FAp>bG&;>qyx>@?X@wirG@qyZoY%#Au%+ zDN}Plh0Ka1a)@GiRY0nCHTfD$QPd<(Hyk#Zy10M6w;N_r?KO32{~u07*x$kRKhqBs zz3rbHTmGrNU5t`L<0>k3wghy$t+pN0h-;$%%RhAz)CRD9wOxpTQ>j&J0r>s7Z*6lk5h2uBg|LLnwdSs{1F*~P!oHG|&bbCdnQxPeeIF?lp*~kTCX<%W<)k_q z9?cIsZA9}D&pm^ORPYr6DdI6HS?Khv ze=#Q|=tF6fygsy|sFNp$#CJz7Uq(r9^C9!!zo-9m`Bcd*nk2ED-jtS6ix$~ydtIlX zSFjrvHn{RxzR__voL@Zm0N)@7)nf0ZOMG?JuWi?jdspkrdLc;dOmf9@l_yE++WjuE z$z?xb3d*N}$Uz!Z##y;4KEG2#2Zrjgy0_F%^S~t_zI3T{@W)^lC!nGhb1m?p<=mng zuo{vAATfH#%n(4=+9GDR?%mUOAw3v>@x|SdACgq3Uup{FcM7IbnytV||*tc~Eb{21s~6SgS|=uJl3B)tGU4k7$3E z0{>M3?=3I4gg-biLyqoNcalz6^Xx55lGV!hOH@v<*qx*md%;g3r${8GDt6-o)Ag&{ zB^p{Xo4WMX@SUj))A3%YJmINmDs#V@^R|XI?m31sIaC&C8%AeP*mPzX7|0BdVbOzW zY|xHIVbR$!ps9(;0V5E!XM$l&Hh6{}!Di6|BH2`sLub>Nk!+A7iLt3$rC|}&FgC~x z0x6M_BbKDfgGP@4B{PW00>fGKD2k*mY`YDEL1hKfDWPCw1Qle4g~mwIiVBJf-%#kG Ypa;_m4E(EqAcaBr_tuEX3I?qI1Ub7;3IG5A literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/blank.gif b/images/mood/charitycam/flowers/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..2246c42117ab5d16a8ff59b0a6b9b7421b2794c9 GIT binary patch literal 1524 zcmaLXc~H_>8~|`s0uMk?1h4Fem8-56p_WIspk^NFc-5L|fgpm5pzu?J%2fo#Bd^T7 z!<#fUUDwiT(@aOpF*PeqD=qBUjIy%v| zLP(GYt`Jq=BRHs^MOZo)&jhi25t&TJic*0jv1?-9K~Z@~V#QHm9X#tKEdMkjHyu_Y z)u|}Jq)Rd9GL1_L;MF;>i)Z2OW%!0Nb6K91tZ;kD`CVmIdrE6!;20d< z0B2wzK_koH>Iu5YN_T#Fg)Sb~tvHvQB0ksQdLva=QjaqHI_DHbckcnoS9AVNO-HQ7{^sN<~$Y-B{j^W3;Cubz$e5 zhNy3UB+x*J-_#tk*1O^et&@yl2i502tXZ&>9eOi?xA9QU)Hh}HoI-PE9V&u%X6wGi zK8`OrqI_Z`jK0o_S3ll;)7`WsQWVuSC$(UjG1D<58?;2rc&aPG_l!4{Q+$cCdiRf^ z7c<&|6?&t!P;Zpr0FzslIaM2btP&^tQ-`dkZYL{{?d3oFgP=qj$xzIv?>8}=o6i8! zm#g*7i&@WQJ{5{c*|t_o^9*08+J=@*|D(kQrLN}I>HQwrDsh_!3J_cLQsq9A+-pxV z0)kGUw3TLIB;j5Qw9I``qStZED>)b=l^S4#Dk7m_;d(KixkvvaB19we;OcB$WT87V zzd%K#wK7YPkd)QPXZ@lpEc=&8I!2Z$LUr997!Z9U(pp|o)!tn;hog;mn-)+!V-H++bp=GKULnP?fpYMsq7+}vf$PmxqP8tK^mE+`R;Q#{pR zz?(_7My|x=MBT^%`d|(Yv5HvM$dDaWM}Tr=bz${dzY)GHm%<(DWivg>5TZ&4rBW`A(d*nFJf(*HgOZ|mQA-!o~5><3$#RJ>cVLX6m8Se91LZ)@@6hWV&`dZdH zJvqFjC_X^pvSVo=o5uy{yf`7B9nAs(cNUG$2895LNZhpp06cgAmj?n2wgBX_BNM@D?G7G48shQ~p?!5> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/cold.gif b/images/mood/charitycam/flowers/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..307424d9bfdbd08a98753e27416e62b83225aa5c GIT binary patch literal 1622 zcmZ?wbhEHbRAw+@xN5@y1mdwdeDzf#$$8>wB_c&t4h{|s4F5%{8WqZ$Y|Hw6s%D3j z&55pD!roQQHldcMuZ?X+EBBm!V|Fy-dgf_L3*hr1@8Truh1p{Dy6JKp^3`uBg;e;@!k8U_^q zbNji51UowhxEkphFf#(h6@RjDaxvI2=z!FKyve}!&tYDHhmKVLi6uoRbFAiHSW)7& zHfsHiHPe3HtmT{kVVgAD`#sL@9~!9E?|#m&|3_A2QTq>Rxo>rxEUdzwCFwSmS=lM+ zb?mGh!omXX1-)tUV%c#$@$3@?1o$Sqq!nf-h-ZrlR(8iP5D^sQU+g5j)LMXj&0Ka# z*{<2~LPDGPx3~z+iaWI@+rrS;aBV8P*y>G-Tvpb`Z(43_Y5cHDIa~bt<`b?G9rr{n zvL8KqobX(H(`G*Rw|fPZjTvN4I0no)pl@Ka#QGaUr){Kc(i4V&2?+;+je!>frB%b(!{7V z*>}c|vVN`+UeqD+p=_?*uB|tudz{vs;O}~s(|oQaNT;NwKbl4J$plY{geMa{)GC(< zdzrm_GRezEGj)=W-%6EeH9|omr;!34CUnRit8%Ll6p~dPArhR*mz*NVZ?#$ zuNZsxENC_t+ney+^tMY-vh^~Cqumb{x=v;=QFKzPb`#^05Xf-k5#DASAJ*jjw%YYTMaHry7n$d3#^=dWH&X=rxP8m1X+NE*S{@pIr-(OMGB62 znYoE2nfZAN$@vA9MVaXtB?`_NiA9+ul?p}%28MbH3NHBydHE#@DVfD3MVU#ZC8-MK znI#$dr6mgGKxHMVAgy`Dsd*&|`DqG?r9i17pstXN%wh!~O3N=&C@9J-O9bl616z}u yn_85dnV6$cTAZqopO;e!RL#r9%jKJxnWGSrZ>5k7u|GL6*8#!Q%P&f2um%7Fsg9BW literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/confused.gif b/images/mood/charitycam/flowers/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6bd0f62be45b93c380a32ffb39266eab31c2de9 GIT binary patch literal 1943 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 E067D#tpET3 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/excited.gif b/images/mood/charitycam/flowers/excited.gif new file mode 100644 index 0000000000000000000000000000000000000000..38cd02a2fa4d64bdac47d11f261c2842c355dd9c GIT binary patch literal 1907 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 aSqVTm#~q0I)<1@xNcqoo3x^vI^7uC)&A?;; literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/gloomy.gif b/images/mood/charitycam/flowers/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c6b0d48b02f100054d3113d1a50a2fe2a68da29 GIT binary patch literal 2662 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 LOuhV~bOvhxLl-E7 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/happy.gif b/images/mood/charitycam/flowers/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..bbedde0004c7d2a1a3ae5b9d142c93ad13f88436 GIT binary patch literal 1895 zcmc)KSx{3~7zgl#faG#>6AXw^DPBaZ$_^@t+A$abkwrkZDzu4V3rhka5OApwQV0kF zVJVdW0YNrF5C~K)iy&wKB?T>`fQll5&{~Q!+8LxbsZQ-fee3kjnYm}q`Mz@={_{JI zP7Y)W!w6-KYDTHPjFYJPJXEU$E6LM78m`SmMvS&lNXe+&PoY$vyfYayIm4V>$yhzTKb1~T3;p4gXwb%?`Y149tcVAXh6M=da6>R=A`m{5 zv_(@u-c>ZN*cLnPX3y7-v#78mR5+z<1S`)9gupenmrL#q|=v z&EHXXQd3?$HuO*e()aDPc`1KB^8x~C2}Cv)D4kw>@j5JH+OR5evePaE1=miAO6?ep zTh|nQ>x9<}ASj>#FD%vUT;lEZGOb;Q^KJ@>VQJm@CKu}V5u4q~JEM>E`8uc#mF=oZ zgNjzJHrezVJ}TEZXf$njo>8-@%7tudDr%a1w}mrr0_+8gOmiVnu$68Y66wEEMT)NQ-DI&L#v z;+TGEL|$;@M0~1f$dGdO;ykI6NUY zpOAwCgZ+^xzEtBYqiDvrHdhFFp;S^a8YpdRl{V)<-`P?~uCCd#p4|36fabAB_nu~# zc(|vp5A?RN*fP~MG5IJ5v}F^SSRikFc5eRb>+FZ(x#j+Nf7FtPb!bVaXBBb5^WF=W zTtCfwR^(?USd`DX#QC$lx<|&TNoeE7tBYDb2bemof#qE+!wS(w-k4o8E;C!#V!>lW zTPkKR6%?%Jj@V!n`y9>Kr1o&B0UlaLS&eYZY9W$It$h0oD>bJfE-k`)an841cX-jA zmt>aJ7WGtK?A+EcaSh32VxWx!Xe44lADG|B=;07dR{6(UF*@}(eL9r?6AGSCB1KsI zg9<{U<8syqDL1<6Iwa70D&2QVdK4-uk2MF1AKpIAkD+KoYZtZ{rtydk!~?Pun~ZG0v6%Sx&UOm;zy%UgQs7L1Ac%q!$41*Cv$qrl5I zRmb(Ts!Z8aq=AD{%Khg%nwo4L+wxP$^T%4Gtctx(HdOB&JD;se?bFwrO0-gl$rQ8u z4=jm+^;b^I;-bDEC{&kO_BZTwPGXA=t$igQLqgF|hGL*UhI!H>0>cju#y39c6E3qw zs#rAs?fv@itq>qQBt~$2ge4cs5q^ZFl2DE>YsteYv6P?zX-jL{MW|3^B~e@^lU3%8 zs n1i>73L;_L`X+c`93|0i}#n}xr|GJ;ah@}2KHRo_cP<#Fa{M-an literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/high.gif b/images/mood/charitycam/flowers/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..11c819b08cab2de0c1e42b1cc97b342dd08ff7a0 GIT binary patch literal 1928 zcmd7Qdr*^C769-M67nTHVnU;dBxZZRHVpG@+Qp5FVix z^UlX3AqfZ(s7-jJ5Zwx`yA6+82rdm&S3$~Sr7KV@h}O}%J4+oGHqdsrGdr_?@0t6@ zow?`CIcM(g<-`Q~evUs70es5_Tmd3L5DAif$dnxvVrCKcYy}~gPb?4`Dq2!YTi=p&h?5jx^}8tjd)_)V%B1pYHQ?1MqDF>4 zSLJ6ifR6&*a>kJ30B6yr~KC%pJ+=w^cpNkNNJMBD z!p$`#^#>#-0$>9nTLW)>698^V*>Z(arPjbz)f!ffu9~H-t5+Etn%Iq|`sNnh`xo>I zvqjn1(JBAX1bTR&FW0s=fqy__FgOZDv75p|*_!Nq0|UF|6b#4$F@}aw%AVc3_xSmd zP{03(g=P)HAN8Qw>|9I0tajGBp;mA}PM1`PPzt9CaFbvoWiK{*|>w^pw zo=V%u-K%ZZzcWXO?#_4#5nV}5sHHy{MxeyxDGW!$^dE27_lYFqb!1f?6syA};(N0L zq!`To2lsc}siHCEL5cm5Xy0A_toUbpJ36VbZ*NJ@!jK29^Wcd{;qVBE?*=THUlUm) zhdnkBNL;xkeyqlhIPrW{#&UjM+VycEeV73NZdd>i;sAye#jKoK&soTHOWoW!AGRcy zo*=!_IKNZ>k1y&dJMG~EX-A{vo=3|Eg^y`tzJZLa+IyS|jdwZA4{Iw~NSFJ@t_5d{ z4)F4BALhpg6ZgnFQ)}WOXhDjMz2%5^iwbXu-^96Pr+6J4x~3$gJLA28Hv-+$|4F)+b%sd@qN(T1 zd!6d%_H#FI-^;+Su`$ci5#;mrr%hFRJ*RcZ$cGCj%lA7;2zRv5Ow*|dvQGACOj5D} z8|!|4#G5crn-7>Zm>sxi@xC|@eB|;ie@a@r3=Gu&?th!opmt{o-emEtk=KX3d?C$xBNRd4@E{0{ce4)Y$uR zKXaV%BVt(JJLt&+`r731EN29a9!|d7m&NMH$1S<}s^#N4c6;e}Suo!JwKI>U%vQb6 zJtemX?j56xf_i^pau}C=_1yC}ryu-qeB_rV{nlO(P26&*XJRsh3+`~ro=`vg!lD8_ z@{T@~;>-Ds67}AOCkhQcW>p!9BGA4*fjAOdL&9;Q#{bJCbp0#0_-B9HGC8zma$%== z+oW>v%^9u!qWgnjXz__-xF+D$20%h>)ZG77#8ht_eRVn}Gw{r8=GB0*NvHMfJbWwE zVpeRM6iaSzo22TSql(yV>@Aa%D>u(FTqZ~Dq80bg=T%pB)T!&>~^d=3nevape(Lq1?g8_abcBawvj$f#A^vVQ+{1~c>;{)HW2Kv$U3 zCucmFiA28vY7?gN%s;_gxuSGd-doO?to*h$Xoc#%WT(a*e6d_+tP;~ra`nPtu|YC&84+qS@+fI;BF(*9iVPp zNhlJO<%=LDpLdEQ<_Y*vu0SXe@!sZ&p*Su_#1l)Ph_JBmPzZ__KzxB1%HtJ_MZA+G z;(Vx#C*}%D#88OV literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/horny.gif b/images/mood/charitycam/flowers/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..78d4b27f5cddd6abedeeef737a9bfb1c1d7f91bd GIT binary patch literal 1847 zcmdVYYgE!_7y$5ppg@X7ifmtswvrJH5+KCsDL6!QWg>*nHMN8 z2<8nl&}y~RV`V!)wbEHxYr0x$S}B{Y*=@PD>Hf6sY@hah&v`$*=e*Bzp65C5kMaJR zh!t!iKm{fk02I-FQH11d%w8!jl}|_$;e=8ekw#lW+Z7?9(P(?)_Tr>PphO;>U$Itd zNXoC!DJ5RPFcCX^~B(2=gK2DLtW8AE>S%s}H`Zs|nWE zhu0dHncLS_AKzHg#x$PWQ`DVnxFiDr3jkbM7bnSuY@bFxx&_DE(=bIy64 z)YhKg+r#fall#?|pV)40?;B!WznyaPhG^)!0{hsG+b?n+A5dK=(e~;pzcC#gvB^ho zs2|Oi%+9sVIkx(rM8KTu`naSGvGjyEDrGr*9yE5qFHZBR00UU+Si$j40CHBwknd9{ zRmJN4B?n5&$}2S5gNG`ss%vz$`cfwt%(=lpCObJfBM@i;fnmfE;BbvG$Y^eF$91&8 zoDgLlL7nXjaJU8D-deq z+M0^ec>K!jImaLktIDs+XQmT(q^(=Ln$`B8HBqxlw@`h{FY+|0LTRjgKjI>N*ycjY zz}H4rP4xS(Tp%>aP^{0fQ6)k zgdNc*XKiJ;xxXmqt&~s21f#(p&ZW&*;sl#-ah{P;hq&|w?{GRzVJ+|++ zfeYdvIG0D@Qyup);ffjfs0`EJxKCO&W*KoUPL_d1s-59hpgx)wi}5{C9E--*d0rzP zH;>cjue#MpM0*X% zlOjlNZyRO2va3NqLKZLEu| z)iJ}@`^3)5Ks@)gIt#5r!SF|uP zFwVWi+M@VA!`pdJXVQCX6tR9izqiX^9IcU&SpVo09PF5{w!d((8n4LVu9{czSg@$V zKa`3lO{;;x+;JL;UH|~{z}Yp-F1GB;yv&H#cV~bPS`H?cu5*^5{oUC7VgGV zL>-m)D#4q4w|m9ZVCM}>?vi}NreJK-P1E3KdhxAk4S(n~@fhWS4H$2}S@&V$lqERz z;}Dg5P4I@WH`4p?OSd*YZX#YT^LlP8j0&Vmox$$HlL@C{Lh}5=^a7GVjy1#Yx-J zSq0BXq~v!zSvr)INiV3EyUu9KHw?q=9TP^dy9;k}|k?Aav3MLNG_j&1XY({MT)GJdQAx%gzSHc^pu{&n|$n g-CW#U*0H(SV3HsbO#QQeDw{|9=SmR>(}9(L0Ify3+5i9m literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/hot.gif b/images/mood/charitycam/flowers/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..22c85ec2f5f6ee3d257120e026b2f3eee93e88ea GIT binary patch literal 2876 zcmeH}dpOg5AIE>2O&i9>6rp|&v7RI$k{)IblSB7PA*VJoHivDt*$Cw@<+R*MV#Jn~ z(x_VpBBF>2p&EBNrIM76Pj|Nz_v*Qx>-p=sdj5T`>-k=vKfc%X`Mj_1_m9{0`hJPq zJU2U1OaU996AOG_1t~yXF>tv8QBjNzjzv?I#YGE+js-FT01zAAwX4j0#PQ6=V3@201H@tPk+A#0AB>x9FAmE z(rfGEUbV3;@A2X%lIkyd?l8P=)P>)whv~uCthHTL;)9tQur-Vz(aHHU^A$M{9K3Ml z$j9p+?kf=I#b=Vi4K*rraiA|WdKol>&e-E4G|To1;Xr9f7y=RQd!-8$2Bc&rVn;p~Ac`=ANm z1&!jH>0canR>fx!$kw*dL2qmxd^uv=*l9l1aq3pR_nMA;pi=CM@;MLDWF5^2PRO`1jNta zVqm*4jdrwA;^Eg%`-iJXJ6`A*Yi_s+@iNv{A$6*oyPrB^o5}Y{Cmit(8x-p3z_KnX z4A4$00XrW$qDNZ7Yc~8c^i~oL4gOA4Xh>XwNlq^N2T?^RBtJ7Y)s$W;{#8kow7M9T zA!eH=3evTzFGw4-Q2aP0Q4HuI2{ zHiw5M$pg%3O4@wbX(fj6$WZJaNkuf`ukh3wx z#9(iYCxZux-kMdg?yiu|8>>&LlGe{t#1XTmFw8&jJMf=i?pxJN(CAmVbSQkC9**px z@Ckxo>^(a3^EJQ(K|RI`$-JnTOQCef1k1 z*_ee?gJD#SIx>R$%(0_u4Ec81w?#(212*Ce6@^$mALu*IhF!wq{TILL*HODQ?HWB> z7yd|ioNIA_`Sq$jMfD2OHZX00Pwl_p$Xzt7X!rwDi}c^_TXth#w`lk3O7gzUg^wmf zACILC+b{K38rhG<^dDgdg~`&YEDY1d6#I#o-*!ilS?|_*?M*~Ql#I|Ze-femHb&rZ z*em$(UjB(sM13}tGi`8SVC+y?%85;-Wy14PxN%ywY{npcg7E?jj!v$Tq*#}9PZS=e zC5aLJb4kZ@F_!qf5$ZvEj8iu^*HH7U0+Np(v)X?33F3D4+EtW*sI%n4ck`;U7#b5{ zTt?+6Bo$tH(N#$;e)?x}4>bQ5#Qsm{PzPxJmk(#rIvN_SKaBW6Da6@v9rRl{id|`~ zuT3gctpAf2M50Sit=XakE*T52T@D07fn462%$KIPAG4c|a znj*F&AA}$=%J;P^%nrKzbZ;v$_p7jK6T1P_LTRs^&?bKp`8M1obm*mKj$$x(lEk80J zQ(s={uxGq!EjfEub6v)D*}@g`ul}7JHOfV2O_bfKms6JnEq<1*&C^2(tuDGueiG+d zNyn|{V)558#o6mwM3KHt^6k2t`D3%kIqw_JAytF-rS&Zzf~s%cDhXiU_+6Hss4iTw zBHYXo?V5>*;y;*fzKYj421Cy0mA?D z>-v8I{#1Z-BuToLy34^uM`MlEHM%`Sl_8b? z9Yg61x!Nabuj4wf(vk5V*F^0>0JX7z_(+uA7z;GwzU&0b74IW@OknJOAL)h&okC(E z{BCJtES#+CKHfXLK4@8CbW3Hr0+Q90*HQ9o-$J9x1(pZi>J8u!)g>X~*ua7V_0|3| zhv;{y^X!S9^IQkfwd9WvDmEQ0Wu|QWJfU-VwO}l?V;VU+ca#jQ;=o4#{C04KpkC$y ziEG+eM1merbPcae#ZEq~wpt~^e4<|mIvU5Q_QT0|NOTqO=8!(J34TFB!D4w%%w3g6=Gk$>M>L3@(quh)Cqo zKmmhCXC?ALfpUyT`yOR-X-po-iUKK#$`(hN+C^t@L1jg;I3SzD;8T=2=8t3I<7pf! sgAxZOa%muo8JDb_Mya9H{3wh#a2IO}Nd4#eR7yPl-&-pdCmL}23+GX-mH+?% literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/indescribable.gif b/images/mood/charitycam/flowers/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe633bfba420c3d463593ce1bbe2837cc8f492ec GIT binary patch literal 2424 zcmY*a2~?9;7XGvRZk?s?~(_wIM@d*8d? zy&0L@

oz5DVO90PDk~0W2E8Y5?peV8{ZDS|N=FG8rJN1r{BIC2mu}Dh;eLzyX&TyT9}{WpD(j5K zFlJDVnhY~0%bZ0uX4TACEl&HvF}rGPNHsTPSsFVyH>R4K5zWjPmYkwFr)18laym^v zEJ>V8njaoWmVQ+I@XYk=+0e7+m;P;{J@d*-&)>yi@zZ0Y=@^uIoAwhHj0G4#9LU6;V^i3QyCPa z%b~;g2F+S+JGY>9K7r;v^GNA+91J5`dI`{k+4OR3$$ZHcww>n7JC>#0W&qF>3nTN1 zBUis$kgDY)XcQU`k^NE^9H^e6kGw6P+TJdDzwE|_bi{Rl4{5;Jua=7*?n8r6+JLqf zjYYxzg}K8YzUUatr@<~SR9Z`5lJc%m@FlzS0~yT+qF-Pxq2)N{xH%-ld((%t4+dxx zl?IgMz0@r-U`=s$LxpQ!^&eA+zDLS}h&A)TH>jTU6#!r!uD^R%_3NUoUH87g0X+$! zXqOLpKl+OUGhC%lZ^nrHBAL9470v$V8_(;#F-zPt#8|_;AT!6$atlo`@Htwn_rtxa z#6|ifUR;+jpBJ7`f+DUJ4D>W4x=JR!_WTlNVXAMg03H_w4YZbkITsq-M@+W}47Z;a zfxQ8X!LNV0OxF{(^2+@R870RHr7`h8QtR)Qb@dYHCaqA^bA@~AV7a5e5T8-nRoW7F z4dCF0{Z{W)Bo)_-y1uu|F>eN59cFj$I-O)jm7~v#@S2M5-j;0T6e0PIJ3 z#znq0K&b8jXnd@#9u~b#nDO#cxE6*zKA01;gXzF+xnTPiPs>5x&SE9x zck$mZ9+$N3IGsd!1D}>yR)E54i=~D555Hr*d$GT`;2`aIRpkPH+27-@>xjVlZd%`^pwIh4{3=%+*ecuV1R?42FvmM1a&6Kx zx3YE;-v1qa!VAPcPfpx=a$*2400B1tCppb7Llb5*vS)VH#%v~pat(<2>{Kh{yK0l& zMB4N)DfRAbXcO~j$RL6k~0j}t-xKA9!CkR^Y??d9kYF=t18Yn z40fP53I%veB2#HeB~bv`C7+1+YMUZrlR&Ra0mV8+a=z*0|$+~tC9!V z`qWTw*oca1`v8=8&0kajvrR97uTJwhIG;((jnkv7P)^fnu@~2c*U?L-URnFBL?G^+ z>Vv|_GdcVipCE?RARHFhjKQhA6aL0mXYfvRZunG9Xd>tO$o?F9N?fSJfB5yDm#<@R zZ2{5S2!6)#hIu%lV|&|C%IK2-M&7*~O6#t^^vC|Png`MRj5mW5m9Cm-%nWoqO5;KK zWD<4g$45hVHtoBy=9XRCUspPWRV==P2uyIz^-ugRH0AA!aBIGEdX-w)5OF`4MXzxk z&yFho7=wZ=tIMtR2^nW}VXnmX?8{@&=GU%WVV*lWbkpMuG10{jYmdDKVDR4LzEXCe zjgD#O2Ff`d*{Q21n1!`Z0bJxYy8hU6d5ZjRZONbtR$2JysYW*BE9>qpVm-c9QsmEP zcI@8Hrr+r#TpZoS)zQ+KMYq9}fZrQ-TrE3|IkvU^5dQza-4md>MfLA`zb+|vy^l;@ zE}6hF{NshZo3!axFB)4rE&Tt-du=5%db-F?3AdY&!?H z`+Q1;(a3+&FYISGlI=%2wT8gzx`%LbgAIQ&Pw&Cw*}^kORgDCy6(dHY^GT86!i^4q zkaQQ#OumHhK-$JanIJ_hULXrNkmFp!#2rX{|32xg2bY>m_{M(+N?+CDz@?hrvJS4@ z!`CjFMFlQkFlf81>iY2^=EIU*pL?!QT<-{>m`iWm5KkUbQx|Y8TVYG+-annlzV)d3 zrHf_XZldvhb4iF6kd2b^i#2OR=?P{kUb`6^LFBVvd*s+^CdSn`1+Lz<7ls(agHPIezg(q@8`sL{Yw}4fm z1Idiyy?o(LHMKd2)xAN4bqw&aAbFTn4mXfll5~68nY^B;{9UN0;8)#7W5Dd66?L^w zLwtGy04MY0bY?rME+ULt@Vl$^B-EWKGVE^ezm9M#74>CGgjFrC607BkYDA)_X;jJ& z$kYf&CRWPTjYuq=9utiqX$quTp+=-~m0Bq;ty7mF^>VdLQKv@g-EQi#b!fG!tXhpI z$`Ns$`$*|V<;&zM#BJpYB~qi5zan + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
blank.gif
cold.gif
confused.gif
dirty.gif
drunk.gif
envious.gif
excited.gif
full.gif
gloomy.gif
goofy.gif
happy.gif
high.gif
horny.gif
hot.gif
indescribable.gif
loved.gif
nerdy.gif
okay.gif
pissed.gif
rejuvenated.gif
restless.gif
sad.gif
scared.gif
shocked.gif
sick.gif
silly.gif
sore.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
diff --git a/images/mood/charitycam/flowers/loved.gif b/images/mood/charitycam/flowers/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..239b859c5b59b2bf47e6d067f6b165904a23111b GIT binary patch literal 1964 zcmciCX;70#7zgk-A;^)_fP!e@6_7&|W31)U7L-K8)j*=ei;{!{!jZt6ATU-X3AZ5O z5F>(w3JefLKr}%Mrbeq=qF5D_Mi3QI>UdyB>Dg(zqLC%vpc){?0)#qZ?{m$ zo?c7`fC!uc=34$f;8ZDaw!*Zc6t^=D$Bz2|0GqtLaBLwiBSRqV&i+ zcN-8TJU9|+X;w(fie%NhgyfNj31a^MOS8)5uVTM2Vr24F^eFY0lGGp#>m=>FTlRDd zgj6-OjJnGxBH*q!?p-f;`&O}~gv1cQS>_0HSQJ~7hL;tknxl@Pk0Fr<@`M={iB;8d z6dHqWP@<5z)v1g3AIw2Ds+H%D9}vN;jFRAmuw&S(nC`3CQ)LY6v#F}yZcOiaR6(fm z0&5PZvf=jarVCUb9^Ln;8A3Tee&JL?5C!m?M5IB3^2p`UubaLpsM)Z9(XzH$92{ zk^9xn{EiA zs04*f%8gviiB3deu*Jn_Y>AY+Tc5=acnVC6ZNs#;)k+WeT31F^ooiRL)uEC-^;rZ5 zXBH_m#i}|FFx1C#vp1q-V4zOBZQUBDQDoIfyRHuD!N;>j_xm-IM-IlF=RbZmJ$W=} zH}Kv?++O$qTo6rcV3iUyaOrdobI>S#n*;bhXgDv&tiau@w5j=f$TUfg_qTOTeEsz0 z^2@&7QwmBJd8;{h+PqReIJRebVA-AF@rECQaUKFmB91`=ub@#vW5Su@+D7!^w8@^8 z6Rz2^=CJMY>tDxa9|5eAlP@`p1|f6r^;8C`n)l#MFu=8as!h6!-~JW?G=&o~FJ`T_ z4Czz1vQeh?fhY3Q-5>WJz0cAu8zxTl6#Dpo5>o$jFU{S8!RWlG6v<@FIaj0sQpMjO z4gCS>=6?zagKca?W0ilk)Pw2k={!Df>3W~Kr|Y97^-$wL*BquPJ*J6?uKRPCenG0H z`=(}g0#{@i8}pwW(K@x%_0)@!#SOV$E614XMUh^PZJQUB zsU_Dh-NkoVvO3*vr^BJx)HJ&F9#X8=)aPXSCEW?=?VVbJnpBU>KIjtBr#6;cl{o}v zZD6%M?k!y(saw@SoaiptGM|(2zkGQAzb7nOQLIpWl2>0WQY!BfXSc&ascl2FdtW7vwQa2%ktf!(xP z$!Z8VA;0mcxaC=%Tej9Qq$%eR+_?y2XS1PRiz#QvWYkc}r*GuCex_U07R9UFsIVD9 zB)xg^aDmv%_}Q2S7Y?jj!>qd}yUA+QN4wW$IKYvz-C1?`ZGd=np}*B=tY;zs?6F<; z^jYVjloz_Lv>CXLn$j|+&9O*PyD?rxbmlp4I2;6n%nUe;_oIbM*$fj~b#FM%oI3HTsekeCMXqGLqh<`^c#6QzMf0%5H?2>J^^zCZ*< z@q{9X$4VA)z!aV+MvyE5Q}o9~978Ez$l;4X0T*N@>$f0%6+MP01ofROfWSnEx0k7} zlkidc1JZ3zYEaZR!eteq#G};_(9?ay$gLHv6$ew?n%}nt9ICU35(SXnI8iO5B literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/nerdy.gif b/images/mood/charitycam/flowers/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ba4cf8a27479233f1f07eb4865bc4f084fbc5958 GIT binary patch literal 1118 zcmZ?wbhEHbRAw+@*vtS1J=F|rr!Z`t!!c)yKvcFsG7uFDw6s|EEOoN9e4c#oUh%z4 z&CmY-{|{8H_@CR)H6+;CF~HSG&w!Z`B=nPo(+EiGfD8i}%fRwa;DqPuy%w*}?*5;k z(U+1rFJo1aTcFH)E{QLR%0F73FRFcG&H3npk&Kf=LPBT8&YF%h#%?R3I8Uoytl*By zifu|zSeM3pH$}m#QH{OH!ff`Pi<+f(f^=4>ad0q(ho$ETh4S-<`*8B|@NoC@au(Kh z@cW1`b@EU1=A6UJ&CR=zv1kr|oABJuVwRQsi#GBWb~1K~^QWw1T)L8X{~VtB89VqT z=5AQY$A5Ot+4G&wZ2W8z5vMQkT{?GXrC*G@$U}C{30n?zF6L!@6la|9jOXCOgWPi# zFJWY@6w2ce+Mq1@W}aOw?=_7`CWZ4m8`+gN3A<=;H#mkVI8L$XnkQpCUF>*>k+Rk! z<~|;Q9vzkh1{urwCVi*GH!{jk;8EQnqMYIBS*xxrq}@FE&}qy0b&GP+6)wo+6wlg{ zabzQ-X@$%J72OQe^Q(B`W*P)e&SZ9*z;SNV9feCmmx8C-%zgNvXz9^i2JcI5Xf8Rjjz8 zYPIH3!7`PEIqqF+E}xnfT(x6ei_HAO0}Q_G4oBEkoKrfKn~FRcm2#lyD#`3DQiKUpv~q0H&slK(uW7q( zE>6svpb#&Un-L+%czuGjp5CjIo)=a0WZar!R%}z5&1b-RqC~PhuR+M>qF=#lA-AL4 z^_3iQK07u%Jlr9y9d~92FsdeaYs~Q3xvA;UG~;x!H9J42oSCQZ{!D<8LGj-fx19X) z)FK7Pyv*FhlFa-(h2;E#%A(Blj1mRsjKreMl1c?50|P@n1qGLUg}nR{g_O+VlA_F{ z(vnn#^30Nq{L&JIa-g!3RFKxZ;?%qnh5R&y#8RMC5l~l1MrN@B5T)f8DHIfCmL&r9 z<$cvC@oG^$j{5E1ghrc;^p#9%*;^;$+uEShS;B+nCpOG>g5-uGgt!v D-o>eo literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/okay.gif b/images/mood/charitycam/flowers/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..93c3e5f5649dd81a2275b3284523fae16a15e217 GIT binary patch literal 1711 zcmeH_|4*BB5XV0)r7fk*hw)|5u;l^yBIC;nV+=-3S_+embSYoNQ9)ZuX&(!1>GO1q z6}5%3AbFMyedW{7EmD z%jNFgxy$AC!jZ#8#jP-yx3-V|D>|7JNXwoBX{ zdGUQ{nnu1ti>c(z#l@)5_@VO``fv9BAQr#*OGPc9Bs_Yls(sY`^lVzb7MQIDr@VQ>#Hluu1{{YI2=2%bJB17E6ybd1!CZ3`N?`vI84#h(MppY7(aNqwF{>LeN{a>O`9dvF}_~g<3 z5QU4MyQXNnCe2gyjMlYD)y{|U<$Yc!BkoU26u$UFvU};232S-(@tsd6tkrT3zPP4tHtxchqBeGW5fGS|ErnNIP9mR@biDXDCT&q0<%m3Uj Pm$mW#PII+-B`Em=yKA%7 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/pissed.gif b/images/mood/charitycam/flowers/pissed.gif new file mode 100644 index 0000000000000000000000000000000000000000..327f9dbd72d6eca7650ff4af1c3a2b09501cd2f3 GIT binary patch literal 1623 zcmYjReNK?zi_q5G_SM2XK-1QqCKG8m$v`tR7PX@NfP6n?`7pzL-@zYb1I0*E- zG)|(W1U&nB5(kn2piTgY8kNa0duzzFFq^X@_Do$^>{3gDx{PN5?4|H4>W;Yl z?0hFeel3FI%eo4|E-E<$Q#++F8f;6d9SI+S0d?@)i$>g72nAbX8k{;J?R4f092Xiv z30y`YUB7AMl~SPIAbXSjz7Y-&Vz~Eojb4L9-)2AVW6d|gq=XzN(Q>%Y`_`B>=4s@D zK|oCu`kbaSRTvFpzbY_D_+6OviuHj&D1vwZ`ZO4J-63o)0Q)e4GMg~!f4tOTgS{)3kv%3 zh6yAh=L!BUtK2xVbZ>1hBfm73@YX+`dftn!^2;DuM|a)Ljn5V(tS2v6CtPo3vQO+S zgyN+R!=5pN9FwTNve#eTobQ`qn(`{%+Q14K_LsoZg+N2 zUOS*>dI}`Dv!}P2*QOjOR2=EAJoH{qbgN%}g}J4*G_HSZq;#~zTJ%xbYr#8P>h~3m zwAAND61ls2Kab|QO=}LWJdo&c^Pdj4J^XS!b>QJwfb!?OT$oky$P*QPNbMobV{_6W z=>KAb17e)_uNe7GGl|BGXP@tANdrM~NkWg)gisI)m#ZGQoo0=gXJw2Sy*xDJ)fC1( z;7unXWGYw9F`3cu{DRwGKEo!!MXiY{A2F^oe96HE>SPEdG^2W!A$ z)O;*KLzrl25cW;a2Oi_gtk+5hzJC@W`Sz3gc0cWn&LgfU6khm2ohT`uU5hf8}* zeX7;hITL3nzux`uzzN^Fd+9ZAWOYE5XZ6CEs(X@`pmcWof<`1%fZurgN=r45{A}(J zb8Y0-J9L=g+tOFreecArHSeKSj?xQT7mCQ#GRH?~(<`i1z>)v^9%+2BV_Bf9-!ms!}Ua>Tp##E~*T)Gy#@CCfDKtl&dtjS|hI#1$fH8&nOfU tjaV+Kz$>*9T&1kg2c|=VLW6Qe@(Ns_T8xYTxi1zei2uSQl|~Ad`~?#CiXQ*~ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/rejuvenated.gif b/images/mood/charitycam/flowers/rejuvenated.gif new file mode 100644 index 0000000000000000000000000000000000000000..0319ea01e40a4134a8ecd83d239aac6c2b6ca7fe GIT binary patch literal 3744 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/restless.gif b/images/mood/charitycam/flowers/restless.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e608bd645dec2bc46cd8f1215b27bd863a1662c GIT binary patch literal 1295 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/shocked.gif b/images/mood/charitycam/flowers/shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..adf42f60d21bc922bcb98ff339463933d44333ff GIT binary patch literal 1411 zcmZ?wbhEHbRAw+@*vtS1J=F|rr!Z`t!!c)yKvcFsG7uFDw6s|EEOoN9e4c#oUh%z4 z8=w9E{~xGY@jthpYe=xOV}PrXo&hr>Na!aErxB3WVPxQ9P-0MLU|{(taKdw`=F=yq zcC))x^mtfKefGSUz02!Fp=A51op}qC#g8e;-EVWy5h}5g?ESK;V+PAX1uqx289NvX zJ{{&|d7v!RE;auIM{J0LkHDp4i%PjWPH*L8OFkHHAe4|3nkE#~*j!m%TT{)G-5ezv zpO{t0&)+@0jwd0EQHD8~iP61kI^PWL?JEz} z*4uiU3Lj@b*nO^>$6r@d@dW4j8%M)47-BiD-@L&SWoe!A;NiJGx3Dsom#^kDtz&FU zT-x=4o1?vW;onX3c$?i=FR3#uTr}a*LihQzD?QYF7ERZPHDNA@E0j2*?BZG)&thb< z@nUaFpG)Vxg3XO;XU(Tamfa|Le(J7_^tX2}7>p<0JIMb(X)o8QXKE)~7RPux>m8!@6~A6i!T^u{Pl_Fvz#9xw$#x@~YU=+t%LRUSO{=!+ZNWrp;xa zpUJM?{yt_;-TPIjkwE2iFZ=MLg4(s*ZNk zDG3w@68cPJzZoU(!|W^bPB|?RboS=y7m&NY_4I`!ZDvAN zHdQJOY2973qJ)+xI-g*+@%X@T>x8)nyF}l2tCa>jUMU7UI>oy2uyQJ`=;V)OdN3o) zDR^nr>j_T`)S;2U?a&B}gva}?YHeS4cc=WjSH0fl>tpx@f!W~S7Pp-I^3);)$Gptk z#FEVXJcZ=^g36-I^o$Y(=ZwUn%#un4BLf3NJp~1qe1*LH5`~n^;*z4wq|%a9h4Rdj zjQr9Pg>s;>l2nk^yyDcn5{3LUg~U>zR1r{DNJeI{0uZI;7bz4JWtJrZ_2q%B$<0kI wO3qBoQ7A1=RmjiFsRXL#<>KY?P0Y+u2+6lnNQT&-oS5r?VCv-;r88Iq0P+eyfdBvi literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/sick.gif b/images/mood/charitycam/flowers/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e3b201a3374512d453749479cb18fe2a94ca920 GIT binary patch literal 2123 zcmd^<`BTzq9LK+axcF59Z@a&WXQ>%&JgPy%%rIBY%rz^? zOcT`dD9dWSx;8xMFzs-4%FL^rt+t%qiKY5sf7X{RGXl_If?0AM_TS1EBn@2A># zAi*ofs(~i8vLzzQp3PQ_O*dXsf(e}M)^9M68>h$SCio#_(qE51EKKenq6JwQ?lZE_ zV1>}G=VmEw8ZL3idjrL5XltGq$bI3ifT-mMg7C{&t7UH~!BOYD*O!mFwTbjrp|Z}Y~HWoy(AO%gWdP4*-* z+7CNzFH^PI45>?cqp$WQrE+W99Me}R&fbq1>~Jc2Y2szRAPcv{>+eu?>@GkT6M|2! z7)4LstyrtLt;%ef94K4aj6r+@Po{;g(IrvZ(}0t6&j%jWtmv6Cw!t@}kTI4<=%GG+ zTk@Iu*4%We#JeOYUM)2?*Oj&ouf=RoS*OXy%D*3i)VhOJ1yu1a6P3LHtz^HsA_OzBsFTPujlV*h4 zHzL7iPUk>ic7-TjXE_J=ppMX7Kdb{fS`~Y1^iS!MXX@c&z_EE1@2E zX84(~?oB^&+f3I4;ow0^o?omjIxa&QZOiI#e>VNc+Bg^BV{vA9q}QW>WTUgPy*f)@ zKk&=95}lZyyvu0cA$88O>;?(;7=#4|>!QdpB4xBql$2_Jxt#R&uT%9T302!n>$95!dPk$t&1PJTi1D7_h98+@0UOq3#E#T zuCYth%UVy&WN)5*(h+EvGN!uRIyG2LlC7d#X`8-ZXI`JspM{tjK2HxRqEO$@K5hzY z{U*8Zu(9TDR3I!|ouX>N8*xdq7|LW&dJ8$pB#gYIh3U|}m}O1G7ElS>(X_5IFJLED z>9Z`78){BKlyB+}8d|w6*s+V5I`g9>*M}D2dB;5(iPqz^^Xa<}I7NUNcXg|yQhWnD z4Hm9H^bm|3szA+MF;#AsIGAmj2L}|7>SfeYyWo0`g&(5R&^BU-iaO7}w_#-0mj3bs zGo44mZpAFPFED@Lm^k9wZxA+_2vAxTR)lc1k1@Q1NcL2zL+l)6aC*4 z^ZRH?*=Y~vNt37{(|f=4g?6ieagTPj921|MwOCqf#Bycs3NNAM8J79S1{qAK5BLWy zIi+*!2DPte^%>nzr$u^Y;tW9%7ULPI8}bsb#J&)KJBy9R)W%BMRxU-^dbUQIL9F_Fm4s%HqfA)Tb{Q=1=$CuRvCFD{%)7r{I(#NhEW1#mK31d-Tu0W8Xdh%PSc zogv7F2XT2KhzSct0yr^E#Dc`Ih|NnAL1L{;#QJRI3Rzqc#7lzcY1%7+))mQyg^)Iq zcmjwofYa$(ANNa{)Kr#$0n<59nvezYxSUL_8Vh1U3LWM^kvw;Z@wGmKp6dDU(U~Vm H20Z=&#Bgg= literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/silly.gif b/images/mood/charitycam/flowers/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..22ca40cc213883ce87732b96053dc2fa0a7caeba GIT binary patch literal 2670 zcmeH|`BT%^8pe|fUmyX=P7;ECgJKaQhFlg2Qpv{R0F4$=bVNfENHiNEVQaA@K*COt zMItU?HK^R8pqHu_0)h)F#f3!$WSfczj@w+jD7|1i)8E>EpzoX?&Ybf+^PV&Fndc1& z3*PL{TLYm%1_L2Wg|tILwr=$$`apK?#_cJ_Rp)&*Z%8#3$*bAY2cu;T_~PByY4k62X-)D!~dGN8ri)L>j+TDiHZj&izbd&!yb z+Dj_kC8e>)0)gB>Z|Da(4`|ZDZ3TwJOHEOYb<(TG^zMs_z7baGlc@Ho$j1JCH-`B4 z9;ZH=+TTAZc=T4Wpvn1fadDry@XMPg9Jh-%Yx-^LV!ifNku4ySaP#oc}qe+HDFe4Yu@wS$hpdxSt3j){SNMn z$5r%kcf?Q{e@vopL`HXv&t8oy4W*#bNVq@<91M*;5Qr%%!ecZ@WNM-as}7EhmthD* zJOPi_pb^JqDip%Vs!TdeB(&Ba`8wm{H_tXcs>ppMbe}AG)h^TYcFT=7lzm6Mg>U+;2459S64orW<0TlIv=1~5h*@-b?Vh5Q1HT?L~ZY>2-~z3Jy9ERHrlDI2hi^-e63{f{S)sY9rMYP*%(}nB?ljGChH>6 zlG#Z;$pbo-OH2-((qTQ3R)0$g1$R=XtqEHQYyhs+?jUUQDBx674JyA!@!Vi8@B6U@ z>^Nh%Yr%%00S>bv5Tn)NG08}zM7S3#4(7)2{y-xcjVR@bP>5nyK|&IdU^eO%N|nA= zp3sa+uKWXyEKH6r1=-Tk*_rYu8s?)_$7HRhgd9x@_S88Jqfp>GHX2dN@~c}!mc5JzOy=A!1C*= z9=p1iXZgvrasRQyMQa*+ulSMevCquCF86;xSpxh-A0(HLZY%^UsSQat39hcdhB(9c zSv-(W!G6)|+fDtl5}^Eazhe|c9rdW+{7rjTtv}4h9v>#`KDcsYYiy@BqgU|Ki`{G0 zyDvr1GWU)7vGhq>fSn*$^K`#5yy0!9>euv<;S-&CzuaZD53R!5yKFZ(+paTDXzhJx zC$bR1?n{(Ji+EU=z&xpgp(!^f^{ZWNr*aADp>cXA+TT$!gFqP%lye1wxt=X`BevQ8 ziSZq`V_WkV7;C3xK%Ka{X=ie|-ScFxr-ju8O>;h6l!%W>P2aDGm1Ju2a2SIDFOJs9 zG+Lt(i^GW$D+${o@K`L|47Yc1Y+gw^i8@hY*b$Y11ps?T4{E2E*9J1F(cFmTpu+hT zc$9sI#rt8GhXefbb*vC`S1Z5M;TnC<81d8lVImrG>@SA z+&A}8biYmIO6z&bHlibh( ztr}~JK;7V0x%OxqGjqeOk7=+RYm_Z?SC+aVH2aVcQ!`n(?mC{6M}2IbF5dFL+3AuX zVEv4NjT6t5hIp7}j)Z$m@XNT&@A>6X9zP2zB3)yG5ubv{`Y*=SKSA_Q5G{|Z#kOFH zJVmGk88WeyrxMF$AYZOXQ;HKrDv%}ODaEQZkVd6?d4eEY4$9;zP#{iHDaCPWl@Lr3 zt3-0O3QSp&sf5c`S&~qu0_E`_PrY=dTyjN;#7W@NikB-vg;Jc%Tk^?1wUJ7NO1_vU p0o6%DP%e|CEvX$~4zLKGSOP}L=^+32{(PP^=+CXET$um~_&;-cKbiml literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/sore.gif b/images/mood/charitycam/flowers/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..b8081811502387a8cd60df10a804cc361daf6bf5 GIT binary patch literal 2166 zcmds%{a4awAIA}a2+|3nC~AH&^&mdR?shac6GhbSH0P*HyHzBVZy_L{h}uGi(@fEA zno@)hi8G%{CxVZ;-A3M-53_r%G|7{v(xS)Hc51F1uAQ@AcJ>GCb3W%>*SW6G`}$nx zywB?s9ZL@mVQzy^AmfmCp@38rLb_@oIyF*VW0!o?j%7)aokBr0ju5A(i8qWy)3lFH z=c5~m2no>^PKQ)zYjjU3i?=^oU(dh(T&q@VM@CE{(*u@iJtAUVp;)h2w}j<&;yOA$ zit$M#H6e-;5M*t&ar7FtnPOS}HkxmI0|I{w0LsIlhST27eKacYn-OQGTJLvk*z zzSX6_AA_|XI)0(F=Ok$5+COfnRLc0fvg*DYH|kw5L)FmCLn-d=u8S@U`tw(Lq+uS` zWpQC~eCbNYVUkRS#jKjmt8*^c90k(rS7Ny2y$1a;Obd?OEJ&w*wkA07oB`T8ZpQni z=R3tE!}bU)2EWR{K69`jd*PohuZIP|2>#6bDt zA)IfmgNH|;*XB>_x;Uy@2WA>s@Iv^I{vhM1U-`qn*#DEhZt^21aDZG_2J~!0=8d9* z9muBE=mUZRxvuKRi!8k?e5n8Ng6=;{rm0YUxoM35$X1z>chc_fd|Ywro z=}-y1PG(MCL^vV@BB&%0nk6lwoZ$M(}om&mBv#aw8D*?U>^-A=A@O+gh(5Gz@jip-J&^?(S}Lgjs|0nM>)U3+Y(rx!F1W z4~AjJev(j##SGlNJ1}9uvht8#KiT5!pFF+(g5Y5{z+wR^yl{)-g&Sgm&uN(NJ0Lkw~@Z@NInAdj1>20QkYy{XGOk zxpO}9?=1ZXp?NpB@mZtOXwjNSj1Pl`Dna3%xK()j%boVt-uFxhCpM2-V3nd^kZpq* z#J)&6XU7x5i1Xvm$DGnM*F#}1=(DgG_d;GW;JXB zP11a?W+nx*#WhL0M?(qzWVqcNeZ>x4x$j|A{TVb%>yYOYJ27O25g>tQdJ9%3$J5lq zF!ZeICZYTiEqA`cwJ#9eX5Dh+a_8&QXy_J_pN!Vr`v4z7;`o0rHm12>WL^JDH2eQR z6aLpD_8)*I5^L{h|Mc05f6)Np6$JH|BRT1nWKSxLTy0zXaqo;AE`eBwy`*dkr|}I0 z1kH$MT-n=TOe}Hr35--6DBfucEM2XW<@rUYcBrQ8AW#^I(fADQN#VHDU&wtpFe`t} z*iuVg-#zcNTQM*>F zl>YYT;WHWD*EHRndG0Sz(oCyzAXd2c)mTH@JUMN8x60cZh1#jCR;zlEO}Khh891mo zb>kvyQWIwxvG@!8hKa6)pDIiiG~H97^5@GF#M$_1wbXonwlc7)TOE9FW9Yu^qjUKZ zwh*B5z-*=%$pvyn mY=F<>N-fnkC>vB96XXI6{!W1Pu0M;J9scJwfG^B~g#HG;(1^JJ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/stressed.gif b/images/mood/charitycam/flowers/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc36734f914373ce5a8a670d14841c43bbf02dc8 GIT binary patch literal 1517 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 XpX~rr{_0O5M-u;cv|w|>fqj1hlvZXO literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/thoughtful.gif b/images/mood/charitycam/flowers/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..b731a66759a71db23cddce2d7296f339580a2e48 GIT binary patch literal 1932 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 Z#Xx~vSBUXPe+E7F;D16AmlqAV{S)-UCt&~p literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/flowers/tired.gif b/images/mood/charitycam/flowers/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f41ceaf438eb375e75156543547e41f15f54546 GIT binary patch literal 1869 zcmdUv`CF3*635^0hL8{w4GD<}5nn(Ncrc~W5^zDo6;UWs4QyQ%373fr34}LV`)Z6^ zYir)EZ(`N8Ztv`lJ9jZb+jX$@^V9OravDa=05DDsoTi7|VP<_DB$Xw|O0#>a;K7eh zUTev|URyZaoi}k!I5m(nIeK(>HtE*=WiOLR+x|u z4vzi3dgL`n6befwtBGU~?7e9o9ww^DsH;d+_Y|2zBvMEu7w~GI;|+^$VZha9qq@$y zxHw+FIYhp#eQCzJ(%h&tDs|2$($JsG{uD!4-gGcf|4j*w=IM}m0@u)&=Um2}3X~t& zgQEw@%-Lb#gU-($NGc64x9qQ)XH)^qw7vRG;iokk+jqy!C7M?+f7pjW8r(xQP{O0s zaSYxCF*wObw?qmzs(j|PSDuw`CV=}jJ$!Hvjs!H>nyoSi&(-XQD7HCbFZ$0bTLK3E z06SHH0N$KH1K2Y6kc{MwzySck0T8Fr#w%G^&!{TD+DYXY4sAtiT2($U0v%x--fj$L z%-#-8nro11YHY{df5nfQ2L8Bo`@N0+spqCQL}0Pu{t2N!|M(q!=dPe@58n6MkxAM8 zAokHcR*HMDa6G#Ilg6YP-%>bz*)0(7=G_uU;z#ni&U*%bN^VXW5xrnN2pEn}2~H); zPf0E~IQyALK|Jd(K*E8=O(}_c1d=D<`o|XyiehURUkU#6SFh?M^56d&2Qt5Xu{o24 zv?+qfX_^+#{8LZPf;+5MPZ`VnLiWy;0`XC&EkB=RTa53p&Flz#&gBmRNk^@6`0fW| zF5b4GZ_8tBwR`V*zN+&{j7%hKohj4P$0?_TuMeHyMrqmVdYJR2z^lpBc6hOWUBjxP ztcruIdCQe@jjQUC`i90vqJoUlBT;Rfj{lIQH#pWcX>L@yj*L)U2kd0k)|<#(s@o0! zCToC1_yP-d5(%@)_L)0GH`>bltxvD^-&(rd@jY?i5sglVHZr0E5)p@)$6THh{6CDp zU+ThEJ-78njISrG^yPe?QNE#1=jJN|W?P*qjN6LV1rIG8>ra1$yjoO)wHPXcVwUG# zS{hjx0zPZJT^`;~3?SZ0G)3`_vX|gBX>rvKw`iwZ{G$2=o#hMx^-YZ29k9g z>0iGZ7VDQ4);7M+F}~o%XNYEs{CE%gm+b&gGtnOPeAo6)))@BW4C>hH?g>j`kK}L5 zUv~GSl!rPpG5b&O!q8RfA?Bh<$x%ywfajlapADpZl?O?jNc$0#w{Zqa}3(U}OJl`@M^ZV(VdraK80hE@_TN|-AKTJL@S8+#Tyzx^qi(-Bruz+=u9E@O- z!3yGhZU6{y`Qy8qkUm?k-09K~`AE2qbbp44b=`3^RvpW-9$1+o&9X?&X-2aVGsU_a zNT-G+B@P0?(Uoyu{d6$?pv!w6HR@ymRD~{xTx6cn9F9&<_ta(h_Xc!&o8YemOO5${ z6KPG_sfnfPVimQ+<22rH>3sgJPMa~0v21J3+5MW|Y9wnrJmvPEw|a$>DUzm(p)jE! ziw6rtLMT;~T_6^m;KNV^pC=Z;1rReJ;9Uj;MT#Jy2!_%Gxv*G}B7xH(sQ~7SBrqhk zm%-_4Qekeo5Qan<5Km%HiR~&bUyuvgJwqghvc-Zto?R#WtxZ-|x;Rz9%Y-Dk>5xd6 jSzxcmIpdt)=Ls?)u4osO`nG>6FN^)(kRcME0Dku`G}ys> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/angry.gif b/images/mood/charitycam/frogs/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..d1efc2dd8b5ee4c843413b1fa17ccd607f84a7ac GIT binary patch literal 1410 zcmZ9~do+}J7zgm*JJ;7tF>{oe5q2hKNZ6s+LA(2okhD3*W!7ad8n=+6m>Rmh<1&M+ z9SVhEToSvHatXEVu&tHK(oL(fB2&>yCht=-cbN1}_kLQo)d(Ly7KR&y5d-9wk z&4B~B$p9Y%1KVL zeE{^W=09qJ->!}=0DD`VxhH~wT#nq01RLQ z0SsUQ?%D$@U|UoivqjUBiQi-;>K|hAv#|ItvSi8o+;a?UIZ<9iHGOiEjlxu!VDr!U zbbj8v?4CvMw>Dc94|v;jdrCK?=-eAyqkpYJ$aWN$0P(PfNE2Cgqp$tyhz6q0WW+k~ zd!okdIwGHW&>Ysz`6I7*MsS&7q*7ZK_XaoNCpccdQagEP99jIBEbe`(2Nw1*0S$|4 z6_!A^=`7dp2j!v*?+yA++zQ?u(zW|{K$!vhCqgc@`i?V?z$Sebpv$7FRi zk&`1TUF8`tbygqdA}FqB$=-{CoYaObk!-G-9wV$1qtHB_0&s?J9DA_u?;g>}0qK>Q z97+{3(@C71N=PlB^U)(=biUkpFz}hkrWvlmZZ6`9aS$4Z=IJAv$pZD==t;1#WGNg+ za7mWLy7UsO3O-+>Po^~gxXS4+j30B(lDbZEmof?IW)V>fHWC_;@IkV&Mu^CHn%Gde>BqC zsyg(r@@d%_@7KDj6c-n(3r9v34RYL$tCKa+ryh0HN^yw|(`7at)A2=l>h#K#h*7C8 zWN1t&O&L0`J15253>=sDQ$v{$!C0AyG2qQ5UJ%P+#PK?pXi2+fMgt;VUv>Lu*k#x4I{jOtH&>3#)sS z7&0kKCZBLG*kE8}(J6?!g{9elG&WE4qIya^%AKB% zc0`!ANtug@Vb`EL4#~)42-^yg{`3eE0}LUPY^ca*zME)-9TGedS!+zUlx#6>^AT4A zTjiui>_?jX@vs-dlg9VzMO{-I7@0;Ju@~J`fF?Z%3vEyNfb{qbnAG+Usn*9INgYRp zcH&BIkc2hMb_D{iP~U zKWK`1K)C)DA}2k4X(D^+EC!kS$oO+*Cz~ryClnCPjvL>5#KKYA=yGM}H#{VFsgTA` zCgG5BrCm2H!9W2#Nj7mbr?y~+C!mRJ)8RVR_HdbbnpX#pj}H=Z`KR^P0d`?N6&Wkk zYmu=Jhum0-Ds}G`)?%W{f}t`I;Z}Y25*1h$M_W5v5>o1OE7alf?Y_`aT~K{Ru#P@)zMy8Z*;JHQWFzDU6;78XvE|M;j0g!gu|`7Il)O7lNXIp z(iP*d=334iiZuud-0C*AMOEn*aQr(};+=sGRi$F|{F~_fy{^UW4>osO*T}+4B2w^e za7>4jCqk>S)gL!)*WQIqLq?4>fz2lc>`NW~O#^mU=4WT#{s@Q_!vbT$p1B?iMm~41 JA07u>{{kNwDt-U} literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/artistic.gif b/images/mood/charitycam/frogs/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b808ee38adf924ba59e943950cd3fe544ca3a37 GIT binary patch literal 2369 zcmeH`Ur-YV9>;grB?$y@!`}rFl0t1mjS`0{QFJzogcxlbBDIp96-?`&Mz~;9&@h_d z8t_~YbgzeH2ZOy;w64O9i(ap5gJ3|bdvNC=cVY~VHU7DdSaATaCzrd2n?Bs*J>0{6 z<~P5Y-^=ge_xpScR_JmxrRl%|VB!$)Pb2_<1Aq^Zpb|uZAW8%U02DBCqGIOkj z;~X4Ma6=RqWVokxo-pv7h3Bk1=iqre&$B$w@j=$d+kHIY<4K<{RJ6~>_(Wxv-QF&jSL?m6BW z@eQ=NXn3s4_MOYUDEn9^po#^+1 zQOO<{LJ-gPQ-w<*A{KbuvhTsoOYw-&gH<^J-7lUr$#QdEJi2l0)$@kbz?a)^-(qjC z8H>+N4q|;@G?nk^srlRFuCBn9|Xg~z!6nKe4aUI=YG(6bf zXdz`1a?41tr9S6z)oaC~_BZc0{v4Jqmo57d>4OeD?7T06bHeYgmcpg`qw*Hw5(TPn z1fcYhTc6awQxopNqygi;=wj*_9IY+M>ITKRCEfA(o5deC?0oEgBQo{l#+uk_Bgy8l}g*bKZWM>b2ElQ6OXb~`qOQdyQ{RNXY+cHm^sllE| z{bZpe)qbWlA6an`z|TT)w$>79-57KlX#}qTBbQy`Srw$r9fu9r)^A$&s`m-B2p)tJ z%2K+&2R2DA*QS(Z%ko^%!;INGex*WskoW6keF@K72Ww|~DxT#AWR;{$V% z<>Q0;H`a|~hDEAz3zrVDB}R`e>8d$5%%wkV*r=&$RaITPi|p;0N_eE%df|HO zE@{{pSJLZ*_gwkoF5y()x{Bey7aViyJPJkfjO02w81X}2NhLV2C_u!nxu^wRmbTyB zJ!{**Xzk|nb4H!%pEZ|m+w3`UPbBMV?r%8o@Y#kf3tA_Oz&n4wc)Vfd3wV>@^&5`V6t4lqg}U~F*YaJbGPZsYW4nFiy^5=f2I=`n8-E#hxcFXKRFap0 z%IEz%ZN1?wKv+&e(D+h?Xb}s#O`P7ir%l(AwL$lBWwF^EgvbUNtf<4TNfJxumdH0k zNvDC&MJWLcc~#%L*oV66KG(J6hKD>&$tf_lXuZi#W_2fw_ROr9>pXfktStQIIqllg zyfgI(E)m6KIK7fG)6R$K|1n?NKMY=wdIMUKGN)UtDEDCC?-Do5;n=tfD>L`rwv2q5w@|Kn1!4(JZj0A{G_GVokZIHfVwYv4ctUX<<-^6 z?ymR_r(}LkB$#B3lxL?@b;$bAQauPq{a`*3Td{b)Ef0C8WY8zWXWHEI>i$7ptor_x z(J1ZBS{}clw=;ie(|D|-lN#NuFX%qy6pa}>j5tTTK1g(1lt3srTQMt(~5J5-~#S0e!Jqh8C zY_#DbK}`Y)2|`T;6t&tE6;bM~q9Rhn3n02#sI{BYuBO4A-RZvV?DVPA-<t~tx*Q5T2(|VI`v0J-xlTWPccdD!6k7C-g zWa)xywl2YE{MdZ2&?EHV7}{j|oXc{D8QlXqc6}JpPjIPEk3*|bG~<%-=!Up(RWK7+ z8QAvnt_wt%SnjroaaX?XBw53%Y}}wl1NUaVYELe2jK5mZF7y`@NK2oT=D9~gk}}eC zBn;yQ6@h}C!U?-5h7U(Kp>Y;eoszk zAgYbVq&tTk56)skTnP-3!&W%tpGNG_5c}>tqrV9~G#R11IAoL%m)5Vj_HJPEyBDpi zeJQjEP&__#`TabK0c-wYTKA6aJ6BX;;^`A#US7B!$0ct(ZZ$@(ReWKdPRNx7p*F6R z6S(`pL++l3`m+Pbc_y$`3?~6W=v*gV5L(SHo|W;@tC2wxGgT)kaIXrW6?J>uiL*z( z&cFcgr5 z)4cjgy@t=t7)!F5ro&VSo25xkxc_m=ORWz}hV8k1b24QQ@=x1g<)$~;vmx7nv&N*L zQzMBAXq^_nwyEsqOxU*D^R)-KiX3tjy1uFh*7FYTr; z4|UBGV>(O?08W*dL@HIUKN?uT`e9|!DGvj02WznysCO}Dbi{4MBrUdcVna@5n24mb z9$sHhWaq<6x!1K}*jM8?Ig7~fFR$s`T*ej5arMJHBd^vFb2Zpx`U|m?NtNZ|+l$dn zGa_3klI??cB&5IUfVVgf!}0}7cnL-mjLj=oVpWC-BIN9A$Xg~&n?5V`am0bRuTr0_ zV^aS#vG1Jd>ob3OzwpPHcl*;#Ub4*5N8-kup5@mv8C$^%+umMZ<{S5fF11(`>-`3I zk0j2G-S<=UgRO|y;sD7(g+mr5Hhbuf0Zt613L^U>bRyKdG(K-MI!avV*?>q2H)Z$5 z6sy-K4y2cq52h)`J zF_>nc?r^Y1q{N$OVh6iabXe)$5 z4N4)z5_^WPY;RUou!Op5=NE~!FmuR9r@4VP>)S`J=&`O&w-lS+2nE<89GTey_B6@F zFiq;d;EXcGMe(`!1e$E)5QXaOaR1Hm`JZ?jl1L2Q>-q3?o1c3@$6L-+D3`ZcXl)(P zBb>3tyP!{0j~5!gY@+Q9K4HpkzNFohe-QcG64|7jA~Ne~qP@E4+x+wAGJ{Z;nB@2ZSgQnf z+b(v6p;iwHMsm|8CzQH<7Q!tX%RVz;B{I&dWNuZ6y3}`nUo_-5MWmNH>-k~kKlU0A zz|6Vvhh{jJ)Pt<3M}jIOAhaIb*aS#m{z!))xi~RJD`RMZARC9+0HqyV`e-IM_gzt^ zEHlZ7%US*|j}v&r>zZRT8)RGpE1Ut9^WL3{+_#RG-FVphgOgV|!YL;cOEdY8M)N`u z>d*kBxLaGj1N|cMc_Trhf7X&coG7Y;htVhal2_UH6RzwYYHl5zwyWW|oH_Bgb}B_` zYW-%P$aLnRu*YS|60nh4^q}jAUUb+CB)}BVmzQ%YKu zT=)Don{BkecaRyIMQi)7W~7oXLbY7@Q|J|>9Jmz_w1Lzd4WXtc83^A%|HEZhzv$mw z?zM8+;=apZOtU*G&+&YGO5eC!aRl1IqNX-`UjFlG1>WVh^G1Lv6zIaWI>0vIxv#u( W`IEZuZ_`sk?%WO#A#bO+T=om}CWS5l literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/blank.gif b/images/mood/charitycam/frogs/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e4b5704ccd9b535c3aff03efba852231f9de370 GIT binary patch literal 1298 zcmZ?wbhEHbRAw+@I3mda0vrqsP7E9p90H000-6Gf*@~7D3|@1*l3Og3&n0JbC}vOb zs{UTx0t9P=dbUQ*IhVZkeetpXJ=fN9y#IgiI|IY_?*jk-fByhB44D9mDE{a6a}5c0 zb_{Se(lcOY1WGIZWZ^VokYvzdWZ+>?U{C`(;2(oAhm428;ig7zKCY064GW!{#YNO& zBt9-Y+Q_aKV=X+*fg691x?FX zSvWibw&yXO&DZ5NTjRj^jL}9}W5uberX~)X&te+2I}4atg;W@11riz@!3B?0?6n$=PmeTz^|th5c2m)8`L1 z@*n1$pZWYJ`^)S4(*+*vY5c+OqVS+0{^oaw;yWALXS1A>JrUU;_+;Ab2G(EZ4o$xo zE^}a*!>O^bMMO=&p-6mHxHRLv%o7XSg|?U}<|wNbJgo9xT5-E;r*FW)K2aZog*_^> zJi-_?v=$^W3BKA9(l2ztV^Q7IyJabpM0I{9_b^|GkYseb*OAg4niQZq*^i0yN(-4XE@B-x+*eN+2z#|;Z;*CQ!lQP zv{>+Z-JWl+wAZuz)q1mGKb!ZPjl20o1W-~9GceWY56)DxOlQJ@^$qMCQW|*)5`|6M z#hTMJ6dW9yc9jZ;wCPkTJY->3<9{IO=y>(Au!zfpncp`j91;>iN-P1@3<0b{LK9SZ z?l>?ovt?ZGYp7;oxwT~?zkxvXkIO7a*=u~ySv8d3TEqLVW^P=qMH%O@?VoE7Z2p@% z?~(k3@Pyh=KOgh+tf?1Rxc~q94^PbaDC=45fW-|%H-_(CS}G!4cqo^RJ5whIfXAIwlu+wh=M^h(4*7R{z(Nge)z4YEC| zmv&s~hK z-|EHF_D!ZC4O7_!5@yz`&+AxRKTB{z%xve2>M^NlNtMgHrvB`>J7uyYLwbf}M4M#8 zRL(8S8I!~oXauk@&SGHUcQ`Paf#v5iha$_pohuxsE|to33{83^Ip4$YDa-4W&Bwf6 zPszWQu3fm^@I>+&J+BK_X7lhpxV`S!uV2yu4xOEo{aAIR*RB;Wb$h$@M%wJP%y-IO V>u%pzr~Pin!@k#RT^Sh}tO1Or{ht5; literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/cold.gif b/images/mood/charitycam/frogs/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b332ac9715396d70fcef66c7da25bdb6831af8c GIT binary patch literal 1348 zcmZ?wbhEHbRAw+@I3mpe0vrqsP7E9p90H000-6Gf*@~7D3|@1*l3Og3&n0JbC}vOb zYGGh#0fMzbJzJyZoJ-#NzW5je!?FK8@BiQX&cN{fyTE@2hX4P+|NsC01K3Ci0c0!w z=k{|A33hf2a5d61U}gkLDE?&OG-8lu&|zfYWKdwx1Uld!gE@zc$A$$5*m!xgVpa$& zWaZ(M^fI}@(CpeR$ZAz!u<_y1ZZRdR3lkcX-J3-1<8lmwn!P8h2d{EDap~#l$ec7at18+YJD{&p>c_bkjjDyQyi}HhBGo)bTu%s zvbY~j`|!%-%?%#@M|K|8({#@`Y)>8^_HdFhN0&Vc&Xrl?d4%B}}`Qi)wh-I%Kmj zq%{XK2smm#X4;jX9;V>P)Oe7QjiX|<2{QxZMRuF~bq~tkJ!510Ct)C9>(IavV;s<6 zu;5R{$2)t~6Z9Hu?tD0QcDi|v0jL6XV7v#(4f0d zVsU}7T0%0DEStuKa$7Y4$6}F?2Pv!~b3C5(T5bwG(8r~+Gi9=;qo!k_Gv9{?4m&e7 z8K--MDx}VEo8;**?eouyG*rkx zkfC~DVke)%ycG$ZRX2;5@@~1cVfDnyr>QHHeqVJtn6>5N<_m7xx?5O$v)^vL9M=7I z+j%|_0hHv#08CCsLnt|wCpEH6WVLZn2+MhPmXpa?M`2e310(07vUf7(2VY)V#2)8o z!0?7)tsujUyS|JLENgqxZ|~J{WJF3uC)s7f6%-k7pT5G&VvvyF(C|cX$G@}%34x?ENc3* z@y7gGk-ihRJ47yJEbe-@^~BZu#KXo6pqxO7=a zRHtf?s7Yk<^r@l_4NQq%1y2JbvVPv4$t)orU7hnTV(APoCd=i$$0S1-X0r)2M78Ga zI+@bCPVhqP0#@EtQx~>>%LwaqoTrvrKeaKHVd2)?2C1Z?ooWpZ{Za+#jPvE(FJvZ0 zIeuVZiJEIQp@gd>{py0bTqU>GFPGf1Z1pC`U!fZ_rK)uzPI=vW9XscgnbMT_o$8I@ z&3zUPCCB-uB^6$lEx$9je4^O8S*QEl@^-!1_Bt*bI$jD#~ E09^$e8vp>s*Ff_(QK@=54#sUNt z9Is63|BtP9N%=o)6E5=Q-y&&xhZJun=xQ zyesepH|)V%kpWl_$P6;VLJ$vxrCq@}a;~d#&8;XRaZ7E`XLfY9gz;-FYRd4lUYk171C==OoLV&95U(6w zDG)qL8{?N*3SA@~5$-`6J98iGQK@Twjji9Edjc#;1v?+NUVbFK2`4b>5;UoMR3Zyl zy2cv-r3j|6nRvf{vK}K{$}FD4UJzRq-#$I)fUY23e1{?NMt460u*Kxl`*#5kbfp)$ zi0?6YLpP6&tx4psf(U@%B$=e(=aqeCNTib(^$(sdW0Z?+6mZtM=MtOPyu_Q#m ziGK}~s3lJ9*pD){k*wXk91*D!oZYGoNBR%q4@N18--qv%Dk0*1;yhdkvI+3`y=z&w zz7B+Tn+*?T*!isMOeLoLuu<1F5NL#6I=;q*Fqu1gWsf`Mi@On$l)nm?nfI~t!)k`esa7%OMX znBhsu?ahMjGMi0koqE;a{%DB10+SJ_q1b5DWnz2h8sM4`g zadHe#l%6r`Ui=L!WU$6FLC!9hXC7EqQD!sY2%U*)(pH5>8yuilHnArnnr7wO>*<%- zprny1Qf8Xaqb8&~<*}lDKTgcb_rd!Qi?yrG&}jf~Fq^J`nltTI2y1QI2a@bDwpVh4 zFlOM)Ep`>7WxfBi=NB9-;TLTKl)Vw{5AV>C|ByrkE@0*Vl9cxkNxdpl9|>2TCc8zn z3!-$QxeYhV+#T15Z~Km_%ACV|-3-dcjT#5P2+eFuV=n=vxeYI`0R8H9jZ zsuP%4tM)-7089-Bf}(-QoSofKA=jHGIUlrCyh_Lgo9!F2aWpx%Kvrpm;^?I0vIPQn zc$P^axRB$Nk=z4*OKrSSRP|L;Br#M_J#A2x(kzfb zGzlirBDM$+o9Q*TXzv+6C1}M!Q8o?n-(`qEcdWTU7Ed(On zdGtE>itNW@7oGP09LUA;sG-a{m=;?&0vvogK1rd#oZ&pz5^(|naw|+w&86v19p&(G zo2@S4q4mWclpD;WYmabwq)pKrp1PGtq-bc>O-{(6$oH6)zEsx-APeh=s2oS8G;MLcs*lQ&1!UdK%17Dx)lo8IR9lYrrPSZd>U&*0 z48ZW>(R(WN_2QES02UUo#l?mBug|_6#tnPXA~qr+J}iV6;pgK^fsAMNCxq$;n7|7H zFkk^+V}UQ=`|RA?xKdYw+N@f`6*XNgqgjO3E7WZL5!gGkwWG*+sA7eql(wno`N#>g zI3M4Of;PO?#XeOu_I6_QgqcsOe`T@o7KO8#hjkWD^QxJ4w9g((w~w|37H<*FoF@zj zb#JDtK%NcJ1W>d#5CVJ}(wPYa;#absj2mb4ALZVBvjWGVh=KDs(Mxkc#agm}fDf3l z1lV4+U>LQ!6M<{|U|o&pt+WSg!z4(pi9gP2`b~Db#fJ6a(l|MVTgA0G$mn+g+JoIOKWs;G z8WMFiJAz*Z*t$?)!CT=?sbw~n&e+z((&cxqQSGSk^gEDG)+-5@iZceC`I&(lEOADYSikV?n2=NNSZNs^hiE0rA zqA@ylE+3RN+pM_Tt@@dO#)g{Q{DaBaxA&mIFZT;~l3lxJ_5B<1xzp{GhI!9-Ua!eZ z(%CA5`yPSzG6e;uiez}gyR1Pxn0zfgXE6lRmC%7ASweA8q)Q)~@R$S^%E^GCM@df) zyvXPvN*y9a<9XIF+FWk8%wCu4?nWvP+dk*(5O1le^C2Ex?Rbpytm9z?{mQg+QAHZJ z^;o1|V#sl}50#&daOPV}Y!Z0YwcMVq6QFl3RbIm!A8D(IkK~*w?_HZf)R!_^TjmGjs3r-Kug{}SPL0pX$ zQV(CBSmWLT$4t&-$6Dr$ofQ(n@_1F%(;fNUNjDGu)jh2Hz^c6P2SXBH9PAH7TA!c- r5f0_J#Rl2}Ro}q2yU9jcFID}PGS9h-PsgL?G}CoQ<}TWqARy>pZUP+U literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/dirty.gif b/images/mood/charitycam/frogs/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e4dd293c8a149f1f8401c1633c16c258346472d GIT binary patch literal 3116 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/embarrassed.gif b/images/mood/charitycam/frogs/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..afe5054369f3dd6500d7b1e50fcee4ce7353eb3f GIT binary patch literal 1790 zcmd6n{a4cW0>?jmc@WVMof`QRUX!HIF-?Y+?#rBMZl$SIYEvePpygyfRGI|>Gbtal z3!6AKAJgbssn^UlI!l(C=oAgTInjJ5yfxiY*4*-T&;9A1bN_(*{_%a@=e&P;oma?# z{S3d)+<-TDU3XYBn zVnzged(n`Hw|}m$QRd#j3Q!Ti5|98H0PGvE9qSaj!W4!xzOmc|eywLr z&*`PPh3E7oJrE#UiXH4!>~F(20>KGbod^l<*^u|W59a$mFoO=2)l!~Vf>zlgAR)u= zA{dS`_k6H8UGsf<={k7z7;tIw z{E=&>N=^Ys~aFS_ifRE0Z;OT%eQQ#`~(UmSlZU`+{#4xpMB;=Go?84?iY z5_gaZ^#wcaQ!2$Si`Yu8%AGft*2zLwmss00T)yO<&f^?rKqJRfWQ~jUU-nVfYWRn4 zwGg=wjL~1&;?HO}r1PWOe){RT{#r#-jOG|82rYN|s{HfPC4{8x`DEN)zg&@p*Gq4$jyj$J-MA!$H#jn%J@^2kEEHKBD{72%rkcaT_#^vAk~#Py=Zer>{R{Fo zDP;r*j_{kxLyX;v5e|=hBf`gC%r}2^bn1?QTjW*S36_O34Sm9V|mI`yqb z^yPov9@=H`qC*$B`(&ryYi|VnUrIr~Rm!{ncS=bTb|ZBAi)D1$%thvQ6lvx0Zed61 zxR*=SX+r`MvQ5x}+SU|2@LuW2n|v{2X`c1haemIV!mg97orHsvFoZ_|0^7+K#x#al zU7r|IfI^g_W=gBp?|%BDc(8aRq;{vUP_o5;3!9!;2JC7ciC2V#V19JnHyecS7er_ZijK$xt>8V;8ZS zXOovU#*cB5!>!M_o)4yUk_zeTIr3eqh@! z(iw%zZ*ftH=LY8E;6F7xYg)5q?yZWy(D`j!+cmq=+P3IYmsOpCvgI4S#(`y(JsJh} F{tNEd_uBvf literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/energetic.gif b/images/mood/charitycam/frogs/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa24b6cd846849b6a03bf7edc0f67a1cabceb35f GIT binary patch literal 1315 zcmd7Q`&ZI;7zgmr_kxm=d?iunHW*5#MjYo#klB|w8eS&S)h;$J(=J}pt&62|Uyz(D zW2hYhP9i#Unt9olWjoDDW_IPc)r!q*bT8c&tK*PebZkHQC+z*h^TYE#=Q+<0uT?3@ z@d70W#Da@V@NdWftOR5R8DnGEVvL=~7BE2S@l>@=pmwP9$n3nMsimG$oi81$t9v#b zcc^<_ynkuB`gRBT#q>Q703HuEJ?(M-cWmbHZP?R+8A)r`NW_^*u{=Hk`D(ToofQC> zAO->yzye&~15@A)@_Z?OK&uH13Rs)f-6*LD3*l~I{MIvAo6M14n~46y7q`Tu3vafzQ$n1V;u7i$i0G#>mQ9qD72B9B;*&00>FqD`9Pu z+$=m8MIWf>qIRbiM4iULr5&{Gtk`b6Fe&YF!hN)Njg|7D9BX>GR zmbvNY(Wm%OnxWA86tPauxhw0R(v(gPr(mGe&*{NYGIx?LLxZrbWnZW8M-fu_LEElA zcCVs>>gTk;(6fE)N@jA=JHR2Bv=*Y(9%U8h>UtF%$#t>HWalo=tL}R{)BXuP-OzYs zai?@Wv?R){f`g^5hpWY@nVXLwpo+OGZJD=OPN$?q=uN@4NBVT(MzMTbvLNSBd-m_Q zOsv?p2t#)2Ic|+MTd)AKMm%e-TgjEqg`Pe(Ka|y9Y0I&ZYq|L06|*PmAz{R(uq^#p z_<}vh=M{p)|>K8j1$p9D9MD^fBz#hS31_*)|qi4F3&FrjsCg& zVrW8)_!77M)aRFZfyfR`lbAqrnGc zgdt(yE66YZwGS=0m*{e+r~DZW31>82&K}MSo>EX^rIuWkVJqxj|L64lv)8R&1aZHG z*$K3K@aBF;+fa6~^Y2v+M6i_Ah$3^VTp-}(kYXP+yxgUmv)+V*Ka{OM9het2eE%cb zY3_Z3V>Bt>quE+~NX}&0_4IVNYDcVfG6Wj^p|?q&HX&73;|rIYE0Z5o`ON$!Rn=)X zCKIqcIbKXk(zJ!=ZwM+Hsgo67Ve7ZP%!)YpuCZjZgjBQxK;~el>Tn`$k_kC(2#%Hy zDKE7g``|(qvt~4BhZ)*yF^Y5dXeP`6ChY_k5*`pDuH*tcg1L3i@qxvzEg5@+QCP0L zTXlQb*r4aOt`UsxG(Y+*_dYTv@H(HgwDZ0iGv>*0022NI2siyI literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/envious.gif b/images/mood/charitycam/frogs/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..0dd98e163921cba44d54b9c58992af41c425610f GIT binary patch literal 3072 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/full.gif b/images/mood/charitycam/frogs/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..abada04f6fb4f968893be76905278f3adac2e64c GIT binary patch literal 1878 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/high.gif b/images/mood/charitycam/frogs/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..45a971724bbf4b21537991e6d6766c87110a6201 GIT binary patch literal 1383 zcmV-t1(^CrNk%w1VIu%C0K^*r000002mk;=00Cx@`kepMV}td`GEof0xTCOJ8=1e1#}Ax5F25E-s=+$wNPdFSn?AAR!mP(BT6SwCG}CVx>3$f*6h`fqoCDSXhhX zk=G)OGSX<`bPEKa0E-dy*yE211W@0M7J|0{0SXdnB##nc=i_!xDlp@PYE>!TmE=uO z!I>3I;G>sMMyXfPLV8bn>XCUU{~7903k;8fIC@g<7YYS1ukW0F}%cRDgj7 zfYoYoFd_$5e*5|Mn}G!A=Ub}^K=1$rVhNy@0mbT<>#$(KS*=0HWs6*M)>fMP*g&wL z!Gj1B7IZLBp~Hs@Axd=EaH2(m6)RqRIFR8+i5)+J)F@J+$C4aTrc`NCA%lVpUJ{fE zk>tz^GGpGPNipGp3l|Rj3_A1xNQDBNR487M89lxI(Y2c-rD`jdjymRJiG z7^^^m(6R)^UaVLEfLj0)%1(F-fWXs+1v0qJkRic@2?_Y_wOdoHUI2U_D1IOqF=2}Z z0`SeyVDWP_TJ}T7#%tD}QZSfdB!U3!oLNV8H^roy$g8@VEPf1rf^rnl4~n0ru(=B%~b> zV1R%LljCQYAfWw#wCNX^m%bpqfdK{>&|UxmL;&A>5U|HyfB@#VA9@l9sMvqv5jdcD z1}N5`1p1`~;eQjB^*~u9Dlnn~89uOKhy0}%K!yg0_&@|S)~HxnFb?3Lhy6(a-~%x# zMq_&E(RgEyJGSU!bpe<-B#}i%Fk%4u>BymZ8xVlr08A?Iq<2v&K&1jYc1Tc*TrSXL z1nEss!J8FKP$ZdEUP)L1S}u_0ni9AfUz`$zH|78=Qm1E^Z2CD_1#=E+rdR|Vs-~BH zR=}5~fC^gWb;XG#>6(ec$!MUO(plS?WEwz#0A3C$=U-{0h9>|46rO4viL0_&W1n)? z=-jNh9#jB>28{KbiK5;3+*tnw*y*tU5ddIu$0`890}zxYz?rHJ0AR7k6+2d1#}V}0 pxzCA(=UB|L%MwE63dGR7^ww)Hy$0Q@@4olu%kRJQ78DQw06XT7HT(bo literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/hopeful.gif b/images/mood/charitycam/frogs/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca2682d8d2d4aaff43b7c26ab84d1c54c84b9c29 GIT binary patch literal 1618 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 Y>%h3=mOC!4=BBGIy6To|Q9u9yJLL-j5C8xG literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/hungry.gif b/images/mood/charitycam/frogs/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..a059aefcd94fb67aef8194e31410524933ea8012 GIT binary patch literal 2651 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 + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
awake.gif
blank.gif
cold.gif
confused.gif
determined.gif
dirty.gif
drunk.gif
embarrassed.gif
energetic.gif
envious.gif
flirty.gif
full.gif
gloomy.gif
happy.gif
high.gif
hopeful.gif
horny.gif
hungry.gif
indescribable.gif
loved.gif
melancholy.gif
nauseated.gif
nerdy.gif
okay.gif
refreshed.gif
sad.gif
scared.gif
sick.gif
silly.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
diff --git a/images/mood/charitycam/frogs/loved.gif b/images/mood/charitycam/frogs/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..9ec11f3a68d14936018a081597d3daa9fe1a3938 GIT binary patch literal 1388 zcmV-y1(W(mNk%w1VIu%C0K^*r000002mk;=002v4e9$+D%( zmoQ^?T##@9&4M>yF2HcpCQhC(4`9G>Kqyh82V!EVuyiO>rZN{WMY=Sn&Z$F%R|PBI0zc487w*ae0n#!M z{D48)00sIEK)_%zKYKPDvFwHd2@p&W@Bl%B*9|}mn1CQbX6|fPwJ=0z@!R0fKn(_SN@ZeBI3#Kw$J;mmhxD84#F&62M1R zffCS%AXpE8rC|aYCg9)$5K1VY1OYf`0EQ1lpyG;wfo0+V15W6j1ob^|VqhwM_nnF@ zz8K?(&nXZ9hdJuFV+0un03VDIZbv|YK@M5uU3VRsfRYKoC}BbJMVUYZ-%((}m=;j5 zW0p%cX;=YID&QrUV!BnP1lD0WfQY(v_of7Kre(pIc5bN~0d96DC7%|cmFS#xF49WF6qzem3O^_faRRU6>N-UtEs|E^GDR|XD zKx;y-004AFK!E~+u4&1dJ&0DVh6i{bz*SpzZh-(^8RUJyz-xd4b2k(ifPjJE!Gswg zIP4dJ<;w{0V!qrLYJmg@CJ1TInFUNhkN`2ztcnE)NHC$c?b``tyM}$1>Hx(9 zs7APbI|5b8pA&ReoIrvCtOEiJ5FnQLgs%dm55THGf^vkPyZ##pV8B3h=@Gj|bQv{kQ?V@X6O%coK|7XFhG+*f=57oL?)mjm1AAmB9mGM>Dr88 zj%h)eS^Ajfgme+0K$}Otsll6O8YkzLSVeVblw!JRrILRB_}o@^8bH8o93FWjmK^3r zfO(4wdX;R2j!Ef~vVB?Ka&#Hc=x-a$23cOY32+dma0aYd>T|Mkng9e3KtPqN2yLf; zc?wCDsY0?9E89YL271=8iP6QZV$UX4z_ZiR>DQ=dt=OfsBudcNv?~s$D@W25N>@QFO0RTJtQaqsm literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/melancholy.gif b/images/mood/charitycam/frogs/melancholy.gif new file mode 100644 index 0000000000000000000000000000000000000000..da1affbaf24a4a7ec7827cd5012d7c2e77482be0 GIT binary patch literal 2496 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 TtewKz&Az_bZ?}p8(~&g*V@T4? literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/okay.gif b/images/mood/charitycam/frogs/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..464d3d4bdeed0e80abaa98797ae9516484536dd2 GIT binary patch literal 1299 zcmZ?wbhEHbRAw+@I3mFS0vrqsP7E9p90H000-6Gf*@~7D3|@1*l3Og3&n0JbC}vOb zY5{_^K|Nce=A293`o8$s|DJ1WIo|)j_nm>^`*(r=|G$3#n}kLH1r`5u`?-b$J39ur z8tEA@GXhm8{$$}aVvu0aVPxQ8P+(94I^Z9JA%~2Iz~QDwZa%J%hz$#!o5e)bVkAB; zJle>v6Jar-F!?yMxO3DDgCJ$kNs7*T3O@@~4o~3=&$}|C@R0Wm7VZ~56B?BLnXC%M zbP5)}VCA$?mDuaxu)<*x1A~aGf+JJYqQIF}ty*83n%DDf@XFQN;=r(&=YUm0f{8=p zT4n(QkJV+m%q)4Qm2R9CKX`p#%}G0+u7wUv`mXx4#5UK4g-gVOH18UIUd+DXyma@ zbAN1RaG-(l9wU>(58a0c-`zboTi!pfy0T&YnZ$qY?R>WngufM>!2DLO(XwJ5U&X2W zXD;ty{_<+7J4eDjh8lJO7L5ntUo8*ZDSLfa%(0j)k4=GP$3roN#=pD`3+k3@3LHpd zbdz}4!pYJwr}gDUH-~b`yc>xuYdn9<>fnr6aW7co)-t6$p@0R-tU?|Vk2_Q+g&yeS zS~7#7#ZvERGK+rS4EfY;lAS87UcWdVGZ+WCIZQN@JE=5PJYZ+aWP2u4k?B%$mQVZi z+FmS42rzSRNMqV`BB`IL%FUso;L?xav@E60^oDty1&{olQ_~y#8j9Q=q_Y}4zmqc2 z$lalMBIB$B%zQQnCNua;7GxH8i)~xs=OCySkhUhx?dAkUtCuCOQv4#9XtD7=S@n9| zo^QLf9rv+muUUV9FMG{8W>yyDG{X!`Gx~!w%`DTIa9}+HJI5k7(;kb1(cO-QA_58u z2g8qc?N?jy$KsR2Ax<_AxdXyYO{-R@YBU@$*3UTDqO8GSrEq|O(QCTYRD}cI7#46T zsVI0`>}X_Qe=AC`0W@c&q~r?lby*64rIKfLZ*eS9O>SN!~C z!}99WHpi_s)<4*l^5ulAM8bQ9rvLwEsT#~HdX^|IQ~E3Nnmmi3i9}=lEM5zT#_zH- zVi~6We7>MrKuy4*R`^=^yjHG+6^Se>O<&A!R|txTVOcVD21Bz(Py#TytdNN6R()?|#}|6PV9MN?s`Ipiz9pB1c%?baS(F$M z8Jm!+*5FVhWst_$&Ey)efYau|0cIOts|)#D8q)$C9(J(y!n7(|JN>^4F?!mugtJ`8RD?{@}sJW>DSU$zuk7* a?7`dZ52~!QcRZP9owxHrl!yQWgEau*F86f+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/refreshed.gif b/images/mood/charitycam/frogs/refreshed.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f6f7c4c93cc30af47617c17597993e3fb423109 GIT binary patch literal 3614 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 D#0MRn literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/scared.gif b/images/mood/charitycam/frogs/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..501f60fa28ddb9881728b77c08e341b8a54327e9 GIT binary patch literal 1253 zcmZ?wbhEHbRAw+@I3mFS0vrqsP7E9p90H000-6GfK#;9yDZ$`1$1AzTGWlF`Hiu#h z5UdUA*%~$HT=LfU#mD~lTwBZW{{Ox23=H4D3;h58{R7w}Gy*87_@CR)H6+;CF~HSG z&w!Z`s6z243nx2+1cMF}0}q1&gBs8Q{}>E8WIP0zn;UufxI!W}EOc%b6H$wi__*+B zBZp3e!-T?QcNTHys2K)9%AS)HosATJ7OEVc!WW)*Wk%s4?-?wNFG3bHDErT4C=g>Q zSg66kX`?D&suiLTIM+>8!}QmdmzS3^$XFbR3Vm^Dk@%)O*3%&wjq8)P*6{`$$Z2A6 zxSv%kZO+)(&3Y?IV}U{=Gb7)FV}GS18t?64{i(Gh+M$7gHLLN}l~o4{qmP!eeu~}D z@R4DjK%bW^F9VbRwrWfLd#e*1TR2#_csL9k4uo$?WW69K@cV1i(b@6x5(N(!-ZC&M zcxY%nJox73(azs&_o6Bo)*kj(wy*ou5cX2A?%(lsa)}mY^Y|)OwV%1XoB6||W_OMU ze;KOS1wOrAzGlI{hL?|biZK@Q-B=!4w|?(5`P6@m8u!z=Sr{anIJGz&s~G=$i?3KM z7$Dms6l5`rMNDhLLZ<(n%Wt-?ZT&HeMdXMFW2fK@vxYXAw6KPD?uHc%EP@9-uJxGC zT9H`8ocm09f>V=gW0TvW6-kp=zT9}!?-&#?Wtz*ZvPZoeRnt;i?2R-ZPd2TpOi5$; z=qkh5|57|EEzm6Nl$&+EZ@JKu8>{+MJ72Ao?^L=L;<1VA%7L{zo~?Sl zZl}H5$Rn!&2c#6kNNI}U8D=AhKhzD4hEGD zIbMdQOAOP@wUJYd!?leJEZ`KwbaWO{in*bQoMN^>QVc^BBE>A_o3g5Y%@wp1Gaos{ zw15K#ikS~gF&`xGrI_iMDJBV#VmhusQ%oi(#c-jem<^MmDMk?~#i&41Odll0 yxFe;QjLccrX0&@jQq0vG$r+|rk(eoF!4!s>NGayZja9vn6eAZF;)N&0SOWl5*8GV8 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/sick.gif b/images/mood/charitycam/frogs/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ee6a07181f48a958a36472971b8da45aeb38b81 GIT binary patch literal 1254 zcmchUTTD}T0LK64^t6<=zyWEkLuLyKl`ttNuEpSL372+YIxe$i%36>PEvU#q!L{R* zizo~WDcTCMqFAU5$JH>xWVm@8Ns=zI^#biXwP? zg*ONSQy$=N$N&fdnMp?3D7qPCtJr)d5DJB2ajdvToKnb7xs{?KvsHR=;VR9sWu1vN zw^BNnvIbYNm;KyKwgF(Xp?15?ZnrQ0Q~CeI>K5Bh-5nku7q&|h9<+r^fL4duZxP2J z-~s$0Km%UDXZ7F;_>jCl>PT1t=HyI?m$uY}6*Ap@_A+1A4QL&>asl3YY3Ph+fZP43 zy8R?4PTZAANhJ(dP+bjsMR8%pl>v(Fy4*Hp%sDRA9f-HSG!d8pog5@XU?OA0pJ9w}@v>$JvHN94f zUi1*;R%bNQoh&L1%w@r0e?H@GqL;>g2D0ulMQQ^Km#fd6*N(`BX%5!QxLZpyLx!OBhHr_&|B zd5enuHniPu47@}%1X3Aye~?2%wMfphbSbOgHjSS5DepXnk7MBw;9fBaiNuJ@+tuCd z#Yq}^LpU5VwJ-rgb}^VH93vpde_wo1ZA*rT`E-^^z$+;3FIl5vMMKyC zOm!EaT!U6IVAzW0L`%~4KrlnV{AykM!r+Ay&hsIr2IP8+B5WTQ+cgeBBr=c~TbCYP z=O5dL%e5FF(H=WXrW;B9`&=;7abWDm_bVPQrXPJ_3+PF?y0eFO zluXJizxJI*eSCHeiJ2der&)M+veh?9MMGFKs#j2nA^(kQnh7DVIIs!^_+9zPnlBsV z`A=L0HAT#WUF;LTVg`lQn_{IyG{fEM!si+0xYC=UZxYjav%!}%Na5LE&ZuQWK%)1| znXV|QVt8h|OTQ45jyfV6b-QO6=k$20B{h4;bcE#aXT>8jC`mIiX-s>MzCJ!xBkC(I z4K#ZhsfJ)($>N`khe+p?46SWwo=(Vo>m;AMz!~Js9V{TxC#$|@nCF!rBpyrKbuvS@ z$MnsUU{Jp{HLoH0s9QZ2by0i@SgI|C3G@3#zSYvi2wfIry{^iuXzuZ0c{X&P-v3;G K!pR*4V8>tJ2GAY= literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/silly.gif b/images/mood/charitycam/frogs/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..b82924e6753f547c3eab47920684e678a37fb400 GIT binary patch literal 2458 zcmcJQYdBPk8pqdKvu4Z)&A7}(Y%`gLB*~6FH1#Zr)Y+%RU`*sP?j*HKC|N`0GDzt% zh=!DVO=akAC1zLqB)gz95!mv9o6^{0EKD57|{eE~qyzle8&->x`{C}G^yKwCT zO#vIAnE`w&A^>avh;$;EMJ6vNv!Yn`bYRQ5Eutg#qE=B9k#%tD;E{!@b0E$G&e16W08qt4V)0?BDiMgn zQ*_VWlXN2hjzEB8wF8HaXfz$gnFJt;n08X);x@xWpJHEvE=$@T_sonAP!7#`d>BN_ z6O_D$wF8$`38CsnV>)vTNSXa2eEyq>%Ge>Me`2+l2~5$ai<4${(R`D~W@&zLIKyye z3JGreA$cU}gAD5I^j5*lt!}a;gPjkVyD8DiKnQlRcEnqIF?+>l^QEjvcw>1`nw1w| zK(Kih9+-V=yRtjSa&lUPH$CI}K7wn3vc;>YeWF}4*B*;JRl?~@wRC5g=4pi5zdz&V z#kmN=mT~7LR+;hs!7$t)bi&t_7X}5oFE`7`?4$b?pJhUoEn}S`eD6?ycEO1HC9g3`}x%DA3)s5<=%D$dL zbM#A~a?xE4k;?Ot4Of-IvvI~}qQPr#EG(`+^NJc#ys(pv)b~UVM>eRAec5%RN2pK! z3s_nUU~&H6U}b_BT&$N)Fem_#?d8s9?4-;RbB_v7i9;-^7;-=7r`Y>s=yU{F1JuW~ z7|PH#h)4#qZ`+Rg!mt%Jwy*?&U>%r?U@~hQmO^2xZa2u@!U>Crs4&8Tp%pE`=>SU?~(L3rXw;81#mFiR(oFx(1VM7>IE=9MdNT9@@8m7^wozG4sOU_u=(5b zXnT>1nYr!fy20lc0V6IZ^c;9rO1~C^|BW9mz7nJ;T^T?HAz6&#)=>!xv_d2@m#hN7 z)JCmO6VAD4Z3}el8!bq6SDlWo<<{tU<{KDiqfb|Rh}~s+`hbdoj)dHX#$DWyfL~A$ zT93o8RQ(6-&|Jz!vVUq20|YHCqS~+tCh2l`^!2=H09SpWe5>jp>h-QHqfrOxLOVYE zo-pTeT>Zu2=|kT03sa-O9cZxNSKNUB)g2sh`j4o-LBIIv!JF$g`HQ9;$@j$+RfB&r z?kmk7ZQtX~Od(oG5n#-Ax;UO}ff*mx*s|<}c-l`|l6uz}%TFWG>GxrSX2E@!9TeAl ztdfGf&NR6v0DXSsgqLRD_Uu@4eC20ia5h~xLzttYM77tm!vnfK69B+`zGsdb-p@>C+qJ;GT9Vlu(iHL&&nf6do)g z@ykJ9s#|yzJd*!ESm4)}&{&ui8s;Q9-4*T#M>B>h{#l#JDc+b`uQ^<$R(w|F;f>NS z)co5yfL5%b6I)nYXnVsjrdFZs^Gj##Kx*ob-HNVj_ljDn&_Tr^rw z#lzog?r%w>?=+`cfGEe}=wtqX#|0fD-|Vh^m8}&%cXhQb>M%i(&jS}cS%&z)M6~IN zrneOY(H7l!;>H9a4akTYfJpDZ#fZ8eU+j?YhVFdxU2eTi7ku)ygK~xZ3WU$q_{z5~ zsdJa{x+iA8N_Rte%2KkqHFLptX$9JVB6xvn-lGXYja-5nTPBqiOPmQ_F>o8g%rOt&RVsNw*gfXI@Y3CW3tz@4n3?W zLGB#ui=GK4o$krzJQat_dTIWG$P400<<~SP8Wh)c7bhh%S!MTSElXen@%9 z*u&?~B4HuF0?dOz2tF5?>c>Zgtsf6^A+k+J2H;YbaFRf&Ut%qiW8QX%8 zvJ)%fr0np6t0O{=+Gs|I@D^K0LZ>9-O<3@3QG8J5Y@iEpfN#_JrZ6^0Ak6t1$U)P2 zeUE7S2?NV~QclmF^#PSE8mCN2iS5}b;iysEVl^8HBM1_GOVfrtvFI#qc4yVe)d^LV kCbYUA%cCvDNwKV5E&YGpEH7zCc-cHlpIytv5>-q3}c%E~f^L+U24i5D8iE;s( z!F@XTS404O0g*6sLG69~ubJhDfq~B)yV&qEmcHNcO54!it(Bw7rt%`IJro zI#-IGG!W-ko-YBgv_x51Sz7pS>|!{Pf=IbQ^Vr$NBaH4e$#_5MSYi-jbP!2TjE7BP6gGjR0Fnh2^>d z!`ch1u-3dKw)c$cjkp%Z6JtkpHz1=d$O_{C9MpShM`a-L*QTt2MykAc&G4pxyL7Uv z+7rX!N!a>@#R{=J;U%naLquGaicoRVcwUPw%O-9rHt@0In22a$^#QUqk4l)v4{Kh9 z>JZ=TI}qNKg76wMO)Usr>kqH$5|!nQB3hPaIcugt41jIg`^OgEOK$m{k$U zc_ZZ|fv*jfDQq^gCT%E}i4r(9FZD5}p43ScgqYf?a*vx+9%o~Er?i?>2LU(R=>CMg zye?f>0g~2)Bgyy7f&kj-a1n#dI4li_w_|yt9R}f7qO>uFI%Sfr8M&17$*@<1Pg#A~ zXK$0o`K|9BWgPwSosAXcBkaH`c256e$KtPIN3^ta%~vCSITXuX_JcZoM?MV>?GI;3 zIty(4juqXyF8=w9@gBB+@Y(8LG%QImhn|GC!P{U%Nz15jsFt1C-IF-lo&yD(X6$5b zy$6#&|He0GXzM+E?VifH@q)*)z2t*YHnfWf?$Hl~&hCw>Do+(j>IP(|P*u1oFubTh z24+Qfyq+4qo<_cheo{o*5V;!k`<>9zaT6HP_f+75vPp(fAICD) zswQAebnPk~wM)(Fu1{JQQ-LMmaCi&OrJa8#;YZJ>Up`d9Me)Bw-M(sUf2x8g{nR$` z`9UNeraFJP;y@9r07?FvM2+a)tD45FS2IuYYC65IDA`ak2B38Ga|wDY@;*`=B9mRssG2_tz2zaw!*F-S@peO3#N3`{pkTFYj6n8L(fKNOqM faAY4k%nzEpTAvW`>e}?&otdkI`Mc&Y0qpn(+JGxM literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/frogs/thirsty.gif b/images/mood/charitycam/frogs/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ed8b79c5fa84026fb7e4e363aec6bbdd5a9ecd5 GIT binary patch literal 1426 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 RZo&*Jv~a^-ITR2806Qn*J1hVI literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/angry.gif b/images/mood/charitycam/goth_boy/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..b61bc75912ffecb7058a77c98a2379c04daac75b GIT binary patch literal 1106 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_6Sqj0|!Nh71fW z|1O-+oF2<|e|GM>yKF(C=}kA5%$+@b(tPVlN~>!(#vTscacXTmpZiVL-s4XUrvzKg zzp&zpW(3E&;B3+CgJJsjpP1X+n|Ank(e*V~7d3~M)!1!!I{U>&y6)QZ`E}v!>`l!v zWeF)QOwBF5J^iK9CA|};PR#F|-pnv{?$pAX3G56@=PX~cY@y@4rOQ^%SvQ~Ey?4_( z&TZT0Z(YK*{{Yu~hJy#@?me>qOnaYg2`@Os@xWKJwFN`GES6}7L&19p?uO!;cr9C=k#Z*LJfC5SW@x%!bFbY zn+}+O=|CEi4hnRQm(Eqou6lh|{9&X<3gwVl~y{c*d~ z(X}-dl`XAVNtrdxZQYp(y)_Koll$VkDj8%HwAbWgoD-e&BkKrRKve_vhVSUoZM_Gv8zWCC197z|g?pc%Yt}iAyEp!-9Pc wtdeGb*b5U5cKYyzOp!3Szt=`gP(Lo&i9Kt0At@;-LMbV0N=kbODTDw3goFUSy}iZ& z0LI3~|Ns9NuND9R02i+oA^!_bMO0HmK~P09E-(WD0000X`2+bj(LI!k&lgvnR1DnhI*8iml}4XrhQDFaBgpLU#oAju(7jmDYm&kvIf1f zNe#JYz!JiK#KpqM76WGk%NGX+3IGZU($E#s)7975*%H#$-QM8g)6~}G;0faC*3zWV zPvh#x7YOf)A70gz@TtQEE1F@` literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/awake.gif b/images/mood/charitycam/goth_boy/awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..d9724ba811ca9b57c4384a7cd7b05c918f1c558a GIT binary patch literal 830 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_oYQA;b~DVJ(bUT}XZoU9(-zNTTd-v2?753qPF=R5W^VU_P2FvqH%NAN zlsD#YuRl^IbM(ZN!zat-jeowOCo%8Q9tHYu%^FJ+EH+c%K~m=3TyF&YVV(%Dz$OmTUaF L(y*qBgTWdA?G8U2 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/blank.gif b/images/mood/charitycam/goth_boy/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..002224877a67c237af81c0e93a70ae0d44665363 GIT binary patch literal 814 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&tVRsn3_2h$gF=acg#v6SgP(s^eL`Nd(^eibnaFx1-$MU}whwS0gj2*jdKQ5d7z1*#^A)~Ijy{Wvh zt)ZyCw^gXBadKZ>XJ7Udw&_hNap~c6Qa_q#(Q$mN2pF4l?(vhRbuU%xjeCzn(9S8ld+%CTEcwO1{ mwbA=`3Em&&KZywfqYdFtE}%a(fd0HT-2D0a(>GC|SFHgbK{aRq literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/cold.gif b/images/mood/charitycam/goth_boy/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..aa28b434ec236c350e0c2037990969eb442ff6f9 GIT binary patch literal 683 zcmZ?wbhEHbRAMk<*v!iS0xc~J$BqfC6;M=E)YR0h=Fn^biv9n;ckkX~3_zJ<|Ns9N zUoQq!2qYE%bNji51UowhxEkphFf#&06@RjDvNP~9=rA&HGsrNgGcd6H+i+6Td4|~i zT`SMuNlkssK5g-YRnvYM_MBjIx~ru8c%O0;yWKQ~K<6VavfX^*CPM9g5}PjXxZA@s zKcrwuskzDg3JK*$LY<4YSV=8qec@s$-7(qUK-Q)&>)xL`-!}p@U(KOGsV@Ltl+U zX&*zTf^ZE(<&=zxGYw{Q$`#I=#XV=q{ES7MD`xdpZkV!q$(Hr=*KOXgZq2ThtM_c2 zv1|7J13U{B?_Ma;Nfr*?)w;-T6pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVj1002h71fW z{|ZieuAZy*+@wGM`rLTmEh5n~?1fRvAj_ zRiAD;{BU`k_EDE|>$S_SZ#|PSDQZN%l&k(w!{LI~L4M%+}nH2!3h(^3|Jn@6BJn{rtt^`|G#A zOxS-s^$tHXTdL-t!CiyR&5C{Y^>S7lHx(#N;T9aeQ47k)QsAh43(UvUckXz#m-qi1 z_P)s;Z8s%XEk0S6ue1A;nvRp-t6fKew|g0Me7;*{`6%VY5!v}(k1x+$^Dif4^|hTT zS^EQDelIvN@$``=LbYOB&Sz{D^)tKt*x`FEe|YeDhQ^vkh6ar=sS%a``gUOS~@Wy+?_JzM*?uW4wiZYkJN zb9C>%V>O~Dk4e?ATsS3trbOY&arrCy%;n5RkQjYn_~7B=r_XdAJbCq6|J|b}AGO#& he|W(DJ>~t^2@wqw4Gr4l?e+P-d32;CwgU62H2~9AebN8` literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/determined.gif b/images/mood/charitycam/goth_boy/determined.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b3ce3d6fe35bc397b92862a740e82315fb1306c GIT binary patch literal 1018 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8q`_oT@oATNoJj?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVObk*C1`G@= zzb35lT)j8gYtOf5Qf@s@ILc&J&Ab0}X@>Vy)!F;Lze+23f8J_-f}#dj`?1bKkHoMU zei}iqaBc%YI;WZ~KIXV|{1yMbBLnyLe8#kM%~M%#|jCJLhfh*o!c?F+Ub% zW8+}p;CS^y_|@yT??1eF_3rDpk3ZkM`*Te8!*>7Jjq(*=7@xHG`R*~Pl~Y@!Ytr7n_1Nlr1YM!;hX8bc*^ulzxCcJpH7w9?QCz>)!~zxn7YZqS8x9Ew;wFty<7Y8 z$2UtawjZDC7)ph58MxY;3fnqTglpR;FmU!y;OgvS@18m>an{tP8M7A6oj8$w;q0E7 zE9cBuJ->DK^p+`ex|Subn_FMen7ga;;LZbwN<@zyk~qkEQ0hdX-1);7Pv|h0FzZ30 z^S18oJNF(u)Vh8D=`)>|ckjPZXMgwl_Hvb!S08${V)g#%etVOs7{Go|iA~#ufx#L8 D-9Mr= literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/devlish.gif b/images/mood/charitycam/goth_boy/devlish.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad33cf47c3dad5b2a3e5a1bec701fb6e421b19e5 GIT binary patch literal 1016 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0gj2*jdKQ5d7z1*#^A)~Ijy{Wvh zt)ZyCw^gXBadKZ>XJ7Udw&_hNap~c6Qa_q#(Q$mN2pF4l?(vhRbuU%xjeCzn(9S8ld+%CTEcwO1{ zwbA=`3Em&&KZywr-)LiG;9!tp&;mx=zkrh~ITr4?H%IsQwQqv$KSGysPFt=rL5DrR zX~C7?+@;^8ZtIB`xH0%8=-fHG%w<(TyUJ#_T1)G|%&lELtL7ZlEuG#gdwSZcgA25) z8{alJ*v4PKnO$wV{M_rml_8R*4XtfWHRTN5ZEW2PC2m4>43QHWrUp)Dlc=0IjbmQk z^tpX`v$E%>PFOmB-O6dx=7?-qK7G}urOQ@NS)9FVH~Z{GEB0@h($m&occAy&vE%2@ z$((0DFW(#4t9$ddF4v_q_a{GmEXmx;tZpFB%6cg9ow6dkd_De@NB)VZ|0csyysBn=k^25SI@ C50_p5 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/dirty.gif b/images/mood/charitycam/goth_boy/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..fcb1a73917d2212b3b9860ba6d191cd4a9608d4e GIT binary patch literal 1110 zcmZ?wbhEHbRAMk<*v!cQ1OjUX6crUUH8ra_G+P)LT3T9;F);l9|6hE)7)Tlk07Vr4 zbNji51UowhxEkphFf#&W75|;~%uP&BRdCKPs4U7%&nQtaGB7YyP$(}i*GtYwEXpjY zOis+z%P&e-;N{}w3dzVUR>%bF$W5$N$jdKLNJ>>GEly2QD9TGrD$+GROJ!O^E z?F^H8Co#138;ebytUi01iOZ~c^B2uqV9da=YBk6Fm1|Z_lVe-IcJ;dL+udxpY}hz! z-&)t1Tlb3}J#<)DZR?WbyG*R+&S{;hc6w&-Ep5Bo_i}IEYklxgoaK4%>E(MKX{)?_ zt@OycxwYsECo3yE13UXKtt*)qwy(c$-ypq<_s;S2_Z=l~XuSBG{vq*@+!G$3oEQH0 z*LBG2=meC!=wt1$5O+Kmx%k}O}MT_$_#h1=nxYT?B1INZq9E&$>-Z)pCZQGVjTlei-F1CC7 zj+IBZ9I`mFdD)qRr}Ac8Xx+1H*P7X@*R7a*uT|~-Bb`V0GYtgI07SY+xI6Z-4W$J9Bq%rd8SFfdpH0J`+D(EtDd literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/drunk.gif b/images/mood/charitycam/goth_boy/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..450be1a288fd810f0a2a8932f4a938b46e09e284 GIT binary patch literal 1117 zcmZ?wbhEHbRAMk<*v!oU0>>Bx)(R*pDr#zKR&!{!Ffg>VwCvrx_ZS1i|NsBR*NcG_ zfe0X5@jthpYe=xOV}PrXo&hr>P*m~XY0uom^i&1s{DR7&%=C;B1tS9kLj{HM@^Zc8 zjKreMlFH=7T)q6FbOl~6UapXg%wmO1u#VisN`<`q5{0Bxh0@~G6ovB4l8pS)5`~hC zRE5M+AiJnop&+#=H?z1nGe1uuEx$-1F|SggC^fMd$c3pcD9Qv%lmqQ4NzGG8&d)1O z%`4GUPzcBYs!LT!%}vbAQ9wAv0l@^j31liv6E7Eo;!hS%BL;2;9gyGTfuY2}@~_~e z=j)Xg*;U)$N&krK_Lvo8+4$&T+=tm-2Ax;G?`*T#yLj_NP6?Sxqa%xpPM+ZrYt9H( zni@3!yl2_uyJZ{iuYFeC+H^K4T~sD__d@S&)%)byUskB@ljU&vT^A=B7SPzh+}_Zb zD^c84Ti@Ru(=lmUS5NOmMuxf5=Q2!|>{>9dfoaat2C0Un3zn=~$hc+>*S76kn;3R% zU$|xWwgWqB4;|gSc|-apvHXv$b1}?45M%%K0P9ZrnXCG5ygb>Bo#KrprBh z?7qB<^~1Z>Ua$LoyI#Bue)Ka~l;so0kHZNE9GDn5g+ydL7A|mX;Sx8B2{2GR(jlxV zWivxS*_lN_)KX2SR6 zHJ_dHqs5YxPs*;iu`)G$YGTj6D>>I+a?R4^eXkYx&dItm%3<-R%_fHP1I{NHu5eQi zTdk5kvu;n^tFl#V+bkcLOg&?le&+So%5$~bUjF!D-TQv`_c}(#(5B|Zyr_`2R_318 zwgT~z{-%~G6M}lD&+eZ%X&NKLqB)BgW=QrgUEIpFa8;{J>#C(IH!ow{xR7i29S zd-p8cd0_X^eND$t?O3tv;E8hw51+kwY~`ht0A-%o5{{R60|Nj@S78kD;A^!_bMO0Hm zK~P09E-(WD0000X`2+j=!}_!@G@c`0^Qp8ep*qY}!6Yr*xSdO0UQ&worg^ySr>}A^?BOTy(mb zaemM0w^A5?+wF4<@Xp86G6Qb_gLi`fb^{xMT!w^SjfY=}8jFyQmXQUMfRBxWo|1~6 znVqDXqJ62Ml&YliauNScehmp99w{Ntyg20cx9kIH+xx8Gyu(F6Cwyq-3vm^u7 zeAde$+1xA!f!ZhFE8O7ODAUU5+?wa)r{3T2$74q^+6p~UEN{drd6v{J8GV)7H z6iPBu6%tE$5lH!(9u0pSn_1QYBgkf|_Dyj%>5KUp}97IYkq!`p0 z7+9`sIO(}sXKhCI_k9v(ol`t!DSGuKyk4q3BP}YoJ;v?+pF8ht<8!6?CUSNX1-0!-lU%JCbWmq_mb#=jK!OCz85Ry-M)Y9$6XKe+yC>c8n|k! z+A7PdTkEUqdU!Hw`+7T?TZFQwlor*@$WDn%51*8}w0Oy~IMJ2M#Ns$MY*;0;Cem`= z*6k}&cZspZvh9`OTV7&bU##`nJi^tZ?)8mD+=CRLG>dKp| z5OXhjpXS}EF%Qn|-nV;O82<}lo`&YduQ_%L_MUk1NnmPgiPyo#Rkj-JjZ407|J1p= zx!L{A&3{!pWX;#!yLI^HmYx;a_nFzbxH6lXOMH|ZYCKyToBEnctWC>28CxeZ&uGo` zv5aV$y=ZoFxM3^9%EeqO8JZ`H$~7^Rt((0idYiWJin5(Ec5H2u+`RA5nq&KqoY;B% z;CZgo2ls8eeCYI<<43O?mN;;0@BX`@+gB}KJLAUc*R4`--b?Ym=J@jZZmF4fvgcld)yOm~jFfdpH0OU-u`Tzg` literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/full.gif b/images/mood/charitycam/goth_boy/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..71f3c32cd43218e8a54ddc8698a5d36a37070872 GIT binary patch literal 1150 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_{TqJHm3|nEaVCr7Nc{pV440XVzk6WoKY#f1vr`;p3;z)E_)~ z^;+ZIqbDEL*gk)Fuv|6%{nz+_gg`@sqjPN3`7R0kNM6{+F?=JGg+YQrl0ga>p&pO$I8pNq?dTkjH#P({sl+Y z!b@>YzGhpumbk}z{V<+3Wow2v%dk!S%)pS624V&lA5d7WefCP%_t}Fdtxr6fp6#rh zpS5wVckRkMrH0F%d_FUOr_=|fCnB!pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&tVRsn3_2h$gF=acEy!TSG6U>*SDO&Y%0OP1N5y|fv4xIIalw+`fr>2 zJ@IB@*;36e?uD~X{yz4;{K%KJ&nsjP8Qt}9&)Avap6EX{^K6~o)lDy4mIe89O~}$& Uv`Fq$`)SE`^A}qpgcupD0WlToq5uE@ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/happy.gif b/images/mood/charitycam/goth_boy/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..33d5bd047514a690bc4633d83c64bc0eb89254f9 GIT binary patch literal 1007 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelE`4|)#SQ&uHm4#)(3QwhB W>rY+=1qODoKUpWNu=HeMum%9Qa&YMY literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/high.gif b/images/mood/charitycam/goth_boy/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd4920eaa5516f380b0cd5137e385ab7be9297ba GIT binary patch literal 1106 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVEDZ7tdJGIK z{|Zieu3mfW&e@gI;?J1z_T!Sn1zV6{%leF8n%Ql72E%;x~ z$=UuMJ&)E!EO^dzwrX+o%g?{}@+^IFm~nZWc<;uQ2ky>W{kD9K>g{!pe}{+I)YrDQ zHgc&cQC$j$ z_+6IQ*@q9mc=;&B;={+MxAeXni88k_{}$sCabRFzWNKv4@xvl-vAc-Tc2g+ z{`wN#QF=3|YenR|l`}TxdK}aASp4Da%SjtJ4tT8-;`vsy&$H;qYt8=sDi_j~ofh9% zbg^V++VX__AXAsN^HC?gHC=a?yMKSkFz52|#WnY47Xr zs8kIuW0*F9eHue~vQGP~>3s`k7iWo1UCh9_V)4=#k>ZuJHg1}|Y{Sg0TQ;$87v9Kq z@DSG$hQo)p?c<($e93{sOXPQ)Khl5f;JF^5MGLRp-FxZwjK_Vq9zA*Nba?{H#0(Dc z87!YmjvxQ<@y)yRA3tBLGyK>1*zmzc200OEGHB&c)rh(ALD8j!OEzqagrTx?yMj!m l%!eI;4;`e+Oq#X`fAl?~ksf!bN4faoqG@ht0At@;-dk86n006zcy~Y3l#>U3~LPG!l zLjV7S|Ns9NuND9R02i+oA^!_bMO0HmK~P09E-(WD0000X`2+f^Ri6S$TL*T{{K_oL!Zcbtj(*o}XEro>y3klBcMildGR~CU~;CSp~A8 zCZ(PL!?I4j!vLwG6|w*f&&i%q1rRK3;+ny+SUfx2H@M#<<{fc>%!*d;u`JS z@8t9EhyVZ~`2+OOvU1_VHtEm>SMuw-cba}L>v#qeNt{T3otii+?5dZ)?)ol#S literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/hungry.gif b/images/mood/charitycam/goth_boy/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d5e3591e320c932422e62d9b804cbb8b0708160 GIT binary patch literal 322 zcmZ?wbhEHbRAMkw8ht65^D&MiCl6nsTGYjj^zuF!o zQGfewG0%r{$1fW(=QA{yH#3wmOE<=}wZ!+f$9GC~Pw1OAk#%xIe{a*gNnP`2&RsHV zQSHiwQ&z2=Ez!NUcD?vU*7k`zdba0p+1hlVf3NJuU3+%!iP^VdQ-{K~bxIdDt1w@y zxprFd<{cfj##`zSwC_B)sd4$#i#xNPKUse7{)Z>m-)TO6to7sbi{(G11(7@~$e_)@ P$iM{jF!O{791PX~NX?9+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/index.html b/images/mood/charitycam/goth_boy/index.html new file mode 100644 index 0000000..fa49d08 --- /dev/null +++ b/images/mood/charitycam/goth_boy/index.html @@ -0,0 +1,74 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
awake.gif
blank.gif
bouncy.gif
cold.gif
confused.gif
determined.gif
devlish.gif
dirty.gif
drunk.gif
embarrased.gif
envious.gif
full.gif
gloomy.gif
happy.gif
high.gif
hot.gif
hungry.gif
loved.gif
nerdy.gif
okay.gif
sad.gif
scared.gif
shocked.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
working.gif
diff --git a/images/mood/charitycam/goth_boy/loved.gif b/images/mood/charitycam/goth_boy/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..7346feeacc963b0165e6dd3c631690b1138a2903 GIT binary patch literal 625 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3d?t7PeD|#=zI}eYMJ4{p!{QRAZmwp{XHPVLG_!HF@|n5-;}jMMoD5710u0K) zKrj#RbP`oHdVPB9^XcD9A9YN9)VVI_^}Yg~^Ch|WE7mQZ@hej7(lTK!(MIk2d78!& PB7SNnzpADwF<1itL$daI literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/nerdy.gif b/images/mood/charitycam/goth_boy/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..f0980c221b4ffd5fa9cdd6d09ea906dcd098a79b GIT binary patch literal 1060 zcmZ?wbhEHbRAMk<*v!cQ1OjUX6crUUH8ra_G+P)L_U_$#jDg|*|Nr9a#X!n?bLV0FMMt*6DLPP%kq;L+|im*Y&&N zxn~}Un{B=RAcOSe?kkH9Fl6*!&o7IfwQTGA^v|_@%eIskaWv&sF*I@1a8?VIm$kKb zFeK+rn5f6l(={V+%G8N-r*?PE>RGU`d|va6C2RUuO<1t3Lu%c`4eK_ome@LP)50x# z+N)Pilxp0&;)L|%JuN#Yoj!ADQtRbpnbwN5Gq+@K-@1J#P43}smZy*9U%bAq_~xm~ z`XB~iv@Ez}0DHxW4*&oF literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/okay.gif b/images/mood/charitycam/goth_boy/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..73b6d9d21f0d1c0ebcdf44cc0aa3601a2f1fc91e GIT binary patch literal 1010 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelExfsM5_!xl6m4!{f!&Q5# W!m#xzCxZlo0L-T=SIsqIum%7`+HraS literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/sad.gif b/images/mood/charitycam/goth_boy/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..73b8c4cd2cca57aeb797e7fc5f2b8554543fb8bf GIT binary patch literal 1859 zcmZ?wbhEHbRAMk<*v!oU0>_RCtQAmHRMgbetme>cVPM$1ckeNf@Uj2@|BJ5|11ka% zK(^w4Za>$MU}whwS0g;=j|Lxryni3eNcjl|`B986^rv1_p)-3gzYHddV4y zMVTd)$%(mo`9Vna=}T@ z)iT)`+28j`m~~F^n5F2|m+*S2_KdWs-1Zo^`+x4dvz1d{VJXvf?0jB{j6}bG`W3b* zcC)X)=_^u2SFaF@W8JhV&T<_v>b9@k$-RBA z7%=J%K%?&XQPJZkPMtY>PU!gQOP8-+J8|;#t*h+U@0~ur=Yao>`^C2%Z!6orH~Rc3 z!TYQHw~-NbHwPx_FmfCtVcJ0mR@ty#F2d;fuh!oc`D3XQ)rr$o=31(uhW zh0a{Ke&Z-3qwt+`7w#W?SoP%InIi}N?><{~%kh?~?KfrlgrDC3e*XCp*}=eI4FK3? B_?Q3y literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/scared.gif b/images/mood/charitycam/goth_boy/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb9a26357e747e9166e5dd9dd9b074121200c867 GIT binary patch literal 499 zcmZ?wbhEHbRAMkM{(W@`v^-}E_X;HcD zF>d$&+<9j!r@lf_pzGNAyb=+Ke*g3_CxmK0a}H#9ZpM7Fi(Cr_yFpP1A!C3#vwWzFo_-EIwy>5FIe zi8SSOubeY~Vfpk@%g%}GL^n^hT+Y0`e)mq9-3RyW-=DVih}f|c2M+B$e0ovb@tuc` l9lUUI(v1VRZl~@(cW-^(sYj=t-g|ymOc2R)Y{SrV)&O6U$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_oYQA;b~DVJ(bUT}XZoU9(-zNTTd-v2?753qPF=R5W^VU_P2FvqH%NAN zlsD#YuRl^IbM(ZN!zat-jeowOCo%8Q9tHYu%^FJ+EH+c%K~m=3TyF&YVV(%Dz$OmTUaF z(y*qBW7sBkW(E!h83svU;M4*W`|=g9yn0t&xUbfyES{HeGBxA&x_7LHRMIwCc$R<4 zE!`th5Hay-hl_HNIW$`s820YndyIkM*s){(|Nj?X zF9ue}0Awis=k{|A33hf2a5d61U}gkLDE>R`nVXoNs^FYoP+63jo>8J;WME*Zpio|3 zu9uvVSd>{(nVgubmtT~wz{|zU6_SxztdI%Tk(*elke6Sgkd&%WTAZ4qP@Y+mkzZP( zP?C|VkXQ<27ZocMq!#6778hsc=P9J+7bzs>RVoyvCKdy^Fx3S`nLvqhpgkq2c?!w- zdBv%DC3*@90XaZ*sS2sNiJ3VH2!}Wzm|!=7OoeIU zz;bQENzc_PJsH{G_eq#_PVtzf=+&3-da3q|w5Z(n7`OX>?!2>=Q(xhz&~@y5UWtlC zzkm7_wkdYAufOD)`8F+klX}7%*B(aSOQIVx7H`h^UaXXNo3U$G?Z;)azn8leHe}Q_ zw>OnHwlx&h_qGaEHBRoU>+H*(!ZE!mB`!UDZt4;@k)Sa52uG}Na8q2z0hMk?0fs^yt5z%AEPo6$=R_NHNi`lXwi_cf z%i<@FPn2zc82$O3;Qi0;&t?I}5s>?+6^CDa&TYDQtn&wNz?u7noq`)){1z{$sjtl_ zN~>#XsP5?CXzQ$RY;NhR>YkY0T+lYXE3dbbCoeZPJ$z2;N`H}6YeiSGZCoi9w{aUN zA~(faPV;9xcrbF`oP$g!7?&RvWjt|`k@bw&@$ zJ-R;i^0RBF?teJ{;`8fA-=6+>{_@Moe?N{s2E`#}k@JE|2^ZDV6YK7MzF3r2UsuD? z$iUs%#a+$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelExfvuG_!)SBktrFV$*^Rv z$=Rx<%VHssIV&i}Q{aWS+c5ULIMDNaK+nqwFt}z<6^UM*={5UnWrD{nU`oz;y{{lk zgT?xK8q2T^0S*Rn1_5vg$OoL9vSja-XWhaKcfLj@YfMdpgn&+bOVW<7XI+PJ5WsSP gtbr;d5p4g?@F7r9v+wB&P$HPNP++Z3v><~u0R415IsgCw literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/sleepy.gif b/images/mood/charitycam/goth_boy/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc24e01d936a6e817f728e50cd9aed2135c1463d GIT binary patch literal 1045 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8p}zexc@iGk%? z!AZ~8Mi#fvu6&vBwNR3+@8Q*jirUL2y*~IV>XhN#X;tr+H?<~k@Cd0MdEnw1Xf)SN zqqwt$Yw`6=QR_EVljpoB?^&C7@-c5!g~f*3$KPDi&Dj06bdUM(ZI}O61=lvT)Wt@Z zF?6-EcQKUs)b({YOzzJW?wrQJIcwSsq1@Shix&6K?B!a;u!?K?n$>HUFI>5H)1qzL zS8UzhxpVsNJ<})cWk1+ErDaLk@t$+X&Yo`&y>wpe9LqVGtCwZ(EKs;(%iO|j&&tZd zz`^mt?#0X3Z{JzHc=PGA?YCENewwiV{;;rl+M#oM>&}!c__^`IaYakMew#NR3zAwn zhHuP*60;&WX8&C{kvVOz#p_<}{|}zFE-{;?W;##f#YSn@eQ%l4ORCEk?Yg~iezuyk zXtwD=rvolgv(7FLs$AH%BJ52_Hf!e6)44l-Cw869__ArM@9v|i?{4?bGUji$w%c{> z18ZeNbwy=MW1386TXj=+M_h0Bq_%$Pv=)Y$li6o7v@5jDoz=Z)Ud4inr87BatXeL= za@FEZvsP?bww-<3mW`WsZP>eL;kx}Yhv!aO+OlHpvXhI~ADex-Tk*9j*A`^o(0Cs@Ap#T5? literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/stressed.gif b/images/mood/charitycam/goth_boy/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..467fc5255d37b0a7a550640171f610bc748957dc GIT binary patch literal 692 zcmV;l0!#fzNk%w1VIlxB0J94K0000Gtq>t0At@;-dk86n004x9guT7J#sC1u#>W5u z{}-Gs(FW=-hJl>YW$8y)K)uMw}c6>g!Le2C%8-CX3pMF;d2ZDoKc3@+4DE@0CjM z^G@sp_v}!c1daTcQuE?X2?#BVg#nue7;I6X00ICA5HwtPp`k;F5+_n@7!hMeiX{s; zK8*Nr;Q^5z8x|Zms3XZnApL+`^JnI&RWZ5XqXohEB~>(&<+c9lel)(N6!T8`XFsvq34uiT;fc+WK)X-F&@k1nKgNfIms zP-QeKnO>aDss%gcQaj$Nv-|vB$b12nJ4KFeEue0X_;g=%7H ze1nFIX<&_f0E?53Uy6AEnwgvjnv;(fl%JKGo}_#ilBAjmtE_pdo(iLBM|t0tzH(@Swhc1sOK{2XSD*iA)Yulo&AIy*w5X aFJ5Cp2Vt2vCPRh#r_u~bDl0og0028!m^NGh literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/thirsty.gif b/images/mood/charitycam/goth_boy/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f40b734a04d2bfcb16b4c649aa3f3707a209e37 GIT binary patch literal 1241 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjPZmxi25tr&W*{NQpw7U+@~_~e=W0>!jMLBW zU2;#16{}KY%Sv%ymo=yHo%rS*5%Vg~pOcw!e*0`*es*4?n^}y`XO=qbO8MuuLn~G-ilhgGM#&9d?0%zlgNjy-(=&9rj_hqnsDItYxZ*X%KD;~s_dr9?zE1M#@y!m z{z;RoCy3Uy=1neY>TQ^_aDG}wLRRRK#MK_MYu2lJvu$ScW?3V%Wi!W~t?VoZ5_j%7 z!m(xBAu+bSyVjST+B@@{>}fVt=2+${yEexaS|LdvOBkcLuU7#8{CI4 zUlzS{_ddsqLywO=7Q3_i)oa$bPd+@qd+*4@9WU;j@wHIsm*2rOLybpUE#T0k$|HG! z5guz6vMZgGU_1E2=P|1yzp6&mo*zwZ8zNQL^{fl literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/thoughtful.gif b/images/mood/charitycam/goth_boy/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..3be38a36704d6ac26178e4db1b6e1ed0f10066c1 GIT binary patch literal 1393 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&tVRsn3_2h$gF=acN1 z&((V^UZ36lKS84}C39ZJs&xxCa2QA)zvQ!1wr~Gd@58%$^L~7iY?eyc$dPl)&V6~w zOc}5BC$zp5G!*XMos+M`P=7k6WY^5Xy7RBL2T9c5ep}4*f&0b%owW=JNh0|STpdki z?Va(`H60TfI44Zx>gs3jnKr#)PVdawi{^DsVqZ9a?yQwfGgnXRTC!}pRNLlly)o+= z>gpTwch?^}aPV-w?6H$_hgi-YQaD+zbg@tQiUxBzvlc5W2LlJkUCq1q9z1%ie)r+? z7aFhcKYXXg{^9N2Eh_PEK3!Fd&|+9NWAbwrM=1?Hp;ZEm!!|M*88{gP8Ki)bDN``h zb@g7iv!`FbgGXl0>wN_}=eJb33|s#*F|aZSFvtP@FAwtnR-pf1qWizZR-RjM_$C2X zV1AZnPzDA;4k$nG-2N(6X=%-6-Jb7zXY0wEi);U{o3z|ji>-cZ zxXu?XwM@%16TZKBsEi?MeyB#%t>upE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_45Me9=>;W!vs<__l&)_WB!}9~3Zby6wF>^=;bvxA_%e+-GmUud6O@sB5ik zs?A~OZe#Ces1mR2@2Q(IA!kz8bOz4+IWuN0n7VkvBChExx>ihCwR{Z&*Q&lv{ae{* zZCSB>{?Cl0`sjdB$$9m81ICHK}^5QwEUX~lZa#t?N-6(A{-dGg(DfZho6*#yUCnrte z7974&%M47mQoszr!1Ao%q-F2kX|K*^|DVIyCuiBE*0JpFsl0dIM~hlxOV4q2KbX9K zzKX}g%${TSCa8Z=RX>r@?^&z2GI;s46D#xf2WNco-WGSVy;*;)pVh+LZ4T%1_HY0C z#VTL_+|P#6{Ky=Jw#GJwTA|X;_R7AlOySmv44hLZPVQl!)|ol4eahU03zjZkIB6yO z;w7_Y_RZ$*-8fA$>t|BWX5yVtj`D(AfVkfWb!`p<}s_tkY5j)R7>N(>Cv0Ns9} AzW@LL literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_boy/working.gif b/images/mood/charitycam/goth_boy/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..25cc66b25285450cb7f3044be0692c3e5ab013a2 GIT binary patch literal 460 zcmZ?wbhEHbRAMk<*v!KK1OjUX6crUUH8q_yHM70EsyQ@U7#Q~M-Fu9I;n=Zb|Ns9N zUoQqy$G`w&DE{a6a}5c0b_{Se(lcOY1d1yDWMMU8;9<}KDFGSF!18axNzc`LEnaKR z_z}(4bjhQ1VR%uhdtFAyzPz^+KSdngGjrWug*V$4a<=ZjE!g27X3U?N%MeoalS!;%=g)cdc{eH=8Mqo6xvT0qYTDWhdTKkn zC-qe}aZK#*?V4HCIlHZD%CzZHWs8^9`phfH%P)*yoxf?r#?ASf+jiP-V%xjPlV@l8 z0ii>6M~)skA;z4}d|I5Hos)r+^U?*;OP8-+zj0IO(zUzy9z48!<=WE+9FJaJyR_tj z|KnH3AGkl0@la&>_n(1L>ZSOG1V>frf1(j5HYgr$u+Y;e@%WhN!23@tE2m#49Nv`f+F+F4#^PC&;odKwA7#^7 z_~=*@^E_1(57TE29imD|p~}O+%OJ$S3=CC)35E_!w~9Pi^Ztqabx$QxMh0sD-o?ET literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/angry.gif b/images/mood/charitycam/goth_girl/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..440f153206669ef131ebebcfc3a1ecf8ebec5122 GIT binary patch literal 771 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WYA$?U}jKc&}U#^`Dd`yF?*^-diBQ(m)QGeN%&oJnYMD} ztogsE&5JrdrMIa3-LWmb?^ND=bdrfE+R9`!Uq!vdYi-o}84e1YkEZRul^e0xcZz3h zaYb!d^UTa`F=ty(zt7n|Q~LPt>(!<8&6PFf?2K$|QQf`eLYaBlY^+_ZQS8%ux*HlN zP3~IQxo}EXWo=Fu!|EjqS2N6+J7Fao1IP9aOSbLUm^+`5efM^bom&s@*c9J$==g>+ zhZ&L^S01{0Y{!M-`PYvhxpVf?soCd`KG~SE;Lg!i7nVINU$v37 zzvUC^9x6L*xGGb(->p??!-Yw<&RhQ3ij@1uFZ9@aY=fmjg0Fj|>%MOpM~(zCFzT|f z)Ev2?mclkwjdNK@XIq!oOry*y&jbcFza|6TipU?E7c82~+4aap%WDmJ9P6)&CEZw zum7hr&eomd~HFoMHNmSux8v zHm#Y@u!&>MqNY^#ZQFOO+P`Dn?$&*W)*Ro@kRG1KcKqUn?HBWw96Pl6^35}eN9Ub7 zu<`WT_@$2@9lW)+;{37|D=&QLF8=s!<&4L=IR!c)$AJhJ34gU7xh{=BkVb+U*?`gdOt4}@$7gp z?f=f$?o?)}RO{|nC$0$AHy=>YS{pR+WMJMYUfcW;)#<~3`WPsD!RK5m1rj)J9x+;a!F2R z#FYcbn3)V8b#Jo09LL7=TJz1bP0vJLGqHUA`dZ?iBezT^SU7>-+y zH!W;9+%BLjrf}lm!a3a%cP-w8Up%|GJB>xpZ_D+K{U`17-kg+-T>r$~QZc+J=S86K zsR@S8n^XcWDf_gtlzrP%!jOK7*(p2=j&TJ z_KGOCyrfm@a$fH%&^cd{d%t4c`8yFL-cjDTqm&)&6fQ4-_tpwAGARCw@XSq2Pqk7=&M&Ae%1qBFQE<*kEXpjYR46Ym*Gq=5lM{3G z@{7_Hj0_A6dAWGG-13VQ3W_qz5=&AQ^78Y5nsakgi;^=Fa}-L8Qx)>_aw_#0tO1xE BI(Ps8 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/cold.gif b/images/mood/charitycam/goth_girl/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d3f7fd70585fe95ccfe4c581338ce97fb425707 GIT binary patch literal 2172 zcmZ?wbhEHbRAMk<*v!cQ1cru&PEP-w{{Qb`VA#8N@3H^?&z(E>|NnoG90pMQ&+X?L z671|4;A*62z|06#p!n~CbACZ(QD%BZiGq=VfuTZqdAVM4Mq*KBNo8_ku3mmoIxiP5 zS4c)`ajHUQZen_Bu|jTQr9xhQi9%AULTPboib7_dLSkN}LP273HdsEtNFfb~lk;

V zDhv!PpA1fVrgDf}Kl^;^{iT&RuJZNo7o@5Fyo+)F~jQFaf}^5ZgEfFoau6Lp`81f)3rsp z9^N&L*=@B9?z$m0{S8H3hB2*;T@$BwS5$h>EX$mgBO1GKLFk0?yztcYj4Yo(i;OJ^ zxvGX+cO{wb%wS<)*|tY<->!{Q^em5;Tb**qm=fKxql!iIdh?vCF6`_FZXTTNWHLwO z0n5u*4C-d0FJ3)(_nGy>$CufkWkbKeV)yx#^QBw-!d-__R#rKc2^$VOwegzU%n@e< z2Ll%<7#JCNfx(~(42FNeU|7CFEW2{!i!0kJ7pS%^535U6;$i-Abk&W$I@Ss&eqLH9 zbN0K@fhwlBH20SyW;7y);SKRCk*XBjXZs_g$BepbQ zHp9L%&w8w^YzmCx^Rf(z0*Z>#HLJ6GBMe;QBP%ua!YjiW=6Mx!%ws5;DN|x-!w|8$ zV$qsLbDc=*wQIJgGq_rZT2^n{xjuc>G_!C+wr!^lone^f+_wMlsxt?zld~cN51c)` z%iAT`|H_jci&%A3jDuIrzr2|BfoOh1z~%2-8a7R}sh;-z+q)kdH>^B9rJjXBfMK!z zZ81Jp(VNkmH98mAu$&LjVs1UhI;hN<-NyYM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WYA$?U}jKc&}U#^`Dbv_uO>R{F8lW)Izx7kg- zwJFL`{E* z=Lrv{K2q|z!N?dOkmgmU-ZQ_MiQ|ugf`j7p6dvP{o)>*dN7dBSwaVW72yAccRlb{R zQt&wLRC!^=9+{iU2ha4G=I=Vaa`N-D0)i+Z#{>*H18~SKbzHs2;`Lni{|VbewJ3?JH87`7eve!?Dx25C~&}JviP!=n@iG`1f4T>d>gg==G(N_ zy2VG6d@FOeEjsz8VtTdh>G$_FehU~#%&2e74)#lBW36NLVee|FFD^-FtD90grM)h0 zVp(h*!~E$}<}>t9m=rRPW7U%B468Vn%&LlIU$=h4qU{@&ZLZz6YsvoY4DtSPZ2M21 zSbs8Y&c0o%PhUI|xp&&39V-tn4WE1a*3L^y3y#lQu<*o-=Iod67ETDA{QljnW9O$W zWcmH!Tl$Zme*_kod=S{}^!eV#n=Bu0tEOkpv$a-O;O!cGjbmq|OCSTInk5TMj8C#| zGTTJC@2w&$Q#(ASYDGGECNQX;sny_hP^_3dfBsC)szWSVjw`$tIra)UtSZsGxJ*$A z7?}UOlJg5Hi!#$QN)(I?3=9>@%ggnWGZKq3ODdBSbM^9z(s{Xfx!m%L6bgzm%Mwdc g74q`)bd&RQb5o0wGZS+ZN{dq!^7C>k6%`q*0l?d2*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/determined.gif b/images/mood/charitycam/goth_girl/determined.gif new file mode 100644 index 0000000000000000000000000000000000000000..e5322b1277a7b93257ba65e4e9ce9ee3a21178aa GIT binary patch literal 815 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WY7UARsTvaIaz+S2Zl?z+;@j@*z^hG~7>(-_*?JH4lJ zES%lPu#jW+#KKVarOTGjT(^Ags`9lPXK!1_5au4rw(Y?FWd~v>m+U-zXyc}UEv+XO zpE_AEulLf$1&byWB+Z;YWB>iCyAPiBwfl5EdpdFNv1@%SpJt@Qz5l?*(*3LMam}k| z$2@kqcgATM9P5!4aA-|jo>qN|BTA!zL6C__rYVzcqtmf2%})ktJw-~%CnhN8OZ=z^ zy64Vp@@?y!aQEY9Cfnt;omn}V!GErOep3fZ;4uLM&j1>DtEVR4Ih+6PDb+ONphJU^Yt#~5q*&ywCsMFI>US$i^1b)=?N)mcqu`${NHzvAwOTIxV|( zcE_ClX))!!Yz#~1%wEc{Aa!O`D+9;IRdY6MTAi1|zI7wV<|TVJP48*hePGqmJq)R# zy}Qrt-*hsk_Q-*g7p|RZSle=A+xnXeVv|=~-}3BG;fiI;m%QnE_4d=8>Cv-3e=a_A z_KTazWZwfc-~)}-Q20Tm6_>SiqH3B^NusyORx$|aB?_s ztgqZ+hRDzLOFRwSeYWNNyu`)IteyTZI`hCXmKG~Uu}_wYFMJk>^lWp93ejX-CN#&c zRZG-`1sJ6Nypr<^DvL7HGfEVU3=9kv%FE03k~0#EGD|9x6LaYM|8x7fh6Fo1 z2DlpO889;f6)65>VKrjlWY7UA1{ur1^3UL;=jy!{ug~uOpPkg@0$k?MY-z#?W_Liun)9#c?pK;=6Y*sYWv(MkXWTArI z5x%@nJGkfA9{o`?&-S?AJ2r-<%8Dk2TIYJFBnFPY_R8M=j$kMDNqrm>8fW&GWTwoR z+rDTfgR_U@oc?92XD#z`u~@fw%Z8Ay&D&-#ZSUM!v~G6K+K#gBp5~UuQ|Y0rPG77n zF=@DT(Wx{e>om)~mOz*DyRK)aPrY+J;MRd_6&rmw**LN@IeweJnF|SVPUM2_V{puy@^}gOeawx(Iuagcfx_N0Vi KB%YNV4AuZdeyUjj literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/dirty.gif b/images/mood/charitycam/goth_girl/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..786b6888a0ae4a1bf60a1c774bdfa3905b214826 GIT binary patch literal 1430 zcmZ?wbhEHbRAMkgmXk@NbxT)!Nq0+} zmoqavvyEP^MW6eOj#=_EWS!@yd3LZei?5Kh^H?Lwx}15{rd4Z}%4}!YvU|%850RaF z4jtIPRQu2&mL2;#Pi)duxVY;a^QB8yu3l5PaqIS#yV7?q3XYg~Iy&g$iGgXU2g8=V zTV%G29Nc&0(C%FtM~<)@VA{FP@DwnvuI{9)e%YY(m{+y+NggeRy}vjP@ZuyW8DQv6{l3c*Drs5o*1mTv_`nPrJ3 TslcKz53Q^N7EU>pdJNV8xDOo@ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/drunk.gif b/images/mood/charitycam/goth_girl/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe65e59a8704eb7c1ae16052858f548bb43f9d42 GIT binary patch literal 723 zcmV;^0xbPUNk%w1VIlxB0HOc@0000nF)>mA0Hs1gy}iB8&d&e;{{R30A^!_bMO0Hm zK~P09E-(WD0000X`2-0v0000i00031ApkJ|00jOJ$T_CHxMEDUpWR1!+E$9;)upN^ zRVPr!a%~dTI;1Ow_dgn-BNWz*7M2UNv^7UdWmEcGBCFV}Rul+Wyjw|EJnn)g^j#m=|my?JbXgLiX)got-veFXso1YMAld}51kkC}D1-G@Yy}6+Ty|=@}te;?)2L{c|&cn?H&(pEX z(%1*l*v_A+tK8b)*`9lCnAGCv(&D*%=&i24l<%(gql$;3_x5g}pmyvD7`W*asxMxR~*5CH%o`2-0v0000i00031ApkJ| z00jOJ$Vn?0HtQ`3{~yMQ8JT&ThgPbFnG^}j(?HmOYQwG7Td&au#sV2j$K+(CG!mQ8 zsPq^JP^{Ccq-y0>v|0@oz%6^X;c;ecZj;q&OMCA2!rAnEnf!h0|7R0<1px#ERfmal zTUTv{k5vVSh?8e{j*o_gnUH&zWrhc$oS~y`f@Yd#GgvuB(ru zX=q#o2L{E&#>2%1$IGXw%*xBj(Z+$nl+e2!m6ahqvm#)>hR`_ zbMf$Ie0=Yj0{oJlo^QUP%T&PMKY+1P)uV&&8a+cI#T@Z?@}$Qp1WLAa$&X2rMY^fyJP&M6Xn&IEcv=t-hRj{;5lghB)W F06Q0;T801s literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/energetic.gif b/images/mood/charitycam/goth_girl/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d96d48e91a3e70c72ffb82238c7b8c7afd0c27f GIT binary patch literal 648 zcmZ?wbhEHbRAMkkhD}i8_!hdimouV?%pu%K>M^5CU#~vHq}{k zVpJkMa%V1{J!`3)MdHNPrHkjRTM}nzlrfWG`-W{hs#fXhZ*yeWz;JL@ok9is5wAlB z&Qxq(&34+0<U5D7dL{eZoem8-i~SwFG8z%bXCIq|?4bc>B$}4dogfQo_HO z!W1h$#O^Us0>;I^3(olkl|`B986^rv1_p)-<>lpi$r*`7nI)CUiMe|DMd`d;yj&p} zsl}-ZnYoGSsl^JpiIoa@`6UWTsS2gVsVNGXc?yYnl?nxk$=P7}{33-kAWqKD%}p&z z&P>b!DbrI>@Jv&v%r8|aPs}S(D9Hy2DwH6bo1C9ll9&vX%Scs7Ov*1yRR|680qO%e zAQGq%WG_@xu0npELP2U#aef}q`0~`G;>;4D%l!R(B9YSLVc z=7(jgqV~qk?9XDDanQ$@VfE}d#*QDixTkNv-H@98 zhN3RRnAXOwiPO6)D!pfxWzNbGja|4PbV7Mvcxrk^mQSEX#+HO!Rl}{jl1z7Iurjc2 z+oQN|*TyM&mdDGjPB~;uiEi0Z#j1I|dCpZAcJ>1|56*TnnIrOm_2nxDbu-ZyuO7Vn z%=Y2q%k0mxq2FJz`~1rJ(k*`Bu0ts+tDMe+4TqiDc+G9*h%*ACHo_AWUsk|~fW@#g lBx12dGC1-<0qq8ixq_n1vc!^9U?k_E#Ue1+b1L;1tO1T6q;miO literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/full.gif b/images/mood/charitycam/goth_girl/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6ce1f4233f9d0a0848ad3185c9acd34a9d0ac8c GIT binary patch literal 646 zcmZ?wbhEHbRAMk$AK6CusDgWX{W2wJzuNJV%Fg=3rIm(zC}ZJud7iWx81& z=yL7)+4Kpg&jg&`U2?nf*&!Q8Rwl;}v%DiiLs{S7G`#s~Lbc={rcc(N92YnUv+zi% zI3)EtG3H53tC+#d>e`{M7qw)^N5ysyV5qG}M-I?o&J5h-81*dVeK$qY6IIR-JHDGV$YAT#!U z%9^vC-Q|1c!yTzg%Yt5B-}dCktdiXO73*FfGGW*&_kjHlNBb1UjVmmFO%qOcy=5|M zjv&H8tPC;?;y~jVSX?IvIIP|q@o28;|EcUvmpx`>tO|PiYF~2o$%3_93ja8*j{jac z&vnM_7i=yK2@alGn#?NsQn^yvfoclTg+iNey%YV)>;iP=KhNa+g36-I^o$Y(BLf2i zh4S)pz2uCGet~{Qc~$ZfnkO z=v_W}uEF=;u`MSap2<*FoA2Gt<8{?@a;t;lYF?f_9umGgbXRXP++up%Y1-NM-}_`$ z#2J445aWNa?zL5QYHfZ?d3?QXV{K+zPdYY1l&K=!p`rum9zk_eX2+F@LL6T)A#ZMHtg*q1DyLRQB?g=(W#0xnj%Xl|j1RXO;+R&XrmI z?8mCQY1eYvSFUvfhWft<&)mfHR4aw#{DR7&%=C;B1?P;!qRf&?h4S)py<`YGIWbo+ zzbIY7$iTpmmy4InEx$;ipeVB}u_RR?FFy~cIX5@8C^<7RN1?PhRUtnwr&5o>8UPNk B+Q0w+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/happy.gif b/images/mood/charitycam/goth_girl/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b16667775a9c83fa6760697cc9f05d030083fead GIT binary patch literal 656 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 + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
cold.gif
curious.gif
determined.gif
devious.gif
dirty.gif
drunk.gif
energetic.gif
envious.gif
full.gif
gloomy.gif
happy.gif
high.gif
hot.gif
hungry.gif
loved.gif
nerdy.gif
okay.gif
sad.gif
scared.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
surprised.gif
thirsty.gif
thoughtful.gif
working.gif
diff --git a/images/mood/charitycam/goth_girl/loved.gif b/images/mood/charitycam/goth_girl/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ffbf79554b8466bda3460cacf9222a50336c44f GIT binary patch literal 698 zcmV;r0!95tNk%w1VIlxB0HOc@0000nF)>mA0KL7v#sC1$&d&e;{{R30A^!_bMO0Hm zK~P09E-(WD0000X`2-0v0000i00000ApkM}00jOJ$VmaY@{-DX*Wl)jUMP}i1*WWe zws0)ZlV)M5ZMz|BzO_}WSHi(|BjAw6Y&s=@07cr2LakBi1gqs}v*7I33g~*rVQ{%? zuB6}TwUqsZ+tudzeXpLv3jqTIQGT)-S6~IKs0ON@w5ffGfwQ=(y|f3CREo341IEFm#kj%9&AG3zkifRj zzL9QVi^rDTx^LW|p`W&g;i2i4eR`GZ>0y(TY3Ty?j+&cX?u!NZ`I|~XdIv||G<56Y z8RR6VkpM6c!R3)7$Dh537bT6^=;5NriyCy?! znK5y;L=gc1A^8LeG5`PoEC2ux03iS)000E)5Xebo2o%@N=e6IZdDz#DVk(l_$f2qV zm{teIcshp}oc}A=YzHi^dbmPhFt{|IxEd?PtX>LDXZGk*RjuEztSe$3&S5h;hAa;b zhWH^2mv3oAQK23;%*}mrIu%rWfpdm^2V6H!e2;I6ifnmHiFTKMM^j6YhgFGln~j~G zesqdVgOyruXlZAEQ8;O}VS^Y#?=WWgt&ZOj#iSJ9iH?>i_@% literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/nerdy.gif b/images/mood/charitycam/goth_girl/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..3d01024aef4c26ee0f38b4b0e4b3b264d6d3a18e GIT binary patch literal 910 zcmZ?wbhEHbRAMk^rd9Z%UHE8=k+{Chm&bKM~&icmbppqSn%%J@5H)8Di<>LsLc0@-MqaeYU#8) zrP61dI2#WtnCaQ)i#Awkg}7EHEq&_`Q>v(7SCI-VCwW$)BC%G=k`xqUbbRVe~8oa`K#9~ayHJ{ zz4Gwt0~>N$Hn(-GnH+n<>1Cx;E86_1!0m^rd9Z%UHE8=k+{Chm&bKM~&icmbppqSn%%J@5H)8Di<>LsLc0@-MqaeYU#8) zrP61dI2#WtnCaQ)?_N^jE4RJ%1!u|GWtSiNd}TPWz56FaUaYZGJ!^Yo2}3(;V?m1} zOLtFi_T(Oh=FF7oQyS;aaQ1Mlo-t!-$HM;5Ia8J|=y0BpyP$K$@=Zlc+B(Xncg|X4 zF|D?)Au0V(Zrz!jMJ}yp&sG$jI>W@kR2JxRD)G{}E1P#;3UHWRe7oQGg3UxG#}BhY zt_B&hurU2H{PiigQt}t)oAM`z4>YT?$=Fyl9GTVn>&T3T75uEOjAEK;EjtPo+c|(S zt@tm(6BK(^z-WQRw=*P~u|zpIDS(3A4H%CFMVV!ZC8@wD&qIq-U?k*J>M>XY0Kz5s AssI20 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/sad.gif b/images/mood/charitycam/goth_girl/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ad8a4bbb1a0c2416d0f38f5970658376b63c5fd GIT binary patch literal 763 zcmZ?wbhEHbRAMk-nxc@Ir;wOesZfxZoDG)GFH%SY;^h3?+|;7v%)}g!GCc(a z&oqU~{8EMT#Jm!Pl6;V$LJ6|D$@zIDiOE2@j8uihr2Mi}h0q`$pgxcTB7qt~_Cht~ zD&*%W6r>gv=jQ>9FHcP>&MX1C%-_!^l0oq&3#$>(Z#tlW00jvH%Rhk=o~!p-ygs}8 ze}YC|O6I(bRqJwI&uelxnWl5pDDGyN8}p6@@2>q$tUIJ~A!Coqe6QHe+gqZRPP};LQr5#-@!A`8b zoowB;Q@Uc~QYO!6o;!uTsLgSD*TQ8}7kar^tem%gb;y!+8>cO3ZrxI_a$4hxmTIT$ zriR-3e%G2~XAV|{Eu^I#}VMcxN5KI3jts%i|_;`9V=j( qfF(9(NE*YE-oWV)6z6WhL{w0eS(aFm3QTW#XbB3K0&*(#7_0$)J{j%+ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/scared.gif b/images/mood/charitycam/goth_girl/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..17ef2c3776431851683722c2c5fcbfe76b88f4b0 GIT binary patch literal 721 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;pAfAWYA$?;AfC$P-b9Y`Dk#`(|Lu->zt)~<=Nw;X4Yi9D1Cly zoo3ane98MSdHmGgJ-5A^e?n*(A7k^uO*!{$45lnxpcBCt_AKbyA-^ zi-_h0sGRerZxZqhsV7~atKhJyu(R{2wBFWjIL!*@;1I6YW*zn?*=c5~-6NGP0! zg@XA9cqkY^Lm}0@y`rOQ;>4J^?uiqcTioJi%`ECkiS=68Shm122ow%$9agW~96zma z%a&^EdD$%cvJH)Emd3Lj4Gmb5z9YZ&u;#jhj!WFxnKZAr&b6{)zsAHO&cbw4PgR!l z$%B25pU9d@KY8=!-HR7&uRia4#r93+=&w56kJlA}q40ud)9dzvW~X>oDXW?eJthXl ze|gFI1(ija=@}&oMg|6k3gzYHddV4yMVTd)$%(mo`98T1pZgPHZZfa3-W?~LViJpRj8&I&ID6=fF1guFRKQE_J HkHH!M*V!Wf literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/sick.gif b/images/mood/charitycam/goth_girl/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..8be8f4874dcc91f08efdb01ff732c05df00d3348 GIT binary patch literal 2383 zcmZ?wbhEHbRAMk0BW_Qh~+es*k{hA59g!h?kK^EJGS&Yal%!jaXsR&DRgpya^C{`0$Xv?i)I ztPWh8#M`-f6(fVdA*K$lus1=IOjNZrq{R+Jtj;~UO2=bL?wyTgx0w>EE~($%AOH2$ z(^+Ndahu!k-jms7{Ne7R%Hw+PZr|7#y{W45obH-0+Sk^E-)D23xwYiVPEqGsakg8R zyjsJWq-=W2>e1`vTxpl{&fd^|eKFQ^zL@3YbzZ$(Tqz;@B;THy;Xe7eoy6>&K9kOI zhS?w3Th-XD#%+@Kylz3&kI!t!ChN=JKJc^6_4;IegWr2Se|~z~etdsilTSKC>R#j^O3&vbF&x{wpbPaWqQ8;TwIae48@879u_WU8*bXlCx)B^JQkbXsG5*{eU*|f8}F{IIw70W);?Mi@mafJd&c&CtPG+W2WN3TJ-0Nw zOh0z3xTDzz?(p^ZXYthXsqswzczXgH?<7`+g+`611YQJf>ydN_I;qH>EVs6@M7H+;U+Ivt+bzZcaEfP?mlnF^>boxlqJqIzg?I6V8M@T%qKdfze`Qa_3BUUw$5nS zv#VtNiuIdB*VI&%KDoZOhU=`xpO>YtPA>iJv-4WznH?DuZ|&hO$%*+WE7^CqE`YI# zm6xG|A;Exm>)kT0AMFR~d37uj+{!ycgB&NZz%QXpNv?jj`%iUd@wM{Np&zV@wU7Oh~zMM@TglOZ|Nd8{cArS_2}QsSj=Q$ zwIsQh?aPe|{pMUJ1t#i!S`p|l8Y{SR37N4XDALf(%GS`}ENaz~*e1R2OAxbsnuG(h zl9kJ&X0~}V7Pae~Du38*aLhuvmuKpZ`@I%X63Q)%Um_;->FyiNCD=->4%(Jle5?uw zdQ7+k92j^GteDtidZ{9r!OHANa=#th$qN%)Ze^r6dI)hYabsiz*C<>ARx>xQPFUP@ zcU94giyITSF4DdIRr}V4{DVfeFOBuWb~Eg_v?lv{?w#3bSNn9O$}=68H!*g|?wPVG zXn&-ld7q@wrqsp7fpObxwx&E?!|J4bbj_wknMeGc#V4G)ntbZ)|Ne3 zc4EhDUC;A^{aOLF6Mnp(D&o6Jui(LfPr!P3Ro=ar(l4*srUkE;yLI4eo9j%4{BpZr kyH9?6eAeB4e{AEgwl^!Q>-QVf760OSD_@Xrq`+Ve0P+v=umAu6 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/silly.gif b/images/mood/charitycam/goth_girl/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..f3189b76cecd63a01dc4dd783a60ce7a6ef362e8 GIT binary patch literal 1672 zcmZ?wbhEHbRAMkF z^;|QjIZdAq41$}@)-5hBEH{pbAGz&hQX%^E^;31TS8raw|IGaHBlBn3&~Ho;KYq&o z5M=)0w}7F^j7Nz_qkygffRqC23X0p(>wrn1t0TX$8x#O-wVjQ#fB`URGAIE07A&kQ zndQ?w9i9k40bsauA20wip#iWKmi6n?V@> zuq@D7)?WwoeQA1Eeo;+##gvBWb)f|dih%*qP!>Pir+Erd0WjHV$`oJ{xV3KXp8G7& z0GK;80-zwhJ-@E4+o;mJf6Al@U7!>&v0>u8UQhx6mI82$rU|8J;WME*RP+nfHmzkwQRGW?5oMszP3Vo0yLW}?ay}iB8&d&e;{{R30A^!_bMO0Hm zK~P09E-(WD0000X`2-0v0000i00093ApkD`00jOJ$VsKR_}0z)7G5X<;AmFmsivyQ zw&DwW^32utmtlDi2LVd32b2JV$4ar-83K;bq><_5IHTBSwYtH2v&rrCONKs`+Ok?Y zAr}G!0#Hu(8im-n9$1ji{ZeCjdU0@sduD=AaR-fujE-4tQIL%XhnA6MlTZbjmU^F! zn|O1gpr@l$Q%3{`2C%QOuCNBOwvv>$wYIdpv23h=ySVC@Bf%UAP5vnghOP;Xygo!$Y>Lwq>i3csWeOcXusNQGKdA6x7efj%$`EOg#dvd zq}#vh$#>2d7U*?=Rb_j8b8?1#QC4qJa|e)#kC9<|Qj?GeiJ6p(mQe+qnS7#bd&}eE}&;thp zf6_`x;+Kg9-{9e>8fc&cQTC^~<6`FA_}vGNL9z6~U$+4WxjBj9FCoHi lKL|8*m{3y>QWOz>`;pNh5C9Dw6MhVda3o2SAxlI606Pb9C2s%# literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/stressed.gif b/images/mood/charitycam/goth_girl/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..68ab6834f092025905e187d7da69087bba0b2756 GIT binary patch literal 734 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;pAfAWYA$?U}2DF&;wHc3Qkx~-uvUyEVpg<)YBGjFIDzjm~ms$ z8nx+bMe@yV+}yG{Sxq9Ky;#(A#}thfIdwD6ttj!D%Ely-bG7Jc+4@_j&F6?VpO0NX zEhcR7!A_I%FYER{j^B9mTzmV*+Qy9Pe0D}Qw(!pG(&CB?Hr5W-aP}!(o$1A89do9hCmns+XJ$?|h$`M2+L zS^le;zIy(C?p%w!S4(y`PY_sO%+4}rq6JUCoc&ZKE`@^D28J%z99N z@w4Jn$|+qouWe_-FF8!DH~y-4Ym!2`_dKzhd0S2fXY6Bg=oQKkVnhTZ6CxN5PI^Aw zA#vT-{gX&U=QZ)P@b9V1S|`b6c743DYlYPEFVgo^X9`Gc+1qB+S9CJRYW{^4C9^nK zG{Un?v-g&1U(;3J{dU&L`>TX%?Yh-d3aa1zE4uk*k8Iqv--m@NL17ry)=^xP&c@ox z8pb}My)7-GxOHa7tiGw4wXv-Xi)YPT%rGxAcM-?h6|)%Da;(T(z{tLF)8=KnHcu;9 zxO4A{L%SH}_Z&LKc52h{RcUATuDf*ke8rTbyVo3>cVOY2+k398+}5&a$o zKWqPt4o&^ zU^FWH)4JqC;bLGgUIz!GmliM>uY_MZAktv`UG&nV%}d2NZT)XOk(}btINz01r;~xf F8USNnQdIx| literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/surprised.gif b/images/mood/charitycam/goth_girl/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c77f6ba01aa94994c47ffffa2f684694203bd80 GIT binary patch literal 588 zcmZ?wbhEHbRAMk<*v!rV1cru&K@1F27#Ozh-FxiVvH$=7gG6xv#sA!Xt|7tBjsdPl zdIrplKxK+QSy+u2*co&{T0q7!u>AXQ!gKXri`Qp&|4-29OUayv@h2C)0F} z8pYi#bCch(;N7*~iFJomE@bRcneP?5d3#IL(rI@}rO!BVH!@ksC`_5ZJvQh}UuWTa zy@GEk+uxQwtO?R*_*aos&yZYH@ju0%Ec4<=TuFZzhu#Z+0G>et7ml1ZjIZqx@YFv!jRCZO%09BM~Z42&*v`Nu>V41 zmB+EXM&>&efi5?1T|E=Az2k8}^}P6d>wPcZWMy*v+;%iG=oS+bvmx{EZ3kpeZRnTZ zUjMtV=0^F4ghN6sTxL(gCNOX^v2ys>crYyP>=oh-Y7%1 z+>Zs(=MoMtSLa%^WJy5iv&#?tln?>W1~gKffe&b;#|ID2S9?V7@b<8?Jd?atRw8V< zaFSM@*6eA^6XllV9{Y9o{Z#ok*SLfV-GkgCQXW+}$-Qy@cqVMG;M!$RdsfUjqnm8$ w$CXjc!l3w1F*(1WvM4h>qeQ{Tz`#(Uyu4g5IU}(sv!pUPF;_3YD4oF?0MUl$qyPW_ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/thirsty.gif b/images/mood/charitycam/goth_girl/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..a9a75be167f85411eb9a78d54c9b20ac3d40ecaf GIT binary patch literal 2232 zcmZ?wbhEHbRAMkwN=PEAqB%u`6rt5hgROwI<&=NBoY0daDEZf#J^%g;@>Or{C=2lb4mgMm#4341b2h5W{^S$fxa9Fs#jlWcK&WR&RhZ|K{RsU_)c=&ijll1F} zdpL@mY$raon4$7w)BPi{+8bkwB?}iHMHXU`d5 zy#OYKw?c0Zef<1F{mEV7A8&7)A80daIQoe9&e91D2Xi?}Ia5wNS;&yM`;+dI?*j72 z7-fE{oqN6G?P9lyPF68TBql99-6Xp@kb6bJqr;J$h&Cx19Ue?Oy{+MCHA z&fc(T-YqBOk>QsxwL@aQ;ldpolNq{h3y7x0TdKvmL-;?0vii?XsrQY L^_^3x$6yTrtMz;3 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/goth_girl/thoughtful.gif b/images/mood/charitycam/goth_girl/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4085935f3137dbf596dc83193200580f73e0187 GIT binary patch literal 967 zcmZ?wbhEHbRAMkY7}>~%#C@+f_K+`C)OQOxsb6(WxiMJ=It#}OQ+o_ zl|JLd&B&x^re~kOdr5__-1gQNoF!+MU4H0e`tZQ^?w{;=vBpmIZ0(ID?Corg1uc%O z-95e8lY7{kGgGEdX`DO5*~77V#*C#M3;RRoOj*95!+ApPg3cAoHx(^u>nNMvIctr@ zwA#9cr1V3%b!T!GxwM`=TTyiC3^O}(S)j|Q#7pO{Y~Fn-z+rar?S9`2HWQg0KgT2~WLru8 zV}l93soIq;dju!GU}7pgJa3BUp-6S>n?aE!i@LNod{mxS>g%6V7*!h^s2P_V<5?cW zw92;p_$M zU}whwS0gvWH2R*1vWP^fEiYM= ze|6i;Q~NAxSDU3hKMqU+Nu3NW_7>ICrp>OK zR$(1IwP{ILOKZy1?s;=pWX|eo%I@gyU!gS)`EbtWh#P;*&CpG!=zZkyR zY6m`u-xtfoT_SK`!$Rj;Hl}x{4;@^1v|Uh9FUMlR;^T}F;-+~Ier#0n=>F+e^yac) z^G$CqmK=gFls8 zcbdyiLG92UHk%lk(*j8m8&jlb`L0xCLWDIJgCGzx1H+onK-FRCRFNAo`q$&lTLl>u z|3!G_CZ?xaDJ16?R2F5XXOt*7XCxM7mQ*T~mzV1$L)giQxqA6U=?X>$28O&`yj*Vi nMG6H)nPrJ3sS0`dc|gs%xv53TnTa_HrNyZV`FS~&dJNV8sWsp< literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/index.html b/images/mood/charitycam/index.html new file mode 100644 index 0000000..f9a390f --- /dev/null +++ b/images/mood/charitycam/index.html @@ -0,0 +1,53 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+aliens/
+bears/
+blackbox/
+faces/
+faces-animated/
+flowers/
+frogs/
+goth_boy/
+goth_girl/
+mice/
+stars/
+suns/
+ +
diff --git a/images/mood/charitycam/mice/angel.gif b/images/mood/charitycam/mice/angel.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdf3ece83ea63e1fd83420099efe61a69ec2ed71 GIT binary patch literal 1066 zcmV+_1l9XTNk%w1VIu%E0J9DN0000&|NmoJT7-mz#>N1~#>U>YrQX)P=gz(N-q!c; z-v7q`|Nlb&|Nj6000000A^!_bMO0HmK~P09E-(WD0000X`2-0v01f~w000aCBLF7= z00jQfNjIvsGwX}@Xh9ejL}{L76%<9&R9omaY{T4mev5Sb4inX^)<78vGFL$alnjzS zP@pL(P(-U}YwFZSrBv&arE&C*s)8UFZtfg-D2$+|Pu6rQ zDp7;0*hT;-g`orh@c=*;ZY+irL1-gKjvoCiv7jW0$&CwwE)XVkXv<7305zM^&SB96 zET2ZC=t~9_2Lc2NWjPCg(3ZtOxabEXLrrNbr4>MMpje=>6v}F-S-|GQsheWP)nK;5 zz`tvY1rc(UZ{KhA40jkjSAc?#?Cd-??BU)7$&c3^R4|z`RzsE@aP9-{palhmJzIWE zZIoLMp84MU3GrS{1Q6xMzN~SU#|qL??+zl(q{W@=*lk) zUd%TF03rDV2{Hf<04x9i3jiYkB>(^f{?N%uC%HJ2%DWpN$c$vkNTFAOLC_3Z90q9@ z4o%a(!&IQU){e(v<#NK8?=u({3b_J^!gA#VSbYGrE_D4F9^;~C1p)?y1A<&10Rn=9go|2!e}Ym536=(r4qbtRmj-;14WI&+r3P=B zA8nPT36E2fZKSQ3U|@u;Xm>qjoV1H>hK#1KyjFn&m5#!DQXq|vg1kCMi;P&$wjokk zhL9-7XS(AD<>lQ^Z{u+;W>>o9tqJDX+;B8ZI_~cR2lA!otZ9LQ?@u^c{s1T}r4Ycp z1LK~!01@QKl>z?#{R=pd2E_o|`_9B$KypE;k|rO9DNvA&#eV)!CU7W|o|YDVDoV&x zuB1at07^c5g9M){9S%h4K$8*Z!cqkg93WbBT8pFv+Z-s+w3SVZI1^bhih;d7U1Z!DTT2p@Y^h~U}}4DWNCxL!D2AN z)P+!h!$sK6kk4ASrRPnsiaC=sFdG8qyt7OZ%&W3R)sQh@G6n?Es`HcyY<^SmicR-a kB2*@hSpF literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/angry.gif b/images/mood/charitycam/mice/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6488472c4199e8acc7fee3afacf64683007e880 GIT binary patch literal 1168 zcmZ?wbhEHbRAw+?*v!iS1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZXJGi>((?b< ze;@#<0|UkX+V9%*jmc4A8CvTiUlgrYJ8zaTuj2jx0}Bc~bfo$lQw}Wk>0*+2&Mx&-g+1cU zC9M-#+ov2*aL_0}C|tP7Cm{O>)1kzBa{G^ea*mW1V|m8TT2+@{*if98S=Y{*>+73Z z+!T5X?fPON+hDQ^Ui;G^L?Mfd$l(L-6xh5oy@V4Zp=tf=`CW?e$6)f zstbFLT#Q(JjuM|D|YTR&@Q zXlQPAS42V4tfmUf^p4uO%ze3x3~31rS~(>Xg|f1PBp5>1Ni5%1S3c(e7sKHlfvI~A zM9*P8e2C#3>#-9GLBKFSf9N{H#VrLXt8U!BcI^fi*U50E=TC3Gef~U1p7F!EuV=r$ zxL^MB@4u+4I&ST%`SD5A#A1V-gO&uFp2#6p_O@E_JQqg??Vg3s!4jSlP8%mG zukPoth?;QR)#;Shal2Ix1uj8sebZ0%Trqqf%IJDgk4qy#L9k0ZNJRBj+rz-Kd{cTf z|Naa)9N^+JRZ7>W#DP)5es7rRq9msCT!JXU%mNH%eQ+?FI zI>K&Q7HQpS%aOdjc}>6exvxr5IubsD{g7aue_@4*)C#r<*Rl)}E_UsR4JdU`i$B`5 z>E|3y9;TLxS-pkfk6Csf(^Zi9SD9a(U&mgUmdnIg&(7M`RbAUtUsc*QnYA)9var4{ zrlf3MTa89`Pvb)7Nrj9ISt$&n1r<|;^76w(7$P@`tlrgBz2FEZ!|^?#nFo% zjNuaNsWa|jz@WZ->^8&I9VJPe>+amYb?Xl2)2_$WZ|=SRboWh|3**O2zb^iI`abs$ zr_77g(+8S46%vIz*2LMgazD0Q^E}VfuI1ajhL?;6%&m!090gMg#e-TG^>1fV;Na{| zIhh!Kz$0R2>df6-95pV#1d4)ZP1e|OR_nnEDONpJ9uud|^IePG9%}ep@^oQPOZD#z g(*3kWFwBj0Tam25HRixgN!>9YHiS8|FfdpH01Ke=`~Uy| literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/artistic.gif b/images/mood/charitycam/mice/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bb3e826914a352d5799ed764da26a4539b00ae2 GIT binary patch literal 2988 zcmeH}X;hPE7RR6WO(IJSO=yDbgs{jiA}AoWFCq}FMW9F^680r5A}X>;=^Hi)JF+CK z1_a8M2v~$c>jde9WvErFA|S}7f+LGq5H}d@%=FB3KFpbqbI#l^_dMsG`{6m~fB(O~ z<3R^YD?cq@4t^kkUuzR=0&QJJ`O*OC7YWc z+lSYGQJR~0CwsTA>};Lw%}h)&(1%sc*H{@dKmtYpU;qu60wBEsw4_z(rf^D%^d|~l z{ZW25&JmT&Bi5HWf6DrVcBn$Hl_ts4Ae}m#;erknZnrZCq~D(P4l5FjwnjdZOElz}+|7+0k?U&WQGJB=3|*Gt6{xp2=xGgZtGnq` zAK^{ak95y@01ITyZB&(`$1fei5%t8~U@k3@(HZl8k0~3|bu!CjJ?2d0IF{`0ejF8Z zW^kE1w4EQWpM27@tvt|s5>5V#lwezGB&+A-c*F39NH>ZF!Aqh}#*S}TSC0=rCk5_c zy;)yHtuwG#HC23c}UlCnLV(5@`qviloF@U_HHtRm{bWW>ar8fIOQ+UFB|uTb4DmZ8kEr zv$ZGa+5tuiQ4`twyd8tGY3b)4PQlIPbx@E`q z$5YBrocFA+pw%`a@SkWZ%C(+@lB%{5c{e1Hd@76GHND^Z_{GPSS&NA4K3P#w zZueUe0&eU*W(Pt4thrBtCZPUZbAii~8~|aY^|Yz2)xGI>igh4zYtk0RnJMJ26Kf>d zTczBu(Z%S&Le0JYHe9pW{;Vz1s(eps{UF~gq$H5uMje8s$kLy+zMQ%#kPWVR9!k=J zs%44V<7~2?TlL;j?}u>|=ynDvM7H>uTQgc2P+0Pg-=^bMv-3w0q3N>j7lq2FpJl&o z*LF&y_Jo&ds)KMA3ori4j|wLDxj7YqdVL850z@|k`tmk z=WZr_#Z0mSFQ@NS9-E15>6&^xgsZ*2W)vOg)~^~;E~*@9gQc?7kTf~u&5PMT%2>vV z$KSkM>?^qZwmyfsH+k`Hb4u*tGw)VbdMJvuOp6Z>FbzaQMa)s*<8Fd2jIP@nCTHNSKMr>G$HJ*icEE|zQQpN_Zp z)%?cL!Cc8#$=Dfi{b7dG8~uqV8K>X_N+8|KQF&5JM*Z&N?)IZyieHzgY)COCfPxP-D-P*JnP= zX!E;~1Mkm#K1Zy!FVMr~SM-Cx!2&}mbsMEq=#S+Xe_8X_h_+LOHQ~y0&!2)bji@=A`d zlh+e>ipSH>zI{{t`lyK0dv4zBVU}gv^d(qYks2j9#Tmfs{8^ZYTz0;E9I-9{-UbUcmlP&Cx_ zV(NO4m7Uarhl$T5XUE3d)m*D3urvn&M63=$t3!Qxn?uoI39G<=MoJvF!MyA@fCJcP zqy{mHTj42s`zWoBqQnDyja2#Wry5@~7c5j#Ul&NKBNpGMO?g5@aTP4r@Dz#Ahg)eG zw6c&#T)DgJw9MVfiZnk^6GVe|FFy6pq26Ef`PwlwLnW!}d4Do!yO-&SUgQ}`bE zek(@e#ET9DI`e|UsgB|D>M!Ob#nz-HQBVYKcVP~DF~XD-BeS<0MNUkl$p$gXBntk` zi1K7Q!NnhA}zT+Ws)#N|Rj zMA7{~Yp7f|$e`Bq&MbNXNs*(6o(%3QGx=JUWo;hfQgsjq2uMfRQGt_2>w%_d^xh@6 zHrZR<_xy*O2zQ#kw~p3kGPHbLV3Qb6gR)9P%i#sEx%i{0WF^>o<1=12a!kx6s`{%)JRfHk%j z*7RO1+Ur3rKLwU37_ra%-=28I8qfc7I$W8Jhc48 zJ}>jgiJuF8b~Ld4?2*^ROBYgY9man)0jQuGhDdr)*M3;;}|A!y2yTAZ(A za{N6imIzGMfGRvWnue+=@B*kYa{^f3TCXOoxKvs>#8~7plQJPp_j64Na%W{}q|+-? zD;FBbY@)#=nj&|&QyY9K=UJPqtUE6*b}`^S&OdNoSL?jA?>w!LAs5f$Djjl1&S;1% zDtH0eeM}!K}8|)2le0P#Wx?M49uhPVcTAxgaF90<=-hQr{61 zrppV!A1=F4$20rI16!?ge?E{R+b{y--cguX+rr!sK}{LOoeCX1#Mg&qoEgo+yf&HY zrpb=(2M7*zoGp7Y5O35TZ=xb>`^lkIw@M=7f-CoEhGm`QJO52n|4%Ld)2Su7;oIL* zOI6kLe@!i)OL#$L2BS*bgo|XlX6R&S(ofpkUjq;O}A3K5#`+AKz|KhQ_zpmPfGjod%W9_Jw`n o483r9U|chui`VbSDLEI}jXC(5-Q{Zi#^f3dDK142a9FVSuc*-TNdN!< literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/blank.gif b/images/mood/charitycam/mice/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..8922872bdb95e024462e2a5ee4c816399c2bfe9b GIT binary patch literal 403 zcmZ?wbhEHbRAw+?*v!QM1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUFajS3Y1 zbNji51UowhxEkphFf#&W6@Rj@8ZmG&=zvs$jAdZ?7jV*Z^h+w^-N@97W|8yOT}?po{6 zZV}NWGIJ3l>(Zt3CM~vVTw1+s=G+Bl=B(8P%Y&!cI&R%ow%l=(FVo(A`&ljImTcub z%UN*lJo}DQYcF0nclpXy*6S(Pmln(09X-a(#`@^-5$31cZ!6jzS+?x?E0s?juJZN? zj2t_surQxk=wZ)kF2K-ZG9jTY<&%oW9Y#$F0T!kyUzvBToV>48&oxTXIO4#8EzPG2 rz8v~`*zcGiQ(bD*%s!Tl(Z>0ETOt?SJzZ(%t1!!8OIs@k1A{dHmQbho literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/bouncy.gif b/images/mood/charitycam/mice/bouncy.gif new file mode 100644 index 0000000000000000000000000000000000000000..69e30d598f35d5a09f5310ceb7f49525a6e25f7d GIT binary patch literal 723 zcmZ?wbhEHbRAw+?*v!oU1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUF8Kq`=c z;(u;G*N|Xm#{gF&Jp*P&pp@cI7EU7uZU!AD24Mzy1_cHNmVX5&cQ)~woX`F$w%|f# zC`ZyP(>2<&xN=_SIXm3>pu@Vg_OsQzh5`+t21$jF1=)d2ixy2$@ZwwQ`b51UwP>HY zP6^u)Id-)PIjin2?6i-_5&iTx%YWw6FT4x&Ej5#q85mgGSs7c4l$uqlySTU*f*2+- z1k_tKO>3RZK6kE7g^IP(!uc!O`j!T;E|@-bW4riL(ROyuR?eVZ413tO%=X{GdF;T> z;|C9I+s=A?itGMkr$f)Ki)g**%FM=k?K%@H^ZMA+orn7sI^NuUa5gNn^sIs>BgbN$ z-XALJU#-7?ID7N>c{w%>CKZJP>>cOi1UQ7YtvWt|nMd%`p}7a9o``2;);;*|=A!^V z2@V~hhn@lrtaEoLwFj-L;VkywIYCRaLs>oW&W?P`(pfVm9CKzt2|$6-03;&-tpTpm BC1C&n literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/cold.gif b/images/mood/charitycam/mice/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..54f5bf6f79fc5e04d7f482d8a24f67120d15accb GIT binary patch literal 769 zcmZ?wbhEHbRAw+?*v!WO0>_Ry{r{gF71h$xatsLm|G&3&>Ah=vpP$?N{ob|j@9+Hw z3jO~NR?49GpWDwhB-q(8z|~04fSC~}s`!(IlZ}CoL5G1sm_eRFfq{YL--VMe+hk47 z3%X?Aa_eak^?PB8MMd-^{yyI~Pj{>mkR3HgB3l?`=AC3ZVGTP&2LjoILS3H%+uRWyR4#;QPs|_!O2<7 zO}<>N%~RY#FFd@$t+m`hb(XrAD#x6>Ni~|&0%kHVE6>)YU{!s zJEIwnCAuBw*lM}>G#AfBp2SN&r_U;`kG^!-=gxsMhec1{zjyU?!C}qlNUr0NtehM# zU$JnozIprL#v{#dry1U>E>J(m)!D2Zl`63?`9PDbVT7&C#0iRA?flAKb8ZMU+jF{b z%f&IdW*uQ-`Wny`61cgAAgy?3->)7M_|nr6p%trEJFb zn4Sg&jTw6%o{q@WTVwp#k3rrz>_@JOJqW5T>bj;f~h;$cJ1<>vt>)jR5k{Njw5Va z4=8vuaC0B!ID7uY+RRv{OWce{&fQ|zb1H%b?m$y!1gRv*81IWZ~L*(_)=(N6I!+;Bs&IP*cng2e}? zs5}W}6%3H+jq`0?k#xs(t@!#!1`ZRCT5O7m&UqD(?975Av`>1jo~!))^lsU>ip-?W znHtQ?o}SuQ@bp+o?){2&?`!nA91iMhJmD~5PI%s-6V}j@apk9s$MTR)U@%v#jXWmy zLbqprizDMfv*L?)%M!gTxo&VUFPgAs-A9ge;j#v{G#8h+oT{?YnC|Lm56Os%ypT!R zaqi(kQn9H`Q4tQ39X?^6OY{B9*0F8a;24&<)JuFDFpwK|v#nmG=m-qtJsd}l?T=pL z?RkXp=x*+dr}iH_S9S9E?e5cwr5iZ7c5_uceO7r|j_DEC`g zE4>UhO%+fRiV#}3)XSNvFVvyNWeV3~&-7(SV!c1TcbGTdyNO}SQ5FF|erB$zQB?*< z?c0N8?OIoDSj82=z1_*Rsc}s!2TCY20MoQFI86gXc`Z1UC$m+}`!@0E_JwymcD`Zt zF3vbs(L48T*W_LEeLQsddQU7VI+DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th7S3YSm&-$CjlDEvyU-(tjb9O(wtQr^RHj6tVD$8o# z>+89Ntk*yGPPdx>Y3)tz9o&CyY%d4wSS(t5WO<3#+Nkw6)|8!oTebheh6*3OV1D+^ KBC%Zz4AuZiQQp@8 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/devilish.gif b/images/mood/charitycam/mice/devilish.gif new file mode 100644 index 0000000000000000000000000000000000000000..03945d3d616f03089d56a2b0a63f8067f6d016c3 GIT binary patch literal 704 zcmZ?wbhEHbRAw+?*v!iS1j$iREes4TEiK269lN)6>Ah=vpP$?N{ob|j@9+I*VEBLR zKM;V_fq~+GZa>$MU}whwS0gPs+BVn61Pn)ukgN2>#`i%fKmXJkvx|DBND|EfP_wcoU zj@m8}1y4rKWjcMoRn$Mcy|Dd#-~Rfa1`d)6iU;l7W;v-ObYvwqx634SEKt`wvQbly z`?%~3r3*J$i@U|r7HX_N$e>>z(3Gv2*kC!~@scx3UQW8>H`^}qQi^foiZ%|k5R`+3 zpe5_x@C=`=PiHKvnPV_%fy<2O6U(xe_B`!5)a%)9ruThMtg?fSSg}>&@ia~WwhJ1G zQ*%<&79U7BHP?;#4BNrb7OBolj31{7W^}ey?0KVl=mH}%L&FQ@Z)_Rc(=mb4afaBo?+dF%QO8`-w5 zUb|&ymc`t<`syxFXdODt%*HbBSY6T5bLWeSPMx(Ai3)shN5)v(g|k0q*7L{8PlTR5 zk8Nh;d@U<&CG^!T`g0&BbI=p(^0e+*1&pjomS0~*FK1rA;K7Fp%lS1mjtZ4Y2b{TR j+%0)#m*o za+wtCk{m?igv=UD<+?jGJ2pchM=f2>ZfAPE&c06P^WX3F`~LO*ynny18_xBBbC4yl z7id)nlp*=~F&K=2fq~h!n%RkN#Yp$Y?8L_F*-rzXl=(dIMa(~`0zD?7K&#nlAplt}~$9u0m!N|61rKZhR#i)DAP><;~9Vz+A@v~)jJXA4F( z>0Q9-NjWxMFA;@-vk?lNk_9J4Z4LsnVTenjGx*uG1X2lv5C}=xh51(~HQdbLSjtsq zX&SmXDJU+|@p49sdg70MyQ?n7l6qP6{Cog_Mj%k!I4}@8q^1V&fhnMU+|*AxH4V?r zJWP#w^4kl=v_uw)Din)+M^4^C8sr{_;Znyvc^0r8~VGS7;Q`xzlKLQL6TirPxndcO+g} zZyDd;G_h^RA+_{T!5JNair2(T>n2_DKIzK%X_KO1Qj3g(KZ(i&f_f-Eb8F60O#>}W z1e2R#f|-6HB8f|ntKz2!BGCtvQ|`t@ zojp(*6hY{?pUY+|xeq{KpP;9Q_(;i}3rK)~mOy`z*GobbNMfd~nzw#Zx>* zR`Ld?4Zr~y+lS@82R^R79h7>yteW-E*XC(W-&a;1X0BP-g}5yWyIj#4o39*b79wsT zdb%pc%()^F$2e;B+d>^Qd#9?b>0f$pT#LQ|wfZ>6TdmFQzA;!3x7ZqJV!ZUF9MSDb z57So(GoFg9GSJPt?JO83wyCMs$AtXUpLk3AO5Wgp$JF&Xm|{9@wAjLE%u@Y=`{zes z@jvgC+`FAVRls@I+{=rTgOA*>Z|uCb%AruKPJaA((%IDBX0bb`=A2#j79LokLP%q(PasQfaBO(LbRu3u#6W(tZj9PAPc+3D2m9C}(pv^|Y}KMNt))r6<< z`+BMM^~wsKK;USXNMzPGHVPCUQ4*;i#De>>{+v;+C!B*7)K*8G+$ie4UgS382{;(5x-`|;LR z+*^VJ?e}c`J;d7)_jm8Qbz(WBjbRfUb|U(G7&h9fBmQg(a{Icwt*O`EV_$TD0wAUP z_J6rAI1rK2zA>}ikK~*+fBEK)?GJ`Nv^3nC*jfJS>*0!rm6FXiD#r%o)_Zhq_KD}U zeT;n@eClPn!}!m(Klt54*zW*d0M%8Q@4l64KKhDen`M||rj~?{ilN3u2I8}z2pow|CF3Q3kIkyGGA33cy_t{-;4#IUJsjJa;E+}%*R#$$XGmPaA})HjEv)w4 z(<#mk5uIw*s;*AlmWwIIr8TF}gm9I*)z`gigKPe~5@$*gr`0-glZ9^lvh8m^H5TVi znbf+dV(*wW_*>HZZJNV**4rh)IbV?eybR3$Ydda7ZTA61{lR&Ih2%naEm%M(xB7Z%#IEyNOvCR9E+j>!j+lIyptYigR!hhnYf`4@` zs+1pP=$pGPX$wpG*_X}C>GG+Vf`feJ$Fl|3A_Pua@9RuPDN2S5Y`gY&UX5q59993l z5T{?js5J~hZB;emkWU>7m%00vT=Z`-R4sMi)LB1`uYOZtGIseMLcsKMXXudSgC00;jAF6na( literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/embarrassed.gif b/images/mood/charitycam/mice/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..6badc94a71f7393df6c5b13fcd2b45a6684711b4 GIT binary patch literal 552 zcmZ?wbhEHbRAw+?*v!WO2FH@4qFP#7jvYI8Z|l-~*Y-X?xA#5A_wU93zu&v|{r$cF z$NmEWM5*F`Za>$MU}whwS0g;!hSvW zH2P99=Vh!~m-BjGfzEjowL47h_vae?VV=kP<8)?TOUk8;kDAlZbT=qyM6h2`+nP1k zP5ZK=qoZEM!7CdN?ULa-!FAY*L+tR$^vn-=2Jg$lQi|;2h2xsC6I~*r3(_KkSju91 z{3p4F#ZHKdHg~Oem}C*rDl%_56Wgj)i#;7%mL{~YF));GWt+EXV~{xmFYh+4{Rejj z&$e*ef&rpf5G6F#@~4LTAIyo=oe7HRS6Jkk~SU}k^RvZU>?!s@p2j6R72$0uKG zP~kXas1`cm(o)uiRs|U!UIi%$i(TCzz=#N8E(Tc!AqH+>2&-T4oS8M(B6#)hZ;=m7 zCVRx)Z^@fJb;J6{=SuEgGMIkc)a<=%w2u&0y($+xJE3|bF0?#OpV!yAM5cOYmd@!9 RGX5oh^U7v_ox#Ci4FFca>rVgx literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/envious.gif b/images/mood/charitycam/mice/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..7ba9c87e601a3a9427323da993d6a6a12fd2d982 GIT binary patch literal 552 zcmZ?wbhEHbRAw+?*v!WO2FDnVF(gMtwE)5YmSe|`-P^kK-nG5Y&+Yww@7nkG_x>OI z4+IdUivPL&TtkAL9RpmA^bD98fuf2(Sy+u2_!x9RDnQ0Eu>8Al(sT7*i`Qp&|4-29 zOUaywN_}=S|G+Ft^{o>+pwV9`BFSnR#s~moh$TPCs+{fPqB>=M}ZBS##aA zgAX}6+EpC9vhmO^8NL%-N31x+4xdcV{Lp9czAP-I$Sz(ut|>dwB_g^YEi#C$EVjpg zl51G(gs5n9*LsIZ77?u?^OiGntXj3$)3Ie~LJJ22L-|&Yd5bm%nKSV6ZsXd2aA)vr zE5{?ej9U+!VOXC+EZF2dhH=vrNj^vEoF#{3bD(;7?x4?Mi+Us&^t5 zTnuvWmn^Wz&}e+Z=eE8-BzB_r*Po-AE);~U1a`%$K^y8*x?`5NXgs|#Wx!|b@)f;i4<#GDFKGh{M)jP9vPJfW` PFZr8SHv8)g4hCxgQw-`& literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/full.gif b/images/mood/charitycam/mice/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..588c97a81966d83d02093ca5c90424cb5ade9922 GIT binary patch literal 656 zcmZ?wbhEHbRAw+?*v!iS1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZZ)y2|?AZTf z|A7Fc4h$6kbNji51UowhxEkphFf#%L6@Rj@8Zq!P=ztV}jAdZ?x8bDc>b(}P&+h)8 zpwX9-IWJ??x}4Yh3Utn!h}~gqzaOjchiM+~kJFiX%_)~MK59-sli*bg2I zo^9oL^zi9bo8;_@cJEBNT)5WBYBf9eO74QY4EL|!lxDom{qpghSJ!XsU;XOJok#aq zm+WUM+O_gCGaKuNr`iSy_hrkUetMaF^woR^Av-a~nWYceby<#2IdbU4!VXtXA9I0( zEn6lgv&rx(c?s-fp0-?`gT-NUhu{>APOj#h?57(W8ZG1(KD@F0)l=D-$}Ar~x|k?% z))s7V6m2olbX?9WCbnkQloKtkrg|<&;VZzP$-u_I3=Ch64W5>2vRfZ=AOfF{L4|>v zfeR?9uwkpJ>RR3hz`%cSK($lF?9c>_HIsOfc5TboxihKZo*+UKFM}#D;&_0X^fsJS zmR<{rvG<1;a3*DR^?EGxoV_4xvPQ{YGbX#s40Aaw=PU@5W>Gz`#6W@(-3Wf55vChX zmc7^mG-AEPEd`Hw3%0o}X(vq^W=`7kbcx3%i)}&;>WkYH7HUYP9=v!_;|#~VIm^EY IF)~;K06{MWG5`Po literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/gloomy.gif b/images/mood/charitycam/mice/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..5016573fc65af2444f8c53480b944e7c599c4e81 GIT binary patch literal 663 zcmZ?wbhEHbRAw+?*v!oU1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUF8Kq`=c z;(u;G*N|Xm#{gF&Jp*P&pp@cI7FHt$ZU!BYGLW$hEdL5ldamAU@%rrU{|Op>DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th7S3YSm&-$CjlDEvyU-`|brxO#6ym*eK`w-3}lF`1Uq4h`Uv z-1`;l-fw2pMSBX>TKR})92YTr_TM_aAQpk|MskZ fwRH{kF;Wad3@xpqonpOZQOzZJ$s93)3=Gx)a#a`S literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/happy.gif b/images/mood/charitycam/mice/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee3fc8624458767517ef9d5f9f751f3e4f1b43be GIT binary patch literal 532 zcmZ?wbhEHbRAw+?*v!KK1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZXJGh$>^~5I z6v2Sve{Mh5kYH!W09PYD17=2`xZ+P1RwD);1|5(Zkg*Ib|0bODT)o%g_1WG36Eyl# zGUsKiT9@;BUxChf6R|st?e}99{xHqs{c$=ouQ}yX#z)QRXS@>x6e3u!sBO)f>!uyd z_|QSE;^38!2Y1P^ooGK~#UXb1WP0X@ID_|PVJSs+@xpOU*@-R@(FJLdLCj^bJ^qti z!(t~yMVq_UJ4~{OXcd{aoPmLLH7n!F9>R0TFF&#m*M{Po6?L$ceq|Xc=fpO>9caq&tE>5m+WUM z;N1R~o3nuH!RhwCc>9JYX)}K-F2C2v$i_D5!$yt{CvN);MT=!B*WCF0T#dYTG$t%o z?Uy%xkl+yLbW(PM&0hxvhNxq`3tU3agr`KWp1{g;M39r0eOIW_`-vCCFI*06^uD;a zTWmwx6~+Kbj)>N)uY#0>#jfrUU_^v4H!yq!7}$UzEM));;TVhTxi?~cG?FI0P<;?F zE2+IQr{^~5I z6v2Sve{Mh5kYH!W09PYD17=2`xZ+P1RwD);1|5(Zkg*Ib|0bODT)o%g_1WG36Eyl# zGUsKiT9@;BUxChf6R|st?e}99{xHqs{c$=ouQ}yX#z)QRXS@>x6e3u!sBO)f>!uyd z_|QSE;^38!2Y1P^ooGK~#UXb1WP0X@ID_|PVJSs+@xpOU*@-R@(FJLdLCj^bJ^qti z!(t~yMVq_UJ4~{OXcd{aoRM|as>Pm;ElU$xSQ!|~x3bP#v@yth>(-S03_F8oTRAdt zpFDN)^x>WBi9ppaMbYxG$Dt4}|Tm=sv79P2Dm+R$|d#|28li;lXw2$G{!&N1c zoY(*S{mZ!R0gpj|g8ZJ!PYtQn;)mKBLIv2RR2~)tPUN>wQPf!Wd$= zs{QiD4-y^(IGvR3iDPtBaELnAyTB##Pk`Z6nG8ocsSf2JDL%`mHk>;XHH2m#Bs5$Hm(t z7k^J(s?w)^W1G&5w7XWTQ|cb8#AGd;%cb!}qT6!zgpM~qgAOk9`!y$Y;r01ncFZ-~ YY+sP0J#FIY6(S9c5u0x|a4=W{0N*y_*8l(j literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/hot.gif b/images/mood/charitycam/mice/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..22bcc95c0f00e316650429e149f2720b607113bc GIT binary patch literal 1322 zcmV+_1=adTNk%w1VIu%E0J8u90001ET3UpJgvQ1I#>U3pwWZ$Hz30xo_ukg`@816a z0RM!9|Hl9S|3d%&{{R30A^!_bMO0HmK~P09E-(WD0000X`2-0v0000i0ss>L9{?Z# z00jOJ$O(cCG|y}G7NF31RS065MXW2D3T*3cL{QxDECscF^E#fOfG8G#86XjHYf%EC zBErBFC5O@?@)O7!jvUUdNQKUTWTwyr>q(EbCjt9w$L6QoFHY-OPGKQ)7da_rhX#p> zgexM4B!2-04-Z+C27iM(h5-)_4wVR=pqM;-Bqg1opOmYln2x9=RHLD_WTl%=i3kjo z3{tC(!R1C?(y~@PJ#)-k5v|m)LFU5&n?9{T2f%-^5p`cwa8g}m{wnZPOA-?lMi!Z zaX%nDPCrRBgo#cSh=Y9|j1(my6Bl@rCzhEeb8DFap#ejpp(X(WsRE`PsH&?Qp#-zD zqp(2FRtQ zz|P#L!^P{>%dfb;0ou^+1kBaQ54p1sRQ)<8PC~DGp;A346)=@PQNlDNoETuigNq9j z&RW%O7_WA*1}<8BFw%fVjygm=aNvNXMV1dt9`q=2)ykDEZ^E3>@dc_GI9&#vBFg6! zky4NnrO9iG)2C8coq|erfj6H5o+_Pk6>HU{l3Z2o8g||*rW8^s3y|O-EshA#rgBA$ zZQFkw6SS3RiY@@XrRZ@~l|TSi!)?*wT4gq+Km*)N&J|$bz&5ohMRD6EGnF<3h9wF3 z+<7zP(2OXTOSt(mC&~m2gr;mDHfqtYCd}Iq0RSQS1PL+#001lk0096W05Sjo1pW}n zNoA8`$W^NWUIE|6emYzQq#;; zKh5jwu}z*{R?oF5l^#JdPkFtptv+C5k{fgm-Jan}dCp$*L_tab8EIBdaDpvJEqfGy z6?Hd9WQ}i6IYuR!mY5YhL7q=wh@t_f0b&%WrzrsfumY_gud%Worv$pXskj2WyuGUg z0R_gt!V>|+#m39Y0Luae2-OA870=WN#=NVt)d&XMx8K|0*vjDH2G^{t#?|Am$7_SfxXsIOSTjs#<-v+){v*EkJ^syDHxO0IQZVyLSuf z-CH-6UjPa2qS{w6RssP{=_+RROBURg2n~!=*;jyp1LEkmL^V#FO<3U&K=vdc_36@@ gS7Y+b&SB}$q5ya%U|_Xp1H5IkwlzVYhX?=wJI`iPY5)KL literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/hungry.gif b/images/mood/charitycam/mice/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..4962d054479b1840496d3e1d741d2889a2da20f8 GIT binary patch literal 634 zcmZ?wbhEHbRAw+?*v!WO0>>DVqoP_`T8I-0@Oy-ue5j9KBwXSsW9s zPeidqz7?zaE5ydyvdiIF>gA4Hlgg0W+&)}_dHMdY%L*NvqZ?gPt0Eh7(!FC7%j?oI z3Um5Hd)=dx zp@iiQ?#GUtS+nv0GuzQUyRNRaJFu36XEjgRU55J{H##JlZu7i)eCPF(r}8h@Uhm9$ z^y+=(#ml=^H?pwvytwV&5Wk>&{TW`(N2?SMG%CAUHmz95!OzG!!BKPSL}!g|KcOm> z6CIt&$BUh&ct}XPh^^Y z!aVIQYPn7=I3RS1>)wPkht-_!!Ux_R5MV@vFbe}0gCK)6FofkV@Vc+wyZG$s*YA)+ zxIpK8iLarkFp?e)21W)+1~s6bI$*4{?=|t)&i^gHymUJIyu&Xd6spY}Bf1WA&v(4H z<5N^Kqbtug4Ys-!=R6Po5t%O^d;ahmtL_D9*`GHyiFvyQaSGo$w|feIhu!M%+$%mT z^&hKN?etuCYWHtt52O4B>EhOo&aUpB-oE|`6DLicGIiSY88c_ip3X3*cV4F;1A{dH DDE$fy literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/indescribable.gif b/images/mood/charitycam/mice/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..f7e67e4c1446eb5c66fc12374433b76b3bd1caed GIT binary patch literal 692 zcmZ?wbhEHbRAw+?*vtR{{~7)>F#P|Y92M2l(sJzBF(B{W)}=tvd)M}UK6UT=y=&j! z-}?^~WnfVJ&+X?L671|4;A*62z|05|`pLp-1f+F9@*rawSpEr|@Lavu;`Q0x{}VL& zQZnadtXh}zdS8Lgc@wugEbaGY1OKqjQpQKk>1VhPIygjdUs2ndHP=o1 zGEA9Mt#_DY5z#6#Z#fJ5s#S|U9b1+rw5;B;dfuXqLFQZcc+9qPWamG;TK5&TMnCTFrfl`{Ly-=cQM!x_ssMo$EV&Z(n7z&Xym-lacI%DzAI`p0 zvFmntC~CinH+bG2rV|T0>^aS)7`B*9NMMs;_~aR|qxqt?0xy@wXLf-p8nxzMnlvUX zR+!&Ev5-&eu%f!($(nMLK8*v%gHKO1auvytJgz3gYFVmfzz}li+(K7xomm^Uw6$^| z1tk}QEQ1gOH!vub1w3A6&6T*F`}xU&=QXmWGZU<)tq`j_;1QQ@eZKV7syF|<1QAhy hqE8d1Pn|SA3V+0|1a;5~2VA literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/index.html b/images/mood/charitycam/mice/index.html new file mode 100644 index 0000000..12fb962 --- /dev/null +++ b/images/mood/charitycam/mice/index.html @@ -0,0 +1,73 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angel.gif
angry.gif
artistic.gif
blank.gif
bouncy.gif
cold.gif
curious.gif
determined.gif
devilish.gif
drunk.gif
embarrassed.gif
envious.gif
full.gif
gloomy.gif
happy.gif
high.gif
hot.gif
hungry.gif
indescribable.gif
lethargic.gif
loved.gif
nerdy.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
sore.gif
stressed.gif
surprised.gif
thirsty.gif
thoughtful.gif
worried.gif
diff --git a/images/mood/charitycam/mice/lethargic.gif b/images/mood/charitycam/mice/lethargic.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5fa998e02a6a3483f1d2d237c0c141d0e673ae9 GIT binary patch literal 470 zcmZ?wbhEHbRAw+?*v!oU1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUF8Kq`=c z;(u;G*N|Xm#{gF&Jp*P&pp@cI7FHt$ZU!BYGLW$hEdL5ldamAU@%rrU{|Op>DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th7S3YSm&-$CjlDEvw24*Z8fMw(j$_9hTsEdzwxx>~Q8Z7jW2OGBK$w(}7tv>T zGb~#;ysjK7cg^^_DdK>`obEGap3)WSPdONCY(8eWGu^Xa_`l}gopygF$2zZip_v<2 z9Bbu33R8Xtc?KQ^PGFeI2&}PGjm?_Z^xjJDh3}n;&gTiUly*&#;*ic}bZ4*z01^~5I z6v2Sve{Mh5kYH!W09PYD17=2`xZ+P1P9p{$1|22_HU@bHT?Pi0e-lo6rh2`(cJ}Ar zDD|ob8F}|t2HkkIuR!N~N$&j$JGPpFZ#IDr4k9ephZjveENwB@ZrKCQ-XNxChD7VF zejE1aGR7R_;%NV35q)kEfAov1Gwehjoc_7n@86}@tjP`z(V6AWaS3e&Xe%+_~pd{*de4(|0e*Uip-= zD=2)cyjse+`#-l3!>#b%x%=yxE*m;KJ@MPe$i}hD<59uLBVzolu%{@hO!|zls8UEn`-fT?#ksc8d3K$ z@}90tx(*IyJ&sFn${#;DH`(4-+e1gHe`bSGL6nv&V`In%9@pg|eMJYJ8f|S__kFeu z3&#rsNnwNe7vGvL)>V*s*Rn$`&wjyP&yaF<*1E{X+UBa9re@YkKfjFf*1+t-DRm_g ziFwVHX{n`km2;DrgYyd(<|KOsO$<*AS--|}+B9I0?_p)!HFwLFu${mFZ)P~g5V#^V zVE^$`CoW&k-4+&d^*H*;iD}YW2(Nn;IkM zF(xjV84m(17)98Gd;$(UI9S6VzHB$UE0;^M2%AK~3nwvFop=#rkDI~_2e;~N@o8%? z4Qdi%QS)CK;yLN0D5t?(mTFbj#)f8lU$4LG@b%3oYYE8Com^WSo{+}a zR56XYq_$vA;-bLx{4Sx?xt=R01TFH)65Fr?8su|=r)H;21*P()<0k{Q9NE7Al~!JA#+!M9nVyH0RPe@l#A}Y)eI!w@k3rZsOxeRa97I#pqY*>)W_hP-nSU YVuEadgT^(clDVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2?i<}+9_E)1r!}cDT{|TH)8xsTzp1Fw`2(<m-(~9a!+z`3xnP2Nqj1a z0)4wzHO;cJwJ1I4+!8fcNYHXyTPp`rC^IrJF^DtB0z=t2pu=_b-iSwMP5)12uY0s( z>a*5m509k1%U-L0_Eyol_cibTA6QV}p(EAGa6omYmyxEQ0}CRySb^q9yyc>kc7C25SHj-57oV literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/sad.gif b/images/mood/charitycam/mice/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..8370fc04dcf265c3ed39b394cc1e5a50e3b4c5f2 GIT binary patch literal 1334 zcmZ?wbhEHbRAw+?*v!oU0{{OfM@6-?v>ZEj?B3R;_pa@Ies1sgd)L0dzxV&xf3OM! zq4=NM&ow02*)hP?NY8+o5h$bhlZDfWftx{xi9wh_o$!%MWfxdpd-iWtXZ)Rg{Mqu``hKq?{Sp<6#Vs|{+SxigTeOwhRqB~KBZIpG znyuOd;pcQk1SlHPvUJ77i3E9+j;F2nH*Yg{2zM-Am(wgj4&%)MXAtGEH3i za2G4{oy8&}Zw9h=rp z0tV%_o!h6fZQjCmVB1`VT~iSuci|#1*@7d7sGQDXG%f??vsl8d+U#% z%D;a5AhCdF!UP97WgkT$9u?JsMn^samo?JmNs|m~*!X--UVnW^+gnv(la7yiV#9QM z`OOpO7(AG5n77JpUCztg#M60N;hRi08n?6q<9Sf0IrM)4A3m0U`TAZWfX%~0pkHvA04K{Nt{n>$*d>&%ByvB@ z_BxQmzU;y4(uY%31ymwM=1n#@a9Y0qnwy`*f!+wSP^HjKca}|9x^0S9_^b<(hn!i4 zTevB7Jpu+Ba%y|8qW;GE-TU%SpWjLZFbfH(a0oo`Uu>@+#Gvvu|DbhKkIMq)@+6^+ iRlo$d5uV^oAPH_QFu^rQZ_EKDxShF)-nmE#&KdwzGbynE literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/sick.gif b/images/mood/charitycam/mice/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bef08ce9f0ed29795e35550f58def3e514587c3 GIT binary patch literal 601 zcmZ?wbhEHbRAw+?*v!KK0!|DJEey#~Q7tVk$BrGlw{_{gYkQxc+xz|AweRom{Xg~} ztO!ad{^#~{4GDI33~)8lGhk)}3M>9(VKrjlVbB370U67{@^8XP&((V^UZ36lKS84} zC39ZJs&zT9_Z8@zH!-`z+7yE$1im1}q2!Bt9nApgm z0CU$`hjxpICXtzonAw*uoi}N*RpZj?Wi#h4Ff(VbE?6Es&DL=%Cj&#u{_X6In|xXJ zZd-T6$!ab41@3~2mpFIGE!leI^2KY{Z!EpCpW*h>VtKoh2M!jna0~qp;r5YF|DB~#;ZxLw8R8hEm$@P+U!^v z>`>_%C0Ja+(73hzM!}auUl0485M+6iI*YTPWmB|u{@o*$4flLgT&t%!m^5bcatk7b zB|n2I0~-S?Ff92d7&@qOhq4L26T8FCCWr`bUIr}&E(T_x5^e(z$JUgESu;y{QREeX z^1?uQxd|IpRM*0yBSL^9LubONLj|ywYTpNJYPS>9 pTvjDHKioBG(UyEi17|w{y@mg6DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th741x|)@7WshUa(u5WUE-r?GZ9Dun%A4=rzVqOoT)C~=53wIv zwdpuh(aM#(E)}kIvRci~xstQs4#T}`H>4SFalUwT`{lLk`&Ykw_3>KC{tM-&e=xJL ze*MPE{NzEl`#Cw2ur=R)DnCpXoDeBqcfrZvsi#htOqa)$0%k^6Z&z`{v;!L#EM)1o zPN@9V=y1Szx`<vtCj&DuV7Uu)71Fm((p&m2Ob}UK4l2(j(BQgq$*Q!o;VcMg vUIsZ}^nkSU7H9$knEOU-<1;a23wVJRa5FFgRd59`ZpfPJ6|}p6g~1vC0VT`G literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/sleepy.gif b/images/mood/charitycam/mice/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..63e284cf191b053258434448a9306e273a9e314b GIT binary patch literal 776 zcmV+j1NZz#Nk%w1VIu%E0J94K0001ET3UpJgvQ3k-nFIP*1hM>z4zYM_wU~S#{d8S z{{R30000000000000000A^!_bMO0HmK~P09E-(WD0000X`2-0v01E&t0ssO49{@1` z00jO}$hoS$IO{65{~Rc0-Doc5DW>Yjw%$a+G$u>6n{V$P`Zi!tXz2lOMxrRd3@n?@ zO+d!N*a>h9ynaA;FH-?_2L*isaZ`MQ zd1Qx!gm_R;Xm*8xfM%6_b2nmxcxz+>bbWYgVOtY!Z=n@sZA=o9S89i`tz?0^1-!gX zr?$3IfxM4|zF@*1O@+pl1zNaShlKzK*45X?y2}F1+K<-HP0Pgz=Lv)8>DzI7=IDe6 z>&MXU?*;S#0Q9_vOWwlm6L(;Mfdc;k78uZM-=JPqOkC+j(O|+Bw2<7pfCEqf1X8cK z*aFGpP)9i*L82N-QcsmD6%c^@l`5751W8=smMFV^cENOQ-*~QvK_8I5UMCLvG%eAZ^bGg9M0kE_-a06omD~Ld?>i(<1+m$?#lNCVL?GzXLdwfUWRUDGErA^ zXnhi7W?4j1O&C~UlM7amJr{#WQF5YcV~DE-t*t(fr>94Vt$TH^n6n^0b^x~kxp2I4 zz6!r}0LQqi#CEsP%tlAH3Dya92iMrryw%rq+h+p>)6@mx0082xcsv5nbn1KL1@7+! zU3y&b|M} z|K8TU_ukg`@7~7${{R30A^!_bMO0HmK~P09E-(WD0000X`2+dbO3z2 z5MfFf9sxicb=n~qzJ{rwDHM3Y;ms7mW>?2St)cBEXb1>GVn2WX%6WQwcy<_g273t% z34{WFW_gKwZiZnDmx*CRa(kEzgp~xBmkW$rTZxOGX%~c~i-%})fuoFhh6sp@jI(sP zUxI_Tt#wntr(n5T!-ihQQw!12RI_2ug?G-;qomVb%GexK3*6k^lpfj)4-e(+4Aa)> z2IS@T@C#Jw+Y0>(qyGNk`%2U+FD?YeLopyE8UK001HR z1O+kx001lp02BZj01^NI1WXWsLW{ikR*K8{N0w1wD1pG?i6`oQ4I`~07^j|>NQ+Fc vKN&#w(Oq^d(E|6`A(Kgv1xi(+s8EAS^22(+;IMd1E}PG2*5k6KMgRaiHdFG; literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/stressed.gif b/images/mood/charitycam/mice/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..7ee59a2f2ac1e2c78407db60b6e52a16ff4cf424 GIT binary patch literal 1948 zcmZ?wbhEHbRAw+?*v!KK1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZZ)y2|>^~5I z6v2Sve{Mh5kYH!W09PYD17=2`xZ+P1P9p{$1|22_VFq~y1qKF|e-logY~nRJpZ!&A z!G+3Dj-*+pYqV!^<-E>wcDVCFhjnZ1XRCP)1sXyPk_sOSvIChGJz97`M78~r(kI~) zVtq2_)_Sy_Ye-pkf#tPl|JLUWzq5}&TYg*L?{%bKqGGYQrDj??YiDPRwo%&@6ZQJuSB{*={AX7sI44OzT!Ys%8u{+;YxQ@Dcm9|&H$ zX;KK+$-{e39XWce^VESuCy#_}+B|K_LUv|0*6TL{SeZi>-RV-kVXe^h?%u=K{yA#9 zL=-$3IhN`4{Z>)`@b<#?_kH{8e;POlDli_jbDQO)kkFB(*xW9Y(6K;W@5n|?J?`U@ zGn6jeU@h(zOIxVX-^id}AJCMo>DXX7;qj6)OI}X8<2Tzb@=}U%jgI0TuG zgf&cfFTVV%jsk;Br2;q*yEqwon;Nv0x>On%S$lgJX0lG0q#`W_48>VJiy7wF)Xq;^ zv}nn?<(!<8*D!5fzjWv3&EoS#_sl#vd7NVFJ1~bfAGvD z)$Ql5-vx%)aY;~!t3H_A0<-yf>V7_ks>q7?w9QkI? zV+yf2shyB;YEQh(3Lj5arEbSU#gBU!E^&NZY{4kCyk|<#fhQ-Kn4`QLID^$raOM=u k`XImvPIllxW1wBK8@_?YJQ`@DDUB}Kb2Oz9U#3|D0Cs>k8UO$Q literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/surprised.gif b/images/mood/charitycam/mice/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0adb5f657697ceb3eac8cc39c85b3cc3d24ed61 GIT binary patch literal 640 zcmZ?wbhEHbRAw+?*v!oU1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUF8Kq`=c z;(u;G*N|Xm#{gF&Jp*P&pp@cI7FHt$ZU!BYGLW$hEdL5ldamAU@%rrU{|Op>DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th741x|)@7WshUa(u5WUE-r?GZ9Dun%A0Rnxr6=S!Qk0ejzUVpk?vY)A_{7L~c z8|%04Ts$YrkH_w;{t>b975jviepiRI*dLDE2Mtv>>J(`>1s>vM@eC>|`!f#48XL~P?o9GBIex5?wptTj zHnlJ>ms2%L4D96=L<(JQ1{nr^1`c58Di(M$ELmEn6>7S_>kH#UqiISr3s)Uon09rZ z=8wv|Q~fJh5OKoAAk84izy;K$S8$T`z?83k3#J^syIpfq_{47WIJu~(Inz!pv%aaH zx_ynr@~QJ*9g=+2<09xL$%xGe=Yo@}$EG;n(RASmzK}VcoxwGVCH?3|p@K6GI(qT8 tCwI*~xZ63ukx8^=qvWIt4IjSFU?)jdAM?(fq(yi0#3I*(3o$ZS0|1gq_I3aO literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/thirsty.gif b/images/mood/charitycam/mice/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ecba7be35cecb8e0b585efe5190347f6411d6fd GIT binary patch literal 1421 zcmZ?wbhEHbRAw+?*v!oU1j$iREkN-9|FL7o?rmLq@7mty=k|WTckTQ8d;gF92dO{; zivPL&TtkAL9RpmA^bD98fl`V;SvZXtxEXYq8H5-VfRKUZU%^SuW?qx?*`~Zs8YTCb zx{@;mb-F7PUhj)^U~$#EGb{HgYka?ghC-j?z2|8zPhz%SER6D~?Yg}9gVYHt%Lg%H zF01cs@(jsvyPMZ>EXL=U(8Gqj&u@j8=9ejpS*J>;w6S$`)RZ=<7^HN>bvC*5sj7*w z#RYenc}-VSp2fky5WLjAt8seW?Adc$q?tEwVdUB#ynP49T!YOr`*(Bf;@Y#yJ@npl|OY>Pc@Bg)0c!7U`y%L|=Z)3m9o9xW5@qOT0C>Y(! zz1XVtgizojPcEiSI?NL{Mf0cK;D~&z(lO_(+=B!ug%8297pHyK@eSB4(%KGm_7Dro z9m}u><&rqeu)K3$nwwb^6q*k{shNU<^KZ>np#Tj>dn*QJC25a>Mn^ttt-qcZ0>ah` z^ZjM`rJR(w$=>>jiSFyHd#U8w2^@B-meL5y%S9RnohlZ zV_4i|%H(`qvG?c0CU#S|z>1C`7n~%eOju}s`UnlpKL!s%wWl=5&#h<3=HO9vaDoQs zhr>>eygwTmzqqq(in8W$&5XKs{1#)JqFvBqNN_H1TmlKs-LT+1@$wC0-!euf=c|gn zE6-nIG4&sc!AV}~{0vW>2}f3kK~m>62??(TmS&l6|D@G{K3mYPWz>7tT0SrV~k9SYWCcGLEp(bm{aTdS#dM|YaAl68~ifQ R^NUYdG-JUrXBGwqYXC#sG5P=i literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/thoughtful.gif b/images/mood/charitycam/mice/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..906f30c7ac5d3abf687723166d1dfa922a7012a8 GIT binary patch literal 672 zcmZ?wbhEHbRAw+?*v!KK1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZXJGh$>^~5I z6v2Sve{Mh5kYH!W09PYD17=2`xZ+P1RwD);1|5(Zkg*Ib|0bODT)o%g_1WG36Eyl# zGUsKiT9@;BUxChf6R|st?e}99{xHqs{c$=ouQ}yX#z)QRXS@>x6e3u!sBO)f>!uyd z_|QSE;^38!2Y1P^ooGK~#UXb1WP0X@ID_|PVJSs+@xpOU*@-R@(FJLdLCj^bJ^qti z!(t~yMVq_UJ4~{OXcd{aoRM|as>Pm;ElU$xR+Sg7@mnu%QM9#*)nm4mBP+wvtw$Nw z?6hUtvv=$EjlNsBu5uMzyS~lI>dLhn_gCM!%X*WYf&JO4l3i!ZPn0vWvA%iB%Dm@A z!J|v=_Ny75UR8dWEI6S~wC;qH!PAr4Z8BXNQwo?FoxS-L(+(V5uz;o8)>>jOQ`?{N)rqfSMLqg>G~a`@H}>w#iVptfR^OmuUNO9f!PJ2jfH`e zL6AWPs7)EHtvImf=r8H?%7qrQ;PC*~_MRtzQ4pbzlYtRvnHo@E)dWw?S9>I`@0vCv zIwRI8y)Erl?vz(MKOCP@u(xjuC&S%$ZJT5Iw|}^5w(W`MiXKDp&X6nL9(q^@XI+?j zB5VHH%Wu9UGc|im4V|;Fz-4FP?X`(#-~ZTCcmDnF{|${z%`L5M?d=S?T^&_D68*iC UBq#Drt?r**(=|&{kb%J(08?ffssI20 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/mice/worried.gif b/images/mood/charitycam/mice/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..463f5d603242333515982fae629e61277c2a32c7 GIT binary patch literal 467 zcmZ?wbhEHbRAw+?*v!oU1j$iREiEm_jvc$Vb?Lopd!L`%`~BXv@9*#ZKlUF8Kq`=c z;(u;G*N|Xm#{gF&Jp*P&pp@cI7FHt$ZU!BYGLW$hEdL5ldamAU@%rrU{|Op>DVg&! zR;|lasd@?=rL!80;vapmQyLjQartCzQi0Fc}$ROsj*dG5$u3@ng zqN2@R>m4RpM6`;`Th7S3YSm&-$CjlDEvw24*Z8fMw(j$_9hTsEdzwxx>~Q8Z7jW2OGBK$w(}7tv>T zGb~#;ysjK7cg^^_DdK>`obEGap3)WSPdONCY(8eWGu^Xa_`l}gopygF$2zZip_v<2 w9Bbu33R8Xtc?KQ^PGFcy3aqhIjm?_ZwEn*wd(iQ6o@A+}M@c=d(u@q&0J{gjt^fc4 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/angry.gif b/images/mood/charitycam/stars/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..1cd1ce737be59a77f45c365dfb00c9d16ff6f38c GIT binary patch literal 2154 zcmeHF|5Fop8r~2H2_S4DV32@GNgxQN1ocep6qE2hCkO#Mh}Z&QYMG240nr|@cL4$f zjV)mAL@!6qOWeb@eIG%MciWf(AoEqtS?3Aj~Sny&A$RBoLTD(g`%^W)hK- zsE|a1s36gF5;ak%ltR-fR7as^+9RbABaKRFR6(N}8r9LLg~rlpOh;oz8Z*(jk%4p! z8gwIrX&6k$V8Ot|U^NV8Wr9`Q#NcKIw=#s8A!-=1hM`&++RD&&7SXUsD~oAZOvhqI z7PGUsiN!4}VP=UMmNc_u5G^ceWyw~Sw6mm}r7SFEWvNz{va`Vnw3B5#!0QEG1b9(^ z*a6}J2m(+iK)nFd0n7+6C&1hQ^8hTEK>)4;xDntcfI9*12Dk^{2q4UWr~!lp5LQ6g z0pSFM8xS5qcmaU|(hSHNKw1E41*8X1RzS4^$_^+epzVMTq8rd2Kzjj=gWx`l7qA$I zU>u5Zn2EzN4#zp7h9fK-fpMgTBdr{Xa3sM|tsG_ND1@U>j>0&K;AlHXyE)p!(O!;5 zI2z?>jH3yT@p25pF(}7i922A@$Ko7Ia4h-HAOGL}#|0EzWLZH~WuBqDASWxE&kMFG z{vIkShen`G9>jwbPzD4EUqE>xS@BrF2P>ks*ZQ+#XM5npTzBz!V7^O~ku$CCzf8E2 z_clxptv`eY)uqwe^qe(Qbmo>G=Tys5*O1`Ihf%v6`}z&L4@suAzOw_n8#*J}swdKt zRGP9(-(vsvdmVf_Ftg+8StZ3)QqtrT@-}JRI;`cjR+I{g;6LV)&7jruz%D=m5`O6!3ybe5vAIH46 zx9wIeRPRt%-gxn-PVs5``MAcV<1u1KWm@@t+&a^s3Jd!#MMxXJv95D}Ufn=GjHEO+kt1H{wm%6K=b5UYnHT1re8dW4atQM}nnfz<5;4NkP zw*&Kumg3Z4+%Zw@Yco?T$sq+I_(a=Q^G5_%=@f5|gQpv?csb9kmxVU*RXo1wf; z(YCEJeMQ4HSB$1-)IU>S*u5>>Ec>hPq48{*;h1uBV|mFLMdB^Zv%;mjU25A$GJVf` zgVMD4A?LN0%Z9W67Gqwd`TEbz`T^Cc)GuwehrX3hDtQHQE}KK3`ejbjofLkLNSu;6 zR;M7A6}uaY-MFwt-&?>7*;w?XH=o|R|4OxP$AU{Nw7!tlZnQHQ+mX6lxQm!sM>G{o@nO|*)svIjH@$df4{CNKD(+Sr?W1j!% z9s-H@`4?JL;b;8*+t=k5LAwj`?s?JCo_shmJ|kW2MvD0ha=GS-Z#`N56;kHy?B$)a z2>f6ArMr+vxoRT4=2@{a`-F|SMq3YE`F80Y5SuACI5eelji zU+RVX6%UNDO}<%$eo3Fd^uMr@5qNvtZEjn*rvpx@UNsfJ<^>&e^wEr zUs8N8HjItW#-}zb2CfER>2zwmCbl!g-ZN+X6~J*m*FDWxp_g#zV$D%MZ@bvNZmeoL2mtVU9UJ< KTds$oSN{RiM`U~e literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/artistic.gif b/images/mood/charitycam/stars/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..e180a47be0c2e3b2f72eee3d363c5dab8c7822e0 GIT binary patch literal 2381 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 OK8)(Dc!Uj>H)<#@Q!QBav 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/charitycam-star1.gif b/images/mood/charitycam/stars/charitycam-star1.gif new file mode 100644 index 0000000000000000000000000000000000000000..739a88a46e41a5980f070201f6221b83e18f1d72 GIT binary patch literal 2386 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 Y!5jMaybGV^9yliWYFBtHjYQi0Pl%ZaH~;_u literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/cold.gif b/images/mood/charitycam/stars/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..11ad8bc4815393f726188a872b051ba0ebb1b4d3 GIT binary patch literal 1186 zcmZ?wbhEHbRA$g+IKlt|Ym*taW^=b4 zYrT%G4YFK&?%4PLk5=nF-RAxCbnN@R+24;he_y)v^R4pVPkR4u-u(aaj{gsL{eQpr z|NC?QzaRVm|3A=h#sA!Xt|7tBjsdPldIrplAfcZuoLoR!hk=2EL5V>HNd04AZ_6j zM*aX+rH0H8O>EpkY6+=YrMck@@iW_MI~99aRWyakDjvL!}dViah286zfZgP-y@z{M+kDXV-!Tz13V#AXI zE0}xIVi#F;@Rt!9%CY)@7UPQuh6|ZQIkK7$zU~j8|o5)sjeqgJr#` z4;13W9bSYtKKEq{X5cn3V65lMdJtX9oaC;^u^VVG;Z7y52}}C8!bBTGg>-JJIGu3R ze3Iq9PV68Pqrrg#jJb{lX+3OgmMSxX+!izhZL^#(#bp_<=F+KbJswF#6?GyGX`!AC zB93x9QWO~S!%7?Gcd4--oZ9XtB^V%RleN;tK`=Yatd!Sy1QbVcEfs~!*(tU8V|GaN@)Z{{8Z46U&pe)jWyvyQyZ_W*`1>S3z@=J z*2~(6N{BSIY?8K6xi+EkZ@ifV%4@{ zxYaJ_cw$Ps>O6IoK4Ae3#%MkV28Bri$21rlEyN;1S;AyBr%uxAGl}b2E?61G!p(Ak zfth^+E8|RWzAus!V(lawnY>P_EesIs6giNY=az7w`SI1T=N`(tG#P{RbyaT8jh8!+ xzL2HYLv>+~n@9*tmz!2#01Ly61Iy-=?b7rp;d=6N#k_k{1XeC(0+v7w)&MDp&YS=M literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/confused.gif b/images/mood/charitycam/stars/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fd7baf0a6e3653205b7f5d25d7d0d990958ca30 GIT binary patch literal 1545 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/devious.gif b/images/mood/charitycam/stars/devious.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6c7fe26539687e67f509c10a22deff542a5bb27 GIT binary patch literal 1655 zcmZ?wbhEHbRA$g+*vtR{{{o78~F(@*qF)*?8&UP3D=q%?8}lYJUFv>nQ}O}m^k}; zyuz9p%XV=0-lhX?WSInEkH)k!=dhaPyEdxq= z<{Vkge`NPUu6_EBJu8`3?^ttj^*Wx!^mDZfvKcR3y1!=OO}m+Qys96qS^bE2!P6Nl zUcBVtJ$`h@i3R&U`K)|-&+x=`hj?|izfWu@rRZOgDyY7u(_#L2j!?UxvDY4@CO0Ow zLhd)2JsO-HT>T2luO^gi^gYDI!m}Y}^Q5IJT{2lW?_?hB=b5WBpY!eK7f*Yf6{j1l zWIV~B(x?24b#0(}TBw!!OpVrC2Q@ku=2f}W9t+L!bL-zQ<89Zgv$y(YUSX1O*uE}y zmwmLyj?>@Yd2-kOW$HkR1SSSXU?k`aUynF?Vh0i`K zuS`r{a9-BXjOWkUYL%C98u^#Lt%+2~XR}h}SIwGJ;mXp>QpF>7=e9I6!bm|~s@&JxUX2T7J-9L*8~pCzmT DF}A`w literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/dirty.gif b/images/mood/charitycam/stars/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..aef105aeadf7f540a48d043f91e532103177e1cb GIT binary patch literal 2748 zcmeIy`%{xw8o=>47swluyaXX7+}wmqxMM(q#3BPp0HJ^ZAtIs%(yp+uNE}!}w3`qR z2%>-iX~CLeK(Is;6x0gc5NJSaAy7+2SQ-!obupo>21{2q*iJ|Pft~40&zw2W%=zie zna_Nqq9cRp=`MgT@GY>uhycjr@#H+9I~(k4_SZCnnpXUX92{vSj>w6(JKQvK&yn>V zqmd`hNQn34#2GnxLhd;sr_ad!XO#YPO8P=KeWsN$)6JOaGo3LD-H|g&&YbeVQcuXj zK+;cri3=mC`mc5^k8odpwM&2P;Hu`p>IiRngunFN!KLYAYZC`wP8Az3o;0?$8YSJU zQss}gPZ-Bftlqr1roF6Rki68@{rADS)u+m}3C-GE_u7JHO+RFMJb4WhACa_^8P1Lf z@S`GN>sK$4=m6970RR}_40r26w3rZjuwvosuvqZN3jOI)- zdEf+*>2)V~jDk$#me=<<*mODK>>x?{(NFLx2(x1->Fg`s`RLTtGag1$1=_1#;Y_E-NTV1ct zx%}k6=$X=$yt%S;f*+^Tw-4YxX6lS zhNjBSmyu$2EQlqTI(^Kb;1|;#S$l20(-16$gB$wz#>LtY)l=Ip@Aytq3&Mi1`N$@t zk{6}7r^UZIYM>Tu1+CpUT4@3^5^(tU8KWWhyauxz<1VI-kt5J;fhs_R^&e&rK-*Rn zj+XShVFM^m9E$&mi4tBuj{lZCs!9U85o0CqR&UgBy z+zH#!|D8hxz4TrQ+Vm^qfOS4FogJi8H9@eS+Uqe*=nHkcFN>t=BlN%<$v|+LN0NnW ztidi5DN&VRf~U2uXZ&1yQY;eVAE$uciZEsqV_SWR#aeg-!z@ZzibuP-21zVj^MR5U zN}v}5EULB{0~}=K_ds%HSU&)T;Dt!*BzCwt9{KTIesO~U4w_XwyjYVFboRndkmN&c zW_i_?!qB~S0zpS;^x<%@G7`vEoK8fQz=xchk}~hSnD3NY3u$%I?YE+*eA;6AF{N)|53lE?_2)DTi=H=L%xX)VM6Ei8#>4B3K9T= zW4+Qc@#+1gSeH;6kk5^%#BSObQlWgHuHN9}<)}@VA1p&89+?Ic-;cq#qCb{oDarj3 ziv6H0>$JlVonhgO1EV$OqR+X?5@tzDC?>A-*){Fn1<5|gNpgbj70**}oFOJe(;E7Bd)DIBpodPU#@>idAq!;7 zQYIAKOihciE!5g$JX$ET|D3L;e6*h!yK65B`UJ(yU85N@AZia6j@UyBQX!qfj7_*; z>IEhc+w~BhJ??ompBtdQA zqg5>=aa*M&qV!rej6*^P0%*6K$okh1+bH=ah*ji*Z_HP+f*7DZn<_w9vPk{NbV5=M z3|VtB|7?q!6kx#epWA45Q?4|%L-y>ZLG1nbhGD`XOZLv>O+Nqzd(+$>J#^Z!Uqjb^ zQdksOh3ABy!||Cz^S45BhS~C;zr@-&WxVIeh9N5fdX53qosT*N(Ec_E0z3`cQt8gY zzm^8ed4&B}jC| zQNvO0?K+dRiVKKC^vs9qzxH>`6Zsq4sr#Yfzni2vSgcDsYHn|mCP3h})a-7@`hF(>1{II$L;p~{rvGfcfU1j1)SuP2p|?1 zS`EyH;tK*msZ zIGPBKcAf(wI3S7xN^n5Q4im!-@!X~aw<+0e%5rz}+}%>Qqs(K=@z{zycDc8#%nM1q zrbcf!&uh)`TK9Rajb2-g*Dm$io4k%Pue-_XG5H|KXVv;_MLwI<=aBmx?LLRq=Wh48 zO+L5P=dt;GzQ3l=ZO3J2=H>FaqRd2AJOVaGms6u1&gpo6o3|ufJmD&6tmpt5z z%rncl)XaLscFf4&6Vb0+c*JIxvV@<3LY5(Z$V~WBzZM==YF4)PWP^(zBkv#6YBQZ4wCl*waoZNCA zoX!IaZ4tEr#HW6J;y*-Vjd}&X6tGmScqQXwR*Z@)*bd4Q3vOxYbeM$PXtww-ZxZjq zMAr$_Qno%w)pBhS@TRK#YqNR*jhtlx+4SL|b2N=vjj5GPxxh{B>4;qnQnb1vU4R`% zlMWj?LGt0C%Nvo$l%0lsnziX>1ePh|A_-y<%&$@8Z_4$2*KqrU%I^g)rDc;#5nr%wxb5U-gtNR}l&u_gJ^v<;lzBPh z!$`yUI?wkv`LDLp^IusZ10-S6U zoFhd9mYX9;Ym7MUYhKUS^85?DgL@Zjt5{HyD?Z6!IW zX#b_uM6!7uA+G*zfnRW+7=iL9v3PY8niBrWKx&S`u#xYFdKik4ktaEVvqV;oGX7xO z6gD_k&}hWH-*akll4QIN|JGV>Pt58oq?Fg7U$$(xzIE{0rcf5W><~fax zxXL>Q<M(;-g6XQl~k?3PSRTb(bu2!%bdOeN136u z`HkdXeQ)ItCQ)H?`ee(h{?-R1&FdSxyzNk=kybUQ4~~oOm-Q@&?AP%z%XPIhTwJMf zM|qes9*$daOJuncsZC#kIX|S~A-`Ci57dbrd*HawG#WZ4Vo>MWfc#wu$1s~^y9+j) z)#YPXR$dB$QFUmS{-R=lTdl1JcxYA3h^k|!K068q3#1#(et5Bx>$mV;mJ-dh7F45A z3wJUl82o?^OI_cwV_lx&$PlVkO@a z2+jy&&LMNoN{r5>5Z)M!=R&3DtugP`bMM}S_e!<*bFKHrTK{{!|CHYUwch{6_y69E z|L4a4@Av=z{{R30A^!_bMO0HmK~P09E-(WD0000X`2+<#0000i00000BLFP`00{m7 z0SFvOu%N+%2oow?$grWqhY%x5oJg^v#fuURU`%MB9ccVWu%iW$BnKLhAmQXl zk_IfabeVGHh6ycEGJL5p=FOQ3coyvFai@d{8*WC3Ad;xljuC_+G!Oyl01g{wMi>ym zf>)U`qc)@}VSrf<941&WE1)GymKLN=jUWN7T@FVpWYAk7s|B%RWtzQecktc}H{*__ zy4HhZ!UG(8AY9?E+>(sxMh-9;?dHxLGAQPl*#c4y9ys4k?cuNm1ec+9Wr>qR1=e>v zsNM^BXw1KFC2Y_e`7zoLk_U*s48Y{q38(iC?oillhYq8sGWN<+Z-(#J(Uo2wuavn! z*|a6-4R06eb-y}$8gS4xtM?2OuqI6keM0YrP|1W-QXHJsUt%;l)DcTJZ7|pXI0a`J zL@_Z4omp%9Nf~U48YHc|+0l)?Z6eg#c4aEfrsfU(E#DQ#2|#n^!3UXyb-K z!4zVSK6ce(O)o#i1A~{ zkr6MbtN>ww$b~Nvdc<%6B!vVq2R3v_@*@VC5L)gWx|2dqf(0N{!0;gh29`ku1cg8W zBuEHHbt?TJKtP5JAG-p0`t)OktXeB*So>AO&$n-{qBU4mtcDD0y9$7N0c*sh5CjbT zkawT}w@>{lY&f-oV1b7Bp<~EUo25pQ z1sHW`Ue1;~S+afS0w`UUW`^P)xtsi6v7yhUdiR<&I~}IdrL=XmpH&pdrrvs04JaE0 z4;1KNPzNTppKK5|(7*%Y1$Ci%$t4KE0Yrt!VS!McL{fcI$>tJD{!s-1eJt|kB8)L& V_TqsfHMC-lF!97AOgshz06U9okXZl# literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/energetic.gif b/images/mood/charitycam/stars/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..498d960063ee22eea10748cfec1fc1d014a56d76 GIT binary patch literal 1316 zcmZ?wbhEHbRA$g+xN64$2LA;ZIGmiE)+RG-&F0uU$MD!3j$>@ZQ?wds{W{ZMD3&)#>?Kr{{Zv-Y+eFzt-^mRv@Z= zzt`#g-t70sg5IA?et)j`{kfj^*RtPVD}H~k<^A(1-{;KvK4Sf z@5frcpPTaiTK0bdum4-u{@?5L|5(ufbIJd&75~4s_5Zz=|M#Z+zjy5a^EvBP&+X?L671|4;A*62z|05~Rs6}qDZ*gKpu@<(!Jx>X!oa}skD-=B#v?$X zv57-iOUGlu!$a)?(m@s+86_7V6dc%>#(mO%gUF%E4B9=~W&LF)h zofnk(WK_~>EF6jxoZI<1dkhkp)H!$!>$P%kEL3-767rgHV{ z!+u$_922nyrlVbADt0P)5f7Ui*pt**Jt$V~#j9?l#MPwnzQniIiW7 zKfb=vPO9Pat=^j{C|70nhk=Q?SI9gj#Ln=hb^l50DFXMs0umXRI21cRgr^!F3Ai1X zAu8Gwv6{6!fkS)AcBd4xHwD)s&7Z0SwTf3XEG#rTAfU+Oa#z8Lca>{MLX+Nu1STGf zLkfp@e@ta?a_f`~IZ$bSrzJU2<%$CnC%f5EK}LCl6lH? z-IGt)C01N;WVd=*GGjVRL_pA_uaOFjj64bgjx0h?el{>W3SDTdWpBFB$mlJ4OMR9? z`W5;k5D8D`y9k)WHZ$9onO*V+5v-S6NfCX1!XuX4|V*tA#dfvpTS53*U#VwL8vL MWv}C4Wnr)e0NQOEApigX literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/enthralled.gif b/images/mood/charitycam/stars/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..57614bf4c0909d880aa77570d8790b484e4fab80 GIT binary patch literal 1995 zcmaLXdsLEn8o==vP;M%LpfTbdydo1an4mMA7nIDhBC}#L8z{A#wKADGX*=*DiiT;W z<}|cHlM{{NVrjM2oCB|lP8XLh5Cl!zf%ZMvx1`nI>SAp=tfQ9NYr@_Xq=Z% zzBZd?dbKl-Qm3uVd9!ZrQQ5DK`rq%HXU1z^kDvPe$JVz4wztzguH!@AdaMy;tWOe% zMV$B9D8&5gS2rBT^~WFpBoG2b0|537fWZ2%Fzc<5J04h3WHuy0IJz*S=Y=7uf*iX! z&uG`%s)8|vo~idnfNDxgy&GE}25X{MT`tMz{IC*YrLc`rv*BwfjDp#pKh6j6W?Dlqf@d!E;d{OsKGuQOE{+lQUo}9TWjB$S z0$%H2dG#H>q^;(0C_0;D%oGw4{q2+f{Oq2ccSl8@)JQI{Z$b)bym_48ej=3=$*I9S zbB;rXs-!GMz8S;XI}TI>9Q!TJ$Y_Uq3yYpc6^wRz(PHf5Fa&EBwzrX9{Y z?Ch%93Os+=tuNx=eqr6js*r}@;)ix*dBDF|p5)3Ovt>!Q<-h~n2g4~_%I_(8eRyI_ zyaI)(C#oP0(2vr{s~Vy7a4)+89aIabyev<}lIm?aSD{a7brSe6FPYot#mg>&tG)E~ zeh92X-?3p$iy5wGG(5}M9jcR_IT2B-hu1M)#KBlnGhcya=q7T-v^28-bI=hb)CPMg z5V-JWJ*1{~t`N9;#Ml)mf<&P>iOLH`iVqY@!OiFTI>jO-sS;9?r!wlm1a=n}bo1TZ zU^x|P@Eh1i&o=`t!~pL0gXyfUjPqH3#d)nL-0;*Td%~B-RY=jEy>09K3Rsr`H@9~& zAzYZ4|G^|4RzO$}3ZN$%l2j|n-@XGf7X_Dv)!{j-DeF*vC1RxK(lJX0B5{gX2Qi=LdjHA4Hb0Qyld4uh@j75T z>OzPJ{BwLHZVb=lr9wIDLc?I(v%%UNT=b1(WF}op6r5aB0SfD-U$c3jS(_3Yd3sQZkmOt=ZTe!c0#=eW54;73Lw&4DOt|G)O;eS{ ziWD{xCcym(carY|G>}g^^MNR1vgMfLVc2=@os4fxJ>g9;sUC6dd4j}c9#bw>(&={O zz)BV{P`Jm`_WhwFV(|YIiU=x^Xp--i98EZq%nDM=XoB1{K4iTG1<@}i3(h`U4bc+`pbV*A+rTV$=;hl~&>4c^eg8^S zH~uTkx#MXUd>U~9iOrQYHFZscwE@?T7l28aYIAt9RHL^dF$B8!xhTYtopu^P|F1&5 zv%WH1<|AHS32myfdEgH2Q>j12V$yWrL_{}*pNnf&P;G>(E$iR-Sa*y=& z%Ny8GX9aEPHsg%kQU2OLwi6Jd#f@!N?8spGC!QQ*MAGMPpRzkJn;RLhnlYsKq>x4F z4$3?Its15F`luVRHsW^86M5i1+ZP%pI6MRp7!sj^Gge^FlwHWr$Ut%RR!o>hnnd7F zn^6+K7Q0RqUatru5Y-1%8{&1t+flm>$qFdGRGoB!nf;mH?yR#680TcQ!?-Y`g^c_3 zC|l^Z3(s{G>c)4uYZnSt_%I66#>hYj$28`LpgHMcE7F5ItU&n&*Ng)+4LbrKK+W$n ze(7BatH}f0yI+&G6v>crpIsb#g!PXhGFK54&f3(^vusf(nID(k1FjPome!u|;utY! V?|~B+?a_%uDT75Zwav#V@t>u_H-Z2F literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/envious.gif b/images/mood/charitycam/stars/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6fe51af47b83e0e22f6ca1923cb4e2cd921e374 GIT binary patch literal 1622 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 Z*lZ1L1*z9)s-Js8?HyQwVEvtJ{|7p6(nbIP literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/high.gif b/images/mood/charitycam/stars/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..21c40d0ba3b8d544bac8ccd9108cf65d8994e77d GIT binary patch literal 882 zcmV-&1C9JgNk%w1VIu%70M!5h000000RIpG2tqUR2 z5YDX#&aENNtxDFdQr?sp-lam`tr*^|G2X3X-nA*-wK?9kLg%eQ=e<(zgy-+2bMLJ& z@3k@SwR`WqLhrq6@5WN^&SUS+bMMZK@78PY)^qRPgzx8+_ne&foUQkzd-t_D_qCMw z#(Ve1g!j&r_ttCw080P0t^d73|He}P&SU@9bN|-0|K5cE-jx5|#{cJ>|L?W`@6P}K z{{R30A^!_bMO0HmK~P09E-(WD0000X`2+DQNsiuplLNPw`g z;Q|B<7(lda$sudO0u^lR`1;jEjR_i5sOaFr1_=@&+`i>d;)aeMb8oz0fub=A7ba|k zupqePj1mGe_uz5kMrHviQm}AQ0z_qj9V>wNtXT(Z(4%WysN7M)3J@Y*_i)Wx28#|D z1lRU(p+<`ruXXVL{Ck3ftQ|L4pb?^ki5D_b_z2+Ru=4FbSpGC;dKEepGw(B0$p zh!1W%f(U`3h6x-mLZkSs{P1TUCcvjqZ5V_Qf(Rol7Mct)D7PD3P>ImiLca1|`9uKE-rZq$+h3>Oe-K_|Q_QrfMXd2nM-oVoV7I1OOrV1O+kx001lk z0096O02lxO2w?yL2oy+QpuvL(4H77rupxkj1Q|L!2$7)0i3258l!%dIM2s0JdYs5` z;mD2=Pm+9CP$kNXAVbQGX|W|ug%5Mytf_OSO_vUT?yOnSXG@?#VGdo&v}scTP@xKp I3N;`AJDrkyJ^%m! literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/hot.gif b/images/mood/charitycam/stars/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5d20bb34fb1b93483144dd0cca45c84ca6f8789 GIT binary patch literal 2099 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 Wc53Ks{=(I2X1)K7hFk#vNq++_YaW*X literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/indescribable.gif b/images/mood/charitycam/stars/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..2531cdd099698e5a99a4b13dd36ddbcf458a1ebe GIT binary patch literal 2312 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 Wtxf|c + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
awake.gif
bitchy.gif
blank.gif
charitycam-star1.gif
cold.gif
confused.gif
crazy.gif
determined.gif
devious.gif
dirty.gif
drunk.gif
embarrassed.gif
energetic.gif
enthralled.gif
envious.gif
flirt.gif
gloomy.gif
happy.gif
high.gif
hot.gif
hungry.gif
indescribable.gif
lazy.gif
nerdy.gif
okay.gif
peaceful.gif
pessimistic.gif
sad.gif
scared.gif
sick.gif
silly.gif
sore.gif
stressed.gif
surprised.gif
thirsty.gif
thoughtful.gif
tired.gif
working.gif
diff --git a/images/mood/charitycam/stars/lazy.gif b/images/mood/charitycam/stars/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..6847a902b2aff214817b7c59fa134fff66298250 GIT binary patch literal 1816 zcmZvadrVV#7ROs?OBpXxDMC9G{B{PzsmF)Vn~sm0>40bTdN@o6QwAv)9RHy<0Oof9zyWKKUlU z^T3S&f)23$qC^n+&s=F{l`W zDlkZeL2VeM!{7=GR$;IjgN>M5jk#MecN^x`VMrT>_)?GgmU{>B3Ox>5ajOis*>I== zhg3N1Lyf~A4qI^;!rd*nyA4Nt=yAk|BOs30a0J4AvtAHKZ8!?!7=+{a`$PY~ioy34 zNlHsZ0=XnDmE%wJ^~C%@3QQwhBe01CA|Zyr_WjU1!Y-9{S{~ieNu?iVpEh~sx@m!& zDGhBz(iy_6Z&+IMNOVl*D&z4)?{Xr*yFMSc))z@BX_gC?XTMwi^kCd&*W38~VEQ4N zYf_p%CNP9N+_)rM`1E09@qJMvsb@u3V{5(CmZ0eI&EYF}1{L5=E3n6K{Tm*{i?#?a-quj(s}8 zQV5Z2;Ln9N)+)$!At8pus2LSpsPA32lY4`YdlaIBJxT~j{>D(PS89oi5lF)E#b0GB zE%y~n#g?6(v7se}6mU8yA8LBGC6(D#TuAzSV$@X;-1??7C~xL1G+4Xh5rv3fx;G5migo$>EKYQ{>=M-Y);a<#)a7Ku&{Q65gblSO{xS4tMR(c5=v{M=Q)s z|G0Z^7Q%no(6R9Bc~*hI0hAg&VtNYo&Vh2S)3WpY_lcg4kU}1p0>ss7nR&_Jv>nKL z{YLGdcub@9r=Q>x$p`q_uX|%AXg9{wPuTs+ldqCea#>8zJUz`IC&^MD$?C);O|%H$ z&Kme-|GfS$8j+#j5>rDgb+^lZ5hNy%^DQR+>66b~oQ71k_RkA}$7;2+telyqrRe^K zz2)Sw@x2vx=84&_IF9yaXU5`*mX}AvLuvnGFqIHXNcg$I;vWs(r71NY<@_i9NogA! zmd7GJkeO!UUQ`VX6f#;#Dg7OhIlz-|O}E$0kw(^$T-VgD^iEXb$!N>Re|S=KBQPSZ zzIotQL}t!tMv8VXzMwmbSv0vx>JC0C&l~5+txsfr)qNK$S0<%hQ75;Zp5_rY3I4oTRS?!Vh->%n)*ZA1j@b&#q|gA`n}5oWuWkvSRqt zsq5n9<~mBxXUst3zYEUuBiF5`;(D7CD2tt4itR9Ez^|L$i^~iAvQF_|ar++q<;rT$ zaM62j+wZu!a|~ubG)M7GrhcIhP!WH*h2o<)wBVjZY=sWL%m_+N^2T zcw#zZc3g6D>^-jk2bl#+u?*$xE+z8x3i-}{#^k|RO~lXSWkct}8!NdK*-PoXtN2HG zpT312RyjRgtdp%1lCaCy40H`|XkHbR@`5|YYMxr7+&ce;-$f5LUb^^s%1etQtg_WZ z2|wRpr-W6!HaUQj*Y``yBwS8s;Dz=zN7%X12aeE@3@2a0EXwGgQ_3c~ih=ae9rZKm zHItZLq$fJ4%zC#%_E8f@v_Jdp=BzY`wKYo$mh%N9T753#411pNH{gs#epVKhB{SsZ z@^*DVd}#lAzB%f()xI@70YjH#oo9?e=}^l=r8i{vQkae6alex#I7aGu~e-{(htJ`|T8(j0_wMiVP|Y3>^O$7&&A- z0umaUIE1xyBo;h8)Gi=xX2G#h=`e$+M8K8|Lk2c35tE`f9*WFtoJ#I?UsgCew{ftU zt?TJXJlw`3sv$6;^5Vl&v&@VGG6Xg+ytr7XLW$>sLvzD&X*;(HEr%u+F8QTesW%)L z+WBNzN(z1*U}9ku)5$pSp-}rUhvdGpAEy!zx9k>H$SLT2*cja;vC?j?b_7G*!g^k# zr3wd{lQ$;HRvXwHWNPE6m$qA4u+XsSWQc9evOibWx-beFaNKxMxvBlcV)X^33JIE* zIYe1fE*#ipnsPtmZ`__)yPmw--7CM}&#tn$buF)>*MSR{*5w>b;LfgC7x1X$T*cwN z&2K+QtvSmrEME10hU1?fys{72&(4TQV&N87yU=QI(1zvSp4e$Kl6XBP+-E6sG-zo0 zzjcdPtt@XqP-!Kv0b{%*hpS_d3~RupJl&hA&ym|l|K^M#B(yHhFXRi$fn7< zeo%}SvN4#*%x!SMf!V>X;6MWdOG0Rvv{u2DNp4Fu99iXaXH2TnG*ggeWfizNacWT3 z&ZVJ-D@7(w4DPxa%aF)7<-n|*Z9CK4?HC_Co0GS!Ltt(xlYjt9gfapnRC_c+j}D0l powak4f7ZDx&t?}K(|kUs#BR!gxfN;(>GNvt?M$D~!OFs54FJ4}rIP>v literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/okay.gif b/images/mood/charitycam/stars/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd871ddd62d18d6adb451c9ed6828215b51cad98 GIT binary patch literal 1900 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/sad.gif b/images/mood/charitycam/stars/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..672fad03dab1f34a766d7acdfe87a3d5099288f8 GIT binary patch literal 2445 zcmeIzT~yL%9Ki8Ei1^14LD4WwK}8GAfvKT8p2Lf8b*w3Aso9PuIp5k)%M3jeP!V6l z4s&MauzW#;vW`@<+(-496IS?48MQ(+f9X6Y>7$U%Ht%)gak9}5bv&DqA(#q6cB^}K)?r}0RZ?0 zC%3A2M_fhtw2%`kck#~{i|16F6g~*d*{Z%zjD9jVx&6(Ua3uSw-1#%I6l}?o zVaUPs<846|kYKg{#I445YBWgjeVvkqWrDW!^w>Ivg?IL40JrpX%r;(1?r#hO5ZdjR zoJ^`%qI}hoQpUvvWU!D<@&jYu;^1i^63bBUHiF@8cq!JkFh_xyxexd@*3_|i7}|^d z>2daAb~lD`FA<5QU0@h%s471rI&#yHS4*_)7m4G_jB~d{Yejn{8)<^Jlx8PC{6!Qt zfq_6d&!>tVet$V`MI=1S>vJ$m0I8!dbAA%N`0OmZm9WoW?Lc5m&7;b$4&9V_5k<4T z9i^IMJy97XgSxvla-pUP9VYJAwnws$<56`}^!_8CugdQ`_X9nV{XrrKfC>ctJCUIG ziIBIkz*9a(WC$s7DEE}15l;y%eoT^%H7dw)^ryL_(HN{FKUi5e@vwFHFiCIbCGv5_(5$T%HG12u9jlr)B&lD@DcJhPX5v*rcDtQMiJ(tWnc4agE>hyMbx7nB~B(9FV{r z1AkOeYrQF0G~cz?J7^v&{_NaSK(e`88QP_TJOY`7BOVLrJ=F&6WsgPi6l z%9UwFv~)(|cy%*|E2`bMm$Q*J!FXivN}OOL2?+)R%9XvuZniHQ^r~D~J$U=OGST34 z8(na(swS-G97pu$I)%$Iy2sezZwZ6FZHP-&u2L}y6U)tRH!&xNyns;@;!yu+eMHt;qVx~BQd z^vQm=0h49{AcQ#%X#39$^VJt_eq`k%EB|0c!&RK1D{8z4&(v#b5V!LSfYY&&2Hgcq Uq(OWBdHZ7DsnPm(AJM0O0ewX2t^fc4 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/scared.gif b/images/mood/charitycam/stars/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..01fec586381dd7117d44e6b7d8863418a1821194 GIT binary patch literal 1049 zcmZ?wbhEHbRA$g+IKlt|Ym*rS7&x|Oa~zw)ac(WgxupX4rbswBIqjWecy6uYy|pq7 z4F8X<4LY~h>()xIr<=`x@3eisH|YDZpqG17-(N2HeJTCxhVJhd+TP!5`Tc0p|Fb*( zzu)@*{ki}D{{szI{Lk&@8WQa67~pE8XTZz|68g!)$quA-m>4)16d6<)7&!hhFmlLv z1SB*xaR_VaNGy1Gs9iu>&w^v4(qRT+k$^23h7GM;lIBGqJ1!YQT`uz?{_ z)1O0>rQ_)V#b(xxOnL!30v4`iT_3NV^Ws9|8#W&CPp|f#6kT_aL-NA4yBiqS#_>4+ zHEU6DY-m5uWF=Df#_>Sgp4wEiUIoQ9>}*q2t=Z<9t#4V{ZRzi@=iz4dUB$7lmp({% zmc$`^EA2qR&95;h_kFhOxEXMWg+pFj;oNHpqr1HFL_Fpia12;WHwA=kl3;`F-^8~+wHuhnO_3KM0^V7#IrqJ79B0@A;8EYI3wdx zhz66u0p^p9E+OH3CL0day|*o3=wkGlI@ME1rQymXmtz?RLj+wsf?PSI)Eya3gHA?t z3omsM>d{ZtT*wkswNlcDMRCEiSvjjTAG+lpyQwyn;KJ@+x`=JXpA~fv;J*T42M$b#bko${rtHH6Bbk(PKM%t2Se18mBN% z{);z?dNJ3^H7z=3N*rR@Drpds#w%`=znec}aodNDO^LgEWRLsWNiw(2;SG#WT`B!D z{KV;lX%+JfHnOZf_I6vCoP2oRjroy=#j0{~dmiv6&Nf@y8MK#)L*!LlMg2Urvv(wx zhzo`b1-J{d-}-q39FYxCI++2$h+L8SFjY2pT6A7KFd{=md<+^J1n;)Zj)FvFhsLAe z>W^O?3KdwVPG#oRDUfFouqklpVYCSaMP$I0i7t*;#6$gEFC@5lX|>H_VLg%|*r@3@ sMaWZUUy7>xMcbWAs|*BN4$RD0R=KQMdgaSyv%HkPsLf$uVPUWa09_-YHvj+t literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/sick.gif b/images/mood/charitycam/stars/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce74e0963b953a91173f43983b0b645c9cda3d33 GIT binary patch literal 3220 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/silly.gif b/images/mood/charitycam/stars/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..23ba4cb6ca407af7586480c9e22af0a2e02d752b GIT binary patch literal 1326 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 CUq*-k literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/stressed.gif b/images/mood/charitycam/stars/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8a72356e9ea5ba07b81c7738557401c78ccee6e GIT binary patch literal 1427 zcmZ|NSx}Q_7zN-jD}Oc&OG5&oBoL4-l+_TxP7(w`0og=ksX;`sDh5yo)Y_~-B(-2u ziUpm>CNuhvp-P2L?LeX-T1-<55i6wZTBQTkNMx!~oL=;z({ppqyjSnVvpG32np@-p z*kBaA3tSAy0O~ye8CoF|3>iAfrcSB}rdnXCRZX?RYny3>nTE~)103)ea0LRv&DJn$ zr@#aUSl|FF9A<&J)4gmf%$>a&XYCgl;7rTa6f0b;ve*}UqWio^s$A;BK)7taQRYF=qc2+z;Js~_K6oq(qT0!IRYaI*#5->p^ z0MJ{2fapnD4PWL2SaC*e(V(2*6?nuLD!pCrgb{R%iG27fH?DVUba;D`g5lGpqE2>f zR?<*L*Oli!$&&D}>v7eY^AJ9^I+NHSy^YfdYALDZQogwZt2Ai_ck3mWNIi*#8L}FJ z%X+BP)4#Gy4}8nU2c`sQ2vsuE~X|~;VjMty29Z~xDtGXe=(6RBMv>(qK=3lUpS~_`(=mM+@ui=%$fnF`A>u=#J$7-fXe7I>igX=5LY31(!r!Hwt7Eq=4eSly z9*V$mEkcyziG&)IdO}3SNQ;ASE4H&ZJuw+Y3ZzF_wjzk>QUb>;8Yg_vXBH4n zu{rap0L?%WLLe}BfedMp63zvY4r0XhI;XMJ3_ut<#Na_p6=;H32Q}MM5eGwe;j8iH zK@8%^03S)p7D_NK{^XI1M{9V3j7`3+WGT90^z?gOja@<}snL^;ow-L65U zd+h!4yEZJz%`c5S79;XYtwn4Z?~~{i5E(msH!4;dJP2r||lx z5In|inNk2mOvPlCs;xrxBRl7HVF6`R{hbD{2X%<{NEIz2TMZ5F6pEdKE0)as{8}Qd zYwJ%!e%s4oBCG7llc{)z&xec{V_&PZ*8(U!)~6}o*NP!8^gy3VAfGr#Nqj3$>X|;i z{QfBBr16Kinp(&FeNs@~hOVbYjqJN2vBo@~^RH?cP4TY#O8N(OA2dGcN1Y{Q2a>x=As+Tkz+HM4|~&({Z@M8jxb(!?Ptpl61!AOtzxRRI%3Df z^0Z_4G~*#@%@)`f@y=G9MJQ`HImMXE3mIOLenx*Y&&PE)zM?9#@AG8%q>_>>fKpHD zNRceNju3L)tlM?(9PO7vZ|$TMkZm{#2%>k-;MS`Ea$C?uf&hoqHjHDDa~g2}67Vb_^Bm|bGY><_4V56-zIi!N5{tTBhhrv%K7a-LWA@`|(n;}Q&cx0p ztlyq!0Rmo8OCY~GE$^ET6>i9!jE!!(tkDnM9&8ROWS!l~Ir=Ox&qwLu3=jwq`!~%a BOacG^ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/surprised.gif b/images/mood/charitycam/stars/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..348c287abb66c1af5ea0a309c2c9306eefe8b900 GIT binary patch literal 1299 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 REVZmGNHbKKcLv literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/thoughtful.gif b/images/mood/charitycam/stars/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c8bc1d5f42d540d179f1b136d4091de6215442b GIT binary patch literal 1380 zcmYk5e@qi+7{{-aYpaM{1Jo)lwxU8E>cC9tQ0xziP*Ex1gpMp=nGnhbSf{umD-qUZAU;*lZFb^xlI4mY$ zG3rsEumXeS7_7iy1p&)(SV_PM1RD_rfhb8>NqG_|B!Nbhv{#A2dKAtkJQ|#hh=xG) zgjYkrCKA?=2#cQdYDll1LNt_@)!8(np}j162GLU<3*|Lah?VwONi>^8jU;BI&}<4d zQdl;H8EG_|MvXLt&g(4bg z%t_-7G%JV}CV-Q{U>SwGa#@vUfatfWS8ag0}!iAW83b57-6a>k7uYJBA!kjNX-g>*~l!VMt+S zp8I#yF8!eNO?tNpS{#!R6bFq6gwA#Q^!bUPAoFbeqw7UISJnFC+ZX+#P(HtVIaX_1 zEim@P9$9FK6&Ix#iy>S-z-OGs~q{8idbs8@N#P4=#qBflsH{w3Dp)viKqcJMJ(VU+^9-ad%P;jc zgzM7h)}(^7{i#>VyXS_(cNEBv3w4ZjS1S-F?p0}xY#@0J6@(%{TywMe@4jO)s>YGcM{Z;k)#ZKxr@6|6A znF28QUFU(oQUGK(Acz1s03@q)t2wp6yu7K+t#WWU?~FkJ4~PV!SYytA#z2emLDtw^ zq&{9N`q0(c=1X;mHkM6~-MTi~D$_PgGJ39$pNq?Bo*pVGj&861q}IumwMtw0{uxf? z%<0iBV8zc1)wbgE_5ZIE!j3{DAYHLbK~-9P^!Db}s{YoD_SlV$1>-%QJM9v~mxuBmtle$revwkV;3qX5 zQCos`bwZ|rrjU!8Q+njvhh2F;ls%n5x*mOBIMgiN`Qu-CDMyzMzM3Fq(a8mKvjZ0Y ksqij-FvhXPR!D)0n>Ql`%l^juf`pd4R(B|F1Aydz0R>WdjsO4v literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/tired.gif b/images/mood/charitycam/stars/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b093b093390d778524602e3c8a8da854cd0a2aa GIT binary patch literal 1919 zcmY+^e^Am1769b<5oaG4aifRMt9S*GOjIM)11SuI=a1?IGeq>n|<@<6ew(2$qmi1#sSPel| zL##~~VKYS74Y3wonpu}+9Yp3gs{ygWjV$W+hDbAtjuO;un#ua%vla| zmdzryS*mUGWw!Zhhec{PH`wRP9P`x*g~Hz3Ywy+B4H}0*XS1km)@Hl8*>2G|tj!Lq z#xZZOt!Nx8y$+kfVKqB!7Kg*Jc|6PEoSvM$FEK%s92w3-gCAG_!r&t}dngE?02UAo z0MG{j9HB3u6yr+BEjYhT&omt;y9!jr>SvS3J%Z9yJ((Ba4)^%q(e9}g6I~o4HSa91 z@V+vH)pHDA>EDjsRuaxppPz(!1xL=rbU&9_w88tPdm0N&O&47IgO`rJz!Ioza!Sk1 zst^PfShb`-fK2>&wK%tGgYaft#n@517!%>AY$kdLwtj}P{qHK8*UmOF zr3rh&Eietpi3OcVzVXnDA<)z!^N1?abGs#x0LoW{$$Kirkr-Fdx9dP9wu5pyS4gLv zsv=$=qy1U-y%sQY~feDr$1B1y81r(>O-7sKd5~8H8oPr zZ7dLW(zi}XKlu7$HHSJ5B51A1MU<%S<1f4NpebfQ{)DuRmPZ9$ zeXyS`Z$<%mjz=D0TEM_vfCqGs%&fZHu3?L^SjYUgIg0@3S zmr#wcyV6IVXClVZ#R^H{V_qVj6DNLL;`COgB&BCfHQ__Giiy_Aqe(`nz`|4#3;v)- zGQ8cBn=rY3_xgIIT}IH!vyO+#fxM0uViWtt($8{o#30%=YQu>3;E26I2KR=f2{$mf zni+n1a=f0cfhTmGf2VV)>`wkw=m~B3FVBq_Qt0kDFdNnZV zUKTp+Rl{E&p7v@OK>p%eCW3zh2;2k|@+%;Sks@L?HlYr3%NzBQL=@QvCFTzMB|$h! z)^}WrUpv+lcX;Wg8t$O7;SSEdZn)hoD61$x=F~ELdRvipLC+kxb0+BUBAifwL4D)I z5{}gQ?dt0H=e*5M+v0~CfbelW-O{^V-hskGwf-mMIEkI!*Q?-{VB7__>;Kq|m~a$7 zWJX;1JgI#&HBf6DzpyKx!581iTW>PExcf%}0Vzgw2hh{7ZfrzXD?GM}XW)o}YY8Zd zu+B0qeJ7g@ir&-uUNHf=U2Pco+y^aeBPmL%7t}~{=i;sSe`7PjkR-fkiUy9jAXL$J zV&8M8mAh&`8B6?7442kmUa!tcZcjZm8C=L;vbwmltUE5=^IzQ9SRB)@_-r%gp33pj zh??+`9PHzor>g;f-N)6>b>}eX#V8lvTeBzW^E(D~^CxG8Pq57VJX5Rh&st@N{Vc#p z9jQ@>iQAXN3b6XoCIWfqGeybvEs8#(U=dVMToR1k+HahI3gThd$(^?Wqg~@F5>P2~7yx8Elrg`; zWe*NzG?DH%%H>(wA2R$Bj-JN6*)jyEqx*${I2TOm<-N+CqT&oHzm(E{dNg%yZzM*$ zrv5f8YdJrVpW^xF4b9W&P-xYNkLL4@5z z6!1SpdTl~u7GPzHo*-G;o(L(ngXmlpO)H&Q?)2uSs9^Y^)O?Yiu{6~<(%h`gxL&jb%)L;0#@4Ri zs4Pgr;=RM=FL}?GAK*XREfn`Bez)Km6m^Wu^1~3_1JgBa2dhv7MqK^FJDKR#6L-Ul zr^T6mXbFIc(?Z6ZcS($x7+l?J6qZP1LoyW)k;{Cq?mCw~++SwK(S$v1Ptl{V=$mUr z{W()BEx2^!pJ9TSHbT<2v?=&Jro)q85PH%lUpb>=cYQc`my~$xm2Z5(17J4lMH|(p z?(tB9;&o%OCplbzFi|1w2(ZwcyY#CfCCMMRa7i*yQ4Wtd0UYsbnVN_J3SLIdeHd%v>J| z4>=Y8NIifLfw*EqT55%7kqBGZmg7V^Zdi z!xj6#>?@qeMma^sj$Fdnh6jyj!iKR$=LM-W2`*v(FHD@K^Z*S!OX3)Z2F?i9PI}=B T*S@_tT1dX)q(hN6UF`S|f1diJ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/stars/working.gif b/images/mood/charitycam/stars/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..66b5bbc576376ca0716cfa7aa6f28fc7142fa481 GIT binary patch literal 1095 zcmZ?wbhEHbRA$g+I3mXY2LA;ZIGmiET3TAxCNmtH!*OhF(7B}o=hk{%TdR0)ip0IO zhWFNbz2EBeey`K}b5ZZl6~Dh${Jpy6`_?Jnj}?Evmi_%+%lCUz{xdNAKNj@=-rE1q z_x}I>9AdQMe{Mh5kYH!W09PYD17=2`sNzo+P9p|61|3EQ4hBUARR#u*e+;%9G9Cd5 zjZGZFS~?L69v*5JkT$a5*r;@vNlGMOOUA|qRt^D^qBk6hO|0xn?si`)9y+nGbC|8` z$zWt|$_@zvn-^YO%vYhLbKpT!!*U5bs|u|Ljm#YK_GSU6CNwti z%2;qbc(BE>m6J&;WXA_VrtmgCm4>GbWz1|`6`DRfG!GuS)+MphZmD*JLmX!wyHLcL z9UC7XXR(r47I5&r8xw<3_PsMRi=UkIPfdDv$Flk5Wd^%okJ%0k2QM!7Ek5V)%Q$=9 z2J_2o3JeGG&QCH7378eV{n_2Urot6fi57<*ovi))YkVQ6~X~J|#MoyUp4NN>!W*lH*7d&yl@s#Y-q%OfjQome5doBVV+6*V&ftzWWusPw1Gi?JlUu-WOHa#7@xn!tuBE17wjRAM5|N)^4|QqO5t!?5t+agJ3V&FbD% z{Y>Ez-C@Skx$EiO8%>AB_6fu;bh)DX`BxYJ>4T*=fKe$Faem+4-``m*Sk7upW@z~R z5>V2RvrhOeAdm7pU5Ea^NF*wSLBmsfvGbbCo|NXRGs#-)-!eL_fE@aPO8gxE}f-Q zwla~eEJu?Z`P^MZJFqsYILodsLVmPml~Y&&@WV|Jr}JuM!9m)<`wAvLc&!lJoGZ} zj3MPfDSG$~;^cZ_cs_qjl`@>mA1D`GsXzxSr`=e`zflq_j zsuS-Ujj;*kS`&5F{mJ=D>)y9G1JYh{hg+}viValf%`^)9_t``T3<^;efqAYD4) zD?7%<>gTKv1-GdTQ>`aH<7tgXMH_c|O!;svH) zSJZ>-y69-J*B)mn5Bf98FIiGbwc&!=mkt&eW_s6%(hE-upV;o;(b1{0>d{w!{V8eg z8=i?*Ci^2@Cl_uQ$nu^aI$>RRj{c)#B7EdT{tnsHPgT`ic+Woi=5Z|^t!;_Dpo%}a zH6ku-s#`XXMROvBoA$?)Y=6YLKhpAc5I_hmkjx;D`PKHCh|85B|Mn5ygocw~Bq3z3 z+ntn?X(w2=1iKL?VAV1o9wQLH4pZkA|xt z=>IH{r!3R{W4XV>O#xMyeC2?*L~TP8ayH0@p87;)$8`1*)3d8%RW`9|xI<@;%arH6 z`Df>#b57~!F4@t8mp`6YK5A}R-H-2`U-+0Wn|>P;q%Q9&uo{EIG4l(R@K`@l5~hhJ*!I9*#o73lU=F z`jrcZemsY8q=yqDwkyB968CJ;K*5l@zqB!}^Zvs671i}Ia}D1RU-g}{qt5u@{=&%% zb)uO&H|+f5?7Gd7@rxooL+1OpMDvOt7fkhKjtP?XF%#~Tv*baEr(t7b-#NqG!FQ)_ z|IKTysp{>DSI2v_p$LXLZMmDEBmq>ct;KlPeKs`JtXRcKx+*QQEj9-zHlGZ! za9}WN&=lqO6pGD2S2;xL8i0!wzM)-lsS}Xnfpyef6FZA|jZRDLYIh`jt@A@DN`fWN z?{Jqmu=Y@iLrhwH5KCc>Et!j6v~seiZCk_PC!0vHSZ)+%XYy zySB2zVw>EQ&1jG&G{zT%=my@352@E#0yp)^kagUO#c%M^fNjdK*1~KP)jqU*QiH{2 z=}8viIi=qPp9$Vzi`IB4OyYX@8H^KzAE|GZula$@7;yKoc{+ukeR^rK73T5v0FKoG znMM+jYj9CkH|@o;U@kv?Y69a{7AlC;2qMWS!)3 zcX~$EJKRRvkFW{yK8a^nFBPvGL1_G@bVZi~#4r_x9 zia2P%IrU`+1?#AEnJzDe<5A-#sG}&2fJ&{F6kT?)=oUmP(5h_u(GUF#_CCMo-gEAU zd(QKm-%U%`u2AGg0dc@oC*TQz2Z2B=;K~JDsZ=VLOBD*aUMkj0rE0mtECrwhHl$Ff z6>0-0(CZZ-s3=VHgUoEm%!SNi$gF@NF$~GoYQ0|n+XX?;U;s@9gUO^fnGCSm06}UP zHki$3$Yg>bGXz1frx*|uNWu`NRL**iRn8{a+bItibxSefuT|y zm12k-LlihJCr~MY%P~}qAqETuaZHV4dJHw;h#ALC1g<83Lr>tKtwwK0^dxQ~2{lRR zNdhDZgN*=fqz3~@c>0iyG}&z)%r+Zr_h5%mH-x*)*dR=}%%lq%#1zwqeBU)Jm>@%b zXS!ySOASjArmUe25ClRJo{SSDM%oaY9U)25 zZuelr2T|J~MvP*%QNlh-Qg(#0qvJM=qEO0(QWWlTVJ;U=Q3T~8Da!70*#_Nqx7+3# zwNq2}**oa$cdb)Xoi4X)(B&F*yWDQd?a8B~<8JrVAT>JbemhRh&U(J~|02Y*err;* z)~2X3Qsb7$yl9?Bi)R=!3jlKfF%S&^?DxQ@-;AYXG&!qS&mXo|O&BASILyhd zx^~^%TAyGoPH+QGC5jSU9VU5*c4gT_pY!~=!_u|BK~(L!ku@n+Vo4r9d!*o2Vrt&; z(>{~NMm%AsZ>#C6Ea{15jfwAGojaUbT~^eakvRG6)KTJm;K;rGcjqPVoX8)#6cp`h zE0{Spl(Ort8cVp47YoL{hy*O5k8Ead8F2M8|2O?x<*hl%Kz=%_cvtR7PYNQ?Y)pgd ztBd^Z(3570@&~?*U;5ENLCDAAJ-*93Oe3!gZhw*XLs!3W>5b5;Lpfh0JzD;d5~O8O5s51v}H=a;GH zON=tBrNsGny1Q=S$A5j@I9lbmMAp}rac+9b&DC;Vx{=rY3pR6Q7e%zsS-}(Ce$0s{ z!~4hm^KQ*ast~Jb1FI7>`ywPGPhh_sP)U#Mn(PTkdecO~_kwvEe<6r~G{%*LZpr*b z)|$mh?=4P-+xqUzOq^XR$QcsETw=Gpl46GIiKsfRovaVSxWxu>`GQtt;MMH z7UB*Si-%_3K;#!rWT!l3j#&5lE{^Cvu;@@zTcvk&@q{XPqq6ykfs2NO$`DqTacUHYcn5OMuPw&i{^Y`JkP0c=w zS{#!HqO^Ad%le0YTHXwZqBg~E$T1K7{4G1TE>rn|^no7fMITE4-$k18wt#snSu-*` z`;1FdRW=sOKhFy|g$e^6wFsV{ZcHqHmUI8!O{~QlVY(5sV}C9MhAj1seH!<#9!dME zZ+gqy=D5NW6(?fWZ9BW_?5f$fKd#L*HHI&1a3yXWJACKswZBgAF7H1)H)%uX=GZ=V zepY+M^o!#wH$3SH&t4iLoy_BA1D4>Q+Lt|?V+7z=!WTz6^S%wOo(8O`VU|BvA6Xp0 zYmh~aN_>}H1(t^u7hEQmc@6ir>yB=OtEZivP0Gsq=j3 zjlan?-FLf70DL?FRwsZ7C`H&Yt#AoMnCnn{Bc;Rg_**dM$bw( ztkS)VVWlW4zeCTOcV=&MDC1G4h^KN4?`8PUyUs8B&{-HLU4hgoB+=_>Sv6v2c{o7V zd2=};3zHF&t>MOhzoLFFQ`3(GZ;_p5vstB0PM?T;u2ZlsBjMCB^S^(`)_9%6c*Hx{ zqGHEpZPU#^iSDfx2_pbn$S0O|gu~~HRQ?Idu^}e5zLp(DmRzCv#I%;@^$7E}zeG4e ze9xYgug+33muKCkhwr%16g&Uqh59sM!IpMLP}dD^RUZ4hvy9*z{0S@Kc9$%D5uWvw z6{^eFP{@gItww@!kJaCdc(R7BUs!lXrR9%(eGqF)Kh{hMk7*=6(yuHX>GR(`N}Id6 zwP2Hjzhw(uAJbOxlwBqPLt6?HG~2C=gp7rjOGD{N{r~h%w|1x;WBK7Jv1Z~yPbiZC Gto$E~D|71r literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/awake.gif b/images/mood/charitycam/suns/awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..24e5686e8c82dd92c1c9a162b736662d8d70ef7b GIT binary patch literal 3736 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/blank.gif b/images/mood/charitycam/suns/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b857461c289fb7a4d4c05567a345bb152d9598a GIT binary patch literal 1439 zcmb8tSx^%P00!XQO|scsuz^4TLrefU#R;dNfV&}LL<`}tU_d9xT^Slhns_H11!=$_ zs9+IO5kZ9-Em~{GP7(#7A`Ohtfw4Afhod@@j#z64*y>}aPyJv1ng8j3_%>}$h>Fhf z210>x;6nelisrB6H=nB>_w-XxFRL4 zq!BkVh+9R(1iEPTB?i<)n~oUP5tBW{{B2@p;Qe_a!ARPeo)(YGHioVdk-!hrJ2EZw zeXj-pIv@mA0syiMfPfK~8O)XNHlspoH?X)&%1Duv-A}KBGkO$zQfvv_$n>I@{(1_X z6DQicF9mweSP`Q()FMEqqhqj#{IM45z&Rl)-FA&7-jTmHnJ+P?RU~UM)yrFR9W{@5 z>-YX<+~ZWu;5hSQD2mYC!#!EFDFc`bGq^#PxNX7{#S=He3T|o4Tv+1j=PN<88oM3) zLKN1_S=Rx}eSYL%L{W$LXis?FJ?XIODgFNHxI?o7c|2Un`>3sbPTYU2K15QBEUBN1 zM?IsIR{bcM2JmAPrav;sOtvu2dSo$5Qu7$a^bsN2XZ5bv&mDJtn7uIT;NriGX&TS3 zOW+CHHYC4_?NiM>WnUOHnf(5qnc84fT_yG}G8kxq=aH$#iFVa;iV}bz)YjzitNZK@ z`r@$xTutQ(uz2Zq%H1NK+V)HBk3uO3QOPzNo)J8a(|L!`T%AwDAXpdVl~=jbU!l~} zJZgQPQE@o>8SENk6>Rj)w>4vwB2ixb$~L1JW*{<6vh$-t8NkinoKN@7wqqa-)q9Jl z-O2F^Zl2x@`?g?RO%DDTMt1JmZ!Lz$MR)1kaDkc3^;xGSJA}(HkeMwoH?dmLS!Q6K zwG%oXXbb2%8)^bNa>uQ5*ulrv2~x-+6Clfi(95Ue4oBdSkuTW+LOx18bpGZf%JS7& zWi+>~G61~h(X8oeg6i~43*D!S{GfE!`P`UCI7VhgUovGLCdtl(Fec2rQ;;?HScFyEaXs`URXaW=p{)8H9-ctL$8cT)o|GU>ch zyQ_k95!foPFFtA5?jb5LDz90B(p2mX%C;2Ff&mcYm2KO1vycj%y3s^Lp@x zx3p1<|70J!bku+T%xm=7soDTIzJUdS@X=pu_-#FB#9_Uoe@eL0`}2)bMIEy~L5jCKs67VgL(yM~u%KJWCa3 z5;Zk172ZNi*TAtq{AH%CC^2dP%0jsIAWTu>%}Ey(7K$TB4}f7_3ukeWy&Q+#OB5Bf zQm;7;M3#u~R%&&Dj1|_S#7RzDm1cvp)P|8L9FvLSW-0Zex)egFUf literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/cold.gif b/images/mood/charitycam/suns/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..448d86f2fbca8b313fcc582ce020af991efe1ec1 GIT binary patch literal 1289 zcmZ?wbhEHbRAw+@xT?wk1Oj%+oIXXth1I+fo&1?I_)FFcrv6tf`p?-nmA`c>_tNc3 zEA|NWoaUJJMR>&}o>f0Ar(IX;_@lb^pV*~KLKnZQoc*Qw`MX!wHm9xUe0KjS-f`dW z=wJWezj9Ch@4fuL_y6zZH~(*c`2YBe|3Cn;kE%fNKewN2NU*bGfUA+70W%}eaK)c2 zoLmg53_1)9Tnvf~@(c_d{}{Zdd~gU@aIl$8(Pu`(hXw7eY^El2I2aEdY2lLOI&Q6;hRLSqw?yZ4u#RmQ7A_~a}KE^H7ubain^XO-;f#HNUiVq#VX2@Kjt zCo1n@x*G z*C5E8#KEiL5mC{&@x}4NSZ}ri3e91wg#|rcDC{hJeqx_&aKeFuI_K`Ltv$?k=H^FM zF75!~1Dy*Fw_dAWAD4EG(qD;G4fiAr`XNO&2#;C?fQ=Z#=yUWX3{ z8riwp6chMu4#>B&cV1}-Wa9k5z|we={Q%1pO$VUib5kcU@Gi-aPne;paA2a29Lr+I zTup|g2})f*k{GSU7C1~|3l$S=4VQeN(oqsvnZl^A*LlI0sW)`V3?_jG&-&bVMLHz9 zZ*7&F`j_{^y?KV)JR4>Te_ir;BKz5=&mCDh*k3rx&TI={(f`!BVs=Sp=LI${6P9Py te`8ISFSYNRzLarpTIiugOdU~&x|b=jBs%~T1w2hKji!mwGyzEy)&OH#^Mn8Z literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/confused.gif b/images/mood/charitycam/suns/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2745af245c82c0eceb1291066577d80d661fcc1 GIT binary patch literal 2819 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/drunk.gif b/images/mood/charitycam/suns/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..2c85e018a44074d76b849138a6687025462ae346 GIT binary patch literal 1918 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 Mn7-Pm!?3b{1AV*1zW@LL literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/envious.gif b/images/mood/charitycam/suns/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..c27921dbb7ea5bbc0833c19f28e3d4d83f4547b9 GIT binary patch literal 2668 zcmeIzX;f1O76o@X#*>-Szjs&EE%O2jBv_7Qq+j^RXu#+ldX1$ z-~32+<`-cHA|0;ayjKwykJ`O&Wgusq$6IBK<^D*GY+4(OH2WjX;mD<}$Q4P~j2SWv zE$G-!KG}6G`Xe{9-z@q*Mr3liT!pArNLMSO`yTlTsVTjIsO}+c$Y3cl+A@czkT+Lv zArrH2ZvK7mzZDB11^Y&X3wT0bx798f)KZf*k0rVRxq#EsX#f_m0sz28;L|%-fv~Q- z0N){<$T!q6*N|~XQ~h@j&`XH4IJi-Fgn5Kc+0))gcEH()$}fA!J*d)R^iK+oY;gS2Vo+7PZINnvtYb}x{(8=b zS5FJ>^#@T^A72FwA9`={XcL)&KT0zy{fG{Xy;w;RVXXYvL$MdRA zQr!AnxaH3@ zyyVi*abxdNrVq5SB?p5BAJmD};6y}3uAu((SziqkOF8yIEn%5*T5g{6QNh9=%xmpd4W%-RNj3jI~_Gzyw} zCvL+t+XMoxzU@A*ZFv&60*~UnszT$izZa(4{NKW~DMFKPh_7^rBquC|NdcGOwf>qt zp>-9?7^gJv=;S`oi_x4>nm-dr_u2=uFZOP_Q&dQwe%NPkNZNdaE*f^vkt&8vybp{u zh2J^~{~>5PsVq?UtjJ;Ih7A9)(+v^T5k%9z^Y{V2L+tSr7jN%%qC15T_wT?^o1=^w zd8=)~x(pg19s!~~qm3#q;xFt?`WiPtTMt;DV>w;9^Qb?vuE?cvPoG#B?HqU1yV^yh z2Zp$}J)a0xsI2+-cCKVxm{fKIG;^Nz1&*}9yi& zdBWrN1+%RJZ81#Ec3lkXIJ!Wddp6aYW!5cP?;|8vgVvC3Mi zRhETR$Q8IauN&R9f@p7*n<5>-63{7suO+_=cc+0)<$r|$v;VJz3z+zo+?zKrx)I6ti@_72LQC_xp_v9!Zr#Q`3 zDyAf-4|tC%Q$n}UrFFcltHlt#bsc;|rCbi%Ys6s+WkYVwg9hMO!adt+0#V+`TmSZU z!@Wmv90t&uTdm<1|CS> z0>pbh;451woW+`tb2#}eHb@$hPq+eP*wMl!hj-x?$&Ma-aL}-3;;yN^ z-zuTa=7JacN;`iEH-FV|iG6T|z3aqVEctTKN`lKNjsnkiYG}QZko_~!R=x6cOYH|N zNG2~n)xN&YdHeG6_g;h$QTN`%_GiET{A{gP;WR{diH5j#HJ_$Z4|ns?30B=%B*Sx^ zP^gif#M0sDllvaMGUFZseed(}X9MCNA2v<1%Tv-iGif+@I~TQwnjqH5X+B+DN?O_8 z2RxKemykTRV>kx4HX)jt;3Mq zis>cr!y8F}Nd;5O|DrIb8k5pPe6E!A1T+LYZ;#BYLECceRJq&xQ^Hbei=im9)pB)B z`f`|^PSgt7wM6Im=a@KlU(X4eg zf6I^9Jl_`%#h}1v_j+^i##V_`jRVNd;aIu!qMWSnVfgoFp*~0exBHe)&d4#wgqJ!& z6(L6~WF}T*VJHcBst+Y?Tn?Z;u-$?setc3SA$o(|Kly3=7eB&(@T2>0{Pb3F{)3+l qjWu8~uaTSdWIv$bbP`*5_?J3J?VgbdwGfzqmd6d8)^brO!0T6j;ZJV> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/examinate.gif b/images/mood/charitycam/suns/examinate.gif new file mode 100644 index 0000000000000000000000000000000000000000..e15e9a72a464d166124d2694a57ee2bc67328bee GIT binary patch literal 2975 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 Y33e}Aj0|7#&4urz3#eUvAPD&V8}pd7-2eap literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/full.gif b/images/mood/charitycam/suns/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..c72fa8bcabf3f90adcb2080f89bf025f9371a6d9 GIT binary patch literal 1881 zcmd7Q`&-h70>|+$a`8JZ?u#OVl1QGsr((>s@i;(4=i^Z<^3t)w(!A9sL+32EgY{La zH6ORxwDRm&XQm~1*=pX(0itFur)5r^CCp5xcx#(@VQ}2#*?G=?u=kIjA3x74@^wK- zXsSC91U!Ei*ec5t$Or|c-az4QFpCGK^PqeI2moq2&`YI`v4F3=yk>W~&+OVYw`b2f zpFb@SSPmUpOiVPVr(5&$H_Dh`V<-qmgC!zjRWw+U3|1Yb+=wIGJ^! zb#%mxl!wkJ?3ccaH( zIX!+%8yN6-@L>1YnD^vlh;;-q4|+^Z1sIKcOeVHk9o6428X1Wh8A(v9#pC0dmhOUu z1%bhE@aLajH=7eSH#0Xj3fkH}uB)p%bH-XxVXdvT-o9eACkZzI9AFHFb7x!QadENJy41e9TC=&?qS0u+`|caH+G-l{0B8X=f1>h) z)tWPy{AGR7vL2%2(b%l0=3=|^m;z%`<%f!w8GBd)(mkYYDVtJgT#iS&moZL^>nVjn zaqqhlBu4QWA(#EW&g;_>qLdaAaTLpw3r)O;zjROEYHnM6JE)^$4~t!mZ# z(ksVCRN?SvgzdU1yQbKDI0akXP}UK4dRB##_Y#P1+62}mPhTMH>?RMdoytApm`ku5 zTgkiO$aszB{`^rz^K+dS{^l)Wd$)Gm?zcl4I@*@99{@o&D~D>)r4BJC{bWztB}YaB zdd35}Ow-KMUWb2zABDql9?Vi?u0d-$HsJ36jMHog#gm&-Ey5XtP4GFR2MfI33ZrrM zvScCsaOdJCk?aoz>ZKQOrWbv?>4iVG6?}>&LxY3y3FwtctUo7Y5@w^4v}iJ@p5!Lp zp61~oo|hhWXpkF9z?$i<6CR^wHt^1v$ZHpT$_F*?kuJi#eKy<5c(~yewA?9w*iel1 z$>gXJVdn-9(nWmlbm!^9p>AsCC^6mERxAe2gP|E1LPSg|-*G?GjKTWk5xX7Vtm5(= zGbq4mQ0xlxoQ0%#^tKfB)kym{>NK9jq}g~6TI_K#4`c_YAxZowrh+VSThWmt%DGt% zZw{{LT%(|74Thmq2>%@&lFBE~M=UdMl8*5abF^66RWv<i64amy0Wd?H5#xLg=I~D|i4cvlj zz7UcmyV^)Gug(X2l{)L&h)mu7jMI5|;_9+i%u+T{#3HE32G4?3Ts*t1u?wdlmQV^f zDH_y^Ft<-Qc6@mt1sC8~(&@nFtn^Xpl}o+YQ#8rfj*n!*`x|?KlHS8j{a<`T2zApq zISBQ)9yx>z0uKq2oIF%;xLj=`a@Q>&mtvcCetQsyS{!?6kOuvqe!DIG?tfwZlkKjB zD1(F|$F^b=#&_C>&zI3ZAO;NJfnx5(V0KGV>r{^&AX^*$yXvxJ?s4O;|LNzeE*IoH zZQB18C8rD3J<*wLO&D-iE8If)YiaiGZP`x#DZaLW-}CH9F4rwxVuK5SH?mX8J%^sa z7!9eSNz6SRfHTfM{Yv5UzO_sVow+n7CiW)j5ym|4CNqcH|sba}h&|5OHmta%Vq;U9!zlDDufV zP~os64{(dv!R5jvX(rLuKJIutpPCT7g4q^lEJ6{Tpmsd=*O8U!5;V9SJP9GOZu%c;t4lV1K!PC< zZy)JbtjaIv=IU!z0%10|%+LYo!_Rzr8t$yN=TO@2tn)Mr4$mR95EVphHK53Ok& zW!{Z2dHomtCBJF?hX(a|n4F8DR?Q`cZ;|z*^!xh?8n(#pA|&DLba^clsSiMbe){IPPs5hyQ2)9t Qdn^1}PnEh4fdF3pFL!w{ZU6uP literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/gloomy.gif b/images/mood/charitycam/suns/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a09ce76fc29a3a8c2e05e919a9a184c753ec11e GIT binary patch literal 3052 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 ct6t6-PCi90pR)f_q?zhY ztOx#@^flb!dNW(87D?Vmut5YrJ6S#^Rd`nTl`R0JD0|p&Mgn7(tVF6Q7sdf)Vxr9Q5v zW6%5f;13JCG}XnunifrWv1a(f$B(6-KVSPg+o92DzMl>N<{GVFPIws0hsSYoq{ATJ zSBr3r3$Pw=0014p954d_^fw?!P50p`TJw?K*=lf3Ath)djwW!+^H2vd`o0UbbT$T0 zTeGB&D@S$Usmv6mM;p7;1gkec<^y4~WFC(3B<{F~izkUE6_|NNVKr_Kc0mS1=^S^h z@v3pYSHO`_DRw-s`RU>+k4B<{pbjo2nlXhV|IxF0)GP{=Tl-YqXI9{@$Dii8%xD83 z`Dx1+2pzb)4|iOZ=zQTB5!lB?rtB3=b`dQM*{^+EC6e7*pMiCYyM=xAtDPFaR@8H} z1MSzwlqDBYcl|Ecgpw)?ErNk#Aa&P1wGgGv6^$d+vX|7jt27l7-b!SKDH` zQs3rVP}Od6UM5`Ept<2@eBS=|;|*n1??#s(a0qhdy6$LB_TsfJ^2r<&T&3cz9b+)X z#Bh}Y1o}`AC`w!L+$XHIJu)BXi>fWu2^E_&MNRrXa4J`6zUx4)tto=wz%%FAaby(? z7@Ls`Iz});_qoRREB7D~DKAP10fWO(*yI`u<{FAH5@t)ysw}};(Unl#x-3}|F~?09 z%b%)jkYI)kt(jhnw8)*TBu@r3y{LL!jUJZUSHPeM_|K?l{6R%z zb6oCR9FDAwc#yzNZO8tgLWRH`!s4$scfuyPWIK9W;}w=4H+Q9YE^554mQ!V@_ijj# zI(e|hbrm&we4ZIBUzOQ2Ssq@fled~tdM9pSy7TPXQ_O~t`~%uX4$&7B`$$$H7q_*Z zLEKJp7(Qs#0+rt;Sp0blhycYa>GnZ&F`^zoRZj;cMHpjbZ>!>Q2c>~{@?RdQ_y<+S z_u%EZ69;u1X;;zCo8OO18gRc5#<$yZ^c@529J7aA-gfJ{cN(7f10lsaSxy>**K}Pd^wg?O$Oh?gq98+GVIp3Cg z`WPej7KdLR9-{!EaDx8?56L-py3#u~OH>9=j(i!iUZt$90|gCfv`s2UkH>)kcn>9Ll*7#3$RAm9X$KnUv)_N&wZcO!b%Ke zfe+$R*WO6#C}L&Y1hQvl#_zwq>T&6|qZXliwYuhE-IomV^QOV`?=F2^1%bF{f+)K8 z9r4JJel$&`dWADhK07<|_|$S5464{m2#dKzi_Bbpf1@o8YSCXQq*SY*c^Igy4HLFn zEEBRZY$ayJG+z*9^wes=2g){#&$CVN13(J3U%(b@JOladsSz-?)tN%7X2eQF%B}8q z8!RDCNoy>b29V)ip%=1oqCE7?%@Ix_rm3ERs3y~L*3%M2d>c_??I9AJe>&iY84&;9 z3^v%Y#VU3Y9vMil=C>BpF_o8+amHfW1pWKfi5EOv1!0&`e_n2$<|Ek*jy9nyb5I=7(O9hgbacM4qoKJ3 zEtN#Tb;UHF16OnhM$$=)X0Sl7h6D+P;s_9g=3-PUcdAt!0vj?S0a6clbv0@V7iU(4 z?oA-X;bdGP-_>5G1hm|glRjrL@IgN2nf1$dIg}_(HsuL|1%9GHk^odg_XUa>qwc8t*bc_A53b{5; W(R5;q>FLC3^uws6Bj251?f(Grm3a#Q literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/high.gif b/images/mood/charitycam/suns/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..759c6ef5febaf26a506460d298f31e3005d13567 GIT binary patch literal 1595 zcmZwFc~BE~6bJC%?&jDWz{;TkVoU%dU|;|RgSN2QAR=BN;!%`NG-#2422epkNkYPr z1`Q0_fLJ4fgN!)npru}u1VrjE)_c4Sq9UzFY_Zf@*#`gVbf#~<^WMDo$NTHEU}3U2 zeqAt#0k^?K5d@)(N0o#-n2JDE1XdW077}P-Dq0ecmbkl8u1`hva!jw+n=&v{2B$s@ zt(T)s?qs-wH7Pl*8EC5#?TAJ@lvsxf>(I+jD=`v)VGeqSz(~1(%!nUTa)wptX%$A6 z0MZ1=67+%!dtBmPIiy~2wU8jo7QQuM7fb|MkG-vrCY!LaR{7i360#$VJS`{t3dySi z@~Vk^+(8cak)-=Q5Rj~;^V640C9?T3kx>XVar!`E#JH#E^8z9OK*s@ua#K33_Hw}E zukANm9TgZgp_p^>DQ=t`ku2}PxG$Js**o8;G&)M7J zInDe?+dRlPnYFXl3#8r*(BlX!OqUn{s})|H_nQSgo*p7+75i_a^qG?7JSCp?X= z%+0}OmqY&~Vg`W*Sa2wpw(aF$wqU6^h}B*V2-G`U4ItJ%T!-T0p}~xZPCSH>XtZi+ z-k}O}rs2Xh!kkj42r(p`(LAeO>}?B{R1T_p^g-#>Ejd)0^+jVY&1I*I*dp=K$}Om31Qtq1t>M{sUYuLA#% zR2T?AAd24aO z^hF>%ljqA>E?nFg7Z`awtnizwMzQ}3TP<>g?LSB7J&-T$!@2&;#Jg6zLT_jnY;ktZ zU12r(gzg*|O&#hpRm2szoZ4p9U7q|HoP7?VUh+{rxPs?5)4jSwUlB=ZMaX>LFSftZ zJUCLh{!)BU`TTr@TFLSqdm}p_F4z;0q^gQ!NvRtvS2D=eHOQ#P^;s*)Zm1`z;wEjG zW?Pf=k6%tj*8pq^uw(Mzz=M+**>zJ^{t*0`m@Wga6@4lfw~6Jd$iMTfMB zdMm^draR5$L0xm4Xvlf|aMjyt>tTkkb0bzIIFTG=5T4>6K>2#UmPW^%W{;36ewKN5 z-8Gn%T!*!w0oi;lO#AfwE-Qk4EQFD=GCPZv+Ws;GO7N!md(M%CI`*ZWa_LG%6z7Wr z>d#y~Ry0g-h4+^fgslOi)bKVhFfiiB%?Pk9d$5;xn~{Q4$fTrLIZIuvK-0XFAdU7lXDf0c3yF(ojOUR!Ko($ z`Y`sg+ZqQmFddV?46&jEVaZr-uIxpV8vdUvp0<2~>pA4MFbAR7*VvEIUQcjsQ@}9A wIZuY%`KwVSi3K8aK39Z;de03uXdBhftd)eTF-eLyA_GSegUP!bg223g0MM;)#{d8T literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/horny.gif b/images/mood/charitycam/suns/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..82bdc351fe36bcc78daff0359eb09c36c2102c98 GIT binary patch literal 1219 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 O{}DL);{RUY4*dzPs-%$s literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/hungry.gif b/images/mood/charitycam/suns/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb291604e62eaaa9c6873ab29405f5981fbdb5f7 GIT binary patch literal 3335 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 SWujay$E5ejT5*bk+w~v&U0ad> literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/indescribable.gif b/images/mood/charitycam/suns/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..19c1f97b2785ddfda2fd29b8cbef717ae74d77a2 GIT binary patch literal 3669 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 literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/index.html b/images/mood/charitycam/suns/index.html new file mode 100644 index 0000000..bd16e01 --- /dev/null +++ b/images/mood/charitycam/suns/index.html @@ -0,0 +1,74 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angry.gif
artistic.gif
awake.gif
blah.gif
blank.gif
cold.gif
confused.gif
determined.gif
drunk.gif
energetic.gif
envious.gif
examinate.gif
full.gif
gloomy.gif
good.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
indescribable.gif
loved.gif
okay.gif
sad.gif
scared.gif
sick.gif
silly.gif
sore.gif
surprised.gif
thirsty.gif
thoughtful.gif
tired.gif
working.gif
diff --git a/images/mood/charitycam/suns/loved.gif b/images/mood/charitycam/suns/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..13bc15f12f9ae225c7de9108e4ed1c2f863d88dd GIT binary patch literal 2783 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 Dj{Nm- literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/sad.gif b/images/mood/charitycam/suns/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fd3ec65609af34bc557a9e14501f89bb0de4dae GIT binary patch literal 2594 zcmdVbTT~Nw0>|-5GRaIJ!67D?Adw^_NI@%7kc%iYL1`_`;i|aGDg!35EBhL{f%sP=9{0cBp^t$UuPgvS94K zVI_RdA1)4uOBD9TaQNs(xF!}crf^Tc&%6{VY)paMRLF%b$TvRhaev`A;q0rKoUeAm zU*@nz(%B<94&zbW>BzU9WiuwTL|^Tc60uSuGoni$K3wHLd5}I^>H1R}muOvnyKU!8 zP3YemV~G|S(YAr;iXpl;6T`?f?n(^g62@}kPvyj|R$}~f;^6>65Obdw61EW`iVeY- zJjCm5PYP-NX$qu!&E3lYzy=Tk&Hw<<0wkarlbb9>wCMJvf{7&NA_nzZhODB`ri{)B z1x+~h07u|UPD<{8LLEHfn$44S0|)sw3!jf-bs@oqfVY)w+1<3O9C7Yr6a7bPnUTB8 zCaxn`XLo!}u3t_W@oPCthwGKsuNm%;OX9h< z>s8(OXTs7-W!5ye2N5MW6zwy>9YeJdMn6?w&6CTz2hN&BQGa0EEyAii0uRUNIUR>A zNBJ{Y-stpqJI+n=+gidx5$z;T?I;Ah}=lWzz>Pe{8jo8EvaSH2FQb zr+wxu>CF5r-+G0{w3E%|8IYMiy?yELjQGhlPxRw<0qaKpjMFF}BQ!Pf)Fp8L?8Ch` zwG=YazQGO_H=oL%nYo!rAK#3l6tcH>mBQ`&D=1wQIB6*dVsHY)}RwYU)OmaK}|CsfO^0(R|FERxItq;Pkaj=z0b@r1?TwW^Awp;0F= z_`T0#q%dD0M@bT;_c6{-mf{mhPDo>#?q|*ikMNtcrOe%<O^c;c9WE z?}LjEp=hb6D`*IK(G0Q}BOGStUerQ~ag?I~g&{{Psi?q0jc=>AQ0g43G16LcpxSVn zWegi+wEHv^Lg!eXW7q<8Z0Sk3KdA-Vszg;EuO19*#VDpSyaLJ2!8^!It)x>Q>wzC5 zk^U1D@@9dms8J{MRbzRc`W^i$mTiaV`O5F0M?FEZCRe5?Sw%|oR!;a`<>8>Wq2I8{iSy{QG5ObN%vMqrq;CxQE+Ru5SY{vYESAVgf@1aJ zJ!@_cNMUDiN*T;6PnQGE#ioW5NimL5scb|P+RHDFrt$L(jYnb~!bl((XRuU3+f)eC zE5nCG%h-iuG;R;?6EMV4bK`_2UoHWYrB=841K|S96hGKL46y@~8c9^p(+p6ZHUc0k z4j+o;1p;T*^VkA2B@n7`$BwbDPs9eh=i=_9+9gl5^?4(ua>jYb23ML=+I`sA>*%dL z4Rh#NG{o`1fhfmJw=Qxu5BaY?3ErGOz0OH_cG_jdBa47lA|qMP=@$Ds9GSe6(tc>< zlgt}uw^@pBGT0xUN9Sskb+2)eLr}g|_lnbxKS(+~g8m1bXl3%kj~Qpv1(2OLYSu#Q zeJEk#7`<>$P^z0$ClDzp@gBK21`A@~-mMLfUX$dx_+ZiXc}Y*ddnL)BEcrA?j*+N& zdV4i=ry7Ht6};YK?nzDjdZLcoKCb5UB`GGC=87XAoZ;8xaTg!`>$urwtuDPDc?ix!NcEi-qL zsq>O%+;QOE^8EmSN%tGhLmOM#BH!pf{XYlq1c^+0eeeo@cIiC#bwVMPu%8>ZmxK4i zN<(7)^wgC^I%yUDGE&H#s*(k(YW@N{`QZSGwq)H9LtJ4J>iE0d3iXoTRAs>A?WN3t zMA%6o7lgR&HB_NgEkfS@_hj8-TVb9cwVauTp2SFbNN?rxBZw5@u;oB0m;Mowz{{Q} zII?N`W-%2()EG^%JUOtk=4op|3#i|XQw}}X rES0YOb_;%-TOM{NVy9gu4m62U#b7)?wH2krX&%=O*`%sa09gGmRPO(Z literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/scared.gif b/images/mood/charitycam/suns/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f45c21a3cd30e03064117c5a3176622994c350c GIT binary patch literal 1741 zcmeH_-A|Ke7{;G|@)Rh0fXZGO3|>A(7ig=6Rxs%YAnOuVUjgL}i^WEP)ofs0fE1Df zb%0hZu{sD1p_96)t3yU{J7_`;lr3%q5{BXu1_{y~IAAi?)G?lQJKCSH1Fu~9<;s0{ z=Xdn&VyUb;6^OxFD+r}V1`Q%;ltG;m>XjiPy%HIe(4dA!B{YVpqbym_EQ9teXp_L( zGU%2;vl^NyWT8VP>}qJEppAxh8uro1t|Odk%@Hp*rUN=z%UPVF*N9*c6pCi9z--%R)|Xd_e`5wL)O z1!6P6pxC>cWru@j@S7aN;F5_Iof6 z(T6eq=kNc9#1W-MWye(tO_4ZT$YO+!WRT4Z2d&^OCWrzgNCE)vfjit8&%bsx zoA0c0Y_V@Dk{UM)j_sQ|I+$;4k@ue87+=ggbmct>xyOd(i^?f> z*zMMF>GfD!k3EsY3% z&n8ceTfd`%FQUGR%K4*vH1|sX%#C2$!YF6^+3VbLarfNx^uq(C_bzblhkyHE9*EcF z)K8re((1U~^&f)b`jonU`w;QjW&PUYoX+HfXAb*>#rJkuC}p_${U5W^cA9#<{(+P{ zlOKxHE~DlBRAFs{w?UOBd!l8X-s(NE)M{F^{>+MoTGP7*c3THuT2i~*w#p$L;rj}J z7w}i^cfNVSLb9VI>^T*Z!|2J2m9<^0h?qm#iH@*_^sxAor~`tVMNY0!j63d`Hd6XcaI1q*cxotg5}t2NhNY*ZHZNOH@ouc-g;hdncF- zfgCWIqzQ2LHkslGO`lM~n2nz_^CBXJUWGtAq;L=p$7D1=eWjfTiCLE-b~XIYEqHz9 zy;~ydh>4N>GOe9ALYA2z-y>}2)FztO6`c8IO+P<&zefHaE5R!(Us?Hou`>T}VF>+#CMbQgtyTj^WTias&!=V6axi zc#(*ZVT}@JtSC`%h!9WctT-H90wT0?6nkcBJBul<8e1#awc@{Whuxd~IcKjuJ9}RI ze&;-|o)@3^K0pKmz6gfK3AkxGA;MTZ>X>i)tpFf;oKlNYN|t7LFBN?Z|O-?`{-{6`8_o;{$sl ziS-WK7tl??i!0u&Cbqr15(^ciI!5n9tzJAnRrVC$H57CtI@s)2dfPq0D=Gu-PiyyR zBbJx@-T9lN>$$Gom*nOOvex0+ZQH_A+hyW zjQhG$t7X%?D`n$@^T$PJD?;cGx)cS;>+as1;D;RvFOi=*a4~@MRy*bQuf2Tx53Z%m z@Un53#^)uRS9i-Fd>!_F_%DgqU}W&~<2x5@EX~hs;HKnxUYV|C^Zd=>rg}Au)CLxB zm>#an?_&o(i9Kg1A|2xmld(_VcfT>0U36jb$BXOBY5JpxILp!-)xN#@$Q_dvZV!wq zD($+KJ{!!N{c)j$i@b?@VdUY~QJumO-fxLw4fkVVxsLw2$S7mlhTr9@uUjN-Z$<48 zRgRK7g$LWHYHeu{z{=|X1Pz3 zoaC%PGd8I1q%>>v0D58B_tD*GD4^0(W5hmch^zH94Tn{^$c-rLpG5^d_oB?-RF!^_ zbbnt+h2XREn8&zI6dw_L%&YoaumIH^0CNkDbA-|6hm-kR6Tc2S{qvzsM=LI}fh5IP ze!L+6uCJ4sKK6rQAZHdK`}Wv3j}uLwq{dyAt@XC^h>v!<_0R=nNl-}Ev|g|OVURa2 zKi3oB?_j^h7hu`R`R3g>!vE6K8YrFG{e&G7LDD}}y7iIfhhczbIrRVdx;`Kk8SHibp8~ z)@To)t2ss*TmHr&hgsA(N<*^>w9qzG;Pf7Rx~QQUL8Tj`6acdy}B3eAb(;{5JzVyY-A0!@0=*61;Xq!%oS!WP{m*7 zl4nxtKP*Wr4=PbZc!a(4-9KuKT_jswjPEZHr9Tm3Ure;;=h_aOD0|Tg@uv!hhEYOY+*Uk0*$E(A>;IB!oueJ#mn-EI+gPBc z-r-9103lWZW14hWiC`kKgKXj|dS$JAx$QSOiNo{^we$uWLWKTe8!E#)auSjckLdqg+Lu|amKfsAC&b@B}pfGo>)V1 H09O1RLs1`m literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/silly.gif b/images/mood/charitycam/suns/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..ccc9d4a154bda5d898f68d6a64adc26394327bdb GIT binary patch literal 3857 zcmeI!YfzKf9R~0>$(!U2fpCxz0&+1%P~;Sxc4l`v{oIb*GiUzi z%=vicH_tq=D`O(~DZWT3@&uV(8GI}!1S{lYX*iaJ&rFbogB%>oiN^|YtZ-(gNi_>F zH6N>4fa$`qb9}6ckE!D^wG?P%Gn-u#kLjeCPKMRUFue@aq_OMcLA?yCmx5Ltv`V@4 zX_zq$7_&fA8feM_ty#bl0{WM-M)+Kd6g zV^78f!1$1f%5az#4|AkO zwX{`(_v`qBYA~o~4{E^3%+|5THOROIgK7lMT+{&S5U9go4F+{iBO2~>SpcjEht-o?a0$aHcj5$y(dwX0wST7r?m%;OK&?tpQ8ElfmCK;?xgDsn3>u%T& zU=MfP5&|D^p(P*IXyAtTOAe9#03TOpj876{?Y=W`)_P4v38BB3NYG?+&s z%sx$`w9uI|5JBt^F5-dOJ!A3F3A)1RX1Fh zd>j_T?CPZIqS!5R+DY{9?4%3DpBNaCdLego?!_bYas1R=IZ$#eyZ;-t|p4pkoOZq1Bu5|L-L!MhalTprQap?$wc2)(?Em7I8x z6?`+Yob%aNf1*|9T$}c&?zy*T%w}Gzo-cYF850t-Gu_cgT=DYhLTTK@m`~}q5z+VM zq72~x=m4_5+tm(}(N;70({MDFvE+_Y1jv6`zo~@%$RxLO6myh>s9R3za@R+azm+Z8 zb(U!7DBuZ1dtS7ad!}P5k%RCBKmnfFoKhYbXH^pXygFPwx8{zuJ1&1cK?N(eO~e)p ztOyaMN(LzIn*UW}$69ljs}E592+JNe0oKqh6z=; z`H-vI1T)rY=^bk#;G-dG)_C3)(mtmv3RRjzTUDvU5*t8EUj6mDtt?`>-b`}BsvBYM!&~1xL*gu(j*Abvuh1)LV}6c{)O^tmzeGyXfP3W`J@x^&FR@VofmPnow1rnAkjP|3MJJ) zeUIdm&nZS#O!8cf9H%!Q;}NMYfl4LiOiXl@Gv$)X;u4}WsK_)wL0cm;(7K)Mmfo;P zwq2b~w)a>KIEZ~95D-uf2M{rdRz=O+@3f!h%#>dgeyDFSAyoMWrF)EPOo-O zuwJPo{OBIm*7%jVQtLL->Q183+47Sg`RFBcadL&#O84EM>=#aZtuxh8hxwOJ6Upc= zDqfGQe>2(0+ok9a4Sg0@_gy)ipUPqk2TmPg1tpzrWC;Cs9Cl_7PUrJ|zJC4kjydtn z3|PDTS+MhAzzo>i!{_6;53e7zkLpb5a9EPd5;KJMCpwF3?>1~ggOY3;M2Z1fH)8RL0(9+fXNj3Ov0>{P6G(H&tKi0A`iMWS7C2ol| zR-*lHpEZ!2SDOSxD$~QJqUpVK$Az_7hN{~XU%l0A^w*e#WID&7I+u_zpcZa7WJlZ2 z%ajX=G>I*cOy~VtNO2pgWX(-UB9N%g2!@d8s01Nkm>MB6(`^J-M)}aT-S~T-bW7nyi@;2z^bH-x{QJrz1fQ@MW{hRX zll+nDVi*z@RMwmm5C}i@`kn;rvNw~5^XaZZU&5jM6v^hpY@{f#<2gznytQxYLNYeD zd343B*U$dxl@>hJJnMBmbS{az=N~YCx@T;s`0JP7KUqKPHU6Df>-4PGp+CIuUe*5_ zUah|*um8Ee?p@e8Q(v2(zVrI8d`$>i{?4nn<4^Lnu<7OZkN+)ShyMKkLhxTN1d;y$ Ds}AUQ literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/sore.gif b/images/mood/charitycam/suns/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d8b6f3d79e9c3312dfe5855500d5afa94a6dd8d GIT binary patch literal 2154 zcmeH{TToL69>z~@=MWlGDtO&}@00!{FDo~0P69|Hc zHP~!L#hc0`7d~cAC zK-ocLsR!7|1Emq5JjzVT2bCU>k`Ku|tYmyE1VMs=g2ZAm(A)da12TAk%ie$y0NPJm z{+vizIZ9c+N?v9$jS<_IFEfor%pW(!jE997kA7`Lltw9FltPQGjA!LXjrBo`b(zMV zFN{S`J32agdwY!|4~=hojmvGl#tp6i%`}>Z1cV;*n#-R+)G~3 z+={yCq`O43NVnco*jaB%=GQbj6cu^kaoRi6GWwGmJ8MrIC{|vXf&zKb`Y? zIkw0v$v@Z3T?!*fE6Omfz|Q6nCeKufI;H}FD3U)Ef9555yL7%DZ%*Rs6Sii!S60k^ zNWqe<0~tI#kB)yy#p%NvsJ?iKbG5Hj-Dz?mO2U)jD~_M3zGF8tNWIb?j;RWzrw#&9 zzZ_y!XZ-%Ip^hF0%Mn{CYbF6#ki;fpAF_CaMUQR_C6^mIliL*4SvUhL_Rl0KTAxMC zDw|c6Jd+3Ji|jk-4f!0{I?|3d_N>mgDEd8LaMa`gpL1Ui>Sl11VY+|L-M-_=sy0+q z_0#?RvKO!K%$CloT1#3^T0HvaGt;*neVPAy)3&hm;!W$APrsW2{1rW?RZqse?XdOd zEOgTj%RYhsn^g`sLAAoI3=2<1u|toBZb!&E@vxQHPjw(xLdA%9;MOkxa`YW0?yx;0 zQWbo{i=fNf^4Y4{NEZ>6`wMvZ36$#1zUzaD%-!$jZ%MYk`W z#xPBW%q%Js$eWvvWvB+Myr2Z?U%L z`bWMQb--BWD%H?^<2w2@rRUO|Tf^FsSDdvyrdS7rE10r-zc{by=etp~n&>>|$^3lZ zsO-ODIW#rw_viVgQP5BeAIou3!?qYaO)jC(hVQHSA7Id;gVXV1GT?6CZkBf-D z{)c{(9DFmZ!E)%`ktKf#nZ}iWa)5+2u{nDU14eG5MMz^Zk2{6o1acmh6bxZaeA$am zVSEZSRUTugfN^GAVS=A+@U$Qv$7QpK@KzrTuE-$7$@g=0B@I%F*abJr>h5fiWv(VR zVOe?@cQ)(kZhdo;&n~TUTMBswp((s2)W(a2$*T6&7PJ|_n@*`^tHRv7QBNag)z3H0 zKEG$pn)PcNP*uMEc65yFa^Es>i|V_v(vz-XFX?~0Zhv7InN!UqCAm?$#=c3UOqBL_ z{tX~<+%?t&{C`5xbRCLL|A*rL1d5oAF;$ss44LLgK_?yx4V1)}nM1-aTvzo5>Yj)) zyL7LSCJS@Vdaj0gc#SIz8;T6Wl4$66da}E8-cfqQb9&pCFO?`lqOGIQ&oM=9sQi;^ z+KK2ak%%fRtin+f+i_uT7^<8usj-byi|`hwB%*43iNyJ<&zDx5iI(NzBAK2geN_{6 zLp}`_VcCgFKY9`$GP3Ro-W(zP|gYw`E!}nvlw>)1~V;0cA7O Zs^&NCRbB0K7uT`3GI{yJ0SpG%^KY;@j{g7v literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/surprised.gif b/images/mood/charitycam/suns/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cfa99f1f4f5447a3290478bb9baed351ee52271 GIT binary patch literal 1768 zcmd7Q@l%uc9S88|NuDI%5E8$E7#<=>5*Uc3lB6Pegtf^NK+0SVPbt-$x=2LgVmoMR zg;Hw*(IRALxMf|a(M4>qbxRLKTI@A<2`YH?WZ~*q?Hq$En)c>IYc0}gzDw8hZa?e~ z*yld?{(SE9+G)_9Obg>K z1TG5r3xT%;yib7<3b<;3i-B%avPpjp@G`(_0)7+lnV{c725Vr@1cD3<(=f~^f))_6 zz>p1&Sm1~ahHY?M4W~<`3zTA#zx z8ui2aJY*_~H%Y$QM^k#RR%NVb<;bYqKdfLs_#E-r|?81e$-2goa4a4Qmr3Q$)G>dQrMmn?=z6f8tR z3Wd}tte6Sek<0YxXhl3|S_qoZAF5G^K_L?wVbF*P1uf`YBMR?B(-2K67RS|SMuEm# zk>8CjccIIDXxfLSgJ@<1#lr|Ca~vU*e7*t+o~x{T-k>*DYSyUO_z$Ngg0D%=A`DBx z6j%<1fdqzQ%?4v2+Q|(y&vo1h94$`e^zW{o;z_%?L*^~M-pd*5>ep6DE?wk#pC-?l z`6r1l$?wBpbw~pU1X9icq_x zi+gvm4~Wk;J1xR!Z>MnGEF?O<``g6qA#J&Dj4cLc$ELl6xc`v$di+F>{Ip|?4O3&D zmHY4P;APUYMg#mQfxBS#>p&?;TWgLS=CxFAkZpT-=ll_U0(W_`6D>J#tpkhVl5@`S z4C82QEN%U_a+gT=>U1A8+#aNPBGqA-QTvImLk}(ucJ|P9Hyfm75nX|gJQj%R@rdgD z?;Rgssu1K91tR!s%AG8_ac2uHP-#CtFWRWW+59YHvxAqv^L69P$GIVA)%F!`Gc6c> zN5$eTFLF4zr>ZJ@)44;=@#Si7z{%m~>7v7uqSziz=FY(!V*K^;!W z<&Xu89w*OwP<)V|E-`B0R`h=g_8G^IV0T0gjFvwJ zd%f-6#E}~p%%k2ZX6YNzu&9{jIa7b7Z}RO&c{5|2`!_PUFRVL^M<(c^O@ps;{p;_( zeDy%mDf6S##O*6fnr7whqyB()qQ`dgFU4=IGBmEQQdfPDKw{;)ZNL0;Vcx^m-e{9w zS?Y)bO+^o!UCmTjTcRxnE%mvX-Egn>#hLw%Yo5P9Ch6=HYOAfY&UudFM9QjiEQ$%g zp5o=a=1~x$5@N~#bwGUKpvl_B{*TMf$1V-sPb6@n;mcna5dYJqA&uJJQ})N0ldV-= zsFW0Y%#fwIWtR8OHx98=f1x=%#g}DCu+*pCYdhiGc=k?|m68SX>3n%zm9*e2#y(zl zD?+5JJQ1A3Yc-DrcvHJ#GVA1{>g}dt{)DF0!)4Ek`;LA39bS%ky zO_cRfy+_Xt_Ft?bUyMYe#6R&!goR6V7>lKFV4TcWM?G2VQ|a-T?5c||NL5Ak5_3R* zf(#B3X~M#}4n81bA$|IM%IN{nH@9s-?HP37^6&FH_=Ac%2M~r;9UN=6>$aYAwawTk MOkZu(VOZI}0k>ks4*&oF literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/thirsty.gif b/images/mood/charitycam/suns/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..9804f9a3554a2b260f263b8867b1c9a29584ebdf GIT binary patch literal 1227 zcmV;+1T_0cNk%w1VIu%C0K@(d66)rr$NRR^u zg$X-!kZ_?P$PE`U3Y6e7WCaNwILrijumVm8It5nXutCF2nN67z)L>Cz1qTa~j$Eq2 zWz(rsGib1I;c8Z$Aa8O2t09A1w+m4^z=}~q$*&*sF3ezouZ6rH?9w&(ai>v&Vn29T z{2}f_#f&3NFo?3kWC<1mXjZ5=FXOnKA%B>xRKiNT6Ep{~Kq2(!#~wV#hOkmDLIN8I zT)+T%act1O8AE`O;c7$N1TtXY?fV0T=ddF~U?5>ag4-Li6IdPrFog)vpZ)`m5Mla+ z24@Z8-hg0x1PtIQV0a$>`TOz;7#JvkUAz4E-_b__YXXu7fdUE`a9nn|!3SP^0@jDY zbP5!}-$5MUhCpr;*wx zOy3kEeXoG78fM1vJ7EEK5mf`*J54_c_$;i82K7am+B$bmyhjvYEkxWF*u z28$O3N@$t!q=XI}WM({A;iiL}964;zAT#Dtr35up)L6m6f{6jL0yxP*L(8R6qh`=x z;X>7`ShIrM&^2s^w{I1mbYS%&fei#Yfc?N%VFn9-E%5yyK|As4jmhU%DD&cBEb6^vTxa- zeTRksAwyM!t$Fv3OriN~%Mchyn2-Q@XXOzFQ;6Wa`QQiwL1p;nYp8^ITm!5jy1z4bb7(}N)0r~02pMTtO z_rZf3&d0!n6P>rDa-A~tCQ=9;g%G2ks*37C1F8lD06Wjn=FtEE literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/thoughtful.gif b/images/mood/charitycam/suns/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..a61f32cde3fa99acf4fa3ab4c71fb31d8109ba00 GIT binary patch literal 3057 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 j!gorW*c&`f{c!|KjJF1MY%h;!UK928XP%kw zAJ060d^WsVpvx{-K$*~0==oT(fdyL%V#RJ+^#BWA$v*?%wbX$-<3*xtkx~)i`73p@FCPm;%e%zul zdBBQ9-{C&0lu}!AZ@#I~pR$7O*_6v~vy~+>Z#>;TvlvhT23iTmM^9qxg?os)=tbv2|T& zR~DLhC%;V&cc^1#$v{gG7iURlPiUrOp0-sLsINwQoDAyRw+uQ(J}%`|N4vu6{jt*Z zfBi`~e`Z5lH|Trd7HDFwiPl=WX2OG3UN6gnUqv*`c1g}xzsxw}zVQ5elV!|3;mjKn z@A~4_V$Q*po&=rkqNsd6U^`ie5kI7hl zrA&cCbhasyT~+m$pbZ1dRYWD`J}?^Av%EGMm+KLy@|AvX^~bzIw-IVRj8uH+yR#-t z;|N35m^7u1&f9UP& zzVLbw@81=;*a2;g@ZPcoViVV`yx3Vd81Tevd6PsZHk>EUY2dukM!!4KqBRZ8^w^l2 zL)(_&%;s)&8zkdeksCmiMPCZoCtPi?>ncrE?jm17d+X66S9-!iKC1(J+nSvLf5L zDI}@CZ5q9c>Bu=fwi=IyVS2w6p?^Ix``PhFXCMDSqbJ@qG9_Re0*h0AQZhxU>oxDQ M7H?c0fMF=-S8suCNB{r; literal 0 HcmV?d00001 diff --git a/images/mood/charitycam/suns/working.gif b/images/mood/charitycam/suns/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..06b4fb9d5fb63d5e88e6948a2fe64374c3ff17d6 GIT binary patch literal 1143 zcmV--1c>`bNk%w1VIu%C0K@BYY4S# z5Ved-y;32@0LI3~#?EsP={^|ua|r))A^(gB|CAy3tq}jq82E`t?zM0K#&iGUl=t_w z|L?~Cg#Z8l{{R30A^!_bMO0HmK~P09E-(WD0000X`2-0v0000i000UAApj--00{m7 z0RYH=0fWGU2oFx6Kp`Q*3>6v*yx_26gb5WDE|dshVFe5mLUIH^;Ub5O6ed(ykg=c! z4ht1>;1HpL!;l&QJf#3u3r%0Rx2!6S6W5iL>h1v1G|I#H!Y!Nevh>eAvtI0tLSm_I`+B z?$McdXD>dhX&63=psr1NZyvz2^@J0q4dE5jeQC zn6smX2nuw@%rI1@2BsOJVjzlAfdQoeP(~FRm0&>(7cO9+P+@{qr6DIg^(r>3+l5un zRxGIjLxvA{7ha&Smjd1o5s+Rzm?5Xdr)@uYSo|S?zwj90^M-MukdxBy`_ z-rUD|%U0eTLURewi+?a~{P}c>7$m(^7oR=4ci#eCZpd&!yae~IyPI$P9l+YL5!^R# zOnmul20OZL5T-F;N_QAW(j}*WC~>FjbR=nK!*r5h*d)g J2ow+i06Ub1!)*Wn literal 0 HcmV?d00001 diff --git a/images/mood/classic/angry.gif b/images/mood/classic/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..e1fbeb5f0ce20eda0aaad987497cd071d31385c3 GIT binary patch literal 94 zcmZ?wbhEHb`FT literal 0 HcmV?d00001 diff --git a/images/mood/classic/biggrin.gif b/images/mood/classic/biggrin.gif new file mode 100644 index 0000000000000000000000000000000000000000..8be2882f21aff6358bd78574b1bdd2bfd59d4f81 GIT binary patch literal 899 zcmchWzmJV!5QPuRW>>H_vJDDEhiX>1Q6b1mG-?GB6T}uoK~1+e5y?hOw~b=E)vB)e z5yjM^RUot^q8iV9{0-jbW-{-4<~e7+dw%KMiP6O>4iP=0F&3mfqx)y2sL6rL&;S*7>qX3XjLcIZE8+N zR0oMa#!_WQ7P(><3Yt+FMUEs*0B~`gpm9r-+|z`)F)1LA<>8JKkE@XkCwndxDYLR96e oy$qhZHVcJ26*Ka}R@LdYYblsbk807Y{f2mk;8 literal 0 HcmV?d00001 diff --git a/images/mood/classic/blush.gif b/images/mood/classic/blush.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad7efa2fbec6f55dc4d486c3f906b76a7c5b69d9 GIT binary patch literal 99 zcmZ?wbhEHb07IlA A4*&oF literal 0 HcmV?d00001 diff --git a/images/mood/classic/clean.pl b/images/mood/classic/clean.pl new file mode 100755 index 0000000..586676a --- /dev/null +++ b/images/mood/classic/clean.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# + +opendir (DIR, "."); +@files = readdir DIR; + +open (HTML, ">index.html"); +print HTML "\n"; +print HTML "\n"; + +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + my $newfile = $file; + $newfile =~ s/\s\(\d\)//g; + if ($file ne $newfile) { + rename $file, $newfile; + $file = $newfile; + } + print HTML ""; + foreach $col ("#FFFFFF", "#000000", "#C0C0C0", "#FFFF00", "#FF0000") { + print HTML ""; + } + print HTML "\n"; +} + +print HTML "
$file
\n"; diff --git a/images/mood/classic/confused.gif b/images/mood/classic/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe5e522b15588682a59ae074ce128078b719518f GIT binary patch literal 112 zcmZ?wbhEHb6lM@)SjYeZ|NjFK2q^w!VPs%nV$cDJg5(*P9H;biaKDsD^3Dkq5a}!8 zT2pXC%;)At-K1ZwD&f-({XF>O_0_v8ycTkZ{7rC?U)6EurI)B8Yi9MH4lmxVuT~`R IvNBi$0CT@8GXMYp literal 0 HcmV?d00001 diff --git a/images/mood/classic/confused2.gif b/images/mood/classic/confused2.gif new file mode 100644 index 0000000000000000000000000000000000000000..684b51c98545b827ab9828472b757eb4c35bfef2 GIT binary patch literal 110 zcmZ?wbhEHbCMz|5cn;)CQJnC$PQwC&VkT$rJM>-MC3 zre}V5@=eo>3d?&{xYgr&)cTgr9cWgFjxZs<@F?4 literal 0 HcmV?d00001 diff --git a/images/mood/classic/devious.gif b/images/mood/classic/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..b2593f38d9dd090518ab85bec1c5bcf94a5f5302 GIT binary patch literal 913 zcmds$F>94!4292yBCTRugwlcv79FIhC|O#%SkQYFS8=+FAlY=#%|+3v)y1|5*}J&- z3p#ia3rZFp93330;4jc6KEZ$CyM-ht&p998=;m;B?e3iB^h5uiNiKzyQi;k;=CY8b zth(tYcX`NDUOgM8a78FmQN5a`bY&=0StzMY<*HDniUMt<(PEkD>O1}1EX>lZ`Ye^Z zd6=hpH3iLZi?B$GYA9yYEyFS`3r1G0+$yZnimOl~1~iml(c>`MNTbDawV|$g;hyf* z{y0k&;gKHIcA=n|;hCO=d!U&03a|9S9(jPtHgVt|2pmF<7|>8M3I~VLMjEZ^_R~^Dx=7eqzM2n#t9m?L`fcCvP~Q?VHk%{BL*~^V8Ov*w2`j< zL_JNLnpb==g2W$Zsj{j+Ai4h6Z~6Dsplx30KcW8#O+V1tjX$ILryI|wmS@J(GkSkx zcH!&R?OV%xn~RHg#!H*8hc8YZ8$MflwRcr@>hb>1`F96fM=o9(fBbyr!^@-V-_E_c x{QY3(^!+anS0CNGwmW(_b3la zGZ9;^!h|r0g@KuYoq+{t5SIam!m0^Zvb1#j5z?$cX;!c_hXISD_KpQ%lGr3U13Va< zCPYMZDI;W&Ob+l6WSMd0o|SnYLYf(9GAGz%o`4gQAnC5P4aB|Hr&sr2lja6_Z0eOP->2^c8LR=jQcTSN literal 0 HcmV?d00001 diff --git a/images/mood/classic/drunk.gif b/images/mood/classic/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f2bf7e122bd808c87aab1db2759e111736b4b7e GIT binary patch literal 114 zcmZ?wbhEHb<>Ua{)J-Va+G zUN$et+WqMsLvSUdT6k==7Mf*Mo_{ F8UTuKFO2{I literal 0 HcmV?d00001 diff --git a/images/mood/classic/eek.gif b/images/mood/classic/eek.gif new file mode 100644 index 0000000000000000000000000000000000000000..43cf2125e64d3d306fd2a60fb425c2e4b8cda9cc GIT binary patch literal 1264 zcmZ?wbhEHb79a*vAp;NmU zYmJCOg2UlSa?W`^JB1dXnkE@4HD$)eWUrZ``Bgp^LMey3*s}R}II!6ehSvtGEgA`l z?yY=`3>_X0OI-U|*mx9Heo}GomyIvlqamnvwoNi!YRyW)#7^eZPYQ$kx z3@)n{HMH{S3Mo_wGBk9s*ffRQxcJz8vb=s1i$TJHlhZT}+j=yOlAU|B@}uUQD1PiW z)!uy470E417iV)8rujr%TyUY0krA8U;;>lAqEjL<@xXyD28M(y8WR;7dnE0fY$61f zcur<><&$72Ns?HTH2qoY`WIA)!g$}7+GEWar490w~@-ure<8ciy0WK0g=}sl>h($ literal 0 HcmV?d00001 diff --git a/images/mood/classic/index.html b/images/mood/classic/index.html new file mode 100644 index 0000000..2ed8187 --- /dev/null +++ b/images/mood/classic/index.html @@ -0,0 +1,62 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + +
angry.gif
biggrin.gif
blah.gif
blush.gif
confused.gif
confused2.gif
cool.gif
devious.gif
dizzy.gif
drunk.gif
eek.gif
energetic.gif
frown.gif
laugh.gif
sad.gif
shock.gif
sick.gif
smile.gif
thinking.gif
tired.gif
wink.gif
diff --git a/images/mood/classic/laugh.gif b/images/mood/classic/laugh.gif new file mode 100644 index 0000000000000000000000000000000000000000..7204cee6fb9832024552928726086c3bc51245d4 GIT binary patch literal 158 zcmZ?wbhEHb#j39;%hyckmFd4My&OAPW@nMouROPF^ rOs=vGbAM>aOVnN4ocpG;ZN&~Nq4t|^r@u}7JgG#A-2U_3hKFef6mIvXI7>SU2cpF)&PEy9cTam literal 0 HcmV?d00001 diff --git a/images/mood/classic/sick.gif b/images/mood/classic/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B+|z`)3$0}=(vGcf7&@XkCwk?CQQLR96e oy$rdXnO#3Po-UvHQhe?jl|_mfopNio+`JvQ`qqgaDOLt+0L51ydjJ3c literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/alien.gif b/images/mood/ibrad/alien.gif new file mode 100644 index 0000000000000000000000000000000000000000..4e47b43cec507eda257df1ddbc9c58f9d43cab67 GIT binary patch literal 94 zcmZ?wbhEHb^CHnN>(o3w5W%H!5RSgOC8Dp literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/angry.gif b/images/mood/ibrad/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..a38492bf0a3e5b044475867e7f21ee225966f907 GIT binary patch literal 154 zcmZ?wbhEHb+Xj;G)W@DcaF| u7MUB=PEBNCcyedu<%Ng3teW55`LQ|GcY=7Z)>e+dz9|8>lKyc6z8Xv=q2ap>L=!9<|d|RCUbE)7o{eaq^2m8XO?6rI6{RL+&$eC z!W0bk49t?ak}4H~GSf3k6iV_Hd{Wa&6oP@KlqVLYDtP84>v3^~8T2tc|d-uLQ!gZW^qYs5zvyd)S}|d{5-DGyyT43g z7lqDR&din&q3J9$d410L^#!-Ln7p>1lj_DI)xJBHW5yH3*_%|a{FKpI;m??Gy2Nys zL84z|R;dtn)3q-CyRgyY{+iO*Ii|;Nt9J%^%vyA8#d3o^>ksWLuwBrYbiGLOviU4e niQS_40uTD8$Gmg$Qop2>YF23$A~NA@LgJ3Lb+eN!g&3>>wq%=c literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/biggrin.gif b/images/mood/ibrad/biggrin.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1509e17e9b2f7e977856a5975201c66d23e0c50 GIT binary patch literal 152 zcmZ?wbhEHbp8*Ld{$$}~U|?j>0f~XsI&j1?Fms4_ zEJ!%m$igbXz>uKm+|DAx)*%tN(6yU|EzBe$puweA&bjN1MWEvG$s*o*B{w!abZ=1? tJhVpQlY+-&Q}byeCykdMYUhdG^@hVx!=+O?vaH5(;xhNyj7&@n)&Qe>Eu;Vd literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/bigsmile.gif b/images/mood/ibrad/bigsmile.gif new file mode 100644 index 0000000000000000000000000000000000000000..068670079a9f732c9632b0bc9a7f39a157044302 GIT binary patch literal 140 zcmZ?wbhEHbAqRgR zbx^Mgw&-JcI`h!Athu*0ebUT(Be^T={OpFt0t<#iQAd8X)!pOkD$e;sK3o?U&#l*maGi$Cz$ibgS z9n`CWE&3Q#XS~i@w&v;4H=227QP0<<@0YsYD>CO~$I*DU>pxRWrirLAF<1itP#hrU literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/clam.gif b/images/mood/ibrad/clam.gif new file mode 100644 index 0000000000000000000000000000000000000000..879aac37be26bffbc52c172ef040d9b9fcf78bce GIT binary patch literal 807 zcmZ?wbhEHblwc5KSj5KgpW)2^|Nqa-WcYuE;s1XIAOLcKq~d>WKi808XU70nBRvCV zMv%}?7ET5RHU=G#Dv)*tX6KAucm5fi^32w?Nbc_Ze^0D5K~jt_b6rb@NY0;y8*;KM z)@2_~SZ_OP!Sl_6tQxFt25)Beolr?Wsp7O)NUOMe?+XP^kh!cUP|c0Y*cJ7!&+}!+ zUbAzd`bVUuI;MmN1PDygI=S@KuOpw5CzM1#DcyN`SHgRiVvb&05#D9VKT2HhCpdhF z?T+ zg9oF``SYJb1axM~HGIq5$>rC(s`Ta^yXj5(5;Nt*w`8nm$#9` z3@!#wu@G5NmQZajhkHVYnx?xjtowE9rq*uZpPP24RR40l^!|B`n1Pi5Bu#*$0Fl=G ziAif4#29=wTv^OnwNEm^Qbhrjed-S-KUvErCKYtCmFf3dqScPobI?7 YxPjpgOc2bR9=q;X8FYENGBH>K0A}MDYybcN literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/confused.gif b/images/mood/ibrad/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..684b51c98545b827ab9828472b757eb4c35bfef2 GIT binary patch literal 110 zcmZ?wbhEHbCMz|5cn;)CQJnC$PQwC&VkT$rJM>-MC3 zre}V5@=eo>3d?&{xYgr&)cTgr9cWgFjxZs<@F?4 literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/dead.gif b/images/mood/ibrad/dead.gif new file mode 100644 index 0000000000000000000000000000000000000000..7486d10fe7e1fb671b80cdca9e2881d861550e96 GIT binary patch literal 890 zcmZ?wbhEHb6krfw_|5$GjSWM)=hJ_3*T(Vv@76J#3baLn#ZCNof`EaYeY}Or%OOFpvR?&}RSs9e# qK2_FR&g93$1|J6IqB0c?!R6}gt=_CRl*jiDC@ u-zIT2#-e~5J^U5ZlAh@*?vS`;ef_TG{9W7cMe^(Xby|6zt4)J}!5RR}uN|@g literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/disbelief.gif b/images/mood/ibrad/disbelief.gif new file mode 100644 index 0000000000000000000000000000000000000000..43cf2125e64d3d306fd2a60fb425c2e4b8cda9cc GIT binary patch literal 1264 zcmZ?wbhEHb79a*vAp;NmU zYmJCOg2UlSa?W`^JB1dXnkE@4HD$)eWUrZ``Bgp^LMey3*s}R}II!6ehSvtGEgA`l z?yY=`3>_X0OI-U|*mx9Heo}GomyIvlqamnvwoNi!YRyW)#7^eZPYQ$kx z3@)n{HMH{S3Mo_wGBk9s*ffRQxcJz8vb=s1i$TJHlhZT}+j=yOlAU|B@}uUQD1PiW z)!uy470E417iV)8rujr%TyUY0krA8U;;>lAqEjL<@xXyD28M(y8WR;7dnE0fY$61f zcur<><&$72N{||QjZzTI)TlBvi z`!g|y5Do?pb_Nw@hW}a7|9vd~yBPkr*ZyCc{!4=4f(XNZCGP)mzIrSS|5HQ%TPXkc zwf-;7oWsT7z{c?Z|9^&2Fd71bH3SrYvM@3*C@|=N90;e+964ARA2c82k!0YB z;b3S!%ps)a6R_jLVKy!)lYoYTgeKN51-qCl2?rS1xx~HdL|!N|v2saRNW4f`(8R>b z>lF8(;(ZMJXVzSckb^&u zI;d9#Tl6ug&QRQ)b@$m!?b@!QIp-^SZks5ad92Kv?sWAn>!zzls@`0}j11NQS42f# literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/erked.gif b/images/mood/ibrad/erked.gif new file mode 100644 index 0000000000000000000000000000000000000000..d837bb22d4c4a3685d0e265af4f20bfdf183d3d8 GIT binary patch literal 92 zcmZ?wbhEHbp?6zfb2mtH0YYXGfc9!>xN literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/flirty.gif b/images/mood/ibrad/flirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..c9241e8e88eb002afb170c21d901ad8dcd3cd9ba GIT binary patch literal 923 zcmZ?wbhEHb6lV}%_|5RZa zAr}Jwe}7o8U`azm11JRpQ!|(X(m)mvDE?$&WMJT7&;j`ilqVQCDj38K1WqhaU}oSD zl#1CgA;GbQTgffNVuRA*b|GUwofi`n8G02MV`6?3G9Kwvb?vj^*tGOix4iJFDVas7 zXV`cd9-QekR&(#xDgE^3=H_Sq&F1ZVUo$T+37YFOdzQ#7s?HTH2qoY`WIA)!g$}7+GEWar490w~@-ure<8ciy0WK0g=}sl>h($ literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/googlyeyes.gif b/images/mood/ibrad/googlyeyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..edb8b8913577d001bfb08bdefd7997d81f5fbe81 GIT binary patch literal 367 zcmZ?wbhEHb_b3la zGZ9;^!h|r0g@KuYoq+{t5SIam!m0^Zvb1#j5z?$cX;!c_hXISD_KpQ%lGr3U13Va< zCPYMZDI;W&Ob+l6WSMd0o|SnYLYf(9GAGz%o`4gQAnC5P4aB|Hr&sr2lja6_Z0eOP->2^c8LR=jQcTSN literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/hot.gif b/images/mood/ibrad/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc43735ea707b2b7ae4d1cc64f90967118e0ab0f GIT binary patch literal 1793 zcmeHGT})eL7=BOB>FL+@ocaO99SYHNDhNzQ3WKy2F50eiY%v6!QH;c#GNQ-~6y1dr zFIsviIP2U+O}31ScC4lsYf`c`>BUGWKi!O`DQ4+~F$9PSyKCbO^QwM8RN}pNd-Gm> z$@@I-_dL&g{({G5_hP_sUtj7ofhm)39SdVVb!>Dm^RE;=&ZOFIm%7v<}Hs7s4woij8>LeIL;5Y&{M!+5g&X<&S4eY3!IjV$yJ1=*1QNJQd_?&YVx zy^u!BRuvr40?pL6I~i$T`WF2nasQoyTsB)hB#q?%=ko7ij?!@teX|}e1l9eHRX;Va;UA~MpOdKzDIIBhsYjPC4o7Zb-P1kdL z*)tH(SfVmz4tiMqD-2G}GX8q&4~EPa-6!(I08R456DRr)Be1)>xf*1}2F1I>`scbQ zdaoh?s)m_BUkwF8rJ`$%B8J9r{cBz%h?osuZ~s8$vpNi;`dw8ZzHa?=3yv{kj7lu*vE)V=0ou9T$FFhs!>0wkjBjF~FqPx~^*)NGC zo8#3#UwiQS=BzGY;Ev2AcW8q)7N~!)r_q>%=Xr+FuMHs1A_K=->{sKL;VGIBO literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/index.html b/images/mood/ibrad/index.html new file mode 100644 index 0000000..2a38ae7 --- /dev/null +++ b/images/mood/ibrad/index.html @@ -0,0 +1,84 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
alien.gif
angry.gif
asleep.gif
biggrin.gif
bigsmile.gif
bigwink.gif
clam.gif
confused.gif
cool.gif
dead.gif
devil.gif
disbelief.gif
disgruntled.gif
embarrassed.gif
erked.gif
flirty.gif
frown.gif
googlyeyes.gif
hot.gif
laugh.gif
licklips.gif
lonely.gif
loved.gif
macfrown.gif
mactongue.gif
macwink.gif
naughty.gif
nerd.gif
ohcrap.gif
paranoid.gif
rolleyes.gif
rollingeyes.gif
rotate.gif
sleep.gif
smile.gif
switching.gif
talking.gif
tongue.gif
uhoh.gif
unhappy.gif
upsidedown.gif
wink.gif
yawn.gif
diff --git a/images/mood/ibrad/laugh.gif b/images/mood/ibrad/laugh.gif new file mode 100644 index 0000000000000000000000000000000000000000..7204cee6fb9832024552928726086c3bc51245d4 GIT binary patch literal 158 zcmZ?wbhEHbZjIX9RU6|;OLz)99og6UH z6(S9GACkERJTP;)KsItPZ~;vP*~o0r!U1*(R2*a*rZ_v$70h6Fuo^HZLhS(SV8bcH zic<#UC+wy{e9H_82?nPQgv(gKE(XgKaG=R>!%PckP;iF$AM7?(2DnT?gF+gT3>!`v ccAPRC3_P%~3Fv@?Sqda9xnbf3Jsb?y08o=w1poj5 literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/lonely.gif b/images/mood/ibrad/lonely.gif new file mode 100644 index 0000000000000000000000000000000000000000..137889c21891f0ad50751617d681268aa2aa084f GIT binary patch literal 348 zcmZ?wbhEHb zOixwF%meaM6^c^RGmA@7i-2~Nr4|)u=I3#h<|SvOCTA-s`4^M``Naw~2%CY<%T3KI zQAjIF%uQ9|Vo?0a!kEIq#GnK6B*@ePF^Y*i4GUr66K*?p0J7Cy1+&DmnK MA$MU}whwS0gZqn%-qEE%w#UEkc`Y?g|y6^RE6@yVuj?Q)Wnk16ovB4 zk_-h$s3HY-Pd9}y1p_@xL$0Jsg`mvzj1q;Cdv=W72ppoT?MX3s&dC7VVia%Kx zWf_$E$G2qG*XgSlV_kt@4fMUD=Cs@1Bxd zYTIA~3jDaMGF$W6*iYxwPVPpc*Iv_1WtIa-fI!P$nd(0M&A>4L8nzh&ae5@8dhok-o|Lkz2fe#ohR3QXL^;fXSQ~Q pQ(vBsWd8I&8y6j(6u3i6#K}uXH>5Uk>x*-qZxeUlpUS~t4FDs7K1Kil literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/macwink.gif b/images/mood/ibrad/macwink.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf7263046b8c30a788554b4dcae3584b7806f3e7 GIT binary patch literal 113 zcmZ?wbhEHb6k!lyn8?8J|NsA)GykWhonc^LQ2fcl$ONQyfEXw%!oa}f)Y8B5^xDS~ zC5vx$FPB{OTd*Z*0ppzOjmZ&3%e7ajd^%L2TKe9wr8B0K^k2AOHXW literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/naughty.gif b/images/mood/ibrad/naughty.gif new file mode 100644 index 0000000000000000000000000000000000000000..40d42724f6ae2618342f0591411ebe7b3b5f87c6 GIT binary patch literal 343 zcmZ?wbhEHb$MU}whwS0gDY7$=Fw;xn z;)EHQr8tc;fw>B3)T_OWCzmHkdDKl~Td;DMt4ej)K?9A2Gp_y8seWyDszz=#+r_Jy O3OT(@c)drWo2&s%Aa&gU literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/nerd.gif b/images/mood/ibrad/nerd.gif new file mode 100644 index 0000000000000000000000000000000000000000..3765f9734cb764fc7b48922a35c451a0d5782345 GIT binary patch literal 139 zcmZ?wbhEHb;K7+SH{!~H zpGO_ktAZ{17(^o!cW1r6b?W1_b7r|!kKRUZ;(c4<^|r}2lzoSeZma%DXkt;WN_U=08S^cd#= literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/paranoid.gif b/images/mood/ibrad/paranoid.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6f33f81fbcabe5f529e759766485ef19c422bd5 GIT binary patch literal 657 zcmZ?wbhEHb0x1Dfy=NsrXtBO17$dY z#xk&Q1u!VQnxYsm!4Zda3s9Qj!UU+fU_T+5E5HCVR}$h%76uNmxf}u=3N1X_?{R<~ z3YUaf%3;95(6VIvGl(SEe;_lVIs<@KvTS-Jfbb%%oXf(%3=AMg^=5Y;napRyv%HDCdnE7AZpR}K_NNM1!T7a9)m*c9lnM2!@93J~b< JWbI(E1^{5WZrlI> literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/rolleyes.gif b/images/mood/ibrad/rolleyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..d5e29f5249b43644303b028c0ee55817bc783907 GIT binary patch literal 1784 zcmZ?wbhEHbZoX@_SDtLLp*Ia%ps4_kiN8BGx-|5=>c+k7Mh z$g}IfAx1gnJQ2xF37!*GyqPpA10SE7BBi@6r=#%Mk=f#+kM?*3rn@zpXumtd8JKpg zMU*$s1-o65g#2|e;draGG9N?01eKE$m0X!3GAE^awQGk?I&(uH`S>g`^;bMAFDtsX zTG;+$x%D~8X*MtrO?C(-I$-nJsBJ?tBm)VilEmYE(#la^ZUijxY}OD@y7D9Nu}6=1 ueBT@kLlxgi(xTH`A~!wq?Gi{o<`W^9dZ=MEb)Xeiqxo!5mLW7q`PKjpS}J+~ literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/rollingeyes.gif b/images/mood/ibrad/rollingeyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..592b42a130618007f131debafa82bf813deca55b GIT binary patch literal 223 zcmZ?wbhEHbyg0FZS!gznJi)CT31^_ifIr0Di literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/rotate.gif b/images/mood/ibrad/rotate.gif new file mode 100644 index 0000000000000000000000000000000000000000..a743173c82fbfa879f7405953d570a22971ea91a GIT binary patch literal 982 zcmZ?wbhEHbCh9#njrzR90zoi=ZD0J!zF-Bx{>K z_g1uVAWMP_;RGAfq0q2r^CMm74KWdoNtsDg1W*h?s5=2v*A%sL<8j8Xy)o|drfaw$ z%wqvMiUVw(PykTfmZqeWyZ;Nb)*UeG3PN%_D^M9b#99Fk!9#n(;uydDQ%H-wWKlZV z(iLGGLY+_mgJU-D!7dx!7f~w`@1=RgA{hs=l?7-o(2D^c3aj_tXp=&i0SPCN7lnY~ zy=-qp%Y@wwp~owyw1p-knSoFy9B=}t%;L1bmKWjyl|igg&qPo{f(7VskX=9@YBKDd z!6sAouOXCEE_JFCigBz!Wsul8q3O85B3n|ALHGsd^bfwWsIdc6CujhS9nl9t6Y{48 zGjv^kUMh(20}I%D;5Y=S+FQ|tH4cRWI)J{nNMavH)AStn4@?QsB8z*gxwrd z$_s_WqtZlCJP3*NGuf2`t x^B$o)9hRCQsq~EM4T-D1k22S8;)hmYQ&l#UQVR-zQ@$OxQJ9ikaTw%C;nc>nUh64u<96rpj zZy&?9Z48?>F?4k?m{sw%gtDu;@SsG_2nq9V6~ zf|!B=pS(PSv^0a16t|=#x41Zim>2^;KLZaB!%zW=KUo+V7$g~VKn@1Qi39uI2FWHR zv!=H8COc6EZXI3*S$PHq5xdTA1`fu_bEbAQsjJSHbmN}P$ToX2zXLbBTbr&%liuPs zJ4+#6J`r(Sn>J_R*?h*lOj0ruhTMYAhh_`72+ZL#I_tdMQkeU$u;sM*YLW^n+d4EA zpSPJ?SlgQ{))(btoh+vLJ1fPa=z$0`;~WW=NQVa;hdr;! o6jT{(Ok%5NkUDUof@`6Z<7bJ2SyvV??e}-;IU&-dA;4e_08%}QlK=n! literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/smile.gif b/images/mood/ibrad/smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..603ddddbda6d52988a603e467f7b5e35b3238bbd GIT binary patch literal 93 zcmZ?wbhEHb~%(;@m6eN)|FRS#;s#9sQ*A478ZGMq8PnPpW6>sOZGrrRnMg+{@ zz-EkbzzNNUty69tu)G%gf>B6eUW#ei?N@BNIrColY~Ft3)!OZro3TE#wn_2=mqbpi-;z5k z9v#lHn7&kn35UNt8}~MNN$=vn$x@@TW9r=uF0JXS6y7x5@2N85yr18-O($Nrv?{hh zDb8a{cjgRnU#$Kz7U=NQ-l1^ED*wlVwALjWDNEBAt!mqq;C(9f&$-f5*WUcRJ1hQp zTW4T{Vkhg4hb0DHURcdB5@2v#Jyn4vbLEum^AUp4+%&G0R`%87W zR$u0qIK0DSmoK~f>j^z`v4)SafCtbRMStyre~blu?4b;fQRO)y^85otydHZ7!xEr=DFo*-&&{sCwCdw^|FrX zpV#KC6y}%c@eL7+UtzqtbdvBCRjjdP63}4Tx>vkqulBSU35FSJZ7LSCveRb@iWanONNmtx3X;s2+vTTw zeBG+bYunyDD^K6O;cBMHlF$^%d)m#5YiCUL#~NLR0Ul6u*ns9Far(&4=xbWFwm@@V z(TbI(-yeN@aZV?uwan>imt@?5=9xURv4)RPfCppN+!;;4ydJI2c0i;r$+I&3sps6& z$JA$CGwXi-$#0)xOu(g0TYM~o+}uvj=$VN<(y3Nt;3;~xO$Qb|>w!fN+mxjtJCjeE zpVrYmN4j&iO}`H`#t>YBY1oCZeLtC@qnVC1jPaI)+om6fn-j7-gcD?r7j|<@@CDDd z>FcXcpVtt|N$p%&wsO+@X)KvKXL}T|rb1wJAr+};Mf0}l=c{+W0veRI5MW-TM* zN#umj;}@&G>qlg(d2_aFOnA%871=X02y6J@cTPIg9M|BVc?)8-9&bvS(LjcC${&H9 zqwN;FHo{R^YwE;WqovqOF#N&XzG>UbPrJm|lydl)j7PK;*h0$2jn;e70K?Z4ra=SLI)p32OIrX5Sv52=8)`&O78}ZwptvGp4KZ4s; z=$wvgsNUkAXJ?3bdkHXND-rRVWd0mslB|F}>#ws$s@%cYO~RWyzMXouI(_yku`ZU& UCxZ^ggL9b&w4K03h4zLu02Ej{^#A|> literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/talking.gif b/images/mood/ibrad/talking.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3503efd250fcf0e6b1ac1e8c7757402e30638e6 GIT binary patch literal 819 zcmZ?wbhEHb}o1}7vT5?~i0nPh-$ z5|TLiHlVw8)CQyog2%(ag%TquEwM1LK+_DX0gGcQB$a{F1~X8G6R3oNg)4wT;nfty afC-K`q+5W}3>PLiBS|BfE5HCU*BSs~U1+TU literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/tongue.gif b/images/mood/ibrad/tongue.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b36c3d0ce24eda2a3d44ce4d46bb3b43daccaac GIT binary patch literal 338 zcmZ?wbhEHb z$e;sc12yn7FmMDgFms4lEJ!%m$iXbaa$v$k#};NOuM!J`M@KrDIjpvDBqX}G^4gX? z(fG9J$RsuMGM}B779X6h=V&Ej(2(ZQYs`9MNk_5D$rcTHwU8f1i4I^(BvCE#CfAZp he>5hiy7g-2hdtS0_|UJJlbH!@{scx8Pf*o-YXA`EY;XVo literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/uhoh.gif b/images/mood/ibrad/uhoh.gif new file mode 100644 index 0000000000000000000000000000000000000000..1061c93107384611a5bf903baf68e6eb57d78ad6 GIT binary patch literal 1032 zcmZ?wbhEHb=@u`q-Vg) z2=u(-PZm~I1{MY#P(XmP2?IwI11EJ zaWUa|tF$tcM8E`J1EHU+0Je`-7U0Wr2lkS`de15*m z(pb$U%OKGKVqFTzI%Xij34{zB(hQse5()tdjttDKN-7Z>79MUFQ1+T*A?N^A4|X0% tJqH65P(43TJp)jE10zs9i+}*w3t%%@kkqgXNO(9TI5IJ?ae>rW0{{reKo$T1 literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/unhappy.gif b/images/mood/ibrad/unhappy.gif new file mode 100644 index 0000000000000000000000000000000000000000..25a218833cd275bfb7d05363611eaf911c8967d9 GIT binary patch literal 229 zcmZ?wbhEHbs3>*Rs92^WB z3=CiiARovA2?Hr&fZ|UUMg|5Z1|5)Mkev>!NedLZcqS>F(GYWdy)RGEAeV{Z?A|S> zIS#IG>tbEgS+6_GJ_O|n1`baKRt^!41qlZmIaoz(4orCH*uo&?RbpYV$hldJpF!b8!J?zR tlIm4FnwuUTnxq`KY)^)fvd1(7bFC21iOOCxMLq3&RtO{?YG7cn1^{NDF5>_I literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/wink.gif b/images/mood/ibrad/wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd57f1f90dcca14f50a437787f0dd512d5d648d0 GIT binary patch literal 970 zcmZ?wbhEHbzCAXBDX*G&&2Gb`oAuxS zPyYBn^3{Ly7k`ak{4hFxQ-8-1qp6FuKKw8I@Za<13xhX*Odh;9-h0kKMwavA|LT*s zjo=5$eEx#!N9ScftN$%#=?YyjU2opdmI{_ zm^s)5%Mw;N9&TafkxO`Cu)(>tjaOW!;D7;>d#kA3ia#43HlE@VwJ5u>VL>A+kF-TZ zz|Mt^O-;NmU29G(IK;-zuTWMnVdB9iPGJd?3l)jU?d;+X23!jZm<|Y8Yh0+dNOEdr^XKE? HV6X-NDHU?a literal 0 HcmV?d00001 diff --git a/images/mood/ibrad/yawn.gif b/images/mood/ibrad/yawn.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b8f4cca568a0e14b98639cd5fcd4a18f3e5a384 GIT binary patch literal 676 zcmZ?wbhEHb<9Z0EAlS7?ma_wu2*NDS{F|WBx8!Rjk}5W!3z)%p!iQC$!xHKxXjp)>fn^NPT@3OIC@k23GE3JeA&i5B0!R~!L5C!U z1Xxc%i)Je?io3aB?lyqB8_Cy@Aa4N%Im3ks*u#xSfB_P2Ki4>+1S~wr5ndC4#1 + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+charitycam/
+classic/
+ibrad/
+moonsis/
+neko/
+niaha/
+nolegs/
+opiummmm/
+palefaces/
+punquinheads/
+roshi/
+sam/
+square/
+threnody/
+xenia/
+ +
diff --git a/images/mood/moonsis/amused.gif b/images/mood/moonsis/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..9def0c51a68be9e4838a9b8f23b86484e5cc23b4 GIT binary patch literal 448 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/angry.gif b/images/mood/moonsis/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ecfbc3c256535006c30a4704d04530c66224c34 GIT binary patch literal 420 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI<20Yw`N*?*9oIecX;o&oY;Ct+raTS}0FzKSS<2 zizWB>PSQJZftATQNiRUaV&cL0g_Z&;>Bp0U4NhFzaOP#1!#5_&mJe4>s_x#qsHFIH z$?lyejJsYgx&5ChK+dEjC%4|Du}ZtOy~8TDNxCR(LOnA}nSZx%X5WnR_L(t_lO*S* zOe>$!nd3f3a9)h{^cj|IjA0o&H?M7*%CgRHgPr?E2|=Z=-; z&D=V>`QV>Y`@9VTF z-zHfX_W8Q_%7+AsZYXS#((8GAz?k*;mOom}ddV^#3L;ZD+WHqQc_1M%&)=^>(;#Ne JLiZa&b}TyoVOu1M`p3s*tgz0Pf#vF0=tDd&~Qd{K0V6_d#A zVv1(7ZYXGC9zy80#KNrBFi3fF-N=j?esdgw4kQ**BPQPRl4JAGEv z-VuyHk0gH|C^_a_bp2|asjohzMNCy|3PrA_;h9*wF~jlb^pdA2bDwv5V)pq$h153h zX%`vBt7`|q{co+pRD-hS%XnPvpkg4Q=ESB+4KlB{xQ?{pXVzzwKJ^sc+N74Og!lIz zK3Vzm$BW&yp1Zyra0z_rZ}op#bF)c=&GZl!q;)#WBwK@|R5BCpYc8;P$;6uvu3dL- z9@D&m)m6pS>l9Nqzuvg&MJ`&2&;3;^x{>r`Y6wM=@^5z{wS^6)_U<}~i)tiaPl4XY zIxl^h%4{eJn-fFU zrcEKGZ@0v!9arZVvKP|KVB>{6EjTeeXVUyNxHM+41jvQlAQ(&nr?{E)7@dxI`TCN1 z&s*=-;#0D=;Hq`bAyTTA3@-XAD9>z_cKK=QYPN3JvM}LZ>{nV<&8n~Omj*W=abWLn D<+?(X literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/calm.gif b/images/mood/moonsis/calm.gif new file mode 100644 index 0000000000000000000000000000000000000000..5964d613dc90ea883ba98886457ca3820841e6a3 GIT binary patch literal 404 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xw8ht65QAbuT;pX1)YW5};nf;q; zpZ}Wodu^0L!0VYDjLiw2dqg?eo;n1CD7K$`$`EbMw>a=^g7urO2?fFQ|LtJZ^{d4Q3D|#jux5;{xRI?N(&#nzlm6rWy6}aO)Gcp zNM_Bs-Q#lMVihy%lgSGeDy}@cK7G>bRR0(6B2rQ#?myu5?+gFFmpSm9B9}++xqVVA z4k;WiNS!5L&(oD)n6muP!EP%(rkfLhp#ln&C{UpAF-S1*0U-mkp~kMu_nJ;zS6OHg vA2Ijt9diNJ7gM{o>b&~3c7uVNvrhHQNrArtEcUY>4(G7r*_))s$Y2csP>HBW literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/cold.gif b/images/mood/moonsis/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..f98417ea6c91f87c5adfb39b0e86419941c164fe GIT binary patch literal 905 zcmZ?wbhEHb)Me0R*v!iS0xka;mi}ir_Fqv^QImne>Hq&^28JmN4F7?sn&JN(hW~rP z%D{x;e{Mh5kYH!W09PYD17=2`pyE#!PId-f1|5(Bkg*Ib|2CZTT)o%g_1WFa9W?4x z*c3E`rmYcK_TomB{v0Ob+`|>;=I);HUR;FF^gzP<3PIImhNF`#8Fj>X+>DL{c&rS~ zF?)TcYPrwrioJHfd8Ralp2@3EXWQZ8xBm7;`AUV_x_alD*48|`tj@Y_6^5#g$na^? zXG}1u;_VIhTd=UZL2S~TVs51w)24C<8L=%|%btdD0TFdI|mvraNU%2S#Ch4qg4D2k-&!00fv%FE-{lH^B>ucU;FJ7>G zWnxmCB_GDXwIbO)VgA8d7T!~l2bEkJ88~ioDnt}4I?~MgX{!Rm#|QgLn}pdbzN{!r zZs>dU;qLD3`VJ?1S*_R2(cJXZd$LjHxsuAstk%qI=T#+UB`o(=lWAP$68`1h$$7>% zSQ%D*eiGcZxkk-5v$P>}dOWA!g0@Dbqowidy<{dl&lKGx%CRL@t7z`cF7?k6XVg6} zvGoZAF01vtu!>=x)Wc(YPv3A#Hkcso0*)0{R$Q^N9~dig2?-2~loWT)TrRrq)r+`| zb1rEYOty}D`<;`k_DJ8vcAtGMw$HtfuxQM>#Fely!JtX8?a{2OWqacU4_F`byK}&} z>YQ3MPk~>e_VUHIB`Q>^fzeWCQK`||*51WyDb>>3+aS{4J!NV~zWn64n1zcLPm5Ab zkI7oKdZ}=e!t{koix)274mT5BA7vT6xu-69t;j?nwdsm6vx*NLmOQRrb70EZIp+;8 zUY>Pz#u47*(Is0R-*Gs$V&&>JXYWooe8{Z?jH9n#fpPRp>CoH!_ba)cWILRnXUoLG z%E9r_huMLF^}|c$1sfI}>Jn!UW#Xt8_>mEqXg85LYMakW zBL?ppc3!CviH2ofT{@*)y(cfHpIzYG`pu-ud46NpS0NAI1zXZ*PW3OmwK(g7TCmbD zCL7V#oY%D(Ms&U^+52Uc@4)!4r~6Fz;3?>^D}X%Rm^ as>RJ0KFt-eO2YZ!X&?RRH*FM|7_0#t3w~(; literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/confused.gif b/images/mood/moonsis/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd777d24d1f6a1209d7556296985a1329f0aae4c GIT binary patch literal 682 zcmV;b0#*G-Nk%w1VJ!eH0HOc@00000g#Q4g{{Y7SAt53E004y6)&KwiA^!_bMO0Hm zK~P09E-(WD0000X`2-1C0000i00000EdVV500aIAy4?OS%BhI8?_$aUF(61ZUucY- zR9@n;S}mkq5mugVyUJ#W@~2+~wR7BhI2jEn%=uuk6r*VLRjjq9Q#;*2lbPsLtTJ)C zSGUXvjPOYs|2#h zxD(Nmn6=oq%EQLqqsfM#w8rGek=u;p1K8)7li_Xwy?DlWyvWU!DCPZ~R-@G=3EH_sx@a2G;NI|Ya+(MB4A ziH(o|03rDV1x5e>04x9i001ojEdT%m_6WM%{xHf(tGzhu&Ab0#D2`-lo*BWY=tHRN z+cvN~(=U7D`kn`Y+zvnp3)bmwc9$Wttq5 zYcP#4b$J4t6r}?>s&%nRg`_}*FRZk*s;v{HvaqauvaEx+ZB30yzpezUe~xU5a>>(o zaAJgJ1&*U2bJ&T_l8lX1a8Y~bREe7D>*h>+Q}MA};F4d`ru5KxjIb%U0#|@K=@k7i QDDT<7e-0iF*^mGLJA}45lmGw# literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/content.gif b/images/mood/moonsis/content.gif new file mode 100644 index 0000000000000000000000000000000000000000..ede114b3e86164e1cdef53ec176bfacfd27baca1 GIT binary patch literal 475 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI<20Yw`N*?*9oIeJPpqBoD55;k@F_ZL+P**h8f|UzNnMM=THvc_X(!p&%?oY|h0@#npZ;c5K?b)u%&$+eYc>2fG889o)6MqH57Z&#BW`HWaZ1&rFcZS@KKO z@ROPhOWtO`wUHl~IaIBLe`VfrXA68hftM30WOy0482A}vfFV=N;dSd@!v?d5Nx`=y zOxq`Ij}_Hmb<7ZSRNS*tSg6&SBdcZ6I)gWgacj*r-bEdrzW&4$&MJMi&p(^ImU_j1 ziHh;s5x*`%>X6v!&8zi$1(UB$T4VHO(fL<}KN}i$pWL3F#MqE*AI;Vp#?02!6QtYF J8xC}bH2@tGzghqQ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/curious.gif b/images/mood/moonsis/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3f0b18172a7edf3915994d88ee2de5579070148 GIT binary patch literal 627 zcmZ?wbhEHblw;6jSi}GZE&myo{%1J$Ur|xu2c!w4oq_o|$F4j73{H8j-fQvttp3Xj>>Ur%o46NFda+|sw!j`)K?x_j zeC@;s%#3H1CqHCqUes0bTb4aQRr|`HrxPx$DM~slTYOWe$Sk#_`2L2d4b>|eSPaa( z1-8rXi-}z-_vW={xu$tSZJT3Gs+otAR&ls?kx_7WKz?>zW%y*?Zjb4;`QbTEa~TsR zF0Sgcs#>;u!u&N=tCps1SXJlLv31@0@Wh5%t5m%u#qE2Vwr{9qZA(#{Rm^(6c8*~B zi3_JI(%W4x#@ugYe0uk0joHH#+oNfA?(h2SmwPLIU4BD3Z1H=&&mJs$t}{6?f&I=J zh3fZzAitkJVad4myOwjsKVikPNcTP!^J({A%@mqbrK@{fzvH0g!XGws)SMa(O2j%p zKL3%U#jkL{T}Ev2;-`XLqM7@HofH%n)a~Tn=y-r{M(_0v9!e5Z_MTo{Aro=^XN5pO zwMY(gdqciJmT*pK`-Fz5ET+1)3GMZbd{d_O&1h$tnb$4b-_}22(ITcLfpr=Sm=|qc zl-w0uyK>W>+#N}!+bg}PNZqD80 zr-xs>eDE;!Hq)#U@^u2+t>PHA%PJ(IL1^uFKs+#}0-6#}AixYn-NeV{0e?O;^3 zqv9V+$u$q8IZ70m_?`>%Oj8w_d_yK;;l{Q}w@RY+UpN_d;cH#*`4_9dXAA9nzggjj z#?=1jj(4oi3*9lOtkU)`k<4l8jCauRinFik?)IBvq1@N3T4|taU)*LhL8nt^Ua@-= z8Iw~nQHN^ zy1h|>5flWhQK&)i1QG-KerW&meD6 z-Hd)G_YF>!%Qr7v*XZuHZ+-is2^C%Td(&(fYcbTvF!7-76!5RQ!r19tg literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/dorknerdy.gif b/images/mood/moonsis/dorknerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..91a522a2a8c447d3f567ea995244d9a05cb282e8 GIT binary patch literal 438 zcmZ?wbhEHblw;6jSi}GZE&myo{%1J$Ur|x>Ur%o46NFda+_#w!oUy1dbnj z*0vP#GfA~6Ouoy~{OGjPmY;piD<+8+{VF)IBFs|pUZ2HUG0Vk9du*J_CWO6~TO}{B zQ_P(;-(7#lCilvqN=-ACq}H}J%d}Rl94*K4EbW>KZ?1+u)|}ZrEUX^6)0K_u=k+bu znx9kQsNCG%=NOT-F^ADYeLCap$hngeH*My1+0ih`!6sryl~F`TU2&6UUgCwMh)d1e zO9N-sr7BimWoErsW|Wq0_W0V1*tk2$AS~-EMV6*4J0R9K79hexb0i&L(O8@`> literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/drained.gif b/images/mood/moonsis/drained.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ad9daf2d30a62ded8d7f166d23ec979d07cf11a GIT binary patch literal 467 zcmZ?wbhEHblxI+8Si}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI-223Yo;KbMEr7#+x2)Ndhy{ompBH*1uH}a<$<| z`n$^DCc}wUD~c>1CalnMiaRl*Xs3!)@+HksgA$_!n{-O|h+LRwF*C~BtX?MbUYm_T z?`(d9#GUs)|F1UAH)D*ct4(b$jY&(7Z!InDXsFGq&}+3xuA3ObGR>x7<|OItqNT=0 z&9YiC(MzJ1t=3=WG{13c*6KAg*VUI;=Vhej9GJFSeC@si<#FPL``FG**Kk~S=~BuS zjfBfCC-m<6Fh1^6Ew*>iHa{0{5%gxMW$Rnn&#hP9Z<6|`_V=r)oC=b+*%%M5+cd6dYi3l$?1_2;s18S7g z*kbZ-4KJts+=_>*X0MmoVd`Ybr`l}PrKW25m7vtCKS!kO3rFzMX^)y<+?`4q+Kt~b$9iQ-G1Fau=joL^YiEZ`XruY z#F8^f010?T0d~Vf0U-*gP(X(QCKRxsc$Eupbm2`dg3>`yx(G%G!RUgN4hXSBhy#Y; z-N@{)&Q642qR>W^*@!w@Bm_sQ<|1`AG6a)(Q)J~7S+z5BGzg|CEi~m64Mme6IEiOT zl39|J7A8x^5rq&D1ppMl|8wsD zYQd=YY5JMugkzu5qrxMwZad}RH}0McfC7Z=7TtXl;IYl86bXdIA~8`cEtQo?BxQ<9 zk-Vy$QZ1{vrKl~fZd3{DHM&-P+wJy_PDHI~sRWDed@nOfyX*P}1;)FAAF4p&h!7m6 zSXzmbQIAKIi=-pFIWY_QmEl#~*(yTDmaav&z4|$J-gId=X$41$w-5qQ}h9;+{yXx z(xjUymar2J+r#?(7v}CkGi%hs1BsPk^m4sH&QR!DuC<4Jaw+DDI_;npBVu0rIb+&OUw_ak@zMwqWnc`|2NmuFC=aBDf(&t#gxf*<&zo9pqnsX>K=z!3#L-qpF@( z&}v=4;+{Y3T%TXrz&W=@^y{xSHl5pBOI2b_q|0MHdDfE!x%GHaGi zE7l9ARs$F_~4XaM*3v^I`U}Q<=-85BOG-a^OFJr H;N!mm8I|H> literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/embarrassed.gif b/images/mood/moonsis/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..a03592ac7e3dbbdda8bf8630a727bb3680ca5490 GIT binary patch literal 1189 zcmb`F{ZCtU6vi)5x{GY^-AdYTEeslP*ocKP&=#?2%ga~?h?kAQl~u8`nRHR4Tg-A@ z0`$u3Wn=8h>s5i#Y0#UFxe{>Jm9llUPF^IkIb+2!U|F^m61QS}sjy%45AZoB=f`vM zJfE{`cdlGfk$~(#mJG;-2tPsu5Hf%;0mKqO>;c3TKnXue`%v1CGJe$NLv4Q4?gu6x zpnZT{2CNU*e9*KEDKDg!A-xP)FJza+5Q^7j^ol93*fJ-!c*U$&0-?k>Cn4t~%%p^w zlUU|t5Xy*2896DVT{3!7#!M<8R1hu&?b1M~G1)bQT|?P5fq)i5EpF2qZCaB}OWL%Q zP3!Yv5MmgM8Ci^AF_Oh0#0f?Zp@pvXW95dg~a-82;9Gn}ow>+E+t<2b$7k~1I78XA~Ju|@E`t8BDtG$ke zzkDm+kr|$V@{Uw5ZL{B8dM&Gww>35IT9tUBsRi(pRG(U>pK0Y4cGXtYaav9%8mW6# z;)R+6ElS;5(HU-}P*#0+vvc-JV>o*7=#lh!bwgBY)%?n@6OF}Zi{2T%gQyQ(3j!IV zrBD2jR~%P#JkL^@z7!H6d3_#n^4)DC#}w6fy2k4&ox4TSzN4!H)?Y3q-_?~?y}PY$ z6F=j<6-U=T!LI2z)$?Da@e^uNDm2|w9|}_rO*_;`P*&FQ-bZ7xJNHc87~9@~ zR~)V!>aa^ormkD}`77VPS#x-QRaKf!*U|as;#>Jw-WWd;#q58$XybfAx!zsjag`J(D~xKR4ZP4&!k- z$JQLOtokrCIN`}R;}+cN+W$P%zaBo?@WADoIrZjdZiGmjxK-FL6bKVLL3p^KhnHwb z*^!VmIGElSBj^qn#HOcbrpms!pdOLN3(&|INvd3~ROViGy5#E)L5y_Vl{=wwDczpP zXo*a&`dO9bRVXrcCV51HAEn9n?mtLg67*i=$HZ=5TZ{c8HcrUf5{wQE#|4pLJP)dI W*Qm|hh+woRdzjKRn}dUp7ybdmO~dg3 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/energetic.gif b/images/mood/moonsis/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..43b88387f10e2a4d3191c39c53516e3f792ff6bd GIT binary patch literal 783 zcmZ?wbhEHbRA4Y?*v!KK0xka;mi}ir_Fqv^LQzrC>Hq(8=g!@`cke#~!~f?%9*{-= z#sA!Xt|7tBjsdPldIrplKpDlKES!=IJPbM@RUl&-SpH2o>A8BZ#p|=X|0ihlrDV>_ zShX(a^**14r-Wn|m&_9@+W*Opzlr&e0-w}_hV9%EECIJUA`EQUn-;AQcwx1WSzq`_ zY1I6t#wZ=%S!*wBsnUB_FhAo%%v`=6K3Lt&(Ofks$$mSwtBHn8}GjADN_>L z#T#4ZwN8+TDVo2eKO#2Ql(ERGI&)pX$~kK`a8GMt-Co!hxg}v2>z=}cg#`jSX3sgab^d~d4W}|WTVA!)oe;KZ=KTD5-e&2>qAzbs z9(2SPzgoNUaU=VIvYdOJMIpz!t<$(vKdy8+8o8=NSw3BU zdF`6%zi)-fl1a{?ef_HvCeATnT-mlUbK;mRS7YodHsxB2`l{xz1x^acG!qZ1jU&k$oDqO3PV!T;5K{sN~HO4<2 zMoXto6;_t4a7sIHrp+xXVA2Z~u06s@S9VUQU_U-d&a3B`L{$lU*HVML7gH7;T@kd> ztfb`x(^ai0!qF#P&RT_WT~`dvR}k#pa*}01&e3THW(eg*t@d@bx;lIM+dKOjnB{vJ G7_0%2U{_-R literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/envious.gif b/images/mood/moonsis/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e9172351baff8fa3b5916bea1e1eba39917d607 GIT binary patch literal 1624 zcmeH`?N3t&6o*ggD_HCm7~E|YxrG9C3$~IXjS*-`wcx-Oa8TagbV$a67`5n_v_&k8 zOa|ztDWo0LO{5VmH7wGFio3zM6%clX&2`|!mN|i_jAghQ29pQOHZbF0c7b^TtTwO` zV0D7k1vVUP4zLk`TLHHLjsxxjd;#!fz&+qFfx`?AD>w*nIKklpLJx!q2pbSMI8ER* zgVPEwJ-AHBArW$1gw%*JEx<5L;_-N1 zUGRFnCh-3VV4iiU(v0*(v0S<}icco3wqVaG-f|GbyK9YWZvu=J&@$MvUV~lB@ZX#} z+-n>axGpXx`yZ9y!Od1S>wMU`w9Z>+$tga_qTdA;DIRrq zovWHXtq(>gD569AQ)$7C^K z`v#+nWCro&Zr|J2K14R{Npzg--d3KY&AalX{gL*gyauo4^SSTDhNWFQu|53ZFPS~` z)=bRuY(t^lYrRNwZ+g_&H`m&6)MrOo$)J`VdSv*Mm!PR&Y^yq+KUz(?P0+$+ZgH-L z5qve`y-8yt{qfJ=DX#}ci8a)9oMX%&h3z_J)>@$op{yi)t9v>%cF7fIPbh1M31rqT z7HVJmhCX>T5UT0q$(?A7<1eNc@219<6m!cT+}|5;Bew0d@WxGf!Ydclg8z0A znyil;qkn&L)kRmoK!$(DuE}Coj~Qg2b6FjfH}9MRQbhW(fJLo3<;$SVm2c+M;vX8f z6cDA;SY)y;>cBkv5939}Sw>#e#^k<>dpmtiTMgMim5+S2%fI~Ba?7Q=7nqfeOLof# zQvy?!Cb40GoAt$Lq##t1qiR5p{yx`4ma+eStT zYP7-LQ_VwUhOCg}6R9^$`!HivUbH@5uT~OA;RA)GiqSCGN8Cn+w;O)T&QMY*NadU` zNL*rapD9)zm@Ss`%~{Q|8qrcqKA*#Fp(l;?-`Rs+5l%F7DwfDaMN;ed?v{$u($a2) Pt~4t%hLHq)#U@^u2+t>PI<20Yw`N*?*9oIeJPpqBoD60SS+-jX?qdxW}UA4 zCP(ylUe*=(@s*>oDIs#nT@Kc#4hcGnohP3%SZ@|u9QZcD`%T+~gryZW&$=!!eVwIy zW0v)YADhm-^PeqeP!v+kQp?m(k>y{<+>_#{8QD9fq+_ClN6nPkCH0+?O8e*a_$-*o z=xyBAtItxsa)#KfMF!Q|%{Q!)3Ey75bKkyAqFeU$g#;hmU*S?+yQbIY@aFX^=T6;l zdGp!pQ_F502{@O`#x^B2J@Rhdi}Zr25w89U29r}5zq@`6z2a}s_wm#dDS@STSv6RL zWQ(4>7hR-MbYN#j+S`TF3STuo&Az~~L3vr9t(6KmY*^!Qg-v(HnTPjcR|wqHC{vlR z?D^M~Ij^%e>Re3Db$_xuT>q{g$LqfZ+OoYJL888vX&RhOUbz;>LtVI8HZ7HJ7SP~0 zcmLS6;9eoFXN?RsS^azBHYYS}FK$UmEvRB{tXzkX+MMZJzlMhVT zHhb%ly{BRh9K1AZbKlb9t22+V+%8UknDON5*$XC*-kg@a_GoMI-Z#%*^xfQ@@h(h^%?b;8l@whQ@;X=C# ztKKaeQasmAIdzSHq&ZJq&w$7>*q~c8-DJT(#4= zrPbHAR^RJkxHm`f-crTqYZd=9F#L~V_+QQNe-01@{ol**{~p*V3_|fgx1VcBu(M-; ztC5}oGb2!e;!hUV6b4BK9gt#>GZ zYm06&cAkEAx_g)Q(Yxi(-(5RdpIw*M41H~)ViRc=4Oy!5MG+1>yE literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/flirty.gif b/images/mood/moonsis/flirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..1292353dace111951064477171f679ffd3a9064d GIT binary patch literal 544 zcmZ?wbhEHb)Me0RI3mda0xka;mi}ir_Fqv^QBzaX>Hq&ZJq&w$7>*q~c8-DJT(#4= zrPbHAR^RJkxHm`f-crTqYZd=9F#L~V_+QQNe-01@{ol**{~p*V3_|fgx1VcBu(M-; ztC5}oGb2!e;!hUV6b4BK9gt#>GZ zYm06&cAkEAx_g)Q(Yxi(-(5RdpIw*M41H~)ViRc=4Oy!5MG+1>yE literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/full.gif b/images/mood/moonsis/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..f708963aceaffb4393daeb0823423cc904df6e02 GIT binary patch literal 2998 zcmeH{TU1kL8iqHJKmq}G4!{OMNCYHmm;@0L8#M_5LI|=6G>t)9C_%BHK%rF1p_~aP zO@M@>2sBhs;*vwEjxrJmC{-*tqm_CnAhs%6K$(eH7MVD`pEXx=)pvdW`>*d`-_`$q z>j?=BrZeIw00sC3crTD40XY(oF98|xASWK=n>-2RCxM)Fke?0;(?Ll($jJuz*`Uzm z#UQ^56c&S$Y%o3>loX?cbr^{pI78T?DiSV9)?*=Ugr?qO=CopaImHS_3p_0JNrgBT8!owMJmj2#gs~gGO-BNErJa z8Z$z-jl{9VopERL{g46fKb=#{Ii#|Srj%Do06L&8ZU>TN{C%%SxqQ71bR!@|Oq;}k4 z@Nomp8o!QsciXzI%A$593VXEk+Lsqo-J>1)=ShX%Kb`^Pn=5aG)8CS7hxKPkJ&PA~ z4TT96F$p7A)US*BZcUGQWM~G43gRn7$!q&s#O=3SRecsE-px&^NW6UtX5+_9{mcEt ztia)zw5Vy^6-6>_JbQ=tUSiwkry$Am+_fzc$^JQXFgPS{J#P&pN64NApIf~&m6KMT z=G_%OUGZ%B^zw1I*uY{7|=OcIN$+{sd9tY>5hC{-0Pk{SUEL zQS0i9R1Nh_&9$dm6>aTG)i>%&>e;hh)m}b6v@@DwFG@gI*p6-VfikLHM5ZZFj!%F4 zIci95jyOeZP45|?yK#8Dgq-9_VJHWESH0CO?D+HCuf&rvlE_dum-z-CRzglBb?4t;pK5H#puL@@q)0Bm&em<%!9GCfa|b~ zty2@u)RN@oXs`<36Y#UgL1)eLsK|Avh5cuiJ{`$x80*ZhbIlhBXL^~bQIzce5s|A zbmihGuJ-_L1S3>BPU82vDDF8#y6f(E(ud}4^CDb`a|b;gX3!V}v!HAvQnk|hiIo(A z#vqxImd>Bb6tP)iu2fM8rYOuUY`M%xE;fo4m!NcW;ab>v!B0Z%7;vf{A9!F=*Le8z z3&R+$OI)#)O`M)lM4Qz3H;yJu8exJrdm;}k}2!!smjJCRZDy8=@WD>GMV0@uA$g%-00&)@2MhF z0=R(!0SjkE)|OK#Txn*aNE{XD>T`CusAG3_-KQIlQyf{2KOuf94aUJ!S2(;Ri9)_Aq}xcD`4gIih7>kF%fLle%FXq7j1?&Skd zXYR`L=kb&ct^qOM^<<5_o>1jS)*YA0^Y3|}1DEInnV*wXO3ME8SqxZKMxc4PQZuU~ zc5R10w6uL!^F6`ihfTdOsK&VZudT5=>Ds50^#BG`J%dk8ar2pO?SFEWS51%3~~~}Qb`0jwiv(A_|H4e z`yjTykR6Rx+F#0=86t56y(QBAP8J(~9@+WOIfyzrY`p`djf%li|8~-*7H=mZ_12^_ z%;}Ei+W6|*hAqOyvzv<}0iDb$Qd}UR(j3+mB@P1rBat9Q-xiOIT6^|{z@^rh5k#<} zDZo71KL{UKH;ssfzjq(8j$ZdJu^0Q!4dGIJds#MHC*l2AE^~>6WVJCYwwi%l%Xf^%StA oC$J9;=_crZhesGveU8kg@#WJulVyKk9Qh~4|HSzJ8RH-P8!R!*y#N3J literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/grumpy.gif b/images/mood/moonsis/grumpy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a96db52e15a9904e0c1b99f386cab399b66311e1 GIT binary patch literal 452 zcmZ?wbhEHblwnX~Si}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+uOO!RoTrXqIh<}35A#l~_7yjVF)C~8v@S8;~Gj?a=J zPW7AhoEpsq9@wzV?p2r2NS*p5?}SXme0{e`r*fk9pFa_H;cH#D--@#9ujk!wif0ae zH}m|8AKn@7_wLsVFOtb|tY>CPw^L>;?})GKay66ojBA{vS35wqir=)OjmA++0^~$=+7czN^_}O<#N2p_X~+Y-ifdt7~k}TxP4E!=LPX z`P_-9)8g^ZLk7W`)h4R{r=Bz;NjFLj^{J&siCS z8Tc7^fIc_&SatdAIYITbm}z`_9QV!Jpy`wurlO{|v?}jv!M>m;EKAq&@34?K5POhC zM=GarVg7Xwq!2`yV*)g1FVGy98l78P5AI=pnCq1qcE^cB>(pFD>p2@(_#8{)cW$+2 Uot)@l;=<&3e?dl$3Il^R0IzDVf&c&j literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/happy.gif b/images/mood/moonsis/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..49e12b2708e51b89318f46e427daf77fb98547e2 GIT binary patch literal 404 zcmZ?wbhEHb)L>9&Si}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI<0YF^fMd8yBD6y6}g<)9_gWU3=fWI5uqy>Piie|;>QTfwPoir7FMkl z6|h{fB*-uR_HJR8K)qUKv*>bVhvL=}=LTKIp!Q^^Hoc&-P7%MP8Fk(oMYATzO`6QW zQtQ2P@ua1e%crv}E}G%&w871K=c0vM_HSL&b!f78_0hv!%ZpdF_E&7#)I0S;#hxIx zl3OJ9&xGKv40xka;mi}ir_Fv%GcZsFn6%`dN*S@#h``+pQ|Kz>*rc9YK zXATg}nX?oKdO*a|wM*BoUAuG&kl4DmXY1Cjd-v`=wzucnvFdxt$=@X;{)0`W525&< z+s`#5*x50_)kx2PnGtBK;!hUVC%X4%O-=ngGlGxhRQ6)U2?96n7baQ-%5yx(F3u|{V{T4JZmOwi zWp2ys2r2F^?d|Jp51q_3b=q{Mwuu3==aem&zM`%oFut~K*~%46s~4}^xP8VJ-`Sb* z)AzEi-{n)he8a}$s}5%{E;z7%@3IO0N6$rX4`*Apx&F%8bMd#ArCur%;pX0*SO4VA zt#|KP#l;2qd0stgy>;*r`{&O>S_uV88aEpfrgLcg`0jtGg@3qrGE02?;DW-ZMN;`wWpaPa$eOjpcL&?vN=vTi>Wdldr~7Ia2dJwg z%nAr&TGs1t9C&4p+2)w8hzZ3NzXKwGTdI}cWPI`&wHiG z?|wS}*%J3sJ%xdpF=?Zy0mr^o%ipKDkob(Kq?%>Q`sZ!?2l@kkD0aen*C zPmO`W0mqlNGAb-`dd@5%spq-uK(e#c(QdcY(2(3MB0-`Db3zw=oc%S>=k!Ex9TjkB zu?CP8S|)A*EHM)s8V~rVOA9iwHHMrF;W2h-QnV5fY4ts4%sG|sg!hKfId}5THWwS+ zos>K8oraB^`}8*vsa4fAOz9<=;Q|#w%{BdnOd<8zqV_SdZ7dV|Cz%*eV~b^uoUpX0 zOQgqsPT}ktmf)4b{%vb#PH3AnS!(N&-8gdFj`7-&C2?1u-;zy!v0?irxx>%eShxQ;vM1+T;g1On-xeynaqnT` z5ayaA+%$2mJLm5Yi;u4mbuxLP6FNm$wc+uRwl&8l1WsyIIBI_VK(1l>r*mG#JZl%o SurErPW^ZQvtz!ZMgEas|SR{`C literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/hot.gif b/images/mood/moonsis/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..dcc0a4e5d2b1cc98c4e4575b4502f81429c1c6cc GIT binary patch literal 2146 zcmeH`ZBSF`6~`Z9A{P`4%F6|TjpHr^5s9@4 zTp(&HAscrP;}V1*%BCyGt!!t~0zzO#5f!a$?HyvZf$lI;%dC{K+~R)j$A0X8esku0 zICIX-IscQke_x!im}HXj!0Zl*!^CvhL=J~z3VN(3kwpz;7E2b2;}DnO|L zg#*e2sP#%KplpC5)&Sk-+5f};W&@DgbRaeJ zU~*D=YV1zI2DkOD@LzO~P|yPS?#6c6BdbAbEi!Ic(notrn(6P#;wrqaD-{_Mp5vf(c|8Q1xSN1gYYIC96cT+LN+ zJ3GTOYrm!EU?*St^)D_O7am>tB<+YfE~_ldExUcIE@Gmfo2Asq8@~?cej)dT%NWYzBWRW~mx`GDzEialT2Nl+w=z{8-fDR(#M+Q{X-L zu>K#H7^(RK;dAxl`pr4p@WL8n;uaQC9H8hEiL~sLn$jMNQ3To!xig<)VYlx1^2Gdv zkz_^%&6m!8Pg*10((Q|^1;_a~8YRI2dHDF(x1|Bv`t9CJH2j*I+t#C*eb|>8+;?M7 zRnnG2tr@>O<#p28Afa_>82(wfHaR2ApsA;?SOubh)6aa60nPg&D zQ>`Xvx~R4a8wxyhV}%`3omm{wyeA#o=&LIG&cG@=t{w6_tn+Z5-y-W9^V@@C4s^F3 zKE1?R)efQgy5X_&*^0h~=JUrehhL_mqQR>a?J=;@Hr5#e%fCo+_+=mMyXs%g7asOY zHC5d9|5JfNXkeK)j%a9~of>ZFx!8v7>-Nlxb_6C|seRF{wO|aSP~#l)cX)O;1uCmD zF8UWLwATX1gSwiac6yo-Sde+?2z%gR5E5L#KfDh;_EAR~TN||;W4|0LdT((4`Xn+q zAR3k}PtCH}n5ezzR~+BtkB^=Vvd(y-+mDFaR zn+%n@)qtZ?d*!B|Y?DiodM`2WtM?aV&XR%6(vcc0xAJ>05FKgSf1+|WU?;ORV#ukQ zAH}5K?wuQX>Ac_GNv{jZuXY1L(}l+?ELL~k>ED&dNq z2}9x&I@gkuJYV9W=NjM6;8(^!T%o1U>;IU$=3U)Q{~>|$VB86zLLa+7I9V&0`AT(S zx@GPJ;&{{kE6?zzrsUXF7Wz6uqmQ)~snb&s zgxzv#Itd9M?PzE1SoP7JdwsH%*p;+|tIJ<6idNfFR z*XeHh?7BkC=KnpZ{DQ|~u^8%nWnzweb%oo!cds#|xk?agfq1ZNg54-E{-ss5Iw3Zn zPVBfUs$E)$g!KYWRL5*qZI4wQWSoFF!a2;ApKdE;HwDE;w7Cb~(Q(d%JzwZb(Z-I* ztBr-V1)|xHA5L(3_r+hcTxh#9!8NvBH*^_3dOp$rn?%}~uF)r+i`=QbB{5-$SH6vy TiTHEOt!ME&juCVQ9ens7G5qfj literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/hungry.gif b/images/mood/moonsis/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..65908ef945b44df1eded395c7f3f808fd82fca3b GIT binary patch literal 1275 zcmZ?wbhEHb)Me0RI3mFS0#OVM)eHGW?HX_&0#|R^_$Z*cV7O&>?O;lgtpAk zomCLDd`j8|ouoC}c6TpWX|St#OK*43($;L|3RjNhXHOKII^(yr>v&q~4z1G7SJ`ib zUc0Ti>)Nq`{O8vfMNaNHw|u+V)ziB_eg5+9`_}1o9CIW*ClqMiRP@{`A<3h>dcItd z{+v6KDaQp3to#n#tc+ky(rK7v6_&mE%!E}e?|8(TWR3?s5t^Y6;m-;6L4S*56Lc!_@~YWuBI}eJ;|-JAQaU<2YXh6LC$dhSGL^Na z$8`3b)CE&l6r`K^&0V&c#5{S8fdInyEWGbmz{ry)Dce4jnI8wROTV_5+*G z2QBN)Ikv!c)6Sdgj~&rUs=mBF_3@Uc*UnwO#PQUxVEui~hfi+o`1)~i?JD^6TmDz{tiL&KU) z%N{SZ(7CPhaP1@|B(SlmHsylic8ToEcdsZySkCM(66^O~~dv-gw&<=*4NsHpj1-OKHck>GG7U30`zt=9~Y_O0pKkv3UfI z$na=uKRA$a`PZKA@Ci?uCz-x}y6eVuhAoD|$NyB%D&#qB7bij6FZ3RG z`tI;L!*hMT6&BYYNcgAMbt!y&a&B_ao!ECZMyU~2Q|+e)$YxzQ)n?rNByPLOx4Hq)#U@^u2+t>PI<20Yw`N*?*9oIecX;o&oY;Ct+raTS}0FzKSS<2 zizWB>PSQJZftATQNiRUaV&cL0g_Z&;>Bp0U4NhFzaOP#1!#5_&mJe4>s_x#qsHFIH z$?lyejJsYgx&5ChK+dEjC$~POu}VAIzQewvNxG=LW14@raAr(j`5dd5#z~U1Q>+@8 z7v#9l6r4TBa+-A;V_3%4`7CWYs~Y{*+PUvH30t*y&-UG=yI4X`o!Gu(>e=aC&AWC? zYnUOQd6Su~>|uT7U6#5BY_B@jC{CF=?d`iMw<4bweu;Je^+{#E3fhTE6Ta9|A1 zs(m?aL)iY})|{EbI}F&5c6phpfJ1~8EkynyLPUF!^^>?AxhxufPcvpcXP&n5NSlt& z+3P&)je8&LnB6R(!O^$3O)t1vw1>Gdf5{ocjy;bGC-eqdYv234Q?{V;orpdqMGOQPskE=shTo1 zFlc(qL?6aRgZ^ICh6$^(*DPjO+9cE6ux5eAwhenWEkC?%zmZMX#_30o1l4Xk(i^nw zeAlc?yXG$2(mo-YZO)^#y(i31H9kpuU10lMqod&s+t)cWb?ffDyH{I!C-UCbA0OZQ zFf{-5+i^&!;M4)_$sW3&J_$_Ms8OvjS@pyC@HB^*mu5w4TAs9O*j|tm^1SLY^F+-j ju8QuXuT&@ZRi%78t-;R286>E3=|RQh6@mPm3=Gx)lMW}m literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/indescribable.gif b/images/mood/moonsis/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..165534ea95df0f4f2bb8ab75a64d5e7ade4cf284 GIT binary patch literal 1309 zcmZ?wbhEHb)Me0RI3mUX0xka;mi}ir_Mf9=tw3^*Kyil2GrElGf8Vohif2r>CWLdd<}ADljNw6~3C z`Nmzw=bpdrYkB)F{>8`k^4UDoYD7eqw>?Y<<(_h&am}@(om-kYm)ga@Quy`o)U89> z`FRDinlIj*mGsN3R;O%2yk?dTr`5hd$)Gbm0^q=5wIMrjd;?c&q=|S>a$|{l=Mf+n zq134E|H`?3z4vAXp^Y<`zkRq>yY2k*3c)H1p3?OA__8jhiUe!M4zb=2LFTfIXmg&5 z+M=}53Db(Q9F&-Q8q$`}FV2`_)>_n6GQX2)K4Ye7>-4zByrAxxCX7WTrS(VKJIb3( zW{WX5`D{~4u5&%1asZCSg0vT?Z2%IPXz zfrjQzkc1Wh3QG= zCM*d}?#k$x89C2|WnFS6ufv9IF5y*v;bJcP{5<(ra9lWc+%BDK{)yWMw%G9;+_B6y z{!ZNE>(0kn_FSL+Xs(dZ=0y>#s_*#g-mR&4-nY$GE6_nfA}sERgu#iUkrSdL#QY*O zHcsvhKX*;>%)<>QJ2FBSMRG8LvK^}er z0i~N?H0`AdA%w(b<$KHaXRkEh-)yRI(ZZQshhWy@@@E}OH|>s)T; z&UJCw?N`qQd+(YP*ng3~o&Wz~I8z!v0^z?y( z-@ + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+stars/
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
amused.gif
angelic.gif
angry.gif
blue.gif
calm.gif
cold.gif
confused.gif
content.gif
curious.gif
depressed.gif
dorknerdy.gif
drained.gif
drunk.gif
embarrassed.gif
energetic.gif
envious.gif
exhausted.gif
filrty.gif
flirty.gif
full.gif
grumpy.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
hyper.gif
indescribable.gif
lazyrelaxed.gif
lonely.gif
loved.gif
mischievous.gif
mischivious.gif
okay.gif
pensive.gif
pissedoff.gif
relaxed.gif
relieved.gif
restless.gif
sad.gif
scared.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
thoughtful.gif
tiredyawn.gif
upsidedown.gif
working.gif
worried.gif
diff --git a/images/mood/moonsis/lazyrelaxed.gif b/images/mood/moonsis/lazyrelaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..e72346672aadff1f7fb440b5b65900dd57f26fad GIT binary patch literal 2216 zcmdti{Z|ub76NZ9$=3G+KF? z1s9?PnNty`EKo;*I&4H^MVviEF>BY;h*h($9@D^5W5E{bx}v*6HuewbAF%g)&iAM1 zmwV5BZbqgu3D+b*@z5*}y)McHu`bBs66r+}29dDH>taxZ!4MWjSa;%x2}4Xc!UL3& zpavAB-7u6vQO2D(%3>&sqa22EIBEhY53mXtqfm^-FdD}g3}bMN#V{7fI5&WC1ZKi9 z_cNZrEC9zPxE{f245x9NL2<^N0B13r#c>wkoEw3g0B$019^gEITS!2mfW`m~0D}Pr z2doR?q7x9ZDHcimRaP27>{kX^dtG+D0=5gkeyI!5QAb@H9)~tkc9XD97kb zEY7nC&!Rkw@oXVKZLyFNi^XC!;8spz_l7l!MFy|$#722Vt>?m|oZ;MeOBeOORdk_Qp1VU(>+35niXCGE zvTC--_QN&iD^!Fkhv_kU<#ZPv?hy~}ULX*P(ak;A5W&@S!$;D~5}=?CEtVw~i-JL# zf8sz&P56$9T4CU!E#<0&M^MDFvdF|>4WJA`8CCDU80|jS6trpc*Aa2wgSwF>Pc*sQ zJL6D%;MXIaSurE#t5mA=Hi8*n6CJi78C+(Up!X>7N= zw4iEqWke1Q`*~lCjfwKPrRqE^l1k(dUVo@%sqf3!rj_1j;pz}!T6lF!&`g`UeqiLv zgxp8k<3TSFsVAC5T_Juo#&Ue3S?wD?+@5?iv-x<5@5Dsw_6zuMM>+X2MrItT-PoS< z=pUy}=%v1=8KGdGG_GgK)00p`OnXUNndRlq&Vk{W(i08aWPMOx!emLD_Y!p}{aItg zd%g2}y1R+Ep8orj9lfVyzd3Wz`k&sm!Kmmy<1ylg6E#VJD=P4pn3Ucs+b=Jt_k&W zdTwCXG&uMwRfLRLhPXD3MgP;V&zvS>@h(U3^}l>0C4TBT85KRgbWhrtA}Dlfvj59| zrCx5{WSY4a7PFztYl&nTv9Wvo5HTUxJu>61EKEC_4yV3wYz^zJPli@yeUUOD*x9C0 z-V7Rq)8W;_kisS&emcb^FAP^oNF9pNbYLV(S7I3nSNeYThp? zzZwOHz`uGUp~-b zmla<&-dN+K{3PXR|2r0XrTueeaO{z_J@vcuarY}qTTfO67Q7L?d-8<$j-}*|b@F zGjAwe^)URCuT)>o{qx_8wyuyK%$tAq-;ZZDP}}FaQTp@9J-4NG?}RPNX4GWy_GfeX hjkTGpPUYA7P5yNhZBHS`!2ay7T2s9P#qJSr_#b}4RG9z( literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/lonely.gif b/images/mood/moonsis/lonely.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f171b8e7c9197da48220230bc21b0cf8b4a01de GIT binary patch literal 589 zcmZ?wbhEHb)L>9%I3mpe0xka;mi}ir_FqweK~YiBQjx*w|Nmr5hHNK>Y%k4XFNR_- zj$$u~YA=RrFOHTVhL$MHo*;&vC?N8h62veiieU~AB{Q5mckVyfJY+)gKewN2NU*bG zfUA+70W%{|PVpxTs||xRgAPa?$QcZ*{~oCIrDV>_Se1A5)wgjXUSeID*j+m zdxy1vD%dh;%g_yetbkM9ra-n@T8P~hq6BS#&oOXkn$Y^?W~ z-r*@ATycHcgEC=WO+f(xK^3#C9H|Emto%G&8oa_{uRm(deO;W-%*@T9=&`^d@d#77 zfZUPh?&S&oOgb5vR}L~wP!Lvd*l;m+&x++-T^YO78=W|n zBKn*+d|GJDEU{#AMb5HH4xD&-`qs+* O24~&=D6My5um%87Y1ldd literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/loved.gif b/images/mood/moonsis/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..90e68c805d645a55b308fca2f762057673f5375e GIT binary patch literal 3295 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 WXKP?i_{+om=C0q|_3w7qjsFG3#waQP literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/mischievous.gif b/images/mood/moonsis/mischievous.gif new file mode 100644 index 0000000000000000000000000000000000000000..109b2358e28bb769c8a794469a0ffcc25d4acdfb GIT binary patch literal 801 zcmZ?wbhEHb)Me0R*v!KK0xka;mi}ir_Fqv^(dqyHWCn(628JF6hA9jTa~K%@gO$Ju z#sA!Xt|7tBjsdPldIrplKnca4ES!!EJPbM@MId7tSpH2o>A8BZ#p|=X|0m24WC@;? zq&4-)%C5J!H6v^;ZfaehB5-5(om_Vg5tbA3&VnLdBDziwEd;jAIL9?P(}k~wF{dmj z#jn4qvC3OYd^uN1)ZVZkF*~Ji}o(}XleR8?{o|7}fCZ0Ss|LmmwS<8A`&OR>TzPn34$8N@c?$>i0-$k>r^|fVv z{NDgScL8YolOgyJ?)rRMOFtgG%m_v)|+Mr=v%gj>OQK13&W?i{{ zRom>@C7x3hfPp+|MsH?Ervc-N-c>96=1$$1sna$?&BHTHYxypf{l|3o?_4V9dg^GP z$BAPHcU+ER3G2Idah~1&S$ndUbluqbu>G-S&b|IR?l$|=Qqf#&Y~A;nxqtuuu-^D9 zPsoMOE995gGqCdg5#jT(k!F~w@#LZ_?+pEfS$8>~G3IO1B}1>&T+7 zg0oj^?thZ`@rCa6)jc9n4Kt4vra3TwjpEW(6#)nHjoCA{C^s!r5V2`}bx@ACI>b=J aBVc{@A8BZ#p|=X|0m24WC@;? zq&4-)%C5J!H6v^;ZfaehB5-5(om_Vg5tbA3&VnLdBDziwEd;jAIL9?P(}k~wF{dmj z#jn4qvC3OYd^uN1)ZVZkF*~Ji}o(}XleR8?{o|7}fCZ0Ss|LmmwS<8A`&OR>TzPn34$8N@c?$>i0-$k>r^|fVv z{NDgScL8YolOgyJ?)rRMOFtgG%m_v)|+Mr=v%gj>OQK13&W?i{{ zRom>@C7x3hfPp+|MsH?Ervc-N-c>96=1$$1sna$?&BHTHYxypf{l|3o?_4V9dg^GP z$BAPHcU+ER3G2Idah~1&S$ndUbluqbu>G-S&b|IR?l$|=Qqf#&Y~A;nxqtuuu-^D9 zPsoMOE995gGqCdg5#jT(k!F~w@#LZ_?+pEfS$8>~G3IO1B}1>&T+7 zg0oj^?thZ`@rCa6)jc9n4Kt4vra3TwjpEW(6#)nHjoCA{C^s!r5V2`}bx@ACI>b=J aBVc{@Hq)#U@^u2+t>PI<20Yw`N*?*9oIeJPoKM}7*dytK;i_aX1B%ZApE zx1QU*#^JzmWfrccCli(_i%ei)HZNV)o6hl`iX=SlA-#R@5`O+p4IhPjXsfXXSLA#$=gk z(-~MMnk@@j!5A^S(Q`}9wvC%QSoZAQvvouN?ycQHfd?B}#X}n^*G%*}eP-|ONsBMZ zpDn6lo9KM`N(D39)BE$LhTplqT+uP$d9ts<`#WJt$zcy33i|eh{+e~7@=~AV!O}pJ zpTR{>c=t;<6&R*mW>!$N68n>RgoEwKeSSVpNXTe_LWYMyl7XLr8yGU`8qOyF`VM-o n7S7tlcJ&*>@>aR#xi{2nq$kc=v7PTDXJ5E_xPz(7E4vW|x2=0_Mzr%q>xz+_GZ zgK}|1mU_=`wN^uZpV9U-bB?K_sZ@DiO?(x8e}RHt0#+U~Uw3$ljD-_jfscxrdX*4< zilAqWTLF@SiEn><9AtPud1ya?jH4%|u{xSMv!$I5t+6w+fU;Foz71{1!UM&{v&ccW z!_5Mh!_XbdsLh~N(a8ji+}__LOyr@2N_Sob?*)RZAcv;%wT_>PW$PkKkY)7DGx4eo zKQ3a}ok7SfjWuw;yr3J{C6YCI42xu3GX%s$0ssIZ`2-0v0000i1po~I8UPpo00X56 zs?Y?Re{f+nD`a|x zJy(bm0}yg(kzWCBj}~87nKw3Mc5jdko}-$dUyyD`nwxcnd4y_$mSBIYd(^e@(8-z{v^IhX(T3JQaj9GD0w7+g{Z-m zRg|VH`@Lu^HzzILPOfV_+;10T_;j|SYN)cvjxeLtWEnw0Nz;mxUF5hl%w&VJVihi8 z)%G==z2tEu5V)Y8@Qd) zp20k~D#RGI*1gylp5ozue#mkWwCTO%p63tZw7sqI=De4M)31N;4*~eaT0z?cFkq^F Q4q6o|P@vegAPE2fJK1kkj{pDw literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/pissedoff.gif b/images/mood/moonsis/pissedoff.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4de37d0a96c4f5a817117b669a26c5e077299a2 GIT binary patch literal 578 zcmZ?wbhEHblx0w7Si}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PQB#Vd-~Dp(EGmM6OSzKO~_oUuw+s0vSU3`EXKS7 zj*5SF+*tiUnxkmR?X&6<8r~=6CR(nrOElH|czsRPe4%;$KR;K^wpjDS-E24OL9WI# zZ+GQx*tzP>x>aimC2f7{Ygy79lx<>T+C%MGV%*%!)fijq`zGthOpQ#{u4UFPojz@W zYH9CEhY69(su!=BQ@VUri@V$QUPbdsakKIZG*(V8Th!mlZ*%NKZRY9X{cKmRrp?o9 zF1yOceAln>V)MChVb#ZZUJnyh7r&aSA0Vh2?f!A1%Lcul({EUR-LvSfu%SSA9~&pw z_pAY^zW)aDeg6T^scXLK^(wxX{AzfFV@8}aZ44rGBi_@% literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/prepare.pl b/images/mood/moonsis/prepare.pl new file mode 100755 index 0000000..240fd48 --- /dev/null +++ b/images/mood/moonsis/prepare.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +# + +use Image::Size; + +require '/home/lj/cgi-bin/ljlib.pl'; +&connect_db(); + +my $num = shift @ARGV; +if ($num) { + my $sth = $dbh->prepare("SELECT mood, moodid FROM moods"); + $sth->execute; + $moodid{$_->{'mood'}} = $_->{'moodid'} while ($_ = $sth->fetchrow_hashref); + + $dir = shift @ARGV; + unless ($dir) { die "No directory prefix given!\n"; } + unless ($dir =~ /\/$/) { $dir .= "/"; } +} + + +opendir (DIR, "."); +@files = readdir DIR; + +open (HTML, ">index.html"); +print HTML "\n"; +print HTML "\n"; + +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + my $newfile = $file; + $newfile =~ s/_bobl1//g; + if ($file ne $newfile) { + rename $file, $newfile; + $file = $newfile; + } + ($w, $h) = imgsize($file); + my $noext = $file; + $noext =~ s/\..+?$//; + my $moodid; + + $uri = $dir . $file; + my $quri = $dbh->quote($uri); + + print HTML ""; + foreach $col ("#FFFFFF", "#000000", "#C0C0C0", "#FFFF00", "#FF0000") { + print HTML ""; + } + print HTML "\n"; +} + +print HTML "
$file"; + if ($moodid = $moodid{$noext}) { + print HTML " ($moodid)"; + if ($num) { + $dbh->do("REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) VALUES ($num, $moodid, $quri, $w, $h)"); + } + } else { + if ($num) { + print "REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) VALUES ($num, , $quri, $w, $h);\n"; + } + } + print HTML "
\n"; diff --git a/images/mood/moonsis/relaxed.gif b/images/mood/moonsis/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..5b8d52cc36842f447a1c67c22c987a80ecb3298c GIT binary patch literal 3917 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/restless.gif b/images/mood/moonsis/restless.gif new file mode 100644 index 0000000000000000000000000000000000000000..77ca53746340f737640606a6ba3a835d6e39464c GIT binary patch literal 1061 zcmZ?wbhEHblw;6jSi}GZE&myo{%1J$Ur|x>Ur%o46NFda+|swg5+#q=b{) zhU;DuI~dotDV|8NIQYQhi$dec#wjPOB^G)vEjc|WhBfkS*p3{leGleT=!m{?vd`^1 zb8pw`t{)QuP9{So-+mnY)z^tG<8s{l8#q#RQ1QMNmEd z0^#xCMe6MF+Y6T55Xi{rd&#xPQDK3$AkgD0!hs$?*weQ0Xx`3)6C(_nfF3tG)^lUt zjuj!hz9?+IwbmihR+06=+9<6XjscDjEB1)(mfs(<%I-$-d!BIPnjn^JD;ou)mZEm2 zkhGHO5~o@XOREMhGfx)QwxrhiGjfe5CTlL4vC^t4&B&RhYWl`i%NjSVs%_r3q|w9E@p0~@_PJF=3_%>d0$CmVvY`% zS%Gacvu#l@Z+oB?YgW=EORG9%MvqC2)27dEZJ(+&eVO(G%SA@3mUb_#WLdVVfA;37 zPKDdIY~5De-DK6;wrN{a=7Pg*YxW;cKBbotIJvP;Fl|5Um8fgi)0*6jFYstJ1Tj9J oDOBb9(AHVeF5>-C`-P7`t-1SY^N%kn|4(d5fW$iMh>dk?0Q~^W^#A|> literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/sad.gif b/images/mood/moonsis/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..10899ccc43a4e6a13e7260c54cd6ea44509d2175 GIT binary patch literal 708 zcmZ?wbhEHb)Me0R*v!cQ0xka;mi}ir_Fqv^(dqyH?C<}tJ%9cmEQ3iX{^#~{4GDI3 z3~)8lGhk)}s!;sN!YawY$)E#L4KkL2<)6Vx&((V^UZ36lKS84}C39ZJs#Qm%w!LHb zF0MJd)%Qw4-sRmcr@zmB({%LA#2?mdOvhDP1vEI;1-#spAj`4n?DNZ75*-uuvZi{= z?Kpo%aH_A~?)T|op#j_P?@h~4Ee(gxPN482G zJiRWyFZ_JzrOT(n7tCb6uv+2l(q%I@-`RF==FEWCms#4FIljGrGN(F~qx^6EmI#3& zb+&t5veox&E{beuYP9FPBVq91VaMvGEj9;t6hBz#(r+XqG4bM!Zts-}!u&EnZWJ!k zoxD_v>*1y~tw$KO=KIPx1j>0TtC;)UIXQW`2$xN4Tn9K5Ipsj1$ipDTAjrTA3`O?| z6C9V$bz+&MarT~h#_cDZ;u9yPSrlB7T9BQ4a%R`DQvdxcF235FwKZn3FT3QV!Wkzn z6*V{*FgG?QM)l_Lu)kpFeyYOL#sQ8Yu-P08k_^fWB0#hE1oU{WmQ|c^WcPm;iKs^! z9JiKNT`!3enzb&=Go-2Zl=NTT*|$|KZm<^Zo1bw!W?tWkl=jM^pxKu+g=c8Li`gCb z&0BC=z$2Y4tkuhwW^Z%->?d}DnPt&b%M@G2a-kv#&ANI{md0jrNy$<+PPWO~irvC} zt^IP7*+e;o=gKNM^!1r3%80PfTex>Ur%o46NFda+|sw!j`)K?x_j zeC@;s%#3H1CqHCqUes0bTb4aQRr|`HrxPx$DM~slTYOWe$Sk#_`2L2d4b>|e92LtP zBDTx!i}Cjj&wQ_GUR={+m1^c;TN+Sh>ygu-%ow4?nqA8pJ|VcHlVw`X)LE0~OrFOw zD_lE#+0wOI%X?R>T)Hx0Md`L#?MC5=-8F4_E0(onAIjU?d@RuWaAv@Q8l%*-rqh=v zR-_+uO%c&*3N-SJ7Sk@dcctrUnw|Tb74}QsDu14QMKf%-;Ky@%AEP`xApUj(`J0`A zhk=hl4CwC&4z4SLi`Kd}30er;>e%V5658L&yEM6Wy1^dR+q?2}&y~m~ZGQK@MaJ=Z zra<@pCk#IiiA=N%cMmYQmT@&f?C{Z?<%<$_X!pK3apZ|-<=Krpw>oY5I_Y#RCxbNr DJKU+< literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/sick.gif b/images/mood/moonsis/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..77ded42753be9f3583a4688d1411f6cba38b5fce GIT binary patch literal 2015 zcmeIxSx}Ql0KoANL*$br_?0UkikJY2NrO-jS`rdWI3kw}3DkpDw9q;NMMZ>mgietp za)m2IL=2!96e8hJQn><%5I`}MAm4OQg2xCLoPvr67TX5<(wDyb(4GJ6?883n?r(NS zFxQ*@%~oJ5Fv9~@hg1(pX8{=k$n-!h0w~phQUjs^*jDu9h5+QXWq%oEPX;UCX29BGCtcw+h580@Uriq;x19VD@JwFH0a4oyyM1&C3@T6c!bi zNJ^!r%g&UatvDyEtSa=b&blC=3*ZmJvTM?)G)s^XmYE3MEm09 z(r=Ggi(l&AgjMwjz?yxx2G$38pJ1<$um^K@FbJ@d!$@5+U~;k~4QfkkmiG(qIlIsA zmONpkuG`L!ZqK}^IrDi7Dat#(mO$x=ct)59Iibe`S>ZAqp(G~1Grjd@uvNV!{w@1`=!*`r zIl^e44a&|0j{o4`R4mD+>jsa}paY2|7O{$pm-WQrj^j^NLb|!>2Mx}uh8bWE5CF%2 zY4GUTc_N0;M^KP25inUi-z;WPsf@?w`E$xED>(tA0J(xhCMinU{v;ek4ybO*4!{Lj zb>r&W1uYFhYC9_m*}w0+MJuGX+6+yQMw4{#BoMSPi8=s!GgK!p)Wu0mx z$Yv`$9H}jTQaAT{P57bAoxEbpCH~v1XZrNL2l8^9pP#OYWvAL~yqXA%MnEyIT=Q1Y zEyceSPjApi)*qe}rfphRxl%k9d%FVnlZr;UcB9Xlx5oo(2;G9N5`>4}-qT8r+`pb| z&ywT%gcZB1W4AIUE{-lRu;<>?pZ*V*9OPdVn&9GGvmzcJ|#C500lKdXCRe56_~ z0JbyjR-7Mj=UMIR(aM%{09%i$ioz}Kk#t;d8911Z>cPc%%f6`JQNofnq1-P z=Bg+q(_HbkZZ1Y18lG$4jW_a8uDWr(y6xRvZ?sb_TWyEBZ6`*wzj{rM4^Q+`Ev1cuQ(!=g|Gx8NAB_2^BxSusGZ+p}4AtV|%UOB9Yt%h@;%S{5{bOW3bLe4K+LV z_`m)%A%k)<=EA;i>pbQb-NT!hdF)ASuz)aJHskX3%8$hJ!6{Dl$>qUARcMQC+%jza zQEr!1)bDOR$Dc+QdH!s1mvW?}Cwt?==TX75L{8nQ72c9p+_1!Pk>I$m|B;@4EhbQ$ zc299=026O>WpCsw$F(sD6Ap%gWRqRywhcmq8Y+mVMbUQ2du`AIpE%(e*bH%7Q7oc$fy}4Yj4@J4QW9J3K`>_0Nl=|Njsl?T7IB8(69- AR{#J2 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/silly.gif b/images/mood/moonsis/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8c9b7c808bb902ce39ddb6f62f505fbf40aeb91 GIT binary patch literal 658 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xu2c!w4oq_ou$F4j73{H8j-fQvt?C$>w8ht65QAbuT;pX1)YW5};nf;q; zpZ}Wodu^0L!0VYDjLiw2dqg?eo;n1CD7K$`$`EbMw>a=^g7urO2?~oh)0;fUHMo7I#O!3& zdGqJC`79BiU9zHWiYcqNPl(Kh)!SM2vTWP2Q#w4v_1JO$?cQ!88%~$(tG#gH>^bM{ zebc6|Te^?2==S!zOK;3!o%SNPY*%9v>xYl8Qm(C!oU{Bu^+ZLdpqv#K5*0tOwAlMG zGV$#RYLo3!Uno&zX{NxnKV0l%XH$g4;!ugSrw1CdpQ>><`-H|7#=LA$72xFrhZU<4 zp|E=5HsuQE3XPIgYlJ52=Lm=!j0uH~91<)SQUpB=Y}lDnS9g{; zvBxHLW^b)yPgr7cMaTYpMoGjKu{{q987uCtP*v#A+*;eg!fewt zWlE-_SY6Yc#=x1PzTLf*8NF34{gR88u}+#dd3xX~iA7Z`>*nrY>1v6T*|u>{z~RVs zU5rN#ctm!F>h($ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/sleepy.gif b/images/mood/moonsis/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0f8a042be359ecca42e0151598c6f5e94cd9772 GIT binary patch literal 666 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI<20Yw`N*ZtjE^g$lycPD$!ywVCPfKJ;1ibbN2} z_q;p(+J~ z`HU|wL>X|T9<3}Y%3*G;%a_Y+s;+76s|)C2>gnw(sjctK%ITRlk10>tZ%WS8c_j-w zmn>hCDm#feXw9aQ1s#Em%jWN@S+G(nbJzT7OZROTJy^44UeM8<$9;E}o;{iqpLASyQE{WaVs5U< zbx&`otZMG5@#|pf>h3A3u5HiA>Y6f#DaXTSQr6@-Mf2MiEnStYGJ)A=Rr7|Td2RlT zOXlvZnzvj&edpXMi}!95Jx~>}D&WYDVghjNW;3%ft=lzS@BD%WHm{9Ahg5>s@cnVvd24gy tBPZQc?;PF;$!wgu-$rJpi`D}kITMRldUbQsjN&}>^rNpGoWQ_f4FFa}EzSS{ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/sqlstuff.txt b/images/mood/moonsis/sqlstuff.txt new file mode 100755 index 0000000..49079ae --- /dev/null +++ b/images/mood/moonsis/sqlstuff.txt @@ -0,0 +1,160 @@ +insert into moodthemedata values (3, 2, "/img/mood/divmedia/angry.gif", 50, 50); + +insert into moodthemedata values (3, 1, "/img/mood/divmedia/aggravated.gif", 50, 50); + +insert into moodthemedata values (3, 3, "/img/mood/divmedia/annoyed.gif", 50, 50); + +insert into moodthemedata values (3, 8, "/img/mood/divmedia/cranky.gif", 50, 50); + +insert into moodthemedata values (3, 12, "/img/mood/divmedia/engraged.gif", 50, 50); + +insert into moodthemedata values (3, 47, "/img/mood/divmedia/frustrated.gif", 50, 50); + +insert into moodthemedata values (3, 19, "/img/mood/divmedia/infuriated.gif", 50, 50); + +insert into moodthemedata values (3, 20, "/img/mood/divmedia/irate.gif", 50, 50); + +insert into moodthemedata values (3, 23, "/img/mood/divmedia/moody.gif", 50, 50); + +insert into moodthemedata values (3, 24, "/img/mood/divmedia/pissed.gif", 50, 50); + +insert into moodthemedata values (3, 28, "/img/mood/divmedia/stressed.gif", 50, 50); + +insert into moodthemedata values (3, 6, "/img/mood/divmedia/confused.gif", 50, 50); + +insert into moodthemedata values (3, 56, "/img/mood/divmedia/curious.gif", 50, 50); + +insert into moodthemedata values (3, 45, "/img/mood/divmedia/determined.gif", 50, 50); + +insert into moodthemedata values (3, 11, "/img/mood/divmedia/energetic.gif", 50, 50); + +insert into moodthemedata values (3, 56, "/img/mood/divmedia/bouncy.gif", 50, 50); + +insert into moodthemedata values (3, 52, "/img/mood/divmedia/hyper.gif", 50, 50); + +insert into moodthemedata values (3, 13, "/img/mood/divmedia/enthralled.gif", 50, 50); + +insert into moodthemedata values (3, 15, "/img/mood/divmedia/happy.gif", 50, 50); + +insert into moodthemedata values (3, 44, "/img/mood/divmedia/amused.gif", 50, 50); + +insert into moodthemedata values (3, 41, "/img/mood/divmedia/excited.gif", 50, 50); + +insert into moodthemedata values (3, 16, "/img/mood/divmedia/high.gif", 50, 50); + +insert into moodthemedata values (3, 17, "/img/mood/divmedia/horny.gif", 50, 50); + +insert into moodthemedata values (3, 21, "/img/mood/divmedia/jubilant.gif", 50, 50); + +insert into moodthemedata values (3, 70, "/img/mood/divmedia/optimistic.gif", 50, 50); + +insert into moodthemedata values (3, 43, "/img/mood/divmedia/hopeful.gif", 50, 50); + +insert into moodthemedata values (3, 69, "/img/mood/divmedia/refreshed.gif", 50, 50); + +insert into moodthemedata values (3, 62, "/img/mood/divmedia/rejuvenated.gif", 50, 50); + + +insert into moodthemedata values (3, 53, "/img/mood/divmedia/relaxed.gif", 50, 50); + +insert into moodthemedata values (3, 68, "/img/mood/divmedia/calm.gif", 50, 50); + +insert into moodthemedata values (3, 57, "/img/mood/divmedia/mellow.gif", 50, 50); + +insert into moodthemedata values (3, 58, "/img/mood/divmedia/peaceful.gif", 50, 50); + +insert into moodthemedata values (3, 77, "/img/mood/divmedia/recumbant.gif", 50, 50); + +insert into moodthemedata values (3, 26, "/img/mood/divmedia/satisfied.gif", 50, 50); + +insert into moodthemedata values (3, 64, "/img/mood/divmedia/content.gif", 50, 50); + +insert into moodthemedata values (3, 63, "/img/mood/divmedia/complacent.gif", 50, 50); + +insert into moodthemedata values (3, 65, "/img/mood/divmedia/indifferent.gif", 50, 50); + +insert into moodthemedata values (3, 42, "/img/mood/divmedia/relieved.gif", 50, 50); + +insert into moodthemedata values (3, 66, "/img/mood/divmedia/silly.gif", 50, 50); + + +insert into moodthemedata values (3, 35, "/img/mood/divmedia/ditzy.gif", 50, 50); + +insert into moodthemedata values (3, 67, "/img/mood/divmedia/flirty.gif", 50, 50); + +insert into moodthemedata values (3, 72, "/img/mood/divmedia/giggly.gif", 50, 50); + +insert into moodthemedata values (3, 36, "/img/mood/divmedia/mischievous.gif", 50, 50); + +insert into moodthemedata values (3, 48, "/img/mood/divmedia/indescribable.gif", 50, 50); + +insert into moodthemedata values (3, 61, "/img/mood/divmedia/okay.gif", 50, 50); + +insert into moodthemedata values (3, 33, "/img/mood/divmedia/lazy.gif", 50, 50); + +insert into moodthemedata values (3, 78, "/img/mood/divmedia/exanimate.gif", 50, 50); + +insert into moodthemedata values (3, 75, "/img/mood/divmedia/lethargic.gif", 50, 50); + +insert into moodthemedata values (3, 76, "/img/mood/divmedia/listless.gif", 50, 50); + +insert into moodthemedata values (3, 25, "/img/mood/divmedia/sad.gif", 50, 50); + +insert into moodthemedata values (3, 5, "/img/mood/divmedia/bored.gif", 50, 50); + +insert into moodthemedata values (3, 7, "/img/mood/divmedia/crappy.gif", 50, 50); + +insert into moodthemedata values (3, 9, "/img/mood/divmedia/depressed.gif", 50, 50); + +insert into moodthemedata values (3, 55, "/img/mood/divmedia/disapponinted.gif", 50, 50); + +insert into moodthemedata values (3, 10, "/img/mood/divmedia/discontent.gif", 50, 50); + +insert into moodthemedata values (3, 80, "/img/mood/divmedia/envious.gif", 50, 50); + +insert into moodthemedata values (3, 38, "/img/mood/divmedia/gloomy.gif", 50, 50); + +insert into moodthemedata values (3, 71, "/img/mood/divmedia/pessimistic.gif", 50, 50); + +insert into moodthemedata values (3, 22, "/img/mood/divmedia/lonely.gif", 50, 50); + +insert into moodthemedata values (3, 39, "/img/mood/divmedia/melancholy.gif", 50, 50); + +insert into moodthemedata values (3, 37, "/img/mood/divmedia/morose.gif", 50, 50); + +insert into moodthemedata values (3, 74, "/img/mood/divmedia/uncomfortable.gif", 50, 50); + +insert into moodthemedata values (3, 34, "/img/mood/divmedia/drunk.gif", 50, 50); + +insert into moodthemedata values (3, 14, "/img/mood/divmedia/exhausted.gif", 50, 50); + +insert into moodthemedata values (3, 40, "/img/mood/divmedia/drained.gif", 50, 50); + +insert into moodthemedata values (3, 31, "/img/mood/divmedia/tired.gif", 50, 50); + +insert into moodthemedata values (3, 51, "/img/mood/divmedia/groggy.gif", 50, 50); + +insert into moodthemedata values (3, 49, "/img/mood/divmedia/sleepy.gif", 50, 50); + +insert into moodthemedata values (3, 18, "/img/mood/divmedia/hungry.gif", 50, 50); + +insert into moodthemedata values (3, 54, "/img/mood/divmedia/restless.gif", 50, 50); + +insert into moodthemedata values (3, 27, "/img/mood/divmedia/sore.gif", 50, 50); + +insert into moodthemedata values (3, 29, "/img/mood/divmedia/thirsty.gif", 50, 50); + + +insert into moodthemedata values (3, 46, "/img/mood/divmedia/scared.gif", 50, 50); + +insert into moodthemedata values (3, 4, "/img/mood/divmedia/anxious.gif", 50, 50); + +insert into moodthemedata values (3, 79, "/img/mood/divmedia/embarrassed.gif", 50, 50); + +insert into moodthemedata values (3, 30, "/img/mood/divmedia/thoughtful.gif", 50, 50); + +insert into moodthemedata values (3, 60, "/img/mood/divmedia/nostalgic.gif", 50, 50); + +insert into moodthemedata values (3, 73, "/img/mood/divmedia/pensive.gif", 50, 50); + +insert into moodthemedata values (3, 32, "/img/mood/divmedia/touched.gif", 50, 50); \ No newline at end of file diff --git a/images/mood/moonsis/stars/green/achy_sg.gif b/images/mood/moonsis/stars/green/achy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..372af9a704d1e053e597fb438a5179e6b1f1d488 GIT binary patch literal 991 zcmZ?wbhEHb)L_tHxXJ(m|NsA2D6o?&wu-!09sQtIq+UDnZb{^wT(*93L09p}+i8)v z(-|xoB5npP`#*crpOwn`iV@fBcm%jZuE~a8kqEmi7Jh**?4n@gIicj_WKB&?2?>b< z2M$Ett=ar`zfgl3SC{Pae{uSuB1wZpv?4)5`~g{1)tQk5`|!(DdmYpsS2KX$$DH|A^8f$r3D2=sl~+#B^jB; z3b{a5VtT4VW*(5As!)`go>^RyS_HJCEVZaOGe3{3G%qB$-kfk$S+o?LD&p* zUT$h$i9%XYVs5Gu7lYzY7ETQYSq2?Yc!A=If$jf+z5)*&ss0m7icaQ8F$OeD=CoxJ zis&opV#!$3d0ct-Q=z?gKRhn-oYHzhKlES7=G(WDYC7M2X=g~v&WXq`sQ0Q3Y)mT8 z;S=vpFRlwu?3>Y&(iRdS-aIi!Omv|*OGHXc_zZ@H5+ZBYE@N4qw~BM-&hjl==XB2N z3lNvgIkacx_8mtVH%&ZqoU<~m?m!?1A4}kt6PK?fGDNX%36R-(>25*Op4YdZzX)&I z$;}=iy)XE~g1{Uhp1m(#$~kDbeK^#V{C$=IQ!CeLCeGt;7It6o2xit;u|PG(=%Aoc zK|}`c2G({yQQwRA8jdI(aFBGVvB;^~6m)Q!?T+Yvz*m+Op!}VvosM zZx<|F89do_zE^Hm$*QZ1!&d5jm1MydY;Tc+&1(LI6(wG4qdFUO9-Lxn**8a5{H18; zfk%ZKb)7x#8xUy5no3s!D5><&+ykBI9dXdgB!n>to}Un|oX2`X@~C zitBC6TOhYMevaq7=_~UV&nyUtQ*2qVXvyrr4Ydr63_EwP>0jo(qdjs>)YkIO?louj zZ)>PNdxrO9Xqo>`87V(^%tm?by L%ZZI%0u0swJjZy0 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/angelic_sg.gif b/images/mood/moonsis/stars/green/angelic_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..d20c5df1008c8f9617b630af3f052b25a2a88188 GIT binary patch literal 1916 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 Dt}NbL literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/awake_sg.gif b/images/mood/moonsis/stars/green/awake_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..ade1b84f262a471a4fd9221bc1f6bbbf9b3b90e1 GIT binary patch literal 1477 zcmZ?wbhEHb)L_tHxXJ(m|NsA2D6o?&wu-!09sQtIq+UDnZb{^wT(*93L09p}+i8)v z(-|xoB5npP`#*crpOwn`iV@fBcm%jZuE~a8kqEmi7Jh**?4n@gIicj_WKB&?2?>b< z2M$Ett=ar`zfgl3SC{Pae{YQedU8UtV6WS5%TyoS#;rmzeT$GwvlA5AWo>`Ki;0P60 zaQAdm2vacBGcw{zs#FNdOwTA$D9KmwNlhzJ2nL!`o>-Ks;F*`K$Hf(ruTWfCP*9Xw zT&z%%ky)&e3uGmxrz<0r{y4MXBkT#U-glKs(A(i;6Sz^SDa$k~311vlW#53rc|e zVuc!n%|PenrskC>q!lIRrYdnUDE?&O)L@Wh&;f-MD6SaT-X7>H@X(R!Ke43fWRBJR z3oA;z)<$(U=sY;Z(z0)kuJ}vQ&I6AMH|j|BI%RI1aJR1gsdK~4H+9F?Mpc#8D$6N1 zhD65KwDiU+Cf3KsD>wJH$n{T{G z85wplY>Qv#y>rXHC0m!4cXqEiv;SmhlhWBUyys8J*X&uiBwqTUZ)!{9;y~)luK4};=YE-8Ec4^(vJYBU_0R9uSGeNISYR+|q7LuZ(o05$-1E96 zjI-`|xHKQ{m)CES;Vj}gIa$?r(U%h&y#%m@z<=ZrkYWsIDE{RWVHu<)I-$a5U1aX$ z*L!1x5;sozV=#Z?E7b$H&7vjFa{-?3k6cJCK8qC2;A^ z=2nIX)};Y5%L*!GYxvjRI(4-&CwJdAZuT(g^?o_qsu_fM)?KR+SS`-I<9TmM-b_wz zp&ic(mA+U`UcjiReej*;%m?W+jayjQ=18Tb&y?fqWRVEq;9jiec4>{q0}ky|Qj@O* zt%^ChY3b?d2Fa)9taNQYJ6kI0(Vfi8s^>Z8>(_rgBq+d$T9h2jgyNCWyGBM~(y2!?rE+!=z^f=d8PQ?7H8n_IYRT z_SNQ1<2=fFt)(=bleabOPD}m9lQN$cKF%)tR`p}rH&sT42^WQ%{vF|wl3<;AxLrWm kYmUdpMMt|Oj%M6A5!igRPr=-e$8(aB=S0cREQ}1+0QzK4s{jB1 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/blank_sg.gif b/images/mood/moonsis/stars/green/blank_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..41f43f62633833f2f13b8c829aeebb66fc151d29 GIT binary patch literal 1512 zcmc&z>r>QK7(OWElDo7i%^;w-uF?ufz=<6RisiPfB4MUv$RwBET9n!3#vN8LNN|FifKzbv)p3#sp(hQHaI3bIt^3 zQV|RuD09JtU{cW!TIlAI3CW~l2i$@^@B;=wF(g70M1VDDf)|KjGoXPDFifKzbv)n* z&ZS}{6k;*%LU5@#3&G%lvXERVMk5yF0OR2_tc8~_4{pI8_yGf;7!pAmSYQpB-~}Ss z3}|2j4AW>w9S=BC$qZIPAr|89{D1*a z42d8OEU*Sm@B$HR1~jk%hH12;jt3m&m-s(?=;Y$(6Slq>7qdAbEI4GL3n=LRc6E=! zchEeY`M(KK%@G%sucfQ0uSB&pAl=#3+;7wBH#S(hTM~-L!mL-E+Io$X)_krRM6wtgh~wQ>J4_tV1Fzf2FZDWY28V7hCS6B*un2J@51z2CMu^0#4qK zGg#aMa*V$l`fNjO8R1?vWMP}dzM^xBCU8Vs*B$TIz9;g+qHjaW2MR|o59=3RTvqCT zAg847(NEuw{w6uiqOLo)SHI6KuwAA7J>Ate0(W^FTN0Yq)EXK&lymrW z!qIbWsoU=B)q00*XK#9tS)D%OaWwei)Q$zyM@(ghf^z#W)g~0=r~Jb|$;&x=voi5S z`t4~;?i!QH%DR?+wB7M@XiZPrpFOd;0nQb9)sOEWKDyhz-}N*e`dX4l4C9B%_RR63 zMRT_CVpYw+c!}m2RdbPRs;5@*)a}1Kjmgz^M>NcAF4nlOS-qvre$(7)Ub5OT+|#Wy zx>x&VPwR?yZzy{*`ZZ@$pP9V>)MM79@13^tx^?-_Rn2tYN~!Z6$gSH)MF-zU~OS&?D5J6Pp=WzIG7!qlclZ}q!teMUQ7H5ng&cB)`&|Ekce zU}M=^d#5&DvrmRu9S3qI&ID%9HdOel^_6K!2aj+5<8*C^WAc@&Yxh5V>1nIiHBHdI zkQ*(XgPs-Zd|Gp^MCnEz6#ei^#gG2adY>$ObMhz0^<}^A-+jD2|EhJ!H^t-py@^U= zaK&$#s$`veZ~o4+j);dXF7~m(w$B@u){m-R4Yw}Ndm*^$a@|+9_(*NN%Y)GCrsc6? z9T~ThlVjo=T?5pXjQEfk!)U2zYSu)V7wecP_dVFr{KU%gEH~S#6Dn)DfBQ^kg}z{Y JriqZqe*yV)cMSjl literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/bored_sg.gif b/images/mood/moonsis/stars/green/bored_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..70c47eaba0d7199d46c5bcd9a897562667d53825 GIT binary patch literal 1528 zcmc&z>r>QK7(OI4P>_s5aWh>ZAS4wIY!Hrdk&T-OY78cpyU}rp%Q#~hH8djEAL1HV zfd`qmDWHwXqB+o%!)=rFcp)GcWE!y%L?#DksKA*zJ^cQGK6XCr&N=VDFG5j(TgH(ONUX)DHW7TbusRYQO>AfRH{5sW}I?P1*cM_ zg>EJ&7gPu;RhAfLl5$Cfq*5gf5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD#T*kIcI`1 zsR{-Ul(}F+FsbSXEp&6qgk(~+18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY z=Tfy23b7b>A-GhXg<$YNSx7EbqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR z1~jk%hH12;jt3m6W(F&v5Q}k_YJ|uifg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`I zhD4AC7FdHOc!3Bu0~*)>!!+7a#{-V~OZ*=`H1gTx*qu9KqEcdm*Kb^A0}7f&TZc{f z4qT$M^fw{){}3B{uegrJ-eUWe0U3iGP5tH0-U;<_=4MN!i#cmT32M@xi*)jn;E@==Y8(ou?ynOdh%OO*XARnZi~*_Bz{Jm2_-n=n)ZrF>9NH*7!@o z!uF@)+LE2(3pK}m25MjKf0W@q?CcS=woPjr;gX&HRq257kNDB2i<=@J=ehLT=kEMA zJNDiWWyk%reFgnWiH%kNX1|A1Y0$+X=kaROY_KuY-L$KF-%abD>c#Bj8wTGN9(bF~ zRBm|he$rT4fAh8T>kOaYQrds)s2K|O|Gld^Wqj~cr8`&2`*}E~DPj4qw{>|HVHM+{ zjV@t`_!#-2CMift26Y?7p3p7`|r$-ImnpI^be?DVAWBsJ?bYhN;b*?rqPGkGU zR(s#}yG4#GGA+f<(aPQu7o9b=)a|W&ec5ttdTOL2Op2aQLbL5Pz zQ`(`jk zZxF6Fm&hZ_K;dQA z^RZ*L`gePF1@(07iMF=yuS>IwDrv9{@KW|}*_i4-QtHOqC(FDJKA0?DQ}&?A)u+a2 Wr}(zU8Oj4Lg&8XSj^yj%d&IvP)r@Wc literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/busy_sg.gif b/images/mood/moonsis/stars/green/busy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..f16bfa2c4f1e83f7aa7c072a0275baecf931c371 GIT binary patch literal 1546 zcmc&z`%{!v7(OUA?1;4@jI>^Gx#Wf>$Z@~XC{dA*HBcF^F_g-s!$J(|An26V01K?R zFwUBnBNq`j!-B5I673fky|jCp$a{(*k%{IEOcyzl$G&t*4$ zi8^;)s)?A$-(=)aLKq>O5J8C4?vxTn38zF*BDFGQgfYSy5sXN!n{vW9;hYFgq&7?i zVS;c$gdkGGqLMI4xFkXnsX>sQNgIxc%aNU<(vvm zrA7m$&ii?^RIob;pjL*Gw zD!ylq&>8ug5TBRC%V)BssqTES&xG&~JWYoe=IGt?s)v$_#_7UBSGer$>Jim1ba&@z zw^7kmOwM|2EX-I^GCd~SQ+Hk^`y*aUOSs`FD?RvD-h9W9`^xfzh6`4^Jui6iF7@+a z&z%!LCDtj%+;_5KW3Nu_svP$HGgh?idVOBOKUwCPH+*w5%V%dO4J&nq#+TyL{II2m z94&P}bouwiHOCl-KQt(gK-Kqn?z`0!yT5PR88K;5x~KlSbIOybi*Kl#7SAr3d0SjM z`Rw=WiOF00ZH>*3?9G{%XXPB9@YOPxbIkOTami0sc$n;K*H;bP>?oQTF_3s_W8c^s z`RZrgr#JPSac8&M=1xl9w7Sa~@LT(vX&nJUHNUDyZ*TkSR&Db1+ND3gczXYrwha@l zdkf=xw)Er|E%jCG`}IorN$+l(5_soM@j&VjPnultpto#Vsp+mgbf2}}zQ)y19}xEK zgS2wfxuLuEsFrQPWnNw*?vME|_gl;KA@5aN-1TuqT~TR2dh}J}bjqll`}WTCkocek zM`*IX%BEIqw>G(*UoO~Fnbsk!dDD~wksl4$U0QK(dHf=?$Nyfdsm&2o9A48OYqIFV zKUSWa&X;w#HkbpQWVFj-pL#62)AYqR@6So!IX`j6oSd#jX&1I%J<}Od+?-pL?cZwI zXgRkdX4FL`Kk`UqQ0laShHa0`Ii)RuEd@7ruWQ^BZ7`Rsj>0R3Lj^G1eC)a*B_!qS z+gsM(bUBSPN_Q>)hwe^o@p}jW$HP*um)?_psF7?ZO&|4b1!xU^cRvzdr2^ix|qW=YJ2%o|L literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/cold_sg.gif b/images/mood/moonsis/stars/green/cold_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..4fea2e840da0122df216df3015ff6d0bd06cc31d GIT binary patch literal 1640 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/dancing_sg.gif b/images/mood/moonsis/stars/green/dancing_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..622673cfbba30e8f3c59410e11f8845c27198061 GIT binary patch literal 2051 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/drunk_sg.gif b/images/mood/moonsis/stars/green/drunk_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..d9eff5567aca1bc08bffe335e1dfe04dd612d9ad GIT binary patch literal 1669 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 Gy!j6wlV#Me(3Z|?+2Ls&N;vHTW(_G zlwosnq)3W>MdOD-2qVNIL=d9fona7W5X&IKAj*{)j4(zlMg$|ubu%o&EMi$iSVXyD zh9FE3OAsN5a###Sm?D-ULJ{Sl83af$3cXN-+xWo@!!itE7|Jb%JH`x)8G;$g@qjXB z8J1-T%TSIMbYsG>gdv2X97`C+lwm1DC__2YAOcteP2dGYU^A=&Yyg94Xoos{fWu-; zFs7VBSPXZT#e~I_6AV0{%o0oprksAD1>G#ggks9s0d9dk;0G80ia{c10ujI(XaX-F z0-FIEumKFFp&jb*0S;kV%2^2tVKLkZVJYV<2nHTdCX}U|(GUyd0LFvUU@dqF=7C#a z5BLEFfMSpcqyY<915MxsL|`*O12%xcG_*qv$m z1}Q--kOLSGPJ^}JCD;KhVHo@X13)oI1k!*7tbr!*0wS;(paC1eU>e$?4j2yrUw+Py_(e>)dj|Uu6FIw9di(G=d?2Y2tUN$R6 z(iIaFC-=0iL|B)lPL02h%4n)n7Kp_q{!*pr9h;z=lKZWhs^%(ZHN~tPgD}IkPsxzl(%z z{4{p)ocmq*ny%tUi#lRc?Y%n2s_ga!buP&^wXAnl_-ZTD@tAYd?WKN#+S~DyaP-BM z@e%G@bVD(X)(^gGY987V*f}~>F7K5N8<^*IDF($)qw0!z=ldE|v#}@dbrgwz6NR~y zCyC#$YO9agHW;El+sCVMc2wAENA%WZl33Au2A>RGO|jBgq-ky2-4wp3LVcNN)_NcQy=ylimqB02~5WlwKr}mj5lvsWBFSLKCe8I zv_KquK(N(4W6j46)>@`&dFzbR=0kGlOV7)d3dsbYtdBax4|11?az;BlN0V19Ztb{t zKkdQGmK<$?C4I>(e)GUig;wR#FxdO3?A<+yUxXr$#&vfSET`Wp3kokhv*L)Tr`L02 zlOb#MSIsX|x7+dGc+@{d;cM`_T_n7gw%(<=|T@6;JANqzfC}B=y?<)Moo&VZ~T+wJ9$}B&Z&9xL+ylsphZN z)C${V-|E$~^F~zHa#LzD#NQL^*wMP~gdlal{JQMNv-ynNNv9m{EAjI!az3^}>vC?h zAXr|WCdts=XuUPj_&yOt39jT1{5G|o-|I^A0-Zd7UylO7&_?wQY$RkHKa;j)nHdbQEJgP-*}fr<0}f93z`E1&xpsk_A7 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/happy_sg.gif b/images/mood/moonsis/stars/green/happy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..b41aeee8e693e7ee63b28e408e9cfc36dfcf8eed GIT binary patch literal 2260 zcmeHHSx}Q#6uy*2qXB~kgn*jJ(hNnm3#qoUNJv=RC^9OHAPMk`6rwFIh`0htkYI5` zF5t+f;M5|i1r?``%3^GPFx-7Bt#R3!I)soVobTg5Hk!W3}zWjIUbN^ z2qpxx1XGR{R5L6lEM{3uIhN4OP)sOhDW)805CN=#Ch!6xFd0SxHh@7lltUga;1Gsk z8HRESVKBsmFf3sxCm47@ny?JZGL+K~w4j<$hNTSU>;SjG9`FMU0L35?G=T_U4K#rl z5P``64cGt%-B1pBxPZeFLOClzAq<9?WeMe+1;M}r(kvyEGaA+cdjR9XX|NW&1oOZx zum}7A13)oI1k!*7tbr!*0wOROpaC1epc~2|4;OGKw==L36vAMLDYrt{KP((J3@e2l z!qQ+%uol<@7!OW^wcsV#0W6^z`~U+$F-Qc`fCa39Ch!6xFd3i$8^E9&${`OIaJZNF zAACsY)MbkJ74k)~iU1!!OADYNd2Pj82;bflbS8c#X!09mG1)b$rRGY(bm}!WKUXj(fgs9rkX2Cbkuj6dhuP8 zPFp!IC&ci|cx!p3s53*a&zT!hqTDrR8aR7xNsUaRS-4&<@15PZe~kaDob4)cUa)0+ zeUSHEzGmG%|1??C3ZCfn8+Q9AS8Fcx2}cxdp^~vAk<8$v}da4$1diTN#nS!$049GIq=!@xepYQ3vRA< zf%8z7h0i|w86DdEW7`s*yDaK+O6gGeUw-yb?q$9sjCdVgb9JwLhiq*`czV;I)^*G1 zpiZon4(TO{s-fbQdi~Ho&z+{B67i+Jxy8;lR`29|hfd%YQypcjQ|#>vP+v3&s%&|( z_p%=8&8cpYa~2!i69iR-%F_Id7URJaVTbmsd)SN|v8=)`eXQns-0j$p?X1ec|fP{N8r6 zTS1$qDpS}IwIS-#j?lJmwb@>>?!u1z!ae8fhgzL&i~JjIl_j4(a_(M=*@V{ws`<4c zI8TwG3svRy8rLZy%1n7{hBUH?L7WIU^3e z7wcowTsk;?SDa_7MF)y6J9X2q%w^}o0!ugJk+3=E@}iAm=iQUUG?V{$`Kd6+{QPv` zZd;vw=Q$f8Muw zz_R}PqmztXpZA&~wUsi>kd?sx{xv0Dl_?mmmoC#g9=KgSwn9Fwd?ucflzUri(-3pU zE9n7Qw|-$KQ*bR)JBhg7*u&%ZY>&@+HA`9Ctdo$8-AWQ zPln7m>fo)i-cT|7gwM(9JIo+CB2O%Z0*~8G}Vm pnzSyhYobb}6Km$H^zLy{b$Vwz2LbnIV*R#1lmDOezkSjl{{>7bx5@wj literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/horny_sg.gif b/images/mood/moonsis/stars/green/horny_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..32fa2e0b4bbcc2f946b89d8702f16fa8c4118698 GIT binary patch literal 1642 zcmc&z>rc~H7(S)Y73!r_pcO$ukRS?E4^$l+DU`O+s+a2ZZzMyFA;vWm!U zLu=qD7*MuoVigThGg+c?8P4BG@q(yh>qM8C%`Ike#yLHE`27Lk z5@8bI5|Jb#WGpHO6NC#Q2_j@@N`Qn>^rDE{_+gZCN+n8#ycl=JC}&h+RLDF~W}I?P zB~FD*3*AhjT%wXhh0GGeOi(VUB&d){Lj+iZCU}7eHe(gA0fuR`qmBn0&X~lQkQHJv z?wm7;Ga(BG50tsYB#8-GKWL$w3nmFBWINy%?13LJ0E!_InjiwKK@+?{1e*a3Y=B`J z?Wp4cN8((_Rze{b<1R^D$j(AAc%Uo^E@Yz-3vz(*a2nRaOPB|@U=RF&0Z?j{HmfA3mamW|<{tr8#|tWkJ$Br2-V9 zpZf=<<9qHno$W~t}O6F~k zFX(n`K4WqEz22JkG+L3b@yn}N65`8PU+D>Vg=cI!N)(Eah5P#|O~*&OJ`Q$=cFv!< zG*GQmYj^lgO;(l#L}@pj9WytVKCWStk<8v8v6CiSKSxy?rpZ5zPP)obd}TZTGPXCJRfd5fA!}*)l9kL z#prsaQdPdL$9bx+=?A7-U~01}++E*0CmUV$s$+J;G~=x1SjB{ncU<*BG1I;8rAI{S z^|l~S|Mj}$;gYfXu)OxMhSa+QW1qcw*8joh=|T36hDDVjS~-+}h5sE&^yM(pY425$ zqdm1r>P)x8oDo=)G`BEk#81v5Wq*{@->6@e*^oRkv({d&3txQQXTEYxKfgG<+uCN* zv?Qdg^EzTKEf34koQq%K>ln1ACC__$r_vP0GXgHCdDMw_J!`cs@g|e$X7xz#b#2=% zTh+<824@=PnC>raF>1R^ZSAiaJ=;|bhp j^x(h>>uh&uPHt)6fm~*vbzt?@JL{VAmpm^p5t8~ZLyn$d literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/hot_sg.gif b/images/mood/moonsis/stars/green/hot_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e1e039f36b44dba5bfaee2762a90e6bb713a226 GIT binary patch literal 1686 zcmc&zYfO_@7(V4vTM-bIiv`rm-N}L;)`2WjD3?N}gMc_L)0WFY2-}=SL}QGARE&Ut z2pp>!$h{$)9BMP(m0XoDhi+A>Sz_j1o?XM2V2glo7@VXGCH|$la6^#tG*{;zY>9R3c0w zTq2T0gp5T6VS;c$Bte7>O$m@Nie40Pn>>tCPN_txkQd|580Cygj0%|t%8XOasl=&} zX`!1*luJ~SsE}D=m`+sX@~%8&;&0K!Dg%iHo!2AcGU5J!x@tp6S6`q#+`E} zaVBKJ;DIuim?SYF>jy1#bHOCRglq@gf<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;7FVc*-9wHV%#N(3)xu+1`m`a!G&xzVnGft9!|qrcnS017VLo^FaU}n5u||y)}RSq zAcD<+1~$Mjjds-WfFtD0U?mh{G44W+5cwl;B#cOrAwok+hy^*ocsLDf;U(+$B6|HFq?xUERa%GAfFCoO(6%2@#l+7~YB zAbc;Jq%-+9A*z3fLKR@JcG_!HGZzF5R2lVEp1x^2RK${0?iBalZPmQ_I<+pi)i&@T zA-PfgR`%C}$C_Q5M`G&N`gtAJy9LH_gI?*bTR7*3 zoA&Aqb3k>y?fWywJ>BOOR>V|4KVjRQpI5f-@$)xs9rBN?F7L_Kdw%vleLXF9M$nZ# zy6CHYy=@b#+|A3r3wZJNx(Cj_Zfml-;_EvuW{5Ov?;jC&dp6Rj8E3{1-#e$hvF)kJ z>(riMbHCAJo#yw4M@LSY3N8K?ZFIq3!w=78Rp;$)8_W+5tf(whH&~l(=FqcA-u95I zy11y1f);h#JMxsCdtc>@H!9=))`Y&A`l#Xh%K`GD&vUL#-ye2&W8^O9p}w$WZCf#G z+f-RQtHq^Yx?;7T?tIDc)UsIb7KKklS#8E9(T0pavnJLW(TXsT32XN$M&VH z&I#Fj+tp<X&PwBmYBK3-rw2KWM_FrJt2{!IKUZzPkW>}8xZv8cCezNQnXw0= z)h$H{yBFwlRkL?!ce>4q?Fp{T9BcLnvZ^n!Pj_7L3g4uAXLDkR&VMpt-F(B!Zr|2y z$HY+oP;%p;md;!8E&Nln&o+K1pOkBSFSwzj{-qGKDE(|DZyd_IY?KXD{E5CE; zo6d-$EhopGYRsCcg@(TM%FO3WK8bGa>3Es()g$k^o2RsopD0oeDhi)Yv1Oiqy)Q4{ z6dqQ!?OE#mTbueyZFPS3;u2ncF#b`EUo9!QTVh-uzA7ujRHrn1mQ`AIRV^}-wHaSt zRyp_Q==N`%UNCc6gGbNE0j2%Jqgwdmt8Yv*b@!J~Q583(FHH+6+Mthc@T&ZZU&h*v f=F}$dqP85?!H$%&_Oi3zhFU&uiD2yt1&R9?M%lew literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/hungry_sg.gif b/images/mood/moonsis/stars/green/hungry_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..0659992ad7ee902e77007d81e5476476e8691cbb GIT binary patch literal 1636 zcmc&z>rc~H7(NAL)D=Yuh!oTgr$yPuIDk4fGC-)*4M8k26_vJ}m4TWtj5t9Bu_I`w zAUY3XX00qbQ7f`38Q!=Urw60ibW*{60Gu;wG?^NAJA3&30sFf1q0Kq(`#$e;X$|RV zv*+aNiJrV5BZm^g2;qbXLZou1lrTy-C4v&Elqn;O5zdHUL@M2s6UGVWL~tUNVJZj{ zgbN}BkqQ=-gh|3B5t2v+ni3#k6ul_oHgXuHoKiulR2JjT80Cx#My0|7WyUGzRB$R4 zTIgniazTZlQelZLopUBQ zlZs&QK$#0B1e1z>&_XwtOh_gbJKz@VfgdmciXjo2AOfsG6TCnKn*j}MfMFW#sN(@g za4r=qp%9C47lKR0SqKIXl!fF{F&eQT2N(~hVJ*Cbd2kE%zz-Mz#gGWnzyfQ~1TPT5 zWUhABN@lPU3b7b>sYHnU5jYY?q{tAVAtl6u9AG@0hPCh#c7P>@;Rg(W zVn_sOV1YGgf)|KjGoXPDFifKzbv)oGzr_FHLnmL&NL`ejl9ZVm^JcWS3KVoNeblq? z9W_E{J zy6W|6^Qjw$>wMHx(~@J?w_1~SIKm2_=#uUwH%?z;v>nlH@ztuzz1%!&u(!!kZkz2n zHRZ>zH8agceYS71{LQhpJWr|9uqS&R+v#!XO^0r8j&C{aJepg)ym{eIEAKZuY73s$ z4n&4%?{t>;w6u6ihgZ5*4P-c)D(lSZ#D;6(QEMM8pPUx?M?j!GYe8*+D(cqt;5%_0 zMR}G$%S5ZX-Tzq2xrC*f##-~}in;rjxOVSwxO?VW^qSNlb8*o%+ps6D!C~8W!uKezfj*Vx}T-bec{`lbSG3VCyf2uW|UsF(${`^_{Y14f9^u;e5 zb6TPYQf3A;CsjU7E$d(L_(*(^&2PzcXGnB(PFV4jzMW2c;3d*kH74KHX-I!$IJkOh zc`2!l^zzjiET*#SmGA5cTCpRy@)hgql;Falx_Q%%45dC(7g~2^zNQ{-NYD6fsQ&RN zpOKhG{YOkQmR)u`yFL$yFgEFLjP9ukrlH-Jkk_`caaCb8y>=h1>fO+`n0npSFMa06 zmsne?ja5;)&h3%Ttcb~>#rvp-JaUu^Up&UM=^yAmtBp6S{OuiAqX%=_k;yffcU zZ1Xx(`>l0Bb6&*yye>a$=9sy zcC3r->3gduBze#i*VuR{yme7U@0Dd25=&0^d>7~nQs*=-RT(!EYi#uKnq!wIeP8;# z$aC|Pvh+!3vul=W-&iMG+c!KI4qE-;gTanJWpBDWxx{}}oN2@T*KhadX#&bVS{&c@ z>sLXY`-i413*Bu0dHv8yYrTJTb=tW28JY2on|f6j#;K<_m)7N4+9zZiCR8+-9ajcw lB61R*-yh6}*t)E(Nyf@1_SEV8e{{nUGt%m>r literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/hyper_sg.gif b/images/mood/moonsis/stars/green/hyper_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..d96cae3d387c2d9975f6fcd637c997ce32848d00 GIT binary patch literal 1540 zcmc&z|4-Cq9DfK&Za{&ZsrZcxq}xG!d+-)ze81yR2?o^6p_4pMRhqdw#gv^Ss~h*ZcM5 zE-Tyka#FFDXvyDX`A|X_A)F9Fh*a*B5=IH9L{K7?GG&A@!Wj{aNTr){!Z_ia2u`Fj zOa)BET9n!3#vN8LNN|FifKzbv)p3#sp(hQHaI3 zbIt^3QV|RuD09JtU{cW!TIlAI3CW~l2i$@^@B;=wF(g70M1VDDf)|KjGoXPDFifKz zbv)n*&ZS}{6k;*%LU5@#3&G%lvXERVMk5yF0OR2_tc8~_4{pI8_yGf;7!pAmSYQpB z-~}Ss3}|2j4AW>w9S=BC$qZIPAr|89 z{D1*a42d8OEU*Sm@B$HR1~jk%hH12;jt3m&m-s(?Xk@_ahQfl3v^+yXOq{O|C}{p! zp;F^JdYR7h--P%-AwK>aOoOiRdjIEiMV`UV343t(_70P~%TPC)V7}-HZVyuFpDMrO z@Ro#UZQkLGcq_QQ!Ps158FZgIpZZ~od0JSkVfu4%2bNq{^A~cn(zkll3lrK&=jM9d z$BP+SlS+3`|4=(_pYGYWb?qtQ+hcNU>M!$ZPk+8Ev7{+^XH;VOY`XbM&CHlLyneW{ zy-Yn}ddKwbk(A*}jTJimRKr9~L+xny?V)u+w)mdwt$Qz=8M(R7>!C%7=D^NmT5Yh{ zQ;Mr^IhnQ0cObUR5i{kk14uZ0-Lsu66yj}Z+3&wxPAd;~Cv`l^ zs|!+XiOBD9Tr+kXS4FgXN8K8|s(C}{@0!~E*|rx`$~>-dBl#%yS@Vt?9(!ZkOV(uP zBlq>(w$LjUhr{|p<_Y7mCC}Vf-|uwkHI>^+Gcsm2&9*EB{+b~sPpnI-dR)3S`bJ>o z+aJX5*Y_2uLN7cK?;qZh^NI62*Eh53yN2Nu&C;Gwy>qQG@XN~AI@bI=G}sioKE1@# z_0y@1ez#X^Tza{-tcbIksr<_OM3n iZAZjeZP#k;rxw2^-LS*#h?#oN?2Kv~Elwrm)qeqe4TU`b literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/indescribable_sg.gif b/images/mood/moonsis/stars/green/indescribable_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c554f3e0304c0ee47c53d315aafb7dddac5540a GIT binary patch literal 633 zcmZ?wbhEHb)L_tHxWWJe3I%p@#a5B`s-qv&iqvaI-Yto|lgrjGF6b&Ac{?rgb~=M4 zL&VLXW&dYy`m<75UoqmE9ghHa_yxYOi-M8ogp!k!H8nLQBqRyxUlPmfn4D!(F4~_ZcPdd%!w-TlbW0>lD4|) zycrAM=|_rcX^*d2daS;A`n#pg!V@ofS(sSa%Md6tk(#UP5tm86@s9Gu@vTw)ROTBkLLOr{y^YpE*Bz8~!rb`tLsj zGnb6Vh6M+kIa(tkPF!d@*d`#(*W)o!!L^ffa|_lmxQ_^f*ZT@|&X?p)cHq0CbK&m{ zS^lS=D;f?Zu6*&c#>#VP$ITkHrOFK#U(~qeTIFv2eX-`ymOK64dH<~r=D+_gX?-~M zth8SE&s*gw43$z<0S5IA&9U97t@gE=cCrn*z5O+YlczTJwY3|~PHCOq7M_{ix@6Ui z<)%q;s~FZu@vK`Ros&C5e4?J~w3fDgx=C~9RUOgZ5L+#~MRspynLSUI{i+F>DIUQR zHxA#Pzn$T}z087z&kEHnU!SV8`e+&P_1pI!KUKv3{Qdj&AJZ>sr40`pn%I86TrJ4N GU=09zasze% literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/index.html b/images/mood/moonsis/stars/green/index.html new file mode 100644 index 0000000..fa1fae9 --- /dev/null +++ b/images/mood/moonsis/stars/green/index.html @@ -0,0 +1,82 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
achy_sg.gif
angelic_sg.gif
angry_sg.gif
artistic_sg.gif
awake_sg.gif
blank_sg.gif
bored_sg.gif
busy_sg.gif
cold_sg.gif
confused_sg.gif
dancing_sg.gif
dirty_sg.gif
drunk_sg.gif
emberassed_sg.gif
envious_sg.gif
exhausted_sg.gif
festive_sg.gif
full_sg.gif
grumpy_sg.gif
happy_sg.gif
horny_sg.gif
hot_sg.gif
hungry_sg.gif
hyper_sg.gif
indescribable_sg.gif
indifferent_sg.gif
loved_sg.gif
mellow_sg.gif
mischivious_sg.gif
nerdy_sg.gif
pensive_sg.gif
sad_sg.gif
sexy_sg.gif
sick_sg.gif
silly_sg.gif
singing_sg.gif
sleepy_sg.gif
sore_sg.gif
stressed_sg.gif
thirsty_sg.gif
working_sg.gif
diff --git a/images/mood/moonsis/stars/green/indifferent_sg.gif b/images/mood/moonsis/stars/green/indifferent_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..0195f6fad26b7152e4ee2b96d156ee770a089593 GIT binary patch literal 1516 zcmc&z>r>QK7(QHM6BG&&5icuS{RT|eJ+dRCAc(u55`s88T4cJ^nH7ndhES)$;l8YK zNw5(Pf-RRC9F1XZG|Zt9!CLEx*r=`Ahb1G4n(1QNYGbE|-#^gD&WGJO=Y8MjeJ;Bh z8_lbeb}K|7f03C(31NhALIfdFy;DjUC7cpLiB!v!5yl8-L@*-NZpsPcgmWS|k?JrN zgbBh05rRk+i%P;I;gSeRqzX+5kT8l~6mgq5j8aaipj4`hac7KjMg^l%<$*HelyfRL zl`1WCGeNnaLQtu)#4wYTODZIlDrtxSYtRHQ5W!}w0ye-fjds-WfWsLRj7e1?7URx2 z6P!s^FnFNM1rvfvRX=ErRppMg9pk&a;X}PSdasZhtseYUcx-M1$*EJ41i)t1ZiM_HE4nt zh+s3IfekQBqaAfT;7BzySP6w#jJs4LME(dI2_sTuh|rJ{VnGft9!|qrcnLee62tHV z20$?+f;6ze8Z^NRM6emqzy=tm(T+MEaMWMo|L~!ev$9Rw^3v0COorw906$RBJ_^*V z#rLuqIx~M067mo63yIAfa1K|8JR6_y9_SjW3y<5>k?HC-Re227^X~9tVH%@<(GQOC zg1C&un;UdH!jILM8_R41u9go|k2G1wgso(Wu}%NRW9Q|qceiA$PjpA#9Z@bdEUu34 zoK9CVHSv3me=5UuW4*f)qgzNoZ>D3>iNbN^{g1b=Dmavqm9VPFv)(#dcKx&QxPXEA zM}luIu{VbWC-@#d@jQ$y#4gp-|5dMmo0onbNJFoLRsv*w_YmJ^p%(Z$}rbG5w@WUq9(w(Les?H$AymBM$mf@3*fW=^T1AUAtEi z`S$xKdbiAU8B7+Bgu`(J^5yuJXiQ z=nPzW!TCXU{Pwr=@**_*o!Jq?kzF~F7TZK^H0ztN$L^b&uv==B?zsz_Y*t6i@xG;w N_!ghG*3XZu`4`=-f$#tT literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/loved_sg.gif b/images/mood/moonsis/stars/green/loved_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3d6b1f40409370d89075b52787d68f1e31b027d GIT binary patch literal 1726 zcmc&z`B#)x7{0^K1WF@w8W<2p78%Tr_~FPR$_`o@$&w3tVARXvXljKWQ$rD45E5LN z3nDH!fm%^0$K_}&f}j`0oHGvTvG5>*m2Jl*t-c<w9S=B+QckHTDa2yj z8Kaz0Q4$OuC^Jqur=p}Ew9w5&%0((lcEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ue zQO5%gXH1l=ghDLFopUBi&O$JFpv*-kN=73VM;#A1qLdk|ghDLFU6dk3{shK@Kn;PQzMw2|K_N z!|($JKrtkOG_b%LG{Fl*uo=+61{kK%jyfK2q+jCy@Szc3nU|238W)q2F!hZowlYxA z{AuSLgYVZz>5TqOh|@nr=H!*!bhxd^XwQr5rH*4Aw z3lBRkIl<2<8ojr_sSejKvdM2tUAyD4!RBFbhI5(cpM6;!D`RFRSKQm#XfDY(WB6pk zi~#%V?vWcen&w`xB;DEe`HM`0lY5P&-P5w`x0}y>yNYKqMLF+J8Zar&pI^bvj!U~6 zrl~5)v60j|UBpVV$k>t}dUEXT2fHUv%Qxsf*ZlU~TeNUyu zQ2b7dcj}YgcsE_H(rR?jyHEA9CHkjELvh|~2kn%BgH}2-v~!>9tGl+;xH<<9tCs6p zv!dx-`}GdC=X=fSoGac$sSCJlT)f?JNtN1GE5GcQ8?vUsmslHGtIIq8b}w|DC-d-6 zk*Bu|9>^>hc~F(LIj_^WywbxIy~4E6WXx~L3#?haXzkEJVrMs+r2T&+IS_4d`${`Q z8C>0(TkzAtbwO@5c520(9^1X_sz#?S^PIgWTJIl|67Y**>$v<|wPArv z=Hw107man+Iew>I*i%2dZkBq(?nX_KgIZQ;^Mmb^k+*Bt)GJmE#&x9EJH*LW$;~-l zk8|?FZskYvhTC=3Zn1wYxP9tVmlYqUMU^Ti6dsx+yAd&bv!tXws;PhS z$^PxCJ-!Jxx%MB9YdCwLH`sDF-1f&4dY4U!lbR+@Djq-WRK`VXL%NT(PZjY;h<46h z-`+=M!;8N##^z>iGhhAn__mG>U*_pb=Uz}HHYa@Z{zju$SbRu!U;M_I%|p+(TGR=4 z?>QZnhxjyKnjSXYqzSzt3sU>t`q}aOlydW#+H~uVkUMg7*)v7@wVnqZ9?c2eH#42} zSG<;fy~%WBf&0{_6{@JivRYR+Pp4LSnzuuxtZ0jWjYcRt+gCt~bqbxV&_D45-SCc@ z)jrDSdt|yocUzaluH&(r%iA3NlY`?u-i<%IcI19lR*81Vxcorg5X&_+(%6jCBPM0u WC2dX(y`J}w6?}Vc$S9MM$bSJHAkf?Z literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/mellow_sg.gif b/images/mood/moonsis/stars/green/mellow_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..10e9b06a0339d41b4baf3252a31da5e5671104c2 GIT binary patch literal 1499 zcmc&z>r>QK7(OHtTT3wpgsTDDf^B389N1t~lH0Nfa#19#HDQtCf-8>0 zB?mPTuw){K9n=6P69L_(6N57pt4pXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)(8_1ild?A@#APN$yb-p@4HUG0xvS#v zy>fxh!rz2=J|S+N%T2xQLsgzHgqoebr-$pjb?Z-<934rOt_aH|r}uF$mEkGdPxkQw zU2wef=qi5E&G+M@lwKT}k8df;p{>{eejO6$zr_c1TezYO5D)i(` zg5IPG-D&tkKU6o?l^5lIlq~8p*#o+Z$Mqk6ksDcXFgESANSiC(GO}-Ca9mf_Wh~VA z4x4tHE`Ly@*(zM!iRUV#>cbikO3YQim(Vi%$%O}5IhnQt zcPq_%mj0f4#kS$mN10`xPh9N1lYW2ep7Y~JoTJs@?vozBezt8#L>QUX&4iVmT5(}$ zDu&qHde(Nndi!0i!4Y(6awO+ov3lUh=BBk*`a` z?k8PL)uk7P8r3?FEnnWsTR#x-^D%RIgx|3LuKYUlvhbt=`@_-Z_{G2dZMC1z8|(_- zfBDU%9{7$vdmSOG{{?7razc7(b=8w$NtfHVfV;MQ#;Wc(G`<5H7Y91`HH|A!51gs3=4ohB0v&(phm< zE+XXxB%pwxTm{@l)Sy6y*>OP#!jNr{AZBDFXq=+cojtt&z&`GLXmifg&9Dlv0Su<09qRA^hsBs+ zOgV+H815{K35zKw7h? z_yGohVvq==0Sj0IP2dGYU^74iHh{r2v_l;p;7~3zuo4u)Vz^T-LdYKihlC+g$Phw< zlpq$!0gMNy!CLSV>;RT941RzCpco_qX}|*3KofWY5!ejSfDK?U4ed~e2RPg>@qhSG zP@8CN+^*2z7_HwHHJ=9*6t4whKlt9fLTBY~f<*ryo@kxEv+i!8$lg17xU+u1BvVGz z=({ct@q}Fm2X(S5+5WDtj*GNX08#AnM#`@arCdd;!88-g&)#?^PuIbDfWN(0>t zHb%w+S+<j26I)!(8`i7GJa%o=o3jUXe|g79PbX(LG=?8Mrax0AkWuUF@0xnX@-!Gt-%*A#5;)cClJ z?MVImY*ddt)Rd*JBx_#mGZ#y<90rCP_7}CLUCTCBbg z;6VPJ(d+JQ$ER?v)Z?M`{l*CgiLm^$(Ss)Orc#^xd5u%N7Z;aYloEaX^l^TS+&NW8V}ePy0XuiYCt{G@3v zc>L1>gH3c`kt|_%lDOYd`9t}Wpm?KKQ{{Wo8P`1d$?fx1>6(mrWOc;Lt@7}r@TL&` zgQAj4xtZayL0qh>{v+1eeqOwFTJ@Q>8DtW-Nksm#YQb8&h&YF4+w^-p8PCxDu(?zq zcGF$<&nr{jl>2O5E{X9SiL6>3dzrKZ7n;#zObYMpkps#wr~Hg%&vND1d56_9pM?RF zu-v{Q`t4-1=R~uU|BiQZzt-?#jeq(02){b1!}-rl_2A9L$KPvD%&m`{X#Z7mdT^=N zceFmN4=X;F9)3Sc;qS6GAla+nSjz1bk2j)pk+kqiRY0NS+~U;it@a_c9pBG=*Uwt7 zv$lo0TzQFW$2Gw(qCJti29IlXixYFbCVpq{;lVw=&OSU`gsX``hYI8*TXo(xaC0qMRKO%yT*o{6+2xqeO&;(nK?yx}`-58rI~6B{H`VjC{H}YKkkGo*s>Wy+cQqzn mG6nzIci|xJeE=baZC_6Y^(!+!xkE#9U8 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/nerdy_sg.gif b/images/mood/moonsis/stars/green/nerdy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..705cf7d43521f772fe0cc1b23a5b1b1b79b04c80 GIT binary patch literal 1538 zcmc&z>r>QK7(S>li$J0agCVyK%$+q6IIxM~h1Oj#NRUV*m~mP3xDYWggiSMq39_sP zdBL)S+8{{D5DYtw4sw}shfAxT7}CbH!VI;nLCFRNqlweQ?;q%6=fm!t^SO5J8Ak?vxTn38zF*B9$^_gfYSy5sXNsn{vW9;hYFgq%uqe zVS;c$gdkGEqLMI4xFkXnsX$W#B#fdLMcn2Oqm)xBD3!`$+!>>sQNgHGc%aNU<(vvm zr9uncOi(VU5L7BGG0Y_8k_t(sLK-5#8Z^NRM6emFfDJHAqaAfT;BdwSV^UFw#kh0M z1ZPqa3?3+R!GvH^(GOba=8_4?q+$o$f<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;0Vs8VkHz}G44WesW=P4;DNG`Tq;H*7UTfq;WVs;moN`*!5;Vl1E3fZK^juh3?uOt5S)ATAI&y^7w=j>mbT1?9#j*fOa zG+Y9dr8em`#R&xlLuPx@dz~Wem+_&xpx(I&=i5a&(YC7|<+{Y`*NZmo9UnRsu%ac( z8mX^&_sOa|A(o1X>C)kJkD`(_cka9VCNK2+4&~}I^h5>}^|FLujxj zxIQa2Ke}vJ!Q&IZ-S}c?&=#0t{j|(@wI#qOp%UZ{MHt<@8Qq2VK(i!J>uha&HmcYtnP<&7wr~% znry; z<8YeY%{3-E+ilB=*<&~sSN!10g_7X`OTy#>-HgN87~+_I)c$?v52Ko_#^OUg$F|2- z)K>NYzZrSjL|L)++>bL&Po6a@&e{{l}=BpWXi=yI$BIbN>P+1pcKTjlI(_MV*qwXNIp6ud@9f>+ z5b452aUvu_Z_xO{2oVU82vG>p%pPMzU_@d>VMH@wOdx_lB!MUb(M&cb5kVr7L==f= zrWjL*pb$wRib6Dlg=s|4h@=rkBbtH62#}x@av=!2@kL-vVoYI7GmT+S5SSz|MPQoY z0bzo~B#9{!(+n-hCMZl&n4&Pvu!LfQ#w3j?8q*AE5CN=#Ch!6x&>30*Hh@7jq(dAI zV37nt5d_UBgvPKZNrEB?nh^{g=hIEL-0W6xC8CVGlp)u@fW`r<* z7&uHAMhY{8p}~}3EHDQ!9-Ibi!Ar0MSVA%Q0S16#kO-s!3s?h9-~~jWGe842fI&5+ zLmUoZF<;_;@UW++u9B<^7cXBU@pAJpH316tZ_OtA!`o$?&iFM!toO)-HA{B7qInk`D_-~Mpm{+uQT5C9u()Ti6TS~9G*$ar!R_ZtTa)s zuZq%J@<;hq(p+1;a&Su6mWOOPyFs$J;YoCp^hQT$r-*$tZ`; z=kluV`nW@-R;49avYzDtA0vm#&t`Z`rBKQz-tAkA9UGnBE-{FN}Jgek@UW#u&MBx_9<8zv<^E2p{B` z+wS2XS}#n^Q63})X7?Sp_x9*cvJ;nXPU5OpTD^>5d$3Cir&x|s{j-vtM&X(4i1DY`m4Y)kD$sz}?z2{c2gkr3op0HFXhHVfvncVS{h{P^+K7=9m2I z+n%b*!}gW5e3yRY^N>G=;(K|G@$T`@yuWG7_pQ$x+2U|MsAj{~A3QR+OI~0$x_t0P zUqFb;QEOJdhpT=))AU99j98gx*3N<{>bEK5YlRH>^PG*%`UKYUb7~PH-rD_MH$aQtn#(?DV(!6 zNS5XBNnw{Zf0IM-Qg2ymnnw+M^p3S%70uU!%gxg}syA|?T!Qsq#(OAD6PM>KJLNgi zgIn4m4N6vW`l}XD$0AuPp0m!@_MEWZHTXO0l|gDqoVXqC!?zon$D|cd|u} zGS>woqpf8L{^zq4N$!Kq3U-r4OYNqNp4KY08_Y00+ z4Et85XgV+U>qc$DrLK$9&I*cOu6|^;;9gy{_Z?&LvB18!hP}br?KKr%snm0p?Bv`9YS60|l~}qA;n{T8+wm{l4!^$u D)Gp%} literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/sad_sg.gif b/images/mood/moonsis/stars/green/sad_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..06d2cf961aafb9442d93c67760b9513e3c15cf13 GIT binary patch literal 1580 zcmc&z{ZrIM7+(a9Gssh*z!&5=)RRnsg_{`BI1Y|OZ;%8{EtO7P4#cv-tSK@Dfnzv8 zkUt;5Jm_mL=YmCJEeqC!YL7yNTo~}VT^D_1S3-ErkpTNI46P=sSHy= zm>^sbA&6A4s3c4hE{TvtD$tYw38Uym5x0rMDCLw2N~N+Gcg84ZR4^(P9w;+TIj4eC zsn9|<6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l* z!I@M9g9pl7Fd>*!^n(_?j#M&(l~9PqxJxBMj`Z);k~f>-if%@<7M(2{A^mA71FrHwBYEO(4JudZsG*=4ia3&N8tOdpTA z?tIl_Y1V7rO2{=DuZMc7#{7niqPrp_e)m7Qaf{aYuRYWoxW$#9acst&@hr{ofaTM| zkP<_IbD^l%6Bk(2{#puYeAj>dnQw>hUT?d3alEU3y$HFi|GNH|}+wOlue|v+?lDauy+PTh)9hudp9&6LXOvlE7=iUpK z9}ed<+-A;VdVkKw;_j!`9~Z~mP8gWV>5`dy-`DRpKZ$B%iJwoOrK&jBt!~`@q@=Dd z(KCBzjZgIXy_=If?NQw3W5_B>c^dM`A)uvd+4x9HxoOhi(K0WuiC88l{6{R8%GBBwht1BT zDMg+b>uHy|$zP?Plz-pu-l9#NyV4P{Ufs0cR9R^2aMrdZ9;~wV3R^*#z9DMcSo7u8 z_g1AQ#km6SUD9UJ$h^Qr(jGJ?!Skj60+!{StpET3 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/sexy_sg.gif b/images/mood/moonsis/stars/green/sexy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..1313b8f94faae4e1126ee11d2fee8c69863113f2 GIT binary patch literal 1693 zcmc&zYfzL`7(U$A1wnxzV$);=W(Y{s16yj%C@TmI8n~OHf$q|BMBExJZ{#>3iwg$J zkaF2WUUmZC{jpOOz``_=*kKH-vec$JOF1stT zGhbO`Odtv5Z!&c#A&d}Ch(w5x@01co38zG&M95{z2xEjZA~7Q5ZpsPcgmWTsBIIEz z5hf8X5lJFK#-f5SLAW52AVP+w1V|V~FN(NL9Y!gqRH9VKi*aX+az-Uah0FtG#wq7i z;#A1A(9I;uB`Qf&$Sg6;1m%KCf(n^5M1VDDf)|KjGgbi`V3UhB6j7f|MSs@nV z&N-7f6S83NK$%NSl9-V7gBH5EV3J@$wgYa#9{2$RpcoRN2_nE6G{Fl*uo=+61{kK% zjyfK2B+i9wB@|*Y?vliX>?{O>2g;J*LN*$)AO{!^r(rF;gn4ia_P`Gq0L739(!c_1 z&;&0K!Dc`M8(^45JL-7A5prg*5(=>xcOgfJ{1G@3Mx@9Pp&=#2f*fExoQAdV5_W(k zhT#VcfMQ4lX<&ghXo44rU^AeB4KPfj9d$h5$iKw@;X^H^ugcKtw9E1`7S5aR=K~7r z$Nqr{_)eapGxawi%BRFfIV-Evamk{5M)jocL2X}k&;`S`1zovS${9X}+chDdTuF(F z-cXl!?>Y(8#5GP#gsJ;gQJI-vE~R~SnYO%l%m+f*U~N=#;qR3?i{km@@@F4Lzjr?% zpy+DqjS;QoT6@m4q2X;^+UnZSt*ZvN>V1b!`)(;Ty`k=_x9dJtMYip`=WQ;F-QMYF zv(zi~?!P=sH61pxq>bzs8T#CqcW^JZ`69{p#BFE!Y&v!?W# zn8sx9DT`M3W5w~%*2Z0t#c#g$RigLej-;q?i^9q}hF2?oRrdaoX1<&fI~cOyeATF@ z-*LAzA@^ES>9p?k$I2SNpR_6REHhI!n0IMQ`|Q>a?2BJFhpQH~=8U{-Of7EjuH5@V z{MyD+|KOOlGmHK0sy(X76-V={^5Ye;M*pl4?Ql(`J;a(Fqp*y5=f~_xiYU?ND9ok; zORb^DnBKH^_bg4k;|D`O>9127+kA6s?tGqKujy7gi+Z>D-)$;j zCr6tLcTSGB7_5&wB2CSk1MKX0Hft&CnJoEu%ZKG9OXVB`Uj6SJ6AQ0)I{T|bV{;B? zg$-XtyJv)E$#Gh z!|BB3!_Gr*uMM%L+PB~C%v?8p@#2XZL(7?4&UiI)G;Yp9ju9+rKvBoj=KQliSbehc zpn2uaNXvjH_nW{aDUbG@d2q*Ly{vDpP^o*qb*>zn_u^Qc`f^y8J9ux%?IN?wHNQ2a zttb6%u%k6KV!-pzyF4kV#gnjeb82z0W8cO&p8=ookgk)qqS-4SJx~NYHYFU6yfsv` z&hmxvE!UIrpQC$PW)?@Rj`kDr?Z4>GHl_abZd3g3hWEGZNV}PAf zdT@W&OMMmk7b>q_EcZ3)`f|^?$HJ>&jd>jKZ1Gidb4_?m1VGVaX&PJQ6U l!CcMc{X==-CRd|=bzn(T!5X)zxv=bfNsBJiZ9-;C{smuH!S4V7 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/sick_sg.gif b/images/mood/moonsis/stars/green/sick_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..d9e83b7a8f5d4aadde03956158edbe1baf41257e GIT binary patch literal 1915 zcmc&zdo+}37=I_1=;m5GuAOmPNj1C(t^Uwm+d3UKsib!IBxP5=eSClK|NH(ibDsBkp5OEP{hs%8-|yz=bkq`A zqK|0hV1x)l6hbsY3>#yN2u2h}G)4@Y#sm?9D1vB$7`7Tyh){^45KSS5ZN@YrG@@uk z(}-cQFoOt#CJ2V~WN!jTx3DG!q6>45k^(u%tl*um+mI3y8pE7zNk>2Hj8&dANW>5keEfunJ)? z#1utniZHBT-~nlhCNxbLRzJ{!YKkE=Lm1W$a0~1KKfnM`3=%;Thyd0=6L z4Pej><&cL9I5b5utd*b;2188K6vH|Tf`JF5X@+80qhT$u2QVI-25Z4fFb~`Ud%zDc z02G5nAPrc+8fXG9AOe#C8n6Kjx}hBMZ~=#5cLr91LKqA&!>$na4-1D4!%AU?ur$~b ztOfP}#)H#fEqDob083~FKfnM`3=)AfU;%5O3A}&^Oa^Gc1~BM`a>&C49QGyt4?jF+ z?SXy%egaqFKHKelB@R&FEh?+K!oT$jot4i7sVyUpnxTihsw-Pf$11c>UfrFqY3gZx zDxp*sGT!Kuddg?)vd!*c`NOt@Q}*s6d412!4Xyr*y1wVTh#*UXtTj4v)T@5yZMHLT zYCc|E>m@PA1Ig1$bvbSlyH7=(!}+E)+W3&N`e>eM-EKRD@b&Y2nOJMk{7Vb~(8X!7Xf{8e5a$1HT*U%%Vj%qyrl(>x$N&+eyd{y`shKJz=f32kPcnNv6)Ziz588 zlz)+MjYW~4lSZvApVSWrxLB#a;>C!0y2P{pVzhp~rn5A#WVZH_J-517N06I1TfZkT z$Eu;Oa)aG${f)HqvkmnP1F>}~wU6{Q*>|Dx-|u3wHLgWA=zQu{6}*e}1IekDgFN@< z4Q>-{f0fH@MDl_j2UU^ag5~No!{ZCcB@ra^*v1saX zskXk;@T6ds!%h1yV%tv($9e=JySBM{Ubd=%NqRK5SXC;^b&Rr)crA$cs+II)oERwC zGUyh)D{R-iV9q1n#USRDbFg?!nsCO^S#L;mM9NpuSdhBLYdqv9D63WE+4NlTNQl<- zKAjYFucSA!RGw91eW9wU!1&74j*+Kldb!`cy<-s{;$a_Jx^?2t@y$^^{4}SOu|JCV ztC{q)(|^A!t4LobaV)HjS5IzQKKz4KdVBISGqS8$4vBizXxf|Oiid^VIp6fE{@*^C z`juTjTKp{1M2}zQohX^o`#z>kCD`}nHj})>pZD{_zuhMvSMU-NUYrXLyIRW8Z*P4x z8nO27IM27n$Sq7m=b@dS&z6QyWBGq-)tyZ~TDLHovG?tVO+gX2NH&*md;L({Q50IA$X1nlVacW! z2XBZ;PjG-vda!nxrBR8dV8;fV=~@51TDq~f+GZNwG`26yzPa6ch&Lw>L~k^k`qsqB UzV3IpZ{0Gu>7Th~4hQY}7uqH{?EnA( literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/silly_sg.gif b/images/mood/moonsis/stars/green/silly_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..86ecb62d8d9207342aa52e628e804ba54cdff631 GIT binary patch literal 893 zcmZ?wbhEHb)L_tHxXJ(m|NsC0`QgvoM_&~R?Bt5ABJWj4Kd6noTM~IEm#tqs@^)I} z?Q{l9hKQR%%l^;a^k-$nH9H;w?(hqIk>`Z|Gcer0e?K`nSyNL}LPFxefdf%@Yc{{# zFVvvM)g`<9-`x1qGGI$+MJWE~_Hzvhc6JPKHPSO+W(3-!_>+axhCzx!2V^J6n+$CK z9eN8qbfo%EqzE3!v6}C*G=!NWVtr#**=bgviJ@<%datY4?`^p4j_u-=S%$lRw;ezJ zd2O`RzUb2oDS^SYb&;_-)d_7C9ZfAg^$q=A49u;JGuqSqrX(;k&8Q6!7WOTf$~-;E zUszDcLz&tj9UryV^vQ>RnF%caA8vQlW45%Xnpp$@yJ!MR$Y(P8Vqo#sjtxZWXtsB7DWBr+Gv6JuqOfzEZaH zVM(fw+5GKUhQD9d9e(_va&zAC?zuI!nGDTUfo1v4g>CMQO-WfjksayX&E5>mHI0=a z(*v2AX2*mnCEyvtd)^46#LPmj$msCcS^ljNo0z zm!D@iDJ|Es)gzBV?&!voM^DOK%?`NvQ2z3Z%MT^5Jz2sa|MBGu-ZyVcmdMF`yzuvd zoW!~v+zLkzvqv0rSh2e7?F5m!4f{&G-B`QDDg+!`em_!-H7oy+(3%}!aA!;ZkFvc{ z$Jrd%CU5eHyyM!tbnWzqRz8`JC#fo%Yg*i#c+p^4(v-Q*v3y69{2yGhJuuHHR&DCZ lHHFT48FzPW)e7Q`Ib5_>%Vo{YjVTA`U7fW}ccKD=H2{-KU|;|M literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/singing_sg.gif b/images/mood/moonsis/stars/green/singing_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..099356a84c2dff13ebbaa1e3b6658e1a5d339a9f GIT binary patch literal 1639 zcmc&z>rc~H7(SJXg0Qfvh)mQ9YnT#JIJKdu8(OGZfhadK5d#$t$iU%bf}3uxunrKp z6i^O0yf7!|+^TcVY|hBMP|a}>VzgcoZ-j`tMKgzNi#vPx{Q>*B^P$Z-@B2RQb7>bZ zwZxcm!bv!JK}HWHgb~6C5rjzPPAOrOa7qLvQYlkL7$ck!!H874DJP5*&WYeeD#KI| zCI}Zq2qG0MDhZQ>OCltZ3N$4^!YF!C#BKC2N;##1QmHJ)oiWN86^u%S2g;07&Z*#3 zDzwne1m%JXL8ZbH!%R{xsgP7Eq#**VK@+?{1e>u6*Z{*c+EK>?4rfd-CKZKPj63H{ za3&SO;DIt1Ob8|w{h)? zj^JD>Rze{b<1Pf3in9<59w-aRrD8Nm`6F;7j7X6oLPJW31v$WYI1OvzCF}r848so? z0L739(!c_1&;&0K!Dc`M8(^45JL-7AQGSX4!-rN*NKQygH7{JA5FM%aQh|c@Pqj}p zz9UBIjQ&l?_t52 znSIe=44&(p`H9+X52GEEVw&z=u+$kw8lF0JOZUuu$M@8YC1!7by zMFVE9ln(vp{o;d^{b?;3^@RbQJ#&6;O8jhn;=1&F$DswaYm$QdzR1{XHWh{+(ysR$ zitXL>WaQ{jR&((KYw3?M71}6UtUYmi$=W+7GG3n8dRUdDH8^Lya_(Bx#yeHJKHU3J zt+%7MBVbwP`AzB5H1HhRyw&Ex8ThI=|rij+oh#w+57l7R~6JU)NB6x4+NZUbgyPyJ?*(?upIrEB#GVqeV!@;Li?nXz@fYoz zGJZ9*s%=;D-BXROvORHgw!J=Wv3I;7sNCiXySwPbrwN{TPs5p4%k=7z?6j>Lp0_29 zD-B!dr!VSi^u3gopIS97WM-#D^Q_=Ob)5Gb0}b(k>joN^=(-1-+Vk-@8j~%XTN_d` zs&iXXqfKk#l%&S~XHqd&Y9>1Zw6R;l`*PwdCQV(XZg{r;Or6g>`_+>xLVFs=9PK`r zQDTd)iS)O9tL?Fno&L)rE4%4|9hSO+oo9xkSfbq%W+)smSNQLrQa^pSPjh!_%XHIl zL{;%n|Ceue{8oGN*x^uDa9ho@6~i;FU(=RV36H&sl6=hj-di1Xz4!L z1#8n+*)5)3N3G@@zax{*x?OAP=~P2>bL_EJw@COVrsKQEDT6(I>bKUqxA{JD7gxDg zT?&f0b+x~zDZTJ?#G{9rt7gNpm3cSywH>LywDlj(YBPGC?heW?HHLira$la8pLbX3 zl#NXn4+a>0qf1D#r+N9r4Sr8nhUCtTD!CiyX((BlqtR9F@U6@$-)&W?%Y*FX_<{RY n!(i8gy7|KoJL@Noz0p>;DA1IfVbN_4b6QXT5xPUABJ=(Q{oSmO literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/sleepy_sg.gif b/images/mood/moonsis/stars/green/sleepy_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..26d276813b92135f427b5ff21cdc3844bf851941 GIT binary patch literal 1609 zcmc&zTTs+h7(Xi)p9Fwj(Nzpg3VOHi){y zh6rA24r;l0LrsEAO>8CBr-6ji6B`$SmC7c(CNqDo_p;)?9Msg_x--#Wq00u zYtk%-p6JO_GJGf@j1W$UAVey6N(rNcQz9slN|`dk7~zZvMx@eBIbob|P6Q`X8K#0T zLAW475UF5MNth&D5+R9HpeX?oM$wBRZo`LB$|)6;N@X$bj8V?0U{oqRP-dKRP6ek@ zp@nWHC>K-+DixL(W|DGAg``p;4G~}sn&1T@*o;-c1{kK%jyfK2IAek_sVKx^+&O20 zGpPs$50trJLNKZ52Q74S$%JH5u>)?w9{2$RpcoRN2_nE6G{Fl*uo=+61{kK%jyfK2 z1m{w*5(=>xcOke`oP}WUKv_sG6{8Uga)9x08rH%~mi0K+ueQO5(0@=N?5J|;+YW_os(C1p{1;xvPw3KS;%1}2p0vQ3)U+}+Bp~Xw$oh_*>1D5ky2P`h zXzTV@)yJ2WpNTQKCyuUK_T?3q|9Dk4DfDf0-q<%+xAJUXy@4#*?0m zY0iTeems>qvg`v#an{-%PkPj~u0{D99uB^J`%ahP-j?77RcG>7-^|@Kcx52=SZYb` zpF{gns{Ixxwt2Nn7i^y#;LZLw6<@zTvCmo_zs|V9 zxv|~7XH?Vt{LY|>nvZPb8cKWXSEmKXAGW5K?>dfqv(`>)SAbsVR@4ttF*eNp8F>~$I_msvaw*%$7P${_Q`=EZ(URC zsP9qI%IB%5hEo}1M=GI6REmuK_7T6HsT;p=RBJu`ZQyiBb->O2v9+By zV#Xz2zcfAPcv<`VhGxG1(+8g2>*i_b#m_f?#w$*EFU~N(Suu0)#I)_M!p%qHO5fFK z0vnxsL$3979$FjGV~)=5-dDJ{MAO}PIQ18ux5eS_$TKf*PJbub&%V|By=uq9FLEl> p=Zkxb4PJd;r7?3=`>v!1xp`G{2Evib(6hYinO*ru%_2 zX$c}h^sbNf04JQvxK6q8CNn1`nf@Qz}s^4KPfj9d$h5aKck})+44f&FOik?{~zjv$rpDslEK2zIN9rKlg7^u4aAkqU)R}H+`4&;Cjuk7beyk z+xGqx_{z+_*azML#nV!6C2Z<=oZ$cYiM6Sr>0hiHc;?~92Oj;N_ZPby`$o0uxoXXm z?&v)i1B}D1X{>3-y;FU!tlKnNmmhc1q~odk%ELbiYjce|tkwNJv}|LF$=;dj?%_LR z7zw=Oqo33euyTt}QC#`^v$g#zY_s-MjNBGH;Ni3{@J)2)M+87fwLG^q#c2*26IDVpyp!fvOkCp7-HkJQHaN{Ebfylk zm=W=dE24hZB|92()Z-@9c`mQB@Bg;st?SqNwRfzp8pW;Z$hPAXuU4lGxiM;eW`?TX zJnnqIa@%L?&s$r)itTL{O~Ia^Z41P4~BsNS=19S-n&-a84Ed{Sw>r z8IEUl%aXib=Dy0OXI#}?W8>d*M(k|YU01feJ7ez7mnUP)VmQ^xB9Iv;dLYb*{!@=(t#m2&IFg)upk>bLG*<+^udgJrv-s52{ZM9oVp rJi9*XF@!#BD>@MNDQvjT literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/stressed_sg.gif b/images/mood/moonsis/stars/green/stressed_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..598cfdc803a22e52eff3b585fa7303129c16264f GIT binary patch literal 2852 zcmeHHYgo&?%KDG&k?K`9{R5*ZTYfDn+Yqc$Bu2#FL& z?s9}y?s6Yc$bfw;B65?XAmypl(Fzr&RIB4Cqqbu`vp7Fso|#YcVP=0wp1s#v?|R>N z?Xv@S1-$pZjF0%}C0bt?LO4PMLL@>Iy~i+wV~D^Ii6M#(V>rTbMBs?T5k+TX1i}eK z5QroYMHgcv!bwDsh$In3V__7+DMV0+q!2|zV+fF-6mlU5yY+=*7=d9VhEa55*yA`x z;24Qx6wL#|IDruaMiLlB(}HZA#0U~2NsOXdLNQKZ1ci|lM$x1}1h590zzc{#XJ`f3 z00z~N4skeuMc_Dz;}oqB8pEC-aFW0&S}^c{FhSxZiBq(Gpat0kg_9Ic(RP4aU=R2K z27qFa2%10yum+mI3y45xfCg*;gK9{JI2^zt34)@n1clHT_9RJAw6h=>ctDt>2#Piu z#sYHy5fs8^E9%(jg89uqb+FU?nJo z#;~X85yJdo;4onrDa;Ut22+Buz#PDMa2l)yFToCA3B}+C7yybvB9I0wU=1{Z7Z8EY z01emx2Gx)baX5fQ-^BmI50CoQ9&tpt$Tw8H-PKKp0Tg&Y>FT`=|1Rrv);|+u@CGpq zY$Uz)BLxO#PSVNVhEX-!A*fE$*C;-*uwDMeB)gVn=&?buteH)42(;T>;uy`YEetrN zOz!O~Z}F-4gZw6$oXz#9aZCKUek$z2-atR$r1^tU{#c1!fzxLXMSO{&Q>w=re?)z= zIbO&qM>@?C&D-rMv;4~LC_%zW?_g(vV!=;-O*wyQ)}cU~UYlY*Dmf(i@{s{V8*es&U*3gpZNZ|s;jS^a_R*taEkc8X5Vua8yg zg&*9{`qcaTp4Dfa`WA}tM~P1_J($um4s;k?;WMQ}W(mg!{+5{|n>nTq+x?oz>1VWY z$8_)iqkl)i(n3(P-R_^-qe}mpIzAkuJ?f`$D$PZEx5>=V?~-=5l=BEWMr;7Gh)eYNFI{qOAGy%DSvsk>ye;9gqOl%QNoW{(z+pR&U2e^c1B zWfS2Y-_>indeFZ@J*ZhZInZTdDEug5#-Dp;Eb=>jb&OfwSMTV1i|5ePB-wJ7I&KUF~M+3z_7Ptf{!&S?zQ6YJDSC zh9I;n-|Z{TPMb%kcpkY^9A>(s{?<)z$x1yl?hp2f6}Pp{jtfs2AEz>hxZQ52`&Nn; zL^F18dSXVnFG)_`Rhy8wcgC~&^4Pu=oHnDGCYe^_n;;>da9-rDYz|a&uZC|*)|B1; z@bzPTb7!5b{tC`}&Au{eqp&D|qx5wr{B3QstX1RpX0I5z3&tfJw|aeh=kQEkxJli~ zYAN&8Jyc+!$vZO1k>pp~F!g`T6>)x1G3G*k`&e)$Z2EGdiosl9k5}!?uri2E%N-d@ zEEdj6xr^OCD`nHWwAVk%H50)EXrtCwt}MNc9H23zDoQ zVe-YODZlwuwpCSEjFVvM`mF|$d@w4y{rRGh=wf&K(( zy%^vZWtK9^%Y$#Z70&ZA^-Lo|Z?{<1Wln5MDiborUlGwEj0?6_ijc+S)S|VCAZJ$J zTnzW_sfOl|?bnc~BL3`{sVIPt_4&`<`2W8?|8uX8*FOP!NwWU{ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/thirsty_sg.gif b/images/mood/moonsis/stars/green/thirsty_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e3e77c079a55f1b5623cae1a15335e3c472228f GIT binary patch literal 1643 zcmc&z>rc~H7(Ps_6lmmPm4b?e$_fH12O5i)2tp}t5-aL7Srj`wL04l9Z1J`X6f25i z3wSxf8L)`OLU# zFhRH=LJ+B7QAwC2ToNIPRG=vV5=POBB5q@cQOYS5luBhW?u=2+s9;noJWytwa!v)O zQlW)zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}r zf-|WI1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+ME za0KU4u@VZg7?j`Bw z0lt&R=#2eMNYFndAZV(!t?~Napva{6``Vha9AWLcvWNY8liFmccdu!WCk|6|M(vD> zz`Q+^7Eb?asLwM|6H$Bf-If*l?=8{kulkLig!1|fwY_@8=Q$EOf6HG}UnQ61IO4Yb zArgBhnE2ZZvwMs$N8V|U-r40(Kj#>(nX;v%>vh`G!PZ4RRZCUpFBm&Ef6b~+T%52z zc6;N@i>j1a-PNDmzp}3(OBg>an;qTB+t0hM9oKIzN)P7L&1dbYcdn$S%V+hOqr0Dv z6gNa^W3oReIoCwJr}Vpyjb=P`+k>0bsm$g~pJOqT@6N z7%Ww%96ru^6B>J*G2R+|{72&IQg>YG&P&sJpBrr(pM5h?zARaPw`5XW#a2z$9c{jD zc!uiZkh^VfRfJ@XR2Aroi@R3q?j5^VUSRWOSz^?c%hXXBefLWBRwe7#pub=A9ebVOOaZnO6Q{lee5+k7z5(BeHY$9u}WYx19u--`*2 z)@7!sZaFPyw=^eQ8h&x-j6HPU+)7tx**N4f3ESf8g1{2F|rVsN@sRi0Z^7C&?Q(5f!IZ-qKA z?c4HCpKL1Xvxcsj7iKbq2JH=uNUb~^9MR=0FO9cHmTL@WeD=KB`;TtdEEs+C;K-D< ddcS+g8>`=w^QO{Yo1b*E*}b@BQWzog{{?8itib>P literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/green/working_sg.gif b/images/mood/moonsis/stars/green/working_sg.gif new file mode 100644 index 0000000000000000000000000000000000000000..4aa926a3ead2cc9229b2d3807e5b1a4cfffaefb1 GIT binary patch literal 2039 zcmc&zX;)KM6um@91wks2Ydj5Na4AC@6^r zcm^tnifBMoj7uDf71V_fi#Xvd3RaOi)LGZ!_4rnQLBI5VNY=UMoPGA*=f2<&@suBv zrXd0Ph`t>HA&d}-5QPxU!~}sbfk*;T1frQVff2@t#E8O(W~vDiVG@xfqDVwD%>;!o zg-8lf6rvd{f<~A|B#kH<(F`hrhH}Wm1soD% z3S*j42!kOeNlcNLW&{HdNRt$%C`>c@ffiJgG^S`wGj@PmU=R2K27qFa2%10yum+mI z3y8pEfCg*;gKj8?JY2w`NRno(1cfjdVu~VZ##s;yJRnWcB+VENYk@t0@!&LA3tobG z;1<{eet-d>7$gE|zyj7l6L4Pej><&cL9I5e{}uo4u)V2EjEg|L5EIBXbJ z3Oj_Q!Ioexum><6oCa&bORxi2LNoXQ27qFa2&4fESOZPq1w>#nKm#^_K{u2`9xmW8 zFY$l);nPFr&RGySJ1}C7ulJ-u7C?dj+0uF%{Cj<)^X)T1g9nhs;4zYh%5yn`M|j3x zYN$HD*wvmb3zNtJ$zk))BQ$^^gK;V+h)Ez z&#R$%sdz`x80Bkzx7+#R2~p2l%$wZj=^QkEoyCDUMM&(BeC#Oet|)!3(Lc{~cwC2g zhA?L0ofXS&6^B33s&|Q!q-136L5J$9eF^nlER8{0_VV{)_qRjai_M!C?Tl7Cwv;SL z>At+idRJo=fBCTVG^dYaJ=v-@)6NMm$~T-0&`_+TgEt;=g^F=b>5&dg4hZAg4QGyi z|6sx2Db|gt?uVN)53t2a9hE^Du6qs3>W(>YFOte&k0ihIBM_uT6L>zw0mHNRkZg(P{TiW9}oaFFp9pB%-T^+uFk6khn+ zQE!v%RVM%CoyCEQgvUR7|XWfX3C=NqHZ}% z@NZYN>Li@cNnz_gCvK9kKQ%jtuQ}(@8J%;r%taUPY5h>{f2E{^n;IrxDy84#?sbS4 z3x?>fK65EcT-+u!D*f`i2W8o?YMpc%%O+f!%NZ}N)MU7K*sOi5?c8AuX*RC@&2D52 z&y?8KEAsJo-D+H+3W>@&wsey|^hoPPXIsOCoBQ@JBym#!&#EQuS^1XO(7PcMW1Coq zeVSL`xe2PiouXVe3#FGFeAM0Gaprh`<7IP;t0~CLsn%0zex4g|#-3at?Q!fY4er^0 zsJ_WX-t_WRzxPOc=ABvnhj+G}H#@XNtlxV<-{q}OnRB$6wZrj9NCUqrsI9;y+LTz3 zp^=ul2H#O!mtdAD`Ps01{WE#vhE_$u^QhFw5{+P#LaKV&ZE|||As}qk z#IW410skVeOy6kIPdMhKCS&>2R(b2{`rB(C$@Ee6h6i>d;`+`Q<4%0g1x|_e(WZQy z&i%6dr_PS=1{K#Py?xM^?~{6?*~519uH!WWTeF&+zl1;JY^9xFN}z(Rywk)esr^al5mQSLe3eZtYx z1>x~E-B!Je)+=8xQu&#t+&7vm_w)YqlQEU7gwoIIk~TsJAhcGA6;PV=liJ#|`@uei*{Q>G0^!rB%6C;H7&L&7WH PV8f|*S(hUM5SscAHaToK literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/index.html b/images/mood/moonsis/stars/index.html new file mode 100644 index 0000000..940b23b --- /dev/null +++ b/images/mood/moonsis/stars/index.html @@ -0,0 +1,45 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+green/
+purple/
+red/
+yellow/
+ +
diff --git a/images/mood/moonsis/stars/purple/achy_sp.gif b/images/mood/moonsis/stars/purple/achy_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..a6b1f4e92abcf2c399856b778156517d9b96b949 GIT binary patch literal 860 zcmZ?wbhEHb)L_tHxWWJe|NsBL7We&9=aZ8?PxD1K9X|J;!IB|4IayOvQ$j-Gz<~n~ zTc6xXdVeeD%`)vhS2`cxjQw`G^GOBIn$u_ggAKq(DE{a6a}5c0b_{Se(lcOY1gcg1 zcQB)*q`*pFzr4I$uc#!aI6tjKFF8L~KQS*eH!(dkS)Yr`xhOTUBsE2$JhLQ2!4WF1 z;O^Jh3QM!80#ekBciLU!l0Ppr9zV zxLBbiBePf`7syIXPgTgw1M*W9ic-@vi%U|AfOeFn78Pga=W&(hC1<22XDcZA7nA_` z#R@eDn}N>DP0cG&NGnRrO;zGzQ2fclslmX_pab$eC@dLR|36UbOUay8R|Gs=CrZgLKf0nAM$&;rVm$&p! zXr0qB%_53{anUMI~uNj!B#?Q%fz&yAJnc z*Pof#bh7ZYU#0y{;X@gv_UxHgPh=!7WZ=5j{D8l5&*LlIi=IrjRI_})$1q*1p^c!mH_325`l@vbUHd6gAg_s z&|$d(BZz{K1OW{*Xmwf(D)_L9CF~%r#R^h8R$(X|UJvgN=-1v4F!!Bve&@H`go#3T z`6qiI543<*4uKGf5JreXh-U5tfk*;j0#O8_nKD5ll0=w96p3i2o4|;~2xCNHL^Hz# zg-8lv3Q-iI87zWEB#khQC>qfWG=TsKMxhsqa9cSfL12QQ2!du7!<{4vOcE4H&Kk?DVn4iJHRcl2mAm7Kru)JO&|hT z15MxsL|`*O12%xcG_*qnA z63hd)z#i}e3;@L-5l90Tum+mI3y8pGfCg*;gK21oI(&dbGns*vpb!?ron|70{2_2i z7$SuXAv8z{Vu2jMcyJo51uwx4Ug%>WJ900z_04t4kd zhk1$r!yjjQZDdG{_>;h>5T9+^SFwPC^P;JR5B%ShzQ9&$Fb-NaI_vn-_ zyXCu%l)S)-0JVvtaKmU(g168*QC+}w3H16Pg;?FkcK6GQ-_~tZ^1Lst`rIWWPsqE> zS>4vDHjBWXY1uL9To2={p)LBAVCVk0ZdT6FP!JLFdakN7rKkOEQ95s=?1r`9zJor0 zO4Dk`a=a3;R+ru`$rH?0$e+n0Wu;xc^O@wmY>U(~<;gDxpXnrRGkdj7Bchl?x3``i z*0-l*O+2)|z42*gd7{mma_cHWH0Ufm^m;EM{Ko9aUehW({rU*||t!1-60tjJpuKruFJP|MDofSG?v_yy;23YloV89eQk{Reljn}23Ui@VNl681iA6xZ&( z6Pedj>ftL6b?a2mY>4)jA2_A@=WlWIgR^9rx?j6x_R#f+Rd19%N}g|U`)=c2xwSr3 z7bc%jE*kZ^xQaHtQ=7@?mWCnz(`d8I?6A8HZSRk{O8Vm-1=RJmcLY7R46KmlX>{xC z<0eDZOYWi7I|T_@mrU5wC7JZFvi^(6UPzM?kw(NA^b8$+^Zd_5)|xqgML2g#xFzGl`pO~es*g7f(ewFVo7(Q4to zYRuV&?eeZkT4EW%bvGC2c4%T%$CJB9sXH<9mg zv-W5m9!Sdlmb+Ob)3CaSLu%feJ4T-v&x=(k*N09PNA=5oja^#IcT@;NJP!mW@eCFA z9~y&`6*V>foXS!wp^H4#Zu91g94}Yf$cvp*8dYLXlbuJU&V0a9XGr)R51E#v%kosp zlj-wwg$-er<5yob)@rRKAYXZ6h!5^wEQcqDuN E1=A!t@c;k- literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/angry_sp.gif b/images/mood/moonsis/stars/purple/angry_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f93869dfa082d3591f66bc7eb4f9cd018a55e53 GIT binary patch literal 1567 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/awake_sp.gif b/images/mood/moonsis/stars/purple/awake_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..8e1b2b8aa1b5fa9fe12788df44cfb206710f9848 GIT binary patch literal 1212 zcmZ?wbhEHb)L_tHI3mmd0+tLC5)zu4n#sw@*#cXuIo2-K+_{~xTAFroOL+s`#5*x50_)kx2PnGvW%@h1zXBZDx5 z4oEl184Rr79;o!CWX{W2wJs-{$>71c{6uaeUuM>(JC?EC&%F(}92a(V7^rbsJmq?j zt){STNr=c|G2w(`N*AXd%DMI-G`IOs$sVS~Cl#(AZg{=u?Y)y%8F(7qDl3!tsy*t; zv$On4xhHl;1)B*Zv{X({shs3cU{=~BRN1m*UaeE%bi+w&I|I`)7%bLp*)XLbbkd%Q zE2DjU+Y%V|u`=&8_Bj%Jl$$RyS~xDOynIhrT4-VoYsb73x2~EorkmZr=(V(T{$-}; zlhfY3jd@>lQfG_96oYRYUl~qgnc}u#!NFz@VXc@G8x}gtvM70}94J_Hw1ZPWD`bV> zK(Ix93BN?f_Z!+^(gX~#<+iKa_} z4viT`64zGvZg*`sIN?Z>e3)4|;{^H9vB`V#?nt|c_F9qYZE7sn}J&zNt2bH^3k z6`|`Hm_B~a<6$p5z3hds%lhL76#9!^XbT8T;}gx@fy)d7?$z@W3{Fe7KXFn)$%wT9pVd$IfR5+!y-)~8ET1NkdS!<)?I5uwBye>3lVT&1a)SP&p`lK}n zt#`W}?QcDyw>7bfwXeDIK-ytYy4ZAHXMx{R1}3xSHZO+K+(6~0mmdT_%R6ZB<=rbo v@88k?{xdLh$#{Sh2)9tgi3tY|wh4#}^>_p-y0&xvZ3Tw`>uAbAPZ`z#qm1Ko literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/blank_sp.gif b/images/mood/moonsis/stars/purple/blank_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..09173af4d4a080622464a7d71ec025687ceb4b9e GIT binary patch literal 1489 zcmc&z{V&~D7(X{`v7qzPqHYtB-f&$d9u z#)a?A)eOCltZ3N$4^!YF!C#BJ*^N;##1QmHJ)oiWN86^u%S2g;07&Z*#3 zDzwne1m%JXL8ZbH!%R{xsgP7Eq#**VK@+?{1e>u6*Z{*c+EK>?4rfd-CKZKPj63H{ za3&SO;DIt1Ob8|w{h)? zj^JD>Rze{b<1Pf3in9<59w-aRrD8Nm`6F;7j7X6oLPJW31v$WYI1OvzCF}r848so? z0L739(!c_1&;&0K!Dc`M8(^45JL-7AQGSX4!-u!DKNy>8ijGQ(4Gw(6Mgh}}z~vfCBk-F&yg&Q+H+*8SzZGfuk`F2`H0$Cl3rAL$=+YEtWKw-r1( zJH0z3ztB*v$(YuJm?joG^ZcgG!KUG*w#IRnh4F^roQbFHziAF6>7#Z~^TnU=svr6r)Z<L)WL9mxa5zWmJ>--WUKA(Q8r zw*A-NSDYl&@R^6mm#fY6JTa%AQ7aDr{Oy=OE zgGal1JjhC1ftxX^Vj}JFfv<)Q4=$$G-O#irUn{NG)upFj+Vx}jFB7i1LwsbhYQ)z1 zIJUP~r9PgyCoki6(fy?t6EgvGcN`8~tzQqj>DN{GdjIhHhnCF#%AhnyU5z$mp!8YQ zRQ!8wqm9jhZyi_H7Ejm3&XhmcsM?lyrZw%O%CEoh$TCNm6FiRv{jvU&{ke$VaF-6X z{)Y<CISp9Saa)xxR4LHsjb)h?fc fvpG?RHEqp1Yy#JE%E^9h?kN{T$+A(UB9Z?BBD#P@ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/bored_sp.gif b/images/mood/moonsis/stars/purple/bored_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4af0f52710931e84f37288d325d6a30fa991add GIT binary patch literal 1516 zcmc&z{ZG|Z7(WQ)4a5nG@+Ryi7m1f99L5b~OkPEW8zAyBY6Zc8?2029fzAc;6691s zB+eiLQ$d&@ zTo56MRIsQdOcE}MkVGoblmH2%=tU8?wZkaolnP3vvKV*9C}&hKDit0mGfp|Df>Wu` zLN^nX3n~Pa3QG(#Nx7s#QmK%J2(SiC@B$HR#wuU~4AW>w9S=C1F~OKr6k;*%oHN0h zR0M+u%3LrZm{jzG7P`4)LNck?0k>ce{D1*a42jSL5nv6P-~}Ss3}|2j4AW>w9S=By zbE#Mfg;!!+7a#{-U3GJ};+h{d=|B|_wnz>zQ_MTQ6sDIpf*0OR2_tc91b11vENKVSe9 zLn2563#>sCyg&q-0S#<`VH)kI;{iwcCH@Z|YH6v9NH`c45*y+B$}UqAP*6WNdoc*# zUTbvL{w75A4>3_WMfEh_C{bU|1mXQxP?bzQKWoR8cy~Xg(Y=w{7Upv`6lzVku z>UfDumTA;$Xe}r(7UzChU!fFrn2L;f84n^I(y2(^W{gO z`lGX#8@uYJyFM+f9IDP6UV2lTQkH(b{K(@Bea=Wtp4YZsab`5s`qt%opRB7@Ef4QD z6fDhXJ#@RxEWD2`rWacE_0{+O9v2%|`Q%E9&q7kB!}^^Yy;8d;I!j{s%}+kgTJ8ul zUEfq|x9T`=lbiUSxh8RSe7MrczVsY0?9qFyJF(Od_hZApJpaw5E(OaCi_Ydnm5!PR z11|oagC>qe&YH5x*Zd>gjip->qpED}SbbWlL;j_-z0T#&)D4hqB}=Jr>YaqUv%yA*zv@# zy{>+y$1C7kuEm9{r0WwOebuj8Ss3e#`XPAxUr((%K1(_oIF@ha_|~oIr!^06KmIi( z*7|4W#_SAJRg=Tl`Yqqjh%F9p8T!+9!rMK4Y*&1fin6<(=Y+AKlfE5E`uxoDb~@9h z8!pJaui2W^rRxgToOz?^#1{uzb>3%3?|*;f!J?)(#&ly!;=STWX+E|eJYShN)=htt zx?w0-JwUb{NcL7O2W|iMPQ*%0QKxP8T(QdS(%h*H{`cle98=WB(nP-~W0{Rdg|XZ+ Nr(RteVs1uu{|jSngKq!; literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/cold_sp.gif b/images/mood/moonsis/stars/purple/cold_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8955844eec3d6b6e8575f46a3b19ad719c5f4b5 GIT binary patch literal 1663 zcmc&zYfzL`7(S#hyCRORgp%OM{idjU6eJXt9cY(WTyWi3By&k84Wdqz5bEfdIVCV?M?)uZnUGPzG|LIiOIFkA;rrc>{&jxr&N=VAfR4P1BW}I?P1*cM> zg>EJ&7gPu;6_yxgl5$Cfq*5Ub5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD8ypiIcI`1 zsR#xSl(}F+FsbMVEp&6qgk(~&18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY z=Tfl}3b7b>A-GhWg<$YNSx7DwqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR z1~jk%hH12;jt3m6WCkmt5Q}k_N`%NCfg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`I zhD4AC7FdHOc!3Bu0~*)>!!+7a#{-V?OZ*=`{G@wIf_bTKu_-|tIct;)DEPe?t#-xt z^btBEe-onmo4BZa^sUoKzN*bTv%A%{IDeG?IMe;s?1b%_fV30ck8Fw6zB*0E(b-$O z?Uu2@zx3F0%d10Nn#{!xopI0f6 zol8ya^*d!~uH*iDPR@?XuDSVTSikAG)>KJD21>2oL)jez`cH)E*D0MH$w8T=Z_hp2 zz0Oh-Im3JIsWs00!C<$HCuM#0L1$7A)})7ascheF*gRZ4C9l(O(sPe~|EN6YLft@$ zShVHAq{hZo(XN$$WiLH+Q=f4qbLNSTeQo<6cb3fj{gN~GUWMHB=g_mk!_8HNyHC$n z7pS^6G$!@r1@CuJJ-l1-L1~QrakD&)q#Zz=Kd6@GgyX(>XvwU2GyBa zUsLV;)y1BBS9*DlS0ZyA^RJQJTJ&Ec`$!#Ir1!QBUaW9N7S$X}%YA*TB`dBarv0AX zJ^o`mNd{ZFP}fIg{JX21)BF%a~#Xc(_FP{D~FG~Q9mie?PjGm*w~PI!N0>> z>t{T=pd@j-Y5iyV{B`|JPcGf~G~G~O9(``!#X9ZMj?crp5?k61M1SaeXPMiB*4zvG z!XnmWRyn5_cG=?Ml7%_G<4B8t@Scqcc~=YctIk#!qaJphpX%Pb!&rOZf_jHNsjBBu z;Hcv>vP%ZtGKRap=4Tr+Jom4^Qr$k0&ieS(te<<5_m*jPI?eZbFV;s#XIf9r%L zd_M2Z!nMz;+I0<;mp2#Z3gexwz~PtgCvG$@F6?`&`*!`__cu?l8;cu!^%J5Z=Cl6N zvDYozw$%FE(p2p9nC!6lc-W2Ps~z(u$A=%{emxCa}pMg l>oe_&w>pMulTw}r>^5mv=hT^#Vsh(^uN=F($i;=k{sYn%xU#FhRH= zLJ+B7QAwC2ToNIPRG=vV5=POBB5o6hQOYS5luBhW?u=2+s9;noJWytwa!v)OQlW)z zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}rf-|WI z1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+MEa0KU4 zu@VZg7?j`B72%>dW?wu!hM-O^+$wy^q_Ue%|VR z&|Mdp>*bn0{>(jo|1?`qhXMzuj=1=P7%25ijDJ*q^X96sXZqm6p_C_uIo*qckFBrU_V?+hyxl(FxD9m= zc-Z-2f8vgNKf2`CWtH7bvI?nG&+o}PJW{NRTQyR&gR9ClH!VkxdY#>VWN__CP5!M7 z(+y*5OL=@${a$C!px<|#*jtuVkhkbXU%IBnan^iY{S7zWlk-o9^CL|?$$7Ig8o~~O4qdv5b@V-e3*PD<&XVt;4r z!ZR9&Ywu6`mJRQ+@IEzMG(~rRxY#CleNTz~>XGzP$K_q=1{ZDbaf7YO!G@4`{sr~z Bwfq18 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/content_sp.gif b/images/mood/moonsis/stars/purple/content_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..4cfab097b6496a5b125ade2de61344ec4301d179 GIT binary patch literal 1207 zcmZ?wbhEHbRAJCyI3mmd0+tLC5)zu4n#sw@*#cXuIo2-K+_{~xTAFroOL+s`#5*x50_)kx2PnGvW%@h1zX4TCU) z4oEl184RqS9;o!CWX{W2wJwKikAwDPheYm=cdl_1J+~6&pO_%haPabm85$2JX*l%H zXt*)KbHPfYY288x)Rqv+0MW%ur#$ z77YIo!SH%tK@F3M!uE!R+~4Lt<2bVJxiO0jO=7i=JlRT8Uh|{%BQAWUDNSa zY*K{5K7(0&+^XG^tu%R;d$-)bP-v-_{&Z53X>wC4AGcMkF8*}HB#DMtOZIcZXs`6*AyrgwIpoVSEq>Gu61#FC2R=f8-&{z_^YUlfpnLO-; zCzQU|JUJ_1pd!fI#QJCLD#1R*sqF&FUUP0VH5~00S4_Iov616=zpQQ37LScfPEJw; zCJroV;{zg4XqGk-8)EDFDko;}FeKI{&hX3CGwaUi^XZ*w3``n*8x{f+#>Nec0-QtU z&M9kQWnQf9T_3+{f@5@{Pfc&ri8aA-6=oX`914taH3KJ$8(wj4JA@gS?mq;kjLk|f zu3WHwxhPlv>w9p@_|L!$PaA5A2R0}&HuEVP$!Kg;I@l#Fs>aC(3ItZP3^JNBtO2GT B$`t?r literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/dancing_sp.gif b/images/mood/moonsis/stars/purple/dancing_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a71986742813cd105e737fb3dec5de20d460a9d GIT binary patch literal 2061 zcmc&zZBSEZ7JefJ;VPP7f(RBNB!Li%l2=l#x=YLk2#Xp}Qa+keLcAhU(U1{g>na$a z!k~mtFS-g85tgtvD2`U!L7G&8*BL<2R<>Je{RmpePCFIb&UkycKljJ}-SnPf1;a4ir@>nA63hd)z#i}e3;@L-5l90Tum+mI3y8pEfCg*;gKj8?JY2wG*qwoupb!Q_ z%&;qj{lmgx!?04=AuJ8H1Z#mkfbrloSPNc)9l#Qr!4EJ16oW({4OqY$XaX-F0+Rt6 zumKFZp&asX0f&8w|A(J2X5m)Nj_qodPNRrkN?RD{?U@S$Es6ayQ7>^|JI(C`hUN&Uv-3zR`}ICJ)M-Cp+2jhw}~5S2~}6e zXGeKS4&EX^{bBB2jnDX&yn=g+pIK{bV$4qqy7&uTSJAs?`}4jO ze^&Kp&xZ4py#x4K`<;?aDJ_k+%*Dw+-jCG}huy4J%`P91F=SgsGwl^##yXDV`X z2QyZNNPLv?eU2gGVqaV`DfQOb_Wm`-Y23S@(JV+jlwuXzB>t93ou47MLZ-LJ-6YZqutbMORw!&@gLt4k%`pAd`LkPRET-&TqSTf% zPVtk7gv}u(o~FjkrxD6Em5D9&$%;~)Z(@Icxv(hY5qWNRSCDD2y;tvaZM{%RoEIJ# z`?{iOb>HB_4&PXhP33Tu5C1d1UNb{nd^OwP-~>6xOh!Y>41pJW1Ot8nf?!+upl8*x zwtms`OA{ioR4otfSac-ew}b-wgZ_Eh=-Gqcc}G4B5b)Ty$Ne8~FX+GC9^W_fJ0n-5 z)Q+}YwV6(IN~V=!bBeEjtIW81iPL)Wr?AU)N<)(Q;?LhDTm24KUUxU1 z?C;#TM9~>I(WuZx8y>8vmLYYm*IO@Ftm8Mx^3qi~7e_383S;<8;`sU>BS+$LB}vAo z{!@1@AO6<==t5kOeth9KCfCTlsK}cx?=M`Y@x7Z1gctI64!5*VLl;5USUivS{Jqeq z-W1p% zBv^DV)a;}Fyf3~kH6vw5>Ia31kG%zU=dzXhCw|K2tn`XXzH-5$U*1sK^SlYUeR`s$ zIOI0=1HOEUxT8<-fvFH zRo(o^#A=thOeA+l?Rl=cmwscE_~^*}N5sqLQF{&@lnUdnypUSYp5}7rqYZxmp`2Tx literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/dirty_sp.gif b/images/mood/moonsis/stars/purple/dirty_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..4dfec36488b950d87e6405e17a92b3cf028be247 GIT binary patch literal 1816 zcmc&zX;YI|6ux0maH(u@6i`{hl2B22fvOb+F$swVK{ipbB!yd+)S?v^tV&a)&^nPkOE zr6=-4f1>HbAcPSj2vLMs?#?g>Gl(#VGKl5M3`Q6uf)T}t<+>SyFhPVMN)XEpGZbNp z2t|}4mcwFLgjqybL|Mdg&Oa!fpCsh9L|?8HVK+!yRLWV1{Cb<#<3D6NV6m z5{BhyK{uuhp$w%A%dv!E%rb;!D9f-MX%GRdfhO<*BCr`&0XBfaG_*q<9^ep+DaI_P z5EjFo5KIYXIl;gK%7kJ{G0W)(TF^~cOj*owc7R)85BLEFfMSpcnm`1w2AaSNh`?rm z25bO>X=sN!JiwuZu$+~k5EjFoQo?f1f?(hQWy%tkGa6!n9Kd*R8mt8`!8~va>;XT( z08k7Pfiz$NYoH0dfCy{`Xut+An1*(!!vh?a%M7dpg|HazEEgf<4}n9%5GiB`p+QOz z3*-RCgVSIwcnNj@OBe<}zyMGT5`i>e0c)TMynqO7257(rFqnpRsKWys?w9yKd^oeS z!^BaMA;IBdU+?9nJfPtG#>{dxe7`?UXZmk~EZ!lWg=1*5uIspkt!VrA%@x6Fs}|=u zqsyJeNdHs9?#t^`x>KgXqC_{FPN_z3Fgxb{!z{a8_t_<@_n*GsrS(!6TTDK$6rZzb zk%?;h>{g#!h@{ZQE8}JNUE~D^(L`O|++|xM^>k9B$_^X88Gd7H?zeqfU-e0avHN`c zy~V0-T|&I)=H$nfI&Dor>H+_)gO#PNNn?^?94>Z_am#6cnO4ASy;CTc+IV`M{95^< zK(W%tt2}kd%l5X3k^DU(shL9kmuh2I+xXtLFsnzswSwkdC)!PfcKozUXJ+Oq?#d^7 zf*c-)eA4m7E4C+VAn|BW$cW~8m%B{*tY^Kwq%eAK+YO zN&2mRtla$E&6u-er=L-9G<0Y8gAjd@uJp*|63=lT;IO}WKH`nS z$Wus;DvxkA@B{#c9tP`a_7X*`z zZEq$MRDnmPyjKkmIDFIJ9DmFG0NJCiTgxw5IGple(!23l{!-Z-JD=CxSMP3r_lGe` zmSJM;^^yAUfy-+&JJl11>xI=*){##R%}_u8D%P9VYMbz#IN(Xz+6w>sX$Sun7blho z&3oeJE28tZq{}2Ude1~~{@(q8S&D73PjSECj_h^sp%R&mGS>f}60NZOx*>-rxFN_* z%DmpCJo4Db!z$p2@VDUteZ$k7Fx`TYhx>xf*TpYde$(2*$<@47>!3;Zv?&oOKOWuW zo>D!uI5kDP#VO`W=}^4oP+d~qyjKq@j1Fcpp&Dzn#!gw?0R N&ho3uW|*N5{{_$a1{44Q literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/drunk_sp.gif b/images/mood/moonsis/stars/purple/drunk_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..b853944bb2cbabb99b7f8100e107950b3cda57ac GIT binary patch literal 1695 zcmc&z>r>QK7(NEb#lg5$D58LXERdu8bdeDWM6R(r#4a1Dkh`#F2E$b3n%bbi2BUy3 zD0@(9DP2gL5tPVFIx3*T97+ug%d)(qWixm|XPQnAzpwoPoe#Tn&ilU4`&@RDQWBR$ z=|e~enIMx#B7_pc2;qbX`7TL>N`y&-OGLhN+O4khqY9Od2A<8Z^NRM6emFfDJHAqaAfT;4n%#r9xJS#key@ zIio@r3?3*mPC2JS)(=|fW`c4-g=`1hf<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;Bdx-Y$X(8G47l*Av+7f;DIt1Ovpwf7UTfq;WVs;moN`*!5;Vl1E3fZK^jlbiqaEoB=FeLGxI^i9bdzUZ&XV!(ezvd;6!+F`n0|rvB-wZe8kowJ2W86p_iL zD+{8$S`a+B(Ap0&Dx==_IPEg1=rY*Wv;@7p>Z&=Mt6~ARW=nR8 zW6tBR6a!wr_G~^9tkdzKefy$}hRwH?^Lbz4gvVT3^f;rv{KSGOc;Ky62<1#_L9Z?F+r# z%#g&)PljCT*HKT?B4!@QEoyRmO&L16xHfl*vP$J#axiFkr_#YRhZH7w88d!dR(>T( zSF-0|YSxG48F9KQh0T&Pd(l0X`%&$^mi$8l)MC8wUV5yYqr-o5befgii5y>f=C}G% zr+ztc@r~$9bYB&p;o+WRS25%o92piKp!Hsu8&_bq#%-EAP;sfcBF*DlQ(b+k(H3}m zOIAj3TvMn@VOOmq`6}BYJ<-zUeO~oPE#=hvIX{Sp3!s^ZY4gEct3-l-ZJnoN-b><~?869qK2|aEx zG-OXRU#;AI`(l?`k!q`H&RW=zIH&$^#lTQr!6H?)jd^Py?Xqv59zJGKuhAsFUE$&o z8e2=+#tpYtb}kbMncwt!j5vJm{#i_GSxBT~a(DJGowfpv z)&4ElSgyRpb2O&b9gVk)X)lc3!>UU6drkS}4i7F@sFsbi1fEgs9o?$kxWXDS`^4}S zAM@%9-kGI)zHUw)?fA{)vsbV4*RN>n@l=L&-r48lqV_tQ6x31dp>&M3Tuv@5UdTHeaEclT=M58Q1|`}n%CDRHVjS^6&x?aiG4 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/emberassed_sp.gif b/images/mood/moonsis/stars/purple/emberassed_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..da333df59e59bdc43d545e38e53c1dd4e920d755 GIT binary patch literal 2367 zcmeHH=~Giz6u+@R0hO{Z;;3MX1W}L|4H%>ZSt1Aq2+HDyz%5z?suZoIQz~m&C9D^8 z8Zp6OsbeTo24w~@AmXzFxHO7`WgAh^v5Ff^`+9i(0rgAUFTEd6vNVjZcI~zrf8aCSe9@ZGZbMcnxPn$G>8D!KofWY5tt0402{#IHnc+>4qy?C zX^a_GAq<8+A($qZVFd#ZC=(jfG-g=+KnuDFgJ}jctR3JM*aLom0iYNpf+i3Ftbr!* z0wOROpaC1e;5M{F9S&g8gfOg?pb!Sbo~8-IItzk<2b5`sFs#uK3*-RCgVSIwcnRi# zTVN0P0S16#kO-s!3s?h9-~~irGC%`1fWd8OhdLaB)cVb8D;LjDjqBn**4 zh7cO01hGI4U_3Yt)`FK{2e5?8;0G80ia{cf1}tC=G=Ucofyn?3*Z>B%p&jaQ0E_)4 z{s$j+%={2PY4}Ew#LsQD>jxa5VE0zXz!Scm=jhBm6Qutq;^;3HpOat8(l>M3-h1w( zD9Kpuar{mHLI=T0ZkQrJ*p#1`%(dxnQ`@auzqFFbe47jXOH&J4J$w0cA>AJO?2vKC{=WO?&*YvqY%b7br1E?>moeaYL~6tn9Hi3>5fH7af@pPcH} zS#mPIvpQ$dvxl$R2TxnYhFOTTi+>Au$lzIY`q^-F%f3ynP)dDWLKBB_tg&h&cX9gU zNZzvCwlWKDRbqFZLxb2p@#Tez~oTI&6NzF*EWULJT{tgiPvs&(6Qq1U+1RvWZuM6La{CY4EHg_d(7?RRLFv{B-=vgB;<5u>z6L^7u*!dj zV1Ku1kbkLvaLg;&dd@t7=C)5@#hrBi9h>XEfrV!6wtD%igv}EpVKu%{qqX)Ef=K@t zobDF4G+xT^A@2Q|1HxO44R7SPb^4w@D8HB0PIR6xT=OdJhoI@GwMvdkrhQ$_9jmOc z5*KqauXAK=BinZ9F3B$D5yf=RH`Z(ND-WB;hIa+*^{5;$#80H5;f5#0Hwv6vCr1kn zqU^?ssAln4F<+KFR^suf_f(Nv4L^fH0=x5`$ zlJw0r`u$ch$SmEv<5KUP@jAzhkQPTyL8SV|swwBjpFC8ZrjZJ*$@7bm!0u(jK!!n1w^_uZ*n{3UBPV;APf~2pGLg|t_Wf*k-PBNjZ_%{e zw&)M5fuI#L4WsX(aP4s%E8-`|cNe=y+r^c54!_w`>fNQUC|#>(@h%VDzxzx2|7rXy HPeb?@{;32` literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/envious_sp.gif b/images/mood/moonsis/stars/purple/envious_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..466a484f3037414e7b9c08170243d92d4231fc63 GIT binary patch literal 2387 zcmeHHSx{3~7(N*wW21Bc4U1F}2uQ*vxd=o9NJxNKkdTG4RYA-(T9md5V%u>nN{q5d zB0+BvhbTe9Vu@n4IL>GdRNz*ER*Kcy4k%EoGsWW8#oM3TnZDMSPG5Q+k~!!9&-Z^z zPLicbF@l016oj6k*@Yp5BSauXB1F-93`01E2n>-JqUbV)BOFHrjz}C)bT>vIoInJD zNCHvxWsF2Pi3k#rB%)|6j6yht2nvxDqG)Ig0TNt=UMRwDcHtOCU>J#E6g?RBIF1oG zM&cMn^MEo=U<84Y1V+)cpc^MKg2YG?qiB|J8K*FU!bl3EXwo18SOZPq1w>#ni~?)` zgWJ#!bvS@U;5don6s-^j!=4~;lE5iiFz|pfLEFRNlN3(Tc7R)85BLEF zfMSpcnm`1w2AaSNh`?lk25bO>+t3bmIDkbG1Vvj33SltpNs^#wXF)LVfHFxD6m2xb z0y%*3;51kZUV?ex7T5!RfB~QwBm!x`0@gqicmWZZ4A6iLU~n7Sp$-SIC^|E+5){H< z*i&?bkUsKnDf$4D5&r<=d1@kw*d z-PvRw+%p;{!pw4mcSAHoOnPl=$xtU2i@MJ%%zW7z^{H-8G?rB4o|dqO#qv(KtTnpM zl_ty6Y7EV7Htm92s8xFL&bF0J$48*_$e$;7%*dMx%InH^HP)2w8$EVeE)fW) z&GR;YqMJKQ^vwreQl}|M<@q?K_>p@;)*i20S*MpYK zg0a2XWZLTJ;O@YgviTi-)?%Y;!*BSMB0B#|?Uu^AEbHe>Zq|3abCyfW(k9DSbNPO6 zDQc~6UzsR{R0OIuGdhcs>&fhLohu1BaX{WQrD@Ss*DO|Pg+mt~ddU{YavWDG8H2Sv zxq0GcfK!Um+3u0s{@`L;9amPXV)z|f+SxnOp1-mi;xZ`nxx5b*2o zyh!!Ht?iw~TBdtlgVYo|()dTlIZ@Gi?jgBmxkdKPI_`^e_5705$NG<)MgsO{v+5UI z+Pg_$9A@E?Q?D7@&&oE99SAmD9jgp6IF46E45XYm5R|jP<<$cCm!8Fd z>VE1;o9Mb;dFTYk!t;L|X|6wVyDLP{^B$|D)6$b}bPb*u@v|TH_~mqO%kjE4`RF{) z+FKrqo9%IF#&Sj>yGo>;cUh)(NaD&2Q+3Y=UAzNhD_EiO#-5U&gxmSd-lt2e{B9TI zd>Xc0EAtF(UbOy;F?or` zq*2GN{H!A}x*G})!H8Q_fZaDUFHBXIk+dqITa=>avWMRcU$OM>XVE%dBiy>7_u#4= iQ(>+6Wm%yXk8vo+cSotT}n(xj4 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/exhausted_sp.gif b/images/mood/moonsis/stars/purple/exhausted_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..b1a4aaaf9a1ba161ed3825239db175af2760152f GIT binary patch literal 1577 zcmc&z>r>QK7(N1S2$8S|Nz064LI^E`dsMvOjw}~JSTc7tg$B8KA_E&mG0S2Q1)?MZ zc7_9Liz0Fn1!qaiB83$lILrWwm&!D)8MLe!#}-lR^zi!w`r7%hJLkOb`@GL(cV$A{ z;w2fuB$$ko$wLWYgm6LxAyT>tCPN|?&DvNPvjB-W=qf+64GUJqUDmax2 zEp#(Mxu8N&sj$Q_laxy;B$WzjhyZKQ1TPT5W~>4>z%Y$=)bW7B854|2MIjdB&N&mD zNkuStpv(mmf=NX`XrY@+CM1)J9dHZwzz-Mz#gGV15CPVp30@$A&430rz%Y$=)bW5L zIG2i*P>9923&Ex0EChoG%0hCf7>!tv1B{2$uohmzJh%mW;0FwVVn_sOV1YGgf)|Kj zGoXPDFifKzbv)omB{NtFg;1+4lo{0!&-O=JHQgd@B;=w zF(iUCu)rEL!3#vN8PLE67^cyVIv#M8U*iAp5g^@@W6h@MsMWE$uyE%opb#+OGA$C{ zuTIjL{F@Nhf5;S9|M(8;`C?b^kT)-NG(_ckb}l*ac*r9tB6RMW#xkRNLC%)BenV$E z0~RfvW#LsZry6@IW*NOwcUg}P6kpdH=+QM*n)-+-F~Tpu>Ge&~?;31pOh>zVFm{YM+F*0hvu{kSN|p)!qH*DwDgP*wX% z^SNWiZliwV3+HbvoWEt!z0PLyq5ZU9@0YK&A8WWdbmQB~U|X;CJ*SERbysqWKG5PZ zm~wigCQ@szu;1@9KD-~+Yw*~$Zmhg=+tknx-yhzdnEU6=?7FrE=Psz%`M3;!;Arq2 zPJFJv>Gq!I7meL6_KXYudGCxZ*%$WBObN&+@lSi4UOL<0dbrd_<>RUNJoP_)j`!5` zmQME|m5aR&#}=t{PV0+|cVj_A6T%g$sF%J7F8c>oR@#Org5kt*23pF;`R-+xgXSP-SXPZtsy7B zwEM303vRcT^OQC<8K}>@wQ4j`49<=4Kd<}ioz~;2?e@mHwO7Z3($Bl*ZC)<6o&2G{ zzuYUd!26*oqV&bz4t`^)efvaJq{i-0**4_npFXt5Bb8peI4dt%*R^x%MpNLbr<)%v z)MjMbB3}OD>_pJTuM7S*B<_Ag{kk2`x@MP#B$Zt*oTHkZk=~YZ#Az$(yQDU0qmJFJh;)qI{VZfdz%P~2 bPSeQe@#-5{RY@UVWmg+sx|g+rkY)b@l~|sY literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/festive_sp.gif b/images/mood/moonsis/stars/purple/festive_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..906617f7db733de9b6b0f0b0833e69b1a3893734 GIT binary patch literal 1639 zcmZ?wbhEHb)L_tHxXJ(m|Ns9#u&`8C92Qx}a3as??%gf94ib`^d^V3T7lJj%*6Z0~26Vo%3^|`p5i&7Iy zQd1PlGfOfQ9HHV0?w)Q6VG4$NMn+sol?p+b=@}&oCHV?Isc9t&!9Y{W6N^$6JoA$E zxVS>{6^cs>3W`#Tixo;TGK&>*fvm*zRE5kuAU{>1C^bE^xFod*Xh&IUQE_H|9#?5z zaz<)$wt|v>K?#swtWbln8R)#+)Vvafw4%h^R3$D3#h)yk8VnK)I-oED#T5hFe}|p| z4;`ug6HAIt=2*?Yu%g6kZB(bgiR9lW;`%3Xc6ztfbWZX}*!wK&Z2H5L5G~1DjCnH5 z0yBLSnaZ;xV+$GT8yeYETH-<(CU$fwHY&<92@CZHO;oCzGIi0^`6B8Q18bEO7cO3` zprov#BF+#{yKd5=U5W|{^2$ov{CBK7wrJnJ`G@^h?cO6fiQ(k@tt;p6W@J#5lVZ4a zMd{ky8;X;pWfUfzdUWPVoy^CRA75U57d%<*>DWxE6bc1Vgxv|mG%k9>iv7X`O~7)ex}*7 zJyRy9cq({$EqN>HwPnS{#a>z(vAd>dTwd;T-eIm(s8;AwkF_j7*ANIaF~te(Ul>cH z423*XPPN9&oYYWZ(_6LQ>!i!Zj1Kum%_vR>0|}jxXh4Y3gT~yNZRGi<6UMQF!TUmNnaVu4QGNIW24} z3;Wz7YnhMl+cI~JlM~fh_zY5SZTldk zp7&8Nr{wqsPVJ8GBAqQa3j3_`*u>ZRcydwi{%g;;AcWCC4{k62|;$qPz zrP!=1>X(<>&o@(@rNKckxJJ|1AW36$SHcq5+@9H6SeU^HY!eIn%2mvVcW<0IXB*3w z!^|@`99wpZ;ndbkN7nCIa(vF2+1Jk(FXcJ&m?M#`3Qz?9n2i5-AYz;1HOfv4CZjx7XJy7vP zfvW4@=qaC++}uhMcFp$OyzK03i(*h3dp=#5%b_{!hUONHfH`iHpZQc>NnfPEU=08Y C|D}2W literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/full_sp.gif b/images/mood/moonsis/stars/purple/full_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..5220d1f18e8ef6e843688f18033c5e1a151a7644 GIT binary patch literal 1739 zcmc&zYfzL`7(N6Di#VZjNevYQPyRHgzE1i}O&3WQ7Dlo5du#)!xWmxifG z1d%Y2h$7(<7Ue|XgmEHr!X;=*fP_)>qKMnr5h!Jpij;C`G46sunLtH>a)}4Z0;7yk zkx?$uLbo7NCQ?zPTw;k~fm6n*$SIddLj+iZCU}7eHe(gA0fuR`qmBn0CJ3S+a7iH+ z4>-~<@qhU6FW4cl{_jU($N7F z{9ZZ9*5NyRjLz8Kgt-1q99-W_XtiEH=sGzx>+9CW8)Y7|5|1aeos#eG&4}^aKcP=v zGKKC7H5*f8M`yU?987E0hHU9HW$!runzqx+mdMh^z5g_2L8`Uni}EhdVC|Wr&^}pn zK*KU?dRCT0rz!QM;w{~%)6X@@6}>;1MxWHI%~W?>z9S>v(`<`Z#jaUXVBhjEl~o%m z%e#&QsJp8&T5|74v?Z~J@4EeFZd`w1d0T$vo*lE>zNwftXZVWg*EHJ+_Rd$~%JXrb zZCmQnU*19=SJuWRN9opOS0`zPa;{|9hx7Ehy?)Ul&q>fH))9Mnc5!d6-rPyCa->cVj$^{1N$3^8WXVPrRM=akzK3r!TFm!Bg zj}IGuUY(l%?0S!zp|YTNySPjfBOBQtUAJ1Li?Rgm?4CPw#khb&*3}2{U)(OeVOTgl zF0lVe=G%ey24sayUndL7RoX4713h!Il(m1k{7~lc=b(>oqLbGQUuBHn?PJxZ!s4pH z?umi2v>Y~3;j%PSE%$w9R@H^sG=pr5?QBqd#)TnUz3y7b)B2Du-Ry>)j~)zKW;i>I zW$OGNnfk@*!>k{)mv%ME_j~wBQ5q|Je8!^G{2Qevp(HHH9CgM$FxirKBIfqXb2FpW zR+G8;Y-P|#Rfdt`w4R!NHX9qktXQgcdiOK;@85I48x zbJmy#`#Mb}ISKl_0CvFJGxT9=zERuxWSp9`xZkb1YTWAo_~<;NGNN+r>H1UK4o~gU zr~j@|n!Rj$YZkSy(AT{lZ*qUH`c}7Fjb?PzyYJ%3?5&$-{gT^ytJWoQgY(5Et<13_ zebe}ug6)cOAEo`$)cN7T-|jOnQY5;JTz3pe{L*qNdAND=ABrWH8y&TW41J;)h3xCQW;mHj+@uxkoc+HlXyNbt7?PtLI&$JAL^t`2QB(&?alh_>)M3l VhHFNlp~z-zYS>ya#eFbq7@4X82Vb=a2ocnP z2nWy-qKu*yLPbOvM~8qSR|YBAIN>2$DN7}w!-gr0Fh&F;8Y70yrU=3W5rSxf z7`B+A5vCEL5lth8#iAI58AKRFGl*fKDFjGR3b_!3+w{Q{MJS4A@ z%LBrgP=ru4p%|7HWMi5lG)2=C!?J{8%us}(Xog}~(jWp@15MxsM4&UY0&D<-YDkAT zJis9s(-g&HxSA00z~N4sm#Z!>}_0D?uSNhC9QK5atg9 zhY7<-VTLd?m=cTy<^aZn(_k%l33dQWCC8a*7EIHb{+S?)zmSQAOH@<0jymQMdHM9tc*2hs zB<2r`NqEy-`=1D!c*|7^Cp@^fZwShX}pWt6tOP>;3aN7S22Sfui@`w3er3QD2i3w|W+z0GVzSX4ZJY+N9RWIaJ>kACSSJcYu54-Xl zHKBVt?>>q==&m906Wu@ce8Vp%9qHf_5>32qL>zE+Yk=wXIR~q1V z!q;W~r4F9;T7mtAl;_IpySG%C9}t=4oGa_=lq779|El6wv!mq;`dfI-T+QIAb-^bS z)QTC`PCv-C3Z8rrk+9N7lV`PBKAz{Da@M`TG1FoE;JgB#x)twD{_sw38xK?1IJ@ex zSzTw*^iI30=dJX!4@osW@P4OlqHWW=)UHozBsiutO2tW9Cde7!>Z)e&_75(#HAc(p z%E z^e?bt>h7I;7gIzdUBZ{%I@#`RzYX3h4@kRiQ_gug6fF4iXzZ+w?b#I*SdnAIPJ1}c zbK7#=3vleylH0uwBAK7bvITlnKEB>w{wiIr*BEyU-!Z1I5!W8uDO$d_^~ovyj?vGD zPki#UDDs?8;F7Ex8jWgCy_(|GVd(zFb+ebK&9=IGu|{0yW=QJTH0l>W)fM#Z;>40t z)5mJd%;F#2qD|y_^=g~PyT*2L_!9f=|Jdp5NzI{v{99>-yxikyMLrpYbwzIR4mRw+ Oh*{|WYyI!8b;#e0l*h^d literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/happy_sp.gif b/images/mood/moonsis/stars/purple/happy_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c8936ab27bcc18ec02012c95f5f89d5839190be GIT binary patch literal 2222 zcmeHH=}**G6n(T{P;3QM)Q$ux1G2e5GD{oAY34# z)J!>HoCut7PDBZdiiC+o5D6EFC_z&KB($OyNkrp^Q7TZ%DHWx`h#8{-qnuGu;(;_1 zs31@-P*I|VYR0L+Dd$v_SfZJUR1hf_sVI?#2(SiC@B$G`#wcI|4BaS49v3(QW1KNj zQi#Eb1%YvaiIQOOKw998b0$jqK?~J_$hgQv$qu*$d*BBQfMQ65CWruQ&;&0K!DK)K z8(`>0Ir6x`;esGaRze{LBj#KXC1)WRJdoz1AWBAKE!YE$htseYUcx-M1$*EJ41i)t z1ZiM_HE4nth+s0HfekQpqa1l$;E2-BU?mh{Fk(?!A@+}jW5ZY}c8H~6OIQo`0OR2_ ztc91b11!-DKVSe9Ln2563#>sCyg&q#0S#<`p&RAM;{r!|iT}Zey=V~?qE-b3C_+5u zFMQhs6zqRDo#=;e_i;MoKNDj9CowUfy}YsFr)=}7t{>lMtPIdt>U_#ybiL!`?Iu@N z=S5n3Ca210b+zd1y?pITg_7W=>Z^rzkyf!gDzrDVd;9~bR#_q|^EL_Qvp%o+FexZ4 z@Is49>!FBBI(uOz=?m4^LLZ0J<9c^TigL)9xAK*B z*|+Lib(8ma?54jfxqY^xJ+ckQsNE`d{g}=;$?l{oFs)?->(W zg{5tJ3=429J(PLQvCfz^*=yLCZ5is^n=>sYp*J@=IInlFjqi=#eN%Sz*yjeAnZA+B zZTl=8R+KN-oes(B@kqRM!?H}~UGlD`Kd;NdGdV4=P#)7I_f&P>Z&>frrS(whAJiT1 zu)f!EOdsF*xPC+)q3{lvPPN5DZ3pcNT!VIwIq8aAPtG4(+;RJ6eRM)!P7IG+;q7+8 zY3z%s4eh$LQme98Y*^(Te|>LC{*g7h@8=kfHf(Bk;flzitQ9UE@2^%Z)Wx+8Zfjb% zZjLNGBO<~jnfYDf0_KULOv5`*SRks&;BgP--i14a5< zcGa(0iOkoLUG%mXEy&33G2Jt9V^mUgVBC_Cn&Pb%-Tjiw34zh-CLfuLzn-hx7@jEAfi?u*j=nXTqUn}br|*39zA}q(cS0bXOl`dtiIHF;7YUk z*ub^gjrMm_!W(89S{HmZfmzIy#cEQ6j?UXL>K-qoYD3%Ai=3m2(w?;zMA(c3pYD3_ z()ID3^!AFk656+D4$K=obZ%+YeIMF)>&ljhvfGc;XFTrc`&v9ZPmL2Dx&mKwI-9sig z8~2#nBpWl$o$8FC(VoK<)6M;z6SB>sk}ET9lr8ZJ6O-`=Z1#756aPQpfBJxz`~~rB B!?^$e literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/horny_sp.gif b/images/mood/moonsis/stars/purple/horny_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..905dbaa5a735122cd3a8e3d1c1353d0a0aa89eef GIT binary patch literal 1657 zcmc&z=}**07#M;#A1oH4M;#A1 zf^(@@358gUyAWI|&O$JFpe!VpiqVJ#Ily>04Qt^g%!6C72Y$c+D27Ck1{PR@CU}7e zHUk>i0K+ueQO5(0R5F8=P>992OC>_&kHC>IB1MJ>4JjcOrD$1CFE5tP{5arP4r-?^s3X6v~v9(ms0TYF~e8^VJY-*QZ7@*<8~1y$eP z+vBARjGkj^vCq;cUFkT{QcQL?`G=;@IhoKw;!Nv{=2GpT(@V3!=UAw*-~QdM16zF- z*7vwI=)&4OO?S`5Yg{6%JaF!yndnklO0}WEv$Cum7JK`R;m!3&)i&;3S=8OtS?98B zYVYwq!_B)=8rz%JcIK8iE==`}X)FD4XZ?QtXWao+*NO(__@8=o;c=Gn;Eaprz?#Sd zO$%)14}*>ujcpssIdfJ`svq$>TV7di?S_ZOlJw`NQUK?4(jV&Eo96ii%!@EtSAFIF=Jc`JCcnmp>bO-ea!iGshxfO~s=}PjOEhboEoIqOXKRLf(Ak#kIcdZaX9&=?-f?ps zkI60iKVr(g)N4Jz#e0Rf#pAKnYl14z*xlLdrtuH3nVhS8<9BQ)y?tc} z8DnSaqswQ{C>U*x7azajsjgh-8+asof$eB;b4jt#gy$Cf1P^wGm6W>{_>4U{7~7e4 zJ1bpP+Unwx9aZykXpftI@0CjkH)*u~n|Cr#Z?5*cmRn>`88vrJeUNqLK#I?@l*tFP z+x;pGk@lTB%jx$rb>Y7_E_?2Ht>XLkzQex{of!!1bNSU6b!-UD40(O}h=~ubYmRQatPcI#VX952IC(hVG;wnO7nOaF-LI~+h0)FGrzfuOYUnZV zca)b0Yjf9DR9?Kg!WL3epWJsUB*@?$x%}t+s|}x;J^gNE_!kbHjA)#`-cmnZ|N5Ox z*Gf0J)eqMF(`C6|x3Op6m4Y&Dm$NlRKRSC+#*(o87K35Uh$VStmv%>XdB8|pvdWdb F{Vx~cyiNcB literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/hot_sp.gif b/images/mood/moonsis/stars/purple/hot_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c8e31482698baba99dfcbe0459d7d507463ea02 GIT binary patch literal 1629 zcmc&zYfzL`7(NIX-sK`W;+n7;V1mdI1CbFV(8Vy8TSy?V>H)lzB4TJX-~|wu6%llg zXt4$e<^>p2B1eUU8Sv16mth@8$8@nU4I3Q|o$2)O{qJ|@$L^f-zVGusm)&KWaQ}d` zS;T|9CL@Ou!U*An2tuTCr<5>CI3h2loQ4Y=R|NKm0>Cf6NC#Q z1d$3Bm4r#cB@vQH1)35dVHCY6;x=*^rJPbhsZE17*f3=TvYi6xcd0~({1G@3Mx@9Pp&=#2f*fExoQAdV5_W(khT#VcfMQ4l zX<&ghXo44rU^AeB4KPfj9d$h5D8I!2;lovqTNxG`6B-f~=IiZaZ3POh!!~2o_?|mL zXXI}}?EWEEcGH(PR=4f8bDUubE;9uejaBUTd!b5D(Vk>yg<&6-|&Rc!Nuu&3@q9T1q%I9wK5 zW^YbdN(W-ftBfkcgPNnwC*s#t_s-dnIKM8kWX8oeYrAhdC7&~nin?XCKjfK_Y5jKN zldWe~ESl#P9;@k3?`Yk`9n_Dbo7xR~Z)Q!ol)I^^YlfHmwO3lNn3Ch#PwI{t&-J&N z&!)w=xZGWv^11IbzaL}D@0EOC;J9;l=IhUn^fp#D25}wf&JDYAyYu?_IY2{kk-akwWIRWzIE>FPd+S}d*Szo z`+Yh+9_bg{$ml5bPjp>lSbYC)-GShCyP5-jr>0I;^04*#?>w@mwv?r{7flWv|1>ou zHMDrr>`@P*w5dh=o#(qHnSWL1Pc%pC0tdC0kdo;USyvy2-*A~?_D_0H-&fmlTxF=v zww`dbswyB*?=!e{O_zFplV;8-QQ@*ty-VMF=jE(-OwJk3ezoIo&9YAL@_07wQ0Sh< zFcWtRe-#-$Gbs5)Y`}$$ak}idvoCowONolRUheltXHQ9mTjomN+5JOF%||Njcd8ry zTBBd!sE*HF^*l+}F>TVQg~_8*qNc#Sr`c(TWQzh!ts;wq1}{C&BXOYinrP9drn zRnuM8r?f8lsb;wDbcD`Socyl$AlcHp%w$Xpby>VFzsGQ8nPHqUXY%k ze!ghC?aZ7e-8Z2jx5#GSM6v? zF8n6je0sA}YG*-lZ`QWO=6joFFYLS%7n$Z5oPIy=Ncq0Oo|6t6mi*~%Df`Gd({gZW hqRCRe!mZ14=wpX50~Oi`O>Oyd)-Z6`+t!8z{tHeTzH$Hn literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/hungry_sp.gif b/images/mood/moonsis/stars/purple/hungry_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..29da1c5437bd58ee2b8304f5fae2fcf2dbff73db GIT binary patch literal 1672 zcmc&z=~L537+#g2U=a~P3m$_4a!9MJD3y+Ff`kT8qe2WSj6__uGU=d1M`=e4AV;AG z1n`GPIXqBQqEZ~SY87IOE*2C^I<11O)T4Bq4pK*|ZXbSsK)-fBB(wXz@AE!K60K2( zzmpO`0?2bRbSNQ=5Qz{@h>-7;5=Mzc38zHJWy%O+L}G+9BIIr=5hf8yB3vRu9;Tcy zP9#n^Cql-ef-pfOLAW47hNc8a7)39NxD6dfsYEHKRLF~QXN*dWaz=&B17#*rNupe$ zLZ*do#;L?9=TyinG0X&&1m%JXnKVRzHE4nth+s2T0UKbLMmy?wz>yf^j0ssG7UM2S zj7v<&g24l2i8IcbkoAKWx+TH5U_!P7ZowY-0Rx~I5}^qqz#25c3q-IP(7*;5rqPZ% z9&orM3E4_0#A4hzmxSyr1cL|4Tu4GT8nGY;7!RjmExd$za0~Xp4;TQ&kONCatMfi-A?7l>dppn(lAOrsrjJmAQ`#Q)*LM~q$^6~8=Esf`MKYu1Qipy2bu z!D$}8XAaRB`kRnZugS1clRmIkUCAEh9<=&;+`JU9P<(iwf>QmP+ z^Q8Q?VsFjJcfA@zOMGrrIK-;5|8_hSW1i`AwdgTB9JtPC9K(;EsfychJM ze2Q=89DcUG-K?FwvM;~wNT^n$^q{tZqYFRtzi57Su6&PXZ-}=cc&XX0H@sKxZ>vAP zXK$rZ7oMbFmY8*HvfGxIn&auMSDa7zmF=r&NVaaBe0kTtvEDy5q`JFD*uI`!SLqnO z?R9KlaMLDB!NqH=tE<(Lo@6MEADI?ys7~FI_R`<_Bv)ruUKw4e@4t5Q&wC3_e&N@* zNmmlo?CCtd$x!T4({s~nbFO!={X|yO{hDL9HU(F$Iier;Dy%Q`Qcz~WJ?Hvo?j7nP zQ`f@gsav1>MIVSvQf60pbo`Rnlk>z$JvCuX^^C7_6o&PMzAF@U-OF_P+ub|uyEa$) zcA8j>zfE&mWqzEP;=IPxnBTto_C^2uI(wbgJ$gdfK)iXjDWfC0Kjdga>EgMTRhIbV zmhQ5IF{a+~<+_&MiliM*tUT4xVJJ1lf2201vBp{*X?|n6SBn~9?RHhfw1kh{>m6s* z>E~?7t!*v|a59uSxKw&;9M!5h+fSz|(=t{DQ9sS^s>&H3oz7u}6Mq=7V3?iP{l#Ky zBK*#2&RYVT3+)Fy@5aQvsXG)Gv7^P|jwMtZvCXTjFp$`+#99`hESk7dYv;zc`XYPm zd_TkPfkz2%H(gb`_Mcew>$+RJ^A;(>>vc~P&r}uOami}!T${VywKgOsy}qm2^h%d= z;nt(Xw61CH*~K9PH%2V!2^t6poNep$_~X*Xe_o`tR-Cyz{5#KY8+;F*4@q$Gpz7`yFQ~oMV<=zFxQd^C=a3Jf1d0)qZ^0Fuy%-d-u<0Ynl!YzUWw| zD9(Hu_1pfPgNZ)lGKYKic8BfiJTk>(jI;IV4!@u75_=noml5doGIfJKE z)mx^iJhObWQl{U}=qzZw8f`o^q3c7}lQY^^%rAL%?-OP6gSB6VxfS?oV&^`7P^wi2 b9$MC){xG#nzo4METx;CeYw1upkcfW)_Q%g` literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/hyper_sp.gif b/images/mood/moonsis/stars/purple/hyper_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..5c7f2b40a6a2429206b229dc877f7b80cda27722 GIT binary patch literal 1515 zcmc&z>r>QK7(Prep-=%LhN~j6FkB3E53zEI;eL~ajYYiR1vE}HuFy=0WYi!lf})Tl z;Td$~s@M>@3>aO;CfNw|R6E2L6HN+(u{P2O(Nx%UdiebVee8VLopavzectD?o068i zC88jZ1d>0<(xHSfLO3CU5UJcLC5#eIiJ(L(Wy%O+gfk)-kxDn^gmJ<-5u8Y6mpXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)@Rcr^NjZjuIDL{Pbkk!Fpy2zL<1$Zt zZ&;$U^fw{S{}2b~HL2HHJ~uh92;Mz>t#z>4%`g2zs<|zxa$K|jlVP`JmA2tY<8+PH zFRZ8}zD~WI}U$ZYAwJJ2QCN=S*4R3wl&{!GB!;;__SO%8LG;gG@2u_E)~y) zT$wu=^IP`iFk&;#*4wu3e<|8y;#9rmTc3`2cKR=ug5*-6H4Oy1`M4VeP&@#-_v9&+32NmD{qgPgK?q65)RmC^8 zqaQv#aNax6^80HdWmn=x_p*s&&H-I_D_z6wOD^wtd!=V?QI*MyrA}6^E*;LVR;8C2 IVhM@*7vCm@3;+NC literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/indescribable_sp.gif b/images/mood/moonsis/stars/purple/indescribable_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..785c1d131c345b00b581dc338647ab6c34e3451f GIT binary patch literal 624 zcmZ?wbhEHb)L_tHxWWJe*W$ik>U?st=V`vkro-p{GgvYtCnsxaYD!2*95`^`UdN4x ztxxVGy}y<7W|{V$E1i#T#(ulp`J{qp&FM4$!3N+X6#sMkxrPKgI|jHK=@~FH0@W)1 zWZ~3c;9}4L=>s`~f%WbJrM{HRc^RwL=Jm#GPe7M}jPAkFQC3tiE~ryX70!3(Tb+)>X{4 zZSf6_6`Fa~>2)2A0nJr?6FMBcdgB_V$InboEn!G-o78O_!`iu|vvhK#Phq_o#|mfL z!s(sikzA|#CYEjw3h^srSy#F(Io6$pEyZk4)2z4!44jv{lEW56-6}iM^DtZg=6$E6 z9>aa_-hcS`>GPMb-@gBFV*mYz{o7xL?`OF^CdfH9{@m1p)yFRoK7PHgK<9i(?qmnP zJ30n`J7xKwE)Hlol(^DkqKBI2(vFukY)h3JHb%B;l}6=-3QcUt+&RDSOr6qV-TN*| zWlgIm$_qWqo_(C5La;JUzc#lqw6nR{zCgRE&X2p^uU9y{#=cH~r*m4h(Zpn4zWLK< z8W)N1trcVtzPwT4e*ec=Ol}9p4 z?b$NzFI?P~ypVzOe#_|zLi|!6dthCZ2{{H*Vz}#oyup!}K9h + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
achy_sp.gif
angelic_sp.gif
angry_sp.gif
artistic_sp.gif
awake_sp.gif
blank_sp.gif
bored_sp.gif
cold_sp.gif
confused_sp.gif
content_sp.gif
dancing_sp.gif
dirty_sp.gif
drunk_sp.gif
emberassed_sp.gif
envious_sp.gif
exhausted_sp.gif
festive_sp.gif
full_sp.gif
grumpy_sp.gif
happy_sp.gif
horny_sp.gif
hot_sp.gif
hungry_sp.gif
hyper_sp.gif
indescribable_sp.gif
indifferent_sp.gif
loved_sp.gif
mellow_sp.gif
mischivious_sp.gif
nerdy_sp.gif
pensive_sp.gif
sad_sp.gif
sexy_sp.gif
sick_sp.gif
silly_sp.gif
singing_sp.gif
sleepy_sp.gif
sore_sp.gif
stressed_sp.gif
thirsty_sp.gif
working_sp.gif
diff --git a/images/mood/moonsis/stars/purple/indifferent_sp.gif b/images/mood/moonsis/stars/purple/indifferent_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d116fcf15c92f98d282aecc3b45c6f7a6077460 GIT binary patch literal 672 zcmZ?wbhEHbRAJCyI3mmd0+tLC5)zu4n#sw@*#cXuIo2-K+_{~xTAFroOL+s`#5*x50_)kx2PnGvW%@h1zX5rZ&; z4oEl184RpnAE@-DWX{W2wJwKikAwDPheYm=cdl_1J+~6&pO_%haPabm85$2JX*l%H zXt*)KbHEt-K)k+(mJTqp< zsMsU?=H?Z(uNJxbOpA?@^b#B-JvJ;j*vuiU6?0-kq7ajSvQU7=Mx`UoV#Z2mDlR5Y z5&(w;t2t^&{6mDq>wN_^OePB38y0eZoBNF8$hzmojG~-vjS(`klR25!dopPVc(5s- znsRkb$6K*U5eEAVX7O>Wc2Bm_PquXlG7P@Ch|F#bVoA?&EgbX#4u-`o@KXyDPNl@H}5L_H5?2!+#7ec*TzL~Oq?)r z4r6c}+rg*?&q-{|ol_D6;%B!_HcY6>pS|*u*6n~AwmFk7W=0mUF=koq-uFObN%X3n z?>}bpuos?C`d;(otbl=vAa4`vpS7z5`xK|P3n+WdxzW^cv|C&;=}yN+j^q8ZwoO|+ NHZD0iNfDSntO2wX`C|Y8 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/loved_sp.gif b/images/mood/moonsis/stars/purple/loved_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..b66eb0db237bbc13e67ee3c64fe1f549265dd987 GIT binary patch literal 1703 zcmc&zYfzL`7(Ocsh+rv7u7ZiM2%5J&fhgq6VxS<4++xhjDB_-gA#qg_%|Sve z2em+8lM-}ANttK{1M+e(P%sdLQ4y_ls7Yin>-6x=^uK?dAG>qT`@YZnTy~cS26!)y zb|>y+h>RRc2qT0OA_$Snol?Rm;gkqUq*A7gFh)2df)S~7Q%)EsoD;!`REDV_Ob{-J z5JW0iR1zi$mqbV+6=+I;gi-XOh}+0vlyXW1rBYdpJ7bhHDj1at50n|FoKwN6RA`}_ z3CaZ(f=Y!YhMA;XQX#2SNJ9izgC=-^2sUFCumOf?w4;s(9L|_vOezYo7GEdm}`o4h>jzUUcv>rH0S& zx)gY8YN{&b0M{Pt^g6M{w#Q1JXjWg{5I^X#xg_q1Ub}wJcTXH2Lnx z@3OtsDgRG8x;JjC_KVRSJRZ=bnoMtA%^~Lk(=3}0yIRb%3U^d*?>kxKZEn3^A#%%# zM-8{R#@}{3k+Wo1(aiqmq%Fer%cky0Ka7w1yd~H(ug`KeDfKtRuPK}`?QUgqhR4@) zKI^+0iO~PGJBVRC9!ip^>}R-t8|DQ*i@ZWv18><%>z@zg7Z!8YcIH-^$t7lf8<%w zua)iQW=l;*$k+!Cc~w+OWz<`~-KT-)7C95#tq4_PLI{w`rpYbPTOg0ymRo?;Gz;ka7FpV&CI3h2loQ4Y=R|NKm0>Cf z6NC#Q1d$3Bm4r#cB@vQH1)35dVHCY6;x=;_rJPbhsZE17*f3=TvYi z6xcd0~({1G@3Mx@9Pp&=#2f*fExoQAdV5_W(khT#Vc zfMQ4lX<&ghXo44rU^AeB4KPfj9d$h5D8I!2;Uh}U+nSMWO*fb`5>~E$O$7>3f6bn2 z!1wYQIx~M0;{S@M{1;|kX}MGG9}=J6f2GynP`i`Q{pkyg(J#|k+N(^OMEhP{xbLPr zYHdnn19xt`+Wu{Aq$xP>;}+Nb@}UiB)Mar-H0xCxMfm=U@9j=6PV?Nfx)RJ=cXxZj z$f(hwH5tkS0wUh+*wGL?FKd&TmLotnxMB+%l3ISL$kW-UTB6t^8{y2*4RrMbtyWs&U>;W-g~>- z_I_Y|U99K!;g_`!GV?CoZQL=X>DB6Wzqhe<8U%Xx*?k-oM=E>(U-xLI9vCURf! z*Qa+D&tE(7OS#$@J5mvvYcDY5?z+^vAY|`EL8ba=Y+=QcvV$Wgm1@T6IsfH!?{RhX z=5v|uwv4i&gu+|>>gEW&Gsy9@$`_qzFHWn~*?hW0>%E`4cE$Nz30CiuON|4X;eoT> zo%ddJ{GofttT!y6uKMxbQ;{|C>4zp`+@HsvUpbjH@aTR=Zoz1UO_(<8mw93)4~BI0 zxr-Zun_sdCtA6L*%A)Gi+uS{i2hVhUG?jYd)avy5q|{l%`R2F`$yw32-l}^JYh{F?*YK{F7gQ_1ACCP@~_^zVU&coBJc`9N#_L;<#8>w(oF`=Z`&~erbE-!o;=99jBXmzEa8HPX^q{Io~Im z&vxskUw6lKj-8)Mb;Lh9pgrnW5K^kUklauozqupUrGMo3 VLg(z!s;HBhZIxl$L)C<=`xlm3g@gbA literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/mischivious_sp.gif b/images/mood/moonsis/stars/purple/mischivious_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c7e90a9075bd12e5cb484ce7c379c2a0cb10d87 GIT binary patch literal 1796 zcmc&z>r+!l6yGF(f`9=DRxuPXXy6)!Tp(1?F(?oakb+nqfdayc6)7k_@G%1jmc+*( z4`me{A`n{}EFf5MT8kpo+KWZSidKtC2Nl~6Op#V>-5%~A(68MO$?TqUe&_c{Lc>D* z-%FDtIrhJ)EV9a4m zd4;eT?u1~DV9E;y9#AG6<~U4w{Xh%43B?@6l(z%i0(-y@FaQ*TM9>5xfHlwrUO)sk z12kX*7)(Pu)ZqaRM+oJu1ck5|?i@!b?<@!g9#G~ep}f%$3*-RCgVSIwcnRi#TVN0P z0S16#kO-s!3s?h9-~~irGe842fWb7hLmeLAP(CxT5){H>xKlnt$R7fSgdtMM5JH2L zAQs30j0dN|TJRF=0G2Qeet-d>7$gE|zyj7l6L zi(7tBDVS>$J&}(O=dB4o6=52GQnu@vXV-R{TfY)j8hm+DG|H;*Wz^zDz3 zyT!;K&xU(no)v#RI+tN$TYe0DQ_#9YbZ7oRN`R>n_w{6|3(mcnG^`c~ZB?%VP7KBV zUhO*KP^c)M=+$NpYrR(mw^eN~RyS&sAHKewxO-A+jKh@|T_t`MbtNAbP1-!Zx<0R? z$KH?e8aOWNw`+6IEVf4RQi-!ltdlp6hv<>n)7xmY-9@umkg@Y#h|gs^=b)m_P&dY; zT^|!#uO`tIqfOD0mG@Frcace(@MxP$dvoP6O>w_Fu}HopobgNE#&St+&zudbm_oBb z#MIuesNHk(e&5c(l(G5hy^fv>SDI39H3aRS)D2e)1XEd?|7X_zxu~mTD&i13Cp9CQ zw>+@STddB`@#;uOdq1`ApwrA#2j$`uvaG&`8fCPyzNgCE8(WtgvW>_z$`Z7?S%zN0 z5(9~`u!=?5eh21C3vG-s>FO7&suP=^qR&@!rT1!%Fi7uOE%YswFmj`tyHtK)mTW<6 z-_ONY9giw5G+qn3QJeIE{ZEa?zutDAtx>dmt6ZI9HfN&AQh%Um@+$2 zRbP01FzwZYO*PtQq`+G3TZkO~X)rh#mdZLMP32)?rYPh2V6j5`Vt9oqe_>~_ s(Bw6IQZ&}KA!J?6#%@Ddh3<)=z-=V!bk1_m7ly*9aF4op3o{h(FWk-QaR2}S literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/nerdy_sp.gif b/images/mood/moonsis/stars/purple/nerdy_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..800296836cde0d77cc3b850d3d15e560c06e582a GIT binary patch literal 1527 zcmc&z>r>QK7(PtW;CLBOBxp6FT?iJ!;Ow#@W$favh%6$zFbIZ%a@=VkMj$Om%K!xw zbzCAlfRhmmGJvrKGme^?Tt?uOOW6z|l{dPZQmoDxBaRLYbQ#t3IbFd~(1$_e9yb0RpA$}km# z3Bm;tf=C66O2Q=Jk_btp0!;~!Fp6FjahpAiQckI$R4R*cXN+=21*1~ofimNib1FEM z3N3UqLAjtpP^qxQFq4!^DkPN(X@~%8&;&0K!Dg%iHo!2AcGU5J!xhK@Kn;PQzMw2|K_N!|($J zKrtkOG_b%LG{Fl*uo=+61{kK%jyfK2lwaci@DU>CrJ3!vBxAZcHu~8|yg(sjX3pH_ z@EtWvXZCMGd>#@npQXt?CqJq5S*+c3rRTl=YF~9qbF#a|TrnP7aPEq4lgi*+Sahex zqt-b}Oh+^uJsO>DWU^~pgvS+Y8~EnbJHv~v4<8@cGV)8uZ<^F}gK-IU9s9n&F8HuE zY4>!P`>6Ir^z@41Yoi@m`M0Vz3TuiXvNvq{)v}kqaF^5$@1@fns-E$QipxXx<#7dr zr&BU=oxfTy7#pU{^Y53W^;WHm%iMYR1Ix%8O|0(J*r%G&L$z-PSPk7n?fOEKx=r`d zWO_^H!n(=Q)~ju$hxGb$rF6UDg`-&~A|txZ^_lmddSy>vwE11nrN)V-G5eNFpM{!& zJEKCsUR&Cqb1`Ps*!Emo`GQ3Kyfg84`?i*iJi4!VaLuiI>$IKpNA*nOgR#(I)y%Rg zD{&@%XSZlQeKxZ-!av07pXIo@KQL_D;DM#3+4=f~{z?`t}e)xYcX z_Aqx(RQ%Z;2aBI^pB-P+EW9DJ^?!LQy=lvRjx7V7Pi$Q^HTRF=D-*``ZIgf7 zUDtcca}qQYy=D0qOKxkw+_y?5oBTD)C1D(1)iaHG=K5`MGF-{ctFAD9!9 Xe_&~zBfol?#iylui8j!ekc58$F*b&U literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/pensive_sp.gif b/images/mood/moonsis/stars/purple/pensive_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..176e742feac4d3fda403ae2ce093a964c794a715 GIT binary patch literal 2359 zcmeHH=~Giz6u)sn1hp7Nk%&lG1R_+pD1vB#umlB1*5kW#wmS~VG z(k9A);)1~v_dOz}R|O;rh%(?(#OjQ@wA$Ch`v>ZmPQUbiNantC&hPw|yo82@%=Afg zM$YIX8aNms1|fnFMTq6@7$XKFf)T}t<;s{r41)-RD1%t88xzD3L#otO9HRgK21oIy`_w7=|(o%PEA# za3_SJgkd?szyr#JGL$kbrypoRH(?pdGAw5YxCQorA7B6|28o~vL;!1`3A}&^YzAn+ z1~8b0cBsPxIFt~Uvl0}-Vz^UESk74x3_PGrS;BHgLoAR37!OW^wcsU~2X28q;0G80 zia{cf1}tC=G=Ucofz1F7*Z>C8&<=HY0Egu=11muxEQUMFMF{yr;E*sx3K>FZkP^fK zIe_utG*}B>f*rsThQSXo02G5nAPrc+8fXG9AOf2K8n6KjrlB3`@Bj|?OZ*Q$>{#>p z!O>CTfCa&x?$ZYIfP!8Bkl}vtJ#~Q2z-xj`|3W;|iINlQE89)SxGrrxVW-P$vz{9y zzctdyTO^#{X^P4nRyB1>Jk`w#%R+N)Gw(3nQz?%dW23V2CW@qs>?I=-#)bxf+SmyBqAB(*wLofH=Ba8t3nbIU7pui6y_ z%X0WL7Nl8xiA!8(#T@G1F)_2ZJ8$w1 zXJM$5Y87AZRJB2v=c?;XED#l*PW1mO-!<3rEbQm*muQ8-GApgiFVgEmBwO1l@m0T8 zt5Wa#E=wOgvZK7jk+*K_2G8W+Vz&sFw5Yl&0}(B8#lgStGTSw0wweAO-+Ez%UrNpS zGLLG{1>yiptny%jcG?}28huLRC1uM5+53|W&y5;=`ka_pdTXAysKtGV&$~4Z)jz66 z3qCvbi7zHUZFpIriq~EdzIWBfTCI(%(3~A*@?QBQ&RdotJ-6f5w<$L+25l-mUAihn zs*zuCSH#s_t8eljeRuYTQ!9+RZ@e@7KD}NcHHqy?BG}zIDn8>9O&wj`sj;g4Flxfm zV@ zfuqvO;w!wL*`yHf7^V%=n=~8h3r5)n>YthHF1H+Ox%j+ILC^u+)9M1$SZtA|18qNz(uTdU~lNxka zKd0oX^@R%}Tn4M~%7ur^21#V`!ixs;3L0!9f>VU6_j6XAk$woW}Az>L`F9qzb&%swoU)8 z%7Z7%TS}75rZqQSSM?8a%pWzp=88{MPQ(bWjIPVuL$_GBkC!c1KU5ydI&SkcDoU-W z{_ZxvGIRTkbFSv)o84sI>5X@unXPeKdD$4OyStgG_!t{HbyiNtA7voh5Ed1cC+IWEa1k%6SLh{qfFXBzqs|4jeCA^*}FGV5>n CH22H^ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/sad_sp.gif b/images/mood/moonsis/stars/purple/sad_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..13822f64c28d9fdfaa061ce128603c91dcd69e4a GIT binary patch literal 1571 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 Rx?Na&QSr{LMMnp%`xnE8CwKq= literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/silly_sp.gif b/images/mood/moonsis/stars/purple/silly_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f1b9f54cc0ede341797321178d67eec88b59664 GIT binary patch literal 745 zcmZ?wbhEHb)L_tHxWWJe|NsBL7We&9=aZiw{^W~ndi&_>;dB2PEE)bYFx|IWJ??Ivwsk1v>k4xmYUX zRBGNcn_l*v{#jD^z=I5rBeL};6*j-D`L<}S=G9-TGq<}rNMtWIJM91ICHFtst4_v- zvT=+&xBk2d-7d*dX=%XR(qa&+RbJs@)M~&qfi=mdK!t&&+lqmCHp2v_xf3UamvJ@p zu+L_m-@?np%E~+0qs(9y`;Pg$CT`+OnyTT$u!DV0TgxJzngiKQJNoobEIRFV=zOcq zrHNO9&b4l^VcpGo>daZji!B>C^fx@Z{Os&1<_&xI@ousDtsdqG-6x>xeeXBj=l(nRLlA5sWLZ8gTk2+WllJycY zotF8|Fmb(eXJ+v8b2Dv=+aMtpfGfmuUhgZ=IlqPZPQ|+WTV?+oa7gmdVajMo*l@x} zCe>4QLuSpsMVBDpEv_l!%;?KiGXT(;uQ@stM- zAD)?^bnpKB>!K^ZoE5um7BK(D3J&wHTZ@h;sCM2EX5bBAwP9%%vCViVbm{OB0ZE4F zERQ=ADpo%dm09i3By*!V<)k*RpW>z+ra`GPq1;KQrc?@vH_Wt1|F&V~=JYdC%C(nD LJg+!%FjxZsk}Eg@ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/singing_sp.gif b/images/mood/moonsis/stars/purple/singing_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..687b19064e007fd5999423eb41a7e280aec9307f GIT binary patch literal 1619 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 lc%EsS2+>@8+^qAu?DC3{{^iPu1Ej? literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/sore_sp.gif b/images/mood/moonsis/stars/purple/sore_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2d6782a9304b705a9f74a2aed4cb63dd4918a1a GIT binary patch literal 1664 zcmc&zYfzL`7(T>BKnfE<6h;3Z`SR4B5%prX>zki0BIC>e@0mP3W)jCy+b{`b4{V|UJZ-}iZ+%WkknJ$GKB zC-Ef1WaLmn7$KYxL5NiDloCb>r$kU9l`>_7F~S)Uj7X)Ma>6*_oCr>&GE44KPfj9d$h5aK;29cgkVz94_fHvk_pMAVh7xUJ@5ktKrtjj6GVVDXo44rU^AeB4KPfj9d$h52+pNq zB@|*Y?m}>>I19nxfwGWXDn=s~M;#A1QppTfLLnC8E|mz8KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4Pz;G6 z4J@z*P4EH{Yz8#20fuR`qmBn0<(K$Be7MTd;Xx~+0v1OE&7Pq$H30?JS7ugfd`}yp zGx9efmT!rPrE^Hb;mbQL?Iy)tPVaU0v+X|@8FHuB+Q)Hq;N2^cwug4Pn8aO8tt+Wc z_Kf_EJMKNAE;59Bl;0do3N6$>JF#qDxm#$#szvI)uJT_4=DRo8+sxmiTT<@7t@CDA zTg7a@s)`wUO@H$BgB`80=5=D+tSDpWI`iHNty86KP0Sqs;pZ`$XwzDIqi^Da%43JU z+=@&7=xS{*YAFj0?lh_2X4|}Z?tO3Hl%hM@=B20qdfepFsM+tI^St*=R&nO4gF_z8 zZJS1Y{Kza%KNy|%z(q&mp7JudjcJFePtmYC;OI9DLa>39-%Eru2|ur zsjCPbJ7J6xlzG^H2jv}iBfX~bvoZFun;jdqi+2%KY}(ummuvPeqi$!=4dDk$CRpVj zOic;WEKm(~EZ&@M9_pk2drEgp)Q_6|=J9(s9i=gmRWyHWTEOwCA0Ab0_n!W0oVO@5 ztXfM?WF&?kj~r0xla_KXzcnpOYL8NnsML=3{U7-5o6&q;=hHkeZ>%9EqMiKU{<5v4 z)->Da%#hC8u=Xq)=v=8brr-b0rhE76^$suMqN=^@e4bk9gVGExqjRSX52k7h+!I+* zy=uKSyTAHdr*90pdWS~M7P|@EbJDJrUd-K?;~RMQ>Y&!m!P+lDd+|_k;O`a_XGJt5 z9@(+;mUH8BV(i^A)8fE_ty+tBQWy60%=C=Pdr|6ZR0rBphYn-Twi0sYp*%K!iX literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/stressed_sp.gif b/images/mood/moonsis/stars/purple/stressed_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..7403e00b5e403a0a73042d191ab18a0b0ac19de7 GIT binary patch literal 2739 zcmeHHYgAKL7CsAhqf$RlAnn+1@ojXZ7#=m^nX^bl1V#`TNnjLB3$k$%BS?%SF^Xmh#W;l#6h=}QMUw^*z#3=*FCYS) zp%q{Q7*s<##NhxIf#W2OQ?x>8410pWNdl*6!N3E;1c{R*PSN^-7Gx6?PEt5U+W~HY zJ>Ulz0E$5(XaW(y8fXG9AOf8M8n6Kjsv#ZXZ~%)W2#U566hdRzlO#dW&Vpdz0b!CN zDB5Tk3(NtG2dBYW@Dj`ex4<6o0}KGgAQ4Cd7O)1Izzc{#XMhH50E22shd3O-qUf1{ zm7owB!=9o?2=j-5!-Qd^Fhdv`ObNyUa{%MPX|NW&1UrBw6oVgN04N5DKpL=sHP8fJ zKm(2x^ zy+U?Qep@c+uhuzv^56O9Lc6e#XL#ONF@sd=d-`oV5xM+*V`^^Pp4k3DnIU|8a&BM$GV~y!&^t+3 z=i=gW6=s=-u32WR*LZ0cHwkA$z4xvO)`x{frAyp8G7py= zso!*Dpl@5@_mfda{d{zR8-ftFiTEyU=<~MO@bZSguO1-vX2#>Jh_0B9(chl_v@!B* zK|5#Hsc&yY6mPjLOz}>avu@j&_uU;Gn`aJ;AU@}$eshK?*%TF~3UK82sqO_e$TwVE zXX!uvxjzx+=K6s-VLEC*mHt~=^~0J;xu$1Y_VNbu$#wJ+EqP&Pja&2yK7%jQvTBlxe^Hb!<>rmd1@d^F0U^f>Q9LYSUdHBb zs`kjSGP`)WaYFYxX@ENAP{^~qyVIpz8K!`@vO{wd3r06rSz{s?bK{(@P+LE*CNx+q zua5fc<;1`|Yx_vyqZ<2Wg>jp<^^42CPN8poQM2&lCvJ(y(p0CyKWq22Dn*yetOze~ z8R2}Z@0rxyvMgcuwnoR5Hri~h(mKZUft$}B7i=#7x$n5nd1B{y*_~M7fys+M-1FPo zTe7+`-ubNFs+fwq{-QO;sC(jQc_8`uP44i@-L+bWmk*C6svY@^^nxdZk1Twr^GDY z``+vnZq2Y#>R)j`-MH?#F7?x&l=03I=Hie4)Z!cTPm=UdzNMs#sIsv-rgXQke^^tJM|d{gbA?<&=XB}%8Rjx!?-R{g&( z!P5V9368G{k$vO>pIgcO2>F_od5y(~eV@mB{IojFHX;2UI-dP_Tp zPjc4x33BHeIVZzd*$=r-RwNQe9lPH-e(7)vDj%?1>sF5+_ES4D7EDXnT=5@cbxtRK zl*xJ$36HHk{4;OL-z(NsFlQ8>3bxj0&(F(@=d0E<>4L`6rW%a)4eX6RUR;&_QLH5E zX?t4Jp6LA^FHHE&6#d%Wm(=e~?=-hL>~|4V{*5!-oZ@TD-|+BjqhUrXFS_)rdZIed z`)E=4g_&D}w#k3QT@24L1u3WHp+9t&jO*1F9Z_1Ozg<1YJeMg>85@^gedRK%@Hq9) z`Nln}zWfDzl`W}KwQt#n^EbCuTb-g?On=>L4i^e;#D6dP%ec_fmU=x$UbMSu3rZ-v zxzEq=i+okp=-8cF!fP>GQKg(nJ-DkOeS{;=o1EgXtDGKWCtqcqR#aDr#q8z_d6QW? zBg&bIx+}RItnJo}>$S~avs4K^Jsv&>>)12z{<%>SoG!~WKh0K@tglyoEO%T`HGOn> zwsRYwp{lQXEYYONvTC1CXfm^Xf<#;FMkf^E@d8)DBDIZ`Q5ihzmBrwfaRrOK`Am^z z9pBceljo1dSwxK{gDZQ^rfG4Uv$eOcm@zbUHg%sn$1<$o?{__SX$Aj$TX&*5hJK70 QzxNpb|B3h?cp^6b3saba?EnA( literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/purple/thirsty_sp.gif b/images/mood/moonsis/stars/purple/thirsty_sp.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f0c996fb37e2de32c008e8b4b0dda7f3a0850f6 GIT binary patch literal 1601 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 OwjGqK#ior2ZT}A)G~x6B literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/achy_sr.gif b/images/mood/moonsis/stars/red/achy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..193f4c7d3df356e86768ee9165793c7efdc774c6 GIT binary patch literal 854 zcmZ?wbhEHb)L_tHxWWJe|NsBLVd!?l$m_Fj#mB(V9f z86_nJR{Hwo<>h)sB{{|UX(f8e`MLUud6~J1>6yv;TwKmYsfi`2DGKG8B^e5iP;mu! zPd9}y1w%a}Bd(-Mg`mvzj1q;Cdv=W72pef~vMX3s&dC7WQTp{@i#ia!WMXANb z3MCnt#R|DVR$_XpLS`P2pQ=!lnx0u)l3E0`qb#+kI5R(wt28e;BQ-f&LCL?M1jsK| zs6p5abY5<1UWr0lQDSbY5*LHwPZmxM20jKIkmo^R$-w%5fpT9;=Ddtm>vFQ03?6Ly z#3@q|eEwUKJezagacRby{R)i*3RV-=D!*D5BUhsO(rb4CQ&XGj=ATV@6F26E>L@Jf z4V34R5EDO=bVoF7k1R)NUPTiNQ&qK%c{4*xQ%@^XTZ(a4^R%3all-EqDh%fJ%yh1` zNMc~@&s(vm!QlNfGOm>ev{pm?s+WZk=75F!Sg{i$k3yjTOh)c~0tOHD*qj zwcRaYXB5oXqom-DW^Fe8y6kzmN3rRvSYzw_fAp!t~VWpOHTHvd9vg!kzm3WFpm%c z^Lk%_&iRtu$qsyXbPE3T%JM&*?9p&2aixZ$0H5d5j+ZrTOO+coMz(5|M&(WYpwN)H zbAI8Ox_=8UPJ8bluzhv^_lLheZ7dCKNa3%Ht1T%nZ)veF)Gkg=NNec!Fr47Wz{t=z zdunxGk^M}|ZmXUJro}?tYv#n zKm#^_K{u2`9xmX}gfOg?pb!Q_Ow)v6odv20E2EQhdf-sVc4C4m7ov?L(H%%g#E+9VZ*Re*dZ(p zwghW|J%I7xG*}B>f*rsTn!yh+02G5nAPrc+8fXG9AOe#C8n6Kjx}hBMZ~=#XiT}fo z38S;aJ2YggN3ge(ox>6}pkVS&UE2x%g^P3+KNF<&0jX&j`Y9T}%hOt66Emo2y7Psu zSwNj%$CGB`#9XO$S4yDwsq=c;{XTlNx4qVw%N@iHe#Ir0!F7?^yGMre)-99wcE{&? zRJrHf=r25QSIQG`aY2pvi!H@pNd-C zAKTd0NW&Y3XC{^NQTN0GNkEIxe0a)Q{=Tlj`e^&~PtvH4iOofAq1@28ZQ`5VPW)*n zNvUG8*4DI=&S-wJq&9U(c%-vDVXb$-_WifgK9rq4SCG7}t!jO=-9eWk?tW2>I)DGF zsPR&>`qKjzU7ZWFk39Gd8CI=mS4e}~M%{#Xw~e(~s+hdM^yPh)vD-CsA99j7Z_~#k zRl=0qWb^cwo`s^p(7v1mH{VhZ!^Z<|FY_X(!ZQdSc%l zDG51aCHGA{yWjap4ypRX6EhswY6gC8Z_{s_l^KkU{Hu&!_3eL_KBSvas-L0n|J%^G z5vSPyenfT0NM+sGJueb0(^ZMf%hUuzr#v%r#{73yRKC)hW~{dy-S3S&LfPkudfS=v1_)2^>0Hkp-n^##nzu6CZ8mG{gj+og(b16}s5 zX#B@pvB(Uy@FQl4N~!hlRt0@UOYCwqEvW%GYIyO6{-IT}|WH7x6?FWtEzNo7N523pbRc&OhQ>1<6Hm zsjsQ7y$v-%CrtMxuH83!?z1ePKU5{cG1thJ`4q=|yNH(Tj2khVbPPA&Y-6i*nw#QZ%ZJn&s}z{&|awMS$jG{LeCV<$vZwIo@*g#2OFhw z7g?d{P2YjJl5ZoO^rOe+*ELF=byttQ9No4mVj@h%%^xwE^7j#A*~k2|Y8o;HH^kl_ z^NtMm9D2YV?BPd83|BPvscE($ZX8dkPBQFbR8irLJ%R#`R>dKtz0l#bQkUYO&bxsKEviT@@DRUV)lCH%`v$oi84%@IE~qmgIhNRicYwS=(5? zadqth3z5g2Hz^Sb@_OS>QpLAi^lBoTcDwt^n{LM+J=RAix!ax(jd9ke_%(zdi*H_e zyxctOqvLydHRT-nqkg1tWgZu%u28F6Yk2cM|mX6dmkGl RU%9R1NUvP$TzoLD{{T_HJc0lK literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/angry_sr.gif b/images/mood/moonsis/stars/red/angry_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..b1fa70c8e36f8a107237c0c282254ed6cf299954 GIT binary patch literal 1602 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 Z2HD@IgzMQ`G}gj|sF~_Eh9wiN_yfml?koTR literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/awake_sr.gif b/images/mood/moonsis/stars/red/awake_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d4389367967d3e45b0bf56584b3ebbaeac196ec GIT binary patch literal 1323 zcmZ?wbhEHb)L_tHxWWJe|NsBLVd!?l$m_Fj#mB(6yhPsYO6L%2JDpGxPJf zO7oI4Qj@b4l>7@yfc#>G8idV2=jEp6l_;bYCFZ6oaWN?VWZ~3c;A7AM`4$wG46IKV zDEFmg&dXS}F6Z^W0-f_Exsx6E?&uW!>6PVwI@zP)P~u7rMFBp~r5!J8*p@0cY>aHx zDvipU`az)~bLafRGj;zKT%7jaL16pp{_hWeecD(W+K|Fu8CP3UUf$ATU#MN&*pz0~ z?O`~^uwG%MzMf_vs~e zwg~hbvCWRHTDRx4R#dV*SEl{^OPV|VrtvZG-aMRf?|$&3s@pCv9s4YKg+&BkyI5WR z9`WnCItrOM3o4!wB(9hTP?*Mr!8>$kt|1=L)5>mjOF?3 z=g7UQXJrbn$ZUygXlOFdt8_D{DrzsU=wV>2naVJcJ-{ii*Pz|7V|GrL85@HIbAthI zy&rgq?I?; z-_k58n-j%b#>w$eT25SIXeH$eJ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/blank_sr.gif b/images/mood/moonsis/stars/red/blank_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..e8553e478943996bad2f8b4542f57b1337a38bda GIT binary patch literal 1533 zcmc(e{ZrIc6vpo+On^>+y96o>EEuq0jB?XqCj)ueg%v~IXE5>w;cCtrg<*k0Me!0$ zSl|oSS#UuRwW(NW6oi?E5_!8g5Sq)B7MO-JsLWJ`Hq-6l+aJ)6-5+-6-gC}#p7S}o z@g`%0epfIFCV!H}LkVGoa6$wjQn^z~7$uw%L5Wntlo7@VXGAa}m2AohNu(l836xNZTm*4jJd9FKsi0IUjd5p;az+KCQt^Q>{VJ?^uOe*uk7P7fyLNck~04?AF4*poN@qnZJ690z}tz4R9NKcE6PBw&xtzDvm1?^)8 z=Z*MYvuJ1WZ$g~@CMqZIgbr)}2Ttmc?4ge4Z!6sbHd_*GErv3Ccuwz-+Yio~piJ{G zRpYyTBZHETdYL+{!;x=yT6RvQT1}B9XNIz~4)|TD*FWBJk9M^g%@Mn=T+`)^q*Skn z3LNt<-{-5-=apJaUCr^DpvugQlZJMm^L|n1XD^MnUTxFcs>X`rt8X4Ld*sBvU+8kY zp`@$&*i6hw&Cw!t>DW^zbhp3Gb52z0!dnK_Syz+XLn7#Poh~#nd)dW#b|x&cE@7^4 z*g5jx(!tt~bB0ylKl5(WSAUhwYo>z3xA#pI>890N;$mM?{kHCB%fU9k3k&tG8CUG> z3t`@U{@>kQmzGt1s&QM-ozIR$tsHWy%TMb|?h4qEe_$Z~fgvbovM9&dd@7xtyTBqPAxJX@3v_-Xi64xc|lpOsoW=u_0&6_9zF52tt4IV zn44&E4Je(X>cp*{Y5un?P7?tsx~$gU@9Fc{%QYc>ug_I=x;}gIg?6tyX@At#)Of}h zY_xUWZ~QXzP|W(!0mD$++7!EP<%ZE)7t>$8cC5fXKjsVbYnwmcwqc*IXV~_g>kltD z)c1rAKk8p&A6Tx*+EH-R>``DJ++#>(_KDjggN5y%JZDy)-PEYlx>hWkn%P&M^wFb? zxiZs!Yj;Ld*l2IZ{vWrR9yWHa8pvq9?o38`_9O( z|S5S&j literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/bored_sr.gif b/images/mood/moonsis/stars/red/bored_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc40340f14fd7e6d7e35246e86b9b571eeed9653 GIT binary patch literal 1529 zcmc(e`%lwX7{(8ivKq&@w5}u$!({`6>gJAujRrv|au-@8fG{H~XK0w21aTu{BQh?^ z*d<)#KtV+a+O3n~LM9|jKv0Hf1U47kNSGzggbBMi2W(_Jd-(nX`*G)oHs`$W`@GNl zdE5O7ak~shLP!W%CToWh!U*An2tuTCr<5>CI3g}loQ4Y=R|NK zm0~Ig6NC#Q1d)msm4r#cB@vQHMVb;Qp%l3Y;k17XG~ z=TvYi6*!=7%k0bIF8cQo#XQzylrtfQd08X2K9~4V&-||&mkMaC1$zK^kOo??1U%3J9`FDFOpFm>8d`7- zoA3oA=nQFSLk!hOM;s40QrQ_$VnQ^=T`DWY{;_au7%RmNu{3N6Yr!4>9;AU5EP(?q zQ4AgcfQd08OhXH7>4@V2NBJfG4u921>pd}-T@>s(;L z|4-NTd+@Dav$OU$A?kmKi~8C4-U~yOYE5YFSntIfHJ*Wq)_6zfXx&D~(UI!(i#H?R zO0#B7dHMHi{8p2vvij~N)SLUPxkHZbs3O0J{I=rGptyFwUo2js8RO&i+MOLyLp>i% zwwU^ootocAzV3+h?TB^pwvAuiUUxRv77%u$A+%=vPRr=T_wD6fV|m9){lm4UjQlrS zo3G~TOfP5IAD+09)Bf5I`5W|AdgpNP(}!ma+8N813S;vdMbpO$>fecQ>rbSY;v-wk zJ#Gst0TZ9L^pNJQD%JXloC7<$ZQ&0ZuZJYIJ%}l>Cq{0wc=XrW=hO7&$FnZ_bHT?4 zqq~R>|OfJDqUo)v)ZS0#98B8rtYlLW@&Id(PBVyBK>uGB~wy@^c4hl&@HL@o7s!mG545y+L*9_PHk=yfB+G*0ku`ZFYn-J(~OED|>KDR7#oqq3oijJmJoN zdw%+g*ZhF`@8N(mLqRd#-G*u7-GSt%E|gxT1rKLRRO>eSn1c>}+?HPAmUE~et0-)> zusQ$Ksl^`iYJB^?zi{uuFKZ5`hUPX-nLO^{{`05h=KqB literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/cold_sr.gif b/images/mood/moonsis/stars/red/cold_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..cfb038b7caf6e45547d7a7f1cbb05f614ca62a59 GIT binary patch literal 1684 zcmc&zYfO_@7(O5@ZB-(uD8{;hLa7%7&W4ww;bH+bT*M2-fu<;jY1kBp7mPYC1q23) z)YdaWP{7MF6RLBGnOl%dM)9!V5;t^gI<;gjZh^^E(CqBt%YN?1{_Xr|bI$v|&-+~3 z_?2;smzaY|FnLbK4kd&U!U++CNaao`VU%!61SL`_Q$`pgoDso@RJtiAj1$g@;6y6J zR1hWz7eojm6)Y+VlY~nmB#{a@Z3>rGiqaEXJKN${7`mN`(i?j8o33 z;8ZHK(9Hzpf(k*U!V<$wQZA{GR4Sw)0<1w3yg&q-u?pA#!!+7a#{&*$OfV)Dg;EjHkW4Cez%AGVKVSe9Ln1Um1XzP6c!3Bu0~*)>!!+7a z#{-VwTq;&VAr|8<1ec1l5DXqD3(2KoG-5#xFdk0BT6hWb;1=wGA20xlArYj31=gSm zULbqhI>i_s5<1Qe6#Pd# z)SmdBKSpQlZ$eam5jWM$gtj+GuFBz;(bZ;-&K(!vmGVnlmhrI9?9@-YhRku*+E|~j z&W9Cu)u;{m34Z2>&a%Fc{G%6Avv1nH9JlM8PdhyAi(h}%zvSt;=y@A9{W@oE-9S(C zst<8ugJVpYMvUk;K4HQ89%(0+u$#40j?XzCI{}a8yzjXJHA!VYwpwz-*??n zReZkhz3F+oi~2@e28S|6O80aJCj_VU>^m^nySJrzaFcdNqrsGs+!NCuJ}~;=ip?{^ z{iiTqu<%v+N`peS-6{F7f1|5-*o&xGC8dpBHkmZ@8(~V)7oC@=ojARb}du%F?!`9-bn+p89oj^!4%xu!bMT3?&tw$t~Zwspmv pI**1w=U7*!Zp*IA%;v7+?{9nTI+k)sf7X^(b2ZSO@tOxQ{0$ee%Pjx^ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/confused_sr.gif b/images/mood/moonsis/stars/red/confused_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..ea3beb1712dda9aa7d069e7a48579fe414d747e4 GIT binary patch literal 1670 zcmc&zX-t$y7#{5|E*M3+zzTu_BJLt0I*|&+19X)mP&q}a7GxQT6)VIlT4|8O71k)o z^sb zA&6A4s3c4hE{TvtD$tYw38Uym5x4QfDCLw2N~N+Gcg84ZR4^(P9w;+TIj4eCsn9|< z6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l*!I@M9 zg9pl7Fd>*!^n(_?j#M&(l~9PqxJxBM`7qxIf!t*s$=+qCw8n$Zzev38zkOw+*^tLm1`jVix&uHD_= zK4;X#v+_(~g|5rl`7(9mjjBoQIdK7MQ$&sJ?9ZQ5ZNvw7) z_bvP+yX>u2pL@)3`gV|a-{$oCz_f%6pNqbm9tMt08-DiY;|IDe89grd z{7s?upZ0865U^>{UdPK3YwxT+v@txTCN0$*bU0F7Jg0X4)-|J!roUQM!8`4=KNdCT z8K0@ULQL0;s+WW2Mwnz5?Yj^MRC7H8( zDi_3`FAr^R4y%}DyS?fBPweU!wysuF#yU2KG^*PTeOII1ZgBfkuUoy!+|FwCQLV{O zU%Ew?PPOxJ$nLVO)6NY~?)*94Q`9@`pQyk8II2=RaIf~xvz?~Ms?78Su zQ+wGizdA$CNXu_GZvEbOVnFqJe|7 z&XNjN`Y7p%t6_b6OG(bL=hk<3x21)hxp3s=t&1l})xObtY4(?v-k)=6&+Al!@ApHg za|Zj5zZh<*I=*hf-+k}e_gFrhwByCoBA;Cy$)~=_S?)g)lWd&0r_afJB`YHAaY&x8 zsVjc}XI#?t8m6{{1(;NKUxjCgVZ%4RO(;b@#pKeoGM5d?n;an^4Kk5q{x2CVs bpV+BiS>%Oj0E2EQhdf-s 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 GMSlUB^Wj+l literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/envious_sr.gif b/images/mood/moonsis/stars/red/envious_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..afe590033c3fe9f5b3a33e0ec92e756422a20b52 GIT binary patch literal 2413 zcmeHHSx}Q#6uu}?pe_MIL=jnK4JclvpcZ8dLPXgG!4{HmMT`n4I#skL8i62)BLnG{FqZ1Hy#D z6oqLDGb}C0CN!pKOw*WQSwb;kFvVb+!3;|ph5*(;6LJXbg9XA~Z!9c3|KEVTvX+O&E55pat0!LuiIDtQ?>g$OC$S05CC(2s6PDz#3=* zFCYS)0UEFY45}d=;_v{6rYMG$5+;PkaHnaCVU>k}fd_7y4pvmbDjho^>JKP)Ok*0mn6eU&HM;1ARUW$6#YnkP-#qW%4Lx{XoIh`*!_~cS!>gaPr z2Z?4~)AkyXwV5`mp)sQ*SKdC~|HbeGf6hVogmaChw;zP$na0V*8<7+=0=n=!xDY4G5}A5sSMy&j$z6t?^tJG;PV(wJSo zAAf`7u>aGX$mM^}m8NX2T}Z_WO?9B6cY*jq8@Jz(=NKcqpVKL^8n?$hSX+6`XNR^T z@u!H&V4vN`+Y;ioTAw}QJ+^Wf>uQ8DFG=f7=j8Tq)y!oM*KL)lR?gnZdn$r;RY5$* z?3n1Xz*@^X>t%IAUw5i+l+NmS(d87QDmo-H6Z^|Ejf!j5=%#&c+oCL*;r!C!w=&Kd zprkdVeX2!rp{=7hzPnmvZSEpVqoy{YAy+p)myw+< z?T_#3E+kN!TG}6|dK1xN{hW^H?lEV!*=%lV43x$ASv*p3GIp3XpZ-iOyki?y(iZz> z>7EB)rPF ze3sHYS`}X>jo(R&C)b7@Unv<$?|3b~wcqli)*{9Ay((9Ey*hKr1F`T_)Z0Y4o?YQo z59PTNr5EEuzW+A)SeggVVP#dfcuKml=>bumY0NIMPFvIPr2EU&TQo0XJ*RZnhJHoz z`zNJj>pWb4HaQ`(9!NOVTzuQM@KJMk{fc`%9Bzp_|4fq2+xB>Vide=3I6~ QIDhrW_5X_et1GhP4{_oG-T(jq literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/exhausted_sr.gif b/images/mood/moonsis/stars/red/exhausted_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..48a6c2e346b251be4f1b5ccb64df130cf139db82 GIT binary patch literal 1594 zcmc&z>r>QK7(S~YD3hYgf)_0A!U7I)9E8GzVnGDf3t-}9@`492XvTHG3j+m;fLjUy zYe!Z~Ss}@BTrCDF%a9#tIGX4vJE2aH7%(`dqkvB1>EZVW^tJP0cg}g=_j#YoZbD*w zWYpF`5=h3$pXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)@RlxmU0UjUv8#3Ai^Ha>K*9Tk!}Mr; zhfLC${F@NxS48FPx#GfCzZ`H@Yd3XWI2D`gYK<~a{Oxd99qhN(Qt>G6%Xb#(Yj3n# zy(8R;CNjC9G&8Ym;d0hi z?O-WJt=C7R6&Gi@AAhT9?%;vEMx)Uq!4Pe|7~0aj_ca&fhccR~vQ|b_RBwEwaRz4dae?Iu5T2E76Ys-dAUj{^3I53;*7;vmdWK6le>d zG3SeU1<&kbi*KIY%jZ_)8JhBLH=OaBrVVRMKAzSvpsTKKyGV~ZA=CG@hYde$+%dMfblZ5Mu`aYAVZFOHsowVfl|6437hgX)aH>iZYp>eU zQ}Sw=rCsNgo$eavGEiQ#HcS_Hw`?x^y8n=8!BBs>*P->FYy3>vw(@|+6+Y$K7W-CX z@L}h)7{zzT@c;5X(sjYr@>vV#yS7d_tt+vwi|jD<^y`coYl?Z|$>|kjX0R!`t9pCv z5l!NGzlul5X8s2|(|*0-+pR8|Fh{OwZ%`fc(%c!n^_SkHj$i)rpLyT@R@PNI*G;)RQoDU)$o8n$O+GgE;Gli=gl%Bm=%6*#(pvR&+fdfQgMF;B-myNn zuO)p?yeeblhAq#U;eVp6? z2TG$idBpvk;PAcs^W1N4?P_jvc{cNj=~8}SgfV<5_YXhMEuA~hI^U0@$A;HXMP-u@RE$*j!) literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/festive_sr.gif b/images/mood/moonsis/stars/red/festive_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..bed5ed6c3c4248367b3982efbc17ab77c80c01e9 GIT binary patch literal 1639 zcmZ?wbhEHb)L_tHxXJ(m|NsBLVd!?l$m_Fj#mB(f==Y!h87vw8GccTEV7Pz({@%TNmo8n})6^!3Zj%k_#%a*FfQO7xQRbM+JRGIJBtGn4hXxSWep6H8K46v{J8 zG87!4;tKAbZVF)vhI&RuTuGG*L7C|pB?=|^3O=c6B?`enQ_2&IQWZS&lJ&T_Lh==g zOA88$Qj3cfN-{Ew6>@>B#Pn2!%se1JRiP*~J+rtZwFqcOS!z*nW_})5X52ho)w%Kkn6fN!S0t5wC=^@AA&S;C+x#Xrqwrxj=e;y&Ve+ z7f()9Tn0mZLt`^oy+Sw|_G`L%`ZSds(J1oLnSz=Io+9j10Ff@4tF|&CQFG zPfoedel2vZ{KmS7CKa?(BIX`DuaM)JbhVk`7@@dj7up@K#}6OQVZt zP5FcSHW7=IT7+27CkodIKIUXx(75GqwM zn(xre)!MXhMc`tGel6Rsw3WfjeCLbFR;h9j3@$0=$(<=$omT5-d$l^f_1kd9E5T=( z*Zv18;BZRzY?$S?j+c$e@t}hH>QXm`ipr`Q-sHfHQik5yct=7uJ4-7I!-6$cOu)ce7M{Is?b@oH8(o7_Kt!>y_I0veCJp?ZnR)uNuoITv&4< z^}+Ja3&!sEzFoataDK*?OqQ9FSCm&R+Q-cNyHrU*>yTRDeI+YKkF!zM6F$3`T?{px zW6LWltPpVWNy@H{k6zcDSF}7oqzDQwS+6ZCE-v<%+;s537R|QBev6G%wYFwmTopX^ z8aETcP#aBT)JbFuQh=EelE^%lT=c+_$Xctam0*cXRdvF|`O0&^X-rjl-hzorbNG0d zhG#G6o48e3X(up!ZCbJVz>b}3RT(0d&)=@R_3#|2W5?%I^`72#nqlX;3(GFeKfLD1 z`9|sGDu(n+&$Z(_|=`0 jo0p%L04B0!2OYL(w9R*$EcA5cmdx|Zyj%N#Y0DY_3mKdq literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/full_sr.gif b/images/mood/moonsis/stars/red/full_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..cab0fb3492bcf069b62093a3d3dd4413a2578674 GIT binary patch literal 1767 zcmc&z>razc7(bwFTy!h86o`r-x1xmvss#~rnXWpVOuvYu1ogO4W!lItN(ADZM%{G6vc3E9?hn|7gi#`h z!yF?#Ba{)wh#+Ed0^tQh1;PX(h|nAX5=POBB5pH>=Qzr7jN=4xG44FiQJ!NwCx|>y z<|#)h$0#R=w9w5njxvrhP7qmQm=`!Ia7^F?ku*erHE4nth+s2T0UKbLMmy?wz@a?P zcwP_{VlnQN@{IC=C>T6Yri^Ed7exJ_g>EYFOyC944!8w-;0FwVVn~E0hyZKQ1TPT5 zWUh9mlnSDiP>992Ge!l`SqKIXl$k&U(P+ei9AG@0hPCh#=D{u413zE@ z6hk6N0}HG{6TCnKn*j}MfMFW#sN(@g5Ho|7P>9923u1)GAAuubM2ZX%8d5?m$N|Q~ zX;=#{VFy@Z7=FM2D27Ck1{PR@CU}7eHUk>i0K+ueQO5(0_)GjBK0*YaY|YyI)yX-U zWihH*ZlDk{HQTEI-^v*}Gk+7}`8RR%T%fhv`geOumlO`!JCZ9UXXD!SlEsbE$o1N; zAxT^6fxPM8`}HNEY4uCj7vJBl$rwsBbgR8==83C&^mdnT)V%9fWnQ*jRb?8;GA}JG zdH7}Tcdg3mu0H+Z@x~j+iT!-*n6!LRRBZpnRmPT3b%d@c<-o&{icDE_Mu1{eGU_GE z>?x-1FTefi3uBS0s;V|508NcdsOPM?|rc-AK@_6nQ5v|I8leASVN>qLQ(t3Z{^B<+p z8q%C@F3Z-ywRwy*>mSALa(d+^xh>QzX}=)f@Yv`yXEyaaQe>~S%gCbqI*0$BnDh4b zwYtNX&1sSA$`{LZTBo~r?$+unJ8tY9%pqY<{cg=8@<7Ljc^&rpPkaKmENqVK8%ps} zpUb(T$@pmdr-d8%`nkKp0+RB{`=?D#Z+)qsZ>g^P;Y8b(!Klght+y*Ctu;$FIgZv9 z7|V{Cp2U^e>Tjl>wAGgQNyLyn{ww5f_DDiA+O=mpHD=ecl1qK6(3!L=A6Rm`v{5^! zP0HAo2aSIESH;cdb88Mo<+`67zUn()uH2s2J@8)SzE-JHw;;Hx$|Fm;)Ao|KjDIZi z&+IC^Z*WfD>QtQgL6-TO`nn~Ms!teROpKi3a(flVdzGszBXg3h=F&!2!p=V}FCLlq z?vpA*#;kYcZ9{{BJsY<@b8b$P8Ga2oIOl>w?;mp}CfR5(k|y2eC(N^U@_YY9nv}3A zbHvY4t~18t??kTnYPe(kkfkO#qx?wj^6cB5cU40tUJq(1_YL=c(VtqR>-fdrVf;M0 z;D%~jO;Y!;vaV1~-Q%x4km?FdT|vd$M-uBQGpJ$PYgyN7t-;4?BnwSh8FXE^V@_bR zBS;!-m3YXU$zAR{-hDh7B#$0mP79T4qe<=dG`6AmgIaCAkFCg2@1Eh

^E9{)Bg>5<0gl-W-PAkXx&75-Z9hkRGF>%_SM`ZLK6M~ZtC6U literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/grumpy_sr.gif b/images/mood/moonsis/stars/red/grumpy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..129048674fc88dc67b1bf1d544d9808f125897b6 GIT binary patch literal 2285 zcmeHH{Wp|p7=9@0qqU7tHsoWE3}=+>QHw>PVJ5;%Mq24GcsNVDeJmE?D8^vqJH4Xy zS+>I|*;Q?8TVc}lMmE)0?Mgnqf;VpuH9Ai^MuK{SIH78)Z!f>x-7Bt%PxU`%05W6ZFFAtnS<1k(gFEDuN% z3R4uODa^36pqkK_qA^WlhGhxOguxVpX$CVaX%GRdfhO<*A}|?70XBd^H5xfHlwr zUO)sU12kX*7<5B9(ft8>T21CrSD}?>S!ePU( zQrICZ4YmYpfjxln;51kZUV?AG*Vrzb-wXkXe zPe!XM_1matWjO;ilyjC|<7IqH)FA#dDEPb5Xn$V%nc0I?InCxqCcA@a>R?&|(Jwz#~oduN+`JLLWue%Ou7X&2)nEPq*VsC)~}= zN$!MxYqL3$K#~A>p$tL%hu3f?e=+#-QBsI4|Y@w+Uog7)tjVO`#2-IMz$dd6Y@Jz z79O?%1X=(?m2APQRcGX{}i`3`6M_;DTnN0RHFR%x30f! zo%5-Mol8tcwXnU;*T}X8ekhU#qhbrm7vXW@SpUL3XJ)g~eDlMLS&4clns$$q zJ@&o)v7!{i4D;$q?s!Aa*~XnM&XeQu>Iv80z4HkIRjR}2hwue(~s^B_ZoFy z*jkF7e;XKjRd#BvPu=T!-)gUMQX`#f5EP^>aNS*SN$kpXhjsOqi9C0tSlQU@?^TSvT$i^qCw1U=zu%mSezw&uMpMZ_>1C}IgL-~E zt9?mppWcfI(SZ3m@V9SY-C`5Spjt|FIDdtmeVA8|?0Wy5%W+NR>2AHfk!#G1Fa0uoY4)Mr z5zRT5H(sq%xBZo>PFdk}$o&)H)e+K1uO1hsHwwPziBttPT(zcTSUYTg_Xe|fiVLOt zA1EY3)6+9Yg+ovFb;;asr8^xiQimsRF|Qh`3mJaUhV={dTjLWdkLAXye4C>y=FeW+ z_U__B>NlqMlxm+BO}3J>sLAMZKYNb+ZmzOEFOwCJ=yIt>V5ICJP;jpXFdfQ*j|8M?Zc=I3s E4Kh#KfB*mh literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/happy_sr.gif b/images/mood/moonsis/stars/red/happy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..fc5db454b3077ca90697de58473481e118e045ac GIT binary patch literal 2260 zcmeHHX;4#F6uu}KSsVyMB*=iQWh;wvl>t-`G(rGb3{nxagyo7FVZ?D6izrJ1Bx1E7 z`Y`ck~`j9gGk`h(d@)h+$)l5y6PUh{lLv)0iMa5JeD85W`ku3K0rX6rw4_ zu+5l8ghmvNXc{pr7G@A(5XB&xK@1Cx5gP&f*F#nKm#^_K{u2`9xmW8?9RYSPzZw|X4nCIP!4&x zfWyAT|KP)sF^v%Q10&mr=GtpTMwXr_ z-OY8O60RmtIr+WTnCI!TQdK&>?0B$MRMul%^NSn7Niq9ePW5Ei2aA@-GcIulZhGat zQKbk)smqS~wvNyq>hEH!x!(EOd+SZ?>yqLgg^IUuwB>g3N-vvtX7}q;ePu6`?x)As zSsb;ITCb8PpUz0$MW@YhOE@w&q~pmK^RmC$KPNp#sIW@2zbNt{+Q^^PV#&Jlv)h_< zIsI2l%sZvOOlZ?oPyEK@Ax!Fmi1iES%{-GFZg5%IGTQtr<#{TF11f z%543*>tq%aJnrAK_}db$bEGmtQ!gmg`K5Jsa|euhZi$kYr9J8P!EP~?*20$Bo54F; zl&SqIYlXqPPj;syZFOj?2-HW9;#T!?NkIDb2OgQX;^nhLT<={`caPZI{;}6RQC|6_WLDbJf^8;M>d#uujyZKnEBPMpTt8HE zvLDxln?4h0{OfO6mba#M%EryC8kDB7`iQVC1C`|qA`{2M&W!GN&_`?!)y>`fkiSQE zVe@ zu;sz(J1vINf_)D9+_yfxllLk|G-oDvTKgs(iyC}oX`IZ7SS$2wzn-|<(@SHxYjlI^ zaPi_*Swm855^!La?RK45I!89*D0Hd{a4K`nZ4?U(4F1uJHk4a_`sa%VmwVbZj{dye zlNnTQVTMp@7eX#oa8BGlJVUcPA&`?1r8IZWe~m4pV)-Jcr%Iz<=Xj4K)lZ{=nPi2+ z(;@qHX^Xj4bx?!#aM9+I3I#trcaf&WyG@n&tm^WMFuCGDl(@cGRO!0nO2V%?yS#Zh zVP_>9A`4c}-;mVl+iVk@S7`iTq3-PEW7O=UiVi-$^3pS)el7o`vqDKXpSaOh)D&~+ zwia!wSQ@)$PTquD9GWM(Tb}%|KC3n;Gibl{h4vg}ke>e2@&#Lk_eRulL(iHkjoM!loCb>r$orz5+jrm#t3Ib$iosR zloQ4Y=S0X@k|0zNCI}Zq$j}l25=POBB5qTMN)nSKE=fXOj60Uh9mlyXXitPqQF zXN+=2g)A66P-dKRPKB%=w9w52<$?;?4!8w-;0FwVVn~E0hyZKQ1TPT5WUhB6j0xFFD8ypiIcGw47J|V8WiFVIjYcfU0mj2=SPL&<9^8UG@B;=wF(iUCu)rEL z!3#vN8PLE67^cyVIv#L@oEfZyLM+Bz$Pprc1dfCeDKbQ8NC~kZ2N(~hVJ*Cb9bk!J z_yGf;7!pAmSYQpB-~}Ss3}|2j4AW>w9S=D2FY$l)2oh?uDLX4JCc_kNTs%zy3PG>j zr!U2~VT#Vw--LMnO%$GiiGy92YCU}xmKHT1AKB|!;N`V%Ko?PM42=EJ<<_JoE^}Ap z(Bl(o!>pzAOAk6Xj7IG?w})2WaH?Au`m77is0xbk-91^%wvCLdwadJRLo*!CZ=&*E z6bCg7D60+n7FFq^5tCN2xZd1gizV9L#IqXTW^coszMX^ncZAgss1=*_>wOkSJ8t)F zdz0F*-2P=%~3sYR%pJY^BbFewfwZDO?SWE*IyTQ@-MyV z*PpM}ylIb0JF_v7NEvHhC+TxDou3LTH`F(K8 z)1JuFZ$(U7lHT>fjA&aDxjQy=>Dh+Y^%E~Mi%%Rl_GaLhq1rZUXJ^IA9ZfDCq50&T zQfc=cOjFEJxu1I4nH_GbI9l1a$-f}u>oli(#j1w)+jdRN3~^}|1Xcw^EE=ur*z)bC zAwH@j-gRlybsdB5wG;i8fc45X-6M%%z1D-VRSIry6rL1bB7PO+%Jsw zm08pVBeATgete~|**MsI$E8zWx9^^8k6i86*5n_ag76;dZbt1q-Cp&o#&k`qRGoM1 zsY$=7Pp%xE+g#FnMQhA2_O{q>wMJRfJsq06n@oz}Yq}fTJk&Y*tcMr8qJR6WO5ygp z>uk!>rVc~0P))vF7ShzGqkBA6p;X zw#WDn2RlvA51*X9JigMly`b6Eeew3Q@N+LZT89cQ@6WMq9a~Xp&bPU}H~Pb&RVr)$ zNW})@tvouv#brQ40lw9J~NtxGfqT`@YZnTy{TL7P8PM zQA0Fjj7%I#2qT0OA`v3wJEeqC!YPp`5ptO_!WiL)Qv0TM>hiz03lhf&HYl_(YRV%!;{oKcBUA@e|)amqQBI2AH2 zbTf%^iAoX`GD{3ILAjukph6}M5nv6P-~}Ssj8(t}7^cyVIv#L1V-jORR*1#8bIv5r zge(|5Q05YoBqn72poMNOm?W5x?SNab2Y$c+D27C6f(Wn%P4EH{Yz8#20fuR`qmBn0 ziE|-a358gUyCiWTI}5?!fwCmHkc~zx$N|Q~X;=#{VIJIqJ@5ktKrtkOG_b%LG{Fl* zuo=+61{kK%jyfK2gq#_yghDLFUC0q4e*}(%5h*f6Xh;dMAO{!^r(rF;gdJdsVfX<9 zpcoQC8dzWrn&1T@*bHc30}Rt>M;#A1@-Oj!_;3^!5!#h8K><-(FAvYj3Q%wyH&Hs{ z`~3+z6Mqw8{+cMv?L!-@ujHBAxY@VmBn0KWp$^M8Cr7ktll;Q_%;z|rwb4X;*U~l^ z7*ed9rwhJS*HL8S(wIKumZwu#p`GvM7d>7#%4~Xkhc6^Ndxsoz_8s{nZz#g9vM0o3 z@aC1=6$SRW`&xcEeIT;JzoED-Gj>4x{f-y<=Dg%E2eqNyu7BN=;7HdEmm{8xPdBRe zE?9b6|FFz`byM`q@KS3peR!F}_~VO}6;G4Y(QA|L@3!3a)sG)OKO0-sT5KVC1a3TG z@icg?pWU;tBKINfLzgMKGc4DjI=i7~^qOh5@0rm4ssOi3nj!CJT~Rl5S-(#C?UOFM z$$jna{b}8uF?;qOH!JEJjy@UD|G3qDi{9|V`nm+4&+E=T9Q*i8)y3VuTQl2JGoQz8 zm@{uI@U!LT47TxE?m4-Nt-JKqEIILzHfiaslya4I;MkquD>W*T_4kSwjSk;C;BV$?T%ntuYP9vA-JmaB?D4ztK!lf%F+-u4 z2*}j^zXN*nzGq2d(5|V@lZHJT^GtKBTtbZIU;L!andOz#RbP@=SYqQ-<*huZ58Ue( z6mLE=-?7kQw$J&ux5o^XS~)i=TUmPk^=TTz{6(3;F8{_l-zhZqxVlVtf28wj=aQ_N zgVntOChgPW=N9Z6ur)op#BjQ*#Y~Yh<=fPE|)^~1aZTPV&ou;d)@|1UZ%_@(s=ALa!w2EyR%kB)T?UY^=?Z)#YeO*g6WEZ<4~s$G@3-?C};_OKnc z-P?k0>DH{A`i+?`EiPelKRaw|Sd&tnJom`R5VUmrRx$T!*oQh{S zW?UN@y`zd+HrGKlbM08SvZ=Xpj{Qdzfm&y15 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/hungry_sr.gif b/images/mood/moonsis/stars/red/hungry_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6b82f7554961f16798d1d84cca8d0b08368dbf5 GIT binary patch literal 1669 zcmc&z>r>QK7(N&~u^NV41QC>r;I1&MaMZMn2^54y1%}ITSp-Z@88C`DnHgRdx$6jo z=^sb zA&6A4s3c4hE{TvtD$tYw38Uym5x2?1DCLw2N~N+Gcg84ZR4^(P9w;+TIj4eCsn9|< z6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l*!I@M9 zg9pl7Fd>*!^n(_?j#M&(l~9PqxJxBM1vZ}g=VRPsj0M)Zmt8mX zyr-|KiAY-7YMODZuR4(Hd7s0cpYmPS?z-lYmo--#o_BO{yPwC`#KhQz-0stZzR{=k z%ZsKQ>o4$XNj0B2;+Y!YI-xIXcJdjj_O9HZPIA~{(CReD=JjkD-Eb!PuD_*k)_z zt=ng<_WrhVcD^C4rNcJd#in+@tNMP*n!xqjB6o-6FHR{p`8~e>85_Mkw<1WtX*j_y z`O9>pW7bu#LyjuT$-q?q5!m$BQ%yB1jjwq+cZDFQ{MS|bu4Oi6wf+3K_{Hz%)pnL^ z)So=*f7n%I>*;=UMMAUNQu~}|8~Ij`2OWHV*2z>pysok|z~ZK;@AVEp5uG^h+g73N zEH=fDYm2>3muTY;`6m}PsG_t9pN|#2S@)>-;DRQLtWdu_B>^9_H;(kYniS>e7L_`! zw4!mEcGrQw)*e^QHhq_~!eh?Pmh7b3kdY^bl8G%F?GI>kgU`&$9%{7jzdI6^?Mn`7 zbnjk#(Do=ZQ#ZZkof>0aM%|nOW1Yrpd$4w)q4-5ZZ;yIrne{#0`dfLwcg$)qT#PG^ zsOmf%TNNG{Gcbn2mWq*rgpq@f$km&+8Ji{L*)_s=?ctFaO}xg#=gx^69k$V~ z^-~O6^R85ddfiwynBkyRRew4q@0@4Yxb-H7(vZHJDdqDf1B(pN4p#*Hdj5WC98;%P R8bYq7$HqK$vLWQHe*xAC$dUj6 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/hyper_sr.gif b/images/mood/moonsis/stars/red/hyper_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..a23cd780593d1b17f308b631b503a281ec5400cd GIT binary patch literal 1545 zcmc(e`%lwX7{(8gIxdT_flvsH+rn)Qoo5n?3Ii=rm^h_YKux5=8EoJtMz$C)0V$Vu zG8YPZSV84J6I@%IVG`VonUi^3U@;Mc6PcHRlWox@Kt^`<@cjq&!Wj{aNF|$c!Z_ia2u`F@ zOa)ML%=m`!WWF7Gg?6#VyH$s;&{N}j0wi1G9en{ z&N&mDNo8R8K$r_A1e41Au!U?cnUG8>I6w<{zykm;m=KL|7lKQLECz-TgoWf%0gbg_4*(C+Kns?D2U@@b9sq!eF(OPu3$9@k zzF-8MAq{Pap&IFk;{iu1I|E8gh{m`}Wrf&37LE;LrPv{shAm+&*aN_WG|+-2aKI&s z!2x9t{ijoiQReKe)ejucSNQw!_ls-8e44~yzV{j?i*z& zeONcLCnPB<+p5+%&kQGh2UY;oq791FE(oC-=3!ZU1_BWd#>GzDf(fH zIUqUmX1M9SkQhzT5u2|6Y`Sk$tzlb>wkP;pX!5zKOCy~>o(jD2Y&6{ z@J-QvbNo)ouyvESp!vk*CxrYqNh&_&uB3XvCJ7yw1O-HAQTbB{p>L(>kY@UrS<-`q8nn zZi~e~y?mX+`TE69!$kAYgH*HSL{>q&J;xfk>9YRsvEV~*e2{v+v?Q}K_sx>L!Ik#F zq(fEix7LoGA8O?RpIa{Z)5{NI6WVwAcSl%k!rqZyx^&&RNqs-AaqKPClZD(_?avci zJ$_y4o%4A7i@bFc+OWW>y-lZ@jE&DyJ?`BdJe}X=5v2OflsI4H-4)I|8x7fh6Fo12DlpO889;fl`H;a;nZN@ zWzYd>1v!I(^=5){UrOe@j8*G$vY8AXoLir0Y~;)A7I?=pw)?p>50B%*t_TCU!c(FL zuAAJN6d0HjRl>*AoGWr|wG?NZw!rB}l5A;@uSsrTEPr2egL?t{E02n*YQNg}`i30u zvgTH|j`E7i=C%oJ0Zw_D^=<7Fz4FqS7!vyDCx>(_>FA7%N-eB2M_F70?(!?skpVPj;gR%ujT=>v&|%$@TK&(!@}aB + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
achy_sr.gif
angelic_sr.gif
angry_sr.gif
artistic_sr.gif
awake_sr.gif
blank_sr.gif
bored_sr.gif
cold_sr.gif
confused_sr.gif
dancing_sr.gif
dirty_sr.gif
drunk_sr.gif
emberassed_sr.gif
envious_sr.gif
exhausted_sr.gif
festive_sr.gif
full_sr.gif
grumpy_sr.gif
happy_sr.gif
horny_sr.gif
hot_sr.gif
hungry_sr.gif
hyper_sr.gif
indescribable_sr.gif
indifferent_sr.gif
loved_sr.gif
mellow_sr.gif
mischivious_sr.gif
nerdy_sr.gif
pensive_sr.gif
sad_sr.gif
sexy_sr.gif
sick_sr.gif
silly_sr.gif
singing_sr.gif
sleepy_sr.gif
sore_sr.gif
stressed_sr.gif
thirsty_sr.gif
working_sr.gif
diff --git a/images/mood/moonsis/stars/red/indifferent_sr.gif b/images/mood/moonsis/stars/red/indifferent_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..570e91fd216a8c865a0148e394a66b0ee6434023 GIT binary patch literal 1532 zcmc(e?NiiM6vwa17Wj~~uDe=p!m@+Aq?TSE*igx2g$2QQaDl)=WN#&_V-T7TXhFaV zGdzo2TUbmCWx`k(pYTP~1h~e{!O1DhiDnsUpi!qWE1gMiUw-`oz3jf&oqNwY-}616 zvm0yM7-`vNA|~<|nLLybMhGWF5F(X3rG!z!DG`)NB}^G%jBrK-BT~txoG?x}CxR2H z6jMQ%AY2e3h*Y$wBuo-6iI7Ap(v(06rN~7Px5>jO<&+9arP3I8#wcf0Fe()v2s2JO zr-D2;+=bv$A&Y_G17RV#R6t`b*aN_WG|+-2;DHwKfCm6zVvGpW(1L5& zgfAFDXGlXEVyH$s;&{N3%Fcii6QVKhQduGPkA-8ySSfahrD0203-$o;APux&2^?^V zV(8d`7-oA3oA=nQFSLk!hOM;s40$}jPM_z0CVlB{W|8`i&SUB2|iX;WY! z^kG2I8hkIFv@`iPA%Ty{l)wdX-ECi#2F{7d_I025vLZMv-W})t*jjRPdG2Lj@U0-t zBD-_UHN1V{xy%{E06+voPd*gXQ6-3EF#Vqcd{*;0?3m ztK`c0(cxbk%62R?TO5bnw%!x5nne}%Eyt}L`p%H(&hftC_G``04BfkKvR5|NIOpbW z_@HQd)2Z~{r&rxFP?!fC|$>z-V`x6!iORS0r*>&61Gh2InMaR6KQ~#*0 zs?x<4tnv1A4Yxl1W?${7VJxNDbXzm)*`m%Zeeb_8lIT0SBrz&Dy}s<`6;;Zor9qyY zsVgT|I=6YZwjTKQmxQyaVFlVphW6Lo`n9=3zh+GDS1)a9^G#1{yH-=(5jnENx_c*C z<|uiTrLzwHaA99=a_2{9w~lS-DsPETUtQ^&S#)pT{*_}#ek@#@eOTLSJwL@|%KK(X zvA*cW(a@S{(K&T@>ph+Wt+j~-#DZyuU*B$g&0~$&{x0?P%T{e%M e_Lr+N{r(DjPT;8PIeXmb5p8RRp&}Bzqy7OITY$g- literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/loved_sr.gif b/images/mood/moonsis/stars/red/loved_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d5a3fcb65c7e5dc9cf83cdf4e3313ec43cfef43 GIT binary patch literal 1728 zcmc&z>r>QK7(Q|fRwqnA&?H4gmX#0pS3$h{yn5fK)I6wMZ`R zfkovG;$;y<939OBH2e)rsJSXOA!?}sUdUobJw5#T1Nzwcusi3x@B6&ZW%skCOT6br zDv6T(MMe)Lgb~6Ckq8m;ol?Rm;gm>}2)RrdVT^D_Bu0eXO*vtla84vnggi_o!X&~a zB1uHZSX2-u2p2>WM99#T012b$MG?2r!zksHN|XwDG46~}&Zxwwka?iYIOUv5oC=v1 zx|u||L?wv|nI(pqpj=Q%P$83s2(SiC@B$HR#wuU~4AW>w9S=C1F^MrDE5u^lIcE}Q zLKX}jD07KP5)-n1&_XvCOcG4UcEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ueQO5(0 z#JP~IghDLFU6QzvorPfVKv@!8$VMX;M;#A1Le30ULLnC8F60Q2KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4 zPz;G64J@z*P4EH{Yz8#20fuR`qmBn0`Iq=Vd^m}*%lyJZKlRo4&2j(GbPOmsjhI>a z;@fSM&gkESSiT`+ET{Mz4qeQ)v{9{6J`JmnGaWF-w;Q4^YSQlYdYJ!uz1%z5d*u;J z)pbYLplaipOVJAb{28-vTiNZ(E1wmpY00rEbUGLms;iFP*IZk!GwzED@DEi4SG=G2 zOY3{UKlUw`#+iwqeh?6VHE9 zM(uZ>?RaOdHr;Su^X6EFI($NRY|4eI;VoP34cF+ntR3B{_MwAi-R>8rx17!hZ0g-8 zJ!8widT}FtvS&|ltv-CkpJAE}8TFob6VEO6D9tg8?01N6TdkX#b=A4UiHPvrvQ^>5 z?eA_^F1}K+E9+E?nZjabOz{TiQl(S&cg4;#JZFcs>yuof`fpBnmg>J~ci{Bg@t&$S zmoGz9ZcRCRsLEWw-{ou9hq~yJc*d7kH`JEKDo#EuOQ^K^O|R`-T4$H|(8|Y0PSpHA z6HPEVeyizPex$F~p~-n%j7wK}e%)YO-rCMeAFYcX7M(aX7B|v7`6I)R#YQbh)aoH;J5V7k_=(&*g!2 zPczm%4V%(9r#~)4_s*TJqv?kFRF9fLpQa?g+uJvd@6Rj$qI%|FRhr`St!Qb7gz-tBdIlQ3j6^^G&T4+g5Hjy>+T6JvDMh``D2C z7LhsW&P)2@Oe!_2mj(2hbG1wTTZgueSO4CZIvlySG+BG9)o2@_-{2EqJW|k;=(_ic zX2*hxX_I`71qD5+b0_BRRn!gax?dQ)-g4U-9uxhbWL4Uu2m2%bO>|zZU0iLvIbYY3 S$8_sET$w(p^id4Loc|BIQ1^lW literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/mellow_sr.gif b/images/mood/moonsis/stars/red/mellow_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fcbf7d749bbb0c9e04fe2196d2118de9cf8152e GIT binary patch literal 1519 zcmc(e{ZrIc6vi(m6K|s^3ri^jEXg~La%*ENK@fIXP+%8WWrPw~E@A63>XbDjOz|Sj zVnQQfm)S-jUV@p7T_&U&Yp7r-t_Bm8iDizGSdyhp>ezI9`1S|%WA}&Mx%Zs&oacPb zuED5J(v?P&XmW=vA4&)#gcBkNk;ry#U+ZFq+C)VsZ>m32)Kq#_<|91Mk{DT4An?S91l30F~OKrCPZW0 zIcI`1sSFGs2y?-NU{aYMwvf#w6Ou^<2WSBgcmMz<#)y~+L%=m`!WWF7Go+ynF;pWR zaXjD%&ZUA96QVKhLU5^&#lY}^u#j9Tps^P00pLLzXu%TjKnr-l0{}2FMucf-!8L5c z7mT1Yq@fKlR3ja6Jm5%WXF!Pw(HM8BtPuOh!m(kj6g$MyuqCVodjNQl23oKL4!A@y zcmMz<#)vQtEx3kF_<|91hBUMxhH9iEjt3m&m-s(?giGI?jDq}asd*WR8#g`R0Sn>x zR(hx6JAT>D^52Ab{Y^Z))@KfPjn{hx#1>BtcYoUCACcwEboFG^olh+LaLRw)TNP!o zU2UEz4^58BX%9BKyFO1o&u|R8dWq!p@9=kfE@Yp~Vkode6P_@bsFg5x54*PhD+OHIAx%f`qZ@jyIYGi>yG)k6AM(?8g+7~ z`Rc^UqzxYrKex-L^2=4#KYjMiSp4WGVI?~sed${D;@AuO)FHL*$E~)8lI@$1t~fM5 zn4f3gk~(kC{H5jHJf^!pyH($IxbI5i&&5lbwz%Y=9KXVAYwrXbZ58ffjW+OC*XytO zWXFeJOwUc|H|6?i7k{kxUu&IcP?@LpGzMET%}3Vn9V=}L(C;#BRTz8z7vof$zf0%5 z``b!KK-?qd-sYwBlgnsl#$4fARn1*1KTu~iHio3I_m6wNHGSeiS51M=)0*vE9Z`FO z24v@|^EE#>y=Eg!F-5(9T-Q~w9WAk8_8ZOa)j^$43>MT>dZqtSCbFCZ8atGJ#&Z_EKQGP4j@hU5{nV)W$J9_&u(?my=dh(rv zr)RnU+1TncGh<)3sdMLQOy9EK+v8l8_|#IOx$xEWGaY@7!U%0((9*Gi+Of*a$OZ4R zxKdY2O~cLiPOH*m)Bg;8dChoxnEhYI`sm9ID$BE%^%m>f-GM6mV(F1Jwb4Bdnz|Rm K^E^Drlm7q=?{(Dx literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/mischivious_sr.gif b/images/mood/moonsis/stars/red/mischivious_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..3fb448978b7c826dd36df88850fe7c0434705e5a GIT binary patch literal 1799 zcmc&zYg3a)6y5}=AzTa~P*fBU3IfvLLKG=Z03%>ANC3G-1q>@pt%7Y49Iyok5Xw*) zQCvg;C0x985~_$DodO06@wJ1ZL%g(AM8#5UwQ6PB>GtscfPU?MNM`q(^PK0BM8&LK z8ItLPe9)h0_F#kvLKGnmA;#Y^Mg${@5r+}u%a|ZS5G9Bsi1FQ+B0>?Rh@*({!xD$dY!5qPi=K*CxF{PNJ znDMlrn{b$NnBy?xS;8=3m@>>U%y`lu0$2l0-~~irGpqt^0E200hdMmKp@eXRFkT@n zhC8K%qlEE-fd`Z+M>vi!UO&)+ZpsM92;=Plx4<6o0}KGgAQ3cy2w)8~ffo>g%>WJ9 z00z_04t02d!%@n3D?uSFhC9bm#ybmwfd`a1Mj3B3!~!{h@!&LA3tobG;1<{eet-d> z7$gE|zyj7l6LE>tOSLy819UZ5b}q>Az_FVGKA0|C5Q!b z0OP@Fuok=oJAfq&gCAf3Cf3u9TXTEi3gNC*@x)bW~a=+AXMFU7~FAsSA`C>n+3fSX<(2#~fV3Hurbs zJ+(ZN@?7KIbucGtyYw#&wRf0Y-{BNEF!9LYTD`xjJtL^<^>}>Omfs4eBVV76o#z{{ z%4ViJPUUYZRt`>$S~%3<;a%1t=cPTNMbny)rrp(6O9M3G+DVl@O`F@%eLd^xi$`?_ zU2lf9CL0w$WW+`8bzlDczC&!=TSI|OdfHu+y7)bpJ-VUQ?e9kvl*Wsv`clG;zwWy( z-!bHDwuX#<5E9-gUHske)~Vv0Det1GH`_ylcWdT(9o%y7;`u4l>f;S)eeK76gPn~y zE_GU{*jetZADfe0J*;_LDow=DYG zm%zO-TG!jGN{aiYzAU zkWlwUx!ahuNK)^7RwDA-=xeS;CUaGGgDB~lr_4{3Xh$vdWjB=J;f5!2ve{f)B2?cn zHks+|qpRa&rhy~HVuP1V7&PhDurcVDoJftwsnL`5G9zg`MACBF4?Eq>mhLFe0l}gEybu~HJ<9z~0S6iLWi17=#g}%zLc4SFZshP~yP#_$va`cQpH8E-DiMIQ^ zeHD^_!hBf1G|m`1+&#BBG*x*Zwn)**omkc3xvXwi`>4QF^M-bR=H1g05k_eRI$eJ@Wnx|a9o68E6$-7#;NkMXvAWdf(e(aH zX=Kyq9U0-qki3a+RO;xW{?V5Mmzr-^|7{)e>On($+#mk;-p-eG73l69_sAB<9dU^N z*(KzTMZR7=EB4R; literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/nerdy_sr.gif b/images/mood/moonsis/stars/red/nerdy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..52718190454cefb26f8a40ca06092879b2d933b5 GIT binary patch literal 1559 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/sad_sr.gif b/images/mood/moonsis/stars/red/sad_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5509c8011b885e2cf08967d617945a297644fff GIT binary patch literal 1588 zcmc&z>r>QK7(NIjs55TtCa5sTV#109akLQ=bcGcNVp}dY7Ab|C#96ixCDMSIMAqdt zLjpQS76n8^?XtVfP-1?NKvy{w5{_#&j*v`RnvK(pnAYjx_Yd^3^I><+dEfVWpUZAa z+Q!xK??#eH@|esVN(du_6Cwza%AHceDB+X{N~BVzj4(zxBZ3jBbW=_kC!7<(iByKE zAWRT0h!8|7SX2@w3714jA{A&#fP_)>qKMnfVU%)81*KA1j5}kLGb$LB3J;VSr<_y4 zsZ?m8n+eJV6@p5IC5D-#Tv8#aR7gVvSc4{bfe1EZ6|ez@X|$t`2OQ3rU`#3su^4yG zncz$+g24l2E|?HZD*8bS-CQyunN;k6Td)UyzyK(QL}-Etum(-=0ugKmG_V1NX|$t` z2OPnS(`E<)>br=XP}H%_?WSefkfdT6NUYtS;MwA!F{T z1n1eFs44BO{dqUWnrB_zG3F}Wnx9ZV?W67~bG-BM)7;+M7n-(~v@LReQ8#wb)YvW@ z$1nBmKN+0F0u7tmXO(uZOc)x<|FLYRw@sJ*`}m5g7&iEM>-!6AIsS`T;>x-<7eD@2 z=68ELG82=}R9ffNY`8L4cfNRXyf|SvK=a%YYjB?0P&R0K)0&r9UOm*G@oec^#)xmq zZm#z<=Rd#aaoGNbIe{VVxq6lUqk&I44L(iQfzrDZdUv^J)U1u$olz6n-7{G`yDhTw zh1iSRef8G`E3m~}?g_8=zGf2*FFuG|TD#$qTWj(1nn}d>zY_WOfGYeod#bb3u+J0s z-Z{7GroSd)llhKqv>88_lZ= zE{^L8ub65Vu3I*ut=HJF89xU zhqsKZ)=>8ii*fH3OUh2mc~5AuG2}?x)YgYZ$BfU477nL)oAmvbd8-~Z-y)7vjo$|u zrmIS>S!cZ+)Z)l3mJ7R%nTrd%1_IK1zB;?qrQl+uNBOW8L0Z9~`Gq5%TK4_;IDV literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/sexy_sr.gif b/images/mood/moonsis/stars/red/sexy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..a0ee4fab17c8276af043c637d6bb8be60db3cea1 GIT binary patch literal 1699 zcmc&zX-t$y7#?6(IRX(-C@6_rJXo}BWdf066sjB=MdT8UE}+Y-RUnX3JgJJTVDTt+ z3y$0>h(!%}m9`jV0a16VjiwZf*iyP^Y^_HctBH2{@TGtIyYpi=Gw=I8?{nb&ID&t z5eyzEbHRjQQqd1u=;o3M$)sWj+=4yu0|r1bBtjEJfHi1>7l>dppn(lAOrsrjJm3h< zrD7!%VlnPQaH%*8!Qg?ikX$N8BNpTU4>(fE3|2xR7UM3J2$4SmN5Y5{86q^KgjkRRjEB>(7GA;*u*5L@fB{ep zi69Luum(-=0ugKmG_V1NX|$t`2OQ;>_&QsTnM_^9BZcOC3NLGw!GG!Ngi z$LNgxO^D;)#LjU_Y+FOuZb#3+)z{h@yGtkdFR6)jzfx769vJw#xHqaV*!^vTYUk-` zq5B;!mvp`r{QiEOLtITn<1dEZ@{pkO`|=u%D&L})Vp`^BYvbxQx>U!#rsehFX>k*4 zHzygbF3z2fkEq&O>p81=$*FdKL#dl)lIn4Hh;`!0fQ==FWR2y3OGvY!!gArDSv#Zm zJ@e$o-D*F-f<=dK_a7K+p-s*ysSd@aCe5Unj*;(Ar(X^*+^*Rdf5xpOTX<8 zvrTuFpUKN{tC{!b6PI?=sKcP?!w0&X$9k?7hCS8(@oa%^SKV;I3F~n4}~+VOLkEyXx}S$_St?q!S8i@%EW`qAle*!qS&)~w-yrQ^&KeVuP!R}Dwn ze;qYs7n*s_vNWNm)KWe!^Vkm_&s|Ggoht0EuZtXL$*aqlezL8{!+*nikIjik4Ytoy z*-2ZaDs9+Sm7eP~dN@PBc$8-y+1p&TTJJMKNl+d9-wFD@wmdDjlsaF|$e+``w8YWP zE@QCF^=O~Y+eg1Ie#E-db7p+Y!-wvgZeQ={=#B_#zkhyF!l8`2x2K9D-n!I|GPSW% zJ9G1kX)o#MH6^&+wzx{qS>~Wgsq6ZB-TZ67X!2W?{{if=Jr;e{at@& z;7n%XX`j|yli2ao@Z7AB7;jztsjd3(34^2aV-7y}w$m_YOYuP7^Zdv+p>OUzvDQzm zRu2vzYi%+of9!jG)7|K^E52Nmpt@=_XQik&jW0@EUpTbz*|S~xwV%{R)Nbg%^dQ5l z@`CY7bWL*VkjW`?MpRmWYfFW5wYto{{F@<@hv!U7jD-cvE*n93pH5k)&N*+Xc=g!i l7o&>S+RRBQAN-r(#<2ub3`kJF3JI>POPf*kO06Q{{{V-x)l&cf literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/sick_sr.gif b/images/mood/moonsis/stars/red/sick_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..66395405259fcd25dc5dcd5bea3cf116c8ce33c4 GIT binary patch literal 1875 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 anSI$>%jE@ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/sleepy_sr.gif b/images/mood/moonsis/stars/red/sleepy_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9cd27505c20f18268d52a2cdef304c9e1beba5e GIT binary patch literal 1578 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 N3obe6^~L})<6jVT+W7zg literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/red/stressed_sr.gif b/images/mood/moonsis/stars/red/stressed_sr.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4d4aebe321664d05cd2a01f0b45a7ac4c19e1f1 GIT binary patch literal 2853 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 YIY0e;!nsV#lk4)Cd}UIHrG<9>50I+H3IG5A literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/achy_sy.gif b/images/mood/moonsis/stars/yellow/achy_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f724e4459310605fa715f2dc18f7874aca58ae8 GIT binary patch literal 792 zcmZ?wbhEHb)L_tHxXb_o|NsAIuw?lB?e70S44*$WUD?5toSdwwsVN~Lap1s#Z$EB- zdf)ovfi_qzgW`W~Ki808XU70nBRvCVMxdzTzk?YiB?VUc`sL;2dPOBU#rbI^ddc~@ z`iXg&xrynS$@*Me&PAz-C8;S2<(VZJ3XV{51$R$3g)jv}JtHHoq)LUL%=C;Bg_3*) zpVYJxgK&i;S9EoH)flPYAoZzA80i=Y|cTigN?5bF(nr zK4~m{g(1nOv9Y2uT)4olKC9QKvfbIzxTm?*QKhXax67z#2IF*wg%iyEJ?E=VST(z5 z`4nab-PN1g*Dd!9nXr4?TzRj|_=z0*WWA=%TsmpTPKTx$v#O3N$A#sv?O{8zBREr= zDP4Q_Y5(a?bEG*RwOR<~CVXzU=Ukod{Q!oLVm9~Mo;$ny#4Uj_~VyPpTE9-sVc}|4FHfxM`8c~ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/angelic_sy.gif b/images/mood/moonsis/stars/yellow/angelic_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a6079e582b5d8f6e7bd89a787ac2d1256507f9ab GIT binary patch literal 1902 zcmc&z=~Giz6u+qf1jJG_jzFTagP;Nr7|`N?CJ<4SO;&MOk_!?Y6%?c@WeJKPOJwt+ zC>0P0izu49PzwqQ`hp;`*r}FcOG}g)9V=El`g(YOK)?2WfVuaa^E7}w!A@%LB@oP=ru4 zp%|7HbYq$#G)2=C!?J{7%us}(Xog}~(jWp@15MxsL|`+l0&D<-X=sN!Jis9s(-#o zKm#^_!8Ei(9UkD&gfOg?pb!?rou&!HItzk<2b5`sFs#uK3*-RCgVSIwcnRi#TVN0P z0S16#kO-s!3s?h9-~~irGe842fWb7hLmeLAFl=UEB`Ac&aA(*EA%6%Q5{5`2LkJC0 zf>Iapv>I?KRyw^B1k$(bxXn-Q$K9 zerLs(Cu&znvs>&s_WO(E#YVb4K1OG{gv+ej93vdXB?`WKc(`ti`eBZXL0hLPF4wzq zHFc9aX=J0~b%d7KUjO1Ndtr76zeihAQR^!^&@RbWPdkLJ*J%?z(Nj1Gt@PqvILemz z3HjpPJonj`u2+Jl*Lp^U_HwevadgK`ZTsUl;vZi5n4cK>Q+dbYb)qQe*ABwmhjRX# z#^kVwA;~qPqoaGn8ph5InA>&CShR!-c&m4NPd#WW2<%Aeeem}8=g!O3-}r0WU+}FO zso{5brt1D&`Ga|!uE71(q?LZN-HGxKd8f0gKdaXI3lw9CvcS}Hf>WQWrk~5=qZZ7_ z`V|42E?s*q_W$EmQCT2KQ)$hXB@P>e7)K0ig)Ma(i_ykFFknD}9ZWN_ExnY6+*??VZ{rfgMkM|NbEyXd<}Biss3dhHCaE_7GA5(k;V zRE7M@^^f^FCEoGp^7U5b6>8n>pFJ;^8YXhmL!3iMjI74ebd${8{6*}0k%Ux8`z&or ztb-OWP5w09mBncpnUX3NIvK}oc~p2c`#dec4W-wn_jT^r>ntJ#eH81N|Ot2 z;XMQS^~$B3A;dz?Mv?mT|L5I Gb^ih}oH+CV literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/angry_sy.gif b/images/mood/moonsis/stars/yellow/angry_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..955ea2ff4d3dc46644c0235089add494757032d2 GIT binary patch literal 1562 zcmc&zYfzL`7(R^ix?L@Auy1r4USAD0=q0A z0?Kd%1+g?yG%jm_jw6EQ386}8PBoBG zHxrZ#Dg>1ZOAIqfxuil;sgQ;Uum(-=0ugM+DqsT)(`ZK>4>+7L!I)GOVlnQVGr^fu z1cL|4TreS+RP=)uy18URGO5@Bw_p$afB{epiO>WQU=5n!1tQoCXkY^j(`ZK>4>*Ez zsaOexSd6<6Tq@2&FnFLWB$tZOhy^*ocsLDf;U&z2Td)UyzyK(QM34p+Sc4{bfe1DO z8rT5CG}=+e1CCTOgOyN-#kfl)LgbIYkuV}fh6oKQAr|BSO_)3w5tAD-KWm9O0on`8fv3$6vV98Ru-fy}s z40bLKn>Bg9KL=K|pXHj$fnaBmuuiCvOr6{`I-tYNT z=jh3zlMe069~pg^n_tDH)r)^OX8u_2zGt;X;;zW1^RLxqXXyv7EN$4jto#35 zeBQ6Vwew@=&S$+{?*yzKToq^5wd^`)p6}+gJ!ip$XXhqG%ueJSS@mFG)31Y_j|zWCn`y~t(-_8bzneLeH9!)oAGa`@ve^)nJ{ar&Up;+I`!%5A~W;#W%y$VYM3uO28+AwYss$b}%>J{}yy2n-`JjG`OE9mg>O$4DHb zXdV#835*~xlE5gM7G&cjMvxduVie61ig5}fD2${qiY5&rfHlwrUO)soLo2`rFsO!f zh{FRM0>?=lr)Y)H814jtlLSuDf`JEw2@)qsoTBvuEyyM)oTPAywgcP(d%zDc02G5n z&;%lYHP8fJKmg&HxSA00z~N4sm#ZL(ww>D?uSNhC4-% z5atg9hY7<-VTLd?m=cTy<^aZn(_k%l33dQWC*gL=m?kBwFIT+K0&i3j8Hwvmp2veWdg8GePVRh{1M}bvE^t zu&upPJ!(&xm$SRV2TiQRJclu_6@z#Cj4D>xIGA(`WG!ONB!1A<>Sc2O>I5UgxKP)x z&B<}u*>oV6Q@N&c*Xb7D8j({|z=}K9#M-8ARn~0PiFT!(>g>?Mn4{F?pekcQ zahZF;x2Y*Or)+4t+B$zEqPKj$#j0kdCiig1)hD-rg)*kLxb82@ zmmF<~Gu3m0`*i#M@%C?lUp3t}eSB*1)_s(IBu!p=w&;41>wsUy_XTQUhIne&-g^C0 zec_7<_pzeihngB>8lHhI_)IM;7ior74WeJTy%X}$p(%Tm(D_uR)³HT$$YLQXi zV4t7YzPnET%?Ep*6o2yL<-7dNBZ90dkxDr(mpw1DFk4D0l&5UHSav!klanU8pqXqVcvyFMn}?Wnq{} zxFS@_i^T`<4*5U5z zpqJ|O4t-}y(>q6-|LA?=y!7eW1wJO;oL|>OTKJ_h+2u^DT)%3j*`aEoDnP|ytbG+P zyunV|(i<`v#ypok)@hV_+bnoNsW{ECv7|o+*8lz(Ecqt&R;!vNrA1oyH^X&X?YxWD zSIr0qs$@Gnx}0y=s^cRQwA$1gzsD9z>S-H-gv zyDHLB`Z(fEwv*l2x@2oS_M$DWJJeggVN@*A8fF^fMZKBHk%Ga4xgtVpn;?s4oMc_e zIbVA4rDDIWcYjj#cig~z7D>ytw|`Y;BL7L0R1ui9D#FLj|5D|{AkOnQ-9fE zpAkVuMYoTAb4k`F*?Gj^ z{Mu(vGS?XorTbi9#makZ!X|U4j#Q}jrW!>*+{_$%WvR>vG37_Jbxn`Q8YlH}Y&f4k zvOkc$($Jb@)D~ZRZqvFpll+=zuFp>&8p^Ew^609?^N#BsqR&P}sRrCbj<)$H?$$Ig z!p=@Tv+#^)cemT;lh_ihOZTzCvl;!N=VA1KU!jwyUMD;A^LRSTWfv@dX50MN ae(pC7qI=)}-~0bu z^Z$Q_|3FMSQ2fvB=Nc01>=@u`q-Vg)2sAo(i%4uBV`YrWeZ^k@d z&z0Rjf7isx`wnE??3i?}Ff5_Y>@e%uw0I6P#`H&5?@sNR7sK?1m-U@yo5x4x?QcBO zK6CA3lFyoD0|KE*tqDZEQ?W=ibLVz<2{1*T~joKo*dOx1cnMI zP;5{Gg%_B#TMon zx^9I@QyT*JrquZFx{#e$ZO>-EpY_D`R89xRoICZs*{!$tFfcvqIoaHGYmd^~XRIIl z-?5gcS^jx-GT^hv@hQz5!dfvani>wb^9wr7;h4yAv|Cg+spP~3Hx5WZ=%NP1Q$#?3 zQ%8Oxw~;UN(ZV~HvE9#|6}TK1c2yY26`m43aNXqAq`<(OssM{#-XmsQn?v_!L^HOh ze&p&f{&hQG{cZ0b=FgreOErXBR~2(`W;8T4mxgyW3qrtD# zAu^x6b9v|DNdA~*D^_-|_VJxDZIT)D96g`fiIW!Xa<+?`wr}}HueE+X+NA>y0Oaj&brWxD( literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/blank_sy.gif b/images/mood/moonsis/stars/yellow/blank_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..319bf68f801b8fc1806690523a6b9fb87b35e52a GIT binary patch literal 1508 zcmc(e|4-Fb7{?C@K~w575EOwc0Y=%(I0Iu6g9Ppcf*~LRl3m#KNCTTFkg{0uMZE?H zq9i9+l7P|;0tUH>(*nW(4dJLh?x_w#;U&%K)9 zptrme-HAJSN|p~Lgb~6C5rjzPPAOrOa7qLvQVCN=7$ck!!H86{DJP5*&WYeeD#cU~ zCI}Zq2qG0NDhZQ>OCltZiZmrqLMd_)#BKR7N;##1QmHh?oiWN86^u&72f~a~&Z*#3 zDz=c#1m%JXL8amn#Y|EzsgP7ErZEIu!zO&e2s)z`v>}FSq$7?89L|_vOezziG47l* z!I@MBh7W|fU_vmd%nw`0=8_4?q=EyqfCoGP02546%G_>FvHsK3K z&>7Ouh8U`mjyN80q_Q)h#Dr*!yHr+){bS+SFjk5kVrkeC)`C3%JV*mASON!Jq8K~? z02539Syo2uILEUaHk=x+L|^O(vdq*B{_E--i4Bk6LtYMuE?hmh1s z!_A5Ml=Z=du5qf0BXKQG4P#BEwSL97lS&Wk69dCOAJ$z?$DYkt6Lfu zC%4-2ITxV`v$lG#x@=l=R%4gdI_o}F?XlM}ZQn?G{;rajowH6aCSQne3m7<%u{C!^ z*d_hrFB_g&oP1Xk?>J|+)@v-b{Um0rMbLXh2pG}Ku{qS=9 zwZi!c&#O&##aGwZu+(9P=%1%bDBF4ETy}i=TI&J(AHyskEos{(27AlWw!D!YSrikX zZu#k<_m#;AuC@%-n|_dZX}hs1XaDzc9e@7y(7f5d&*`J}7oYs0sXQB7_H3YV;}2%< ze{5eCQx#^hq3&+(stx+CJk>kpx_p};ZRC+P@rM$RzT}m>-A}=5_Fs7YQ&r90l?x?# zW-q$AM%EaLI=_pv3r-##UZ#3`$Y*?WX-&rowPV>~{g_|q8T018k;UYq>Vhq4&l&0- zeNi8fQsQerXK)WU*zSECZDhvY0^1nB(cys(m#_6%y*4uk`wUjLZ$6*h({9}5sh!yL z_VpY$O{1^6EUo6i`CcRIKS6p2lKMN36PNol+S#tc1j}PP`27AI?HSIe9*i8E8*Scm z!*};gQ%bK!Z>m23OJVbV$&U*#uhwnKh>!X`?{V^S2UZ9 zsdOp+hWmZfrBUO7uD|5`i`VPk-8@y$Le*-Um}IkjTc%CSv(LPzJGL(5kPeKu{sZ6u Bj!OUl literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/bored_sy.gif b/images/mood/moonsis/stars/yellow/bored_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bc44d4f9eed7d42188276c8bff3fc30558bc096 GIT binary patch literal 1484 zcmc&z>r>QK7(OU0i-K|8(vgH&VRjf`&|@MK5!52LBDsWuRBG#KMTQBH8jA|pfwn;i zGOz=T+-!gqixn|0p$TGK&em8HFv&E?n8h+<7e~ORJU#sWfj)LV?9Msw`#$e;*^Nus zy({9Nj_AlTSv`~xMhGWF5F(X3rG!z!DG`)NrA!%NjBrK-BU0(6oG?x}CxR2H3{ydv zAY2e3h*YqsBuo-6iI7Ap(3AiPqv%Bux7EWa<&+9arLq`z#wcf0Fe()uC^Jqur-DM;#A1oH4M;#A1 zf^(@@358gUyAWI|&O$JFpe!VpiqVJ#Ily>04Qt^g%!6C72Y$c+D27Ck1{PR@CU}7e zHUk>i0K+ueQO5(0R5F8=P>992OC>_&kHC>IB1MJ>4JjcOW9QZy*a+S`Kn3n6_h>J-7@mNyEd^g-r71^;cY!KYu@I+b3+fyoZGWz z|JSCO;OvI`#>(rboSx1p(yMN^oepz4w7%aO;C#wA{O*@i7Y?_^Y4eUXcGQ^4s&{Ou z&A(Wl)A~em!hF%njbUwF>~wsHMYUk|NZv~dSFE~?pYEJo$}Z5HFY9$ntMZv#&e^9w z{%zH@$?ipM|5HC~^~`$HFm5g%Jv3Ne`I{lPFv57)o^HQB&=j{T(AB!wI}l@MmztO6 zzp1vo+7sx;M-uCbD$YEg)Ufz{T(O6(XmB8We@B18xrdqg9rG4#+hm^2`-}8;Ree?P znUtUx{dx)`KbyIHbLE+a))QXWGKM=3+*{X>6L3EN?>i@xJl5I9uUtWXo`%t4N6)cW zO4OQ}lv3BAz5}MUs(mTZil0vZYeecIcerJ?NVe#T|nIDQE%Jb&ZP!y9MBdYyZG4N zyPNd-g_p%xZFgesboWBp$;wdY-q69QRIi%6U%vXJDeJk2<*uK4TFUHtm%d&npQFz2 z8Ge2v(B5VBt=D&6u-vxPh1?GP;7?;}EwyDme!06Nz3E8Ez|>#I>+T5nOG9BBI2$iHe{`!}Q}%Okeuar_RG}X3ja^`7XQB zF}lDY<5IGeJSH=T62b`Kga|^Ua;KCqN;oBg5~-9aBa9Kwh+sr2-INo?3Fky`B9&n( z2or=0A_S2N7L|la!X*)sNClb_AYl}}DB?DA7^R$2L8(+0!L3uo4Qf7bdKB}QruQU1OwXW4*)$J5#N zw)kE#Lucl1LhPoAjh#l{@EXarYgBJCHyE|KvlcrU#v9V3Oe)WWX7dB1Zohk^>gN-y z3e6?tUgz>;^=eB<3CcI zG_hr$njZh^*1hqSj71l$FMWBzv2o+deddO-?t?z`)$)b@ksTHDDq^0Pgy-cNcZV?h z>;5e{)=k}U?p8X|VVa*8XLh}RuXfHvm(F$fst*TSg3@a)?rfSE?kt$o+4KC|o%tmj zmULzrhdkHjsEUkfP3=vOz8IX>+tbnZe9GKZe=?@Ir#z!K_)zMA)6VuW|9o}6VY8<4 z_=a7jl_O@i@Ra+D)+`Uab4dGk)Rf(4J0A2V?zT;TBWaJr#ntbBkm->WQRMvB>~vG! zwaJYUN%qaRb~sz~p3&aJCq_#`T*gLALoH86%fjyIZymFy(1{+gKT>2>-A9!UkU zRmJPZn@(FCd5P{xhUf^BUrzki}6(`xGPIumUg+P~zxA9eKZxb;+POX#zw zQ?>sjQ=2*vw)*oI$s9a>H7)hcgd)!zV$^Q^>FmveJDl4mhdixg7jI})E~alITzoS} z@_%qFGT6HnW|b$$Ub9V%uq$#-kEX@eAw$4**Np88#>_|b$+MRoEqlu=;CA`iY18em SBVE+a724os$HHxFNXXxA_PcTb literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/confused_sy.gif b/images/mood/moonsis/stars/yellow/confused_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a52be01285a76d615c71bf469668df10e9f5009 GIT binary patch literal 1626 zcmc&zYfzL`7(SRFs30h=vV+KS@d9Yb5n9GVQSO+d0viwzq8xV$EeyykC*`861}L%M zfnYGf3oOQ>RN~|WB%z!%NMSWKs8PmJM{@|7nobYj@BVjw?9Msw`#$e;*^P{j&<1Z> zL>7@TGI1y&j1W$UAVey6N(rNcQz9slN|`dk7~zZvMx@eBIbob|P6Q`X8K#0TLAW47 z5UF5MNth&D5+R9HpeX?oM$wBRZWD)5$|)6;N@X$bj8V?0U{oqRP-dKRP6ek@p@nWH zC>K-+DixL(W|DGAg``p;4G~}sn&1T@*o;-c1{kK%jyfK2IAek_sVKx^+&O20GpPs$ z50trJLNKZ52Q74S$%JH5u>)?w9{2$RpcoRN2_nE6G{Fl*uo=+61{kK%jyfK21m{w* z5(=>xcOke`oP}WUKv_sG6{8Uga)9x08rH%~mi0K+ueQO5(0@=N?5J~VRLy72h8HKFUn1D5)~UxVn{+ccXt24)+L1+y2Y754NUj3`u3*>%pg-=kxn zoyMnJo9)?E@nXXH@+k9(Xyg1D+w0H&$hxa%%(Jl{Z_QYJ+}gbOQuhY;Uhdp9YFhA# zdys=lTb};gAMP8DI5>IC-kCelX7cjNn{7w+;dP`X>1g2ZeQF2GK<#zkewNVcdgg}r zv!2eWCtjV?8Xw-~8`PdVXldJ%xa^I6&YPC*{;;@ZB+}DuTgXk-@rZ`R2e(p}B<*l9 zB^&b-4m@crip&k){6U!Zh`OOJ^5buIY0U`^O_v|0olQA+=T7JTxS*^4j~@jz^=ix3 z?ks-$Lf_f%bdU8_E%{jsP;k`567FztQT2(2!OPSi?l+vt`D3=RPs(Cu6n5a$r zo15>ur+JiRR;cqdlU~=U)B_&5rLW}QQ75_7#p_fiZH=LK+sUrImh!rxgDcfjQgw5? zy)(-^{kY~$Ro0EqHu^q!t-%x&2XtKaFiTNq=1`GIpy&ea1WwUwDYC)ej) zba7OowGQ~tXzMx(Y-jnT^t2oc&2lscfBO7zfwhCT*T#B7aaUW?oM`=Ri(_?B(%`_$ zzxbEccb3ebXMBIl@T%C#Ddz8Qjq8h#A9^W!lHt^|DpS~7heOm)4U5(pR9i>m8(HI( zLn_^>+m^mg&(m9~l5-22M+{D?Wj4DncQjgB6M8FB-&HM%ElJz`=j|174KV?^k>s8} zyRphpdfjVv%2-CknWBV@3qfBlzSr)0z5U@Wnvr@fKX7H+(f)@wzup=??M85K^3b3v z-sJta+4vJbefDaezP0VjSB{nU@21YY=T{#iZ7%-h++eCL=}#+cZX18v749AM>r_P1DEB*yUmbpg& literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/content_sy.gif b/images/mood/moonsis/stars/yellow/content_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6a38383512849b0775f2d34d96c5abc4dfa7b67 GIT binary patch literal 1170 zcmZ?wbhEHbRAJCyIKs~W0+tLC5)zu4n#sw@=hg~b+spC(`}6PbTfTn>qI=)}-~0bu z^Z$Q_|3FMSQ2fvB=Nc01>=@u`q-Vg)2sAUte-=(fD z6ZSPZ^zDdVZl_YzTVHdjHxE`#%R6+%z_*+?+?g#swj-{&f;CUgl(mFYzeGR2+`Ou~ zppK6rlVN`Itp5D=MEz!inf^`_xfm>0Zz^9G8Pcm4X9YxY=wG27g1_p#)dFgC`NTUX9cNN3x=>2b@`Ah*hZSFGFKnlL%&Px!Rg#^A)i zKqf93j|~eBHggDT#b~rN9ByY3aGLXCgTm2nHvO=a6)G&)g5f(N7+&uys9`cu*bWSd zrrPC}txnf}FKps+IrPAI(u59;^)G7}T28i1(OMll`BcWD#t(-wtQJ~GO?y{$XR+SG z3t6|{6fXYQH@he&&@`!;qng*MPPL(|vAnXa+PcfXxY8t%b4Giu#k5pDh8%{4bAt6P z*_uq+O(!i+&t$OWsWxHi*kBmX)xK|%Yb;wtY9m9n74sB_!?|%2J6KPFFq?a{g#{CnQ(i`s`-2AfRa(CO^gGwJ*Cw=y3axtm@bhkK>&7)Tf6bvUW zur{^}D5~{%7%rOFC7~O4=EsJG$NS}+u_lSTh_C=B35P`Pk9V#eFMMt#`o6(Iq~YM@ z4H-vN0~_QvW;m-QUTkiP%u(2|YkKY}-P>Fi+E>~Xrtj=Ej>=s%HPOdr(ZThb-sHP- zrqn_ZXtg&som^1kQ#dm*xpm2mV*g0?rAz9qGCQ0Yvyg%5Qtgq_)8{W=zkUDV$nyIS%h$gQ-%oOT6v#O?{+!eT_Ax73CK$1?Zw&xw C9M_Qm literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/dancing_sy.gif b/images/mood/moonsis/stars/yellow/dancing_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..f81ff014772cd1b07cb47b3656bb018b2e6edb1a GIT binary patch literal 2041 zcmc&zTToM16g@m5A%cULP(-R=N(G}1azv#%PMQc9MTL@}M8KeMl$U}=LDaEOAyJW+ zfL@dl1j@q%!8aox8WS{nb>ahwRILIkT3X-FvEFX(=ubcT+w+mkIeYK5*IIkuP+7># zpm<;8i{7E3gApPKQ3%lpG3*^P&f*Fg=hIEL-0~~e} z|A!xMX859Dd8G8m@Zf+c{&qG%!TW=~BOm@J4bd6;Oc3`ovf+BpYpp)_3wM- z=$ED*%bla_YaG8=i@%vJ_Y+<7XebJqot*W$dU39k-&GHu!g)!BV6slNFTGE(gFi0K z2fsNiOqGTfRIkqHj~3-zwcYpr#N?PG=?_{;W_3S2TZd>jBZ+UUttrkpnjp)6&aJh3 zGxmV>eN*LJr*T{3MpdSpc4>s`@(cc~yx-K~xV~{gI5u?Ejdoq*`|fz`l#^>C)%s;q zp0zjP$3E>d1_CczlDda2x?Zc(ACbL#1zEDmp{!r|~ir%k=R+{0PD5VnuL;`7BRu$?Loxo!+MCOf|yWr@4Lintg_9(>(qPo2;EoM**n-2pKzb<6Mo#_ z-FapD{-wgK_cuMVBkElgQ3WcY!w)fSJO@QKH#)s*_gND!=JSQvJyBX>3cNR3Zs693 z8P5rp_G%Ya&OUmZq^-NF^~uyuGjkTHN)t+Ba_?wsGm<3jk0m~mhQ7Qaw**wE`!s_b zO!4YnU2n(vxsMkkmp|n0dC5&C*6K^=#ztt0wNE2cB=T`vhnY5B+&2AE*8uOulO&7Y zn5>?tPU@N0yY;;5vO%#?-#UNCn0V=mEr~%XzXeA5tNXdH?z#^)bIhR$QXAERH4+=1 zC|u0$80SBB%-jm+V{1y-m^5re?>>M-Sx*oSc=n&-2lZ9d2WDeAbui zzAoD;vp!%#seV`Hq_~ch*MDtj;y)3WNxyZj+Oo%ILBP&XcY!skujc~)e6!5>{MtZZ zy@6EtF5}$ znha}Jqq}IzoS~H~IGxWCe`hV*={e9<6PHuB+QbvhK9!qPWS{Ts;%Q%eOJXe(M>vY? zU&gFyuL_jxjMQIKNO7Qgw?OD*&Ka>pXRx9C7CnmHU@d^XOKDN%ZCa*`uM~7wpR#a& z4Lkn5!z_N&eWC2_lZKG&k+Q~3npCrC;o7L~s<>R2=>GND+3f?8sU)*bd(c%aF40+o zR@Fu}Mfe?v4{kXd9Gp<-pIlm>%%4!T+0(XGpW!Kv~>vxQgkHnjg(yPI)&nKMVVro(Y6S1-1) HL9_k=rGR@( literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/dirty_sy.gif b/images/mood/moonsis/stars/yellow/dirty_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..d766e33a11d042f7de09077362c6c11e52cc56fc GIT binary patch literal 1817 zcmc&zX;YI|6ut<7ut*bDBhiLU8HiMQjRHzb1QHf?3W7u=DoburaEd7)>Y$)RgQP4f z%XLs$gi5Oz6|G9!0R;qo)l$Vqw9eRqLIrh3+G?xb9^OCDkG&s~x%Zs&oM%atQHsEz z6d&Y+{z6lSK?oy65MmLc+?`<%W)NWz%OJ{?8H_MS1S1wB%5^gYVS)%jEJ2hTW>|z- zL|DYKh;mpAMVKN&5la!}pcw>6Fbcg;gxl1?3_}=(Wf;mWhC9X#!3>KT%JG0QCJZ4A zOBl-0f^N(*gk@Nkp&UyX#*`tHVJSm7(jWp@15MxsL|`+l0&D<-X=sN!Jis9svlvrO zAuNVFA($nYa)N;elnIMj7E?|?(1LD4F-tM!>;SjG9`FMU0L35?G=T_U4K#rl5P{7A z4cGt%)6foec!0waLOClzAuNVF%M!{t3xa_MlvzqBXEekDIe_utG*}B>f_dN;*aLom z0iYNp0%^bk)<6?@0TI{?(0~nKFb(ZchX**6%M7dpg|Hazl#3AZhrl6Wh!iq}&>$s< z1#$r6!D+A-yaYRdB@BZfU;rovi9i~#fHlwrUO)sk12kX*7)(Pu)ZqaR_e=aAKHRD8 z%82+?Ve(HS0{rKjn*jy)Hx|}Q;afUIXX7H=~pOgLVXkS!}+U*m+MU0 zQ4-N&d!uH$`MZVr3o`20lwVezX>@Fj)XkB#g)W?|tnycD$GuDk$6~UA%?k?JTWlMR z<-uhdy@T66zhsr#?165=Ghp@XHGP#~Pm_;YO#C{%y{6Rlg8rUYT-cKVz9a}|OSYJP z@9ik~CvS4e_M0POmq5cjzn}b7O3mB05~*7(5!V)}YH$3Vc3oWcbDvJSSgEpiS#4mq zy9AA8n(i5UEDO5z;>5s1ofjTv$va%$kL0y~ocfmU7i6D5{yfO*b>{G%in+HNUatHz z{gwF!UWCgxYhLj(y7Ce)wO1(QzgSe|*d^tu?WGT`gu8>ryLvn|fma6BSF7bS5**!U z=+n;jD`w!-gyNghlNCbZ+1it@b`2;_7!3Ez+rnGhD(Vz!g9Uq&T>YF(2ct~kgFM5~ zM6rvNxMFTtrR7eiRjDn__tI0nB%i76y__xd{dXRKtPc2}@d+>y^MH;p!+<;|mwdYksqCWEET*zwBf=&|@OJ!T5H;CcTQ zygW;A#@%jszIy~Rx7-VUA0BGD=1(1~S@{ky$CSeKqFSX&l)PLN9; zYa1gD^O-#B_Ldk|zga1Z>@4nXkYuSRjUIP&%gaQo>l_T1awXkg6G zgZsDW4CRW`lI`KW*PCR?ZNnzhnWtAu7in^crpHF)koo+Pw>-C7?-!u0c=^n6#JMS_ zW5bSiV)yiRrg-c97&0$fr28--q3)tgEeTQ#_oZ~b7^)EapC%oa9_q`2XT48i-du>v z5^H^W^QN!Od}30Fk2G8@yw+w4^Y}Jn*Bs3h0P`91(`@~rJA3QD3wOrL%l>0#LW3m(7iu@5Pa~smE z{Zr0OvkGSS)^C2*zi@bFiLvikqFHulQQCRUHRl4ajFR+?f~wHEnz$bhRY!RjOjae) zciwlDMWaFoiMz&m{o!5reY}qCdT;G;WG)Ya*U$NSw9#-&WopvNq6NnfDTXqdYol#Y NOZBG98KDR*`4{kw{%imM literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/drunk_sy.gif b/images/mood/moonsis/stars/yellow/drunk_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce7273591de2669fbddae48499900b6f1c10034f GIT binary patch literal 1671 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 C2>%cO literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/exhausted_sy.gif b/images/mood/moonsis/stars/yellow/exhausted_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad88d564fd093716b2d699d6eba42f657d5cbf3e GIT binary patch literal 1542 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 WSn$tZjaNJTZ+G~WvH!)#VcnlY_gYE- literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/happy_sy.gif b/images/mood/moonsis/stars/yellow/happy_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..00fbf834e68fcbbf4b061baa57a24e2bef695ffe GIT binary patch literal 2219 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/indescribable_sy.gif b/images/mood/moonsis/stars/yellow/indescribable_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9ec1c5f90dfbc87e2db32eebd6c678475ec96fbe GIT binary patch literal 559 zcmZ?wbhEHb)L_tHxXb_smJFZ2-TnWE;q#}aD?50SlanA8BZ#p|=XSrs1i z#wRK%c`~&s%vpJBqn@M4#x)n4Y8UU~J#cmN%pyn6jEK*IY%Qq*DOy(RmoagjOcdn^ zyM4)ABBfFJTId^=38#-=Er0v%>gj?xHT$;R{$QXLSDWKsnbD*co?6=07#y0y5Ky1i z5$sYixnf#Or%P=m`@Bru#NLJ~PoG4;IjgMJ*hQ+%Nn1Q4OpP&QYr~RQzkUXeeQ5`r z-1@zavKE}MJ{v865E^8y|DA`!R|es;#W({xhty+^y_2m%UhCa zYTH>#U7PZHmDB8EbEi~Ii-@Y^VW^zyt`^8uxp>JuRU6yVin;84@}?bg=5Cb>j1OM3 zTh}Z&QGZF*mWUvGR>sI*vn|`CWM)T>i=~|cHc)b7c f@zZBvwr}6RzyI<3hw-2PfB!IUabNGk!e9*m){^z& literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/index.html b/images/mood/moonsis/stars/yellow/index.html new file mode 100644 index 0000000..3b02a8f --- /dev/null +++ b/images/mood/moonsis/stars/yellow/index.html @@ -0,0 +1,82 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
achy_sy.gif
angelic_sy.gif
angry_sy.gif
artistic_sy.gif
awake_sy.gif
blank_sy.gif
bored_sy.gif
cold_sy.gif
confused_sy.gif
content_sy.gif
dancing_sy.gif
dirty_sy.gif
drunk_sy.gif
emberassed_sy.gif
envious_sy.gif
exhausted_sy.gif
festive_sy.gif
full_sy.gif
grumpy_sy.gif
happy_sy.gif
horny_sy.gif
hot_sy.gif
hungry_sy.gif
hyper_sy.gif
indescribable_sy.gif
indifferent_sy.gif
loved_sy.gif
mellow_sy.gif
mischivious_sy.gif
nerdy_sy.gif
pensive_sy.gif
sad_sy.gif
sexy_sy.gif
sick_sy.gif
silly_sy.gif
singing_sy.gif
sleepy_sy.gif
sore_sy.gif
stressed_sy.gif
thirsty_sy.gif
working_sy.gif
diff --git a/images/mood/moonsis/stars/yellow/indifferent_sy.gif b/images/mood/moonsis/stars/yellow/indifferent_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ef1abdb9cdd4604b4ed2ba4823aafe40d667419 GIT binary patch literal 577 zcmZ?wbhEHbRAJCy*v!iS0+tLC5)zu4n#sw@*Y*;!@$d+15yJrmVxELhLfJF_gcI@Yy87OJ;))E z>*0;597W4k9aCxxJn+%f-4I4TaVE+V%cC4EYS5E$LBm^$OLKQ~M27 zSveRqrpzhMnBi2tWWj_wr^+HV=H*7SLOhad*2%3b_g+#PxIH3mDeKxjacYb~YP+_I zb$Pe)&N)$hO0v%U7@8ynXln!^cmCEMLE|y#M~| z>zm*I-v0Y>_Ou`)$kVK7o_+@N^zQ!&6^tqhWey9up3Pj!v1!{nR^_(93tvl~TZQ#A zbv)$T8M{8@h~$Kwt&N;YE0Zi=2(QrEP@zBd;7-XxCnaBw;#HZ;=CHa| z1H$RyR*Pa&rw_lspx-(lb~E$7@AE##uCJfk&E4os zoXI;fb|@i?5Kf37L@IYm38RElA}EncnKHr{;fx4Iq|!|}VVrPI1Se7%rh+g*xFA9h zsbEn_m?T^hA&FF=DFG5j(TgH(V~0`7DHW7TWijrIQO>AfR4P1BW}I?P1*cM>g>EJ& z7gPu;6_yxgl5$Cfq*5Ub5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD8ypiIcI`1sR#xS zl(}F+FsbMVEp&6qgk(~&18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY=Tfl} z3b7b>A-GhWg<$YNSx7DwqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR1~jk% zhH12;jt3m6WCkmt5Q}k_N`%NCfg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`IhD4AC z7FdHOc!3Bu0~*)>!!+7a#{-V?OZ*=`9OR@xpAfB=N05)p(&c6*px`h%&e8+li^u4U z{Y{9)M`B`OzoFs8^}QA|7H)ML4sq6+2K;m(@j&IR%*vNHbKA_<*Q#bY7@A@icGsvr z^{DVp*;ehNnmbhQ{e@-q#_ZIsWu2XE>ikf0O^U)L>Kl`-+d+j6~2{^I&wi$hxx zOnBpc(}x$A=0*;dZ|JOQ&sVPrw%XFKZTfQd3`0?DVo0mkMg8vTkxjfg$3oSvI{8(1 zU9Nk5T2@(qpLa`7)12#-2~WCCUr2C$6}#Iu{z}yx-R{wXs9P7Uhq5nkej6X()8PKi zv9*`FpIIF}cHZIg(KS1NEZOJT+M?>%G1PF^Jn-+UACpIae|6^GRol^=+Iy$=PuAyG zyYhs)woVTt_jZkROfCjHcdqWpCI^U*%vt+wk^ zb2=w(3MhNx+4ovq5w@)T{lh#F-qK_AD%n-F$NR6DcIg|O>Yf(*yZRlm4pQ636b0)R z#1!gSiestXb0E6V#AGb5@&75W0kZ-JkNBAv9IayJ2ikv5JRjsH&M)@K=ylujD9E$Q zLtE+kz}8YzT>2>`hMFos87zLVLU0PWA^^Z*yPx zrsGD&X;ZJzmHN-71ZMZLy0oVDE=>ao3~2TXF1nEycm6v~Q}$5RwEW@e^E57p!?R|F z{t!91d2&?Eq9yg$oExmW0!~b?X&R1Q!LQ}dHb$u;voxjaqQ1TS{o@t=U59=14cfjY zZRRl@=z zbKhoNWX#5)PeS##-Hx{oyy;(drd4+(ec+GR`GesvzwR9V)84;yuEsCC&Dzj=q@iN` zF2AxeU9Zvm=cLKctGf+HD%vyB3PW@5>l4mJ6LrD8#@(W9kJzk$wsqr<|aY9scOgCc@gQEaiv{*{9Om076qvnJSz^-#W|MfqU%mshwd1N TDGg3v@Vq!OGv!nfl2iQ)SpwD- literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/mellow_sy.gif b/images/mood/moonsis/stars/yellow/mellow_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..22c1bc298cac362483e33239126a3986983b14c9 GIT binary patch literal 1514 zcmc(e|4-Fb7{?D9NLt1!0vZDer$kU9l`v(5F~S)Uj7TM$a>6*_oCr>&QcMM5 zf^b2EAX3qyk}yfQBtjCYNK*nOlp+^F+{}kj$|)6;N~JOGj8V?0U{oqT5N4cmP6ek@ zv4w0VC>K-+DixO~W|DGAg``q3jUnI~HsK3K&>5|u4KY+B9dSJ1aK;245sCJX`BunAuum^w#X`ls5zymGd0S^Gc#268#p#|5l312XR z&X9&S#88cN#PNV5m7M`4CPZW0rLsco9}CBZu~O_1OT(717VH7wK^kbm5;))z#oz$| zm>46%G_>FvHsK3K&>7Ouh8U`mjyN80lwaci@ZlskL}?S^-wTY<`n=`6)&drsp1ts5 zAilSo?U?^2#QHh0uyzRTZ0swse$_pBu(RoUnT>OJeP~y+w%Fv8_T!+9{kjbf;W;z< zk>A_1w}n-@B-(skns|AuajLVXE#S;}T1{a_sy6bxDdk48^JxE_FEu5HBU)!wqan^) zUE69Gokd7wc}G~QUB;bCmA|gQb}4o<*Xw;B`ZaroR@?Xwecm14B7*YAySMb6U=v-L zJ-^-FUEnp?vVI_~C}E$a??&up^PG1-wA8UMOaBY>H?SX?$C2E%C6sF0);#9UZ&aFvnVPS@B`CpI&b8Nc& z>YrAXSZ;K6iEGuLy55ucT3FVE$;@_qZ11#pO>6&Y$1UdyGo}I}zFOCH`N1JrB`P@NiZaY%7axqN9hy@1J!mzp5UO z+U}mcP^bU2+QX~-=u=J55wD@)-9=5qv+kZTn&XB;tD_64p@dI6umn!Sm6V`8Dm@IzDSAl%c3^}V5kVB`6HTi=nW%l9v_y9uo F{0n}xj9vf$ literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/mischivious_sy.gif b/images/mood/moonsis/stars/yellow/mischivious_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe17a2d247ed1830c7891f263f1fc14fa3290fef GIT binary patch literal 1742 zcmc&zX-||_6uu)+5DSh0iP8Z^7C{!Zyntg0$|4Nl(s9YKuZ0&7LMb{?>XJ%Pk$`k? zpkA>A8H*cZz=f7B7J^o+S7i(WE@_|w+B8^-OKqF>_Tl{j{o4CsCik9mp7Sg->bMxy z$}At^Lw+YSM<7Hbgc8CC;nH0Yh$s*$5GD{Vl?9QABB3H-BH>cEK#52RrG!z!rD1^) zkrB!WV}wgs0w*FTloQ4Ym!Jg#B#fdLMcihNC_UzG47%$P*Gr_z$G3ii&UUg zU{v4|Ep&@apiE#);1Wv=i(H^wU|ir5X@~%8&;&0K!Dg%iHo!2AcGU5JLq(B^B9|0m zG47O#jEYKE!YD;U;q?DA~Zn+Sc4{bfe1DO8rT5C zG}=+e0}i8VnGft9!|qrcnS017VLo^FaU}n5u||y z)}RSqAcD<+1~$Mjjds-WfWxKCU?mh{G45Q75cwl;B#cOrAwok+hy^*ocsLDf;U(+< zOANyg7y!kP2-3g;YtRHQ5W!|Z0~=tNMmy?wz>$85|HH>3K4(Mpmd#NSn&`l#%PnM} zu;>rV*@5`>pP@7JHz79v5Sfi4w!OLMV;cwGR8pkPouRBzdt1NO7(^8&ST7=XJ1!q%l^n7j%to2uPJ8gNY zDZ1FQD*18jSiE6_l~&QbS=$nv;a0P=LZ7WAj#0OdISx1DCfP z$_Y<)?>glcxi51pBV$*6R!ZD(n?{*u?Y{k1{6G>}v)3)IPnI*^x58Dfu+$8xhYj+( z+vaAC&HB*W^+j4)g56Y$y3fV2&(`ndP`Pqw?6i?AFm>DdMc5uv>K82O>JQdx1`J26 zX`WSWKzrnPH-1!x~TV~-| zme*9)G~4HRp6^1rl&{r)=G)hPqW7TOBi^9O{OPJ}et>;@w!BeYWc7BkWoB-;vV2&T zIHH;58CSh9xY+S%>EPvh&+s?OS8h_?F${@e$-OeqJ540heq?!});+k^zfDs$@PrhF z>_5M7tL&j!?`9pe=g-sCMzx1)){A_z@rTx0g(>cm?%81dru&iW3P$z)7or|Flv(O- zRrdO&JR6rEWyV_FYWuLz@+kASd#s0Cs`3lpyHvSs_1N0i9b>_jtFn#9hsX2l_jRQ8 zI_(O{y;Wihg#(c*idK^sfW_DSp03LRcLt9`9hpY4!$WV>khnL6rZ z#io;wcD$MN!HCD!Pky+I=!*XYCd7SC3~m=}j6P n|1{&()vAh=!`2ft^Oa+tA-|KhM&J5b)!LYzz9c7{kazwCLB`!? literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/nerdy_sy.gif b/images/mood/moonsis/stars/yellow/nerdy_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2cf901a65b8929d5956b7dbe3432cbc50b578d3 GIT binary patch literal 1518 zcmc(e{ZG?Z6vi)O0#0ScL79lWq_R{ToAkyC4qQ=6DMTFD87Yhj!3zeWd&9`kxloWQ zYJm;6i^fP-BQL@rZpt={0p}*&bq*oWIJba;E;GY0r_-41?&o6UGVWL~tUN zVk!s|gbN}Bk%|_Tgh|3B5t2wnni43X6uAiE<~@v3PN|?&DvfbxjB-W=qf+sKFyoYS zDmayjEo3u6xu8N&sklTjlaxy;B$bM33<1}$312XR&S(W~h@l$kh~oi=GbR|5%7kc) zJLgPrCY6EV17R+h5KJob!xpl+WI{5j-~cV)0S^Gc#267XVFe zluy}zx^=oN%6xEXuIgxQ?wN?L$)2W@2FG|&Q)O|Xas3g`mhbX4BZF5DgxLx*UAKcq zOqz(8lb_CNglYZ$ZnG<-`0Bx+Wb3Zr``L@Q-LC&7(HWQCs7iM4PJN+Wr0)Fr@PvWR zc+Plkch3#qyj*`i$`Kn}zw)g`rX2r~=E`07#(N?)Z(h_V+-kX^3B2%nf5NiD!Pb)z z`UMXs(;X=fy2lo;p1Rxjc}YxjSEJ2+)D?QOzoVi%FK|uV*Q3iSbS38_ZL8*6kF=$o z`r=7Wa{IpJPRGQyY)4;GeA|S>ucNwV`^O!*rmY_~e1EoRPu?F3ee=#9>iyPq?ppK1 z#to*emdL%9Z5C^pe&ufyHdUIvAtZRy=2n}Ul}4MxcJ@WrMdWB(jXpkJ$aDS+a!R?X zH}Tk`2HTv#n58)``=N_p=7yR}Z+N_H$H$Uxu4r-%9*$hnTvu}erHyLhth6gq6#qYa=@4kD*9;A-<+cPu} zJKVnGs&nhmaOZ~dmBGnQW;K07=Wv^TMB zI^(^21>ys_^Vikcw+hlMh_$(rEp#g}TIw?-H43om%Ir7mi1 OfU_>-nGh8rulx(~)rNuq literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/pensive_sy.gif b/images/mood/moonsis/stars/yellow/pensive_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..521f7d1372e76d17ac1c198d2f00841400d2afc6 GIT binary patch literal 2323 zcmeHH`&Z0q7=OD^q0Tg#QB+ihQ5{EKIWE~FU1oCaP7@t7^2$z@r4r#pX(mdAYTuMY zxsB#$<~(TWu+;wWmZbn|oMxefR1653C>doc(3rA7;+`eV*s@d@l1HS%CkX zxk@RLqW5U{V1x)l6d{HX$KNqV1S5(O!-(U{m>@zBC5REk@!gmrLJ_5iQN;1Xm?6Rt zWr#7v@mQEcghP}=j6)m`jS(QhDD*-RZo`LQOfhB{bNphs6M`whj9`xE0cAolrI=C7 z@wA|uFiaU{40Ak77$zL19A+Hmc+wyOSOZPq1w>#otO9HRgK21oIy`_w31NhAyh2zE zcS;GPgyRJR4=7Vc7$Y37A80{0l$J+sJfj!^{7yybvB4`2;z#3=*FCYS&0UEFY z45pzS>hJ&#qm<*V1ck5|?u=26cNPQ#4=6K^a=g(H3*-RCgVSIwcnRi#TVN0P0S16# zkO-s!3s?h9-~~irGe842fWb7hLmeK#;rPtJN>B)k;m+|9LjDjqBn**4h7cO01hGI4 zU_3Yt)`FK{2e5=;@B<70#UK$#0~W9bn!pQ)z-E93Yyg94XoosHfW!Y1|AP-FZuD}$ z&=4Q*K);#OXP6iP1*bnuExh2{eVEShYl6%_BO`NrdDV%A6!WpJtDCBv>NMTs7yD{6 zQ$|=xoR{~QpXjTN7#9$uSM7hWC{|3?M847b__}pf=FZyD`oLYb-Z5fMvgMhj1)du$ zcI$7nHRj{J38|&Q;l-XSCT1p@29-2x#2c(L&k?s<2gTuD{j1upxl}}J`$8k*TC~<; z4@G=agIicmq^>vqQ(nrgOlhakp(kMry|6jUxb9-uvSLlv*2=vZA5{L;84;?>X@fZr zTDk?F>UVi!U&C41s^bUm8V_hnmDeQ|Hpg1k+HLPeWuYfz5sHXW`R58!y6;QF@)|5& zS=+UVR~-qn`_o$4xBK)8{qB~HK~>`TC{5?{Ess}PjjW1df8~<_eYC&YP^a3hdOc?T zc^!)O@{X0HnvL5tRcT^sW|R@u>NC_FHo~PoE+yLHbVr4);ENnTd0iuLSzIXBIs3)h>Za*cjm{|6-hGSoaKZF{WG2w z$b}N4EjEcW*ZV;REj#sTKFtNL8!E5V9bqn`-DVjNNd?Dl7pW5!AIe^ueb_eaoL6*luqC@o zVCKy(o%cICZ^!7(gVvLSO0zB>5?FjBw`B=~sxiOsc>1C`X5xZJ^&eDAJim4b)mcvK zdFOjJ`Bv(z8R60KUFQdiN2(m}je5WH@)EiNR+iun#w3@icK#a5_ zL^dMD6}iyGCw3lbX;&)!uh%Z6Sbc^?Jj$^$Sz!73Xh6-R zx`;c91zYtYvi5yed!y8&*7k+O)Wl6`pWBzS^1FoZZ^)l|wet!wm^bfPmUjPXhjGu( z`CXF~HLGd|e(F*TZMs=o{^JF870oS=e6M!McB-sTQfzBWFPbn=e<>&BP)GEFb&d@} zIeK($?$hj{OP`({O4?u8RVccbv^}r8v7}J)?3a?_7r!Mve;mBaaI9Kb=24!+Z7+Xk z_x7l#QkM`B)ZCJPKcFVrFMmy7hUv}# literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/sad_sy.gif b/images/mood/moonsis/stars/yellow/sad_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..7048e783ec7848c92e8bd0cc2efd66ab7b4e39b9 GIT binary patch literal 1558 zcmc&z>rc~H7(TdxEG49%Ttuuig{3;LoY;Z$(hB8PMc9f0QzIRmp=dS+G7&YCiYuZN z*kl}Fn-?(Rs1s2aaf=bixa1%bopgp}Toz?)*@9+qewb$uzkgsKcRsW^=Y8MjeJ*W$ zVq8>omY(RzGct21A&d}Ch#*8NcS;GPgi|6YkxH2|!WiL<2u7sRO*vtla83j#QW>U# zFhRH=LJ+B7QAwC2ToNIPRG=vV5=POBB5pH>QOYS5luBhW?u=2+s9;noJWytwa!v)O zQlW)zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}r zf-|WI1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+ME za0KU4u@VZg7?j`BP0A>J>Dhj(bg<%Dx&v`5_*-S~Hv-P1QB{LLoE$*yY|L5aB| zZgoRh#_)qR<11>KIx810I8~fIX0&`ZyKUg%^W2l?Dqhc@<+$*)zBM+lYF)^*L!ayj zeD^QwMRu{jB5;dw#68rhYss$9+;`OV*x?tr((6#)?ThJOE>5f6UJ$s{Qn}-hAuXC# zhcvsVDoOv)c)BCMq1IKhQn$4$t!?{j^S693+8%np+n+`yBOIn=n=u%z94;gcjwRP5#HC&R8_Hy<^4)VH2ar z!};X6aoC~PmM=TJKgAJZn5$L-@cgd;x;|Fxk{T1*&YDZzk+z$?>iM%(p-Fpwaon9~ z%?nFB5uP!VM7zc{cDbh6=p44y6lZ6dH`Tg#e!oq3uXFHth<%5p>5<>Pc%3Gqxo%n~ z;y0CFN^AXN=oJBT^YG1d*xlViF)4rmCOjmAs$DusyAMW>jVG4KiGB$p1R-n^VQ0r>XQ$P(uW|K+$ccJCrMSSe`2M3gmp&gb^&F{pj}!!JZZ*Z67)by5!uHGG9&Mn9;+7yzwuX C5}M`! literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/sexy_sy.gif b/images/mood/moonsis/stars/yellow/sexy_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4e91b5c6777504b6661c3f61149e6590201b979 GIT binary patch literal 1653 zcmc&zYfzL`7(Ppoc!5BLm79bZ!%Y#78lo1gunU9+N-By9xqH+=5oaRCDMyn6;wE6| z!BDoq!9ZQq2rsD!;_cu7mb-Wv2bT;>2XvBhMms%x|NGtfu{-Cy@B6&ZWmgxg4V#r$kU9l`>_7F~S)Uj7X)Ma>6*_oCr>&GE44KPfj9d$h5aK;29cgkVz94_fHvk_pMAVh7xUJ@5ktKrtjj6GVVDXo44rU^AeB4KPfj9d$h52+pNq zB@|*Y?m}>>I19nxfwGWXDn=s~M;#A1QppTfLLnC8E|mz8KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4Pz;G6 z4J@z*P4EH{Yz8#20fuR`qmBn0<(K$BeE7(*i=&g4E{sfwo;iKSYbsFid0{)+AK$?v zbVmLr#QqmI(TJNwRrKd1`OZo1#h`vZ7_caH~<59yatic4)mQQ%~F-IV-5F zO6R&P*br#yC@J&`Pf1Gs^R|0!z>iz)60B1i#yDrE)Q67ku8Jy|T%6OMc;s@kbNGs` z?ns?&ZOq_-Mf_vmo9<4*<9@2Q+T`jC&yMxX;KEYI|P_IU2Jr5S3o<+G@ViJKcdo)0^Ax_HE$ySn_~rECX}L35D#qfc*S zIb@bxKXEYq{^q`cdxIXU3%!p$y&ar<*4m)HcXRHI?|Pg=%-7bedvSXIk!2}v=H!Tj zI?LTW%cjz>@!lEMw{nVu3+zX&jC(fQ)tH!X)L+mREy$_S*tqX4&#^S_NXzu~n_6ub zu^}wss~}CwEp5aWryc9;HYM4_y^Ox%T(EF>eScYu-{Jo9_&JaID-yOEF6~KL*{A<{ z#o|-?%9NQ`>nanEtDTg{?B@S>WPvGHOvbi6C*QblVwxVbhfF#@uD!!~fAr3^rWU7U zKaFiMF=d%97;|-nYvVthItMX*4*Tp`liz=Euy{l-8aYL?~E9=~L^2=TC7ep3U zolR}6Rad7wEjVs^5YS$)*|?^@+pcWMq4;SzuTHn=^BnzL{1??eOmx$gYUlsnQkmvZ z(HIzI3C-^GJ!$AV-hb_B!>Y02;RE?Y`SFHBCF4siqNlE{#`XKEpR-gpx|3cGnUh;v zAN}T4+oq|>`1@#DTfXTC>s6=O+H2l8)^~lD^Zj3f&TRj{v?Q!K-7@1{bLT0;;1_|@ zW;|)BnwQ?;a-w+cDlh%>&3|||1ymc(E!b8Vc&xg3`~L9ve(kGxN2A{tw)KahYQrQq zuTaB*^ofT*DRwWI)ZDY{$$SkB4Y9vjSliL8#Uccm3No= zHh1(Ej5b`ctn@7N@5}Wv?z8IV4-Z&NBVLc)?GojhtlzEm+o&&%n{#Sv#p3Y+`cjpO G%=;Id-^D2a literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/sick_sy.gif b/images/mood/moonsis/stars/yellow/sick_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..73d5040ad23bf6b03b616ea5b9628cd26bdef34c GIT binary patch literal 1826 zcmc&zX;4#F6uuO&p$-bQK?077K@B0;P9C6uWn@VZL_|PIA|fR4Kmvm(tw^OxgGg9| zV#^ETj2H-8Py|^zPG>5D6}VWC#n3ty6d_uzilAeyz8>E1{_p*f%)RHF?|e%V6fEB2 z70*LF^ad>+0wEG13L%UT&D;qBkp!X$gb745Wr9Q`i6|0b646XIK_QYt6ooK_Xl9te zh{TA(2xCMuSOkqo8c{UDG@==30s#_?LN65Iws=T_pa=pJ1kEglJ4q50Nnnzo86Hq3 zDT1O1Oc69g3%W^6P?*4&pc$4hOwt5J6PPAwhBSx()<6?@0TI{?s{k9oU>e$?4i9iB zlEfrQGYVlb+$oC06iG9Jfd`Z+OkzyZjDDa6-4sn?nxq*!z%8%``~U+$F-QbWAOcte zP2dGYU^74iHh{r2v_l;p;9!cP87n~{EQUMA6wNpbf`JE=F-_5o(GUyd0LFvUU@dqF z=7C#a5BLEFfMSpcqyY<915MxsL|`*O12%xcG_*q<9^lYSW?&^KgvD^DnFt|&2pkfI zNFhTA4N`(wAO|oWoCa&bORxi2!Z7#&27qFa2&4fESOZPq1w>#oKm#^_!8Ei(9UkB? zzr_FH!--xRCW?v-@Cz3SH+^Al1{9p$T3GqPw_uUZ;@YOk}C;`qgfh-Kx~YVD?U>?_vLQbeYoZ4>Yjeh-PlhI zSrIb^rF&Xyri-m&SAbD~wF}ACr_TvQc0X-s;_8}=TVfO;Gv$`-a7Q(M{6gy?jplG< zc}sqe&?~hviPXdoYhBt9D{7pZ)m=KVrX;IoZbp(n?of^Ur)C`jGq{^~_QcN=RutFp zN2|uVbyBtSQMZQ$^IF?_)uo=IAp_QzjoO4+?MsXtFgg*kuI#l7c# zG`)Dt>vigH%1_zi*dw*=C9Mt~Wkt^%Iy_3ppJx7&f30;$Y}j|eXX3c`lgEvhQ*J9u z-eYN(YI0Nhlu#!siHWw8@!seC@$I{X&O7U<+D?s!ubX96LcMeeJAHWudEFzoJl>J> zkKdz7@@ep`{b}Ew>x?*QvtM^!p*iL;63XJ=dJv%g(Q+T>97l7f*eTz_R%W#5SYl(R zL2OUgp&I!Pj=yA@V0|GAEO@*H{rZb=-P?09kn@CTh>FQ|<0@ z|EPuea>2?+3FUhPy>pSflcZ;pvhCHGmEypLx{-^YOQ%e_GGT~KO@)7da&4t7`=Guw zBU-+*yt~Bs@LfH3hw&K zAI9aHTcs8YV|@f^F)c{|lBGB$O4{%O(%mCCx^^Uh9VZM)jl^rayeF_ ztLYk;^xdIfV6|^)em^Mn8NMHsQrh{K)rd<_LwSbc+V|2onW@cQSvNaa^GB3zx@Q}g zPspapnKVVf)nISoS94W^M?M_C`L3^e?Lh3S!4p0@QNH`Sd(l_IYa^xCp1pSbxM*s6 z)y~bso<$ysaUCnI2HZ|XiVsKwMt7^4I~>2RI+(mB=Iumgv|RAA&OX%q{?Qdu)x`K2 zv)uOSs{AL`KS&c3lizT*yPC3A7k}yNsfe&cFCUx;WcT^0xxEGQ?b{C7AVuUJ=V&Xz z+xf|y$-Z8RC}+L%K=HcsyoagF^bNy)iQXn-j;EA6tMH7^ObXv+#pXrj*`=7O3pO;G jE*7s&>D6gu!^wW-d;d1oAW5T(o=V}n)Rio;KtBHh>zf@* literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/silly_sy.gif b/images/mood/moonsis/stars/yellow/silly_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..33dd4fd955ca16abd878aedf794fe8b5350d90c3 GIT binary patch literal 739 zcmZ?wbhEHb)L_tHxWWJe|NsAIuw?lA@Av0#cmMxk`24Bq@89=VcJTcA_V7Og!~OgB zlarG*H8mw9Bn})n@a@O#9}l#_`iLSF|8x7fh6Fo12DlpO889;fH7WjN;nZN@XV3u| z0CENc>;DJJeJPpqGNPDrUhi9@W$%!1zj4uf8-vBBcY57Je$;6zuDfBal4{1hBX|EqhfR|7&utg&7ZuEgHLCv ze>2PBUGw+aB~C9jXE@B#*1w8v5eM)7Q<{g)x9VMA};=rypUn6GC^i6$hrp3e^I-^#sCNRxxzQK)?lO6qpY@6Tx(cJRlJiBYV z+*U~@e1W%W9Wd|;bk3LfGFPm7zk`?MK!Ss#jufN$!V4!t6jJR|H&oW_TXactYesJ3 z=EJ(zzp|P$o{?LfV;8hrqwHHvT=UfTU$`b{Y~E>ArCGyX=V-&gYUy6h&Ru88Hp#w| zm6d}d!=(Tif~{Uw)4D9C&ET8mSIynOaIxUx#mg;{wXB>N1Oztj;aH)RF=t!*E;fcq zlb3PudK@%}IDW#4ZPQHtbK&hLZco~H?MBM2Ni&}8J#*bK(Bd%%lf~0hX9E~7Za%;_ zW0Td(FHiO>Gkj1qV0{~DA2O$a!=>~@0$=p@29C|Fu4j#Eg(w2qT0OA_$Snol?Rm;gkqUq*A7gFh)2df)S~7Q%)EsoD;!`REDV_Ob{-J z5JW0iR1zi$mqbV+6=+I;gi-XOh}*1~Le#?ojmkBjc!so%e+BB|lgy8EHY4Na-bGB1rh8<<~Q5c@~t zg*`*B8}1#s)0_X7N7d7MU2~83_>L#K{Jqyp)}{BQ3}!T*-?cPqcuZ(-%rU#uc_S`y zukPLDANV>JIp}{d8Mnpfersi&^`lW;kU97KhrdQH)s#NZoch^7WR%A)gDEZ5SQ>s< zU8m~K@on2&9OxIdI6gOEu>OlY&FDyc{;3YtR*e$KVp3H5d+JWQ-fny+_+gLc^s;$ZE7iX}yR37LnReXq&7w6kJzb3H z2``VXFZ7>r(95v*!V_JR^RZTsH@&N~?XPStFz(d1>)c%vzX_V{arBJa4(-@Y_DY{` zzbV4&@YBJ-JbTw0i{0C9x$g-wrSI_Sa*%9*QS#y~=D6OkXbLd{%mR!H+<2m>LNxl{H!mjVn zfbzpFji!*^ZAA+^n+o=(wz+2*&s{laE+gSd!zOFvWQ|!DmSsD$ZCj$5RBOqXAD_@q yb=$S1Ym0rH`K3X1t<-YHt7^bm literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/sleepy_sy.gif b/images/mood/moonsis/stars/yellow/sleepy_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ddf84ba01d6c28e0ea713b35246ad5e5c8e0abdd GIT binary patch literal 1598 zcmc&z>rc~H7(PzWBD0gLy0HN*GpJygMxu}z(M1iss1h;_~ya3BYK}A|H zO5Cx=SP;Yv6cA9+8Ij5eJJSqMOwbryBswqAVKV17&mMk%z`pK$Xmif{zR&wyTI13s z5s~S^B$)g`#ttQf5yA-(gh=I1DPfdwN(3cRDN{xmBb*Vzh*Y{MCyW!$iQq&k!&DF^ z2p2>MA{8tu36q3NA|#OtG$la7D0)%EZR{{gIi-S9sVv5wG0GVgj7o(E%8XOaso+#9 zw9w52<$?-9rNR=!Oj0hXkW?z9Ap)#H6TCnKo3RSm0K+ueQO5%gXG}0A6@^%gJLgPr zCKbWpfif3N2qqQ%poMNOnUG8>cEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ueQO5(0 z;9M$JLLnC8E(Di~vk(j(C=1D@Vl-kw4lo{0!&-O=^WYZjfgdmciXjoCfd$r}30@$A z&430rz%Y$=)bW5LmCRrz6k;*%Qi%}xBXA^)NRc5zLrRDRIly>04Qt^g>;Ov)!w(n$ z#gGWnzyfQ~1TPT5WUh9Weu@9XN1$|%k6pFWpi7LMJ11=XI8X@u)5UEW zzC*_7jQvfB>Ma?k@-sD^=-jRHnw8qqG^|tm25ibTeKNdwmuKj^!t5~|TkJnSzc4E- zsM~gDMTXagM2qf-x_N0xvuBLcJ}ollZoOBXo}W7t8HD*d^oOla3EUmlJC@3S!UM_>dHkuF zN&3Q8@2Bq@i$0v5KTo4^`s7XREqqng7+3f8$`v1ZWV$$e7KNrgKfuopU(v28@SVLa zY<>8V!GMm2D9!TD>cOn;QogNsph9Q#vF@;DcUgDmRPj}9n{WAT@e9!TlJ*nljxVSP zKBh^m{rsn*%6ON%?_{=^PK|6mnKF5c`@Ij=C6}3_%`b1H7=AeO_QmpjH}lT>7Zp9u zyqZe%Q|~7nZak=3d_E<)IKD0PyD6W(ee9i{;NmWr4+uPv4HZ)au3D1o^CS0LU!o%*g)cWqo|M018- z?dl)pSMO01Yn%Gs&c9V@Cv}GcKF(OX->T6co}-H2-)N$PSWPi%?KeRcGxabJgRyVLXOk5zuh zXKZp-J*iooeIY8fJ}$NHZ@&^UZR<;Wr@j4n zNk?S1I!axsawkIxBR4jDU-x{peqgS{Yx_U!a>qH>`ur62H(xmlW1kq^j_{3dE*4Y` zUW_U$=)c(YSHtyWvth#3TZx;8+$K)fT%BC9+%4~y326ztpM7CBPg(O~XpdXEL7y7l x*xom(E$>d?vV{)Qy|R$@M-L8!A&c^PeJYDJ;&xAlE&8_$mI~S(JeI|Re*uq>rvm^0 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/sore_sy.gif b/images/mood/moonsis/stars/yellow/sore_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..862344398a627c2405609a744da42c7a57973f74 GIT binary patch literal 1664 zcmc&zYgCj)7#<8<5V@E_f(U|wkYVM-%}a&AE~1d)bpcl)7?Bl1@UC^(1kEb~D>4D5 zC<#aLAlO=F983YRAw^AAfkF=GQOr|TbS!gv`2P31`LTOu-uHdp=d!DrqYe&9^d-LJ zPcn2UA&d}Ch#*8NcS;GPgi|6YkxH2|!WiL<2u7sRO*vtla83j#QW>U#FhRH=LJ+B7 zQAwC2ToNIPRG=vV5=POBB5p&6QOYS5luBhW?u=2+s9;noJWytwa!v)OQlW)zCMXwF z2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}rf-|WI1`m|E zU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+MEa0KU4u@VZg z7?j`BHTwtW!)tgo^;>Zc&0k0 zY-`d}ZT0q&;|*=yz9wx)W4_0V!zTtz8TVq`4d(i-wjIM%?o)$Dt+MUj+;Mwl(Wn+} zj$`@8w$%L-?)PkQHfxq|%QvnqvDh%aIW+Ag?@Msmf65{}Hzl!tSdyDpRcC^Il<$FE zzBiUGdH;Mtqs7Lr?kt|Yil!OMXTNhl#TfpU{pR@vYM<)kbNm8YuNS(7_<0vPN3ZTL zQtNhk8^eZM4rOJf{_m{Z6E0@pIJ+RSy=TOfu}i~mU0UE!zI%d2!sXP;eTS2M z7d+z2u18(@*wyoV2;b||l0STT!x;09{a1|vA$2pW>XX8cgoeD`=SbqeGenI3^tqog z<{Bc>_VoN--B_i1SoYYQU3^EQ{b8mnBI-O%8lx6J%Pc;o*>!7DT#@z9I{Wy!U;Z;9 z_VLw#diR6cFfaeR&3a8HxiBoFDbT@VR&1v!o165tN5_Y{*7ol<2mjK4GH}3Eqiy%{ zirzA?dbin>F}Npvy{=uKs%qFbuC~|I5q`3%xNI=_;tbX2rkp|l^nr;xG?Rn7{cYBC z)O?nm(@_3*K>gX9hkRD(RzA``X#cA%t~9KF@QJ@DJQ&p8+4jBm-LARj#zQ6g-zr<2 zKC;qX`bi(3-elO~+_h9^P^C2)EHWahdUC2}&EE0Jwe@*zBjRmTUKy!c5}sFFUQ&@f z<<&lC$9Z;34#azt<{vkFP%}1pbJjgoY=Js9H@R?L;KRP6`D(w)qDhNGQVuRlvP>yX QP`6eVFP!G$NXU$T0j0ppSO5S3 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/stars/yellow/stressed_sy.gif b/images/mood/moonsis/stars/yellow/stressed_sy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dbf3b053ce71d32f42b91456f057b2154c1b5849 GIT binary patch literal 2752 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 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/thoughtful.gif b/images/mood/moonsis/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..e98c59cdbd607a0c299ff1ece72d8104db8151ff GIT binary patch literal 852 zcmZ?wbhEHb)Me0R*v!cQ0xka;mi}ir_Fqv^(dqyHW5v-|PLnDWsX|<{A zf}rh9jk|YdWuN`fSf?kp^n-a-UtV9dn3*XTB?5GOO+l& z+Yzs=(;T+vPZ2GymW!?vZtBP>&FAc_%JDSLcP(LdO`Ie>O}s;bC9%|NmfV8GCH8jt z4fCgou3Wct)q-hWo=X>ON~-Sbj_dE-wpW^Q|AC;8g2ZHY_Kul~f)EdQgQA)p7}csk z2#xBsD)-Okt9kqojO}dAST$2^#y*adMUgRwKknJNfcx|=;ZxtaxsrD*YEn~;vOH6j(%&~_ln&**JvBY=l(2HPS4~x=gd`(l zWlKZ4F$*Ir)8wvVOSfK0)=A7v-F=Roos*cD7cH2Kb=FK?x^CO@l|oEQ zCU4uev}>d6?k)R{F-=`Lckb3>>rNapkvylo{-oQvn`f>&GG9JFk7fVd&Wja~_A9e& zc{;=JrtOv!^JYkX+9LmE^0W4(KOeq+_i=GR&fFc6V@GB8*J06hP2asU7T literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/tiredyawn.gif b/images/mood/moonsis/tiredyawn.gif new file mode 100644 index 0000000000000000000000000000000000000000..a95163088c9d189928031f2ec00019e2a5d322b7 GIT binary patch literal 512 zcmZ?wbhEHblw;6jSi}GZE&myo{%1J$Ur|x>Ur%o46NFda+|swg5+#q=b{) zhI?5Ln4@@|C!8#3YAlS9Gs>g>{K`^&-Z=Sd5;i7^O4 zye|jxK0AXb10Mq~(EFMeyUu)B!Yi>oov*IGFT!^uBXI{u#;O%>Ts9OirxmEX zF?K!t74%2cIqQS=qZX-T6-KZrMyRIfYiz#bH(`h1QyHhbOACW9Zg-KLHaGTIN=jE# c)0cU@Pg!0ad+;>vLbp?*(2vrV$t(=k0Oy{@VE_OC literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/upsidedown.gif b/images/mood/moonsis/upsidedown.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cc5aca3db266d6f965cbdf2d2a20b93de78a178 GIT binary patch literal 593 zcmZ?wbhEHblw;6jSi}GZE&myo{%1J$Ur|x>Ur%o46NFda+_#w!oUy1dbnj z*0vP#GfA~6Ouoy~{OGjPmY;piD<+8+{VF)IBFs|pUZ2HUG0Vk9dn`6o=w7f5v3Igq zt=e<9Pww2hDE=R1o)wyAiFNG`xoIvQj#?!V+Qmj8J%L)RIrS{85xLFEjEOVaXUtnP zb&DzZSjy7WMJ4`VrQHVnRY- z@3Y#VdjB8X`x2AqnisYta?E$-V7w{NXgFc1$Rfuz8xDP_x_4;4#%%owLK6LkVO=wX zewk@J;ny%INC{S(Z17^{7UpH^qKccQxXg|6-RCwXJ2ufS@ARdQ2j|pnnZ+p0SXou+ z=2CCrmd)DSX29Rs9GmUluHZhyJyu13rla;eIX5}$023z%SA&olOWIZh2E|mao6qC5 zmNmvQn`KwBskV#d;$5?n_o?e2Jk&L*wd_z+Y|Q4pSKYz{EV8a8&)r>jTl0MF%`+2p z^e^1Jn4eTwtHkyqKO-mf^E9>Z&!c4n;yNBoeAuQ{RsTctW6+0bv)i;Koc1uTNIEPO RZs1gMnDt{~GYbQQH2~3X^d0~J literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/working.gif b/images/mood/moonsis/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a535cdf81bb7dfa0748f11f6fa6ff721beb06de GIT binary patch literal 1556 zcmb`_`#aMM9KiAK*4IqU$t8D<$)%O!L{4!!mCIJFgt?ZK#Z%Ia#w=9Z%zf^PSZt3w zjWHefLW~jdNG@jtv^js-7HdgzNwE>UMWMtJOa>8F^pWby^dHF_i|77C4}#ovUgf;p+d$+4>0 zFfc9M8Nvntd^Cc=$Od5*iQY9>wt@l#Ko+}}RpwX0o^ir6oVaFe2(OQAjM&+9id)`R zRsC#?$Ao<lR7xHat62=xXI(=5alp>^XLdxODl2pQG4sY!uTj_QaVjVy`Yi;< ze;eW*={3hR7Cq@b{@yxd2a+Y-7}SehpJ856*j#2G!Eq65I(yw|CVLhuAa>&c)W(FR z-Qr$Fq>y%3^tKa+|EoIY#YYeAPsm%`RT$LDP(|Aza(XiNt^L#&z^UHOsRgJCh zD-MS5gh@Ot406(tbzYRF8^*i$m<3v@j8OD{;8bBpW{FEd7hi_!-yZXf^Pp5d*no}@ zTUHZCik;AQIeWQFqsRX4a(--FS*4oiTN^e!m7q6@OX!Ny-S4wJ(C`hK=O!TuoSR|V zWVLhSqv{Rh)JNpKcu(OK`xO@}KhW|*JL>BfjpYX9i7w0o0B(p{J*kFjwbWT(=2`bU zW)LWLezcVa2&UxCzGN!T*MyeKE&rfYuVRFu`=)hnti(5NEZ`RA^|&+Ljt3zDosN<7 z1KEMv(zftApyFtSLGz>-i%*3u|@xTM!|-&3JT{l#J9Dg4zLbqYJlFS z;$4D-N}A@2#q=Jx3TB*E)f+!+5Ru_(;Lw9rypB2ji3R^2!L?^J2chW}=L=aVq>Cw+ zVxn|42>Y;?khBnWHW{E4gdz#U##8Gkikq8N;%P>RW|C>XO<38q5iyJ~$G($qZE(g- H4)n-BeCDb0 literal 0 HcmV?d00001 diff --git a/images/mood/moonsis/worried.gif b/images/mood/moonsis/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..7eba553c2aa291974fc9cf604987c282b5137bfb GIT binary patch literal 618 zcmZ?wbhEHb)Me0RSi}GZE&myo{%1J$Ur|xf>Hq)#U@^u2+t>PI<20Yw`N*?*9oIeJPpqGQ2d7%+k}{uxp*x_N{*o z{WvGw=y0B0hokS1cwc}4AB(fFfrJ4U+m(pSTRC#<4|3iGzmZ%2pd>6rBw~N&hfs@q zTkbyJ5jWw>mU{sO2`q&*rIJ4G7FEre`*k4O6|Wzn5Pvb5F8~W<>9l;`WIW?$uLf7uR)6D(Rosab+@|BB>*Hu|pZJHq#*1g4VFU!^q(z6cr1qU74*6CbT(>iB*!@*5c+q`$JxO%O| z<)(P!IcByeY`rOp6}8XqF7I4i8~(05tnWg2a?1UgtpSXs#!oCaJ#X<+(_~)oL(?O> gXMyWNpRJjS&jO5FO4=HeGuS6Ac2^J+VqmZa08A+i{r~^~ literal 0 HcmV?d00001 diff --git a/images/mood/neko/index.html b/images/mood/neko/index.html new file mode 100644 index 0000000..0801a61 --- /dev/null +++ b/images/mood/neko/index.html @@ -0,0 +1,42 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+kaokitty/
+ +
diff --git a/images/mood/neko/kaokitty/accomplished.gif b/images/mood/neko/kaokitty/accomplished.gif new file mode 100644 index 0000000000000000000000000000000000000000..93bfaa4c14f1211e16890274a0be38ae1619a314 GIT binary patch literal 1187 zcmZ?wbhEHb)L_tH_{_|ZoIPjG*8k`3{RaX=L&N0c1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/aggravated.gif b/images/mood/neko/kaokitty/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..675f74f1464d6608a642108a4537f0c3653d6921 GIT binary patch literal 1767 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aD+Wdm8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByLI%?C1hS$%FFJ@<8|Ow15<2x(v>XX%+Lj))B9v2zrBuJnr|wWD{cBJYHrDECfV!- z>ltUW^S$6*b8$W6ri`!aOz(*2-kH?HKbduA#N%Ug_|=2NswF==ot1V@FI{2!G~?2W z;MIN-H}hXzn<#o{o^Ey7{boi+Y`#3lz{tSi5CDo~b}J9(9igM&%~154JVo|DEZ z=Vs}ai@n%cl;N>}IZ;eCYfH-ECDzlA<-EG`%wgakG;l)wN0 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/amused.gif b/images/mood/neko/kaokitty/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ea3f9042a6ea2240a426c6f7bac198568c59156 GIT binary patch literal 1748 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3RobPdvdST zN2!d{!f$U(XJ);xTT{{S=wPm+(p`z`58O{`Yx;*)%=~ohET8)_7TH}}US8&qe{8z; z*TzHFHpCy^S8bqx&4(u$7#TPm0zh%gE@mR(z;KX(Q_!xY!r%Y{BcGyMNJn9VTca3z zOpV8+B@7egw1os_3NH0-QfC+VVKL#rnF)HuLR&nI51g6f5Pxn>hjGS*R)uac4Tcg; zuO-aMd>Rf7E4^2Rxra^JWwQFjIt@*uC$GL_MXpWmT_wsLwCdKJB;FII1)mNuZY|S4 zXFB1Vme=|W#y3-E3$HnSu;zG~N!P?&ry1RclUjBO7Ck;`VlJdRGjj9u^9!82<$R?~ z9vxZa|DJbkRYBHOX=WyDzB^2l_?tB){cxl3Y`&u$p$ASeMN}r~ZkY7SW3}qeqF&8y zs{=O#C0Fh3G<)ma$o5ET!zu^IOS`0=O08J+Rm*>U)#I$QQpO+dtx}kn7xTLy>Crmr o`C5N=RBTLXR}Q{)THpgaCsz0Ms0n`Tzg` literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/angry.gif b/images/mood/neko/kaokitty/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b9e2eae9994fd325da2aee06deb47b445acc02b GIT binary patch literal 1771 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!c+no z=cKX9xmmj9VlQ?UWq2%LP83tk+LCg3iS_hjIj^ofb6FG-?0 zSf3saj7hWX^IOet@9MR@))31a!!L7URrupr=9K4`M1Nk_JHNq(n^}!pXw8-00(rlj pHD!;3Tjdp<_q{1d@j5rxxm&I`;A8B?Wun?XXRA!JcY`9(8UPKLk-Y!_ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/annoyed.gif b/images/mood/neko/kaokitty/annoyed.gif new file mode 100644 index 0000000000000000000000000000000000000000..42b2d0fcb9a8a6f56873e1fba6a46ab81a8acb32 GIT binary patch literal 1757 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhfz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MJShL@d4%l-pPEg%;*-M#?|()vey}dWR^7}F0Jv%-=W@BbTc$}Sqok5a8 z7U=QwNFJBtIS`QO*v81gCctn}(WOg>onwK7pyJ_PW-Bfpg9R$?9UAu2cr+(AoMci7 zU&j;R;NZ!m#K@x1Fgb;Brgpv2lbOZoXC~RFs_ABiJPKS8kSX}+mguC(c^sJSJtnPjsUtY@6f&i8_M&BgVMo2nMB zGrc387d5koe==)i`Qy9o!kXQ8XM{dEwlB2S$rcymkWT77-# zFpHT>V1`!E>yR#90_YYs-8u#r zmsn3fmhw)^ACL;d~o(Pb7!OMTBRaPIb7@gwiW Tr7qD$acir#-fd=NWUvMROudFk literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/anxious.gif b/images/mood/neko/kaokitty/anxious.gif new file mode 100644 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/apathetic.gif b/images/mood/neko/kaokitty/apathetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/artistic.gif b/images/mood/neko/kaokitty/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..714ed16c5d205eca323176802573bc43390647ed GIT binary patch literal 6325 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/bitchy.gif b/images/mood/neko/kaokitty/bitchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ea9832cd1793316a33f0a8ae6d78dcfe86770e5 GIT binary patch literal 1773 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0y)v8VX75w7(46o&U7rKfUADQR9^OVkltJ*${-kcq}3&he-uFp6= z>8#cC=f`(Mzizww>)V=3`|E!T9p#qT@Su%NNZO(Lfx|<_UVkk!hVS~38`bA4&C79k zmAY<@=Hc9#-#__GnYF(uCsQibtA{yqS6QxDSIUBO@XJ*csRvBpGCZ0dNT^0OWWM1SC4PF>n+8W>ozCg}(itNOQD<~~w+xmo@ERA*J8-pUe( z;3ZDet!kq-Ib3dIR{y2qu$AHZREf=8A2P3I+?+0SJj~X6Tjq_4S=Fa{e|}55v$OcH z)Q#+fH;v4>;s36lxZV)4Ic()V-96JYA1&|U?Pj$!-FULsOx}+rvr^f;-Q2wT*qob5 zr!FlBUL99!U=)9Kow9b1Z?)Omz3j|P*t~g~fsuj3ApjK5>|!Po4h#nwI0fxWDhv)V zF!Cw7g>)1)xHXEg$JBUCTEZ|sXZHuC| zW$%=lk^SIFBXa@!oxL8{9jfi%Tj#e>!&F h-?HB)GIGny%PTm|_GMRUraS-u literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/blah.gif b/images/mood/neko/kaokitty/blah.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/blank.gif b/images/mood/neko/kaokitty/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..d34f7de7f0cc8d45b6d1da151e52eaf6329f4cbc GIT binary patch literal 1256 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aX$D3P8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCL^y>#jhh6Klh~t3(;ZRz=K6Ijv^vZL&6MPLAcS z+G?TKPRtd&XLPj{);De}dF}P3`@8PL{mId7u9@O$9!Co#&Hw$7So(CG1othGnL9T> zKfl1a+^$E$By<0Ke_^xQs4cIrZ%EeX;XwG0oq?S}l0g>ezl})#ljAuMkm%UP$iXJS za8c2vONgCgfrOyq;a+AdE*^sgD()Q`_S1MYCpLJtX(z9ead1#+U|`9b)N|5U<=iaY z@^3O-m(|WJ^r-a`nKdQ-aHH^SzM~wW4OixcxJT`kGJbt_ZA`oui}bWrjhop{c!@S# zbGW)e%5|IV>C$z#S1C-)`|_(G>E6`p`C5N=m~ZfHHxK4=JF{csx~ice2Z M)1PlEA;4e_0Oe)NZvX%Q literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/bored.gif b/images/mood/neko/kaokitty/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..98807d5819024455ead64a98216187f0faf163af GIT binary patch literal 1741 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqO^k%7Y@02Hn4VkQy}3F$pi8&hUUcTPJpXXobU=NABd_xI+9hZmN8Z}O9s zD1Ft-$cQcK4$&m)W=%;y+$cPo?^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPEd&GfCx}NV&Hhnz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN z6@~|nFfdu^y^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MJShL@d4%nT+R^Um%Uw>is~?}*X=!wO zT3DdiKMtWSQBx8PnG!UkO0upp=XSOD?%wwH_72UmZ#mWGPj2lq{Qhn3?j0W=pWtO< zLHL}Vft^8;K^Exq(?~v-<2ewJ=-9@{!6v|PQPHJKh@E4BgrMT#US=yU9)krc?j0KT z(|9x|Hh8vaC$Exma8PMrV9A=)bJAGl+$`PlZ!%q%)y^#RsPz)DTHw$)&oA6e#-cEl zk;y+f?(C|ID;QP>Zf$$3^)cIXdCd8~qaIgtF3rnv-&HF;d2QovwtZRw6H3;*?P0t1 z>B+2VYa9-gv-j(ES`1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/calm.gif b/images/mood/neko/kaokitty/calm.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7cc71f62318ee4593546041cdc7b4aa06513e53 GIT binary patch literal 1304 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhfz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wEI%dH zPfd|v-(*u;mHev7%yr*9-`(5Z-WIVeU$^$Q;oE!DE59G}-LvE4V>V_cgvZ$#*cl`l zWPu((f#h*Ho&y1ij%|z_Yyu1y6hfIdwzlf)qb5d125SK2 CSLC<= literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/cheerful.gif b/images/mood/neko/kaokitty/cheerful.gif new file mode 100644 index 0000000000000000000000000000000000000000..7fde6e74894e9c498cc6a50490a8e86294cee20f GIT binary patch literal 1860 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8eU&z`0@Xwz`MG6LbrV2@w3Xx^0#R>tL z>7}V942nNlIE{b`bwI%a%0~dimaWx#`+K|Y#obM{mrUOXG$ym;3#$m|R5mcN_8(O`w%c@N z!)ZZzd%s!cE0fRk-QBjO%V-HxmsxbRTc+^q6H9cWx4-L{o$>yb^y+6%ZdflYxP7d9 zeaO76YRbZY@@?i7$X&sdLKxX|U+TWL6HBxid{yHLhpVh^w`l z`Z{Dof_Go*uC1!K*RwyW3*CK1J!WTOao^f%q1*_T2Eh)W2??4H8M#DQw!PY%8$G3y zm5uMtjvVg;U5wptcWhbg%E}sE_3dTlQ}^W#wyUSTC|1h4zASe8IZNw@*|$v8U%M4p zFF$p6ceogfUrh0#N8P+^EZBVhoPm*n!yy2aDA>hJBpetHGH?pol~foUU|{4^bPMSy zY;bE7V~?rvn6!jpqMWvnz)ZoV-c9Q40zWJ!95^#UuUKe{r}2R^a~$H&t?4k%xX`N5 zEvCUxqUp7SIhjwxp<$)>Dj(hq(}2KNL8~?P^WE4bx+Hvg`1CB>17WKp7du?v_EbtV zFJ=>izzf#`BS)qkb?h1e8>TM|nV4{JlZ;Nm`+IYeVqdAQ*`DpbSVC57LdGYfQ)g67 z#lGG!FwSVQVqeA=TVUdHUD|P-pRDw@L+u+SC!IOFyFB^$)Y|`S?{1iXe0->%-Csfg zo8RxyD%OMM^DB4NSY2)iWfob^r*Yt_`gJDeb#b~YMRjh>Oj|1#kv&!C>a?tzNoQAn zT^q56jOMPOZA~Bse)t^n3 vpUZUACratcoaK)8BDNE^I$d8QecJ7T)$&s}H;0QIIXk=P(7hH=WLpCOQG>?! literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/chipper.gif b/images/mood/neko/kaokitty/chipper.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9e940430845398dc0c21c5b6cbfcdd0751aa687 GIT binary patch literal 1301 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kk$gC;phZ}`w^Bv^~ zJ#dOCqB2Q$!=zUpt5tUv^=fWg9k?MVxoU5x*<0^MwntJMRyjCc+9mZ=YQ?J3*AbhU zzaD%0d;5|HdqW+S?(X>Z(B){Xxn1awiH46)^0_bDGIQtV=jS>3Pk+_<<6{ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/cold.gif b/images/mood/neko/kaokitty/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc9566c556a7c97805e5e29ddaa3077e0194635a GIT binary patch literal 1393 zcmZ?wbhEHb)L_tH_|C#`;J^Xnv@>Zl|Ia-09|#zXXEFe}XZ{0uX=!N;qhK@yhII%i z{^#~{4GDI33~)8lGhk)}dRFnDtb1mfQ)y;SN@|gUfu5;CQl&y*j ziWw@^a1=G1Xp>{F*>hsjQiiE&mTU?Oj8x9dRtXidI9c%Q+!XU>JCzN=&(1CIC=^@D zVUl^NQ)9N6Mnj2~&kEc4RXPq0uYA|Vg`c`&m5_B~ZCLiFGalD+0=8!zx0<_qqSDQs z9@mvj4qQKQnwk9>)4vDH+qku~+|@zB{Nt_ttV+jaZOj>- zos6}v=d-Cg$iga=aXs(vuW#>f^X_J5@SnH)$ERmU%lSDF;lswj#302W2MnKI!0_R5 z2mpl-qX18XK|@0;r?gPbje>@Tb{=J|5{(20w`NARjw3rZJaL&QCoLr5DX{ePWM+;U z84rgvkLeb+Y%45-7oM5p;QH>(O{0tpP3+xWIsppm!BadO%VNA1tUS#W8W`kbRmu>& zT4R5f>aEZ>SC{KZmzj1IuMXMf&MP$|d%@#IX1DiIOR^iZW2WaZewf>RS?AQjT7J2R z>@P|F&8%X^Y;Piz8J10wj29`mzR6)txq0`#=&PTf&SH7DN-cJC!%HTPgvIlEZ+(4z znj`9Y-`v~V(r<5wWk3G*w#moy6ME%+0u&mHpP!m;KmVVN)z{Y-)+YNeFjQc$1^^jB B4kQ2o literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/complacent.gif b/images/mood/neko/kaokitty/complacent.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c1748eb5a68dd5cb4201a438f45bc0029f88f04 GIT binary patch literal 1832 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M44z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wyT8;OXDhLWon2Y5{YCS>?8kp{4Su}16EZP5X5WP3^k>X- zt=sqtvP~CzT1CQ_jv;N_;kFhVY7u z)0`!L*<@W=7&Mu6k=PH-(yR-eimTn0t}M-RYm407^>tP8gR|>mw&v+*e|XlgDrD)Y zBd5N+2ybHhB*jtrfZ_5!>90}@-cw(n-(A5f-H|woJSMSMB%bn*sw@c+j6r?mRXDxH;{dG~pu|IhJ zp)*ojm4esA9G>;Zs^N9m3J?1>7t7FBm$%rbt35sWc|qfDHXAt$gYOJ6n+#V@Q;iZ* zjN6mP+HX^HJ;`l~v%Iuy^oNgrCnvuadh^5LanQ0^{j;{bGT3tD^3u*lak{^ZUtiyl zte$cw;+w;*p4`XFa-|RCF|S}|LiMjSIF@f9$FdAGmL-s5S?N%l40}b3#e$T^$*f9d zE|CkCoakg>+hFsuD9xKmSyD(LVe|4+bC{SPY>E7w!Z2O6(afY%XyutHepBUiUxhpi zneN4U<;lw}4Chv`YKrA{iab5v88vf~>}#Xs8(TsjPb=XTTz6+x38Tb~Y=_s4%;o>{ zo@77By*|tD^DEVy1=_w#dbs!VYEEDLXtRRm_NOl^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aGX_Qu8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>X#T(UC=6~B16OJBM(Mss$|T_u)&a&^Y? zNwU`8p9J(3F1$8X`Sj&!O^2kZ)4 zmUgNjI?J{5ruNIz8oQHN4oou1ytXC zWN97_gxA>_*cl`lWPx5kgW~la1`W<_%(83>5)KVV+W2&XWE2iOa%qud<@upuaG+tb zoa(AG6-6qpOd7J==A0~IV4TFjB(Nj1XxaIRR{8thSS~nlezKc8SFeZ3%ZrQD<&9je z9^BtQKWw3wuI8sF_DtdFb-bqq(~nLIJ6UyBYI4%`RXG=rU6uIw_VWCao%d?Jt~bOp zEAh+h(4O%)p1Jh+#_`l0f zHd68R^>y*TZ6yS-dGH7WBLjy+04Q$R#Y`j|7!ERU3fh%a7#v_=g)nPEG8T{GeNIdXp5)u0iP+XMNFbEH>;mp;M87aq9v4h zX(6}cv6@*^ln$?SoNFfg;L56y1*}_&c)KsXKCm*RcvkL=ZL8dv3wY<)6f|hv?Jnev z$$fn(J8p;5QNACmzh@m^E^*c?r(%cBu@%ymYJNPHMu#U&)y=+lX6NST=NIq`>D{R; zi95IK|1`6`h6>0YV*$pT0x;(8fn!d-8?qxidNPYSB}!h-D8B`Y=jIhinZJ_e`Ssmu1b0)vckJT1W z6PXLx^?Co?Fo@h{qV3%F+i1Pt)JEZ5Z~jC+z1hClakgHTp!&(44aukH`9^Phc2+Xq z{@9A$MR|9*nVFEI80OzAD47#cE*T~@bo1+jbLp{GDcd4oE`99QBJRy+p$W{T)74B* z`TQ(Wb!Rfrzjnv7n1OK`Fqi&#S+xA(RHyoTI#vq~T%7I~t|hxd_|@fEfrdf4ufE*h zzc_BT(o>BE&+M7v%jfxe3uU-(PP}?7*IP{Q_Vl=$T}z_Ay}G(r_xCT`UDtvBP34#Q zuzJRmMCKZHX;z?rZ!Dgw_&N0Fc9jcFnwHmfGAAWwT$*R!JZI(BMMuuG%N{znreNFK MTibZ$fu)c&0F9Y#kN^Mx literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/contemplative.gif b/images/mood/neko/kaokitty/contemplative.gif new file mode 100644 index 0000000000000000000000000000000000000000..85e4d9e201235a584e9a528b068a919ef8d4bba2 GIT binary patch literal 1888 zcmZ?wbhEHb)L<}T_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~adj>`h8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tc1sv% z-8r#w@$r5I=Pnt~Pe~1v`Tf~uNH{c{YSoI}B%^TPsaK17Hs20O!vhWT%|f}({w!Aa zW^(Wsi}fmDV4NqwEKu>Pc;(f(LG$I-S}izmb$(oV*3=auZ>}#&44ky~)mDcaOY?Ro zrD`(hHf~RNFE-V4o8FBb1&o(lW?jk;KUjbN)7#7+Z>}B{gFu^6`CV3tya`bfB4A|KzUH zW&s`rh2(?H(&}Y*EF2u%d%0b?BpQMe8W;`y)8=Rjsh#d+N%Grra`Q6=CS69Bf*q5W z2TpTtd{o1^`M||x2JLLRRtH`Nukdho(oLAEetlJ>>be}S1==^)DIdM{Bx~EN@VU~* zcjcbGmKHU=XuaHCZIktJ^D_D6Vk#dr+&iSo>ip*S^%t>6+55N2GE^4EPp34M%ULv382Ox#x^HF|C9&CYWpQ~`n&jk-k7xLJF4}TZvNWsJ)O$ML&WmsT zZ*47peedkn}Sb{x9PC=Et&Bt#b>6mW8R*b7n6_9 zwW(#&I3S$Zz#!2$DaLcc%d?$k-Eu8fL9ec?QrZ|L>S6jUaA_>JoUX=$*P$C3Pl?GW zELd}?(fu~x4atOt*zNJ3k8QQyuF$yK{U_Hw>js9{u0~evdEHkw+}~Bkt<#qyt{HoR zS;c?ZnFyVyOtV;<&)tz+$FPr;qor@nto2csSGadiJ3H;&%M)7)+w1Or{PyhR9^+sC z*8bS)+`gP&=EvGOZwuFCc8cHsap&Qqt7WUReYMMrZ$DsHdR$h1w@k^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/cranky.gif b/images/mood/neko/kaokitty/cranky.gif new file mode 100644 index 0000000000000000000000000000000000000000..70340cc8bc2b10e65cbf9119e756c371cd231ac8 GIT binary patch literal 1768 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhiz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnh~j><~N6ti(`W41Jxr8EM3QRJ_xG^ z_j>jg>HM0Ud3C0hnL9)EXcdOE9LPb z+1u0B-JKa_eD3S3(DxS)w#=5w%UH0naUnaON?*;Tjf^|Xh4s^NZXUS1-@-b6+HIrH zo>LkVn{;@^OJDV`4m@SoJ#m5Wt*ync@15Ok?sjo;CG++@)fMRv57%nPpWE~EPy@pI z>}3nT;;5BD-#aq$=|P;u|ju%E`G zIkDj+lS=qHo&X02PbMWs7KMh%DU36<>y4hwEKWZ&$v#z0H#6i>;DUg3vD&DF%nM6- z+5LFD4!mk$iVaV?k|mrOx*&9VpKRo}*O5!}O~rDhOQBUs@5o+D_tT{;O*f zMGwu>tuDLY%*cq%m**H588{pQK#|NYW+LIhaFBsh(5|Gy-~a<7pQ2kxM`43oqZoTk zjmM-V3=`$Fg#T#y0%Wvch{De zmsbSOPrFlLn!RUPynNZ&s$>UjUOY)oM0&PqC$Exma8PMrV9A=)bJAGl+$`O4u@^gw zGCUSACyJ?NZAm%2#CrO%oL5(#xh#r^_Yw)%!f=%_Zg!H-sjW{gtWOUIMxnFD*SOQb4q31QteOcV-LnvO0oHfElHRxoohGeMMQ4ONp8*jJAbYy fUYRn_xm!-Q>SOH1W#ZaCXRA!Jce67yF<1itEnJNW literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/crappy.gif b/images/mood/neko/kaokitty/crappy.gif new file mode 100644 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/crazy.gif b/images/mood/neko/kaokitty/crazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d71be310067f9a949d849622373a685d4614bd0 GIT binary patch literal 2335 zcmeH{`9IWo9LGO%G&6GK7#g!?n{hObSPZh-GD8@K7$YH+T;oXPswwsOqC)N&DNGqO za*kn*7#&lDTpgrzNTpM$-3n~JnU~Ci@AKWj|J?v-UVf8<7t5aJ;b3lJihwQflD-n0 zBEswvBBDb=V~M6Fmc$(#qHkho9MK~pJRvk5kUk^j%oi5dEXrBDBY?RNU>GgBSa3NN zqh{#eBQEPmQ`T|e(;LgLW-21sNmXXDP5`$td4v1?DS(mIYY(T#LcQrQRFCUu<7!5c ziLL6%YL&CsOAwgzhj9>e676c>$UK5*M`0M0GPp_FcuW6{e8~Bz zQE-hGm8uH?WF$B18bx=o*m&=>*0G`0{blrnF4*FN@Q!4)5~Zt{&9Yv&4`+w5nERSu ztJfBrZO~H76nh5mzmQ?|mXVBlf(Io{Apx*hMK8ry1rhWH&eOT|QgiC|4D6R_H~QVF z?P+V7HX;ls#HHjoC2GvyboW^QX?r6DH=C)Kw<;A;$p4~h2QYx4dMu`h*08`)!DS$) zvLSw-sSLoBNRD3VdmzVT4YYp}oqGo4|7fJDT%;moq>$0dv(|aC{ydX7)n;dkte;Qa zHdvQVVc$4H%*5Xwr9Af(U^Q)wsg~s1aQ%uDz742l)CD?u$IlH5N0LMOnughe`s9;( z4qfWwBam0FYeHoGeQyKWsif{X!g*%U*oh;W+yaJqV<*>wz&P#N*7U5e@N>&RUE9>e zV6j1J%MWJ6Z#-ZjCGy`X{kbG1Lw~j@WS<6KWtU~0PlD1^(Cp!tyLGzL;iiU3IP;3` z95Q7&Mw3|9aU9_n_z_0|Zbep>O$9wHnInH~+}A8RmE0@XfL6}qFtr`>SIVtXcli(w zs$Gp$g?^u&d)6bF8n~^{>d_|4%Svy2s5M^Ah!q8WtF4`Bi{GQbS(ml|wKsW2;VU;?pZU@?v*Y zg8*D_Z6UwS9CCrL*{Y!n@pK1DQJm+)a^u45rF7a8-PhcZchw&Rk(`Jj~o|wi02rwd3#KqMdp_yZ>6Hn=YtDYM68eO*K+l&u1y{X!lxc0CAo^2f0t#6 zmVaK@zQwX2R@q@^^MX1vU?}!54p6%mPI^DqgZbE=i=`d?Smhbw2-9`2QUGy!j68yE zOnjSJWoIcov9goHs&azkgKH+}EFD;p?N5cj%z3@=tVEvnv%rnNy4?^E8Y7%-ght_p z*UJ?R66-o(%bLOhn$@~J74S2n(d_USO4RDTy83-iDG{!YX3b9mfNqCOm1>b_$2PQiyznV5D|W8fYXCdEgcOH`y(bq!VVu0+2n u4s#n%O;da4+H&s0`F^#peEbFJr^%57URR(;d(6}rx+8Uk?fz&gSoas>>WxqU literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/creative.gif b/images/mood/neko/kaokitty/creative.gif new file mode 100644 index 0000000000000000000000000000000000000000..714ed16c5d205eca323176802573bc43390647ed GIT binary patch literal 6325 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/curious.gif b/images/mood/neko/kaokitty/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..109d542c6536225bb5c39b4e0a6acc6fa543b678 GIT binary patch literal 2183 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/depressed.gif b/images/mood/neko/kaokitty/depressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b3d29daf4e63f6aeeffd3819a332cbfb14fd9798 GIT binary patch literal 1288 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>2?WDt=|nQ>iB>!gCT1 la&Uf*_1W_9*fBn3?|E~!uQ`0GQZ(t_no8rF&5Vo;)&L5m<6!^* literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/determined.gif b/images/mood/neko/kaokitty/determined.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a168428b3f97b7cea81d64cb476bd677ea5a3ed GIT binary patch literal 1741 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a3kF6G8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0eFv;pP6*nNox*I1L#Z z7aDT^nX)qEao{4E_Fo}ZSCO=C?>oMdT>FXk>1ZpP!P$@GkL4g=kRRo|1PB zXQw{g_N2?`qx*!#cNgh&3o@L(v@~+NTt@JdH@9~bzrN=ySn}e|KF!B``y?w0?wy#d z9iL~Qfbcv!13QBxgDlYVCr~`U!=S;rjaimWLBgToNE@GSkc`5CM=mXrtUNz73=T9* zmQ!7IrlLs2l}W>Q+Z@ZFCk#v~j4TQbm!H_rQm?mqGP8L3nFS{G+f2MZYFt>Z+->!D zd5PN9rLMVrKin5&U0A1U>UPEJ>g#K(4K*jZ-rkgRV@<&0F5Q);dcGUkK1m5wK5)3R zPv)zXMD}+*&x4hXvt%18KHTUlvVNu`u}RPUZIgkGGVU^V%WjaErU@Dy&x zd3QVyXofBqk@N#b-|N%sBI@&4e_z%1-sp8XZR)JB%rNEx-Z?e}3c7c@3wbkge;4J( z?XX(g^=EZ>w)=L8Os|{@3Dsjg(%MFKb0P{;Ca5lsyLV>i=I7@ZIIF9~+%SH*XRiN$ z)7q+J2W&n&M2%<*Ry#YBukzWQm!F^eFB0kgXS{36)59IE>?XOEU!Po_WY(K?Rl@M~ zrBy+Pk1cueRX$>K@Xn;Gr^42rTa%MnWa@Ce;RG}LjYm%-t~*@cQRMk;>2KjT4F~IX wm*w0xOg}iGz|yR&Mxf~UNr8pymdx3?+3`rJakJZ+f-NsEEqf`)!@*z;0H%tZEC2ui literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/devious.gif b/images/mood/neko/kaokitty/devious.gif new file mode 100644 index 0000000000000000000000000000000000000000..48fb4af554af801c4c398f860cb33e2fffc5ced5 GIT binary patch literal 2005 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

)ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%%u!om;@P@A`m>#k%=V{yd|j<`b+&wQ zyl~<5B(tA8-<^MbA@o}5EZgMojrSEZ&1&uHmi+wuLRrjw-n<9DZog&S$1fNE@At1C zpI_gN9=Gj;|R21N!1Y+>fy$jBtp^W#H;3nPm&ql29Sn<149!7k5bHu2@4z!v{RJb zZc4?(2Mzs<8b&;lA0IdLF|Y|3NER+(n5-Shr{R$Bl%bE${+dp~rpITPOnkXSy%;q7 zXR8p?&u73;`iyaz+xkySq^>@?GT&iqS}s>;^5Omn?heuHFUoFh8Jjop zYG2bmIgR7sDpP~+4DpK%dAZ_Nd~Zlx({}WjPQ|p$q$BN9-HyIAT${S4TR2E;#rL9H zXJ&CKN%S&gG_lO{XIAY!p!jf6hkmn}_Jpr5woL53mFH`{KH#)7>*G6jc3NCJ*~}@w z{^TADuXD%St?KP+6G~?~Jxr@Vw|DpV_p*ZJpV{=IY%)J>J-gX$e%zk#4LHLHIpfhL z5%r$hs&Q?V@AiMMca`J>Y%t+;()GT!CVaJgI#a}HvsJgZ3mcxh@dCLYVe#YY;Iq`5d07?NEW4Pxzh3>eb9TMaVr@kk0TW?*8@dS}96tkJkoGqvrH zC&P-f%l+9+Yif4!vU=oZEoews*DG&5_hq?Z&DvU}jKYP{aty41?fE;2gTZW7T9aA;g;*{UXcsyL%@zJxzhK~?ChD=SsGV`8H&th~NHJshg5Js%CqY zy*7L9bYzZY^*Nmn4KJBJ1Qj^e{(AP3dB*8HzS^CMFR!y}nfrA~o4s6M@mq*bMkepg z+?r}X-8`ebL$eMpUVmlP*PVxF8LqFt6L+`l_&Z%;O{N#MvvS-%?X_PNzrJqo%N9mP zoS~#)&~T7}g;B;O!eHUyMjm;u9*vEQj<$&l>#0--JaT1ZWJy>f5!B$(D$G8^Ch}qm z!&EuLHWdR0RquASY@r>U29JE0Ov1TDtr%YT^@%WYXfRw^c5%67qu7qlNe?cqWSW=7 znziY`m5H3w)9!keJrCc&<2x-j+bAt`X>y~K!G_Xx7q=-Zb7^R8XSlnZ?T=LJ%K-g& zrsDrnzBV&no!Hy`mT8(y$s&gn*(Zg{s(%(dTRyv*&&J`GLm&&swMEM!e>q%TGQ-~d zY3D}M%(Xr9Zl8oL)?7r%O49JcbM8=Tq6Hk5zy zy}+*UFLuw&4DZGj_QG;Dre&{orxw1_^@-jdyD9baw>htFr`%~VE!B=+8LC~>Zkp`$ h-{WrO;r?s!_FH(RcDTOV#%13muV44)IVdez0{}66Ckp@o literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/disappointed.gif b/images/mood/neko/kaokitty/disappointed.gif new file mode 100644 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/discontent.gif b/images/mood/neko/kaokitty/discontent.gif new file mode 100644 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/distressed.gif b/images/mood/neko/kaokitty/distressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..c632702aef5c3dfaacde3e6427061c7b47b49a60 GIT binary patch literal 1796 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aKL$n)8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jwaA)t@fa*fJ2k_C^-77SfI7o0>&kyB3Bk!1 z=IUe%Rd9-AUY@1JED-VQi$=&wZ}u=#DU(-0s}mNc&8?iGeQ9Rs;j+}IZ|Od3{kcUp zXkE`dzulnpnvO$4UckOO|9veSMa%CTsD3T>cSZSuhl~5gy>-@z<(xd(tIfXm&xM9` zW-ES~0PSB-(wS$N=F7eLuqFLOSNSft-knR651R#U`p0qUo8J^o!$YioG0Q&ewkVg6 zKeuP+=jU_N?dQLpWm)?2+Ir{v=l1R{Z)Rjf4ia`?fXD)ajLSdLz-m;5|{N_|%>glMbBeGOb;A z#q*0I<9tokUn-|U($CHplsB8Z%XsCfh0I(c39C%ik1Vl?6jRs``uxTw-L-9JZ(Yr~ zy(J-eldJYO-Qzn#mfvH2Wt1N{J+NEO!lBgQ+GJjS`FX1>3Ii8Ky_~1>>PDu=M$6M} zIdgtIJ$l;8xvM6#G{N)Y?1j^|y@>q!>iULccN2%*Ww|$5a$j%Lt=^u0Z(}`kzJvh6 z%WMqn4ANjPp8$H9#~}ce3K#`=CKxm{v~mjS)!Zm(XlUnA)+*6Ra5&b?$kuUW#|D*y zeMo;om@Iv>09a$@S)Hq%Nj-=D#Y&MkD}mU6WU(e#+&Qyw&h zV{60JxnbM~=KK;_7Pi)Kf8N%W0$Eo!DtOOp%?x^Yj)9#|p|?8Z+3l^R)%SR-P1Ej8 zuhZ{hv1WL4bicH3oJsb_4W65{E%nOQY%F@TZJKfRy)!#EKR>^Kw?i&h!Q|!TrIw51 z-d1jXaSAy;5uQ7R9G@Z*3m!T(@iI&BC@4HS)FG>42=9I&8%p|Y9@w}3Lw$r*>tTaMkS-Puo4RP)K{sq#ikdcr`S6O@whon`Xk(h6^TpR-Y44_#Zw J%f`ZB4FHxTw8sDd literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/ditzy.gif b/images/mood/neko/kaokitty/ditzy.gif new file mode 100644 index 0000000000000000000000000000000000000000..57c00620779c00083efab637b5afa942bc3b0fc7 GIT binary patch literal 1350 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a2L?tC8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=12d{HE(XKAO;+4>6 z_bE-WYP{JKQ@v--c^+iaYgBq|7FX`AGgeZ`PS>~bKROp%V4mN!Svbk=PxXU>^LzUF z_1D=HeSCglvG;Nb0pvhnVNd`<298&-Kwx4M*7Av1@bFMOx1iIU6&n`1bV;zso#9Yu zINr?1UB$y-*w8RhO1RG^vZ$e9vWjR`jith~Lk!GChh$C`r=6Rn%K75UkIgI2GqU8I zQkfu*wEHC41q6`i1{MGS literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/dorky.gif b/images/mood/neko/kaokitty/dorky.gif new file mode 100644 index 0000000000000000000000000000000000000000..8573666daa89c0c54d17b1e757af09f8acb41862 GIT binary patch literal 1818 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a4+cgK8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>1UV%xK(D!giQbfQUQ9z%aLL_G71t*{h!seUFcx*{wWOChIcho9m5yPg$^=Y~dg%4b| zgwJ1>YaQfpWm(0?OM5fJ^R6w6H7zr7xY2NznZ0VA%bJZF7`NAcz8C9x-7s-+y?0a{ zkK~f1Ug=!BIWJ}wWnAR;%#Yc7b>ZzPYhzE(^R<5X?9k@?{IC_f&EMZ^;b&vP=HXim zj0_wO0if7t7c-G?U^vLYDQH(xVQ_$fkx$Vrq@%FGtx=3Urp9B^5{8L#+Cl;|1($j^ zsk00Gu$XY*%mlq+p)H=q2hK3EHi@0kELm}Wo>=>$5Uwjr1DE(Tn}uqLzHn-EauriB zFnJxe%2At(;dW`(RVES1zN=bWbHWy6I?hYE6|(yB#H5>HvA@jLHtuKhle3s``RRl1 z2Hq8_yG+vW9I5YoC(0SQ@m61JWYQANjf!bgB#iUcys-R|c5bobv^}$SZGC-xL-Of) zb2n^Cy|GPr|2baC@^`(AjM%(;jkfX2ur=l4Dt~D{m0OcnUtB1}YOq&o>YIojX7xVV zsBfCLmuI+hb==yLcXx;R^If&KuV_axH}IaZEm-i}>yQ+)w8!e}dUvN5iZcI;3jLIH yOo2E1PR8elN6t*JERXw9xj1tz-{oa4b3xwa)MYQzy}jwstsVJ~*=h_F7_0$7ytGmP literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/drained.gif b/images/mood/neko/kaokitty/drained.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&J&Nz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6Or!30i7snc8|Iz%S8H>_%_V8v4@6#zE|1!3cYj^(D*=@oD{?v~ z?R{;W@66o5TVq?0p#5-iBX7@B>+qzc0|5_z)vT$=IlV#SWg2T`Wp3J8k;p|dbA=u| z&Q|hW9d~xu*6gcOw72)ooniX+_~y+0_s;I#{=Suw5#e2S26hHX23eqYk05zhj^{u? zqGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsSPvg;?*x)%yJ9(9igM&%~154JS zo|BUk{bpN~f0B{fw9I9pOS_rO34@iFmnySb_;yWPd1VsorcY<05>l_O(B56vt9ecP z!s_74y1kudYa<)k9!X88deCrrm()|K4X?iG#_VNl%j)HJit o$Ni{SoVtR~ec6#YJ2yW+&%u5AtIn@7Klgc`#mvzo)ow6XeX>xM*oH<+npS$-T2n-Dk zlarJGZ~f0O3PwX<*oA=Ne{Mh5kYH!W09PYD17=2`2NnOxx@V?2m1gFoq!uX{=$R@c zRVqZ5r4}m$WTuy$({SLqUz>Tin#Hb94o%D5O1*r4m1z322Fwk+>t))=v`mX%m3DuA>btIJ{=KWK%Tms-vO51x_15&q_m^{v=orkdC=8p&u}W{onHisw zcTaqNPP8lX^Rq*Ok{xLRI~|$NF6-<|yKwV!*g386?!4@st8%W*nCeyLvqj^@2HVnb z-K;Io4lOy-dEKtZyK~;&=2+V;@4s))#|A{uumgie zl0gL+H19z{!WWIgMGSo$ zzVlo%1(q;Ol;J;-qWPKOATvi+*qWK2)0kK+bCsrWnluJ9vI}YOMs3y%T z)z#&kA~LK64vp7Vg&jWiW!F~i8yhluv-Vb+>E4>joEn##Eus^%gk!-q5$)-(&hGIN z*N6}ZGf3QD$fzE1U`Ijnk&3%s?`B49iay0-WPIZGg2pH3>`jeVx(0<3pcS<-BP%CBOvp>Z^dl03wNdGzDn`jQ&D(*R-jV(+k%~+pPe(7=i$H+1}p*s z3=P0A5Y}Q*Sn%*rI}^8@jD}#+AqG+LB$tQ_u;crExvquraksBcr(!HVAou3am}WkdDX}E zt}bc3zoAat;cB+{s)U1K{QP>S#q%Q$#YkJn=}c%$Wh<99nX&rk^HjEK_26}XW-{K| zALiYBFZznXqxlZo#Z+!p73ADx&t$$EYrgFAJ)LH5_m#hlK0aD1s}#SkX6MspMn(o} E0L0wj%K!iX literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/ecstatic.gif b/images/mood/neko/kaokitty/ecstatic.gif new file mode 100644 index 0000000000000000000000000000000000000000..c848689c01097f022f4a6525870f1e4e0138805b GIT binary patch literal 1365 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a9|lGa8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D!v6Iqy5xgo*RQLn?fT$ziD79 zn0iRpAXwLP4TIjfCEnZB@9zp&|I4J?EH|OE;;Y!Z%;`^qnJ4hh2wBjeojPG6Z%XRz zuy=R%HJoNT!E@6%WBL-)?tK!IvQHda6ud9&*Q}hJX4UxiEw!^#&fGiD%*{T}>Qh0} S(O`c6b2XO5Cq$W<7_0%p)d%+g literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/eh.gif b/images/mood/neko/kaokitty/eh.gif new file mode 100644 index 0000000000000000000000000000000000000000..125305e97e5b9e7b8ac353f068fdde6c5aefd763 GIT binary patch literal 1739 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/enthralled.gif b/images/mood/neko/kaokitty/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..c94069bf5c1461cb8046e9b0ffab004dd59434a3 GIT binary patch literal 2263 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aHwH!y8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&LZLax|>JU1*H>aUoniEC!{LBP9}WW zvy(Z|QLd2^X}%Y;GTTIFi>PE?3N7CBFLQHp_GEkhWAjcIY=3uKK3i=|=f;X>=Z|sM zU7I6wpyTxya(!3n^ zUA5Aa*Ea5E+ou(&7Gbb^{g^v zmFqd5NG+bbJC{5=YvgIYr}IVj2u3nqEtolle3p8diF*3Ud#evdd)kiFF#9Mo(US z$%kd(y6Jj^L)izI0n9}mM?`?*Na`YnM zyK!fJ1T6A9KBIeC%8JcToac%^XC`{y%r`KM)ui8YU+v|KIw5X4-#-SOtbrFd72G zIs_E|bNji51UowhxEkphFf#%@tN2gWJu}UzG&3h9wMfB0&r~6)QX#S|wOAn_Grcsm zghBBq3#SoKp$;fyK>3J)<2eH(hm6OD1qYisgtcN$Y*=`>T|n7uj>pDDN4t5MGip{C z9yr3lWTp2;;?rXWMnzktD;-4*r#cwfPWas1sOCLW&t7Q8O2OslXESr`X_07XxG;mY z=8?~;i!TEDoNCpk{tA9^e1_L@z6)K&i;v9n-g!!A!BuS^MsLmz-34OlC)Z~jpLEu0 z`t##EqF=XN{q=3lrTz84g^qGdYI&2g^Iur59+28K>^h z-L5ycQ|NQ}goSsfnfXpsJ#}5vP;QH6(6+a?cND+g_V#D-yL*!hnXmtm{_*bdiOJgW z5&{UnvokO;NHQn^{r(B)ca{kW2~EvxoN6*BHY_;QB*3o}a-ty7rCmTgEayeQf+L;M zrd~cbHYT5#tP#A*MsmT^Q;oXJ20RK1%TCQOP3IE`2v+l+#l-eQL?WT#;ylC2+jz1{ zG#VIK`nH*PZPoN$%reL6Y}6Kq&{c8KLMN<@vqRUXuXef`^+o#@WB$rrEjO=aH0~(7 ze@^w3h#un})_*}~IXAzLJy6b`Z93;i&f~e=`@N?5%y|FgbP%i5jU0s+jm$Ib-#^J& zV32mo*)zZF_l*^=F11!Zv#pu3{BoCfYWUNe#i@Dsw&mXs+4X(t$HynM_dUz0`T2Uv Oxy8=?`z%u&7_0%P`3qhE literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/exanimate.gif b/images/mood/neko/kaokitty/exanimate.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bb7d52e488b06afa2f68021b09964908da03a3c GIT binary patch literal 1293 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aeFjDj8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!djzPm}|8;TG>qI_?X5E+^VLa*XEmO^iIjX8n zTfEHm&TK82dP}v-eEs>oyu2J{4&M$i?rQVrGgH{UKK?+XxO74EgEtH(d!)B-=@Qx$ zGhz0_MRz&^6;7X<>p5L5BlyXy>l>0!&+`>5es*J<_~CQ9lI3}~4m5Mi=NTv<{LIe4 z&LGJk3-t3LBtOgX90*8sY-8kL6JWTg=+Y&`&aps3Q1NgtvlSPQ!2%Wc4h{QhJem_5 zJlnLBSIIays5CIJWKHThX{>T?mTvhsnXb!fXBK+YdWl3OI9#6LJ6}uILhx0#Zr+^77KMhjKg|4AuaKL)v%% literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/exausted.gif b/images/mood/neko/kaokitty/exausted.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&J&Nz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6Or!30i7snc8|Iz%S8H>_%_V8v4@6#zE|1!3cYj^(D*=@oD{?v~ z?R{;W@66o5TVq?0p#5-iBX7@B>+qzc0|5_z)vT$=IlV#SWg2T`Wp3J8k;p|dbA=u| z&Q|hW9d~xu*6gcOw72)ooniX+_~y+0_s;I#{=Suw5#e2S26hHX23eqYk05zhj^{u? zqGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsSPvg;?*x)%yJ9(9igM&%~154JS zo|BUk{bpN~f0B{fw9I9pOS_rO34@iFmnySb_;yWPd1VsorcY<05>l_O(B56vt9ecP z!s_74y1kudYa<)k9!X88deCrrm()|K4X?iG#_VNl%j)HJit o$Ni{SoVtR~ec6#YJ2yW+&%u5AtIn^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPC1}L9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D!v6Iqp>eC-+efxPr)ft`jDLA5WOsQ%^t^y>HI~Tl1&{Ztsv7Z0n;H2WoH8@2EMviD z#$D`u0erQWHZz`_!G1k<*UZhC%-)>(wY5^Er%!3L2c=X>tDl-8(cARrZ*|UxBW9)Y z@#psJ{QO)X^Ln1%U6aqR)~^h2Keu=H_xEf}%uL9E!VU})Szw^NMGcgK#D;cWRy!Vn zjR_2l!m@TpA|@s@Ffthgx$Fo$&@fS!u||fWXp#4Hwa7(pBpMjJC+ZZR+H+#kfiqpE zwd<~UeoU;rv%l#jbm#F0#r1q!bME5Q$#FcMrYg~^b7O@|c?Gu}oV3pQ+BV-$Ps8pVXy%UZ XnDy~P^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a2L?tC8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=12d{HE(XKAO;+4>6 z_bE-WYP{JKQ@v--c^+iaYgBq|7FX`AGgeZ`PS>~bKROp%V4mN!Svbk=PxXU>^LzUF z_1D=HeSCglvG;Nb0pvhnV^Cm_0|vq~XdoP5W@k_^0S1C&i-4?Gi9})2VFn3FHIoiV zAk-a!20|Q*Wu^B(e18&qiD`GS?zu^km#b1wZ+(4xnat(9ubk#@?k%b1m6FI=pz5@` zomIe0K>Xz`CNuv>syiw+B%knL4sq)?Dt>m-AaYr2)zwA87Zr_**UY@C_PS|F@hr2S j#b$5U^J?qwTd`}wyZg&sgZ}x>*_g|4l+&1pgTWdA-5dHa literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/frustrated.gif b/images/mood/neko/kaokitty/frustrated.gif new file mode 100644 index 0000000000000000000000000000000000000000..3331bcbb6d7e2401e0fc6d3318c51aab7c05b2b8 GIT binary patch literal 1822 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSv`!yMfh66sm7R~o$93Cw7 zZ8U6EQVlT4ys%tq=Bg5{%gR^hFjNKUewd=|x7K4}n&|AWuNc;+&)+pi>)Wdr@{SkKH& z&ddvVKiC#D7{8pnkT+x7naU5R+gCd3v)L$Ydv#UUdU1{K#ME~OcUMM#>D{y=wud!W z&i&k;ou8jyn0R~N--pvNO~$Z?r&6P@ExfWZIrdjeXSmMsE;c6VhRO#F_YNtrO3$dAsCjFLPP!If&*zV~ zrcM?&<~u3=F7=#yI+I4Gkot=Yi&W#D)L3nGo4z9U^gQ3)$!Q0-a^5=^Q@#EDy?xB? zJRArgvof#){R{H(6`+q<1Qt9v(9FRu#xo%R=uvKIxfqVXB%ntXjJEs;IMC3`sn2&{ z$A%Qoeq~1`9*2Y_$0iyC+sSx3Jau6*bvD!~5GyD0ldh{A{)Y?cac<9u`%dEhopz!EWhp0NAKtSLl zmo6r@3KNNhhLe4Q!Dc*}MJWdvSp3XPJU6SlPG*U5Qkk$hl-Jq^IhQGb8$UmTSf1pwL7P;Ph>Vd?X~Xb4}+w>u7yQ8YYJ4;j>*W{ n$-Jm6&X~KHb(P3mphvH-)&AY8ySwPstsVJ~-_15qV6X-NR_?~E literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/full.gif b/images/mood/neko/kaokitty/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b6aee37d62dbde6e57e0019fbf0a3055835d7dc GIT binary patch literal 2362 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aF9t>q8IKJM4mNWLYsH+{u<&rZfU?(|9|jGsU1H1@ zJPHcRM|xz<`2;R}Ogc7Mjxj>T(joaU19Q@}7Rk-ad?%R38u2(dq`A#@h+fy@>G0fX zo@*vstkx8Vi@mNhz0UspvNUKmD;LXIt}l-hK2tt?aax@q<|Z`lf?ZLja{30-6(xo5}6$0sIh z_j}wrP}F!;8=JH5^BF22f`f&Dl|hj~9vB?2P=Z6lpuxF~Lzc}#!lA*X zgIP6diG@SM(RLx{IF<(&9yfHdG4n+H419WOx`F9Fmq-H!#%V%{uWTZVR2gTn3b%b%&+N{v5$hp!-#pd4ns(O1- zrgUGf*YwmoU8SGPmPB4$61S|-^U>ekmm3})X5f>Kt9;OK@0dRG53_{Y z9t(!YhbCzRw=L-iTH?f{YC0+8=A@?#OnUrm3Jt|-XXi6lJ~P>I`T6<9iiJ@oQJWkX zXZeK+$!IcYH7?iWj+tsTH6wII;O4f_$cwN2mq!FH`Wv||p<%tp<7H=Fd|G>Fx5n*# ztexh0xBF}Rr6hbL7#b~T^`%Y!dZy^P zcM4m6Qe7=*`fBfD^WAlKKYn?0dq?r>duMlVe}8it?;kUXKOf#dn$oVkUseE{-$!`V zKO6i}-xw;VXLFO`(w3b6yPn=QUz~n6&c1k==k&!#I%V9SU#bvMjEo;=iln~wuq%-^SBrk`z8J0qweWTmok)ZNGhtIw@t?aI3nWs(yy zBkd^D+KR1f-Dl<8j+6Di^f+v%+sjEk-Qmj{_ct&y{M-HM0OQWK_*ZLhUw{8#f0MlQ z*Hd3|ukMaHueB|Erc(OusnJ2b8ke4&+wNd!_UDY{)>myx&im&1?k;^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M48z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7VPi9fdK?W8- zGZW9vs;-k+Vw_YaY)&~lUn%j~oEgOqjf+|9lzh2@pC6d%ndxR4HF;%lBkyv#rBbD< z1KZgr&eCyESQ)V?w%<==!Zn@n^{hrlDb{7Hqc^%eoy21~_0^44((9RaWQwd0*;BGpI9>&Y+&qX z=X=vL^GEW@Hsi&wS|be?CLVTU?B5e}Bgt(_w_#dH*0u-F=g!}`Zj1NV&DmEKBlS%! zuP)5#+>v{H&D`ookMA95=4L;)^Ye%1qn7gQ6ZZTldUm#$odq=rWWed+IdXc?fu;u; z&fK^l`B2r>V|)Hc7`gAM zx94X)AewSw#v=F6ygC=Yr1ym=-p-wCwC&A4e*1IhcqLUG&$U+avz)Uu|M>V=zp$Hx z05-qBL5=0Vy%lpeqBxtoX5m%#Cj`4^XhyyVK&i7V2QFe zcIq@1%>!Cj*W0hWCt_*r5VQcw+%UBW?Y-pU!&i9~X z<_+bOEqU#FM?D3B(eM1fYfsD$rDOZL^^;nxrX{;ipTF7bPWG?Q87l(6yXmf!+VrMl q2j{(Wdp{b!zki_l`LjEbKO7#-=~Y(GoAaUQ4kIIK0F3m)z#0Hmzqnce literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/giddy.gif b/images/mood/neko/kaokitty/giddy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd0075dcbfbc4e00872393a325d6f3c6f5117e7b GIT binary patch literal 1299 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPJW<59Z;}<@(}~aLk30;8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0eFv;pOLNGjr@|k!WbR zFwbssmWkDr#TS+Y)N}pqFv+^oD`fghCxAgKd`?6n*MZ0ehwE$83a6d13RAnjIc5K+ zKR3z_++I@teACubKZlSYikWJKrh6~FKr?&Z6 zE?{6>ZnQS(XvO5L%WIYQAKT(_QTxi8^qqD~x^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPA;HA9Z;}<@(}~aV+KYJ8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tC!kVATcs-FDZY%Y3r%-wGsQm{#uzh+&FN9nf-^7UF3}eaR=;J`SWrTUPtd>*04^yeQE8T z$r`hRTqDcVGA@cnPEwN zMb5p6MWBJfbE0zcsuqh$2Tn~hOFVUF=7ff`?Pld%Q*VA+c5b1wXpl|Rf`$vr45zmF zST0~-TyC^B>1f5|tjlYa_aEEhaZ&rqn)ID^OS(cdZm!IoILXxEdc$#M_FIpRMqGEe zIXC|DKA9WS^`bT!a{tzyZK#&iBN;B{ax)^$tyg$@+&vxB&zB}ovh9}h-L>UqQ`hTB TersTDwqDf|IZ4%PqM^MIhh*_{ zzkYkhA0k|nG!8CsU{})p^|9e{yC1)gO@qR#Ln}g;t2qROYB?>B5w7U1P-wilF7R@b zsdm|_rpwPuCq#UCzy>!!3bOUmAgC>|`5y}xy3)CZr-tK-k_ zTkz$j?0xy?8uu$}e!l(u`u=+Z1w@#!Gw?7-GN_}6nT~`)!+|z#UNaGegruV#%*+9I zc3f0+V-T};`s3k{?ApO%CzLb8XsK6|9{aH)7QxR>Ph%*!7Sj>@;9N6%(;*!T;}?ug z>;e*|5hg2wmT(Ga*mhmeY+?yvmGd}Iy6WP3znw|0s}^JjY|J>U7BE5d03&P8c0C8} zvb=yDx%czddY7+@*z56q(bw4xAMWpI;+B54t6{^1M$gw;5qlCg-B>6;^$ z%n}X$CS#hPv1^6?Y`?R=j2YNANXFz|SYY~g#YV}Lyk4o#ukY|!>9eh~-W+nQX0cap z^o3WMPlJ`Mrtg~b(`iG0eAfMc6D!`lyT{$A&EsEZQ+b1(nF)937&tIAvToJSQ?Vv@rP0Qt>QEJvCh~lCS4yP}=F4X2n@H z2aMIvGqdn3{P6tr{K5iG0UlPbiOVms_y7aNq4eeX)qX3TcvmgZ@?V>S6euan z^%z!{>iTaLOPRHj>TW2@Czq_OA_phb98uHIKI^EWi*psmF+TsquExIw& zH(g&ai8FfM8Szb5&g3{Zf6Wowl5uf@GiC++1E&lp$WBSi`Z%>D6BXtp(-qXA+ zH-=nhTl>f^FJj@R$HDPUx&JopD(zXb`F7k1s~zS29NfFB<@eux@Z%#W-B<$v7U?TA literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/good.gif b/images/mood/neko/kaokitty/good.gif new file mode 100644 index 0000000000000000000000000000000000000000..afffbf1f4b312ab5d511da3a535439eb8eaa65a0 GIT binary patch literal 2278 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 X@7Klgc`#mvzo)ow6XeX>xM*oH<+npS$-T2n-Dk zlarJGZ~f0O3PwX<*oA=Ne{Mh5kYH!W09PYD17=2`2NnOxx@V?2m1gFoq!uX{=$R@c zRVqZ5r4}m$WTuy$({SLqUz>Tin#Hb94o%D5O1*r4m1z322Fwk+>t))=v`mX%m3DuA>btIJ{=KWK%Tms-vO51x_15&q_m^{v=orkdC=8p&u}W{onHisw zcTaqNPP8lX^Rq*Ok{xLRI~|$NF6-<|yKwV!*g386?!4@st8%W*nCeyLvqj^@2HVnb z-K;Io4lOy-dEKtZyK~;&=2+V;@4s))#|A{uumgie zl0gL+H19z{!WWIgMGSo$ zzVlo%1(q;Ol;J;-qWPKOATvi+*qWK2)0kK+bCsrWnluJ9vI}YOMs3y%T z)z#&kA~LK64vp7Vg&jWiW!F~i8yhluv-Vb+>E4>joEn##Eus^%gk!-q5$)-(&hGIN z*N6}ZGf3QD$fzE1U`Ijnk&3%s?`B49iay0-WPIZGg2pH3>`jeVx(0<3pcS<-BP%CBOvp>Z^dl03wNdGzDn`jQ&D(*R-jV(+k%~+pPe(7=i$H+1}p*s z3=P0A5Y}Q*Sn%*rI}^8@jD}#+AqG+LB$tQ_u;crExvquraksBcr(!HVAou3am}WkdDX}E zt}bc3zoAat;cB+{s)U1K{QP>S#q%Q$#YkJn=}c%$Wh<99nX&rk^HjEK_26}XW-{K| zALiYBFZznXqxlZo#Z+!p73ADx&t$$EYrgFAJ)LH5_m#hlK0aD1s}#SkX6MspMn(o} E0L0wj%K!iX literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/grumpy.gif b/images/mood/neko/kaokitty/grumpy.gif new file mode 100644 index 0000000000000000000000000000000000000000..cda97f1dd44e60ce7c8d8e9a485e77bb0e9f82b8 GIT binary patch literal 2012 zcmZ?wbhEHb)L<}Y_|C;};J|^XsHld9hC_!AIaw_|a^%S2!-tcz=gisq|J=R*KwxNS zn4Fyaf9rpSQ7{?;!!86A|8x7fh6Fo12DlpO889;fJ*fCk);%-LsWdYuCACPwK+jYm zsZt@bEVWo6ATzx*wS+TDwqDf|IZ4%PqM^MIhh*_{ zzkYkhA0k|nG!8CsU{})p^|9e{yC1)gO@qR#Ln}g;t2qROYB?>B5w7U1P-wilF7R@b zsdm|_rpwPuCq#UCzy>!!3bOUmAgC>|`5y}xy3)CZr-tK-k_ zTkz$j?0xy?8uu$}e!l(u`u=+Z1w@#!GVm}+GpJ*PnS?^afi`YIGZBS^q@x|I%mH_H zTvR;PC}!>SM`J?6u`U7531=i6mY$l*8qYVybJ8=P84NMc?qmutJ~v5)pF=fc^0Eue zZ2SrqSr=AZSn4UP5YZ*_FqnmNm5|MZ1=?2^C(JK9J1e9yd|~qCF5d+XuMaSD-71Qm zP^J^Ru<$Nd%jv6mvAdFgs=b{pR={+)@hg)mE*E>T+brYw(fZ_^^P1kx$WRPR56YuH9UkdOaN<7aZ$kl#@I2qfn8NL5^{bP2?s8@2Ljy+f+1! zpZQE@&c1hN=ZA*#v+el5xCnen4p?L>te~J(vgrI$&RL+K(Ym}KVt!cft>DJc`O$~7 zfI;&L7&NDXVg<^yqvvOy<#O@9nj5_>`sKGZ(qj2c`zxO^F}xNlxXM~rFJ{wlU@g;O zZn=EdT{}J|9w|4hmyMFxl(w`;yWn7yyKyVHUIzs literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/guilty.gif b/images/mood/neko/kaokitty/guilty.gif new file mode 100644 index 0000000000000000000000000000000000000000..2be353057283d47bb79fd85c2a92c002b661e3d6 GIT binary patch literal 1728 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=N#nwa&DGx`8S!a%W7v9denM}SS@g9oaYyACSy^k+PK1S zy6L#z+B z=iS<<%Kbl;d(+GC$10MJt>+Uu{dLM)08f=^f2ZE-Z?e}47zu_3wbkgUw=!E+hKWn z*Pqql*~eF=L?$iK-1snYO}C_bOXtR-W4+Sec1Obh8d)tG2@bA};>K(e4x5%7XOOjLYVcrKbaJ{% zq?3xo0@X9K4Wlo~bP7NB>9(mp^oMiP;(!^FnNqR=4KGhG^Yv8Qx?@Yj)#c$!*#fFW zUWToTjrTKkxaM%2nZ0V!(THmdH#SJ@XUgyv%f2$H^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%8Ej+5B{ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/high.gif b/images/mood/neko/kaokitty/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b1337480b9f123704e35bc5fd5b07d112efe0be GIT binary patch literal 1611 zcmZ?wbhEHb)L_tH_|D33;J|_8>^XC`{y%r`|CA|H{{R1PXlR(6ocw?5|LZ$a1V#C72?E=bPb38UK zI@-<4oKdsF@W2rUCM&%+5}zJ3Fe=(AUFj%lIMu<(cEac8Mm6u5dh9|EA`+Il&2h-* z)A&%d{4fJ+$1#>uS5$)*S+Pomc9djZULCqvXvVA$&#$ic<1Tuebu}}1ed6LYk%rC6 z!Q1UP``(@kTh_?LHsjt|>2O`=2^PE@*Q|G}zp}XWpqcK=@|2{b4wCY56$?HwZsQPW zI9qe+Q{&0(uT4{RO7k4gPv!i4wDXtoi~Sn%#=Ub_O{H zSzzE?L=GGqi3Jaxns}L2coY;K9qJHO=MxABR65iq!(NeMu^{Dmhlb-c5zCDYC)>1> zSIGn0ZBPAT129~K8q^sm**Jr!`^REN#ReRDFl zE&+x>MIG<%ugTXL*)Da3MsIr+v{>@&K3%Ep4;pu~uTgT?Q1aew5Brm2D&FQV91fIU zm-09;<6{$R!_KxTGp}w4?n_@B6~-a7`B^(pU>a+!pz6!ZD>#+<=13iQb$xmK>3!1G zW^Y@u`|=|LBLjy+04NEti}`36G%z$VO31bR2zYdWkx9;Niig4DhF%_K9*LELi%#|_ z+e@i57&tIaVhKLwV!439W12Ac4H3=F&)uh+g>xNwIcfR%#jdSF3Rzz?f+jfg9`ms* zU3RfGa4FYE}K8wCby E02K#sdH?_b literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/hopeful.gif b/images/mood/neko/kaokitty/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..3feac74222c4908827f3c62887aa15ac7f986eae GIT binary patch literal 1756 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0yrK*MQ3Q4=ToUfX1hS%0r-fJY2^`2UZJ$LI=m@cHSyHxkwqzu-c z)aV88qBrnd_S*V-vtIZPgQsP(HA3$_4z{dhD$7`~k#Q$GpFm&DrHzd{ymoGiJ#%AI z>&mZpm zA9rrg&f;c9MnnLxGq5vAGROi0;1o&#>@a9>Zex~ZQ;=|IIMT+a8ziG};E_vljT%bovA2Nab?nw-8ScB5d-5S1}1?WnVSxrnPw;Z?#Rl^PZ;LgH_p@Xx~Oq! ziI=;OY1O6!!3+H5-9#d%9=N(VE;{Q@*VolomnVA{*=Bux9=Xxwx>M^cv*mYo+8>v? zk?ruLk-6f3(Ua_kH)oc|UlzLedfVGGM_ad-9l5hp3WEa-jC_i2AsvMcZjEB> zF*P2OmM~0|(-sn#DY(?TNu6EbhsA^gKHaP_i_UmnP&>M63LLZ!8xaIKN1@^wE^cOD_VKsLQ*(dHF>% zWTmQWl&{PoA@pxsmO@TK2XW&(CSe?rS(T-M?`ZzVezg*I7BGXS;FcF)shrertcd JJJ`Tr4FCvLr*QxP literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/horny.gif b/images/mood/neko/kaokitty/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..493acd1801f24b83ea272f8c28cc66517eb23ef7 GIT binary patch literal 1882 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

O^>%G0%XIUw11iG}lC zQ`jv@#vrCd`RJ>Ac5X>OFwt}OvYRHkmnSmtNb|0qy&>kFee?IQleb@f=sC`=wp{n~ zg5WzB7JHY!nDzNf)7A9&^KpN7IlNoOvA0{^f8U-j4Tzv&XJBEFWKaMG%^S3!NoZi; zQ#7m5aAuWe&3IMG$xRH5)0v(4d~Qy1 zXq?K-E+Wwty!7HkyLKi~ivtW7Cps_I%C)?5Ac(#Qx4ef?D{WK)X! zraM+&4m7UITfB-_>uW>f_R{xmOFhk3MenJ5Y`0cYq9FR9+1W*|r>DP6+EgRx;bvgs z$h2izyPunY$;$X+-saxVeobGUan7-~&$ep9+Mspo>ZN+_eqQE%V{@YX(z(&ELf7m_ zm$vO~D0Onqt+&$ zpUidG$&|X{s@By@F4ps=os`;o{g7Alt~iU`Z=)_P&V0V^#P03y@9(p%XXA6&k@Db} zv9N!fp#nC~zZ$UE@7i{tkvZ@xTdwt&2F4x!*>0`fS09a@%0_u;4ORzqbE6nNJ5B7_0#iCEwuy literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/hot.gif b/images/mood/neko/kaokitty/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..2365e5dbaa577bcad31d16f6cd6290507d11e3e8 GIT binary patch literal 1943 zcmZ?wbhEHb)L_tH_|DF7;J|@qMa7xS%>SobefjV3zb^OxvFZQ+|99!S=_4$hoSe)s z3PwX<_=bSue{Mh5kYH!W09PYD17=2`PZj^kx@V?2m1gFoq!uX{=$R@cRVqZ5r4}m$ zWTuy;zNI1a2$Y8PP&5TbfrzXlVvq(53EcKqO&B-%Cb5mjila1vila;|5 z{tFD`r8F2!96Xt<7S5V-@`}Ux4z^8ZPft$G3R~^TEOSBY^Xka;YHm_0NRp%>a>c6)CYnbRAiPF4V^9;*dt)=p=pJ%Us zckZ-F+5Kk)v%mXgO~@*Kd7@Q*`MJHjzrTMVd$?PD#ezMRtdH5}#mCp#{Qmy({&s)= z{rmp@zQW9e2rqU9CI(3cC17~{Mh-6)fds|Ft-QQ$A{K#442(={ZgV;eA3OFi+pwLu z@$pf^1R+o`H9Ya0pu))$5NYVZI7^XrgN>%J^4Zxe%n}*}#j4&jS*lj4WGz_MxZE|< zEB4ox%nQr`p<#Eut{!Nd#lDa0uGhBAh7AeFr^QxpTXt(}ir@_1UuKR?o66=Z1xRjj zxXQx*E{|15f-#`CZvHLNKj!Nh51R^0NBB(p^!Tud>S5jPnG2ttjkdncviIADkQMWt z)u(mMD0$HteBZAu#o?lp~-|uI; z>+`D{OV!Wh-A!=779Kx=;UOZC08Bru{7NP>3Kkw}WK!buxe<_bxS5HKM}R>=$-Pt7 zyvRjD;Q#}Zyld7Uj|7L4-Hcp&dMbjFy=UpC8kqz*q&4)gM6q3s*tDE+2HT`xH7B=Z zTw2V-uc7;M%c@{z_5`^TQVUjHU!uA_>+P?tZ!WIkIXUZV*8>fot!zRnKeWs>nu{nfAi&d!$Dn0VACQ7rCvslmaMQ&vZ@2^bfrcIi(|`j&M? z_ulDw^P}>(%=J<>_2?1=O@o5mG4zYJ(ELzQC8+MBU6GioWH3Nf+*AEWWWwWWxSx|8G zSjYdMm^0<8Q`)9zr(az?^G*E90OM#r9npg4XGNAzYV|2wl>|%_alk}T7J9Q%@z#{y l-HV*B@08_|_X8%1$0sK8`=7Jf`SIC>sp>uN?f?^oH30Wb?g{_^ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/hungry.gif b/images/mood/neko/kaokitty/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..24dda691b0cb71009fcc1672766cd83e96789967 GIT binary patch literal 2537 zcmZ?wbhEHb)L_tH_|C&{;J|_8>^XC`{y%r`|F>`73=Iu$-@cukocw?5|DNijm-qks zKl4AsC>RZaVHyI8|GE8KLxPzLCpIiR+%BN(HOFJ) zqNCls%o#N+3=bS(V6xJCBk}1m1EZp?(v^;)hEpAkY$tqfZdCK0sb?=VW2NBo^Rt;b z_OwVeG+dZrH+h$iR)~7g(tvKhr$0opLZ+HYemfGmpyARw3-hqED+N@-nc`~29J)6@ zxv`S%?5Q`irfEmaW4PBRlCb^Vo!#oTuXImeUv+g-WpNGXqT$Qr5pOp4 zR0#v)A~9xx9a$x-t}l#QZ};}s)-_>kM3+vB+kQDGV9_F6;SGNWMC7Li#ahN@lZRjvRREs;3C&1PNS?V6(1KNLWO}b z$mq_Bz|`XmOhIfN8ph8~Ffg+mnX}Vi={ZIl{YNqrf|ms@X6j(t>)G(aZ)rfSkgC9y zBnGCCcBi|ugt9|B!?)(ia!=7ZyqGC?QmpqC)u@f$S2wAy7Frjx)Hv~+YWC%Iu~R%d z#Uu?0#!~hGP%^b>@a-V zFjat=XU57)i_cCoj&D+NC{8{%--2DB;pW5x0W<9<@8e0Bvch?p$5gLYuS?4u<_B%o z3zaB+=Dx<5TO>fsO#OIEY-!t>$c6(q=I7pDR1#(IHk>i%^r5TP)3Yz_u6)||G<(wO zP=@TSUb-^E>ywuDFiOmr^P%A>bA`Chg;kPIQyV8cPcD&}k$=8%VX*w38q1Xt2bm+} zJsftI<*w88boS#6ZhU`#|LSLcvwp8}cyK~`+nLxodJMO>Ti+|G`etLd!xr6{}03q_zXv#q;kP!hh!V4N}01LJlv;Y7A literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/hungry2.gif b/images/mood/neko/kaokitty/hungry2.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e60e1bd8f4a371f519fa761a3d30ccf8d33ac74 GIT binary patch literal 2285 zcmeH{`#02i7{@=~`7$$dNiv#>nsLizXk6DNR!uI0axIEl8HUkBjY}fC-%&|tl*>fM zt!cWsmP>;}YAUtFU|otrj0#~nUCy$nnjL#~kM>{K)AQr!e13Vo->>I!rMlSI9x?z1 z;14+<5{YPsi;9HOu2HFM%*@PaG@6trrAz662c&em6o8!M10SW<@1^AyfX7>Y_&(ng z_@5*|lq&9a_V=S~_jWcnCBu*mi}+Q`l|kPT&tQgyvj}8UD?;cA!oGy?Sb{erB0fA0 z5SQc>%w-=*%NZ>15x@=u2&?H<&3|wTyVfYUt@_HNv#L7oMQ$~M#~fui@?@!*s1=~> zOlR@$Cjdlr(C$xXAy3mGberc;jlKuZ^hdS)vNbom3t{Zt(|82w$#>*7k&OJe_+Izs zsJvNJkLoW|N!~AP^3iUq+Ut>oL+X&BYjnjibwzHar!Xqz;Q@}-)u3wXkXj4pQuIz3 zQOlrl@ zUrmBYvh%cxy~-k%g-|oq{L(CKeF-Qz1vN|EqrJqALSu~TVrdAwn`aLXYew}F*~O^j zuNjTp(msJ3WN@Izd#dl|YOZfp63)2&6t3BBAfH^>j*2`hFcIaD+#u3WZHr;UT)-*% zInU0(8DfO$f3y-p_2q@RD`8n5}6#^hyU6Umz zA%flD`$_}bWF7Gmik;jf_P8`Nawo+PmDltPIRr zQQ}qYx@|V2U%AAK?yOx;J?kjG^V+LlkJeGLtGRwIqsYFa>x+%`d`I(%txDK$iT`c* z-M0;U;`!q{Qk7u?B?3Y6Fder=Mb+C!`(c_UCh@ZkKkV0ZgY9|h`^ei<*$_6L*;sqy zDJ18DN?ZUBJb+m&x|Dh+jDoUNa6|ya7Ufeo?l_)5!3*nf*`?TM;L0AE!mQ$VdkBG8 zFZqnzf@5R8=}{gU`5tl6?A#+_!I|~PMI+5tQpo@#OY%Z+V)X{cU<-}B$0hOb|U-sSj z^kUC~_}*#GhUiFs4J5>0=wuPBc`eksl zh5P4ghDDj50H5uMb3YdHq>SpYAE#P}1Y9|&*xFx^Gvi(p8Y9r^=qEiZ3`=fG3G(B! zo6(J%Y!>3Sy4^+Br_LE&B#kwP+#lVhnOH%+Nu1CiEhRGB%2ye>-s|L!dvva$aQ3$0 UZ$IkIpk8&UN{XLIg&<)67ae4VZU6uP literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/hyper.gif b/images/mood/neko/kaokitty/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..c33e89fd32b63cf0fcfd3305e21f3b75ad968f04 GIT binary patch literal 1312 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPEd&GfCx}NV&Hhrz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN z6@~|nFfdu^y^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MBz#|Y^QgL@bi(W_hH>+RROQ#ngfDw` zGABC9HS&kD$HlC`wxb*ks+pHoNAhpc4BGbg_KxD$%YI0jyt_9kpZWS9=^yVNpO~y| zE+K&MJ39kAgCv72(C=rF{4U3HARy7Pjgf;*fZ?K|OP3Hk#{vmK#lyYKR$M#=3sl@Y zH0-DGXijYKY|~C&CF9_r(!juyHL2&MvC6qwy5-+wx-P4oS?E#gC1SO}p>dvHxS5Pa zVJah&e{$T}RTozuI5~tm*c*xR(kT<#@%fDv;r20<(}Lt z^-(J0wD8*-)0tWC>(*2>JUW=`sB~B2`UCfq+M52M6*E5_JIm+3j74_WmY0_~^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w`3{2y=Qd_pHU$ZXh9hl!xK2K@r>W-_2G^~xm(Ux%H+|JMgH%3*H#r| zU6p2L!sfgEw2HT&`TWXVHNS!vUzx_b>DQU41xv3^3T7{PYgN1^d`aTUc}r)6=^pQA zdn6@L`QX5%T{2Ilc0`G-KEJ-|ao$xc;}3BwWv7?@$udZ}eKb(iD(;P7(vhhXb+i34 WBGx@U*CyH|r(0EWr^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aX$D3P8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCL^y>#jhh6Klh~t3(;ZRz=K6Ijv^vZL&6MPLAcS z+G?TKPRtd&XLPj{);De}dF}P3`@8PL{mId7u9@O$9!Co#&Hw$7So(CG1othGnL9T> zKfl1a+^$E$By<0Ke_^xQs4cIrZ%EeX;XwG0oq?S}l0g>ezl})#ljAuMkm%UP$iXJS za8c2vONgCgfrOyq;a+AdE*^sgD()Q`_S1MYCpLJtX(z9ead1#+U|`9b)N|5U<=iaY z@^3O-m(|WJ^r-a`nKdQ-aHH^SzM~wW4OixcxJT`kGJbt_ZA`oui}bWrjhop{c!@S# zbGW)e%5|IV>C$z#S1C-)`|_(G>E6`p`C5N=m~ZfHHxK4=JF{csx~ice2Z M)1PlEA;4e_0Oe)NZvX%Q literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/index.html b/images/mood/neko/kaokitty/index.html new file mode 100644 index 0000000..5a850b6 --- /dev/null +++ b/images/mood/neko/kaokitty/index.html @@ -0,0 +1,182 @@ + + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
accomplished.gif
aggravated.gif
amused.gif
angry.gif
annoyed.gif
anxious.gif
apathetic.gif
artistic.gif
awake.gif
bitchy.gif
blah.gif
blank.gif
bored.gif
bouncey.gif
busy.gif
calm.gif
cheerful.gif
chipper.gif
cold.gif
complacent.gif
confused.gif
contemplative.gif
content.gif
cranky.gif
crappy.gif
crazy.gif
creative.gif
crushed.gif
curious.gif
cynical.gif
defensive.gif
depressed.gif
determined.gif
devious.gif
dirty.gif
disappointed.gif
discontent.gif
distressed.gif
ditzy.gif
dorky.gif
drained.gif
drunk.gif
ecstatic.gif
eh.gif
embarassed.gif
energetic.gif
enraged.gif
enthralled.gif
envious.gif
exanimate.gif
exausted.gif
excited.gif
flirty.gif
frustrated.gif
full.gif
geeky.gif
giddy.gif
giggly.gif
gloomy.gif
good.gif
grateful.gif
groggy.gif
grumpy.gif
guilty.gif
happy.gif
high.gif
hopeful.gif
horny.gif
hot.gif
hungry.gif
hungry2.gif
hyper.gif
impressed.gif
indescribable.gif
indifferent.gif
infuriated.gif
intimidated.gif
irate.gif
irritated.gif
jubilant.gif
kiss.gif
kisses.gif
lazy.gif
lethargic.gif
listless.gif
lonely.gif
love.gif
loved.gif
mad.gif
melancholy.gif
mellow.gif
mischievous.gif
moody.gif
morose.gif
musical.gif
naughty.gif
nauseated.gif
nerdy.gif
nostalgic.gif
numb.gif
okay.gif
optimistic.gif
peaceful.gif
pensive.gif
pessimistic.gif
pissed.gif
pleased.gif
predatory.gif
productive.gif
quiet.gif
quixotic.gif
recumbent.gif
refreshed.gif
rejected.gif
rejuvenated.gif
relaxed.gif
relieved.gif
restless.gif
rushed.gif
sad.gif
satisfied.gif
scared.gif
shocked.gif
sick.gif
silly.gif
singing.gif
sleepy.gif
snow.gif
sore.gif
stressed.gif
suprised.gif
sympathetic.gif
thankful.gif
thirsty.gif
thoughtful.gif
tired.gif
touched.gif
uncomfortable.gif
weird.gif
working.gif
worried.gif
diff --git a/images/mood/neko/kaokitty/indifferent.gif b/images/mood/neko/kaokitty/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/infuriated.gif b/images/mood/neko/kaokitty/infuriated.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1c2789b2938fd62556b2422f2a13121c24e9c57 GIT binary patch literal 1447 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLi zH4+;a9q*QM3|jKyqSDD;8Ski^8Agv?rWz!l;&BjGJIi3i$|g{-`H}BDOGXw6g$8xM z7L#s13#;OW;Kk;P)k=3=Nx#y_$YHb8bL;CXj4U&}uHM|bDu5}mT}#{#q@p_l7i&<6pKj^G=gTaFxr7zEkYVBxvxUD5yi*3#4Rep@koHlw3W@=qH zWh?ql=FN^Z$%p2rC$;U_`Q_Sz#WzoVJ7bde=H{m0)h?Ys4=~=@*SY9S6D6T(Q`$_#elLc(*ll}Jh$<{coynl9e{P}%*e}8|q(7jy0 z{>SfMrysVrtlPi;|9^&A;sVGa$H<`0po|uBS}`XA7B)7rDLJux2uL{E#;$F5$HQ=u zOP7RT)*FjYkB&}|^soBUVWjLbO-6Uy9M8)M4YL*V*=9&OG@NU-s{JIRaNxOLi#agl zx{MAqEO#sQ^8Hn!>CY69A9mNPl!0-XC1*|PuB~q_F(e&Ka`7&6VBDOydehUJ-(KEc zTmE!a?uxBB_x4m(ay58ctbVYHRp@tU&W=?7BZVK`)OJmO`1nvktCd`inc;&~vkceC z)I4a2JzwrE9J{k}^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/irate.gif b/images/mood/neko/kaokitty/irate.gif new file mode 100644 index 0000000000000000000000000000000000000000..06ee36f9991a85466b20bf28443372f15d2f929f GIT binary patch literal 1798 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!cUStNwq#`gTp8#W$B_Ux!V>274 zn#_p}3l232@GFI!C`fc^7Z4B2c@ePSNT;-^m(Puj$tNajNU}xD-1O)agBI(aoS#9< zPBAj29J1MI^t@p%6Ely*s?SR=&U3C`rQ%SMdTF@_y8r{10z>0Ur}n|tn?Xz6Y<5y!*IDrQkx7Gkne5!5$ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/irritated.gif b/images/mood/neko/kaokitty/irritated.gif new file mode 100644 index 0000000000000000000000000000000000000000..aca255cbb7f8231982a5026a6adb02824d4b4dcb GIT binary patch literal 1297 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a0|rJ88IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>X#TN1V1Q#E;FfVYLneT;V9@jP`pPuJCJ1On#rhN0hwX=)z?rv@7miN1p;DGQn zI|Dm|B!eu_(?^j!Eyr^pAkndnk%LWu;i95Tmk>M00trFI!@bN_Ts#H~RNOl>?5FW) zPHgaO(@tI`Bz2&Zx45NU(Bmn^&$E3u_>~BJ~JaXKR>@fP-)%oN|U74Wx^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3RobPdvdST zN2!d{!f$U(XJ);xTT{{S=wPm+(p`z`58O{`Yx;*)%=~ohET8)_7TH}}US8&qe{8z; z*TzHFHpCy^S8bqx&4(u$7#TPm0zh%gE@mR(z;KX(Q_!xY!r%Y{BcGyMNJn9VTca3z zOpV8+B@7egw1os_3NH0-QfC+VVKL#rnF)HuLR&nI51g6f5Pxn>hjGS*R)uac4Tcg; zuO-aMd>Rf7E4^2Rxra^JWwQFjIt@*uC$GL_MXpWmT_wsLwCdKJB;FII1)mNuZY|S4 zXFB1Vme=|W#y3-E3$HnSu;zG~N!P?&ry1RclUjBO7Ck;`VlJdRGjj9u^9!82<$R?~ z9vxZa|DJbkRYBHOX=WyDzB^2l_?tB){cxl3Y`&u$p$ASeMN}r~ZkY7SW3}qeqF&8y zs{=O#C0Fh3G<)ma$o5ET!zu^IOS`0=O08J+Rm*>U)#I$QQpO+dtx}kn7xTLy>Crmr o`C5N=RBTLXR}Q{)THpgaCsz0Ms0n`Tzg` literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/kiss.gif b/images/mood/neko/kaokitty/kiss.gif new file mode 100644 index 0000000000000000000000000000000000000000..338ed7d9dc03cbee47cfb845f13ee22087c2cf8c GIT binary patch literal 1294 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/lazy.gif b/images/mood/neko/kaokitty/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/love.gif b/images/mood/neko/kaokitty/love.gif new file mode 100644 index 0000000000000000000000000000000000000000..d01fd9db406be6b371bb91433f021a7916be5500 GIT binary patch literal 532 zcmZ?wbhEHb)L_tH_{`4$1jfe3X=!OQ85m}!%{(*n|9>Dl^B)&b{Lk&@8WQa67~pE8 zXTZz|)UWtY);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+obX(|*CIHm<9fq!L4{+o#}};9*tIQoW})lFdl|B)_dNK|G_Szpj*Xn$oJ++j zqW-5|oQ+%)wf@GMvS`HvE(sfWU1imRnYT=d5p#-tz5Z)2*OoWiW3MfKUB9Ej)}h&< zv8}zMvr{Rr-X+eoPprl)*M^1PGTov^!y|M?Tw(Bh|3%t5x|x|d3z9R|m~UjSN?X6U z$l1Y+jV*icmewW*3&vv>EyX6=w@jQ?op`?M@)e<$=JxA$SMNj$V)M;@h;Lq>HCJ@k z=sH|5<diWNYPrK&zQsV_oIbmy zW8TWQ?iDt6XRaT&VcX@T`dm}5ebW7xe-_p*?@Cb$t%+?Bvu^LOZ0+vp?dzW)lAt}= zfjvY^B3Q3^3cpi^Pq1RTXR2eB^73UX)QU=qX67ju6=*chmGxd}vQx@hkB!YhpOO90 kbZhetWg}yyj=^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJL4b1F(Y9=Q(EOc(-P_~<6A+XS?O~_Df zi-n<*do#Cb+M6E}lMYT4ah}DpbJJ4q$&5+cdL$n#J;1<};kRVwWwizdW|k*wZW=7R zz~~asBr7mwS@3eE8A@Lz8yGGx4B9M}>ZP#q^s3nDX|mFj9l}?|9$$5}>RQ^Ftpzhr zm1vhaG%{tq_nN!fMC&pW%ZD^pogJE?`^&!ah2`APeYCsvztOvw7J4zKYIWBi-E*lS zojFkOn5gc9&5fs;m%8P>xwPf^#tFxF*}eVoB6VS0?Y|?L(W@>j+$AaX_wVfdf`|US z^6}^P?EL)vg73LyvbDQ1UtEg~-!8Xz_xJY?n48&I5TU{X3>7&B6=0}*hJ?z3gUw9* zG7Jj@79MWo74^#bapB>SRw3=MGcy7fA8VC!?(*pnd~%{$+&^lGg;9g|6!uuQ0tttP zGhIfxmt+(UJo9PMtLFP5S=ILwy<)8z7y_FaIU;x!wyqAG9<^TV z%&DuZZ!QeWoMxN-P4&W7W-gHrTGLnFp20LjOu-=h)xCW-M}^j`+`caUaAW2(Q!R0W zqD z4-dBUife^vOiVi3!eQuCBJpwI(OyC8C=-cIDNd6$0@)&F3LQAbAjr&75&7xqnHkJ1 zXIgF+EIr3)BgrP=Q1blrV!KYJUe5(Dyp{$`=2H+TNn~IOX?MEI^+hXmS=7$1y-`~q z1aHjPeT>I?fdk{Zys4YsXgXvvGUYG4cXsw>9mknvk6(%2F;9zKl=o9ft!8pw)Rx{> zxw<{3Mvlxgc(2&bn6|m$44cgBtMJaq9lsrL+Fc34d{O-jb__V))OX12Pq4z60|X zj$L>D8EkTFn|k0L(qjfo-Mo1_PtUNa+&O2`oBDd``^VwTw!){1A3cb$Kh}C6=h-BXM|yiorm0>kvxo^=>RoQl zEycwCSZ!_O-!lmttSyuB+O*Vmo+>}`uR*`IxuvzOy~9gEF~U@$s=BLeq9`-FyLqBx zTz;I3Y8KnHDI)RZ=_}H+y3JIa7Ou)FUR$_zv!bC2E9=(XT86p}3o0ZVN=nz|PH47S z)7jQ|tmdN8`D+1K{c-^oDY1?n0@Ic@iv+q!$~dl^ml@e9ojxxy;`C?qAO2kfylINW+Ems=A*1;t?rPZX~?EXU}i+^-q1p^y2+gte&KGgc(62j4ML1+pJPSz+0ud2RXi&XPW}!Yk7Ls1YmqE rSeaG4rf|z9aC~jq1&Xiv;P_gbTQw!fW;HOvj@DdkI)BZRlffDQ?+<+r literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/melancholy.gif b/images/mood/neko/kaokitty/melancholy.gif new file mode 100644 index 0000000000000000000000000000000000000000..00aec28b8ac47ace1469bb0aa92711a3c162abbe GIT binary patch literal 1292 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/mellow.gif b/images/mood/neko/kaokitty/mellow.gif new file mode 100644 index 0000000000000000000000000000000000000000..72b8e4becef7cc1745ccc7bda9d56ec77e651481 GIT binary patch literal 1832 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M44z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wyT8;OXDhLWon2Y5{YCS>?8kp{4Su}16EZP5X5WP3^k>X- zt=sqtvP~CzT1CQ_jv;N_;kFhVY7u z)0`!L*<@W=7&Mu6k=PH-(yR-eimTn0t}M-RYm407^>tP8gR|>mw&v+*e|XlgDrD)Y zBd5N+2ybHhB*jtrfZ_5!>90}@-cw(n-(A5f-H|woJSMSMB%bn*sw@c+j6r?mRXDxH;{dG~pu|IhJ zp)*ojm4esA9G>;Zs^N9m3J?1>7t7FBm$%rbt35sWc|qfDHXAt$gYOJ6n+#V@Q;iZ* zjN6mP+HX^HJ;`l~v%Iuy^oNgrCnvuadh^5LanQ0^{j;{bGT3tD^3u*lak{^ZUtiyl zte$cw;+w;*p4`XFa-|RCF|S}|LiMjSIF@f9$FdAGmL-s5S?N%l40}b3#e$T^$*f9d zE|CkCoakg>+hFsuD9xKmSyD(LVe|4+bC{SPY>E7w!Z2O6(afY%XyutHepBU2y+pNw zmNKod(rqx#a_n-AR&xDWoD??MX!|9dnIB(At}VFjRKq=eRSW|#mQPeYaJUPK<$~Q? zmt6+Ma)9==rH>BgIUjqfaaGCVq@HEjpI4#>QqN9lWP2;~W%=Re;MlG@i(gu=`?Waj XuKkXB@a8yw{_AsVt=}JPV6X-Nv_Hjn literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/mischievous.gif b/images/mood/neko/kaokitty/mischievous.gif new file mode 100644 index 0000000000000000000000000000000000000000..fc0097e9a45d7938aa0205bc3ebf8b5282a9d974 GIT binary patch literal 2011 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

)ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%JY#qGnpfRi`P=8!L|EjVuAJRfb}J&| zW%Gi?*Hv>r72lnIWAW-WuS2Tc-ZLv5yqv=|_s@yXFD|>A)Wz63e%pSRyG1|dU(Jti zpI_fUf4|lN5oqiTEDVYa3fKb8xsj1cr02(n1Q$jo6{jN}8y_8DkTk7h(cJW~VX}g8 z)RT%LhQo|3QL9WiHl?1K&dPB_Cg9U!&$+BIdNKhEUYwieQ7^{(>r%tT$=-{#bQ2s_ z9Aac!C1fj5s(F1ubCrV6wOD&5aKpEwEZ_f80ha@6t=Y zjm>dhwK_rfIrt}4u`t~G{^Qe&^NY>@8YtilAq@iuh9(9crI-^F7C168@rkvp*s$cFq-jKMa?dUO`ifNfiN7|>l9eruIHg!$6aFE!F z??t!H%;Hp%=w--gVwva9tlE1(@!_Jr<3_BxVG6G=PI!JVFV=c}z-edJ$9L}Rw77P% znNxoK$vqZc=Z?2q)!Wr3l+JW|m{xyo@9yvKWd+MWv*}0KWPaLqcC*|3xINz+aE1|b z)}u`->OHkpwRra_-grdrijyKt8Q->HavI7Yg@kG4hAJI zu@l=5+}PbFY`=BIwRiSM`tRQJvEHyDe%)ksvwc2hpFJ8moRl?YDKy@{^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!cTF z2hL2;D;C<~X?(zE3TsgpkJhDh|2fXZLasXnR4y$Ei2v53xkc;rN(XKo*;S&du5BUB zd9n)Ew8K`1?QdGrW%fLrxqx?$O#y@M-R?r(hTPZRlH+!G?cVigwRn#ErYP3rkl6yy x64y)2&U><>V&jvOJl=7~&g|U${QLsvZaa@1AD&;Tv|aqKTI%buhLIA3)&RXGIwAl7 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/morose.gif b/images/mood/neko/kaokitty/morose.gif new file mode 100644 index 0000000000000000000000000000000000000000..00aec28b8ac47ace1469bb0aa92711a3c162abbe GIT binary patch literal 1292 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/musical.gif b/images/mood/neko/kaokitty/musical.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c4fa9c48a78db43adef3babccbffdfb842d0531 GIT binary patch literal 1430 zcmZ?wbhEHb)L_tH_|Cxa|Ns9v$#V=14gb&ipPZch|J;8D28MHUK;$SG4S``F0*e2+ z{aizWogD*Qjr0td8G#;F{3q+4ndVfQnUj)Qq+p3J)<1fR1P8p944;&a6c(h_p6eJ#M6OdJ^(GXa8uv0`?tY*f=N5{IP z^wqwcxS(`$f~b31NJf$Bsp$ryY%@BG(i&#`XOh{#dGVRw97Zmg8Zy@ zu;T1;e|{5RE)j>|MZufpa=9E{o@U@kPm{e}l6GU2&&gG+ueYW}ZOy*jCc-VQcXo!= z>qCD#!?S`J8;&!H8BBd2w4aqj_}r=;8)AAZzfLm!Bf2qVt!?E$(`ulaMNC`g4cJpRlMb!^IG)nz1U&`6t4nh{=a-$VHY+$6-~Ihtu8GN~6>fpwzwG>y{rQyH>!5tO k*s8L(A!7Tx<^Agx7u|aLe{Q&5-QM3H-=#0-;b5=^0Buz@TmS$7 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/naughty.gif b/images/mood/neko/kaokitty/naughty.gif new file mode 100644 index 0000000000000000000000000000000000000000..f23b53ff1f1ba4c0c77984707462233b54c944cb GIT binary patch literal 2013 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

)ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%JY#qGnpfRi`P=8!L|EjVuAJRfb}J&| zW%Gi?*Hv>r72lnIWAW-WuS2Tc-ZLv5yqv=|_s@yXFD|>A)Wz63e%pSRyG1|dU(Jti zpI_fUf4|lN5oqiTEDVYa3fKb8xsj1cr02(n1Q$jo6{jN}8y_8DkTk7h(cJW~VX}g8 z)RT%LhQo|3QL9WiHl?1K&dPB_Cg9U!&$+BIdNKhEUYwieQ7^{(>r%tT$=-{#bQ2s_ z9Aac!C1fj5s(F1ubCrV6wOD&5aKpEwEZ_f80ha@6t=Y zjm>dhwK_rfIrt}4u`t~G{^Qe&^NY>@8YtilAq@iuh9(9crI-^F7C168@rkvp*s$cFq-jKMa?dUO`ifNfiN7|>l9eruIHg!$6aFE!F z??t!H%;Hp%=w--gVwva9tlE1(@!_Jr<3_BxVG6G=PI!JVFV=c}z-edJ$9L}Rw77P% znNxoK$vqZc=Z?2q)!Wr3l+JW|m{xyo@9yvKWd+MWv*}0KWPaLqcC*|3xINz+aE1|b z)}u)(;$xpL1ulU>fQ=T7&U-#5j) YX^9*!W5sjXx;;NXJ#)9`;b5=^0Osi!G5`Po literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/nauseated.gif b/images/mood/neko/kaokitty/nauseated.gif new file mode 100644 index 0000000000000000000000000000000000000000..6fdaa09904c67169f3b25f9e3cd3a8daa30761ef GIT binary patch literal 796 zcmZ?wbhEHb)L_tH_{73+;J|^jnQ1fspE>jY%>V!Yjg5`d($bQXlNJAS`?-b$J39ur z8tEA@GcqtRDE^am&rEYF&CE$jEmAPhGgU~cRER7~EmjD~OfO9>VNm?Z!f6Clr~|}6 z(=`|zm^X6ly7SLqlS0$f1D6^UWfL4l5;P|zTy>qI(31A5D7*H~kHGge_JSGo7_%WrqY1Rri-Z|;|l^oNfVtz>8ICcEV zKg-&t=9bnrDeI2({3spWRDVVm%_Ns{1;>ew#nWb{N2uj3R88|N%FW51GO=h*WVNiN zzFx`}rbe^+m5Z1g0?N0PR5iscZ99H~uc5yAwE4*k!JG(RurshTNHWL*eK8g2i+7DJ zj;r??t~lH;ai~00@rJDbD!pKdjF-`eycGCc>z=ZD8gH7Us#39*VR?%C*I%-;9hjC{ zNS@RXN|?In_E!zJYq>6L2dCW2cRiWo)X%+C#;-qcuE5Rw>hj(B)ht5MsrpUTEvXXK z=BzAPG5vN9y|JP;lasnqU3txBi_aBsiJ2a(=WpiXl32PG3w%rFUk(w@KKMcvq|~aFrWlBIi{LgCf8;>B3|t1YAAl&9-Q^mZv%iez`qpPC{ele1Ve%O^LYVEu-T{6*{=wiF9sb?gL+ zg0=L>Qi;gz?^f*ad{-i-x|!2fZ%V;-8@E!Yl>NDL&+dE5DHI*6-%#0^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a4+cgK8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>1UV%xK(D!giQbfQUQ9z%aLL_G71t*{h!seUFcx*{wWOChIcho9m5yPg$^=Y~dg%4b| zgwJ1>YaQfpWm(0?OM5fJ^R6w6H7zr7xY2NznZ0VA%bJZF7`NAcz8C9x-7s-+y?0a{ zkK~f1Ug=!BIWJ}wWnAR;%#Yc7b>ZzPYhzE(^R<5X?9k@?{IC_f&EMZ^;b&vP=HXim zj0_wO0if7t7c-G?U^vLYDQH(xVQ_$fkx$Vrq@%FGtx=3Urp9B^5{8L#+Cl;|1($j^ zsk00Gu$XY*%mlq+p)H=q2hK3EHi@0kELm}Wo>=>$5Uwjr1DE(Tn}uqLzHn-EauriB zFnJxe%2At(;dW`(RVES1zN=bWbHWy6I?hYE6|(yB#H5>HvA@jLHtuKhle3s``RRl1 z2Hq8_yG+vW9I5YoC(0SQ@m61JWYQANjf!bgB#iUcys-R|c5bobv^}$SZGC-xL-Of) zb2n^Cy|GPr|2baC@^`(AjM%(;jkfX2ur=l4Dt~D{m0OcnUtB1}YOq&o>YIojX7xVV zsBfCLmuI+hb==yLcXx;R^If&KuV_axH}IaZEm-i}>yQ+)w8!e}dUvN5iZcI;3jLIH yOo2E1PR8elN6t*JERXw9xj1tz-{oa4b3xwa)MYQzy}jwstsVJ~*=h_F7_0$7ytGmP literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/nostalgic.gif b/images/mood/neko/kaokitty/nostalgic.gif new file mode 100644 index 0000000000000000000000000000000000000000..85e4d9e201235a584e9a528b068a919ef8d4bba2 GIT binary patch literal 1888 zcmZ?wbhEHb)L<}T_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~adj>`h8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tc1sv% z-8r#w@$r5I=Pnt~Pe~1v`Tf~uNH{c{YSoI}B%^TPsaK17Hs20O!vhWT%|f}({w!Aa zW^(Wsi}fmDV4NqwEKu>Pc;(f(LG$I-S}izmb$(oV*3=auZ>}#&44ky~)mDcaOY?Ro zrD`(hHf~RNFE-V4o8FBb1&o(lW?jk;KUjbN)7#7+Z>}B{gFu^6`CV3tya`bfB4A|KzUH zW&s`rh2(?H(&}Y*EF2u%d%0b?BpQMe8W;`y)8=Rjsh#d+N%Grra`Q6=CS69Bf*q5W z2TpTtd{o1^`M||x2JLLRRtH`Nukdho(oLAEetlJ>>be}S1==^)DIdM{Bx~EN@VU~* zcjcbGmKHU=XuaHCZIktJ^D_D6Vk#dr+&iSo>ip*S^%t>6+55N2GE^4EPp34M%ULv382Ox#x^HF|C9&CYWpQ~`n&jk-k7xLJF4}TZvNWsJ)O$ML&WmsT zZ*47peedkn}Sb{x9PC=Et&Bt#b>6mW8R*b7n6_9 zwW(#&I3S$Zz#!2$DaLcc%d?$k-Eu8fL9ec?QrZ|L>S6jUaA_>JoUX=$*P$C3Pl?GW zELd}?(fu~x4atOt*zNJ3k8QQyuF$yK{U_Hw>js9{u0~evdEHkw+}~Bkt<#qyt{HoR zS;c?ZnFyVyOtV;<&)tz+$FPr;qor@nto2csSGadiJ3H;&%M)7)+w1Or{PyhR9^+sC z*8bS)+`gP&=EvGOZwuFCc8cHsap&Qqt7WUReYMMrZ$DsHdR$h1w@k^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*P z4X98D6h5GQ#K7^4fssSTW5a@j%^bp7F()=GJlrmz>@~+@jWD(F&3PZ! zwMJgoy0X{h_b*?r9Sa)|v)z)jcu@Y)^9b7wJ~f+i#V3b7->dDFnVEZJG;}esmc{spcHv)N` hkAa_on}G%BbrA-3h}Rieg~WVTY&hW5!pO*A4FGC+nWO*! literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/okay.gif b/images/mood/neko/kaokitty/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f57b0d5d791f4781c57d699ff916660ff93ad42 GIT binary patch literal 1746 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/optimistic.gif b/images/mood/neko/kaokitty/optimistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..341b988f7b0b1d9369167ff7b0e483953d3d4307 GIT binary patch literal 1756 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0yrK*MQ3Q4=ToUfX1hS%0r-fJY2^`2UZJ$LI=m@cHSyHxkwqzu-c z)aV88qBrnd_S*V-vtIZPgQsP(HA3$_4z{dhD$7`~k#Q$GpFm&DrHzd{ymoGiJ#%AI z>&mZpm zA9rrg&f;c9MnnLxGq5vAGROi0;1o&#>@a9>Zex~ZQ;=|IIMT+a8ziG};E_vljT%bovA2Nab?nw-8ScB5d-5S1}1?WnVSxrnPw;Z?#Rl^PZ;LgH_p@Xx~Oq! ziI=;OY1O6!!3+H5-9#d%9=N(VE;{Q@*VolomnVA{*=Bux9=Xxwx>M^cv*mYo+8>v? zk?ruLk-6f3(Ua_kH)oc|UlzLedfVGGM_ad-9l5hp3WEa-jC_i2AsvMcZjEB> zF*P2OmM~0|(-sn#DY(?TNu6EbhsA^gKHaP_i_UmnP&>M63LLZ!8xaIKN1@^wE^cOD_VKsLQ*(dHF>% zWTmQWl&{PoA@pxsmO@TK2XW&(CSe?rS(T-M?`ZzVezg*I7BGXS;FcF)shrertcd JJJ`Tr4FF_wr_=xd literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/peaceful.gif b/images/mood/neko/kaokitty/peaceful.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c1748eb5a68dd5cb4201a438f45bc0029f88f04 GIT binary patch literal 1832 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/pissed.gif b/images/mood/neko/kaokitty/pissed.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a9bec095271702ca0f25299bc778c42808927bb GIT binary patch literal 1918 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aHvn3l}+Hn$Hi`wSRAW(3>Kt%_cKIrDR6#%;K|6GwW(xg@pA7OcA2YKIzK;k zn6E$anTY3tr43A8@nRZY4(jLUg*OVVIJN1()oF32d0S5vtDaaKT3Hnuy)En1W=_+( zxzXFyTz2YluL<34o^oVjCFdJf?Hj6Ioec+H?Oj#={^5RCc9XO{H&({>O?+8bTVuXC zZQdMdDT!Q$=Z(y>{P_hOZZRaCpYPnAm)r2^0ppg~{qs1@)?c1EUH#q{o5^a&7Atp) zf3KGLdEwcG#oqJ%_9o@sy|jLN-@3VFWpA&tAMTd-zn9>E95U>{aFGRu%um#iDM)N+ z=Vi6y5!jf(z$h$hcO+tBLIWd{L6FOizyl2vWf^N^7>X8oPgjdvr1G*Tfq_YfRV3o% zrt}6TL(VfbD>p6o>11iC(@EH(e!1N<@Y58_uPT>T`t+tv)x45+xjkMrEZ6JXk}K;& z-J42xO z!b2(-0v#Bq>oAL~uxx1Xn(GkkrjjrvnQ@Nne5sTwlNWBi-i>ytJHIZz*dwAH*Xm`K z;ki+5YuVR`1==oK)H?Yz91`B%*(GOqsQ2_X-E-SwzrHKg5dRRr-}XFTpT>5bkb~Wl z)_UBP8yZiuWyx7QsMzdrhD}L4$0l+~(&+`fGTUZbZOJ&M@qE);%THfkuU7VaURNEx z@W`Frx!=nyCV&6%_{3ywU}#ikUq8!g$1Yo2_38z~nr=Q0Y=QBK(xl5k@SC2uC< z_*G9TgOnH-Xm@_9sSruMG|$ETo==p+%Z61(jkkJ!ZCP<@T|{}?+nuGE;VWa;cZG5V zCS6%Csd{XS*Yw3_XK~hU(m60)|O#Aj^I^v}?zrM@Ma>jZGYGHk@Q; z7fWV~yy@UIwOH}_9LbHwsrzdyXMOwgGwH^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/predatory.gif b/images/mood/neko/kaokitty/predatory.gif new file mode 100644 index 0000000000000000000000000000000000000000..c3193551d72f53bb7ed1e14790e9cf46e745fed2 GIT binary patch literal 2346 zcmeIxX*d*k9KiAa90rS7S8_Ka$2ex12`!Q#-_j zs{)*%=mjaUa=Uz}pJ*IE0WgXQ0`GHgI8KwV%AR`bs5eqhzK+z!O$F}?>AY-x!**9Q zS;2zI!YhY*%z_geiD4d*>Z7u;dUXSDQwG4>-MuN$uiQ;p{NB0ENRab zzfkaMu<5uG#WNxP)f|T!5>^)^a?^SUm&onCE?pKfT)A3N&)@8GEU7^?`#_^i$?`93 z{vQx>vTPcs<;QRw>u%%fe1D0PAm85xynq)-0l6K6o=*%K@$|!~FgXND(um%kio{Z6 zQEaYhvJ{Wt1_sZj=g2En^u$Ff5}_EIdZsRA20#@da1?!L#_*y_qTWnFRC!O4R${%D zrGQ0;y*M%@`8A z?g5K(kP=N#KQgU2(yht#j!3p73E#1};u9-Y(6Y1LPY4s^&B zFupuVVyhl07nic#DY?|ma!w56c{ieNRb@Fu&AWIs=qQXP#MGyuuu~ZkLV+VeBeUao zX`AajH}lb5rAm7hQZ^$aEKg?=EMu+3{HC*W#i*<&&IHnU4GTg17>iY2)8_=1$Cl zU8R%5+hOSg8XdRP^E(xnD8a)u`zAWYi*mu}`PhiaTB!jQkJ{ryi`dQI!rdFly1`oR z>lNJA%x(jNz@lo%9bTkXpT=M{qr+(#>ABDpxzJo@7_x?mSM<&>?Mjc{lCB@kY9v|0 zr7kUpJ@rg9T)W^}M`Lt22-x){=&o{_VbD(t|0S^X&%)MecsfXeNXjQ~*mK(CyC>73Cc*@)4 zu3TnrQAa$SB4o93At1(G) z)r>XhUEw-*NbN?JS~asf8M<;6XHQJ{y@W)CClb3veOiHc$@t}hiCWUFpWO~VD6D(4 zHtn_PdjHjU*zik)I4R%2Q}%tp>+?-2ru#g%zFS}XJk#ud97wyzzSeb=f{k;iaI8N#H7=AsTEw`IxGS&YmG9qK zZ`_73>TU!_*mN;<55d~klMIa#+mmG+C8K|Z;Qy0zUIdmJtyPDEDx+Ca0axhC*^ eb!Xl=w9Fg_->`gNl=p)?QeOvf=}HJVIQR#RGMd2v literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/productive.gif b/images/mood/neko/kaokitty/productive.gif new file mode 100644 index 0000000000000000000000000000000000000000..93bfaa4c14f1211e16890274a0be38ae1619a314 GIT binary patch literal 1187 zcmZ?wbhEHb)L_tH_{_|ZoIPjG*8k`3{RaX=L&N0c1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/quiet.gif b/images/mood/neko/kaokitty/quiet.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a3c12c97e12372d0924e63e8be57b478b7059fe GIT binary patch literal 1723 zcmZ?wbhEHb)L_tH_|Cxa|NsBw>^XC`{y%r`zoDUFa&q$jt^XND!DtAKj1W-#&+X?L z671|4;A*62z|08rwc(#)Kc)FK4~JyV6GN`=U>)MABz%=FUK5(dSeESyF_ zg*u=h0_7tHj(ZG@95Nmo794Em5Y~!0v0>rib^&FtIUXAq9qs02&Zt>oc;E;Fla<~Z ziBFFi7!_@mu5=VNoa$g?JK=M4qnh_jJ$t4ZD+QOIpKTQH6ms+O^1$gX_F}fDt}G7d zGo0z=y6TELBa{33M|U&?Rs5J3Hbn7uZ%zqkjNcj+TK#FI^LnH8UB1@Wb$qr2&%7nu zWxoF6US4hvJ%!5+jVs$y`Sc3RGJKcFR(i$gSiA~b%&1{(mu;z$b|ADqsmy!hX74i+ zoVQpuSZ#fMeM9nTzqOUcZ*FxbK3-NM{r%1T1I^s=5&{S>voo+WNHWL*y?hkO%W^yi z0umkD7&+Jk7%nQhbP2I@ERYaXJlxA{#l>T=K*ha7!+si%reK3-n|AUl9Zewz_Zf!8 zZF@8Ym!F$2nEmSyXNbnhsVp2Xe0FVmc%ajRQKQ$>;gwg9KdVBj*VNT+3!}W%=I)xR zb8TW`=RcclP&r{(77=NE`-&HG)sCF$Za-^G4=cO*Dq^VuN=Mg|Ut08nJIiTfX-msJ^=Z2A|eSQ$KHU}Bgc)!Q{m$$7c^(nV*YLe;~Tx*hCW^CCpU zf3?EtS*4j<8*Vcx@k$tIhd;T^6rMWi%Z~Cj2X^N*R~_M$cprMOyK+#m*l*2GfsM(>*krZKEQFT&o}L2q)|w3)qR-CbF6Wc2GRZv5 J%FM)I4FG;kai;(P literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/quixotic.gif b/images/mood/neko/kaokitty/quixotic.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca43109be40faaca819e0f62a74a2b5940ed21da GIT binary patch literal 1849 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aKL$n)8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raQl`s$XAc<9y(h&_;50`#blhp}+dhf8OFt=FFf=!Hv+4**uS}T0^ zJk2KZ|H|%ZYZK2!*Q)Ww+){XPs_y@(8rdkFQ2`<(2mL&+Xk^-pt5|93X8oPgjdv^hTnA!F!@k@u@v0CLK7_Wm>!L zisu(a#`&76zf?|zq@SHHrEWHNm+|7mi!8ZC5>|z#U0m%KnRRzn@tW}E3B~KKWCg1? zu2bKyB~x`RCvr!Lzfp~6=_~J9hQEcL-niJ1$gIXMBM@EIkTjv4SLNwVi`9OIT9u_0 ztfuLBpPi)M&a-C0mZsT?3;p&<6g6bBE>=`iJsIWj^2)08=$e_)+uz?mFuBQ2X3v9y z3rG94{ny{oVF;&Dh=a%`eOu$_#j!&4U~Q`cj6A_bQFwwji6^`5-6?Bqg^ zRJSWLh0+?CoaURUp8E3m#PWdTq`6$170$0_jXI{Ha8>K-dgg6ey3tb~UR>hryUvBP zJl(a0?UU4piU$Wm*E0V~x{|%%q0a%o zibj}eT-=;`W{&mrc^N@pUtQmje0rYm?rm?ICu`n5=ext~{juGZ>-jja`S>1kgxg3g zc<9u`%dEhopz!EWhp0NAKtSLlmo6r@3KNNhhLe4Q!Dc*}MJWdvSp3XPJU6SlPG*U5 zQkk$hv#>0M9)xr*lWeA z_U`xO*N;zji5D+fxnOhCWEo{+7RgJSnfheqwOsF7ZppZ+CA$jj}Lc0CP6UmH+?% literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/recumbent.gif b/images/mood/neko/kaokitty/recumbent.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/rejuvenated.gif b/images/mood/neko/kaokitty/rejuvenated.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cc6917ec766e8cb6038ed3ba9b101c357906850 GIT binary patch literal 2437 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 SdTR={yu7sRu^bNvgEas+ZiKu5 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/rushed.gif b/images/mood/neko/kaokitty/rushed.gif new file mode 100644 index 0000000000000000000000000000000000000000..83106ed425885561e9cd538b3e8b3a769e6aa02e GIT binary patch literal 1684 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a3I;|F8IKJM4mNWLYsH+{u<&rZfU?&dkBy5CFt8c1 zZTMl3e3(JOxl6`VNQI$a#$M{ij7f=Zz09m9=6G&ic6PRD^s753KPR7<$L7ld3WD8^8HThict!^m%;B zwQ6hb_1yyJUoGt{&+^yZBU{?#u{OKHkr&%_QKkY01gS8o~2ePHtLyxZxl_j&x_K8ohZn_1V=8rJeVBS5JR;xdGXcY{2l913L0O!jZy4 zJO=_29oraXlz0>v7CCo_s><;gI5-^b5Z2_9U@%fV(#B-T_o8Bx>fwpn-b@*m#Y=rB zFmkN8UJUtM*u$qyBTTo4$_itzc?Svwr;k zZMD`*PTxDw%q{P?XGg)6mA%Xk`)*o%zIbZBG#>|Y7_bAwKo%GV*O9^in92$g8`^nU z?RW$>CNMAx%i0}@n3&MO$Yc=YvLo<7!$eue8X1P7Mc&iZA{V`pXkhT3s8f7u&xuI~ z&UBg9uDjy-MUip7rs^-1Qz7YR=L^c4&D~|Z^3=kRZl~N6#@fMsp1b)p9Hwd9WU@TC zOr%?E?YV84+l@qCo4$*hURu1bC+f=q##MD2=RJusS)Z^|jC;TC>n$3I%M~N%rOJFN zxH4T_c|L2T^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/satisfied.gif b/images/mood/neko/kaokitty/satisfied.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb49f85416770c98f85d69dbdeb9e83ff572c68e GIT binary patch literal 1300 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhdz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6On>PFFldF(iAdx+5ZT~xeQjFdv@=#=YS%ZX?Em!VM%jVeOUj>b z+Ip&dZN$E?zg8v=HxArjX8)mN7kT5ry|pQmx#aHLV2Imkp>3UZ+sNS5vXH=QbAL*f zxK3N-+J4mI!ZMF*8~O@QH|qDz+$JI4YELB+$p%vM}H1`AZ&J2dR4@n}wL@SLQbyh_Hw zL8XC#CF@Yn$;pX+vn|R$$w+Nl=CaVG-Av|$!OF`^m02x(yC$x@GKrNfrFUlOYPSX9 zTg5(fmA*N(DsZ`wYqjy3TbpHhPnarvJ;1m|d;6`c7S|g>=f$0@lf4nHm$2E8`}bC^ yNw3^y^Q)WL{g(LTbW+;bxzxhwY1+93&fRV+D)L@j>JnWPx3+5Qon}Tx25SHjRpJH! literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/scared.gif b/images/mood/neko/kaokitty/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/shocked.gif b/images/mood/neko/kaokitty/shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..a29f52dedc28fc67d6690818e9305dd096f3309f GIT binary patch literal 1776 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 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/singing.gif b/images/mood/neko/kaokitty/singing.gif new file mode 100644 index 0000000000000000000000000000000000000000..cef417a7e32213cd1791fbfbc294a839490fdb56 GIT binary patch literal 1372 zcmZ?wbhEHb)L_tH_|D33;J|_QmX_q~IdiuDKX>mx5EvR7CMPHV-};|n6pV(za1Q~+ z|J;7AA;Hd$0j@@R2F#2=|0@2Ib}&8#2z` zvgtO{z1b3Sdt2+x56kXsvw6)|k+tCc^?hvfp4sj)&wOwol%Km!d&`Hr>zhlh>h{cd z*m#=#o05YH$L>7q8WZj<%iI+QxlENx4BeqR&1Pa%=kwoAYiG- zeAYHEnOP-E0_U)CN@z@&qH$<`2(Q3Wjmyg$*N3)u9sL#h`gm&qzmNsPxAdFaQ+Q=I zNQFGOwKM4ctE*Mh^X_h~{LaM|Q@$YjV8>6fZPFGS;}&#tiWKNryi8g+dB4()HRZ-l zo2DtJn|=8C`Szs+f7zz`ROY`pv?h9gt*vq6Tb9Y98Xjw^U%h2nl)63k&+TtXpYgOY6xC){S=cb+Wr}ZM-YHw_DzS-=3eJ4W{b5umAV`=eMIbx4ZlA z-}m?T4Q3`H!fV6A!_D069y|>J4X)k%fqIb>hjoPKbc=<3M_8aKt9J{9|W%NxdR9{hJyt+%fa+*=X6>*?+71vhp( zuu7SpnUR;o&@C-(H*3ebCx=3`SDQ90D87G=<4Ky_Zp)GvJD0h#i)H@&bmwBO`R=ye zw-TFfa~{wNxKOb@><*{N`DJq@e!M+2@3|EJx=QU=m!q~{%lm!hXZFj>+Tr(4&HeOv lQHI>!dSH0j{Cv9Othmem7~9|9-`&3-1`e+uvTQ62)&QtoJPQB- literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/snow.gif b/images/mood/neko/kaokitty/snow.gif new file mode 100644 index 0000000000000000000000000000000000000000..7bc05445033cdf2c9419f84dcd06d0ce49052eca GIT binary patch literal 1054 zcmZ?wbhEHb)L_tH_{_lY|Ns9v$#V=14gb&ipKO>61n2Jk|9|d30|UdkIUo`ZDE{a6 za}5c0b_{Se(lcOY1WGIZlXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*$ z#PFX%2V@q=UI&&dA5MC%-aBK~*mhiDGirqX6Dk%4U-)v)z(-|itB7X zw|rLqk=b)!h_Aaj>Bcg;1{I)3Z-YH*aehM6_5S0m501*N zVBpADy(uF+DQ41^ik!(yKmOR~ndqS-)xLSjr}PXfO-D}#h7V8H$!Xxy3#?a)$eFQkR1G$)wA`!_nigD8wR>OfLCqGumPr*I z%}tFv_jerX-X_`1WX{Z7b-VS3*n%4uPM)ZLoW6NW_Xh8^(#6-7_%8muV7hzKL&+aA zzJA5(-^)P%W}BKtpGmh!5b8;hRCyqn@uqm0)10P_6S{KsdOhEFYtQ`#65WH;S>ah1i|3Li0}^VSIyT)DiN85q9Kk~(_*qB!q^){prW&Q&Gh zc~R=NEq0Bmy-6OfI{tl@lcyvHOxN|5i)@-V$y-F;c7d3UMvt^;fnsr}jY3gUfqct` z&8u^^nbaE8E^CTmHw`_yZp-2A#%)&a8qCZs7uh-8ohKYKGMymSV-cFSI@M@P3R)1bYkJpS<>%ft^Vda}?$0k1ye)#{ug7>aEuXs+Vw5oG5 zFv!h1^;t#I*?8rbX*XZ4dth+lv`GK{RPP09S=%?WuQpt@w052Plm{Ea-~MKgDK4ne zY|t%AlQZin*Y}(t?qr`fb=tJdc-NWYUel936j)e0fpI!VG~1{z%djxPuOnNhTO(j& zK&iIhQvH(M!TVGzYna-PH8i;#J=o!P{J1eQbJUf_i%ep3ZXVaZc>iu z&^wC%WZg5<$M z7&&A-HY_;U%pt55b7I57!|ei$EFB(!4M)4h)Pqtq8XAuGGntu*1T0wMIa$h8N~dzc z($mw_y;q5x__XxwbT!v&Ih_mA&(Agxb}{+6Dcxs2N6e{~hy^cBvIg`^=^ilA^k-pR zkac&L!n1(Y5u1x-cQ-gPv&ApZD|HCdX5JEdIIEQ*Q73kLfxKNS*Fwj;Yis}ObxaUf zYUU_@&lF~}ucu1=iAoB zmVSM=iF;@Hald_getza=Wjj zhzM|K>{oCMD*5rT;pAjB=Q^JVp{3qa6nM9pbS_9cJ6%(lhoy7VGOyVje(OXc7NnnG z^{D@)<6xrU%fdRrYwj+Gr+&)=76;wk1qzh#>3*dLLbaGT_-^(B28wp{<_ty|S74yr zURnBHuR|bQp_wE5{v**n+w~jvH-5dOdS<)AqfM#O!ZkdVt5X<+jJz3uf%4>BwW;?E zo*kdAoSxz8z2H>XN2aTbJ>50det(y9h3)*kWmUg(T<>nLmM*KSK8hmDIGIs{ooZk(8??9#(z zE+^qxlybaR&~;i&c7<_#Z%pNh<=)tTltAaTM)-4kC7CR8INI+^ytyKBDCXQTI zqmF_y-Prx*pP6plzOEN@pn_Y7Puk4z;L)D-R%{9jH?iy!Rx>zPbA40G@fv0Oxjr{H zv#iMA)i?MnS<-T$?D;;m-hwwdD>ff*y0W{xEbrj%<6PqVcJKK37#I@%=XQPl_-tOU zv-w|{U56U5g~Pi6N)gj^tIO0+Y)w^OAbUcgDTJe9<)c=G(7c1Y%Edp-JyrgJX+I0& z;k#Wk*4;fCBJDjx=is{*&TM`8Wjcxvv}T(t)<<#8+aSblysnV*e?!5RQ3Zv21% literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/stressed.gif b/images/mood/neko/kaokitty/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..c632702aef5c3dfaacde3e6427061c7b47b49a60 GIT binary patch literal 1796 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aKL$n)8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jwaA)t@fa*fJ2k_C^-77SfI7o0>&kyB3Bk!1 z=IUe%Rd9-AUY@1JED-VQi$=&wZ}u=#DU(-0s}mNc&8?iGeQ9Rs;j+}IZ|Od3{kcUp zXkE`dzulnpnvO$4UckOO|9veSMa%CTsD3T>cSZSuhl~5gy>-@z<(xd(tIfXm&xM9` zW-ES~0PSB-(wS$N=F7eLuqFLOSNSft-knR651R#U`p0qUo8J^o!$YioG0Q&ewkVg6 zKeuP+=jU_N?dQLpWm)?2+Ir{v=l1R{Z)Rjf4ia`?fXD)ajLSdLz-m;5|{N_|%>glMbBeGOb;A z#q*0I<9tokUn-|U($CHplsB8Z%XsCfh0I(c39C%ik1Vl?6jRs``uxTw-L-9JZ(Yr~ zy(J-eldJYO-Qzn#mfvH2Wt1N{J+NEO!lBgQ+GJjS`FX1>3Ii8Ky_~1>>PDu=M$6M} zIdgtIJ$l;8xvM6#G{N)Y?1j^|y@>q!>iULccN2%*Ww|$5a$j%Lt=^u0Z(}`kzJvh6 z%WMqn4ANjPp8$H9#~}ce3K#`=CKxm{v~mjS)!Zm(XlUnA)+*6Ra5&b?$kuUW#|D*y zeMo;om@Iv>09a$@S)Hq%Nj-=D#Y&MkD}mU6WU(e#+&Qyw&h zV{60JxnbM~=KK;_7Pi)Kf8N%W0$Eo!DtOOp%?x^Yj)9#|p|?8Z+3l^R)%SR-P1Ej8 zuhZ{hv1WL4bicH3oJsb_4W65{E%nOQY%F@TZJKfRy)!#EKR>^Kw?i&h!Q|!TrIw51 z-d1jXaSAy;5uQ7R9G@Z*3m!T(@iI&BC@4HS)FG>42=9I&8%p|Y9@w}3Lw$r*>tTaMkS-Puo4RP)K{sq#ikdcr`S6O@whon`Xk(h6^TpR-Y44_#Zw J%f`ZB4FHxTw8sDd literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/suprised.gif b/images/mood/neko/kaokitty/suprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..a29f52dedc28fc67d6690818e9305dd096f3309f GIT binary patch literal 1776 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8Om={`pUcQ_Op z+?yn1`MyXrBrq_lm`-xZENWnwqN-d~W2vz000VQ;A(fNGY3F9CalZKSWAlphj4U~2 zDicJ~FD^G_HVD^V7$hHLK{j_L_YOWfJ<-v1zjiu|+J7R#TVOv@~) z?VS10=i>DEXgSdQ^k#)fO^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/thankful.gif b/images/mood/neko/kaokitty/thankful.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f57b0d5d791f4781c57d699ff916660ff93ad42 GIT binary patch literal 1746 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/thirsty.gif b/images/mood/neko/kaokitty/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cc6917ec766e8cb6038ed3ba9b101c357906850 GIT binary patch literal 2437 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 Jzd71QzXI_h8lwOJ literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/touched.gif b/images/mood/neko/kaokitty/touched.gif new file mode 100644 index 0000000000000000000000000000000000000000..d716b78b96c78e0c0bfc3c93e24716d09ede821b GIT binary patch literal 1913 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}FmVyTij?K)%S}_$H6rCGcmF?zO7$iA%u?r^6 z(I{N()+VlR_h-k%#YZP;_)hXUDU@`&moaHskK_Z@1_q{#q$M*ir!_D#65Fn-an zP`93s!E1A7Fr#<>FO>};8CO=jP8V`GWyH|9)@yxN@6V~P&#Xkr5F%EWp5#V^9GG&NpD- z$an-iXk=#K6N@=9;o-q{UU97ujfqJ|TR04zN+domJlZR09c3c1DaC2BM)0bblbcc+ zrfbEsbx1fg_)OQ&y(FV>;MtirOIDsACk+lXEVfJ4I$K$y;mhO^Z#MT-2?OIIZf1cU zStYBkFN|7m_x9J;HDPO5mrjf2o~Cw_k(H~a_qK>yz(RL!feF^3`tkEJIIrbMeb0~E z6`1*`wR=WE^4#*9>sn((-XGpHozd9jz|97R{u%OIFLD$6fVAFSsw>vIEhA1{AK z?5{lkZMNa=K;iSqtZJO_eQPcw)y zb5wACdU|FCGs~G4$%#wPG1@4yNjQ`|KfTzlld0Epfrj_efXRFc0wIYEOd;(~ce%c3 zg)WQQ*|j&y^kMMEjNQk0tQR;iuFIRc?Tw~GCL>e+!h2_DZ`N^|S@!sq=pFO4*hP6i zmDFk`=S6MlZI#Q@m{ye7%4Q@j@L)rcGvh2?i)ClN>pnff>6|WCps?W)<0{w7e>o$U z-=AlcseN^4@Y7Rw_T=8T>zuOe{o@nBpg3oflymds{B}3J*wT`h;@E@Y{XnLQ$Zc_n zOrl)hSD)MI%l+c(s_hP!ce}pi`|!G4>*0Q2@>r8?{_((3X1Qro&s^Tvc$$r+V$Poc zhBW31RdG3)p9xRf=Igtk+g+ZOb)mR=(_2mn_1yJao*rA{X}$gN6z}|PGJbn@9JoHC UUAca3(az7$&gr}Ja4=W{0N5tw2><{9 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/uncomfortable.gif b/images/mood/neko/kaokitty/uncomfortable.gif new file mode 100644 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/weird.gif b/images/mood/neko/kaokitty/weird.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d71be310067f9a949d849622373a685d4614bd0 GIT binary patch literal 2335 zcmeH{`9IWo9LGO%G&6GK7#g!?n{hObSPZh-GD8@K7$YH+T;oXPswwsOqC)N&DNGqO za*kn*7#&lDTpgrzNTpM$-3n~JnU~Ci@AKWj|J?v-UVf8<7t5aJ;b3lJihwQflD-n0 zBEswvBBDb=V~M6Fmc$(#qHkho9MK~pJRvk5kUk^j%oi5dEXrBDBY?RNU>GgBSa3NN zqh{#eBQEPmQ`T|e(;LgLW-21sNmXXDP5`$td4v1?DS(mIYY(T#LcQrQRFCUu<7!5c ziLL6%YL&CsOAwgzhj9>e676c>$UK5*M`0M0GPp_FcuW6{e8~Bz zQE-hGm8uH?WF$B18bx=o*m&=>*0G`0{blrnF4*FN@Q!4)5~Zt{&9Yv&4`+w5nERSu ztJfBrZO~H76nh5mzmQ?|mXVBlf(Io{Apx*hMK8ry1rhWH&eOT|QgiC|4D6R_H~QVF z?P+V7HX;ls#HHjoC2GvyboW^QX?r6DH=C)Kw<;A;$p4~h2QYx4dMu`h*08`)!DS$) zvLSw-sSLoBNRD3VdmzVT4YYp}oqGo4|7fJDT%;moq>$0dv(|aC{ydX7)n;dkte;Qa zHdvQVVc$4H%*5Xwr9Af(U^Q)wsg~s1aQ%uDz742l)CD?u$IlH5N0LMOnughe`s9;( z4qfWwBam0FYeHoGeQyKWsif{X!g*%U*oh;W+yaJqV<*>wz&P#N*7U5e@N>&RUE9>e zV6j1J%MWJ6Z#-ZjCGy`X{kbG1Lw~j@WS<6KWtU~0PlD1^(Cp!tyLGzL;iiU3IP;3` z95Q7&Mw3|9aU9_n_z_0|Zbep>O$9wHnInH~+}A8RmE0@XfL6}qFtr`>SIVtXcli(w zs$Gp$g?^u&d)6bF8n~^{>d_|4%Svy2s5M^Ah!q8WtF4`Bi{GQbS(ml|wKsW2;VU;?pZU@?v*Y zg8*D_Z6UwS9CCrL*{Y!n@pK1DQJm+)a^u45rF7a8-PhcZchw&Rk(`Jj~o|wi02rwd3#KqMdp_yZ>6Hn=YtDYM68eO*K+l&u1y{X!lxc0CAo^2f0t#6 zmVaK@zQwX2R@q@^^MX1vU?}!54p6%mPI^DqgZbE=i=`d?Smhbw2-9`2QUGy!j68yE zOnjSJWoIcov9goHs&azkgKH+}EFD;p?N5cj%z3@=tVEvnv%rnNy4?^E8Y7%-ght_p z*UJ?R66-o(%bLOhn$@~J74S2n(d_USO4RDTy83-iDG{!YX3b9mfNqCOm1>b_$2PQiyznV5D|W8fYXCdEgcOH`y(bq!VVu0+2n u4s#n%O;da4+H&s0`F^#peEbFJr^%57URR(;d(6}rx+8Uk?fz&gSoas>>WxqU literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/working.gif b/images/mood/neko/kaokitty/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..93bfaa4c14f1211e16890274a0be38ae1619a314 GIT binary patch literal 1187 zcmZ?wbhEHb)L_tH_{_|ZoIPjG*8k`3{RaX=L&N0c1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/neko/kaokitty/worried.gif b/images/mood/neko/kaokitty/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/index.html b/images/mood/niaha/index.html new file mode 100644 index 0000000..f621a94 --- /dev/null +++ b/images/mood/niaha/index.html @@ -0,0 +1,42 @@ + + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+kitty/
+ +
diff --git a/images/mood/niaha/kitty/ankangry.gif b/images/mood/niaha/kitty/ankangry.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fe6ee21134581c4c3c456a2b8b35e7e6ee78685 GIT binary patch literal 398 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zIBghM8FY9VI2lA3Wd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcO0ZFMM$XC2PrHv*sx6gKFWIT&qj@lUQi9LSLxItf#~sBt@8|w< zdfw*#cL#56?sNRAZ>q|~Qr}wZ*v!&u)ZI{|pw^SzpI}_$X=j? zaHcS@GU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5Y3qq4AMYn&V)GgeuMh^TdEwf22F~lJWspYo}ChF^jUU~Ysaqc z%S<=dZQqq?x9MKMw?@v%%}=|JRjMtOQ7_r4)6cFYSi6Oq@dQ5+@D}v<7sN9J5eWNR)evjuFX;%pC+Y- arqJAmP9=38A7z#4(xSe*A~k@nwFUs@B9tKj literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankangryg.gif b/images/mood/niaha/kitty/ankangryg.gif new file mode 100644 index 0000000000000000000000000000000000000000..7640effa67043cfa12c48d47c48cde2495aa74c3 GIT binary patch literal 398 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|!7+4u}co{euL>S~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8z~5JW(v%i5)9HnXU>E;^L~T+`&+6Uu?9_wraVu(+Mb;fYxG%m zk88)S?#oO!*KOaGX}9TKz_&)u$<0r@k5#HIl~FI*spO-1Fndyh&&)%C(UQj<#W(Ng z{&ITW=KgmFZ*A^#{HkxN%EVINTI<-%(rVP*P^6&NliZ(RT;pkKraMt5V^)K)p{~tR f9iJwphNjTmhE64QA0K6v>C&RUyCOA!uC)dLb={J7 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankangryp.gif b/images/mood/niaha/kitty/ankangryp.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b1043207a0a5019cee967fe8681850d3dd9e1b8 GIT binary patch literal 399 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ|@7U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|ohdMPN-#(R-8mED&if7O?{BGc#2Pdyn({pDYP)kv zs?lfJJ+2+Qx-T=`T(^B!rroA{0pA)qCpSOs7E`v1l~FI*spO-1P-S|8&&)%C(UQj< z#W(Ng{&ITW=KgmFZ*4Ynyzg$Dz*65*>!`}a(qhzIrC>UttF^zTDZ$g!Om~7##;kth jI$fKkIzAJX`X?IZ_ID_$`}ioUOqYxF-L+E^=vr$4t1_5T literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankangryr.gif b/images/mood/niaha/kitty/ankangryr.gif new file mode 100644 index 0000000000000000000000000000000000000000..0665cf66a3cb076e0017e35287f062190ba1b643 GIT binary patch literal 398 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$QnnH4(VM0%k&!jCe|CRV>I}8Xvt*=2 zS2*gn%9`eh8)j{gjTD49GX>^M2?lAPGiO4adA~vZ{Vi3FSc4`-Q=X??ZO=}LHTo>O z$F*Zu_hqJ=>$dO8wA*wq;9Dc-pvGbN{=8w>I}Ve$_WsWn!sst#xc>X*KF@C{j@CN$yWDuJJTA)19c3F{{DYP}gRu fj!%Wd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcOt#Ad fAyXz!US+6~I7NNsN@W#WX;FC-pWPZj_gVu0wKk77 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankawakeb.gif b/images/mood/niaha/kitty/ankawakeb.gif new file mode 100644 index 0000000000000000000000000000000000000000..e02e383f38d46384ffbf2623fe973d32754e4e78 GIT binary patch literal 400 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za4IvfGU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5aP@Vm@_39q=C+y4RPlE2KD#1R5@Y|niNfWo_4i8J0;fWvuxg* zSH^Om_so8_S&5;7p{bi$TdveoyyvltR^%DQ51Pt*Y?zkxDfrAh#N1F-dZ@B)+ZyZT zzjtMq-WQNS~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8z~5JW(CZd5)9HnXU>K=^L~T+`&+6Uu?9_wraVu(+Mb;fYxG$* z@69V?xzBrMKijOtP{GjD&8#g~>M7py*hMSyjN%7PusFFBEedS7J6U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ_h1U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|ofR;5N-#(R-8l>5&if7O?{BGc#2Pdyn({pDYP)kv zs?lfJyf?3m^FAGz{cN)mLj^-qH?y`}si(M(nSs(&oo50+rU=H#F$TE{Ec1E9n6TIC zp^d#PXU(&VwPp7Wa+zm46xyU&sxn2SFgM$`vb2YKb=iuvIZSAsWKyG3q}!lVW14F! j+HGmQe75%t`{KyOYnCRe8!eo_Szq47XXhSCpmVJO2zir% literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankawaker.gif b/images/mood/niaha/kitty/ankawaker.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d24f3799043bdb1dce40d398376c501494ecb49 GIT binary patch literal 400 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$QnnH4(VM0%k&!jCe|CRV>I}8Xvt*=2 zS2*gn%9`eh8)j{gjTD49vjXN!2?lAPGiO7bdA~vZ{Vi3FSc4`-Q=X??ZO=}LHTo=@ z_vV$c+~+;BpKVrRs9I0RFxj8tlPH6 zdin2N*`@adWZS1^)>zeRsWOEpGuIoova~bzb}E=oYIE>P?N%yn(w(GJQ!&wark3?G g9ixyb6DO}SR7sqozH+6qimkM$yot|l4WN6i0cbOjTL1t6 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankcreate.gif b/images/mood/niaha/kitty/ankcreate.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0fef55a5874952e86110b46ec7c0a98cc14b685 GIT binary patch literal 972 zcmZ?wbhEHb)MGGU*v!KK2FDnjoETbK7>+S896Q$1@*e~l82&T-|Nr0V|9_w;0x16H z_Hzvhc6JPKHPSO+W(3M8{$$~FW8h)X;bq`t5M_{NU|^Xr!BcbDS~KH=#>b^hc@`Kn zEesHO+EsPKCq0%WF}k6m zbXRVTWze?m(aUd5H{I3taqqL2RS&bH{`_&&Qf20@Git4_YHqV^5G`|x)~nRAF)5zf zX{9@Pu9cp+VU~`}l0|;XD!#re%Vp)$`#psOA&v|HIg*KinL(975$MQ=6HXpjvB%|M(@)#z=QJ(JnlPO5&t?bgcOH!kv*sK=#5awm#6G&VVAGo-tA z6n7d}F(+geHY7#+g#}02&9HCwN(`8*vn0gavwaFPcl^d>G14rGF5DXfcd>4nyIpDL zrhTT%6GoR}-fujcOYYqlh26>>r8Cb4PIO(~1X~)ykyZLwmpRb6A9%n)x~*(74b9FgcR%oN-;adM#B z1l3w6KhLQ$b9{9sH_BRZhp(I$BEMp#7x(HVYb}{K)U(>p*X;9}KG!HC%6VVV!Jq{u z`_H)UpWSCOIl6b(DHCg(vqw7}3ho;hOnfZI#`Eln=nLW3FNN4XynFTG$M zU}whwS0gCi z*(W5OM7`XDDSc{nOdlk%sKU_n$YyHIx zRV{hjuSV)~-Iz9e*YZs@dK+d-9(J;ms^4$BwQ}{1i@YW3aVe2piQ)~7O^(?N>8>5c zod#Ac37LfrNzr~`!I5?|?3=w31Lo>12{HFYeNFF?SO2V`GtW%UZ2lpNE%U8k!&pvs4SCV7uHT%4#&o#=3a^4qoFld3v z{xh!oXZP7mj_%!c%Ea2{?9on#g8Rk=6Cca5azA?_`a<~iOChg!uL3`ce0V%!W7ir0 D5J-~2 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankcreateg.gif b/images/mood/niaha/kitty/ankcreateg.gif new file mode 100644 index 0000000000000000000000000000000000000000..1cd0a73a2b3d95d5a79816e79481c92bf69c3fff GIT binary patch literal 1220 zcmZ?wbhEHb)MGGUIKsmK2FDnVF(@i3IypJDwEPFcIdkUxXJGix@c;jRCm@C>B9B!3 z&+X?L671|4;A*62z|06VMe!#KryBzggAOkPCxa-1Gy?<2E(S>s5sQQc2b*N?dMIs zv_(_s@tI!p@<(5O8ofBiDlgvVlUd^EGr^nD<8H;rCr;BfHPv!=7G)n>$G$yDxAVf& z;~OJS%T;6*9`xRBXd0%n;lSDxyRxsI+d5k)&vCQS^eUg#6ID-cZ2i3Ijm3_QUj6LO zSx-+)*pxC~So7PPnLl$5w}=0KCL$pK_D%rEJ4_7B45|!@K=1qmdWYvg!-50N9Ku>L z9Ty%rw(}@^$w)9fI?~Ohopt1dVe-*F1?Mgi%Y?*}6V=$~*sLg0^_s@Qu|`JV@>6d% zWpy!7te42dJ+E!snUaMK9VX%}e5-yjygasCb(z@PT~D5NFePa( z>DjW$YXfKU^J~2Z&+ptbnmW(tK*P_250CV-z4fiF`rN|l$8Vk)vFzjh)@*Tk9|ybQ zGf!-n&yV-pXLD@Jht11m-`gpGgDM3SR2&Sf4D!Ihf&`U}$A$%tO&k&`HYYYLJlrlI zsuv^iQL(8T81q*mJ}9|$v9WjPXiQRe>fvJ-P)G<;J>8|qFO#8pS;dDblh3MOqEZwJ)Di)tJO^X@xyIpTsKj4-XcYF^1=8Urs-Fh)44K6AOzx z=c(L%X=OfN6rY{363h zO}dyGR@IWX{c5B>*NthjcP-ykW4B@UOeSYLsrvo4TPt_pxX4|i9+wiyohaVW*yNba zknY-1+-YFNmXKN4kQD6~7943e!@k)oF<`FFk`Qyx_9<-K@f(-LNHZzAaBmFU#lB_k zcBP%0_L(kMWI8CdBx0#mf#kuHrzAX^&pJh!bMo8~zkDS;@a&VvcO^NuUpAZObnX1q zqvD)jRyyAFef<6Qm#-R?440qGe6G&~jvBD9IT%62Y;k^WjZRe(MJiJhS3!|jfLxGilWM`gAEUEPITkaR&%Q>U0 zd-IeHzilUU%dKf~0hIs4BCJ`gHh(v#3=HRZ0 zlLOr*sMb39c}|s?^_^x(Y?D)nONJLJ=*C|aNoFK;$t}$o@Y-)UkJZ`Da7*O-K!5DKfU=n Jam2>2H2^Lqnpyw= literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankcreater.gif b/images/mood/niaha/kitty/ankcreater.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d19466a40a02da971ddbca22c9cb37854cc9657 GIT binary patch literal 974 zcmZ?wbhEHb)MGGU*v!KK2FDnVF=Pt}w6y#O!fQc6&wG0QGcf#T`2YXE6A(ibK}f~_ z+=3?dA23=AxjCU{ydTWi+8wsKx`VuFuF z-Gjmj&0bk;yQY2mx%Jbm^B>;bUfRpEL3x*r$<#uPWX`Ea)r6);uM%4yv}RT`gQJq_ z0gY2lPP->YZjQcxYen3<>f6iiE^PJpUoIh5Wz@i48`T)wlAYmOoTl4trKM~m(xW#` zTOuQCX8-K|sMHy1lV{0Di>`3gZIw066F1D-AR8$Nab^I>nM@4K45|!@KxaOjaPq*4 zJr=Kf-+qnJ@ME-?7qxOxPSmynozsWI&VMV2|JC=I?QovJm%kFthZ9$rJnA^5YNTc3 zHR)n%SXE2j_N$TlTsNl8-nD#FjopUXGnt(2r0VzEZmryX<05y7dR$5*ccOShW0PYx zL%M56ai@V5TS8`GLsGO~Sa77>4EtuU#DKXvOG3;&+o!N`$8TH~Bh94f!o4wY7yFjE z+m&{1+Go04k?Ek+l8B{N1(F9(o|5ovKI;@^&dGB}{PLCXz_U*t-<9Ote%WlA)3x(c zkBW1CS?PGw_wo1JU%qNoGF*N#^SM3~IC4@zzUE+HWsnE@n}Ox(gp;1Dmv%foz5D-y zZMhHI=R7P}d9`!WHHC1a?uGXfB(|NKzVYxv^(~B&Ru2VM{*j$|DzT)}$8Wh`fG_8a zvhK}OHvG1o&@IpEym4<_wzz3)tuD9tu^mo%Pu;{LtEy|PlNsWzE1N`&*dh}Bg_(o9 zCQc4?o1j|j!R)8`sxL^XQCP(+~I%Q&QbM|PbL&1IHf{BmiSa_a25q%;2`lS%dhj*_&eEjt0 K>%xLdBZx)1)#et&CKsk`i6vGrG8EK$64+A?;Mr=cm b=jt^(+6;CqkCsS^PA`hATIwvw$Y2csee8mq literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankfoodb.gif b/images/mood/niaha/kitty/ankfoodb.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b07cee1835ad2fc89f8cefc04b06a999d95569f GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zum&)&GU$L5fV4BP9NuukbM;<}*JpSCPtfQ~$()z5YF)&EHpf3@jS0Ko#XJeI{bPAg zOKmbsoxS77(A|;~Js$=%^aL^nJblB_nzZ`%I*Bu1`WmCPKK=eHxJ2WQq(jZ?S&x>L z?f&ezlexghtUl06*u^lAxmwiQxhJN;w@J0mE2E=ct8QYOf7nz5CYJPScZ)eomL@H4 z)G=M-;1OlFNO^8!WY_u$a~pQ8*bsW8vU%c)sx8}hn9Xo->GAV1a^rd9Z%UHE8;y|0@pR&e;-S1+agxLPE zyr-o$nWfI&@nh(2$%&p10~&e)83Ufa;b=`-eS4k6nJ;~f(ORE={}o)KaYxdj=Jl*c z%gT0tcHGHa;A2)FXeI1o7|2{L>h0VUQ{daATIZF~QLj}uvCThhssR&AdbPX7oFz+> zmN)8{u5s{)vRkA)w=uG7{e-y-L?y z_wGM<_~`MIr#ga2{t^Ltj){R8=r7g{Jxbmz2p@|BMVWzeAekwKDM&KXKye-hcA$*d dh91w=Yj(65>{uQxkrbU?6j`;@S&)&z8UUqsg1P_z literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankfoodp.gif b/images/mood/niaha/kitty/ankfoodp.gif new file mode 100644 index 0000000000000000000000000000000000000000..9dd7dc44c6c471fc1252e34aac23effc32f1aeba GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ybdU|?m?0Vx1!XJ9$J;e_Yvy%w*}?*5;k(U+1rFJslZhy!hof65vYcE5{x5@P$u z@}8F3WR^O6$B&`AB`1153~1;HWDI!vhNCrU_3d>MXTJ0`Mr(cg{a0{_#vMtAn%A=) zEi2po*>NXxfsa{zpp~$TVIXt0sJC-ZOo4BcYMoa`N4-|v#5Vu1sRm3e>DBHQbCxVk zTHdH*y2imH%5IVJ+{VbR^%Lec>{_uQ^hjm%#1&Orw(l^T;o#Ea=VRnzd#(NEt=o6* z-n;+c;iJb-p6Uo9`AY=oIVJ{Xpubo*^eB0=Abczi6lDg=fn=r_rXa~k1I2k5*nu)) d8+trfui4RNuw!|&L{fBmQDoIpXF)~=YXG?Fg!}*i literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankfoodr.gif b/images/mood/niaha/kitty/ankfoodr.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca5072316b7dd286fbbc583dc89a6f4dda976ee4 GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$%u;9X_%U?1*%wDe!Glt@Fz0sMo5S*ybNL)qsg5z1rPk&XT1` z%Nun}*Eo1Y*)39@+Zfrke!|>_T`M+(9;s}exT0#y_8n$399(+*e2iRdueIO2b^FfU zd-oqaeDwIqQyoDhe~AD+$Hc%4^cU-f9wl!Ugpb96qRc=!kjxar6eJmGpg0c$J5WY! dLyza`H9Oi2b}WyUNQzD`imY1dEXc@U4FC*DgTVj* literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankgeek.gif b/images/mood/niaha/kitty/ankgeek.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d7f2a69019e724748f8c04420f554fe248c8e55 GIT binary patch literal 347 zcmZ?wbhEHb)MGGUSj5Hv0!~g0EiDYkjwvcC{{MdrEX1JrpWDwhB-q(8z|~04fSC~} zs`!(IHGqMQK?kG)q@97~`h^potM^*GKD+yWf<|9T=Ddtm>vAL{@=voe$)1+9y-}g} zrZM6DB58^2!(JCH9Qrr{oQ{i0h%i_SF)~azS9dHsY|GoK6=7?HL%!9`Jo9yVt(eGz zW4GtL{&%mxO0Gn~wWvC+rJ%8?rX`^vrB~kDw_Ccow0=U)q?xmlivwF&=PwY6UJ<)0 zrX#)F(Pvufnk{Q;jjfqXXD{EnZ*8z|!&I@rW5)v~_m}T>vh}V%+ol~FS`lhGP4n7@ zLdRQLu2=7S3Om}jKG1!1?&-6)?>>I|{N?Mn?>~Ni5`_3w8RS=5NFJn}f#v#z6P~O0TD(5H`+tH)UrOe@j8*G$G$is*b27`Gmh`<*VfUsf z;r$|IiR{B(7d;&Mm@YURS5pvSunuBim~gJ{Sa#T!w^b{`)(D4utDAY|>+)JTkq5_a z&w2gtUVoKbiGpiUby`b7V^d8_LPJWgyti++baQF_gq%q;XC)U0wy@4$AQHVIc2!JA zdby*|wA3|Q*3=qXGn>v{zIET)VBdzRVu8nw2TblS-|b}UU4OPsJ2bQ+)O4EWwGD-i zx3pZZ-uD!Cv~PW&`{>-$XK&wq{Pg+D*Kgl{{QM*c@vAb(uRIL=49q~tz`}MxfQezE R8X_2wr9>Q-nFumi0|59dgVz86 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankgeekg.gif b/images/mood/niaha/kitty/ankgeekg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2acff60b4d989698bffc0af3e16b2ab26461f03f GIT binary patch literal 343 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr7<7+4u}Kng(G8CWiFIN`Z^uf^-LyZ^rd9Z%UHE8M?xh3G%J(rX-V4~6?$(P z6W%Y9mdHNrbvu7LtW*%AhZg3CHxO`R1rad NEG1yDOh=Hx8UUVafNTH& literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankgeekp.gif b/images/mood/niaha/kitty/ankgeekp.gif new file mode 100644 index 0000000000000000000000000000000000000000..7dcd4330152c7ae81319abd1b33efcc9815c5dbb GIT binary patch literal 347 zcmZ?wbhEHb)MGGUSj5Hv1d57^*@i7!qmI2_`u_j_V;~`*;D2sE*N|Xm#{gF&Jp*P& zkkC&S)&K@J1|5(*NIL_|^$RCFSMRlWeRlW%1dYCw%y}8B*5znO$G|g)p z3LS50xn8~RDeP$9`at*5xu?(GzWey;^OvvRzW@07Nf6>!WsqNa82A~OfslcP?ScRk T!$dViFd$2bI4m;}WUvMR>zss^ literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankgeekr.gif b/images/mood/niaha/kitty/ankgeekr.gif new file mode 100644 index 0000000000000000000000000000000000000000..3fcbff7ed8f2ff29dec00c639a7ad81b3c882cb7 GIT binary patch literal 347 zcmZ?wbhEHb)MGGUSj5Hv1d57^*#ZLBf`Xp+^!)$-A0z}6{Lk&@8WQa67~pE8XTZz| z68g!)8ob(}P&+h)8pwX9-IWJ??x*QFO{L`GwvZp0|Z&cX5 zX-as%NLeELu-8Qohd!nY4#(9LL>R1t7#Jp;t2>q*w&iWrim)}pA>Zm|p82}GR!-!> zvD;C0C;0T2!6ZQqb5`(~{7T(kt)n+b!K(T0bFY(#%=O#eprX^B0IjuZUe0 z(~(~8=rb*K&6YK_#@5WHvzKq(w>H?fVX9c*vEu=g`^$Gb*?QNXZPN}7tq3)prg?2c zq2nzr*Q@tEg&pl%ALu?h_w?D@cOO4}{_^$P_a8q$2}1m;4Du@v13v>Z5Hhf^T@YYm Sn5c#b24pD_hh-*$4AuZ#gM(WD literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhappy.gif b/images/mood/niaha/kitty/ankhappy.gif new file mode 100644 index 0000000000000000000000000000000000000000..82ecc6f6a69954ba13db8cd3c40ee76aec215161 GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSSuJ<8FWDMAngn+hc=w>T)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y-)wNu|LzAIW4z)qNdhIAC&{K;W~3S zWz37FDa~83 zN`Gp~q>zp*J=eA%Ti3-q+=CBpuh`%mYZ5+ZuFakU?q}90oBNtxzU+A8=B?Xz?%uoq x;NhdkPjmz!-U`fs=s==q-+dhQL)z7QB){_!&u3fG1$plEpwtYXINibs+!% literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhappyb.gif b/images/mood/niaha/kitty/ankhappyb.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f46402be9bf5967432be7518258d8f1cdec694a GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSi}GVhE7wwg08i+{Qu9u@c+Nle-O=}_@CR)H6+;CF~HSG&w!Z` zB=nPowE{@%05JndI|IuhffJsq_gcI@yZe8FMqf(iyo^=r)=0(VXS0^L9{(i5!L;wY zrB{N%2f@OfvKu)hgc=>62UYcOO^eVeDUFufbU(TG>7O?CXIe9-<#tch)cWXSav(Nb z=kA8wzt7kcZOXGNy=_~JiaI?bJ(9cH{0+T&RK0QooNG0#*>dO4@`+($oA14hdC@eb zc?(wQPfeK=(vhX-+7@K%x_F0s@WJgB8=PZJ!spDj*>k}C%o=5LU(?H%9dF#cb^FfU zd-oqaeDwH^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvrZsa~Zudk@t&ct`2V%o@ z=5EOS`-~ycraZgS+qT81sM9mjBe|>1-_WZ^)hjo^xmLrPC3pTTpBN^V`QFQz7fn-| zw_uh2)Rajf9a(y=Z9%rKi+8vOAKYHC!8z6>e9l~(JqO&+tWh@iHNAY<@y5+tx9{A& zcmKh|M~|QA2tvFS0P>a)gCGMZ0~63&90d)5tClQyC4=xYlB57nz^WySfs)n$0|j+I literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhappyp.gif b/images/mood/niaha/kitty/ankhappyp.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbb6f17b37d81351a260efeb3a749967945dee23 GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ydTU|?m?0Vx1!XJ9$B;e_Yvy%w*}?*5;k(U+1rFJslZHBvG8*{mh5$3Ka1Fzx$p z>6KvcL9lSA?8XQQp+?8&K~+6m(;{?AN~4)J-B0d)`lpTknbyo{x!n^rwLbc&9Ec6q znY$tP?=yx(oAT^RZ`&55qE639kL0d4e?zYxRj=Ft=UNSGmfZQXd}5eb=6f$=UNlW< z-hx&7Q&T2|bY$tdwguU`F5clDd~kck2Ip9l@HumB_8f3Ovqst6*Yxsb#~U|q-M(}8 z-u(v;A3c7eBM9+U0LWWH41x@t3`{_8aTGKJu3EC-l?=kqNRk3P0jriQ21;530KlGi AfdBvi literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhappyr.gif b/images/mood/niaha/kitty/ankhappyr.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ef37775cbe2229c5826f33b9104cbfd68ef385e GIT binary patch literal 328 zcmZ?wbhEHb)MGGUSi}GV*#ZJBE&pF>YCiAj`TyVP|Ns9$LB;>vey$DeTY)=g8c=zP4nE090x!=^ITrlT#NH+f&)bv$g!l{KbE zf+MW19yrTenaQ4HQ?6~&5aQn&8`T}y>(r-K>1Sv^NqI`B+thGow!8(k&NCF8*%nl< zoaRw6f8pHe^CE+~vfFI8bS_z26uLindz;O+xb{POemf8DWUdW2HD|bV$?@9t8#iy= zzH|59{Ra;p=?FqR6#(*-5Q88CCj%4EQyddym{u)W{z?YnVvCT2E6_P#lFPE)mzAmi z_4auS%zt$m3T)lSv##up# sSCm0s;b9O5Qp`ZFa9!w0<$KN0If%J*Z=?k literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhuntb.gif b/images/mood/niaha/kitty/ankhuntb.gif new file mode 100644 index 0000000000000000000000000000000000000000..752b09b6ee5bd5c64a0ba10dba199342871dd3d9 GIT binary patch literal 314 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu-Y)NGU$L5fV4BPY};_cbM;<}*JpSCPtfQ~$()z5YF*CjeFZw_OJZ5J`?50izurD? zf%&gaCgvv!lAlDUdM{?zoU6B<`BBILmX8~}-|9N(y(wnH7=J89!s@-0-^TORAXbGUArh z6a>zl72Yeqxhrtu#EPmE)zsXLhvw|mO*_6X&EfQ!v**rVxOnOEm8;jT-#9A>@rp9Y hD?AM149q~tz{0knCy^rd9Z%UHE8=k>k2c9rWHW^3}75k=xaNEWg~EL10pV z-1Gzc(;vr#N)?r5C)C#2+Iu8Px0I)}dDkSkcr{5BP4di&Na>89F>`Ks-Sj0@%yk)Y zOKJ)N=gtc6mEYVIIB{Y{Rf=kA?#4rNcIu`b-U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ydbVPIv@0Vx1!XJFa3;e_Yvy%w*}?*5;k(U+1rFJslZoY(sbbk3K=vTXNdW$J&u zecl4|U!6?MPZT6SiB9!i%&s|CZ$0y)kOM3qH+a9*b~0lb<>wrG1q0p zEvYF8oI5MLSAKI>;KYd)RVk{exf>77*{Pd$d|#Tw=`&}~oxgDL(&Z~xuU)@!RuJM9 iWsp~R7{nQvfslcPZ9`8W7lSdvm&j5KL0po?4Aubkzi5pSVrHab36Kd;h?LCsDTgp?~ylWC%yqYA6CV6H>q;$s5m^nARZu*ic=DLiy zB{cjap2|}0~Kr2x(b(k=H@87P#dpCxugi!uF^z@X%#bO&ZoON;aq~ClPcd4+{gogTx)ZIiUp+DTN7M3;SL)sWt{lUhQ1vTiGK1 z_WM-9J}F_z1KSn`8_Igld3G_lEM}HY^<$rKzdDdR8>&1D-L(Ac?S0dFI#VV(OrBz6 kR-Qbow!Bbz(QJ8zEWM?9rWs3P*S1$}?AX}J3UsD50K^%JX8-^I literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhyperb.gif b/images/mood/niaha/kitty/ankhyperb.gif new file mode 100644 index 0000000000000000000000000000000000000000..bffde8b1c0cddaf29277bcf2503a11e69d5ab4da GIT binary patch literal 390 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za7r?;GU)I!a59K7$TBdnOx)lhxooZ35oywFU(CoyS>srq8M zCBZ9#X3w8KTT~Fmm26N~P9o?^9u@|E2Z=j+b3zLuQVJ8i7WTbpQf&;9yxO_Sx3We2 z?f0pIeNw`b2evH?Hk9?8^Xy`9Sc>9eesv&sHdJ{Qx@q~>+xw>Vbf!#nm^{VC ktUP&EZF!;cqS^8aS$a$JOf#0ou5GW{*s-yb73fTB03D-@2mk;8 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankhyperg.gif b/images/mood/niaha/kitty/ankhyperg.gif new file mode 100644 index 0000000000000000000000000000000000000000..773cf0c6760f36f98501599f7da87d78722ced74 GIT binary patch literal 390 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp{>8CV%~co{eu#29257+5B5@Q_@#*6ebF`g zvD}j26+yG-PoFI+h~i2%s4FKCbR`c91HXgB9lbfB1raHQ30@2PUNosT21#D+T;*HY zBL4RKRKY$eVaWsA76u#2dd_)vF}N&dmQM9!pK!lAkUJZyJPX~l{Oj#~(|S5nCOS-> mVq;dGJgc_6PU;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$~lWME~`;bq`t5Mz*KU|^ZJ!9#M{TC>Xy>hGmgIbsc(5)F8scBMT#CHBgzZOWTh z#abT@+-}{h#8AP|)Xl6dSL!L=V_~2)Rp%M&k12w2TjWFB1+sjS8g8Ze9W7D$FjL+C zVqyBmHND1xn`;bItWE1GT=JQlqwGR$yc*?_B3!#l6CI{i%$PZ=Hc5G*nS4)T(h^hk z#d1r6R|L(TKYg~SAc`y5pst)m(3Lza4Ezofcl73j7DS{JCU`CEd(ouY7$kYMbCqvp zi}>5`Qw95^ge4DbTNrF8>pADy#o)4-Svu8^eZu|fK<;d)@+@@I@~^k|P3!4QndmTi mij7%$@~qnOLghuXO5opF-0(Li+qT?K$cHZ!>u&Gqa`XIW~%#N zEKJ|Hrq?)dbB%$DwP{_2OFnaRlwGKeSEF1~glku6qQkU`88c_qCMhp8lkZ7PT4Jic zSZ+!1ilEu^r_UA@L~$h>)RmJ6x{`;5f!{&mj^3Qmf{2vD1h0jCFPc;vgCwtZuJWyH z5r6xAs$id#u;hVl3xf@1J?A{T7+e-JOQ-s=Pq<$l$ej&Uo`r5&{`L00X+51O6CEZ` mu`w%8o>g03sJv*lyh4`V(md0QrLk+|_Nx(;5J4q>GFI literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankitten.gif b/images/mood/niaha/kitty/ankitten.gif new file mode 100644 index 0000000000000000000000000000000000000000..da5df8519fdee8d0b3a8127b138e9294b54edc52 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X1tAIt|4ivPL&TtkAL9RpmA^bD98K|()S zSW_5S8FWDMAngn+`!<~LT)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y{f#`%h&2%+%vCl=S{|H2Zy5d5oU?A zpRHv~v?yteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I yL5Cp3OOhZj2{8yTa569hy~Mqt$LS@D>ElMt8G;BeBg;29y_7LcZg>flw*~+wlXRZ| literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankittenb.gif b/images/mood/niaha/kitty/ankittenb.gif new file mode 100644 index 0000000000000000000000000000000000000000..7153ac366544b7b1afdf775be099c719e2232d67 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu%a^isw&x#1;H-WmYjoOTBQ literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankitteng.gif b/images/mood/niaha/kitty/ankitteng.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf337dd06d3dac0432b940f94d2759dd66256111 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr8)7+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k z@BV`hL5PU;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWMNHVU}Mk$$%C{ru8n&VII*G0~_9Q7FWx!z{8nEV5=o;iOuY!s%1XS*Cl>VVq|DuSH zg&NMSuHLrYDZyLZ^HRcX*P6I`ZCtKwzj2$p&HfZqb6*qI*wrl?4%99<)nnFv?dGl9 zckbT1|KMSVAjD6SAU_E)2rzImFa!O>eSydMC5!3fM$H+52tOmsGdRDLF->lG36!@6 E0C`e)RR910 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankittenr.gif b/images/mood/niaha/kitty/ankittenr.gif new file mode 100644 index 0000000000000000000000000000000000000000..57b99c9af813bdd6416399f476275d1f067ea254 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$RsG3uW#o~#%c$LqV*AG ziL;-rWlXdw%k+xMcN7Zo=`f3I4vVarP&lcUrEvPxa+c}dbC_r8G0lyb*}o_vWTA$0 ztE;zdcS`UU_q>#F+qEXHUK^Jy+i%?FZnHnd)ZF*vp4BZI4%99<)nnFv^~TLxx9{A& zcmF|$AjC_OATJ3q2rzImFay2By`jhHC5!3fM$H+52rnbcH#ohNF->lG36!@607%4j AivR!s literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksad.gif b/images/mood/niaha/kitty/anksad.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e2f6b534aeb0d7634852ff9e3d06bed95d8b380 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LBnHoETbK7>*tL|Nj_7Nbx_npKD04vtxj(k)8oFBT!WF zCktx;0~>=5NCikc1IxY(Cp=g0wRnAY_x}WqzLd;)8LQUiye?`gIQm|Nr`hLjW$vAp zc`O<=oE#oaZ)RMPoa~XdnXM(N*)Pd#r@=y#&E??6lmk61EVE3+zUS5{bKeY| z%A+fC&?45NGJ`qHvc*5nPAtZ&$GR<`K4emRXB9JR`0Ob~vu1m;&YhuYzOXjJuG(wz zQg!$0Aj|#)-|c|~^CLE98n$g&uV}MnXQ0KwB9r(tne#$6ADX%6(y6NxZrr?e`_A2a i_aA5oB6&%KL4<*o0q9E>7K0g*N(jG-Fo>Z@SOWlIYHd6K literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksadb.gif b/images/mood/niaha/kitty/anksadb.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b360d429468f681bf60fc7234038dc2aa7f44b3 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LBD6rg#NiYiaop1P~#`|J;7AA;Hd$0j@@R2F#2=QN^Du ztN{#c3_2hcAngn+`!1aDT)o%g_1WG36Eyl#GUsKiT9@;>sHx!SdljB$pSzX0cUtDL zXw-0Wcr?A4aYb^nN7`n#mZ)aGP@k&Syl9^W3r#kcgBw#0^sunZG7gd^VaPeaNKt&MIcs@Yz#}X3h3wojXI*d|_>bUA5Qb zrRwh0L6-dqzS{!}=0|MIG;G_lUeRXD&OnQUMJDlQGUtVCJ~VUBrBhcY+_-t`_MN-; i?my5FMDmgdg9rmF1JIW&ECw?ql@NXvVGu)+um%8vzHM3n literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksadp.gif b/images/mood/niaha/kitty/anksadp.gif new file mode 100644 index 0000000000000000000000000000000000000000..1cd4f6e58813070e99a0043129236788e43fbc20 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LH1STee0Wd%yJk|NqAzLW=*n{aizWogD*Qjr0td8G)jT zKUr7<7}yweKq^4m8CdpRIN`Z^uf^-LyZ^rd9Z%UHE8=XFt2!O{0BJk36LD|7F( z%wy50;pFgWdNbpSUiRjql^J`EO{Y%T{krX1*DVVPwj_C2>wnfqqw zR32TCgBGzCl^M)omM#8qc49GJJ=Sdj^&ykmJFA#k!)H$^nl;;#b?yvJ^M$n$cGX^! zm#Vv02U+$f_-+p@m>;n*)39yJdPSQpI|D5a7MaAK$($Fm`OwTgmrh-saO38!+js8X iyZ=B#5Xnm-3?dAy3_xG9uo%pcR6_Vwgh32N!WsY`h;N(# literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksadr.gif b/images/mood/niaha/kitty/anksadr.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee7e74b88b16ce0cdd1a672c3f9c8a9c6ea55eef GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LH1K1g-@IJ@4uH|NlQkNbx_npKD04vtxj(k)8oFBT!WF zCktx;0~>=5NCikc1IxY(Cp=g0wRnAY_x}WqzLd;)8LQUiye?`gIQm|Nr`hLjW$vAp zc`O<=oE#oaZ)RMPoa~XdnXM(N*)Pd#r@=y#&E??6lmk61EVE3+zUS5{bKeY| z%A+fC&?45NGJ`qHvc*5nPAtZ&$GR<`K4emRXB9JR`0Ob~vu1m;&YhuYzOXjJuG(wz zQg!$0Aj|#)-|c|~^CLE98n$g&uV}MnXQ0KwB9r(tne#$6ADX%6(y6NxZrr?e`_A2a i_aA5oB6&%KL4<*o0q9E>7K0g*N(jG-Fo>Z@SOWmF4{l)q literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankscared.gif b/images/mood/niaha/kitty/ankscared.gif new file mode 100644 index 0000000000000000000000000000000000000000..821f52bb15bdc951238dbdd6369604ba376a17ad GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zI9VB38FY9VI2j}uq!}1k7Hsg4T(;KieuMh^TdEwf22F~lJWspYo}ChF^jS9V%`0O$ zVF$?x20JqCw3!-a#O$)zpjNyfWnadelz{A3xk_e+{(_|(6-f&XQ?1$=UkaZSzC7_% zpzOS}hxflS3s+NUD66+MVG4F~ZAn+{>UPXF>FDhC?3L?Rs%o=r(aFj? zaI!M6GU)I!a56|RNHZ|7EZE>7xooZ3{RZ{-w^TV|4Vn~9d7gH)Jv$}V=(B9zn^(qi z!VZ!X40dGNX)`sf~F lG{bV8NSSn%IkVM`O!bsirilc|M~EKK5JYk`_YiWlH2{_Yk469h literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankscaredg.gif b/images/mood/niaha/kitty/ankscaredg.gif new file mode 100644 index 0000000000000000000000000000000000000000..9cde3d2a60775540d748113e96941b7551148341 GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|g8CV%~co{euBp9R_7+4l;@Q_@#*6ew|5$q5EKGVQdP8fL`ove=+jydY&?#+;OZ>{hu-W`_QPr5qJW3k_4P+8JL8pA)`3 z@l>Gfyt9Y*zcLF~Q)noww>4o3c5-b=SMBO{%r@!h?Dp)H>sP93vux4H(`hs|)U{r@ n#DAJ$xlW`^y2_l{>PDt|$|}=D0^}n^4`>J?IhuP2IocWkI?av4 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankscaredp.gif b/images/mood/niaha/kitty/ankscaredp.gif new file mode 100644 index 0000000000000000000000000000000000000000..da85544a4e784eeb3ea375b5ba06dd76772fde86 GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$}~Wng8{;bq`tkYJEzU|?CW!9#M{TC@8N>hEuN=mDVp*;?P_~=O03am*}ONe zjOBzKBqtc`$h6aDYM2qT%VL9C@q(0n8FNwsvRmaUnHl;EmU2`iEi_EEYG-^Yd`|fC z#8ZK?^UfaL|H>>}O`)Nz-qwUE*vYjeUA3#*G25i0v)i**u3xFD&9X%&Pp8q?P}h3p n68~w2DXUBq36PHvJ)j|o6G zv7E4jRPW{ n;y=x>TqjZ{U1iQ}bt6+fWtC|n0rC-|2Q&nc9L+t19BmB%)%K3c literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksleepy.gif b/images/mood/niaha/kitty/anksleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c176148234f4731f6e81346f7067619279ab13b GIT binary patch literal 593 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zI0G118FaW9xEN#^q!<`j=4@#3blz$4dav&P1y37Oj)yK)t4r3Jm>U%+`Rbm9+mz1v*$B=-`DLPI!9nu()z|_tyu@G7~K) zrdcjiJk@mb>$w=W>UX|Rccpwk@W68kH%E-yJTC(W$=O?$PhPp^$UJ5Zv0FPiW;7?4 z$w;J6jbm(VV4Qv5edhb!Y7_4N`0N+EJ^52*QEF*gQX~UIen*v9UO{SFXM1u^af5qb zC5wA+L*$IEDRbsdU@mJFZz!5uxNP~_!f>Uu@cF4pi%lciHi{{ST1)IZAPaT%kP2pN E01yJ>V*mgE literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anksleepyb.gif b/images/mood/niaha/kitty/anksleepyb.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cf516bf3ba54e17d34bb7d02f314ba6e4c4f41a GIT binary patch literal 593 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za0W22GU#wIa52a-NHH+5%-PW5>Ach8^Hx&4-6 z9Bc3UsY&$I9h6ofc91>#^ILCzzjI-~%&wRgIZ^Hc_pZ#LDCx5CeN-a%GiezBO@2C>XD@aZ2Y){T9 zZgB6bWOeUth@8U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$|{U|?m?;bP!okY$i!U|^ZEp~cgAr^V~Ny8jnEZA>{Hx>T($S!-f$RG{Rmdlqv0 zEyXz2-uF|J=&3t4Z%IYUskEbxLYlI1YE2per+5oiFQ4Dwu)t-1#)Bi%RfTuGu$b{y zOdc%-yw9r^N;3*H={eGH2B; zT9IXJy&%+hMqKo~#Ha;pgp|TeO-w8WAr4M~IG7daV0oZ}7j8J=>Al0^%GuptA1upE zw49h`xlHj?)6K8vV%)0V`99s1^8LUA&n4U(F>dp`3>+k9Z&^Nh<(eb&m^H+1?c|uz zoLnX&kv=t!v9W=1_I>x6?{}+Bxc}p`U+nhePnAWfrD;i#3=H`lRbqJsscD_<$vMRh z?tPUk?!66>GrFeCnLB~GtW~_BXl~)My-yX!kkkM2eQrHmF+!&J@o}SrW$>QK$8RRg5xx04iw78)B`id%F=B(O9 zE3%BO7lazmh>M<=7`0%HkW!ebiHW5k#K9>L2eSelEDv<>!VM=py?0n#IlKGogJqeC zmJ`z~mnoiVy7~27j9c|P->17$z8`qtxrCb|#%-RLfrI4iEz2jbTyta|vxeBMog6co zlgnfz(x=8THa0NMzVANs{cg1h_kVo$i`}05sj?`wG%YETfg!)6N-VD+HLbHfIj6Y6 zy|0qRy|*E9M%R=%b0;vDwTd?s%`IHEd~IR4Qd;=@)TG6x5p5gAltZm0_8pLgx_U?j Gvo!#pWd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcONgybfVw*c6uby`FD1g=^SKUy z+$}2zba(sidB=YGcsU+YEL^D+V}4w+oS~w!*Zrb!xbx(oK($?q*u;gP~Imvu#L2K~s66W4t0uXp@x+(BV`4>x|km=V}}0YA)>SvNmnj>x%4IwW4fE cwz>V9uAHR{Gl4FzwKSL27pamQ!Xa)A0QR>fRR910 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankthinkb.gif b/images/mood/niaha/kitty/ankthinkb.gif new file mode 100644 index 0000000000000000000000000000000000000000..e89e20e07396495e3b47972d54a6283ee3429a99 GIT binary patch literal 778 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zaN01iGU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5XqUG3>*wHK*+$dc*6-x=Dim84{SZ(s1S86Jn`XzX-|)r1}#{{ zl+%`Mb9t@ynK|+a;l`pVyYC8QxTwuUP^?!=W`tZ zxm#8c=~bYDL+S cY;*fHT{%k^W&&MaYiTa4FH$8rghSjK0LWt|_5c6? literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankthinkg.gif b/images/mood/niaha/kitty/ankthinkg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f522b22b992d5992032f0fe57d21ef1eb2b8f5e GIT binary patch literal 778 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|!7+4u}co{euL>S~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8!3q7Oil(41{ok^U|GE3geCJ{i~9$*o^Mo$x)z@JaKW^v$4i42 ztYXS(OSZYZR{P8x`Gjy|(UjeH1u|UJ<~PqfW*OnMbiw_cOj&^qvz52}`X$xBNPXQ6 zn`LEw8~k@anyam!l6&CZ2~DHwKn+W|{3hFwqWqdFT_eW?MV9283GTs6EK~faHMh+w zFm~0f&selrMq4kiq$_ZKu*2pob9>VX*(dERi9Fc&!I|UTH2zM_f!rk+^ z4uIS(D+qLV`|f$ie)@Ph9#Sk^sT5;=T(X>@qO#ZhqHwtLqKl?u?|Q~m3V+A`;A8|P{+?CY{NZPx3G>{+#< eY)Q7c{hF?vr3*8GF0ZvTm(>@kk{rSzZVdoVTqSb= literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankthinkp.gif b/images/mood/niaha/kitty/ankthinkp.gif new file mode 100644 index 0000000000000000000000000000000000000000..94735e4e7240d61412d44e439365ad358e679959 GIT binary patch literal 779 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ|@7U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmatWJ2@FR7-WEufo1W96PC<-E$$!KdcIL1>RNc>!v)ix z9xn}Au!z7pj zBK37QY?hVzZSddyXs)(?O74MsCp3+!12rt=@|$c!it=l!bd4Mn6j_pUCb$PPu}txw z*4#F$z}Qu@K4Z~h8Ew75lCHq{!48|V%sPBqN7Aq@ph<%y2*iY%c`Rw_V;PxY@eYRjCfZJevQu&>M7v{|n! ivS-zbvL)H(_G`LwmM+W$y1drXTvlJCN^%H?xHSNk-z)b3 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankthinkr.gif b/images/mood/niaha/kitty/ankthinkr.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed6ecfdd3f6866490d7189adcbc06ab0f8c83f05 GIT binary patch literal 777 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$QnnH4(VM0%k&!jCe|CRV>I}8Xvt*=2 zS2*gn%9`eh8)j{gjTA(3CMN?2gA5Qduq@ti!jgHf#r*?Y&o?SWT?}41ovPjmMQ+zn%ia- z7`tlLXDnJQqpcTM(iJ#A*kN;)xxMLx?3LS;9rSBj^z_G;|o!VCYnwiG2k<67}Zg58` zx8=$i)iOs|B$nD}i-fip)>T+J)-$n$)lGB{nKIQgvSN>PR8f~>_h9?RxO^|Z9; mm1~DBTW&f(*Ep|Hskuep#nN0>zxyc6;ox+EaQKi2aBBedVJ8s) literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anktired.gif b/images/mood/niaha/kitty/anktired.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4ce64b1482c228f4bf4b85a45990cbc352b8648 GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSOXYX8FWDMAngn+`!<~LT)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y{f#`%h&2%+%vCl=S{|H2Zy5d5oU?A zpRHv~v?yteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I zL5Cp3OClgI2{8yVa569fy~H8F6R>K@;#V?Y|JtBQ7BmE|TCxBtnF5g%0P181>J$~2 a;@K@z)Ree$t^}(e4AuZZs(Pyc literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anktiredb.gif b/images/mood/niaha/kitty/anktiredb.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc677750cdc35f001b815f2c5614ef493cacc1ff GIT binary patch literal 374 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zum&)&GU$L5fV4BP?Avg{bM;<}*JpSCPtfQ~$()z5YTX*CnEY(k64&FOL^zoCeYf;V zF!&%?xKnmxgoIF|B*Y-Vz{$W2^b+@m9;cTqrjHvnX9$A5Y=bV};Pg_)G`Zm=R6YeE&koct cDlo;fTc)TfapznKR)I*b%7 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anktiredg.gif b/images/mood/niaha/kitty/anktiredg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2389d6a59152b1a537fa271eca59c938abb37707 GIT binary patch literal 374 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr7<7+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k z@BV`hL5P<`Kwc7J5MbbBUK7H5;@K@z)Ree$t^}(e4Auan1${06 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anktiredp.gif b/images/mood/niaha/kitty/anktiredp.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f0652d8a13e06683cd895b98e5563c6b2e87515 GIT binary patch literal 735 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ?{8U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|og%32oJO=ew=iB@k@Km^;(p%YPlll_;hNKS3pFTA z+_K<8UduI~!0qNXd-5*Ve-k*koxPp28tBeC5vE4V+T1Loz?KZ%9;>v8;=R-L zdL^=Qw4J04m5tRF&D2v`G+QPlfHkDQIMcLDeBqjnnNd)u+Mqgh&<1G=sym4aQZ9xY zg0XV5)>xd`*utDv(wQR3d5Q61XqWCrBPIbAsU~(MJ&h|a>VaM}rCKK+*1vaa&YR-H z&MbC~$tf(2iOt0gO?Bp#R#oQOm8HPgFPf=WB$1=6E4^Ueg4oPilb6kvS?DObu(#ZC Q;>Os#{EchGfI(^v0O6w^5dZ)H literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/anktiredr.gif b/images/mood/niaha/kitty/anktiredr.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ea7d038a45ad66b4cfcc50bcd2d53dfdc215955 GIT binary patch literal 374 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$RsG3uW#o~#%c$LqV*AG ziL;-rWlXdw%k+xMcN7Zo=`f3I4vVarP&lcUrEvPxa+c}dbC_r8G0lyb*}o_vWTA$0 ztE;zdcS`UU_q>#F+qEXHUK^Jy+i%?FZnHnd)ZF*vp4BZI4%99<)nnFv^~TLxx9{A& zcmF|$AjC@|ATJ3q2rzImFay2By`jhHC5!3fM$H+5U@zOC%QrZ^lrc?icnOtHLCCWM e^@|Ej@$8lyteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I nL5Cp3ODP~PNiYa9Ff%X#y~HZO6X4c~@GO!{K|`QJCxbNr7DjEO literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankwinkb.gif b/images/mood/niaha/kitty/ankwinkb.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad7176c28e80703ec751096b422766ff4f0ab00f GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu-Y)NGU$L5fV4BP?Avg{bM;<}*JpSCPtfQ~$()z5YTX*CnEY(k64&FOL^zoCeYf;V zF!&%?xKnmxgoIF|t|!m~&+1r31?oeb6h{j6_9 literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankwinkg.gif b/images/mood/niaha/kitty/ankwinkg.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f5322d666a441d4a2d848f738c3812b644b4107 GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr997+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k p@BV`hL5P=9Kwgqy5M*FxU;=uHRe&eJtrOu{B$U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWMQ>oU}Mk$$%C{ru8n&VII*G0~_9Q7FWx!z{8nEV5=o;iOuY!s%1XS*Cl>VVq|DuSH zg&NMSuHLrYDZyLZ^HRcX*P6I`ZCtKwzj2$p&HfZqb6*qI*wrl?4%99<)nnFv?dGl9 uckbT1|KMSVAjD58Fh4Oe0KLh=bioDTRS5<`24)5(pfIZdPeNNKgEas#0C9T& literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/ankwinkr.gif b/images/mood/niaha/kitty/ankwinkr.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a2ffe50a71ece6637977ac20c7a034b5994682c GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz1la-t*Mfqc_w@Y#{~yE$1I7Q`ey$RsG3uW#o~#%c$LqV*AG ziL;-rWlXdw%k+xMcN7Zo=`f3I4vVarP&lcUrEvPxa+c}dbC_r8G0lyb*}o_vWTA$0 ztE;zdcS`UU_q>#F+qEXHUK^Jy+i%?FZnHnd)ZF*vp4BZI4%99<)nnFv^~TLxx9{A& pcmF|$AjC^4ATLQU2r@7;Faf>9D!>!q)`{>el1xEEphG8vH2`g-ZpZ)t literal 0 HcmV?d00001 diff --git a/images/mood/niaha/kitty/index.html b/images/mood/niaha/kitty/index.html new file mode 100644 index 0000000..fb79b8a --- /dev/null +++ b/images/mood/niaha/kitty/index.html @@ -0,0 +1,116 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ankangry.gif
ankangryb.gif
ankangryg.gif
ankangryp.gif
ankangryr.gif
ankawake.gif
ankawakeb.gif
ankawakeg.gif
ankawakep.gif
ankawaker.gif
ankcreate.gif
ankcreateb.gif
ankcreateg.gif
ankcreatep.gif
ankcreater.gif
ankfood.gif
ankfoodb.gif
ankfoodg.gif
ankfoodp.gif
ankfoodr.gif
ankgeek.gif
ankgeekb.gif
ankgeekg.gif
ankgeekp.gif
ankgeekr.gif
ankhappy.gif
ankhappyb.gif
ankhappyg.gif
ankhappyp.gif
ankhappyr.gif
ankhunt.gif
ankhuntb.gif
ankhuntg.gif
ankhuntp.gif
ankhuntr.gif
ankhyper.gif
ankhyperb.gif
ankhyperg.gif
ankhyperp.gif
ankhyperr.gif
ankitten.gif
ankittenb.gif
ankitteng.gif
ankittenp.gif
ankittenr.gif
anksad.gif
anksadb.gif
anksadg.gif
anksadp.gif
anksadr.gif
ankscared.gif
ankscaredb.gif
ankscaredg.gif
ankscaredp.gif
ankscaredr.gif
anksleepy.gif
anksleepyb.gif
anksleepyg.gif
anksleepyp.gif
anksleepyr.gif
ankthink.gif
ankthinkb.gif
ankthinkg.gif
ankthinkp.gif
ankthinkr.gif
anktired.gif
anktiredb.gif
anktiredg.gif
anktiredp.gif
anktiredr.gif
ankwink.gif
ankwinkb.gif
ankwinkg.gif
ankwinkp.gif
ankwinkr.gif
diff --git a/images/mood/nolegs/aggravated.gif b/images/mood/nolegs/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..a92fd49eef26fb6f81975168ef9f68e7e56d4a77 GIT binary patch literal 1224 zcmc(e+iO%;6vo$tDd>Q=Oh&QDq(;*)#|p|05*w}UOeTq@NjqT@Cthd;yW4oFG`)a6 z1QqKIC5h7L3N}rx(TNul4XIHd)WA@aE@)F)tazc&YTrr~3HVS~zkT{gbiXb3+TZ$p z-#VviWo6mY4N;2HpY-1`M3#t&gh&aMF=Q+mCL?6jU0Ordl4Y_&R$VU}VoS`#Lagqo z7!pguBtoK4A~mFzlu3mY1+*azEj&iIx;gGxW7rrmM%`Fc)*8#kim~b_aLLv%8y3Ur zpwKJU2pbV23PwCNYK^i{F^Z|6h8Unh2`t=UFti~JEj(6d$kjM(tyrthAI73$wk(#_ z*#!kIg{_Dcg?m7u*D6~TtFVVWfQi?L1O5R4hoFWSph1aNa9}XBAq_2c$+>IPIKr$h zNch88R3a>jTwxa!xMUSpK5p)-%cA-Fp2f9iyL)+qQ4mA^RTO@_j7l zz@G$Zd=A(W!hWV3q~ug{y6*@VdXx_4#|A=lDE9HCpRdel3oI}CGJES* zek9dhzP$0k2T!u4UhzMFmtJl8=4d2X`{Ze2WLo#vv1HShuJ9KJ+m&|R-`+8MQAv8; zl1Op7pr$Qv=&y=o(eKy$ZSSUyjf+bL2Y20g@wGQ|zpfbG_qZo-qAmQ#HSc`comg#e zlh<;h=g7+wC#%NGr}ejYt$A4ERjsf8Xr$}?|Dpm z9nVgUg%|7?&hUr5tG0I5m7bZX-aU49^KUm#uMJ-h-5Bk(-`}kro%Pw^rrYO7zuIuAL@us|vfoSvFeRQm_b^lM}HSyWgk8RFOE=aV#y09v@ zrLc9>0ssI2 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/amused.gif b/images/mood/nolegs/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..bfa1e16bbbb6bce172e6e6c6d8f1a2b01f6b631e GIT binary patch literal 1218 zcmc(e{cDwF7{{-3SmrdtHjk*B##Ropb52P2HaAKb!{dCJG&PTB>dMV|;~1J#gk{aL z`M_+eChnPDp?M@-l2Z6yvEVFU@Z~B<6el%;RHPrQFiDKj<@bL2Bf5XPxUc(reZJr8 zd8+5mF0W`PpaOb8{~beQiI_-;lu#K%#*$$&LPp)CHDoPWCM#ss^|B$h#7r#2>Yj=r zu_R0)Bnl-`LuyHxR7g=k8`99iV|1&V zy<&~95iz1*#8aczC>s@{m%M%tW_!}h3~UV_XnOwM;q&p>pWn>v+;F(@#MV^FsKPZpNk5T( zF4g7z@qXo-<35`;siL_rwj`YVy?es`<*8i{uXMNkGp4J*;`Eje<=6g z`9BTr{Gll^P(J_XGaFCQ{5^@a2SdB__q{fA^~LV^@yysehZeuw8o#k%RVdRw{>P7t zcm6Umv?bPdp!1_=20poev+eJ%bNjry(%kCT-@UuKEM5Qo+GKtz8mb&#(9(YO(wLFv zO-cL2@SVEZH4T5g`qpsqZC;tkDZKK=V|_!Js%UFzZT;lb>HO-@p`NFzI>z7cefwJb z+1kzK+gqQ$GPUgbq~__lzcp;Hno^OMq>^j(-Jx_*am}cRw`XxQuWV5z(Myj2#P0rQ literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/angry.gif b/images/mood/nolegs/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..a59e7e210a63aa6e460d49db56f49692e571b15b GIT binary patch literal 1187 zcmchW?`zd{6vt08^|~hxn@c6u)Mc{k72%ky8FZaE_1eVgy~>8uP1xavLogUg#-*q= zokXcz^o$v{d~mhtoY=|-$(=D0Ibo?ae?+mO=k`ED%$?q!Z~hH^o?H&+^Ld}w`+dH5 z?fQn=SK2G7lK!Uu4igEH5*d*bDrRCKR$?Re&=e*S5+yMb4|kPGg;Yt6)WcI_G9gnk zBXcN`Gr5o}xsjuQHl(42$GGibPB_A>%*O0tEGiKeWib{H6lkijDyy-2fWlo9Hf1w5 z2P2-c3%jx#JEnpfVt@uEu+YO`XhRxWcqikmp>ArD~UHR6DOK)@lWAqHqr;wm^W7}}7AmWSj*8#RupdI%E!Fcy`Wnj=@( z1qGVwrj8tuGy(t@t|Mr;MU=<`n0Spizy!l^2x^D{8ZUtb4h)7iq&=)C+(sKUj$>m8 z68#TIK^mU}wuJED z38SKEPd~^1^Jo5}l4po+(~>YW{3j?jNy9UqUw8iG==-thE$a^?e&|ico}0IQ^nUxQ z-YJQSiwpj$diT(r;j?otHT{w7iPuSg?T^(f@-Mx%-v}b>UZt0|MT49 zSsy1BZatJ5+xcDR%~V&-wPMz4N?Mxsjvs72oxWeyu%`RXZRzT&pC9yn^~DRX?)d!f zWbZqPe0RL^w-dSXnPbHd$7S2@+M%w)-(Py~_n$WQH}lBGiYWt)PnNddsL38Vzw*=N zXPP!8;$3(1sjGM1diiF4&ygqP`O-I<8;&NwJ$S6|*_O<-d7Q~Uys`P0vzeB*#z*bR z^yu7@7@Zi-AInay8@@6>mcLNncDb>qcTfD2%;DYpHjPvqsB6w#>s&Q4(X%+WuA^A` Lc2#*9(aL`Tf?oC? literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/annoyed.gif b/images/mood/nolegs/annoyed.gif new file mode 100644 index 0000000000000000000000000000000000000000..99f6cd57464fe15d6c860e34bf65c023a9e15629 GIT binary patch literal 1136 zcmc(e?`zF*6vq$S?5@<9dnIO>WV20~Lx%jwTy||;8}6_t#_WSgd$8n3p;6XKc4O%i zg*EGLy4r3iJn$o{;Yi&PC32NCJmA5wlH>jP`XhXvoj&LDKCk!te7|c$YswaH&!as0 zME?#G86rz0L`tZbi4CzO7GiamhRGN*mW+^5*K3)qA#2GBS#?i^Neqc45fX(GDU%vf zODd!&pbcqg;W4_^&2h&tTV`QaHx`vKY%CjLqmBZX*08l~g{?X$^on7zEW)B-#8Xzo zYFUL9Q$Y_DajY?7j5>c9i^^JK#aMNAL4ixLM#PB1J)qEQ z)EX6|u!lT=iPwk&{s94ppoSQrL5WsyU@){H4J~!axogxoVy(I$;SXa`iC9tO3cH}d zrB$(t9Fa5v02kU3G~6OeF$4*J z7>i0&-2%P!I|^^3ZlB(g9F&*4TdxcO^`4^NFvi)_8JW1y|*+Kk!FA2I{H zDfTT^J!bIAnilCQt$dt(KDe?Vv-jfdoLO8mtKm;W&-_R*5UEb3`_Fb?3e--m+nUNO zs5)Iz6ZbX8KQAmU>bkw}YP7p;S)w;_ctc}jxV256?4x$sR&T+op9Mk|M55XBke?^sp06oV`t~hxUjh9`K92~--XkT zk9>KRJz?jvk(-5S;l6O%l;w#Rq1WLizV|FQ+Blpsboh7c-OkaL%6NK-?2U27gZUmv77JpBW8Aw$!wh_@>8(R-K>gpFm6h0t|Fgh5!Hn literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/bored.gif b/images/mood/nolegs/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2606f927dc1668bbb0d46e11d41aee962a535bd GIT binary patch literal 1062 zcmchW-Aj~F5XMK@qJ^Lmiz1O$mLRYoPMDer#`=+lxS|{8McBm`5onWHK|~RSl2BNI7llDh&w1-_=-e#Bob$}@dFI{HttGj64Vjcl zKj`mqL`)<^N@Rq}IdV)+$SFDVO?JdgEW}D|{;oI@CJ_=PG5=H@DU%ARk{XoA92t`d znUbM^Hl(42$GB~Njz8?2IH%5;AB&3Fu{c)8<|)t=b|OyHiFqj8Rdy;))v19IPo1$d zai-2N71R&|G$?_E9tJ}j($K7kno4Gs8mG_xxy|e&=gZK z|DzYs3L27=}YoLk!S(2`q46Ftj0UentK^+Ng018$*!rhq0*C z%r7ulzo!T`>h~Ee$wLLX`}GD3mFj}^?d?;5`3;`@8Tw?7tlZfIN8wkEy0Dy=Y_y1A}q zx}v9`t)QiGw)eRt;)6xyRo5#iqwi}=D6v|P)K|>Tl(oM~bks=s($0PS_QKA-+0e-^ zw-OI(o8DafS-m!XzjjG?`l&rPCNH0}oYs{?gQGW7Q|epw-nWUT9nUJ87v{~3KZzDM z9vWNU9UHmwsrm8e{K=`|(97vZyH^}Yp6O{iJ^n8J;D@34k(7;B?{<}r^uFIwQy3p8 YKN~6D`z!Yae?PHhB(#0o^2N025A71dnE(I) literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/bounce.gif b/images/mood/nolegs/bounce.gif new file mode 100644 index 0000000000000000000000000000000000000000..a49a118a0ffb537207c0fc0c114e48605a736d33 GIT binary patch literal 1188 zcmc(e|4-Fr6vvMnBg8e*iz#e;k&PwB8uG}Bu~{2}VxtLoZ`^jT%ZaBcUu-n5&gcic ziZ|I5nz|m`RM1Teh`OkormNLmVLLF?>_S`f2dP&2OJwWToX7X`>5u67?d&Uymq%VaHCA*=4G z7!oG2BtoK4A~mE;YDt9@1+*azEj&iIx;gH!G1eF{M%`Fc%!aLDF|3XPmzIsS#)`4( zpwKI9#2OJJ3PwCN%0{hGF^Z|6h8Unh2`t=UFti~JEj(6d$kjNOS(w%N!&p?-vK6-K z?1BQ9Vp)Vm;T}-vWworr3VX-{n0Spi;2#ih2x^D{8kA@S2L?kM($G?uoV!MiBi5=5 z68Y$Pq~+0C1rlLBlPgL>|DzYs3L27=}YoLk!S(2`q46Ftj19 zZbhye*Qjw68$*!rhq0(c)h*ClzoYOr>h|d^$w7I!yY+feIz}%Yw{6d`L-stl<$GAp zfj0@#_#Ch$ga=O;^`)EkKb#f+q%9ztp;9;7{S%b&m_A#Woyxd*IQrCRVeZ7IgVo*L zOX33)8^6iSSyZsID|_`b!>xtY@mu3XeYJ;Y`P|FY>5z(T`^nrQ7#6FCJ-XnL9LoW$kahSB@o5 zt{T4|x!`};&{u3;JwEksS9SEo_KN;MQtKD4BHGA$HR^k|`0D7lNQd(fwfdP)VqeSVkSRL`Abn z9}J_s9Kzrfg!NEFfsO|&6(7n6>p=w3iU=v1*8b{mXulkW*?Y}zt@+Nu-0bvSMe!6* zKj`ljTwxa! zXtD|`azxSy09?3^py3u#A`f8VHR1ph48tL)AqHr?1Qs|j7}}6lw<32NZPYl5jUh<* z!&p?J>K5p&-%)rQb^G*|NoF1TFndkD}J6kJh)vrcgqGe>CC6_2^Y;!I8Z1=9J7C< zA?I@a@~VZB{HEM?-{YAbN3+WJb+_#8+c`RPKQZ%GdF7Yh+?Ex`gRMPphfds#tE(Bi z6D&K~The}Uynk((Z!mK{?^0EC-$-xXqA&Hv*tU-y{^z?hhQ`l@V(Yp$pZyiHX|k&# zY52hHijC8+Qa_#g;IFz@_`YXr<4E=5x11*#DaD-)YZ50W@=u>B=xHi_cX#qxUu56l z)1qL?vX@hV%DK>$6uwXsnw^!l2S4M|vZszEErhBIW4`wcd@Y?%jn+a literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/clean.pl b/images/mood/nolegs/clean.pl new file mode 100755 index 0000000..586676a --- /dev/null +++ b/images/mood/nolegs/clean.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# + +opendir (DIR, "."); +@files = readdir DIR; + +open (HTML, ">index.html"); +print HTML "\n"; +print HTML "\n"; + +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + my $newfile = $file; + $newfile =~ s/\s\(\d\)//g; + if ($file ne $newfile) { + rename $file, $newfile; + $file = $newfile; + } + print HTML ""; + foreach $col ("#FFFFFF", "#000000", "#C0C0C0", "#FFFF00", "#FF0000") { + print HTML ""; + } + print HTML "\n"; +} + +print HTML "
$file
\n"; diff --git a/images/mood/nolegs/complacent.gif b/images/mood/nolegs/complacent.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0c4e1658d1fc343c69387dd72d5059c6f8a2c8e GIT binary patch literal 1075 zcmc(e+e?&D6velf$_9#w5)5iG>Pda-JTxI8L}=wh8l)o%V%f&R=z@wbfsR5_6dFx* z>Os>Cam+Cg31P}gO=TBm5L6I!QMy4OgqqQAov%Nl^R_wrto>VSe_!7I+~BT?00n4) z{vAWaM3zX1lu#K%hRIkmLPp&s8)7E5#6qmD*BY`+){+&n>Yj=rVG>IsBnl-`L&~I< zR7g=k8`99iV|1&V;|?2RjS*wijYY+5*cukY>L_q&*;s3=7^@Bny~0MU5iz1*#8abe z)EX6|m0fk;x z%POp}hdh9Z*N6lD0Re}gh8UnhiB@o6Fti~JEp^GcYt%Smt-2uL4`We@SW)B(yP&|O zRk4a3ku(AT7updt+#*Wk0ZhC`9AJWBI0QAs0F9Tx0tW^|8`A1lkFCj1{gT(SDyh42a_HpY!Ii~jXYz|P%fg{= z!{=^H_q>a5Tb}>@wyvr?+Fbfz@5G*?N5&endl!G*pM7I(Hglk+IXP7 ozisa8T>SOg$MN{`p&!*H>jvs;XMUa<4#ZM+#}<4I4Mf?00Zhlx@&Et; literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/confused.gif b/images/mood/nolegs/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..2babe08269616cecb1128928a4977dac37a2ef94 GIT binary patch literal 1060 zcmchW+e?*E5XC1mQBbl%x{H?xK_7};qS%cjGwZRA_7Ikr0TrVMdkTV(9<(SDB&QoD zhK0AVEF_bZdeIR~3$hFfkwT3Of>Q=fYk&1Ov|kRx?7il<)_iCGfxN8j6N!{aVfuR< z5fcfK5*eX#jvSK{a!Ss8lN~V=3$YTLzblS}NrXg6%s*8}%A`W7qy{B2N5*7Arer9f z4QXiMF>afm;}1J0&Z%?e$D(3(ERNN&c?vXzorn{4Vjc>2m7R)Hb!uS5Q)lcG_>&8ydhuX2(vPq_lL2lL|Bx?yj@VBsluwP2KRu%T{dA;HrPWR zz{G3B0snx2Lr_Bu(4fRsa9}XBAq_3_$@w;F92GGiB>Z74DpgTKuCNOVG{sa5IU;EU z04`id&~S?=kq0pG8gYOLhT#y@5Cb$`0t*}%3~fl8Uy;9!HfkKh#t&^9u~t z?tZ|`V|cv|^lxW4;%VNpy?V@Y#2J#Q#K{bhDCp`x>F-;dBqeUjRD z_U6H{_V*VGOQQxxhO3$f(%)SAzPNp?_i^2~o`@~sj_Ll&aM!8%gs-K;6PeR-uU>Z* zg-Ui7&($yXR6e^?d?v1Xrnh?NdRyM|&Ue$u~V zh%6Bk36T;iW5`%COh(A4yR?R^CCg-mth!z{#Fm(eg;?EFF(j6RNrXh9L~2MaDU%8* z3TQ(bT6m0Zb#vUY#;`GBjJmO?tTmR66=T&=;F7IjHY|qKL7`Wy5jG-56pVOk)EZ@@ zViZ$B4KYB25?HvyU}!@cT6nC^kgIXnTCrB0Ka54iY*{R;vkMAb3R@8?3ip6QuT{1x zR$&i$028kf2mAv94nYkuK!Xyk;J{#LLmFD@l5^LnafDf2kno4Gs6<#4xxy|eaLFpH z$Pq~+0C1rlLBlPgL>|DzYs3L27=}YoLk!S(2`q46Ftj19Zbhye*Qjw68$*!rhq0(c z)h*ClzoYOr>h|d^$w7I!yY+feIz}%Yw{6d`L-stl<$GApfj0@#_#Ch$ga=O;H8zH6 z|KVh7r7do@`zOfvhX(v@yW{6Z`ip|Gw|yyds|#%u zzjfQVFRpj0E2*kEekJDI^{)K8{)nmBPcN?)ltt~WA6TBCru{kN{Jm{YU())T&NCBB z39VF}+0c3{Ce)K&d1th+YcL$#^yJEi`TU`&VAI&@zTA@~<()D0%W0=t!j*JOg| zf4DN7F!O6B@E|Mk)&+lPLtfd@#mDD6;;s!9e?8pO(s=LDm(i8^%N>EL15c}NF7ZIg zp}IFwISVf?1|DX&ul=yEo2m!H$qNl{r~M!MqbuImeV#6_8Y#_PTb!9rf4+HRYRYM9 szm(b--JDULZs?#)lfa(1~tBID?uKc%dLfg$nA3qCpS|MW6)bJY_R! zY|PTEFa>Y*WKTj=$}UKf3?C{@kb$5cL?UXp&etE&dE1CGL{UJ5i;s7ts!g4GFc(3u9pq5C1zqFR`*m4i6vnYAyFui8d6Kj zq(X`U+K`489-~{`9CxfSY>XJAZY(Nmjb&rSSalS*WNVlWi(z$8=oM>(jffEiBc2+y zM%kzs#Z*v34A7ti7Va<@+K`489;-9tY8X?JJ)qEQ zm92_Z*h3z`#B0O>|A2r)P(uvRphPP;Fc{j9hL*bI+%;+(VOAF;{9!CA5f(+RunP)Y zvI;A5MA8TVTxdtoaEmCB2Qcv(aexVi;Skgi12kR&3mg~>ZAhzIk?Y1aY8=JJ5G4Fz zEGkiT3-s3SD7=ljeR@lBP+snCyoY&X$sn+4rk+OH~!2cyf2`TtTFB zVcU+%!}}gi_m+f?Wo?}Zw)bq>y{j*p+53u1x7;f#&Yr1mdA9Vj@=DF};!t|iL?n^% zq;$mh;rPnX?US>USI5GwBNqoE1LaPde5_L0A2QPiQTz}!*==S(v?(fCZpZXhb6zBEUt*t&k mu{Qdm@8jC}#C%_7y!*)AK<%x)jl=h&KOX&B|DKlYqvF429L6aC literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/crappy.gif b/images/mood/nolegs/crappy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a4c8c824ab41622cad7cf6f822a25109a244d2be GIT binary patch literal 1041 zcmc(e%}bS05XL9CkYO!Sl!~%10|ldCDzCK>&GbeV)}qw1PsZZj2qoIoCY8cPajUB} z5R_O8qfiS1cWNmJ<0deIjIu?!2+KB66w`Cw{)ooiy z5eNJO0uDh9F+hV7t>D05XhRxW9+C^!sBuiyLy+)?v8c?{9J#_SC~&E6>c|mEBLHxr z9YMn_qC_6R#B0O>CK!f8P(uvRcnK_UU@){H?O{cs8`r3D92-NB@Q1Oe%snhHT7RI3 zHX8OBEh#`nxrg;eQ3l2+ov`i5a6pbcgylzA!9g?$()b*(C4>i07=>B?<*fY~TR_xL zC1HB_Cn#%<+|&^p{#2VRI;n z*R{S24?c{^>qaY^Al+$`jKNMieE#YDkXv=gZ&V^W=6qpU?Ze-tY6h>o=@hwtV|snoIBK z?_nY#azsjGgo>G1h#j#Kn{Nt}2#F(667zQ*lM`}|oRTyDRGCyr9jTHUl*pJ&$Q+rH zp@24|p@qk|ZGMhF!t9up+5A{kA}o$YS4cqQr|ir_;jRj+V^vlIBc8Gen`2Wp zOa(Q>01ZlDp@+fHhBUPB*t{WM<2Vr&G4Bs!Q8_10#hJGY3N+P;s;I#|pm0~riK!Uu zArD~UHR6DOK)@lWAqHqr;wm^W7}}7Amigp-8#RtPXFf>y!&p?RP7S%jE-27+rp}Nf zl12dF!gT}FVA?Ig!d)`IAQ;v}7&Hdh)&NRqydR zyyaO*L*ilGl%-cT-pbUhZ5~Rbjy5-p44hlgn9%;OZ#P^j;&T_SgJD>c8Yx;Py~dd9V-x~rRFRo8DMYBrq+g7~=8LCMRyyshOsGMUVp z;?g70vW|P_m&V(Jg5L{&RViO;DmX9lE+|4X-I3uHZT$jN-y!_h;*!JnrdrH(TEOoN-541Ju&g6*dl@? zj5VO9!5F}S4akRq2uTyiI+4(XWJE_XY(=3Y5d5N~+SkS=*cZ3!T=^S3FO!{p&f34V z_MNBOTkB(~c{Go1(SOGfSt2G9A|+JDkg;T#jF3^+w1%uD%VdSDy1Q(MEin@dvAU;X zNGu7H2#G?8)R0c*n7)>t-Hj8#X0CR@X7SPZL! z!d(1tX$@K~K8SL3j?Vy!xV7>kP8vRGDU z7Zhj;TM;V?_khA(t87)Q!XEMfCSD^B_y+_Wf*N9g1|_b71B0OrX=tfS&b3kF2(!8% z;SXa`iLfYggtY>kXoGj6phX+ks(+9C&cc53rnr zU=pP9Ibcf&51ww1y8Si&uRr(Aggm0F{`f4bY2qnH8UvadlGjTGKAI!JBQ{DMS#n&UXch}Xm9eAQWee=VNUwq@GxsT*m z?p#`wxc0#Lp=e|4=8?qIo~U=M{_J#Y^z!T@8ULr#0!_@lT>3wa#Sk zPpyi!XF9{Fl$UOap7Do&Ubr=xZ>sV}bJKGQ=@o|_Ufny_pDZmI>Nqtb)m4i#`=7kI zpy#K-SJP+L%XrP+y;EJoUiQxVmAQe5oZs={)XWzXSAN`mac%9AEj!W|V{d;O?ilmu zU)r<%w_V>KoEX2{-m$!~Jo>@p^~~lqzs9Qn{wwo%RsLYh_1BhM@COr-@@&zz=Z|k2 zUH9Jh@P)&Z4YLm2)0b?R@AteLKUZ2@)|M>kl+)cCXkmP?tp2;?@0BOIHWf;X?@h?E>;Z4U%;vXNs`bwQqg(78d$dwUDOO7CSX5doZIouE#ZutXXl0Bttc+MF^s-iL6tiLh zBc3YJN{kX#f~lZ}7@$E3EZku*v>^>GJQi!n);LCM)>^DTj74RPHmr?UyP&`&8_ld) z;2u!u)nc@;7T7}`z{G3B0snx2Lr_Bu(4a&sI4~I6kcO7niL5@fo0e}nb2pVn?CGr3!ULy`L!7v{(w6OBVJtc6CIK7E-hQ?TKzo z+Evn(6{t=NW#zPg%&YRx`&4neZ*m}?8>&*nwZ8GP+=;xrl2hq{7;@rQ#U%uNryGZY em8F-HcZRol(}EMlhn(CwUq<)TEtwHV8~*}{Z02VG literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/disappointed.gif b/images/mood/nolegs/disappointed.gif new file mode 100644 index 0000000000000000000000000000000000000000..58fe816ec49fbebb6345d43ec6423ae264540eb7 GIT binary patch literal 1159 zcmc(e{cFx)6voeEqiq(}JlcdcrWP|V_Yy{pjTw`+C)1d%VK>qw6EY-Pa5~(4zq)aNLD4-2# zXyGxs)y;9o8pFnjG3v&mvesBOR*Y3gflIcA*{~Q^2Zdg-M%aiLQ841EQEQZqicw4j zHN*f7N?_p*gP{#+XyLIsL$1bQYsFf1{xB95vt_ZY&Mqi$DQrcoDBJ@Iy;j+(ScN_0 z0ZhC`9PkeaI0QAs01ZmCf&+u04QXhpOU_-R#t~+9LBb!#q7q?Iz$L4&B1a^R z0KkQI1P!-{5_tdFWT4KYCDC9uGO!O(`Zx)r%@T%*QOYz#rdAI72*RkuKI z{f@%hsN1KvBnRc??$+x?=@`9q+_pW#4%zeImhWLX2i_z|<8#245FR{XlwQNM|8U}a zLVZLpD9O!s{{)5op)=t_X15%^zB4R(RKc#twaqIdV;kDfH7yNKEYF^q)S5J)Hdx+k z_xaqY;O)J~MlFiEcmHjCptAdBVsQy)B#zJSy)I_gvq$yQLQZWzyEgV-dO{=GI&+gpcBh1HuU&DtE;pp}%crUb!J6KcS0g{ytPY%>vh~=OMdOa%ZJ82M zmv-V(*WBuf;oBkyUo3r^wx)S_zl?G15u@{pK7WW9nEbLaJ-ng4oL9ZO70ln?cBQGS zt+8NJ!w#AFEqLw4mkoQnHhy~0d~#vhz=P}db-X&T_|5aI-&Ovm(72ib9L%o#rFo6H~k1b6Yk?!+R>R&$p>X!fj literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/discontent.gif b/images/mood/nolegs/discontent.gif new file mode 100644 index 0000000000000000000000000000000000000000..d6c8606a89617fe49453d730d7f15f998f38b3d4 GIT binary patch literal 1035 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 LA!XefqMd&Mnls47 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/enthralled.gif b/images/mood/nolegs/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..796336b02db2b105d11f36ffb9b631ae20900c84 GIT binary patch literal 1167 zcmc(e>uZ!(5XQ%t^|Do2jT;IL!2~fOSrvK^Rn4FMPa^^4D5i_w6E3x@raU@J4BuZlbsX9_7 z6;dTND3LibCKECxLji3_Lko}5ZGMhF?3_5K&Y2&JirKL^R>$Tka4GCWoTwA?Q0P^5 zDo)j@fe}xgu`_X|&M+0!5Cb$QfrUE^hBl<3g~#R%`5H%)u)Kp{5~T4t zU`q%Oo-itt!LC!FfoPOsezyN7Xv%x)o?4X1&MAzg!WEyLiF|M%8Y#Inc&)3n zcUj$e>YBCh$WYa+P%8FSsB~y^`I_F1(Zq{i4vto@|E_I!w0hmlb6xGp?v2T8-O}4{ z`#Q!}6+X;-JkXKXdE{`s;bNvg@9v@#;avW!zS7kw5Zo3u4uqE9)Zzd4qhfv%K};2*a$iZ!17a!3Cc zZ)zwzF&C*HnU}gzmRmOM<=e`}p3(jN@7s5ly}sL%+mtG48?ULHu&;gm+Z`RP&*SIX zihlq4ept1&pYw#MZTQ!N$W&rKwkckkKIlD}YfglNgXdJOET literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/excited.gif b/images/mood/nolegs/excited.gif new file mode 100644 index 0000000000000000000000000000000000000000..0dbe4acb23fb504b9925d42c7d1674609c488e3f GIT binary patch literal 1222 zcmchW|7+D{6vxl-UY(|JwX3^rDs0X%QkM0sQp1>=?VDsS)J0r_K_dO)>HU1_Z}9o$ayZZPKCk!t zd~R7q>D+mB(`h5@Au~3cH{{lT}!eBa%h{;KFqT4Y!CAc>oiy5eJxH7!E-VF+k%bu)u-A(1x_S z6}j7JqsCEe3_-#l#-b8cw?J?Gj>6lh+o!iA2j%7N*6T&-7`=4dwmriR+4JC*?_oIy z-XuulbHJ7m9z0=GL?i!yj8FF``yXE#QIcl6vF<-X=}+j`*r{^^6Ap!DjXzp`YEEmY z&^MzpxO1aFqo6JG(){MTBLi9C+{)j21D!|r=fAum_jFEIdE*D+P|wx;TNUlk*IyeB zjiQXbFIM{+-mmvZit?KhVcxqqnl))+&dhsPjwDK^?CxFFaPv-4!RXe+{cSIme%95# zqUOqnRh^SZ6~w<;5PdXMv2Xsp?|Pz#x=R|?gA5RRV9%q)V z{JVM0t&uHbMsku5R`&nccKPD{UwVh*V|Tp5OQvP}B9Tu*k=DkV<-s3X0;}rYS$`vS zqIi6AcU}sHoQ*3DM3zHXBm8^KTx$2GD K(qMq-wSNKXeh1_L literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/exhausted.gif b/images/mood/nolegs/exhausted.gif new file mode 100644 index 0000000000000000000000000000000000000000..a90d6ef19ded7c920a761d38b17635411c662c30 GIT binary patch literal 1343 zcmc(e`%m0O6vZ!JS&;>F!QBNP-7b{chNV$Eih`D~2<=iJ#iBf#-3p|P)sSdO2~B7! zv|^}|lqS2`j*lji0?#JDSgQqaZX$im&BFs6^sNYAxKCP zNe;7W1@d&mQrc#SyV9}sW|YKQ?ElxPJ9216Ut z&{8@%eT^DN3ZZn6@Q1Oeq!dyiSJ(vwE`^dpAx9*Q0KkQI1P!-{5_tdFWT z4KYCDC9uGO!O(`Z(ks&4xJHemurUM)e;A8ODy0`_u3uA_8`b+Xm!zT0-1U0RC^e&* zj^4IuSRj zd%XLsS^k=rE8I>`RczPxV%wQFW?};eYc6kedpmNBx*eU4v5w+uF9I z4{ttg%~)NR9LRld^8JYqZ;y`coV663^&Br7`lPTo!RyVt>(pGrLi>foan*y}`+eC( zd#f!;&dk*pt295=EZe!Mtsvq!_TE%?gOsO`Nj`AJo$kW?HRU-&EbYxSK@ed zI`m!sjo=?w{ds$}g`cLj?$-3i{a1%4 zR*o$0T`0{LYa0sf(aFF|7s|(?*6?KSiZz>pm;4!_+J|l1%O7;g|~PXQyy4WFm|FWxLl&3ClWn>{VpE8F)t zpPjR=AG_puswI>;v+2;*BQ& zPTOcb*2b)9rLb1&WHlv)GK+Yj7MAhCaot~kg!|p;KKFG#*LA+%qLK|OSJf<_1@x2t z9Y@4OLZn1SsGK9m^>GJT`C0*Eqtg%;x=JEGiKeWif9T6u4AjRaS$0K%tjS*pvhBl<3Wj;B7jT%Qq%m)d77>i0()Q~Ief&!OfDux`9 zGy(t@+7UF|B1+@|OuR-MV1i*d1U19}jhDaz2L?kM(&ks>yK#*g$FMO334a)iO3nNN zgY|ogV55GY!IC^wkh@=R5T$1f((&644146jgI|7t2?YcM-O07&-R63Lx8f(svaKYg4tntFkXjbX| z`1hgPN0yXz%^AvVFRty2?%7__+SwMaU0=TENomLMm7JXmBgN6nPj95fznjxu*BCBO z-I^G8HZvnRIlH4W)UcvsRH~;9w0};yTXAc4)4GbJ$=L1|sw>QR@?%+1dHwgUzQT-8 z%~wuMR_}Xsw5IA(Y$&65TWe2EThm}?Lsm+xYN$R^SrC{1?c;;0mNWgS#bbvCn@Z}} zZE8Jm@YTUzqm65)zEo$PuNa?x>%{WSd22=zUkt|4mY%Zog8Od=dX9I;V!4m|KQ!g% z%_u)|@^SQ7UF7(kRWEtR^@Y!$#qOPZ*c|TveJ$y5`g-eM6q=eBdDA^IF}iVL*4G*H a_ini`d9z^l+TL(Z$LYl>XOgBT(CWX`z|)oh literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/frustrated.gif b/images/mood/nolegs/frustrated.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d57cb6dd66e4a3e7005cdcb926416f70a1112fe GIT binary patch literal 1593 zcmZ8gZEO@p7@oW9(WO1eLR+#lf-J3#OWSzcmX`A)p38^0NVHcy>ZL%-0V!@F$YP@` z;!zfDb&F6IQ*;w6x_*^4C~PUnYCmu#X<0GQQ3R&d7>6Kcqejp8gL7-*51qU-nRn)S z-uIb#XC8cL*`i3(Trd};!DP#1G6X@8BuP;eP16j+uq+#iL^zJ)c|I14B@zii5JXXw zBuSQKP1AH;Hw?qFEXQ$N*G;F>5s$+#G({m@O(W=-1~PR!0@BdtScWDE$N{X&P!*BD z!XyKEfOvq_q@_wwU{Hd-$IL?~d#07?MYF_RGr3xsQ_F@}HwiA7T82%QHR zm9>(jYbmatz%s4yMA{Twl@)l}wIo;P1debGp66JoGnzyz5@&0aZE2=TCwLN@AY%iT zAxsry93ToDv_(}SY#l^cfSiO2*$e`@7Lz3=Jvm{aO(BPH5g`g7;{wxQ6Nwndc}Hg` zid58uAo59(mz1OdC0UUan^z4IHs(N?I z3$kG&8)A-+F%do{TU=6Mc#(=}s^KIRJ0_WIQYRUn;v_O6QoPEGCe14mE+%WXpxBCL z@q$4{6o%zA0~#ho2+OjPObT8xy^>;#UC$;vcGE8U$MNciFoqZ-*LARKL1ZIrK+jD> z>>7?I30cTBA$AbfY~l5kqGcUjW>1)Pky?uip_W$3!MQ_UkcrXv_Q9NSVWTeTz0Ek;)Pw-;Abau`9 zS>R~m`skxIFAnw;v@QGS$U?zyZp!^*^l;_+ajvlbccWn8YUlKZ?Iq#)CmO%$*(CO{ z-IY(C;|;Fw$;&nCYu^9)=+fh_S1&G$%-{UyXbG1)4$1;2#lyj^Pu5Xv-|TWntjy32S4x4o%nYC;#RVLr15I|w!n`!mpl^hh0_6uM%%J-(3h>u*~mb>icQ){-wYg5OMm3_Y8J&;p8FWL>(ZLL2Qd8_%{ z#&Xa*sNc;F1v{q%=U(l9Gm!EHiLBJc8wypmZtcjfdwTsf(+c+&(k}MM`7qw2!jY-8T#T&$O1FV1q>~%D>N_ z0KP!;k*Q5*OWFpGu9ayJTva|CDlPOK9IdF^{oDMe-V@wS|Hr$2S$eXeP4tzHE*kzi zp54*$M6h<_JE_4{pdn|`cd2DPOY)u_KA-g_Sxq#}EQ#6$kCAp>>4{52o#ExPxDX4e zws%waGtusrsf|rpV8+g*uk=b4oLTkFS^3@3bNh#LBIE5{U`KatU#PaV>EeN?b@_*f z*O7MKT literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/giggly.gif b/images/mood/nolegs/giggly.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b59f515335a7d7e78c21163fa914c4860722fe4 GIT binary patch literal 1205 zcmchW|7+D{6vxl!_PMy-SxRoxAZ7DQ&D~36k5LkV##Y;Op~jRuMeo%-IFK0OLX2d) zW(3v`BS$;)3xacK_ZIi+q#7~D6u0ug7LB;j4@Fdj{!soTk#&4OpZptoez_dZ^SsaN z{XU=jO6$wdugfl@WptPRJC2Bngh+{uP&r4A$q6|nXTHgfn2Cj0iOt^?N5UjRq9o>@ zsv~7mAyra?5}6}oG9gnk6wrn=wD1_W&Cl_NofGHOIrC#tF*_E=>exI5n!--Ri8?V4 zg}cg5#i=?qFyg5*b|%i$8K#07Vt@uEu+YO`XhRxWcx>K~uW^J~na%sdSX3e`%3|Iw zD9}`4RaS$0K;bT%uqhktArD~UHR6DOK)@lWAqHqr;wm^W7}}7Amigp-8#RuKm=6;E zFcy`ns3BL_1qGU7Dux`9Gy(t@t|Mr;MU=<`n0Spizy!l^2x^D{8ZUtb4h)7iq|L9$ z-$olXj$va668A|Q6U*rG!Q~y^O5S1zAr~3Z{Rs2h(%Ew!}GeIm&RPUTF*7XHJtnhwA zrg!qahpR?2^>^CpHsoUI%CouVmp%yVW0^apft%Zoc2g%QWjnmtYB#wPKT66s5{CS0zZ|3&R<~!!4`-a{;HuG`awXylP-Tr(s=uV`buDP&r zC^<6zVe<1^iQ0#DgqibepZGSPE1dXebwh7eU#jp$P2+U3OuO@!IYwzRq; z-!U47#bV>!f$u&UPRDy&1}>%xO)E}*-#Ag~n(K>qoo@VlRr_??mIaR!B?pO&;Q&R)*#Y3rGqdu!J~^J5#ra8@?o?T>G5@9C;p zpNo~IGMfq$9lPG$`(pg(^}#cPa;W@iaZlUQ?6#pz``;N{6r{>4%UsB;=}*M8yf8T2 c`g(KS@2ySJzb<=p<)Ku?Y_4-jJfs)y17J_|y#N3J literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/gloomy.gif b/images/mood/nolegs/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc551e0ba5f6f4b2648a7c55292a4a9c31785b37 GIT binary patch literal 1162 zcmc(e+e?&D6vek=!e~~SOkquf8f7(h8IFl&kc3Sd89j8N3uL9cqMJt72P?}k1Zyh8 z4pd}N2qvY`LoXpxk+h9&cCmz#=ppE#I|a2{=j)H?ylu`tYyZ~T-#5QBnqROsL?QY? z|BfMIB1!(=QOA*1e+4KWj2Vj))7YYkZ@Ysm^(bx*~RFo`7*5`_|}A!Sla zDx@f&4QXiMF}l^wafgku#)vWM#-d_2Yz>QHbriU?Y^*g_j8zAPUST8Fh!{~Y;;B(K zYK@9fOa(Q>01ZlD;SPhL4QXiMu{uMp#<9%8tj-_CqOz8)uvKRl6u1=2A}k8`fI=^; zWffM~Lmt4yYs3NnfPh0#Lk!TML@PKj7}}7Amb&EJHEJBOR$Y+rhq0(ctSEAYT~OfC zs#ryiNE!iv3+)IRZV@H&0481|4luzm9D*8RfW}K;fdhk~4QX{Na^1K_jicBYf`mVe zMJ1|kf!_KZg||_+Pj5*M%FErY*Nf6Idg-`rdxjmd=fN%C!*UM1Nsz|pfGr_Bc)}>m z`Y$K*=a4v}7nI|syMLm{|A($721{ZY;bjSFQ<5tVp1u<8%!<}c>KM!<|Ip5r)va00 zfsC88o4%#KOPZE4XLwV|r`WxQ@oV#ZJ)c|VhJ%IAf;}^0-L={4lLks7>ypDo%Y!-9 zN3)8XBMU=)n|2<#eQe&5kS~3FN^@%@II8#8m;Pvc*f(xR;^PH(JLBUM0!fj!oU_|! z`W_aHdjH_~zTPnxRxY17aCAz-w$*WOE)8@SSGHg4zOx{=KCR&7kgoKu(yRFed)_^+ zy11#ODe?O3ipr{a4OP8^xjhrAw%loNFRz^ZyzBfc->SAeshs}0F|ugG)Ylu|H*}tA zeqNVc{kb<#Q&w10^JsVflm6cuXWcmTG~@f3%}>^p9q@lyc6e<3*81SB*3;MgE8_gO zV;>%Vyu2&>erBY+?#$8=HA~7joJ;7t7oGkww|vKy>bHHH8yDxjsn|a(aJb~_*7~%) egJoY+N7r@i9?36HOiB&c#^#530ZR61Z literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/groggy.gif b/images/mood/nolegs/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b40a70f1b6da48dc1329bed60d47809701561bd GIT binary patch literal 1050 zcmc(e%}bS05XL9CUA%}9niOV+AE1bCIxY+sMdvNp$8XKUU?>u$`(mnND|uPuFF zZF$>wXr`wiHL`McsIhTJd^y}+lZZ9t{p?;%uFaJdrrw+=FP)q!xZOH9xF>nxVQ)qM zm+R?;V^gt@*P;#eSE^pj47a}7S9ZDiYum9O;g(a$`N_r1`)yA*MmCa}1G_7KCthw2 KrSA`isNygA%Dr>| literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/happy.gif b/images/mood/nolegs/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..056fc4e522f4dceea24671e792bbaee4aaf6c069 GIT binary patch literal 1162 zcmchW{Y%zo6vmG-E%!q_G#`R$t~D(Z8{uuFYel0+%~4CsXXVomLvu%kpn|=$Voj^f zWIC{maAQ-1l`p*LA*6 zVNpSDUU?d&(ZBTaI3gwzA|*0H{uMDWAhYf3Of-e>cl)0?kYPK zr|Q(eh^NljnK)BtmJb;PUhy(rs0f(T57@$FktKh(3XhRxW=9BYn)Ho_)K1le(SX8Q_ zhFoD66ljX67;;3?2moBTj-cTdQ6dju;x*y`6AZ&4s38VuyaX0FFc{j9Hoqc&8*S7$ zhK(Ue_`_IKYUURhtlv`v8}<7PmgJ#=-2HlkC_Q74j^B1**dqrX{PF`V?;w~2X?zaY z62gP0VATKL;w%1n`{`>5L{pUI=lcHy&3;Z7QWoZhh{DOyMekQPw*Fo}MU5+3uN;4i zyE@yR94;(he{@blaq7s%=AxR6P1!R8q0UQ3=521;D04HyM;2xD#EjUSUEZI#`{NoP*J+52%;!zk4rO7DuFembzUtT`jO4y1zgCuH;nT^x%n^_ol!4 zC%bZZ?W&IU#nHWg{@PK}o}C*@s_6gzn=N?{Qz^3~ymP4K?i=B%n$p)Nhp%tlJ;tAY z-Mitz)!yx#*_Gax_o(kl>6&Mce<+B4dnZ2sc=Z>bAIhx$WVEW~zq0*97wS$Oi_Xqj z*Z#}($FVP)26rszIXTjDxu9uxdMGkk)tC^U+?JeJ9NU$6=I1}w&l;XJpO>`V3?B{^ orMDEt>*`Bl@8(Bt*PrjcHt(a1-#!baO!QSvY+C+7D)L?Z0`j!$2><{9 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/high.gif b/images/mood/nolegs/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..525fdf494d7165819c7abddce55339ccb17e972c GIT binary patch literal 1338 zcmchW|4-C)9LHY-Z0Hcqyt4xd@leyqg5HOBF4r*OjN>FcC*G7Aaq^})bXW9^C0pmg z2u>ZtmG=%RAkNTaQyM9(wF~u9dS``vGi}S|${*bHhrSHfeD{2R>Tl@%%k8z-`~7@9 zp3m3kwv@V@8(z$&Z2F7-J&cGG2_i|P2o+<*I59y?5>vX#8F5Zr5SPT2zAG3BPC}57 zB$R$C8A(o3kd!19lt?jBoRlCXNuhu?q@jh!xUKXYeK=!+G0B+HV^ML=xL{l|t~3Rj zf-@nQkW45Ig}ah7DVUT@Dlpj)Zd5hd~fCSD^BFu^b! zf*N9g#!Fy<1B0OrX{A@BZ=;PGM`2?K68~p+Jm}>cSlWRx3DWo+uqA{CPZ(uP`|or7KYv!tB_$Be(qnq4{!dWKeLAxs z%Xx2CPF`NxK!vrs#Zozw;_kjQ-X63R?7wmEt8M;6;i|q(-OuKKzc8`DdGbzg=PzGd za!X(MEYg`pY@&vuaM+rvjKTP%agXYcf$js_FQM{MKQVsFp(jeZxf2fAtl-?&Ha54kfpC#Stv zQ2FYYXY!vIe|P`R!7mb;0(TP~4HJ&jfj8glb;%{ONP;X&^)_wW0f zEe&IfrbWy8o7E4#d~($%UFnYQTf56f8)uezs!o|hmcq549}FzJ_$JXKi>7vz`!Ztf zuYDMu4(&5W{C@h%sImMF0Q* literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/horny.gif b/images/mood/nolegs/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a1188b4d231b5015159885fb70f949cab7b8f8a GIT binary patch literal 1056 zcmc(e-Aj~F5XMKeNRU1(Bx;d_B$O!QkQySXnb{H+1_ma$Vh$^*7g6+q)`AxjN<=p` zWwdQ1)s;bQL?9RzMN=CY!o*C1?JU9WfINu@al_6-UA(LZT$*pQ#--R9@`!_J9w>YVwpsF)p#V|8qv0++&0#ECjF4~1T3r{Ywd8W{1^89Nha z>I_ps4KYB25?HvyU}!@cT6k>UkgsusS((lI!&p=zEXrcuE+}xR!m6wW_kcn#o3JSx z>>&?e;x*!ce?Y(?s38VuP@)wa7z}MlL(6<}{u(uoikJ@){xBAms;D7X*aZbH#Z(MA zB54EwF0>W!L z7BbR^-q1!r-2W4_1h1Rj`ZxN;;~qEthPO;(bWN->7a4KY5z$e0^@;ijnUV$xYJ_%bL6HA1;}# zig!<*y7jAgb6w*2^JH7a`_2~w(fK27ML*{nAJsJ%FV%&vch@eIef-+L>P|FurF_4h zoa#uu%{kCF6B1t|raH6qbEY)|r;n>{o#L?@E P@{2}J_q313h|2x~A@08u literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/hyper.gif b/images/mood/nolegs/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..0760c9caf1a8c8871553a779fede6d17c9f59201 GIT binary patch literal 1179 zcmc(e{ZGwd7{>38TFPw5iFwJ(n5h_^GQ?00bz&>(DCX__@FcNWv7wE;#AN+o#2z+p z&7_WUnqxCrva;BXw3*o0vN1Gfj5?dSUC-Aa;rZ>}b3fPpxvu;BU6HkX-ux{IltBIT z?(-{b4LBW3*vy#M%V~F4<^i%>ws; zLa!F1g|)yQ@&G1YBM$fn1RR1IVt@uETET(A(1tX$#3pC2QRA>NVuOS~j77z4Sdc61 zf&!OD*a&h&(g*-tXh+a+iztx?F!363fC+}-5Y!L@G+qJ=92g93NQ+&O?Z!1~9KpsA zB>Z74Di*N|bk=VvoQ>LjI!m%pPVRQSPL!6>Nyl#6F>H|?4|e$umUZAvf;2t{Yzg7P z6Gqu#|Km&wM@A6!P_i9v{|OrWhk`NVGIK7a6i3C4S+-}`i_MAh<2`*jwS= zztOwQ^P{S(B&TV3sQHjL`*_^iygRGQqLS(YzQD~9nMuAw`41Zhw^!A7g?2o04V1;7 zzZfd1ZQPvO5!>UgaP=-sn;XbUy7745y$*-@- zZ}Zpm+)fV6ep)j0Q&DlE%TwJq>T^$XsHyP!yY7i|^G?*pMweFxcDCJ%o-_VwOZam` z>!`)MXSU2Jtqks7ACq|NZvSm+-}~J+P*hexy&d(NT3t&DpT!f3w9OOzF-p4tBW8`<_IN@FrwsbnK{q w;yV+&KY3*LvB+?)XH7$7dX4Yf@za|!>V7ZvY|WqYb6wWL7oo}N5fPO37Zcw0N&o-= literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/indescribable.gif b/images/mood/nolegs/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe10d94f9585e02349582b6460de347558830253 GIT binary patch literal 948 zcmchW&uh+yWPKHs5{!M^^JUD74rfg8cpMSRhShq%GNqTB-{U;8zUX!V|&f&u! zXD_y{@9sIb;r6SmEA4yEf9YMFyS#bVvF8hm_Xfwd3>^A3yy^bJM9avP{l55lWMcQ; zmz~F#rWS5)Yg;|hfBnF#fjkA7XgW788K-rv}{GPCdP-0xc(pUgiy`+9YDbnDps1(AV2oP>|V literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/index.html b/images/mood/nolegs/index.html new file mode 100644 index 0000000..860b18c --- /dev/null +++ b/images/mood/nolegs/index.html @@ -0,0 +1,114 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
annoyed.gif
bored.gif
bounce.gif
calm.gif
complacent.gif
confused.gif
content.gif
cranky.gif
crappy.gif
curious.gif
depressed.gif
determined.gif
disappointed.gif
discontent.gif
ditzy.gif
drained.gif
drunk.gif
energetic.gif
enraged.gif
enthralled.gif
excited.gif
exhausted.gif
flirty.gif
frustrated.gif
giggly.gif
gloomy.gif
groggy.gif
happy.gif
high.gif
horny.gif
hyper.gif
indescribable.gif
indifferent.gif
infuriated.gif
irate.gif
jubilant.gif
lazy.gif
lethargic.gif
listless.gif
lonely.gif
melancholy.gif
mellow.gif
mischievous.gif
moody.gif
morose.gif
nostalgic.gif
okay.gif
optimistic.gif
peaceful.gif
pensive.gif
pessimistic.gif
pissed.gif
recumbent.gif
refreshed.gif
rejuvenated.gif
relaxed.gif
relieved.gif
restless.gif
sad.gif
satisfied.gif
scared.gif
silly.gif
sleepy.gif
sore.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
touched.gif
uncomfortable.gif
diff --git a/images/mood/nolegs/indifferent.gif b/images/mood/nolegs/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..3c9491a0a1c9b333ba2cc8d213f72c0ea7a42cea GIT binary patch literal 1227 zcmc(e|4-Fr6vq$f_1h)A8rP8_yIjGcAhVv4v9<0rA|whWQbWq5mQ+YlKpWD~!eex+o8t}}V~r7G)Qv^OY}gtW!|Et-Y1vq7tQe~f z3cbQctPwGyV8m0SY}6VRqnHY6hyfauz``8{LmSf2!ee!YT#aLyg;||Hj74QFTVbot zE+}v*mPJ?;?g52fR?8}^u!lT=iPwk&{s94ppoSQrL5WsyU@){H4J~!axogxoVy(I$ z;SXa`iC9tO3cH}drB$(t9Fa5v02kU3G~6OeF$4*J7>i0&-2%P!I|^^3ZlB(g9F&*4Tdx6{&b-dDEWiB=acc+BDAYgg6nh~KPgDXciu8T;^hR>6V|HGPYAf1ceNIFfZ_S7yfOythkgDpLjF z*K*4KI$SZe|D&>wwx0O$DY4O_zBS1|PSvF6T|Is2-q@+uE&B$3yq~`|`E*^p?BqD_ z4<=^jzj&d~zy13sXWjbtldm{bTDCRZkkNA^B;{Sd?it9ryy~Z2(WertYdhNaZhT|Q z+Ob&AqKm20S>bQO?@SEW-=1?O+1|4KKu_zfg&%*~HlFe|_UgHd5UopvdcWB-FW4#Br7QPyf&c7e1ni|^ZThY1Xw>>)~ZBGOv z@A?y!FC>Q3U+)b~w9Xz`pZVR~<(nV2RyVHeuP>NJ{u#%v)SGVK?DXVBbH$#s7gO_# zmp#hv3btH5(Y|Tnwu#4|IW}}Ov-5#(&hqJ>Eh+B^#c~g2`kQix&IJeJ*S-jq^uN9{ LG_x){K=jcl)0dX=4uQ*~-!#8YSNOq{7R zOa(Q>01ZlD;SPhL4QXiMv3Wzj#t~*^Ht!E(QHii9i+Q`Cz@-YSvKrh23cYN?rfjf> zJb;PUhy(rs0f(T57@$FkR&Zc2v>^>G^U3*Z)Ho_)K1le(SX8Q_hFoD66u1;qG31D( z5dgT*j-cTdQ6dju;x*y`6AZ&4s38VuyaX0FFc{j9Hoqd@jce36hK(Ue_`_IKYUURh ztlv`v8}<7PmgJ#=-2HlkC_Q74j^B1**dqrX{PF`V?;w~2X?zaY62gNgjKZw{a*}>U z^&^VVR6pJS6BOM?O@kA&nj6~oMh~C7^g>QjbH$K^{)g7))z3V5Z`$Np--n)gP##~r zI5oQHT~>MWgo;_bXjMklfMutzb-Y-UUL6;@Qq=k-KYM>_)5ny~CFd5_j2*;FchxrN ziR8@K(vNZ7X<2pS*6oY>wst{z!Qq;5NjpBhJeC_Xe^kt#sPXxmBh|%?vqR~vMXy)A zdOEVV@J4h}%cPhCO>gg)J>Hr;F+O|w&4TN_RhN#&hr+8n3zOR(&ggDE)lxd}Zhc+H zgBltUE=m|y+kQDz5I%Xlu`s_f=W1J3Ps-=}8#ZoxmV4*thn7gi=oPVvXK7!bw!SRz1`QirLW6& Lhr)SjMDzXv7`)a8 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/irate.gif b/images/mood/nolegs/irate.gif new file mode 100644 index 0000000000000000000000000000000000000000..073cc19b5c4e251c91a0704940b174b9687b4d8d GIT binary patch literal 1083 zcmc(e+e?*E5XGkyQZY&+p;9qBSY#5i6*LL$Aje~;ry>L^!qP#-${sQ!j8G#A3omqR z6G-=q5b7y|Fo^6Si;2L(R7z4GBoIMLqL-$%zy65!+puS^`K>kIS5g|t%dbeKRQg5# zjv-bX=vdwy4B5bhmEnuh%xHMqGC2|4U1uQ6u7i(tTk4QRR@J$VI$Uv7*R0dsZlm+ zjfzoB1vSI~4N73)4uhc$X=vfGIzz6;vCP7(&L762vX-r|Rc99zxD?AGEDHC4LNBXj z6;{|o9>BzF!~y?+fJ0D24A7uND>yJ1+K`5py5!t7Y8C~}2eP~g(4 zSVfLV8UcU{?Fbrf5hd~fCSD^BFu^b!f*N9g#!Fy<1B0OrX>}`d-MB`Lqu3aNgg=Z$ zC8}9}osh8?o!!7bmzat^#nkjCeLEg?L3!YIu8 zFK6TL=w(EoX`7qw{t1ftLw&Ky!Ty`CT4GlD{hj^OMTzY({^q>;Td$jgTjE-y(`Eu! zVmlgN1e&McbR?Ig7Z2Z0KObIR(c>El@Sen+V@aP%{d2j#jO`2YTN5_>gTb!E`RAS0 zqiw$1ft2r0(%(I#w9&~O0}pmzJk)h$LqRy{M%&@CaBK0iEMNKfaC6o~cz*cN$zA13 z*CWTLdREUiIh6Y$GBw^Y7Mg6#jH0-o*(Hfwc=XP-goT<5?Qu~rQ@ZcX te0{ufuIk77n#Jzep>>goFZ+AXbc`297Ka9#&eo0Y+*I~Hzp03*;4iln%RT@A literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/jubilant.gif b/images/mood/nolegs/jubilant.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2a79343c3bc4a5109029e49c44af8481bf3ca6f GIT binary patch literal 1105 zcmc(e%}bO~6vmG-6UKlpB5k3=C}=in5jVrHXmF9GEsRX?qsb_4mbs`%P?VgcK#Ura ztgA$3Qc8t`Wn_^=sDvFO$THl-6p2v;t+Jp_&wcwNy1TDq4J|xIx7a!MXr+u&td!WXsI*qvD9uWXrNE`p${1x>8L?34Wv$pKX2k+V zJXNBV7$vL(Q$Y>nSR1i+L4iv)npv~J zJ)qF5#b{wIu!lT=iPwk&{s94ppoSQrL5WsyU@){H4K1e0-;SXa`F&h@- z3cH}dr4crQ9Fa5v02kU3G~6OekNU>;j$jTMB2RcAw6YER>VGU9S_RWpvW9+jb0FWXFSDzJp~QIFlfa&jDLP zc<_W#fdHochm-o#6+<*n*><-5Cn)X@jjT-G9`5%fxmWosmImCO#MpT6Bp!|Nr9J3=7aW?*th@2NA;;ya4~=HbB*o`eAB<_A^7I9EJ-Raf%H2*| zJ65EWZi<%o=I&jd%*Z`Fo9MfG`hNbL`_0{2bvC(vuAzd0FV;8u!^2hAYaaX4^DA@a zAJ&DM8nY5JUtT+Psi(1U_i!|l`pFwCT25P-I(IL~p5}Gc&vZiNMBnnpve~YEfx(vM z;|r8>sI>M;@7k`B&W{6AodqY4To~GNd#SbMOINnP!*i>xplNY+x%)(IbkEK2-8*X{ z!4w!@9IOeqwO-u(ZDBZlL-FOJs+QU4(@@Qs^J6~GTz|sI^i0p!lFzTxCrW-FyHosY SEc*6+nR`6!4Y}PeD*Ou|QqAuG literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/lazy.gif b/images/mood/nolegs/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b26d3a8eb3a3d38c73e9a8c1ce5c324c9b87af70 GIT binary patch literal 1093 zcmc(e+e?*E5XGlZId<|=ltP4fd9nyK!^4SV*Q-&*s1dE0XXnPmx-Ky&o( z7$Qr=L_(y5$`~@143iNu>MpGzYsoTMA*-&J4Y4I=Vj))dR1AqFVGg<97m%>)Wio!jh&})^g zidEP{9>BzF!~y?+fJ0D24A7uND>yJ1+K`5py5!t7Y8+u!7bN^)EGiKeMXs<53S6=Z zD{@5A2moAYN6>JKD3J#+@fvY}35MYi)DQzSUIGgo7z}Mlt6P!l#x-gj#l{dM{9!CA zQFROS*6%31jk zqRfsDCe=y1xGhy%yV^4e{!zcMMYx~#ppYHl>N zx0?nwhWB;!e@Oq)`si^=VP`Nf@~c0**cY34;=!r5gkFDjOnv(A^Sy;Hu4k^#pKKu7 F^cPiy%H99~ literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/lethargic.gif b/images/mood/nolegs/lethargic.gif new file mode 100644 index 0000000000000000000000000000000000000000..23822e08b8a6b4fc5c66a39c91ae72acdadc75f3 GIT binary patch literal 1034 zcmZ?wbhEHblw*)%_|Cwf4gziJ>QB_w|3eXw*Vd-q_C&qyKNJBapR}nzd7}R0KNNw~ zwyFPrqW=Fs3=tLq84NNSXckB_2!Z%O@T9E`$Oa>zwLspJCv8vuLlMXoK*=X<|Np}f zVG)p%L4E)_8sth40$B_+8)!7hED!=o1NlGzWP=gNe?V)2y#FvnSOgq!z`z2A4lFpp zegk^|=4h}BAa+2F2B`*m2xt!+5FrAJq+w_mIPHNGBYg?QpDc_F4A&WS7=QqjCm1-M zGpy&7@z}87U^53l6N3PQ!=ZL2DX$a_2L|VMer~oK5rqv6j5nN;x;qS$4|g%StP=4w zdTh#|8Gee#azUco4CCUY%`*)g&dd~KUbAI}K)T<2`^afmW`r#Fna5(z_w}UE(<@7_ zujsm?QL_5TGQpXvuB^JGd~~Wbr_@x*kIP**FfJ-f-Tm!tz?$Os%hptgy$#x=rJJ`$ z!dU6_4(97@&mum4h*`wE)T-1+tmw%y=buWvJzMo}x6R|14ylnyOWw8E^Zk*U>kl66 pnLJf2b**uR|K;V`#wL{$4Nu({iaj;eV~%3d!xNLW^(6!ttO0|GYlZ*- literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/listless.gif b/images/mood/nolegs/listless.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbaa7cea44fccfbdfa9f4936b8bb20ce0e102f8d GIT binary patch literal 1213 zcmc(e|7+D{6vxl5uDPq!O70yCojPO9d8O$CHY>tS=bWyxTK9_#D`f|4LAoN867H@D zne@eVyK%5YmrG_-wrLW&i0S6Edk_?Y=?{Y9RQjb6h!djI`}y=o^!#>s&htL6_xpT4 zjZJH6SG-+L<@A95JC2Bngh+{uP&r4A$q6|nXa15MF%t{15}WT8N5UjRq9o>@sv~7m zAyra?5}6}oG9gnk6wrn=wD1_+=I8js&WUsCocXb+m>r8_b!?sjm%>iOi8?V4gN>3{yc3F+hV7Sh&MrXhRxWcx>K~uW^J~na%sdSX3e`%3|IwC~&F5 zs;mb0fI=^uuqhktArD~UHR6DOK)@lWAqHqrq7@t%3~fk5%Y1VF8a0lJm=6;EFcy`n zs3BL_1qCj}R17&HX#@Z+v?FM^MU=<`n0Spizy!l^2x^D{8ZUtb4h)7iq|L9$cjFp0 zj$va668&Hg-#f`HSwfTv2yAM2gyrrTtM~UXwOY>dTlLw08|hAH^=E%hxp56?CVb`(^d5hFAM06X~BO pZtsZ{ZM(m)DcN6hGaP?mBt$2cG+o{J+UN28iNuH3+Ex-h|1aVX{W$;t literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/lonely.gif b/images/mood/nolegs/lonely.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf8198643c60fd09f63587723deaaa2eb0219c94 GIT binary patch literal 1035 zcmc(e%}bV15XC1`c+*-)A4;i}3&~Q82Ba|P4Z@FF6o^S*h$e%E5}{D7GEGY)g2HIh zz$Bzi_>vH0*aumeO$#Y%;U=(Bi-I7CK$y;b`Xjo#;m$qtJ7=D!tfF+=_SziEq2KiH zFp&@`kr6qeVkQ=1B{pIYm%=1Mq9jJ*p;wtyNR`w`Jv=og6EY<;GKUg5lMA_$8#xMS zLmFCmjBXEe!VzX=Hf9fFQHii9i?Mj1z@-YSvKp%gDD;}JDVwo581a-{*p=PbF%{Gh z12iasg*yy}Hl(42#~uuY8b?J;#DhPKMWrfgq8{vm0+*&@CgyMtDD;Y}xQW9a@&G1Y zBM$fn1RR1IVt@uETET(A(1tX$JR}#cQRA4Zhalk(V^Nu@IdX+vP~cMC)R7~SMgZVK zJA#H=M2S3riPwk&OfU?GpoSQr@e)|zz+h-Y+QW)MH?C3RI5vhL;SXa`nR{4ZwEjR5 zZ8YpNT2g?Dau4f`q6~~tI$_(9;eZ@@2+NPKf`e!hr13dmO9&61Fe)C$wEu9{|4Cj% z^nnV(?C?)eY>tMPWR)ido_55RZ#*)Qxb^J9(xc`5b4j_oG71kQ#|BOwYg@H4dry6O zJl>PBp{D-KRQt?$XHjwcc+YWB%+>vUK4o!-Ld z-PPYy7h{uMDWAhYf3Of-e>cl)0?kYPKr|Q(eh^NljnK)Bt zm zJb;PUhy(rs0f(T57@$FktKh(3XhRxW=9BYn)Ho_)K1le(SX8Q_hFoD66ljX67;;3? z2moBTj-cTdQ6dju;x*y`6AZ&4s38VuyaX0FFc{j9Hoqc&8*S7$hK(Ue_`_IKYUURh ztlv`v8}<7PmgJ#=-2HlkC_Q74j^B1**dqrX{PF`V?;w~2X?zaY62gP0U{uGykMaNh z%>0oUNA!lmeysmbP||O@Ju-d6_;(Z+H!(ALVMD`{lL^I1d5;@IsjH*KHQA0)-DHNBL%Es1-+=2I-o-EH`}t#J32 z`na=wop;uhUr3p~_d?m_S)XDQK2k8YC;3LSE^$P2S9NWuPogJ&CqJ(}PPb>DAJ?|4 zj!RSH9}T_UGM6VpS9 GwEPb+5Zz?} literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/mellow.gif b/images/mood/nolegs/mellow.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0d454fdb1439c68b948636e3218f75077d7f511 GIT binary patch literal 1194 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 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/nostalgic.gif b/images/mood/nolegs/nostalgic.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3c9e18c46f9f550281ace672ddb8562e57c1386 GIT binary patch literal 1059 zcmc(e%}bS05XMI1_;&!i-uJ1yL=`O}J@#&f6c+*$rpTGr#AV_bu8}n3rFbMrrh$ z{vAieL_(xQMyQ-4$K-^Zk~4qFj+lvsSc%Q|iX&kXAyE?ZPt}n!sgNqEL5a+fF`1Al z8474a8d`XaZu4{eVdum-b+h8Unh2`t=UFti~JEj%`F$k#Z+tjy;9VJs>U7G*JS7ZkWuVO3UxdqAO=P1uwT z_K*iK@fvZ!KOo=`)DQzSDA5WI42CwOp=CZfe~lVPMa%~Ye;A8ORn(9x?1BQ9Vk(9l zku(AT7updt+#*Wk0ZhC`9AJWBI0QAs0F9Tx0tW^|8`9=i z0)zE?ieRIDpTUwmRFJ!0ZxE$t4ASx24h(zbz=L0YfaM(olOT=H0b4?N@Ptu~jhOZy zPR9Jg1fpq*_}TuSprk)Eki05-xiTC{O35xSolS2K)T7E2Tp!`zqxT=U&+Mx(cvqVhaRqf5gRL6dav}+ip+{r zzh-|tdyv)qd~y0FY9DK`_zvkgT|TsYL(9=yudCxD;en((%66Bmbf Vw@%$G>yLKLf0#*KkdR0Pe*qP>zm)(0 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/okay.gif b/images/mood/nolegs/okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..7e5bf64e6c1f7ba48fe4306466876a2da50d2ed7 GIT binary patch literal 1099 zcmc(e?Q70q6vxkM6M2{!x7C(Byuxo*u7swL42dmI_dPboi<4$e!V5CyVIFoX=3zM= zqSlbiY#xTzYsJ-xzIKJ1OdcLj z-LR|m%#MkX$k_BzFAg=-zpTxs(|SCG;zx3Jww0xoTwfTZH}z%p4_0f{n5r?wrE4ZF z45poHJ9%?WXTi0Mt3yt|ZRU7w=Jwv(pH`QwxHGvWa^=VF{&fvSg++umc~@b%-XjVR|ZCIYA&e_ N62Dtk9Y{)|+`n!#*W&;H literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/optimistic.gif b/images/mood/nolegs/optimistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..85ad7db6e99f7e4f8e16821b3fe5a42de71c81ae GIT binary patch literal 1075 zcmc(e-Aj~F5XL9`z)+#IRkpUpEC^i9>QEG7h+&qYmzo-4i4%ojfsh4(VZr7iDU$7> zASJr!16xBZw4j2evbiu460$6VZWMwFOvt9^y!{cKyWz}v=J!1FzU2q@?b>}LNI_bp zf5#9pktGr$B~-?cVKSDCkWqKZhM0*hu@I~4wT3K{wPb~?x~F1Dn8cC@i9(6gkTR(y z6;c$?hBUPB7~SgTxWmR+W5gJBV^J|1wuZ&9ItpA`Hr5&|#;SutudoqoM2sjH@zf|A zwMNA#rh*z`fCeS7aEHOrhBUPBSe+qP<5*^4R_706QCZ7Y*s8M&3S5e15f+7eK%tk_ zvI;BgArD~UHR6DOK)@lWAqHqrq7@t%3~fk5OI>pA8a0kst1d|R!&p=zRus9yE+}wm zRjeXMB#i*Tg?0oDw}=vX028kf2bf?O4nYkuK;tE_z=6TghP1jBxo%ve#!+kxLBb!# zq7qfNKyUqy!rQ3Zr?(^r<>l_y>qY4py>#5RJ;M&!^Wc{6VL1ohBuL|Pz?KjmJYiHx z38wvrvtcQ51<^aoceC9;K`DRe{>s4q*ub;Sl+3)tFJqrev-1PN3x_7lDBHJj`$+iI zKq{>-ZU}_Sn&Q0)wTWAQZQE4dpHn;<4S%nD-D%c+4Lo`~7`aihch87_&C!mVp`KBi zcyMvTS5TLe-ZK@C+^xBlTkLPVo!T-TYe+iSzYxhUOpK148NT=aVQWD~+u&SiX1sN< zYotDFE;Y7lX>2*#*EBOaoi=-=t9Pg|R#^8tJ>>sZ8E-cU!ArG2>az+mUbHRvhvJik zMOUjHm(r&<;hN6owCd(BW2Ym@zLP)akDtHus-m*u`iX^WJNwR_3stwwe$4HjPhPvY kxx-hQ#KY04c4V++b=Gp#j`8Q0KXhjv%Nu_3w1cSVFSnP%=>Px# literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/peaceful.gif b/images/mood/nolegs/peaceful.gif new file mode 100644 index 0000000000000000000000000000000000000000..f20d80ed512a819ea88e509e1bc7df0ba499a603 GIT binary patch literal 1127 zcmc(e+e?&D6velb&}GCd8nYBHBxGo2o(M${6ErUff;DNF<`jpZ3n3QvCZ<77qDUnN z5zWth8lzW#{L+ve=E_HV8IeMgH6v$E^rDV~1P zzoUpWks)FtAyi6{(xeP2CMEV#E7F>@Aj3f$3Qu0YXHd6R!<_@0u6Nnf2mwQ?-t zMe|aL+n=6XvKDi%HL*QqW8b%-j0Z&*4n&O=6<0hgOG~5is9kEp)02AK7dD(3^7L-s zwmv%_^ttbNPE^MY2Mdauy`yI*^ScWCx30I;)J?hquiDa21y1+X2fY0$=liP{qhj-) zU0xZOaxE;jJ!#zV^2+YKM|J&`uEr0ctc<&@O|hkgH#?WVguMF`=H`FBYn$$R9a$Dw z&77V(+5S7cy*p4gIIxm?xb*74%=^Y{@A$~UCO?gamM^xI4}Ut6P+R1A-g$o|=zi;K z>1j=W98E*HHBWsbAK%n>6x=u#%DEIh(@_<%_UHD{*R)MZkyDYM54k<*!R4vxn8EMe p-jRvgvgD<`U2YeZ&o!OdcW$AyYCJKoq2k(XuW##?9Z^I%e*qEx+f4uf literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/pensive.gif b/images/mood/nolegs/pensive.gif new file mode 100644 index 0000000000000000000000000000000000000000..dac6a532108bef96e5e2b9b392587e5a219a906f GIT binary patch literal 1199 zcmc(e|4-Fr6vxkXl3F$<-3y3~fz7nI*7Pw0*{}!_iKzs1FAYhSKJ%AWZmx|r7+f5I zjMezsVFD^_F3N^vLaFW6xLfKm@dwSQe&~j{TKY=`u{KWc=i?vY^V`{Tp7(jZ-{r+K=643Q;bA|X;jWegchhRFySb(hwVwPcyBkX6^qhS(A_u@I|!Du%?8 zFo}>Tlt>M!C1p|}MFDL{Lko}5t!|Dx))+QMj8Qihm9@sQv0|(`3S6=^%!b9VIwvt61M%_NWB{?WBceh?IO2_D>By0e0`XEJjA#AG0}WX0>3lG*~T!J?kYr0C^9Pu8+u{WAv=+X9)=xl0B!tL)z!V@DKr}Ja6!Ql93e>Rn!DjnGN$wL#7)AxS57<@Ek@0WAy&n3Tm zY3$R>wHt2_H)q~FuqtQ$u4|E#kzX!!#N+3?)+MIp&TVKLeEzYa*^=6)uVf`v-0Qk9 z{drAZWV||O-w$o&{k7YFD@m)n^H#L8EM@kqwPrr~WM%vOz%&0m+%Omj_3fUB|9P7-&5awwbi6-be}vE7+2?%T=k0B!m6ys>H!M9CTz-PYz{^|Wfyj3H+D<~HN*f7 zN?_p*gP{#+XyLI3L!rh|5fky?4`WfOikhegyP&|OshEj5+ye@|;wo<9u!lT=iPwk& z{s94ppoSQrL5WsyU@){H4J{AJg=^F}rs^R`_`_IKW@?UHVHXs*R5x|xh@=q!xX_NE z;TBOM4`AXo;s6s2!y%|4257tl7C0~%+K~3JqR@?N)HsffAxQYcSXAa778tERP(&LI z`;3+pprYKvdZQ=Z9B+ zJ^T|iVU*gE(&Oz{yN*nlo_sWxs4k1g`wO($u@pEQu8EBqt#|pM({haqo%H!GeKDD73anye8A8uJb zzvFV%`L=Zz&b=O~xHwZ*J!x3nlaah}aPUQLQd??g$H9+nr#IAOu6~~N?QOx$DN7Fh n;h`_B_h-C(Yg2PZJ`5kYcB%3~=kMETpPpY?^Jw(mVWN`1h*!x! literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/pissed.gif b/images/mood/nolegs/pissed.gif new file mode 100644 index 0000000000000000000000000000000000000000..76d657942ac7d42208eeb716ce2a04443aded10f GIT binary patch literal 1157 zcmc(e%S)9}6velh=GD4LW^cqBik23^k;)#VWWLHQOOv2MdON+Khej`GqES=^;=tNb zB4H6EHx+6iI=E$*u#MFX%F01C=z%o}B5TlYov%NlGuxbf*8Z)vzptdMct!rMG)kkN z^zRrVOTCGL{UJ5i;s7ts!g4GFc(3u9pq5C1zqFR`*m4i6vnYAyFui8d6Kj zq(X`U+K`489-~{`9CxfSY>XJAZY(Nmjb&rSSalS*WNVlWi(z$8=oM>(jffEiBc2+y zM%kzs#Z*v34A7ti7Va<@+K`489;-9tY8X?JJ)qEQ zm92_Z*h3z`#B0O>|A2r)P(uvRphPP;Fc{j9hL*bI+%;+(VOAF;{9!CA5f(+RunP)Y zvI;A5MA8TVTxdtoaEmCB2Qcv(aexVi;Skgi12kR&3mg~>ZAhzIk?Y1aY8=JJ5G4Fz zEGkiT3-s3SD7=ljeR@lBP+snCy{Gndo{L-GzaC1UnVbO`!Y4gsGj<%-9_&yZu$Vi*nwZ64| zT~lJ<$k*Gw^^xY*j8J-S+t9TO$(ij#@n3vT3c4Hm`ue{6HeO9EDbCG5cP6#yRokM9 zxsMaiZ+ux-fC~jn%>+$BiNER|JdjE=h7SYwww*L*Df$~ U{9Q>)a}VylaXz~)C7Ec|U+i|`e*gdg literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/recumbent.gif b/images/mood/nolegs/recumbent.gif new file mode 100644 index 0000000000000000000000000000000000000000..b748dbbcc1029817e5ff3d8d9d80400950fb7a1a GIT binary patch literal 1164 zcmchW*>8q{~)X>@q6|+dpQ&LkjrG{;tkH5irx!Kw0to>VSe|KW)gps4N<0y`r=^>GJjQKxbKJ4UurXqcy0NINHI|JPW7Sch$<{C%7Q^bGa96AmHX=q8jCg9)8fBwm z6jMPBF+hV7Sm^>GJXUAO)i`XeSgXz-#-d`jESA;T1qGVIR>X?JJ)m&cDq9t+ zu!lT=iPwk&{s94ppoSQrL5Zv2z+h-Y8d~a-b8XZ(!mKVx_`_IKA}oqrVHXr=vI;A5 zMA8TVT)2*);TBOM4`AXo;s6s2!y%|4257tl7C0~%+K^VaB6k~Y)HsTbAxQYcSX83w z7U-?tQFt45`}CINpuF7Odc7zeqnD1`wrAKOdmh~KJuK(In*?cm4%iaHgC}p)zi;tB z|MdReB7*1vCAhinKS7bdsj5wE%J%qm8(MbuOF8Hj9h7Rce96;vU13?YlFGf*sPTenN>Y<&X(?*)iAqk-jvoWvYL)JJn}#JV5@y!79YE~ z<64*I=%X)RR7Z6U9~|~!SmJ`Dg}HaS-8+3{*OCnXro6HFDZ9^!f;qxMdqtp`^r0YA|Wx;SocT+3#7r#2N^HJY90`*MiISLqs*aRNg;YrmN@R|V$%IVF zP(T~f(86PMo1fzkJ15SmbLPjQVs`a`g zGfV|F!~hLSVBrpfp$%zh;jwu`zQz$|Wj5~*V^N8)D2sW!punXHtFjv00}8!t!lrDn zhdh9Z*N6lD0Re}gh8UnhiB@o6Fti~JE%V9wYt%R@Vm?Ut!&p?RqJ~^y7ZkV@Q!(U- zq!9qP(2k(t7EvM(VB$66022(uA*dk+XuJd#I4~I6kT$;}-;Hb3IEIZONch88RBGlI z7_8q@1RM4H43^}fg53RjgD5>?kdEJWVAvxE9{lnHEbkzg1ZjK@*b>5nCqHUv=-~#Frzbzlp8bAz{8s+zaAEyq z*UIy$tsj1l&P2nVq2};HsoPNzzpJP|^-$Z$tB&#))1UXX&%M3#v0)%KvoC9+>r`y( z;HSQaHTN5*whs2^G*msmIF{Ct|75B5X6-`SwabzD>h7yQ*2XpF)|JJ#Z0tFGX8(ie z%j;!tcDIy&J2_sNQBs%?S&B|>KUfo2l-)c1I@DQm_E*89%1ej0WFA>u|8)NAyA#Vb PqrC%*bMM#1#ZbW?)&0LP literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/rejuvenated.gif b/images/mood/nolegs/rejuvenated.gif new file mode 100644 index 0000000000000000000000000000000000000000..01fc5a1b0bae278cfa553f6aa2e1a439d9ebb8d2 GIT binary patch literal 1114 zcmc(e?@!KQ6vj`cmcqQDNwxB#pHEx5^GLN(BlRX@@hp>-+1(6p(3os$>4jC(v~Ulr z`O&cKi4w-1W!S=L(W6z5LM*n7H=hc(hp&9yj z6pTao8BKLBb!#qGC2I$Q5=$ zflDK71UVvU1OP6yBWSoql*j{^c#Sx~1jBF$YKQ?EFM$OP42CwO#jeP9;~F)NU}Fdp z{xB95i`WG^>$eonM(sYGC0QsZce`FEO3Ub^W4G-Xw#beLyL<=BI&daI8lMBUgz(@A zqpGVh?LVBjpL2tVhRJ1T+kb*W|B!cHR6%Fk!`jf`oh5ypagUCNM1+J=+4?7xvbF5h z$i=ukm&@(u^u+MOW>1Em|Keusk_OMMvU7!9@%_yun?ri@7KM|`9TAAi@+WMpi>w)Z zd@C=>-Bh&4mvf~5YH?$FeSGw@gB4pEih^qvM7|5#3FG?4K;tjohilY!#2*F9C2ezoM3q)pyES<%y%c_($Cd!2Xs#?$5B zhUoN(>pQ-zTKRc+pLe!yHt^|oyDQP}JM}whs@0Y6_hkou6t$;hEj%_lom9X0T10$h z!G(#pXXfM%WOVGmGV`_eWoFpe?yk#)=Rf-W(cY@e@|v#k1HrLr_l^#YOk_Wh;t#z| c$Qri4mYY!dz4Xx16=%oR1_e>}U(^TPzW@LL literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/relaxed.gif b/images/mood/nolegs/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..513e489992a90ca3220ea943f61ad60f2ad4fef9 GIT binary patch literal 1053 zcmchW+e?*E5XDF7gqcNmLk^;#U?)jq>p`jDNah8fvLGwNN}VD!3ZtTzk_s{_FuFJz zbW?gT%dSvR8DV4&rydGTdXXNAf?h)dr?tQO8`>|2VfJ40TWh{kURhRDyd#~`=@-QAFM*Tj6C3&bIcfZ~sO3xUiw?wV~N1 zD|GkzSV=;5D5qxlesTn$ts@_s8Cy z&s}*gWnSUnhf9T5#|uu+k8EmR_oVA~TT5TngR(<69;R(jx+AoZTADoftg4ExuT4zD{)STQ=Q49R0SX@96L8+T`Mv^0tQF$0uv6zw@KH z8*V-Sae43PXjXmw>!zZf=Fa?%NaLC#1)twOYb}e1SNB)Soc0$NJ}r#y`S`wS!J_=_ QJws>4?$(7P`5Cn84_FAe8vp+*^UQne>i1XIoG7G1 z`ayq>BVr;UQX(T%&XHqsLQctTiTS7MNSRbfmDHd_=E#^# z$dn8Pv>^>GJjQMFbNpfF#5r}&{8&`Xj>WM$Hcx@3uoH2jPRv8$uCh~cs!k1zcN^e`COkcJi>n>XZZ9AQ>w^Zqavl?aQnn70cGG*wuY)!-gbxXUJN z$_9JL1DJS?IN%=;a0qIM0UDIJ3Jwg0Hl(3tJ~`h;jiVywgM>efMWrfg$Q5=$fu@*> zAx9*Q0KkRo2pVn?CGr3!ULy`L!7vem)&5eWb zM9#wduBKq}#p}g^$;azgZ7QG7PS%c|ExDSXSM;=H>FUkhBg5OiRz2^zU;e$l`rP56 z+q)lB#n*iKG?v&ma6T(hHIsPM`EsEr(mI`r6pxL}UamaVkzZ36k9U8VcvHVNmA++S L`@zm2pq+mJSskU7G*IO4-~jmVO3UR^#Fxl6E3Xchq0(sMNQO$T~OfCRLsO2?g52faTPal*h3z`#B0O> z|A2r)P(uvRphPP;Fc{j9hL(rq!Zm6fQ}qxe{9!CAGc`x9unP)Ys+&4;MA8TVTxdto zaEmCB2Qcv(aexVi;Skgi12kR&3mg~>ZAg1qQRv1sY8=PL5G4FzEGlyk3yjtuD58yq zeMU7iIRpN{Y@LIvWHgF zS7!%eWmg;0DmNU@xV!7o*7qNlx)z7i+v3TE)o(TD3R)jNuOBL`y4U>m{PpxF_n%zUQZ<5?H zwr;7nDOEnzI9e1dS+7Q z#Td=0O~YczvdraijIencX5$^R-ne}4pFhI=?%I9b-|O@JUccYsfgKq^##m#-7&c5o<(@C>Zh7C>ym# z#VDqN8e)J3C9rUZ!O(^@wD4G+Ay?yAW?@$64`WeT%U0N`vkMAbie(WNg?m7um({Wg zE9@Z;VB$66fPX;1A*dk+Xi%aR92g93NJC3qa_$;6j##TMNch88R3cUsxxy|eaA{Sn zB1a^R0KkQI1P!-{5_tdFWT4KYCDC9uGO!O(`Zx)r%@T%*QOYz#rdAI72* zRkuKI{f@%hsN1KvBnRc??$+x?=@`9q+_pW#4%zeImhWLX2i_z|<8#245FR{XR8J44 z{fCo2==Tx5qAWMt{Sy@YLmhGBa!ZbkO7_u}U~F^Wfy{abKD;Y-zx3vLgaVmO!= zUw1KqinTtF`Ep|816pElV$#AKbp>`@r?J3s&tJT=(K#Y1O>)?h{#&&V=IpM`L#NJ-J_fTFWo} zyzwLD%>2ibZim;dYFj+CzB=4ex_Q&dnzF9SnIk%DzT||L&we;0HUGoHiYko;-kcrv z`rE#hT+$Ki&8rL_f5Su1g-RM)?@Ugu^Ry;$<; rS7Y5xC*r@4Ot2?_7g literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/satisfied.gif b/images/mood/nolegs/satisfied.gif new file mode 100644 index 0000000000000000000000000000000000000000..a85c71445262a25c9ec4086c015c1d1f73f852e0 GIT binary patch literal 1157 zcmc(e+iR3p6vekm3=LK4B_q`&cBHXrCj{YOo!~w-&p)E)ZFBZn`?uEq zzPA(0q7}`vX*T^!FODN(A|X;DBUH|jV{$@H$(g@oN6f@RtiS^@Lk!TM1QzZv7}}7A79N{7eoa^P#Dha84}}{}%$k0>X5Qg%x@k>A_QBEmZ@WVa7B;5#bi7f0 zu&6h?p>|t&Bo%7iGO6vao~BrKC}-EtIX~3IHof1r;^7ewZ1m7&3Oc6=~*-=D`*D-&1iS{i3=FUbte4OLZDOdL3t-amPuF1&X4x%JB< k1xu&WuTS#p!_kT>&9Tz*r6tQgT3b7H^_%g+DMX8(152mmlK=n! literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/scared.gif b/images/mood/nolegs/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..d2e652687f01c8c9e1dfd1801b708efa36e79ba1 GIT binary patch literal 1153 zcmchW?Q70q6vvN;@|4vr%xr0!8(Z5FmptU54YS*{yUnsSS?j*pK}gsX_F^8^Si%sF zq~)CIU%Ry%s1H)GqDgWvH82=NSH)Ol*If~b)-xxq)KW~B6DO+CS*#6 z0@{#<79Qia`8ocubK;yjXMQXyX2;@K9h;{>Q`m_(Q77i1a97!>I8~ADBNWeHf4i7 zbh#gHSC zMgZW#bp#E!h!S}K6R!~mm|z$VK@BlL<0Y`bfx*y*wD}eJ+i0W4F>DM$!XL(>QZv86 zVEvvV*r?xUup|!^b;?~#wso5E*TEqv1U;aKI#aDVo= z=6z8Km!;;X&sbZ0HGCrB;LZbAo>t~HM=nZD!g5L+vgBJNzHY^}MH|iyuDDgba$~5u zy=Z)5m<|_g+7m8J&q*e3D7k-p_WEVFxMV?Id|Ual-Jz-Pk7tY?R)0Qc#h#SH(K+o` z*Yp+Vk9yNq`ZAjJD*Md6t%axWY>R$A)l<9a-PYYduPZKxVCXveg8@As<9eTS~Jx4!%KwXXt9w^>e`-wLF|xIxrG8fa$CibY=1)mnoff-Lws_sM USUi&4w7#}F>Z%*2C zHW-Y>rzCTudx!oyb~@1SuSi{PNGEr>Ln|)@w*@N$Uuqv-ShM+uE0n6w94;&Gn%0-u z5bsEKc<)v3d|TZ+{`if^o1CKf$#ElJz9`8Lq}$3Tw;Y%n|MdFlsZHLVlJMt&=X?D> zT+QLS*!?PX@ONovZRXnf!OJ60y4yco9Cqei=K8+HZ_{h@{6pG1?o1CiHjg@TEuH!} zP(LPAb~oHL(SIwszI#k#;&D$ZTGHx{{QOpRE^;N*>uMUleMN5lmb|gEyHwFkotFOyVINJXFohV@j01lF|n*B{Y-8}{rqzqRK3(syjzu<>Xd#nBA? zJBmmX86qYULZuWbP0EmBQerQ)BCSaq(o9-xuTf+)8AFE2h<(b6SQ8s!CKf1>C=yL# zNSFi#v>^>GJVv+JIreC!j8d$W*s-XzR@x}dN{gkyrP0b5Wmp-pQ0Qf?*eGVj0!BPl zqLmmWtOQd*4KYB25?HvyU}!@cT6iqhkgaiy)~vNye;A9(7;RV^v35a$OE#KWv%o!| z(5uC0VJ)zSJb;PUhy(rs0f(T57@$FkR&Zc2v>^>GvB}wM)HrO6*dXB#V^J|17UT-M zpunXOHi8_HGy(t@+7UF|B1+@|OuR-MV1i*d1U19}jhDaz2L?kM(qdO+yK#*gN3byj z34a)iibd=Ko%LG^XQOtX&XO#Yle=B76QyNz(y`li3|nN!gI&IZWgR$^AdSxfTS9p7 zgi-zdnD!q|{4ckQXq;Bt+4i5H;6KzIvUIz@{aLNM(@mbd!O+MWPsY}v>Ck!J+T}%w zD~Cc`&X4=ui<(Z|OilHK_w0|lJecO~^oO)ndXk1}V&{xK?eVpb)~yZd2-_Qe%-7+| ziO4?}G1Yu^ap}mqjFa)yka_%WMU0y6Pp!G0;Pw{Y%Dm#elh^mAaj^NG-W8L0VtwO4 zL)nk%*ylyJ+uN(k>kq$PlQPke?f1VQA4wRX0C!kaN?s2QgyrN#k4C0^9?tPyj4Y|V zaqyaV%Yvwvz2#qA_1R4k`4#0Y!;ed*UL?mn+*9l=DR@#GRaQ7Tm^3r@)nq75bd~PB zloj1u=*n*H`!p7Nn!bK~l$o}~A5dNKF7SRqh-bEXW~wVN`1`lq*_jXZ-4D(lS(ZFI xS~}m?O22>ZYdf%MRsNwfO$&pYaE=D#k{+K&JL literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/sore.gif b/images/mood/nolegs/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..b1582cbfbe8d36f08a22af657d15a8aa7800acb6 GIT binary patch literal 1052 zcmchW%}bO~6vj`elMaGf)Iw~)T4*#ubTJhRTJ$BQV4$M8aiW8LERyI$Xi?};NChq; zPf|$G!f-ID%p}NBle7~AfflqVk|-ros6?nv&wcA}=x&C?x%WB0=Q;1}F5gvB+8Ch- zEz;lPh?q!-l*kB`bL5zukW+Hzo9u|0ScsL_{9SP*Od=#oV*aT*QYIBrB{e9KIWi^_ zG9^O+ZAe24k8#`l9Dmq3aZa5xKNc0UV{xpG%~PN$>_nWX6Z25GtL#*qs#60ao;qV^ z;!K@kDySg_Xix$RJq(66q@jh!<_-B8N0^n_yg!UZCBmXC=Iw$4O%+yUHMj>9?y?D+ zvcVqm0481|4)_NI9D*8RfCeS5f&+u04QXhZPtLbd)bBG`l7|X%_v;O!^o&6|e%pazj~saL%MY-;gJ2S*@i|~i2oIhxYIu0~ z-^ciWfAW`7ml3_Ds2}V96O_J0{TX?C?sg|z(^rP-a|-j5+iP;eZH3M6M%q&nP0_)T zaPmr8U0q}K@%(2OGB?&_j;&ZX5RYWtJlk|AUeT3P5X;=Lzo4RPYhV9nc@=xn8L9{k zjo<%Vba8#!k-U~o+2?Lo-fO=!J0F|s+jn#*I+5M`=K8j*sh^YWhYutgCSoVU3q4o+ zigIohJ-=4{_WYWqA2&*0er-se>8MYgU%fCLFRv}xGFSX%Y}Mt0;&`<7#K*^>=`cU| zo_K$!b9o9)ep@>`TKOyXyLYg=X|U&@?QALDuy>%XYB7>%J~q?QdV21u)P1V@kn!-; SOh)yi(UIJ;$|sR*D*FTCLcgs5 literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/sqlstuff.txt b/images/mood/nolegs/sqlstuff.txt new file mode 100755 index 0000000..ea887fc --- /dev/null +++ b/images/mood/nolegs/sqlstuff.txt @@ -0,0 +1,160 @@ +replace into moodthemedata values (2, 2, "/img/mood/nolegs/angry.gif", 30, 30); + +replace into moodthemedata values (2, 1, "/img/mood/nolegs/aggravated.gif", 30, 30); + +replace into moodthemedata values (2, 3, "/img/mood/nolegs/annoyed.gif", 30, 30); + +replace into moodthemedata values (2, 8, "/img/mood/nolegs/cranky.gif", 30, 30); + +replace into moodthemedata values (2, 12, "/img/mood/nolegs/enraged.gif", 30, 30); + +replace into moodthemedata values (2, 47, "/img/mood/nolegs/frustrated.gif", 30, 30); + +replace into moodthemedata values (2, 19, "/img/mood/nolegs/infuriated.gif", 30, 30); + +replace into moodthemedata values (2, 20, "/img/mood/nolegs/irate.gif", 30, 30); + +replace into moodthemedata values (2, 23, "/img/mood/nolegs/moody.gif", 30, 30); + +replace into moodthemedata values (2, 24, "/img/mood/nolegs/pissed.gif", 30, 30); + +replace into moodthemedata values (2, 28, "/img/mood/nolegs/stressed.gif", 30, 30); + +replace into moodthemedata values (2, 6, "/img/mood/nolegs/confused.gif", 30, 30); + +replace into moodthemedata values (2, 56, "/img/mood/nolegs/curious.gif", 30, 30); + +replace into moodthemedata values (2, 45, "/img/mood/nolegs/determined.gif", 30, 30); + +replace into moodthemedata values (2, 11, "/img/mood/nolegs/energetic.gif", 30, 30); + +replace into moodthemedata values (2, 59, "/img/mood/nolegs/bouncy.gif", 30, 30); + +replace into moodthemedata values (2, 52, "/img/mood/nolegs/hyper.gif", 30, 30); + +replace into moodthemedata values (2, 13, "/img/mood/nolegs/enthralled.gif", 30, 30); + +replace into moodthemedata values (2, 15, "/img/mood/nolegs/happy.gif", 30, 30); + +replace into moodthemedata values (2, 44, "/img/mood/nolegs/amused.gif", 30, 30); + +replace into moodthemedata values (2, 41, "/img/mood/nolegs/excited.gif", 30, 30); + +replace into moodthemedata values (2, 16, "/img/mood/nolegs/high.gif", 30, 30); + +replace into moodthemedata values (2, 17, "/img/mood/nolegs/horny.gif", 30, 30); + +replace into moodthemedata values (2, 21, "/img/mood/nolegs/jubilant.gif", 30, 30); + +replace into moodthemedata values (2, 70, "/img/mood/nolegs/optimistic.gif", 30, 30); + +replace into moodthemedata values (2, 43, "/img/mood/nolegs/hopeful.gif", 30, 30); + +replace into moodthemedata values (2, 69, "/img/mood/nolegs/refreshed.gif", 30, 30); + +replace into moodthemedata values (2, 62, "/img/mood/nolegs/rejuvenated.gif", 30, 30); + + +replace into moodthemedata values (2, 53, "/img/mood/nolegs/relaxed.gif", 30, 30); + +replace into moodthemedata values (2, 68, "/img/mood/nolegs/calm.gif", 30, 30); + +replace into moodthemedata values (2, 57, "/img/mood/nolegs/mellow.gif", 30, 30); + +replace into moodthemedata values (2, 58, "/img/mood/nolegs/peaceful.gif", 30, 30); + +replace into moodthemedata values (2, 77, "/img/mood/nolegs/recumbant.gif", 30, 30); + +replace into moodthemedata values (2, 26, "/img/mood/nolegs/satisfied.gif", 30, 30); + +replace into moodthemedata values (2, 64, "/img/mood/nolegs/content.gif", 30, 30); + +replace into moodthemedata values (2, 63, "/img/mood/nolegs/complacent.gif", 30, 30); + +replace into moodthemedata values (2, 65, "/img/mood/nolegs/indifferent.gif", 30, 30); + +replace into moodthemedata values (2, 42, "/img/mood/nolegs/relieved.gif", 30, 30); + +replace into moodthemedata values (2, 66, "/img/mood/nolegs/silly.gif", 30, 30); + + +replace into moodthemedata values (2, 35, "/img/mood/nolegs/ditzy.gif", 30, 30); + +replace into moodthemedata values (2, 67, "/img/mood/nolegs/flirty.gif", 30, 30); + +replace into moodthemedata values (2, 72, "/img/mood/nolegs/giggly.gif", 30, 30); + +replace into moodthemedata values (2, 36, "/img/mood/nolegs/mischievous.gif", 30, 30); + +replace into moodthemedata values (2, 48, "/img/mood/nolegs/indescribable.gif", 30, 30); + +replace into moodthemedata values (2, 61, "/img/mood/nolegs/okay.gif", 30, 30); + +replace into moodthemedata values (2, 33, "/img/mood/nolegs/lazy.gif", 30, 30); + +replace into moodthemedata values (2, 78, "/img/mood/nolegs/exanimate.gif", 30, 30); + +replace into moodthemedata values (2, 75, "/img/mood/nolegs/lethargic.gif", 30, 30); + +replace into moodthemedata values (2, 76, "/img/mood/nolegs/listless.gif", 30, 30); + +replace into moodthemedata values (2, 25, "/img/mood/nolegs/sad.gif", 30, 30); + +replace into moodthemedata values (2, 5, "/img/mood/nolegs/bored.gif", 30, 30); + +replace into moodthemedata values (2, 7, "/img/mood/nolegs/crappy.gif", 30, 30); + +replace into moodthemedata values (2, 9, "/img/mood/nolegs/depressed.gif", 30, 30); + +replace into moodthemedata values (2, 55, "/img/mood/nolegs/disappointed.gif", 30, 30); + +replace into moodthemedata values (2, 10, "/img/mood/nolegs/discontent.gif", 30, 30); + +replace into moodthemedata values (2, 80, "/img/mood/nolegs/envious.gif", 30, 30); + +replace into moodthemedata values (2, 38, "/img/mood/nolegs/gloomy.gif", 30, 30); + +replace into moodthemedata values (2, 71, "/img/mood/nolegs/pessimistic.gif", 30, 30); + +replace into moodthemedata values (2, 22, "/img/mood/nolegs/lonely.gif", 30, 30); + +replace into moodthemedata values (2, 39, "/img/mood/nolegs/melancholy.gif", 30, 30); + +replace into moodthemedata values (2, 37, "/img/mood/nolegs/morose.gif", 30, 30); + +replace into moodthemedata values (2, 74, "/img/mood/nolegs/uncomfortable.gif", 30, 30); + +replace into moodthemedata values (2, 34, "/img/mood/nolegs/drunk.gif", 30, 30); + +replace into moodthemedata values (2, 14, "/img/mood/nolegs/exhausted.gif", 30, 30); + +replace into moodthemedata values (2, 40, "/img/mood/nolegs/drained.gif", 30, 30); + +replace into moodthemedata values (2, 31, "/img/mood/nolegs/tired.gif", 30, 30); + +replace into moodthemedata values (2, 51, "/img/mood/nolegs/groggy.gif", 30, 30); + +replace into moodthemedata values (2, 49, "/img/mood/nolegs/sleepy.gif", 30, 30); + +replace into moodthemedata values (2, 18, "/img/mood/nolegs/hungry.gif", 30, 30); + +replace into moodthemedata values (2, 54, "/img/mood/nolegs/restless.gif", 30, 30); + +replace into moodthemedata values (2, 27, "/img/mood/nolegs/sore.gif", 30, 30); + +replace into moodthemedata values (2, 29, "/img/mood/nolegs/thirsty.gif", 30, 30); + + +replace into moodthemedata values (2, 46, "/img/mood/nolegs/scared.gif", 30, 30); + +replace into moodthemedata values (2, 4, "/img/mood/nolegs/anxious.gif", 30, 30); + +replace into moodthemedata values (2, 79, "/img/mood/nolegs/embarrassed.gif", 30, 30); + +replace into moodthemedata values (2, 30, "/img/mood/nolegs/thoughtful.gif", 30, 30); + +replace into moodthemedata values (2, 60, "/img/mood/nolegs/nostalgic.gif", 30, 30); + +replace into moodthemedata values (2, 73, "/img/mood/nolegs/pensive.gif", 30, 30); + +replace into moodthemedata values (2, 32, "/img/mood/nolegs/touched.gif", 30, 30); diff --git a/images/mood/nolegs/stressed.gif b/images/mood/nolegs/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2142c47acdb0b5793b19cf2ddf596ba0fe4a359 GIT binary patch literal 1059 zcmc(e%S)AE5XMJ6k!HHk2&|A!9!13#G7(7>Dq+XWB1u9BN~&3e2tfsft5ie{Ic7n# zDlb8Z*2yf87F{$bnRT3nU1(K{2%?BCG(GRvAJMxT-g%$-J>iL`jUqL$5NakSeK>dU$F~CS*!xWDX^ACKqxgH*yrv zhBUPB7~LM`gd@z#Y|I|Uq7q?I7Gv>1flC!uWi?h0Q0O&bQ#NCBFybk@uq(TGWW2+X#IgA z+GyBkw4?wPMHv{Qbi%eH!vQ(+5SAZd1qab2NaJ(BmJl91VH9TlmlOXH%Oc89 zO_(133CjIL_wqI+(>I^?<`!2UeUTnt9LSBw$5)++CyKgK>CWEPEe*-khJAf8nr!My zrjk?rvB_uG=98(VO0Jl?ytS@+zGSQ*j}i^biH2>7#j&cEpI0+&Rms#Ep4gLJUq&}t zo97eLJh6X!`QXs&%F)>D{k5&xyIMxywGEUEukX2dNEWZx7rZ}N{PknwbW`5kt@a}| zhx?A_gs&neYbHYzhiUePGN6pVz6UsW#Rm>F9kCfy5IEi;OVKZ)VKP_nVzDN zUkm3xjGV}OTk-qK?I&})9~|hfd{nk^sJ8vmsh)K&S7xX6^V#NfdE(*HL4Q?PTlZmk Kbxu|`?feV$(6!qD literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/thirsty.gif b/images/mood/nolegs/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..e9f421eb4cf2cb73ff0f1ba7d1c5c97f943b98c0 GIT binary patch literal 1122 zcmc(e%}bO~6vmG+rfGs!qqE4!YN3r{bSca>lSOG1nN*IcfzsSCXpsaN5~-sJLKJ;+ ztQYj=ru_R0)Bnl-`LuyHx zR7g=k8`99iV|1&Vy<&~95iz1*#8acz zC>s@{m!?YJoch|<@j7}U*tYTM+{-Ij;Z=vW4lY^! ltus3Kv82h)oJ^~X)=b6D6!%~2Xr0T>&1qj&5lAQ6{1;;k(`5hv literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/thoughtful.gif b/images/mood/nolegs/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..a381f24d1aaacee89bbcc8481ae7496e38e2f66a GIT binary patch literal 1055 zcmchWT}zcw5QRrk$jm+nMbkvnip(xz(uy!nh?PQgk)0C3N^4U=U=(%{NI{Ysf)I%# zD1xR5B4lb{Um!|~gC<0XcVU7?ffy1&HLd;DZ)o2fhS__~v(~)lSmDtF2QQ>jDt)KF zhlw1K5Gj!nDrRCwEW}D|zUi2pBPZmPocX)LB#uN#l*If~Wl~2fq)KW~B4aW~CS*#6 z0@{#<79Qia`8obLW?@!l^J7st$4=NOJM$E1ienKLWibzhyXshlRap&;c*^G3giYBn z71R&|G$?_E9tJ}j($Kj)Zd5hd~fCSD^BFu^b!f*N9g#!Fy<1B0OrY4a=cx6ww8W7rsigg=Z$rDlGC z!TLQ#uu;FyU`ZY-$lb3uh|)6#>G*92hCOoN!7o3+@(zMYkjCeLEg?L3!l+={zt8c1 z{-pniiXfV$Y(LchCuq%2dK!~*yzz8Lz{Ya4q$bnSUuoww!Y{A^FbSljBAh4Sga!!=F!N}pv7^`|WL z4P;erpLl*Qex)IC-@Ccy{EXqP$vK^&(VZKLs&7B+uISAyOc)#Ad!zhqO#YjTOa1ec zlj(6SuZEWSb7OYR>$YnfKYpo;iEVm$;`-uXQ)EY0>#yX{RBPhy-(}6;RwiD=ohe@T UzAA0?{#4R%XZ537A)-Tn0Iy`gpa1{> literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/tired.gif b/images/mood/nolegs/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..8cb96c931314623f41e888199d99ffb06adb22b3 GIT binary patch literal 1149 zcmchW-)qfr7{{M8o3YCP&wPcyBkX3h=4Y4I=Vj))dR1AqFVGg<97O<^lyMd2P$ zxNDWIidEP{9>BzF!~y?+fJ0D24A7v&Rd8T1v>^>Gb;-FlY8+u!7bN^)EGiKeMXs<5 z3N%@T6*(el1OP5vN6>JKD3J#+@fvY}35MYi)DQzSUIGgo7z}Mlt6Pz~jW%i=#l{dM z{9!CAQFROS*6%31jkt);w#ST^lOen>MqwC4c#*lxWrxYM;_}D1LN$_NjC0sIsdi z{OKO8yxMzWU((sPw+F5a6a<^vqJcch9m$>axggiKCsy9oGbb9@lG5>DSJLG`f8_VV zHO=GO`tv3ZkK7#WUJ;H@ygs_>Qdexp)4;aYG3$q~4L+_n{xvUO6@KFSwS#XeUeEJW z{)Xnj;-6n%40UIA?|B!V^X(%wY#d%S^giw%YH2J?jQsxI7)XfqB!9WFv#gR`xd_G$A2M?j)-T(jq literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/touched.gif b/images/mood/nolegs/touched.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a5fb927fedcf78ad6ac413797d99204e3d7e441 GIT binary patch literal 1209 zcmchW?`zXn6vj{1+9guQV(Dl*t;-mFp(VCEi`3~0T_K(LroL!cw<2vKw`C)4sB^UQ zx7INi&|0_ls)HCdsa;F08rcgs6q2m!*>HlImCA5}%4DDn8G?9x?sxkecHe}JKD3J#+@fvY}35MYi)DQzSUIGgo7z}Ml zt6Pz~jW%i=#l{dM{9!CAQFROS*6%31jkDPmup9O$O$@eKNgrXFT5UZd&M-BxOxt`xn9S#kb<@da? zE;t=3X$ov;58ghI?XF8c=U>=bH}t`c^tDuFqQ4M*GoQY&WZ;X)iEv_kbnc4sTytQ~ zSnGGOItoWxVv!@f*O%=$^XIwAvlFwc-+N&sz53+9&8ps)kF6PNS~OHe>n^>vyx|*P zc+29&(TWYp^6`%HT=D$}ckf;deArnzzA+rjJpVW|aN?aivwv)?`E>0}wsWfXvsh1Z zQ?s=GoLewatUuk^lP}9PLo$PNbxw+))kB@wQYku7S`qlGuN-q|Qn<`!{P9=^8 zTCQvzZ6B%FHT>w4-+O00jLewRTd&uw89a6&zqzb>?@WB6_jsmn;ep|b_5Ms(sJpTB qe1G((zi#;Z7mcns91Tymy;Yv?I{Q^mM}1&$*TGfC2cte8EqewP$pTLR literal 0 HcmV?d00001 diff --git a/images/mood/nolegs/uncomfortable.gif b/images/mood/nolegs/uncomfortable.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc6fcaa36b652a3a14e47cdfc080f36faf3555ec GIT binary patch literal 1112 zcmc(e+e=kZ5XL9duqacL2sAU33Xf8-KocX3?C7Q>3px}?kmaCK4}wNWkwiw&^%$L) zz{pC26f7T%=*2EX;Xrl)qYw&$%AN|k8904w_eZqehBfP(-}lYlRY7!3+3sA*rJwZg zI3gwzA|*0Hcl)0dX=4uQ*~-!#8YSNOq{7R zOa(Q>01ZlD;SPhL4QXiMv3Wzj#t~*^Ht!E(QHii9i+Q`Cz@-YSvKrh23cYN?rfjf> zJb;PUhy(rs0f(T57@$FkR&Zc2v>^>G^U3*Z)Ho_)K1le(SX8Q_hFoD66u1;qG31D( z5dgT*j-cTdQ6dju;x*y`6AZ&4s38VuyaX0FFc{j9Hoqd@jce36hK(Ue_`_IKYUURh zuHRFH8}<7Pm*kX>fK<^|`!AEM>vMy8E-TOES}zbX6QZJ+I?L0p;zUnUS3tNh*)# z1Vh(@k}b0mml}r}Dhnd%g|B8_=^2ezS0@)XcIF2q)kmjVSGMj6y2mfiJ)GKc?B$Kx zo-+kKRXr84_RCWm)NkD0AN#(xrTKj0;}yLlb98d7sq#$v&f(4{85#GltSV31|Ecv$ zG_xVlyUV}zy}uI~$Xa)3LDP%gQ^B_FJDOA8J-7diB}U_CwQ&M@7fu z^N-ZUyKjFSny4x1y7i#B<=4eXa-un{bm;l;wZX}CXFoh0IM%ndbXRlywtF#P}j|NZ;-2M!!y00YIJEQ|~ctPDCJ9!RYN z^Yn;acm5fi^2|0?YuRI3H~*lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1y|a;>kq nMuxbgPoi9sN~(H#k4Q?3U#ETXOsOWZlF}thmn{$AWUvMRv~Wka literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/determined.gif b/images/mood/opiummmm/foxies/determined.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a643980e4b7b0ae705eca35ddac250e19e7557f GIT binary patch literal 245 zcmZ?wbhEHb)M1cg*!-V?fgvCvJz>K13Gxc^|LYlm0_PbR{{R1f;J^WXetw`d8c_Vn z!pOkD!Jq>Y2btl(vPj^h=jy!{ua^XB#T+WV>ptfNXIEO43X8|NlHB_{j&CaZD%o~b z!(335OH*Ru)F9r@3oA;hI4jp(YI&eg@r&zV|Mz1)Uv1n)jm(zSUQ3%H$XdN|$JlAICXU#V*UdzHh&9}Vy(BUIT%>)^&0dLP(`~Uy| literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/discontent.gif b/images/mood/opiummmm/foxies/discontent.gif new file mode 100644 index 0000000000000000000000000000000000000000..b70972864503d88b30b3a4abe4107e08e0b6611a GIT binary patch literal 222 zcmZ?wbhEHb)L_tISoELaz<~q*>lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1yNIp5}e&HMknvH~4~M@-iD7QA4POx)n> zzBDCj{f#wc*3wsPrawLJ>AP`o&z>I%RqE@|!s%1r`jJA$n`34`qfXStr f`YXkk2Ds;hq=%>Mo|$*tlDoM3!o^FGoD9|gw;Ei> literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/enthralled.gif b/images/mood/opiummmm/foxies/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..8b6b71a1a6849e9b66b1be6f28ff15b50104f0a2 GIT binary patch literal 225 zcmZ?wbhEHbRAbO&SoELae?7y028RFt|G$6#{=k6)3^1VhlZBCifrUW_Bmh$Dz`V?3 z*PVX`r#xdh8CrrQ{>QTxN(Q8;S51vl*UFYY^YPifigoX6QTxMrJa}gylUdN{v?7FLnK1#k%)@T;`izKd{W3m8I#X|KV4b z^DnH}!ZFJ(V^faUHN}$Rl}uX7`${aDO$5sW*9I+r_Ey<>lKq{y6PvgF`rpvl)ZEe< zlq(%y7t!e!)s+zKV9ZrLFI2n0%7*HyFEb U)`(22ic!#7)pqy@4<~~)0P)pV)c^nh literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/indescribable.gif b/images/mood/opiummmm/foxies/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..9adbfde94208917058d3ec2df80aa42318fbb4a5 GIT binary patch literal 201 zcmV;)05<06+tdXu90~Fv>~g8D!|KNj^sdR>~y^Ac&^sDQF=n&vad}whay^tM0B< zEJrLFkH{qC;2De-zSObh3J9#BowHCFQZA|>>f{vnYSA=K$!@#f@VI + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + +
angry.gif
awake.gif
confused.gif
determined.gif
discontent.gif
energetic.gif
enthralled.gif
happy.gif
indescribable.gif
nerdy.gif
okay.gif
sad.gif
scared.gif
thoughtful.gif
working.gif
diff --git a/images/mood/opiummmm/foxies/nerdy.gif b/images/mood/opiummmm/foxies/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..47ebea7b063b1efc6383879ca2531564e46f55fb GIT binary patch literal 653 zcmZ?wbhEHb^kvXvIP#z2{*C+RPn_3h2sm)yKtXvyLwm!56$>`(*f3%G1bGGd|Md+2 z;~DF4KWi%S$41#?B3JJ)@*F*nzf2AmswPR z@6?&osV9~xZ96de>b2`PZr-|m-Jy8WosQX}6XqqP+?cvLJkR=Ga@>L?PA^*CFuw{s z`d#hu)_I4S+5(f>cxOxf_%b)}fs3epCQHQx<_k-&Y>8oc#q#4LQ>d2DN)ekW&z3td z_DBW)zs9)XB0m#L~DEW;m!TJvmUfGEmK?*!MVZfhV=!pW1F>d zR&9F}sB+kN{%={1xexAdiI%85c=Lyjv9H$Ji${)eb6j|#q7nR#@4@lu3K9pi=LPEC zeB%FXkC;V-LP>bT#{E_2c~(AqW+>{waPr~~Z|m}Dn*SG=3D1d`s4gn@lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1yia%Kx85kHDbU+-CS_kI2 z61(pFGdShBy7$`JzuV)H5?!99hh@W2zRT>D98X46l54?WsHe{`dcex{&4+ zu9grpX}z)_?bt4hKI=R=tI6d$A=7wTi@FjLoQgFngxi}ZxVVcg*3b-&_U}^H)SeJ* NynK1%9sy1UYXGC3RMh|g literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/scared.gif b/images/mood/opiummmm/foxies/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d6cc9772557d02531d041bb613cb11a35888ad4 GIT binary patch literal 216 zcmZ?wbhEHbRAEqISoEJEK|bKXfddC>0*XIb7#SEC8FWA#kXi@k zxe~kX{4+S^IaM*`#oCQ4rzrNN9FsiCzAopr-t^^qN4Yy)?VcP}u(Q9A>fo@{%6Uod z$sDUzwV52wx_bJ1=AOG{Qn0V#{FWKBTW$7CdA{0^+q2+OvETaJ?|+28WleuG-_td% z&{3x`G{h@hEhi>CLc@AulS96Qbezi+MitGr9_cW{T&8*2$(BY7mgEUJr?|V!RM#`y PCfBjHa`zrlP6lfLu9#HE literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/foxies/thoughtful.gif b/images/mood/opiummmm/foxies/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d7457d094c6297bd33ea0d9f06a81199f000a5c GIT binary patch literal 204 zcmZ?wbhEHb)Mij(SoEJ^!;TIA>lywtF#P}j|NZ;-2M!!y00YIJEQ|~ctPDCJ9!RYN z^Tdc>Y2EW|+0}>>S0$GX0&Zv`_ed_qOj8KEH?2RyR_K+8@dWxl$oq;{kDYb>#1aMF&)(^tgmzE gTWz~%Z}FbT6{-^>9A8&&$`FZny0zfzd_e|l0JL#(CjbBd literal 0 HcmV?d00001 diff --git a/images/mood/opiummmm/index.html b/images/mood/opiummmm/index.html new file mode 100644 index 0000000..2742292 --- /dev/null +++ b/images/mood/opiummmm/index.html @@ -0,0 +1,42 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+foxies/
+ +
diff --git a/images/mood/palefaces/aggravated.gif b/images/mood/palefaces/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d44f5629f0f4e3622f68549a63f96a50d8c3c85 GIT binary patch literal 862 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91>)eKr7Ascm+OH4Q6NJe30N4KPL(vb;@yTf^IZ%#d2X1GLLP{K5a zV|(F-9|h8;2?8H&AG7hv?ycBhb0hhRsH{canTWcl$9rU~tA6}oWbqJCe9=7R|HH+{ z`(%u_#6<=zcH?{bxPFfR|K{4SGGBEW1%#bN5|0Ras4QF{#G^HXMaW$u@Q8qqNczK8 Ki8w(H25SJ%ZELCk literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/amused.gif b/images/mood/palefaces/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..ccce6019dfcb4c9779a5517817ae4219a3d75ff3 GIT binary patch literal 863 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 I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/artistic.gif b/images/mood/palefaces/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..18ee0bd4d8659f3bfc77add55a1478241854df40 GIT binary patch literal 1054 zcmd6l>rY#C7{`C56eOKwEOC~EYP&7jqPT1`Y8gpGv6oZYa{^H##tSmT0*i);)h!y$ z;q>&n^?X#VkXR=w8YYCk*l_7=*+1d);(7JtlkYd5 zMDmkH!O${ffM~Ex7h}V77JAPw+Iue*k&(9Lq zuO`DGA~Kf=`y!D@JQj_`V$r2!A|4~+(L^F~gCH`?i?_bNnaN~+xP5D7WhI-1HaIjqLc{nY4ksUL7Kt^O(}syf%@|t<#PA>(o`f$6+1N=)AQT0@L12+k z0G-5Ge15dW4S%;hFKS6;SXw^sD~(&cHa+Y zarXEG#5!%%q8}apO(7bfo~~GY68X7iq*0ZB(Dp87ryhUnr+ZAp7;*W5xp2?$YxFRn zed=rHy!UL%+Z`xu_BSuRPVIeuUtQ~BRPpv3o-eX1q*FMBv;WKyC|ss^>9xr{caG&c z;~ijs-}3p{acP%Y!)m{K7Hg`a>l*$Hru)hA+wL~2tH~j)R#!_d-ff+eoY~`l;o6Tm zdmEWrbD#;`vGUeC#v;|(hQK1(q-A)rUam7{QS=fOKbl)T7 r!AB9vfLertN+t>e02d?T3OSA-YMEANG?~A&SOrAwbaeY$n) z*1LD_u3fwK=+PsfV#WX5ey$>XzuqP#RUQ5fIoNkZK zMIkw=>XQl?yf|mrUwV^pLR6+bZuJri3oh3K42=#(DLRseJy|^kyRW;rO$$80@jl_= z1QxZPiaWNMI(u5&e)9@2JSncJtI}ksv}j^rFS73B*r4Nm*Gpu;as+KSy^Hz-o*9out7rJ~VR9+dJvmf{#x`G!mvquuco8d|_O7m(^d=_gW|mHEgv8 E0QgkSUjP6A literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/bitchy.gif b/images/mood/palefaces/bitchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fb65aa360cf6ca3283e32fe160e41494b03a25b GIT binary patch literal 870 zcmZ?wbhEHblw^=(c*ekx!@&2Sf#LuE|9}7f{qyI~@87?F{rdIe$B*ydzkmDo?aP-h zpFe;8^y$;bk00N^fB){?ySH!OzIpTJ_3PKKUcGwx^5u&cFP=Yt{_NSar%#_gdGh4( zTLUxOVN@)vH&pT)A@j^5sjHE?vBM z@xp}*=g*%%ckbNTvuDqoIdl5-=~JgpojiH+#EBEfj~_pJ^yrZzM-Cr8eDL7G0|yT5 z-@kv~zI}W5?%lIz&+gs3ckbM|W5IMm>+9p@=H}w!;^gGy;NW0qXJ=()Wnp1qW@ct$Vq#=uWEeQ01F{+v z7YywG8$v^Zg8~Br{QZ2pdwl);+XI7wLqbEtZ6s#R7N0v$eD-Xc@M(_BOe)!o)S-HZ6^>>&^N{R5Yvz%VFmxY~I zL`u?Rhq;`BvB2OBHP2Ua!?9)1yN1v&E_mf=bYd#iK<940(yY6y4e*m3FoslL|J zOja{243iuLt*gE&1U~X=h?7@#kdQp6d_r5*wM*E(iqZ3;lWV7-qFup>2F4IJK6$4e zjfIO`xfG&K2k(eze3Z>0Aa7Oh;sayLEg_At9Tm5=J06H>2hC7$Ols*kt}HRzW8de7`3HKR43{{$3>>k0^-JLM>-Uf%@`OA^Ukl6Ro>RExVPiL zip0e`dT*bYEWJIDnQh_&;KG{nC#9kZ{NVc*<{o4 zOWv;P%?U&0*HcwZvz~0|`{yp8$iViIx#rf>3HOB<4Gmoc-DDbFgaot{6um%9rm2N5k literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/blank.gif b/images/mood/palefaces/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..77fd817e13b3753882430c7e77d2d11a2e254d3d GIT binary patch literal 900 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 literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/complacent.gif b/images/mood/palefaces/complacent.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fbd616cffb4d4a5cbc289f1d1ea63119754fb7f GIT binary patch literal 867 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z^03WeYgTPu!6X|Ns>Qu^<$*N^!Z^6K_UH=*M`ieEuC^k zzDsUov>s~V5Y`az{a8G$Usx+Z;z+vAtw(Hj>y8PE%5FT`+tTkI%e`%uEAEuW+vvEs z?V}Xiw|74U=9gK#Sk9vB&Ee=G=qA&6q}kKuhk}s1L?DZxlg`3B LZ8BQo91PX~8B1jI literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/confused.gif b/images/mood/palefaces/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8ba7dfa98f61d6c5c7850222b72049d7e02b8d1 GIT binary patch literal 404 zcmV;F0c-w8Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`Td>gv+c(&pyoEEpX2_V&8E zx}~M1wzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E*5XecZwdCl{J0}wpjAUt^ zj5M5VJ4i;7RBR<1l28CL37Ef;3{VhA9GXI}B}^1F4hdl}I24q!1S#u$QbB+zmBP(Z zr~~k{Aqh;b@b;vUmM9u*HvmC|@AQ0l3U&=RfPHa?1`UG%cQ`+9esVC3b_SRfNmm*a zmkM4g}cP7und(!`IvdjS~vt1P-hU;0o*v?(gsH<>!qH&Din^@C^Cg4hs_&Fjzpa ypuvL#2VPjna6$wCA^8LWHvkU+ECm1q01W^H000CH5XeWX4cOkGH3ywFMF2a}-<~W0 literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/cranky.gif b/images/mood/palefaces/cranky.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bbde811e2fabebe102702088817b6b2975ba46d GIT binary patch literal 556 zcmZ?wbhEHblw^=(*vtR||Ns9#ckbM_ZQEYGdbMxgzGu&#-MV$_-o1O*u3a>eMNqV#WX5ey${9vKu=2MyyliUIo%$I zl(w$f!ZFEN;1kb`{U?*2pOBQ=bMgHa88aSN2gXK+PhxA1PPnk3X-S9k)q<rdFYj>LmZttd_nuW~SLS{zaM7 zIA=4>TwE|&wmEe$SK zte3<^F0mfGa4m?nP4V(IzMFTLpFDl`?9xLao{Nv4zkkWcBh16h^Zm!qU*Er7`S)KC z7$QGe7`Ykv8FW|}I2Z&Oc!3_){LsibZ||gM3qC#(S&=Y3f^}L@uU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;#jY^ z;l~FllQ^D_x`&VT${Z>Gka2S2aSd6^yc-iX-s$3(v?$r~<>O=a2?{S7r(8ef%+4nn zwN_)HBXj!~IlG!U{`2>@m&$z6+;~RFNg%LA&|P6+f)I~Z#}Pp{5yut*Z;|wetrAg! H91PX~9CK># literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/curious.gif b/images/mood/palefaces/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..8647a76ba72605692ce0d1479921bcaeb0f0fe4d GIT binary patch literal 510 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11>ZQJhMyZ7wbvwi#aS+MXNJ9g~SrAx0~y;`_% z;ipfZ&Ye5=?%g|}V#WX5ey$moJ^~IL>w_N&GI`@o5|n?zAgDefanp^V_$I@7~_wXy?Ao_VMS(&m7#s+{|Je zG9DWi9B2?1(wZZ{2=YCnG6O$@4l4sEkYWM)UPz$f!>X;qGM@Q&g>O_UJ&%oK!LE$O zVgBBHuc{AM*N>P literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/cynical.gif b/images/mood/palefaces/cynical.gif new file mode 100644 index 0000000000000000000000000000000000000000..25a53ad00ecd092a798d970c830b3002098ca45a GIT binary patch literal 865 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91}8f0v1bq%aQ~^Zr$v znb~-RB_&LDnaj#c3G;EYv$8OMW?^OL<`b5Zmo?vIso+wxpw!i|shM3=;Ew{6OJAh5 z%Y+rKs~cUrMbak*E$K5f;M`1+RrnY)u*=bAA|ddvu9udG&BSOk{53USN>( zK_JP6Q&jg@5W~w^hmLZIBstf7IFQK9&M$v!n#0CJt#=|Fxwc0voWjy6sHD_iz*FMN zy?gySmP|orH*PWQkR=|Ci@s!tYDa8o5M1o~Oi?fGOoyN|+uKOPg6GS0Zy%iy>5_0| zgX0~xgO88qUTJV-`Ozb7QBv~c+Bxl5%Fb{H=HIaS`c=*^3VkJ$wj99vfK7yWDR zm$NQ9^Pno#vscP;#q|FZ>;Ce8zy7q~zR(r}Ll;3enMM~O9<7H8&7KN{ErPB*2agm= Nq^)=;+Q`6Q4FIpCYHI)h literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/depressed.gif b/images/mood/palefaces/depressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa10c4f75ee38a4b6845ce24519eae424e1aa5f7 GIT binary patch literal 884 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@lR|G)-=2*v;0ey$M47M9|>=oR^B`B~#xKY%&=CsfWL3@Vd0w-rQ7Kqj~^q)9+ zh3oqD4RcPvm~-)oz#{>E{wGI1?|t&&trDjIAK!<6K|z0PAFwMr?rY=~`sLW-k=R_v z#;8&-VM3!k8+XdtsD$RmqwRv?79T3I8k;6-Xa!FD^1>mEu};N!mXGFSW#&58C;^WK zhJ%gFY)xFEzc!~cG4V{+ise#Z0finTKZ6W|4hsVZgCGMNF!YQRLL(!l6=uvz40H9J zQW_hPo4on!p~X}GO}obJpmMHmx>BIh!;@*2*IOhryXrJost7TGjp1UDX3${<8Y9fW z3pB>^!8S$}g?UMt%NW8JCI9ZzGdPfByGC05-G*!LT~>XJaC@Y)glZuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91{W;V@xAQ$x622gAh0*ZBlh zrm^NYOk8v%PQ~TTi>u8pobh`ZVj4dzP+^%6?lMi`;^OK2!s-ECQy3OL+sL4}evZMz z!%I6w#McMR5J+TdU7%U5JosHICx^Ke6f@53b4t__NI6%RHvHn;QVcrS=}sFb%}p(T2ahgZ`P4#5fTCjWLW za=jZK-n6BIaWQMRs8-Mt2gj%_U7|Ws2Rbe?eHIWmPCL?}m|V7AVteNKzPCvp`bq{_ zH#RhGusHP4G(q5}?PE4RS?iJy8J!#0`CnKS+?lcQV%%d#&YJ~DGmP;k1$ZutMO zd%vt@TF%~0OWb;8E}#7Gu>PNW^=r!;+g%)dcmi7l-4!MtY4S4Jks#zDljtJoY>;@T LRYFRfgTWdAmxOMd literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/dirty.gif b/images/mood/palefaces/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe7b8c277c1b5425649243dbe4a4d02d44ecd2c6 GIT binary patch literal 665 zcmV;K0%rY3Nk%w1VHp4!0M!5h_4xJ$6$$6_>iGQm00{yC9S3c`euBr4n98BU-N>fT zt*_R$zTCsm=hFZK01FKZ2M7oK{{8v-`C5`za+z=A=HlAk*p#D*^YrqvxT%bnc!`gD z*xA&_$inaM?yRe#dUH#JeOjEGm(Hq)#{r&v}1Ox&C z0ssI2EC2ui02u%o000L6Kwqz?fu~r03JGN9hf+*ohNC= z$fn8_z$a@yS1!%2Iv(N}7#^-aUlwaAEiW^hJFXTU7CJict|OkCA0)Z)KT7;Sz{o;{ z9{>gB$Z=y6ihT)RAxMA?;U=1S5j2l>4fCv$y#Zm$yE@-&$0VU6|8EwX35duVs7BPMhxIm!<2n}_eZd&t0FJBNK z0RIR;VS;54G8&#cx3@2d7lA2HC^3P;g&#LuY_|D>@8!S+DqA*P<3nl}E^d5q9Ad&} z*c4=gFku@v?i;#gnCJ|e#^eH}DQplyy}ES~CbGwf;aqTl0tEsPaIm?&`5*v0OnDo_ literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/drunk.gif b/images/mood/palefaces/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..519de5431642006b5bb7613b749b8beeb537f13a GIT binary patch literal 821 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$d)O3GgraBpxO~~cU@|+&@5oIZeg27ugLbBDI)6v4cx8mlBDU6`V;bf!)|oeF zo|o1W5iSuc^OEWatVwASF=OBn7HSp~7nhhZvsPTJX>vce(Bu{|hFKB}2BPzXxRn+L z>oQE6Ic*bz;M(;8eCwU3MLyn8Lc&;Rbk??3N;2;38LD0sji&(O@i^1)$u0VgIw zPC1JV2f+(##YCk=YB&@Q9%18gGHSS%)Yv;g#6-3r=7GYKrs-Tsr>6Y8q{7U8flHty zvUpk3EHh5A3`Ye;r^}}rcTH%5zN|(BJFD^QnV>SO2dx_Uw13yKu5xO8F zm>HNDgc-PjM(8})#<(P7-is4!Q@xm!4$Rb!x^{c&JcD`fS4b9k=tz}sTAZmMBsWv~ zxuGT(BiH~ogaN`p10o)5D+C$9u_o24Xc5~CkO6aM0S(ZQE#O!aVK6h6EqUb(HIdU# zn;a9DiJfv`F^wvlwrrXjQ%r#P+yJGQb^ebyZ(mtv5iGj4<;45n{~N5G8e3|bF z%oUGoIa-c(C=0Jiwf>YKCX$vS;_GuUWLnWutJx>@i+uEEpMP?EL)X2Hfjz+-4AubK CV@DzY literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/ecstatic.gif b/images/mood/palefaces/ecstatic.gif new file mode 100644 index 0000000000000000000000000000000000000000..74b0209f0d7779bfae26f3f404ea0e81ccd3aff9 GIT binary patch literal 577 zcmZ?wbhEHblw^=(*vtR||NsAg_3G8Wefyq0d$w)cwo|80-MV$_-o1O*u3fuy>5>7D zz^6~27A{=)=+PsfV#WX5ey$G~xYb_rv*preuueGJ;a^^Nh zB~2cOTX_wydz2)Z7#}~oW!Tgve^Bwv%sxIRAp-}68HXNr7K&J`QP6s%FuUM<%qa;$ zIT<0Lxhfw0{zB~qij33s8A=?@gz9TF8LI8-8XB7!>bW@EJIjiD`xqup=9(iSRU#!a zhif+5MD~*&Z|B|j>ixGj&)Il|d0Bb?Gca@g zdEP(!V6z}FXnwLVaxw5T=&&$wFbFd60DW%x!BXkQ?jMGZcdR*7Ic^#konZ8HsT7R; z#USpG#$;>nxoO+X8w-y|?^IcNr0`^p)%3RK%37r_XYAqto2HB~jSFa+#)n4Ed3z_N y38>w>yT#{VdT-3uh`a1-{5@OsUItF>oL%$&zk@elL??z*K$=a-aEcTogEassd*TED literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/embarrassed.gif b/images/mood/palefaces/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b23c27f97ffebd0cdb5115182fa582d70609da1c GIT binary patch literal 685 zcmZ?wbhEHblw^=(IKlt||NsAg_UzfKSFi5fyLao>t#|LC>lk$BtcFwQAkEb;ph!`=+2UbLPy6GCHSDo%;6e+pk~04jnqg!ou>( z!{gY#eaE(KTexr`&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kx9DxdTfEegXNd^Yie+mp4DarFPys{RZ;3&{JZ**DDaozix z{T(eatB*^waV%|&c(8?ubJ>U&SI+cTWxzsY_! zpX*-!S@xU!SCzQ=1%!nKHcdNwb{4yUw6uWOwdc~Wq@Nu7_vn|}hr{iDvMiip`xpXd z1RUB^#s4Al#D#^-?RITEsS9o>9=0tOGBc7m*$~#vqGBwWGbKT{v1KA>lHLr@$!R`Q zcvLPdQh1npa<-}Xog+6VJ8^Sy+i1j|+OqNztDCXcTrX1=P%tubF~~FMurP2i2r{q% zgV9J~AxGQenv7QxO->>$20U)L(wjdVT0G%j(=~1fm2-8?N`j3KPNrFgH&$kJ)oE%z z5@5n+jN$|Ko&)LglxDJNS#45@S-3ogEiH7{5A*$Ng$t%AUFupYfK3-UmRkb=0N)4) literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/energetic.gif b/images/mood/palefaces/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc62158ff8d0343463245bfa51a6f09a6a6058fe GIT binary patch literal 422 zcmV;X0a^Y>Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`RN3=rz->eABE=H}+1p`rHn z_PV;dwzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV6aWAKEC2ui02u%o000E*5XecZwFK$SJ0}wpjAUt^ zj5M5VJ4lD3RBR<5l3)Nb37Ef;3}6sQ92!HfB~%zR4hdl}Kp2!V1u5%%QbB+zmBP(Z zr~~k{Aqh;b@b;vUmMj`kM4g}cQ71`O&!`IvdjS~yu1P-hV;0x>w?(gsH<>!qF&Din_@C^Cb%?T3{Fi1eK zpuvL#2VPjna6$wCA^8LWEdUPyECm1w01p5Q000CZ@PY8EweyuqZ{1G-cHStF-kGj! Q>%MSY0WEz2HkL;KJFdN`oB#j- literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/enraged.gif b/images/mood/palefaces/enraged.gif new file mode 100644 index 0000000000000000000000000000000000000000..f73741861299e91a5da769a97940d3c657379738 GIT binary patch literal 833 zcmZ?wbhEHblw^=(*v!cAp8*8^|NnpM)~#d5j=g&I>e8i4&z?QY%*@=kZ{Md+pU#~- zckSA>UAuN|+qMm;Qt>~xpKD04vtxj(k)8oFBS`3??yug`?z;LB-m z6(qYZ?Mn}k77Dx~d}m3R!WWbM6OU{W(cqFwRxp&1;j(A#zM|x`dO>EW*_xTTlM82@ zieOT?u_OABM2mEfS;GImWagUuN?xG~n?}Yu)`l8JHl7y7HlgZ*x+(d66I$8kig-jw ziOgl2$j8RrpDf3o%(H?`lW{rs%F@+R$;|7wZWQ9%y0>!sy2=#?HyvPMIk@E9+=HjN zPja8WcG}kV`lXYnIqxTmKj1ul_kj@SL}A|S`z)JyS?=?G;rsUe`xayX z+u?akO${8vRt^OV7arym1cnhX2v|Wuz{nuVAkM%H3<53zU=ZxJXkJj=fh^4rlx71; zi$J7bpLJ%CbFWOfS-W6nm>@_YBP#;sPh!SMRxcZ{~frx!+rpzZYKN z%*uMrgrb%es#Ze4iz8YzP%&a3yDv8wO-pYVdmNnqZ5ONp+eMTr-ru-b1pL1gJX zQH%878Hz^=eQqqB>7^)i(x7LulFjS~EAuYxigEud+LygR+MsG$Q&4A(K?jN{Fdyq| zF#NVkS0dVawn_BV%!LOlcqIBm{W-CFhX70F857?_Z#mu<2ng8S(_{CR5Z<@s(~O2r4)^#) Q3wcZ?G%6nyWMr@g0F3Glj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz+%@&#%7KOpGg5u3Ei{$zh4i z^02TqTQ@T@$%KV!a)oW$zGm|lrZ6te-Fkuo94srhth&I+!XY52x7%1;LWrA)5g_JAKyb3(za(c3$+>4%q%Uzv9 zwrSHG4qiOP!YQEQqtV6mLPuULXpTii156A!iYN7@H$@Njfu>EM&ni(n{q zbY>S&I_kMl|!Er|Z8$lT5+XIt~<$HASStK@Af zUK~(-yjoP%B;&z>dH2{SC@?TRWUjgWaKe0{!#avAg02#UEJ6Zmii#~BGKnsNE*u+M Pie$=OEEH{IV6X-Ny5MA~ literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/envious.gif b/images/mood/palefaces/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..a1fa93b52e44e59ba0c7d71881f726c8201a51e6 GIT binary patch literal 852 zcmZ?wbhEHblw^=(*v!bl(8~Y>|Ns9#b?VfkM~`;x+I8#Jt#|LNF)wXThe*O9dRH^u%+s`#5*x50_)kx2P8E625;y+oZ(#)I^h4Rdj3E4Hm)vvb$(`Nt3LI?T+)b<~yd z!uhkzr_Y`h7rB1!@O9Sv_eCGvzrKc*>oF_u>o;#+zSwd0<*T=!&#qzQeEa*)Th5yd z%x=Ii0eYDYo3JeScs1ch<)#8v{Sc8cwJZ5rGr#tM^>JH}gK*-0!W)-y5H~ zd4Uze+`|f2=pmpr*C?R-_t#nKeNRFP?@FR7WP~c@H)sGl{L`zmyZL6CHwLpHI}D~q z!a&4n_1l7jlsX~ElD1RM14S{+X3YYFvL;c-jJdfMmlp`IJWYt6WvQ@I zqb*QwOL3Oj-D6&Y()0TL#Q%sYVe_E;h8bU1*-Aw3_R-|tYCF@c?S4}a|71g*O-o*% zxKnQ9j_f>GxM^-!Aep7ml9_YZ#kHB|MADpyuDQpIlzJ^DsLkH=*5lac7(G+53s)^&0fP!CApigX literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/exhausted.gif b/images/mood/palefaces/exhausted.gif new file mode 100644 index 0000000000000000000000000000000000000000..4acf90a545857159d61c2fdc6c420202a5761b29 GIT binary patch literal 667 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkC_ph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^^~g++@eb|^@kXv^M1+%dCHwn(m4rn)xP^OUm6#bOOq|6qX9l;@biW02^7|#i zW-|y0FJV|Vi6LksniAKoM>D2~yy~8D`q}lT0s_zWe*O0Bli+nuL4N*E4D)RmIS$6RuqX+MlpHAV zpDD&G`^T9>;UIGxkCD-Yt4WP+Y&`M-F&`8jH%;c!4q6pbc}cmMeG}IYHWu+Ob zQm2OoUTsZ`%uWCN_0Z#~|E6E#c2F^^o9lM*Muu5>!19tVA1`OH3H%H)$R;Q%u=g;e p&r_ONre(EB#b&|sn6hU9yDZH2uN5wsqI9WisQ_4)4Mp}^0|0f~17ZLG literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/frustrated.gif b/images/mood/palefaces/frustrated.gif new file mode 100644 index 0000000000000000000000000000000000000000..56dc7d1c9c5279d8c3c250e708fb41e5b086e65e GIT binary patch literal 860 zcmc(cTQ6Gy0Dw==>1j_-v9^?UsubH;Obn5l%LK!cy4Q&y%kZ*g9_B@Cu?uqzIuo&E zGIR(-meQf3XhU;K-EXP5)xGX17NW%FSM1C8{ylu5Peb_L$!vfPYyrUaKd-N^uC6XG zFO5dy#l^+>`T5z|+3D%&$;rv_@v*^RI668yJUl!&IN0Cc-`m^U-QC^U+0pCu+uPe) zTU(o(n;RP&>+9=lYip~kt2&)-Wo2b~d3kARX>oCJVPRo@eqO89&dtru&d$!v%uG*D zPfbltPEJltOpK3@kByCuj*gCujA%5P;o;$-p&_+ejpMjVr5YR@92gi-DwPU_qQAet zudlDSw^uHg_w@91cX!KVvaYVK&d$z`jt;3*+TPyY*x1<6&`?)bCl-rqYHF&ht1Buh zL?RKDN<~qWLZKiCLMD@87$y>l5CnlBNFWe^|BA~^{pJNgzWykTjfswmjEo2u6qg9X zBMPFTV`7Cu%*XOu74v&Fv#QDms|)}MO+TAkn!$j2PGhUI1>|6H&M4OYy8}a=Wv+A@ zhT~E-PNTcZJgis@DhUFy7CA(sGFVm~GA|C7%`ipDFcCT=!erEx!RB(jWPDp5S3^NS zl0Y&NRCtRo+Cd)Lv)xHF-XmWx`&?0~Z%CO0)Wzduvp|2HeiALB`-=WJCFi8#B05)H zqARa2V)zLw1EP<$L<-GOpnnO&W2ydvdVbqJm{()&loX#~pGUF9-`76>l9P+jY&?@B zz-~^ynO$&Mm=aWdZgo;7H1SuNxdmp{o@sg=??I9I{REjG$ znQ<7US-L%w#Eb1=)Z$*?hX`>BTx{hQFSMKr%r{}Vr6~MKpEA<4zY-B|uMN2Lw&InG zHCIk5wF=7ANYWi}m5uXP1FOLSH??*zPc-nL0yC~(*5x_DvG9%E`nyw|7%DJn#VRIh yv!S<{wwvR|sK+*V)*ZDAk4S&QN+&XqyJEYXFivtXJs4>ld~Jcf5Hqs@z~?XIrCquJ literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/full.gif b/images/mood/palefaces/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..d99aec8742652a015371636e7c0672d17d2fb0c1 GIT binary patch literal 564 zcmV-40?YkJNk%w1VHp4!0K@~3^?d|RH@$vNZ^!obx z{{H>|0000000000A^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0?AWd&} zX=NZsWnpq4GA=d%A^8LVJOBUyEC2ui02u%o000I4AOHlUV4i472BOGVa4gR<(<)r9 z?|iR_l%8-%5k)eZmPn`sXfhGeQ9Us-f&SSMJ-4ggilI;6gB`16B0`;7?F{WA`%md3lfeTA_D-DlbisanhPSCQKFs~ zl2oby5fY{VsFVN~xVW~lvkMWwN-()FO1}}a3K0;o6M$s=2@nnr1HQV2E^zR1flCE2W5yh?z$60)vkLrc>2iTg z1wBdLbWorLfdmK;95`U0sZ*y*lO`ZAv8vUHApig&`2+z702}};1ONyC5da1N00lB2 zRasb;acG)hRz*#ebzN9(W3%gCIqFJ8QO{`~o~XV0EKefs3dlgE!AKYH}&;lqay z9z3{z|Ngyu_wL@kd*{xb+qZAuym|A+jT_glUAubq>Xj>3E?>TU>C&Z(7cXA8aN+#< z^XJZ;JA3x*nKNfjpFVx+)TxsvPo6k&;`s67M~@yoa^%S2!-o$ZJb2*1f&KgU@7uR; z@7}$8_Uzfcd-u+rJ9q5Zv3>jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{kS+hmv&J&qE+bVRLJrm=Km8({-VzOT%y?o8) z)lAZ%AsSrlo3?Ca=hE1rE5OgevNCk_sTC|7`~tc=jKsu4uV3GMtZiGlUdgSg@G6C)A`*VB=#cej!zdtd<80R9U8mdQEtcIO#}dd#H*_g@7Z|Ibq}V zUo{#J9Wmn;F7cX?kT{!DM71jBb72x|m!P6u!HI;0Od8yh7Bw7(Oh>zf?Uv0;n0Scg z8o%sLi;NQs8lBrWD*G%+X#94of3J2BgQ%hsOUGeFj@v#Po8GS0vJcx+u+hntOGMpo z#*I0Wu3VzpF?%9DT5xnr7{={sSorG}_x07Gi_-+3%n}ec&UmqGuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z@->@RGs%X9YH@Rf?cKY1-(C)GtsVM8VVo>0!&aYN!NM6Pq`$*hLQ<(j}@Bb)e%S(`Es2qm&~ZiK%7!x3*@U?|bXyv0l+2 Kg`$lN4AuaYE^EO6 literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/groggy.gif b/images/mood/palefaces/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a36b42716b7350ea0c8d4e6611154d2ff84af001 GIT binary patch literal 1005 zcmZ?wbhEHblw^=(IKlt|tgNh@oSgbW|EDoX^!4>knKEVGym^ZjEn2p0*``gKwr$(C zbLY;zd-qPAdhF1lLr0GuJ$drv*|TRaUc7kq>eU-JZrr_l_u<2bPoF-0`SRu4w{Jgw z{P^X|mtVhr{rmS1Xt?5kZa>$MU}whwS0ggL# z%v1&U)WjkMBRw+)#h)w;{0#C8Iw049+{wWDPl17DNy5AgFSbQD5^gY@E{M4waaphV zd3E!H_t&NQ#FS272#@*aV%MEv^uVF_@HGAnk{wEt49geCGS$s>R1+3FsW;O%{q>in z%@Q3i5;q<&l};`$la-N{k`%Ay*Ao*B(ruKP+@{OWCuYUKD=HG8E46Upd?gXlSv(^1 z57(wNsKL1 zd5ZLIoSdBQH-lF}z?ebs`T2R=bxf@p3tSmlIfWD)3KpyiT^+nwOG9AO>g($noPeSJ zlZ6o+sEiDZ4B`wTz(7rVpx!61#`kpPq~`_|@;-|+thPn+ zoeWb0ZnG|adDBd)=W^K0Fw-^bw;kG=U?gea*?cVG#G0cONvhBSk1riLMYRw6|3VjfR4YfkOXx6qUW>JUe+3GcN<1;4n8-_ z`r5H{?MH4d%9#iLI83?li7v0<$1lPAUhuta_m6oYY`W6uFEx85WYuf*Cf*IF&x-* IlVZ6w0P#4A<^TWy literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/grumpy.gif b/images/mood/palefaces/grumpy.gif new file mode 100644 index 0000000000000000000000000000000000000000..335119ad0d9c7e8720fb9c4a97bcb171d058aaa7 GIT binary patch literal 418 zcmV;T0bTw_Nk%w1VHp4!0J8u900030|Nl%tMB3Wgva+)3>gv+c(&pyoy1Kf;!otqZ z&hql|%F4>t*4Dnhz5oCKA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E)5XecZweIN6J9iTijAUt^ zgfyINJ4nVNwXC!l5>piN44A*kV#kmqG`!L8v>a*@#=+pQTP#@C-9ZWkIHWJ3b=*@) zLEb^bC)v5#fW`ogXsiPg0l>Wr0`ztW5_LFue|vm>dIk-G0EBRS1#pax2nLuGNLmLJ zm^u(=8h47;Dnn7hUb#0d$; z(m6TO4A9OJ1lQ1A7e?I-x!oWL4vrJ%f)3rS2ni172nYoA_V)AU?4i){`Skbx#e>$$ z)xCoV4}M$7FaiJ}`2+z$01p5x1^@*B4FC}U00bQH$sjAO65yw||6nMNWNDsgiZUU? MINb-pBM<=qJC8c7*#H0l literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/happy.gif b/images/mood/palefaces/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..53b37a9b4e80209993939177f498db93741a9500 GIT binary patch literal 871 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{^S+m9F&J&wG+bVRLJrm=Km8({-VzOT%yPPp} z%bJy2LRT=!hK6WybL?DkX!Vg$4sNZzdP1R`EZdK+WZ?`I(%Wk!At}tm#=L1Y6Eho+ zu%v|1UQ=0lDPcZtc2*YVZ!E0r+*e%weB_Ow=C1BI3lR_$G7ak=(aydO&Na00}+3D1&!fF*~ zOeQuZi*gAo`7B5tVi6b(AJkJ%@Dx4-fI z!A9ldy%GtlRc0DKb}Rd8yMsNR|8rqEbG_$-MJ@u)0)Z`p?k*iiS_I`1T?Act1Y3ko Om%ez|9?HVRU=0BLC~C3* literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/high.gif b/images/mood/palefaces/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..bff3498f0067a2b5f502a6e935133bbbe3b011b2 GIT binary patch literal 483 zcmZ?wbhEHblw^=(*vtR||NsBrwQJX{Teln-c-F03ckI})SFc`Ox^(H;vuEGFeLHvV z+_h`hX3m^>=+GgcV#WX5ey$1fcAl?KjE z3La|;wn-n5SR(nF>rU3e`-O}`jn&qT_6!_6^-XOpJqBF~9Fs*n!lXndb7XRGcP7bk zCh^RjJ&Ai>=>n-F<|QkZF)*!QSXr@lUB%q3+?m{LZX0GDp3BW}V6PDC{sYI)9=AMu zfQ_5=)B(Pm;vzTs4qRhkWxL7r^r`5xr#IOiFtNRSsrcdPdm-KfpMSnQz$?tl${@`l z<58e+fa&ix%@7Gjknb6}8Tc7=SQ$8h6bsPzf*)8vtlAnJR`hXOOnK{+j6gx`s`e_Z po;&RxPs;sxcY$bAJFKdNJ~Xy1Gg)BIT&tO4V}u=xN0 literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/horny.gif b/images/mood/palefaces/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..902797009c2b8330a84167fbc342ae8a92e7dacb GIT binary patch literal 493 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11}efwU$dUfpBv1iYoEu1*@(xprH?%n(J>C>)V zyUv|Ew{6=t78VwuV#WX5ey$b<0<5;@!G+<+?-pySMJ;VP)OF_{^OBCwY#a zJjrn7s;$T6Q+rP`-%HGry3c&_&f|NNq`03y*~HEIf}5N7%h#`;UO$<{ewX>j=WqWi zy~`X9H?pw{X~mo{P&`y1pzOsWzz7ZoK~OO8GjK4l0U-m6aDZk~kkSsWge)Nzg|2xC h)0l)H>iALB@dq?=Ug8l+c<}Dcy_6IW7NX6v1^`@_uwwuK literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/hot.gif b/images/mood/palefaces/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..7579818afed78a1c7d5e60fce9962012c1cd326a GIT binary patch literal 1001 zcmZ?wbhEHblw^=(c*Xz%tgNh@oSdhb7|t*;oMU0Q$i{e?oAC-4<1K#1>w-)-1exxN zGu@VCx+B4KPl@@y3iD-El`E<$7tBmA*;rk%wR)hy{79Gip+3tKZI&lGERPIWo?5ZI zFlTw~%<{^W<&_8PJ3rR9fh-@RSU$wCd`@NllFafYh51V=%hzn?Z&@tga+ts6u>2@w z`dP;GyOQxwCF8$ZhQq!-N4>l*x;kC-cD)$raVgyEa-8>-SntcJK37wGuV?#S&GEfn z?03Dy??#p1t$N>m9YIIBgU&|!-IWSvSgb4nD-GfOfQ+&$eCeDljP zQx)7(6N?m#^voC(f3h&>0u}0jd;y9_2KIjq3=E7dOl|EQoh^(_O~%3#CQh0dIN7+@ zNQfnnW$wH=EX;Ek%oQ|h5@icyWno>ne#6E&B26Z2+jp$mxqGKclPL#BZ__~zcJ_mZ z84j8@nQ=03U*hIs;JSYO+KsE+W=-Zie2@5epFVs3g4evsQtaJf{*MBm`9FNLXtI`+ zY6|R?U@%X3as9<1R@tVCk_QY2ZSap(C?5Qsu3MyI=D>`;H zwO$pC2u`@WOSE%=iteEaatp3pR< ztCh8@oo&|idEN6H5!x7m+Qb+*f!Ykg+JKr`g#rRQdRqjWSSNP3^z=?^Ve6aKJfkmw zeSXutjwMs)FI(QXa_-_qi?Etv1TiJBwY8n4qo<`kpue59WpYn VbIs@S&R^ckKYw+Aeb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nY@e}}Pzq%aQ~^8scy9$`rd z;~i$Q@>0Tl-0Z9@%%50T*}3_IrQ~JJc33DV*>MCgqaK0%c^KeHSr zE;21uAya2PIX z=@QdCQdi*nFp0HmgQ8u@Q5M6dDiYC6IpIKkcI-_Av@cf-RP zwsbHqX6+U|R%QEkX%cI3z^${)`m^F zu%I#7y+Yohf#v4>c-wwii!;kx^u0M8T?E}^8jm!2n(R;za+e5X5p>c~Jku(XR*|T{ GU=0AwkZD!` literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/hyper.gif b/images/mood/palefaces/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..ea5a47026bc65acc724382e47ca83b4b34fc9199 GIT binary patch literal 1121 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$WK(@>6S}%NcrkEi3TzW@$ukmdo^(#op5d&(`PnTc zqF1j8ojZSv>+aoc^Dn-e|MZo>3ju!qSEqg+e)a9M5~qNS1xKOEcC)u^Chb%VoH!+5O@ z&ESMaF%}^Ohk^$Ujf*`dipkDuIB;ZnfO;D+kdebsfu+2zJ=wNoJGcg3mwj4Jkmd$XCx#tvq?y?0KoC*!UuS?0SRIeh0e-qj;t+PuBmzTA`_2jZInkfdzY@+${IDf)kb-;005_3(hpiJpKbFbe>M0DFIb ze{XMZcXxMZXJ>nRduwZJb8~ZJV`F`NeQj;c>2$8HuCA=CEH5uFEiE}5j>W~rg@uLr z`T4oIx!KuSyWMWH*=A;DtX8YVVlkV|)6>&aQ&W?ZlM@pYCd8ySuBatFyDSqoc!UG#U(swzf9CUf*AqWCN5cq$cJD?9<0OT_ps&U<|g$1>zEi>&bAVq9g?VjgU~P z8^e>!xkRL8kS(APLdf)!T02jl!@<+VY=MN8CGj}hdxV~3sN#A@x)zbloiKX(cpee+ zL7&UTGYa@Ws_%=@0Pi6psYLw#lTUOC;U5ekl*8F2zb-p+-npN8ERsh*f!<=8s8YT& znMHFy7n4r|OR};tR*=YK0>xy8Z`W-(U}c73%v0@eewh-pvfYjaYJ5^d!X)+h8}>s* z(n2oXDug+UP^MM`fC{nCzk=^jjI70Ee=xct=LW`PKm9`%>s`@{1#NV!*E0bt4V z_3h(VUo07UO2~92(2e>%ljB$JZG^2)pK9nBL$qZ%C&hU8R>nBph^e|Ul PXc{Md-onfTfGht16r^jP literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/indescribable.gif b/images/mood/palefaces/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..e88f817e97ecb79ca0d2fcceb0f6d8bfe5315104 GIT binary patch literal 943 zcmV;g15o@&Nk%w1VHp4!0OkMy|NsB}{r&v>{QLX+`1ttt_V)Dj^z-xc^78WW@$vBR z@bB;M?(XjG?d|OB?Cb06>gww0>FMa`=;!C>=H}+*<>ln$W+}qpR+S=OL+1c3G*w@$B*4Eb5)z#G0)YH?`($dn=(b3S*(9h4$&d$!w z&CSfr%*)Hm%F4>g$;rsb$j8UW#l^+M#KgnH!@|PC!NI}6z`(!1zrMb{y}iA>yu7=+ zyScf!xVX5tx3{*owzajjv$M0Zva+$Uv9PePudlDJuCAx2r>3T+rKP2#qobjrp`V|h zo}QkXnwpuJnUs{2j*gCqh=_!Qgn)p6e}8{_dwX|xcXoDmb#--aZfNUaBpsljBammhjMdtb#``mJr$ap6rG+Fo0~m&mO=plsHv)}ssTcz8>g!W zNmf`)7_0yR8+dmr2nDhLQEYg}cywI@sR0EDD!wle4+hLp$6-M_T5)(`r~?KM5HG$o z78el-3dUEeHgtGA1PKur7Bs#%8yy%CO7N^fFhGF80b=lgVGsdBhYdJ<>F^Mu!v!N_ zwj40Pks}v8Vga-{4$dqXYPZbLrK#&N*x1`i@iknnNrhlvv_Ib^5+0fK`HWbn8_l7WNH6DEFCHIc%^hz}e8Fi?({7R!mam@y+p3>oH!M1f-7Jo*^qT@X1|1V#-T`0?M!f(Olw z|M}rp0}MsbHvVGj!KkOK}g6o>~9Gw8sB4?h4AL=Zv@VWJQt z0`Y?nJm@fkWOz(bLk&7K7$OiQo(P1BKJ=i&j8h;(1rbUx(S#FEBnib7l1V<{L=#LX RK?D`ZRB7dvSRNAy06U>DwXXmG literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/index.html b/images/mood/palefaces/index.html new file mode 100644 index 0000000..7fd8571 --- /dev/null +++ b/images/mood/palefaces/index.html @@ -0,0 +1,108 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
annoyed.gif
anxious.gif
artistic.gif
awake.gif
bitchy.gif
blank.gif
bouncy.gif
busy.gif
cheerful.gif
cold.gif
complacent.gif
confused.gif
cranky.gif
crushed.gif
curious.gif
cynical.gif
depressed.gif
determined.gif
dirty.gif
drunk.gif
ecstatic.gif
embarrassed.gif
energetic.gif
enraged.gif
enthralled.gif
envious.gif
exhausted.gif
frustrated.gif
full.gif
gloomy.gif
good.gif
groggy.gif
grumpy.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
hyper.gif
impressed.gif
indescribable.gif
lazy.gif
loved.gif
mischievous.gif
moody.gif
nerdy.gif
nostalgic.gif
okay.gif
predatory.gif
refreshed.gif
relaxed.gif
relieved.gif
rushed.gif
sad.gif
scared.gif
shocked.gif
sick.gif
silly.gif
sleepy.gif
sore.gif
surprised.gif
thirsty.gif
thoughtful.gif
worried.gif
diff --git a/images/mood/palefaces/lazy.gif b/images/mood/palefaces/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4fc624c6d5cd74e0d1e88d0ba13a63a527200dd GIT binary patch literal 603 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$pa0d7?>}CB5xB)Ez{mH3bBdDd1Lg(+p$?CN4ULEG ze4}h~1OgNrSoma&Zk%X{>}Hjbv?xg^Y;5l3)(g^#I5{cRYXXmqfi{D{)6>(q;tsJy zEMRS9;Si9qNLa8UaItf( z!{gYtZ3`DJJa_IK&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kxbb$(WfEegXNd^Yie+mp4OOoehcx5d*!BL=d-srNPn4|d; zcJw;^np-Hy^szem3`J{)fMlVxEL->0zT zQ)=8^t{-|f4-PzZly`13@>x^CIR7XQkCV}Yt4@s`Y?6j1QNbS+mNZT0PC7N^=OvY9 z_AN>_8J3%#onbZ2eb;kA=};4&$7HS8t`f$;o`A((yo{hgWaMIyXV76`;9wABU;_rC zkwPPf>*bn^TOv$O5-kQiuDRlyKO9;-;a}4=ZU>cfbIGo!0c^QEF7 z6E^ C88Pqx literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/mischievous.gif b/images/mood/palefaces/mischievous.gif new file mode 100644 index 0000000000000000000000000000000000000000..7860c4c11b715609f62a2c1b71eb7fa6a3f92b4f GIT binary patch literal 433 zcmV;i0Z#r$Nk%w1VHp4!0J8u900030|Nqw3*1o>J>gwvo#>OxV5Yp1p=H}-1_V%Hn zp}M-d-rnBM&d#>Bwg3PCA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV9smFUEC2ui02u%o000E(5XecZwFBwRJ0Fu1jAUt^ zj>Md7%ScC(w6uIk1wmA7r588^fFK(IOviw1hX4WwjHpgl98nXxC z1_FU3Fwwc!lQegcK1vKj_l^y~rxy}*H+*<{dv^c_0)PO5a1w@(iHm^;mJ}Lp8WffX zj1C74ifK_DQE3992Ppuc4Wg)8vZ$e=tPZcQqo}-TwXe4g1qHdC#+JFm4Z*|10M5@i zK+VLr!vok{7uf^D*4)^P6AR$otP2I<3kweI?(Xa4-HZy?1M%$d_}Ie=6ABI#2pmYT zpum6^5-OY!0RSQS1OX@j4*)C!00RIM015yA1S~LsIfK2D0*N`^ACV+oX^jN)tgC6U bDl5-)ZP(kK%SKiAyA?3-^T~p=U<3d=nryC* literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/moody.gif b/images/mood/palefaces/moody.gif new file mode 100644 index 0000000000000000000000000000000000000000..87a9ade7e997708d6d4dd9211fb2ffc666183faf GIT binary patch literal 485 zcmZ?wbhEHblw^=(*vtR||Ns9#b?VfuTesG&TW7(-^Xk>BOP4MkI&|pSvuEGFecQEb z*S>xGu3ft}bLLE-V#WX5ey$6e9iQZnato6O0v_Gn)e zlA|g=DS^R=bH@IOJP86G0#eTFRYN39IvyuXFwjWl61w(tjvHgo%j``@gN`VCSfI%1 zv*yFMC59gQQaR=e99rIgsj1LpD7R>+Eo^7!ZEh_Rsy^P|-JfL@m~V_Fpw@c8$Z zBI~QN(XTSz|39#x;K%PZI)Y&Bk`V38KMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGId-onbeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$H8O*vFgj{qb7$!~f(CzP0>d#=FJa5vRK4)%*(1qfVOSD6 zO=-pE3Eu0J)^AWUU|6w7S8$CISE!(na6_sggJ`F)&{2DaBLZn6qBk0y1q3f~2|TzX z^!UWn#}^(7+!NsEe|Yf2$A@oUDRBz$@x5jE{U;0bknR#>U3p-rnZs=F-yAosE(5^77W! z*4o4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LVHvj+tEC2ui02u%o000E;5CBK3y;#a&y8qxeXiZ?A zXsR|+p}ue-9Z8}AaB$a$LHy zG_`c?RxXSHgM~suk!4-|7Z0C!u00Dyi9JvumpgpG{{3W+^9jD$dzGm{$! zo;MwL9XFl_Zw&_wk_%>3A6cx5sw@Dg461ysVX$(kvl0!rw~~OY#(=WIw7~=f!llrj z!p#iJ49(3~R@+M0&dc7}hCboo%>(G@g6Zhkv;zd}0}b@`_44r&25dZ)o`2+z901p5x1ONyC5da1N00b$p6eCi4I45D`nnEa!T(NwU dk*!8&0x%q|LJTVkN{#MuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91kV{eAvKvm^DDc ztb)UEQA?MY=COtX--k)8T^khbDjsZTY;Nbz@m>(|P$_S{LQC`-53i;p9D)1%N5iAPptdP|NZ*Yg8M@I3=CZa-DDbFgm|eb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nPdURa4*v;N4bhe6d1JlDsPY%VkJvxp}?(5~${FcaQGB)|9oC%4tOk8x_TUgT| zYN3JRAr>yD;4g2UK5pR>VKxj=@LI^!)~FFO=flOz3GXMevq=*-S18M9Vn zp(FEgzK?bd44jAJ|5wRbKX8~YbWlf;MbK5EkVS|`?V&=mhfJc2pbN*wBMuU2D-_!r H85pbqgpp(o literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/refreshed.gif b/images/mood/palefaces/refreshed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d224ceed80a723780d4ddde211de783f67614b6a GIT binary patch literal 681 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBNa}rhIapXV1a;&9>meg2ef1 zx-w=zrVBVQwed=1q!_F|+SJPLmZc8%LXJC(|siw@7Ao)oHF&5n=)xBf=n!Y>dhS vww?oN^OR;X-RW5O)}rT5_PHF(8E?7Y%$Cx8ws@z9s&tVsM583-_FDr0wAKoz literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/relaxed.gif b/images/mood/palefaces/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d20441e97d3ff9e3a285ef604cfbb31b08ea81a GIT binary patch literal 624 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$VxbS&DowU=)a`u^}NrfF!BBvyp@65P(hbK)o ze}{&!tFDJstG`!+h#3Qqu#l3klEmc66Lf`yySat>Co(fknL3YQ4!6?mz{TQILKX`O zEn`?QO-X#)wk-_nH*yQ^^D@|O;I&V1BbT7Sdf~<#BhiMwlY;gPCj?H-Xe<)Fa8c;w zsjFN!Zmgek=H;9RPX!(e@bf=C`eonKkMEQ?1^D zywX3MITQ{aV&gF~>bRQJ=*Gq)8xZqA;c?SsE}fuNA(fYunb|jTeKEdSw6tlO-fz(i zM+HVE7Ir=f39l&`7v^(v*uLmZc8%LXJC(|siw@7Ao)oHF&5n=*IgBvIsSQ(fZ y_<@*#l}|yTC?&G%K<26^+xF#hfNhdvkVaO*ub|$S!Z}B^k|~;diOlUb25SIRv+myj literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/relieved.gif b/images/mood/palefaces/relieved.gif new file mode 100644 index 0000000000000000000000000000000000000000..6f70c4ae787e7b7ae892cc4e96fdce13fdc8fca5 GIT binary patch literal 775 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$PekFwzIj&Y}VaXUp%wA=a0f`AJ%o~Hd} zO*beg~tATWLY) z%BA8n#eJ7B2nwxbSU;N~>A=37ySW9A^%@*7=shO5n@dn&r*K=Lk!b6bi-PtH7X&WN zZ7UbOaZ~8xrMp}Y9_(Cr<>SH^Zv|cp@bkYt`{&r(pWj?m8Xg>Q+}9koMy4h}z=^4m zN7`e`jTJ{-I@#ozJRUeGHTUzBZH-`<#OT(`Z6s3@b0Dbk^mP5mNhuE!!W)~kQxAnG z6sH|z(&bQb0Gh@iu*)XRjiu`6J)7pnjhC=?m_8KfC>m>HNEgc$^Zq3Hi$Tj7$7 zc`D^hZ(eR{kl6ht`hJC9xY)F-l08e4W(DX>=RVfz8KogSabo()$hLsXJOzcZ+tfN! zqHGh@AAQ&o*63C8VMmSM{WDqRQE{)i7_r&m^k5q!$c};{pdE8o>@=ypTCwi(%2UhL zgxEWnc)S-sUa;&-Zqn?=;1m(vm2OD}-7=Zocjs34=uMWlG+7szJl_dytPPEwZVdne C$2y7t literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/rushed.gif b/images/mood/palefaces/rushed.gif new file mode 100644 index 0000000000000000000000000000000000000000..07302380ac064b1776832e327e2dda4e03dfafd0 GIT binary patch literal 714 zcmZ?wbhEHblw^=(*vtR||NsBb^a*(O?Af+$+xG3-ck0xsTeoiAyLa!}wQH|ly?XTM z(WOh5K7IQ1?%g|}V#WX5ey$0YppLV*preuucc*9PPd1T z^42w13??nq_{1|~zh`p#30|>17vFD@(PMLUU~F`-lHwJ+wlE^VG3dxc)g!a2R~hao z@c5z9SMi6}L*_tBi?xCv!;|6~hPo**zvrtr)Wk(w?g zGKXh2+a&g6f0?)yoIJ~xE-On8<&I0rUB5wyg>B!asuhQ-*6nATa%|t?({oN9-*axC zrRBvFY^*oLMQ*U}J8`F-wN3F+(2eu$*B`OGdHe3&^J_QWe|hu#Mf=xZ?{EG6CkXN` zBP-CuIxGwv41x^2K<`?8So`qS?jNS+*Q`%0(D3_a@wh?efys>P7uNC@Fm|oH@pZDw z+VHfpA3viEPHIiev6_EjMTwWM*qrO$EMVg#QH|65(8xJ&@1$o7K0XoANSGeMIxV2` ng>l_oR)0y~Yp>V7uX+FfK*EFr%27&S-CU@;2i7rE3>j+xRI)9H literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/sad.gif b/images/mood/palefaces/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..70b6ddaa456ce38e0402f97b5c9ce147695ae6d7 GIT binary patch literal 860 zcmc)HX-|>?0KoBwOHMTe>A?dKwWYQdX{nR)CT(eWV$I50HDBbWZ(3_Dk6LLuhDEOB zQqi1v)KXF(=LG{o1;sm^C!lyAc;YphpQ8U4_`Uewh~)VBKcoUwzz6_E0BEsTPEJma zkB^Uzjt&nG&1Uod{{G(H-p_V)JH)|Sa++Su4wUteEaTU%XSU0GRKUS3{WT3TFO zTv%8z8jbVw^K)}^27^Jb*Xwk;+1c5dnVIS7>8Yuy$;ruyiHY&?@v*V7(b3V7k&)ry z;h~|S!NI|Sfr0-1eyvv9*VotE+pE!N)M|B4PfvGucUM=JN~KaNl?sJIE|<$>GO1MB z+1c6A(b3-C-qzOE+S=OE(gHzHb8~Z3Q&VGOqeLQUXlSUas;aE4tf;6EiA1HPr6naL zLZOh)=i~8s91e%YVlfyD8jVJwP)H;afk43Fa2N~*{J$=o(x)!~v?VJcJ}x$f%e@^P zm0u7Qefxb(Y+QUo0*`(6Ycb_p38lE0%_|Cq!^G7!wKeeI@6J_ql3KVkFVPc^X%O>j zJFDRsyeD+gj>uE1B^ou+?jqy^Qb`0WMEehf6@f$reIQ?Fx&z4uk47O8n@AKIZ$omR zJNrWZ3?^Mmb_4ymGKnoSXfCNK6q)x_;}9XlWKglhfTCSSjQ;OsfX85iSee0I;2yD) zWRxqgpBU~zUp!#O&!ls&e)$xZ>+NwQ=B=_>@9@4Sfzje16Co5;M)pj3@h(J}M^|Tk zPZgCba?jANra%BrZe{Dj5poBZC_$ZvEV(X7cSV7=b-J3qx#^OIC3_`9_b6`Z`SzSh z0q9b0!YJ9i--4s%n*s_e<#$SbNcacx`H;-S`kZh)$hsR((?9xC0J0uS?^E79e>V2> z9^noL$+32nrm-DqlN@U>?1dJ}4!yyld6n*hjiG41qxZ)L2P{_=pLYE<0J96rJzy9z z&5QM}DncEvXjoi`cxk53Yc1TsYpP>+%_UYCk>ivdW{2?)dq8E=W<1eqe8oS3S! I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/scared.gif b/images/mood/palefaces/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..e75a2d1bce06cc8352dd448d65cb8e22869a6c34 GIT binary patch literal 407 zcmV;I0cie5Nk%w1VHp4!0J8u900030|Nl%dG}_wQuCA`?>gv+c(!#>R=H}+Qy1MrE z_Rh}E*4Ea(zP`%J$^ZZWA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV761SMEC2ui02u%o000E(5XecZwGHXbJ8x4GjAUt^ zi8PGW8MMJ5846(9B~Aj0AvuMDLg6|MgAU0-BP13_N6kSw7$AbfAt|c}BC1nBqbi$l zvlKE&JYYy(lA!!OVGPy@h8r#b$b&W#eR?SXc|Lr8e}Mpf1`LIVba9J}0FRLdniNc4 z2o#zInG26(9$!@q2Bf2;cBUF+ZL6#j2@ANcda`YLw78KA4i34Y#+tdq3xxy=2M5E^ zKR?k9&kF<+1lG^b7fRjG*#HFH4ImALA?OX=;|T}n3G?*z_U8x8&+_*D3HS%bkt0B` zpuvL&zbRZ80RSQS1OXNR4*)C$00{sO00aO41QHN{@T#>F2uW|<6WDno=UrI@06Qt8 BoKgS) literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/shocked.gif b/images/mood/palefaces/shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4c79bd8ff4d917c4fdead4e5c2a5b8e14cf77cc GIT binary patch literal 871 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPlj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78oVp@Rnx9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91h>qO)h)gimv1VqCFu)#_DD zj!R^ghi~4zhH=YQCYkUsO|J0eE5lbGUda^BrMX8>P=JGF+Zq-Q0YSYz#^Mq}+-%GT zS2HoQaSKU^8}Bifk&_hS6AOo++JUEvN7`jJ zm$gU)c8fK4i)){g5==V2Mo!s-XEy7DQ_Sod@;!TkCLQUJ+gvlnVB@Bg7Iq8eD|?a_ zwe-(W4anGIe=M`fwq!xs6xWW`}B_lWX_R%}o+%3zJ@U2r4;wh<&tJ z!6jB6AIo`&=@_?|cE}QeD%Dq_BAOv<5Zo z{%T+I<;Fy3x9i&885d3z+WzfVaAJ`-!v8UMdUKukg+oUKTqO!wggjkV9BC0$Ydj+8 TCSu4UytDMh!}f3%CI)K&^B-yx literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/sick.gif b/images/mood/palefaces/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..1d313ef7f9b187aca928947f11b506a342821eea GIT binary patch literal 1856 zcmchWSya8LI-}9XJcb+#W zIMBy8${yH*pTHX-(EyDBCPtY7Q%e9@0y8r+b3DM>0L$&biU@Fyz}gAez`)i8*tvqw zYLKzDsJL2891|1Igc9m35}1~kS=JPmbyB@ua)W(pmNdCY{{%*1>qrGS}I+>yXw-Y8=ym9vv8*eNCa$TD6`1wXD_7+obwtP)?U zl_Xa3QY$&vYxp;+I5%qqRAz5dorF>^zQzT$DD9mUcptTIpTYC$dyBICqMJ-*$ zt-OkR{F;uQnl@os=RhG_RLdE-%N;0dz(8wxF?-+sYQ!arkW1A=nb%OpTL0_vtY@BerySuxDyl$aDDC!YPI3kg#zrVjln${}KY*VJSE7Ch2WOd34 zI#pS0RW?Ufzh^wlmqaO$ z$VCHkv1GJPrs$O`CGtV8Vo)R-ZIX|)JRIXcoaCv-y46#B)u>1{A|9R^P*3xRv|W$1 zJ;O77!`gnCOr}&ShlYk8jXW5hkPnY5hBfMu(Z`yp!O_XbBij2T(~8kK#rV8(a&~y~ znR@c+BaLQcYpI0}&-*{!z=KALApEfr)e|i1O>wj-;LI-{*T28@|n{CexYPE+rNY3J!#i|Kn<03>*{_l?;1(9t6(+LK}|<0FO5bZ|(>{TL1xw zq;;As9kQ|B0f)ja6x^<3Rc`oG0e&0am*!O5dYGbP@Fi8p zm1aB$siny5LgT-L+W=vyBr%3^JLWNSg8l;FamiLr?cy%_#j>)0TDr}-~}Kp zUM;%PcG8iq*wD7C$14vaOHtW?g0;T@GLoxZB0)9M#3IYG=xjR?iC%#qNV+<`@|Px; zVEVjHcJD0r!edrgydM&UK2p6%hG^jZI~Qp__*gPbbvj3)V?3n`Q6O327hpXRkgim12eXHUhX&H8rf+SP8 zE<2hW5H`&v+no!SrCa&VQBYRC%hLPXoz7k0nmC0)CWLs%O-e&;Bk5LAmR?MN9C6ii%Tv1l0VdYkAKWtVTi>&MlP*;IBo_aj$tCy$6es?q}b zH3|#9`(xBG@C-qObk(wSq}lEa0@GQZu>oOX_mDu&SD0B7;KhOur@La0ytTejoqY|B zWu9h6$^y{PC?1E?MGRrKc}dO}N&)>E0`a^3|80{)zd1Rz!_4;EdeYxfx0FTRg(Z87tWijC_`lOw BL7M;o literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/silly.gif b/images/mood/palefaces/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..38febb68674aad005e58b5d1273e81d5197a185f GIT binary patch literal 1030 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$Y84jDbg3NQs$QNn-Nk{)r4i!d=`#eZEts`p)H6niDAF%^*G{WJLsn zpwJSAW!~$=ckI~awrQ#0elLTa244FGH**OJY!q(DHWIDxJtb(*a8ls(%!WeIi zoxa9(^XA66XJ5^I_)Or506+h;V_)|_`}AIkQ-F^z{?k4N0f~YI_8gqwYzrYc&7i}|z{$YRzyb_D;RnYUqcdkMj^I<@ zH7lq3*pi${irCd{D@@AlQ>$FoaARG*HBYu>K2~)i57=^2GW%{Ptjk=PCv*EylFs#L zu*Hyg1I4m9g9JF<4n(A6&QoL7hOjB%=&NI*u<_cK8lDn~htJ!ek2R3FKiRR||MqoVg za0}HrFtoJx_j30LdfPFGx46m76cm~&G~L%meED*_c?=7t3a)ohS)t;vUXU9YPYZ+# zW7R|pYIg~8?G)JES(qex@X+EDN4ZX1>^-%&ws+T+W57tdvhC6OEB6JsK#|1HaR2Q) zoA>Wt3vhA<@&4-n^NaV*_kBBVZhmo*sfp){rN@Q?2j_Y1==o}}jNy?SJ2%&wYL1DE z3_I8**Jv{|I54qr2=d7o9N3iVJykMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkCaph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^@fzw8wvrDjr{98CuqEG(bO6)y+)A^978gwp zTP!5JjA6yJxXdsHUxxJ?xrKyyJ9x!2#SiH6?%T*EB*?&f{($kh3k-rn_6(;5&+6uj z-Oum1eO-y`_TxD-L|*sLIrIF+GXa6;`@VgD{#oz_ryxK7X9gA#3)VAx>IH>5JQyA} zHn-OaC^o%dSm4CKDPxszV4~w1F>WiPiXRUiHL=SWh_47auqoAhs-mP#N9coiuNiux z2YP<4ci?8?6i~1zIM8r$v3n<%uY<#)%gX~8TY!Q5lZBCkL6$)W6qJGtY``$oO-PNM zxvVr}RqFK6z^ko^k-6!gzaDx#_22Ys+zu*cb#vV=-pDXZ4_IE(<>TcHH9-d11Vsh* r9)|RJN;Au}tTw6GELa{>_AFqRh57!q!Ua>5E_E#x0PFIm$X;szv^xkW literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/sore.gif b/images/mood/palefaces/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..b75301ca5ca46407a71bad249495bb694de42eed GIT binary patch literal 1219 zcmZ?wbhEHblw^=(IKsm4jDg{iipnz$jsO4uGcYiGn>+WNfx$fmg=f9JnI=go5I(F>Xt;WV%t5)5*b?aPd>9yM0OP4M^d-g0fGWK3;>$|B_&z(DWsj~8# zgv28aje9^db##CRD*os8a}5c0b_{Se(lcOY1PT3-7BG@ny4g+1>6< zdF-%7agAtcZDmDO4U1@UBTKUqZ>6`g?gR&smcl?imCC8TB9fIEdZHPX^D89hi)6&5 zESa~gcg2d?t5$E>B$+SC$G2(A{!M#!ZrpQpkB7&xL;0uFRZgAR!+ZI%>Xpk!&s@KK z=Q^Jy=cT)kdG~NCbMkV&e)IO->sRMKeO3hdjFE#uo~YIeFb}B3UlN6+ivdp=hJcixv7efeMjdq6_IPRJSMpn@0?PyTYOu{RgYET8f84J z-un_?r1u2YuX?`f_meh#x&ECed*knX&ML{Ot#5GBaP+O30wwSV#~ zi@sjr88c^h&!0AbN%xAC%Y^H^q*e<%ZIs^-yoP&Sa9&pMwz}Z-gIWQH(u4OOtUGo3 z^g*fpap`9+pF6L8`Nj=-tR7hMpqvBffoF``sQ zQ=iEwQ{9rtR38;k)5>nks4*$nws?ZfWc8Y<{S#Vd&Ym!B-n`O&wC(moCuMD=<)u$vIB*uL!|fih_W&LKXyrPf!(UDB zGmbsAB4+Y0zQcQG_(|;fT5~+sDEx`+Oy}g_SIj>3H`bJ$UfNl(|A}$U+gXuU3plVv M=8z4Gp_K})0f_S%1poj5 literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/surprised.gif b/images/mood/palefaces/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..be69df1fa2c3d4f87ed532a0a232fd273938c290 GIT binary patch literal 675 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBR>UF#b3o-@@{n%Piu?a!>9y z-hYZL6Am17Vv~?OleJMnxw(~3O|PJ#u+fuMLo0Zh$<2w4&5^8srlzb6Vmv+VAJ-Oz z2@H%)%!HO{|4qBb?Vxh5Zn{#S(!-N!me*S(GrQ_ESE>jxfsNs3kVZB}@c~=U zfwXx_GmEsWHmTSwSRPaKEMV6Uv;Av@3#KSt>RKuQ)};&5#mvCWAPj^ItcE~ckAb>4 yJ7R9H(|E8?d{?1a-?g&${|_uE@X(R!Ke41JQ)g=1h7}twZU~&|bV;9u!5RQ5Bnt=t literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/thirsty.gif b/images/mood/palefaces/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0fe339de6f899c8607ec23a100870af667eeff4 GIT binary patch literal 597 zcmZ?wbhEHblw^=(IKlt|tgNh@oSb%x|4(C(==thiz&5@E?)3=x2{yy-3 zpI^at0p5C#CmWO|Wtbg$vhn)O3>75~w#!0+m9YoP6sls5NS)(rNGZ3FdiPYZC`3!l z=h?}?_rJmJ5_HYXc?h@$~Gi|vld`ZZa z;iBN>`JEMFEgjP?UB1Wt@Zqk-S3fPj{Z8D62%Ck}hpdANDb1by#%4wp43ip9vl=8HD~a56kU5Tx zXWJ6ZV#c$x*m$>SEKqP{V&UM^h}|W!GLV&3$7^nuAqyxN8ATXm7<3pJ7#YMFSb@PP zub|#{=O}N=s(DGCC#Nqkemv&#%2#y)BwrfN_JYM~s0Ts7D#7=dmka%BfQ2 gRqN(hZ_0@}{N(SkVyhF@f&msaqRp$6)ma#<0e$7}*8l(j literal 0 HcmV?d00001 diff --git a/images/mood/palefaces/thoughtful.gif b/images/mood/palefaces/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..3550c5d490e45910edf40fdbfe2c2c031d6d386b GIT binary patch literal 863 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91?Bg zv+)Q^N|@|2mz9?i=Hq5(Wnuor!phFgCoCl|Yre};LCLOU_acQx$7U|JIsrx{_qDQ0 z9wpLcOB-Fgg|jCLY+M}1FQmGT;YTU!q2|c~E|YW|7rE=otNE?iV#?d(o2r~S&*0(X zrJW*@>jP#8Br>%w(5$%jtI&zHt5HIWXK4WAVFwW{zdtKjRb076Roz-XY+yXh8X#d- z!C|mM5xAW(CFNk=kl($x)C3=mASJM#=!3pjr|8_2N zy&E3hw55Y_F>AM|R?rd$$EYn`qB>CrIxaGO77#a1JJO+;T((wXd*=DRw@DtlN(Nas zBWEx$Bc(fiWGuU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;t=<^ zGyQ{X2bW3+4*HH zQZlwKYGLD*xqR}s!}@#f)vqmXEI(r8&Ee=G=qA&6q{-7{hk}s1L?DZxlTP5BRtYh2 H4hCxgy%}m2 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/angelic.gif b/images/mood/punquinheads/blue/angelic.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d3ba77efd158bdb900e260a77c494b106d568ef GIT binary patch literal 2006 zcmZ?wbhEHb)L_tH*v!rF{=l!N=l}ozpJr@qeCCYt%$fgZ&YYQ+mUiaMnY6T-XU+hn z{xcu}#sA!Xt|7tBjsdPldIrplKq@^jy8y;`Q0x{}VKV zTry`pcH_voEu^_EjY%eY_3K;ab@TQvFmTjSYY|(NbTUL>B6n)>E1PdZSKeHDWmv&0 zq*FXW)p%|EhNImX$_J8;CfLoLJ(s)r_u6x>zvptYCYSh@`LJ>}k*hOPzNwjE?@chNgSFaV=-@Rvl_2Kio=U=|R z`2O|HpTGb93sT#|vkn=tM;c7NZ8(GX;(LcRY4Yb^^e{TQt8l%2IV;xVieRBwaY=Ex zZ%(^!Z9{3JaC1*tMO0Mx#0HV(;^wv~k<(_k2+e9K0r`|GCt<}Zt_4eHa2FJmS1{~c z9nZCsVMFcKbeXnw-qqg6Y7Mu~^I<)G=ECIp7gA!kU-7=|@8NR!!QB8MH`m8t4@-eO z{1WKl$6vlbhj{ok)WdRkVz@6QbDr|Tb=p~iPCBPstPjo%xXo>I-a4-TsF0L>=MtmB z7!}bAE0j)Fd#w+CrrG$`X{%iG4TXnp?6D;w)@sp5IxL!U!g$_Y-(9uK;KcL1+PeBe zPS*5_psGMt&X&R?p}OXRwyw;e-i8UqB2$W{#l_8UPlGUr(6Xo zYu0fsSviNhq@=orVek56uDuLf8h2*PbZrW#4>;ARx_eO|>-h^;rZ2vdk+}Ot!1WL_ z&+AVfx{>JNn-u2ZHDTF*n{?w^q!`7t+1_i)?2DDS_Ga_nzHoIepW>oIZ&uFQtT>_a zn#_9Nl4hT_%FY~--t7M5$SKpNi)PMhm=iLuvnnHgHqgf{g=^PywWZ0|H!$qlP_T<( zOPgl@CU53r-bW4|VqLQIOpNl5v&+sqx}3RupzT8Vr5m>cMBH2-K79sE(o*bi-m*V` l_wmicPhX#Y{ru|J?>{dEsa#?Wkqk`T^gNn@2UiBR1^{fzo7DgS literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/angry.gif b/images/mood/punquinheads/blue/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe6f56225b90c0a292b259bcffee841890c5c22b GIT binary patch literal 1147 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMGbmX>C0Z2bTKe+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEC&TndamAU@%rrVneH4)@|tB4Ki8&3 zcOZk$(BP0Xd*6odT<4JS_-`Idl}1fcMpR^zTWfnSb60U~U;7069tK8+_8GJK zn`LWi85bv1EN1MVI<0n2sUGv%RjVhJ)CG)s{rzSRdh1PYU=!^lBgZF-0h8J))pbN zgL0=?Pt)VRv*lN{OaAf99}Tf3<<5nBrmfQ!xL4Isz*3`8my#75)8f|N+0WclT0fz4 zl6@c0U!Ak&Ol*~{t7lxARJD|G;`ABy^UC#@*RNSSrMw}UWy{uWS-WURnmHP7Pl-##DaZuV7p_y>KC8*ThLP zr!Fp@HOFIq<)+#dJuKThw{I<*-yXUvKG1j9k%N&@{>P4=26;*b7*%ZNu3W!#`o`@u zw{Ko}0Q3~rIc8B zJv`3DD7)$VMwUXWs;Kc`Y#YbrY!{0LSrDx}MWMr}1v|rG$<_+7v1og|&4reGX1(t$`w zb7YK}Ko%0lV1$ufguzPP;^+*p0;Ov7kGg)g0I(zXmf$zm!8kJSW!X2!n!h+UeRn%wcZKUn@l z>yumBy_1*l$2nh}g-FoHHMQg)D=4IT;h8V$Nt9nI$cl!13aY@WiZOXfV`~bpy`=T} zXVvXwRLqyq1%1lg`_czxcgp2y)uM+=Y)~m48i@j9aR7ga8;qu8BRp-h+sui;j=0<& z_l%D1^iTuAP;dcWX8J<3?VZ1NR*CJPAFd_vmsx2wW*>YyQLh(2xQgC-&L4M5>q{(y07K~HIrx=|DP>KVZ^)7jKth$at>yiUs%m# zKAq^54XF=a4v4X}0EHf>4-He}xA zcG*FK!%g)Ef&mY_#PSAdTiZL^A!H4I7Fnl;N;)X$#G$1BcbwUIk#T;D663si1MNzd zeJGGHWToAA%L+&%)xu zEbL^t7HKQ1YpY9$Z64{cM)wVua;+GWVEWilV22tN*MfH zsklcfJTDXV(@$e*GQz1+{}Bs@Gz_5Y(cyYMR}Y&lR?8FzSP_SF-Z>2tX6LD1pWo+# Z7g$Sv+Q#PAW&l~yMwS^qo(Vzxe*q*Q5heft literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/awake.gif b/images/mood/punquinheads/blue/awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..13891fabb3c5a1f2687d8a5496c242bef98866c3 GIT binary patch literal 1668 zcma*neNfVO9KdmY{V43_TAFhYXH8};xFE$}l4K8-k7z1RLS1RtDeA;bMR^cS6c9BO zAM#mC%|Os(!?czU2ns5wSxdL8t=wI;yVlfYYisS;&#OPyj%$7Y{@(ZQb??vT8$kB= zB*kG67=*?Kaev0LsD0ksd(UjP)Yn@WjCu%y7z~ERVnJ9tXv;gHe$)t`gA_maoo*li z-$DP0TV6zS1ZhWfdI)7OqO{{C1I|2ypP3r{_SPKU?kycWznnf1&6dR+`NLyA`ruNv zV``Kpgzvq1A<@D999TPQtR~xeDf+mN<5BBUIY|x)@BX}<=d=x-oRZbxk2(G0DZ*F# zbt#wmj02Q(iU6GkOXw+aC1=1QXDaNFrq=?MRn-S%r!rwi;c1`XY)PKq zVDUm3=?CAy6+3Z|OU51lF z-&_}dtWfY}rZ85F=EIiwT(C?AmO4j)Kw|}~p(%`)<5SIIchsHnu=5 zXyPEXhTDeSyUSJg5o*j}z#AuxSktt5YGzCi57w(74zCAMTM1%)L44c7g-#zf4L;Ox zw%)lAu8^ux)SNWbq5lMg9F10pXRP7R+^hVqh8lUpPOm;S%gQNi^xp`m- zP*5lq(fkwhiBhmG)8_bDM`o%dX}2V}Ek#1lkYij``&3z2wMvt4na~Rj4h?G|lztR7 zI5w`wO_=fK$&uL`H?40+&l?fJI;zw{`d(Ozy(9EL?;hagxSkk&gF&G+uf=St5(TA+ zmt6S?+5N|29C3zB?e*Ck zkkt*hW_Y{JsMPlUs@`*GCE}iYv)8hM&s33m*L&G)7_wWQWO<^H2x?+pKA4unWAKs3 z0I7f!A_YX^V#zTwvrrb>$WEwpP|uaiIFEM1kUeTd zr^D+FdaQABe8My`3>#i`i2wg#`nLfhM_g%^B{sfrUmHUpF@M`?mYqDcpPE7;n~3bCp)`cqH?xyqOWPnS3*PbKFt>#Dn#?(7Ew9ya!Z_ARs)jpg@0AY9&+(C~YHI8D(O%s!5o%ZE0 GdHn-SVb@sz literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/blah.gif b/images/mood/punquinheads/blue/blah.gif new file mode 100644 index 0000000000000000000000000000000000000000..41b239e061827cd1ef4b974793966fa57e8cc8b9 GIT binary patch literal 960 zcmZ?wbhEHb)L_tH*v!H3^!)$#2Y#ic&73*&|CTKe&YbygY;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^p3 zwr9fyul&UOM|WSVn15QmF+YQOQj7WFfJ)=839QXq)Kj1JH9rvv-^)8k-qCF5ky`hp zMZf;Ytgd|%unTB<+t+GEKB08x2ImIG>YCcfO0(FKvg(BPynN=iqRA6&r}g{SO`kc- zea^J_`HqHG#w%8?TD_8e-Fo&F8#b@g*|J@C`_?sk_U_Xa1iLo?)xC4DxHsqZJ_EHg zTRxm~T_^sz>%GIgw<;V`#m+&2=>}${o)#mhD@&?O3;F@4o#|2aBLOcm@^+V-H}LMS(3k5_9%G z-&`ScXG!3S+zo#?)?9yBa{Ft|WS4g@dcLiknc%=+Fy%7$`wQ2lUhw~Btf;ICD>Gy3 zFl%dWNyugH>Fvv#km^%CxhZCv`-}-w=YT?Y>9XZ3ma(s1!@hLwhSfS7x9D!!v~uUJ V-B8CGp*nWZrv^0l4(`-o4FERspjH3? literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/blank.gif b/images/mood/punquinheads/blue/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e943c9cd68b9afe842c3950fea29127400f8d90 GIT binary patch literal 347 zcmZ?wbhEHb)L_tHSj56`=FI<@GykWh%}h&6`~Uwx0}Lqs=k{|A33hf2a5d61U}gl0 zEB<8ROkrSQ&;h9dX=h-r@z{0epTQ~5)q5>opWXdGL8EVp%A6GeTIvt>9kAS1AiH{g z!h5}QFKy=eGxOYPlW;t+gIht@YuVYIonDC{k3Ri6m9{3P!Cdl2+-d(6kyihvozML~ zJG@VL>SsNxzlX1X*JjbwXl!k3?@(dx?qP21ozUGiaiZ#!Nu4ui%~s?DJ1BsVgHkf* zX{fAOQ?SlKhxs+fd5gDoPVbIe`@R3poz-?^j-WD!N^RrPr9aQOnqPVKrm7?>^^VUs zZVqGSINc~K-|(|ZTcqTs|G)4h`7&SJ=GN+pI(=PJ&2}Ee2Yx+0|Nmm%+Amx0&Ybx_4FqNy8ylZF^B)KpP=Vrq zZa>$MU}whwS0g|f``}!?B5dQ`_LjQ&73_!IlJjd?s`5*s+$&pqY8$LLx~n-_rqr;Ps!ptt zoGdYYrV2ajocUFAt6AAQ7f)SRvue$f-rkK-Yq#`l^WVY5$izAAAm_dVoV(o?FJU}$ zcsb`8#^WbWE;+h<+4U<|H}AZ>x>M-X-B#9T4<0^x-12PIib1R#&*Bp!`jza@dz z0VTFeUQ=j{~9<;qN}7cOBy@tODYXi>$)a3rS(l{;OLyu z$lfZ&F^yAsy3*{qlI*OFi|SX`v$7kkn7O%e{l=A(CT-K+v~%KawY|X5SU8>Y@KMeK z3M*DJUO2Xf^8(}PGiO(xT(jiFk<%N@&+Thqy>al_j{VObnhTY@?0i}BPVB?W&u_ne zEBo^M|9@aWSO_SvHgRw=`J4!Nc&Lqu7Z?y57rAl?LK1}tYFLciL}4@<5Tm&RId@nC E0Kvd}m;e9( literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/caffeinated.gif b/images/mood/punquinheads/blue/caffeinated.gif new file mode 100644 index 0000000000000000000000000000000000000000..cfec9df4a5e7932b6fd946e97dcc0d30a46bd427 GIT binary patch literal 1148 zcmZ?wbhEHb)L_tH*v!lD{{8>=2Yx+0|Nq{-|KC6S|MmLsxpVi7jg9~R|37o)|FpE3 zX=!O^&H#D;8NfjCKewN2NU*bGfUA+70W%{|Q1K@VX9@!^gAPam$XEuJgBwnIuHI|$ z`t0ui2^xJVne#GMty{Bf&xT80`pNgt?7mhp|Fn8*eg^ZTmL1OioyJ`gwl#lIOJyoL z?ouT6G*0+jztilPTkCi}Wca*UcsY@OcP;aRtNxo56cP;n@>H|L7s@6_F?Kct@^msX zFjrJI*2MZ$GfikM;!G)-Fe!WPJUixzvla9gTX3&kx1L*V)nZO=j_o@*HX3X)+_rN& zcfbmz{X5ncA31v5WNw7cI*~obS2nD@dTsrMn;UfRY`pUD(c>plf?!_-p!(_%7GLGO z-e<7v%$85*eAXF%?t1Sq@9h!}sbc4#!g2<)a?guKA3y*(eEh9@#m27$}V^4Dk4D@$@m zHD_r71M}3pg^L^(GP7wIudwFcw0R4++WHkhukG2(vCU+=>F#}dxP#{_AKAO9=A`u2 zEoX$fY?LnE*d}~X;pRQ9dz%a&KY98L;w=$WZ|%Y2E$oryvM8`+i>!pd`W3blvcfyk zOQhDSO_OIeyZ!psKIKB8aNB0vSEgHg)B0E$4~BH9SKOCPiePN14sHQPQ)wAbMO6TM zV1HLb0cUb{S5M}QnRd+G(-idQS#Ymdxr$qD={%rkHf`ouW3bk6P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)Rspt^Ss7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RYeOnmo8yaJ3+vECsdJBtKCQq5_Fnva8)2unR zTE=shF48qMF_U_vcb+8Cw2V)OlmqmdsG7@w4KHprS za%V~4irx)>MAlq?SaSPo&19E%FM7VMoSERj@WAB8{GwkEWPe35H zH8Xd2bSC720yu9u5d_$=Fm8+r(H~S07nz7F$wQn*d4^oki28*v_2f-!N;= qT=)4i;}?OPyn4;rb!*r+Zem}(dD}*v?Yne$?O4D6z`>!ID69dawW=-v literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/cold.gif b/images/mood/punquinheads/blue/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..b5ac5fe3bf9dbd8d3f5aa33459b6b0777a368454 GIT binary patch literal 635 zcmZ?wbhEHb)L_tHIKsp5^!)$#2YzkY^5D#w|1)R)PfMG5=;Ob_TR&{qo-sBy{{J5+ zk_IFh$OVf3x&2&2f}I@$T#fV$m>GfQDE?&OWMJT7&;gkVas~tI3kBuAl+1YjKWEFStzw(DI+fe#-Z*mQ zNQAHHP>teG7S0p~4h9{NdXTXUENcZ$damAU@%rrU|8o_+7CH7Mc+3=@ zounajJU{nvcHR4$eDMPb2h$n(`c5!T=rB;5e@byZ!&C!um}8S#+nK913o{reb@)$W?CtB%=nkDT zb5?ETj7EhC3;kJEF6m#kV%6&MWh>YFh&VZJ-MMS`p1o4+2M)6DK6LcJ)?+7ko;<$q z-1!T81;IWDK=r{oLOyu^|Gw;&gHDbX1tLFlYf8W z^9ug5&HG2!rF^x}mmppcLG{8KLSDcT3HGbSelL>aWiAlX3H!(4@hP}gr2rTSyQ1WFWEZaedT;7_ z?|>T3N|5stliNDV^5sC0(CImev8<^X5(#xxEb|vE^k2LrcEYk1-YyO+Hm>s#a&p|V z0~85T?E4R}?>cy7|CXaCcAPl2_w2dzdmtV#LiGT_IKbrrU@GzjrXt6emTq;9tcNzP z5mn_(_m4VVdnmhj^;fIX6);qkku19ch>B> zDtDFz3l{|}U6wF$#ms_c`?ae!fRfQRP%7Fd#eVP*`<}zc4sJVsYS*a~`+;$=Z&)NF FYXD9o%bx%M literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/curious.gif b/images/mood/punquinheads/blue/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..061be62538f6b16cb21186364a1f4af59ec490bc GIT binary patch literal 967 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEOP`-damAU@%rrU{|Op>DVg&!R;`=z za8t12c~+gB#}>T*r1jn*;e7~)RO_-wdg&>zvQ(Zjh%d2Q+_H4_uB(Cz7CMzxmhkOU z{#f{ywfV{$8R_T(x@5YWDRT*jH}cvR-HF4uc)r*6!W6-#`%T-~dzy&&A^4oY(sd z!p@X@l=`vY^^T3_b|)0HX>s&BPcBS%Fe^8^RCGZ&tTZsN@xU3@^~_FUTmD)#KMIsQ z$=7fH`kUd}r+f^I3_|P6S98WNHra$&H8CcZl$KZ8#MRUVH56Glwb{n~x|59mT%EQ0Fd*;rh>CTvf^MK3qo zJLS1+^xyr~4|(X$GOO+A69+dZKA!XPB2~#S(QdQtHQ=v#UDa z1V{-mh`jvfXybE&?Vn|AJ!4gM4ReL1Sx0GALQ!pgT-$_+p0!iLBc`R*I%?_9STtYP z(7<>FFo;*NuUpT)V#DTjI$O5uZr{3Q&)$7d_Zp$P7h96R?p_P$z|P4NCotdjuPW~1 zYFTpDT~=U?f=>C%-+f1pZV~_ExVrOMb{Ww0uCKp;f!!NuUe6d;SX5GG8C_ZJUz=}H oo1+*pA+xq!Rez@aOh>IbGv`my1UeW!N$5h71k}MpD@j-b0O0n)G`(4hUsRHjiCka0F?G$>ZMI6zPJ0d|0IKU(VRe1Y`~MEXPJtRy++B+6CrDV#Z)OP!FELwqU1=S|+p6Uz?>^sB zP+nWp@+5}BDTe-E$)G7UzW6~X&^8Fi`4tlxG>Sy`l{q~vC;|Has z_6JVCs0pphtO7bbw5_AING~g!abj@pM8?|Y7Ur(tB)8c!TB;hS_Zsvs@?%-GG;_J{ zs=_r1%QtLv=5ln{zI)H!eKza|53z4QeC*%>VA!8JvH$#qi-B7BRo5wgMtY8XbLt8s@Z&<45yxHxwEwd&VOj;VqvUWwzs(`g6 n>yuY)-s0}+>$q2i{lLM4wug=$vOIS3_=!^o_5mFZ3~_4!^%=;F literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/dirty.gif b/images/mood/punquinheads/blue/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef4903f6b45aee8ebe98400837da4a42324b8b78 GIT binary patch literal 1206 zcmZ?wbhEHb)L_tHSj5V(`pC`BRY%g&W~Qa3853>5!!`?-b$J39ur8tEA@ zGXez_f3k3V^x3@^Z{EIp|AB`S?8^XDUtU7^^7Yx>|HT!B&U$F6 zPmj{}*!t?ki50sJq{^k~+Fj>sEYO(ogKOn9fde^AErRp&U#_w1-o2po^bsa~CiO(? zysC-oU1wOX+P2%?(@P*@-`hoL2de*EI-25F9m!fB6Vt4dRT@^_l%Cnz!#IT@bsEEz z$rA*;rp}s?Gjo1t#$3nJ1z`)8E?dr1($nrUCB4>Qz&!oLmf?3_2jiAY&O=b{d@YT)o%g_1WEKaTStFGW;H_^h((^ z@7?LGo5ZhI=!w?EzYx8b;34y&;n1Q>KURxQyO3D?RYht+_@gf&vRkIaYfep2Z9MCI zsO+-0$ceC=z_)g3yKE{%Rvo+lureaUtG1y&rIDF|ks(euyt|jVwL>a5KZS8tU;He_ z$tAgp`CUEEi4!MhE6u1bF43P+<;}8nbg7|nZr?d6h|M?a;l44A+X3`V+=I+XE2Xx*i#n$6bH5_!P0hsU-Hinn zH~yBeE(*%nqdNV9(%Y3L4r}eiOHZttv}rk0;!V{}90`K`HL?pX%f2$Ra`ARfO538d z<*<2DatP2H%sMK}Ep=+y&Wsb zT$zeTJ&?e}i$m@;kpjIidp^X9uYmmAqE^IGO^wQ|{-MIm-;9ky-Xv2&Lk``&%*JNF;j zyY29??Z=MnK7HowIjqi~0(U;~Q6Sm+E9T0oPgPn1TLPHEpIrUakrZm_wRG9;__8~; zd~4UX=*P}oKd-g2w5%|pp{cngsxi2-)2p{#&APY0abi|n?}X{Ww!ZEQ7A{)6M2>y= z3iib-*DPPKcEiFA>y~Z>Iv=Y;r@sBsWziIKN4a-5{jMb@g;Z7wpOs5~dTzk;Vu!u+I-MJSFXPjDAG4uP5 zKWEQW?60YEDrRYrO092dwM$j3EX;~%oiK6If)(z7n2*fuV1!KP5$Jz+P1$pZo@~Pn$^bf z1=cy{GhZ^ZWNO7XG?vR&mNa#AHWelHSlIMu^z_zM_D=^E8MbplsbHxT`-+w9i&w2( zF?Zd@g&Wr|1EzwdSY5gV?o#5zR@20#(@uP9X=)aybKdj`rlJQDRr@`{=B^LP`W+&$ z`r@ZeE6%a9F!-<}ROab~F?Kj-J2h2Rt2os)1QzEt#X9!}H)RCO>B~!>p3}R)(0a~F zUw0u}n>8CYZrZ#>ihcVI_DwtYY+tkYz=i|+wgL;lEm$2+Mp>tu*$_6}F1&H+6Rpk5 znGRa3@N+)6&}XotY@@H~EZL)cmt{82$WXJps8q$m$dIcO%Ft5I%+k=9)Z7-sIHj&o zEva>qQ|BzFKCKC*F1-~qdP@RUEK8iQa{kgaQR`M@Z1S_6?hY>NWI$!zK44k5`^4!z Lkh1QwAcHjkR_6{+ literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/embarrassed.gif b/images/mood/punquinheads/blue/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..5dcc439d0c75177d0aa0d45667cf592c695f1dd9 GIT binary patch literal 960 zcmZ?wbhEHb)L_tHSj5h7=FI<@GykWh&3r!l@con}#>U2JX=(re|5yCa?dKX2?Ccoe zYNTht%*epNp!k!8GlhYjK?leNYSv(2U|vwM>&`!eQ=Y5$TD(5H`+tH)-x8HMD+09C zAM86|xvfBU_56hQdgorQKjio0Q)WX$)23xA$Lbm%2wkgT?Gbl0v1o}kkDB+R`VQZ@ zby^Q>3MLvqWK6Ux5PMQ`KzcFn1I|*%dS=Gzn!4f!)8@AJx(u_N)`)`EXzOWH+-s-j zO`c^xXIl6IOHCu~m8({-S;e+~1KY}tTh^;=-J!Z;+uFVR_N#J&9UXw`=!F=LPRX37 zp|WO8!8!*W=GPqOE#B5Sy*qC0=O6Y#G}ZB}KtRT$S?;q897@hD*yQj@X@O9$@!Ms; zwY#U@YqV-(UBSMwxXni42Kz;)zkCytcQID8RJb%TGuG8NmNi?nb#^soTjqB}7k9+j z&7AJlFspFdT&MXnqZZrfnrg1$0Xlkv>c%Y_6}Rr#wteUNwfpuTfVx@))z$MbT#YrT zZRYtivxxL;eZ28I_ns-9OSBF4aLhS>w% z42FgRJA_~O*D=?`#?=JPD*QT50w8(|mIM(#Ys!unaZlpA8`rK9pO%3hkD^{*r z$+mVK+w%3B)~amYrn+s*>fL+xLY-_xmXp^V^5giN+0dGz>-pv{lcQ=6C%1$?Q$|6= z=DbaNHhf-le}&!5%1;kRIgQhG9LX>A>IdwC&eYg<=|Mp=G!|Afv-B~vn3S*F#`WM-Ki zH@9s1#InVi%R1JTuAVcmL#tzB%Vq{fhR)@?_AFWwK6f7DvAt!-7#D5d!MuOng|j<0 zuitR_%GGTwH|89zkO%_!ujLRw@-f=o-=+~ zzJ9^MW{$!Zh>ruP>Eo!9IQQ%2C(a(oo1+)6&Y^Q&Uk= ztI^g!VN&0eI?cL?Ku>qin!K2qWnSEZ$-RB8%QIK4*|cm$_{OPAYu3+S$PD!M+R6J5 zZrQ-Hknz-^+Ea|ncJJADV9k+ZSqt`V-gWW#iOnbO-ne<|&ho8!r4L_sG^&)Bz5A5O d{`K3p&z#?Xe{cNr|L-5hHPgX9z6$iQH2~0g466VD literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/excited.gif b/images/mood/punquinheads/blue/excited.gif new file mode 100644 index 0000000000000000000000000000000000000000..20848840fbadf1fff3cf4a7e61a5872c69d700dd GIT binary patch literal 970 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEb|0TdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMWLyG?K+x|L^3v2#5OV3*40N=o5hxt)h2Z1<+F4aO`BpnbCQ3< ztT}Vt=g*8^u#*E&ojeDNlXG70 zGYC6V^6{MWI{wdH?;Ym74dIX~b`Afsx^B&vpJ63aK%SE!CF3EsXUIjWM6)4tt`=oqw|>3uhRqu^w`||KZO6Jbd-v^!I#`6TgRzIP%c8&*8HqW2 zpKq>Exw9m2Mel|`B5STcEV=!)X0pq>7d_ur&P;G%cwlm4e$lT7vcIC38%oQW8yKr= zYQrkcnwh&hIumkPCQO`^Hzn1lZhCvnEcZE6W-b7Q@XA%I*Q{b+zkz+_#x3i0w(ii~ Tv288F!A7VK9!(TfP88Mv!yBwe literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/flirty.gif b/images/mood/punquinheads/blue/flirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..e33eebf73282bc5e32a1e1945c6513ca7c7ab5d5 GIT binary patch literal 1117 zcmZ?wbhEHb)L_tH*v!dr=FI<@GykWh&3wJ)^7F?1_fwV}b!;;>Hcm@R`~Uwx0|rq1 z&+X?L671|4;A*62z|06#p!k!8GlhYZK?kH5WGn;APJ@%4t94ZqPw!sO7A6s&>8DsZ z?>5`I?2eTMy?teUuWH`^KcL|5pu^Q7s+4e&MPTBoWmhWya4x%%I<-7iZbSStv+Jxf z=PniBILTXa(bv@2ppElRT*2gZyVL*Iq*O4sM6@t_H=5Nkv-B}%v-kEhbeWbjPG*@9 zH;b8Z+Vq)yv(qx>EnGCSHMo62Y4?JPh)o+(W^C?Uzb$6Rrjk8jZvGxej~zd8(tzX4 zS&kFuE}l7h>FTkomrvcgedn$qHs9<4`X*KL<+ZcB&BGHbQg${jUO7v1X=ZjzW4QMH z7i;~$z59P)L4k*kRKG}Lk*0&%l!g@|3v`^8M`RgmoTyqH9UorxVcOEfyAlN%$+y#2 zSvZvWKfL5%rM6)5+2AVc+W6L{tUBhdxGv_vcJmfymMP4I?31T5OfaftoXIjRWdSqe zoVoL-EX>JUvV6t-?#SL{)f1Q1#qHRZHE(DC);&r4c2pgT@d@=iEz5E4{CW2amoGS9 zxqkK9jdN%2-n;(*;vo@gM$e|Rx$C$sW-PtGewy@$d9yRq9C(Dc?2Y(Zv~F|r=9=Vk zaP(A{XoI7t3KTt!W@RYRlbQ~To-WfF3)@};g>hI*Tb>D6eAvf29;OLPDMbB|y b^c=i&^(Z8IPC|TRG^~7smUV`9VzUMS$>{DC literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/freakingout.gif b/images/mood/punquinheads/blue/freakingout.gif new file mode 100644 index 0000000000000000000000000000000000000000..a00c63d8cf6ae0475e88a28767542188b613796d GIT binary patch literal 1903 zcmZ?wbhEHb)L_tHSj5io{=l!N=l{=~`9Cc!&DhvDEp6tRGyj1=@jthpYe=xOV}PrX zo&hr>0|SHNPZmxi26hG=ARDMzgMoqha>cGY{|rufYDcO(F5bB=pu9Kknx^`R4%JhM zD_H}ln@N>xrFQr_iuPQcwLj%! z_@fw)^EZ30a;)3)G_5IU|3A;4HHFp1=B#lImCbBSrCM!;jZqcdy$byWGp5*0ubdp! zGdqrvfsxI$YVp!pwr!yd>zA3bt!L<7u#jzKb;Yjj3*%;bB~3M2dmue&pM&$sw37j@ zZYM8axR~dE_1dl5ckbSEWq$aG`TpZ)5AQsGb@$ba`|m$|{3OJQ&7YTu^yh*Pff`cW z&PfLkw3#Js#;&b(M>C#RyjdzC&gxioC&rldZMpLADW{H> zWR+9|`R3N8u@}bll*e_~@)Q>J*Qcb0v~)2|;j5bM1N3H;DchnYY_qz;g(tHyY+S0g zVbh#;qwW8nw&rO(awEAFNz0e8Uu=?uSmK^)!w&u9zW~Ri-sJia>8n%AB z&XU#Y>`AZ(-ZBbJzUY{%PwD9?D8P zFf;$esUl~OQ58)i-i|3Y+f0# znPKfZ^WN24+4k<*%`{$sEnj%Nf(^ogRd)N8i7G}P8|Gw{o#}8bd zJb(J^#l1Ukfl-M)!H#B3)Bvb8XqYuqK)!_L%`Gd{ z*tRgNTW{XGrZso}p1q*VdHBfD<3~?s&p5UllsV5{-w4W_cZGqa>_gv2PanBFd-?pu Ls|WX>wTU$VG6;!_ literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/full.gif b/images/mood/punquinheads/blue/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..968495def231a1968e6a063222a3b72dc04b3d09 GIT binary patch literal 1049 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEb9bLdamAU@%rrU{|Op>DVg&!R;|+s z+f#5y%sKb|(O>s!{?6Jk@4|QPi)|j!?}8P+@HlDoZ+K!dpKYb?>aBrm{c_3=h}M~2 zUvVp@v~}_asfTa+ZnJ;!F0Nx{VQ{Kzu&u1hG-d2G4G8LF%t@%N?~XKWnjqa?-qKo? zKij-GSF(CR@$$J#RxI~eWTarIUo&U1diCl>#v9k`?v-LcaFBi9p`!8+=Aj23o=%&@F+H1(z&6rc9p}Ll^Y#480qelWP>teG7ETcc4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yg4oKC;>@wxp~!0p#M&qG?lXXHN2Om^Ejv`}~>liyRHDj90H&yKW8p#!c+2 zH*edhvwfHDt{v<5A2^8J$)iEcuxJ2+IOp{~gRnCtAI~|jxS74d(E9XYoUv&t>G#W_O8{_jUUT!dEnBy*U5zsp z&&QIAak)1z-N3BW^I}oL3Z~Wm^ClhG@@|8b)0f}}Msuw{uBgdbz4Tex2iYWk21W+a z+ecormnfvhFt%1Fv@$j{HpSFgCX`n;B=;5;vGkPAobE7ZYEbjs`3t-j%}H7ca`QS7 zU@G3EyLsDY&F#B(?A*O^{egpruqWd=G;#CSp6mQCKu&I{w)AabtZ!(Hscnzz?*X}Z z@|39#(`S@6&6;DYWjtr;B3)Ax!_}g|l48B?hRqu^w`||KZO6Jbd-v_f?%+Wm$kqTq CN|D|G literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/gloomy.gif b/images/mood/punquinheads/blue/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..942da66c1934effb90e1a1c2ed05f4c694212027 GIT binary patch literal 971 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEOP};damAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7o6TIEFOv9Feg&}a0to?-MBaw_vm1bT|jJ0+3k=4$3Ke z89&>7?(|s;9SyCFSFK*Nb~XEkjqIy7ZQY==ZKv+e?d$gKKcFiJc5wizi|1i+an9>~ z24QDPKAv-4$N#zOy~Dh>AskZ0&Ow3c24+l1b}!rY$ZGL~6+vt|S} zPwh#X=e1zg+$AoiwuWm(fG*ysyJ_nt&22lk@7T3r-Tngyp-vV-b@FU1PR1U{E{g(N zWF+S7eZILu<<6486}=n&h^)E(u;ljFn#nHjUc52h(VnFyA;6Hau;jOb+^;C+hI0P~ z#_F2duuA8y_Kt*%wp4|>emj=wlWM2fPLG+HJ!S4ZV-7=uB`a30TCKyrZaw>w4V%}k c-Lge@`_?sk_U_Y!1hEmSdq)!mwG)Lk0Q)(po&W#< literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/groggy.gif b/images/mood/punquinheads/blue/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..b076eecf9580cdfba7a28e92bcb2fe6c53cd5e0c GIT binary patch literal 508 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEC&TndTLvlz20m1|3OJYaz>Hd)OpXU z_D(u|Xs*@mqOH+i8E)< zoxgBV-u}uZ@hdkxl5XC-c*pzN!$*&wNDG2|#TtO>s{=q^t=?;qU6OPE!PQz}$-HHn zE7gy!J1(*PruWSfo!gpk7pnHXpZ57{+j2pn&SbK#x!FDd) zj`NY9F7>#rZhzD0C^zr?dCTX{T+rFHxF>4y)@|E+cZCHlZrQnOcYpJtL$Pt9 gA;D)Z_*h-`y>#Vz-1S?R&)l}U_yFjuI6($$04v+y=l}o! literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/grossedout.gif b/images/mood/punquinheads/blue/grossedout.gif new file mode 100644 index 0000000000000000000000000000000000000000..1610b41103da8d837d3a9bca806999d8e8368ab0 GIT binary patch literal 977 zcmZ?wbhEHb)L_tH*v!fBf99E|=l{Py@N3JK2WQUwpE>h?TG~uwW8<{6wEzGAGhhJ4 z|J;7AA;Hd$0j@@R2F#2=1&TjeI8zun8FWC3LB=w$%rQ9Wxq7d~>$AK6CusDgWX{W2 zwQfz?o(&hh^b_wN*?p~I{%Q5*{0!zvE!z(VR2p|pXldS}p8Bk>^@&LMUeP)7&SpE0 z)Ve1v`t?U9c(-kthA#&PQ{XyT{|U`UBAJ>hEt;5W>*^z`oqIaF^0GP-idm;+Pn+W3 zFtHO7@&lu} z)*n~YyYPH8eKG)VcNd^cLoJCzr9#%$qqq zsCi0v(p<0kGv_RJF|{>ZBLZ~r2HlNYHfnC&v2FX#^=tR-KLB;H2&#+cV{tL|Aa+?4 z*rFmcXYcdP6*_m81g==S;g7_c>kmtAf32D9^6teO>mA3F-b$9RFaNyt}sGE&Y-MolsHF(RJ N`S6jWLo#t#0|5UouUP;9 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/grumpy.gif b/images/mood/punquinheads/blue/grumpy.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4267e96a75f919f5f7244726e979724746811a5 GIT binary patch literal 1344 zcmbu;+fSNz7{KwDy)QxZVu@XoE?d@V+(v5CHF~j{ElYH>?YuB9_G)2E-53`n;#RR0 zImkhvFMjR8TzNit|vShPI3Ih(xPfXH^vBps*KqV5*Z?q=yJJob8};{7?9j##L|ijZ12U$4yL*lC;Y^GT+ny)bY5_os%%D0!w zw%?}ZXShl}TNLs;-F2jyhhOU`-(-FcFFunm{djfahn$ODWc%7jg=NJbJJ%l-eDBzO zGyQgTRwbRr81@-8=LLj)G)NY8)gzM&QQrC$@)0T{@Ht*0@l%(J|cwYyy9O_S`<~p2E+pNT5wmr?+XdcT44c z^*1A{hUyF8F`;lc5Q#=8Q7m-sr<11N!h>oj^bdG!CJ7E2SQYeh6Z*c?yY z)~ZaT7D!b{bj) z4*fgU)&_T&`My=LM`P2gm}n}NQ*)Pon=gdxsdeNAFq^HAR-hpv(wPd$2r8OHPt)FO zhYetFxvmd3k<5q}9<&=f@v3%|Q=oC8j04v85rLdK`_%QwGUIsuf&(ot^#8gzqg`$D zEU#?vC=BM#>)pM5UmnIEz#OC=Mg056F<;dG^qNsU&dn?M_niL&UP>Mu|JZlVz77_Q zP|gQq;2j!+#bejpLNl@aS`qtaVS~7ld6z5&vw3ZD1l@pBX_=6Mpk_7qvh*z)aX;8s z-h-So$%>%GBV(3sJQ8`TzH2Ie&6@H0RwfeJWSey^{K1Dj%LBiy&g#7#8=m!Tn98B; d6EKHP>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)Rspt^Sf7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RY1>F zZ`0kjW%ceod!f!XLUry?OA~Xj1TST2f*+U^zV=+_f1!{X!`M=7>D$6s-_RIS+aA~7 z(_2`?GI`2Whv_p)n`X_i)iR#5bdfGFJ**Z5rs4Iv8#Zsy+_HV^wjJx%?A^B?7{Jy5 Dt}m%I literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/hopeful.gif b/images/mood/punquinheads/blue/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..281e8a93f914caf30dd9e213c2bd06595315934d GIT binary patch literal 994 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEQDVg&!R;^nT zwx{5tSF7Qj9|WB;~?D>{BN&Sg&RSZVCA+VACZhm5HC_oW?gKV<87 zyHjz~bvJwV#Gk!={5PjnZWl%MT@%T;Q>-Zqqc2`YXb5VNJ*y zAtC$sH-uJGW`>+PiztK6d6!M~)uTg}7S; z)!p;4xEp71SL8gJqPXm1`{uxf^O+WA@szQ%1Tp;V?UKZs3fCi$Gz$V$Irh x>vh;SZDwDwW&5U$J9g;q-nrqx!9&onHbQmt5KSW3oIO~Q$d*mOlnqQF)&Lr(uzmml literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/hot.gif b/images/mood/punquinheads/blue/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..f4a6a9ec6163881ff52fa9a27aa9ad6221b39a69 GIT binary patch literal 1602 zcmd_n>rYb$7{~E*Jm)yd*`|TGX-1rY6Y(}FIAjYT3Oc7#qUg+IUb2ng7* z-P?UmuLsrx%_z{XvyL{*R#h3>+pS!#H7txf`P`u|3FuP-o}QjzVPRIQ75E?LY()_R|T4 z%Geg)x+%&K0l)foJ zA;Wm!nCt8BcJ4Z~GGu9H;X21&uVbl zM{0lUnEq_b@})w2&&1#PZKbDM*FF$y+)V_HA0Hph**6fS+&kp4cT0@{!8;6_VxG`z z6O98U-F8F@or>%ZL@qE%$Zu#m8OO{avyWy$I3AssN9DlTe2Rb!U-m{s*}0TbMj4AK z_mk!p(yJt8HZ-?fRS(_5OGTizfs~^KoA0!Unwa-HyZ)%`5G&xGn@=Be)P|>}CM;@T zC<=2YM89plaiKLj2fXS*za3j0ko?+VL#QS=$nHPXLv@5ry4dt9@qz(wIp6nl`Lv@m z7VvBd_nz}d2iGkj#~vsSp&u-C;EPpD+(XHwL|{tgCDB+euI_| zVt*!_u%pt_l8__Y5C)cje9cb8VV4rKy==V&X#!3X56%R5GT0>bztLdJ!-#^wc z@@y!`CGPzA)HeH>+1Y6qi`DWBbXpm_rja_opgysv`susYZ`Jq5eP0rpW9TVGwPi)} zPQ7mIEIw0Je7ZF-M9{)J!rbmuet7J#b}~*iIO<)#nSzcHK~-cuYHJO6yPfnWQ0OEA zZ7cBtle#^fgkxrrk!=``L+9jVcp@;F$IU0fd3Yg(FQF6*3Ro;zsr;IhT~1suUf6_2}v9PJvKuR1*SS3BALEFTOYzGdkgEKQ%o) ciJIrkFXn;yc{KcBK_lJHvC9s8PeXt654^zYQUCw| literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/hungry.gif b/images/mood/punquinheads/blue/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..a0f1fe13252fef211459ab1028274d04cae855df GIT binary patch literal 966 zcmZ?wbhEHb)L_tH*v!eWWy^yzXa3Ke`9CdfW>c|NN~plBE*oQGE(_28O)PfwjU0tH13+v*t|tO^_k6vlMWN+JX&SmD9p^7 zx8HltjN*N2w~jol+Wd6Z&cdHF{y6=37@J^QtjNq!(HNJQ6sge05z>`tlNZ6nR9DG3 zUB9BbWcrM{30ZUUr%#n(UA<=Qy7j$stSl^S+qUo6xrJ4E^VXdQw(nNicksaBBU|<# zV>`7+b@i4ryU(j%JavO*weI>g#)}_3(0TZzPWS0E<5#cWyp7d!KK9(df(8G~0x0E9bNsY69J}i}K_7EZtA5wZG&wvo70TUHFsxVElCchO~@? zP>wRQ#)gXcFa_qCz^)3L9Qoo2`Aj`|Ek(1KYG!22GAf=b%erzE(0dTiZP~hQ`zBW9 zjhnac+qzR_&;ES}4{h3egzdyG)s>r0?L4b~{=_wwmAY$J885tdPv`!l8r{cFj9YEz?_m>QcH+YIZAJCbZuq7@3vD?4&06}Lzi#7*aznKyNg1ncq@ zz_<&L2PMl*o40J;z^c4{hyJ!D_4Z9Dq9owP0e8Y+Dr`69MyTY5oZkm)E&8i literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/hungry2.gif b/images/mood/punquinheads/blue/hungry2.gif new file mode 100644 index 0000000000000000000000000000000000000000..70a23641e488a431e4b84161f219959dd09457a4 GIT binary patch literal 1263 zcmciB`%hDM6aetcMHIZ;a={VF#H>hNa8qDwSCIk(3~q={T}`$*67ki+mNCfK!hjKU z4+OM@J}BkYCkUk!xs*pK4_jX4wIWzrpkTEWDKKD%}64I!?U~0&U`*t8_x2yY24crLZVeHiyf($=e5)mcjc&_?%KiDnm+1 zBC4cHQC(3&g6o^44YyGlp{ZTg!fQi<6}skDNFCHOD22M%@PJxVHCi&JG8?<^n(L>z zCd37FX|mao`(kJST$Q$Wtb&fE<%jc6h95cpTDHuZ*EV((debr|MUCWu6zicscI?re z(u**f+TTu%HyzDdq?ei4+l#ghgUmT~#@s1S?R9vY}B*K-JP_ZYvU8 zr&YB;Z9zJ{1nR8qZ)=y0@L@v}I?*+0s+$rSa2)i34Vhyb`@t27TC)N^T6FZ=SBG9a zdp=`=HeRjAZkTSAwr67{-dWy$bX{(>PqkSVE9oon_er$0dHTCCiAOHF$9_JqXTKfp zCg0?V^YVM6^VU{%;scRLA|ce~R7>^&a?Z!SBogvZxLla|J$jdi^4CsA))({^A+!~>xIUhC-}a{%M-6% z?JL-Qp!km7Q`*lYhG)AcoskZ50_fZ1XFb8!ziP{C^Z&t!3Cd;>ZWCP7aT|p+L7hE9 zNR7j2TEw_Z!?>Yhc)a#r;oa9Rv-gpyYDfz%3Y%LOLEF6DGPl(Cz^1oPnigKJt=BAA zqv#9*u{#@e-5#d@)}=ZQ_CHS1iX<@wyW-+4=^ywHu=a*uQP>teG7ETcc4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)S@p}Kbt7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RYeOnmo8yaJ3+vECsdJBtKCQq5_Fnva8)2unR zTE=shF48qMF_U_w{-NCc4I2d~XyDSQ9k&&3Q_xa`u zl{-rUSM+Z9BeLfD!;;%yYbLwAd(rc4<;(;Jh6SysUN)D%$mad=+P{vmvZ^|)+>EWu ztfRFpA(y4Ee?s1*RG*ruEip6PXHA+u&(YAzcsVeDSFo>L$G&|1rnNeox9M)%vU>NP Ry-?>4we*1I-oc$7tN~fKrm+A3 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/indescribable.gif b/images/mood/punquinheads/blue/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..db241c62e5575f09b386df55e10d8622b11a0fec GIT binary patch literal 809 zcmZ?wbhEHb)L_tHSj5V3=FI<@GykWh%``SPPD@Ms|NlP&7%2Yd_Hzvhc6JPKHPSO+ zW&{c<{$$}yVPIv@0Vx1!XJBrO*mdWh!70zxdo5m{-Tgm7qi>1IoD~6D>JRoEu-sN4 zyLx`Yd%bfnZRYti^W18aa7-}Ic*o??eaT{jqj_-JRjIWpy<4>lPd@21_A($>__?&|L8?O~ZPk)>-;%%MNyW`e=@4s_rwH=uwsLb($Eg(K2GgFOy z=gVWij-;&=%@bN~Yc+p=(XvXp<4mtgZ_7?U-&ydXwRZl&*U>d8l~s-P?WStFI-0$_ pKvzvvoiufl;+oi#`T%V;RLYA{5hH2{7XQT+e_ literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/index.html b/images/mood/punquinheads/blue/index.html new file mode 100644 index 0000000..86a2ca1 --- /dev/null +++ b/images/mood/punquinheads/blue/index.html @@ -0,0 +1,102 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angelic.gif
angry.gif
artistic.gif
awake.gif
blah.gif
blank.gif
brainy.gif
caffeinated.gif
cheerful.gif
cold.gif
confused.gif
curious.gif
determined.gif
dirty.gif
dizzy.gif
embarrassed.gif
envious.gif
excited.gif
flirty.gif
freakingout.gif
full.gif
giggly.gif
gloomy.gif
groggy.gif
grossedout.gif
grumpy.gif
happy.gif
hopeful.gif
hot.gif
hungry.gif
hungry2.gif
hyper.gif
indescribable.gif
indifferent.gif
lazy.gif
loved.gif
magical.gif
mellow.gif
moody.gif
musical.gif
naughty.gif
nerdy.gif
okay.gif
rockin.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
smart.gif
sneezy.gif
sore.gif
spooky.gif
stressed.gif
stupid.gif
surprised.gif
thirsty.gif
thoughtful.gif
tired.gif
unfocused.gif
working.gif
worried.gif
diff --git a/images/mood/punquinheads/blue/indifferent.gif b/images/mood/punquinheads/blue/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f1a0830ab92fe90fd3e3e62c71fe8e79471ead4 GIT binary patch literal 960 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRwy(bx_=M7#8=M;$t7~c_E6rj{%BmCE^YU5RiY8CAo!0MPH+|+T z_c_zz=Q|o&8LwEmYV}I?b?ezzY}mX`XUlfo?OWIE*}G3y5bWLnRQJxo;@+Is`wYU) zlzcqrypI2K*L#O~Z$mhwik*W3(+$i@Juem|tYBL0KX1~3E$=p1IeiI!U^LhI#mhD@&?O3;F@4o#|2aBLOcm@^+V-H}LMS(3c5_9%G z-&~<`XG!3S-VJ|5)?9yBa{Ft|WS4g@dcLiknc%=+Fy%7)`wQ2lUhw~Btf;ICD>Gy3 zFl%dWNyugC>Fvv#km^%CxhZCv`-}-w=YT?Y>9XZ3ma(s1!@hLwhSfS7x9D!!v~uUJ S-B8CGp*nUnHBd7(SOWlGU8D>E literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/lazy.gif b/images/mood/punquinheads/blue/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd0bdf05e6145c37ec349dac122c0c39ff8af49c GIT binary patch literal 1041 zcmZ?wbhEHb)L_tH*v!H3{=l!N=l^fn^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEUN`hdamAU@%rrU{|Op>DVg&!R;|l< zy>CP4nUcF=&gW8WwDJS+{G43OoCzP3)TcjvPI9MCp` zKW74lenXRES$PFRmt{J07ehw1L`6#vTg=q9Ni~(erL&Fd<~q!m4O~=GyHsxZsuc;L iW(uapr5Ww&YuD{iWoO^A1#9>lQSAQF^h0j?w*~+hlFx+z literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/loved.gif b/images/mood/punquinheads/blue/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ed247c5e4ec15000145b93cdde6a493102b4813 GIT binary patch literal 1115 zcmZ?wbhEHb)L_tH*v!dr=FI<@GykWh&3wJ)^7F?1_fwV}b!;;>Hcm@R`~Uwx0|rq1 z&+X?L671|4;A*62z|06#p!k!8GlhYZK?kH5WGn;APJ@%4t94ZqPw!sO7A6s&>8DsZ z?>5`I?2eTMy?teUuWH`^KcL|5pu^Q7s+4e&MPTBoWmhWya4x%%I<-7iZbSStv+Jxf z=PniBILTXa(bv@2ppElRT*2gZyVL*Iq*O4sM6@t_H=5Nkv-B}%v-kEhbeWbjPG*@9 zH;b8Z+Vq)yv(qx>EnGCSHMo62Y4?JPh)o+(W^C?Uzb$6Rrjk8jZvGxej~zd8(tzX4 zS&kFuE}l7h>FTkomrvcgedn$qHs9<4`X*KL<+ZcB&BGHbQg${jUO7v1X=ZjzW4QMH z7i;~$z59P)L4k*kRKG}Lk*0&%l!g@|3v`^8M`RgmoTyqH9UorxVcOEfyAlN%$+y#2 zSvZvWKfL5%rM6)5+2AVc+W6L{tUBhdxGv_vcJmfymMP4I?31T5OfaftoXIjRWdSqe zoVoL-EX>JUvV6t-?#SL{)f1Q1#qHRZHE(DC);&r4c2pgT@d@=iEz5E4{CW2amoGS9 zxqkK9jdN%2-n;(*;vo^#=-Ey|^qfuGzEkgk!L&&yqw*Rm&8AOhH1OGwmVB|`XV<&4 z$4YA$n42S-nJXKznOS<6E7-ex8R`=m87H#z<;-B7R#iQ{XJ#^c%A6^k(_4bu=Gm1@ zi<`E>)@5_hW`Cz`n|IE4aC7xId;}OhrW~hEa~wN!{?y?MmycY&c;d#*Tel&8F+%mr LXi^(INzEDnpyTaW literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/magical.gif b/images/mood/punquinheads/blue/magical.gif new file mode 100644 index 0000000000000000000000000000000000000000..50ec1f1a79e21515a709ca162e1b7d5c021dd4f9 GIT binary patch literal 1455 zcmZ?wbhEHb)L_tH*v!q46z6#QqTKrfzn-4|Ke4x%fq`M>%>QX=X~xFJX=yXhocRv~ zKtVWA{Lk&@8WQa67~pE8XTZz|lu-Q1!kNOr&7cEP1TvO^z^7=j_mKYtgCjZWlOJ+sAFbgjtS!G>ftIav-51_ zVw%}&6+Dw^(&UJM^a*n^mo8l7IK9cLH9UozL3p!p+8XcHm8(P`9?ZVkY_W2{&))330Hp#^DsCwkkAH#JI= zty>FL+_+l8xhN=O%@d20OSgDDtX<^P5@P*DcSGC@0mraOJFl#7yy>}SbLykYj1N1n zC-z3~Q@y4dCdMG#oE6+&FXYe7(Av{n-5%7*-QC+VAs-klTp3Zb=Wnjg@KxFccPsPN?WU32a?&)$gwL*bj^$LAv7|9+SM_3WqgkA7zdZkCUXXRf`Q zd$?V|*#!~^BB+7z7keP!P6}RXmv=hkE#h)1TXEG)^P1104X=x~TQwIxll;8r`P{0; zrCld4J-u^xGlN=vNkye|HCsvc~h-8Hug`P9+J3v&it0l6)WqySI=*DY2UkV_JQu1M_b!xB}jB#5;r<}?Yt}l z%kA5zL`-tzH$Hyy7@R6LvU5BadHI^-?R(*mZ{B_7{{H!=7&`;AoWQ~UIMzlE#wLvy z{!WM5A6|%4W2cLVZoKTyS6gT(EnAE z?&DKgnk3R7)X>)K(#n<|USHSU1j#AWXL41R*wsuaOiO24G0Q4=1=IWm5d}+xO6RW5 z+_qt(Sm)#|6MA!YrA)4^Ydp|0VNwbM%lY%ijV3f5%AK^khK2Pu%keGCuAIIhb&iGU zq68?%yn7GJF&{-ff93f8Q~39rhrhQgBhvFhIE<;N7Ew`%f{V(lKU3NfA1m9k3P zo+oaJS<|sT#aKyq`Fh^i?V_^}a6d1pFLq|LtF4Gj_VTQCX-sozjd!c+=I)J&nIsgP z9GX%$(|Y0yuHW!`a9gb5+4Je`4C0Z2bTKe+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEDHrrdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq?YF9PZy$%id7c|SI#!-UC5-E`PPW@M*p7vJEu6o?%Gl7rc-{I98#l0R*~+$V+s-XIyY}kt-M#71;Ul_&U{?pAx_S{7 zSLeLmXApL#Z-aE{D8^R$~>>N~BkRjJ_PJMkyk6G!pbfXXjgUt`r6Mw&~ zTO9E^!NzF*(wDDiy(yIM&6y}Iz+kYExu&i-mnDv|qu$cLgE70ZDz2%!X!3-KaphKR zB?_@^P>teG7S0p~4h9{NdXTXUEOP};damAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7o6TIEFOv9Feg&}a0to?-MBaw_vm1bT|jJ0+3k=4$3Ke z89&>7?(|s;9SyCFSFK*Nb~XEkjqIy7ZQY==ZKv+e?d$gKKcFiJc5wizi|1i+an9>~ z24QDPKAv-4$N#zOy~Dh>AskZ0&Ow3c24+l1b}!rY$ZGL~6+vt|S} zPwh#X=e1zg+$AoiwuWm(fG*ysyJ_nt&22lk@7T3r-Tngyp-vV-b@FU1PR1U{E{g(N zWF+S7eZILu<<6486}=n&h^)E(u;ljFn#nHjUc52h(VnFyA;6Hau;jOb+^;C+hI0P~ z#_F2duuA8y_Kt*%wp4|>emj=wlWM2fPLG+HJ!S4ZV-7=uB`a30TCKyrZaw>w4V%}k z-Lge@`_?sk_U_Y!1Tk8oAl|)ZhXXo+iJ~n-|CEj#r>ACLm$HRDYfjP4&wYoEZ274< zujq6Cv(#bEcKC fp@A{Ty{ka(T>*5j&X(;^_d>%L&Ao#?Nmv5_YOJPb literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/musical.gif b/images/mood/punquinheads/blue/musical.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a795f0ffca0d5085d7b3269421b5fdcd30d00e3 GIT binary patch literal 1484 zcmZ?wbhEHb)L_tHIKsv7^!)$#2YzkY^5D#w|1)R)PfMFAFE5{yot>7JW^8Qy|Nnmm z%7Eg3Za>$MU}whwS0gI^ZQyR+Q+J`S`DK|>Zgop#tx~;DX;W)&TSup3cSRLv@3g9dnBqyXQACA5MoWzy;{@dU7Uv3{> zf7g#cAd-JaCg#M3g@@Y(yf;K#Dp=&&E@o_Z#=~&Y@qPv8RUC}q&cjo-k~Nbywa zSh?=atZf^*_bFwaD~Z{+bMN(C(Wj1Y5^Ua@=$9I!1PqN5ueDL(?Q6=acXVy(+)y#+ zLeS>qYZlVB9iFW__BaTYPkhI+$Kb_p_QKNCiYleT`i|O0rDm(jw$6!NJ-r6~HFca5 zXVsM?mQPEX!JO2ww5!apGLdCw;Y}+@?>0mj+ z$>sE(#MQZJOG;E)|qIc2&pr!cxa3Q0h3! z3`-s>81G+>sl3m4<7VW!s}~7pFVv2^yO=ka_*;k2}l+1Y1l^_3e7G;c{3l#ns<_FIy)LPTn{@$-cT-il=%TfSzSF3-6ajMH^= zl`j<>iORCu|FC(tROI&8e=}JfYdKmA+tQniSy?h#>nl5$S-K2+GAEQ}PU-Hgn4dAn zX!?Q$i>A$EU}UK5V_vmp@>GMKUdHWfXKiPkynMy_)pg|?HZ`-%Tbh1+^Wx(tD$bqh z-gN}Z@X_NZPoJr9zI?^`{Pnw+Pu_oe`su^-?>~P2(ozKbFaXtu zr%`=)z9jelr@}c_esXPdIW>+jHrp^?+TkOXeLP*W%G#{{)N7q8jf(xObAx7Gu4I4l z<-ls?0|4;e B_Kg4l literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/nerdy.gif b/images/mood/punquinheads/blue/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c2a87fa02c2d2a59c25b551867f1a4f2bb4ae2f GIT binary patch literal 1159 zcmZ?wbhEHb)L_tHIKsp5^!)$#2YzkY^5D#w|1)R)PfMG5=0A`G0^>7hW*QqC&zza| z|Nnmma)IK1Za>$MU}whwS0gqynXxTJ?a`WOGAq)S z#~&)&o40y#%jeY!>i6%aL{?Pk)g-5sMRk-_8n*@d1q8YEX0W({62OdEQ(AOurZX-{ zid@3T%rbQv^UT>3BG<24(7Jlgj@7^vu*1{A!hZF1k4pF5hKCLx?mtoOcwv#}!Q<)& z%(%JF-n?`7t}*AsORNvMA96l>`rPoI!@c)+IrX2vdinCj^KV~tIX?XReP>teG7S0p~4h9{NdXTXUEVBeodamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRwy(bx_=M7#8_c|X8W^i)4mC-?Ua|^ETaWTUPJhvsYIT?A!oU=g!9B+??0@48qQo zd_3p8j{kGldxv>%LpY?0or40?4a`bCFBT=NU|Q`zZ_1ODeF=VGG}rp$ikh6& zOP`f}kWJ!eU~CXvFMq)?HHNX-($~M4v97)$rlvKnue+zPh-K2`DGt-7mp0CvZL4KG zd&xpwQxn5gqCn@a(_O!5z2@d^TefaryL!*weNgv`pt^S^7WZNgUYA9IEiw{w_CDWS zp>k(Q;ELW2e?-hYbu_dxUIq-_O*e{!dGrnURL52QTOIKE_3zzU(Hz|^L!T0Mad zjU6X+V@wlTl~&39-WF=Cxi(JuHCK6m)jWj{r3?+Zb~PgPrEJYyU8Nk=Y3-eCy_2W* z+a%10XP?$EWh(pZSs8so9CJInr*bV?zN~%aj1}Emv)0XN**JIe%5BX%R_w{B+QP-e z$kemy#HqE5t3=wCv(II`embk`I^)_MhL^7#KY43P*4gtDYUk|Re|5IJZ;kJjtJ|*L zS5GaRxct!DdoBkrr>pr{)c+82V@_Y1u%Bm^lF-fX0i4d-VwC|g(*v1Zdt^0jrx+$& zU~cDj*wMgb`ADVRsnBE7o`;`QRO*a_ulQ*8d!Cr@(9CsKf)N~g0hpnu?R)ao+46S_ z+G~Z7#lC>?*16o?TZ|iaD_pyN>df8gxfd=?ZkT`Y(2aT0f%Spc zZ|uDBNG79X%Brq|+~HYq`%Owtu--X7;g*Fi2V>X^7sC$wPR|#rB8^Eb6T07Nij~Mz zE&Hwp1&adzOE)jr)o(N{>(KzijcY+gM zDI3?siiwjeZ4-KgIM^plYM5HeJ}bVeu6y>}dCk+f7SCSMzG~K-u5Ih%H%rc$yJZzH z@$H$uyJ{;a?B-`pJb8NEl9_UCE9WxaI5YnS9Qg>}c=npc{V_`{TfAZ!0wI8PPrTMsx0H&Shk< F1^_54@&Et; literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/sad.gif b/images/mood/punquinheads/blue/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..3813d999d402b58a8b5fee7496caeffa931b4f4c GIT binary patch literal 1133 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 F1^`mUU|0YE literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/smart.gif b/images/mood/punquinheads/blue/smart.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2ff08b3be5a349406e6c2376ddb1a93a16b56cb GIT binary patch literal 1608 zcmZ?wbhEHb)L_tHIKs>D^!)$#2Y&rO!|?zA|1Db{oSDgR=FFLyGygL%Fr=l;OiN2M zHa0$U1}F&=k{|A33hf2a5d61U}gjwq4<-9GlhYdK?h_U$QcZ*{}Yt^QZnad ztXh}zdS8Lg`436=E7rY!EA;okf&z({9c4$9`mcRZ?NvGGzE_agDsIr8zOdpsZ|{GqcT)y({!B*X=ukW2`y!W|g zTHTWGC%^1nQN%gdJpSjGw~MbIciGm=l`8Nh_|a5Xsn}nJg@OH#-1I{1x@0srcF9aq z@ey9d(^<6Cdx}!brWVi5%g)YLa)yLc0RC_)$-Q53Pp9Vne}{x@K~1Ut6Hf{sa%oLJ zB=zy63TIf?8YR&uGuLSyO-Q&gYuTw+95Qm#z3rBqKP8my*~!u@c<1@`(!4a@s_M4( z4o;;U&9eNKcJ7YqNo`#{z`*LCFvX_Bb{Z4w4E0%Qoa}82C(f^CU%XVkvTNnU$u;d8 zn3(D{TX`y1?Kr~2UO8?5;X_A{9N%{E)T%R}z}h+G>h<-9E^BRRVPD1g^ybc|jK_|* z?3+1f+qD}t>pmUp(w+6;@!7V=KN`(=y^fy0xnDfWVym?Infvw)KUrpeIQC&-PfN4c zg$*H-g2bz}3 zxXYWTPp@QRouEDml$vJEoKeO;cRnyREpD2H z>`V5P0mEp;jLTOK?75(|uKqj^^>JsP;#=!Y=H!n5&Z&cG~W&Hd}j>+j7P%4 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/sneezy.gif b/images/mood/punquinheads/blue/sneezy.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6e8a4d76f047101f877cd0534f4700c5c9abffa GIT binary patch literal 1000 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^1#^Gc;?LiX&^B3%$ff{z<>=X{^#~{4GDI3 z3~)8lGhk)}s!{yO!kNOr!Jq?D4>Fd4WwyXc&((V^UZ36lKS84}C39ZJs&#A9_H4N5 z^*-_b@!i)d=ATw?&d*?;)Uy3xK&5flg!aZQ>Z#BATAql6?-iUQ?`*d7NUeL)qF;Yx zR@c4>_ysh5(UV_)1=u?`Gd5P3c{MWD)Ye5-wM6%HcID->Oqe*ycFNSE`sp*RwDe~# zny+hUV7y}Gs@1Dl*R5w=v0?K%oh{pSw{KmuXYW2;L9lxRP~AHRi+gik?=wg{v*qJC z_jU50yWTs@dz-=`RqPxTXl`Iu>Ur^#!3w6;{_`ds*z#_JmD88x2S#(PKdz|BS-tdG z*$3Gqc?L#?uRYi0Unr!;Ft$`%`nE9EH#El7w#W7N^cEJeOrA2;Vfu{Hrde}rwT$O1 zU8HMjVz^oq=-&0Z8#Zsy+_HV^wjJx%?A^B?>R=I62hYXgUAXDwR{a`T$C>(;Mh-L#o?&6e$(baw34-Mw?efrE#jZZ<*<<=x0` z_HqsldY-X#$;vn#q2u|s=hm%#U-SOIcymDpgHlWTl1~b66sHHIT}iyz59X;)&MWCvxxuz literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/sore.gif b/images/mood/punquinheads/blue/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..934f84dc4934b568846d1676308562971fa68f10 GIT binary patch literal 1358 zcmZ?wbhEHb)L_tHIKs{F^!)!VTOOP_^MB^d|7mG6kA#H$|NsB>lqoBel#Gpy)6&v_ zTm}k&;(u;G*N|Xm#{gF&Jp*P&pizoHSvXS|xEXXn#)6!|!20lkQeR5uyo^=ra$fJt zS2}ORqwcj%!YgTi#{z>N$*lY*RD=S36sKHJ-K;63#eE}3QBy~0o9CN=j!?hE_$3mK z8M`?Tep*;iR(n0Su}(kZ`14ZT@*I|$wyL@$GpE+}zS`LC-YU+%snrF(la1Tvbj)I| zp0~)TnwiCwW#OV}HOp77?(bV~ziQgj_AO@Hm>BjkO+T=AKhrLQRSWkq9GY_YH1o0J zCy%t9I=W)P#!W{r?!IuV?f#7r?%ewiFXTQ^eRluR1{{G8Q z{D9lTK;E(Ow~$uMi2zp)u&)D9ef#= zHQF#|b?+|2JxmNonC2cke3a>c!G`5W7*5POd6D_d+4HA*E}UMsZ2OMW*AHHM(DU@3 zS@F~7*NQ`4KYj5sguArl>rZ{hKMp_tGW`9@;SuoQKoi#&&6pD#9(D_Wy)A<3?R&`H zrcq?~_W@&?lWAtn%-OZmnXBivEv|w@cHcZEU~Erm-(bILtx?}rv+Ya_`)94$&#-L8 zHs*zg4_3`Qb>i6ZeFxglT{ymJ^Z5|&RVSvL*d3DlpzT5KZPmvQo?UyPlArhP)8{Y1 t$X2oX_2buH%dh{KZgKzMpMS8KLwFSjBiPGEs9qi+=^M@0BO!fT0{}#1V#fdg literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/spooky.gif b/images/mood/punquinheads/blue/spooky.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab806f5e1757e03a49500a06a783eed19a7ce200 GIT binary patch literal 1867 zcmZ?wbhEHb)L_tH*v!k2ZpQTK3%{|ku|*`SR5wFLCQr5nlY6R!Wfa?nSmtCCrcVtl zX=!Qy|NmzI1I7Q`ey$}8CcG2IO(~1uf^-L zyZR2@0N`yy~^TAR>emkn#Vy-RYB?|8?zIpUmqphQ2{qN6)JbmsXj-gL0VZg%)e zzs9Xq8&8UD*L+~L@M&I!i5|Pi^H%A9G3_tj9r!)7-dea!zJjYNw9>7DT?$K< z?pr^B^Z0@CLlajwoXk0N{KR=v5BK03H*ej(qrh|j0nhD+PwwA%`r_t`XLsMed;dXj zWOz^mH3m;3$6#Md=DZBoCD$IvX?gEFVj#HM=6cY&_uKB}J3anc*R>?bFh@nav(;qQ z6x-!N8QZFYGBzgYZhq3rwddl?pVo3y&ojDKF;4fst!Ql{F#X-*K+X#JDz2LFYR|@I zxiZdlE{4bwPqwJ0yvE4l#O|31bK)~+C>8ZHtXR2fWx$f9fxtLiQL}jy!#tH`C7ZVG zowT+`VcGHn8z*s|JXCpP^4g};c}Gs3x~S&u<$Ft#=kC3G_V*v%*L?i!$6 zJ%91?)d)$OXr;?>|a1^^DUWaj_? literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/stressed.gif b/images/mood/punquinheads/blue/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ad750176fc9cc34de06375aa29735d690054ee1 GIT binary patch literal 2530 zcmb`IdsJHY0mr$yw3sbx^K_5ePG)W4C?!ZWAtsBBZ;h`>4JKmHgJ`P62Z$hOL;(>* z@%=(nOoBpGB0iG&LhudI#6)eX#$;QPos(sWtzEV*J?v6*PMg+kZMXaPJ@?$t`Fww$ zpMRj=K|&k~hJxwsVE5;&PYhr5^xU;rtaWu(8m$hG$J1yutJMnI>Ooq68tO}o^!^~+ z*X_OiAOO9C{0Dry8_W*oYJ1=ISr}Zub2?Bvbnwx&0V@SnLOr8Q(sW*m8ce$p^n|iz z8dzjEnbrBJNnp9)fGM1Vm&n0_o_7--9M%Q$<%&OO4&>ub@wfG_IfoukuD*H#ULQa; z-<$P(wnLrGWu4;MQ?oo^04(CeAh85wWgK$I2Z0(Xr3R3fA(KixC}4}S37*4jQ57^ch+_kY=3yYXtUvd28We(GKIkJ7Z zeZr_6%#_i;yDvq5@U+sNPSS_)yxzQ*xOaCGSTiI^ z?T|n&>*+ld;*@5N{B+|0bIAO-7$u0-?yUbm`F@Mt$vABeo z|9E+EZe{KI+Ul)8-GA_Klk30x`H@`C$TP{A^?s;xchYc|e``$c<Ashc2@ zVzAJW2>Fqv*8t@el}F`i3`kGGIq2`j!D^8Ph3N?EAY+Lg8Z8>)7_s?rwD~bYenu>F zhD|?9n;fW@{cN?flt;t+qb$tzS?|u*Ka)K1Qa&cy{fgoJyNJa79+`nRGAM1^v|-9Z z5A@F3#W$n;12SB0ww(CON|p1OjT2JRuS=hNaad#3JUkKS#fih`Ix-=+a$)N0>`|x!-VQgrX?f@u;Rb81ZS^zgUB+ut~tP~W+Wag04OKF_Q zlJcCGQxXV`>Yt!&mhs}lKtS7)uLWc!A9s=Llu~rr)h*Z5p5);GP^K~7nR%e`kFwW)h z`&i>IxA5~~XM11XneMwC_%}WCQAG$GexVq8sAs>uaz3I>rhC5k($YQV^5?t?pR))L z!asLBZK=PgeV>2U3wBp9`8f|{WU(l0coZPX$ps}qet}3B<(HV}Ap>g}cBiZCQ|RKP z1L9y+vY3*gMq#x_w3%p~R-e#|>%k8Vj~MU>(->lCe9GiHZNXS(MxhRT@0fi9BG^cj zSqZlVHRu(AU$dLPr~P)1=y_UrRO2hCJr%;BRMAr`FM-t`L$-IFC`*O6&+1=2mA)R4 z({5pi?YL*@M|1g%Bcc40kP46*FDnIeBaeBX41k9NN_iQm1gfg*_a)XQR}kr!MD6x@ z(vv(7MQ!2LH^{wS3XwC`AiOg0j>%vUyW;eCTg))Fm|cfr=DM=Buy)%Pvlm?7idolx zl=DAuN&jY}LS}9f6&8U4$3&n)A_XgeQh8apj7V2DC?E{Ds`b2=x=l#d)TbXqV=whF zFgPFlAS7oHVKgB|$0o;Jrpy?#(ExGbw+wRU77X7nWaWmQzv>Ph+lajD*66w3#!Jx> zdbWGoy*9jSeTI1u0f!M2bMwGdZZ?evj{#(SLWm3yii*TBfhh%k4Ot1b_MF{K^fOuP zBX2d){G{q2tygC|8sFL9SDRx7a^iW6`{f}{2aTW!Pg2OJdWJ)+Oxs?pS{=N zMB={1jvmmLZiI&9I{1@MCuJNfAhW$d0>0me!P*oA4RX|<6a$kxf zttLb#?XVY$3i<7d;(<5fuSlAQ&W((+OwRabvvCUL-iMpFLo6&VVwOHxLNDK0SzTMW z`SrZM#kJMh|Nn9QCXWG8A+x_CDlP$w98-XrQbKeMbiq^+%R*F5&8PVU_=SsVZ;e(G m-=SprqVZi<*%)_!+{hkiUM9@gP>teG7S0p~4h9{NdXTXUENcW#damAU@%rrU|8o_+7CH7Mc+3=@ zounajJU{nvcHR4$eDMPb2h$n(`c5!T=rB;5e@byZ!&GKyX^q;XLVZyQ%-YyO+Hm>s#a&p|VW9P2jd!*R+A7I~g@W}oxM^EfHacu9| zbLaO6f;|v`>VXY}Jn;Vifdw0aG^DtlT?!B6@O2$nTKvo96W0};%UOrbcq0oY|Ng}1 z75rtJ_m8ei`D%@SG`H+ee7+~``mgV)<$kJ#RV8w@AYUZKcQX{V%a-LbPLG@p^hHBs zS5M@GIg>l))>X}`ncEbyW~qYfn&9;tQm3w&8{q8j=DA;z{m|jVPDhR(u{&}4P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRwy(bx_=M7#8=M;$t7~c_E6rj{%BmCE^YU5RiY8CAo!0MPH+|+T z_c_zz=Q|o&8LwEmYV}I?b?ezzY}mX`XUlfo?OWIE*}G3y5bWLnRQJxo;@+Is`wYU) zlzcqrypI2K*L#O~Z$mhwik*W3(+$i@Juem|tYBL0KX1~3E$=p1IeiI!U^LhI#mhD@&?O3;F@4o#|2aBLOcm@^+V-H}LMS(3c5_9%G z-&~<`XG!3S-VJ|5)?9yBa{Ft|WS4g@dcLiknc%=+Fy%7)`wQ2lUhw~Btf;ICD>Gy3 zFl%dWNyugC>Fvv#km^%CxhZCv`-}-w=YT?Y>9XZ3ma(s1!@hLwhSfS7x9D!!v~uUJ z-B8CGp*nUo!m$q;J5(~JE&aK0@vD7_vk#Tz9(G+PzI`hHfd>lLo&U6)P+TA8Vbyp# z+&H5ktU2&%Nx}=I-PadRarnx0(9!8zutM-!r>(31t~tH+-FnGN^NZ{Zj0`aep^eSV zwFSF2zKdLbbtvZal= zL7^~%abkPUL`GncXLPydG`IHT&#bLunbEj(vCoQyas4Y-uL)bXB5z}WgQwFj3HH7F Z_F3;gwBP*ju_H&1@7)b_|9L?MYXGYxxtag~ literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/thirsty.gif b/images/mood/punquinheads/blue/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..76dd7c0dc7d29211588164d84afdbbfc51977756 GIT binary patch literal 1012 zcmZ?wbhEHb)L_tHIKs>D^!)$#2YzkY^5D#w|1)R)PfMF=Y;63lYW2)B|4Y_ByZGY2 z@ys)6X=(re|7RczDE{a6a}5c0b_{Se(lcOY1RA3FlZDfWftNuCWFW{H46Nr8l>1UL z=Vh!~m-BjGfzJ7o-1`;l-tUS2bHK^}i?l?4^Zj)lIclxjn~JkqE-i6q7R{WR$lms0 zTa{|c(PXFZp$6&4-M+5jEkCvQ-LH>wi=`PD8A@vmSlL+E7`qBsT6EYau(#JY_GD{M zP|odW?o;Ppuux@oWm)g^`5a8l9Nen*y-S%ldg*en=31-1VdIt+n%vAxJJ)GAIv8zvYsOGmFeB_+4l3hD?fhz z`pv6|&5Nf<@?yxU&^B3#JvU!XE%;M+xaI9?2fg;*my*BV_7va#ve?$loPmj};$5w_cHPG1 znp=3c?NA5$Z^uE9?>NpLI(hmm$9d!Sc-N?{Tfb?A=2qVAJ3;>2dB|Di@Qzc; zXU;fZIH$zT$;rWSQHAI3J)Yy&uixgq|LiU(?w-H3ef#3dr_W!mK%y=MHFX{s5`Md^ f!E@s#&+*ghx9;BndFsJ4+h-52yngc*=qYOegSw|T literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/thoughtful.gif b/images/mood/punquinheads/blue/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..9491f9238198b194cb3e1adab48f1020f9f0dec0 GIT binary patch literal 1201 zcmZ?wbhEHb)L_tH*v!fB^!)$#2YzkY^5D#w|1)R)PfMGbmX>C0Z2TV#7%+h1e{Mh5 zkYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=&KjKbd~IWqox6KEyHcM@WsOEgQc~Ko z%m}3->v;xImrZX!+con8+m|;P%Y@ctSn_3_IiEJGGiv>crn2Z4IvZ~_R@huvweO5U zW$Zhz3rCr%^~#!0wpZ5WY(I5WGP|)ffhD=QT_TyKwy>?eDy1i!wZEiza^1A)*)s#D zCNVHFbXG1}!aOgNrHyf2L&`eFm8(`WFE8G)b@lA&YkKFe**j@}gh}^Ev&VLM$tcagpRqwByy5ogqF+A~p3nZQQJSif-%?S+lGfIxoW{}+ z)7e#<-fze{sl04jR_qSdv*Y=bQrD0QjJ~GqjwF^UVDuF?GlSx36H*;;OG+uM&F&MFCIao TF9PC2BbxhgG=b76fm#Cq!~Q?u literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/tired.gif b/images/mood/punquinheads/blue/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..88b6c78ce9b7548506de329c732af133573aa97c GIT binary patch literal 958 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YwkF8*kb2;LMr-GiUx!OPiUNmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBeodamAU@%rrU{|Op>DVg&!R;^o; zwr9gdFa5;(M|NMUn15QmIX{DWQj5!?z!nvbIeVXPuF$!&Byh#r4SyuoTz^<{`)kc) zmv=9EzO9^@;J}a|d?UBW>Y?nfDCUOJa+U_h>YCcHO6Ts5&V*dnzWxb$lTv-^rnbk- zaGy14`aDNNE92!WR<2sXzIGk^^7Wh6>TKSoyKT$r-Fx=x3WA**fa=`YSe%>ldY?hs znJpjBxvUfZ-1XjJ-rE!osbc4#j}<;$(^wouG^Q#|WsRL`byjqaymMIgma2nthM#}P zuDpKmTQLs@Ls3)Bx;pg}&PkDs%@tKF&5U*R4Usi&ece6D1*{V%O)i|8;omr;D}J`u z+^Mq`x|rG;t`Y${cb)F~P3tu`Z`-nU``Xoe_U?naR|M6)gFSeShL&@OQfjaU0Kzz> AQvd(} literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/unfocused.gif b/images/mood/punquinheads/blue/unfocused.gif new file mode 100644 index 0000000000000000000000000000000000000000..df6fee2d1fcbaa213b3333e9fac81c850e025e77 GIT binary patch literal 1082 zcmZ?wbhEHb)L_tH*v!fB^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmi8YE7%+h1e{Mh5 zkYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=wiulBT)o%g_1WG36Eyl#GUsKiTDK-_ zPr*g6_X+n8?>=U;Zoa{twPq%Q>}(6)YDiz5)b@f`N>^ttt5eBrm!ipGPQqUK+PoYH1lRxUIv z(`hivI&bva$fH<2s=~q@tpHI{?AeWci-#WcKKn?vd0Gk&S>T; z%UpK2>bsIPeT&0_s+p(tjlCP1((Y@?9> zXK!k^ZG-tf_M^H-Pn-E_ZD#DW=;&%K z7V2zhh-RDEY*|$;G~J&qU{1V!b`HzZ^7w?A{U+hdES9cx6G`5%!9ZhCj?H$hox=O} a?lwMrL=6-lhf(6=24x-@O<2@VSk?euFx;a6 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/working.gif b/images/mood/punquinheads/blue/working.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e56c11c9113324a9fc5aecf40965a2b2af82c12 GIT binary patch literal 1768 zcmc(fU1(Eh7{^a%^Pcx0yD(`%>qpn6ZH|(Y9+vK;LlF0&!)!>vU1%a0nG^+g(Nl2| zwlWYJ7&4h1joob5q)D5!woR6_r#bm<(&p>5`Ebces?%24#hA_;cQM(>PP!{uE(XH- zUc9^)4=?=q|DWIc$BuTrbrwf(#El_8XDUy_&pn=Xj;jm}Rl2)}luBi#B0Rc<8~N91 zscb)fz|LWX@k@IZh zMV-CzAonc1NKfB=dg^ib)b(fEfze{=G1fQ24_-6>a^>i!cfS5zn{GENubz}qS-<(o z=!g3<+2gMmUhNER^!)bS^DAPc4mtb6nt7)Dsd_KD70`=HaM?$FKbfvA_Ao1m$-1=bf7!3mQzvgm~bCrhRCnO0YkFFEmY z(Q*I5`bP7PO{9hwkpf$S1jq&jf!!KzvW)GtjgC9i#%4I{yp8Fm_d;~R>v0Q2jF%0F zpxY!3M;0KFmL*fU)mCSr$j{=X!uU@DQf;E}RuIv^M2Z!1FtXb+w#$YQ;|`PB*aBT} z#;u=ihA4~bM1Go*d3_;G&_CQ7jU_}b7A|skxLoRoQhBY|ez!EWzVYx;Q_Yw{TL47^ zp?Y#akh_3ow^eMmVGi}M6iz$!Gc8cyVQA{WJgf0Ca=1T;E{b3(6_2$q$8-7o>TH@X zl?!ca{G`ylhqZ(9|Nl&KAgq%NC`@F-CKF+^o7BVab&8LGggv}6FipS{c}nB0%6l0PqJ;DtB;`j(gc zqX$DzbFZL>PpWn>Xuvn;`;FS(8wPN*T|oc|K{i-1^@z5!LpOQm9lL?T;rx8B$F7n= zG!!OKNCw04cx*1jtT0?4kx!(gt9)sGuDoWe>H)9WyDiZJ=r_5UX!iksMn6ZJM(7Q4kW0N6rKoAt8vymX>1?JQ@zJ ZBxLD$ekmzk;Y)0`yk@P2^!g6u;NPGr`-%Vn literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/blue/worried.gif b/images/mood/punquinheads/blue/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..a018a5a24a2d7513077aac6e725d7b355373a26b GIT binary patch literal 987 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEDHrrdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj;H|dndgsIPt>gzeURuH&&=9c{@S#>BGnx~kmzM%9))JC@$U89Ajh zngUwpn9X+7)Sta#sg9w6@w)XJHf~_wvXy<^ww+sacJ0;OyL;22!$))l!LANKb@d`F zuFiSA&minf$;Wff>-axgN$*~;uw09$!BO#iii^_JQ;pflN0t_yznQQ7&(iCFj7(43&I~h|ds~T$ynp#xb3msV| zl+4brnB5xOKHqYli>C3s)hl#NO$;}R0$sgTciYZwn!EPy-m`DZro%^$LY*yw>g>5# zoQ*56FIG&M*tYGSk=GteSJp$mRWU;A7U<;dI$Gb8FNZXqiTG5ySnqU%~&Q(oa8ojT14ZF&iH!Ixw94+a~K*dTeW)4S{?Qc z8`+m_+PY!=wr#pQx3Al`|9~bWpwW`YeEcrHRx$td@}{#7b_*7(Jv>nGMz;UJ#0e)$ z!lrv@CRUi1vA1Zf*dQx5d)tO>C;YnYpBP_VE_Rf?fq^0W%=?4+aw*Y_tu^MYj0vS> z(RHr)1DKW?!>q`zD79M6YuI literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/index.html b/images/mood/punquinheads/index.html new file mode 100644 index 0000000..1cbe702 --- /dev/null +++ b/images/mood/punquinheads/index.html @@ -0,0 +1,43 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+blue/
+pink/
+ +
diff --git a/images/mood/punquinheads/pink/angelic.gif b/images/mood/punquinheads/pink/angelic.gif new file mode 100644 index 0000000000000000000000000000000000000000..5c97a6545e462a994a11c248de422889aa378308 GIT binary patch literal 2080 zcmZ?wbhEHb)L_tH*v!lD>D2r82Yx+0|Nrau4`)`~nUp{2)wR$6|EC!n8=pC2JagvE zw6wG{XU_cp|DOR26#sMkxrPKgI|jHK=@~FH0tFR+vTzzP@G|It6o8CnV0pITr043r z7O&6l{-2-`*=f(;HjVl85e5>J{4Oyo^1er5BG z>&lx;uL3JXg>-}`sv572-*EJFhVg+U<|Mnhv*+@*{$6|T_4iy>mgExOG9MP!hTJ%z zs`{L!wp8EFnx1@-33-#EqNdH5DVj5<{I$f zr6>s(WICNON&>8ymy?$oUN3 z(`L5_&1xxWV_;s#ki)TdJ=@Y%Gk6OM%2_ruZ;0Q=z*4&_U8ejHTlKtk`)dvNELu4K zNQ%;)$&p7cgx?IlH{zL1qAy&|Y8kcG9S zFiEJcxuC5pGpM&=Lb1q{qG@q)v*yedEm+Xb#;_)K4MV_^361&5)4-8l&9P(GhTdEc z7GR{G*pq(zrX1-_MfV z-@bo$`|(+&*x<1@-<=Ef17mU z+Ga6|NejH!l-ZZ7aqZ3KzkT8296rTGh2AWzwOMgOk~OPZCTZpCSMQq_n~c#2M@EfY1Z%Dn$J;ihT-I? z6DwCNI}xM2f63gNjxHzew%)uIe&8X7*qYwIwZVdq9Ose4k literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/angry.gif b/images/mood/punquinheads/pink/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3d35b3749327de3aab4c4cff3c068857a0baec9 GIT binary patch literal 1148 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEIr=_JC8yo-s|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7f%$mFt~>t>PI<15RC`>!b6r4rZ`?Ia^%EVc zrxI7bI`T}t{e$PO^7sD_EZ9&eDbe42eS)EZz`TGa#ho@1^Uq~mvygGwpYZBD_u0C$ zEQS3#XXo7Y-`=9E9Pp=@2X$1sd-QQ{+Lj={U?rwa(lR+ zK7ZljrOQUF*RHc(x^es3`8)S7+`oI}$~`q}wZV%C1m8_A48H{9^Xso@ml|$2iAH@361 za#NpHKGSr@DW>xnn3`MWPMSY;(b8pe+l!*6wJ(`fv7|m``_`5@ zJ4(0gPT#w|>|lg@c;KniXU?9pXT5ld_1xua7f)Zmb>`NM^YU!c_3 z*}SBvAV!7rf`(#djo13%Wd#hT35)M#PT>C6wlGS5X2Py*7xyvE|(i6;)cmNSg-q+tlf8lN5@WW;4z(UBtlD-m!4n;+e}2`K*O_Hzvhc6JPKHPSO+W&}zp{$$}4Vc=%a0Vx9+%fNEA;H2m3y%w*}?*5;k z(U+1rPi4_Mj;fWOI_j&m4;K4vS6}qsFpkSZq^rj0sK2IhlR*2DCe5XCbL28i&9^35 z-+EG1CfmyWLVlNkw*2DPUv$ouwJ&HtlyH9Ddv;d#vhvFM951h`n&uYvdc#;wuKK2U z`HDa*ucn@~88K6*&6_ia%T(KpTW7^8-<9U;5*KOC)U7aCzp81+D$|{NIoS3~upM20 z^u)D9Kg zcRyVCY@va~h18l_R`!a@>e{-PfX2Gkww^q$Nt_e<`s+h;r@2@8#e}t(nrXGLb1l_2 z6VcH&N>}qR;Z9nwx@B|Ard2!qY*y|z*J3*$$#(1r_pwu_PphA1xNz~(#WRX*ml$u} zx_#^NVY%zKnI1oR`s5D7ed&i!S>C<>@ctR&%M(DK{``gAuUClnD`m0T#oQ6h+1D5^ zACMhll--k7F_W_?eCk}Tg*uBhm;0It13j9!A}w%z#ricHnzn22SgXahSCZ}UL6O79 zPn=Lc!EpB6`Ew@~+0HXwyME*Pg#&U|ZZJJ~_~_wHhC9;t9|wns&6hiIz2*X7`ZW{Y zVWYiEM4N5D6x-3m5=T#-I;DP!;rxY*7fvg(U1Yp*^VZEvhvcr^VtVxW$>ZA$_oN>@ zVR`%R{kx}(FOGwf?@wv0>GuYmyoxuavFO2Z@71L#Y;Cf$vTRkh6* z%-Jf$w)dbI+wr5vj-NhrM*R%K#Y>kjomFJJ%y{eeo!eK~<#hv$s1PJ+_!Z|t5WK3=JkSy{Q7fY~)TYX&g88nbhSr)&CZw=7y}YouceOvDKu zCL7GdHs`Na)!yE+TaRt;HZfpkJ%%k_+2j%NDuamEBj9*d#2T-}mrE4p)do-s<^pHd zELJXHW(6i;u4(g{!nKxjnTcronwzdR&(-xX*~o3zv}N=59UFGe-Oi@HSCsAe>f_kT SB{q3Pxg>)qmyW{9C2Ig`g#)hu literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/awake.gif b/images/mood/punquinheads/pink/awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..05e5cd4e464413c7b2bbeb910b6924cbe93d8858 GIT binary patch literal 1651 zcma)+eNfVO9LK->5X@|5X`NhGlM@p9X(?Lb!_22L6O9TV^C2^xrTK`=e8$93Bu%CS zVp$rIF!6a#5flx4e#l+6u9mfKJ(^Z)v$~sO*Y38JxAouWpU)q!d%fRpZ=c;{$0!0I zfJ^$|MD006LW^bANq zA6V&b-7^6IWNSv(?cZ&NeWX3)r(@kqhY4ru?M08MTP*J>2OK++H%jjwp5HqDSg!V8 ze0eOtu%JbZ(^yHaxfzG4h1;0hZn@nT&tNGdTNqa-kms}((kYF@YYzHmcyPhS+0=ax zjlz;L5iH=h7qAf7iN{H%c_l?`6t5IIgE`304z3Ya3$mQE1SyvU34)6oEM?neMHEwVOKQh!iIdvUxupCFrha91vZz@mO8z(%eU1;r?GM}Uj zJ^!ZrCRs51^Yn`|dOY=R8gaE+y0QsV7- zLKrKNH(5B^1ax$D>o|vS-PSUREYg zS4@!Say_4Go&EO(F06}jA1kNE-4}WbS?y*k*y9-5<`oAvjMN0gi_+IcEd*qmE#*G^ z)rqJonaR&i@Et@RNeN^aMW*KHF!rMW8#LKh>o&lR3jIElA}X;(|aqaO^iGbzjn8X3YFjYMvNW&sDcI7 zq9=0h#bXY5PyjznLh$_Nn)^ zQLGY8+(`{>4?E>@9M!(K7Q_Wb&3Pa@V?yfK?;t3nH#2X-WI&&u7Mu=2If%?G6dM$= zD64|}U4yv06S(=zB3q-QF-3{aiDeb3(M7?|4dGrq>A|wbolOn2Hb2W$PAxof71?OszSi3sFd1OHgNwwiS-WdX zB=J6zxuT8OEXl@bYE9wljE)XR6eEgG zmjS4h3-R>6$BAR=68O6Vh9$sn0SXpxdxYnIrRU20v;VL~8T_dw? zly8Kko!d8CUnMH_mkHHhE{^^?RLvi`_$LRfB`wINpQm~wL$-Co*G&iN_8O<*4OmBL z8D=(>tKn%PoRR+HD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B@rM-Kbm3bPYZu7P*#CopsiLyFu-4PNp}D0x!z`;QBCjdhddejCs;M~> zXV}l05X|pgjPf*w@;59j_p)Y4`w0lMHdQM8 zyTtq~F1*6AqDxkNs_9fCr5RIaH!5gqXfIv1e8qCM)oa+6 iuHCR&W#bmrEt^*E+_f9(U?Wrq4~2Ar=Hx-2F027sgrye% literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/blank.gif b/images/mood/punquinheads/pink/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..2587a813948bfaffcc70eb38d187cfad2a76eefd GIT binary patch literal 782 zcmZ?wbhEHb)L_tHSj56`X2qRJ`IBB<`<#}R_W%EX1{hHM&+X?L671|4;A*62z|05~ zSNzGsnZm%rpaW6^($2tKY~ zc6gug)X#cWe-B^(uFayU(b(G7-l4+W-NW42JE6O4;zZRclR9V4nyttQc2EEz2c=}r z(-2vcQ?SlShx;|hd5gDoj_;0J`@R3poz-?^j-W7uN^Qf^r9aQOnqPVKrm7?>^^VUs zZ4P6`INc~K-|(|ZTcqTs|G)4h`7&SJ=GN+pI(=PJ&2}ED2qL+dr(k^YP4zI~ViTe%X3=QvRe@*FLAEr5PI=|NsA= z0Tn3z=k{|A33hf2a5d61U}gl$D*j~QOkv<+&;h9g8Oy-(GvK7>YA*}*)4TW2ZmnG+ zQI+gDOW`YYR9a)Z@-PL~7<*eN7Vx*S`vHQ`gZveaCzM*SbF{o0Q|4_vjxX#LIS z$Jmxkn|W3#$3|D;UV(Ge-#Qdu_ZeG~ky7&6(PNDOgd#*p&{;K6|{tKD>x8Fa1 zkt;0t_3u9eGndQ?*2aU)92{N_CoViV&?dm?RI*~jqNCjsr7n=r2tW;uU!c&~Yw`N* z?*9o&eVji!#k111qSswr&0)grZ{#an<9~AX^u7QMfnK*ez8ViitNrI0X$XqUKk+!2 z$>!`jza@d*0VTFeUQQb{~Fj!qN}7cOBy@tODYXi>$)a3 zrS(l{;Ov~y$kr;wIgMR;y3*{ql5EV4i|SX`GqV}2n7O%e{l=A(CT-K+#LlpP;(ms8 z8}_VZU_8k%YvGAg?7P)gFrQ;QJ^d;J^TkV7PF`EMD2qL+dusH^!xX_U+*7(`Saq}or`zQthh5Nf6}XKpN)-; z|NsA=mX-!28NfjCKewN2NU*bGfUA+70W%{|Q1K@VX9@!^gAPam$XEuJqZ>|ouHI|$ z`t0ui2^xJVne#GMty|N!$KaAze$xGuyRTKuKds)9pTRt-#lqFU)3|GbS?d?IRIZ}q z&P7sBUYmlOG|8CUQ#HaGhIy~4!Qz~IBlRnN#;Ril{9-p1Gz z(#Oow)!p0B-x55Dr7(%Tx6H0|^3>V|xhzxWb@!y0@oe0*nMX~3!44ko-FvvV8f-J% zwRbm9z#8Sldo~uIIC*mBkQ))t++w{#zDz47$f^A}QrV4npL_F2yB zeFkl3Og^3ST&MoI>%GIgw=En}#m+&6%NfkdJuez9U-4>{FJn+;Le$Ez+(!a`6?XY7 z_w$yU+wble-NkmJx2(Y-?%N(l#zqEzPOb(v`H#^&$_R#pb~;*tprtzlE9 z%`E9JcPwLOS-2>}Z3YXQhVhKmoIG2%ZRb(jxQU&Id;bCMohG|X_Z{5N6WpV6{J_?H zo3lH%ofqo6qD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^IRMqo3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_w9!|T7;0Ju?DowJbz{t zk)ExOH+~o1GsSa>x4|BsIp^;dMQx2~wt4l;n_)(I8bkRT7M6PrO)>AwYHDZ$1A5JBw)Gp> kR&Ly~US;bJ)g9Z`A{=dm>S!9Ijs+`QV5#Hf2u&T<0E4Wk?EnA( literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/cold.gif b/images/mood/punquinheads/pink/cold.gif new file mode 100644 index 0000000000000000000000000000000000000000..f0e79583d52cab56355aa1d5284b26932238f271 GIT binary patch literal 591 zcmZ?wbhEHb)L_tH*v!rF>D2o}AOC&b{-N;Jk4gEH&aAj&yY|ehYoCpcjsO4upO%&e zBpHx^;(u;G*N|Xm#{gF&Jp*P&pp@cI7ET5RZU!BYGLW$hEUyYqdamAU@%rrU{|Op> zDVg&!c1h-}j>=Iw|1O({dEtAOycOnm6FqERu-Q-9aKc1rlB!d&mCB4IE=NMVw@li= z-ZDe;nbiK)H#;KK#P%pUS?$){=U%kxpWZ2Xh6d-{`bPGe!b}FHZiY0DuAa66g(B7o zOudoQ8CcsD*`{^R@R^+-FrRr^>yn1K9x7~%D~p5YvNAI+SJ=q8d5iNl3(lPz7>z8p zojhc8BwnjqCe& qp-);r{{GeH{=<2Oy+FaSfkRj;rbCGdD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq6s4t~>t>PI<20yES7e_x*@t72J|e4<;^4 zf4wOA&$*Jfd=+*#`27AjF!hyxVC_F7o7<4{Z_4(Bg_f*N{%7K!@2I`Uav(2)StLfE zxnPEr$@WXWNMGJ&}9AVx773d;Z?F>=1?Tn2Tig`?J9bGJw zdztztOzLTLo6az6_M{r0hMCP06Y~RSE-G2=z0SkjcHQLA)V?>Wz)~y@5S0%$JK)CH>=K$q`sBdXL57UEm+#0AO6~xT!iL zI&3?eApj?&<5Ob)3X7by{DAN6nOa ziQX*VDRT>!xvzA#u~@ljy$hF>=gofgKhVrqX)JgJGt}Z@qNI!*bDK65jA`P zOi{c}{yt96cd*78G9O&8eU*hZ-aEp}c2RWp^3T1Z!VEt?it+!r=$sAmMQAe67xf8D vKwq?#cQEv3X7x>W@9*qx=&kXsnQENaThu$ZU}>4d3ZO4m5a)|wkff{u3LnvW literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/curious.gif b/images/mood/punquinheads/pink/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..42878a0dcc300ab4b9d9896f87999b8fed37a09b GIT binary patch literal 951 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeLjhkPA^!; zylMuk;`vuA&RN9OJHLB9@1D*x!jc2=NwHs z!qV_-Iop)Ofes1pj-7lN|JhZ02m2kLItHeMf+p|arq+VmY`ff+s>qgT`ze#8w5C{2 zpW#_EW#T*=9c#ViD^{*r&bD?P+nV*8HYji2rm=19>fL+x>T!ad96-p)DVg&$OxC<9 z5HnCbU0}Gbc;5O43;tX8=Z7(frR$xW5OCQv)$^=_L(kKBERG_^d!>qR`HFj-%hOM8 zkXpfZ;!u#5f`yGCUaf{Xt{dt$&c<) z&$+E`amVJ}+r0{oM;V2ZpMebN@`VMji+8i zZbemwO;(eAWnkjuX8(Xn^J&xFXHIUKE3c`cy$tB&6~IttTefcF8kJ33RkvD2qL+drIHac5Hgq*vEI&zw0kEiLWLnKQ=5#{d8SXTSi8 z|GE8KLxPQ%!hNhxgnK-6a#_9;m9tNi3l8M<98hfXd zbXRy)P3}maT$;6Hk-Xs&&*du=S1nnqD`af6dHar?yLPhe-N&|l|DnA)hmYwVJF@%q znX|frVCM&*I)615=jXiMx1m+VIhX(B89t7O|5;f4LO*|PI4+gNkYm-Z^6dSMB|;07 zG6fRv25nr>m~d+Cv|6SO?mZ=JjV}dn`>G$=oXnK){vPv%EZH0e#@2d=mbS7+nIxu8 z#`+lB2@Fi-6;t!4v`(B+(O=_NH@zo&dS%{WQK_v!9G zv|sb^u_H&1@7;ao>^Z3WMNr+p5{vus1i#jN>t!cyt`=I$qM4y^<7r#m8i&^pyZQFNnkItc^xXkwC<+_VA`{GQ770Rz0V&=SNW%*ZWUDr^MDi_Pt%vhP!#lTcu(-%6WZ(>bn znPbI-HieE{j|tO*7dR}o)iPeZW~HvFiQy(uptHB>Zr`0hNh z(UTtkJn<>ywtU?k=lA@(ZaQ64mgsMZd$O%rWa0&t4~M#=dM{s3Z7_-0dpyVZglXA= z^qg)Ti)DA`ELJ!zqsNx}UEFf{z0cucwPMN@ZVVl1g)AKmZp|%RZ48W484_67rc7g* zAmqZtG@EgH-eQJ@CEk1$%LA6rD^0Fn)EU^jGJ7>|#lpsg8$}db_crveOp-ow;EY$4 z0gt_%v-&2j&1Khb?3OTB5V+>8cT0lx*>lz>{4d@-d&T|sp-epny%gTzQzKJ89(?|PMdHbN2o<` ze*VifcHO%dl%77qq|dxO(K@ec;(FH^maDeyw)f0Z$k_LG(Xs>8e=Z$O@vDwxuaAjo z*2yYmVd%@L?Codi>}oA#V4TH}%EC5t_LTHM-V&w-jC0CXFfdJZHz-*Xx@Ky|5}sv! z4AHySrPpp;*AspCK<4(=Wk-CDEw(8>eYm~RJAzl_i_3|x*m&u9Zg12e29oJoSP*6VkEJa(#V$s5U zXcTWZ^_>y?zA`qj4jjjw$ub>Xwecc~?Vu>m1jcZ`C@_L&0V8-J!+cN#FAZ4Q66M5G zv7m2l=kn~8yqg=Fca&MR?FpD)JVEWy(NkUyGE$q9rh_2&A-DvMOy;^bQ?Bt literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/dizzy.gif b/images/mood/punquinheads/pink/dizzy.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bd09e8251c3ce25b80870f59ebf1880f980eb2f GIT binary patch literal 1761 zcmbW1Sx{4F7>3UY;fz+H&}y+%n85+76tF@UwnQXCG%N*Cu`WP@Vu&oV#RQ1vB%C2E zF^gcxXpk+0lMo1Dmo0=vAf%vx%hVQZosPIrOLbb*)`ni>Di`X1{mnnm^M3Dq#C@T@ ze&lVyHlTG4usremi_T}04fn+9;zzgs^zrdYN=kb3{{t*NmpAJoLk`3cc1MMHdwppI znr2*9uxmd6)&L%>^Q+$i*j~HweX2g+$HpG7IL5|0YUBb+I&rOX$oc~#=H}ljn@iK=tQW4IRK@=C{D50qS^V~c32v~FFi4*vtRFj+68#jPbS;pv zK{+~qpGg3?1Tq&$hC|PvfB{elc)AKiSQduwn3|3$2gMh!0@7WnF6p&#NwwLDl?7pi za&K8~n6#OWMlg`l8G-S9jJ2f_UXZ+4B<4-@&FW6fWYB39W z#&wy5;uey{sAI>{kIAe8t;%ZrW9)x zaKc?TEjGbkkndJCwCrwy@qk!^o^S{79GmW4sXASPm!0$W|hmij%(VYz}N?K%RI_K zKa#w@C!T%}XRB6ob{v;AS0c2=E@6i%6v~{UjW*b$4OKthhlfTg7gs_)Za-o3 z>PgduzEJ;{+q?1xa>+FJ)HLk50#+I;!-Wlpuy{L?ibbXT0)aSD>W$|HnLy?B&Je1E zw82dJ_StUt*i(de zD9<@bvnHg)3ct3|k=+D)56PMj&|ZCIXSEdG*6X2c1wa@G!6f9Rd04YK;k$#8e3mP= z1ms3#r6Iv*C1JuCgj!J*dFpbCP!yx6Q4%-c0yS-`eRYI-dZCU!U5{pPxNTV9Z90XP zJKXy2@SfkZ4@vO1+42YOtqNEd;QFEU!gOR%7riASN8~hOJ9DLO6JVFS!U_+jZpp=f zpy})ZrkpVa2&J&NgwKORGPY6#$0`I|1|o`LpAsJtWk)sEk;~Lv(UnMTBUR&z3nZG( eo_=TxGCZ}{$#^KqyTet0jfd2r4+YoaA literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/embarrassed.gif b/images/mood/punquinheads/pink/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..ea6a79a47c859a5e3046a369c4816ebb7db56d22 GIT binary patch literal 960 zcmZ?wbhEHb)L_tHSj5ioeD>k{DND|*xHBn#(yMEqjg5`d($fC_|F8I;+s`#5*x50_ z)kx2PnUR5kLGdRGX9@#5gAR}l)U3h4z`USh*PVX`r#x5hwRnAY_x}Wqz9lAeUIb{V zKiqf3a$AAy>iY@r_0GLqf5`90r_6?yrcKLKj@30i5V}^w*)!eI#G)nEJZj#L>N`y5 z)@eQDDVS)S=#aoyAoir>ko02F2h638^$bkaHFd=erp;~bbs1(ktq}#S(bm(ZxYth4 zn>@>Y&b06amYPP|D_5;vvx;r~2DX(Ox2#v$x(F-vgosv0E z!(`2yf^{xB!ml~bTfD7ves|p3&p+&gXsYAc2>}_8X1UJ_a40#qz{v5F(E_1fc%Y_6}Rr#wteUNwfpuTfVx@))z$MbT#YrT zZRYtitBCY$eZ29z@SZ82OS}#C@XR@Xw% zEQWy!JJ?_N*D=(@#?=JPD*QT50w8(|mIM(#Ys!unaZlpA8`rK9pO%3hkD^{*r z$+mVK+w%3B)~amYrn+s*>fL+xLY-_xmXp^V^5giN+0dGz>-pv{i=%1}r?7-Rb4EeL z=DbaNHhf>fI%Bby@d49w4UCNz3p^W6bLRSlCGej~tYu)Ttg0!jGi_{Xtw}e_Y7Wn9 hjD2qL+drIHac5HgB-gK%udaPgOG`60Hva$rKLa+P_@CR) zH6+;CF~HSG&w!Z`s7CQ83ug)g2ZIhsJ;+!FmU{vxJ+*BuUgzvy&#u__q@qS6BS}rL zD}C0!#J5=+bZ$$&d1fWDb_*k$_4?>bX*N-lR2K#BSb1#OjWy{9-ttYj#kt)|A3kK99jE`{W=2Y` zL|J`9Q(a4*WL_iC*VSFklUbSi{3bNl)|F0=oHb|Bv>EOT8CFbcS;3GqzkebF<7S37 z_RWlI*9T8v+O(x@|4yded-m;En|Fxe=&^k(Yu6lEdT!#PBWD-vy_S2UqA>Nwqx*$L l=}(@%bZ2|>_U$W-RSw{s6rkrNqEs4FEoN1^)m5 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/excited.gif b/images/mood/punquinheads/pink/excited.gif new file mode 100644 index 0000000000000000000000000000000000000000..caaf6e4ce52c799595ec5436ed516a4ee8fff79d GIT binary patch literal 993 zcmZ?wbhEHb)L_tH_{7fe>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^9~_sle>(#)Kc)FK4~JyV6GN`=U>)MABz%=FUK5(dSeESxC}>b(}P&+h)8pwYL)WX_8KE%k@{j#zFhkX?O0;l19um+KGt z{rHsG(9*PNnaZ)crUydTYB+nQJDOOu#F|IV`%!&|>D+GP1Fq*<7#l4XtZX^WncEYV zz<=gtEdx_!RZU@?r*~sZYfXk(R&zvNbF}r;$?nzDawg5RpFK5vzNMy-_KKCORz57%-!EO#fb@KuYH>YII(=b`{reK|mj__-a^A>OGoZlU{ z_VW+>Ae!oUc0xeLqgn2=0vt-tEiiKYWVAr2*ZA$S-`d?%;~H))XFGCE(n!I9-G%$J z6=UB^u1}0*E)5J!HMR96jXr)Y?H%>mmbq=wg>7+mGp2df&CH)V$7$Y-s6{rqrkbmH zfNox|x?%GM#Vy;nZribL&E9?cp^g?I*I~zh4)PHT;gr8hiA_D zyG2o3W14MVJ@aOmQJ%(7{)UC+UPDvNyEfq?E{zN1I?i*~FjU3HRp-~b6{WT}wX{~J zn`Ji3g;zONRZN{0p+D0|Nqy$x1*)1F+Q5Kbvzl%F2DX(Ox2#v$x=%U1vCIS;rExS_rM|9bZ)T!mEavS2GnO!%P zId`e}#!1zRi@v6l4cbKS#1%|lw>$lRO-cnrOGFEUccWPy17jaUHhXVBTbF4$%Vfq0 zakCg$rcIyOH#;q3-oiyQTZ7vdly)zuh}g6tWya>t_1j{0Y%19k=H~Bl^w{weCk;5x zoaH!i?&6uFm#!YWdim6?+js5?V)M-&pl_B6yu5aHxBPU2ijw5*0u4iO<8peU2$Cuf$iok42)A43fU)5Wt(7B%QBO3TFL?j zmN|3hPg$6gw`BQ>`Q4Gd%c>_XtBc#QEocUqR?-1+nF7cO6L zzH2V4F3|=@PZcP78qLa3q9-*S7Cl|2Gs+_ttgPJ>wAJ6qW$V7(9zt%e2f@)J4~m}S c!00)6>FQBP^qhqF#%Ngi1}*Ch?Zjpc01j05asU7T literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/freakingout.gif b/images/mood/punquinheads/pink/freakingout.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f0352429c99757fbfcd4d6b2beba2f6ef532c3f GIT binary patch literal 1933 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEIr=_JC8yo-s|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vXP9p|(1|1+9s9A%7f%$sHt~>t>PI<15RC`>!b6r4rZ`?Ia^%EVc zrxI7bI`T}t{e$PO^7sD_98QoB5mIJuD*7N{)!+L>NOOi!+o?B`D%T3_@O2dJxjJiq z%E$0WF&^h{_FUyyx94eEbI|^OoE@@%G!kvyA;|h`v zpE{j(F2L38-1RG0^Zak#x_AGHPoJ?qe*Ws|gV*mKzI*fd^OvvRggCMJ^$L-G zUGTwBLyFz`QNw{8p)OC?i=L@Yt=>+{yj+!lM3qhUpE-(;52ertnpD6)`X_1$uPJGM1L0 zaN)_T7?+!FVqjWpTevMMdfU!jJ7&ks-qC(=NAHdU_O7QxPOo=9clzS-K=*}#x9{A& zci)cn(PP&8Po6)z^Wyd0*DoJ@`1t8FFT|r7sF8Y=SdSKX=*Y2oC>AM53e594Ui7QL zNtyZJ)W({sg%@4RqD3BWo|`b;Nc&)1z0?WYu=?uSmK^)!w&u9z zW~Ri-sJia>8kT;$&XU;ZP_-4w9Q+X zc2)0Oy?yz-{R^{~>~YMWRFZbI<80Q2B4>{aH?O$`SGe6b0($iEgD20QxV(7%^3|J1 z4}c#1Vvp6Q#3tVbK%Yu=HZLhEh*9CZprM#q5+LHvS!jx#1iEIFQZKK#;F zkMoym_TTir>-&(8^~uwxzRzAhb9wdl^_zE39^p>D#QJqKs}7;8N_3e-`>YBqnc!K~ z6qZ%Xb|L4~BOPb5&I5Dm`5RY3IrW|q>%&Kn?mvF^*yZ`F7cXBwybmgqu;=-gkT-@UcFA^2GP)i>EFx-@JPL_VGht Lne-J{&sYNhmzJ0( literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/full.gif b/images/mood/punquinheads/pink/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..125b689151a0343b35232ffa366daffa262beac7 GIT binary patch literal 1048 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8Sqt~>t>PI<20Yw`N*?*9oIeJUn%GNSlg zUhg|xv9F}MDr4>K@?-BD!rvGPT;Z}(@ikZ?($Bh7TdUM?u3N@bhpVxw=a<~LZIasj zV%mf3b&U6RnK$sn&1Y=<^QZOt^&4u5EVYcq9v&^#`VG0doiTyUm96!uy?q6FGrN2E zn=<3(&dXj9R+c@jbomnN6TA3g$-1sCTPeSBqv}2pwu6V*_8&fWQ04e3)l(<- zpTBVNk`O1@9|5TTSdZb4l+1Z6jMwBu^SS7pKfL2y#h$91cdvKzym6m$Rgc+m-Gk&u zEbd-Kkp-t#g-M32T9U>YaX-u`ch=EBkDVv_IFG%0$K&w*B4fsJpY5s!zMN!rHGpbfDvtOkrp{u>le~GN; z+UnJ^Y;2o1vnlR7a`e~{rQ^pm&zwDX9^wZPR6lIO@B{9+VCipCTpFP*Fh^hg%hVXD z+5WRa!lxRPUVgDo`lsA^rca08FzqPKV+h~r7th(?@Zj&M*H2BdveW9SBmG(%LQ2%i zJN;QZs@fWRN^5IO3QaSo@#Un?Y3eOsSXMS~$?~O*o}jqMj9F~4dihFOU{vfCVLNb; hZQr4z2UL!oR6Tio-#K7hK%>G4)f=NpYJifIH2{xH)CK?m literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/giggly.gif b/images/mood/punquinheads/pink/giggly.gif new file mode 100644 index 0000000000000000000000000000000000000000..9dadf3cde9a409827e4fded3de95f64e117d78e0 GIT binary patch literal 1499 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vXP7wxn1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{|+Sn-{EXfw}qRP;v8U zIAclA^DxqLO6EKblQnM&*16~izveh^@wU$S-EnKb_usj*+FG21mWMF4GDS|_*#kR)9mvxdld!pNtj=^%}oj_FKDqYFxvu literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/gloomy.gif b/images/mood/punquinheads/pink/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..4cee556c1f5f6603a509815f8ac78e63434f2df6 GIT binary patch literal 962 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq6m2t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA ztlv7;YwC&{Oq<)<>oUx8S|bWtqphb+aj%`8 zH+h!*oN3_;EH#a^SFT#UW)<7|4QwknZdtFgb%*MXZEN@L+po$Ac60!$qZeX0IwfY1?yaNgkN)!V5+NcENixC>+EXGw#@H{F7Al4 zn>pR9VOHU^xlZ$EMlH6{HPu|h19bET)s0&=DsJ7eZTrskYxnIx0Clwps;lQ=xEgCv z+syN4RuSph`gr4a;XPA4mv|fO;hA&(Zc)_Mm}Z+-&%7CC#I|lZ&GVpdZbO622Hhji zSquXecCf$juVbi*jjJuHH*KoQuT3}0X^{)BajfZ)RiAD;-AHNH^tr7Hni|^6SFBvM ll5Ooew&m+LtyS5)O?BIr)w}oXg*w>?)ybo&gEpzd8UP+Mr}zK> literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/groggy.gif b/images/mood/punquinheads/pink/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..918f9b72ed2edfde700cdcd3f15898f8af101388 GIT binary patch literal 489 zcmV&pS>ell!Gc#spX8-^HA^!_bMO0Hm zK~P09E-(WD0000X`2-1M00#gp00000C;%t`00YB#y4+_j$~hsucp12}rxp`_-uRq~ zNurgwx@t>~akF)I`D$yO`8HgqF(?`bwqB%2XgUeSU5Yq(TAR_=sCw-}r3$XMiC)+x23d$?^y4xn)-*IDIe=m9j0Ek_P0CspJdH?~Ej0Kg4k^zi_c>)5F zlWCTpnVpW0o|ueJqX3(Qor{WyrC>agMY_eo!c<45$jr^o&(P2} z)6oyp*Faj>*wWkC)!^ac;|TyE`2+<}00#gp00000C;%t`00YB#y4?OS%41xe_|?03 zo}QP zzftbc3kHjKWI{omU9ZDqfz;h*M+N87KtBJz?|C14Wng$fg9HGIQ3Z`riU5FzasUCA zk&SDWmjs4r0s@->n2w?Vpn-y+mZNH=tf#4}p^I9Os7HICWuTt9x_nZ-RaOT|y~xDH fS4_&w&p|TMMMTrq)X~@4#o98^-{9fmLkR#oB23{l literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/grossedout.gif b/images/mood/punquinheads/pink/grossedout.gif new file mode 100644 index 0000000000000000000000000000000000000000..70588d826f572213727dbfb99f00238076880593 GIT binary patch literal 970 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq6m2t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA zty}hir(mLSqC)~-f!g!NZ_tIIIUX^ALkiMF0L#l3cV z-sD;KbEbtau+%itUb$-ZnpJG;H?XbTxMjV{)*Y%lwyoW}Z@(%h*wF!~j$Vl2=#8oyok zTf2K|T!R&x?kdKO#cezsHy8t#*)mK|-o;c}UfEQ`R9D|vU0~eG(9zkLZJFO5UECgL zH*>mI!>qz-bDieTj9P4?YpS`12k7VxsvEa#RNT5_+xDI7*Y4YY0P1QHR97#?a5dJT zwwdS8tRm90_3_5^3*+=d334LU5B zikoI=2poA{%2ZZd8yiX>;>T{MYR@Kzd zUbA-H`gLrZHnXkSvVD`vj@_!ecWyXv@DSA9Mr660v?QV+#^h!7u=gU@laex~@)D++ n+WKO~+|1@KhW3v7jF6lO6DLJmx6LT1o0Zo_thZfuLJg^mXNacIco_Do#I#~ z-P{-VdWhkwX}iN)uM=k|3(u+!zMi?=xcJu#nlo>vT=j7#WcDwKiGs;15YNgydL;jy za}J8dmp8od)8^DfOetExtjgjRCsg1WLQ)LO5SP|}1Aj-5@X(T$%O@55PDDmg0Ucil zlv*i(`V7q8esz1A1pWash(`geFkXqtk9OIH}lY@0pGj%NkOv_H{#ySytk#T8)J@&gjAF|6 zVYyw)n{yKL<|=+$ATQ0`jVRy8j6EA}oPQJN-3t2GclJDcA@BadlW^*>r(2!&zZN%f z%RU6x?1BNs8}EHSyK%zeO;pFT-&HaOH-Z;wMU+Ye&l2&nV_*)(OoRC(F`X-;HwnHi zS0b%h7_X*W0~)_4wg9L{PdD~d`3DS#30Icd9?y(4OjZfN!wQQYru-SU0+&N3m zb+YDNf+6S6D=3x0jBd3j73cHgHexq}zNf|8&naFxoN;8acjNB3Gltp8L%$1xBQN(% z&Hu^8=Trsn=Wr^~DrOmlhv17FgjjWDg1CtZi%62fn$|*DtrYD<+Orf0(4%?`nTR2q zx(oXU)I9_VY=*iU#<5G*j+rLvXKXibja@G>*hl1c73!KJf8{D(T&f*){kqDfvFYn1 a?2did9s8+)P;h70>%s2$Np?H{AN&h7?1BdX literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/happy.gif b/images/mood/punquinheads/pink/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..3db0b17031d0993e2809af10745aa40b2b49f3a3 GIT binary patch literal 957 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^IRMqo3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_w9!|S_IY6b1@u^HK1+g z`7^7C^lW{+@w@PzDV|Hb4fgQNIe)h(YHLih&8uhL3^U5p7|P$Uu-t3NJ;D2qL+dsUz_W8_;JCpJ!Jw5;b{efRwwmdj<=Ksu@|I^ZD z8XFs@rKSD<|DOR26#sMkxrPKgI|jHK=@~FH0tFR+vT&v_@G|It6o8CnU|G50r043r z7O&6l{-2=Hmy$UzW7WDfZhH(adL2=^vtz@FSJ}^Z%AR+*z}Ua-;fjvmjB}Y%J61+J ztoD1^Zjcc*|Nd=<+Yj0L-R@M}bluIGJu#AD#p2fthBK4dSpG5iao05zR7=M&w=g#P zb~7*+7IoG4M3hXO&|WjKqP%qC>^T$jCr(n;U*@n(Uwh@UHH%aX4UD&K-?4KC&z`+J z+x8vYqjTt}?$N`$PMtoZD+qRd0IKU(VR3!V>wN}pXG}f{buV~-C~5U(nf~X$XL9Ua zXp}CaSbiumVvQ;MccRW)AeywX^E&C2yl zRZL9`cZvdCzgKtP!F`&CjvhX8Y|pOKXU;;MFM{g)#aNt=Gw>^N9!*hP_OX3);6nLB z3$l31SebL&U%Ng#bb9UOPO*us4Hd?GJGL&4c1Yk~p!cOFAxS2Rxq-1Zw4H&uyrSER z+pN2r9$&9}pczd@%(Q5`YhD#Z7mSJ!%09iLqhn}j=<@P1;=jjY+33h&zwg}+ z`5bn@?Lq>>t;GU_F-Kq#+gDz$e2aj7_qp#?C)qdg$Yqaz4P}FUdOEjeg3bAI>GluU z_PDD(*TIt1Ox?MEfv}g-ZUTMgd!O@jtV97{?s~%4(@LF$Cw@&1gD;)GM2Sd+@R_uXFoY5<%)r@o+si<&bPOg3%T*!yCjyd^eO3LPZ3_o?07ct@>QQ{ zfd9zYxLl!}*oaYUFepI^$AG(bcFxmmcDVD{_x{9UTcwVRY(G_xMcV1gBtLOP?Y*7D5 z(BP)CXWkf!Rg>y1m?<4bgVoPXP0qhnzg?I?AhBjO7Hd{>9{Etc*Z-u!IiiZWSrN`7 zY!YeeO%ZkDyoWl`*1®&D17hraN9PqYkUc!l7uIFIh|*pVPbZTmOrm8*!#Hhf=l5s%E=+YL7a)e zqn>pUFZ%ek{Xlr2RHJn@&eF7ytWeP~IW-DplX4Euj?Yeyu|`2rx%8ZKP=+OgnigG5 zVJ0S)U9AAztRgO8U$MBhf}Ll;MprdLE7*nYpp7q)#mmIi(%J-G=Qc)LWm|W_i;AfJ z;5{3H`$zs5{4_M=jlv3}nw(T()jIW{es+3hPNiL$xAp4t9{30P?_%bNGZ!Dq$C|ZF z{Mg~JuqOJ+An)_QdyX5)f&yRsCvdi#{AgF~SJwu{9c%0N8x6$(kt)&10F4lg9oVTQ zmaLT?S}Sa$yVe;KlOs?ziD)<@HY0^#s7<0pW<@}$mbnZ{}oRk_3ou3-83<;Z=z1x~e+JqDta389i4N`=XcJ|E%Ms6ZTBd h@EaS9T%j0SuT(3CH9GB-Uap#7SbRHd{6FM%`4dYf+4KMa literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/hungry.gif b/images/mood/punquinheads/pink/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..1004a355240c35b4563d3ccb5cf2fe25dd8d146d GIT binary patch literal 1033 zcmZ?wbhEHb)L_tH*v!SyRIGJo#hp*5-hbWxAth8`QvRe_T{f?-eKs~WPD@Ms|NlP& zDp35-?dKX2?CcoeYNTht%m|cK{K>*;#K6U%15ybxmVxC~z)8>5do5m{-Tgm7qc0_M zUdF0*Yr^&vT=aUMc>nnBYZdcPFK^1vV4l=sek7pMxN8D?%NF(2XEqx=6(`Jjv}${U zFf(i3e(yOmiuY;VI`Xh;^V3;7*&FLth~IctqR-i!&cxi#6dKgl!QP1GyCSIGy-BopT^0ql*eJ}|`+W0@MqjSR*(O|DS*OiV6X>2@lpoJ$>3&+R z{UxuNbs6`&!@Cb~^X(UENMT}bVd7|SZ*FBTRBT}EVs7i;n8?H!AEvXmcu8`A3vpX_Q-{k45u$2 zzIu)A_RY&z?w)#}w)^&rCt%;cf3Nf5bA#@euf{)t-o@_Q;U2kYY56+Qkqb`CMG3-B z7#-gR&a~_g3FA;%z2mj+gEJ-FUByM6%H_M_)=l>)*&pBeC+2|sCswmEMb=7ST5hla zCgmoDg36w*c4j8Vlz@K5w$|X#?x{0;XU(putTeBmu3wz$KRs?aXYT6E>5+0QyFh7q z=1yST9sx$~Az<7dI)3ihNtH8)&!1p8b?MNRt8BM!T)KSceK7w1#l5?qIbUB+SB27 zs_c9jkuOBlmwZ(b67mJ{Z4*XBGL%dZop7j$Qrffbm+Yhc2mG|>`QiELdG5K_Jx>hn zN^nT3AMgWX9^k;R_o{c_K?gj#gA8~M031BD0=ffDx{(fyZB|w`>+e4g>2x}oOm@5p zaN_WBKwm~DC0>e5hz>kYI)y~)P4e*X5g;<@I(VX5c@A!8x$A3CI zG(17RSJ-lq>g|*pY=>PQ6n%z=tK10?*YBHqG)YAF9bDs;ZFRosR&8?GQ7FNC?2~p) zkvZ#!-5}e7F0wuB+l)}>f(tq4!z(Jvaw!Z7mBr?;t7^}{4Ub^oU@p4>5s8roBA+Uh zbhI|r6X8ykNYSMfV^#g)p4vWy)S=V#LfU}QNf9*6f+w^C5>x$*+G7577ObdNfboy^ z34qzMNj9G$OPm>K2V?8+KLF74y%$@DBa=rjcPqC#z4{8*qc$q3cT#nE`}n|1|IAz; zD>Z$rGmLG|k246d!FU=g?JCnZ(X#=TDsN4)J(A@mG*zqVQE+t0Td0H+Lye`lyWW3@ zamuxv!^RV!Yn0QT1H{NhqwndIvb)!VzVlhyEt)AU99j1==bJj`N>&C4S#Gl1q0T>k ze)D2vczJnlBBh!_WwO|;UpQxBUIXe>$L1kI5yB(3Fa=_nq>)R6JCs7XqFaPjYDF4O zFG7-ysC%Hk0G(b44N1rQ`o%^rJgrjB4Nn8B(h8nqZvuF7pn-5#3mRG+c4q zHMieR@=ku1y^Q274S)>TUyBF3mQZnAT_-3rD53a&^Id!=t%FBIqKK}!E z<#N=5%w3g34~%@gvDs|jzZ+A3s1CcIl3x)1b9h!FrIJFeX4EjsnMAmbiyE<+bw~>z zsUtQrngwk_9;a3+Z;^Gt3UzlAAB$)O+5w>w>g#VC;zK>v@Q6-2j7)G0YQ;>`6tKuG zpv7GC1Yp*z0^9nuo@#(LG1lLA0rd1Q``YvV0OZBXSN26|k16(c=F`AyE^a^F$m?2; zD4oT>7v{pOb&cctXIj&B4<;BNh13BWPONA7#Usse+h2*NxTNn5NghsbKJLVa^#2J7 zuyPF_MIyBgb}6BOfT7VANQ(*$^axNO#gl0iXhFUJ#`V-$fUzwLR@adE8UwU}S=MOm z0D88)W7|arQJ@`*bZPS*IVhVaD?T+RC8x)wM5RN}hXwjCoLghP$e9!yUlhZ5Keo{O X^{2#1wr@NvwBwbMW1)6e3<&)XvsFpe literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/hyper.gif b/images/mood/punquinheads/pink/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..a5da87b6ff2484399e208399c02b458288260cfa GIT binary patch literal 957 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vXP7wxn1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^nG4m;3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_wC2-=(!k<#v0Hz^Zc1r zM0&P9-uPX3&lJxk-UfSk=A6G<6ty*`+2++VZ-yD=X$<9WSXk~gQo>P@>mf0v5Ug=obEvr7wbefUU%xQC)6f`xomn~nhas}I(wQS4Q eZCsoR*gM|NnmmFi`x@?dKX2?CcoeYNTht z%m@@z{K>+Z!obR)15yCe&cNIlvFpx1gHxWX_gcI@yZe8FM&A;ZIV%FRoSEbgb^lsHIJo%*4*vsgKsKw%| z+25t*a?15Ht=8xse|EU6ysoCjNLy1wyQ{mWw})lIM3$~eQzxiQo2fc;df&YH3sgD5 zt_nbPRTGA*QZnahsH|C2u+CYB|24;Xi??-7?~Yshz5mXg)plf#pfbk~hJg5l%uF@L zoiC65I+C_hG*4)`t=0VfMawGXjx)U~y)8Tad}qOj*4p_8Uq{!ZR8}?Cx0|Zz>S*@z p0$nvxb<)&HiqmFJpD}Af-~0s&q0SOPb=DvWETf^|s=*M2)&TF!Q + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
angelic.gif
angry.gif
artistic.gif
awake.gif
blah.gif
blank.gif
brainy.gif
caffeinated.gif
cheerful.gif
cold.gif
confused.gif
curious.gif
determined.gif
dirty.gif
dizzy.gif
embarrassed.gif
envious.gif
excited.gif
flirty.gif
freakingout.gif
full.gif
giggly.gif
gloomy.gif
groggy.gif
grossedout.gif
grumpy.gif
happy.gif
hopeful.gif
hot.gif
hungry.gif
hungry2.gif
hyper.gif
indescribable.gif
indifferent.gif
lazy.gif
loved.gif
magical.gif
mellow.gif
moody.gif
musical.gif
naughty.gif
nerdy.gif
okay.gif
rockin.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
smart.gif
sneezy.gif
sore.gif
spooky.gif
stressed.gif
stupid.gif
surprised.gif
thirsty.gif
thoughtful.gif
tired.gif
unfocused.gif
working.gif
worried.gif
diff --git a/images/mood/punquinheads/pink/indifferent.gif b/images/mood/punquinheads/pink/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..1135ce4e4f5dc91b62f9fe1ae9b384b642608d19 GIT binary patch literal 952 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B@rM-Kbm3bPYZu7P*#CopsiLyFu-4PNp}D0x!z`;QBCjdhddejCs;M~> zXV}l05X|pgjPf*w@;59j_p)Y4`w0lMHdQM8 zyTtq~F1*6AqDxkNs_9fCr5RIaH!5gqXfIv1e8qCM)oa+6 fuHCR&W#bmrEt^*E+_f9(U?WrqkERRirweNUZ$hOt literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/lazy.gif b/images/mood/punquinheads/pink/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..50fa8a38fe75bd636c3d5b120791544a6c25658e GIT binary patch literal 1039 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8w!t~>t>PI<20Yw`N*?*9oIeJPpqRv53z ziRN?BIe&P^xr#kiIqzQY=6T~j<*FXDh4*|o#4=%U1vCIS;rExS_rM|9bZ)T!mEavS2GnO!%P zId`e}#!1zRi@v6l4cbKS#1%|lw>$lRO-cnrOGFEUccWPy17jaUHhXVBTbF4$%Vfq0 zakCg$rcIyOH#;q3-oiyQTZ7vdly)zuh}g6tWya>t_1j{0Y%19k=H~Bl^w{weCk;5x zoaH!i?&6uFm#!YWdim6?+js5?V)M-&pl_B6yu5aHxBPU2ijw5*0u4iO<8peU2$Cuf$iok42)A43fU)5Wt(7B%QBO3TFL?j zmN|3hPg$6gw`BQ>`Q4Gd%c>_XtBc#QEocUqR?-1+nF7cO6L zzH73pY+&0gy zWLn&`6}B#$gEsp+ZQHzazJr^q$KfNu=rQFub(-VYne(R(U$}ha^2HN3Zr-{L@rx0v MUq+MK;7MxM0J@s@LI3~& literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/magical.gif b/images/mood/punquinheads/pink/magical.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6c8f6c4799068260280f9abef6d387208d6139b GIT binary patch literal 1482 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 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/naughty.gif b/images/mood/punquinheads/pink/naughty.gif new file mode 100644 index 0000000000000000000000000000000000000000..501df098f139e041fb8e53b27d4e525982b11f31 GIT binary patch literal 532 zcmZ?wbhEHb)L_tH*v!fB>D2ohhK66ae<)^VKC|M^r2I**u6;H(Hcm@R`~Uwx0|rq1 z&+X?L671|4;A*62z|06#p!k!8GlhYZK?kH5WGn;A8H1CatM^*GKD+yWf`;GWf~m=7 zEX%fT)7-i#-QoC?*ux*sgxkd=Et`C^OZonS136+|+vcy>q9d^`f_bvm8o5mm4u@sz ztvlGZSuEUa_1&9JYid`tzYYJn!r{QR`1vd-pl+Ja~NX=9A~QoG!89|o3H`W|nxu|Vc zYjau6gLzz$A8#zUH|xSnvu_IeQy%14MfPv)=VB==s?24nQ*4N8E{D2qL+drIHac5Hgq*vEIpZWhk4FrtOoSA8CY&>&j+W-Im z8IXYDe{Mh5kYH!W09PYD17=2`l;TeoP7wxf1|5(xkg*IbFA7e2uHI|$`t0ui2^xJV zne#GMty^QZ=fedr{lxo6cJq18f4~y&RQ59cI(|m1H{}t)1Uhx)AW_60?42)e24xQb#*>br|eT+T9 zEK?bn+S;ddO-q?Icit3+9*3FB=S)t833t9FjpFUrZVgLT) z=da&?WZC{RFmuUh6to>|<`9nS!0P$egT?c?1}j_FXfT^^wV0E&w%%;=&Ry1XEDfy; zw2p~ww^ZZe;y8c)>?L3roK?QSaqiZ|3zID`C|-X2D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B@rM-Kbm3bPYZu5xaJSYlFjZ7m7uI@uH@37^XP9L*N8~j}TTh+rUNtRe z(oFl=Q^V(5Y8q*;Sh;HTO15?D*;Z`WyiR4ycGc}$*X-H5Pn8qw<^WVTFTikfO6EKb zlQnM&*16~izveh^@wU$S-EnI_|F93Dsg7qS1Y|s#lrmm#H$FHTmqb}Prw=KG`EzWMn zG_Ts3`BUdO&6^Rm$VS&xb2Sgp&FfV+Y~G-_W&74`JJzk)yKg_#(ITjho`d0NtO0E^ z&!1UEq-X2njo*d$Oz~XeZLo)D&iT7VQCnl0ZC*X|W|&c)#!&u-h2>t>3~4_BVb-Qf z2i~j9A7bMw^Q+xh-RsJ7D$~s}8|1<(94oqH)u)<<4EZp$;}eb?|7)phe2C1^}ANqp<)0 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/rockin.gif b/images/mood/punquinheads/pink/rockin.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa07077bdbade4ff65dd3e78fb25bd1bd2351d44 GIT binary patch literal 1694 zcmZ?wbhEHb)L_tH*v!rF>D2qL+drtz619J&ac0GxdG1>#DI9D~i&h^YLe+|4T)_IK}R*uHm9 zM%5Mu#?uT_IZvHgySPfEZ8;0e1;(?Tw-|2B*0^^4Ue6Scdpj&2&$)S^`OpJH-x}ZR zH@4k)rJhesQ;VEM48tMTD<=fCEJchuh0=Ux%Kp8&rrIv{y5C&hb3{bWYZ{zW)an6nL<3^|{VTP>|5#3RuyPQ)`J1E-22N2xT|Jx=rp=h7l{`C%WoGmA87%YWW=|AiThP-tgJbEcm0fFQukPECyK#Q|mId3^ zFdXVT#IWnY{_NWA423w{Gve{Z=NUL}O*t)_ni{+5azHs8nxD*kAbMO=h6R2B+oSjtpTwn;3Z) zh-&BuFkJjm=y+nX`67!a;0rTj}RNngh>rkOIc>cSJidTo;$C38pq<D2qL+dnXz`Oh@>$e9&)Cgo3hb?vjUv2j{j+W-Im88Cq2 ze{Mh5kYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=wiulBT)o%g_1WG36Eyl#GUsKi zTDK-_Pr*g6^@;b7?Y>qq|Mc>v{0!zvE!z(VR2p|pXlvf0p8Bk><%vl6Ucou@oy>L~ zsdZ0E@_)cueTl8%&b40d8*QJBxjB9?hOyT&Gc#1?$tJPX);IPrGO$!t_qSP0om|~r zY*#dK=B#ArNeeQ%7MU%v($ZhDZndtVf$^5D+qUbrv~cX%%dx9Peb>Gtdk!$G96ow< zm+JA;#|~;9Kd|H4bz?!WM*>hivKfmCav79p=3a;gBkJ4hk$c zFe~-Ec&T6o(`x^DlMZZox53KkOYj4uxz-<7)a0yQn$}>$ZgzrkXL$!N&?AxTwM>i^ zRSKyfe>5{Ou(Wq{)wMbReK#R_a#yiq`NTPM)7&Ob%I;iRxoEN1s^v-RTuf~Zw{y;9 z26|-gE@t(a`;P28ptAeusr{-4PVYacdEoMntJm}({t!X+$5t%J9IZ};Mlv5WA_I2-TRO3J-AW%$gyL)RZpBben|7g!JXG{ zKx4#c*!To3ZDGqK)Jt3SY@npo%-G=5#lX_m-dWe}&^K{XCoo-2NUolc=C*KtP{*Rm zc}u;PFHB-GH??KjU?{@OthIv~7$^I7?^N5d|LFdMDtnHdKA?K=%z;B12d`|qcHK~r G!5RR;8QZ1+ literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/sick.gif b/images/mood/punquinheads/pink/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..10adbf5a93e65a4c77e9c123f14353ca4b0ae6d8 GIT binary patch literal 1372 zcmZ?wbhEHb)L_tH*v!fB>D2qL+dugFN}pMAXHx#8SJytLr5UFIv9a<0|Nj{Qsf%Pr9oL+el>A9-qg={ku1pO zY*4HtGbJ!R$-=i}_QlJ8F3jr^XJ|+YYGBCCS1x2=>}H7M=;~puDPU%vz}TBPondNw z$F%Ml-m@pyPHm}dnHx5>qH^uLwDhUo8#WqQuifS6E^KSF_u!$!M~*79pE${Wf_Q}s)hmYvz$NIxuPeY9s5d$HCq@b?*FyiUJZbGPrEzjx>I<0ns_ zVfEID!Q!oDv+5hb-da8h=qqNX?Q9@V?b{CY)Y0`P#F$R8F`YSk?%bto*Dcv^-Dbaj z=l-oT4<287{P4z$m#^xm-pr^L?8J|}vC?UKlqYo~Wyy~%mw8vBL|Ozh{_pFe!G;l-sF@1EcN z`04W(F|3*FIGMf-UiF?;RBPkC7X`DGc-rE%${gfob|#oiJX@9ip0(;{48xDT3Qlzl zPE{KD42)e25geV}mAOi3%>9f#8Pgb;+uEmgP4}KPcizZR;vv zw5{I>PK$dE=rFMzVLK?wbol78<3cA-pE-N}^jY?kmya;9A7HD2qL+drIHac5Hgq*vEI|NsBr*w{ENEe*(Ezy=imbNji5 z1UowhxEkphFf#(xDE?&OG-BXj&;h9j8Oy+OLg1w5>b(}P&+h)8pwX9-IWJ??x;18d zK3wq9PrQF*_qB@orbkO<2 zAcnb&Q`VwS;tVU}F^inQvig8D`sdzR?x%y^RqWe*mHX#rEGcTBctV4TlT%{Fhr>^$!! zj0>F?&tK);*|n0PCu-_ChDqfsX8BLsxofxgjENgGbiKQsPbTY!oZPVSxW!p*pyzJh zl4ieqkNxKTM|ZD1es=xYliRP~ynRQk_txdS-e+KT=F5k3F6)FpcfEI*_tr!~q>pt$ zV&;RHU98I#XUks=_a-^l90NvRMefBvrO#(JGI(@8?6bV<;_-#E%}cq+Yl3G>z--Y% z;|ku(O*;Z&^Q`X{GWJB*pY#g6wcBppQ8tU58Ot|wmY1_I70UZmCfDbcG`Gt6u*BEr zCR?;9Phgl8!ZM3tT3?1U1LIPLdbTCYdT02rVqEUNa_I*Dg^SkDkDt4RVR|*wygBo> isYN)?X+COvJlMZw`;6n~FX-Et=--sY;yqyOSpxu%jjeM4 literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/sleepy.gif b/images/mood/punquinheads/pink/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f4f316d9d57d6685945d00a15ce97d4b9793183 GIT binary patch literal 1270 zcmZ?wbhEHb)L_tH*v!fB>D2qL+drIHac5Hgq*vEI8yg#+`Oh%(3`1I4+W-Im88Cq2 ze{Mh5kYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=t{I&4)ZVq@(&3%|9<;QyCzd5@ zO>Z&@Gb-@h}?i*ad7R_t$%dLH#f z=v+qAbZMjI_g@*zHfp$i{!``Oy7R@~Sy&tMo0=-Bm@-;hn$wx;QaiiK+WICqFi)x} z=+Bv%&akj-A;YwJoeYetma?v8S-F~JZaovz2F5k(wli#`NtA&h6cIlQSXy{^KW4pFMwJ>EZX}wa2q}ub+Q>^YYvGA3sF} z!CnnO_3B-qS6A=-l+kPLs&GlxZD(bMQqmGj**J-?)mNnovaSlnZ?(MJZnk-6i?fP= z<;SIYj&p+h=VVVTx9p{aIW(o7bH<@v0u@|QDAo$fP}fpH7N zs_mP%&fVbA&$N?q+jiCi3`~oc?B8;*WA)J!C-<+YSbKcWjN=OyT`S4BS$?ysg!A6b zhu0rxWj=nB8e#O-_Wk?EpT8-*`TpbMpTGb9mncCZR|M6^!#Q$|MvhlURywu@0O5pO Ao&W#< literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/smart.gif b/images/mood/punquinheads/pink/smart.gif new file mode 100644 index 0000000000000000000000000000000000000000..e57d8415be09376c8952f699b5f96646be6251fb GIT binary patch literal 1545 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 Y8RX|IsGp5c{X7zqHky}*ebTlD0AvbQL;wH) literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/spooky.gif b/images/mood/punquinheads/pink/spooky.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab806f5e1757e03a49500a06a783eed19a7ce200 GIT binary patch literal 1867 zcmZ?wbhEHb)L_tH*v!k2ZpQTK3%{|ku|*`SR5wFLCQr5nlY6R!Wfa?nSmtCCrcVtl zX=!Qy|NmzI1I7Q`ey$}8CcG2IO(~1uf^-L zyZR2@0N`yy~^TAR>emkn#Vy-RYB?|8?zIpUmqphQ2{qN6)JbmsXj-gL0VZg%)e zzs9Xq8&8UD*L+~L@M&I!i5|Pi^H%A9G3_tj9r!)7-dea!zJjYNw9>7DT?$K< z?pr^B^Z0@CLlajwoXk0N{KR=v5BK03H*ej(qrh|j0nhD+PwwA%`r_t`XLsMed;dXj zWOz^mH3m;3$6#Md=DZBoCD$IvX?gEFVj#HM=6cY&_uKB}J3anc*R>?bFh@nav(;qQ z6x-!N8QZFYGBzgYZhq3rwddl?pVo3y&ojDKF;4fst!Ql{F#X-*K+X#JDz2LFYR|@I zxiZdlE{4bwPqwJ0yvE4l#O|31bK)~+C>8ZHtXR2fWx$f9fxtLiQL}jy!#tH`C7ZVG zowT+`VcGHn8z*s|JXCpP^4g};c}Gs3x~S&u<$Ft#=kC3G_V*v%*L?i!$6 zJ%91?)d)$OXr;?>|a1^^DUWaj_? literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/stressed.gif b/images/mood/punquinheads/pink/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d72afdd84fc29770b69f97e241051e1d19e1e259 GIT binary patch literal 2520 zcmcK5X*8Sp9tZG$9uZZon%2y4+_rKgLmJdtDXJ=3Rnew)ZfO-QwZ%Gig2WnHK}2F{ zEu)e_YpJn>pb4=Av6QOna;H10xA&UqIoHjd&N=sLoqKxj^6q)_y!f2&_xJtV*q*>0 z_SOPg;D#Jn6Ro_zvpQ0@P!L-1a^{_(q2Z-Vmo_#wkQ)l8k2^Wyj}ea>=<3P90078e z;PM7Q4roiir9W!{Ak!SvvG6xNku9ei_iD6rnlA-J~(grxONsv7(NhvQ!G;=)Zk1AOy1`p?s>YU z?p+E$^GxwvXdH|J>`ws-EFt8IfpT&-HB*+J3+1UgG7{X%N?FW!vv_9M4Q3GYx|$}} zn0po3$h}?Hf@#Kfb@O_#h`xSA*MP7OH8_kO9_k&Rm_*C}=Gea3A^6ncf&Zl_%}6Qe zW#wvf+l2Z!VQBfs&U-lK($A8&d2o8)2`9`h!|IlGuC=^uK=d<-wZf7{3=4IH%)Nyh z*-h-UTV89^c=viahLnf5+lVDbk_djO+8`?+C<_GZQb@$hCIH3&J{O8h;ADD%6~u-y zORE9?x=R(K#?8B~!V6Dxpw;gqL^|M`|A6M%@SHU}c_AEuo=9U%EOqQcOwS-DX6L8J z?k|cL7bH)f{^{qBv`-?s{lB3-1@1m!CFti~WBxjg-DJC($Q2rRUNxHtfKv!Ck@V~@rkI}W*_4DJyFrRZSD+v0mba;D!~&Os zhJD0Xf=%0A4Bw9Lj^*(q8r6*gH7Ar1Q`6JvnYkI{{Db=oi&K;TY}yw@^dHiu6r&F@ zyi->x>v)+rZ+AWriF0NFIVhA2Na5c|DY;Tg4h^29O1uWki(&wq%q)my$0|&&OeIjt z_7MYJY^t@mc8%^>Zev)vx{mP$DcY zUN#d@DTE!ar!8D*CxU1xWU9WRuOBtUEF`}m+=uFBR_|#|=Q!p!9Brz1YB`Ll!%9c3 z7mMg0Ky=?7>_-iaphrafiAl-UtH%E~kfG}Yg@?B~#wS)^TCnv5zrKg-I*&Um9iqvg zzS@2Kz=lK_?t z&bephz@zO<%^WNtC?A$fD+MJC+nwhN&z8e4m#0=M#$+%PaLJX%>ED+)M78YKY&U6d z>vC?dEJR@%u%h9SQ8Z$F0wJ259!Jg0iRUC^iw~E6SA8;QjsF)_;CzaCGh43xwW<$* zrAs|&6nKh?a~6!6kq@9;8bpU*rWZ3x;&6#YriMihQB~@iwI;QJNKS1-H40;nZU3pG zvmL?fL3H=_^EC#9Xd$m_WONMsWuq)zfiGAyqGjY*rNOZ^gUa1B!#A}busIm6EED(( zn}SRpC7d)VHZxG~m9tiePmG8?`Mp;x1d(A$);S<6(~|0R%rhUCAL&`77`>ex3@mP3 z+fm`4C*!nxh-|5t0y5$hPd_KDGZXZ%GBpej=@}#5udlbH#FJ<7f zDE^g!6&kE^CClM9GVTZ4v6IRJRi~69(DIavPBAKaMZ2&P3^pce@x|Gk(HZW86>aT3 zxWI2BT}>lGp9*f2t#Q0yDf&V16rdmPOu{)OrNi>UMOly!qsH4Fv2evhP~p{r%Hr}e z`<=d}E>%=RZstwJ#H0$c8Knl7olx!?_tSoCw`q4L-=n*x6s6OQ5z8SaB@*=1>=g3e z{ki#t$?->zpKJ~L?9tqm&wm5+)R0^E34$j{S*rg3xSWf!(#xT$cu0@Nvj{*1bckun mWS5mEo29Xi9Ade~)v04SrW_KoiPL-&rE?V1t*~`IW`75o@>@j! literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/stupid.gif b/images/mood/punquinheads/pink/stupid.gif new file mode 100644 index 0000000000000000000000000000000000000000..160b35fd7ba1d47a45c75f70e75aa8c45e8c2f58 GIT binary patch literal 1089 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 DBk!Dq literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/unfocused.gif b/images/mood/punquinheads/pink/unfocused.gif new file mode 100644 index 0000000000000000000000000000000000000000..2939c3acf022068fc4331298d84f3d8ef31d0e84 GIT binary patch literal 1111 zcmZ?wbhEHb)L_tH*v!FjX2qRPr`~_v{$W!7q*vEI8yg#^rKSA`0|snB@jthpYe=xO zV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEIS2GdamAU@%rrU{|Op>DVg&!R;^oOw&%kI zFa5;(M|K~xSvTL{&RR1QK~C0%Z#AT^PHKI@DU#{)3HtZhi*i#q3K*H%>MdH^OY@rB`k6XdCUiH-`%ak{HFnvnm97d;Bj!AWKmP_hVD`yGCFw~UhuTn|NSns-ivufqG zo$F0B7Pi?R&^jc1{MZq;GrDKaU$~%o@yZpgtCtLczPSVOjR;}iV2zvBeU61CIs$Vn z(j8|e^DzXi)ct)%kYUpW?%S=?cE@dyD0JmM>ulW0!^ihgh{)c#g2_8XGS1eRy3gr>!s~whS(LNi>C|Sh+r_V zQVV*DWu?-N&eXEbE;#2lcXw^aavN>4t5z6Y9(r15)RQ&SUnL-U=o?2?^Zcd573)NkET zF5~mKnX+&2qDBaVq`CRrvk>gb_wF#+D&GYySsi}4asSPI%+f=fx{K=q6^@akJ&D)_f?!;(Lx0 zsfTLQiIb-*E<(o-QanSofp<=%YLO%GHMm8uxpBQQujPELin^^vWJTo!*4ed+?pa~J z*EgUvmV(F3Lrgog8lWRiyNx1+4(F(c4{Qp7&p!ePRve8bo;_hw=}dTXis^gvc6z3? zV2-Wm|6%hktT#j9YU#%RZ@hItwiXO-eo2;HlXZU3x*io zqcXseIVf`7@Myi$AqA2#G{6V3SR^DGk0g@GXOCHqE+za)_wVJBk5G5iMln*ZkQL9- zaqdjYuG$Jd&{}94s;cLsppqg{ht%hi0KWx9W8)#wL@=K4xdm)Glg6jm!QcNm*Wc!{ zhAz3X_xaW0HKM11L!0B0{JsQ3T6XrtXQ5LUjvZ*`>8tg;Ga{9NTPCfr;gaTh8`7F* zI9sb~zLkgEtm0BxNXUvznDTCI#d__1jc%}+#DUFbw3roQfVw>d3S=%%DCD=g?J;|F zG&~uOtYx34Y}Ry!e)amzTYTP3F6^evL(Uni2t>i5(OAycdTqZ(_kbd00CbRcvxFlf z>@Hw)2SY(W?n1q+*Buc?!^!dZL^?B>ntIWbvnHIE?XRuOp?Xl*p2@0T1-vJ}K B3^xD( literal 0 HcmV?d00001 diff --git a/images/mood/punquinheads/pink/worried.gif b/images/mood/punquinheads/pink/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..c843b7efa3966b80fc91a0dcb756894d92604141 GIT binary patch literal 972 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7BIt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6m;N_+p2 zS$d2I_Ido6Ws%+n-x@*V!{Ra-Ja)O;5fa>hU7|u?~ zoTp*3=1svm7aif(JH(3PuH1KcU@3d{F*8%^e#PVB+7_kfXJi`-oS1VwZHmH-v{jqm zlwMmJ)tnI-$*jh3FY1A`Ky>}uh6cF;ohRR8;v_KSXo+ZdS2%DXJPddpi29E*FJ za(dD;X3q?1nNvDrzO44_6*j86I-2WvfzIBfx_R4X#qGOx?A*O^{egprpzanyb@xIH zcjE}|^WTFD%hug8I9V-e%6!oKr!?2R85%j3t+D1&i)MUi_2O(O*>u61Ip%4Pn7|6= zHr8Epd-l4pRxy?bH!?647B!SMnYDIwHe}i5wbxEacWLiWsGm_Vb(*aDtR>*kUIh&9 zHEbI;vaQ;*b%V;bovJ&xuiLl(0MylJi3G2!w-v~)zW+e%+v($SvI{?~{#&=Bx6i}G ztleR0!uKzsoJ}fe26w-9ty{CjoiAHIMm)hccOBz1Lj?!+2JSBmF>4-jJu6LUsA8(A vt* + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+palefaces/
+ +
diff --git a/images/mood/roshi/palefaces/aggravated.gif b/images/mood/roshi/palefaces/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d44f5629f0f4e3622f68549a63f96a50d8c3c85 GIT binary patch literal 862 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91>)eKr7Ascm+OH4Q6NJe30N4KPL(vb;@yTf^IZ%#d2X1GLLP{K5a zV|(F-9|h8;2?8H&AG7hv?ycBhb0hhRsH{canTWcl$9rU~tA6}oWbqJCe9=7R|HH+{ z`(%u_#6<=zcH?{bxPFfR|K{4SGGBEW1%#bN5|0Ras4QF{#G^HXMaW$u@Q8qqNczK8 Ki8w(H25SJ%ZELCk literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/amused.gif b/images/mood/roshi/palefaces/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..ccce6019dfcb4c9779a5517817ae4219a3d75ff3 GIT binary patch literal 863 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 I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/artistic.gif b/images/mood/roshi/palefaces/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..18ee0bd4d8659f3bfc77add55a1478241854df40 GIT binary patch literal 1054 zcmd6l>rY#C7{`C56eOKwEOC~EYP&7jqPT1`Y8gpGv6oZYa{^H##tSmT0*i);)h!y$ z;q>&n^?X#VkXR=w8YYCk*l_7=*+1d);(7JtlkYd5 zMDmkH!O${ffM~Ex7h}V77JAPw+Iue*k&(9Lq zuO`DGA~Kf=`y!D@JQj_`V$r2!A|4~+(L^F~gCH`?i?_bNnaN~+xP5D7WhI-1HaIjqLc{nY4ksUL7Kt^O(}syf%@|t<#PA>(o`f$6+1N=)AQT0@L12+k z0G-5Ge15dW4S%;hFKS6;SXw^sD~(&cHa+Y zarXEG#5!%%q8}apO(7bfo~~GY68X7iq*0ZB(Dp87ryhUnr+ZAp7;*W5xp2?$YxFRn zed=rHy!UL%+Z`xu_BSuRPVIeuUtQ~BRPpv3o-eX1q*FMBv;WKyC|ss^>9xr{caG&c z;~ijs-}3p{acP%Y!)m{K7Hg`a>l*$Hru)hA+wL~2tH~j)R#!_d-ff+eoY~`l;o6Tm zdmEWrbD#;`vGUeC#v;|(hQK1(q-A)rUam7{QS=fOKbl)T7 r!AB9vfLertN+t>e02d?T3OSA-YMEANG?~A&SOrAwbaeY$n) z*1LD_u3fwK=+PsfV#WX5ey$>XzuqP#RUQ5fIoNkZK zMIkw=>XQl?yf|mrUwV^pLR6+bZuJri3oh3K42=#(DLRseJy|^kyRW;rO$$80@jl_= z1QxZPiaWNMI(u5&e)9@2JSncJtI}ksv}j^rFS73B*r4Nm*Gpu;as+KSy^Hz-o*9out7rJ~VR9+dJvmf{#x`G!mvquuco8d|_O7m(^d=_gW|mHEgv8 E0QgkSUjP6A literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/bitchy.gif b/images/mood/roshi/palefaces/bitchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9fb65aa360cf6ca3283e32fe160e41494b03a25b GIT binary patch literal 870 zcmZ?wbhEHblw^=(c*ekx!@&2Sf#LuE|9}7f{qyI~@87?F{rdIe$B*ydzkmDo?aP-h zpFe;8^y$;bk00N^fB){?ySH!OzIpTJ_3PKKUcGwx^5u&cFP=Yt{_NSar%#_gdGh4( zTLUxOVN@)vH&pT)A@j^5sjHE?vBM z@xp}*=g*%%ckbNTvuDqoIdl5-=~JgpojiH+#EBEfj~_pJ^yrZzM-Cr8eDL7G0|yT5 z-@kv~zI}W5?%lIz&+gs3ckbM|W5IMm>+9p@=H}w!;^gGy;NW0qXJ=()Wnp1qW@ct$Vq#=uWEeQ01F{+v z7YywG8$v^Zg8~Br{QZ2pdwl);+XI7wLqbEtZ6s#R7N0v$eD-Xc@M(_BOe)!o)S-HZ6^>>&^N{R5Yvz%VFmxY~I zL`u?Rhq;`BvB2OBHP2Ua!?9)1yN1v&E_mf=bYd#iK<940(yY6y4e*m3FoslL|J zOja{243iuLt*gE&1U~X=h?7@#kdQp6d_r5*wM*E(iqZ3;lWV7-qFup>2F4IJK6$4e zjfIO`xfG&K2k(eze3Z>0Aa7Oh;sayLEg_At9Tm5=J06H>2hC7$Ols*kt}HRzW8de7`3HKR43{{$3>>k0^-JLM>-Uf%@`OA^Ukl6Ro>RExVPiL zip0e`dT*bYEWJIDnQh_&;KG{nC#9kZ{NVc*<{o4 zOWv;P%?U&0*HcwZvz~0|`{yp8$iViIx#rf>3HOB<4Gmoc-DDbFgaot{6um%9rm2N5k literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/blank.gif b/images/mood/roshi/palefaces/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..77fd817e13b3753882430c7e77d2d11a2e254d3d GIT binary patch literal 900 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 literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/complacent.gif b/images/mood/roshi/palefaces/complacent.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fbd616cffb4d4a5cbc289f1d1ea63119754fb7f GIT binary patch literal 867 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z^03WeYgTPu!6X|Ns>Qu^<$*N^!Z^6K_UH=*M`ieEuC^k zzDsUov>s~V5Y`az{a8G$Usx+Z;z+vAtw(Hj>y8PE%5FT`+tTkI%e`%uEAEuW+vvEs z?V}Xiw|74U=9gK#Sk9vB&Ee=G=qA&6q}kKuhk}s1L?DZxlg`3B LZ8BQo91PX~8B1jI literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/confused.gif b/images/mood/roshi/palefaces/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8ba7dfa98f61d6c5c7850222b72049d7e02b8d1 GIT binary patch literal 404 zcmV;F0c-w8Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`Td>gv+c(&pyoEEpX2_V&8E zx}~M1wzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E*5XecZwdCl{J0}wpjAUt^ zj5M5VJ4i;7RBR<1l28CL37Ef;3{VhA9GXI}B}^1F4hdl}I24q!1S#u$QbB+zmBP(Z zr~~k{Aqh;b@b;vUmM9u*HvmC|@AQ0l3U&=RfPHa?1`UG%cQ`+9esVC3b_SRfNmm*a zmkM4g}cP7und(!`IvdjS~vt1P-hU;0o*v?(gsH<>!qH&Din^@C^Cg4hs_&Fjzpa ypuvL#2VPjna6$wCA^8LWHvkU+ECm1q01W^H000CH5XeWX4cOkGH3ywFMF2a}-<~W0 literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/cranky.gif b/images/mood/roshi/palefaces/cranky.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bbde811e2fabebe102702088817b6b2975ba46d GIT binary patch literal 556 zcmZ?wbhEHblw^=(*vtR||Ns9#ckbM_ZQEYGdbMxgzGu&#-MV$_-o1O*u3a>eMNqV#WX5ey${9vKu=2MyyliUIo%$I zl(w$f!ZFEN;1kb`{U?*2pOBQ=bMgHa88aSN2gXK+PhxA1PPnk3X-S9k)q<rdFYj>LmZttd_nuW~SLS{zaM7 zIA=4>TwE|&wmEe$SK zte3<^F0mfGa4m?nP4V(IzMFTLpFDl`?9xLao{Nv4zkkWcBh16h^Zm!qU*Er7`S)KC z7$QGe7`Ykv8FW|}I2Z&Oc!3_){LsibZ||gM3qC#(S&=Y3f^}L@uU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;#jY^ z;l~FllQ^D_x`&VT${Z>Gka2S2aSd6^yc-iX-s$3(v?$r~<>O=a2?{S7r(8ef%+4nn zwN_)HBXj!~IlG!U{`2>@m&$z6+;~RFNg%LA&|P6+f)I~Z#}Pp{5yut*Z;|wetrAg! H91PX~9CK># literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/curious.gif b/images/mood/roshi/palefaces/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..8647a76ba72605692ce0d1479921bcaeb0f0fe4d GIT binary patch literal 510 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11>ZQJhMyZ7wbvwi#aS+MXNJ9g~SrAx0~y;`_% z;ipfZ&Ye5=?%g|}V#WX5ey$moJ^~IL>w_N&GI`@o5|n?zAgDefanp^V_$I@7~_wXy?Ao_VMS(&m7#s+{|Je zG9DWi9B2?1(wZZ{2=YCnG6O$@4l4sEkYWM)UPz$f!>X;qGM@Q&g>O_UJ&%oK!LE$O zVgBBHuc{AM*N>P literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/cynical.gif b/images/mood/roshi/palefaces/cynical.gif new file mode 100644 index 0000000000000000000000000000000000000000..25a53ad00ecd092a798d970c830b3002098ca45a GIT binary patch literal 865 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91}8f0v1bq%aQ~^Zr$v znb~-RB_&LDnaj#c3G;EYv$8OMW?^OL<`b5Zmo?vIso+wxpw!i|shM3=;Ew{6OJAh5 z%Y+rKs~cUrMbak*E$K5f;M`1+RrnY)u*=bAA|ddvu9udG&BSOk{53USN>( zK_JP6Q&jg@5W~w^hmLZIBstf7IFQK9&M$v!n#0CJt#=|Fxwc0voWjy6sHD_iz*FMN zy?gySmP|orH*PWQkR=|Ci@s!tYDa8o5M1o~Oi?fGOoyN|+uKOPg6GS0Zy%iy>5_0| zgX0~xgO88qUTJV-`Ozb7QBv~c+Bxl5%Fb{H=HIaS`c=*^3VkJ$wj99vfK7yWDR zm$NQ9^Pno#vscP;#q|FZ>;Ce8zy7q~zR(r}Ll;3enMM~O9<7H8&7KN{ErPB*2agm= Nq^)=;+Q`6Q4FIpCYHI)h literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/depressed.gif b/images/mood/roshi/palefaces/depressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa10c4f75ee38a4b6845ce24519eae424e1aa5f7 GIT binary patch literal 884 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@lR|G)-=2*v;0ey$M47M9|>=oR^B`B~#xKY%&=CsfWL3@Vd0w-rQ7Kqj~^q)9+ zh3oqD4RcPvm~-)oz#{>E{wGI1?|t&&trDjIAK!<6K|z0PAFwMr?rY=~`sLW-k=R_v z#;8&-VM3!k8+XdtsD$RmqwRv?79T3I8k;6-Xa!FD^1>mEu};N!mXGFSW#&58C;^WK zhJ%gFY)xFEzc!~cG4V{+ise#Z0finTKZ6W|4hsVZgCGMNF!YQRLL(!l6=uvz40H9J zQW_hPo4on!p~X}GO}obJpmMHmx>BIh!;@*2*IOhryXrJost7TGjp1UDX3${<8Y9fW z3pB>^!8S$}g?UMt%NW8JCI9ZzGdPfByGC05-G*!LT~>XJaC@Y)glZuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91{W;V@xAQ$x622gAh0*ZBlh zrm^NYOk8v%PQ~TTi>u8pobh`ZVj4dzP+^%6?lMi`;^OK2!s-ECQy3OL+sL4}evZMz z!%I6w#McMR5J+TdU7%U5JosHICx^Ke6f@53b4t__NI6%RHvHn;QVcrS=}sFb%}p(T2ahgZ`P4#5fTCjWLW za=jZK-n6BIaWQMRs8-Mt2gj%_U7|Ws2Rbe?eHIWmPCL?}m|V7AVteNKzPCvp`bq{_ zH#RhGusHP4G(q5}?PE4RS?iJy8J!#0`CnKS+?lcQV%%d#&YJ~DGmP;k1$ZutMO zd%vt@TF%~0OWb;8E}#7Gu>PNW^=r!;+g%)dcmi7l-4!MtY4S4Jks#zDljtJoY>;@T LRYFRfgTWdAmxOMd literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/dirty.gif b/images/mood/roshi/palefaces/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe7b8c277c1b5425649243dbe4a4d02d44ecd2c6 GIT binary patch literal 665 zcmV;K0%rY3Nk%w1VHp4!0M!5h_4xJ$6$$6_>iGQm00{yC9S3c`euBr4n98BU-N>fT zt*_R$zTCsm=hFZK01FKZ2M7oK{{8v-`C5`za+z=A=HlAk*p#D*^YrqvxT%bnc!`gD z*xA&_$inaM?yRe#dUH#JeOjEGm(Hq)#{r&v}1Ox&C z0ssI2EC2ui02u%o000L6Kwqz?fu~r03JGN9hf+*ohNC= z$fn8_z$a@yS1!%2Iv(N}7#^-aUlwaAEiW^hJFXTU7CJict|OkCA0)Z)KT7;Sz{o;{ z9{>gB$Z=y6ihT)RAxMA?;U=1S5j2l>4fCv$y#Zm$yE@-&$0VU6|8EwX35duVs7BPMhxIm!<2n}_eZd&t0FJBNK z0RIR;VS;54G8&#cx3@2d7lA2HC^3P;g&#LuY_|D>@8!S+DqA*P<3nl}E^d5q9Ad&} z*c4=gFku@v?i;#gnCJ|e#^eH}DQplyy}ES~CbGwf;aqTl0tEsPaIm?&`5*v0OnDo_ literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/drunk.gif b/images/mood/roshi/palefaces/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..519de5431642006b5bb7613b749b8beeb537f13a GIT binary patch literal 821 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$d)O3GgraBpxO~~cU@|+&@5oIZeg27ugLbBDI)6v4cx8mlBDU6`V;bf!)|oeF zo|o1W5iSuc^OEWatVwASF=OBn7HSp~7nhhZvsPTJX>vce(Bu{|hFKB}2BPzXxRn+L z>oQE6Ic*bz;M(;8eCwU3MLyn8Lc&;Rbk??3N;2;38LD0sji&(O@i^1)$u0VgIw zPC1JV2f+(##YCk=YB&@Q9%18gGHSS%)Yv;g#6-3r=7GYKrs-Tsr>6Y8q{7U8flHty zvUpk3EHh5A3`Ye;r^}}rcTH%5zN|(BJFD^QnV>SO2dx_Uw13yKu5xO8F zm>HNDgc-PjM(8})#<(P7-is4!Q@xm!4$Rb!x^{c&JcD`fS4b9k=tz}sTAZmMBsWv~ zxuGT(BiH~ogaN`p10o)5D+C$9u_o24Xc5~CkO6aM0S(ZQE#O!aVK6h6EqUb(HIdU# zn;a9DiJfv`F^wvlwrrXjQ%r#P+yJGQb^ebyZ(mtv5iGj4<;45n{~N5G8e3|bF z%oUGoIa-c(C=0Jiwf>YKCX$vS;_GuUWLnWutJx>@i+uEEpMP?EL)X2Hfjz+-4AubK CV@DzY literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/ecstatic.gif b/images/mood/roshi/palefaces/ecstatic.gif new file mode 100644 index 0000000000000000000000000000000000000000..74b0209f0d7779bfae26f3f404ea0e81ccd3aff9 GIT binary patch literal 577 zcmZ?wbhEHblw^=(*vtR||NsAg_3G8Wefyq0d$w)cwo|80-MV$_-o1O*u3fuy>5>7D zz^6~27A{=)=+PsfV#WX5ey$G~xYb_rv*preuueGJ;a^^Nh zB~2cOTX_wydz2)Z7#}~oW!Tgve^Bwv%sxIRAp-}68HXNr7K&J`QP6s%FuUM<%qa;$ zIT<0Lxhfw0{zB~qij33s8A=?@gz9TF8LI8-8XB7!>bW@EJIjiD`xqup=9(iSRU#!a zhif+5MD~*&Z|B|j>ixGj&)Il|d0Bb?Gca@g zdEP(!V6z}FXnwLVaxw5T=&&$wFbFd60DW%x!BXkQ?jMGZcdR*7Ic^#konZ8HsT7R; z#USpG#$;>nxoO+X8w-y|?^IcNr0`^p)%3RK%37r_XYAqto2HB~jSFa+#)n4Ed3z_N y38>w>yT#{VdT-3uh`a1-{5@OsUItF>oL%$&zk@elL??z*K$=a-aEcTogEassd*TED literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/embarrassed.gif b/images/mood/roshi/palefaces/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b23c27f97ffebd0cdb5115182fa582d70609da1c GIT binary patch literal 685 zcmZ?wbhEHblw^=(IKlt||NsAg_UzfKSFi5fyLao>t#|LC>lk$BtcFwQAkEb;ph!`=+2UbLPy6GCHSDo%;6e+pk~04jnqg!ou>( z!{gY#eaE(KTexr`&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kx9DxdTfEegXNd^Yie+mp4DarFPys{RZ;3&{JZ**DDaozix z{T(eatB*^waV%|&c(8?ubJ>U&SI+cTWxzsY_! zpX*-!S@xU!SCzQ=1%!nKHcdNwb{4yUw6uWOwdc~Wq@Nu7_vn|}hr{iDvMiip`xpXd z1RUB^#s4Al#D#^-?RITEsS9o>9=0tOGBc7m*$~#vqGBwWGbKT{v1KA>lHLr@$!R`Q zcvLPdQh1npa<-}Xog+6VJ8^Sy+i1j|+OqNztDCXcTrX1=P%tubF~~FMurP2i2r{q% zgV9J~AxGQenv7QxO->>$20U)L(wjdVT0G%j(=~1fm2-8?N`j3KPNrFgH&$kJ)oE%z z5@5n+jN$|Ko&)LglxDJNS#45@S-3ogEiH7{5A*$Ng$t%AUFupYfK3-UmRkb=0N)4) literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/energetic.gif b/images/mood/roshi/palefaces/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc62158ff8d0343463245bfa51a6f09a6a6058fe GIT binary patch literal 422 zcmV;X0a^Y>Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`RN3=rz->eABE=H}+1p`rHn z_PV;dwzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV6aWAKEC2ui02u%o000E*5XecZwFK$SJ0}wpjAUt^ zj5M5VJ4lD3RBR<5l3)Nb37Ef;3}6sQ92!HfB~%zR4hdl}Kp2!V1u5%%QbB+zmBP(Z zr~~k{Aqh;b@b;vUmMj`kM4g}cQ71`O&!`IvdjS~yu1P-hV;0x>w?(gsH<>!qF&Din_@C^Cb%?T3{Fi1eK zpuvL#2VPjna6$wCA^8LWEdUPyECm1w01p5Q000CZ@PY8EweyuqZ{1G-cHStF-kGj! Q>%MSY0WEz2HkL;KJFdN`oB#j- literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/enraged.gif b/images/mood/roshi/palefaces/enraged.gif new file mode 100644 index 0000000000000000000000000000000000000000..f73741861299e91a5da769a97940d3c657379738 GIT binary patch literal 833 zcmZ?wbhEHblw^=(*v!cAp8*8^|NnpM)~#d5j=g&I>e8i4&z?QY%*@=kZ{Md+pU#~- zckSA>UAuN|+qMm;Qt>~xpKD04vtxj(k)8oFBS`3??yug`?z;LB-m z6(qYZ?Mn}k77Dx~d}m3R!WWbM6OU{W(cqFwRxp&1;j(A#zM|x`dO>EW*_xTTlM82@ zieOT?u_OABM2mEfS;GImWagUuN?xG~n?}Yu)`l8JHl7y7HlgZ*x+(d66I$8kig-jw ziOgl2$j8RrpDf3o%(H?`lW{rs%F@+R$;|7wZWQ9%y0>!sy2=#?HyvPMIk@E9+=HjN zPja8WcG}kV`lXYnIqxTmKj1ul_kj@SL}A|S`z)JyS?=?G;rsUe`xayX z+u?akO${8vRt^OV7arym1cnhX2v|Wuz{nuVAkM%H3<53zU=ZxJXkJj=fh^4rlx71; zi$J7bpLJ%CbFWOfS-W6nm>@_YBP#;sPh!SMRxcZ{~frx!+rpzZYKN z%*uMrgrb%es#Ze4iz8YzP%&a3yDv8wO-pYVdmNnqZ5ONp+eMTr-ru-b1pL1gJX zQH%878Hz^=eQqqB>7^)i(x7LulFjS~EAuYxigEud+LygR+MsG$Q&4A(K?jN{Fdyq| zF#NVkS0dVawn_BV%!LOlcqIBm{W-CFhX70F857?_Z#mu<2ng8S(_{CR5Z<@s(~O2r4)^#) Q3wcZ?G%6nyWMr@g0F3Glj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz+%@&#%7KOpGg5u3Ei{$zh4i z^02TqTQ@T@$%KV!a)oW$zGm|lrZ6te-Fkuo94srhth&I+!XY52x7%1;LWrA)5g_JAKyb3(za(c3$+>4%q%Uzv9 zwrSHG4qiOP!YQEQqtV6mLPuULXpTii156A!iYN7@H$@Njfu>EM&ni(n{q zbY>S&I_kMl|!Er|Z8$lT5+XIt~<$HASStK@Af zUK~(-yjoP%B;&z>dH2{SC@?TRWUjgWaKe0{!#avAg02#UEJ6Zmii#~BGKnsNE*u+M Pie$=OEEH{IV6X-Ny5MA~ literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/envious.gif b/images/mood/roshi/palefaces/envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..a1fa93b52e44e59ba0c7d71881f726c8201a51e6 GIT binary patch literal 852 zcmZ?wbhEHblw^=(*v!bl(8~Y>|Ns9#b?VfkM~`;x+I8#Jt#|LNF)wXThe*O9dRH^u%+s`#5*x50_)kx2P8E625;y+oZ(#)I^h4Rdj3E4Hm)vvb$(`Nt3LI?T+)b<~yd z!uhkzr_Y`h7rB1!@O9Sv_eCGvzrKc*>oF_u>o;#+zSwd0<*T=!&#qzQeEa*)Th5yd z%x=Ii0eYDYo3JeScs1ch<)#8v{Sc8cwJZ5rGr#tM^>JH}gK*-0!W)-y5H~ zd4Uze+`|f2=pmpr*C?R-_t#nKeNRFP?@FR7WP~c@H)sGl{L`zmyZL6CHwLpHI}D~q z!a&4n_1l7jlsX~ElD1RM14S{+X3YYFvL;c-jJdfMmlp`IJWYt6WvQ@I zqb*QwOL3Oj-D6&Y()0TL#Q%sYVe_E;h8bU1*-Aw3_R-|tYCF@c?S4}a|71g*O-o*% zxKnQ9j_f>GxM^-!Aep7ml9_YZ#kHB|MADpyuDQpIlzJ^DsLkH=*5lac7(G+53s)^&0fP!CApigX literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/exhausted.gif b/images/mood/roshi/palefaces/exhausted.gif new file mode 100644 index 0000000000000000000000000000000000000000..4acf90a545857159d61c2fdc6c420202a5761b29 GIT binary patch literal 667 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkC_ph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^^~g++@eb|^@kXv^M1+%dCHwn(m4rn)xP^OUm6#bOOq|6qX9l;@biW02^7|#i zW-|y0FJV|Vi6LksniAKoM>D2~yy~8D`q}lT0s_zWe*O0Bli+nuL4N*E4D)RmIS$6RuqX+MlpHAV zpDD&G`^T9>;UIGxkCD-Yt4WP+Y&`M-F&`8jH%;c!4q6pbc}cmMeG}IYHWu+Ob zQm2OoUTsZ`%uWCN_0Z#~|E6E#c2F^^o9lM*Muu5>!19tVA1`OH3H%H)$R;Q%u=g;e p&r_ONre(EB#b&|sn6hU9yDZH2uN5wsqI9WisQ_4)4Mp}^0|0f~17ZLG literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/frustrated.gif b/images/mood/roshi/palefaces/frustrated.gif new file mode 100644 index 0000000000000000000000000000000000000000..56dc7d1c9c5279d8c3c250e708fb41e5b086e65e GIT binary patch literal 860 zcmc(cTQ6Gy0Dw==>1j_-v9^?UsubH;Obn5l%LK!cy4Q&y%kZ*g9_B@Cu?uqzIuo&E zGIR(-meQf3XhU;K-EXP5)xGX17NW%FSM1C8{ylu5Peb_L$!vfPYyrUaKd-N^uC6XG zFO5dy#l^+>`T5z|+3D%&$;rv_@v*^RI668yJUl!&IN0Cc-`m^U-QC^U+0pCu+uPe) zTU(o(n;RP&>+9=lYip~kt2&)-Wo2b~d3kARX>oCJVPRo@eqO89&dtru&d$!v%uG*D zPfbltPEJltOpK3@kByCuj*gCujA%5P;o;$-p&_+ejpMjVr5YR@92gi-DwPU_qQAet zudlDSw^uHg_w@91cX!KVvaYVK&d$z`jt;3*+TPyY*x1<6&`?)bCl-rqYHF&ht1Buh zL?RKDN<~qWLZKiCLMD@87$y>l5CnlBNFWe^|BA~^{pJNgzWykTjfswmjEo2u6qg9X zBMPFTV`7Cu%*XOu74v&Fv#QDms|)}MO+TAkn!$j2PGhUI1>|6H&M4OYy8}a=Wv+A@ zhT~E-PNTcZJgis@DhUFy7CA(sGFVm~GA|C7%`ipDFcCT=!erEx!RB(jWPDp5S3^NS zl0Y&NRCtRo+Cd)Lv)xHF-XmWx`&?0~Z%CO0)Wzduvp|2HeiALB`-=WJCFi8#B05)H zqARa2V)zLw1EP<$L<-GOpnnO&W2ydvdVbqJm{()&loX#~pGUF9-`76>l9P+jY&?@B zz-~^ynO$&Mm=aWdZgo;7H1SuNxdmp{o@sg=??I9I{REjG$ znQ<7US-L%w#Eb1=)Z$*?hX`>BTx{hQFSMKr%r{}Vr6~MKpEA<4zY-B|uMN2Lw&InG zHCIk5wF=7ANYWi}m5uXP1FOLSH??*zPc-nL0yC~(*5x_DvG9%E`nyw|7%DJn#VRIh yv!S<{wwvR|sK+*V)*ZDAk4S&QN+&XqyJEYXFivtXJs4>ld~Jcf5Hqs@z~?XIrCquJ literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/full.gif b/images/mood/roshi/palefaces/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..d99aec8742652a015371636e7c0672d17d2fb0c1 GIT binary patch literal 564 zcmV-40?YkJNk%w1VHp4!0K@~3^?d|RH@$vNZ^!obx z{{H>|0000000000A^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0?AWd&} zX=NZsWnpq4GA=d%A^8LVJOBUyEC2ui02u%o000I4AOHlUV4i472BOGVa4gR<(<)r9 z?|iR_l%8-%5k)eZmPn`sXfhGeQ9Us-f&SSMJ-4ggilI;6gB`16B0`;7?F{WA`%md3lfeTA_D-DlbisanhPSCQKFs~ zl2oby5fY{VsFVN~xVW~lvkMWwN-()FO1}}a3K0;o6M$s=2@nnr1HQV2E^zR1flCE2W5yh?z$60)vkLrc>2iTg z1wBdLbWorLfdmK;95`U0sZ*y*lO`ZAv8vUHApig&`2+z702}};1ONyC5da1N00lB2 zRasb;acG)hRz*#ebzN9(W3%gCIqFJ8QO{`~o~XV0EKefs3dlgE!AKYH}&;lqay z9z3{z|Ngyu_wL@kd*{xb+qZAuym|A+jT_glUAubq>Xj>3E?>TU>C&Z(7cXA8aN+#< z^XJZ;JA3x*nKNfjpFVx+)TxsvPo6k&;`s67M~@yoa^%S2!-o$ZJb2*1f&KgU@7uR; z@7}$8_Uzfcd-u+rJ9q5Zv3>jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{kS+hmv&J&qE+bVRLJrm=Km8({-VzOT%y?o8) z)lAZ%AsSrlo3?Ca=hE1rE5OgevNCk_sTC|7`~tc=jKsu4uV3GMtZiGlUdgSg@G6C)A`*VB=#cej!zdtd<80R9U8mdQEtcIO#}dd#H*_g@7Z|Ibq}V zUo{#J9Wmn;F7cX?kT{!DM71jBb72x|m!P6u!HI;0Od8yh7Bw7(Oh>zf?Uv0;n0Scg z8o%sLi;NQs8lBrWD*G%+X#94of3J2BgQ%hsOUGeFj@v#Po8GS0vJcx+u+hntOGMpo z#*I0Wu3VzpF?%9DT5xnr7{={sSorG}_x07Gi_-+3%n}ec&UmqGuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z@->@RGs%X9YH@Rf?cKY1-(C)GtsVM8VVo>0!&aYN!NM6Pq`$*hLQ<(j}@Bb)e%S(`Es2qm&~ZiK%7!x3*@U?|bXyv0l+2 Kg`$lN4AuaYE^EO6 literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/groggy.gif b/images/mood/roshi/palefaces/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a36b42716b7350ea0c8d4e6611154d2ff84af001 GIT binary patch literal 1005 zcmZ?wbhEHblw^=(IKlt|tgNh@oSgbW|EDoX^!4>knKEVGym^ZjEn2p0*``gKwr$(C zbLY;zd-qPAdhF1lLr0GuJ$drv*|TRaUc7kq>eU-JZrr_l_u<2bPoF-0`SRu4w{Jgw z{P^X|mtVhr{rmS1Xt?5kZa>$MU}whwS0ggL# z%v1&U)WjkMBRw+)#h)w;{0#C8Iw049+{wWDPl17DNy5AgFSbQD5^gY@E{M4waaphV zd3E!H_t&NQ#FS272#@*aV%MEv^uVF_@HGAnk{wEt49geCGS$s>R1+3FsW;O%{q>in z%@Q3i5;q<&l};`$la-N{k`%Ay*Ao*B(ruKP+@{OWCuYUKD=HG8E46Upd?gXlSv(^1 z57(wNsKL1 zd5ZLIoSdBQH-lF}z?ebs`T2R=bxf@p3tSmlIfWD)3KpyiT^+nwOG9AO>g($noPeSJ zlZ6o+sEiDZ4B`wTz(7rVpx!61#`kpPq~`_|@;-|+thPn+ zoeWb0ZnG|adDBd)=W^K0Fw-^bw;kG=U?gea*?cVG#G0cONvhBSk1riLMYRw6|3VjfR4YfkOXx6qUW>JUe+3GcN<1;4n8-_ z`r5H{?MH4d%9#iLI83?li7v0<$1lPAUhuta_m6oYY`W6uFEx85WYuf*Cf*IF&x-* IlVZ6w0P#4A<^TWy literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/grumpy.gif b/images/mood/roshi/palefaces/grumpy.gif new file mode 100644 index 0000000000000000000000000000000000000000..335119ad0d9c7e8720fb9c4a97bcb171d058aaa7 GIT binary patch literal 418 zcmV;T0bTw_Nk%w1VHp4!0J8u900030|Nl%tMB3Wgva+)3>gv+c(&pyoy1Kf;!otqZ z&hql|%F4>t*4Dnhz5oCKA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E)5XecZweIN6J9iTijAUt^ zgfyINJ4nVNwXC!l5>piN44A*kV#kmqG`!L8v>a*@#=+pQTP#@C-9ZWkIHWJ3b=*@) zLEb^bC)v5#fW`ogXsiPg0l>Wr0`ztW5_LFue|vm>dIk-G0EBRS1#pax2nLuGNLmLJ zm^u(=8h47;Dnn7hUb#0d$; z(m6TO4A9OJ1lQ1A7e?I-x!oWL4vrJ%f)3rS2ni172nYoA_V)AU?4i){`Skbx#e>$$ z)xCoV4}M$7FaiJ}`2+z$01p5x1^@*B4FC}U00bQH$sjAO65yw||6nMNWNDsgiZUU? MINb-pBM<=qJC8c7*#H0l literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/happy.gif b/images/mood/roshi/palefaces/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..53b37a9b4e80209993939177f498db93741a9500 GIT binary patch literal 871 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{^S+m9F&J&wG+bVRLJrm=Km8({-VzOT%yPPp} z%bJy2LRT=!hK6WybL?DkX!Vg$4sNZzdP1R`EZdK+WZ?`I(%Wk!At}tm#=L1Y6Eho+ zu%v|1UQ=0lDPcZtc2*YVZ!E0r+*e%weB_Ow=C1BI3lR_$G7ak=(aydO&Na00}+3D1&!fF*~ zOeQuZi*gAo`7B5tVi6b(AJkJ%@Dx4-fI z!A9ldy%GtlRc0DKb}Rd8yMsNR|8rqEbG_$-MJ@u)0)Z`p?k*iiS_I`1T?Act1Y3ko Om%ez|9?HVRU=0BLC~C3* literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/high.gif b/images/mood/roshi/palefaces/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..bff3498f0067a2b5f502a6e935133bbbe3b011b2 GIT binary patch literal 483 zcmZ?wbhEHblw^=(*vtR||NsBrwQJX{Teln-c-F03ckI})SFc`Ox^(H;vuEGFeLHvV z+_h`hX3m^>=+GgcV#WX5ey$1fcAl?KjE z3La|;wn-n5SR(nF>rU3e`-O}`jn&qT_6!_6^-XOpJqBF~9Fs*n!lXndb7XRGcP7bk zCh^RjJ&Ai>=>n-F<|QkZF)*!QSXr@lUB%q3+?m{LZX0GDp3BW}V6PDC{sYI)9=AMu zfQ_5=)B(Pm;vzTs4qRhkWxL7r^r`5xr#IOiFtNRSsrcdPdm-KfpMSnQz$?tl${@`l z<58e+fa&ix%@7Gjknb6}8Tc7=SQ$8h6bsPzf*)8vtlAnJR`hXOOnK{+j6gx`s`e_Z po;&RxPs;sxcY$bAJFKdNJ~Xy1Gg)BIT&tO4V}u=xN0 literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/horny.gif b/images/mood/roshi/palefaces/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..902797009c2b8330a84167fbc342ae8a92e7dacb GIT binary patch literal 493 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11}efwU$dUfpBv1iYoEu1*@(xprH?%n(J>C>)V zyUv|Ew{6=t78VwuV#WX5ey$b<0<5;@!G+<+?-pySMJ;VP)OF_{^OBCwY#a zJjrn7s;$T6Q+rP`-%HGry3c&_&f|NNq`03y*~HEIf}5N7%h#`;UO$<{ewX>j=WqWi zy~`X9H?pw{X~mo{P&`y1pzOsWzz7ZoK~OO8GjK4l0U-m6aDZk~kkSsWge)Nzg|2xC h)0l)H>iALB@dq?=Ug8l+c<}Dcy_6IW7NX6v1^`@_uwwuK literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/hot.gif b/images/mood/roshi/palefaces/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..7579818afed78a1c7d5e60fce9962012c1cd326a GIT binary patch literal 1001 zcmZ?wbhEHblw^=(c*Xz%tgNh@oSdhb7|t*;oMU0Q$i{e?oAC-4<1K#1>w-)-1exxN zGu@VCx+B4KPl@@y3iD-El`E<$7tBmA*;rk%wR)hy{79Gip+3tKZI&lGERPIWo?5ZI zFlTw~%<{^W<&_8PJ3rR9fh-@RSU$wCd`@NllFafYh51V=%hzn?Z&@tga+ts6u>2@w z`dP;GyOQxwCF8$ZhQq!-N4>l*x;kC-cD)$raVgyEa-8>-SntcJK37wGuV?#S&GEfn z?03Dy??#p1t$N>m9YIIBgU&|!-IWSvSgb4nD-GfOfQ+&$eCeDljP zQx)7(6N?m#^voC(f3h&>0u}0jd;y9_2KIjq3=E7dOl|EQoh^(_O~%3#CQh0dIN7+@ zNQfnnW$wH=EX;Ek%oQ|h5@icyWno>ne#6E&B26Z2+jp$mxqGKclPL#BZ__~zcJ_mZ z84j8@nQ=03U*hIs;JSYO+KsE+W=-Zie2@5epFVs3g4evsQtaJf{*MBm`9FNLXtI`+ zY6|R?U@%X3as9<1R@tVCk_QY2ZSap(C?5Qsu3MyI=D>`;H zwO$pC2u`@WOSE%=iteEaatp3pR< ztCh8@oo&|idEN6H5!x7m+Qb+*f!Ykg+JKr`g#rRQdRqjWSSNP3^z=?^Ve6aKJfkmw zeSXutjwMs)FI(QXa_-_qi?Etv1TiJBwY8n4qo<`kpue59WpYn VbIs@S&R^ckKYw+Aeb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nY@e}}Pzq%aQ~^8scy9$`rd z;~i$Q@>0Tl-0Z9@%%50T*}3_IrQ~JJc33DV*>MCgqaK0%c^KeHSr zE;21uAya2PIX z=@QdCQdi*nFp0HmgQ8u@Q5M6dDiYC6IpIKkcI-_Av@cf-RP zwsbHqX6+U|R%QEkX%cI3z^${)`m^F zu%I#7y+Yohf#v4>c-wwii!;kx^u0M8T?E}^8jm!2n(R;za+e5X5p>c~Jku(XR*|T{ GU=0AwkZD!` literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/hyper.gif b/images/mood/roshi/palefaces/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..ea5a47026bc65acc724382e47ca83b4b34fc9199 GIT binary patch literal 1121 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$WK(@>6S}%NcrkEi3TzW@$ukmdo^(#op5d&(`PnTc zqF1j8ojZSv>+aoc^Dn-e|MZo>3ju!qSEqg+e)a9M5~qNS1xKOEcC)u^Chb%VoH!+5O@ z&ESMaF%}^Ohk^$Ujf*`dipkDuIB;ZnfO;D+kdebsfu+2zJ=wNoJGcg3mwj4Jkmd$XCx#tvq?y?0KoC*!UuS?0SRIeh0e-qj;t+PuBmzTA`_2jZInkfdzY@+${IDf)kb-;005_3(hpiJpKbFbe>M0DFIb ze{XMZcXxMZXJ>nRduwZJb8~ZJV`F`NeQj;c>2$8HuCA=CEH5uFEiE}5j>W~rg@uLr z`T4oIx!KuSyWMWH*=A;DtX8YVVlkV|)6>&aQ&W?ZlM@pYCd8ySuBatFyDSqoc!UG#U(swzf9CUf*AqWCN5cq$cJD?9<0OT_ps&U<|g$1>zEi>&bAVq9g?VjgU~P z8^e>!xkRL8kS(APLdf)!T02jl!@<+VY=MN8CGj}hdxV~3sN#A@x)zbloiKX(cpee+ zL7&UTGYa@Ws_%=@0Pi6psYLw#lTUOC;U5ekl*8F2zb-p+-npN8ERsh*f!<=8s8YT& znMHFy7n4r|OR};tR*=YK0>xy8Z`W-(U}c73%v0@eewh-pvfYjaYJ5^d!X)+h8}>s* z(n2oXDug+UP^MM`fC{nCzk=^jjI70Ee=xct=LW`PKm9`%>s`@{1#NV!*E0bt4V z_3h(VUo07UO2~92(2e>%ljB$JZG^2)pK9nBL$qZ%C&hU8R>nBph^e|Ul PXc{Md-onfTfGht16r^jP literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/indescribable.gif b/images/mood/roshi/palefaces/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..e88f817e97ecb79ca0d2fcceb0f6d8bfe5315104 GIT binary patch literal 943 zcmV;g15o@&Nk%w1VHp4!0OkMy|NsB}{r&v>{QLX+`1ttt_V)Dj^z-xc^78WW@$vBR z@bB;M?(XjG?d|OB?Cb06>gww0>FMa`=;!C>=H}+*<>ln$W+}qpR+S=OL+1c3G*w@$B*4Eb5)z#G0)YH?`($dn=(b3S*(9h4$&d$!w z&CSfr%*)Hm%F4>g$;rsb$j8UW#l^+M#KgnH!@|PC!NI}6z`(!1zrMb{y}iA>yu7=+ zyScf!xVX5tx3{*owzajjv$M0Zva+$Uv9PePudlDJuCAx2r>3T+rKP2#qobjrp`V|h zo}QkXnwpuJnUs{2j*gCqh=_!Qgn)p6e}8{_dwX|xcXoDmb#--aZfNUaBpsljBammhjMdtb#``mJr$ap6rG+Fo0~m&mO=plsHv)}ssTcz8>g!W zNmf`)7_0yR8+dmr2nDhLQEYg}cywI@sR0EDD!wle4+hLp$6-M_T5)(`r~?KM5HG$o z78el-3dUEeHgtGA1PKur7Bs#%8yy%CO7N^fFhGF80b=lgVGsdBhYdJ<>F^Mu!v!N_ zwj40Pks}v8Vga-{4$dqXYPZbLrK#&N*x1`i@iknnNrhlvv_Ib^5+0fK`HWbn8_l7WNH6DEFCHIc%^hz}e8Fi?({7R!mam@y+p3>oH!M1f-7Jo*^qT@X1|1V#-T`0?M!f(Olw z|M}rp0}MsbHvVGj!KkOK}g6o>~9Gw8sB4?h4AL=Zv@VWJQt z0`Y?nJm@fkWOz(bLk&7K7$OiQo(P1BKJ=i&j8h;(1rbUx(S#FEBnib7l1V<{L=#LX RK?D`ZRB7dvSRNAy06U>DwXXmG literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/index.html b/images/mood/roshi/palefaces/index.html new file mode 100644 index 0000000..7fd8571 --- /dev/null +++ b/images/mood/roshi/palefaces/index.html @@ -0,0 +1,108 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
annoyed.gif
anxious.gif
artistic.gif
awake.gif
bitchy.gif
blank.gif
bouncy.gif
busy.gif
cheerful.gif
cold.gif
complacent.gif
confused.gif
cranky.gif
crushed.gif
curious.gif
cynical.gif
depressed.gif
determined.gif
dirty.gif
drunk.gif
ecstatic.gif
embarrassed.gif
energetic.gif
enraged.gif
enthralled.gif
envious.gif
exhausted.gif
frustrated.gif
full.gif
gloomy.gif
good.gif
groggy.gif
grumpy.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
hyper.gif
impressed.gif
indescribable.gif
lazy.gif
loved.gif
mischievous.gif
moody.gif
nerdy.gif
nostalgic.gif
okay.gif
predatory.gif
refreshed.gif
relaxed.gif
relieved.gif
rushed.gif
sad.gif
scared.gif
shocked.gif
sick.gif
silly.gif
sleepy.gif
sore.gif
surprised.gif
thirsty.gif
thoughtful.gif
worried.gif
diff --git a/images/mood/roshi/palefaces/lazy.gif b/images/mood/roshi/palefaces/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4fc624c6d5cd74e0d1e88d0ba13a63a527200dd GIT binary patch literal 603 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$pa0d7?>}CB5xB)Ez{mH3bBdDd1Lg(+p$?CN4ULEG ze4}h~1OgNrSoma&Zk%X{>}Hjbv?xg^Y;5l3)(g^#I5{cRYXXmqfi{D{)6>(q;tsJy zEMRS9;Si9qNLa8UaItf( z!{gYtZ3`DJJa_IK&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kxbb$(WfEegXNd^Yie+mp4OOoehcx5d*!BL=d-srNPn4|d; zcJw;^np-Hy^szem3`J{)fMlVxEL->0zT zQ)=8^t{-|f4-PzZly`13@>x^CIR7XQkCV}Yt4@s`Y?6j1QNbS+mNZT0PC7N^=OvY9 z_AN>_8J3%#onbZ2eb;kA=};4&$7HS8t`f$;o`A((yo{hgWaMIyXV76`;9wABU;_rC zkwPPf>*bn^TOv$O5-kQiuDRlyKO9;-;a}4=ZU>cfbIGo!0c^QEF7 z6E^ C88Pqx literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/mischievous.gif b/images/mood/roshi/palefaces/mischievous.gif new file mode 100644 index 0000000000000000000000000000000000000000..7860c4c11b715609f62a2c1b71eb7fa6a3f92b4f GIT binary patch literal 433 zcmV;i0Z#r$Nk%w1VHp4!0J8u900030|Nqw3*1o>J>gwvo#>OxV5Yp1p=H}-1_V%Hn zp}M-d-rnBM&d#>Bwg3PCA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV9smFUEC2ui02u%o000E(5XecZwFBwRJ0Fu1jAUt^ zj>Md7%ScC(w6uIk1wmA7r588^fFK(IOviw1hX4WwjHpgl98nXxC z1_FU3Fwwc!lQegcK1vKj_l^y~rxy}*H+*<{dv^c_0)PO5a1w@(iHm^;mJ}Lp8WffX zj1C74ifK_DQE3992Ppuc4Wg)8vZ$e=tPZcQqo}-TwXe4g1qHdC#+JFm4Z*|10M5@i zK+VLr!vok{7uf^D*4)^P6AR$otP2I<3kweI?(Xa4-HZy?1M%$d_}Ie=6ABI#2pmYT zpum6^5-OY!0RSQS1OX@j4*)C!00RIM015yA1S~LsIfK2D0*N`^ACV+oX^jN)tgC6U bDl5-)ZP(kK%SKiAyA?3-^T~p=U<3d=nryC* literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/moody.gif b/images/mood/roshi/palefaces/moody.gif new file mode 100644 index 0000000000000000000000000000000000000000..87a9ade7e997708d6d4dd9211fb2ffc666183faf GIT binary patch literal 485 zcmZ?wbhEHblw^=(*vtR||Ns9#b?VfuTesG&TW7(-^Xk>BOP4MkI&|pSvuEGFecQEb z*S>xGu3ft}bLLE-V#WX5ey$6e9iQZnato6O0v_Gn)e zlA|g=DS^R=bH@IOJP86G0#eTFRYN39IvyuXFwjWl61w(tjvHgo%j``@gN`VCSfI%1 zv*yFMC59gQQaR=e99rIgsj1LpD7R>+Eo^7!ZEh_Rsy^P|-JfL@m~V_Fpw@c8$Z zBI~QN(XTSz|39#x;K%PZI)Y&Bk`V38KMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGId-onbeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$H8O*vFgj{qb7$!~f(CzP0>d#=FJa5vRK4)%*(1qfVOSD6 zO=-pE3Eu0J)^AWUU|6w7S8$CISE!(na6_sggJ`F)&{2DaBLZn6qBk0y1q3f~2|TzX z^!UWn#}^(7+!NsEe|Yf2$A@oUDRBz$@x5jE{U;0bknR#>U3p-rnZs=F-yAosE(5^77W! z*4o4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LVHvj+tEC2ui02u%o000E;5CBK3y;#a&y8qxeXiZ?A zXsR|+p}ue-9Z8}AaB$a$LHy zG_`c?RxXSHgM~suk!4-|7Z0C!u00Dyi9JvumpgpG{{3W+^9jD$dzGm{$! zo;MwL9XFl_Zw&_wk_%>3A6cx5sw@Dg461ysVX$(kvl0!rw~~OY#(=WIw7~=f!llrj z!p#iJ49(3~R@+M0&dc7}hCboo%>(G@g6Zhkv;zd}0}b@`_44r&25dZ)o`2+z901p5x1ONyC5da1N00b$p6eCi4I45D`nnEa!T(NwU dk*!8&0x%q|LJTVkN{#MuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91kV{eAvKvm^DDc ztb)UEQA?MY=COtX--k)8T^khbDjsZTY;Nbz@m>(|P$_S{LQC`-53i;p9D)1%N5iAPptdP|NZ*Yg8M@I3=CZa-DDbFgm|eb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nPdURa4*v;N4bhe6d1JlDsPY%VkJvxp}?(5~${FcaQGB)|9oC%4tOk8x_TUgT| zYN3JRAr>yD;4g2UK5pR>VKxj=@LI^!)~FFO=flOz3GXMevq=*-S18M9Vn zp(FEgzK?bd44jAJ|5wRbKX8~YbWlf;MbK5EkVS|`?V&=mhfJc2pbN*wBMuU2D-_!r H85pbqgpp(o literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/refreshed.gif b/images/mood/roshi/palefaces/refreshed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d224ceed80a723780d4ddde211de783f67614b6a GIT binary patch literal 681 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBNa}rhIapXV1a;&9>meg2ef1 zx-w=zrVBVQwed=1q!_F|+SJPLmZc8%LXJC(|siw@7Ao)oHF&5n=)xBf=n!Y>dhS vww?oN^OR;X-RW5O)}rT5_PHF(8E?7Y%$Cx8ws@z9s&tVsM583-_FDr0wAKoz literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/relaxed.gif b/images/mood/roshi/palefaces/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d20441e97d3ff9e3a285ef604cfbb31b08ea81a GIT binary patch literal 624 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$VxbS&DowU=)a`u^}NrfF!BBvyp@65P(hbK)o ze}{&!tFDJstG`!+h#3Qqu#l3klEmc66Lf`yySat>Co(fknL3YQ4!6?mz{TQILKX`O zEn`?QO-X#)wk-_nH*yQ^^D@|O;I&V1BbT7Sdf~<#BhiMwlY;gPCj?H-Xe<)Fa8c;w zsjFN!Zmgek=H;9RPX!(e@bf=C`eonKkMEQ?1^D zywX3MITQ{aV&gF~>bRQJ=*Gq)8xZqA;c?SsE}fuNA(fYunb|jTeKEdSw6tlO-fz(i zM+HVE7Ir=f39l&`7v^(v*uLmZc8%LXJC(|siw@7Ao)oHF&5n=*IgBvIsSQ(fZ y_<@*#l}|yTC?&G%K<26^+xF#hfNhdvkVaO*ub|$S!Z}B^k|~;diOlUb25SIRv+myj literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/relieved.gif b/images/mood/roshi/palefaces/relieved.gif new file mode 100644 index 0000000000000000000000000000000000000000..6f70c4ae787e7b7ae892cc4e96fdce13fdc8fca5 GIT binary patch literal 775 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$PekFwzIj&Y}VaXUp%wA=a0f`AJ%o~Hd} zO*beg~tATWLY) z%BA8n#eJ7B2nwxbSU;N~>A=37ySW9A^%@*7=shO5n@dn&r*K=Lk!b6bi-PtH7X&WN zZ7UbOaZ~8xrMp}Y9_(Cr<>SH^Zv|cp@bkYt`{&r(pWj?m8Xg>Q+}9koMy4h}z=^4m zN7`e`jTJ{-I@#ozJRUeGHTUzBZH-`<#OT(`Z6s3@b0Dbk^mP5mNhuE!!W)~kQxAnG z6sH|z(&bQb0Gh@iu*)XRjiu`6J)7pnjhC=?m_8KfC>m>HNEgc$^Zq3Hi$Tj7$7 zc`D^hZ(eR{kl6ht`hJC9xY)F-l08e4W(DX>=RVfz8KogSabo()$hLsXJOzcZ+tfN! zqHGh@AAQ&o*63C8VMmSM{WDqRQE{)i7_r&m^k5q!$c};{pdE8o>@=ypTCwi(%2UhL zgxEWnc)S-sUa;&-Zqn?=;1m(vm2OD}-7=Zocjs34=uMWlG+7szJl_dytPPEwZVdne C$2y7t literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/rushed.gif b/images/mood/roshi/palefaces/rushed.gif new file mode 100644 index 0000000000000000000000000000000000000000..07302380ac064b1776832e327e2dda4e03dfafd0 GIT binary patch literal 714 zcmZ?wbhEHblw^=(*vtR||NsBb^a*(O?Af+$+xG3-ck0xsTeoiAyLa!}wQH|ly?XTM z(WOh5K7IQ1?%g|}V#WX5ey$0YppLV*preuucc*9PPd1T z^42w13??nq_{1|~zh`p#30|>17vFD@(PMLUU~F`-lHwJ+wlE^VG3dxc)g!a2R~hao z@c5z9SMi6}L*_tBi?xCv!;|6~hPo**zvrtr)Wk(w?g zGKXh2+a&g6f0?)yoIJ~xE-On8<&I0rUB5wyg>B!asuhQ-*6nATa%|t?({oN9-*axC zrRBvFY^*oLMQ*U}J8`F-wN3F+(2eu$*B`OGdHe3&^J_QWe|hu#Mf=xZ?{EG6CkXN` zBP-CuIxGwv41x^2K<`?8So`qS?jNS+*Q`%0(D3_a@wh?efys>P7uNC@Fm|oH@pZDw z+VHfpA3viEPHIiev6_EjMTwWM*qrO$EMVg#QH|65(8xJ&@1$o7K0XoANSGeMIxV2` ng>l_oR)0y~Yp>V7uX+FfK*EFr%27&S-CU@;2i7rE3>j+xRI)9H literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/sad.gif b/images/mood/roshi/palefaces/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..70b6ddaa456ce38e0402f97b5c9ce147695ae6d7 GIT binary patch literal 860 zcmc)HX-|>?0KoBwOHMTe>A?dKwWYQdX{nR)CT(eWV$I50HDBbWZ(3_Dk6LLuhDEOB zQqi1v)KXF(=LG{o1;sm^C!lyAc;YphpQ8U4_`Uewh~)VBKcoUwzz6_E0BEsTPEJma zkB^Uzjt&nG&1Uod{{G(H-p_V)JH)|Sa++Su4wUteEaTU%XSU0GRKUS3{WT3TFO zTv%8z8jbVw^K)}^27^Jb*Xwk;+1c5dnVIS7>8Yuy$;ruyiHY&?@v*V7(b3V7k&)ry z;h~|S!NI|Sfr0-1eyvv9*VotE+pE!N)M|B4PfvGucUM=JN~KaNl?sJIE|<$>GO1MB z+1c6A(b3-C-qzOE+S=OE(gHzHb8~Z3Q&VGOqeLQUXlSUas;aE4tf;6EiA1HPr6naL zLZOh)=i~8s91e%YVlfyD8jVJwP)H;afk43Fa2N~*{J$=o(x)!~v?VJcJ}x$f%e@^P zm0u7Qefxb(Y+QUo0*`(6Ycb_p38lE0%_|Cq!^G7!wKeeI@6J_ql3KVkFVPc^X%O>j zJFDRsyeD+gj>uE1B^ou+?jqy^Qb`0WMEehf6@f$reIQ?Fx&z4uk47O8n@AKIZ$omR zJNrWZ3?^Mmb_4ymGKnoSXfCNK6q)x_;}9XlWKglhfTCSSjQ;OsfX85iSee0I;2yD) zWRxqgpBU~zUp!#O&!ls&e)$xZ>+NwQ=B=_>@9@4Sfzje16Co5;M)pj3@h(J}M^|Tk zPZgCba?jANra%BrZe{Dj5poBZC_$ZvEV(X7cSV7=b-J3qx#^OIC3_`9_b6`Z`SzSh z0q9b0!YJ9i--4s%n*s_e<#$SbNcacx`H;-S`kZh)$hsR((?9xC0J0uS?^E79e>V2> z9^noL$+32nrm-DqlN@U>?1dJ}4!yyld6n*hjiG41qxZ)L2P{_=pLYE<0J96rJzy9z z&5QM}DncEvXjoi`cxk53Yc1TsYpP>+%_UYCk>ivdW{2?)dq8E=W<1eqe8oS3S! I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/scared.gif b/images/mood/roshi/palefaces/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..e75a2d1bce06cc8352dd448d65cb8e22869a6c34 GIT binary patch literal 407 zcmV;I0cie5Nk%w1VHp4!0J8u900030|Nl%dG}_wQuCA`?>gv+c(!#>R=H}+Qy1MrE z_Rh}E*4Ea(zP`%J$^ZZWA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV761SMEC2ui02u%o000E(5XecZwGHXbJ8x4GjAUt^ zi8PGW8MMJ5846(9B~Aj0AvuMDLg6|MgAU0-BP13_N6kSw7$AbfAt|c}BC1nBqbi$l zvlKE&JYYy(lA!!OVGPy@h8r#b$b&W#eR?SXc|Lr8e}Mpf1`LIVba9J}0FRLdniNc4 z2o#zInG26(9$!@q2Bf2;cBUF+ZL6#j2@ANcda`YLw78KA4i34Y#+tdq3xxy=2M5E^ zKR?k9&kF<+1lG^b7fRjG*#HFH4ImALA?OX=;|T}n3G?*z_U8x8&+_*D3HS%bkt0B` zpuvL&zbRZ80RSQS1OXNR4*)C$00{sO00aO41QHN{@T#>F2uW|<6WDno=UrI@06Qt8 BoKgS) literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/shocked.gif b/images/mood/roshi/palefaces/shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4c79bd8ff4d917c4fdead4e5c2a5b8e14cf77cc GIT binary patch literal 871 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPlj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78oVp@Rnx9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91h>qO)h)gimv1VqCFu)#_DD zj!R^ghi~4zhH=YQCYkUsO|J0eE5lbGUda^BrMX8>P=JGF+Zq-Q0YSYz#^Mq}+-%GT zS2HoQaSKU^8}Bifk&_hS6AOo++JUEvN7`jJ zm$gU)c8fK4i)){g5==V2Mo!s-XEy7DQ_Sod@;!TkCLQUJ+gvlnVB@Bg7Iq8eD|?a_ zwe-(W4anGIe=M`fwq!xs6xWW`}B_lWX_R%}o+%3zJ@U2r4;wh<&tJ z!6jB6AIo`&=@_?|cE}QeD%Dq_BAOv<5Zo z{%T+I<;Fy3x9i&885d3z+WzfVaAJ`-!v8UMdUKukg+oUKTqO!wggjkV9BC0$Ydj+8 TCSu4UytDMh!}f3%CI)K&^B-yx literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/sick.gif b/images/mood/roshi/palefaces/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..1d313ef7f9b187aca928947f11b506a342821eea GIT binary patch literal 1856 zcmchWSya8LI-}9XJcb+#W zIMBy8${yH*pTHX-(EyDBCPtY7Q%e9@0y8r+b3DM>0L$&biU@Fyz}gAez`)i8*tvqw zYLKzDsJL2891|1Igc9m35}1~kS=JPmbyB@ua)W(pmNdCY{{%*1>qrGS}I+>yXw-Y8=ym9vv8*eNCa$TD6`1wXD_7+obwtP)?U zl_Xa3QY$&vYxp;+I5%qqRAz5dorF>^zQzT$DD9mUcptTIpTYC$dyBICqMJ-*$ zt-OkR{F;uQnl@os=RhG_RLdE-%N;0dz(8wxF?-+sYQ!arkW1A=nb%OpTL0_vtY@BerySuxDyl$aDDC!YPI3kg#zrVjln${}KY*VJSE7Ch2WOd34 zI#pS0RW?Ufzh^wlmqaO$ z$VCHkv1GJPrs$O`CGtV8Vo)R-ZIX|)JRIXcoaCv-y46#B)u>1{A|9R^P*3xRv|W$1 zJ;O77!`gnCOr}&ShlYk8jXW5hkPnY5hBfMu(Z`yp!O_XbBij2T(~8kK#rV8(a&~y~ znR@c+BaLQcYpI0}&-*{!z=KALApEfr)e|i1O>wj-;LI-{*T28@|n{CexYPE+rNY3J!#i|Kn<03>*{_l?;1(9t6(+LK}|<0FO5bZ|(>{TL1xw zq;;As9kQ|B0f)ja6x^<3Rc`oG0e&0am*!O5dYGbP@Fi8p zm1aB$siny5LgT-L+W=vyBr%3^JLWNSg8l;FamiLr?cy%_#j>)0TDr}-~}Kp zUM;%PcG8iq*wD7C$14vaOHtW?g0;T@GLoxZB0)9M#3IYG=xjR?iC%#qNV+<`@|Px; zVEVjHcJD0r!edrgydM&UK2p6%hG^jZI~Qp__*gPbbvj3)V?3n`Q6O327hpXRkgim12eXHUhX&H8rf+SP8 zE<2hW5H`&v+no!SrCa&VQBYRC%hLPXoz7k0nmC0)CWLs%O-e&;Bk5LAmR?MN9C6ii%Tv1l0VdYkAKWtVTi>&MlP*;IBo_aj$tCy$6es?q}b zH3|#9`(xBG@C-qObk(wSq}lEa0@GQZu>oOX_mDu&SD0B7;KhOur@La0ytTejoqY|B zWu9h6$^y{PC?1E?MGRrKc}dO}N&)>E0`a^3|80{)zd1Rz!_4;EdeYxfx0FTRg(Z87tWijC_`lOw BL7M;o literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/silly.gif b/images/mood/roshi/palefaces/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..38febb68674aad005e58b5d1273e81d5197a185f GIT binary patch literal 1030 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$Y84jDbg3NQs$QNn-Nk{)r4i!d=`#eZEts`p)H6niDAF%^*G{WJLsn zpwJSAW!~$=ckI~awrQ#0elLTa244FGH**OJY!q(DHWIDxJtb(*a8ls(%!WeIi zoxa9(^XA66XJ5^I_)Or506+h;V_)|_`}AIkQ-F^z{?k4N0f~YI_8gqwYzrYc&7i}|z{$YRzyb_D;RnYUqcdkMj^I<@ zH7lq3*pi${irCd{D@@AlQ>$FoaARG*HBYu>K2~)i57=^2GW%{Ptjk=PCv*EylFs#L zu*Hyg1I4m9g9JF<4n(A6&QoL7hOjB%=&NI*u<_cK8lDn~htJ!ek2R3FKiRR||MqoVg za0}HrFtoJx_j30LdfPFGx46m76cm~&G~L%meED*_c?=7t3a)ohS)t;vUXU9YPYZ+# zW7R|pYIg~8?G)JES(qex@X+EDN4ZX1>^-%&ws+T+W57tdvhC6OEB6JsK#|1HaR2Q) zoA>Wt3vhA<@&4-n^NaV*_kBBVZhmo*sfp){rN@Q?2j_Y1==o}}jNy?SJ2%&wYL1DE z3_I8**Jv{|I54qr2=d7o9N3iVJykMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkCaph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^@fzw8wvrDjr{98CuqEG(bO6)y+)A^978gwp zTP!5JjA6yJxXdsHUxxJ?xrKyyJ9x!2#SiH6?%T*EB*?&f{($kh3k-rn_6(;5&+6uj z-Oum1eO-y`_TxD-L|*sLIrIF+GXa6;`@VgD{#oz_ryxK7X9gA#3)VAx>IH>5JQyA} zHn-OaC^o%dSm4CKDPxszV4~w1F>WiPiXRUiHL=SWh_47auqoAhs-mP#N9coiuNiux z2YP<4ci?8?6i~1zIM8r$v3n<%uY<#)%gX~8TY!Q5lZBCkL6$)W6qJGtY``$oO-PNM zxvVr}RqFK6z^ko^k-6!gzaDx#_22Ys+zu*cb#vV=-pDXZ4_IE(<>TcHH9-d11Vsh* r9)|RJN;Au}tTw6GELa{>_AFqRh57!q!Ua>5E_E#x0PFIm$X;szv^xkW literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/sore.gif b/images/mood/roshi/palefaces/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..b75301ca5ca46407a71bad249495bb694de42eed GIT binary patch literal 1219 zcmZ?wbhEHblw^=(IKsm4jDg{iipnz$jsO4uGcYiGn>+WNfx$fmg=f9JnI=go5I(F>Xt;WV%t5)5*b?aPd>9yM0OP4M^d-g0fGWK3;>$|B_&z(DWsj~8# zgv28aje9^db##CRD*os8a}5c0b_{Se(lcOY1PT3-7BG@ny4g+1>6< zdF-%7agAtcZDmDO4U1@UBTKUqZ>6`g?gR&smcl?imCC8TB9fIEdZHPX^D89hi)6&5 zESa~gcg2d?t5$E>B$+SC$G2(A{!M#!ZrpQpkB7&xL;0uFRZgAR!+ZI%>Xpk!&s@KK z=Q^Jy=cT)kdG~NCbMkV&e)IO->sRMKeO3hdjFE#uo~YIeFb}B3UlN6+ivdp=hJcixv7efeMjdq6_IPRJSMpn@0?PyTYOu{RgYET8f84J z-un_?r1u2YuX?`f_meh#x&ECed*knX&ML{Ot#5GBaP+O30wwSV#~ zi@sjr88c^h&!0AbN%xAC%Y^H^q*e<%ZIs^-yoP&Sa9&pMwz}Z-gIWQH(u4OOtUGo3 z^g*fpap`9+pF6L8`Nj=-tR7hMpqvBffoF``sQ zQ=iEwQ{9rtR38;k)5>nks4*$nws?ZfWc8Y<{S#Vd&Ym!B-n`O&wC(moCuMD=<)u$vIB*uL!|fih_W&LKXyrPf!(UDB zGmbsAB4+Y0zQcQG_(|;fT5~+sDEx`+Oy}g_SIj>3H`bJ$UfNl(|A}$U+gXuU3plVv M=8z4Gp_K})0f_S%1poj5 literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/surprised.gif b/images/mood/roshi/palefaces/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..be69df1fa2c3d4f87ed532a0a232fd273938c290 GIT binary patch literal 675 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBR>UF#b3o-@@{n%Piu?a!>9y z-hYZL6Am17Vv~?OleJMnxw(~3O|PJ#u+fuMLo0Zh$<2w4&5^8srlzb6Vmv+VAJ-Oz z2@H%)%!HO{|4qBb?Vxh5Zn{#S(!-N!me*S(GrQ_ESE>jxfsNs3kVZB}@c~=U zfwXx_GmEsWHmTSwSRPaKEMV6Uv;Av@3#KSt>RKuQ)};&5#mvCWAPj^ItcE~ckAb>4 yJ7R9H(|E8?d{?1a-?g&${|_uE@X(R!Ke41JQ)g=1h7}twZU~&|bV;9u!5RQ5Bnt=t literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/thirsty.gif b/images/mood/roshi/palefaces/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0fe339de6f899c8607ec23a100870af667eeff4 GIT binary patch literal 597 zcmZ?wbhEHblw^=(IKlt|tgNh@oSb%x|4(C(==thiz&5@E?)3=x2{yy-3 zpI^at0p5C#CmWO|Wtbg$vhn)O3>75~w#!0+m9YoP6sls5NS)(rNGZ3FdiPYZC`3!l z=h?}?_rJmJ5_HYXc?h@$~Gi|vld`ZZa z;iBN>`JEMFEgjP?UB1Wt@Zqk-S3fPj{Z8D62%Ck}hpdANDb1by#%4wp43ip9vl=8HD~a56kU5Tx zXWJ6ZV#c$x*m$>SEKqP{V&UM^h}|W!GLV&3$7^nuAqyxN8ATXm7<3pJ7#YMFSb@PP zub|#{=O}N=s(DGCC#Nqkemv&#%2#y)BwrfN_JYM~s0Ts7D#7=dmka%BfQ2 gRqN(hZ_0@}{N(SkVyhF@f&msaqRp$6)ma#<0e$7}*8l(j literal 0 HcmV?d00001 diff --git a/images/mood/roshi/palefaces/thoughtful.gif b/images/mood/roshi/palefaces/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..3550c5d490e45910edf40fdbfe2c2c031d6d386b GIT binary patch literal 863 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91?Bg zv+)Q^N|@|2mz9?i=Hq5(Wnuor!phFgCoCl|Yre};LCLOU_acQx$7U|JIsrx{_qDQ0 z9wpLcOB-Fgg|jCLY+M}1FQmGT;YTU!q2|c~E|YW|7rE=otNE?iV#?d(o2r~S&*0(X zrJW*@>jP#8Br>%w(5$%jtI&zHt5HIWXK4WAVFwW{zdtKjRb076Roz-XY+yXh8X#d- z!C|mM5xAW(CFNk=kl($x)C3=mASJM#=!3pjr|8_2N zy&E3hw55Y_F>AM|R?rd$$EYn`qB>CrIxaGO77#a1JJO+;T((wXd*=DRw@DtlN(Nas zBWEx$Bc(fiWGuU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;t=<^ zGyQ{X2bW3+4*HH zQZlwKYGLD*xqR}s!}@#f)vqmXEI(r8&Ee=G=qA&6q{-7{hk}s1L?DZxlTP5BRtYh2 H4hCxgy%}m2 literal 0 HcmV?d00001 diff --git a/images/mood/sam/aggravated.gif b/images/mood/sam/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..5dda545e6151d738bba3e9cd61faa095bc1cbd1b GIT binary patch literal 643 zcmV-}0(|{PNk%w1VKM+R0M-8h|NsBYGXTjl0LU@`zc2u^Eda7D0H!GbnkE35CIFEn z0EQv}h9LleAOL?L0DT_-d>;UJ9sqM40CF7wa2x<{8~|q;0ALsZUl;&d764fm08|wK zQxyPG6#!5a08bPEP80x6697yT07()6ND=@<5dcFG074M}Ko9^w5CA?805=W*GYtST z4FE6<04)muEDHcC3IHhz04E9nCJF!`2ml`l03HYc3`8lIG@m{^bmQi4p7`usFQlX z;IPiv4V$40)r)X;j)^vQd)~G!oAkVW%kTUDLO5M=VQe~DfJ0?aFBwrEA5sM$1zrUX zPj5yzd7WmOK8v1U7B6R@ie4)v78S0pA1|y6o``>fqX9aoiAuY_z_z_fFQU0RFNtxI z5w4YA1y@f97?hb?qLU9_3z$y@cx}8wHfBNpYaVTY!s77Ct$!LV=eT>YQY7 z`YDN2C*9~=%Jb4kO^x5ON}0)}%?5*Ny+pu)1q`Z~Xusgoc(Vj8I(zd5$S|XB*LZ>h z*oZ47us#G(3T%KF#^G6c2oylBa|CZ>7rteCo15*P}i81f?-GD8?Lf*I0-7*YZl zlKdDFd>NuW8KOKGLR}bwofrZf82s%SeC-$%ft`(kjg^6gnE?oZZUj--fZ|UUMg|6R1|5(j$WIPz{}0SA@X(R! zKe1#|1((JA3oA-q_2{;4)_myjwrZhq@;C1?Ee{PRO98cG*FJ0tz1eg4`Sm?@=l7pH zmThcQ>(UUwBBIBW70jlhE-WA*G?_an*UhMGcI*uEwmHF~8Y%Of7ldf=#EQqnH`mrL zG+x%?wPnZ74col*R?IfmZpn{jTOG*B*%-cGLt>%7hUB^&k0bFC@@i};e8zln6%iNw zCAfMD=IwvNqnNtvb%DCEnwqx0^qsh^^PkM#?H;qnP@%D3Y&8gnZ4!c*paZfvJTN|fvVu2ZJoVVXACAkv< zPL6Z7q%$W(IBpAGxWhlLVQaNkQjj{E*_Dq*7qynB)W^#@c5asvIwor6@}&HGx3ZAH wCMLCsjIyGqTxYDaYyc*OwfxfT6`8MJq=+m1HDF`5`ZhmiXVU9;!YmBd0NPyGwEzGB literal 0 HcmV?d00001 diff --git a/images/mood/sam/angry.gif b/images/mood/sam/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc9cd7f18137b47c57847a164ceca5752321e631 GIT binary patch literal 841 zcmdUs|1%Q+0L9;ij4_*`h52qw+i_bCiPh%V+$eqZJ9piQNfSkWaBf#Qa!!rv(kboGn*NL4eeS(q-@BJ2NsNxk<$;G43oI7P8$Kp@ zc*VnT1O~Y1=Ry|-9UJ#T&>Dhf7MfV73qnNzJI^>E_5NdC$>*^b7<7yNFO>={-eT!O9(bU#aOX2cuI|&a| zvE7fJw8hrk>Q~eF49(NK&xc3!inyk}mTtkFQRTyWI|m2)-hhDn8arzhI2`Bqos;^pWr68+jd|zK&n?%f^vWVb|C!|=rjaUH@K@M(xoeAM z2C|r%pH8m4ki@2hW=ppZd>mJ$3^fLqj_LJ>idRpkR?FKp@rs4)?UHrkIE5A%}D+@ZcfRN*ZfWUUB8ih(q%Jxn7w|;rzyn0;ACUoqg62nVT#-rRzz~ zTVHGc0Plnn^|PwbAR;4Ot7R<-ZD{=b1TmF8N+zA7o6BY;bLAf5$R4KaW}%$e6gb38 znpD1>sb_5%qfNR`S*CZHzvQFkkBz-Ci!!ceV~yG6WzbCgP9wNTqu5_t`;I7=Iuf_8 z&1cO9Ifd`3k*y2IZ0+^AVf85!guKs7=DGrTUQ}}Ttj)}P)XeJifau%H$;zDmVatvk IN$Q8#zmW0t`Tzg` literal 0 HcmV?d00001 diff --git a/images/mood/sam/annoyed.gif b/images/mood/sam/annoyed.gif new file mode 100644 index 0000000000000000000000000000000000000000..29d4b2c1ec314ac95e1a6a0c69280325e0e7288d GIT binary patch literal 609 zcmZ?wbhEHbG-5DfxcZ;r|NsAIj2TWEF`O`B*l)nFS(jmxF2gb{hGm)zv(*`9sxeGb zVVJ1G(5}SLro_;oz)-KiP$SP!F2_(T%TOfCkRip8Ai)qX!4M_J5GlqGBFYdf$`B;V z5FoC#I*H`nb5bP_z$s4rONwtMG>)X#7G;@|(+6Q^-{ z+xB#muxjVTKo(v(IYCZdCC(^z4HGF&_P{JRqmnsMGcDTYhKOs#&Tnnt>=n~hTg2F0 zRlCS!d5hQ9ox3(}_nf@m-$bJ&=RnN1gka8fLA+7{>}nFM%RCH{B;?et#0Z%PMVGBO zCc#^uF@NDPKS8CW<*(+bnW(Ah8pz$5=RW&&-X1rvpSP2o&TnnZtdebHRF)Hw;t}BbeDLJ7IkQY4BH>_jn|F*rrNBfZ2S?SvOI#{ARU0|# zW&}tr5Dw h{&ht^qZ{{6M(^X@IG@m{bn3J%g-xn<%LQ1A z*=~1HQVqmjFnTTiCc{(CVH$~W-PgQ+&$q$5etc?L27g)^8B};oY>jt}j$9ThfJcUr zVl{#~ewcxqdVZp#i=dX5jW#Nqs81XdTNw;mrADX>le26E6A=YbwVYxZAtt|E4mJ*3 zi>+%J3TJG1&XEivZG)HqDK;i4Dl#0$w3geE!B|}bFBt^}DkdTvD9zj+~Zh2sKQWgCr9j(QO7Yh)@u5NKG^tR0w_Kw5SvrK0~UL zi2zCg4l$`#EsEekS9{v5R&uF!?He&)WxSAac1^mYQzmeTQs4lzE;RaRVW2`puR0Mz a*r+?x6vA@~A3pVRcOfZK3p0ZX0suP`GvjIi literal 0 HcmV?d00001 diff --git a/images/mood/sam/bored.gif b/images/mood/sam/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..83974b2efcb1429d5f39d61cc660c6c107f3d26a GIT binary patch literal 851 zcmZ?wbhEHbG-5Dfc=n&+|NsAKGykVd|D7`JSHgr33H|S*+8#u<-4Cw45L|QKuk^5A z$swQO{hqnoJaV@>r><~LS?&-&-!5*BUF>X|sA)ElQ?0@#Scdgmg!GvBH=Fo18T&RE z`_vnFR2aCI>pBn>-kD+ zI7_KHh$~x(DOrdqnu{u!ipraa$Qz5u8VbuA2uNrMh^zC9t8wv3uyOJ;v#>LQ zFff4J4y-+cazPO zS+nQ#*|ga(&0Wl|W6Zjkaej*h%gXh0ExLQ>@EEIeY}hn?&)$9eo2+N9TWmA!K=aJW zg8DWhoU?^=<&>1(jUI@4j@J zKY6pt_(Va862sa%HUX2AOfDSLJl4uQSty`E!r_3U!ab`-i-%2*)VR-?J(Yg`Ua*6m zC%E%<_@{|2B6D@bk~r7R>=rjJ==k9AGU3>?^=@LjKCW$GnJYf&*n_|(Cp}NYI!>P* zO3XXDzZ5)Jzi!mr!6g=;UE9Q8$M)k}vq z5ktEl-K$|F#KbGznoCua*%jxH9juyEP|u?vEAVmAVWaaAJvvX?W8w?Y&=qxLO6++~M7JFh{-9 RhC!_Cd?TwGhmQh-H2`~W4#EHc literal 0 HcmV?d00001 diff --git a/images/mood/sam/bouncy.gif b/images/mood/sam/bouncy.gif new file mode 100644 index 0000000000000000000000000000000000000000..7acd1be8c0ef240bfb4a76e796f0c78c770ad1b6 GIT binary patch literal 859 zcmdVX{V&u30LSsq@#VUhr`-+xa2s>Da68WrcRzgF;ZAjPg-vLVvt+C2hs?$}=R9;L zhoUXy+(pOQ&p`_vDLu?XbLG$I^%uN9`v?=_qoT7y5Q6tsSPx)l z2ix1&+=Rt~^>xh8!(_tfC=3Q@wP(AS#dIKsjZ8j9dxaJdKyg1gcXv2DgGzYA%6C5KX{sc&ekvv*^&qo|Y^wSs?L+o5aZSGDU6bq;JU(M{=8#ux%T zdwW||*9J!(wT&9bOeF7aFP}HAoYFXO+!|@a8p8XQuD^;m@=Cu#&aG-axrX(M*E+(1 z#c_T_z@qKq-fmPww{p4B6hN4={h$txH(mpYVl4(WvL>6LS`c7L%$=I4ChYVHxASPFdcuxqF=yI7U@HNcjB#%AwG zUOD0M%{RDD)NpJX9C=d8no{B&_9q z)uq`}jGke7F`ez`G??FDEuAILyRw)fsoYZj} P&;1D-vQ&%{HsJjQsjv>J literal 0 HcmV?d00001 diff --git a/images/mood/sam/calm.gif b/images/mood/sam/calm.gif new file mode 100644 index 0000000000000000000000000000000000000000..1c38ace676798aeb74f620050408d6b3941b4de0 GIT binary patch literal 560 zcmZ?wbhEHbG-5DfxcZ;rKMv@tAiW0+sh zFuR6fYB|G%Vut=AhMoe3?tF&&G=_=kK=CIFBLjmzgAPa&$WIPz{|`(r@X(R!Ke1#I2babC3oA-q`RKN4uPQrTx~}Ku zI*W^(f=3$l4O{cN*PdFon|J@M_dou4i@L23sdA|;&dYMsYUvDa({Jty5>kxqaqbIZ z<5v?B$?Bkk{B z|NPzbHW=fx`7AA3VQ<$G`k9ttrA5U&Z5oYlxISbi?WSJHx*{B^^ z!98;tkE{}h=+>0123Elhy-b1&Wv!=&n;nYTu|!j^W2sZc(@lqt9I!3k8?v`sTvTgc K!$)A?S_1&IRlI-z literal 0 HcmV?d00001 diff --git a/images/mood/sam/clean.pl b/images/mood/sam/clean.pl new file mode 100755 index 0000000..586676a --- /dev/null +++ b/images/mood/sam/clean.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# + +opendir (DIR, "."); +@files = readdir DIR; + +open (HTML, ">index.html"); +print HTML "\n"; +print HTML "\n"; + +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + my $newfile = $file; + $newfile =~ s/\s\(\d\)//g; + if ($file ne $newfile) { + rename $file, $newfile; + $file = $newfile; + } + print HTML ""; + foreach $col ("#FFFFFF", "#000000", "#C0C0C0", "#FFFF00", "#FF0000") { + print HTML ""; + } + print HTML "\n"; +} + +print HTML "
$file
\n"; diff --git a/images/mood/sam/complacent.gif b/images/mood/sam/complacent.gif new file mode 100644 index 0000000000000000000000000000000000000000..dba96b8b6923869da82928c80e6e7248aea09564 GIT binary patch literal 633 zcmV-<0*3uZNk%w1VKM+R0M-8h|NsC0%mDkz0Q$%P@4o=xvjE?+0MDiXz?uNRnE9*0GoUOm3IJ;a{!NW0E}<|i*EpeXaIp{0Dxuye`Wx9U;uYt0B~9W zZ&?6oQ~+pG0B2GFWKaNNP5@y}09r@@RYU+&LI6-e08c*vO+ElcHvm9006Z`NI4uA- zEC4hr05d57F(&{pCjc-e04N{;Cm#SN9sn2<01pfR2L=EJ1povC00000|Ns9000000 z00000A^8LW002AyEC2ui05SkF06+%+K%Q_&EE{J_IG@m{bn3J%g*Yn5LG4mM zlqb%Z^_roJQ;TqRj)^w!woQLpmCbrIVS&L?Qg>H_goTDYH)V7_K?9Gjt}#^(+s%|-2XD>y4DFfi;0T&Hp?Jx*8Pjdz79Xb2%%U_j8ts}jT(XZC8LcGL`$ Th-$m>j5`r9V7P-H3IYH-*B0pm literal 0 HcmV?d00001 diff --git a/images/mood/sam/confused.gif b/images/mood/sam/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..32382b95aa1e0fa6422f5e85b990f873ec2ae3d2 GIT binary patch literal 663 zcmV;I0%-k5Nk%w1VKM+R0M-8h|NsA)%x0I!W0%HakH27svs#9-S$(Ece5O-$n@)3@ zO>>z{Wrsv%hC^hALtubFU3@-ScRW^eI#zNyRB$*`Z#Yh9G)-qTO=dGlU@%8tFhg1` zLs=|8R4P7GDn3#vJWwb*PbfQ1CpSqXHb^8hL?SXmAu&N9FhC$LKOinXA1OB+CNml) zG8rT=7$PkeAuJXjDHI+f5gjKK9VQbPAP^TH5EmW~6&wx^5(x>m4IG@m{bn474g*ySX0HJ!n zPDaPMGiJf)uqsAK2g*d*z)eTXmQ8djR0t4a31~J~goTEOLpfOkT3-VLJ64E8J5mG? zEOk&9I|op3Mmdd|q)`H(Kb56l8ZT(5l$r&7q_BjFt2?%nNxHtjlDtYOm7|(kJ9mgS zR0lE_v|tP&7Hywbs!$tat4{?M7lEfp%xD`UEYV&PI}u(3gGAZg8w}QTsPo-W5G82i z^7aK_v4aH*88$koo3bm1z&Zkg9Z5l_M4ti|HdH($BMpHBp1|x9hEQLW9X6B+Tgj4F zNhbng#)OGdWlMQG7(sj^kyp;NhcImxDktSYgoRXQNeNNN-;@L_LZ%T=Km<1^C6+jp z(m`Xl11ls%8~J0aw-O!h2~3cJL4b%yWEcag)QiwmX*$TbfmDhF9a0$8bGsTYlARHRUCQsc5)ig8^eV xWH*D!ju9igeqqXs*ux!JZpo?&(k!_;zy3B?TkMGQR!49%Gg4QUMZX$%z!38nAq*M8 z4Cz4(seueB0Sw9h42gaW3BC+b9t@!_48cwe0S*klb_{M73=YN&7P<`PIt<2|42J3q z20*07prOE^F3+GQ#~>lhz|X_L&c?vT%D}?R00cmnf+$p=_>+Z^fx(hN2P6#glLOoT z19J*Ibfo%EESc27WikK4ijr4zbX!eVm7OlV)^l^+jlw9wBaQlnZF${mPo-U-utNI6 zht+lG-#^bt%rG^nb7>6ZmzCw?jAd6=5Y^=f%yKiyn;A3BvVB&FxOVIu=XvupTIw2> zn=WbfTDx)6%Jp6b%VwGCw&pBPT9>e3U&sN=y)jbCn&mNqrh?Ix5r_Sx_|o&{>^RJ? zvfuS~u9m5$rmmsvnWzH~uY_!IH;Cd9S62~!#mFIRDxRcW+qcs@`1Oe%$+uZDIwv+L z>bFFTcolanjdiJ5uah=w1^Z~$+3D2b&#m5=C z8u_$#C5XJ}Zj7Gqx^SKMqK}WyWd`ds6bO9lY+dJ_GHFi2dgcy3jdgoDHO!x^7A-YD XxZsESrs=yy7*9@e-MM+b0)sUG@SWKk literal 0 HcmV?d00001 diff --git a/images/mood/sam/cranky.gif b/images/mood/sam/cranky.gif new file mode 100644 index 0000000000000000000000000000000000000000..cb27bba8bf003a2b8e11f8e50d51a3571ee9db18 GIT binary patch literal 592 zcmZ?wbhEHbG-5DfxcZ;r|NsAIj2TWEF`O`B*l)nFS(jmxF2gb{hGm)zbJQ7Tt24|} zW0;)L?_!*3O8FaZBbhsI`xEM6K z7}U8K)PRVSL4kuoo`XS-gMo*cfs=`Wm63sofq{_$1b_|((@;Y3Cks&Ann4G|2l>f? z?f-$f1s*z5{U?@8>fo}Ne_=(*t2Mf<=Bvt1m)`5Sx$efqD8VC*`h{g~yLWC*{rt8s z{{4?VaS^AtZBI83t9DKdU=@?nR^?-j<hRJ_2z+QA|) zd4otW!x6^ZpieC&UnCYZ_-IOR?07lh-3t*;)4FZSlP0bZ$@{=plJJF1`y#LYlBgwF zS5I;;4?h`o_~#M__NtgCysB3f7;o!&PMvnPbIGdXjalEF71zF)ukR7I Z<-yF^JD8_RhfXQocWchh;&}=T)&S^r#J~Um literal 0 HcmV?d00001 diff --git a/images/mood/sam/crappy.gif b/images/mood/sam/crappy.gif new file mode 100644 index 0000000000000000000000000000000000000000..e0d413f8a4c3e5525f066916dc2a93de67ab8bf6 GIT binary patch literal 616 zcmZ?wbhEHbG-5DfxcZ;r|NsAKGykVd|D7`JS3>{$sI~`@ZTEv~&ij=e@hd&-TYSK$ zc)v^PO6SxS&MC_s;^*7N&bEo1Y85uYGOXX&x53z_-oT^6z`b18xj@G`U&}sI(=J`Z zCPl+KS@TS~)8O3gt`$wExgTvXmfMBZ3L)=*g1 zKtMu6KwO<)T#buQf{l}(nT4H+g^h`cg@FO&NFa$7DE?$&WMD97&;iMU{N%v)|G?}5 z4;`ug6H6v#a9Pa1u%hJE6x~+iRb{73&-EBPmY-2r$?^EW^dDZkkFQVNeA>Wv4qu3Q z-P_;)8=Q#bTWn`T^JL?xUE!4O?dOc6W zSY1O)U;0GU!D;*Q&$;S_aPx7TP!MQkViFZ?o4~;L+~xLmo~khKm;W*Kw`uPC9gc_ta=MElIXwZf8f+<6DYn zT<&aaWr_~4liuve+S3rCcETcIbF{ztwQI5$7@8bSmDHpY0}hr<-!(^nLeQaId5j{= z(q9S+mwmd##FAE8RCPw`}7iLfwO0|3bV;5+~T literal 0 HcmV?d00001 diff --git a/images/mood/sam/curious.gif b/images/mood/sam/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..b8f49d66ef8ad42500ce4ba633ff525e5959bf7c GIT binary patch literal 645 zcmV;00($*NNk%w1VKM+R0M-8h|NsA)%x0I!W0%HakicM%zhH*5T86S&eWp`}gvIG@m{bn3({g*pLs%k2hq z#;kYTNVy8*ZxJ>~yS=bw^DR(R8U}9d%J2LCLpWIjT3iDII#z%~I#LD=Ffb4S0s<-| z5nc#{P+&(mg>Rx$0-ji-UKuQ2rbLaXqpf{{usX7fO18SYinvNCjiI7iI&pwCT?Toz zSFdi$Pyz-OFfJr83R0y=$f+VK%Ul&Y6k7v(uCP!U4QOwz&gxMSBwpL;@+vwiDlj!0 z;i%m5fkWP~UPn@lf{CH1O~S$N+;bm%xGr zz<@givAk?g3~X4{B_>XFbreAEA^@FT!FiF~1?>bQqfwAthyd|-i)p=SEP<%7AtDvA fN@|ofxDyvJi#mv|q~#{j$|Zt!?K;jJR}cU@wp8$@ literal 0 HcmV?d00001 diff --git a/images/mood/sam/depressed.gif b/images/mood/sam/depressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..b12d5c0f1f4c8aff6bd54db7f42d922136e462a7 GIT binary patch literal 618 zcmZ?wbhEHbG-5DfxcZ;r|NsAKGykVd|D7`JSHgr33H|S*+8#u<-4Cw45L|QKujG(# z@d2OW{m!W??BeFw#m=^gnr0I@)hcX)WmvyONRLHuw~1eqiEpE^Z-cQ!n4-Ceys?O^ zp|GrhfP{vCxH`YM8W*1g8z(*y|dyawX^2*%#u-35))=G z=xS=6AKl#;y>;8V&7S)6<`?R8mxPE3luJrZ4c`;Uqd1FGgC~G#iSvxCa%ljLI{45h5@NuyQ1~3TyNM&iV=82GL zDhlx2->xZZ;gV#K#4}UHexblpLEm7%g#ip!OPoFkdmCsRUitHYQrkX#;WUY*PN$YQ z8NB$T`odrl<*eCRPEp9M8`?JT9Fu5^&>FD88mwZxYvVgz({Sdy?Xib z<@4vypFMl_^y$;bj~_pL`0&Al2lwyazkB!YojZ4K-@bk0#*OROuV1}-^~#ki7cN{l zfByWrbLY;UJ$vfZsS_to96562@ZrO|ckkY{YuC=5JGX7ywsq^)EnBv1-n@C^#*G^` zY*@d3{hBpvR;^mKWXX~R3l_|qH*e0IIn$?4pFDYTe}8{RM@K_LLw$XHZEbCNd3i}m zNkKtDetv##ZfN;O=z1vug`*wNy}?~>--ffx_eiyoVI?$#!by@ zr*7Ud*~`Pj)YMGhdh49_mA*bJJZHBYn(e_h@5q@$+b?a~zJBKQX=|=t+j#dv_Y4o~ z-LrkAq!blZ^etQ`blz0JYXG7EFM=rK3$tUT9!Onl{!|CIaZH2RE#)Ni!@DvGfaOlNO&+ucP&G3 zEJJT9KWQmGXDB>mC_7^(J7Om~VJ13YBsW_mHd-PxRU$G}Au>}SFi;;ZO&TUZ7$rRx zA~+TyHx(Z=6dyAb9WfIfFc26h5Emy87bXf07zPOs0|W;G1O@^E1ONa4|Ns9000000 z00000A^8LW002AyEC2ui05SkF06+%+K%Q_&EE{)AIG@m{bn3hILw-~ZAtVBrh5aQfo#x zbeUR~JcgQ77%qWFo}X!hdVQZboPx!z*3ciicx{M;@xm5 literal 0 HcmV?d00001 diff --git a/images/mood/sam/discontent.gif b/images/mood/sam/discontent.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd59983e363bd2cd8523c981d6f9f825abcc3dc9 GIT binary patch literal 592 zcmZ?wbhEHbG-5DfxcZ;r|NsAKGykVd|D7`JS3>{$sI~`@ZTEv~&ifSacTQd55I^58 zZjN2-Y@5ibR$&t?!}^VV8w@-ube#)yob$EpGqvn8H0{zgY*I9=lhv#e)GXsw%%YTx zLzRp|6pe!A^?YTt+@#bTBvfp~lq|#)%|+ymMPvC(UqrgK)s{h22Ng7-h^DnF@d6lBu zs=KP}bm_JpUB~h{Kc;XzJ}`ZT*Y4vhQ$N4$i+}%PPuz)9Y)4{s!>XO@0@)SVO8mIQ zy8N@hdD4&hJIFI*a&+b8g7u?Rn#w#Sx5Q})c|^Y?`X zD_-~pKFEn~)c8F`rMak~xg%k!$b=INM`h*vll98Jq(4|PEw?w~ScJyHMJiL-brOOS zrwT3?$-BlE@L)oM^u%Q)DpLY>v97u-;-(wBb=vz*MlR)D0kQL+F<6Z{lk)%VNJLtw6aTD70uXEO-lTZ7ZS(Yyxw(SY_4tW9m|uuz6`q zfg;e74QtVWO0S|IS~s$+Y<7$-fH<3sn7GBr2%t`rp$}8^0pY*cmy?{=@8oRNsy4}9`g%~;oS({4&&cDn7EC{J_H%uXE1aDznsTlI|3fuIfwpMeCNVdJFeK#Nu%R5 z+N<%68O{@EIgZAoa2$cvgqkYQ2XIOc^IjY)$I&vFO7Lkhs&>J+6Z>|cvJi$s=(nRn zi*gN0l_<$aaUOP3*q#er4peebGHj9JgA8n5kL+~F(~y-4Sqh{iGLw<95DC%~L5h$Z z4~Y<>Sj4YF%nC$?Ba{OU8^jVUurO}1{>O;t2o|72+M?s)CsgP>t+QBdwf4ID28T_? zYHne1<5tVK&a*6n#|w3;8ZBz~A?fv; zP$1y*I2$BR-+u*vk|E1Bb&)lSiKK+5H_|PdTWb{!4b?*xg1~U|q5h0ovgk#THF{!s z&-WLfyJ}i*Q-`O>b(L9VqFqCD*)@wRjA`S0Ov?z{?wKIpyGlRk@YJ@AdJIPOnK(*4 zyJo-a5vhyIStAN+Kjey%QVZy5t*fP!JFoG*a?#^WRbuTIv-C)S6ZLVXFgDNF&0iZJ z)_oG*bki_&rdXR^dibUBL_-JPbw#YMk0>-3PzR-U*UFTGJ;!47YMI%6;A`6NIoa)Z z4DXQ!JSM&JhcEm5*<|1BBX+_5-z0~K2fdfquVlS$pZko_^~G1P#Lt4yoz#oY!nvGN z8me>O=vM>Y{-}++`H!pb{@BfVW9CPyQh%Mc@_I#M3430CG|EjGu>33uKeAlG7M#o& zTuM!`L$cZB=51lV#DL**hbEe}ml4g5lX)BS<5T!hgt0C)O?s5Eu1Y%6lr#a3a6I@| YTCS3@DV`X~uB__ll&`OpkB_8>hlIPkgtN1ly}hWNov4kCh?SMF zxw(*;nUJxupplWFzP^B-9>10rpSn7)ni{W?61Sovx4b-;tSpzbG^eB_hlB)&xHyNX zC_5h?D<>y23kxF?6C(oy$ZbFpKT!P10#s_kpaW6{@{&1g9Fwu;$s@i*_djsO;;9UZrdWV^P^>WMPj&D68H;RTDB3R_-?ZbVyq zN2jxX6jO6ZpJ8~Hb8@T%Upxz!k|ckTU!uEye{o!2#iGb%S;89et6U7TB*pVoIM_J& zC1o`n`26qI-&?)5ulcXBKhb8B%C&hF%Pn3_;BI8Ow^vYv zXP3&4DO3FmES(k{I2k@CW8s&OyQwm}?fm3!yb-GKyuRc2g-Hxj7U9|{1>G4^U WH)YQ0+v@7dP#|Taj{x%u1adE zQbK}4e7r(ztbA0ITx6tNSeR@`h>V|~l&`OpkB_8>hlIPkgo}%~v$L4Jy{Mg?sEv(? zwY7+qm9V9yu(`RAnVFEWv7nKWpn-vao*uuJ7N43LuaXkCq9V7vJeRC2m$Wpegan7U zI0qjeD<>y23kxF?6C(oy$ZbFpKT!P10#s_kpaW6{@{&1g9Fwu;$s@i*_dDIqLIJ67B(Q_^9u2@^Y4GR>qjvag)|$6 z*E=T%v5T|%@u~+)vA0YLOmx?8sfcZ!H#0I`Shzx1D}JGiVLYp#aApvzu!6+=kX1E} zbNvl>c6#kQbhzVym+G21a}7)D^-e7fU||c<($bSsy%MlLDV9}AfqP>hYkxe`T@$?& z2?h1%v4VztF-%pf_XJ5iKK=7oj7)>W^ls4=dg@7YEDC*{ZDMBan-a0$*ukZmVSN(? z6An092uOL{-Nb%~U#lVLlB9LfSp_}uvtg&^WL|1L=x8x_Nwa5gkHRsVXuh*CEuT6Y zX4K9TKttdH&WcWWofLQ6SF=`h|i5XW$(8a2#f64 w$MC#``BZS1c93yV%Jj<-Q=H0#L?w)N8y>iH=cz>Xd8NiSUhDJ!`~?`S0kg~QsQ>@~ literal 0 HcmV?d00001 diff --git a/images/mood/sam/embarrassed.gif b/images/mood/sam/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..1076e20c0adce5723480f93d185569b8e24302d7 GIT binary patch literal 1599 zcmbW$`9ISS0LSqUZH#Y+p@k4RMkQp?rN?A86Fp2{UF4V*LrJJdiRLI*Wh?7KZpP!A zsFsLt)@DMva*WLti)F(cn_+y{zwmwj@cQlj;~RrTA37X(05||hH-HU=_4N(8d|ke_ zzP7r)y0X3^TbC`%Wm5UFL@r&DOBUrz3u{aBYm4Hwg}Jr)*){RZs)AUwIwxG6onD>! zy($u{D2S$3gp(`NzgB+pR|FF>!MJSdr|j3Lj6br>A6}jqS{~;u|Ku)@4NAubq@x_^ zNWXNrPdd~q8S0Vnen`08lEE&?Ktc8FVi$X%t7)N=wa~#_ z_|BOB-ZF2Ds+nv0Fvp_LG2YH9%!pOibeDyA-z!ezCidcU-&jpSp90cDrfpl_Vnu)zbmM}%d-UK zPXx5bf>N@eBy*}TW2zv1GCy@PFXh+E1pbS={O9rfXL0-xW9Ke&Ug5Z4==`x7v;%| zJjMO|f%~b78|lHl=FW{c$-ROdyy7|-ju{Mf86=_xh|U9-k(^7%IRr;e&@m4FXn(+= zet(C)i-^7pw!P=Ad(Z9f@q+i@%zt>Ac6%6gpET^k?(B4dbvkKwD12piI6*rcx3nMo ztNn=D_rt18CiAmGLp_~Nr_pHn`T2QydAZN1+1c4tDwRT^kjdoC%*>38j6{WNp$Q2I zBoZk;K0YeQFY;Q%AO7cwL}ExtNN{j4fj|ff3c};@fq{V+J>4%{xNzQK?^*l3-rnA) zPoKu&a2_5WXf)c%$q9)>9#XJ0b#QP%AP{zTb_Z;%ZEbCBY;5*hm|0m_Sz21c;c#Qb$9LY^fYE|HbA8= zR#B8eAh4Ft!R-4WrxsmQB}t8GrcTi{HoBv)bKMm5su%Aq%hH^rIHodlh$MDm222ki#Ophsys0jhMRSOM2a3hj0Pm| zcsC+^PG-f%int?)OjM z?%cE^(gv+&mdIkbY=dXn<%VGfG+cCJEeatR+u zx3}HkzQ+4UGjq@I{OakJlQ~!9rG7clnqWU)LIu4nGTE#KXUM^6x4!%&W8?N9BDFoD zVyzZ~4cn8u^)xF(T5@lyi3Dy465IPSO`ji_a+{?D`-b3U)j+K#&TX`sJL{E~z6@jQ zf*F-=XHe5|rlMeix~oJTXVGB6On22FkrTH#(uy}#i{+}gszVnGw0F3_wirRxpEF5U zv9n>g?7S(g#_SAmg(arMIhuMy{-%WNP7k2D4m{qCwS#CAA=k0+yy)v`MnoHE5>b2v z5rNM*C`mOWSmaCulp}kZ_kRtMxCZClgQdVq;vmR(n_xQ41`)|h;3W3(tk!S#O^u+m zOu`p6c&4RJalP|>jZJQQsv literal 0 HcmV?d00001 diff --git a/images/mood/sam/energetic.gif b/images/mood/sam/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..089e4e1b84a0725e63710d50db815f88e9a3a065 GIT binary patch literal 893 zcmd7PYfq8^0LAh1$Rmo;psaLeDvp^VHccB?n2@28Ia$_f+UBhb_9CUVNw2tSCUOzh z#n3>iiB>b$Wo=QB*j8wS%W|1Zbf#A8vei~>ZkFGo-zWH=ogzsgKeuKpwqkx6%PSBH z;m;p@|Bhe~)6)n9@ah%3UU)os@&tG8puZn37kYbPx1*~IHXF{Lht&$R8733j+o9K^ zwG|o-)M_Y|P$4WRj8~)MFkEVKzTW& zQk0dUv=k*J5DJl>4}k!DK6pIj5s| zk|2n58&`SEgDnM9a|1JyiAN9J@w~nT?I$a9x`!pY;u!Y_KAOZo`qRRSZwGg(+Z4}# z9@G_WV>#%G2ZLCz*|1(xQxRKTSg0h5WdTKGZ9kK9Y$|M9&vR1xVpiS0&Z$m6wZQk! zjSn4Wb(^@Jq(-ln9Vb3E8l2I_x>Sp@r>(nH6dEJ3YLj5tJGG~n+BUUx`s%xz-4;hO zJ(-lPVLhH?`nn(9|62awG=u2MHEfY8<+jeHyGdWzaqpAI4$XgyCfA1cWys?DZaU>Q znJ{+5K+^ogc*;}mCsCgAUh%(-UR4h$5y_Oz9d@ z=SRu4O^uVj#E>U1ZQ%wjKyRXy%>H7()zYkyLQnQ0n$zpw*nFDsV$Mmv*tq!HKN@5mZ;UAOZP>qd`nb;UK9sqY90CODxavcC~8~|t<0AUyaU>E>j7yw!p09h6Q zR22YI6#!Bd08tbGP!s@96aY;V07()6ND=@<5dcCF06-7`J`Vsm4gfO^05A*yEeilF z3jiq!04E9nCJF!|2ml}m03Qed9tZ#&2LKEM00{yB1pxp80003100000|Ns9000000 z00000A^8LW002AyEC2ui05SkF06+%+K%Q_&EE_jVIG+I&14@M+P!6hXDa2L3 z)J)c?I)J}8qxa0NGEgi+`40qHePsaayVOyLu+ga zID}seHJV^`MmBq+d7wO&q-+-~bEcK4umO{bjj=ecluEa|ytBDUEU2UjPB<)-cV{6X zZ3Q@wRJdw;3@@He7c-?u+H)KsD%W5VI1+4zudz=W4A9%@>QxUV@9?oII4UYHGaTYo z(nQ50<;w`Gfpb(S>V~k`uOl;N2#Xf+p~Z{HB(lL#5o3{CwhB@brh=KC0tcO-OT>^0 z$~+vVR6&7A#he$!&Ty!}MxhdcfpZ*$_!r>Cn2kw*>dDaQ$paKbzlh|~vSEM%QB_X! z#xLs=2{z1}aW&CuDhNE;oY?H-i=zgC-Y)Iv0Z)7lQ%^ zgFFX=90vmrGXp0R11lo~69WSy0|)>e38t|Sia%L^YRnmQKyn~IIk5ddFuTA*N2>qC zl1Uz17RT|X{SGged6(U*F(t<&q+qkdtXPg$y&rpp;jLe(Tny*<=! zOcdAuU^}z%;-cgI$BpJa?BIK%+PkiS)p_NrC5t+f0wh>M5-y7fb@|LW=%AP&(PzuQ z+9kwj)mcW~TdNdgW-iH4oM*@1GDFhsslW`8`63@8kE*V+l=@S+^^=0zrHt>JRyDbQ z%;;ckyRnM5q48*>LD6%z1Vgc0t4d?;jD(6~T44qvX$N>GFECVCAHVj*D+SiucY`kN wVR+@>824;{j+MuOsU51WCp`JmkM7KtI9jWge@APIc3E)zj@;LAA}kEn0LMJewEzGB literal 0 HcmV?d00001 diff --git a/images/mood/sam/enthralled.gif b/images/mood/sam/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..465d717aa498f490fdde3634b7fc17a24d5c51e2 GIT binary patch literal 612 zcmV-q0-OCuNk%w1VKM+R0M-8h|NsBY0L;k($H)T4zW~3p0JE|HvZes0oB*7g0GpZs znwbEZkpPi~0ET}6e|!LZcK~;E0CaNzb8-N3W&mbj0AODLUs?cKSpZp708~=|Q&Ip@ zPykR*08dQ-O-ukxN&rep07*yyNJIccLI6TP06#teJ~#k4GXOI(05UHCFD(EqEC4Ji z04XN}BqsnTCIBWS03{&+As_%C9{?X703I3u8WRB$3;+xU00spB1p@#B00030|Nj60 z00000A^8LW002DzEC2ui05SkF06+%+z@BhOEE@+)IG@m{bn3({g*mEr%XQ|A z*{--zQW3;~FOi0Bi)qWIyM4Rb@A&)>7e?o-dP99v6clIDfnb_}Br#KR+1SG;$pS8?gyhsEgS(_uAmG?Z<($wt;XWS7 zFaltktU@igpej$>RVOr{P61mFXMqg+w&WXGkO2am*f5^ug0Rx10yJDe7!^!bn*sDcfhh|J$TqTrj!Jr)d46va0Qf#qSk1Of{LWf7ExqAZ2NYPHD%0*fQKAcWLvU@2l_X)slBLTgBt zmj;0nAMK46Gj5uciqX8I!a5;p@L0k@Fa%Yc#Fo4TZLW$!_ zj8GCF1ma4ZP?Cg_B2-dBMUyHysZx?E6^x=J!vG*iGCGRUQ;Y#dF-q4-F()WpkMx~- zAsCVB2BrE@seVeTyNMDs#SB6SPV1)-jKoMKt+%0soKg+a`lqC_mo_+XsouFqaVdgP z1bu?m&tasBQr#q#gU+*Hl*B0=DesXoQxJ?w85^y4P^wXa?!-t2gb);`Y28zt(j%CZ zkQz`Y9*n^VfuJPlWc$DVV-7f@#0ssf_{yX${nGk`_P`C@zx{MYr=o1+x390E5 zlEQU*@O1YBOYEakyR~lCdm;TmM7g#PJPo{2IZd*IdH?Fiaz^!Al*tS&fWubc)qnZcT^i6`6Kri4~ zjqTR4y{>1Ytj`yXK=F?28g@Sy^n`}ib*aV7qA;o9WKis%4FSPYy3r`Ju(`ZticM=8 z!|MejdHt_1T|O&o#zp&9OymJF%bLt$M?tA%=Jj(MN3rr;BOtT(-hVbs4cLL^v9cJH z>c4ueCfm0uS@NLM_g=|N{mT{!cVQ_|JagNu6{HS@xA5{GDP$?-@kc(*k2I<^9?@w( ze2gp2ohl8b%UlFVfrQ%zx% zAKMiEq`l)+$`h5xDhJcv-nsZyaE0eX5qu_JXqsvI$a?9HHgqQ8?&h^RnU?P@F#5M0 ziJVFDj*(#Oec3{g%gcMA=x^hF)()Nbi?(tE8S2@`zL_G|6_xH~)$;D$w^c=_*^5G2 z&eJ<1t={P&5gn-ug{dju-($~a`LZPYx02kl;=2d1oPQ3r9nXiqJ>Z+U=kNNOdAraf ztQOF?A+-u(LxO!a3yOa+eRez6ExG`P>P77OxM`T<5n3{Rk^`-O%yN%14E>Rm6jG3s zv2we@;v!hDwn!tVPZMAO|eyNlfMBVDHx~Fy$|o0$yU#LTd(+wnpsYS7a8u zyN;x5+yW{VTU`8ih>FI4{moW*Bf(ao@o)>%SKV0FX#Bt<{Mf6$%Wqe`7(WnKJ|R;I zv-2iP#A7i@J~?)CpVzkc&dImbj-M&*7{!^Vrv5K$qjujsY}+!JvE*o#sdFK`<0!O+%kf)aeu2AM^6Z2G4B~N7VqZ`d=b)4k!Qs literal 0 HcmV?d00001 diff --git a/images/mood/sam/exanimate.gif b/images/mood/sam/exanimate.gif new file mode 100644 index 0000000000000000000000000000000000000000..b8e2ae07cf50bbaf3217fe57c7b418af939a0a1c GIT binary patch literal 822 zcmZ?wbhEHbG-5Dfc=n&+|NsAI&YU@U^5lsVCk`Aquz&yl&6_uG+O%oevSoAT%$YfJ zW_x>kTU%R0LqmOieN9bGMMXtz&!j0_A83_2h$fa1h~{eOc)Q*%peTYE=mSBnN?U;l)OlP33BcQ@Hg znKgS(pH17$xr?|pbXgZM&TlcB!)L^?Vue|E@5XJG(|7LLy{FlF;R>5+dz%kzJHD#T z`uLeyCmoKRoh+_9_x#Z*k}@kdFpA2^D5!9=Z9BYY|0SF2N4j3W|M2{6r|!kGHbzG* zFCCoz?a!PWoVTuP-sviuqx7L;1E=`H`r}4A7OAf#UF!HeI(C&^Y-rA#74{)wqf;BN z0LNU}C^yZ440o-^hs$(i4a$;_NlU{jU7vGHFQqCv+wB>QI1PH8F@ses)$89 zPOesWy}?){#ApymoEQ|~cRt!2IF_51e z*#0}rE%4Bh>OZk$QU;gBe7`PUueCv$-Vdi#DMajl;Gk&KbgSp~hF?1+mhO3dV5Ud+ z?e`I>!Z{YE5ByoxIT9-)+dDeDtV}Zt%}l#p`uxSY8_J}_!iwEY%NO)dURWrqnLT%L zBA04_sK|y5TwFz26T5qt_?fMo!R`CJ^r!4H)0tEnCN5D}yJb$~ajxSFxCC3$ zJkDf^%c-(u^PBOvx?W#6ZN?(!SG)Xp72du7=&xp`s;Xls^*FIAGqRY0v8ilVn{4I6 zv_mZh>~0KyCOJ*qt}mJs;4opMqeGH=#)SrTca;;9HKzCSWEiDdO=1-N)g*Z;U{QB~ zMo7frhJ)g(ggg99cbB*;A61>dN~6NLi-C>r_6|i)uBS~Gsu=|$It&aOd=xD<+8G8Y zJQp=7H2L!Sm#R}QvwUc$tJ?Q_j64cr4PLIoS6Iag0I zU(MQjm5*B46E-G&tQKr`x^p%wM`l^lLqmzi>4zmAJowx#Ut+%BR(kb8 kWr+p*f)1<+IP~SUxSnLCo?N66AKF?6B8pN zBLffs-2lesW;@?=YjlLr1Fr#F9xCoEGyhtSFHZSTOC-)P_@U zy<{&=4ScO@Ek0Y|pp1a9bF`WHIX>OlA%~AB^v~MR(Ad=MtP#aj64Id^-r}rXJJCPS zO`|iIkB=jCQr8rNl({iNvZ?d?r%&XV$tSD0UQsBquWga`@;DN1W^is9=KX6*=Ms&|=ij!}p^yXeA`XF)s?sc+t%lhu}8 zr*<#yjK;gy`}#5xni-l`3(V3}J#3(H#9sY#ohWDGBAKb8YCWEJPHap(s@36?*EntC z;~CE9Z?T*aJvEo1w`qcHkC9@)o|z#MS|8gddz-XM*i>spX|njqGu7-8aWGI+meVlU zTyZjmqm{Yzc394*$Rmpa>b}f*d2mBR#Ep6(Cl%J;E1sWbT6V7M)~h84T7u%j{EXEZ z8sjI#9+Ca{t5i(r5dTCezos2$w5nwze#(9e&J$tcHfTw3P>>W~>7ri0*3B+Z^fx(192c!z*CkM9w4zmh8bfo%EESY4%WikK4 zijr3~x~+z*!m2AasBq?)&eJSrty!n2v<(k%#&MrWOJ8YC{s36Qqs^7I~2X!|oq=oIwWHaj zICiQw?0v@gaIL=nwJ+b-{`vdo`_H5|pWW5uElQU2=vjSpzqdzS`AnTdvN_%UsDlw10&EX5TU92xz5QzSJP6r^*% zI6Kod{@J3(Pa0T-(gmjVOj(dMcjBWhXLd&FYflwDDpwZjwX~%zZT>O7hZUdw4sR3m bpBm7S$?E7>GJndh>cFY-`x=;885yhr@O#Rv literal 0 HcmV?d00001 diff --git a/images/mood/sam/frustrated.gif b/images/mood/sam/frustrated.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f5bc50c67af5064dbe492794381dcb06dbe4939 GIT binary patch literal 623 zcmZ?wbhEHbG-5DfxcZ;r|NsAIj2TWEF`O`BIAFlA-+*DWF2g2WhGm)zv(y-7sxh=F zF*GPJ)GIL5$TO77F%-)(6v;BAOEIKLG9*ecBuFqsi7`ZqF@%UR1c@>Ph%op8kuZa= zFoTaUgNG1P3g8>hNE;oY?H-i=zgC-Y)Iv0Z)7lQ%^ zgFFX=90vmrGXp0R11lo~69WSy0|)>e38t|Sia%L^YRnmQKyn~IIk5ddFuTA*N2>qC zl1Ua^7V|Hx5a~LgFlXb^0<*VPg01O?ZqJq6`NX8e(5dw*qwz=AhTCt~r%v88q369{ zWmI!ZYnzi{OlfARab&x5MzD~vPzsw+SW1zbVZ;2)Ip&iV#EEHSEtzny%#%gLh`V#k2-RHfXUn1#P`uv`}I-i@4Lh_-2ZJtZlU9I|< zbZ@exNO|U+6%!Y^s!Na4LtpQ3k%Rc}B literal 0 HcmV?d00001 diff --git a/images/mood/sam/giggly.gif b/images/mood/sam/giggly.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8a604a02d761687145203d14b13dd4b66961f1a GIT binary patch literal 860 zcmdUs{WH@60LCBMwXK9mDKgXXW$A5gSi7_B%hVFl;%Z&j!bP3ht{);-*vzEWm{yL> zVIqkR6_*t2MH6?CyE?sTT~~U!i(j1T+L}M3&wcKmU!Uim?UIBT-eES_`0Rw!#V8yu zNAPDDzipTq#LoeIxP_^1jJ4o-3m(_up$UVv7^p#S6?&?0$ADHXu4&OwjQS#&&%$&D zm-A3@5*L)vDWJ}QDjP*dkS|BxAt+@~?8ni)$limj6lCs3Mlud3L!N{K5~Pcf7LUCy z;~*uGBE)V1l42p;ikJ0T)5UO z#Qy{H7sU+_BXXhg!Y4wivskPy(UfY-&Xu3naNYD3m4>QIdXY{|8f#5vJ*lm!v-q;3 zs1~<+ji9x|BG6r|wJmfR|1F;!URuCouJ)gv iQrI8OOU}$n$BvLcX3`U0p3az5SwR_7c{_Y);Qs?jFb`e; literal 0 HcmV?d00001 diff --git a/images/mood/sam/gloomy.gif b/images/mood/sam/gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..3109e300d2df1044fcf84a09943fc485b9c2166c GIT binary patch literal 624 zcmV-$0+0PiNk%w1VKM+R0M-8h|NsAHng3*$`(&2-V2|%whTvI--&1|iQ+&@(cEnC} z!cB9)Omn|OWvD}Br$AqyK3$tSR**SXk2q6{G);jsO@J{-c`!(LEkkfDLvJcSX(~Qw zC_H2+J7Xt0VJ10WB{y6oH(Mk&S|T%5A~IAVGE*NeO&%;t8YVy)CO;S?JQyQ87a}

`8lIG@m{bn474g*&Qt%XRLI zJ3)8cFue%lz?W!CyT`U=^X-mb@A$l4n9BylT{~8LLw-;N9uy9A0uU@82~cZBIa~)U zDF}1~6dVs!lRt)ZTNW;XN26T?37Vujgngu5p@d62xVgE5wn{UqvpX+@ZL?1g5{px{ zsZto9##92#d}A3PC2E1JC@C*C9NJsd@#`dIq@u5X01w%d&q_Jb6Fu?#4x=5-d z9*7a4q`)I^%7Ym%P;^1&Vn-&8DGrrXiei8R1#`0)FqD*JXcP)DrKtP?Gp2z8TU?6j zq5m9)E^S*3FWBz0+ctoWv!M8jTk6Ds1{Pfa zR-Gk4DPb;CS@xwCu5Vx^lIP(9G2#V?&zvLey&_p0j)#_K+WO^h#|)D{WVyiwyQ!|* KwR7hQ0suR|)alRw literal 0 HcmV?d00001 diff --git a/images/mood/sam/groggy.gif b/images/mood/sam/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..49c81805f637b4b2dafc4e1a3141a1bde210d0df GIT binary patch literal 592 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpietyWEqW?7j=S($oisd{m- zT5hgNYN}FftbAmoTv(WFXsAqZu#AU?gtN1ly}hWNov4kCh_$tdm6fo$xsaKekg2JV zv9X|$k)WO)znU7ak`lL~BDcIem#i$8gan7UI0qjeD<>y23kxF?6C(oy$PGY}JfQfK z1!#m05CQ?nPY!JV9i|m{=t%XSSTZSs(_;RG6(v#vbEX}d(s1f+6|?5zZ{B$|ZY)MS zEN-pZnfEp0W(fDAc;T}1?|-+eN0rBwYlhc5C+BzjC%UUw^i1++>WiElC#*0rXqt=W zj7jrq8fR!O?(kZ^dQJOEFZl&?x;2aI)iy5-T#>XZf2xOCiini5l&C0c5DSl}f+k-< z)%<;oBD|Sfu3Qb^lZroZd*OKn1!c99aeLJ7l&y1@@8LWr#g@V(Rj2$mbkF+d3wA6q zNPIo@VDm}_tDT1n9v*1ou;+~0a#X;{^(u?Qljd&uDO@%CDyKB%bMBrP@@Jz(XHnNw z<=iVG9upXvHfgYFIe0WYP@9_DtHV^avS8f-h3QNROE#!)=(sQ~*2ebelwfD(+)kSy ziGv|?E$Y;2%+9{jW}L!wZr`3{#WT|xW~KE92^yT$yfVde*}c$8&q<9eH}`!|UEP+p kPBVLY$rlcz&^1|_pIl>BnrA&a>B6)zsdeY)`3ely0A;nv`~Uy| literal 0 HcmV?d00001 diff --git a/images/mood/sam/happy.gif b/images/mood/sam/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f19694425dd8744ac40814f2c63cae8f1cb204a GIT binary patch literal 569 zcmZ?wbhEHbG-5DfxcZ;rKM|HP6>5?mJZFRUnem7?3K zx2o)P>8_re>moi13La_HpV*q$z4p|zX%iX>0yHi@z0ex}zoD_oNH;MxogC5Xq*XV zlb4E7YC8Oi@y%vu9i2-%8D6Yk;26tzUeM-*?%kbrT{31xY##UbsVg!}-Q~eLf0BpH zc~wTqOIHNDfAffBd|Q2*RYdDdZsmn0e$_nH+Y!O#3z*o$Sg(q;E(tiKHhr#Ya*+@h zFQW*v=#v>SoB10a*g*{Dbewugqv$-@PS8rrY~&tW#Y2v5IAZi;8iLa c-T9$Pgw@%pX77r>(HvrH_II$eGBQ{L0OIbxJ^%m! literal 0 HcmV?d00001 diff --git a/images/mood/sam/high.gif b/images/mood/sam/high.gif new file mode 100644 index 0000000000000000000000000000000000000000..808f55b514e38c9d06c6a7d809df7df5cf37a640 GIT binary patch literal 562 zcmZ?wbhEHbG-5DfxcZ;rKMGE69D=r3Yu&ta%YU?`7gD2QUnk7URUVaNz(NDpF231CR}XNdM> zi1J_vbzum0V(_(NaI;`=FlMmOWiZ!aFwtT#)?_eLXD|RFH3lsu1`P!Ub$JFgIR;fZ z1_@yXejWyPHU>6U1{P)pAON}!MBxUCKUo+V7)%*-KuSP}yIim2DjO;(sq07{joy9hY{+_d ztu9GUKelK7D)k4RXKrxU*MDaC>&JhF{I|-_^%J&LOuV$x=|x(ky!*E$Eiali7fq}5 zQi$rA;_}!{m#g(kcgBJSqqtb32I=jpOgw=yg0(ruZ)KXe<-|NDXI?zS=|3YTt1jiB zk=o`ot_2c13>I}CnmAR&!&SKGl24JR#I4&$H=ku;=Tv!cu*`M!WM1)miX}T(UWqYr e@)gWn(baO(LyL!PSGQOG@vw%!T;GIQ7_0&I9>aqG literal 0 HcmV?d00001 diff --git a/images/mood/sam/hopeful.gif b/images/mood/sam/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..48b02baaef1ff9807dfd9dfcc80594b70642dde1 GIT binary patch literal 883 zcmdUs=}VIV0LGse=QP`F<>pNBT6r?<^}yLSYBP^~YnnMNt!$>1Lek|ClC{e)t2W0wZ^y7i&>+j*o$V^Y(UL22jEUsW>6({~o z;P*I|p29VRxj{_b#^^OTYg?ID9OgLEEH#JK)^?0G!mi^7XflL;n)_A$Ph#XBRmLxKG?v32OV^G(A==fs{UI2w}k$p5r72z zwFPURNIX`Q617HKue+jeXw=3Mh8CmAY%vI%)M6{aOiE(gx(IJF%)3Rb>+H507||rH zpXk*J2OsvgHD2we`v(k|Y0(_>llJk6my;4v-=J9J)J{Dz)5Bg^hIOKMbGFZtw=N5p zv@dABTG+f`9+?y-{;}la!}1`wT+3_c^;Ww;RxqORBz)zinpr_m!tIaIW7KTu6?373 zbo4#*FqrsWHa|+E_YILsT?FwaZZA8yT*3O@mfXw^wDunKyu;^;3x_*YJ-aB1S9fX4 z{Vp|~^4jq6V3ng@o5$I)S3S^N8tERGs^{b!OP6KvxZkGdEn_qFXQsc59{IF<_p_XO zo)*)=eLq=RR6?CIF>bhIoL4Ceed7W4^~~C0Wsc$yZ_LIz>{6lKEhu(bIwRU-RrL%q z`Hx3Txbvf%r}) pcWZ>&t8rsKi&5t;aa4P56*Mtx*71z8^5easDIv9yyaW{>`Ugr+0ulfK literal 0 HcmV?d00001 diff --git a/images/mood/sam/horny.gif b/images/mood/sam/horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..7dec783ae9df9ef98dd05e5ea48480bcaf0180aa GIT binary patch literal 886 zcmdUsYfq8^0EG`hkcvrR>YOVu0W}?d5 z)2taebI#W0TBS%jZMG0?Ycmq(rEFdN)WvFsKci=7J71r(lc0zfN1O~n2o_hd>R=qd z$FMSrZv(JD!b~45op{{|vjIbT47OmP8IS8>BygWVyBcj}FkFVd6gP`eSAZM&(4K)N z7wR08<>2B86lX$}jtgnXOGfTNWGCU&eq0EYnVXV7`*{_UKxtpM&(87ipIStmUv}T5-UvVv4zBPJMy`t9l z_Sl}N7Oc-)oIi52i~p9?ICX#Cr{Jqw=S1fhQ+M0MwyLhY;Yx~=GGf|!ELfOG&oZ=^ zzMYubMeO|$2xgN%Bfd@9XCb$Awsnmy1l8KjPBiiDg`#;4@#WqpBF4(juzoe)E6}JX zmI}}2)BEm51~)cnN?uCHwJ47*A2*IhW%`M+&a;~-kjZ98YP~qh7mSH_kCv6*Qw25K xeeG74G=soSCb>{qLkW7nuq3+d62t78ZYv^ZYX3}D@AQ%9SgP2!#QRu?`UkQ|4gdfE literal 0 HcmV?d00001 diff --git a/images/mood/sam/hungry.gif b/images/mood/sam/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ad91bb86cc912651acfcc41fda10f5e367f1df9 GIT binary patch literal 667 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpietyWEqW=V;9aj{xzs!~dd zVnTvKe7r(joP2Dod}O3tSeUGzpOmk!l#h?3hlhl_yM(i|n7zHIot>zSjfl0ih?SMF zrKPaBxsaKekg>6#k&&Q*fq@}wzBOPEuWvi__q4nD26JaSZ{PRv$z|OC`c2h9RW)eKfrNM7`r@TBQzj@dHk&rwy%eF@wyb4&I+Kk|Rp_aO zraZ5_zAC9*xGN%|J54b9s?shHP=8)xiQtr%-S*^2vE@@gAU}wVe zC*b6g1qoAnyak#Z6MSEaXK8M5m9%tzHHA%R)+?<8A5Xd{7q_`-25b-u2+cI$C^@Ct z#JyU*dq#-2|1^JQKG7SGj(>OJ+7lD>HuQFrp6F3$eJjm|g)FlYoeupJX;@G!YQS{k z<<{ngg)Qeg690N7C%7oe%;GH7TpsH-!msWB)kGl+{b@bfdUvoo-O00GFYs6g>23nK%A6@v~)8004h zw*L-u3p{kB`cEvGl)+^&|H6urS4(tT%~qA2F1^)rbKMR@FTo>?`V-soy4RjcyB_d! zNsug06ZigK{~H>uOcOKAOq*OYEWPsu?@Wc}^gkAzua` zTS!M!%iPRGonB^Jw{2Uy*-LN9bThrqoDE5v5<=L-xDQYEI20oxtFk&qz)T>zHsZ9O z1W$V2ti6Z%?QPVV(z8rP*1tXut?SP%`dPhzLbBcLXES{t^!MG-~M0TMg z^IYCGE@dyCYXzqd=Lm1SFnM|YH8*pKzcMaAjvSE>;80(3LwV@}A@2~O8i!I(zbQ#h z34VqSlT#Y1`<&dAOad5YZ`6~%bM&&(LN;%$MRvbhg!tr{c;qD-f=#YAbuSm&>BlRO ztQoTL^dC#Z2F9n;`kbtFXLPf@P}5sg^JvfRr_QV`)mw87H+;-$U36w$O-UltAvq>a nsT+w2VqPAqh1+M&nd-F4H9<0d>&mGgpRT>UG?<%39jg5?q^z`)9)YO!eloS;e<>lpNWo0EKB*ewV`S|!aIXPKaSeTfY7#Kh< z0g|Kw#h)yU3=Db*1@MBM%y-y}!CTZfRxR0zd7oZC<;*p)b_0w4; z?H*MP$zz3;(~{z3wGXd~tX5udcwQje{2bx3C-dzzwF6WZpV;`=S>)!L!c~(B7aw=7 zU)9K|#uMn0**48}&LqY2duKMuXlZ&pZR%(ikmTbiRdId6$SRD!(uMA7sc=rS`@ay_5P4?V*RFmOoxL5J)vzul)9uc2* zH%@BpqowaAcBg$*a-8#nbGvg24@c?+E+?ji?@v5Rj1m1HG&3#xlag3rt6%^2djeKF NKTprTwgD6+)&L-@*irxh literal 0 HcmV?d00001 diff --git a/images/mood/sam/index.html b/images/mood/sam/index.html new file mode 100644 index 0000000..6682c16 --- /dev/null +++ b/images/mood/sam/index.html @@ -0,0 +1,122 @@ + + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
annoyed.gif
anxious.gif
bored.gif
bouncy.gif
calm.gif
complacent.gif
confused.gif
content.gif
cranky.gif
crappy.gif
curious.gif
depressed.gif
determined.gif
disappointed.gif
discontent.gif
ditzy.gif
drained.gif
drunk.gif
embarrassed.gif
energetic.gif
enfuriated.gif
enraged.gif
enthralled.gif
envious.gif
exanimate.gif
excited.gif
exhausted.gif
flirty.gif
frustrated.gif
giggly.gif
gloomy.gif
groggy.gif
happy.gif
high.gif
hopeful.gif
horny.gif
hungry.gif
hyper.gif
indescribable.gif
indifferent.gif
infuriated.gif
irate.gif
jubilant.gif
lazy.gif
lethargic.gif
listless.gif
lonely.gif
melancholy.gif
mellow.gif
mischieveous.gif
mischievous.gif
moody.gif
morose.gif
nostalgic.gif
okay.gif
optimistic.gif
peaceful.gif
pensive.gif
pessimistic.gif
pissed.gif
recumbant.gif
refreshed.gif
rejuvenated.gif
relaxed.gif
relieved.gif
restless.gif
sad.gif
satisfied.gif
scared.gif
silly.gif
sleepy.gif
sore.gif
stressed.gif
thirsty.gif
thoughtful.gif
tired.gif
touched.gif
uncomfortable.gif
diff --git a/images/mood/sam/indifferent.gif b/images/mood/sam/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a5b181eed77bec1c7204f8342366f9343a7ff6b GIT binary patch literal 612 zcmZ?wbhEHbG-5DfxcZ;rKM{)H2MjVVGLZFrk>CzlfnBjiEk`p(25yJf5K-iXlIeAv1&_J%}MCfFaqR zA;Fg+-iIN|gCW#~A=rr_z=6Tnj={m0!QP0$TA#r}m%&_z!9 zVEgYdx4=V3s{h22NfBHY^DnF@d9_5h)ofMS>C#(0H`mQDbP_z$s9(74X~l&P2Xb!q z9A0~UPu+R(Ylkw-Olw^l0wm*K!gRa61wa)XCGHkdUJHB)_GDW)-y;UK9sqY90CODxavcC~8~|t<0AUyaU>E>j7yw!p09h6Q zR22YI6#!Bd08tbGP!s@96aY;V07()6ND=@<5dcCF06-7`J`Vsm4gfO^05A*yEeilF z3jiq!04E9nCJF!|2ml}m03Qed9tZ#&2LKEM00{yB1pxp80003100000|Ns9000000 z00000A^8LW002AyEC2ui05SkF06+%+K%Q_&EE_jVIG+I&14@M+P!6hXDa2L3 z)J)c?I)J}8qxa0NGEgi+`40qHePsaayVOyLu+ga zID}seHJV^`MmBq+d7wO&q-+-~bEcK4umO{bjj=ecluEa|ytBDUEU2UjPB<)-cV{6X zZ3Q@wRJdw;3@@He7c-?u+H)KsD%W5VI1+4zudz=W4A9%@>QxUV@9?oII4UYHGaTYo z(nQ50<;w`Gfpb(S>V~k`uOl;N2#Xf+p~Z{HB(lL#5o3{CwhB@brh=KC0tcO-OT>^0 z$~+vVR6&7A#he$!&Ty!}MxhdcfpZ*$_!r>Cn2kw*>dDaQ$paKbzlh|~vSEM%QB_X! z#xLs=2{z1}aW&CuDuEIW3hGBg}GYQXWBwX_i=8hCg(OWEcc%_Fwe)@ZPWQ@s1}Ri;T*aL543j*lf00 zIi_TIDZ^+O2179r3UdeyLNp7}5CnY?ssd4ICjh1Xxap4)0g45xax}nA6)T4 zo;R{Rk>!cA9ysHH3_jBMILSjQ4=HxINaiAmixV8gvk}KeEE`8zIKsl=Jy5tK+zoO! zgt|iF3K5AA62T;db{Gg^z@H8Q9e#8$X<#_OiGTw@U|073|MGvefZvYxAxcPg2kd^L zbg`8x%T?-%%Bt!bjao!#b@lp&TiWQ_a;ni_G-;{I=9UhoSnAk8w5lV!EPbZP+PY2& zvx_ZZ86Vz$`fSu%9^Kq)?4p{+RP7C(l#4|oAsc%tqx+Xk3(DDd22W|r@=QNl*dXti zvQB*H{yeRrer|7n-KvqU{Gg=M5Bvj^n|)Au$?4|d=cydRX?P_@6HKqNxCt|P8{uUy z)E6qe^WSHQ_bK!onu(j>eoyQ{-F;;xay|()ZwF#V!dAPX@$4UHyt#9t1?o3%f#TQ$;6)F+UShqN5He~GN1Te;!tfi*qHEY|ZJ}n_C#1};1 znlN9%T~B!Oos~YWBmbCkAD!=Vm+wtCw9yRars|=V_#161hI4>Vk&e6fhX;ImRR@@s9hRUl#E&|gBq;*bCU literal 0 HcmV?d00001 diff --git a/images/mood/sam/jubilant.gif b/images/mood/sam/jubilant.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9701d32837e5d04b19d2a4ae81737f396ce49aa GIT binary patch literal 890 zcmdUs{WH@60LGs&+gfw$2(6?M`g*NQhs&{H(u+`tap$cf*PUJErOsuW*O?f#rK4SGy2?f_x$>K?%B6L*xM(`10MLWf|XTXVYv@W zz4+3JsRuB$VDJ`R)IwK-&TDvBiN+!{6hS3IT^?$3q0E6I8}hTLID;}FWEqg8L7a-b zlgLR#b^?R~WW?fBB+`x|^$3oKBP9&UhmjbHghPni4?zf`f)E*qqX7u>N2nhT>_xCQ z_+H?0;JXXnZt!x2r!zQC*u4Y0R^y1Bj&QRF!N!hlaJ0d8Yiu$HlL0CP6cdn*vC8V2 zwfcXs{Y54Le7LSDuYJO$u88=O{DQ)w;u2|T!ERD{1&PX|$Q9)d9H!D=CgCYn>iP)@jP5dP2_ArOw3&E{FogJ4A+LvUEX5 zVQ#SJpLdmTMr9V&XJ+pw1-@*j(WBX-A7PdyW@=jXmOX*2kO=BMB_SroG^+nz{7ozo zC4xNR#EdRVpEVx$J~Ig2jHa5+61q!-h9;9Iv)`xR&X0|!1bJqS zMn!lXWcf0bd>GHRN&WQXn}~Mk+;+_0Rqmk}v-Xvg*5mkMH!t%lv~VF@_Z3mkH<0uTjL`Jt7+;vw5Mwp=z3wFP@qeU1cv$B@Y(g_>^KN KCEU$v*!vF!p%g~| literal 0 HcmV?d00001 diff --git a/images/mood/sam/lazy.gif b/images/mood/sam/lazy.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2497e74d0a5ffdd2dfa8de5c7c4b8fb3f0fc518 GIT binary patch literal 577 zcmZ?wbhEHbG-5DfxcZ;r|NsAI&YU@U^5lsVC-(2(zj^cKO`A3?TefV@oH?^*&6+uL zW_x>kTU%ReYimP8Lw$XHO-)TjMMY6jQ9(gLetv#NMn+m%T0%lXR8&-CWMoK4NN{j) zKtO=MzrU}quaA$9mzS5Do12S^i<6U+gM)*eot>4Hm6@5Dv9YnPuC9)bj;5xjy1KfW znwo-wg1o%En3$NTsHm{8Fh4&(4-XFq2L~G)8#6OABO@aN1IV>N5*aA|WC2Q8G3bB< zL4I;z`|mKfz(Yr>|HP6>5nLAYFRUneHAlDA?A4c#3!O zy|}HuX$GU&oOZ8un>Mf9;Hf!%hM7*g!J3xvo%_?*JMGJmP&bpElyu5WQ-nLX+T~D} z1b1%b)a(2C6{on~D?X*JuA_hEh(psf)>qnJf+x z?4H3c>vUiSWAZYwI8I|eoe39Qxt4dT{fxXFu7AYD>aI^xLScXG@+JB;L7l(!&P-;K zdNx<5s8FJ5bMdNP@2syJK|O!h`DrCIwr<E$`@y&DSNHeU-kp|zrr`?Y{c N_OwUG8=4pxtO2^u<%a+O literal 0 HcmV?d00001 diff --git a/images/mood/sam/lethargic.gif b/images/mood/sam/lethargic.gif new file mode 100644 index 0000000000000000000000000000000000000000..75c3509c2f2eaaa79bfa2407cb6d359d3b99d336 GIT binary patch literal 594 zcmZ?wbhEHbG-5DfxcZ;r|NsAI&YU@U^5lsVC-(2(zj^cKO`A3?TefV@oH?^*&6+uL zW?NfZLqkJ-eSK|hZB0#0d3kwpadA;mQ9(gLMn*tvTCx7!U({oaBvJ_BTckRQcteZWDqp$C&J1@WMShjvxt#gCF za#@HvhhMInUgyN%KI67YL82-tQ(C77v8$_a2RGN$Ptu>$;S>JcmaKZxC)moo#NbCg;Q?MdRo%JAR6^EWnw|dLd$xPiWLKYv6%$tzk5TGE@9kO7) zNZ;HODGBK%TrA=?4@EC#2%XxV$ZquJbKBV`t-^u(W7h6kv~tSEc@lTeG@S3Y?cXJE zBDOd;D|Dmhies7=5-thtjpZ;|VX$cZ{rK{QSI#nje|#czbK718$3VFRGZXFTvZr2~ LpW8YzFjxZsntI+! literal 0 HcmV?d00001 diff --git a/images/mood/sam/listless.gif b/images/mood/sam/listless.gif new file mode 100644 index 0000000000000000000000000000000000000000..48172441f7fd270f63714232dc82e295e7aa83d2 GIT binary patch literal 595 zcmZ?wbhEHbG-5DfxcZ;r|NsAI&YU@U^5lsVC-(2(zj^cKO`A3?TefWW?Afzs&6+uL zW?NfZLqkJ-eSJ+$O?i2FadB}`QBhi2T0%lXe0+RVR8(YSWJpLzaBy%?P*6ZXfUmEw zkB^Ushlh)ci<6U+y}iAiot?3 z4-Xp~8!Ia-Gcz*-1ISfCk{F=)lZBB1=oKB1VvwI4*#0}rEb!2g>OZk$5(k&X{0l2e zUghYv>S;b|Tu`-F`sC%*Gj-=Lux7Y8Sf6y6TJ0CEJNt{x>r?N4|993+E7l8ZaBdFf zh^=H5kq#(u)2*BuD8fF`rE^+{kaEVP*>mT%)i*8CTh#8oYTf!}Ydn?b%+*tGFItkf z+I_1Zud?*axqUs1d!2NGSdRGjE3szq>+uKX_*XC9?I*&WTe)ce9bUOTu8&KU^pup; zwWKe_pPX`M>PEK((^hd8E7k9M(>t-$g|)lnM8pln6B`s2nmJ-MN+Q@E+SIh`ghl;G zpLsx2;aA6xA1+KCY=QqYSGqrKYEQ0oTOiZXqAJ27?Qr6D>jM^%f*vC#JIfD6;f-?{ ztDGKooH*N7?y=G)vp-rYX-w&8SL$&pN6hlehq`bo#x0t8FFqVf#5V=jDW zo$p@VoltjiTIkz7DpHG4I6Ozatz3{$sI~`@ZTEv~F9g?|_bWZ@S8~Xw zc)xS%3WtOR4)OEt;^x@J&bEo1Y85uYGOXVsq{kw-+t|0kz@tLfxj@G`U&}sI(=J`Z zCPmFMUd23G#Vkt6I8@0fMA0Z%!5~0E-(OzOS4z!6Qq5jW$wExgTvXmfMBZ3L)=*g1 zKtNJcKte-6T%BKBjaOKKi%)`$lb@M|or#5wiHU`Q0pwI5i3SvZvM@3*STg8<#6f;? zVEcbyPJxGxRR4)3lPb6@=3iJ*@@k20tLdt;)1}vXOdZS5XsqOTd|*0<_wM5xQa{UP z80`AEy6*gY?#xKWq*&9iI_Jhu;~=-?e-54o|%`+qBwqmxXZ5nCE@aPp$Y^Akz}p1+kKHY8zvO zOa-I&TAo=b$#XLE@}mp<3bB`5U*`3l(=w30wRrV~g%4cymKieg_;_qpb)BE|Yo5<% zQx-O!imZ$$i5?pt9c=ew$+)s2V3DgqqKoJ%4#O)hb{xWPmK%@XpT^3)L%<`zvz1H0 z)GEPf#gbW5T3yBGam=WEaF*HgRNs%DB* b(TR^rU413PX@)Bt>`H9Kg}XF_k*D3 z%Mz|#EgU8dJ03sFiR77cY=^EigIl;(aqrQZBnM`$NY^D@LJY=rK3<$YU7I{vl{!|CIaZH2RE#)Ni!@DvGfaOlNO&+ucP&G3 zEJJT9KWQmGXDB>mC_7^(J7Oj}U?ewNBsN+iGgTonQy?%{)AIG@m{bn3({g*j@#P|$k4 zIb%-nEjt^j7r`6|6Km|axwdS|nmLz;ORloBs<25jpp`iLv_ z#!4smMATGj3X44hB?dUaV#ctSC=ZoP`r@EroDDxAB^f%!0g4j;bOzWaWTsRuUSe`9 zndR7&F{BIr<}ft<8wH@qNQ57F5tHNaAV%S-_j10GtG*=ALff&_le zP~FPLKmxsQle~0-f&#q{*E7tiWtd&VFtwavLNP;s5kpS_Lw7zyb0$MW8bf^=Lq!5ZK@>xNBtvEh zLwXQHN&rKmA47sKL$oJDlm|no3qy!AL$DKrzdeJm9fN~0gS`=hr5=NYE`zxagNYV{ zu_l9|I)ecasWE6MFsREjsL3%%2s7~WFtD>Ru(2|*Ff#xF(7hlE1{8m?FfuS$Gw6T> zKz?#y`+s0=frpM%|A{4&W^h@|zp$d@)f(Ma^H+@yZ>#2;Cx7!UGxE{Nv-DXr^?t$X zO`Pjbum7>9ZvW=q`{rgfF7-hye9DT79P!+J!8vYbrBmW3TDMLOko;#%z0u2P;Z$?|=Dd~J;ky_GwfI(YYL@tIaM~X)t*F74B4{oc zR~~V|Uz#VYVEW+$9S2+PFlw4>Xy_ZuUWq&V*iYj{;5K)oS=MeUsVviX*c@$| zbz%3!57Q2}^9k$aa0K$$R{l(iU9v=%|6r4U(36)eo4OrTC$Es$U~tH>iRHlxjo|4? zj#HXzSL7(1e0!L+P(yO=)S9FP4rYd_Ry(?%r#A7r#oFb{aJk;GWsz|+SdqN-Nt<|p z?%c&z&6!s=-pLVqyP(PESpQ0ym8I1wS)Oyg*v(jxaP8`(m3&$&W=wq~e_(TXP*Clq gLe4wYO352HX#2alDy}{BaL=9gY3b({fFi&e0J4AGNB{r; literal 0 HcmV?d00001 diff --git a/images/mood/sam/mischieveous.gif b/images/mood/sam/mischieveous.gif new file mode 100644 index 0000000000000000000000000000000000000000..8c6c3f7ec718792d61269df40048fab57f838ec8 GIT binary patch literal 843 zcmdUs{V&u30LGu=+(|k%FIhv}sAw9EwXs&MtVu88&*-yfdw%^qd(MZ2@O`iHz{AHq?CtXkzhM05b6{1HjuoDTv#;m?D> z9ll)f-QdH4w<|nP!NUda`(c4|5^N{990$u0c2=-32b~6*38=={XMe;&{fC_RNu>Zn za1PuLJ_(@jNrXkx;u2Y@yi8Hdr6@_2x~f_!C@&&3^$m?mLRP13J>trvwo;mk1sbNA zu9vJ)RQB}_)INJY`aXBr{kU87es*XzUY;;&oAH*x7IZHPwiJq0uE=w#8PNtM+ z_F6yEpWf_pPObMcXj@?W`Dg=SqI4DRgVT+;SpX^X}ZVc&fyu?RU6+ig>wngX_PZi(QvBZXs~? EAFhJ`SO5S3 literal 0 HcmV?d00001 diff --git a/images/mood/sam/mischievous.gif b/images/mood/sam/mischievous.gif new file mode 100644 index 0000000000000000000000000000000000000000..8c6c3f7ec718792d61269df40048fab57f838ec8 GIT binary patch literal 843 zcmdUs{V&u30LGu=+(|k%FIhv}sAw9EwXs&MtVu88&*-yfdw%^qd(MZ2@O`iHz{AHq?CtXkzhM05b6{1HjuoDTv#;m?D> z9ll)f-QdH4w<|nP!NUda`(c4|5^N{990$u0c2=-32b~6*38=={XMe;&{fC_RNu>Zn za1PuLJ_(@jNrXkx;u2Y@yi8Hdr6@_2x~f_!C@&&3^$m?mLRP13J>trvwo;mk1sbNA zu9vJ)RQB}_)INJY`aXBr{kU87es*XzUY;;&oAH*x7IZHPwiJq0uE=w#8PNtM+ z_F6yEpWf_pPObMcXj@?W`Dg=SqI4DRgVT+;SpX^X}ZVc&fyu?RU6+ig>wngX_PZi(QvBZXs~? EAFhJ`SO5S3 literal 0 HcmV?d00001 diff --git a/images/mood/sam/moody.gif b/images/mood/sam/moody.gif new file mode 100644 index 0000000000000000000000000000000000000000..79d0218b21af86414ed0926730f2644f859532a6 GIT binary patch literal 608 zcmV-m0-yayNk%w1VKM+R0M-8h|NsBYGXTjl0LU@`zc2u^Eda7D0H!JcrYQiNCjgr# z0GcKMnI-^|Bmj{l0EQv}h9LleAOL(H0C*k%cOC$99RPA20B{@tZyW$;8USG!0ALsZ zS{49V764Qg08X08SGCO%ni05&%gO07w!5L=gZ(5dcCF06-7`J`Vso z4*)X_05A*yEeilF3jiq!04E9nCJF!{2ml}m03Qed9tZ#o0{{sE00jX60ssI300000 z0RR90A^8LW002J#EC2ui05SkF06+%+z@KnPEE{)AIG@m{bn474g*&Qt%XRLI z*{=A(f)T`lFY$IpyScYzQ|mf(3HE6G%J2LCLOEG&TW32~fJ0$#Q6elNC@?4-4+T(a zMmda|T9`kJoKzezU7m`en}~mcp*yCDO0KfAs<25gpsg^8Y^bGIxlR%k4+#kb2{#YE zuR=Fs93n23TogMLTYIOz0hEMjp26G_C}O7KZ!SA7E;BbC)SX9~+;6o;q+JO!GbkAt z4U8oaA;LqRDK7pztM{atts6Jcd4XuFqQ#03C8nWx5sbzyhc13(q|MJlhEZ7bals9l zv4c?(DxnwU0S1C7)+Nw#fKY*b2N@(parlE~mjdxZ-E)Q#3es#~#CUL*lnR9$Fr}Pp z$|zjD10GN;bK|ushZ$L^l;t|3>Xfypc0MWKA>WpJCw&E!+oj|-t{{_)L`f9On*$PV u5+s;*D4&ny_(~!0Km>;=ewXA$sS*~hdh0p{8r-n3XhE}PiCzsW2mm|rtI%8k literal 0 HcmV?d00001 diff --git a/images/mood/sam/morose.gif b/images/mood/sam/morose.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc355f655b5ed17ceaef0dadf28dda555802b154 GIT binary patch literal 631 zcmZ?wbhEHbG-5DfxcZ;r|NsAKGykVd|D7`JS3>{$sI~`@ZTEv~F9g?|_bWZ@TYSK$ zc)v%^7U$Fz4hah!;^*7N&bEo1Y85uYGOXX&x52=pLf5%K$2niiK2yssL(?u@!zM+; zI$6ysLB%{;#Vkt6I8@OnSYFRpM$1h~%|TMlUP9GYOvyq_(OgvCL`2?LMAlGP)<8f) zLqJ@eUtEn_P=f0OLuMja9h=OWcfV=VZ?`pD;H>R3m48&!RvMRnhFO z=C+lSx|^nKTffCqci|#q&F-?5Ma$jy1aQmBPOoK?;`e7d;&d=uTuvoETgX^2v3|uN zKXKl|+WE&G3Mk}UbbV2wYOJEFsV8+a;nMp6PEMY`fB8BNr7m&Zp)PhRz|pYd)|~b;s;%STh$6b`JgyOsL^XD&*6ZR%S^e0Di(a& z_`GR~@OdTGotj4-nz=-UmKYf@$2UwikJ@Dtz`)g1|+kqi^`0?K4ro4 zg`3zVG=sKyFfui-RP8&g6-iQvr+h!@*liuEM JX<}fo1^~}`?vMZg literal 0 HcmV?d00001 diff --git a/images/mood/sam/nostalgic.gif b/images/mood/sam/nostalgic.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a67ce59ac2ce1b64ebe78cf77c3abfaa72eb6f7 GIT binary patch literal 623 zcmZ?wbhEHbG-5DfxcZ;r|Ns9CGmROh8!=2XV(2$uXwzk=)ncg8WGGc>h?QrElw$~!WeApG@RwrnlVb3dV(^h<@Q`3|7Gtm%Wv~-vun}Rf7GW?GVlWnD zFcM@i5Ma>bXVBtfP~&A#;$~3fW{~G%kmX{K;bf5DU=ZhE;A3UrWM*JtWME=sU;w)W zNRbE>e**P0=rQPk^nv{3!1mu^dVz>~Cg;4OdBEctlHUTf37+6jNhR50iFtM`S#ghKgWs zFcYh|N?bsiyT+{Qke-AIF51fq1XZ#Yxvp8ebyHi{Rz~gZlfCyGI5=sar}UZ?YkRaS zI+pAT;0W34z9mRdd}$UFhYG*{s>KCj(u%BE{Mx+nVVlqUi*e;wZ@>C3AnDfLuUi$h z6%|ziVhq^RW^s#r`?f)QSvN})lc3U)n*|(UPU;UjPM-X#DrDTN;2iek2Z!VmZ>94( zK@~<%PPH)EJv#Nw??9`Q^d*G}73`C3dNf3)T1<9Y;AlCkkENqiOpEi7Cfh07^uu1+eqiF@M W0TX3jyLf4u%*eg9Ly(n`!5RR6^u?pP#3vr-z4!i;Ii1v$KPsWqHc%RR5{lM zvx};r<~Mq6 z-o9h~R!`NLQw=m5b7m!NNr=*9oyxWEn2BDJxU9;l7=8o(=u($`Q^dK`^QPZD!pNg= z)b&ZOib1=kj_lQG?vtMu?{b^_Jyxai@SiS+D%UDX?J@2GC%YzeHOrMwK zuv}fryk|j(+#ZXBz`1^fcYerTU`S#NStOTf^i|}mCijvFyQXD-UDD82Yu#P4XL*C_ ztX#kOX0DSiKK9i~;@gm7@bF;EHjYDQV}qtk#8_v$H?6taE#D&~TqyRfs9Z@tW`|Pt JHDMM8YXGid-;V$Q literal 0 HcmV?d00001 diff --git a/images/mood/sam/optimistic.gif b/images/mood/sam/optimistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b1527157c846deb3d4c4b19fb6154ada6f24854 GIT binary patch literal 866 zcmdUs{V&u30LGuwIZ|GGnU~6)!WZY|&Xt$U-O-5=I=U9hp`m`^n0Z+ZU+26W=aRd5 zTTU-`tY~8_l~EMMyv>?cD@z&Wt*Nb8i9e&yp6&Vd^Xxet66EcZzy=%hTiDuW6q~QG zF^ttd%y!~q2PU)_*J7X%{q^XpLw7Y=WYEc=DL_*`8n2__8dTX(W}+$s73q+tflNhV z3JQ{upNt$avg45+gR~2{5{(ogE=M9M0tw-W4?}DSVuEq*6ruwW6@W+{BDgr?k05Ud zyukAWmkmD;c)P-j363*7oxpO0$95dx?f`-gM_V`?!O=so+y~RWFra~^59%&#v%O}g z{vQ~>sT4o}=8p2tCp?3#0s&bhEtZv(mX%9c6h)P?%7k`9rR2&J)dR+_sL++VV>69vjw^r@np%YSdkIgD+kV33&H9_`G51h|0v?o;oTB}tk{W;>}V{rks6uO2uzc9~C zV_kYbYp(Z2C-;|-&N;y)PE_9@%eHCFfO9BEQ5kJLrD?Y1R?{fox*oihB?MMx<%*(& zU15D&z4k-u8BrwduD=nxOIVS(6wYV~S~n-@?rcKTNG}``d}3OOpOJj>`CKA%rh&*f zMkP+T6oVp+<7eBJ&8KL1p%uD-UteQe^_1ne^D>rGZ@TE25!Tbv?#;;(n@6q|?te=S zmV>7rt8GP*+9E=%k3>YkQ8O(JUOtct`H5m-m84Q3(jX^_!L0z6fO^!iAn1P>% zft`(kjg^6gnE?oZ?gCMSfZ|UUMg|6B1|5(>ke?jb{vViG;GrYce`3ib4K9oM7gm(K z%F%7r&q_M7plWeX;Fr`hb>{<)w!1i3pFA?H+Hbqo>@R!%o_hcLzp-9gvA$k|OLJvc zfty}ee_W4o=Y(Kkm5fQwQ-at8w1kDYr!uxRG)>i?)$X-w-TGx~ytL-@>#MgHEtwg< z)t^J0y-Q3yXtmR>bTJu4whTUfzWC~h-F{+Rxs{XlE#Z;Pn{~HXNncS>U0d>8{PD+( ziq`@+x@%3~6#n@uUZwuzC&s>$Sr?P;a5rrd((>`Rpm3-)^`7gZ<6evA#V{=Ic+sr6 zczT_eOs!*rqCb<_u}K|sk`kIY68p_oNU*jl8TI?~h|CB(=G&H5@@AhyLF0m0!ETHB z1(Vs=G&kjT6hv7BPPx8p31b*bugKLXCJi>D4ol~c@+(;~p5K_$a#dqep|qXHjagZp wu53bXJA@YI%U{>lz8$nXN$i1Jn9780!Hj_%T2`y1+G|`RH>El_GB8*J0Aj4kq5uE@ literal 0 HcmV?d00001 diff --git a/images/mood/sam/pensive.gif b/images/mood/sam/pensive.gif new file mode 100644 index 0000000000000000000000000000000000000000..9faa82b8acf94aff4c780941ce436cb6cb51630e GIT binary patch literal 621 zcmZ?wbhEHbG-5DfxcZ;r|Ns9CGmROh8!=2XV(2$uXwzk=(PSu5XDC)<$W>v;R$)k0 zVu)8@h?QrElw$~!WeApG@ReflkYI3^U~m>=a1vv%7iF*$Wv~@tun}Rf7GbawW-t?C zFcxGm5@gU9V9?`d(BflI<7H6dW>Dm2kmq8Me**P0=rQPk^nv{3!1mu^dVzLtiAY~ zcb%Sts*|OF+O%!2cWmF1bLw&Un!5AvxdWq^3PPK-E9)Z5gLzezmgHmj?(q;A^$lsOU0 zLPU0}ip-uKbjn>LRYXRKHHBZBH#W@m%n3#j?yRCEPo4(y%ADNvW`>gXL{$y3J8|3f zuD>lj^4CdiK?7?uDQT(qWkA_Rt+mGM0$&-skI6v?cAcpFUliJXw`GR**SXk2q9}I8%!@QiwE7fiq2jFi3bXM|Ukla4bV_ zDnDr{K4&OAWGFjhBsW_mHd-PxRUtA{ATd!OFi;;ZO&lvn8YVy(Bs>=)ITj)~79lqj zA2SpkF%umy6C5uR94-+VDi9bb5Emy87bXrAA_@)|1_=)X1P1~H1_A;E00030|Nj60 z00000A^8LW002DzEC2ui05SkF06+%+z@BhOEE`8lIG@m{bn3({g*mErD|Hy6 zIb%-1Ejt;e7Qq|{6KU+YnYL`o3izhJApaIh=<}wYj>nw@EOinmH|pa8szSPqw6N z4;yh0jZXr~e`XsXC|_I=IS^aCoyblb3~O?nz~azl(?#iWDLE)8Ei@h4o6F*I;6*T7 z1Rxzi#-dNLeNL$LqCw+bLL7N|Nt}3#VITn*F(!jZk<^%A{rou86p_zCgiuoK`3EY8 zgaTX~bePFtN$0u1&7 z40iks#=HzhybK0B40_xQy4(yp+zgsr4C-7AYFrEo91QXt400R{Jj@K7Obo1y3``6R zj0_+E^aYq6dW7On7N8fL7<52R2gQj4`~L=~rskH`w)T$Bt`29){ zGHdpnKD)M=a~JXI8?!EAoZn)_vSQs_tM1o!i`zGLUECYzaS=d87xw!3-ZmPx#J z0#jDC*&M$x`K;5ii<4!H=UzU#UO|TK!r@(eFWTKc()H}s>qjp-jjuj6KC zJ>LH33nt$)F$r)8U}Tq=$g@I2@Zof|dZ&^Op+F`!3qP@%h#M*0v-dJ6NX@A-)xCF| zK`^A_R@x*n9(jX=I~M{UJv!`seu1fmAu}60pQ!a#<0-kqO&qEM5zPy|ADygw$M^EW z#ZC9GtccirY4NU;$3xe)o|!7`wI*vz-_AL9ya^8$amR2>o-cJFASqI1Syz#p)vAT* zKJ&TMGy@JgzVvmeTBtcAFJU`{KLEUr)W70v75P|k=Cx*p} pTVAX;ublnY>xa_)?E8zF%Z1b;6rThnv)|6XyX*6Za#kh=YXCZO>AU~{ literal 0 HcmV?d00001 diff --git a/images/mood/sam/recumbant.gif b/images/mood/sam/recumbant.gif new file mode 100644 index 0000000000000000000000000000000000000000..3cb17255fb50747e4babe92c8a089bcf7b9e6407 GIT binary patch literal 607 zcmZ?wbhEHbG-5DfxcZ;rKMltR(Fib6Hm{82nU&PQ;z|ft~(3HVYpTcSB0#1P=X;BU|1YscVV%wVC*V6MYpqQzjW$zZ6?U;spF z3>pdy>hcU~atso}4E#I{>}(8dtPCv73_t*MCWyiSia%Kx85k@WbU-p7KRK}dcbHS) zp(E9QV#%ZqE{pjWR+PM&qT6b+s_b;>rJkGXDgwO(k2LBBw&iuNJ+*8%@BUlwf7s-S zxm`}Ha;Xhs;}j8Li(wPd)DYqc%yKg>o*FgDqIp`dm}cw@=UFX6`eGszW;ayT%r;rj z=(TRs=2aWK^cPJv(P_+?owPn7ShXXNuQNzaEQp0Y;Go667%4^d6VU=D0@0-r`~9W3 z)AMHRyw9g}!1YTEh^qBk@! zwbh77%~LJZOpTOgdAy^hXPZ!0Bh#Ih(uWG~pNVi93nau`FY(*i!eQ1C;ouh#&a1Pf z&gix&1JCN9eeZ%FOlh8@%k7;PbU^&>||t$ zks*RS2^$lU8VgZ0k_1TLBW@L9Bd{h6(V>V60e>M}gmJ)QBP0M^f3SVww*o9CJeGn^ zfN%xP1q&?9TCD$`z+W^cK!%7#)5T9j^m$T7RaTu;S8KGVs-m6h>h*>OV_k}lk~Er{ z&2?x0rBl zP?S9+i~(?Tpcq zE?&X{l|F51^rFw#k8SZkY!}#+Inkymsb#uyyo6tqx!+&V>0aB*W<#R7+%u=QT1{f5 zw8k&-N|Q@lDCNQ7QKnAOZJydH3sj91Y3RX(xOkvtMXNN!D@a((DmmRltQVe8)Z~z9 z41eyBY4CQc>P9j@Ze+*bMEa)$k zX*#1l!%I6N5=WH`hiS90`eWtcL!Y!hA_3nj4Qba*M6v4Kg>f5+MtSTXd5qK3CBFIR z;wuki5Cph))wUK=av dZwq|~`TCn<3%@&8IikHZ@qwe`J2Ty|?jO|Z7mEM@ literal 0 HcmV?d00001 diff --git a/images/mood/sam/rejuvenated.gif b/images/mood/sam/rejuvenated.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4135524b240b20058efcab24ae231149b083006 GIT binary patch literal 853 zcmdUs=}VIV0LCBN>+}tE-cHC9@@j=nXS1Qc?>v@Tvt#8^;h9=gN`A1U!%Z`F-p>2p z2k-DIB_o{&rY59Df~KSfSxIJu;X#=G8U1+R`TBc!M1H<}w+Jq{__Bw+eI~Ixj-4_5 z9KcdHK6PQL0q+_xT!o=Zs46f}j-EoaW}+z_jp?XMLDfT4K0t92@)MDF7ugAr$3qqe zX)ID=@Hhtd!jTk)giyqX;D!XT7Z808QGtjQBSMU@Gq~!HD}D$)jSvwoc|+obi$a{I z5$K7t9-y4z!3F;~PIBPl0B3tR*}`!@Hn6vXoh587U}Fxp0a#klV1lU*f`NVZ*BsRU zgVi>n2Kaz;pnUKNrLmXdBTG$tlKwO!Gb_zmEjKT}ps*;{Q!b+w6_r)Fbb5KUlI6%F zlxnqUo)vtprjBBHPNxRhOExM>N?-R6sAN=q6HN`KjpUI$PJ1VlZEf0DlRV@%2Exz%5(VM~H_2#c*a(Zifd*e@*VB)uIi5kt)XXrSFPg+KFFiA$y zce6wMK!rE0?k441F|2J5({{I3co|ApT~>=xfJvrGnx!8c%!%fzG6`i2QDDUovGmM& z*V;@eVNR*h(O-h+UJ^Hb_UQFiHBQuw$Yl5L7VYw3_EGq-Y;m497SvhScZX|p`L=7} zKv$cXyM)*t)BZ_6Ys=*kQj_NCO;JO_aFN6);+4ZV$dnK{Cno#mH_Mj_Z9_KcFUc@- z*9q(bF&J8*SgcR{NYa|dtjK5LADV>D`_*9KDOIEfb6P1}J<&YQIHal1cTbF_h#YZ= zlOS1JF5R3k&`w5;3wOHgZM*M!kDsru&T@B-h0A>dDbv_+c4Mvg*h0We`^t-;)Xg5V VIP!C??OHuA+hd1ls&khDf`3UA{96D3 literal 0 HcmV?d00001 diff --git a/images/mood/sam/relaxed.gif b/images/mood/sam/relaxed.gif new file mode 100644 index 0000000000000000000000000000000000000000..39aa188595e66b907eaa851e1e6aaf61c198a71a GIT binary patch literal 601 zcmZ?wbhEHbG-5DfxcZ;rKM z-B49C-E>Z)*QRaT*KP6An>W!^yD?|FKg$Y{o`B5>A$;8FhXYSp9*U7tQeP7zU@8z@ z8gao-iuZi(l)V@DRFdYr$ki}aSJyU_y*b(ao&U@e4|lrj9qRO)*goq3!~YWAnTF2s zylq^{UOd+dP9M$}-uPnk41){DEG6Db*!*BQD(f4?H%E*8X#=;orc2F)3-37{RVOU7 z_@U4=N4Sjj!jiX&oy#7ZEb`|O`LJz`H+$9hEglOB4| zi`Ui|E(+q5=F7OmR}>{GS?Sq$chS#Hd0w9`rgrh0KIdS)?&jFa)t2HlfkEQF=$gY$ hS_`!=sH_#4pu6kD4)x+$2PJ>r*>!a1mU#*c)&K+`+q?h( literal 0 HcmV?d00001 diff --git a/images/mood/sam/relieved.gif b/images/mood/sam/relieved.gif new file mode 100644 index 0000000000000000000000000000000000000000..d1d2cda0e3cc8ca992350220f134bbb046af5daa GIT binary patch literal 663 zcmV;I0%-k5Nk%w1VKM+R0M-8h|NsC0%mDkz0Q$%P@4o=xvjE?+0MDiX!kYlUnEH$P(T1pJ^(;706#JSI4uA-EC4ks05mE9GbsQu zCjc-f05B#1EhGRaAOI&H045#)BOCx2695kk00#yD1_b~F0{{R30RR900000000000 z00000A^8LW0027xEC2ui05SkF06+%+z@2bNEE^|FIG@m{bn2`vg*U2p%XQw2 z*{*m|N)g0?FR_Mhi>=D0wvjS84fbaPcAmnofPsR8J2qixH#USshf^CEZUHA7eO^d5 zk(pX*SejfEDP5e5q67&D2n`ae5)i8l3Nl-Ygoa%Ql}|ULi%Yw|z_h(eFpZu!EsJbh z76)B>9eKJ}#!d+oHwm5uDcaLV%Ul>9Cem6EHxOHYot{q^3%O#W)$UFWA@fD`ZYMV; zCR)hYU~USpcJ|x|I|4)81}O==1xRp19+VV=!c9pK;zol?CrnT|IBZ9a8vMMREXlH^ zGL&0xtaQ0AC6`1kZDwK@NMk0n3MN7@ka8kWC@lmwP!dC6LcS;%m0;3hf`TRw9-@#G zGL@*+gi;m`@d-A7fdcEmh}j^p;1mfqoNd}yRuet22Qq|M;O1`K02o@xy-Dh?6B%x$ z__Zg|>;@EF#FEt%vGJ@UIt`~ul6eCZ xPC_)$!gI-FJrq7lNijG|(OxNRa!k>p<7+54V9+d-8T!`g)PVuR&RtLt06RgD>;M1& literal 0 HcmV?d00001 diff --git a/images/mood/sam/restless.gif b/images/mood/sam/restless.gif new file mode 100644 index 0000000000000000000000000000000000000000..d1428152b4f4eb53b7b3e216a53bd38b406ec573 GIT binary patch literal 626 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpietyWEqW^u7vYN}Fvyh3cO zd}O3tSeUG@uau9Eq=$!uySs$5vzWcTsGXgtjg5%4wTPLSkg>6#k&&RD9>1CzuaXkC zq9V7vJeRC2mxKg|xHtzNA1fy(GYbnN6B8o?1ISV!Nfn^@lLcs^I)e_#G?1Sh*!~}w zT;QQ2)qi5iBnwW9`4?7{NC|XIbDE^!wWwU2Nv+e0+ zd*u%O`rpv#tQ5sm64#~@-sBt`$R*8D9Uv#n>R;%l)b7v6H#wj!o@u6f--0+kxs0W~ z)g02&^UK!OwX9It+T*!%@4oKcUQ)4hCaY95DIQ%BvdeY3ABWteGk#1HuANg1ninV} zETRgPZ<-!Uf&b%#et_HuzSaSZ0w8};~#c2s8ohzIZq>Qx>1?YY*QoNv5 z<^O@z_|baV=>jLzvhKVvXi;`n*qrzzW7&kcx?N`T8Y5Jd6;gGU`uv!z_e?m;UrI|- zg4L0wziHmnk5cy;6eYnI;Tg4thFn(SAFNOc$}v@%3m z{M>dc$E<%|Bd7SWE1IbrXR+|7GjEHPW_lyCOQ4WV!yu7aYPtHhi^2^H3PlZ=t}XRV zc3`qiU-l-)AS1^!)__B%=HKgd6YnG53G3$W%$9Hwva-B4t9zD;pwqsZoA-1zI2fz} D{S?M1 literal 0 HcmV?d00001 diff --git a/images/mood/sam/sad.gif b/images/mood/sam/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..01bc76e8ef02f47c98ecc48bae08b50a6332bf2f GIT binary patch literal 606 zcmZ?wbhEHbG-5DfxcZ;r|NsAKGykVd|D7`JS3>{$sI~`@ZTEv~&ij=d@-05#Q@r0Z zcbjwS3WtORcCoWH}RoUs%b3Mk6N z`S;wZk&H>P#$k2NjlsN9G7@S2b2q)zp_bH)G+o@++>ovC_JH92^-OLK5miu>oIBvYz)|qpTk{;j@zR`Gf5O z>{=yC3zCkix5~J=h%B3CW6!OhdB=H!!W5zE7rB-P68Y2{y(W2D1~?sJ%FXkVnJ~p= z*~w~kt|*0$PaBtbGP7>$S#yomnM>mB7MBSdFUwAxV86Vex%|N)cDCE=($-E`q&0nQ zB=epQFV?ksN&Y-PUOSzAp~}ehX;RhnveSkxwYNXLYI?xT&Zil)WrD-OHSxBJ(j6B> jlNF{eoD;Ba7Hhs+cdxnMPEXcd%U54s8vL1)iNP8Gn_$`8 literal 0 HcmV?d00001 diff --git a/images/mood/sam/satisfied.gif b/images/mood/sam/satisfied.gif new file mode 100644 index 0000000000000000000000000000000000000000..7bd3fd5ba8558dee246e4045a99b4ceeafb09ebd GIT binary patch literal 622 zcmV-!0+IbkNk%w1VKM+R0M-8h|NsC0%mDkz0Q$%P@4o=xvjE?+0MMoY&!zywoB+U@ z0Kb_4wUGd*h5(>|0GxdQn|uJ4cmS1m0FiV6kaGZ!asZ5Q0E=$`foA}KW&nR?0C->k zcV7T-S^#fZ0BKYJXHo!UPyk_009#1_T1Ws@L;zGn08>H$P(T1pJ^)HP06;SUKQaI~ zEdVzx05d57F(&{pCjc-e04N{;Cm#SN9sn2<01pfR2L=EJ1povC00000|Ns9000000 z00000A^8LW002AyEC2ui05SkF06+%+K%Q_&EE{)AIG@m{bn3J%g*d8q%XQ+6 z*{-;eauLLVFVV)WRM2p%vI(!tulT%v&%1@uI5&Jme^3SuFfba68Vd_jjEgIYk56hw zH+7m^mpp}=R2nW_okO2d3@Hr-pizQ+eyupAgG#fvxUaQJGpCz4FoSHZVzgkyTnQsk z#yrDZ9wRFTT@pAFTX$H_*z;^(nq5b1*tmy7BE*Xrg-xtyF(bNr_4?HUsYzR&h7O;w$TLdI zf=CCYV3;}6k(7l>GEH&7q0**{1vn5eOQJJn6a*YxMKt=v04psfJ&6GUg9g1V6>bRC zQi>$gp{DjB_)wxjI6_Q4z}U(O?N_U$+-^ybV2e+DAX;=0iBgJ$H(VUu-6C?EmIg_U zHj}C)#e79!Cdha{aS?~>6Nuyc;z(1W1rPtB75|M3zzHL Ie1ZS~JM!h~X#fBK literal 0 HcmV?d00001 diff --git a/images/mood/sam/scared.gif b/images/mood/sam/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..e5801490aa756f161304e67bf8635d3de31b5d6e GIT binary patch literal 540 zcmZ?wbhEHbG-5DfxcZ;r|NsBLfB*jV>(~4D?;kvPaR2`O^XJbWK74rp{{1Ufte8D} z_SC6UCrp^o-``(RQBhuAUQkewpP!$ZnVFuRo|2N1oSYmL6%`s98XO$#@9*#H>+9y` z=HTF9V`F1sVPS4=Zen6$Y;0_3XlP(ypsTB^p`oF!uCAu0CL<#wB_$;xA;Hhj&(6-y z#>U3N!omOq|3L)tK=CIFBLjm0gAPaw$WIPz{~cx&c<4y=pI9>K1e3-53oA-qrRcW$ zt|~jt8qs|-FTC(4&yhHTD&2o-hi~^iTKS^n?)5!&=hF|quc$Go&&h6dZfWiEujuR! z;FB+R?~7tn(a?|=%+_vdo*Gj(zq)SO^7bWeb^QT4^79w2?FrwsIdEljlAxF@Yb>u0 zcXZ>nSV7M8oZjt0DY;pjWp$)w<<*4uADMFYwAV4eq5x@*3rk~J+1YR1UbT8n)UtP< zzij*v^66{BgP_Hq|2+FuGJ8_?)dOYud|h5E3Kkx0W4$3*b0YPSX=jMk8iNJ_Z)azp zS&|(EijC$jT*@^MEI3o0g(cK?%?W+y$v9Ov{gO+7arz0%{*Mx3RSOoRJE;8OshPo? yaDaWWWA?(Iml#`?bZ4v=Yf(&FrSv+oCH{;)d$#A-&$CAo8xtnX2t*)emaw$U5EcjV z$A~!{zV>3W6B7?%ZiT58hDPWcpi`swI=X6cR}PIFO(nQ_9*yVFa2E9^p(sL4Aubo7 zDj%h}xR8V512~nAf>h+E;7}5BcOfSc*)n9sBXcMA$002isZ#8YMsgIA2<#FgJ`y`3 z5W592VGs!r7JyJLg8U%x1>YOI<#-{$6FwYxyTgl(&1|rp;lhG56HEs<*n&X^-3pd8 zEVI06rTzytE?8Os5^z^!S3VIjmP#b0W#mP9dBvqll4n8HC~B1|N?cV+)TtX(?9~cF ze!a1oatIJuwOHIDBigks5mnV%CqA9+>u5*VskUC#8~Xao#CO_>D+6VNN=HF&hw7eO zJoZ}sLShB`zwc4Wad)Jez%@?PvU4h|E51 z2SFN-mLIu4N}6O;^6IE-#&?DoinU!>pibaUw$TM~I_vLKnoXw{sCnzmBB>%JW3(+e zeJ1TC0@lLf0inyLrbNWzNbAw(CQ#N%>__bed9U zvyJOJV5Yf??zSH{el$xNyuM<4v8b?l7X?zl~iw@mT(DR0hvl4C97Z>2sc vi&>ra{`*Q8UfG;gmdg2HQ-qc!N;oLgo#+eK_D!XG7++6# zk&&RD9>10rpPCx4k`lL~BDcIem#i$8q$G!g1c$gd2Ol3RCnqxt3nLQ~BLf4-89s2c#F|CkM9w2c{Kx=t%XSSTZSt(_;RG6(v#v3#K_uZ8-I|idk#%H}9|t zHtq#QrjMXQH}gJ%*yN6M1whWQEWJG`{E@7U44)k|*KtRk(FI`spa0=Fa`FQ4O~ zo+2uxFoSzW2)`Cj3{&OOqJ{j|{6)Dk8QE^K#VuKOI*^G+D*o)f(+XM&3d-tYk3vpr z+%ddedW3ni?y)5t7cRI@aWFku@izPW`y&Q%62{kNt#F&5&>?0jxASY@IWcD`QBIM9 ziT)eggLK|ZWS=bHtjd_Z$#YWhbF8SERF>+ NJEKm26J}ws1^{#o&j$bi literal 0 HcmV?d00001 diff --git a/images/mood/sam/sore.gif b/images/mood/sam/sore.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d3396a2c79b698fc619ec687337f57080c798ac GIT binary patch literal 625 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpi8jb=%SdU3H@YN}E~f6#k&&RD9>2OeubLXK ziVBaC61Sovx4b-;tSpzLB!`3qhqyQgA0I0xCo>xx6AKF?GczL-6C(oy$PGY}JfQfK z1!#m05CQ?nPY!JV9i|m{=t%XSSTf0j(_;RG6(v#vQ>Go7+;Hk`6|?%{Z{B_x4lG7H zIBu=FA9rEXPqQ4eK7G#9?|=VyR*hoHi)m30Z*WeIVHeAdXO|96bXRQ+W|dYKo{>^E zIf!X$WX@29@8%WK=N-JLtUq?)(*s~0t>EDL7evOTF+n!6>Y zyy8^IVh@!RVKHgecwY6&Yt?HH1qgFy=3noA7Q!tS|K{zx+2slesR=1al z@laDM=O>*%fnVRBw2625F!zD`B8em265^9)c&td?5-4ii#kq~oM?Zeu9l=d6o<|(k z6!~?eyF^LEq18*TP;)|7qg9_4yUd-HYOON`>SHIkS~{4#JgGP#&Q5bfKi6rUcn%w- zz^U9jths0LX&Y@6?DX5RC@?Yf+FV91F`)yA+E-7q2(X>Fu=aJ!>s3YnXNfIHn0)$j z&VLqz&}C(JCT^?QDUr%(Sv2KjM7&_atnd2MPQ_Ju30;5sQfPXLRC#A7cf?^~3*&QD S$=)gFVt3@eW)opyum%91?a{sf literal 0 HcmV?d00001 diff --git a/images/mood/sam/sqlstuff.txt b/images/mood/sam/sqlstuff.txt new file mode 100755 index 0000000..ab5563c --- /dev/null +++ b/images/mood/sam/sqlstuff.txt @@ -0,0 +1,160 @@ +replace into moodthemedata values (3, 2, "/img/mood/sam/angry.gif", 50, 50); + +replace into moodthemedata values (3, 1, "/img/mood/sam/aggravated.gif", 50, 50); + +replace into moodthemedata values (3, 3, "/img/mood/sam/annoyed.gif", 50, 50); + +replace into moodthemedata values (3, 8, "/img/mood/sam/cranky.gif", 50, 50); + +replace into moodthemedata values (3, 12, "/img/mood/sam/enraged.gif", 50, 50); + +replace into moodthemedata values (3, 47, "/img/mood/sam/frustrated.gif", 50, 50); + +replace into moodthemedata values (3, 19, "/img/mood/sam/infuriated.gif", 50, 50); + +replace into moodthemedata values (3, 20, "/img/mood/sam/irate.gif", 50, 50); + +replace into moodthemedata values (3, 23, "/img/mood/sam/moody.gif", 50, 50); + +replace into moodthemedata values (3, 24, "/img/mood/sam/pissed.gif", 50, 50); + +replace into moodthemedata values (3, 28, "/img/mood/sam/stressed.gif", 50, 50); + +replace into moodthemedata values (3, 6, "/img/mood/sam/confused.gif", 50, 50); + +replace into moodthemedata values (3, 56, "/img/mood/sam/curious.gif", 50, 50); + +replace into moodthemedata values (3, 45, "/img/mood/sam/determined.gif", 50, 50); + +replace into moodthemedata values (3, 11, "/img/mood/sam/energetic.gif", 50, 50); + +replace into moodthemedata values (3, 59, "/img/mood/sam/bouncy.gif", 50, 50); + +replace into moodthemedata values (3, 52, "/img/mood/sam/hyper.gif", 50, 50); + +replace into moodthemedata values (3, 13, "/img/mood/sam/enthralled.gif", 50, 50); + +replace into moodthemedata values (3, 15, "/img/mood/sam/happy.gif", 50, 50); + +replace into moodthemedata values (3, 44, "/img/mood/sam/amused.gif", 50, 50); + +replace into moodthemedata values (3, 41, "/img/mood/sam/excited.gif", 50, 50); + +replace into moodthemedata values (3, 16, "/img/mood/sam/high.gif", 50, 50); + +replace into moodthemedata values (3, 17, "/img/mood/sam/horny.gif", 50, 50); + +replace into moodthemedata values (3, 21, "/img/mood/sam/jubilant.gif", 50, 50); + +replace into moodthemedata values (3, 70, "/img/mood/sam/optimistic.gif", 50, 50); + +replace into moodthemedata values (3, 43, "/img/mood/sam/hopeful.gif", 50, 50); + +replace into moodthemedata values (3, 69, "/img/mood/sam/refreshed.gif", 50, 50); + +replace into moodthemedata values (3, 62, "/img/mood/sam/rejuvenated.gif", 50, 50); + + +replace into moodthemedata values (3, 53, "/img/mood/sam/relaxed.gif", 50, 50); + +replace into moodthemedata values (3, 68, "/img/mood/sam/calm.gif", 50, 50); + +replace into moodthemedata values (3, 57, "/img/mood/sam/mellow.gif", 50, 50); + +replace into moodthemedata values (3, 58, "/img/mood/sam/peaceful.gif", 50, 50); + +replace into moodthemedata values (3, 77, "/img/mood/sam/recumbant.gif", 50, 50); + +replace into moodthemedata values (3, 26, "/img/mood/sam/satisfied.gif", 50, 50); + +replace into moodthemedata values (3, 64, "/img/mood/sam/content.gif", 50, 50); + +replace into moodthemedata values (3, 63, "/img/mood/sam/complacent.gif", 50, 50); + +replace into moodthemedata values (3, 65, "/img/mood/sam/indifferent.gif", 50, 50); + +replace into moodthemedata values (3, 42, "/img/mood/sam/relieved.gif", 50, 50); + +replace into moodthemedata values (3, 66, "/img/mood/sam/silly.gif", 50, 50); + + +replace into moodthemedata values (3, 35, "/img/mood/sam/ditzy.gif", 50, 50); + +replace into moodthemedata values (3, 67, "/img/mood/sam/flirty.gif", 50, 50); + +replace into moodthemedata values (3, 72, "/img/mood/sam/giggly.gif", 50, 50); + +replace into moodthemedata values (3, 36, "/img/mood/sam/mischievous.gif", 50, 50); + +replace into moodthemedata values (3, 48, "/img/mood/sam/indescribable.gif", 50, 50); + +replace into moodthemedata values (3, 61, "/img/mood/sam/okay.gif", 50, 50); + +replace into moodthemedata values (3, 33, "/img/mood/sam/lazy.gif", 50, 50); + +replace into moodthemedata values (3, 78, "/img/mood/sam/exanimate.gif", 50, 50); + +replace into moodthemedata values (3, 75, "/img/mood/sam/lethargic.gif", 50, 50); + +replace into moodthemedata values (3, 76, "/img/mood/sam/listless.gif", 50, 50); + +replace into moodthemedata values (3, 25, "/img/mood/sam/sad.gif", 50, 50); + +replace into moodthemedata values (3, 5, "/img/mood/sam/bored.gif", 50, 50); + +replace into moodthemedata values (3, 7, "/img/mood/sam/crappy.gif", 50, 50); + +replace into moodthemedata values (3, 9, "/img/mood/sam/depressed.gif", 50, 50); + +replace into moodthemedata values (3, 55, "/img/mood/sam/disappointed.gif", 50, 50); + +replace into moodthemedata values (3, 10, "/img/mood/sam/discontent.gif", 50, 50); + +replace into moodthemedata values (3, 80, "/img/mood/sam/envious.gif", 50, 50); + +replace into moodthemedata values (3, 38, "/img/mood/sam/gloomy.gif", 50, 50); + +replace into moodthemedata values (3, 71, "/img/mood/sam/pessimistic.gif", 50, 50); + +replace into moodthemedata values (3, 22, "/img/mood/sam/lonely.gif", 50, 50); + +replace into moodthemedata values (3, 39, "/img/mood/sam/melancholy.gif", 50, 50); + +replace into moodthemedata values (3, 37, "/img/mood/sam/morose.gif", 50, 50); + +replace into moodthemedata values (3, 74, "/img/mood/sam/uncomfortable.gif", 50, 50); + +replace into moodthemedata values (3, 34, "/img/mood/sam/drunk.gif", 50, 50); + +replace into moodthemedata values (3, 14, "/img/mood/sam/exhausted.gif", 50, 50); + +replace into moodthemedata values (3, 40, "/img/mood/sam/drained.gif", 50, 50); + +replace into moodthemedata values (3, 31, "/img/mood/sam/tired.gif", 50, 50); + +replace into moodthemedata values (3, 51, "/img/mood/sam/groggy.gif", 50, 50); + +replace into moodthemedata values (3, 49, "/img/mood/sam/sleepy.gif", 50, 50); + +replace into moodthemedata values (3, 18, "/img/mood/sam/hungry.gif", 50, 50); + +replace into moodthemedata values (3, 54, "/img/mood/sam/restless.gif", 50, 50); + +replace into moodthemedata values (3, 27, "/img/mood/sam/sore.gif", 50, 50); + +replace into moodthemedata values (3, 29, "/img/mood/sam/thirsty.gif", 50, 50); + + +replace into moodthemedata values (3, 46, "/img/mood/sam/scared.gif", 50, 50); + +replace into moodthemedata values (3, 4, "/img/mood/sam/anxious.gif", 50, 50); + +replace into moodthemedata values (3, 79, "/img/mood/sam/embarrassed.gif", 50, 50); + +replace into moodthemedata values (3, 30, "/img/mood/sam/thoughtful.gif", 50, 50); + +replace into moodthemedata values (3, 60, "/img/mood/sam/nostalgic.gif", 50, 50); + +replace into moodthemedata values (3, 73, "/img/mood/sam/pensive.gif", 50, 50); + +replace into moodthemedata values (3, 32, "/img/mood/sam/touched.gif", 50, 50); \ No newline at end of file diff --git a/images/mood/sam/stressed.gif b/images/mood/sam/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..8074388f590f48e445ba28bde6b3265742d22b19 GIT binary patch literal 632 zcmV-;0*C!aNk%w1VKM+R0M-8h|NsBYGXTjl0LU@`zc2u^Eda7D0H!GbnkE35CIFEn z0Ei+0h9UrlApn3N0Dm9=eIEdP9{_hA0CODxavcC^8USb-0A?8gU>E>j7yw!p09h6Q zR22YH6#!5a08bPEP80x6697pP07w!5L=gZ(5dcCF06-7`J`Vsl4gfO^04@svEeilF z3jit#04WLpCkg;23IHYv03-_jVIGv0P;z_Mqsko(3ckOz= zR-KUxE<;f(f;k{2+SKbf*tTqzGq6H8b){?nfPsQSI9zaFYC2hiLu6(QIvP|6Fe?vV zZALh9oM4$gj-6f?D`lUJq5%~j2LT@yWs8D^sXC{OO18SYvbaerp|vZFZ(a{D5Qkj^ z5HJ}Ehqq&?ozgxwW*Q_ZdSDVd5?_9()J_@<%4VOzP76FDLN@BFg73EUecT8 z4@#}+Wkg^c4*RI!Nk=7xAZ+cZSi@z*#=IvwD*D>Uabv}cPBM<`NW@kxf{Z|l8VLv@ zl>!VtXyEsVl@k|$WA_L8pCj~OBATh;?LnZ&>5NH)LMNv;ll14Ox^4ioY1%6gx z3CawId|ItYz`?Z3DV0~vmW+6S0|^Fl)};-g0Y+I&Yv%^A5w?olc25Ho;2Eok%W?=5 z1QvG$t=@@_mn}#^ieZ=~k*N?^)opO!kbg1@7dU3H@YN}F7ief^7 zLTs#jWTad~glt%tY)FVqaIlQ8uat*}guA6# zk&&RD9>1CzuaXkCq9V7vJeRC2m$Wpegan7UI0qjeD;F0tCnqxt3nLQ~BLf4-89s2c#F|CkM9w2c{Kx=t%XSSTZSt(_;RG6(v#vbEY{>b*Qq)S@~dj%POO+ z!x3-r<}cqr_ImD8?CF z=%(H~BcUgeX|Ar;!h9j6%w>}^G=hsv zF7{6JR$uC~%4D-fGJ}VvW~E5MC4sH$HIrYhIKh6@X<>cHA3@h-hr>ZLq^DZUDPo8* z)$*Nx$kWL5RAcv7o|=LsKIg7hv5Ez~oT)19v^7C)&H=Y&9G?BZ;%rS49GQ=qFMDUV zCV_K=uoq>p6J@XwVXzWrFc)Gl6JjtHWH1tB zFc4tS<7ZIgWl-W~P~>Ki=VFlMVvyuukl9k#a zFjv5e36743R4&Ba>QY|NuqSt-RO=qcpGTg{7^Z6N`F->0K~Cn+9TSv)rN-DYo8%tb z*fpt%W5t3cLA(h~n&RvB$T?~TJY<&awXEd4@x3Ex^MYB&+-!|P^=GTru3YCN kWw7<((ah=Lo?%;FEsc07@KDNGG;-gqIXgGcS75LP0LS*ZF#rGn literal 0 HcmV?d00001 diff --git a/images/mood/sam/tired.gif b/images/mood/sam/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..52660b0d3b586f3818bed96df353436c37fbf50d GIT binary patch literal 693 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpi8jb>@7dP#|Taj{xzs!~dd zVnTvKe7r(ztbACQY)FVqaIj2ZptPT#l&`OpkB_8>hlIPkgtN1ly}hWNov4kCh_$td zrKPaBxsaKekg>6#k&&Q*fq=fgfSw+|jt;+?8n2QPx1u7qf&#a^JeRC2my8Ujgan7U zIER=RJ0Bk_7Z)=pCo>BRBNG!4F#rM3kst~iQ2fcl$iQIEpaYTw`N@Ip|AE;B9y(I} zCzec_!D%u7!io|pfdkVH&1^XJwu;$!@i*_V2_Y;-J67CUbwBRvCeN=jdmgXkKK=gp ze`kXzro5OIa#!S!M9%F;YpQFggsuG$$FST?2V8J&3? z^p35^oLw*FMn&UgY3-YPZoItIwWQsCb42PKiK7R)*?wvz1wU+BI7L!#U*heP!BS^0 z6}L25Wlr6^e5YfBqQH&Qv{q-k+`2I}sA1`p73=qie0X+9-%5gS%h>}3n>)^G3J1Jxbt+iT zxS{lF$hfx#L8UV{5b literal 0 HcmV?d00001 diff --git a/images/mood/sam/touched.gif b/images/mood/sam/touched.gif new file mode 100644 index 0000000000000000000000000000000000000000..402182eeb851a42eab110a866594b831ac2b653d GIT binary patch literal 644 zcmV-~0(<>ONk%w1VKM+R0M-8h|NsC0%*^}A$@<91@4vs`v$Nl_vd^Zb!)k8*O0Z*PERW`Aa8cwk_6Ute%qT5nld zYgSfiR8(hDQe;q2V^2?FPEKJ?PFqPyT1ZG$L_||ULQp_JPd`6RK0ZJ*GdL|RH!LhP zDk?K6DKRG}FeWA_ARs3nA0{3iBODwU6B7>%3_jVIG@m{bn3J%g*U2p%XQw2 z*{-;OViClFFHweWi)G8^mQZR?U)tJr&+q$(HeqNtR)0f+PYx^@25tllASD-3YDPA0 zm|T@Rh?!IuEM1$2Z3+|=7a$%WC@Lr(ol=E0*D*^t^qqDqXxYjHQ;OR#fr;SYlo*y9??FtZ!3YRaAWWKaGncT* e4l;P~uwWgO8!S{xmFy*|@IbwK319vv2mm|&rv5Sj literal 0 HcmV?d00001 diff --git a/images/mood/sam/uncomfortable.gif b/images/mood/sam/uncomfortable.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f19f86a9422c97b0151a994624afc42ea3dba5a GIT binary patch literal 605 zcmZ?wbhEHbG-5DfxcZ;r|Ns9pXBtnRZZvJ0QGdTdTbpietyWEqW^u7vYN}Fvyh3cO zd}O3tSeR^Zu#At7q^GBZhlhl-vzWcTsGXgtjg5%4wTPvqu$h^Vv9X|$k)Xc5fSw+| zni{W?61Sovx4b-;tSpy=1c$gd2Ol3RCnqxt3nLQ~BLf4-Y9L7=Q2faPG)t2~2V@S& zPY!JV4@@cW(2?ptv1F13r^WmWD@vpUCQNgh+>oUZus>n>$rZe_=W_C$sFo9UyuJAk zPn6m7AA)7)-~Vn`iDD{@Z&nMhcUDW}kS&%i56E***!gtUm+I+RrdgVQVENqFaLcGBnQ{p+)IMxNu_E1h2l8{}M z$g9TPTIDkDBBKyzPVt;aj{~?R(k?%IEvqIgtDr1=EB>^~>x!_Qc7lhS5B6)+`#pH5 zRpdWcL|C~_caF!!2OR#*Mrth@8y6`#{*SwRD3onsLtjl(Z}0^FQ!IAx4(UutSazU| zJ(x@DCHt~_s#SCNCx4iu#K?E3MY&zV_SKSxeVQ89b7vO3*PP0x()CvR(S(;PDqi#W z9GJl1Z?)caYn$b3(*qoVjYcH<&4~z+G0PUj3MgRZ+ literal 0 HcmV?d00001 diff --git a/images/mood/square/b/aggravated.gif b/images/mood/square/b/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..752a251681b0605075f0d6c1c6f363a8777520fd GIT binary patch literal 434 zcmZ?wbhEHb6k(8KxN5~vwfukg#{VI;7xmprdp7^~$lmOkvzdW`K}bd~eb#>#R?hU9 z|I%mvk7&MKxbVM@bHRcG|FdWRl~Q+1oAQB?ktuJ^FYAcO(wZ(=vwn#wnr6-XmNxB& zvPpREoL?EU{>f>3s+vb<%=nQt^{s+oVBv!QPRUC%r+?0$|372u`#F36FFEwzC2f_O zMO^0Wf9AoRJVJ6D+=3=PbqtJ*HW8CDX8o7b^GToeZ`-;5QfdxqGyekt&~3;-@jthp zYe=xOV}PrXo&hr>P)_kD3+prnD+V2qI*>OR*ycLSE%4Bh>OZlh=wy!7{D8-~UTecb z)s<9SU;NwEqCX=uI*rtZWxfi^;fXD_h*SdFxi--Fx>RJbdKj2zGG_$i?go91N@s%s>}& RIWz_QI4#+IB1VA08UXR)pcViC literal 0 HcmV?d00001 diff --git a/images/mood/square/b/artistic.gif b/images/mood/square/b/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..58334e9c46acbb79acede31caeb3c117cb8720a3 GIT binary patch literal 475 zcmV<10VMuMNk%w1VH5x!0M$JJdZ+(LYqN{7|BSQ$FGh7#ebHx{|7V&1XPN#41ql)y zE*>jMBQ#fUpZ`K*r5YzeEJJW6I9??;TWXp1009AUq5o)_|7ex(W|sJAoBnQ``e&N{ zX_xaJE=)XFk{~fraiITdn)*a$s#t^D79lkV3lVCS?P!?zpuqoYoBgE1|81Q5Xqx^v zQ;9T8erA;LoW1`$Sd$DA9svOY8!1G#&i@)FK$VV;cya=hivYc}3ZR$;W|{y0|Nj60 z00000A^!_bMO0HmK~P09E-(WD0000X`2+>X06hRK000006aXFo00zpyo^UwK<%r0n z@MgRzpUz?QDNRnH*sPX#-S)cFDVX{#la)7}dd+UTjqtcUzSHGu_`F`PYT)WQC@=$r zg@%M64u5t606dS7k&gugi#d&wnLL!1n3|ECfSxo8kTNrnp^T0^3KWnD38|H$te=y# ztB?n~1_rpDjt3nn8$1UYBq6}HJO&UFCK?tC5iiWTJQE%+B@ZnZ7}%Gr2qzpX1}q4( z!ME*z6(a%k_4f2J43;7vHvazr0WQKpu%N+%1$QW1$grWqAOIox1O*fTJpe2Q01*HO R009611_nT$aL5Y+06VsL!1(|G literal 0 HcmV?d00001 diff --git a/images/mood/square/b/bored.gif b/images/mood/square/b/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..c6098b26df046c8632197409a305dae365417580 GIT binary patch literal 405 zcmZ?wbhEHb6k(8KxT?;e?^fEg`G3{&|J@t^htyv5$llDt$|)qHx8%@&4sJmP28R6k z|8wX3%9!zkfsxTBVv@2+ctrDUDRsxfh5xw(q_Spy%bfn%#HVh~-v3U?OVelmTX5jN zf?=SLl$J}{s=@{Tts^E&Yq~HpGVut>Z9Dg0O3fi{=6@gnnoJd-_@CR)H6+;CF~HSG z&w!Z`XsF^(7S=dMbp{=f1t4!Su(ceRT;QQ2)qi41(a9XE`2otAUTebyxgW6!zo^=O z*T2m|V8*!@UuH5W%)VN%Ow^<@aQFs&`LR z>zk4$$}i3-WG~x0xk8Fpj3+~+qj=i%#S;d^zi=;r~Yp|{lBPjVfXR}&9hHmfAXJ|ol{y#@6G4`(|7%w zzyJS?-Tx6j@{|B!A*ERR)UvlBx{r^H@a^cyN6x2;8Z+fq7>N$7c|CTwYuRZy{ z|H}Wjpa0)@`hUjGUnx1YRejrL?EW`x)#XQT{!dzdQBB|R;I;o#Hocv>`)^Q6r&CaY zg-hJjt)H_>dspnd_37LHAHV-IGBQou{$tUu*Y#5moxKNi^M43n7z#k~KewN2NU*bG zfUA+70W%}e&5A!+I2jl`7<54H2SpPD`>_U(rskH`w)T$BuI`@RzWxalCw03{oi=^C znMRAYFw^`63+HpYv@kNbtz5NwB@6Si6>B!F+puZ#`sU>;r8rh8JFeQYb0Y`;Dt7jR zJDPTFTYc!v#&c^=dz|HRvJsRqfL^l(04qH{)Bpeg literal 0 HcmV?d00001 diff --git a/images/mood/square/b/confused.gif b/images/mood/square/b/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c0e98151923fffdfdff36ce2efbce15d504f813 GIT binary patch literal 451 zcmZ?wbhEHb6k(8KxN6DZk-fQl<9~g((w@!#LuxNpE&tEJz!1@Vn}wA#fByeDd;eQU zOjb4tcS&32l)O~IFfe20-zA6s7cTgpKJ#DU!v8`tdJ7Kx&z?ZbJi#|GE8KLxPSWhrmGU$Mmg1pJVHv2#fpSuWOx0BMj6EbGgeO?qx_O+?od)d!+neNoz-LSxN(c<~N3)@y$EM2~0eVdV-tfYdrfzHY<3jrAwDOCx9 zX{(m4*?3%po#EX13+K3be0cfIZ`{0fE9>sP`wtQv!R{3SxtEQBpMe7i8Q5eU<`ihG f+0n+qQg|}Qs$DsFZEIIwo%8Ao|C`$|)qHC#UVH zY!aS7|G!i6QYm#u9p?fyi#S#D=&YIF7#JA~7yi$f^*>|k`?P64GH3tGoAWDu*1yc@ zpXKy?Y$7Hp7zP$D_@6cFmrL5Ji00d3il!Xgf>~4FX3Y4p;K2Xv*?*TD`ky=JSH`S= z=E0pNK6PnRKFrzs-#TJ4kB}TABa^hI%eHg>rPLhKX8s2P25dm_KewN2NU*bGfUA+7 z0W%{|jp9!h);LBB1|5)kkT)6FW;)C%@X(R!Ke43fWRBJRfaF}SwPB&WN?c|ys`kfD zXx3o3bMD2Loem1KuNG{Rmdocqoj!|6clN@k<@sD98JwK;Wlj|(nGId}=Ij~lY;4(` z78UHWn$i;`RTQTevk3^PNr`a_>Mw3g7najg<<}LLSl6GpasCN zGYcpxENdVnt-I~qe>|8x7fh6Fo12DlpO889;fl`8&ZVNGE$ zWzYd>19_8yt>wV10uLRj{u4`zPUcw64@l1OS{o)VpmaFs#lKyx`Zo*}nOL@%yxktQ zoRiV`mT&#>_UBcydj9czSwfsyH5JABT3LD=E#*#?Re7!b#U*Uh%W5a~&dRi(UozQr z!u+KR`xX~3T`+0IgxMyGBt)3EZri?Kg9ihT96fgY#7QSdgu_@Fco{eu z*ntj{KX6MiNL#7v#FC(uk$S?C5X|9dw752?MV?^c>V>wo&p{|pQaEUcXAGye(6 z=w;6Smo@8`oVI5~^KCIj)2yj)Ik*Mq?ERlU>tEr*|2obExpRJH%=n>d9-TJjL*ATU zY8G+%^Z%O%cV^7`?~=Ak*(6-SFi=jr{txD3;r)T^j})jC42T?DRsxp>7Uc4 z{aA3|zfHs>9w9jspE?FcAYjUx`OP|Fa>ms6+s^%$QgcX~`5y>?u0jKf|GE8KLxPSWhrmGU$Mmg1pJVHuu1s0uLRj{u4`zPUcw64_KV*wKmLOHYwZa zMb-Y;;7$#W2j^aVnHiukyKuj}RbSffs}*x_xano HnHa1AdZnH| literal 0 HcmV?d00001 diff --git a/images/mood/square/b/embarrassed.gif b/images/mood/square/b/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..6dc1ab331fb398c7434954990ec61eb464b5fb4c GIT binary patch literal 692 zcmZ?wbhEHb6k(8Kcvi~bk-fQR^M8G}(vaGV-5dX>&-hoh{D1b8AL%pxHrL$T?b4TA zbU173uPxrwYnmUKxD*?>m1a%-Y3Eq5K49)~i@J>IfBJ&wgjb)hUHq%JW-PyKf9!@S{%PFedho4S^qEVV8fZK=I!Z=01q^WTC4 z|1)O%SQxjlx#mXhq;J*{ljWrK%!503x%T&L_*>Qbv@U*i-ke_=W>JEy+)EDq&zSYE zZ|$%4ipy-QoDt2pO=V4cCO&aWUYb7Z-=ec{-~|L079 z$SWkr%*Z6K;UXlXx9!}2DK&?*ng4-+0WVPe&+X?L671|4;A*62z|06#toW0K^#nsH zgAPa|D4H19A2yUWHMg|3wRd!Ob@%l4^-pLknmlFdRPUS?n>5C`^XAW03~pgzD_Oo` z<#J}GCCgTAShJ3G!%Ego&8`ycJOza-^6~}Q1;qtgl7j5roZ?sbd-3^ka`U(3M)KN4 zC2wKn;nUy}b{A?1monnY)Z|#6YRMZdB9_$>Dkox*q7qVK5V2^Ff>C4JPRB&Qf)fjr zJ4IDg-RAsMXqvUv(bw$EhK+8m)A@AT8XTFQFicNw=D4z=;elJfm_m}l%|@>23xc+W z++35)#MLn0q4^)rrltwqdc~8pVt1KLy1YDKvDaKJ4FRyPML@o0W8h(6X8;BSJ4b_P MNofl!M9wMwQ@zY=jM;0hfI-*cb^PvKGD7TXV%JF z5zV(FIu51J`I$cNOH|*^vb%|e3;(Cj`|OdkDQDBsklG6chv#IkJ6E{if7QA-A$8}A z&owI;24*aJRki+=OWLYAd;c#v^uK%audZ$HyLP-%HVF@HJd?L;b41rZr{tyi`&MNv zc$c~S-hu=F^XLDU(r_$0SL0Ue#3Ll9>0-^q!k9Db9s>gdBQt}vrc2hG7j`Lya>kmX z%6g0}jBK2oau(8JIvni0oGh%I+=7C|3qA`g@h~znv2ZZ4a|@Q9Ysj7ZBVY(c~#pr#kt!_&GAnoi~53rB@3JTgmbj zE0?n}FIl!~!asWgm6S54f0onsG!O1%WMtwI zlG}dzcgC#$CO&nA3;v5Knr2OXt6&(&z{qGFFu!)$obpP);d;c#u@IQb4|H6g;bLaeu zXuh32`>&csoV2Ekl)9r!+A0oiK`Au{prg}f{s#h}CqXIH07S8p3ne}@ZC8}Foc7v44zml-Yd zMA`&h#OAv#brEb6m^Y8ViGQ7oKr5@vI@Vpg*O^(iSeT0nakCve&MhP=uhqiH)T)BMh`pxF^R~|pPaqFVJ@D*vP`_Em4m9KDdy?c23$k`SwKND;DkWthK^=Y z@iLW$hX>{<$l7qcP??al++RqSgH_OQ$%>1M-NiLyPie|`a$Y2csi;v$d literal 0 HcmV?d00001 diff --git a/images/mood/square/b/full.gif b/images/mood/square/b/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b254a3301604f22b714bc86f834a8a2f2298dde GIT binary patch literal 430 zcmZ?wbhEHb6k(8KxN6K0QhTv`${a!E&spd(Et4T|09}j3(4rQuyVSj ztx_-yoU`};f&>2x7yef^2`^mm-#TKlQ}WX6sV}6|9XYrKWz_96X8%v0^*?L+M@A+_ zn}|s&#-X`$ewp~x70>_5BP7Sj$dobbpR}e+=Jd~5v;U?|`@z7-Xdc{|HsvEbm!O=k z7c(nI#*81^&i$8Cb6{X#NSpZ|2!ITNK=D7fpKD04vtxj(k)8oFBT$3lPZm}kMq>sY zkY%HhfXF|L%zv35^ryUVM>sP?&wS zV4JjDKL6?TASPL%g-^@#b?r0kTe8cXDoQdNy7GHEiYHELOmAT+I szyX8|Y;q1W3p9Kdv~jT(p3LE^_kPj;d1FY>{>$e>Kc%=`P++hI05m$8tN;K2 literal 0 HcmV?d00001 diff --git a/images/mood/square/b/giggly.gif b/images/mood/square/b/giggly.gif new file mode 100644 index 0000000000000000000000000000000000000000..f88a52848294d0922d3efb11563ccb5cfdbae745 GIT binary patch literal 667 zcmZ?wbhEHb6k(8Kc;?3tQhQO~t+Zq%kfBLNd`SbrrG~aeg zUh0yzDr5HlC5Qf}&-};2$~kB6e+9$9!iE2pO~Mx(_|L$|Sh(Q7b;RV1nSYs>ScGKs zIJgBfXaAE>Fie~BK}y{*YwBA$Js)NkHVz(9R(77^`Cl`pzL!zASF?!Ap8CQ(xKm74 zN5weQ#HTKA_P6ZWf3s$O%bNW+W9EN$EwhGt>yQp|?7EwXgx%1}F73XeYVe(zRV&!rM#wE*EZCJBz!^XAEOSi1r zw0*s_*a`uG6}y{u>^!{f=z3rF73>@wt55pvU{^9QKO<{uducO=m%XBcn~kRYy*}VyCsad zxL6R5W@X@I;ACJ2I@+MYPqp5!Rjj2I=;$tEmHG)2r1W{Em38Diq+~4oTy-^^O)RZF Q{Uoil)Od{~{Tdmp0mXjFpa1{> literal 0 HcmV?d00001 diff --git a/images/mood/square/b/groggy.gif b/images/mood/square/b/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd43241e85231cb945ed9fb5eb727277ae3a9880 GIT binary patch literal 420 zcmZ?wbhEHb6k(8KI3mfQ?^YU8d$DKp|ElHxJ+e15{f8qWQLvjNY8R z{}l`a85kLrO~MNo{?DKPf5CzOOAh_Fj+k7y;J;Jy(rxGdOQ|`e&HN7pK)q-{@jthp zYe=xOV}PrXo&hr>P+IXP3#So-B!dn}DaaWNtn~?MeM>qLQ)exbT)k?|?{%MY&Ohh9 zzH9FH#S#}>WVTfto0xhs$4pfqC`EBa)cR1b))0v~`yS*o9QfLH{_!VCU%Arj54YT2 zlTpLZUKstQ?e*0<^`e@z#%9S{b++!p>W)^4ZnoZrw!Y4~c79Hlx%1}F73Ndn;1OTG zV&zKDHCl=wH?g9*sS4<(l+1Z5Z3}ajZ8P|DY~_wiWqr55-#cfwApgWBiGGhIEKXfI zEEiUYc&(hk#XPlaH7~=u$aOck#rpRvubJuX*DlKY_TdHB?klgWEZ1k?Xz`LIF3VLF8LREQG literal 0 HcmV?d00001 diff --git a/images/mood/square/b/happy.gif b/images/mood/square/b/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..be809f73371138e369dfda27d34eddf1fecbead5 GIT binary patch literal 760 zcmZ?wbhEHb6k(8Kc;>|5k-fQR^M8G}((aA_LuxNpE&rcB>wo%8Ao|C`$|)qHC#CMV z;K2XfIlr=Iev4?nZ64go!7W(0;6DQcL)x?-CO&m(Q$A$O_%Ubi|EyWRGN!&)HVIcS z40K6b<&?ZMW7fa?`TuPqCM`Mizi{Dy>xjvj(?82;d#aj8XH9*ZIs0Gs?7!)={xL8z z>NppODVnNT#L4OT&+X?L671|4;A*62z|08rgW^vX)@ck*3_2kHfTD?k zeOZH3Q*%peTYE=mS9ecuU;l(Q`^i(LPE}H9;gMjRJ8%A6A-NW2R>$QlRxW2@TC!}_ zhBfOpY+T#Cbh$Ct3KP>6o3^j#(pkaDxqn;Jjx8$>oLcY5zJi^NZS_f~9qa~L+7~tT zB(HB~(^c0nG*Z(Sdwg&?pQ5NBw}6z$yYtIA#8r9O z7;`zcn3%SJeAQ)F-`{U0X>M(4Wn*h02GNiL(ZI{V!N3aCpwPgj>O?^fEq@qf?e{~p9t$fc zGb=~_{Qrdu|GT8Ea!OvRY!W_a@Bak{{ueIzuV5Hx9Wi;yq5l~(|3@_6PMh)}ZQ75F z89y?nzE7X^Pt`m+ch0YjS^pUr8FicsY$7IQ&itE*d&*s6Ma(X`5v;RtKx`-*7 zs#(Nk&HR=%>zACir>K}TBO`;BnXjn40gsSe#_a#>+(O&}l8j6&jEqcKQ{U#z`NhF4 zD5dUb;#0@U&a>^@e+b81cM8M z4#+2zg^0<*jWL4Roa*A6%}dVsC4wAuIjv{Blkibp;MJA%)pTa~>$LOR{Oi zoCsLh%F!YhBH*-fk!$xvqpUk8HZFE|Y=k&n1mtu!1|9|u26mv+bqL{`XnYOn)Oe0F*Y=rYGKsd2=;CYNDnJe4<}F;1G{pAvo@D=tEp8hmr|=UH+Rp3 ziEKS=Y#bA3G&!_P^|C7`IPf7p#ev_WG z(7(y)oUAPWXBYmzy5s+uP5=M?{C{!#|9^j7)TKX9%#1Zte>)-T=j(1pMuvY=GOE-V zzU;91J=^)$l&l{gCjEc8?%$O3Xj9d1H)EI>8Gp>x|35ST!wbuQQ!{^e82*00?ElU= z&s`Zh{mnmp%J~0g$JdW_|93C=|6O4)p zP0pGWYV&{plE2fkg}B*2ybt}c*yz{v+|0k#Y|NozXszC8Sx1VcBu(M-;tC5}oGb7M& z#h)y!A`GbvIv|Tc(Zs<1upzanxuvzOy`!_MyQjC8ty8#D->7LqGn-(ig5Lx#t|mdY zs17a15HEjqGqwnMWr<0xYz9G^GJ2}AY`$(z?rhVW+1bNFkDTBa2#*x9Q)@BQX1Q|p z+7&*X7DlF&d-osQV`aX5_u=!$Pw$Cv-w#%~|FZecJ#NYSyu2Tue17))!6%lBzu70u zcPQp52$?a_fw{T%)rk);HZprm5%bLGFpg-8V^UJm<5{`!NK;?$D}g&d1e@`W cWA8hA?)-&|mo5WC>-vqGw{G9*YGkkm0LGGA$p8QV literal 0 HcmV?d00001 diff --git a/images/mood/square/b/hungry.gif b/images/mood/square/b/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f867b384e0ec2d46f4fc0431178578a23653ad3 GIT binary patch literal 753 zcmZ?wbhEHb6k(8Kc;?N}v-yAb#{c?mr6IK!tCs)w$ljbj^MCrR|17MWLNa>kGyg3) z^q+%UFmw86X-yYZ^Ju5!rTO#!M>OBgn)S;%V)B9m|K;?2vZlT*TmaPdFJsof?Ad>% z)E#x43lt0k^XB}@oc)i1kRpG+_jEqcaQ$EOPd#YK)nfTPr+52DFB%DV`E@Rez zF-6m~X+JWizBdo<%$oVlCSp>?j32pke%;&p@WHkRH?};yzUA?vl>XOeJSHDTgp1X1N+imCmOQ|`e&HN7p41*Xb z{^#~{4GDI33~)8lGhk)}I#ux}3#$l&H-iqy*`R1*U|-$f-PGLD+ScCD+11_C+t)v# z&13SEsZ+THTSPS(=FXcxS3;nLk;QBIij~WmnU*YDwPDS=4I9@sFI~>Zxk6iI#is4+ zITcrMaO~gKv}4Q41E%iPSH%gf8uqN%A7p^OztnY)#pVezyyR0>}(At>>v}Y0sdI#9smFU literal 0 HcmV?d00001 diff --git a/images/mood/square/b/hyper.gif b/images/mood/square/b/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..52aebc52269a4d0fc70470746b8958c4088a2801 GIT binary patch literal 1149 zcmZ?wbhEHb6k(8Kc;>|5k-fQl${a!E&rcB>wo%8Ao?dHqsPL^$-uxM zrS2Hfe0$E`{|gTMw~m<1!7XSLF)4HU=d79E(x!Z1WMq=objhFpKV!y^v}r#I7yK_= z_}@IZlSfD{cg`;ppSmT7{%6ekr)(1LlC~;q)-MIaK&RxT8B^cO>G?1)GGI~&{D(@wkCHBF5# z>*}c9+{$L8r){8bVkr9b@JbOO1wkHJ4XFcz8UW9 z#|M|goc-?na*(sxlmrxJAI*87z{ks=5pyCyu|=@OV+MoM#zn5(6OFR&oY=V7-LVmC zn9o3Udbd3=%qKzIJ!|%ySrB(GS-NZq6U)NI%h#@4y>{KI=0!`yIhV?bEnUB5&Bi^O zo3 + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
artistic.gif
bored.gif
cold.gif
confused.gif
content.gif
cranky.gif
curious.gif
embarrassed.gif
envious.gif
evil.gif
full.gif
giggly.gif
groggy.gif
happy.gif
hopeful.gif
hot.gif
hungry.gif
hyper.gif
loved.gif
mellow.gif
nerdy.gif
okay.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
tired.gif
worried.gif
diff --git a/images/mood/square/b/loved.gif b/images/mood/square/b/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..64934dc8420bb09929a5bcca193b66b84572148b GIT binary patch literal 465 zcmZ?wbhEHb6k(8KxN6H#wfw(F_GW#z(w@!#yEpz1slAv!^MCrR|17MWLNa>kGygF% zGRf)rEI9B#fBt`$v{h+SKB!s5{byoYa_GODwrAd)Uxf?)7cTs-Y!V*Pd|Su4z$tlY z?wnsX5tHWZ1)B3OYu2xfS^qPpzGq-$R4@#bQg_Ul@gsZoUujL3%-R3M6iqXyf6kiu zjYmjM)jT?D>RS$OLG$2F6Q8=YX+JV%{j-jk{9j-HzoFrOHMMQ${!6Jj{AXZDoB1CI z7{EaBKewN2NU*bGfUA+70W%{|Q1K@VYYKxcgAPam$eRpo%MQ#d@X(R!Kk=ks`)k9g zF3Y}fiu%pIs%pCXN!9)bDS1A6)7ANs4jX6ezMp%#&4b~?yB~k{DlEADwV|f2p|RGv zv|NL;LYKRuslA?4xq^eEzs;$mrE5D3g z2nuYTSgs>$WT0xOWV~;FIhUHY47&-}jOIC)oy8>?Z{5Cg%T&UJU&ZRl(`U~TU%q-kGD;&6&cSD=6{E+e`vpu}3E{TCn-eT(`vc;tDN==MQHsfHh1^`do Bwr2nU literal 0 HcmV?d00001 diff --git a/images/mood/square/b/mellow.gif b/images/mood/square/b/mellow.gif new file mode 100644 index 0000000000000000000000000000000000000000..fafb535a1fa67efa42dde83fc61ee4e09f27a03a GIT binary patch literal 712 zcmZ?wbhEHb6k(8Kc$Uu4v-!VA_U7)5|7A2?tCs)QcPljy?h2{BsA-#)KJ&kbtYP}B z|Lk0X|NsB@F4)a0qNu3r>J-%_ukTkl;rx6yJbbNc7(sV{V# z3mBOg)298%oAWDs_TQ}8f7ALOnfTPDP5F>M>mMsSPu|RTVv43-*_&02L$fA56qD7- zn)xkj>RVBHV>vyaj9LFPXaAGa^2*H!lq^s zC#CMFY95_8`&-7Wf7{Oemr`?JU|>j_2@H(?Kn7KS;(u;G*N|Xm#{gF&Jp*P&prMLC zSy)dnq%-J%EC59l1N+&A^rq&P*0%PJ&aUpB-oE|`ZON0TOr0vC*J2>bFn8YkxhgU( zOe|^3SFBvl&f21*$y{I0&%wdWwsEtPP>Zl3FVCiWwluB-hZL6xupK&_w*9R9DXz18 zY3^t1<(3GZhHm#pC zlhyWs4Wklk`*bDN$1{x{AK{wF7he?fQ!wzp3%6<6g$RXXOj=1xI{5$aBAZC>q-4AuakIrYf^ literal 0 HcmV?d00001 diff --git a/images/mood/square/b/nerdy.gif b/images/mood/square/b/nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ef93305ad137584e909acc29e2f29fa763a4454 GIT binary patch literal 1222 zcmZ?wbhEHb6k(8K_};(}7w2~K=4NAKwVImPLx(1Yg*iNWbmaQ=^*3&8Y-~(qWMVvj ze*T?1JFi_^d*Hx?HESBp%{4DxTzvNItg~llpE@=D{{4N24o!Oe_{5PTlNl~DFtIQN z2ix7hzyJ2_ZL?>WeE9G%FwizXKkn(%(-$r*c=6)G>C-cOeXU--x_al%ne*r8tzFx6 z{rdU-{_MWKtlPJ@@7}%i#fyuZHnlEWR&(|0>PwfFIyo67BzR1iQ2zMw@v^drJ9lu&uiEAxw)BCR75>|c$=zqGbiuV3GM?%dqHd;1u^F*G+PZQIsy^X8Vk zyr8#lZ!|p@0=p4|K+LA6{by%e{I}>(EKX=vvTRm5cp>;fBa36P(uZJ?3m2DIOgF3Ly1Fc+ zDP(n=>M$6ewIUX%f|vu&Y|~ z;6bC163fC51{)VPJU-s%cqQQGgoXTq;yfAm*6d{B6=B=?Ai-gK$xCLDIEgz8QyUZd zRYUG*Xgu|7=3H-^R;bkSfL&HlM?k`_W=E@BM3}&ziA#<)JioB``G$)v4<-oIY|6gB zuGZ`6dtPQHM3}HKa4@hl0E3BxlVNWPgUg1~(;E=7tPGqCTnsEgSp^2hR1W4952k9f z0z+(t!a^oqDF#i6V749?!<2Ix92{UxI*h${a!E&tEL%9%d%pOB0m10$n?VPMwG zZ!T%87999*6EP`c*1wDyKcv(hGp4?`j+h+Ld^>I04`q|^%;}#^eCp=x{a?7?fBLNd zxpRKy&;M^8-076ObjhLr9NdD13;**7$uTlANo%@nJNI8o%^_{(e;{C>7%2Yd_Hzvh zc6JPKHPSO+W&|3j_>+Y-j!~0A2V^+Nn+$BN2c{Hw=t%XSSW6*8l(j literal 0 HcmV?d00001 diff --git a/images/mood/square/b/prepare.pl b/images/mood/square/b/prepare.pl new file mode 100755 index 0000000..39c21e8 --- /dev/null +++ b/images/mood/square/b/prepare.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# + +use Image::Size; + +require '/home/lj/cgi-bin/ljlib.pl'; +&connect_db(); + +my $num = shift @ARGV; +if ($num) { + my $sth = $dbh->prepare("SELECT mood, moodid FROM moods"); + $sth->execute; + $moodid{$_->{'mood'}} = $_->{'moodid'} while ($_ = $sth->fetchrow_hashref); + + $dir = shift @ARGV; + unless ($dir) { die "No directory prefix given!\n"; } + unless ($dir =~ /\/$/) { $dir .= "/"; } +} + + +opendir (DIR, "."); +@files = readdir DIR; + +open (HTML, ">index.html"); +print HTML "\n"; +print HTML "\n"; + +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + my $newfile = $file; + $newfile =~ s/^[bpy]-//g; + if ($file ne $newfile) { + rename $file, $newfile; + $file = $newfile; + } + ($w, $h) = imgsize($file); + my $noext = $file; + $noext =~ s/\..+?$//; + my $moodid; + + $uri = $dir . $file; + my $quri = $dbh->quote($uri); + + print HTML ""; + foreach $col ("#FFFFFF", "#000000", "#C0C0C0", "#FFFF00", "#FF0000") { + print HTML ""; + } + print HTML "\n"; +} + +print HTML "
$file"; + if ($moodid = $moodid{$noext}) { + print HTML " ($moodid)"; + if ($num) { + $dbh->do("REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) VALUES ($num, $moodid, $quri, $w, $h)"); + print "REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) VALUES ($num, , $quri, $w, $h);\n"; + } + } else { + if ($num) { + print "REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) VALUES ($num, , $quri, $w, $h);\n"; + } + } + print HTML "
\n"; diff --git a/images/mood/square/b/sad.gif b/images/mood/square/b/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b3bec9c46fa7f79060d75d12b93e9d2f919bdda GIT binary patch literal 738 zcmZ?wbhEHb6k(8Kc;?E`v-yAb#{X5z|LePzhSXm4$lmOkvpId{e<2w?7FN#mng7yf z{f}GoJ9o}6Rr6?@h)L5?_|?ScdUO?>JY7#UsCRuwMzpE>(q z;llr!(?82;dnyNpqpbf4aS`@e*a!@P6}=l-Y7{0{^SLkcMV=k{|A33hf2a5d61U}gk5UhyXj zs}X}MgAT|eplD)XU)VgVa>V?8`m~3T`t10LQ8PPrtRxFBvx>8?%&q5W6R0|r`DfYebV(b zmzpduw=&m>%`Q6p;zouB>W-H-a~t!C>T1Xd+q^jF!mgqq@Kst-|MU5aci9Rf0v9Z3 zY+~in(D~uavXDo<#bb`g#H1zN62@6~P6P%hAl%K%z{kMCzzTG?XoIVrYm2F+tGP9g z6_1Ing{y;^Ya_Z!HlRw023Hr?7Q1E_Q%e?{iur-YasU;}Hn=pgG`X-iHrv>>=_BcI LaximhWUvMR80^m7 literal 0 HcmV?d00001 diff --git a/images/mood/square/b/sick.gif b/images/mood/square/b/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..573071bb46d62cd3997b9740a74a919839480344 GIT binary patch literal 830 zcmd7P`AgGr9LMp`?(I8wdJLA@uCLR1O(Tz{#?npQVMdW;3K>Fy1VR4b4`#W|dtRwC z%S2MlFkuCz>E`Br5SI2snA$wT&L2j950Mccf`UQG>O2|@F%pOlf@m?sv4=zgzq`D(rN2UrciDm!)IfZ#$qs7@ls1hkc25z;d;6cN6qAPigWJ{M*7#Vu$>ZT}_N=t6wO0KZAqd1mQ;`NHt9qO<$$L8$7G=Z{Knpeax(4YW< z38M&$rzodH2HAzh*2m3#y$=I0@`0K1kGb`)*<>(O)YMcPt+ln*hQ_)(Ew+}b_NKOb zwvGqp=I+Ygp8C!{vu@zY;NT&A==t!_A>8GjaFK|P@yYq=+4+STv-9QT;;Xp?s+;_vx^E_5kvF1j KOVyMkr1}H#C=Pr8 literal 0 HcmV?d00001 diff --git a/images/mood/square/b/silly.gif b/images/mood/square/b/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..3afe6ff3960b72766937eebe85c2329a29e97e10 GIT binary patch literal 439 zcmZ?wbhEHb6k(8KxN6H#wfuib?Zxhm|2?ud_iX;J?^c>V^MCrR|3Wf)EUcUn&9{H= zxntr}C#Go1BP1uS>9XX||Bb8PX3zdBr|p?B>tFu-|Ah9q@07eWW9oZllklvmZ}aB-a!Ffd9Wi;q zf&X*%{^#HpRI`XnoA%@5uDgW`{-;g(kU9HbN$K*;>7N-G8PjL}%bN9T+qwTzY7S{L z{{sO77%2Yd_Hzvhc6JPKHPSO+W&{c<{$ydD#$d~!15yC;CIj2N1M>Lfuah})OFhx2l*W5Lt%d=B#r zPR{x=r;3uyhOT@YwhT6Q_UumE3N{5H>4_%1meY&bzlW3-wwQY|G~pYkDVM5PG)1^ dVPI!q0y>$`;U4qF;+hJZBWtI>_}Ii?4FJxLu^#{c literal 0 HcmV?d00001 diff --git a/images/mood/square/b/sleepy.gif b/images/mood/square/b/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..668ff75c0e2ca037497d5ef07eeffad1266f75ce GIT binary patch literal 424 zcmZ?wbhEHb6k(8KI3mdqQhTv`<9~g((yHbEJ+e3VZ2r%}${Epod%=PK3WkB!5tE&g zmkP<~6)yPCz{ps*@c*2>|6S5nEjjdG*(5xF{{L;~{!6JjFfcHr&HN7pKn5C6{Lk&@ z8WQa67~pE8XTZz|lve!7!kNM#$)E#L3UUSmYkh)RUrJ_Q#H@Kbom<~(ugb1DRo1!L zn(Mo9M4Os2SO1A6M!}g@^ZhwnTN*^x-FUNgqXH}25d$`b4^2l+Hc8Ia>))3%^;d10 zMF?B-9o?qm$7>|(3X5ygTN;}s#Cu#?o7%g3bF=IFyE6Lu*;(e!n?ILJSVfRiZ25|n zE4|m~DuUd^isq&|u$$&(bgj+o-ul9N-KOkoS)IqNbS@cB%lFXX(>}2zNOR!?feB3| zUQ^A)mKel+#-)kicw8dL<(@a{$ m+bd(bdg}VxVj7zp@+5&ynlpFa9Eg*aEnl(1ZMCK%gEau2Q=-8D literal 0 HcmV?d00001 diff --git a/images/mood/square/b/stressed.gif b/images/mood/square/b/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e4efbd7de68ecc48a821f089637ca025c6ade37 GIT binary patch literal 619 zcmZ?wbhEHb6k(8KI3mxW?^as1{C`O8MUU*wJ)8e`Z~QMLqnAGOzqFMKs?|pY^|R;s5;k{|guVS1=6R zcJ9BFnnT*m|3IMlpWDwhB-q(8z|~04fSD0!oZ?RwPHzTz1|1-q0ptt@*1iYoeJPn; z^UBvHN3GKJ+4WiH`1;&SYtQ}Lef#+_W~qL)zM_*UZbmBZ%?@j$R?gyFDd17LKaMfs zHtX!8DW5BC9xW4K%WoA*>%JrBeCTw-mCIT28M&!)>~ZYu;+oCnt&MWM@)h}9g-vCX z``NgwXEaQhICIK`NfKhrD_5;vDIlc6FD<)y%hs(PJ9h5ct)z&}iM?Pa&YS;y;gegt z7G)hW)SX_E^;~n`<^#d+!nmdSbugS5fa=6mFekp!-xYgq^|$g`b`CB!pabj6^f4ubCwkC>`C$HV@vc}>t`w)q`2T!)o!MSX}@*b zkEd>~*b=J9bC-*CkJwh*HkauK7c9OUm!6X%2X&-YQ&~#|cU5Dle0g3+eBZPQY?Ee9 jo!%ffdr`w|pd(kWS-TqI$gSJ9Z+G9dd(U2VMFwjCVx9Gb literal 0 HcmV?d00001 diff --git a/images/mood/square/b/tired.gif b/images/mood/square/b/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..6bc47416921957fb759d02168ff8047908af49bf GIT binary patch literal 287 zcmZ?wbhEHb6k(8KI3mdqQhTv`<9~g((yHbEJ+e3VZ2r%}${Epod%=PK3WkB!5tE&g zmkP<~6)yPCz{ps*@c*2>|6S5nEjjdG*(5xF{{L;~{!6JjFfcHr&HN7pKn5C6{Lk&@ z8WQa67~pE8XTZz|lve!7!a9vXl0gTg6yyvB*1QC@zLd;)8LQUiyxzAV@@z@0w@9ah z>-+zEk2Q%%B=ntlBB-DsH8o(FuvBheSIE*YzfvqFurU{DA4)rZ?bGKT#q={d<}#mG zW?z19dUxKG*PH8dyes(GS=u`~+qr~Q1UbbfPMSQ~aN6`4GiS|KQUp681>^)a1|9}> S2B520*&cjPT_VB6U=0AFacI2& literal 0 HcmV?d00001 diff --git a/images/mood/square/b/worried.gif b/images/mood/square/b/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3d1375b23427daf29abb5365da7c5eb45151263 GIT binary patch literal 514 zcmZ?wbhEHb6k(8KxT?cYwfuib?L~dJ((aA_dp7^~$llDt$|)qHmp=2KQ}R;lh{-k) zlL{C9&zkv-gIiEa-Eq#|{|tW@d(K=FaUKhaS2FeOnsj*>tEWmAL+CHn+JDpJNI8o%^_{(e;@#= zArC12=k{|A33hf2a5d61U}glGqWF`AHHAS32!R0PO$N3WhiL^KI#T^7mK2@Lv6>%{ zoaMDPOjkCE&FMwe{#d^z3x+l4UVO1sP?&wSV4JjDKL6?T^NhSg3!j$fvkPXhvDKG3 zRg`2lbmjMCcj|Oc)b5*-#>*|l$8Rs+JGp{GSX3lKxuba6^u-e<&ft+^-MVf2RxSw_ zacQmn2M!(#JaY8d@e?PV91#vhSUX2ys==Bjuo4lF+Yw5* z4ooeuuyJW)a~43Dzy>sdodM`uHg<>ejX)D1TEX6CWe{ZGWMBr$i2}8H + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+b/
+p/
+y/
+ +
diff --git a/images/mood/square/p/aggravated.gif b/images/mood/square/p/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..0aa31f1c3d7f31b552e0fc2f3e0a389ab49d17b2 GIT binary patch literal 434 zcmZ?wbhEHb6k(8KxN61lzv|Y-khTB2@0RK({_nZJ*<;H8^vetk44XZt=n1L)OTWy? z!Y;(Y_rLJkzw}Grvd%e5nca@q+G$?I#K`n3@8YlAi@&liMyvXSD|`IUzxIF0(@EBq zldY@XW*s*Z)A^rqd6i4AkDUGcj1!)+HvclO{4cz|*>h^0amMG&)BiFq|6lOrL)r-! zX^X$vmzO$q#;W-RD!9n;NdCw;m#-W1Bkdd`1LOZWj~%2;|8INsKkf4W|Nnt*Lk5cf zx&2&2f}I@$T#fV$m>Gd`ia%Lcr!iPD=z!FLyve{e*I{mfhmKVLi6uoRbFAhEDCc>t z4KtNobjt0;zg;c*J02==G3+dPw>@k*Gqdq6-}>Y2&#Pqh{5K0_8473BR1|ZXW^r@3 zlsi>c<+b(~Pb{modz1|BKyqFJb>@)Bb1E2?Pf&5+?tg z*=(*L03T_#Qv2o8xia#tfrNgX^< zAVhvMXm2fC|8Ld;0RluDI35fcKpHjww(6CRj(BnclZybovX06YLJ000006aXFo00zoHo^UwC;fTnj z&}OtLpUz?QDNRnH*sPX#-SWEBDVX{#la;oddd+UTjqtcUuFK(S_`F{KfZggiCkg|E zg@%M85PxzbSk0lH)DI+Qt8rZr!2NV||1{o%^ z&bRG=91a5X_4f26E0zl_H2(hp0WP{hu%N+%1$8J~$grWqAOIox1O*fTJOC^P01*HO R009611_r>LaJUNs06Vln$h-gm literal 0 HcmV?d00001 diff --git a/images/mood/square/p/bored.gif b/images/mood/square/p/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..307f349451cb0f71e47e3c08aaa70422d29bebcf GIT binary patch literal 405 zcmZ?wbhEHb6k(8KxT?-@F=Xxk?z^S>iT``<|F62W*<%VP3%j0>+GOjhRW7~%3$OoQ z@Z@vmX(=u-Ar8L(OP&TQxM&F}|1Z48$iV0*WyZk3@Gt%H?TD?vaxebKI9F$!@qfT+Iz|H`4D;t}`;d^zi=;r~Yp|{lBPjVfXR}&9hHmfAXJ|ol{y#@6G4`(|7%w zzyJS?-Tx6j@{|B!A*ERR)UvlBx{r^H@a^cyN6x2;8Z+fq7>N$7c|CTwYuRZy{ z|H}Wjpa0)@`hUjGUnx1YRejrL?EW`x)#XQT{!dzdQBB|R;I;o#Hocv>`)^Q6r&CaY zg-hJjt)H_>dspnd_37LHAHV-IGBQou{$tUu*Y#5moxKNi^M43n7z#k~KewN2NU*bG zfUA+70W%}e&5A!+I2jl`7<54H2SpPD`>_U(rskH`w)T$BuI`@RzWxalCw03{oi=^C znMRAYFw^`63+HpYv@kNbtz5NwB@6Si6>B!F+puZ#`sU>;r8rh8JFeQYb0Y`;Dt7jR zJDPTFTYc!v#&c^=dz|HRvJsRqfL^l(04qH{)Bpeg literal 0 HcmV?d00001 diff --git a/images/mood/square/p/confused.gif b/images/mood/square/p/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..f88e9bba3029c894fa26a3e7b43021a964f9ad64 GIT binary patch literal 451 zcmZ?wbhEHb6k(8KxN6O?*<;H8s$2hi?q3X9`@j2cseU2@1H=D0kHeKc{x5m@KmXcf z>nctb_N7jpt6X~j7hVfgaM2S|yB)Fhf8q823!eN-zx*%b^8bv>-?GlV$UgEb_u|8> z{h`Y4|I#mUFth*7xacKk$Hd4e#KGq%WhTcXImx>6bLQ!fS*Jdxo&2AE`CZ=0A8F_6 zj5F+|O_>;(z80VFG%xy_b=gJQLXe&BeZ~n!2FAY`mw#lObC5FqzwOokw9Ehh{|CAd z4ix`$`?-b$J39ur8tEA@GXfpF`Mr5 zqF5@|YW0nrNvG~+t$ncJx`u4``4?aGj_2*Z%gH*qNZ`i%irXQ26hVs)^EnBnkxUdkzx$_s!adY_a30T~?dFxiz-Fx>RBshZID*|#a8v{QB q2M{u_$vVs}(CE3+#=};4GRLZYhLE>O)5Wlj|m-pYwQ? zOYbD>%3paGZ%1tXzvSssr_Ntl7a18C|7KtQk#WvP&i;MIiO-p*&BS#6WnBJ|cJ4#k ziT{Py|7To|R`vOpdF5B`#kX0<{}*0!lro!aUG**N+`sfo{}()oRr3?#;OjIm3Rm{< zl(h*|aH%uS$k&bepMQ;sk;z5cLXJn$LCW<1wpahtF8}}kp8*F@{Lk&@8WQa67~pE8 zXTZz|RHpcog*A@RoIwYq1>{WzwiyRz7kKDM^`BT$bTY?ken4`r*V-_7gGZi*FRJ#( z3buG~+&K5*i)4Vp?5hRaq~-GYPp3yR*>*2{TAt4-l)=GKU*=R%lG)IeZ^o9vHYK~$ zyn;l3ouLj<@dF%F_yH1W^$BHlj9m~eR!@$k}bUz!L!|Z|#ZYBn60LeL^ AZ~y=R literal 0 HcmV?d00001 diff --git a/images/mood/square/p/cranky.gif b/images/mood/square/p/cranky.gif new file mode 100644 index 0000000000000000000000000000000000000000..47c8a8a063ec458d3c0b248f318910e9d3efabad GIT binary patch literal 491 zcmZ?wbhEHb6k(8KxN5@izv@=0e&YY`yPG|xTnt(Jzvuq{^vileYMdR!yGUF7FT5tqAt1#i#=*?a z&dkQk%55sDqbsB;#Lj;yWE~d^hk>w0mR5uS8!tZ_kC~WmjH*wFlG`l1dKM;TO#vlY z9tlwnL1soK2PxD4+g|-oyUf7A@c;jRAc-F+{^#~{4GDI33~)8lGhk)}s#g5T!kWTh z!k`1v3GyZbTZ_Z20uLRj{u4`zPUcw64@l1OS{o)UsPrW8#lKyx`V!8HTnwAGyxAVM zoRiV`mT&#>_UBcydj9czS;AadH5J9m`dLaGE#*#?Re7!b#U*Uh%W5a~&dRi(UozQb z!u+KR`xX~3T`+0IgxN-m#JHKaZri?l}fD&n%eSAtIcQ4+4tK$RlAl?^9fU8Wn{1h05;#8kpKVy literal 0 HcmV?d00001 diff --git a/images/mood/square/p/curious.gif b/images/mood/square/p/curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..4340c03b154837a2dca7ae88df1039e3568a0d19 GIT binary patch literal 429 zcmZ?wbhEHb6k(8KxN5=hzv|Xzk0}>J*8cCgU#g$@zx(e0^vetk44f?N|I#n(38_V^ z`h3nj{eRBmw^_%-l|9~PoQPHP6XM`wVr2T2b@6ZZsk|H{3%%B9yq%Jl!XSO3#4|Ns9V=qgO0_@CR)H6+;C zF~HSG&w!Z`s6z243+o963kDsKYLGV>*ycFQDe%yd>OZlh=wy!7{D8%|UTecVwHK{4 zd{MPOwx>OU;m)}iUm_h8X6Nshx9UsVef7ue+6cS(A{qL^rMWfvT(TJ)94+OQnbl6U z>1-Kn)3aMArLoC~a+)|I#lvYsCaAxWuXW1Pbf^FTD0YXZ!!c>;E$@*Jwuk@4E9}Ht|>P#sA6YR=M>4 zk3aFh?%cPGQ@`>qzE3|s*}BS7Q2oDo-KC(_w+WnBKBbcUIM@n8Cd z|4FCwBy9gLdHO$m_y6*1|6S(($T;`MY3hI31aDcJPV=IFX_tN^pJHKT(i2jX=aF=m zws4R#{lD$i|Fp~h|Nmzo8Yuqf_Hzvhc6JPKHPSO+W&~+4f}xN>2V@8+ni$w0 zHWW5Bx3spkcXW1j_w@GlPiV`ZJZ0+Cc*z#OP=>kl=Fe5~ZDC?7SiWNAa%Pq#%T{ez zvyOGcO4d!y>WLh}x!EgnvUoUnTtr(WoFmMPqF4CX3UP~AinUlt^YJEVZDAD_;$`Oy z5NJ_0)?nw3yXAlKq$!Ot1zEn6TM<1|5X`jI;e#O#jzF1@^CoGwv`$s{H?kEwrcl*HFbA-mmFQ*T56c^f5DT< z)>YppUA#17+K;@G7em*4X+8C*ZOzf_S$BJu{4cz==5W&gIgd{-=sB~Xmzj<6@{H-9 zOAduAd#rNl{hxnr&&G;vI|>37T+Ytx|6h2$)FAP5+sUKLTfR-c@H6-H&z#dga!>v4 zyKyRM;mi81n?0v|EzPv6ZGsq;z=6VFAiTy!pUsZ;0gtaJaD zJbl)@;Z4oX3t_9TESW2z!{I1xW~`&k$-@3K?}CS=(X-mEjLZy7ER5@S=R7XjBgnz` zuzfWXGh>}!+~%EmF47iEj7&V-9B&H_$?-^vDRLV~sxdGybTvhAbFj0rGkqyJmr`sg z%E$MhW3{%igr1PvgZfPlQl|g6z51Va`Tzg_K*e}~;(u;G*N|Xm#{gF&Jp*Pπ%3 zEUYION*Q!O+Cb67!2Y12w5hqJwXMCQv#YzOx37OfTk+&6Q>S|CwMeNk%$+xXu8L<1 z3v0>p6)TssF)vxRYQvg!8#bzPKOgynos1cV&hg)>SE7W$|@ zIKaqwh~+GU(1PXX=QGyiBsi{c<+1dbtQ9J?a^>aa0gJsvML58o76Eyhm4SzWgMl6B rX{CnJl9JNa=F+s-*3#h2?*0iAC&p*QV`|Ns2?Uw`_4)46{@WhFZ~S=j$Sdp60s@_+ud_ZcUAmzfxuE@+<4&+pOdN z(l2?++T`oTge!Y=nirXg>8x_;{grp|L)wXdnOFW7Ui*=D?pxM5Mh3>e*_U0UEtWcU z{>V7@f5DS~8JA<#{Ql2*>>y?OKkf2=pqu{#iJ=4(|8x7fh6Fo12DlpO889;f-LCkP zg>@Q(D}xTmAE0PrV87Gg+SJ_A+ScCD+12UN)!W9`-{Hd7#xtqig{O_%Wk$<9?lyiG zuKBJ@UHIEL=gkvs5?$xQ*~+HAj&0ZOb*kbmc8-F=0_?|*3kVCE*|ab+J7287=zRGK z6T`U+S1w<>ezW=fmB&wR+`4GZdqq*<{&Qzu%PS%x?;hTM^7KK|ql>IpSee|6%k|^! zn*J;hJ+Z*~&;%yaq!ki7)_3e+(sNlev4mY+;v>$ZOHDaB=GAli~W4 zkm!G*gO{a9$YbH=<(=X!DGLOgwyX$T+&xJv_SBY@!A^}34~u|2%+A2Yz{5EH`hUTb|M}O# zl|49F*#8$^4^(i`6H=ROUG=~4+W$F^SGn|lEk4h|%@jv~ty|n57jLVa(E14J> zKW3f!n08W-ov+ip=yT@j7uiR=|HP7_lQ~xN1C(>T)`szNB{@00sM>$`L?egBiE}T$SQ;qI zzFM$NS}vdeboy!LyHX3EmgkGwXV|x7mpN6GWHxl=_jD9boYa`!-df*j+-0TdhGa#lc$^;6Z7qet&9we;mRJO9D*;hk9;jY z&&0_1E9;_;n3|WIoxQXv4=Y!wvisYt;~&yae9SuaBkkO;yo(RB_SYF_c*@!cvh#h; zJpDK0;@_;xldLP>XPo$!b093U z9~tL<S&)NYS6J7ITP!WWve!7NU-Bex^zaGTQPQ RmVVBvQqmlHx_*re)&LW0(8d4& literal 0 HcmV?d00001 diff --git a/images/mood/square/p/groggy.gif b/images/mood/square/p/groggy.gif new file mode 100644 index 0000000000000000000000000000000000000000..ea87e8cc5f3de924648e62ce48d3376c7b8af9d2 GIT binary patch literal 420 zcmZ?wbhEHb6k(8KI3mgLzvq6be&S}2DHlW5{;#_Azxyr&0|O@ud!T}go{-v7r_TR# z9{(@A91KmQsd1LOZCPj5$TUFFjIf5DUgh1VuqS2;+T{@?cMf7<2$|NjH^q5;MK z+!x!)H{TyT-uR&nfN>d724MZQZZj4PtnhjulED9qXS;Jw0uuWjcaf0Fc-E4}`3 z%k4Q8HT>*_(O=qLU#(Lws!3~XmaJ80>n^PBXqD(@>uqT3>#S?%5oDS>Z~k0SUKJq@ zvE?gPuJl}^r3i8pE1H|CfNo03oTt*ZFlX5|gFnYs?zmLecl-Ojb9M{zPwbND_fR?F zI7^4&!U_?uzzJL|Q_EJ%vaE|-cY|B3f4}mYncjZw!u)R^UU2Qc^18}$eb)WMHFc5| pT5N4OWz7u|ZEPLYjh!u(O+e?&m^o_(#5s!=FInQUTvd_58USgSsvH0S literal 0 HcmV?d00001 diff --git a/images/mood/square/p/happy.gif b/images/mood/square/p/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cd6c40727f0cebacbbff28982a6d6fbc227ee84 GIT binary patch literal 757 zcmZ?wbhEHb6k(8Kc;?9Pzv@=0e&YY`yPG|x{O`GcF=Xxk^vnO!FLSc6>j|m-%DVW! z@cJs3-e0*F|L0$uWL^0qE_u@|3lSR`rQh^J8RSe4BOrf5zp1 znOFX1U;dSM(M(LoN6tQ9H^xQULXJn0iIK@zRLfPyQiz?OkB!GjOiP$UKwnfNT`Npa zSj|Do^#8V3|I;r2|NkH8h9L?R|8x7fh6Fo12DlpO889;fy`lJ%g>@Q(BZCgeOQ2|C zU|-VU*woz8+ScCD+11_C+t)v#&3^KfsZ*u+TBLsaO~gKv}4Q41EG0+PIJDhdtO2x Ry1X0ca+tFrdT`ip4FF3q$m;+A literal 0 HcmV?d00001 diff --git a/images/mood/square/p/hopeful.gif b/images/mood/square/p/hopeful.gif new file mode 100644 index 0000000000000000000000000000000000000000..2581a22983a636491abcf45c3a95a7de9879fa9f GIT binary patch literal 788 zcmZ?wbhEHb6k(8Kc;?7Zs-O73`|f6sDgUc({qMPdF=Xxk^vetk4F5AO|4YBDC#1&7 z!p_0Wemi1opn^-dvd90zYyTHK`CoYbfBv!-hBkkP#j1!Cuj4sj^KQhkc>&8s7uIw}~`jvIjN6!9l z_GL3MozI!4Ss0n+cqFAoB^enRgxL9gwVWlnMGZtXm>8LaIQZUX9p_=?a+ETwGtT&x zchN!0^#8V3|I;r2|NkH8;2{bW|8x7fh6Fo12DlpO889;fy`lJ%h4lo3BZCgeOQ2|C zU|-VU*woz8+ScCD+11_C+t)v#&3^KfsZ<TLdLo=FXcxS3snNk=bGSij~V*8I~+t zwPDS=4I9@sFI}$6wZg!B#is4+xl~qgbMN2Qv}4Q41Ez-`K03HuM#IL!T2oo+?fK=LYI+K6ijot~CaD!nXklX#(u$dJ;SjTv zxXh0k9vhR6dPo>&-8r#w@d5|1!$m+2XJg=D;9y_}I$W;7n8&e2zuu9jy`{dZrLT`; z0>{MusV0VIQ%#L}8^KyqKw4OVS~!847}%8>98|d+S`Exwxl~#mxVd{KOl0d}n>ulN zlU2(^uKMm76Cm2aHX*cGH#h>VYSpiA<>_dx?{4j%;KF%{%LM>e1bf!+h!3iO_% TjE1REJQGFSruOB2^|C7`IPf7p#ev_WG z(7(y)oUAPWXBYmzy5s+uP5=M?{C{!#|9^j7)TKX9%#1Zte>)-T=j(1pMuvY=GOE-V zzU;91J=^)$l&l{gCjEc8?%$O3Xj9d1H)EI>8Gp>x|35ST!wbuQQ!{^e82*00?ElU= z&s`Zh{mnmp%J~0g$JdW_|93C=|6O4)p zP0pGWYV&{plE2fkg}B*2ybt}c*yz{v+|0k#Y|NozXszC8Sx1VcBu(M-;tC5}oGb7M& z#h)y!A`GbvIv|Tc(Zs<1upzanxuvzOy`!_MyQjC8ty8#D->7LqGn-(ig5Lx#t|mdY zs17a15HEjqGqwnMWr<0xYz9G^GJ2}AY`$(z?rhVW+1bNFkDTBa2#*x9Q)@BQX1Q|p z+7&*X7DlF&d-osQV`aX5_u=!$Pw$Cv-w#%~|FZecJ#NYSyu2Tue17))!6%lBzu70u zcPQp52$?a_fw{T%)rk);HZprm5%bLGFpg-8V^UJm<5{`!NK;?$D}g&d1e@`W cWA8hA?)-&|mo5WC>-vqGw{G9*YGkkm0LGGA$p8QV literal 0 HcmV?d00001 diff --git a/images/mood/square/p/hungry.gif b/images/mood/square/p/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..02f551a49bf27d748b3284c25f4b778384265b7d GIT binary patch literal 751 zcmZ?wbhEHb6k(8Kc;?CQzx!^fe&S}2DHlW5{;#_Azvuq{^vj$q?0Q0K|I#n7a_J3J zaQQ#yu@DE}{{>I}W?%l5ckx%&#kX0{Y$^}KI6oXv~xc)&P}qe{FQt0>#AE{*4_TR`qr2Aw|_TX`_*u1Q{vQ5+wXkZ zdFTJeTmL(*{oj52|HSK`x7=P7-u->@^?%!L{_nZwAZ7Z0+pGU+m;e9&&oJnL;(u;G z*N|Xm#{gF&Jp*P&po0~EvapIUcrxgK91n^n2KJQ=o=wdyt!?ccon75My?y-?+T15k znL1TOv4xL^b?&_Rb5#^t7+5@(uUNU9nQ_UoRU6i<+puwM^U~$g94lm%S8Uq8o?qJjA=e($;DU{{mQ!7XBV8-ZRmRd-REv*|N0>uEPgqTe zo!>#q^#8V3|I;r2|NkH8&LIjE|8x7fh6Fo12DlpO889;fy`lJ%h0}<^kwFLKB~Uam zurF?KY-(<4ZENr7?CS36?dzW~aZ=kfWZ9%F0>Vy99(0tK;E6b~;o%`( zIgZ|n2a6XS?G{(hymKNjSpl27mteTN&3^KfsZ$}Yo;z>;T!^ceuUNU9foaLIRU6i< z+puwM^U~!K>?@>1R&3h7o?T}JC+GfcO*^)%JaB5g1KSF=E2~dB?f|*^BGA>>Hp5;0 z=-_ggtKXhq4t6y!--NSCY6TbA*_eg2VrCRHvpXrv{g~mgG3ls>gmKoL6B`#VaKPs9 z8K@5Lwg(3IB#5hL&7Lz0;_4+!mn~snTDW-m+Lf!-QYn$8>$j}gxMy?I z)&mDO99?n9aVwie{rU6OiYGU)ncJF~T3Xo%T-mn-=G6O#*Fc?m?7<0#y-o5w%zys= p`y*{5AocM;`@v=oL93_}8x|gJ7f|+Uk>CJ1mK7~^42@8>1^`} + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
artistic.gif
bored.gif
cold.gif
confused.gif
content.gif
cranky.gif
curious.gif
embarrassed.gif
envious.gif
evil.gif
full.gif
giggly.gif
groggy.gif
happy.gif
hopeful.gif
hot.gif
hungry.gif
hyper.gif
loved.gif
mellow.gif
nerdy.gif
okay.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
tired.gif
worried.gif
diff --git a/images/mood/square/p/loved.gif b/images/mood/square/p/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..80fafe7ddedaaba7eac5cbf4960a9189b534442b GIT binary patch literal 464 zcmZ?wbhEHb6k(8KxN5`jzv|Y-khTAN?r-*(^1u6Tsea=B^vnO!FY5`Zak8+xNL$>F z*gDC&(o9U}|AHsKvM&B#@^qeO*l1z+D zAJR_zFTDOM_u~JI%h9Sn?=w!k%{u-q>)gN0E1t48v1)$*3$Hm!nT0ERe9k=mFa44b z2j67ts{eBycbXRkD!9}cXZ%Pz_b=mezHZEaL&N`SYX9~19i&YEZ+rDW?ec#HhX4P8 z1QaO#=k{|A33hf2a5d61U}gjgEB<6*O<}NM&;cm{d6R){sl&Vi4;`ug6Hf}ZKQ^4| zvg`||sNd|Xs;0Z2RPBF|lINp0T~TP!VbzS?_umG$crd(p_v4Rkz=GRf8*1tr8f%?P z%egozq@*jF+Uq$)DmXd&+nhRDDksdUw_>YcTT(sKrh`pblzpKJFaNS;HWLLUad}lW znN1VRm3a(xH1rjX_RcS77t@ksGuEEbJm-?LEI0GbTeolOYPv`oSUi66^l9RYm#-4X__I1BASBi ze2To%u8P+Gfgt1ZZtvM$PG$e+Jl^g({r{4uv+U|ux%B=^zr56`GhEq&jfu6)B9(=S z`Tv3^c{ne2tg^yXMKBk=%Km38r3*12za=YOP~ zdy#$QbLMGdQ7wCE(|_rg{$^Z`R`q$5wr{i7lse;#&7MgG%xy>aoJPW=0n4ruHlMqJxy_|81}Sr(I@XU;qXKkfat+{Lk&@8WQa67~pE8XTZz|G*|H_3+oAn zGzJ}z9iV7pU_aZC*3{h6+ScCD+11_C+t)v#EqU^ksZ&KXT4aS7=FXcxS5=~gi6v$E zij~XRnOiiaS?lY0I5}C_Hf~nbX;GHv>~55oO)3y+U9cr|{b5r7Ji-b9_lz^E8FS(_H+w@17SCto{>hSd2RY zPJU$Qo~Fa{b>hv7PftwI2;26hL*l&1Om2(17RLftj#V|yJ{=qfj2I?OGl))6NNH@D zG25c}S{lUItDeWMDS{`Ou^pWeE9G%FwizXKkn(%(-$r*c=6)G>C-cOeXU--x_al%ne*r8tzFx6 z{rdU-{_MWKtlPJ@@7}%i#fyuZHnlEWR&(|0>PwfFIyo67BzR1iQ2zMw@v^drJ9lu&uiEAxw)BCR75>|c$=zqGbiuV3GM?%dqHd;1u^F*G+PZQIsy^X8Vk zyr8#lZ!|p@0=p4|K+LA6{by%e{I}>(EKX=vvTRm5cp>;fBa36P(uZJ?3m2DIOgF3Ly1Fc+ zDP(n=>M$6ewIUX%f|vu&Y|~ z;6bC163fC51{)VPJU-s%cqQQGgoXTq;yfAm*6d{B6=B=?Ai-gK$xCLDIEgz8QyUZd zRYUG*Xgu|7=3H-^R;bkSfL&HlM?k`_W=E@BM3}&ziA#<)JioB``G$)v4<-oIY|6gB zuGZ`6dtPQHM3}HKa4@hl0E3BxlVNWPgUg1~(;E=7tPGqCTnsEgSp^2hR1W4952k9f z0z+(t!a^oqDF#i6V749?!<2Ix92{UxI*hnxmB2|NLu09DLuh z&fSjKy40z2vUSz3+>8IxFaKZg|HP7_lQ~xN1C+D8 z)`qEaCbcNNsM;Uv+ibzHti68&~ literal 0 HcmV?d00001 diff --git a/images/mood/square/p/sad.gif b/images/mood/square/p/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f2cb66d6d56c985f0ee7cfd409015fd6200a996 GIT binary patch literal 739 zcmZ?wbhEHb6k(8Kc;?FRzvq6be&YYCTmQT7UJO~g*<;H8^vjz)r|1c({Y$^h$-*AD z=C`Ai+5ZJk{$^kHl(l)Eal%YY=XS)_U%3~V7@7XhdHlcd`ckLP|M}N^HWXtsf)CQ5C`9n zjB~%TF8<5BlCK+6XPnV#UKFU{;?sRv**@k&+6kx14U?^_=AHXrzwiH?v;U>^UAEu; zFQMbG@y35mubj=EQ-7qLbC5FqzwOokw9Ehh|7RFdK=D7fpKD04vtxj(k)8oFBhc}R zKUr9f7+e{2Kpp`_69fB_2G^$Mme#iRj?S*`p5DIx32n}kr%auyDbd0!$}o4{{JApX zEzC?V%U7&i&ce84*{Tg|)@|6hwt4AtEshoPA}cm+U(cbmf{Sbawx%6hRvtLD{>np6i;k+QB^k3<}nm-ytJ83UqMYumS5WR#X%P~Nj}c6dV;#2&tJUD7C9kc z!Gp#oRz4Yqpbu^AP8um3Gd(sY9rchf&bo7AlOl+MR8LR<=mDiU5 literal 0 HcmV?d00001 diff --git a/images/mood/square/p/sick.gif b/images/mood/square/p/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..573071bb46d62cd3997b9740a74a919839480344 GIT binary patch literal 830 zcmd7P`AgGr9LMp`?(I8wdJLA@uCLR1O(Tz{#?npQVMdW;3K>Fy1VR4b4`#W|dtRwC z%S2MlFkuCz>E`Br5SI2snA$wT&L2j950Mccf`UQG>O2|@F%pOlf@m?sv4=zgzq`D(rN2UrciDm!)IfZ#$qs7@ls1hkc25z;d;6cN6qAPigWJ{M*7#Vu$>ZT}_N=t6wO0KZAqd1mQ;`NHt9qO<$$L8$7G=Z{Knpeax(4YW< z38M&$rzodH2HAzh*2m3#y$=I0@`0K1kGb`)*<>(O)YMcPt+ln*hQ_)(Ew+}b_NKOb zwvGqp=I+Ygp8C!{vu@zY;NT&A==t!_A>8GjaFK|P@yYq=+4+STv-9QT;;Xp?s+;_vx^E_5kvF1j KOVyMkr1}H#C=Pr8 literal 0 HcmV?d00001 diff --git a/images/mood/square/p/silly.gif b/images/mood/square/p/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..33ead3dba4b7d3de772c75ffa4176fc66a906509 GIT binary patch literal 438 zcmZ?wbhEHb6k(8KxN5`jzvq6be&S}2DgV3gUJP0Lzv|Zi^vileYMdlfT)QJI#y! zZMzw(=JzlCQlNs%|0Pd&E;qydJLX;UH!Df7`47X_x>1 z|IYveivPL&TtkAL9RpmA^bD98f#QlkSy-nr*f8jT)PTInz&6)mUV(>>RR4)3MJIEt z<_9d!^I990Xp+>${Gw`q?1WAWjW_3Be3>brF#Br3Hfgzh{?pG-GrqmC;Awe2yKn{v zM}3)7MM-8uSH3k{2HTYEPMZogMJ=w0%EltoirLKMB~;}!bd44@TJ!4g2=I$(D;cis zw>FjJ7UX1;((5Qz5$&<=voRN9I(PoUIav!Ab$!blH*ehvynFBdgNKit91$*NW8h(6 bXJ7)lnD4;drw592%61=aX@BsxiNP8GarL>E literal 0 HcmV?d00001 diff --git a/images/mood/square/p/sleepy.gif b/images/mood/square/p/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..48754d58d3e17a213ab6a7fecdc118e901cc3d32 GIT binary patch literal 424 zcmZ?wbhEHb6k(8KI3mfg*<;H8?z^S>iT|r^T?|?Kzvn(D3;X{iPya7?^1twUxU$FX zh^=};YJmzaj0}wb3$Oj3^LVLK=PH-p$<|f>^RGEbnf~AQih+UQf7<2$|NjFSXh88l zx1VcBu(M-;tC5}oGb2!1@h1ys3WFqr4oE4;84RrT32J>QnSBwn=IL~9eXG4HyXI6` z=VoiJ@5T{rYRX*wCzco`XIjla&)nM5AhPbpo3Db3tZYXN+7v!C9W~h`IajZLU(VED zwP_Y1Y|VFcn~oo^k*q5$u1#-gY?cu3acOO8@9xdbuJ7;4=;!2Sm^*L&TwyL1Azsnt zD^{-bUZblBauX|>o9e)BnwQbFHnV%{3+r{8vae-z9=FoDWIQe3Lx)fI#FC)O1rr1& zG?jQwwNqMhpyAkCA(orD<$rklPd=FV?Tv5uHHo(7G=mGLvJ9(R>tBDbl`PN}Z_Q0J oX%%m;jOpsB>uZZ?Y;MSt1UhNX+<9{#PFl8n#R|98nu-k809U%FB>(^b literal 0 HcmV?d00001 diff --git a/images/mood/square/p/stressed.gif b/images/mood/square/p/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..972a8348a527833d05049a64439f52b547bc610d GIT binary patch literal 617 zcmZ?wbhEHb6k(8KI3myRzx(e0s$2hi?w9H(ZuXdRF=VZtklO$B%P!Iuj0}uCtXvEX z44f?N;mRINj7mX(N zf7`47X=nbYUH9XaPirxUJR&Wg{-O_gJhWAD^#E^lp=>yfX>=PGO} zo7Bg~T|K>_f5ME({S(E6SyrrEwL*|rMM_k9)8;K(Jht!Hxl2hAn+touE}S?2`NAi+ zb}h;}WT-p6BRZ0zmzW%3nT zY}}j)4c)bJErnHGJ#u{$W@OfN&R;MI=)mPGRxXD)aO0-Un?1GxT?la?D_RgvfH*My z`b_PceOl4`l5Fnl#XjE9_fIeGEW3`B@0=w?JNMXl2y`WQt@Se&5>j~ZvTFa`Lk_2* zL3pc75Ez6HUALcZYngs<#b(#MtoX79U>Jg2*^^i=-x$lrUDez_QLeLaT4vnjsdaOk h`W7v2kq0_*^_sP-A&%U-ZToijUAy<}Raa!N1_0jt`*8pO literal 0 HcmV?d00001 diff --git a/images/mood/square/p/tired.gif b/images/mood/square/p/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..891e92c6c3f0ded28af04129bcb49db577622786 GIT binary patch literal 287 zcmZ?wbhEHb6k(8KI3mfg*<;H8?z^S>iT|r^T?|?Kzvn(D3;X{iPya7?^1twUxU$FX zh^=};YJmzaj0}wb3$Oj3^LVLK=PH-p$<|f>^RGEbnf~AQih+UQf7<2$|NjFSXh88l zx1VcBu(M-;tC5}oGb2!1@h1!GGzLiq9gtFxGZ&{?fA7%pL-P3&*YfP zd|sJ-`Mv4gc~f3*uFLVR;N)g#@91n7=28*j6`eR~@?^tl(`U?_HCss$?1U7M6WADd U7}yzru3}|-@I7^j1QUZb0LC0^>Hq)$ literal 0 HcmV?d00001 diff --git a/images/mood/square/p/worried.gif b/images/mood/square/p/worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..0122ec50b48519f6a87618e27f4c1e06e4ff8634 GIT binary patch literal 514 zcmZ?wbhEHb6k(8KxT?!gs-Ji+W$F^0~K5xrOYN< zSAEMmcROP1|0Pd< z3s?5|pMOn?OH4~hnSp^pjz`i(+JcFZ>3{m=PV=Jo87KawU;2@D?q9}b2PxD4+g|-o zyZrzEf1pY-fZ~5{Ki808XU70nBRvCVMxYUjKUr8)7<3tQK*oW*$-vffU|NBPj#U4N zB}FH5tmX$i&hlCtCM&y$Me#+|{=2-b9ugbQz4&6upfLMt!8U2ReE!qv7a3)x7CtS{ zXBW(1W2-N7swl~9=*sWO?$qs`sM9wkjYmpCfXiOKcXEZ8s5pOyTu1S=>5C^!oFU1} zx^>(3t=uv$!kk+B4;(xgc;x7@<0no!IU*d!%D}_G!N3G`7@xz%MpvHRh<1*NsRkRG zz)D0wZbvBLa+p?NVdK)q<}83PfemN^I|IHUk0&Q|mP-!pDsiTL$7%h6tHQm@UwZy7&6r2YDo zTUTlF|3@JsBSUPIx|}S}zwephq00Zhr~7!xty<#Z=_dE~S=Q$_nUnji|NmO@<3q;( z@A+mXqW`}a{{J=S!;7>)KLsWx#$TUvqa##ZoTUH%-sWI0_5XX?|NsAiu0jKf|GE8K zLxPSf?>qGU$Mmg1pJVHs`>c0uLRj{u4`zPUcw64_KV*wKgnN zN9l>{i+{UX^mhm=@-gi&dAB`mIU|$tE#La%?a!-Z_581kWGNVB)l?L7$z^eJwv;RJalpdJ2(a8V0H!$237`Upo6&_ QngV_tmhAS35n!+e0Q&!{uK)l5 literal 0 HcmV?d00001 diff --git a/images/mood/square/y/artistic.gif b/images/mood/square/y/artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..7563ea547330e94cc01e5fe7c2056b9f944f9a80 GIT binary patch literal 475 zcmV<10VMuMNk%w1VH5x!0M$GIv#v=0`HTPfjCFA@(aTi-_j>>LXa4qQ2?+!)EfQN; zB{nn_Nk$&}^KJ9&Y5(|fZ)`39_i>4ZH~R8z0RaF^N*@0AXa4tT_U~#E5eNVIp#S%8 z|N5jsKN|k_XnuJ#laD*^=xCCSJXcjC`0!}|_h|a_YWVPGrJzFF)L8xXYpSF~QBEN6 z=w|KaYF%0<|N5K)0s%xq8y+1D|NFK;KN^*ej(BnclZybovX06YLJ000006aXFo00zoHo^UwC;fTnj z&}OtLpUz?QDNRnH*sPX#-SWEBDVX{#la;oddd+UTjqtcUuFK(Q_`F`v+1%0cE)69NFD=crj~F5!866TKC)m0>2P6&?1|A2q z&bRG=5h(!l_4f22BbF;HHU9qq0WP{hu%N+%1$8J~$grWqAOIox1O*fTJOC^P01*HO R009611_r>LaJUNs06RqG&BOoz literal 0 HcmV?d00001 diff --git a/images/mood/square/y/bored.gif b/images/mood/square/y/bored.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a124a389cd4133fdcc78570d9cde297488881d5 GIT binary patch literal 404 zcmZ?wbhEHb6k(8KxT?-@@pQ=Mbsqn}SN;FlU0SIB|3?oeCySo0(C0Uq|G(#lhbl`+ zatR5t-@Xztsn^EQUP?=@u` zq-Veka+Kmv7S=dMbp{=f`5FZcf;d^zi=;r~Yp|{lBPjVfXR}&9hHmfAXJ|ol{y#@6G4`(|7%w zzyJS?-Tx6j@{|B!A*ERR)UvlBx{r^H@a^cyN6x2;8Z+fq7>N$7c|CTwYuRZy{ z|H}Wjpa0)@`hUjGUnx1YRejrL?EW`x)#XQT{!dzdQBB|R;I;o#Hocv>`)^Q6r&CaY zg-hJjt)H_>dspnd_37LHAHV-IGBQou{$tUu*Y#5moxKNi^M43n7z#k~KewN2NU*bG zfUA+70W%}e&5A!+I2jl`7<54H2SpPD`>_U(rskH`w)T$BuI`@RzWxalCw03{oi=^C znMRAYFw^`63+HpYv@kNbtz5NwB@6Si6>B!F+puZ#`sU>;r8rh8JFeQYb0Y`;Dt7jR zJDPTFTYc!v#&c^=dz|HRvJsRqfL^l(04qH{)Bpeg literal 0 HcmV?d00001 diff --git a/images/mood/square/y/confused.gif b/images/mood/square/y/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..c26351677dd912a85d5a14cf17fbfa9c3c022111 GIT binary patch literal 451 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 R=OyO(h6QGI2Q@NS0|4zgEQn(EZ!%q+ zq{Bm%|9@Nf>r-xQlsXd=ql3NF|L-;s zF5L57m%50y3D29y-^9PpMYxsCVjbJA-RtbsTJ*)actqHb9T(x@GPY`AWOBY(f6@8! z6=sHW7p`2scKv4a`74i~+_-hohVP1r6HKg literal 0 HcmV?d00001 diff --git a/images/mood/square/y/full.gif b/images/mood/square/y/full.gif new file mode 100644 index 0000000000000000000000000000000000000000..649ff4417030d43ccbf63b8c0c7fc3b101aad560 GIT binary patch literal 430 zcmZ?wbhEHb6k(8KxN6Ms|9jQ{A3YaOhiqQwQCg_~|7Z9AUrSakaap>+iIbB>Pgm&n zm5A_A<^SLF|Nkfq^i%l%z3~6f1^<7|ncQ#P*=qjdLxz`!+^$~Fr-_w75NUN(fadDDnVq$Q#mttgO`1~gGazTN?8UO@=qfh_< literal 0 HcmV?d00001 diff --git a/images/mood/square/y/giggly.gif b/images/mood/square/y/giggly.gif new file mode 100644 index 0000000000000000000000000000000000000000..fce30d60d11d4f110c64316e2ec8ec2365975a22 GIT binary patch literal 665 zcmZ?wbhEHb6k(8Kc;?G+@pQ=l?^T=Ed6X9F|Nq(j|3}aN@97K-4FA7p{QprH9;&=* ziOc_AOKx9@nA~su|L1~#-_rm8n)CN-#?l2&|GyXh|DGS{r@+X_z{0}B$;qOtBOD!} zDk#YD_iOgYS84eXe=ysZ@2*<evw z;!*au_gRkiQhK^VlX`9HDowt<&-?KqgNKLp*XOLzK$U;rGk<-`{r`KLgT2)M?`i-4 z{|9<%5CX;j+Lt)E-LzCJCl-;JdY+Q7-TO8m^Z$F{{~v{`mbffk;Pn6ZHV1pD|KHR8|Njrviv|?` zbNji51UowhxEkphFf#(B6@RjD8Zk&R=zx@hoWa0apP<&aq$4qP)*{K(tJeHp_bKQ6 zbKdK_=6+u+alu7qTg9=7sV8&Hg!zP&j8;Ugzv|h_qA_RR1AWB%a8T<#m}@oh;tS#Ub4hxxvC+H|9jQubsiT_hy4H1^Z#deX`%lA@9F=(rE_w!=;;ax39^5F zlX?3}L|vuH(gjYF`>lU{%KiUy!T(=#7#J8jTg`ubNSoAa^X+|Bc&PIG7a9M*7ykdA z|Kmf(zi%1;e=S+H#KqBG>cfk)|33-?{SQ2fvB=Nc01>=@u`q-Vg)2=s~KPZri`3=RxBAYXx^iGh7d zgF{nuOKV$uM`u@ePj6rUgf`pBQ>IRplWq|dVxBv1{#+%#78VBko#m$+q`tS3FitU;}x5>ujkZT!NIYAThop$D-WDnZ_l=Z?aJzt4m;R14RtQ+tEpVu z%x0jjtE#1~q4?+H|9e$wq5kG|9v4rC{Queg|3}aN@97K-K=F)!-_rGTg%}xu z>_SdXmOwv++gBp~f6xE_a{&hjb9kuo(gjZce=Yg{qj1#{m&yIs|9{Q-@geQk=d90f zGJU+{Vx!c5eaij!J=4rY^!j@rYR#Zd%Eg~n&BPqdcpfAeA#3&@l?r1MnS84M0S=O)5xja0q|9@|D zu$TJ(J?;Ph|3KFcU7+}%+s`#5*x50_)kx2PnGxs{#h)y!Cm0+UbU?lWMH2)2;s%GN z=9bpB_Kwc3?w;Ph{s|L1ZKq6~HceEZMNpD;-uwmg#6((H80=T9T(yFkaq05a8`rMi zxM^MUvK7i)D~-)oZr-thi+d$6?}6=2JGZVnczT09+e)^pYfd@rWRum>yriHgeSHg? zx|)?WhlZT?<3lTSR4mOc^pvFDU0A`XD|2e^TDiDe?Rj~7CQM}OVVgQ}dXr7dM6UYo z851Ddz&0VYSvNQUt!mY;Zx!ljt?zE_pWwjJ&oLF`I|nwP_kf-Q+6wfXgN}*`cRkQ+ N4iJxVIy5p^0{|7q*^|C7`IPf7p#ev_WG z(7(y)oUAPWXBYmzy5s+uP5=M?{C{!#|9^j7)TKX9%#1Zte>)-T=j(1pMuvY=GOE-V zzU;91J=^)$l&l{gCjEc8?%$O3Xj9d1H)EI>8Gp>x|35ST!wbuQQ!{^e82*00?ElU= z&s`Zh{mnmp%J~0g$JdW_|93C=|6O4)p zP0pGWYV&{plE2fkg}B*2ybt}c*yz{v+|0k#Y|NozXszC8Sx1VcBu(M-;tC5}oGb7M& z#h)y!A`GbvIv|Tc(Zs<1upzanxuvzOy`!_MyQjC8ty8#D->7LqGn-(ig5Lx#t|mdY zs17a15HEjqGqwnMWr<0xYz9G^GJ2}AY`$(z?rhVW+1bNFkDTBa2#*x9Q)@BQX1Q|p z+7&*X7DlF&d-osQV`aX5_u=!$Pw$Cv-w#%~|FZecJ#NYSyu2Tue17))!6%lBzu70u zcPQp52$?a_fw{T%)rk);HZprm5%bLGFpg-8V^UJm<5{`!NK;?$D}g&d1e@`W cWA8hA?)-&|mo5WC>-vqGw{G9*YGkkm0LGGA$p8QV literal 0 HcmV?d00001 diff --git a/images/mood/square/y/hungry.gif b/images/mood/square/y/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..02b97a4dd9c28e73a96336cb2a04eeaae7ea43c4 GIT binary patch literal 750 zcmZ?wbhEHb6k(8Kc;?Bld7VdTq5l7$-T!~|{Qq8c@pQ=l@9CVJEPA>^|GuUF`=0LU zCU^TvM4+F-->=z>j0_)Mq=knn|Nmb2|9k$bB`*0ny3rA;|G#Gl39|qDma%k!)BhiZ zu~F)i`>o$T%lh{{)67IvPL}8Y&jn0Oj6Pm+zdq->I7xqglllMGlK;QvIND3qRhs({5;-;aAgA3gTv@aeC|j($0G_W$kq{|;UFwCBd> z{g;0|>iqv;%BI=@u`q-Vg)2z0RGPZm}Y22TbZkmEto#K69y!LzBkrM0cSqqD2Kr?;Z=>`q-Y#czHgUy_73Ny0}Ks^+XZCHIvhHjnw2Gtv#w~YTztG=!I6y# z;do94VFoq^W}xGR8azD>4D~!rEj&3rJj~3Sni>(xSdo-jTG@NHIyl*S8nfBCw0d~p qQ08Hz>)GnTsqblO;o;G0W)4wy0u*AL!0=)MLI!rW24gmm3Dy8x^YR@4 literal 0 HcmV?d00001 diff --git a/images/mood/square/y/hyper.gif b/images/mood/square/y/hyper.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d27d39d73a2b3c8d05d338e74ec49370631509a GIT binary patch literal 1144 zcmZ?wbhEHb6k(8Kc;>)x@pQ=lA3guSSCtm(|Nq&&d7a1q@9F=(rR(VmadNT<39>UV zFnoTK`Tu+V|L=uzvOIN_CXV(}E>6-vKBWEnl-t>A{^3O$6BFa4UYk`*T>k%>vvh&e zug_UOK4iRqk@4+)*8iUi{{LEX`%1*WZyDjC%Kv{9PVTo3^iyDDWcc+t_y6~df8Wz% zqtt!8=@u`q-Vg)2=s~KPZmxi1_uTmkgq_|#K69| z!J(Ejq5&~R;qH@CTFRo;lcQ3(kcbo0xDO0CHTs?Q*{J9WUFJG~8IRo>OWve!GxxX$Ht_i9ume`cTQ|vyubmQ!)Ks6 zyxSHS;FBP(o;7>UEQqU@EM2yQfqCKL>ahnW?DsbDDY5?f`|ppM mhrp?VL+uBfIRveuPHb3sxLrWmt3`qX + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
artistic.gif
bored.gif
cold.gif
confused.gif
content.gif
cranky.gif
curious.gif
embarrassed.gif
envious.gif
evil.gif
full.gif
giggly.gif
groggy.gif
happy.gif
hopeful.gif
hot.gif
hungry.gif
hyper.gif
loved.gif
mellow.gif
nerdy.gif
okay.gif
sad.gif
sick.gif
silly.gif
sleepy.gif
stressed.gif
tired.gif
worried.gif
diff --git a/images/mood/square/y/loved.gif b/images/mood/square/y/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef4125f52f5558122fae5c9ad5868fecd55095a2 GIT binary patch literal 464 zcmZ?wbhEHb6k(8KxN5_2@pQ=l?^XYQc9$0FZ(ir||3}aN@9F=(rR(VmadNW!`<5Xm z%k%eZwvU(Gj}K{%_ENt-=l=hm|NlqfhZkv#j0{48?9mabE>6;)-( zLE+?n>)Tf%!b6q+eb0RVBIEz}j9;I#etgK7)NAwq*PQ=MO#go_sH-&j|7(e-o7~a` zPG%;e|GuYxd!H2>rQX?UzG{g}pq~O06XSnF!~be(|Mm6%|K8?cFZKU>+J6Ry|Nnsm z6e#}Z_Hzvhc6JPKHPSO+W&{c={$ycIVX$G)0Vx4_lYwoi!@L3y9jX2kPYSj_Hk|6R z>=c6}0R8Z+uNXG8_xt!e^953Ge_#F5#idv!>deKUMhud*T0|3;ur1 zC@Zqy<70dOvdPUwCNE3p_LYeL-}AfLoF?~M|Nk|Ig@x(;iv&dlf&V`W1N{{Iyyfj} zCEZ%D~^s(H8T;7jZ$~Cm-_fBZSy*>{2bl) zFEajp&-8SY`};MEjg9%^tE@@AHji$neRz@f_F2}$+gVIZ4FA5T+uO)|ev|p{TLvQ| zNs`j{Qb z1|5(!plD)XKiiPn)ZEhA*51+C)!ozE*FT{xaq^U@Q-zgUq*NK^&YM41Q@@3YHF^1p zmCM;!TI6Jy>+AVAIholvZkE?>kMpVc|Vb(SaD;B39_ z66Ld8%k|F6DlB0YXWp*9f@d42$lB(mD>y!Ld`VvOG?^nJ*z>ntUP&aY{{$Nrn;eOq zmmaY9DY1O*eQ5NgbBat@)sYT~^H(G|{ieA%9&lk=Rnu(L!g0XpK+iM-&j^JO$JQCM zEsCG@9NE15{CtOIE-n_Z4^u!sWM$xG-~>Vjb_0+PeVai(Y~wYm@9R@b;0WeE9G%FwizXKkn(%(-$r*c=6)G>C-cOeXU--x_al%ne*r8tzFx6 z{rdU-{_MWKtlPJ@@7}%i#fyuZHnlEWR&(|0>PwfFIyo67BzR1iQ2zMw@v^drJ9lu&uiEAxw)BCR75>|c$=zqGbiuV3GM?%dqHd;1u^F*G+PZQIsy^X8Vk zyr8#lZ!|p@0=p4|K+LA6{by%e{I}>(EKX=vvTRm5cp>;fBa36P(uZJ?3m2DIOgF3Ly1Fc+ zDP(n=>M$6ewIUX%f|vu&Y|~ z;6bC163fC51{)VPJU-s%cqQQGgoXTq;yfAm*6d{B6=B=?Ai-gK$xCLDIEgz8QyUZd zRYUG*Xgu|7=3H-^R;bkSfL&HlM?k`_W=E@BM3}&ziA#<)JioB``G$)v4<-oIY|6gB zuGZ`6dtPQHM3}HKa4@hl0E3BxlVNWPgUg1~(;E=7tPGqCTnsEgSp^2hR1W4952k9f z0z+(t!a^oqDF#i6V749?!<2Ix92{UxI*h^LW1m*dTqYF z&sw^`>Hn`KjEoF*l_ozvWc>S<@&9|eqrKGUH<{s~%Bz;R+`ba=|JR&AKZRePa{vD* z{Qo_Fa=-PD4{4pP=I>u*{QtS&|Mx-{Cut@oMmbrY|G&36*h~HYp7#I$e+G(y;(u;G z*N|Xm#{gF&Jp*P&pn-}%SyWio3va$|LNy~OtDG}pO)uy@MW;G*Oxg}lw>w^ z<@aQFYIaZ5=$kTO;*4%?E`Cm7c?G#i#Tsk^B2q$vY#qy|%}^3&+_rtkHd#>@F-i3U q2M-+zJbLW-iIb}je&=OodM`rHa3ST1sz;W4AuZGNQwji literal 0 HcmV?d00001 diff --git a/images/mood/square/y/sad.gif b/images/mood/square/y/sad.gif new file mode 100644 index 0000000000000000000000000000000000000000..f750e64e9ddf790c5df4bc3499ed001fc8aed22f GIT binary patch literal 737 zcmZ?wbhEHb6k(8Kc;>=TTB!g3XZQafJ^#N~T|6DKd7a1q@9CS@d2({H=;;dm`<5QJ z=67_2DkCGqug|%YdTrjn$oT&~PP9A1^r}LH5sYGFL5eS-QZ9iHY(5 zuQ_#{N-Bc<=+(|uY($6@>J|MmO+ zZ@lr}sdB@dv;Tj5NOQ24`u}^||LY+eR_1{MZZptD6ATx?xhtZiIO?YZr^ zEzK=ljICT6(N(emRZ29tIJ>miHalC}u;5fI05p~Zs93haxrwF8nZ=>m#I{WtNr$7c Jm184=H2@8k*SG)x literal 0 HcmV?d00001 diff --git a/images/mood/square/y/sick.gif b/images/mood/square/y/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..573071bb46d62cd3997b9740a74a919839480344 GIT binary patch literal 830 zcmd7P`AgGr9LMp`?(I8wdJLA@uCLR1O(Tz{#?npQVMdW;3K>Fy1VR4b4`#W|dtRwC z%S2MlFkuCz>E`Br5SI2snA$wT&L2j950Mccf`UQG>O2|@F%pOlf@m?sv4=zgzq`D(rN2UrciDm!)IfZ#$qs7@ls1hkc25z;d;6cN6qAPigWJ{M*7#Vu$>ZT}_N=t6wO0KZAqd1mQ;`NHt9qO<$$L8$7G=Z{Knpeax(4YW< z38M&$rzodH2HAzh*2m3#y$=I0@`0K1kGb`)*<>(O)YMcPt+ln*hQ_)(Ew+}b_NKOb zwvGqp=I+Ygp8C!{vu@zY;NT&A==t!_A>8GjaFK|P@yYq=+4+STv-9QT;;Xp?s+;_vx^E_5kvF1j KOVyMkr1}H#C=Pr8 literal 0 HcmV?d00001 diff --git a/images/mood/square/y/silly.gif b/images/mood/square/y/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..4586422e9fae29b4bb807678595a458a2365d138 GIT binary patch literal 438 zcmZ?wbhEHb6k(8KxN5`j|3}aNpWUT}`v1RIT|6DKd7a1q@9BEFLY$l|W+tNlZ_oe# zbAhLu+^mw<+Q0AVu~F*(z5_)v>MBiEEpeILZ~gzllwY57?RbUoBjtLr1Fr#FC6y2@haax&@$Yx}MB z40-uX*%Y-piY4`Xtov+K`M(?#6K>c-7mw*v3pyZ_+fBPU0Mi`f`>7}yz@ ZfG*}cAp7LN?S``5&Asgp-Zn8<0{{s5yt@DZ literal 0 HcmV?d00001 diff --git a/images/mood/square/y/sleepy.gif b/images/mood/square/y/sleepy.gif new file mode 100644 index 0000000000000000000000000000000000000000..41d4af3da04e01a4e4c029b0244b8f66d04058db GIT binary patch literal 424 zcmZ?wbhEHb6k(8KI3mgL|3}Z}bsnXK`u~4+UpyW1|9cfDC(HjIg_HZO|9{WFeI?@m z&jqWNxG*v@=;;cDhbsU7HRu2L!letG{{LDM=%?`i_cjN6DFz0H|KHR8|NjqUpaI4I z+z8gohsVQ^ypIBlPoM|=xyl2yv28MMv-h5S18Qyj$+>#{`*NoK zsx31KVQapl+jRVRjbvS6acz1_W3z;Kk4tM)dv|Ycc71l zU$Jtf_ZnSAkegW1+*Aj4)4YtXwVB;pUs$i(lzlC$^SG7HCF5!N9y)y5Czb?RdQK1% zXejZTDyOotBDbl`PN}Z_Q0J oX%%m;jOpsB>uZZ?Y;MSt1UhNX+<9{#PFl8n#R|98nu-k803(v8vH$=8 literal 0 HcmV?d00001 diff --git a/images/mood/square/y/stressed.gif b/images/mood/square/y/stressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..9cb78265b6a6fa47638e2482ffc26b1289727273 GIT binary patch literal 616 zcmZ?wbhEHb6k(8KI3mYz@pQ=lA3gtnc9$0F|NmaKd7X!zuF(JQ=`K#vjEoFCJgf{1 z44j-Sx35G5`YEhh;vy%@!^Fh+|JR)VKMMcK3Cd2S|-4zuOgJzeMi>$(CLILm$TwCa#Lm5ss1$>E(}0*;VPI5U+M3PJ-7N>c`Z8!7aMzfeVJT^7Mnb0 zLPK}0Y)fHPSC4Gpgc+H2o%0t=0y=Q{ij~VD4&1nD^Jb52Ko>$B$ch$({SXJHU!SRc zvrj8}Uy{vzz1YVa`u^#~on_aN@}0e;Xy=s>4-wA&BDY9TUc4;-0wN%JgHI~Yi=XJ#QPVHx#ICILh i2H9B)8)gCBxN7y9RS-9B*}83;`_5gv_oyo}SOWkg+WH;< literal 0 HcmV?d00001 diff --git a/images/mood/square/y/tired.gif b/images/mood/square/y/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b7ceb459fbfc519f30e4fbcebddf9acc1dfde61 GIT binary patch literal 287 zcmZ?wbhEHb6k(8KI3mgL|3}Z}bsnXK`u~4+UpyW1|9cfDC(HjIg_HZO|9{WFeI?@m z&jqWNxG*v@=;;cDhbsU7HRu2L!letG{{LDM=%?`i_cjN6DFz0H|KHR8|NjqUpaI4I z+u<|6GwX~(a9`rM$MU}whwS0g5y5hI&^xf@gB`+p?Yq(TgQNS*o z$;Q@D?o?Tt)!1Foo71J!GfBIDYC1o+kf@lwa^I9n4na}|=`)s0oHSE{mvP(n z9owX2T_k0+4jepmDCp?1<0noyBHYEwz{|kFzyx#`-+>E>u3s9$+BpkT4c0V)m56|x zj!?pNU}}MdjZYh!vjD;bHlPXY3_#Dau^+h52s8nr73^zP1|bGc24CTWSMI}zIQ!Np!j11NQL|3PM literal 0 HcmV?d00001 diff --git a/images/mood/threnody/index.html b/images/mood/threnody/index.html new file mode 100644 index 0000000..d5e5ff0 --- /dev/null +++ b/images/mood/threnody/index.html @@ -0,0 +1,42 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+mice/
+ +
diff --git a/images/mood/threnody/mice/index.html b/images/mood/threnody/mice/index.html new file mode 100644 index 0000000..ce7f327 --- /dev/null +++ b/images/mood/threnody/mice/index.html @@ -0,0 +1,78 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
m-accomplished.gif
m-angry.gif
m-artistic.gif
m-awake.gif
m-blank.gif
m-calm.gif
m-cold.gif
m-confused.gif
m-curious.gif
m-determined.gif
m-devious.gif
m-drunk.gif
m-embarassed.gif
m-energetic.gif
m-enthralled.gif
m-envious.gif
m-gloomy.gif
m-good.gif
m-happy.gif
m-high.gif
m-horny.gif
m-hot.gif
m-hungry.gif
m-indescribable.gif
m-loved.gif
m-mellow.gif
m-nerdy.gif
m-okay.gif
m-optimistic.gif
m-sad.gif
m-scared.gif
m-shocked.gif
m-sick.gif
m-thoughtful.gif
m-tired.gif
m-working.gif
m-worried.gif
diff --git a/images/mood/threnody/mice/m-accomplished.gif b/images/mood/threnody/mice/m-accomplished.gif new file mode 100644 index 0000000000000000000000000000000000000000..4028f57996fc34c5c485ad9770509c8427eff988 GIT binary patch literal 1829 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 YZi-{L=a2qwgNTn(W|w|zgFs;Oe>hMJ5dZ)H literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-artistic.gif b/images/mood/threnody/mice/m-artistic.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca0b15165c5c21fcf64a1a814f3efc80ee25ce61 GIT binary patch literal 1433 zcma*k|2xwO0KoCjzWD4*8?()q`O=Ld-$KrLL?>et&g0OgxE=|uC02Gq9@WP-U&mS^ za=y%rwB(V(hMs)4aEeg&)Ui0{E!}GcJG=u*d_tyStT2 zWn*LG7jEPc2#wJJR-KOt2`IZwJMdng_;cADtJSCEU z*ec8CVCRkVFDjEq%DE%Ae%{^P1^!VNTpue;02~PbKtB>j*z&ybaN#rc7fwIBS$Qbu#f-);^t1>iMUmqvpp9yMzRejjT z5q0ryahAX5Rnst^_FgikE4sY|AI#j#nrnP5!(fCo$!D7HP#P6rpS1Y{lIQH5zgmD= zqoHZ2KvvPdd(?ihx#{azqn9bgLZpWVa(e(mu6eY&}t z{eP34FofeN70y~%CqThVnz2k@44SZODdAg5xsFWhxhk~6#SSatEw9Fp=yQ=IYr9jO zUq-!k`f}|XlFPNQ{8AonAyC3kJf<|Tnx+~0P+l;5dPjv zx+n6@_eDP#sDFTa|# z(2J95v&+loAVDiGdKkRSa)AUjwp1F8-gB4C^Wb09&n@4UFbuW+Mp0Pn_t% zu`dJjS!Ko)pWXfKgk}iYy2geCj-1;Nq81N%N05ckjFYgR{)~+|Sp?`X!(NPBhxstH zrO~?l;sb>YUn@jfu=Ey0d5k_+!5g)$Jc=H_M8y*W*1D@gBMeQYLMbaCmbfzGjk@jT z4XZ9mMEyzCnTsiK3r*zMg_=uP@i(sz=0VY#kNjTn@pRz(vvG+_HmTKE*`4#6xn}^1 zOun!zQiZc4vbr|PDb2lG^L0hrR-P7Er@_s8ym7*oo;TScegz?3y}QzuHX$HD9`_U$ zD#nLYM>*bq?nXN?Q1xhZ{iDW7{rdjQpdN4yT)8On z;~A|v1=!T|6Mt~-p_6>w*OBB@FCLJrz~ku1I30RNlfV>Ka+U5 z1xN{Z*8gPUNgua%dQfmG5`-URuq~LF1g9MtZ-g&~*PtOCXfaiZtja+>I literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-awake.gif b/images/mood/threnody/mice/m-awake.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8ff1b67cce5fb05afc43c12eaf2b838df012465 GIT binary patch literal 1488 zcmb`E{Zo<$0LLF5-~klq0a5WK1K(03!*ag06{wk6nVP%oWt}Ng(n8}J=d3)y2f@Uq zW6=k9a(NK9Dxg+PD> zSowfftL^IQ>g?=nX=&Nm08J*7(P-4^bZWKQY&MULja5}u6%-V_cmaw;;Op0}DwXQ? z?b}mRQ%a>$C=|}mgK9Nsvt@U8gEKQT2!do}WGpQ$rKYA@ty_E0wqX;AMDg+QR;#sF z-D_+&W@Tl?#l=lbfL(1}wgH>9+nS%BZ|k?M_N@v8f|Qh$)pj^}VVO}CnaLSM^M zOH52mL_~zyd|>X^x!Tg&71K&bO~=Z>%KZHNOYO_Rz(5cL{r&xC#%A6=c^e!Y+*Z?; zl$4}Y(vy=}ot@z1>LGK3H3O zv!(_f9VIE1c{baQ_V&F(VUj=)sn?SN_XgJ2dv0*D$E}X#Q4= zE&gi);5Nm4X(1vjk}HaDmMBY$0ThV7CB-0E2#3PoDIwV1EmzqS3rPruT)9n3AYf}j zJRYVLQ|;`4A5}2yK$AK?SQfE5f zd+eYx%p;?3rd^qy2-OQ(KzsW`I3e_f%XCGgEXr}0FOoiTA)y_O4hz5Z z(IkVQJ*jk-v%W!j!Zq}}bz_>I$ZhZ@CG?j24mkzW6W%AJd-n<(0HWr~NuT4;?i_po z<0@y!$-OaxN1+}jAA=Y}kqhxziI13~dJejWBjz8vY<~R_)a_K4ZSs!PmFe1&AMH0Z zQ8a_&uUbF(I<`mV|JPWaLrTjHvp!m0jpu!JEw9>3G031A%+NMe2Khj}fcO{%k-5!I zED>I+SB!g6=a;aS#czmSx#%EsT9n)&9kX_ZZP_z4sJW8a6Z_OnF+O$PxmDd<_$Nae z9DO(QRNoRYQg>7i=b&)oOr4z0L`jFHp2>+W27rNXbua!jlXBjejddYRPh@YbRrek{ z6t+@FiMr0g+q2kW8aCK{B>vLIyQ)8SX}rta(3T)zJ5k%43l_?+Y9s`fAXN+=?0JB? zb`Q_)g~|yUK=6YlgM$lWFhTO7k5Gz_#h(T?eFrQ>1Q7cYlmMS;LnIf&Fcib}n{XLI ziJ_-Dfe@`hi~_R~8elDdAq@qxQ>7Q zEny+Db-RL-6`sVBnrL8bh&%hKZ=IUc^@QJ4g-IOw(h+hzdNlOS>Jv#$z~3QRtv`#z z1|l~lksKt4bNgal`Z^{tL`KbQcc>B-_|s0_MH9}i^^5|W!jnjv&zM%)qlwdOy>1_! zg2nExg3!N2sp_zsPGm-*F_w~tCUe$<7S6UtA_LzS69tcN1t?)yk2`nu@#OPwrG7{w z4UuOTuMIr^fMeO$$(-Nu8Ra)(Wz`+9MZ^&36O-3bkn66r-k=>7ONa1O5$QsHM9y3% zo_0zp#hzwSf<0Ny3Ec411Xwr0oL&cC`RF(yg^t(CWC3KJMG^51Y4j{ngq9izp>TLK z4f>4x8v}9nhN$e6%k6?;U3^89JGFS%TyFUDwa;n`ZY{Ep99$=%g^p z{4Dpm1{3K~fqFnmFN;82pzslnNm?Brjyl1z+<62!A`%*%^w9X&(JX7;MZEJ^?GPOdSH;GI=JbXeTsv(`^UZkz{M7G0AT;WvvygU literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-blank.gif b/images/mood/threnody/mice/m-blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..eddda4a809d131628c812a98ff4d11dde517cab1 GIT binary patch literal 1253 zcmd7P4O5Z_0KoBw7ZnhB_g&i~m@kbO*{RIT38Vwk@@4bT%!PTbc{^inndgcj;v!!$&WJacBAx#sN{$2rHbGIhqedBa`bV*gL@yZe94FJyfvVgSj& zdNJT~xu&M3EEbE&WLjEUnwy)m*=!>tBLf2iDwS$wWyRreXti1hf>u{otyZhSV9@Dw zGMUWnb{maGjYiYl+`PTL-P+n33Oy4bBCFuHd?D zy|J;;X0n-drrO%tyu3Weh@+~i%Ahq!BoYpXhLYHD(FauyaA1OkByQW*ve7M-QA zu+Y2e4Y&eEjj^Gj!SD5FWo3E2-b05DEt!_wR=2WMSy54;RcZ|?LrO}@`ue)x?>}|w z6dVp`Fc=vb8Tq8OmR)4h8FgzZa3_1v(PA3-|!y9$SUp7NUZhL-vlQ_oA{ zwZRbx@SgaOH~mO-Tm_42$3$@@uZ3fF`*a5g2bw2+oi~yo60;W6l!A$mFK_IM%ytn3 z@+TOsI^G>8hJvg!uO;hAaztj0HbK;8EJlPQi`w~`x(PTrAx#aFlGBBRm@#wJ+y02| zY#mC!+||G(vi60rmvz$R`*O;O$XT}bwkq*`R2hNL)pq7`?txrp$d!vKT^CmO>>!X6$$J;7R{@!Y%F>T-aS838p{44#qSYN(-6TP1Ez03> zlhUA_dxz879)_mgWB86&XS84G`k<$gSRNom&xcg1nWy1I2}(jcb5Q`{OACG({k){^ zs4~*?J;keMw|4}O@x%*6WR!0PnL#JmWpJ?cTpR8jVdg5|x!Ep(u1Mh+%XI#8B5ya} z^DU1qmXZXo#C8}_(IUrF^Oz^F{Bg6hqt~hCV2&UkO0nc?DEq}UgF=>mSb;jf4pxiQp5R{W<$Mz75^)fOLC?h;bPJ}t^TXo^qwIw zl2^eFS(&BP<6p*Y!A1hpn{3QSo2?h%=CX~>hm;;O_+V!5_2O?&B2yoU zN2C9Fx&?B@v+RitiI`4~>$|cIrepV}e{#A#9Bg)6(wlj?6C7JSo;&1!mY;f+2Li|b E17U~S%>V!Z literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-calm.gif b/images/mood/threnody/mice/m-calm.gif new file mode 100644 index 0000000000000000000000000000000000000000..ec401b91bc9679d21ced0d4f37323a47578f694e GIT binary patch literal 1556 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 literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-curious.gif b/images/mood/threnody/mice/m-curious.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef82bb38eadf2c129f832a0e75176e82fda18885 GIT binary patch literal 1822 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 bL?yX``&e(dz8kMZKK<*-NmOeg6TJH`*unH) literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-devious.gif b/images/mood/threnody/mice/m-devious.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ab1525c25a95a6f46d0883a62be54eebaa8489f GIT binary patch literal 1343 zcmd7Pk5f_y0KoD09?Fj=JP^>SX+6L!37wL0rPCogb@oFer{h=1zwzlc%>B-4Sg+k$Q zI1C0uM@L6E}Ua$B0^XH3;i_7+9u~;k+2)rKe%*+gz%Y|Xs)L}wkM5R#GR@aI|A_PIA zqM~ABW5dG2_hlECzG}!LaAFxq|-^OP}U%uO$*|*Q>p%cMy`&E zTAf{-RIh{7sXq{p?AAc2u#SsL3M*+0pb(5GO#nd*4vz7QMrmkU+Hqeo^VR}8FmivK z_tlHXarUD@{P|=SAbD`?3F$ z6?$5_;GVnH9aK0K00@Cz?ONX|G4W-P9265J@ndq^`G@cdzLF`7E_R+4(AQadx?87z zQoBd{S-8gSq=#)0_^-}hL?TwMf~wN9pAF z&B~-of?;TbMz;~HMDbmiCH(ro4Dy<$3drxBJ$aZ^SlEuzm~k`!dNFZDq5zKNDgw>A ziuAgpa2q$Mx5&i+) zLWJrOfHt>x;J!OL`Zgxr4exEZfzCrchpM%!q#F1`LS`+0b3-e zSF_(-at)FE%wjo&oqPA~J14}uG2}>LXzu{>=z=dpy zoPaZj%}?OaJlDGN<3A!#Hs-2Yc=P1JvBjxUhvXde2F;<+C{c*o@ zqXqtLdup+<=mNHO%a3PoD4K-zcptL%_Ez!U@~2lPq$8Z0kI!(|<2BJL8I=>)!~Z3x zT%MZA*5T=jUrN7m05Adb+7 zQh;DB;B-2zR_nsTg4gR^TU)c+?Rvf5=kslBY?w?YgTbIytNnie&d$#A^77*1;_U3~ z^z`)j__$K3bi3U;o$mPfSfNk^0s)Oi)85`bG&I!N+1c3G7>PuDR$s&&iL6EBa(Or$ zwwkOagQ>N(RU{IHonao2*VWZkQ&Uq>QQ=?q`xbq5b#*~|u)e$5^`~iEQt*x!8 zsmZ@|5yN=g*%is_;0qobo>Fvw=J zAqYA-IYA&0EEWrf;i{@C8jThg7bg%13JVK~MB?e`De!;C{0EHs6X-_TjG38@hGPwCV;m6? z9SuFE;Ns0n{272W2SXG}Yy#~O0sLXnO-W3|(UZ*hH&C<53??HsG2t2OHX#Kum->Ri zNDI-~=~@CBAd{J|A{lYw`3V7e7MOGW`)5(9Y9LnIkk)VH8ZMGEYPV&~7JkpWIh?u< z$?um^KorYyttB7q!?BAIBW&}-cgS2>gMiPhSpXqU#?oh!DfMJ6J%()LLtCGoZD2Zt z(%Nn`g3S}~Uu5>v3Xk6Ax9ma^x{hAFR05kbG1${oRP{^#{v~P>T$BIg(fkViW(X23 zRrVmhZ$)~Z?iIO+iCMQWy5>W+(lHR?jEv!X0-l@c*)dx^svDey$?N8yk>}*G+o@7R zj&WM+<#plR(zYn_VCk;t)+kds{2@h`V>V_XhB4V3;XJnr^ILpb2dQASr&mN2YDOH= z{q^Y7a*wRo2~br)g(vy_<6VpzC=>r8AAP=wqn>Z6E+eoTnn36bcMF8@+-@&Y#=MaX zRRU5&RAz?-f#XdnFt{w6MM)h#*S$&t=?+&jG;eWHuD-gv`o(4b79Wu$WTHrKwY)bF z!~5HD7m2O@1Ph4M{s^27s+)n;QOfSa2V8Zv)RXDMkhgVtb&OJ|&^EIw$rtV+$5enN z=A*~i7GR=s>1!u09&@c1lQ%iQW}?UmA3z*%c^^gl*x^JW5Bi?p{~Q*;pu3zK?7mk+ z>m>~6g2Fy6tc(Sp-jnrWSa<48gu)qy5v$P$_YBeE8S#b0;yo9<6gY5^@B4#7_@Ye{ zl-o8tiC<<4M+FK%&u>NNTNtY0uPTh5^C9u(2wc@6o%{B?Czh9_D;*{4;7^lh)2GZz z+~GI-`pR{%&5jKXf(PhBSk96x*p&VJ`N6+(_u9}^!qwgtfJ!OrMqQP(qVp^x%3Kn@ wNZe1I&^VfxQVy;htUz^PMerBb0#xUjIW zy1J@RC^#IB^B-qPNlA8gw(h2GVqikA*0b4ceUIKb>dei}WwBWHyLPcy%;WJ=Qc^~G zM_yZAr>Cb!MMcf_&L$)zIE;>6yLPqKw(|M>J6G-$oh{NU^lQs&|B;L3(b3Tkhhu4J zX>oATBsYbIhB|+CYD=_L#Z^y7pCS;5;NW2486lBK?7rOH(b{p5cd?vPE<7O|;f*}m z^JG41-kM@0L5$sqDT~tfex@g^0z|=f>e$sEUC8A|O zKAp9Rgn>`2hWW`u+)k*%0x?l8Q=cRW$%2kkwTXgaQy~Ox-m;wjRKtk@#jp ziwoF}B;sA0D+vVXX5$SEsk=&zy`sesF?iUmN9<1U0B;yE7*7)HC3W`(9z68)#E<*< z_PBev$cUT#$g^|bQ!3N|QtKbE>_?j4Oucp+CEK$6Hej6Q_JbJC%bw$Y5sjrWWYlws z)DCy_n;O{8@OeYgxRY-LMU6f0^Zhxr5`Z%`Knkjc$&!0FFZeWZ`6ZsV-`2{ z#Fj&-WWPe#jywRwkfGYHofa(O>pe{oTwn&&P$CBfX{wW=MB`e!?%U3$q0BZYb?OZu ztw7lpl2WtqeZ?=&bgU8~NkdRa z{w8zM`OPv%VTXS1@;A%x*uC^vaeD5|z5xYH<=2sFKgXsk>6~GI@4)%I@1jJfPC|4S zABGJLwkYrRPwc?5_G95wZ%;n6p#jcJNS6Wz!2)Riv$elc%ZCeD3`SB$jkTRb*qi@u zKE}2#NOO6ieO~68A!QO76;cov0^}s1+~NSFiz^gvLF`Qu43))DR-Oj~N&O;-;-pfL z+qt4v{Nu>H5u8_rm4i~-`s`&GI#&|@cP&>05a~lIxG7DEzz0q%B^#~`TKc_)-7+N( zAXKkNuvky-5GKf}oJJn0OAsOAReiZ(6~GEU6?gT-cx_O6*ci&?f(MvMS7%|7a-b$D z2w%7^L6|aL0BMZCX6+3Lz`P6|Ff!vJ#sw2WMKl33!!4dtZdS_-^-RE@T3_LQD6D=0 zwf)sWiz>7nj`c{{Z-+cTk-j~ONJ|Juc_n7J<*0|f$IO`6qvufGnRz*y-kUgBa_7@P z^L=E*DRMR{Bo2=A$>P>m`p{*X-=aPff$_ei5CMqWHXOS1N=+Si*f+N^$9jE2QH1u% zYb*fqhsCK#0@D`B$~)clrSy8TboAKSxz`2dSMm9MlW6oC#yb$bO|%lAznfLy&*}*% z))EMhkC?S^1APQF8!lNziJg4{l$T(L+7Lln7>fI&)7bxDXl- zI?Gf(l#In}4fM0mWei|e>y!4}{))V<%Xe|mSCnL_-_cS!NTzlHXN`eIA_9NzQ7H~D TLUNYnheluhX|IG3z(@ZAXzM5s literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-energetic.gif b/images/mood/threnody/mice/m-energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ff4352eebfa020c62e70003190ef962efb48905 GIT binary patch literal 1907 zcmcK1`!`z&0>JT`ryH)gA%aM_VQP(bH1!shMyRHCOQV?9cCw^Bsj*Yr(xXOOO(Np$ zkSdy0B_31Os>zsCjXGS9Vmz{HoG!zp*{Q1CI!1}{-km>UKmWk@hwrJ=;Q@h(9DoBX zih!Y^ArwWsy1KMlZBtXz)YR0(#Kh?6Xj@yGMx#-y)iX0Qv$L~3Jv};|uBD|#sZ=g3 zEY#H0R8&;R`OUo}8Q< z5fQPnva*J*?T_y75A9F1O-Lk?8Qn~DbaaKPB0N0YXf&FJOeWMcq#e@MXhk9shr==U z7+=xUXhsz<8$#goMMx&*qridkC ziAdt)fI4it4tjVQ77DP<*-|*HpRJGOuC7>5ju%#_W&Q3qLv7QkhO)Gn~o&`UQvg2+VSE)o2CNX>q6` z-^P7i23Ml`Z_`XM)$BYCp8)Q1S^u*dtcy>3Y?B##}e`8 zcAV1hI}$>GxMSoJYBHZlFyHe_@mPK7aQcCdRs3*ZHgOV12B%^A#=HDxmf?b}&j{w2 zW7IQMH-+C1F|rS6zDesy9|mW+oX+G3lk&2hQbBXxhzkGU;#Tq!yFO$x5@T=4u4c(f zp6Bl+!(a2;?Jz~Dr_cUAQ=E(IK_+82r1#|zjqO^~88AqmB;%`M{r~Dd0(!QE%mgQB zpOX;JRl)b&*?CT`w?V!Em{v@ApVuIYo+}X02Mni~t7|>)i58 zLHYv{kZl&gDATZ*7ui1$>=b&1O%$8g2%q)gVDm~V#1Q~AHk?#{7F^<4{D<_6Pt9_h z$_AO`$t@rh)+>Xp6V%PVo_K@Q;~O#}gY7z#6EQYL$RP1B{N(^u-P+y<4W}TOPblrn z%UB9ywU-*>lR1E^xZEpkcQkb#T=pHLA#F2^Ab^&J2uL}!EHVhurVAvajq4E-Q zVCcABRO#-OSA+!qZ0P^&F`}1Z?A)cJ-XHwv#YE!zM^_JQT%dRV>{T+Z@jNC3`V#h5 z7(@u7!`q);b-Xe13#-gmQ^%>40;uf=aiTZKZ0&xP=GeWdWmz_e?Q?C9gvkgWJnu|H zS3fV!Nej+^3AaP7RC6Bl8J92-cXLYl)Q=VOGvw%?7Yoo~19ELfPJKEW94)EUff;Wf zZW05IG^PI#L?t~%UZvERl>f9|ij{+=+RlH4)^ugaKid!N#Q*(G^i%HP48s=j(Jg&C zIXSAQk1Q+->a-&%#v%*t4Dd+{*XafMTyS~8QyM>0kF~5rjXV|(^1{r&|0sBo80Hf- zKs~iPwm{?8^who)K~KJA4gTc>h|halzk48L@%|B3Ck*W)-0F7SX}0R8Y3}@}7(1G` zCt`eFwq}24K8dDW=GD7>`rNhyG5f_;wAb~PK$J|%M4bRW-LI*!u0crG_fl&0IV0o1 zdDq8id)}cFW)qW&+$AZY1Vx|JJrRaU69zgu;D8T@MlR=$r|^rDoLrn8 zz(xOGbMG~@B7|4#O{^OuYl%Dk6F Szj1fx<&}sloID-?1pOEKVFo7v literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-enthralled.gif b/images/mood/threnody/mice/m-enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..293608500d44677dedca72448013a8f1c32c1262 GIT binary patch literal 1320 zcmcK1{Zo<$0KoAFQ9$052atS6R5CL{bey{KK*=SgBfGffd5Y9nxn|BBb<_}15Xm`b zhRPg=RA|JQJuNEE+yj_rwlU^9>RfZi?U?7?w7jjAHr(|`?E4RVe)zsqURF?8&jvDq zP#rKiIq7n_APBNrt#fm8v$M0))6+Ja&1f_R0s)`T=X5#^2E)R_!ug zudh!oms>2Bo}QkywKc6)8w>_zGFdnr*6a03rLwxZ`o)VEHjB*%`J7f~b8~Z5RTX4~ z!n5J4U0YiVnIMHi(a_MKSL?-MaZyo`%i)qrr9z=FG#TP@xk`o7 zX0SCjHkOr@%?IWKjsRqY!gJyE_4QyNC~uaB*TO3+E1^(md3l+|Vp)yW=Emmi>}-e8 z5fKqlTwLt4`GjRcr_t#!IEX|dhr^M|q#y`ZR#tM0xCsdfDJdyTCQ~6-Fc=J3LqnOc zjKyJXZf*kqb7`+45lhHAAm@$q<_Un_RMn~5J2cu(9e{{H>N+E%P(TD4(=$*PjqStr z;|B>uYzzVyizb2OLCwge^Jp{$L%pUY5aMFGDJ0ByAkAqfY{5=UV(=i97Jn-NKqK#x z9(6)0O{6i>J4WUnW@Iumw}xm*@mT{z;%~@p&o-I9tApcGkvbA( zJ)onlrsAkOYQ|1oj!yD|K*iW1J!qou#bt@$nepGx>)29yl^KA6c&0Gi{z&S^=4IXd=J5cZD#4DPOJfzkE+OjPU8x*vYrjs(uU-_;%4c3qpw z125qF(yo|~&*po{mU;{cFVGj5xvyv_LW*ui{ME&yT53@@M$c>GYtnB%J>L7-dOoV5 zzctq{K_Hj^h+!FcoFjtn3^j|LH=2=tgpqH^*+w)EtgVu#c79Q@DAmR%4{mX@bY9Iy zwz2>X;)Z29UbJ7eK29i>ENOHPg;@v#gvn0BQ z5s62-kUw4@=xxP_ZXi0L-HYnJeZ@0+D)(`dn~BKcWvWo3CQa+Uzp4-jU;VhM;!w_g zeOe5K-F2AC^Cu4P%empkQ}w-GtZ?Q2)@^F$z%1(I`Yksq+YVf`uojt`OPWYvC};Ae zI0hXqFAz}~-x^Ctx2uJF>$_iD@S3kfwhuoUmidRyK}3!USj^hW7fdp**@?rJf>M(! zYGWt|Uvm)A&xZYcXL2{(f%|5?s9nEbxDgeFJe=;9Cz@4iV*b>5H7T!SV*z`Joo2m* z@7MoONNbTy!R3;XW4H6{Y>$42a67+npw_I$cCgxln!AMgUO`-lXz`$^{`6eiMb>lc z?d>hStJBG3X{s{uV>5C%>)Ni9aY?s!=`a*$Qz@>RcV*#hw72Op>Ae#pd1=Y2FOlG# z5PT2JdlLAF_UP$EOWL6p(M{-J#*-a{tYh}S16niBd*Oh11c}W(^IYORMgzUSp8ka% Q<^JH&pZ{dG0l?e;0rd3~X8-^I literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-envious.gif b/images/mood/threnody/mice/m-envious.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2b8149aa1f7c4c8dbbc53881233c2cbe24b2058 GIT binary patch literal 1854 zcmeH`?@v?r0*6n(Z4d3S91lk*SV}F2QoSAP&N|1Svf36_pqF*fn2N|c3XEYlE8xaR znb_ZT)pbBvMZzT%CTq~E6%AozV}*5in^- z6V&*1YPo(rG1F%@jbGlZNPHfXkM%tUmFq+a2?m% z(Jp}K0jvf3mhMJtCrU3x{n5Qk)WR4k84XpMRz#1SM6R%N^ryos7 z26$W_3@d8xgJYu&cVMJYDqzMOS&dk~sChO>4RDgEHA;RXyh=OAg<%o-Y9K1WE z49e`4xJchvx%x0_Ps$ur|2$mx63i{zn|BB!RBl8%B{`C~!Bi!alIWBz;k?F$4fFG) zGd9ml6R?_9Q(t+xY@#vTO7}*Xh5Vv;Yvi8p>&>#ei5uO@^3&e?X7X6j`{5QP1Bb}; zi0RAG;-nOri#11VlGJwW?+<(am0uJli8$ojKp-FHzxVhECMxest(FBxp$+_!YAk#D zUDHNMKeoOzOg7*DF_62xAU@2dZ-wLv6)Dt!ZB>J1`&Kg#9mOuZY=0j@>q^1l;L~r| z=$xTk+k33as@Kx027ipu(CXCz_zP1DbEE$&TZEo7)pFw1FS2Ym_DC+Ls`uzjmG+9X z3)M8P>*sIh(()REZsoyGyVZX8A@V;oE^%AQN{=o%D$>P;%EO*>Ep%)z>%Rc5-G)UD zoc&JO;C$W?S5;8UfP`^YB_G&YD@8CG%(~aP4@u_(i{7N zq0Mh>_h~kI_dRe97JRJg=55}#=mdq@uqR^}k!w<6Ta^>f8idRt`$Q{^y}x?>w&vu4 z)F|LfLO}=eT%%CMKjq85m~rqzf{{fN{ZW!NyWHw!C=#f3%;eg#xAtg?;BdlLO4DsmM3YW|;oeXM#Yg0x;ETKB5R!8@0)!oJuePXG*YT^HnJ2> z>e#`WWh9q8>3FD2&Py!|iaK(gp%bqQ=P}7$vN*H+))n_RI~(+)%%=~&<>b}gH!;2! zbl6-x-9?`(WpCr2Uu_)bJI#oivk<$wpF_Nm?Pd`rr*mFeKj+SVvth!L#_sEPfHILk ziWQ3#(NxRbte=vtiNu3t{##*v%|H6W0P{9xTe;pRJyFhc;fNY9s<`4lY5$~K`E?e5 zW)4YtJJ|WnfzO0djF4BQq9q_2GcqG~Au_mK8v z2ML!)R4m`p59?6XGz|}Tb~e+`>>}CP%CpJ7kSiDJVG85yu4_A3LdyfX;9T9toy~lq zk#z5DHrbAsWvg3AciycVOzXTOC39@}tTnmPE1h-XA1yI8AJ1a@LYweUemif2pdJ4M D817$J literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-gloomy.gif b/images/mood/threnody/mice/m-gloomy.gif new file mode 100644 index 0000000000000000000000000000000000000000..4093127f927cdf997dd0464eabe23ff3bd6e40b2 GIT binary patch literal 1603 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 literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-horny.gif b/images/mood/threnody/mice/m-horny.gif new file mode 100644 index 0000000000000000000000000000000000000000..da3baf29abf49f9af957f3ee046ea98772daf2a5 GIT binary patch literal 1353 zcmb`^|5K880KoCb50AhA@qxf^P=PixHBxj~w)q9g%%$^7*IK2g?jp5vM4g#)4ju*M z(UD;_kDTYX)Pb2fD_34a6wawRvPI3zGjgt|oO9~6cEPUyVedcS^~-zbuEed|a>Jk? zXkH900bm254S+rXOaNFcmVtqR>({UA_4-wTV0?VMySuxwvC(F;O-@dlOs3x6UZqm` z5`Z}XCM=fr_I904H$6SA)oP`Fel0C68jYsByxeZLzj^cK!i5Xd02~J33jhiW3mp!J z6@W4TuIaBiN1bmiZ^ydFFbqRcR4SEbWo0caEa)5cg?Lh4US3R0jJeyKO(NOZYNd*3X|e<F32_tJZq2!{4J&ywa_2IM0IGjP?;?lWk!$}ocm#J}!m!4EX>yTsk6!``< zxe=i>^g>aR9C~t4*XS*8H?+Wu6PkPcesCR)r>l=�FKC;O{zD7hx>#Hf5Th)-#qoN*tiK{+YkdXCJz`PIK+Z0zr+nR}=c$Lp~s&-SRJ5_TU}_s1+ZUvgv+ zpnpzOZ{Na+R8cq?T^H3d`79|!s5sL$I87F}f*g@1H*;cp5IP~I^PFPM ze&m6X;P7oS9;fEVHJ>;jxr?6g7?%wd@kDoFuPlb$>=`rsI)T2c>`A;LR?-~swRdfX z5r^z4k!ubj9WrVV2*1J})w2V0zZ@pJq?zeT zb30Ees~u(@$rFy?VzG`v0;@_j*mkh$2bA*3o&0?rjijZxkdBhf?CreWe(^~;4flog zrsqgv7usW1N45LH%|0S2luJ(NTMWTcIF3zlDK~S55T5+v)eXKV{&V`aIVcew)};@A z`%`5??U#IG$j|^W^+h9j@v|4-A8NJX5*aygsDu$w10DU5FKezqpXLWV|jEb6eqTHu|*I970ZCAs^WI zdijA^mK*lXq-M3L}g<+6k*7Kxmn( QW9et7&K@pL;y~N~1LtcP*8l(j literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-hot.gif b/images/mood/threnody/mice/m-hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..290133ef2c86c4d37711193e700488919a2c7bcd GIT binary patch literal 1657 zcmV-<28Q`ZNk%w1VKe|R0OorD%6ogtadFCMXv&zF%8ri8goMXpV!~WpwNOyXs;azI zRjEWo>cj%drKPV)NufJCwqjn~t`Pm!72~}Em^3uWyu8-BBK_0^^4d7c$;pHuAj-6~ zj3_An{b2RX0`$}x!KS8@EiHW*82<53br2B!=s^D9C;sR){_sS=jRWGn8Sc6==B`@i zyl(E!LBN!Nx^`-3XJ-Ne0%=@aZwU!#0|N>Q3RwaIa$;f*3=EEUcZ@MFjy5vHqynN+ z7C{06o?1r!=|}$lc>ey>{{D&n-W>k@%;dcd{`W`z-W2`)u>R&6*|h@v^jq%A0{-qR z=+tVCI1c{)nBKYq=)@AjqYVE0Qqivi(wZvt%MShh!s*<8{@Vur@HhVbfd2m6=i7)* z9URN40{;HE{^AU}j%Gd=7PfvOa~K7HE+i`s4&=x#{^%&KVg~HiV)5gO+{k3gqH6N( zvcjho`0}XIu9|xu2a-xW_32Xn{%+#VT>t<7000000000000000A^8LW=mUEIEC2ui z05kwF000O7fO~?2goTEOh=TZIumIen04vAEV zqNI(c3Jwd12@MIA2A{A92!|F$Duo-h1B|(+rwRxQ4~8296#%)W$qLE~6oqS97!nbL z2^j^RpVhp}4;NWc>AqE7D)AgCKLZQc+U0Wdn1wrSxPi(puK zctF_$p^Y0*ps<6cfJU7w8_bX)MuiGx0l;_&0fOHQHe^&7oOUz^m3ssTutuOVYZ=IA z+~N#N!Exj=HblG|iNZ|aiLDuow7miA8PH|aI#!J}i0}y#kSuBacMU<-<_!qlU_*wX z&~1nUZ~y`_=fj|vKyeZw5CR7x&~U>b^VB0$1{I`-gA6&OcS|yz0T5w&I_NMAVIeSO z9b`1nK*$3N)FTT52Mv(H1|M3OUI7FUV?Y5J$e7+R1B9T!h#Y7@LJcMoLP1{4Fmq4; z1F!9=bt2oRnExhODa0Tc*XB9T>KvWE{P(m=pZmsWX;G(UtV z!vO{;@PLKIu=N`aKm_rTq;i+R9>T9M}rB$2;1riQVM`fXR*{1UJWW9nHRJ{mKdzHDoCJ&WT^e85HrYW zkmLgzj7uhhG}K_iKf+4T0TXaGXU(|Kk_jyd_mrt+4K*~es-#&w0mTHuCB`lP1S4{( zvBnx4Nv3r|))0jUCw#!F1X4`FzyX}a$BPCW#0;~{2_~#DzBRZY0Tmz2fk_rtTrtHF zSWMI3JoJzt!qQCVn=p_e*N_DR9yt8S8bxR^L={&s@t-vb)x!b94Bt?2#yHo&z!X~y zVZthicyK`%UJUUC7!J6c&@!?Z6^6amwRb1OVtio)5hYw;@*`ASP(%k>eBr=3^z>~M zyfQq^rOaP4tVIVVT)=>}S6o0w5M`)H(dF=(fn1pfYME~hD3Ec%H`Wr8MF}Xfe)$8h zQ-Iv&K_~xo$pyGz0w@A;4^&_RA|xOL z@acgFNr0arjxf3_K4Jo7AOaYqK!yRDQF$sT!Wfp2yf;$N2`6}%9SLZ~J^HbGfdBwI D&5Ol8 literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-hungry.gif b/images/mood/threnody/mice/m-hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee76ff33a146b0a740b3afb9cb14b41a1dc6cd1a GIT binary patch literal 1343 zcmb8s>sOKo0Dy6PML<(70w!Kk%t*rvsZ-L;z$;>PjLZATZYLFs>%e4hOt{$z0U{8Pc*6s=7lL1WN6U9wTj`84gV>-G5Sk=Mc> zKE~&M+TV!79jK{ZeE(0t@C~545V%?j7@h#F6~NEcz|C4@{X*XDiMtjvqh%zVH2+GiO3WLz9z}RZXhEz(94qT9_-G(ayA$ zw%xjP3k1Q{)zyKHfhutoXaoTOh>MH!^YaS}3nP=s50nqmlGE0P*R(gZ!NI{zHBBTE z2?m3iOeVRlJ@%oHDKY_qa=S~z9io}wl;*!!Lh#6omt&mHg7BD!%vevTl zO0m@@Yik>5b2CzjMAlzHp)nX+EUpuev}@n2szllo92}jTw>UeyI6Alz@5P z+qRLmxo?GUACY@_LUxdC+SFfQr!q5L-|A0>c{_9pR+B40I z8k`VY7semZ_y+(Vo1c zb7cjT6cEjuWw^W3{+>ZHuZm~5UEDkyvyM13hVxu9#5_h%moFTX5 zwyM&DDPx#P5eRu{s_FV3&sY&c;dT(Z@GKv@c=%R?h7;3y5ne_X&Vd=c*&Fdx>r1tY z@2X32WHxm975zE9&oOi+cteV}s&ZomO;Q&AJoeJ-;yQCyH#$`AO64qOD^n2yYG9!4 zUW3D8wPI6xj@R#s$Md62S57686^%nKO(xdb%$yWC=aWgXQ5J^Oym|UYl9=W0TUNST zIA0$UX`Qp%iNNryh{Z7>sX-1oG$<8j%TU3_GNxjvuaVEb zIwZoU)e#?MgjkMF98Pwpi$yr&g)!6|v4LnCe2qShOJ~yu32s(O5jxC+9&uQZOD9SL zY$G)$RMeJTL~-}tn}bDr+D98*S@xJ342PeONAG1ZxKXrJes~R!H6G;<>($Vxkl=Rq zqvJ-pp%|LAM@tgz?4j`RAc%q#7uUYOAH$E&lsFbUWs2|#PB%ASzsd~xF6t7Bf0Dw!=|W1E)L>5u=VTFNZI#PUPFt`u z&aFiWR+Q^Bdc>ibK)Y)=v$8#Ygap{xr|5Y5*I(e{HJ;puq5ci6j-2TOOLfPR9E9zI(Pa!*NXUOg5=|@s literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-indescribable.gif b/images/mood/threnody/mice/m-indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..20ec18795a65e5070640bd4be9cb55ecb7004b07 GIT binary patch literal 1330 zcmd7Pi&N4E0KoAdKahv=5{X37@laAyLamOhbNCqZwdSekR_%-&XP2c{X2z_HhvKUd z;iipk3bZ(-=Fl4FQ4wH~+NMZ5qHc$a+mX46M9r*iuR|ecvzPb9Wrb0+@im z3b5PlX0v%>V#4Ke&CSg@91e@cVltV=#>R$*hTLwq!C=tobOQqeUa$A@u#B$YQY!y@u@U z?6%f6EEY>35VmjMo{*40B9Z8HdUA3ylgW%kBEbJ3+G`kO30ehYytTZ20w5ydDygia zQ{L5G1wg=_E+{MtjzFRmifE+@5rf7IVsRHBUwn(f56ZQ%00N95pyP-ex=GPE_z&ot zC=7Aqs1&P(euGBM#NCc38xr8gY1I8hA_bph$0oxGK2+q$j_zH9G1Q_$$Nned(<0lZP}w z8T`Xj-Vx3d8?=~Dwy6a^*@K}~R?8AMRm>LdiOlDvk)Dlgh8YP*IM40$l8Z@4g~2p2 z;m6x&kBfque8}cX(Pi3$aSu3ik#Y1VkFC(@fp>3V=Pg|7!o?WtXkT+|U5KR1XI`#L zTJM}A@uW!KwgWQ!x#*39Cf={0r1lqPagZYvJwp_c6lpH$wLp5J;n>KEwyV>{w{Kp$ zYnI4^TT5~88kI$T=&e!;Sty0_kg5MDj;j3}Al z=`7#mrp$s-i2`0#b=m|l`d!ERy1Sw6D}h~WP**@I8nlzLm2M3pH^CQ`m}9 t@?SGNr$DwK9Bf41e9`MP#q0{s2>Y88RsKazkbLL2)2|x2bO`|L{14w*3p)S+ literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-loved.gif b/images/mood/threnody/mice/m-loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..1fea73ac5ed2b078796442b57129f61dd1f70915 GIT binary patch literal 1421 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 literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-nerdy.gif b/images/mood/threnody/mice/m-nerdy.gif new file mode 100644 index 0000000000000000000000000000000000000000..27b8d6ed32341260cb9fc95522029dacc09668da GIT binary patch literal 1620 zcmaKp`&*KS0)W2@-v^?^MKsDpFzYZwGxD~HMdT1K8M;g67DMg$G~8Ue@RT#24-hoP zM7z=2h|K6>kC6lCr5t?WWnv5^PJns6$``=1W~Efylr_^B~=^_r?IS2sZ@%^ z;>fj;e!u_ugXcD_t;5jq^7hM;yb^3b78@HI9UZ-KT zw)FajeDVUhKp-HK$%%=HEEWqz(c1iMe`|#{Px9v@g)Nn32Kif6nZk2=O#5zT;g-m& zZnv(hE4H(9t<$NIzq6o~C-n3jb~>*avD3Z1C0$)_badq4c;f$Z;rJn+uOG*+*=z+q z-)H0F2DQ3O7?aT18T$08q56oXXwT7#vOFGpZwz~7Wd-=ZaQ{gFU%)DW|GV}36M(pa zskFKpy`i>F2Y?WKtd>APP$QAlWDaOPVT6g~vw>?G3dV5XrxWT5A}ySIZvU8=y!@#?n?K9-w>H%VRX94rJ)esoch#-xpj2%Y+CD?SxcIh z&C2HF;vR7kG3T&pso5%R;Sn+_l4WUGCWc~Lq^o>`^gKInnos{K2LyU@s&5_JJ@6)z z5}6?YtS2|@-Xw(n!E5%wtt#O0sB_fz;1s{$%F(#&(Oijbh1M<0T0Oao5z6y0Wv5>5 zrbplJ$LKphuDN<}mr9nUO_MnV>H_mUjpR$P(e$51*~Nj>Fzd&r1G%jyFTYRZJ4Cd9 z;S_3e!F1fFa>=n(Yf`ymH}BtBHNqC@FaRWILoch`$}R415mI3NALdf1Y&7)^_yy3-pD*wqgE4$Be*vkUA?b>Tbf{-$DbW)Z>%v=OoWA-nu98DkJS=S;_l zn}H;p6mFi`9B*JI+{5A514Qo3Rti^ag==uBZJqe!nTzqt}SfPEqeOdH1H`K&&Kdbxf(&=-#V?g(m zE-ViZS{8iRgBW+_+b#r)**)BF``x972hSYCCpV-1Ba!jfzbHSePLW5ASZ*AblDJ+4 zL^)pCFf-8w7b_VVi?Zbg_m4jlB6o|LtD|$JTaXaF=vi9GNO6&#LI|3w`Q`gPfcPf7 zXa9K;6O4M4%Cr{lX!>O)0z$yO2by1k=tt$-SHB7yMM609;?5u%c&*wEoacS8f`Ulg z1ZQs{Z71Pd6JK!a6OGO)Mi`i0VAf!0GQ76s6uL2N6xp^Wk z!(bNE@DS!$LUuQi)dad9B P_&x@OcOS+@0Fd%uu9l>) literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-okay.gif b/images/mood/threnody/mice/m-okay.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d6a2f81f702d5549e62e64e95c91c583ccff78d GIT binary patch literal 1306 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 QyUUVZ?s0c2Xb|wmf7vh|rT_o{ literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-scared.gif b/images/mood/threnody/mice/m-scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..86b63405f0a083a1fce67dc8c6020996246a3239 GIT binary patch literal 1326 zcmZ|M?^BWo0KoBwp9%;f3L=sLLo*{IDogB`f`WmPk>{LqiLB|(qYhcensXkapy5eM zJLYl8ly=nE!P%3M(T>AMr90Yr4DUG4b)0FV<#tYa;mX@|*B`L&>(9HdCb!EEb1c zA%#MbNF;ndUlPLsLUR zK|x+#o~ljNrR&) z787*@3q#{bS(Xfm6%9{GNy8Jz`uPOZPzs5ZnKfzRlTi**T3Tvq7KP){@u@#ONXvxq zIXT7*GH{PZ%cUQ{<0;vsG3t}Nyn_rTgY_OeCqKJC9d$SNP+{TW!lEPd6=UgGT=Vji z_G1e;)ko+Go+gM2WWA}IA35HK!Z$w#s9PF1tD^gqdP@I7H1hpDl`DSIg`0G`23akgFMgi~3#X08{git;*>} z7J8PEN=dd;GuKjbXs1xrrkpZ*#!ch}C9xNgj{KsM*fQ2@>^^3KwJmpx`r zuZq4s{d{$S^p`>=!j%S@Cj9COGl+bt!q#H`H8UliEkaGzkTE}B{q*P?;jI?T$)7t> zTh z$zy_Go$x^ZW#+(r2Yj@O@bE_KuSwnf2@05MGnS2f3JFwaG>lzLt7oB literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-shocked.gif b/images/mood/threnody/mice/m-shocked.gif new file mode 100644 index 0000000000000000000000000000000000000000..bd5bb030a48ac07a44d4a6601dc8db9ffe9da39c GIT binary patch literal 1242 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 YXv?=K(&W*f+dHyY@1ngcV6Ywk0!GV+@c;k- literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-tired.gif b/images/mood/threnody/mice/m-tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..a45f65f5a107aac9188ef46f4156c456ad72d465 GIT binary patch literal 1213 zcmb7>|4)*60LLFbd=Vt&LG!yQAexdn@zN`=xgaC8Rm!Y0?K*Kc=GnzLb5v~S@ZqbF zW@czyQ9c?O5tpuU9dS-cnbFNFy0NSCoMkbO8h6shO>+-df5N?gdhfNpe|f$4RtmQ7 z5EVjMkY55}7zl^K%a_380dsR87zCjZKv5u-fjlrBKcAbMbGzLRhr?_(8w`eyjt;NaYq3~NCR1Nu-@?Lz z-|x5CY$%EvjmDmyp0>8OP$(pm$pV3ZPNzF?-~fhUZkyX~wj&7A($W$RhcP#Xc`&tF zeeBq=uq#|uRb{u>(H>MR7MGTmN+goQhYx!^9;sB?)YQc1^Ia~N-EKFd<_=kh&*wu8 zsND`izK}p5aJfKWAy8jmADjpl6ck9r5)OysFgXDDAmQcO+L}-(EGjDM>jO3$Xpyw| zyuOl>5`zKM*C%4wMvq4zZV|iPU~LVsSS%8Wl#`PqX_J(dl|>>E=>LbgO294SB~bpy z>Bmo?sEAyGD3mI-M%$&6KoAb#2}B}EZx}cWMUj#2ZU88Q!>VZNhAU7E*&0iOsUsuM zC_<0xiYJU4pv%a{SbajgvkL+W=-xo$a8hy?PMM-fO-tXDoRP^GNM$}tW@WKe7EhEa zJ3D97=8W8|JkAzE!iPoA|@Uug3QZ+$U zIlc#GA{Lzdko<8kb!E`)DA#$FCEw|u?k5qVB80c?CkYR=?1oDm z%8-a+A6xQpYra3VCq^S_;+}lUp4!G{31?^Z4;~WP6$PzwDZkuFPc2CQ3F>d{%{3Xzv4BxfNEX@LRc_lz74-1!}%LMcMXx z^&KEH;I1z}myvKoSDn@za@^+re{q!Z)5|wCLTh7POzF<^SGel-l3&fj<;B1)el@*3 zrg)v9q~`*q1`5tg=ANc(6-If^7kIdc#umMLV zfFQ`w(2&7ku-oku6B8DTMW@qsbaYHjO^uI_kBp4e*4EC>&i3{7b#-;AR4Tb#Znav6 zhljOVtwN!A`0(N4;$nMydwF?zOG`^hNl9a4V?{+pW@hH{^77=+^p-wnh&{qd{6Q0rYXJfbPurK`)4Z6PcQc(0pvcMHH4PHtnZHEP_ z=rUYvvF75e1UmZSwJGkhO+<)=uI<<(<7lJlOBvx}O_sc_aXt51_cM$@hV6F+#dMoQ zq$D?1(@BQOSWWhfAskIh(LflGGS)Ok8?7gJVGBTGj|>od)3e$(oQ$ujBNGC;Z-;Bi z)PSP;mfo?+0W`R3oAt5&E>il*leim+!cdAoKYU#5GX6;Mk5(+=JGDwpIyJ)fs_r}w z%&l7H_5Ou^dYrP(@7r`^yvg?RxA19D(Z#y!I!iCI8>#6q+XgLZI;}+EHrm1h(mb+kF z1)1I9=XNB*s9a|1-}3!ov|Z9%mEXXE92;(1h$BS;+#n`l>B$sm|NQj>BJp4`Ld@>N zomJ-(K;oBFo44a!wgncRJ!k68>X7ewD&^fg1S8asV|)+dnNNT&w^D^7zr!=@?i`k5 z)F9pG5dqXWXlfF{BydAu$c;VydsTwC*;on=j<4|LO2&g-{vF^kM(XR}W5I6%ykpcMPmp5Y2&GF(0Ke@KAbQ&ml@e0O|)q zB4C0BRgeHU0`a9PjJyrV_q6vw&i=u#HHFl-U?M3RlYl z(Rx3H)ih4uC$de4-drGGm_GK%R(*^Tll5ACWu`wN==ifp0dyeE@W!EpKp^@*1|1ME literal 0 HcmV?d00001 diff --git a/images/mood/threnody/mice/m-worried.gif b/images/mood/threnody/mice/m-worried.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ce2f5ca8ed0837507f26200b0e1cf8f09ccd63d GIT binary patch literal 1371 zcmd7P3s+MG0KoBkFWcRdjXmWdco{HZ0?vU;A&3n@zz47rClMhUDk|qlo>fa}3>bp| zffRy+v`t+~Iwu4n;@mDdaT+bqSvu$76hbD4FlVA?RNtcCC-|T9-=YHCU@mseC&6c!e?wzig)l`SqVZr!?dZf;Jm)7yG&Xb)OnU!Rqg zHDnm_+Pq$?SEW+r=jVH@9(|`?CX*Ex7pJGE>soaQ2?&D9*;ty7&;A}aZhY)tV*fMO3$j0 zRdBgnu~-}!7$^`3*lae3!=cmZOG`_@|3>Ib3^?PH3q=1{^xqQzx1`8bR#n%iYSp;_ z2-Vg4V6ZR_PiSf)Hn-wPWZ!lQwFNwW($}wDrKJHlh(sqdm@GA$NQEzwhY7ySW#^O> ztxp%3aFcP(KcI(7!(FoZ1~QrcK`3Q87MdX3axndZf~&P5csiZ10tvmw;rOw_+No6R zlkf;GHzKPbu~G}wiw5yWb~Qst%4a;JNP5VR0Z75%l6VkAiR>6m6yk@pr8X`VFmKOu zXyN<#-j~lF^Q|>3!CYD>Q1r0ji?|OAXPYZk8VFz?eXv6_k=iKQeq`HTXB<%i!&zpQ87!2 z!?E(>E;14a}ZP3aebPU+rBA0I_TCJ-Xe_zH-baTnmYyhC`R zV5aEwvBFPsv`e)Vr)HAEL=dxzJ^t8C2pe{f(BDG7%pe8-ZLFdOlXFfr_&5~+1GTi8 z!S(q@K)yP@5~)`Y&yP@7-jSYwDDHc2L+GCxGEA|*P+$^v^Tq8bQvygM)|e?!kT7R2 z?zM<7N?dlpK69#tEx8+ht|l&9`%G=;6a|gW7ckDy(Kgl1>Qpeve_iNuIQX0tEJ~iU zLl^pqTaPp!27NGxO z;RT5paA*I;t1%j5|tb^d8s4sx@Mmu6WjW}xlZ5aH%)xCa7zqF?vAQ%4kK|O?A%E=0>6>jKVs^*+Eq!V zP87s_dZF8llA`DNDE>_VPP6l0@x_d|6-lG8S$2o^qXfKAbumX%^qjO~f0CNa%DCJ2 z&hNtE5qx~S_IpO@GVy6j%y$RE>-OwAc-U3dU`&Oh!($J_iHG?peec&>21Bu7o2T(H ccKdI2e%Z;RBu%aB4DIwsb1!FWFc6UV56$xo2mk;8 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/aggravated.gif b/images/mood/xenia/greyblack/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..43738b33b947b676d8ca34a7a4d2c02aee40b6ca GIT binary patch literal 895 zcmXYwe`s4(6vscec_kInbgSu)LD3W|i6XWNU8a^$Q=N&e*v$OVir5KF9yrjz#m$M+ zml{{YqIvb4R`B}!TGKr6!jcTkip zaZ`|I%c2N3c{op;lr8!@*$`N}Qa1g9EZYWcSyN3L%($sj+VRj~?$wzNS0HCL5#gb+ z@XF&Md96$$e8UTC71AfP&WEa#akpg4yexg9eR7{$MH0)H0QxD$%v2b~&|81$|lQBWPb}MS?ddo5rp}_vz7z4>1fU z6gH99S;{bV*5q;!GH`o_njk&Hyugd1Om{Wdi$Op@6wFKD*Dt($_pt4aFDORCZ=Yqg z#|Rh1yk%cn==7SuC>5j8_Z%t_^l@=z(3Pj2HW zM>+hA`1(z}BI=@3?l>I#hHV^$J4?MV=jU3CCKyFsjSRu9LZXp0P%FJcxHpKwaZ&)Vn)lam{2L_@I#aGmV!wqhRBy|5lGRr0<&n zOq>~*T%{mQQJhCiksYhS04x%0YK2hTfYiYU)$dzIBX}rq!Ji1Xy@Y7%%U)P|@;%Y{ z;K}& zzSL-`Qzwgp%A_5F=(n*|_eFUDKhzy1Wd?e0s?g?^DP4h0hsAH0 z@&iHh&0m?Vb67H^lkZv+e3A_qAsC?=BC@EMYQ=0^j|GFuyxl4aS@CcPVgB1A3PG_g z$ZQKHvp_TL-)E4=j6@$q&N^NDLw^o|vuq{zc7vj0ptGIKP zeU+bE#I^7IRkE>)ydGa*zsa(3W~t?sHxjUEP@cnCM7C>D@?B&S#Gk-^RBsx(ggw{@;AJx>o{ z>{4=ki@cwT^_VVrU{y#$1%FdZ1QHsg2A<~J=>@e$aKv~1pD@BRh;T>t%F5I4h}a{? zC&w@U^ls$AXCuYpPVK#DXm&oE{)!JpW?`)F<3EQlcHMu^eCqL;(N9UdD=(eA7#p5A@^>z|e)+^(5AD_~+qvbF%R^tDPA7Qke*^Ro00000 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/angry.gif b/images/mood/xenia/greyblack/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..da9600f3c3bc388dd3d4d2496c0f7c5ab2b7b6c3 GIT binary patch literal 910 zcmX|=UuauZ9LGN=_lBE?B&+>jD4O9)Y)4d;!?5q{@%tvjc*oa=SjTAy_YBxy-n4XmKB5j*Q9@A)3oXW zhhCfOnAS-_=-L(LtMpjR@PGK=bV@V)kf!V>Sdz?iVBWmcs_W9c+aYo(@sJ;3{xu+S zy0{_8a93vmZq)W=+9K3V;j}U(5H0&*H>B=s_(xfAZtlR;&xj%D2D83uEsc_H z)&Wx30%<0#Bk=zu^? zoo=~~>_T2fc4p%drDTSk$%DVMW-z@@p{q!EYb|6=Hz*)433&|Z3F*+sQSt)oGISd8 z2@NyAgqoA!8>}Um{#^Ak3kkS)h_WDdh?1Zl#tG?^dl)u2sv#f@q5tx}3ol28OvaZX zZoFG#vkhxUh~rbfWpRERP0e3jL+8LBFu`yw(0S4b_V~PbItLrF{xhxr8gRG`N-RUx-CYnQHncr*F;=3>?IJY~Sd znLU%6WGzLC{fHvji8Abg6`C)#fEH0874VeVyFFcL1P?b;^G_Io!-zm{>cZOS`=WL4 z$n@mdZ$Ah=@JukDuT?(m90+Hlal3M=MU3b_{(5e#@Sy*r;FUM~DkW0iKjuAp?%?U+ zp(k$taIyc{69@dkmc2*5%&h2btwYC;yqY)}TZ|q2bmi>$$1k3L?w6lFnT_-0zqi*C ALI3~& literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/bitchy.gif b/images/mood/xenia/greyblack/bitchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..38cfc1f8ef8b1a06facad99fcab72be263c241b5 GIT binary patch literal 899 zcmXYwUuYav6vlryJ7My$*@SiTrxNOhgml$v60l9xxWtXrY!fsa_aX7YM9l7hg05U_ ztyr8*w+&Hg#rV*aU?PI}Bt`q@MVSRxgQ8SPlUb#p4H5HTK(H_wNV(n#J#Y_~%Q@fq z&UemzI(_uWqc6sY;ekfdVVQpTE8iulNH;Md^xW5)*{o5__ zhPWljaN8gUw|F>1oIXpmN7)n@jeQpFf+2P_+KQr-)R=KyC%@;RLElT04X!{=ZX?W| zL38b~kX$Wr!2I1al@n6ul*)ukqj5KH$;1N0y3R)s^>@k6{>0Hk(5mTp$QjMK4_&eZ zH$iqkOImdCcMz<`NcNXjg?j?&2Qu`;53kKza$=BTox8nKnQQSq90x8!6Vz?!)2dcb zEvW0L=IlURD;YGXE&K<|CgUp)hF%e>F0}=SAB(l1O}WQZLMT#}mnc-F~(BfrW z7b!Je)lKLWTRu4lW2a`{VAUKB;%&D|Md2%)clO5O>dDyfZZ`F25-+1i!RAx{t)Hq& z-`4{eS?nBLCo6SP>|R}D&&tpV^8}k(Box;m74X4n_YJKP91L9WC(ODjL|xm^rR672 zi|7OW=D(Qo|l>!*Xoj`Z=^$q)ZZiG$*U(uLlR sA1~hfdeS77I#xe>V(HjJt&KeXKRrAU%K!iX literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/blank.gif b/images/mood/xenia/greyblack/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..be70d88c8025df7c406baeb165bb1e0c27e476c8 GIT binary patch literal 874 zcmXAoUuaxK6vls(z2W9zv#IIkPodxjl4e`PBo9rhmNjmq$(lg3WgikBOp4jPP(c?5 zt%}9Fadk;sEE2q>$O@S$k6FUl;qx(I;^ZF09*(1w70Fd$gCdm&|=m6yx=G8p?YzqmyD43A!>O7b5Xo|ZBNV|R4x#-<~Ef#RUc zT^xB)(0=E4mKq$8%!k>Jtpz@tirB4?q1sBcqM7f)*}mCnS=xEnB??pGa4W+3cSsa0 zabJ+-p+z3<^K_O3V~*(SWLseE8*}IrOtEXw>Y8%OU?xnN!k&i?b1yG+cmlbwgRqAu z?2Tt5@^+Cy`w!pNDxyEpIvXj^CcJ_plV3u7;8G0H{+KJ3bxs_GUPH%6E*s8cn383< z2Xg2n88N`$VX!_$>UjCK@XjKGP=?{e=*Fre=O-w&c{}ymN>AXU6nq6;(6(hxudbte z(6`Xtx$%TiGHlRT^iS4o=IWGs%Ea!iwad9(O6Z$HpG5~kD+YLrqG{|Fbbm2Ea{GYewDix>E-yd`S6?S#BisFu#B70Vaepn^k)Dn?|0jWU%sxPpNM(|YV!arfRO(NP3PF-Jn;X~1R zR#*KWr;3V-7k$%;9tsQEtT4I4Eqgwl_+_ZeLcRWrD>l5PE%6#q;5Ccsb`e z=RD7O_jK;w{`6}N)KdaSjUzppu79-Nu~zwRAk@#&AZz={5m}~a6$~Q={#n~OH?JEd zfk}OeU(t;Z1n$|J^cM*l?Bjn+!kZCAbwV>aC$2G@eH&=ZUkf@Mw!XSSBqO5PiO~Pt zERqg!TM%c}!2sN*B~A!$qi73~7dRgD>a+joS|5tWjX zGBu_VSG4LWnHPQ@=BUr6BHxQve=^_ub-7b=B~=1z6r)Cl6HP=zcDzf0<;kxGENjd# z0-$Y%<5bEhCiZ=lj^c8cA+I83{YKuVY-7H=E{i3VNx}OQyB4FA;#K&C*kALvLGrAGBuF00a^{U?hvW#JsJiN(P_<7HTK)5vvp>A2 z)p`QoM9=*=`oJSQCj$?q@)>QDXX-@!-1K-u!$H@nk2hXF=~bp)`6IqKJ@WYLU+&oc zNp|LpaJ_siQ`_|Hhnog!PBgbqT|XUj`rO$=OEc$NPqw`D?dru?=E;kn&p!Org`1bQ xegF4z^IJoSv2AA#uI#UCpPM|e&hF*1U zICfKSTPn_i^JQbWx|dB~EdJYza06!cL1Dty-Y5mPS+NfmL@wNw2{YL;Jd=naWb!P_XrhIe^K+KWu>9_hKwvNn^s-mlC=2+ z)A~TraN}pjYqVL6D(8C=f{(LdJpuz%BE)7Sqs^GBSDG|Uns=H-F)JR8Ak4qJL{SsB z1Uc?#6yO%Sa~SlRqP>Y#f%ZVJNxLA+ri!*GandTLq4E^BG&HKaGuG${tg&^3-rcV+ zJr%aDm)NPV)OG2G<%d${!p^Ya6-_I377`tEaYVztVrPEh;2vmI<5OTO_EU~}>xPgR^1!^mi|? z+@in*HYd#K*{0CO54Z_x8@zfLzQs=TY^*Q5t{g98n>SOb>Enc$!xnSh#rtw8)cV-2 z%~ix#?@%w`ercB)-%fnPrh3O4r<$Mi2SSPoil`^C!myU#Sx6f*xxrQi==|4s9+p*6 zfV&8vWX-4GqHWODU(*Kzd)xb!s>GMLr?$r8sma*zem-+EO+BYZ!Rmp3mrvF#-&X?| zI^Qw8Ox{vSu^(4Swxogr${B)9EfY3WkSh4#w)>i51djzO_!D}xfQTlu3-eFECz^Kc z9~u7i`>EK&hhnAD?dtTl$V+ct&T*jJw(msDm{{#Q&7u3VpG|Z!)!Bd1S?m7e$Ek;2 tKC-fH;?mVm(w*_xxqp6t_Ux|HJ6_xS(Ic6Q4<3Ia`CsYt=ck2W-~T4K2~Pk3 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/confused.gif b/images/mood/xenia/greyblack/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..e964731e52ffecf1c197c63318e55bf7a4592b99 GIT binary patch literal 947 zcmXYwe`s4(6vsceNlnE57+uB$BVRDkijZz^P&u9N5Fq9C=QZ9%k{pp1NU&bobx^3 z^F8ObceEXT`gI>Z^586SCMFWT$9%w#BZI@Vyvf#4(ggk{Ye`)XLi4IDUCU^CUSQ%g z_#I837L>29Fq~zVPE;j7uoCz*>~NJr2kBDEl9FgOTJCz4(+VWqfaQ#&8U(I zxC46QOLT|;f7!vZhv0LG+rk<{FWNFR`46qlYI?MlxZB!TUYe{e<}pq95~{&{PaUsZ zM%E&4A#1!Le=n+6zl~OQmz0bCW#Y97D(FmA&Wwq1bBy0)z~el`8?Eh z7R9j3M5F8ksTTUrt6T=51-1rA3xWeA1^Eh0)m<76p%4&I0qVu}_ZE)rJgDV6Crv`G z_s)~4Rl?aZ?`l^ktMY|kOw&WQz*{|V4Z~Ak*qD90BFe?Mp&bqcZj7sinK2D9+7$Cd z0;kB280Hmzt`y&WZ?BSxG0JJr1e+y>i8ahppDcDbOmZYfu#)IrTa>-@`iXQZigNC% z!?JR^uBPv7WY-y7MO3`I;G{K6r>>+jtPD$%qQrcEdn}fki~&>LmOp#RM^sgENB+y4 z$?CYAsbRZR2oPXqnsnv$x-Z17v(fzNDuQv2uaF1Wf{c!S| vS3f*vp5A)+323@xN(FocMn>?(bk*5x2 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 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/drunk.gif b/images/mood/xenia/greyblack/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2686999c14407686a7b26d3e81f7a62a7fe3848 GIT binary patch literal 906 zcmXYwe`s4(6vscec`;GabkuZhA!sTsOUJMkTwAq-nvR*Q9X2CKs<2LM@<71_o;nqW zFEtwL#DSeZnXL0K5&syo+dz~TSX>Ya6SnqcSkTpg3@iv6ygul--dA?u9xj)2zUOilcUzh%sRo!p|7EzNM z=*Gu_*6Y7B+o0QES|#7J7C4pi1^kev>L*l@On0C+FSTo$)bDhNLQ3@e5&C}vqM(VJ zf(&;w@^F(!GsGCyMNd0Tfwp5-tOQF>z<%GhFsXB#i4{hpRo@uiM#>@sHFgPAq zdD3TGE3zx_hZB&NPkth0##f$-*#+H*e+7}glVL>bJ+hT$_V0x*MaRLIQ=ErUCCjh| z#=x_rMIZlo!SWD^(egE6AH#4x83toRD+{_YJx(cTZ`5n^ovwpr!Pn3M!F6@IWF6Uw zyo%hJ9g8U?y#|$q{$w#gu1=}5On7av)yQp8LS7Q`7}6EeqL0@ps>ZIu&M(I%PoNl1 zTIht1vX~@yM&)t@l5ls1svt2#Mc{<7RCiSvLLnd^4C=-6>*o$XxL0>3<}Jno@0?+^ zQwitAysaz6xEGt4|lUEMGMa)R==ElOS;c31rnfgdP{>xixVNP16C=M1PnfPls zdDA-2uWjPT3*IVOm_^=*%(2yCTG+GHveHfaESi+_*cFT}B}#S|i5Qs)MNyt!^4WIN zFx2$50lJS9a8dEWO~H7B2}4O`+Bc|4T#5DW_E>B+852IrCjUy{WK>m}`);ouZy2tt z1~7TLcWRZamx}qAD!6S`=!FHmO)cSzDUcetigS;vDUD!{=e$1=2GwqY z?$O-T*~{;T9zGB%7T0SZ-0z=V>l%A0IT!Z7xjgdex7Erca+C0=YIIDcdZv0yZTdS_L~H$;Am8x#*^B zcvG*IICV<*!I#PE%Lo1B*rxM?as$TY%V27k-UtI-S8yLJ2o7#8bUZ${?7(w)csS>O z{^x(r^W?;#k^Rp_iQ05$c9$rmMKXxc{~Z(s zP23P;Lq>TK4kTzaTCg!_8x#H;e7BM!#bV)5ghB%`SQqElLxVqK?D}z^&}gd@8<_nd(&nowJ(793*gpTON5Etr_eaZ-l1&c+;sx!EWFAeFx^I8WvF6M9wAj->8S9(< zV)W!l^755$9=@LsAA9D&?(*zczby}xyC0q0ar5`n9iOe|epr35{^_o7k37)Z!6W|z D+hG(r literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/embarrassed.gif b/images/mood/xenia/greyblack/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..9c2d65c9287364fe7674067b782d40b189b016a5 GIT binary patch literal 914 zcmX|=Z)jU(6vlsVZ(^df>1s2ZLai-|!$B7bkI z$oa$_L5BN2X5dci`An~gJs?y+2LxhMH@pb3p0U+v`TOi|q zGZh#SffWq7TwqIJ#SXa2aL>AK#we#vE0>qC3lJXqB!uYl!nOVU6Z^MAM5kjT=OF1( ziZZNf%(YiZiy_v$m-W|(?jcvAWElB%$I611WDhE6QLk0{oGhvYOK=ymElR=2 z+jT^rrh%u1F(c?&O%JW}4=Mq&bxM6@LaUW7nQc?Ty)N7nxQ=iYLma0dkY4PkyHjV- z8Kx9@I*(ErC;PdM^}yEQ;bE$Rmk%>9utO+aT@`kq5fBgped77nl{b2~=k19F#qPjt zi$*U}kAULjfoluGet=TY{EYM%dNhjaTs408*i;r#Dl&RI{(W)EMyMi%U@m+l*2Y#v zz54<2jrSg9-Yjr3JWG3~sIFSm-L=VYour2Mx`Z`{?9j{MEksN=Ghx8S#cMN`H7})B zCb$(&(RMHt?t_4_r@1j9^;8tCWoj;ti+b--TfA-;VR3l;b_6@)!LP>uX`E_G$I%6( zE|N4T~*)TOo4IG{GGmcMdq|@@8_a_3uqljQMaiuc$zVYO9 zyRzv^H%@mB?2i@-t=b16|MYBP CnHh`# literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/energetic.gif b/images/mood/xenia/greyblack/energetic.gif new file mode 100644 index 0000000000000000000000000000000000000000..4020ad9687093909924daa736cab5d9b7f35bbf4 GIT binary patch literal 902 zcmXYwUuau(6vscm=9WZBQ?2QrLDdxE7RzX=xOUSKY9qC^6`PTV#s@R8$pr{c$hK4H(;(!G>#lqZD)_;L9q4gPRK-KYzFE!0+(m$2s5g zJ>PSF&yS59JoIXmC@yGCnl)>6Khh2SR5&`#@ax=tnF@*9)EsFTDHvRr%^RD#;RlWNt?F*&TOEOs-$n%c z)4`3W1ICRK`+{3;P}%|cg_N0qH5qe?x{){o(fFwdqU9dhxvPvEfG$PH#h6u`2T>(0 z*a9Q@5@RCH-+r(>Lh7(}LpaAUJYR_lEec4UWQN=d&#W#K_Y*rPkn$Bk&_;G~U==cr%jYyRxYtOeB8(KrPHE+Z3h#VlDIvVJP&6RO~@RZxPmfWN6_0x<yH6nq}Ku@~hQjD*3UWm|ir6m+qof&<0D?S+oxxz!KO_waGP@Bjb) z|8t(pJ==f$l{j%+2sQ<+Ijd`b7x2y0#3bogdH515B>$xDC@E8L?5+x}Zy3@Q*mRlv zfFaKdn(wYLS!bVQTsQw8O>i+A2!|lYN{HyZV!Rz=>qcuZsEh~gqLdXqA%yYQVNnW- zdxAU1g;_MRz?M4&oMX%*++IlgVbCsn_MPAk&;OGXo(h`ELt3pnfnyO zy&}9$K;9{HDD1dlWe3#9O63FANWv)@GWjXQdm1s?n*Ggf7`=t)gHABqB{?@p&aVqA z!)6gFPJ`&l{H75RFTx4yj&P=to-adh;^_LKA;(Wri8%Lb)rAhv#nv;IpdBI&eL7VQ z)qz???JW!>w32ytnMZ$OIm}p%N{2;kbGccL?NCA85NaCb31!p6o0J7|74}{l82(T* zWZ1?adY0uhW1s0>CLj$D&#)p$oncJ9iwjkW?UHOUWZK=^nZ?(Oe2$$a)5e*kT2NjtV6%lag)@)TLPrXRNF~S*X^QIdwSePnNvYir z9%kPxVGn&jvK``NogoRB&N@|vr?B6JP4L||;anm8a|$=_+qjkaXJfW5Jx?z%e7SpM zgM#0Rc|-&5#tL-9BK}LQ5J>1DRq(Xg2fd)y2%hqj|0lwc2}GnTdv$s6J<w}RLX$Ju-Y@t_q?*e8pZrp@4h*JeF17xeyYSfY3m21XpFe-@$l2Ss m{`mXx+R_uV>EMrxM*95z=|`{MT>E|X%NMSk>g(LYGyei)y%&H0 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/flirty.gif b/images/mood/xenia/greyblack/flirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..3923b6ed0c25b4b5f61bdbabb0d495a17718e325 GIT binary patch literal 898 zcmXYwUuYav6vlryJ8|}5vnlE3Pa*0C61$OVqSB;lS=L1B#-y4p`;dsZ6_XuMs4G`3 ziq+XTx}+8(#s^y}jf$XetycS@%wkvLgHWMOW{U-FSSW%4!N6o7<$5Rdz&%_p=X~co z-#Pd3u><=ad@ex(AB-l$nRB}D=mvh6Jv_t63*3B~Dye^{drHbQ3|~>rE320D1uoq- zSFz*?LCcljnW?i&GOd$uSrdGmjhM|aMzxt(MKRru)ws}R7|Pmc7sagTZ$?=E4v3;5 zt_yN(7|g8*b+T$Gz7+uVT&F?mMx98tZ>pAGpXwow>`A#yHjZO1hTM>Fb7A? zm4_noa*5sMAHJ#Fi26XOT*R47dPPg7PC}w@A&zLdMYi%A2lhgjrsE^$H0NP-Ne8Zh z9C(T`(Z`K2SREq0-?=QjqsSnXVK6zgvS`WaQOZ$oeYrN@8Thy^oPu_UuIbaImQkIk zOQ?=~CaIMS8`Kv2lO>a>Wy+ln@oP&ha%zh*>Vi;5QGrk{eY{FZH+Bg+KFLhHk7hXG zVi9|Zr4gpi=v)rN2;3}C6{HJP1b!S>cUOfWGy($RpkG42cJ|qwdo6!_-X&wcd4|OTB_W zYrEg@bF29FyKt3U>=Lgf=GbboUA!4;c@>OBTpBpDcok%q7A3!%bdub-rl?Mzk9b}~ zN8l(n+=G+q)S|ivKy6{h!(E=jcojtqs$UCC# z?)_7fpIv-6cIOkZQfaOBUdKRuB9-~vUbubdk!Mn5vLE(5*7R%kTw}Dn=boQV^uK)9 q!OGABZ`Dr9FE4(&L*AD8`=cA#Q|-^+ztJzho;?2K7ag%E5C0Fjfepa` literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/happy.gif b/images/mood/xenia/greyblack/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..a14fbec0a3c5fadf66f68d180ac8baad9e67bc3c GIT binary patch literal 905 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 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/hot.gif b/images/mood/xenia/greyblack/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..3781ba719df1f944b6a8d9ecbe142949a4f1198f GIT binary patch literal 990 zcmX|=e`wTo7{_0q`_Ub>U$C3o;B+T5c8ck3G}9F!?wXq$dKZgsMNVV8TeEEO-54#c z@7)g8Ds+qle=J=PIK#lw5{mdXBI*~boru`N zdJ%PqIYF2Q4mx3ubzyuIR*1TC(gH_OVT?L~pPWR?WJm^Sk_ix9@=z$_WP715P}=Vz zT!DJmWSw2P+C!D=x2((5?B)T}4BL|-pB{}V{v+V2JXnCp|BvpKOKhu!GD#6?#94VaX8qdBfzel%yWbt&>TQml_eYID7{8Aab3! zyX^H0q7<&cvJrd%5b zmJg8(TQp+iy~+3%A}3_61$G-2+erzYZD&Z3EkKjgrCvi7ktzZ{Gu&*4 z`LT1Ix;~^RW#C>9`^g#DHOz;myV5O=}rj6`G<|k)2ShCGe7^WZ!@Hg4EgWlOSm@Bar$~MEV$y5x&ACVC8b=>{?s%}R=f<|d zH7_Ju?|ixI(lN2@=;=*GRoe$ww%Zo&oV~d{@zl`g-jUv2q2tw$*W~-cryAei>iqrV zHKTi4PCofg!=dRz^DoBN?ODwIUHnGmi{OpA%iXnmUuMUJ1J2pM*6#ea&v^Hffs)gW r6P<4zz5H5a;uWpSS=7~azdB?){Pv$uJla}wbFja!J9;GGqH5} z*IH91>XsNHj0KuF!6?B21H@o%F(t*s=x|$K!6j^s3V%#zkmT*f#^-&Qc>XxKzs~oa z^PO{F@V2gdx_bp`p#q{w6k}rCB-$!%@mPGsB-$UbZ$k>MdE}G~r5>PaN;gku!&D_; zu*W#s3xpUU3N)Gq4&dGl~;BwpPHAzFZ@UdiX&F3AxB>Gf4Q) zH6$dGIRZZ(i0B38@=y57C8!R%3vr*Mgu>Ky46r!|OF>GEaBe?-k4+6gHBUzc zjR9VRlEi@-j(K-8e8h>n#>>nWc%F?<5@jE#X2{^a**HDGC20Y(D#)ahRayWn3XB2^ zKp>B(wYo0@QpIV2${|Q@@LDAUt@sX-76dYgR>e^|lPsZu0;13_6MY|ajpz(c^dmw* zjo712?T5iLY-b3gcrTL82%O}x2G~8|pPfh%Y}knefm#a2t4jfm;0PcEqB(X#=2YHU1n}vyK5JoKV0c(t-mqx*!4ldbV&Rz@=1DdiTK%C>8TzJ zI*N|g$y+{^KNenF(&Y93);jFibE@OYN2kfj+|hrHkEzx$I@-}zh>=szTMz@ L>(ZV>gkb%@feA{^ literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/indescribable.gif b/images/mood/xenia/greyblack/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..48877181faabd35b284e085db727ebefa90f6940 GIT binary patch literal 907 zcmXYwUuYav6vlsdcfu@^Y--#zsf4hR;I2|kind9$EbGS9jR}~Ii)MW=wIn;DsDV+7 z#o%llS)!qRh)9({qrUhUY_tf<1RG7MVhi~*TL`o%3-!T(U~zUJ<$5Rdz&%_p=X~co z-#Pc$f#bbLUyTvN11+T4({@{X8}QS_iE%QobN6MIN&Zd6m8O}3o^@Hbv1yo|z@g3J zI)*tbXjs3-c!dKd1(kfyLhxBOtk=N+={g=ROA5^x)r(Dwr)FF(2xcUrF=v>CK1vaHXLV(!#rJR=_!62Sa!Z|7xr%H- zUPbQDr{hY=ph0EzH(1aaU8U4w6Wv;9Fh_SOAukGf3h4{!kl=?%YxJxWq}vPQQa-W5flOfqM%*^e{1oT2M!zF;EY3B|KL2E zElRi`=CrXi)8y5DbDS8J8gGoi4_L9z+Roft(E{I=ETcD>{P}&gFlQZ0Om-Jzx#T-| z6PEKGzcz{s-v_JYU`_H~Y?|GW<=~F9l9&EK*rAF&fm_CGRifk*q~hcT6-7C}6n5RJ zX{zaKT^yJ~_fheYTA02HgQk+oa$Qy=zQp-(Z!E5wj0KT)Uy%b5Gyj%`FcRKdh@Hdyw?Cby9{&A%E z%WPxe%2x7)+rQ5}H1+4w(Z$5I&->r}ue0`eGE;uyrS|-TR>#`>ix=AKBRus#cf=DA literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/index.html b/images/mood/xenia/greyblack/index.html new file mode 100644 index 0000000..8929f0d --- /dev/null +++ b/images/mood/xenia/greyblack/index.html @@ -0,0 +1,77 @@ + + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
bitchy.gif
blank.gif
cold.gif
confident.gif
confused.gif
crazy.gif
crushed.gif
dirty.gif
drunk.gif
ecstatic.gif
embarrassed.gif
energetic.gif
enthralled.gif
flirty.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
indescribable.gif
indifferent.gif
loved.gif
pensive.gif
rejected.gif
relaxed.gif
sad.gif
scared.gif
sick.gif
silly.gif
surprised.gif
thirsty.gif
thoughtful.gif
tired.gif
diff --git a/images/mood/xenia/greyblack/indifferent.gif b/images/mood/xenia/greyblack/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..b392fe198bfec68262d0c173b88679c70d25a0ce GIT binary patch literal 899 zcmXYwe`s4(6vsceNlE@l)6u=I9Ry7=viJjA!LD`AP*bVtS}_^lAl9wCcM((dr81#3mxt zGZ{* zaMZyh@-CG$V`p?OlaPi76I2DM31$Rd6i0Vgh5cv*1Vll*Tt@u-K3)Omyj5yFX8gi7mV-M*EkErKH)&1Kin#8$EnDpha#oYdhL^_=r``p-y9OLfVCX{^856BSMJzzi`gGC^G`i~erhpW sx%{p1=DL09-gkeUdhBE|c4>F<)wvht8?`^Px3B+r;OwE^&Rx9lKdzn>IsgCw literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/loved.gif b/images/mood/xenia/greyblack/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..9934f2b8c277623a14ef037de9978dd4200dbf7d GIT binary patch literal 954 zcmX|=aY)={7{@>F-S4`K^ejE+*-TE*G_$->&b7)!Z9DN`p6(AFp$_zZ)To5tmNZ)Z z&Tg0$4zjj2E;K5r{*qd=p!i*6`A4G_&ii>}tc`3D`)he*@#7i+dOj5cV!EIq3k-N*|p zs!X!z#+!oT%Re)^My0_Z|C zOb<|_z0z{a87X7#WN*lh>qf)75U4xlM-=}@cj_YhS|F(Ctce1L9I$8{%I_R;oOaz)q^7zIa$aA^1HtZoc;lJMCZ%S+Q0g*=u8=b#*X*VGBh zWn=~N5^_hdJ=BltHRPZbU18qKz%q%7B>wgJVq;*71aeWx31mS?i#m=mt{S@pJI=O8 z-#{^pTIdu#&wK|1b1Ih+=zv?pqy=rmObPOSEY)2acB2pw;0N{M_-hM8Wi5KXXWF9O z`_del3MHHqb6h_^U7Fwg!LkCZZE~a!E?@>~H#cUV^AGZI!qoRPG<@@-T9{LoDaOO` zK&;^?`7zV_jPFat=U+IhWMPi;LST|DmuX>-vUE@uy4@Bzl4ICY7(qvrdiq1edK5*O zI`6jaoMEWxYt2-iz*|7Y`!)rgYxEdOD$~xgBq>O&SGLDutI3$~da&d7e)2I@m0Z`2 z%!xIlP*4MirfPdL9CT7Kcd3HgmWEoG#o5#Z?vMgmf`Z~)Q_z$~(BwGhPk4Q25WcF& z!u+?d`pO!g`m)#jF5<yMq55esa3(_M!F7@CWTPJ0E{p8;s>5Z{1rn8U18e?T@GL zs=w`Q_l=Q@Cm%L4O|Qk?|7lJ{U7kN<*Ui*^Bi^+)^z_Py4~;cGd-pq^_NAil9s2E$ z{(3%oqSAlQ&cOZIg}60yvauz-vUuRDbI0zOIFh|^^vci!$4}Q~&$xbZRX2r0Jo+!P ChbUG6 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/pensive.gif b/images/mood/xenia/greyblack/pensive.gif new file mode 100644 index 0000000000000000000000000000000000000000..29e7e73701f648f4a64126ee56a062c1efcc51bf GIT binary patch literal 976 zcmY+De@LBW6vsc$^$su1xmy0DJJBZ1g`|tNYYxQJnO8USrj$3xYt4HvHP(zryS3)J zx(m9-9JGE6Ct+;hC=6YO1;*>@ngzzfsjrdI8vYTBpr5?HuzGr4|LeeWI2^vubH3+$ z&hx0hw(Q|&^2oyix67UAOL+6V$p=B`yyG6i+Q$wz;4 ziHJ-51OfhXd&87(gy3rw1+b=>;fuBvh>W_8cjnaIL`9b$ABYHhp-V$`oCvjwzOv~wuUgoK);SGEI%$;}Pdik>KOtrW6(RZsRyxKOn8A^#Tk8YqpfirYInLdC zuo{8}y{X5)WH|%*uLC}&CQm7A9Yc?C?2#o_gwsvFH%0cZ2p zYW`gAS&_D_8#pjr*tATGbCvjRU2wzxx1OYgOhgiF&AGsKYmLx)YjgfYs%H%0@z#xx zTs`SYO>g~b{Jk#{uI=^1>*F`7#AcB;bN6QeZ)_xC*LuAjUdIGr-+^2|)`YIv*mLVfqp?>{eoAl`gn_Sn+< zEh02pd*s#|&jm+oX5a3(qkU{~GW5f{`!`Sg^8JUEpWgarC|2^sCnsiI>GQGD1LDZl Yh3(T%9&R6V-BX=65W5mSDFple0}s7Cy#N3J literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/rejected.gif b/images/mood/xenia/greyblack/rejected.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb9e057d4e4a2414cf4dc53bbc0ec88d638b2f0f GIT binary patch literal 968 zcmX|=e`s4(6vsa|c_Bg8wAAz`v7}m?IMhaQ>zt*QcC0DwuvsT-i<${-A8s&%Z?@h?FdCtLL3$RKbR#b? z38uJ)Zk!SnEc`-WjtYYw{x=uA7jt_(&_iHAH0{qH(4 zpowKcoZA}xu*{=zLe%S`x|kJ#R#dN3Er_w9(B>qWMuiztl?FCF6smhBQD_N_#2UgI zZSgMdbQ|+Y!rp6nuQc8A9Vz4POlQa%(2d9$2!zM{h=Tv)oX4k2wJO~SlNQZ;rJN1o%O{I6jemL2T1$AB86G zYv)-iQ^Gkh$Mkcf#rgH0Ofx`kokM%!8&ZMf`dZ+ye}ju=O8+1dId@bo%$S)H$>=~J z9yvn3KV@EGworWawX;elsU(AeVK!VT6RVGzebR1oo2-!O#~Q&XcSH%(6(ZiQD9Z86 zZp&IR3^jeNj*8=WZB)E(-Azl5c0);(vMgpKw#0m6b1ascObXsAZ~ncDd|Xv!W!FDT z$8&~ls{wS3*K{ti&q*cqm@2qw(@+DaaW*xLJETBnz*d~AZB1ze4?E8J6JFnE2wyOk zo%rE|@7}G?eVd#{xIMAHlbttPP8NH1T^^5zc*l`JD8qocXRTt%=@H5?Z)2slm=1hg7rulJh&A--QY)x5 z>I$l}Fl1^a!v?j*|6nP~)C%RaL*nLAo1EIBjJhb)aa16bOCPUM(v4k#&d-M?K14H| zaIuKL%F-}X=X5SdU>NSqP!(inSP=LLT-{w2_Mj0EkO2J>`o{Se@7rzpB7ZMHB{XIyHjY_CpD5h&buw#VY>$=L8gVffE1eqL9l`Rsq|C+ji@ z^Z+K#_D-%-2ve~i*9Et&3cXMv+|)7=Q-jnX(42b$Lu&+&hA#XQ(bx-!SohfZrDxt1 z$zA)VCcpaiz4(I%;-ylfcB->KF_AGJzU17WzK5%yG%kN?iZ_-srEf+*OCJ8^Sf=vz lb7xXV-#+nv#XKm6_GfEw}K#ePsvk;c_|W zd%ov;&V6ZgWMJ@clqfD}O`0`p#UG0Umu3!4lYWZ_uTdrWFLg&6Mhf~@Wb^8pZny%Q zxXEpFtWY)5ZgY|}KU-)|R%jCi6Mq2KEf z1x?%)al~R}qRj07yp;g_jsa8i|Ol=~9 zy~DxP{Q=`vkv+jb-JrAs@=Gam0V|tu3c8V8f@t^22%_a7+46Np_CbfD<6_Jz&i$y8 z7OaEO^D3jFn}7UZd63ir>y~hiVR*g_y@|fnMctSjrWA5EmuvGe&&9UkJ7|Z{hB_T` z85u*~K<>&9C6tnWgUZ5xQ3*1!Oetm&S+BGh6Wf%K7lk~A^n|qO<^zhVu^X`K+oAC< zPz=Xybi(gaNi%U;<#Gtp@L-CnAT>o<;6|`jcU9;^As`?E>c#gPXJ3DGpYD#$+YALi zKFwN83FpUrq@SN}bGNSAc9i-SZy$u;Fr!^tn~U#6Ci$sk>I2E-@7rd z$@g(*O#2*HTE(vy{8h3siyV#4vfX6bIMdYf(i;ufG_YoH$`~C=l>8o2336kKqC9mz z;5ZG#P}A3X*nOO!hl&qv35M&88A>YCxlK*tN$gK{#^R{SnDBW%eJ6#RQ&nla_}|*` zy5V_h0OO~+vTNl1RLo~p!5ynY7cAm$YKcHXfz-fLoI5>DX#`LE&i@m^(3^-*Jae}4 z!l$C`$paJFAO83({P@e^VsWE37ZC%|dkc3)L_A=wguXhHUg*pn-Mf_iF|+Vg_qpk% wY~{-L(IXpH^1Ul{8&j>}HC!i$!gfb=l?!v6VIb12!XK>IXZe$wfsMxXh_I zys6QUPC8iqFvnmSe%Z%5r~9&T16B(<=x}Xs90k`=u!sfG!R>|2<4F-;I4_68d!FZc zpZA=h;UfnQz7`^c4IY=LFkR@_(^31Uc0F@!ih(zI@Cp?oe^9lguE!v{EE`rk;dMB=Ommt!yh4<@MyVv`gFb^ud#SAqQ~1Ox;?oz(Na`B$6!HG8yV68C<1 zk=0gZT)pN4?P@7#Z~tJLA*$QFbrinE2z705&Ak(t;Bwy34n!h1-d7LijA@8mUpADC z)UZv%H25Cz^?TSE%qvE&>D|yb)G$n}DHc-G&ag{)f^yW7=x*3d?ajo(#pGz4GU&op zEDK#%a%C^>Q*1h9Og!7J_Q9%mv|evmRTdgBE06_n!0dE9$|HEPp6Y+X>(ddwj>LTV z`Hw}g=Wu%b(s!TuA06@MZmn}V@JLTb`0ne>?r9FLMamn@c6Ykw(^nq*akl;Cv-?WH zcw*++=$$d&Uzg&g=<%7G2fx}}Dn2zD+&!}Iji1jAH6MEWq5j{O&-M(BoH+l|m&s4v Nk5BLZsV~fP{{r*@8b1I4 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/sick.gif b/images/mood/xenia/greyblack/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..dfc46d61b0c7968d58777a3ee41448312d9ef82a GIT binary patch literal 904 zcmXYwVQ5=b6vuzJc_AsLsm63|p=hdc%VgL(Xfw5h+Ujg=#b!ik_rY%1xH$3c3>57Yl-e*9RHb`^pa7!{u_$|NPJY zocqk^{(X-fjuXcPqscI4%U$<%0YBys%`o%|w+~Vw^$%-~k}?D7>ngZfGo>rA>9Y6( zQ+_CDxqg+IH993zI{A(@!KslzC$xT049UwDMz9yWbNY9s{H_^YkV9KdsN?~Vnr8?j4x!5**4s8(L(5FMKpxRMa zP&;yi39Y2xpti_gEQOd{q10X`y1vvRCmWPd7lk^C@`SQU@&-lS*cI6E+2HsGXoll9 zCXpj74KaB}=W+;!;Px~XL1vmcfg8ov-Bq9;jevkC=ojB_EWdbfpXrXx+YE-@IYX^o z3+KnYZC;pk`uO5K!vEs?C&4t&ZQ+!pj%zdfUPjBgkIcZy>*jtEaQ?KLZ zE&Dt_w~BAS^H<5nD)MH0mPV6hUEAnL~DHQF6P;B*>0wifZvfz;WtQ z>ggLjbRHw*q2t3_FucZ?)KXc_pHvl|!hUyqERLRx1t)Ste`j#Bx+?Xj{;M5Zlb)vs zFus_asFCwiu^!b0x2=K}lm+}vEfGj)kSchZbGK(`jbM-O{67&2=Mmwqk>#Z)kBivD z1CtY9TzW5Z|Fe-|aijWvvq;95zj^6$DH<&1Qoncq^6`V|bB&kxo*g@}v+v;I?&8kp wPWL}lJC%yvytHuF)1Nk)b6;NlB;K4E_~HBmzn;72$lmo%`SlCOh2V+*0l0h+`2YX_ literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/silly.gif b/images/mood/xenia/greyblack/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..331b53d7322d5d9be8a1946d46389eb7ddfa9256 GIT binary patch literal 907 zcmX|=e`s4(6vsa|dF4e&(^=CWgQ6*vEXr6bxVGvDv6Y#uMVk^vD`Gcj^EL$yzUfd} ze5p@s=Z}fqA5#izL1F$kZFT=BuV}V{2otvUMH%R7K!g&9%v!Wp0?*hTHF0?-%cDGr|$*sKFbQJ+f-d?nrY~{A?w!G4bu}i zv|0RuVZJY@zwtBURrZ>U^1p@PTsExNL5@rv$r;IL6GrWFqozq?t4S2I;=wwEai>!h zHE~OjXG>!OZgC(_f*wP(H&PR5dwLAo1zC0!+N#7(E6jwdRNVE@pziiqgDWt{HW7MP zzrOZZ*t}k1pZ=?-OD8NplrkT-hZ1hlFjJpEJb5;TsQ-`d%ugIX2(5~ahdHe{_n=DJ za1+eVXUK^pe+I#FnDin0x^Pcp`hg5xiSD&I!yN6W9C0^SE3+-WhvUGf&;*eUbz0>r zvITh!*<8pZl#)S%%A&uqpfj>cxy2@SbD`cG*`bWQEaYjVFQh|~S1GB+u0iwp%;0+{ zhJy|U(U)21W8{L$xus?9YpU@*G5Rta*rG+Qn z5{(ZX8W~#r;qB-HN1~S)y|ge7ryR<8vp! zOkO$Pee%HayGx&aKbOfTZ=V>pSll!9&m(8Hl2<<(JbrX%_FQ}Zi=#`;(Fl+K3#aK6 AB>(^b literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/surprised.gif b/images/mood/xenia/greyblack/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..16efd58b04fca99aac4447bdfe717f5df3cf0731 GIT binary patch literal 946 zcmXYwZD<@-6o#Lhov^Fqi*)l*SagGtZY7xbBT22A#w5h72{fBjOo}#*COfS~T^MVr zSe;#0)5MtkNI+W(*%peTEtJ?;#E)5NYJOO(wn=7{g0=?zV?=0SGLmw=6MEntE|+uO z^Pcyd`&6`j+oOXaLO7u1Y3WotbYBSgdU)>;EiZ9rH(4Tole48^G(qE{%wJm84M$)R zGWiAF7#9>S{=`s@%?AA{`L5-`bcfHM4^guD6pTpv%g|RYlxmvPZoEuRk z({LS(+MPs24S#vTvWKR})7ON32*dScs0%kNP3cB|E6ISpx-dUl;W}6r9EUOp+*GGh zE+8wASCHkE&EZ~DuVD|Z;5RaU`W8r5q$#?dDKz@lNg^)@c?jtWX;H&L5~{H)Q2tSK z*ZU}jT^2e8uaaq@Z${;^7h2%X09irP03!mY2upRBg$5J?0*XMrc>dy zJQ$0-hBIthvs@|`pU-)#WML+FJ(yxW&$O_InBOJcsLx`B^f2}aMx`gp7J9?PIu%8E z;=IqcR}4cqK?;GP}G~%tutg4a-6`OyO;65?@$>%!8{qSGk(f2&K0&?@#yxlZZg5 z<6P#ucLJO80wv8SFQy9afBLyx;?%{Xg+U73q?>%|X%lFP5 xd*@xVP?F6VsD z_k7Q}$47_zo;wvGf&*HeR+uX+)oE>ywtYK$a)!avJbalFiNC1W(lC-98a94mrothEDgL)Q_-MrEuZK}e^#qHOsb=)*jj*OkeYaU;M?_~mLVwUD zvYNOrNU^Ii3-@^{MT}luw1=q*w5DF2cEJdH3T<6dNGi;js+8UL(5UW(=|)>%Oz$B4 z-9!G(=Y7VV9C80$$1g3PT#z#5D@?@ftZpPefk^yv2+{B#-Qv#-_du(n<6z7w&b_FT z1-J)B*Gr6wIDdG-GEMSm;f}D+Vz{0R-LWH^i@Gs2L_T2ete59oTnEd7PoWtC+v>E+ zbz}?jHZq#&k0~X+29*VWW5v(pI{B6Yp?fP0#^fG(@=DwmTm2oI+z36j$k1x^S{bytETCv9#e7;7+_w^Rz#`tJ=JCZ8NEuwkx!u*2M)0KPyg%U&yow04ja*w9 zxFEt$9G#rFdh7k*V<&>S+;;h5v@3M3uXO5o@sWX0t?%!{#}*DBT+kjGh^+tU4u4BS1r#beHpYq;Rb{3A z@8yA%kxr`tG*6W5UZ%}SC3dqaxM2w>fiav-9mE|_AW29o&c$g>X#_hQ=lltecN*dK zho&b#f7a{qwSPVR`j>Injg1p)(-&*SCXtyqv43mbXx`RNe<=@t^WwIOd)uCzc`N)% z*@G=5RX@BLK3TQzq1!?;Q}xf?G;oX7ID0yB#69ZrCT2^UUT!$qcwqd`Ul-pI$9B#g zUV6JtM5h`ayYkW_9aHsl$GflVdUtU)`qOK7Z<_h-{ChQ@T={OizwG{xpPq9a{3n0M g`8W1&UdZsXZO><&_TIeUp}%U*9>4X5OfPr-3smwrOaK4? literal 0 HcmV?d00001 diff --git a/images/mood/xenia/greyblack/tired.gif b/images/mood/xenia/greyblack/tired.gif new file mode 100644 index 0000000000000000000000000000000000000000..444bf0c1366677781913f37273c8f76c39480c4a GIT binary patch literal 938 zcmXYwUuau(6vscmCLuxEWU|a87~2dRma23a*fHyn+SaZAV9hp0Dq`nIb743QUh8yp zcvAzhDqW^Ns7x1zsPn(N_CnyA<(gkm)S5si ztZ^Mh{YcPs?JB7%A(atX{J_%iTFl{gK^r9(jd_ca4YZUmgq%)GS=}JgG12BiDF190 zX{Wd)NU-W;3~te$AcC(&bcQGkoa=lFoq`y3iB_qQ>!n{NKzhxCPsX`XpCM33?;zaq z9`}5wL!Ha8$$g{dwseOzZCMFNZa8A36*cxb_@l?Xh^7Z*uUuxJ1A>xH4RsRwC1j__ z!6K-)cQGuY+_sY|yXoDYn-j)iRMVCr{>Rq&DJe-0y2qeWE(XjbdKSKhyO3NW>j}PE zK?L9mJW?PMN6s3t(Hj4z=q6bq8_3~ZEH!a9s)3QH%-I2k#ZUHe(r(1%Ed zLplnLuT$(Mc~aKeV9RiSl#<}NQSySC7hO(Qf~`md1b9Kd*na8k%j-Lo+TfH_q(q9skSn_1Aa#H7fN^TzUfW!T~<@J-HiRF$%8qjYa-)G`wzzI z)O1bPxP2-e$Ghw%6re7{ZcErB`_vY8)R76L_A_81|6_+VrI-R z@~RpH&t^DE-Nd0|-4l+U>dK%huR=4fQ?@WI^mo_RV#v*C@Ij&bW}I5WhF|Rccj0JN zHBEGV=tS%A0(({232lo6UbB+y`~O~$Iy)i~qztCyywP+@jo>NU*?+?A$s;`BzO%)P z?|Ifg@zU(o{aW7l=zw$G{sYgy|FCP{%-fmAUzmQ(ePDI=cxzui7@dB4 + +
+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+greyblack/
+redblack/
+ +
diff --git a/images/mood/xenia/redblack/aggravated.gif b/images/mood/xenia/redblack/aggravated.gif new file mode 100644 index 0000000000000000000000000000000000000000..cb7a4210596aeeef4fb195abfa598649e3003387 GIT binary patch literal 896 zcmXYwUuaup7{-5JbIQpiO@>SV1O|<$G?ijkuw~9-YqF`ag*DQPw9Hkd$pLQ+eCnoH zJeko@b=!pq{wXYC{c|~_x?W7afYDGGxS6)6!kDgJxC_Sw2WJNg$M4j=7axa@=Y8Ji zdEW0lm3{Kyqc6mXyrt z->~Edf{yje%x{s9%;@I3brDXdLuNZ=kZXHXOk zab1w(wm|`|^KgzN)n3t`;F`eLTeavHq}kDI%@~zovKj!z-4kN^yD}GZ1aj^s!aR^M zHx7klt3;oVn7Ts0!RDO1rDW2$}%_QP4NRxqbflzG2IqSX7LgZ=PebTL%|l z-soLfOt^P`Rw~ZPWnO;~zQ>L)hi|3|(OJGJ+t$H)>W5eKgE^~gQL>BinbZ!hvX!lo zqIwdyfcp0NwOFb1JHml5XP(CNDKFcmv|*j7<0C_GW3{g^maOI`dLX>Cg5w~img^4^ zTHuC9L1EkpCo)^+M1Z%QUupPwKI*OAwK#e+n*P1j^dDomIlT)0JpAwG!j|+rl$u<6 zU}}?TsfS_@=^?vShvonGg3dXV)Fch?K;7pVIwN%6x`Kbg3_phm?|=Gy?TNR=y$_A% zr#}Djok;I9ky2^9@ov{(bUHO|H_q%8qsH2mFEZu(v#&j}XXwkdk7BvvN=km!_;lpx j_OZ1OAN=X`o`pm6i$m6t&mu>PllM&bwZ1k&Z9MiL=|Ks| literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/amused.gif b/images/mood/xenia/redblack/amused.gif new file mode 100644 index 0000000000000000000000000000000000000000..d40d51073168b2426f403d72420270c9f7717660 GIT binary patch literal 899 zcmXYwUuaWz6vscm=7t+an&_6=1{{q;Y$9VuSxR+kyHqw~3pV0I+6Swn$%Va`?dQ-9 zWj9^6&`s;h1``WL*8TBKhSNT5y8)w_Ak$IX+kv>*$$U{POo$hRyWg#zhr{ppM(3SNQB8A=$8DmJ770JXSlS>8 znz$>-@>nAecX=&Kj7q0SM7bl-R#XfUf;3MRS|dz3MMeccVcA1ioy((PTOdatBJ^ax zKDWguXNz>{H=DX^`P@m@&HBniF}q;M_$i1aPlgb!&&e9s=~Ml6C^}8#IAkiQl4ZCJ zvay>TBFTL(IJ}3{*7B^d4peVXi7ksvTPf9g? zZ3EF`=ng7A@FYn80s|5-?cb@pI4;)5%VV+CWEA}8GwHv3X=YVb{@L;0{ILb;I9S%; z)Y_qW_Ijz98&$z&tHJcMxuA6R#S};#9L0H!qbZHxRnK{ULJ#am1Xk}nUw!iv@#6Ze zxuLU{KMi*73Kolt_0K~7v7>*W_-cUI;HzGCfUF!A2ES59{y o+;{w(?Arb1rUU;TO1!`B%H+1pD-W(MeShP-)ahN@I#%$;|CHDYQ~&?~ literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/angry.gif b/images/mood/xenia/redblack/angry.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf40fb602fb17d98bd5712ddf11f08287339150f GIT binary patch literal 911 zcmX|=UuYav7{z~gX5x&H>;|3uStw*hv6~=G15K$KOx!K%CIPb&a8uB%$<7u^YwLr3uvBPaJ5U(!MDad++=ug> z@0|19`)vA|J&zwSF=>IOXr+bHlA@X2=7pRy$NDSW+DDbdUo^d_Z4blHM$op|uBy6C%dKBj4bb*D?@lcK*3Vf{TQ z@|w6N$Z$s^2iMqZ{V;}|7k6(i%1BbUhDW_t>G89;MOc9Z?7L3U=v}Kr z5Bvh%E5t{UUgIHK`&BAB**e9Z5|PW54m*2~BEfkP93k*U;4;8r3es5EtB*~pSO$|| z(f$UNB-xX)7YEki)+|-QQ?rx>tq5+1Mm5H6ox>^uA|U;Sb;p^PYBX0%sU6+2ORS~lh9O$bLZI(Jp4KGPmlUK;o3(D?k(Hy=%X8aw^^vG32l`lG{>{{ZPv25A5Q literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/bitchy.gif b/images/mood/xenia/redblack/bitchy.gif new file mode 100644 index 0000000000000000000000000000000000000000..1a6d6d68e4cf3e435c2c96487ab738fa9ea686b0 GIT binary patch literal 896 zcmXYwU1(cn9L9fd&nYKDnhckILYR9I<#$;1t>ug3Z(t_5HCI`GRaMVq4 zc(O%9{n+qA@S|)I>&NAg>Uy#54J;Tc107j=Dvar>;4T~!HaI&_IKHRuz4-HTc>d4- zd7l4ypUgh7Yxj#WVz{8U>GN%RtSbhbF4(iQUg7#Qb&~(E=0q)P7=|wT?JKLMq+gI`L$NiZREEha02DVXMAf}A6LkdE%r%6u zBV(*QqFJpHea4Dw_)_za`hHHUOeCD5X(c~{*ub#}qT{w$^E@f#uSdyou?|DFiW*sg zOJFshWsex(?*JU#&+tg4C7c6TUJ%2M3p-clR3sT>$f4P&b$fYa8I~Xk)9aK&J?ERy z4ZlFw5{Xfi*F?Y;{+*gZzDc>eLgZ4d!^&?^#y=(e1NffsB?G)pNf`@zKTVB)fKoUv zF$up)ElvJ}>cxf@T%VyXcx;BMz>Of4yE^PdF(4oU>Pt}9Pd>kO*mTF{Bq`(V6RdWt z-~!BBy^C{k_tsBR#yGgZn=iqS*s+DswPYbO&39$n+*MDWc}@K=$D}Pvb}=@U+`yH# zv=vfR58@V(-@mXNEp`4tC=lk%(wIE#W!t1OtP*v6EDf$M^%X`F)!bMQgyt7<94t%8 z^#{=oan++B(Qg^?%$hM4;BBWx!^iWH?`*EcQJYcp?=PkQ7{$%0Rq*GY8>@%bEYCyA z@%il&t4vyIDE5#VvU%#T@c&*=Ico_;(f|+S-JY&8g8PFKya^-p93r&ssgt$GkBB?( z8_7?6dG6hC@6+K@X}$4Y*I;BanX(&4w}=sa`NCJ3@;%u%9=>Df>*Y_Px#D8d`lj*u nLsR=3yFdPG-|>MX$G7Jne0lE|;k|b~^Ye|q*0-A0#-slMv4aXT literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/blank.gif b/images/mood/xenia/redblack/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..994795c19b4bdef85c22774a44cc020146819796 GIT binary patch literal 874 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 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/confused.gif b/images/mood/xenia/redblack/confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..a70a9304a7db39cf9bcca9a7374b5de1017ceba6 GIT binary patch literal 956 zcmX|=Z)lrU6vlryNy%Gj6LsmIKwVRmF45MuYRcSXlw{PE7T1h?X#2rVX%ZZwwQtL+ zIDFFuLjALW2s+4E)Pe;OO6b-Nw!P7X1!r|`Y5PVT)z*Pu98(-*k;&^#70-vmy_a*I z^PK0L`)ptD&Zl2!qKOjNEVjfRsm}+8BjH+#Vr|_cw}$Q&s)YwPIGSuEo@n zK&MIL2V&~Gg4&hu87tye8Rmbx2=4`~_9_U{Q$=giWVnvz^(D8>X2$N+iD*Fhst~c? zJ4DnbHUuH=*oeRekB9J(Y!*H@>jK;T$rwICfO`@x?J#FwPEpp=398t9i^cL)OHg$B4#M?+I|VA9o;X|DzjQrbqVIDCv|?XP_^M zESZ2Cpyv0pSG4nMCD?fY|1*h#Fb<=ZD>8Im>t3Cek_6EegM2RCP#!{$!&&gc$R=^6 zaXAkSa24vO@r04RdMao&KasXGlqcShz;Pp8s}9{Gj=3bv!a;V(xNNMF`%%xp zJ4l8DIx%WqB^_Ysl*~ng0^A-YE7&tiQc!ZB%kHw!jYL3z1LRA^Z!SE)%^xfE&+7Ep z-#o=ygA}e3^G5UHth;pgvaY+Bp5yfw;S8Exca{9Io+()pNk@3piYJx@jRX{VYkuxcq=x=R}#gLPc@NZ8CehyO#$*TOa_s_K> zMYUW;*9TIM46YHbq@s1nf?Jk_xqs(^)YU72>P*VV z<~Q-K*RH3|Wm=a{J{9_FWq5-APurTeKcs!&yPjg=yUF|BKXl;a6CZX*t~}ZD?Pr#3 z;O}bJ{8yRC)#s+Joc`SSXla@`#8q)eFYs5t-rbTQgO)m3`mD@3= z9o}?-Sf^I{X=8;2)(=}hjXJk5rZ;La42OS6+Z$n2R|}$SOxPg3Fu1;{;`wlR-v}hIEjga$6-}=S zOqvaTLDN4L)GhtQXoaB8AphG}@JZCIdZ3Sphiy5B!3J7ZF9#LH(e5>fbX2r^5Zd26 zL|PFy1qtpcq~In`CJ2#h5$!=%1xkHRqg@c?zC(Kv|BHav0YuRs*dS)K6RXgJG(z*r8PZ#3IZL|K1AJrbhYb5WPeSPP8EF;VmV~V zEZhLS^b-A|gFkA){+H?AlPwGD2)bR9q4VdS{7>jKohM z8OBXCw!BR~O7e`%#eg#08Kx-MJ4{Yc^Y44 zu+k`ntHr$6a&anH-T2Nl1H3!O(Kq1|Mqti+JDl$)zduk0Xr4An-)dpA`2Dh%j=VU<~QupP_~HpgPg$w>H*3en$ssU~Dqe(%4#a;&1; zHl`V$ZQZ}Zfm$j?mn^txMVR|{E=Zl-Aqlbww&eVntw@dFiJGhZ3Dx^P!rT19h5XmY zafSAr8yopH`>>~HVxx1d|HDTfe4vu-I%`aao^lb}+4{{)*wY+8wJ>r`v>u#kZPJbS z>7Bj4i9>fE|6#^;boJJ5ef|5B;o}Rh&yOD(IJ@_qeQoof|G9L2+v$f2`(AB(@w3-X UTp9oCaN8@>k!R;U_4PdS4+@bN&j0`b literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/crushed.gif b/images/mood/xenia/redblack/crushed.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf10cc3a0c414f147af728e2b611a3ec694f8832 GIT binary patch literal 909 zcmYL|Uuau(6vscmG$UbjjhnY!0~xJSY}yJYV7D4&?b52N-MWVDA+50J%pV*G8Nbd= zZC%pcE!$-4gNT2qkd6&}99q{tRBq8=6bmX{dn?qb-OJuAI=#Cvy#8)q_Io&-b2z{6 z`JV6Z{9f#Tq3fAfH8d>ndc69CKIQRh4cdI>LYjleiH-0);W1W&0cmw&L~s4IWjULZ z2p}}iFaPAERQ|1>qUqJfptOcDU=rG35wh_b&lczfWlPTDaDBGvb~Wg2cXHGV;=;}6 zHasHh5r05}d)`on*ruy43-%?6pk$v^A1ju7fAQ+ zM?FLD@s5RUD4lDeoF^$&Jq1{TKT|9S_NFKatU8Qsuz)MkNu?Fkfy%gc{RWSAVhy}( zQ1p#`%Zi5l&ndu zzA9~74RBzpWoU&XQZ=OzRZTXJDtfq{)TB&A1#B=Lv%N|qc+xfQpYZvQBmANLH_H3Y zdUmuwmmHe@=3H&lOIkj^UO8XqOONf3+~Klk@5F(wjp^_7)?Hhlwzp>nKA`1FZQF_K zU(;|RKL2`jdhk+o{9kS3iqw-TXa5K7 CEf&52 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/dirty.gif b/images/mood/xenia/redblack/dirty.gif new file mode 100644 index 0000000000000000000000000000000000000000..3325b8d6fe73b54c8c171e5a2583cf9769feed8f GIT binary patch literal 929 zcmXYwUuYav6vlsdch+oewFD=dEEG4DCE2X~vr1B93??Sqm^HyYuR{PQ4*k|q;nAJT}l4-o`~$%1sevw9v5=U&eF z&N<(A?~AFP)@NT+QE@==Ddr_*)~Bc;wf9VY8}|hdV3F7ko3^X#HNYL0^^F1D5mFCqT5+-v-GvAG^R^VziZ{(t1&l?IXGi$LXUZ6(U}6GsRAG zkeZJW?=YbRdc>upIm!tL;F>gJuKDZ>lY03mRv_{7q4lYp?kr>Nw_&+RIpeePlOFN{ zjINTet=p1F(jpKpkxd}dmHF8hqzIW6@*$JeQn6OgERa{-Z#vxzIk$Y)wf08oWZXda z>Obye8Yz~r~hd9XEf@12wyNz{|>li|JD zTiAB5uD3}|k0LHY87#D2ME9oA=j9vruPnQiU98E9ERt;9fGef0tprY5rei1n+PJu> zm&;gI|7>({gW(Eq##42&i)V|l17AyBJl_2Eo?`zsJ6Kk{sW{|0?@v?(-$Mis^jTvD$X!xeqlRx%lSNq6Bab-HW Yzaj9X@kGxD>WzmFf3k4yw!w4%0%;o<0RR91 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/drunk.gif b/images/mood/xenia/redblack/drunk.gif new file mode 100644 index 0000000000000000000000000000000000000000..591cf488ab06ea2f755b021d2b53922f26e85997 GIT binary patch literal 902 zcmXYwZD?C%6vuy0bK}jRO=PAofk9&#HVy8Lt)uF&F&S!Y#b)e7+7Ihqnq1tM1+KCw z4sW{5SnV7X5gmm^?FaofWH0%kK7j>;Qc!7|TcJ!>C;DMygNtAjdW>X;9 zWbqq@IU{IW`i03AA|_)h`H_7OXOceM4=ECUo+`PFwbOm=N<`CK<6gVSB}JbfVcgj! za+k-t^a+wYRA}`O#eRlV0OZy^gw(k>5wZp5#4Uur zJ*6){>oXVg^y-bK?n?#nGspGtAg$5RRV>BHA92H5N#y{<;*MCgv0jl~5&% zunK1VHTH@)e|y29ee~}sE(-fNrsK)5{ny>g(@K&QGGJ4$l{=jbvH%r`!T1`5K-WSY zI^k#Ns1O}Q^&0iiT7Rdklc`haED~HTx0#uT6mYKy_c*R2TuGca$*ab^+)ooDAEFqJ zNDNw!QBIOMuX3?q5pGXV6+AydNze=;Rd-d`jY2>`5Y&t3*Df4*qTgr^PfHT|JLhS1 zD&f4Cx4SP+N16|QkTT4PdEPnX`I zlHYJSBubaORgxV1k$n3Uffhx~o}{+lb%uPB8x*tHCCn}eRC*bVk{(tR-MNcC+rD9% zYWmtXA}7%uRD9sUW29CXHUZ0CqUPeb$amMrVynq0_zx<{KL%;0RaO4nd$)0N#dI8` z9GTlZ+F-wzinT)(T(>IB|34R$&c3Jusez+7Kj~;nBY4_#-k;C|M-YKcFJCCXa7t{9 z@5zjQe)V)~_baXW{95h34gSg1uEde#RM3B7VPN))YN;pn$*#!km-X4+EkDil-R-f? tb-X@%v$ApR)zdwv?rUG~`zJM%IP>r3bG!bkzrQmQ{5WQ4q^ZR literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/ecstatic.gif b/images/mood/xenia/redblack/ecstatic.gif new file mode 100644 index 0000000000000000000000000000000000000000..a429f3d2dbf5c804a1f04a85b1e98efb76fc237c GIT binary patch literal 902 zcmXYwUuaup7{-5Jb3(F_CjLp+Mkb9=Y%-*4(Uz)Xt?AI!7S`x4(q63oX>!1uMLuOy zHaw}(Slyo+1;xTrtf0FZvbi#*U&Lr83^(oCQ(;V3FWiM=0}E#dipTHNeHSkuhv$9X z=Xu`qJv01t|Kl&liQ|CLWXv`h@hx%SeBPR3@fB`OP$Ts>D|SrEUg){v1(%jh=?D~C zEq=q4M+D7RE;F@4LNczK@1AerXeJN}!VrT&99x8aZkl0Ey%F0*%~p*y$ovr6gDcv^u0V8vjuYUCL+{5 z6k2*BAQy{thJJNIo(g!!JTDt4k0tGbDN~<7yz6)r(R^2|d67ZwuT9Hwkkc?+L60oM zRgjH6>=Ir4<%46-(YvF(DC`4B*N>t5m%gPL9mxW_hP{!+?u2&*f~i>;6zc{T@Cus3Jr%~U=*!51aV?60N1c}@Q?$CV|DRv|u~TE|hA zvNTdu4&vldU%l{Ctk`mfurJJ>qP}<99d1(EuujzWkO8={(3u}dRuo1+m>Vv6g>h$dVrV5a;^Qs*GIbBvL%p@J7F%yd)4#uv`C|Ylt5?CFyZ%`|ydqr} zrAB8v#+KPD^-!!HJ!Iq5VE+HTpmPo+HAx*@P!G9=&Ilgyi~lA<;g=ENt-DWEpL$!| zw{1smZ0`GaBJIycipACXyV2m(q21k|aa8P_9__z9ccI+*;O58Nd-Ee7(Qz!2e)aPo uKJDAT@5q;9^OrvCkpHf4>M<|OJ=$|_ZPWAVpWoY)c%XUPnUmjHJoz6YJq~05 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/embarrassed.gif b/images/mood/xenia/redblack/embarrassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..83a68e9d8011d5fc7076102d17d8290d9e714863 GIT binary patch literal 914 zcmXAoU1(cn7{`BaKDOdY#d-P#)kG~#JX9Btxu5~u1*oGCCNi}p$PT0j*?8}&w zjh<}LGR5^m1_}i;Wiq_Uz}c~@Q)cG8(ALp3r$R2a-MEVh1BKHAvg0}Nxp;VZ_&;C& z|NFifKd^UTRzbmnfG@D@3n*<$)fX7gh6i~dcnqsVAF^dSQnmtBht1lgv;;=AOV9kl zK1mvefA@It=2&N7(#aia6$g8Sn;*+PdP8Uj z#k~Z{>3;%~S*GqWlO#*|m{5;!bC$q-IXAD0*&bvNdE3br`!aD}h9ersAm11jE~YUB zGQEL_#73>nK|^j_Ad;+E6ONH{E<~Lq#i=Dz6Ef;ms7s587aO&LMexEhLUpM)3-NLY zb+`z1kRgZRK9zSMh*PAG;)c&WxghO57{S<`-p%tlX;mKMCJM#$?(5B}u{ zpW%un46oKlX@L|JAiTzdHXff~RWOuhQD9ADEq_mTh00W{mLgT!OZFL*tdKxhR#mxeRS!UV&s`8`s}B&iHq!R>Corr^sl<- z)+z%ZM1H$C^wN&^PJQv+t#1bA)UF#!&z;N9r}y`ssvf=lz4F4d*$+2WvmEgIcx+P9scd^ppux%QrX*<`9LenzbBuygT7;e9^- zzd!G*$^Bh>-wYAL0j*A(tkXhULcrCmIZpL$9*i+Z^gb(glaza4_bo5Dw49fYz+$V( zZ{+3Yf`(f+7+)bQ8CA{y$4_u39?*l(M^BLLWslJo+HYS8YnqpT)FN_m5ep*n|LhVu zP23fvc%+eqyR{cn%@Le-VTBnHh>c~4L44EWU@r>}C5vPtLWZ1(_}d~)DwSxmK_>nt zqjv~>iGZvY*rD5w?pXov3(rdhN<$GlmzU9RAQY=L(%j%Hw_s!uq4c#u-Z?K%^^)}K zqLg4YgA@lr#1en0jfg|AuT&NGair^G=(yRrG@+36VHq|H^OaUNja7tMh{9NnqS3av z0IhHxw#*XgMrmEYy#5Xqo%905))I}Yl?Iu9OcC#j@Q&lT!n2g{_b3RY-}`mX;AwRs zgBE$}-=PvGeL?kNLKPkyVNUS!5y}Fm5vu`ZADyTP2xtUV@pJ9c8_j$2&cK94kN#ne zHJAADSjItECIvGW8jT*q$(q*p zTy7HOAD#d``U{1YQy6vXFngT&Vb4tlEbdXtVwaH$v@yGb?g*&?b)q*p6R_=jQY!bg zU4&1fyQufZT9CdK1|(qGOU!$?9@a;&s^%)U)%ee5uZ-Py&sFs&+SVO zOzP-P`aAV3m-S$-H@TcE>%bCF56Zefx=FeY-x4nM&;@Lm@i<`UOJ!d?eUOe~0 oE4Qz%bxi+S>Wck4nVcCv@YRN$PiNmc`)qY;|AqdRwvD{>ALSkrasU7T literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/enthralled.gif b/images/mood/xenia/redblack/enthralled.gif new file mode 100644 index 0000000000000000000000000000000000000000..7338074ccb44a0def05af9fa001ccd9876385769 GIT binary patch literal 901 zcmXYwe`s4(6vscedEteUCOXr#fk`7&n}~EB+ER6{G3|6+3O2Go(*Ci|(&T~vEOM2p zZ1_^6q1tWW5GDqeVTJuUWIy_c+Y2lj2V+jV=2aNe)rtQ&HgJ$V7(DN*JAWMRy`1ws z-}61^zCQli@QZInh|mJ9O{=tNktAgevL&$C zV)7e?ToiO%zsB4eQOT4_eqNEVw8JCBFasH_E^~A$vg*YdeXTsPw@O~&lJA>&^`r2l9L(ea3^afPJnuUpY+A?IPdj4D}z z8z38RFedu>+Y1iA$>8?Vim(qL9Z!aVUxro}lq92A0h>m>+T~=iim(iEm|mwC=)Tf` zF8CQXFB2O<^&0cgg1=MM$u=li={1@6vJ6YQ9wENF$WRChHPLLnd^1nR}}>!TJ;0c;t zN;og(!=5t>(bj_>Ei1zNOMEa3=P)BnfjjYBXqr<+(-^MBFTAT3=BQDX-O3rCZQqts zO<&te^bop(iVr+!XLOCU1WfxHbr;9Q`e+{Z|27Y;Nyovm zCMvy?P4;-HnA=pr4XeS@|8qg_}`O3pIQwE34F>Q0WJ#L_Ptfhlnf_pGe;5HkEsjBtz;hM?XdcRs0=+~OH z^lv<^l7h|^yVyWe5z+^{rK+OXBZ3Y;Nhe1NW^|5uXX6^>LmX7X1UMQGv;K#jFTUjG8CZ(tT5kH0kOB5Ku`e7oIwO76mLRw z#!Ij>51XKRO*-3r41p6fPaFAFn{jeNt?Wm49{6?N+S!a+E}?HXpj4zXY}0cSR^~ZK zE|Y6$ye>0I@j_D_sdhxX+CQ}}iZHxH&XZ?(v)G^x&yjPR--XSS8M88O>f3yT$!e%p z{3l`FMUo|Sd8oBfoM0Goa{481dAN6idBHO&3W9P1J!8>FJDk8`W*I#2GGuOEitG%9 z%dzu14K=6cSa(a{ET1>LvuB&iTR-c%8_h@dkTrwmX6rA~4{YONNXuxAfithlTvJV& zP%bLs#ehOtXtJZ95Z_uhx}s&ph+L$*X!=zn9V#W1O0?Rv#KBNdtv#vp)80ZnCe1&m zXEBUkRqc?R?nj)43g{?Xh{%Q(v-~yVcS1; zPQ8Bc%d78)j{V_V{P1Q(gq?S54-ck$&UM*+k6l^4u=H{5`77swm-jAwH8l0e{r9

jCs7;Hkt+KJvleWm(6krMktP8V4ZM^2 zH9VQoP<0!K7g`ENnHSy->0B?Sr(?k&3{=|YR4D4=&>LlngR>)p<9j-vi|69ueLnub zKkw1>69*5Sh!MjDtxa2M(_-B*;7Z<_XYDy|&9O@24>p}nDfh$hx*y(X7Nsk&*<_LQ4nUZ&FoaELZ<^V^(Q%f zNa!1c-^uemJnPppcAX8xD6VxYDuymt6nTvgImX06&yKERp3UjJ5cs<05t&t5m1#Nw=O;t-CuMk7HmfK*IP8B z$ZZg>&MYqo_YSsV^710DjG+Ko_5~xA$miw|Ws8HWsjp7vT!d{=vI?=;#7W$|Wq-k! zouYc_9?)mMrPOr>qfH&=%u}ECy>!UtCY3x+6{$cQD}9WZWG2*!{?c;Dac)Yf+}8$) zpGNmk?~OY<7~f<<0+zE*-N*B>-+(POSGldmzq6A3Wdt`9*!XMepXTXJ>3K@PN_xHZ`@AT~74_#Y~pFdase7XOs#pC}0%rp(g literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/happy.gif b/images/mood/xenia/redblack/happy.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a386b34266c98ba727fb1c0e5e7bd2e9056e08d GIT binary patch literal 902 zcmXYwU1%It6vuxzJIgGx+4W=6WT7Q1M6+v(O~Hg{LX&QaZA_rql7~&e#%gv4`qGuL zRHen)IChEl<4H&{kS!*lJ{9Rl9<;O4)vZuyWt&WdQf({Pm6*Y}Onz#Y;bbbH24RqaATJj^#+zupeJQ3Wp8lXoN)vqxi`)iSO>KM~7R794v z;1(Fwz3dVl{Ot!v_tDj7)r4~d!}Vq8{H=R=MoKb>9df8vO3iKty8ug&fQdBkqN#jn0ik+@#6<_VNTno$eTHBJRxsc z)Bc`|QBl0$uaeC>zmjj7Ce$E_Ia5@|Ja;Hya~CU%Q^aV2&{8}7ani$*qBnOw;5c^; zLr!1WM(h}>i;NFFR2f`l*Z@qYM#aPRus_)tiz6o^;XhwW{n<}FEvxd^uK!k!ts1V2 zZI8^gjjk}}r($lG1vjh=3s2^P)Hx8BAQf;W=NDZ?Y6M$-=l=;c^d2I#dC$4h&QHbj zuk>X`&tCZ~-1=5HpI@sSj|8WV?&OQpp#JB5#M5jY)BKE!xN)(mvQZoBYrh19xLn zoc>ayv05Ee5GTcE+6Nzp>`xzbH()SRDsFV`uR@u&4t#M;Tp|0x;OG6-orlA{mvg@7 zd%ow~1B1`@J@ImsC`~Y0jM)|=+7Si5%i9wyy~eFEY9#(<)rm;i3wy44!Q~Z8HU)}p zHosxXX+hhyD@?2slZ@)*dv*yvP6x~&WJm>hwBj+^PWSbTF~jhz&2~{pi)0XC{j*CH z46!cAvT2Zqbsoil4V!} z*?55gk>oEwIPxOB`^!thIgWIF8FpXYw>+gK$)G|Gje51y&7n%L00|h|pcLv_Y(OXc z3LOi?`_a9|eYDo!shZ>(lse0V*Q#wYcb5|0Md2OCbA_i!a*U#G%+LKiHT)5p;jqG@ z^>wOga&tNt8bUt)5kq?jYP06V-L_Y*Dle(b0sy|e{y5noP0^b@7jT>#QtIg& zyNI2{bkXslJ3%t53`xLtmZ^KV9_pQ~u{e4%8vetD^dJ2+v$`sO4%}Wjxhh>3rG{r8 z9$Dd#pNhRl7u>QM%>O?Zw9bLJ2C0LqIX~nYS|ix$JO59Zp(BXUw&%`PpLth2uw#F2 zi&IDZwAGv6#UaRH^P|PoVpJiQy0tvgX?>%cs?B7_vM`D zJm)#*eWY*erp-^^iJuxM4N7i2H`Ac_*7!b886zz2;rb9o!dIzSUS02j4NG?8a#_=B z0+Tj_pV0IvLG#l0j8q8d4D!Ey3DZ%R+6XZsjjYSt47SjI{&YZ5Y^~ZN(oxaTh|vD% z5@|(T6vU}2q~Id=#|e^e7aal43zXaQ8XbZtwt zg%Y&Fcd#ZyFoEnf=%6+IOhF}CBHNn7bFR>=CvTC(J}vD1*mYr>bn+sjvN0$3gUG;} zNQMI@8clmCL`fczxfrkr*M}(z9v&tysCh7DcSYEUL_mNC1!6W6xJJ52UtFsZV|DyRh%K zg^7@Qrmgsd_H|B)|6See`!(_o&)s(A@Q)vEJ+OW6-OYC_r+Pnra(c&I$@e}g=U2UP nwA%UCp0l6C#@;`9u>0Oe-}M|{JN@iuBbB2s-PqCO=D~je;V2=^ literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/hot.gif b/images/mood/xenia/redblack/hot.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ef3e1e238c9e71dd524c3f0cc7abf41f285ec2c GIT binary patch literal 985 zcmXX_e`s4(6#j0K+OSsb*z1q5YPwRI7`CpPZP89_FkP0cV@+sqt#%96`W{ncfx9u$ zjlQ%`;~cDP3>mJt44rg?t%a_cg5%a%r*uEs(KfHcPWD5vXa!O6^+DyLf>j4m3^K$sAM)!gF93E@!emK+xzxXC8K?tZ+y1PWQEDm!s8Eb`_JhYQpcE zl|Qx;xs5z%K{WQaqxB6$9-uRd5Qg><-+o-Hfun0kdD}-4)j%Fx-&^@wojnXEN09%= zsR1gqICKIUp9b;N28`K8MyHR#6aC59VKK!z=Cz{GBK^8ds8^I#_NPFe$u%HI0U{g% z@o_48f$)$Uz9tQr2dLXZQ(Yxq7WkHiI%v~2{a_C@H-hEW-dR6;M4`qw*poUio`%_O zW62)TIRkV~B3W8?pLgQs23$pmH-JQQ^P|v-G|+w<$r25d^XXFBoJ# zSV1NHNT{Hq{*)g_!Nnqs9|~GM270CPA%2A}DrHB`p1p?k5T`Sg$H- znYV8r@73>8i99HiSG+O|qVkEp0~rx9n5-s9hXgD`WjFQi`tg`-hI2!69&{O0yptji z8Y&QN;o&a>m!az+N*lSR8$k{OCcq#st&o7OwupRHpU1cb(*oE|D)3R!OZOXK zM0q;&=D)Is=cs9du^j_dkt||4-qcNH97Wg|un3HDT?B9T3ZdA4VCzhWm%qQq`~KxqiASLm1zSID?wI;~ z+lOn{z8N$B?7Dfnz;)^5J0qUZCmY^d_4vfK3u#o-8Fg9HZ}3}+{_nKSL7Re-rw@^#UH*5kM7*PJ^SnI)xCE%UwyTB nICg3GkN=$e?fAOnC{1Om{9jey8|Z(l=7Yi$&)(1o!Ipmk$qPGH literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/hungry.gif b/images/mood/xenia/redblack/hungry.gif new file mode 100644 index 0000000000000000000000000000000000000000..f4d24bd3d12fc2745e0bc7fe74e9831c1841c973 GIT binary patch literal 1004 zcmXX_e`r%z6#ni@LgOkk;Oj4_q+|V&X8q-8!fdAvrnb$hw!zM}QcSDadu%e7c`44J z>q~vo*`XQ!u?;L+5XOW}n$52I-_1&_3Z-?__O(n#E!!;EF=b<~4~B2|WjlWy&b^%b zopZkL+}2RbD?0{W#5U-FU9j7S?W$lG^F?)79TV&X&ww;M>sZoEO7j5RH?gqTL3ILl zzgUSb<5h|X&~(p6mY`4&o&%fZvL@Mr1PvAFbD(>~4E5&icTY7J**i?RJC7VFC;Yxy zezJ#12gt*AguDK-cf5hlhv*BV4da8vdmK|T>?g+MQ(jV2jw24decOzw^$5YqD@gy> zsR2sV2s8p3nFpz;3+f9EjLu&~MffLuugPTdqQ?wF?M!GAp&sj5Sz-jFG7CU30$AZV zh?i3_41~tr@HVNy1Aw|sG}V{kAmD(hq8{qJpq(6|MlG15?#HTy^D@;lU|TdGlZ4SD zu=tRLJPGv8Azo0p!jZVSfg%?oevojse{6Ol3G~b&p08r=L9&4MOd>9tHv;BK*)-lX zS#B8uh$*1f`_BUS2wW_}_+hhvE-=}W4}M?}mNIid zK5!V2S5v{QzJT8T1w%p3=}9b#oH#4zefPxqB7I|;F%e2BVlCDTiinNh5q&-vSAB}C z6nf6S!?6-Y3X!f##P88nJEs*P03??Zt(klZ0Kw&dl)R*a!j8L{|&Vwd_T6^NE zfWHLcb{;+&n}DXZQQE*Ytpzy)7yyH`K}c{(X}9tfZ5bI8h6y&5m4%Z{6=2l0d&Lhu z%+sMY|G9W(i5dnN+dEd;xrnYTZ_4&UUd6IBunv6Bb+LG}l~{`XSL_9YFFdy@%UORS z$9WgTS=^RN{&3d0wY)T)8VH_qIsC=wS8k1p?v|=M_pY=i$nFoKH^Zx~#FO)(XuON~ zrP`fWMAypEeTlrt@zU7Kzs_8)9&GvL)VE(@bWinj+g_VkoB5>X)2Vgm>y@E%j_=;` zt)-4NU+cedqPnu~n`I%o<@245o!(5!mY#Mz{`>2LiQcE9`*O7-hgtu;u-4f9$Iq9f zN5A=AdhgoNiPP@u7uE}(3}lYwMyC4$PgiFz@91_^-AqRBe7R}Y{tF*(f2>7q0vi7X Dnh!pA literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/indescribable.gif b/images/mood/xenia/redblack/indescribable.gif new file mode 100644 index 0000000000000000000000000000000000000000..32c733415f45a9805db5b3d54095db01386459bd GIT binary patch literal 901 zcmXYwZ)jU(6vlsVbIZL-nmD~(8{BM!xuzrT57Mz|wJ|NatQ~9IkhCA{EKM%@#lTgj z(&0^wggW=xv$^Ck+)Br-ixEZfjEAivmlR#i2;;#v zkyFI7Ak9OCEG)A%O_WlH=!$SlpgdJF=n^D(B++VNiru7S0OZy@gyp$78g>Nc=skqG zy-!_uIbhcFbgJ_W)w2WManDN!ibGK+XPB|mpvO;y5G{|%8rMk3{@Nv-2IeHBO30E$ zxCv%$Km8)k9X~ky7TrC?x^NC-y1oqCf7`h*B_-*@)*Nbc^1761%IcklBrQ>D-ya{ZZR{DDBxWb-eEjfcs6l9A}<^Bb5A7(k0Kck z+86{spqwOgM&@Ec9qx}(6}&b|Nze#k%kHYM6N!L;5Xcwb-#+)wGu=jGV9F+;PMl$} zO$z77eA;n-D$-c}(YAFyp5>D{!@RIDAc;F?uo_W!vcbq+)&$Q-zm^YgAEHA3nw&HodsHipnP>^WC{{d4j3 zmY&SeH&?$1wmx}k&$_Xz=r6q;%&$9Zm7aUC>E!C)%l$_~`={flhoV1y9p8O?;;-}z t{nO8OT$*_Az@5R9uWk&jL=J4)H@z`6*;BdRSw9 + +

+ +•• click for background color •• + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +../
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggravated.gif
amused.gif
angry.gif
bitchy.gif
blank.gif
cold.gif
confident.gif
confused.gif
crazy.gif
crushed.gif
dirty.gif
drunk.gif
ecstatic.gif
embarrassed.gif
energetic.gif
enthralled.gif
exhausted.gif
flirty.gif
happy.gif
high.gif
horny.gif
hot.gif
hungry.gif
indescribable.gif
indifferent.gif
loved.gif
pensive.gif
rejected.gif
relaxed.gif
sad.gif
scared.gif
sick.gif
silly.gif
surprised.gif
thirsty.gif
thoughtful.gif
diff --git a/images/mood/xenia/redblack/indifferent.gif b/images/mood/xenia/redblack/indifferent.gif new file mode 100644 index 0000000000000000000000000000000000000000..94d3a8557e482c1289d3ddabf080e3bcaf7e5f08 GIT binary patch literal 899 zcmXYwUuaup7{-5Jb3%fo$#m)3z@$;8O~!B?m{N6HYdUmY3u|;2X)o3}njG+Ekx$u_ z4Nqz`RJRTUQCVRb)<3%&GF>m!FR;uw7;Mr%r^1-7UbqX#3LBgqC>+02_g%bv9G>@i zpXYhc_v+v)y)V2GCyoO~i!sw;#5cu(p9rvl!z=j8&Gk)&NTW$H_ar%y)_t&hZ-*XY;&Iec9Gm6c!|)?kd^UVHRfvx9UD+~w>#3jL)<4W?Wr>nijE|<)aFnGi zjTF^mI0e-Ahpxs-Z9fq9h1nA{4otd(ElL~KiP|1A0C(oP3Vq3HZm0voGZ(RKq||b~ z?F3G6$EBb!9tINw%b_73Z`q49JX{a;{`y*My%|ma@m%(=KAfCh1%L0kzjR_*x-Lo$ z&ukf4;(*jcv3BSo>!%L0|L+Bzb0Dcn8sLI@$~AOGu+1<2n+SyuA;O#YUZ}nNfp}u; z&iu%^%O6HM_eDyjmBvTW;KcF0-CuD^?4BI%T|M_(rR&MZo_8NF41LCy=}7vmudkfx qIdbsidD*r9^QT|`blds+&s>?_RXx0Lb@kip-(=40+tsmwm;M9T6%8~1 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/loved.gif b/images/mood/xenia/redblack/loved.gif new file mode 100644 index 0000000000000000000000000000000000000000..bea0aaa213ab83fd893e66131972ea5dc879562c GIT binary patch literal 944 zcmXYwVQ5=b6vuzJd0is3$)stUu(75vmNX38qA7Da32D`(Ex1U~wn*!wNn~FvJj<$B zeW`(v)vX}tT&XO$4mUpyw{=6*7qKjeL!D{!DwNIDf(Vu=R?-K9=S|)DaJct!&j0++ z|D5}5^qB*XAKk+qDxlOTb2W;)$qjs&&_*d8blF`2x{wG6aDsfP`n5~L4WU$}FQ*f>zjc;! zvlOlx^JdGHoVT)dL)YC*%=5-8uz=>CcWeX_&LJ+OwbX$^;H%f=!p!KJ7}JvO!GOFa zH2rfHTq1k5x=K1Pf5%wk6pk86%ot@cZkbV=&N`U{Mi$irjtM_;AF)13(VDwrGmLdr zmD5++@lIklk@1eL9dxhIrvjR>#G-|1p}(^|7DG-(!k?Ik{2HeclU4bx=b!TAifWqZ zdjH(sBW2>%RJ2Z6aN7zn|NmT&I@^2_WD!isxz$vpMzFu?s(-@nIEirVK71+v&AX0< z;7iv#v~SZ+TSt%Q@1sxW8Xg*6-Rd|OKDF!6+sa^U{qXzyTBrIicJBTD!-xG}?Dt%5 z?VYWQmNze49=$PL6WsCdnMXg-&N*kC8?TlEKhxXZG=A{0;H}KA(~*yJSN$)Z7(U;% lJUjkr@aYx-wr7GFI$|LKg9bQe!mMTsNw5 zTJXk-$Y%V6$}*;W*p_T#lMR!(-KvB-gJF}wt!9~QE-^uuX+%pC;`J#S&xe!ed2-JG z{LlZK=aHs|8}5B-0~^SLQljX6`f!QjDtCPzOLZ~(95*`1;QN)F>D06U_%B+ebMtX6 zFECi2;(OxSyMnTd=jqDf(P-y?I}3v$n_3Eu1WTz&TeQ2Wx;)`g6f3^u7TqCHTZ)MP zRwud@aYYbjNg)PTxI2uObd{*}a9NA$e=kBvw~5= zvZM}|K+CqWRrvY280>5#@PIxm%pSBtQHISI>gW2UB#jt$lkDV3MInmO3!i}xIcJ`q%fQc060)&k?ohC0 z0Lie$AkNws83_^HFLO!3EZpcMBY3crv>@-mklkgV9*KYe2gsMAzdH8B&4GBnx!)kD zzP6wF3MpJM=GCh4eouaR$}n6cM|tIGI7P}eYQOG_IXXDln~FDNd}m&k3$xcqiA1W~ z)$WtGSjsrTDW^!EEUuElljlgd`>>ZtVrCbU5v$N-Gq{Ex!%U-9f<3v3h?j7)q-YI~ z+f4JCrpf6mb$E887Lf7wR3!U843SRGPDpOAC^`5Y3m>J zyK`EhfMK)@Z`?jlq?k&|FAJ_(21fs#3sPsBSAtAJL2|yWph%72&Y~;+3DtfCVPF5~ z*vJ=e+SQw)UymL5N-w$fvEk*hg%E30<^0e~)s1`H)w`A&g3p{Atl9F`N&~@f-mh!j zwlR6Udg>#QSX_Gcy^mY_*ZKc`zHkyk{|dI9lp;4+Vbt z?vO3hcIF3H&EubL8)$oIp#HAOlXuKa?K`~dNbdNS(~EN-_8c?MzW#fOV|wD~j-eOU Y-166HcW_~9$Dg5^w|Ab1=|XV-KW`T{WB>pF literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/rejected.gif b/images/mood/xenia/redblack/rejected.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbd69a1b4c9d1d7c4cbf49eb279dcea3b10ecb84 GIT binary patch literal 955 zcmXYwZD?C%6vuy0Z({C;zPYArJIWSyYda~fleScR%hGIXX~9GzeL>u$ZGzhe%kIWH zar34Iv%2{L1?{9@)y^SBD6X?(s5gU3(G{n*&5ff>mrX28nPB1W!tnas>G^OzJe>dk z{LlZKXLtLqmPcOL$VM#i6nMr9JpT25;L8EMpT&LL>Lo+nALPsuO>2VfOOAIro6szQ zLAB1$B(#%)qNN|`&rzk(BfepI|csww~G-)E?h=pfuNkPQp&N= zhN0bUDN?W^Ip?1uEb95)tt@$(rpHo?!aR&-yEZiZ*t|RA&E09oWnS_a181>#GpWP zv17r`6G(-f1_=sZVj@KM2NH`8i*RcX8Nm~KNDHiD3^`o}nvo0$CYWlagI zW5gindnHe{3{9SZ!OLAUBf`3kVZhM)9NB?94c(Yj!*v6Fy@;evOD6o)!9ELN=nU#{ ze^1>(tO4EloG(g5`kZ@827A9{uzVP`KngSanTt7gyJB#I)Bt80trFCsT4DjB9a5q* zKBJiC4Na5V_iUr;C_WomuijQ^&C#I&y7?1x4z`2w>fN=t+m`fi426D;VMS$Eu8055 z9?faCEeGfv-yF#jbD`+lWy8CXfyw{&g7jGlNRm0QrRMu=kMs!Xw+#1B_|!3kTHQ81 zaq%^^?7`>GM|2%UY3n~8$+sR~r?gCVH(dYbIdsowYU9TjKYaYe@WQA5)k~w1_x@QMI(zz3s(I>a%KwO)mPyz*VNh z;mwSO`m&0j6pM?{5BoUA-10$v0tSOPaU*SSm9dv@urC`MY>-_TT%TKaJ{+Fs;hg{Z zpZ__}iFuvjiSJzCdBajT* z{DWzIDd<@_%ltY~i&>R?-+qO!QUN^(X_7%6t9s1#61#9Zs%f5ir&knHVkn3(Z;gtg zCN2xI+|ek&WuC|qry3JOQ7#CyEme~tL5h0{trej%K}H2YannOYoh$i>Be3!}5c*hJ zU)>e3+9kH@s~z2w0q=Uwdf6>`X04lKMwSS?gEA z`7sA$Cl{ifyT40m@WC=4z6qzWjpfjdL?JxKv9fLMY$SepPc6)%v_;7-8nX#?E7IlfO!m*Z-i@dzes{BIeA~+~>KOfaEHb0!|fc07CWcOvcGhDT?0G$$;ZrwJbG# zZItLCbQcvLx~r33XUYO>r%ltt^^hNLj>S=vQShJFQxTleWTWrq|queDDQEm#f$IAu@L6QdwtsbV-&!`H3{HBMnI+v!xwm?qZM(DjM zef2q?TrSY9H=4R@`P|d4oAH&#V|Lz<@lPSrb0&mneMr{0#<1$IQ_*Q6XJNFADp`UX zAnUI%B6|4C3l8t2e|KqF*vF8LCqwV`fz>%BNeU}qQ?FGzoGexmmLLw3>l6c>*Xqy# zKSTQxu_08iF%K>HI~AR5onl9c(2Yu~%s!xqdr7#*a2?@V^za4+)tHz2$#D7u6vMQI zLGTEbB-sU(iwVncXNsy|&lF`rGlZqOtHJ;Z0RbUUFP>jNci^dhqd7KbF|5xl(CARY zc`S6^2CMOJUsnrr#xh00%tt2T>XtLD zuelf&_y?mvRfR literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/scared.gif b/images/mood/xenia/redblack/scared.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f4d13fbf35eb11ee1aa8c1061faa74e19ef6889 GIT binary patch literal 919 zcmX|=Z)h839LGOTbMb#ft12@?e zhnE_Sb+dcBL1Eb_=-$mTU0%3dz+zAbR71Z?s*nPwCuCz4W7MMf~ zen!(z2|8~qGrdY!XPp1fHTX2?QN1us!poBthw(0=H?M>h#nJ9}i9%BJdJ)>6yF@_| zw*?vQE9Bue&t!;EiHhDZHwDTg6^&j&k`2k$2vQzkL;|3&IUy*Y%acJ%pikaKsQtt0 z%6^aDEV4sgu~oPp)>Ig!I=V<=E&mFj7ITEW;Y; zjaN7*`uNQS2gevVP;LtA7<$`{q5r47E3-0^VN9PzW2xHR&S93I2633UL&?{3y#d|u zBW$Y?8$x=GxorMlsH)@|l)B3V)~cO)Zi5oe72zDiX$!}skGCmGWA5EEiS$XN!nBEo z|1GLXa_8h-3~0i=N$P^&uWlXC?9{ADLVfQXt!^2d zi+MMCc{Xf6_|`N-9ADs_*WfFR(1P!7JRg|g^OB(r*5g-?$`9tWX^5gx2#v=#uua1> zBvMq4W9Km!r@jjoyS~Kd3bUqJ%FeV$I!tL;CTcn89$2sK$PdLTnN$z><}YJe=(?2a z?80+`^)`7E<$)R=UR6^r-msc1IkX+j_cv>?WHXZflUnlD5OzjZ!LJAZYMofs+igrU zJ->alMOK$fF?P!(o2L#7|Mr5+*%Ol_OV9@M@wOr}f~VZ!{u8S2D8d(c=~DIi4?4E& zJdhhb|ILT~=*ywv@)1r39^L8hzjcAR$F^=+8=R6xBdL!fuYWNuo6Z)L<+1$tb9Dr#p4xb8o4@Vx(T=?OPXZvDyeesR4kCSKjKfO=CXk5&`@I-pB>-W}q|DlIEQ-4n- Gc=jKe#}T&x literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/sick.gif b/images/mood/xenia/redblack/sick.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6752b1aedbc718af490e2e116c6e4668da8129a GIT binary patch literal 905 zcmXYwUuaWz6vscm=7yU>n@qj64HS~GGLs=zkxJ*vTGKL@wXnwZA?<^8BgqwCj9iD? znCzy@7V0(~d)kJ>So$FBMYc}+uz3Ru3$luTVtP9ew|0Ur6NL%!O5yHzJI}-6_xo|q z_k7RyoZtTBYyB_3t)bBbrA1L@irQ8U_&IB4s2}0s6cu9suwsV{qYrl7cKwZI-DnCd zx=sE-H$E4%-@ZX+g|NY-Onzop;ERM$^}{ejeqJoOOm+~tdpWEquKu_~uVjoEv0J#khA$cxNhiri{{Q#lv z99A29eMUXcHq~ybuH|!2yKc%?9FN*L-H3eyTKr59(f*9AzQmC1uS?QtV$49Yge+Nv zJ7Cn_WJJWd?*)er&^J)53;P6yJDoIE0Tv+!Q)?6gT}w6S zgzK<%k?0_@*Qkfq_9tbPbd5r1k>H(jyOCa}fO}cECvY9%TEuymyll+N{d#EZGbF)<037SDH*EyqVJ`WAc_Y ztsl4)5~ZKKRkApAm3+qxffh;3&QP6joutp=9>pwn38M=Fi`y8Ck{Xp1-Lnfm+rDQQ za{5Xy;ghHiGCuIc&+rPP24LC^sxFR;_0h&yY&jVTe`+!D*C5T5tjgab|1O_gF&qcW z8avxFzRZM|in&V`+^`DF|34R`&c3Jwse&UpKkq0~BiQaa?@y?K93s&D`o;3TkHzMf z2GZl_fBmE_@+yQ-`uTmWbKOsWoV)r}WYew81ufS2-tTMSmHz-U%MGXi literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/silly.gif b/images/mood/xenia/redblack/silly.gif new file mode 100644 index 0000000000000000000000000000000000000000..9864226e276cffa5bdefc15b020a1934ee08f463 GIT binary patch literal 905 zcmXYwZD?C%6vuy0bK|{8n)q_NHZW;~v8GmB2c~peS!+7xVgoi~AJT%WN|FovvdC4Y zdto;<8awy$MM1H!3@c3hGRNHdLA?Q^Q5e3ErMJSEt{eKrv4Mr`!tnasZs)_{c^=OB zpa1!v^E{v0IlSc+9i28P9m;%%qOa3|uk%)p=00vuQzQNl%TB~J6R`P;7i=vVW?Nvh z-r{!*^SGe%%CF>>iJDBwWMjo+s*B!hm!gW|8LM5QkQDtvgmGt+ zC@A8(Aj7Ic9&?6=caW zTm`f7B0IzYfBV6a-6TfJP2n8CbbT2He;aDeNlC`BHHSvM+U;hsORxxWm|mfz^;~X1 zH~a$Y7Kx1_dyV;Mp+BgqWE+&a%Y?61JI(ApN_dxqcL2{7p3MMnP?U}NxgU+C-$yb` z+ZcrQQ%#aREpxG;3Abmc3AWEr5wyeDvb!1#ArTM|2KnOqm2-O^PZ;fqIh!%{@M)I1 zrEq@C!QKmV(e~XRY+L8e1>SlUE@J5m+O2p#Jk8mXWenHi-@Gmt=9F!TqE*nR;_{Za z?DJfVh{{*~D%rgJ6UDAsv<^wk$x+|qxv7B7P0D$k3T6*zi+zm7$V^Cz-u#7te& zIeldl(IcoXGG4o@GQP}&30O{(x`*pwA6*-ZBPS!_k1Zzu9HpI+Rk^X_-=!nVrt4zc z>G=(lOYHGeu{O(sYgU7W`*T6+9EeGfI=GValdd8)f~S4w{|QwqAhh+n&Q+g#TRisE zNOtnfckhIHUkDY8EA@B7!QA0pgP(FjY@baJ-#PPRx$lXGpLHM2PkhLRlcE0CKKuTY vq5XT0e_s4+=X)bB9ZRRqFQh(5Z2NC@>dU^}RqfEvxwHDl))x;2I@tC<+TRSI literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/surprised.gif b/images/mood/xenia/redblack/surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a874b44bc41590af90aa086e9ab8cc245c5d563 GIT binary patch literal 947 zcmX|=Z)jU(6vlsVb4yZbli`xKkw7BInxfbS?5I;_NQSd(Ve5?0R%dlIi59`Y)vX&2 zZ{n4#^G{Wnf3UD@E27&6i<{e!%^O)YY}BnYX>Wwlb+h6=Y)o{J1qRnQRXiUK@B4Dj zbDr~@^KR^Uvis2&efX$=Qm5z{eX>q*H@i>AwGoP=+!`WJ@CIemrK(*JDp~dO3rV#i zFz{*oN>Y7S&{UdZq>NW(kpJy_crRkJ*F%(WJ!`TSgC6{gC%uYdC2xB~A|l%B5y?M0 zL_!f)1^wJsh{IJL?k7OjFWS8<3Y1mZB<+F-cO_cEh2BMv41mOn2bVnS!!A>x4&OxB zJEQjbbvCt_qRoD>Vz&&N^}c2G+w?5~Gm%t-pMg6x;Y2k3M>jc3SoYT{=~PfN(33@$ z)ZsFyh0SabA^xZZySCExxLy?IPSk2mhR#cC=f|ZaQ4EJkVJ6p79l%J#DG0*QHPVjO z*#fk{MQ9!)5JUDFsG&7pA!lcxK)OZ8c{$gl4%{V;by8S6v8uu{2=O{8*;p<2({SHA zNQQj|Ng7`z7h&Ll%teDD+!`h?SU*fwP;p|&?((n}iGTnn$d{VGHvRnSu4JWm+#qa! z;{XdSQn*^oZvXLdZ{^NUhT&#xie1~`1e$xwaWfcq4)JALOLpgjXI_&FGht{Vr6t^h zL3xX7#y6aBiR`zvRWf+t94Su*N1Y^QjxZCmsy#M?W%M{^7PS=|V{OC&^!G}N*5q-U zX)dd(oW9b5cMtX|GTw2giD;Q#70}F|nX#x^7;mnO#gvng@cYIhOED__vMRrA_TC;0kQt~-&i7XpsS!L>bG1KVcYJ_w_@0{1 z{qUA!b)92X_~6-0qkq$L<c^gH{XcxJt_F7VQ&TwB8$&-G*13x_-QFTOHb`f5(^{P3Q+?@Eaa tlR+c%<0j8&X?pX-ku&>t9348g?c5jJKL6!V`Bc>S_{OdsUtiI9>>m{jDM$bS literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/thirsty.gif b/images/mood/xenia/redblack/thirsty.gif new file mode 100644 index 0000000000000000000000000000000000000000..68f6e864446ad2563b363d3570d0a46582eefd0f GIT binary patch literal 905 zcmXYwU1%It6vuxzGhv31>=wKESPW*RwVg<88fZ$?YS!Ig8xt`r6*hS=re=4fFI^a= zDhbZU)g@|MkWwrJxEV zpa1!vbN3Iv*!T2Aga|cI>(seAHPR9RzRlQ^EFI?V7-fvVSaZXc)eAk#e*Ma-Y1IS{ z?KZz*TAvA;mVah)ji|+_OnzvW;aEb^>LE$Io*hM>(PlcXUy7=#Z{BYf*@WnxYc2~ylw$-pgkrHE1N5S>x33)C$|lTJZ`2NJCsrqIiv41nyWhp;>s#>1|_8oz_k zb|B_SYuq)Uak?u!t;K zfNNk?UtvIW@kbCGewE&Rg(cx0#qt6fcK@<>WmZa(#L-=vA17%;X@UT<5h zLM!|PEepi@k-f$Ow8k5hG}2Y_tp!5YN=;V!0eSpO!as`d3E!cMcgV@cg4{3S!=EA< z4m+4M9-)*VeMaVD!xG#br!07WoT8u>!javTVJ{K^0U?ktfnPuS`qo~vHZ}aEn-NpfBvCKSpXuQuOD}E3SLn zvgGvDZlcp@9x`6v&`GW_WC6DOD-|El$N6A$EUui4g#TnAakHOVN>=6ffqSddYnJEX zIKy+>M^-r)q+<8Tf}2)``TysF)LDs1kP3K`^W&Z>HA3nwE%+0fo<->G2hNsW_)t9Z zCu(P} xoQgiRzS!9_|KsQJH~-%L^|?P^o@qapsJwM@NAh&T#ADM9uNf=fC`ujA{s+9J3iSX0 literal 0 HcmV?d00001 diff --git a/images/mood/xenia/redblack/thoughtful.gif b/images/mood/xenia/redblack/thoughtful.gif new file mode 100644 index 0000000000000000000000000000000000000000..888b28a6c2cc4094f824c3c38ffa4a9d8c347cf5 GIT binary patch literal 979 zcmX|=Z%mt26vls-zWCMv?GjrG$u_D?RuYh*Lhw&aX*U%iV`Y3On23L%HO46V>gbHq z78@HxHsc3_+Bw|#uq_(dWSfbOw`v2cbBPJMOe0BYLVUeNS zdCqgreW>lhmV2Jq$VPIY6e;oHc(O=wlsmo}i1w3th8w-4@cd5JuxnZqG+r=^7Z$@> zPN1_s%8!J#w*_Sv&eNZzQlp3eZ3f1C7PT1sc#Ek?nDjWQx^${iQOxkNQ-pk?wiprq zqd|leaYYbdSz!RKa7O?)i7HWB$t8iZE)k|y;A2&y&Dn`J(Ix{RwC2Gs&+$IHA<+7+ zBh)Q^b>Uu%mKkKTn#rlAZZY?oX225P;Wk2H&GSAu>i5|YW&hC)pT#TttB`bZXv5H! zK$eWdMbPFt*(&P!wGeFYqUrv4Mi@hA`GO2v=9?Erq$GZHtHE4)!j%uA$KVU_K<`yz z){3)p;DU2d9>Lv>?A2XBEB%=XmEasPR~*~Li83v?N(}RqFo!Vn!qlnfWd>zqh1_v( z$0(9vhfbK%=b7*kJRoz4LI!U1krF)6M?#RZq08=4(2PVtfDPnJ!C#$v?3Si*u6;zu ztG;@GMVAz=5c5ja^hjlHWmeZ6L?+q&B%CDbn6zH^4A^=(9E*lqQl8T<$%WacN5xxP4XuC>uX~%AL>pznHA}(dzjHzAY;jAFG~^}cTl0$42|AT1;3m6_}h5VhDVYsQC+Rz3Tn7+hL@`kjNFBkLOfezs!z@cf~2?KWp>`p7p)*I4uZrMs5`M}x&~=Xld^ zKOC{7x=#P(sM-1X_R+3wqs{f{6Stq6-G6k~r`cnzUoI_tF!Y%*^V*+9AC)xM?L7Ws cNoHFep+{%>a?fq>?7p-0llSiOms+{+AI(@as{jB1 literal 0 HcmV?d00001 diff --git a/livejournal/Inline/README.txt b/livejournal/Inline/README.txt new file mode 100755 index 0000000..b931fa6 --- /dev/null +++ b/livejournal/Inline/README.txt @@ -0,0 +1,7 @@ +This is a dummy file because we need to make this directory here. + +This is where the optional LiveJournal Inline.pm C code compiles and +installs. + +To populate this directory, make sure you have a C compiler installed +and then run $LJHOME/bin/lj-inline.pl diff --git a/livejournal/README.txt b/livejournal/README.txt new file mode 100755 index 0000000..df7adb1 --- /dev/null +++ b/livejournal/README.txt @@ -0,0 +1 @@ +Read this: http://www.livejournal.com/doc/server/ \ No newline at end of file diff --git a/livejournal/bin/api2html.pl b/livejournal/bin/api2html.pl new file mode 100755 index 0000000..d25c927 --- /dev/null +++ b/livejournal/bin/api2html.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} +chdir $ENV{'LJHOME'} or die "Can't cd to $ENV{'LJOME'}\n"; + +### apidoc.pl does all the hard work. +my $VAR1; +eval `bin/apidoc.pl`; +my $api = $VAR1; + +print "\n"; +print "LiveJournal API Documentation\n"; +print "\n"; +print "

LiveJournal API Documentation

\n"; + +## print list +print "

Alphabetic List of Functions

\n"; +print "
    \n"; +foreach my $func (sort keys %$api) { + print "
  • $func
  • \n"; +} +print "
\n"; + +## print each function +print "

Function Descriptions

\n"; +foreach my $func (sort keys %$api) { + my $f = $api->{$func}; + my $argstring; + xlinkify(\$f->{'des'}); + + my $optcount; + foreach my $arg (@{$f->{'args'}}) { + my $comma = $argstring ? ", " : ""; + my $lbrack = ""; + if ($arg->{'optional'}) { + $optcount++; + $lbrack = "[" + } + $argstring .= "$lbrack$comma$arg->{'name'}"; + if ($arg->{'list'}) { + $argstring .= "*"; + } + } + $argstring .= "]"x$optcount; + + print "\n"; + print "

$func

\n"; + print "
\n"; + + print "\n"; + print "\n"; + + print "\n"; + print "\n"; + + if (@{$f->{'args'}}) { + print "\n"; + print "\n"; + + print "\n"; + print "\n"; + } + + if ($f->{'returns'}) { + xlinkify(\$f->{'returns'}); + print "\n"; + print "\n"; + } + + print "
Description:$f->{'des'}
Source:$f->{'source'}
Arguments:$argstring
 \n"; + foreach my $arg (@{$f->{'args'}}) { + print ""; + my $des = $arg->{'des'}; + xlinkify(\$des); + print "\n"; + } + print "
$arg->{'name'}$des
Returns:$f->{'returns'}
\n"; + print "

\n"; +} + + +print "\n"; +print "\n"; + +sub xlinkify { + my $a = shift; + $$a =~ s/\[func\[([^\]]*)]\]/$1<\/a><\/tt>/g; +} diff --git a/livejournal/bin/checkconfig.pl b/livejournal/bin/checkconfig.pl new file mode 100755 index 0000000..e316e47 --- /dev/null +++ b/livejournal/bin/checkconfig.pl @@ -0,0 +1,195 @@ +#!/usr/bin/perl +# + +my @errors; +my $err = sub { + return unless @_; + die "Problem:\n" . join('', map { " * $_\n" } @_); +}; + +my %dochecks; # these are the ones we'll actually do +my @checks = ( # put these in the order they should be checked in + "modules", + "env", + "database" +); +foreach my $check (@checks) { $dochecks{$check} = 1; } + +my $only = 0; + +arg: foreach my $arg (@ARGV) { + ($w, $c) = ($arg =~ /^-(no|only)(.*)/) or die "unknown option $arg"; + die "only one '-onlyfoo' option may be specified" if $w eq "only" and $only++; + foreach my $check (@checks) { + if ($check eq $c) { + if ($w eq "only") { %dochecks = ( $check => 1 ); } + else { $dochecks{$check} = 0 } + next arg; + } + } + die "unknown check '$c' (known checks: " . join(", ", @checks) . ")\n"; +} + +my %modules = ( + "DBI" => { 'deb' => 'libdbi-perl', }, + "DBD::mysql" => { 'deb' => 'libdbd-mysql-perl', }, + "Digest::MD5" => { 'deb' => 'libdigest-md5-perl', }, + "Digest::SHA1" => { 'deb' => 'libdigest-sha1-perl', }, + "Image::Size" => { 'deb' => 'libimage-size-perl', }, + "MIME::Lite" => { 'deb' => 'libmime-lite-perl', }, + "MIME::Words" => { 'deb' => 'libmime-perl', }, + "Compress::Zlib" => { 'deb' => 'libcompress-zlib-perl', }, + "Net::SMTP" => { + 'deb' => 'libnet-perl', + 'opt' => "Alternative to piping into sendmail to send mail.", + }, + "Net::DNS" => { + 'deb' => 'libnet-dns-perl', + }, + "MIME::Base64" => { 'deb' => 'libmime-base64-perl' }, + "URI::URL" => { 'deb' => 'liburi-perl' }, + "HTML::Tagset" => { 'deb' => 'libhtml-tagset-perl' }, + "HTML::Parser" => { 'deb' => 'libhtml-parser-perl', }, + "LWP::Simple" => { 'deb' => 'libwww-perl', }, + "LWP::UserAgent" => { 'deb' => 'libwww-perl', }, + "GD" => { 'deb' => 'libgd-perl' }, + "GD::Graph" => { + 'deb' => 'libgd-graph-perl', + 'opt' => 'Required to make graphs for the statistics page.', + }, + "Mail::Address" => { 'deb' => 'libmailtools-perl', }, + "Proc::ProcessTable" => { + 'deb' => 'libproc-process-perl', + 'opt' => "Better reliability for starting daemons necessary for high-traffic installations.", + }, + "RPC::XML" => { + 'deb' => 'librpc-xml-perl', + 'opt' => 'Required for outgoing XMLRPC support', + }, + "SOAP::Lite" => { + 'deb' => 'libsoap-lite-perl', + 'opt' => 'Required for XML-RPC support.', + }, + "Unicode::MapUTF8" => { 'deb' => 'libunicode-maputf8-perl', }, + "Storable" => { + 'deb' => 'libstorable-perl', + }, + "XML::RSS" => { + 'deb' => 'libxml-rss-perl', + 'opt' => 'Required for retrieving RSS off of other sites (syndication).', + }, + "XML::Simple" => { + 'deb' => 'libxml-simple-perl', + 'ver' => 2.12, + }, + "String::CRC32" => { + 'deb' => 'libstring-crc32-perl', + 'opt' => 'Required for palette-altering of PNG files. Only necessary if you plan to make your own S2 styles that use PNGs, not GIFs.', + }, + "Time::HiRes" => { 'deb' => 'libtime-hires-perl' }, + "IO::WrapTie" => { 'deb' => 'libio-stringy-perl' }, + "XML::Atom" => { + 'deb' => 'libxml-atom-perl', + 'opt' => 'Required for AtomAPI support.', + }, + "Math::BigInt::GMP" => { + 'opt' => 'Aides Crypt::DH so it isn\'t crazy slow.', + }, + "URI::Fetch" => { + 'opt' => 'Required for OpenID support.', + }, + "Crypt::DH" => { + 'opt' => 'Required for OpenID support.', + }, + ); + +sub check_modules { + print "[Checking for Perl Modules....]\n"; + + my @debs; + + foreach my $mod (sort keys %modules) { + my $rv = eval "use $mod;"; + if ($@) { + my $dt = $modules{$mod}; + if ($dt->{'opt'}) { + print STDERR "Missing optional module $mod: $dt->{'opt'}\n"; + } else { + push @errors, "Missing perl module: $mod"; + } + push @debs, $dt->{'deb'} if $dt->{'deb'}; + next; + } + + my $ver_want = $modules{$mod}{ver}; + my $ver_got = $mod->VERSION; + if ($ver_want && $ver_got && $ver_got < $ver_want) { + push @errors, "Out of date module: $mod (need $ver_want, $ver_got installed)"; + } + } + if (@debs && -e '/etc/debian_version') { + print STDERR "\n# apt-get install ", join(' ', @debs), "\n\n"; + } + + $err->(@errors); +} + +sub check_env { + print "[Checking LJ Environment...]\n"; + + $err->("\$LJHOME environment variable not set.") + unless $ENV{'LJHOME'}; + $err->("\$LJHOME directory doesn't exist ($ENV{'LJHOME'})") + unless -d $ENV{'LJHOME'}; + + # before ljconfig.pl is called, we want to call the site-local checkconfig, + # otherwise ljconfig.pl might load ljconfig-local.pl, which maybe load + # new modules to implement site-specific hooks. + my $local_config = "$ENV{'LJHOME'}/bin/checkconfig-local.pl"; + if (-e $local_config) { + my $good = eval { require $local_config; }; + exit 1 unless $good; + } + + $err->("No ljconfig.pl file found at $ENV{'LJHOME'}/cgi-bin/ljconfig.pl") + unless -e "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + + eval { require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; }; + $err->("Failed to load ljlib.pl: $@") if $@; + + # if SMTP_SERVER is set, then Net::SMTP is required, not optional. + if ($LJ::SMTP_SERVER && ! defined $Net::SMTP::VERSION) { + $err->("Net::SMTP isn't available, and you have \$LJ::SMTP_SERVER set."); + } +} + +sub check_database { + print "[Checking Database...]\n"; + + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + my $dbh = LJ::get_dbh("master"); + unless ($dbh) { + $err->("Couldn't get master database handle."); + } + foreach my $c (@LJ::CLUSTERS) { + my $dbc = LJ::get_cluster_master($c); + next if $dbc; + $err->("Couldn't get db handle for cluster \#$c"); + } + + if (%LJ::MOGILEFS_CONFIG && $LJ::MOGILEFS_CONFIG{hosts}) { + print "[Checking MogileFS client.]\n"; + my $mog = LJ::mogclient(); + die "Couldn't create mogilefs client." unless $mog; + } +} + +foreach my $check (@checks) { + next unless $dochecks{$check}; + my $cn = "check_".$check; + &$cn; +} +print "All good.\n"; +print "NOTE: checkconfig.pl doesn't check everything yet\n"; + + diff --git a/livejournal/bin/cvsreport.pl b/livejournal/bin/cvsreport.pl new file mode 100755 index 0000000..534a7d1 --- /dev/null +++ b/livejournal/bin/cvsreport.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl +# +# This is now just a wrapper around the non-LJ-specific multicvs.pl +# + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +# strip off paths beginning with LJHOME +# (useful if you tab-complete filenames) +$_ =~ s!\Q$ENV{'LJHOME'}\E/?!! foreach (@ARGV); + +exit system("$ENV{'LJHOME'}/bin/multicvs.pl", + "--conf=$ENV{'LJHOME'}/cvs/multicvs.conf", @ARGV); diff --git a/livejournal/bin/dbcheck.pl b/livejournal/bin/dbcheck.pl new file mode 100755 index 0000000..e1d44ea --- /dev/null +++ b/livejournal/bin/dbcheck.pl @@ -0,0 +1,339 @@ +#!/usr/bin/perl +# + +use strict; +use DBI; +use Getopt::Long; + +my $help = 0; +my $opt_fh = 0; +my $opt_fix = 0; +my $opt_start = 0; +my $opt_stop = 0; +my $opt_err = 0; +my $opt_all = 0; +my $opt_tablestatus; +my $opt_checkreport = 0; +my $opt_rates; +my @opt_run; +exit 1 unless GetOptions('help' => \$help, + 'flushhosts' => \$opt_fh, + 'start' => \$opt_start, + 'stop' => \$opt_stop, + 'checkreport' => \$opt_checkreport, + 'rates' => \$opt_rates, + 'fix' => \$opt_fix, + 'run=s' => \@opt_run, + 'onlyerrors' => \$opt_err, + 'all' => \$opt_all, + 'tablestatus' => \$opt_tablestatus, + ); + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +if ($help) { + die ("Usage: dbcheck.pl [opts] [[cmd] args...]\n" . + " --all Check all hosts, even those with no weight assigned.\n" . + " --help Get this help\n" . + " --flushhosts Send 'FLUSH HOSTS' to each db as root.\n". + " --fix Fix (once) common problems.\n". + " --checkreport Show tables that haven't been checked in a while.\n". + " --stop Stop replication.\n". + " --start Start replication.\n". + " --run Run arbitrary SQL.\n". + " --onlyerrors Will be silent unless there are errors.\n". + " --tablestatus Show warnings about full/sparse tables.\n". + "\n". + "Commands\n". + " (none) Shows replication status.\n". + " queries Shows active queries on host, sorted by running time.\n" + ); +} + +require "$ENV{'LJHOME'}/cgi-bin/ljdb.pl"; + +my $dbh = LJ::DB::dbh_by_role("master"); +die "Can't get master db handle\n" unless $dbh; + +my %dbinfo; # dbid -> hashref +my %name2id; # name -> dbid +my $sth; +my $masterid = 0; + +my %subclust; # id -> name of parent (pork-85 -> "pork") + +$sth = $dbh->prepare("SELECT dbid, name, masterid, rootfdsn FROM dbinfo"); +$sth->execute; +while ($_ = $sth->fetchrow_hashref) { + if ($_->{name} =~ /(.+)\-\d\d$/) { + $subclust{$_->{dbid}} = $1; + next; + } + next unless $_->{'dbid'}; + $dbinfo{$_->{'dbid'}} = $_; + $name2id{$_->{'name'}} = $_->{'dbid'}; +} + +my %role; # rolename -> dbid -> [ norm, curr ] +my %rolebyid; # dbid -> rolename -> [ norm, curr ] +$sth = $dbh->prepare("SELECT dbid, role, norm, curr FROM dbweights"); +$sth->execute; +while ($_ = $sth->fetchrow_hashref) { + my $id = $_->{dbid}; + if ($subclust{$id}) { + $id = $name2id{$subclust{$id}}; + } + next unless defined $dbinfo{$id}; + $dbinfo{$id}->{'totalweight'} += $_->{'curr'}; + $role{$_->{role}}->{$id} = [ $_->{norm}, $_->{curr} ]; + $rolebyid{$id}->{$_->{role}} = [ $_->{norm}, $_->{curr} ]; +} + +check_report() if $opt_checkreport; +rate_report() if $opt_rates; + +my @errors; +my %master_status; # dbid -> [ $file, $pos ] + +my $check_master_status = sub { + my $dbid = shift; + my $d = $dbinfo{$dbid}; + die "Bogus DB: $dbid" unless $d; + my $db = LJ::DB::root_dbh_by_name($d->{name}); + next unless $db; + + my ($masterfile, $masterpos) = $db->selectrow_array("SHOW MASTER STATUS"); + $master_status{$dbid} = [ $masterfile, $masterpos ]; +}; + +my $check = sub { + my $dbid = shift; + my $d = $dbinfo{$dbid}; + die "Bogus DB: $dbid" unless $d; + + # calculate roles to show + my $roles; + { + my %drole; # display role -> 1 + foreach my $role (grep { $role{$_}{$dbid}[1] } keys %{$rolebyid{$dbid}}) { + my $drole = $role; + $drole =~ s/cluster(\d+)\d/cluster${1}0/; + $drole{$drole} = 1; + } + $roles = join(", ", sort keys %drole); + } + + my $db = LJ::DB::root_dbh_by_name($d->{name}); + unless ($db) { + printf("%4d %-15s %4s %16s %14s ($roles)\n", + $dbid, + $d->{name}, + $d->{masterid} ? $d->{masterid} : "", + ) unless $opt_err; + push @errors, "Can't connect to $d->{'name'}"; + return 0; + } + + my $tzone; + (undef, $tzone) = $db->selectrow_array("show variables like 'timezone'"); + + $sth = $db->prepare("SHOW PROCESSLIST"); + $sth->execute; + my $pcount_total = 0; + my $pcount_busy = 0; + while (my $r = $sth->fetchrow_hashref) { + next if $r->{'State'} =~ /waiting for/i; + next if $r->{'State'} eq "Reading master update"; + next if $r->{'State'} =~ /^(Has (sent|read) all)|(Sending binlog)/; + $pcount_total++; + $pcount_busy++ if $r->{'State'}; + } + + my @master_logs; + my $log_count = 0; + if ($master_status{$dbid} && $master_status{$dbid}->[1]) { + $sth = $db->prepare("SHOW MASTER LOGS"); + $sth->execute; + while (my ($log) = $sth->fetchrow_array) { + push @master_logs, $log; + $log_count++; + } + } + + my $ss = $db->selectrow_hashref("show slave status"); + if ($ss) { + foreach my $k (sort keys %$ss) { + $ss->{lc $k} = $ss->{$k}; + } + } + + my $diff; + if ($ss) { + if ($ss->{'slave_io_running'} eq "Yes" && $ss->{'slave_sql_running'} eq "Yes") { + if ($ss->{'master_log_file'} eq $ss->{'relay_master_log_file'}) { + $diff = $ss->{'read_master_log_pos'} - $ss->{'exec_master_log_pos'}; + } else { + $diff = "XXXXXXX"; + push @errors, "Wrong log file: $d->{name}"; + } + } else { + $diff = "XXXXXXX"; + $ss->{last_error} =~ s/[^\n\r\t\x20-\x7e]//g; + push @errors, "Slave not running: $d->{name}: $ss->{last_error}"; + } + + my $ms = $master_status{$d->{masterid}} || []; + #print " master: [@$ms], slave at: [$ss->{master_log_file}, $ss->{read_master_log_pos}]\n"; + if ($ss->{master_log_file} ne $ms->[0] || $ss->{read_master_log_pos} < $ms->[1] - 20_000) { + push @errors, "$d->{name}: Relay log behind: master=[@$ms], $d->{name}=[$ss->{master_log_file}, $ss->{read_master_log_pos}]"; + } + + } else { + $diff = "-"; # not applicable + } + + #print "$dbid of $d->{masterid}: $d->{name} ($roles)\n"; + printf("%4d %-15s %4s repl:%7s %4s conn:%4d/%4d $tzone ($roles)\n", + $dbid, + $d->{name}, + $d->{masterid} ? $d->{masterid} : "", + $diff, + $log_count ? sprintf("<%2s>", $log_count) : "", + $pcount_busy, $pcount_total) unless $opt_err; +}; + +$check_master_status->($_) foreach (sorted_dbids()); + +$check->($_) foreach (sorted_dbids()); + +if (@errors) { + if ($opt_err) { + my %ignore; + open(EX, "$ENV{'HOME'}/.dbcheck.ignore"); + while () { + s/\s+$//; + $ignore{$_} = 1; + } + close EX; + @errors = grep { ! $ignore{$_} } @errors; + } + print STDERR "\nERRORS:\n" if @errors; + foreach (@errors) { + print STDERR " * $_\n"; + } +} + +my $sorted_cache; +sub sorted_dbids { + return @$sorted_cache if $sorted_cache; + $sorted_cache = [ _sorted_dbids() ]; + return @$sorted_cache; +} + +sub _sorted_dbids { + my @ids; + my %added; # dbid -> 1 + + my $add = sub { + my $dbid = shift; + $added{$dbid} = 1; + push @ids, $dbid; + }; + + my $masterid = (keys %{$role{'master'}})[0]; + $add->($masterid); + + # then slaves + foreach my $id (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} } + grep { ! $added{$_} && $rolebyid{$_}->{slave} } keys %dbinfo) { + $add->($id); + } + + # now, figure out which remaining are associated with cluster roles (user clusters) + my %minclust; # dbid -> minimum cluster number associated + my %is_master; # dbid -> bool (is cluster master) + foreach my $dbid (grep { ! $added{$_} } keys %dbinfo) { + foreach my $role (keys %{ $rolebyid{$dbid} || {} }) { + next unless $role =~ /^cluster(\d+)(.*)/; + $minclust{$dbid} = $1 if ! $minclust{$dbid} || $1 < $minclust{$dbid}; + $is_master{$dbid} ||= $2 eq "" || $2 eq "a" || $2 eq "b"; + } + } + + # then misc + foreach my $id (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} } + grep { ! $added{$_} && ! $minclust{$_} } keys %dbinfo) { + $add->($id); + } + + + # then clusters, in order + foreach my $id (sort { $minclust{$a} <=> $minclust{$b} || + $is_master{$b} <=> $is_master{$a} } + grep { ! $added{$_} && $minclust{$_} } keys %dbinfo) { + $add->($id); + } + return @ids; +} + +sub check_report { + foreach my $dbid (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} } + keys %dbinfo) { + my $d = $dbinfo{$dbid}; + die "Bogus DB: $dbid" unless $d; + my $db = LJ::DB::root_dbh_by_name($d->{name}); + + unless ($db) { + print "$d->{name}\t?\t?\t?\n"; + next; + } + + my $dbs = $db->selectcol_arrayref("SHOW DATABASES"); + foreach my $dbname (@$dbs) { + $db->do("USE $dbname"); + my $ts = $db->selectall_hashref("SHOW TABLE STATUS", "Name"); + foreach my $tn (sort keys %$ts) { + my $v = $ts->{$tn}; + my $ut = $v->{Check_time} || "0000-00-00 00:00:00"; + $ut =~ s/ /,/; + print "$d->{name}\t$dbname\t$tn\t$ut\t$v->{Type}-$v->{Row_format}\t$v->{Rows}\n"; + } + + } + } + exit 0; +} + +use Time::HiRes (); + +sub rate_report { + my %prev; # dbid -> [ time, questions ] + + while (1) { + print "\n"; + my $sum = 0; + foreach my $dbid (sorted_dbids()) { + my $d = $dbinfo{$dbid}; + die "Bogus DB: $dbid" unless $d; + my $db = LJ::DB::root_dbh_by_name($d->{name}); + + next unless $db; + my (undef, $qs) = $db->selectrow_array("SHOW STATUS LIKE 'Questions'"); + my $now = Time::HiRes::time(); + my $cur = [ $now, $qs ]; + if (my $old = $prev{$dbid}) { + my $dt = $now - $old->[0]; + my $qnew = $qs - $old->[1]; + my $rate = ($qnew / $dt); + $sum += $rate; + printf "%20s: %7.01f q/s\n", $d->{name}, $rate; + } + $prev{$dbid} ||= $cur; + } + printf "%20s: %7.01f q/s\n", "SUM", $sum; + + sleep 1; + } +} diff --git a/livejournal/bin/dbselectd.pl b/livejournal/bin/dbselectd.pl new file mode 100755 index 0000000..8430c90 --- /dev/null +++ b/livejournal/bin/dbselectd.pl @@ -0,0 +1,392 @@ +#!/usr/bin/perl -w +# +# DB selector daemon. Returns connect information on a preferred DB +# to a requestor. +# +# +# lib: Getopt::Long, POSIX::, IO::Socket, IO::Select, Socket::, Fcntl::, DBI:: +# lib: cgi-bin/ljconfig.pl +# + +use Getopt::Long; +use POSIX; +use IO::Socket; +use IO::Select; +use strict; +use Socket; +use Fcntl; +use DBI; + +my $PORT = 5151; +my $PIDFILE = "$ENV{'LJHOME'}/var/dbselectd.pid"; + +my $SELECT_DELAY = 0.3; + +# temporary: +my $DBINFO_FILE = "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; +my $opt_foreground = 0; +GetOptions("foreground" => \$opt_foreground); + +my $pid; + +# statistics on known databases +my %db_lastcheck; +my %db_conncount; +my $conf_modtime = 0; +my $conf_stattime = 0; + +# Buffers. +my %inbuffer = (); +my %outbuffer = (); +my %cmd = (); +my %clientinfo = (); + +sub connect_to +{ + my $svr = shift; + my $dbh; + + if (ref $LJ::DBCACHE{$svr}) + { + $dbh = $LJ::DBCACHE{$svr}; + + # make sure connection is still good. + my $sth = $dbh->prepare("SELECT CONNECTION_ID()"); # mysql specific + $sth->execute; + my ($id) = $sth->fetchrow_array; + if ($id) { return $dbh; } + undef $dbh; + undef $LJ::DBCACHE{$svr}; + } + + my $dbname = $LJ::DBINFO{$svr}->{'dbname'} || "livejournal"; + $dbh = DBI->connect("DBI:mysql:$dbname:$LJ::DBINFO{$svr}->{'host'}", + $LJ::DBINFO{$svr}->{'user'}, + $LJ::DBINFO{$svr}->{'pass'}, + { + PrintError => 0, + }); + if ($dbh) + { + $LJ::DBCACHE{$svr} = $dbh; + return $dbh; + } + + return undef; +} + +sub db_can +{ + my $svr = shift; + my $cap = shift; + return $LJ::DBINFO{$svr}->{'role'}->{$cap}; +} + +sub check_server +{ + my $svr = shift; + delete $db_conncount{$svr}; + delete $db_lastcheck{$svr}; + + my $dbh = connect_to($svr); + return unless (defined $dbh); + + my $sth = $dbh->prepare("SHOW PROCESSLIST"); + $sth->execute; + my $ct = 0; + while (my $r = $sth->fetchrow_hashref) + { + # weight busy connections more than idle ones. + if ($r->{'State'}) { $ct += 2; } + else { $ct += 1; } + } + $db_conncount{$svr} = $ct; + $db_lastcheck{$svr} = time(); +} + +sub connection_load +{ + my $svr = shift; + my $time = time(); + if (! defined $db_lastcheck{$svr} || + $time - $db_lastcheck{$svr} > 10) + { + check_server($svr); + } + return $db_conncount{$svr}; +} + +sub server_power +{ + my $svr = shift; + my $cap = shift; + + my $weight = $LJ::DBINFO{$svr}->{'role'}->{$cap} || 1; + my $connections = connection_load($svr); + if (defined $connections) { + $connections ||= 1; + } else { + return 0; + } + return ($weight / $connections); +} + +sub use_what +{ + my $c = shift; + my $cap = shift; + + ## reload the DB info file if it's been more than 5 seconds since + ## its last stat time and if it's changed since what we remember. + my $time = time(); + if ($conf_stattime + 5 < $time) + { + my $modtime = (stat($DBINFO_FILE))[9]; + if ($modtime > $conf_modtime) { + delete $INC{$DBINFO_FILE}; + require $DBINFO_FILE; + $conf_modtime = $modtime; + $conf_stattime = $time; + } + } + + my %cand = (); # candidates + + # best candidate is one the client is already connected to + foreach my $svr (keys %{$c->{'has'}}) { + if (db_can($svr, $cap)) { + $cand{$svr} = 1; + } + } + + # if not connected to anything suitable, then: + unless (%cand) + { + # every db with that capability is a good candidate + foreach my $svr (keys %LJ::DBINFO) { + if (db_can($svr, $cap)) { + $cand{$svr} = 1; + } + } + } + + my @cands = keys %cand; + + # sort valid candidates by server's connections + my %power; + foreach (@cands) { + $power{$_} = server_power($_, $cap); + } + @cands = sort { $power{$b} <=> $power{$a} } @cands; + + # use the one with the highest score: + my $use = $cands[0]; + if ($use) { + unless (defined $LJ::DBINFO{$use}->{'dbname'}) { + $LJ::DBINFO{$use}->{'dbname'} = "livejournal"; + } + return join(" ", $use, map { $LJ::DBINFO{$use}->{$_} } qw(host user pass dbname)); + } else { + return "--"; + } +} + +sub handle +{ + my $select = shift; + my $client = shift; + my $line = shift; + my $c = ($clientinfo{$client} ||= {}); + my $out = \$outbuffer{$client}; + + $line =~ s/^(\S*)\s*//; + my $cmd = $1; + + if ($cmd eq "HAVE") { + foreach (split(/,/, $line)) { + next if ($_ eq "master"); + $c->{'has'}->{$_} = 1; + } + $$out = "OK\n"; + return; + } + + if ($cmd eq "NEED") { + my $cap = $line; + my $use = use_what($c, $cap); + $$out = "USE $use\n"; + return; + } + + if ($cmd eq "STATS") { + my $svr = $line; + $$out = "Stats follow:\n"; + foreach my $s (keys %LJ::DBINFO) { + $$out .= "STATS $s = " . connection_load($s) . "\n"; + } + $$out .= "End.\n"; + return; + } + + $$out = "unknown command.\n"; +} + +# Server crap is below. + +$SIG{'TERM'} = sub { + unlink($PIDFILE); + exit 1; +}; + +if (-e $PIDFILE) { + print "$PIDFILE exists, quitting.\n"; + exit 1; +} + +sub write_pid +{ + my $p = shift; + open(PID, ">$PIDFILE") or die "Couldn't open $PIDFILE for writing: $!\n"; + print PID $p; + close(PID); +} + +if ($opt_foreground) { + print "Running in foreground...\n"; + $pid = $$; + write_pid($pid); + $SIG{'INT'} = sub { + unlink($PIDFILE); + exit 1; + }; +} else { + print "Forking off and initializing...\n"; + if ($pid = fork) { + # Parent, log pid and exit. + write_pid($pid); + print "Closing ($pid) wrote to $PIDFILE\n"; + exit; + } +} + +sub killpid_die +{ + my $msg = shift; + unlink $PIDFILE; + die $msg; +} + +# Connection stuff. +my $server = IO::Socket::INET->new( + "LocalPort" => $PORT, + "Listen" => 10, + "ReuseAddr" => 1, + "Reuse" => 1, + ) or killpid_die "Can't make server socket: $@\n"; + +nonblock($server); +$server->sockopt(SO_REUSEADDR, 1); +my $select = IO::Select->new($server); + +print "Looping.\n"; + +while(1) +{ + my $client; + my $rv; + my $data; + + # Got connection? Got data? + foreach $client ($select->can_read($SELECT_DELAY)) { + if ($client == $server) { + # New connection, since there's stuff to read from the server sock. + $client = $server->accept(); + $select->add($client); + # If the nonblocking mess fails, uh, give up. + unless (nonblock($client)) { + $select->remove($client); + } + } else { + # Read what data we have. + $data = ''; + $rv = $client->recv($data, POSIX::BUFSIZ, 0); + + unless (defined($rv) && length($data)) { + # If a socket says you can read, but there's nothing there, it's + # actually dead. Clean it up. + cleanup($client); + + $select->remove($client); + close($client); + next; + } + + $inbuffer{$client} .= $data; + # Check to see if there's a newline at the end. If it is, the + # command is finished. There's only one command line, so I won't + # bother making %cmd a hash with array references to request + # lines. Although this might be needed in the future. + if ($inbuffer{$client} =~ s/^.*\n//) { + $cmd{$client} = $&; + delete $inbuffer{$client}; + } + } + + } + + # Deal with cmd stuff. + foreach $client (keys %cmd) { + my $cmd = $cmd{$client}; + $cmd =~ s/[\n\r]+$//; + handle($select, $client, $cmd); + } + %cmd = (); + + # Flush buffers + foreach $client ($select->can_write($SELECT_DELAY)) { + # Don't try if there's nothing there. + next unless exists $outbuffer{$client}; + + $rv = $client->send($outbuffer{$client}, 0); + unless (defined $rv) { + # Something weird happened if we get here, I'll bitch if we ever + # need logging on this thing. + next; + } + if ($rv == length $outbuffer{$client} || $! == POSIX::EWOULDBLOCK) { + substr($outbuffer{$client}, 0, $rv) = ''; + delete $outbuffer{$client} unless length $outbuffer{$client}; + } else { + # Ahh, something broke. If it was going to block, the above would + # catch it. Close up... + cleanup($client); + + $select->remove($client); + close($client); + next; + } + + } + +} + +# Does the messy Socket based nonblock routine... +sub nonblock { + my $socket = shift; + my $flags; + + $flags = fcntl($socket, F_GETFL, 0) or return 0; + fcntl($socket, F_SETFL, $flags | O_NONBLOCK) or return 0; + + return 1; +} + +sub cleanup +{ + my $client = shift; + + delete $inbuffer{$client}; + delete $outbuffer{$client}; + delete $cmd{$client}; + delete $clientinfo{$client}; +} diff --git a/livejournal/bin/deleteusers.pl b/livejournal/bin/deleteusers.pl new file mode 100755 index 0000000..a1c00ff --- /dev/null +++ b/livejournal/bin/deleteusers.pl @@ -0,0 +1,157 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +my $dbh = LJ::get_dbh("master"); +$dbh->{'RaiseError'} = 1; +$dbh->{'PrintError'} = 1; +my $sth; + +$sth = $dbh->prepare("SELECT userid FROM user WHERE statusvis='D' AND statusvisdate < DATE_SUB(NOW(), INTERVAL 35 DAY) ORDER BY statusvisdate"); +$sth->execute; +my @delusers; +while (my $duid = $sth->fetchrow_array) { + push @delusers, $duid; +} +print "Users to delete: ", scalar(@delusers), "\n"; + +# Get hashref mapping {userid => $u} for all users to be deleted +my $user = LJ::load_userids(@delusers); + +LJ::load_props($dbh, "talk"); +my $p_delposter = LJ::get_prop("talk", "deleted_poster"); +die "No 'deleted_poster' talkprop?" unless $p_delposter; +my $ids; + +my $lastbreak = time(); +my $pause = sub { + if (time() - $lastbreak > 3) { print "pause.\n"; sleep(1); $lastbreak = time(); } +}; + +# FIXME: This will soon need to be changed to use methods of the $u +# object rather than global LJ:: functions, but this should work +# for now. + +my $runsql = sub { + my $db = $dbh; + if (ref $_[0]) { $db = shift; } + my $user = shift; + my $sql = shift; + print " ($user) $sql\n"; + $db->do($sql); +}; + +my $czero = 0; + +foreach my $uid (@delusers) +{ + my $du = $user->{$uid}; + my $user = $du->{'user'}; + print "$du->{'user'} ($du->{'userid'}) @ $du->{'statusvisdate'}"; + if ($du->{clusterid} == 0) { + print " (on clusterid 0; skipping)\n"; + $czero++; + next; + } + print " (cluster $du->{'clusterid'})...\n"; + $pause->(); + + # get a db handle for the cluster master. + LJ::start_request(); # might've been awhile working with last handle, we don't want to be given an expired one. + my $dbcm = LJ::get_cluster_master($du); + $dbcm->{'RaiseError'} = 1; + $dbcm->{'PrintError'} = 1; + + # make all the user's comments posted now be owned by posterid 0 (anonymous) + # but with meta-data saying who used to own it + # ..... hm, with clusters this is a pain. let's not. + + # delete memories + print " memories\n"; + while (($ids = $dbh->selectcol_arrayref("SELECT memid FROM memorable WHERE userid=$uid LIMIT 100")) && @{$ids}) + { + my $in = join(",", @$ids); + print " id: $in\n"; + $runsql->($dbh, $user, "DELETE FROM memkeyword WHERE memid IN ($in)"); + $runsql->($dbh, $user, "DELETE FROM memorable WHERE memid IN ($in)"); + } + + # delete todos + print " todos\n"; + while (($ids = $dbh->selectcol_arrayref("SELECT todoid FROM todo WHERE journalid=$uid LIMIT 100")) && @{$ids}) + { + my $in = join(",", @$ids); + print " id: $in\n"; + $runsql->($dbh, $user, "DELETE FROM tododep WHERE todoid IN ($in)"); + $runsql->($dbh, $user, "DELETE FROM todokeyword WHERE todoid IN ($in)"); + $runsql->($dbh, $user, "DELETE FROM todo WHERE todoid IN ($in)"); + } + + # delete userpics + { + print " userpics\n"; + if ($du->{'dversion'} > 6) { + $ids = $dbcm->selectcol_arrayref("SELECT picid FROM userpic2 WHERE userid=$uid"); + } else { + $ids = $dbh->selectcol_arrayref("SELECT picid FROM userpic WHERE userid=$uid"); + } + my $in = join(",",@$ids); + if ($in) { + print " userpics: $in\n"; + $runsql->($dbcm, $user, "DELETE FROM userpicblob2 WHERE userid=$uid AND picid IN ($in)"); + if ($du->{'dversion'} > 6) { + $runsql->($dbcm, $user, "DELETE FROM userpic2 WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM userpicmap2 WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM userkeywords WHERE userid=$uid"); + } else { + $runsql->($dbh, $user, "DELETE FROM userpic WHERE userid=$uid"); + $runsql->($dbh, $user, "DELETE FROM userpicmap WHERE userid=$uid"); + } + } + } + + # delete posts + print " posts\n"; + while (($ids = $dbcm->selectall_arrayref("SELECT jitemid, anum FROM log2 WHERE journalid=$uid LIMIT 100")) && @{$ids}) + { + foreach my $idanum (@$ids) { + my ($id, $anum) = ($idanum->[0], $idanum->[1]); + print " deleting $id (a=$anum) ($uid; $du->{'user'})\n"; + LJ::delete_entry($du, $id, 0, $anum); + $pause->(); + } + } + + # misc: + $runsql->($user, "DELETE FROM userusage WHERE userid=$uid"); + $runsql->($user, "DELETE FROM friends WHERE userid=$uid"); + $runsql->($user, "DELETE FROM friends WHERE friendid=$uid"); + $runsql->($user, "DELETE FROM friendgroup WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM friendgroup2 WHERE userid=$uid"); + $runsql->($user, "DELETE FROM memorable WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM memorable2 WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM userkeywords WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM memkeyword2 WHERE userid=$uid"); + $runsql->($user, "DELETE FROM userbio WHERE userid=$uid"); + $runsql->($dbcm, $user, "DELETE FROM userbio WHERE userid=$uid"); + $runsql->($user, "DELETE FROM userinterests WHERE userid=$uid"); + $runsql->($user, "DELETE FROM userprop WHERE userid=$uid"); + $runsql->($user, "DELETE FROM userproplite WHERE userid=$uid"); + $runsql->($user, "DELETE FROM txtmsg WHERE userid=$uid"); + $runsql->($user, "DELETE FROM overrides WHERE user='$du->{'user'}'"); + $runsql->($user, "DELETE FROM priv_map WHERE userid=$uid"); + $runsql->($user, "DELETE FROM infohistory WHERE userid=$uid"); + $runsql->($user, "DELETE FROM reluser WHERE userid=$uid"); + $runsql->($user, "DELETE FROM reluser WHERE targetid=$uid"); + $runsql->($user, "DELETE FROM userlog WHERE userid=$uid"); + + $runsql->($user, "UPDATE user SET statusvis='X', statusvisdate=NOW(), password='' WHERE userid=$uid"); + +} + +if ($czero) { + print "\nWARNING: There are $czero users on cluster zero pending deletion.\n"; + print " These users must be upgraded before they can be expunged with this tool.\n"; +} diff --git a/livejournal/bin/dumpsql.pl b/livejournal/bin/dumpsql.pl new file mode 100755 index 0000000..bc7bffa --- /dev/null +++ b/livejournal/bin/dumpsql.pl @@ -0,0 +1,167 @@ +#!/usr/bin/perl +# +# +# lib: cgi-bin/ljlib.pl +# + +use strict; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl"; + +my $dbh = LJ::get_db_writer(); + +sub header_text { + return <<"HEADER"; +# This file is automatically generated from MySQL by \$LJHOME/bin/dumpsql.pl +# Don't submit a diff against a hand-modified file - dump and diff instead. + +HEADER +} + +# what tables don't we want to export the auto_increment columns from +# because they already have their own unique string, which is what matters +my %skip_auto = ("userproplist" => "name", + "talkproplist" => "name", + "logproplist" => "name", + "priv_list" => "privcode", + "supportcat" => "catkey", + "ratelist" => "rlid", + ); + +# get tables to export +my %tables = (); +my $sth = $dbh->prepare("SELECT tablename, redist_mode, redist_where ". + "FROM schematables WHERE redist_mode NOT IN ('off')"); +$sth->execute; +while (my ($table, $mode, $where) = $sth->fetchrow_array) { + $tables{$table}->{'mode'} = $mode; + $tables{$table}->{'where'} = $where; +} + +my %output; # {general|local} -> [ [ $alphasortkey, $SQL ]+ ] + +# dump each table. +foreach my $table (sort keys %tables) +{ + my $where; + if ($tables{$table}->{'where'}) { + $where = "WHERE $tables{$table}->{'where'}"; + } + + my $sth = $dbh->prepare("DESCRIBE $table"); + $sth->execute; + my @cols = (); + my $skip_auto = 0; + while (my $c = $sth->fetchrow_hashref) { + if ($c->{'Extra'} =~ /auto_increment/ && $skip_auto{$table}) { + $skip_auto = 1; + } else { + push @cols, $c; + } + } + + # DESCRIBE table can be different between developers + @cols = sort { $a->{'Field'} cmp $b->{'Field'} } @cols; + + my $cols = join(", ", map { $_->{'Field'} } @cols); + my $sth = $dbh->prepare("SELECT $cols FROM $table $where"); + $sth->execute; + my $sql; + while (my @r = $sth->fetchrow_array) + { + my %vals; + my $i = 0; + foreach (map { $_->{'Field'} } @cols) { + $vals{$_} = $r[$i++]; + } + my $scope = "general"; + $scope = "local" if (defined $vals{'scope'} && + $vals{'scope'} eq "local"); + my $verb = "INSERT IGNORE"; + $verb = "REPLACE" if ($tables{$table}->{'mode'} eq "replace" && + ! $skip_auto); + $sql = "$verb INTO $table "; + $sql .= "($cols) "; + $sql .= "VALUES (" . join(", ", map { db_quote($_) } @r) . ");\n"; + + my $uniqc = $skip_auto{$table}; + my $skey = $uniqc ? $vals{$uniqc} : $sql; + push @{$output{$scope}}, [ "$table.$skey.1", $sql ]; + + if ($skip_auto) { + # for all the *proplist tables, there might be new descriptions + # or columns, but we can't do a REPLACE, because that'd mess + # with their auto_increment ids, so we do insert ignore + update + my $where = "$uniqc=" . db_quote($vals{$uniqc}); + delete $vals{$uniqc}; + $sql = "UPDATE $table SET "; + $sql .= join(",", map { "$_=" . db_quote($vals{$_}) } sort keys %vals); + $sql .= " WHERE $where;\n"; + push @{$output{$scope}}, [ "$table.$skey.2", $sql ]; + } + } +} + +# don't use $dbh->quote because it's changed between versions +# and developers sending patches can't generate concise patches +# it used to not quote " in a single quoted string, but later it does. +# so we'll implement the new way here. +sub db_quote { + my $s = shift; + return "NULL" unless defined $s; + $s =~ s/\\/\\\\/g; + $s =~ s/\"/\\\"/g; + $s =~ s/\'/\\\'/g; + $s =~ s/\n/\\n/g; + $s =~ s/\r/\\r/g; + return "'$s'"; +} + +foreach my $k (keys %output) { + my $file = $k eq "general" ? "base-data.sql" : "base-data-local.sql"; + print "Dumping $file\n"; + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + open (F, ">$ffile") or die "Can't write to $ffile\n"; + print F header_text(); + foreach (sort { $a->[0] cmp $b->[0] } @{$output{$k}}) { + print F $_->[1]; + } + close F; +} + +# and do S1 styles (ugly schema) +print "Dumping s1styles.dat\n"; +require "$ENV{'LJHOME'}/bin/upgrading/s1style-rw.pl"; +my $ss = {}; +my $pubstyles = LJ::S1::get_public_styles({ 'formatdata' => 1}); +foreach my $s (values %$pubstyles) { + my $uniq = "$s->{'type'}/$s->{'styledes'}"; + $ss->{$uniq}->{$_} = $s->{$_} foreach keys %$s; +} +s1styles_write($ss); + +# and dump mood info +print "Dumping moods.dat\n"; +open (F, ">$ENV{'LJHOME'}/bin/upgrading/moods.dat") or die; +$sth = $dbh->prepare("SELECT moodid, mood, parentmood FROM moods ORDER BY moodid"); +$sth->execute; +while (@_ = $sth->fetchrow_array) { + print F "MOOD @_\n"; +} + +$sth = $dbh->prepare("SELECT moodthemeid, name, des FROM moodthemes WHERE is_public='Y' ORDER BY name"); +$sth->execute; +while (my ($id, $name, $des) = $sth->fetchrow_array) { + $name =~ s/://; + print F "MOODTHEME $name : $des\n"; + my $std = $dbh->prepare("SELECT moodid, picurl, width, height FROM moodthemedata ". + "WHERE moodthemeid=$id ORDER BY moodid"); + $std->execute; + while (@_ = $std->fetchrow_array) { + print F "@_\n"; + } +} +close F; + + +print "Done.\n"; diff --git a/livejournal/bin/fingerd.pl b/livejournal/bin/fingerd.pl new file mode 100755 index 0000000..9380a3e --- /dev/null +++ b/livejournal/bin/fingerd.pl @@ -0,0 +1,144 @@ +#!/usr/bin/perl +# +# finger server. +# +# accepts two optional arguments, host and port. +# doesn't daemonize. +# +# +# +# lib: Socket::, Text::Wrap, cgi-bin/ljlib.pl +# + +my $bindhost = shift @ARGV; +my $port = shift @ARGV; + +unless ($bindhost) { + $bindhost = "0.0.0.0"; +} + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +use Socket; +use Text::Wrap; + +$SIG{'INT'} = sub { + print "Interrupt caught!\n"; + close FH; + close CL; + exit; +}; + +my $proto = getprotobyname('tcp'); +socket(FH, PF_INET, SOCK_STREAM, $proto) || die $!; + +$port ||= 79; +my $localaddr = inet_aton($bindhost); +my $sin = sockaddr_in($port, $localaddr); +setsockopt (FH,SOL_SOCKET,SO_REUSEADDR,1) or + die "setsockopt() failed: $!\n"; +bind (FH, $sin) || die $!; + +listen(FH, 10); + +while (LJ::start_request()) +{ + accept(CL, FH) || die $!; + + my $line = ; + chomp $line; + $line =~ s/\0//g; + $line =~ s/\s//g; + + if ($line eq "") { + print CL "Welcome to the $LJ::SITENAME finger server! + +You can make queries in the following form: + + \@$LJ::DOMAIN - this help message + user\@$LJ::DOMAIN - their userinfo +"; + close CL; + next; + } + + my $dbr = LJ::get_dbh("slave", "master"); + + if ($line =~ /^(\w{1,15})$/) { + # userinfo! + my $user = $1; + my $quser = $dbr->quote($user); + my $sth = $dbr->prepare("SELECT user, has_bio, caps, userid, name, email, bdate, allow_infoshow FROM user WHERE user=$quser"); + $sth->execute; + my $u = $sth->fetchrow_hashref; + unless ($u) { + print CL "\nUnknown user ($user)\n"; + close CL; + next; + } + + my $bio; + if ($u->{'has_bio'} eq "Y") { + $sth = $dbr->prepare("SELECT bio FROM userbio WHERE userid=$u->{'userid'}"); + $sth->execute; + ($bio) = $sth->fetchrow_array; + } + delete $u->{'has_bio'}; + + $u->{'accttype'} = LJ::name_caps($u->{'caps'}); + + if ($u->{'allow_infoshow'} eq "Y") { + LJ::load_user_props($dbr, $u, "opt_whatemailshow", + "country", "state", "city", "zip", + "aolim", "icq", "url", "urlname", + "yahoo", "msn"); + } else { + $u->{'opt_whatemailshow'} = "N"; + } + delete $u->{'allow_infoshow'}; + + if ($u->{'opt_whatemailshow'} eq "L") { + delete $u->{'email'}; + } + if ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail")) { + if ($u->{'email'}) { $u->{'email'} .= ", "; } + $u->{'email'} .= "$user\@$LJ::USER_DOMAIN"; + } + + if ($u->{'opt_whatemailshow'} eq "N") { + delete $u->{'email'}; + } + delete $u->{'opt_whatemailshow'}; + + my $max = 1; + foreach (keys %$u) { + if (length($_) > $max) { $max = length($_); } + } + $max++; + + delete $u->{'caps'}; + + print CL "\nUserinfo for $user...\n\n"; + foreach my $k (sort keys %$u) { + printf CL "%${max}s : %s\n", $k, $u->{$k}; + } + + if ($bio) { + $bio =~ s/^\s+//; + $bio =~ s/\s+$//; + print CL "\nBio:\n\n"; + $Text::Wrap::columns = 77; + print CL Text::Wrap::wrap(" ", " ", $bio); + } + print CL "\n\n"; + + close CL; + next; + + } + + print CL "Unsupported/unimplemented query type: $line\n"; + print CL "length: ", length($line), "\n"; + close CL; + next; +} diff --git a/livejournal/bin/interdoc.pl b/livejournal/bin/interdoc.pl new file mode 100755 index 0000000..63cc8de --- /dev/null +++ b/livejournal/bin/interdoc.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl + +# This script parses LJ dependency info from all the other files on +# that make up the site. Usually that dependency data is at the end +# of the files, but in this file it's here at the top for two reasons: +# as an example, and because otherwise this script would parse itself +# and start at the wrong place. So, here's this file's dependency +# data: +# +# +# lib: Getopt::Long +# +# +# This file parses files for lines containing then starts +# looking for dependency declarations on subsequent lines until +# is found. Note that leading junk is ignored. The +# dependencies are of the form: +# +# type: item, item, item +# +# Where type is one of: +# +# file -- data file +# form -- form with method=GET +# lib -- perl module or library (append :: if ! /::/) +# link -- web link +# mailto -- mailto link +# post -- form with method=POST +# prog -- program that's run +# hook -- LJ hook name +# + +use strict; +use Getopt::Long; + +my $opt_warn = 0; +my $opt_types = 0; +GetOptions('warn' => \$opt_warn, + 'types' => \$opt_types); + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} +chdir $ENV{'LJHOME'} or die "Can't cd to $ENV{'LJOME'}\n"; + +find(qw(bin cgi-bin htdocs)); + +exit; + +sub find +{ + my @dirs = @_; + while (@dirs) + { + my $dir = shift @dirs; + next if ($dir eq "htdocs/img"); + next if ($dir eq "htdocs/doc"); + + opendir (D, $dir); + my @files = sort { $a cmp $b } readdir(D); + close D; + + foreach my $f (@files) { + next if ($f eq "." || $f eq ".."); + my $full = "$dir/$f"; + if (-d $full) { find($full); } + elsif (-f $full) { check_file($full); } + } + } + +} + +sub check_file +{ + $_ = shift; + next unless (-f); + next if (/\.(gif|jpg|png|class|jar|zip|exe|gz|deb|rpm|ico)$/); + next if (/~$/); + + my $file = $_; + my $indep = 0; + my %deps; + + open (F, $file); + while (my $l = ) + { + if (! $indep) { + if ($l =~ //) { + $indep = 1; + $deps{'_found'} = 1; + } + next; + } + + if ($l =~ /<\/LJDEP>/) { + last; + } + + if ($l =~ /(\w+):(.+)/) { + my $k = $1; + my $v = $2; + $v =~ s/^\s+//; + $v =~ s/\s+$//; + my @vs = split(/\s*\,\s*/, $v); + foreach (@vs) { + push @{$deps{$k}}, $_; + } + } + } + close (F); + + if (delete $deps{'_found'}) { + foreach my $t (keys %deps) { + foreach my $v (@{$deps{$t}}) { + if ($opt_types) { + print "$t\n"; + } else { + print join("\t", $file, $t, $v), "\n"; + } + } + } + } else { + if ($opt_warn) { + print STDERR "No dep info: $file\n"; + } + } + +} diff --git a/livejournal/bin/jmk b/livejournal/bin/jmk new file mode 100755 index 0000000..9cafbaf --- /dev/null +++ b/livejournal/bin/jmk @@ -0,0 +1,3 @@ +#!/bin/sh + +java -jar $LJHOME/bin/jmk.jar $@ diff --git a/livejournal/bin/lj-inline.pl b/livejournal/bin/lj-inline.pl new file mode 100755 index 0000000..73ea4ff --- /dev/null +++ b/livejournal/bin/lj-inline.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{LJHOME}/cgi-bin"; + +BEGIN { + $LJ::HAVE_INLINE = eval 'use Inline Config => DIRECTORY => ($ENV{LJ_INLINE_DIR} || "$ENV{LJHOME}/Inline"); use Inline "C"; 1;'; + + # to shutup Apache::SendStat's warning: + $LJ::JUST_COMPILING = 1; +} + +print "This script will recompile ljcom's Inline.pm C code, if necessary. You need a C compiler installed.\n"; + +unless ($LJ::HAVE_INLINE) { + print "\nBut you don't have Inline.pm installed, so quitting now.\n"; + exit 1; +} + +print "Testing your Inline install...\n"; +unless (inline_test()) { + print "Error. Sure you have a C compiler installed?\n"; + exit 1; +} + +print "ljlib/ljlib-local.pl (if anything)...\n"; +require "ljlib.pl"; + +print "Apache::SendStats...\n"; +# wrapped in eval because ap_scoreboard_image isn't around +# when not running inside apache +eval "use Apache::SendStats;"; + +print "Done.\n"; + +__DATA__ +__C__ + +int inline_test () { + printf("Your Inline install is good. Proceeding...\n"); + return 1; +} diff --git a/livejournal/bin/ljblockwatcher.pl b/livejournal/bin/ljblockwatcher.pl new file mode 100755 index 0000000..604ec5a --- /dev/null +++ b/livejournal/bin/ljblockwatcher.pl @@ -0,0 +1,631 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +dbreportd - Report database latencies at regular intervals. + +=head1 SYNOPSIS + + $ dbreportd OPTIONS + +=head1 OPTIONS + +=over 4 + +=item -c, --clearscreen + +Clear the screen and home the cursor before printing each report, like top. May +not work on all terminals. + +=item -d, --debug + +Turn on debugging information. May be specified more than once for (potentially) +increased levels of debugging. + +=item -h, --help + +Output a help message and exit. + +=item -i, --interval=SECONDS + +Set the number of seconds between reports to SECONDS. Defaults to 3 second +intervals. + +=item -p, --port=PORT + +Set the port to listen on for reports. This is set in ljconfig.pl, but can be +overridden here. + +=item -V, --version + +Output version information and exit. + +=back + +=head1 REQUIRES + +I + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This program is Open Source software. You may use, modify, and/or redistribute +this software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +# :TODO: Change param order in received msgs + +############################################################################## +package dbreportd; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + + # Turn STDOUT buffering off + $| = 1; + + # Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: ljblockwatcher.pl,v 1.3 2004/03/09 22:25:05 deveiant Exp $; + + # Define some constants + use constant TRUE => 1; + use constant FALSE => 0; + + # How many time samples to keep around to determine average latency + use constant SAMPLE_DEPTH => 10; + + # How many samples to show in the "top slow queries" + use constant TOP_QUERY_SIZE => 5; + + # ANSI vt100 escape codes for various things + use constant VT100_CLEARSCREEN => "\e[2J"; + use constant VT100_HOME => "\e[0;0H"; + + # Modules + use Getopt::Long qw{GetOptions}; + use Pod::Usage qw{pod2usage}; + + use IO::Socket::INET qw{}; + use IO::Select qw{}; + use Time::HiRes qw{usleep}; + use Data::Dumper qw{}; + + # Turn on option bundling (-vid) + Getopt::Long::Configure( "bundling" ); +} + +our $Debug = FALSE; + +### Main body +MAIN: { + my ( + $helpFlag, # User requested help? + $versionFlag, # User requested version info? + + $interval, # Interval between generated reports + $port, # Port number to listen on + + $msg, # The message buffer for reports + $sock, # UDP socket + $selector, # IO::Select object + $lastReport, # time() of last report output + $host, # Message host + $time, # Message time + $notes, # Message notes + $type, # Operation type (currently unused) + %buffers, # SampleBuffers keyed by host + $clearscreenFlag, # Clear the screen before every report? + ); + + # Print the program header and read in command line options + GetOptions( + 'd|debug+' => \$Debug, + 'h|help' => \$helpFlag, + 'i|interval=i' => \$interval, + 'V|version' => \$versionFlag, + 'p|port=i' => \$port, + 'c|clearscreen' => \$clearscreenFlag, + ) or abortWithUsage(); + + # If the -h flag or -V flag was given, just show the help or version, + # respectively, and exit. + helpMode() and exit if $helpFlag; + versionMode() and exit if $versionFlag; + + # Either get the port from the command line or a default + $port ||= 4774; + + # Set the interval to a default if it wasn't specified + $interval = 3 if !defined $interval; + + # Open a receiving UDP socket + print VT100_CLEARSCREEN, VT100_HOME if $clearscreenFlag; + print "Setting up listener on port $port\n"; + $sock = new IO::Socket::INET ( + Proto => 'udp', + LocalPort => $port + ) or die "Failed to open receiving socket: $!"; + + $selector = new IO::Select; + $selector->add( $sock ); + $lastReport = time(); + + %buffers = (); + + # Print reports every couple of seconds + while ( 1 ) { + if ( $selector->can_read($interval) ) { + + # Get the message and split it back into four parts + my $addr = $sock->recv( $msg, 1024, 0 ); + print ">>> Message: $msg\n" if $Debug; + ( $host, $type, $time, $notes ) = split( /\x3/, $msg, 4 ); + + # Add the time and notes to the table of hosts + $buffers{ $host } ||= new SampleBuffer ( $host, depth => SAMPLE_DEPTH ); + $buffers{ $host }->add( $type, $time, $notes ); + } else { + sleep 0.5; + } + + } continue { + if ( (time() - $lastReport) > $interval ) { + print VT100_CLEARSCREEN, VT100_HOME if $clearscreenFlag; + print_report( values %buffers ); + $lastReport = time(); + } + }; + +} + + +### FUNCTION: print_report( @buffers ) +### Given a list of SampleBuffer objects, print a table with the ones with the +### highest average times. +sub print_report { + my @buffers = @_; + + my ( + $row, # Row count for display + @top, # Top 5 slowest average buffers + %top, # ^-- Hash of same + @sbuffers, # Buffer objects sorted by hostname + @wbuffers, # Buffer objects sorted by worst op + $fmt, # printf format for report rows + $prefix, # Line prefixes + ); + + if ( @buffers ) { + # Pick the 5 slowest operations + @top = + map { $_->[0] } + sort { $b->[1] <=> $a->[1] } + map { [$_->host, $_->average_time] } + @buffers; + $row = 0; + %top = (); + foreach my $host ( @top[0 ... TOP_QUERY_SIZE] ) { + last unless defined $host; + $top{$host} = ++$row unless exists $top{$host}; + } + #print Data::Dumper->Dumpxs( [\%top], ['top'] ), "\n"; + + # Make an array of sorted buffer objects by worst average time + @sbuffers = + map { $_->[0] } + sort { $b->[1] <=> $a->[1] } + map { [$_, $_->average_time] } + @buffers; + + # Make an array of sorted buffer objects by worst time + @wbuffers = + map { $_->[0] } + sort { $b->[1] <=> $a->[1] } + map { [$_, $_->worst_time] } + @buffers; + + # Output all hosts with the average worst operation times + $fmt = "%-2s%25s %0.5fs"; + $row = 0; + header( "Average longest blocking operations, by host" ); + foreach my $buf (@sbuffers) { + $row++; + + if ( exists $top{$buf->host} && $top{$buf->host} <= 3 ) { + $prefix = '+'; + } else { + $prefix = ' '; + } + + printf "$fmt\n", $prefix, $buf->host, $buf->average_time; + } + print "\n"; + + # Output the worst operations with their notes + $row = 0; + $fmt = "%0.5fs: '%s' [%s/%s]\n"; + header( "%d worst blockers", TOP_QUERY_SIZE ); + foreach my $buf (@wbuffers[0 ... TOP_QUERY_SIZE]) { + last unless defined $buf; + $row++; + + my $sample = $buf->worst_sample; + printf( $fmt, + $sample->time, + $sample->notes || "(none)", + $sample->type, + $buf->host ); + } + print "\n"; + + # Print the raw buffer objects if debugging + if ( $Debug ) { + header( "Raw buffers" ); + foreach my $buf ( @buffers ) { + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Terse = TRUE; + print Data::Dumper->Dumpxs( [$buf], ['buf'] ), "\n"; + } + } + + print "\n"; + } + + else { + print "No hosts reporting.\n"; + } +} + + +### FUNCTION: header( $fmt, @args ) +### Printf the given message as a header. +sub header { + my ( $fmt, @args ) = @_; + my $msg = sprintf( $fmt, @args ); + chomp( $msg ); + + print "$msg\n", '-' x 75, "\n"; +} + + +### FUNCTION: helpMode() +### Exit normally after printing the usage message +sub helpMode { + pod2usage( -verbose => 1, -exitval => 0 ); +} + + +### FUNCTION: versionMode() +### Exit normally after printing version information +sub versionMode { + print STDERR "dbreportd $VERSION\n"; + exit; +} + + +### FUNCTION: abortWithUsage() +### Abort the program showing usage message. +sub abortWithUsage { + if ( @_ ) { + pod2usage( -verbose => 1, -exitval => 1, -msg => join('', @_) ); + } else { + pod2usage( -verbose => 1, -exitval => 1 ); + } +} + + +### FUNCTION: abort( @messages ) +### Print the specified messages to the terminal and exit with a non-zero status. +sub abort { + my $msg = @_ ? join '', @_ : "unknown error"; + print STDERR $msg, "\n"; + exit 1; +} + + + +##################################################################### +### T I M E S A M P L E C L A S S +##################################################################### +package Sample; +use strict; + +BEGIN { + use vars qw{$AUTOLOAD}; + use Carp qw{croak confess}; + use Data::Dumper (); + $Data::Dumper::Terse = 1; + $Data::Dumper::Indent = 1; +} + +### METHOD: new( $host ) +### Create a new sample buffer for the given host +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + + my $self = bless { + type => 'db', + time => 0.0, + notes => '', + }, $class; + + if ( @_ && (@_ % 2 == 0) ) { + my %args = @_; + foreach my $meth ( keys %args ) { + $self->$meth( $args{$meth} ); + } + } + + return $self; +} + + + +### FUNCTION: blessed( $var ) +### Returns a true value if the given value is a blessed reference. +sub blessed { + my $arg = shift; + return ref $arg && UNIVERSAL::isa( $arg, 'UNIVERSAL' ); +} + + +### (PROXY) METHOD: AUTOLOAD( @args ) +### Proxy method to build (non-translucent) object accessors. +sub AUTOLOAD { + my $self = shift; + confess "Cannot be called as a function" unless $self && blessed $self; + + ( my $name = $AUTOLOAD ) =~ s{.*::}{}; + + ### Build an accessor for extant attributes + if ( exists $self->{$name} ) { + + ### Define an accessor for this attribute + my $method = sub { + my $closureSelf = shift or confess "Cannot be called as a function"; + $closureSelf->{$name} = shift if @_; + return $closureSelf->{$name}; + }; + + ### Install the new method in the symbol table + NO_STRICT_REFS: { + no strict 'refs'; + *{$AUTOLOAD} = $method; + } + + ### Now jump to the new method after sticking the self-ref back onto the + ### stack + unshift @_, $self; + goto &$AUTOLOAD; + } + + ### Try to delegate to our parent's version of the method + my $parentMethod = "SUPER::$name"; + return $self->$parentMethod( @_ ); +} + +sub DESTROY {} +sub END {} + + + +##################################################################### +### S A M P L E B U F F E R C L A S S +##################################################################### + +### Class for tracking latencies for a given host +package SampleBuffer; +use strict; + +BEGIN { + use Carp qw{croak confess}; + use vars qw{$AUTOLOAD}; +} + + +### METHOD: new( $host ) +### Create a new sample buffer for the given host +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + my $host = shift or die "No hostname given"; + + my $self = bless { + host => $host, + samples => {}, + depth => 10, + }, $class; + + if ( @_ && (@_ % 2 == 0) ) { + my %args = @_; + foreach my $meth ( keys %args ) { + $self->$meth( $args{$meth} ); + } + } + + return $self; +} + + +### METHOD: add( $type, $time, $notes ) +### Add the specified I"; + } + + # Show the link if it's present and different than the + # . + # [zilla: 267] Patch: Chaz Meyers + if ( defined $it->{'id'} && $it->{'id'} ne $it->{'link'} + && $it->{'id'} =~ m!^http://! ) + { + $htmllink .= ""; + } + + # rewrite relative URLs to absolute URLs, but only invoke the HTML parser + # if we see there's some image or link tag, to save us some work if it's + # unnecessary (the common case) + if ($it->{'text'} =~ /<(?:img|a)\b/i) { + # TODO: support XML Base? http://www.w3.org/TR/xmlbase/ + my $base_href = $it->{'link'} || $synurl; + LJ::CleanHTML::resolve_relative_urls(\$it->{'text'}, $base_href); + } + + # $own_time==1 means we took the time from the feed rather than localtime + my ($own_time, $year, $mon, $day, $hour, $min); + + if ($it->{'time'} && + $it->{'time'} =~ m!^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)!) { + $own_time = 1; + ($year, $mon, $day, $hour, $min) = ($1,$2,$3,$4,$5); + } else { + $own_time = 0; + my @now = localtime(); + ($year, $mon, $day, $hour, $min) = + ($now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1]); + } + + my $command = "postevent"; + my $req = { + 'username' => $user, + 'ver' => 1, + 'subject' => $it->{'subject'}, + 'event' => "$htmllink$it->{'text'}", + 'year' => $year, + 'mon' => $mon, + 'day' => $day, + 'hour' => $hour, + 'min' => $min, + 'props' => { + 'syn_link' => $it->{'link'}, + }, + }; + $req->{'props'}->{'syn_id'} = $it->{'id'} + if $it->{'id'}; + + my $flags = { + 'nopassword' => 1, + }; + + # if the post contains html linebreaks, assume it's preformatted. + if ($it->{'text'} =~ /<(?:p|br)\b/i) { + $req->{'props'}->{'opt_preformatted'} = 1; + } + + # do an editevent if we've seen this item before + my $id = $have_ids ? $it->{'id'} : $it->{'link'}; + my $old_itemid = $existing_item{$id}; + if ($id && $old_itemid) { + $newcount--; # cancel increment above + $command = "editevent"; + $req->{'itemid'} = $old_itemid; + + # the editevent requires us to resend the date info, which + # we have to go fetch first, in case the feed doesn't have it + + # TAG:LOG2:synsuck_fetch_itemdates + unless($own_time) { + my $origtime = + $udbh->selectrow_array("SELECT eventtime FROM log2 WHERE ". + "journalid=? AND jitemid=?", undef, + $su->{'userid'}, $old_itemid); + $origtime =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/; + $req->{'year'} = $1; + $req->{'mon'} = $2; + $req->{'day'} = $3; + $req->{'hour'} = $4; + $req->{'min'} = $5; + } + } + + my $err; + my $res = LJ::Protocol::do_request($command, $req, \$err, $flags); + unless ($res && ! $err) { + print " Error: $err\n" if $verbose; + $errorflag = 1; + } + } + + # delete some unneeded synitems. the limit 1000 is because + # historically we never deleted and there are accounts with + # 222,000 items on a myisam table, and that'd be quite the + # delete hit. + # the 14 day interval is because if a remote site deleted an + # entry, it's possible for the oldest item that was previously + # gone to reappear, and we want to protect against that a + # little. + if ($LJ::SYNITEM_CLEAN) { + $dbh->do("DELETE FROM synitem WHERE userid=? AND ". + "dateadd < ? - INTERVAL 14 DAY LIMIT 1000", + undef, $userid, $mindate); + } + $dbh->do("UPDATE syndicated SET oldest_ourdate=? WHERE userid=?", + undef, $mindate, $userid); + + # bail out if errors, and try again shortly + if ($errorflag) { + $delay->(30, "posterror"); + return; + } + + # update syndicated account's userinfo if necessary + LJ::load_user_props($su, "url", "urlname"); + { + my $title = $feed->{'title'}; + $title = $su->{'user'} unless LJ::is_utf8($title); + $title =~ s/[\n\r]//g; + if ($title && $title ne $su->{'name'}) { + LJ::update_user($su, { name => $title }); + LJ::set_userprop($su, "urlname", $title); + } + + my $link = $feed->{'link'}; + if ($link && $link ne $su->{'url'}) { + LJ::set_userprop($su, "url", $link); + } + + my $des = $feed->{'description'}; + if ($des) { + my $bio; + if ($su->{'has_bio'} eq "Y") { + $bio = $udbh->selectrow_array("SELECT bio FROM userbio WHERE userid=?", undef, + $su->{'userid'}); + } + if ($bio ne $des && $bio !~ /\[LJ:KEEP\]/) { + if ($des) { + $su->do("REPLACE INTO userbio (userid, bio) VALUES (?,?)", undef, + $su->{'userid'}, $des); + } else { + $su->do("DELETE FROM userbio WHERE userid=?", undef, $su->{'userid'}); + } + LJ::update_user($su, { has_bio => ($des ? "Y" : "N") }); + LJ::MemCache::delete([$su->{'userid'}, "bio:$su->{'userid'}"]); + } + } + } + + my $r_lastmod = LJ::http_to_time($res->header('Last-Modified')); + my $r_etag = $res->header('ETag'); + + # decide when to poll next (in minutes). + # FIXME: this is super lame. (use hints in RSS file!) + my $int = $newcount ? 30 : 60; + my $status = $newcount ? "ok" : "nonew"; + my $updatenew = $newcount ? ", lastnew=NOW()" : ""; + + # update reader count while we're changing things, but not + # if feed is stale (minimize DB work for inactive things) + if ($newcount || ! defined $readers) { + $readers = $dbh->selectrow_array("SELECT COUNT(*) FROM friends WHERE ". + "friendid=?", undef, $userid); + } + + # if readers are gone, don't check for a whole day + $int = 60*24 unless $readers; + + $dbh->do("UPDATE syndicated SET checknext=DATE_ADD(NOW(), INTERVAL $int MINUTE), ". + "lastcheck=NOW(), lastmod=?, etag=?, laststatus=?, numreaders=? $updatenew ". + "WHERE userid=$userid", undef, $r_lastmod, $r_etag, $status, $readers); + }; + + ### + ### child process management + ### + + # get the next user to be processed + my @all_users; + my $get_next_user = sub { + return shift @all_users if @all_users; + + # need to get some more rows + my $dbh = LJ::get_db_writer(); + my $current_jobs = join(",", map { $dbh->quote($_->[0]) } values %child_jobs); + my $in_sql = " AND u.userid NOT IN ($current_jobs)" if $current_jobs; + my $sth = $dbh->prepare("SELECT u.user, s.userid, s.synurl, s.lastmod, " . + " s.etag, s.numreaders, s.checknext " . + "FROM user u, syndicated s " . + "WHERE u.userid=s.userid AND u.statusvis='V' " . + "AND s.checknext < NOW()$in_sql " . + "ORDER BY RAND() LIMIT 500"); + $sth->execute; + while (my $urow = $sth->fetchrow_hashref) { + push @all_users, $urow; + } + + return undef unless @all_users; + return shift @all_users; + }; + + # fork and manage child processes + my $max_threads = $LJ::SYNSUCK_MAX_THREADS || 1; + print "[$$] PARENT -- using $max_threads workers\n" if $verbose; + + my $threads = 0; + my $userct = 0; + my $keep_forking = 1; + while ( $maxcount == 0 || $userct < $maxcount ) { + + if ($threads < $max_threads && $keep_forking) { + my $urow = $get_next_user->(); + unless ($urow) { + $keep_forking = 0; + next; + } + + my $lockname = "synsuck-user-" . $urow->{user}; + my $lock = LJ::locker()->trylock($lockname); + next unless $lock; + print "Got lock on '$lockname'. Running\n" if $verbose; + + # spawn a new process + if (my $pid = fork) { + # we are a parent, nothing to do? + $child_jobs{$pid} = [$urow->{'userid'}, $lock]; + $threads++; + $userct++; + } else { + # handles won't survive the fork + LJ::disconnect_dbs(); + $process_user->($urow); + exit 0; + } + + # wait for child(ren) to die + } else { + my $child = wait(); + last if $child == -1; + delete $child_jobs{$child}; + $threads--; + } + } + + # Now wait on any remaining children so we don't leave zombies behind. + while ( %child_jobs ) { + my $child = wait(); + last if $child == -1; + delete $child_jobs{ $child }; + $threads--; + } + + print "[$$] $userct users processed\n" if $verbose; + return; +}; + +1; + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/livejournal/bin/maint/taskinfo.txt b/livejournal/bin/maint/taskinfo.txt new file mode 100755 index 0000000..6fcca4a --- /dev/null +++ b/livejournal/bin/maint/taskinfo.txt @@ -0,0 +1,27 @@ +bday.pl: + bdaymail - Sends people birthday wishes & notifications + +stats.pl: + build_randomuserset - builds/cleans table of users applicable for inclusion in random listings + genstats - Generates the nightly statistics + genstats_size - Generates the site size stats + genstats_weekly - Generates the weekly statistics + memeclean - Removes things from meme summary that are excluded by new URL cleaner rules + +statspics.pl: + genstatspics - Makes a bunch of graphs to show on the statistics page. + +clean_caches.pl: + clean_caches - removes old cache files + +synsuck.pl: + synsuck - Polls needed remote, syndicated RSS/etc and updates journals. + +captcha.pl: + gen_audio_captchas - Generate any needed new audio challenges. + gen_image_captchas - Generate any needed new graphical challenges. + clean_captchas - Purge old challenges from the database. + +generic.pl: + joinmail - Generates daily email digests for community join requests + clean_spamreports - Clean out data from the spamreports table older than 90 days. diff --git a/livejournal/bin/moveucluster.pl b/livejournal/bin/moveucluster.pl new file mode 100755 index 0000000..cc0a2d3 --- /dev/null +++ b/livejournal/bin/moveucluster.pl @@ -0,0 +1,1000 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +moveucluster.pl - Moves a LiveJournal user between database clusters + +=head1 SYNOPSIS + + $ moveucluster.pl OPTIONS + +=head1 OPTIONS + +=over 4 + +=item -h, --help + +Output a help message and exit. + +=item --verbose[=] + +Verbosity level, 0, 1, or 2. + +=item --verify + +Verify count of copied rows to ensure accuracy (slower) + +=item --ignorebit + +Ignore the move in progress bit (force user move) + +=item --prelocked + +Do not set user readonly and sleep (somebody else did it) + +=item --delete + +Delete data from source cluster when done moving + +=item --destdelete + +Delete data from destination cluster before moving + +=item --expungedel + +The expungedel option is used to indicate that when a user is encountered +with a statusvis of D (deleted journal) and they've been deleted for at +least 31 days, instead of moving their data, mark the user as expunged. + +Further, if you specify the delete and expungedel options at the same time, +if the user is expunged, all of their data will be deleted from the source +cluster. THIS IS IRREVERSIBLE AND YOU WILL NOT BE ASKED FOR CONFIRMATION. + +=item --jobserver=host:port + +Specify a job server to get tasks from. In this mode, no other +arguments are necessary, and moveucluster.pl just runs in a loop +getting directions from the job server. + +=back + +=head1 AUTHOR + +Brad Fitzpatrick Ebrad@danga.comE +Copyright (c) 2002-2004 Danga Interactive. All rights reserved. + +=cut + +############################################################################## + +use strict; +use Getopt::Long; +use Pod::Usage qw{pod2usage}; +use IO::Socket::INET; + +# NOTE: these options are used both by Getopt::Long for command-line parsing +# in single user move move, and also set by hand when in --jobserver mode, +# and the jobserver gives us directions, including whether or not users +# are prelocked, need to be source-deleted, verified, etc, etc, etc. +my $opt_del = 0; +my $opt_destdel = 0; +my $opt_verbose = 1; +my $opt_movemaster = 0; +my $opt_prelocked = 0; +my $opt_expungedel = 0; +my $opt_ignorebit = 0; +my $opt_verify = 0; +my $opt_help = 0; +my $opt_jobserver = ""; + +abortWithUsage() unless + GetOptions('delete' => \$opt_del, # from source + 'destdelete' => \$opt_destdel, # from dest (if exists, before moving) + 'verbose=i' => \$opt_verbose, + 'movemaster|mm' => \$opt_movemaster, # use separate dedicated source + 'prelocked' => \$opt_prelocked, # don't do own locking; master does (harness, ljumover) + 'expungedel' => \$opt_expungedel, # mark as expunged if possible (+del to delete) + 'ignorebit' => \$opt_ignorebit, # ignore move in progress bit cap (force) + 'verify' => \$opt_verify, # slow verification pass (just for debug) + 'jobserver=s' => \$opt_jobserver, + 'help' => \$opt_help, + ); +my $optv = $opt_verbose; + +my $dbo; # original cluster db handle. (may be a movemaster (a slave)) +my $dboa; # the actual master handle, which we delete from if deleting from source + +abortWithUsage() if $opt_help; + +if ($opt_jobserver) { + multiMove(); +} else { + singleMove(); +} + +sub multiMove { + # the job server can keep giving us new jobs to move (or a stop command) + # over and over, so we avoid perl exec times + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + + my $sock; + ITER: + while (1) { + if ($sock && $sock->connected) { + my $pipe = 0; + local $SIG{PIPE} = sub { $pipe = 1; }; + + LJ::start_request(); + my $dbh = LJ::get_dbh({raw=>1}, "master"); + unless ($dbh) { + print " master db unavailable\n"; + sleep 2; + next ITER; + } + $dbh->do("SET wait_timeout=28800"); + + my $rv = $sock->write("get_job\r\n"); + + if ($pipe || ! $rv) { + $sock = undef; + sleep 1; + next ITER; + } + my $line = <$sock>; + unless ($line) { + $sock = undef; + sleep 1; + next ITER; + } + + if ($line =~ /^OK IDLE/) { + print "Idling.\n"; + sleep 5; + next ITER; + } elsif ($line =~ /^OK JOB (\d+):(\d+):(\d+)\s+([\d.]+)(?:\s+([\w= ]+))?\r?\n/) { + my ($uid, $srcid, $dstid, $locktime) = ($1, $2, $3, $4); + my $opts = parseOpts($5); + + print "Got a job: $uid:$srcid:$dstid, locked for=$locktime, opts: [", + join(", ", map { "$_=$opts->{$_}" } grep { $opts->{$_} } keys %$opts), + "]\n"; + + my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE userid=?", + undef, $uid); + next ITER unless $u; + next ITER unless $u->{clusterid} == $srcid; + + my $verify = sub { + my $pipe = 0; + local $SIG{PIPE} = sub { $pipe = 1; }; + my $rv = $sock->write("finish $uid:$srcid:$dstid\r\n"); + return 0 unless $rv; + my $res = <$sock>; + return $res =~ /^OK/ ? 1 : 0; + }; + + # If the user is supposed to be prelocked, but the lock didn't + # happen more than 3 seconds ago, wait until it has time to + # "settle" and then move the user + if ( $opts->{prelocked} && $locktime < 3 ) { + sleep 3 - $locktime; + } + + my $rv = eval { moveUser($dbh, $u, $dstid, $verify, $opts); }; + if ($rv) { + print "moveUser($u->{user}/$u->{userid}) = 1\n"; + } else { + print "moveUser($u->{user}/$u->{userid}) = fail: $@\n"; + } + LJ::end_request(); + LJ::disconnect_dbs(); # end_request could do this, but we want to force it + } else { + die "Unknown response from server: $line\n"; + } + } else { + print "Need job server sock...\n"; + $sock = IO::Socket::INET->new(PeerAddr => $opt_jobserver, + Proto => 'tcp', ); + unless ($sock) { + print " failed.\n"; + sleep 1; + next ITER; + } + my $ready = <$sock>; + if ($ready =~ /Ready/) { + print "Connected.\n"; + } else { + print "Bogus greeting.\n"; + $sock = undef; + sleep 1; + next ITER; + } + } + + } +} + +### Parse options from job specs into a hashref +sub parseOpts { + my $raw = shift || ""; + my $opts = {}; + + while ( $raw =~ m{\s*(\w+)=(\w+)}g ) { + $opts->{ $1 } = $2; + } + + foreach my $opt (qw(del destdel movemaster prelocked + expungedel ignorebit verify)) { + next if defined $opts->{$opt}; + $opts->{$opt} = eval "\$opt_$opt"; + } + + return $opts; +} + + +sub singleMove { + my $user = shift @ARGV; + my $dclust = shift @ARGV; + $dclust = 0 if !defined $dclust && $opt_expungedel; + + # check arguments + abortWithUsage() unless defined $user && defined $dclust; + + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + + $user = LJ::canonical_username($user); + abortWithUsage("Invalid username") unless length($user); + + my $dbh = LJ::get_dbh({raw=>1}, "master"); + die "No master db available.\n" unless $dbh; + $dbh->do("SET wait_timeout=28800"); + + my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE user=?", undef, $user); + + my $opts = parseOpts(""); # gets command-line opts + my $rv = eval { moveUser($dbh, $u, $dclust, undef, $opts); }; + + if ($rv) { + print "Moved '$user' to cluster $dclust.\n"; + exit 0; + } + if ($@) { + die "Failed to move '$user' to cluster $dclust: $@\n"; + } + + print "ERROR: move failed.\n"; + exit 1; +} + +sub moveUser { + my ($dbh, $u, $dclust, $verify_code, $opts) = @_; + die "Non-existent db.\n" unless $dbh; + die "Non-existent user.\n" unless $u && $u->{userid}; + my $user = $u->{user}; + + # get lock + die "Failed to get move lock.\n" + unless $dbh->selectrow_array("SELECT GET_LOCK('moveucluster-$u->{userid}', 5)"); + + # if we want to delete the user, we don't need a destination cluster, so only get + # one if we have a real valid destination cluster + my $dbch; + if ($dclust) { + # get the destination DB handle, with a long timeout + $dbch = LJ::get_cluster_master({raw=>1}, $dclust); + die "Undefined or down cluster \#$dclust\n" unless $dbch; + $dbch->do("SET wait_timeout=28800"); + + # make sure any error is a fatal error. no silent mistakes. + $dbh->{'RaiseError'} = 1; + $dbch->{'RaiseError'} = 1; + } + + # we can't move to the same cluster + my $sclust = $u->{'clusterid'}; + if ($sclust == $dclust) { + die "User '$user' is already on cluster $dclust\n"; + } + + # we don't support "cluster 0" (the really old format) + die "This mover tool doesn't support moving from cluster 0.\n" unless $sclust; + die "Can't move back to legacy cluster 0\n" unless $dclust || $opts->{expungedel}; + my $is_movemaster; + + # for every DB handle we touch, make a signature of a sorted + # comma-delimited signature onto this list. likewise with the + # list of tables this mover script knows about. if ANY signature + # in this list isn't identical, we just abort. perhaps this + # script wasn't updated, or a long-running mover job wasn't + # restarted and new tables were added to the schema. + my @alltables = (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL); + my $mover_sig = join(",", sort @alltables); + + my $get_sig = sub { + my $hnd = shift; + return join(",", sort + @{ $hnd->selectcol_arrayref("SHOW TABLES") }); + }; + + my $global_sig = $get_sig->($dbh); + + my $check_sig = sub { + my $hnd = shift; + my $name = shift; + + # no signature checks on expunges + return if ! $hnd && $opts->{expungedel}; + + my $sig = $get_sig->($hnd); + + # special case: signature can be that of the global + return if $sig eq $global_sig; + + if ($sig ne $mover_sig) { + my %sigt = map { $_ => 1 } split(/,/, $sig); + my @err; + foreach my $tbl (@alltables) { + unless ($sigt{$tbl}) { + # missing a table the mover knows about + push @err, "-$tbl"; + next; + } + delete $sigt{$tbl}; + } + foreach my $tbl (sort keys %sigt) { + push @err, "?$tbl"; + } + if (@err) { + die "Table signature for $name doesn't match! Stopping. [@err]\n"; + } + } + }; + + $check_sig->($dbch, "dbch(database dst)"); + + # the actual master handle, which we delete from if deleting from source + $dboa = LJ::get_cluster_master({raw=>1}, $u); + die "Can't get source cluster handle.\n" unless $dboa; + $check_sig->($dboa, "dboa(database src)"); + + if ($opts->{movemaster}) { + # if an a/b cluster, the movemaster (the source for moving) is + # the opposite side. if not a/b, then look for a special "movemaster" + # role for that clusterid + my $mm_role = "cluster$u->{clusterid}"; + my $ab = lc($LJ::CLUSTER_PAIR_ACTIVE{$u->{clusterid}}); + if ($ab eq "a") { + $mm_role .= "b"; + } elsif ($ab eq "b") { + $mm_role .= "a"; + } else { + $mm_role .= "movemaster"; + } + + $dbo = LJ::get_dbh({raw=>1}, $mm_role); + die "Couldn't get movemaster handle" unless $dbo; + $check_sig->($dbo, "dbo(movemaster)"); + + $dbo->{'RaiseError'} = 1; + $dbo->do("SET wait_timeout=28800"); + my $ss = $dbo->selectrow_hashref("show slave status"); + die "Move master not a slave?" unless $ss; + $is_movemaster = 1; + } else { + $dbo = $dboa; + } + $dboa->{'RaiseError'} = 1; + $dboa->do("SET wait_timeout=28800"); + + my $userid = $u->{'userid'}; + + # load the info on how we'll move each table. this might die (if new tables + # with bizarre layouts are added which this thing can't auto-detect) so want + # to do it early. + my $tinfo; # hashref of $table -> { + # 'idx' => $index_name # which we'll be using to iterate over + # 'idxcol' => $col_name # first part of index + # 'cols' => [ $col1, $col2, ] + # 'pripos' => $idxcol_pos, # what field in 'cols' is $col_name + # 'verifykey' => $col # key used in the debug --verify pass + # } + $tinfo = fetchTableInfo(); + + # see hack below + my $prop_icon = LJ::get_prop("talk", "subjecticon"); + my %rows_skipped; # $tablename -> $skipped_rows_count + + # find readonly cap class, complain if not found + my $readonly_bit = undef; + foreach (keys %LJ::CAP) { + if ($LJ::CAP{$_}->{'_name'} eq "_moveinprogress" && + $LJ::CAP{$_}->{'readonly'} == 1) { + $readonly_bit = $_; + last; + } + } + unless (defined $readonly_bit) { + die "Won't move user without %LJ::CAP capability class named '_moveinprogress' with readonly => 1\n"; + } + + # make sure a move isn't already in progress + if ($opts->{prelocked}) { + unless (($u->{'caps'}+0) & (1 << $readonly_bit)) { + die "User '$user' should have been prelocked.\n"; + } + } else { + if (($u->{'caps'}+0) & (1 << $readonly_bit)) { + die "User '$user' is already in the process of being moved? (cap bit $readonly_bit set)\n" + unless $opts->{ignorebit}; + } + } + + if ($opts->{expungedel} && $u->{'statusvis'} eq "D" && + LJ::mysqldate_to_time($u->{'statusvisdate'}) < time() - 86400*31) { + + print "Expunging user '$u->{'user'}'\n"; + $dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart, timedone) ". + "VALUES (?,?,?,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())", undef, + $userid, $sclust, 0); + + LJ::update_user($userid, { clusterid => 0, + statusvis => 'X', + raw => "caps=caps&~(1<<$readonly_bit), statusvisdate=NOW()" }) + or die "Couldn't update user to expunged"; + + # now delete all content from user cluster for this user + if ($opts->{del}) { + print "Deleting expungeable user data...\n" if $optv; + + # figure out if they have any S1 styles + my $styleids = $dboa->selectcol_arrayref("SELECT styleid FROM s1style WHERE userid = $userid"); + + # now delete from the main tables + foreach my $table (keys %$tinfo) { + my $pri = $tinfo->{$table}->{idxcol}; + while ($dboa->do("DELETE FROM $table WHERE $pri=$userid LIMIT 1000") > 0) { + print " deleted from $table\n" if $optv; + } + } + + # and from the s1stylecache table + if (@$styleids) { + my $styleids_in = join(",", map { $dboa->quote($_) } @$styleids); + if ($dboa->do("DELETE FROM s1stylecache WHERE styleid IN ($styleids_in)") > 0) { + print " deleted from s1stylecache\n" if $optv; + } + } + + $dboa->do("DELETE FROM clustertrack2 WHERE userid=?", undef, $userid); + } + return 1; + } + + # if we get to this point we have to enforce that there's a destination cluster, because + # apparently the user failed the expunge test + if (!defined $dclust || !defined $dbch) { + die "User is not eligible for expunging.\n" if $opts->{expungedel}; + } + + + # returns state string, with a/b, readonly, and flush states. + # string looks like: + # "src(34)=a,dst(42)=b,readonly(34)=0,readonly(42)=0,src_flushes=32 + # because if: + # src a/b changes: lose readonly lock? + # dst a/b changes: suspect. did one side crash? was other side caught up? + # read-only changes: signals maintenance + # flush counts change: causes HANDLER on src to lose state and reset + my $stateString = sub { + my $post = shift; # false for before, true for "after", which forces a config reload + + if ($post) { + do "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + do "$ENV{'LJHOME'}/cgi-bin/ljdefaults.pl"; + } + + my @s; + push @s, "src($sclust)=" . $LJ::CLUSTER_PAIR_ACTIVE{$sclust}; + push @s, "dst($dclust)=" . $LJ::CLUSTER_PAIR_ACTIVE{$dclust}; + push @s, "readonly($sclust)=" . ($LJ::READONLY_CLUSTER{$sclust} ? 1 : 0); + push @s, "readonly($dclust)=" . ($LJ::READONLY_CLUSTER{$dclust} ? 1 : 0); + + my $flushes = 0; + my $sth = $dbo->prepare("SHOW STATUS LIKE '%flush%'"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) { + $flushes += $r->{Value} if $r->{Variable_name} =~ /^Com_flush|Flush_commands$/; + } + push @s, "src_flushes=" . $flushes; + + return join(",", @s); + }; + + print "Moving '$u->{'user'}' from cluster $sclust to $dclust\n" if $optv >= 1; + my $pre_state = $stateString->(); + + # mark that we're starting the move + $dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart) ". + "VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $userid, $sclust, $dclust); + my $cmid = $dbh->{'mysql_insertid'}; + + # set readonly cap bit on user + unless ($opts->{prelocked} || + LJ::update_user($userid, { raw => "caps=caps|(1<<$readonly_bit)" })) + { + die "Failed to set readonly bit on user: $user\n"; + } + $dbh->do("SELECT RELEASE_LOCK('moveucluster-$u->{userid}')"); + + unless ($opts->{prelocked}) { + # wait a bit for writes to stop if journal is somewhat active (last week update) + my $secidle = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ". + "FROM userusage WHERE userid=$userid"); + if ($secidle) { + sleep(2) unless $secidle > 86400*7; + sleep(1) unless $secidle > 86400; + } + } + + if ($is_movemaster) { + my $diff = 999_999; + my $tolerance = 50_000; + while ($diff > $tolerance) { + my $ss = $dbo->selectrow_hashref("show slave status"); + if ($ss->{'Slave_IO_Running'} eq "Yes" && $ss->{'Slave_SQL_Running'} eq "Yes") { + if ($ss->{'Master_Log_File'} eq $ss->{'Relay_Master_Log_File'}) { + $diff = $ss->{'Read_Master_Log_Pos'} - $ss->{'Exec_master_log_pos'}; + print " diff: $diff\n" if $optv >= 1; + sleep 1 if $diff > $tolerance; + } else { + print " (Wrong log file): $ss->{'Relay_Master_Log_File'}($ss->{'Exec_master_log_pos'}) not $ss->{'Master_Log_File'}($ss->{'Read_Master_Log_Pos'})\n" if $optv >= 1; + } + } else { + die "Movemaster slave not running"; + } + } + } + + print "Moving away from cluster $sclust\n" if $optv; + + my %cmd_done; # cmd_name -> 1 + while (my $cmd = $dboa->selectrow_array("SELECT cmd FROM cmdbuffer WHERE journalid=$userid")) { + die "Already flushed cmdbuffer job '$cmd' -- it didn't take?\n" if $cmd_done{$cmd}++; + print "Flushing cmdbuffer for cmd: $cmd\n" if $optv > 1; + require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl"; + LJ::Cmdbuffer::flush($dbh, $dboa, $cmd, $userid); + } + + # setup dependencies (we can skip work by not checking a table if we know + # its dependent table was empty). then we have to order things so deps get + # processed first. + my %was_empty; # $table -> bool, table was found empty + my %dep = ( + "logtext2" => "log2", + "logprop2" => "log2", + "logsec2" => "log2", + "talkprop2" => "talk2", + "talktext2" => "talk2", + "phoneposttrans" => "phonepostentry", # FIXME: ljcom + "modblob" => "modlog", + "sessions_data" => "sessions", + "memkeyword2" => "memorable2", + "userpicmap2" => "userpic2", + "logtagsrecent" => "usertags", + "logtags" => "usertags", + "logkwsum" => "usertags", + ); + + # all tables we could be moving. we need to sort them in + # order so that we check dependant tables first + my @tables; + push @tables, grep { ! $dep{$_} } @alltables; + push @tables, grep { $dep{$_} } @alltables; + + # these are ephemeral or handled elsewhere + my %skip_table = ( + "cmdbuffer" => 1, # pre-flushed + "events" => 1, # handled by qbufferd (not yet used) + "s1stylecache" => 1, # will be recreated + "captcha_session" => 1, # temporary + "tempanonips" => 1, # temporary ip storage for spam reports + "recentactions" => 1, # pre-flushed by clean_caches + "pendcomments" => 1, # don't need to copy these + ); + + $skip_table{'inviterecv'} = 1 if $u->{journaltype} ne 'P'; # non-person, skip invites received + $skip_table{'invitesent'} = 1 if $u->{journaltype} ne 'C'; # not community, skip invites sent + + # we had a concern at the time of writing this dependency optization + # that we might use "log3" and "talk3" tables in the future with the + # old talktext2/etc tables. if that happens and we forget about this, + # this code will trip it up and make us remember: + if (grep { $_ eq "log3" || $_ eq "talk3" } @tables) { + die "This script needs updating.\n"; + } + + # check if dest has existing data for this user. (but only check a few key tables) + # if anything else happens to have data, we'll just fail later. but unlikely. + print "Checking for existing data on target cluster...\n" if $optv > 1; + foreach my $table (qw(userbio talkleft log2 talk2 sessions userproplite2)) { + my $ti = $tinfo->{$table} or die "No table info for $table. Aborting."; + + eval { $dbch->do("HANDLER $table OPEN"); }; + if ($@) { + die "This mover currently only works on MySQL 4.x and above.\n" . + $@; + } + + my $idx = $ti->{idx}; + my $is_there = $dbch->selectrow_array("HANDLER $table READ `$idx` = ($userid) LIMIT 1"); + $dbch->do("HANDLER $table CLOSE"); + next unless $is_there; + + if ($opts->{destdel}) { + foreach my $table (@tables) { + # these are ephemeral or handled elsewhere + next if $skip_table{$table}; + my $ti = $tinfo->{$table} or die "No table info for $table. Aborting."; + my $pri = $ti->{idxcol}; + while ($dbch->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) { + print " deleted from $table\n" if $optv; + } + } + last; + } else { + die " Existing data on destination cluster\n"; + } + } + + # start copying from source to dest. + my $rows = 0; + my @to_delete; # array of [ $table, $prikey ] + my @styleids; # to delete, potentially + + foreach my $table (@tables) { + next if $skip_table{$table}; + + # people accounts don't have moderated posts + next if $u->{'journaltype'} eq "P" && ($table eq "modlog" || + $table eq "modblob"); + + # don't waste time looking at dependent tables with empty parents + next if $dep{$table} && $was_empty{$dep{$table}}; + + my $ti = $tinfo->{$table} or die "No table info for $table. Aborting."; + my $idx = $ti->{idx}; + my $idxcol = $ti->{idxcol}; + my $cols = $ti->{cols}; + my $pripos = $ti->{pripos}; + + # if we're going to be doing a verify operation later anyway, let's do it + # now, so we can use the knowledge of rows per table to hint our $batch_size + my $expected_rows = undef; + my $expected_remain = undef; # expected rows remaining (unread) + my $verifykey = $ti->{verifykey}; + my %pre; + + if ($opts->{verify} && $verifykey) { + $expected_rows = 0; + if ($table eq "dudata" || $table eq "ratelog") { + $expected_rows = $dbo->selectrow_array("SELECT COUNT(*) FROM $table WHERE $idxcol=$userid"); + } else { + my $sth; + $sth = $dbo->prepare("SELECT $verifykey FROM $table WHERE $idxcol=$userid"); + $sth->execute; + while (my @ar = $sth->fetchrow_array) { + $_ = join(",",@ar); + $pre{$_} = 1; + $expected_rows++; + } + } + + # no need to continue with tables that don't have any data + unless ($expected_rows) { + $was_empty{$table} = 1; + next; + } + + $expected_remain = $expected_rows; + } + + eval { $dbo->do("HANDLER $table OPEN"); }; + if ($@) { + die "This mover currently only works on MySQL 4.x and above.\n". + $@; + } + + my $tct = 0; # total rows read for this table so far. + my $hit_otheruser = 0; # bool, set to true when we encounter data from a different userid + my $batch_size; # how big of a LIMIT we'll be doing + my $ct = 0; # rows read in latest batch + my $did_start = 0; # bool, if process has started yet (used to enter loop, and control initial HANDLER commands) + my $pushed_delete = 0; # bool, if we've pushed this table on the delete list (once we find it has something) + + my $sqlins = ""; + my $sqlvals = 0; + my $flush = sub { + return unless $sqlins; + print "# Flushing $table ($sqlvals recs, ", length($sqlins), " bytes)\n" if $optv; + $dbch->do($sqlins); + $sqlins = ""; + $sqlvals = 0; + }; + + my $insert = sub { + my $r = shift; + + # there was an old bug where we'd populate in the database + # the choice of "none" for comment subject icon, instead of + # just storing nothing. this hack prevents migrating those. + if ($table eq "talkprop2" && + $r->[2] == $prop_icon->{id} && + $r->[3] eq "none") { + $rows_skipped{"talkprop2"}++; + return; + } + + # now that we know it has something to delete (many tables are empty for users) + unless ($pushed_delete++) { + push @to_delete, [ $table, $idxcol ]; + } + + if ($sqlins) { + $sqlins .= ", "; + } else { + $sqlins = "INSERT INTO $table (" . join(', ', @{$cols}) . ") VALUES "; + } + $sqlins .= "(" . join(", ", map { $dbo->quote($_) } @$r) . ")"; + + $sqlvals++; + $flush->() if $sqlvals > 5000 || length($sqlins) > 800_000; + }; + + # let tables perform extra processing on the $r before it's + # sent off for inserting. + my $magic; + + # we know how to compress these two tables (currently the only two) + if ($table eq "logtext2" || $table eq "talktext2") { + $magic = sub { + my $r = shift; + return unless length($r->[3]) > 200; + LJ::text_compress(\$r->[3]); + }; + } + if ($table eq "s1style") { + $magic = sub { + my $r = shift; + push @styleids, $r->[0]; + }; + } + + # calculate the biggest batch size that can reasonably fit in memory + my $max_batch = 10000; + $max_batch = 1000 if $table eq "logtext2" || $table eq "talktext2"; + + while (! $hit_otheruser && ($ct == $batch_size || ! $did_start)) { + my $qry; + if ($did_start) { + # once we've done the initial big read, we want to walk slowly, because + # a LIMIT of 1000 will read 1000 rows, regardless, which may be 995 + # seeks into somebody else's journal that we don't care about. + # on the other hand, if we did a --verify check above, we have a good + # idea what to expect still, so we'll use that instead of just 25 rows. + $batch_size = $expected_remain > 0 ? $expected_remain + 1 : 25; + if ($batch_size > $max_batch) { $batch_size = $max_batch; } + $expected_remain -= $batch_size; + + $qry = "HANDLER $table READ `$idx` NEXT LIMIT $batch_size"; + } else { + # when we're first starting out, though, let's LIMIT as high as possible, + # since MySQL (with InnoDB only?) will only return rows matching the primary key, + # so we'll try as big as possible. but not with myisam -- need to start + # small there too, unless we have a guess at the number of rows remaining. + + my $src_is_innodb = 0; # FIXME: detect this. but first verify HANDLER differences. + if ($src_is_innodb) { + $batch_size = $max_batch; + } else { + # MyISAM's HANDLER behavior seems to be different. + # it always returns batch_size, so we keep it + # small to avoid seeks, even on the first query + # (where InnoDB differs and stops when primary key + # doesn't match) + $batch_size = 25; + if ($table eq "clustertrack2" || $table eq "userbio" || + $table eq "s1usercache" || $table eq "s1overrides") { + # we know these only have 1 row, so 2 will be enough to show + # in one pass that we're done. + $batch_size = 2; + } elsif (defined $expected_rows) { + # if we know how many rows remain, let's try to use that (+1 to stop it) + $batch_size = $expected_rows + 1; + if ($batch_size > $max_batch) { $batch_size = $max_batch; } + $expected_remain -= $batch_size; + } + } + + $qry = "HANDLER $table READ `$idx` = ($userid) LIMIT $batch_size"; + $did_start = 1; + } + + my $sth = $dbo->prepare($qry); + $sth->execute; + + $ct = 0; + while (my $r = $sth->fetchrow_arrayref) { + if ($r->[$pripos] != $userid) { + $hit_otheruser = 1; + last; + } + $magic->($r) if $magic; + $insert->($r); + $tct++; + $ct++; + } + } + $flush->(); + + $dbo->do("HANDLER $table CLOSE"); + + # verify the important tables, even if --verify is off. + if (! $opts->{verify} && $table =~ /^(talk|log)(2|text2)$/) { + my $dblcheck = $dbo->selectrow_array("SELECT COUNT(*) FROM $table WHERE $idxcol=$userid"); + die "# Expecting: $dblcheck, but got $tct\n" unless $dblcheck == $tct; + } + + if ($opts->{verify} && $verifykey) { + if ($table eq "dudata" || $table eq "ratelog") { + print "# Verifying $table on size\n"; + my $post = $dbch->selectrow_array("SELECT COUNT(*) FROM $table WHERE $idxcol=$userid"); + die "Moved sized is smaller" if $post < $expected_rows; + } else { + print "# Verifying $table on key $verifykey\n"; + my %post; + my $sth; + + $sth = $dbch->prepare("SELECT $verifykey FROM $table WHERE $idxcol=$userid"); + $sth->execute; + while (my @ar = $sth->fetchrow_array) { + $_ = join(",",@ar); + unless (delete $pre{$_}) { + die "Mystery row showed up in $table: uid=$userid, $verifykey=$_"; + } + } + my $count = scalar keys %pre; + die "Rows not moved for uid=$userid, table=$table. unmoved count = $count" + if $count && $count != $rows_skipped{$table}; + } + } + + $was_empty{$table} = 1 unless $tct; + $rows += $tct; + } + + print "# Rows done for '$user': $rows\n" if $optv; + + my $post_state = $stateString->("post"); + if ($post_state ne $pre_state) { + die "Move aborted due to state change during move: Before: [$pre_state], After: [$post_state]\n"; + } + $check_sig->($dbo, "dbo(aftermove)"); + + my $unlocked; + if (! $verify_code || $verify_code->()) { + # unset readonly and move to new cluster in one update + $unlocked = LJ::update_user($userid, { clusterid => $dclust, raw => "caps=caps&~(1<<$readonly_bit)" }); + print "Moved.\n" if $optv; + } else { + # job server went away or we don't have permission to flip the clusterid attribute + # so just unlock them + $unlocked = LJ::update_user($userid, { raw => "caps=caps&~(1<<$readonly_bit)" }); + die "Job server said no.\n"; + } + + # delete from the index of who's read-only. if this fails we don't really care + # (not all sites might have this table anyway) because it's not used by anything + # except the readonly-cleaner which can deal with all cases. + if ($unlocked) { + eval { + $dbh->do("DELETE FROM readonly_user WHERE userid=?", undef, $userid); + }; + } + + # delete from source cluster + if ($opts->{del}) { + print "Deleting from source cluster...\n" if $optv; + foreach my $td (@to_delete) { + my ($table, $pri) = @$td; + while ($dboa->do("DELETE FROM $table WHERE $pri=$userid LIMIT 1000") > 0) { + print " deleted from $table\n" if $optv; + } + } + + # s1stylecache table + if (@styleids) { + my $styleids_in = join(",", map { $dboa->quote($_) } @styleids); + if ($dboa->do("DELETE FROM s1stylecache WHERE styleid IN ($styleids_in)") > 0) { + print " deleted from s1stylecache\n" if $optv; + } + } + } else { + # at minimum, we delete the clustertrack2 row so it doesn't get + # included in a future ljumover.pl query from that cluster. + $dboa->do("DELETE FROM clustertrack2 WHERE userid=$userid"); + } + + $dbh->do("UPDATE clustermove SET sdeleted=?, timedone=UNIX_TIMESTAMP() ". + "WHERE cmid=?", undef, $opts->{del} ? 1 : 0, $cmid); + + return 1; +} + +sub fetchTableInfo +{ + my @tables = (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL); + my $memkey = "moveucluster:" . Digest::MD5::md5_hex(join(",",@tables)); + my $tinfo = LJ::MemCache::get($memkey) || {}; + foreach my $table (@tables) { + next if grep { $_ eq $table } qw(events s1stylecache cmdbuffer captcha_session recentactions pendcomments); + next if $tinfo->{$table}; # no need to load this one + + # find the index we'll use + my $idx; # the index name we'll be using + my $idxcol; # "userid" or "journalid" + + my $sth = $dbo->prepare("SHOW INDEX FROM $table"); + $sth->execute; + my @pris; + + while (my $r = $sth->fetchrow_hashref) { + push @pris, $r->{'Column_name'} if $r->{'Key_name'} eq "PRIMARY"; + next unless $r->{'Seq_in_index'} == 1; + next if $idx; + if ($r->{'Column_name'} eq "journalid" || + $r->{'Column_name'} eq "userid" || + $r->{'Column_name'} eq "commid") { + $idx = $r->{'Key_name'}; + $idxcol = $r->{'Column_name'}; + } + } + + shift @pris if @pris && ($pris[0] eq "journalid" || $pris[0] eq "userid"); + my $verifykey = join(",", @pris); + + die "can't find index for table $table\n" unless $idx; + + $tinfo->{$table}{idx} = $idx; + $tinfo->{$table}{idxcol} = $idxcol; + $tinfo->{$table}{verifykey} = $verifykey; + + my $cols = $tinfo->{$table}{cols} = []; + my $colnum = 0; + $sth = $dboa->prepare("DESCRIBE $table"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) { + push @$cols, $r->{'Field'}; + if ($r->{'Field'} eq $idxcol) { + $tinfo->{$table}{pripos} = $colnum; + } + $colnum++; + } + } + LJ::MemCache::set($memkey, $tinfo, 90); # not for long, but quick enough to speed a series of moves + return $tinfo; +} + +### FUNCTION: abortWithUsage( $message ) +### Abort the program showing usage message. +sub abortWithUsage { + my $msg = join '', @_; + + if ( $msg ) { + pod2usage( -verbose => 1, -exitval => 1, -message => "$msg" ); + } else { + pod2usage( -verbose => 1, -exitval => 1 ); + } +} + diff --git a/livejournal/bin/moveuclusterd.pl b/livejournal/bin/moveuclusterd.pl new file mode 100755 index 0000000..2bd0c18 --- /dev/null +++ b/livejournal/bin/moveuclusterd.pl @@ -0,0 +1,2750 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +moveuclusterd - User-mover task coordinater daemon + +=head1 SYNOPSIS + + $ moveuclusterd OPTIONS + +=head2 OPTIONS + +=over 4 + +=item -d, --debug + +Output debugging information in addition to normal progress messages. May be +specified more than once to increase debug level. + +=item -D, --daemon + +Background the program. + +=item -h, --help + +Output a help message and exit. + +=item -H, --host=HOST + +Listen on the specified I instead of the default '0.0.0.0'. + +=item -m, --maxlocktime=SECONDS + +Set the number of seconds that is targeted as the timespan to keep jobs locked +before assigning them. If the oldest job in a cluster's queue is older than this +value (120 by default), no users will be locked for that queue until the next +check. + +=item -p, --port=PORT + +Listen to the given I instead of the default 2789. + +=item -r, --defaultrate=INTEGER + +Set the default rate limit for any source cluster which has not had its rate set +to I. The default rate is 1. + +=item -s, --lockscale=INTEGER + +Set the lock-scaling factor to I. The lock scaling factor is used to +decide how many users to lock per source cluster; a scaling factor of C<3> (the +default) would cause the jobserver to try to maintain 3 x the number of jobs as +there are allowed connections for a given cluster, modulo the C. + +=item -v, --verbose + +Output the jobserver's log to STDERR. + +=back + +=head1 REQUIRES + +I + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger Eged@danga.comE + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +=cut + +############################################################################## +package moveuclusterd; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + + # Turn STDOUT buffering off + $| = 1; + + # Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.20 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: moveuclusterd.pl,v 1.20 2004/11/12 00:31:07 deveiant Exp $; + + # Define some constants + use constant TRUE => 1; + use constant FALSE => 0; + + use lib "$ENV{LJHOME}/cgi-bin"; + require "ljlib.pl"; + + # Modules + use Carp qw{croak confess}; + use Getopt::Long qw{GetOptions}; + use Pod::Usage qw{pod2usage}; + + Getopt::Long::Configure( 'bundling' ); +} + + +############################################################################### +### C O N F I G U R A T I O N G L O B A L S +############################################################################### + +### Main body +sub MAIN { + my ( + $debugLevel, # Debugging level to set in server + $helpFlag, # User requested help? + $daemonFlag, # Background after starting? + $defaultRate, # Default src cluster rate cmdline setting + $verboseFlag, # Output the log or no? + $server, # JobServer object + %config, # JobServer configuration + $port, # Port to listen on + $host, # Address to listen on + $lockScale, # Lock scaling factor + $maxLockTime, # Max time to keep users locked + ); + + # Print the program header and read in command line options + GetOptions( + 'D|daemon' => \$daemonFlag, + 'H|host=s' => \$host, + 'd|debug+' => \$debugLevel, + 'h|help' => \$helpFlag, + 'm|maxlocktime=i' => \$maxLockTime, + 'p|port=i' => \$port, + 'r|defaultrate=i' => \$defaultRate, + 's|lockscale=i' => \$lockScale, + 'v|verbose' => \$verboseFlag, + ) or abortWithUsage(); + + # If the -h flag was given, just show the usage and quit + helpMode() and exit if $helpFlag; + + # Build the configuration hash + $config{host} = $host if $host; + $config{port} = $port if $port; + $config{daemon} = $daemonFlag; + $config{debugLevel} = $debugLevel || 0; + $config{defaultRate} = $defaultRate if $defaultRate; + $config{lockScale} = $lockScale if $lockScale; + $config{maxLockTime} = $maxLockTime if defined $maxLockTime; + + # Create a new daemon object + $server = new JobServer ( %config ); + + # Add a simple log handler if they've requested verbose output + if ( $verboseFlag ) { + my $tmplogger = sub { + my ( $level, $msg ) = @_; + print STDERR "[$level] $msg\n"; + }; + $server->addHandler( 'log', 'verboselogger', $tmplogger ); + } + + # Start the server + $server->start(); +} + + +### FUNCTION: helpMode() +### Exit normally after printing the usage message +sub helpMode { + pod2usage( -verbose => 1, -exitval => 0 ); +} + + +### FUNCTION: abortWithUsage( $message ) +### Abort the program showing usage message. +sub abortWithUsage { + my $msg = @_ ? join('', @_) : ""; + + if ( $msg ) { + pod2usage( -verbose => 1, -exitval => 1, -message => "$msg" ); + } else { + pod2usage( -verbose => 1, -exitval => 1 ); + } +} + + + +### If run from the command line, run the server. +if ( $0 eq __FILE__ ) { MAIN() } + + +##################################################################### +### T I M E D B U F F E R C L A S S +##################################################################### +package TimedBuffer; + +BEGIN { + use Carp qw{croak confess}; +} + +our $DefaultExpiration = 120; + +### (CONSTRUCTOR) METHOD: new( $seconds ) +### Create a new timed buffer which will remove entries the specified number of +### I after being added. +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + my $seconds = shift || $DefaultExpiration; + + my $self = bless { + buffer => [], + seconds => $seconds, + }, $class; + + return $self; +} + + +### METHOD: add( @items ) +### Add the given I to the buffer, shifting off older ones if they are +### expired. +sub add { + my $self = shift or confess "Cannot be used as a function"; + my @items = @_; + + my $expiration = time - $self->{seconds}; + my $buffer = $self->{buffer}; + + # Expire old entries and add the new ones + @$buffer = grep { $_->[1] > $expiration } @$buffer; + push @$buffer, map {[ $_, time ]} @items; + + return scalar @$buffer; +} + + +### METHOD: get( [@indices] ) +### Return the items in the buffer at the specified I, or all items in +### the buffer if no I are given. +sub get { + my $self = shift or confess "Cannot be used as a function"; + + my $expiration = time - $self->{seconds}; + my $buffer = $self->{buffer}; + + # Expire old entries + @$buffer = grep { $_->[1] > $expiration } @$buffer; + + # Return just the values from the buffer, either in a slice if they + # specified indexes, or the whole thing if not. + if ( @_ ) { + return map { $_->[0] } @{$buffer}[ @_ ]; + } else { + return map { $_->[0] } @$buffer; + } +} + + + +##################################################################### +### D A E M O N C L A S S +##################################################################### +package JobServer; + +BEGIN { + use IO::Socket qw{}; + use Data::Dumper qw{Dumper}; + use Carp qw{croak confess}; + use Time::HiRes qw{gettimeofday tv_interval}; + use POSIX qw{}; + + use fields ( + 'clients', # Connected client objects + 'config', # Configuration hash + 'listener', # The listener socket + 'handlers', # Client event handlers + 'jobs', # Mover jobs + 'totaljobs', # Count of jobs processed + 'assignments', # Jobs that have been assigned + 'users', # Users in the queue + 'ratelimits', # Cached cluster ratelimits + 'raterules', # Rules for building ratelimit table + 'jobcounts', # Counts per cluster of running jobs + 'starttime', # Server startup epoch time + 'recentmoves', # Timed buffer of recently-completed jobs + ); + + use lib "$ENV{LJHOME}/cgi-bin"; + require 'ljlib.pl'; + + use base qw{fields}; +} + + +### Class globals + +# Default configuration +our ( %DefaultConfig, %LogLevels ); + +INIT { + + # Default server configuration; this is merged with any config args the user + # specifies in the call to the constructor. Most of these correspond with + # command-line flags, so see that section of the POD header for more + # information. + %DefaultConfig = ( + port => 2789, # Port to listen on + host => '0.0.0.0', # Host to bind to + listenQueue => 5, # Listen queue depth + daemon => 0, # Daemonize or not? + debugLevel => 0, # Debugging log level + defaultRate => 1, # The default src cluster rate + lockScale => 3, # Scaling factor for locking users + maxLockTime => 120, # Max seconds to keep users locked + ); + + my $level = 0; + %LogLevels = map { + $_ => $level++, + } qw{debug info notice warn crit fatal}; + + + $Data::Dumper::Terse = 1; + $Data::Dumper::Indent = 1; +} + +# +# Datastructures of class members: +# +# clients: Hashref of connected clients, keyed by fdno +# +# jobs: A hash of arrays of JobServer::Job objects: +# { +# => [ $job1, $job2, ... ], +# ... +# } +# +# users: A hash index into the inner arrays of 'jobs', keyed by +# userid. +# +# assignments: A hash of arrays; when a job is assigned to a mover, the +# corresponding JobServer::Job is moved into this hash, +# keyed by the fdno of the mover responsible. +# +# handlers: Hash of hashes; this is used to register callbacks for clients that +# want to monitor the server, receiving log or debugging messages, +# new job notifications, etc. +# +# totaljobs: Count of total jobs added to the daemon. +# +# raterules: Maximum number of jobs which can be run against source clusters, +# keyed by clusterid. If a global rate limit has been set, this +# hash also contains a special key 'global' to contain it. +# +# ratelimits: Cached ratelimits for clusters -- this is rebuilt whenever a +# ratelimit rule is added, and is partially rebuilt when new jobs +# are added. +# +# jobcounts: Count of jobs running against source clusters, keyed by +# source clusterid. + +### (CONSTRUCTOR) METHOD: new( %config ) +### Create a new JobServer object with the given I. +sub new { + my JobServer $self = shift; + my %config = @_; + + $self = fields::new( $self ) unless ref $self; + + # Client and job queues + $self->{clients} = {}; # fd => client obj + $self->{jobs} = {}; # pending jobs: srcluster => [ jobs ] + $self->{users} = {}; # by-userid hash of jobs + $self->{assignments} = {}; # fd => job object + $self->{totaljobs} = 0; # Count of total jobs added + $self->{raterules} = {}; # User-set rate-limit rules + $self->{ratelimits} = {}; # Cached rate limits by srcclusterid + $self->{jobcounts} = {}; # Count of jobs by srcclusterid + + # Create a timed buffer to contain the jobs which have completed in the last + # 6 minutes. + $self->{recentmoves} = new TimedBuffer 360; + + # Merge the user-specified configuration with the defaults, with the user's + # overriding. + $self->{config} = { + %DefaultConfig, + %config, + }; # merge + + # These two get set by start() + $self->{listener} = undef; + $self->{starttime} = undef; + + # CODE refs for handling various events. Keyed by event name, each subhash + # contains registrations for event callbacks. Each subhash is keyed by the + # fdno of the client that requested it, or an arbitrary string if the + # handler belongs to something other than a client. + $self->{handlers} = { + debug => {}, + log => {}, + }; + + return $self; +} + + + +### METHOD: start() +### Start the event loop. +sub start { + my JobServer $self = shift; + + # Start the listener socket + my $listener = new IO::Socket::INET + Proto => 'tcp', + LocalAddr => $self->{config}{host}, + LocalPort => $self->{config}{port}, + Listen => $self->{config}{listenQueue}, + ReuseAddr => 1, + Blocking => 0 + or die "new socket: $!"; + + # Log the server startup, then daemonize if it's called for + $self->logMsg( 'notice', "Server listening on %s:%d\n", + $listener->sockhost, $listener->sockport ); + $self->{listener} = $listener; + $self->daemonize if $self->{config}{daemon}; + + # Remember the startup time + $self->{starttime} = time; + + # I don't understand this design -- the Client class is where the event loop + # is? Weird. Thanks to SPUD, though, for the example code. + JobServer::Client->OtherFds( $listener->fileno => sub {$self->createClient} ); + JobServer::Client->EventLoop(); + + return 1; +} + + + +### METHOD: createClient( undef ) +### Listener socket readable callback. Accepts a new client socket and wraps a +### JobServer::Client around it. +sub createClient { + my JobServer $self = shift; + + my ( + $csock, # Client socket + $client, # JobServer::Client object + $fd, # File descriptor for client + ); + + # Get the client socket and set it nonblocking + $csock = $self->{listener}->accept or return; + $csock->blocking(0); + $fd = fileno( $csock ); + + $self->logMsg( 'info', 'Client %d connect: %s:%d', + $fd, $csock->peerhost, $csock->peerport ); + + # Wrap a client object around it, tell it to watch for input, and send the + # greeting. + $client = JobServer::Client->new( $self, $csock ); + $client->watch_read( 1 ); + $client->write( "Ready.\r\n" ); + + return $self->{clients}{$fd} = $client; +} + + +### METHOD: disconnectClient( $client=JobServer::Client[, $requeue] ) +### Disconnect the specified I from the server. If I is true, +### the job belonging to the client (if any) will be put back into the queue of +### pending jobs. +sub disconnectClient { + my JobServer $self = shift; + my ( $client, $requeue ) = @_; + + my ( + $csock, # Client socket + $fd, # Client's fdno + $job, # Job that client was working on + ); + + # Stop further input from the socket + $csock = $client->sock; + $csock->shutdown( 0 ) if $csock->connected; + $fd = fileno( $csock ); + $self->logMsg( 'info', "Client %d disconnect: %s:%d", + $fd, $csock->peerhost, $csock->peerport ); + + # Remove any event handlers registered for the client + $self->removeHandlerFromAll( $fd ); + $self->unassignJobForClient( $fd ); + + # Remove the client from our list + delete $self->{clients}{ $fd }; +} + + +### METHOD: clients( undef ) +### Get the list of clients (JobServer::Client objects) currently connected to +### the server. +sub clients { + my JobServer $self = shift; + return values %{$self->{clients}}; +} + + +### METHOD: raterules( undef ) +### Get the hash of rate rules the server uses to calculate a cluster's +### maximum number of clients. +sub raterules { + my JobServer $self = shift; + return %{$self->{raterules}}; +} + + +### METHOD: recentmoves( undef ) +### Get the JobServer::Job objects in the server's "recently-moved" timedbuffer. +sub recentmoves { + my JobServer $self = shift; + return $self->{recentmoves}->get; +} + + +### METHOD: defaultRate( undef ) +### Get the default cluster rate as set on the command line. +sub defaultRate { + my JobServer $self = shift; + return $self->{config}->{defaultRate}; +} + + +### METHOD: addJobs( @jobs=JobServer::Job ) +### Add a job to move the user with the given I to the cluster with the +### specified I. +sub addJobs { + my JobServer $self = shift; + my @jobs = @_; + + my ( + @responses, # Inline responses + $clusterid, # Cluster iterator + $job, # Job object iterator + $userid, # User id for user to move + $newJobCount, # Count of jobs added to the queue + ); + + $newJobCount = 0; + + # Iterate over job specifications + JOB: for ( my $i = 0; $i <= $#jobs; $i++ ) { + $job = $jobs[ $i ]; + $self->debugMsg( 5, "Adding job: %s", $job->stringify ); + + ( $userid, $clusterid ) = ( $job->userid, $job->srcclusterid ); + + # Check to be sure this job isn't already queued or in progress. + if ( $self->{users}{$userid} ) { + $self->debugMsg( 2, "Request for duplicate job %s", $job->stringify ); + $responses[$i] = "Duplicate job for userid $userid"; + next JOB; + } + + # Queue the job and point the user index at it. + $self->{jobs}{$clusterid} ||= []; + push @{$self->{jobs}{$clusterid}}, $job; + $self->{users}{ $userid } = $job; + $self->{jobcounts}{$clusterid} ||= 0; + + $responses[$i] = "Added job ". ++$self->{totaljobs}; + $newJobCount++; + } + + # we might've learned some new clusterids + %{$self->{ratelimits}} = (); + + # Scan the task table for users to lock and then send notifications to + # anyone who's waiting on new jobs if there were any added. + $self->prelockSomeUsers; + $self->handleEvent( 'add', $newJobCount ) if $newJobCount; + + return @responses; +} + + +### METHOD: prelockSomeUsers( undef ) +### Mark some of the users in the queues as read-only so the movers don't need +### to do so before moving. Only marks a portion of each queue so as to not +### inconvenience users. +sub prelockSomeUsers { + my JobServer $self = shift; + + my $start = [gettimeofday()]; + + my ( + $jobcount, # Number of jobs queued for a cluster + $rate, # Rate for the cluster in question + $target, # Number of queued jobs we'd like to be locked + $lockcount, # Number of users locked + $scale, # Lock scaling factor + $maxLockTime, # Max number of seconds to keep users locked + $clients, # Number of currently-connected clients + $jobs, # Job queue per cluster + ); + + # Twiddle some database bits out in magic voodoo land + LJ::start_request(); + + # Set the scaling factor -- this is a command-line setting that affects how + # deep the queue is locked per source cluster. + $scale = $self->{config}{lockScale}; + $maxLockTime = $self->{config}{maxLockTime}; + + $self->debugMsg( 3, "Prelocking with scale: $scale, maxlocktime: $maxLockTime" ); + + # Iterate over all the queues we have by cluster + CLUSTER: foreach my $clusterid ( keys %{$self->{jobs}} ) { + $rate = $self->getClusterRateLimit( $clusterid ); + $target = $rate * $scale; + + # Now iterate partway into the queue of jobs for the cluster, locking + # some users if there are some that need locking + $jobs = $self->{jobs}{ $clusterid }; + JOB: for ( my $i = 0; $i <= $target; $i++ ) { + + # If there are fewer jobs than the target number to be locked, or + # the current job is older than the maximum number of seconds to + # keep a user locked, skip to the next cluster + next CLUSTER if $i > $#$jobs; + next CLUSTER if $jobs->[$i]->secondsSinceLock > $maxLockTime; + + # Skip jobs that are already prelocked. If locking fails, assume + # there's some database problem and don't try to prelock any more + # until next time. + next JOB if $jobs->[$i]->isPrelocked; + $jobs->[$i]->prelock or last CLUSTER; + } + } + + $self->debugMsg( 4, "Prelock time: %0.5fs", tv_interval($start) ); + return $lockcount; +} + + +### METHOD: getClusterRateLimit( $clusterid ) +### Return the number of connections which can be reading from the cluster with +### the given I. +sub getClusterRateLimit { + my JobServer $self = shift; + my $clusterid = shift or confess "No clusterid"; + + # Swap the next two lines to make the 'global' rate override those of + # specific clusters. + return $self->{raterules}{ $clusterid } if exists $self->{raterules}{ $clusterid }; + return $self->{raterules}{global} if exists $self->{raterules}{global}; + return $self->{config}{defaultRate}; +} + + +### METHOD: getClusterRateLimits( undef ) +### Return the rate limits for all known clusters as a hash (or hashref if +### called in scalar context) keyed by clusterid. +sub getClusterRateLimits { + my JobServer $self = shift; + + # (Re)build the rates table as necessary + unless ( %{$self->{ratelimits}} ) { + for my $clusterid ( keys %{$self->{jobs}} ) { + $self->{ratelimits}{ $clusterid } = + $self->getClusterRateLimit( $clusterid ); + } + } + + return wantarray ? %{$self->{ratelimits}} : $self->{ratelimits}; +} + + +### METHOD: setClusterRateLimit( $clusterid, $rate ) +### Set the rate limit for the cluster with the given I to I. +sub setClusterRateLimit { + my JobServer $self = shift; + my ( $clusterid, $rate ) = @_; + + die "No clusterid" unless $clusterid; + die "No ratelimit" unless defined $rate && int($rate) == $rate; + + # Set the new rule and trash the precalculated table + $self->{raterules}{ $clusterid } = $rate; + %{$self->{ratelimits}} = (); + + return "Rate limit for cluster $clusterid set to $rate"; +} + + +### METHOD: setGlobalRateLimit( $rate ) +### Set the rate limit for clusters that don't have an explicit ratelimit to +### I. +sub setGlobalRateLimit { + my JobServer $self = shift; + my $rate = shift; + die "No ratelimit" unless defined $rate && int($rate) == $rate; + + # Set the global rule and clear out the cached table to rebuild it next time + # it's used + $self->{raterules}{global} = $rate; + %{$self->{ratelimits}} = (); + + return "Global rate limit set to $rate"; +} + + +### METHOD: resetClusterRateLimit( $clusterid ) +### Remove the explicit rate limit for the cluster with the given +### I. Returns the new limit for the cluster after resetting. +sub resetClusterRateLimit { + my JobServer $self = shift; + my $clusterid = shift or croak "No clusterid given."; + + $self->debugMsg( 1, "Resetting rate limit for cluster $clusterid." ); + delete $self->{raterules}{$clusterid}; + %{$self->{ratelimits}} = (); + + return $self->{raterules}{global} || $self->{config}{defaultRate}; +} + + +### METHOD: resetGlobalRateLimit( undef ) +### Reset the rate limit for clusters that don't have an explicit ratelimit back +### to the default and returns it. +sub resetGlobalRateLimit { + my JobServer $self = shift; + delete $self->{raterules}{global}; + %{$self->{ratelimits}} = (); + + return $self->{config}{defaultRate}; +} + + +### METHOD: getJob( $client=JobServer::Client ) +### Fetch a job for the given I and return it. If there are no pending +### jobs, returns the undefined value. +sub getJob { + my JobServer $self = shift; + my ( $client ) = @_ or confess "No client object"; + + my ( + $fd, # Client's fdno + $job, # Job arrayref + ); + + $fd = $client->fdno or confess "No file descriptor?!?"; + $self->unassignJobForClient( $fd ); + + return $self->assignNextJob( $fd ); +} + + +### METHOD: assignNextJob( $fdno ) +### Find the next pending job from the queue that would read from a non-busy +### source cluster, as determined by the rate limits given to the server. If one +### is found, assign it to the client associated with the given file descriptor +### I. Returns the reply to be sent to the client. +sub assignNextJob { + my JobServer $self = shift; + my $fd = shift or return; + + my ( + $src, # Clusterid of a source + $rates, # Rate limits by clusterid + $jobcounts, # Counts of current jobs, by clusterid + @candidates, # Clusters with open slots + ); + + $rates = $self->getClusterRateLimits; + $jobcounts = $self->{jobcounts}; + + # Find clusterids of clusters with open slots, returning the undefined value + # if there are none. + @candidates = grep { + $jobcounts->{$_} < $rates->{$_} + } keys %{$self->{jobs}}; + return undef unless @candidates; + + # Pick a random cluster from the available list + $src = $candidates[ int rand(@candidates) ]; + $self->debugMsg( 4, "Assigning job for cluster %d (%d of %d)", + $src, $jobcounts->{$src} + 1, $rates->{$src} ); + + # Assign the next job from that cluster and return it + return $self->assignJobFromCluster( $src, $fd ); +} + + +### METHOD: assignJobFromCluster( $clusterid, $fdno ) +### Assign the next job from the cluster with the specified I to the +### client with the given file descriptor I. +sub assignJobFromCluster { + my JobServer $self = shift; + my ( $clusterid, $fdno ) = @_; + + # Grab a job from the cluster's queue and add it to the assignments table. + my $job = $self->{assignments}{$fdno} = shift @{$self->{jobs}{$clusterid}}; + $job->setFetchtime; + + # Increment the job counter for that cluster and delete the queue if it's + # empty. + delete $self->{jobs}{$clusterid} if ! @{$self->{jobs}{$clusterid}}; + $self->{jobcounts}{$clusterid}++; + + # If there are more jobs for this queue, and the next job in the queue isn't + # prelocked, lock some more + $self->prelockSomeUsers + if exists $self->{jobs}{$clusterid} + && ! $self->{jobs}{$clusterid}[0]->isPrelocked; + + return $job; +} + + +### METHOD: unassignJobForClient( $fdno ) +### Unassign the job currently assigned to the client associated with the given +### I. +sub unassignJobForClient { + my JobServer $self = shift; + my $fdno = shift or confess "No client fdno"; + my $requeue = shift || ''; + + my ( + $job, + $src, + ); + + # If there is a currently assigned job, we have work to do + if (( $job = delete $self->{assignments}{$fdno} )) { + $src = $job->srcclusterid; + + # If the worker asked to finish it, assume it was completed and + # timedbuffer it for statistics. + if ( $job->isFinished ) { + $self->{recentmoves}->add( $job ); + } + + # Otherwise, requeue it if that's enabled + else { + + if ( $requeue ) { + $self->logMsg( 'info', "Re-adding job %s to queue", $job->stringify ); + $self->{jobs}{ $job->srcclusterid } ||= []; + unshift @{$self->{jobs}{ $job->srcclusterid }}, $job; + } + + # Free up a slot on the source + $self->debugMsg( 3, "Client %d dropped job %s", $fdno, $job->stringify ); + } + + # Delete the user's job and decrement the job count for the cluster the + # job belonged to + delete $self->{users}{ $job->userid }; + $self->{jobcounts}{ $src }--; + $self->debugMsg( 3, "Cluster %d now has %d clients", + $src, $self->{jobcounts}{ $src } ); + } + + return $job; +} + + +### METHOD: getJobForUser( $userid ) +### Return the job associated with a given userid. +sub getJobForUser { + my JobServer $self = shift; + my $userid = shift or confess "No userid specified"; + + return $self->{users}{ $userid }; +} + + +### METHOD: stopAllJobs( $client=JobServer::Client ) +### Stop all pending and currently-assigned jobs. +sub stopAllJobs { + my JobServer $self = shift; + my $client = shift or confess "No client object"; + + $self->stopNewJobs( $client ); + $self->logMsg( 'notice', "Clearing currently-assigned jobs." ); + %{$self->{assignments}} = (); + %{$self->{jobs}} = (); + %{$self->{jobcounts}} = (); + %{$self->{users}} = (); + + return "Cleared all jobs."; +} + + +### METHOD: stopNewJobs( $client=JobServer::Client ) +### Stop assigning pending jobs. +sub stopNewJobs { + my JobServer $self = shift; + my $client = shift or confess "No client object"; + + $self->logMsg( 'notice', "Clearing pending jobs." ); + %{$self->{jobs}} = (); + foreach my $userid ( keys %{$self->{users}} ) { + delete $self->{users}{ $userid } unless $self->{users}{$userid}->isFetched; + } + + return "Cleared pending jobs."; +} + + +### METHOD: requestJobFinish( $client=JobServer::Client, $userid, $srcclusterid, $dstclusterid ) +### Request authorization to finish a given job. +sub requestJobFinish { + my JobServer $self = shift; + my ( $client, $userid, $srcclusterid, $dstclusterid ) = @_; + + my ( + $fdno, # The client's fdno + $job, # The client's currently assigned job + ); + + # Fetch the fdno of the client and try to get the job object they were last + # assigned. If it doesn't exist, all jobs are stopped or something else has + # happened, so advise the client to abort. + $fdno = $client->fdno; + if ( ! exists $self->{assignments}{$fdno} ) { + $self->logMsg( 'warn', "Client $fdno: finish on unassigned job" ); + return undef; + } + + # If the job the client was last assigned doesn't match the userid they've + # specified, abort. + $job = $self->{assignments}{$fdno}; + if ( $job->userid != $userid ) { + $self->logMsg( 'warn', "Client %d: finish for non-assigned job %s", + $fdno, $job->stringify ); + return undef; + } + + # Otherwise mark the job as finished and advise the client that they can + # proceed. + $job->setFinishTime; + $self->debugMsg( 2, 'Client %d finishing job %s', + $fdno, $job->stringify ); + + return "Go ahead with job " . $job->stringify; +} + + + +### METHOD: getJobList( undef ) +### Return a hashref of job stats. The hashref will contain three arrays: the +### 'queued_jobs' array contains a line describing how many jobs are queued for +### each source cluster, the 'assigned_jobs' array contains a line per client +### that's currently moving a user, and the 'footer' array contains some lines +### of overall statistics about the server. +sub getJobList { + my JobServer $self = shift; + + my ( + %stats, # The returned job stats + $queuedCount, # Number of queued jobs + $assignedCount, # Number of jobs currently assigned + $job, # Job object iterator + $rates, # Rate-limit table + ); + + %stats = ( queued_jobs => [], assigned_jobs => [], footer => [] ); + $queuedCount = $assignedCount = 0; + $rates = $self->getClusterRateLimits; + + # The first sublist: queued jobs + foreach my $clusterid ( sort keys %{$self->{jobs}} ) { + push @{$stats{queued_jobs}}, + sprintf( "%3d: %5d jobs queued @ limit %d", + $clusterid, + scalar @{$self->{jobs}{$clusterid}}, + $rates->{$clusterid} ); + $queuedCount += scalar @{$self->{jobs}{$clusterid}}; + } + + # Second sublist: assigned jobs + foreach my $fdno ( sort keys %{$self->{assignments}} ) { + $job = $self->{assignments}{$fdno}; + push @{$stats{assigned_jobs}}, + sprintf( "%3d: working on moving %7d from %3d to %3d", + $fdno, $job->userid, $job->srcclusterid, + $job->dstclusterid ); + $assignedCount++; + } + + # Append the footer lines + push @{$stats{footer}}, + sprintf( " %d queued jobs, %d assigned jobs for %d clusters", + $queuedCount, $assignedCount, scalar keys %{$self->{jobs}} ); + + if ( $self->{totaljobs} ) { + push @{$stats{footer}}, + sprintf( " %d of %d total jobs assigned since %s (%0.1f/s)", + $self->{totaljobs} - $queuedCount, + $self->{totaljobs}, + scalar localtime($self->{starttime}), + (time - $self->{starttime}) / ($self->{totaljobs}) + ); + } else { + push @{$stats{footer}}, + sprintf( " No jobs assigned since startup (%s)", + scalar localtime($self->{starttime}) ); + } + + return \%stats; +} + + +### METHOD: getSourceCount( undef ) +### Return a hash (or hashref in scalar context) of srcclusterids => # of +### pending (queued) jobs. +sub getJobCounts { + my JobServer $self = shift; + my %rhash = map { $_ => scalar @{$self->{jobs}{$_}} } keys %{$self->{jobs}}; + + return wantarray ? %rhash : \%rhash; +} + + +### METHOD: shutdown( $agent ) +### Shut the server down. +sub shutdown { + my JobServer $self = shift; + my $agent = shift; + + # Stop incoming connections (:TODO: remove it from Danga::Socket?) + $self->{listener}->close; + + # Clear jobs so no more get handed out while clients are closing + $self->{jobs} = {}; + $self->{users} = {}; + $self->logMsg( 'notice', "Server shutdown by %s", $agent->stringify ); + + # Drop all clients + foreach my $client ( values %{$self->{clients}} ) { + $client->write( "Server shutdown.\r\n" ); + $client->close; + } + + exit; +} + + +##################################################################### +### E V E N T S U B S Y S T E M M E T H O D S +##################################################################### + +### METHOD: handleEvent( $type, @args ) +### Handle an event of the given I with the specified I. +sub handleEvent { + my JobServer $self = shift; + my ( $type, @args ) = @_; + + # Invoke each registered handler for the given type + for my $func ( values %{$self->{handlers}{$type}} ) { + $func->( @args ); + } +} + + +### METHOD: handlers( [$type] ) +### Return a hash of all registered handlers of the given I, or all +### handlers keyed by type if no type is specified. +sub handlers { + my JobServer $self = shift; + my $type = shift || ''; + + my $rhash; + + if ( $type ) { + $rhash = $self->{handlers}{$type}; + } else { + $rhash = $self->{handlers}; + } + + return () unless $rhash; + return wantarray ? %$rhash : $rhash; +} + + +### METHOD: addHandlerToAll( $key, \&code ) +### Add the specified callback (I) as an event handler for all implemented +### event types. The associated I can be used to later remove the +### handler/s. Returns the number of event types subscribed to. +sub addHandlerToAll { + my JobServer $self = shift; + my ( $key, $code ) = @_; + + my $count = 0; + foreach my $type ( keys %{$self->{handlers}} ) { + $count++ if $self->addHandler( $type, $key, $code ); + } + + return $count; +} + + +### METHOD: removeHandlerFromAll( $key ) +### Remove all event callbacks for the specified I. Returns the number of +### handlers removed. +sub removeHandlerFromAll { + my JobServer $self = shift; + my $key = shift; + + my $count = 0; + foreach my $type ( keys %{$self->{handlers}} ) { + $count++ if $self->removeHandler( $type, $key ); + } + + return $count; +} + + +### METHOD: addHandler( $type, $key, \&code ) +### Add a callback (I) that handles events of the given I. The +### I argument can be used to later remove the handler. +sub addHandler { + my JobServer $self = shift; + my ( $type, $key, $code ) = @_; + + confess "No such event type '$type'" + unless exists $self->{handlers}{$type}; + confess "$type handler for '$key' is a ", + (ref $code ? "simple scalar '$code'" : ref $code), + ", not a CODE ref." unless ref $code eq 'CODE'; + + $self->{handlers}{$type}{ $key } = $code; +} + + +### METHOD: removeHandler( $type, $key ) +### Remove and return the callback associated with the specified I and +### event I. +sub removeHandler { + my JobServer $self = shift; + my ( $type, $key ) = @_; + + no warnings 'uninitialized'; + return delete $self->{handlers}{$type}{ $key }; +} + + +### METHOD: subscribe( $client=JobServer::Client, $type, $args ) +### Subscribe the given I to the given I of server events with the +### given I. +sub subscribe { + my JobServer $self = shift; + my ( $client, $type, $args ) = @_; + + my $method = sprintf( 'subscribe%sEvents', ucfirst $type ); + my $func = $self->can( $method ) + or die "No such event type '$type' (No $method method)"; + $self->debugMsg( 2, "Subscribing client %d to %s events via %s(%s)", + $client->fdno, $type, $method, $args ); + + return $func->( $self, $client, $args ); +} + + +### METHOD: unsubscribe( $client=JobServer::Client, $type, $args ) +### Unsubscribe the given I to the given I of server events with the +### given I. +sub unsubscribe { + my JobServer $self = shift; + my ( $client, $type ) = @_; + + my $method = sprintf( 'unsubscribe%sEvents', ucfirst $type ); + my $func = $self->can( $method ) + or die "No such event type '$type' (No $method method)"; + + return $func->( $self, $client ); +} + + +### METHOD: subscribeLogEvents( $client, $level ) +### Register a log event handler for the specified I at the given +### I, replacing any currently-extant one. +sub subscribeLogEvents { + my JobServer $self = shift; + my ( $client, $level ) = @_; + my $ll = $LogLevels{ $level }; + + my $callback = sub { + my ( $loglevel, $msg ) = @_; + return () unless $LogLevels{$loglevel} >= $ll; + $client->eventMessage( 'log', "[$loglevel] $msg" ); + }; + + $self->addHandler( 'log', $client->fdno, $callback ); + + return "Subscribed to log events for level '$level'"; +} + + +### METHOD: unsubscribeLogEvents( $client ) +### Unregister the log handler registered for the given I. +sub unsubscribeLogEvents { + my JobServer $self = shift; + my $client = shift or croak "No client"; + + $self->removeHandler( 'log', $client->fdno ); + return "Unsubscribed from log events."; +} + + +### METHOD: subscribeDebugEvents( $client, $level ) +### Register a debug event handler for the specified I at the given +### I, replacing any currently-extant one. +sub subscribeDebugEvents { + my JobServer $self = shift; + my ( $client, $level ) = @_; + + my $callback = sub { + my ( $debuglevel, $msg ) = @_; + return () unless $debuglevel <= $level; + $client->eventMessage( 'debug', "[$debuglevel] $msg" ); + }; + + $self->addHandler( 'debug', $client->fdno, $callback ); + + return "Subscribed to debug events for level '$level'"; +} + + +### METHOD: unsubscribeDebugEvents( $client ) +### Unregister the debug handler registered for the given I. +sub unsubscribeDebugEvents { + my JobServer $self = shift; + my $client = shift or croak "No client"; + + $self->removeHandler( 'debug', $client->fdno ); + return "Unsubscribed from debug events."; +} + + +### METHOD: subscribeAddEvents( $client, $level ) +### Register an 'add' event handler for the specified I. +sub subscribeAddEvents { + my JobServer $self = shift; + my $client = shift or croak "No client"; + + my $callback = sub { + my $count = shift; + $client->eventMessage( 'add', "$count jobs added" ); + }; + + $self->addHandler( 'add', $client->fdno, $callback ); + + return "Subscribed to add events"; +} + + +### METHOD: unsubscribeAddEvents( $client ) +### Unregister the 'add' handler registered for the given I. +sub unsubscribeAddEvents { + my JobServer $self = shift; + my $client = shift or croak "No client"; + + $self->removeHandler( 'add', $client->fdno ); + return "Unsubscribed from add events."; +} + + + + +##################################################################### +### ' P R O T E C T E D ' M E T H O D S +##################################################################### + + +### METHOD: daemonize( undef ) +### Double fork and become a good little daemon +sub daemonize { + my JobServer $self = shift; + + $self->stubbornFork( 5 ) && exit 0; + + # Become session leader to detach from controlling tty + POSIX::setsid() or croak "Couldn't become session leader: $!"; + + # Fork again, ignore hangup to avoid reacquiring a controlling tty + { + local $SIG{HUP} = 'IGNORE'; + $self->stubbornFork( 5 ) && exit 0; + } + + # Change working dir to the filesystem root, clear the umask + chdir "/"; + umask 0; + + # Close standard file descriptors and reopen them to /dev/null + close STDIN && open STDIN, "/dev/null"; + close STDOUT && open STDOUT, ">/dev/null"; + close STDERR && open STDERR, "+>&STDOUT"; +} + + +### METHOD: stubbornFork( $maxTries ) +### Attempt to fork through errors +sub stubbornFork { + my JobServer $self = shift; + my $maxTries = shift || 5; + + my( + $pid, + $tries, + ); + + $tries = 0; + FORK: while ( $tries <= $maxTries ) { + if (( $pid = fork )) { + return $pid; + } elsif ( defined $pid ) { + return 0; + } elsif ( $! =~ m{no more process} ) { + sleep 5; + next FORK; + } else { + die "Cannot fork: $!"; + } + } continue { + $tries++; + } + + die "Failed to fork after $tries tries: $!"; +} + + +### METHOD: debugLevel( [$newLevel] ) +### Get/set the server's debugging level. +sub debugLevel { + my JobServer $self = shift; + + $self->{config}{debugLevel} = (shift || 0) if @_; + return $self->{config}{debugLevel}; +} + + +### METHOD: debugMsg( $level, $format, @args ) +### If the debug level is C<$level> or above, and there are debug handlers +### defined, call each of them at the specified level with the given printf +### C<$format> and C<@args>. +sub debugMsg { + my JobServer $self = shift; + my $level = shift; + my $debugLevel = $self->{config}{debugLevel}; + return unless $level && $debugLevel >= abs $level; + return unless %{$self->{handlers}{debug}}; + + my $msg = shift; + $msg =~ s{[\r\n]+$}{}; + + if ( $debugLevel > 1 ) { + my $caller = caller; + $msg = "<$caller> $msg"; + } + + # Call each subscribed debug event handler with the level and message. + $msg = $self->formatLogMsg( $msg, @_ ); + $self->handleEvent( 'debug', $level, $msg ); +} + + +### METHOD: logMsg( $level, $format, @args ) +### Call any log handlers that have been defined at the specified level with the +### given printf C<$format> and C<@args>. +sub logMsg { + my JobServer $self = shift; + return () unless %{$self->{handlers}{log}}; + my $level = shift or return (); + my $msg = $self->formatLogMsg( @_ ); + + $self->handleEvent( 'log', $level, $msg ); +} + + +### METHOD: formatLogMsg( $format, @args ) +### Create and return a message for the given C-style I and +### I, dumping any complex datatypes and marking the undefined value. +sub formatLogMsg { + my JobServer $self = shift; + my $format = shift; + + # Fetch level and format and strip returns off the latter. + $format =~ s{[\r\n]+$}{}; + + # Turn any references or undefined values in the arglist into dumped strings + my @args = map { + defined $_ ? + (ref $_ ? Data::Dumper->Dumpxs([$_], [ref $_]) : $_) : + '(undef)' + } @_; + return sprintf( $format, @args ); +} + + +##################################################################### +### J O B C L A S S +##################################################################### +package JobServer::Job; +use strict; + +BEGIN { + use Carp qw{croak confess}; + use Time::HiRes qw{time}; + use Scalar::Util qw{blessed}; + + use lib "$ENV{LJHOME}/cgi-bin"; + require 'ljlib.pl'; + require 'ljconfig.pl'; + + use fields ( + 'server', # The server this job belongs to + 'userid', # The userid of the user to move + 'srcclusterid', # The cluster id of the source cluster + 'dstclusterid', # Cluster id of the destination cluster + 'createtime', # Epoch time of job creation + 'prelocktime', # Epoch time of prelock, 0 if not prelocked + 'fetchtime', # Time the job was given to a mover, 0 if unassigned + 'finishtime', # Epoch time of server finish authorization + 'options', # Job options passed between populator and mover + ); +} + + +### Class globals +our ( $ReadOnlyCapBit ); + +INIT { + # Find the readonly cap class, complain if not found + $ReadOnlyCapBit = undef; + + # Find the moveinprogress bit from the caps hash + foreach my $bit ( keys %LJ::CAP ) { + next unless exists $LJ::CAP{$bit}{_name}; + if ( $LJ::CAP{$bit}{_name} eq '_moveinprogress' && + $LJ::CAP{$bit}{readonly} == 1 ) + { + $ReadOnlyCapBit = $bit; + last; + } + } + + die "Cannot mark user readonly without a ReadOnlyCapBit. Check %LJ::CAP" + unless $ReadOnlyCapBit; + +} + + +### (CONSTRUCTOR) METHOD: new( [$userid, $srcclusterid, $dstclusterid ) +### Create and return a new JobServer::Job object. +sub new { + my JobServer::Job $self = shift; + my $server = shift or confess "no server object"; + croak "Illegal first argument: expected a JobServer::Client, got a ", + ref $server ? ref $server : "simple scalar ('$server')" + unless blessed $server && $server->isa( 'JobServer::Client' ); + + $self = fields::new( $self ) unless ref $self; + + # Split instance vars from a string with a colon in the second or later + # position + if ( index($_[0], ':') > 0 ) { + my ( $idtuple, $options ) = split /\s+/, $_[0], 2; + + # Split '::' into members + @{$self}{qw{userid srcclusterid dstclusterid}} = split /:/, $idtuple, 3; + + # Split '= =' into a hashref + if ( $options ) { + $self->{options} = { + map { split /=/, $_, 2 } split(/\s+/, $options) + }; + } else { + $self->{options} = {}; + } + } + + # Allow list arguments as well + else { + # First 3 args are id members + @{$self}{qw{userid srcclusterid dstclusterid}} = + splice( @_, 0, 3 ); + + # Any remaining are assumed to be pairs in an options hash + $self->{options} = { @_ }; + } + + # Check for the stuff we need + croak "Invalid job specifications: No userid" + unless defined $self->{userid}; + croak "Invalid job specifications: No source clusterid" + unless defined $self->{srcclusterid}; + croak "Invalid job specifications: No destination clusterid" + unless defined $self->{dstclusterid}; + + $self->{server} = $server; + $self->{createtime} = time; + $self->{prelocktime} = 0.0; + $self->{fetchtime} = 0.0; + $self->{finishtime} = 0.0; + + return $self; +} + + +### METHOD: userid( [$newuserid] ) +### Get/set the job's userid. +sub userid { + my JobServer::Job $self = shift; + $self->{userid} = shift if @_; + return $self->{userid}; +} + + +### METHOD: srcclusterid( [$newsrcclusterid] ) +### Get/set the job's srcclusterid. +sub srcclusterid { + my JobServer::Job $self = shift; + $self->{srcclusterid} = shift if @_; + return $self->{srcclusterid}; +} + + +### METHOD: dstclusterid( [$newdstclusterid] ) +### Get/set the job's dstclusterid. +sub dstclusterid { + my JobServer::Job $self = shift; + $self->{dstclusterid} = shift if @_; + return $self->{dstclusterid}; +} + + +### METHOD: stringify( undef ) +### Return a scalar containing the stringified representation of the job. +sub stringify { + my JobServer::Job $self = shift; + return sprintf( '%d:%d:%d %0.1f %s', + @{$self}{'userid', 'srcclusterid', 'dstclusterid'}, + $self->secondsSinceLock, $self->optString ); +} + + +### METHOD: prettyString( undef ) +### Return a less-parseable, but more-readable string representation of the job +### than C provides. +sub prettyString { + my JobServer::Job $self = shift; + + return sprintf( "User %d %s from %d to %d (%s):\n\t%s", + $self->{userid}, + $self->verb, + $self->{srcclusterid}, + $self->{dstclusterid}, + $self->optString, + $self->timeString, + ); +} + + +### METHOD: verb( undef ) +### Return the correct conjugation of the verb "to move" that would describe the +### job given its current state. +sub verb { + my JobServer::Job $self = shift; + + return "moved" if $self->{finishtime}; + return "moving" if $self->{fetchtime}; + return "to move"; +} + + +### METHOD: optString( undef ) +### Return the job's options as a string. +sub optString { + my JobServer::Job $self = shift; + my $opts = $self->{options}; + return join( " ", map { "$_=$opts->{$_}" } keys %$opts ); +} + + +### METHOD: timeString( undef ) +### Return the job's various timestamps (if set). +sub timeString { + my JobServer::Job $self = shift; + my @parts = (); + + push @parts, sprintf( '%0.2fs old', $self->age ); + push @parts, sprintf( 'locked %0.2fs', $self->secondsSinceLock ) + if $self->{prelocktime}; + push @parts, + sprintf( 'fetched %0.2fs ago (%0.1fs queued)', + $self->secondsSinceFetch, + $self->{fetchtime} - $self->{createtime} ) + if $self->{fetchtime}; + push @parts, + sprintf( 'finished in %0.2fs', $self->aliveTime ) + if $self->{finishtime}; + + return join ", ", @parts; +} + + +### METHOD: prelock( undef ) +### Mark the user in this job read-only and set the prelocktime. +sub prelock { + my JobServer::Job $self = shift; + + my $dbh = LJ::get_db_writer() + or return 0; + + # both before and after updating a user's read-only flag we add the + # user to the 'readonly_user' table, which is just an index onto + # users who /might/ be in read-only. another cronjob can periodically + # clean those and make sure nobody is stranded in readonly, without + # resorting to a full tablescan of the user table. + $dbh->do("INSERT IGNORE INTO readonly_user SET userid=?", undef, $self->{userid}); + my $rval = LJ::update_user( $self->{userid}, + {raw => "caps = caps | (1<<$ReadOnlyCapBit)"} ); + + if ( $rval ) { + $dbh->do("INSERT IGNORE INTO readonly_user SET userid=?", undef, $self->{userid}); + $self->setPrelocktime; + $self->{options}{prelocked} = 1; + $self->{server}->debugMsg( 4, q{Prelocked user %d}, $self->{userid} ); + } else { + $self->{server}->logMsg( 'warn', q{Couldn't prelock user %d: %s}, + $self->{userid}, $DBI::errstr ); + } + + return $self->{prelocktime}; +} + + +### METHOD: prelocktime( [$newprelocktime] ) +### Get the floating-point epoch time when the user record corresponding to the +### job's C was set read-only. +sub prelocktime { + my JobServer::Job $self = shift; + return $self->{prelocktime}; +} + + +### METHOD: setPrelocktime( undef ) +### Set the prelocktime to the current floating-point epoch time. +sub setPrelocktime { + my JobServer::Job $self = shift; + return $self->{prelocktime} = time; +} + + +### METHOD: secondsSinceLock( undef ) +### Return the number of seconds since the job's user was prelocked, or 0 if the +### user isn't prelocked. +sub secondsSinceLock { + my JobServer::Job $self = shift; + return 0.0 unless $self->{prelocktime}; + return time - $self->{prelocktime}; +} + + +### METHOD: isPrelocked( undef ) +### Returns a true value if the user corresponding to the job has already been +### marked read-only. +sub isPrelocked { + my JobServer::Job $self = shift; + return $self->{prelocktime} != 0; +} + + +### METHOD: finishTime( [$newtime] ) +### Returns the floating-point epoch time when the job was 'finished'. +sub finishTime { + my JobServer::Job $self = shift; + return $self->{finishtime}; +} + + +### METHOD: setFinishTime( undef ) +### Set the finishtime to the current floating-point epoch time. +sub setFinishTime { + my JobServer::Job $self = shift; + return $self->{finishtime} = time; +} + + +### METHOD: secondsSinceFinish( undef ) +### Returns the number of seconds that have elapsed since the job was +### 'finished'. +sub secondsSinceFinish { + my JobServer::Job $self = shift; + return 0 unless $self->{finishtime}; + return time - $self->{finishtime}; +} + + +### METHOD: isFinished( undef ) +### Returns a true value if the mover has requested authorization from the +### jobserver to finish the job. +sub isFinished { + my JobServer::Job $self = shift; + return $self->{finishtime} != 0; +} + + +### METHOD: fetchtime( undef ) +### Get the floatin-point epoch time when the job was fetched by a mover. +sub fetchtime { + my JobServer::Job $self = shift; + return $self->{fetchtime}; +} + + +### METHOD: setFetchtime( undef ) +### Set the fetchtime to the current floating-point epoch time. +sub setFetchtime { + my JobServer::Job $self = shift; + return $self->{fetchtime} = time; +} + + +### METHOD: secondsSinceFetch( undef ) +### Return the number of seconds since the job was fetched by a mover. +sub secondsSinceFetch { + my JobServer::Job $self = shift; + return 0 unless $self->{fetchtime}; + return time - $self->{fetchtime}; +} + + +### METHOD: isFetched( undef ) +### Returns a true value if the job has been assigned to a mover. +sub isFetched { + my JobServer::Job $self = shift; + return $self->{fetchtime} != 0; +} + + +### METHOD: createTime( undef ) +### Return the floating-point epoch time when the job was created. +sub createTime { + my JobServer::Job $self = shift; + return $self->{createtime}; +} + + +### METHOD: age( undef ) +### Return the number of floating-point seconds since the job was created. +sub age { + my JobServer::Job $self = shift; + return time - $self->{createtime}; +} + + +### METHOD: aliveTime( undef ) +### Return the number of floating-point seconds the job was alive, which is the +### time between when it was created and when it was finished. +sub aliveTime { + my JobServer::Job $self = shift; + return 0 unless $self->{finishtime}; + return $self->{finishtime} - $self->{createtime}; +} + + +### METHOD: activeTime( undef ) +### Return the number of floating-point seconds the job was active, which is the +### time between when it was fetched and when it was finished. +sub activeTime { + my JobServer::Job $self = shift; + return 0 unless $self->{finishtime} && $self->{fetchtime}; + return $self->{finishtime} - $self->{fetchtime}; +} + + +### METHOD: debugMsg( $level, $format, @args ) +### Send a debugging message to the server this job belongs to. +sub debugMsg { + my JobServer::Job $self = shift; + $self->{server}->debugMsg( @_ ); +} + + +### METHOD: logMsg( $type, $format, @args ) +### Send a log message to the server this job belongs to. +sub logMsg { + my JobServer::Job $self = shift; + $self->{server}->logMsg( @_ ); +} + + + + + +##################################################################### +### C L I E N T B A S E C L A S S +##################################################################### +package JobServer::Client; + +# Props to Junior for lots of this code, stolen largely from the SPUD server. + +BEGIN { + use Carp qw{croak confess}; + use base qw{Danga::Socket}; + use fields qw{read_buf server state}; +} + + +our ( $Tuple, $JobOption, $JobSpec, %CommandTable, $CommandPattern ); + +INIT { + + # Pattern for matching job id tuples of the form: + # :: + $Tuple = qr{\d+:\d+:\d+}; + + # Pattern for matching one job-spec option which is a moveucluster option + # key-value pair in the form: + # = + $JobOption = qr{\s+\w+=\w+}; + + # Pattern for matching a whole job-spec + $JobSpec = qr{$Tuple$JobOption*}; + + # Commands the server understands. Each entry should be paired with a method + # called cmd_. The 'args' element contains a regexp for + # matching the command's arguments after whitespace-stripping on both sides; + # any capture-groups will be passed to the method as arguments. Commands + # which don't match the argument pattern will produce an error + # message. E.g., if the pattern for 'foo_bar' is /^(\w+)\s+(\d+)$/, then + # entering the command "foo_bar frobnitz 4" would call: + # ->cmd_foo_bar( "frobnitz", "4" ) + # + # The 'help' element of each command is used to provide the information + # necessary for the 'help' command. + # + # If an entry contains a 'form' element, it will be used to describe the + # arguments which are expected/required by the command, and is used in the + # 'form' part of the individual help for that command. If it is omitted, the + # command is assumed by the help system to be standalone and take no arguments. + %CommandTable = ( + + # :TODO: Implement a 'desc' or 'longhelp' or something to augment the + # per-command help. + + get_job => { + help => "get a job (from mover)", + args => qr{^$}, + }, + + add_jobs => { + help => "add one or more new jobs", + form => ":: [, ...]", + args => qr{^((?:$JobSpec\s*,\s*)*$JobSpec)$}, + }, + + source_counts => { + help => "dump pending jobs per source cluster", + args => qr{^$}, + }, + + stop_moves => { + help => "stop all moves", + form => "[all]", + args => qr{^(all)?$}, + }, + + is_moving => { + help => "check to see if a user is being moved", + form => "", + args => qr{^(\d+)$}, + }, + + list_jobs => { + help => "list internal state", + args => qr{^$}, + }, + + move_stats => { + help => "List recent move statistics", + args => qr{^$}, + }, + + recent_moves => { + help => "Show a log of recent moves", + args => qr{^$}, + }, + + set_rate => { + help => "Set the rate for a given source cluster or for all clusters", + form => " or :", + args => qr{^(\d+)(?:[:\s]+(\d+))?\s*$}, + }, + + show_rates => { + help => "Show the rate settings for all clusters", + args => qr{^$}, + }, + + reset_rate => { + help => "Clear rate settings for all or the given source cluster/s.", + form => "[]", + args => qr{^(\d+)?$}, + }, + + finish => { + help => "request authorization to complete a move job", + form => "::", + args => qr{^($Tuple)$}, + }, + + quit => { + help => "disconnect from the server", + args => qr{^$}, + }, + + shutdown => { + help => "shut the server down", + args => qr{^$}, + }, + + lock => { + help => "Pre-lock a given user's job. The job must have already been added.", + form => '', + args => qr{^(\d+)$}, + }, + + clients => { + help => "Show a list of connected clients", + args => qr{^$}, + }, + + subscribe => { + help => "Subscribe to server events", + form => ' ', + args => qr{^(\w+)(?:\s+(.*))?$}i, + }, + + unsubscribe => { + help => "Unsubscribe from server events", + form => '', + args => qr{^(\w+)$}, + }, + + handlers => { + help => "List the event handlers registered with the server.", + form => '[]', + args => qr{^(\w+)?$}, + }, + + debuglevel => { + help => "Get/set the debugging level of the server.", + form => '[]', + args => qr{^([0-5])?$}, + }, + + help => { + help => "show list of commands or help for a particular command, if given.", + form => "[]", + args => qr{^(\w+)?$}, + }, + + ### Internal/debugging commands + timedbuffer => { args => qr{^$} }, + + ); + + # Pattern to match command words + $CommandPattern = join '|', keys %CommandTable; + $CommandPattern = qr{^($CommandPattern)$}; +} + + +### (CONSTRUCTOR) METHOD: new( $server=JobServer, $socket=IO::Socket ) +### Create a new JobServer::Client object for the given I and I. +sub new { + my JobServer::Client $self = shift; + my $server = shift or confess "no server argument"; + my $sock = shift or confess "no socket argument"; + + $self = fields::new( $self ) unless ref $self; + $self->SUPER::new( $sock ); + + $self->{server} = $server; + $self->{state} = 'new'; + + return $self; +} + + +### METHOD: state( [$newstate] ) +### Get/set the client's state message. +sub state { + my JobServer::Client $self = shift; + + $self->{state} = shift if @_; + return $self->{state}; +} + + +### METHOD: stringify( undef ) +### Return a string representation of the client object. +sub stringify { + my JobServer::Client $self = shift; + + return sprintf( '%s:%d', + $self->{sock}->peerhost, + $self->{sock}->peerport ); +} + + +### METHOD: event_read( undef ) +### Readable event callback -- read input from the client and append it to the +### read buffer. Then peel lines off the read buffer and send them to the line +### processor. +sub event_read { + my JobServer::Client $self = shift; + + my $bref = $self->read( 1024 ); + + if ( !defined $bref ) { + $self->close; + return undef; + } + + $self->{read_buf} .= $$bref; + + while ($self->{read_buf} =~ s/^(.+?)\r?\n//) { + $self->processLine( $1 ); + } + +} + + +### METHOD: close( undef ) +### Close the client connection after unregistering from the server -- +### overridden from Danga::Socket. +sub close { + my JobServer::Client $self = shift; + + $self->{server}->disconnectClient( $self ) if $self->{server}; + $self->SUPER::close; +} + + +### METHOD: sock( undef ) +### Return the IO::Socket object that corresponds to this client. +sub sock { + my JobServer::Client $self = shift; + return $self->{sock}; +} + + +### METHOD: sock( undef ) +### Return the file descriptor that is associated with the IO::Socket object +### that corresponds to this client. +sub fdno { + my JobServer::Client $self = shift; + return fileno( $self->{sock} ); +} + + +### METHOD: event_err( undef ) +### Handle Danga::Socket error events. +sub event_err { + my JobServer::Client $self = shift; + $self->close; +} + + +### METHOD: event_hup( undef ) +### Handle Danga::Socket hangup events. +sub event_hup { + my JobServer::Client $self = shift; + $self->close; +} + + +### METHOD: debugMsg( $level, $format, @args ) +### Send a debugging message to the server. +sub debugMsg { + my JobServer::Client $self = shift; + $self->{server}->debugMsg( @_ ); +} + + +### METHOD: logMsg( $type, $format, @args ) +### Send a log message to the server. +sub logMsg { + my JobServer::Client $self = shift; + $self->{server}->logMsg( @_ ); +} + + +### METHOD: processLine( $line ) +### Command dispatcher -- parse I as a command and dispatch it to the +### correct command handler method. The class-global %CommandTable contains the +### dispatch table for this method. +sub processLine { + my JobServer::Client $self = shift; + my $line = shift or return undef; + + my ( + $cmd, # Command word + $args, # Argument string from user + $cmdinfo, # Command hashref + @args, # Parsed arguments + $method, # Command method to call + ); + + # Split the line into command and argument string + ( $cmd, $args ) = split /\s+/, $line, 2; + $args = '' if !defined $args; + + $self->debugMsg( 5, "Matching '%s' against command table pattern %s", + $cmd, $CommandPattern ); + + # If it's a command in the command table, dispatch to the appropriate + # command handler after parsing any arguments. + if ( $cmd =~ $CommandPattern ) { + $method = "cmd_$1"; + $cmdinfo = $CommandTable{ $1 }; + + # Parse command arguments + if ( @args = ($args =~ $cmdinfo->{args}) ) { + + # If the pattern didn't contain captures, throw away the args + @args = () unless ( @+ > 1 ); + + eval { $self->$method(@args) }; + if ( $@ ) { $self->errorResponse($@) } + } + + # Valid command, but bad args + else { + $self->errorResponse( "Usage: $cmd " . $cmdinfo->{form} ); + } + } + + # Invalid command + else { + $self->errorResponse( "Invalid command '$cmd'" ); + } + + return 1; +} + + +### METHOD: okayResponse( @msg ) +### Set an 'OK' response string made up of the I parts concatenated +### together. +sub okayResponse { + my JobServer::Client $self = shift; + my $msg = join( '', @_ ); + + 1 while chomp( $msg ); + + $self->debugMsg( 3, "[Client %s:%d] OK: %s", + $self->{sock}->peerhost, + $self->{sock}->peerport, + $msg, + ); + + $self->write( "OK $msg\r\n" ); +} + + +### METHOD: errorResponse( @msg ) +### Send an 'ERR' response string made up of the I parts concatenated +### together. +sub errorResponse { + my JobServer::Client $self = shift; + my $msg = join( '', @_ ); + + # Trim newlines off the end of the message + 1 while chomp( $msg ); + + $self->logMsg( "error", "[Client %s:%d] ERR: %s", + $self->{sock}->peerhost, + $self->{sock}->peerport, + $msg, + ); + + $msg =~ s{at \S+ line \d+\..*}{}; + $self->write( "ERR $msg\r\n" ); +} + + +### METHOD: multilineResponse( $msg, @lines ) +### Send an 'OK' response containing the given I followed by one or more +### I of a multi-line response followed by an 'END'. +sub multilineResponse { + my JobServer::Client $self = shift; + my ( $msg, @lines ) = @_; + + chomp( @lines ); + $msg =~ s{:\s*$}{}; + + $self->okayResponse( "$msg:" ); + $self->write( join("\r\n", @lines, "END") . "\r\n" ); +} + + +### METHOD: eventMessage( $type, $msg ) +### Send an event notification I for the given I to the client. +sub eventMessage { + my JobServer::Client $self = shift; + my ( $type, $msg ) = @_; + + 1 while chomp( $type, $msg ); + $self->write( "EVENT {$type} $msg\r\n" ); +} + + +### FUNCTION: stringifyHandlers( \%handlers ) +### Stringify a hashref full of handler coderefs. +sub stringifyHandlers { + my $handlers = shift or confess "No handlers argument"; + + my @rows = (); + + foreach my $key ( keys %$handlers ) { + if ( ref $handlers->{$key} eq 'HASH' ) { + push( @rows, + " $key => {", + map { " $_" } stringifyHandlers($handlers->{$key}), + "}" ); + } + + else { + push @rows, sprintf('%s -> %s', $key, $handlers->{$key}); + } + } + + return @rows; +} + + + +##################################################################### +### C O M M A N D M E T H O D S +##################################################################### + +### METHOD: cmd_get_job( undef ) +### Command handler for the C command. +sub cmd_get_job { + my JobServer::Client $self = shift; + + $self->{state} = 'getting job'; + my $job = $self->{server}->getJob( $self ); + + if ( $job ) { + my $jobString = $job->stringify; + $self->{state} = sprintf( 'got job %s', $jobString ); + return $self->okayResponse( "JOB ". $jobString ); + } else { + $self->{state} = 'idle (no jobs)'; + return $self->okayResponse( "IDLE" ); + } +} + + +### METHOD: cmd_add_jobs( $argstring ) +### Command handler for the C command. +sub cmd_add_jobs { + my JobServer::Client $self = shift; + my $argstring = shift or return; + + # Turn the argument into an array of arrays + my @tuples = map { + JobServer::Job->new( $self, $_ ) + } split /\s*,\s*/, $argstring; + + $self->{state} = sprintf 'adding %d jobs', scalar @tuples; + my @responses = $self->{server}->addJobs( @tuples ); + $self->{state} = 'idle'; + + return $self->multilineResponse( "Done", @responses ); +} + + +### METHOD: cmd_source_counts( undef ) +### Command handler for the C command. +sub cmd_source_counts { + my JobServer::Client $self = shift; + $self->{state} = 'source counts'; + + my %counts = $self->{server}->getJobCounts; + my @lines = map { sprintf '%4d: %d', $_, $counts{$_} } sort keys %counts; + + return $self->multilineResponse( 'Source counts:', @lines ); +} + + +### METHOD: cmd_stop_moves( undef ) +### Command handler for the C command. +sub cmd_stop_moves { + my JobServer::Client $self = shift; + my $allFlag = shift || ''; + + $self->{state} = 'stop moves'; + my $msg; + + if ( $allFlag ) { + $msg = $self->{server}->stopAllJobs( $self ); + } else { + $msg = $self->{server}->stopNewJobs( $self ); + } + + $self->okayResponse( $msg ); +} + + +### METHOD: cmd_is_moving( undef ) +### Command handler for the C command. +sub cmd_is_moving { + my JobServer::Client $self = shift; + my $userid = shift or croak "No userid"; + + $self->{state} = 'is moving'; + $self->debugMsg( 2, "Checking to see if user %d is moving.", $userid ); + + my $job = $self->{server}->getJobForUser( $userid ); + my $msg; + + if ( $job ) { + $self->debugMsg( 3, "is_moving: Got a job for userid $userid" ); + $msg = "1"; + } else { + $self->debugMsg( 3, "is_moving: No job for userid $userid" ); + $msg = "0"; + } + + return $self->okayResponse( $msg ); +} + +### METHOD: cmd_list_jobs( undef ) +### Command handler for the C command. +sub cmd_list_jobs { + my JobServer::Client $self = shift; + $self->{state} = 'list jobs'; + + my $stats = $self->{server}->getJobList; + + return $self->multilineResponse( + "Joblist:", + "Queued Jobs", + @{$stats->{queued_jobs}}, + "", + "Assigned Jobs", + @{$stats->{assigned_jobs}}, + "", + @{$stats->{footer}}, + ); +} + + +### METHOD: cmd_move_stats( undef ) +### Command handler for the C command. +sub cmd_move_stats { + my JobServer::Client $self = shift; + + my ( + @jobs, # Recently-finished job objects + %times, # Per-cluster/global time sums + %counts, # Per-cluster job counts + $totaltime, + $totalcount, + @averages, # Average 'alive' times + @stats, # Statistic lines + ); + + $self->{state} = 'move_stats'; + @jobs = $self->{server}->recentmoves + or return $self->multilineResponse( "Move stats:", "No finished jobs" ); + + $totaltime = 0; + $totalcount = 0; + + # Build average 'alive' times + foreach my $job ( @jobs ) { + $times{ $job->srcclusterid } += $job->aliveTime; + $totaltime += $job->aliveTime; + $counts{ $job->srcclusterid }++; + $totalcount++; + } + + # Generate averages + @averages = map { + sprintf( ' c%d: %d @ %0.2fs, %0.2fs avg.', + $_, $counts{$_}, $times{$_}, + $times{$_} / $counts{$_} ) + } sort keys %times; + push @averages, + sprintf( ' total: %d @ %0.2fs, %0.2fs avg.', + $totalcount, $totaltime, + $totaltime / $totalcount ); + + # Return the statistics + return $self->multilineResponse( + "Move stats:", + "Average 'alive' times (create->finish)", + @averages, + ); +} + + +### METHOD: cmd_recent_moves( undef ) +### Command handler for the C command. +sub cmd_recent_moves { + my JobServer::Client $self = shift; + + $self->{state} = 'recent_moves'; + + my @jobs = $self->{server}->recentmoves; + + return $self->multilineResponse( "Recent moves", + map { $_->prettyString } @jobs ); +} + + +### METHOD: cmd_set_rate( undef ) +### Command handler for the C command. +sub cmd_set_rate { + my JobServer::Client $self = shift; + my ( $clusterid, $rate ) = @_; + + my $msg; + + # Global rate + if ( ! defined $rate ) { + $rate = $clusterid; + $self->{state} = "set global rate"; + $msg = $self->{server}->setGlobalRateLimit( $rate ); + } + + else { + $self->{state} = "set rate for cluster $clusterid"; + $msg = $self->{server}->setClusterRateLimit( $clusterid, $rate ); + } + + return $self->okayResponse( $msg ); +} + + +### METHOD: cmd_show_rates( undef ) +### Command handler for the C command. +sub cmd_show_rates { + my JobServer::Client $self = shift; + + $self->{state} = 'show_rates'; + my %rules = $self->{server}->raterules; + my @lines = map { sprintf '%6s: %2d', $_, $rules{$_} } sort keys %rules; + + # If there's no global rate set, show the configured default + unless ( exists $rules{global} ) { + push @lines, "default: " . $self->{server}->defaultRate; + } + + $self->multilineResponse( 'Cluster rate limit rules', @lines ); +} + + +### METHOD: cmd_reset_rate( undef ) +### Command handler for the C command. +sub cmd_reset_rate { + my JobServer::Client $self = shift; + my $srcclusterid = shift || ''; + + $self->{state} = 'reset_rate'; + my ( $rval, $msg ); + + if ( $srcclusterid ) { + $rval = $self->{server}->resetClusterRateLimit( $srcclusterid ); + $msg = "Reset rate limit for cluster $srcclusterid to $rval"; + } else { + $rval = $self->{server}->resetGlobalRateLimit; + $msg = "Reset global rate limit to $rval"; + } + + return $self->okayResponse( $msg ); +} + + +### METHOD: cmd_finish( undef ) +### Command handler for the C command. +sub cmd_finish { + my JobServer::Client $self = shift; + my $spec = shift or confess "No job specification"; + $self->{state} = 'finish'; + + my ( $userid, $srcclusterid, $dstclusterid ) = split /:/, $spec, 3; + + my $msg = $self->{server}->requestJobFinish( $self, $userid, $srcclusterid, + $dstclusterid ); + + if ( $msg ) { + return $self->okayResponse( $msg ); + } else { + return $self->errorResponse( "Abort" ); + } +} + + +### METHOD: cmd_help( undef ) +### Command handler for the C command. +sub cmd_help { + my JobServer::Client $self = shift; + my $command = shift || ''; + + $self->{state} = 'help'; + my @response = (); + + # Either show help for a particular command + if ( $command && exists $CommandTable{$command} ) { + my $cmdinfo = $CommandTable{ $command }; + $cmdinfo->{form} ||= ''; # Non-existant form means no args + + @response = ( + "--- $command -----------------------------------", + "", + " $command $cmdinfo->{form}", + "", + $cmdinfo->{help} || "(undocumented)", + "", + "Pattern:", + " $cmdinfo->{args}", + "", + ); + } + + else { + my @cmds = map { " $_" } + grep { exists $CommandTable{$_}{help} } + sort keys %CommandTable; + + @response = ( + "Available commands:", + "", + @cmds, + "", + ); + } + + return $self->multilineResponse( "Help:", @response ); +} + + +### METHOD: cmd_lock( $userid ) +### Command handler for the (debugging) C command. +sub cmd_lock { + my JobServer::Client $self = shift; + my $userid = shift; + + # Fetch the job for the requested user if possible + my $job = $self->{server}->getJobForUser( $userid ) + or return $self->errorResponse( "No such user '$userid'." ); + + if ( $job->isPrelocked ) { + my $msg = sprintf( "User %d already locked for %d seconds.", + $userid, $job->secondsSinceLock ); + return $self->errorResponse( $msg ); + } + + # Try to lock the user + my $time = $job->prelock; + if ( $time ) { + my $msg = "User $userid locked at: $time (". scalar localtime($time) .")"; + return $self->okayResponse( $msg ); + } else { + return $self->errorResponse( "Prelocking of user $userid failed." ); + } +} + + +### METHOD: cmd_clients( undef ) +### Command handler for the C command. +sub cmd_clients { + my JobServer::Client $self = shift; + + $self->{state} = 'list clients'; + + my @lines = map { + sprintf '%3d: %s', $_->fdno, $_->state; + } $self->{server}->clients; + + return $self->multilineResponse( 'Clients: ', @lines ); +} + + + +### METHOD: cmd_subscribe( $type, $args ) +### Command handler for the C command. +sub cmd_subscribe { + my JobServer::Client $self = shift; + my ( $type, $args ) = @_; + + $self->{state} = "subscribe to $type events"; + + my $msg = $self->{server}->subscribe( $self, $type, $args ); + return $self->okayResponse( $msg ); +} + + + +### METHOD: cmd_unsubscribe( $type ) +### Command handler for the C command. +sub cmd_unsubscribe { + my JobServer::Client $self = shift; + my ( $type ) = @_; + + $self->{state} = 'unsubscribe from %s events'; + + my $msg = $self->{server}->unsubscribe( $self, $type ); + return $self->okayResponse( $msg ); +} + + +### METHOD: cmd_handlers( [$type] ) +### Command handler for the C command. +sub cmd_handlers { + my JobServer::Client $self = shift; + my $type = shift || ''; + + $self->{state} = 'handlers'; + + my $handlers = $self->{server}->handlers( $type ); + my @res; + + if ( $handlers ) { + @res = stringifyHandlers( $handlers ); + } else { + @res = ("No handlers registered."); + } + + $self->multilineResponse( "Handlers:", @res ); +} + + +### METHOD: cmd_quit( undef ) +### Command handler for the C command. +sub cmd_quit { + my JobServer::Client $self = shift; + + $self->{state} = 'quitting'; + + $self->okayResponse( "Goodbye" ); + $self->close; + + return 1; +} + + +### METHOD: cmd_debuglevel( [$newLevel] ) +### Command handler for the C command. +sub cmd_debuglevel { + my JobServer::Client $self = shift; + my $level = shift; + + $self->{state} = 'debuglevel'; + my $msg = ''; + + if ( defined $level ) { + my $oldLevel = $self->{server}->debugLevel; + my $newLevel = $self->{server}->debugLevel( $level ); + $msg = "Debug level was $oldLevel; now $newLevel"; + } + + else { + $msg = "Debug level is " . $self->{server}->debugLevel; + } + + return $self->okayResponse( $msg ); +} + + +### METHOD: cmd_shutdown( undef ) +### Command handler for the C command. +sub cmd_shutdown { + my JobServer::Client $self = shift; + + $self->{state} = 'shutdown'; + + my $msg = $self->{server}->shutdown( $self ); + $self->{server} = undef; + $self->okayResponse( $msg ); + $self->close; + + return 1; +} + + +### METHOD: cmd_timedbuffer( undef ) +### Command handler for the C command. FOR DEBUGGING ONLY. +sub cmd_timedbuffer { + my JobServer::Client $self = shift; + + $self->{state} = 'timedbuffer'; + my @jobs = $self->{server}->recentmoves; + + my $count = 1; + my @entries = map { sprintf '%3d. %s', $count++, $_->prettyString } @jobs; + return $self->multilineResponse( "Server's timedbuffer:", @entries ); +} + + + + +### Template for new command handlers: + +# ### METHOD: cmd_foo( undef ) +# ### Command handler for the C command. +# sub cmd_foo { +# my JobServer::Client $self = shift; +# +# $self->{state} = 'foo'; +# return $self->errorResponse( "Not yet implemented." ); +# } +# +# + +1; + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/livejournal/bin/qbufferd.pl b/livejournal/bin/qbufferd.pl new file mode 100755 index 0000000..33c6c3a --- /dev/null +++ b/livejournal/bin/qbufferd.pl @@ -0,0 +1,253 @@ +#!/usr/bin/perl +# +# +# lib: Proc::ProcessTable, cgi-bin/ljlib.pl +# + +use strict; +use Getopt::Long +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/supportlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl"; + +my $opt_foreground; +my $opt_debug; +my $opt_stop; +exit 1 unless GetOptions('foreground' => \$opt_foreground, + 'debug' => \$opt_debug, + 'stop' => \$opt_stop, + ); + +BEGIN { + $LJ::OPTMOD_PROCTABLE = eval "use Proc::ProcessTable; 1;"; +} + +my $DELAY = $LJ::QBUFFERD_DELAY || 15; + +my $pidfile = $LJ::QBUFFERD_PIDFILE || "$ENV{'LJHOME'}/var/qbufferd.pid"; +my $pid; +if (-e $pidfile) { + open (PID, $pidfile); + chomp ($pid = ); + close PID; + if ($opt_stop) { + if (kill 15, $pid) { + print "Shutting down qbufferd.\n"; + } else { + print "qbufferd not running?\n"; + } + exit; + } + + if ($LJ::OPTMOD_PROCTABLE) { + my $processes = Proc::ProcessTable->new()->table; + if (grep { $_->cmndline =~ /perl.+qbufferd/ && $_->pid != $$ } @$processes) { + exit; + } + } else { + if (kill 0, $pid) { + # seems to still be running (at least something is with that pid) + exit; + } + } +} +if ($opt_stop) { + print "qbufferd not running?\n"; + exit; +} + +$SIG{'INT'} = \&stop_qbufferd; +$SIG{'TERM'} = \&stop_qbufferd; +$SIG{'HUP'} = sub { + # nothing. maybe later make a HUP force a flush? +}; + +if (!$opt_foreground && ($pid = fork)) +{ + unless (open (PID, ">$pidfile")) { + kill 15, $pid; + die "Couldn't write PID file. Exiting.\n"; + } + print PID $pid, "\n"; + close PID; + print "qbufferd started with pid $pid\n"; + if (-s $pidfile) { print "pid file written ($pidfile)\n"; } + exit; +} + +# Close filehandles unless running in --debug or --foreground mode. +unless ( $opt_debug || $opt_foreground ) { + close STDIN && open STDIN, "&STDIN"; + close STDERR && open STDERR, "+>&STDIN"; +} + +# fork off a separate qbufferd process for all specified +# job types in @LJ::QBUFFERD_ISOLATE, and then +# another process for all other job types. The current process +# will keep tabs on all of those + +my %isolated; +my %pids; # job -> pid +my %jobs; # pid -> job +my $working = 0; # 1 for processes that do actual work + +my $my_job; + +foreach my $job (@LJ::QBUFFERD_ISOLATE) { + $isolated{$job} = 1; +} + +foreach my $job (@LJ::QBUFFERD_ISOLATE, "_others_") { + if (my $child = fork) { + # parent. + $pids{$job} = $child; + $jobs{$child} = $job; + next; + } else { + # child. + $0 .= " [$job]"; + $my_job = $job; + $working = 1; + last; + } +} + +# at this point, $my_job is either the specialized 'cmd' to run, or +# '_others_' to mean everything besides stuff with their own processes. +# $working is 1 for nonempty values of $my_job . + +sub stop_qbufferd +{ + # stop children + unless ($working) { + foreach my $job (keys %pids) { + my $child = $pids{$job}; + print "Killing child pid $child job: $job\n" if $opt_debug; + kill 15, $child; + } + + unlink $pidfile; + } + + print "Quitting: " . ($working ? "job $my_job" : "parent") . "\n" if $opt_debug; + exit; +} + + +while(not $working) { + # controlling process's cycle + my $pid; + + $pid = wait(); + + print "Child exited, pid $pid, job $jobs{$pid}\n" if $opt_debug; + if ($jobs{$pid}) { + my $job = $jobs{$pid}; + print "Restarting job $job\n" if $opt_debug; + delete $pids{$job}; + delete $jobs{$pid}; + if (my $child = fork) { + # parent. + $pids{$job} = $child; + $jobs{$child} = $job; + } else { + # child. + $0 .= " [$job]"; + $my_job = $job; + $working = 1; # go work + } + } +} + +# the actual work begins here +my @all_jobs = qw(delitem weblogscom send_mail support_notify dirty); +foreach my $hook (keys %LJ::HOOKS) { + next unless $hook =~ /^cmdbuf:(\w+):run$/; + push @all_jobs, $1; +} + +while (LJ::start_request()) +{ + my $cycle_start = time(); + print "Starting cycle. Job $my_job\n" if $opt_debug; + + # syndication (checks RSS that need to be checked) + if ($my_job eq "synsuck") { + system("$ENV{'LJHOME'}/bin/ljmaint.pl", "-v0", "synsuck"); + print "Sleeping. Job $my_job\n" if $opt_debug; + my $elapsed = time() - $cycle_start; + sleep ($DELAY-$elapsed) if $elapsed < $DELAY; + next; + } + + # do main cluster updates + my $dbh = LJ::get_dbh("master"); + unless ($dbh) { + sleep 10; + next; + } + + # keep track of what commands we've run the start hook for + my %started; + + # handle clusters + foreach my $c (@LJ::CLUSTERS) { + print "Cluster: $c Job: $my_job\n" if $opt_debug; + my $db = LJ::get_cluster_master($c); + next unless $db; + + my @check_jobs = ($my_job); + if ($my_job eq "_others_") { @check_jobs = grep { ! $isolated{$_} } @all_jobs; } + + foreach my $cmd (@check_jobs) { + my $have_jobs = $db->selectrow_array("SELECT cbid FROM cmdbuffer WHERE cmd=? LIMIT 1", + undef, $cmd); + next unless $have_jobs; + + print " Starting $cmd...\n" if $opt_debug; + unless ($started{$cmd}++) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:start"); + } + LJ::Cmdbuffer::flush($dbh, $db, $cmd); + print " Finished $cmd.\n" if $opt_debug; + + # monitor process size and job counts to suicide if necessary + my $size = 0; + if (open(S, "/proc/$$/status")) { + my $file; + { local $/ = undef; $file = ; } + $size = $1 if $file =~ /VmSize:.+?(\d+)/; + close S; + } + + # is it our time to go? + my $kill_job_ct = LJ::Cmdbuffer::get_property($cmd, 'kill_job_ct') || 0; + my $kill_mem_size = LJ::Cmdbuffer::get_property($cmd, 'kill_mem_size') || 0; + if ($kill_job_ct && $started{$cmd} >= $kill_job_ct || + $kill_mem_size && $size >= $kill_mem_size) + { + + # trigger reload of current child process + print "Job suicide: $cmd. (size=$size, rpcs=" . ($started{dirty}+0) . ")\n" + if $opt_debug; + + # run end hooks before dying + foreach my $cmd (keys %started) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish"); + } + + exit 0; + } + } + } + + # run the end hook for all commands we've run + foreach my $cmd (keys %started) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish"); + } + + print "Sleeping. Job $my_job\n" if $opt_debug; + my $elapsed = time() - $cycle_start; + sleep ($DELAY-$elapsed) if $elapsed < $DELAY; +}; diff --git a/livejournal/bin/statserv.pl b/livejournal/bin/statserv.pl new file mode 100755 index 0000000..97d9ab6 --- /dev/null +++ b/livejournal/bin/statserv.pl @@ -0,0 +1,207 @@ +#!/usr/bin/perl -w +# LiveJournal statistics server. Sits on a UDP port and journals +# information on the incoming hit rate, manages site bans, etc. +# Loosely based on the ljrpcd code to save typing ;) +# +# lib: IO::Socket Proc::ProcessTable IO::Handle DBI +# +# + +use strict; +use IO::Socket; +use IO::Handle; +use Proc::ProcessTable; +use DBI; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +# Max message length and port to bind. +my $MAXLEN = 512; +my $PORTNO = 6200; +my $PIDFILE = '/home/lj/var/statserv.pid'; +my $LOGDIR = '/home/lj/logs/'; + +# Maximum amount of hits they can use in five minutes. +my %maxes = ( 'ip' => 15, 'guest' => 20, 'user' => 25 ); + +# Pid and pidfile. +my $pid; +my $is_parent = 1; +# Socket. Needs to be here for the HUP stuff. +my $sock; +# Cache hash. +my %caches = (); +# Cache array. +my @events = (); + +# Exceptions hash (IP range or username as keys) +# If you want some host (such as a big stupid random proxy) to +# be more lenient with the number of hits it can make in five minutes, +# put the value in here. If value is -1, then there is no limit. +my %except = (); + +# In case we're shot, unlink the pidfile. +$SIG{TERM} = sub { + unlink($PIDFILE); + exit 1; +}; + +# Local network bind to. +my $MYNET = '10.0'; + +if (-e $PIDFILE) { + open (PID, $PIDFILE); + my $tpid; + chomp ($tpid = ); + close PID; + my $processes = Proc::ProcessTable->new()->table; + if (grep { $_->cmndline =~ /statserv/ } @$processes) { + print "Process exists already, quitting.\n"; + exit 1; + } +} + +print "LiveJournal Statistics Daemon starting up into the background...\n"; + +if ($pid = fork) { + # Parent, log pid and exit. + open(PID, ">$PIDFILE") or die "Couldn't open $PIDFILE for writing: $!\n"; + print PID $pid; + close(PID); + print "Closing ($pid) wrote to $PIDFILE\n"; + $is_parent = 1; + exit; +} else { + # This is the child. + my($cmdmsg, $remaddr, $remhost); + + # HUP signal handler. + $SIG{HUP} = \&restart_request; + # SIGUSR handler. + $SIG{USR1} = sub { open_logfile(); }; + + open_logfile(); + + $sock = IO::Socket::INET->new(LocalPort => "$PORTNO", Proto => 'udp') or die "socket: $@"; + + # Main loop. + while ($sock->recv($cmdmsg, $MAXLEN)) { + my ($port, $ipaddr) = sockaddr_in($sock->peername); + my $ip_addr = inet_ntoa($ipaddr); + + # Make sure it's from around here. + if ($ip_addr !~ m/^$MYNET/) { + print "Got message from an invalid host.\n"; + next; + } + + # Quick command parsing, since there isn't much to it. + if ($cmdmsg =~ s/^cmd:\s//) { + handle_request($cmdmsg); + next; + } + } + die "recv: $!\n"; +} + +# Sub to restart the daemon. +sub restart_request { + $sock->close; + unlink($PIDFILE); + exec($0); +} + + +# Handle the request. This updates the appropriate caches, +# and may set a ban. +# Requests look like: +# cmd: cachename : ip_addr : type : url +# type can be: ip, guest, or user +# If type is "ip" then cachename can be anything. I suggest +# it be set to "ip" as well. If just to save space. +sub handle_request { + my $cmd = shift; + my $now = time(); + + # Clear expired events. + clean_events($now); + # As of now, we don't care about the URL, really. + if ($cmd =~ m/^(\w+)\s:\s([\d\.]+)\s:\s(\w+)/) { + my $user = $1; + my $ip_addr = $2; + my $type = $3; + # If there was no cookie of any kind, the type + # name is set to "ip" - in this case we up the + # cache number for the IP range. + if ($type eq "ip") { + # This regex is dumb, but the data we have is trustable. + $user = $ip_addr; + $user =~ s/(\d+)\.(\d+)\.(\d+)\.(\d+)/$1\.$2\.$3\./; + } + unless (exists $caches{$user}) { + $caches{$user} = { 'numhit' => 0, 'type' => $type }; + } + push @events, [ $user, $now ]; + $caches{$user}->{'numhit'}++; + + # Now we check to see if they have hit too fast, and ban if so. + if (should_ban($user)) { + # FIXME: For final operation, this should be replaced with + # a call to set_ban(). This is also going to spam a ton, + # but with the "spiffy" algorithm I can't easily nuke a user. + print "Would have banned user $user. Hits: " . $caches{$user}->{'numhit'} . "\n"; + } + # After this, "add_stat($user, $type, $url)" should run. + } else { + print "Got a mal-formed request: $cmd\n"; + } + +} + +# Returns 1 if the passed "user" should be banned, 0 if not. +sub should_ban { + my $user = shift; + + my $max = $except{$user} || $maxes{$caches{$user}->{'type'}} || 0; + # If it doesn't have a defined class, do we really want it around? + return 1 unless ($max); + return 1 if ($caches{$user}->{'numhit'} > $max); + + return 0; +} + +# Removes old events, and decrements caches. +sub clean_events { + my $now = shift; + while (@events && $events[0]->[1] < $now - 360) { + my $deadevt = shift @events; + if (--$caches{$deadevt->[0]}->{'numhits'} < 1) { + delete $caches{$deadevt->[0]}; + } + } +} + +# Placeholder. Sets a ban in the database. +sub set_ban { + +} + +# Placeholder. Runs various stats collections. +sub add_stat { + +} + +# Opens a new tagged logfile. Also sets it to the default +# filehandle, sets autoflush, and returns the new handle. +sub open_logfile { + my $now = time(); + my $logname = $LOGDIR . "statserv-" . $now . "\.log\n"; + my $logfh = new IO::Handle; + open($logfh, ">> $logname") or die "Couldn't open $logname: $!\n"; + my $oldfh = select($logfh); + # Make sure the old one is closed. + close($oldfh); + # Set autoflush and return. + $| = 1; + return $logfh; +} diff --git a/livejournal/bin/truncate-cluster.pl b/livejournal/bin/truncate-cluster.pl new file mode 100755 index 0000000..eec0743 --- /dev/null +++ b/livejournal/bin/truncate-cluster.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# + +use strict; +require "$ENV{LJHOME}/cgi-bin/ljlib.pl"; + +my $cid = shift; +die "Usage: truncate-cluster.pl \n" unless $cid =~ /^\d+$/; + +my $dbh = LJ::get_db_writer(); +my $ct = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE clusterid=?", undef, $cid); +die $dbh->errstr if $dbh->err; + +if ($ct > 0) { + die "Can't truncate a cluster with users. Cluster \#$cid has $ct users.\n"; +} + +my $cm = LJ::get_cluster_master({raw=>1}, $cid); +die "Can't get handle to cluster \#$cid\n" unless $cm; + +my $size; +foreach my $table (sort (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL)) { + my $ts = $cm->selectrow_hashref("SHOW TABLE STATUS like '$table'"); + die "Can't get table status for $table\n" unless $ts; + print "Size of $table = $ts->{'Data_length'}\n"; + next unless $ts->{'Data_length'}; + $cm->do("TRUNCATE TABLE $table"); + die $cm->errstr if $cm->err; + + $size += $ts->{'Data_length'}; + +} +print "Total size truncated (excluding indexes): $size\n"; diff --git a/livejournal/bin/upgrading/base-data.sql b/livejournal/bin/upgrading/base-data.sql new file mode 100755 index 0000000..20af5eb --- /dev/null +++ b/livejournal/bin/upgrading/base-data.sql @@ -0,0 +1,1071 @@ +# This file is automatically generated from MySQL by $LJHOME/bin/dumpsql.pl +# Don't submit a diff against a hand-modified file - dump and diff instead. + +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#000000', 'Black', '210', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#0000FF', 'Blue, Bright', '150', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#00025C', 'Blue, Midnight', '140', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#002400', 'Green, Pine', '85', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#00EEC4', 'Green, Mint', '110', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#00FF00', 'Green, Bright', '100', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#00FFFF', 'Blue, Sky', '130', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#01059D', 'Blue, Navy', '145', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#015B01', 'Green, Dark', '90', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#019501', 'Green', '95', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#019997', 'Blue, Ocean', '125', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#066D98', 'Blue, Steel', '120', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#330000', ' Brown, Dark', '30', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#520155', 'Purple, Wine', '185', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#5B0101', 'Red, Darkest', '5', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#6569FF', 'Blue, Medium', '155', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#676767', 'Gray, Dark', '215', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#696A0A', 'Olive', '65', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#88FEE9', 'Green, Aqua', '115', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#8E01D7', 'Violet, Dark', '170', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#993300', ' Brown', '35', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#9E0000', 'Red, Dark', '10', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#A501A7', 'Purple', '190', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#ADB1FF', 'Blue, Light', '160', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#B0B200', 'Yellow, Dark', '70', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#B3FFB3', 'Green, Light', '105', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#BBFFFE', 'Blue, Light Sky', '135', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#BC5D00', 'Orange, Brown', '45', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#C0C0C0', 'Gray, Light', '220', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#CA65FF', 'Violet', '175', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#CC9966', ' Brown, Tan', '40', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#E3E5FF', 'Blue, Powder', '165', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#EFCFFF', 'Violet, Light', '180', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#F999FF', 'Purple, Pink', '200', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FCDDFF', 'Pink, Ice', '205', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FEFFBB', 'Yellow, Light', '80', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FF0000', 'Red', '15', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FF00FF', 'Purple, Fuchsia', '195', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FF6600', 'Orange, Bright', '50', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FF8B8B', 'Red, Light', '20', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FFB22B', 'Orange', '55', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FFCBCB', 'Red, Pink', '25', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FFE2A3', 'Orange, Light', '60', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FFFF00', 'Yellow', '75', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('#FFFFFF', 'White', '225', 'color'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('0', 'None', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('0', 'none', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('1', 'Western European (Windows)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('1', 'windows-1252', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('10', 'Western European (ISO)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('10', 'iso-8859-1', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('11', 'CP949', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('11', 'Korean (Windows)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('12', 'Chinese (Simplified)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('12', 'GB2312', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('2', 'UTF-8', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('2', 'Unicode (UTF-8)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('3', 'Cyrillic (Windows)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('3', 'windows-1251', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('4', 'Hebrew (ISO)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('4', 'hebrew', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('5', 'Greek', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('5', 'windows-1253', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('6', 'Cyrillic (KOI8)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('6', 'KOI8-R', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('7', 'Japanese (SHIFT-JIS)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('7', 'sjis', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('8', 'Japanese (EUC)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('8', 'euc-jp', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('9', 'BIG5', '0', 'encoding'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('9', 'Chinese Traditional (Big5)', '0', 'encname'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AD', 'Andorra', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AE', 'United Arab Emirates', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AF', 'Afghanistan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AG', 'Antigua and Barbuda', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AI', 'Anguilla', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AK', 'Alaska', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AL', 'Alabama', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AL', 'Albania', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AM', 'Armenia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AN', 'Netherlands Antilles', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AO', 'Angola', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AQ', 'Antarctica', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AR', 'Argentina', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AA', 'Armed Forces Americas', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AE', 'Armed Forces Other (AE)', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AP', 'Armed Forces Pacific', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AR', 'Arkansas', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AS', 'American Samoa', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AS', 'American Samoa', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AT', 'Austria', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AU', 'Australia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AW', 'Aruba', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AZ', 'Arizona', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('AZ', 'Azerbaijan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BA', 'Bosnia and Herzegovina', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BB', 'Barbados', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BD', 'Bangladesh', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BE', 'Belgium', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BF', 'Burkina Faso', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BG', 'Bulgaria', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BH', 'Bahrain', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BI', 'Burundi', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BJ', 'Benin', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BM', 'Bermuda', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BN', 'Brunei Darussalam', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BO', 'Bolivia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BR', 'Brazil', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BS', 'Bahamas', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BT', 'Bhutan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BV', 'Bouvet Island', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BW', 'Botswana', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BY', 'Belarus', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('BZ', 'Belize', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CA', 'California', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CA', 'Canada', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CC', 'Cocos (Keeling) Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CF', 'Central African Republic', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CG', 'Congo', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CH', 'Switzerland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CI', 'Cote D\'Ivoire (Ivory Coast)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CK', 'Cook Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CL', 'Chile', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CM', 'Cameroon', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CN', 'China', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CO', 'Colombia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CO', 'Colorado', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CR', 'Costa Rica', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CS', 'Czechoslovakia (former)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CT', 'Connecticut', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CU', 'Cuba', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CV', 'Cape Verde', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CX', 'Christmas Island', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CY', 'Cyprus', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('CZ', 'Czech Republic', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DC', 'Dist. of Columbia', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DE', 'Delaware', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DE', 'Deutsch', '1', 'lang'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DE', 'Germany', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DJ', 'Djibouti', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DK', 'Denmark', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DM', 'Dominica', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DO', 'Dominican Republic', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('DZ', 'Algeria', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('EC', 'Ecuador', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('EE', 'Estonia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('EG', 'Egypt', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('EH', 'Western Sahara', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('EN', 'English', '1', 'lang'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ER', 'Eritrea', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ES', 'Espanol', '1', 'lang'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ES', 'Spain', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ET', 'Ethiopia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FI', 'Finland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FJ', 'Fiji', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FK', 'Falkland Islands (Malvinas)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FL', 'Florida', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FM', 'Federated States of Micronesia', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FM', 'Micronesia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FO', 'Faroe Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FR', 'Francais', '1', 'lang'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FR', 'France', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('FX', 'France, Metropolitan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GA', 'Gabon', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GA', 'Georgia', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GD', 'Grenada', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GE', 'Georgia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GF', 'French Guiana', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GH', 'Ghana', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GI', 'Gibraltar', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GL', 'Greenland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GM', 'Gambia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GN', 'Guinea', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GP', 'Guadeloupe', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GQ', 'Equatorial Guinea', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GR', 'Greece', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GS', 'S. Georgia and S. Sandwich Isls.', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GT', 'Guatemala', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GU', 'Guam', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GU', 'Guam', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GW', 'Guinea-Bissau', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('GY', 'Guyana', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HI', 'Hawaii', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HK', 'Hong Kong', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HM', 'Heard and McDonald Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HN', 'Honduras', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HR', 'Croatia (Hrvatska)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HT', 'Haiti', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('HU', 'Hungary', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IA', 'Iowa', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ID', 'Idaho', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ID', 'Indonesia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IE', 'Ireland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IL', 'Illinois', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IL', 'Israel', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IN', 'India', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IN', 'Indiana', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IO', 'British Indian Ocean Territory', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IQ', 'Iraq', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IR', 'Iran', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IS', 'Iceland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('IT', 'Italy', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('JM', 'Jamaica', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('JO', 'Jordan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('JP', 'Japan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KE', 'Kenya', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KG', 'Kyrgyzstan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KH', 'Cambodia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KI', 'Kiribati', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KM', 'Comoros', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KN', 'Saint Kitts and Nevis', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KP', 'Korea (North)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KR', 'Korea (South)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KS', 'Kansas', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KW', 'Kuwait', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KY', 'Cayman Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KY', 'Kentucky', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('KZ', 'Kazakhstan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LA', 'Laos', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LA', 'Louisiana', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LB', 'Lebanon', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LC', 'Saint Lucia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LI', 'Liechtenstein', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LJSC', 'Scotland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LK', 'Sri Lanka', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LR', 'Liberia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LS', 'Lesotho', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LT', 'Lithuania', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LU', 'Luxembourg', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LV', 'Latvia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('LY', 'Libya', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MA', 'Massachusetts', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MA', 'Morocco', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MC', 'Monaco', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MD', 'Maryland', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MD', 'Moldova', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ME', 'Maine', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MH', 'Marshall Islands', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MG', 'Madagascar', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MH', 'Marshall Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MI', 'Michigan', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MK', 'Macedonia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ML', 'Mali', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MM', 'Myanmar', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MN', 'Minnesota', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MN', 'Mongolia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MO', 'Macau', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MO', 'Missouri', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MP', 'Northern Mariana Islands', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MP', 'Northern Mariana Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MQ', 'Martinique', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MR', 'Mauritania', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MS', 'Mississippi', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MS', 'Montserrat', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MT', 'Malta', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MT', 'Montana', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MU', 'Mauritius', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MV', 'Maldives', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MW', 'Malawi', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MX', 'Mexico', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MY', 'Malaysia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('MZ', 'Mozambique', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NA', 'Namibia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NC', 'New Caledonia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NC', 'North Carolina', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ND', 'North Dakota', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NE', 'Nebraska', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NE', 'Niger', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NF', 'Norfolk Island', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NG', 'Nigeria', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NH', 'New Hampshire', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NI', 'Nicaragua', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NJ', 'New Jersey', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NL', 'Netherlands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NM', 'New Mexico', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NO', 'Norway', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NP', 'Nepal', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NR', 'Nauru', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NT', 'Neutral Zone', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NU', 'Niue', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NV', 'Nevada', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NY', 'New York', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('NZ', 'New Zealand (Aotearoa)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('OH', 'Ohio', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('OK', 'Oklahoma', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('OM', 'Oman', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('OR', 'Oregon', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PA', 'Panama', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PA', 'Pennsylvania', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PE', 'Peru', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PF', 'French Polynesia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PG', 'Papua New Guinea', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PH', 'Philippines', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PK', 'Pakistan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PL', 'Poland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PM', 'St. Pierre and Miquelon', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PN', 'Pitcairn', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PR', 'Puerto Rico', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PR', 'Puerto Rico', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PS', 'Palestine', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PT', 'Portugal', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PW', 'Palau', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('PY', 'Paraguay', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('QA', 'Qatar', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RE', 'Reunion', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RI', 'Rhode Island', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RO', 'Romania', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RU', 'Russian Federation', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RU', 'Russian', '1', 'lang'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('RW', 'Rwanda', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SA', 'Saudi Arabia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SB', 'Solomon Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SC', 'Seychelles', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SC', 'South Carolina', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SD', 'South Dakota', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SD', 'Sudan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SE', 'Sweden', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SG', 'Singapore', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SH', 'St. Helena', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SI', 'Slovenia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SJ', 'Svalbard and Jan Mayen Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SK', 'Slovak Republic', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SL', 'Sierra Leone', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SM', 'San Marino', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SN', 'Senegal', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SO', 'Somalia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SR', 'Suriname', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ST', 'Sao Tome and Principe', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SU', 'USSR (former)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SV', 'El Salvador', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SY', 'Syria', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('SZ', 'Swaziland', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TC', 'Turks and Caicos Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TD', 'Chad', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TF', 'French Southern Territories', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TG', 'Togo', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TH', 'Thailand', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TJ', 'Tajikistan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TK', 'Tokelau', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TM', 'Turkmenistan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TN', 'Tennessee', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TN', 'Tunisia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TO', 'Tonga', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TP', 'East Timor', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TR', 'Turkey', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TT', 'Trinidad and Tobago', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TV', 'Tuvalu', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TW', 'Taiwan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TX', 'Texas', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('TZ', 'Tanzania', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UA', 'Ukraine', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UG', 'Uganda', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UK', 'United Kingdom', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UM', 'US Minor Outlying Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('US', 'United States', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UT', 'Utah', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UY', 'Uruguay', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('UZ', 'Uzbekistan', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VA', 'Vatican City State (Holy See)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VA', 'Virginia', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VC', 'Saint Vincent and the Grenadines', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VE', 'Venezuela', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VG', 'Virgin Islands (British)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VI', 'Virgin Islands (U.S.)', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VI', 'Virgin Islands', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VN', 'Viet Nam', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VT', 'Vermont', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('VU', 'Vanuatu', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WA', 'Washington', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WF', 'Wallis and Futuna Islands', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WI', 'Wisconsin', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WS', 'Samoa', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WV', 'West Virginia', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('WY', 'Wyoming', '0', 'state'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('YE', 'Yemen', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('YT', 'Mayotte', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('YU', 'Yugoslavia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ZA', 'South Africa', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ZM', 'Zambia', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ZR', 'Zaire', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ZW', 'Zimbabwe', '0', 'country'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('act', 'Australian Capital Territory', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('al', 'Alberta', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('bc', 'British Columbia', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('be', 'Berlin', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('bm', 'Bremen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('br', 'Brandenburg', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('bw', 'Baden-Wuerttemberg', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('by', 'Bayern', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ha', 'Hamburg', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('hs', 'Hessen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ma', 'Manitoba', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('mv', 'Mecklenburg-Vorpommern', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nb', 'New Brunswick', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nf', 'Newfoundland', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ni', 'Niedersachsen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ns', 'Nova Scotia', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nsw', 'New South Wales', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nt', 'Northern Territory', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nu', 'Nunavut', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nw', 'Nordrhein-Westfalen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('nw', 'Northwest Territories', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('on', 'Ontario', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('pe', 'Prince Edward Island', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ql', 'Queensland', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('qu', 'Quebec', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('rp', 'Rheinland-Pfalz', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sa', 'Sachsen-Anhalt', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sa', 'Saskatchewan', '0', 'stateca'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sa', 'South Australia', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sc', 'Sachsen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sh', 'Schleswig-Holstein', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('sl', 'Saarland', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('ta', 'Tasmania', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('th', 'Thueringen', '0', 'statede'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('vi', 'Victoria', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('wa', 'Western Australia', '0', 'stateau'); +REPLACE INTO codes (code, item, sortorder, type) VALUES ('yt', 'Yukon Territory', '0', 'stateca'); +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('num', 'Unix time of the last change to number of comments to this post.', 'commentalter', 'Comments altered', 'general', '99'); +UPDATE logproplist SET datatype='num',des='Unix time of the last change to number of comments to this post.',prettyname='Comments altered',scope='general',sortorder='99' WHERE name='commentalter'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Your current mood.', 'current_mood', 'Current Mood', 'general', '5'); +UPDATE logproplist SET datatype='char',des='Your current mood.',prettyname='Current Mood',scope='general',sortorder='5' WHERE name='current_mood'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('num', 'Your current mood ID number, if known.', 'current_moodid', 'Current Mood ID#', 'general', '6'); +UPDATE logproplist SET datatype='num',des='Your current mood ID number, if known.',prettyname='Current Mood ID#',scope='general',sortorder='6' WHERE name='current_moodid'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Music you\'re currently listening to.', 'current_music', 'Current Music', 'general', '10'); +UPDATE logproplist SET datatype='char',des='Music you\'re currently listening to.',prettyname='Current Music',scope='general',sortorder='10' WHERE name='current_music'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'True if comments to this item include screened comments', 'hasscreened', 'Has screened replies', 'general', '99'); +UPDATE logproplist SET datatype='bool',des='True if comments to this item include screened comments',prettyname='Has screened replies',scope='general',sortorder='99' WHERE name='hasscreened'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'Set to true if this item shouldn\'t show up on people\'s friends lists (because it occurred in the past)', 'opt_backdated', 'Back-dated', 'general', '35'); +UPDATE logproplist SET datatype='bool',des='Set to true if this item shouldn\'t show up on people\'s friends lists (because it occurred in the past)',prettyname='Back-dated',scope='general',sortorder='35' WHERE name='opt_backdated'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'Turn on if readers can\'t post comments on this entry.', 'opt_nocomments', 'Don\'t Allow Comments', 'general', '25'); +UPDATE logproplist SET datatype='bool',des='Turn on if readers can\'t post comments on this entry.',prettyname='Don\'t Allow Comments',scope='general',sortorder='25' WHERE name='opt_nocomments'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'Turn on if the poster isn\'t interested in receiving comments to this post by email', 'opt_noemail', 'Don\'t email comments', 'general', '40'); +UPDATE logproplist SET datatype='bool',des='Turn on if the poster isn\'t interested in receiving comments to this post by email',prettyname='Don\'t email comments',scope='general',sortorder='40' WHERE name='opt_noemail'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'Turn on if post contains HTML and shouldn\'t be formatted', 'opt_preformatted', 'Don\'t Auto-Format', 'general', '20'); +UPDATE logproplist SET datatype='bool',des='Turn on if post contains HTML and shouldn\'t be formatted',prettyname='Don\'t Auto-Format',scope='general',sortorder='20' WHERE name='opt_preformatted'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Like opt_whoscreened: A = All, R = Remote needed (anonymous only), F = non-Friends, N = None, else use userprop.', 'opt_screening', 'Custom Screening Level', 'general', '45'); +UPDATE logproplist SET datatype='char',des='Like opt_whoscreened: A = All, R = Remote needed (anonymous only), F = non-Friends, N = None, else use userprop.',prettyname='Custom Screening Level',scope='general',sortorder='45' WHERE name='opt_screening'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'A keyword that should align to a defined picture', 'picture_keyword', 'Picture Keyword', 'general', '30'); +UPDATE logproplist SET datatype='char',des='A keyword that should align to a defined picture',prettyname='Picture Keyword',scope='general',sortorder='30' WHERE name='picture_keyword'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('num', 'Number of times this post has been edited.', 'revnum', 'Revision number', 'general', '99'); +UPDATE logproplist SET datatype='num',des='Number of times this post has been edited.',prettyname='Revision number',scope='general',sortorder='99' WHERE name='revnum'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('num', 'Unix time of the last edit', 'revtime', 'Revision time', 'general', '99'); +UPDATE logproplist SET datatype='num',des='Unix time of the last edit',prettyname='Revision time',scope='general',sortorder='99' WHERE name='revtime'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Unique id of syndication item', 'syn_id', 'Syndicated item id', 'general', '99'); +UPDATE logproplist SET datatype='char',des='Unique id of syndication item',prettyname='Syndicated item id',scope='general',sortorder='99' WHERE name='syn_id'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Original URL of syndication item', 'syn_link', 'Syndication item link URL', 'general', '99'); +UPDATE logproplist SET datatype='char',des='Original URL of syndication item',prettyname='Syndication item link URL',scope='general',sortorder='99' WHERE name='syn_link'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('char', 'Comma separated list of tags on the entry', 'taglist', 'Tag List', 'general', '101'); +UPDATE logproplist SET datatype='char',des='Comma separated list of tags on the entry',prettyname='Tag List',scope='general',sortorder='101' WHERE name='taglist'; +INSERT IGNORE INTO logproplist (datatype, des, name, prettyname, scope, sortorder) VALUES ('bool', 'True if text has 8-bit data that\'s not in UTF-8', 'unknown8bit', 'Unknown 8-bit text', 'general', '99'); +UPDATE logproplist SET datatype='bool',des='True if text has 8-bit data that\'s not in UTF-8',prettyname='Unknown 8-bit text',scope='general',sortorder='99' WHERE name='unknown8bit'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to view paid accounts that are going to expire soon', '1', 'accountsexpiring', 'Accounts - Expiring', 'general'); +UPDATE priv_list SET des='Allows a user to view paid accounts that are going to expire soon',is_public='1',privname='Accounts - Expiring',scope='general' WHERE privcode='accountsexpiring'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to grant or revoke privileges to/from other users. arg=Unique privcode that the user has access to grant/deny for, or \"*\" for all privileges.', '0', 'admin', 'Administer priviledges', 'general'); +UPDATE priv_list SET des='Allows a user to grant or revoke privileges to/from other users. arg=Unique privcode that the user has access to grant/deny for, or \"*\" for all privileges.',is_public='0',privname='Administer priviledges',scope='general' WHERE privcode='admin'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to set an IP address as being allowed if it\'s listed as an open proxy.', '0', 'allowopenproxy', 'Allow Open Proxy', 'general'); +UPDATE priv_list SET des='Allows a user to set an IP address as being allowed if it\'s listed as an open proxy.',is_public='0',privname='Allow Open Proxy',scope='general' WHERE privcode='allowopenproxy'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to access new features that are under development. arg=Feature codename', '1', 'betatest', 'Beta Test Features', 'general'); +UPDATE priv_list SET des='Allows a user to access new features that are under development. arg=Feature codename',is_public='1',privname='Beta Test Features',scope='general' WHERE privcode='betatest'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to view information that isn\'t otherwise available. All use is logged. arg=Arg="*": can view everything, Arg="suspended": can view public posts in a suspended journal, Arg="styles": can see private styles.', '0', 'canview', 'View All Entries', 'general'); +UPDATE priv_list SET des='Allows a user to view information that isn\'t otherwise available. All use is logged. arg=Arg="*": can view everything, Arg="suspended": can view public posts in a suspended journal, Arg="styles": can see private styles.',is_public='0',privname='View All Entries',scope='general' WHERE privcode='canview'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to change another user\'s journal type.', '1', 'changejournaltype', 'Change Journal Type', 'general'); +UPDATE priv_list SET des='Allows a user to change another user\'s journal type.',is_public='1',privname='Change Journal Type',scope='general' WHERE privcode='changejournaltype'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to change the maintainer of a community.', '1', 'communityxfer', 'Community Maintainer Transfer', 'general'); +UPDATE priv_list SET des='Allows a user to change the maintainer of a community.',is_public='1',privname='Community Maintainer Transfer',scope='general' WHERE privcode='communityxfer'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to delete comments from other journals. Only used in rare cases, like people posting other users\' phone numbers to be mean.', '1', 'deletetalk', 'Delete Comments', 'general'); +UPDATE priv_list SET des='Allows a user to delete comments from other journals. Only used in rare cases, like people posting other users\' phone numbers to be mean.',is_public='1',privname='Delete Comments',scope='general' WHERE privcode='deletetalk'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to FTP files and have them copied over to the main site\'s document roots. An example argument would be: \"client/win32=files/bin/clients/win32\". arg=Unique path of the form \"devftppath=htdocpath\"', '1', 'dirsync', 'Directory Sync', 'general'); +UPDATE priv_list SET des='Allows a user to FTP files and have them copied over to the main site\'s document roots. An example argument would be: \"client/win32=files/bin/clients/win32\". arg=Unique path of the form \"devftppath=htdocpath\"',is_public='1',privname='Directory Sync',scope='general' WHERE privcode='dirsync'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to add documents to the Frequently Asked Questions. arg=Unique faq category code that the privilege is applicable for, or \"*\" for all faq categories.', '1', 'faqadd', 'FAQ - Add', 'general'); +UPDATE priv_list SET des='Allows a user to add documents to the Frequently Asked Questions. arg=Unique faq category code that the privilege is applicable for, or \"*\" for all faq categories.',is_public='1',privname='FAQ - Add',scope='general' WHERE privcode='faqadd'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to modify FAQ categories.', '1', 'faqcat', 'FAQ - Edit Categories', 'general'); +UPDATE priv_list SET des='Allows a user to modify FAQ categories.',is_public='1',privname='FAQ - Edit Categories',scope='general' WHERE privcode='faqcat'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit documents in the Frequently Asked Questions. arg=Unique FAQ category code that the privilege is applicable for, or \"*\" for all faq categories', '1', 'faqedit', 'FAQ - Edit', 'general'); +UPDATE priv_list SET des='Allows a user to edit documents in the Frequently Asked Questions. arg=Unique FAQ category code that the privilege is applicable for, or \"*\" for all faq categories',is_public='1',privname='FAQ - Edit',scope='general' WHERE privcode='faqedit'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit a static file in the main site\'s document include tree. arg=Unique file identifier, or \"*\" for all files', '1', 'fileedit', 'File Editing', 'general'); +UPDATE priv_list SET des='Allows a user to edit a static file in the main site\'s document include tree. arg=Unique file identifier, or \"*\" for all files',is_public='1',privname='File Editing',scope='general' WHERE privcode='fileedit'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to find other users by different criteria. arg=Optional \"codetrace\", which allows the user to see someone\'s use of account codes.', '1', 'finduser', 'Find a user', 'general'); +UPDATE priv_list SET des='Allows a user to find other users by different criteria. arg=Optional \"codetrace\", which allows the user to see someone\'s use of account codes.',is_public='1',privname='Find a user',scope='general' WHERE privcode='finduser'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to generate unlimited numbers of invite codes.', '1', 'gencodes', 'Generate Codes', 'general'); +UPDATE priv_list SET des='Allows a user to generate unlimited numbers of invite codes.',is_public='1',privname='Generate Codes',scope='general' WHERE privcode='gencodes'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to grant another account a Permanent Account', '1', 'grantperm', 'Grant Permanent Account', 'general'); +UPDATE priv_list SET des='Allows a user to grant another account a Permanent Account',is_public='1',privname='Grant Permanent Account',scope='general' WHERE privcode='grantperm'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to view data in the \"statushistory\" table for all users. arg=Type of \"statushistory\" entries user can see, or no argument to see everything.', '1', 'historyview', 'View statushistory info', 'general'); +UPDATE priv_list SET des='Allows a user to view data in the \"statushistory\" table for all users. arg=Type of \"statushistory\" entries user can see, or no argument to see everything.',is_public='1',privname='View statushistory info',scope='general' WHERE privcode='historyview'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to record payments for paid accounts.', '1', 'moneyenter', 'Money - Enter Payments', 'general'); +UPDATE priv_list SET des='Allows a user to record payments for paid accounts.',is_public='1',privname='Money - Enter Payments',scope='general' WHERE privcode='moneyenter'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to search for payments entered.', '1', 'moneysearch', 'Money - Search for payments', 'general'); +UPDATE priv_list SET des='Allows a user to search for payments entered.',is_public='1',privname='Money - Search for payments',scope='general' WHERE privcode='moneysearch'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to see details about incoming money.', '1', 'moneyview', 'Money - View Detailed Records', 'general'); +UPDATE priv_list SET des='Allows a user to see details about incoming money.',is_public='1',privname='Money - View Detailed Records',scope='general' WHERE privcode='moneyview'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit mood themes and make themes public.', '1', 'moodthememanager', 'Mood Themes - Manager', 'general'); +UPDATE priv_list SET des='Allows a user to edit mood themes and make themes public.',is_public='1',privname='Mood Themes - Manager',scope='general' WHERE privcode='moodthememanager'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to delete all email addresses from an account.', '1', 'reset_email', 'Reset User Email Address', 'general'); +UPDATE priv_list SET des='Allows a user to delete all email addresses from an account.',is_public='1',privname='Reset User Email Address',scope='general' WHERE privcode='reset_email'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to reset the password to an account', '1', 'reset_password', 'Reset User Password', 'general'); +UPDATE priv_list SET des='Allows a user to reset the password to an account',is_public='1',privname='Reset User Password',scope='general' WHERE privcode='reset_password'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit the database schema documentation.', '1', 'schemadoc', 'Edit Schema Documentation', 'general'); +UPDATE priv_list SET des='Allows a user to edit the database schema documentation.',is_public='1',privname='Edit Schema Documentation',scope='general' WHERE privcode='schemadoc'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to add or remove people\'s access to post in a shared journal. arg=Community/shared journal username that\'s being administrated, or \"*\" for all journals.', '0', 'sharedjournal', 'Shared Journal - Admin', 'general'); +UPDATE priv_list SET des='Allows a user to add or remove people\'s access to post in a shared journal. arg=Community/shared journal username that\'s being administrated, or \"*\" for all journals.',is_public='0',privname='Shared Journal - Admin',scope='general' WHERE privcode='sharedjournal'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to view/adjust certain critical site settings. arg=Unique keyword that user has access to view', '1', 'siteadmin', 'Administer Site', 'general'); +UPDATE priv_list SET des='Allows a user to view/adjust certain critical site settings. arg=Unique keyword that user has access to view',is_public='1',privname='Administer Site',scope='general' WHERE privcode='siteadmin'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to change the summary on support requests. arg=Unique support category', '1', 'supportchangesummary', 'Support - Change Summaries', 'general'); +UPDATE priv_list SET des='Allows a user to change the summary on support requests. arg=Unique support category',is_public='1',privname='Support - Change Summaries',scope='general' WHERE privcode='supportchangesummary'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to close old support requests that other users haven\'t closed themselves. arg=Unique support category that the user has permission to close in.', '1', 'supportclose', 'Support - Close Requests', 'general'); +UPDATE priv_list SET des='Allows a user to close old support requests that other users haven\'t closed themselves. arg=Unique support category that the user has permission to close in.',is_public='1',privname='Support - Close Requests',scope='general' WHERE privcode='supportclose'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to delete duplicate or fake support requests.', '1', 'supportdelete', 'Support - Delete Requests', 'general'); +UPDATE priv_list SET des='Allows a user to delete duplicate or fake support requests.',is_public='1',privname='Support - Delete Requests',scope='general' WHERE privcode='supportdelete'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to approve screened responses, change request summaries and answer and comment unscreened. arg=Unique Support Category', '1', 'supporthelp', 'Support - Manage Requests', 'general'); +UPDATE priv_list SET des='Allows a user to approve screened responses, change request summaries and answer and comment unscreened. arg=Unique Support Category',is_public='1',privname='Support - Manage Requests',scope='general' WHERE privcode='supporthelp'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to make internal comments on support requests. arg=Unique support category', '1', 'supportmakeinternal', 'Support - Make Internal Comments', 'general'); +UPDATE priv_list SET des='Allows a user to make internal comments on support requests. arg=Unique support category',is_public='1',privname='Support - Make Internal Comments',scope='general' WHERE privcode='supportmakeinternal'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to move support requests to different categories and to mark requests as still needing help. The supportmakeinternal privilege is required. arg=Unique support category', '1', 'supportmovetouch', 'Support - Move and Touch Requests', 'general'); +UPDATE priv_list SET des='Allows a user to move support requests to different categories and to mark requests as still needing help. The supportmakeinternal privilege is required. arg=Unique support category',is_public='1',privname='Support - Move and Touch Requests',scope='general' WHERE privcode='supportmovetouch'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to read support requests in private categories. arg=Unique support category', '1', 'supportread', 'Support - Read Requests', 'general'); +UPDATE priv_list SET des='Allows a user to read support requests in private categories. arg=Unique support category',is_public='1',privname='Support - Read Requests',scope='general' WHERE privcode='supportread'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to view internal comments on support requests. arg=Unique support category', '1', 'supportviewinternal', 'Support - View Internal Comments', 'general'); +UPDATE priv_list SET des='Allows a user to view internal comments on support requests. arg=Unique support category',is_public='1',privname='Support - View Internal Comments',scope='general' WHERE privcode='supportviewinternal'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to read screened responses on support requests. arg=Unique support category', '1', 'supportviewscreened', 'Support - See Screened Responses', 'general'); +UPDATE priv_list SET des='Allows a user to read screened responses on support requests. arg=Unique support category',is_public='1',privname='Support - See Screened Responses',scope='general' WHERE privcode='supportviewscreened'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to suspend or unsuspend user accounts. Used by the Abuse Team.', '0', 'suspend', 'Suspend accounts', 'general'); +UPDATE priv_list SET des='Allows a user to suspend or unsuspend user accounts. Used by the Abuse Team.',is_public='0',privname='Suspend accounts',scope='general' WHERE privcode='suspend'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows editing settings of syndicated journal that shouldn\'t be editable by users.', '0', 'syn_edit', 'Edit Syndicated Settings', 'general'); +UPDATE priv_list SET des='Allows editing settings of syndicated journal that shouldn\'t be editable by users.',is_public='0',privname='Edit Syndicated Settings',scope='general' WHERE privcode='syn_edit'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to modify bans with the sysban mechanism. arg=A specific ban type the user can modify, or \"*\" for all ban type.', '0', 'sysban', 'Modify System Bans', 'general'); +UPDATE priv_list SET des='Allows a user to modify bans with the sysban mechanism. arg=A specific ban type the user can modify, or \"*\" for all ban type.',is_public='0',privname='Modify System Bans',scope='general' WHERE privcode='sysban'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to add/approve/deny new topics within a category. arg=Unique category number that the user has access in, or \"*\" for all categories.', '1', 'topicaddtopic', 'Topic Dir - Add Topics', 'general'); +UPDATE priv_list SET des='Allows a user to add/approve/deny new topics within a category. arg=Unique category number that the user has access in, or \"*\" for all categories.',is_public='1',privname='Topic Dir - Add Topics',scope='general' WHERE privcode='topicaddtopic'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to have all access to administrative functions of the topic directory. They can then create/edit topics, create/edit topic categories, etc.', '1', 'topicmanager', 'Topic Dir - Manager', 'general'); +UPDATE priv_list SET des='Allows a user to have all access to administrative functions of the topic directory. They can then create/edit topics, create/edit topic categories, etc.',is_public='1',privname='Topic Dir - Manager',scope='general' WHERE privcode='topicmanager'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to approve or deny entries that are submitted to the directory. arg=Unique category number that the user has access in, or \"*\" for all categories', '1', 'topicscreencat', 'Topic Dir - Screen Submissions', 'general'); +UPDATE priv_list SET des='Allows a user to approve or deny entries that are submitted to the directory. arg=Unique category number that the user has access in, or \"*\" for all categories',is_public='1',privname='Topic Dir - Screen Submissions',scope='general' WHERE privcode='topicscreencat'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit site text in a given language. arg=Unique language code, optionally appended by |domainid.domaincode', '1', 'translate', 'Translate/Update Text', 'general'); +UPDATE priv_list SET des='Allows a user to edit site text in a given language. arg=Unique language code, optionally appended by |domainid.domaincode',is_public='1',privname='Translate/Update Text',scope='general' WHERE privcode='translate'; +INSERT IGNORE INTO ratelist (des, name) VALUES ('Logged when wrong username/password is used.', 'failed_login'); +INSERT IGNORE INTO ratelist (des, name) VALUES ('Logged whenever user posts (to any journal)', 'post'); +INSERT IGNORE INTO ratelist (des, name) VALUES ('Logged when a forgotten password or username e-mail is requested', 'lostinfo'); +UPDATE ratelist SET des='Logged when wrong username/password is used.',name='failed_login' WHERE rlid=NULL; +UPDATE ratelist SET des='Logged whenever user posts (to any journal)',name='post' WHERE rlid=NULL; +UPDATE ratelist SET des='Logged when a forgotten password or username e-mail is requested',name='lostinfo' WHERE rlid=NULL; +REPLACE INTO schemacols (colname, des, tablename) VALUES ('FIPS', '??', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('Name', 'Name of city', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('State', 'State', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('aaid', 'Primary key for each authaction.', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('acid', 'Account code ID. Primary key.', 'acctcode'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('acid', 'The account code ID from [dbtable[acctcode]].', 'acctpay'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('acid', 'The resultant acid code in table [dbtable[acctcode]].', 'acctinvite'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('action', 'The action command name to be run when the authaction is confirmed (clicked/etc)', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('alloc', '??', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('answer', 'The answer text, in plaintext.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('area', 'The type of usage: \"L\" for log, \"T\" for talk, \"B\" for bio, \"P\" for pic.', 'dudata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('areaid', 'Unique ID within area, or \'0\' if area has no ids (like bio)', 'dudata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('arg1', 'Optional argument to accompany the action.', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('args', 'A URL string of arguments.', 'cmdbuffer'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('auth', 'Five randomly generated bytes. This, along with the acid encoded, make up the invite code.', 'acctcode'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('authcode', 'Random characters (the confirmation bit)', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('bgcolor', 'The background color used in the friends view events.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('bytes', 'Number of bytes item takes up.', 'dudata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('cbid', 'unique id', 'cmdbuffer'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('city', 'City name', 'zip'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('client', 'Client string, of form Platform-Name/Version. See login mode of protocol docs.', 'clients'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('clientid', 'Clientid of client from [dbtable[clients]] table.', 'clientusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('clientid', 'Primary key. Auto-generated for each new client name.', 'clients'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('cmd', 'Text of the command name.', 'cmdbuffer'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('color', 'The #rrggbb color (or one of the constants)', 'themedata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('coltype', 'The color code, references [dbtable[themecoltypes]].', 'themedata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('curr', 'The current weighting value for this dbid+role.', 'dbweights'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('datatype', 'Either \"char\" for text data, \"num\" for an integer, or \"bool\" for a 1/0 value.', 'userproplist'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dateadd', 'Date code was create.', 'acctinvite'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('datecreate', 'Date the auth code was created.', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dateins', 'The date the search was made.', 'dirsearchres2'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dateview', 'The time of the viewing.', 'faquses'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dbid', 'The dbid from [dbtable[dbinfo]].', 'dbweights'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dbid', 'Unique database ID. Recommended to use the mysql server-id value.', 'dbinfo'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('des', 'A description of the table, for use in the schema browser, and in the LJ manual.', 'schematables'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('des', 'Description of the meta-data, for use by developers (humans?)', 'userproplist'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('digest', 'The md5 digest of the event. Concatenate everything important and run it through perl\'s md5_hex (or MySQL\'s md5)', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('domain', 'domain name, without any leading http:// or www. Example: foo.com', 'domains'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('dupid', 'The unique ID this action generated the first time.', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('faqcat', 'The name of the main category the FAQ item belongs to. Is the index to [dbtable[faqcat]]', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('faqid', 'The faqid of the [dbtable[faq]] item which was viewed.', 'faquses'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('faqid', 'The unique id number of the FAQ.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('fdsn', 'The DBI connection DSN, username, then password, delimited by pipe characters.', 'dbinfo'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('fgcolor', 'The foreground color used in the friends view events.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('friendid', 'The [dbtable[user]].userid of the friend to watch/trust.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('groupmask', 'A bitmask of 1 (1 << 0) OR\'ed with (1 << [dbtable[friendgroup]].groupnum) for each friendgroup this friend belongs to.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('groupname', 'Name given to the friend group.', 'friendgroup'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('groupnum', 'The group number. Can be 1-30.', 'friendgroup'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('incname', 'The filename of the include file.', 'includetext'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('inctext', 'The text contents of the include file.', 'includetext'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('instime', 'The time the action first completed.', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('instime', 'The time the query was buffered. Not used by applications, but useful for debugging/humans.', 'cmdbuffer'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('intcount', 'The number of users listing the interest.', 'interests'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('interest', 'The text of the interest.', 'interests'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('intid', 'Unique id assigned to the interest.', 'interests'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('is_public', 'Determines if the group can be seen by anyone, or just the owner.', 'friendgroup'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('journalid', 'Journal id the command affects. This is so that all of a user\'s queued actions can be run before that user is potentially movedbetween clusters.', 'cmdbuffer'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lastitemid', 'Itemid of their last post (see [dbtable[log]]/[dbtable[log2]])', 'userusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lastlogin', 'The most recent time this user used this client.', 'clientusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lastmodtime', 'The date the FAQ item was last modified.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lastmoduserid', 'The userid of the [dbtable[user]] who last modified the FAQ item.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lat', 'Latitude', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('lon', 'Longitude', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('masterid', 'The dbid which this server replicates from, or 0 for the master server. Note: only one server should have a master of 0!', 'dbinfo'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('membership', 'Can people join without being invited?', 'community'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('name', 'A unique name of the server.', 'dbinfo'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('name', 'Name of property, matching [a-z0-9_]+. Intended for use by code and clients.', 'userproplist'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('norm', 'The normal weighting value for this dbid+role.', 'dbweights'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('oldvalue', 'The old value of the item.', 'infohistory'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('other', 'Optional note space.', 'infohistory'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('payid', 'The payment ID from [dbtable[payments]].', 'acctpay'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('pop1990', 'Population in 1990.', 'zips'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('postlevel', 'Who can post? Members only, or a select group. \"screened\" is not yet used.', 'community'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('prettyname', 'Mixed case pretty name with spaces and punctuation. Indeded for use by humans.', 'userproplist'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('public_browsable', 'If set to 1, users can view the data in this table from the web. (lookup tables only)', 'schematables'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('qdigest', 'An MD5sum of the SQL search query.', 'dirsearchres2'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('question', 'The question text, in plaintext.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('rcptid', 'Userid of recipient, or 0 if code is unused.', 'acctcode'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('realm', 'The area of the site the lock is being provided for.', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('reason', 'Reason code for generating invite code. See invite/gen.bml', 'acctinvite'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('redist_mode', 'Determines if data from this table is made available in the LJ source distribution. And if so, is it to be updated with upgrades (REPLACE INTO) or just inserted once.', 'schematables'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('reid', 'Realm ID. If you don\'t need it (most don\'t), use 0. Example: for comment realm, reid is the itemid being replied to.', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('role', 'The database role type: master, slave, clusterN, clusterNslave, etc... See other documentation.', 'dbweights'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('rootfdsn', 'The fdsn to connect as root, to do administrative stuff.', 'dbinfo'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('showbydefault', 'Unused.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('sortorder', 'The sorting number the questions are ordered by. Used while SELECT\'ing them.', 'faq'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('sortorder', 'The sorting order.', 'friendgroup'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('state', 'State code (see [dbtable[codes]] for how to turn this into a full state name)', 'zip'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('tablename', 'The name of the table being described.', 'schematables'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('themeid', 'Unique ID, references [dbtable[themelist]] table.', 'themedata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('timechange', 'The time of the change.', 'infohistory'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('timecheck', 'unused.', 'userusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('timecreate', 'When the user created their journal.', 'userusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('timeupdate', 'When the user last updated their journal.', 'userusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('track', 'If the police or a court has contact us to track a user, we turn this on and activities are logged to the [dbtable[tracking]] table.', 'user'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('updatetime', 'The date it was last updated.', 'includetext'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('upropid', 'Unique id for this meta-data property.', 'userproplist'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Community\'s userid from the [dbtable[user]] table.', 'community'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid doing the action, or 0 if user is unknown (as in support realm)', 'duplock'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid of the [dbtable[user]] making the change.', 'infohistory'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid of the [dbtable[user]] who added the friend.', 'friends'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid of the [dbtable[user]] who this friends group belongs to.', 'friendgroup'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid of the remote [dbtable[user]] viewing the FAQ item.', 'faquses'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'The userid the disk usage item belongs to.', 'dudata'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid of [dbtable[user]] that code was made for.', 'acctinvite'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid of [dbtable[user]] using client.', 'clientusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid of [dbtable[user]] we\'re verifying.', 'authactions'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid of [dbtable[user]] whose journal should be loaded.', 'domains'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid of [dbtable[user]]. One row in this table per user.', 'userusage'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userid', 'Userid that can give this code.', 'acctcode'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('userids', 'List of matched userids for the query, comma separated.', 'dirsearchres2'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('what', 'Short name of the item being changed.', 'infohistory'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('zip', 'ZIP Code', 'zip'); +REPLACE INTO schemacols (colname, des, tablename) VALUES ('zip', 'ZIP Code', 'zips'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('', '0', 'off', NULL, 'moods'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('', '0', 'off', NULL, 'user'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('', '0', 'replace', NULL, 'schemacols'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('A history log table for certain types of changes (like user e-mail changes). So the old values can be looked at by administrators or automatically retrieved.', '0', 'off', NULL, 'infohistory'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Categories for support system', '1', 'insert', 'catkey=\'general\'', 'supportcat'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Categories that frequently asked questions can be classified under', '1', 'off', NULL, 'faqcat'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Clustered version of [dbtable[querybuffer]]. Uses specialized commands instead of general table locking', '0', 'off', NULL, 'cmdbuffer'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Database table for storing special \"include\" files used in sections of the site (like the \"known issues\" box in support). Useful for keeping clusters of web servers in sync easier.', '0', 'off', NULL, 'includetext'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Different color schemes. Hopefully this will die when the new style system replaces the current one.', '1', 'replace', NULL, 'themelist'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('For LiveJournal installations with many databases, the database connection info, roles, and weightings can be stored in the database instead of the %LJ::DBINFO hash, for easier (web-based) management.\n', '0', 'off', NULL, 'dbinfo'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Holds Frequently Asked Question information for the FAQ section of the support system. Alternate text can be loaded for the questions if available.', '0', 'off', NULL, 'faq'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Holds the results of a directory search query. userids is either \"[searching]\" if a query is still running, or a list of userids if it is finished.', '0', 'off', NULL, 'dirsearchres2'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keep track of when [dbtable[user]]s did certain things.', '0', 'off', NULL, 'userusage'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of clients that access the protocol.\n\r\nWhenever the protocol encounters a new client, a new row (and thus a new clientid) is generated.', '0', 'off', NULL, 'clients'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of generated invite codes.', '0', 'off', NULL, 'acctinvite'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of properties of community accounts (which are just normal [dbtable[user]] accounts with some extra behavior)', '0', 'off', NULL, 'community'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of relationship between invite codes and payments. Some people pay to join the site before they have an account, so their invite code carries with it the knowledge that it comes with paid time.', '0', 'off', NULL, 'acctpay'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of user-owned domain names, and which journals they map to when pointed at the LiveJournal installation\'s IP address.', '0', 'off', NULL, 'domains'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of valid invite codes and who has used them. To see why they were made, see table [dbtable[acctinvite]].', '0', 'off', NULL, 'acctcode'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Keeps track of when different users use which clients, for purposes of statistics.', '0', 'off', NULL, 'clientusage'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('List of different admin privileges that users can have.', '1', 'replace', NULL, 'priv_list'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('List of possible meta-data for comments.', '1', 'replace', NULL, 'talkproplist'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('List of possible meta-data for journal entries.', '1', 'replace', NULL, 'logproplist'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('List of possible meta-data on users.', '1', 'replace', NULL, 'userproplist'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Lists the system colors themes available to users.', '0', 'replace', NULL, 'themedata'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Lookup table for states, countries, languages, etc...', '1', 'replace', NULL, 'codes'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Provides a place to record that an action has been done, so it doesn\'t get done a second time later by a user accidentally double-clicking a single-click button in their browser.\r\n\r\nThe idea is that the application should grab a write lock for both the table it\'s inserting into, and the duplock table. Then, check the duplock table for a duplicate. If it\'s already in there, unlock the tables and remember the dupid to tell the user (app should pretend it was the first time... don\'t show an error message!), or if it\'s not in there, put it in the table, and then put the resulting uniqueid from the table handler into the duplock table (as dupid).\r\n\r\nThe duplock table is purged every hour or so of all locks older than an hour.', '0', 'off', NULL, 'duplock'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Table describing a user\'s friends groups. Friends groups are used to restrict who can see an individual post, or to filter the friends view.', '0', 'off', NULL, 'friendgroup'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Table describing the different interests listed, and the number of users listing each interest.', '0', 'off', NULL, 'interests'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Table describing users someone has listed as a \"friend\". Also details preferences on the friend item.', '0', 'off', NULL, 'friends'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('The [dbtable[dbinfo]] table keeps track of which databases exist. This ones keeps track of each database\'s roles and weights.', '0', 'off', NULL, 'dbweights'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('This table is the documentation for the database tables.', '0', 'replace', NULL, 'schematables'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Tracks user-based disk usage totals.', '0', 'off', NULL, 'dudata'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Tracks viewings of the individual [dbtable[faq]]s from logged-in users.', '0', 'off', NULL, 'faquses'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Unused as of this writing. Part of the \"subscription\" system.', '0', 'off', NULL, 'events'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('When authenticating certain actions, the server generates an authaction along with some random characters (the authcode) and emails the aaid+authcode to the user to confirm they actually got it.\n', '0', 'off', NULL, 'authactions'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('ZIP Code data for the United States that includes geographic coordinates. Only used with a ljmaint script that generates marker files for use in making xplanet maps. Most the LJ code uses the [dbtable[zip]] table instead.', '0', 'off', NULL, 'zips'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('ZIP Code table used to validate and auto-complete data that users enter about their location. More information can be found in the redudant table [dbtable[zips]], which was imported later.', '0', 'off', NULL, 'zip'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('unused. designed for the \"Adopt-a-newbie\" system, but never fully implemented.', '0', 'off', NULL, 'adopt'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('unused. designed for the \"Adopt-a-newbie\" system, but never fully implemented.', '0', 'off', NULL, 'adoptlast'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES (NULL, '0', 'off', NULL, 'style'); +REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES (NULL, '1', 'replace', NULL, 'ratelist'); +INSERT IGNORE INTO supportcat (allow_screened, basepoints, catkey, catname, hide_helpers, is_selectable, no_autoreply, public_help, public_read, replyaddress, scope, sortorder) VALUES ('1', '1', 'general', 'General/Unknown', '0', '1', '0', '0', '1', NULL, 'general', '2'); +UPDATE supportcat SET allow_screened='1',basepoints='1',catname='General/Unknown',hide_helpers='0',is_selectable='1',no_autoreply='0',public_help='0',public_read='1',replyaddress=NULL,scope='general',sortorder='2' WHERE catkey='general'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'If the comment poster\'s account is deleted, this field gets added to all of their posts, so the UI can show something besides \'anonymous\' when posterid gets set to 0', 'deleted_poster', 'Username of deleted poster', 'general'); +UPDATE talkproplist SET datatype='char',des='If the comment poster\'s account is deleted, this field gets added to all of their posts, so the UI can show something besides \'anonymous\' when posterid gets set to 0',prettyname='Username of deleted poster',scope='general' WHERE name='deleted_poster'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('bool', 'true if auth\'d, false if not', 'guest_auth', 'URL of Guest Poster', 'general'); +UPDATE talkproplist SET datatype='bool',des='true if auth\'d, false if not',prettyname='URL of Guest Poster',scope='general' WHERE name='guest_auth'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'Anonymous comments with an email attached', 'guest_email', 'Email of Guest Poster', 'general'); +UPDATE talkproplist SET datatype='char',des='Anonymous comments with an email attached',prettyname='Email of Guest Poster',scope='general' WHERE name='guest_email'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('bool', 'If true, mangle guest email', 'guest_mangle_email', 'URL of Guest Poster', 'general'); +UPDATE talkproplist SET datatype='bool',des='If true, mangle guest email',prettyname='URL of Guest Poster',scope='general' WHERE name='guest_mangle_email'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'Anonymous comments with a name attached', 'guest_name', 'Name of Guest Poster', 'general'); +UPDATE talkproplist SET datatype='char',des='Anonymous comments with a name attached',prettyname='Name of Guest Poster',scope='general' WHERE name='guest_name'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'Anonymous comments with a URL attached', 'guest_url', 'Website of Guest Poster', 'general'); +UPDATE talkproplist SET datatype='char',des='Anonymous comments with a URL attached',prettyname='Website of Guest Poster',scope='general' WHERE name='guest_url'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('bool', 'Turn on if post contains HTML and shouldn\'t be formatted', 'opt_preformatted', 'Don\'t Auto-Format', 'general'); +UPDATE talkproplist SET datatype='bool',des='Turn on if post contains HTML and shouldn\'t be formatted',prettyname='Don\'t Auto-Format',scope='general' WHERE name='opt_preformatted'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'A keyword that should align to a defined picture', 'picture_keyword', 'Picture Keyword', 'general'); +UPDATE talkproplist SET datatype='char',des='A keyword that should align to a defined picture',prettyname='Picture Keyword',scope='general' WHERE name='picture_keyword'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'The poster\'s IP address, optionally logged.', 'poster_ip', 'Poster\'s IP address', 'general'); +UPDATE talkproplist SET datatype='char',des='The poster\'s IP address, optionally logged.',prettyname='Poster\'s IP address',scope='general' WHERE name='poster_ip'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('char', 'partial filename for subject icon to use', 'subjecticon', 'Subject Icon', 'general'); +UPDATE talkproplist SET datatype='char',des='partial filename for subject icon to use',prettyname='Subject Icon',scope='general' WHERE name='subjecticon'; +INSERT IGNORE INTO talkproplist (datatype, des, name, prettyname, scope) VALUES ('bool', 'True if text has 8-bit data that\'s not in UTF-8', 'unknown8bit', 'Unknown 8-bit text', 'general'); +UPDATE talkproplist SET datatype='bool',des='True if text has 8-bit data that\'s not in UTF-8',prettyname='Unknown 8-bit text',scope='general' WHERE name='unknown8bit'; +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_back', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_back', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_text', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_text', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_text', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_text_em', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'page_text_title', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'strong_text', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'strong_text', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'strong_text', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'strong_text', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'stronger_text', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'stronger_text', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'weak_text', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000000', 'weak_text', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000050', 'page_link', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000050', 'page_link', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000066', 'weak_back', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#000099', 'page_text_title', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#0000FF', 'page_link', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#0000FF', 'weak_text', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00025C', 'page_back', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00025C', 'stronger_back', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#003333', 'weak_back', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#005614', 'page_text_title', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#005614', 'stronger_back', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#005614', 'weak_text', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#006005', 'page_text', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#007537', 'page_text_em', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#007537', 'strong_text', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#007537', 'stronger_text', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#007537', 'weak_text', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#009007', 'page_link', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#009900', 'page_text_title', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00A427', 'strong_back', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00B208', 'page_vlink', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00CC00', 'strong_text', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#00FF00', 'page_text_em', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#01059D', 'strong_back', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#01059D', 'weak_back', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#303030', 'stronger_back', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#330099', 'strong_back', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#336600', 'strong_back', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#404040', 'weak_back', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#500050', 'page_vlink', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#500050', 'page_vlink', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#606060', 'weak_back', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#6633FF', 'page_link', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#6666CC', 'stronger_back', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#6F6F6F', 'stronger_back', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#707070', 'strong_back', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#7070FF', 'page_link', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#7e587e', 'strong_text', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#7e587e', 'weak_back', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#800000', 'page_text_title', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#800080', 'page_vlink', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#8b1A1A', 'page_text_title', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#8b1A1A', 'page_text_title', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#900090', 'page_vlink', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#909090', 'stronger_back', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#990000', 'page_vlink', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#99CC66', 'weak_text', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#AD39FF', 'page_alink', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#ADB1FF', 'page_text_title', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#AFEFBE', 'weak_back', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C00000', 'page_text_em', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C00000', 'page_text_em', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C00090', 'page_link', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C0C0C0', 'page_link', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C0C0C0', 'strong_back', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#C0C0FF', 'strong_back', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#CC0000', 'page_text_title', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#CC0000', 'strong_back', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#CC6600', 'page_link', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#CCCC00', 'page_text', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#D5E6C4', 'stronger_back', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#DD57FF', 'page_text_em', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#DFFFDF', 'weak_back', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#E0E0E0', 'weak_back', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#E44545', 'page_alink', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#E44545', 'page_link', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#E44545', 'page_vlink', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#EEEEFF', 'weak_back', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FA0029', 'stronger_back', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FBE3E3', 'weak_back', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FCDDFF', 'strong_text', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FCDDFF', 'weak_text', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FEFFBB', 'page_text', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF0000', 'page_alink', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF0000', 'page_alink', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF0000', 'page_alink', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF0000', 'page_text_em', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF0000', 'weak_text', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF00C0', 'page_alink', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF00C0', 'page_alink', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF133A', 'page_text', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF33FF', 'page_vlink', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF6982', 'strong_back', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF70FF', 'page_vlink', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF8B8B', 'stronger_text', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF9900', 'strong_text', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF9900', 'stronger_text', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FF9900', 'weak_back', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFC000', 'page_text_em', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFC1CB', 'weak_back', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFCBCB', 'page_alink', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFCBCB', 'page_vlink', '12'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFCC00', 'page_back', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFCC00', 'page_text_em', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFCC00', 'stronger_back', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFD000', 'page_link', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFD040', 'page_vlink', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFF00', 'page_alink', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFF00', 'stronger_back', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFF30', 'strong_back', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFC0', 'strong_back', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFDF', 'page_back', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_back', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_back', '4'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_back', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_back', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_text', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_text', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_text_em', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_text_title', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'page_text_title', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'strong_text', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'strong_text', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'strong_text', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'stronger_text', '1'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'stronger_text', '2'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'stronger_text', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'stronger_text', '6'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'stronger_text', '7'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'weak_text', '3'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#FFFFFF', 'weak_text', '5'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#b93b8f', 'page_back', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#b93b8f', 'stronger_text', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#c38ec7', 'strong_back', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#cc33ff', 'page_alink', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#cc33ff', 'page_vlink', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#d0d0d0', 'page_text_em', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#e6a9ec', 'page_text_title', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#e6a9ec', 'page_vlink', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#eafeff', 'page_back', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#f9b7ff', 'page_alink', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#f9b7ff', 'page_text', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#f9b7ff', 'stronger_back', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('#f9b7ff', 'weak_text', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('Black', 'page_text', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('Black', 'page_text_em', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('Black', 'stronger_text', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('Red', 'page_link', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('White', 'strong_text', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('White', 'stronger_back', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('White', 'weak_text', '11'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'page_back', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'page_text', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'page_text', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'page_text_title', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'stronger_back', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'stronger_text', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('black', 'weak_text', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('blue', 'page_alink', '8'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('blue', 'page_text_em', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('green', 'page_alink', '9'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('white', 'page_back', '13'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('white', 'page_link', '10'); +REPLACE INTO themedata (color, coltype, themeid) VALUES ('white', 'strong_back', '13'); +REPLACE INTO themelist (name, themeid) VALUES ('Black on White w/ light grays', '4'); +REPLACE INTO themelist (name, themeid) VALUES ('Blues', '11'); +REPLACE INTO themelist (name, themeid) VALUES ('Bumblebee', '3'); +REPLACE INTO themelist (name, themeid) VALUES ('Foresty Nature Kinda', '8'); +REPLACE INTO themelist (name, themeid) VALUES ('Leprechaun', '7'); +REPLACE INTO themelist (name, themeid) VALUES ('MysticBlue', '12'); +REPLACE INTO themelist (name, themeid) VALUES ('Pink & Gray', '10'); +REPLACE INTO themelist (name, themeid) VALUES ('Soft Blues and White (Classic)', '1'); +REPLACE INTO themelist (name, themeid) VALUES ('Supernova', '9'); +REPLACE INTO themelist (name, themeid) VALUES ('Valentine\'s Day', '6'); +REPLACE INTO themelist (name, themeid) VALUES ('Watermelon', '13'); +REPLACE INTO themelist (name, themeid) VALUES ('White on Black w/ dark grays', '5'); +REPLACE INTO themelist (name, themeid) VALUES ('Yellow/Green Pastels', '2'); +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'AOL IM ScreenName', '1', '1', 'aolim', 'AOL Instant Messanger', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='AOL IM ScreenName',indexed='1',multihomed='1',prettyname='AOL Instant Messanger',scope='general' WHERE name='aolim'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'num', 'The ID of the blob cluster user\'s media resides on.', '1', '0', 'blob_clusterid', 'Blob Cluster ID', 'general'); +UPDATE userproplist SET cldversion='0',datatype='num',des='The ID of the blob cluster user\'s media resides on.',indexed='1',multihomed='0',prettyname='Blob Cluster ID',scope='general' WHERE name='blob_clusterid'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'LJ lang code in ml_langs', '1', '0', 'browselang', 'Language to browse with', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='LJ lang code in ml_langs',indexed='1',multihomed='0',prettyname='Language to browse with',scope='general' WHERE name='browselang'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'City lived in.', '1', '0', 'city', 'City', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='City lived in.',indexed='1',multihomed='0',prettyname='City',scope='general' WHERE name='city'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', '2 letter country code', '1', '0', 'country', 'Country', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='2 letter country code',indexed='1',multihomed='0',prettyname='Country',scope='general' WHERE name='country'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Used for large communities to prevent loading and displaying the complete list of members', '0', '0', 'dont_load_members', 'Don\'t load membership information', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Used for large communities to prevent loading and displaying the complete list of members',indexed='0',multihomed='0',prettyname='Don\'t load membership information',scope='general' WHERE name='dont_load_members'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'On each postevent, the dupsig is checked and updated to prevent accidental duplicate posts', '0', '0', 'dupsig_post', 'Duplicate signature for last post', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='On each postevent, the dupsig is checked and updated to prevent accidental duplicate posts',indexed='0',multihomed='0',prettyname='Duplicate signature for last post',scope='general' WHERE name='dupsig_post'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Comma separated list of email addresses allowed to send mail via gateway', '0', '0', 'emailpost_allowfrom', 'Allowed addresses to post via email', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Comma separated list of email addresses allowed to send mail via gateway',indexed='0',multihomed='0',prettyname='Allowed addresses to post via email',scope='general' WHERE name='emailpost_allowfrom'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Numeric or alpha PIN used for posting via email gateway', '0', '0', 'emailpost_pin', 'PIN for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Numeric or alpha PIN used for posting via email gateway',indexed='0',multihomed='0',prettyname='PIN for email posting',scope='general' WHERE name='emailpost_pin'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Location of External FOAF file', '0', '0', 'external_foaf_url', 'FOAF address', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Location of External FOAF file',indexed='0',multihomed='0',prettyname='FOAF address',scope='general' WHERE name='external_foaf_url'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Base Title of Friends Page', '0', '0', 'friendspagetitle', 'Friends Page Title', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Base Title of Friends Page',indexed='0',multihomed='0',prettyname='Friends Page Title',scope='general' WHERE name='friendspagetitle'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'M: male, F: female, U: unspecified', '1', '0', 'gender', 'Gender', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='M: male, F: female, U: unspecified',indexed='1',multihomed='0',prettyname='Gender',scope='general' WHERE name='gender'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'How the user heard about LiveJournal', '0', '0', 'howhear', 'How heard about LiveJouranl', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='How the user heard about LiveJournal',indexed='0',multihomed='0',prettyname='How heard about LiveJouranl',scope='general' WHERE name='howhear'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'ICQ Number', '1', '1', 'icq', 'ICQ', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='ICQ Number',indexed='1',multihomed='1',prettyname='ICQ',scope='general' WHERE name='icq'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'blobchar', 'Packed blob of a user\'s interest ids (4 bytes per id)', '1', '0', 'interest_ids_blob', 'Interest IDs blob', 'general'); +UPDATE userproplist SET cldversion='4',datatype='blobchar',des='Packed blob of a user\'s interest ids (4 bytes per id)',indexed='1',multihomed='0',prettyname='Interest IDs blob',scope='general' WHERE name='interest_ids_blob'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Jabber address (username@server)', '1', '1', 'jabber', 'Jabber Address', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Jabber address (username@server)',indexed='1',multihomed='1',prettyname='Jabber Address',scope='general' WHERE name='jabber'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Domain which will load user\'s journal', '0', '0', 'journaldomain', 'Domain Alias', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Domain which will load user\'s journal',indexed='0',multihomed='0',prettyname='Domain Alias',scope='general' WHERE name='journaldomain'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Subtitle of Journal', '0', '0', 'journalsubtitle', 'Journal Subtitle', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Subtitle of Journal',indexed='0',multihomed='0',prettyname='Journal Subtitle',scope='general' WHERE name='journalsubtitle'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Base Title of Journal', '0', '0', 'journaltitle', 'Journal Title', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Base Title of Journal',indexed='0',multihomed='0',prettyname='Journal Title',scope='general' WHERE name='journaltitle'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Comma separated: Unix time user agreed to the Terms of Service, revision number', '0', '1', 'legal_tosagree', 'Agreed to Terms of Service', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Comma separated: Unix time user agreed to the Terms of Service, revision number',indexed='0',multihomed='1',prettyname='Agreed to Terms of Service',scope='general' WHERE name='legal_tosagree'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'Encoding in which to mail comments to the user. Defaults to UTF-8.', '0', '0', 'mailencoding', 'Mail Encoding', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='Encoding in which to mail comments to the user. Defaults to UTF-8.',indexed='0',multihomed='0',prettyname='Mail Encoding',scope='general' WHERE name='mailencoding'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: This community is moderated', '0', '0', 'moderated', 'Moderation status', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: This community is moderated',indexed='0',multihomed='0',prettyname='Moderation status',scope='general' WHERE name='moderated'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'MSN Username', '1', '1', 'msn', 'MSN Username', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='MSN Username',indexed='1',multihomed='1',prettyname='MSN Username',scope='general' WHERE name='msn'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Time (user-side) of the user\'s last entry in their personal journal', '0', '0', 'newesteventtime', 'Newest event time', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Time (user-side) of the user\'s last entry in their personal journal',indexed='0',multihomed='0',prettyname='Newest event time',scope='general' WHERE name='newesteventtime'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Minimal security for new events; values are: public, private or friends', '0', '0', 'newpost_minsecurity', 'Minimal Security', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Minimal security for new events; values are: public, private or friends',indexed='0',multihomed='0',prettyname='Minimal Security',scope='general' WHERE name='newpost_minsecurity'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'True if this community allows non-member posting access', '0', '0', 'nonmember_posting', 'Non-Member posting access', 'general'); +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'If true, mail to user\'s site email address isn\'t forwarded to their real address.', '0', '0', 'no_mail_alias', 'Disable site e-mail alias', 'local'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='If true, mail to user\'s site email address isn\'t forwarded to their real address.',indexed='0',multihomed='0',prettyname='Disable site e-mail alias',scope='local' WHERE name='no_mail_alias'; +UPDATE userproplist SET cldversion='4',datatype='bool',des='True if this community allows non-member posting access',indexed='0',multihomed='0',prettyname='Non-Member posting access',scope='general' WHERE name='nonmember_posting'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'bool', '0: don\'t get birthday reminder mail, 1: do get birthday reminder mail', '1', '0', 'opt_bdaymail', 'Get Birthday Reminders', 'general'); +UPDATE userproplist SET cldversion='0',datatype='bool',des='0: don\'t get birthday reminder mail, 1: do get birthday reminder mail',indexed='1',multihomed='0',prettyname='Get Birthday Reminders',scope='general' WHERE name='opt_bdaymail'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: don\'t allow robots, 0: do', '1', '0', 'opt_blockrobots', 'Block Robots & Spiders', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: don\'t allow robots, 0: do',indexed='1',multihomed='0',prettyname='Block Robots & Spiders',scope='general' WHERE name='opt_blockrobots'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Y = send email, else don\'t.', '0', '0', 'opt_comminvitemail', 'Get Emails for Community Invites', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Y = send email, else don\'t.',indexed='0',multihomed='0',prettyname='Get Emails for Community Invites',scope='general' WHERE name='opt_comminvitemail'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'N = send no email, D = send daily digest, else send email always.', '0', '0', 'opt_communityjoinemail', 'Get Emails for Join Requests', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='N = send no email, D = send daily digest, else send email always.',indexed='0',multihomed='0',prettyname='Get Emails for Join Requests',scope='general' WHERE name='opt_communityjoinemail'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', '1 = send poster comments they make, else don\'t.', '0', '0', 'opt_getselfemail', 'Get Emails for Comments You Make', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='1 = send poster comments they make, else don\'t.',indexed='0',multihomed='0',prettyname='Get Emails for Comments You Make',scope='general' WHERE name='opt_getselfemail'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '0: show friendofs, 1: hide friendofs', '0', '0', 'opt_hidefriendofs', 'Hide Friend-Of List', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='0: show friendofs, 1: hide friendofs',indexed='0',multihomed='0',prettyname='Hide Friend-Of List',scope='general' WHERE name='opt_hidefriendofs'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '0: show memberofs, 1: hide memberofs', '0', '0', 'opt_hidememberofs', 'Hide Member-Of and Posting Access List', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='0: show memberofs, 1: hide memberofs',indexed='0',multihomed='0',prettyname='Hide Member-Of and Posting Access List',scope='general' WHERE name='opt_hidememberofs'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'width|height: specifies maximum image size on a user\'s friends page. 0 for either field replaces all images.', '0', '0', 'opt_imagelinks', 'Use Placeholders on Your Friend\'s Page', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='width|height: specifies maximum image size on a user\'s friends page. 0 for either field replaces all images.',indexed='0',multihomed='0',prettyname='Use Placeholders on Your Friend\'s Page',scope='general' WHERE name='opt_imagelinks'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'LJCUT disabled in friends view', '1', '0', 'opt_ljcut_disable_friends', 'LJCUT disabled in friends view', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='LJCUT disabled in friends view',indexed='1',multihomed='0',prettyname='LJCUT disabled in friends view',scope='general' WHERE name='opt_ljcut_disable_friends'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'LJCUT disabled in lastn and day views', '1', '0', 'opt_ljcut_disable_lastn', 'LJCUT disabled in lastn and day views', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='LJCUT disabled in lastn and day views',indexed='1',multihomed='0',prettyname='LJCUT disabled in lastn and day views',scope='general' WHERE name='opt_ljcut_disable_lastn'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'N: No, S: some (anonymous), A: all', '1', '0', 'opt_logcommentips', 'Log Comment IPs', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='N: No, S: some (anonymous), A: all',indexed='1',multihomed='0',prettyname='Log Comment IPs',scope='general' WHERE name='opt_logcommentips'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', '', 'Maxium picture height to be shown in journal before being linkitized. 0: for no max', '1', '0', 'opt_maxpicheight', 'Max Picture Height', 'general'); +UPDATE userproplist SET cldversion='4',datatype='',des='Maxium picture height to be shown in journal before being linkitized. 0: for no max',indexed='1',multihomed='0',prettyname='Max Picture Height',scope='general' WHERE name='opt_maxpicheight'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', '', 'Maxium picture width to be shown in journal before being linkitized. 0: for no max', '1', '0', 'opt_maxpicwidth', 'Max Picture Width', 'general'); +UPDATE userproplist SET cldversion='4',datatype='',des='Maxium picture width to be shown in journal before being linkitized. 0: for no max',indexed='1',multihomed='0',prettyname='Max Picture Width',scope='general' WHERE name='opt_maxpicwidth'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', '', 'Maxium word length before forced word breaks. 0: for no max', '1', '0', 'opt_maxwordlength', 'Max Word Length', 'general'); +UPDATE userproplist SET cldversion='0',datatype='',des='Maxium word length before forced word breaks. 0: for no max',indexed='1',multihomed='0',prettyname='Max Word Length',scope='general' WHERE name='opt_maxwordlength'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Show number of comments in URL', '0', '0', 'opt_nctalklinks', 'Show number of comments in URL', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Show number of comments in URL',indexed='0',multihomed='0',prettyname='Show number of comments in URL',scope='general' WHERE name='opt_nctalklinks'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: do not send moderation emails, 0: default, send them', '0', '0', 'opt_nomodemail', 'No Moderation Email', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: do not send moderation emails, 0: default, send them',indexed='0',multihomed='0',prettyname='No Moderation Email',scope='general' WHERE name='opt_nomodemail'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: no forum icons shown, 0: default, show them', '1', '0', 'opt_notalkicons', 'No Forum Icons', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: no forum icons shown, 0: default, show them',indexed='1',multihomed='0',prettyname='No Forum Icons',scope='general' WHERE name='opt_notalkicons'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Boolean: 1 means show only mutual friends on your userinfo page, 0 (default) means to use the standard mode of showing everybody.', '1', '0', 'opt_showmutualfriends', 'Mutual Friends Display', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Boolean: 1 means show only mutual friends on your userinfo page, 0 (default) means to use the standard mode of showing everybody.',indexed='1',multihomed='0',prettyname='Mutual Friends Display',scope='general' WHERE name='opt_showmutualfriends'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Y: include links to topic directory, N: don\'t.', '1', '0', 'opt_showtopicstuff', 'Topic Directory Integration', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Y: include links to topic directory, N: don\'t.',indexed='1',multihomed='0',prettyname='Topic Directory Integration',scope='general' WHERE name='opt_showtopicstuff'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: use journal style when commenting on other journals from friends page', '0', '0', 'opt_stylemine', 'Style=Mine', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: use journal style when commenting on other journals from friends page',indexed='0',multihomed='0',prettyname='Style=Mine',scope='general' WHERE name='opt_stylemine'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'How much content to put into syndication (Atom/RSS) feeds; values are: title, summary, or friends', '', '', 'opt_synlevel', 'Syndication Level', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='How much content to put into syndication (Atom/RSS) feeds; values are: title, summary, or friends',indexed='',multihomed='',prettyname='Syndication Level',scope='general' WHERE name='opt_synlevel'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'User defined permissions for tags. Format of prop: "add,control". (Who can add tags, who can manage tags.) Format of both is one of "public","private","friends","group:N" where N is the group id.', '0', '0', 'opt_tagpermissions', 'User Tag Permissions', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='User defined permissions for tags. Format of prop: "add,control". (Who can add tags, who can manage tags.) Format of both is one of "public","private","friends","group:N" where N is the group id.',indexed='0',multihomed='0',prettyname='User Tag Permissions',scope='general' WHERE name='opt_tagpermisisons'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', '1: friends view uses shared pictures, 0: uses poster\'s picture', '1', '0', 'opt_usesharedpic', 'Use Shared Journal Pic', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='1: friends view uses shared pictures, 0: uses poster\'s picture',indexed='1',multihomed='0',prettyname='Use Shared Journal Pic',scope='general' WHERE name='opt_usesharedpic'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', '1: ping weblogs.com with updates', '0', '0', 'opt_weblogscom', 'Ping Weblogs.com', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='1: ping weblogs.com with updates',indexed='0',multihomed='0',prettyname='Ping Weblogs.com',scope='general' WHERE name='opt_weblogscom'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'N: none, A: actual, L: livejournal, B: both', '1', '0', 'opt_whatemailshow', 'Which email address to display', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='N: none, A: actual, L: livejournal, B: both',indexed='1',multihomed='0',prettyname='Which email address to display',scope='general' WHERE name='opt_whatemailshow'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Screen new comments: A=All, N=None, F=from non-Friends, R=from non-users', '0', '0', 'opt_whoscreened', 'Screening comments', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Screen new comments: A=All, N=None, F=from non-Friends, R=from non-users',indexed='0',multihomed='0',prettyname='Screening comments',scope='general' WHERE name='opt_whoscreened'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'blobchar', 'Public key used for email gateway signature verification', '0', '0', 'public_key', 'PGP or GPG public key', 'general'); +UPDATE userproplist SET cldversion='4',datatype='blobchar',des='Public key used for email gateway signature verification',indexed='0',multihomed='0',prettyname='PGP or GPG public key',scope='general' WHERE name='public_key'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Username of other journal to redirect to, if u.statusvis==\"R\"', '1', '0', 'renamedto', 'Redirect to other account', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Username of other journal to redirect to, if u.statusvis==\"R\"',indexed='1',multihomed='0',prettyname='Redirect to other account',scope='general' WHERE name='renamedto'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Keep track of syncitems lastupdate value & time for last two getevent+syncitems requests, checking for loops from broken clients.', '0', '0', 'rl_syncitems_getevents_loop', 'Prevent loops in syncitems getevents', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Keep track of syncitems lastupdate value & time for last two getevent+syncitems requests, checking for loops from broken clients.',indexed='0',multihomed='0',prettyname='Prevent loops in syncitems getevents',scope='general' WHERE name='rl_syncitems_getevents_loop'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Records the error message when RSS parsing fails', '0', '0', 'rssparseerror', 'Syndication Parse Error', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Records the error message when RSS parsing fails',indexed='0',multihomed='0',prettyname='Syndication Parse Error',scope='general' WHERE name='rssparseerror'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'The style ID# of the S1 style for the calendar view.', '0', '0', 's1_calendar_style', 'Calendar View StyleID', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='The style ID# of the S1 style for the calendar view.',indexed='0',multihomed='0',prettyname='Calendar View StyleID',scope='general' WHERE name='s1_calendar_style'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'The style ID# of the S1 style for the day view view.', '0', '0', 's1_day_style', 'Day View StyleID', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='The style ID# of the S1 style for the day view view.',indexed='0',multihomed='0',prettyname='Day View StyleID',scope='general' WHERE name='s1_day_style'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'The style ID# of the S1 style for the friends view page.', '0', '0', 's1_friends_style', 'Friends View StyleID', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='The style ID# of the S1 style for the friends view page.',indexed='0',multihomed='0',prettyname='Friends View StyleID',scope='general' WHERE name='s1_friends_style'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'The style ID# of the S1 style for the recent entries view.', '0', '0', 's1_lastn_style', 'Recent View StyleID', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='The style ID# of the S1 style for the recent entries view.',indexed='0',multihomed='0',prettyname='Recent View StyleID',scope='general' WHERE name='s1_lastn_style'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'S2 Styleid to use', '0', '0', 's2_style', 'S2 Style', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='S2 Styleid to use',indexed='0',multihomed='0',prettyname='S2 Style',scope='general' WHERE name='s2_style'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'BML scheme name', '0', '0', 'schemepref', 'BML Scheme Preference', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='BML scheme name',indexed='0',multihomed='0',prettyname='BML Scheme Preference',scope='general' WHERE name='schemepref'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Index to speed directory searches. Only present if opt_infoshow=Y', '1', '1', 'sidx_bdate', 'SearchIndex: Birthdate', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Index to speed directory searches. Only present if opt_infoshow=Y',indexed='1',multihomed='1',prettyname='SearchIndex: Birthdate',scope='general' WHERE name='sidx_bdate'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Index to speed directory searches. Format %2s-%s-%s (iso country code, state, city). Only present if opt_infoshow=Y', '1', '1', 'sidx_loc', 'SearchIndex: Location', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Index to speed directory searches. Format %2s-%s-%s (iso country code, state, city). Only present if opt_infoshow=Y',indexed='1',multihomed='1',prettyname='SearchIndex: Location',scope='general' WHERE name='sidx_loc'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', '2 letter state code, or full state name', '1', '0', 'state', 'State', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='2 letter state code, or full state name',indexed='1',multihomed='0',prettyname='State',scope='general' WHERE name='state'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', '\'1\' for S1 or \'2\' for S2. Undefined means site default.', '0', '0', 'stylesys', 'Style System to use', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='\'1\' for S1 or \'2\' for S2. Undefined means site default.',indexed='0',multihomed='0',prettyname='Style System to use',scope='general' WHERE name='stylesys'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Notes about underage status; Y: underage due to birthday; C: underage due to cookie.', '0', '0', 'underage_status', 'Underage Status', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Notes about underage status; Y: underage due to birthday; C: underage due to cookie.',indexed='0',multihomed='0',prettyname='Underage Status',scope='general' WHERE name='underage_status'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'URL of website', '0', '0', 'url', 'Website Address', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='URL of website',indexed='0',multihomed='0',prettyname='Website Address',scope='general' WHERE name='url'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Name of website', '0', '0', 'urlname', 'Website Name', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Name of website',indexed='0',multihomed='0',prettyname='Website Name',scope='general' WHERE name='urlname'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Yahoo ID', '1', '1', 'yahoo', 'Yahoo ID', 'general'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Yahoo ID',indexed='1',multihomed='1',prettyname='Yahoo ID',scope='general' WHERE name='yahoo'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', '5 digit zip code (if in US)', '1', '0', 'zip', 'ZIP code', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='5 digit zip code (if in US)',indexed='1',multihomed='0',prettyname='ZIP code',scope='general' WHERE name='zip'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Disable QuickReply', '0', '0', 'opt_no_quickreply', 'Disable QuickReply', 'general'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Disable QuickReply',indexed='0',multihomed='0',prettyname='Disable QuickReply',scope='general' WHERE name='opt_no_quickreply'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'Number of Public Fotobilder Pictures', '0', '0', 'fb_num_pubpics', 'Num FB Pics', 'general'); +UPDATE userproplist SET cldversion='4',datatype='num',des='Number of Public Fotobilder Pictures',indexed='0',multihomed='0',prettyname='Num FB Pics',scope='general' WHERE name='fb_num_pubpics'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default comment options for post-by-email entries', '', '', 'emailpost_comments', 'Comment options for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default comment options for post-by-email entries',indexed='',multihomed='',prettyname='Comment options for email posting',scope='general' WHERE name='emailpost_comments'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default gallery name for post-by-email pictures', '', '', 'emailpost_gallery', 'Gallery name for email imgs', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default gallery name for post-by-email pictures',indexed='',multihomed='',prettyname='Gallery name for email imgs',scope='general' WHERE name='emailpost_gallery'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default image cut type for post-by-email images', '', '', 'emailpost_imgcut', 'Image cut type for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default image cut type for post-by-email images',indexed='',multihomed='',prettyname='Image cut type for email posting',scope='general' WHERE name='emailpost_imgcut'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default image layout for post-by-email images', '', '', 'emailpost_imglayout', 'Image layout for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default image layout for post-by-email images',indexed='',multihomed='',prettyname='Image layout for email posting',scope='general' WHERE name='emailpost_imglayout'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default security for post-by-email images', '', '', 'emailpost_imgsecurity', 'Image security for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default security for post-by-email images',indexed='',multihomed='',prettyname='Image security for email posting',scope='general' WHERE name='emailpost_imgsecurity'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default image size for post-by-email images', '', '', 'emailpost_imgsize', 'Image size for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default image size for post-by-email images',indexed='',multihomed='',prettyname='Image size for email posting',scope='general' WHERE name='emailpost_imgsize'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default security for post-by-email entries', '', '', 'emailpost_security', 'Entry security for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default security for post-by-email entries',indexed='',multihomed='',prettyname='Entry security for email posting',scope='general' WHERE name='emailpost_security'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Default userpic for post-by-email entries', '', '', 'emailpost_userpic', 'Userpic for email posting', 'general'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Default userpic for post-by-email entries',indexed='',multihomed='',prettyname='Userpic for email posting',scope='general' WHERE name='emailpost_userpic'; diff --git a/livejournal/bin/upgrading/blobify_userpics.pl b/livejournal/bin/upgrading/blobify_userpics.pl new file mode 100755 index 0000000..eacac8b --- /dev/null +++ b/livejournal/bin/upgrading/blobify_userpics.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use strict; +use Getopt::Long; + +# load libraries now +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJ::Blob; +use Image::Size (); +require "ljlib.pl"; + +my $opt_fast; +exit 1 unless + GetOptions("fast" => \$opt_fast, + ); + +my $clusterid = shift; +die "Usage: blobify_userpics.pl \n" + unless $clusterid; + +my $db = LJ::get_cluster_master($clusterid); +die "Invalid/down cluster: $clusterid\n" unless $db; + +print "Getting count.\n"; +my $total = $db->selectrow_array("SELECT COUNT(*) FROM userpicblob2"); +my $done = 0; + +my $loop = 1; +while ($loop) { + $loop = 0; + LJ::start_request(); # shrink caches + print "Getting 200.\n"; + my $sth = $db->prepare("SELECT userid, picid, imagedata FROM userpicblob2 LIMIT 200"); + $sth->execute; + while (my ($uid, $picid, $image) = $sth->fetchrow_array) { + $loop = 1; + my $u = LJ::load_userid($uid); + die "Can't find userid: $uid" unless $u; + + # sometimes expunges don't expunge all the way. + if ($u->{'statusvis'} eq "X") { + $db->do("DELETE FROM userpicblob2 WHERE userid=$uid AND picid=$picid"); + next; + } + + my ($sx, $sy, $fmt) = Image::Size::imgsize(\$image); + die "Unknown format" unless $fmt eq "GIF" || $fmt eq "JPG" || $fmt eq "PNG"; + $fmt = lc($fmt); + + my $err; + my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $image, \$err); + die "Error putting file: $u->{'user'}/$picid\n" unless $rv; + + unless ($opt_fast) { + # extra paranoid! + my $get = LJ::Blob::get($u, "userpic", $fmt, $picid); + die "Re-fetch didn't match" unless $get eq $image; + } + + $db->do("DELETE FROM userpicblob2 WHERE userid=$uid AND picid=$picid"); + + $done++; + printf " Moved $uid/$picid.$fmt ($done/$total = %.2f%%)\n", ($done / $total * 100); + } +} + +my $end_ct = $db->selectrow_array("SELECT COUNT(*) FROM userpicblob2"); +if ($end_ct == 0) { + $db->do("TRUNCATE TABLE userpicblob2"); +} +print "Done.\n"; + diff --git a/livejournal/bin/upgrading/compress_cluster.pl b/livejournal/bin/upgrading/compress_cluster.pl new file mode 100755 index 0000000..252630f --- /dev/null +++ b/livejournal/bin/upgrading/compress_cluster.pl @@ -0,0 +1,77 @@ +#!/usr/bin/perl + +use strict; + +my $clusterid = shift; +die "Usage: compress_cluster \n" + unless $clusterid; + +# load libraries now +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +# force this option on, since that's the point of the tool +$LJ::COMPRESS_TEXT = 1; + +my $db = LJ::get_cluster_master($clusterid); +die "Invalid/down cluster: $clusterid\n" unless $db; + +# table, column, [ prikey1, prikey2 ] +foreach my $t (['logtext2', 'event', ['journalid', 'jitemid']], + ['talktext2', 'body', ['journalid', 'jtalkid']]) { + + my ($table, $col, $key) = @$t; + my ($pk1, $pk2) = @$key; # 2 sections of primary key + + my $total = $db->selectrow_array("SELECT COUNT(*) FROM $table"); + + print "Processing table: $table [$total total rows]\n"; + + $db->do("HANDLER $table OPEN"); + my $ct = 0; + my $modct = 0; + + my $bytes_pre; + my $bytes_post; + + my $stats = sub { + printf("%6.2f%% done (mod=%.2f%%, size=%.2f%%),\n", + ($ct / $total) * 100, + ($modct / $ct) * 100, + ($bytes_post / $bytes_pre) * 100); + }; + + my $loop = 1; + while ($loop) { + my $sth = $db->prepare("HANDLER $table READ `PRIMARY` NEXT LIMIT 100"); + $sth->execute; + $loop = 0; + + while (my $row = $sth->fetchrow_hashref) { + + $loop = 1; + # print status + $stats->() if (++$ct % 1000 == 0); + + # try to compress the text + my $orig_len = length($row->{$col}); + $bytes_pre += $orig_len; + my $new_text = LJ::text_compress($row->{$col}); + my $new_len = length($new_text); + $bytes_post += $new_len; + + # do nothing if the "compressed" and uncompressed sizes are the same + next if $new_text eq $row->{$col}; + + # update this row since it compressed + $db->do("UPDATE $table SET $col=? WHERE $pk1=? AND $pk2=? AND $col=?", + undef, $new_text, $row->{$pk1}, $row->{$pk2}, $row->{$col}); + + $modct++; + } + } + $stats->(); + + $db->do("HANDLER $table CLOSE"); + + print "$ct rows processed, $modct modified\n\n"; +} diff --git a/livejournal/bin/upgrading/d1d2-single.pl b/livejournal/bin/upgrading/d1d2-single.pl new file mode 100755 index 0000000..2010aea --- /dev/null +++ b/livejournal/bin/upgrading/d1d2-single.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +my $dbh = LJ::get_dbh("master"); + +my $user = shift @ARGV; +my $where = "dversion=1 LIMIT 1"; +if ($user) { + $where = "user=" . $dbh->quote($user); +} + +my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE $where"); +unless ($u) { + die "No users with dversion==1 to convert. Done.\n" unless $user; + die "User not found.\n"; +} + +die "User not dversion 1\n" unless $u->{'dversion'} == 1; + +my $dbch = LJ::get_cluster_master($u); +die "Can't connect to cluster master.\n" unless $dbch; + +print "$u->{'user'}:\n"; +my @pics = @{$dbh->selectcol_arrayref("SELECT picid FROM userpic WHERE ". + "userid=$u->{'userid'}")}; +foreach my $picid (@pics) { + print " $picid...\n"; + my $imagedata = $dbh->selectrow_array("SELECT imagedata FROM userpicblob ". + "WHERE picid=$picid"); + $imagedata = $dbh->quote($imagedata); + $dbch->do("REPLACE INTO userpicblob2 (userid, picid, imagedata) VALUES ". + "($u->{'userid'}, $picid, $imagedata)"); +} + +$dbh->do("UPDATE user SET dversion=2 WHERE userid=$u->{'userid'}"); +print "Done.\n"; + + diff --git a/livejournal/bin/upgrading/d4d5-global.pl b/livejournal/bin/upgrading/d4d5-global.pl new file mode 100755 index 0000000..c6d3b19 --- /dev/null +++ b/livejournal/bin/upgrading/d4d5-global.pl @@ -0,0 +1,320 @@ +#!/usr/bin/perl +# + +use strict; +$| = 1; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $BLOCK_MOVE = 5000; # user rows to get at a time before moving +my $BLOCK_INSERT = 25; # rows to insert at a time when moving users +my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move + +# used for keeping stats notes +my %stats = (); # { 'action' => { 'pass' => { 'stat' => 'value' } } } + +# rows come order by user, keep last username so we can avoid dups +my $lastuser; + +# what pass are we on? +my $pass; + +my $get_db_writer = sub { + return LJ::get_dbh({raw=>1}, "master"); +}; + +my $get_db_slow = sub { + return LJ::get_dbh({raw=>1}, "slow", "master"); +}; + +my $get_cluster_master = sub { + my $cid = shift; + return LJ::get_dbh({raw=>1}, "cluster$cid"); +}; + +# percentage complete +my $status = sub { + my ($ct, $tot, $units, $pass, $user) = @_; + my $len = length($tot); + + my $passtxt = $pass ? "[Pass: $pass] " : ''; + my $usertxt = $user ? " Moving user: $user" : ''; + return sprintf(" $passtxt\[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n", + ($ct / $tot) * 100, $ct, $tot); +}; + +my $header = sub { + my $size = 50; + return "\n" . + ("#" x $size) . "\n" . + "# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" . + ("#" x $size) . "\n\n"; +}; + +# mover function +my $move_user = sub { + my $user = shift; + + # if the current user is the same as the last, + # we have a duplicate so skip it + return 0 if $user eq $lastuser; + $lastuser = $user; + + my $u = LJ::load_user($user); + return 0 unless $u->{'dversion'} == 4; + + # update user count for this pass + $stats{'move'}->{$pass}->{'user_ct'}++; + + # print status + print $status->($stats{'move'}->{$pass}->{'ct'}, + $stats{'move'}->{$pass}->{'total'}, "rows", $pass, $user); + + # ignore expunged users + if ($u->{'statusvis'} eq "X") { + LJ::update_user($u, { 'dversion' => 5 }) + or die "error updating dversion"; + $u->{'dversion'} = 5; # update local copy in memory + return 1; + } + + # get a handle for every user to revalidate our connection? + my $dbh = $get_db_writer->() + or die "Can't connect to global master"; + my $dbslo = $get_db_slow->() + or die "Can't connect to global slow master"; + my $dbcm = $get_cluster_master->($u->{'clusterid'}) + or die "Can't connect to cluster master ($u->{'clusterid'})"; + + # be careful, we're moving data + foreach my $db ($dbh, $dbslo, $dbcm) { + $db->do("SET wait_timeout=28800"); + $db->{'RaiseError'} = 1; + } + + my @map = (['style' => 's1style', + qw(styleid userid styledes type formatdata is_public + is_embedded is_colorfree opt_cache has_ads lastupdate) ], + ['overrides' => 's1overrides', + qw(userid override) ] + ); + + # in moving, s1stylecache gets special cased because its + # name hasn't changed, only location. so if there is only + # one cluster, then there's no point in physically moving it + + if (@LJ::CLUSTERS > 1) { + push @map, ['s1stylecache' => 's1stylecache', + qw(styleid cleandate type opt_cache vars_stor vars_cleanver) ]; + } + + # user 'system' is a special case. if we encounter this user we'll swap $dbcm + # to secretly be a $dbh. because the 'system' user uses the clustered tables + # on the global dbs, the queries will still work, we just need to misdirect them + $dbcm = $dbh if $u->{'user'} eq 'system'; + + # styleids to delete since s1stylemap isn't keyed on user + my @delete_styleids = (); + + # update tables + foreach my $tableinf (@map) { + + # find src and dest table names + my $src_table = shift @$tableinf; + my $dest_table = shift @$tableinf; + + # if this is the style table, replace into stylemap here, + # so that if this process is killed, style and stylemap + # won't get too out of sync + my $do_stylemap = $src_table eq 'style' && $dest_table eq 's1style'; + + # find what columns this table has + my @cols = @$tableinf; + my $cols = join(",", @cols); + my $bind_row = "(" . join(",", map { "?" } @cols) . ")"; + + my (@bind, @vals); + my (@map_bind, @map_vals); + + # flush rows to destination table + my $flush = sub { + return unless @bind; + + # insert data + my $bind = join(",", @bind); + $dbcm->do("REPLACE INTO $dest_table ($cols) VALUES $bind", undef, @vals); + + # insert new styles into s1stylemap + if ($do_stylemap) { + my $map_bind = join(",", @map_bind); + $dbh->do("REPLACE INTO s1stylemap (styleid, userid) VALUES $map_bind", + undef, @map_vals); + } + + # reset values + @bind = (); + @vals = (); + }; + + # s1stylecache is the only table keyed on styleid, not user + my $where = "user=" . $dbh->quote($u->{'user'}); + if ($src_table eq "s1stylecache") { + my $ids = $dbh->selectcol_arrayref("SELECT styleid FROM style WHERE user=?", + undef, $u->{'user'}); + my $ids_in = join(",", map { $dbh->quote($_) } @$ids) || "0"; + $where = "styleid IN ($ids_in)"; + } + + # select from source table and build data for insert + my $sth = $dbh->prepare("SELECT * FROM $src_table WHERE $where"); + $sth->execute(); + while (my $row = $sth->fetchrow_hashref) { + + # so that when we look for userid later, it'll be there + $row->{'userid'} = $u->{'userid'}; + + # build data for insert + push @bind, $bind_row; + push @vals, $row->{$_} foreach @cols; + + # special case: insert new s1styles into s1stylemap + if ($do_stylemap) { + push @map_bind, "(?,?)"; + push @map_vals, ($row->{'styleid'}, $u->{'userid'}); + push @delete_styleids, $row->{'styleid'}; + } + + # increment the count for this pass, style or overrides + $stats{'move'}->{$pass}->{'ct'}++ + unless $src_table eq 's1stylecache'; + + # flush if we've reached our insert limit + $flush->() if @bind > $BLOCK_INSERT; + } + + $flush->(); + } + + # haven't died yet? everything is still going okay + + # update dversion + LJ::update_user($u, { 'dversion' => 5 }) + or die "error updating dversion"; + $u->{'dversion'} = 5; # update local copy in memory + + return 1; +}; + +my $dbh = $get_db_writer->(); +die "Could not connect to global master" unless $dbh; +$dbh->{'RaiseError'} = 1; +my $dbslo = $get_db_slow->(); +die "Could not connect to global slow master" unless $dbslo; +$dbslo->{'RaiseError'} = 1; + +my $ts = $dbslo->selectrow_hashref("SHOW TABLE STATUS LIKE 'overrides'"); +if ($ts->{'Type'} eq 'ISAM') { + die "This script isn't efficient with ISAM tables. Please convert to MyISAM with:\n" . + " mysql> ALTER TABLE overrides TYPE=MyISAM;\n\n" . + "Then re-run this script.\n"; +} + +print $header->("Moving user data"); + +# first pass should get everything, second pass will +# get changes made during the first +foreach my $p (1..2) { + + # this is strange. perl bug? + $pass = $p; + + # get totals from overrides and style so we can do a percentage bar + # there will be overlaps in this when users have both styles and + # overrides, but we'll fix those up as we go + foreach (qw(style overrides)) { + $stats{'move'}->{$pass}->{'total'} += $dbslo->selectrow_array("SELECT COUNT(*) FROM $_"); + } + + print "Processing $stats{'move'}->{$p}->{'total'} total rows\n"; + + # 2 passes, so we catch people with styles & overrides, + # styles w/o overrides, and overrides w/o styles + foreach my $table (qw(style overrides)) { + + $lastuser = ''; + + # loop until we have no more users to convert + my $ct; + do { + + # get blocks of $BLOCK_MOVE users at a time + my $sth = $dbslo->prepare("SELECT user FROM $table WHERE user>? " . + "ORDER BY user LIMIT $BLOCK_MOVE"); + $sth->execute($lastuser); + $ct = 0; + while (my $user = $sth->fetchrow_array) { + $move_user->($user); + $ct++; + } + + } while $ct; + } + + print $stats{'move'}->{$p}->{'user_ct'}+0 . " users moved\n\n"; +} + +# now we're confident that all users have had their data moved if +# necessary, so we can just unconditionally change dversions. + +print $header->("Updating remaining users"); + +$stats{'update'}->{'total'} = $dbslo->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=4"); +print "Converting $stats{'update'}->{'total'} users\n"; + +# now update dversions for users who had no data to move +if ($stats{'update'}->{'total'}) { + + my $get_users = sub { + my $sth = $dbslo->prepare("SELECT userid, user FROM user " . + "WHERE dversion=4 LIMIT $BLOCK_UPDATE"); + $sth->execute(); + my @rows; # [ userid, user ] + while ( my ($userid, $user) = $sth->fetchrow_array) { + push @rows, [ $userid, $user ]; + } + return @rows; + }; + + while (my @rows = $get_users->()) { + + # update database + my $bind = join(",", map { "?" } @rows); + my @vals = map { $_->[0] } @rows; + $dbh->do("UPDATE user SET dversion=5 WHERE userid IN ($bind)", + undef, @vals); + + # update memcache + foreach (@rows) { + LJ::MemCache::delete([$_->[0], "userid:" . $_->[0]]); + LJ::MemCache::delete([$_->[1], "user:" . $_->[1]]); + } + $stats{'update'}->{'ct'} += @rows; + + print $status->($stats{'update'}->{'ct'}, $stats{'update'}->{'total'}, "users"); + } +} + +my $zeropad = sub { + return sprintf("%d", $_[0]); +}; + +# calculate total move stats +foreach (1..2) { + $stats{'move'}->{'total_ct'} += $stats{'move'}->{$_}->{'ct'}; + $stats{'move'}->{'total_user_ct'} += $stats{'move'}->{$_}->{'user_ct'}; +} + +print $header->("Dversion 4->5 conversion completed"); +print " Rows moved: " . $zeropad->($stats{'move'}->{'total_ct'}) . "\n"; +print " Users moved: " . $zeropad->($stats{'move'}->{'total_user_ct'}) . "\n"; +print "Users updated: " . $zeropad->($stats{'update'}->{'ct'}) . "\n\n"; diff --git a/livejournal/bin/upgrading/d5d6-mkf.pl b/livejournal/bin/upgrading/d5d6-mkf.pl new file mode 100755 index 0000000..9ae8c62 --- /dev/null +++ b/livejournal/bin/upgrading/d5d6-mkf.pl @@ -0,0 +1,349 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; +$| = 1; + +use lib ("$ENV{LJHOME}/cgi-bin"); +require "ljlib.pl"; +use LJ::User; + +use constant DEBUG => 0; # turn on for debugging (mostly db handle crap) + +my $BLOCK_MOVE = 5000; # user rows to get at a time before moving +my $BLOCK_INSERT = 25; # rows to insert at a time when moving users +my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move + +# get options +my %opts; +exit 1 unless + GetOptions("lock=s" => \$opts{locktype},); + +# if no locking, notify them about it +die "ERROR: Lock must be of types 'ddlockd' or 'none'\n" + if $opts{locktype} && $opts{locktype} !~ m/^(?:ddlockd|none)$/; + +# used for keeping stats notes +my %stats = (); # { 'stat' => 'value' } + +my %handle; + +# database handle retrieval sub +my $get_db_handles = sub { + # figure out what cluster to load + my $cid = shift(@_) + 0; + + my $dbh = $handle{0}; + unless ($dbh) { + $dbh = $handle{0} = LJ::get_dbh({ raw => 1 }, "master"); + print "Connecting to master ($dbh)...\n"; + eval { + $dbh->do("SET wait_timeout=28800"); + }; + $dbh->{'RaiseError'} = 1; + } + + my $dbcm; + $dbcm = $handle{$cid} if $cid; + if ($cid && ! $dbcm) { + $dbcm = $handle{$cid} = LJ::get_cluster_master({ raw => 1 }, $cid); + print "Connecting to cluster $cid ($dbcm)...\n"; + return undef unless $dbcm; + eval { + $dbcm->do("SET wait_timeout=28800"); + }; + $dbcm->{'RaiseError'} = 1; + } + + # return one or both, depending on what they wanted + return $cid ? ($dbh, $dbcm) : $dbh; +}; + +# percentage complete +my $status = sub { + my ($ct, $tot, $units, $user) = @_; + my $len = length($tot); + + my $usertxt = $user ? " Moving user: $user" : ''; + return sprintf(" \[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n", + ($ct / $tot) * 100, $ct, $tot); +}; + +my $header = sub { + my $size = 50; + return "\n" . + ("#" x $size) . "\n" . + "# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" . + ("#" x $size) . "\n\n"; +}; + +my $zeropad = sub { + return sprintf("%d", $_[0]); +}; + +# mover function +my $move_user = sub { + my $u = shift; + + # make sure our user is of the proper dversion + return 0 unless $u->{'dversion'} == 5; + + # at this point, try to get a lock for this user + my $lock; + if ($opts{locktype} eq 'ddlockd') { + $lock = LJ::locker()->trylock("d5d6-$u->{user}"); + return 1 unless $lock; + } + + # get a handle for every user to revalidate our connection? + my ($dbh, $dbcm) = $get_db_handles->($u->{clusterid}); + return 0 unless $dbh; + + if ($dbcm) { + # assign this dbcm to the user + $u->set_dbcm($dbcm) + or die "unable to set database for $u->{user}: dbcm=$dbcm\n"; + } + + # verify dversion hasn't changed on us (done by another job?) + my $dversion = $dbh->selectrow_array("SELECT dversion FROM user WHERE userid = $u->{userid}"); + return 1 unless $dversion == 5; + + # ignore expunged users + if ($u->{'statusvis'} eq "X" || $u->{'clusterid'} == 0) { + LJ::update_user($u, { dversion => 6 }) + or die "error updating dversion"; + $u->{dversion} = 6; # update local copy in memory + return 1; + } + + return 0 unless $dbcm; + + # step 1: get all friend groups and move those. safe to just grab with no limit because + # there are limits to how many friend groups you can have (30). + my $rows = $dbh->selectall_arrayref('SELECT groupnum, groupname, sortorder, is_public ' . + 'FROM friendgroup WHERE userid = ?', undef, $u->{userid}); + if (@$rows) { + # got some rows, create an update statement + my (@bind, @vars); + foreach my $row (@$rows) { + push @bind, "($u->{userid}, ?, ?, ?, ?)"; + push @vars, $_ foreach @$row; + } + my $bind = join ',', @bind; + eval { + $u->do("INSERT INTO friendgroup2 (userid, groupnum, groupname, sortorder, is_public) " . + "VALUES $bind", undef, @vars); + }; + } + + # general purpose flusher for use below + my (@bind, @vars); + my $flush = sub { + return unless @bind; + my ($table, $cols) = @_; + + # insert data into cluster master + my $bind = join(",", @bind); + $u->do("REPLACE INTO $table ($cols) VALUES $bind", undef, @vars); + die "error in flush $table: " . $u->errstr . "\n" if $u->err; + + # reset values + @bind = (); + @vars = (); + }; + + # step 1.5: see if the user has any data already? clear it if so. + my $counter = $dbcm->selectrow_array("SELECT max FROM counter WHERE journalid = ? AND area = 'R'", + undef, $u->{userid}); + $counter += 0; + if ($counter > 0) { + # yep, so we need to delete stuff, real data first + foreach my $table (qw(memorable2 memkeyword2 userkeywords)) { + $u->do("DELETE FROM $table WHERE userid = ?", undef, $u->{userid}); + die "error in clear: " . $u->errstr . "\n" if $u->err; + } + + # delete counters used (including memcache of such) + $u->do("DELETE FROM counter WHERE journalid = ? AND area IN ('R', 'K')", undef, $u->{userid}); + die "error in clear: " . $u->errstr . "\n" if $u->err; + LJ::MemCache::delete([$u->{userid}, "auc:$u->{userid}:R"]); + LJ::MemCache::delete([$u->{userid}, "auc:$u->{userid}:K"]); + } + + # step 2: get all of their memories and move them, creating the oldmemid -> newmemid mapping + # that we can use in later steps to migrate keywords + my %bindings; # ( oldid => newid ) + my $sth = $dbh->prepare('SELECT memid, journalid, jitemid, des, security ' . + 'FROM memorable WHERE userid = ?'); + $sth->execute($u->{userid}); + while (my $row = $sth->fetchrow_hashref()) { + # got a row, good + my $newid = LJ::alloc_user_counter($u, 'R'); + die "Error: unable to allocate type 'R' counter for $u->{user}($u->{userid})\n" + unless $newid; + $bindings{$row->{memid}} = $newid; + + # push data + push @bind, "($u->{userid}, ?, ?, ?, ?, ?)"; + push @vars, ($newid, map { $row->{$_} } qw(journalid jitemid des security)); + + # flush if necessary + $flush->('memorable2', 'userid, memid, journalid, ditemid, des, security') + if @bind > $BLOCK_INSERT; + } + $flush->('memorable2', 'userid, memid, journalid, ditemid, des, security'); + + # step 3: get the list of keywords that these memories all use + my %kwmap; + if (%bindings) { + my $memids = join ',', map { $_+0 } keys %bindings; + my $rows = $dbh->selectall_arrayref("SELECT memid, kwid FROM memkeyword WHERE memid IN ($memids)"); + push @{$kwmap{$_->[1]}}, $_->[0] foreach @$rows; # kwid -> [ memid, memid, memid ... ] + } + + # step 4: get the actual keywords associated with these keyword ids + my %kwidmap; + if (%kwmap) { + my $kwids = join ',', map { $_+0 } keys %kwmap; + my $rows = $dbh->selectall_arrayref("SELECT kwid, keyword FROM keywords WHERE kwid IN ($kwids)"); + %kwidmap = map { $_->[0] => $_->[1] } @$rows; # kwid -> keyword + } + + # step 5: now migrate all keywords into userkeywords table + my %mappings; + while (my ($kwid, $keyword) = each %kwidmap) { + # reallocate counter + my $newkwid = LJ::alloc_user_counter($u, 'K'); + die "Error: unable to allocate type 'K' counter for $u->{user}($u->{userid})\n" + unless $newkwid; + $mappings{$kwid} = $newkwid; + + # push data + push @bind, "($u->{userid}, ?, ?)"; + push @vars, ($newkwid, $keyword); + + # flush if necessary + $flush->('userkeywords', 'userid, kwid, keyword') + if @bind > $BLOCK_INSERT; + } + $flush->('userkeywords', 'userid, kwid, keyword'); + + # step 6: now we have to do some mapping conversions and put new data into memkeyword2 table + while (my ($oldkwid, $oldmemids) = each %kwmap) { + foreach my $oldmemid (@$oldmemids) { + # get new data + my ($newkwid, $newmemid) = ($mappings{$oldkwid}, $bindings{$oldmemid}); + + # push data + push @bind, "($u->{userid}, ?, ?)"; + push @vars, ($newmemid, $newkwid); + + # flush? + $flush->('memkeyword2', 'userid, memid, kwid') + if @bind > $BLOCK_INSERT; + } + } + $flush->('memkeyword2', 'userid, memid, kwid'); + + # delete memcache keys that hold old data + LJ::MemCache::delete([$u->{userid}, "memkwid:$u->{userid}"]); + + # haven't died yet? everything is still going okay, so update dversion + LJ::update_user($u, { 'dversion' => 6 }) + or die "error updating dversion"; + $u->{'dversion'} = 6; # update local copy in memory + + return 1; +}; + +# get dbh handle +my $dbh = LJ::get_db_writer(); # just so we can get users... +die "Could not connect to global master" unless $dbh; + +# get user count +my $total = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion = 5"); +$stats{'total_users'} = $total+0; + +# print out header and total we're moving +print $header->("Moving user data"); +print "Processing $stats{'total_users'} total users with the old dversion\n"; + +# loop until we have no more users to convert +my $ct; +while (1) { + + # get blocks of $BLOCK_MOVE users at a time + my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion = 5 LIMIT $BLOCK_MOVE"); + $sth->execute(); + $ct = 0; + my %us; + + my %fast; # people to move fast + + while (my $u = $sth->fetchrow_hashref()) { + $us{$u->{userid}} = $u; + $ct++; + $fast{$u->{userid}} = 1; + } + + # jump out if we got nothing + last unless $ct; + + # now that we have %us, we can see who has data + my $ids = join ',', map { $_+0 } keys %us; + my $has_memorable = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM memorable WHERE userid IN ($ids)"); + my $has_fgroups = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM friendgroup WHERE userid IN ($ids)"); + my %uids = ( map { $_ => 1 } (@$has_memorable, @$has_fgroups) ); + + # these people actually have data to migrate; don't move them fast + delete $fast{$_} foreach keys %uids; + + # now see who we can do in a fast way + my @fast_ids = map { $_+0 } keys %fast; + if (@fast_ids) { + print "Converting ", scalar(@fast_ids), " users quickly...\n"; + # update stats for counting and print + $stats{'fast_moved'} += @fast_ids; + print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users"); + + # block update + LJ::update_user(\@fast_ids, { dversion => 6 }); + } + + my $slow_todo = scalar keys %uids; + print "Of $BLOCK_MOVE, $slow_todo have to be slow-converted...\n"; + my @ids = randlist(keys %uids); + foreach my $id (@ids) { + # this person has memories, move them the slow way + die "Userid $id in \$has_memorable, but not in \%us...fatal error\n" unless $us{$id}; + + # now move the user + bless $us{$id}, 'LJ::User'; + if ($move_user->($us{$id})) { + $stats{'slow_moved'}++; + print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users", $us{$id}{user}); + } + + } + +} + +# ...done? +print $header->("Dversion 5->6 conversion completed"); +print " Users moved: " . $zeropad->($stats{'slow_moved'}) . "\n"; +print "Users updated: " . $zeropad->($stats{'fast_moved'}) . "\n\n"; + +# helper function to randomize stuff +sub randlist +{ + my @rlist = @_; + my $size = scalar(@rlist); + + my $i; + for ($i=0; $i<$size; $i++) { + unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1); + } + return @rlist; +} diff --git a/livejournal/bin/upgrading/d6d7-userpics.pl b/livejournal/bin/upgrading/d6d7-userpics.pl new file mode 100755 index 0000000..2269dc8 --- /dev/null +++ b/livejournal/bin/upgrading/d6d7-userpics.pl @@ -0,0 +1,352 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; +$| = 1; + +use lib "$ENV{'LJHOME'}/cgi-bin/"; +require "ljlib.pl"; +use LJ::Blob; +use LJ::User; + +use constant DEBUG => 0; # turn on for debugging (mostly db handle crap) + +my $BLOCK_MOVE = 5000; # user rows to get at a time before moving +my $BLOCK_INSERT = 25; # rows to insert at a time when moving users +my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move + +# get options +my %opts; +exit 1 unless + GetOptions("lock=s" => \$opts{locktype}, + "user=s" => \$opts{user}, + "total=i" => \$opts{total},); + + +# if no locking, notify them about it +die "ERROR: Lock must be of types 'ddlockd' or 'none'\n" + if $opts{locktype} && $opts{locktype} !~ m/^(?:ddlockd|none)$/; + +# used for keeping stats notes +my %stats = (); # { 'stat' => 'value' } + +my %handle; + +# database handle retrieval sub +my $get_db_handles = sub { + # figure out what cluster to load + my $cid = shift(@_) + 0; + + my $dbh = $handle{0}; + unless ($dbh) { + $dbh = $handle{0} = LJ::get_dbh({ raw => 1 }, "master"); + print "Connecting to master ($dbh)...\n"; + eval { + $dbh->do("SET wait_timeout=28800"); + }; + $dbh->{'RaiseError'} = 1; + } + + my $dbcm; + $dbcm = $handle{$cid} if $cid; + if ($cid && ! $dbcm) { + $dbcm = $handle{$cid} = LJ::get_cluster_master({ raw => 1 }, $cid); + print "Connecting to cluster $cid ($dbcm)...\n"; + return undef unless $dbcm; + eval { + $dbcm->do("SET wait_timeout=28800"); + }; + $dbcm->{'RaiseError'} = 1; + } + + # return one or both, depending on what they wanted + return $cid ? ($dbh, $dbcm) : $dbh; +}; + +# percentage complete +my $status = sub { + my ($ct, $tot, $units, $user) = @_; + my $len = length($tot); + + my $usertxt = $user ? " Moving user: $user" : ''; + return sprintf(" \[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n", + ($ct / $tot) * 100, $ct, $tot); +}; + +my $header = sub { + my $size = 50; + return "\n" . + ("#" x $size) . "\n" . + "# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" . + ("#" x $size) . "\n\n"; +}; + +my $zeropad = sub { + return sprintf("%d", $_[0]); +}; + +# mover function +my $move_user = sub { + my $u = shift; + + # make sure our user is of the proper dversion + return 0 unless $u->{'dversion'} == 6; + + # at this point, try to get a lock for this user + my $lock; + if ($opts{locktype} eq 'ddlockd') { + $lock = LJ::locker()->trylock("d6d7-$u->{user}"); + return 1 unless $lock; + } + + # get a handle for every user to revalidate our connection? + my ($dbh, $dbcm) = $get_db_handles->($u->{clusterid}); + return 0 unless $dbh; + + # assign this dbcm to the user + if ($dbcm) { + $u->set_dbcm($dbcm) + or die "unable to set database for $u->{user}: dbcm=$dbcm\n"; + } + + # verify dversion hasn't changed on us (done by another job?) + my $dversion = $dbh->selectrow_array("SELECT dversion FROM user WHERE userid = $u->{userid}"); + return 1 unless $dversion == 6; + + # ignore expunged users + if ($u->{'statusvis'} eq "X" || $u->{'clusterid'} == 0) { + LJ::update_user($u, { dversion => 7 }) + or die "error updating dversion"; + $u->{dversion} = 7; # update local copy in memory + return 1; + } + + return 0 unless $dbcm; + + # step 0.5: delete all the bogus userblob rows for this user + # This is due to the auto_increment for the blobid overflowing + # and thus all entries recieving an id of max id for a mediumint. + # This is lame. + my $domainid = LJ::get_blob_domainid('userpic'); + $u->do("DELETE FROM userblob WHERE journalid=$u->{userid} AND domain=$domainid AND blobid>=16777216"); + die "error in delete: " . $u->errstr . "\n" if $u->err; + + # step 1: get all user pictures and move those. safe to just grab with no limit + # since users can only have a limited number of them + my $rows = $dbh->selectall_arrayref('SELECT picid, userid, contenttype, width, height, state, picdate, md5base64 ' . + 'FROM userpic WHERE userid = ?', undef, $u->{userid}) || []; + + if (@$rows) { + # got some rows, create an update statement + my (@bind, @vars, @blobids, @blobbind, @picinfo); + foreach my $row (@$rows) { + my $picid = $row->[0]; + push @bind, "(?, ?, ?, ?, ?, ?, ?, ?)"; + + $row->[2] = {'image/gif' => 'G', + 'image/jpeg' => 'J', + 'image/png' => 'P'}->{$row->[2]}; + push @vars, @$row; + + # [picid, fmt] + my $fmt = {'G' => 'gif', + 'J' => 'jpg', + 'P' => 'png'}->{$row->[2]}; + push @picinfo, [$picid, $fmt]; + + # picids + push @blobids, $picid; + push @blobbind, "?"; + } + + my $bind = join ',', @bind; + $u->do("REPLACE INTO userpic2 (picid, userid, fmt, width, height, state, picdate, md5base64) " . + "VALUES $bind", undef, @vars); + die "error in userpic2 replace: " . $u->errstr . "\n" if $u->err; + + # step 1.5: insert missing rows into the userblob table + my $blobbind = join ',', @blobbind; + my $blobrows = $dbcm->selectall_hashref("SELECT blobid FROM userblob WHERE journalid=$u->{userid} AND domain=$domainid " . + "AND blobid IN ($blobbind)", 'blobid', undef, @blobids) || {}; + + my (@insertbind, @insertvars); + foreach my $pic (@picinfo) { + my ($picid, $fmt) = @$pic; + unless ($blobrows->{$picid}) { + push @insertbind, "(?, ?, ?, ?)"; + + my $blob = LJ::Blob::get($u, "userpic", $fmt, $picid); + my $length = length($blob); + + push @insertvars, $u->{'userid'}, $domainid, $picid, $length; + } + } + if (@insertbind) { + my $insertbind = join ',', @insertbind; + $u->do("INSERT IGNORE INTO userblob (journalid, domain, blobid, length) " . + "VALUES $insertbind", undef, @insertvars); + die "error in userblob insert: " . $u->errstr . "\n" if $u->err; + } + } + + # general purpose flusher for use below + my (@bind, @vars); + my $flush = sub { + return unless @bind; + my ($table, $cols) = @_; + + # insert data into cluster master + my $bind = join(",", @bind); + $u->do("REPLACE INTO $table ($cols) VALUES $bind", undef, @vars); + die "error in flush $table: " . $u->errstr . "\n" if $u->err; + + # reset values + @bind = (); + @vars = (); + }; + + # step 2: get the mapping of all of their keywords + my $kwrows = $dbh->selectall_arrayref('SELECT picid, kwid FROM userpicmap WHERE userid=?', + undef, $u->{'userid'}); + my %kwmap; + if (@$kwrows) { + push @{$kwmap{$_->[1]}}, $_->[0] foreach @$kwrows; # kwid -> [ picid, picid, picid ... ] + } + + # step 3: get the actual keywords associated with these keyword ids + my %kwidmap; + if (%kwmap) { + my $kwids = join ',', map { $_+0 } keys %kwmap; + my $rows = $dbh->selectall_arrayref("SELECT kwid, keyword FROM keywords WHERE kwid IN ($kwids)"); + %kwidmap = map { $_->[0] => $_->[1] } @$rows; # kwid -> keyword + } + + # step 4: now migrate all keywords into userkeywords table + my %mappings; + while (my ($kwid, $keyword) = each %kwidmap) { + # reallocate counter + my $newkwid = LJ::get_keyword_id($u, $keyword); + die "Error: unable to get keyword id for $u->{user}($u->{userid}), keyword '$keyword'\n" + unless $newkwid; + $mappings{$kwid} = $newkwid; + } + + # step 5: now we have to do some mapping conversions and put new data into userpicmap2 table + while (my ($oldkwid, $picids) = each %kwmap) { + foreach my $picid (@$picids) { + # get new data + my $newkwid = $mappings{$oldkwid}; + + # push data + push @bind, "($u->{userid}, ?, ?)"; + push @vars, ($picid, $newkwid); + + # flush? + $flush->('userpicmap2', 'userid, picid, kwid') + if @bind > $BLOCK_INSERT; + } + } + $flush->('userpicmap2', 'userid, picid, kwid'); + + # delete memcache keys that hold old data + LJ::MemCache::delete([$u->{userid}, "upicinf:$u->{userid}"]); + + # haven't died yet? everything is still going okay, so update dversion + LJ::update_user($u, { 'dversion' => 7 }) + or die "error updating dversion"; + $u->{'dversion'} = 7; # update local copy in memory + + return 1; +}; + +# get dbh handle +my $dbh = LJ::get_db_writer(); # just so we can get users... +die "Could not connect to global master" unless $dbh; + +# get user count +my $total = $opts{total} || $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion = 6"); +$stats{'total_users'} = $total+0; + +# print out header and total we're moving +print $header->("Moving user data"); +print "Processing $stats{'total_users'} total users with the old dversion\n"; + +# loop until we have no more users to convert +my $ct; +while (1) { + # get users to move + my $sth; + if ($opts{user}) { + $sth = $dbh->prepare("SELECT * FROM user WHERE user = ? AND dversion = 6"); + $sth->execute($opts{user}); + } else { + $sth = $dbh->prepare("SELECT * FROM user WHERE dversion = 6 LIMIT $BLOCK_MOVE"); + $sth->execute(); + } + + # get blocks of $BLOCK_MOVE users at a time + $ct = 0; + my (%us, %fast); + while (my $u = $sth->fetchrow_hashref()) { + $us{$u->{userid}} = $u; + $fast{$u->{userid}} = 1; + $ct++; + } + + # jump out if we got nothing + last unless $ct; + + # now that we have %us, we can see who has data + my $ids = join ',', map { $_+0 } keys %us; + my $has_upics = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM userpic WHERE userid IN ($ids)"); + my %uids = ( map { $_ => 1 } (@$has_upics) ); + + # remove folks that have userpics from the fast list + delete $fast{$_} foreach keys %uids; + + # now see who we can do in a fast way + my @fast_ids = map { $_+0 } keys %fast; + if (@fast_ids) { + # update stats for counting and print + $stats{'fast_moved'} += @fast_ids; + print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users"); + + # block update + LJ::update_user(\@fast_ids, { dversion => 7 }); + } + + my $slow_todo = scalar keys %uids; + print "Of $BLOCK_MOVE, $slow_todo have to be slow-converted...\n"; + my @ids = randlist(keys %uids); + foreach my $id (@ids) { + # this person has userpics, move them the slow way + die "Userid $id in \$has_upics, but not in \%us...fatal error\n" unless $us{$id}; + + # now move the user + bless $us{$id}, 'LJ::User'; + if ($move_user->($us{$id})) { + $stats{'slow_moved'}++; + print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users", $us{$id}{user}); + } + } + +} + +# ...done? +print $header->("Dversion 6->7 conversion completed"); +print " Users moved: " . $zeropad->($stats{'slow_moved'}) . "\n"; +print "Users updated: " . $zeropad->($stats{'fast_moved'}) . "\n\n"; + +# helper function to randomize stuff +sub randlist +{ + my @rlist = @_; + my $size = scalar(@rlist); + + my $i; + for ($i=0; $i<$size; $i++) { + unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1); + } + return @rlist; +} diff --git a/livejournal/bin/upgrading/deadphrases.dat b/livejournal/bin/upgrading/deadphrases.dat new file mode 100755 index 0000000..9d425ca --- /dev/null +++ b/livejournal/bin/upgrading/deadphrases.dat @@ -0,0 +1,207 @@ +# these get removed if found by texttool.pl +# + +general /allpics.bml.edit +general /allpics.bml.nopics.text + +general /community/join.bml.label.authpost +general /community/join.bml.label.closedcomm + +general /community/manage.bml.actmembers +general /community/manage.bml.actsettings +general /community/manage.bml.commlist.actmoderate + +general /community/members.bml.manage + +general /community/search.bml.contasmember +general /community/search.bml.userlikes + +general /community/settings.bml.label.admconsole +general /community/settings.bml.manage + +general /create.bml.aolnotice.head +general /create.bml.aolnotice.text +general /create.bml.error.seebelow +general /create.bml.proceed.head +general /create.bml.proceed.text + +general /create.bml.tos.error +general /create.bml.tos.haveread +general /create.bml.tos.p1.2 + +general /editinfo.bml.allowshocontact.email.if_domainaddy +general /editinfo.bml.allowshowcontact.email.reason +general /editinfo.bml.newemail.body +general /editinfo.bml.settings.about +general /editinfo.bml.showsubjicons.about +general /editinfo.bml.showsubjicons.header +general /editinfo.bml.tm.about +general /editinfo.bml.topicdir.about +general /editinfo.bml.topicdir.header + +general /friends/edit.bml.btn.proceed +general /friends/edit.bml.edit.head +general /friends/edit.bml.edit.text + +general /editjournal.bml.enterlogin +general /editjournal.bml.lostinfo.head +general /editjournal.bml.lostinfo.text + +general /editjournal_do.bml.error.mustlogin +general /editjournal_do.bml.success.edit + +general /friends/editgroups.bml.login.header +general /friends/editgroups.bml.login.text + +general /interests.bml.findsim.account.notallowed +general /interests.bml.findsim.account.notloggedin +general /interests.bml.findsim.btn.find +general /interests.bml.findsim.head +general /interests.bml.findsim.simtouser +general /interests.bml.findsim.text +general /interests.bml.interests.findsim1 +general /interests.bml.interests.findsim2 + +general /login.bml.error.forgotpass +general /login.bml.error.noaccount + +general /manage/index.bml.information.setlang.about +general /manage/index.bml.information.setscheme.about + +general /modify.bml.btn.proceed +general /modify.bml.journalstatus.about +general /modify.bml.journalstatus.head +general /modify.bml.journalstatus.select.activated +general /modify.bml.journalstatus.select.deleted +general /modify.bml.journalstatus.select.head +general /modify.bml.journalstatus.select.suspended +general /modify.bml.lostinfo.head +general /modify.bml.lostinfo.text +general /modify.bml.modify.head +general /modify.bml.modify.text + +general /modify_do.bml.title + +general /multisearch.bml.region.text + +general /register.bml.new.body + +general /setlang.bml.select +general /setlang.bml.switch +general /setlang.bml.title + +general /setscheme.bml.current +general /setscheme.bml.default +general /setscheme.bml.noschemes +general /setscheme.bml.select +general /setscheme.bml.switch +general /setscheme.bml.title + +general /support/faqbrowse.bml.title + +general /talkpost.bml.label.picturetouse + +general /talkpost_do.bml.opt.spellcheck + +general /talkread.bml.pageofpages + +general /tools/memadd.bml.body.added.body + +general /update.bml.update.about +general /update.bml.login.success +general /update.bml.htmlokay + +general /uploadpic.bml.success.text +general /uploadpic.bml.btn.proceed +general /uploadpic.bml.error.badurl +general /uploadpic.bml.error.databasedown +general /uploadpic.bml.error.filetoolarge +general /uploadpic.bml.error.imagetoolarge +general /uploadpic.bml.error.invalidauth +general /uploadpic.bml.error.invalidimage +general /uploadpic.bml.error.toomanypics +general /uploadpic.bml.error.unknownmode +general /uploadpic.bml.error.urlerror +general /uploadpic.bml.fromfile +general /uploadpic.bml.fromfile.key +general /uploadpic.bml.fromurl +general /uploadpic.bml.fromurl.key +general /uploadpic.bml.header +general /uploadpic.bml.imagesize.by +general /uploadpic.bml.kilobytes +general /uploadpic.bml.makedefault +general /uploadpic.bml.makedefault.key +general /uploadpic.bml.restriction.fileformat +general /uploadpic.bml.restriction.filesize +general /uploadpic.bml.restriction.imagesize +general /uploadpic.bml.success.editpics +general /uploadpic.bml.success.header +general /uploadpic.bml.success.preview +general /uploadpic.bml.success.upload +general /uploadpic.bml.text +general /uploadpic.bml.title + +general /uploadpic_do.bml.error.urlerror +general uploadpic.error.toolarge + +general /userinfo.bml.canpost +general /userinfo.bml.closedmembership.body +general /userinfo.bml.fbpictures +general /userinfo.bml.label.viewlabel +general /userinfo.bml.openmembership.body +general /userinfo.bml.posthere +general /userinfo.bml.rpmembership.body +general /userinfo.bml.syn.lastnew + +general /register.bml.error.alreadyvalidated + +general /tools/memories.bml.entry +general /tools/memories.bml.entries + +general /create.bml.tos.p1 +general /create.bml.email.text +general /create.bml.email.note + +general /syn/index.bml.table.cost +general /syn/index.bml.quota.text +general /syn/index.bml.quota.your +general /syn/index.bml.quota.numbers +general /syn/index.bml.invalid.overquota +general /syn/index.bml.invalid.overquota.text +general /syn/index.bml.invalid.overquota.title +general /syn/index.bml.invalid.overquota.username +general /syn/index.bml.accounttype.notallowed +general /syn/index.bml.add.other.title +general /syn/index.bml.add.other.text +general /syn/index.bml.notused +general /userinfo.bml.syn.cost + +general bml.needlogin.body + +general /userinfo.bml.label.frsyndication + +general /syn/index.bml.invalid.address + +general /community/members.bml.key.name +general /community/members.bml.success.addusers + +general /userinfo.bml.label.totalfriends + +general /community/settings.bml.label.closedmemb + +general /talkscreen.bml.title + +general /community/members.bml.success.message + +general /community/transfer.bml.error.banned + +general /create.bml.age.check.question +general /create.bml.age.check.yes +general /create.bml.age.check2.question +general /create.bml.age.check2.yes +general /create.bml.age.head + +general /community/members.bml.reinvited +general /community/membres.bml.success.invited + +general /customize/index.bml.s1 diff --git a/livejournal/bin/upgrading/en.dat b/livejournal/bin/upgrading/en.dat new file mode 100755 index 0000000..24822b3 --- /dev/null +++ b/livejournal/bin/upgrading/en.dat @@ -0,0 +1,4676 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Change Status + +/accountstatus.bml.error.db=There has been a database error processing your request. + +/accountstatus.bml.error.invalid=Invalid status type + +/accountstatus.bml.error.nochange.expunged=This account has been purged from the system. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Cannot change journal status from suspended. + +/accountstatus.bml.header.success=Success + +/accountstatus.bml.journalstatus.about=If you want to delete or undelete your journal, this is where you do it. Once you delete your journal you have 30 days to undelete it, just in case you change your mind. After 30 days, the journal will be permanently deleted and there will be no way to recover it. + +/accountstatus.bml.journalstatus.head=Journal Activation Status + +/accountstatus.bml.journalstatus.select.activated=Activated + +/accountstatus.bml.journalstatus.select.deleted=Deleted + +/accountstatus.bml.journalstatus.select.head=Status: + +/accountstatus.bml.journalstatus.select.suspended=Suspended + +/accountstatus.bml.message.nochange=Your journal status has been left as [[statusvis]]. + +/accountstatus.bml.message.success=Your journal status has been successfully changed to [[statusvis]]. + +/accountstatus.bml.title=Account Status + +/allpics.bml.current=Current Pictures + +/allpics.bml.default=Default + +/allpics.bml.edit2=You may be interested in editing your picture keywords or uploading a new picture. + +/allpics.bml.error.noparam=You need to specify a user parameter. + +/allpics.bml.keywords=Keywords: + +/allpics.bml.nopics.text.other=This user has not uploaded any user pictures. + +/allpics.bml.nopics.text2=You have no pictures uploaded. To upload one, go here. + +/allpics.bml.nopics.title=No Pictures + +/allpics.bml.pics=Here are the user pictures for [[user]]. + +/allpics.bml.title=User Pictures + +/approve.bml.comm.success=Success + +/approve.bml.comm.text<< +You have been added to [[comm]]. +Click here to add the community to your friends list. +. + +/approve.bml.commjoin.text<< +You have approved the membership request of [[user]] in [[comm]]. +Click here to visit the member list for this community to set +other options for this user. +. + +/approve.bml.error.actionperformed=This action has already been performed + +/approve.bml.error.approving=There was an error approving this request to join. + +/approve.bml.error.internerr.invalidaction=Internal error: invalid action + +/approve.bml.error.invalidargument=Invalid argument given + +/approve.bml.error.unknownactiontype=Unknown action type + +/approve.bml.shared.success=Success + +/approve.bml.shared.text<< +You have been given posting access to [[shared]]. +Click here to add the shared journal to your friends list. +. + +/approve.bml.title=Action Approval + +/birthdays.bml.description=Below are the birthdays for everyone that you list as a friend. + +/birthdays.bml.description.others=Below are the birthdays for everyone that [[user]] lists as a friend. + +/birthdays.bml.error.badstatus=[[user]] is not a currently active account. + +/birthdays.bml.error.invaliduser=Invalid user: [[user]]. The specified account does not exist. + +/birthdays.bml.findothers=If you would like to see the birthdays of the friends of another user, or of the members of a community, enter a username below: + +/birthdays.bml.nobirthdays=There are no birthdays to display. This happens when a user doesn't have anyone added to their Friends list, or if none of the user's friends list their birthday publically. + +/birthdays.bml.title=Birthdays + +/birthdays.bml.view=View + +/changepassword.bml.btn.proceed=Proceed + +/changepassword.bml.changepassword.header=Change Password + +/changepassword.bml.changepassword.instructions=Fill out the form below to change your password. + +/changepassword.bml.email.body<< +Your password has been changed at [[sitename]]. + +To retrieve it in the future, visit: + + [[siteroot]]/lostinfo.bml + +Regards, +[[sitename]] Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Change of Password + +/changepassword.bml.error.badcheck=Bad new password: [[error]] + +/changepassword.bml.error.badnewpassword=Your new passwords do not match. Retype both again... you made a typo on one of them. + +/changepassword.bml.error.badoldpassword=Your old password is not correct. + +/changepassword.bml.error.blankpassword=Your new password cannot be blank. + +/changepassword.bml.error.changetestaccount=Cannot change the test account's password. + +/changepassword.bml.error.characterlimit=Passwords are limited to a maximum of 30 characters. + +/changepassword.bml.error.invaliduser=Invalid user [[user]]. This user does not exist. Are you sure you typed it correctly? + +/changepassword.bml.error.mustenterusername=You must enter your username. + +/changepassword.bml.error.nonascii=Passwords are restricted to ASCII symbols. Please choose a password that does not use non-ASCII symbols. + +/changepassword.bml.error.notvalidated=You cannot change your password if your current email address has not been validated. + +/changepassword.bml.newpassword=New Password: + +/changepassword.bml.newpasswordagain=New Password (again): + +/changepassword.bml.oldpassword=Old Password: + +/changepassword.bml.proceed.instructions=Press the button below and your password will be changed. You will receive an email as well, noting the password change. + +/changepassword.bml.relogin=In addition, you have been logged out from all your existing sessions. You should log in again before continuing. + +/changepassword.bml.success.text=Your password has been changed and email has been sent to you with a reminder message. + +/changepassword.bml.title=Change Password + +/community/create.bml.btn.create=Create Community + +/community/create.bml.btn.proceed=Proceed... + +/community/create.bml.create.text=Creating a new community is easy, just follow the instructions below. + +/community/create.bml.error.notactive=Your account must be active in order to create a community. Please make sure your account is not currently marked as deleted or suspended and try again. + +/community/create.bml.error.notperson=You must be logged in as a personal account to create a community. + +/community/create.bml.error.postrequired=POST required. + +/community/create.bml.error.username.inuse=Account name already in use; please select a different one. + +/community/create.bml.error.username.mustenter=You must enter an account name. + +/community/create.bml.error.username.reserved=Sorry, that is a reserved account name. + +/community/create.bml.errors.label=Please note the following problems and resubmit: + +/community/create.bml.name.head=Community Name + +/community/create.bml.name.text=What's the name of this community? This will appear at the top of the community, and in the user directory should you choose to list the community in it. + +/community/create.bml.person=Would you rather create a personal journal? + +/community/create.bml.success.btn.enterinfo=Enter Community Information + +/community/create.bml.success.head=Success! + +/community/create.bml.success.text1=Your community has been created. Additionally, your account has been made an administrator of it. + +/community/create.bml.success.text2=Your community will be available at: + +/community/create.bml.success.text3=Now, please take the time to fill in some information about the community. It's mostly optional, but it lets other users have an idea of what this community is for. + +/community/create.bml.title=Create New Community + +/community/create.bml.username.charsallowed=The community account name may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_). Additionally, it must not be longer than 15 characters. + +/community/create.bml.username.head=Account name + +/community/create.bml.username.text=Each [[sitename]] account must have their own unique account name. The account name is what appears in the address to the community. + +/community/index.bml.main<< + + + + + + +

Create a Community Now!

+. + +/community/index.bml.title=Community Center + +/community/join.bml.button.join=Join Community + +/community/join.bml.error.already.member=You are already a member of this community. + +/community/join.bml.error.closed=This community is closed to new members. If you wish to join, please contact one of the following maintainers: [[admins]] + +/community/join.bml.error.statusvis.body=The account you are logged in as is not an active account. + +/community/join.bml.error.statusvis.title=Unable to Join Communities + +/community/join.bml.label.addtofriends=Add "[[maintainer]]" to friends list.
+ +/community/join.bml.label.allowposting=This community allows posting by all members, so you now have access to post in it. If you already have a LiveJournal client open on your computer, you'll have to log out and log back in for this journal to show up in your list of journals you can post to. + +/community/join.bml.label.auth=Although you are now listed as a member, this community only allows posting by authorized users. Contact one of the maintainers if you desire posting access. Below is the list of maintainers for this community: [[admins]] + +/community/join.bml.label.banned=The maintainer(s) of this community have banned you from joining. + +/community/join.bml.label.closed=This community is closed. If you're interested in joining it, please contact one of its maintainers. Below is the list of maintainers for this community: [[admins]] + +/community/join.bml.label.commlogged=You're logged in as a shared/community account, not your personal account. + +/community/join.bml.label.errorcomminfo=The specified community information is not valid. + +/community/join.bml.label.expls=Press the button below to join the "[[maintainer]]" community. Uncheck the box below if you want to join the community without seeing community entries on your friends page. + +/community/join.bml.label.loginfirst=To join a community you must first log in. + +/community/join.bml.label.membernow=You are now a member of the [[commname]] Community + +/community/join.bml.label.sure=You sure? + +/community/join.bml.reqsubmitted.body=Your request to join has been submitted to the maintainers: + +/community/join.bml.reqsubmitted.title=Join Request Submitted + +/community/join.bml.request.body=The [[comm]] community does not have open membership. Please verify that you wish to join this community by clicking below. + +/community/join.bml.request.reason=Optionally, enter a reason you would like to join this community: + +/community/join.bml.request.title=Request to Join + +/community/join.bml.success=Success + +/community/join.bml.title=Join Community + +/community/leave.bml.button.leave=Leave Community + +/community/leave.bml.label.buttontoleave=Press the button below to leave the "[[commname]]" community. + +/community/leave.bml.label.infoerror=The specified community information is not valid. + +/community/leave.bml.label.lastmaintainer=You are not allowed to leave this community because you are the sole maintainer. If you wish to leave the community, please appoint another maintainer and then try leaving again. + +/community/leave.bml.label.logoutfirst=To leave a community you must first log in. + +/community/leave.bml.label.removed=You are now removed from the [[commname]] Community + +/community/leave.bml.label.removefromfriends=Also remove "[[user]]" from friends list. + +/community/leave.bml.success=Success + +/community/leave.bml.sure=You sure? + +/community/leave.bml.title=Leave Community + +/community/manage.bml.error.badaccounttype=You must be logged in as a regular user account in order to access this page. + +/community/manage.bml.commlist.actinfo=Info + +/community/manage.bml.commlist.actinvites=Invitations + +/community/manage.bml.commlist.actions=Actions + +/community/manage.bml.commlist.actmembers=[Members] + +/community/manage.bml.commlist.actmembers2=Members + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] pending + +/community/manage.bml.commlist.actsettings=[Settings] + +/community/manage.bml.commlist.actsettings2=Settings + +/community/manage.bml.commlist.header=Your communities + +/community/manage.bml.commlist.moderation=Awaiting Moderation + +/community/manage.bml.commlist.moderation.num=[[[num]] in queue] + +/community/manage.bml.commlist.none=You are not managing any communities. + +/community/manage.bml.commlist.text=Here are the communities that you manage or co-manage: + +/community/manage.bml.commlist.title=Title + +/community/manage.bml.commlist.username=Username + +/community/manage.bml.create.header=Create a community + +/community/manage.bml.create.text=You can also create a new community. + +/community/manage.bml.joinmail.body=For communities with closed memberships, you have several e-mail options: + +/community/manage.bml.joinmail.email.all=E-mail every time someone requests to join + +/community/manage.bml.joinmail.email.digest=One e-mail each day with a list of all pending requests + +/community/manage.bml.joinmail.email.none=No e-mail, I will use this page to look for new requests + +/community/manage.bml.joinmail.save=Save Settings + +/community/manage.bml.joinmail.title=Administrative options + +/community/manage.bml.modemail.body=For moderated communities, you can choose whether to send emails or not: + +/community/manage.bml.modemail.no=No email, I will manage the moderation queue manually + +/community/manage.bml.modemail.yes=Email me every time someone submits a post to the queue + +/community/manage.bml.title=Community Management + +/community/members.bml.error.adding=[[user]] has banned this community from sending them invitations. + +/community/members.bml.error.alreadyadded=[[user]] was not added because they already have access to this community. + +/community/members.bml.error.alreadysent=[[user]] could not be added because they were already sent a confirmation email on: [[datetime]]. Please wait for them to respond. + +/community/members.bml.error.invaliduser=Cannot add community or syndicated account: [[user]] + +/community/members.bml.error.limit=Unable to invite [[user]], the outstanding invitation limit for this community has been exceeded. + +/community/members.bml.error.noaccess=Only community maintainers are able to edit membership lists. You are not a maintainer of community [[comm]]. + +/community/members.bml.error.noattr=No attributes selected for user: [[user]] + +/community/members.bml.error.nocomm=Community not found. + +/community/members.bml.error.notactive=Account is not active: [[user]] + +/community/members.bml.error.nouser=User does not exist: [[user]] + +/community/members.bml.error.unknown=Error inviting [[user]]. Please make sure they're not already a member and try again. + +/community/members.bml.key.admin=Maintainer + +/community/members.bml.key.member=Member + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Posting Access + +/community/members.bml.key.preapprove=Unmoderated + +/community/members.bml.key.user=User + +/community/members.bml.manage2=Manage communities + +/community/members.bml.name=Community name: [[name]] + +/community/members.bml.nextlink=(Next page...) + +/community/members.bml.prevlink=(Previous page...) + +/community/members.bml.reinvited2=[[user]] has been reinvited to join this community. They will need to accept the invite from the Community Invitation Page. + +/community/members.bml.settings=[Settings] + +/community/members.bml.success.added=added: [[list]] + +/community/members.bml.success.deleted=removed: [[list]] + +/community/members.bml.success.header=Success + +/community/members.bml.success.invited2=The following users have been successfully invited to this community with the listed privileges. They will need to accept the invite from the Community Invitation Page before they can become a member of the community. + +/community/members.bml.success.message2=The following changes have been made: + +/community/members.bml.success.nochanges=No changes have been made. + +/community/members.bml.success.return=Return to the list + +/community/members.bml.title=Community Members + +/community/members.bml.update=Update settings + +/community/moderate.bml.approve.button=Yes, approve it + +/community/moderate.bml.approve.header=Approve this entry? + +/community/moderate.bml.approve.preapprove=Also, add user [[user]] to the list of pre-approved users for this community. + +/community/moderate.bml.approve.text=Are you sure you want to approve this entry? + +/community/moderate.bml.brlist.actions=Actions + +/community/moderate.bml.brlist.poster=Poster + +/community/moderate.bml.brlist.subject=Subject begins + +/community/moderate.bml.brlist.time=Time + +/community/moderate.bml.brlist.view=View + +/community/moderate.bml.browse.empty=The moderation queue is empty. + +/community/moderate.bml.browse.header=Moderate Community + +/community/moderate.bml.browse.text=Here is the moderation queue for the community [[link]] + +/community/moderate.bml.choice.approve=Approve + +/community/moderate.bml.choice.bkapprove=#82dd88 + +/community/moderate.bml.choice.bkreject=#e08291 + +/community/moderate.bml.choice.reject=Reject + +/community/moderate.bml.error.noaccess=You do not moderate the community [[comm]]. + +/community/moderate.bml.error.noentry=Entry not found (perhaps already handled by another moderator). + +/community/moderate.bml.error.nolist=You do not moderate any communities. + +/community/moderate.bml.error.notfound=Community account not found. + +/community/moderate.bml.manage=Manage communities + +/community/moderate.bml.moderate=Moderate this community + +/community/moderate.bml.modlist.actions=Actions + +/community/moderate.bml.modlist.actmodempty=[Moderate] + +/community/moderate.bml.modlist.actmoderate=Moderate + +/community/moderate.bml.modlist.count=Queue size + +/community/moderate.bml.modlist.header=Moderate Communities + +/community/moderate.bml.modlist.title=Title + +/community/moderate.bml.modlist.username=Username + +/community/moderate.bml.posted.appheader=Preapproved + +/community/moderate.bml.posted.apptext=Additionally, the user [[user]] has been added to the list of pre-approved users for this community. + +/community/moderate.bml.posted.header=Success + +/community/moderate.bml.posted.proterror=The entry has not been posted due to this protocol error: [[err]] + +/community/moderate.bml.posted.text=The entry has been successfully posted. + +/community/moderate.bml.reject.button=Yes, reject it + +/community/moderate.bml.reject.header=Reject this entry? + +/community/moderate.bml.reject.reason=You can also explain to the poster your reasons for rejecting their entry. They will be sent to the poster by email. + +/community/moderate.bml.reject.text=Are you sure you want to reject this entry? + +/community/moderate.bml.rejected.header=Rejected + +/community/moderate.bml.rejected.text=The entry has been rejected. + +/community/moderate.bml.title=Community Moderation + +/community/pending.bml.approve.title=Approve Membership? + +/community/pending.bml.no=No + +/community/pending.bml.nopending.body=There are no pending membership requests for this community. + +/community/pending.bml.nopending.title=Nobody Pending + +/community/pending.bml.success.added=You have added [[num]] [[?num|person|persons]] to this community. + +/community/pending.bml.success.ignored=[[num]] [[?num|request is|requests are]] still on file pending decisions. + +/community/pending.bml.success.previous=[[num]] [[?num|request has|requests have]] not been processed, as they were no longer pending. Another maintainer might have already processed [[?num|it|them]]. + +/community/pending.bml.success.rejected=You have rejected [[num]] [[?num|request|requests]] to join this community. + +/community/pending.bml.title=Pending Membership Requests + +/community/pending.bml.yes=Yes + +/community/search.bml.button.clear=Clear Form + +/community/search.bml.button.search=Search! + +/community/search.bml.checkbox.onlywithpics=Only communities with pictures + +/community/search.bml.label.byinterest=By Interest + +/community/search.bml.label.bylocation=By Location + +/community/search.bml.label.bytime=By Journal Update Time + +/community/search.bml.label.city=City: + +/community/search.bml.label.country=Country: + +/community/search.bml.label.displayoptions=Display Options + +/community/search.bml.label.hasmember=Has Member + +/community/search.bml.label.othercriteria=Other Criteria + +/community/search.bml.label.outputformat=Output Format: + +/community/search.bml.label.records=Records per page: + +/community/search.bml.label.searchcomm=Search Communities + +/community/search.bml.label.selecriteria=Select the criteria below that you'd like to find communities by. The results returned are the intersection of all search criteria. In other words, each checkbox you click means "AND", not "OR". + +/community/search.bml.label.sortmethod=Sorting Method: + +/community/search.bml.label.stateprovince=State/Province: + +/community/search.bml.label.updated=Updated in last + +/community/search.bml.sel.bypicture=By Picture + +/community/search.bml.sel.communityname=Community Name + +/community/search.bml.sel.commview=Community View + +/community/search.bml.sel.day=day + +/community/search.bml.sel.month=month + +/community/search.bml.sel.simple=Simple + +/community/search.bml.sel.updatetime=Update Time + +/community/search.bml.sel.username=User Name + +/community/search.bml.sel.week=week + +/community/search.bml.title=Community Search + +/community/sentinvites.bml.date=Date Sent + +/community/sentinvites.bml.key.date=Date + +/community/sentinvites.bml.key.sentby=Sent By + +/community/sentinvites.bml.key.status=Status + +/community/sentinvites.bml.none.body=No invites have been sent in the past 30 days. If you wish to invite people to this community, please visit the Members page. + +/community/sentinvites.bml.none.title=No Invites Found + +/community/sentinvites.bml.send=Send Invitations + +/community/sentinvites.bml.title=Sent Invitations + +/community/settings.bml.button.changecommunity=Update Settings + +/community/settings.bml.button.createcommunity=Create Community + +/community/settings.bml.error.alreadycomm=Account is already a community. + +/community/settings.bml.error.badpassword=Invalid community password + +/community/settings.bml.error.hasentries=This account already has entries and cannot be converted. + +/community/settings.bml.error.maintainertype=Maintainer account must be a person, not another shared account. + +/community/settings.bml.error.noaccess=Only community maintainers are able to edit community settings. You are not a maintainer of community [[comm]]. + +/community/settings.bml.error.notcomm=Not a community account. + +/community/settings.bml.error.notfound=Community account not found. + +/community/settings.bml.error.samenames=Maintainer account and community account cannot be the same. + +/community/settings.bml.label.anybodycan=All Members
Anybody can post immediately once a member. + +/community/settings.bml.label.changeheader=Change Community Settings + +/community/settings.bml.label.changetext=Here you can change the settings for the community you own or maintain. + +/community/settings.bml.label.closedmemb2=Closed Membership
Nobody can join the community. + +/community/settings.bml.label.commchanged=Your community settings have been changed. + +/community/settings.bml.label.commcreate=This is the account that you want to turn into a community. It must already be created, but should not already be in use by an individual, because after this, many different people will potentially be able to post in it. + +/community/settings.bml.label.commcreated=Your community is now set up. + +/community/settings.bml.label.commheader=Community Account + +/community/settings.bml.label.comminfo=Community info + +/community/settings.bml.label.commopts=Community Options + +/community/settings.bml.label.commsite=Community website + +/community/settings.bml.label.community=Community: + +/community/settings.bml.label.createheader=Create Community + +/community/settings.bml.label.createtext=From here you can create a community account. A community is a special type of account that other users can join and post in. For an example of a community, check out the Seattle Party Community. + +/community/settings.bml.label.howoperates=Choose how your community operates. You can change these later. + +/community/settings.bml.label.maintainer=Maintainer: + +/community/settings.bml.label.maintainer.login=If this is not the maintainer account, login as somebody else. + +/community/settings.bml.label.managepage=Community Management - to add members, grant posting access, appoint moderators, etc. + +/community/settings.bml.label.membership=Membership + +/community/settings.bml.label.moderatedmemb=Moderated Membership
Requests to join are emailed to you for approval. + +/community/settings.bml.label.modheader=Moderation + +/community/settings.bml.label.modis=Moderated
New entries must be approved by a moderator. + +/community/settings.bml.label.modisnt=Unmoderated
New entries appear immediately. + +/community/settings.bml.label.modtext=Are submissions to this community moderated? + +/community/settings.bml.label.nmcan=Non-Members Can Post
Users can post to this community without having to join it. + +/community/settings.bml.label.nmcant=Non-Members Cannot Post
Users have to join this community in order to post in it. + +/community/settings.bml.label.nmheader=Non-Member Posting + +/community/settings.bml.label.nmtext=Can users post to this community without having to join it? + +/community/settings.bml.label.openmemb=Open Membership
Anybody can join without getting approved. + +/community/settings.bml.label.password=Password: + +/community/settings.bml.label.postaccess=Posting Access + +/community/settings.bml.label.rellinks=Relevant links: + +/community/settings.bml.label.selcan=Select Members
Only some members are able to post, once they've been given access by the maintainer account. + +/community/settings.bml.label.username=Username: + +/community/settings.bml.label.whocanjoin=Who can join your community? + +/community/settings.bml.label.whocanpost=Who can post to this community? + +/community/settings.bml.manage2=Manage communities + +/community/settings.bml.members=[Members] + +/community/settings.bml.name=Community name: [[name]] + +/community/settings.bml.success=Success + +/community/settings.bml.title.create=Create Community + +/community/settings.bml.title.modify=Community Settings + +/community/transfer.bml.account=Community Account + +/community/transfer.bml.badstatus.body=The account you are logged in as is not active and cannot use this page at this time. + +/community/transfer.bml.badstatus.title=Account Status + +/community/transfer.bml.body=If you have the password to a community and are not currently a maintainer, you can make yourself a maintainer by filling out the following form. + +/community/transfer.bml.button.title=Transfer Community + +/community/transfer.bml.error.alreadyadmin=Already a maintainer of community. + +/community/transfer.bml.error.badstatus=Community is not active. + +/community/transfer.bml.error.mismatch=Password does not match. + +/community/transfer.bml.error.nopassword=No password provided. + +/community/transfer.bml.error.notcomm=Account not a community. + +/community/transfer.bml.error.notfound=Account not found. + +/community/transfer.bml.password=Community Password + +/community/transfer.bml.success.body=You have successfully added yourself as a maintainer of [[comm]]. + +/community/transfer.bml.success.title=Success + +/community/transfer.bml.title=Transfer Community + +/create.bml.birthday.birthdate=Birthdate: + +/create.bml.birthday.security=Security: + +/create.bml.birthday.head=Age Verification + +/create.bml.birthday.question=Please select the month, day, and year you were born. We require this information to create an account in order to comply with the Children's Online Privacy Protection Act (COPPA). This information is not stored in our database and is only used during account creation. Read our privacy policy for more information on our information practices. + +/create.bml.birthday.required=(required) + +/create.bml.btn.create=Create Journal + +/create.bml.btn.proceed=Proceed... + +/create.bml.captcha.answer=Answer: + +/create.bml.captcha.audiodesc=Type the numbers you hear to prove that you're not a spam robot: + +/create.bml.captcha.desc=Type the letters and numbers you see below, to prove that you're not a spam robot. If you can't read the text, type "AUDIO" and take a sound test instead. + +/create.bml.captcha.invalid=Invalid answer to previous challenge. Try another. + +/create.bml.captcha.play=Play the sound + +/create.bml.captcha.prove=Prove that you're a human + +/create.bml.clusterselect.cluster=Cluster: + +/create.bml.clusterselect.clusternum=Cluster [[number]] + +/create.bml.clusterselect.head=Cluster Selection + +/create.bml.clusterselect.nocluster=No Cluster + +/create.bml.clusterselect.text=Please select the cluster you want to create this account on. Note: This is a debugging/test option only. In production, users won't pick this, or know anything about it. + +/create.bml.community=Would you rather create a community? + +/create.bml.create.head=Creating a New Journal + +/create.bml.create.text=Creating a new LiveJournal is easy, just follow the instructions below! + +/create.bml.email.head=Your email address + +/create.bml.email.input.head=Email Address: + +/create.bml.email.text3=For verification and security purposes, we need your email address. Read our privacy policy for more information on our information practices. + +/create.bml.error.birthday.invalid=You must enter a valid birthday. + +/create.bml.error.coppa.under13=Sorry, due to COPPA restrictions, you cannot use the service until you're 13 years old. Please come back on your 13th birthday. + +/create.bml.error.email.blank=You must provide your email address. + +/create.bml.error.email.lj_domain=You cannot use a [[domain]] alias when creating an account. Please enter a different email address. + +/create.bml.error.email.nospaces=No spaces allowed in email address. If you're on AOL, remember that your Internet Email address is your screen name with all spaces removed, followed by @aol.com + +/create.bml.error.password.asciionly=You can only use ASCII symbols in the password. + +/create.bml.error.password.blank=You must enter a password. + +/create.bml.error.password.nomatch=Passwords do not match. + +/create.bml.error.postrequired=POST required. + +/create.bml.error.username.blank=Please supply a name or handle/alias. + +/create.bml.error.username.inuse=Username already in use; please select a different one. + +/create.bml.error.username.iscode=Username appears to be an invite code, not a username. + +/create.bml.error.username.mustenter=You must enter a username. + +/create.bml.error.username.reserved=Sorry, that is a reserved username. + +/create.bml.errors.label=Please note the following problems and resubmit: + +/create.bml.initialfriends=Add these journals to your friends list to be kept up to date on site news and information. + +/create.bml.initialfriends.heading=Starter Friends + +/create.bml.name.head=Your Name + +/create.bml.name.input.head=Name: + +/create.bml.name.text=What's your name or handle? This will appear at the top of your journal, and in the user directory should you choose to be listed in it. You do not have to provide your full name or even your real name. + +/create.bml.password.head=Password + +/create.bml.password.input.head1=Password: + +/create.bml.password.input.head2=Re-type password: + +/create.bml.password.secure=You must choose a secure password that is not based on a dictionary word, your username, or your email address. + +/create.bml.password.text=Select a password. + +/create.bml.success.btn.enterinfo=Enter Personal Information + +/create.bml.success.head=Success! + +/create.bml.success.text1=Your journal has been created. Important registration information has been emailed to [[email]] containing further instructions. Be sure to confirm your journal creation by clicking on the link sent to you in email. + +/create.bml.success.text2=Your LiveJournal will be available at: + +/create.bml.success.text3=Now, please take the time to fill in some information about yourself. It's mostly optional, but it lets us get an idea of who's using LiveJournal. + +/create.bml.title=Create New Journal + +/create.bml.tos.error=You must read and agree to the terms of service before creating an account. + +/create.bml.tos.haveread=I have read and agree to the Terms of Service. + +/create.bml.tos.heading=Terms of Service + +/create.bml.tos.p1.3=Before continuing you must read and agree to the Terms of Service (which includes our privacy policy). + +/create.bml.useacctcodes.entercode=To create a new account, enter an account creation code: + +/create.bml.useacctcodes.welcome=Welcome + +/create.bml.username.box.head=Username: + +/create.bml.username.charsallowed=Your username may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_). Additionally, it must not be longer than 15 characters. + +/create.bml.username.forpaidaccts=Or, for paid accounts: + +/create.bml.username.head=Username + +/create.bml.username.ljaddress=Your journal will be at these addresses: + +/create.bml.username.text=Each [[sitename]] user must have their own unique username. Your username is what appears in the address to your journal and what you use to log into the [[sitename]] server. It also shows up when you post comments in other people's journals. + +/create.bml.username.username=username + +/customize/index.bml.change=Change + +/customize/index.bml.choose=Do you want to use the old style system, or the new one? + +/customize/index.bml.choose.header=Choose style system + +/customize/index.bml.choose.s1=Old system (S1) + +/customize/index.bml.choose.s2=New system (S2) + +/customize/index.bml.error.cant_generate_user_layer=Could not generate user layer + +/customize/index.bml.error.disallowed_custom_layer=Your account status does not allow access to this custom layer + +/customize/index.bml.error.fail_create_style=Failed to create new style. + +/customize/index.bml.error.not_your_layout=Not your layout. + +/customize/index.bml.error.not_your_theme=Not your theme + +/customize/index.bml.error.no_core_parent=No core parent? + +/customize/index.bml.previews=(Previews) + +/customize/index.bml.s1.2=The old style system is configured through the Modify Journal page. + +/customize/index.bml.s1.header=Using S1 + +/customize/index.bml.s2.advanced.denied=Your account is not permitted to use the advanced customization features. + +/customize/index.bml.s2.advanced.header=Advanced Customizations + +/customize/index.bml.s2.advanced.permitted=To create new layers and styles from scratch, visit the advanced customization center. + +/customize/index.bml.s2.customize=The following settings are layout-dependent. + +/customize/index.bml.s2.customize.header=Step 2: Customize Layout + +/customize/index.bml.s2.customize.language=The following languages are fully or partially supported by this layout. + +/customize/index.bml.s2.customize.language.custom=(Custom) + +/customize/index.bml.s2.customize.language.default=(Default) + +/customize/index.bml.s2.customize.language.header=Language + +/customize/index.bml.s2.customize.settings=If you want to customize your journal further, here you can tweak individual settings to get it looking exactly how you want. + +/customize/index.bml.s2.customize.settings.delete=Remove Customizations + +/customize/index.bml.s2.customize.settings.delete.confirm=Are you sure you want to remove these customizations? + +/customize/index.bml.s2.customize.settings.edit=Edit Customizations + +/customize/index.bml.s2.customize.settings.header=Change Individual Settings + +/customize/index.bml.s2.customize.settings.new=Customize + +/customize/index.bml.s2.customize.themes=Choose from the following optional themes for this layout. + +/customize/index.bml.s2.customize.themes.default=(Layout Default) + +/customize/index.bml.s2.customize.themes.header=Themes + +/customize/index.bml.s2.layout<< +Pick your layout. Because theme selection and custom modifications depend +on your layout, changing this setting discards all other edits you may have made. +. + +/customize/index.bml.s2.layout.header=Step 1: Layout + +/customize/index.bml.s2.related.editinfo.about=Set your journal's titles and various options. + +/customize/index.bml.s2.related.header=Related Pages + +/customize/index.bml.s2.related.links.about=Some styles can include your managed link list. + +/customize/index.bml.s2.related.modify.about=Set your journal's mood icon set. + +/customize/index.bml.title=Customize Journal + +/delcomment.bml.changeoptions<< +Note: From the [[link]] page, you can choose +whether to allow all, registered users, or +friends only to post comments. +. + +/delcomment.bml.confirm.banuser=Ban [[user]] from commenting in your journal + +/delcomment.bml.confirm.body=Are you sure you want to delete this comment? + +/delcomment.bml.confirm.delthread=Delete thread (all subcomments) + +/delcomment.bml.confirm.head=Delete this comment? + +/delcomment.bml.confirm.spam=Mark this comment as spam + +/delcomment.bml.confirm.submit=Delete Comment + +/delcomment.bml.error.alreadydeleted=The specified comment has already been deleted. + +/delcomment.bml.error.cantdelete=A comment may only be deleted by its author or the journal owner. + +/delcomment.bml.error.cantdelete.comm=A comment may only be deleted by its author, the author of the journal entry, or a community maintainer. + +/delcomment.bml.error.invalidtype=Invalid comment type. This page only handles comments on journal entries. + +/delcomment.bml.error.nocomment=The specified comment does not exist. + +/delcomment.bml.error.suspended=You are not allowed to delete comments while your account is suspended. + +/delcomment.bml.success.andban=The comment has been deleted, and user [[user]] has been banned from commenting in your journal. + +/delcomment.bml.success.head=Deleted + +/delcomment.bml.success.noban=The comment has been deleted. + +/delcomment.bml.success.spam=Additionally, the administrators of this site have been notified that this comment was spam. Thank you for your report. + +/delcomment.bml.title=Delete Comment + +/directory.bml.browse.country.desc=Select a country to read journals from that country... + +/directory.bml.browse.country.title=Browse Journals by Country + +/directory.bml.browse.usa.desc=Click a US state below to read journals from that state, or click a country name below the map to read journals from that country. + +/directory.bml.browse.usa.title=Browse Journals by US State + +/directory.bml.error.accounttype<< +Sorry, your account type doesn't permit usage of the +directory, or you aren't currently logged in. If your account type permits +directory usage, be sure that you are logged in and then try again. +. + +/directory.bml.navcrap.matches=[[count]] matches + +/directory.bml.navcrap.xofy=Page [[curpage]] of [[totpages]] shown (records [[reca]]-[[recb]]) + +/directory.bml.open=Open + +/directory.bml.post=Post + +/directory.bml.search.monkey=Hundreds of trained monkeys are currently running about finding your search results. Please stand by. + +/directory.bml.search.new=New Query + +/directory.bml.search.overflow=Search results limited to [[count]] results. Please refine your query. + +/directory.bml.search.title=Searching + +/directory.bml.update=Update: + +/directory.bml.user=User + +/editinfo.bml.advanced.about=Don't worry about this stuff if you don't know what it is. + +/editinfo.bml.advanced.title=Advanced Options + +/editinfo.bml.allowshowcontact.about<< +You should keep this option enabled. This lets other people be able to contact +you by showing your email address, ICQ number, and AOL Instant Messenger screenname +all on your LiveJournal. +. + +/editinfo.bml.allowshowcontact.email=If visible, email address to be displayed: + +/editinfo.bml.allowshowcontact.email.actual_only=Actual address only + +/editinfo.bml.allowshowcontact.email.both=Both (actual + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Site address only + +/editinfo.bml.allowshowcontact.email.neither=Neither. Don't show any email address. + +/editinfo.bml.allowshowcontact.email.no_show=Don't show email address + +/editinfo.bml.allowshowcontact.email.show=Show email address + +/editinfo.bml.allowshowcontact.email.withdomainaddr<< +With the option above, you may also choose to hide your email address +(while still showing other contact information), only show your site email address, +only show your real address, or show them both. +. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr<< +With the option above, you may also choose to hide your email address +(while still showing other contact information). +. + +/editinfo.bml.allowshowcontact.title=Show your contact information on your LiveJournal? + +/editinfo.bml.allowshowinfo.about=Turn this on if you want your city/state/country and birthday to be visible to other users. + +/editinfo.bml.allowshowinfo.title=Show location & birthday? + +/editinfo.bml.autotranslate.about<< +Use this option to tell LiveJournal which encoding to assume for your entries and comments entered before the site was converted to Unicode. +If you write in English, choose "Western European" here. +. + +/editinfo.bml.autotranslate.header=Auto-translate older entries from: + +/editinfo.bml.bday.title=Birthday + +/editinfo.bml.bday.year.opt=year is optional + +/editinfo.bml.bdayreminders.about=If you want to get email reminding you of birthdays for your friends on LiveJournal, click this box. + +/editinfo.bml.bdayreminders.header=Send me birthday reminders (currently disabled) + +/editinfo.bml.bio.about=Here you can enter a little mini-biography about yourself. This will show up on your User Info page. + +/editinfo.bml.bio.header=About You + +/editinfo.bml.blockrobots.about<< +If you check this option, robots will be told to go away. +Not all robots respect the rules. +. + +/editinfo.bml.blockrobots.header=Block Robots/Spiders from indexing your journal + +/editinfo.bml.chat.aolim.title=AOL IM + +/editinfo.bml.chat.icquin.title=ICQ UIN + +/editinfo.bml.chat.jabber.title=Jabber + +/editinfo.bml.chat.msnusername.title=MSN Username + +/editinfo.bml.chat.yahooid.title=Yahoo! ID + +/editinfo.bml.city.title=City + +/editinfo.bml.country.choose=Pick a country + +/editinfo.bml.country.title=Country + +/editinfo.bml.donotlog=No + +/editinfo.bml.email.title=Email + +/editinfo.bml.enableboards.about=Check this if you want people to be able to reply to journal entries you post. + +/editinfo.bml.enableboards.header=Enable message boards + +/editinfo.bml.encoding.about=Don't worry about this stuff. In general, only international users that write in several different languages will need to change anything here. + +/editinfo.bml.encoding.header=Encoding Options + +/editinfo.bml.error.day.notinmonth=Invalid day for that month. + +/editinfo.bml.error.day.outofrange=Invalid birthday day. Enter a day from 1-31. + +/editinfo.bml.error.email.lj_domain<< +You cannot enter an @[[domain]] email address. +Enter your real address in that field. +If you're a paid user, your [[user]]@[[domain]] address will forward to your real address. +To choose which email address (or both) is displayed publicly, see the option below the "Show your Contact Information" option. +. + +/editinfo.bml.error.email.none=You must provide your email address + +/editinfo.bml.error.email.no_space<< +No spaces are allowed in an email address. +If you're on AOL, remember that your Internet Email address is your screen name with all spaces removed, followed by @aol.com +. + +/editinfo.bml.error.excessive_int<< +Sorry, you listed too many interests. The limit is 150, but you've listed [[intcount]]. +Any changes you made to your interests were not saved. Go back and cut down your list, +then save again. +. + +/editinfo.bml.error.invalidbio<< +Your stored bio contains invalid characters. You must visit +the conversion page to convert it +to Unicode. +. + +/editinfo.bml.error.invalidints<< +Your currently stored list of interests contains invalid characters. You must visit +the conversion page to convert it +to Unicode. +. + +/editinfo.bml.error.invalidname<< +Your name contains invalid characters. You must visit +the conversion page to convert it +to Unicode. +. + +/editinfo.bml.error.locale.country_ne_state=You specified United States as your country, but you typed in a non-US state in the "other state" field. + +/editinfo.bml.error.locale.invalid_country=Somehow you selected an invalid country. + +/editinfo.bml.error.locale.state_ne_country=You specified a non-US country but selected a US state. + +/editinfo.bml.error.locale.zip_ne_state<< +Your zip code does not match the state you specified. +Either correct the information, or erase one or both of the state and zip code fields. +. + +/editinfo.bml.error.locale.zip_requires_us<< +You entered a zip code but you did not select United States as your country. +We only collect zip code information about people in the US. +Please go back and remove the zip code or select United States as your country. +. + +/editinfo.bml.error.month.outofrange=Invalid birthday month. Enter a month from 1-12. (Jan-Dec) + +/editinfo.bml.error.noname=Your name is a required field. At least provide your first name, or a nickname or handle. + +/editinfo.bml.error.tm.require.number=If you're going to use text messaging, you must enter your phone number. + +/editinfo.bml.error.tm.require_provider<< +If you're going to use text messaging, you must select your service provider. +If yours is not listed, please contact us with information about how your service's text messaging feature works so we can add support for it. +. + +/editinfo.bml.error.year.notenoughdigits=Invalid birthday year. Enter a 4-digit year. + +/editinfo.bml.error.year.outofrange=Invalid birthday year. + +/editinfo.bml.finished.about=When done, press the "Save Changes" button below: + +/editinfo.bml.finished.header=Done? + +/editinfo.bml.finished.save_button=Save Changes + +/editinfo.bml.foafurl.about=If you do not want to use the default FOAF page we provide, any URL you enter above will be used as your FOAF resource instead. We will redirect FOAF requests to the specified URL. + +/editinfo.bml.foafurl.title=External FOAF URL: + +/editinfo.bml.gender.title=Gender + +/editinfo.bml.getreplies.about=Check this if you want to get email updates when people reply to your journal entries in the message boards. + +/editinfo.bml.getreplies.header=Get message board replies + +/editinfo.bml.getselfemails.about=Check this if you wish to get an email every time you post a comment in a journal or community. You will not get email for anonymous comments. + +/editinfo.bml.getselfemails.header=Get comments you post emailed to you + +/editinfo.bml.hidefriendof.about=If you check this, the list of people that list you as a friend is hidden on your profile page. + +/editinfo.bml.hidefriendof.header=Hide "Friend of" list + +/editinfo.bml.howhear.about<< +Just for curiosity's sake, where did you hear about [[sitename]] from? +If it was a specific person, enter their username; if it +was from another source/article/link/website, enter the appropriate information. +. + +/editinfo.bml.howhear.header=Curiosity + +/editinfo.bml.htmlemail.about<< +Check this if your email program fully supports HTML in your email. +Many clients try to support it but fail horribly. +If you uncheck it, LiveJournal will only send text emails. +. + +/editinfo.bml.htmlemail.header=Send HTML Emails + +/editinfo.bml.imagelinks.about=Placeholders are useful if you are browsing at work or over a slow connection, replacing inline images with links. What size images do you want placeholders to be used for? + +/editinfo.bml.imagelinks.header=Use image placeholders on your friends page + +/editinfo.bml.imagelinks.size.all=Use placeholders for all images + +/editinfo.bml.imagelinks.size.custom=Custom: use placeholders for images larger than [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=Use placeholders for large images (over [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Use placeholders for medium images (over [[width]]x[[height]]) + +/editinfo.bml.int.about<< +If you want other people to be able to search the directory and find you by interest, +list below everything you're interested in, separated by commas. +Short single-word phrases are best. Rule of thumb: You should be able to put +the interest in the sentence "I like ________". When referring to nouns, use the +plural form for consistency. "I like DVDs" instead of "I like DVD". +. + +/editinfo.bml.int.ex.bad=BAD Example: I like lots of bands and watching movies and talking to friends and going to clubs. That sort of stuff goes in your bio above. + +/editinfo.bml.int.ex.good=GOOD Example: biking, snow skiing, computers, dvds, mp3s, cheese, women + +/editinfo.bml.int.header=Interests + +/editinfo.bml.login.enterinfo=Enter your username and password to modify your personal information. + +/editinfo.bml.login.forgot.header=Forget something? + +/editinfo.bml.login.forgot.recover=If you forgot your username or password, recover it here!. + +/editinfo.bml.logip.always=Always + +/editinfo.bml.logip.anon_only=Anonymous posters only + +/editinfo.bml.logip.header=Log IP addresses of people replying? + +/editinfo.bml.mangleaddress.about<< +If you have the above option selected and are afraid spam-robots will find your email +address on LiveJournal, select this option. Your email address will be modified +so your email address won't be found by email-collecting robots. +. + +/editinfo.bml.mangleaddress.header=Mangle your displayed email address + +/editinfo.bml.mutualfriends.about=This option adds a new list to your profile page: the mutual friends list. People who you list as a friend and who also list you as a friend will be put on this list. + +/editinfo.bml.mutualfriends.header=Display mutual friends on profile page + +/editinfo.bml.name.title=Name + +/editinfo.bml.newemail.body2<< +You have just changed the email address for your [[sitename]] account "[[username]]". To validate the change, please go to this address: + +[[conflink]] + +Regards, +[[sitename]] Team +[[sitelink]] +. + +/editinfo.bml.newemail.subject=Email Address Changed + +/editinfo.bml.numcomments.about=Check this if you want to append the comment count to URLs to make your browser possibly display the links in a different color. + +/editinfo.bml.numcomments.header=Add &nc=xx to comment URLs + +/editinfo.bml.optional=Optional + +/editinfo.bml.opt_in.about<< +If you want to know when we add some cool new feature to LiveJournal, check this box. +We aren't currently using this feature, but we might in the future. +Your email address will not be visible to other users, and you can turn this off at anytime. +. + +/editinfo.bml.opt_in.header=Send me LiveJournal news. + +/editinfo.bml.persinfo.disclaimer<< +Fill in some quick information about yourself, for our own curiosity and statistical purposes. +We're not going to do anything evil or annoying with this information, we'd just like to see +who and where our users are. Please, fill it in correctly. If you're concerned, +read our privacy policy. +. + +/editinfo.bml.persinfo.header=Personal Information + +/editinfo.bml.screen.all=All + +/editinfo.bml.screen.anon=Anonymous + +/editinfo.bml.screen.header=Which replies do you want screened by default? + +/editinfo.bml.screen.none=None + +/editinfo.bml.screen.nonfriends=By non-friends + +/editinfo.bml.screen.nonmembers=By non-members + +/editinfo.bml.security.header=Security + +/editinfo.bml.security.visibility.anybody=Anybody + +/editinfo.bml.security.visibility.everybody=Everybody + +/editinfo.bml.security.visibility.friends=Friends only + +/editinfo.bml.security.visibility.regusers=Registered Users + +/editinfo.bml.settings.friendspage.title=Friends Page Title: + +/editinfo.bml.settings.friendspage.title.optional=Optionally, enter a title for your friends view pages. (no HTML) + +/editinfo.bml.settings.header=LiveJournal Options + +/editinfo.bml.settings.journal.subtitle=Journal Subtitle: + +/editinfo.bml.settings.journal.subtitle.optional=Optionally, enter a title and subtitle for your journal. (no HTML). + +/editinfo.bml.settings.journal.title=Journal Title: + +/editinfo.bml.settings.privacy.about=Select below your personal privacy options and preferences. + +/editinfo.bml.settings.privacy.header=Privacy Options + +/editinfo.bml.state.other=Or, type other state/province/territory + +/editinfo.bml.state.title=State + +/editinfo.bml.state.us=US States + +/editinfo.bml.stylemine.about=Check this option to view comment pages in your journal style when following links from your friends page. + +/editinfo.bml.stylemine.header=View comment pages in your journal style? + +/editinfo.bml.success.header=Success! + +/editinfo.bml.success.message=Your information and journal settings and profile have been updated. + +/editinfo.bml.switch.button=Switch + +/editinfo.bml.switch.header=Switch Journal + +/editinfo.bml.switch.workwith=Work with journal: + +/editinfo.bml.title=Edit Personal Information + +/editinfo.bml.tm.details=details + +/editinfo.bml.tm.phonenum=Full phone number: + +/editinfo.bml.tm.sec.about=Enable text messaging from other users. + +/editinfo.bml.tm.sec.title=Security Level: + +/editinfo.bml.tm.servprov=Service Provider + +/editinfo.bml.tm.title=Text Messaging + +/editinfo.bml.translatemailto.about<< +In case you chose to receive message board replies by email, and your email client doesn't handle Unicode (UTF-8) +messages very well, use this option to specify a different encoding into which LiveJournal will automatically translate the text of comments sent to you. +. + +/editinfo.bml.translatemailto.header=Translate email notifications into: + +/editinfo.bml.unbanusers.about=You have the following users banned from posting in your journal. Check the checkbox by their username to remove the ban on them. + +/editinfo.bml.unbanusers.header=Unban Users + +/editinfo.bml.userpic.about<< +Below is the miniature picture you have uploaded to represent you +throughout the LiveJournal site and in your journal and in your friends' journals: +. + +/editinfo.bml.userpic.edit=To delete this picture, or upload a new one, go here. + +/editinfo.bml.userpic.header=Your Picture + +/editinfo.bml.userpic.none=no image uploaded + +/editinfo.bml.weblogscom.about=Select this option if you would like to have Weblogs.com list your journal when you post new public entries. + +/editinfo.bml.weblogscom.header=Notify Weblogs.com of updates + +/editinfo.bml.webpagename.title=Webpage Name + +/editinfo.bml.webpageurl.title=Webpage URL + +/editinfo.bml.whoreply.header=Who can reply to your entries? + +/editinfo.bml.zip.title=ZIP Code + +/editinfo.bml.zip.usonly=5 digit ZIP code; US residents only + +/editjournal.bml.auth.poster=Poster: + +/editjournal.bml.btn.proceed=Proceed... + +/editjournal.bml.certainday=Certain Day: + +/editjournal.bml.desc=Please use the form below to find the entry you would like to edit. + +/editjournal.bml.in=In community: + +/editjournal.bml.recententries=most recent entries + +/editjournal.bml.recententry=Most recent entry + +/editjournal.bml.success.delete=Journal entry was deleted. + +/editjournal.bml.success.deletespam=Additionally, the entry was marked as spam. Thank you for your report. + +/editjournal.bml.success.head=Success + +/editjournal.bml.title=Edit Journal Entries + +/editjournal.bml.viewwhat=View What Entries: + +/editjournal_do.bml.body<< +Edit the fields of your journal entry you'd like to modify and press the save button at the +bottom of the page. Alternately, you can press the delete button to delete the entry. +. + +/editjournal_do.bml.btn.delete=Delete Entry + +/editjournal_do.bml.btn.deletespam=Delete and Mark As Spam + +/editjournal_do.bml.btn.edit=Edit Selected Entry + +/editjournal_do.bml.btn.preview=Preview Entry + +/editjournal_do.bml.btn.save=Save Journal Entry + +/editjournal_do.bml.continue.head=Press to continue... + +/editjournal_do.bml.continue.text=After you select an item to edit or delete, press the Edit button below. + +/editjournal_do.bml.currmood=Current Mood: + +/editjournal_do.bml.currmusic=Current Music: + +/editjournal_do.bml.date=Date: + +/editjournal_do.bml.default=default + +/editjournal_do.bml.delete.confirm=Are you sure you want to delete this entry? + +/editjournal_do.bml.deletespam.confirm=Are you sure you want to delete this entry and mark it as spam? + +/editjournal_do.bml.edit.text=Edit the fields of your journal entry you'd like to modify and press the save button at the bottom of the page. To delete the entry, just delete all the text and press save... the entry will be deleted. + +/editjournal_do.bml.error.getting=There was an error getting the journal entries to edit: + +/editjournal_do.bml.error.modify=An error occurred modifying your journal: + +/editjournal_do.bml.error.nofind=Could not find selected journal entry. + +/editjournal_do.bml.event=Event: + +/editjournal_do.bml.localtime=Local time: + +/editjournal_do.bml.noneother=None, or other: + +/editjournal_do.bml.opt.backdate=Backdate Entry: + +/editjournal_do.bml.opt.backdate.about=won't show on friends view + +/editjournal_do.bml.opt.nocomments=Disallow Comments: + +/editjournal_do.bml.opt.noemail=Don't email Comments: + +/editjournal_do.bml.opt.noformat=Don't auto-format: + +/editjournal_do.bml.opt.spellcheck=Spell check entry before saving + +/editjournal_do.bml.other=Other: + +/editjournal_do.bml.pickentry.head=Pick an entry to edit + +/editjournal_do.bml.pickentry.text=Select which item you want to edit and press the edit button at the bottom of the page. + +/editjournal_do.bml.picture=Picture to use: + +/editjournal_do.bml.preview.header=Preview Entry + +/editjournal_do.bml.preview.text=This is how the entry will look when posted. Using the form below, you can edit the entry further, or you can submit it as is. + +/editjournal_do.bml.save.head=Press to save... + +/editjournal_do.bml.save.text=After you're done editing your journal entry, press Save. + +/editjournal_do.bml.spellchecked=Your spell-checked post: + +/editjournal_do.bml.subject=Subject: (optional, for use on longer entries) + +/editjournal_do.bml.success.delete=Journal entry was deleted. + +/editjournal_do.bml.success.deletespam=Additionally, the entry was marked as spam. Thank you for your report. + +/editjournal_do.bml.success.head=Success + +/editjournal_do.bml.timeformat=24 hour time + +/editjournal_do.bml.title=Edit Journal Entries + +/editpics.bml.btn.proceed=Proceed + +/editpics.bml.btn.save=Save Settings + +/editpics.bml.curpics=Current Pictures + +/editpics.bml.curpics.desc=Here are the pictures you've uploaded in the past. You can assign keywords to them so you can use them by keyword later, select which one to use as your default, or delete old ones. To upload a new one, use the form at the bottom of the page. + +/editpics.bml.error.badurl=The address for the picture to be uploaded does not look correct. It should start with http:// + +/editpics.bml.error.filetoolarge=Image uploaded is too large. File size cannot exceed [[maxsize]]. + +/editpics.bml.error.imagetoolarge=The dimensions of your image ([[imagesize]]) exceed maximum size. Your picture can only be 100x100 pixels large. Use a image/photo editing program to reduce the image to thumbnail-size. + +/editpics.bml.error.invalidimage=Invalid image file. + +/editpics.bml.error.keywords=You used the keyword "[[ekw]]" for multiple pictures. One was randomly chosen, but likely not the one you wanted. You may want to go back and fix that. + +/editpics.bml.error.toomanykeywords=The [[?numwords|keyword|keywords]] "[[words]]" [[?numwords|has|have]] not been saved as [[?numwords|its|their]] user picture icon already has [[max]] keywords. + +/editpics.bml.error.toomanypics2=You are already at your limit of [[maxpics]] pictures. You cannot upload this picture until you delete one of your existing ones. + +/editpics.bml.error.toomanypics3=You are currently at your limit of [[max]] [[?max|picture|pictures]]. You will not be able to upload additional pictures until you delete one or more of your current pictures. + +/editpics.bml.error.unsupportedtype=Files of type [[filetype]] are not supported. You can only upload GIF, PNG or JPG files. Nearly all image/photo programs can do this conversion for you. + +/editpics.bml.error.urlerror=An error ocurred while trying to fetch your image. + +/editpics.bml.fromfile=From File: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=f + +/editpics.bml.fromurl=From URL: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=r + +/editpics.bml.imagesize.by|notes=This character is inserted between two numbers to indicate "by" when specifying image dimensions, for example "100x100". +/editpics.bml.imagesize.by=x + +/editpics.bml.kilobytes=KB + +/editpics.bml.label.comment=Comment: + +/editpics.bml.label.default=Default: + +/editpics.bml.label.delete=Delete: + +/editpics.bml.label.keywords=Keywords: + +/editpics.bml.makedefault=Make this your default picture + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=d + +/editpics.bml.nodefault=No Default Picture + +/editpics.bml.noneupload=You have no pictures uploaded. Please upload one using the form below. + +/editpics.bml.nopics=No Pictures + +/editpics.bml.piclimitstatus=Currently uploaded: [[current]] out of [[max]]. + +/editpics.bml.restriction.fileformat=File format must be either PNG, GIF or JPG + +/editpics.bml.restriction.filesize=File size must be less than 40k + +/editpics.bml.restriction.imagesize=Image dimensions must be no larger than 100x100 pixels + +/editpics.bml.restriction.keywords=Picture will be unusable if keywords are not supplied + +/editpics.bml.restriction.keywords.faq=Picture will be unusable if keywords are not supplied + +/editpics.bml.title=Edit User Pictures + +/editpics.bml.uploaddesc=Use the form below to upload a new picture. + +/editpics.bml.uploaddesc.fb=Upload a thumbnail of an image hosted on your [[sitename]] account as a new user picture. + +/editpics.bml.uploadheader=Upload a New Picture + +/editpics.bml.uploadheader.fb=Upload a New Picture From Fotobilder + +/editpics.bml.warning.keywords=One or more of your pictures do not have keywords defined and thus cannot currently be used + +/editpics.bml.warning.keywords.faq=One or more of your pictures do not have keywords defined and thus cannot currently be used + +/edittags.bml.button.save=Save changes + +/edittags.bml.current=Current tags: + +/edittags.bml.disabled=Sorry, the tags system is currently disabled. + +/edittags.bml.entry=Entry: + +/edittags.bml.error.db=Sorry, we encountered a database error. Please try again. + +/edittags.bml.intro=Use the form below to edit the tags on this entry. + +/edittags.bml.invalid.entry=Specified entry is invalid. + +/edittags.bml.invalid.journal=Specified journal is invalid. + +/edittags.bml.invalid.link=You have reached this page in an invalid way. Please follow a link from an entry to edit tags. + +/edittags.bml.invalid.notauthorized=You do not have access to view that entry. + +/edittags.bml.permissions.add.yes=You may add tags from the list above. + +/edittags.bml.permissions.control.yes=You may remove tags or create new ones. + +/edittags.bml.permissions.none=(You do not have permission to edit tags on this entry.) + +/edittags.bml.subject=Subject: + +/edittags.bml.title=Edit Tags on Entry + +/edittags.bml.users=User's tags: + +/edittags.bml.view=View this entry. + +/export.bml.btn.proceed=Proceed... + +/export.bml.description=This feature lets you download your entire journal to a custom format for backup purposes. + +/export.bml.fields=Fields: + +/export.bml.format.csv=CSV (Comma Separated Values) + +/export.bml.format.xml=XML + +/export.bml.label.encoding=Encoding: + +/export.bml.label.field.allowmask=Allow Mask + +/export.bml.label.field.currents=Current Mood & Music + +/export.bml.label.field.event=Event + +/export.bml.label.field.eventtime=Event Time (from user's clock) + +/export.bml.label.field.itemid=ID Number + +/export.bml.label.field.logtime=Log Time (from system's clock) + +/export.bml.label.field.security=Security Level + +/export.bml.label.field.subject=Subject + +/export.bml.label.format=Format: + +/export.bml.label.header=Header + +/export.bml.label.month=Select month: + +/export.bml.label.month.month=mm: + +/export.bml.label.month.year=yyyy: + +/export.bml.label.notranslation=Do not translate between encodings + +/export.bml.label.what=Export what: + +/export.bml.title=Export Journal + +/export.bml.what.entries=Journal entries + +/export_do.bml.error.encoding=Invalid encoding selected + +/friends/add.bml.add.header=Success + +/friends/add.bml.add.text=User [[ljuser]] was added to your friend list. You can view your friends page here. + +/friends/add.bml.add.title=Friend Added! + +/friends/add.bml.btn.add=Add [[user]] + +/friends/add.bml.btn.modify=Modify + +/friends/add.bml.btn.remove=Remove + +/friends/add.bml.colors.bg=Background + +/friends/add.bml.colors.fg=Foreground + +/friends/add.bml.colors.header=Colors + +/friends/add.bml.colors.hover=(Hover your mouse over a color to see its name) + +/friends/add.bml.colors.text=You may also optionally select the colors that will represent [[user]] in your friends list. + +/friends/add.bml.confirm.header=Add [[user]] as a friend? + +/friends/add.bml.confirm.syn.header=Add syndicated feed [[user]] as a friend? + +/friends/add.bml.confirm.syn.title=Add Syndicated Feed + +/friends/add.bml.confirm.text=To add [[user]] to your friends list, click the button below. + +/friends/add.bml.confirm.title=Add Friend + +/friends/add.bml.error1.header=Log In First + +/friends/add.bml.error1.text<< +To add a user to your friends list you must first go and log in. If you don't +already have an account you can create one to track your friend's journals. +. + +/friends/add.bml.error1.title=Add Friend + +/friends/add.bml.error2.text=Invalid or missing username given. To add a friend, go to the edit friends page. + +/friends/add.bml.error3.text=You already have [[user]] listed as a friend. However, you can modify the colors you've chosen to represent him/her. + +/friends/add.bml.error3.title=Modify Friend + +/friends/add.bml.groups.header=Friends Groups + +/friends/add.bml.groups.nogroup=No friend groups setup. + +/friends/add.bml.groups.text=What friend groups do you want to put this user in? Friend groups are used for filtering your friends list view and also for group-based viewing security of items. + +/friends/add.bml.remove.header=Success + +/friends/add.bml.remove.text=User [[ljuser]] was removed from your friend list. You can view your friends page here. + +/friends/add.bml.remove.title=Friend Removed! + +/friends/edit.bml.title=Edit Friends + +/friends/editgroups.bml.btn.ge.del=Delete + +/friends/editgroups.bml.btn.ge.new=New + +/friends/editgroups.bml.btn.ge.ren=Rename + +/friends/editgroups.bml.btn.gs.private=Private + +/friends/editgroups.bml.btn.gs.public=Public + +/friends/editgroups.bml.btn.mv.down=Move down + +/friends/editgroups.bml.btn.mv.up=Move up + +/friends/editgroups.bml.confirm.delete=Are you sure you wish to delete this custom friends group? + +/friends/editgroups.bml.done.btn=Save Changes + +/friends/editgroups.bml.done.header=Done? + +/friends/editgroups.bml.done.text=When you are done, press the button below to save your changes. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=You have reached the maximum limit of 30 custom friends groups. If you have deleted one or more groups but have not saved the changes yet, do so now, then come back to this page and reload it. You will then be able to create new custom friends groups. + +/friends/editgroups.bml.error.text=The server returned the following error message: + +/friends/editgroups.bml.group.public=(public) + +/friends/editgroups.bml.ingroup=In group: + +/friends/editgroups.bml.ingroup.not=Not in group: + +/friends/editgroups.bml.prompt.newname=Enter the name for the new custom friends group: + +/friends/editgroups.bml.prompt.rename=Rename this custom friends group to: + +/friends/editgroups.bml.saved.header=Saved + +/friends/editgroups.bml.saved.text=Your custom friends groups are now saved. + +/friends/editgroups.bml.text<< +This page allows you to edit your custom friends groups. Custom friends groups are used +for setting security on items and for filtering your friends page. +This page requires JavaScript to work. +. + +/friends/editgroups.bml.text.sec<< +Security note: If you wish to delete a group and make a new group, +do not do this by renaming one group and then editing it. +If you do this, all your old entries which are accessible to the old group will +then be accessible to the new group. +. + +/friends/editgroups.bml.title=Edit Custom Friends Groups + +/friends/editgroups.bml.yourgroups=Your custom friends groups: + +/friends/edit_do.bml.addfriends.head=Add Friends + +/friends/edit_do.bml.addfriends.text=Enter your friends' LiveJournal user names in the boxes below, and pick what background and foreground colors you want to associate with them.... + +/friends/edit_do.bml.background=Background + +/friends/edit_do.bml.bgcolor=Background Color: + +/friends/edit_do.bml.btn.close=Close + +/friends/edit_do.bml.btn.save=Save Changes + +/friends/edit_do.bml.btn.toggle=Toggle Preview Window + +/friends/edit_do.bml.done.head=Done? + +/friends/edit_do.bml.done.text=When done, press the "Save Changes" button below... + +/friends/edit_do.bml.error.updating=There was an error updating your friends list: + +/friends/edit_do.bml.fellowfriends.head=Fellow Friends + +/friends/edit_do.bml.fellowfriends.text=The following people have listed you as a friend. You may want to list them as your friend too. This is provided as a reference, so that you know their LiveJournal usernames. You are under no obligation to add them to your list. + +/friends/edit_do.bml.foreground=Foreground + +/friends/edit_do.bml.friend=Friend + +/friends/edit_do.bml.hover=Hover your mouse over a color to see its name + +/friends/edit_do.bml.mrcolor=Mr. Color Viewer + +/friends/edit_do.bml.name=Name + +/friends/edit_do.bml.needmore=If you need to add more friends than you have room for on this form, save the changes below, then come back to add more. + +/friends/edit_do.bml.nofriends.head=No Friends? + +/friends/edit_do.bml.nofriends.text=You do not currently have any friends defined. However, we're sure you have to have a few friends! :) Just enter their LiveJournal names below.... + +/friends/edit_do.bml.opt.addtolist=Add friend + +/friends/edit_do.bml.opt.delete=Delete? + +/friends/edit_do.bml.success.head=Success + +/friends/edit_do.bml.success.text=Your friends have been updated. You may view your newly updated friends page here. + +/friends/edit_do.bml.textcolor=Text Color: + +/friends/edit_do.bml.title=Edit Friends + +/friends/edit_do.bml.user=User + +/friends/edit_do.bml.viewer=Color Viewer + +/friends/edit_do.bml.yourfriends.head=Your Friends + +/friends/edit_do.bml.yourfriends.text=You have the following friends currently defined: + +/friends/filter.bml.editgroups=If you want to edit your friends groups, go to the [[link]] page. + +/friends/filter.bml.error.nogroups=You cannot filter your friends list because you must first setup your friend groups. + +/friends/filter.bml.error.nogroups.header=No Groups Defined + +/friends/filter.bml.reset=Clear + +/friends/filter.bml.select=Check the group(s) of friends you want to view on your friends list. + +/friends/filter.bml.select.header=Select Groups + +/friends/filter.bml.submit=View! + +/friends/filter.bml.title=Friends Filter + +/friends/index.bml.about<< +Here we have the concept of a "friends list". +By adding other users to your friends list, you can easily keep +track of what is going on in their lives from your friends page. +Friends aren't limited by individuals, you can add communities and +syndicated feeds to your friends list as well. +. + +/friends/index.bml.edit.about=Add, edit, or remove users from your friends list. + +/friends/index.bml.editgroups.about=Create, edit, or delete sub groups of your friends. + +/friends/index.bml.filter<< +These friend groups can be used to filter your friends list: you can +pick a specific friend group to view. +. + +/friends/index.bml.filter.about=Filter your friends list according to specific sub groups. + +/friends/index.bml.groups=In addition, subgroups of friends can be specified. + +/friends/index.bml.security=Your friends list is also used for posts with restricted access. + +/friends/index.bml.security.custom=With "Custom" posts, you can specify which friend groups can view your post. + +/friends/index.bml.security.header=Security + +/friends/index.bml.security.only=With "Friends-Only" posts, all of the other users on your friends list can view your post. + +/friends/index.bml.title=Friends Tools + +/friends/index.bml.tools=Tools + +/go.bml.defaultbody=No parameters given. + +/go.bml.defaulttitle=Error + +/go.bml.error.noentry.next=There is no entry following this one. + +/go.bml.error.noentry.prev=There is no entry preceding this one. + +/go.bml.error.noentrytitle=No Entry + +/go.bml.error.redirkey=Bogus redir_key. + +/go.bml.error.usernotfound=User not found. + +/interests.bml.add.added.head=Added! + +/interests.bml.add.added.text=The interest has been added to your list. + +/interests.bml.add.btn.text=Add [[interest]] + +/interests.bml.add.confirm.head=Confirm + +/interests.bml.add.confirm.text=To add [[interest]] as an interest, click the button below. + +/interests.bml.add.toomany.head=Sorry... + +/interests.bml.add.toomany.text=You already have [[maxinterests]] interests defined. + +/interests.bml.addint=If you're also interested in this and would like to be added to this list, click here. + +/interests.bml.btn.switch=Switch + +/interests.bml.communities.head=Relevant Communities + +/interests.bml.communities.text=The following communities are also interested in "[[interest]]". + +/interests.bml.count=Count + +/interests.bml.enmasse.body.other<< +Below are the interests of [[user]]. Check the boxes next to the interests you would like +to add to your own, and uncheck the checkboxes next to the interests you would like to remove +from your own. When you're done, click "Save Changes". +. + +/interests.bml.enmasse.body.other_authas<< +Below are the interests of [[user]]. Check the boxes next to the interests you would like +to add to those of [[target]], and uncheck the checkboxes next to the interests you would +like to remove. When you're done, click "Save Changes". +. + +/interests.bml.enmasse.body.you<< +Uncheck the checkboxes next to the interests you would like to remove. +When you're done, click "Save Changes". +. + +/interests.bml.enmasse.btn=Show list + +/interests.bml.enmasse.header=Add/Remove interests + +/interests.bml.enmasse.intro=Modify your interests based on those of: + +/interests.bml.error.add.mustlogin=You have to be logged in to add an interest this way. + +/interests.bml.error.enmasse.mustlogin=You must be logged in to use this feature. + +/interests.bml.error.enmasse.noaccess=You do not appear to have access to the journal [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Interest wasn't found. + +/interests.bml.error.nointerests=The selected user does not exist or has not specified any interests. + +/interests.bml.findsim.searchwait=Please note: Search will take several seconds. Be patient. + +/interests.bml.findsim_do.account.notallowed=Sorry, your account type doesn't let you use this tool. + +/interests.bml.findsim_do.magic=Magic
Index + +/interests.bml.findsim_do.magic.head=Magic Index? + +/interests.bml.findsim_do.magic.text=Each matching user gets computed a magic index, which is a weighting of two factors: the raw number of like interests, and some extra points for sharing uncommon interests. + +/interests.bml.findsim_do.nomatch.head=No Matches + +/interests.bml.findsim_do.nomatch.text=No users are similar to [[user]]. + +/interests.bml.findsim_do.notdefined=User [[user]] has no defined interests. + +/interests.bml.findsim_do.similar.head=Similar Users + +/interests.bml.findsim_do.similar.text=The following are the most related users to [[user]] + +/interests.bml.finished.about=When you're done, press the "Save Changes" button below: + +/interests.bml.finished.header=Done? + +/interests.bml.finished.save_button=Save Changes + +/interests.bml.interest=Interest + +/interests.bml.interested.btn.find=Find + +/interests.bml.interested.in=Find people interested in: + +/interests.bml.interests.findsim=Find users with interests similar to those of: + +/interests.bml.interests.head=Interests + +/interests.bml.interests.text=Here are some fun things you can do with interests. + +/interests.bml.interests.viewpop=View popular interests + +/interests.bml.login.enterinfo=Enter your username and password to modify your interests. + +/interests.bml.login.proceed=Proceed... + +/interests.bml.match=[[count]] match: + +/interests.bml.matches=[[count]] matches: + +/interests.bml.morestuff=More fun stuff can be found on the interests page. + +/interests.bml.nointerests.text=Don't have any interests listed? Add some by going to the Edit Personal Info & Settings page. + +/interests.bml.popular.disabled=Sorry, the popular interests feature has been disabled. + +/interests.bml.popular.head=Popular Interests + +/interests.bml.popular.text=The following are the most popular interests. + +/interests.bml.results.added=The interests you selected were successfully added to your interests list. + +/interests.bml.results.both=The interests you selected were successfully added to your interests list, and those you deselected were removed. + +/interests.bml.results.deleted=The interests you deselected were successfully removed from your interests list. + +/interests.bml.results.del_and_toomany<< +The interests you deselected were successfully removed from your interests list. +However, you selected too many interests to add. You may only have [[intcount]] +interests in total. None of the selected interests were added to your interests list. +You may wish to go back and try again, selecting fewer interests to add. +. + +/interests.bml.results.goback=You may wish to go back to [[user]]'s profile which you were viewing previously. + +/interests.bml.results.header=Results + +/interests.bml.results.message=See your updated profile page. + +/interests.bml.results.nothing=You did not make any changes. + +/interests.bml.results.toomany<< +You selected too many interests to add. You may only have [[intcount]] interests +in total. None of the selected interests were added to your interests list. +You may wish to go back and try again, selecting fewer interests to add. +. + +/interests.bml.title=Interests + +/interests.bml.toomany.body=There are [[intcount]] people and/or communities listing this as an interest. A list will not be shown. + +/interests.bml.toomany.head=Many matches + +/interests.bml.users.head=Interested users + +/interests.bml.users.text=The following users are also interested in [[interest]]. + +/login.bml.bindip.label=Bind to IP address: + +/login.bml.bindip.no=No (works with all ISPs) + +/login.bml.bindip.yes=Yes (safer) + +/login.bml.error.mustenterusername=You must enter a username. + +/login.bml.expire.btn.neverexpire=Change expiration mode to NEVER + +/login.bml.expire.btn.sessiononly=Change expiration mode to SESSION ONLY + +/login.bml.expire.neverexpire.text=Your login will never expire, so if you're at a public internet terminal, a school, library, or other place where people may be using this computer shortly, make sure you log out when you're done! Or, change your login mode to expire when you close your browser: + +/login.bml.expire.sessiononly.text=Your login will expire after you close your browser. If this is your own computer and you're the only user, you may want to set your login expiration such that it never expires: + +/login.bml.links.head=Links + +/login.bml.links.link1=Your friends page. + +/login.bml.links.link2=Your to-do list. + +/login.bml.links.text=In the future this page will have all sorts of links and relevant information, but for now here are a few places you may want to go: + +/login.bml.loggedin.head=Logged in! + +/login.bml.loggedin.text=You are now logged in. + +/login.bml.login.btn.changeopts=Change Options + +/login.bml.login.btn.login=Login... + +/login.bml.login.expiration=Expiration: + +/login.bml.login.forget=Forget? + +/login.bml.login.head=Login + +/login.bml.login.never=Never + +/login.bml.login.otheropts=Other Options: + +/login.bml.login.password=Password: + +/login.bml.login.text1=To login to [[sitename]], enter your username and password below. New Users: To create an account, go here. + +/login.bml.login.text2=By default your login will expire when you close your browser, which is best on public computers. However, if you're the only user of your computer and nobody else has access to it, you may choose to remain logged in forever. + +/login.bml.login.text3=[[username]], you are now logged in to [[sitename]]. + +/login.bml.login.username=Username: + +/login.bml.login.whenbrowsercloses=When browser closes + +/login.bml.logout.btn=Log Out + +/login.bml.title=Login + +/login.bml.whylogin.benefit1=You won't have to enter your username/password anywhere on the site anymore. + +/login.bml.whylogin.benefit2=You'll be able to view "protected" journal entries from your friends that give you access to read them. + +/login.bml.whylogin.benefit3=A lot of features are only visible or accessible when you're logged in. + +/login.bml.whylogin.head=Why Login? + +/login.bml.whylogin.text=Here are some of the main benefits of logging in: + +/logout.bml.already.head=Already logged out + +/logout.bml.already.text=You are already logged out. + +/logout.bml.killall.btn=Expire all my sessions + +/logout.bml.killall.head=Other sessions + +/logout.bml.killall.text=You have other active sessions, from other computers. Do you want to expire all your sessions, and not just this one? + +/logout.bml.loggedout.already=Already logged out. + +/logout.bml.loggedout.head=Logged out + +/logout.bml.loggedout.killedall=All your sessions have been expired. + +/logout.bml.loggedout.success=Logged out. + +/logout.bml.loggedout.text=You are now logged out. + +/logout.bml.logout.btn=Log out + +/logout.bml.logout.head=Log out? + +/logout.bml.logout.text=Click the button below to log out. + +/logout.bml.title=Logout + +/lostinfo.bml.btn.proceed=Proceed + +/lostinfo.bml.enter_email=Enter your email address: + +/lostinfo.bml.enter_email_optional=Email address: (optional) + +/lostinfo.bml.enter_username=Enter your username: + +/lostinfo.bml.error.commnopassword=The account you are trying to retrieve the password for is a community. This kind of account does not have a password to retrieve. All community management can be accomplished by logging in as a maintainer of the community. + +/lostinfo.bml.error.no_email=You must enter an email address in order to recover your username. + +/lostinfo.bml.error.purged=Cannot retrieve password for a deleted account once it has been purged. + +/lostinfo.bml.error.renamed=Cannot retrieve password for a renamed account. + +/lostinfo.bml.error.syndicated=The account you are trying to retrieve the password for is a syndicated account. This kind of account does not have a password to retrieve. + +/lostinfo.bml.error.sysbanned=Your account is not allowed to e-mail passwords. + +/lostinfo.bml.error.toofrequent=You are trying to send too many e-mails at once. You may only request three lost information e-mails within twenty-four hours. + +/lostinfo.bml.lostpassword.text=If you've lost your password, enter your username and optionally, the email address you'd like the password sent to. Note that the email address must be one you've used at LiveJournal before and had confirmed at one point. If you leave the email field blank, it'll be mailed to your current address. + +/lostinfo.bml.lostpassword.title=Lost your password? + +/lostinfo.bml.lostusername.text=If you've lost your username, enter your email address and we'll send you your username. + +/lostinfo.bml.lostusername.title=Lost your username? + +/lostinfo.bml.title=Lost Information + +/lostinfo_do.bml.error.no_usernames_for_email=No username(s) for this email address: [[address]] . + +/lostinfo_do.bml.error1.text=You never used that email address with this account or it was never validated. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** This is an automated email. You do not need to respond to it. *** + +This is your requested password reminder from [[sitename]]. +Below is your username, password, and email address your journal is +registered under. + + Username: [[username]] + Password: [[password]] + EMail Address: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=To validate your email address, go here: + +/lostinfo_do.bml.lostpasswordmail.part3<< +This information was requested on the website from [[remoteip]]. + +If you didn't request to have this password emailed to you, don't panic. +After all, you're the one who's seeing this email, and not the other person. +It's possible that the user who made the request is mistaken and +believes that he or she controls this username. It's also possible that +someone made a typo in a username or email address. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4= + +/lostinfo_do.bml.lostpasswordmail.part5<< +Useful links: + + Your LiveJournal: + [[journalurl]] + + Update your journal online: + [[updateurl]] + +Regards, +The site team + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Lost Password + +/lostinfo_do.bml.password_mailed.text=Success. Your password has been mailed. + +/lostinfo_do.bml.password_mailed.title=Password mailed! + +/lostinfo_do.bml.title=Lost Information + +/lostinfo_do.bml.username_mailed.text=Success. Your username has been mailed. + +/lostinfo_do.bml.username_mailed.title=Username mailed! + +/manage/index.bml.about=Managing your account is easy. Just choose from the following areas below: + +/manage/index.bml.communities=Create and manage your own communities: + +/manage/index.bml.communities.create.about=Create a new community + +/manage/index.bml.communities.header=Communities + +/manage/index.bml.communities.invites.about=View any pending invitations you have received to join communities. + +/manage/index.bml.communities.manage.about=Manage your communities' settings and members + +/manage/index.bml.customization=Customize the look of your journal pages: + +/manage/index.bml.customization.advanced=Advanced Customization + +/manage/index.bml.customization.advanced.about=Browse, create, and edit your S2 layouts and styles + +/manage/index.bml.customization.customize=Customize Journal + +/manage/index.bml.customization.customize.about=Change the appearance of your journal + +/manage/index.bml.customization.header=Customization + +/manage/index.bml.customization.links=Links List + +/manage/index.bml.customization.links.about=Create a list of links to appear in your journal + +/manage/index.bml.customization.modify.about=Modify your journal's display properties + +/manage/index.bml.customization.moodtheme.editor=Create and edit your custom mood themes + +/manage/index.bml.customization.moodtheme.editor.header=Mood Theme Editor + +/manage/index.bml.customization.moodtheme.header=Mood Themes + +/manage/index.bml.customization.moodtheme.set=Select which mood theme set your journal will use + +/manage/index.bml.customization.moodtheme.set.header=Set Your Mood Theme + +/manage/index.bml.customization.s1.header=S1 Style System + +/manage/index.bml.customization.s2.header=S2 Style System + +/manage/index.bml.entries=Work with entries you have made in your account's journal: + +/manage/index.bml.entries.edit.about=Edit and delete entries in your journal + +/manage/index.bml.entries.header=Journal Entries + +/manage/index.bml.entries.memories.about=View and work with your memorable posts + +/manage/index.bml.friends=Manage your friends and friend groups, or filter your friends page according to your saved friend groups: + +/manage/index.bml.friends.edit.about=Add, edit, or remove users from your friends list + +/manage/index.bml.friends.filter=Filter Friends Page + +/manage/index.bml.friends.filter.about=Filter your friends list to display a specific friend group + +/manage/index.bml.friends.groups.about=Create, edit, or delete subgroups of your friends list + +/manage/index.bml.friends.header=Friends + +/manage/index.bml.information=Choose what information is displayed on your account: + +/manage/index.bml.information.changepass=Change Account Password + +/manage/index.bml.information.changepass.about=Change your account's password + +/manage/index.bml.information.editinfo.about=Edit your account information and various options + +/manage/index.bml.information.emailpost=Email Gateway Settings + +/manage/index.bml.information.emailpost.about=Manage your email addresses and PIN for post-by-email support + +/manage/index.bml.information.header=Account Information + +/manage/index.bml.information.siteopts.about=Select your preferred site layout & language + +/manage/index.bml.information.status=Account Status + +/manage/index.bml.information.status.about=Set your account's activation status + +/manage/index.bml.login<< +The following links will navigate you to pages where your login information +is required. To save yourself some time, you can log in beforehand. +. + +/manage/index.bml.title=Manage Accounts + +/manage/index.bml.userpictures=Upload and manage user picture icons for your account: + +/manage/index.bml.userpictures.edit.about=Upload and Manage Your User Picture Icons + +/manage/index.bml.userpictures.header=User Picture Icons + +/manage/invites.bml.abilities.title=Abilities + +/manage/invites.bml.accept=Accept + +/manage/invites.bml.accepted.body=You have joined the following communities, with the mentioned abilities: + +/manage/invites.bml.accepted.title=Invitations Accepted + +/manage/invites.bml.actions.title=Actions + +/manage/invites.bml.back=Manage invites + +/manage/invites.bml.community.title=Community + +/manage/invites.bml.decline=Decline + +/manage/invites.bml.fromline=From [[user]] ([[date]]) + +/manage/invites.bml.label.admin=Maintainer + +/manage/invites.bml.label.member=Member + +/manage/invites.bml.label.moderate=Moderator + +/manage/invites.bml.label.post=Can Post + +/manage/invites.bml.label.preapprove=Unmoderated + +/manage/invites.bml.manage=Manage account + +/manage/invites.bml.none.body=You have no pending community invitations at this time. + +/manage/invites.bml.none.title=Nothing Pending + +/manage/invites.bml.rejected.body=You have rejected the following community invitations: + +/manage/invites.bml.rejected.title=Invitations Rejected + +/manage/invites.bml.submit=Submit Selections + +/manage/invites.bml.title=Manage Community Invitations + +/manage/invites.bml.undecided.body=You have not decided on actions for the following invitations: + +/manage/invites.bml.undecided.title=Invitations Still Pending + +/manage/links.bml.about=Use the form below to create a list of links to appear on your journal. Links will only appear if this feature is supported by your S2 style. + +/manage/links.bml.about.blank=To create a blank line, enter a "-" for the title. + +/manage/links.bml.about.heading=To create a heading, enter a title with no URL. + +/manage/links.bml.about.reorder=To reorder links in the list, modify the order number at left (decimal numbers are ok). + +/manage/links.bml.error.s2required=The link list is only available on supported S2 styles. To switch to S2, see the [[link]] page. + +/manage/links.bml.error.s2required.header=S2 Required + +/manage/links.bml.success=Success! Your links have been saved. + +/manage/links.bml.title=Links List + +/manage/pubkey.bml.error.invalidkey=That doesn't appear to be a valid PGP/GPG key. + +/manage/pubkey.bml.error.notconfigured=This site is not configured with PGP support. + +/manage/pubkey.bml.header=PGP/GPG key + +/manage/pubkey.bml.info=Publishing your public key allows others to view it via your userinfo page, and you can post to the email gateway with signed messages. See instructions here. + +/manage/pubkey.bml.pastekey=Paste your key in its entirety (ascii armored format) into the below field: + +/manage/pubkey.bml.save=Save + +/manage/pubkey.bml.successhead=Success + +/manage/pubkey.bml.successtext=Your public key been saved. You may view it here. + +/manage/pubkey.bml.title=Set Public Key + +/manage/pubkey.bml.whatis=Don't know what a public key is? Need help exporting your key? Read more about PGP and GPG. + +/manage/siteopts.bml.btn.lang=Switch Language + +/manage/siteopts.bml.btn.scheme=Switch Scheme + +/manage/siteopts.bml.head.lang=Select Your Language + +/manage/siteopts.bml.head.scheme=Select Your Preferred Scheme + +/manage/siteopts.bml.scheme.preview=[Preview of [[title]] scheme] + +/manage/siteopts.bml.title=Browse Preferences + +/manage/tags.bml.addnew=Add new tags here! + +/manage/tags.bml.button.delete=Remove selected tag(s) + +/manage/tags.bml.button.rename=Rename + +/manage/tags.bml.button.show=Show journal entries + +/manage/tags.bml.confirm.delete=Are you sure you want to remove the selected tags? This operation is not reversible. + +/manage/tags.bml.hint.create=You can create multiple tags by separating them with commas. + +/manage/tags.bml.hint.delete=Remove all references to the selected tag(s). + +/manage/tags.bml.hint.entries=Display journal entries marked with the selected tag(s). + +/manage/tags.bml.hint.rename=Change a tag name. + +/manage/tags.bml.intro=Use this page to review and edit tags you have defined. + +/manage/tags.bml.label.tags=Tag properties + +/manage/tags.bml.label.yours=Your tags + +/manage/tags.bml.none=You haven't created any tags yet. + +/manage/tags.bml.sort.a=sort: alphabetically or by usage + +/manage/tags.bml.sort.b=sort: alphabetically or by usage + +/manage/tags.bml.title=Tags Management + +/meme.bml.meme.disabled=The site administrator has disabled this feature. + +/modify.bml.title=Modify Journal + +/modify_do.bml.availablestyles.disabledstyles=Disabled Styles: + +/modify_do.bml.availablestyles.head=Available Styles + +/modify_do.bml.availablestyles.userstyles=User Styles: + +/modify_do.bml.colortheme.about=Here you can select what color theme will be applied to the layout options you pick above. Or, if you don't like the provided colors, specify your own! If you come up with something really sexy looking, let us know and we'll name a theme after it. + +/modify_do.bml.colortheme.area.head=Usage Area + +/modify_do.bml.colortheme.color.head1=Color + +/modify_do.bml.colortheme.color.head2=(#rrggbb or name) + +/modify_do.bml.colortheme.customcolors=Custom Colors + +/modify_do.bml.colortheme.defaulttheme=Default Theme + +/modify_do.bml.colortheme.head=Color Theme + +/modify_do.bml.domainalias.about=If you have a domain name already registered (or which you're planning on registering) and would like it to automatically load your LiveJournal, enter it here: + +/modify_do.bml.domainalias.domainname=Domain name: + +/modify_do.bml.domainalias.example=Example: my-journal.com + +/modify_do.bml.domainalias.head=Domain Aliasing + +/modify_do.bml.domainalias.helptext=For this to work, you'll need to arrange to have your domain name's DNS point to the same IP address of [[sitename]]. + +/modify_do.bml.done.btn.savechanges=Save Changes + +/modify_do.bml.done.head=Done? + +/modify_do.bml.done.text=When done, press the "Save Changes" button below... + +/modify_do.bml.error.dupdomainalias=Another user has already registered themselves as using your selected domain alias. + +/modify_do.bml.error.stylenotavailable=One of the styles you've selected is not available. This is either the result of somebody deleting the style, or you trying to pick one that you don't have access to. + +/modify_do.bml.friends.about=Here are options that control how your friends page looks. + +/modify_do.bml.friends.head=Friends View + +/modify_do.bml.friends.opt.usesharedpic.about=This option controls what picture you see on your friends page when a user posts in a shared or community journal. If you check it, then you'll see the community's icon. If you leave it unchecked, then you'll see the person that's actually posting's personal user icon. + +/modify_do.bml.friends.opt.usesharedpic.head=Use shared journal pictures instead of poster's user picture + +/modify_do.bml.journaloptions.about=From here you can customize the look of your LiveJournal pages. If you're really curious how everything works, read the developer information. Otherwise, we'll assume you're satisfied with the basic options below: + +/modify_do.bml.journaloptions.head=Journal Options + +/modify_do.bml.journalstatus.about=If you want to delete or undelete your journal, this is where you do it. Once you delete your journal you have 30 days to undelete it, just in case you change your mind. After 30 days, the journal will be permanently deleted and there will be no way to recover it. + +/modify_do.bml.journalstatus.head=Journal Activation Status + +/modify_do.bml.journalstatus.select.activated=Activated + +/modify_do.bml.journalstatus.select.deleted=Deleted + +/modify_do.bml.journalstatus.select.head=Status: + +/modify_do.bml.journalstatus.select.suspended=Suspended + +/modify_do.bml.moodicons.about=When posting journal entries you can also specify your current mood. Different users have submitted different sets of mood icons that you can use. Or, select "None" if you don't want any pictures beside your moods. (or, you don't even have to use the Current Mood feature at all.) + +/modify_do.bml.moodicons.head=Mood Icons + +/modify_do.bml.moodicons.opt.forcefriends.about=Force this mood theme for all friends on your friends page + +/modify_do.bml.moodicons.personal=Personal Themes: + +/modify_do.bml.moodicons.preview=preview + +/modify_do.bml.moodicons.select=Select mood icon set: + +/modify_do.bml.overrides.about=You can ignore this section. This is for tweaking very specific things about your page layout. See the developer section for details. Also note that overrides are for overriding only one or two things about a style. If you'd like to override everything, you need to create your own style. + +/modify_do.bml.overrides.box.head=Overrides: + +/modify_do.bml.overrides.head=Style Overrides + +/modify_do.bml.overrides.note=Please note that not all style variables can be overridden. See the documentation for more details. + +/modify_do.bml.overrides.warning=THIS IS NOT WHERE YOU TYPE YOUR JOURNAL!! + +/modify_do.bml.pagelayoutstyle.about=Setting this controls how your journal is laid out on the screen. + +/modify_do.bml.pagelayoutstyle.head=Page Layout Style + +/modify_do.bml.pagelayoutstyle.warning=Your account type only permits you to select between a small number of default styles. + +/modify_do.bml.success.head=Success + +/modify_do.bml.success.text=Your journal settings have been updated. You can view your journal here. + +/multisearch.bml.formaterror=Format Error + +/multisearch.bml.noaddress.text=You did not enter an email address. + +/multisearch.bml.noaddress.title=No Address + +/multisearch.bml.nointerest.text=You did not enter an interest. + +/multisearch.bml.nointerest.title=No Interest + +/multisearch.bml.nomatch.text=There were no results for the criteria you specified. + +/multisearch.bml.nomatch.title=No Match + +/multisearch.bml.region.bodytext<< +You can search by region in one of the following formats: +
    +
  • Country
  • +
  • City *
  • +
  • City, State *
  • +
  • State, Country
  • +
  • City, State, Country
  • +
+Notes: +
    +
  • * searching for only a city or a city and state defaults to assuming the country is the United States.
  • +
  • Country can either be the country's full name, or its two letter country code
  • +
+If you want to do a different type of search, check out the directory search. +. + +/multisearch.bml.region.head=Search by Region + +/poll/create.bml.button.editpoll=Edit Poll + +/poll/create.bml.button.insert=Insert + +/poll/create.bml.button.postpoll=Post Poll + +/poll/create.bml.button.preview=Preview Poll + +/poll/create.bml.button.seecode=See Code + +/poll/create.bml.button.startover=Start Over + +/poll/create.bml.elements.limitreached=Element limit reached + +/poll/create.bml.error.accttype=Your account type does not permit you to use the poll creation feature. + +/poll/create.bml.error.allitemsblank=All items cannot be blank. + +/poll/create.bml.error.notext=You need text explaining your question + +/poll/create.bml.error.parsing=Error parsing poll: + +/poll/create.bml.error.pqmaxlengthinvalid=Maxlength attribute on lj-pq text tags must be an integer from [[min]] to [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Size attribute on lj-pq text tags must be an integer from [[min]] to [[max]]. + +/poll/create.bml.error.scalemaxlessmin=Scale 'from' value must be less than 'to' value. + +/poll/create.bml.error.scalemininvalid=Scale increment must be at least [[min]]. + +/poll/create.bml.error.scaletoobig=Limit of [[max]] selections (to-from)/by > 20 + +/poll/create.bml.error.texttoolong=The text of your option is too long and has been truncated. + +/poll/create.bml.haserrors=You have one or more errors with your poll. Please scroll down for more details. + +/poll/create.bml.insertquestion=Insert question here: + +/poll/create.bml.options=Options: + +/poll/create.bml.options.limitreached=Option limit reached + +/poll/create.bml.pollname=Poll Name: (opt.) + +/poll/create.bml.preview.desc=Below is a preview of your poll. This is exactly how it will look once it is placed on your journal. Use the buttons below to go back and make changes or post this poll to your journal. + +/poll/create.bml.preview.options=Options + +/poll/create.bml.properties=Poll Properties + +/poll/create.bml.question=Question: + +/poll/create.bml.questionnum=Question #[[num]] + +/poll/create.bml.questions=Poll Questions + +/poll/create.bml.title=Poll Creator + +/poll/create.bml.type.check=Check Boxes + +/poll/create.bml.type.drop=Drop-down box + +/poll/create.bml.type.radio=Radio Buttons + +/poll/create.bml.type.scale=Scale + +/poll/create.bml.type.text=Text entry + +/poll/create.bml.whoview=Who can view this poll? + +/poll/create.bml.whovote=Who can vote in this poll? + +/poll/index.bml.discuss=Discuss Results + +/poll/index.bml.error.cantview=Sorry, you're not permitted to see this poll. + +/poll/index.bml.error.postdeleted=Owning post deleted, so poll no longer accessible. + +/poll/index.bml.filloutpoll=Fill out Poll + +/poll/index.bml.gotocreate=This is the address to participate in a poll. You've stumbled onto an address which does nothing right now. If you'd like, you can create a new poll. + +/poll/index.bml.pollnotfound=Poll not found. + +/poll/index.bml.submitted.head=Thanks + +/poll/index.bml.submitted.text=Your poll answers have been submitted. + +/poll/index.bml.submitted.title=Submitted! + +/poll/index.bml.title=Poll + +/poll/index.bml.viewresults=View Poll Results + +/pubkey.bml.error.notconfigured=This site is not configured with PGP support. + +/pubkey.bml.error.nousername=No username specified. + +/pubkey.bml.info.desc=Don't know what a public key is? Read more about PGP and GPG. + +/pubkey.bml.info.head=Information + +/pubkey.bml.info.upload=Want to upload your key? Click here. + +/pubkey.bml.label=Public key for [[user]]: + +/pubkey.bml.nokey=[[user]] has not uploaded a public key yet. + +/pubkey.bml.title=View Public Key + +/register.bml.ask.body=Click the button below to have send a validation email to [[email]]. + +/register.bml.ask.button=Send + +/register.bml.ask.header=Validate Email + +/register.bml.asterisk.comment=(Please note that accounts marked with an * have not yet been validated) + +/register.bml.asterisk.name=* [[journal]] + +/register.bml.email.body|notes=This string is used to create an option in the "Work as user" drop down list to allow a user to view all of their journals. The * signifies that the acount, specified by [[journal]], is not validated yet. +/register.bml.email.body<< +This is the validation email as you have requested. +To complete validating your account, please visit this URL: + + [[conflink]] + +You may have to copy and paste this link into your browser's window. + +Sincerely, +[[sitename]] +[[siteroot]] +. + +/register.bml.email.subject=Validate Email + +/register.bml.error.emailchanged=This verification link is out of date. Please request a new verification email. + +/register.bml.error.invalidcode=Invalid validation code. + +/register.bml.error.useralreadyvalidated=The email address for [[user]] has already been validated. + +/register.bml.error.usernotfound=User not found. + +/register.bml.new.bodyuser=Thanks! The email address for [[user]] has now been verified. From here, you may be interested in doing the following things: + +/register.bml.new.editinfo=Edit Information -- Fill out your user profile and set various settings. + +/register.bml.new.header=Success + +/register.bml.new.login=Login -- So you don't have to enter your username and password everywhere. + +/register.bml.new.modify=Modify Journal -- Modify the look of your journal. + +/register.bml.new.update=Update Journal -- Write in your journal. + +/register.bml.sent.body=A validation email has been sent to [[email]]. In order to complete validation, you need to click the link in that email. + +/register.bml.sent.header=Success + +/register.bml.title=Validate Email + +/register.bml.trans.body=Your new email address has been validated. + +/register.bml.trans.header=Success + +/styles/create.bml.choosebase=Choose base style to start with and edit: + +/styles/create.bml.createstyle.head=Create a Style + +/styles/create.bml.createstyle.text=From here you can create a new personal-style, useful if you're going to either embed your journal in your homepage or you want to make a public style that everybody can use and you need to work on it here first, rather than in your overrides section. + +/styles/create.bml.enterstyleid=Or, enter a non-system public Style ID#: + +/styles/create.bml.noneorother=(None, or other below:) + +/styles/create.bml.selecttype.head=Select Style Type + +/styles/create.bml.selecttype.text=A style only affects one view type. If you want to create a matching set of styles for your journal, you have to create your style for each view type. + +/styles/create.bml.submit=Create Style + +/styles/create.bml.title=Create Style + +/styles/create_do.bml.editstyle=Edit Style + +/styles/create_do.bml.error.accounttype=Your account type doesn't permit you to make styles. + +/styles/create_do.bml.error.invalidview=You did not select a valid style type. + +/styles/create_do.bml.error.styleexists=You already have a style of this type named [[des]]. If you really want to create a new style of type [[view]], then go modify your old [[view]] style, change its name, and then come back here to create a new style of this type. + +/styles/create_do.bml.error.stylenotfound=The style you're trying to make a new style from ([[baseid]]) does not seem to exist. + +/styles/create_do.bml.error.stylenotpublic=The style you're trying to make a new style from ([[baseid]]) is not public, so you cannot copy it. + +/styles/create_do.bml.success.head=Success + +/styles/create_do.bml.success.text=Your style has been created and has been temporarily named [[des]]. You can begin editing it by pressing the button below. + +/styles/create_do.bml.title=Create Style + +/styles/index.bml.about<< +

This section of the site allows you to create, edit and delete +customised styles. This allows you to control the look of your account to a great extent, +whether you want to make it look like your website, or just feel like being different. +

+

You can also create embedded styles which, rather than +creating a full page, include only the entries and leave +you to embed your journal in another site.

+. + +/styles/index.bml.about.header=Creating and Using Custom Styles + +/styles/index.bml.nav.browse=Style Browser + +/styles/index.bml.nav.browse.about=The style browser lets you browse through public styles created by other users. + +/styles/index.bml.nav.create=Create a new style + +/styles/index.bml.nav.create.about=Create a new style from scratch, or base your style on an existing public style. + +/styles/index.bml.nav.edit=Edit or Delete an existing style + +/styles/index.bml.nav.edit.about<< +You may only edit styles “owned” by your account. In order to customize +a system style, you must first create a new style based on that system style. +. + +/styles/index.bml.nav.modify=Modify your account + +/styles/index.bml.nav.modify.about=Change your account's default style, either one of the system provided styles + +/styles/index.bml.title=Custom Styles + +/support/append_request.bml.back.requests=Back to the list of open requests. + +/support/append_request.bml.back.support=Back to the support area. + +/support/append_request.bml.bounce.noemail=No email address specified for bounce. + +/support/append_request.bml.bounce.notauth=You are not authorized to bounce this request. + +/support/append_request.bml.bounce.toomany=You can only send to up to 5 email addresses. You have specified more than 5. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=This support request has since been closed. + +/support/append_request.bml.closed.title=Closed + +/support/append_request.bml.internal.approve=To approve an answer, you must select "Internal Comment / Action" and optionally explain why you're approving it. + +/support/append_request.bml.internal.changecat=To change a request's category, you must select "Internal Comment / Action" and optionally explain why you're changing it. + +/support/append_request.bml.internal.changesum=To change the summary of a request, you must select "Internal Comment / Action" and enter in the new summary. + +/support/append_request.bml.internal.touch=To touch a request, you must select "Internal Comment / Action" and explain why you're touching it. + +/support/append_request.bml.invalid.blank=Your message was blank. Please type at least something in the message field. + +/support/append_request.bml.invalid.noanswer=Invalid screened response to approve. + +/support/append_request.bml.invalid.nocat=That category doesn't seem to exist. + +/support/append_request.bml.invalid.noid=This action requires a support request ID. + +/support/append_request.bml.invalid.nosummary=You must enter a request summary. + +/support/append_request.bml.invalid.type=Invalid Reply Type. + +/support/append_request.bml.logged.text=Your action/comment/response has been recorded. Thanks. + +/support/append_request.bml.logged.title=Success + +/support/append_request.bml.login.required=You must login to help people out. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Append Comment/Response + +/support/append_request.bml.unknown.request=Unknown support request. + +/support/encodings.bml.edit.header=I cannot edit my entries in the web interface! + +/support/encodings.bml.edit.text<< +Short answer: (applicable if you write your journal in English): Go to your +personal settings page. Find an option +neat the bottom of the page that is called Auto-convert older entries from:. Choose +"Western European (Windows)" from the pull-down menu and save your settings. Your entries should +now be editable. p?> + +Long answer: In order to allow you to edit a non-Unicode entry, LiveJournal code needs to +know which encoding that entry has been posted in. For users of English and other West European +languages, this will normally be "Western European (Windows)", although if that doesn't work well +for quote characters and other similar meta-characters, try "Western European (ISO)". Users +writing in other languages should select their encoding; if it isn't in the supplied list, +contact Support and explain the problem. p?> + + +. + +/support/encodings.bml.editcl.header=I cannot edit my entries in the client program! + +/support/encodings.bml.editcl.text<< + +. + +/support/encodings.bml.groups.header=I cannot edit my friend lists with my client program! + +/support/encodings.bml.groups.text<< +group editing page and then use your client program. p?> +. + +/support/encodings.bml.overview.header=What is this all about? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Still stumped? + +/support/encodings.bml.still.text=Support Area. p?> + +/support/encodings.bml.title=Encodings + +/support/faqbrowse.bml.backfaq=Back to the FAQ. + +/support/faqbrowse.bml.backfaqcat=Back to the parent FAQ category. + +/support/faqbrowse.bml.backsupport=Back to the support area. + +/support/faqbrowse.bml.edit.faq=Edit this FAQ + +/support/faqbrowse.bml.error.nofaq=The specified FAQ does not exist. + +/support/faqbrowse.bml.lastupdated=Last Updated: + +/support/faqbrowse.bml.title_cat=FAQ - [[catname]] + +/support/faqbrowse.bml.title_num=FAQ Question #[[num]] + +/support/help.bml.interim=The support queue is intended for use by people with support privileges. + +/support/see_overrides.bml.error.noprivs=Only users with the supportviewinternal or supporthelp privilege can view another user's overrides. + +/support/see_overrides.bml.error.nos1=This user is not using S1. + +/support/see_overrides.bml.header=Overrides for : + +/support/see_overrides.bml.nooverrides=No overrides found for . + +/support/see_overrides.bml.title=User Overrides + +/syn/index.bml.account=Account: + +/syn/index.bml.add=Add Feed + +/syn/index.bml.add.byurl.text=Add a feed to your friends list by entering the feed URL below. + +/syn/index.bml.add.byurl.title=Add Feed by URL + +/syn/index.bml.add.pop.text=The following are some popular feeds you're not currently watching: + +/syn/index.bml.add.pop.title=Add Popular Feed + +/syn/index.bml.add.selected=Add Selected + +/syn/index.bml.back=Back + +/syn/index.bml.create=Create Feed + +/syn/index.bml.create.name=The URL you have entered is not currently being syndicated on this site. Please enter an account name to use to syndicate this feed. + +/syn/index.bml.error.nocreate=The URL you have entered is not currently being syndicated on this site. Your account type does not have the ability to create new syndicated feeds. + +/syn/index.bml.error.unknown=Unknown Error + +/syn/index.bml.feed.url=Feed URL: + +/syn/index.bml.invalid.accountname=Invalid account name. + +/syn/index.bml.invalid.cantadd=You can't add RSS feeds from this site. + +/syn/index.bml.invalid.http.text=There was an error retrieving this URL. The server may be down or the content unavailable at this time. Please verify the URL you have provided and try again. + +/syn/index.bml.invalid.http.title=Error retrieving content + +/syn/index.bml.invalid.inuse.text=That account name is already in use. + +/syn/index.bml.invalid.inuse.title=Username in use + +/syn/index.bml.invalid.needname.text=To add a syndicated account that doesn't exist, go back and give it an account name. + +/syn/index.bml.invalid.needname.title=Need an account name + +/syn/index.bml.invalid.needurl=You must enter either a syndicated account's username or URL to add a new feed. + +/syn/index.bml.invalid.notexist=No syndicated account exists with that username. + +/syn/index.bml.invalid.notrss.text=The URL provided does not appear to contain XML formatted data. + +/syn/index.bml.invalid.notrss.title=Data not XML formatted + +/syn/index.bml.invalid.port=Non-standard port number not allowed + +/syn/index.bml.invalid.reserved=This account name is reserved. Please choose a different account name. + +/syn/index.bml.invalid.submission=Invalid form submission + +/syn/index.bml.invalid.url=The URL you have typed is invalid. Please make sure you have typed the URL correctly and try again. + +/syn/index.bml.loginrequired.text=To manage your syndicated accounts, first login. + +/syn/index.bml.loginrequired.title=Login Required + +/syn/index.bml.promo.text=After you've created a syndicated account, share it with others! The more people there are watching a syndicated account, the more points are freed up to read and create syndicated accounts. + +/syn/index.bml.remove=Remove Selected + +/syn/index.bml.table.account=Account + +/syn/index.bml.table.feed=Feed + +/syn/index.bml.table.watchers=Watchers + +/syn/index.bml.title=Syndication + +/syn/index.bml.user.nomatch=User posting doesn't match user that filled out the form. + +/syn/index.bml.using.text=Here you can add syndicated feeds (RSS) from other sites to your friends list, removing the need to check a dozen sites every day. + +/syn/index.bml.using.title=Using [[sitename]] for syndication + +/syn/list.bml.error.nofeeds=Error: No syndicated feeds have been updated in the past 24 hours. + +/syn/list.bml.feeddesc=Feed Description + +/syn/list.bml.feedurl=Feed URL + +/syn/list.bml.numreaders=Number of readers + +/syn/list.bml.title=Syndicated Feeds + +/syn/list.bml.username=Username + +/syn/list.bml.xml_icon.alt=[View Raw Feed] + +/talkmulti.bml.deleted.body=The comments have been deleted. You can view the rest of the thread here. + +/talkmulti.bml.deleted.title=Comments deleted + +/talkmulti.bml.error.comms_deleted=One of the comments has been deleted since you selected it. For security reasons, please go back and try again. + +/talkmulti.bml.error.inconsistent_data=The supplied data is inconsistent. + +/talkmulti.bml.error.invalid=Invalid parameters specified. + +/talkmulti.bml.error.invalid_mode<< +You have not selected one of the actions. Please go back and choose +if you would like to screen, unscreen, or delete the comments. +. + +/talkmulti.bml.error.login=You are not logged in. + +/talkmulti.bml.error.none_selected=You have not selected any comments. + +/talkmulti.bml.error.privs.delete=You do not have permission to delete these comments. + +/talkmulti.bml.error.privs.screen=You do not have permission to screen these comments. + +/talkmulti.bml.error.privs.unscreen=You do not have permission to unscreen these comments. + +/talkmulti.bml.screened.body=The comments have been screened. You can view them here. + +/talkmulti.bml.screened.title=Comments screened + +/talkmulti.bml.title.delete=Delete Multiple Comments + +/talkmulti.bml.title.screen=Screen Multiple Comments + +/talkmulti.bml.title.unscreen=Unscreen Multiple Comments + +/talkmulti.bml.unscreened.body=The comments have been unscreened. You can view them here. + +/talkmulti.bml.unscreened.title=Comments unscreened + +/talkpost.bml.allowedhtml=Allowed HTML + +/talkpost.bml.error.cannotreplynopost=You cannot reply to a non-existent post + +/talkpost.bml.error.nocommentsjournal=User has disabled comments in their journal. + +/talkpost.bml.error.nocommentspost=User has disabled comments for this particular post. + +/talkpost.bml.error.noreplypost=Replyto post not found (deleted?) + +/talkpost.bml.error.noreply_deleted=This comment had been deleted. You cannot reply to it. + +/talkpost.bml.error.noreply_frozen=This comment is frozen and cannot be replied to. + +/talkpost.bml.error.noreply_screened=This comment is screened and you have no permissions to see it or reply to it. + +/talkpost.bml.label.picturetouse2=Picture to use: + +/talkpost.bml.loganonip=Notice! This user has turned on the option that logs IP addresses of anonymous posters. + +/talkpost.bml.loginq=Login? + +/talkpost.bml.logyourip=Notice! This user has turned on the option that logs your IP address when posting. + +/talkpost.bml.noaccount=Don't have an account? Create one now. + +/talkpost.bml.nosubjecthtml=No HTML allowed in subject + +/talkpost.bml.opt.anonymous=Anonymous + +/talkpost.bml.opt.bannedfrom= - you have been banned from commenting in this journal. + +/talkpost.bml.opt.defpic=(default) + +/talkpost.bml.opt.friendsonly=- this user has disabled anonymous and non-friend posting. You may post here if [[username]] lists you as a friend. + +/talkpost.bml.opt.from=From: + +/talkpost.bml.opt.ljuser=LiveJournal user: + +/talkpost.bml.opt.ljuser2=LiveJournal user + +/talkpost.bml.opt.loggedin=Logged in user: [[username]] + +/talkpost.bml.opt.message=Message: + +/talkpost.bml.opt.noanonpost=- this user has disabled anonymous posting. + +/talkpost.bml.opt.noautoformat=Don't auto-format: + +/talkpost.bml.opt.noimage=No Image + +/talkpost.bml.opt.preview=Preview + +/talkpost.bml.opt.spellcheck=Spell check entry before posting + +/talkpost.bml.opt.subject=Subject: + +/talkpost.bml.opt.submit=Post Comment + +/talkpost.bml.opt.willscreen=(will be screened) + +/talkpost.bml.opt.willscreenfriend=(will be screened if not a friend) + +/talkpost.bml.paraformat=Paragraphs will be automatically formatted by default. + +/talkpost.bml.postresponse=Post a comment in response: + +/talkpost.bml.title=Post Comment + +/talkpost.bml.usermismatch<< +You have entered a username, but you have deselected the 'LiveJournal user' option. + +Please either clear the user textbox or select the relevant posting mode and try again. +. + +/talkpost.bml.warnscreened=Notice: This comment is screened. Replying to it will automatically un-screen it and make it visible. + +/talkpost_do.bml.error.badpassword=Incorrect password given for the username specified. You can recover your password here if you've forgotten it. + +/talkpost_do.bml.error.badusername=The LiveJournal username you specified does not exist. You can recover your username here if you've forgotten it, or you may post as "Anonymous" instead. + +/talkpost_do.bml.error.banned=You are not allowed to post in this user's journal. + +/talkpost_do.bml.error.blankmessage=Your message was blank. Please type at least something in the message field. + +/talkpost_do.bml.error.confused_identity=You entered a username, but selected to post anonymously or as the currently logged in user. Go back and decide which you really want to do. + +/talkpost_do.bml.error.deleted=Your journal has been deleted. You can't post messages. + +/talkpost_do.bml.error.friendsonly=Only friends of [[user]] may post in this journal. + +/talkpost_do.bml.error.lostcookie=Your login cookie seems to have disappeared? + +/talkpost_do.bml.error.manybytes=Sorry, but your comment of [[current]] exceeds the maximum byte length of [[limit]]. Please go back, shorten it, and try posting it again. + +/talkpost_do.bml.error.manychars=Sorry, but your comment of [[current]] characters exceeds the maximum character length of [[limit]]. Please go back, shorten it, and try posting it again. + +/talkpost_do.bml.error.mustlogin=You must be logged in or using a username/password to reply to this protected entry. + +/talkpost_do.bml.error.noanon=You can't post anonymously in this person's journal. + +/talkpost_do.bml.error.noauth=You are not authorized to reply to this protected entry. + +/talkpost_do.bml.error.nocomments=User has disabled commenting on this journal entry. + +/talkpost_do.bml.error.noparent=Cannot reply to a non-existent comment. + +/talkpost_do.bml.error.notafriend=Sorry, user [[user]] does not list you as a friend, and they've set the "friends only" option for who can reply to their journal. + +/talkpost_do.bml.error.nousername=You did not enter your LiveJournal username. You can choose to post as "Anonymous" if you don't have a LiveJournal user account. + +/talkpost_do.bml.error.noverify=Sorry, you aren't allowed to post comments in other people's journals until your email address has been verified. If you've lost the confirmation email to do this, you can have it resent from the lost information page. + +/talkpost_do.bml.error.postshared=You can't post as a shared or community account. Shared accounts represent groups of people, not individual people. + +/talkpost_do.bml.error.screened=You have no permission to reply to this screened comment. + +/talkpost_do.bml.error.suspended=Your journal has been suspended. You can't post messages. + +/talkpost_do.bml.error.testacct=Test accounts can only be used in test account journals. + +/talkpost_do.bml.opt.preview=Preview + +/talkpost_do.bml.preview=This is how your comment will look when posted. Using the form below, you can edit your comment further, or you can submit it as is. + +/talkpost_do.bml.preview.subject=Subject: + +/talkpost_do.bml.preview.submit=Submit + +/talkpost_do.bml.preview.title=Preview + +/talkpost_do.bml.success.loggedin=You are now logged in. + +/talkpost_do.bml.success.message=Your comment has been added. You can view it here. + +/talkpost_do.bml.success.screened.comm=Your comment has been added. According to this community's settings, it was marked as screened, and will be visible only to you and the community maintainers until they choose to unscreen it. You can view your comment here. + +/talkpost_do.bml.success.screened.comm.anon=Your anonymous comment has been added. According to this community's settings, it was marked as screened, and will be visible only to the community maintainers until they choose to unscreen it. You can go back to the comment thread here. + +/talkpost_do.bml.success.screened.user=Your comment has been added. According to this journal's settings, it was marked as screened, and will be visible only to you and the journal's owner until the owner chooses to unscreen it. You can view your comment here. + +/talkpost_do.bml.success.screened.user.anon=Your anonymous comment has been added. According to this journal's settings, it was marked as screened, and will be visible only to the journal's owner until the owner chooses to unscreen it. You can go back to the comment thread here. + +/talkpost_do.bml.success.title=Success + +/talkpost_do.bml.success.unscreened=Additionally, the screened comment you were replying to has been unscreened and is now visible. + +/talkpost_do.bml.title=Post Comment + +/talkpost_do.bml.title.error=Comment Not Posted + +/talkpost_do.bml.title.preview=Comment Preview + +/talkread.bml.anonuser=(Anonymous) + +/talkread.bml.button.more=More Options... + +/talkread.bml.button.post=Post Comment + +/talkread.bml.confirm.action=Are you sure you wish to delete the selected comments? + +/talkread.bml.deletedpost=(Deleted post) + +/talkread.bml.deleteduser=(Deleted user: [[username]]) + +/talkread.bml.fromip=(from [[ip]]) + +/talkread.bml.noreplies=No replies + +/talkread.bml.nosubject=(no subject) + +/talkread.bml.posted=Comment Posted Successfully + +/talkread.bml.qr.spellcheck=Check spelling and preview + +/talkread.bml.replysuspended=(Reply from suspended user) + +/talkread.bml.screenedpost=(Screened Post) + +/talkread.bml.select=Select + +/talkread.bml.subjectdeleted=[deleted] + +/talkread.bml.talkmulti.delete=Delete + +/talkread.bml.talkmulti.des=Mass action on selected comments: + +/talkread.bml.talkmulti.screen=Screen + +/talkread.bml.talkmulti.submit=Perform Action + +/talkread.bml.talkmulti.unscreen=Unscreen + +/talkread.bml.title=Read Comments + +/talkscreen.bml.error.login=You must be logged in to work with screened comments. + +/talkscreen.bml.error.privs.freeze=You do not have permission to freeze this thread. + +/talkscreen.bml.error.privs.screen=You do not have permission to screen this comment. + +/talkscreen.bml.error.privs.unfreeze=You do not have permission to unfreeze this thread. + +/talkscreen.bml.error.privs.unscreen=You do not have permission to unscreen this comment. + +/talkscreen.bml.freeze.doit=Yes, freeze this thread + +/talkscreen.bml.freeze.sure.body=Are you sure you want to freeze this thread? No further responses will be allowed to it or any of the comments underneath it. + +/talkscreen.bml.freeze.sure.title=Freeze this thread? + +/talkscreen.bml.frozen.body=The thread has been frozen. + +/talkscreen.bml.frozen.title=Success + +/talkscreen.bml.link=Go back to the post. + +/talkscreen.bml.screen.doit=Yes, screen this comment + +/talkscreen.bml.screen.sure.body=Are you sure you want to screen this comment? + +/talkscreen.bml.screen.sure.title=Screen this comment? + +/talkscreen.bml.screened.body=The comment has been screened. + +/talkscreen.bml.screened.title=Success + +/talkscreen.bml.title2=Change Comment Status + +/talkscreen.bml.unfreeze.doit=Yes, unfreeze this thread + +/talkscreen.bml.unfreeze.sure.body=Are you sure you want to unfreeze this thread? + +/talkscreen.bml.unfreeze.sure.title=Unfreeze this thread? + +/talkscreen.bml.unfrozen.body=The thread has been unfrozen. + +/talkscreen.bml.unfrozen.title=Success + +/talkscreen.bml.unscreen.doit=Yes, unscreen this comment + +/talkscreen.bml.unscreen.sure.body=Are you sure you want to unscreen this comment? + +/talkscreen.bml.unscreen.sure.title=Unscreen this comment? + +/talkscreen.bml.unscreened.body=The comment has been unscreened. + +/talkscreen.bml.unscreened.title=Success + +/tools/emailmanage.bml.address.current.title=Current Address + +/tools/emailmanage.bml.address.old.none=None + +/tools/emailmanage.bml.address.old.text<< +The following is a list of email addresses that were used with your account, +and the time they were deactivated as the primary email address. Check the ones +you wish to delete. +. + +/tools/emailmanage.bml.address.old.title=Previous Addresses + +/tools/emailmanage.bml.delete_selected=Delete Selected + +/tools/emailmanage.bml.desc.notfirst<< +This page only lets you remove email addresses that were used after the first time +you used the email address your account is currently validated with. In particular, +this means the attacker isn't able to remove your original email address. +. + +/tools/emailmanage.bml.desc.text<< +This page lets you remove past email addresses that were used with your account. +By removing them, they'll no longer be able to have your password mailed to them. +This is useful if somebody discovered your password and hijacked your journal. Simply +have the new password mailed to your old address, change it back, and remove the +attacker's email address. +. + +/tools/emailmanage.bml.desc.title=Description + +/tools/emailmanage.bml.log.deleted=Deleted: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Changes Saved + +/tools/emailmanage.bml.notvalidated.text<< +To use this tool, your current email address [[email]] must be validated. +To do this, visit the lost info page, which will +send you an authorization URL. After visiting it, come back here. +. + +/tools/emailmanage.bml.notvalidated.title=Email not validated + +/tools/emailmanage.bml.title=Email Management + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body2=Your list of memorable posts has been updated. You may return to the entry just added. + +/tools/memadd.bml.body.added.header=Success + +/tools/memadd.bml.description=Description: + +/tools/memadd.bml.description.text<< + Give this journal entry a description that you can remember it by. + To delete this entry from your list of memorable posts, enter a blank description. +. + +/tools/memadd.bml.error.deleted.body=The journal entry previously described as "[[desc]]" has been removed from your list of memorable posts. + +/tools/memadd.bml.error.deleted.title=Memory deleted + +/tools/memadd.bml.error.entry_deleted=Journal entry no longer exists. Memory deleted. + +/tools/memadd.bml.error.fivekeywords=Only 5 keywords/categories are allowed per memorable post. + +/tools/memadd.bml.error.invalid_security=Invalid or missing security option. + +/tools/memadd.bml.error.login=You must be logged in to use this feature. Go login and you'll be brought back here. + +/tools/memadd.bml.error.maxsize=This keyword exceeds the maximum allowed size: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +To add a journal entry to your list of memories, you need to provide a description. +To delete a memory, you can edit it and remove the description, but you didn't already have this entry in your memories. +. + +/tools/memadd.bml.error.nodescription.title=No description + +/tools/memadd.bml.form.reset=Reset + +/tools/memadd.bml.form.submit=Submit + +/tools/memadd.bml.keywords=Keywords: + +/tools/memadd.bml.keywords.example=Example: Funny, Geeky, Romantic + +/tools/memadd.bml.keywords.select=Or, you can also select keywords you've used in the past: + +/tools/memadd.bml.keywords.text<< + Why is this post memorable? + Enter up to five comma separated keywords or categories so you can find it later. You can also select keywords you've used in the past. +. + +/tools/memadd.bml.login.enterinfo=Enter username and password of the account you wish to save the memory into. + +/tools/memadd.bml.login.forgot.header=Forget something? + +/tools/memadd.bml.login.forgot.recover=If you forgot your username or password, recover it here!. + +/tools/memadd.bml.multiple_selections=Hold down 'Control' while clicking keywords to select multiple ones. + +/tools/memadd.bml.security=Security: + +/tools/memadd.bml.security.friendsonly=Friends Only + +/tools/memadd.bml.security.private=Private + +/tools/memadd.bml.security.public=Public + +/tools/memadd.bml.title=Add to Memories + +/tools/memadd.bml.title.added=Added + +/tools/memadd.bml.title.add_memory=Add Memorable Entry + +/tools/memadd.bml.title.deleted=Deleted + +/tools/memadd.bml.title.edit_memory=Edit Memorable Entry + +/tools/memadd.bml.whocansee<< + Who can see that you've marked this post as memorable? + Everybody, only people you list as a friend, or just you? +. + +/tools/memadd.bml.whocansee.comm<< + Who can see that you've marked this post as memorable? + Everybody, only members of the community, or only maintainers of the community? +. + +/tools/memories.bml.back=Back + +/tools/memories.bml.body.keyword<< + +[[user]] found memorable. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] has placed memorable journal entries in. p?> +. + +/tools/memories.bml.body.memorable=The following is a list of uncategorized journal entries that user [[user]] found memorable. + +/tools/memories.bml.delete=Delete Selected + +/tools/memories.bml.delete.confirm=You are about to delete one or more memories. Are you sure you want to do this? + +/tools/memories.bml.delete.deleted.head=Success + +/tools/memories.bml.delete.deleted.text=The selected memories have been deleted. You may return to your list of memorable posts. + +/tools/memories.bml.delete.deleted.title=Memories Deleted + +/tools/memories.bml.delete.error.dberror=There was a database error while deleting your memories. The error is [[error]]. Please try again. + +/tools/memories.bml.delete.error.noneselected=You did not select any memories to delete. + +/tools/memories.bml.edit=edit + +/tools/memories.bml.error.noentries.body<< +This could be because:
    +
  1. the user hasn't defined any memorable events,
  2. +
  3. the user's memorable events are protected and you don't have access to view them, or
  4. +
  5. the user doesn't have any memories that match your filter criteria.
+. + +/tools/memories.bml.error.noentries.title=No memories found. + +/tools/memories.bml.filter.all=All memories + +/tools/memories.bml.filter.other=Only other entries + +/tools/memories.bml.filter.own=Only '[[user]]' entries + +/tools/memories.bml.form.filter=Filter entries by: + +/tools/memories.bml.form.sort=Sort entries by: + +/tools/memories.bml.form.switch=Switch + +/tools/memories.bml.login=In order to view your own memories, please log in. + +/tools/memories.bml.plur_entry=[[num]] [[?num|entry|entries]] + +/tools/memories.bml.sort.description=Description + +/tools/memories.bml.sort.journal=Journal + +/tools/memories.bml.sort.orderadded=Order Added + +/tools/memories.bml.title.keyword=Memorable [[keyword]] Posts + +/tools/memories.bml.title.memorable=Memorable Posts + +/tools/memories.bml.uncategorized=Uncategorized + +/tools/recent_comments.bml.maxnotshown=Your account is only permitted to see the latest [[current]] entries, not the full limit of [[max]]. + +/update.bml.altpost=Journal to post in: + +/update.bml.auth.poster=Poster: + +/update.bml.btn.preview=Preview + +/update.bml.btn.update=Update Journal + +/update.bml.currmood=Current Mood: + +/update.bml.currmusic=Current Music: + +/update.bml.date=Date: + +/update.bml.default=default + +/update.bml.defaultjournal=([[user]]) -- default + +/update.bml.error.cantpost=Sorry, you cannot post at this time. + +/update.bml.error.disabled=Your account type does not permit posting. + +/update.bml.error.disabled.title=Posting access disabled + +/update.bml.error.login=Error logging on: + +/update.bml.error.nopass=Enter Password + +/update.bml.error.update=Error updating journal: + +/update.bml.event=Event: + +/update.bml.full=Full Update Page + +/update.bml.htmlokay.norich=(HTML okay; by default, newlines will be auto-formatted to <br>) + +/update.bml.htmlokay.rich=(HTML okay; by default, newlines will be auto-formatted to <br> - or, use the rich text mode.) + +/update.bml.htmlokay.rte_nosupport=(Sorry, your browser does not currently support the rich text environment.) + +/update.bml.localtime=Local time: + +/update.bml.loggedinas=You are currently logged in as [[user]].
To post as another user, click here. + +/update.bml.loggingin=Logging in to server... + +/update.bml.noneother=None, or other: + +/update.bml.note=Note: The time/date above is from our server. Correct them for your timezone before posting. + +/update.bml.opt.backdate=Backdate Entry: + +/update.bml.opt.backdate.about=won't show on friends view + +/update.bml.opt.defpic=(default) + +/update.bml.opt.nocomments=Disallow Comments: + +/update.bml.opt.noemail=Don't email Comments: + +/update.bml.opt.noformat=Don't auto-format: + +/update.bml.opt.spellcheck=Spell check entry before posting + +/update.bml.options=Optional Settings + +/update.bml.other=Other: + +/update.bml.password=Password: + +/update.bml.picture=Picture to use: + +/update.bml.preview.header=Preview + +/update.bml.preview.text=This is how the entry will look when posted. Using the form below, you can edit the entry further, or you can submit it as is. + +/update.bml.rowarn=Warning: Your account is currently in [[a_open]]read-only mode[[a_close]]. Due to this maintenance you may be unable to post to your journal at this time. + +/update.bml.security.custom=Custom... + +/update.bml.security.friends=Friends + +/update.bml.security.head=Security Level: + +/update.bml.security.private=Private + +/update.bml.security.public=Public + +/update.bml.servermsg=Also, the server has a message for you: + +/update.bml.simple=You're looking at the simple page. For more options, click here. + +/update.bml.spellchecked=Your spell-checked post: + +/update.bml.subject=Subject: (optional, for use on longer entries) + +/update.bml.success.links=Now that you've posted, you can: + +/update.bml.success.links.edit=Edit the entry + +/update.bml.success.links.memories=Add the entry to your memories + +/update.bml.success.links.tags=Edit this entry's tags + +/update.bml.success.links.view=View the entry + +/update.bml.timeformat=24 hour time + +/update.bml.title=Update Journal + +/update.bml.title.readonly=Read-only mode + +/update.bml.update.alternate=If you don't want to download a client for your computer, or if one doesn't exist for your computer, you may use this page to update your journal. This is also useful if you're on vacation or away from your primary computer. + +/update.bml.update.head=Update your Journal... + +/update.bml.update.success=Update successful. You may view your updated journal here. + +/update.bml.updating=Updating journal... + +/update.bml.username=Username: + +/uploadpic.bml.error.unsupportedtype=Files of type [[filetype]] are not supported. You can only upload GIF, PNG or JPG files. Nearly all image/photo programs can do this conversion for you. + +/userinfo.bml.about.comm=About: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.body.leave= You may leave the community at any time. + +/userinfo.bml.comminfo.body=Below is information about the "[[commname]]" community on LiveJournal. + +/userinfo.bml.comminfo.name=Community Information + +/userinfo.bml.date.never=Never. + +/userinfo.bml.error.malfname=Malformed username. + +/userinfo.bml.error.notloggedin=If you wish to view your own user profile, you need to login. + +/userinfo.bml.fbpictures.lessthan=less than [[count]] public + +/userinfo.bml.fbpictures.over=over [[count]] public + +/userinfo.bml.friendof.comm=Watched by: + +/userinfo.bml.friendof.hidden=(hidden) + +/userinfo.bml.friendof.syndreadcount=Number of Readers + +/userinfo.bml.friendof.user=Friend of: + +/userinfo.bml.friends.comm=Members + +/userinfo.bml.friends.user=Friends + +/userinfo.bml.label.addbuddy=Add Buddy + +/userinfo.bml.label.adduser=Add User + +/userinfo.bml.label.alsofriendof=Also Friend of: + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=Birthdate: + +/userinfo.bml.label.clientsused=Clients used: + +/userinfo.bml.label.comments=Comments: + +/userinfo.bml.label.composted=Posted: [[num]] - + +/userinfo.bml.label.comreceived=Received: [[num]] + +/userinfo.bml.label.datecreated=Date created: + +/userinfo.bml.label.dateupdated=Date updated: + +/userinfo.bml.label.email=Email: + +/userinfo.bml.label.fbpictures=Pictures: + +/userinfo.bml.label.frcommunity=Communities + +/userinfo.bml.label.frpeople=People + +/userinfo.bml.label.frsyndication2=Feeds + +/userinfo.bml.label.icquin=ICQ UIN: + +/userinfo.bml.label.interests=Interests + +/userinfo.bml.label.interests.modifyyours=Modify yours + +/userinfo.bml.label.interests.removesome=Remove some + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] interests not shown + +/userinfo.bml.label.jabber=Jabber: + +/userinfo.bml.label.journalentrs=Journal entries: + +/userinfo.bml.label.location=Location: + +/userinfo.bml.label.memberof=Member of + +/userinfo.bml.label.memories=Memories: + +/userinfo.bml.label.moredetails=(more details...) + +/userinfo.bml.label.msnusername=MSN Username: + +/userinfo.bml.label.mutual=Mutual Friends: + +/userinfo.bml.label.name=Name: + +/userinfo.bml.label.nofriends=None listed. + +/userinfo.bml.label.post=Post to "[[journal]]" + +/userinfo.bml.label.postalt=Update your journal + +/userinfo.bml.label.reqfinduser=Only users with 'finduser' priv can lookup users by userid. + +/userinfo.bml.label.searchjournal=Search This Journal + +/userinfo.bml.label.sendmessage=Send Message + +/userinfo.bml.label.shared=Posting Access: + +/userinfo.bml.label.supportpoints=Support points + +/userinfo.bml.label.syndicatedfrom=Syndicated from: + +/userinfo.bml.label.syndicatedstatus=Syndication Status: + +/userinfo.bml.label.textmessage=Text
Message
: + +/userinfo.bml.label.todo=To-Do List + +/userinfo.bml.label.user=User: + +/userinfo.bml.label.userprofile=User Profile + +/userinfo.bml.label.viewfriends=View Friends + +/userinfo.bml.label.viewmembers=View Members + +/userinfo.bml.label.website=Website: + +/userinfo.bml.label.yahooid=Yahoo! ID: + +/userinfo.bml.membership.body=To join this community, click here. + +/userinfo.bml.memories.entries=[[count]] entries + +/userinfo.bml.memories.entry=[[count]] entry + +/userinfo.bml.monitor.comm=Monitor Community + +/userinfo.bml.monitor.user=Add this user to your friends list + +/userinfo.bml.nonexist.body=The username [[user]] is not currently registered. + +/userinfo.bml.nonexist.name=Unknown user + +/userinfo.bml.sendmessage.body=Send [[user]] a text message
on his/her cellphone/pager. + +/userinfo.bml.syn.last.never=Never + +/userinfo.bml.syn.lastcheck=Last checked: + +/userinfo.bml.syn.nextcheck=Next check: + +/userinfo.bml.syn.parseerror=Error Message: + +/userinfo.bml.syndinfo.body<< +If you would like articles from the syndicated site to appear on your friends page, +you can add this journal to your friends list. +. + +/userinfo.bml.syndinfo.name=Syndication Journal + +/userinfo.bml.tellafriend=Tell a Friend! + +/userinfo.bml.timeupdate.dayago=1 day ago + +/userinfo.bml.timeupdate.daysago=[[num]] days ago + +/userinfo.bml.timeupdate.hourago=1 hour ago + +/userinfo.bml.timeupdate.hoursago=[[num]] hours ago + +/userinfo.bml.timeupdate.minuteago=1 minute ago + +/userinfo.bml.timeupdate.minutesago=[[num]] minutes ago + +/userinfo.bml.timeupdate.secondago=1 second ago + +/userinfo.bml.timeupdate.secondsago=[[num]] seconds ago + +/userinfo.bml.timeupdate.weekago=1 week ago + +/userinfo.bml.timeupdate.weeksago=[[num]] weeks ago + +/userinfo.bml.title=User Info + +/userinfo.bml.title.communityinfo=Community Info + +/userinfo.bml.title.syndicated=Syndicated Account + +/userinfo.bml.userinfo.body=Below is user information for [[username]]. If you are this user, you can edit your information (or choose what information is considered public) at the Edit Info page. + +/userinfo.bml.userinfo.name=User Information + +Actionlink=[[[link]]] + +Backlink=[<< [[text]]] + +bml.badcontent.body=One or more errors occurred processing your request. Please go back, correct the necessary information, and submit your data again. + +bml.badinput.body=Your browser sent some text which is not recognised as valid text in the UTF-8 encoding, as it should be. This might happen if you forced your browser to view the previous page in some other encoding rather than UTF-8. It may also indicate a bug in the browser. If you cannot get around this error, contact us. + +bml.badinput.head=Bad Unicode Input + +bml.needlogin.body2=In order to view this page, you must log in. + +bml.needlogin.head=Login Required + +BML.parse_multipart.parse=Error parsing upload + +BML.parse_multipart.toolarge=Upload too large + +BML.parse_multipart.unknowntype=Unknown content type + +bml.requirepost=As a security precaution, the page you're viewing requires a POST request, not a GET. If you're trying to submit this form legitimately, please contact us. + +btn.search=Search + +crumb.acctstatus=Account Status + +crumb.addfriend=Add Friend + +crumb.addtodo=Add To-Do Item + +crumb.advcustomize=Customize Advanced S2 Settings + +crumb.birthdays=Birthdays + +crumb.changepass=Change Password + +crumb.comminvites=Community Invitations + +crumb.commmembers=Community Membership + +crumb.commpending=Pending Memberships + +crumb.commsearch=Community Search + +crumb.commsentinvites=Sent Invitations + +crumb.community=Community Center + +crumb.createcommunity=Create Community + +crumb.createjournal=Create Journal + +crumb.createstyle=Create Style + +crumb.customize=Customize S2 Settings + +crumb.delcomment=Delete Comment + +crumb.editentries=Edit Entries + +crumb.editentries_do=Edit Entry + +crumb.editfriendgrps=Edit Friends Groups + +crumb.editfriends=Edit Friends + +crumb.editinfo=Personal Info + +crumb.editpics=User Pictures + +crumb.editstyle=Edit Style + +crumb.emailgateway=Email Gateway + +crumb.emailmanage=Email Management + +crumb.encodings=About Encodings + +crumb.export=Export Journal + +crumb.faq=Frequently Asked Questions + +crumb.feedstersearch=Search a Journal + +crumb.friends=Friends Tools + +crumb.friendsfilter=Friends Filter + +crumb.home=Home + +crumb.joincomm=Join Community + +crumb.latestposts=Latest Posts + +crumb.layerbrowse=Public Layer Browser + +crumb.leavecomm=Leave Community + +crumb.linkslist=Your Links + +crumb.login=Login + +crumb.logout=Logout + +crumb.lostinfo=Lost Info + +crumb.manage=Manage Accounts + +crumb.managecommunity=Community Management + +crumb.meme=Meme Tracker + +crumb.memories=Memorable Posts + +crumb.moderate=Community Moderation + +crumb.modify=Journal Settings + +crumb.moodlist=Mood Viewer + +crumb.news=News + +crumb.phonepostsettings=Phone Post + +crumb.popfaq=Popular FAQs + +crumb.preview=Layout Previews + +crumb.register=Validate Email + +crumb.seeoverrides=View User Overrides + +crumb.setpgpkey=Public Key + +crumb.siteopts=Browse Preferences + +crumb.styles=Styles + +crumb.support=Support + +crumb.supportact=Request Action + +crumb.supportappend=Append to Request + +crumb.supporthelp=Request Board + +crumb.supportnotify=Notification Settings + +crumb.supportscores=High Scores + +crumb.supportsubmit=Submit Request + +crumb.textmessage=Send Text Message + +crumb.themes=Theme Previews + +crumb.todo=Todo List + +crumb.transfercomm=Transfer Community + +crumb.unsubscribe=Unsubscribe + +crumb.update=Update Journal + +crumb.utf8convert=UTF-8 Converter + +crumb.yourlayers=Your Layers + +crumb.yourstyles=Your Styles + +date.day.friday.long=Friday + +date.day.friday.short=Fri + +date.day.monday.long=Monday + +date.day.monday.short=Mon + +date.day.saturday.long=Saturday + +date.day.saturday.short=Sat + +date.day.sunday.long=Sunday + +date.day.sunday.short=Sun + +date.day.thursday.long=Thursday + +date.day.thursday.short=Thu + +date.day.tuesday.long=Tuesday + +date.day.tuesday.short=Tue + +date.day.wednesday.long=Wednesday + +date.day.wednesday.short=Wed + +date.month.april.long=April + +date.month.april.short=Apr + +date.month.august.long=August + +date.month.august.short=Aug + +date.month.december.long=December + +date.month.december.short=Dec + +date.month.february.long=February + +date.month.february.short=Feb + +date.month.january.long=January + +date.month.january.short=Jan + +date.month.july.long=July + +date.month.july.short=Jul + +date.month.june.long=June + +date.month.june.short=Jun + +date.month.march.long=March + +date.month.march.short=Mar + +date.month.may.long=May + +date.month.may.short=May + +date.month.november.long=November + +date.month.november.short=Nov + +date.month.october.long=October + +date.month.october.short=Oct + +date.month.september.long=September + +date.month.september.short=Sep + +Email=Email + +email.newacct.body|notes=This string is no longer in use, please translate email.newacct2.body instead. +email.newacct.body<< +Congratulations, you have a new [[sitename]] account! + +To complete your journal creation and verify your email address, go +here: + + [[regurl]] + +The URL that your new journal is located at is: + + [[siteroot]]/users/[[username]]/ + +and also: + + [[siteroot]]/~[[username]]/ + +Below is your LiveJournal username and password: + + Username: [[username]] + Password: [[password]] + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Welcome to [[sitename]] + +email.newacct2.body|notes=This string replaces email.newacct.body. You may refer to the old string while translating if you wish. +email.newacct2.body<< +Congratulations, you have a new [[sitename]] account! + +To complete your journal creation and verify your email address, +please visit the following location. Verifying your email address +will help to protect your account as well as allow you to utilize +more features within your journal. + + [[regurl]] + +You may access your journal at the following two URLs: + + [[siteroot]]/users/[[username]]/ + [[siteroot]]/~[[username]]/ + +Below is your [[sitename]] username that you registered: + + Username: [[username]] + +If you need to retrieve your password, you can do so at any time by +visiting the following URL: + + [[siteroot]]/lostinfo.bml + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +entryform.backdated=Entry is Backdated: + +entryform.comment.screening=Screen Comments: + +entryform.comment.settings=Comment Settings: + +entryform.comment.settings.default=Default + +entryform.comment.settings.nocomments=Disabled + +entryform.comment.settings.noemail=Don't E-mail + +entryform.date=Date: + +entryform.date.24hournote=(24 hour time) + +entryform.delete=Delete Entry + +entryform.delete.confirm=Are you sure you want to delete this entry? + +entryform.deletespam=Delete and Mark as Spam + +entryform.deletespam.confirm=Are you sure you want to delete this entry and mark it as spam? + +entryform.entry=Entry: + +entryform.format=Text Formatting: + +entryform.format.auto=Auto + +entryform.format.preformatted=None + +entryform.htmlokay.norich=(HTML okay; by default, newlines will be auto-formatted to <br>) + +entryform.htmlokay.rich=(HTML okay; by default, newlines will be auto-formatted to <br> - or, use the rich text mode.) + +entryform.htmlokay.rte_nosupport=rte_nosupport=(Sorry, your browser does not currently support the rich text environment.) + +entryform.mood=Mood: + +entryform.mood.noneother=None, or other: + +entryform.music=Music: + +entryform.nojstime.note=Note: The time/date above is from our server. Correct them for your timezone before posting. + +entryform.opt.defpic=(default) + +entryform.options=Options: + +entryform.postto=Post to: + +entryform.preview=Preview + +entryform.save=Save Entry + +entryform.security=Security: + +entryform.spellcheck=Spell check + +entryform.spellcheck.noerrors=No spelling errors found + +entryform.spellchecked=Spell checked entry: + +entryform.subject=Subject: + +entryform.tags=Tags: + +entryform.update=Update Journal + +entryform.userpics=User Picture Icon: + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Error + +error.badpassword=Incorrect Password. + +error.code.comm_not_comm=Account is not a community + +error.code.comm_not_found=Community not found + +error.code.comm_not_member=User is not a member of this community + +error.dberror=A database error occurred: + +error.deleted.name=Deleted + +error.deleted.text=This journal has been deleted. If you are [[user]], you have a period of 30 days from the deletion time to undelete the journal. After 30 days we will delete all content permanently from our servers. + +error.deleted.title=Deleted Account + +error.expiredchal=Login window expired. Please try again. + +error.invalidauth=You could not be authenticated as the specified user. + +error.invalidform=Invalid form submission. Please refresh and try again. + +error.ipbanned=Your IP address is temporarily banned for exceeding the login failure rate. + +error.malformeduser=Malformed username. + +error.nobutton=No button pressed? + +error.nocommlogin=Logging in as a community has been disabled. + +error.nodb=Database temporarily unavailable. + +error.nodbmaintenance=This part of the database is temporarily down for maintenance. Try again in a few minutes. + +error.noentry=No such journal entry. + +error.nojournal=Unknown Journal + +error.noremote=You have to login in order to use this page. + +error.procrequest=There was an error processing your request: + +error.purged.name=Deleted + +error.purged.text=This journal has been deleted and purged. + +error.purged.title=Purged Account + +error.suspended.name=Suspended + +error.suspended.text=This journal has been either temporarily or permanently suspended by [[sitename]] for policy violation. If you are [[user]], contact us for more information. + +error.suspended.title=Suspended Account + +error.tempdisabled=This is disabled temporarily. + +error.unknownmode=Unknown mode. + +error.usernameinvalid=Username contains invalid characters. + +error.usernamelong=Username is too long, 15 character max. + +error.username_notfound=Username not found. + +Help=Help + +label.screening.all=All comments + +label.screening.anonymous=Anonymous only + +label.screening.default=Default + +label.screening.header=Screened Comments: + +label.screening.none=None + +label.screening.nonfriends=By non-friends + +label.security.custom=Custom... + +label.security.friends=Friends + +label.security.head=Security Level: + +label.security.maintainers=Maintainers + +label.security.members=Members + +label.security.private=Private + +label.security.public=Public + +label.switch.button=Switch + +label.switch.header=Switch Journal + +label.switch.workwith=Work with journal: + +label.warning=Warning: + +langname.en=English + +ljlib.pageofpages=Page [[page]] of [[total]] + +lostinfo.head=Forget something? + +lostinfo.text=If you forgot your username or password, recover it here. + +lynx.nav.friends=Friends + +lynx.nav.help=Technical Support + +lynx.nav.home=Home + +lynx.nav.login=Login + +lynx.nav.logout=Logout + +lynx.nav.recent=Recent Entries + +lynx.nav.sitemap=Site Map + +lynx.nav.siteopts=Browse Options + +lynx.nav.update=Update Journal + +Password=Password + +password.max30=Passwords may not be longer than 30 characters. + +poll.dberror=Database error: [[errmsg]] + +poll.dberror.items=Database error inserting items: [[errmsg]] + +poll.dberror.questions=Database error inserting questions: [[errmsg]] + +poll.error.badmaxlength=Maxlength attribute on lj-pq text tags must be an integer from 1-255. + +poll.error.badsize=Size attribute on lj-pq text tags must be an integer from 1-100. + +poll.error.cantview=Error: you don't have access to view these poll results. + +poll.error.cantvote=Sorry, you don't have permission to vote in this particular poll. + +poll.error.missingljpoll=All lj-pq tags must be nested inside an enclosing lj-poll tag. + +poll.error.missingljpq=All lj-pi tags must be nested inside an enclosing lj-pq tag. + +poll.error.nested=You cannot nest [[tag]] tags. Did you forget to close one? + +poll.error.noentry=Error: this poll is not attached to this journal entry + +poll.error.noitems=You must have at least one item in a non-text poll question. + +poll.error.noitemstext=lj-pq tags of type 'text' cannot have poll items in them. + +poll.error.nopollid=pollid parameter is missing. + +poll.error.noquestions=You must have at least one question in a poll. + +poll.error.notext=Need text inside an lj-pq tag to say what the question is about. + +poll.error.pitoolong=Text inside an lj-pi tag must be between 1 and 255 characters. Yours is [[len]]. + +poll.error.pollnotfound=Error: poll #[[num]] not found + +poll.error.questionnotfound=Error: this poll question doesn't exist. + +poll.error.scalefromlessto=Scale 'from' value must be less than 'to' value. + +poll.error.scaleincrement=Scale increment must be at least 1. + +poll.error.scaletoobig=Your scale exceeds the limit of 20 selections (to-from)/by > 20. + +poll.error.tagnotopen=You cannot close an [[tag]] tag that's not open. + +poll.error.truncated=... truncated + +poll.error.unknownpqtype=Unknown type on lj-pq tag. + +poll.error.unlockedtag=Unlocked [[tag]] tag. + +poll.error.whoview=whoview must be 'all', 'friends', or 'none'. + +poll.error.whovote=whovote must be 'all' or 'friends'. + +poll.pollnum=Poll #[[num]] + +poll.scaleanswers=Mean: [[mean]] Median: [[median]] Std. Dev [[stddev]] + +poll.security=Open to: [[whovote]], results viewable to: [[whoview]] + +poll.security.all=All + +poll.security.friends=Friends + +poll.security.none=None + +poll.submit=Submit Poll + +poll.viewanswers=View Answers + +portal.bdays.count.des=By default, the 5 friends with the soonest birthdays are shown. + +portal.bdays.count.name=Birthdays to Display + +portal.bdays.portalname=Birthdays + +portal.bdays.portaltitle=Birthdays + +portal.login.portalname=Login Box + +portal.memories.entriesnoun=entries + +portal.memories.entrynoun=entry + +portal.memories.portalname=Memorable Posts + +portal.memories.portaltitle=Memorable Posts + +portal.ministats.active=Active: + +portal.ministats.title=User Stats + +portal.ministats.total=Total: + +portal.popfaq.portalname=10 Most Viewed FAQs + +portal.popfaq.portaltitle=10 Most Viewed FAQs + +portal.randuser.count.des=By default, 1 random user is shown, but you can have up to 10 vertically in the narrow columns, or 5 horizontally in a wide column + +portal.randuser.count.name=Number of random users to show + +portal.randuser.error.tableempty=There are no random users. Contact admin. + +portal.randuser.hidename.des=By default, the random user name is shown. Check this to remove it. + +portal.randuser.hidename.name=Hide Name + +portal.randuser.hidepic.des=By default, the random user picture is shown, if available. Check this to remove it. + +portal.randuser.hidepic.name=Hide User Picture + +portal.randuser.portalname=Random User + +portal.randuser.portaltitle=Random User + +portal.randuser.portaltitleplural=Random Users + +portal.recent.error.noentries=Sorry. No entries. + +portal.recent.error.notsetup=You have to configure this box. Click the plus symbol to setup the journal you'd like to watch here. + +portal.recent.error.userstatus=User has deleted or suspended their account. + +portal.recent.items.description=By default, only the most recent entry is shown. + +portal.recent.items.name=Items to display + +portal.recent.journal.description=What journal do you want to see the recent items from? + +portal.recent.journal.name=Journal + +portal.recent.nosubject=(No Subject) + +portal.recent.permlink=Link + +portal.recent.portalname=Recent Entry View + +portal.recent.portaltitle=Recent Entry Box + +portal.recent.showtext.description=By default only subjects will be shown. + +portal.recent.showtext.name=Include Text + +portal.stats.journalentyest=Journal entries yesterday + +portal.stats.portalname=Site Statistics + +portal.stats.portaltitle=Statistics + +portal.stats.totalusers=Total users + +portal.update.mode.des=Full mode gives you a ton of extra posting options ... including posting in communities and setting your current mood, music, and picture. Simple mode is nicer if you hardly use those features and would prefer not to see it all. + +portal.update.mode.full=Full + +portal.update.mode.name=Mode + +portal.update.mode.simple=Simple + +portal.update.portalname=Journal Update + +portal.update.portaltitle=Update Your Journal + +protocol.bad_password=Your password is too easy to guess. It's recommended that you change it, otherwise you risk having your journal hijacked. Visit [[siteroot]]/changepassword.bml to change your password. + +protocol.hello_test=Hello Test Account! + +protocol.mail_bouncing=You are currently using a bad email address. All mail we try to send you is bouncing. We require a valid email address for continued use. Visit the support area for more information. + +protocol.modpost=Your entry has been put into the moderation queue. It will be accepted or rejected by one of the community moderators. + +protocol.must_revalidate=You need to validate your new email address. Your old one was good, but since you've changed it, you need to re-validate the new one. Visit [[siteroot]]/support for more information. + +protocol.not_validated=You are currently not validated. You may continue to use [[sitename]], but please validate your email address for continued use. See the instructions that were mailed to you when you created your journal, or see [[siteroot]]/support/ for more information. + +protocol.old_win32_client=There are significantly newer Windows LiveJournal clients available, and we recommend that you upgrade. Visit [[siteroot]]/download/ to download a newer client. + +protocol.readonly=Your account is temporarily in read-only mode. Some operations will fail for a few minutes. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Sorry + +talk.anonwrote=Someone wrote, + +talk.anonwrote_comm=Someone wrote in [[commlink]], + +talk.btn.preview=Preview + +talk.commentpermlink=link + +talk.commentpost=Post a new comment + +talk.commentsread=Read comments + +talk.curname_Mood=Current mood: + +talk.curname_Music=Current music: + +talk.curname_Tags=Entry tags: + +talk.error.bogusargs=Bogus arguments + +talk.error.comm_deleted=This comment has been deleted. + +talk.error.deleted=This journal is deleted. + +talk.error.deleted.title=Deleted + +talk.error.mustlogin=You must be logged in to view this protected entry. + +talk.error.nocomment=The comment does not exist. + +talk.error.noentry=No such entry. + +talk.error.nojournal=Error: couldn't determine journal from arguments. + +talk.error.nosuchjournal=No such journal + +talk.error.notauthorised=You are not authorized to view this protected entry. + +talk.error.suspended=This journal/poster is suspended. + +talk.error.suspended.title=Suspended + +talk.frozen=Replies frozen + +talk.parentlink=Parent + +talk.readsimilar=Read similar journal entries: + +talk.replytothis=Reply to this + +talk.somebodywrote=[[realname]] ([[userlink]]) wrote, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) wrote in [[commlink]], + +talk.spellcheck=Check spelling during preview + +talk.threadlink=Thread + +tos.error=You must read and agree to the terms of service. + +tos.haveread=I have read and agree to the Terms of Service. + +tos.mustread=Before continuing you must read and agree to the Terms of Service. + +Username=Username + +userpic.inactive=Inactive + diff --git a/livejournal/bin/upgrading/import-includes.pl b/livejournal/bin/upgrading/import-includes.pl new file mode 100755 index 0000000..a83a9a9 --- /dev/null +++ b/livejournal/bin/upgrading/import-includes.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# This script goes through all of the files in your include directory +# (LJHOME/htdocs/inc) and then imports ones that are specified by your +# ljconfig.pl file (%LJ::FILEEDIT_VIA_DB) into your database if the file +# on disk is newer than the one in the database. + +use strict; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +# create list of files to check +my $dir = "$ENV{'LJHOME'}/htdocs/inc"; +print "searching for files to check against database..."; +opendir DIR, $dir + or die "Unable to open $ENV{'LJHOME'}/htdocs/inc for searching.\n"; +my @files = grep { $LJ::FILEEDIT_VIA_DB || + $LJ::FILEEDIT_VIA_DB{$_} } readdir(DIR); +my $count = scalar(@files); +print $count+0 . " found.\n"; + +# now iterate through and check times +my $dbh = LJ::get_db_writer(); +foreach my $file (@files) { + my $path = "$dir/$file"; + next unless -f $path; + + # now get filetime + my $ftimedisk = (stat($path))[9]; + my $ftimedb = $dbh->selectrow_array("SELECT updatetime + FROM includetext WHERE incname=?", undef, $file)+0; + + # check + if ($ftimedisk > $ftimedb) { + # load file + open FILE, "<$path"; + my $content = join("", ); + close FILE; + + # now do SQL + print "$file newer on disk...updating database..."; + $dbh->do("REPLACE INTO includetext (incname, inctext, updatetime)" . + "VALUES (?,?,UNIX_TIMESTAMP())", undef, $file, $content); + print $dbh->err ? "error: " . $dbh->errstr . ".\n" : "done.\n"; + } else { + print "$file newer in database, ignored.\n"; + } +} + +print "all done.\n"; diff --git a/livejournal/bin/upgrading/make_system.pl b/livejournal/bin/upgrading/make_system.pl new file mode 100755 index 0000000..f6efd26 --- /dev/null +++ b/livejournal/bin/upgrading/make_system.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +# + +use strict; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbh = LJ::get_dbh("master"); + +print " +This tool will create your LiveJournal 'system' account and +set its password. Or, if you already have a system user, it'll change +its password to whatever you specify. +"; + +print "Enter password for the 'system' account: "; +my $pass = ; +chomp $pass; + +print "\n"; + +print "Creating system account...\n"; +unless (LJ::create_account({ 'user' => 'system', + 'name' => 'System Account', + 'password' => $pass })) +{ + print "Already exists.\nModifying 'system' account...\n"; + $dbh->do("UPDATE user SET password=? WHERE user='system'", + undef, $pass); +} + +my $u = LJ::load_user("system"); +unless ($u) { + print "ERROR: can't find newly-created system account.\n"; + exit 1; +} + +print "Giving 'system' account 'admin' priv on all areas...\n"; +if (LJ::check_priv($u, "admin", "*")) { + print "Already has it.\n"; +} else { + my $sth = $dbh->prepare("INSERT INTO priv_map (userid, prlid, arg) ". + "SELECT $u->{'userid'}, prlid, '*' ". + "FROM priv_list WHERE privcode='admin'"); + $sth->execute; + if ($dbh->err || $sth->rows == 0) { + print "Couldn't grant system account admin privs\n"; + exit 1; + } +} + +print "Done.\n\n"; + + diff --git a/livejournal/bin/upgrading/migrate-phoneposts.pl b/livejournal/bin/upgrading/migrate-phoneposts.pl new file mode 100755 index 0000000..f0bc46a --- /dev/null +++ b/livejournal/bin/upgrading/migrate-phoneposts.pl @@ -0,0 +1,323 @@ +#!/usr/bin/perl + +use strict; +use lib "$ENV{LJHOME}/cgi-bin"; +require 'ljlib.pl'; +use LJ::Blob; +use LJ::User; +use Getopt::Long; +use IPC::Open3; +use Digest::MD5; + +# this script is a migrater that will move phone posts from an old storage method +# into mogilefs. + +# the basic theory is that we iterate over all clusters, find all phoneposts that +# aren't in mogile right now, and put them there + +# determine +my ($one, $besteffort, $dryrun, $user, $verify, $verbose, $clusters, $purge); +my $rv = GetOptions("best-effort" => \$besteffort, + "one" => \$one, + "dry-run" => \$dryrun, + "user=s" => \$user, + "verify" => \$verify, + "verbose" => \$verbose, + "purge-old" => \$purge, + "clusters=s" => \$clusters,); +unless ($rv) { + die <{phoneposts}; +die "Unable to find MogileFS object (\%LJ::MOGILEFS_CONFIG not setup?)\n" + unless $LJ::MogileFS; + +# setup stderr if we're in best effort mode +if ($besteffort) { + my $oldfd = select(STDERR); + $| = 1; + select($oldfd); +} + +# operation modes +if ($user) { + # move a single user + my $u = LJ::load_user($user); + die "No such user: $user\n" unless $u; + handle_userid($u->{userid}, $u->{clusterid}); + +} else { + # parse the clusters + my @clusters; + if ($clusters) { + if ($clusters =~ /^(\d+)(?:-(\d+))?$/) { + my ($min, $max) = map { $_ + 0 } ($1, $2 || $1); + push @clusters, $_ foreach $min..$max; + } else { + die "Error: --clusters argument not of right format.\n"; + } + } else { + @clusters = @LJ::CLUSTERS; + } + + # now iterate over the clusters to pick + my $ctotal = scalar(@clusters); + my $ccount = 0; + foreach my $cid (sort { $a <=> $b } @clusters) { + # status report + $ccount++; + print "\nChecking cluster $cid...\n\n"; + + # get a handle + my $dbcm = get_db_handle($cid); + + # get all userids + print "Getting userids...\n"; + my $limit = $one ? 'LIMIT 1' : ''; + my $userids = $dbcm->selectcol_arrayref + ("SELECT DISTINCT userid FROM phonepostentry WHERE (location='blob' OR location IS NULL) $limit"); + my $total = scalar(@$userids); + + # iterate over userids + my $count = 0; + print "Beginning iteration over userids...\n"; + foreach my $userid (@$userids) { + # move this phonepost + my $extra = sprintf("[%6.2f%%, $ccount of $ctotal] ", (++$count/$total*100)); + handle_userid($userid, $cid, $extra); + } + + # don't hit up more clusters + last if $one; + } +} +print "\n"; + +print "Updater terminating.\n"; + +############################################################################# +### helper subs down here + +# take a userid and move their phone posts +sub handle_userid { + my ($userid, $cid, $extra) = @_; + + # load user to move and do some sanity checks + my $u = LJ::load_userid($userid); + unless ($u) { + LJ::end_request(); + LJ::start_request(); + $u = LJ::load_userid($userid); + } + die "ERROR: Unable to load userid $userid\n" + unless $u; + + # if they're expunged, they might have data somewhere if they were + # copy-moved from A to B, then expunged on B. now we're on A and + # need to delete it ourselves (if purge-old is on) + if ($u->{clusterid} == 0 && $u->{statusvis} eq "X") { + return unless $purge; + # if we get here, the user has indicated they want data purged, get handle + my $to_purge_dbcm = get_db_handle($cid); + my $ct = $to_purge_dbcm->do("DELETE FROM phonepostentry WHERE userid = ?", undef, $u->{userid}); + print "\tnotice: purged $ct old rows.\n\n" + if $verbose; + return; + } + + # get a handle + my $dbcm = get_db_handle($u->{clusterid}); + + # print that we're doing this user + print "$extra$u->{user}($u->{userid})\n"; + + # if a user has been moved to another cluster, but the source data from + # phonepostentry wasn't deleted, we need to ignore the user or purge their data + if ($u->{clusterid} != $cid) { + return unless $purge; + + # verify they have some rows on the new side + my $count = $dbcm->selectrow_array + ("SELECT COUNT(*) FROM phonepostentry WHERE userid = ?", + undef, $u->{userid}); + return unless $count; + + # if we get here, the user has indicated they want data purged, get handle + my $to_purge_dbcm = get_db_handle($cid); + + # delete the old data + if ($dryrun) { + print "\tnotice: need to delete phonepostentry rows.\n\n" + if $verbose; + } else { + my $ct = $to_purge_dbcm->do("DELETE FROM phonepostentry WHERE userid = ?", undef, $u->{userid}); + print "\tnotice: purged $ct old rows.\n\n" + if $verbose; + } + + # nothing else to do here + return; + } + + # get all their photos that aren't in mogile already + my $rows = $dbcm->selectall_arrayref + ("SELECT filetype, blobid FROM phonepostentry WHERE userid = ? ". + "AND (location = 'blob' OR location IS NULL)", + undef, $u->{userid}); + return unless @$rows; + + # if a user has been moved to another cluster, but the source data from + # phonepost2 wasn't deleted, we need to ignore the user + return unless $u->{clusterid} == $cid; + + # now we have a userid and blobids, get the photos from the blob server + foreach my $row (@$rows) { + my ($filetype, $blobid) = @$row; + print "\tstarting move for blobid $blobid\n" + if $verbose; + my $format = { 0 => 'mp3', 1 => 'ogg', 2 => 'wav' }->{$filetype}; + my $data = LJ::Blob::get($u, "phonepost", $format, $blobid); + + # get length + my $len = length($data); + + if (! $len) { + my $has_blob = $dbcm->selectrow_array("SELECT COUNT(*) FROM userblob WHERE ". + "journalid=? AND domain=? AND blobid=?", + undef, $u->{userid}, + LJ::get_blob_domainid("phonepost"), + $blobid); + if (! $has_blob) { + $dbcm->do("UPDATE phonepostentry SET location='none' ". + "WHERE userid=? AND blobid=?", undef, $u->{userid}, $blobid); + print "\tnote: changed phonepost entry location to 'none'\n\n" + if $verbose; + next; + } + } + + if ($besteffort && !$len) { + print STDERR "empty_phonepost userid=$u->{userid} blobid=$blobid\n"; + print "\twarning: empty phonepost.\n\n" + if $verbose; + next; + } + die "Error: data from blob empty ($u->{user}, 'phonepost', $format, $blobid)\n" + unless $len; + + # get filehandle to Mogile and put the file there + print "\tdata length = $len bytes, uploading to MogileFS...\n" + if $verbose; + my $fh = $LJ::MogileFS->new_file("pp:$u->{userid}:$blobid", 'phoneposts'); + if ($besteffort && !$fh) { + print STDERR "new_file_failed userid=$u->{userid} blobid=$blobid\n"; + print "\twarning: failed in call to new_file\n\n" + if $verbose; + next; + } + die "Unable to get filehandle to save file to MogileFS\n" + unless $fh; + + # now save the file and close the handles + $fh->print($data); + my $rv = $fh->close; + if ($besteffort && !$rv) { + print STDERR "close_failed userid=$u->{userid} blobid=$blobid reason=$@\n"; + print "\twarning: failed in call to cloes: $@\n\n" + if $verbose; + next; + } + die "Unable to save file to MogileFS: $@\n" + unless $rv; + + # extra verification + if ($verify) { + my $data2 = $LJ::MogileFS->get_file_data("pp:$u->{userid}:$blobid"); + my $eq = ($data2 && $$data2 eq $data) ? 1 : 0; + if ($besteffort && !$eq) { + print STDERR "verify_failed userid=$u->{userid} blobid=$blobid\n"; + print "\twarning: verify failed; phone post not updated\n\n" + if $verbose; + next; + } + die "\tERROR: phone post NOT stored successfully, content mismatch\n" + unless $eq; + print "\tverified length = " . length($$data2) . " bytes...\n" + if $verbose; + } + + # done moving this phone post + unless ($dryrun) { + print "\tupdating database for this phone post...\n" + if $verbose; + $dbcm->do("UPDATE phonepostentry SET location = 'mogile' WHERE userid = ? AND blobid = ?", + undef, $u->{userid}, $blobid); + } + + # get the paths so the user can verify if they want + if ($verbose) { + my @paths = $LJ::MogileFS->get_paths("pp:$u->{userid}:$blobid", 1); + print "\tverify mogile path: $_\n" foreach @paths; + print "\tphone post update complete.\n\n"; + } + } +} + +# a sub to get a cluster handle and set it up for our use +sub get_db_handle { + my $cid = shift; + + my $dbcm = LJ::get_cluster_master({ raw => 1 }, $cid); + unless ($dbcm) { + print STDERR "handle_unavailable clusterid=$cid\n"; + die "ERROR: unable to get raw handle to cluster $cid\n"; + } + eval { + $dbcm->do("SET wait_timeout = 28800"); + die $dbcm->errstr if $dbcm->err; + }; + die "Couldn't set wait_timeout on $cid: $@\n" if $@; + $dbcm->{'RaiseError'} = 1; + + return $dbcm; +} diff --git a/livejournal/bin/upgrading/migrate-userpics.pl b/livejournal/bin/upgrading/migrate-userpics.pl new file mode 100755 index 0000000..1188f34 --- /dev/null +++ b/livejournal/bin/upgrading/migrate-userpics.pl @@ -0,0 +1,318 @@ +#!/usr/bin/perl + +use strict; +use lib "$ENV{LJHOME}/cgi-bin"; +require 'ljlib.pl'; +use LJ::Blob; +use LJ::User; +use Getopt::Long; +use IPC::Open3; +use Digest::MD5; + +# this script is a migrater that will move userpics from an old storage method +# into mogilefs. + +# the basic theory is that we iterate over all clusters, find all userpics that +# aren't in mogile right now, and put them there + +# determine +my ($one, $besteffort, $dryrun, $user, $verify, $verbose, $clusters, $purge); +my $rv = GetOptions("best-effort" => \$besteffort, + "one" => \$one, + "dry-run" => \$dryrun, + "user=s" => \$user, + "verify" => \$verify, + "verbose" => \$verbose, + "purge-old" => \$purge, + "clusters=s" => \$clusters,); +unless ($rv) { + die <{userpics}; +die "Unable to find MogileFS object (\%LJ::MOGILEFS_CONFIG not setup?)\n" + unless $LJ::MogileFS; + +# setup stderr if we're in best effort mode +if ($besteffort) { + my $oldfd = select(STDERR); + $| = 1; + select($oldfd); +} + +# operation modes +if ($user) { + # move a single user + my $u = LJ::load_user($user); + die "No such user: $user\n" unless $u; + handle_userid($u->{userid}, $u->{clusterid}); + +} else { + # parse the clusters + my @clusters; + if ($clusters) { + if ($clusters =~ /^(\d+)(?:-(\d+))?$/) { + my ($min, $max) = map { $_ + 0 } ($1, $2 || $1); + push @clusters, $_ foreach $min..$max; + } else { + die "Error: --clusters argument not of right format.\n"; + } + } else { + @clusters = @LJ::CLUSTERS; + } + + # now iterate over the clusters to pick + my $ctotal = scalar(@clusters); + my $ccount = 0; + foreach my $cid (sort { $a <=> $b } @clusters) { + # status report + $ccount++; + print "\nChecking cluster $cid...\n\n"; + + # get a handle + my $dbcm = get_db_handle($cid); + + # get all userids + print "Getting userids...\n"; + my $limit = $one ? 'LIMIT 1' : ''; + my $userids = $dbcm->selectcol_arrayref + ("SELECT DISTINCT userid FROM userpic2 WHERE location <> 'mogile' OR location IS NULL $limit"); + my $total = scalar(@$userids); + + # iterate over userids + my $count = 0; + print "Beginning iteration over userids...\n"; + foreach my $userid (@$userids) { + # move this userpic + my $extra = sprintf("[%6.2f%%, $ccount of $ctotal] ", (++$count/$total*100)); + handle_userid($userid, $cid, $extra); + } + + # don't hit up more clusters + last if $one; + } +} +print "\n"; + +print "Updater terminating.\n"; + +############################################################################# +### helper subs down here + +# take a userid and move their pictures. returns 0 on error, 1 on successful +# move of a user's pictures, and 2 meaning the user isn't ready for moving +# (dversion < 7, etc) +sub handle_userid { + my ($userid, $cid, $extra) = @_; + + # load user to move and do some sanity checks + my $u = LJ::load_userid($userid); + unless ($u) { + LJ::end_request(); + LJ::start_request(); + $u = LJ::load_userid($userid); + } + die "ERROR: Unable to load userid $userid\n" + unless $u; + + # if they're expunged, they might have data somewhere if they were + # copy-moved from A to B, then expunged on B. now we're on A and + # need to delete it ourselves (if purge-old is on) + if ($u->{clusterid} == 0 && $u->{statusvis} eq "X") { + return unless $purge; + # if we get here, the user has indicated they want data purged, get handle + my $to_purge_dbcm = get_db_handle($cid); + my $ct = $to_purge_dbcm->do("DELETE FROM userpic2 WHERE userid = ?", undef, $u->{userid}); + print "\tnotice: purged $ct old rows.\n\n" + if $verbose; + return; + } + + # get a handle + my $dbcm = get_db_handle($u->{clusterid}); + + # print that we're doing this user + print "$extra$u->{user}($u->{userid})\n"; + + # if a user has been moved to another cluster, but the source data from + # userpic2 wasn't deleted, we need to ignore the user or purge their data + if ($u->{clusterid} != $cid) { + return unless $purge; + + # verify they have some rows on the new side + my $count = $dbcm->selectrow_array + ("SELECT COUNT(*) FROM userpic2 WHERE userid = ?", + undef, $u->{userid}); + return unless $count; + + # if we get here, the user has indicated they want data purged, get handle + my $to_purge_dbcm = get_db_handle($cid); + + # delete the old data + if ($dryrun) { + print "\tnotice: need to delete userpic2 rows.\n\n" + if $verbose; + } else { + my $ct = $to_purge_dbcm->do("DELETE FROM userpic2 WHERE userid = ?", undef, $u->{userid}); + print "\tnotice: purged $ct old rows.\n\n" + if $verbose; + } + + # nothing else to do here + return; + } + + # get all their photos that aren't in mogile already + my $picids = $dbcm->selectall_arrayref + ("SELECT picid, md5base64, fmt FROM userpic2 WHERE userid = ? AND (location <> 'mogile' OR location IS NULL)", + undef, $u->{userid}); + return unless @$picids; + + # now we have a userid and picids, get the photos from the blob server + foreach my $row (@$picids) { + my ($picid, $md5, $fmt) = @$row; + print "\tstarting move for picid $picid\n" + if $verbose; + my $format = { G => 'gif', J => 'jpg', P => 'png' }->{$fmt}; + my $data = LJ::Blob::get($u, "userpic", $format, $picid); + + # get length + my $len = length($data); + if ($besteffort && !$len) { + print STDERR "empty_userpic userid=$u->{userid} picid=$picid\n"; + print "\twarning: empty userpic.\n\n" + if $verbose; + next; + } + die "Error: data from blob empty ($u->{user}, 'userpic', $format, $picid)\n" + unless $len; + + # verify the md5 of this picture with what's in the database + my $blobmd5 = Digest::MD5::md5_base64($data); + if ($besteffort && ($md5 ne $blobmd5)) { + print STDERR "md5_mismatch userid=$u->{userid} picid=$picid dbmd5=$md5 blobmd5=$blobmd5\n"; + print "\twarning: md5 mismatch; database=$md5, blobserver=$blobmd5\n\n" + if $verbose; + next; + } + die "\tError: data from blobserver md5 mismatch: database=$md5, blobserver=$blobmd5\n" + unless $md5 eq $blobmd5; + print "\tverified md5; database=$md5, blobserver=$blobmd5\n" + if $verbose; + + # get filehandle to Mogile and put the file there + print "\tdata length = $len bytes, uploading to MogileFS...\n" + if $verbose; + my $fh = $LJ::MogileFS->new_file($u->mogfs_userpic_key($picid), 'userpics'); + if ($besteffort && !$fh) { + print STDERR "new_file_failed userid=$u->{userid} picid=$picid\n"; + print "\twarning: failed in call to new_file\n\n" + if $verbose; + next; + } + die "Unable to get filehandle to save file to MogileFS\n" + unless $fh; + + # now save the file and close the handles + $fh->print($data); + my $rv = $fh->close; + if ($besteffort && !$rv) { + print STDERR "close_failed userid=$u->{userid} picid=$picid reason=$@\n"; + print "\twarning: failed in call to cloes: $@\n\n" + if $verbose; + next; + } + die "Unable to save file to MogileFS: $@\n" + unless $rv; + + # extra verification + if ($verify) { + my $data2 = $LJ::MogileFS->get_file_data($u->mogfs_userpic_key($picid)); + my $eq = ($data2 && $$data2 eq $data) ? 1 : 0; + if ($besteffort && !$eq) { + print STDERR "verify_failed userid=$u->{userid} picid=$picid\n"; + print "\twarning: verify failed; picture not updated\n\n" + if $verbose; + next; + } + die "\tERROR: picture NOT stored successfully, content mismatch\n" + unless $eq; + print "\tverified length = " . length($$data2) . " bytes...\n" + if $verbose; + } + + # done moving this picture + unless ($dryrun) { + print "\tupdating database for this picture...\n" + if $verbose; + $dbcm->do("UPDATE userpic2 SET location = 'mogile' WHERE userid = ? AND picid = ?", + undef, $u->{userid}, $picid); + } + + # get the paths so the user can verify if they want + if ($verbose) { + my @paths = $LJ::MogileFS->get_paths($u->mogfs_userpic_key($picid), 1); + print "\tverify mogile path: $_\n" foreach @paths; + print "\tverify site url: $LJ::SITEROOT/userpic/$picid/$u->{userid}\n"; + print "\tpicture update complete.\n\n"; + } + } +} + +# a sub to get a cluster handle and set it up for our use +sub get_db_handle { + my $cid = shift; + + my $dbcm = LJ::get_cluster_master({ raw => 1 }, $cid); + unless ($dbcm) { + print STDERR "handle_unavailable clusterid=$cid\n"; + die "ERROR: unable to get raw handle to cluster $cid\n"; + } + eval { + $dbcm->do("SET wait_timeout = 28800"); + die $dbcm->errstr if $dbcm->err; + }; + die "Couldn't set wait_timeout on $cid: $@\n" if $@; + $dbcm->{'RaiseError'} = 1; + + return $dbcm; +} diff --git a/livejournal/bin/upgrading/migrate-userprop.pl b/livejournal/bin/upgrading/migrate-userprop.pl new file mode 100755 index 0000000..df84150 --- /dev/null +++ b/livejournal/bin/upgrading/migrate-userprop.pl @@ -0,0 +1,162 @@ +#!/usr/bin/perl + +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +require 'ljlib.pl'; + +# so output happens quickly +$| = 1; + +# make sure we got a parameter +my $propname = shift; +die "ERROR: no property specified\n" unless $propname; + +# verify it's a valid property +my $prop = LJ::get_prop('user', $propname); + +# see if we know how to handle this parameter +if ($propname eq 'external_foaf_url' && $prop->{cldversion} == 0) { + # this one is simple; we're moving this one to the clusters 1000 users at a time + print "Beginning initial data migration...\n"; + cluster_property($prop); + + # update the property to be indexed + print "Updating property data in userproplist...\n"; + update_property($prop, { indexed => 0, cldversion => 4 }); + + # strongly recommend a restart + print "\n"; + print "* " x 38 . "\n"; + print "WARNING: It is recommended that you restart your web nodes now to cause the\n"; + print " updated property to start to take effect. Please press enter when\n"; + print " this is done.\n"; + print "* " x 38 . "\n"; + readline STDIN; + + # now let's hope they restarted and let's migrate anybody who is still stuck + print "Beginning final data migration...\n"; + cluster_property($prop); + + # done + print "Finished migrating external_foaf_url property.\n"; + +} else { + # don't know how to handle it + die "ERROR: don't know how to handle '$propname' (has it already been handled?)\n"; +} + +############################################################################## +### helper subs + +sub cluster_property { + my $prop = shift; + + # some state tracking information + my (%dbcms); # ( clusterid => dbcm ) + my (%to_write); # ( clusterid => [ [ userid, value ], [ userid, value ], ... ] + # note: livejournal has only about 7500 external_foaf_urls... those should + # be moved in less time than any database handle will time out, so I've made + # the decision not to worry about handle timeouts right now. all other sites + # are probably no more than this size, so it should be fine for everybody. + + # setup our flushing sub that we'll need later + my $flush = sub { + my $cid = shift; + + # get the ref from to_write etc + my $aref = $to_write{$cid}; + delete $to_write{$cid}; + + # get handle to database if needed + my $dbcm = $dbcms{$cid} || ($dbcms{$cid} = LJ::get_cluster_master($cid)); + + # notice that we're flushing data + print "\tflushing " . scalar(@$aref) . " items to cluster $cid..."; + + # now construct SQL + my $repstr = join(', ', map { "($_->[0], $prop->{upropid}, " . + $dbcm->quote($_->[1]) . ")" } @$aref); + $dbcm->do("REPLACE INTO userproplite2 (userid, upropid, value) VALUES $repstr"); + die "ERROR: database: " . $dbcm->errstr . "\n" if $dbcm->err; + + # done, status update + print "flushed\n"; + }; + + # start our main loop + while (1) { + # data storage for each loop + my (%users, %values); # ( userid => user object or value ) + + # clear our handles + $LJ::DBIRole->flush_cache(); + + # get main database handle + my $dbh = LJ::get_db_writer(); + + # select up to 1000 userid:value tuples + print "Getting values..."; + my $vals = $dbh->selectall_arrayref + ('SELECT userid, value FROM userprop WHERE upropid = ? LIMIT 1000', + undef, $prop->{upropid}); + die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err; + print "got " . scalar(@$vals) . " values.\n"; + + # short circuit if we have 0 + return 1 if scalar @$vals == 0; + + # get the userids to load + my @to_load; + foreach my $row (@$vals) { + my ($userid, $value) = @$row; + $values{$userid} = $value; + push @to_load, $userid; + } + + # now load the users in one big grab + print "Loading users..."; + LJ::load_userids_multiple([ map { $_ => \$users{$_} } @to_load ]); + print "loaded.\n"; + + # now push data onto the cluster lists + while (my ($userid, $value) = each %values) { + my $cid = $users{$userid}->{clusterid}; + + # clusterid 0 means the user is expunged or somesuch, so we + # don't weant to migrate their settings anywhere and should + # just delete it. + next unless $cid; + + # now push this onto the to_write array + $to_write{$cid} ||= []; + push @{$to_write{$cid}}, [ $userid, $value ]; + + # now, flush this list if it's large (100 or more) + $flush->($cid) if scalar @{$to_write{$cid}} >= 100; + } + + # now flush everything that's left + $flush->($_) foreach keys %to_write; + + # now delete from the global for items that we've written + print "Deleting " . scalar(keys %values) . " items from global..."; + my $instr = join(',', map { $_ + 0 } keys %values); + $dbh->do("DELETE FROM userprop WHERE upropid = $prop->{upropid} AND userid IN ($instr)"); + die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err; + print "deleted.\n"; + + # last if we had less than 1000 this time + last if scalar @$vals < 1000; + } +} + +sub update_property { + my ($prop, $sets) = @_; + die "ERROR: nothing to set\n" unless %$sets; + + # now make the updates they want + my $dbh = LJ::get_db_writer(); + my $updstr = join(', ', map { "$_ = " . $dbh->quote($sets->{$_}) } keys %$sets); + $dbh->do("UPDATE userproplist SET $updstr WHERE upropid = $prop->{upropid}"); + die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err; +} diff --git a/livejournal/bin/upgrading/moods.dat b/livejournal/bin/upgrading/moods.dat new file mode 100755 index 0000000..dfe548b --- /dev/null +++ b/livejournal/bin/upgrading/moods.dat @@ -0,0 +1,107 @@ +MOOD 1 aggravated 2 +MOOD 2 angry 0 +MOOD 3 annoyed 2 +MOOD 4 anxious 46 +MOOD 5 bored 25 +MOOD 6 confused 0 +MOOD 7 crappy 25 +MOOD 8 cranky 2 +MOOD 9 depressed 25 +MOOD 10 discontent 25 +MOOD 11 energetic 0 +MOOD 12 enraged 2 +MOOD 14 exhausted 74 +MOOD 15 happy 0 +MOOD 16 high 41 +MOOD 18 hungry 74 +MOOD 19 infuriated 2 +MOOD 20 irate 2 +MOOD 21 jubilant 15 +MOOD 22 lonely 25 +MOOD 23 moody 2 +MOOD 25 sad 0 +MOOD 26 satisfied 53 +MOOD 28 stressed 2 +MOOD 30 thoughtful 0 +MOOD 31 tired 14 +MOOD 32 touched 15 +MOOD 33 lazy 61 +MOOD 34 drunk 74 +MOOD 41 excited 15 +MOOD 42 relieved 26 +MOOD 43 hopeful 70 +MOOD 44 amused 15 +MOOD 46 scared 0 +MOOD 47 frustrated 2 +MOOD 49 sleepy 31 +MOOD 51 groggy 31 +MOOD 52 hyper 11 +MOOD 53 relaxed 15 +MOOD 54 restless 74 +MOOD 55 disappointed 25 +MOOD 56 curious 6 +MOOD 61 okay 0 +MOOD 68 calm 53 +MOOD 70 optimistic 15 +MOOD 71 pessimistic 38 +MOOD 74 uncomfortable 25 +MOOD 79 embarrassed 46 +MOOD 80 envious 10 +MOOD 81 sympathetic 25 +MOOD 82 sick 74 +MOOD 83 hot 74 +MOOD 84 cold 74 +MOOD 85 worried 25 +MOOD 86 loved 15 +MOOD 87 awake 0 +MOOD 88 working 0 +MOOD 89 productive 88 +MOOD 90 accomplished 88 +MOOD 91 busy 88 +MOOD 93 full 26 +MOOD 95 grumpy 2 +MOOD 96 weird 66 +MOOD 98 ecstatic 15 +MOOD 101 contemplative 30 +MOOD 102 nerdy 0 +MOOD 103 geeky 102 +MOOD 104 cynical 2 +MOOD 106 crazy 66 +MOOD 107 creative 88 +MOOD 109 pleased 15 +MOOD 112 irritated 2 +MOOD 113 blank 78 +MOOD 114 apathetic 78 +MOOD 115 dorky 102 +MOOD 116 impressed 15 +MOOD 117 naughty 36 +MOOD 119 dirty 74 +MOOD 120 giddy 66 +MOOD 121 surprised 15 +MOOD 122 shocked 121 +MOOD 123 rejected 25 +MOOD 124 numb 25 +MOOD 125 cheerful 15 +MOOD 126 good 15 +MOOD 127 distressed 4 +MOOD 128 intimidated 46 +MOOD 130 devious 0 +MOOD 131 thankful 15 +MOOD 132 grateful 15 +MOOD 133 jealous 25 +MOOD 134 nervous 46 +MOODTHEME Classic Smileys : The classic little yellow (and other color) smiley faces. +2 /img/mood/classic/angry.gif 15 15 +6 /img/mood/classic/confused.gif 19 17 +11 /img/mood/classic/energetic.gif 17 17 +15 /img/mood/classic/smile.gif 15 15 +25 /img/mood/classic/sad.gif 15 15 +30 /img/mood/classic/thinking.gif 22 21 +31 /img/mood/classic/tired.gif 19 17 +34 /img/mood/classic/drunk.gif 15 15 +46 /img/mood/classic/shock.gif 15 15 +61 /img/mood/classic/blah.gif 15 15 +66 /img/mood/classic/wink.gif 15 15 +79 /img/mood/classic/blush.gif 15 15 +82 /img/mood/classic/sick.gif 15 15 +130 /img/mood/classic/devious.gif 15 15 diff --git a/livejournal/bin/upgrading/move0cluster.pl b/livejournal/bin/upgrading/move0cluster.pl new file mode 100755 index 0000000..8a7ed30 --- /dev/null +++ b/livejournal/bin/upgrading/move0cluster.pl @@ -0,0 +1,886 @@ +#!/usr/bin/perl +# +# Moves a user between clusters. +# + +use strict; +use Getopt::Long; + +my $opt_del = 0; +my $opt_destdel = 0; +my $opt_useslow = 0; +my $opt_slowalloc = 0; +my $opt_verbose = 1; +my $opt_movemaster = 0; +my $opt_prelocked = 0; +my $opt_expungedel = 0; +my $opt_ignorebit = 0; +exit 1 unless GetOptions('delete' => \$opt_del, + 'destdelete' => \$opt_destdel, + 'useslow' => \$opt_useslow, # use slow db role for read + 'slowalloc' => \$opt_slowalloc, # see note below + 'verbose=i' => \$opt_verbose, + 'movemaster|mm' => \$opt_movemaster, + 'prelocked' => \$opt_prelocked, + 'expungedel' => \$opt_expungedel, + 'ignorebit' => \$opt_ignorebit, + ); +my $optv = $opt_verbose; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl"; + +my $dbh = LJ::get_dbh({raw=>1}, "master"); +die "No master db available.\n" unless $dbh; +$dbh->do("SET wait_timeout=28800"); + +my $dbr = $dbh; +if ($opt_useslow) { + $dbr = LJ::get_dbh({raw=>1}, "slow"); + unless ($dbr) { die "Can't get slow db from which to read.\n"; } +} + +my $user = LJ::canonical_username(shift @ARGV); +my $dclust = shift @ARGV; + +# tables which are dumbly copied by sucking all into memory first. +# use smarter mover code for anything that shouldn't all go into memory. +# also, to use this you have to define the primary keys below +my @manual_move = qw(loginstall ratelog sessions userproplite2 + sessions_data userbio userpicblob2 userpropblob + s1usercache modlog modblob counter + s1style s1overrides links userblob clustertrack2); +sub usage { + die "Usage:\n movecluster.pl \n"; +} + +usage() unless defined $user; +usage() unless defined $dclust; + +die "Failed to get move lock.\n" + unless ($dbh->selectrow_array("SELECT GET_LOCK('moveucluster-$user', 10)")); + +my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE user=?", undef, $user); +die "Non-existent user $user.\n" unless $u; + +die "Can't move back to legacy cluster 0\n" unless $dclust; + +my $dbch = LJ::get_cluster_master({raw=>1}, $dclust); + +die "Undefined or down cluster \#$dclust\n" unless $dbch; +$dbch->do("SET wait_timeout=28800"); + +my $separate_cluster = LJ::use_diff_db("master", "cluster$dclust"); + +$dbh->{'RaiseError'} = 1; +$dbch->{'RaiseError'} = 1; + +my $sclust = $u->{'clusterid'}; + +if ($sclust == $dclust) { + die "User '$user' is already on cluster $dclust\n"; +} + +if ($sclust) { + verify_movable_tables(); +} + +# original cluster db handle. +my $dbo; +if ($sclust) { + $dbo = $opt_movemaster ? + LJ::get_dbh({raw=>1}, "cluster$u->{clusterid}movemaster") : + LJ::get_cluster_master({raw=>1}, $u); + die "Can't get source cluster handle.\n" unless $dbo; + $dbo->{'RaiseError'} = 1; + $dbo->do("SET wait_timeout=28800"); +} + +my $userid = $u->{'userid'}; + +# find readonly cap class, complain if not found +my $readonly_bit = undef; +foreach (keys %LJ::CAP) { + if ($LJ::CAP{$_}->{'_name'} eq "_moveinprogress" && + $LJ::CAP{$_}->{'readonly'} == 1) { + $readonly_bit = $_; + last; + } +} +unless (defined $readonly_bit) { + die "Won't move user without %LJ::CAP capability class named '_moveinprogress' with readonly => 1\n"; +} + +# make sure a move isn't already in progress +if ($opt_prelocked) { + unless (($u->{'caps'}+0) & (1 << $readonly_bit)) { + die "User '$user' should have been prelocked.\n"; + } +} else { + if (($u->{'caps'}+0) & (1 << $readonly_bit)) { + die "User '$user' is already in the process of being moved? (cap bit $readonly_bit set)\n" + unless $opt_ignorebit; + } +} + +if ($opt_expungedel && $u->{'statusvis'} eq "D" && + LJ::mysqldate_to_time($u->{'statusvisdate'}) < time() - 86400*31) { + + print "Expunging user '$u->{'user'}'\n"; + $dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart, timedone) ". + "VALUES (?,?,?,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())", undef, + $userid, $sclust, 0); + LJ::update_user($userid, { clusterid => 0, + statusvis => 'X', + raw => "caps=caps&~(1<<$readonly_bit), statusvisdate=NOW()" }); + exit 0; +} + +print "Moving '$u->{'user'}' from cluster $sclust to $dclust\n" if $optv >= 1; + +# mark that we're starting the move +$dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart) ". + "VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $userid, $sclust, $dclust); +my $cmid = $dbh->{'mysql_insertid'}; + +# set readonly cap bit on user +LJ::update_user($userid, { raw => "caps=caps|(1<<$readonly_bit)" }) + unless $opt_prelocked; +$dbh->do("SELECT RELEASE_LOCK('moveucluster-$user')"); + +unless ($opt_prelocked) { +# wait a bit for writes to stop if journal is somewhat active (last week update) + my $secidle = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ". + "FROM userusage WHERE userid=$userid"); + if ($secidle) { + sleep(2) unless $secidle > 86400*7; + sleep(1) unless $secidle > 86400; + } +} + +# make sure slow is caught up: +if ($opt_useslow) +{ + my $ms = $dbh->selectrow_hashref("SHOW MASTER STATUS"); + my $loop = 1; + while ($loop) { + my $ss = $dbr->selectrow_hashref("SHOW SLAVE STATUS"); + $loop = 0; + unless ($ss->{'Log_File'} gt $ms->{'File'} || + ($ss->{'Log_File'} eq $ms->{'File'} && $ss->{'Pos'} >= $ms->{'Position'})) + { + $loop = 1; + print "Waiting for slave ($ss->{'Pos'} < $ms->{'Position'})\n"; + sleep 1; + } + } +} + +my $last = time(); +my $stmsg = sub { + my $msg = shift; + my $now = time(); + return if ($now < $last + 1); + $last = $now; + print $msg; +}; + +my %bufcols = (); # db|table -> scalar "(foo, anothercol, lastcol)" or undef or "" +my %bufrows = (); # db|table -> [ []+ ] +my %bufdbmap = (); # scalar(DBI hashref) -> DBI hashref + +my $flush_buffer = sub { + my $dbandtable = shift; + my ($db, $table) = split(/\|/, $dbandtable); + $db = $bufdbmap{$db}; + return unless exists $bufcols{$dbandtable}; + my $sql = "REPLACE INTO $table $bufcols{$dbandtable} VALUES "; + $sql .= join(", ", + map { my $r = $_; + "(" . join(", ", + map { $db->quote($_) } @$r) . ")" } + @{$bufrows{$dbandtable}}); + $db->do($sql); + delete $bufrows{$dbandtable}; + delete $bufcols{$dbandtable}; +}; + +my $flush_all = sub { + foreach (keys %bufcols) { + $flush_buffer->($_); + } +}; + +my $replace_into = sub { + my $db = ref $_[0] ? shift : $dbch; # optional first arg + my ($table, $cols, $max, @vals) = @_; + my $dbandtable = scalar($db) . "|$table"; + $bufdbmap{$db} = $db; + if (exists $bufcols{$dbandtable} && $bufcols{$dbandtable} ne $cols) { + $flush_buffer->($dbandtable); + } + $bufcols{$dbandtable} = $cols; + push @{$bufrows{$dbandtable}}, [ @vals ]; + + if (scalar @{$bufrows{$dbandtable}} > $max) { + $flush_buffer->($dbandtable); + } +}; + +# assume never tried to move this user before. however, if reported crap +# in the oldids table, we'll revert to slow alloc_id functionality, +# where we do a round-trip to $dbh for everything and see if every id +# has been remapped already. otherwise we do it in perl and batch +# updates to the oldids table, which is the common/fast case. +my $first_move = ! $opt_slowalloc; + +my %alloc_data; +my %alloc_arealast; +my $alloc_id = sub { + my ($area, $orig) = @_; + + # fast version + if ($first_move) { + my $id = $alloc_data{$area}->{$orig} = ++$alloc_arealast{$area}; + $replace_into->($dbh, "oldids", "(area, oldid, userid, newid)", 250, + $area, $orig, $userid, $id); + return $id; + } + + # slow version + $dbh->{'RaiseError'} = 0; + $dbh->do("INSERT INTO oldids (area, oldid, userid, newid) ". + "VALUES ('$area', $orig, $userid, NULL)"); + my $id; + if ($dbh->err) { + $id = $dbh->selectrow_array("SELECT newid FROM oldids WHERE area='$area' AND oldid=$orig"); + } else { + $id = $dbh->{'mysql_insertid'}; + } + $dbh->{'RaiseError'} = 1; + $alloc_data{$area}->{$orig} = $id; + return $id; +}; + +my $bufread; + +if ($sclust == 0) +{ + # do bio stuff + { + my $bio = $dbr->selectrow_array("SELECT bio FROM userbio WHERE userid=$userid"); + my $bytes = length($bio); + $dbch->do("REPLACE INTO dudata (userid, area, areaid, bytes) VALUES ($userid, 'B', 0, $bytes)"); + if ($separate_cluster) { + $bio = $dbh->quote($bio); + $dbch->do("REPLACE INTO userbio (userid, bio) VALUES ($userid, $bio)"); + } + } + + my @itemids = reverse @{$dbr->selectcol_arrayref("SELECT itemid FROM log ". + "WHERE ownerid=$u->{'userid'} ". + "ORDER BY ownerid, rlogtime")}; + + $bufread = make_buffer_reader("itemid", \@itemids); + + my $todo = @itemids; + my $done = 0; + my $stime = time(); + print "Total: $todo\n"; + + # moving time, journal item at a time, and everything recursively under it + foreach my $itemid (@itemids) { + movefrom0_logitem($itemid); + $done++; + my $percent = $done/$todo; + my $elapsed = time() - $stime; + my $totaltime = $elapsed * (1 / $percent); + my $timeremain = int($totaltime - $elapsed); + $stmsg->(sprintf "$user: copy $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent); + } + + $flush_all->(); + + # update their memories. in particular, any memories of their own + # posts need to to be updated from the (0, globalid) to + # (journalid, jitemid) format, to make the memory filter feature + # work. (it checks the first 4 bytes only, not joining the + # globalid on the clustered log table) + print "Fixing memories.\n"; + my @fix = @{$dbh->selectall_arrayref("SELECT memid, jitemid FROM memorable WHERE ". + "userid=$u->{'userid'} AND journalid=0")}; + foreach my $f (@fix) { + my ($memid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]}); + next unless $newid; + my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ". + "WHERE journalid=$u->{'userid'} AND ". + "jitemid=$newid"); + if ($newid2 == $newid) { + my $ditemid = $newid * 256 + $anum; + print "UPDATE $memid TO $ditemid\n"; + $dbh->do("UPDATE memorable SET journalid=$u->{'userid'}, jitemid=$ditemid ". + "WHERE memid=$memid"); + } + } + + # fix polls + print "Fixing polls.\n"; + @fix = @{$dbh->selectall_arrayref("SELECT pollid, itemid FROM poll ". + "WHERE journalid=$u->{'userid'}")}; + foreach my $f (@fix) { + my ($pollid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]}); + next unless $newid; + my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ". + "WHERE journalid=$u->{'userid'} AND ". + "jitemid=$newid"); + if ($newid2 == $newid) { + my $ditemid = $newid * 256 + $anum; + print "UPDATE $pollid TO $ditemid\n"; + $dbh->do("UPDATE poll SET itemid=$ditemid WHERE pollid=$pollid"); + } + } + + # move userpics + print "Copying over userpics.\n"; + my @pics = @{$dbr->selectcol_arrayref("SELECT picid FROM userpic WHERE ". + "userid=$u->{'userid'}")}; + foreach my $picid (@pics) { + print " picid\#$picid...\n"; + my $imagedata = $dbr->selectrow_array("SELECT imagedata FROM userpicblob ". + "WHERE picid=$picid"); + $imagedata = $dbh->quote($imagedata); + $dbch->do("REPLACE INTO userpicblob2 (userid, picid, imagedata) VALUES ". + "($u->{'userid'}, $picid, $imagedata)"); + } + + $dbh->do("UPDATE userusage SET lastitemid=0 WHERE userid=$userid"); + + my $dversion = 2; + + # if everything's good (nothing's died yet), then delete all from source + if ($opt_del) + { + # before we start deleting, record they've moved servers. + LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust }); + + $done = 0; + $stime = time(); + foreach my $itemid (@itemids) { + deletefrom0_logitem($itemid); + $done++; + my $percent = $done/$todo; + my $elapsed = time() - $stime; + my $totaltime = $elapsed * (1 / $percent); + my $timeremain = int($totaltime - $elapsed); + $stmsg->(sprintf "$user: delete $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent); + } + + # delete bio from source, if necessary + if ($separate_cluster) { + $dbh->do("DELETE FROM userbio WHERE userid=$userid"); + } + + # delete source userpics + print "Deleting cluster0 userpics...\n"; + foreach my $picid (@pics) { + print " picid\#$picid...\n"; + $dbh->do("DELETE FROM userpicblob WHERE picid=$picid"); + } + + # unset read-only bit (marks the move is complete, also, and not aborted mid-delete) + LJ::update_user($userid, { raw => "caps=caps&~(1<<$readonly_bit)" }); + $dbh->do("UPDATE clustermove SET sdeleted='1', timedone=UNIX_TIMESTAMP() ". + "WHERE cmid=?", undef, $cmid); + + } + else + { + # unset readonly and move to new cluster in one update + LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust, + raw => "caps=caps&~(1<<$readonly_bit)" }); + $dbh->do("UPDATE clustermove SET sdeleted='0', timedone=UNIX_TIMESTAMP() ". + "WHERE cmid=?", undef, $cmid); + } + exit 0; +} +elsif ($sclust > 0) +{ + print "Moving away from cluster $sclust\n" if $optv; + + while (my $cmd = $dbo->selectrow_array("SELECT cmd FROM cmdbuffer WHERE journalid=$userid")) { + my $dbcm = LJ::get_cluster_master($sclust); + print "Flushing cmdbuffer for cmd: $cmd\n" if $optv > 1; + LJ::Cmdbuffer::flush($dbh, $dbcm, $cmd, $userid); + } + + my $pri_key = { + # flush this first: + 'cmdbuffer' => 'journalid', + + # this is populated as we do log/talk + 'dudata' => 'userid', + + # manual + 'loginstall' => 'userid', + 'ratelog' => 'userid', + 'sessions' => 'userid', + 'sessions_data' => 'userid', + 'userbio' => 'userid', + 'userpicblob2' => 'userid', + 'userproplite2' => 'userid', + 's1usercache' => 'userid', + 'modlog' => 'journalid', + 'modblob' => 'journalid', + 'counter' => 'journalid', + 'userblob' => 'journalid', + 'userpropblob' => 'userid', + 'clustertrack2' => 'userid', + + # log + 'log2' => 'journalid', + 'logsec2' => 'journalid', + 'logprop2' => 'journalid', + 'logtext2' => 'journalid', + + # talk + 'talk2' => 'journalid', + 'talkprop2' => 'journalid', + 'talktext2' => 'journalid', + + # no primary key... move up by posttime + 'talkleft' => 'userid', + + # s1 styles + 's1style' => 'userid', + 's1overrides' => 'userid', + + # link lists + 'links' => 'journalid', + }; + + # ask the local mods if they have any tables to move + my @local_tables; + my $local_tables = LJ::run_hook("moveucluster_local_tables"); + if ($local_tables) { + while (my ($tab, $key) = each %$local_tables) { + push @local_tables, $tab; + $pri_key->{$tab} = $key; + } + } + + my @existing_data; + print "Checking for existing data on target cluster...\n" if $optv > 1; + foreach my $table (sort keys %$pri_key) { + my $pri = $pri_key->{$table}; + my $is_there = $dbch->selectrow_array("SELECT $pri FROM $table WHERE $pri=$userid LIMIT 1"); + next unless $is_there; + if ($opt_destdel) { + while ($dbch->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) { + print " deleted from $table\n" if $optv; + } + } else { + push @existing_data, $table; + } + } + if (@existing_data) { + die " Existing data in tables: @existing_data\n"; + } + + my %pendreplace; # "logprop2:(col,col)" => { 'values' => [ [a, b, c], [d, e, f] ], + # 'bytes' => 3043, 'recs' => 35 } + my $flush = sub { + my $dest = shift; + return 1 unless $pendreplace{$dest}; + my ($table, $cols) = split(/:/, $dest); + my $vals; + foreach my $v (@{$pendreplace{$dest}->{'values'}}) { + $vals .= "," if $vals; + $vals .= "(" . join(',', map { $dbch->quote($_) } @$v) . ")"; + } + print " flushing write to $table\n" if $optv > 1; + $dbch->do("REPLACE INTO $table $cols VALUES $vals"); + die $dbh->errstr if $dbch->err; + delete $pendreplace{$dest}; + return 1; + }; + + my $write = sub { + my $dest = shift; + my @values = @_; + my $new_bytes = 0; foreach (@values) { $new_bytes += length($_); } + push @{$pendreplace{$dest}->{'values'}}, \@values; + $pendreplace{$dest}->{'bytes'} += $new_bytes; + $pendreplace{$dest}->{'recs'}++; + if ($pendreplace{$dest}->{'bytes'} > 1024*500 || + $pendreplace{$dest}->{'recs'} > 500) { $flush->($dest); } + }; + + my @styleids = (); + + # manual moving (dumb copies) + foreach my $table (@manual_move, @local_tables) { + next if ($table eq "modlog" || $table eq "modblob") && $u->{journaltype} eq "P"; + print " moving $table ...\n" if $optv > 1; + my @cols; + my $sth = $dbo->prepare("DESCRIBE $table"); + $sth->execute; + my $styleidcolnum = -1; + my $colnum = 0; + while ($_ = $sth->fetchrow_hashref) { + push @cols, $_->{'Field'}; + $styleidcolnum = $colnum if $_->{'Field'} eq 'styleid'; + $colnum++; + } + my $cols = join(',', @cols); + my $dest = "$table:($cols)"; + my $pri = $pri_key->{$table}; + $sth = $dbo->prepare("SELECT $cols FROM $table WHERE $pri=$userid"); + $sth->execute; + while (my @vals = $sth->fetchrow_array) { + $write->($dest, @vals); + if ($styleidcolnum > -1 && $table eq 's1style') { + push @styleids, $vals[$styleidcolnum]; + } + } + } + + # size of bio + my $bio_size = $dbch->selectrow_array("SELECT LENGTH(bio) FROM userbio WHERE userid=$userid"); + $write->("dudata:(userid,area,areaid,bytes)", $userid, 'B', 0, $bio_size) if $bio_size; + + # journal items + { + my $maxjitem = $dbo->selectrow_array("SELECT MAX(jitemid) FROM log2 WHERE journalid=$userid"); + my $load_amt = 1000; + my ($lo, $hi) = (1, $load_amt); + my $sth; + my $cols = "security,allowmask,journalid,jitemid,posterid,eventtime,logtime,compressed,anum,replycount,year,month,day,rlogtime,revttime"; # order matters. see indexes below + while ($lo <= $maxjitem) { + print " log ($lo - $hi, of $maxjitem)\n" if $optv > 1; + + # log2/logsec2 + $sth = $dbo->prepare("SELECT $cols FROM log2 ". + "WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi"); + $sth->execute; + while (my @vals = $sth->fetchrow_array) { + $write->("log2:($cols)", @vals); + + if ($vals[0] eq "usemask") { + $write->("logsec2:(journalid,jitemid,allowmask)", + $userid, $vals[3], $vals[1]); + } + } + + # logprop2 + $sth = $dbo->prepare("SELECT journalid,jitemid,propid,value ". + "FROM logprop2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi"); + $sth->execute; + while (my @vals = $sth->fetchrow_array) { + $write->("logprop2:(journalid,jitemid,propid,value)", @vals); + } + + # logtext2 + $sth = $dbo->prepare("SELECT journalid,jitemid,subject,event ". + "FROM logtext2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi"); + $sth->execute; + while (my @vals = $sth->fetchrow_array) { + my $size = length($vals[2]) + length($vals[3]); + LJ::text_compress(\$vals[3]); + $write->("logtext2:(journalid,jitemid,subject,event)", @vals); + $write->("dudata:(userid,area,areaid,bytes)", $userid, 'L', $vals[1], $size); + } + + $hi += $load_amt; $lo += $load_amt; + } + } + + # comments + { + my $maxtalkid = $dbo->selectrow_array("SELECT MAX(jtalkid) FROM talk2 WHERE journalid=$userid"); + my $load_amt = 1000; + my ($lo, $hi) = (1, $load_amt); + my $sth; + + my %cols = ('talk2' => 'journalid,jtalkid,nodetype,nodeid,parenttalkid,posterid,datepost,state', + 'talkprop2' => 'journalid,jtalkid,tpropid,value', + 'talktext2' => 'journalid,jtalkid,subject,body'); + while ($lo <= $maxtalkid) { + print " talk ($lo - $hi, of $maxtalkid)\n" if $optv > 1; + foreach my $table (keys %cols) { + $sth = $dbo->prepare("SELECT $cols{$table} FROM $table ". + "WHERE journalid=$userid AND jtalkid BETWEEN $lo AND $hi"); + $sth->execute; + while (my @vals = $sth->fetchrow_array) { + LJ::text_compress(\$vals[3]) if $table eq "talktext2"; + $write->("$table:($cols{$table})", @vals); + } + } + + $hi += $load_amt; $lo += $load_amt; + } + } + + # talkleft table. + { + # no primary key... delete all of target first. + while ($dbch->do("DELETE FROM talkleft WHERE userid=$userid LIMIT 1000") > 0) { + print " deleted from talkleft\n" if $optv > 1; + } + + my $last_max = 0; + my $cols = "userid,posttime,journalid,nodetype,nodeid,jtalkid,publicitem"; + while (defined $last_max) { + print " talkleft: $last_max\n" if $optv > 1; + my $sth = $dbo->prepare("SELECT $cols FROM talkleft WHERE userid=$userid ". + "AND posttime > $last_max ORDER BY posttime LIMIT 1000"); + $sth->execute; + undef $last_max; + while (my @vals = $sth->fetchrow_array) { + $write->("talkleft:($cols)", @vals); + $last_max = $vals[1]; + } + } + } + + # flush remaining items + foreach (keys %pendreplace) { $flush->($_); } + + # unset readonly and move to new cluster in one update + LJ::update_user($userid, { clusterid => $dclust, raw => "caps=caps&~(1<<$readonly_bit)" }); + print "Moved.\n" if $optv; + + # delete from source cluster + if ($opt_del) { + print "Deleting from source cluster...\n" if $optv; + foreach my $table (sort keys %$pri_key) { + my $pri = $pri_key->{$table}; + while ($dbo->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) { + print " deleted from $table\n" if $optv; + } + } + + # s1stylecache table + if (@styleids) { + my $styleids_in = join(",", map { $dbo->quote($_) } @styleids); + if ($dbo->do("DELETE FROM s1stylecache WHERE styleid IN ($styleids_in)") > 0) { + print " deleted from s1stylecache\n" if $optv; + } + } + } else { + # at minimum, we delete the clustertrack2 row so it doesn't get + # included in a future ljumover.pl query from that cluster. + $dbo->do("DELETE FROM clustertrack2 WHERE userid=$userid"); + } + + $dbh->do("UPDATE clustermove SET sdeleted=?, timedone=UNIX_TIMESTAMP() ". + "WHERE cmid=?", undef, $opt_del ? 1 : 0, $cmid); + exit 0; +} + +sub deletefrom0_logitem +{ + my $itemid = shift; + + # delete all the comments + my $talkids = $dbh->selectcol_arrayref("SELECT talkid FROM talk ". + "WHERE nodetype='L' AND nodeid=$itemid"); + + my $talkidin = join(",", @$talkids); + if ($talkidin) { + foreach my $table (qw(talktext talkprop talk)) { + $dbh->do("DELETE FROM $table WHERE talkid IN ($talkidin)"); + } + } + + $dbh->do("DELETE FROM logsec WHERE ownerid=$userid AND itemid=$itemid"); + foreach my $table (qw(logprop logtext log)) { + $dbh->do("DELETE FROM $table WHERE itemid=$itemid"); + } +} + +sub movefrom0_logitem +{ + my $itemid = shift; + + my $item = $bufread->(100, "SELECT * FROM log", $itemid); + my $itemtext = $bufread->(50, "SELECT itemid, subject, event FROM logtext", $itemid); + return 1 unless $item && $itemtext; # however that could happen. + + # we need to allocate a new jitemid (journal-specific itemid) for this item now. + my $jitemid = $alloc_id->('L', $itemid); + unless ($jitemid) { + die "ERROR: could not allocate a new jitemid\n"; + } + $dbh->{'RaiseError'} = 1; + $item->{'jitemid'} = $jitemid; + $item->{'anum'} = int(rand(256)); + + # copy item over: + $replace_into->("log2", "(journalid, jitemid, posterid, eventtime, logtime, ". + "compressed, security, allowmask, replycount, year, month, day, ". + "rlogtime, revttime, anum)", + 50, map { $item->{$_} } qw(ownerid jitemid posterid eventtime + logtime compressed security allowmask replycount + year month day rlogtime revttime anum)); + + $replace_into->("logtext2", "(journalid, jitemid, subject, event)", 10, + $userid, $jitemid, map { $itemtext->{$_} } qw(subject event)); + + # add disk usage info! (this wasn't in cluster0 anywhere) + my $bytes = length($itemtext->{'event'}) + length($itemtext->{'subject'}); + $replace_into->("dudata", "(userid, area, areaid, bytes)", 50, $userid, 'L', $jitemid, $bytes); + + # add the logsec item, if necessary: + if ($item->{'security'} ne "public") { + $replace_into->("logsec2", "(journalid, jitemid, allowmask)", 50, + map { $item->{$_} } qw(ownerid jitemid allowmask)); + } + + # copy its logprop over: + while (my $lp = $bufread->(50, "SELECT itemid, propid, value FROM logprop", $itemid)) { + next unless $lp->{'value'}; + $replace_into->("logprop2", "(journalid, jitemid, propid, value)", 50, + $userid, $jitemid, $lp->{'propid'}, $lp->{'value'}); + } + + # copy its talk shit over: + my %newtalkids = (0 => 0); # 0 maps back to 0 still + my $talkids = $dbr->selectcol_arrayref("SELECT talkid FROM talk ". + "WHERE nodetype='L' AND nodeid=$itemid"); + my @talkids = sort { $a <=> $b } @$talkids; + my $treader = make_buffer_reader("talkid", \@talkids); + foreach my $t (@talkids) { + movefrom0_talkitem($t, $jitemid, \%newtalkids, $item, $treader); + } +} + +sub movefrom0_talkitem +{ + my $talkid = shift; + my $jitemid = shift; + my $newtalkids = shift; + my $logitem = shift; + my $treader = shift; + + my $item = $treader->(100, "SELECT *, UNIX_TIMESTAMP(datepost) AS 'datepostunix' FROM talk", $talkid); + my $itemtext = $treader->(50, "SELECT talkid, subject, body FROM talktext", $talkid); + return 1 unless $item && $itemtext; # however that could happen. + + # abort if this is a stranded entry. (shouldn't happen, anyway. even if it does, it's + # not like we're losing data: the UI (talkread.bml) won't show it anyway) + return unless defined $newtalkids->{$item->{'parenttalkid'}}; + + # we need to allocate a new jitemid (journal-specific itemid) for this item now. + my $jtalkid = $alloc_id->('T', $talkid); + unless ($jtalkid) { + die "ERROR: could not allocate a new jtalkid\n"; + } + $newtalkids->{$talkid} = $jtalkid; + $dbh->{'RaiseError'} = 1; + + # copy item over: + $replace_into->("talk2", "(journalid, jtalkid, parenttalkid, nodeid, ". + "nodetype, posterid, datepost, state)", 50, + $userid, $jtalkid, $newtalkids->{$item->{'parenttalkid'}}, + $jitemid, 'L', map { $item->{$_} } qw(posterid datepost state)); + + + $replace_into->("talktext2", "(journalid, jtalkid, subject, body)", + 20, $userid, $jtalkid, map { $itemtext->{$_} } qw(subject body)); + + # copy its logprop over: + while (my $lp = $treader->(50, "SELECT talkid, tpropid, value FROM talkprop", $talkid)) { + next unless $lp->{'value'}; + $replace_into->("talkprop2", "(journalid, jtalkid, tpropid, value)", 50, + $userid, $jtalkid, $lp->{'tpropid'}, $lp->{'value'}); + } + + # note that poster commented here + if ($item->{'posterid'}) { + my $pub = $logitem->{'security'} eq "public" ? 1 : 0; + my ($table, $db) = ("talkleft_xfp", $dbh); + ($table, $db) = ("talkleft", $dbch) if $userid == $item->{'posterid'}; + $replace_into->($db, $table, "(userid, posttime, journalid, nodetype, ". + "nodeid, jtalkid, publicitem)", 50, + $item->{'posterid'}, $item->{'datepostunix'}, $userid, + 'L', $jitemid, $jtalkid, $pub); + } +} + +sub make_buffer_reader +{ + my $pricol = shift; + my $valsref = shift; + + my %bfd; # buffer read data. halfquery -> { 'rows' => { id => [] }, + # 'remain' => [], 'loaded' => { id => 1 } } + return sub + { + my ($amt, $hq, $pid) = @_; + if (not defined $bfd{$hq}->{'loaded'}->{$pid}) + { + if (not exists $bfd{$hq}->{'remain'}) { + $bfd{$hq}->{'remain'} = [ @$valsref ]; + } + + my @todo; + for (1..$amt) { + next unless @{$bfd{$hq}->{'remain'}}; + my $id = shift @{$bfd{$hq}->{'remain'}}; + push @todo, $id; + $bfd{$hq}->{'loaded'}->{$id} = 1; + } + + if (@todo) { + my $sql = "$hq WHERE $pricol IN (" . join(",", @todo) . ")"; + my $sth = $dbr->prepare($sql); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) { + push @{$bfd{$hq}->{'rows'}->{$r->{$pricol}}}, $r; + } + } + } + + return shift @{$bfd{$hq}->{'rows'}->{$pid}}; + }; +} + +# this function needs to die loudly if moveucluster.pl is unable to move +# any type of table that exists on this installation +sub verify_movable_tables { + my %table; # tablename -> unhandled flag + + # first, assume everything's unhandled + foreach my $t (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL) { + $table{$t} = 1; + } + + # now, clear things we know how to move + foreach my $t (qw(cmdbuffer dudata log2 logsec2 logprop2 logtext2 + talk2 talkprop2 talktext2 talkleft + ), @manual_move) { + delete $table{$t}; + } + + # local stuff + my $local_tables = LJ::run_hook("moveucluster_local_tables"); + if ($local_tables) { + while (my ($tab, $key) = each %$local_tables) { + delete $table{$tab}; + } + } + + # things we list as active tables but don't use yet + delete $table{"events"}; + + # things we don't move because it doesn't really matter + delete $table{"s1stylecache"}; + delete $table{"captcha_session"}; + + if (%table) { + die "ERROR. Won't try to move user, because this mover script can't move all live tables for this user. List of tables without mover code available: \n -- " . join("\n -- ", sort keys %table), "\n"; + } + +} + +1; # return true; diff --git a/livejournal/bin/upgrading/pop-clusterprops.pl b/livejournal/bin/upgrading/pop-clusterprops.pl new file mode 100755 index 0000000..c677b67 --- /dev/null +++ b/livejournal/bin/upgrading/pop-clusterprops.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl +# +# This script converts from dversion 3 to dversion 4, +# which makes most userprops clustered +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $fromver = shift; +die "Usage: pop-clusterprops.pl \n\t(where fromdversion is one of: 3)\n" + unless $fromver == 3; + +my $dbh = LJ::get_db_writer(); + +my $todo = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=$fromver"); +my $done = 0; +unless ($todo) { + print "Nothing to convert.\n"; + exit 0; +} + +sub get_some { + my @list; + my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion=$fromver LIMIT 200"); + $sth->execute; + push @list, $_ while $_ = $sth->fetchrow_hashref; + @list; +} + +my $tover = $fromver + 1; +print "Converting $todo users from data version $fromver to $tover...\n"; + +my @props; +my $sth = $dbh->prepare("SELECT upropid FROM userproplist WHERE cldversion=?"); +$sth->execute($tover); +push @props, $_ while $_ = $sth->fetchrow_array; +my $in = join(',', @props); +die "No values?" unless $in; + +my $start = time(); +while (my @list = get_some()) { + LJ::start_request(); + + my %cluster; # clusterid -> [ $u* ] + foreach my $u (@list) { + push @{$cluster{$u->{'clusterid'}}}, $u; + } + + foreach my $cid (keys %cluster) { + my $dbcm = LJ::get_cluster_master($cid); + next unless $dbcm; + + my $uid_in = join(',', map { $_->{'userid'} } @{$cluster{$cid}}); + + my @vals; + foreach my $table (qw(userprop userproplite)) { + $sth = $dbh->prepare("SELECT userid, upropid, value FROM $table ". + "WHERE userid IN ($uid_in) AND upropid IN ($in)"); + $sth->execute(); + while (my ($uid, $pid, $v) = $sth->fetchrow_array) { + push @vals, "($uid,$pid," . $dbh->quote($v) . ")"; + } + } + if (@vals) { + my $sql = "REPLACE INTO userproplite2 VALUES " . join(',', @vals); + $dbcm->do($sql); + if ($dbcm->err) { + die "Error: " . $dbcm->errstr . "\n\n(Do you need to --runsql on your clusters first?)\n"; + } + $dbh->do("DELETE FROM userprop WHERE userid IN ($uid_in) AND upropid IN ($in)"); + $dbh->do("DELETE FROM userproplite WHERE userid IN ($uid_in) AND upropid IN ($in)"); + } + $dbh->do("UPDATE user SET dversion=$tover WHERE userid IN ($uid_in) AND dversion=$fromver"); + $done += scalar @{$cluster{$cid}}; + } + + my $perc = $done/$todo; + my $elapsed = time() - $start; + my $total_time = $elapsed / $perc; + my $min_remain = int(($total_time - $elapsed) / 60); + printf "%d/%d complete (%.02f%%) minutes_remain=%d\n", $done, $todo, ($perc*100), $min_remain; +} diff --git a/livejournal/bin/upgrading/pop-weekuu.pl b/livejournal/bin/upgrading/pop-weekuu.pl new file mode 100755 index 0000000..459ef53 --- /dev/null +++ b/livejournal/bin/upgrading/pop-weekuu.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl +# +# This script converts from dversion 2 (clustered + userpicblobs clustered) +# to dversion 3, which adds weekuserusage population. +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +die "This script is no longer useful.\n"; + +my $dbh = LJ::get_db_writer(); + +my $todo = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=2"); +my $done = 0; +unless ($todo) { + print "Nothing to convert.\n"; + exit 0; +} + +sub get_some { + my @list; + my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion=2 LIMIT 200"); + $sth->execute; + push @list, $_ while $_ = $sth->fetchrow_hashref; + @list; +} + +print "Converting $todo users from data version 2 to 3...\n"; +my $start = time(); +while (my @list = get_some()) { + LJ::start_request(); + foreach my $u (@list) { + my $dbcm = LJ::get_cluster_master($u); + next unless $dbcm; + + my %week; + my $sth = $dbcm->prepare("SELECT rlogtime FROM log2 ". + "WHERE journalid=? AND rlogtime < 2147483647"); + $sth->execute($u->{'userid'}); + while (my $t = $sth->fetchrow_array) { + my ($week, $uafter, $ubefore) = LJ::weekuu_parts($t); + if (! $week{$week}) { + $week{$week} = [ $uafter, $ubefore ]; + } elsif ($ubefore < $week{$week}->[1]) { + $week{$week}->[1] = $ubefore; + } + } + + if (%week) { + my $sql = "REPLACE INTO weekuserusage (wknum,userid,uafter,ubefore) VALUES " . + join(",", map { "($_,$u->{'userid'},$week{$_}->[0],$week{$_}->[1])" } keys %week); + my $rv = $dbh->do($sql); + die $dbh->errstr if $dbh->err; + next unless $rv; # error? try later. + } + + $dbh->do("UPDATE user SET dversion=3 WHERE userid=?", undef, $u->{'userid'}); + $done++; + } + + my $perc = $done/$todo; + my $elapsed = time() - $start; + my $total_time = $elapsed / $perc; + my $min_remain = int(($total_time - $elapsed) / 60); + printf "%d/%d complete (%.02f%%) minutes_remain=%d\n", $done, $todo, ($perc*100), $min_remain; +} diff --git a/livejournal/bin/upgrading/s1style-rw.pl b/livejournal/bin/upgrading/s1style-rw.pl new file mode 100755 index 0000000..0027fd1 --- /dev/null +++ b/livejournal/bin/upgrading/s1style-rw.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl +# +# Library to read/write s1styles.dat +# + +sub s1styles_read +{ + my $ss = {}; + + open (F, "$ENV{'LJHOME'}/bin/upgrading/s1styles.dat"); + my $uniq; + my $entry; + my $read_entry = 0; + my $line = 0; + while () + { + $line++; + if ($read_entry && $entry) + { + if ($_ eq ".\n") { + chop $entry->{'formatdata'}; # we added a newline + $read_entry = 0; + undef $entry; + next; + } + s!^\.!!; + $entry->{'formatdata'} .= $_; + next; + } + + if (m!^Style:\s*(\w+?)/(.+?)\s*$!) { + $uniq = "$1/$2"; + die "Repeat style in s1styles.dat at line $line!" + if exists $ss->{$uniq}; + $entry = $ss->{$uniq} = { + 'type' => $1, + 'styledes' => $2, + }; + $read_entry = 0; + next; + } + + if ($entry && $_ eq "\n") { + $read_entry = 1; + next; + } + + next unless $entry; + if (/^(\w+):\s*(.+?)\s*$/) { + $entry->{$1} = $2; + next; + } + + die "s1styles.dat:$line: bogus line\n" if /\S/; + } + close F; + + return $ss; +} + +sub s1styles_write +{ + my $ss = shift; + + open (F, ">$ENV{'LJHOME'}/bin/upgrading/s1styles.dat") + or die "Can't open s1styles.dat for writing.\n"; + + foreach my $uniq (sort keys %$ss) { + my $s = $ss->{$uniq}; + print F "Style: $uniq\n"; + foreach (qw(is_public is_embedded is_colorfree opt_cache lastupdate)) { + next unless exists $s->{$_}; + print F "$_: $s->{$_}\n"; + } + + my $formatdata = $s->{'formatdata'}; + $formatdata =~ s/\r//g; # die, DOS line endings! + $formatdata =~ s/\n\./\n\.\./g; + print F "\n$formatdata\n.\n\n"; + } + close F; + +} + +1; diff --git a/livejournal/bin/upgrading/s1styles.dat b/livejournal/bin/upgrading/s1styles.dat new file mode 100755 index 0000000..b2476d3 --- /dev/null +++ b/livejournal/bin/upgrading/s1styles.dat @@ -0,0 +1,7523 @@ +Style: calendar/Clean and Simple +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:47:15 + +CALENDAR_YEAR_DISPLAYED<= +
  • %%yyyy%%
  • + +<=CALENDAR_YEAR_DISPLAYED + +CALENDAR_YEAR_LINK<= +
  • %%yyyy%%
  • + +<=CALENDAR_YEAR_LINK + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=> + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + + +%%head%% +%%title%% - History + + + + + + + + +
    +

    %%title%%

    +

    History

    +
    +
    + +%%months%% + +
    + +
    Powered by %%cons:sitename%%
    + +
    + + + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +
    + + + + + + + + + + + +%%weeks%% +
    %%monlong%% %%yyyy%% (...)
    SunMonTueWedThuFriSat
    +
    + +<=CALENDAR_MONTH + +CALENDAR_WEBSITE<= +
  • %%name%%
  • + +<=CALENDAR_WEBSITE + +CALENDAR_NEW_YEAR=>

    %%yyyy%%

    + +CALENDAR_SORT_MODE=>forward + +CALENDAR_DAY_EVENT=>
    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Default Calendar +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:49:24 + +CALENDAR_YEAR_DISPLAYED=>[ %%yyyy%% ] + +CALENDAR_YEAR_LINK=>[ %%yyyy%% ] + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>

    %%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + +%%title%% - Calendar +%%head%% + + + +
    + +%%title%%
     
    + +[Most Recent Entries] +[Calendar View] +[Friends] + + +

    %%yearlinks%% + +%%months%% +

      + +

    + +%%website%% + +
    About %%cons:sitename%%
    + + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +

    + + + + + + + + + + + +%%weeks%% + +
    %%monlong%%, %%yyyy%%
    SunMonTueWedThuFriSat
    View Subjects +
    +

    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE<= + + %%name%% + +  +<=CALENDAR_WEBSITE + +CALENDAR_NEW_YEAR=>

    %%yyyy%%... + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>

    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Disjointed +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:50:18 + +CALENDAR_YEAR_DISPLAYED=>
    + """; + } else { + """
    $day
    """; + } + """ + + """; + } + """ + + """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
    +

    + """; + + print $m->month_format(); + + """ +

    + +   $*text_view_month   :: ^

    +
    + + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
    $*lang_dayname_short[$d]
    +
    +

    + """; + +} + + +function YearPage::print_body { + """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
    """; +} + + +## -- p r i n t d a y p a g e -- ######################################## + +function DayPage::print_body() { + """

    """; + print $.date->date_format("long"); "


    "; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } else { + """
    $*text_noentries_day
    """; + } +} + +## -- t h e e n d ! -- #################################################### \ No newline at end of file diff --git a/ljcom/bin/upgrading/s2layers/nebula/themes.s2 b/ljcom/bin/upgrading/s2layers/nebula/themes.s2 new file mode 100644 index 0000000..f3157e4 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/nebula/themes.s2 @@ -0,0 +1,269 @@ +#NEWLAYER: nebula/ohblue +layerinfo "type" = "theme"; +layerinfo "name" = "Oh blue"; +layerinfo "redist_uniq" = "nebula/ohblue"; + +set col_entry_bg = "#44366d"; +set col_stronger_fg = "#1b0c66"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_cmtbarone_bg = "#9f9cfd"; +set col_neutral_fg = "#2f2e55"; +set col_cmtbartwo_bg = "#adb3e5"; +set col_sidebar_link = "#2f2e55"; +set col_weaker_bg = "#d9dcff"; +set col_strong_fg = "#2f2e55"; +set col_neutral_bg = "#ab5c90"; +set col_cmtbarscrn_fg = "#1b0c66"; +set col_stronger_bg = "#b8bef8"; +set col_cmtbartwo_fg = "#000000"; +set col_weak_bg = "#404380"; +set col_cmtbarone_fg = "#000000"; +set col_weaker_fg = "#04025a"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#7e7cb1"; +set col_weak_fg = "#9ba2e8"; +set col_sidebar_vlink = "#1f1d46"; + +#NEWLAYER: nebula/ohgreen +layerinfo "type" = "theme"; +layerinfo "name" = "Oh green"; +layerinfo "redist_uniq" = "nebula/ohgreen"; + +set col_entry_bg = "#4ca65b"; +set col_stronger_fg = "#12661a"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_cmtbarone_bg = "#bffdbe"; +set col_neutral_fg = "#12661a"; +set col_cmtbartwo_bg = "#72e580"; +set col_sidebar_link = "#12661a"; +set col_weaker_bg = "#0d6315"; +set col_strong_fg = "#12661a"; +set col_neutral_bg = "#000000"; +set col_cmtbarscrn_fg = "#000000"; +set col_stronger_bg = "#9df89f"; +set col_cmtbartwo_fg = "#000000"; +set col_weak_bg = "#08390b"; +set col_cmtbarone_fg = "#000000"; +set col_weaker_fg = "#0e2a05"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#4f9f58"; +set col_weak_fg = "#08390b"; +set col_sidebar_vlink = "#12661a"; + +#NEWLAYER: nebula/ohpurple +layerinfo "type" = "theme"; +layerinfo "name" = "Oh purple"; +layerinfo "redist_uniq" = "nebula/ohpurple"; + +set col_cmtbartwo_bg = "#D89EE5"; +set col_cmtbarscrn_fg = "#000000"; +set col_entry_bg = "#eebfed"; +set col_weaker_bg = "#eebfed"; +set col_stronger_bg = "#efd5f8"; +set col_cmtbartwo_fg = "#000000"; +set col_sidebar_link = "#592b7d"; +set col_strong_bg = "#9c6e9f"; +set col_cmtbarone_bg = "#EECCFD"; +set col_stronger_fg = "#c459d1"; +set col_weaker_fg = "#0e2a05"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#2d1e41"; +set col_strong_fg = "#614a62"; +set col_weak_bg = "#614a62"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#000000"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_weak_fg = "#a1319a"; +set col_neutral_fg = "#614a62"; + +#NEWLAYER: nebula/ohblack +layerinfo "type" = "theme"; +layerinfo "name" = "Oh black"; +layerinfo "redist_uniq" = "nebula/ohblack"; + +set col_cmtbartwo_bg = "#ffffff"; +set col_cmtbarscrn_fg = "#000000"; +set col_entry_bg = "#ffffff"; +set col_weaker_bg = "#ffffff"; +set col_stronger_bg = "#ffffff"; +set col_cmtbartwo_fg = "#000000"; +set col_sidebar_link = "#606060"; +set col_strong_bg = "#ffffff"; +set col_cmtbarone_bg = "#ffffff"; +set col_stronger_fg = "#000000"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#606060"; +set col_entry_vlink = "#606060"; +set col_sidebar_vlink = "#606060"; +set col_strong_fg = "#000000"; +set col_weak_bg = "#ffffff"; +set col_neutral_bg = "#ffffff"; +set col_cmtbarone_fg = "#000000"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_weak_fg = "#000000"; +set col_neutral_fg = "#000000"; + +#NEWLAYER: nebula/ohcontrast +layerinfo "type" = "theme"; +layerinfo "name" = "Oh contrast"; +layerinfo "redist_uniq" = "nebula/ohcontrast"; + +set col_cmtbartwo_bg = "#000000"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#000000"; +set col_weaker_bg = "#000000"; +set col_stronger_bg = "#000000"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#c0c0c0"; +set col_strong_bg = "#000000"; +set col_cmtbarone_bg = "#000000"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#c0c0c0"; +set col_entry_vlink = "#c0c0c0"; +set col_sidebar_vlink = "#c0c0c0"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#000000"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#000000"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#ffffff"; + +#NEWLAYER: nebula/ohbedtime +layerinfo "type" = "theme"; +layerinfo "name" = "Oh bed time"; +layerinfo "redist_uniq" = "nebula/ohbedtime"; + +set col_cmtbartwo_bg = "#5c60b6"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#ffffff"; +set col_weaker_bg = "#5e5b7d"; +set col_stronger_bg = "#8381da"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#8381da"; +set col_cmtbarone_bg = "#605f9a"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#ffffff"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#879afa"; +set col_weak_fg = "#3c3c60"; +set col_neutral_fg = "#080255"; + +#NEWLAYER: nebula/ohgreenywhite +layerinfo "type" = "theme"; +layerinfo "name" = "Oh greeny white"; +layerinfo "redist_uniq" = "nebula/ohgreenywhite"; + +set col_entry_bg = "#ffffff"; +set col_stronger_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#93f390"; +set col_cmtbarone_bg = "#7fe278"; +set col_neutral_fg = "#550301"; +set col_cmtbartwo_bg = "#4a8f41"; +set col_sidebar_link = "#000000"; +set col_weaker_bg = "#546847"; +set col_strong_fg = "#ffffff"; +set col_neutral_bg = "#000000"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_stronger_bg = "#69ac59"; +set col_cmtbartwo_fg = "#ffffff"; +set col_weak_bg = "#ffffff"; +set col_cmtbarone_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#69ac59"; +set col_weak_fg = "#366030"; +set col_sidebar_vlink = "#000000"; + +#NEWLAYER: nebula/ohchocchip +layerinfo "type" = "theme"; +layerinfo "name" = "Oh choc chip"; +layerinfo "redist_uniq" = "nebula/ohchocchip"; + +set col_cmtbartwo_bg = "#4A8F41"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#977e3b"; +set col_weaker_bg = "#546847"; +set col_stronger_bg = "#69ac59"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#69ac59"; +set col_cmtbarone_bg = "#7FE278"; +set col_stronger_fg = "#5b4b26"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#5b4b26"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#93F390"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; + +#NEWLAYER: nebula/ohcoffee +layerinfo "type" = "theme"; +layerinfo "name" = "Oh coffee"; +layerinfo "redist_uniq" = "nebula/ohcoffee"; + +set col_cmtbartwo_bg = "#AFB13E"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#977e3b"; +set col_weaker_bg = "#effe8f"; +set col_stronger_bg = "#fbe46a"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#fbe46a"; +set col_cmtbarone_bg = "#E2C956"; +set col_stronger_fg = "#5b4b26"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#5b4b26"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#FCDA3E"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; + +#NEWLAYER: nebula/ohred +layerinfo "type" = "theme"; +layerinfo "name" = "Oh red"; +layerinfo "redist_uniq" = "nebula/ohred"; + +set col_cmtbartwo_bg = "#983035"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#d90d12"; +set col_weaker_bg = "#fe0410"; +set col_stronger_bg = "#dd6568"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#dd6568"; +set col_cmtbarone_bg = "#d25c64"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#bc0811"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#D38086"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; diff --git a/ljcom/bin/upgrading/s2layers/opal/layout.s2 b/ljcom/bin/upgrading/s2layers/opal/layout.s2 new file mode 100644 index 0000000..fc6f7d9 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/opal/layout.s2 @@ -0,0 +1,1625 @@ +# -*-s2-*- +layerinfo type = "layout"; +layerinfo name = "Opal (Libra OSWD)"; +layerinfo lang = "en"; + +layerinfo author_name = "Ported by Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo des = "Based on the Libra and Pasilda design available from Open Source Web Designs. Originally written by whompy."; +layerinfo redist_uniq = "opal/layout"; +layerinfo previews = "opal/opal.jpg"; + + + +################################################################################ +# +# Properties +# + + +propgroup prez = "Presentation"; +propgroup prez { + + property use font_base; + property use font_fallback; + property string static_font_size { noui = 1; } + property string static_font_measurement { noui = 1; } + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + + property bool show_entry_userpic { + des = "Always display userpic?"; + } + + property int summary_items { + des = "Summary Items"; + note="Maximum number of items in the Page Summary list. Set to 0 to turn off the Page Summary. Set to 100 to show all available items."; + } + + property bool use_count { + noui=1; + } + + set static_font_size = "12"; + set static_font_measurement = "px"; + set summary_items = 100; + set show_entry_userpic = false; + set font_fallback = "sans-serif"; +} + + +propgroup colors = "Colors"; + +propgroup colors { + property Color color_bg { + des = "Background Color"; + } + + property Color color_bg_font { + des = "Background Font Color"; + note = "The color of any font appearing on the background color."; + } + + property Color color_med { + des = "Page Holder Background"; + note = "This is the background of the main body, but within the outer borders."; + } + + property Color color_med_font { + des = "Page Holder Font Color"; + note="The color of the font appearing on the Page Holder Background color."; + } + + property Color color_fg { + des = "Content Background Color"; + note = "This is the background to the main content where the entries and side elements are."; + } + + property Color color_fg_font { + des = "Content Font Color"; + note = "The color of the font that appears on in the main Content area."; + } + + property Color color_link { + des = "Link Color"; + } + + property Color color_visited { + des = "Visited Link Color"; + } + + set color_bg = "#2d3851"; + set color_bg_font = "#ffffff"; + set color_med = "#7C8AA4"; + set color_med_font = "#e9f2fc"; + set color_fg = "#BFC4CB"; + set color_fg_font = "#333333"; +} + +propgroup text = "Text"; +propgroup text { + + property string free_text_header { + des = "Free Text Header"; + } + + property string free_text_text { + des = "Free Text Text"; + cols = 30; + rows = 10; + } + + property string links_header { + des = "Links Header"; + } + + property string page_summary_title { + des = "Page Summary Header"; + } + + property use text_view_userinfo; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property string text_forward { + des = "Text to show in a link to skip forward through entries"; + } + property string text_back { + des = "Text to show in a link to skip backward through entries"; + } + property use text_read_comments; + property use text_read_comments_friends; + property use text_post_comment; + property use text_post_comment_friends; + property use text_comment_reply; + property use text_reply_back; + property use text_nosubject; + property use text_noentries_day; + property use text_meta_music; + property use text_meta_mood; + + set page_summary_title = "Page Summary"; + set links_header = "Links"; + set free_text_header = "About this journal"; + set free_text_text = ""; + set text_back = "Back"; + set text_forward = "Forward"; +} + +set tags_aware = true; + + +################################################################################ +# +# Prop Init +# + +function prop_init () { + if($*color_bg.as_string == "") { $*color_bg = "#000000"; } + if($*color_fg.as_string == "") { $*color_fg = "#000000"; } + if($*color_fg_font.as_string == "") { $*color_fg_font = "#000000"; } +} + + +################################################################################ +# +# Stylesheet +# + +function getAltColor (Color color, string dir, int num) : Color { + var int lt = $color->lightness(); + if($dir == "light") { + if($lt > 200) { + $color = $color->darker($num); + } else { + $color = $color->lighter($num); + } + } elseif($dir == "dark") { + if($lt < 55) { + $color = $color->lighter($num); + } else { + $color = $color->darker($num); + } + } + return $color; +} + +function print_stylesheet () { + + + var Color color_bg_lt = getAltColor($*color_bg, "light", 30); + var Color color_fg_dk = getAltColor($*color_fg, "dark", 20); + var Color color_fg_dk_font = getAltColor($*color_fg_font, "dark", 20); + var Color color_divider = getAltColor($color_fg_dk, "dark", 30); + var Color color_fg_dk_dk_font = getAltColor($color_fg_dk, "dark", 50); + var Color color_border = getAltColor($*color_bg, "light", 90); + var string base = ($*font_base != "") ? "$*font_base, " : ""; + + """ + body { + font-family: $base $*font_fallback; + background-color: $*color_bg; + margin: 10px; + } + + .border4 { border: 1px solid $*color_bg; } + .border3 { border: 1px solid $*color_fg; } + .border2 { border: 2px solid $color_border; } + + """; + if($*color_link.as_string != "") { + """ + A { color: $*color_link; } + """; + } + + if($*color_visited.as_string != "") { + """ + A:Visited { color: $*color_visited; } + """; + } + """ + #bodycontent { background-color: $*color_med; border: 1px solid $*color_bg; padding: 3px; } + + #headerinfo { + background-color: $*color_bg; + color: $*color_bg_font; + text-align: right; + font-size: 10px; + padding: 2px; + margin-top: 1px; + } + #header { color: $*color_med_font; } + #header h3 { font-weight: normal; } + #userpic { float: right; } + + .userpic2 { + float: right; + text-align: right; + margin-top: 2px; + margin-right: 3px; + } + + #nav { + white-space: nowrap; + margin-bottom: 10px; + font-size: $*static_font_size$*static_font_measurement; + } + + #nav A { + border: 1px solid $*color_bg; + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + padding-bottom: 2px; + height: 20px; + text-decoration: none; + color: $*color_bg_font; + background-color: $color_bg_lt; + } + + #nav A:Hover { background-color: $*color_bg; } + + #content { + background-color: $*color_fg; + border: 1px solid $color_fg_dk; + padding: 4px; + } + + .columncontent { + background-color: $color_bg_lt; + border: 1px solid $*color_bg; + padding: 3px; + width: 200px; + font-size: $*static_font_size$*static_font_measurement; + color: $*color_bg_font; + } + + .columnitem { + background-color: $color_fg_dk; + padding: 3px; + margin-top: 5px; + color: $*color_fg_font; + border-top: 1px solid $color_divider; + border-bottom: 1px solid $color_divider; + overflow: hidden; + } + + .entries { color: $*color_fg_font; } + + .entrydivider { + border-top: 1px solid $color_divider; + border-bottom: 1px solid $*color_fg; + } + + .minicomment { + background-color: $color_fg_dk; + padding: 4px; + color: $*color_fg_font; + border: 1px solid $*color_fg; + font-size: $*static_font_size$*static_font_measurement; + } + + .minicommentholder { border: 1px solid $color_divider; } + + .entryinfo { + background-color: $color_fg_dk; + font-size: $*static_font_size$*static_font_measurement; + padding: 4px; + color: $*color_fg_font; + } + + .postedby { + background-color: $color_fg_dk; + padding: 6px; + font-size: $*static_font_size$*static_font_measurement; + } + + .entrylinks { + border-bottom: 1px solid $*color_fg; + background-color: $color_fg_dk; + padding-top: 4px; + padding-bottom: 4px; + font-size: $*static_font_size$*static_font_measurement; + } + + .entrylinks A { + text-decoration: none; + padding-top: 4px; + padding-bottom: 4px; + white-space: nowrap; + color: $*color_fg_font; + border-right: 1px solid $*color_fg; + } + + .entrylinks A:Hover { + background-color: $*color_fg; + } + + .messageholder { + border: 1px solid $*color_bg;; + margin-bottom: 5px; + margin-top: 5px; + } + + .systemmessage { + background-color: $color_bg_lt; + color: $*color_bg_font; + border: 1px solid $color_border; + font-size: $*static_font_size$*static_font_measurement; + } + + .systemtext { + font-weight: normal; + padding-left: 10px; + padding-right: 10px; + } + + .systemmessage A { + text-decoration: none; + padding-left: 10px; + padding-right: 10px; + color: $*color_bg_font; + padding-top: 4px; + padding-bottom: 4px; + } + + .systemmessage A:Hover { + background-color: $*color_bg; + } + + .systemmessage input, .systemmessage textarea, .systemmessage select { + background-color: $*color_fg; + color: $*color_fg_font; + } + + .systemmessage TD { + padding: 4px; + font-size: $*static_font_size$*static_font_measurement; + color: $*color_bg_font; + } + + .entry { margin-bottom: 30px; } + .entrytext { margin: 10px; } + .subject { font-weight: bold; } + + .meta { + font-size: $*static_font_size$*static_font_measurement; + padding: 4px; + } + + .meta A { + text-decoration: none; + color: $*color_link; + } + + .systemmessage A:Hover { + background-color: $*color_bg; + } + + #sidecolumn TD { color: $*color_bg_font; } + + #sidecolumn A { + text-decoration: none; + color: $*color_fg_font; + } + + .sidetd { + width: 200px; + } + + .backtop { + text-align: right; + } + + .backtop A { + color: $*color_fg_font; + font-size: $*static_font_size$*static_font_measurement; + text-decoration: none; + padding-bottom: 1px; + } + + #cal A { + text-decoration: none; + color: $*color_fg_font; + } + + .calrow { + clear: both; + font-family: Arial, sans-serif; + } + + .calempty { + width: 24px; + font-size: 11px; + margin: 1px; + float: left; + } + + .calactitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + background-color: $color_fg_dk; + border-right: 1px solid $color_bg_lt; + border-bottom: 1px solid $color_bg_lt; + } + + .calinitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + border-right: 1px solid $color_fg_dk; + border-bottom: 1px solid $color_fg_dk; + } + + .friendcolor { + width: 10px; + height: 10px; + border: 2px solid $*color_fg; + } + + .multiform { + font-weight: bold; + } + + .ip { + color: $color_fg_dk_dk_font; + } + + .friendname { + padding: 4px; + text-decoration: none; + border-left: 1px solid $*color_fg; + border-right: 1px solid $*color_fg; + } + + .bigday { + font-size: 2em; + color: $color_fg_dk; + float: left; + font-weight: bolder; + } + + .notablemessage { + padding: 4px; + } + + """; +} + + + +################################################################################ +# +# Global functions +# + +function generateDots (string un) : string { + var string dots; + if($un != "") { + foreach var string s ($un) { + if($s == "a" or $s == "c" or $s == "e" or $s == "f" or $s == "h" or $s == "k" or $s == "m" or $s == "n" or $s == "p" or $s == "r" or $s == "t" or $s == "v" or $s == "x" or $s == "z") { + $dots = $dots + ":"; + } elseif($s == " ") { + $dots = $dots + " "; + } else { + $dots = $dots + "."; + } + } + } + return $dots; +} + + + + +function print_box (string header, string text) { + """ + +
    +
    +
    +
    + """; + print safe """$header"""; + print safe """$text"""; + + """ +
    +
    +
    +
    +
    + """; + +} + +function box_item (string text) : string { + return """
    $text
    \n"""; +} + + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + + +################################################################################ +# +# Layout specific functions +# + +function Page::lay_print_userpic() { + if(defined $.journal.default_pic) { + """ +
    $.journal.name
    + """; + } +} + +function Page::lay_print_username () { + + var string dots = generateDots($.global_title); + + """ +
    + $.journal.username
    $dots +
    + """; +} + +function Page::lay_print_header () { + var string title = $this->title(); + """ + + """; +} + +function Page::lay_print_freetext () { + if($*free_text_text != "") { + var string text = box_item($*free_text_text); + print_box($*free_text_header, $text); + } +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var string links; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + $links = $links + """
    $l.title
    """; + } else { + $links = $links + box_item("""$l.title"""); + } + } + } + + print_box($*links_header, $links); +} + + +function Page::lay_print_calendar () { + var YearMonth m = $this->get_latest_month(); + var string mon = $m->month_format(); + var string text; + $text = """ + """; + foreach var YearWeek w ($m.weeks) { + $text = $text + """ + """; + if($w.pre_empty > 0) { + foreach var int empty (1..$w.pre_empty) { + $text = $text + """ + """; + } + } + foreach var YearDay d ($w.days) { + if($d.num_entries > 0) { + $text = $text + """ + """; + } else { + $text = $text + """ + """; + } + } + $text = $text + "\n"; + } + $text = $text + "
     $d.day$d.day
    "; + print_box($mon, $text); +} + + +function Page::lay_entry_nav (Entry e) : string { + + var string line; + var string date; + if($e.new_day) { + $date = $e.time->date_format("short"); + } + var string time = $e.time->time_format(); + var string subject = ($e.subject != "") ? " :: $e.subject" : """ :: $*text_nosubject"""; + var string j = ($.view == "friends" and $e.journal.username != $e.poster.username) ? " : $e.journal " : ""; + var string item = ($.view == "friends" or $e.journal.username != $e.poster.username) ? $e.poster->as_string() + """$j """ : """$date $time"""; + $line = """"""; + + return $line; +} + +function Page::lay_print_summary () { + #blank because there's shouldn't be a box if there's nothing specific about the page. +} + + +function RecentPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + if($count > 0) { + $text = $text + $this->lay_entry_nav($e); + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function EntryPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + $text = $this->lay_entry_nav($.entry); + $count = $count - 1; + + foreach var Comment c ($.comments) { + if($count > 0) { + var string subject = ($c.subject != "") ? $c.subject : """$*text_nosubject """; + $text = $text + """
    $c.poster :: $subject"""; + var int num = num_comments_in_thread($c.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + $text = $text + """
    """; + } + $count = $count - 1; + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + if($count != ($*summary_items - 1)) { + print_box($*page_summary_title, $text); + } + } +} + +function YearPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + var int num_entries; + foreach var YearMonth m ($.months) { + if($count > 0) { + var string mon = $m->month_format(); + if($m.has_entries) { + $num_entries = 0; + foreach var YearWeek w ($m.weeks) { + foreach var YearDay d ($w.days) { + $num_entries = $num_entries + $d.num_entries; + } + } + $text = $text + """"""; + } + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } + +} + +function MonthPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var MonthDay d ($.days) { + if($count > 0) { + var string day = lang_ordinal($d.day); + if ($d.has_entries) { + $text = $text + """"""; + } + } + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function DayPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + $text = $text + $this->lay_entry_nav($e); + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function Page::lay_print_subnav () { + # +} + +function RecentPage::lay_print_subnav () { + var string back; + if($.nav.backward_url != "") { + $back = """$*text_back"""; + } else { + $back = " "; + } + var string forward; + if($.nav.forward_url != "") { + $forward = """$*text_forward"""; + } else { + $forward = " "; + } + + var int start = $.nav.skip; + var int end = $.nav.skip + size $.entries; + var string text = "Viewing $start - $end"; + """ +
    + + + + + + +
    $back$text$forward
    +
    + """; +} + +function DayPage::lay_print_subnav () { + var string back; + if($.prev_url != "") { + $back = """$*text_back"""; + } else { + $back = " "; + } + var string forward; + if($.next_url != "") { + $forward = """$*text_forward"""; + } else { + $forward = " "; + } + + var string text = $.date->date_format("long"); + + """ +
    + + + + + + +
    $back$text$forward
    +
    + """; + +} + + +function Page::lay_print_sidebar () { + $this->lay_print_summary(); + $this->print_linklist(); + $this->lay_print_freetext(); + $this->lay_print_calendar(); +} + + +function Page::lay_make_username(Entry e) { + """ + +
    + """; +} + +function FriendsPage::lay_make_username (Entry e) { + var Friend f = $.friends{$e.journal.username}; + var string url = $e.poster->base_url(); + """ + +
    + """; +} + +function Page::print_entry (Entry e) { + + print """"""; + var string time = $e.time->time_format(); + var string date = $e.time->date_format(); + var string security; + if ($e.security != "") { + $security = """"""; + } + + var UserLite name; + var string pname; + + var bool show_name = ($.view == "friends" or $e.poster.username != $.journal.username or $.view == "entry") ? true : false; + var bool show_pic = (defined $e.userpic and ($.view == "friends" or $*show_entry_userpic or $e.poster.username != $e.journal.username or $.view == "entry")) ? true : false; + + + + + """ +
    +
    + """; + if($show_pic) { + """ +
    + $e.poster.name [userpic] +
    + """; + } + + if($show_name) { + $this->lay_make_username($e); + } + """ + +
    + +
    +
    $e.subject
    +

    $e.text

    + """; + + $e->print_metadata(); + + """ +
    +
    + + + """; +} + + + +function CommentInfo::print() { + if ($.enabled) { + $this->print_postlink(); + if ($.count > 0 or $.screened) { + $this->print_readlink(); + } + } +} + +function CommentInfo::print_postlink() { + var Page p = get_page(); + "   "+($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment)+"   "; +} + +function CommentInfo::print_readlink { + var Page p = get_page(); + "   "+ + get_plural_phrase($.count, $p.view == "friends" ? + "text_read_comments_friends" : "text_read_comments")+ + "   "; +} + + +################################################################################ +# +# EntryPage and Comments +# + +function EntryPage::print_body() { + """
    """; + $this->print_entry($.entry); + if ($this.multiform_on) { + $this->print_multiform_start(); + } + + if ($.entry.comments.count > 0) { + """ +
    Comments
    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($.entry.comments.enabled) { + $this->print_comments($.comments); + } + + + if ($.entry.comments.count > 0) { + """ +
    +
    +
    + """; + + $.entry.comments->print(); + + """ +
    +
    +
    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($this.multiform_on and ($.entry.comments.count > 0)) { + """ +
    +
    +
    +
    + """; + $this->print_multiform_actionline(); + """ +
    +
    +
    +
    + """; + $this->print_multiform_end(); + } + """
    """; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + } +} + +function EntryPage::print_comment(Comment c) { + + var string datetime; + $datetime = $c.time->date_format()+", " + $c.time->time_format(); + + + var string parent; + var string thread; + if($c.parent_url != "") { + $parent = """   $*text_comment_parent   """; + } + if($c.thread_url != "") { + $thread = """   $*text_comment_thread   """; + } + + var string subjecticon; + if (defined $c.subject_icon) { + $subjecticon = """"""; + } + + var string ip; + if ($c.metadata{"poster_ip"}) { + $ip = """   """ + $c.metadata{"poster_ip"}; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + + var string pic; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $pic = """
    """; + } + + var string indent = ($c.depth - 1) * 25 + "px"; + + """ +
    + + $pic +
    +
    +
    $poster $ip
    +
    + +
    + + """; + + if ($.multiform_on) { + """ +
    + """; + } + + var string replyurl; + if ($c.frozen) { + $replyurl = """   $*text_comment_frozen   """; + } else { + $replyurl = """   $*text_comment_reply   """; + } + + """ + +
    +
    $c.subject
    +

    $c.text

    +
    + """; + + + if ((size $c.replies) > 0 and $c.replies[0].full == false) { + """
    \n"""; + $this->print_comments($c.replies); + "
    \n"; + } + + """ +
    + +
    + """; + + if ((size $c.replies) > 0 and $c.replies[0].full == true) { + $this->print_comments($c.replies); + } + +} + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : """$*text_nosubject"""; + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
    $poster - $subj
    + """; + $this->print_comments($c.replies); +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ +
    + """; + print lang_page_of_pages($.current, $.total); + " — "; + foreach var int i (1..$.total) { + if ($i == $.current) { """[$i]"""; + + } else { + var string url_of = $this->url_of($i); + "[$i]"; + } + } + """
    """; +} + +################################################################################ +# +# ReplyPage +# + +function ReplyPage::print_body() { + + var EntryLite e = $.replyto; + var string poster = defined $e.poster ? $e.poster->as_string() : "(Anonymous)"; + var string datetime; + var string time = $e.time->time_format(); + var string date = $e.time->date_format(); + + var UserLite name; + if(defined $e.userpic and $*comment_userpic_style != "off") { + $name = $e.poster; + """
    """; + if (defined $e.userpic or (defined $e.userpic and $.view == "entry" and $*show_entry_userpic)) { + """"""; + } + """
    """; + } + """ +
    +
    + +
    + +
    + + """; + + """ +
    +
    $e.subject
    +

    $e.text

    +
    + +
    + """; + $.form->print(); + """ +
    + """; +} + + +function Entry::print_metadata() { + var string caption; + var string val; + var Image i; + if ($this.tags) { + """
    """; + print $this->get_tags_text(); + "
    "; + } + if (size $.metadata == 0) { return; } + foreach var string k ($.metadata) { + $caption = $k; + $val = $.metadata{$k}; + if ($k == "music") { + $caption = $*text_meta_music; + } + elseif ($k == "mood") { + $caption = $*text_meta_mood; + if (defined $.mood_icon) { + $i = $.mood_icon; + $val = """$val $val"""; + } + } + println """
    $caption: $val
    """; + } +} + + +################################################################################ +# +# RecentPage +# + +function RecentPage::print_body () { + """ + +
    + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """ +
    + """; +} + +################################################################################ +# +# YearPage +# + + +function YearPage::print_body { + $this->print_year_links(); + """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
    """; +} + +function YearPage::print_year_links() { + """
    """; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """$y.year"""; + } else { + """   $y.year   """; + } + } + """
    """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
    +
    + +
    + +
    + + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
    $*lang_dayname_short[$d]
    +
    +
    + + """; + +} + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + """ + +
    $day
    + """; + if ($d.num_entries > 0) { + var string num = $d.num_entries < 10 ? " " + string($d.num_entries) : string($d.num_entries); + """ + + """; + } + """ + + """; + } + """ + + """; +} + + + + +################################################################################ +# +# MonthPage +# + + +function MonthPage::view_title : string { + return $.date->date_format($*lang_fmt_month_long); +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + var string back; + var string forward; + if ($.prev_url != "") { $back = """$*text_back"""; } + if ($.next_url != "") { $forward = """$*text_forward"""; } + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
    + + + + + + +
    $back$select$forward
    +
    + """; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + +
    +
    + +
    +
    + """; + $d->print_subjectlist(); + """ +
    +
    +
    + + """; + } + } +} + +function MonthDay::print_subjectlist() { + # Too many tables... + foreach var Entry e ($.entries) { + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + """ $*text_nosubject"""; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
    \n"; + } +} + + +################################################################################ +# +# DayPage +# + +function DayPage::print_body() { + + """
    """; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + "

    $*text_noentries_day

    "; + } + """
    """; +} + +################################################################################ +# +# Page +# + +function Page::print () { + + var string title = $this->title(); + + """ + + + + $title + + """; + + $this->print_head(); + + """ + + + + + + + +
    +
    +
    +
    + """; + + $this->lay_print_userpic(); + $this->lay_print_username(); + $this->lay_print_header(); + + """ +
    + + + + + + +
    +
    + """; + + $this->lay_print_sidebar(); + + """ +
    +
    + """; + + $this->lay_print_subnav(); + $this->print_body(); + $this->lay_print_subnav(); + + """ +
    +
    +
    +
    +
    +
    + + + """; +} + + + +function print_theme_preview() { + + var Color color_bg_lt = getAltColor($*color_bg, "light", 30); + var Color color_fg_dk = getAltColor($*color_fg, "dark", 20); + var Color color_fg_dk_font = getAltColor($*color_fg_font, "dark", 20); + var Color color_divider = getAltColor($color_fg_dk, "dark", 30); + var Color color_fg_dk_dk_font = getAltColor($color_fg_dk, "dark", 50); + var Color color_border = getAltColor($*color_bg, "light", 90); + + """ +
    +
    +
    Username - Title
    +
    +
    +
    +
    + Welcome +
    This is my new journal using a cool new style!
    +
    +
    + """; + +} diff --git a/ljcom/bin/upgrading/s2layers/opal/opal.jpg b/ljcom/bin/upgrading/s2layers/opal/opal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c11fb314e1dedc9c0a9e16e7bd01dbba1e82387 GIT binary patch literal 13075 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 krAR}U$=z`~g+ - \". The Custom Date Formats section of the S2 Documentation at http://www.livejournal.com/doc/s2/siteapi.core1.html#siteapi.core1.dateformats will list the pieces that you can use to construct your format. You must wrap each piece in two percent signs (%%) in your format."; + } + property string text_format_entry_time { + des = "Format for Date and Time (Day page only)"; + note = "This is provided as a separate customisation from the previous because users may want to supress the printing of the Date part of the subject line on Day pages. On these pages, only entries from that certain Date will be printed and the Page's header will reflect that under the menu. Putting the date on the subject line is unnecessary and is left out by default. If you would like it to appear just as on other pages, use the same format as the previous setting."; + } + set text_nosubject = "(no subject)"; + set text_entry_username_seperator = ""; + set text_meta_music = "Music"; + set text_meta_mood = "Mood"; + set text_meta_tags = "Tags"; + set text_read_comments = "Read 1 // Read #"; + set text_post_comment = "Speak"; + set text_post_comment_guestbook = "Sign Guestbook"; + set text_permalink = "Link"; + set text_edit = "Edit"; + set text_edittag = "Edit Tags"; + set text_add_to_memories = "Remember"; + set text_comment_thread = "Thread"; + set text_comment_parent = "Parent"; + set text_comment_reply = "Reply"; + set text_comment_permalink = "Link"; + set text_multiform_opt_delete = "Delete"; + set text_multiform_opt_screen = "Screen"; + set text_multiform_opt_unscreen = "Unscreen"; + set text_multiform_opt_freeze= "Freeze"; + set text_multiform_opt_unfreeze = "Unfreeze"; + set text_multiform_check = "Select"; + set text_poster_anonymous = "Anonymous"; + set text_format_entry_date_and_time = "%%dayord%%-%%mon%%-%%yyyy%% %%hh%%:%%min%% %%a%%m"; + set text_format_entry_time = "%%hh%%:%%min%% %%a%%m"; +} + + +function print_stylesheet() "Prints the CSS that goes into the stylesheet for the layout" { + """ + body { + font-family: $*font_base, sans-serif; + font-size: """; print $*font_base_size; """px; + margin: 0px; + background-color: $*color_body_background; + color: $*color_body_text; + background-image: url('$*layout_background'); + } + a { + color: $*color_body_links; + } + a:visited { + color: $*color_body_links_visited; + } + .entryHeaderDate a { + color : $*color_body_entrytitle_links; + text-decoration : none; + } + .entryHeaderDate a:hover { + color : $*color_body_entrytitle_links; + text-decoration : underline; + } + .header-title { + background-color: $*color_header_title_background; + font-family: $*font_header_title; + font-size: """; print $*font_header_title_size; """px; + color: $*color_header_title_text; + padding: 0px 20px 0px 20px; + } + .header-subtitle { + background-color: $*color_header_title_background; + color: $*color_header_subtitle_text; + font-family: $*font_header_subtitle; + font-size: """; print $*font_header_subtitle_size; """px; + padding: 0px 24px 0px 24px; + } + .header-icon { + top: 0px; + right: 0px; + position: absolute; + z-index: 1; + border-left: 2px solid $*color_header_borders; + border-bottom: 2px solid $*color_header_borders; + } + .pageheaderblock { + text-align: $*layout_header_alignment; + } + .pagefooterblock { + border-top: 2px solid $*color_body_entrytitle_border; + background-color: $*color_body_footer_background; + color: $*color_body_footer_text; + padding: 4px 4px 4px 24px; + margin-top: 4px; + } + .pagefooterblock a, .pagefooterblock a:visited { + color: $*color_body_footer_text; + } + .bodyblock { + padding: 10px """;print $*layout_margin_right;"""px 0px """;print $*layout_margin_left;"""px; + } + .bodyheaderblock { + border-top: 2px solid $*color_header_borders; + background-color: $*color_body_titlebar_background; + padding: 4px 0px 4px 0px; + } + .bodynavblock { + border-top: 2px solid $*color_header_borders; + background-color: $*color_body_titlebar_background; + color: $*color_body_titlebar_text; + margin: 10px 0px 4px 0px; + padding: 8px; + } + .bodynavblock a, .bodynavblock a:visited { + color: $*color_body_titlebar_text; + } + .body-title { + font-family: $*font_body_title; + font-size: """; print $*font_body_title_size; """px; + color: $*color_body_titlebar_text; + text-align: $*layout_header_alignment; + padding-left: 24px; + } + .body-midtitle { + font-family: $*font_body_title; + font-size: """; print $*font_body_title_size; """px; + color: $*color_body_titlebar_text; + text-align: left; + padding-left: 8px; + } + .entryHolder { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + font-family: $*font_entry_text; + font-size: """; print $*font_entry_text_size; """px; + border-top: 2px solid $*color_body_entrytitle_border; + margin: 4px 0px 4px 0px; + } + .entryUserinfo { + text-align: center;"""; + if ($*layout_position_userinfo_entry=="left") { """ + margin: 0px 8px 8px 0px; + """;}elseif($*layout_position_userinfo_entry=="right") { """ + margin: 0px 0px 8px 8px; + """;}""" + background-color: $*color_body_entry_userinfo_background; + } + .entryUserinfo-usericon img { + border: 0; + } + .entryText { + padding: 6px; + } + .entryHeader { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + padding: 4px 0px 4px 8px; + } + .entryHeader a{ + color: $*color_body_entrytitle_links; + } + .entryHeaderSubject { + font-weight: bold; + } + .entryMetadata { + padding-left: 6px; + } + .entryMetadata ul { + margin: 0px; + padding: 0px; + } + .entryMetadata li { + list-style: none; + display: inline; + padding-right: 10px; + } + .entryMetadata-label { + font-weight: bold; + padding-right: 4px; + } + .entryLinkbar { + font-family: $*font_entry_linkbar; + font-size: """; print $*font_entry_linkbar_size; """px; + color: $*color_body_entry_text; + text-align: $*layout_linkbar_alignment_entry; + padding: 4px 0px 4px 0px; + } + .entryLinkbar ul { + margin: 0px; + padding: 0px; + } + .entryLinkbar li { + padding: 0px 5px 0px 5px; + margin: 0px; + display: inline; + } + .commentHolder { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + border-top: 2px solid $*color_body_entrytitle_border; + font-family: $*font_entry_text; + font-size: """; print $*font_entry_text_size; """px; + margin: 4px 0px 4px 0px; + } + .commentUserinfo { + text-align: center; """; + if ($*layout_position_userinfo_comment=="left") { """ + margin: 0px 8px 8px 0px; + """;}elseif($*layout_position_userinfo_comment=="right") { """ + margin: 0px 0px 8px 8px; + """;}""" + background-color: $*color_body_entry_userinfo_background; + } + .commentUserinfo-usericon img { + border: 0; + } + .commentText { + padding: 6px; + } + .commentHeader { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + padding: 4px 0px 4px 8px; + } + .commentHeader a{ + color: $*color_body_entrytitle_links; + } + .commentHeaderScreened { + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + background-color: $*color_body_entrytitle_background_alternate; + padding: 4px 0px 4px 8px; + } + .commentHeaderSubject { + font-weight: bold; + } + .commentLinkbar { + font-family: $*font_entry_linkbar; + font-size: """; print $*font_entry_linkbar_size; """px; + color: $*color_body_entry_text; + text-align: $*layout_linkbar_alignment_comment; + padding-top: 4px; + padding-bottom: 4px; + } + .commentLinkbar ul { + margin: 0px; + padding: 0px; + } + .commentLinkbar li { + padding: 0px 5px 0px 5px; + margin: 0px; + display: inline; + } + .replyform { + padding-left: 10px; + } + .yearlinks{ + text-align: right; + } + .yearlink{ + padding-left:4px; + padding-right: 4px; + } + .month { + width: 500px; + border: 1px solid $*color_month_borders; + margin: 8px 8px 8px 40px; + } + .daysubjects { + color: $*color_body_entry_text; + padding: 8px 8px 8px 40px; + } + .daytitles { + text-align: center; + border: 1px solid $*color_month_borders; + background: $*color_month_title_background; + color: $*color_month_title_text; + } + .day-blank { + border: 1px solid $*color_month_borders; + } + .day { + border: 1px solid $*color_month_borders; + } + .day-date { + border-right: 1px solid $*color_month_borders; + border-bottom: 1px solid $*color_month_borders; + color: $*color_month_dates; + width: 50%; + text-align: center; + } + .day-count { + width: 50%; + text-align: center; + float: right; + font-size: """; print $*font_archive_daycount_size; """px; + } + .day-count a { + text-decoration: none; + color: $*color_month_postcount; + } + """; + + # print sidebar css only if we need to + if ($*layout_sidebar_position!="none") { """ + .sidebar { + font-family: $*font_sidebar_text; + font-size: """; print $*font_sidebar_text_size; """px; + margin-"""; if($*layout_sidebar_position=="left"){print "right";}else{print "left";}""": 20px; + width: """; print $*layout_sidebar_width; """px; + } + .sidebox { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + margin: 4px 0px 4px 0px; + } + .sideboxTitle { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + border-top: 2px solid $*color_body_entrytitle_border; + font-family: $*font_sidebar_title; + font-size: """; print $*font_sidebar_title_size; """px; + padding: 4px 0px 4px 8px; + text-align: $*layout_sidebox_title_alignment; + } + .sideboxContent { + text-align: left; + padding: 2px 4px 2px 4px; + } + .sidebox #profile, sidebox #latestmonth, .sidebox #search, .sidebox #tags_sidebox { + text-align: center; + } + .sidebox #systemlinks { + text-align: $*layout_sidebox_links_alignment; + } + .sidebox #latestmonth table{ + width: 90%; + margin-left: auto; + margin-right: auto; + margin-top: 4px; + } + .listtitle { + font-weight: bold; + } + .profile-label { + font-weight: bold; + } + """;} + + """ + .header-menu { + padding: 0px; + background-color: $*color_header_menubar_background; + border-top: 2px solid $*color_header_borders; + padding-left: 19px; + font-family: $*font_header_menu; + font-size: """; print $*font_header_menu_size; """px; + line-height: """; print ($*font_header_menu_size+8); """px; + } + .header-menu a, .header-menu a:visited { + white-space: nowrap; + text-align: left; + padding: 2px 6px 2px 6px; + color: $*color_header_menubar_text; + text-decoration: none; + } + .header-menu a:hover { + background-color: $*color_header_menubar_background_hover; + color: $*color_header_menubar_text_hover; + } + #footer-menu { + font-size: 11px; + } + #footer-menu a, .footer-menu a:visited { + color: $*color_body_titlebar_text; + white-space: nowrap; + padding: 6px; + text-align: left; + } + .header-menu ul, #footer-menu ul { + margin: 0px; + padding: 0px; + } + .header-menu li, #footer-menu li { + display: inline; + } + """; + + if ($*layout_replyform_textarea_width>0) { """ + .replyform textarea { + width: """; print $*layout_replyform_textarea_width; """px; + } + """; } + + print $*layout_custom_css; +} + +function Page::lay_get_previous_url():string { return ""; } +function Page::lay_get_next_url():string { return ""; } +function Page::lay_get_previous_title():string { return $*text_nav_prev_page; } +function Page::lay_get_next_title():string { return $*text_nav_next_page; } + +function RecentPage::lay_get_previous_url():string { return $.nav.backward_url; } +function RecentPage::lay_get_next_url():string { return $.nav.forward_url; } +function RecentPage::lay_get_previous_title():string { + return get_plural_phrase($.nav.backward_count,"text_nav_prev_recentpage"); +} +function RecentPage::lay_get_next_title():string { + return get_plural_phrase($.nav.forward_count,"text_nav_next_recentpage"); +} + + +function DayPage::lay_get_previous_url():string { return $.prev_url; } +function DayPage::lay_get_next_url():string { return $.next_url; } +function DayPage::lay_get_previous_title():string { + if (defined $.prev_date) { return $.prev_date->date_format($*text_nav_format_daypage); } else { return ""; } +} +function DayPage::lay_get_next_title():string { + if (defined $.next_date) { return $.next_date->date_format($*text_nav_format_daypage); } else { return ""; } +} + +function MonthPage::lay_get_previous_url():string { return $.prev_url; } +function MonthPage::lay_get_next_url():string { return $.next_url; } +function MonthPage::lay_get_previous_title():string { + if (defined $.prev_date) { + return $.prev_date->date_format($*text_nav_format_monthpage); + } else { + return ""; + } +} +function MonthPage::lay_get_next_title():string { + if (defined $.next_date) { + return $.next_date->date_format($*text_nav_format_monthpage); + } else { + return ""; + } +} + +function EntryPage::lay_get_previous_url():string { + var Link prev = $.entry->get_link("nav_prev"); + if (defined $prev and $.entry.itemid!=int($*layout_guestbook_entryid)) { return $prev.url; } else { return ""; } +} +function EntryPage::lay_get_next_url():string { + var Link next= $.entry->get_link("nav_next"); + if (defined $next and $.entry.itemid!=int($*layout_guestbook_entryid)) { return $next.url; } else { return ""; } +} +function EntryPage::lay_get_previous_title():string { return "$*text_nav_prev_entrypage"; } +function EntryPage::lay_get_next_title():string { return "$*text_nav_next_entrypage"; } + +function YearPage::lay_get_previous_url():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==0) { + return ""; + }else{ + var YearYear prevyear = $.years[$pos-1]; + return $prevyear.url; + } + } + } + return ""; +} +function YearPage::lay_get_next_url():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==$i) { + return ""; + }else{ + var YearYear nextyear = $.years[$pos+1]; + return $nextyear.url; + } + } + } + return ""; +} + +function YearPage::lay_get_previous_title():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==0) { + return ""; + }else{ + var YearYear prevyear = $.years[$pos-1]; + return ""+$prevyear.year; + } + } + } + return ""; +} +function YearPage::lay_get_next_title():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==$i) { + return ""; + }else{ + var YearYear nextyear = $.years[$pos+1]; + return ""+$nextyear.year; + } + } + } + return ""; +} + +function Page::lay_print_header_links() { + # Menu start + """
      """; + + # Journal Navigation (Previous page, Next Page) + var string prev_link = $this->lay_get_previous_url(); + var string prev_title = $this->lay_get_previous_title(); + var string next_link = $this->lay_get_next_url(); + var string next_title = $this->lay_get_next_title(); + print ($prev_link==""?"":"
    • $prev_title
    • "); + print ($next_link==""?"":"
    • $next_title
    • "); + + # Standard Journal Pages (Recent, Archive, Friends, Userinfo) + foreach var string v ($.views_order) { + if (lang_viewname($v)!="") { + print "
    • "+lang_viewname($v)+"
    • "; + } + } + + # Memories + if ($*layout_menubar_memories) { + """
    • $*text_view_memories
    • """; + } + + # Need to add a link to scrapbook account in user links, not do this manually + # Scrapbook (picture Galleries) + #if ($*layout_menubar_scrapbook) { + # """
    • $*text_view_scrapbook
    • """; + # + #} + + # Guestbook + if (int($*layout_guestbook_entryid)!=0) { + var string guestbook_url = "$*SITEROOT/users/$.journal.username/"+$*layout_guestbook_entryid+".html"; + """
    • $*text_view_guestbook
    • """; + } + + # Website from Userinfo page + if ($*layout_menubar_website) { + """
    • $.journal.website_name
    • """; + } + + # Menu end + """
    """; +} + +function Page::lay_print_header() { + + var string title = $.global_title; + var string subtitle = $.global_subtitle; + """ +
    + """; + if ($*layout_header_usericon=="show") {"""
    $this.journal.default_pic
    """; } + """
    $title
    """; + if ($.global_subtitle!="") { """
    $subtitle
    """; } + $this->lay_print_header_links(); + """ +
    + """; +} + +function EntryLite::lay_show_usericon():bool { return true; } + +function EntryLite::lay_print_subjectline() { #will only ever be used for a comment, so we can use comment settings. + """
    """; + # print $.time->date_format("%%dayord%%-%%mon%%-%%yyyy%%")+" "+$.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + print ($.subject==""?"":" - $.subject"); + """
    """; +} + +function EntryLite::lay_print_userinfo() { #will only ever be used for a comment, so we can use comment settings. + """ +
    + """; + if (defined $.userpic and $*layout_position_usernames_comment=="below") {"""""";} + """
    """; + if (defined $.poster) { + """$.poster"""; + }else{ + """$*text_poster_anonymous"""; + } + if (viewer_is_owner() and $.metadata{"poster_ip"}!="") { + """
    ($.metadata{"poster_ip"})"""; + } + """
    """; + if (defined $.userpic and $*layout_position_usernames_comment=="above") {"""
    $.userpic
    """;} + """ +
    + """; +} + +function EntryLite::print_linkbar() { + """ + + """; +} + +function EntryLite::lay_print() { #will only ever be used for a comment, so we can use comment settings. + """ +
    + """; + $this->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_comment=="left" or $*layout_wrapping_userinfo_comment ) { + $this->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_comment) {"""""";} + } + """
    $.text
    """; + if ($*layout_position_userinfo_comment=="right" and not $*layout_wrapping_userinfo_comment) { + """
    """; + $this->lay_print_userinfo(); + } + + """
    """; + $this->print_linkbar(); + """
    +
    + """; +} + +function Entry::lay_show_usericon():bool { + var Page p = get_page(); + return $*layout_show_usericons=="all" or ($*layout_show_usericons=="nonrecent" and $p.view!="recent") or ($*layout_show_usericons=="friends" and $p.view=="friends"); +} + +function Entry::lay_print_userinfo() { + var Page p = get_page(); + if ($p.view=="friends" or $p.journal_type=="C" or ($this->lay_show_usericon() and defined $.userpic)) { + """
    """; + if (defined $.userpic and $this->lay_show_usericon() and $*layout_position_usernames_entry=="below") { + """"""; + } + if ($p.view=="friends" or $p.journal_type=="C") { + """
    """; + """$.poster"""; + if ($.journal->as_string()!=$.poster->as_string() and $p.view=="friends") { + print "
    "; + if ($*text_entry_username_seperator != "") { + print $*text_entry_username_seperator + "
    "; + } + """$.journal"""; + } + """
    """; + } + if (defined $.userpic and $this->lay_show_usericon() and $*layout_position_usernames_entry=="above") { """
    $.userpic
    """; } + """
    """; + } +} + +function Entry::lay_print_subjectline() { + var Page p = get_page(); + if ($.itemid!=int($*layout_guestbook_entryid)) { + """
    """; + if ($p.view!="day") { + # print "base_url()+"/calendar/$.time.year/"+zeropad($.time.month,2)+"/"+zeropad($.time.day,2)+"/\">"+$.time->date_format("%%dayord%%")+"-"; + # print "base_url()+"/calendar/$.time.year/"+zeropad($.time.month,2)+"/\">"+$.time->date_format("%%mon%%")+"-"; + # print "base_url()+"/calendar/$.time.year/\">"+$.time->date_format("%%yyyy%%")+" "; + # print $.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + }else{ + # print $.time->time_format(); + print $.time->time_format($*text_format_entry_time); + } + """"""; + if ($p.view=="entry") { + print (defined $.security_icon?" - $.security_icon":""); + }else{ + print (defined $.security_icon or $.subject!=""?" - ":"")+(defined $.security_icon?"$.security_icon ":"")+($.subject==""?"":"$.subject"); + } + """"""; + if ((size $.tags>0)and($*layout_position_entrytags=="subject")) { + """ [$.tags[0].name"""; + foreach var int i (1 .. (size $.tags - 1)) { + """, $.tags[$i].name"""; + } + """]"""; + } + """
    """; + }else{ + """
    """; + print (defined $.security_icon?""+$.security_icon:" "); + """
    """; + } +} + +function Entry::print_metadata() { + if (($.metadata{"mood"}!="" or $.metadata{"music"}!="" or ((size $.tags>0)and($*layout_position_entrytags=="metadata"))) and ($.itemid!=int($*layout_guestbook_entryid))) { + """"""; + } +} + +function Entry::print_linkbar() { + """ + + """; +} + +function Page::print_entry(Entry e) { + if ( $e.itemid==int($*layout_guestbook_entryid) and ($.view=="recent" or $.view=="day" )) { return; } + if ( $.args{"noshow"}==$e.journal.username ) { return; } + """ + +
    + """; + $e->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_entry=="left" or $*layout_wrapping_userinfo_entry ) { + $e->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_entry) {"""""";} + } + if ($*layout_position_metadata=="above") { $e->print_metadata(); } + """
    """; print $e.text; """
    """; + if ($*layout_position_metadata=="below") { $e->print_metadata(); } + if ($*layout_position_userinfo_entry=="right" and not $*layout_wrapping_userinfo_entry) { + """
    """; + $e->lay_print_userinfo(); + } + """
    """; + $e->print_linkbar(); + """
    +
    + """; +} + +function Comment::lay_print_subjectline() { + """
    "; + #print $.time->date_format("%%dayord%%-%%mon%%-%%yyyy%%")+" "+$.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + print (defined $.subject_icon?""+$.subject_icon:"")+($.subject==""?"":" - $.subject"); + + """
    """; +} + +function Comment::print_linkbar() { + """ + + """; +} + +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + var int indent = ($c.depth - 1) * 25; + "
    \n"; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + "
    "; + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment(Comment comment) { + """ +
    """; + $comment->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_comment=="left" or $*layout_wrapping_userinfo_comment) { + $comment->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_comment) {"""""";} + } + """
    $comment.text
    """; + if ($*layout_position_userinfo_comment=="right" and not $*layout_wrapping_userinfo_comment) { + """
    """; + $comment->lay_print_userinfo(); + } + """
    """; + $comment->print_linkbar(); + """
    +
    + """; +} + + +function EntryPage::print_comment_partial(Comment comment) { + """ +
    """; + print ""+($comment.subject==""?"(no subject)":"$comment.subject")+" - "; + print (defined $comment.poster?"$comment.poster":"Anonymous"); + """
    """; +} + +function Page::lay_print_bodytitlebox(string title, string titletype) { + """ +
    +
    $title 
    +
    + """; +} + +function MonthPage::view_title : string { + return $.date->date_format($*text_nav_format_monthpage); +} + +function DayPage::view_title : string { + return $.date->date_format($*text_nav_format_daypage); +} + +function Page::lay_print_bodytop() { + $this->lay_print_bodytitlebox($this->view_title(),"title"); +} + +function ReplyPage::lay_print_bodytop() { + if ($.entry.itemid==int($*layout_guestbook_entryid) and $.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_signing_guestbook,"title"); + }elseif ($.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_comment_to,"title"); + }else { + $this->lay_print_bodytitlebox($*text_reply_to,"title"); + } +} + +function MonthPage::lay_print_bodytop_monthselector() { + """
    """; + $.redir->print_hiddens(); + if (size $.months > 1) { + """"""; + } + """
    """; +} + +function Page::lay_print_sidebox_top(string title) { + """ + + """; +} + +function Page::lay_print_sidebar_profile() { + $this->lay_print_sidebox_top($*text_sidebox_profile_title); + """ +
    + """; + if ($.journal.default_pic.url!="") { + """
    """; + } + """ +
    $*text_sidebox_profile_userlabel$.journal
    +
    $*text_sidebox_profile_namelabel$.journal.name
    + """; + if ($*text_sidebox_profile_info!="") { """
    """; print $*text_sidebox_profile_info; """
    """; } + """ +
    + """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_systemlinks() { + var int num_links = size $.linklist - 1; + if ($num_links<0) { return; } + $this->lay_print_sidebox_top($*text_sidebox_links_title); + """ + + """; + $this->lay_print_sidebox_bottom(); +} + +function Entry::lay_print_summaryline(Page p) { + """
    """; + print ($*text_sidebox_summary_bullet_bold?"$*text_sidebox_summary_bullet":$*text_sidebox_summary_bullet); + if ($p.view=="friends") { + """$.poster"""; + if ($.journal.username!=$.poster.username) { print $*text_sidebox_summary_username_seperator; """$.journal"""; } + """ - """; + }elseif ($p.view=="day") { + print $.time->time_format(); """ - """; + }else{ + #nothing + } + + if (defined $.security_icon) { """$.security_icon """; } + """"""; + if ($.subject!="") { print $this->plain_subject(); } else { """$*text_nosubject"""; } + """"""; + if ($.comments.count>0 or $.comments.screened) { """ [+$.comments.count]"""; } + """
    + """; + +} + +function Comment::lay_count_replies() : int { + var int total = 0; + foreach var Comment reply ($.replies) { + $total = $total + 1 + $reply->lay_count_replies(); + } + return $total; +} + +function Comment::lay_print_summaryline(Page p) { + """
    """; + print ($*text_sidebox_summary_bullet_bold?"$*text_sidebox_summary_bullet":$*text_sidebox_summary_bullet); + print (defined $.poster?""+$.poster:"$*text_poster_anonymous"); + """ - """; + if ($.subject!="") { """$.subject"""; } else { """$*text_nosubject"""; } + """"""; + var int count = $this->lay_count_replies(); + if ($count>0) { """ [+$count]"""; } + """
    """; +} + +function Page::lay_print_sidebar_summary() {} + +function RecentPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[$pos]; + if ($e.itemid!=int($*layout_guestbook_entryid)) {$e->lay_print_summaryline($this);} + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +function FriendsPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_friends_sortorder=="newest"?$pos:$i-$pos)]; + $e->lay_print_summaryline($this); + } + """ """; + $this->lay_print_sidebox_bottom(); +} + +function DayPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_day_sortorder=="newest"?$i-$pos:$pos)]; + if ($e.itemid!=int($*layout_guestbook_entryid)) {$e->lay_print_summaryline($this);} + } + """ """; + $this->lay_print_sidebox_bottom(); +} + +function EntryPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + $.entry->lay_print_summaryline($this); + foreach var Comment c ($.comments) { + $c->lay_print_summaryline($this); + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_tags() { + var Tag[] pagetags = $this->visible_tag_list(); + if (size $pagetags==0) { return; } + $this->lay_print_sidebox_top($*text_sidebox_tags_title); + """
    """; + """$pagetags[0].name"""; + foreach var int i (1 .. (size $pagetags - 1)) { + """, $pagetags[$i].name"""; + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +# TODO: Interesting, maybe add as a builtin function later? +function Page::lay_print_sidebar_multisearch() { + $this->lay_print_sidebox_top($*text_sidebox_multisearch_title); + """ + + """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_latestmonth() { + $this->lay_print_sidebox_top($*text_sidebox_latestmonth_title); + var YearMonth month = $this->get_latest_month(); + """
    + + + """; + foreach var YearWeek week ($month.weeks) { + """"""; + if ($week.pre_empty>0) { """"""; } + foreach var YearDay day ($week.days) { + if ($day.num_entries==0) { + """"""; + }else{ + """"""; + } + } + if ($week.post_empty>0) { """"""; } + """"""; + } + """ +
    $*lang_monthname_long[$month.month] $month.year
    $day.day
    +
    """; + $this->lay_print_sidebox_bottom(); +} + + +function Page::lay_print_sidebar_freetextbox() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_title); + """
    """; print $*text_sidebox_freetext_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_2() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_2_title); + """
    """; print $*text_sidebox_freetext_2_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_3() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_3_title); + """
    """; print $*text_sidebox_freetext_3_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_4() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_4_title); + """
    """; print $*text_sidebox_freetext_4_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_5() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_5_title); + """
    """; print $*text_sidebox_freetext_5_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_6() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_6_title); + """
    """; print $*text_sidebox_freetext_6_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + + +function Page::lay_print_sidebar_freetextbox_7() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_7_title); + """
    """; print $*text_sidebox_freetext_7_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_8() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_8_title); + """
    """; print $*text_sidebox_freetext_8_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_9() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_9_title); + """
    """; print $*text_sidebox_freetext_9_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_10() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_10_title); + """
    """; print $*text_sidebox_freetext_10_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_private() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_private_title); + """
    """; $*text_sidebox_freetext_private_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar() { + """ """; +} + +function Page::lay_print_bodymiddle() { + """ +
    This page does not have an implementation.
    + """; +} + +function RecentPage::lay_print_bodymiddle() { + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_recent
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[$pos]; + $this->print_entry($e); + } + } +} + +function FriendsPage::lay_print_bodymiddle() { + + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_recent
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_friends_sortorder=="newest"?$pos:$i-$pos)]; + $this->print_entry($e); + } + } +} + +function DayPage::lay_print_bodymiddle() { + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_day
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_day_sortorder=="newest"?$i-$pos:$pos)]; + $this->print_entry($e); + } + } +} + +function ReplyPage::lay_print_bodymiddle() { + if ($.replyto.depth==0) { + $this->print_entry($.entry); + }else{ + $.replyto->lay_print(); + } + if ($.entry.itemid==int($*layout_guestbook_entryid) and $.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_signing_form,"midtitle"); + }elseif ($.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_comment_form,"midtitle"); + }else{ + $this->lay_print_bodytitlebox($*text_reply_form,"midtitle"); + } + """ + """; + if ($.replyto.depth==0 and int($*layout_guestbook_entryid)!=0 and $.entry.itemid!=int($*layout_guestbook_entryid) and $*text_replypage_warning!="") { + + print $*text_replypage_warning; + } + """ +
    """; + $.form->print(); + """
    """; +} + +function EntryPage::lay_print_bodymiddle() { + $this->print_entry($.entry); + if (size $.comments >0) { + if ($.entry.itemid!=int($*layout_guestbook_entryid)) { + $this->lay_print_bodytitlebox($*text_comment_seperator,"midtitle"); + }else { + $this->lay_print_bodytitlebox($*text_signature_seperator,"midtitle"); + } + if (viewer_is_owner()) { $this->print_multiform_start(); } + $this->print_comments($.comments); + if (not $.comment_pages.all_subitems_displayed) { + """
    """; + $.comment_pages->print(); + """
    """; + } + """
    """; + if (viewer_is_owner()) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + }else{ + if ($.entry.itemid!=int($*layout_guestbook_entryid)) { + """$*text_post_comment_entrypage"""; + }else{ + """$*text_post_comment_guestbook"""; + } + } + """
    """; + } +} + +function MonthDay::print_subjectlist() { + foreach var Entry e ($.entries) { + if ($e.itemid!=int($*layout_guestbook_entryid)) { + print $e.time->time_format(); + print " - "+(defined $e.security_icon?"$e.security_icon ":""); + """"""; + print ($e.subject==""?"(no subject)":$e->plain_subject()); + """"""; + if ($e.comments.count>0) { """   [ $e.comments.count Comments ]"""; } + """
    """; + } + } +} + +function MonthPage::lay_print_bodymiddle() { + foreach var MonthDay day ($.days) { + if ($day.has_entries) { + """ +
    + +
    """; + $day->print_subjectlist(); + """
    +
    """; + } + } +} + +function YearPage::print_month(YearMonth month) { + """ + +
    + + + """; foreach var int i (1..7) { """"""; } """ + """; + foreach var YearWeek week ($month.weeks) { + """"""; + if ($week.pre_empty>0) { """"""; } + foreach var YearDay day ($week.days) { + """"""; + } + if ($week.post_empty>0) { """"""; } + """"""; + } + """ +
    $*lang_dayname_short[$i]
    +
    $day.day
    +
    """; + print ($day.num_entries==0?" ":""+$day.num_entries+""); + """
    +
    +
    + """; +} + +function YearPage::lay_print_bodymiddle() { + var int i = size $.months - 1; + if ($i<0) { return; } + + foreach var int pos (0..$i) { + var YearMonth month = $.months[($*layout_year_sortorder=="newest"?$i-$pos:$pos)]; + if ($month.has_entries) { + $this->print_month($month); + } + } +} + +function Page::lay_print_bodybottom() { + var string prev_link = $this->lay_get_previous_url(); + var string prev_title = $this->lay_get_previous_title(); + var string next_link = $this->lay_get_next_url(); + var string next_title = $this->lay_get_next_title(); + """"""; +} + +function EntryPage::lay_print_bodybottom() {} +function ReplyPage::lay_print_bodybottom() {} + +function Page::lay_print_body() { + $this->lay_print_bodytop(); + """
    """; + """"""; + if ($*layout_sidebar_position=="left") { + """"""; + } + """"""; + if ($*layout_sidebar_position=="right") { + """"""; + } + """
    """; + $this->lay_print_sidebar(); + """"""; + $this->lay_print_bodymiddle(); + $this->lay_print_bodybottom(); + """"""; + $this->lay_print_sidebar(); + """
    """; + """
    """; +} + +function Page::lay_print_footer() { + if ($*text_footer_signature!="") { + var string footer_signature = $*text_footer_signature; + $footer_signature = $.time->time_format($footer_signature); + """
    """; print $footer_signature; """
    """; + } +} + +function Page::print_body() { + """
    """; + $this->lay_print_header(); + $this->lay_print_body(); + $this->lay_print_footer(); + """
    """; +} + +function Page::print() { + var string title = $this->title(); + """ + + + $title +"""; +if ($*layout_stylesheet=="") { + """ """; +}else{ + """ """; +} +$this->print_head(); +""" + + + +"""; $this->print_body(); """ + + +"""; +} + + + + diff --git a/ljcom/bin/upgrading/s2layers/smoothsailing/themes.s2 b/ljcom/bin/upgrading/s2layers/smoothsailing/themes.s2 new file mode 100644 index 0000000..0fd9e57 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/smoothsailing/themes.s2 @@ -0,0 +1,612 @@ +#NEWLAYER: smoothsailing/starry +layerinfo "redist_uniq" = "smoothsailing/starry"; +layerinfo "type" = "theme"; +layerinfo "name" = "Starry Night"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#000000"; + set color_header_title_text = "#FFFFB9"; + set color_header_subtitle_text = "#dddddd"; + set color_header_menubar_background = "#000044"; + set color_header_menubar_text = "#FFFFB9"; + set color_header_menubar_background_hover = "#000000"; + set color_header_menubar_text_hover = "#dddddd"; + set color_header_borders = "#89a2be"; + + set color_body_links = "#ffffb9"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#aaaaaa"; + set color_body_titlebar_text = "#000044"; + set color_body_footer_background = "#000000"; + set color_body_footer_text = "#ffffb9"; + set color_body_background = "#000044"; + set color_body_text = "#FFFFB9"; + + set color_body_entrytitle_background = "#000000"; + set color_body_entrytitle_background_alternate = "#aaaaaa"; + set color_body_entrytitle_border = "#89A2BE"; + set color_body_entrytitle_text = "#89a2be"; + set color_body_entrytitle_links = "#89a2be"; + set color_body_entry_background = "#000044"; + set color_body_entry_userinfo_background = "#000044"; + set color_body_entry_text = "#FFFFB9"; + + set color_month_borders = "#89A2BE"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#FFFFB9"; + + + +#NEWLAYER: smoothsailing/pink +layerinfo "redist_uniq" = "smoothsailing/pink"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pretty in Pink"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#CC4E5C"; + set color_header_title_text = "#FFEEFF"; + set color_header_subtitle_text = "#FFB6C1"; + set color_header_menubar_background = "#e6828f"; + set color_header_menubar_text = "#FFEEFF"; + set color_header_menubar_background_hover = "#CC4E5C"; + set color_header_menubar_text_hover = "#FFEEFF"; + set color_header_borders = "#FFEEFF"; + + set color_body_links = "#CC4E5C"; + set color_body_links_visited = "#CC4E5C"; + set color_body_titlebar_background = "#FFB6C1"; + set color_body_titlebar_text = "#CC4E5C"; + set color_body_footer_background = "#FFB6C1"; + set color_body_footer_text = "#CC4E5C"; + set color_body_background = "#FFEEFF"; + set color_body_text = "#CC4E5C"; + set color_body_entrytitle_background = "#FFB6C1"; + set color_body_entrytitle_background_alternate = "#e6828f"; + set color_body_entrytitle_border = "#CC4E5C"; + set color_body_entrytitle_text = "#CC4E5C"; + set color_body_entrytitle_links = "#CC4E5C"; + set color_body_entry_text = "#CC4E5C"; + set color_body_entry_background = "#FFEEFF"; + set color_body_entry_userinfo_background = "#FFEEFF"; + + set color_month_borders = "#CC4E5C"; + set color_month_title_background = "#FFB6C1"; + set color_month_title_text = "#CC4E5C"; + set color_month_dates = "#CC4E5C"; + set color_month_postcount = "#e6828f"; + + + + +#NEWLAYER: smoothsailing/easter +layerinfo "redist_uniq" = "smoothsailing/easter"; +layerinfo "type" = "theme"; +layerinfo "name" = "Easter Basket"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#00B789"; + set color_header_title_text = "#FFFF82"; + set color_header_subtitle_text = "#005100"; + set color_header_menubar_background = "#FFFF82"; + set color_header_menubar_text = "#005100"; + set color_header_menubar_background_hover = "#C7A0CB"; + set color_header_menubar_text_hover = "#005100"; + set color_header_borders = "#009300"; + + set color_body_links = "#005100"; + set color_body_links_visited = "#005100"; + set color_body_titlebar_background = "#C7A0CB"; + set color_body_titlebar_text = "#005100"; + set color_body_footer_background = "#C7A0CB"; + set color_body_footer_text = "#005100"; + set color_body_background = "#DDDFF0"; + set color_body_text = "#005100"; + set color_body_entrytitle_background = "#FFFF82"; + set color_body_entrytitle_background_alternate = "#C7A0CB"; + set color_body_entrytitle_border = "#009300"; + set color_body_entrytitle_text = "#005100"; + set color_body_entrytitle_links = "#005100"; + set color_body_entry_text = "#005100"; + set color_body_entry_background = "#DDDFF0"; + set color_body_entry_userinfo_background = "#DDDFF0"; + + set color_month_borders = "#00B789"; + set color_month_title_background = "#FFFF82"; + set color_month_title_text = "#005100"; + set color_month_dates = "#C7A0CB"; + set color_month_postcount = "#005100"; + + + + +#NEWLAYER: smoothsailing/mocha +layerinfo "redist_uniq" = "smoothsailing/mocha"; +layerinfo "type" = "theme"; +layerinfo "name" = "Mochachino"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#666666"; + set color_header_title_text = "#e6e6e6"; + set color_header_subtitle_text = "#B1A68B"; + set color_header_menubar_background = "#635a48"; + set color_header_menubar_text = "#b1a68b"; + set color_header_menubar_background_hover = "#b1a68b"; + set color_header_menubar_text_hover = "#666666"; + set color_header_borders = "#e6e6e6"; + + set color_body_links = "#464640"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#B1A68B"; + set color_body_titlebar_text = "#e6e6e6"; + set color_body_footer_background = "#b1a68b"; + set color_body_footer_text = "#e6e6e6"; + set color_body_background = "#e6e6e6"; + set color_body_entrytitle_background = "#b1a68b"; + set color_body_entrytitle_background_alternate = "#796D51"; + set color_body_entrytitle_border = "#666666"; + set color_body_entrytitle_text = "#e6e6e6"; + set color_body_entrytitle_links = "#e6e6e6"; + set color_body_entry_text = "#464640"; + set color_body_entry_background = "#e6e6e6"; + set color_body_entry_userinfo_background = "#e6e6e6"; + + set color_month_borders = "#666666"; + set color_month_title_background = "#e6e6e6"; + set color_month_title_text = "#464640"; + set color_month_dates = "#464640"; + set color_month_postcount = "#796D51"; + +#NEWLAYER: smoothsailing/yellow +layerinfo "redist_uniq" = "smoothsailing/yellow"; +layerinfo "type" = "theme"; +layerinfo "name" = "Insane Yellow"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#202020"; + set color_header_title_text = "#FFFF04"; + set color_header_subtitle_text = "#dddddd"; + set color_header_menubar_background = "#000000"; + set color_header_menubar_text = "#FFFFB9"; + set color_header_menubar_background_hover = "#202020"; + set color_header_menubar_text_hover = "#FFFFB9"; + set color_header_borders = "#FFFF04"; + + set color_body_links = "#aaaaaa"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#aaaaaa"; + set color_body_titlebar_text = "#000000"; + set color_body_footer_background = "#202020"; + set color_body_footer_text = "#ffffb9"; + set color_body_background = "#000000"; + set color_body_text = "#FFFFB9"; + + set color_body_entrytitle_background = "#202020"; + set color_body_entrytitle_background_alternate = "#aaaaaa"; + set color_body_entrytitle_border = "#FFFF04"; + set color_body_entrytitle_text = "#FFFF04"; + set color_body_entrytitle_links = "#FFFF04"; + set color_body_entry_background = "#000000"; + set color_body_entry_userinfo_background = "#000000"; + set color_body_entry_text = "#aaaaaa"; + + set color_month_borders = "#FFFFB9"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#FFFFB9"; + + +#NEWLAYER: smoothsailing/forest +layerinfo "redist_uniq" = "smoothsailing/forest"; +layerinfo "type" = "theme"; +layerinfo "name" = "In the Forest"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#635a48"; + set color_header_title_text = "#e7dfcf"; + set color_header_subtitle_text = "#607c6d"; + set color_header_menubar_background = "#899ba3"; + set color_header_menubar_text = "#464640"; + set color_header_menubar_background_hover = "#e7dfcf"; + set color_header_menubar_text_hover = "#464640"; + set color_header_borders = "#464640"; + + set color_body_links = "#e7dfcf"; + set color_body_links_visited = "#e7dfcf"; + set color_body_titlebar_background = "#e7dfcf"; + set color_body_titlebar_text = "#464640"; + set color_body_footer_background = "#e7dfcf"; + set color_body_footer_text = "#464640"; + set color_body_background = "#607c6d"; + set color_body_text = "#e7dfcf"; + + set color_body_entrytitle_background = "#635a48"; + set color_body_entrytitle_background_alternate = "#464640"; + set color_body_entrytitle_border = "#e7dfcf"; + set color_body_entrytitle_text = "#e7dfcf"; + set color_body_entrytitle_links = "#e7dfcf"; + set color_body_entry_userinfo_background = "#626b5b"; + set color_body_entry_background = "#626b5b"; + set color_body_entry_text = "#e7dfcf"; + + set color_month_borders = "#464640"; + set color_month_title_background = "#e7dfcf"; + set color_month_title_text = "#464640"; + set color_month_dates = "#899ba3"; + set color_month_postcount = "#e7dfcf"; + + + +#NEWLAYER: smoothsailing/red +layerinfo "redist_uniq" = "smoothsailing/red"; +layerinfo "type" = "theme"; +layerinfo "name" = "Seeing Red"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#bb0000"; + set color_header_title_text = "#ffffff"; + set color_header_subtitle_text = "#ffffff"; + set color_header_menubar_background = "#880000"; + set color_header_menubar_text = "#ffffff"; + set color_header_menubar_background_hover = "#ffffff"; + set color_header_menubar_text_hover = "#bb0000"; + set color_header_borders = "#ffffff"; + set color_body_links = "#880000"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#bb0000"; + set color_body_titlebar_text = "#ffffff"; + set color_body_footer_background = "#bb0000"; + set color_body_footer_text = "#ffffff"; + set color_body_background = "#f6f6f6"; + set color_body_text = "#880000"; + set color_body_entrytitle_background = "#bb0000"; + set color_body_entrytitle_background_alternate = "#880000"; + set color_body_entrytitle_border = "#000000"; + set color_body_entrytitle_text = "#ffffff"; + set color_body_entrytitle_links = "#ffffff"; + set color_body_entry_background = "#f6f6f6"; + set color_body_entry_text = "#880000"; + set color_month_borders = "#880000"; + set color_month_title_background = "#bb0000"; + set color_month_title_text = "#ffffff"; + set color_month_dates = "#880000"; + set color_month_postcount = "#bb0000"; + + + +#NEWLAYER: smoothsailing/army +layerinfo "redist_uniq" = "smoothsailing/army"; +layerinfo "type" = "theme"; +layerinfo "name" = "Army Attire"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#444444"; + set color_header_title_text = "#cccc99"; + set color_header_subtitle_text = "#e6e6e6"; + set color_header_menubar_background = "#665d34"; + set color_header_menubar_text = "#cccc99"; + set color_header_menubar_background_hover = "#cccc99"; + set color_header_menubar_text_hover = "#444444"; + set color_header_borders = "#e6e6e6"; + + set color_body_links = "#444444"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#cccc99"; + set color_body_titlebar_text = "#665d34"; + set color_body_footer_background = "#cccc99"; + set color_body_footer_text = "#665d34"; + set color_body_background = "#e6e6e6"; + + set color_body_entrytitle_background = "#cccc99"; + set color_body_entrytitle_background_alternate = "#665d34"; + set color_body_entrytitle_border = "#444444"; + set color_body_entrytitle_text = "#665d34"; + set color_body_entrytitle_links = "#665d34"; + set color_body_entry_text = "#444444"; + set color_body_entry_background = "#e6e6e6"; + set color_body_entry_userinfo_background = "#e6e6e6"; + + set color_month_borders = "#444444"; + set color_month_title_background = "#e6e6e6"; + set color_month_title_text = "#444444"; + set color_month_dates = "#444444"; + set color_month_postcount = "#665d34"; + + + +#NEWLAYER: smoothsailing/midnight +layerinfo "redist_uniq" = "smoothsailing/midnight"; +layerinfo "type" = "theme"; +layerinfo "name" = "Midnight"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#000000"; + set color_header_title_text = "#BEAA61"; + set color_header_subtitle_text = "#76456B"; + set color_header_menubar_background = "#76456B"; + set color_header_menubar_text = "#dddddd"; + set color_header_menubar_background_hover = "#000000"; + set color_header_menubar_text_hover = "#dddddd"; + set color_header_borders = "#dddddd"; + + set color_body_links = "#aaaaaa"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#BEAA61"; + set color_body_titlebar_text = "#000000"; + set color_body_footer_background = "#76456B"; + set color_body_footer_text = "#dddddd"; + set color_body_background = "#000000"; + set color_body_text = "#aaaaaa"; + + set color_body_entrytitle_background = "#76456B"; + set color_body_entrytitle_background_alternate = "#888888"; + set color_body_entrytitle_border = "#cccccc"; + set color_body_entrytitle_text = "#dddddd"; + set color_body_entrytitle_links = "#dddddd"; + set color_body_entry_userinfo_background = "#000000"; + set color_body_entry_background = "#000000"; + set color_body_entry_text = "#aaaaaa"; + + set color_month_borders = "#dddddd"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#BEAA61"; + + + +#NEWLAYER: smoothsailing/violet +layerinfo "redist_uniq" = "smoothsailing/violet"; +layerinfo "type" = "theme"; +layerinfo "name" = "Very Violet"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#7c52ab"; + set color_header_subtitle_text = "#dbcfe9"; + set color_header_menubar_background = "#bfaad7"; + set color_header_menubar_background_hover = "#7c52ab"; + set color_body_links_visited = "#563976"; + set color_body_titlebar_background = "#dbcfe9"; + set color_body_footer_background = "#bfaad7"; + set color_body_entrytitle_background = "#dbcfe9"; + +#NEWLAYER: smoothsailing/purple +layerinfo "redist_uniq" = "smoothsailing/purple"; +layerinfo "type" = "theme"; +layerinfo "name" = "Bruised Purple"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_body_entrytitle_border = "#d4ddee"; + set color_body_footer_text = "#454b74"; + set color_month_title_text = "#8792bd"; + set color_header_borders = "#8792bd"; + set color_body_links_visited = "#dddddd"; + set color_header_menubar_text_hover = "#ffffff"; + set color_body_titlebar_text = "#454b74"; + set color_body_entrytitle_background_alternate = "#d4ddee"; + set color_body_entrytitle_links = "#6b7da6"; + set color_body_entry_background = "#454b74"; + set color_header_title_background = "#454b74"; + set color_body_entry_userinfo_background = "#454b74"; + set color_month_dates = "#8792bd"; + set color_body_links = "#ececec"; + set color_body_background = "#6b7da6"; + set color_month_postcount = "#8792bd"; + set color_body_entry_text = "#8792bd"; + set color_body_text = "#ffffff"; + set color_body_entrytitle_background = "#d4ddee"; + set color_header_menubar_text = "#ffffff"; + set color_body_entrytitle_text = "#454b74"; + +#NEWLAYER: smoothsailing/parrot +layerinfo "redist_uniq" = "smoothsailing/parrot"; +layerinfo "type" = "theme"; +layerinfo "name" = "Parrot Feathers"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#009900"; + set color_header_title_text = "#f8f8f8"; + set color_header_subtitle_text = "#66ff66"; + set color_header_menubar_background = "#33cc33"; + set color_header_menubar_text = "#ffffff"; + set color_header_menubar_background_hover = "#66ff66"; + set color_header_menubar_text_hover = "#ffffff"; + set color_header_borders = "#ffffff"; + + set color_body_links = "#006600"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#66cc66"; + set color_body_titlebar_text = "#ffffff"; + set color_body_footer_background = "#66cc66"; + set color_body_footer_text = "#ffffff"; + set color_body_background = "#f8f8f8"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#66cc66"; + set color_body_entrytitle_background_alternate = "#66ff66"; + set color_body_entrytitle_border = "#006600"; + set color_body_entrytitle_text = "#000000"; + set color_body_entrytitle_links = "#000000"; + set color_body_entry_background = "#f8f8f8"; + set color_body_entry_userinfo_background = "#f8f8f8"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#006600"; + set color_month_title_background = "#f8f8f8"; + set color_month_title_text = "#000000"; + set color_month_dates = "#000000"; + set color_month_postcount = "#006600"; + +#NEWLAYER: smoothsailing/toxic +layerinfo "redist_uniq" = "smoothsailing/toxic"; +layerinfo "type" = "theme"; +layerinfo "name" = "Toxic Teal"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#7cb3b0"; + set color_header_title_text = "#496a68"; + set color_header_subtitle_text = "#c9eae8"; + set color_header_menubar_background = "#aededb"; + set color_header_menubar_text = "#496a68"; + set color_header_menubar_background_hover = "#c9eae8"; + set color_header_menubar_text_hover = "#496a68"; + set color_header_borders = "#496a68"; + + set color_body_links = "#496a68"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#c9eae8"; + set color_body_titlebar_text = "#496a68"; + set color_body_footer_background = "#c9eae8"; + set color_body_footer_text = "#496a68"; + set color_body_background = "#496a68"; + set color_body_text = "#aededb"; + + set color_body_entrytitle_background = "#7cb3b0"; + set color_body_entrytitle_background_alternate = "#6e9e9b"; + set color_body_entrytitle_border = "#c9eae8"; + set color_body_entrytitle_text = "#000000"; + set color_body_entrytitle_links = "#000000"; + set color_body_entry_background = "#aededb"; + set color_body_entry_userinfo_background = "#aededb"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#496a68"; + set color_month_title_background = "#c9eae8"; + set color_month_title_text = "#000000"; + set color_month_dates = "#000000"; + set color_month_postcount = "#496a68"; + +#NEWLAYER: smoothsailing/banana +layerinfo "redist_uniq" = "smoothsailing/banana"; +layerinfo "type" = "theme"; +layerinfo "name" = "Banana Tree"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#3D5D2E"; + set color_header_title_text = "#F6F6BB"; + set color_header_subtitle_text = "#E1D751"; + set color_header_menubar_background = "#E1D751"; + set color_header_menubar_text = "#3D5D2E"; + set color_header_menubar_background_hover = "#9A722E"; + set color_header_menubar_text_hover = "#F6F6BB"; + set color_header_borders = "#F6F6BB"; + + set color_body_links = "#3D5D2E"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#9A722E"; + set color_body_titlebar_text = "#F6F6BB"; + set color_body_footer_background = "#3D5D2E"; + set color_body_footer_text = "#F6F6BB"; + set color_body_background = "#F6F6BB"; + set color_body_text = "#3D5D2E"; + + set color_body_entrytitle_background = "#3D5D2E"; + set color_body_entrytitle_background_alternate = "#9A722E"; + set color_body_entrytitle_border = "#9A722E"; + set color_body_entrytitle_text = "#E1D751"; + set color_body_entrytitle_links = "#E1D751"; + set color_body_entry_background = "#F6F6BB"; + set color_body_entry_userinfo_background = "#F6F6BB"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#9A722E"; + set color_month_title_background = "#F6F6BB"; + set color_month_title_text = "#3D5D2E"; + set color_month_dates = "#000000"; + set color_month_postcount = "#3D5D2E"; + +#NEWLAYER: smoothsailing/fire +layerinfo "redist_uniq" = "smoothsailing/fire"; +layerinfo "type" = "theme"; +layerinfo "name" = "Under Fire"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#95261F"; + set color_header_title_text = "#F5EBC2"; + set color_header_subtitle_text = "#CA6036"; + set color_header_menubar_background = "#CA6036"; + set color_header_menubar_text = "#F5EBC2"; + set color_header_menubar_background_hover = "#DEB450"; + set color_header_menubar_text_hover = "#95261F"; + set color_header_borders = "#F5EBC2"; + + set color_body_links = "#95261F"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#DEB450"; + set color_body_titlebar_text = "#95261F"; + set color_body_footer_background = "#95261F"; + set color_body_footer_text = "#F5EBC2"; + set color_body_background = "#F5EBC2"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#95261F"; + set color_body_entrytitle_background_alternate = "#CA6036"; + set color_body_entrytitle_border = "#DEB450"; + set color_body_entrytitle_text = "#F5EBC2"; + set color_body_entrytitle_links = "#F5EBC2"; + set color_body_entry_background = "#F5EBC2"; + set color_body_entry_userinfo_background = "#F5EBC2"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#95261F"; + set color_month_title_background = "#F5EBC2"; + set color_month_title_text = "#95261F"; + set color_month_dates = "#95261F"; + set color_month_postcount = "#CA6036"; + +#NEWLAYER: smoothsailing/chocolate +layerinfo "redist_uniq" = "smoothsailing/chocolate"; +layerinfo "type" = "theme"; +layerinfo "name" = "Chocolate Caramel Creme"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#6D4506"; + set color_header_title_text = "#E1D6C0"; + set color_header_subtitle_text = "#CF9B48"; + set color_header_menubar_background = "#A2701F"; + set color_header_menubar_text = "#E1D6C0"; + set color_header_menubar_background_hover = "#CF9B48"; + set color_header_menubar_text_hover = "#E1D6C0"; + set color_header_borders = "#E1D6C0"; + + set color_body_links = "#6D4506"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#CF9B48"; + set color_body_titlebar_text = "#E1D6C0"; + set color_body_footer_background = "#6D4506"; + set color_body_footer_text = "#E1D6C0"; + set color_body_background = "#E1D6C0"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#A2701F"; + set color_body_entrytitle_background_alternate = "#CF9B48"; + set color_body_entrytitle_border = "#6D4506"; + set color_body_entrytitle_text = "#E1D6C0"; + set color_body_entrytitle_links = "#E1D6C0"; + set color_body_entry_background = "#E1D6C0"; + set color_body_entry_userinfo_background = "#E1D6C0"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#A2701F"; + set color_month_title_background = "#E1D6C0"; + set color_month_title_text = "#6D4506"; + set color_month_dates = "#6D4506"; + set color_month_postcount = "#A2701F"; diff --git a/ljcom/bin/upgrading/s2layers/tranquilityii/layout.s2 b/ljcom/bin/upgrading/s2layers/tranquilityii/layout.s2 new file mode 100644 index 0000000..10a0546 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/tranquilityii/layout.s2 @@ -0,0 +1,1341 @@ +# LAYER INFO +layerinfo "redist_uniq" = "tranquilityii/layout"; +layerinfo "type" = "layout"; +layerinfo "name" = "Tranquility II"; +layerinfo "des" = "XHTML/CSS Compliant layout. Relax."; +layerinfo "author_name" = "Matthew Vince"; +layerinfo "lang" = "en"; + + +# PROPERTIES: COLORS +propgroup Colors { + # odd + property Color c_main_border { des = "Border color of main column"; } + property Color c_main_background { des = "Background color of main column"; } + property Color c_menu_border { des = "Border color of menu"; } + property Color c_header_background { des = "Header background color"; } + property Color c_header_border { des = "Header border color"; } + # page + property Color c_page_background { des = "Page background color"; } + property Color c_page_title { des = "Page title color"; } + property Color c_page_text { des = "Page text color"; } + property Color c_page_link { des = "Page link color"; } + property Color c_page_link_visited { des = "Page visited link color"; } + property Color c_page_link_hover { des = "Page hover link color"; } + property Color c_page_link_active { des = "Page active link color"; } + # menu + property Color c_menu_background { des = "Side Menu background color"; } + property Color c_menu_link { des = "Side Menu link color"; } + property Color c_menu_link_visited { des = "Side Menu visited link color"; } + property Color c_menu_link_hover { des = "Side Menu hover link color"; } + property Color c_menu_link_active { des = "Side Menu active link color"; } + property Color c_menu_text_color { des = "Side Menu text color"; } + property Color c_menu_header_color { des = "Side Menu header color"; } + property Color c_menu_current { des = "Current menu item color"; } + # entry + property Color c_entry_background { des = "Entry background color"; } + property Color c_entry_link { des = "Entry link color"; } + property Color c_entry_link_visited { des = "Entry visited link color"; } + property Color c_entry_link_hover { des = "Entry hover link color"; } + property Color c_entry_link_active { des = "Entry active link color"; } + property Color c_entry_text_color { des = "Entry text color"; } + property Color c_entry_title_color { des = "Entry title color"; } + property Color c_entry_border { des = "Entry bottom border color"; } + # metadata + property Color c_meta_background { des = "Entry metadata background color"; } + property Color c_meta_link { des = "Entry metadata link color"; } + property Color c_meta_link_visited { des = "Entry metadata visited link color"; } + property Color c_meta_link_hover { des = "Entry metadata hover link color"; } + property Color c_meta_link_active { des = "Entry metadata active link color"; } + property Color c_meta_text_color { des = "Entry metadata text color"; } + # footer + property Color c_footer_background { des = "Page footer background color"; } + property Color c_footer_link { des = "Page footer link color"; } + property Color c_footer_link_visited { des = "Page footer visited link color"; } + property Color c_footer_link_hover { des = "Page footer hover link color"; } + property Color c_footer_link_active { des = "Page footer active link color"; } + property Color c_footer_text_color { des = "Page footer text color"; } + # comments + property Color c_comment_one_link { des = "Comment one link color"; } + property Color c_comment_one_link_visited { des = "Comment one visited link color"; } + property Color c_comment_one_link_hover { des = "Comment one hover link color"; } + property Color c_comment_one_link_active { des = "Comment one active link color"; } + property Color c_comment_one_text_color { des = "Comment one text color"; } + property Color c_comment_one_title_color { des = "Comment one title color"; } + property Color c_comment_one_background { des = "Comment bar one background color"; } + property Color c_comment_one_border { des = "Comment one bottom border color"; } + property Color c_comment_two_link { des = "Comment two link color"; } + property Color c_comment_two_link_visited { des = "Comment two visited link color"; } + property Color c_comment_two_link_hover { des = "Comment two hover link color"; } + property Color c_comment_two_link_active { des = "Comment two active link color"; } + property Color c_comment_two_text_color { des = "Comment two text color"; } + property Color c_comment_two_title_color { des = "Comment two title color"; } + property Color c_comment_two_background { des = "Comment two background color"; } + property Color c_comment_two_border { des = "Comment two bottom border color"; } + property Color c_comment_screened_link { des = "Comment screened link color"; } + property Color c_comment_screened_link_visited { des = "Comment screened visited link color"; } + property Color c_comment_screened_link_hover { des = "Comment screened hover link color"; } + property Color c_comment_screened_link_active { des = "Comment screened active link color"; } + property Color c_comment_screened_text_color { des = "Comment screened text color"; } + property Color c_comment_screened_title_color { des = "Comment screened title color"; } + property Color c_comment_screened_background { des = "Comment screened background color"; } + property Color c_comment_screened_border { des = "Comment screened bottom border color"; } +} + + +# PROPERTIES: FONTS +propgroup Fonts { + # page + property string f_page { des = "Generic font for use on the page"; } + property string f_page_size { des = "Generic font size for use on the page"; } + property string f_page_title { des = "Page title font"; } + property string f_page_title_size { des = "Page title font size"; } + property string f_page_link { des = "Generic font for links on the page"; } + property string f_page_link_size { des = "Generic font size for links on the page"; } + # menu + property string f_menu_link { des = "Menu link font"; } + property string f_menu_link_size { des = "Menu link font size"; } + property string f_menu { des = "Menu font"; } + property string f_menu_size { des = "Menu font size"; } + property string f_menu_header { des = "Menu title font"; } + property string f_menu_header_size { des = "Menu title font size"; } + property string f_menu_current { des = "Current menu item font"; } + property string f_menu_current_size { des = "Current menu item font size"; } + # entry + property string f_entry { des = "Entry font"; } + property string f_entry_size { des = "Entry font size"; } + property string f_entry_link { des = "Entry link font"; } + property string f_entry_link_size { des = "Entry link font size"; } + property string f_entry_title { des = "Entry title font"; } + property string f_entry_title_size { des = "Entry title font size"; } + # metadata + property string f_meta { des = "Entry metadata font"; } + property string f_meta_size { des = "Entry metadata font size"; } + property string f_meta_link { des = "Entry metadata link font"; } + property string f_meta_link_size { des = "Entry metadata link font size"; } + # footer + property string f_footer { des = "Footer font"; } + property string f_footer_size { des = "Footer font size"; } + property string f_footer_link { des = "Footer link font"; } + property string f_footer_link_size { des = "Footer link font size"; } + # comments + property string f_comment { des = "Comment font"; } + property string f_comment_size { des = "Comment font size"; } + property string f_comment_title { des = "Comment title font"; } + property string f_comment_title_size { des = "Comment title font size"; } + property string f_comment_link { des = "Comment link font"; } + property string f_comment_link_size { des = "Comment link font size"; } +} + + +# PROPERTIES: PRESENTATION +propgroup Presentation { + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; } + property string time_format { des = "Format for the time"; example = "%%hh%%:%%min%%:%%sec%% %%a%%m"; } + property string date_format { des = "Format for the date"; example = "%%m%%/%%d%%/%%yy%%"; } + property bool menu_disable_summary { des = "Disable menu summary view"; } + property string css_page_width { des = "Width of the main page (increasing this will increase the main column's width)"; } + property string css_style_overrides { des = "include any CSS here to override the default CSS"; } +} + + +# PROPERTIES: TEXT +propgroup Text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_reply_nocomments_header; + property use text_reply_nocomments; + property use text_comment_from; + property use text_comment_ipaddr; + property use text_comment_parent; + property use text_comment_reply; + property use text_comment_thread; + property use text_nosubject; + property use text_post_comment; + property use text_post_comment_friends; + property use text_max_comments; + property use text_view_month; + property string text_comment_anonymous { des = "Text to substitute for anonymous commenters"; } + property string text_comment_viewall { des = "Text for view all comments"; } + property string text_links_header { des = "Sidebar links header text"; } + property string text_summary_header { des = "Page summary text header"; } + property string text_links_spacer { des = "String to act as links list spacer";} +} + + +# ------------------------------- +# default property settings +# ------------------------------- +# ODD +set c_main_border = "#000"; +set c_main_background = "#fff"; +set c_menu_border = "#333"; +set c_header_background = "#333"; +set c_header_border = "#333"; +set c_page_title = "#fff"; +set c_page_background = "#333"; +set c_page_text = "#333"; +set c_page_link = "#5ab300"; +set c_page_link_visited = "#5ab300"; +set c_page_link_hover = "#336600"; +set c_page_link_active = "#336600"; +set c_menu_background = "#333"; +set c_menu_link = "#999"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#fff"; +set c_menu_link_active = "#fff"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#fff"; +set c_entry_background = "#fff"; +set c_entry_link = "#5ab300"; +set c_entry_link_visited = "#5ab300"; +set c_entry_link_hover = "#336600"; +set c_entry_link_active = "#336600"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#333"; +set c_entry_border = "#ccc"; +set c_meta_background = "#fff"; +set c_meta_link = "#5ab300"; +set c_meta_link_visited = "#5ab300"; +set c_meta_link_hover = "#336600"; +set c_meta_link_active = "#336600"; +set c_meta_text_color = "#000"; +set c_footer_background = "#333"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#5ab300"; +set c_comment_one_link_visited = "#5ab300"; +set c_comment_one_link_hover = "#336600"; +set c_comment_one_link_active = "#336600"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#333"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#5ab300"; +set c_comment_two_link_visited = "#5ab300"; +set c_comment_two_link_hover = "#336600"; +set c_comment_two_link_active = "#336600"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#333"; +set c_comment_two_background = "#fff"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#708CC4"; +set c_comment_screened_link_visited = "#5ab300"; +set c_comment_screened_link_hover = "#336600"; +set c_comment_screened_link_active = "#336600"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#333"; +set c_comment_screened_background = "#fff"; +set c_comment_screened_border = "#999"; + +# FONTS +set f_page = "Georgia, serif"; +set f_page_title = "Georgia, serif"; +set f_page_title_size = "190%"; +set f_page_size = "12px"; +set f_page_link = "Georgia, serif"; +set f_page_link_size = "100%"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu_link_size = "80%"; +set f_menu = "Georgia, serif"; +set f_menu_size = "100%"; +set f_menu_header = "Georgia, serif"; +set f_menu_header_size = "120%"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_menu_current_size = "80%"; +set f_entry = "Georgia, serif"; +set f_entry_size = "100%"; +set f_entry_link = "Georgia, serif"; +set f_entry_link_size = "100%"; +set f_entry_title = "Georgia, serif"; +set f_entry_title_size = "150%"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_size = "80%"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_meta_link_size = "100%"; +set f_footer = "Georgia, serif"; +set f_footer_size = "100%"; +set f_footer_link = "Georgia, serif"; +set f_footer_link_size = "100%"; +set f_comment = "Georgia, serif"; +set f_comment_size = "100%"; +set f_comment_title = "Georgia, serif"; +set f_comment_title_size = "130%"; +set f_comment_link = "Georgia, serif"; +set f_comment_link_size = "100%"; + +# OTHER +set show_entrynav_icons = true; +set time_format = "%%hh%%:%%min%% %%a%%m"; +set date_format = "%%mon%%. %%dayord%%, %%yyyy%%"; +set menu_disable_summary = false; +set css_style_overrides = ""; +set css_page_width = "800px"; + +# TEXT +set text_meta_music = "music"; +set text_links_header = "links"; +set text_meta_mood = "mood"; +set text_read_comments = "{#}"; +set text_read_comments_friends = "{#}"; +set text_comment_anonymous = "anonymous"; +set text_comment_viewall = "view all comments"; +set text_links_header = "Links"; +set text_summary_header = "Page Summary"; +set text_links_spacer = "_______________"; + + + +# ======================================== +# METHODS +# ======================================== + + +# ------------------------------- +# stylesheet +# ------------------------------- +function print_stylesheet ( ) +{ + """ + @media screen, print { + * { + margin: 0; + padding: 0; + } + hr { + display: none; + } + body { + background-color: $*c_page_background; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + text-align: center; + } + a { + font-family: $*f_page_link; + font-size: $*f_page_link_size; + color: $*c_page_link; + text-decoration: none; + } + a:visited { color: $*c_page_link_visited; } + a:hover, a:visited:hover { color: $*c_page_link_hover; text-decoration: underline; } + a:active { color: $*c_page_link_active; } + a img { border: none; } + a.comm { + background: transparent url(http://stat.livejournal.com/img/community.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + a.user { + background: transparent url(http://stat.livejournal.com/img/userinfo.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + p { + margin: 5px; + padding: 5px; + } + + form { + display: inline; + margin: 0px; + padding: 0px; + } + input, select, textarea { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + padding: 2px; + margin: 3px; + } + + #container { + position: relative; + width: $*css_page_width; + margin: 0 auto; + text-align: left; + } + #header { + margin-bottom: 15px; + border: 1px solid $*c_header_border; + background-color: $*c_header_background; + } + + #header h1 { + padding: 20px; + font-family: $*f_page_title; + font-size: $*f_page_title_size; + color: $*c_page_title; + } + + #menu { + position: relative; + background-color: $*c_menu_background; + float: left; + width: 150px; + font-family: $*f_menu; + font-size: $*f_menu_size; + color: $*c_menu_text_color; + border: 1px solid $*c_menu_border; + padding: 4px; + } + #content { + position: relative; + margin-left: 160px; + } + + #entries { + border: 1px solid $*c_main_border; + padding: 15px; + background-color: $*c_main_background; + } + + #menu h2 { + margin: 20px 0; + font-family: $*f_menu_header; + font-size: $*f_menu_header_size; + color: $*c_menu_header_color; + } + #menu h2.userpic { + text-align: center; + } + #menu a { + font-family: $*f_menu_link; + font-size: $*f_menu_link_size; + color: $*c_menu_link; + } + #menu a:visited { color: $*c_menu_link_visited; } + #menu a:hover, #menu a:visited:hover { color: $*c_menu_link_hover; } + #menu a:active { color: $*c_menu_link_active; } + #menu ul { + margin: 3px; + list-style: none; + } + #menu ul li { + margin: 3px; + padding: 2px; + list-style: none; + } + #menu ul li.active { + font-family: $*f_menu_current; + font-size: $*f_menu_current_size; + color: $*c_menu_current; + font-weight: bold; + } + #content h2 { + margin: 20px 0; + } + #entries, #comments { + margin: 10px; + } + .ind-entry { + padding: 5px; + padding-bottom: 15px; + border-bottom: 1px solid $*c_entry_border; + background-color: $*c_entry_background; + } + .ind-entry h3 img, .ind-comment-one h3 img, .ind-comment-two h3 img, .ind-comment-screened h3 img { + position: relative; + float: right; + padding: 5px; + } + .ind-entry h2 { + font-family: $*f_entry_title; + font-size: $*f_entry_title_size; + color: $*c_entry_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-entry h4, .ind-comment-one h4, .ind-comment-two h4, .ind-comment-screened h4 { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + } + .ind-entry h4 { + background-color: $*c_meta_background; + } + .ind-entry h4 a, .ind-comment-one h4 a, .ind-comment-two h4 a, .ind-comment-screened h4 a { + font-family: $*f_meta_link; + font-size: $*f_meta_link_size; + color: $*c_meta_link; + text-decoration: underline; + } + .ind-entry h4 a:visited, .ind-comment-one h4 a:visited, .ind-comment-two h4 a:visited, .ind-comment-screened h4 a:visited { color: $*c_meta_link_visited; } + .ind-entry h4 a:hover, .ind-comment-one h4 a:hover, .ind-comment-two h4 a:hover, .ind-comment-screened h4 a:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:visited:hover, .ind-comment-one h4 a:visited:hover, .ind-comment-two h4 a:visited:hover, .ind-comment-screened h4 a:visited:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:active, .ind-comment-one h4 a:active, .ind-comment-two h4 a:active, .ind-comment-screened h4 a:active { color: $*c_meta_link_active; } + .ind-entry div.entry-item, .ind-entry div.month-entries { + font-family: $*f_entry; + font-size: $*f_entry_size; + color: $*c_entry_text_color; + margin: 15px 0px; + } + .ind-entry div.entry-item a, .ind-entry div.month-entries a { + font-family: $*f_entry_link; + font-size: $*f_entry_link_size; + color: $*c_entry_link; + text-decoration: underline; + } + .ind-entry div.entry-item a:visited, .ind-entry div.month-entries a:visited { color: $*c_entry_link_visited; } + .ind-entry div.entry-item a:hover, .ind-entry div.entry-item a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.month-entries a:hover, .ind-entry div.month-entries a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.entry-item a:active, .ind-entry div.month-entries a:active { color: $*c_entry_link_active; } + + .ind-comment-one, .ind-comment-two, .ind-comment-screened { + margin: 10px 0; + padding: 5px; + } + .ind-comment-one { background-color: $*c_comment_one_background; border-bottom: 1px solid $*c_comment_one_border; } + .ind-comment-two { background-color: $*c_comment_two_background; border-bottom: 1px solid $*c_comment_two_border; } + .ind-comment-screened { background-color: $*c_comment_screened_background; border-bottom: 1px solid $*c_comment_screened_border; } + + .ind-comment-one h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_one_title_color; + margin: 20px 0px; + } + .ind-comment-one div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_one_text_color; + margin: 15px 0px; + } + .ind-comment-one div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_one_link; + text-decoration: underline; + } + .ind-comment-one div.entry-item a:visited { color: $*c_comment_one_link_visited; } + .ind-comment-one div.entry-item a:hover, .ind-comment-one div.entry-item a:visited:hover { color: $*c_comment_one_link_hover; } + .ind-comment-one div.entry-item a:active { color: $*c_comment_one_link_active; } + + .ind-comment-two h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_two_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-comment-two div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_two_text_color; + margin: 10px 0px; + } + .ind-comment-two div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_two_link; + text-decoration: underline; + } + .ind-comment-two div.entry-item a:visited { color: $*c_comment_two_link_visited; } + .ind-comment-two div.entry-item a:hover, .ind-comment-two div.entry-item a:visited:hover { color: $*c_comment_two_link_hover; } + .ind-comment-two div.entry-item a:active { color: $*c_comment_two_link_active; } + + .ind-comment-screened h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_screened_title_color; + margin: 20px 0px; + } + .ind-comment-screened div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_screened_text_color; + margin: 10px 0px; + } + .ind-comment-screened div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_screened_link; + text-decoration: underline; + } + .ind-comment-screened div.entry-item a:visited { color: $*c_comment_screened_link_visited; } + .ind-comment-screened div.entry-item a:hover, .ind-comment-screened div.entry-item a:visited:hover { color: $*c_comment_screened_link_hover; } + .ind-comment-screened div.entry-item a:active { color: $*c_comment_screened_link_active; } + + .month-entries { + margin: 10px 0; + } + .month-entries ul { + list-style: none; + margin: 10px; + } + .month-entries ul li { + list-style: none; + padding: 3px; + } + + + #footer { + position: relative; + font-family: $*f_footer; + font-size: $*f_footer_size; + color: $*c_footer_text_color; + background-color: $*c_footer_background; + } + #footer p { + padding: 20px; + } + #footer a { + font-family: $*f_footer_link; + font-size: $*f_footer_link_size; + color: $*c_footer_link; + } + #footer a:visited { color: $*c_footer_link_visited; } + #footer a:hover, #footer a:visited:hover { color: $*c_footer_link_hover; } + #footer a:active { color: $*c_footer_link_active; } + } + + @media print { + #menu { + display: none; + } + #content { + margin-left: 0px; + } + #entries, .ind-entry, .ind-comment, #footer, #header { + border: none; + } + + } + + $*css_style_overrides + + """; +} + + +# ------------------------------- +# user pic main page +# ------------------------------- +function Page::lay_top_userpic ( ) +{ + var Image up_img = $.journal.default_pic; + if ( defined $up_img ) { + print "

    \"$.journal.name\"

    "; + } +} + + +# ------------------------------- +# returns a permalink link based on +# the url passed +# ------------------------------- +function get_permalink ( string url ) : string +{ + return("$*text_permalink"); +} + + +# ------------------------------- +# prints the user's 'link-list' +# ------------------------------- +function Page::print_linklist ( ) +{ + if ( size $.linklist > 0 ) { + print "

    $*text_links_header

    "; + print "
      "; + foreach var UserLink l ( $.linklist ) { + if ( $l.title == "spacer" ) { + print "
    • $*text_links_spacer
    • "; + } elseif ($l.is_heading) { + print "
    • $l.title
    • "; + } elseif ( $l.title ) { + print "
    • $l.title
    • "; + } + } + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# prints the LJ specific links (recent, friends, etc) +# ------------------------------- +function print_lj_links ( Page p ) +{ + var string links; + $links = $links + ($p.view == "recent" ? "
  • $*text_view_recent
  • " : "
  • $*text_view_recent
  • "); + if ( $p.journal_type == "C" ) { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends_comm
  • " : "
  • $*text_view_friends_comm
  • "); + } else { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends
  • " : "
  • $*text_view_friends
  • "); + } + $links = $links + ($p.view == "archive" ? "
  • $*text_view_archive
  • " : "
  • $*text_view_archive
  • "); + $links = $links + "
  • $*text_view_userinfo
  • "; + $links = $links + ($p.journal.website_url != "" ? "
  • lower() + "\">" + $p.journal.website_name->lower() + "
  • " : ""); + + print "
      "; + print $links; + print "
    "; + print "
    "; +} + +function Page::lay_sidebar_view_summary() : string +{ + return(""); +} + + +# ------------------------------- +# main page layout +# ------------------------------- +function Page::print ( ) +{ + var string title = $this->title(); + + # generate page id: + var string current_view = $.view; + if ( $.view == "month" or $.view == "day" ) { + $current_view = "archive"; + } + if ( $.view == "entry" or $.view == "reply" ) { + $current_view = "recent"; + } + + # begin main page html: + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + $this->print_head(); + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$title\n"; + print "\n"; + print "\n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    $title

    \n"; + print "
    "; + print "
    \n"; + print "
    \n"; + print "
    \n"; + $this->lay_top_userpic(); + print "\n"; + print_lj_links($this); + print($this->lay_sidebar_view_summary()); + $this->print_linklist(); + print "
    \n"; + print "
    \n"; + $this->print_body(); + print "
    \n"; + print "
    \n"; + print "\n"; + print "\n"; +} + + +# ------------------------------- +# main page display entries and +# footer +# ------------------------------- +function RecentPage::print_body ( ) +{ + # print all entries + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + + var string range = "most recent entries"; + if ( $.nav.skip > 0 ) { + $range = "$.nav.skip entries back"; + } + + print "

    "; + print "viewing: $range
    "; + # go forward/backward if possible + if ( $.nav.forward_url != "" or $.nav.backward_url != "" ) { + var string sep; + var string back; + var string forward; + if ( $.nav.backward_url != "" ) { + $back = "earlier"; + } + if ( $.nav.forward_url != "" ) { + $forward = "later"; + } + if ( $back != "" and $forward != "" ) { + $sep = " | "; + } + print "go: $back$sep$forward
    "; + } + print "

    "; +} + + +# ------------------------------- +# entry view (show comments) +# ------------------------------- +function EntryPage::print_body ( ) +{ + print "
    \n"; + $this->print_entry ( $.entry ); + if ( $.entry.comments.enabled ) { + print "

    Comments {$.entry.comments.count}

    "; + print "
    "; + if ( $.comment_pages.total_subitems > 0 ) { + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + $.comment_pages->print(); + $this->print_comments($.comments); + if ( $this.multiform_on ) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } + print "
    "; + } + print "
    "; + print "

    "; + print "$*text_post_comment\n"; + print "

    "; +} + + +# ------------------------------- +# day view +# ------------------------------- +function DayPage::print_body ( ) +{ + if ( not $.has_entries ) { + print "
    \n"; + print "
    \n"; + print "

    " + $.date->date_format("long") + "

    "; + print "

    $*text_noentries_day

    "; + print "
    "; + print "
    "; + print "
    "; + } else { + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + print "

    "; + print "« $*text_day_prev | $*text_day_next »"; + print "

    "; +} + + +# ------------------------------- +# year view +# ------------------------------- +function YearPage::print_body ( ) +{ + print "
    \n"; + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print "
    "; +} + + +# ------------------------------- +# page summary for recent page +# ------------------------------- +function RecentPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for day page +# ------------------------------- +function DayPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for entry page +# ------------------------------- +function EntryPage::lay_sidebar_view_summary() : string { + var string return; + if ( not $*menu_disable_summary ) { + foreach var Comment c ( $.comments ) { + if ( $c.depth == 1 ) { + $return = $return + "
  • " + ($c.subject != "" ? "$c.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# display an entry (all views ) +# ------------------------------- +function print_entry ( Page p, Entry e ) +{ + # get date/time + var string datetime; + $datetime = $e.time->date_format($*date_format) + " | " + $e.time->time_format($*time_format); + + # get metadata + var string metadata; + if ( $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string text = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $text = $*text_meta_mood; + } elseif ( $k == "music" ) { + $text = $*text_meta_music; + } + if ( $k == "mood" and defined $e.mood_icon ) { + var Image i = $e.mood_icon; + $val = "\"$val\" $val"; + } + $metadata = "$metadata\n$text: $val
    "; + } + } + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( $p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username ) { + if ( $e.poster.username != $e.journal.username ) { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username in base_url() + "\" title=\"$e.journal.username\" >$e.journal.username"; + } else { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username"; + } + $poster = "posted by: $poster"; + if ( defined $e.userpic ) { + $userpic = "

    \"$e.journal.username\"

    "; + } + } + + # print the entry now: + print "
    "; + + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + + print "

    "; + if ( $e.security != "" ) { + $e.security_icon->print(); + print " "; + } + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + print "

    "; + + print "

    "; + if ( $p.view == "entry" and $*show_entrynav_icons ) { + var string item_link = ""; + foreach var string key (["nav_prev","nav_next"]) { + var Link link = $e->get_link($key); + if ( $link ) { + if ( $key == "nav_prev" ) { + $item_link = $item_link + "lower() + "\">« " + $link.caption->lower() + " | "; + } elseif ( $key == "nav_next" ) { + $item_link = $item_link + "lower() + "\">" + $link.caption->lower() + " »"; + } + } + } + print $item_link; + print "
    "; + } + print "$datetime
    "; + print "$metadata"; + if ( $poster != "" ) { + print "$poster"; + } + print "

    "; + + print "
    $e.text
    \n"; + + print "

    "; + print get_permalink($e.permalink_url); + if ( $p.view != "entry" and $p.view != "reply" ) { + print " | "; + $e.comments->print(); + } elseif ( $e.comments.enabled ) { + print " | "; + $e.comments->print_postlink(); + } + var Link tmp; + if ( viewer_is_owner() and $p.view != "friends" ) { + $tmp = $e->get_link("edit_entry"); + print " | $tmp.caption"; + } + $tmp = $e->get_link("mem_add"); + print " | $tmp.caption"; + print "

    "; + print "
    "; + print "
    "; +} + + +# ------------------------------- +# entry wrapper for main page +# ------------------------------- +function Page::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# entry wrapper for friends page +# ------------------------------- +function FriendsPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +function EntryPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# comments +# ------------------------------- +function CommentInfo::print ( ) +{ + if ( not $.enabled ) { + return; + } + + $this->print_postlink(); + if ( $.count > 0 or $.screened ) { + print " "; + print ""; + $this->print_readlink(); + print ""; + } +} + + +# ------------------------------- +# comment post link +# ------------------------------- +function CommentInfo::print_postlink ( ) +{ + var Page p = get_page(); + var string linktext = ( $p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment ); + if ( $.maxcomments ) { + "$*text_max_comments"; + } else { + "$linktext"; + } +} + + +# ------------------------------- +# print comment +# ------------------------------- +function EntryPage::print_comment ( Comment c ) +{ + var string comment_class = ""; + if ( $c.screened ) { + $comment_class = "ind-comment-screened"; + } elseif ( $c.depth % 2 == 0 ) { + $comment_class = "ind-comment-two"; + } else { + $comment_class = "ind-comment-one"; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_comment_anonymous"; + var string poster_text = defined $c.poster ? $c.poster.name : "$*text_comment_anonymous"; + var string sub_icon; + var int indent = (($c.depth - 1) * 5); + if ( defined $c.subject_icon ) { + $sub_icon = $c.subject_icon->as_string(); + } + + print "
    \n"; + + var string userpic; + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + $userpic = "

    \"$poster_text\"

    "; + } + var string commentdate = $c.time->date_format($*date_format) + " - " + $c.time->time_format($*time_format); + + #userpic + print "$userpic\n"; + + # subject: + if ( $c.subject == "" ) { + print "

    $c.subject_icon $*text_nosubject

    "; + } else { + print "

    $c.subject_icon $c.subject

    "; + } + + print "

    "; + print "from: $poster
    \n"; + print "date: $commentdate
    \n"; + if ( $c.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $c.metadata{"poster_ip"} + "
    "; + } + print get_permalink($c.permalink_url) + "
    \n"; + var Link lnk; + $lnk = $c->get_link("delete_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("screen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("unscreen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + print "

    \n"; + + if ( $this.multiform_on ) { + print ""; + $c->print_multiform_check(); + } + + print "
    $c.text
    \n"; + print "

    "; + print "$*text_comment_reply"; + if ( $c.parent_url != "" ) { print " | $*text_comment_parent"; } + if ( $c.thread_url != "" ) { print " | $*text_comment_thread"; } + print "

    "; + print "
    \n\n"; + print "
    "; +} + + +# ------------------------------- +# print reply form page +# ------------------------------- +function ReplyPage::print_body ( ) +{ + if ( not $.entry.comments.enabled ) { + print "
    \n"; + print "
    "; + print "

    $*text_reply_nocomments_header

    "; + print "$*text_reply_nocomments"; + print "
    "; + print "
    "; + + } else { + print "
    \n"; + + # get date + var string datetime; + $datetime = $.replyto.time->date_format($*date_format) + " | " + $.replyto.time->time_format($*time_format); + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( defined $.replyto.poster ) { + $poster = "base_url() + "\" title=\"$.replyto.poster.username\">$.replyto.poster.username"; + if ( defined $.replyto.userpic ) { + $userpic = "

    \"$.replyto.poster.username\"

    "; + } + } else { + $poster = "$*text_comment_anonymous"; + } + + + # print the entry now: + print "
    "; + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + print "

    "; + if ( $.replyto.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$.replyto.subject"; + } + print "

    "; + + print "

    \n"; + print "$datetime
    "; + print "$*text_comment_from: $poster"; + if ( $.replyto.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $.replyto.metadata{"poster_ip"} + "
    "; + } + print "

    "; + print "
    $.replyto.text
    \n"; + print "

    "; + print get_permalink($.replyto.permalink_url) + " | $*text_comment_viewall\n"; + print "

    "; + print "
    \n"; + print "
    "; + print "
    \n"; + print "

    Reply

    \n"; + $.form->print(); + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# print available years +# ------------------------------- +function YearPage::print_year_links ( ) +{ + print "

    "; + print "available years:
    "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + print "$y.year "; + } else { + print "$y.year "; + } + } + print "

    "; +} + + +# ------------------------------- +# print available month +# ------------------------------- +function YearPage::print_month ( YearMonth m ) +{ + if ( not $m.has_entries ) { + return; + } + + print "
    \n"; + print "

    " + $m->month_format() + "

    \n"; + print "

    $*text_view_month

    "; + print "
    "; + foreach var YearWeek w ( $m.weeks ) { + foreach var YearDay d ( $w.days ) { + if ( $d.num_entries > 0 ) { + var string date = $d.date->date_format("%%dayord%%"); + print "$date {$d.num_entries}
    \n"; + } + } + } + print "
    \n"; + print "
    \n"; + print "
    "; +} + + +# ------------------------------- +# month view +# ------------------------------- +function MonthPage::print_body ( ) +{ + print "
    "; + print "
    \n"; + print "

    " + $.date->date_format($*lang_fmt_month_long) + "

    "; + + print "
    "; + $.redir->print_hiddens(); + if ( $.prev_url != "" ) { + print "[«]\n"; + } + if ( size $.months > 1 ) { + print "\n"; + } + if ( $.next_url != "" ) { + print "\n[»]\n"; + } + print "


    "; + + # print dates: + foreach var MonthDay d ( $.days ) { + if ( $d.has_entries ) { + print "
    \n"; + print "" + lang_ordinal($d.day) + "
    "; + print "
      "; + foreach var Entry e ( $d.entries ) { + print "
    • "; + print "" + $e.time->time_format("short") + " "; + if ( $e.poster.username != $e.journal.username ) { + $e.poster->print(); " : "; + } + "$e.security_icon "; + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + if ( $e.comments.count > 0 ) { + print " {" + $e.comments.count + "}"; + } + print "
    • "; + } + print "
    "; + print "
    "; + print "
    "; + } + } + print "
    \n"; + print "
    "; +} diff --git a/ljcom/bin/upgrading/s2layers/tranquilityii/themes.s2 b/ljcom/bin/upgrading/s2layers/tranquilityii/themes.s2 new file mode 100644 index 0000000..407654f --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/tranquilityii/themes.s2 @@ -0,0 +1,707 @@ +#NEWLAYER: tranquilityii/plain +layerinfo "redist_uniq" = "tranquilityii/plain"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Plain Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#fff"; +set c_menu_border = "#fff"; +set c_header_background = "#fff"; +set c_header_border = "#fff"; +set c_page_title = "#000"; +set c_page_background = "#fff"; +set c_page_text = "#333"; +set c_page_link = "#036"; +set c_page_link_visited = "#036"; +set c_page_link_hover = "#069"; +set c_page_link_active = "#069"; +set c_menu_background = "#fff"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#000"; +set c_menu_link_hover = "#f00"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#000"; +set c_menu_current = "#000"; +set c_entry_background = "#fff"; +set c_entry_link = "#000"; +set c_entry_link_visited = "#000"; +set c_entry_link_hover = "#000"; +set c_entry_link_active = "#000"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#999"; +set c_meta_background = "#fff"; +set c_meta_link = "#000"; +set c_meta_link_visited = "#000"; +set c_meta_link_hover = "#000"; +set c_meta_link_active = "#000"; +set c_meta_text_color = "#000"; +set c_footer_background = "#fff"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#000"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#000"; +set c_comment_one_link_visited = "#000"; +set c_comment_one_link_hover = "#000"; +set c_comment_one_link_active = "#000"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#000"; +set c_comment_two_link_visited = "#000"; +set c_comment_two_link_hover = "#000"; +set c_comment_two_link_active = "#000"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#000"; +set c_comment_screened_link_visited = "#000"; +set c_comment_screened_link_hover = "#000"; +set c_comment_screened_link_active = "#000"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/earth +layerinfo "redist_uniq" = "tranquilityii/earth"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Earth Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#424B15"; +set c_header_background = "#667320"; +set c_header_border = "#667320"; +set c_page_title = "#fff"; +set c_page_background = "#667320"; +set c_page_text = "#333"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#424B15"; +set c_menu_background = "#88992B"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#424B15"; +set c_menu_link_hover = "#424B15"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#fff"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#99602B"; +set c_entry_link_visited = "#BF7836"; +set c_entry_link_hover = "#734820"; +set c_entry_link_active = "#734820"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#000"; +set c_entry_border = "#BFBFBF"; +set c_meta_background = "#fff"; +set c_meta_link = "#99602B"; +set c_meta_link_visited = "#BF7836"; +set c_meta_link_hover = "#734820"; +set c_meta_link_active = "#734820"; +set c_meta_text_color = "#666"; +set c_footer_background = "#667320"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#99602B"; +set c_comment_one_link_visited = "#BF7836"; +set c_comment_one_link_hover = "#734820"; +set c_comment_one_link_active = "#734820"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#99602B"; +set c_comment_two_link_visited = "#BF7836"; +set c_comment_two_link_hover = "#734820"; +set c_comment_two_link_active = "#734820"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#99602B"; +set c_comment_screened_link_visited = "#BF7836"; +set c_comment_screened_link_hover = "#734820"; +set c_comment_screened_link_active = "#734820"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/money +layerinfo "redist_uniq" = "tranquilityii/money"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Money Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#68754D"; +set c_header_background = "#ACC280"; +set c_header_border = "#ACC280"; +set c_page_title = "#3D3D3D"; +set c_page_background = "#ACC280"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#68754D"; +set c_menu_background = "#8A9C67"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#000"; +set c_menu_link_hover = "#EBF7D4"; +set c_menu_link_active = "#ebf7d4"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#000"; +set c_menu_current = "#EBF7D4"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#679C67"; +set c_entry_link_visited = "#80C280"; +set c_entry_link_hover = "#4D754D"; +set c_entry_link_active = "#4D754D"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#3D3D3D"; +set c_meta_background = "#fff"; +set c_meta_link = "#679C67"; +set c_meta_link_visited = "#80C280"; +set c_meta_link_hover = "#4D754D"; +set c_meta_link_active = "#4D754D"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#ACC280"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#679C67"; +set c_comment_one_link_visited = "#80C280"; +set c_comment_one_link_hover = "#4D754D"; +set c_comment_one_link_active = "#4D754D"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#679C67"; +set c_comment_two_link_visited = "#80C280"; +set c_comment_two_link_hover = "#4D754D"; +set c_comment_two_link_active = "#4D754D"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#679C67"; +set c_comment_screened_link_visited = "#80C280"; +set c_comment_screened_link_hover = "#4D754D"; +set c_comment_screened_link_active = "#4D754D"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/winterice +layerinfo "redist_uniq" = "tranquilityii/winterice"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - WinterIce Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#000"; +set c_header_background = "#694D73"; +set c_header_border = "#694D73"; +set c_page_title = "#000"; +set c_page_background = "#694D73"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#694D73"; +set c_menu_background = "#694D73"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#fff"; +set c_menu_link_hover = "#C5A2D0"; +set c_menu_link_active = "#C5A2D0"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#C5A2D0"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#5E71AE"; +set c_entry_link_visited = "#5E71AE"; +set c_entry_link_hover = "#808FBF"; +set c_entry_link_active = "#808FBF"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#3D3D3D"; +set c_meta_background = "#fff"; +set c_meta_link = "#B080BF"; +set c_meta_link_visited = "#C29FCB"; +set c_meta_link_hover = "#854D93"; +set c_meta_link_active = "#854D93"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#694D73"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#5E71AE"; +set c_comment_one_link_visited = "#5E71AE"; +set c_comment_one_link_hover = "#808FBF"; +set c_comment_one_link_active = "#808FBF"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#5E71AE"; +set c_comment_two_link_visited = "#5E71AE"; +set c_comment_two_link_hover = "#808FBF"; +set c_comment_two_link_active = "#808FBF"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#5E71AE"; +set c_comment_screened_link_visited = "#5E71AE"; +set c_comment_screened_link_hover = "#808FBF"; +set c_comment_screened_link_active = "#808FBF"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/fire +layerinfo "redist_uniq" = "tranquilityii/fire"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Fire Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#A65000"; +set c_header_background = "#A65000"; +set c_header_border = "#A65000"; +set c_page_title = "#000"; +set c_page_background = "#A65000"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#A68700"; +set c_menu_background = "#CCA700"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#FFD100"; +set c_menu_link_hover = "#CC4100"; +set c_menu_link_active = "#CC4100"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#CC4100"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#CC6300"; +set c_entry_link_visited = "#F27500"; +set c_entry_link_hover = "#A65000"; +set c_entry_link_active = "#A65000"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#333"; +set c_entry_border = "#666"; +set c_meta_background = "#fff"; +set c_meta_link = "#CCA700"; +set c_meta_link_visited = "#F2C600"; +set c_meta_link_hover = "#A68700"; +set c_meta_link_active = "#A68700"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#A65000"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#CC6300"; +set c_comment_one_link_visited = "#F27500"; +set c_comment_one_link_hover = "#A65000"; +set c_comment_one_link_active = "#A65000"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#CC6300"; +set c_comment_two_link_visited = "#F27500"; +set c_comment_two_link_hover = "#A65000"; +set c_comment_two_link_active = "#A65000"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#CC6300"; +set c_comment_screened_link_visited = "#F27500"; +set c_comment_screened_link_hover = "#A65000"; +set c_comment_screened_link_active = "#A65000"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/mobile +layerinfo "redist_uniq" = "tranquilityii/mobile"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Mobile Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#fff"; +set c_header_background = "#fff"; +set c_header_border = "#fff"; +set c_page_title = "#000"; +set c_page_background = "#fff"; +set c_page_text = "#000"; +set c_page_link = "#00f"; +set c_page_link_visited = "#999"; +set c_page_link_hover = "#f00"; +set c_page_link_active = "#f00"; +set c_menu_border = "#fff"; +set c_menu_background = "#fff"; +set c_menu_link = "#00f"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#f00"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#00"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#00f"; +set c_entry_link_visited = "#999"; +set c_entry_link_hover = "#f00"; +set c_entry_link_active = "#f00"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#fff"; +set c_meta_background = "#fff"; +set c_meta_link = "#00f"; +set c_meta_link_visited = "#999"; +set c_meta_link_hover = "#f00"; +set c_meta_link_active = "#f00"; +set c_meta_text_color = "#000"; +set c_footer_background = "#fff"; +set c_footer_link = "#00f"; +set c_footer_link_visited = "#999"; +set c_footer_link_hover = "#f00"; +set c_footer_link_active = "#f00"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#00f"; +set c_comment_one_link_visited = "#999"; +set c_comment_one_link_hover = "#f00"; +set c_comment_one_link_active = "#f00"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#fff"; +set c_comment_two_link = "#00f"; +set c_comment_two_link_visited = "#999"; +set c_comment_two_link_hover = "#f00"; +set c_comment_two_link_active = "#f00"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#fff"; +set c_comment_screened_link = "#00f"; +set c_comment_screened_link_visited = "#999"; +set c_comment_screened_link_hover = "#f00"; +set c_comment_screened_link_active = "#f00"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#999"; +set c_comment_screened_border = "#fff"; +set menu_disable_summary = true; +set css_style_overrides = "hr { display: block; } #menu { float: none; width: auto; } #content { margin-left: 0; } #container { margin: 0; padding: 0; text-align: left; width: 100%; }"; + +#NEWLAYER: tranquilityii/pinky +layerinfo "redist_uniq" = "tranquilityii/pinky"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Pinky Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#242E35"; +set c_header_background = "#242E35"; +set c_header_border = "#242E35"; +set c_page_title = "#fff"; +set c_page_background = "#242E35"; +set c_page_text = "#fff"; +set c_page_link = "#f0c"; +set c_page_link_visited = "#FF82E5"; +set c_page_link_hover = "#B30090"; +set c_page_link_active = "#B30090"; +set c_menu_border = "#B4A361"; +set c_menu_background = "#ECE9D8"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#F8F7F1"; +set c_entry_link = "#f0c"; +set c_entry_link_visited = "#FF82E5"; +set c_entry_link_hover = "#B30090"; +set c_entry_link_active = "#B30090"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#666"; +set c_entry_border = "000"; +set c_meta_background = "#F8F7F1"; +set c_meta_link = "#f0c"; +set c_meta_link_visited = "#FF82E5"; +set c_meta_link_hover = "#B30090"; +set c_meta_link_active = "#B30090"; +set c_meta_text_color = "#666"; +set c_footer_background = "#242E35"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#f0c"; +set c_comment_one_link_visited = "#FF82E5"; +set c_comment_one_link_hover = "#B30090"; +set c_comment_one_link_active = "#B30090"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#666"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#f0c"; +set c_comment_two_link_visited = "#FF82E5"; +set c_comment_two_link_hover = "#B30090"; +set c_comment_two_link_active = "#B30090"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#666"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#f0c"; +set c_comment_screened_link_visited = "#FF82E5"; +set c_comment_screened_link_hover = "#B30090"; +set c_comment_screened_link_active = "#B30090"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#666"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/fresh +layerinfo "redist_uniq" = "tranquilityii/fresh"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Fresh Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#7A97B2"; +set c_header_background = "#7A97B2"; +set c_header_border = "#7A97B2"; +set c_page_title = "#273849"; +set c_page_background = "#242E35"; +set c_page_text = "#fff"; +set c_page_link = "#036"; +set c_page_link_visited = "#036"; +set c_page_link_hover = "#069"; +set c_page_link_active = "#069"; +set c_menu_border = "#CFE0E6"; +set c_menu_background = "#CFE0E6"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#036"; +set c_entry_link_visited = "#036"; +set c_entry_link_hover = "#069"; +set c_entry_link_active = "#069"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#999"; +set c_entry_border = "000"; +set c_meta_background = "#fff"; +set c_meta_link = "#036"; +set c_meta_link_visited = "#036"; +set c_meta_link_hover = "#069"; +set c_meta_link_active = "#069"; +set c_meta_text_color = "#999"; +set c_footer_background = "#7A97B2"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#036"; +set c_comment_one_link_visited = "#036"; +set c_comment_one_link_hover = "#069"; +set c_comment_one_link_active = "#069"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#999"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#036"; +set c_comment_two_link_visited = "#036"; +set c_comment_two_link_hover = "#069"; +set c_comment_two_link_active = "#069"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#999"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#036"; +set c_comment_screened_link_visited = "#036"; +set c_comment_screened_link_hover = "#069"; +set c_comment_screened_link_active = "#069"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#999"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/auto +layerinfo "redist_uniq" = "tranquilityii/auto"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Auto Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#515151"; +set c_header_background = "#515151"; +set c_header_border = "#515151"; +set c_page_title = "#fff"; +set c_page_background = "#515151"; +set c_page_text = "#333"; +set c_page_link = "#00B4FF"; +set c_page_link_visited = "#00B4FF"; +set c_page_link_hover = "#006894"; +set c_page_link_active = "#006894"; +set c_menu_border = "#ccc"; +set c_menu_background = "#eee"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#00B4FF"; +set c_entry_link_visited = "#00B4FF"; +set c_entry_link_hover = "#006894"; +set c_entry_link_active = "#006894"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#999"; +set c_entry_border = "000"; +set c_meta_background = "#fff"; +set c_meta_link = "#036"; +set c_meta_link_visited = "#036"; +set c_meta_link_hover = "#069"; +set c_meta_link_active = "#069"; +set c_meta_text_color = "#999"; +set c_footer_background = "#515151"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#00B4FF"; +set c_comment_one_link_visited = "#00B4FF"; +set c_comment_one_link_hover = "#006894"; +set c_comment_one_link_active = "#006894"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#999"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#00B4FF"; +set c_comment_two_link_visited = "#00B4FF"; +set c_comment_two_link_hover = "#006894"; +set c_comment_two_link_active = "#006894"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#999"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#00B4FF"; +set c_comment_screened_link_visited = "#00B4FF"; +set c_comment_screened_link_hover = "#006894"; +set c_comment_screened_link_active = "#006894"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#999"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; diff --git a/ljcom/bin/upgrading/s2layers/unearthed/layout.s2 b/ljcom/bin/upgrading/s2layers/unearthed/layout.s2 new file mode 100644 index 0000000..8037095 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/unearthed/layout.s2 @@ -0,0 +1,1556 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Unearthed"; +layerinfo redist_uniq = "unearthed/layout"; + +layerinfo author_name = "Jesse Proulx"; +layerinfo author_email = "jproulx@livejournal.com"; +layerinfo des = "Based loosely on the design of the Unearthing T. rex website."; + +propgroup presentation { + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + + property int content_width + { + des = "Entire width of the main content, in percentages"; + values = "60|60%|70|70%|80|80%|90|90%"; + } + property string content_align { + des = "Content alignment"; + values = "right|Left|center|Center|left|Right"; + } + set content_width = 90; + set content_align = "center"; + + property use use_shared_pic; + property bool show_entry_userpic + { + des = "Show user picture icons with each of your entries?"; + } + set show_entry_userpic = true; + + property string dropshadow { + des = "Show drop shadows on content boxes"; + values = "none|No drop shadows|bottomright|Bottom-Right|bottomleft|Bottom-Left|topright|Top-Right|topleft|Top-Left"; + } + set dropshadow = "bottomright"; + + property string title_texture { + des = "Select a background texture for the page title:"; + values = "none|None|brushed_metal|Brushed Metal|burlap|Burlap|camouflage|Camouflage|canvas|Canvas|chalk|Chalk|cork|Cork|explosion|Explosion|fibers|Fibers|floral|Floral|ice|Ice|manila|Manila|marble|Marble|paper|Paper|ridge|Ridge|rough|Rough|stucco|Stucco|terracotta|Terracotta|type|Type|wavy|Wavy|weave|Weave|wood|Wood"; + } + set title_texture = "marble"; + property string free_text { + des = "Short introductory blurb or description"; + rows = 10; + cols = 40; + } + property string show_top_box { + des = "Show the introduction box (located at the top)?"; + values = "no|No|all|Yes, on all pages|recent|Yes, only on the Recent Entries page|friends|Yes, only on the Friends Entries page"; + } + set show_top_box = "recent"; + + property string box_sidebar_align { + des = "Show box sidebars on which side?"; + values = "left|Left|right|Right"; + } + set box_sidebar_align = "right"; +} + +propgroup colors = "Colors"; +propgroup colors { + property Color stronger_bgcolor { + des = "Header background color"; + } + set stronger_bgcolor = "#336699"; + property Color stronger_fgcolor { + des = "Text color on headers"; + } + property Color strong_bgcolor { + des = "Menu background color"; + } + set strong_bgcolor = "#6699cc"; + property Color strong_fgcolor { + des = "Text color on menus"; + } + property Color neutral_bgcolor { + des = "Title background color"; + } + set neutral_bgcolor = "#dddddd"; + property Color neutral_fgcolor { + des = "Text color on titles"; + } + property Color weak_bgcolor { + des = "Content background color"; + } + set weak_bgcolor = "#c1c1c1"; + property Color weak_fgcolor { + des = "Text color on content areas"; + } + property Color weaker_bgcolor { + des = "Page background color"; + } + set weaker_bgcolor = "#ffffff"; + property Color weaker_fgcolor { + des = "Default text color for the page"; + } + property Color link_color { + des = "Link color"; + noui = 1; + } + property Color vlink_color { + des = "Visited link color"; + noui = 1; + } + set link_color = "#0000ff"; + set vlink_color = "#ff00ff"; + property Color comment_bar_one_bgcolor + { + des = "Background color for comment bars"; + } + property Color comment_bar_one_fgcolor + { + des = "Text color on comment bars"; + } + property Color comment_bar_two_bgcolor + { + des = "Alternating background color for comment bars"; + } + property Color comment_bar_two_fgcolor + { + des = "Text color on alternating comment bars"; + } + property Color comment_bar_screened_bgcolor + { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor + { + des = "Text color on background bar for screened comments"; + } + set comment_bar_one_bgcolor = "#dddddd"; + set comment_bar_one_fgcolor = "#000000"; + set comment_bar_two_bgcolor = "#999999"; + set comment_bar_two_fgcolor = "#000000"; + set comment_bar_screened_bgcolor = "#f1f1f1"; + set comment_bar_screened_fgcolor = "#000000"; +} + +propgroup background = "Background"; +propgroup background +{ + property string background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Background's aren't recommended with this style due to non-transparent drop-down shadows."; + } + property string background_repeat + { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string background_position + { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + property string background_scrolling + { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set background_image = ""; + set background_repeat = "repeat"; + set background_position = "center"; + set background_scrolling = "scroll"; +} +propgroup fonts +{ + property string main_font + { + des = "Preferred Font"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set main_font = "Georgia"; + set main_font_fallback = "serif"; + + property string header_font + { + des = "Font for the top header box"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string header_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property string header_font_size + { + des = "Font size for the top header box"; + values = "2em|Small|3em|Medium|4em|Large"; + } + set header_font = "Trebuchet MS"; + set header_font_fallback = "sans-serif"; + set header_font_size = "3em"; + + property string content_font + { + des = "Font for the content boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set content_font = "Georgia"; + set content_font_fallback = "sans-serif"; +} +propgroup text +{ + property string text_linksheader { + des = "Title text for link lists"; + } + property string text_topboxheader { + des = "Title text for the top box"; + } + property string text_minicalheader { + des = "Title for the mini-calendar"; + } + property string text_metaentryheader { + des = "Title for entry sidebars"; + } + property string text_entrytitle { + des = "Navigation menu title for single entries"; + noui = 1; + } + property string text_prevyear { noui = 1; } + property string text_nextyear { noui = 1; } + property string text_prevmonth { noui = 1; } + property string text_nextmonth { noui = 1; } + property use text_view_userinfo; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_read_comments; + property use text_read_comments_friends; + property use text_post_comment; + property use text_post_comment_friends; + property use text_comment_reply; + property use text_reply_back; + property use text_nosubject; + property use text_noentries_day; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + set text_linksheader = "Links:"; + set text_permalink = "Permanent Link"; + set text_topboxheader = "About this Journal"; + set text_minicalheader = "Current Month"; + set text_metaentryheader = "About this Entry"; + set text_entrytitle = "Entry"; + set text_prevyear = "Previous Year"; + set text_nextyear = "Next Year"; + set text_prevmonth = "Previous Month"; + set text_nextmonth = "Next Month"; +} + +set tags_aware = true; + +################################################################################ +# +# Color scheme functions +# + +function color_ideal_foreground(Color bg) : Color +"Used to determine the best text color (out of white and black currently) given a single solid background color" +{ + var Color fg = $bg->inverse(); + var int saturation = $fg->saturation(); + $saturation = $saturation >= 127 ? 255 : 0; + $fg->saturation($saturation); + var int lightness = $fg->lightness(); + $lightness = $lightness >= 120 ? 255 : 0; + $fg->lightness($lightness); + return $fg; +} + +function color_offset(Color color) : Color +"Create an offset color for black or white text" +{ + var Color ret = $color->clone(); + if ($color.as_string == "#000000") { + $ret = "#333333"; + } else { + $ret = "#999999"; + } + return $ret; +} + +function color_link_colors(Color bg) : Color[] +"Determine sound link colors based on background color" +{ + ### Default link colors are blue and purple + var Color link = $*link_color->clone(); + var Color visited = $*vlink_color->clone(); + + ### Thing is, strong colors on strong colors looks silly + if ($bg->saturation() > 230) { + if ($bg->lightness() > 97 and $bg->lightness() < 161) { + var int lightness = $bg->lightness() > 50 ? 161 : 97; + $link->lightness($lightness); + $visited->lightness($lightness); + } + } + return [$bg, $link, $visited]; +} + +################################################################################ +# +# Property initialization +# + +function prop_init() { + if (isnull $*stronger_fgcolor) { $*stronger_fgcolor = color_ideal_foreground($*stronger_bgcolor); } + if (isnull $*strong_fgcolor) { $*strong_fgcolor = color_ideal_foreground($*strong_bgcolor); } + if (isnull $*neutral_fgcolor) { $*neutral_fgcolor = color_ideal_foreground($*neutral_bgcolor); } + if (isnull $*weak_fgcolor) { $*weak_fgcolor = color_ideal_foreground($*weak_bgcolor); } + if (isnull $*weaker_fgcolor) { $*weaker_fgcolor = color_ideal_foreground($*weaker_bgcolor); } + + ### Hack! + if ($*title_texture == "type") { $*title_texture = palimg_tint("textures/$*title_texture" + ".png", $*stronger_fgcolor, $*stronger_bgcolor); } + elseif ($*title_texture != "none") { $*title_texture = palimg_tint("textures/$*title_texture" + ".png", $*stronger_bgcolor); } +} + +################################################################################ +# +# Drop shadow functions +# + +function dropshadow_open(string{} opts) : string { + var string ret = ""; + var string tint = $opts{"bgcolor"}->substr(1, 6) + $opts{"fgcolor"}->substr(1, 6); + var string width = $opts{"width"} ? $opts{"width"} : "100%"; + var string height = $opts{"height"} ? $opts{"height"} : ""; + var string style = $opts{"style"}; + + if ($*dropshadow == "none") { return ""; } + + $ret = $ret + """"""; + + if ($*dropshadow == "topright" or $*dropshadow == "topleft") { + $ret = $ret + "" + + "" + + ""; + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomleft" or $*dropshadow == "topleft") { + if ($*dropshadow == "bottomleft") { + $ret = $ret + ""; + } + if ($*dropshadow == "topleft") { + $ret = $ret + ""; + } + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomright" or $*dropshadow == "topright") { + if ($*dropshadow == "bottomright") { + $ret = $ret + ""; + } + if ($*dropshadow == "topright") { + $ret = $ret + ""; + } + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomright" or $*dropshadow == "bottomleft") { + $ret = $ret + "" + + "" + + ""; + } + + $ret = $ret + "
    " + + "" + + ""; + return $ret; +} + +function dropshadow_close(string{} opts) : string { + var string ret = ""; + var string tint = $opts{"bgcolor"}->substr(1, 6) + $opts{"fgcolor"}->substr(1, 6); + var string width = $opts{"width"} ? $opts{"width"} : "100%"; + var string height = $opts{"height"} ? $opts{"height"} : "100%"; + var string style = $opts{"style"}; + + if ($*dropshadow == "none") { return ""; } + + $ret = $ret + "" + + "" + + "
    "; + return $ret; +} + +function dropshadow (string content, string{} opts) : string +"Given a string, prints a table around it that emulates a drop-shadow" +{ + var string ret = ""; + + if ($*dropshadow == "none") { return """
    $content
    """; } + + $ret = $ret + dropshadow_open($opts); + $ret = $ret + $content; + $ret = $ret + dropshadow_close($opts); + return $ret; +} + +function format_box(string id, string title, string contents, string sidebar_title, string sidebar) : string { + var string ret = """"""; + $ret = $ret + """"""; + if ($*box_sidebar_align == "left") { + $ret = $ret + """"""; + } + $ret = $ret + """"""; + if ($*box_sidebar_align == "right") { + $ret = $ret + """"""; + } + $ret = $ret + """
    $title
    """; + $ret = $ret + """"""; + $ret = $ret + """"""; + $ret = $ret + """
    $sidebar_title
    $sidebar
    $contents"""; + $ret = $ret + """"""; + $ret = $ret + """"""; + $ret = $ret + """
    $sidebar_title
    $sidebar
    """; + return $ret; +} + +################################################################################ +# +# Stylesheet +# + +function appended_to_stylesheet() { + +} + +function css_fontspec(string base, string fallback) + "Prints a CSS font-family specification based on the base and fallback given" +{ + if ($base != "" or $fallback != "none") { + "font-family: "; + if ($base != "") { + "\"$base\""; + if ($fallback != "none") { + ", "; + } + } + if ($fallback != "none") { + print $fallback; + } + ";"; + } +} + +function print_stylesheet () { + + println +""" +body { + font-size: 1em; + margin: 0; + padding: 0; + background-color: $*weaker_bgcolor; + color: $*weaker_fgcolor; +"""; + print " "; css_fontspec($*main_font, $*main_font_fallback); println ""; + if(clean_url($*background_image) != "") { + println +""" + background-image: url('$*background_image'); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_scrolling; +"""; + } + println +""" +} +#Content { + background-color: $*weaker_bgcolor; + width: $*content_width%; + padding: 0; +"""; + var int margin = 100 - $*content_width; + if ($margin > 0) { + if ($*content_align == "center") { + $margin = $margin / 2; + println """ margin-right: $margin%;"""; + println """ margin-left: $margin%"""; + } else { + println """ margin-$*content_align: $margin%;"""; + } + } + println +""" +} +#Title { + color: $*stronger_fgcolor; + background-color: $*stronger_bgcolor; +"""; + if ($*title_texture != "none") { println """ background-image: url("$*title_texture");"""; } +println +""" +} +"""; + + println +""" +#GlobalTitle { + width: 80%; + margin-left: 20%; + font-size: $*header_font_size; + margin-bottom: 0; + margin-top: 0; +} +#GlobalSubtitle { + width: 75%; + margin-left: 25%; + font-size: .80em; + margin-top: 2px; + margin-bottom: 0; + font-style: italic; +} +.overflow, .BoxContent { + overflow: auto; +} +#Header { +"""; + print " "; css_fontspec($*header_font, $*header_font_fallback); println ""; +println +""" + width: 100%; + background-color: $*strong_bgcolor; + color: $*strong_fgcolor; + margin-bottom: 10px; +} +.Box { +"""; + print " "; css_fontspec($*content_font, $*content_font_fallback); println ""; +println +""" + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; + width: 100%; +} +.BoxContents { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; + width: 100%; +} +.DropShadow { + margin-bottom: 10px +} +.BoxSideBar { + width: 175px; + height: 100%; + background-color: $*strong_bgcolor; + color: $*strong_fgcolor; +} +"""; + var Color[] sidebar_links = color_link_colors($*strong_bgcolor); +println +""" +.BoxSideBar table { + width: 175px; + height: 100%; +} +.BoxSidebar table a { + background-color: $*strong_bgcolor; + color: $sidebar_links[1]; +} +.BoxSidebar table a:visited { + background-color: $*strong_bgcolor; + color: $sidebar_links[2]; +} +.BoxSideBar table th { + background-color: $*stronger_bgcolor; + color: $*stronger_fgcolor; +} +.BoxSideBarContents { + height: 100%; + padding: 5px; +} +.BoxTitle { + text-align: left; + background-color: $*neutral_bgcolor; + color: $*neutral_fgcolor; + padding: 5px; +} +.BoxContents { + padding: 5px; +} +"""; +var string headernav_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$*strong_bgcolor); +println +""" +.HeaderNavMenu { + background: $*strong_bgcolor url("$headernav_bg") top center repeat-x; + width: 100%; + background-color: $*strong_bgcolor; + margin: 0; + padding-left: 0; + padding-top: 5px; +} +.HeaderNavSubMenu { + width: 100%; + background-color: $*neutral_bgcolor; + margin: 0; + padding-left: 20px; +} +.HeaderNavMenu li, .HeaderNavSubMenu li { + margin-right: 10px; + display: inline; + padding-left: 5px; + padding-right: 5px; + padding-top: 5px; +} +"""; + var string headernavactive_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$*neutral_bgcolor); + var Color inactive = $*strong_bgcolor->lighter(); + var string headernavinactive_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$inactive); +println +""" +.HeaderNavMenu li.inactive { + background: $inactive url("$headernavinactive_bg") top repeat-x; + margin-right: 25px; + display: inline; +} +.HeaderNavMenu li#active { + background: $*neutral_bgcolor url("$headernavactive_bg") top repeat-x; + color: $*neutral_fgcolor; + font-weight: bold; + margin-right: 25px; + display: inline; +} +.HeaderNavMenu li#active a { + color: $*neutral_fgcolor; +} +.HeaderNavMenuFirst { + margin-left: 50px; + padding: 0; + visibility: hidden; +} +.HeaderNavMenu li { + color: $*strong_fgcolor; +} +.HeaderNavMenu li a { + color: $*strong_fgcolor; + text-decoration: none; +} +.HeaderNavSubMenu li { + color: $*neutral_fgcolor; +} +.HeaderNavSubMenu li a { + color: $*neutral_fgcolor; + text-decoration: none; +} +#FooterNavMenu { + text-align: center; + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +#FooterNavMenu a { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +#FooterNavMenu a:visited { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +.CommentBarOne, .CommentBarTwo, .CommentBarScreened +{ + width: 100%; margin-top: 1em; height: 100%; +} +.CommentBarOne +{ + background-color: $*comment_bar_one_bgcolor; + color: $*comment_bar_one_fgcolor; +} +.CommentBarTwo +{ + background-color: $*comment_bar_two_bgcolor; + color: $*comment_bar_two_fgcolor; +} +.CommentBarScreened +{ + background-color: $*comment_bar_screened_bgcolor; + color: $*comment_bar_screened_fgcolor; +} +"""; +var Color highlightday = $*strong_bgcolor->lighter(); +println +""" +#MiniCal { + width: 175px; height: 3em; +} +.MiniCalDayPosts, .MiniCalDay +{ + text-align: center; + font-size: .8em; + border: 1px inset #000; + width: 14%; +} +.MiniCalDayPosts { + background-color: $highlightday; +} +.MiniCalDayPosts a +{ + color: $*strong_fgcolor; + display: block; + text-decoration: none; + width: 100%; +} +"""; + appended_to_stylesheet(); +} + +################################################################################ +# +# Page +# + +function Page::lay_add_header_nav() : string +{ + return ""; +} + +function Page::lay_sub_menu() : string[] +{ + var string[] ret = []; + + return $ret; +} + +function Page::lay_footer_menu() : string[] +{ + var string[] ret = []; + + return $ret; +} + +function Page::lay_entry_sidebar(Entry e) : string +{ + var string ret; + if ($e.poster.username != $e.journal.username) { + if (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + $ret = $ret + $e.poster->as_string() + ":
    "; + } elseif (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + return $ret; +} + +function Page::lay_show_entry_text : bool +{ + return true; +} + +function Page::lay_entry_sidebar_nav() : string +{ + return ""; +} + +function linklist() : string { + var string return = ""; + var Page p = get_page(); + if (size $p.linklist <= 0) { + return ""; + } + var bool section_open = false; + $return = $return + """$*text_linksheader
    """; + foreach var UserLink l ($p.linklist) { + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + $return = $return + """
    """; + } + $return = $return + """$l.title """; + $section_open = true; + } else { + $return = $return + """$l.title """; + } + } + } + return $return; +} + +function mini_calendar() : string +{ + var string calendar = ""; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """"""; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + if ($d.num_entries) { + $calendar = $calendar + """"""; + } else { + $calendar = $calendar + """"""; + } + } + $calendar = $calendar + "\n"; + } + $calendar = $calendar + "
     $d.day$d.day
    "; + } + if ($calendar == "") { + return "No entries to show"; + } + return $calendar; +} + +function top_box() : string { + var string return = ""; + var string contents = ""; + + if ($*free_text) { $contents = $contents + $*free_text + "
    "; } + $contents = $contents + linklist(); + $contents = format_box("TopBox", $*text_topboxheader, $contents, $*text_minicalheader, mini_calendar()); + + var Color offset = color_offset($*weaker_fgcolor); + $return = dropshadow($contents, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + return $return; +} + +function Page::lay_print_top_box() +{ + if ($*show_top_box != "all") { + return; + } + print top_box(); +} + +function Page::print_entry(Entry e) +{ + var string id = "entry_$e.itemid"; + var string title = "$e.security_icon" + ($e.subject != "" ? " $e.subject" : " $*text_nosubject"); + var string contents = ""; + var string sidebar = ""; + + var string date = $e.time->date_format("med"); + var string time = $e.time->time_format("short"); + $title = """$date @ $time """ + $title; + + if (size $e.metadata) { + $contents = $contents + """
    """; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $contents = $contents + """$text: $val
    """; + } + $contents = $contents + "
    "; + } + if ($e.tags) { + var int tcount = 0; + $contents = $contents + "
    Tags: "; + foreach var Tag t ($e.tags) { + $contents = $contents + """"""; + $tcount++; + if ($tcount != size $e.tags) { $contents = $contents + ", "; } + } + $contents = $contents + "
    "; + } + + if (size $e.metadata or size $e.tags) { $contents = $contents + "
    "; } + $contents = $contents + ($this->lay_show_entry_text() ? $e.text : ""); + + $sidebar = $sidebar + $this->lay_entry_sidebar($e); + + # Comments + $sidebar = $sidebar + """
    """; + if ($e.comments.enabled) { + if (($e.comments.count > 0 or $e.comments.screened) and $.view != "entry") { + $sidebar = $sidebar + """""" + + get_plural_phrase($e.comments.count, $.view == "friends" ? + "text_read_comments_friends" : "text_read_comments") + + ""; + $sidebar = $sidebar + "
    "; + } + if ($.view != "reply") { + $sidebar = $sidebar + """""" + + ($.view == "friends" ? $*text_post_comment_friends : $*text_post_comment) + "
    "; + } + } + $sidebar = $sidebar + """$*text_permalink
    """; + if ($.view == "entry" or $.view == "reply") { + $sidebar = $sidebar + "
    "; + var Link l = new Link; + foreach var string ls ($e.link_keyseq) { + $l = $e->get_link($ls); + if (defined $l) { + $sidebar = $sidebar + """$l.caption
    """; + } + } + } + $sidebar = $sidebar + $this->lay_entry_sidebar_nav(); + $sidebar = $sidebar + "
    "; + + var string entry = format_box($id, $title, $contents, $*text_metaentryheader, $sidebar); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($entry, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); +} + +function Page::print() { + var string title = $this->title(); + + println """"""; + println """"""; + println """$title"""; + println """"""; + + $this->print_head(); + + println """"""; + + println """
    """; + + $this->lay_print_top_box(); + + $this->print_body(); + + var string footer = ""; + foreach var string v ($.views_order) { + $footer = $footer + """""" + lang_viewname($v) + " | "; + } + var string[] footermenu = $this->lay_footer_menu(); + if (size $footermenu > 0) { + foreach var string menuitem ($footermenu) { + $footer = $footer + """$menuitem | """; + } + } + $footer = $footer + """Top"""; + + println dropshadow("""
    $footer
    """, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "style" => "margin-left: 10%; margin-right: 10%; ", + "width" => "80%", + }); + + println """
    """; +} + +################################################################################ +# +# RecentPage +# + +function RecentPage::lay_print_top_box() +{ + if ($*show_top_box != "recent" and $*show_top_box != "all") { + return; + } + print top_box(); +} + +function RecentPage::lay_sub_menu() : string[] { + var string[] ret = []; var int i = 0; + if (viewer_is_owner()) { + $ret[$i] = """
  • Update Journal
  • """; $i++; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function RecentPage::lay_footer_menu() : string[] { + var string[] ret = []; var int i = 0; + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +################################################################################ +# +# FriendsPage +# + +function FriendsPage::lay_print_top_box() +{ + if ($*show_top_box == "friends" or $*show_top_box == "all") { + print top_box(); + } +} + +function FriendsPage::lay_entry_sidebar(Entry e) : string { + var string ret; + if (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + if ($e.poster.username != $e.journal.username) { + $ret = $ret + $e.poster->as_string() + ", posting in "; + } + $ret = $ret + $e.journal->as_string() + "
    "; + return $ret; +} + +################################################################################ +# +# EntryPage +# + +function EntryPage::lay_show_entry_text : bool { + return not $.viewing_thread; +} + +function EntryPage::lay_add_header_nav() : string +{ + var string ret = ""; + $ret = """
  • $*text_entrytitle
  • """; + return $ret; +} + +function EntryPage::lay_entry_sidebar_nav() : string +{ + var string return; + if ($.comment_pages.all_subitems_displayed) { return ""; } + $return = "
    "; + foreach var int i (1 .. $.comment_pages.total) { + if ($i == $.comment_pages.current) { + $return = $return + "[Page $i]
    "; + } else { + var string url_of = $.comment_pages->url_of($i); + $return = $return + """[Page $i]
    """; + } + } + return $return; +} + +function EntryPage::lay_sub_menu() : string[] { + var string[] return; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $return[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $return[$i] = """$next.caption"""; + } + } + return $return; +} + +function EntryPage::lay_footer_menu() : string[] { + var string[] return; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $return[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $return[$i] = """$next.caption"""; + } + } + return $return; +} + +function EntryPage::print_body +{ + set_handler("unscreen_comment_#", [ + [ "set_class", "cmtbar#", "CommentBarOne", ], + ]); + set_handler("screen_comment_#", [ + [ "set_class", "cmtbar#", "CommentBarScreened", ], + ]); + + var Entry e = $.entry; + $this->print_entry($e); + + if ($.entry.comments.enabled and ($.entry.comments.count > 0 or $.entry.comments.screened)) + { + var string{} opts = { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "width" => "95%", + }; + print dropshadow_open($opts); + print """
    """; + if ($.comment_pages.total_subitems > 0) { + $this->print_multiform_start(); + $this->print_comments($.comments); + print """
    """; $this->print_multiform_actionline(); print "
    "; + $this->print_multiform_end(); + } + print "
    "; + print dropshadow_close($opts); + } elseif (not $.entry.comments.enabled) { + print dropshadow("""
    $*text_reply_nocomments
    """, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "width" => "95%", + }); + } +} + +function EntryPage::print_comment(Comment c) +{ + var string class = ""; + if ($c.screened) { + $class = "CommentBarScreened"; + } elseif ($c.depth % 2) { + $class = "CommentBarOne"; + } else { + $class = "CommentBarTwo"; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + println """
    """; + println """"""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + println """"""; + } + + println """
    [User Picture Icon]"""; + + println """"; + + println """"; + + println """"; + + println """"""; + + println "
    """; + println ""; + println """"""; + println """"; + if ($c.metadata{"poster_ip"}) { println """"; } + println "
    From:$poster
    Date:"""; + println $c.time->date_format("long") + " - " + $c.time->time_format() + "
    $*text_comment_ipaddr(""" + $c.metadata{"poster_ip"} + ")
    """; + if ($this.multiform_on) { + println """ """; + $c->print_multiform_check(); + } + $c->print_linkbar(); + println "
    """; + println (defined $c.subject_icon or $c.subject != "") ? """

    $c.subject_icon $c.subject

    """ : ""; + println "
    ($*text_permalink)
    "; + println """
    $c.text
    """; + println """
    """; + if ($c.frozen) { + println """($*text_comment_frozen) """; + } else { + "("; $c->print_reply_link({"linktext" => $*text_comment_reply}); ")"; + } + if ($c.parent_url != "") { println """($*text_comment_parent) """; } + if ($c.thread_url != "") { println """($*text_comment_thread) """; } + $c->print_reply_container(); + println "
    "; +} + +################################################################################ +# +# ReplyPage +# +function ReplyPage::lay_add_header_nav() : string +{ + var string ret = ""; + $ret = """
  • $*text_entrytitle
  • """; + return $ret; +} + +function ReplyPage::lay_show_entry_text : bool { + return $.entry.permalink_url == $.replyto.permalink_url; +} + +function ReplyPage::print_body +{ + + $this->print_entry($.entry); + + if (not $.entry.comments.enabled) { + print "

    $*text_reply_nocomments_header/h2>

    $*text_reply_nocomments

    "; + return; + } + var Color offset = color_offset($*weaker_fgcolor); + if ($.entry.permalink_url != $.replyto.permalink_url) { + var string sidebar; + if (defined $.replyto.userpic) { + var int margin = (175 - $.replyto.userpic.width) / 2; + $sidebar = $sidebar + dropshadow($.replyto.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($.replyto.userpic.width) + "px", + "height" => string($.replyto.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + $sidebar = $sidebar + lang_user_wrote($.replyto.poster); + $sidebar = $sidebar + "
    "+lang_at_datetime($.replyto.time); + + var string box = format_box("", $.replyto.subject != "" ? $.replyto.subject : $*text_nosubject, $.replyto.text, "", $sidebar); + print dropshadow($box, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + } + print dropshadow_open({ + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + print """
    """; + $.form->print(); + print """
    """; + print dropshadow_close({ + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + }); +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" replied to "; + } + else { + return "An anonymous user wrote"; + } +} + +################################################################################ +# +# YearPage +# + +function YearPage::lay_footer_menu() : string[] { + var string[] ret; var int i = 0; var int menu = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + if (defined $.years[$i - 1]) { + var YearYear prev = $.years[$i - 1]; + $ret[$menu] = """$*text_prevyear"""; $menu++; + } + if (defined $.years[$i + 1]) { + var YearYear next = $.years[$i + 1]; + $ret[$menu] = """$*text_nextyear"""; $menu++; + } + } + $i++; + } + return $ret; +} + +function YearPage::lay_sub_menu() : string[] { + var string[] ret; + var int i = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + $ret[$i] = """$y.year\n"""; + } else { + $ret[$i] = """$y.year\n"""; + } + $i++; + } + return $ret; +} + +function YearPage::print_body { + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + var string month; + $month = $month + """"""; + foreach var int d (weekdays()) { + $month = $month + "\n"; + } + $month = $month + "\n"; + foreach var YearWeek w ($m.weeks) { + $month = $month + """\n"""; + if ($w.pre_empty > 0) { + $month = $month + """\n"""; + } + foreach var YearDay d ($w.days) { + $month = $month + """\n"""; + } + if ($w.post_empty > 0) { + $month = $month + """\n"""; + } + $month = $month + ""; + } + $month = $month + "
    " + $*lang_dayname_short[$d] + "
     \n"""; + $month = $month + """
    $d.day
    \n"""; + if ($d.num_entries > 0) { + $month = $month + """\n"""; + } + $month = $month + """
     
    "; + $month = format_box("", $m->month_format(), $month, "Links", """$*text_view_month"""); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($month, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); +} + +################################################################################ +# +# MonthPage +# + +function MonthPage::lay_sub_menu () : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """$*text_prevmonth"""; $i++; } + if ($.next_url != "") { $ret[$i] = """$*text_nextmonth"""; $i++; } + return $ret; +} + +function MonthPage::lay_footer_menu () : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """$*text_prevmonth"""; $i++; } + if ($.next_url != "") { $ret[$i] = """$*text_nextmonth"""; $i++; } + return $ret; +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + if (size $.months > 1) { + "\n"; + } + "
    \n"; + + var string days = "
    "; var string links = "
      "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + $days = $days + """
      """ + lang_ordinal($d.day) + """
      """; + $links = $links + """
    • """ + $d.date->date_format("short") + """
    • """; + var string subjects = ""; + foreach var Entry e ($d.entries) { + $subjects = $subjects + $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $subjects = $subjects + $e.poster.username + " "; + } + $subjects = $subjects + "$e.security_icon"; + if ($e.subject != "") { + $subjects = $subjects + " $e.subject"; + } else { + $subjects = $subjects + " ($*text_nosubject)"; + } + if ($e.comments.count > 0) { + $subjects = $subjects + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + $subjects = $subjects + " $*text_month_screened_comments"; + } + $subjects = $subjects + "
      "; + } + $days = $days + """
      $subjects
      """; + } + } + $days = $days + """
    """; + $links = $links + """"""; + var string month = format_box("",$.date->date_format($*lang_fmt_month_long),$days,"Links",$links); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($month, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "100%", + }); +} + +################################################################################ +# +# DayPage +# + +function DayPage::lay_sub_menu() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + +function DayPage::lay_footer_menu() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + +function DayPage::print_body() { + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } else { + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow("

    $*text_noentries_day

    ", { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + } +} diff --git a/ljcom/bin/upgrading/s2layers/unearthed/themes.s2 b/ljcom/bin/upgrading/s2layers/unearthed/themes.s2 new file mode 100644 index 0000000..ad0b2cb --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/unearthed/themes.s2 @@ -0,0 +1,118 @@ +#NEWLAYER: unearthed/rampant +layerinfo "type" = "theme"; +layerinfo "name" = "Rampant Tenderfoot"; +layerinfo redist_uniq = "unearthed/rampant"; + +set stronger_bgcolor = "#ff3300"; +set strong_bgcolor = "#ff8000"; +set neutral_bgcolor = "#ffb200"; +set weak_bgcolor = "#ffb380"; +set weaker_bgcolor = "#ffcc80"; + +#NEWLAYER: unearthed/acrid +layerinfo "type" = "theme"; +layerinfo "name" = "Acrid Slide"; +layerinfo redist_uniq = "unearthed/acrid"; + +set title_texture = "rough"; +set stronger_bgcolor = "#33ff00"; +set strong_bgcolor = "#0066b2"; +set neutral_bgcolor = "#00B266"; +set weak_bgcolor = "#99ff80"; +set weaker_bgcolor = "#ccffbf"; + +#NEWLAYER: unearthed/leisure +layerinfo "type" = "theme"; +layerinfo "name" = "Leisure Renewal"; +layerinfo redist_uniq = "unearthed/leisure"; + +set title_texture = "camouflage"; +set stronger_bgcolor = "#285577"; +set strong_bgcolor = "#3c3773"; +set neutral_bgcolor = "#287755"; +set weak_bgcolor = "#c0c0ec"; +set weaker_bgcolor = "#b1ecd3"; + +#NEWLAYER: unearthed/craftis +layerinfo "type" = "theme"; +layerinfo "name" = "Craftis"; +layerinfo redist_uniq = "unearthed/craftis"; + +set title_texture = "camouflage"; +set stronger_bgcolor = "#dd0000"; +set strong_bgcolor = "#aa4f39"; +set neutral_bgcolor = "#d2d2d2"; +set weak_bgcolor = "#fcffcf"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/unveiled +layerinfo "type" = "theme"; +layerinfo "name" = "Unveiled Metal"; +layerinfo redist_uniq = "unearthed/unveiled"; + +set title_texture = "brushed_metal"; +set stronger_bgcolor = "#666666"; +set strong_bgcolor = "#999999"; +set neutral_bgcolor = "#333333"; +set weak_bgcolor = "#cccccc"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/wait +layerinfo "type" = "theme"; +layerinfo "name" = "Wait Screw"; +layerinfo redist_uniq = "unearthed/wait"; + +set title_texture = "chalk"; +set stronger_bgcolor = "#009999"; +set strong_bgcolor = "#ff6600"; +set neutral_bgcolor = "#66cccc"; +set weak_bgcolor = "#ffb380"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/drinkdna +layerinfo "type" = "theme"; +layerinfo "name" = "Drinking DNA"; +layerinfo redist_uniq = "unearthed/drinkdna"; + +set title_texture = "cork"; +set stronger_bgcolor = "#4C9978"; +set strong_bgcolor = "#468C8C"; +set neutral_bgcolor = "#53A653"; +set weak_bgcolor = "#ACE6E6"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/gainful +layerinfo "type" = "theme"; +layerinfo "name" = "Gainful Magic"; +layerinfo redist_uniq = "unearthed/gainful"; + +set title_texture = "fibers"; +set stronger_bgcolor = "#DFDFA7"; +set strong_bgcolor = "#FFFF80"; +set neutral_bgcolor = "#AAAA39"; +set weak_bgcolor = "#eeeeee"; +set weaker_bgcolor = "#FFFFBF"; + +#NEWLAYER: unearthed/inaccurate +layerinfo "type" = "theme"; +layerinfo "name" = "Inaccurate Lingo"; +layerinfo redist_uniq = "unearthed/inaccurate"; + +set title_texture = "stucco"; +set stronger_bgcolor = "#FF8080"; +set strong_bgcolor = "#FF9980"; +set neutral_bgcolor = "#E572A5"; +set weak_bgcolor = "#F2B6D0"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/current +layerinfo "type" = "theme"; +layerinfo "name" = "Current Protector"; +layerinfo redist_uniq = "unearthed/current"; + +set title_texture = "type"; +set stronger_bgcolor = "#B5D9D9"; +set strong_bgcolor = "#285577"; +set neutral_bgcolor = "#226666"; +set weak_bgcolor = "#7DA0BB"; +set weaker_bgcolor = "#B5D9D9"; diff --git a/ljcom/bin/upgrading/sv.dat b/ljcom/bin/upgrading/sv.dat new file mode 100644 index 0000000..d710251 --- /dev/null +++ b/ljcom/bin/upgrading/sv.dat @@ -0,0 +1,3248 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Ändra status + +/accountstatus.bml.error.db=Det uppstod ett databasfel med din + +/accountstatus.bml.error.invalid=Ogiltig statustyp. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Kan inte ändra journalstatus från suspenderad. + +/accountstatus.bml.header.success=Avklarat + +/accountstatus.bml.journalstatus.about=Vill du radera eller återställa din journal, denna sida är var du gör det. När du väl raderat din journal har du 30 dagar att återställa den, ifall att du ångrar dig. Efter 30 dagar blir journalen permanent raderad och det kommer inte att bli möjligt att återfå den. + +/accountstatus.bml.journalstatus.head=Journal aktiveringsstatus + +/accountstatus.bml.journalstatus.select.activated=Aktiverad + +/accountstatus.bml.journalstatus.select.deleted=Raderad + +/accountstatus.bml.journalstatus.select.suspended=Avstängd + +/accountstatus.bml.message.nochange=Din journalstatus förblev [[statusvis]], + +/accountstatus.bml.message.success=Din journalstatus har ändrats till [[statusvis]], + +/accountstatus.bml.title=Kontostatus + +/allpics.bml.current=Nuvarande bilder + +/allpics.bml.default=Standard + +/allpics.bml.edit2=Du är möjligen intresserad i att redigera dina bildnyckelord eller ladda upp en ny bild. + +/allpics.bml.error.noparam=Du måste specificera en användar-parameter. + +/allpics.bml.keywords=Nyckelord. + +/allpics.bml.nopics.text.other=Den här användaren har ej laddat upp några användarbilder. + +/allpics.bml.nopics.text2=Du har inga bilder uppladdade. Att hämta en, gå hit. + +/allpics.bml.nopics.title=Inga bilder. + +/allpics.bml.pics=Här är användar-bilder för [[user]]. + +/allpics.bml.title=Användar-bilder. + +/approve.bml.comm.success=Avklarat + +/approve.bml.error.internerr.invalidaction=Datorfel: ogiltig behandling + +/approve.bml.error.invalidargument=Ogiltig argument given + +/approve.bml.error.unknownactiontype=Odefinierad behandlingstyp + +/approve.bml.shared.success=Avklarat + +/approve.bml.shared.text<< +Du fick postningstillgång till [[shared]]. +Klicka här att tillägga delade journalen till din vänlista. +. + +/approve.bml.title=Godkänna behandling + +/birthdays.bml.description=Nedan är födelsedagarna av alla som du har på vänlistan. + +/birthdays.bml.title=Födelsedagar + +/changepassword.bml.btn.proceed=Fortsätta + +/changepassword.bml.changepassword.header=Ändra lösenordet + +/changepassword.bml.changepassword.instructions=Fyll in formuläret nedan att ändra ditt lösenord. För hjälp med att välja ett bra lösenord, se denna länk. + +/changepassword.bml.email.body<< +Ditt lösenord har ändrats hos [[sitename]]. + +Att återfå det i framtiden, gå till: + + [[siteroot]]/lostinfo.bml + +Tack, +[[sitename]] Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Lösenordsförändring + +/changepassword.bml.error.badcheck=Ogiltigt nytt lösenord: [[error]] + +/changepassword.bml.error.badnewpassword=Dina nya lösenord är inte lika. Du gjorde möjligen ett stavfel i ett av dem. Var god skriva om och bekräfta ditt lösenord. + +/changepassword.bml.error.badoldpassword=Ditt gamla lösenord är fel. + +/changepassword.bml.error.blankpassword=Ditt nya lösenord får inte vara blankt. + +/changepassword.bml.error.changetestaccount=Kan inte ändra testkontots lösenord. + +/changepassword.bml.error.characterlimit=Lösenord kan inte innehålla fler än 30 tecken. + +/changepassword.bml.error.invaliduser=Ogiltig användare [[user]]. Denna användare finns inte. Är du säker att du stavade rätt? + +/changepassword.bml.error.mustenterusername=Du måste ange ditt användarnamn. + +/changepassword.bml.error.nonascii=Lösenord är begränsade till ASCII-tecknen. Var god välja ett lösenord som inte har icke-ASCII tecken i det. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Du kan inte ändra ditt lösenord om ditt nuvarande epostadress inte har bekräftats. + +/changepassword.bml.newpassword=Nytt lösenord: + +/changepassword.bml.newpasswordagain=Nytt lösenord (igen): + +/changepassword.bml.oldpassword=Gammalt lösenord: + +/changepassword.bml.proceed.instructions=Tryck knappen nedan att spara lösenordsförändringen. Du kommer också att få epostmeddelande som noterar lösenordsförändringen. + +/changepassword.bml.relogin=Du har också blivit utloggad från alla dina existerande sessioner. Du borde logga in igen innan du fortsätter. + +/changepassword.bml.success.text=Ditt lösenord har ändrats och epost har skickats till dig med ett påminnelsemeddelande. + +/changepassword.bml.title=Ändra lösenord + +/community/index.bml.title=Intressegrupp-center + +/community/join.bml.button.join=Gå med i intressegruppen + +/community/join.bml.label.addtofriends=Lägg till "[[maintainer]]" till vänlistan.
    + +/community/join.bml.label.allowposting=Denna intressegrupp tillåter inlägg från alla medlemmar, så du har nu behörighet att posta i det. Om du redan har en LiveJournal-klient öppen på din dator måste du logga ut och in igen för att denna journal ska dyka upp i listan av journaler som du kan posta i. + +/community/join.bml.label.auth=Även om du nu är listad som + +/community/join.bml.label.banned=Underhållsansvarige för denna intressegrupp har förbjudit dig från att gå med. + +/community/join.bml.label.closed=Denna intressegrupp är en sluten sådan. Om du intresserad av att gå med i den, vänligen kontakta dess underhållsanvarige. Nedan finns en lista över underhållsansvariga för denna intressegrupp. [[admins]] + +/community/join.bml.label.commlogged=Du är inloggad som ett delat/intressegrupp konto, inte ditt personliga konto. + +/community/join.bml.label.errorcomminfo=Specifierade intressegrupp-informationen är inte giltig. + +/community/join.bml.label.expls=Klicka på knappen nedan för att bli medlem i "[[maintainer]]" intressegruppen. Avmarkera rutan nedan om gå med i intressegruppen utan att se intressegrupp-inlägg på din vänsida. + +/community/join.bml.label.loginfirst=För att bli medlem i en intressegrupp måste du först logga in. + +/community/join.bml.label.membernow=Du är nu medlem i [[commname]] intressegruppen + +/community/join.bml.label.sure=Är du säker? + +/community/join.bml.success=Avklarat + +/community/join.bml.title=Bli medlem i intressegruppen + +/community/leave.bml.button.leave=Lämna intressegruppen + +/community/leave.bml.label.buttontoleave=Klicka på knappen nedan för att lämna "[[commname]]" intressegruppen. + +/community/leave.bml.label.infoerror=Specifierade intressegruppinformationen är inte giltig. + +/community/leave.bml.label.logoutfirst=För att lämna en intressegrupp måste du först logga in. + +/community/leave.bml.label.removed=Du är nu borttagen från [[commname]] intressegruppen + +/community/leave.bml.label.removefromfriends=Ta också bort "[[user]]" från vänlistan. + +/community/leave.bml.success=Avklarat + +/community/leave.bml.sure=Är du säker? + +/community/leave.bml.title=Lämna intressegruppen + +/community/manage.bml.commlist.actions=Aktivitet + +/community/manage.bml.commlist.actmembers=[Medlemmar] + +/community/manage.bml.commlist.actmembers2=Medlemmar + +/community/manage.bml.commlist.actsettings=[Inställningar] + +/community/manage.bml.commlist.actsettings2=Inställningar + +/community/manage.bml.commlist.header=Dina communities + +/community/manage.bml.commlist.none=Du är inte underhållsansvarig i någon intressegrupp. + +/community/manage.bml.commlist.text=Här visas communities som du är underhållsansvarig i: + +/community/manage.bml.commlist.title=Titel + +/community/manage.bml.commlist.username=Användarnamn + +/community/manage.bml.create.header=Skapa en intressegrupp + +/community/manage.bml.create.text=Du kan också skapa en ny intressegrupp. + +/community/manage.bml.title=Intressegrupp underhåll + +/community/members.bml.error.alreadyadded=[[user]] var inte tillagd för att den har redan tillgång till intressegruppen. + +/community/members.bml.error.alreadysent=[[user] kunde inte läggas till för att de redan skickats konfirmations-epost vid tidpunkten: [[datetime]]. Var god vänta på ett svar. + +/community/members.bml.error.invaliduser=Kan inte lägga till intressegrupp eller syndikerat konto: [[user]] + +/community/members.bml.error.noaccess=Endast underhållsansvariga för intressegruppen är tillåtna att redigera medlemskapslistor. Du är inte underhållsansvarig i intressegrupp [[comm]]. + +/community/members.bml.error.noattr=Inga egenskaper valda för användare: [[user]] + +/community/members.bml.error.nocomm=Intressegrupp finns inte. + +/community/members.bml.error.nouser=Användare finns inte: [[user]] + +/community/members.bml.key.admin=Underhållsansvarig + +/community/members.bml.key.member=Medlem + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Postningstillgång + +/community/members.bml.key.preapprove=Omodererad + +/community/members.bml.manage2=Underhålla intressegrupper + +/community/members.bml.name=Intressegruppnamn: [[name]] + +/community/members.bml.nextlink=(Nästa sida...) + +/community/members.bml.prevlink=(Tidigare sida...) + +/community/members.bml.settings=[Inställningar] + +/community/members.bml.success.header=Avklarat + +/community/members.bml.success.message=Dina ändringar har sparats. + +/community/members.bml.success.return=Tillbaka till listan + +/community/members.bml.title=Intressegruppmedlemmar + +/community/members.bml.update=Uppdatera inställningar + +/community/moderate.bml.approve.button=Ja, godkänn detta + +/community/moderate.bml.approve.header=Godkänna inlägget? + +/community/moderate.bml.approve.preapprove=Lägg också till användaren [[user]] till listan av redan godkända användare i denna intressegrupp. + +/community/moderate.bml.approve.text=Är du säker att du vill godkänna detta inlägg? + +/community/moderate.bml.brlist.actions=Behandlingar + +/community/moderate.bml.brlist.poster=Postare + +/community/moderate.bml.brlist.subject=Ämnet börjar + +/community/moderate.bml.brlist.time=Tid + +/community/moderate.bml.brlist.view=Vy + +/community/moderate.bml.browse.empty=Moderationslistan är tom. + +/community/moderate.bml.browse.header=Moderera intressegrupp + +/community/moderate.bml.browse.text=Här är moderationslistan för intressegruppen [[link]] + +/community/moderate.bml.choice.approve=Godkänna + +/community/moderate.bml.choice.reject=Avslå + +/community/moderate.bml.error.noaccess=Du modererar inte denna intressegrupp [[comm]]. + +/community/moderate.bml.error.noentry=Inlägg funnits inte (möjligen redan behandlad av en annan underhållare). + +/community/moderate.bml.error.nolist=Du modererar inte några intressegrupper. + +/community/moderate.bml.error.notfound=Intressegruppkonto funnits inte. + +/community/moderate.bml.manage=Underhålla intressegrupper + +/community/moderate.bml.moderate=Moderera denna intressegrupp. + +/community/moderate.bml.modlist.actions=Aktioner + +/community/moderate.bml.modlist.actmodempty=[Moderera] + +/community/moderate.bml.modlist.actmoderate=Moderera + +/community/moderate.bml.modlist.count=Kö storlek + +/community/moderate.bml.modlist.header=Moderera communities + +/community/moderate.bml.modlist.title=Titel + +/community/moderate.bml.modlist.username=Användarnamn + +/community/moderate.bml.posted.appheader=Godkänd i förväg + +/community/moderate.bml.posted.apptext=Dessutom har användaren [[user]] lagts till i listan av för-godkända användare i denna intressegrupp. + +/community/moderate.bml.posted.header=Avklarat + +/community/moderate.bml.posted.proterror=Inlägget har inte postats pga. protokollfelet: [[err]] + +/community/moderate.bml.posted.text=Inlägget har postats. + +/community/moderate.bml.reject.button=Ja, avslå det + +/community/moderate.bml.reject.header=Förkasta detta inlägg? + +/community/moderate.bml.reject.reason=Du kan också förklara för postaren dina skäl för att avvisa inlägget. Skälen skickas till postaren med epost. + +/community/moderate.bml.reject.text=Är du säker på att du vill förkasta detta inlägg? + +/community/moderate.bml.rejected.header=Förkastat + +/community/moderate.bml.rejected.text=Detta inlägg har blivit förkastat. + +/community/moderate.bml.title=Intressegrupp moderering + +/community/search.bml.button.clear=Rensa formulär + +/community/search.bml.button.search=Sök! + +/community/search.bml.checkbox.onlywithpics=Endast intressegrupper med bilder + +/community/search.bml.label.byinterest=Intressevis + +/community/search.bml.label.bylocation=Regionsvis + +/community/search.bml.label.bytime=Genom uppdaterings-tidpunkt + +/community/search.bml.label.city=Ort + +/community/search.bml.label.country=Land: + +/community/search.bml.label.displayoptions=Visa alternativ + +/community/search.bml.label.hasmember=Har medlem + +/community/search.bml.label.othercriteria=Andra kriterier + +/community/search.bml.label.outputformat=Format: + +/community/search.bml.label.records=Träffar per sida: + +/community/search.bml.label.searchcomm=Sök intressegrupper + +/community/search.bml.label.selecriteria=Välj kriterier nedan för de sätt du vill hitta communites genom. Resultaten är en kombination av alla sökta kriterier. Med andra ord, alla kryssrutor du klickat i betyder "OCH", inte "ELLER". + +/community/search.bml.label.sortmethod=Sorteringsmetod: + +/community/search.bml.label.stateprovince=Stat/Provins: + +/community/search.bml.label.updated=Uppdaterad senast + +/community/search.bml.sel.bypicture=Efter bild + +/community/search.bml.sel.communityname=Namn på intressegrupp + +/community/search.bml.sel.commview=Intressegruppsvy + +/community/search.bml.sel.day=dag + +/community/search.bml.sel.month=månad + +/community/search.bml.sel.simple=Enkel + +/community/search.bml.sel.updatetime=Tid för uppdatering + +/community/search.bml.sel.username=Användarnamn + +/community/search.bml.sel.week=vecka + +/community/search.bml.title=Intressegrupp-sökning + +/community/settings.bml.button.changecommunity=Spara inställningar + +/community/settings.bml.button.createcommunity=Skapa intressegrupp + +/community/settings.bml.error.badpassword=Ogiltigt lösenord för intressegruppen + +/community/settings.bml.error.hasentries=Detta konto har redan inlägg och kan inte förvandlas. + +/community/settings.bml.error.maintainertype=Underhållningsansvariga kontot måste vara till en person, inte ett annat delat konto. + +/community/settings.bml.error.noaccess=Endast underhållsansvariga för intressegrupper kan redigera intressegruppsinställningar. Du är inte förvaltare i intressegruppen [[comm]]. + +/community/settings.bml.error.notcomm=Inte ett intressegruppkonto. + +/community/settings.bml.error.notfound=Intressegruppkontot hittades inte. + +/community/settings.bml.error.samenames=Förvaltarekontot och intressegruppkontot kan inte vara demsamma. + +/community/settings.bml.label.anybodycan=Alla medlemmar
    Alla kan posta när de blivit medlemmar. + +/community/settings.bml.label.changeheader=Ändra intressegrupp inställningar + +/community/settings.bml.label.changetext=Här kan du ändra inställningarna på intressegruppen som du äger eller förvaltar. + +/community/settings.bml.label.commchanged=Dina intressegruppsinställningar har ändrats. + +/community/settings.bml.label.commcreate=Detta är kontot som du vill förvandla till en intressegrupp. Det måste redan ha skapats, men kan inte ha använts av en individ, då denna förvandlingen kommer att tillåta många användare att kunna posta i det. + +/community/settings.bml.label.commcreated=Din intressegrupp har nu skapats. + +/community/settings.bml.label.commheader=Intressegruppkonto + +/community/settings.bml.label.comminfo=Intressegrupp info + +/community/settings.bml.label.commopts=Intressegrupp anpassningar + +/community/settings.bml.label.commsite=Intressegrupp webbplats + +/community/settings.bml.label.community=IntressegruppÖ + +/community/settings.bml.label.createheader=Skapa intressegrupp + +/community/settings.bml.label.createtext=Härifrån kan du skapa en intressegruppkonto. En intressegrupp ("community") är en särskild sorts konto som andra användare kan delta och sätta inlägg i. Ett exempel på en intressegrupp är Svenskar på LiveJournal. + +/community/settings.bml.label.howoperates=Bestäm hur din intressegrupp fungerar. Du kan ändra dessa urval sedan. + +/community/settings.bml.label.maintainer=Underhållsansvarig: + +/community/settings.bml.label.maintainer.login=Om detta är inte underhållningsansvarige kontot, logga in med ett annat konto. + +/community/settings.bml.label.managepage=Intressegruppsunderhåll - att lägga till medlemmar, ge postningstillgång, utnämna medlare, osv. + +/community/settings.bml.label.membership=Medlemskap + +/community/settings.bml.label.modis=Modererat
    Nya inlägg måste godkännas av moderator. + +/community/settings.bml.label.modisnt=Omodererat
    Nya inlägg visas direkt. + +/community/settings.bml.label.modtext=Är imlägg till denna intressegrupp modererade? + +/community/settings.bml.label.nmcan=Icke-medlemmar kan posta
    Användare kan posta i intressegruppen utan att gå med i den. + +/community/settings.bml.label.nmcant=Icke-medlemmar kan posta
    Användare måste gå med i intressegruppen att kunna posta i den. + +/community/settings.bml.label.nmheader=Icke-medlem post + +/community/settings.bml.label.nmtext=Kan användare posta intressegruppen utan att bli medlem? + +/community/settings.bml.label.openmemb=Öppen medlemskap
    Vem som helst kan bli medlem utan att godkännas. + +/community/settings.bml.label.password=Lösenord + +/community/settings.bml.label.postaccess=Postningstillgång + +/community/settings.bml.label.rellinks=Viktiga länkar: + +/community/settings.bml.label.selcan=Utvalda medlemmar
    Endast vissa medlemmar kan posta, efter de får tillgång från den underhållsansvarige. + +/community/settings.bml.label.username=Användarnamn: + +/community/settings.bml.label.whocanjoin=Vem kan delta i din intressegrupp? + +/community/settings.bml.label.whocanpost=Vem kan posta till intressegruppen? + +/community/settings.bml.manage2=Underhålla intressegrupper + +/community/settings.bml.members=[Medlemmar] + +/community/settings.bml.name=Intressegrupp namn: [[name]] + +/community/settings.bml.success=Avklarat + +/community/settings.bml.title.create=Skapa intressegrupp + +/community/settings.bml.title.modify=Intressegrupp inställningar + +/create.bml.age.check.question=Är du yngre än 13 år? + +/create.bml.age.check.yes=Ja, jag är under 13 år. + +/create.bml.age.check2.question=Är du minst 13 år gammal? + +/create.bml.age.check2.yes=Ja, jag är inte mindre än 13 år. + +/create.bml.age.head=Ålder + +/create.bml.btn.create=Skapa journal + +/create.bml.btn.proceed=Fortsätt... + +/create.bml.captcha.answer=Svar: + +/create.bml.captcha.audiodesc=Ange siffrorna du hör för att bevisa du är ingen spamrobot: + +/create.bml.captcha.desc=Ange bokstäverna och siffrorna som du ser nedan, att bevisa att du inte är en spamrobot. Kan du inte läsa texten, skriv AUDIO och ta en ljudtest istället. + +/create.bml.captcha.invalid=Ogiltigt svar på förra intyget. Försök igen. + +/create.bml.captcha.play=Spela ljudet + +/create.bml.captcha.prove=Bekräfta att du är människa + +/create.bml.clusterselect.cluster=Kluster: + +/create.bml.clusterselect.clusternum=Kluster [[number]] + +/create.bml.clusterselect.head=Klusterurval + +/create.bml.clusterselect.nocluster=Inget kluster + +/create.bml.clusterselect.text=Var vänling välj kluster du vill skapa ett konto på. Obs: Detta är för debug och test endast. I produktion kommer användare inte välja detta, eller ens veta om det. + +/create.bml.create.head=Skapa en ny journal + +/create.bml.create.text=Att skapa en ny LiveJournal är enkelt, följ bara instruktionerna nedan! + +/create.bml.email.head=Din epost adress + +/create.bml.email.input.head=Epost adress: + +/create.bml.error.coppa.under13=Tyvvär, på grund av COPPA-restriktioner, kan du inte använda LiveJournals tjänster förrän du fyllt 13 år. Vänligen kom tillbaka på din 13:e födelsedag. + +/create.bml.error.email.blank=Du måste ange din epost adress. + +/create.bml.error.email.lj_domain=Man får inte använda en [[domain]] e-post adress när man skapar ett konto. Var god ange en annan e-post adress. + +/create.bml.error.email.nospaces=Inga mellanslag är tillåtna i en e-postadress. Har du AOL är din e-postadress lika med ditt screen namn utan mellanslag, följt av @aol.com + +/create.bml.error.password.asciionly=Du kan bara använda ASCII tecke i lösenordet. + +/create.bml.error.password.blank=Du måste ange ett lösenord. + +/create.bml.error.password.nomatch=Lösenorden matchar inte varandra. + +/create.bml.error.postrequired=POST krävs. + +/create.bml.error.username.blank=Ange alias/smeknamn. + +/create.bml.error.username.inuse=Användarnamnet används redan, ange ett annat. + +/create.bml.error.username.iscode=Användarnamnet verkar vara en invitationskod, inte ett användarnamn. + +/create.bml.error.username.mustenter=Du måste ange ett användarnamn. + +/create.bml.error.username.reserved=Tyvärr, det är ett reserverat användarnamn. + +/create.bml.initial.friend.news=LiveJournal nyheter och händelser + +/create.bml.initialfriends=Lägg till dessa journaler till din vänlista att hålla reda på sajtnyheter och information. + +/create.bml.initialfriends.heading=Vänner att börja med + +/create.bml.name.head=Ditt namn + +/create.bml.name.input.head=Namn: + +/create.bml.name.text=Vilket är ditt namn eller smeknamn? Det kommer synas högst upp i din journal, det kommer även synas i användar katalogen om du valt att bli visad där. Du behöver inte ange ditt fulla namn eller ens ditt riktiga namn. + +/create.bml.password.head=Lösenord + +/create.bml.password.input.head1=Lösenord: + +/create.bml.password.input.head2=Bekräfta lösenord: + +/create.bml.password.text=Välj lösenord. + +/create.bml.proceed.btn.proceed=Fortsätt... + +/create.bml.proceed.warning=Klicka endast på Fortsätt en gång!! + +/create.bml.success.btn.enterinfo=Ange personlig information + +/create.bml.success.head=Avklarat! + +/create.bml.success.text1=Din journal har skapats. Viktig registreringsinformation har skickats till [[email]] innehållande vidare uppgifter. Var vänlig och bekräfta skapandet av din journal genom att klicka på länken som skickats till dig via e-post. + +/create.bml.success.text2=Din LiveJournal kommer vara tillgänglig på: + +/create.bml.success.text3=Var vänlig fyll i information om dig själv. Det mesta är frivilligt, men det ger oss en bild av vilka som använder LiveJournal. + +/create.bml.title=Skapa ny journal + +/create.bml.tos.error=Du måste läsa och acceptera användarvillkoren innan du skapar ett konto. + +/create.bml.tos.haveread=Jag har läst och accepterat användarvillkoren. + +/create.bml.tos.heading=Användarvillkor. + +/create.bml.tos.p1.2=Innan du fortsätter måste du läsa och gå med på serviceavtalet. + +/create.bml.useacctcodes.entercode=För att skapa ett nytt konto, ange en invitationskod. För mer information, läs Hur skapar man ett konto? + +/create.bml.useacctcodes.welcome=Välkommen + +/create.bml.username.box.head=Användarnamn: + +/create.bml.username.charsallowed=Ditt användarnamn kan endast innehålla gemener (a-z) och siffror (0-9) och underscore tecknet.
    Dessutom får det inte vara längre än 15 tecken. + +/create.bml.username.forpaidaccts=Eller, för betalda konton: + +/create.bml.username.head=Användarnamn + +/create.bml.username.ljaddress=Din journal kommer att finnas på denna adress: + +/create.bml.username.text=Varje [[sitename]]-användare måste ha sitt egna unika användarnamn. Ditt användarnamn är vad som kommer att synas i adressen till din egna journal och det namn du använder för att logga in till [[sitename]] servern. Det visas också när du postar kommentarer i andra personers journaler. + +/create.bml.username.username=användarnamn + +/customize/index.bml.change=Ändra + +/customize/index.bml.choose.s1=Gammalt system (S1) + +/customize/index.bml.choose.s2=Nytt system (S2) + +/customize/index.bml.error.cant_generate_user_layer=Kunde inte generera användarlager + +/customize/index.bml.error.fail_create_style=Misslyckades att skapa ny stil. + +/customize/index.bml.error.not_your_layout=Inte din utformning. + +/customize/index.bml.error.not_your_theme=Inte ditt tema + +/customize/index.bml.error.no_core_parent=Ingen core förälder? + +/customize/index.bml.previews=(Tidigare) + +/customize/index.bml.s1.header=Använder S1 + +/customize/index.bml.s2.advanced.denied=Endast betalda, permanenta, och "Early Adopter" kontoinnehavare kan använda det avancerade kustomiseringsområdet. Mer om fördelarna att ha ett betalt konto. + +/customize/index.bml.s2.advanced.header=Avancerade anpassningar + +/customize/index.bml.s2.customize.header=Steg 2: Anpassa utformning + +/customize/index.bml.s2.customize.language=Följande språk stöds fullt eller delvis av denna layout. + +/customize/index.bml.s2.customize.language.custom=(Anpassat) + +/customize/index.bml.s2.customize.language.header=Språk + +/customize/index.bml.s2.customize.settings=Vill du ytterligar anpassa din journal, här kan du justera individuella inställningar att få den att se ut precis hur du vill. + +/customize/index.bml.s2.customize.settings.delete=Ta bort annpassningar + +/customize/index.bml.s2.customize.settings.delete.confirm=Är du säker att du vill ta bort dessa anpassningar? + +/customize/index.bml.s2.customize.settings.edit=Redigera anpassningar + +/customize/index.bml.s2.customize.settings.header=Ändra individuella inställningar + +/customize/index.bml.s2.customize.settings.new=Anpassa + +/customize/index.bml.s2.customize.themes.header=Teman + +/customize/index.bml.s2.related.editinfo.about=Bestäm din journals titlar och andra urval. + +/customize/index.bml.title=Anpassa journal + +/delcomment.bml.changeoptions<< +OBS: Från [[link]] sidan kan du välja om alla, registrade användare, eller +endast vänner får posta kommentarer. +. + +/delcomment.bml.confirm.banuser=Bannlysa [[user]] från att kommentera i din journal + +/delcomment.bml.confirm.body=Är du säker att du vill radera denna kommentar? + +/delcomment.bml.confirm.head=Radera kommentaren? + +/delcomment.bml.confirm.spam=Markera kommentar som spam + +/delcomment.bml.confirm.submit=Radera kommentar + +/delcomment.bml.error.alreadydeleted=Valda kommentaren har redan raderats. + +/delcomment.bml.error.cantdelete=En kommentar kan endast raderas av författaren eller journalägaren. + +/delcomment.bml.error.cantdelete.comm=En kommentar kan endast raderas av författaren, journalinläggsägaren, eller en intressegruppunderhållare. + +/delcomment.bml.error.invalidtype=Ogiltig kommentartyp. Denna sida behandlar endast kommentarer i journalinlägg. + +/developer/index.bml.clients<< +Så du vill skapa eller förbättra en LiveJournal klient för din platform? Fantastiskt! +Nedanför finns några nödvändiga referenser för att låta dig veta hur LiveJournal fungerar. +. + +/developer/index.bml.clients.header=Skriva LiveJournal Klienter + +/developer/index.bml.clients.links<< +
    +
    LiveJournal server<->klient protokoll
    +
    Lär dig hur LiveJournal klienten på din dator samtalar med LiveJournal-servern. Att förstå detta är första steget innan du kan skapa eller ändra en klient på din plattform.
    +
    Complete Protocol Docs
    +
    Alla olika protokoll-sätt och metoder.
    +
    Klientlista
    +
    En lista av de flesta klienter som kan användas med LiveJournal. De flesta av dessa klienter har öppen källkod, och alla är gratis att använda. Detta är en bra plats att hitta exempel för din klient.
    +
    +. + +/developer/index.bml.code.header=LiveJournals Kodarkiv + +/developer/index.bml.dbschema=Nyfiken om databasschemat? SQL:n att skapa alla tabellerna och ifylla dem är inkluderad med serverkällkoden. + +/developer/index.bml.dbschema.header=Databas Schema + +/developer/index.bml.embedding.header=Inbäddera LiveJournal + +/developer/index.bml.notice.header=Observera + +/developer/index.bml.notice1=Följande information är endast till programmerare och avancerade änvändare. Vill de bara använda LiveJournal att ha en journal, gÃ¥r det fint. Vanliga användare behöver inte bry sig om detta. + +/developer/index.bml.notice2=Med det sagt, är innehÃ¥llet nedan uppbruten i tvÃ¥ delar: information om hur man anpassar sidornas utseende i LiveJournal, och information om hur man skriver LiveJournalklienter till LiveJournal servern. + +/developer/index.bml.styles.header=Anpassning av LiveJournals utseende + +/developer/index.bml.styles.s1.system=Stilsystem + +/developer/index.bml.styles.s1.varlist=Variabellista + +/developer/index.bml.styles.s1.views=Visa typer + +/directory.bml.browse.country.title=Bläddra journaler i landordning + +/directory.bml.browse.usa.title=Bläddra journaler i USA-delstatsordning + +/doc/index.bml.about=Välkommen till LiveJournals dokumenteringsförrÃ¥d, där man kan finna information pÃ¥ de flesta ämnen gällande LiveJournals servicer och serverprogram. Välj ett ämne frÃ¥n de följande: + +/doc/index.bml.about.header=Välkommen + +/doc/index.bml.docs.faq.about=Vanliga frÃ¥gor och svar om LiveJournal.com + +/doc/index.bml.docs.faq.title=Vanliga frÃ¥gor och svar + +/doc/index.bml.docs.header=Dokument + +/doc/index.bml.docs.howto.about=RÃ¥d om hur man anpassar ens LiveJournal konto. + +/doc/index.bml.docs.server.about=Allt man behöver veta om hur man installerar, underhÃ¥ller, och hackar en LiveJournal installation + +/doc/index.bml.docs.server.title=LiveJournal serverhandbok + +/doc/index.bml.docs.tour.about=Avsedd för nya besökare att lära sig om webbplatsen + +/doc/index.bml.docs.tour.title=Rundtur + +/doc/index.bml.title=Dokumentering + +/doc/index.bml.volunteering.about=Vill du hjälpa till med LiveJournals dokumentering, kolla de följande intressegrupper: + +/doc/index.bml.volunteering.header=Deltagande + +/doc/index.bml.volunteering.ljsysdoc=Diskussioner om LiveJournals dokumenteringssystem + +/doc/index.bml.volunteering.ljuserdoc=Användare dokumenteringsdiskussioner + +/doc/tour/index.bml.clients.caption<< +LiveJournal klient är ett litet program som körs pÃ¥ din dator som tillÃ¥ter dig att uppdatera din journal när du är online, utan att ha nÃ¥got browserfönster öppet. +Klienter finns tillgängliga för nästan alla sorters platformar och är enkla att anpassa. +. + +/doc/tour/index.bml.clients.title=Klienter + +/doc/tour/index.bml.comms.caption=LiveJournal är ett stort interaktivt samhälle, sÃ¥ det vore inte sÃ¥ konstigt om andra användare har liknande intressen. Vi erbjuder möjligheten att skapa intressegrupper, eller journaler som mÃ¥nga kan posta i. + +/doc/tour/index.bml.create.caption=LiveJournal är ett medlemsbaserat journaleringssamhälle. Den här sidan förklarar vad medlemskap medger, varför medlemskap är viktigt och vilka förmÃ¥ner ett medlemskap ger. Den innehÃ¥ller ocksÃ¥ ett formulär för att skapa dig ett eget konto. + +/doc/tour/index.bml.create.title=Skapa konto + +/doc/tour/index.bml.friends.caption=Du kan hÃ¥lla koll pÃ¥ dina vänner genom LiveJournal, genom att använda den inbyggda "vänner" funktionen. Om du hittar en journal du finner intressant, lägg till den till din vänlista, vilket lÃ¥ter dig läsa alla dina vänners inlägg pÃ¥ en och samma sida. + +/doc/tour/index.bml.friends.title=Vänner + +/doc/tour/index.bml.intro.title=Välkommen + +/doc/tour/index.bml.modify.caption=Det är ocksÃ¥ möjligt att ändra utseendet pÃ¥ din journal pÃ¥ mÃ¥nga olika sätt, med att använda förbestämda stiler och färgtema. Gör din journal sÃ¥ unik som du vill! + +/doc/tour/index.bml.modify.title=Anpassning + +/doc/tour/index.bml.nav.next=Nästa --> + +/doc/tour/index.bml.nav.prev=<-- Förra + +/doc/tour/index.bml.profile.caption=Medlemmar i LiveJournal är uppmanade att sätta in information om sig i sina profiler, sÃ¥ vi fÃ¥r insikt i vem använder webbplatsen och hur vi kan bäst betjäna dem. Men inget av detta är obligatoriskt — den enda informationen som krävs att börja använda LiveJournal är ett namn, en epostadress, och ett lösenord. + +/doc/tour/index.bml.profile.title=Profiler + +/doc/tour/index.bml.sitemap.title=Sajtkarta + +/doc/tour/index.bml.support.caption=Hjälpsidan listar ämneomrÃ¥den som hjälper till att förklara vad LiveJournal är, vanliga frÃ¥gor och svar om webbplatsen, och annan hjälpsam information om servicen, bolaget, och övriga LiveJournalsamhället. + +/doc/tour/index.bml.support.title=FÃ¥ hjälp + +/doc/tour/index.bml.title=Rundtur - [[title]] + +/doc/tour/index.bml.update.title=Uppdaterar + +/editinfo.bml.allowshowcontact.about=Du bör ha detta alternativ valt. Detta lÃ¥ter andra kunna ta kontakt med dig dÃ¥ det visar din e-postadress, ICQ-nummer och namn för AOL Instant Messenger. + +/editinfo.bml.allowshowcontact.email=E-postadress som ska visas (om synlig): + +/editinfo.bml.allowshowcontact.email.actual_only=Endast riktig adress + +/editinfo.bml.allowshowcontact.email.both=BÃ¥da (riktig + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Endast LiveJournal-adress + +/editinfo.bml.allowshowcontact.email.neither=Ingen. Visa inga e-post adresser. + +/editinfo.bml.allowshowcontact.email.no_show=Visa inga e-post adresser. + +/editinfo.bml.allowshowcontact.email.show=Visa e-postadress + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Med alternativet ovan, kan du ocksÃ¥ välja att gömma din epost adress (medan annan kontakt information visas), visa bara din Livejournal adress (endast betalande användare), visa bara din riktiga adress, eller visa bÃ¥da. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Med valalternativet ovan, kan du ocksÃ¥ välja att dölja din emailadress (fortfarande visandes den andra kontakt-informationen). + +/editinfo.bml.allowshowcontact.title=Visa din kontaktinformation pÃ¥ din LiveJournal-sida? + +/editinfo.bml.allowshowinfo.about=Välj detta alernativ om du vill att din stad/region/land och födelsedag ska vara synligt för andra användare. + +/editinfo.bml.allowshowinfo.title=Visa omrÃ¥de & födelsedag? + +/editinfo.bml.autotranslate.about<< +Använd detta alternativ för att tala om för LiveJournal vilken teckenuppsättning du använt i dina inlägg och kommentarer innan LiveJournal konverterade till Unicode. + +Om du skriver pÃ¥ svenska eller engelska, välj "Western European" här. +. + +/editinfo.bml.autotranslate.header=Auto-konvertera äldre inlägg frÃ¥n: + +/editinfo.bml.bday.title=Födelsedag + +/editinfo.bml.bday.year.opt=FödelseÃ¥r är valfritt + +/editinfo.bml.bdayreminders.about=Om du vill fÃ¥r email-pÃ¥minnelser om födelsedagar för dina vänner pÃ¥ LiveJournal, ticka för denna box. + +/editinfo.bml.bdayreminders.header=Skicka födelsedagspÃ¥minnelser (tillfälligt otillgänglig) + +/editinfo.bml.bio.about=Här kan du skriva en liten mini-biografi om dig själv som kommer att visas pÃ¥ din användarinfo sida. + +/editinfo.bml.bio.header=Om dig + +/editinfo.bml.blockrobots.about<< +Markerar du detta alternativ, kommer robotar/spindlar att bli ombedda att ignorera din journal. +Inte alla robotar/spindlar respekterar reglerna, men de flesta söksidornas robotar gör det. +. + +/editinfo.bml.blockrobots.header=Hindra Robotar/Spindlar frÃ¥n att indexera din journal + +/editinfo.bml.chat.msnusername.title=MSN användarnamn + +/editinfo.bml.city.title=Stad + +/editinfo.bml.country.choose=Välj ett land + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Nej + +/editinfo.bml.email.title=E-post + +/editinfo.bml.enableboards.about=Markera det här alternativet om du vill att andra ska kunna svara pÃ¥ de journalinlägg du har postat. + +/editinfo.bml.enableboards.header=TillÃ¥t forum + +/editinfo.bml.encoding.about=Oroa dig inte över detta. Genrellt sett, endast internationella användare som skriver i flera olika sprÃ¥k behöver oroa sig för att ändra nÃ¥nting här. + +/editinfo.bml.encoding.header=Kodningsalternativ + +/editinfo.bml.error.day.notinmonth=Ogiltig dag i den mÃ¥naden. + +/editinfo.bml.error.day.outofrange=Ogiltig födelsedag dag. Ange en dag frÃ¥n 1-31. + +/editinfo.bml.error.email.lj_domain<< +Du kan inte ange en @[[domain]]-epostadress. +Ange din riktiga adress i det här fältet. +Om du är en Betalande användare kommer din [[user]]@[[domain]]-adress vidarebefodra till din riktiga adress. +För att välja vilka adresser som skall publiceras, se stycket "Visa Kontaktinformation". +. + +/editinfo.bml.error.email.none=Du mÃ¥ste ange din epostadress. + +/editinfo.bml.error.email.no_space=Mellanslag är inte tillåtna i en e-postadress. Om du använder AOL, kom ihåg att din e-postadress är ditt användarnamn utan mellanslag, följt av @aol.com + +/editinfo.bml.error.excessive_int=Du har angett för mÃ¥nga intressen. Gränsen är 150, men du har angett [[intcount]]. De ändringar som gjorts till dina intressen har inte sparats. GÃ¥ tillbaka och korta ned listan och spara den en gÃ¥ng till. + +/editinfo.bml.error.invalidbio=Din lagrade biografi innehÃ¥ller otillÃ¥tna tecken. Var vänlig gÃ¥ till konverteringssidan för att konvertera den till Unicode. + +/editinfo.bml.error.invalidints=Din lagrade intresselista innehÃ¥ller otillÃ¥tna tecken. Var vänlig gÃ¥ till konverteringssidan för att konvertera den till Unicode. + +/editinfo.bml.error.invalidname=Ditt namn innehÃ¥ller otillÃ¥tna tecken. Var vänlig gÃ¥ till konverteringssidan för att konvertera den till Unicode. + +/editinfo.bml.error.locale.country_ne_state=Du specificerade USA som ditt land, men du skrev in en icke-USA stat i "annan stat/provins/omrÃ¥de" fältet. + +/editinfo.bml.error.locale.invalid_country=PÃ¥ nÃ¥got sätt valde du ett felaktigt land. + +/editinfo.bml.error.locale.state_ne_country=Du angav ett icke-USA land men valde en USA stat. + +/editinfo.bml.error.locale.zip_ne_state<< +Ditt postnummer matchar inte staten/provinsen/omrÃ¥det du specificerade. +Antingen fyll i rätt information, eller radera en eller bÃ¥dera av staten/provinsen/omrÃ¥det fälten. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Du skrev in ett postnummer men du valde inte USA som ditt land. +Vi samlar endast postnummer-information om personer i USA. +Vänligen gÃ¥ tillbaka och ta bort postnumret eller välj United States som ditt land. +. + +/editinfo.bml.error.month.outofrange=Ogiltig födelsedagsmÃ¥nad. Ange en mÃ¥nad frÃ¥n 1-12. (Jan-Dec) + +/editinfo.bml.error.noname=Du mÃ¥ste uppge ditt namn. Det räcker med ditt förnamn, och du kan ange ett smeknamn eller nätnamn i stället.. + +/editinfo.bml.error.tm.require.number=Om du kommer att använda text meddelande, mÃ¥ste du ange ditt telefonnumer. + +/editinfo.bml.error.tm.require_provider<< +Om du kommer att använda text meddelanden, mÃ¥ste du ange vilken operatör du använder. + +Om din operatör inte finns listad, kontakta oss med information om hur din operatörs text-meddelande fungerar sÃ¥ vi kan lägga till stöd för det. +. + +/editinfo.bml.error.year.notenoughdigits=Ogiltigt födelsedagsÃ¥r. Ange ett Ã¥r med fyra siffror. + +/editinfo.bml.error.year.outofrange=Ogiltigt födelsedagsÃ¥r. + +/editinfo.bml.finished.about=När du är klar klickar du pÃ¥ knappen "Spara ändringar" nedan: + +/editinfo.bml.finished.header=Klar? + +/editinfo.bml.finished.save_button=Spara ändringar + +/editinfo.bml.gender.title=Kön + +/editinfo.bml.getreplies.about=Markera detta om du vill fÃ¥ epost-uppdateringar när folk svarar pÃ¥ dina journalinlägg i forumet (med kommentarer). + +/editinfo.bml.getreplies.header=FÃ¥ forum-uppdateringar + +/editinfo.bml.hidefriendof.about=Om du markerar detta, döljs listan av personer som listar dig som vän pÃ¥ din användarinfo-sida + +/editinfo.bml.hidefriendof.header=Göm "Vän till" lista + +/editinfo.bml.howhear.about<< +För nyfikenhets skull, var hörde du om [[sitename]] frÃ¥n? +Om det var en specifik person, skriv in deras användarnamn, om det var frÃ¥n en annan källa/artikel/webbsida, skriv in lämplig information. +. + +/editinfo.bml.howhear.header=Nyfikenhet + +/editinfo.bml.htmlemail.about<< +Markera detta om ditt epost-program helt stödjer HTML i dina epost. +MÃ¥nga klienter försöker stödja det men misslyckas nÃ¥got sÃ¥ fruktansvärt. +Om du lämnar det omarkerat, kommer LiveJournal endast att skicka text-epost. +. + +/editinfo.bml.htmlemail.header=Skicka HTML-e-post + +/editinfo.bml.int.about=Om du vill att andra ska kunna söka och hitta dig efter dina intressen skriver du en lista med vad du tycker om här nedan. Avgränsa dina intressen med ett kommatecken. Korta fraser med ett ord fungerar bäst. Tumregel: Intresset ska kunna infogas i meningen "Jag tycker om ________". När du anger substantiv bör du använda pluralformen, sÃ¥ att det blir konsekvent. "Jag tycker om DVD-filmer" i stället för "Jag tycker om DVD-film". + +/editinfo.bml.int.ex.bad=DÃ…LIGT Exempel: Jag tycker om att lyssna pÃ¥ mÃ¥nga musikgrupper, titta pÃ¥ filmer, prata med vänner och gÃ¥ pÃ¥ klubbar. SÃ¥nt ska du skriva i din biografi ovan. + +/editinfo.bml.int.ex.good=BRA Exempel: cykla, Ã¥ka skidor, datorer, dvd-filmer, mp3:or, ost, kvinnor + +/editinfo.bml.int.header=Intressen + +/editinfo.bml.login.enterinfo=Ange ditt användarnamn och ditt lösenord om du vill ändra din personliga information. + +/editinfo.bml.login.forgot.header=Glömt nÃ¥gonting? + +/editinfo.bml.login.forgot.recover=Om du glömt ditt användarnamn eller ditt lösenord kan du fÃ¥ tag pÃ¥ det här!. + +/editinfo.bml.logip.always=Alltid + +/editinfo.bml.logip.anon_only=Endast anonyma postare + +/editinfo.bml.logip.header=Logga IP-adresser av personer som svarar? + +/editinfo.bml.mangleaddress.about=Om du är rädd att spam-robotar kommer att hitta din epostadress pÃ¥ LiveJournal, välj detta alternativ och din epostadress kommer att bli modifierad sÃ¥ att den inte blir hittad av epost-samlande robotar. + +/editinfo.bml.mangleaddress.header=Förvräng din visade epost adress + +/editinfo.bml.name.title=Namn + +/editinfo.bml.newemail.subject=Epostadress ändrat + +/editinfo.bml.numcomments.about=Kryssa i här om du vill lägga till kommentars räknare pÃ¥ URLer för att fÃ¥ din browser att visa annan länkfärg pÃ¥ uppdaterade inlägg. + +/editinfo.bml.numcomments.header=Lägg till &nc=xx till kommentar-URL:er + +/editinfo.bml.optional=Valfritt + +/editinfo.bml.opt_in.about<< +Om du vill veta när vi lägger till nya tuffa funktioner pÃ¥ LiveJournal, kryssa i här. +Dessa email du fÃ¥r kommer vara ganska sällsynta, inte mer än ett eller kanske tvÃ¥ i mÃ¥naden oftast. +Din epost adress kommer inte vara synlig för andra användare och du kan stänga av detta när som helst. +. + +/editinfo.bml.opt_in.header=Skicka LiveJournal-nyheter. + +/editinfo.bml.persinfo.disclaimer=Fyll i lite information om dig själv. Vi är nyfikna och tycker om att föra statistik. Vi kommer inte att göra nÃ¥got elakt med den här informationen, utan vi vill bara veta vilka vÃ¥ra användare är och vart de finns. Vi uppskattar om du är ärlig. Om du är orolig kan du läsa vÃ¥r sekretesspolicy. + +/editinfo.bml.persinfo.header=Personlig information + +/editinfo.bml.screen.all=Alla + +/editinfo.bml.screen.anon=Endast Anonyma + +/editinfo.bml.screen.header=Vilka svar vill du ha förvals-avskärmade? + +/editinfo.bml.screen.none=Ingen + +/editinfo.bml.screen.nonfriends=Ej listade vänner + +/editinfo.bml.screen.nonmembers=Ej listade medlemmar + +/editinfo.bml.security.header=Vem fÃ¥r se din kontaktinformation? + +/editinfo.bml.security.visibility.anybody=Alla + +/editinfo.bml.security.visibility.everybody=Alla + +/editinfo.bml.security.visibility.friends=Endast vänner + +/editinfo.bml.security.visibility.regusers=Registrerade användare + +/editinfo.bml.settings.friendspage.title=Vänsida titel: + +/editinfo.bml.settings.friendspage.title.optional=Ange om du vill en titel för din vänsida. (ingen HTML) + +/editinfo.bml.settings.header=LiveJournal-alternativ + +/editinfo.bml.settings.journal.subtitle=Journal undertitel: + +/editinfo.bml.settings.journal.subtitle.optional=Ange om du vill en titel och undertitel för din vänsida. (ingen HTML) + +/editinfo.bml.settings.journal.title=Journaltitel: + +/editinfo.bml.settings.privacy.about=Välj nedan dina personliga Integritetsanpassningar. + +/editinfo.bml.settings.privacy.header=Integritetsanpassningar + +/editinfo.bml.state.other=Eller, ange annan stat/provins/omrÃ¥de + +/editinfo.bml.state.title=Stat + +/editinfo.bml.state.us=Förenta Staterna + +/editinfo.bml.success.header=Avklarat + +/editinfo.bml.success.message=Din information och journal inställningar och profil har blivit uppdaterade. + +/editinfo.bml.switch.button=Byt + +/editinfo.bml.switch.header=Byt journal + +/editinfo.bml.switch.workwith=Använd journal: + +/editinfo.bml.title=Ändra personlig information + +/editinfo.bml.tm.details=detailjer + +/editinfo.bml.tm.phonenum=Fullt telefonnummer: + +/editinfo.bml.tm.sec.about=Möjliggör textmeddelanden frÃ¥n andra användare. + +/editinfo.bml.tm.sec.title=SäkerhetsnivÃ¥: + +/editinfo.bml.tm.servprov=Operatör + +/editinfo.bml.tm.title=Textmeddelanden + +/editinfo.bml.translatemailto.about=Ifall du väljer att ta emot Forum-svar via email, och din emailklient inte kan hantera Unicode (UTF-8) meddelande sÃ¥ bra, använd detta alternativ för att specificera en annan slags kodning som LiveJournal automatiskt kommer att översätta text till, i kommentarer som skickas till dig. + +/editinfo.bml.translatemailto.header=Översätt epostmeddelanden till: + +/editinfo.bml.unbanusers.about=Du har blockerat följande användare frÃ¥n att posta kommentarer i din journal. Klicka i märkrutan vid deras namn för att ta bort blockeringen. + +/editinfo.bml.unbanusers.header=Upphäv + +/editinfo.bml.userpic.about=Nedan är minatyrbilden du har valt att ladda upp för att representera dig själv pÃ¥ LiveJournal-sidan, i din journal, och i dina vänners journaler: + +/editinfo.bml.userpic.edit=För att ta bort denna bild, eller ladda upp en ny, gÃ¥ hit. + +/editinfo.bml.userpic.header=Din bild + +/editinfo.bml.userpic.none=inga bilder uppladdade + +/editinfo.bml.weblogscom.about=Välj detta om du vill ha Weblogs.com visa din journal när du postar nya offentliga inlägg. + +/editinfo.bml.weblogscom.header=Underrätta Weblogs.com om uppdateringar + +/editinfo.bml.webpagename.title=Websidans namn + +/editinfo.bml.webpageurl.title=Websidans URL + +/editinfo.bml.whoreply.header=Vilka kan svara pÃ¥ dina inlägg? + +/editinfo.bml.zip.title=Postnummer + +/editinfo.bml.zip.usonly=5-siffriga postnummer; endast Amerikanska residenter + +/editjournal.bml.btn.proceed=Fortsätt... + +/editjournal.bml.certainday=Särskild dag: + +/editjournal.bml.recententries=senaste inlägg + +/editjournal.bml.recententry=Senaste inlägget + +/editjournal.bml.title=Ändra inlägg + +/editjournal.bml.viewwhat=Visa inlägg: + +/editjournal_do.bml.btn.edit=Ändra valt inlägg + +/editjournal_do.bml.btn.save=Spara inlägg + +/editjournal_do.bml.continue.head=Fortsätt... + +/editjournal_do.bml.continue.text=Tryck pÃ¥ Ändra-knappen när du valt vad du vill ändra eller radera. + +/editjournal_do.bml.currmood=Humör: + +/editjournal_do.bml.currmusic=Musik: + +/editjournal_do.bml.date=Datum: + +/editjournal_do.bml.default=förvalt + +/editjournal_do.bml.edit.text=Detta är journalinlägget som du valde att redigera. Ändra det du vill ändra pÃ¥, och tryck pÃ¥ Spara-knappen i botten pÃ¥ sidan.

    Om du vill radera inlägget, radera all text och tryck på Spara. Inlägget kommer då att tas bort. + +/editjournal_do.bml.error.getting=Det gick inte att hämta inläggen som skulle ändras: + +/editjournal_do.bml.error.modify=Det gick inte att ändra din journal: + +/editjournal_do.bml.error.nofind=Hittar inte valt inlägg. + +/editjournal_do.bml.event=Händelse: + +/editjournal_do.bml.localtime=Lokal tid: + +/editjournal_do.bml.noneother=Inget, eller annat: + +/editjournal_do.bml.opt.backdate=Datumändra: + +/editjournal_do.bml.opt.backdate.about=visas inte på vännervy + +/editjournal_do.bml.opt.nocomments=Tillåt inte kommentarer: + +/editjournal_do.bml.opt.noemail=E-posta inte kommentarer: + +/editjournal_do.bml.opt.noformat=Auto-formatera inte: + +/editjournal_do.bml.other=Annat: + +/editjournal_do.bml.pickentry.head=Välj ett inlägg att ändra + +/editjournal_do.bml.pickentry.text=Välj vad du vill ändra och tryck på Ändra-knappen. + +/editjournal_do.bml.picture=Bild att använda: + +/editjournal_do.bml.save.head=Spara... + +/editjournal_do.bml.save.text=När du har ändrat klart, tryck på Spara-knappen. + +/editjournal_do.bml.subject=Ämne: (valfritt) + +/editjournal_do.bml.success.delete=Inlägget är raderat. + +/editjournal_do.bml.success.edit=Inlägget har ändrats. Du kan se det här. + +/editjournal_do.bml.success.head=Avklarat + +/editjournal_do.bml.timeformat=24-timmars-tid + +/editjournal_do.bml.title=Ändra inlägg + +/editpics.bml.btn.proceed=Fortsätt + +/editpics.bml.curpics=Aktuella bilder + +/editpics.bml.error.badurl=Adressen för bilden att ladda upp ser inte rätt ut. Den borde börja med http:// + +/editpics.bml.error.filetoolarge=Bilden att ladda upp är för stor. Filstorleken kan inte vara mer än [[maxsize]]. + +/editpics.bml.error.invalidimage=Ogiltig bildfil. + +/editpics.bml.error.toomanypics2=Du har redan största tillåtna antalet [[maxpics]] bilder. Du kan inte ladda upp denna bild tills du raderar en av de som redan finns. + +/editpics.bml.error.unsupportedtype=Filer med typ [[filetype]] är inte tillåtna. Du kan endast ladda upp GIF, PNG, eller JPG filer. Nästan alla bild/foto program kan göra denna förvandling åt dig. + +/editpics.bml.error.urlerror=Ett fel har upstått under bilduppladdningen. + +/editpics.bml.fromfile=Från fil: + +/editpics.bml.fromurl=Från URL: + +/editpics.bml.kilobytes=kB + +/editpics.bml.nopics=Inga bilder + +/editpics.bml.restriction.fileformat=Filformat måste vara en av PNG, GIF eller JPG + +/editpics.bml.restriction.filesize=filstorlek måste vara mindre än 40kB + +/editpics.bml.restriction.imagesize=Bildytan kan inte vara större än 100x100 pixel. + +/editpics.bml.title=Redigera användarbilder + +/editpics.bml.uploadheader=Ladda upp en ny bild + +/export.bml.btn.proceed=Fortsätt... + +/export.bml.description=Denna funktion tilllåter att nerladda hela din journal till en anpassad säkerhetskopia. För mer information om funktionen, se denna länk. + +/export.bml.fields=Fält: + +/export.bml.format.csv=CVS (Komma separerade värden) + +/export.bml.label.encoding=Kodering: + +/export.bml.label.field.currents=Humör & musik + +/export.bml.label.field.event=Händelse + +/export.bml.label.field.eventtime=Tid (enligt användarens klocka) + +/export.bml.label.field.itemid=ID-nummer + +/export.bml.label.field.logtime=Loggtid (enligt systemklockan) + +/export.bml.label.field.security=Säkerhetsnivå + +/export.bml.label.field.subject=Ämne + +/export.bml.label.header=Rubrik + +/export.bml.label.month=Välj månad: + +/export.bml.label.month.year=åååå: + +/export.bml.label.notranslation=Överföra inte mellan koderingar + +/export.bml.label.what=Exportera vad: + +/export.bml.title=Exportera journal + +/export.bml.what.entries=Journalinlägg + +/friends/add.bml.add.header=Avklarat + +/friends/add.bml.add.text=Användare [[user]] lades till på din vänlista. Du kan se din vänsida här. + +/friends/add.bml.add.title=Vän tillagd! + +/friends/add.bml.btn.add=Lägg till [[user]] + +/friends/add.bml.btn.modify=Ändra + +/friends/add.bml.btn.remove=Ta bort + +/friends/add.bml.colors.bg=Bakgrund + +/friends/add.bml.colors.fg=Förgrund + +/friends/add.bml.colors.header=Färger + +/friends/add.bml.colors.hover=(Håll musmarkören över en färg för att se dess namn) + +/friends/add.bml.colors.text=Du kan också välja färg för [[user]] i din vänlista. + +/friends/add.bml.confirm.header=Lägg till [[user]] som vän? + +/friends/add.bml.confirm.text=För att lägga till [[user]] till din vänlista, klicka på knappen nedan. + +/friends/add.bml.confirm.title=Lägg till vän + +/friends/add.bml.error1.header=Logga in först + +/friends/add.bml.error1.text=För att lägga till en användare till din vänlista måste du först logga in. Om du inte redan har en journal kan du skapa en för att läsa dina vänners journaler. + +/friends/add.bml.error1.title=Lägg till vän + +/friends/add.bml.error2.text=Användarnamn saknas eller är fel. För att lägga till en vän, gå till Ändra vänner. + +/friends/add.bml.error3.text=Du har redan [[user]] i din vänlista. Du kan i alla fall ändra färger du valt för att representera honom/henne. + +/friends/add.bml.error3.title=Ändra vän + +/friends/add.bml.groups.header=Vängrupper + +/friends/add.bml.groups.nogroup=Du har inga vängrupper. + +/friends/add.bml.groups.text=Vilka vängrupper vill du att användaren ska tillhöra? Med vängrupper kan du sålla din vänlista och bestämma vilken grupp som kan läsa vilka inlägg. + +/friends/add.bml.remove.header=Avklarat + +/friends/add.bml.remove.text= togs bort från din vänlista. Du kan se din vänsida här. + +/friends/add.bml.remove.title=Vän borttagen! + +/friends/edit.bml.title=Ändra vänner + +/friends/editgroups.bml.btn.ge.del=Radera + +/friends/editgroups.bml.btn.ge.new=Ny + +/friends/editgroups.bml.btn.ge.ren=Byt namn + +/friends/editgroups.bml.btn.gs.private=Privat + +/friends/editgroups.bml.btn.gs.public=Offentlig + +/friends/editgroups.bml.btn.mv.down=Flytta ner + +/friends/editgroups.bml.btn.mv.up=Flytta upp + +/friends/editgroups.bml.confirm.delete=Är du säker att du vill radera denna vängrupp? + +/friends/editgroups.bml.done.btn=Spara ändringar + +/friends/editgroups.bml.done.header=Klar? + +/friends/editgroups.bml.done.text=När du är klar, klicka på knappen nedan för att spara dina ändringar. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Du har för många vängrupper (max 30). Om du har raderat en eller fler grupper men ännu inte sparat ändringarna, gör det nu, gå tillbaka till denna sida och ladda om. Du kommer då ha möjligheten att skapa nya vängrupper. + +/friends/editgroups.bml.error.text=Följande fel inträffade: + +/friends/editgroups.bml.group.public=(offentlig) + +/friends/editgroups.bml.ingroup=I gruppen: + +/friends/editgroups.bml.ingroup.not=Inte i gruppen: + +/friends/editgroups.bml.prompt.newname=Namnge den nya vängruppen: + +/friends/editgroups.bml.prompt.rename=Byt namn på vängruppen till: + +/friends/editgroups.bml.saved.header=Sparat + +/friends/editgroups.bml.saved.text=Dina vängrupper är nu sparade. + +/friends/editgroups.bml.text=Denna sida tillåter dig ändra dina vängrupper. Vängrupper används för säkerhetsinställningar på dina inlägg och att sålla din vänlista. För hjälp, se Vad är vängrupper? Hur använder jag dem? + +/friends/editgroups.bml.text.sec=Säkerhetsmeddelande: Vill du ta bort en grupp och skapa en ny, gör inte detta genom att byta namn på en grupp och sedan ändra den. Om du gör det kommer den nya gruppen att kunna se alla de inlägg som den gamla gruppen kunde se. + +/friends/editgroups.bml.title=Ändra vängrupper + +/friends/editgroups.bml.yourgroups=Dina vängrupper: + +/friends/edit_do.bml.addfriends.head=Lägg till vänner + +/friends/edit_do.bml.addfriends.text=Skriv in dina vänners LiveJournal-namn i rutorna nedan, och välj vilka bak- och förgrundsfärger du vill ge dem... + +/friends/edit_do.bml.background=Bakgrund + +/friends/edit_do.bml.bgcolor=Bakgrundsfärg: + +/friends/edit_do.bml.btn.close=Stäng + +/friends/edit_do.bml.btn.save=Spara ändringar + +/friends/edit_do.bml.btn.toggle=Se färgförhandsvisning + +/friends/edit_do.bml.done.head=Klar? + +/friends/edit_do.bml.done.text=När du är klar, klicka på "Spara ändringar" nedan... + +/friends/edit_do.bml.error.updating=Ett fel inträffade när din vänlista uppdaterades: + +/friends/edit_do.bml.fellowfriends.head=Gemensamma vänner + +/friends/edit_do.bml.fellowfriends.text=Följande personer har dig som vän, och du kanske vill lägga till dem. Det här är för att du ska veta deras LiveJournal-namn, och du behöver inte lägga till dem om du inte vill. + +/friends/edit_do.bml.foreground=Förgrund + +/friends/edit_do.bml.friend=Vän + +/friends/edit_do.bml.hover=Peka med musen på en färg för att se dess namn + +/friends/edit_do.bml.name=Namn + +/friends/edit_do.bml.needmore=Om du vill lägga till så många vänner att de inte får plats nedan, spara ändringarna och gå tillbaka hit, så kan du lägga till fler. + +/friends/edit_do.bml.nofriends.head=Inga vänner? + +/friends/edit_do.bml.nofriends.text=Du har ännu inte uppgivit några vänner. Vi är säkra på att du har några! :) Skriv bara in deras LiveJournal-namn nedan... + +/friends/edit_do.bml.opt.delete=Radera? + +/friends/edit_do.bml.success.head=Avklarat + +/friends/edit_do.bml.success.text=Dina vänner har uppdaterades. Du kan titta på din nyligen uppdaterade vänsida här. + +/friends/edit_do.bml.textcolor=Textfärg: + +/friends/edit_do.bml.title=Ändra vänner + +/friends/edit_do.bml.user=Användare + +/friends/edit_do.bml.viewer=Färg-visare + +/friends/edit_do.bml.yourfriends.head=Dina vänner + +/friends/edit_do.bml.yourfriends.text=Du har dessa vänner: + +/friends/index.bml.security.custom=Med "anpassade" inlägg kan du specifiera vilka vängrupper kan se ditt inlägg. Men vissa klienter saknar förmågan att anpassa säkerhetsnivåer. + +/friends/index.bml.title=Vän-verktyg + +/friends/popwithfriends.bml.account_type=Tyvärr fungerar inte detta verktyg för din kontotyp. + +/friends/popwithfriends.bml.count=Antal + +/friends/popwithfriends.bml.intro=Många av dina vänner, men inte du, har dessa vänner. + +/friends/popwithfriends.bml.intro_own=Många av dina vänner har dessa vänner. Även dina vänner finns med i listan. + +/friends/popwithfriends.bml.no_users=Inga användare + +/friends/popwithfriends.bml.title=Populära användare bland dina vänner + +/friends/popwithfriends.bml.user=Användare + +/index.bml.about.joining=Medlemskap i sajten är gratis. Användare kan välja att uppgradera sina konton att få ytterliga funktioner. + +/index.bml.boldcreate=Skapa din egen LiveJournal! + +/index.bml.frank.image.alt=Frank, LiveJournals maskot. + +/index.bml.frank.logo="Bäääääh", säger Frank. + +/index.bml.learnmore.text=Var god läs våran funktionsöverblick. Övertygat?Skapa din egen LiveJournal! + +/index.bml.meta.desc=På LiveJournal.com kan du dela dina tankar med världen. + +/index.bml.meta.keywords=dagbok, dagbok på nätet, skriva dagbok, online-dagbok, webdagbok + +/interests.bml.add.added.head=Tillagd! + +/interests.bml.add.added.text=Detta intresse har lagts till på din lista. + +/interests.bml.add.btn.text=Lägg till [[interest]] + +/interests.bml.add.confirm.head=Bekräfta + +/interests.bml.add.confirm.text=För att lägga till [[interest]] som intresse, klicka på knappen nedan. + +/interests.bml.add.toomany.head=Tyvärr... + +/interests.bml.add.toomany.text=Du har redan [[maxinterests]] intressen angivna. + +/interests.bml.addint=Om du också är intresserad av detta och vill lägga till dig till denna lista, klicka här. + +/interests.bml.btn.switch=Byta + +/interests.bml.communities.head=Relevanta communities + +/interests.bml.communities.text=Följande communities är också intresserade av "[[interest]]". + +/interests.bml.count=Antal + +/interests.bml.enmasse.btn=Visa lista + +/interests.bml.enmasse.header=Lägg till/ta bort intressen + +/interests.bml.enmasse.intro=Ändra dina intressen baserad på dennes: + +/interests.bml.error.add.mustlogin=Du måste vara inloggad för att lägga till intressen på detta sätt. + +/interests.bml.error.enmasse.mustlogin=Du måste inloggad för att använda denna funktion. + +/interests.bml.error.enmasse.noaccess=Du verkar inte ha tillgång till journalen [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Intresseämnet hittades inte. + +/interests.bml.error.nointerests=Valda användaren finns inte eller har inga intressen. + +/interests.bml.findsim.searchwait=Obs: Sökningen kan ta flera sekunder. Ha tålamod. + +/interests.bml.findsim_do.account.notallowed=Tyvärr, din kontotyp tillåter inte användning av detta verktyg. + +/interests.bml.findsim_do.magic=Magiskt
    Index + +/interests.bml.findsim_do.magic.head=Magiskt Index? + +/interests.bml.findsim_do.magic.text=För varje matchande användare beräknas ett magiskt index, en sammanvägning av två faktorer: antalet gemensamma intressen, och några extra poäng för gemensamma, ovanliga intressen. + +/interests.bml.findsim_do.nomatch.head=Inga träffar + +/interests.bml.findsim_do.nomatch.text=Inga användare liknar [[user]]. + +/interests.bml.findsim_do.notdefined=Användare [[user]] har inga angivna intressen. + +/interests.bml.findsim_do.similar.head=Liknande användare + +/interests.bml.findsim_do.similar.text=Följande användare är mest lika [[user]] + +/interests.bml.finished.about=När du är färdig, tryck på "Spara ändringar" knappen nedan: + +/interests.bml.finished.header=Färdig? + +/interests.bml.finished.save_button=Spara förändringar + +/interests.bml.interest=Intressen + +/interests.bml.interested.btn.find=Hitta + +/interests.bml.interested.in=Hitta personer och intressegrupper intresserade av: + +/interests.bml.interests.findsim=Hitta användare med intressen som liknar dem för: + +/interests.bml.interests.head=Intressen + +/interests.bml.interests.text=Här är några kul saker du kan göra med intressen. + +/interests.bml.interests.viewpop=Visa populära intressen + +/interests.bml.login.enterinfo=Ange ditt användarnamn och lösenord att ändra dina intressen. + +/interests.bml.login.proceed=Fortsätta... + +/interests.bml.match=[[count]] träffar: + +/interests.bml.matches=[[count]] träffar: + +/interests.bml.morestuff=Mera kul saker kan hittas på intressesidan. + +/interests.bml.nointerests.text=Har du inga intressen angivna? Lägg till några genom att gå till Ändra personlig info & inställningar. + +/interests.bml.popular.head=Populära intressen + +/interests.bml.popular.text=Följande intressen är populärast. + +/interests.bml.results.added=Intressen som du valde är tillagda i din intresselista. + +/interests.bml.results.both=Intressen som du valde är tillagda i din intresselista, och de som du avvalde har tagits bort. + +/interests.bml.results.deleted=Intressen som du avvalde har tagits bort från din intresselista. + +/interests.bml.results.del_and_toomany=Intressen som du avvalde har tagits bort från din intresselista. Men du valde för många intressen att lägga till. Du får bara ha sammanlagt [[intcount]] intressen. Inga av de valda intressen var tillagda till din intresselista. Du kommer förmodligen att vilja försöka igen, med färre intressen valda. + +/interests.bml.results.goback=Du kommer förmodligen att vilja gå tillbaka till [[user]]s profil som du läste förut. + +/interests.bml.results.header=Resultat + +/interests.bml.results.message=Se din uppdaterade profilsida. + +/interests.bml.results.nothing=Du gjorde inga förändringar. + +/interests.bml.results.toomany=Du valde för många intressen att lägga till. Du får bara ha sammanlagt [[intcount]] intressen. Inga av de valda intressen var tillagda till din intresselista. Du kommer förmodligen att vilja försöka igen, med färre intressen valda. + +/interests.bml.title=Intressen + +/interests.bml.toomany.body=Det finns [[intcount]] personer och/eller communities som har det här som intresse. Ingen lista kommer visas. + +/interests.bml.toomany.head=Många träffar + +/interests.bml.users.head=Intresserade användare + +/interests.bml.users.text=Följande användare är också intresserade i [[interest]]. + +/legal/index.bml.about.header=Översikt + +/legal/index.bml.docs.coppa.about=Den amerikanska barnsäkerhetslagen (Children's Online Privacy Protection Act; COPPA) reglerar hur personuppgifter rörande eller lämnade av barn under tretton års ålder får samlas in eller användas på internet. Vår COPPA-sida förklarar hur vi ställer oss till denna lag, och sammanfattar hur COPPA-frågor ska hanteras. + +/legal/index.bml.docs.header=Dokument + +/legal/index.bml.docs.privacy.about=I Integritetspolicyn sammanfattar vi vilken information vi samlar in om våra medlemmar och hur vi använder den informationen. + +/legal/index.bml.title=Juridisk Information + +/legal/privacy.bml.title=Integritetspolicy + +/legal/tos.bml.title=Serviceavtal + +/login.bml.bindip.label=Bind till IP-adress + +/login.bml.bindip.no=Nej (fungerar med alla Internetleverantörer) + +/login.bml.bindip.yes=Ja (säkrare) + +/login.bml.error.mustenterusername=Du måste ange ett användarnamn. + +/login.bml.expire.btn.neverexpire=Sätt förfallotid till OÄNDLIG + +/login.bml.expire.btn.sessiononly=Sätt förfallotid till ENDAST SESSION + +/login.bml.expire.neverexpire.text=Din inloggning är oändlig, så om du använder en dator på en skola, ett bibliotek eller någon annanstans där andra människor har tillgång till datorn, kom ihåg att logga ut när du är klar! Eller ändra din inloggning till att förfalla när du stänger din browser: + +/login.bml.expire.sessiononly.text=Din inloggning kommer förfalla när du stänger din browser. Om den här är din egen dator och du är den enda som använder den, kan du sätta inloggningen till att aldrig förfalla: + +/login.bml.links.head=Länkar + +/login.bml.links.link1=Din vänsida. + +/login.bml.links.link2=Din att-göra-lista. + +/login.bml.loggedin.head=Inloggad! + +/login.bml.loggedin.text=Du är nu inloggad. + +/login.bml.login.btn.changeopts=Ändra inställningar + +/login.bml.login.btn.login=Logga in... + +/login.bml.login.expiration=Förfall: + +/login.bml.login.forget=Glömt? + +/login.bml.login.head=Logga in + +/login.bml.login.never=Aldrig + +/login.bml.login.otheropts=Andra inställningar: + +/login.bml.login.password=Lösenord: + +/login.bml.login.text1=För att logga in på [[sitename]], ange användarnamn och lösenord nedan. Nya användare: För att skapa ett konto, gå hit. + +/login.bml.login.text2=Du kan också ange när din inloggning kommer att förfalla. Standard-förvalet är att din inloggning förfaller då du stänger din browser, vilket fungerar bäst på offentliga datorer. Om du är den enda användaren på din dator och ingen annan har tillgång till den, kan du välja att ha en inloggning som aldrig förfaller. För mer information om detta och andra inloggningsurval, se Vad är möjligheterna när jag loggar in? + +/login.bml.login.text3=[[username]], du är nu inloggad i [[sitename]]. Om du vill, bläddra genom sajten med våran sajtkarta. + +/login.bml.login.username=Användarnamn: + +/login.bml.login.whenbrowsercloses=När browsern stängs + +/login.bml.logout.btn=Logga ut + +/login.bml.title=Logga in + +/login.bml.whylogin.benefit1=Du behöver inte längre ange användarnamn/lösenord någonstans på siten. + +/login.bml.whylogin.benefit2=Du får möjlighet att se dina vänners "skyddade" journalinlägg, om de gett dig tillträde till dem. + +/login.bml.whylogin.benefit3=Många funktioner är bara synliga och tillgängliga när du är inloggad. + +/login.bml.whylogin.head=Varför logga in? + +/login.bml.whylogin.text=Här är några av fördelarna med att vara inloggad: + +/logout.bml.already.head=Redan utloggad + +/logout.bml.already.text=Du är redan utloggad. + +/logout.bml.killall.btn=Avsluta alla mina sessioner + +/logout.bml.killall.head=Andra sessioner + +/logout.bml.killall.text=Du har andra aktiva sessioner på andra datorer. Vill du avsluta även dem, och inte bara den här? (Läsdenna FAQ:n för mer information.) + +/logout.bml.loggedout.already=Redan utloggad. + +/logout.bml.loggedout.head=Utloggad + +/logout.bml.loggedout.killedall=Alla dina sessioner har avslutats. + +/logout.bml.loggedout.success=Utloggad. + +/logout.bml.loggedout.text=Du är nu utloggad. + +/logout.bml.logout.btn=Logga ut + +/logout.bml.logout.head=Logga ut? + +/logout.bml.logout.text=Klicka på knappen nedan för att logga ut. + +/logout.bml.title=Logga ut + +/lostinfo.bml.btn.proceed=Fortsätt + +/lostinfo.bml.enter_email=Ange din e-postadress: + +/lostinfo.bml.enter_email_optional=E-postadress: (frivillig uppgift) + +/lostinfo.bml.enter_username=Ange ditt användarnamn: + +/lostinfo.bml.lostpassword.text=Om du har glömt ditt lösenord, ange ditt användarnamn och, eventuellt, den epostadress du vill ha ditt lösenord skickat till. Epostadressen måste vara en du tidigare har använt på LiveJournal och som du tidigare har fått bekräftad. Om du lämnar adressfältet tomt kommer lösenordet att skickas till din nuvarande epostadress. + +/lostinfo.bml.lostpassword.title=Har du glömt ditt lösenord? + +/lostinfo.bml.lostusername.text=Om du har glömt ditt användarnamn, ange din e-postadress, så skickar vi det till dig. + +/lostinfo.bml.lostusername.title=Har du glömt ditt användarnamn? + +/lostinfo.bml.title=Förlorad information + +/lostinfo_do.bml.error.no_usernames_for_email=Inget användarnamn hittat för denna epost adress: [[address]]. + +/lostinfo_do.bml.error1.text=Du använde aldrig den emailadressen med detta konto eller så var den aldrig validerad. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Det här är ett automatiskt genererat mail. Du behöver inte svara på det. *** + +Det här är en påminnelse från [[sitename]] om ditt lösenord. Ditt användarnamn och lösenord samt den e-postadress din journal är registrerad på står här nedanför. + + Användarnamn: [[username]] + Lösenord: [[password]] + E-postadress: [[emailadr]] + +. + +/lostinfo_do.bml.lostpasswordmail.part2=För att bekräfta din e-postadress, gå hit: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Någon från [[remoteip]] begärde denna information på webb-sidan. + +Om det inte var du som begärde att få ditt lösenord e-postat till dig, behöver du inte oroa dig. Det är ju trots allt du och inte någon annan som ser det här mailet. Det är möjligt att användaren som begärde att lösenordet skulle skickas ut har fel, och tror att han eller hon har rätt till det här användarnamnet. Det är också möjligt att någon stavade sitt användarnamn eller sin e-postadress fel. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Om du verkligen tror att ditt konto inte är säkert, läs http://www.livejournal.com/support/faqbrowse.bml?faqid=117 för att ta reda på hur du säkrar det. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Användbara länkar: + + Din LiveJournal: + [[journalurl]] + + Uppdatera din journal online: + [[updateurl]] + +Hälsningar, +LiveJournal-teamet + +[[rooturl]] + +. + +/lostinfo_do.bml.lostpasswordmail.subject=Förlorat lösenord + +/lostinfo_do.bml.password_mailed.text=Ditt lösenord har skickats. + +/lostinfo_do.bml.password_mailed.title=Lösenordet skickat! + +/lostinfo_do.bml.title=Förlorad information + +/lostinfo_do.bml.username_mailed.text=Ditt användarnamn har skickats. + +/lostinfo_do.bml.username_mailed.title=Användarnamn skickat! + +/manage/index.bml.communities.create.about=Skapa en ny intressegrupp + +/manage/links.bml.success=Dina länkar har sparats. + +/manage/pubkey.bml.successhead=Avklarat + +/modify.bml.title=Ändra journal + +/modify_do.bml.availablestyles.head=Tillgängliga stilar + +/modify_do.bml.availablestyles.userstyles=Användarstilar: + +/modify_do.bml.colortheme.about=Här kan du välja vilket färgtema du vill ha till de utseendeinställningar du gjort. Du kan också ange egna färger, om du inte tycker om de som finns att välja på. + +/modify_do.bml.colortheme.area.head=Användningsområde + +/modify_do.bml.colortheme.color.head1=Färg + +/modify_do.bml.colortheme.color.head2=(#rrggbb eller färgens namn) + +/modify_do.bml.colortheme.customcolors=Egna färger + +/modify_do.bml.colortheme.defaulttheme=Standardtema + +/modify_do.bml.colortheme.head=Färgtema + +/modify_do.bml.domainalias.about=Om du har ett domännamn registrerat (eller om du planerar att registrera ett) och vill att den domänen ska hänvisa till din LiveJournal, skriv in det här: + +/modify_do.bml.domainalias.domainname=Domännamn: + +/modify_do.bml.domainalias.example=Exempel: min-journal.com + +/modify_do.bml.domainalias.head=Domänalias + +/modify_do.bml.domainalias.helptext=För att detta skall fungera, måste du ordna så att ditt domännamns DNS pekar på samma IP-adress som [[sitename]]. För mer information, läs denna FAQ:n. + +/modify_do.bml.done.btn.savechanges=Spara ändringar + +/modify_do.bml.done.head=Klar? + +/modify_do.bml.done.text=När du är klar, klicka på "Spara ändringar" knappen nedanför... + +/modify_do.bml.error.dupdomainalias=En annan användare har redan registerat sig för att använda ditt angivna domän-alias. + +/modify_do.bml.error.stylenotavailable=En av stilarna du har valt är inte tillgänglig. Det är resultat av att någon raderat stilen, eller att du valt en du inte har rätt att välja. + +/modify_do.bml.friends.about=Här finns inställningar som styr hur din vänsida ser ut. + +/modify_do.bml.friends.head=Vännervy + +/modify_do.bml.friends.opt.usesharedpic.about=Denna inställning avgör vilken bild du ser på din vänsida när en användare postar i en delad journal eller i en intressegruppjournal. Om du klickar för här, kommer du att se intressegruppens ikon. Om du låter bli, kommer du att se ikonen för den person som postar inlägget. + +/modify_do.bml.friends.opt.usesharedpic.head=Använd delade journalers bilder istället för användarbilder + +/modify_do.bml.journaloptions.about=Härifrån kan du anpassa hur dina LiveJournal-sidor ser ut. Om du är riktigt nyfiken på hur allt fungerar, läs utvecklarinformationen. Annars antar vi att du nöjer dig med de grundläggande inställningarna nedanför: + +/modify_do.bml.journaloptions.head=Journalinställningar + +/modify_do.bml.journalstatus.about=Om du vill radera eller upphäva radering av din journal, gör du det här. När du raderat din journal har du 30 dagar på dig att upphäva raderingen, om du skulle ändra dig. Efter 30 dagar, kommer journalen att raderas permanent och därefter går den inte att få tillbaka på något sätt. + +/modify_do.bml.journalstatus.head=Journalaktiveringsstatus + +/modify_do.bml.journalstatus.select.activated=Aktiverad + +/modify_do.bml.journalstatus.select.deleted=Raderad + +/modify_do.bml.journalstatus.select.suspended=Avstängd + +/modify_do.bml.moodicons.about=När du postar journalinlägg kan du också ange ditt aktuella humör. Några användare har gjort uppsättningar av humörikoner som du kan välja mellan. Vill du inte ha några bilder bredvid ditt humör, välj "None". (Du behöver förstås inte alls använda humör-funktionen.) + +/modify_do.bml.moodicons.head=Humörikoner + +/modify_do.bml.moodicons.opt.forcefriends.about=Använd alltid humörteman för alla vänner på din vänsida. + +/modify_do.bml.moodicons.personal=Personliga teman: + +/modify_do.bml.moodicons.preview=förhandsgranska + +/modify_do.bml.moodicons.select=Välj humör-ikonsuppsättning: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Du kan gå förbi denna delen. detta hör till justering på mycket särkilda saker om din webbsidolayout. Läs utvecklarinformationen för fler detaljer. Observera också att åtsidosättning ändrar bara en eller två saker i en stil. Vill du åtsidosätta allting måste du skapa din egen stil. + +/modify_do.bml.overrides.box.head=Åtsidosättning: + +/modify_do.bml.overrides.head=Stil åtsidosättning + +/modify_do.bml.overrides.note=Notera att alla stil variabler inte kan bli åtsidosatta. Läs dokumentationen för fler detaljer.
    Var ocksÃ¥ medveten om att redigeringsförsök pÃ¥ dina Ã¥tsidosättningar med en tagg som inte tillÃ¥ts i dokumenthuvuden – t.ex. <DIV>, <SPAN>, <IMG>, och mÃ¥nga andra taggar – fÃ¥r sÃ¥dana taggar att tas bort. Dom enda HTML taggar som kan användas i *_HEAD Ã¥tsidosättningar är dom som är giltiga i huvudet pÃ¥ ett vanligt HTML dokument. Dessa taggar är endast <title>, <base>, <style>, <link>, och <meta>. + +/modify_do.bml.overrides.warning=HÄR SKRIVER DU INTE I DIN JOURNAL!! + +/modify_do.bml.pagelayoutstyle.about=Denna inställningen bestämmer hur din journal ser ut i skärmen. + +/modify_do.bml.pagelayoutstyle.head=Sidlayoutstil + +/modify_do.bml.pagelayoutstyle.warning=Din kontotyp tillÃ¥ter dig bara välja mellan ett begränsat antal stilar. + +/modify_do.bml.success.head=Avklarat + +/modify_do.bml.success.text=Dina journalinställningar har blivit uppdaterade. Du kan se din journal här. + +/paidaccounts/index.bml.costs.header=SÃ¥, hur mycket kostar det dÃ¥? + +/paidaccounts/index.bml.costs.rates=Kostnaderna är: + +/paidaccounts/index.bml.costs.rates.amount.header=Belopp + +/paidaccounts/index.bml.costs.rates.inexpensive=Det blir litet mera än $2/mÃ¥nad för Ã¥rsprenumrering. Det kommer knappast att panka ut dig. Det förargligaste blir nog att dra ut plÃ¥nboken, hitta kreditkortet och skriva in din information. + +/paidaccounts/index.bml.costs.rates.time.header=Tid + +/paidaccounts/index.bml.features.header=Vilka häftiga funktioner fÃ¥r jag dÃ¥? + +/paidaccounts/index.bml.title=Om betalda konton + +/paidaccounts/index.bml.whypay.argument<< +Nej, sÃ¥klart inte. Betala för webtjänster är irriterande, vi hÃ¥ller med. +Det är därför nästan alla LiveJournals funktioner är gratis. +För övrigt, om du är nöjd med den service du fÃ¥r, stöd oss och skaffa ett betalt konto. +. + +/paidaccounts/index.bml.whypay.header=MÃ¥ste jag betala för att använda LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads=Det kostar pengar att driva websiter (servrar, colocation och bandbredd), och det verkar bättre att betala för det än att tvinga pÃ¥ dig popup-banners och spamma dig med reklam. + +/paidaccounts/index.bml.your_username=ditt_användarnamn + +/paidaccounts/usepaypal.bml.delivery.badformat=Ogiltigt formaterat leverans datum. MÃ¥ste vara i formen yyyy-mm-dd eller yyyy-mm-dd hh:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Leveransdatum kan inte vara i dÃ¥tid. Lämna tomt för att leverera direkt. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Leveransdatum kan inte vara mer än en mÃ¥nad in i framtiden. + +/pay/index.bml.deliverydate.details=Format: yyyy-mm-dd hh:mm (GMT Tid)
    (anges inget fördröjs inte leveransen) + +/pay/index.bml.deliverydate.label=Leveransdatum: + +/pay/index.bml.gift.anonymous=Anonym gåva + +/press/staff.bml.back2=Tillbaka till presssidan + +/press/staff.bml.contact=Om du behöver kontakta oss, skriv ett e-brev till webmaster@livejournal.com (på engelska). + +/press/staff.bml.denisep.quip=Du får det nästa tisdag + +/press/staff.bml.lisa.title=Systemadministrator + +/press/staff.bml.ryanfitz.title=Betalningstjänster + +/press/staff.bml.sandy.title=Konto- och andra underhåll + +/press/staff.bml.whitaker.quip=Vad nu? + +/register.bml.email.body<< +Denna är bekräftelseposten du begärde. +Att färdiggöra kontobekräftelsen, folj denna länk: + + [[conflink]] + +Det är möjligt att du blir tvungen att kopiera länken till din browser. + +med vänlig hälsning, +[[sitename]] +[[sitelink]] +. + +/register.bml.new.header=Avklarat + +/register.bml.sent.header=Avklarat + +/register.bml.trans.header=Avklarat + +/rename/use.bml.heading.success=Avklarat + +/site/contract.bml.promise=Vi håller fast vid att vi kommer att: + +/site/contract.bml.promise.account=Visa hänsyn till statusen av varje konto + +/site/contract.bml.promise.ads=Förbli reklamfri + +/site/contract.bml.promise.community=Arbeta för samhället, med samhället + +/site/contract.bml.promisetoyou.header=Vårat löfte till Er + +/site/goat.bml.image.alt=Frank, LiveJournal maskoten. + +/site/goat.bml.image.caption="Bäää," säger Frank. + +/site/goat.bml.meet.body= + +/support/encodings.bml.groups.header=Jag kan inte redigera mina vänlistor med min klientprogram! + +/support/encodings.bml.groups.text=grupp redigeringssidan och använda ditt nuvarande klientprogram. p?> + +/support/encodings.bml.overview.header=Väd gäller här? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.text=Hjälpsidan. p?> + +/support/faqbrowse.bml.backfaq=Tillbaka till FAQ. + +/support/faqbrowse.bml.backsupport=Tillbaka till Support. + +/support/faqbrowse.bml.edit.faq=Redigera denna FAQ + +/support/faqbrowse.bml.error.nofaq=Den valda vanliga frågan/svaret finns inte. + +/support/faqbrowse.bml.lastupdated=Senast Uppdaterad: + +/support/faqbrowse.bml.title_cat=Vanliga frågor och svar - [[catname]] + +/support/faqbrowse.bml.title_num=vfs fråga #[[num]] + +/support/see_overrides.bml.error.nos1=Denna användaren invänder inte S1. + +/talkmulti.bml.deleted.body=Kommentarerna har raderats. Du kan se övriga kommentartrådet här. + +/talkmulti.bml.deleted.title=Kommentarer raderade + +/talkmulti.bml.error.comms_deleted=En av kommentarerna har raderats sedan du valde den. För säkerhetsskäl, vänligen gå tillbaka och försök igen. + +/talkmulti.bml.error.inconsistent_data=Angivna data är inkonsekventa. + +/talkmulti.bml.error.invalid=Felaktiga parametrar angivna. + +/talkmulti.bml.error.invalid_mode=Du valde inget att göra. Gå tillbaka och välj om du vill avskärma, oavskärma, eller ta bort kommentarerna. + +/talkmulti.bml.error.login=Du är inte inloggad. + +/talkmulti.bml.error.none_selected=Du har inte valt några kommentarer. + +/talkmulti.bml.error.privs.delete=Du är inte tillåten att radera dessa kommentarer. + +/talkmulti.bml.error.privs.screen=Du är inte tillåten att avskärma dessa kommentarer. + +/talkmulti.bml.error.privs.unscreen=Du är inte tillåten att oavskärma dessa kommentarer. + +/talkmulti.bml.screened.body=Kommentarerna har avskärmats. Du kan se dem här. + +/talkmulti.bml.screened.title=Kommentarer avskärmade + +/talkmulti.bml.title.delete=Radera flertalet kommentarer + +/talkpost.bml.allowedhtml=Tillåt HTML + +/talkpost.bml.error.cannotreplynopost=Du kan inte svara på ett inlägg som inte finns + +/talkpost.bml.error.nocommentsjournal=Användaren har stängt av kommentarer i sin journal. + +/talkpost.bml.error.nocommentspost=Användaren har stängt av kommentarer för detta inlägg. + +/talkpost.bml.error.noreplypost=Svar till inlägg inte funnet (raderat?) + +/talkpost.bml.error.noreply_deleted=Denna kommentar har raderats. Du kan inte svara på det. + +/talkpost.bml.error.noreply_screened=Denna kommentar är avskärmad och du har inte tillåtelse att se eller svara på den. + +/talkpost.bml.label.picturetouse= Bild att använda: + +/talkpost.bml.loganonip=Obs! Den här användaren har aktiverat loggning av IP-adresser för anonyma postare. + +/talkpost.bml.loginq=Logga in? + +/talkpost.bml.logyourip=Notera!Den här användaren loggar din IP-adress när du svarar. + +/talkpost.bml.nosubjecthtml=Ingen HTML är tillåten i subjektraden + +/talkpost.bml.opt.anonymous=Anonym + +/talkpost.bml.opt.defpic=(förval) + +/talkpost.bml.opt.friendsonly=- Den här användaren har tillåter bara icke-anonyma och vänner att svara. Du kan svara här endast om [[username]] har dig som vän. + +/talkpost.bml.opt.from=Från: + +/talkpost.bml.opt.ljuser=LiveJournal användare: + +/talkpost.bml.opt.loggedin=Inloggad användare: [[username]] + +/talkpost.bml.opt.message=Meddelande: + +/talkpost.bml.opt.noanonpost=- användaren tillåter inte anonym postning. + +/talkpost.bml.opt.noautoformat=Auto-formatera inte: + +/talkpost.bml.opt.noimage=Ingen bild + +/talkpost.bml.opt.preview=Förhandsgranska + +/talkpost.bml.opt.spellcheck=Stavningskontrollera inlägg före postning (på engelska) + +/talkpost.bml.opt.subject=Subjekt: + +/talkpost.bml.opt.submit=Skriv kommentar + +/talkpost.bml.paraformat=Stycket kommer automatiskt formateras (förvalt) + +/talkpost.bml.postresponse=Skriv en kommentar som svar: + +/talkpost.bml.title=Skriv kommentar + +/talkpost.bml.usermismatch<< +Du har skrivit in ett användarnamn, men avbeställt 'LiveJournal användare' inställningen. + +Antingen radera användarfältet eller välja aktuella postningsinställningen och försök igen. +. + +/talkpost.bml.warnscreened=Notera: Denna kommentar avskärmad. Att svara på den kommer automatiskt att oavskärma den och göra den synlig. + +/talkpost_do.bml.error.badpassword=Felaktigt lösenord för det angivna användarnamnet. Du kan få tillbaka ditt borttappade lösenord här. + +/talkpost_do.bml.error.badusername=Användaren du namngav finns inte på Livejournal. Du kan hitta ditt användarnamn här om du glömt det, eller så kan du svara "anonymt". + +/talkpost_do.bml.error.banned=Du har inte tillåtelse att posta i denna användarens journal. + +/talkpost_do.bml.error.blankmessage=Ditt meddelande var tomt. Skriv något i meddelandefältet. + +/talkpost_do.bml.error.confused_identity=Du angav ett användarnamn, men valde att posta anonymt eller som den aktuella inloggade användaren. Gå tillbaka och dig för vilket du vill använda. + +/talkpost_do.bml.error.deleted=Din journal har blivit borttagen. Du kan inte posta meddelanden. + +/talkpost_do.bml.error.friendsonly=Endast vänner till [[user]] får posta i denna journal. + +/talkpost_do.bml.error.lostcookie=Dina login cookies verkar ha försvunnit? + +/talkpost_do.bml.error.manybytes=Tyvärr, din kommentar av [[current]] överstiger det maximala antalet tecken av [[limit]]. Gå tillbaka, korta ner det och prova posta igen. + +/talkpost_do.bml.error.manychars=Tyvärr, din kommentar av [[current]] överstiger det maximala antalet tecken av [[limit]]. Gå tillbaka, korta ner det och prova posta igen. + +/talkpost_do.bml.error.mustlogin=Du måste vara inloggad eller använda användarnamn/lösenord för att svara på det här skyddade inlägget. + +/talkpost_do.bml.error.noanon=Du kan inte svara anonymt i den här personens journal. + +/talkpost_do.bml.error.noauth=Du har inte tillåtelse att svara på det här skyddade inlägget. + +/talkpost_do.bml.error.nocomments=Den här användaren har slagit av möjligheten att svara på det här inlägget. + +/talkpost_do.bml.error.noparent=Kan inte svara på en icke-existerande kommentar. + +/talkpost_do.bml.error.notafriend=Tyvärr, användare [[user]] listar dig inte som en vän, och de har angett "endast vänner" alternativet för vem som kan svara på deras journal. + +/talkpost_do.bml.error.nousername=Du angav inte ditt LiveJournal-användarnamn. Du kan välja att posta som "Anonym" om du inte har ett LiveJournal-konto. + +/talkpost_do.bml.error.noverify=Tyvärr, du är inte tillåten att posta kommentarer i andra personers journaler innan din epostadress har blivit verifierad. Om du tappat bort konfirmations-eposten för detta, kan du få det återsänt. + +/talkpost_do.bml.error.postshared=Du kan inte posta från ett delat- eller intressegruppkonto. Delade konton representerar en grupp av människor, inte en individuell person. + +/talkpost_do.bml.error.screened=Du har inte tillåtelse att svara på denna avskärmade kommentar. + +/talkpost_do.bml.error.suspended=Din journal har blivit avstängd. Du kan inte posta några meddelanden. + +/talkpost_do.bml.error.testacct=Test konton kan bara användas till testjournaler. + +/talkpost_do.bml.opt.preview=Förhandsgranska + +/talkpost_do.bml.preview=Nedan visas hur din kommentar kommer att se ut. Använd formuläret nedan för att göra ändringar. Eller, skicka det. + +/talkpost_do.bml.preview.subject=Ämne: + +/talkpost_do.bml.preview.submit=Skicka + +/talkpost_do.bml.preview.title=Förhandsgranska + +/talkpost_do.bml.success.loggedin=Du är nu inloggad. + +/talkpost_do.bml.success.message=Din kommentar har lagts till. Du kan läsa den genom att klicka här. + +/talkpost_do.bml.success.screened.comm=Din kommentar har blivit tillagd. Enligt inställningarna för denna intressegrupp, är den markerad som avskärmad, och kommer att vara synlig endast för dig och underhållsansvarige för intressegruppen tills dess att de väljer att oavskärma den. Du kan se din kommentar här. + +/talkpost_do.bml.success.screened.user=Din kommentar har blivit tillagd. Enligt inställningarna för denna journal, är den markerad som avskärmad, och kommer att vara synlig endast för dig och ägaren till journalen tills dess att de väljer att oavskärma den. Du kan se din kommentar här. + +/talkpost_do.bml.success.title=Avklarat + +/talkpost_do.bml.success.unscreened=Nu har den avskärmade kommentaren du svarat på blivit oavskärmad och är nu synlig. + +/talkpost_do.bml.title=Kommentar postats + +/talkpost_do.bml.title.preview=Förhandsgranska kommentar + +/talkread.bml.anonuser=(Anonym) + +/talkread.bml.confirm.action=Är du säker att du vill radera de valda kommentarerna? + +/talkread.bml.deletedpost=(Raderat inlägg) + +/talkread.bml.deleteduser=(Raderad användare: [[username]]) + +/talkread.bml.fromip=(från [[ip]]) + +/talkread.bml.noreplies=Inga svar + +/talkread.bml.nosubject=(inget ämne) + +/talkread.bml.replysuspended=(Svar från avstängd användare) + +/talkread.bml.select=Välj + +/talkread.bml.subjectdeleted=[raderad] + +/talkread.bml.talkmulti.delete=Radera + +/talkread.bml.talkmulti.submit=Verkställ + +/talkread.bml.talkmulti.unscreen=Oavskärma + +/talkread.bml.title=Läs kommentarer + +/talkscreen.bml.error.login=Du måste vara inloggad för att kunna hålla på med avskärmade kommentarer. + +/talkscreen.bml.error.privs.screen=Du har inte tillåtelse att oavskärma denna kommentar. + +/talkscreen.bml.error.privs.unscreen=Du är tillåten att oavskärma denna kommentar. + +/talkscreen.bml.screen.doit=Ja, avskärma denna kommentar. + +/talkscreen.bml.screen.sure.body=Är du säker på att du vill avskärma denna kommentar? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=Kommentaren har blivit avskärmad. + +/talkscreen.bml.screened.title=Avklarat + +/talkscreen.bml.unscreen.doit=Ja, oavskärma denna kommentar. + +/talkscreen.bml.unscreen.sure.body=Är du säker på att du vill oavskärma denna kommentar? + +/talkscreen.bml.unscreen.sure.title=Oavskärma denna kommentar? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=Kommentaren har blivit oavskärmad. + +/talkscreen.bml.unscreened.title=Avklarat + +/tools/emailmanage.bml.address.current.title=Nuvarande adress + +/tools/emailmanage.bml.address.old.text=Följande är en lista av emailadresserna som var använda med ditt konto, och tiden då de stängs av som primära emailadressen. Bocka in de som du vill radera. + +/tools/emailmanage.bml.address.old.title=Tidigare adress + +/tools/emailmanage.bml.delete_selected=Radera valda + +/tools/emailmanage.bml.desc.title=Beskrivning + +/tools/emailmanage.bml.log.deleted=Raderade: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Förändringar sparade + +/tools/emailmanage.bml.notvalidated.text=Att använda denna verktyg måste din nuvarande epostadress [[email]] bekräftas. Om du tappat bort konfirmations-eposten för detta, kan du få det återsänt. När du bekräftat epostadressen, kom tillbaka här. + +/tools/emailmanage.bml.notvalidated.title=Email inte bekräftad + +/tools/emailmanage.bml.title=Email underhåll + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Din lista med minnesvärda inlägg har uppdaterats + +/tools/memadd.bml.body.added.header=Avklarat + +/tools/memadd.bml.description=Beskrivning + +/tools/memadd.bml.description.text<< +Ge detta journal-inlägg en beskrivning så att du kan komma ihåg det. +För att radera detta inlägg från din lista med minnesvärda inlägg, lämna en blank beskrivning. +. + +/tools/memadd.bml.error.deleted.body=Journal-inlägget tidigare beskrivet som "[[desc]]" har blivit borttaget från din lista med minnesvärda inlägg. + +/tools/memadd.bml.error.deleted.title=Minne raderat + +/tools/memadd.bml.error.entry_deleted=Journa-inlägg existerar inte längre. Minne raderat. + +/tools/memadd.bml.error.fivekeywords=Endast 5 nyckelord/kategorier är tillåtna per minnesvärt inlägg. + +/tools/memadd.bml.error.invalid_security=Ogiltigt eller saknat säkerhetsval + +/tools/memadd.bml.error.login=Du måste inloggad för att använda denna funktion. Gå och logga in och du kommer att bli återförd hit sedan. + +/tools/memadd.bml.error.maxsize=Detta nyckelord överstiger den maximalt tillåtna storleken: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +För att lägga till ett journal-inlägg till din lista med minnen, måster du ge det en beskrivning. +För att ta bort ett minne, kan du editera det och ta bort beskrivningen, men du hade inte redan detta inlägg i dina minnen. +. + +/tools/memadd.bml.error.nodescription.title=Ingen beskrivning + +/tools/memadd.bml.form.reset=Återställ + +/tools/memadd.bml.form.submit=Skicka + +/tools/memadd.bml.keywords=Nyckelord + +/tools/memadd.bml.keywords.example=Exempel: Kul, Fånigt, Romantiskt + +/tools/memadd.bml.keywords.select=Eller, du kan och välja nyckelord du har använt tidigare: + +/tools/memadd.bml.keywords.text=Varför är detta inlägg minnesvärt? Ange inget eller upp till fem komma-separerade nyckelord eller kategorier så du enkelt kan hitta det igen. + +/tools/memadd.bml.login.enterinfo=Ange namn och lösenord för det konto du vill spara minnet till. + +/tools/memadd.bml.login.forgot.header=Glömt någonting? + +/tools/memadd.bml.login.forgot.recover=Om du glömt ditt användarnamn eller lösenord, återfå det här!. + +/tools/memadd.bml.multiple_selections=Håll ner 'Control' när du väljer nyckelord för att välja flera samtidigt. + +/tools/memadd.bml.security=Säkerhet: + +/tools/memadd.bml.security.friendsonly=Endast vänner + +/tools/memadd.bml.security.private=Privat + +/tools/memadd.bml.security.public=Allmänt + +/tools/memadd.bml.title=Lägg till minnen + +/tools/memadd.bml.title.added=Tillagd + +/tools/memadd.bml.title.add_memory=Tillägg minne + +/tools/memadd.bml.title.deleted=Borttaget + +/tools/memadd.bml.title.edit_memory=Ändra minnesvärt inlägg + +/tools/memadd.bml.whocansee<< +Vem kan se att du markerat detta inlägg som minnesvärt? +Vem som helst, endast personer du listar som en vän, eller bara du själv? +. + +/tools/memories.bml.back=Tillbaka + +/tools/memories.bml.body.keyword<< +[[keyword]] + +Följande är en lista av "[[keyword]]" journal inlägg som [[user]] funnit minnesvärda. +. + +/tools/memories.bml.body.list_categories<< + + +[[user]]
    har placerat minnesvärda inlägg i. p?> +. + +/tools/memories.bml.body.memorable=Följande är en lista av okategoriserade journal inlägg som [[user]] funnit minnesvärda. + +/tools/memories.bml.delete.deleted.head=Avklarat + +/tools/memories.bml.edit=ändra + +/tools/memories.bml.error.noentries.body<< +Detta kan bero på att:
      +
    1. användaren har inte definerat några minnesvärda händelser
    2. +
    3. användarens minnesvärda händelser är skyddade och du har inte tillgång för att se dem, eller
    4. +
    5. denna användare har inga minnen som matchar ditt sökta filter-kriterium
    +. + +/tools/memories.bml.error.noentries.title=Inga minnen hittade. + +/tools/memories.bml.filter.all=Alla minnen + +/tools/memories.bml.filter.other=Endast andra inlägg + +/tools/memories.bml.filter.own=Endast inlägg från '[[user]]' + +/tools/memories.bml.form.filter=Filtrera inlägg på: + +/tools/memories.bml.form.sort=ordna inlägg med: + +/tools/memories.bml.form.switch=Byt + +/tools/memories.bml.sort.description=Beskrivning + +/tools/memories.bml.sort.orderadded=Adderingsordning + +/tools/memories.bml.title.keyword=Minnesvärda [[keyword]] inlägg + +/tools/memories.bml.title.memorable=Minnesvärda inlägg + +/tools/memories.bml.uncategorized=Okategoriserad + +/update.bml.altpost=Journal att posta i: + +/update.bml.btn.update=Uppdatera journal + +/update.bml.currmood=Nuvarande humör: + +/update.bml.currmusic=Musik: + +/update.bml.date=Datum: + +/update.bml.default=förvalt + +/update.bml.defaultjournal=([[user]]) -- förvalt + +/update.bml.error.disabled=Ditt konotyp tillåter inte postning. + +/update.bml.error.login=Inloggninsfel: + +/update.bml.error.update=Inlägguppdateringsfel: + +/update.bml.event=Text: + +/update.bml.full=Full uppdateringssida + +/update.bml.localtime=Lokal tid: + +/update.bml.loggingin=Loggar in på server... + +/update.bml.noneother=Inget, ellar annat: + +/update.bml.note=Obs: Tid och datum ovan är från vår server. Justera den mot din lokala tid innan du postar inlägget. + +/update.bml.opt.backdate=Datumändra: + +/update.bml.opt.backdate.about=visas inte på vännervy + +/update.bml.opt.defpic=(förvalt) + +/update.bml.opt.nocomments=Inaktivera kommentarer: + +/update.bml.opt.noemail=Skicka inte kommentarer med epost: + +/update.bml.opt.noformat=Auto-formatera inte: + +/update.bml.opt.spellcheck=Stavningskontrollera inlägg före postning (på engelska) + +/update.bml.options=Valfria inställningar + +/update.bml.other=Andra: + +/update.bml.picture=Bild att använda: + +/update.bml.security.custom=Anpassa... + +/update.bml.security.friends=Vänner + +/update.bml.security.head=Säkerhetsnivå: + +/update.bml.security.private=Privat + +/update.bml.security.public=Offentlig + +/update.bml.servermsg=Också, servern har ett meddelande för dig: + +/update.bml.simple=Du använder enkla sidan. För flera urval, klicka här. + +/update.bml.spellchecked=Stavningskontrollerade posten: + +/update.bml.subject=Ämne:
    (valfritt)
    + +/update.bml.timeformat=24 timmars tid + +/update.bml.title=Uppdatera journal + +/update.bml.title.readonly=Skrivskyddat läge + +/update.bml.update.alternate=Vill du inte ladda ner en klient till din dator, eller om ett existerar inte för din dator, kan du använda denna sidan att uppdatera din LiveJournal. Den är ocksÃ¥ värdefull om du är pÃ¥ semester eller inte har din vanliga dator tillgänglig. Har du ett betalt konto, kan du uppdatera din journal med epost, spela in telefoninlägg utanför räckhÃ¥ll av en dator, eller skapa enkät i dina inlägg. + +/update.bml.update.head=Uppdatera din journal... + +/update.bml.update.success=Uppdateringen lyckats. Du kan titta pÃ¥ den uppdaterade journalen här. + +/update.bml.updating=Uppdaterar journalen... + +/uploadpic.bml.error.unsupportedtype=Filer av typ [[filetype]] stöds inte. Du kan ladda upp endast GIF, PNG, eller JPG filer. Nästan alla bild/foto programm kan förvandla din bild till en av giltiga typerna. + +/userinfo.bml.about.comm=Om: + +/userinfo.bml.about.user=Självbeskrivning: + +/userinfo.bml.body.leave=Du kan lämna intressegruppen när du vill. + +/userinfo.bml.comminfo.body=Nedan är information för "[[commname]]" intressegruppen pÃ¥ LiveJournal. + +/userinfo.bml.comminfo.name=Intressegruppinformation + +/userinfo.bml.date.never=Aldrig. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Felaktig användarnamn. + +/userinfo.bml.error.notloggedin=Vill du se din egen användarprofil, mÃ¥ste du logga in. + +/userinfo.bml.friendof.comm=Granskat av: + +/userinfo.bml.friendof.hidden=(gömd) + +/userinfo.bml.friendof.syndreadcount=Antal läsare + +/userinfo.bml.friendof.user=Vän till: + +/userinfo.bml.friends.comm=Medlemmar + +/userinfo.bml.friends.user=Vänner + +/userinfo.bml.label.adduser=Lägg till användare + +/userinfo.bml.label.birthdate=Födelsedatum: + +/userinfo.bml.label.clientsused=Använda Klienter: + +/userinfo.bml.label.comments=Kommentarer: + +/userinfo.bml.label.composted=Postade: [[num]] - + +/userinfo.bml.label.comreceived=Mottagna: [[num]] + +/userinfo.bml.label.datecreated=Skapad: + +/userinfo.bml.label.dateupdated=Uppdaterad: + +/userinfo.bml.label.email=Epost: + +/userinfo.bml.label.interests=Intressen + +/userinfo.bml.label.interests.modifyyours=ändra dina + +/userinfo.bml.label.interests.removesome=radera nÃ¥gra + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] intressen inte visade + +/userinfo.bml.label.journalentrs=Journalinlägg: + +/userinfo.bml.label.location=Plats: + +/userinfo.bml.label.memberof=Medlem i + +/userinfo.bml.label.memories=Minnen: + +/userinfo.bml.label.moredetails=(fler detaljer...) + +/userinfo.bml.label.msnusername=MSN användarnamn: + +/userinfo.bml.label.name=Namn: + +/userinfo.bml.label.nofriends=Inga listade. + +/userinfo.bml.label.post=Posta i "[[journal]]" + +/userinfo.bml.label.reqfinduser=Endast användare med 'finduser' tillstÃ¥nd kan leta efter andra användare med användarid. + +/userinfo.bml.label.searchjournal=Sök i denna journal + +/userinfo.bml.label.sendmessage=Skicka meddelande + +/userinfo.bml.label.shared=PostningstillgÃ¥ng: + +/userinfo.bml.label.supportpoints=Support poäng + +/userinfo.bml.label.textmessage=Textmeddelande: + +/userinfo.bml.label.todo=Att-göra lista + +/userinfo.bml.label.user=Användare: + +/userinfo.bml.label.viewfriends=Visa vänner + +/userinfo.bml.label.viewmembers=Visa medlemmar + +/userinfo.bml.label.website=Webbplats: + +/userinfo.bml.membership.body=Att gÃ¥ med i denna intressegrupp, klicka här. + +/userinfo.bml.memories.entries=[[count]] inlägg + +/userinfo.bml.memories.entry=[[count]] inlägg + +/userinfo.bml.monitor.comm=Granska intressegrupp + +/userinfo.bml.monitor.user=Lägg till denna användaren till din vänlista. + +/userinfo.bml.nonexist.body=Användarnamnet [[user]] är inte registrerat. + +/userinfo.bml.nonexist.name=Okänd användare + +/userinfo.bml.sendmessage.body=Skicka [[user]] ett textmeddelande
    till sin mobiltelefon/personsökare. + +/userinfo.bml.syn.last.never=Aldrig + +/userinfo.bml.syn.lastcheck=sista koll: + +/userinfo.bml.syn.nextcheck=nästa koll: + +/userinfo.bml.syn.parseerror=Felmeddelande: + +/userinfo.bml.tellafriend=Värva en vän! + +/userinfo.bml.timeupdate.dayago=IgÃ¥r + +/userinfo.bml.timeupdate.daysago=[[num]] dagar sedan + +/userinfo.bml.timeupdate.hourago=1 timme sedan + +/userinfo.bml.timeupdate.hoursago=[[num]] timmar sedan + +/userinfo.bml.timeupdate.minuteago=1 minut sedan + +/userinfo.bml.timeupdate.minutesago=[[num]] minuter sedan + +/userinfo.bml.timeupdate.secondago=1 sekund sedan + +/userinfo.bml.timeupdate.secondsago=[[num]] sekunder sedan + +/userinfo.bml.timeupdate.weekago=1 vecka sedan + +/userinfo.bml.timeupdate.weeksago=[[num]] veckor sedan + +/userinfo.bml.title=Användar info + +/userinfo.bml.title.communityinfo=Intressegrupp info + +/userinfo.bml.userinfo.body=Nedan är användarinformation om [[username]]. Är du denna användare kan du redigera din information (eller välja vilken information publiceras) pÃ¥ Personlig info sidan. + +/userinfo.bml.userinfo.name=Användarinformation + +BML.parse_multipart.parse=Fel i uppladdning + +BML.parse_multipart.toolarge=Uppladdning för stor. + +BML.parse_multipart.unknowntype=Okänd innehÃ¥llstyp + +btn.search=Sök + +crumb.acctfeatures=Funktioner för varje kontotyp + +crumb.download=Ladda ner en klient + +crumb.siteopts=Bläddringsinställningar + +date.day.friday.long=fredag + +date.day.friday.short=fr + +date.day.monday.long=mÃ¥ndag + +date.day.monday.short=mÃ¥ + +date.day.saturday.long=l + +date.day.saturday.short=lö + +date.day.sunday.long=söndag + +date.day.sunday.short=sö + +date.day.thursday.long=torsdag + +date.day.thursday.short=to + +date.day.tuesday.long=tisdag + +date.day.tuesday.short=ti + +date.day.wednesday.long=onsdag + +date.day.wednesday.short=on + +date.month.april.long=april + +date.month.april.short=apr + +date.month.august.long=augusti + +date.month.august.short=aug + +date.month.december.long=december + +date.month.december.short=dec + +date.month.february.long=februari + +date.month.february.short=feb + +date.month.january.long=januari + +date.month.january.short=jan + +date.month.july.long=juli + +date.month.july.short=juli + +date.month.june.long=juni + +date.month.june.short=juni + +date.month.march.long=mars + +date.month.march.short=mars + +date.month.may.long=maj + +date.month.may.short=maj + +date.month.november.long=november + +date.month.november.short=nov + +date.month.october.long=oktober + +date.month.october.short=okt + +date.month.september.long=september + +date.month.september.short=sept + +dystopia.btn.login=LOGIN + +dystopia.hello_anonymous=Välkommen till LiveJournal! + +dystopia.hello_loggedin=Hej, [[username]]! + +dystopia.nav.createjournal=Skapa en Journal + +dystopia.nav.developer=UtvecklaromrÃ¥de + +dystopia.nav.download=Hämta + +dystopia.nav.editentries=Ändra Inlägg + +dystopia.nav.editfriends=Dina vänner + +dystopia.nav.editpassword=Ditt lösenord + +dystopia.nav.editpics=Dina bilder + +dystopia.nav.editstyle=Ändra stil + +dystopia.nav.faq=FrÃ¥gor & svar + +dystopia.nav.findcomm=Gruppvis + +dystopia.nav.finddir=Katalogsökning + +dystopia.nav.findint=Intressevis + +dystopia.nav.findrandom=Slumpvis + +dystopia.nav.findregion=Regionsvis + +dystopia.nav.home=Hem + +dystopia.nav.journalcalendar=Kalender + +dystopia.nav.journalfriends=Vänner + +dystopia.nav.journalinfo=Användarinfo + +dystopia.nav.journalrecent=Aktuella inlägg + +dystopia.nav.legalprivacy=Integritetspolicy + +dystopia.nav.legaltos=Användaravtal + +dystopia.nav.login=Logga in + +dystopia.nav.logout=Logga ut + +dystopia.nav.lostinfo=Glömt lösenordet? + +dystopia.nav.memories=Minnen + +dystopia.nav.modifyjournal=Ändra journal + +dystopia.nav.news=Nyheter + +dystopia.nav.paidaccts=Betalande användare + +dystopia.nav.paymentarea=Betalningssida + +dystopia.nav.personalinfo=Personlig info + +dystopia.nav.sitemap=Sajtkarta + +dystopia.nav.siteopts=Bläddringsurval + +dystopia.nav.support=FrÃ¥gor? + +dystopia.nav.updatejournal=Uppdatera + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=135 + +dystopia.navhead.findusers=Hitta användare + +dystopia.navhead.help=Hjälp & Support + +dystopia.navhead.journal=Din journal + +dystopia.navhead.legal=Juridisk information + +dystopia.navhead.settings=Dina inställningar + +dystopia.navhead.welcome=Välkommen! + +dystopia.search.icq=ICQ-nummer + +dystopia.search.int=Intressevis + +dystopia.search.msn=MSN Användarnamn + +dystopia.search.region=Regionsvis + +dystopia.searchlj=Sök LiveJournal: + +Email=E-post + +email.newacct.body<< +Gratulerar! Nu har du ett nytt Livejournalkonto! + +Att göra färdigt journalskapelsen och verifiera ditt epostadress, gÃ¥ hit: + + [[regurl]] + +URL:en till din nya journal är: + + [[siteroot]]/users/[[username]]/ + +och: + + [[siteroot]]/~[[username]]/ + +Nedan visas ditt livejournal användarnamn och lösenord: + + användarnamn: [[username]] + lösenord: [[password]] + +Du kan gÃ¥ pÃ¥ [[siteroot]]/ att komma fram till ditt konto, skapa nya journalinlägg, och ändra dina journalanpassningar, men vi rekommenderarar att du laddar ner en LiveJournal klient. Det är enklaste sättet att uppdatera din journal, och det finns klienter till mÃ¥nga olika datorer! Hämta en pÃ¥ : [[siiteroot]]/download/ + +Att börja pÃ¥ LiveJournal kan bli svÃ¥rt när du inte känner till nÃ¥gon. Läs http://newbies.livejournal.com att fÃ¥ klipska, hjälpsamma rÃ¥d... med litet tur dröjer det inte länge tills du proffs pÃ¥ LiveJournal! + +Vi hoppas att du fÃ¥r lika mycket nöje frÃ¥n LiveJournal som vi fÃ¥r frÃ¥n att ge dig tillgÃ¥ng till den. Har du frÃ¥gor om hur man använder LiveJournal, var god besök supportsidan: + + [[siteroot]]/support/ + +Där finner du svar pÃ¥ nästan alla frÃ¥gor som kan ställas om LiveJournal. + +VÃ¥rat mÃ¥l är att göra LiveJournal totalt häftig... om vi kan göra nÃ¥got att det blir enklare, tjänligare, mer anpassningsbar, eller vadsomhelst... lÃ¥t oss bara veta. Vi driver inte sajten att tjäna pengar. Vi är ingen dotcomföretag betald med riskvilligt kapital som hoppas pÃ¥ IPO... sajten drivs endast av dem som använder den. LÃ¥t oss veta vad du vill fÃ¥ ut frÃ¥n den. + +Har du frÃ¥gor, fÃ¥r man vanligen svar frÃ¥n supportgruppen inom ett dygn. + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Välkommen till LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Fel + +error.badpassword=Felaktigt lösenord. + +error.dberror=Ett databasfel har uppstÃ¥tt: + +error.deleted.name=Raderad + +error.deleted.text=Denna journal har blivit raderad. Om du är [[user]], har du en period av 30 dagar frÃ¥n och med dagen för radering att Ã¥terta journalen. Efter 30 dagar kommer vi att radera allt innehÃ¥ll permanent frÃ¥n vÃ¥ra servrar. + +error.deleted.title=Raderat konto + +error.invalidauth=Du kan inte bekräftas som specifierade användaren. + +error.ipbanned=Din IP-adress är för tillfället bannlyst för att ha övergÃ¥tt inloggningsfelfrekvensen. + +error.malformeduser=Felaktigt användarnamn. + +error.nobutton=Ingen knapp tryckt? + +error.nodb=Databasen är tillfälligt otillgänglig. + +error.nodbmaintenance=Denna delen av databasen är tillfälligt nere för underhÃ¥ll. Prova igen om ett par minuter. + +error.noentry=Finns inget sÃ¥dant journal inlägg. + +error.nojournal=Okänd journal + +error.noremote=Du mÃ¥ste logga in att använda denna sidan. + +error.procrequest=Det uppkom ett fel dÃ¥ din begäran behandlades. + +error.purged.name=Raderad + +error.purged.text=Denna journal har blivit raderad och bortrensad. + +error.purged.title=Bortrensat konto + +error.suspended.name=Avstängd. + +error.suspended.text=Denna journal har antingen blivit temporärt eller permanent avstängd. Är du [[user]] var god läs vanliga frÃ¥gor och svar uppslagsidan Mitt konto har avstängts! Hur fÃ¥r jag det tillbaka? för mer information. OBS: Att försäkra vÃ¥ra användares hemlighet, kan [[sitename]] inte diskutera själen för avstängning med nÃ¥gon annan än kontots ägare. + +error.suspended.title=Avstängt konto. + +error.tempdisabled=Detta konto är temporärt obrukbart. + +error.unknownmode=Okänt läge. + +error.usernameinvalid=Användarnamn innehÃ¥ller ogiltitiga tecken. + +error.usernamelong=Användarnamn är för lÃ¥ngt, 15 tecken är max. + +error.username_notfound=Användarnamnet inte hittat. + +Help=Hjälp + +label.security.custom=Egen... + +label.security.friends=Vänner + +label.security.head=SäkerhetsnivÃ¥: + +label.security.private=Privat + +label.security.public=Publik + +label.switch.button=Byt + +label.switch.header=Byt journal + +label.switch.workwith=Arbeta med journal: + +langname.be=Vitryska + +langname.da=Danska + +langname.de=Tyska + +langname.en=Engelska + +langname.en_GB=Engelska + +langname.en_LJ=Engelska + +langname.es=Spanska + +langname.et=Esntiska + +langname.fi=Finska + +langname.fr=Franska + +langname.ga=Irlänska + +langname.gd=Gaeliska + +langname.he=Hebreiska + +langname.hu=Ungerska + +langname.is=Islänska + +langname.it=Italienska + +langname.ja=Japanska + +langname.lv=Lettiska + +langname.ms=Malajiska + +langname.nb=Norska BokmÃ¥l + +langname.nl=Hollänska + +langname.nn=Nynorska + +langname.pl=Polska + +langname.pt=Portugisiska + +langname.ru=Ryska + +langname.sv=Svenska + +langname.tr=Turkiska + +langname.zh=Förenklad Kinesiska + +ljcom.account.free=Gratiskonto + +ljcom.accounttype=Kontotyp + +ljcom.badpass.email=Ditt lösenord kan inte vara baserat pÃ¥ din epost adress. + +ljcom.badpass.realname=Ditt löseord kan inte vara baserat pÃ¥ ditt riktiga namn. + +ljcom.badpass.username=Ditt lösenord kan inte vara baserat pÃ¥ ditt användarnamn. + +ljcom.meetup.moreinfo=(Mer information) + +ljcom.userinfo.accounttype=Kontotyp + +ljcom.userinfo.types.free=Gratiskonto + +ljcom.userinfo.types.permanent=Permanent konto + +ljlib.pageofpages=Sida [[page]] av [[total]] + +lostinfo.head=Glömt nÃ¥gonting? + +lostinfo.text=Om du tappat bort användarnamn eller lösenord, Ã¥terfÃ¥ det här. + +lynx.nav.siteopts=Bläddringsurval + +Password=Lösenord + +password.max30=Lösenord bör inte vara längre än 30 tecken. + +portal.bdays.count.des=Vanligen visas de 5 vännerna med de närmsta födelsedagarna. + +portal.bdays.count.name=Födelsedagar att visa + +portal.bdays.portalname=Födelsedagar + +portal.bdays.portaltitle=Födelsedagar + +portal.goat.name=Sajtmaskot + +portal.goattext.des=Vad vill du ha din bock säga? Det enda som egentliga bockar säger är 'bäää', men du kan lÃ¥tsas att bocken säger nÃ¥got annat om du verkligen vill det. + +portal.goattext.name=Bocktext + +portal.login.portalname=Loginfält + +portal.memories.entriesnoun=inlägg + +portal.memories.entrynoun=inlägg + +portal.memories.portalname=Minnesvärda inlägg + +portal.memories.portaltitle=Minnesvärda inlägg + +portal.ministats.active=Aktiv: + +portal.ministats.title=Användar statistik + +portal.newtolj.name=webbplatslänkar + +portal.popfaq.portalname=10 mest-lästa vanliga frÃ¥gor och svar + +portal.popfaq.portaltitle=10 mest-lästa vanliga frÃ¥gor och svar + +portal.randuser.count.des=Vanligen är 1 slumpvald användare visad, men du kan fÃ¥ upp till 10 listade i smala kolumner, eller 5 lodrätt i en bred kolumn + +portal.randuser.count.name=Antalet slumpvalda användare att visa + +portal.randuser.error.tableempty=Det finns inga slumpvalda användare. Kontakta underhÃ¥llare. + +portal.randuser.hidename.des=Vanligen är slumpvalda användarnamnet visat. Välja detta att ta bort det. + +portal.randuser.hidename.name=Dölj namn + +portal.randuser.hidepic.des=Vanligen visas en slumpvald bild, om en finns till. Ibocka denna att ta bort den. + +portal.randuser.hidepic.name=Dölj användarbild + +portal.randuser.portalname=Slumpvald användare + +portal.randuser.portaltitle=Slumpvald användare + +portal.randuser.portaltitleplural=Slumpvalda användare + +portal.recent.error.noentries=Tyvärr, inga inlägg. + +portal.recent.error.userstatus=Användaren har raderat eller avstängt deras konto. + +portal.recent.items.description=Vanligen är endast det nyaste inlägget visat. + +portal.recent.items.name=Saker att visa + +portal.recent.journal.description=FrÃ¥n vilken journal vill du se de nyaste inläggen? + +portal.recent.nosubject=(Inget ämne) + +portal.recent.permlink=Länk + +portal.recent.portalname=Nytt inläggsvy + +portal.recent.portaltitle=Aktuell inlägg ruta + +portal.recent.showtext.description=Vanligen visas endast ämnen. + +portal.recent.showtext.name=Inkludera text + +portal.stats.journalentyest=GÃ¥rdagens journalinlägg + +portal.stats.portalname=Sajtstatistik + +portal.stats.portaltitle=Statistik + +portal.stats.totalusers=Antalet användare + +portal.update.mode.simple=Enkel + +portal.update.portalname=Journaluppdatering + +portal.update.portaltitle=Uppdatera din journal + +protocol.bad_password=Ditt lösenord är för lätt att gissa. Vi rekommenderar att du byter det, annars riskerar du att fÃ¥ din journal "kapad". Besök [[siteroot]]/changepassword.bml för att ändra ditt lösenord. + +protocol.hello_test=Hejsan Testkonto! + +protocol.mail_bouncing=Du använder en ogiltig e-postadress. All e-post som vi försöker att skicka dig studsar tillbaka. Vi fordrar en giltig e-postadress att fortsätta använda [[sitename]]. Läs [[siteroot]]/support/faqbrowse.bml?faqid=19 att se hur man ändrar e-postadress. + +protocol.modpost=Ditt inlägg är nu i modereringskön. Det blir godkänt eller avslagit av en av intressegruppsmodererarna. + +protocol.must_revalidate=Du mÃ¥ste bekräfta din nya epost adress. Din gamla epost adress var bekräftad men eftersom du har ändrat mÃ¥ste du bekräfta den nya. Om du inte bekräftar din nya adress kommer du inte kunna utnyttja alla funktioner pÃ¥ [[sitename]]. Besök [[siteroot]]/support/faqbrowse.bml?faqid=11 för mer information. + +protocol.not_validated=Din epostadress har inte bekräftats. Du fÃ¥r fortsätta att använda [[sitename]], men om du bekräftar inte din adress, kommer du att inte fÃ¥ tillgÃ¥ng till alla funktioner pÃ¥ LiveJournal. Se instruktionerna som skickades när du skapade din journal, eller läs [[siteroot]]/support/faqbrowse.bml?faqid=11 för mer information. + +protocol.old_win32_client=Det finns mycket nyare windows LiveJournal-klienter tillgängliga, och vi föreslÃ¥r att du uppdaterar. Se [[siteroot]]/download/ att nerladda en nyare klient. + +protocol.readonly=Ditt konto är tillfälligt endast läsbar. Vissa funktioner kommer att inte fungera pÃ¥ nÃ¥gra minuter. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Tyvärr. + +talk.anonwrote=NÃ¥gon skrev, + +talk.anonwrote_comm=NÃ¥gon skrev i [[commlink]], + +talk.btn.preview=Förhandsgranska + +talk.commentpermlink=länk + +talk.commentpost=Kommentera + +talk.commentsread=Läs kommentarer + +talk.curname_Mood=Humör: + +talk.curname_Music=Lyssnar pÃ¥: + +talk.error.bogusargs=Felaktiga argument + +talk.error.comm_deleted=Kommentaren har raderats. + +talk.error.deleted=Denna journal är raderad. + +talk.error.deleted.title=Raderad. + +talk.error.mustlogin=Du mÃ¥ste vara inloggad för att kunna läsa det här skyddade inlägget. + +talk.error.nocomment=Kommentaren existerar inte. + +talk.error.noentry=Inget sÃ¥nt inlägg. + +talk.error.nojournal=Fel: kunde inte hitta journal genom argument. + +talk.error.nosuchjournal=Det finns ingen sÃ¥dan journal + +talk.error.notauthorised=Du är inte authoriserad att se detta skyddade inlägg. + +talk.error.suspended=Denna journal/postare är avstängd. + +talk.error.suspended.title=Avstängd + +talk.parentlink=FöregÃ¥ende + +talk.readsimilar=Läs liknande journalinlägg: + +talk.replytothis=Skriv ett svar + +talk.somebodywrote=[[realname]] ([[userlink]]) skrev, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) skrev i [[commlink]], + +talk.spellcheck=Stavningskontroll under förhandsgranskning + +talk.threadlink=TrÃ¥d + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_swedish + +Username=Användarnamn + +userpic.inactive=Avstängt + +xcolibur.greeting.anon=Välkommen till LiveJournal! + +xcolibur.greeting.logged_in=Välkommen [[name]]! [[logout]] + +xcolibur.login=Logga in? + +xcolibur.logout=Logga ut? + +xcolibur.nav.about=Om + +xcolibur.nav.about.download=Nerladda + +xcolibur.nav.about.general=Allmän information + +xcolibur.nav.about.paidaccounts=Betalda konton + +xcolibur.nav.about.sitenews=Site Nyheter + +xcolibur.nav.about.stats=Statistik + +xcolibur.nav.footer.sitemap=Sajtkarta + +xcolibur.nav.help=Hjälp + +xcolibur.nav.help.ask=Ställa en frÃ¥ga + +xcolibur.nav.help.contact=Kontaktinformation + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Förlorat lösenord + +xcolibur.nav.home=Hem + +xcolibur.nav.journal.archive=Arkiv + +xcolibur.nav.journal.edit.entries=Redigera Inlägg + +xcolibur.nav.journal.friends=Vänner + +xcolibur.nav.journal.memories=Minnen + +xcolibur.nav.journal.recent=Senaste + +xcolibur.nav.journal.update=Uppdatera + +xcolibur.nav.manage=UnderhÃ¥lla + +xcolibur.nav.manage.community=Intressegrupper + +xcolibur.nav.manage.customize=Anpassa + +xcolibur.nav.manage.entries=Inlägg + +xcolibur.nav.manage.friends=Vänner + +xcolibur.nav.manage.password=Lösenord + +xcolibur.nav.manage.pics=Användarbilder + +xcolibur.nav.search=Sök + +xcolibur.nav.search.directory.search=Avancerat + +xcolibur.nav.search.interests=Intressen + +xcolibur.nav.search.random=Slumpvis + +xcolibur.nav.siteopts=Bläddringsurval + +xcolibur.nav.title=Navigera: + +xcolibur.nav.welcome=Välkommen + +xcolibur.nav.welcome.create=Skapa konto + +xcolibur.nav.welcome.login=Logga in + +xcolibur.nav.welcome.update=Uppdatera din journal + +xcolibur.search=Sök: + +xcolibur.search.category=Kategori + +xcolibur.search.icq=ICQ UIN + +xcolibur.search.int=Intresse + +xcolibur.search.msn=MSN Användarnamn + +xcolibur.upgrade=Uppgradera ditt konto + diff --git a/ljcom/bin/upgrading/text-local.dat b/ljcom/bin/upgrading/text-local.dat new file mode 100644 index 0000000..dc0ee26 --- /dev/null +++ b/ljcom/bin/upgrading/text-local.dat @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +domain:100:faq +domain:101:journal/news + +# EnglishLJ is child of English for general domain: +lang:100:en_LJ:English (LJ):sim:en +langdomain:en_LJ:general + +# EnglishLJ is root of FAQ & news journal: +langdomain:en_LJ:faq:1 +langdomain:en_LJ:journal/news:1 + +# German is child of EnglishLJ for all domains: +lang:101:de:German:diff:en_LJ +langdomain:de:general +langdomain:de:journal/news +langdomain:de:faq + +# Danish +lang:102:da:Danish:diff:en_LJ +langdomain:da:general +langdomain:da:journal/news +langdomain:da:faq + +# Spanish +lang:103:es:Spanish:diff:en_LJ +langdomain:es:general +langdomain:es:journal/news +langdomain:es:faq + +# French +lang:104:fr:French:diff:en_LJ +langdomain:fr:general +langdomain:fr:journal/news +langdomain:fr:faq + +# Japanese +lang:105:ja:Japanese:diff:en_LJ +langdomain:ja:general +langdomain:ja:journal/news +langdomain:ja:faq + +# Russian +lang:106:ru:Russian:diff:en_LJ +langdomain:ru:general +langdomain:ru:journal/news +langdomain:ru:faq + +# Esperanto +lang:107:eo:Esperanto:diff:en_LJ +langdomain:eo:general +langdomain:eo:journal/news +langdomain:eo:faq + +# Hebrew +lang:108:he:Hebrew:diff:en_LJ +langdomain:he:general +langdomain:he:journal/news +langdomain:he:faq + +# Norwegian BokmÃ¥l +lang:109:nb:Norwegian BokmÃ¥l:diff:en_LJ +langdomain:nb:general +langdomain:nb:journal/news +langdomain:nb:faq + +# Norwegian Nynorsk +lang:110:nn:Norwegian Nynorsk:diff:en_LJ +langdomain:nn:general +langdomain:nn:journal/news +langdomain:nn:faq + +# Dutch +lang:111:nl:Dutch:diff:en_LJ +langdomain:nl:general +langdomain:nl:journal/news +langdomain:nl:faq + +# Irish +lang:112:ga:Irish:diff:en_LJ +langdomain:ga:general +langdomain:ga:journal/news +langdomain:ga:faq + +# Icelandic +lang:113:is:Icelandic:diff:en_LJ +langdomain:is:general +langdomain:is:journal/news +langdomain:is:faq + +# European Portuguese +lang:114:pt:Portuguese:diff:en_LJ +langdomain:pt:general +langdomain:pt:journal/news +langdomain:pt:faq + +# Swedish +lang:115:sv:Swedish:diff:en_LJ +langdomain:sv:general +langdomain:sv:journal/news +langdomain:sv:faq + +# Polish +lang:116:pl:Polish:diff:en_LJ +langdomain:pl:general +langdomain:pl:journal/news +langdomain:pl:faq + +# Finnish +lang:117:fi:Finnish:diff:en_LJ +langdomain:fi:general +langdomain:fi:journal/news +langdomain:fi:faq + +# English - UK +lang:118:en_GB:English (UK):sim:en_LJ +langdomain:en_GB:general +langdomain:en_GB:journal/news +langdomain:en_GB:faq + +# Hungarian +lang:119:hu:Hungarian:diff:en_LJ +langdomain:hu:general +langdomain:hu:journal/news +langdomain:hu:faq + +# Malay +lang:120:ms:Malay:diff:en_LJ +langdomain:ms:general +langdomain:ms:journal/news +langdomain:ms:faq + +# Chinese Simplified +lang:121:zh:Chinese (Simplified):diff:en_LJ +langdomain:zh:general +langdomain:zh:journal/news +langdomain:zh:faq + +# Belarusian +lang:122:be:Belarusian:diff:en_LJ +langdomain:be:general +langdomain:be:journal/news +langdomain:be:faq + +# Italian +lang:123:it:Italian:diff:en_LJ +langdomain:it:general +langdomain:it:journal/news +langdomain:it:faq + +# Latvian +lang:124:lv:Latvian:diff:en_LJ +langdomain:lv:general +langdomain:lv:journal/news +langdomain:lv:faq + +# Greek +lang:125:gr:Greek:diff:en_LJ +langdomain:gr:general +langdomain:gr:journal/news +langdomain:gr:faq + +# Turkish +lang:126:tr:Turkish:diff:en_LJ +langdomain:tr:general +langdomain:tr:journal/news +langdomain:tr:faq + +# Chinese Traditional +lang:127:zh_TR:Chinese (Traditional):diff:zh +langdomain:zh_TR:general +langdomain:zh_TR:journal/news +langdomain:zh_TR:faq + +# Latin +lang:128:la:Latin:diff:en_LJ +langdomain:la:general +langdomain:la:journal/news +langdomain:la:faq + +# Estonian +lang:129:et:Estonian:diff:en_LJ +langdomain:et:general +langdomain:et:journal/news +langdomain:et:faq + +# Brazilian Portuguese +lang:130:pt_BR:Brazilian Portuguese:diff:pt +langdomain:pt_BR:general +langdomain:pt_BR:journal/news +langdomain:pt_BR:faq + +# Ukrainian +lang:131:uk:Ukrainian:diff:en_LJ +langdomain:uk:general +langdomain:uk:journal/news +langdomain:uk:faq + +# Lithuanian +lang:132:lt:Lithuanian:diff:en_LJ +langdomain:lt:general +langdomain:lt:journal/news +langdomain:lt:faq + +# Hindi +lang:133:hi:Hindi:diff:en_LJ +langdomain:hi:general +langdomain:hi:journal/news +langdomain:hi:faq + +# Basque +lang:134:eu:Basque:diff:en_LJ +langdomain:eu:general +langdomain:eu:journal/news +langdomain:eu:faq + +# Afrikaans +lang:135:af:Afrikaans:diff:en_LJ +langdomain:af:general +langdomain:af:journal/news +langdomain:af:faq diff --git a/ljcom/bin/upgrading/tr.dat b/ljcom/bin/upgrading/tr.dat new file mode 100644 index 0000000..29f1f5b --- /dev/null +++ b/ljcom/bin/upgrading/tr.dat @@ -0,0 +1,1742 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Burada günlüğünüzü kapattırabilir veya yeniden açabilirsiniz. Günlüğünüzü sildikten sonra fikrinizi deÄŸiÅŸtirirseniz, yeniden açmanız için 30 gün süreniz bulunmaktadır. 30 gün geçtikten sonra, günlüğünüz tamamen silinecek ve bu iÅŸlemin geri dönüşü olmayacaktır. + +/accountstatus.bml.journalstatus.head=Günlüğün Faaliyet Durumu + +/accountstatus.bml.journalstatus.select.activated=Faal + +/accountstatus.bml.journalstatus.select.deleted=SilinmiÅŸ + +/accountstatus.bml.journalstatus.select.head=Durum: + +/accountstatus.bml.journalstatus.select.suspended=Askıda + +/accountstatus.bml.title=Hesabın Durumu + +/allpics.bml.current=Mevcut Resimler + +/allpics.bml.default=Varsayılan + +/allpics.bml.edit2=Resimlerinizin anahtar sözcüklerini belirleyebilir ya da yeni bir resim yükleyebilirsiniz. + +/allpics.bml.error.noparam=Yeni bir kullanıcı parametresi tanımlamalısınız. + +/allpics.bml.keywords=Anahtar sözcükler: + +/allpics.bml.nopics.text.other=Bu kullanıcının hiç kullanıcı resmi yok. + +/allpics.bml.nopics.text2=Hiç resim yüklememiÅŸsiniz. Resim yüklemek için, buraya gidin. + +/allpics.bml.nopics.title=Resim Yok + +/allpics.bml.pics=Bunlar [[user]] adlı kullanıcının resimleri. + +/allpics.bml.title=Kullanıcı Resimleri + +/changepassword.bml.btn.proceed=Devam Et + +/changepassword.bml.changepassword.header=Åžifre DeÄŸiÅŸtir + +/changepassword.bml.changepassword.instructions=Åžifrenizi deÄŸiÅŸtirmek için aÅŸağıdaki formu doldurun. Ä°yi bir ÅŸifre seçmek ve hesabınızı güvenli kılmak hakkında bu SSS'a bakabilirsiniz. + +/changepassword.bml.email.body<< +[[sitename]] sitesinde ÅŸifreniz deÄŸiÅŸtirilde. + +Ä°leride ÅŸifrenizi geri almak için: + +[[siteroot]]/lostinfo.bml + +adresini ziyaret edin. + +Saygılar, +[[sitename]] Ekibi + +[[siteroot]] + +. + +/changepassword.bml.email.subject=Åžifre DeÄŸiÅŸimi + +/changepassword.bml.error.badcheck=Yeni Åžifre Yanlış: [[error]] + +/changepassword.bml.error.badnewpassword=Yeni ÅŸifre tasdiÄŸiniz yeni ÅŸifrenizle uyuÅŸmuyor. TuÅŸlamada hata var. Lütfen bir kez daha tuÅŸlayarak yeni ÅŸifrenizi tasdik edin. + +/changepassword.bml.error.badoldpassword=Eski ÅŸifreniz doÄŸru deÄŸil. + +/changepassword.bml.error.blankpassword=Yeni ÅŸifreniz boÅŸ olamaz. + +/changepassword.bml.error.changetestaccount=Deneme hesabının ÅŸifresi deÄŸiÅŸtirilemez. + +/changepassword.bml.error.characterlimit=Åžifreler maksimum 30 karakterle sınırlandırılmıştır. + +/changepassword.bml.error.invaliduser=Geçersiz kullanıcı [[user]]. Bu kullanıcı mevcut deÄŸil. DoÄŸru tuÅŸladığınızdan emin misiniz? + +/changepassword.bml.error.mustenterusername=Kullanıcı adınızı girmelisiniz. + +/changepassword.bml.error.nonascii=Åžifreler sadece ASCII simgelerinden oluÅŸabilir. Lütfen ASCII karakterleri kullanan bir ÅŸifre seçin. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Mevcut e-posta adresiniz tasdik edilmezse ÅŸifrenizi deÄŸiÅŸtiremezsiniz. + +/changepassword.bml.newpassword=Yeni Åžifre: + +/changepassword.bml.newpasswordagain=Yeni Åžifre (tekrar): + +/changepassword.bml.oldpassword=Eski Åžifre: + +/changepassword.bml.proceed.instructions=AÅŸağıdaki düğmeye basınca ÅŸifreniz deÄŸiÅŸecektir. Åžifre deÄŸiÅŸikliÄŸini belirten bir e-posta alacaksınız. + +/changepassword.bml.success.text=Åžifreniz deÄŸiÅŸtirildi ve e-posta adresinize hatırlatıcı bir ileti gönderildi. + +/changepassword.bml.title=Åžifre DeÄŸiÅŸtir + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge (Yeniler Salonu), burada bir çok sorunuza cevap bulabilirsiniz. , ziyaret edin ve biraz keÅŸfe çıkın, çok yakında profesyonel kullanıcılardan ayırt edilemez hale gelirsiniz! +p?> + + +
    + hesabını arkadaş listenize ekleyerek tüm LiveJournal topluluğunu ilgilendiren konular hakkında haber alın.
    + topluluğunu arkadaş listenize ekleyerek web sayfasının ne zamanlarda ulaşılamaz olabileceğini, ve hizmette planlanmamış kesinti raporlarını öğrenin. + + +AIM, ICQ, Yahoo!, MSN, veya Jabber gibi popüler messenger'ları kullanırlar. Siz de kullanıyorsanız, kullanıcı bilgileri'nde belirtmeyi unutmayın. Eğer Paralı Hesap kullanıcısıysanız, cep telefonunuzu mesaj servisi'ne de ayarlayabilirsiniz. +p?> + +p?> + + +Paralı Hesap satın almaktır. Ama tabii, bize yardımcı olabileceğiniz daha bir çok yöntem var. +

    +LiveJournal bir Açık Kaynak projesidir; eğer proglamlama dilleri veya sunucu yan uygulamalarıyla tecrübeniz varsa, LiveJournal Geliştirme Topluluğu'na bir göz atabilirsiniz, . LiveJournal'ı daha iyi kılmak için önerileriniz varsa, LiveJournal Öneri Bölümü'ne göz atın, . Herhangi bir konuda yardımcı olmak isterseniz, LiveJournal İş Topluluğu, 'n ziyaret edin. İnsanlara yardım etmekten hoşlanıyorsanız, teknik destek merkezimize gidin ve birine yardımcı olun. Grafik tasarımla aranız iyiyse, LiveJournal Tasarım Topluluğu'na bakın, . +p?> + + +Japon Anime'den Zen Budizmi'ne, Astronomi'den, Zim'e kadar her konuda olabilirler. Ayrıca dünyanın her yeri için bölgesel topluluklar da bulabilirsiniz. Muhtemelen sizin yaşadığınız yerin de LiveJournal Topluluğu vardır! +p?> + + +SSS'a başvurabilirsiniz. Ayrıca iki kategori bulunmaktadır (Genel Topluluklar Hakkında Genel SSS ve Topluluk İdaresi Hakkında SSS), Topluluklar hakkında bilmek isteyebileceğiniz hemen hemen tüm konuları içermektedirler. Gene de daha fazla bilgiye ihtiyaç duyarsanız, çekinmeden bir destek talebinde bulunabilirsiniz. +p?> + + + + +
      +
    • Topluluk Arama
    • +
    • Tanıtım TopluluÄŸu'na bir göz atın ()
    • +
    • Arama TopluluÄŸu'na bir göz atın ()
    • +
    + + +Topluluk İdarecisi Jesse Proulx'a, () e-posta gönderin. +p?> +. + +/community/index.bml.title=Topluluk Merkezi + +/community/join.bml.button.join=Topluluğa Katıl + +/community/join.bml.label.addtofriends="[[maintainer]]"ı arkadaş listesine ekle.
    + +/community/join.bml.label.allowposting=Bu topluluk bütün üyelerin mesaj göndermesine izin verdiÄŸi için artık siz de mesaj gönderme hakkına sahipsiniz. EÄŸer bilgisayarınızda halen açık bir LiveJournal aracısı varsa çıkışınızı yapmalı ve bu günlüğün mesaj gönderebileceÄŸiniz günlüklerin listesinde görünmesini saÄŸlamak için tekrar giriÅŸ yapmalısınız. + +/community/join.bml.label.auth=Åžu anda üye olarak görünmenize raÄŸmen, bu toplulukta sadece belirli üyeler mesaj gönderebiliyor. Mesaj gönderme izni almak istiyorsanız idarecilerden biriyle irtibata geçin. AÅŸağıda bu topluluÄŸun idarecilerinin isimleri sıralanmıştır: [[admins]] + +/community/join.bml.label.banned=Bu topluluÄŸun idarecisi veya idarecileri katılımınızı men etmiÅŸ. + +/community/join.bml.label.closed=Bu topluluk dışarıya kapalıdır. EÄŸer katılmak istiyorsanız, lütfen idarecilerinden biriyle irtibata geçin. AÅŸağıda bu topluluÄŸun idarecilerinin isimleri sıralanmıştır: [[admins]] + +/community/join.bml.label.commlogged=Kendi ÅŸahsi hesabınız adına deÄŸil, paylaşılan/topluluk türü bir hesap adına giriÅŸ yapmışsınız. + +/community/join.bml.label.errorcomminfo=Tanımlanmış topluluk bilgisi yanlış. + +/community/join.bml.label.expls="[[maintainer]]" topluluÄŸuna katılmak için aÅŸağıdaki düğmeye basın. EÄŸer topluluk mesajlarını arkadaÅŸ sayfanızda görmek istemiyorsanız aÅŸağıdaki kutuyu temizleyin. + +/community/join.bml.label.loginfirst=Bir topluluÄŸa katılabilmek için öncelikle giriÅŸ yapmalısınız. + +/community/join.bml.label.membernow=Artık [[commname]] TopluluÄŸu'nun bir üyesisiniz. + +/community/join.bml.label.sure=Emin misiniz? + +/community/join.bml.success=Ä°ÅŸlem Tamam + +/community/join.bml.title=TopluluÄŸa Katıl + +/community/leave.bml.button.leave=Topluluktan Ayrıl + +/community/leave.bml.label.buttontoleave="[[commname]]" topluluÄŸundan ayrılmak için aÅŸağıdaki düğmeye basın. + +/community/leave.bml.label.infoerror=Belirtilen topluluk bilgisi yanlış. + +/community/leave.bml.label.logoutfirst=Bir topluluktan ayrılabilmek için öncelikle giriÅŸ yapmalısınız. + +/community/leave.bml.label.removed=[[commname]] TopluluÄŸu'ndan ayrıldınız. + +/community/leave.bml.label.removefromfriends="[[user]]" Kullanıcıyı ayrıca arkadaÅŸ listesinden çıkar. + +/community/leave.bml.success=Ä°ÅŸlem Tamam + +/community/leave.bml.sure=Emin misiniz? + +/community/leave.bml.title=Topluluktan Ayrıl + +/community/manage.bml.commlist.actinfo=Bilgi + +/community/manage.bml.commlist.actions=Eylemler + +/community/manage.bml.commlist.actmembers=[Ãœyeler] + +/community/manage.bml.commlist.actmembers2=Ãœyeler + +/community/manage.bml.commlist.actsettings=[Ayarlar] + +/community/manage.bml.commlist.actsettings2=Ayarlar + +/community/manage.bml.commlist.header=Topluluklarınız + +/community/manage.bml.commlist.none=Herhangi bir topluluk idare etmiyorsunuz + +/community/manage.bml.commlist.text=Sizin bizzat veya baÅŸkalarıyla idare ettiÄŸiniz topluluklar ÅŸunlardır: + +/community/manage.bml.commlist.title=BaÅŸlık + +/community/manage.bml.commlist.username=Kullanıcı adı + +/community/manage.bml.create.header=Topluluk oluÅŸtur + +/community/manage.bml.create.text=Ayrıca yeni bir topluluk oluÅŸturabilirsiniz. + +/community/manage.bml.title=Topluluk Ä°daresi + +/community/members.bml.error.alreadyadded=[[user]] eklenmedi çünkü bu kullanıcının zaten topluluÄŸa giriÅŸ izni var. + +/community/members.bml.error.alreadysent=[[user]] eklenemedi çünkü bu kullanıcıya zaten [[datetime]]'da bir tasdik iletisi gönderildi. Lütfen iletinin yanıtlanmasını bekleyin. + +/community/members.bml.error.invaliduser=TopluluÄŸu veya grup hesabını ekleyemiyor: [[user]] + +/community/members.bml.error.noaccess=Sadece toplulukları yürüten kiÅŸiler üyelik listesinde iÅŸlem yapabilir. Siz [[comm]] topluluÄŸunun bir idarecisi deÄŸilsiniz. + +/community/members.bml.error.noattr=[[user]] kullanıcısı için özellikler seçilmedi + +/community/members.bml.error.nocomm=Topluluk bulunamadı. + +/community/members.bml.error.nouser=Böyle bir kullanıcı yok. [[user]] + +/community/members.bml.key.admin=Ä°dareci + +/community/members.bml.key.member=Ãœye + +/community/members.bml.key.moderate=Ä°dareci + +/community/members.bml.key.post=Yazı gönderme izni + +/community/members.bml.key.preapprove=Yürütülmüyor + +/community/members.bml.manage2=Toplulukları idare et + +/community/members.bml.name=Topluluk adı: [[name]] + +/community/members.bml.nextlink=(Sonraki sayfa...) + +/community/members.bml.prevlink=(Önceki sayfa...) + +/community/members.bml.settings=[Ayarlar] + +/community/members.bml.success.header=Ä°ÅŸlem Tamam + +/community/members.bml.success.message=Yaptığınız deÄŸiÅŸiklikler kaydedildi. + +/community/members.bml.success.return=Listeye dön + +/community/members.bml.title=Topluluk Ãœyeleri + +/community/members.bml.update=Ayarları güncelleÅŸtir + +/community/moderate.bml.brlist.time=Saat + +/community/moderate.bml.brlist.view=Görüntüle + +/community/moderate.bml.choice.approve=Onayla + +/community/moderate.bml.error.notfound=Topluluk hesabı bulunamadı. + +/community/moderate.bml.modlist.username=Kullanıcı Adı + +/community/moderate.bml.posted.header=Ä°ÅŸlem Tamam + +/community/search.bml.button.clear=Formu Temizle + +/community/search.bml.button.search=Ara! + +/community/search.bml.checkbox.onlywithpics=Sadece resmi bulunan topluluklar + +/community/search.bml.label.byinterest=Ä°lgi Alanına Göre + +/community/search.bml.label.bylocation=Yere Göre + +/community/search.bml.label.bytime=Günlük GüncelleÅŸtirme Zamanına Göre + +/community/search.bml.label.city=Åžehir: + +/community/search.bml.label.country=Ãœlke: + +/community/search.bml.label.displayoptions=Seçenekleri Göster + +/community/search.bml.label.hasmember=Ãœyesi Var + +/community/search.bml.label.othercriteria=DiÄŸer Kriterler + +/community/search.bml.label.searchcomm=Topluluk Ara + +/community/search.bml.label.sortmethod=Sıralama Yöntemi + +/community/search.bml.label.stateprovince=Eyalet/Ä°l: + +/community/search.bml.label.updated=En son GüncelleÅŸtirilme + +/community/search.bml.sel.bypicture=Resme Göre + +/community/search.bml.sel.communityname=Topluluk Adı + +/community/search.bml.sel.day=gün + +/community/search.bml.sel.month=ay + +/community/search.bml.sel.simple=Basit + +/community/search.bml.sel.updatetime=GüncelleÅŸtirilme Zamanı + +/community/search.bml.sel.username=Kullanıcı Adı + +/community/search.bml.sel.week=hafta + +/community/search.bml.title=Topluluk Arama + +/community/settings.bml.button.changecommunity=Ayarları GüncelleÅŸtir + +/community/settings.bml.button.createcommunity=Topluluk OluÅŸtur + +/community/settings.bml.error.badpassword=Geçersiz topluluk ÅŸifresi + +/community/settings.bml.error.notfound=Topluluk hesabı bulunamadı. + +/community/settings.bml.label.changeheader=Topluluk Ayarlarını DeÄŸiÅŸtir + +/community/settings.bml.label.commchanged=Topluluk ayarları deÄŸiÅŸtirildi. + +/community/settings.bml.label.commheader=Topluluk Hesabı + +/community/settings.bml.label.comminfo=Topluluk bilgisi + +/community/settings.bml.label.commopts=Topluluk Seçenekleri + +/community/settings.bml.label.commsite=TopluluÄŸun web sitesi + +/community/settings.bml.label.community=Topluluk: + +/community/settings.bml.label.createheader=Topluluk OluÅŸtur + +/community/settings.bml.label.maintainer=Ä°dareci: + +/community/settings.bml.label.membership=Ãœyelik + +/community/settings.bml.label.password=Åžifre: + +/community/settings.bml.label.username=Kullanıcı Adı: + +/community/settings.bml.label.whocanjoin=TopluluÄŸunuza kimler katılabilir? + +/community/settings.bml.label.whocanpost=Bu topluluÄŸa kim mesaj gönderebilir? + +/community/settings.bml.members=[Ãœyeler] + +/community/settings.bml.name=Topluluk adı: [[name]] + +/community/settings.bml.success=Ä°ÅŸlem Tamam + +/community/settings.bml.title.create=Topluluk OluÅŸtur + +/community/settings.bml.title.modify=Topluluk Ayarları + +/create.bml.age.check.question=13 yaşından küçük müsünüz? + +/create.bml.age.check.yes=Evet, 13 yaşından küçüğüm. + +/create.bml.age.check2.question=13 yaşından büyük müsünüz? + +/create.bml.age.check2.yes=Evet, 13 yaşından büyüğüm. + +/create.bml.age.head=YaÅŸ + +/create.bml.btn.proceed=Devam... + +/create.bml.clusterselect.cluster=Küme: + +/create.bml.clusterselect.clusternum=Küme [[number]] + +/create.bml.clusterselect.head=Küme Seçimi + +/create.bml.clusterselect.nocluster=Küme Yok + +/create.bml.create.head=Yeni bir Günlük OluÅŸturma + +/create.bml.create.text=Yeni bir LiveJournal oluÅŸturmak çok kolay, tek yapmanız gereken aÅŸağıdaki talimatlara uymak! + +/create.bml.email.head=E-posta adresiniz + +/create.bml.email.input.head=E-posta Adresi: + +/create.bml.error.coppa.under13=Ãœzgünüz, COPPA'nın getirdiÄŸi sınırlamalara göre 13 yaşını doldurana kadar LiveJournal hizmetinden yararlanamazsınız. Lütfen 13. yaÅŸgününüzden sonra tekrar gelin. + +/create.bml.error.email.blank=E-posta adresinizi vermelisiniz. + +/create.bml.error.password.asciionly=Åžifrenizin içinde sadece ASCII simgelerini kullanabilirsiniz. + +/create.bml.error.password.blank=Bir ÅŸifre girmelisiniz. + +/create.bml.error.password.nomatch=Åžifreler birbiriyle uyuÅŸmuyor. + +/create.bml.error.username.inuse=Bu kullanıcı adı baÅŸka biri tarafından kullanılıyor; lütfen baÅŸka bir ad seçiniz. + +/create.bml.error.username.mustenter=Bir kullanıcı adı girmelisiniz. + +/create.bml.name.head=Adınız + +/create.bml.name.input.head=Ad: + +/create.bml.password.head=Åžifre + +/create.bml.password.input.head1=Åžifre: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Åžifreyi tekrar girin: + +/create.bml.password.text=Bir ÅŸifre seçin. + +/create.bml.proceed.btn.proceed=Devam... + +/create.bml.proceed.warning=Devam düğmesine bir defa basın!! + +/create.bml.success.btn.enterinfo=KiÅŸisel Bilgileri Girin + +/create.bml.success.head=Ä°ÅŸlem Tamam! + +/create.bml.title=Yeni Günlük OluÅŸtur + +/create.bml.tos.error=Hesap oluÅŸturmadan önce hizmet koÅŸullarını okumalı ve kabul etmelisiniz. + +/create.bml.tos.haveread=Hizmet KoÅŸullarını okudum ve kabul ediyorum. + +/create.bml.tos.heading=Hizmet KoÅŸulları + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Yeni bir hesap oluÅŸturmak için hesap oluÅŸturma kodu giriniz: + +/create.bml.useacctcodes.welcome=HoÅŸgeldiniz + +/create.bml.username.box.head=Kullanıcı adı: + +/create.bml.username.forpaidaccts=Veya paralı hesaplar için: + +/create.bml.username.head=Kullanıcı adı + +/create.bml.username.ljaddress=Günlüğünüz ÅŸu adreslerde yer alacak: + +/create.bml.username.username=kullanıcı adı + +/doc/index.bml.about.header=HoÅŸgeldiniz + +/doc/index.bml.docs.faq.about=LiveJournal.com hakkında Sıkça Sorulan Sorular + +/doc/index.bml.docs.faq.title=SSS + +/doc/index.bml.docs.header=Belgeler + +/doc/index.bml.docs.tour.title=Tur + +/doc/index.bml.title=Dokümentasyon + +/doc/tour/index.bml.comms.title=Topluluklar + +/doc/tour/index.bml.create.title=Hesap OluÅŸturma + +/doc/tour/index.bml.friends.title=ArkadaÅŸlar + +/doc/tour/index.bml.intro.title=HoÅŸgeldiniz + +/doc/tour/index.bml.modify.title=KiÅŸiselleÅŸtirme + +/doc/tour/index.bml.nav.next=Sonraki --> + +/doc/tour/index.bml.nav.prev=<-- Önceki + +/doc/tour/index.bml.profile.title=Profiller + +/doc/tour/index.bml.sitemap.title=Site Haritası + +/doc/tour/index.bml.support.title=Yardım Alma + +/doc/tour/index.bml.title=Tur - [[title]] + +/doc/tour/index.bml.update.title=GüncelleÅŸtirme + +/editinfo.bml.allowshowcontact.email.actual_only=Yalnızca gerçek adres + +/editinfo.bml.allowshowcontact.email.both=Ä°kisi de (gerçek + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Yalnızca LiveJournal adresi + +/editinfo.bml.allowshowcontact.email.neither=Hiçbiri. Hiçbir e-posta adresini gösterme. + +/editinfo.bml.allowshowcontact.email.no_show=E-posta adresini gösterme + +/editinfo.bml.allowshowcontact.email.show=E-posta adresini göster + +/editinfo.bml.bday.title=DoÄŸum günü + +/editinfo.bml.bday.year.opt=yılı girmeyebilirsiniz + +/editinfo.bml.bio.header=Hakkınızda + +/editinfo.bml.chat.icquin.title=ICQ Numarası + +/editinfo.bml.chat.msnusername.title=MSN Kullanıcı Adı + +/editinfo.bml.chat.yahooid.title=Yahoo! Kullanıcı Adı + +/editinfo.bml.city.title=Åžehir + +/editinfo.bml.country.choose=Bir ülke seçin + +/editinfo.bml.country.title=Ãœlke + +/editinfo.bml.donotlog=Hayır + +/editinfo.bml.email.title=E-posta + +/editinfo.bml.encoding.header=Seçenek Åžifreleme + +/editinfo.bml.error.email.none=E-posta adresinizi vermelisiniz. + +/editinfo.bml.error.locale.country_ne_state=Ãœlkeniz olarak Amerika BirleÅŸik Devletlerini belirttiniz ama "diÄŸer eyalet" alanına ABD'de olmayan bir eyalet girdiniz. + +/editinfo.bml.error.locale.invalid_country=Geçersiz bir ülke seçtiniz. + +/editinfo.bml.error.locale.state_ne_country=ABD dışında bir ülke belirttiniz ama bir ABD eyaleti seçtiniz. + +/editinfo.bml.error.locale.zip_ne_state<< +GirdiÄŸiniz posta kodu belirttiÄŸiniz eyalete ait deÄŸil. +Ya doÄŸru bilgi girin ya da eyalet veya posta kodu alanlarından birini boÅŸ bırakın. + +. + +/editinfo.bml.error.locale.zip_requires_us|staleness=1 +/editinfo.bml.error.locale.zip_requires_us<< +Bir posta kodu girdiniz ama ülkeniz olarak Amerika BirleÅŸik Devletlerini seçmediniz. +Bu sitede sadece ABD'de yaÅŸayan kullanıcıların posta kodu bilgileri toplanmaktadır. +Lütfen geri dönüp posta kodunu siliniz ya da ülkeniz olarak Amerika BirleÅŸik Devletleri'ni seçiniz. + +. + +/editinfo.bml.finished.about=Ä°ÅŸleminizi bitirdiÄŸinizde, aÅŸağıdaki "DeÄŸiÅŸiklikleri Kaydet" düğmesine basınız: + +/editinfo.bml.finished.header=Ä°ÅŸleminiz bitti mi? + +/editinfo.bml.finished.save_button=DeÄŸiÅŸiklikleri Kaydet + +/editinfo.bml.gender.title=Cinsiyet + +/editinfo.bml.hidefriendof.about=EÄŸer bu seçeneÄŸi iÅŸaretlerseniz, sizi arkadaÅŸ listelerine ekleyen kiÅŸilerin listesi profil sayfanızda görünmeyecektir. + +/editinfo.bml.howhear.header=Merak + +/editinfo.bml.htmlemail.header=HTML içeren e-postaları gönder + +/editinfo.bml.int.header=Ä°lgi alanları + +/editinfo.bml.login.enterinfo=KiÅŸisel bilgilerinizi deÄŸiÅŸtirmek için kullanıcı adınızı ve ÅŸifrenizi giriniz. + +/editinfo.bml.login.forgot.header=Bir ÅŸey mi unuttunuz? + +/editinfo.bml.login.forgot.recover=Kullanıcı adınızı ya da ÅŸifrenizi unuttuysanız buradan geri alabilirsiniz!. + +/editinfo.bml.logip.always=Her zaman + +/editinfo.bml.logip.anon_only=Yalnızca isimsiz mesaj gönderenler + +/editinfo.bml.logip.header=Yanıtlayan kiÅŸilerin IP adresleri kaydedilsin mi? + +/editinfo.bml.name.title=Ad + +/editinfo.bml.newemail.subject=E-posta Adresi DeÄŸiÅŸtirildi + +/editinfo.bml.optional=Ä°steÄŸe baÄŸlı + +/editinfo.bml.opt_in.header=LiveJournal ile ilgili haberleri gönderin. + +/editinfo.bml.persinfo.header=KiÅŸisel Bilgiler + +/editinfo.bml.screen.all=Hepsini + +/editinfo.bml.screen.anon=Ä°simsiz olanları + +/editinfo.bml.screen.none=Hiçbirini + +/editinfo.bml.screen.nonfriends=ArkadaÅŸ olmayanlar tarafından + +/editinfo.bml.screen.nonmembers=Ãœye olmayanlar tarafından + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=Güvenlik + +/editinfo.bml.security.visibility.anybody=Hiç kimse + +/editinfo.bml.security.visibility.everybody=Herkes + +/editinfo.bml.security.visibility.friends=Yalnızca arkadaÅŸlar + +/editinfo.bml.security.visibility.regusers=Kayıtlı Kullanıcılar + +/editinfo.bml.settings.friendspage.title=ArkadaÅŸ Sayfası Adı: + +/editinfo.bml.settings.header=LiveJournal Seçenekleri + +/editinfo.bml.settings.journal.title=Günlük Adı: + +/editinfo.bml.settings.privacy.about=AÅŸağıdan kiÅŸisel gizlilik seçeneklerini ve tercihlerinizi belirleyiniz. + +/editinfo.bml.settings.privacy.header=Gizlilik Seçenekleri + +/editinfo.bml.state.other=Veya baÅŸka eyalet/il/bölge giriniz + +/editinfo.bml.state.title=Eyalet + +/editinfo.bml.state.us=ABD Eyaletleri + +/editinfo.bml.success.header=Ä°ÅŸlem tamam! + +/editinfo.bml.success.message=Bilgileriniz ile günlük ayarlarınız ve profiliniz güncelleÅŸtirildi. + +/editinfo.bml.switch.button=DeÄŸiÅŸtir + +/editinfo.bml.switch.header=Günlük DeÄŸiÅŸtir + +/editinfo.bml.switch.workwith=Çalışılacak günlük: + +/editinfo.bml.title=KiÅŸisel Bilgileri DeÄŸiÅŸtir + +/editinfo.bml.tm.details=ayrıntılar + +/editinfo.bml.tm.phonenum=Telefon numarası: + +/editinfo.bml.tm.sec.title=Güvenlik Seviyesi: + +/editinfo.bml.tm.servprov=Servis SaÄŸlayıcısı + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Bu resmi silmek ya da yeni bir tane yüklemek için buraya gidin. + +/editinfo.bml.userpic.header=Resminiz + +/editinfo.bml.userpic.none=hiçbir resim yüklenmedi + +/editinfo.bml.webpagename.title=Web Sayfası Adı + +/editinfo.bml.webpageurl.title=Web Sayfası Adresi + +/editinfo.bml.whoreply.header=Yazılarınıza kimler yanıt verebilir? + +/editinfo.bml.zip.title=Posta kodu + +/editinfo.bml.zip.usonly=5 haneli posta kodu; yalnızca ABD'de oturanlar + +/editjournal.bml.btn.proceed=Devam... + +/editjournal.bml.certainday=Belirli Gün: + +/editjournal.bml.recententries=en yeni yazılar + +/editjournal.bml.recententry=En son yazı + +/editjournal.bml.title=Günlük Yazılarını DeÄŸiÅŸtir + +/editjournal_do.bml.btn.edit=Seçilen Yazıyı DeÄŸiÅŸtir + +/editjournal_do.bml.btn.save=Seçilen Yazıyı Kaydet + +/editjournal_do.bml.continue.head=Devam etmek için basın... + +/editjournal_do.bml.continue.text=DeÄŸiÅŸtirmek ya da silmek istediÄŸiniz yazıyı seçtikten sonra aÅŸağıdaki DeÄŸiÅŸtir düğmesine basınız. + +/editjournal_do.bml.date=Tarih: + +/editjournal_do.bml.default=varsayılan + +/editjournal_do.bml.error.modify=Günlüğünüzün görünüşünün deÄŸiÅŸtirilmesi sırasında bir hata meydana geldi: + +/editjournal_do.bml.error.nofind=Seçilen günlük kaydı bulunamadı. + +/editjournal_do.bml.localtime=Yerel saat: + +/editjournal_do.bml.noneother=Hiçbiri ya da diÄŸer: + +/editjournal_do.bml.opt.noformat=Otomatik formatlama yapma: + +/editjournal_do.bml.other=DiÄŸer: + +/editjournal_do.bml.pickentry.head=DeÄŸiÅŸtirilecek yazıyı seç + +/editjournal_do.bml.picture=Kullanılacak resim: + +/editjournal_do.bml.save.head=Kaydetmek için basın... + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=Konu: (isteÄŸe baÄŸlı, uzun yazılar için kullanılır) + +/editjournal_do.bml.success.delete=Seçilen yazı silindi. + +/editjournal_do.bml.success.head=Ä°ÅŸlem Tamam + +/friends/add.bml.add.header=Ä°ÅŸlem Tamam + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text= adlı kullanıcı arkadaÅŸ listenize eklendi. ArkadaÅŸ sayfanıza buradan bakabilirsiniz. + +/friends/add.bml.add.title=ArkadaÅŸ Eklendi! + +/friends/add.bml.btn.add=[[user]]'ı ekle + +/friends/add.bml.btn.modify=DeÄŸiÅŸtir + +/friends/add.bml.btn.remove=Kaldır + +/friends/add.bml.colors.bg=Arka plan + +/friends/add.bml.colors.fg=Ön plan + +/friends/add.bml.colors.header=Renkler + +/friends/add.bml.colors.hover=(Adını görmek için fareyi rengin üstünde tutunuz) + +/friends/add.bml.confirm.header=[[user]] adlı kullanıcı arkadaÅŸ olarak eklensin mi? + +/friends/add.bml.confirm.text= [[user]] adlı kullanıcıyı arkadaÅŸ listenize eklemek için tıklayınız. + +/friends/add.bml.confirm.title=ArkadaÅŸ Ekle + +/friends/add.bml.error1.header|staleness=1 +/friends/add.bml.error1.header=Önce GiriÅŸ Yap + +/friends/add.bml.error1.title=ArkadaÅŸ Ekle + +/friends/add.bml.error3.title=ArkadaÅŸ DeÄŸiÅŸtir + +/friends/add.bml.groups.header=ArkadaÅŸ Grupları + +/friends/add.bml.groups.nogroup|staleness=1 +/friends/add.bml.groups.nogroup=KurulmuÅŸ bir arkadaÅŸ grubu yok. + +/friends/add.bml.remove.header=Ä°ÅŸlem Tamam + +/friends/add.bml.remove.title=ArkadaÅŸ Listeden Çıkartıldı! + +/friends/edit_do.bml.addfriends.head=ArkadaÅŸ Ekle + +/friends/edit_do.bml.background=Arka Plan + +/friends/edit_do.bml.bgcolor=Arka Plan Rengi: + +/friends/edit_do.bml.btn.save=DeÄŸiÅŸiklikleri Kaydet + +/friends/edit_do.bml.done.head=Ä°ÅŸleminiz bitti mi? + +/friends/edit_do.bml.done.text=Ä°ÅŸleminiz bittiÄŸinde, aÅŸağıdaki "DeÄŸiÅŸiklikleri Kaydet" düğmesine basınız... + +/friends/edit_do.bml.error.updating=ArkadaÅŸ listenizin güncelleÅŸtirilmesi sırasında bir hata meydana geldi: + +/friends/edit_do.bml.friend=ArkadaÅŸ + +/friends/edit_do.bml.hover=Adını görmek için fareyi rengin üstünde tutunuz + +/friends/edit_do.bml.name=Ad + +/friends/edit_do.bml.opt.delete=Silinsin mi? + +/friends/edit_do.bml.success.head=Ä°ÅŸlem Tamam + +/friends/edit_do.bml.user=Kullanıcı + +/friends/edit_do.bml.yourfriends.head=ArkadaÅŸlarınız + +/friends/index.bml.title=ArkadaÅŸ Seçenekleri + +/index.bml.boldcreate=Kendi LiveJournal'ınızı yaratın! + +/index.bml.frank.image.alt=LiveJournal'ın keçi maskotu, Frank. + +/index.bml.frank.logo="Meeeee", diyor Frank. + +/index.bml.meta.desc=LiveJournal.com düşüncelerinizi dünya ile paylaÅŸabileceÄŸiniz bir yerdir. + +/index.bml.meta.keywords=günlük, günce, çevrimiçi günce, günlükler, yazmak, çevrimiçi günlük, web günlüğü + +/interests.bml.add.added.head=Eklendi! + +/interests.bml.add.added.text=Ä°lgi alanı listenize eklendi. + +/interests.bml.add.btn.text=[[interest]]'i ekle + +/interests.bml.add.confirm.head=Onayla + +/interests.bml.add.confirm.text=[[interest]]'i ilgi alanlarınıza eklemek için tıklayın. + +/interests.bml.add.toomany.head=Ãœzgünüz... + +/interests.bml.communities.head=Ä°lgili Topluluklar + +/interests.bml.communities.text=AÅŸağıdaki topluluklar aynı zamanda [[interest]] ile de ilgileniyor. + +/interests.bml.error.add.mustlogin=Bu ÅŸekilde bir ilgi alanı eklemek için siteye giriÅŸ yapmalısınız. + +/interests.bml.error.findsim_do.intnotfound=Aradığınız ilgi alanı bulunamadı. + +/interests.bml.findsim.searchwait=Not: Arama iÅŸlemi birkaç saniye sürebilir. Lütfen sabırlı olun. + +/interests.bml.findsim_do.notdefined=[[user]] adlı kullanıcı hiçbir ilgi alanı belirlememiÅŸ. + +/interests.bml.findsim_do.similar.head=Benzer Kullanıcılar + +/interests.bml.interest=Ä°lgi Alanı + +/interests.bml.interested.btn.find=Bul + +/interests.bml.interests.head=Ä°lgi Alanları + +/interests.bml.interests.viewpop=Popüler ilgi alanlarına bakın + +/interests.bml.popular.head=Popüler Ä°lgi Alanları + +/interests.bml.popular.text=AÅŸağıdakiler en popüler ilgi alanlarıdır. + +/interests.bml.title=Ä°lgi alanları + +/interests.bml.users.head=Ä°lgilenen kullanıcılar + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=AÅŸağıdaki kullanıcılar aynı zamanda [[interest]] ile de ilgileniyor. + +/login.bml.bindip.label=IP adresine baÄŸlan: + +/login.bml.bindip.no=Hayır (bütün ISP'lerle çalışır) + +/login.bml.bindip.yes=Evet (daha güvenli) + +/login.bml.error.mustenterusername=Bir kullanıcı adı girmelisiniz. + +/login.bml.links.head=BaÄŸlantılar + +/login.bml.links.link1=ArkadaÅŸ sayfanız. + +/login.bml.links.link2=Yapılacaklar listeniz. + +/login.bml.loggedin.head=GiriÅŸ yaptınız! + +/login.bml.loggedin.text=Siteye giriÅŸ yaptınız. + +/login.bml.login.btn.changeopts=Seçenekleri DeÄŸiÅŸtir + +/login.bml.login.btn.login=Gir... + +/login.bml.login.forget=Unuttunuz mu? + +/login.bml.login.never=Asla + +/login.bml.login.otheropts=DiÄŸer Seçenekler: + +/login.bml.login.password=Åžifre: + +/login.bml.login.username=Kullanıcı Adı: + +/login.bml.whylogin.text=Siteye giriÅŸ yapmanın bazı faydaları ÅŸunlardır: + +/logout.bml.already.head=Çoktan çıktınız + +/logout.bml.already.text=Çoktan çıkış yaptınız. + +/lostinfo.bml.btn.proceed=Devam + +/lostinfo.bml.enter_email=E-posta adresinizi girin: + +/lostinfo.bml.enter_email_optional=E-posta adresi: (isteÄŸe baÄŸlı) + +/lostinfo.bml.enter_username=Kullanıcı adınızı girin: + +/lostinfo.bml.lostpassword.title|staleness=1 +/lostinfo.bml.lostpassword.title=Åžifrenizi mi kaybettiniz? + +/lostinfo.bml.lostusername.text=Kullanıcı adınızı kaybettiyseniz e-posta adresinizi girin, kullanıcı adınızı gönderelim. + +/lostinfo.bml.lostusername.title|staleness=1 +/lostinfo.bml.lostusername.title=Kullanıcı adınızı mı kaybettiniz? + +/lostinfo_do.bml.password_mailed.text=Ä°ÅŸlem tamam. Åžifreniz adresinize gönderildi. + +/lostinfo_do.bml.password_mailed.title=Åžifreniz adresinize gönderildi! + +/lostinfo_do.bml.username_mailed.text=Ä°ÅŸlem tamam. Kullanıcı adınız adresinize gönderildi. + +/lostinfo_do.bml.username_mailed.title=Kullanıcı adınız adresinize gönderildi! + +/modify.bml.title=Görünümü DeÄŸiÅŸtir + +/modify_do.bml.availablestyles.head=Mevcut Biçemler + +/modify_do.bml.availablestyles.userstyles=Kullanıcı Biçemleri: + +/modify_do.bml.colortheme.area.head=Kullanım Alanı + +/modify_do.bml.colortheme.color.head1=Renk + +/modify_do.bml.colortheme.color.head2=(#rrggbb veya ad) + +/modify_do.bml.domainalias.example=Örnek: my-journal.com + +/modify_do.bml.done.btn.savechanges=DeÄŸiÅŸiklikleri Kaydet + +/modify_do.bml.done.head=Ä°ÅŸleminiz bitti mi? + +/modify_do.bml.done.text=Ä°ÅŸleminizi bitirdiÄŸinizde, aÅŸağıdaki "DeÄŸiÅŸiklikleri Kaydet" düğmesine basınız... + +/modify_do.bml.friends.about=ArkadaÅŸ sayfanızın nasıl göründüğünü denetleyen seçenekler ÅŸunlardır. + +/modify_do.bml.journaloptions.head=Günlük Seçenekleri + +/modify_do.bml.journalstatus.select.deleted=Silindi + +/modify_do.bml.journalstatus.select.head=Durum: + +/modify_do.bml.journalstatus.select.suspended=Askıda + +/modify_do.bml.moodicons.preview=önizle + +/modify_do.bml.success.head=Ä°ÅŸlem Tamam + +/modify_do.bml.success.text=Günlük ayarlarınız güncelleÅŸtirildi. Günlüğünüzün yeni halini buradan görebilirsiniz. + +/paidaccounts/index.bml.costs.header=Peki, ücret ne kadar? + +/paidaccounts/index.bml.costs.rates=Ãœcretler aÅŸağıdaki gibidir: + +/paidaccounts/index.bml.costs.rates.amount.header=Tutar + +/paidaccounts/index.bml.costs.rates.time.header=Zaman + +/paidaccounts/index.bml.title=Paralı Hesaplar Hakkında + +/paidaccounts/index.bml.whypay.header|staleness=2 +/paidaccounts/index.bml.whypay.header=LiveJournal'ı kullanmak için para mı ödemek zorundayım? Bu aptalca! + +/paidaccounts/index.bml.your_username=kullanıcı_adınız + +/paidaccounts/usepaypal.bml.delivery.past=Teslimat tarihi geçmiÅŸte olamaz. Hemen göndermek için, teslimat tarihi kısmını boÅŸ bırakın. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Teslimat tarihi en geç önümüzdeki bir ay içinde olmalıdır. + +/pay/index.bml.deliverydate.label=Teslimat Tarihi: + +/pay/index.bml.gift.anonymous=Ä°simsiz hediye + +/press/staff.bml.administration=Yönetim + +/press/staff.bml.bradfitz.quip=Ãœrününüzün üzerine odaklanın, sadece para kazanmaya deÄŸil. + +/press/staff.bml.ryanfitz.title=Ödeme Hizmetleri + +/press/staff.bml.sandy.title=Muhasebe ve Ä°dare + +/site/goat.bml.image.alt=Frank, LiveJournal'ın maskotu olan keçi. + +/site/goat.bml.image.caption="Meeee," diyor Frank. + +/site/goat.bml.meet.header=Frank ile tanışın + +/site/goat.bml.title=Keçi Frank + +/suggestions/index.bml.info.title=DiÄŸer Bilgiler + +/suggestions/index.bml.welcome.title=HoÅŸgeldiniz! + +/support/encodings.bml.title=Åžifrelemeler + +/support/faqbrowse.bml.backfaq=SSS'ye geri dön. + +/support/faqbrowse.bml.backsupport=Destek Bölgesi'ne geri dön. + +/support/faqbrowse.bml.lastupdated=En son güncelleÅŸtirilme tarihi: + +/support/faqbrowse.bml.title_cat=SSS - [[catname]] + +/support/faqbrowse.bml.title_num=SSS Soru No[[num]] + +/support/see_overrides.bml.error.nos1=Bu kullanıcı S1 kullanmıyor. + +/talkmulti.bml.error.login=Siteye giriÅŸ yapmadınız. + +/talkmulti.bml.error.none_selected=Hiçbir mesaj seçmediniz. + +/talkmulti.bml.error.privs.delete=Bu mesajları silme izniniz yok. + +/talkpost.bml.allowedhtml=Ä°zin verilen HTML + +/talkpost.bml.error.cannotreplynopost=Var olmayan bir mesaja yanıt veremezsiniz. + +/talkpost.bml.error.nocommentsjournal=Kullanıcı, günlüğüne mesaj gönderme seçeneÄŸini etkisiz kılmış. + +/talkpost.bml.error.nocommentspost=Kullanıcı bu yazısı için mesaj gönderebilme özelliÄŸini etkisiz kılmış. + +/talkpost.bml.error.noreplypost=Yanıtlanacak mesaj bulunamadı (silindi mi?) + +/talkpost.bml.label.picturetouse=Kullanılacak resim: + +/talkpost.bml.loganonip=Dikkat! Bu kullanıcı isimsiz mesaj gönderenlerin IP adreslerini kayda geçirme seçeneÄŸini etkin kılmış. + +/talkpost.bml.loginq=GiriÅŸ yap? + +/talkpost.bml.logyourip=Dikkat! Bu kullanıcı mesaj göndermeniz halinde IP adresinizi kayda geçirme seçeneÄŸini etkin kılmış. + +/talkpost.bml.nosubjecthtml=Konuda HTML kullanılamaz + +/talkpost.bml.opt.anonymous=Ä°simsiz + +/talkpost.bml.opt.defpic=(varsayılan) + +/talkpost.bml.opt.friendsonly=- bu kullanıcı isimsiz olarak ve arkadaÅŸ listesinde olmayanların yanıtlamasını engellemiÅŸ. Buraya mesaj atabilmek için [[username]]'nın arkadaÅŸ listesinde bulunuyor olmalısınız. + +/talkpost.bml.opt.from=Gönderen: + +/talkpost.bml.opt.ljuser=LiveJournal kullanıcısı: + +/talkpost.bml.opt.loggedin=GiriÅŸ yapmış kullanıcı: [[username]] + +/talkpost.bml.opt.message=Mesaj: + +/talkpost.bml.opt.noanonpost=- bu kullanıcı isimsiz mesaj göndermeyi engellemiÅŸ. + +/talkpost.bml.opt.noautoformat=Otomatik formatlama yapma: + +/talkpost.bml.opt.noimage=Resim Yok + +/talkpost.bml.opt.preview=Önizle + +/talkpost.bml.opt.spellcheck=Göndermeden önce yazım denetiminden geçir + +/talkpost.bml.opt.subject=Konu: + +/talkpost.bml.opt.submit=Mesaj Gönder + +/talkpost.bml.paraformat=Paragraflar varsayılan ayarlarda otomatik olarak formatlanır. + +/talkpost.bml.postresponse=Yanıt olarak bir mesaj yaz: + +/talkpost.bml.title=Mesaj Gönder + +/talkpost_do.bml.error.badpassword=Belirtilen kullanıcı adı için yanlış parola. EÄŸer parolanızı unuttuysanız buradan öğrenebilirsiniz. + +/talkpost_do.bml.error.badusername=BelirttiÄŸiniz LiveJournal kullanıcı adı mevcut deÄŸil. Unuttuysanız kullanıcı adınızı buradan öğrenebilir ya da "Ä°simsiz" olarak mesaj atabilirsiniz. + +/talkpost_do.bml.error.banned=Bu kullanıcının günlüğüne mesaj yazmaya izniniz yok. + +/talkpost_do.bml.error.blankmessage=Mesajınız boÅŸtu. Lütfen mesaj boÅŸluÄŸuna kısa da olsa bir ÅŸey yazın. + +/talkpost_do.bml.error.confused_identity=Bir kullanıcı adı girdiniz ama isimsiz olarak ya da ÅŸu anki kullanıcı olarak mesaj yazmayı seçtiniz. Geri dönün ve ne yapmak istediÄŸinize karar verin. + +/talkpost_do.bml.error.deleted=Günlüğünüz silinmiÅŸ. Mesaj gönderemezsiniz. + +/talkpost_do.bml.error.friendsonly=Sadece [[user]] adlı kullanıcının arkadaÅŸları bu günlüğe mesaj gönderebilir.ilir. + +/talkpost_do.bml.error.lostcookie=GiriÅŸ çereziniz kayıp mı oldu? + +/talkpost_do.bml.error.manybytes=Ãœzgünüz, ama ÅŸu anki [[current]] yanıtınız en fazla mesaj uzunluÄŸu olan [[limit]] baytı aşıyor. Lütfen geri dönün, mesajı kısaltın, ardından bir daha göndermeyi deneyin. + +/talkpost_do.bml.error.manychars=Ãœzgünüz, ama ÅŸu anki [[current]] yanıtınız en fazla mesaj uzunluÄŸu olan [[limit]] baytı aşıyor. Lütfen geri dönün, mesajı kısaltın, ardından bir daha göndermeyi deneyin. + +/talkpost_do.bml.error.mustlogin=Bu korunmuÅŸ yazıya yanıt verebilmek için giriÅŸ yapmalı veya bir kullanıcı adı/parola kullanıyor olmalısınız. + +/talkpost_do.bml.error.noanon=Bu kiÅŸinin günlüğüne isimsiz olarak mesaj gönderemezsiniz. + +/talkpost_do.bml.error.noauth=Bu korunmuÅŸ yazıyı yanıtlama izniniz yok. + +/talkpost_do.bml.error.nocomments=Kullanıcı bu yazıya yanıt verilmesini engellemiÅŸ. + +/talkpost_do.bml.error.noparent=Var olmayan bir mesajı yanıtlayamazsınız. + +/talkpost_do.bml.error.notafriend=Ãœzgünüz, kullanıcı [[user]] sizi arkadaÅŸ olarak tanımlamamış, ve günlüğüne cevap yazabilecekleri sadece kendi arkadaÅŸ listesindeki kiÅŸiler olarak ayarlamış. + +/talkpost_do.bml.error.nousername=LiveJournal kullanıcı adınızı girmediniz. LiveJournal kullanıcı hesabınız yoksa "Ä°simsiz" olarak mesaj göndermeyi tercih edebilirsiniz. + +/talkpost_do.bml.error.suspended=Günlüğünüz askıya alınmıştır. Mesaj gönderemezsiniz. + +/talkpost_do.bml.error.testacct=Test hesapları sadece test hesabı günlüklerinde kullanılabilir. + +/talkpost_do.bml.opt.preview=Önizle + +/talkpost_do.bml.preview.subject=Konu: + +/talkpost_do.bml.preview.submit=Gönder + +/talkpost_do.bml.preview.title=Önizle + +/talkpost_do.bml.success.loggedin=GiriÅŸ yaptınız. + +/talkpost_do.bml.success.message=Mesajınız eklendi. Buradan okuyabilirsiniz. + +/talkpost_do.bml.success.title=Ä°ÅŸlem Tamam + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Mesaj Gönder + +/talkread.bml.anonuser=(Ä°simsiz) + +/talkread.bml.confirm.action=Seçilen mesajları silmek istediÄŸinizden emin misiniz? + +/talkread.bml.deletedpost=(SilinmiÅŸ mesaj) + +/talkread.bml.deleteduser=(SilinmiÅŸ kullanıcı: [[username]]) + +/talkread.bml.fromip=(gönderildiÄŸi IP adresi [[ip]]) + +/talkread.bml.noreplies=Yanıt yok + +/talkread.bml.nosubject=(konu yok) + +/talkread.bml.replysuspended=(Günlüğü askıya alınmış kullanıcının yanıtı) + +/talkread.bml.select=Seç + +/talkread.bml.subjectdeleted=[silindi] + +/talkread.bml.talkmulti.delete=Sil + +/talkread.bml.title=Mesajları Oku + +/talkscreen.bml.screened.title=Ä°ÅŸlem Tamam + +/talkscreen.bml.unscreened.title=Ä°ÅŸlem Tamam + +/tools/memadd.bml.body.added.header=Ä°ÅŸlem Tamam + +/tools/memadd.bml.description=Tanım: + +/tools/memadd.bml.error.deleted.title=Anı silindi + +/tools/memadd.bml.error.entry_deleted=Bu yazı artık yok. Anı silindi. + +/tools/memadd.bml.error.invalid_security=Geçersiz ya da kayıp güvenlik seçeneÄŸi. + +/tools/memadd.bml.error.maxsize=Bu anahtar sözcük izin verilen maksimum uzunluÄŸu aşıyor: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.title=Hiçbir tanım yok + +/tools/memadd.bml.form.reset=Sıfırla + +/tools/memadd.bml.form.submit=Gönder + +/tools/memadd.bml.keywords=Anahtar sözcükler: + +/tools/memadd.bml.keywords.example=Örnek: Komik, Bilgisayar Dehası, Romantik + +/tools/memadd.bml.keywords.select=Dilerseniz geçmiÅŸte kullandığınız anahtar sözcükleri de seçebilirsiniz: + +/tools/memadd.bml.login.enterinfo=Anıyı kaydetmek istediÄŸiniz hesabın kullanıcı adını ve ÅŸifresini giriniz. + +/tools/memadd.bml.login.forgot.header=Bir ÅŸey mi unuttunuz? + +/tools/memadd.bml.login.forgot.recover=Kullanıcı adınızı ya da ÅŸifrenizi unuttuysanız buradan alabilirsiniz! + +/tools/memadd.bml.security.friendsonly=Yalnızca ArkadaÅŸlar + +/tools/memadd.bml.security.private=Özel + +/tools/memadd.bml.security.public=Genel + +/tools/memadd.bml.title=Anılara Ekle + +/tools/memadd.bml.title.added=Eklendi + +/tools/memadd.bml.title.deleted=Silindi + +/tools/memories.bml.back=Geri + +/tools/memories.bml.edit=deÄŸiÅŸtir + +/tools/memories.bml.error.noentries.title=Hiçbir anı bulunamadı. + +/tools/memories.bml.filter.all=Bütün anılar + +/tools/memories.bml.filter.other=Yalnızca diÄŸer yazılar + +/tools/memories.bml.filter.own=Yalnızca '[[user]]' adlı kullanıcının yazıları + +/tools/memories.bml.form.switch=DeÄŸiÅŸtir + +/tools/memories.bml.uncategorized=Sınıflandırılmamış + +/update.bml.altpost=GönderildiÄŸi günlük: + +/update.bml.btn.update=Günlüğe Yaz + +/update.bml.date=Tarih: + +/update.bml.default=varsayılan + +/update.bml.defaultjournal=([[user]]) -- varsayılan + +/update.bml.error.login=Siteye giriÅŸte hata: + +/update.bml.error.update=Günlüğe yazma iÅŸleminde hata: + +/update.bml.event=Olay: + +/update.bml.localtime=Yerel saat: + +/update.bml.noneother=Hiçbiri ya da diÄŸer: + +/update.bml.opt.defpic=(varsayılan) + +/update.bml.opt.noformat=Otomatik formatlama yapma: + +/update.bml.opt.spellcheck=Göndermeden önce yazım denetimi yap + +/update.bml.options=Ä°steÄŸe BaÄŸlı Ayarlar + +/update.bml.other=DiÄŸer: + +/update.bml.picture=Kullanılacak resim: + +/update.bml.security.friends=ArkadaÅŸlar + +/update.bml.security.head=Güvenlik Seviyesi: + +/update.bml.security.private=Özel + +/update.bml.security.public=Genel + +/update.bml.spellchecked=Mesajınızın yazım denetiminden geçirilmiÅŸ hali: + +/update.bml.subject|staleness=1 +/update.bml.subject=Konu: (isteÄŸe baÄŸlı, uzun yazılarda kullanılır) + +/update.bml.title=Günlüğe Yaz + +/update.bml.update.head=Günlüğünüze yazın... + +/update.bml.update.success|staleness=1 +/update.bml.update.success=Ä°ÅŸlem tamam. Günlüğünüzün son halini buradan görebilirsiniz. + +/update.bml.updating=Günlüğe yazma... + +/userinfo.bml.about.comm|staleness=1 +/userinfo.bml.about.comm=Hakkında + +/userinfo.bml.about.user=Bilgi: + +/userinfo.bml.body.leave=Ä°stediÄŸiniz zaman topluluktan ayrılabilirsiniz. + +/userinfo.bml.comminfo.body=AÅŸağıda LiveJournal'daki "[[commname]]" topluluÄŸu ile ilgili bilgiler yer almaktadır. + +/userinfo.bml.comminfo.name=Topluluk Hakkında Bilgi + +/userinfo.bml.date.never=Asla. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Yanlış oluÅŸturulmuÅŸ kullanıcı adı. + +/userinfo.bml.error.notloggedin=Kullanıcı profilinizi görmek istiyorsanız siteye giriÅŸ yapmalısınız. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Takip edenler: + +/userinfo.bml.friendof.hidden=(gizli) + +/userinfo.bml.friendof.syndreadcount=Okuyucu Sayısı + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Kullanıcıyı arkadaÅŸ listelerine ekleyenler: + +/userinfo.bml.friends.comm=Ãœyeler + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=ArkadaÅŸları + +/userinfo.bml.label.addbuddy=ArkadaÅŸ Ekle + +/userinfo.bml.label.adduser=Kullanıcı Ekle + +/userinfo.bml.label.birthdate=DoÄŸum tarihi: + +/userinfo.bml.label.comments=Mesajlar: + +/userinfo.bml.label.composted=Gönderilen: [[num]] - + +/userinfo.bml.label.comreceived=Alınan: [[num]] + +/userinfo.bml.label.datecreated=OluÅŸturulma tarihi: + +/userinfo.bml.label.dateupdated=GüncelleÅŸtirilme tarihi: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=E-posta: + +/userinfo.bml.label.icquin=ICQ Numarası: + +/userinfo.bml.label.interests=Ä°lgi alanları + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] ilgi alanları gösterilmiyor + +/userinfo.bml.label.journalentrs=Günlükteki yazılar: + +/userinfo.bml.label.location=Yer: + +/userinfo.bml.label.memberof=Ãœyesi olduÄŸu topluluklar + +/userinfo.bml.label.memories=Anılar: + +/userinfo.bml.label.moredetails=(daha fazla bilgi...) + +/userinfo.bml.label.msnusername=MSN Kullanıcı Adı: + +/userinfo.bml.label.name=Ad: + +/userinfo.bml.label.sendmessage=Mesaj Gönder + +/userinfo.bml.label.shared|staleness=2 +/userinfo.bml.label.shared=Ortak Günlük Kullanma Ä°zni: + +/userinfo.bml.label.supportpoints=Destek noktaları: + +/userinfo.bml.label.todo=Yapılacaklar Listesi + +/userinfo.bml.label.user=Kullanıcı: + +/userinfo.bml.label.viewfriends=ArkadaÅŸları Göster + +/userinfo.bml.label.viewmembers=Ãœyeleri Göster + +/userinfo.bml.label.website=Web sitesi: + +/userinfo.bml.label.yahooid=Yahoo! Kullanıcı Adı: + +/userinfo.bml.membership.body=Bu topluluÄŸa katılmak için buraya tıklayın. + +/userinfo.bml.monitor.user=Bu kullanıcıyı arkadaÅŸ listenize ekleyin + +/userinfo.bml.nonexist.body|staleness=1 +/userinfo.bml.nonexist.body=[[user]] adında bir kullanıcı yer almıyor. Ãœzgünüz. + +/userinfo.bml.nonexist.name=Bilinmeyen kullanıcı + +/userinfo.bml.syn.last.never=Asla + +/userinfo.bml.syn.lastcheck=Son kontrol tarihi: + +/userinfo.bml.syn.parseerror=Hata Mesajı: + +/userinfo.bml.tellafriend=Bir Arkadaşınıza Haber Verin! + +/userinfo.bml.timeupdate.dayago=1 gün önce + +/userinfo.bml.timeupdate.daysago=[[num]] gün önce + +/userinfo.bml.timeupdate.hourago=1 saat önce + +/userinfo.bml.timeupdate.hoursago=[[num]] saat ago + +/userinfo.bml.timeupdate.minuteago=1 dakika önce + +/userinfo.bml.timeupdate.minutesago=[[num]] dakika önce + +/userinfo.bml.timeupdate.secondago=1 saniye önce + +/userinfo.bml.timeupdate.secondsago=[[num]] saniye önce + +/userinfo.bml.timeupdate.weekago=1 hafta önce + +/userinfo.bml.timeupdate.weeksago=[[num]] hafta önce + +/userinfo.bml.title=Kullanıcı Bilgileri + +/userinfo.bml.title.communityinfo=Topluluk Bilgileri + +/userinfo.bml.userinfo.name=Kullanıcı Bilgileri + +BML.parse_multipart.toolarge=Yüklenen dosya çok büyük + +BML.parse_multipart.unknowntype=Bilinmeyen içerik türü + +btn.search=Ara + +date.day.friday.long=Cuma + +date.day.friday.short=Cuma + +date.day.monday.long=Pazartesi + +date.day.monday.short=Pzt + +date.day.saturday.long=Cumartesi + +date.day.saturday.short=Cts + +date.day.sunday.long=Pazar + +date.day.sunday.short=Paz + +date.day.thursday.long=PerÅŸembe + +date.day.thursday.short=Per + +date.day.tuesday.long=Salı + +date.day.tuesday.short=Salı + +date.day.wednesday.long=ÇarÅŸamba + +date.day.wednesday.short=Çar + +date.month.april.long=Nisan + +date.month.april.short=Nis + +date.month.august.long=AÄŸustos + +date.month.august.short=AÄŸus + +date.month.december.long=Aralık + +date.month.december.short=Ara + +date.month.february.long=Åžubat + +date.month.february.short=Åžub + +date.month.january.long=Ocak + +date.month.january.short=Ocak + +date.month.july.long=Temmuz + +date.month.july.short=Tem + +date.month.june.long=Haziran + +date.month.june.short=Haz + +date.month.march.long=Mart + +date.month.march.short=Mart + +date.month.may.long=Mayıs + +date.month.may.short=May + +date.month.november.long=Kasım + +date.month.november.short=Kas + +date.month.october.long=Ekim + +date.month.october.short=Ekim + +date.month.september.long=Eylül + +date.month.september.short=Eyl + +dystopia.btn.login=GÄ°RÄ°Åž + +dystopia.hello_anonymous=LiveJournal'a hoÅŸgeldiniz! + +dystopia.hello_loggedin=Merhaba, [[username]]! + +dystopia.nav.createjournal=Bir Günlük oluÅŸtur + +dystopia.nav.developer=GeliÅŸtirici Bölgesi + +dystopia.nav.download=Yükle + +dystopia.nav.editentries=Günlük Yazılarını DeÄŸiÅŸtir + +dystopia.nav.editfriends=ArkadaÅŸlarınız + +dystopia.nav.editpassword=Åžifreniz + +dystopia.nav.editpics=Resimleriniz + +dystopia.nav.editstyle=Biçem DeÄŸiÅŸtir + +dystopia.nav.faq=LiveJournal SSS + +dystopia.nav.findcomm=TopluluÄŸa Göre + +dystopia.nav.finddir=Rehberde Arama + +dystopia.nav.findint=Ä°lgi Alanına Göre + +dystopia.nav.findrandom=Rasgele + +dystopia.nav.findregion=Bölgeye Göre + +dystopia.nav.home=Ana Sayfa + +dystopia.nav.journalcalendar=Takvim + +dystopia.nav.journalfriends=ArkadaÅŸlar + +dystopia.nav.journalinfo=Kullanıcı Bilgileri + +dystopia.nav.journalrecent=En son hali + +dystopia.nav.legalprivacy=Gizlilik + +dystopia.nav.legaltos=Hizmet KoÅŸulları + +dystopia.nav.login=GiriÅŸ + +dystopia.nav.logout=Çıkış + +dystopia.nav.lostinfo=Kayıp Åžifre + +dystopia.nav.memories=Anılar + +dystopia.nav.modifyjournal=Görünümü DeÄŸiÅŸtir + +dystopia.nav.news=Haberler + +dystopia.nav.paidaccts=Paralı Hesaplar + +dystopia.nav.personalinfo=KiÅŸisel Bilgiler + +dystopia.nav.sitemap=Site Haritası + +dystopia.nav.support=Bir sorunuz mu var? + +dystopia.nav.updatejournal=Günlüğe Yaz + +dystopia.navhead.findusers=Kullanıcı Bul + +dystopia.navhead.help=Yardım ve Destek + +dystopia.navhead.journal=Günlüğünüz + +dystopia.navhead.legal=Yasal + +dystopia.navhead.settings=Ayarlarınız + +dystopia.navhead.welcome=HoÅŸgeldiniz! + +dystopia.search.icq=ICQ Numarası + +dystopia.search.int=Ä°lgi alanı + +dystopia.search.msn=MSN Kullanıcı Adı + +dystopia.search.region=Bölge + +dystopia.search.yahoo=Yahoo! Kullanıcı Adı + +dystopia.searchlj=LiveJournal'da ara: + +Email=E-posta + +email.newacct.subject=LiveJournal'a hoÅŸgeldiniz + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Hata + +error.badpassword=Yanlış Åžifre. + +error.dberror=Veritabanında bir hata oluÅŸtu: + +error.deleted.name=SilinmiÅŸ + +error.deleted.title=SilinmiÅŸ Hesap + +error.malformeduser=Yanlış oluÅŸturulmuÅŸ kullanıcı adı. + +error.nodb=Veritabanı geçici olarak servis dışı. + +error.nodbmaintenance=Veritabanının bu bölümü bakım amacıyla geçici olarak servis dışıdır. Birkaç dakika sonra tekrar deneyin. + +error.noentry=Günlükte böyle bir yazı yok. + +error.nojournal=Bilinmeyen Günlük + +error.noremote=Bu sayfayı kullanmak için siteye giriÅŸ yapmalısınız. + +error.procrequest=Ä°steÄŸinizin yerine getirilmesi sırasında bir hata meydana geldi. + +error.purged.name=SilinmiÅŸ + +error.suspended.name=Askıda + +error.suspended.title=Askıya Alınan Hesap + +error.usernameinvalid=Kullanıcı adında geçersiz karakterler var. + +error.usernamelong=Kullanıcı adı çok uzun. Maksimum 15 karakteri geçmemelidir. + +error.username_notfound=Kullanıcı adı bulunamadı. + +Help=Yardım + +label.security.friends=ArkadaÅŸlar + +label.security.head=Güvenlik Seviyesi: + +label.security.private=Özel + +label.security.public=Genel + +label.switch.button=DeÄŸiÅŸtir + +label.switch.header=Günlük DeÄŸiÅŸtir + +label.switch.workwith=Çalışılacak günlük: + +langname.be=Beyaz Rusça + +langname.da=Danca + +langname.de=Almanca + +langname.en=Ä°ngilizce + +langname.en_GB=Ä°ngilizce (BK) + +langname.en_LJ=Ä°ngilizce + +langname.es=Ä°spanyolca + +langname.et=Estonyaca + +langname.fi=Fince + +langname.fr=Fransızca + +langname.ga=Ä°rlandaca + +langname.gd=Keltçe + +langname.he=Ä°branice + +langname.hu=Macarca + +langname.is=Ä°zlandaca + +langname.it=Ä°talyanca + +langname.ja=Japonca + +langname.la=Latince + +langname.lv=Letonyaca + +langname.ms=Malayca + +langname.nb=Norveççe BokmÃ¥l + +langname.nl=Felemenkçe (Hollanda) + +langname.nn=Norveççe Nynorsk + +langname.pl=Lehçe + +langname.pt=Portekizce + +langname.ru=Rusça + +langname.sv=Ä°sveççe + +langname.tr=Türkçe + +langname.zh=BasitleÅŸtirilmiÅŸ Çince + +lostinfo.head=Bir ÅŸey mi unuttunuz? + +lostinfo.text=Kullanıcı adınızı ya da ÅŸifrenizi unuttuysanız buradan geri alabilirsiniz. + +Password=Åžifre + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Ãœzgünüz + +talk.anonwrote=Biri yazdı, + +talk.anonwrote_comm=Biri [[commlink]]'de yazdı, + +talk.btn.preview=Önizle + +talk.commentpermlink=baÄŸlantı + +talk.commentpost=Yeni bir mesaj gönder + +talk.commentsread=Mesajları oku + +talk.error.comm_deleted=Bu mesaj silindi. + +talk.error.deleted=Bu günlük silindi. + +talk.error.deleted.title=Silindi + +talk.error.mustlogin=Bu korunmuÅŸ yazıyı görebilmek için siteye giriÅŸ yapmalısınız. + +talk.error.nocomment=Bu mesaj mevcut deÄŸil. + +talk.error.noentry=Böyle bir yazı yok. + +talk.error.nojournal=Hata: günlük tespit edilemedi. + +talk.error.nosuchjournal=Böyle bir günlük yok. + +talk.error.notauthorised=Bu konrunmuÅŸ yazıyı görmeye yetkiniz yok. + +talk.error.suspended=Bu günlük/kiÅŸi askıya alındı. + +talk.error.suspended.title=Askıya Alındı + +talk.parentlink=Ana + +talk.readsimilar=Günlükteki buna benzer yazıları oku: + +talk.replytothis=Yanıtla + +talk.somebodywrote=[[realname]] ([[userlink]]) yazdı, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]), [[commlink]]'de yazdı, + +talk.spellcheck|staleness=1 +talk.spellcheck=Önizleme esnasında yazım denetimi + +talk.threadlink=Mesaj Zinciri + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_turkish + +Username=Kullanıcı Adı + diff --git a/ljcom/bin/upgrading/uk.dat b/ljcom/bin/upgrading/uk.dat new file mode 100644 index 0000000..8b89b2c --- /dev/null +++ b/ljcom/bin/upgrading/uk.dat @@ -0,0 +1,3070 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Якщо ви бажаєте видалити або відновити ваш журнал, то ви може зробити це тут. Якщо ви видалили ваш журнал, але змінили Ñвою думку Ñ– вирішили відновити його, то ви можете зробити це впродовж 30 днів. ПіÑÐ»Ñ 30 днів журнал буде видалений назавжди без можливоÑÑ‚Ñ– відновленнÑ. + +/accountstatus.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ðктивації Журналу + +/accountstatus.bml.journalstatus.select.activated=Ðктивний + +/accountstatus.bml.journalstatus.select.deleted=Видалений + +/accountstatus.bml.journalstatus.select.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/accountstatus.bml.journalstatus.select.suspended=Призупинений + +/allpics.bml.current=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/allpics.bml.default=За замовчуваннÑм + +/allpics.bml.edit2=Можливо Ð²Ð°Ñ Ñ†Ñ–ÐºÐ°Ð²Ð¸Ñ‚ÑŒ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… зображень чи загрузка нових зображень. + +/allpics.bml.error.noparam=Вам потрібно визначити параметр кориÑтувача + +/allpics.bml.keywords=Ключові Ñлова: + +/allpics.bml.nopics.text.other=Цей кориÑтувач не завантажив жодного зображеннÑ. + +/allpics.bml.nopics.text2=Ви не завантажили жодного зображеннÑ. Це можна зробити тут. + +/allpics.bml.nopics.title=Ðемає зобажень + +/allpics.bml.pics=Це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача [[user]]. + +/allpics.bml.title=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/changepassword.bml.btn.proceed=Продовжити + +/changepassword.bml.changepassword.header=Замінити пароль + +/changepassword.bml.changepassword.instructions=Ð”Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð·Ð°Ð¿Ð¾Ð²Ð½Ñ–Ñ‚ÑŒ наведену нижче форму. ОзнайомтеÑÑ Ð· цією Ñторінкою Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ вдалого Ð¿Ð°Ñ€Ð¾Ð»Ñ Ñ‚Ð° Ð´Ð»Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ вашого акаунту. + +/changepassword.bml.email.body<< +Ваш пароль Ð´Ð»Ñ [[sitename]] було змінено. + +Щоб отримати його, зайдіть на Ñторінку + +[[siteroot]]/lostinfo.bml + +З повагою, +Команда [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Зміна паролю + +/changepassword.bml.error.badcheck=Поганий новий пароль: [[error]] + +/changepassword.bml.error.badnewpassword=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ паролю не Ñпівпадає з новим паролем. Можливо ви помилилиÑÑ Ð¿Ñ€Ð¸ наборі. Будь лаÑка, наберіть та підтвердіть новий пароль знову. + +/changepassword.bml.error.badoldpassword=Ваш Ñтарий пароль невірний. + +/changepassword.bml.error.blankpassword=Ваш новий пароль не може бути пуÑтим. + +/changepassword.bml.error.changetestaccount=Ðе можу змінити пароль теÑтового акаунту. + +/changepassword.bml.error.characterlimit=Довжина Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð° 30 Ñимволами. + +/changepassword.bml.error.invaliduser=Ðевірний кориÑтувач [[user]]. Такого кориÑтувача не Ñ–Ñнує. Ви впевнені, що вказали Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача коректно? + +/changepassword.bml.error.mustenterusername=Ви повинні ввеÑти ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/changepassword.bml.error.nonascii=У паролі допуÑкаєтьÑÑ Ð²Ð¸ÐºÐ¾Ñ€Ð¸Ñтовувати тільки ASCII-Ñимволи. Будь лаÑка, оберіть пароль, що викориÑтовує тільки ASCII-Ñимволи. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Ви не можете змінити ваш пароль, Ñкщо ваш email не було перевірено. + +/changepassword.bml.newpassword=Ðовий пароль: + +/changepassword.bml.newpasswordagain=Ðовий пароль (повторно): + +/changepassword.bml.oldpassword=Старий пароль: + +/changepassword.bml.proceed.instructions=ÐатиÑніть кнопку внизу Ñ– ваш пароль буде змінено. Ви отримаєте лиÑта, що заÑвідчить зміну паролÑ. + +/changepassword.bml.success.text=Ваш пароль змінено та було надіÑлано на вашу адреÑу лиÑта із повідомленнÑм про це. + +/changepassword.bml.title=Змінити пароль + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge, де ви знайдете відповіді на багато з питань що в Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ½ÑƒÑ‚ÑŒ. Відвідайте , вивчіть Ñ– Ñтанете майже миттєво профі +p?> + + +
    +Додати до ÑпиÑку друзів, щоб не відÑтавати від подій та проблем, котрі влаÑтиві навіть Ñпільнотам Живого Журналу.
    +Додати до ÑпиÑку друзів, щоб бути інформованим про вÑÑ– заплановані зупинки ÑервіÑу, та мати змогу повідомлÑти адмініÑтрацію Живого Журналу про незаплановані. +p?> + + + +AIM, ICQ, Yahoo!, MSN, або Jabber Якщо Ñ– ви ними кориÑтуєтеÑÑŒ, впевнітьÑÑ, що повідомили про це в вашихналаштуваннÑÑ… про перÑональну інформацію. Якщо у Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ð¹ акаунт, ви також можете вказати Ñвій номер мобільного телефону та пейджер щоб отримувати текÑтові повідомленнÑ. +p?> + + +платний акаунт. Є звичайно й інші ÑпоÑоби підтримати наÑ. +

    +Живий Журнал - це Open Source проект; Ñкщо ви володієте мовами программуваннÑ, вмієте Ñтворювати server side applications, ви можете приєднатиÑÑŒ до Ñпільноти розробників Живого Журналу, . Якщо у Ð²Ð°Ñ Ñ” ідеї, Ñк покращити Живий Журнал, відмітьте Ð£Ð½Ñ–Ñ ÐŸÑ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¹ Живого Журналу, . Якщо ви хочете чимоÑÑŒ краще допомогти, відвідайте Ð‘Ñ–Ð·Ð½ÐµÑ Ñпільноту Живого Журналу, . Якщо вам подобаєтьÑÑ Ð´Ð¾Ð¿Ð¾Ð¼Ð°Ð³Ð°Ñ‚Ð¸ людÑм, відвідайте наш центр техпідтримки Ñ– допоможіть кому-небуть з новачків. Якщо володієте навичками графічного дизайну, позначте Ðрт-Ñпільнота Живого Журналу, . +p?> + + +мультÑшок до Дзен будизму, від аÑтрономії до "Zim". Ви також знайдете регіональні Ñпільноти Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого куточка Ñвіту. Скоріш за вÑе Ñ” Ñпільнота й вашої міÑцини також! +p?> + + +FAQ опиÑано, що потрібно щоб Ñтвори влаÑну Ñпільноту. Також Ñ” пара тематичних FAQ (ОÑновні FAQ-и про Ñпільноти Ñ– FAQ по управлінню Ñпільнотами ) міÑÑ‚ÑÑ‚ÑŒ майже вÑе що може вам знадобитиÑÑ. Якщо ж ви вÑетаки потребуєте більше інформації, ÑкориÑтайтеÑÑŒ формою подачі запиту до техпідтримки. +p?> + + + + + + + +E-mail Jesse Proulx, () the Community Director. +p?> +. + +/community/index.bml.title=Центр Ñпільнот + +/community/join.bml.button.join=ПриєднатиÑÑ Ð´Ð¾ Ñпільноти + +/community/join.bml.label.addtofriends=Додати "[[maintainer]]" до ÑпиÑку друзів. + +/community/join.bml.label.allowposting=Ð¦Ñ Ñпільнота дозволÑÑ” пиÑати уÑім учаÑникам, тому ви можете Ñтворювати у ній нові запиÑи. Якщо у Ð²Ð°Ñ Ð²Ð¶Ðµ запущено програму-клієнт, необхідно припинити Ñ—Ñ— роботу та знову завантажити, щоб Ñ†Ñ Ñпільнота з'ÑвилаÑÑ Ñƒ ÑпиÑку журналів, до Ñких ви можете пиÑати. + +/community/join.bml.label.auth=Ðе дивлÑчиÑÑŒ на те, що ви Ñ” учаÑником цієї Ñпільноти, ви не можете до неї пиÑати. Якщо ви бажаєте отримати право пиÑати у цю Ñпільноту, зв'ÑжітьÑÑ Ð· одним з наглÑдачів. СпиÑок наглÑдачів цієї Ñпільноти: [[admins]] + +/community/join.bml.label.banned=ÐаглÑдач ціє Ñпільноти заборонив вам приєднуватиÑÑ. + +/community/join.bml.label.closed=Ð¦Ñ Ñпільнота закрита. Якщо ви бажаєте приєднатиÑÑŒ, будь лаÑка, зв'ÑжітьÑÑ Ð· одним з наглÑдачів. СпиÑок наглÑдачів цієї Ñпільноти: [[admins]] + +/community/join.bml.label.commlogged=Ви увійшли під Ñпільним запиÑом або запиÑом Ñпільноти, не під вашим перÑональним запиÑом + +/community/join.bml.label.errorcomminfo=Вказана Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñпільноту не Ñ” припуÑтимою. + +/community/join.bml.label.expls=ÐатиÑніть кнопку нижче, щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти "[[maintainer]]". Зніміть помітку, Ñкщо ви не бажаєте бачити запиÑи зі Ñпільноти у вашій Ñтрічці друзів. + +/community/join.bml.label.loginfirst=Щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти Ñпочатку ви повинні увійти до журналу. + +/community/join.bml.label.membernow=Тепер ви Ñ” учаÑником Ñпільноти [[commname]] + +/community/join.bml.label.sure=Ви впевнені? + +/community/join.bml.success=УÑпішно + +/community/join.bml.title=ПриєднатиÑÑŒ до Ñпільноти + +/community/leave.bml.button.leave=Залишити Ñпільноту + +/community/leave.bml.label.buttontoleave=ÐатиÑніть кнопку унизу, щоби покинути Ñпільноту "[[commname]]". + +/community/leave.bml.label.infoerror=Вказана Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ñ–Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñпільноту не Ñ” припуÑтимою. + +/community/leave.bml.label.logoutfirst=Щоб залишити Ñпільноту, Ñпочатку ви повинні увійти до журналу. + +/community/leave.bml.label.removed=Тепер Ð²Ð°Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð¾ зі Ñпільноти [[commname]] + +/community/leave.bml.label.removefromfriends=Також вилучити "[[user]]" зі ÑпиÑку друзів. + +/community/leave.bml.success=УÑпішно + +/community/leave.bml.sure=Ви впевнені? + +/community/leave.bml.title=Залишити Ñпільноту + +/community/manage.bml.commlist.actinfo=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/community/manage.bml.commlist.actions=Дії + +/community/manage.bml.commlist.actmembers=[УчаÑники] + +/community/manage.bml.commlist.actmembers2=УчаÑники + +/community/manage.bml.commlist.actsettings=[Параметри] + +/community/manage.bml.commlist.actsettings2=Параметри + +/community/manage.bml.commlist.header=Ваші Ñпільноти + +/community/manage.bml.commlist.none=Ви не керуєте жодною Ñпільнотою. + +/community/manage.bml.commlist.text=Цими Ñпільнотами ви керуєте або допомагаєте керувати: + +/community/manage.bml.commlist.title=Ðазва + +/community/manage.bml.commlist.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/community/manage.bml.create.header=Створити Ñпільноту + +/community/manage.bml.create.text=Ви також можете Ñтворити нову Ñпільноту. + +/community/manage.bml.title=Керувати Ñпільнотою + +/community/members.bml.error.alreadyadded=[[user]] не був доданий тому, що він вже маєть доÑтуп до Ñпільноти. + +/community/members.bml.error.alreadysent=[[user]] не може бути доданий тому, що ймоу [[datetime]] вже було надіÑлано лиÑÑ‚-підтвердженнÑ. Будь лаÑка, почекайте на його відповідь. + +/community/members.bml.error.invaliduser=Ðеможливо додати Ñпільноту чи об'єднаний акаунт: [[user]] + +/community/members.bml.error.noaccess=Тільки наглÑдачі Ñпільноти можуть редагувати ÑпиÑки учаÑників. Ви не Ñ” наглÑдачем Ñпільноти [[comm]]. + +/community/members.bml.error.noattr=Ðе вибрано атрибутів Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[user]] + +/community/members.bml.error.nocomm=Спільноту не знайдено. + +/community/members.bml.error.nouser=КориÑтувач не Ñ–Ñнує: [[user]] + +/community/members.bml.key.admin=ÐаглÑдач + +/community/members.bml.key.member=УчаÑник + +/community/members.bml.key.moderate=Модератор + +/community/members.bml.key.post=Дозволено пиÑати + +/community/members.bml.key.preapprove=Ðе цензоруєтьÑÑ + +/community/members.bml.manage2=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами + +/community/members.bml.name=Ім'Ñ Ñпільноти: [[name]] + +/community/members.bml.nextlink=(ÐаÑтупна Ñторінка...) + +/community/members.bml.prevlink=(ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка...) + +/community/members.bml.settings=[Параметри] + +/community/members.bml.success.header=УÑпішно + +/community/members.bml.success.message=Зміни уÑпішно збережено. + +/community/members.bml.success.return=ПовернутиÑÑŒ до ÑпиÑку + +/community/members.bml.title=УчаÑники Ñпільноти + +/community/members.bml.update=Оновити параметри + +/community/moderate.bml.approve.button=Так, Ñхвалити + +/community/moderate.bml.approve.header=Схвалити цей запиÑ? + +/community/moderate.bml.approve.preapprove=Також додати кориÑтувача [[user]] до ÑпиÑку немодеруємих коруÑтувачів цієї Ñпільноти. + +/community/moderate.bml.approve.text=Ви впевнені. що бажаєте Ñхвалити цей запиÑ? + +/community/moderate.bml.brlist.actions=Дії + +/community/moderate.bml.brlist.poster=Ðвтор + +/community/moderate.bml.brlist.subject=Початок теми + +/community/moderate.bml.brlist.time=Ð§Ð°Ñ + +/community/moderate.bml.brlist.view=ДивитиÑÑŒ + +/community/moderate.bml.browse.empty=Черга на Ñ†ÐµÐ½Ð·Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ. + +/community/moderate.bml.browse.header=Модерувати Ñпільноту + +/community/moderate.bml.browse.text=ОÑÑŒ черга на модерацію Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти [[link]] + +/community/moderate.bml.choice.approve=Схвалити + +/community/moderate.bml.choice.reject=Відхилити + +/community/moderate.bml.error.noaccess=Ви не модеруєте Ñпільноту [[comm]]. + +/community/moderate.bml.error.noentry=Ð—Ð°Ð¿Ð¸Ñ Ð½Ðµ знайдено (можливо, він обролений іншим модератором). + +/community/moderate.bml.error.nolist=Ви не модеруєте жодної Ñпільноти + +/community/moderate.bml.error.notfound=Ðкаунт Ñпільноти не знайдено. + +/community/moderate.bml.manage=Керувати Ñпільнотами + +/community/moderate.bml.moderate=Модерувати цю Ñпільноту + +/community/moderate.bml.modlist.actions=Дії + +/community/moderate.bml.modlist.actmodempty=[Модерувати] + +/community/moderate.bml.modlist.actmoderate=Модерувати + +/community/moderate.bml.modlist.count=Розмір черги + +/community/moderate.bml.modlist.header=Модерувати Ñпільноти + +/community/moderate.bml.modlist.title=Ðазва + +/community/moderate.bml.modlist.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/community/moderate.bml.posted.appheader=Без модерації + +/community/moderate.bml.posted.apptext=Ðа додаток, кориÑтувач [[user]] був приєднаний до ÑпиÑку немодеруємих кориÑтувачів цієї Ñпільноти. + +/community/moderate.bml.posted.header=УÑпішно + +/community/moderate.bml.posted.proterror=Ð—Ð°Ð¿Ð¸Ñ Ð½Ðµ було опубліковано через помилку протокола: [[err]] + +/community/moderate.bml.posted.text=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² уÑпішно опубліковано. + +/community/moderate.bml.reject.button=Так, відхилити + +/community/moderate.bml.reject.header=Відхилити цей запиÑ? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=Ви можете поÑÑнити автору причини, з Ñких ви відхилÑєте цей запиÑ. Вони будуть відправлені йому по e-mail. + +/community/moderate.bml.reject.text=Ви впевнені, що хочете відхилити цей запиÑ? + +/community/moderate.bml.rejected.header=Відхилено. + +/community/moderate.bml.rejected.text=Ð—Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÐµÐ½Ð¾. + +/community/moderate.bml.title=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ñ–Ñ Ñпільноти + +/community/search.bml.button.clear=ОчиÑтити форму + +/community/search.bml.button.search=Шукати! + +/community/search.bml.checkbox.onlywithpics=Тільки Ñпільноти з зображеннÑми + +/community/search.bml.label.byinterest=За інтереÑами + +/community/search.bml.label.bylocation=За міÑцезнаходженнÑм + +/community/search.bml.label.bytime=За чаÑом Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/community/search.bml.label.city=МіÑто: + +/community/search.bml.label.country=Країна: + +/community/search.bml.label.displayoptions=Показати опції + +/community/search.bml.label.hasmember=Має учаÑників + +/community/search.bml.label.othercriteria=Інші критерії + +/community/search.bml.label.outputformat=Формат виводу: + +/community/search.bml.label.records=ЗапиÑів на Ñторінку: + +/community/search.bml.label.searchcomm=Шукати Ñпільноти + +/community/search.bml.label.selecriteria=Виберіть критерії, за Ñкими ви бажаєте шукати Ñпільноти. Результатом пошуку буде перетин по уÑім критеріÑм. Іншими Ñловами, кожна помічена Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð¾Ð·Ð½Ð°Ñ‡Ð°Ñ” "І", а не "ÐБО". + +/community/search.bml.label.sortmethod=Метод ÑортуваннÑ: + +/community/search.bml.label.stateprovince=Штат/облаÑÑ‚ÑŒ + +/community/search.bml.label.updated=ОÑтанній раз оновлювалоÑÑŒ протÑгом + +/community/search.bml.sel.bypicture=По зображеннÑм + +/community/search.bml.sel.communityname=Ðазва Ñпільноти + +/community/search.bml.sel.commview=Вид Ñпільноти + +/community/search.bml.sel.day=Ð´Ð½Ñ + +/community/search.bml.sel.month=міÑÑÑ†Ñ + +/community/search.bml.sel.simple=ПроÑтий + +/community/search.bml.sel.updatetime=За чаÑом Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/community/search.bml.sel.username=За іменем кориÑтувача + +/community/search.bml.sel.week=Ñ‚Ð¸Ð¶Ð½Ñ + +/community/search.bml.title=Пошук Ñпільноти + +/community/settings.bml.button.changecommunity=Оновити параметри + +/community/settings.bml.button.createcommunity=Створити Ñпільноту + +/community/settings.bml.error.badpassword=Ðевірний пароль Ñпільноти + +/community/settings.bml.error.hasentries=Цей акаунт вже має запиÑи Ñ– не може бути перетворений. + +/community/settings.bml.error.maintainertype=ÐаглÑдачем має бути оÑоба, а не інший Ñпільний акаунт. + +/community/settings.bml.error.noaccess=Тільки наглÑдач Ñпільноти може редагувати параметри Ñпільноти. Ви не Ñ” наглÑдачем Ñпільноти [[comm]]. + +/community/settings.bml.error.notcomm=Це не акаунт Ñпільноти. + +/community/settings.bml.error.notfound=Ðкаунт Ñпільноти не знайдено. + +/community/settings.bml.error.samenames=Ðкаунти наглÑдача Ñ– Ñпільноти не можуть бути тим Ñамим. + +/community/settings.bml.label.anybodycan=Ð’ÑÑ– учаÑники
    Будь-хто з учаÑників може пиÑати. + +/community/settings.bml.label.changeheader=Змінити параметри Ñпільноти + +/community/settings.bml.label.changetext=Тут ви можете змінити параметри Ñпільноти, Ñкою ви керуєте або допомагаєте наглÑдати. + +/community/settings.bml.label.commchanged=Параметри вашої Ñпільноти змінено. + +/community/settings.bml.label.commcreate=Це акаунт, Ñкий ви бажаєте перетворити на Ñпільноту. Він повинен Ñ–Ñнувати, але не повинен викориÑтовуватиÑÑŒ кимоÑÑŒ індивідуально, тому що піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ багато різних кориÑтувачів матимуть змогу пиÑати в нього. + +/community/settings.bml.label.commcreated=Спільноту Ñтворено. + +/community/settings.bml.label.commheader=Ðкаунт Ñпільноти + +/community/settings.bml.label.comminfo=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñпільноту. + +/community/settings.bml.label.commopts=Опції Ñпільноти + +/community/settings.bml.label.commsite=ВебÑайт Ñпільноти + +/community/settings.bml.label.community=Спільнота: + +/community/settings.bml.label.createheader=Створити Ñпільноту + +/community/settings.bml.label.createtext=ЗвідÑи ви можете Ñтворити акаунт Ñпільноти. Спільнота Ñ” Ñпеціальним типом акаунту, до Ñкого інші кориÑтувачі можуть приєднуватиÑÑ Ñ‚Ð° пиÑати. Ð”Ð»Ñ Ð¿Ñ€Ð¸ÐºÐ»Ð°Ð´Ñƒ Ñпільноти подивітьÑÑ Ñ†ÐµÐ½Ñ‚Ñ€ підтримки українÑької мови. + +/community/settings.bml.label.howoperates=Оберіть Ñким чином ваша Ñпільнота оперуєтьÑÑ. Ви можете змінити це пізніше. + +/community/settings.bml.label.maintainer=ÐаглÑдач: + +/community/settings.bml.label.maintainer.login=Якщо це не акаунт наглÑдача, увійдіть до журналу Ñк хтоÑÑŒ інший. + +/community/settings.bml.label.membership=УчаÑÑ‚ÑŒ + +/community/settings.bml.label.modheader=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ñ–Ñ + +/community/settings.bml.label.modis=Модерована
    Ðові запиÑи мають бути Ñхвалені модератором. + +/community/settings.bml.label.modisnt=Ðемодерована
    Ðові запиÑи з'ÑвлÑÑ‚ÑŒÑÑ Ð¾Ð´Ñ€Ð°Ð·Ñƒ. + +/community/settings.bml.label.modtext=Ð¦Ñ Ñпільнота Ñ” модерованою? + +/community/settings.bml.label.nmcan=УÑÑ– можуть пиÑати
    КориÑтувачі можуть пиÑати у Ñпільноту не приєднуючиÑÑŒ до неї. + +/community/settings.bml.label.nmcant=Тільки учаÑники можуть пиÑати
    КориÑтувачі мають приєднатиÑÑ Ð´Ð¾ Ñпільноти, щоби мати право пиÑати у неї. + +/community/settings.bml.label.nmheader=ДоÑтуп Ð´Ð»Ñ Ð½Ðµ-учаÑників + +/community/settings.bml.label.nmtext=Чи можуть криÑтувачі пиÑати до Ñпільноти, не приєднуючиÑÑŒ до неї? + +/community/settings.bml.label.openmemb=Відкрита учаÑÑ‚ÑŒ
    Хто завгодно можє приєднатиÑÑ Ð´Ð¾ Ñпільноти. + +/community/settings.bml.label.password=Пароль: + +/community/settings.bml.label.postaccess=ДоÑтуп до напиÑÐ°Ð½Ð½Ñ + +/community/settings.bml.label.rellinks=Важливі поÑиланнÑ: + +/community/settings.bml.label.selcan=Виберіть учаÑників
    Тільки Ñ‚Ñ– учаÑники можуть пиÑати, Ñким дозволив наглÑдач. + +/community/settings.bml.label.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/community/settings.bml.label.whocanjoin=Хто може приєднуватиÑÑ Ð´Ð¾ Ñпільноти? + +/community/settings.bml.label.whocanpost=Хто може пиÑати у Ñпільноту? + +/community/settings.bml.manage2=Керувати Ñпільнотами + +/community/settings.bml.members=[УчаÑники] + +/community/settings.bml.name=Ðазва Ñпільноти: [[name]] + +/community/settings.bml.success=УÑпішно + +/community/settings.bml.title.create=Створити Ñпільноту + +/community/settings.bml.title.modify=Опції Ñпільноти + +/create.bml.age.check.question=Вам менше 13 років? + +/create.bml.age.check.yes=Так, мені менше 13 років. + +/create.bml.age.check2.question=Вам більше 13 років? + +/create.bml.age.check2.yes=Так, мені більше 13 років. + +/create.bml.age.head=Вік + +/create.bml.btn.create=Створити журнал + +/create.bml.btn.proceed=Продовжити... + +/create.bml.clusterselect.cluster=КлаÑтер: + +/create.bml.clusterselect.clusternum=КлаÑтер [[number]] + +/create.bml.clusterselect.head=Вібір клаÑтеру + +/create.bml.clusterselect.nocluster=Ðемає клаÑтеру + +/create.bml.clusterselect.text=Будь лаÑка, оберіть клаÑтер, в Ñкому бажаєте Ñтворити новий акаунт. Зауважте: Це відладова/теÑтова опціÑ. Її не бачитимуть та не знатимуть кінцеві кориÑтувачі. + +/create.bml.create.head=Створити новий журнал + +/create.bml.create.text=Створити новий журнал дуже проÑто, тільки Ñлідкуйте інÑтрукцій! + +/create.bml.email.head=Ваша електронна адреÑа (email) + +/create.bml.email.input.head=Електронна адреÑа (email): + +/create.bml.error.coppa.under13=Вибачте, але за заборонами COPPA, ви не маєте права кориÑтуватиÑÑ Ð–Ð¸Ð²Ð¸Ð¼ Журналом. Будб лаÑка, повертайтеÑÑ Ð¿Ñ–ÑÐ»Ñ 13-Ñ— річниці. + +/create.bml.error.email.blank=Ви повинні надати ваш email. + +/create.bml.error.email.lj_domain=Ви не можете викориÑтовувати e-mail на [[domain]]. Будь лаÑка, вкажіть іншу адреÑу e-mail. + +/create.bml.error.email.nospaces=Ð’ електронній адреÑÑÑ– не повинно бути пробілів. Якщо ви абонент AOL, памÑтайте, що ваша адреÑа Ñ” вашим ÐОL-ім'Ñм з видаленими пробілами, що закінчуєтьÑÑ @aol.com + +/create.bml.error.password.asciionly=У паролі можливо викориÑÑ‚Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ Ñимволів ASCII. + +/create.bml.error.password.blank=Ви повинні ввеÑти пароль. + +/create.bml.error.password.nomatch=Паролі не Ñпівпадають. + +/create.bml.error.username.blank=Будь лаÑка, вкажіть ім'Ñ Ð°Ð±Ð¾ назву чи призвіÑько. + +/create.bml.error.username.inuse=І'Ð¼Ñ Ð²Ð¶Ðµ викориÑтовуєтьÑÑ; будь лаÑка, виберіть інше. + +/create.bml.error.username.iscode=Введене ім'Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ Ñхоже на код-запрошеннÑ, ніж на ім'Ñ. + +/create.bml.error.username.mustenter=Ви повинні ввеÑти Ñ–'Ð¼Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/create.bml.error.username.reserved=Вибачте, це зарезервоване Ñ–'мÑ. + +/create.bml.initial.friend.lj_maintenance=Звіти про заплановані та незаплановані проÑтої ÑервіÑу та підтримка. + +/create.bml.initial.friend.news=Ðовини та події Живого Журналу + +/create.bml.initialfriends=Дадати ці журнали до ÑпиÑку друзів, що буде поповнюватиÑÑŒ на Ñторінці з новинами та інформацією. + +/create.bml.initialfriends.heading=Початкові друзі + +/create.bml.name.head=Ваше ім'Ñ + +/create.bml.name.input.head=Ім'Ñ: + +/create.bml.name.text=Яке ваше ім'Ñ Ñ‡Ð¸ прізвиÑько? Воно з'ÑвитьÑÑ Ð² заголовку вашого журналу. Ртакож щоб опинитиÑÑŒ в ÑпиÑку кориÑтувачів. Ви не зобов'Ñзані вказувати ваше Ñправжнє Ñ– тим більше повне ім'Ñ. + +/create.bml.password.head=Пароль + +/create.bml.password.input.head1=Пароль: + +/create.bml.password.input.head2=Підтвердіть пароль: + +/create.bml.password.text=Оберіть пароль. + +/create.bml.proceed.btn.proceed=Продовжити... + +/create.bml.proceed.warning=ÐатиÑкайте Продовжити лише один раз!! + +/create.bml.success.btn.enterinfo=Введіть перÑональну інформацію + +/create.bml.success.head=УÑпішно! + +/create.bml.success.text1=Ваш журнал було Ñтворено. Важлива реєÑтраційна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ»Ð° виÑлана на [[email]], Ñка міÑтить подальші інÑтрукції. Обов'Ñзково підтвердіть реєÑтрацію, клікнувши на поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñƒ лиÑÑ‚Ñ–. + +/create.bml.success.text2=Ваш Живий Журнал буде доÑтупний тут: + +/create.bml.success.text3=Ртепер, будь лаÑка, приділіть трохи чаÑу щоб заповнити деÑку інформацію про Ñебе. Вона, Ñк правило, не обов'Ñзкова, але дає можливіÑÑ‚ÑŒ зрозуміти, хто кориÑтуєтьÑÑ Ñ†Ð¸Ð¼ журналом. + +/create.bml.title=Створити новий журнал + +/create.bml.tos.error=Ви повинні прочитати та погодитиÑÑŒ з умовами викориÑÑ‚Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ перед його ÑтвореннÑм. + +/create.bml.tos.haveread=Я прочитав та погодивÑÑ Ð· умовами викориÑтаннÑ. + +/create.bml.tos.heading=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +/create.bml.useacctcodes.entercode=Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ журналу, введіть код. Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ вичерпної інформації читайте Як мені Ñтворити акаунт? + +/create.bml.useacctcodes.welcome=ЛаÑкаво проÑимо + +/create.bml.username.box.head=Ð†Ð¼Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/create.bml.username.charsallowed=Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача повинне ÑкладатиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ з латинÑьких літер нижнього регіÑтру (a-z), цифр (0-9) та Ñимволу підкреÑÐ»ÐµÐ½Ð½Ñ (_).
    До того ж воно не повинне ÑкладатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ ніж з 15 Ñимволів. + +/create.bml.username.forpaidaccts=Ðбо платний акаунт: + +/create.bml.username.head=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/create.bml.username.ljaddress=Ваш журнал буде за цією адреÑою: + +/create.bml.username.text=Кожний [[sitename]] кориÑтувач повинен мати унікальне Ñ–'мÑ. Ваше Ñ–'Ð¼Ñ - це те, що відображаєтьÑÑ Ð² адреÑÑ– вашого журналу та викориÑтовуєтьÑÑ Ð²Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ до [[sitename]] Ñерверу. Воно також відображаєтьÑÑ, коли ви залишаєте коментарі в журналах інших людей. + +/create.bml.username.username=ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/customize/index.bml.change=Змінити + +/customize/index.bml.choose=Бажаєте кориÑтуватиÑÑŒ Ñтарою ÑиÑтемою Ñтилів, чи новою? + +/customize/index.bml.choose.header=Оберіть ÑиÑтему Ñтилів + +/customize/index.bml.choose.s1=Стара ÑиÑтема (S1) + +/customize/index.bml.choose.s2=Ðова ÑиÑтема (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ðе вдаєтьÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ рівень кориÑтувача. + +/customize/index.bml.error.fail_create_style=Ðеможливо Ñтворити новий Ñтиль. + +/customize/index.bml.error.not_your_layout=Ðе ваша Ñхема. + +/customize/index.bml.error.not_your_theme=Ðе ваша тема + +/customize/index.bml.error.no_core_parent=без базового предка? + +/customize/index.bml.previews=(Попередній переглÑд) + +/customize/index.bml.s1=Стару ÑиÑтему Ñтилей можна наÑтроїти на Ñторінці ÐаÑтроїти журнал + +/customize/index.bml.s1.header=ВикориÑтовуючи S1 + +/customize/index.bml.s2.advanced.denied=Тільки платні, ранні та поÑтійні кориÑтувачі можуть викориÑтовувати розширений набір заÑобів. ДізнатиÑÑŒ про переваги платного акаунта. + +/customize/index.bml.s2.advanced.header=Розширений набір заÑобів + +/customize/index.bml.s2.advanced.permitted=Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… Ñхеми та Ñтилю з чернетки відвідайте розділ розширених налаштувань. + +/customize/index.bml.s2.customize=ÐаÑтупні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð°Ñ‚ÑŒ від обраної Ñхеми. + +/customize/index.bml.s2.customize.header=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñхеми + +/customize/index.bml.s2.customize.language=Ці мови чаÑтково або повніÑÑ‚ÑŽ підтримуютьÑÑ Ñ†Ñ–Ñ”ÑŽ Ñхемою. + +/customize/index.bml.s2.customize.language.custom=(Вибраний) + +/customize/index.bml.s2.customize.language.header=Мова + +/customize/index.bml.s2.customize.settings=Якщо ви бажаєте продовжити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ, тут ви можете вказати індивідуальні уÑтановки, щоб отримати той виглÑд, Ñкий бажаєте. + +/customize/index.bml.s2.customize.settings.delete=Видалити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.settings.edit=Редагувати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.settings.header=Змінити індивідуальні уÑтановки + +/customize/index.bml.s2.customize.settings.new=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.themes=Виберіть одну з наÑтупних доÑтупних тем Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñхеми. + +/customize/index.bml.s2.customize.themes.default=(Схема за замовчуваннÑм) + +/customize/index.bml.s2.customize.themes.header=Теми + +/customize/index.bml.s2.layout=Виберіть Ñхему. ОÑкільки вибір теми Ñ‚Ñ– анших налаштувань залежать від обраної Ñхеми, ви можете втратити вÑÑ– Ñвої попередні налаштуваннÑ. + +/customize/index.bml.s2.layout.header=Крок 1: Схема + +/customize/index.bml.s2.related.editinfo.about=Ð’Ñтановити назву журналу та різні опції. + +/customize/index.bml.s2.related.header=Пов'Ñзані Ñторінки + +/customize/index.bml.s2.related.links.about=ДеÑкі Ñтилі можуть включати ваш ÑпиÑок управлінÑьких поÑилань. + +/customize/index.bml.s2.related.modify.about=Вкажіть набір зображень Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу. + +/customize/index.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð–ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/delcomment.bml.changeoptions<< +Примітка: З [[link]] Ñторінки, ви можете обрати чи дозволÑти вÑім, тільки зарееÑтрованим кориÑтувачам, або +тільки друзÑм залишати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ð°Ñ. +. + +/delcomment.bml.confirm.banuser=Заборонити [[user]] коментувати в вашому журналі + +/delcomment.bml.confirm.body=Ви Ñправді хочете видалити цей коментар? + +/delcomment.bml.confirm.head=Видалити цей коментар? + +/delcomment.bml.confirm.submit=Видалити коментар + +/delcomment.bml.error.alreadydeleted=Вказаний коментар уÑпішно видалено. + +/delcomment.bml.error.cantdelete=Коментар може видалити тільки його автор або влаÑник журналу. + +/delcomment.bml.error.cantdelete.comm=Коментар може видалити його автор, автор нитки діалогу або влаÑник Ñпільноти.. + +/delcomment.bml.error.invalidtype=Ðе вірний тип коментару. + +/delcomment.bml.error.nocomment=Вибраний коментар відÑутній. + +/delcomment.bml.success.andban=Коментар видалено, кориÑтувачу [[user]] заборонено коментувати в вашому журналі. + +/delcomment.bml.success.head=Видалено + +/delcomment.bml.success.noban=Коментар видалено. + +/delcomment.bml.title=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€ÑŽ + +/developer/index.bml.clients=То ви бажаєте покращити ЖЖ-клієнт Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— платформи? Чудово! Ðижче деÑкі необхідні джерела інформації про те Ñк працює Живий Журнал. + +/developer/index.bml.clients.header=ÐапиÑÐ°Ð½Ð½Ñ Ð·Ð° допомогою ЖЖ-клієнта + +/developer/index.bml.clients.links<< +
    +
    ЖЖ Сервер<->Клієнт протокол
    +
    ДовідатиÑÑŒ Ñк ЖЖ-клієнт на вашому компутері звертаєтьÑÑ Ð´Ð¾ ЖЖ-Сервером Ñ– навпаки. + Ð Ð¾Ð·ÑƒÐ¼Ñ–Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ - первинна річ, необхідна вам Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´ роботою над покращеннÑм ЖЖ-клієнта.
    +
    Повна Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ протокол
    +
    Ð’Ñе Ñ€Ñ–Ð·Ð½Ð¾Ð¼Ð°Ð½Ñ–Ñ‚Ñ‚Ñ Ñ‚Ð¸Ð¿Ñ–Ð² протоколів & методів.
    +
    СпиÑок клієнтів
    +
    СпиÑок клієнтів, що викориÑтовуютьÑÑ Ð´Ð»Ñ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· ЖЖ. більшіÑÑ‚ÑŒ з цих клієнтів з відкритим кодом Ñ– вільно розповÑюджуютьÑÑ. Це найкраще міÑце Ð´Ð»Ñ Ð¿Ñ€Ð¸ÐºÐ»Ð°Ð´Ñ–Ð² при Ñтворенні вашого клієнта.
    +
    + +. + +/developer/index.bml.code=Щоб побачити Ñк працює мехінізм Живого Журналу, та щоб заглÑнути вÑередину деÑких з клієнтів, звернітьÑÑ Ð´Ð¾ Ñторінки Code. + +/developer/index.bml.code.header=Репозитарій коду Живого Журналу + +/developer/index.bml.dbschema<< +ЦікавлÑÑ‚ÑŒ деталі про Ñхему бази даних? SQL, що Ñтворює вÑÑ– таблиці та наповнює Ñ—Ñ… включений в Ñерверний код. + +. + +/developer/index.bml.dbschema.header=Схема бази даних. + +/developer/index.bml.embedding=Бажаєте правильно включити ваш журнал в Ñвою домашню Ñторінку? Тут кілька ÑпоÑобів Ñк це зробити в залежноÑÑ‚Ñ– від того Ñкий доÑтуп маєте до ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ Ñервером. Ви повинні піклуватиÑÑŒ тільки про це, Ñкщо ви не хочете щоб в URL вашого журналу не було приÑутнє www.livejournal.com. + +/developer/index.bml.embedding.header=Ð’Ð¿Ñ€Ð¾Ð²Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журналу + +/developer/index.bml.notice.header=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/developer/index.bml.notice1=ÐаÑтупна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð° тільки Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ñ–Ñтів та доÑвідчених кориÑтувачів. Якщо ви бажаєте викориÑтовувати ЖЖ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу, ЧУДОВО! Звичайні кориÑтувачі не повинні турбуватиÑÑŒ про наÑтупний матеріал. + +/developer/index.bml.notice2=Як вже згадано, зміÑÑ‚ нижче поділено на два розділи: Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‰Ð¾Ð´Ð¾ того Ñк налаштувати зовнішній виглÑд Ñторінки вашого ЖЖ Ñ– Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ пиÑÐ°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ð°Ð¼Ð¸ Живого Журналу на ЖЖ-Ñервер. + +/developer/index.bml.styles=Вам не подобаєтьÑÑ ÑˆÐ»ÑÑ… в Ñторінок вашого журналу? Ðе переживайте! Ð’Ñе піддаєтьÑÑ ÐºÐ¾Ñ€ÐµÐ³ÑƒÐ²Ð°Ð½Ð½ÑŽ Ñ– Ñкщо ви прочитаєте документацію нижче, ви знатимете вÑе, що потрібно, щоб шлÑÑ… до ваших мторінок був таким, Ñк вам потрібно. + +/developer/index.bml.styles.header=Вибір виглÑду Живого Журналу + +/developer/index.bml.styles.s1.header=Стиль СиÑтемний 1 + +/developer/index.bml.styles.s1.system=СиÑтемний Ñтиль + +/developer/index.bml.styles.s1.system.about=ОÑновне про вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ ÑиÑтемного Ñтилю. + +/developer/index.bml.styles.s1.varlist=СпиÑок змінних + +/developer/index.bml.styles.s1.varlist.about=Ðлфавітний перелік вÑÑ–Ñ… змінних що ви можете вибрати. + +/developer/index.bml.styles.s1.views=ПереглÑд типів + +/developer/index.bml.styles.s1.views.about=СпиÑок різноманітних ÑпоÑобів переглÑду вашого журналу, Ñкими можете ÑкориÑтатиÑÑŒ, та детальний Ð¾Ð¿Ð¸Ñ Ñ—Ñ…. + +/developer/index.bml.styles.s2.header=СиÑтемний Стиль 2 + +/developer/index.bml.styles.s2.layerbrowse=S2 Схема переглÑду + +/developer/index.bml.styles.s2.layerbrowse.about=Повний ÑпиÑок доÑтупних S2 Ñхем, що міÑÑ‚ÑÑ‚ÑŒ Ñтилі ÑиÑтеми S2. Важливим тут Ñ” Ñдро Ñхеми, що задане базовими змінними, функціÑми та клаÑами, котрі роблÑÑ‚ÑŒ S2 повнофункціональною мовою дизайну, Ñк от. + +/developer/index.bml.styles.s2.manual=S2 + +/developer/index.bml.styles.s2.manual.about=Повна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ S2 в Живому Журналі + +/developer/index.bml.title=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². + +/directory.bml.error.accounttype=Вибачте, але тип вашого акаунту не дозволÑÑ” виконувати пошук у каталозі, або ви не увійшли до журналу. Якщо тип вашого акаунту дозволÑÑ” пошук у каталозі, перевірте, чи увійшли ви до журналу. + +/doc/index.bml.about=ЛаÑкаво проÑимо до бібліотеки документації Живого Журналу. Тут ви зможете знайти більшіÑÑ‚ÑŒ опиÑÑ– ЖЖ-поÑлуг або Ñерверного програмного забезпеченнÑ. Виберіть розділ нижче: + +/doc/index.bml.about.header=ЛаÑкаво проÑимо + +/doc/index.bml.docs.faq.about=ПитаннÑ, що найчаÑтіше запитують про LiveJournal.com + +/doc/index.bml.docs.faq.title=FAQ (ПитаннÑ, що найчаÑтіше запитують) + +/doc/index.bml.docs.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/doc/index.bml.docs.howto.about=Підказки та прийоми в допомогу налаштуванню ЖЖ-акаунту + +/doc/index.bml.docs.server.about=Ð’Ñе що вам потрібно знати про вÑтановленнÑ, ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° хак ЖЖ + +/doc/index.bml.docs.server.title=Сервер ЖЖ. ІнÑÑ‚Ñ€ÑƒÐºÑ†Ñ–Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/doc/index.bml.docs.tour.about=Створено Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів, щоб познайомити з Ñайтом. + +/doc/index.bml.docs.tour.title=ОглÑд + +/doc/index.bml.title=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/doc/index.bml.volunteering.about=Якщо потребуєте допомоги, а в документацію вам ритиÑÑŒ ліньки, відвідайте наш форум: + +/doc/index.bml.volunteering.header=ВолонтерÑтво + +/doc/index.bml.volunteering.ljsysdoc=ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑиÑтеми ЖЖ-документації + +/doc/index.bml.volunteering.ljuserdoc=ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ— Ð´Ð»Ñ ÐºÑ–Ð½ÐµÑ‡Ð½Ð¸Ñ… кориÑтувачів + +/doc/tour/index.bml.clients.caption<< +Програми-клієнти Живого Журналу це невеликі програми, що запуÑкаютьÑÑ Ð½Ð° вашому компю'тері, тим Ñамим дозволÑючи вам пиÑати у ваш журнал не відкриваючи вікна браузера. +Програми-клієнти доÑтупні майже Ð´Ð»Ñ Ð²ÑÑ–Ñ… платформ та проÑÑ‚Ñ– у налаштуванні та викориÑтанні. +. + +/doc/tour/index.bml.clients.title=Клієнти + +/doc/tour/index.bml.comms.caption=Живий Журнал - це велетенÑька інтерактивна Ñпільнота, тому не дивуйтеÑÑŒ, що Ñ” так багато членів цієї Ñпільноти зі Ñхожими інтереÑами та захопленнÑми. Також ми надаємо змогу Ñтворити Ñпільноту або журнал, щоб люди могли допиÑувати туди. + +/doc/tour/index.bml.comms.title=Спільноти + +/doc/tour/index.bml.create.caption=Живий Журнал це ÑпівтовариÑтво заÑноване на дружбі. Ðа цій Ñторінці поÑÑнюєтьÑÑ, що учаÑÑ‚ÑŒ у цій Ñпільноті Ñ‚Ñгне за Ñобою, чим воно важливе та вигідне. Також тут міÑтитьÑÑ Ñ„Ð¾Ñ€Ð¼Ð° Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñного акаунту. + +/doc/tour/index.bml.create.title=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚Ñƒ + +/doc/tour/index.bml.friends.caption<< +Ви маєте змогу відÑлідковувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² журналах ваших друзів, викориÑтовуючи розділ "Друзі". +Знайшовши новий журнал, що здаєтьÑÑ Ð²Ð°Ð¼ цікавим, ви можете додати його до вашого ÑпиÑку друзів. Це даÑÑŒ вам змогу читати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð· цього журналу й надалі, по мірі Ñ—Ñ… поÑви. +. + +/doc/tour/index.bml.friends.title=Друзі + +/doc/tour/index.bml.intro.caption=Цей оглÑд Ñтворено Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… відвідувачів, щоб допомогти познайомитиÑÑŒ з Ñайтом. Тут буде вказано де знаходÑÑ‚ÑŒÑÑ Ð½Ð°Ð¹Ð²Ð°Ð¶Ð»Ð¸Ð²Ñ–ÑˆÑ– розділи, та деÑкі цікаві можливоÑÑ‚Ñ–. + +/doc/tour/index.bml.intro.title=ЛаÑкаво проÑимо + +/doc/tour/index.bml.modify.caption=Також можливо формувати ваш журнал багатьма різними ÑпоÑобами, викориÑтовуючи готові Ñтилі, та ÑиÑтеми кольорів. Зробіть ваш журнал таким же унікальним та неповторним, Ñк ви Ñамі! + +/doc/tour/index.bml.modify.title=ПерÑÐ¾Ð½Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ + +/doc/tour/index.bml.nav.next=ÐаÑтупне --> + +/doc/tour/index.bml.nav.prev=<-- Попереднє + +/doc/tour/index.bml.profile.caption<< +ВітаєтьÑÑ Ð·Ð³Ð¾Ð´Ð° кориÑтувачів Живого Журналу залишити трохи інформації про Ñебе в Ñ—Ñ… профайлах. Це дає змогу нам оцінувати аудиторію кориÑтувачів ЖЖ Ñ– ми маємо змогу краще допомагати їм. +Однак, це не Ñ” обовÑзковою вимогою, а тільки побажаннÑм. ОбовÑзковим Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñного журналу Ñ” тільки Ð²ÐºÐ°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ñтупної інформації: назва, електронна адреÑа та пароль. +. + +/doc/tour/index.bml.profile.title=Профіль + +/doc/tour/index.bml.sitemap.caption<< +СподіваємоÑÑŒ, що оглÑд дав вам трохи кориÑної початкової інформації про Ñайт Живий Журнал та його поÑлуги. +Якщо потребуєте допомоги пов'Ñзаної з Живим Журналом звернітьÑÑ Ð´Ð¾ нашого відділу підтримки. Якщо бажаєте продовжити ознайомленнÑ, звернітьÑÑ Ð´Ð¾ мапи Ñайту щоб побачити вÑÑ– Ñторінки на цьому Ñайті. +. + +/doc/tour/index.bml.sitemap.title=Мапа Ñайту + +/doc/tour/index.bml.support.caption=Сторінка підтримки міÑтить перелік розділів, що допоможуть поÑÑнити що таке Живий Журнал, чаÑÑ‚Ñ– Ð·Ð°Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ Ñайт та інша кориÑна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ поÑлуги, компанію та Ñпільноту в цілому. + +/doc/tour/index.bml.support.title=Як отримати допомогу + +/doc/tour/index.bml.title=ОглÑд - [[title]] + +/doc/tour/index.bml.update.caption<< +ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журналу Ñ” оÑновою обÑÐ»ÑƒÐ³Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð–Ð–; оÑÑŒ - те, в чому ми пропонуємо нашим кориÑтувачам поділитиÑÑŒ з нами Ñвоїм життÑм Ñ– думками. +Обновлювати журнал не Ñкладно. ПроÑто пишете Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² запрпоновану форму Ñ– натиÑкаєте клавішу "Оновити журнал". Також ви можете викориÑтовувати при оновленні журналу розширені можливоÑÑ‚Ñ–, такі Ñк перевірка правопиÑу, додаткове Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð¾ вашого Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (котру музику наразі Ñлухаєте чи Ñкий у Ð²Ð°Ñ Ð·Ð°Ñ€Ð°Ð· наÑтрій). +. + +/doc/tour/index.bml.update.title=ÐŸÐ¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/editinfo.bml.allowshowcontact.about=Краще тримати цю опцію увімкненою. Це дозволить іншим кориÑтувачам зв'ÑзатиÑÑ Ð· вами за e-mail адреÑою, номером ICQ та ім'Ñм AOL Instant Messenger, Ñкі ви вкажете у Живому Журналі. + +/editinfo.bml.allowshowcontact.email=Показувати e-mail адреÑу: + +/editinfo.bml.allowshowcontact.email.actual_only=Тільки дійÑну адреÑу + +/editinfo.bml.allowshowcontact.email.both=Обидві (дійÑну та [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Тільки адреÑу у Живому Журналі + +/editinfo.bml.allowshowcontact.email.neither=Ðе показувати жодної e-mail адреÑи. + +/editinfo.bml.allowshowcontact.email.no_show=Ðе показувати e-mail адреÑу + +/editinfo.bml.allowshowcontact.email.show=Показувати e-mail адреÑу + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Ви також можете вибрати не показувати вашу e-mail адреÑу (у той Ñ‡Ð°Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑŽÑ‡Ð¸ іншу контактну інформацію), показувати лише адреÑу в Живому Журналі (тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів), показувати тільки Ñправжню адреÑу, чи показувати обидві. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Ви також можете вибрати не показувати вашу e-mail адреÑу (у той Ñ‡Ð°Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑŽÑ‡Ð¸ іншу контактну інформацію). + +/editinfo.bml.allowshowcontact.title=Показувати вашу контактну інформацію в Живому Журналі? + +/editinfo.bml.allowshowinfo.about=Увімкніть цей перемикач, Ñкщо ви бажаєте, щоб уÑÑ– могли бачити ваше міÑто/штат/країну та день народженнÑ. + +/editinfo.bml.allowshowinfo.title=Показувати міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° день народженнÑ? + +/editinfo.bml.autotranslate.about<< +ВикориÑтовуйте цей параметр, щоб вказати нам, Ñким кодуваннÑм ви кориÑтувалиÑÑ Ð´Ð¾ переходу ЖЖ на Юнікод. +Якщо ви пиÑали англійÑькою, вкажіть "Western European". +. + +/editinfo.bml.autotranslate.header=Ðвтоматичне Ð¿ÐµÑ€ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñтарих запиÑів з кодуваннÑ: + +/editinfo.bml.bday.title=День Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/editinfo.bml.bday.year.opt=вказувати рік не обов'Ñзково + +/editinfo.bml.bdayreminders.about=Якщо ви бажаєте отримувати e-mail з нагадуваннÑм про дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… друзів, натиÑніть тут. + +/editinfo.bml.bdayreminders.header=Ðагадувати мені про дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ (тимчаÑово відключено) + +/editinfo.bml.bio.about=Тут ви можете ввеÑти міні-біографію. Вона буде показана у вашій інформації про кориÑтувача. + +/editinfo.bml.bio.header=Про Ð²Ð°Ñ + +/editinfo.bml.blockrobots.about<< +Якщо ви ввімкнете цей перемикач, роботам Ñкажуть забиратиÑÑ Ð³ÐµÑ‚ÑŒ. +Ðле не вÑÑ– роботи поважають правила. +. + +/editinfo.bml.blockrobots.header=Блокувати індекÑÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу роботами + +/editinfo.bml.chat.icquin.title=Ðомер ICQ + +/editinfo.bml.chat.msnusername.title=КориÑтувач MSN + +/editinfo.bml.chat.yahooid.title=Yahoo! ID + +/editinfo.bml.city.title=МіÑто + +/editinfo.bml.country.choose=Оберіть країну + +/editinfo.bml.country.title=Країна + +/editinfo.bml.donotlog=ÐÑ– + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=ПоÑтавте тут позначку, щоб інші кориÑтувачі могли відповідати на запиÑи у вашому журналі. + +/editinfo.bml.enableboards.header=Дозволити коментарі + +/editinfo.bml.encoding.about=Якщо ви пишете англійÑькою, залиште наÑтупні опції без змін. Ð’ іншому випадку вÑтановіть відповідні опції. + +/editinfo.bml.encoding.header=Опції Ð¿ÐµÑ€ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + +/editinfo.bml.error.day.notinmonth=Ðевірний день Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ міÑÑцÑ. + +/editinfo.bml.error.day.outofrange=Ðевірний день. Уведіть чиÑло від 1 до 31. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Ðе можна уводити адреÑу @[[domain]] . +Введіть вашу Ñправжню адреÑу у тому полі. +Якщо ви платний кориÑтувач, уÑÑ– лиÑти на адреÑу [[user]]@[[domain]] будутть переÑилатиÑÑ Ð½Ð° ваш Ñправжній адреÑ. +Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб вибрати, Ñку e-mail адреÑа (або обидві) показувати, подивітьÑÑ Ð¾Ð¿Ñ†Ñ–ÑŽ "Показувати контактну інформацію". +. + +/editinfo.bml.error.email.none=Ви повинні вказати адреÑу вашої електронної Ñкриньки + +/editinfo.bml.error.email.no_space<< +У електронній адреÑÑ– пробіли заборонені. +Якщо ви Ñ” кориÑтувачем AOL, пам'Ñтайте, що вашою e-mail адеÑою Ñ” ваше ім'Ñ AOL без пробілів, за Ñким Ñлідує @aol.com +. + +/editinfo.bml.error.excessive_int=Вибачте, але ви вказали занадто багато захоплень. Границею Ñ” 150, а ви вказали [[intcount]]. Зміни, Ñкі ви зробили, не збережено. ПовертайтеÑÑŒ та зкоротіть ваш ÑпиÑок, а потім збережіть знову. + +/editinfo.bml.error.invalidbio=Ваша Ð±Ñ–Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ñ Ð¼Ñ–Ñтить невірні Ñимволи. Відвідайте Ñторінку конвертації щоб перетворити це в Юнікод. + +/editinfo.bml.error.invalidints=Ваш поточний ÑпиÑок захоплень міÑтить невірні Ñимволи. Відвідайте Ñторінку конвертації щоб перетворити це в Юнікод. + +/editinfo.bml.error.invalidname=Ваше Ñ–'Ð¼Ñ Ð¼Ñ–Ñтить невірні Ñимволи. Відвідайте Ñторінку конвертації щоб перетворити це в Юнікод. + +/editinfo.bml.error.locale.country_ne_state=Ви вказали Сполучені Штати Ñк країну Ñвого перебуваннÑ, але вказали в розділі "інший штат" штат Ñкого в СШРнема. + +/editinfo.bml.error.locale.invalid_country=Ðевірно вибрали країну. + +/editinfo.bml.error.locale.state_ne_country=Ви обрали країну не-СШÐ, але вибрали штат що належить Сполученим Штатам. + +/editinfo.bml.error.locale.zip_ne_state=Поштовий Ñ–Ð½Ð´ÐµÐºÑ Ñ‚Ð° регіон вказані вами не відповідають одне одному. Введіть вірну інформацію, або витріть індекÑÑ‚ або\Ñ– регіон. + +/editinfo.bml.error.locale.zip_requires_us=Ви вказали поштовий індекÑ, але не вказали СШРÑк вашу країну. Ð’ Ð½Ð°Ñ Ð·Ñ–Ð±Ñ€Ð°Ð½Ñ– тільки індекÑи регіонів СШÐ. ПовернітьÑÑ Ñ‚Ð° видаліть поштовий Ñ–Ð½Ð´ÐµÐºÑ Ð°Ð±Ð¾ вкажуть СШРÑк вашу країну. + +/editinfo.bml.error.month.outofrange=Ðевірний міÑÑць народженнÑ. Введіть міÑÑць з 1-12 (Січ.-Грд.) + +/editinfo.bml.error.noname=Ваше ім'Ñ - обовÑзкова інформаціÑ. Вкажіть ваше ім'Ñ Ð°Ð±Ð¾ прізвиÑько Ñи пÑевдонім. + +/editinfo.bml.error.tm.require.number=Якщо ви викориÑтовуєте текÑтові повідомленнÑ, то повинні вказати номер вашого мобільника. + +/editinfo.bml.error.tm.require_provider=Якщо ви викориÑтовуєте текÑтові повідомленнÑ, то повинні вказати Ñвого оператора. Якщо його нема в ÑпиÑку, звіжітьÑÑ Ð· Ñ—Ñ… інформцентром та з'ÑÑуйте оÑобливоÑÑ‚Ñ– Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— поÑлуги, потім повідомте до нашого ÑервіÑ-центру. + +/editinfo.bml.error.year.notenoughdigits=Ðевірний рік народженнÑ. Вкажіть 4-Ñ… значний рік + +/editinfo.bml.error.year.outofrange=Ðевірний рік народженнÑ. + +/editinfo.bml.finished.about=Добре; тепер натиÑніть кнопку "Зберегти зміни". + +/editinfo.bml.finished.header=Готово? + +/editinfo.bml.finished.save_button=Зберегти зміни + +/editinfo.bml.gender.title=Стать + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=ПоÑтавте позначку тут, Ñкщо ви бажаєте отримувати e-mail, коли інші кориÑтувачі відповідають на ваші запиÑи. + +/editinfo.bml.getreplies.header=Отримувати коментарі поштою. + +/editinfo.bml.hidefriendof.about=Якщо ви поÑтавите позначку тут, то ÑпиÑок кориÑтувачів, Ñкі додали Ð²Ð°Ñ Ð´Ð¾ ÑпиÑку друзів, не буде відображатиÑÑ Ð½Ð° вашій Ñторінці "Про кориÑтувача". + +/editinfo.bml.hidefriendof.header=Сховати ÑпиÑок друзів. + +/editinfo.bml.howhear.about<< +Ðам цікаво, де ви почули про [[sitename]]? +Якщо це був хтоÑÑŒ із кориÑтувачів, вкажіть його ім'Ñ, Ñкщо це було інше джерело (ÑтаттÑ, поÑиланнÑ, веб-Ñайт), то уведіть відповідну інформацію. +. + +/editinfo.bml.howhear.header=Цікаво + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +ПоÑтавте тут позначку, Ñкщо ваша поштова програма повніÑÑ‚ÑŽ підтримує HTML у лиÑтах. +Багато програм намагаютьÑÑ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ñ‚Ð¸, але роблÑÑ‚ÑŒ це жахливо. +Якщо ви знімете позначку, то Живий Журнал буде відправлÑти вам тільки текÑтові лиÑти. +. + +/editinfo.bml.htmlemail.header=ВідправлÑти лиÑти у форматі HTML. + +/editinfo.bml.int.about=Якщо ви бажаєте, щоб інші кориÑтувачі могли знайти Ð²Ð°Ñ Ñƒ каталозі за вашими інтереÑами, вкажіть унизу вÑе, чим ви цікавитеÑÑŒ, через кому. Краще викориÑтовувати Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² одним Ñловом. ПроÑте правило: ваш Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ добре підходити до Ñ€ÐµÑ‡ÐµÐ½Ð½Ñ "Мені подобаєтьÑÑ ___________". Іменники пишіть у називному відмінку множини ("фільми", а не "фільм" чи "фільмів"). ДієÑлова пишіть у невизначеній формі ("подорожувати"). + +/editinfo.bml.int.ex.bad=Поганий приклад: Мені подобаєтьÑÑ Ñлухати музику, дивитиÑÑŒ кіно, базікати з друзÑми та ходити по клубах. Це можна вказати у біографії (див. вище). + +/editinfo.bml.int.ex.good=Гарний приклад: їздити на велоÑипеді, лижі, комп'ютери, музику, Ñир, дівчат + +/editinfo.bml.int.header=ІнтереÑи + +/editinfo.bml.login.enterinfo=Введіть ваші ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль, щоб змінити перÑональну інформацію. + +/editinfo.bml.login.forgot.header=ЩоÑÑŒ забули? + +/editinfo.bml.login.forgot.recover=Якщо ви забули ім'Ñ Ð°Ð±Ð¾ пароль, відновіть Ñ—Ñ… тут!. + +/editinfo.bml.logip.always=Завжди + +/editinfo.bml.logip.anon_only=Тільки анонімних кориÑтувачів + +/editinfo.bml.logip.header=ЗапиÑувати IP-адреÑи кориÑтувачів, що відповідають? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Якщо ви боїтеÑÑ, що spam-роботи зайдуть вашу e-mail адреÑу в Живому Журналі, виберіть цю опцію. Вашу адреÑу буде змінено таким чином, що Ñ—Ñ— не буде знайдено. + +/editinfo.bml.mangleaddress.header=Зпотворити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð´Ñ€ÐµÑи + +/editinfo.bml.name.title=Ім'Ñ + +/editinfo.bml.newemail.subject=E-mail адреÑу змінено. + +/editinfo.bml.numcomments.about=ПоÑтавте відмітку тут, Ñкщо ви бажаєте додавати кількіÑÑ‚ÑŒ коментарів до URL. У цьому разі, Ñкщо кількіÑÑ‚ÑŒ коментарів змінилаÑÑ, ваш браузер, можливо, відобразить поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ð¼ кольором. + +/editinfo.bml.numcomments.header=Додати &nc=xx до URL коментарів + +/editinfo.bml.optional=Ðеобов'Ñзково + +/editinfo.bml.opt_in.about<< +Якщо ви хочете знати, коли ми додамо нові гарні можливоÑÑ‚Ñ– до Живого Журналу, увімкніть цей перемикач. +Ðа даний момент ми не викориÑтовуємо цю можливіÑÑ‚ÑŒ, але, може, будемо в майбутньому. +Ваш e-mail не буде видно Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… кориÑтувачів, та ви можете вимкнути цю можливіÑÑ‚ÑŒ будь-коли. +. + +/editinfo.bml.opt_in.header=ÐадÑилайте мені новини Живого Журналу. + +/editinfo.bml.persinfo.disclaimer<< +Введіть ÑкуÑÑŒ коротку інформацію про Ñебе, щоб задовольнити нашу цікавіÑÑ‚ÑŒ та Ð´Ð»Ñ ÑтатиÑтичних даних. +Ми не збираємоÑÑ Ð·Ð°Ð²Ð´Ð°Ð²Ð°Ñ‚Ð¸ вам шкоди, кориÑтуючиÑÑŒ цією інформацією. Ми тільки хочемо знати хто Ñ– звідки наші кориÑтувачі. Якщо ви вагаєтеÑÑŒ, прочитайте нашу політику приватноÑÑ‚Ñ–. +. + +/editinfo.bml.persinfo.header=ОÑобиÑта Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/editinfo.bml.screen.all=УÑе + +/editinfo.bml.screen.anon=Ðнонімні + +/editinfo.bml.screen.header=Які коментарі ховати за замовчуваннÑм? + +/editinfo.bml.screen.none=Жодні + +/editinfo.bml.screen.nonfriends=ÐапиÑані не друзÑми + +/editinfo.bml.screen.nonmembers=ÐапиÑані не учаÑниками + +/editinfo.bml.security.header=Хто може бачити вашу контактну інформацію? + +/editinfo.bml.security.visibility.anybody=УÑÑ– + +/editinfo.bml.security.visibility.everybody=УÑÑ– + +/editinfo.bml.security.visibility.friends=Тільки друзі + +/editinfo.bml.security.visibility.regusers=ЗареєÑтровані кориÑтувачі + +/editinfo.bml.settings.friendspage.title=Заголовок Ñтрічки друзів: + +/editinfo.bml.settings.friendspage.title.optional=Додатково, вкажіть заголовок Ñтрічки друзів. (без HTML) + +/editinfo.bml.settings.header=Опції Живого Журналу + +/editinfo.bml.settings.journal.subtitle=Підзаголовок журналу: + +/editinfo.bml.settings.journal.subtitle.optional=Додатково, вкажіть заголовок та підзаголовок Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу. (без HTML) + +/editinfo.bml.settings.journal.title=Заголовок журналу: + +/editinfo.bml.settings.privacy.about=Оберіть нижче опції та параметри щодо приватноÑÑ‚Ñ–. + +/editinfo.bml.settings.privacy.header=Опції приватноÑÑ‚Ñ– + +/editinfo.bml.state.other=Ðбо, уведіть штат/провінцію/облаÑÑ‚ÑŒ іншої країни. + +/editinfo.bml.state.title=Штат + +/editinfo.bml.state.us=Штати СШР+ +/editinfo.bml.stylemine.about=ПоÑтавте тут відмітку, щоб дивитиÑÑ Ñторінку коментарів у Ñтилі вашого журналу при переході за поÑиланнÑми з вашої Ñтрічки друзів. + +/editinfo.bml.stylemine.header=Показувати Ñторінку коментарів у Ñтилі вашого журналу? + +/editinfo.bml.success.header=УÑпішно! + +/editinfo.bml.success.message=Ваша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‚Ð° Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ, а також профіль були змінені. + +/editinfo.bml.switch.button=Вибрати + +/editinfo.bml.switch.header=Вибрати інший журнал + +/editinfo.bml.switch.workwith=З Ñким журналом працювати + +/editinfo.bml.title=Редагувати оÑобиÑту інформацію + +/editinfo.bml.tm.details=детальніше + +/editinfo.bml.tm.phonenum=Повний номер телефона: + +/editinfo.bml.tm.sec.about=Дозволити текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ інших кориÑтувачів. + +/editinfo.bml.tm.sec.title=Рівень безпеки: + +/editinfo.bml.tm.servprov=СервіÑ-провайдер + +/editinfo.bml.tm.title=ТекÑтові повідомленні + +/editinfo.bml.translatemailto.about=Якщо ви вибрали отримувати коментарі електронною поштою та ваш поштовий клієнт погано підтримує Unicode (UTF-8), оберіть інше кодуваннÑ, в Ñке Живий Журнал автоматично перетворить текÑÑ‚ коментарю. + +/editinfo.bml.translatemailto.header=Перекодувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñƒ: + +/editinfo.bml.unbanusers.about=Цим кориÑтувачам заборонено коментувати запиÑи у вашому журналі. ПоÑтавте позначку навпроти імені кориÑтувача, щоб виключити його з цього ÑпиÑку. + +/editinfo.bml.unbanusers.header=Разблокувати кориÑтувачів + +/editinfo.bml.userpic.about=Ðижче розташовано зображеннÑ, що ви завантажили Ñ– Ñке Ñтоїть поруч з вашим ім'Ñм у вашому журналі та в журналі ваших друзів. + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Видалити це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ завантажити нове можна тут. + +/editinfo.bml.userpic.header=Ваше Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/editinfo.bml.userpic.none=Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ завантажено + +/editinfo.bml.weblogscom.about=Оберіть цю опцію, Ñкщо вам подобаєтьÑÑ Ð¼Ð°Ñ‚Ð¸ ÑпиÑок Weblogs.com в журналі коли ви пишете до нього. + +/editinfo.bml.weblogscom.header=ПовідомлÑти Weblogs.com про обнову + +/editinfo.bml.webpagename.title=Ðазва веб-Ñайту + +/editinfo.bml.webpageurl.title=URL Ñайту + +/editinfo.bml.whoreply.header=Хто може коментувати? + +/editinfo.bml.zip.title=Поштовий Ñ–Ð½Ð´ÐµÐºÑ + +/editinfo.bml.zip.usonly=5-ти значний поштовий індекÑ; тільки Ð´Ð»Ñ Ñ‚Ð¸Ñ…, хто знаходитьÑÑ Ñƒ СШР+ +/editjournal.bml.btn.proceed=Продовжити... + +/editjournal.bml.certainday=За певний день: + +/editjournal.bml.recententries=найÑвіжіші запиÑи + +/editjournal.bml.recententry=ОÑтанній Ð·Ð°Ð¿Ð¸Ñ + +/editjournal.bml.title=Редагувати Ð·Ð°Ð¿Ð¸Ñ Ñƒ журналі + +/editjournal.bml.viewwhat=Показати запиÑи: + +/editjournal_do.bml.body=Відредагуйте Ð¿Ð¾Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ запиÑу та натиÑніть кнопку "Зберегти" унизу Ñторінки. Ðбо натиÑніть кнопку "Вилучити" щоб вилучити цей Ð·Ð°Ð¿Ð¸Ñ Ð· вашого журналу. + +/editjournal_do.bml.btn.delete=Вилучити Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.btn.edit=Редагувати обраний Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.btn.save=Зберегти Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.continue.head=ÐатиÑніть Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ... + +/editjournal_do.bml.continue.text=Коли оберете Ñкий Ð·Ð°Ð¿Ð¸Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ñ‚Ð¸ чи вилучити, натиÑніть кнопку "Редагувати" унизу. + +/editjournal_do.bml.currmood=ÐаÑтрій: + +/editjournal_do.bml.currmusic=Музика: + +/editjournal_do.bml.date=Дата: + +/editjournal_do.bml.default=за замовчуваннÑм + +/editjournal_do.bml.delete.confirm=Ви впенені, що хочете видалити цей запиÑ? + +/editjournal_do.bml.edit.text=Це запиÑ, Ñкий ви вибрали Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ. ВнеÑÑ–Ñ‚ÑŒ зміни та натиÑніть кнопку "Зберегти запиÑ" нижче.

    Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу, видаліть веÑÑŒ текÑÑ‚ та натиÑніть кнопку "Зберегти запиÑ" нижче. + +/editjournal_do.bml.error.getting=Помилка при виборі запиÑів Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ: + +/editjournal_do.bml.error.modify=Помилка при редагуванні журналу: + +/editjournal_do.bml.error.nofind=Ðеможливо знайти вказаний запиÑ. + +/editjournal_do.bml.event=ТекÑÑ‚ запиÑу: + +/editjournal_do.bml.localtime=МіÑцевий чаÑ: + +/editjournal_do.bml.noneother=Інший + +/editjournal_do.bml.opt.backdate=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом: + +/editjournal_do.bml.opt.backdate.about=не з'ÑвитьÑÑ Ñƒ Ñтрічках друзів + +/editjournal_do.bml.opt.nocomments=Заборонити коментувати + +/editjournal_do.bml.opt.noemail=Ðе відправлÑти коментарі по e-mail + +/editjournal_do.bml.opt.noformat=Ðе автоформатувати: + +/editjournal_do.bml.other=Інше: + +/editjournal_do.bml.pickentry.head=Оберіть Ð·Ð°Ð¿Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ + +/editjournal_do.bml.pickentry.text=Оберіть елемент Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° натиÑніть кнопку "Редагувати" унизу Ñторінки. + +/editjournal_do.bml.picture=Ваше Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/editjournal_do.bml.save.head=ÐитиÑніть Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ... + +/editjournal_do.bml.save.text=ПіÑÐ»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу, натиÑніть "Зберегти". + +/editjournal_do.bml.subject=Тема: (не обов'Ñзково) + +/editjournal_do.bml.success.delete=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ видалено. + +/editjournal_do.bml.success.edit=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ змінено. Ви можете його побачити тут. + +/editjournal_do.bml.success.head=УÑпішно + +/editjournal_do.bml.timeformat=Ð§Ð°Ñ Ñƒ 24-годинному форматі + +/editjournal_do.bml.title=Редагувати запиÑи + +/editpics.bml.btn.proceed=Продовжити + +/editpics.bml.error.badurl=ÐдреÑа за Ñкою треба завантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ виглÑдає коректною. Вона повинна починатиÑÑŒ з http:// + +/editpics.bml.error.filetoolarge=Завантажене Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ñ Ð½Ð°Ð´Ñ‚Ð¾ велике. Розмір файла не може перевищувати [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Розмір вашого Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ([[imagesize]]) перевищує макÑимальний розмір. Ваше Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути макÑимум 100x100 пікÑелів. Візьміть програму Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ‚Ð¾ або картинок та за Ñ—Ñ— допомогою зменшіть розмір зображеннÑ. + +/editpics.bml.error.invalidimage=Ðевірний файл зображеннÑ. + +/editpics.bml.error.toomanypics2=Ви доÑÑгли Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñƒ [[maxpics]] зображеннÑ. Ви не можете завантажити нове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾Ñ‚Ð¸, доки не вилучите одне з Ñ–Ñнуючих. + +/editpics.bml.error.unsupportedtype=Файли типу [[filetype]] не підтримуютьÑÑ. Ви можете завантажити тільки файли типу GIF, PNG або JPG. Майже вÑÑ– фото-редактори можуть виконати конвертацію форматів. + +/editpics.bml.error.urlerror=Виникла помилка при Ñпробі завантажити ваше зображеннÑ. + +/editpics.bml.fromfile=З файлу: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=Ñ„ + +/editpics.bml.fromurl=З адреÑи: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=а + +/editpics.bml.kilobytes=КБ + +/editpics.bml.makedefault=Зробити зображеннÑм за замовчуваннÑм + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=з + +/editpics.bml.restriction.fileformat=Формат файла Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ бути PNG, GIF або JPG + +/editpics.bml.restriction.filesize=Розмір файла Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ повинен перевищувати 40k + +/editpics.bml.restriction.imagesize=Розміри Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ повинні перевищувати 100x100 пікÑелів + +/editpics.bml.uploadheader=Завантажити нове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/export.bml.btn.proceed=ВиконуєтьÑÑ... + +/export.bml.description=Ð¦Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ дозволÑÑ” завантажити ваші запиÑи в бажаному форматі Ð´Ð»Ñ Ñ€ÐµÐ·ÐµÑ€Ð²ÑƒÐ²Ð°Ð½Ð½Ñ. Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформації про Ñ€ÐµÐ·ÐµÑ€Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу зазирніть Ñюди. + +/export.bml.fields=ПолÑ: + +/export.bml.format.csv=CSV (розділÑючи комами) + +/export.bml.label.encoding=КодуваннÑ: + +/export.bml.label.field.allowmask=Дозволити маÑÐºÑƒÐ²Ð°Ð½Ð½Ñ + +/export.bml.label.field.currents=Поточний наÑтрій & музика + +/export.bml.label.field.event=ÐŸÐ¾Ð´Ñ–Ñ + +/export.bml.label.field.eventtime=Ð§Ð°Ñ Ð¿Ð¾Ð´Ñ–Ñ— (за годинником кориÑтувача) + +/export.bml.label.field.itemid=ID Ðомер + +/export.bml.label.field.logtime=Ð§Ð°Ñ Ð·Ð°Ð¿Ð¸Ñу (за ÑиÑтемним годинником) + +/export.bml.label.field.security=Рівень безпеки + +/export.bml.label.field.subject=Тема: + +/export.bml.label.format=Формат: + +/export.bml.label.header=Заголовок: + +/export.bml.label.month=Виберіть міÑÑць: + +/export.bml.label.month.month=мм: + +/export.bml.label.month.year=рррр: + +/export.bml.label.notranslation=Ðе перекодовувати + +/export.bml.label.what=Що екÑпортувати: + +/export.bml.title=ЕкÑпорт журналу + +/export.bml.what.entries=запиÑи журналу + +/friends/add.bml.add.header=УÑпішно + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=КориÑтувач був доданий до вашої Ñтрічки друзів. Ви можете побачити вашу Ñтрічку друзів тут. + +/friends/add.bml.add.title=Друга додано! + +/friends/add.bml.btn.add=Додати [[user]] + +/friends/add.bml.btn.modify=Змінити + +/friends/add.bml.btn.remove=Видалити + +/friends/add.bml.colors.bg=Задній фон + +/friends/add.bml.colors.fg=Передній фон + +/friends/add.bml.colors.header=Кольори + +/friends/add.bml.colors.hover=(Ðаведіть мишу на колір, щоб побачити його назву) + +/friends/add.bml.colors.text=Також ви маєте змогу вибрати колір котрим [[user]] буде виділено в вашій Ñтрічці друзів. + +/friends/add.bml.confirm.header=Додати [[user]] до друзів? + +/friends/add.bml.confirm.text=Щоб додати [[user]] до вашого ÑпиÑку друзів натиÑніть кнопарик нижче. + +/friends/add.bml.confirm.title=Додати друга + +/friends/add.bml.error1.header=Спершу увійти + +/friends/add.bml.error1.text=Щоб додати кориÑтувача до ÑпиÑку друзів ви Ñпершу повинні увійти. Якщо ви не маєте доÑÑ– Ñвого акаунту, то можете Ñтворити його. + +/friends/add.bml.error1.title=Додати друга + +/friends/add.bml.error2.text=Ви надали невірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Щоб додати друга зазерніть на Ñторінку друзів. + +/friends/add.bml.error3.text=Ви вже додали [[user]] до ÑпиÑку друзів . Зараз можете вказати котрим кольором він буде відображатиÑÑŒ у вашій Ñтрічці. + +/friends/add.bml.error3.title=редагувати друга + +/friends/add.bml.groups.header=Групи друзів + +/friends/add.bml.groups.nogroup=Групи друзів не задано. + +/friends/add.bml.groups.text=До Ñкої групи друзів хочете додати кориÑтувача? Групи друзів потрібні, щоб буза змога фільтрувати Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñтрічки друзів. Ртакож Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¾Ð³Ð¾ обробітку ÑпиÑку друзів. + +/friends/add.bml.remove.header=УÑпішно + +/friends/add.bml.remove.text=КориÑтувач був видалений з вашого ÑпиÑку друзів. Ви можете побачити вашу Ñтрічку друзів тут. + +/friends/add.bml.remove.title=Друг Видалений! + +/friends/edit.bml.title=Редагувати друзів + +/friends/editgroups.bml.btn.ge.del=Вилучити + +/friends/editgroups.bml.btn.ge.new=Ðова + +/friends/editgroups.bml.btn.ge.ren=Перейменувати + +/friends/editgroups.bml.btn.gs.private=Приватна + +/friends/editgroups.bml.btn.gs.public=Публічна + +/friends/editgroups.bml.btn.mv.down=ПереміÑтити вниз + +/friends/editgroups.bml.btn.mv.up=ПереміÑтити вверх + +/friends/editgroups.bml.confirm.delete=Ви впевнені що хочете вилучити цю групу друзів? + +/friends/editgroups.bml.done.btn=Зберегти зміни + +/friends/editgroups.bml.done.header=Готово? + +/friends/editgroups.bml.done.text=Коли вÑе зробите, натиÑніть кнопку внизу щоб зберегти зміни. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Ви доÑÑгли межі кількоÑÑ‚Ñ– груп (30). Якщо ви вилучли ÑкуÑÑŒ групу але не зберегли зміни, зробіть це зараз, а потім повернітьÑÑ Ð½Ð° ці Ñторінку та поновіть Ñ—Ñ—. Тоді ви матимете змогу Ñтворювати нові групи друзів. + +/friends/editgroups.bml.error.text=Сервер видав таке Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку: + +/friends/editgroups.bml.group.public=(публічний) + +/friends/editgroups.bml.ingroup=Ð’ групі: + +/friends/editgroups.bml.ingroup.not=Ðе в групі: + +/friends/editgroups.bml.prompt.newname=Введіть ім'Ñ Ð½Ð¾Ð²Ð¾Ñ— групи друзів: + +/friends/editgroups.bml.prompt.rename=Перейменувати цю групу у: + +/friends/editgroups.bml.saved.header=Збережено + +/friends/editgroups.bml.saved.text=Ваші групи друзів збережені. + +/friends/editgroups.bml.text=Ðа цій Ñторінці ви можете редагувати групи друзів. Групи друзів потрібні Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ на ваші запиÑи та Ð´Ð»Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñтрічки друзів. Якщо потрібна допомога, дивітьÑÑ Ð©Ð¾ таке групи друзів? Як мені Ñ—Ñ… викориÑтовувати? + +/friends/editgroups.bml.text.sec=Щодо безпеки: Якщо ви хочете вилучити одну групу а потім Ñтворити іншу, не треба перейменовувати одну групу в іншу. Якщо ви так зробите, то вÑÑ– запиÑи, Ñкі були видимі Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² Ñтарої групи, будуть видимі Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² з нової групи. + +/friends/editgroups.bml.title=Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿ друзів + +/friends/editgroups.bml.yourgroups=Ваші групи друзів: + +/friends/edit_do.bml.addfriends.head=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð”Ñ€ÑƒÐ·Ñ–Ð² + +/friends/edit_do.bml.addfriends.text=Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача ваших друзів по Живому Журналу, та оберіть колір Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ—Ñ… у Ñтрічці. + +/friends/edit_do.bml.background=Задній фон + +/friends/edit_do.bml.bgcolor=Колір фону: + +/friends/edit_do.bml.btn.close=Закрити + +/friends/edit_do.bml.btn.save=Зберегти зміни + +/friends/edit_do.bml.btn.toggle=Перейти до вікна препереглÑду + +/friends/edit_do.bml.done.head=Готово? + +/friends/edit_do.bml.done.text=Коли закінчите, натиÑніть "Зберегти зміни" нижче... + +/friends/edit_do.bml.error.updating=СталаÑÑŒ помилка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñтрічки друзів: + +/friends/edit_do.bml.fellowfriends.head=ÐаÑтупні друзі + +/friends/edit_do.bml.fellowfriends.text=ÐаÑтупні оÑоби помітили Ð²Ð°Ñ Ñк Ñвого друга. Можливо ви також бажаєте внеÑти Ñ—Ñ… до ÑпиÑку Ñвоїх друзів. Ці поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ вказані, щоб ви знали Ñ—Ñ… імена. Ви не зобов"Ñзані додавати Ñ—Ñ… до Ñвого ÑпиÑку друзів. + +/friends/edit_do.bml.foreground=Передній фон + +/friends/edit_do.bml.friend=Друг + +/friends/edit_do.bml.hover=Голи ваша миша наведена на колір, побачите його назву + +/friends/edit_do.bml.mrcolor=ПереглÑд кольорів + +/friends/edit_do.bml.name=Ім'Ñ + +/friends/edit_do.bml.needmore=Якщо бажаєте додати друзів більше ніж дозволÑÑ” форма вводу, то введіть Ñкільки можете, збережіть Ñ—Ñ…, потім повернітьÑÑ Ñюди Ñ– продовжіть додаваннÑ. + +/friends/edit_do.bml.nofriends.head=Ðема друзів? + +/friends/edit_do.bml.nofriends.text=Ðаразі у Ð²Ð°Ñ Ð½Ðµ визначено жодного друга. Однак ми впевнені, що ви повинні мати кілька друзів! :) Введіть но Ñ—Ñ… імена в Живому Журналі... + +/friends/edit_do.bml.opt.delete=Видалити? + +/friends/edit_do.bml.success.head=УÑпішно + +/friends/edit_do.bml.success.text=СпиÑок друзів було змінено. Ви можете побачити вашу оновлену Ñтрічку друзів тут. + +/friends/edit_do.bml.textcolor=Колір текÑту: + +/friends/edit_do.bml.title=Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/friends/edit_do.bml.user=КориÑтувач + +/friends/edit_do.bml.viewer=ПереглÑдач кольорів + +/friends/edit_do.bml.yourfriends.head=Ваші друзі + +/friends/edit_do.bml.yourfriends.text=Ðаразі визначеними Ñ” такі ваші друзі: + +/friends/filter.bml.editgroups=Якщо ви бажаєте відредагувати групи ваших друзів, ідіть на Ñторінку [[link]]. + +/friends/filter.bml.error.nogroups|staleness=1 +/friends/filter.bml.error.nogroups=Ви не можете фільтрувати вашу Ñтрічку друзів оÑкільки ви повинні Ñпочатку відредагувати групи друзів. + +/friends/filter.bml.error.nogroups.header=Ðемає груп + +/friends/filter.bml.reset=ОчиÑтити + +/friends/filter.bml.select=Оберіть групу(-и) друзів, Ñкі ви хотіли б бачити у Ñтрічці друзів. + +/friends/filter.bml.select.header=Обрати групи друзів + +/friends/filter.bml.submit=ПереглÑнути! + +/friends/filter.bml.title=Фільтр друзів + +/friends/index.bml.about=Ð¦Ñ Ñторінка дозволÑÑ” вам керувати ÑпиÑком друзів. Додаючи інших кориÑтувачів до ÑпиÑку друзів, ми можете легко бачити Ñ—Ñ… запиÑи в Ñвоїй Ñтрічці друзів. Також ви маєте змогу додавати Ñпільноти до вашого ÑпиÑку друзів Ñ– також бачити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‰Ð¾ пиÑатимутьÑÑ Ñ‚ÑƒÐ´Ð¸ іншими кориÑтувачами. + +/friends/index.bml.edit.about=Додати або видалити кориÑтувачів з вашого ÑпиÑку друзів, або змінити колір Ñ—Ñ… предÑтавленнÑ. + +/friends/index.bml.editgroups.about=СтвореннÑ, Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð³Ñ€ÑƒÐ¿ ваших друзів. + +/friends/index.bml.filter=Ð”Ð»Ñ Ñ†Ð¸Ñ… груп друзів можуть викориÑтовуватиÑÑŒ фільтри переглÑду: ви можете бачити тільки запиÑи означених груп. Також це можна викориÑтовувати Ð¶Ð´Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¸Ñ… заÑобів безпеки (дивиÑÑŒ нижче). + +/friends/index.bml.filter.about=Фільтруйте ÑпиÑок друзів згідно з визначеними підгрупами. + +/friends/index.bml.groups=Окрім того, підгрупи друзів можуть бути визначеними. + +/friends/index.bml.security=Ваш ÑпиÑок друзів також викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ з обмеженнÑм доÑтупу. Ви можете більше довідатиÑÑŒ про безпеку в вашому ÑпиÑку друзів в розділі Друзі & рівні доÑтупу. + +/friends/index.bml.security.custom=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð· "Custom", ви маєте змогу вказувати Ð´Ð»Ñ Ñких груп друзів воно буде видимим. Однак, не вÑÑ– клієнти підтримують таку можливіÑÑ‚ÑŒ. + +/friends/index.bml.security.header=Безпека + +/friends/index.bml.security.only=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ "Тільки друзÑм" будуть бачити тільки кориÑтувачі з вашого ÑпиÑку друзів. + +/friends/index.bml.title=ІнÑтрументи Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/friends/index.bml.tools=ІнÑтрументи + +/friends/popwithfriends.bml.account_type=Вибачте, тип вашого акаунту не підтримує ці заÑоби. + +/friends/popwithfriends.bml.count=Підрахунок + +/friends/popwithfriends.bml.exclude_own=Додатково, ви можете виключити ваших друзів. + +/friends/popwithfriends.bml.include_own=Додатково, ви можете включити ваших друзів. + +/friends/popwithfriends.bml.intro=ÐаÑтупні друзі внеÑли Ð²Ð°Ñ Ð´Ð¾ Ñвоїх ÑпиÑків друзів, але не ви Ñ—Ñ…. + +/friends/popwithfriends.bml.intro_own=ÐаÑтупні друзі внеÑли Ð²Ð°Ñ Ð´Ð¾ Ñвоїх ÑпиÑків друзів. СпиÑок також включає ваших влаÑних друзів. + +/friends/popwithfriends.bml.no_users=Ðема кориÑтувачів. + +/friends/popwithfriends.bml.title=ПопулÑрні кориÑтувачі Ñеред ваших друзів + +/friends/popwithfriends.bml.user=КориÑтуач + +/index.bml.boldcreate=Створіть влаÑний Живий Журнал! + +/index.bml.frank.image.alt=Козел Франк - таліÑман Живого Журналу. + +/index.bml.frank.logo="Беееее", Ñказав Франк. + +/index.bml.meta.desc=Живий Журнал це міÑце де ви маєте змогу поділитиÑÑŒ вашими думками зі вÑім Ñвітом. + +/index.bml.meta.keywords=щоденник, журнал, онлайн журнал, щоденники, пиÑати, онлайн щоденник, веб щоденник + +/interests.bml.add.added.head=Додано! + +/interests.bml.add.added.text=Ð—Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ додано до ÑпиÑку. + +/interests.bml.add.btn.text=Додати [[interest]] + +/interests.bml.add.confirm.head=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ + +/interests.bml.add.confirm.text=Щоб додати [[interest]] Ñк захопленнÑ, натиÑніть кнопку нижче. + +/interests.bml.add.toomany.head=Вибачте... + +/interests.bml.add.toomany.text=Ви вже внеÑли [[maxinterests]] до ÑпиÑку. + +/interests.bml.addint=Якщо ви зацікавлені в цьому та хочете бути доданими до цього ÑпиÑку, вам Ñюди. + +/interests.bml.btn.switch=Перемикач + +/interests.bml.communities.head=ОÑобливі Ñпільноти + +/interests.bml.communities.text=наÑтупні Ñпільноти також цікавлÑÑ‚ÑŒ "[[interest]]". + +/interests.bml.count=Рахунок + +/interests.bml.enmasse.body.other=Ðижче Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача [[user]]. Відмітьте захопленнÑ, що цікаві вам, та зніміть помітки з тих, що Ð²Ð°Ñ Ð½Ðµ цікавлÑÑ‚ÑŒ. Потім натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.body.other_authas=Ðижче Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача [[user]]. Помітьте захопленнÑ, що хочете додати до [[target]], та зніміть помітки з тих, що хочете видалити. Потім натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.body.you=зніміть помітки з захоплень, котрі хочете видалити. Потім натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.btn=Показати ÑпиÑок + +/interests.bml.enmasse.header=Дод\видалити Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.enmasse.intro=Змінити ваші Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð½Ð° оÑнові цих: + +/interests.bml.error.add.mustlogin=Щоб додати Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ð¾ зарееÑтруватиÑÑŒ. + +/interests.bml.error.enmasse.mustlogin=Ви повинні увійти до журналу, щоб мати змогу ÑкориÑтатиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. + +/interests.bml.error.enmasse.noaccess=Вам не доÑтупний журнал [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Ð—Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð½Ðµ знайдено. + +/interests.bml.error.nointerests=Вибраний кориÑтувач не Ñ–Ñнує або не визначив жодного захопленнÑ. + +/interests.bml.findsim.searchwait=Зауважте: Пошук триватиме декілька Ñекунд. Зачекайте. + +/interests.bml.findsim_do.account.notallowed=Перепрошуєм, тип вашого акаунту не дозволÑÑ” цей викориÑтати заÑіб. + +/interests.bml.findsim_do.magic=Чарівний
    Ñ–Ð½Ð´ÐµÐºÑ + +/interests.bml.findsim_do.magic.head=Чарівний індекÑ? + +/interests.bml.findsim_do.magic.text=Кожному кориÑтувачу приведений у відповідніÑÑ‚ÑŒ чарівний індекÑ, утворений з двох параметрів: номеру Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° деÑкої кількоÑÑ‚Ñ– унікальних захоплень. + +/interests.bml.findsim_do.nomatch.head=Ðе відповідає + +/interests.bml.findsim_do.nomatch.text=Жоден кориÑтувач не Ñхожий на [[user]]. + +/interests.bml.findsim_do.notdefined=КориÑтувач [[user]] не визначив інтереÑи. + +/interests.bml.findsim_do.similar.head=Схожі кориÑтувачі. + +/interests.bml.findsim_do.similar.text=ÐаÑтупні кориÑтувачі повÑзані з [[user]] + +/interests.bml.finished.about=Якщо завершили то натиÑніть нижче кнопку "Зберегти зміни": + +/interests.bml.finished.header=Готово? + +/interests.bml.finished.save_button=Зберегти зміни + +/interests.bml.interest=Ð—Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.interested.btn.find=Пошук + +/interests.bml.interested.in=Пошук людей та Ñпільнот зацікавлених в: + +/interests.bml.interests.findsim=Пошук кориÑтувачів у котрих Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ñ– до: + +/interests.bml.interests.head=Ð—Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.interests.text=ОÑÑŒ деÑкі речі, що ви можете зробити з захопленнÑми: + +/interests.bml.interests.viewpop=ПереглÑнути популÑрні Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.login.enterinfo=Введіть ваші ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль щоб редагувати інтереÑи. + +/interests.bml.login.proceed=Продовжити... + +/interests.bml.match=[[count]] відповідає: + +/interests.bml.matches=[[count]] відповідають: + +/interests.bml.morestuff=Юільше цікавих матеріалів можна знайти на Ñторінці захоплень. + +/interests.bml.nointerests.text=Ðе маєте жодних захоплень зі ÑпиÑку? Добавте зайшовши на Ñторінку ПерÑональна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‚Ð° Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/interests.bml.popular.head=ПопулÑрні Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.popular.text=ÐаÑтупні Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ñ” вельми популÑрними. + +/interests.bml.results.added=ЗахопленнÑ, що ви відмітили, уÑпішно додано до вашого ÑпиÑку. + +/interests.bml.results.both=ЗахопленнÑ, що ви відмітили, уÑпішно додано до вашого ÑпиÑку, а не вибрані було видалено. + +/interests.bml.results.deleted=ЗахопленнÑ, що ви не відмітили уÑпішно видалені з вашого ÑпиÑку. + +/interests.bml.results.del_and_toomany<< +ЗахопленнÑ, що були не відмічені, уÑпішно видалені з вашого ÑпиÑку. Ðле ви відмітили надто багато захоплень Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð¾ ÑпиÑку. Ви можете мати тільки [[intcount]] +захоплень. Жодне з вибраних вами захоплень не було додано. Ви можете повернутиÑÑŒ та обрати меншу кількіÑÑ‚ÑŒ. +. + +/interests.bml.results.goback=Ви маєте змогу повернутиÑÑŒ до [[user]]-ного профілю котрий ви тільки-но переглÑдали. + +/interests.bml.results.header=Результати + +/interests.bml.results.message=ПодивитиÑÑŒ вашу оновлену Ñторінку-профіль. + +/interests.bml.results.nothing=Ви не зробили жодної зміни. + +/interests.bml.results.toomany=Ви вказали надто багато захоплень. Ви можете мати тільки [[intcount]] Ñ—Ñ… загалом. Жодне з вибаних не було додано до вашого ÑпиÑку. Ви можете повернутиÑÑŒ та вибрати меншу кількіÑÑ‚ÑŒ та Ñпробувати знов Ñ—Ñ… додати. + +/interests.bml.title=Ð—Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ + +/interests.bml.toomany.body=Ð’Ñього [[intcount]] оÑіб та\або Ñпільнот вказало це захопленнÑ.СпиÑок не буде показано. + +/interests.bml.toomany.head=Багато значень + +/interests.bml.users.head=Зацікавлені кориÑтувачі + +/interests.bml.users.text=ÐаÑтупні кориÑтувачі цікавлÑÑ‚ÑŒÑÑ [[interest]]. + +/invite/index.bml.code=Код + +/invite/index.bml.error=Помилка + +/invite/index.bml.genmore=Генерувати код(и) + +/invite/index.bml.how_detail=Ð’ залежноÑÑ‚Ñ– від деÑких факторів, кориÑтувачі можуть запроÑити певну кількіÑÑ‚ÑŒ людей Ð´Ð»Ñ ÑƒÑ‡Ð°ÑÑ‚Ñ– у Живому Журналі. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб запроÑити когоÑÑŒ, вам потрібно згенерувати код-Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ñ‚Ð° віддати його майбутьному кориÑтувачу. + +/invite/index.bml.how_header=Як це працює? + +/invite/index.bml.invite_header=ЗапрошеннÑ? + +/invite/index.bml.none=Ðемає + +/invite/index.bml.redeemed=ВикориÑтав + +/invite/index.bml.title=ЗапроÑи друзів приєднатиÑÑŒ до Живого Журналу + +/invite/index.bml.unused=Ðе викориÑтан + +/invite/index.bml.use=викориÑтати + +/invite/index.bml.why_codes=Щоб підтримувати Живий Журнал, контролювати його розвиток та контролювати його невірне викориÑтаннÑ, на даний момент Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚Ñƒ вам потрібно отримати Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð²Ñ–Ð´ Ñ–Ñнуючого кориÑтувача або заплатити за реєÑтрацію. Це правило введено Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб покращити умови Ð´Ð»Ñ Ñ–Ñнуючих авторів за рахунок незручноÑÑ‚Ñ– Ñку відчувають нові кориÑтувачі. + +/legal/index.bml.about<< +Живий Журнал викориÑтовуєтьÑÑ Ð² багатьох країнах, багатьма народами. Тому Ð´Ð»Ñ ÑƒÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑервіÑа в належному порÑдку, у Ð½Ð°Ñ Ñ” декілька правил. ОÑÑŒ деÑкі з них, Ñкі потрібно памÑтати: +
      +
    • Ðе турбуйте, не ображайте та не погрожуйте іншим.
    • +
    • Ðе наноÑÑ–Ñ‚ÑŒ шкоду молодшим.
    • +
    • Ðе Ñтворюйте Ñпам.
    • +
    • Ðе порушуйте авторÑького права.
    • +
    • Ðе втручайтеÑÑŒ в чужу приватніÑÑ‚ÑŒ.
    • +
    • Ðе порушуйте закон Сполучених Штатів та ваші маÑцеві закони.
    • +
    +Повний ÑпиÑок правил можна знайти нижче: +. + +/legal/index.bml.about.header=ПереглÑнути + +/legal/index.bml.docs.coppa.about=Ðкт про ЗахиÑÑ‚ дитÑчої приватноÑÑ‚Ñ– в онлайні (COPPA)регулює збір та викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ñ— інформації про дітей молодших 13 років. Ðаша COPPA-Ñторінка поÑÑнює наше ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ закону Ñ– вказує Ñк ми дотримуємоÑÑŒ Ðкту COPPA. + +/legal/index.bml.docs.header=Документи + +/legal/index.bml.docs.privacy.about=Політика ПриватноÑÑ‚Ñ– показує, Ñку інформацію ми збираємо про наших кориÑтувачів Ñ– поÑÑнює, Ñк ми ту інформацію викориÑтовуємо. + +/legal/index.bml.title=Правова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/legal/privacy.bml.title=Політика приватноÑÑ‚Ñ– + +/legal/tos.bml.title=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +/login.bml.bindip.label=Прив'Ñзати до IP-адреÑÑи + +/login.bml.bindip.no=ÐÑ– (працює зі вÑіма інет-провайдерами) + +/login.bml.bindip.yes=Так (зберігати) + +/login.bml.error.mustenterusername=Ви повинні ввеÑти ім'Ñ.. + +/login.bml.expire.btn.neverexpire=Ð’Ñтановити режим "ÐІКОЛИ" + +/login.bml.expire.btn.sessiononly=Ð’Ñтановити режим "ÐРОДÐУ СЕСІЮ" + +/login.bml.expire.neverexpire.text=Ви увійшли "не забувати ідентифікаційні дані". Якщо це публічгий ПК (школа, бібліотека, інше) Ñ– до нього маєть доÑтуп багато оÑіб, то вам необхідно по завершенню роботи з Живим Журналом розреєÑтровуватиÑÑŒ! Ðбо ж змініть Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ входу на "ÐРОДÐУ СЕСІЮ", тоді ваші дані комп'ютер забуватиме піÑÐ»Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¾Ð³Ð»Ñдача. + +/login.bml.expire.sessiononly.text=Ваша рееÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ дійÑна до Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¾Ð³Ð»Ñдача. Якщо це ваш влаÑний комп'ютер чи ви його єдиний кориÑтувач, ми маєте змогу вказати зберігати реєÑтраційні данні завжди: + +/login.bml.links.head=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/login.bml.links.link1=Ваша Ñтрічка друзів. + +/login.bml.links.link2=Ваш "що зробити" лиÑток. + +/login.bml.links.text=Ð’ майбутньому Ñ†Ñ Ñторінка міÑтитиме вÑÑ– короткі поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ‚Ð° пов'Ñзану інформацію, але вже зараз Ñ” кілька міÑць що ви захочете відвідати: + +/login.bml.loggedin.head=Вхід зроблено! + +/login.bml.loggedin.text=Ви увійшли до журналу. + +/login.bml.login.btn.changeopts=Змінити опції + +/login.bml.login.btn.login=Увійти... + +/login.bml.login.expiration=ЗавершеннÑ: + +/login.bml.login.forget=Забули? + +/login.bml.login.head=Увійти + +/login.bml.login.never=Ðіколи + +/login.bml.login.otheropts=Інші опції + +/login.bml.login.password=Пароль: + +/login.bml.login.text1=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб увійти до [[sitename]], уведіть нижче ваше ім'Ñ Ñ‚Ð° пароль. Ðовим кориÑтувачам: Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб творити акаунт, йдіть Ñюди. + +/login.bml.login.text2=Ви також можете вÑтановити, коли вхід (логін) в ÑиÑтему закінчуєтьÑÑ. За замовчуваннÑм логін закінчитьÑÑ Ñк тільки ви закриєте браузер, що Ñ” накращим Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… комп'ютерів. Однак, Ñкщо ви єдиний кориÑтувач вашого комп'ютера та більш ніхто не має доÑтупу до нього, ви можете бути зареєÑтровані веÑÑŒ чаÑ. За інформацією щодо цих параметрів звертайтеÑÑ Ð©Ð¾ за опції Коли Ñ ÑƒÐ²Ñ–Ð¹ÑˆÐ¾Ð² в ÑиÑтему? + +/login.bml.login.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/login.bml.login.whenbrowsercloses=Коли огладач буду закрито + +/login.bml.logout.btn=Вийти + +/login.bml.title=Увійти + +/login.bml.whylogin.benefit1=Вам більше не треба вводити ім'Ñ/пароль деÑÑŒ на Ñайті. + +/login.bml.whylogin.benefit2=Ви матимете змогу бачити "захищені" запиÑи журналу ваших друзів, котрі дадуть вам дозвіл читати Ñ—Ñ…. + +/login.bml.whylogin.benefit3=багато з можливоÑтей Ñ” видимими тільки коли ви увійдете. + +/login.bml.whylogin.head=Чому увійти? + +/login.bml.whylogin.text=Тут Ñ” деÑкі оÑновні переваги рееÑтрації: + +/logout.bml.already.head=УÑпішно вийшли + +/logout.bml.already.text=Ви уÑпішно вийшли. + +/logout.bml.killall.btn=Завершити вÑÑ– мої ÑеÑÑ–Ñ— + +/logout.bml.killall.head=Інші ÑеÑÑ–Ñ— + +/logout.bml.killall.text=Ви маєте інші активні ÑеÑÑ–Ñ—. Ви хочете завершити Ñ—Ñ… вÑÑ–, чи тільки цю? (ПереглÑньте ці чаÑÑ‚Ñ– Ð·Ð°Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформованоÑÑ‚Ñ–.) + +/logout.bml.loggedout.already=УÑпішно вийшли. + +/logout.bml.loggedout.head=Вийшли + +/logout.bml.loggedout.killedall=Ð’ÑÑ– ваші ÑеÑÑ–Ñ— було завершено. + +/logout.bml.loggedout.success=Вийшли + +/logout.bml.loggedout.text=Ви вийшли. + +/logout.bml.logout.btn=Вийти + +/logout.bml.logout.head=Вийти? + +/logout.bml.logout.text=ÐатиÑніть кнопку, щоб вийти. + +/logout.bml.title=Вихід + +/lostinfo.bml.btn.proceed=Виконано + +/lostinfo.bml.enter_email=Введіть вашу електронну адреÑу: + +/lostinfo.bml.enter_email_optional=електронна адреÑа (необов'Ñзково) + +/lostinfo.bml.enter_username=Введіть Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/lostinfo.bml.error.no_email=Ви повинні ввеÑти Ñвій email, щоб ви могли відновити ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/lostinfo.bml.lostpassword.text=Якщо ви втратили Ñвій пароль, введіть ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ñ– додатково електронну адреÑу куди хочете його надіÑлати. Вказана адреÑа буде перевірена на те, чи вона Ñ–Ñнує, перед надÑиланнÑм паролю. Якщо зилишите поле адреÑи пуÑтим, відправлено буде на поточну адреÑу. + +/lostinfo.bml.lostpassword.title=Забули Ñвій пароль? + +/lostinfo.bml.lostusername.text=Якщо ви забудете ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, вам потрібно ввеÑти ваш email та ми вишлемо вам ваше ім'Ñ. + +/lostinfo.bml.lostusername.title=Забули ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача? + +/lostinfo.bml.title=Втрачена Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/lostinfo_do.bml.error.no_usernames_for_email=Ðема кориÑтувача з такою адреÑою: [[address]] . + +/lostinfo_do.bml.error1.text=Ви ніколи не викориÑтовували цю адреÑу з цим акаунтом, або ніколи Ñ—Ñ— не підтверджували. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð³ÐµÐ½ÐµÑ€Ð¾Ð²Ð°Ð½Ðµ автоматично. Ðе потрібно на нього відповідати *** + +Це замовлений вами пароль Ð´Ð»Ñ [[sitename]]. +Ðижче ваші ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, пароль, та електронна адреÑа, котрі ви вказали при рееÑтрації. + + Ім'Ñ : [[username]] + Пароль : [[password]] + ÐдреÑа : [[emailadr]] + + + +. + +/lostinfo_do.bml.lostpasswordmail.part2=Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ ходіть Ñюди: + +/lostinfo_do.bml.lostpasswordmail.part5<< +КориÑні поÑиланнÑ: + + Ваш Живий Журнал: + [[journalurl]] + + ÐапиÑати до вашого журналу: + [[updateurl]] + +З повагою, +Команда Живого Журналу + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Втрачено пароль + +/lostinfo_do.bml.password_mailed.text=Завершено. Ваш пароль надіÑлано вам. + +/lostinfo_do.bml.password_mailed.title=Пароль надіÑлано! + +/lostinfo_do.bml.title=Втрачено інформацію + +/lostinfo_do.bml.username_mailed.text=Завершено. Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача надіÑлано вам. + +/lostinfo_do.bml.username_mailed.title=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача надіÑлано! + +/manage/index.bml.about=Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ акаунтом зовÑім проÑте. Виберіть один з нижчеприведених пунктів: + +/manage/index.bml.communities=Створити та керувати влаÑною Ñпільнотою + +/manage/index.bml.communities.create.about=Створити нову Ñпільноту + +/manage/index.bml.communities.header=Спільноти + +/manage/index.bml.customization.advanced.about=ПереглÑнути, Ñтворити та відредагувати ваші S2 Ñхеми та Ñтилі + +/manage/index.bml.customization.customize=Ðалаштувати журнал + +/manage/index.bml.customization.customize.about=Змінити виглÑд вашого журналу та переключитиÑÑ Ð¼Ñ–Ð¶ ÑиÑтемами Ñтилів S1 та S2 + +/manage/index.bml.customization.header=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/index.bml.entries.memories.about=ДивитиÑÑ Ñ‚Ð° працювати зі Ñвоїми вибраними запиÑами + +/manage/index.bml.information.editinfo.about=Редагувати інформацію про акаунт та інші параметри + +/manage/index.bml.information.siteopts.about=Оберіть улюблений виглÑд Ñайту & мову + +/manage/links.bml.about=ВикориÑтовуйте нижченаведену форму щоб Ñтворити ÑпиÑок поÑилань наÑвних в вашому журналі. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·'ÑвитьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ в тому випадку, Ñкщо Ñ†Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÑƒÑ”Ñ‚ÑŒÑÑ Ð²Ð°ÑˆÐ¸Ð¼ Ñтилем ÑиÑтеми S2. + +/manage/links.bml.about.blank=Щоб Ñтворити порожній Ñ€Ñдок, введіть "-" в ÑкоÑÑ‚Ñ– заголовку + +/manage/links.bml.about.heading=Щоб Ñтворити заголовок введіть заголовок без URL. + +/manage/links.bml.about.reorder=Щоб змінити порÑдок Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñилань у ÑпиÑк змініть чиÑло зліва (можна вживати деÑÑткові чиÑла) + +/manage/links.bml.error.s2required=СпиÑок поÑилань наÑвний тільки Ð´Ð»Ñ Ñтилів, котрі підтримуютьÑÑ ÑиÑтемою Ñтилів S2. Щоб переключитиÑÑ Ð´Ð¾ ÑиÑтеми S2, дивітьÑÑ Ñторінку [[link]]. + +/manage/links.bml.error.s2required.header=Потрібен S2 + +/manage/links.bml.success=УÑпіх! Ваше поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ збережене. + +/manage/links.bml.title=СпиÑок поÑилань + +/manage/phonepost.bml.error.phone.length=Ваш телефонний номер повинен ÑкладатиÑÑ Ð½Ðµ менше ніж з однієї цифри. + +/manage/phonepost.bml.error.pin=Ваш PIN повинен бути чиÑельним. + +/manage/siteopts.bml.btn.lang=Переключити мову + +/manage/siteopts.bml.btn.scheme=Переключити Ñхему + +/manage/siteopts.bml.head.lang=Оберіть мову + +/manage/siteopts.bml.head.scheme=Оберіть Ñхему + +/manage/siteopts.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñайту + +/modify.bml.title=ВиглÑд Журналу + +/modify_do.bml.availablestyles.head=ДоÑтупні Ñтилі + +/modify_do.bml.availablestyles.userstyles=Стилі кориÑтувача: + +/modify_do.bml.colortheme.about=Тут ви можете обрати кольорову Ñхему, Ñка буде додана до параметрів зовнішнього виглÑду обраних вами вище. Ð Ñкщо вам не подобаютьÑÑ Ð½Ð°Ð´Ð°Ð½Ñ–, оберіть Ñвої! + +/modify_do.bml.colortheme.area.head=Елемент + +/modify_do.bml.colortheme.color.head1=Колір + +/modify_do.bml.colortheme.color.head2=(#rrggbb або назва) + +/modify_do.bml.colortheme.customcolors=Вказати кольори: + +/modify_do.bml.colortheme.defaulttheme=Готові Ñхеми + +/modify_do.bml.colortheme.head=Схема кольорів + +/modify_do.bml.domainalias.about=Якщо у Ð²Ð°Ñ Ñ” зареєÑтровани доменне ім'Ñ (або ви плануєте його зареєÑтрувати) та ви бажаєте щоб воно вказувало на ваш журнал, введіть його тут: + +/modify_do.bml.domainalias.domainname=Доменне ім'Ñ: + +/modify_do.bml.domainalias.example=Ðаприклад: my-journal.com + +/modify_do.bml.domainalias.head=ПÑевдоніми доменів + +/modify_do.bml.domainalias.helptext=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб це Ñпрацювало, вам потрібно щоб DNS Ð·Ð°Ð¿Ð¸Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ домену вказував на ту ж IP адреÑу, що Ñ– [[sitename]]. Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформації передивітьÑÑ Ñ†ÑŽ Ñторінку. + +/modify_do.bml.done.btn.savechanges=Зберегти зміни + +/modify_do.bml.done.head=Готово? + +/modify_do.bml.done.text=Коли вÑе буде готово, натиÑніть кнопку "Зберегти зміни" унизу... + +/modify_do.bml.error.dupdomainalias=Інший кориÑтувач вже зареєÑтрувавÑÑ Ð²Ð¸ÐºÐ¾Ñ€Ð¸Ñтовуючи ваш домений пÑевдонім. + +/modify_do.bml.error.stylenotavailable=Один з вибраних вами Ñтилів не доÑтупний. Це, можливо, через те, що хтоÑÑŒ вилучає цей Ñтиль, або ви обрали Ñтиль, до Ñкого у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу. + +/modify_do.bml.friends.about=Тут параметри щодо зовнішнього виглÑду Ñтрічки друзів. + +/modify_do.bml.friends.head=ВиглÑд Ñтрічки друзів + +/modify_do.bml.friends.opt.usesharedpic.about=Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽÑ” Ñке Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð¸ будете бачити у Ñтрічці друзів, коли хто-небудь напише у Ñпільноті. Якщо ви оберете цю опцію, ви бачитемете Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñпільноти заміÑÑ‚ÑŒ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/modify_do.bml.friends.opt.usesharedpic.head=ЗамінÑти Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача на Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñпільноти. + +/modify_do.bml.journaloptions.about=ЗвідÑи ви можете редагувати, Ñк виглÑдають ваші Ñторінки Живого Журналу. Якщо ви дійÑно зацікавлені, Ñк вÑе працює, читайте інформацію Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Інакше ми вважатимемо, що ви задоволені з типовими параметрами, наведеними нижче: + +/modify_do.bml.journaloptions.head=Параметри журналу + +/modify_do.bml.journalstatus.about=Якщо ви бажаєте вилучити або відмінити Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журнал, це Ñаме те міÑце, де це робитьÑÑ. Як тільки ви вилучите Ñвій журнал, ви матимете 30 днів щоб відмінити це, Ñкщо змінете думку. ПіÑÐ»Ñ 30 днів журнал буде назавжди вилучено та не буде ÑпоÑобів його відновити. + +/modify_do.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— журналу + +/modify_do.bml.journalstatus.select.activated=Ðктивований + +/modify_do.bml.journalstatus.select.deleted=Вилучений. + +/modify_do.bml.journalstatus.select.head=СтатуÑ: + +/modify_do.bml.journalstatus.select.suspended=Припинено + +/modify_do.bml.moodicons.about=Коли ви пишете у журнал, ви можетие вказати ваш наÑтрій на той момент. Є Ñхеми зображень наÑтроїв, Ñкі ви можете викориÑтовувати. Ðбо оберіть "None", Ñкщо не бажаєте бачити ÑкеÑÑŒ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ñ–Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ наÑтрою. + +/modify_do.bml.moodicons.head=ЗображеннÑ-наÑтрої + +/modify_do.bml.moodicons.opt.forcefriends.about=ВикориÑтовувати цю Ñхему Ð´Ð»Ñ Ð²ÑÑ–Ñ… запиÑів у Ñтрічці друзів + +/modify_do.bml.moodicons.personal=ПерÑональні Ñхеми: + +/modify_do.bml.moodicons.preview=передивитиÑÑŒ + +/modify_do.bml.moodicons.select=Оберіть Ñхему малюнків-наÑтроїв: + +/modify_do.bml.overrides.about=Якщо ви задоволенні виглÑдом вашого журналу, ви можете не кориÑтуватиÑÑŒ цим розділом. Цей розділ потрібен Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб змінювати оÑобливі (Ñпецифічні) наÑтройки зовнішнього виглÑду журналу. ПередивітьÑÑ Ð©Ð¾ таке перекриттÑ? Як воно працює?, Ð´Ð»Ñ Ð¾Ð³Ð»Ñду та розділ розробників Ð´Ð»Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації. Зазначте, що Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ñ– Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ одного або двух елементів Ñтилю. Якщо ви хочете змінити вÑе, вам потрібно Ñтворити Ñвій Ñтиль. Ð”Ð»Ñ Ð¾Ð³Ð»Ñду Ñк Ñтворити Ñтиль, передивітьÑÑ Ð¯Ðº мені Ñтворити Ñтиль? + +/modify_do.bml.overrides.box.head=ПерекриттÑ: + +/modify_do.bml.overrides.head=ÐŸÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñтилів + +/modify_do.bml.overrides.note=Зазначте, що не вÑÑ– змінні Ñтилю можуть бути підмінені. ПередивітьÑÑ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–ÑŽ Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформації.
    Зверніть увагу, що, наприклад, Ñкщо при редагуванні перекриваючих кодів ви викориÑтали у HTML-заголовку недозволені теги, такі Ñк <DIV>, <SPAN>, <IMG>, ці теги будуть вирізані. У перекриваючих кодах типу *_HEAD можуть викориÑтовуватиÑÑŒ теги, Ñкі дозволено викориÑтовувати в HTML заголовках. Ці теги: <title>, <base>, <style>, <link>, and <meta>. + +/modify_do.bml.overrides.warning=ЦЕ ÐЕ ТЕ МІСЦЕ, ДЕ ВИ ПИШЕТЕ ДО ЖУРÐÐЛУ!!! + +/modify_do.bml.pagelayoutstyle.about=Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽÑŽÑ‚ÑŒ, Ñк виглÑдатиме ваш журнал на екрані. + +/modify_do.bml.pagelayoutstyle.head=Стиль журналу + +/modify_do.bml.pagelayoutstyle.warning=Ваш тип акаунту дозволÑÑ” вам обирати з маленької кількоÑÑ‚Ñ– готових Ñтилів. + +/modify_do.bml.success.head=УÑпішно + +/modify_do.bml.success.text=ÐаÑтройки вашого журналу було змінено. Ви можете побачити ваш оновлений журнал тут. + +/register.bml.new.header=УÑпішно + +/register.bml.sent.header=УÑпішно + +/register.bml.trans.header=УÑпішно + +/support/append_request.bml.back.support=ПовернутиÑÑŒ до центру підтримки. + +/support/append_request.bml.invalid.noid=Ð¦Ñ Ð´Ñ–Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÑ” Ð½Ð°Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ запиту до центру підтримки. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.unknown.request=Ðевідомий запит підтримки + +/support/faqbrowse.bml.lastupdated=ОÑтаннє оновленнÑ: + +/syn/index.bml.loginrequired.title=Вам потрібно увійти до журналу + +/talkmulti.bml.error.login=Ви не увійшли до журналу. + +/talkpost.bml.allowedhtml=HTML дозволено + +/talkpost.bml.error.cannotreplynopost=Ви не можете відповіÑти на неіÑнуючий запиÑ. + +/talkpost.bml.error.nocommentsjournal=КориÑтувач вимкнув можливіÑÑ‚ÑŒ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів у його журналі. + +/talkpost.bml.error.nocommentspost=КориÑтувач вимкнув можливіÑÑ‚ÑŒ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost.bml.error.noreply_deleted=Цей коментар вилучено. Ви не можете відповіÑти на нього. + +/talkpost.bml.error.noreply_screened=Це прихований коментар Ñ– ви не можете його побачити чи відповіÑти на нього. + +/talkpost.bml.label.picturetouse=ВикориÑтати зображеннÑ: + +/talkpost.bml.loganonip=Увага! Цей кориÑтувач ввімкнув Ð·Ð°Ð¿Ð¸Ñ IP Ð°Ð´Ñ€ÐµÑ Ð°Ð½Ð¾Ð½Ñ–Ð¼Ð½Ð¸Ñ… кориÑтувачів. + +/talkpost.bml.loginq=Увійти? + +/talkpost.bml.logyourip=Увага! Цей кориÑтувач ввімкнув Ð·Ð°Ð¿Ð¸Ñ IP Ð°Ð´Ñ€ÐµÑ Ð²ÑÑ–Ñ… кориÑтувачів. + +/talkpost.bml.nosubjecthtml=HTML не дозволено у темі. + +/talkpost.bml.opt.anonymous=Ðнонімно + +/talkpost.bml.opt.defpic=(за замовчуваннÑм) + +/talkpost.bml.opt.friendsonly=- цей кориÑтувач вимкнув можливіÑÑ‚ÑŒ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів анонімам та не-друзÑм. Ви можете коментувати цей Ð·Ð°Ð¿Ð¸Ñ Ñкщо ви в друзÑÑ… у [[username]]. + +/talkpost.bml.opt.from=Від: + +/talkpost.bml.opt.ljuser=КориÑтувач ЖЖ: + +/talkpost.bml.opt.loggedin=КориÑтувач: [[username]] + +/talkpost.bml.opt.message=Коментар: + +/talkpost.bml.opt.noanonpost=- цей кориÑтувач вимкнув можливіÑÑ‚ÑŒ анонімного коментуваннÑ. + +/talkpost.bml.opt.noautoformat=Ðе автоформатувати: + +/talkpost.bml.opt.noimage=Ðемає зображень + +/talkpost.bml.opt.preview=ПереглÑнути + +/talkpost.bml.opt.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´ відправкою (англійÑька). + +/talkpost.bml.opt.subject=Тема: + +/talkpost.bml.opt.submit=Відправити коментар + +/talkpost.bml.opt.willscreen=(буде приховано) + +/talkpost.bml.opt.willscreenfriend=(буде приховано, Ñкщо не в друзÑÑ…) + +/talkpost.bml.paraformat=Ðбзаци будуть автоматично форматовані за замовчуваннÑм. + +/talkpost.bml.postresponse=Додати коментар: + +/talkpost.bml.title=Коментувати + +/talkpost.bml.usermismatch<< +Ви ввели ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, але не вибрали опцію "КориÑтувач ЖЖ". + +Будь лаÑка оберіть вірний тип відпраки коментарÑ, або звільніть поле "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача" +. + +/talkpost.bml.warnscreened=Увага: Це прихований коментар. Якщо ви на нього відповіÑте, він автоматично Ñтане відкритим Ñ– він Ñтане видими Ð´Ð»Ñ Ð²ÑÑ–Ñ…. + +/talkpost_do.bml.error.badpassword=Ви ввели невірний пароль. Якщо ви забули Ñвій пароль, ви можете поновити його тут + +/talkpost_do.bml.error.badusername=Введеного імені не Ñ–Ñнує. Якщо ви забули ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, ви можете поновити його тут, або пиÑати анонімно. + +/talkpost_do.bml.error.banned=Вам не дозволено пиÑати в цьому журналі. + +/talkpost_do.bml.error.blankmessage=Ваш коментар пуÑтий. Будь лаÑка напишіть що-небудь у полі коментара. + +/talkpost_do.bml.error.confused_identity=Ви ввели ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, але обрали пиÑати анонімно, або від імені кориÑтувача, що вже увійшов у журнал. Будь лаÑка повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ та вирішите що дійÑно ви хочете зробити. + +/talkpost_do.bml.error.deleted=Ваш журнал було знищено. Ви не можете пиÑати повідомленнÑ. + +/talkpost_do.bml.error.friendsonly=Тільки друзі [[user]] можуть пиÑати в цьому журналі. + +/talkpost_do.bml.error.lostcookie=ЗдаєтьÑÑ, ваш cookie Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ в Живий Журнал зник. + +/talkpost_do.bml.error.manybytes=Вибачте, але розмір вашого коментара ([[current]]) більше дозволеного розміру ([[limit]]) в байтах. Будь лаÑка повернітьÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкоротіть його та Ñпробуйте ще раз. + +/talkpost_do.bml.error.manychars=Вибачте, але розмір вашого коментара ([[current]]) більше дозволеного розміру ([[limit]]) в Ñимволах. Будь лаÑка повернітьÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкоротіть його та Ñпробуйте ще раз. + +/talkpost_do.bml.error.mustlogin=Ви повинні увійти до журналу викориÑтовуючи ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль щоб коментувати захищений запиÑ. + +/talkpost_do.bml.error.noanon=Ð’ цьому журналі ви не можете пиÑати анонімно. + +/talkpost_do.bml.error.noauth=Ви не авторізовані щоб відповідати на цей захищений запиÑ. + +/talkpost_do.bml.error.nocomments=КориÑтувач заборонив ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost_do.bml.error.noparent=Ðе можна віповідати на неіÑнуючі запиÑи. + +/talkpost_do.bml.error.notafriend=Вибачте, але ви не Ñ” другом кориÑтувача [[user]], а він вÑтановив опцію "тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²", Ð´Ð»Ñ Ñ‚Ð¸Ñ… хто хоче відповіÑти. + +/talkpost_do.bml.error.nousername=Ви не ввели ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Ви можете напиÑати анонімно, Ñкщо у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” акаунту у Живому Журналі. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Вибачте, але вам не можна коментувати будь-Ñкі запиÑи в чужих журналах, доки ви не підтвердете ваш email. Якщо ви загубили лиÑта-підтвердженнÑ, ми можемо виÑлати його знову тут. + +/talkpost_do.bml.error.postshared=Ви не можете пиÑати Ñк Ñпільнота. Такі акаунти репрезентують групу людей, а не оÑобиÑÑ‚Ñ–ÑÑ‚ÑŒ. + +/talkpost_do.bml.error.screened=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу на ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost_do.bml.error.suspended=Дію вашого журналу припинили. Ви не можете пиÑати повідомленнÑ. + +/talkpost_do.bml.error.testacct=ТеÑтові акаунти можуть викориÑтовуватиÑÑŒ тільки в теÑтових журналах. + +/talkpost_do.bml.opt.preview=Preview + +/talkpost_do.bml.preview=Так виглÑдатиме ваш коментар піÑÐ»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²ÐºÐ¸. ВикориÑтовуючи форму нижче ви можете відредагувати його, або відправити таким, Ñкий він Ñ”. + +/talkpost_do.bml.preview.subject=Тема: + +/talkpost_do.bml.preview.submit=Відправити + +/talkpost_do.bml.preview.title=ПереглÑд ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +/talkpost_do.bml.success.loggedin=Тепер ви ввійшли до журналу. + +/talkpost_do.bml.success.message=Ваш коментар відправлено. Ви зможете побачити його тут. + +/talkpost_do.bml.success.screened.comm=Ваш коментар відправлено. Згідно з наÑтройками цієй Ñпільноти, ваш коментар буде прихований, та бачитимете його лише ви та наглÑдачі Ñпільноти. Він буде прихованим доти, доки наглÑдачі не вирішать відкрити його. Ви можете побачити ваш коментар тут. + +/talkpost_do.bml.success.screened.comm.anon=Ваш анонімний коментар відправлено. Згідно з наÑтройками цієй Ñпільноти, ваш коментар буде прихований, його бачитимуть лише наглÑдачі Ñпільноти. Він буде прихованим доти, доки наглÑдачі не вирішать відкрити його. Ви можете побачити тред тут. + +/talkpost_do.bml.success.screened.user=Ваш коментар відправлено. Згідно з наÑтройками цього журналу, ваш коментар буде прихований, та бачитимете його лише ви та влаÑник журналу. Він буде прихованим доти, доки влаÑник не вирішать відкрити його. Ви можете побачити ваш коментар тут. + +/talkpost_do.bml.success.screened.user.anon=Ваш анонімний коментар відправлено. Згідно з наÑтройками цього журналу, ваш коментар буде прихований, його бачитиме лише влаÑник журналу. Він буде прихованим доти, доки влаÑник не вирішить відкрити його. Ви можете побачити тред тут. + +/talkpost_do.bml.success.title=Відправлено + +/talkpost_do.bml.success.unscreened=Доречі, прихований коментар, на Ñкий ви відповідаєте вже не Ñ” прихованим. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Відправка ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +/talkpost_do.bml.title.preview=Попередній переглÑд + +/talkread.bml.anonuser=(Ðнонімно) + +/talkread.bml.confirm.action=Ви впевнені, що хочете вилучити обрані коментарі? + +/talkread.bml.deletedpost=(Вилучений запиÑ) + +/talkread.bml.deleteduser=(Видалений кориÑтувач: [[username]]) + +/talkread.bml.fromip=(з [[ip]]) + +/talkread.bml.noreplies=Ðемає выдповідей + +/talkread.bml.nosubject=(без теми) + +/talkread.bml.screenedpost=(Прихований запиÑ) + +/talkread.bml.select=Вибрати + +/talkread.bml.subjectdeleted=[вилучений] + +/talkread.bml.talkmulti.delete=Вилучити + +/talkread.bml.talkmulti.des=Групова Ð´Ñ–Ñ Ð½Ð°Ð´ обраними коментарÑми: + +/talkread.bml.talkmulti.screen=Приховати + +/talkread.bml.talkmulti.submit=Зробити + +/talkread.bml.talkmulti.unscreen=Відкрити + +/talkread.bml.title=Читати коментарі + +/talkscreen.bml.screened.title=УÑпішно + +/talkscreen.bml.unscreened.title=УÑпішно + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=СпиÑок ваших вибраних запиÑів було оновлено. + +/tools/memadd.bml.body.added.header=УÑпішно + +/tools/memadd.bml.description=ОпиÑ: + +/tools/memadd.bml.description.text=Дайте Ð¾Ð¿Ð¸Ñ Ñ†ÑŒÐ¾Ð¼Ñƒ запиÑові. Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу з вибраного, уведіть порожню Ñтроку. + +/tools/memadd.bml.error.deleted.body=Ð—Ð°Ð¿Ð¸Ñ Ð· опиÑом "[[desc]]" було вилучено зі ÑпиÑку вибраних запиÑів. + +/tools/memadd.bml.error.deleted.title=Вибраний Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¾ + +/tools/memadd.bml.error.entry_deleted=Такого запиÑу більше не Ñ–Ñнує. Вибраний Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¾. + +/tools/memadd.bml.error.fivekeywords=ДозволÑєтьÑÑ Ð²ÐºÐ°Ð·Ð°Ñ‚Ð¸ тільки 5 ключових Ñлів/категорій Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ запиÑу. + +/tools/memadd.bml.error.invalid_security=Ðевірно вказаний або відÑутній рівень безпеки. + +/tools/memadd.bml.error.login=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ, ви повинні увійти до журналу. + +/tools/memadd.bml.error.maxsize=Це ключове Ñлово перевищує макÑимально можливий розмір: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додати цей Ð·Ð°Ð¿Ð¸Ñ Ñƒ вибране, вам потрібно вказати короткий опиÑ. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб видалити Ð·Ð°Ð¿Ð¸Ñ Ð· обраного, ви можете відредагувати та видалити опиÑ, але цього запиÑу в обраному ще не має. + +/tools/memadd.bml.error.nodescription.title=Без опиÑу + +/tools/memadd.bml.form.submit=Додати + +/tools/memadd.bml.keywords=Ключові Ñлова: + +/tools/memadd.bml.keywords.example=Приклад: Ñмішне, тупе, романтичне + +/tools/memadd.bml.keywords.select=Ðбо виберіть із ключових Ñлів, що було викориÑтано раніше: + +/tools/memadd.bml.keywords.text=Чому ви додаєтет цей Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ðµ? Уведіть не більш, ніж 5 ключовихї Ñлів або категорій, розділених комами. + +/tools/memadd.bml.login.enterinfo=Уведіть Ñ–Ð¼â€™Ñ + +/tools/memadd.bml.login.forgot.header=ЩоÑÑŒ забули? + +/tools/memadd.bml.login.forgot.recover=Якщо ви забули ім'Ñ Ð°Ð±Ð¾ пароль, відновіть Ñ—Ñ… тут!. + +/tools/memadd.bml.multiple_selections=Щоб вибрати кілька ключових Ñлів, натиÑніть та утримуйте 'Control' + +/tools/memadd.bml.security=Рівень безпеки: + +/tools/memadd.bml.security.friendsonly=Тільки друзі + +/tools/memadd.bml.security.private=Тільки Ñ + +/tools/memadd.bml.security.public=УÑÑ– + +/tools/memadd.bml.title=Додати у вибране + +/tools/memadd.bml.title.added=Додано + +/tools/memadd.bml.title.add_memory=Додати у вибране + +/tools/memadd.bml.title.deleted=Видалено + +/tools/memadd.bml.title.edit_memory=Редагувати вибране + +/tools/memadd.bml.whocansee<< +Хто може бачити, що ви додали цей Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ вибраного? +УÑÑ–, тільки ваші друзі чи тільки ви? +. + +/tools/memories.bml.back=Ðазад + +/tools/memories.bml.body.keyword<< + +[[user]]
    в категорії "[[keyword]]". p?> + +. + +/tools/memories.bml.body.list_categories<< + +[[user]] розділив Ñвої вибрані запиÑи. p?> + +. + +/tools/memories.bml.body.memorable=Ðижче наведено ÑпиÑок вибраних запиÑів кориÑтувача [[user]], Ñкі не потрапили до жодної категорії. + +/tools/memories.bml.edit=редагувати + +/tools/memories.bml.error.noentries.body<< +Це могло ÑтатиÑÑ Ñ‚Ð¾Ð¼Ñƒ, що
      +
    1. кориÑтувач не має жодного вибраного запиÑу,
    2. +
    3. вибрані запиÑи кориÑтувача захищені та ви не маєте доÑтупу до них, або
    4. +
    5. кориÑтувач не має жодного вибраного запиÑу, що відповідає критеріÑм вашого пошуку.
    + +. + +/tools/memories.bml.error.noentries.title=Ðемає вибраних запиÑів + +/tools/memories.bml.filter.all=УÑÑ– вибрані запиÑи + +/tools/memories.bml.filter.other=Тільки інші запиÑи + +/tools/memories.bml.filter.own=Тільки запиÑи кориÑтувача '[[user]]' + +/tools/memories.bml.form.filter=Які запиÑи відображати: + +/tools/memories.bml.form.sort=ПорÑдок ÑортуваннÑ: + +/tools/memories.bml.form.switch=Вибрати + +/tools/memories.bml.sort.description=За опиÑом + +/tools/memories.bml.sort.journal=За журналом + +/tools/memories.bml.sort.orderadded=За порÑдком Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ + +/tools/memories.bml.title.keyword=Вибране в категорії [[keyword]] + +/tools/memories.bml.title.memorable=Вибране + +/tools/memories.bml.uncategorized=Без категорії + +/update.bml.altpost=Додати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ журналу: + +/update.bml.btn.update=Додати запиÑ... + +/update.bml.currmood=ÐаÑтрій: + +/update.bml.currmusic=Музика: + +/update.bml.date=Дата: + +/update.bml.default=за замовчуваннÑм + +/update.bml.defaultjournal=([[user]]) -- за замовчуваннÑм + +/update.bml.error.login=Помилка входу до журналу: + +/update.bml.error.update=Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ: + +/update.bml.event=ТекÑÑ‚ запиÑу: + +/update.bml.full=Сторінка повного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/update.bml.htmlokay.norich=(HTML дозволено; за замовчуваннÑм, перед новими Ñ€Ñдками автоматично буде додано <br />) + +/update.bml.htmlokay.rich=(HTML дозволено; за замовчуваннÑм, перед новими Ñ€Ñдками автоматично буде додано <br /> - або викориÑовуйте rich text) + +/update.bml.localtime=МіÑцевий чаÑ: + +/update.bml.loggingin=Входжу до журналу... + +/update.bml.noneother=Ðемає, або інший: + +/update.bml.note=Увага: Ð§Ð°Ñ Ñ‚Ð° дата взÑÑ‚Ñ– з нашого Ñервера. Відредагуйте Ñ—Ñ… відноÑно вашої чаÑової зони перед напиÑаннÑм. + +/update.bml.opt.backdate=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом: + +/update.bml.opt.defpic=(за замовчуваннÑм) + +/update.bml.opt.nocomments=Заборонити коментарі: + +/update.bml.opt.noemail=Ðе виÑилати коментарі на email: + +/update.bml.opt.noformat=Ðе автоформатувати: + +/update.bml.opt.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ (лише англійÑькою) + +/update.bml.options=Додаткові параметри + +/update.bml.other=Інший: + +/update.bml.picture=Картинка: + +/update.bml.security.custom=Вибірково... + +/update.bml.security.friends=Ð”Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/update.bml.security.head=Рівень безпеки: + +/update.bml.security.private=Лише Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ + +/update.bml.security.public=Ð”Ð»Ñ Ð²ÑÑ–Ñ… + +/update.bml.servermsg=Ðа Ñервері Ñ” Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ð°Ñ: + +/update.bml.simple=Ви дивитеÑÑŒ на Ñпрощену Ñторінку. Ð”Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… наÑтройок, зайдіть Ñюди. + +/update.bml.spellchecked=Ваш запиÑ, з перевіреною орфографією: + +/update.bml.subject=Тема: (не обов'Ñзково) + +/update.bml.timeformat=24-годинний Ñ‡Ð°Ñ + +/update.bml.title=ÐапиÑати + +/update.bml.title.readonly=Режим тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/update.bml.update.head=Додати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ журналу... + +/update.bml.update.success=Ваш журнал оновлено. Ви можете подивитиÑÑŒ ваш оновлений журнал тут. + +/update.bml.updating=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ... + +/userinfo.bml.about.user=БіографіÑ: + +/userinfo.bml.body.leave=Ви можете залишити Ñпільноту у будь-Ñкий чаÑ. + +/userinfo.bml.comminfo.body=Ðижче ви знайдете інформацію про Ñпільноту "[[commname]]". + +/userinfo.bml.comminfo.name=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñпільноту + +/userinfo.bml.date.never=Ðіколи. + +/userinfo.bml.error.notloggedin=Якщо ви бажаєте побачити ваш профіль, вам потрібно ввійти в ÑиÑтему. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=ДивлÑÑ‚ÑŒÑÑ: + +/userinfo.bml.friendof.hidden=(приховано) + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Ð’ друзÑÑ…: + +/userinfo.bml.friends.comm=УчаÑники + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Друзі + +/userinfo.bml.label.adduser=Додати кориÑтувача + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=День народженнÑ: + +/userinfo.bml.label.clientsused=ВикориÑтані клієнти: + +/userinfo.bml.label.comments=Коментарі: + +/userinfo.bml.label.composted=Залишено: [[num]] - + +/userinfo.bml.label.comreceived=Отримано: [[num]] + +/userinfo.bml.label.datecreated=Дата ÑтвореннÑ: + +/userinfo.bml.label.dateupdated=Дата оновленнÑ: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=Email: + +/userinfo.bml.label.icquin=Ðомер ICQ: + +/userinfo.bml.label.interests=ІнтереÑи + +/userinfo.bml.label.interests.modifyyours=Редагувати Ð²Ð°ÑˆÑ– + +/userinfo.bml.label.interests.removesome=Видалити + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] інтереÑів не показано + +/userinfo.bml.label.journalentrs=ЗапиÑів у журналі: + +/userinfo.bml.label.location=МіÑцезнаходженнÑ: + +/userinfo.bml.label.memberof=УчаÑник + +/userinfo.bml.label.memories=Вибране: + +/userinfo.bml.label.moredetails=(детальніше...) + +/userinfo.bml.label.msnusername=Ім'Ñ Ð² MSN + +/userinfo.bml.label.name=Ім'Ñ: + +/userinfo.bml.label.nofriends=Ðемає. + +/userinfo.bml.label.reqfinduser=Тільки кориÑтувачі з привілеєю 'finduser' можуть шукати кориÑтувачів за Ñ—Ñ… кодом. + +/userinfo.bml.label.shared=Може пиÑати: + +/userinfo.bml.label.user=КориÑтувач: + +/userinfo.bml.label.viewfriends=ДивитиÑÑ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/userinfo.bml.label.viewmembers=ДивитиÑÑ ÑƒÑ‡Ð°Ñників + +/userinfo.bml.label.website=ВебÑайт: + +/userinfo.bml.label.yahooid=Yahoo! ID: + +/userinfo.bml.membership.body=Щоб приєднатиÑÑŒ до цієї Ñпільноти, натиÑніть тут. + +/userinfo.bml.memories.entries=[[count]] запиÑів + +/userinfo.bml.memories.entry=[[count]] Ð·Ð°Ð¿Ð¸Ñ + +/userinfo.bml.nonexist.name=Ðевідомий кориÑтувач + +/userinfo.bml.syn.last.never=Ðіколи + +/userinfo.bml.syn.parseerror=Помилка: + +/userinfo.bml.timeupdate.dayago=1 день тому + +/userinfo.bml.timeupdate.daysago=[[num]] днів тому + +/userinfo.bml.timeupdate.hourago=1 годину тому + +/userinfo.bml.timeupdate.hoursago=[[num]] годин тому + +/userinfo.bml.timeupdate.minuteago=1 хвилину тому + +/userinfo.bml.timeupdate.minutesago=[[num]] хвилин тому + +/userinfo.bml.timeupdate.secondago=1 Ñукунду тому + +/userinfo.bml.timeupdate.secondsago=[[num]] Ñекунд + +/userinfo.bml.timeupdate.weekago=1 тиждень тому + +/userinfo.bml.timeupdate.weeksago=[[num]] тижнів тому + +/userinfo.bml.title=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/userinfo.bml.title.communityinfo=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/userinfo.bml.userinfo.body=Ðижче ви бачите інформацію про кориÑтувача [[username]]. Якщо цей кориÑтувач - ви, ви можете відредагувати цю інформацію (або обрати Ñка Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ” публічною) на Ñторінці Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ—. + +/userinfo.bml.userinfo.name=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ кориÑтувача + +btn.search=Пошук + +dystopia.btn.login=Увійти + +dystopia.hello_anonymous=Вітаємо у Живому Журналі! + +dystopia.hello_loggedin=Привіт, [[username]]! + +dystopia.nav.createjournal=Створити журнал + +dystopia.nav.developer=Ð”Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² + +dystopia.nav.download=Загрузити + +dystopia.nav.editentries=Редагувати запиÑи + +dystopia.nav.editfriends=Ваші друзі + +dystopia.nav.editpassword=Ваш пароль + +dystopia.nav.editpics=Ваші Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +dystopia.nav.editstyle=Стиль + +dystopia.nav.faq=Поміч ЖЖ + +dystopia.nav.findcomm=За Ñпільнотою + +dystopia.nav.finddir=Шукати у каталозі + +dystopia.nav.findint=За інтереÑами + +dystopia.nav.findrandom=Випадково + +dystopia.nav.findregion=За регіоном + +dystopia.nav.home=Початок + +dystopia.nav.journalcalendar=Календар + +dystopia.nav.journalfriends=Друзі + +dystopia.nav.journalinfo=ОÑобиÑта Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +dystopia.nav.journalrecent=Свіжі запиÑи + +dystopia.nav.legalprivacy=ПриватніÑÑ‚ÑŒ + +dystopia.nav.legaltos=Умови кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +dystopia.nav.login=Увійти + +dystopia.nav.logout=Вийти + +dystopia.nav.lostinfo=Ðагадати пароль + +dystopia.nav.memories=Вибране + +dystopia.nav.modifyjournal=Змінити журнал + +dystopia.nav.news=Ðовини + +dystopia.nav.paidaccts=Платні акаунти + +dystopia.nav.paymentarea=Платежи + +dystopia.nav.personalinfo=ПерÑональна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +dystopia.nav.sitemap=Карта Ñайту + +dystopia.nav.siteopts=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñайту + +dystopia.nav.support=Є питаннÑ? + +dystopia.nav.updatejournal=ÐапиÑати + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=150 + +dystopia.navhead.findusers=Шукати кориÑтувачів + +dystopia.navhead.help=Допомога та підтримка + +dystopia.navhead.journal=Ваш журнал + +dystopia.navhead.legal=Правова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +dystopia.navhead.settings=ÐаÑтройки + +dystopia.navhead.welcome=Вітаємо! + +dystopia.search.icq=Ðомер ICQ + +dystopia.search.int=ІнтереÑи + +dystopia.search.msn=Ім'Ñ Ð² MSN + +dystopia.search.region=Регіон + +dystopia.searchlj=Шукати в ЖЖ: + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Помилка + +error.badpassword=Ðевірний пароль. + +error.dberror=Помилка бази даних: + +error.deleted.name=Вилучений + +error.deleted.text=Цей журнал вилучено. Якщо ви [[user]], ви маєте 30 днів з Ð´Ð½Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ñ‰Ð¾Ð± відмінити Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу. ПіÑÐ»Ñ 30 днів ми вилучимо вÑе пов'Ñзане з вашим журналом з Ñерверів. + +error.deleted.title=Вилучений акаунт + +error.invalidauth=Ви не можете бути ауте + +error.ipbanned=Ваша IP-адреÑа тимчаÑово заблокована через Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ ÐºÑ–Ð»ÑŒÐºÐ¾ÑÑ‚Ñ– помилок при вході в журнал. + +error.malformeduser=Погане ім'Ñ. + +error.nobutton=Ðе натиÑнули на кнопку? + +error.nodb=База даних тимчаÑово недоÑтупна. + +error.nodbmaintenance=Ð¦Ñ Ñ‡Ð°Ñтина бази даних тимчаÑово зачинена на обÑлуговуваннÑ. Спробуйте ще раз за декілька хвилин. + +error.noentry=Такого запиÑу не Ñ–Ñнує. + +error.nojournal=Ðевідомий Журнал + +error.noremote=Вам потрібно увійти до журналу щоб кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою. + +error.procrequest=Під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ запиту виникла помилка: + +error.purged.name=Вилучений + +error.purged.text=Цей журнал очищено та вилучено. + +error.purged.title=Очищений акаунт. + +error.suspended.name=Припинений + +error.suspended.title=Припинений акаунт + +error.tempdisabled=ТимчаÑово відключений. + +error.unknownmode=Ðевідомий режим + +error.usernameinvalid=Ім'Ñ Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ” не дозвоені Ñимволи. + +error.usernamelong=Ім'Ñ Ð·Ð°Ð´Ð¾Ð²Ð³Ðµ, 15 Ñимволів макÑимум. + +error.username_notfound=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача не знайдено. + +Help=Допомога + +label.security.custom=Вибірково... + +label.security.friends=Ð”Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +label.security.head=Рівень безпеки: + +label.security.private=Лише Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ + +label.security.public=Ð”Ð»Ñ Ð²ÑÑ–Ñ… + +label.switch.button=Переключити + +label.switch.header=Переключити журнал + +label.switch.workwith=Працювати з журналом: + +langname.be=БілоруÑька + +langname.da=ДатÑька + +langname.de=Ðімецька + +langname.en=ÐнглійÑька + +langname.en_GB=ÐнглійÑька (ВеликобританіÑ) + +langname.en_LJ=ÐнглійÑька + +langname.eo=ЕÑперанто + +langname.es=ІÑпанÑька + +langname.et=ЕÑтонÑька + +langname.fi=ФінÑька + +langname.fr=Французька + +langname.ga=ІрландÑька + +langname.he=Іврит + +langname.hu=УгорÑька + +langname.is=ІÑландÑька + +langname.it=ІталійÑька + +langname.ja=ЯпонÑька + +langname.la=ЛатинÑька + +langname.lv=ЛатвійÑька + +langname.ms=МалайÑька + +langname.nb=Ðорвезька - BokmÃ¥l + +langname.nl=ГоландÑька + +langname.pl=ПольÑька + +langname.pt=ПортугальÑька + +langname.ru=РоÑійÑька + +langname.sv=ШведÑька + +langname.tr=Турецька + +langname.uk=УкраїнÑька + +langname.zh=КитайÑька Ñпрощена + +ljcom.badpass.email=Ваш пароль не може базуватиÑÑŒ на адреÑÑ– email. + +ljcom.badpass.realname=Ваш пароль не може базуватиÑÑŒ на реальному імені. + +ljcom.badpass.username=Ваш пароль не може базуватиÑÑŒ на імені. + +ljcom.userinfo.accounttype=Тип акаунту + +ljcom.userinfo.paiduser=Платний кориÑтувач + +ljcom.userinfo.types.early=Ранній кориÑтувач + +ljcom.userinfo.types.free=Безкоштовний акаунт + +ljcom.userinfo.types.paid=Платний Ðкаунт + +ljcom.userinfo.types.paid_early=Платний акаунт, попередньо Ранній КориÑтувач + +ljcom.userinfo.types.paid_early_expiring=Платний акаунт, закінчуєтьÑÑ [[paiduntil]], в минулому Ранній Ðкаунт + +ljcom.userinfo.types.paid_expiring=Платний акаунт, закінчуєтьÑÑ [[paiduntil]] + +ljcom.userinfo.types.permanent=БезÑтроковий акаунт + +ljcom.userinfo.types.permanent_early=БезÑтроковий акаунт, в минулому Ранній кориÑтувач + +portal.memories.entriesnoun=запиÑи + +portal.memories.entrynoun=Ð·Ð°Ð¿Ð¸Ñ + +portal.memories.portalname=Вибране + +portal.memories.portaltitle=Вибране + +portal.ministats.active=Пишуть: + +portal.ministats.title=КориÑтувачі + +portal.ministats.total=Ð’Ñього: + +portal.stats.portalname=СтатиÑтика Ñайту + +portal.update.portalname=ÐапиÑати + +portal.update.portaltitle=ÐапиÑати в журнал + +protocol.must_revalidate=Ви повинні підтвердити ваш e-mail. Ваш Ñтарий e-mail був правильним, але оÑкільки ви змінили його, ви повинні ще раз підтвердити новий e-mail. Якщо ви не зробите цього, ви не отримаєте доÑтуп до вÑÑ–Ñ… функцій [[sitename]]. Додаткову інформацію можна знайти за адреÑою [[siteroot]]/support/faqbrowse.bml?faqid=11 + +protocol.not_validated=Ваш новий e-mail не був підтверджений. Ви може продовжувати кориÑтуватиÑÑ [[sitename]], але Ñкщо ви не підтвердите вашу адреÑу, ви не отримаєте доÑтупу до вÑÑ–Ñ… функцій Ñайту. ІнÑтрукції ви можете знайти в лиÑÑ‚Ñ–, котрий був відіÑланий вам, коли ви Ñтворили ваш журнал. Також додаткову інформацію можна знайти за адреÑою [[siteroot]]/support/faqbrowse.bml?faqid=11 + +talk.anonwrote=ХтоÑÑŒ напиÑав, + +talk.anonwrote_comm=ХтоÑÑŒ напиÑав у [[commlink]], + +talk.btn.preview=ПереглÑнути + +talk.commentpermlink=поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +talk.commentpost=ÐапиÑати коментар + +talk.commentsread=Читати коментарі + +talk.curname_Mood=ÐаÑтрій: + +talk.curname_Music=Музика: + +talk.error.comm_deleted=Коментар вилучено. + +talk.error.deleted=Цей журнал вилучено. + +talk.error.deleted.title=Вилучено + +talk.error.mustlogin=Ви повинні увійти до журналу щоб побачити цей захищений запиÑ. + +talk.error.nocomment=Коментарю не Ñ–Ñнує. + +talk.error.noentry=Такого запиÑу не Ñ–Ñнує. + +talk.error.nosuchjournal=Такого журналу не Ñ–Ñнує. + +talk.error.notauthorised=Ва не авторизовані щоб дивитиÑÑŒ цей захищений запиÑ. + +talk.error.suspended=Ð”Ñ–Ñ Ñ†ÑŒÐ¾Ð³Ð¾ журналу припинена. + +talk.error.suspended.title=Припинено + +talk.parentlink=Рівнем вище + +talk.replytothis=ВідповіÑти + +talk.somebodywrote=[[realname]] ([[userlink]]) пише, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) пише у [[commlink]], + +talk.spellcheck=ПеревірÑти орфографію (англійÑька) + +talk.threadlink=Тред + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_ukrainian + +Username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +xcolibur.greeting.anon=Вітаємо Ð²Ð°Ñ Ñƒ Живому Журналі! + +xcolibur.greeting.logged_in=Привіт, [[name]]! [[logout]] + +xcolibur.login=Увійти? + +xcolibur.logout=Вийти? + +xcolibur.nav.about=Про Ð½Ð°Ñ + +xcolibur.nav.about.download=Загрузка + +xcolibur.nav.about.general=ОÑновна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +xcolibur.nav.about.paidaccounts=Платні акаунти + +xcolibur.nav.about.press=ПреÑа + +xcolibur.nav.about.sitenews=Ðовини Ñайту + +xcolibur.nav.about.stats=СтатиÑтика + +xcolibur.nav.footer.sitemap=Карта Ñайту + +xcolibur.nav.help=Допомога + +xcolibur.nav.help.ask=Задати Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +xcolibur.nav.help.contact=Контактна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Загубили пароль? + +xcolibur.nav.home=Початок + +xcolibur.nav.journal=Журнал + +xcolibur.nav.journal.archive=Ðрхів + +xcolibur.nav.journal.edit.entries=Редагувати запиÑи + +xcolibur.nav.journal.friends=Друзі + +xcolibur.nav.journal.info=Про кориÑтувача + +xcolibur.nav.journal.memories=Вибране + +xcolibur.nav.journal.recent=Свіжі запиÑи + +xcolibur.nav.journal.update=ÐапиÑати + +xcolibur.nav.manage=Редагувати + +xcolibur.nav.manage.community=Спільноти + +xcolibur.nav.manage.customize=ВиглÑд + +xcolibur.nav.manage.entries=ЗапиÑи + +xcolibur.nav.manage.friends=Друзі + +xcolibur.nav.manage.info=ОÑобиÑта Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +xcolibur.nav.manage.password=Пароль + +xcolibur.nav.manage.pics=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +xcolibur.nav.manage.styles=Стилі + +xcolibur.nav.search=Пошук + +xcolibur.nav.search.directory=За регіоном + +xcolibur.nav.search.directory.search=Розширений + +xcolibur.nav.search.interests=За інтереÑами + +xcolibur.nav.search.random=Випадково + +xcolibur.nav.siteopts=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñайту + +xcolibur.nav.title=ÐавігаціÑ: + +xcolibur.nav.welcome=ЛаÑкаво проÑимо + +xcolibur.nav.welcome.create=Створити акаунт + +xcolibur.nav.welcome.login=Увійти + +xcolibur.nav.welcome.update=ÐапиÑати в журнал + +xcolibur.search=Пошук: + +xcolibur.search.aolim=AOL IM + +xcolibur.search.category=КатегоріÑ: + +xcolibur.search.icq=Ðомер ICQ + +xcolibur.search.int=ІнтереÑи + +xcolibur.search.jabber=Jabber + +xcolibur.search.msn=Ім'Ñ Ð² MSN + +xcolibur.search.region=Регіон + +xcolibur.search.yahoo=Yahoo! ID + +xcolibur.upgrade=Зроби Ñвій акаунт платним! + diff --git a/ljcom/bin/upgrading/update-db-local.pl b/ljcom/bin/upgrading/update-db-local.pl new file mode 100644 index 0000000..770eb45 --- /dev/null +++ b/ljcom/bin/upgrading/update-db-local.pl @@ -0,0 +1,659 @@ +# +# database schema & data info for livejournal.com +# + +mark_clustered(@LJ::USER_TABLES_LOCAL); + +register_tablecreate("paycredit", < +# perm +# rename +# morestats qty= +# morepics? + +register_tablecreate("payitems", <<'EOC'); +CREATE TABLE payitems ( + piid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (piid), + payid INT UNSIGNED NOT NULL, + INDEX (payid), + item VARCHAR(25), + qty SMALLINT UNSIGNED, + rcptid INT UNSIGNED NOT NULL, # cart owner's ID, gift rcpt's ID, or 0 for invite/"pay" code emailed + amt DECIMAL(8,2), + status ENUM('cart','pend','done','refund','bogus'), + INDEX (status), + rcptemail VARCHAR(80), # email address to mail paycode to, if non-user + anon ENUM('0','1'), # is gift anonymous? + giveafter INT UNSIGNED # unixtime to give gift after +) +EOC + +# payid <=> state mappings +register_tablecreate("paystates", <<'EOC'); +CREATE TABLE paystates ( + payid int unsigned NOT NULL, + PRIMARY KEY (payid), + state VARCHAR(25) NOT NULL DEFAULT '??', + INDEX (state) +) +EOC + +# clothing babydoll-royalblue-xl 234 220 +register_tablecreate("inventory", <<'EOC'); +CREATE TABLE inventory ( + item VARCHAR(25) NOT NULL, + subitem VARCHAR(35) NOT NULL, + PRIMARY KEY (item, subitem), + qty SMALLINT UNSIGNED NOT NULL, + avail SMALLINT UNSIGNED NOT NULL, + price DECIMAL(8,2) +) +EOC + +register_tablecreate("shipping", <<'EOC'); +CREATE TABLE shipping ( + payid INT UNSIGNED NOT NULL, + PRIMARY KEY (payid), + status ENUM('needs', 'shipped') NOT NULL, + INDEX (status), + dateready DATETIME, + dateshipped DATETIME +) +EOC + +register_tablecreate("coupon", <<'EOC'); +CREATE TABLE coupon ( + cpid MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + auth CHAR(10), + type VARCHAR(20), # freeclothingitem, dollaroff (-$arg), percentoff (-%arg) + arg VARCHAR(30), + rcptid INT UNSIGNED NOT NULL, + INDEX (rcptid), + locked ENUM('0', '1') DEFAULT '0' NOT NULL, + payid INT UNSIGNED NOT NULL, + INDEX (payid) +) +EOC + +register_tablecreate("paymentsearch", <<'EOC'); +CREATE TABLE paymentsearch +( + payid INT UNSIGNED NOT NULL, + INDEX (payid), + ikey varchar(12) NOT NULL, + ival varchar(50) NOT NULL, + INDEX (ikey, ival) +) +EOC + +register_tablecreate("authnetlog", <<'EOC'); +CREATE TABLE authnetlog +( + payid INT UNSIGNED NOT NULL, + INDEX (payid), + datesent DATETIME, + ip VARCHAR(15), + amt DECIMAL(8,2), + result ENUM('pass','fail'), + response TEXT +) +EOC + +register_tablecreate("transferinfo", <" for owed, free form (check number, etc) for paid +register_tablecreate("bzrbalance", <<'EOC'); +CREATE TABLE bzrbalance ( + userid INT UNSIGNED NOT NULL, + bzid SMALLINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, bzid), + + date DATETIME, + + amt DECIMAL(5,2), + owed DECIMAL(5,2), + expired DECIMAL(5,2) +) +EOC + +# note = "coupon:(\S+)" when method = "coupon" +# note = free form when method='money' +register_tablecreate("bzrpayout", <<'EOC'); +CREATE TABLE bzrpayout ( + userid INT UNSIGNED NOT NULL, + date DATETIME, + amt DECIMAL(5,2), + method ENUM('money','coupon'), + note VARCHAR(80), + INDEX (userid) +) +EOC + +register_tablecreate("tshirtpoll", <<'EOC'); +CREATE TABLE tshirtpoll ( + userid INT UNSIGNED NOT NULL, + INDEX (userid), + style VARCHAR(20), + color VARCHAR(20), + size VARCHAR(5), + qty SMALLINT UNSIGNED NOT NULL +) +EOC + +# paid item expiration times +register_tablecreate("paidexp", <<'EOC'); +CREATE TABLE paidexp ( + userid INT unsigned NOT NULL default '0', + item VARCHAR(25) NOT NULL default '', + expdate DATETIME NOT NULL default '0000-00-00 00:00:00', + daysleft SMALLINT NOT NULL DEFAULT '0', + PRIMARY KEY (userid, item) +) +EOC + +register_tablecreate("phonepostlogin", <<'EOC'); +CREATE TABLE phonepostlogin ( + phone VARCHAR(20) NOT NULL, + pin VARCHAR(10) NOT NULL, + userid INT UNSIGNED NOT NULL, + journalid INT UNSIGNED NOT NULL, + PRIMARY KEY (phone, pin), + UNIQUE KEY (userid, journalid) +) +EOC + +# blob from blobid must be of type 'phonepost'. +# security is inferred from jitemid; if there is no log2 row, it's private. +register_tablecreate("phonepostentry", <<'EOC'); +CREATE TABLE phonepostentry ( + userid INT UNSIGNED NOT NULL, + blobid MEDIUMINT UNSIGNED NOT NULL, + lengthsecs MEDIUMINT UNSIGNED NOT NULL, + anum TINYINT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + PRIMARY KEY (userid, blobid), + INDEX (posttime) +) +EOC + +# blob from blobid must be of type 'phonepost'. +# security is inferred from jitemid; if there is no log2 row, it's private. +register_tablecreate("phoneposttrans", <<'EOC'); +CREATE TABLE phoneposttrans ( + journalid INT UNSIGNED NOT NULL, + blobid MEDIUMINT UNSIGNED NOT NULL, + revid TINYINT UNSIGNED NOT NULL, + posterid INT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + subject VARCHAR(255) BINARY, + body BLOB, + PRIMARY KEY (journalid, blobid, revid) +) +EOC + +# TEMP: Survey of unknown8bit posts, populated by +# a postpost hook in ljcom.pl . +register_tablecreate("survey_v0_8bit", <<'EOC'); +CREATE TABLE survey_v0_8bit ( + userid INT UNSIGNED NOT NULL, + timepost INT UNSIGNED NOT NULL, + PRIMARY KEY (userid), + INDEX (timepost) +) +EOC + +# keep track of avs fails per user +register_tablecreate("ccfail", <<'EOC'); +CREATE TABLE ccfail ( + email VARCHAR(50) NOT NULL, + time INT UNSIGNED NOT NULL, + userid INT UNSIGNED, + why VARCHAR(100), + PRIMARY KEY (email, time), + KEY (userid) +) +EOC + +# FotoBilder feedback surveys +register_tablecreate("fotobilder_feedback", <<'EOC'); +CREATE TABLE fotobilder_feedback ( + url VARCHAR(100) NOT NULL, + userid INT UNSIGNED, + state CHAR(1) NOT NULL, + body BLOB, + + INDEX (url), + INDEX (state), + INDEX (userid) +) +EOC + +# Payment fraud +register_tablecreate("fraudsuspects", <<'EOC'); +CREATE TABLE fraudsuspects ( + payid INT UNSIGNED NOT NULL, + PRIMARY KEY (payid), + dateadd INT UNSIGNED NOT NULL, + reason TEXT +) +EOC + +# External phonepost destinations +# For an explaination of this table, see +# ljcomint/doc/notes/external_phoneposting.txt +register_tablecreate("phonepostdests", <<'EOC'); +CREATE TABLE phonepostdests ( + userid INT UNSIGNED NOT NULL DEFAULT 0, + destid INT UNSIGNED NOT NULL DEFAULT 0, + namespace INT UNSIGNED NOT NULL, + audio_type VARCHAR(20) NULL, + audio_post_url VARCHAR(255) NULL, + audio_user VARCHAR(255) NULL, + audio_password VARCHAR(255) NULL, + blog_type VARCHAR(20) NULL, + blog_name VARCHAR(255) NULL, + blog_post_url VARCHAR(255) NULL, + blog_user VARCHAR(255) NULL, + blog_password VARCHAR(255) NULL, + PRIMARY KEY (userid, destid, namespace) +) +EOC + +# Style contest +register_tablecreate("temp_stylecontest2poll", <<'EOC'); +CREATE TABLE temp_stylecontest2poll ( + userid INT UNSIGNED NOT NULL, + votetime INT UNSIGNED NOT NULL, + vote VARCHAR(50), + UNIQUE (userid, vote), + INDEX (vote) +); +EOC + +register_alter(sub { + + unless (column_type("payments", "giveafter")) { + do_alter("payments", + "ALTER TABLE payments ADD giveafter INT UNSIGNED"); + } + + unless (column_type("payments", "anum")) { + do_alter("payments", + "ALTER TABLE payments ". + "ADD anum SMALLINT UNSIGNED AFTER payid, ". + "MODIFY used ENUM('N','Y','C') NOT NULL DEFAULT 'N', ". + "MODIFY mailed ENUM('N','Y','C') NOT NULL DEFAULT 'N'"); + } + + unless (column_type("payments", "mailed") =~ /'X'/i) { + do_alter("payments", + "ALTER TABLE payments ". + "MODIFY mailed ENUM('N','Y','C','X') NOT NULL DEFAULT 'N'"); + } + + unless (column_type("payitems", "token")) { + do_alter("payitems", + "ALTER TABLE payitems ADD token VARCHAR(25), ADD tokenid INT UNSIGNED"); + } + + unless (index_name("payitems", "INDEX:rcptemail")) { + do_alter("payitems", + "ALTER TABLE payitems ADD INDEX (rcptemail), ". + "ADD INDEX (rcptid)"); + } + + unless (column_type("payitems", "subitem")) { + do_alter("payitems", + "ALTER TABLE payitems ADD subitem VARCHAR(35) AFTER item, ". + "ADD qty_res SMALLINT UNSIGNED"); + } + + unless (column_type("authnetlog", "cmd")) { + do_alter("authnetlog", + "ALTER TABLE authnetlog ". + "ADD cmd ENUM('authcap','credit','void') NOT NULL DEFAULT 'authcap' AFTER payid, ". + "ADD cmdnotes VARCHAR(255)"); + } + + unless (column_type("authnetlog", "cmd") =~ /authonly/) { + do_alter("authnetlog", + "ALTER TABLE authnetlog ". + "MODIFY cmd ENUM('authcap','credit','void','authonly','priorcap','caponly') NOT NULL DEFAULT 'authcap'"); + + } + + unless (index_name("contributed", "INDEX:dateadd")) { + do_alter("contributed", + "ALTER TABLE contributed ADD INDEX (dateadd)"); + } + + unless (index_name("abuse_mail", "INDEX:mailto")) { + do_alter("abuse_mail", + "ALTER TABLE abuse_mail ADD INDEX (mailto)"); + } + + unless (column_type("paytrans", "action") =~ 'ext') { + do_alter("paytrans", + "ALTER TABLE paytrans MODIFY action " . + "ENUM('new', 'renew', 'expire', 'return', 'ext')"); + } + + unless (column_type("coupon", "ppayid")) { + do_alter("coupon", + "ALTER TABLE coupon ADD ppayid INT UNSIGNED NOT NULL DEFAULT 0 AFTER payid, " . + "ADD INDEX(ppayid)"); + + # populate ppayids of old coupons + if (column_type("coupon", "ppayid")) { + print "Populating coupon.ppdayid from payitems...\n"; + + # query will get a lot of rows, but probably not too many + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT payid, tokenid FROM payitems " . + "WHERE item='coupon' AND amt>0 AND status<>'cart'"); + # amt>0 means where it was bought, not used + $sth->execute(); + my $ct = 0; + while (my ($payid, $tokenid) = $sth->fetchrow_array) { + $dbh->do("UPDATE coupon SET ppayid=? WHERE cpid=?", undef, $payid, $tokenid); + print "$ct rows...\n" if ++$ct % 500 == 0; + } + print "$ct total rows updated.\n\n"; + } + } + + # change phonepost entry + unless (column_type("phonepostentry", "filetype")) { + do_alter("phonepostentry", + "ALTER TABLE phonepostentry DROP INDEX posttime, ". + "ADD filetype TINYINT UNSIGNED NOT NULL DEFAULT '0'"); + } + + # email reminder date on bonus features + unless (column_type("paidexp", "lastmailed")) { + do_alter("paidexp", + "ALTER TABLE paidexp ADD lastmailed datetime NOT NULL DEFAULT 0 AFTER daysleft"); + } + + # size and state on bonus features + unless (column_type("paidexp", "size")) { + do_alter("paidexp", + "ALTER TABLE paidexp ADD size INT unsigned NOT NULL DEFAULT 0 AFTER item"); + } + + # add dates to fotobilder feedback + unless (column_type("fotobilder_feedback", "datetime")) { + do_alter("fotobilder_feedback", + "ALTER TABLE fotobilder_feedback ADD datetime DATETIME NOT NULL AFTER state"); + } + + unless (column_type("phonepostentry", "location")) { + do_alter("phonepostentry", + "ALTER TABLE phonepostentry ADD COLUMN location ENUM('blob','mogile','none') DEFAULT NULL"); + } + + unless (column_type("phonepostentry", "location") =~ /none/) { + do_alter("phonepostentry", + "ALTER TABLE phonepostentry MODIFY COLUMN location ENUM('blob','mogile','none') DEFAULT NULL"); + } + + unless (column_type("abuse_mail", "type")) { + do_alter("abuse_mail", + "ALTER TABLE abuse_mail ADD COLUMN type VARCHAR(20) NOT NULL DEFAULT ''"); + + do_alter("abuse_mail", + "UPDATE abuse_mail SET type='abuse'"); + } +}); + +1; # true diff --git a/ljcom/bin/upgrading/zh.dat b/ljcom/bin/upgrading/zh.dat new file mode 100644 index 0000000..2bd1176 --- /dev/null +++ b/ljcom/bin/upgrading/zh.dat @@ -0,0 +1,1376 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=如果你想è¦åˆ é™¤æˆ–ä¿ç•™ä½ çš„日记,你就æ¥å¯¹åœ°æ–¹äº†ã€‚ 一旦你决定删除你的日记,万一你改å˜ä¸»æ„,你有30天的时间决定ä¿ç•™å®ƒã€‚过了这30天,你的日记就会被永久删除。被永久删除的日记是没有办法ä¿ç•™çš„。 + +/accountstatus.bml.journalstatus.head=æ—¥è®°æ¿€æ´»çŠ¶æ€ + +/accountstatus.bml.journalstatus.select.activated=已激活 + +/accountstatus.bml.journalstatus.select.deleted=已删除 + +/accountstatus.bml.journalstatus.select.head=状æ€: + +/accountstatus.bml.journalstatus.select.suspended=已挂起 + +/accountstatus.bml.title=å¸æˆ·çŠ¶æ€ + +/allpics.bml.current=现在使用的图片 + +/allpics.bml.default=默认 + +/allpics.bml.edit2=也许你想编辑你的图片的关键字或者上传一张新的图片. + +/allpics.bml.error.noparam=你需è¦æŒ‡å®šä¸€ä¸ªç”¨æˆ·å‚æ•°. + +/allpics.bml.keywords=关键字: + +/allpics.bml.nopics.text.other=这个用户还没有上载任何用户图片. + +/allpics.bml.nopics.text2=你没有上传任何图片. è¦ä¸Šä¼ å›¾ç‰‡, 点击这里. + +/allpics.bml.nopics.title=没有图片 + +/allpics.bml.pics=这里是[[user]]的用户图片. + +/allpics.bml.title=用户图片 + +/approve.bml.comm.success=æˆåŠŸ + +/approve.bml.comm.text<< +ä½ å·²ç»è¢«åŠ å…¥åˆ°[[comm]]. +点击这里把这个群组加入到你的朋å‹åˆ—表. +. + +/approve.bml.error.actionperformed=这个动作已ç»æ‰§è¡Œ + +/approve.bml.error.internerr.invalidaction=内部错误: 无效的动作 + +/approve.bml.error.invalidargument=给了无效的å‚æ•° + +/approve.bml.error.unknownactiontype=未知的动作类型 + +/approve.bml.shared.success=æˆåŠŸ + +/approve.bml.title=批准动作 + +/changepassword.bml.btn.proceed=继续 + +/changepassword.bml.changepassword.header=修改å£ä»¤ + +/changepassword.bml.email.subject=å£ä»¤çš„修改 + +/changepassword.bml.error.badcheck=åçš„æ–°å£ä»¤: [[error]] + +/changepassword.bml.error.badoldpassword=你的旧密ç ä¸æ­£ç¡®ã€‚ + +/changepassword.bml.error.blankpassword=你的新密ç ä¸èƒ½ä¸ºç©ºã€‚ + +/changepassword.bml.error.changetestaccount=ä¸èƒ½ä¿®æ”¹æµ‹è¯•å¸å·çš„密ç ã€‚ + +/changepassword.bml.error.characterlimit=密ç æœ€é•¿ä¸º30个字符。 + +/changepassword.bml.error.invaliduser=éžæ³•ç”¨æˆ· [[user]]。这个用户ä¸å­˜åœ¨ã€‚你确信你输入正确了å—? + +/changepassword.bml.error.mustenterusername=你必须输入你的用户å。 + +/changepassword.bml.error.nonascii=密ç å¿…须是 ASCII 符å·ã€‚请选择一个ä¸åŒ…å«éž ASCII 符å·çš„密ç ã€‚ + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=如果你现在的电å­é‚®ä»¶åœ°å€æ²¡æœ‰è¢«ç¡®è®¤ï¼Œé‚£ä¹ˆä½ å°±ä¸èƒ½ä¿®æ”¹å¯†ç ã€‚ + +/changepassword.bml.newpassword=新密ç ï¼š + +/changepassword.bml.newpasswordagain=新密ç ï¼ˆå†è¾“入一é): + +/changepassword.bml.oldpassword=æ—§å£ä»¤: + +/changepassword.bml.proceed.instructions=点击下é¢çš„按钮修改你的å£ä»¤. 你也会收到一å°ç”µå­é‚®ä»¶, æ醒你这次å£ä»¤çš„修改. + +/changepassword.bml.success.text=ä½ çš„å£ä»¤å·²ç»è¢«ä¿®æ”¹, 并且包å«ä¸€ä¸ªæ醒消æ¯çš„电å­é‚®ä»¶å·²ç»å‘é€ç»™ä½ . + +/changepassword.bml.title=修改å£ä»¤ + +/community/index.bml.title=群组中心 + +/community/join.bml.button.join=å‚加群组 + +/community/join.bml.label.addtofriends=把[[maintainer]]加在朋å‹åˆ— + +/community/join.bml.label.allowposting=这个群组å…许所有æˆå‘˜å‘帖, 所以你现在就å¯ä»¥åœ¨å…¶ä¸­å‘布新的æ¡ç›®. 如果你在你的计算机上已ç»è¿è¡Œäº†ä¸€ä¸ª LiveJournal 的客户端程åº, 那么你è¦å…ˆç™»å‡ºç„¶åŽå†ç™»å…¥, 使得这个日记显示在你å¯ä»¥å‘帖的日记列表中. + +/community/join.bml.label.banned=管ç†è€…ç¦æ­¢ä½ å‚加此群组 + +/community/join.bml.label.commlogged=ä½ å·²ç»ä»¥ä¸€ä¸ªå…±äº«/群组å¸å·, 而ä¸æ˜¯ä½ ä¸ªäººçš„å¸å·ç™»å½•. + +/community/join.bml.label.errorcomminfo=指定的群组信æ¯æ˜¯éžæ³•çš„. + +/community/join.bml.label.loginfirst=è¦åŠ å…¥ä¸€ä¸ªç¾¤ç»„, 你必须首先登录. + +/community/join.bml.label.sure=你肯定å—? + +/community/join.bml.success=æˆåŠŸ + +/community/join.bml.title=å‚加群组 + +/community/leave.bml.button.leave=离开群组 + +/community/leave.bml.label.buttontoleave=请按下é¢çš„钮在"[[commname]]"加上你的评注 + +/community/leave.bml.label.infoerror=指定的群组信æ¯æ˜¯éžæ³•çš„. + +/community/leave.bml.label.logoutfirst=è¦ç¦»å¼€ç¤¾åŒº, 你必须首先登录. + +/community/leave.bml.label.removed=你现已从[[commname]] 群组除å。 + +/community/leave.bml.success=æˆåŠŸ + +/community/leave.bml.sure=你肯定å—? + +/community/leave.bml.title=离开群组 + +/community/manage.bml.commlist.actinfo=资料 + +/community/manage.bml.commlist.actions=行动 + +/community/manage.bml.commlist.actmembers=[会员] + +/community/manage.bml.commlist.actmembers2=会员 + +/community/manage.bml.commlist.actsettings=[设定] + +/community/manage.bml.commlist.actsettings2=设定 + +/community/manage.bml.commlist.header=您的群组 + +/community/manage.bml.commlist.username=用户å称 + +/community/manage.bml.title=ç¾¤ç»„ç®¡ç† + +/community/members.bml.error.nouser=没有这个用户[[用户]] + +/community/members.bml.key.member=会员 + +/community/members.bml.manage2=管ç†ç¾¤ç»„ + +/community/members.bml.nextlink=(下一页...) + +/community/members.bml.prevlink=(å‰ä¸€é¡µ...) + +/community/members.bml.settings=[设定] + +/community/members.bml.success.header=æˆåŠŸ + +/community/members.bml.success.return=回到一览表 + +/community/members.bml.title=群体会员 + +/community/members.bml.update=更新设置 + +/community/moderate.bml.brlist.subject=题目开始 + +/community/moderate.bml.brlist.time=时间 + +/community/moderate.bml.brlist.view=观看 + +/community/moderate.bml.choice.approve=åŒæ„ + +/community/moderate.bml.choice.reject=ä¸åŒæ„ + +/community/moderate.bml.error.nolist=你没有维æŒä»»ä½•ç¤¾ç¾¤. + +/community/moderate.bml.modlist.actions=行动 + +/community/moderate.bml.modlist.actmodempty=[中等] + +/community/moderate.bml.modlist.actmoderate=中等 + +/community/moderate.bml.modlist.title=题目 + +/community/moderate.bml.modlist.username=用户å称 + +/community/moderate.bml.posted.header=æˆåŠŸ + +/community/moderate.bml.reject.button=是的,拒ç»å®ƒ + +/community/moderate.bml.reject.header=æ‹’ç»è¿™ç¯‡æ—¥è®°å—? + +/community/moderate.bml.reject.text=你确定你è¦åˆ é™¤è¿™ç¯‡æ—¥è®°å—? + +/community/moderate.bml.rejected.header=已删除 + +/community/moderate.bml.rejected.text=这篇日记已被删除 + +/community/search.bml.button.clear=清除表格 + +/community/search.bml.button.search=æœç´¢ï¼ + +/community/search.bml.checkbox.onlywithpics=åªæœ‰æœ‰å›¾è±¡çš„群组 + +/community/search.bml.label.byinterest=按照嗜好 + +/community/search.bml.label.bylocation=用地点 + +/community/search.bml.label.bytime=用更新日记的时间 + +/community/search.bml.label.city=城市: + +/community/search.bml.label.country=国家 + +/community/search.bml.label.displayoptions=显示选项 + +/community/search.bml.label.hasmember=有会员 + +/community/search.bml.label.othercriteria=其他è¦æ±‚ + +/community/search.bml.label.outputformat=è¾“å‡ºæ ¼å¼ + +/community/search.bml.label.records=æ¯é¡µçš„记录 + +/community/search.bml.label.searchcomm=æœç´¢ç¾¤ç»„ + +/community/search.bml.label.sortmethod=排练方法 + +/community/search.bml.label.stateprovince=å·ž/çœ + +/community/search.bml.label.updated=上一次更新 + +/community/search.bml.sel.bypicture=æŒ‰ç…§å›¾åƒ + +/community/search.bml.sel.communityname=群组å + +/community/search.bml.sel.commview=群体外观 + +/community/search.bml.sel.day=æ—¥ + +/community/search.bml.sel.month=月 + +/community/search.bml.sel.simple=ç®€å• + +/community/search.bml.sel.updatetime=更新时间 + +/community/search.bml.sel.username=用户å + +/community/search.bml.sel.week=周 + +/community/search.bml.title=群组检索 + +/community/settings.bml.button.changecommunity=更新设置 + +/community/settings.bml.button.createcommunity=开设群体 + +/community/settings.bml.label.commchanged=你的群组设置已被更新。 + +/community/settings.bml.label.commcreate=这使你è¦æˆä¸ºç¾¤ä½“çš„å¸æˆ·. è¿™å¸æˆ·åº”该已被开设, å¯æ˜¯ä¸åº”该在使用中, 因为以åŽä¼šæœ‰å¾ˆå¤šä¸åŒçš„人都能在里é¢ç¼–写. + +/community/settings.bml.label.commcreated=你的群体已ç»è®¾ç½®å®Œäº† + +/community/settings.bml.label.commheader=群体å¸æˆ· + +/community/settings.bml.label.comminfo=群体资料 + +/community/settings.bml.label.commopts=群体选项 + +/community/settings.bml.label.commsite=群体网站 + +/community/settings.bml.label.createheader=开设群体 + +/community/settings.bml.label.maintainer=负责人 + +/community/settings.bml.label.password=密ç ï¼š + +/community/settings.bml.label.rellinks=相关网页 + +/community/settings.bml.label.username=用户å称 + +/community/settings.bml.success=æˆåŠŸ + +/create.bml.age.check.question=你的年纪在13å²ä»¥ä¸‹å—? + +/create.bml.age.check.yes=是, 我的年纪在13å²ä»¥ä¸‹ + +/create.bml.age.check2.question=你的年龄超过13å²å—? + +/create.bml.age.check2.yes=是的,我已ç»æ»¡13å²ã€‚ + +/create.bml.age.head=年龄 + +/create.bml.btn.proceed=继续... + +/create.bml.clusterselect.cluster=ç°‡: + +/create.bml.clusterselect.clusternum=ç°‡ [[number]] + +/create.bml.clusterselect.head=选择簇 + +/create.bml.clusterselect.nocluster=没有簇 + +/create.bml.create.head=建立一个新的日记 + +/create.bml.create.text=开设新日记éžå¸¸å®¹æ˜“, åªè¦è·Ÿç€æŒ‡ç¤ºåšå°±è¡Œ! + +/create.bml.email.head=ä½ çš„ç”µé‚®åœ°å€ + +/create.bml.email.input.head=ç”µé‚®åœ°å€ + +/create.bml.error.coppa.under13=对ä¸èµ·ï¼Œç”±äºŽå„¿ç«¥çº¿ä¸Šéšç§ä¿æŠ¤æ³•æ¡ˆçš„é™åˆ¶ï¼Œè¦ä½¿ç”¨LiveJournalçš„æœåŠ¡ä½ å¿…须是å三å²ä»¥ä¸Šã€‚请在你å三å²ç”Ÿæ—¥ä»¥åŽå†æ¥å§ã€‚ + +/create.bml.error.email.blank=ä½ å¿…é¡»è¾“å…¥ä½ çš„ç”µé‚®åœ°å€ + +/create.bml.error.password.blank=你一定è¦è¾“å…¥å¯†ç  + +/create.bml.error.password.nomatch=密ç ä¸ç¬¦ + +/create.bml.error.username.inuse=这个å¸æˆ·å·²ç»æœ‰äººä½¿ç”¨; 请选择别的å¸æˆ·å称 + +/create.bml.error.username.iscode=用户å好象是邀请密ç , ä¸æ˜¯ç”¨æˆ·å + +/create.bml.error.username.mustenter=你必须输入一个用户å + +/create.bml.error.username.reserved=对ä¸èµ·, 这个å¸æˆ·å称已被订 + +/create.bml.name.head=ä½ çš„åå­— + +/create.bml.name.input.head=åå­— + +/create.bml.name.text=ä½ çš„å字或爱称是什么? 这个å字会在你的日记上方, 还有用户检索中出现. ä½ ä¸é¡»è¦ç”¨ä½ çš„å…¨å甚至你的真å + +/create.bml.password.head=å¯†ç  + +/create.bml.password.input.head1=密ç : + +/create.bml.password.input.head2=é‡æ–°è¾“入密ç ï¼š + +/create.bml.password.text=é€‰æ‹©å¯†ç  + +/create.bml.proceed.btn.proceed=继续... + +/create.bml.proceed.warning=åªè¦æŒ‰ç»§ç»­ä¸€æ¬¡!! + +/create.bml.success.btn.enterinfo=输入个人资料 + +/create.bml.success.head=æˆåŠŸ! + +/create.bml.success.text2=ä½ çš„LiveJournal会在 + +/create.bml.success.text3=现在请你花时间输入一些你的资料。虽然大部分并ä¸æ˜¯å¿…è¦çš„,ä¸è¿‡æˆ‘们想知é“是什么样的人在用LiveJournal。 + +/create.bml.title=开设新日记 + +/create.bml.tos.error=在创建一个å¸å·ä¹‹å‰ä½ å¿…须阅读和åŒæ„æœåŠ¡æ¡æ¬¾ã€‚ + +/create.bml.tos.haveread=我已ç»é˜…读和åŒæ„这个æœåŠ¡æ¡æ¬¾ã€‚ + +/create.bml.tos.heading=æœåŠ¡æ¡æ¬¾ + +/create.bml.tos.p1.2=在继续之å‰ä½ å¿…须阅读和åŒæ„这个æœåŠ¡æ¡æ¬¾ã€‚ + +/create.bml.useacctcodes.entercode=è¦åˆ›å»ºä¸€ä¸ªæ–°çš„å¸æˆ·ï¼Œè¯·è¾“入一个å¸æˆ·åˆ›å»ºä»£ç ã€‚更多信æ¯å‚è§æˆ‘怎样创建一个å¸æˆ·ï¼Ÿ + +/create.bml.useacctcodes.welcome=欢迎 + +/create.bml.username.box.head=å¸æˆ·å称: + +/create.bml.username.forpaidaccts=或者, 给收费å¸æˆ·ä»¬ + +/create.bml.username.head=å¸æˆ·å称 + +/create.bml.username.ljaddress=你的日记会在这些地å€: + +/create.bml.username.username=å¸æˆ·å称 + +/developer/index.bml.title=å¼€å‘者资料 + +/directory.bml.search.title=正在æœç´¢ + +/doc/index.bml.about=欢迎访问LiveJournal的文档库,在这里你å¯ä»¥æ‰¾åˆ°å…³äºŽLiveJournalæœåŠ¡æˆ–者æœåŠ¡å™¨è½¯ä»¶çš„大多数主题的信æ¯ã€‚请从下é¢é€‰æ‹©ä¸€ä¸ªä¸»é¢˜ï¼š + +/doc/index.bml.about.header=欢迎 + +/doc/index.bml.docs.faq.about=关于 LiveJournal.com 的常è§é—®é¢˜ + +/doc/index.bml.docs.faq.title=常è§é—®é¢˜ + +/doc/index.bml.docs.header=文档 + +/doc/index.bml.volunteering.header=义务æœåŠ¡ + +/doc/tour/index.bml.clients.title=客户 + +/doc/tour/index.bml.comms.title=社群 + +/doc/tour/index.bml.friends.title=æœ‹å‹ + +/doc/tour/index.bml.intro.title=欢迎 + +/doc/tour/index.bml.modify.title=ç§äººåŒ– + +/doc/tour/index.bml.profile.title=用户资料 + +/doc/tour/index.bml.sitemap.title=网站地图 + +/doc/tour/index.bml.support.title=寻求帮助 + +/editinfo.bml.allowshowcontact.email.lj_only=åªæœ‰LiveJournalçš„åœ°å€ + +/editinfo.bml.allowshowcontact.email.neither=都ä¸è¦. ä¸è¦å…¬å¼€ä»»ä½•ç”µé‚®åœ°å€ + +/editinfo.bml.allowshowcontact.email.no_show=ä¸è¦å…¬å¼€ç”µé‚®åœ°å€ + +/editinfo.bml.allowshowcontact.email.show=å…¬å¼€ç”µé‚®åœ°å€ + +/editinfo.bml.allowshowcontact.title=在LiveJourna上公开你的è”系资料å—?l + +/editinfo.bml.allowshowinfo.about=如果你希望公开你的城市/国家, 请选这个选项 + +/editinfo.bml.allowshowinfo.title=公开地点和生日? + +/editinfo.bml.autotranslate.header=自动转æ¢ä»Žå‰çš„æ¡ç›®: + +/editinfo.bml.bday.title=生日 + +/editinfo.bml.bdayreminders.about=如果你想收到æ醒你朋å‹ç”Ÿæ—¥çš„邮件,请点击这个方格 + +/editinfo.bml.bdayreminders.header=寄给我生日æ醒的邮件 (现在ç¦æ­¢) + +/editinfo.bml.bio.about=在这里你å¯ä»¥è¾“入一个关于你个人的迷你自传,它将会出现在你的用户资料页é¢ä¸Šã€‚ + +/editinfo.bml.bio.header=关于你 + +/editinfo.bml.chat.aolim.title=“美国线上â€ç®€è®¯èµ„æ–™ + +/editinfo.bml.chat.icquin.title=ICQå·ç ï¼š + +/editinfo.bml.chat.msnusername.title=微软简讯资料 + +/editinfo.bml.chat.yahooid.title=雅虎简讯资料 + +/editinfo.bml.city.title=城市 + +/editinfo.bml.country.choose=选择一个国家 + +/editinfo.bml.country.title=国家 + +/editinfo.bml.donotlog=ä¸ + +/editinfo.bml.enableboards.header=å¼€å¯è®¨è®ºæ¿ + +/editinfo.bml.error.email.none=ä½ å¿…é¡»å¡«å†™ä½ çš„ç”µé‚®åœ°å€ + +/editinfo.bml.error.noname=你必须公开你的å字。至少è¦å…¬å¼€ä½ çš„å°å。 + +/editinfo.bml.finished.header=完æˆäº†? + +/editinfo.bml.finished.save_button=存档 + +/editinfo.bml.gender.title=性别 + +/editinfo.bml.howhear.about<< +我们åªæ˜¯å¥½å¥‡,你是从哪儿å¬è¯´[[sitename]]的事情? +如果是一个人,请告诉我们他/她的用户å. 如果是从其他的æ¥æº/连结/网站,请填写åˆé€‚的资料. +. + +/editinfo.bml.howhear.header=好奇心 + +/editinfo.bml.htmlemail.header=寄HTML电邮 + +/editinfo.bml.int.ex.good=GOOD 比如: 骑车, 滑雪, 电脑, DVD, MP3, 奶酪, 女人 + +/editinfo.bml.int.header=兴趣 + +/editinfo.bml.login.enterinfo=è¦å˜æ›´ä½ çš„个人资料, 请输入你的用户åå’Œå¯†ç  + +/editinfo.bml.login.forgot.header=忘记了什么? + +/editinfo.bml.login.forgot.recover=如果你忘了你的用户å或密ç , 在这里找回æ¥! + +/editinfo.bml.logip.always=常常 + +/editinfo.bml.logip.anon_only=åªæœ‰åŒ¿å者 + +/editinfo.bml.logip.header=è¦è®°å½•å›žå¤è€…çš„IP地å€å—? + +/editinfo.bml.name.title=å + +/editinfo.bml.newemail.subject=已更æ¢ä½ çš„ç”µé‚®åœ°å€ + +/editinfo.bml.optional=å¯å¡«ä¹Ÿå¯ä¸å¡« + +/editinfo.bml.opt_in.header=寄给我LiveJournalçš„æœ€æ–°æ¶ˆæ¯ + +/editinfo.bml.persinfo.disclaimer=填入一些关于你的简略资料,满足我们的好奇心和统计的目的。我们并ä¸ä¼šä½¿ç”¨è¿™äº›èµ„æ–™åšä»»ä½•çŠ¯ç½ªçš„或惹人讨厌的事,我们åªè¦çŸ¥é“我们的用户是è°ï¼Œä½åœ¨å“ªå„¿ã€‚请务必正确地填写。如果你有点担心,请å‚阅我们的ç§éšæ”¿ç­–。 + +/editinfo.bml.persinfo.header=个人资料 + +/editinfo.bml.screen.all=全部 + +/editinfo.bml.screen.anon=æ— åæ° + +/editinfo.bml.screen.none=æ—  + +/editinfo.bml.security.header=è°å¯ä»¥æŸ¥çœ‹ä½ çš„è”系信æ¯ï¼Ÿ + +/editinfo.bml.security.visibility.anybody=任何人 + +/editinfo.bml.security.visibility.everybody=所有人 + +/editinfo.bml.security.visibility.friends=æœ‹å‹ + +/editinfo.bml.security.visibility.regusers=注册用户 + +/editinfo.bml.settings.header=LiveJournal选项 + +/editinfo.bml.state.us=美国州 + +/editinfo.bml.success.header=æˆåŠŸï¼ + +/editinfo.bml.title=编辑个人资料 + +/editinfo.bml.tm.sec.title=安全级别: + +/editinfo.bml.userpic.header=ä½ çš„å›¾åƒ + +/editinfo.bml.webpagename.title=网页å称 + +/editinfo.bml.webpageurl.title=网页ä½ç½® + +/editinfo.bml.zip.title=ZIP å·ç  + +/editinfo.bml.zip.usonly=5个数字的ZIPå·ç ï¼Œåªé™ç¾Žå›½å±…æ°‘ + +/editjournal_do.bml.btn.edit=修改所选择的日记 + +/editjournal_do.bml.currmusic=çŽ°åœ¨çš„éŸ³ä¹ + +/editjournal_do.bml.date=日期 + +/editjournal_do.bml.default=预设 + +/editjournal_do.bml.delete.confirm=你确定你è¦åˆ é™¤è¿™ç¯‡æ—¥è®°å—? + +/editjournal_do.bml.error.nofind=找ä¸åˆ°æ‰€é€‰æ‹©çš„日记. + +/editjournal_do.bml.event=活动: + +/editjournal_do.bml.localtime=国内时间 + +/editjournal_do.bml.noneother=æ— , 或其他: + +/editjournal_do.bml.opt.nocomments=ä¸å‡†è®¸ä»–人评论 + +/editjournal_do.bml.other=其他: + +/editjournal_do.bml.success.delete=日记æ¡ç›®è¢«åˆ é™¤. + +/editjournal_do.bml.timeformat=24å°æ—¶åˆ¶ + +/export.bml.label.field.itemid=ID å·ç  + +/export.bml.label.field.security=安全程度 + +/export.bml.label.field.subject=题目 + +/export.bml.label.header=标题 + +/export.bml.label.month=选择月份 + +/export.bml.label.month.month=月月 + +/export.bml.label.month.year=å¹´å¹´å¹´å¹´ + +/friends/add.bml.add.header=æˆåŠŸ + +/friends/add.bml.add.title=朋å‹å·²ç»åŠ äº†! + +/friends/add.bml.btn.modify=更改 + +/friends/add.bml.btn.remove=删除 + +/friends/add.bml.colors.bg=背景 + +/friends/add.bml.colors.fg=å‰æ™¯ + +/friends/add.bml.colors.header=颜色 + +/friends/add.bml.confirm.header=加[[user]]为朋å‹? + +/friends/add.bml.confirm.title=åŠ å…¥æœ‹å‹ + +/friends/add.bml.error1.header=首先登录 + +/friends/add.bml.error1.title=åŠ å…¥æœ‹å‹ + +/friends/add.bml.remove.header=æˆåŠŸ + +/friends/editgroups.bml.btn.ge.del=删除 + +/friends/editgroups.bml.btn.ge.new=æ–° + +/friends/editgroups.bml.btn.gs.private=ç§äºº + +/friends/editgroups.bml.btn.gs.public=公共 + +/friends/editgroups.bml.btn.mv.down=往下移动 + +/friends/editgroups.bml.btn.mv.up=往上移动 + +/friends/editgroups.bml.done.header=åšå¥½äº†å—? + +/friends/editgroups.bml.group.public=(公共〔 + +/friends/editgroups.bml.saved.header=已存入 + +/friends/edit_do.bml.done.head=完æˆ? + +/friends/edit_do.bml.friend=æœ‹å‹ + +/friends/edit_do.bml.name=姓å + +/friends/edit_do.bml.textcolor=字体颜色 + +/friends/edit_do.bml.user=用户 + +/friends/edit_do.bml.yourfriends.head=ä½ çš„æœ‹å‹ + +/friends/filter.bml.reset=清除 + +/friends/index.bml.title=朋å‹åˆ—表工具 + +/friends/popwithfriends.bml.account_type=对ä¸èµ·ï¼Œä½ çš„å¸æˆ·ç±»åž‹ä¸å…许你使用这个工具。 + +/index.bml.about.header=关于LiveJournal + +/index.bml.about.joining=加入这个站点是å…费的,用户为了获得é¢å¤–的功能å¯ä»¥é€‰æ‹©å‡çº§ä»–们的å¸æˆ·ã€‚ + +/index.bml.about.us=LiveJournal是一个易用(但å分强大并且å¯å®šåˆ¶ï¼‰çš„个人出版(“åšå®¢â€ï¼‰å·¥å…·ï¼Œå®ƒå»ºç«‹åœ¨å¼€æ”¾æºä»£ç è½¯ä»¶ä¹‹ä¸Šã€‚ + +/index.bml.boldcreate=建立你自己的 LiveJournalï¼ + +/index.bml.frank.image.alt=弗兰克,这是LiveJournalçš„å‰ç¥¥å±±ç¾Šã€‚ + +/index.bml.frank.logo=“咩~~â€ï¼Œå¼—å…°å…‹å«é“。 + +/index.bml.learnmore.header=想了解更多? + +/index.bml.learnmore.text=请阅读我们的功能概è¦ã€‚确信了å—?创建你自己的LiveJournalï¼ + +/index.bml.meta.desc=LiveJournal.com是一个你å¯ä»¥è·Ÿæ•´ä¸ªä¸–界分享你的想法的地方。 + +/index.bml.meta.keywords=日记,在线日记,散文,网络日记 + +/index.bml.news.text=最近的站点新闻: + +/index.bml.news.title=最近新闻 + +/index.bml.post=实时å‘布统计 + +/index.bml.post.hour=æ¯å°æ—¶ï¼š + +/index.bml.post.latest=最近的张贴 + +/index.bml.post.min=æ¯åˆ†é’Ÿï¼š + +/interests.bml.add.added.head=已加上了! + +/interests.bml.add.added.text=这个兴趣被加入了你的列表 + +/interests.bml.add.btn.text=加上[[interest]] + +/interests.bml.add.confirm.head=确认 + +/interests.bml.add.confirm.text=把[[interest]]添加为一个兴趣,点击下é¢çš„按钮。 + +/interests.bml.add.toomany.head=对ä¸èµ·... + +/interests.bml.add.toomany.text=ä½ å·²ç»å®šä¹‰äº†[[maxinterests]]个兴趣。 + +/interests.bml.btn.switch=è½¬æ¢ + +/interests.bml.communities.head=相关群组 + +/interests.bml.count=æ•°ç›® + +/interests.bml.enmasse.btn=显示åå• + +/interests.bml.enmasse.header=加/å‡å…´è¶£ + +/interests.bml.findsim_do.account.notallowed=对ä¸èµ·ï¼Œä½ çš„å¸æˆ·ç±»åž‹ä¸èƒ½è®©ä½ ä½¿ç”¨è¿™ä¸ªå·¥å…·ã€‚ + +/interests.bml.interest=兴趣 + +/interests.bml.interested.btn.find=寻找 + +/interests.bml.interests.head=兴趣 + +/interests.bml.popular.head=常è§å…´è¶£ + +/interests.bml.title=兴趣 + +/interests.bml.users.head=有兴趣的用户 + +/interests.bml.users.text=这些用户对[[interest]]感兴趣。 + +/legal/coppa.bml.title=儿童线上éšç§ä¿æŠ¤æ³•æ¡ˆ + +/legal/index.bml.docs.header=文件 + +/legal/index.bml.title=æ³•å¾‹ä¿¡æ¯ + +/legal/privacy.bml.title=éšç§æ”¿ç­– + +/legal/tos.bml.title=æœåŠ¡æ¡æ¬¾ + +/login.bml.bindip.label=绑定到IP地å€ï¼š + +/login.bml.bindip.no=ä¸ï¼ˆå·¥ä½œåœ¨æ‰€æœ‰çš„ISP) + +/login.bml.bindip.yes=是的(更安全) + +/login.bml.error.mustenterusername=你必须输入用户å。 + +/login.bml.expire.btn.neverexpire=改å˜è¶…时模å¼åˆ°â€œä»Žä¸â€ + +/login.bml.expire.btn.sessiononly=改å˜è¶…时模å¼åˆ°â€œè¿™ä¸ªå¯¹è¯â€ + +/login.bml.links.head=连结 + +/login.bml.links.link2=ä½ çš„ 任务列表。 + +/login.bml.links.text=å°†æ¥è¿™ä¸€é¡µä¸Šä¼šæœ‰å„ç§å„样的链接和相关信æ¯ï¼Œä½†æ˜¯çŽ°åœ¨è¿™é‡Œåªæœ‰ä¸€äº›ä½ å¯èƒ½æƒ³åŽ»çš„地方: + +/login.bml.loggedin.head=登录完æˆ! + +/login.bml.loggedin.text=你已被系统登录了 + +/login.bml.login.btn.changeopts=改å˜é€‰é¡¹ + +/login.bml.login.btn.login=登录... + +/login.bml.login.expiration=期满失效: + +/login.bml.login.forget=忘记了? + +/login.bml.login.head=登录 + +/login.bml.login.never=æ°¸è¿œä¸ + +/login.bml.login.otheropts=其他选项: + +/login.bml.login.password=密ç : + +/login.bml.login.text2=你也å¯ä»¥æŒ‡å®šä»€ä¹ˆæ—¶é—´ä½ çš„登录超时。默认你的登录会在你关闭æµè§ˆå™¨æ—¶å¤±æ•ˆï¼Œè¿™åœ¨å…¬å…±çš„计算机上是很好的。但是,如果你是你的计算机的唯一用户,并且没有其他人能够使用它,你å¯ä»¥é€‰æ‹©æ°¸ä¹…ä¿æŒç™»å½•ã€‚关于这一点和其他选项的更多信æ¯ï¼Œå‚è§æˆ‘登录时的选项有哪些? + +/login.bml.login.username=用户å: + +/login.bml.login.whenbrowsercloses=当æµè§ˆå™¨å…³é—­æ—¶ + +/login.bml.logout.btn=退出 + +/login.bml.title=登录 + +/login.bml.whylogin.benefit1=ä½ å°†æ¥åœ¨è¿™ä¸ªç«™ç‚¹ä¸Šçš„任何地方都ä¸å†éœ€è¦è¾“入你的用户å/密ç ã€‚ + +/login.bml.whylogin.benefit2=如果你的朋å‹ç»™ä½ æƒåŠ›ï¼Œé‚£ä¹ˆä½ å°†èƒ½å¤ŸæŸ¥çœ‹é‚£äº›è¢«ä»–们“ä¿æŠ¤â€çš„日记æ¡ç›®ã€‚ + +/login.bml.whylogin.benefit3=许多特性åªæœ‰åœ¨ä½ ç™»å½•ä¹‹åŽæ‰èƒ½çœ‹è§å’Œä½¿ç”¨ã€‚ + +/login.bml.whylogin.head=为什么登录? + +/login.bml.whylogin.text=这里是登录的一些主è¦çš„好处: + +/logout.bml.already.head=已退出 + +/logout.bml.already.text=ä½ å·²ç»é€€å‡º + +/logout.bml.loggedout.already=已退出. + +/logout.bml.loggedout.head=已退出 + +/logout.bml.loggedout.success=已退出. + +/logout.bml.loggedout.text=你现在已退出. + +/logout.bml.logout.btn=退出 + +/logout.bml.logout.head=退出å—? + +/logout.bml.title=退出 + +/lostinfo.bml.btn.proceed=继续 + +/modify_do.bml.pagelayoutstyle.warning=ä½ çš„å¸æˆ·ç±»åž‹åªå…许你在少数几个默认风格之间选择。 + +/modify_do.bml.success.head=æˆåŠŸ + +/multisearch.bml.region.head=按地区æœç´¢ + +/paidaccounts/index.bml.costs.header=那么, 到底è¦å¤šå°‘钱呢? + +/paidaccounts/index.bml.costs.rates.amount.header=æ•°ç›®(美金): + +/paidaccounts/index.bml.costs.rates.time.header=时间 + +/press/staff.bml.ryanfitz.title=付费æœåŠ¡ + +/press/staff.bml.title=高级èŒå‘˜ + +/press/staff.bml.whitaker.quip=接下æ¥è¯¥æ€Žä¹ˆåŠžå‘¢? + +/site/goat.bml.image.alt=弗兰克,LiveJournalçš„å‰ç¥¥å±±ç¾Šã€‚ + +/site/goat.bml.image.caption="" + +/site/goat.bml.meet.body=这是弗兰克。弗兰克是LiveJournalçš„å‰ç¥¥ç‰©ã€‚当我们è½åŽçš„时候他会éšä¾¿å¸®æˆ‘们编编程åºï¼Œå¶å°”回答几个技术支æŒè¯·æ±‚。弗兰克真的éžå¸¸å¤šæ‰å¤šè‰ºâ€¦â€¦ä»–甚至有时åšä¸€äº›é™¢å­é‡Œçš„活计。当è‰åªè¿‡åº¦ç”Ÿé•¿çš„时候,我们过去说一声,“嘿,弗兰克ï¼åˆé¥­æ—¶é—´åˆ°äº†â€¦â€¦åŽ»åƒè‰å§ï¼â€ã€‚这真是一个åŒèµ¢çš„情况。 + +/site/goat.bml.meet.header=和弗兰克è§é¢ + +/site/goat.bml.title=å¼—å…°å…‹è¿™åªç¾Š + +/suggestions/index.bml.howto.title=我该怎么å‘Livejournalæ出我的æ„è§å‘¢ï¼Ÿ + +/suggestions/index.bml.info.title=其他资料 + +/suggestions/index.bml.welcome.title=æ¬¢è¿Žå…‰ä¸´ï¼ + +/support/faqbrowse.bml.backfaq=返回 常è§é—®é¢˜ã€‚ + +/support/faqbrowse.bml.backsupport=返回 技术支æŒåŒºã€‚ + +/support/faqbrowse.bml.lastupdated=上一次更新 + +/talkpost.bml.allowedhtml=å…许用HTML + +/talkpost.bml.error.cannotreplynopost=ä½ ä¸èƒ½ç»™ä¸å­˜åœ¨çš„æ¡ç›®å›žå¤ + +/talkpost.bml.error.nocommentsjournal=用户ä¸æŽ¥å—评注 + +/talkpost.bml.error.nocommentspost=用户的这个æ¡ç›®ä¸æŽ¥å—评注 + +/talkpost.bml.error.noreplypost=找ä¸åˆ°ç»™æ¡ç›®çš„回å¤(已删除?) + +/talkpost.bml.loganonip=注æ„!此用户选择了把匿å者的IP地å€å­˜æ¡£ + +/talkpost.bml.logyourip=注æ„!此用户选择了把所有用户的IP地å€å­˜æ¡£ + +/talkpost.bml.nosubjecthtml=在题目里ä¸å…许用HTML + +/talkpost.bml.opt.anonymous=匿å者 + +/talkpost.bml.opt.defpic=(默认) + +/talkpost.bml.opt.friendsonly=此用户ä¸æŽ¥å—匿å者或ä¸æ˜¯æœ‹å‹çš„回å¤. 如果你在[[username]]的朋å‹åˆ—上你å¯ä»¥å†™ä½ çš„å›žå¤ + +/talkpost.bml.opt.from=从 + +/talkpost.bml.opt.ljuser=LiveJournal 用户: + +/talkpost.bml.opt.loggedin=注册的用户: [[username]] + +/talkpost.bml.opt.message=ä¿¡æ¯: + +/talkpost.bml.opt.noanonpost=此用户ä¸æŽ¥å—匿åè€…çš„å›žå¤ + +/talkpost.bml.opt.noautoformat=别自动排版 + +/talkpost.bml.opt.noimage=ä¸ç”¨å›¾è±¡ + +/talkpost.bml.opt.preview=预览 + +/talkpost.bml.opt.subject=主题: + +/talkpost.bml.opt.submit=编写评注 + +/talkpost.bml.postresponse=回å¤è¿™æ¡ + +/talkpost.bml.title=编写评注 + +/talkpost_do.bml.error.badpassword=你试用的密ç å’Œç”¨æˆ·åä¸å¯¹ã€‚如果你忘了你的密ç ï¼Œä½ å¯ä»¥åœ¨æ­¤æŸ¥å–。 + +/talkpost_do.bml.error.badusername=你打入的 LiveJournal 用户åä¸å­˜åœ¨ã€‚ä½ å¯åœ¨æ­¤å°†ç”¨æŠ¤å查å–。或者,你å¯ä»¥ä½¿ç”¨â€œæ— å者â€ã€‚ + +/talkpost_do.bml.error.banned=ä½ ä¸å…许在这个用户的日记里编写评注 + +/talkpost_do.bml.error.blankmessage=你的留言是空白的。请在留言盒打几个字。 + +/talkpost_do.bml.error.confused_identity=你打入了用户å,å¯é€‰æ‹©åŒ¿å评注,或注册用户。返回则决定你真的想åšä»€ä¹ˆã€‚ + +/talkpost_do.bml.error.deleted=你的日记已被删除,ä½ ä¸èƒ½å†ç¼–å†™ä¿¡æ¯ + +/talkpost_do.bml.error.friendsonly=åªæœ‰[[user]]的朋å‹æ‰èƒ½åœ¨æ­¤æ—¥è®°ä¸Šç¼–写 + +/talkpost_do.bml.error.lostcookie=收集你登记数æ®çš„cookie程åºå¤±è¸ªäº†å§ï¼Ÿ + +/talkpost_do.bml.error.manybytes=对ä¸èµ·, å¯æ˜¯ä½ åœ¨[[current]]的评注超出了byte上é™. 请回上页, 写短一点然åŽé‡è¯• + +/talkpost_do.bml.error.manychars=对ä¸èµ·, å¯æ˜¯ä½ åœ¨[[current]]的评注超出了字数上é™. 请回上页, 写短一点然åŽé‡è¯• + +/talkpost_do.bml.error.noanon=你在此用户的日记上ä¸èƒ½åŒ¿åå›žå¤ + +/talkpost_do.bml.error.noauth=ä½ ä¸å…许在此ä¿æŠ¤æ¡ç›®ä¸Šå›žå¤ + +/talkpost_do.bml.error.nocomments=用户的这个æ¡ç›®ä¸æŽ¥å—评注 + +/talkpost_do.bml.error.notafriend=对ä¸èµ·, ä½ ä¸åœ¨ç”¨æˆ·[[user]]的朋å‹åˆ—上; 而他们选择了"åªæœ‰æœ‹å‹"æ‰èƒ½å›žå¤çš„选项 + +/talkpost_do.bml.error.nousername=你没有输入你的用户åå­—. 如果你没有的LiveJournalå¸æˆ·,ä½ å¯ä»¥é€‰æ‹©ç”¨"匿å者"çš„åä¹‰å›žå¤ + +/talkpost_do.bml.error.noverify=对ä¸èµ·ï¼Œåœ¨ä½ çš„电邮地å€è¢«ç¡®è®¤ä»¥å‰ä½ ä¸å…许在他人的日记上编写评论。如果你丢了确认电邮而ä¸èƒ½ç¡®è®¤çš„è¯, ä½ å¯ä»¥é‡å‘。 + +/talkpost_do.bml.error.testacct=测试å¸æˆ·åªèƒ½åœ¨æµ‹è¯•å¸æˆ·æ—¥è®°å†…使用 + +/talkpost_do.bml.preview=这是你所编写的评论被å‘表时的样å­ã€‚使用下é¢çš„表å•ï¼Œä½ å¯ä»¥ç»§ç»­ç¼–辑你的评论,或者就这样æ交。 + +/talkpost_do.bml.preview.subject=主题æ : + +/talkpost_do.bml.preview.submit=é€ä¿¡ + +/talkpost_do.bml.preview.title=预览 + +/talkpost_do.bml.success.loggedin=ä½ å·²ç»ç™»å½•äº† + +/talkpost_do.bml.success.message=你的评注已被加上. ä½ å¯ä»¥åœ¨è¿™é‡Œå‚阅 + +/talkpost_do.bml.success.title=æˆåŠŸ + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=评论被å‘表 + +/talkread.bml.anonuser=匿å者 + +/talkread.bml.deletedpost=(删除此æ¡ç›®) + +/talkread.bml.deleteduser=(删除用户r: [[username]]) + +/talkread.bml.fromip=(从 [[ip]]) + +/talkread.bml.noreplies=无评注 + +/talkread.bml.nosubject=(无主题) + +/talkread.bml.subjectdeleted=[已被删除] + +/talkread.bml.title=å‚阅评注 + +/tools/memadd.bml.body.added.header=æˆåŠŸ + +/tools/memories.bml.back=返回 + +/tools/memories.bml.form.switch=设定 + +/update.bml.error.disabled=ä½ çš„å¸æˆ·ç±»åž‹ä¸å…许张贴。 + +/update.bml.simple=你现在所用的是简化的 + +/update.bml.timeformat=24å°æ—¶æ—¶é—´æ ¼å¼ + +/update.bml.title=更新日记 + +/update.bml.title.readonly=åªè¯»æ¨¡å¼ + +/update.bml.update.head=更新你的日记…… + +/update.bml.updating=正在更新日记…… + +/userinfo.bml.about.comm=关于: + +/userinfo.bml.about.user=自传: + +/userinfo.bml.comminfo.name=ç¤¾åŒºä¿¡æ¯ + +/userinfo.bml.label.searchjournal=æœç´¢è¿™æœ¬æ—¥è®° + +/userinfo.bml.title=用户资料 + +/userinfo.bml.userinfo.body=下é¢æ˜¯[[username]]的用户资料。如果你就是这个用户,你å¯ä»¥åœ¨ç¼–辑资料页é¢ç¼–辑你的资料(或者选择什么资料公开)。 + +/userinfo.bml.userinfo.name=用户资料 + +BML.parse_multipart.toolarge=上载太大 + +BML.parse_multipart.unknowntype=ä¸èƒ½è¾¨è¯†çš„内容ç§ç±» + +btn.search=æœç´¢ + +crumb.acctfeatures=æ ¹æ®å¸æˆ·ç±»åž‹åŒºåˆ†çš„功能 + +crumb.commsearch=群组æœç´¢ + +crumb.coppa=儿童线上éšç§ä¿æŠ¤æ³•æ¡ˆ + +crumb.feedstersearch=æœç´¢ä¸€æœ¬æ—¥è®° + +crumb.goat=关于弗兰克 + +crumb.privacy=éšç§æ”¿ç­– + +crumb.search=æœç´¢ + +crumb.singlessearch=æœç´¢å•èº«äººå£« + +crumb.sitemap=站点地图 + +crumb.tos=æœåŠ¡æ¡æ¬¾ + +date.month.april.short=四月 + +date.month.august.long=八月 + +date.month.august.short=八月 + +date.month.december.long=å二月 + +date.month.december.short=å二月 + +date.month.february.long=二月 + +date.month.february.short=二月 + +date.month.january.long=一月 + +date.month.january.short=一月 + +date.month.july.long=七月 + +dystopia.btn.login=登记 + +dystopia.hello_anonymous=欢迎使用LiveJournalï¼ + +dystopia.hello_loggedin=[[username]]ï¼šä½ å¥½ï¼ + +dystopia.nav.contact=è”ç³»ä¿¡æ¯ + +dystopia.nav.createjournal=开设新日记 + +dystopia.nav.developer=å¼€å‘人员专区 + +dystopia.nav.download=下载 + +dystopia.nav.editentries=编辑æ¡ç›® + +dystopia.nav.editfriends=ä½ çš„æœ‹å‹ + +dystopia.nav.editpassword=ä½ çš„å¯†ç  + +dystopia.nav.editpics=ä½ çš„å›¾åƒ + +dystopia.nav.editstyle=编辑风格 + +dystopia.nav.faq=常è§é—®é¢˜ + +dystopia.nav.findcomm=按照群组 + +dystopia.nav.finddir=æœç´¢ç›®å½• + +dystopia.nav.findint=按照嗜好 + +dystopia.nav.findrandom=éšæœºæœç´¢ + +dystopia.nav.findregion=按照地区 + +dystopia.nav.home=主页 + +dystopia.nav.journalcalendar=日历 + +dystopia.nav.journalfriends=æœ‹å‹ + +dystopia.nav.journalinfo=用户资料 + +dystopia.nav.journalrecent=最新æ¡ç›® + +dystopia.nav.legalcoppa=儿童线上éšç§ä¿æŠ¤æ³•æ¡ˆ + +dystopia.nav.legalprivacy=ä¿å¯† + +dystopia.nav.legaltos=æœåŠ¡æ¡æ¬¾ + +dystopia.nav.login=登记 + +dystopia.nav.logout=退出 + +dystopia.nav.lostinfo=å¿˜è®°äº†å¯†ç  + +dystopia.nav.memories=回忆区 + +dystopia.nav.modifyjournal=个性化日记 + +dystopia.nav.news=æ–°é—» + +dystopia.nav.paidaccts=收费账户 + +dystopia.nav.paymentarea=付款区 + +dystopia.nav.personalinfo=个人资料 + +dystopia.nav.sitemap=站点地图 + +dystopia.nav.siteopts=æµè§ˆé€‰é¡¹ + +dystopia.nav.support=有问题å—? + +dystopia.nav.updatejournal=更新日记 + +dystopia.navhead.findusers=寻找用户 + +dystopia.navhead.help=帮助以åŠæ”¯æŒ + +dystopia.navhead.journal=你的日记 + +dystopia.navhead.legal=与法律有关的 + +dystopia.navhead.settings=你的设置 + +dystopia.navhead.welcome=æ¬¢è¿Žï¼ + +dystopia.search.icq=ICQå·ç  + +dystopia.search.int=按照嗜好 + +dystopia.search.region=按照地区 + +dystopia.searchlj=æœç´¢LiveJournal: + +Email=email + +Error|notes=typically used inside an H1 tag to announce an error. +Error=错误 + +error.nodb=资料库暂时ä¸èƒ½ä½¿ç”¨ + +error.nodbmaintenance=这部分的资料库在维修中暂时åœç”¨, 请在数分钟以åŽé‡è¯• + +error.purged.name=已删除 + +error.purged.text=这个日记已被删除和清ç†. + +error.unknownmode=ä¸æ˜Žçš„æ¨¡å¼ + +error.usernameinvalid=用户å¸å·é‡Œå«æœ‰ä¸è¢«è®¤å¯çš„å­—ç  + +Help=帮助 + +langname.be=白俄罗斯语 + +langname.da=丹麦语 + +langname.de=德语 + +langname.en=英语 + +langname.en_GB=英语 (UK) + +langname.en_LJ=英语 + +langname.eo=世界语 + +langname.es=西ç­ç‰™è¯­ + +langname.fi=芬兰语 + +langname.fr=法语 + +langname.ga=爱尔兰语 + +langname.he=希伯莱语 + +langname.hu=匈牙利语 + +langname.is=冰岛语 + +langname.it=æ„大利语 + +langname.ja=日语 + +langname.la=拉ä¸è¯­ + +langname.ms=马æ¥è¯­ + +langname.nb=挪å¨è¯­ BokmÃ¥l + +langname.nl=è·å…°è¯­ + +langname.nn=挪å¨è¯­ Nynorsk + +langname.pl=波兰语 + +langname.pt=è‘¡è„牙语 + +langname.ru=俄语 + +langname.sv=瑞典语 + +langname.tr=土耳其语 + +langname.zh=简体中文 + +ljcom.account.feature.search=目录æœç´¢ + +ljcom.accounttype=å¸æˆ·ç±»åž‹ + +ljcom.userinfo.accounttype=å¸æˆ·ç±»åž‹ + +lynx.nav.sitemap=站点地图 + +lynx.nav.siteopts=æµè§ˆé€‰é¡¹ + +Password=å¯†ç  + +portal.ministats.active=活的: + +portal.ministats.title=用户统计 + +portal.ministats.total=总计: + +portal.stats.totalusers=用户总数 + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=抱歉 + +talk.anonwrote=有人写é“, + +talk.anonwrote_comm=有人在[[commlink]]写é“, + +talk.commentpermlink=链接 + +talk.commentpost=å‘表新的评注 + +talk.commentsread=阅读评注 + +talk.curname_Mood=现在的心情: + +talk.curname_Music=现在的音ä¹: + +talk.error.mustlogin=你必须登录åŽæ‰èƒ½æŸ¥çœ‹è¿™æ¡è¢«ä¿æŠ¤çš„æ¡ç›®. + +talk.error.noentry=没有这个æ¡ç›® + +talk.error.nosuchjournal=没有这本日记 + +talk.error.notauthorised=ä½ ä¸è¢«å…许看这æ¡è¢«ä¿æŠ¤çš„æ¡ç›® + +talk.parentlink=上一级 + +talk.readsimilar=å‚阅类似的æ¡ç›® + +talk.replytothis=å›žå¤ + +talk.somebodywrote=[[realname]]([[userlink]])写了, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) 在 [[commlink]]写了, + +talk.threadlink=主题 + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_zhongwen + +Username=用户å + +userpic.inactive=éžæ´»åŠ¨çš„ + +xcolibur.greeting.anon=欢迎访问LiveJournalï¼ + +xcolibur.greeting.logged_in=欢迎,[[name]]ï¼[[logout]] + +xcolibur.login=登录? + +xcolibur.logout=登出? + +xcolibur.nav.about=关于 + +xcolibur.nav.about.download=下载 + +xcolibur.nav.about.general=概è¦ä¿¡æ¯ + +xcolibur.nav.about.paidaccounts=付费用户 + +xcolibur.nav.about.press=æ–°é—» + +xcolibur.nav.about.sitenews=站点新闻 + +xcolibur.nav.about.stats=统计 + +xcolibur.nav.footer.sitemap=站点地图 + +xcolibur.nav.help=帮助 + +xcolibur.nav.help.ask=æé—® + +xcolibur.nav.help.contact=è”ç³»ä¿¡æ¯ + +xcolibur.nav.help.faq=常è§é—®é¢˜ + +xcolibur.nav.help.lostpassword=ä¸¢å¤±å¯†ç  + +xcolibur.nav.home=家 + +xcolibur.nav.journal=日记 + +xcolibur.nav.journal.archive=存档 + +xcolibur.nav.journal.edit.entries=编辑æ¡ç›® + +xcolibur.nav.journal.friends=æœ‹å‹ + +xcolibur.nav.journal.info=资料 + +xcolibur.nav.journal.memories=回忆 + +xcolibur.nav.journal.recent=最近 + +xcolibur.nav.journal.update=æ›´æ–° + +xcolibur.nav.manage=ç®¡ç† + +xcolibur.nav.manage.community=群组 + +xcolibur.nav.manage.customize=定制 + +xcolibur.nav.manage.entries=æ¡ç›® + +xcolibur.nav.manage.friends=æœ‹å‹ + +xcolibur.nav.manage.info=资料 + +xcolibur.nav.manage.password=å¯†ç  + +xcolibur.nav.manage.pics=用户图片 + +xcolibur.nav.manage.styles=风格 + +xcolibur.nav.search=æœç´¢ + +xcolibur.nav.search.directory=地区 + +xcolibur.nav.search.directory.search=高级 + +xcolibur.nav.search.interests=兴趣 + +xcolibur.nav.search.random=éšæœº + +xcolibur.nav.siteopts=æµè§ˆé€‰é¡¹ + +xcolibur.nav.title=导航: + +xcolibur.nav.welcome=欢迎 + +xcolibur.nav.welcome.create=创建一个å¸æˆ· + +xcolibur.nav.welcome.login=登录 + +xcolibur.nav.welcome.update=更新你的日记 + +xcolibur.search=æœç´¢ï¼š + +xcolibur.search.aolim=美国在线å³æ—¶æ¶ˆæ¯ + +xcolibur.search.category=类别: + +xcolibur.search.icq=ICQå·ç  + +xcolibur.search.int=兴趣 + +xcolibur.search.msn=MSN用户å + +xcolibur.search.region=地区 + +xcolibur.search.yahoo=雅虎用户身份 + +xcolibur.upgrade=å‡çº§ä½ çš„å¸æˆ· + diff --git a/ljcom/bin/upgrading/zh_TR.dat b/ljcom/bin/upgrading/zh_TR.dat new file mode 100644 index 0000000..06c718e --- /dev/null +++ b/ljcom/bin/upgrading/zh_TR.dat @@ -0,0 +1 @@ +;; -*- coding: utf-8 -*- diff --git a/ljcom/bin/watch-nodes.pl b/ljcom/bin/watch-nodes.pl new file mode 100755 index 0000000..550d1c6 --- /dev/null +++ b/ljcom/bin/watch-nodes.pl @@ -0,0 +1,91 @@ +#!/usr/bin/perl + +use strict; +use IO::Socket::INET; +use IO::Select; + +my $port = 4446; +my $MAXLEN = 512; +my $BCAST_VER = 1; + +eval { require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; }; + +my $pool = shift @ARGV; +$pool ||= "int_web"; + +my $pool_file = "$ENV{'LJHOME'}/cgi-bin/pool_${pool}.txt"; +die "Can't find pool file: $pool_file\n" unless -e $pool_file; +my @pool; +open (F, $pool_file) or die; +while () { + chomp; + push @pool, $_; +} +close F; + +if ($LJ::FREECHILDREN_BCAST && + $LJ::FREECHILDREN_BCAST =~ /^(\S+):(\d+)$/) { + $port = $2; +} + +my $sock = IO::Socket::INET->new(Proto=>'udp', + LocalPort=>$port) + or die "couldn't create socket\n"; +$sock->sockopt(SO_BROADCAST, 1); +$sock->blocking(0); +$|=1; + +my $sel = IO::Select->new(); +$sel->add($sock); + +my $message; +my %servers; + +sub dump_servers { + my $now = time(); + print "----- Pool: $pool (\@$now) -----\n"; + foreach my $key (@pool) { + my $s = $servers{$key}; + if ($s && $s->{_time} > $now - 10) { + print "$key: free $s->{'free'}, active $s->{'active'}\n"; + } else { + print "$key: ??\n"; + } + } +} + +sub parse_message { + my ($sock, $message) = @_; + my ($port, $ipaddr) = sockaddr_in($sock->peername); + my $ip_text = inet_ntoa($ipaddr); + delete $servers{$ip_text}; + + my $host; + foreach my $pair (split /\n/, $message) { + $host->{$1} = $2 if $pair =~ /^(\S+)=(\S*)$/; + } + $host->{_time} = time(); + + return unless $host->{bcast_ver} eq $BCAST_VER; + $servers{$ip_text} = $host; +} + +my $savedtime = 0; +while(1) { + my $time = time(); + if ($time - $savedtime >=2) { + dump_servers(); + $savedtime = $time; + } + my @ready = $sel->can_read(2); + foreach my $fh (@ready) { + if ($fh == $sock) { + while($sock->recv($message, $MAXLEN)) { + parse_message($sock, $message); + last if time() - $savedtime >=2; + } + } + } +} + + diff --git a/ljcom/cgi-bin/bml/scheme/dystopia.look b/ljcom/cgi-bin/bml/scheme/dystopia.look new file mode 100755 index 0000000..7a47ba5 --- /dev/null +++ b/ljcom/cgi-bin/bml/scheme/dystopia.look @@ -0,0 +1,623 @@ +# LiveJournal.com-specific library +# +# This file is NOT licensed under the GPL. As with everything in the +# "ljcom" CVS repository, this file is the property of Danga +# Interactive and is made available to the public only as a reference +# as to the best way to modify/extend the base LiveJournal server code +# (which is licensed under the GPL). +# +# Feel free to read and learn from things in "ljcom", but don't use +# our schemes because we don't want your site looking like +# LiveJournal.com (our logo and site scheme are our identity and we +# don't want to confuse users) +# +# Instead, use/modify one of the schemes in the "livejournal" repository. +# (Ideally you'd make your own entirely) +# + +_parent=>global.look + +help=>{Ds}(<?_ml Help _ml?>) + +h1=>{D}

    %%data%% +h1/follow_choices=>{D}%%data%% + +h2=>{D}

    %%data%% + +# Banner Header: search results banner, content desriptor, etc... +bh=>{D}

    %%data%% + +grin=>{S}<grin> +hr=>{S}

    *

    + +newline=>{S}
         +p=>{DRp}
    %%data%% +p/follow_p=>{DRps}

    %%data%% + +emcolor=>{S}#a7c7e8 +emcolorlite=>{S}#d9e9f9 +altcolor1=>{S}#d9e9f9 +altcolor2=>{S}#a7c7e8 + +de=>{DRp}%%data%% + +standout<= +{DRps}

    + + + + + + + + + + + + + + +
    + / + + \
    + +%%data%% + + +
    + \ + + /
    + +
    +<=standout + +warningbar<= +{DRps}
    +%%data%% +
    +<=warningbar + +errorbar<= +{DRps}
    +%%data%% +
    +<=errorbar + +soerror=>
    %%data%%
    +emailex=>
    %%data%%
    + +######################### choices stuff + +choice=>{PRps}
    %%data1%%
    %%data3%% + +choices<= +{FRp}

    + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=choices + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + +{r}); +} +_code?> + + + + + +<?_code { + my $elhash = $_[2]; + return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'}; +} _code?> + + + + + + +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> +%%head%% + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
      
    +
    /dys/logo3-lang.gif" width="122" height="52" border="0" ismap="ismap" usemap="#setlang">'; + } else { + return ''; + } +_code?> + + + + + + + + + + + + + + + + + + + + + + + +
     
    + +   + "; + $ret .= ' + + + +
    + LJ::get_remote()->{'user'} })); + } else { + return BML::noparse(BML::ml("dystopia.hello_anonymous")) + } +_code?> + | + | + | + | + +| {'user'}&sessid=$r->{'_session'}->{'sessid'}" . '">' . BML::ml("dystopia.nav.logout") . ''); + } + return; +_code?> +
    +
    + + BML::ml('dystopia.navhead.journal'), + 'links' => [ { 'url' => '/update.bml', + 'text' => BML::ml('dystopia.nav.updatejournal'), }, + { 'url' => "/users/$remote->{'user'}/", + 'text' => BML::ml('dystopia.nav.journalrecent'), }, + { 'url' => "/users/$remote->{'user'}/calendar", + 'text' => BML::ml('dystopia.nav.journalcalendar'), }, + { 'url' => "/users/$remote->{'user'}/friends", + 'text' => BML::ml('dystopia.nav.journalfriends'), + 'extra' => '/friends/filter.bml', }, + { 'url' => "/userinfo.bml?user=$remote->{'user'}", + 'text' => BML::ml('dystopia.nav.journalinfo'), + 'extra' => "/userinfo.bml?user=$remote->{'user'}&mode=full", + }, + { 'url' => "/tools/memories.bml?user=$remote->{'user'}", + 'text' => BML::ml('dystopia.nav.memories'), }, + { 'url' => "/editjournal.bml", + 'text' => BML::ml('dystopia.nav.editentries'), }, + ], + }; + push @nav, { 'name' => BML::ml('dystopia.navhead.settings'), + 'links' => [ { 'url' => '/manage/', + 'text' => BML::ml('dystopia.nav.manage') }, + { 'url' => '/editinfo.bml', + 'text' => BML::ml('dystopia.nav.personalinfo') }, + { 'url' => "/friends/edit.bml", + 'text' => BML::ml('dystopia.nav.editfriends'), }, + { 'url' => "/editpics.bml", + 'text' => BML::ml('dystopia.nav.editpics'), }, + { 'url' => "/changepassword.bml", + 'text' => BML::ml('dystopia.nav.editpassword'), }, + { 'url' => "/modify.bml", + 'text' => BML::ml('dystopia.nav.modifyjournal'), }, + { 'url' => "/styles/edit.bml", + 'text' => BML::ml('dystopia.nav.editstyle'), }, + ], + }; + } + else + { + push @nav, { 'name' => BML::ml('dystopia.navhead.welcome'), + 'links' => [ + { 'url' => '/login.bml', + 'text' => BML::ml('dystopia.nav.login'), }, + { 'url' => '/create.bml', + 'text' => BML::ml('dystopia.nav.createjournal'), }, + { 'url' => "/update.bml", + 'text' => BML::ml('dystopia.nav.updatejournal'), }, + ], + }; + + } + + push @nav, { 'name' => BML::ml('dystopia.navhead.findusers'), + 'links' => [ + { 'url' => '/random.bml', + 'text' => BML::ml('dystopia.nav.findrandom'), }, + $LJ::DISABLED{'directory'} ? () : + ( + { 'url' => '/directory.bml', + 'text' => BML::ml('dystopia.nav.findregion'), } + ), + { 'url' => '/community/', + 'text' => BML::ml('dystopia.nav.findcomm'), }, + { 'url' => '/interests.bml', + 'text' => BML::ml('dystopia.nav.findint'), }, + $LJ::DISABLED{'directory'} ? () : + ( + { 'url' => '/directorysearch.bml', + 'text' => BML::ml('dystopia.nav.finddir'), } + ), + ], + }; + + push @nav, { 'name' => 'LiveJournal', + 'links' => [ + { 'url' => '/download/', + 'text' => BML::ml('dystopia.nav.download'), }, + { 'url' => '/paidaccounts/', + 'text' => BML::ml('dystopia.nav.paidaccts'), }, + { 'url' => '/pay/', + 'text' => BML::ml('dystopia.nav.paymentarea'), }, + ], + }; + + push @nav, { 'name' => BML::ml('dystopia.navhead.help'), + 'links' => [ { 'url' => '/support/faq.bml', + 'text' => BML::ml('dystopia.nav.faq'), }, + { 'url' => '/support/', + 'text' => BML::ml('dystopia.nav.support'), }, + { 'url' => '/lostinfo.bml', + 'text' => BML::ml('dystopia.nav.lostinfo'), }, + { 'url' => '/developer/', + 'text' => BML::ml('dystopia.nav.developer'), }, + { 'url' => '/press/staff.bml', + 'text' => BML::ml('dystopia.nav.contact'), }, + ], + }; + + push @nav, { 'name' => BML::ml('dystopia.navhead.legal'), + 'links' => [ { 'url' => '/legal/tos.bml', + 'text' => BML::ml('dystopia.nav.legaltos'), }, + { 'url' => '/legal/privacy.bml', + 'text' => BML::ml('dystopia.nav.legalprivacy'), }, + { 'url' => '/legal/dmca.bml', + 'text' => BML::ml('dystopia.nav.legaldmca'), }, + ], + }; + + + my $ret = $LJ::DYS_LEFT_TOP; + foreach my $sec (@nav) { + $ret .= ""; + } + return BML::noparse($ret); + +_code?> + + + + + + + + + +

    $sec->{'name'}
    "; + foreach my $l (@{$sec->{'links'}}) { + $ret .= "{'url'}\">$l->{'text'}"; + if ($l->{'extra'}) { + $ret .= " {'extra'}\">..."; + } + $ret .= "
    "; + } + $ret .= "

     
     
     
    +

     

    +

     

    +
    + + + +"; + } else { + $button = ""; + } + } else { + if (! $LJ::IS_SSL) { + $button = ""; + } else { + $button = ""; + } + } + + my $chal = LJ::challenge_generate(300); + return <<"END_LOGIN_BAR"; + + + + + + + +END_LOGIN_BAR + } + return; + +_code?> + + + +
    + + + + + + + + +
     $ML{'Username'}:  $ML{'Password'}:  $button
    +
    + + +
    + + + +%%pretitle%% + +%%title%%

    + +%%body%% + +

    + +
    +
    + +<=PAGE + diff --git a/ljcom/cgi-bin/bml/scheme/ssl.look b/ljcom/cgi-bin/bml/scheme/ssl.look new file mode 100644 index 0000000..75043fe --- /dev/null +++ b/ljcom/cgi-bin/bml/scheme/ssl.look @@ -0,0 +1,213 @@ +# SSL scheme + +# LiveJournal.com-specific library +# +# This file is NOT licensed under the GPL. As with everything in the +# "ljcom" CVS repository, this file is the property of Danga +# Interactive and is made available to the public only as a reference +# as to the best way to modify/extend the base LiveJournal server code +# (which is licensed under the GPL). +# +# Feel free to read and learn from things in "ljcom", but don't use our styles +# because we don't want your site looking like LiveJournal.com (our logo +# and site scheme are our identity and we don't want to confuse users) +# + +######################### little stuff + +_parent=>global.look + +imgprefix=>{S}/img +statprefix=>{S}/stc + +help=>{Ds}(<?_ml Help _ml?>) + +h1=>{D}

    %%data%% +h1/follow_choices=>{D}%%data%% + +h2=>{D}

    %%data%% + +# Banner Header: search results banner, content desriptor, etc... +bh=>{D}

    %%data%% + +grin=>{S}<grin> +hr=>{S}

    *

    + +newline=>{S}
         +p=>{DRp}
    %%data%% +p/follow_p=>{DRps}

    %%data%% + +emcolor=>{S}#a7c7e8 +emcolorlite=>{S}#d9e9f9 + +de=>{DRp}%%data%% + +standout<= +{DRps}

    + + + + + + + + + + + + + + +
    + / + + \
    + +%%data%% + + +
    + \ + + /
    + +
    +<=standout + +######################### choices stuff + +choice=>{PRps}
    %%data1%%
    %%data3%% + +choices<= +{FRp}

    + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=choices + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + + + +%%title%% + + + + +%%head%% + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
      
    +
    + + + + + + + + + + + + + + + + +
      +
    +LiveJournal Secure Site + +
    +
    + + + + +
    + + +
    + +%%pretitle%% + +
    +%%title%%

    + +%%body%% +

    + +
    + +
    +
    + +<=PAGE + diff --git a/ljcom/cgi-bin/console-local.pl b/ljcom/cgi-bin/console-local.pl new file mode 100644 index 0000000..ec4f0b0 --- /dev/null +++ b/ljcom/cgi-bin/console-local.pl @@ -0,0 +1,838 @@ +#!/usr/bin/perl +# + +package LJ::Con; + +my $success = sub { + my ($out, $msg) = @_; + push @$out, [ "", $msg ]; + return 1; +}; +my $fail = sub { + my ($out, $msg) = @_; + push @$out, [ "error", $msg ]; + return 0; +}; +my $usage = sub { + my ($out, $cmdname) = @_; + return $fail->($out, "usage: $cmdname $cmd{$cmdname}{argsummary}"); +}; + +$cmd{'contrib'} = { + 'handler' => \&contrib_edit, + 'des' => "Adds/Acks Contributions.", + 'argsummary' => ' [/] [] [] []', + 'args' => [ + 'command' => "Either 'ack' to ack a contrib, 'add' to add a contrib.", + 'username' => "The username for the contribution to add.", + 'ackid' => "Id of the contribution to ack.", + 'contribtype' => "'code' for Coding, 'doc' for documentation, 'creative' for artwork, 'biz' for buisness, 'other' for other", + 'msg' => "description of what they did", + 'url' => "[optional] url with more information", + ], + }; + +$cmd{'payment_credit'} = { + 'handler' => \&payment_credit, + 'privs' => [qw(moneyenter)], + 'des' => "Give payment credit to an existing user from either an account code or a payid. Marks the associated code as then used by that username.", + 'argsummary' => ' to ', + 'args' => [ + 'thing' => "Either 'code' or 'payment'.", + 'id' => "If code, the code; if payment, the payid.", + 'username' => "The username to give the time to.", + ], + }; + +$cmd{'unpay'} = { + 'handler' => \&unpay, + 'privs' => [qw(moneyenter)], + 'des' => "Takes away paid time from a user for a bogus/accidental payment, while also changing the payment record to 0 months and 0 dollars, and making a note in the statushistory table why the payment was removed, and what the payment's old values were.", + 'argsummary' => ' ', + 'args' => [ + 'user' => 'Username of person to remove time from. Or, use "!" (without the quotes) for no user, when you just want to zero out a payment and/or its associated account code.', + 'payid' => 'Payment ID# to delete', + 'reason' => 'The reason the payment is being deleted. Not sent to user, only put in user\'s statushistory.', + ], + }; + +$cmd{'inventory'} = { + 'handler' => \&inventory, + 'privs' => [qw(moneyenter shipping)], + 'des' => "View or modify inventory.", + 'argsummary' => ' [ ]', + 'args' => [ + 'command' => 'Either "show" to show current inventory, "add" to add <value> units of <item>, or "remove" to remove <value> units of <item>, or "price" to change the price of <item> to <value>.', + 'item' => 'Inventory code.', + 'value' => 'Number to change inventory by, or new cost.', + ], + }; + +sub unpay +{ + my ($dbh, $remote, $args, $out) = @_; + + my $user = LJ::canonical_username($args->[1]); + if ($args->[1] eq "!") { $user = "!"; } + + my $payid = $args->[2]; + my $reason = $args->[3]; + + my $err = sub { + my $err = shift; + my $lock = shift; + push @$out, [ "error", $err ]; + if ($lock) { + my $qlock = $dbh->quote($lock); + $dbh->do("SELECT RELEASE_LOCK($qlock)"); + } + return 0; + }; + + return $err->("$remote->{'user'}, you are not authorized to use this command.") + unless (LJ::check_priv($dbh, $remote, "moneyenter")); + + return $err->("No reason given") + unless $reason; + + return $err->("Invalid or missing username argument") + unless $user; + + return $err->("Invalid payid format (not a number") + unless ($payid =~ /^\d+$/); + + my $p = $dbh->selectrow_hashref("SELECT * FROM payments WHERE payid=$payid"); + my $u; + if ($user eq "!") { + $u = { + 'userid' => 0, + }; + } else { + $u = LJ::load_user($user, "force"); + } + + return $err->("The unpay command doesn't work with the new payment system") + if $p->{'forwhat'} eq "cart"; + + return $err->("Payment not found") + unless $p; + + return $err->("User not found") + unless $u; + + return $err->("That payment doesn't belong to that user") + unless ($p->{'userid'} == $u->{'userid'}); + + return $err->("That payment has no months or money associated with it.") + unless ($p->{'amount'} ne "0.00" || $p->{'months'}); + + my $lockname = "unpay-$user-$payid"; + my $status; + + # start pseudo-transaction + $status = $dbh->selectrow_array("SELECT GET_LOCK('$lockname',10)"); + return $err->("Failed to get lock on necessary tables to do unpay, try again.") + unless $status; + + my $months = $p->{'months'}+0; + + my $logtext = ("Removing payid \#$payid ($p->{'months'} months & $p->{'amount'} ". + "dollars). Reason: " . $reason); + + # add to status history + if ($u->{'userid'}) { + $status = LJ::statushistory_add($dbh, $u->{'userid'}, $remote->{'userid'}, + "unpay", $logtext); + } else { + $dbh->do("UPDATE payments SET notes=concat(notes, ?) WHERE payid=$payid", undef, + "\nUNPAY: $logtext"); + } + + $err->("Couldn't append statushistory table, aborting", $lockname) + unless $status; + + + # update payment record + $dbh->do("UPDATE payments SET months=0, amount=0, used='Y' WHERE payid=$payid"); + $err->("Couldn't update payment record, aborting", $lockname) + if $dbh->err; + + # subtract time from user + $dbh->do("UPDATE paiduser SET paiduntil=DATE_SUB(paiduntil, INTERVAL $months MONTH) WHERE userid=$p->{'userid'}"); + $err->("Couldn't subtract time from user, aborting", $lockname) + if $dbh->err; + + # end transaction + $dbh->do("SELECT RELEASE_LOCK('$lockname')"); + + push @$out, [ "", "Done." ]; +} + +sub payment_credit +{ + my ($dbh, $remote, $args, $out) = @_; + + my $thing = $args->[1]; + my $id = $args->[2]; + my $to = $args->[3]; + my $username = $args->[4]; + + unless ($remote->{'priv'}->{'moneyenter'}) { + push @$out, [ "error", "$remote->{'user'}, you are not authorized to use this command." ]; + return 0; + } + + unless ($thing eq "code" || $thing eq "payment") { + push @$out, [ "error", "Invalid first argument." ]; + return 0; + } + + unless ($to eq "to") { + push @$out, [ "error", "Third argument isn't 'to'" ]; + return 0; + } + + my $u = LJ::load_user($username, "force"); + unless ($u) { + push @$out, [ "error", "User doesn't exist." ]; + return 0; + } + + my $payid; + my $acid; + + if ($thing eq "code") + { + my $code = $id; + ($acid, undef) = LJ::acct_code_decode($code); + my $err; + unless (LJ::acct_code_check($dbh, $code, \$err)) { + push @$out, [ "error", "Bad code: $err." ]; + return 0; + } + my $sth = $dbh->prepare("SELECT payid FROM acctpay WHERE acid=$acid"); + $sth->execute; + ($payid) = $sth->fetchrow_array; + + unless ($payid) { + push @$out, [ "error", "This code doesn't have an associated payment." ]; + return 0; + } + } + + if ($thing eq "payment") { + $payid = $id+0; + + my $sth = $dbh->prepare("SELECT acid FROM acctpay WHERE payid=$payid"); + $sth->execute; + ($acid) = $sth->fetchrow_array; + + unless ($acid) { + push @$out, [ "error", "This payment doesn't have an associated code." ]; + return 0; + } + + } + + my $sth = $dbh->prepare("SELECT * FROM payments WHERE payid=$payid"); + $sth->execute; + my $p = $sth->fetchrow_hashref; + unless ($p) { + push @$out, [ "error", "Payment not found." ]; + return 0; + } + unless ($p->{'userid'} == 0) { + push @$out, [ "error", "Payment already assigned... not open." ]; + return 0; + } + + # guess everything's good. + $dbh->do("UPDATE payments SET userid=$u->{'userid'} WHERE payid=$payid"); + $dbh->do("UPDATE acctcode SET rcptid=$u->{'userid'} WHERE acid=$acid"); + + push @$out, [ "", "Done." ]; +} + +sub contrib_edit +{ + my ($dbh, $remote, $args, $out) = @_; + my $err = sub { push @$out, [ "error", $_[0] ]; 0; }; + + return $err->("This command has 2 or more arguments") unless @$args >= 2; + return $err->("Must be logged in.") unless $remote; + + my $cmd = $args->[1]; + if ($cmd eq "add") + { + return $err->("Not enough arguments for add.") + unless @$args == 5 or @$args == 6; + my $user = $args->[2]; + my $cat = $args->[3]; + my $des = $args->[4]; + my $url = $args->[5]; + + my $u = LJ::load_user($user, "force"); + return $err->("Invalid user $user") unless $u; + my $userid = $u->{'userid'}; + return $err->("type can only be: 'code','doc','creative','biz','other'") unless + ($cat eq "code" or $cat eq "doc" or $cat eq "creative" or + $cat eq "biz" or $cat eq "other"); + + $dbh->do("INSERT INTO contributed (userid, cat, des, url, dateadd) ". + "VALUES (?,?,?,?,NOW())", undef, $userid, $cat, $des, $url); + return $err->("error adding contribution") if $dbh->err; + + } elsif ($cmd eq "ack") { + + return $err->("Not enough arguments for ack.") unless @$args == 3; + return $err->("You have to be an acknowledged contributor before you can acknowledge other people.") + unless LJ::Contrib::is_acked($remote->{'userid'}); + + my $coid = $args->[2]+0; + + LJ::Contrib::ack($coid, $remote->{'userid'}); + + } else { + return $err->("Unknown Command Type"); + } + + push @$out, [ '', "Success." ]; + return 1; +} + +sub inventory +{ + my ($dbh, $remote, $args, $out) = @_; + + my $cmd = $args->[1]; + my $item = $args->[2]; + my $val = $args->[3]; + + unless ($remote->{'priv'}->{'moneyenter'} || $remote->{'priv'}->{'shipping'}) { + push @$out, [ "error", "$remote->{'user'}, you are not authorized to use this command." ]; + return 0; + } + + unless ($cmd =~ /show|add|remove|price/) { + push @$out, [ "error", "Invalid inventory command." ]; + return 0; + } + + if ($cmd eq "show") { + my $sth = $dbh->prepare("SELECT item, subitem, qty, avail, price FROM inventory ". + "ORDER BY item, subitem"); + $sth->execute; + push @$out, [ '', "qty avl price item" ]; + push @$out, [ '', "==== ==== ====== =============================" ]; + while ($_ = $sth->fetchrow_hashref) { + push @$out, [ '', sprintf("%4d %4d \$%5.02f %s-%s", + $_->{'qty'}, $_->{'avail'}, $_->{'price'}, + $_->{'item'}, $_->{'subitem'}) ]; + } + return 1; + } + + my $subitem; + unless ($item =~ /^(\w+?)-(.+)$/) { + push @$out, [ "error", "Invalid item format." ]; + return 0; + } + ($item, $subitem) = ($1, $2); + + if ($cmd eq "add" || $cmd eq "remove") { + my $dir = $cmd eq "add" ? "+" : "-"; + my $ro = $dbh->do("UPDATE inventory SET qty=qty $dir ?, avail=avail $dir ? ". + "WHERE item=? AND subitem=?", + undef, $val, $val, $item, $subitem); + if ($ro > 0) { + push @$out, [ "", "$item-$subitem changed." ]; + return 1; + } + push @$out, [ "error", "No change made." ]; + return 0; + } + + if ($cmd eq "price") { + my $price = $val; + $price =~ s/\$//; + unless ($price =~ /^(\d+)(\.\d\d)?$/ && $1) { + push @$out, [ "error", "Invalid price." ]; + return 0 + } + my $ro = $dbh->do("UPDATE inventory SET price=? ". + "WHERE item=? AND subitem=?", + undef, $price, $item, $subitem); + if ($ro > 0) { + push @$out, [ "", "$item-$subitem price changed." ]; + return 1; + } + push @$out, [ "error", "No change made." ]; + return 0; + } + + return 0; +} + +$cmd{'allow_pay'} = + { + des => "Permit or deny a user's ability to pay.", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + action => "'permit', or 'deny'", + username => "Username to allow to pay (with permit) or block payments (with deny)", + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + # check syntax and parse out some information + my $myname = shift @$args; + my $action = shift @$args or return $usage->($out, $myname); + my $user = shift @$args or return $usage->($out, $myname); + + my $act = $action eq 'permit' ? 'Y' : 'N'; + + return $usage->($out, $myname) unless $args; + return $usage->($out, $myname) unless $action =~ /^(permit|deny)$/; + return $usage->($out, $myname) unless $user; + + # make changes and revoke + my $userid = LJ::get_userid($dbh, $user); + return $fail->($out, "Skipping invalid username: '$_'") unless $userid; + + LJ::set_userprop($userid, 'allow_pay', $act) + or return $fail->($out, "Error setting 'allow_pay' userprop. Database Unavailable?"); + + # log to statushistory + LJ::statushistory_add($userid, $remote->{userid}, "allow_pay", ucfirst($action) . "ing payments"); + + $success->($out, ucfirst($action) . "ing payment for user $user"); + return 1; + } + + }; + +$cmd{'got_assignment'} = + { + des => "Mark a user as sending in the assignment agreement paperwork for the bazaar.", + privs => [qw(moneyenter)], + argsummary => '', + args => [ + user => "Username who sent in the assignment agreement.", + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + # check syntax and parse out some information + my $myname = shift @$args; + my $user = shift @$args or return $usage->($out, $myname); + + my $u = LJ::load_user($user, "force"); + return $fail->($out, "User not found") unless $u; + + LJ::set_userprop($u, "legal_assignagree", 1) + or return $fail->($out, "Error setting userprop. Database unavailable?"); + + $success->($out, "Assignment agreement flag set for $u->{'user'}"); + return 1; + } + }; + +$cmd{'bazaar_pay'} = + { + des => "Subtract money from a user's bazaar balance.", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + user => "Username to subtract balance from.", + amt => "Amount to subtract.", + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + # check syntax and parse out some information + my $myname = shift @$args; + my $user = shift @$args; + my $amt = shift @$args; + unless ($user ne "" && $amt =~ /^\d+(\.\d\d)?$/) { + return $usage->($out, $myname); + } + + my $u = LJ::load_user($user, "force"); + return $fail->($out, "User not found") unless $u; + + LJ::load_user_props($u, "legal_assignagree"); + unless ($u->{'legal_assignagree'}) { + return $fail->($out, "Error: no assignment agreement from $u->{'user'}. Use the 'got_assignment' command if you have it."); + } + + if (LJ::Pay::bazaar_remove_balance($u, $amt)) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, "bzrbaldecr", "Removing \$$amt"); + return $success->($out, "Success."); + } + + return $fail->($out, "Error: balance wasn't large enough?"); + } + }; + +$cmd{'bazaar_status'} = + { + des => "Show who's owed how much for the bazaar.", + privs => [qw(moneyenter)], + argsummary => '', + args => [ ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + LJ::Pay::bazaar_do_expirations(); + + my $sth = $dbh->prepare("SELECT u.user, SUM(b.owed) FROM user u, bzrbalance b ". + "WHERE u.userid=b.userid AND b.owed > 0 GROUP BY 1"); + $sth->execute; + while (my ($user, $sum) = $sth->fetchrow_array) { + push @$out, [ "", sprintf("%-20s = \$%7.02f", $user, $sum) ]; + } + + return $success->($out, "[end]"); + } + }; + + +$cmd{'rename_redir'} = + { + des => "Change redirection option of a previously done redirect", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + action => "'add' to do redirections, or 'remove' if redirections should not be done", + from_username => "Source journal which was renamed", + to_username => "Destination journal to which from_username was renamed" + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + shift @$args; # remove command name + my ($action, $from_username, $to_username) = @$args; + + return $fail->($out, "Invalid action: '$action'") + unless $action eq 'add' || $action eq 'remove'; + + my $from_user = LJ::load_user($from_username); + return $fail->($out, "Invalid from_username") + unless $from_user; + $from_username = $from_user->{'user'}; + + my $to_user = LJ::load_user($to_username); + return $fail->($out, "Invalid to_username") + unless $to_user; + $to_username = $to_user->{'user'}; + + return $fail->($out, "'$from_username' has already been marked as expunged'") + if $from_user->{'statusvis'} eq 'X'; + + return $fail->($out, "'$from_username' was never renamed to '$to_username'") + unless $dbh->selectrow_array("SELECT COUNT(*) FROM renames " . + "WHERE fromuser=? AND touser=?", + undef, $from_username, $to_username); + + LJ::load_user_props($from_user, 'renamedto'); + + # create a redirection link + if ($action eq 'add') { + return $fail->($out, "'$from_username' already redirects to '$to_username'") + if $from_user->{'renamedto'} eq $to_username && $from_user->{'statusvis'} eq 'R'; + + return $fail->($out, "'$from_username' redirects to another journal?") + if $from_user->{'statusvis'} eq 'R' && $from_user->{'renamedto'} && + $from_user->{'renamedto'} ne $to_username; + + # set renamedto prop + LJ::set_userprop($from_user, "renamedto", $to_username) + or return $fail->($out, "Error setting userprop. Database unavailable?"); + + # update user, undelete (checked to see if already expunged earlier) + LJ::update_user($from_user, + { raw => "journaltype='R', statusvis='R', statusvisdate=NOW()" }); + + # update email aliases if applicable + if (LJ::get_cap($from_user, "useremail")) { + $dbh->do("INSERT INTO email_aliases VALUES (?,?)", undef, + "$to_username\@$LJ::USER_DOMAIN", $to_user->{'email'}); + } + + return $success->($out, "Redirection added for $from_username => $to_username rename action"); + } + + # remove a redirection link + if ($action eq 'remove') { + + return $fail->($out, "'$from_username' does not redirect to '$to_username'") + unless $from_user->{'renamedto'} eq $to_username && + $from_user->{'statusvis'} eq 'R'; + + # delete renamedto prop + LJ::set_userprop($from_user, "renamedto", undef) + or return $fail->($out, "Error setting userprop. Database unavailable?"); + + # update user, set deleted + LJ::update_user($from_user, + { raw => "journaltype='R', statusvis='D', statusvisdate=NOW()" }); + + # update email aliases if applicable + $dbh->do("DELETE FROM email_aliases WHERE rcpt=?", + undef, "$from_username\@$LJ::USER_DOMAIN"); + + return $success->($out, "Redirection removed for $from_username => $to_username rename action"); + } + } + }; + +$cmd{'rename_show'} = + { + des => "View information about a rename.", + privs => [qw(moneyenter)], + argsummary => '', + args => [ + 'value' => "A hex or decimal tokenid, a full token string, or the username of a user who was renamed (source user)." + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + shift @$args; # remove command name + my $value = shift @$args; + + return $fail->($out, "You must enter a value") + unless $value; + + my @ren; + my $hashref_array = sub { + return values %{ + $dbh->selectall_hashref(shift(), 'renid', undef, @_) || {} + } + }; + + # they probably have this form of the token + if ($value =~ /^([0-9a-f]{6})(\w{10})$/) { + push @ren, $hashref_array->("SELECT * FROM renames WHERE renid=? AND token=?", hex $1, $2); + + # or maybe they have the tokenid? + } elsif ($value =~ /^([0-9a-f]{1,6})/) { + + # try decimal, hex tokenids (user could enter either) + push @ren, $hashref_array->("SELECT * FROM renames WHERE renid=? OR renid=?", $1, hex $1); + + # perhaps they have the token itself? + } elsif ($value =~ /^(\w{10})$/) { + + push @ren, $hashref_array->("SELECT * FROM renames WHERE token=?", $1); + + # explicitly disallow special tokens ([movedaway], [manual], etc) + # Note: "----------" is also a special token, but it's a valid username + # so we allow searching for it, + } elsif ($value =~ /^\[\w+\]$/) { + return $fail->($out, "Cannot search for special tokens"); + } + + # if no ren, then maybe they gave a username + push @ren, $hashref_array->("SELECT * FROM renames WHERE fromuser=?", + LJ::canonical_username($value)) + unless @ren; + + return $fail->($out, "Could not find a matching rename.") + unless @ren; + + foreach my $ren (@ren) { + push @$out, map { [ '', "$_: $ren->{$_}" ] } sort keys %$ren; + push @$out, [ '', '' ]; + } + + return $success->($out, "[end]"); + } + }; + +$cmd{'rename_reset'} = + { + des => "Lets account admins modify friends properties if selected incorrectly during a rename.", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + 'mode' => "'friends' to reset friends, 'friendofs' to reset friends-ofs.", + 'user' => "The username whose friends list should be cleared." + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + shift @$args; # remove command name + my $mode = shift @$args; + my $user = shift @$args; + + return $fail->($out, "Invalid mode, valid modes are 'friends' and 'friendofs'") + unless $mode eq 'friends' || $mode eq 'friendofs'; + + return $fail->($out, "You must enter a username") + unless $user; + + my $u = LJ::load_user($user); + return $fail->($out, "Invalid username") + unless $u; + + if ($mode eq 'friends') { + # TAG:FR:console:rename_reset:clear_friends + # clear the given user's friends + + # delete existing friends + my $friends = LJ::get_friends($cid, undef, undef, 'force') || {}; + if (LJ::remove_friend($cid, [ keys %$friends ])) { + return $success->($out, "Success, friends modified."); + } + + # some failure? + return $fail->($out, "Error modifying friends for user: '$user'"); + } + + if ($mode eq 'friendofs') { + # TAG:FR:console:rename_reset:clear_friendofs + # who lists this user as a friend? + my $ids = $dbh->selectcol_arrayref("SELECT userid FROM friends WHERE friendid=?", + undef, $u->{'userid'}) || []; + + # delete friend edges with this user as the target + if ($dbh->do("DELETE FROM friends WHERE friendid=?", undef, $u->{'userid'})) { + + # clear memcache for all friend-ofs + LJ::memcache_kill($_, "friends") foreach @$ids; + + return $success->($out, "Success, friend-ofs modified."); + } + + # some failure? + return $fail->($out, "Error modifying friend-ofs for user: '$user'"); + } + } + }; + + +$cmd{'fraud_watch'} = + { + des => "Set or unset the fraud_watch userprop for a given user", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + username => "Username who should have faud_watch set/unset", + action => "Optional. Either 'add' or 'remove' to set/unset the watch respectively. Defaults to 'add'.", + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + shift @$args; # remove command name + my ($action, $user) = @$args; + + return $fail->($out, "Invalid action: '$action'") + unless $action eq 'add' || $action eq 'remove'; + + my $u = LJ::load_user($user); + return $fail->($out, "Invalid username: $user") + unless $u; + + my $propval = $action eq 'add' ? 1 : 0; + my $verb = $propval ? 'added' : 'removed'; + + LJ::load_user_props($u, 'fraud_watch'); + + return $fail->($out, "Fraud watch already $verb, nothing to do. [$u->{fraud_watch}]") + if $u->{fraud_watch} == $propval; + + # set userprop + LJ::set_userprop($u, "fraud_watch", $propval) + or return $fail->($out, "Error setting 'fraud_watch' userprop. Database unavailable?"); + + # log to statushistory + LJ::statushistory_add($u->{userid}, $remote->{userid}, 'fraud_watch', "fraud watch $verb"); + + return $success->($out, "Fraud watch $verb for $u->{user}"); + } + }; + +$cmd{'coupon_revoke'} = + { + des => "Revoke an unused coupon that was given out by the system (for a promo, etc)", + privs => [qw(moneyenter)], + argsummary => ' ', + args => [ + username => "Username that owns the coupon to be revoked.", + coupon => "Coupon token. A full coupon token string to be revoked.", + ], + handler => sub { + my ($dbh, $remote, $args, $out) = @_; + + return $fail->($out, "Not logged in.") unless $remote; + return $fail->($out, "You don't have privileges needed to run this command.") + unless $remote->{'priv'}->{'moneyenter'}; + + shift @$args; # remove command name + my ($user, $coupon) = @$args; + + my $u = LJ::load_user($user); + return $fail->($out, "Invalid username: $user") + unless $u; + + return $fail->($out, "Invalid coupon format") + unless $coupon =~ /^(\d+)-(.+)$/; + my ($cpid, $auth) = ($1, $2); + my $cp = $dbh->selectrow_hashref + ("SELECT * FROM coupon WHERE cpid=? AND auth=?", + undef, $cpid, $auth); + return $fail->($out, "Invalid coupon, already revoked?") unless $cp; + return $fail->($out, "Coupon owner does not match '$user'") + unless $cp->{rcptid} == $u->{userid}; + return $fail->($out, "This command can only revoke coupons generated automatically " . + "by the system.") + unless $cp->{ppayid} == 0; + return $fail->($out, "This coupon has already been used in a cart.") + unless $cp->{payid} == 0; + + $dbh->do("DELETE FROM coupon WHERE cpid=? AND auth=? AND rcptid=?", + undef, $cpid, $auth, $u->{userid}); + return $fail->($out, "Database Error: " . $dbh->errstr) if $dbh->err; + + # log to statushistory + LJ::statushistory_add + ($u->{userid}, $remote->{userid}, 'coupon_revoke', "Coupon revoked: $coupon"); + + return $success->($out, "Coupon revoked: $coupon ($u->{user})"); + } + }; + +1; diff --git a/ljcom/cgi-bin/cracklib/README.txt b/ljcom/cgi-bin/cracklib/README.txt new file mode 100644 index 0000000..4f9d2d4 --- /dev/null +++ b/ljcom/cgi-bin/cracklib/README.txt @@ -0,0 +1,10 @@ +need to install on clients: + +apt-get install libcrypt-cracklib-perl + +to make the dictionary indexes, need to do: + +# apt-get install cracklib-runtime wenglish + +$ /usr/sbin/crack_mkdict /usr/share/dict/words | /usr/sbin/crack_packer $LJHOME/cgi-bin/cracklib/dict + diff --git a/ljcom/cgi-bin/crumbs-local.pl b/ljcom/cgi-bin/crumbs-local.pl new file mode 100644 index 0000000..eac41a8 --- /dev/null +++ b/ljcom/cgi-bin/crumbs-local.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# +# Stores all local crumbs and adds to the crumbs hash + + +%LJ::CRUMBS_LOCAL = ( + 'about' => ['About LiveJournal', '/site/about.bml', 'home'], + 'abusereport' => ['Report Abuse', '/abuse/report.bml', 'support'], + 'acctfeatures' => ['Features By Account Type', '/site/accounts.bml', 'about'], + 'advsearch' => ['Advanced', '/directorysearch.bml', 'search'], + 'banners' => ['Advertising Banners', '/banners.bml', 'home'], + 'code' => ['LiveJournal Code', '/code/index.bml', 'about'], + 'contributors' => ['Contributors', '/site/contributors.bml', 'press'], + 'coppa' => ['COPPA', '/legal/coppa.bml', 'legal'], + 'dmca' => ['DMCA Information', '/legal/dmca.bml', 'legal'], + 'download' => ['Download a Client', '/download/index.bml', 'about'], + 'filemanager' => ['File Manager', '/manage/files.bml', 'manage'], + 'goat' => ['About Frank', '/site/goat.bml', 'home'], + 'guidingprinciples' => ['Our Guiding Principles', '/legal/principles.bml', 'about'], + 'itsfree' => ['It\'s Free?', '/site/free.bml', 'paidaccounts'], + 'legal' => ['Legal Information', '/legal/index.bml', 'home'], + 'ljhome' => ['Home', 'http://www.livejournal.com/', ''], + 'paidaccounts' => ['Paid Accounts', '/paidaccounts/index.bml', 'about'], + 'paidacctstatus' => ['Paid Account Status', '/paidaccounts/status.bml', 'paidaccounts'], + 'press' => ['LiveJournal Press Area', '/press/index.bml', 'about'], + 'pressarticles' => ['LiveJournal in the Press', '/press/articles.bml', 'press'], + 'privacy' => ['Privacy Policy', '/legal/privacy.bml', 'legal'], + 'search' => ['Search', '/site/search.bml', 'home'], + 'searchinterests' => ['By Interest', '/interests.bml', 'search'], + 'searchregion' => ['By Region', '/directory.bml', 'search'], + 'securechangepass' => ['Change Password', '/changepassword.bml', 'securemanage'], + 'securecreatejournal' => ['Create Journal', '/create.bml', 'ljhome'], + 'securelogin' => ['Login', '/login.bml', 'ljhome'], + 'securemanage' => ['Manage Accounts', 'http://www.livejournal.com/manage/', 'ljhome'], + 'singles' => ['LiveJournal Singles', '/singles/', 'home'], + 'singlesopts' => ['Modify Availability', '/singles/mod.bml', 'singles'], + 'singlessearch' => ['Search for Singles', '/singles/search.bml', 'singles'], + 'sitemap' => ['Site Map', '/site/index.bml', 'home'], + 'sizechart' => ['Sizing Chart', '/store/sizechart.bml', 'store'], + 'staff' => ['Senior Staff', '/press/staff.bml', 'press'], + 'stats' => ['Statistics', '/stats.bml', 'press'], + 'store' => ['LiveJournal Store', '/store/', 'home'], + 'storeitem' => ['View Item Detail', '', 'store'], + 'suggestions' => ['Suggestions Generator', '/suggestions/generator.bml', 'suggview'], + 'suggview' => ['Suggestions', '/suggestions/index.bml', 'home'], + 'tos' => ['Terms of Service', '/legal/tos.bml', 'legal'], + ); +1; diff --git a/ljcom/cgi-bin/ljcom.pl b/ljcom/cgi-bin/ljcom.pl new file mode 100644 index 0000000..54df488 --- /dev/null +++ b/ljcom/cgi-bin/ljcom.pl @@ -0,0 +1,1604 @@ +#!/usr/bin/perl +# +# LiveJournal.com-specific library +# +# This file is NOT licensed under the GPL. As with everything in the +# "ljcom" CVS repository, this file is the property of Danga +# Interactive and is made available to the public only as a reference +# as to the best way to modify/extend the base LiveJournal server code +# (which is licensed under the GPL). +# +# Feel free to read and learn from things in "ljcom", but don't use it verbatim +# because we don't want your site looking like LiveJournal.com (our logo +# and site scheme are our identity and we don't want to confuse users) +# and we're sick of getting everybody's payment notifications when +# they use our payment system without any modifications. +# + +BEGIN { + # kill the LJ definition of LJ::is_utf8 so we can override it without warnings + { + no strict; + local $^W = 0; + *stab = *{"main::LJ::"}; + undef $stab{is_utf8}; + } + +} + +@LJ::USER_TABLES_LOCAL = ("phonepostentry", "phoneposttrans"); + +$LJ::BML_DENY_CONFIG = "guide, clients, files"; + +$LJ::ACCOUNTS_EMAIL = "accounts\@livejournal.com"; + +%LJ::FIXED_ALIAS = ( + 'lj' => 'lj', # discarded + 'lj_notify' => 'lj', # also discarded + 'test' => 'brad@danga.com', + 'postmaster' => 'lisa@grrl.org', + 'webmaster' => 'lj', + 'support' => 'lj', + 'abuse' => 'lj', + 'privacy' => 'lj', + 'feedback' => 'lj', + 'press' => 'lj', + 'bradfitz' => 'brad@danga.com', + 'paypal' => 'brad@danga.com', + 'accounts' => 'lj', + 'frank' => 'brad@danga.com', + 'lj_coreadmins' => 'brad@danga.com, lisa@grrl.org, nbarkas@moduli.net', + 'cvs-commits' => 'brad@danga.com, whitaker@danga.com, jproulx@livejournal.com, '. + 'mellon@pobox.com, martine@danga.com, mahlon@danga.com, ged@danga.com', + 'moodthemes' => 'evan@livejournal.com', # aliases to aliases! + 'bot-watchers' => 'brad@danga.com', + ); + +@LJ::LANGS = qw(en_LJ en_GB de da es fr it ru ja pt eo he nl hu ga is fi nb sv pl zh lv tr ms) + unless @LJ::LANGS > 1; + +# Useful untainting regexen +%LJ::REGEX = ( + httpuri => qr{(http://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?)(?:/(?:(?:(?:(?:[a-zA-Z\d\$\_.+!*'(),-]|(?:%[a-fA-F\d]{2}))|[;:@&=])*)(?:/(?:(?:(?:[a-zA-Z\d\$\_.+!*'(),-]|(?:%[a-fA-F\d]{2}))|[;:@&=])*))*)(?:\?(?:(?:(?:[a-zA-Z\d\$\_.+!*'(),-]|(?:%[a-fA-F\d]{2}))|[;:@&=])*))?)?)}x, + +); + + +package LJ::Contrib; + +# is the given user an acked contributor themselves? +sub is_acked +{ + my ($userid) = @_; + my $dbr = LJ::get_db_reader(); + return undef unless $dbr and $userid; + return $dbr->selectrow_array("SELECT COUNT(*) FROM contributed WHERE userid=? AND acks > 0", + undef, $userid); +} + +# make $coid acked by $userid +sub ack +{ + my ($coid, $userid) = @_; + my $dbh = LJ::get_db_writer(); + return undef unless $dbh and $userid and $coid; + + # see if contribution exists + my $co = $dbh->selectrow_hashref("SELECT * FROM contributed WHERE coid=?", + undef, $coid); + return 0 unless $co; + + ## Lock the Tables + $dbh->do("LOCK TABLES contributedack WRITE, contributed WRITE"); + + ## add the ack + $dbh->do("REPLACE INTO contributedack (coid, ackuserid) VALUES (?,?)", + undef, $coid, $userid); + + ## see how many acks it has now. + my $newcount = $dbh->selectrow_array("SELECT COUNT(*) FROM contributedack WHERE coid=?", + undef, $coid); + $newcount += 0; + + ## update the contributed table + $dbh->do("UPDATE contributed SET acks=? WHERE coid=?", undef, + $newcount, $coid); + + ## Unlock tables + $dbh->do("UNLOCK TABLES"); + return 1; +} + +package LJ::LJcom; + +use Inline (C => 'DATA', + DIRECTORY => $ENV{LJ_INLINE_DIR} || "$ENV{'LJHOME'}/Inline", + ); +use strict; + +{ + eval { + Inline->init(); + }; + if ($@) { + die "You seem to have Inline.pm, but you haven't run \$LJHOME/bin/lj-inline.pl\n"; + } +} + +sub country_of_ip { + my $ip = shift; + return undef unless $LJ::OPTMOD_GEOIP; + my $gi = $LJ::CACHE_GEOIP_HANDLE ||= Geo::IP::PurePerl->open("$LJ::HOME/cgi-bin/GeoIP.dat"); + return $gi->country_code_by_addr($ip); +} + +# old-name (off, on, paid, early (& new)) +sub acct_name_short { + my $caps = shift; + if ($caps & 0x10) { + return "on"; + } elsif ($caps & 0x08) { + return "paid"; + } elsif ($caps & 0x04) { + return "early"; + } elsif ($caps & 0x02) { + return "off"; + } elsif ($caps & 0x01) { + return "new"; + } + return "??"; +} + +sub acct_name { + my $caps = shift; + my $paiduntil = shift; + + my $v; + if ($paiduntil) + { + $v = $caps & 0x08 && $caps & 0x04 ? + BML::ml('ljcom.userinfo.types.paid_early_expiring', { 'paiduntil' => $paiduntil }) : + BML::ml('ljcom.userinfo.types.paid_expiring', { 'paiduntil' => $paiduntil }); + } else { + $v = $caps & 0x10 && $caps & 0x04 ? + $BML::ML{'ljcom.userinfo.types.permanent_early'} : + $caps & 0x10 ? $BML::ML{'ljcom.userinfo.types.permanent'} : + $caps & 0x08 && $caps & 0x04 ? + $BML::ML{'ljcom.userinfo.types.paid_early'} : + $caps & 0x08 ? $BML::ML{'ljcom.userinfo.types.paid'} : + $caps & 0x04 ? $BML::ML{'ljcom.userinfo.types.early'} : + $caps & 0x02 ? $BML::ML{'ljcom.userinfo.types.free'} : + $caps & 0x01 ? $BML::ML{'ljcom.userinfo.types.trial'} : + undef; + } + return $v; +} + +sub is_goatvote_poll { + my ($po, $qs) = @_; + + # to be a goatvote poll: + # the name must have "GoatVote:" prepended + # the poster must have siteadmin:goatvote + # after that, we don't care. but if a poll is in this format, we can process + # the data as if it's a goatvote poll. + + # load the questions + return 0 unless $po->{name} =~ /^GoatVote:/i; + + # now check user permissions + my $u = LJ::load_userid($po->{posterid}); + return 0 unless LJ::check_priv($u, 'siteadmin', 'goatvote'); + + # now make sure the format is right + @$qs = sort { $a->{pollqid} <=> $b->{pollqid} } @$qs; + + # check one two... + return 0 unless scalar @$qs >= 2; + return 0 unless $qs->[0]{type} eq 'radio'; + return 0 unless $qs->[1]{type} eq 'text'; + + # okay, it is! + return 1; +} + +sub expresslane_html_comment { + my ($u, $r) = @_; + return '' unless $r && $u && LJ::get_cap($u, 'paid'); + + my ($free_ct, $free_age) = ($r->header_in('X-Queue-Count')+0, $r->header_in('X-Queue-Age')+0); + return "\n"; +}; + +LJ::register_setter("latest_optout", sub { + &LJ::nodb; + my ($u, $remote, $key, $value, $err) = @_; + + unless ($value =~ /^(?:yes|no)$/i) { + $$err = "Illegal value. Must be 'yes' or 'no'."; + return 0; + } + + $value = lc $value eq 'yes' ? 1 : 0; + LJ::set_userprop($u, "latest_optout", $value); + return 1; +}); + +LJ::register_setter("no_mail_alias", sub { + &LJ::nodb; + my ($u, $remote, $key, $value, $err) = @_; + + my $dbh = LJ::get_db_writer(); + + unless ($value =~ /^[01]$/) { + $$err = "Illegal value. Must be '0' or '1'."; + return 0; + } + + if ($value) { + $dbh->do("DELETE FROM email_aliases WHERE alias=?", undef, + "$u->{'user'}\@$LJ::USER_DOMAIN"); + } elsif ($u->{'status'} eq "A" && LJ::get_cap($u, "useremail")) { + $dbh->do("REPLACE INTO email_aliases (alias, rcpt) VALUES (?,?)", + undef, "$u->{'user'}\@$LJ::USER_DOMAIN", $u->{'email'}); + } + + LJ::set_userprop($u, "no_mail_alias", $value); + return 1; +}); + +LJ::clear_hooks(); + +LJ::register_hook("name_caps", \&acct_name); +LJ::register_hook("name_caps_short", \&acct_name_short); +LJ::register_hook('s2_head_content_extra', \&expresslane_html_comment); + +# if a user gets marked underage, we need to clear out their personally +# identifying information +LJ::register_hook('set_underage', sub { + my $opts = shift; + return unless $opts->{on}; # only care if turned on + + # update records in the user table + my $u = $opts->{u}; + LJ::update_user($u, { + name => $u->{user}, + bdate => undef, + allow_infoshow => 'N', + allow_contactshow => 'N', + has_bio => 'N', + txtmsg_status => 'off', + status => 'T', + }); + + # the only thing we have left on + return if $u->{statusvis} eq 'X'; + + # now empty their bio information + $u->do("DELETE FROM userbio WHERE userid=?", undef, $u->{'userid'}); + $u->dudata_set('B', 0, 0); + + # clear a ton of userprops + my @toclear = qw( + country state city zip icq aolim yahoo msn + url urlname gender jabber journaltitle journalsubtitle + friendspagetitle external_foaf_url + ); + foreach my $prop (@toclear) { + LJ::set_userprop($u, $prop, undef); + } +}); + +# hook to handle creating a button to email someone about spam +LJ::register_hook('spamreport_notification', sub { + my ($remote, $opts) = @_; + + # they can send in either 'ip => foo' or 'posterid => foo' but we + # only care about posterid for now + my $posterid; + return unless $posterid = $opts->{posterid}; + my $poster = LJ::want_user($posterid); + + # verify we got the remote user and a poster + $remote = LJ::want_user($remote); + return undef unless $remote && $poster; + + if ($poster->openid_identity) { + return "

    WARNING: The account you are viewing (" . + LJ::ljuser($poster) . ") is an OpenID identity and has no email address.

    "; + } + + # step 1) find related users by email + my $dbr = LJ::get_db_reader(); + return "" + unless $dbr; + my $users = $dbr->selectall_hashref('SELECT * FROM user WHERE email = ?', 'userid', undef, $poster->{email}); + return "" + unless $users && ref $users eq 'HASH' && %$users; + + # now see if any of these have been warned + my $in = join(',', map { ref $_ ? ($_->{userid} + 0) : 0 } values %$users); + my $warnings = $dbr->selectall_arrayref("SELECT adminid, shdate, userid FROM statushistory " . + "WHERE userid IN ($in) AND shtype = 'spam_warning'"); + return "" + if $dbr->err || !defined $warnings; + + # now construct html + my ($ret, %emailcounts, %emails); + foreach my $warning (@$warnings) { + my $date = $warning->[1]; + if ($date =~ /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) { + $date = "$1-$2-$3 $4:$5:$6"; + } + my $admin = LJ::load_userid($warning->[0]); + my $warned = LJ::load_userid($warning->[2]); + + # come up with notes about this warning + my $notes = 'none'; + if (LJ::u_equals($poster, $warned)) { + $notes = 'user match'; + } elsif (lc $poster->{email} eq lc $warned->{email}) { + $notes = 'email match'; + if ($warned->{status} ne 'A') { + $notes .= ' (unvalidated email)'; + } + } + + # query if we haven't queried based on this email address before + if (!$emailcounts{$warned->{email}}) { + my $rows = $dbr->selectall_arrayref("SELECT mailid, userid, timesent, subject FROM abuse_mail " . + "WHERE type='abuse' AND mailto = ?", undef, $warned->{email}); + $emailcounts{$warned->{email}} = 1; + + foreach my $row (@{$rows || []}) { + my ($mailid, $userid, $timesent, $subject) = @$row; + my $u = LJ::load_userid($userid); + + $emails{$timesent} = "$timesent$warned->{email}" . + LJ::ljuser($u) . "" . + "$subject\n"; + } + } + + # now construct output + $ret .= "$date" . LJ::ljuser($admin) . "" . LJ::ljuser($warned) . ""; + $ret .= "$notes\n"; + } + my $cols = join('', map { "$_" } qw(Date Admin Warned Notes) ); + $ret = "$cols$ret
    " if $ret; + + # now append emails + if (%emails) { + $ret .= ""; + $ret .= "" . join('', map { "" } qw(Date Email Admin Subject) ) . ""; + $ret .= join('', map { $emails{$_} } sort { $a cmp $b } keys %emails); + $ret .= "
    $_
    "; + } + + # get message to put into body for sending + my $message = LJ::load_include('spam-warning'); + $message =~ s/\[\[user\]\]/$poster->{user}/ig; + + # now construct the parts of the email + $ret .= "
    "; + $ret .= LJ::html_hidden(email => $poster->{email}, + bcc => $remote->{email}, + subject => "Your LiveJournal Account", + request => '000000', + message => $message, + extra => "spam-notification;$poster->{userid}", + from => "abuse",); + $ret .= '

    ' . LJ::html_submit('Send Warning Email') . '

    '; + + # include unvalidated email warning + unless ($poster->{status} eq 'A') { + $ret .= "

    WARNING: The account you are viewing (" . + LJ::ljuser($poster) . ") has an unvalidated email address.

    "; + } + + # return + $ret = "

    "; + return $ret; +}); + + +### Fetch the value for the given I from the specified I, +### untaint it with the given I, and return the results. If the +### I has match-groups in it, the values matched with them will be the +### returned values. Otherwise, the entire input will be returned. +sub untaint { + my ( $arghash, $field, $pattern ) = @_; + + return '' unless exists $arghash->{$field} && defined $arghash->{$field}; + my $input = $arghash->{$field}; + $pattern = qr{$pattern}i unless ref $pattern eq 'Regexp'; + + my @matches = ( $input =~ $pattern ) or return ''; + return @matches if $1; + return $input; +} + + +# hook to do transforms for posting pictures from FB +LJ::register_hook('transform_update_postpics', sub { + my ($GET, $POST) = @_; + + my ( + @ids, + $picsize, + $columns, + $caporient, + $border, + @pics, + @rows, + $row, + $nextrow, + $pic, + $imgtag, + $imgcell, + $capcell, + @html, + ); + + + # Untaint and split the picture ids to post + @ids = split /:/, $1 if exists $POST->{ids} && $POST->{ids} =~ m{^([\d:]+)}; + + return unless $POST->{'wizard-picsize'} =~ m{^([tsf])$}i; + $picsize = $1; + $columns = $1 if exists $POST->{'wizard-columns'} + && $POST->{'wizard-columns'} =~ m{^([1-4])$}; + $caporient = $1 if exists $POST->{'wizard-caporient'} + && $POST->{'wizard-caporient'} =~ m{^([arbl0])$}; + $border = 1 if $POST->{'wizard-border'}; + + # Default/bound some values if not defined or valid -- Large picsize + if ( $picsize eq 'f' ) { + $columns = 1; + } + + # Medium picsize + elsif ( $picsize eq 's' ) { + $columns = 1 if $columns < 1; + $columns = 2 if $columns > 2; + } + + # Thumbnail picsize + else { + $columns = 1 if $columns < 1; + $columns = 4 if $columns > 4; + } + + # Make sure the caption orientation will work with the number of columns + # defined. + if ( $columns == 1 || $columns == 3 ) { + $caporient = 'b' unless $caporient eq '0' || $caporient eq 'a'; + } + + # Build the array of ids to flow into the chosen layout + @pics = map {{ + id => $_, + captitle => untaint( $POST, "subj$_", qr{([\t\r\n\x20-\xff]*)} ), + capdesc => untaint( $POST, "desc$_", qr{([\t\r\n\x20-\xff]*)} ), + img => untaint( $POST, "${picsize}img$_", $LJ::REGEX{httpuri} ), + imgwidth => untaint( $POST, "${picsize}w$_", qr{(\d+)} ), + imgheight => untaint( $POST, "${picsize}h$_", qr{(\d+)} ), + url => untaint( $POST, "url$_", $LJ::REGEX{httpuri} ), + }} @ids; + + + # Build a table for the pics and their captions + while ( @pics ) { + $row = []; + $nextrow = []; + + # Fill up each row with the specified number of columns + while ( @$row < $columns ) { + $pic = shift @pics; + + # If there's a picture to add, do so + if ( $pic ) { + $imgtag = sprintf q{%s}, + @{$pic}{qw[img captitle imgheight imgwidth]}; + $imgcell = sprintf q{%s}, + $pic->{url}, $imgtag; + $capcell = sprintf qq{%s
    \n\t\t%s}, + @{$pic}{qw[captitle capdesc]}; + } + + # Otherwise it'll be a blank cell + else { + $imgcell = ''; + $capcell = ''; + } + + ## Now arrange the caption relative to the pic if there is a caption + + # Above + if ( $caporient eq 'a' ) { + push @$row, $capcell; + push @$nextrow, $imgcell; + } + + # Below + elsif ( $caporient eq 'b' ) { + push @$row, $imgcell; + push @$nextrow, $capcell; + } + + # Leftish captions, then the image, then rightish captions + else { + push @$row, $capcell if $caporient eq 'l'; + push @$row, $imgcell; + push @$row, $capcell if $caporient eq 'r'; + } + } + + push @rows, $row; + push @rows, $nextrow if @$nextrow; + } + + # Mangle the rows into an indented HTML table + @html = (); + + push @html, ( + " ", + " " + ); + foreach my $row ( @rows ) { + push @html, ( + " ", + (map { " " } @$row), + " ", + ); + } + push @html, "
    $_
    \n \n\n"; + + # Stick the results into the posted event + $POST->{event} = join "\n", @html; + return; +}); + +# hook to hit akamai to remove a userpic +LJ::register_hook('expunge_userpic', sub { + my ($picid, $userid) = @_; + $picid += 0; + $userid += 0; + return undef unless $picid && $userid; + + # now hit akamai + my $res = SOAP::Lite + ->service($LJ::AKAMAI{service}) + ->purgeRequest($LJ::AKAMAI{username}, $LJ::AKAMAI{password}, $LJ::AKAMAI{network}, + [''], ["$LJ::USERPIC_ROOT/$picid/$userid"]); + + # see if there was an error + my ($code, $msg) = ($res->{resultCode}, $res->{resultMsg}); + if ($code == 300) { + return [ 'info', "Akamai cache purged successfully." ]; + } else { + return [ 'error', "Error $code: $msg (CACHE NOT PURGED)" ]; + } +}); + +# cluster definition hook +LJ::register_hook('cluster_description', sub { + my $clusterid = $_[0]+0; + my ($ob, $cb) = $_[1] ? ('', '') : ('', ''); + + my ($cid, $scid) = ($clusterid, undef); + ($cid, $scid) = ($1, $2) if $clusterid =~ /^(\d)(\d+)$/; + + my $text = $ob . ($LJ::CLUSTERNAME{$cid} || $cid) . $cb; + $text .= ", subcluster $ob$scid$cb" if defined $scid; + return $text; +}); + +# hook to override show_poll for GoatVote polls +LJ::register_hook('alternate_show_poll_html', sub { + my ($po, $mode, $qs) = @_; + + # if mode is enter, we don't handle + return undef if $mode eq 'enter'; + + # if it's not a goatvote... + return undef unless LJ::LJcom::is_goatvote_poll($po, $qs); + + # return a link to the goatvote page + LJ::Poll::clean_poll(\$po->{name}) if $po->{name}; + my $ret = "{pollid}\">Poll \#$po->{pollid}:" . + " $po->{name}
    Open to: $po->{whovote}, results viewable " . + "to: $po->{whoview}
    This is a GoatVote poll. Current results are " . + "{pollid}\">available elsewhere. You " . + "can also {pollid}&mode=enter\">fill out the poll."; + return $ret; +}); + +# extra viewing line HTML +LJ::register_hook('extra_poll_description', sub { + my ($po, $qs) = @_; + + # if it's a goatvote + return '' unless LJ::LJcom::is_goatvote_poll($po, $qs); + + # okay return our string + return "You may view the {pollid}\">" . + 'GoatVote results in progress.'; +}); + +# hook to show goatvote in poll pregenerator +LJ::register_hook('poll_pregeneration_html', sub { + my ($u, $is_authas) = @_; + return unless LJ::check_priv($u, 'siteadmin', 'goatvote'); + + # okay, show them the options + my $getextra = $is_authas ? "authas=$u->{'user'}&" : ''; + my $body = ""; + $body .= ""; + $body .= ""; + return $body; +}); + +# actually pregenerate a poll +LJ::register_hook('pregenerate_poll', sub { + my ($u, $pgid) = @_; + return undef unless $pgid && LJ::check_priv($u, 'siteadmin', 'goatvote'); # only one option for now + + # throw a goatvoate together + if ($pgid == 1) { + return { + count => 3, + name => 'GoatVote: ', + whovote => 'all', + whoview => 'all', + pq => [ + { + type => 'radio', + question => 'What point of view do you most agree with?', + opts => 5, + opt => [ '', '', '', '', '' ], + }, { + type => 'text', + question => 'What URL supports this point of view best?', + size => 30, + maxlength => 255, + }, { + type => 'text', + question => 'What other URL supports this point of view?', + size => 30, + maxlength => 255, + } + ], + }; + } + + # caller expects a hashref + return {}; +}); + +LJ::register_hook("get_cap_bit", sub { + my $name = shift; + return undef unless $name; + + return $LJ::Pay::capinf{$name}->{'bit'}; +}); + +# Register hooks for turning on/off certain cap bits +# This needs to be expanded to activate/deactivate bonus +# features, etc, but right now we just be sure to run +# LJ::activate_userpics() +LJ::register_hook("modify_caps", sub { + my $arg = shift; + + # 1-4 = free-perm, 9 = extra userpics + foreach (1..4, 9) { + next unless $arg->{'cap_on_mod'}->{$_} || $arg->{'cap_off_mod'}->{$_}; + + # only run once, with newest caps... + $arg->{'u'}->{'caps'} = $arg->{'newcaps'}; + return LJ::activate_userpics($arg->{'u'}); + } + + return 1; +}); + +# check for a user diskquota cap. returning undef defers the check to normal means +LJ::register_hook("check_cap_disk_quota", sub { + my $u = shift; + return undef unless $u; + + my $dbr = LJ::get_db_reader(); + my $size = $dbr->selectrow_array("SELECT size FROM paidexp WHERE userid=? AND item='diskquota'", + undef, $u->{'userid'}); + return $size || undef; +}); + +LJ::register_hook("ssl_check", sub { + my $r = $_[0]{r}; + return + $r->header_in("X-LJ-SSL") || + ($LJ::IS_DEV_SERVER && $r->header_in("Host") eq "secure.$LJ::DOMAIN"); +}); + +LJ::register_hook("post_create", \&LJ::Pay::post_create); + +LJ::register_hook("create.bml_opts", sub { + my $ar = shift; + my $ret = $ar->{ret}; + my $get = $ar->{get}; + my $post = $ar->{post}; + + $$ret .= "
  • $BML::ML{'ljcom.accounttype'}
    "; + $$ret .= "
    "; + + my $valid_code = 0; + my $code = $get->{code} || $post->{code}; + if ($code) { + my $dbr = LJ::get_db_reader(); + my ($acid, $auth) = LJ::acct_code_decode($code); + + if (my $piid = $dbr->selectrow_array("SELECT piid FROM acctpayitem WHERE acid=?", + undef, $acid)) + { + my ($item, $qty) = $dbr->selectrow_array("SELECT item, qty FROM payitems ". + "WHERE piid=?", undef, $piid); + + if ($item eq 'perm') { + $$ret .= "Permanent Account"; + } else { + $$ret .= "Paid for " . ($qty+0) . " Months"; + } + $$ret .= ", from code: $code"; + + $valid_code++; + } + } + + unless ($valid_code) { + my @atypes = ([ 0, $BML::ML{'ljcom.account.free'} ], + [ 2, $BML::ML{'ljcom.account.paid2'} ], + [ 6, $BML::ML{'ljcom.account.paid6'} ], + [ 12, $BML::ML{'ljcom.account.paid12'} ]); + + my $cur_type = $post->{'ljcom_atype'}+0; + foreach my $at (@atypes) { + $$ret .= LJ::html_check({ name => 'ljcom_atype', id => "ljcom_atype_$at->[0]", + value => $at->[0], + type => 'radio', selected => ($cur_type == $at->[0]) }); + $$ret .= "
    \n"; + } + } + + $$ret .= "
    "; + + + # if they've already got a code for paid time, no reason to show the feature list + return if $valid_code; + + $$ret .= ' + + + + + + +'; + + my @features = ( + [ "$BML::ML{'ljcom.account.feature.ownblog'}", "Y", "Y" ], + [ "$BML::ML{'ljcom.account.feature.styles'}", "$BML::ML{'ljcom.account.feature.limit'}", "Y" ], + [ "$BML::ML{'ljcom.account.feature.syn'}", "Y", "Y" ], + [ "$BML::ML{'ljcom.account.feature.pp'}", "N", "Y" ], + [ "$BML::ML{'ljcom.account.feature.search'}", "N", "Y" ], + [ "$BML::ML{'ljcom.account.feature.photo'}", "N", "Y" ], + + ); + my %map = ("N" => "-", + "Y"=> "Yes"); + foreach my $f (@features) { + my ($name, $free, $paid) = @$f; + $free = $map{$free} || $free; + $paid = $map{$paid} || $paid; + $$ret .= "". + "". + "\n"; + } + $$ret .= "
    '.$BML::ML{'ljcom.account.feature'}.''.$BML::ML{'ljcom.account.free'}.''.$BML::ML{'ljcom.account.paid'}.'
    $name$free$paid
    " . + BML::ml('ljcom.account.feature.full2', { aopts => "target='_new' href='$LJ::SITEROOT/site/accounts.bml'" }) . + "
    \n"; + + $$ret .= "
  • "; + + return; +}); + +LJ::register_hook("create.bml_postsession", sub { + my $ar = shift; + my $post = $ar->{post}; + my $redir = $ar->{redirect}; + my $u = $ar->{u}; + + my $atype = int($post->{'ljcom_atype'}); + $atype = 0 unless $LJ::Pay::account{$atype}; + LJ::set_userprop($u, "create_accttype", $atype || "free"); + return unless $atype || $u->underage; + + my $cartobj = LJ::Pay::new_cart($u); + my $rv = LJ::Pay::add_cart_item($cartobj, { + item => 'paidacct', + qty => $post->{ljcom_atype}, + amt => $LJ::Pay::account{$atype}->{amount}, + rcptid => $u->{userid}, + }) if $atype; + my $rv2 = LJ::Pay::add_cart_item($cartobj, { + item => 'coppa', + rcptid => $u->{userid}, + }) if $u->underage; + if ($cartobj && ($rv || !$atype) && ($rv2 || !$u->underage)) { + my $c = $cartobj->{payid} . "-" . $cartobj->{anum}; + if ($u->underage) { + my $extra = $u->underage_status eq 'O' ? '&o=1' : ''; + $$redir = "$LJ::SITEROOT/agecheck/?c=$c$extra"; + } else { + $$redir = "$LJ::SITEROOT/pay/?c=$c"; + } + } +}); + +LJ::register_hook("userinfo_rows", sub { + my $args = shift; + my $u = $args->{'u'}; + my $dbr = $args->{'dbr'}; + my $remote = $args->{'remote'}; + my @ret; + return if $u->{journaltype} eq "I"; + $ret[0] = "$BML::ML{'ljcom.userinfo.accounttype'}"; + + my $paid = $u->{'caps'} & 8; + my $perm = $u->{'caps'} & 16; + if ($remote && $paid && ! $perm && + ($remote->{'userid'} == $u->{'userid'} || + $u->{'journaltype'} ne 'P' && + LJ::check_rel($u->{'userid'}, $remote->{'userid'}, 'A'))) + { + my $paiduntil = $dbr->selectrow_array("SELECT paiduntil FROM paiduser ". + "WHERE userid=$u->{'userid'}"); + $ret[1] = LJ::LJcom::acct_name($u->{'caps'}, substr($paiduntil, 0, 10)); + } else { + $ret[1] = LJ::LJcom::acct_name($u->{'caps'}); + } + return @ret; +}); + +LJ::register_hook("update.bml_disable_can_post", sub { + my $arg = shift; + ${$arg->{title}} = "Trial account expired"; + ${$arg->{body}} = "Your 30 day LiveJournal trial account has expired. For more information on what you can do at this point, check out the LiveJournal Trial Page."; + return 1; +}); + + +LJ::register_hook("login_add_opts", sub { + my $args = shift; + my $u = $args->{'u'}; + my $form = $args->{'form'}; + my $optref = $args->{'opts'}; + + if (LJ::get_cap($u, "fastserver") && ! $form->{'notfast'}) { + push @$optref, "FS"; # fast server + } +}); + +LJ::register_hook("post_logout", sub { + my $site_domain = $LJ::SITEROOT; + $site_domain =~ s!^\w+://!!; + $site_domain =~ s!(:\d+)?/.*!!; + + # feb-24-2003: fastserver cookie is now unused, but we'll delete it for awhile + foreach (qw(ljfastserver betatest)) { + BML::set_cookie($_, "", undef, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + } +}); + +LJ::register_hook("userinfo_html_by_user", sub { + my $o = shift; + my $r = $o->{'ret'}; + my $u = $o->{'u'}; + return unless (LJ::get_cap($u, "paid")); + $$r .= "$BML::ML{"; +}); + +LJ::register_hook("userinfo_local_props", sub { + my $o = shift; + push @{$o->{props}}, 'no_mail_alias'; +}); + +LJ::register_hook("canonicalize_url", sub { + my $u = shift; + $$u =~ s!^http://livejournal\.com!http://www.livejournal.com!; + if ($$u =~ m!^http://www\.livejournal\.com!) { + $$u =~ s!&nc=\d+!!; + } + + foreach my $pattern (qw( + \.(jpg|jpeg|gif|png)$ + selectsmart\.com + /test + /quiz + quiz\.html + test\.html + elitechild\.com + livejournal\.com/user + )) + { + next unless $$u =~ /$pattern/i; + $$u = ""; + return; + } + + # strip anchor names (to prevent some online tests from showing up + # a billion times) + $$u =~ s/\#.+//; +}); + +LJ::register_hook("expand_embedded", sub { + LJ::PhonePost::show_phoneposts(@_); +}); + +LJ::register_hook("url_phonepost", sub { + my ($u, $dppid, $ext) = @_; + my $host = $LJ::FILES_DOMAIN || "files.livejournal.com"; + return "http://$host/$u->{'user'}/phonepost/$dppid.$ext"; +}); + +LJ::register_hook("data_handler:phonepost", sub { + my ($user, $pathextra) = @_; + if ($pathextra =~ m#^/(\d+)\.(mp3|ogg|wav)$#) { + my $dppid = $1; + return sub { + my $r = shift; + my $u = LJ::load_user($user); + return LJ::PhonePost::apache_content($r, $u, $dppid); + }; + } + return undef; +}); + +LJ::register_hook("files_handler:phonepost", sub { + my ($user, $pathextra) = @_; + if ($pathextra =~ m#^/(\d+)\.(mp3|ogg|wav)$#) { + my $dppid = $1; + return sub { + my $r = shift; + my $u = LJ::load_user($user); + return LJ::PhonePost::apache_content($r, $u, $dppid); + }; + } + return undef; +}); + +LJ::register_hook("modify_login_menu", sub { + my $a = shift; + my $u = $a->{'u'}; + my $user = $a->{'user'}; + my $menu = $a->{'menu'}; + + unless ($u->{'caps'} & (8|4)) { # unless perm or paid + LJ::load_user_props($u, 'browselang'); + my $text = LJ::Lang::get_text($u->{'browselang'}, 'ljcom.menu.upgrade'); + push @$menu, { 'text' => $text, + 'url' => "$LJ::SITEROOT/paidaccounts/", }; + } +}); + +LJ::register_hook("validate_get_remote", sub { + my $a = shift; + my $caps = $a->{'caps'}; + my $criterr = $a->{'criterr'}; + my $sopts = $a->{'sopts'}; + + if ($sopts =~ /\.FS\b/ && ! LJ::get_cap($caps, 'fastserver')) { + $$criterr = 1; # forged fastserver session option! + return 0; + } + + return 1; +}); + +LJ::register_hook("emailconfirmed", sub { + &LJ::nodb; + my ($u) = @_; + return unless LJ::get_cap($u, "useremail"); + return if exists $LJ::FIXED_ALIAS{$u->{'user'}}; + + LJ::load_user_props($u, { 'use_master' => 1 }, "no_mail_alias"); + return if $u->{'no_mail_alias'}; + + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO email_aliases (alias, rcpt) VALUES (?,?)", + undef, "$u->{'user'}\@$LJ::USER_DOMAIN", $u->{'email'}); +}); + +LJ::register_hook("bad_password", sub { + return undef if $LJ::NO_PASSWORD_CHECK; + + my $arg = shift; + my $u = ref $arg eq 'HASH' ? $arg : undef; + + # only scalar password passed + unless ($u) { + return undef unless $LJ::OPTMOD_CRACKLIB; + my $reason = Crypt::Cracklib::fascist_check($arg); + return $reason eq 'ok' ? undef : $reason; + } + + # u hashref passed + my $reason = $LJ::OPTMOD_CRACKLIB ? + Crypt::Cracklib::fascist_check($u->{'password'}) : "ok"; + return $reason unless $reason eq 'ok'; + + # we have a $u passed, we can do smart checking + my $user = lc($u->{'user'}); + my $pass = lc($u->{'password'}); + my $email = lc($u->{'email'}); + my $name = lc($u->{'name'}); + my $ml_code = undef; + + # username matches + if ($user && (index($pass, $user) >= 0 || index($user, $pass) >= 0)) { + $ml_code = 'ljcom.badpass.username'; + } + + # email matches + elsif ($email && (index($pass, $email) >= 0 || index($email, $pass) >= 0)) { + $ml_code = 'ljcom.badpass.email'; + } + + # real name matches + elsif ($name && (index($pass, $name) >= 0 || index ($name, $pass) >= 0)) { + $ml_code = 'ljcom.badpass.realname'; + } + + if ($ml_code) { + LJ::load_user_props($u, 'browselang'); + return LJ::Lang::get_text($u->{'lang'}, $ml_code); + } + + # no match + return undef; + +}); + +# meetup links +LJ::register_hook("interests_bml", sub { + my $arg = shift; + my $db = LJ::get_db_reader(); + my $r = $db->selectrow_hashref("SELECT urlkey, name FROM meetup_ints WHERE intid=?", undef, + $arg->{'intid'}); + return unless $r; + my $ret = $arg->{'ret'}; + my $name = LJ::ehtml($r->{'name'}); + my $urlargs; + my $remote = $arg->{'remote'}; + if ($remote) { + LJ::load_user_props($db, $remote, "zip"); + if ($remote->{'zip'}) { + $urlargs .= "?zip=$remote->{'zip'}"; + } + } + my $moreinfo; + if ($LJ::HELPURL{'meetup'}) { + $moreinfo = BML::ml('ljcom.meetup.moreinfo', {'link' => $LJ::HELPURL{'meetup'}}); + } + my $link = "{'urlkey'}.meetup.com/$urlargs\">"; + $link .= BML::ml('ljcom.meetup.link', { 'name' => $name}) . ""; + $$ret .= ""; + $$ret .= " $link }) . " $moreinfo p?>"; +}); + +sub LJ::is_utf8 { + return isLegalUTF8String($_[0], length($_[0])); +} + +LJ::register_hook("s1_style_select", sub { + my $arg = shift; + my $styleid = $arg->{'styleid'}; + my $u = $arg->{'u'}; + if ($arg->{'view'} eq "lastn" && $u->{'journaltype'} eq "Y" && $u->{'password'} eq "" && + $LJ::SYN_LASTN_S1) { + $$styleid = $LJ::SYN_LASTN_S1; + } +}); + +LJ::register_hook("force_s1", sub { + my $u = shift; + my $forceflag = shift; + + # Force syndicated accounts to S1 + if ( $u->{journaltype} eq 'Y' ) { + $$forceflag = 1; + } +}); + +LJ::register_hook("finduser_extrainfo", sub { + my $arg = shift; + my $u = $arg->{'u'}; + my $dbh = $arg->{'dbh'}; + my $ret; + if ($u->{'caps'} & 16) { + $ret .= " Permanent account.\n"; + } + if ($u->{'caps'} & 8) { + my $unt = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=?", undef, + $u->{'userid'}); + $ret .= " Paid until: $unt\n"; + } +}); + +LJ::register_hook("support_see_request_html", sub { + my $arg = shift; + my $sp = $arg->{'sp'}; + my $cat = $sp->{_cat}->{'catkey'}; + my $ret = $arg->{'retref'}; + my $email = $arg->{'email'}; + my $u = $arg->{'u'}; + my $remote = $arg->{'remote'}; + + my $manage = LJ::remote_has_priv($remote, "moneysearch") || LJ::remote_has_priv($remote, "moneyview"); + + if ($cat eq "accounts" && $manage) { + $$ret .= "

    "; + $$ret .= "[paidsearch: email] "; + if ($sp->{'requserid'}) { + $$ret .= "[paidsearch: user] "; + } + $$ret .= "

    "; + } + +}); + +LJ::register_hook("recent_action_flags", sub { + # these flags live in their own site-local namespace + # and must be prepended with '_' to avoid collisions + + return { phonepost => '_F', # 'F'onepost, meh + phonepost_mp3 => '_M' }->{$_[0]}; # 'M'p3 +}); + +LJ::register_hook("postpost", sub { + my $arg = shift; + my $uo = $arg->{'journal'}; + return if $uo->{'journaltype'} eq "Y"; # no syndicated + my $up = $arg->{'poster'}; + + # if the poster has opted out, don't record the post + LJ::load_user_props($up, "latest_optout"); + return if $up->{latest_optout}; + + # setup security + my $security = $arg->{'security'}; + $security = $arg->{'allowmask'} == 1 ? 'friends' : 'custom' + if ($security eq 'usemask'); + + # see if it has a public image in it. heuristic: it's an http:// + # URL in an image tag, or it's alone and has a popular image extension + my $img; + if ($security eq "public" && + ($arg->{'event'} =~ m!{'event'} =~ m!\'\"]!i || + $arg->{'event'} =~ m!(http://\S+\.(?:gif|jpe?g|png)\b)!i)) { + $img = $2 || $1; + + # make sure image is good and hasn't been used in last 4 hours + unless (length($img) < 100 && $img !~ /[\n\r]/ && + LJ::MemCache::add("ljcom_imgused:$img", 1, 3600*4)) { + undef $img; + } + } + + LJ::cmd_buffer_add($uo->{clusterid}, $uo->{'userid'}, "ljcom_newpost", { + 'timepost' => time(), + 'journalid' => $uo->{'userid'}, + 'posterid' => $up->{'userid'}, + 'itemid' => $arg->{'itemid'}, + 'anum' => $arg->{'anum'}, + 'security' => $security, + 'img' => $img, + 'taglist' => $arg->{'props'}->{'taglist'}, + }); +}); + +# TEMP: Log unknown8bit posts to decide if they can be disabled later +# see also table definition in update-db-local.pl +LJ::register_hook("postpost", sub { + my $entry = shift; + return unless $LJ::DEBUG{'survey_8bit'} && $entry->{'props'}->{'unknown8bit'}; + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO survey_v0_8bit (userid, timepost) VALUES (?, UNIX_TIMESTAMP())", + undef, $entry->{'poster'}->{'userid'}); +}); + +LJ::register_hook("cmdbuf:ljcom_newpost:start", sub { + my ($dbh) = @_; + $LJ::CACHE_RECENTPOSTS_CHANGES = 0; + $LJ::CACHE_RECENTPOSTS ||= LJ::MemCache::get("blob:ljcom_latestposts2") || []; + + $LJ::CACHE_RECENTIMG_CHANGES = 0; + $LJ::CACHE_RECENTIMG ||= LJ::MemCache::get("blob:ljcom_latestimg") || []; +}); + +LJ::register_hook("cmdbuf:ljcom_newpost:too_old", sub { 60*60*2 }); + +LJ::register_hook("cmdbuf:ljcom_newpost:run", sub { + my ($dbh, $db, $c) = @_; + my $args = $c->{'args'}; + + my $recent = $LJ::CACHE_RECENTPOSTS; + my $uj = LJ::load_userid($args->{'journalid'}); + my $up = LJ::load_userid($args->{'posterid'}); + return unless $uj->{'statusvis'} eq "V" && $up->{'statusvis'} eq "V"; + + LJ::load_user_props($uj, "journaltitle"); + + my $rp = {}; + $rp->{$_} = $args->{$_}+0 foreach qw(timepost itemid anum); + $rp->{security} = $args->{security}; + $rp->{clusterid} = $up->{clusterid}+0; + $rp->{tags} = [ split(/\s*,\s*/, $args->{taglist}) ]; + $rp->{journalu} = { + user => $uj->{user}, + userid => $uj->{userid}+0, + journaltype => $uj->{journaltype}, + }, + $rp->{journalp} = { + user => $up->{user}, + userid => $up->{userid}+0, + name => $up->{name}, + }; + + push @$recent, $rp; + $LJ::CACHE_RECENTPOSTS_CHANGES++; + + if ($args->{'img'}) { + my $rimg = $LJ::CACHE_RECENTIMG; + push @$rimg, [ $args->{'img'}, $rp->{journalu}, $args->{'itemid'}, $args->{'anum'} ]; + $LJ::CACHE_RECENTIMG_CHANGES++; + } +}); + +LJ::register_hook("cmdbuf:ljcom_newpost:finish", sub { + my ($dbh) = @_; + return unless $LJ::CACHE_RECENTPOSTS_CHANGES; + my $recent = $LJ::CACHE_RECENTPOSTS; + my $rimg = $LJ::CACHE_RECENTIMG; + + my $show_max = $LJ::STATS_LATESTPOSTS_MAX || 1000; + + @$recent = sort { $b->{'timepost'} <=> $a->{'timepost'} } @$recent; + splice(@$recent, $show_max) if @$recent > $show_max; + + LJ::MemCache::set("blob:ljcom_latestposts2", $recent); + + if ($LJ::CACHE_RECENTIMG_CHANGES) { + my $size = @$rimg; + splice(@$rimg, 0, $size - $show_max) if $size > $show_max; + LJ::MemCache::set("blob:ljcom_latestimg", $rimg); + } + LJ::MemCache::set("blob:ljcom_latestposts_stats", + [ scalar(@$recent), + $recent->[0]->{timepost}, + $recent->[-1]->{timepost} ]); +}); + +# returns 1 if too fast, 0 if okay +LJ::register_hook("ccpay_rate_check", sub { + my ($tries, $lasttry) = @_; + + # TRIES : LIMIT + # - 1.. 3: 0 sec + # - 4.. 6: 5 sec + # - 7..10: 15 sec + # - 11..19: 60 sec + # - 20....: 30 min + + my $now = time(); + return 0 if $tries <= 3; + return 0 if $tries <= 6 && $lasttry < $now - 5; + return 0 if $tries <= 10 && $lasttry < $now - 15; + return 0 if $tries <= 19 && $lasttry < $now - 60; + return 0 if $lasttry < $now - 1800; + return 1; +}); + +LJ::register_hook("cmdbuf:pay_fb_xmlrpc:run", sub { + my ($dbh, $db, $c) = @_; + + return undef unless $LJ::FB_SITEROOT && $LJ::FB_QUOTA_NOTIFY; + + my $args = $c->{args}; + my $userid = $c->{journalid}; + + # args: item, size, exp + + my $u = LJ::load_userid($userid); + return undef unless $u; + + eval "use XMLRPC::Lite (); 1;" + or return undef; + + return XMLRPC::Lite + ->new( proxy => "$LJ::FB_SITEROOT/interface/xmlrpc", + timeout => 5 ) + ->call('FB.XMLRPC.set_quota', # xml-rpc method call + { user => $u->{user}, + item => $args->{item}, + size => $args->{size}, + exptime => $args->{exptime}, + }); +}); + +# given an S2 context, give back a BML langid. +LJ::register_hook("set_s2bml_lang", sub { + my ($ctx, $langref) = @_; + + my $lang = S2::get_property_value($ctx, 'lang_current'); + + $lang = 'en' unless grep(/$lang/, @LJ::LANGS); + $lang = 'en_LJ' if ($lang eq 'en'); + + $$langref = $lang; +}); + +# what tables bin/moveucluster.pl should move that aren't general code +LJ::register_hook("moveucluster_local_tables", sub { + return { + 'phonepostentry' => 'userid', + 'phoneposttrans' => 'journalid', + }; +}); + +# remove transcription group userprop +LJ::register_hook("delete_friend_group", sub { + my ($u, $bit) = @_; + LJ::load_user_props($u, 'pp_transallow'); + LJ::set_userprop($u, 'pp_transallow', -1) if $bit == $u->{pp_transallow}; +}); + +LJ::register_hook("userinfo_join_community", sub { + my $o = shift; + my $r = $o->{'ret'}; + my $u = $o->{'u'}; + $$r .= BML::ml('/userinfo.bml.membership.paidmembers') if $u->{'user'} eq "paidmembers"; + return; +}); + +LJ::register_hook("forbid_request", sub { + my $r = shift; + my $ua = $r->header_in("User-Agent"); + my $ip = $r->connection->remote_ip; + # @BAN_UA can be either scalar substrings of user-agents, or + # an arrayref of [ $substr, $ip ] which makes the substring + # match conditional on it matching that IP + foreach (@LJ::BAN_UA) { + if (ref) { + return 1 if $_->[1] eq $ip && index($ua, $_->[0]) != -1; + } else { + return 1 if index($ua, $_) != -1; + } + } + return 0; +}); + +LJ::register_hook("bot_director", sub { + my ($pre, $post) = @_; + return "$pre If you are running a bot please visit this policy page outlining rules you must respect. $LJ::SITEROOT/bots/ $post" +}); + +# control panel nag box +LJ::register_hook('control_panel_extra_info', sub { + my ($u, $ret) = @_; + + $$ret .= "
    "; + if (LJ::get_cap($u, "paid")) { + $$ret .= "For a complete summary of the LiveJournal.com services to which you are currently subscribed, visit the "; + $$ret .= "Paid Account Status page."; + # render account summary + $$ret .= LJ::Pay::account_summary($u); + } else { + $$ret .= "Nearly all of LiveJournal's functionality is available free of charge. However, if you're happy "; + $$ret .= "with the service you're being provided, we encourage you to show your support and get a "; + $$ret .= "paid account."; + } + $$ret .= "
    "; +}); + +# control panel extra column +LJ::register_hook('control_panel_column', sub { + my ($u, $ret) = @_; + my $authas = ref $u ? "?authas=$u->{user}" : ""; + + $$ret .= BML::fill_template('block', { + 'HEADER' => "Paid Account Information", + 'ABOUT' => "Additional information and options for paid accounts.", + 'LIST' => "
  • Paid Account Status
  • ". + "
  • File Manager
  • ". + "
  • " + }); +}); + +LJ::register_hook('entryforminfo', sub { + my $ret .= "
    "; + + $ret .= "Paid account options:"; + $ret .= ""; + + $ret .= ""; + + $ret .= "Download a client:"; + + $ret .= "
    \n"; + return $ret; +}); + +# args: { userid , ppid } +# appends enclosure or "" to rss $ret string +LJ::register_hook('pp_rss_enclosure', sub { + my $opts = shift; + return LJ::PhonePost::make_link( undef, $opts->{userid}, + ( $opts->{ppid} >> 8 ), 'rss' ); +}); + +# args: name +# return: formatted name for local config +LJ::register_hook('identity_display_name', sub { + my $name = shift; + $name =~ s/\[(live|dead)journal\.com\]/\[${1}journal\]/; + $name =~ s/^(.+)\.(live|dead)journal\.com$/${1} \[${2}journal\]/; + + return $name; +}); + +LJ::register_hook('offsite_journal_search', sub { + my $u = shift; + my $ret; + + my $user = LJ::ehtml($u->{'user'}); + + $ret .= qq{ + + Note: This search is provided by an independent company, LJSeek, and is provided solely as a convenience. We are not responsible for the resulting content or search results. + p?> + +
    + + + + + + + + + + + +
      
    + + +
    exact phrase
     
    + standout?> + }; + return $ret; +}); + +__DATA__ +__C__ + +/* + * Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +typedef unsigned char UTF8; +typedef unsigned char Boolean; + +#define false 0 +#define true 1 + +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static Boolean isLegalUTF8(UTF8 *source, int length) { + UTF8 a; + UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + if (*source > 0xF4) return false; + } + return true; +} + +/********************* End code from Unicode, Inc. ***************/ + +/* + * Author: Brad Fitzpatrick + * + */ + +Boolean isLegalUTF8String(char *str, int len) +{ + UTF8 *cp = str; + int i; + while (*cp) { + /* how many bytes follow this character? */ + int length = trailingBytesForUTF8[*cp]+1; + + /* check for early termination of string: */ + for (i=1; ihttpd_conf("DocumentRoot $LJ::HOME/ssldocs"); +Apache->httpd_conf("ServerAdmin $LJ::ADMIN_EMAIL") + if $LJ::ADMIN_EMAIL; + +Apache->httpd_conf(qq{ + + + UserDir disabled + + +PerlInitHandler +Apache::LiveJournal +PerlFixupHandler +Apache::CompressClientFixup +DirectoryIndex index.html index.bml +}); + +unless ($LJ::SERVER_TOTALLY_DOWN) +{ + Apache->httpd_conf(qq{ +# BML support: +PerlModule Apache::BML + + SetHandler perl-script + PerlHandler Apache::BML + + +# User-friendly error messages +ErrorDocument 404 /404-error.html +ErrorDocument 500 /500-error.html + +}); +} + +1; diff --git a/ljcom/cgi-bin/modperl_subs-local.pl b/ljcom/cgi-bin/modperl_subs-local.pl new file mode 100644 index 0000000..666b01b --- /dev/null +++ b/ljcom/cgi-bin/modperl_subs-local.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +# + +# site-local version of modperl_subs.pl + +package LJ::ModPerl; + +use strict; + +# pull in a lot of useful stuff before we fork children + +use lib "$ENV{'LJHOME'}/cgi-bin"; +use XMLRPC::Lite; # for cmdbuf:pay_fb_xmlrpc hook + +require "phonepost.pl"; +require "paylib.pl"; + +$LJ::OPTMOD_CRACKLIB = eval "use Crypt::Cracklib qw(); 1;"; +$Crypt::Cracklib::DICT = "$ENV{'LJHOME'}/cgi-bin/cracklib/dict"; + +$LJ::OPTMOD_GEOIP = eval "use Geo::IP::PurePerl (); 1;"; + +1; diff --git a/ljcom/cgi-bin/paylib.pl b/ljcom/cgi-bin/paylib.pl new file mode 100644 index 0000000..84bd014 --- /dev/null +++ b/ljcom/cgi-bin/paylib.pl @@ -0,0 +1,2946 @@ +#!/usr/bin/perl +# +# LiveJournal.com-specific library +# +# This file is NOT licensed under the GPL. As with everything in the +# "ljcom" CVS repository, this file is the property of Danga +# Interactive and is made available to the public only as a reference +# as to the best way to modify/extend the base LiveJournal server code +# (which is licensed under the GPL). +# +# Feel free to read and learn from things in "ljcom", but don't use it verbatim +# because we don't want your site looking like LiveJournal.com (our logo +# and site scheme are our identity and we don't want to confuse users) +# and we're sick of getting everybody's payment notifications when +# they use our payment system without any modifications. +# + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +package LJ::Pay; + +use strict; +use vars qw(%account %bonus %capinf @coupon %product %color %size); +use Time::Local (); # used by /paidaccounts/usepaypal.bml, at least. +use LWP; +use LWP::UserAgent; + +# hard-coded ljcom cap info + +%capinf = ( + 'new' => { 'bit' => 0, 'name' => 'New User' }, + 'free' => { 'bit' => 1, 'name' => 'Free User' }, + 'early' => { 'bit' => 2, 'name' => 'Early Adopter' }, + 'paid' => { 'bit' => 3, 'name' => 'Paid User' }, + 'perm' => { 'bit' => 4, 'name' => 'Permanent Account' }, + ); + +%account = ( + 2 => { 'name' => '2 months', 'amount' => 5 }, + 6 => { 'name' => '6 months', 'amount' => 15 }, + 12 => { 'name' => '12 months', 'amount' => 25 }, + ); + +# list of dollar amount +@coupon = (5, 15, 25); + +# bonus features are of 2 types: +# - "bool" are either on or off (userpics), 'cap' key is required +# - "sized" have a magnitude associated with them (how much disk quota) +%bonus = ( + # userpics are a 'bool' item + 'userpic' => { + 'name' => 'Extra Userpics', + 'type' => 'bool', + 'cap' => 9, # cap bit to activate for user + 'items' => { + # quantities + 2 => { 'name' => '2 months', 'amount' => 2 }, + 6 => { 'name' => '6 months', 'amount' => 6 }, + 12 => { 'name' => '12 months', 'amount' => 10 } + } + }, + + # disk quota is a 'sized' item + 'diskquota' => { + 'name' => 'Disk Quota', + 'type' => 'sized', + 'cap' => undef, # optional + 'apply_hook' => \&LJ::Pay::diskquota_apply_hook, + 'items' => { + # size => quantity (months) + # - prices are NOT determined. these are just made up numbers for testing. + 250 => { + 'name' => '250 MiB', + 'qty' => { + 2 => { 'name' => '2 months', 'amount' => 10 }, + 6 => { 'name' => '6 months', 'amount' => 20 }, + 12 => { 'name' => '12 months', 'amount' => 36 }, + } + }, + 500 => { + 'name' => '500 MiB', + 'qty' => { + 2 => { 'name' => '2 months', 'amount' => 20 }, + 6 => { 'name' => '6 months', 'amount' => 40 }, + 12 => { 'name' => '12 months', 'amount' => 72 }, + } + }, + 1024 => { + 'name' => '1024 MiB', + 'qty' => { + 2 => { 'name' => '2 months', 'amount' => 30 }, + 6 => { 'name' => '6 months', 'amount' => 60 }, + 12 => { 'name' => '12 months', 'amount' => 100 }, + } + }, + + } + } + ); + +# now allow a mechanism for individual bonus items to be disabled +foreach my $itemname (keys %bonus) { + next unless $LJ::DISABLED{"bonus-$itemname"}; + + delete $bonus{$itemname}; +} + +%product = ( + "clothes-short" => + [ "Short-Sleeved Shirt", [ qw(white black grey orange bluedusk leaf )]], + "clothes-long" => + [ "Long-Sleeved Shirt", [ qw(white black grey navyblue )]], + "clothes-polo" => + [ "Embroidered Polo Shirt", [ qw(white black grey navyblue )]], + "clothes-babydoll" => + [ "\"Baby Doll\" Fitted Shirt", [ qw(white black grey pink royalblue )]], + "clothes-hooded" => + [ "Hooded Sweatshirt", [ qw(grey black) ], "disable_coupons"], + "clothes-twillhat" => + [ "Stonewashed Cap", [ qw(khaki black navyblue) ]], + ); + +%color = ( + 'white' => "White", + 'black' => "Black", + 'grey' => "Grey", + 'navyblue' => "Navy Blue", + 'royalblue' => "Royal Blue", + 'bluedusk' => "Blue Dusk", + 'pink' => "Pink", + 'leaf' => "Leaf Green", + 'orange' => "Orange", + 'khaki' => "Khaki", + ); + +%size = ( + 'os' => [0, "One Size Fits All"], + 's' => [1, "Small"], + 'm' => [2, "Medium"], + 'l' => [3, "Large"], + 'xl' => [4, "X-Large"], + 'xxl' => [5, "XX-Large"], + '3xl' => [6, "3X-Large"], + '4xl' => [7, "4X-Large"], + ); + +## hook called from create.bml after an account is made +sub post_create +{ + my $o = shift; + my $userid = $o->{'userid'}; + my $user = $o->{'user'}; + my $dbh = LJ::get_db_writer(); + + return unless $o->{'code'}; + my ($acid, $auth) = LJ::acct_code_decode($o->{'code'}); + return unless $acid; + + # check to see if this account was created using an + # acid that was created as the result of a payment. + # in other words, we might now need to make the + # account paid. + + # old table + my $payid = $dbh->selectrow_array("SELECT payid FROM acctpay WHERE acid=$acid"); + if ($payid) { + # trust that paid users gave valid email address (so email alias then works immediately) + LJ::update_user($userid, { status => 'A' }); + # now that userid != 0, they'll be mailed and setup + # with a minute if the cronjob is running. + $dbh->do("UPDATE payments SET userid=$userid WHERE payid=$payid"); + return; + } + + # new table + my $piid = $dbh->selectrow_array("SELECT piid FROM acctpayitem WHERE acid=$acid"); + if ($piid) { + # trust that paid users gave valid email address (so email alias then works immediately) + LJ::update_user($userid, { status => 'A' }); + # do the payment immediately + my ($item, $qty) = $dbh->selectrow_array("SELECT item, qty FROM payitems ". + "WHERE piid=$piid"); + my $mo = $item eq "paidacct" ? $qty : 0; + $mo = 99 if $item eq "perm"; + LJ::Pay::add_paid_months($userid, $mo); + return; + } +} + +sub diskquota_apply_hook +{ + my ($u, $item) = @_; + + # we have successfully done nothing + return 1 unless $LJ::FB_QUOTA_NOTIFY; + + my $dbh = LJ::get_db_writer(); + my ($size, $exptime) = $dbh->selectrow_array("SELECT size, UNIX_TIMESTAMP(expdate) " . + "FROM paidexp WHERE userid=? AND item=?", + undef, $u->{userid}, $item); + return undef unless $size && $exptime; # eh? + + # add cmdbuffer job to send XML-RPC request to FotoBilder later + return LJ::cmd_buffer_add($u->{clusterid}, $u->{userid}, + "pay_fb_xmlrpc", + { + item => $item, + size => $size, + exptime => $exptime, + }); +} + +# uuid: userid +# what: paidaccount, etc ('what' db field) +# trans: 'P' => pay, 'X' => expire +sub update_paytrans +{ + my ($uuid, $what, $chflag) = @_; + + my $uid = LJ::want_userid($uuid); + return undef unless $uid && $what && $chflag; + + my $dbh = LJ::get_db_writer() + or return undef; + + # load all transitions for this user + my @trans = @{ + $dbh->selectall_arrayref + ("SELECT time, action FROM paytrans WHERE userid=? AND what=?", + undef, $uid, $what) || [] + }; + + # now trans => ([ time, action ], ...) + + my $time = time(); + my $action = ''; + + # currently paidaccount is the only 'what' + if ($what eq 'paidaccount') { + + my $renew_thresh = 14; # days between 'renew' and 'return' + + # evpent definitions: + # * 'new' - user has never paid for an account before, this is + # their first payment + # * 'ext' - user extended their account while it was still active + # * 'renew' - user paid before, expired, then re-purchased within + # $renew_thresh days of expiration + # * 'return' - user paid before, expired, then re-purchased after + # $renew thresh days of expiration + # * 'expire' - user had paid account expire + + # adding paid months to account + if ($chflag eq 'P') { + + # if this is the first purchase we've seen, then their account is new + if (! @trans) { + $action = 'new'; + + # if we've seen purchases before, we must look at their last expiration + # to see if this should be considered a 'return' or a 'renew' + } else { + + # find last expiration/pay actions a user had + my $lexp = 0; + my $lpay = 0; + foreach my $tr (@trans) { + $lexp = $tr->[0] if $tr->[1] eq 'expire' && $tr->[0] > $lexp; + $lpay = $tr->[0] if $tr->[1] ne 'expire' && $tr->[0] > $lpay; + } + + $action = 'ext' if $lpay && (! $lexp || $lexp < $lpay && $time > $lpay); + $action ||= $lexp && $lexp < ($time - 86400 * $renew_thresh) ? + 'return' : 'renew'; + } + + # expiring an existing paid account + } elsif ($chflag eq 'X') { + $action = 'expire'; + } + } + + # insert transition into db + $dbh->do("INSERT INTO paytrans VALUES (?,?,?,?)", + undef, $uid, $time, $what, $action) + or return undef; + + return 1; +} + +sub add_paid_time +{ + my ($userid, $time, $bonus_added) = @_; # or 99 months for perm + $userid += 0; + return undef unless $userid && (! $bonus_added || ref $bonus_added); + + # figure out the amount of time, as well + # as what type of units it is measured in + $time = ref $time ? $time : [ $time, 'month' ]; + + my ($timeval, $units) = @$time; + return undef unless $timeval > 0; + $units = lc($units); + $units ||= "month"; + return undef unless $units eq 'month' || $units eq 'day'; + + my $dbh = LJ::get_db_writer() + or return undef; + + my $is_perm = $timeval == 99 && $units eq 'month'; + + # permanent account + if ($is_perm) { + + # add permanent and paid caps + LJ::modify_caps($userid, ['paid', 'perm'],[]) + or return undef; + + # create paiduser row + $dbh->do("INSERT IGNORE INTO paiduser (userid) VALUES (?)", undef, $userid); + + # regular + } else { + + # add paid cap + LJ::modify_caps($userid, ['paid'], []) + or return undef; + + $dbh->do("INSERT INTO paiduser (userid, paiduntil) VALUES (?, DATE_ADD(NOW(), INTERVAL ? $units))", + undef, $userid, $timeval); + if ($dbh->err) { + # already an paying member; renewing: + $dbh->do("UPDATE paiduser SET paiduntil=DATE_ADD(GREATEST(IFNULL(paiduntil, NOW()), NOW()), INTERVAL ? $units) " . + "WHERE userid=?", undef, $timeval, $userid) + or return undef; + } + } + + # at this point the paid time has been applied. any failure could cause the + # caller to retry us later and cause paid time to be applied twice. + + # log this paid account activation + LJ::statushistory_add($userid, undef, 'pay_modify', + "adding paid ${units}s: " . ($is_perm ? "perm" : $timeval)); + + $LJ::CACHE_PAIDGROUP ||= LJ::get_userid("paidmembers"); + + # get a fresh userid from the database + my $u = LJ::load_userid($userid, "force"); + + if ($u->{'journaltype'} eq "P" && $LJ::CACHE_PAIDGROUP) { + # add as friend to paidmembers group (if it exists on this server) + LJ::add_friend($LJ::CACHE_PAIDGROUP, $userid); + } + + LJ::load_user_props($u, 'no_mail_alias'); + # add email alias, if account is validated + if ($u->{'status'} eq "A" && + ! $u->{'no_mail_alias'} && + ! exists $LJ::FIXED_ALIAS{$u->{'user'}}) { + $dbh->do("INSERT IGNORE INTO email_aliases (alias, rcpt) VALUES (?,?)", + undef, "$u->{'user'}\@$LJ::USER_DOMAIN", $u->{'email'}); + } + + # note the transition for stats + LJ::Pay::update_paytrans($userid, 'paidaccount', 'P') + or return undef; + + # FIXME: If the bonus-activation operation fails, then any + # pending bonus items won't be applied to the account being + # given paid time. Further, if we return undef from here on + # failure, callers such as bin/maint/pay.pl could retry us + # endlessly, adding time each time the above code is executed, + # then dying when trying to add the bonus features. We need + # to queue up the activation action on failure and return true + + # add any extra bonus feature time that needs to be added + @$bonus_added = LJ::Pay::activate_frozen_bonus($userid); + + return 1; +} + +sub add_paid_months { + &nodb; + my ($userid, $months, $bonus_added) = @_; # or 99 months for perm + + return LJ::Pay::add_paid_time(@_); +} + +sub remove_paid_months +{ + &nodb; + my ($userid, $months, $it) = @_; # or 99 months for perm + $userid += 0; + return undef unless $userid && $months >= 0; + return 1 unless $months; + + my $dbh = LJ::get_db_writer(); + my $pre = $dbh->selectrow_hashref("SELECT u.caps, p.paiduntil FROM user u LEFT JOIN paiduser p ". + "ON p.userid=u.userid WHERE u.userid=?", undef, $userid); + + + # 99 months means we're working on a permanent account + my $is_perm = $months == 99; + + # subtract $months from paid time, unless perm + $dbh->do("UPDATE paiduser SET paiduntil=DATE_SUB(paiduntil, INTERVAL ? MONTH) ". + "WHERE userid=?", undef, $months, $userid) + unless $is_perm; + + # remove them from being a paid user if their time has run out + LJ::Pay::remove_paid_account($userid, undef, $is_perm) + unless $dbh->selectrow_array("SELECT paiduntil > NOW() FROM paiduser WHERE userid=?", undef, $userid); + + # log this change to statushistory + my $post = $dbh->selectrow_hashref("SELECT u.caps, p.paiduntil FROM user u LEFT JOIN paiduser p ". + "ON p.userid=u.userid WHERE u.userid=?", undef, $userid); + + my $extra = $it ? " payment: $it->{'payid'}\[$it->{'piid'}]" : ""; + LJ::statushistory_add($userid, undef, "revoke", + "item=paidacct; $months months; was: caps $pre->{'caps'}/$pre->{'paiduntil'}, ". + "now: $post->{'caps'}/$post->{'paiduntil'}$extra"); + + return 1; +} + +sub acct_code_from_payid +{ + &nodb; + + my $payid = shift; + $payid += 0; + + my $dbh = LJ::get_db_writer(); + + my $sth; + + $dbh->do("LOCK TABLES acctpay WRITE, acctcode WRITE"); + + # does one already exist? + $sth = $dbh->prepare("SELECT acctcode.acid, acctcode.auth FROM acctcode, acctpay ". + "WHERE acctcode.acid=acctpay.acid AND acctpay.payid=$payid"); + $sth->execute; + my ($acid, $auth) = $sth->fetchrow_array; + if ($acid) { + $dbh->do("UNLOCK TABLES"); + return LJ::acct_code_encode($acid, $auth); + } + + # if not, let's add one. + my $code = LJ::acct_code_generate(0); + if ($code) { + ($acid, $auth) = LJ::acct_code_decode($code); + $dbh->do("REPLACE INTO acctpay (payid, acid) VALUES ($payid, $acid)"); + } + $dbh->do("UNLOCK TABLES"); + return $code; +} + +sub new_rename_token +{ + &nodb; + + my $payid = shift; + + my $dbh = LJ::get_db_writer(); + + my $code = LJ::rand_chars(10); + $dbh->do("INSERT INTO renames (token, payid) VALUES (?, ?)", + undef, $code, $payid) + or return undef; + my $renid = $dbh->{'mysql_insertid'} + or return undef; + + my $token = sprintf("%06x%s", $renid, $code); + return wantarray() ? ($token, $renid) : $token; +} + +sub register_payment +{ + &nodb; + + my $o = shift; + my $sth; + my $error = $o->{'error'}; + + my $zuid = $o->{'zerouserid'}; + my $userid = 0; + my $user = "???"; + + unless ($zuid) { + $user = lc($o->{'user'}); + $user =~ s/\W//g; + $userid = LJ::get_userid($user); + unless ($userid) { + $$error = "Invalid user ($user)"; + return 0; + } + } + + my $dbh = LJ::get_db_writer(); + + my $out_payid = $o->{'out_payid'}; + my $qdatesent = $dbh->quote($o->{'datesent'}); + my $qamount = $dbh->quote($o->{'amount'}+0); + my $qmonths = $dbh->quote($o->{'months'}+0); + my $qnotes = $dbh->quote($o->{'notes'}); + my $qmethod = $dbh->quote($o->{'method'}); + my $qwhat = $dbh->quote($o->{'what'}); + my $qgiveafter = $dbh->quote($o->{'giveafter'}); + + my $payid; + my $digest = Digest::MD5::md5_hex($o->{'unique_id'}); + + # prevent duplicates (quite common from paypal -> pp_notify.bml) + if ($o->{'unique_id'}) + { + $dbh->do("LOCK TABLES payments WRITE, duplock WRITE"); + + $sth = $dbh->prepare("SELECT dupid FROM duplock WHERE realm='payments' AND reid=0 AND ". + "userid=$userid AND digest='$digest'"); + $sth->execute; + ($payid) = $sth->fetchrow_array; + if ($payid) { + $dbh->do("UNLOCK TABLES"); + $$out_payid = $payid; + return $userid; + } + } + + my ($mailed, $used) = ("N", "N"); + $mailed = "Y" if $o->{'never_mail'}; + $used = "Y" if $o->{'never_use'}; + + ### now, insert a payment + $sth = $dbh->prepare("INSERT INTO payments (userid, datesent, daterecv, amount, months, used, mailed, notes, method, forwhat, giveafter) ". + "VALUES ($userid, $qdatesent, NOW(), $qamount, $qmonths, '$used', '$mailed', $qnotes, $qmethod, $qwhat, $qgiveafter)"); + $sth->execute; + if ($dbh->err) { + $$error = "Database error: " . $dbh->errstr; + $dbh->do("UNLOCK TABLES"); + return 0; + } + $payid = $sth->{'mysql_insertid'}; + + if ($o->{'unique_id'}) + { + $dbh->do("INSERT INTO duplock (realm, reid, userid, digest, dupid, instime) ". + "VALUES ('payments', 0, $userid, '$digest', $payid, NOW())"); + $dbh->do("UNLOCK TABLES"); + } + + ### insert payment search values + if ($o->{'search'}) { + my $s = $o->{'search'}; + foreach my $k (keys %$s) { + my $v = $s->{$k}; + my $vals = ref $v eq "ARRAY" ? $v : [ $v ]; + foreach (@$vals) { + $dbh->do("INSERT INTO paymentsearch (payid, ikey, ival) VALUES ($payid, ?, ?)", + undef, $k, $_); + } + } + } + + my $whoenter = $o->{'remote'}->{'user'} || "auto"; + my $msgbody = "Entered by $whoenter: payment# $payid for $user\n\n"; + $msgbody .= "AMOUNT: $o->{'amount'} MONTHS: $o->{'months'}\n"; + $msgbody .= "METHOD: $o->{'method'} WHAT: $o->{'what'}\n"; + $msgbody .= "DATE: $o->{'datesent'}\n"; + $msgbody .= "NOTES:\n$o->{'notes'}\n"; + + LJ::send_mail({ 'to' => 'paypal@livejournal.com', + 'from' => 'lj_noreply@livejournal.com', + 'charset' => 'utf-8', + 'subject' => "Payment \#$payid -- $user", + 'body' => $msgbody, + }); + + $$out_payid = $payid; + return $userid; +} + +sub paypal_parse_custom +{ + my $custom_str = shift; + + my %custom; + foreach my $pair (split(/&/, $custom_str)) + { + my ($key, $value) = split(/=/, $pair); + foreach (\$key, \$value) { + tr/+/ /; + s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + } + $custom{$key} = $value; + } + + return \%custom; +} + +sub register_paypal_payment +{ + &nodb; + + my $pp = shift; + my $o = shift; + my $error = $o->{'error'}; + + my %custom = %{ LJ::Pay::paypal_parse_custom($pp->{custom}) || {}}; + + # for some reason, every few weeks a payment comes in without the + # 'newacct' parameter. so this hack adds it. some broken browser + # out there? + $custom{'newacct'} = 1 + if ($custom{'months'} && ! defined $custom{'user'}); + + + # cart support (new payment system) + if ($custom{'cart'}) { + + my $dbh = LJ::get_db_writer(); + + my $cartobj = LJ::Pay::load_cart($custom{'cart'}); + unless ($cartobj) { $$error = "Invalid cart"; return 0; } + if ($cartobj->{'mailed'} ne "C") { + # cart is already paid for? or paypal is being + # dumb (as usual) and sending a dup notification, + # so let's see if the txn matches from previous + my $old_txn = $dbh->selectrow_array("SELECT ival FROM paymentsearch ". + "WHERE payid=? AND ikey='pptxnid'", undef, + $cartobj->{'payid'}); + + # tell paypal we're cool if this is a dup + return 1 if $old_txn && $old_txn eq $pp->{'txn_id'}; + + $$error = "Cart is already paid for"; return 0; + } + unless ($cartobj->{'amount'} * 100 == + $pp->{'payment_gross'} * 100) { + $$error = "Payment gross ($pp->{'payment_gross'} doesn't match cart price ($cartobj->{'amount'})"; + return 0; + } + + my $s = { + 'ppemail' => $pp->{'payer_email'}, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + foreach my $k (keys %$s) { + $dbh->do("INSERT INTO paymentsearch (payid, ikey, ival) VALUES (?, ?, ?)", + undef, $cartobj->{'payid'}, $k, $s->{$k}); + } + + $dbh->do("UPDATE payments SET mailed='N', used='N', ". + " method='paypal', daterecv=NOW() ". + "WHERE payid=? AND mailed='C'", + undef, $cartobj->{'payid'}); + if ($dbh->err) { $$error = "Database error"; return 0; } + return 1; + } + + # old payment system + + unless (($account{$custom{'months'}}->{'amount'} == $pp->{'payment_gross'}) || + ($custom{'months'} == 99 && $pp->{'payment_gross'} == 100) || + ($custom{'what'} eq "rename" && $pp->{'payment_gross'} == 15)) + { + $$error = "Payment gross not valid for that month value"; + return 0; + } + + my %mon2num = qw(Jan 1 Feb 2 Mar 3 Apr 4 May 5 Jun 6 + Jul 7 Aug 8 Sep 9 Oct 10 Nov 11 Dec 12); + + my $pp_to_sql_date = sub { + my $ppdate = shift; + if ($ppdate =~ /\b(\w\w\w) (\d{1,2}), (\d\d\d\d)\b/) { + my ($year, $month, $day); + $year = $3; + $month = $mon2num{$1}; + $day = $2; + return sprintf("%04d-%02d-%02d", $year, $month, $day); + } + return ""; + }; + + # is this for a new account? need to generate an account code + # and mail it to the user. + if ($custom{'newacct'}) + { + my %pay; + my $payid = 0; + + my @emails = ($pp->{'payer_email'}); + if ($custom{'email'} && + $custom{'email'} ne $pp->{'payer_email'}) { + push @emails, $custom{'email'}; + } + + $pay{'zerouserid'} = 1; # no userid yet. new acccount. + $pay{'datesent'} = $pp_to_sql_date->($pp->{'payment_date'}); + $pay{'method'} = "paypal"; + $pay{'notes'} = "PayPal Transaction ID: " . $pp->{'txn_id'} . "\n"; + $pay{'what'} = "account"; # one of (account, rename, gift) + $pay{'unique_id'} = $pp->{'txn_id'} . $pp->{'payment_status'}; + $pay{'error'} = $error; + $pay{'out_payid'} = \$payid; + $pay{'search'} = { + 'ppemail' => \@emails, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + $pay{'notes'} .= "Payment Status: $pp->{'payment_status'}\n"; + + if ($pp->{'payment_status'} eq "Completed") + { + $pay{'amount'} = $pp->{'payment_gross'}; + $pay{'months'} = $custom{'months'}; + + register_payment(\%pay); + + if ($payid) + { + my $code = acct_code_from_payid($payid); + unless ($code) { return 0; } + + LJ::send_mail({ + 'to' => join(", ", @emails), + 'from' => $LJ::ACCOUNTS_EMAIL, + 'charset' => 'utf-8', + 'subject' => 'Account code', + 'body' => "Here is your account creation code you can use to start setting up your journal:\n\n $code\n\nOr, just click or copy/paste this:\n\n $LJ::SITEROOT/create.bml?code=$code\n", + }); + + return 1; + } + return 0; + } + + # any non-complete payment we enter is just a placeholder for + # paymentsearch indexes to point back to. + $pay{'never_mail'} = $pay{'never_use'} = 1; + + if ($pp->{'payment_status'} eq "Pending") + { + $pay{'notes'} .= "Pending Reason: $pp->{'pending_reason'}\n"; + $pay{'notes'} .= "\nLiveJournal has been notified of your payment. If you paid with an eCheck, your account code will be emailed to you when the check clears.\n"; + } + + register_payment(\%pay); + return 0 unless $payid; + + LJ::send_mail({ + 'to' => $pp->{'payer_email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'charset' => 'utf-8', + 'subject' => "LiveJournal Payment Info ($payid)", + 'body' => "PayPal has notified LiveJournal of your payment. We've logged this transaction as \#$payid. Its current status is shown below:\n\n$pay{'notes'}\n", + }); + return 1; + } + + # handle incomplete payments for the general case (when we know username + # of buyer) + if ($pp->{'payment_status'} ne "Completed") + { + my %pay; + $pay{'user'} = $custom{'user'}; + $pay{'method'} = "paypal"; + $pay{'unique_id'} = $pp->{'txn_id'} . $pp->{'payment_status'}; + $pay{'datesent'} = $pp_to_sql_date->($pp->{'payment_date'}); + $pay{'notes'} = "PayPal Transaction ID: " . $pp->{'txn_id'} . "\n"; + $pay{'notes'} .= "Payment Status: $pp->{'payment_status'}\n"; + $pay{'error'} = $error; + $pay{'search'} = { + 'ppemail' => $pp->{'payer_email'}, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + $pay{'never_use'} = 1; # but we do mail them. + + if ($pp->{'payment_status'} eq "Pending") { + $pay{'notes'} .= "Pending Reason: $pp->{'pending_reason'}\n\n"; + $pay{'notes'} .= "You will get another email when this payment clears (or fails)."; + } + + return 1 if register_payment(\%pay); + return 0; + } + + # not a gift. + if ($custom{'for'} eq "") { + my %pay; + $pay{'user'} = $custom{'user'}; + $pay{'months'} = $custom{'months'}+0; + $pay{'amount'} = $pp->{'payment_gross'}; + $pay{'datesent'} = $pp_to_sql_date->($pp->{'payment_date'}); + $pay{'what'} = $custom{'what'} eq "rename" ? "rename" : "account"; # one of (account, rename, gift) + $pay{'method'} = "paypal"; + $pay{'notes'} = "PayPal Transaction ID: " . $pp->{'txn_id'}; + $pay{'unique_id'} = $pp->{'txn_id'}; + $pay{'error'} = $error; + + $pay{'search'} = { + 'ppemail' => $pp->{'payer_email'}, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + + if (register_payment(\%pay)) { return 1; } + return 0; + } + + # gift: process one payment for buyer and one for recipient. + if ($custom{'for'}) { + my $giftfor = $custom{'for'}; + my $buyer_ret; + my $recipient_ret; + my %pay; + + ## buyer's reciept. + %pay = (); + $pay{'user'} = $custom{'user'}; + $pay{'months'} = $LJ::GIVER_BONUS{$custom{'months'}}+0; # no months for buyer, unless specified + $pay{'amount'} = $pp->{'payment_gross'}; + $pay{'datesent'} = $pp_to_sql_date->($pp->{'payment_date'}); + $pay{'what'} = "gift"; # one of (account, rename, gift) + $pay{'method'} = "paypal"; + $pay{'notes'} = "PayPal Transaction ID: " . $pp->{'txn_id'} . "\nGift for $giftfor."; + $pay{'unique_id'} = $pp->{'txn_id'} . "BUYER"; # must be unique (see below) + $pay{'error'} = $error; + $pay{'search'} = { + 'ppemail' => $pp->{'payer_email'}, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + $buyer_ret = register_payment(\%pay); + + ## recipient's reciept + %pay = (); + $pay{'giveafter'} = $custom{'giveafter'}; + $pay{'user'} = $giftfor; + $pay{'months'} = $custom{'months'}; + $pay{'amount'} = 0; # recipient didn't pay + $pay{'datesent'} = $pp_to_sql_date->($pp->{'payment_date'}); + $pay{'what'} = "account"; # one of (account, rename, gift) + $pay{'method'} = "paypal"; + my $fromwho = $custom{'anon'} ? "(anonymous user)" : $custom{'user'}; + $pay{'notes'} = "PayPal Transaction ID: " . $pp->{'txn_id'} . "\nGift from: $fromwho."; + $pay{'unique_id'} = $pp->{'txn_id'} . "RCPT"; # must be unique (see above) + $pay{'error'} = $error; + $pay{'search'} = { + 'ppemail' => $pp->{'payer_email'}, + 'pptxnid' => $pp->{'txn_id'}, + 'pplastname' => $pp->{'last_name'}, + }; + $recipient_ret = register_payment(\%pay); + + ## did they both succeed? + return ($buyer_ret && $recipient_ret); + } + +} + +sub verify_paypal_transaction +{ + my $hash = shift; + my $opts = shift; + + my $ua = LWP::UserAgent->new(timeout => 6, + agent => "LJ-PayPalAuth/0.1"); + + # Create a request + my @urls = ('https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate', + 'http://www.bradfitz.com/cgi-bin/paypalproxy.cgi'); + foreach my $url (@urls) { + my $req = new HTTP::Request POST => $url; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(join("&", map { LJ::eurl($_) . "=" . LJ::eurl($hash->{$_}) } keys %$hash)); + + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + + # Check the outcome of the response + if ($res->is_success) { + if ($res->content eq "VERIFIED") { return 1; } + ${$opts->{'error'}} = "Invalid"; + return 0; + } + } + ${$opts->{'error'}} = "Connection Problem"; + return 0; +} + +sub LJ::Pay::load_cart { + my $cart = shift; + return undef unless $cart =~ /^(\d+)-(\d+)$/; + my ($payid, $anum) = ($1, $2); + my $dbh = LJ::get_db_writer(); + my $cartobj = $dbh->selectrow_hashref("SELECT * FROM payments ". + "WHERE payid=$payid AND anum=$anum ". + "AND forwhat='cart'"); + return undef unless $cartobj; + $cartobj->{'items'} = []; + my $sth = $dbh->prepare("SELECT * FROM payitems WHERE payid=$payid ORDER BY piid"); + $sth->execute; + while (my $pi = $sth->fetchrow_hashref) { + push @{$cartobj->{'items'}}, $pi; + } + return $cartobj; +} + +sub LJ::Pay::new_cart { + my $remote = shift; + my $dbh = LJ::get_db_writer(); + my $anum = int(rand()*65536); + my $userid = $remote ? $remote->{'userid'} : 0; + $dbh->do("INSERT INTO payments (forwhat, anum, userid, datesent, used, mailed) ". + "VALUES ('cart', $anum, $userid, NOW(), 'C', 'C')"); + my $payid = $dbh->{'mysql_insertid'}; + return undef unless $payid; + LJ::Pay::payvar_append($payid, "creator_ip", LJ::get_remote_ip()); + return LJ::Pay::load_cart("$payid-$anum"); +} + +sub LJ::Pay::payvar_add { + my ($payid, $k, $v) = @_; + my $dbh = LJ::get_db_writer(); + LJ::Pay::payvar_append($payid, $k, $v) + unless $dbh->selectrow_array("SELECT payid FROM payvars ". + "WHERE payid=? AND pkey=? AND pval=?", + undef, $payid, $k, $v); +} + +sub LJ::Pay::payvar_append { + my ($payid, $k, $v) = @_; + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO payvars (payid, pkey, pval) VALUES (?,?,?)", + undef, $payid, $k, $v); +} + +sub LJ::Pay::payvar_set { + my ($payid, $k, $v) = @_; + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM payvars WHERE payid=? AND pkey=?", undef, + $payid, $k); + LJ::Pay::payvar_append($payid, $k, $v) +} + +sub LJ::Pay::payid_set_state { + my ($payid, $ctry, $st) = @_; + return undef unless $payid; + $ctry ||= "??"; + $st ||= "??"; + + my $str = $ctry; + $str .= "-$st" if $ctry eq 'US'; + + # if we don't know the state, we insert a literal "??" into the db + my $dbh = LJ::get_db_writer(); + return $dbh->do("REPLACE INTO paystates (payid, state) VALUES (?,?)", + undef, $payid, $str); +} + +sub LJ::Pay::check_country_state { + my ($ctry, $st, $err) = @_; + $ctry = uc($ctry); $st = uc($st); + + my (%country, %state); + LJ::load_codes({ country => \%country, # "us" => "United States" + state => \%state }); + + # validate given country + unless ($country{$ctry}) { + while (my ($key, $val) = each %country) { + next unless $ctry eq uc($val); # "UNITED STATES" eq "UNITED STATES" + $ctry = uc($key); # "US" + } + } + unless ($country{$ctry}) { + $$err = "Invalid country: $ctry" if $ctry; + return (undef, undef); + } + + # don't handle non-US states right now + return ($ctry, undef) unless $ctry eq 'US'; + + # now, did they specify a state code or state name? + $st = uc(LJ::trim($st)); + + # full state name specified, get state code from that + unless ($state{$st}) { + while (my ($key, $val) = each %state) { + next unless $st eq uc($val); # "OHIO" eq "OHIO" + $st = uc($key); # "US" + } + } + unless ($state{$st}) { + $$err = "Invalid US state: $st" if $st; + return ($ctry, undef); + } + + # now $st should be a state code + return ($ctry, $st); +} + +sub LJ::Pay::add_cart_item { + my $cartobj = shift; + my $item = shift; + return LJ::error("no cart") unless $cartobj; + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO payitems (payid, status, item, subitem, qty, rcptid, amt, rcptemail, anon, giveafter, token, tokenid) ". + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", undef, + $cartobj->{'payid'}, "cart", + map { $item->{$_} } qw(item subitem qty rcptid amt rcptemail anon giveafter token tokenid)); + return LJ::error($dbh) if $dbh->err; + + my $piid = $dbh->{'mysql_insertid'}; + return LJ::error("Couldn't get piid") unless $piid; + $item->{'piid'} = $piid; + push @{$cartobj->{'items'}}, $item; + LJ::Pay::update_cart_total($cartobj); + + return $item; +} + +sub LJ::Pay::remove_cart_items { + my $cartobj = shift; + my @items = @_; + return 0 unless $cartobj; + return 1 unless @items; + + my @ids = map { (ref $_ eq "HASH" ? $_->{'piid'} : $_) + 0 } @items; + my $in = join(',', @ids); + my @cp_ids = map { $_->{tokenid}+0 } grep { ref $_ eq "HASH" && $_->{item} eq 'coupon' } @items; + + my $dbh = LJ::get_db_writer(); + + # when removing a coupon from the cart, set the payid column back to NULL + if (@cp_ids) { + my $cp_in = join(',', @cp_ids); + $dbh->do("UPDATE coupon SET payid=0 WHERE cpid IN ($cp_in)"); + } + + $dbh->do("DELETE FROM payitems WHERE piid IN ($in) AND payid=?", + undef, $cartobj->{'payid'}); + + # remove items from the cartobj + @{$cartobj->{'items'}} = grep { my $id = $_->{'piid'}; ! grep { $id == $_ } @ids; } @{$cartobj->{'items'}}; + + LJ::Pay::update_cart_total($cartobj); + return 1; +} + +sub LJ::Pay::update_shipping_cost { + my ($cartobj, $country) = @_; + return 0 unless $cartobj; + + # should only have one shipping cost line + my @shipi = grep { $_->{'item'} eq "shipping" } @{$cartobj->{'items'}}; + my $shipi; + + # figure out shipping cost ($5, $3, $5, $3....) + my $ship_cost = 0; + my $last = 0; + foreach (grep { $_->{'item'} eq "clothes" } @{$cartobj->{'items'}}) { + my $this_cost = 5; + $this_cost = 3 if $last == 5; + $ship_cost += $this_cost; + $last = $this_cost; + } + + # shipping on clothing only if outside US/Canada/Territories and order amt is non-zero + if ((grep { $_->{'item'} eq "clothes" } @{$cartobj->{'items'}}) && + $country ne "US" && # United States + $country ne "CA" && # Canada + $country ne "PR" && # Puerto Rico + $country ne "GU") # Guam + { + # get the first one, or make one + $shipi = shift @shipi; + unless ($shipi) { + $shipi = { + 'item' => 'shipping', + 'rcptid' => 0, + 'amt' => $ship_cost, + }; + die "Couldn't add shipping cost" unless + LJ::Pay::add_cart_item($cartobj, $shipi); + } + } + + # delete extra shipping items + LJ::Pay::remove_cart_items($cartobj, @shipi) if @shipi; + + # update shipping cost, if they're subject to shipping + if ($shipi && $shipi->{'amt'} != $ship_cost) { + $shipi->{'amt'} = $ship_cost; + my $dbh = LJ::get_db_writer(); + $dbh->do("UPDATE payitem SET amt=? WHERE piid=?", undef, + $ship_cost, $shipi->{'piid'}); + LJ::Pay::update_cart_total($cartobj); + } + + return 1; +} + +sub LJ::Pay::is_tangible { + my $it = shift; + return ($it->{'item'} eq 'clothes' || $it->{'item'} eq 'coupon'); +} + + +# takes in a cart object and returns the following hash keys/values: +# +# adj_amt_tot: total adjusted price of cart after coupons are applied +# adj_amt_int: total adjusted price of intangible items in cart after coupons are applied +# adj_amt_tan: total adjusted price of tangible items in cart after coupons are applied +# adj_amt_cp: total adjusted price of coupons being _purchased_ after coupons are applied +# +# cart_amt_tot: total unadjusted price of cart before coupons are applied +# cart_amt_int: total unadjusted price of intangible items in cart before coupons are applied +# cart_amt_tan: total unadjusted price of tangible items in cart before coupons are applied +# cart_amt_cp: total unadjusted price of coupons being _purchased_ before coupons are applied +# +# cp_amt_tot: total dollar amount of coupons in the cart (all types) +# cp_amt_gen: total dollar amount of general (universal) coupons in cart +# cp_amt_int: total dollar amount of intangible-only coupons in cart +# cp_amt_tan: total dollar amount of tangible-only coupons in cart +# +# cp_used_tot: total dollar amount of used coupons of all types +# cp_used_gen: total dollar amount of general (universal) coupons applied to cart +# cp_used_int: total dollar amount of intangible-only coupons applied to cart +# cp_used_tan: total dollar amount of tangible-only coupons applied to cart +# +# cp_unused_tot: total dollar amount of unused coupons of all types +# cp_unused_gen: total dollar amount of general (universal) coupons unused +# cp_unused_int: total dollar amount of unused intangible-only coupons in cart +# cp_unused_tan: total dollar amount of unused tangible-only coupons in cart +# +sub LJ::Pay::coupon_reduce { + my $cartobj = shift; + + # types for the following hashes: + # - tot: total amount for all item types + # - gen: general (universal) amount + # - tan: tangible-only amount + # - int: intangible-only amount + + my %cp_amt = (); # type => total coupon amount of this type + my %cp_unused = (); # type => total coupon amount unused of this type + my %cp_used = (); # type => total coupon amount used of this type + + # types for the following hashes: + # - tot: total amount of all item types + # - tan: tangible item amount + # - int: intangible item amount + # - cp: coupons the user is buying + + my %cart_amt = (); # type => total amount in cart of this type + my %adj_amt = (); # type => adjusted cart amount of this type after coupons applied + + foreach my $it (@{$cartobj->{'items'}}) { + + # item being purchased + if ($it->{amt} > 0) { + + my $type = LJ::Pay::is_tangible($it) ? 'tan' : 'int'; + + # NOTE: if the user is buying a coupon with a positive dollar amount, then it is a + # general coupon that can be used to buy anything. we can't apply any coupons to + # other coupon prices or else we open up a hole by which users can transcent their + # tangible/intangible limitations for free. bleh. + $type = 'cp' if $it->{item} eq 'coupon'; + + # add to purchase total for this type + $cart_amt{$type} += $it->{amt}; + + # also update total cart amount + $cart_amt{tot} += $it->{amt}; + + # applying a coupon given to them + } elsif ($it->{item} eq "coupon") { + + # keep a tally of total amount of coupons being used + # on this order (NOT purchased via this order) + if ($it->{subitem} =~ /^dollaroff(tan|int)?/) { + $cp_amt{$1 || 'gen'} += abs($it->{amt}); + $cp_amt{tot} += abs($it->{amt}); + + # otherwise could be a 'freeclothingitem' coupon type + # -- just treat this as a tangible coupon and it will be + # handled properly + } elsif ($it->{subitem} =~ /^freeclothingitem/) { + $cp_amt{tan} += abs($it->{amt}); + } + } + } + + # coupons being _purchased_ don't get adjusted, but for the sake of uniformity, + # we'll go ahead and add a key for their 'adjusted price' and set it the same as + # their total + $adj_amt{cp} = $cart_amt{cp}; + + # 1) apply coupons applying to items of each type + # - how much coupon was unused? + # - how much still needs to be paid for? + foreach my $type (qw(tan int)) { + + # assume we'll use all of it and correct later + $adj_amt{$type} = $cart_amt{$type} - $cp_amt{$type}; + $cp_unused{$type} = 0; + + # if less than 0, we used too much, so decide how much was unused + if ($adj_amt{$type} < 0) { + $cp_unused{$type} = abs($adj_amt{$type}); # unused coupons of this type + $adj_amt{$type} = 0; # adjusted amount is 0 + } + } + + # 2) if we have general purpose coupons and there are balances + # left, apply those to the adjusted amounts now + $cp_unused{gen} = $cp_amt{gen}; # haven't used any general coupons yet + foreach my $type (qw(tan int)) { + + # assume we'll use all of it and correct later + $adj_amt{$type} -= $cp_unused{gen}; + $cp_unused{gen} = 0; + + # if less than 0, we used too much, so decide how much was unused + if ($adj_amt{$type} < 0) { + $cp_unused{gen} = abs($adj_amt{$type}); # unused general coupons + $adj_amt{$type} = 0; # adjusted amount is 0 + } + + } + + # fill in how much was used + %cp_used = map { $_ => $cp_amt{$_} - $cp_unused{$_} } qw(gen tan int); + + # total (gen) adjusted amount is total cart amount - sum(all coupons used) + $adj_amt{tot} = $cart_amt{tot}; + $adj_amt{tot} -= $cp_used{$_} foreach qw(gen tan int); + + # total coupon usage + $cp_used{tot} = $cart_amt{tot} - $adj_amt{tot}; + $cp_unused{tot} = $cp_amt{tot} - $cp_used{tot}; + + return { + + # adjusted amounts + (map { ("adj_amt_$_" => $adj_amt{$_}+0) } qw(tot cp tan int)), + + # cart totals for different cateogires + (map { ("cart_amt_$_" => $cart_amt{$_}+0) } qw(tot cp tan int)), + + # total acoupon amounts in cart + (map { ("cp_amt_$_" => $cp_amt{$_}+0) } qw(tot gen tan int)), + + # coupon amounts used + (map { ("cp_used_$_" => $cp_used{$_}+0) } qw(tot gen tan int)), + + # coupon amounts unused + (map { ("cp_unused_$_" => $cp_unused{$_}+0) } qw(tot gen tan int)), + }; +} + +sub LJ::Pay::send_coupon_email { + my ($u, $token, $amt, $type) = @_; + return undef unless $u && $token && defined $amt; + my $email = ref $u ? $u->{'email'} : $u; + return undef unless $email; + + my $inttxt; + if ($type eq 'int') { + $inttxt .= "This coupon is only valid for intangible items such as paid accounts "; + $inttxt .= "and bonus features. It cannot be used to buy other coupons or to "; + $inttxt .= "buy clothing.\n\n"; + } elsif ($type eq 'tan') { + $inttxt .= "This coupon is only valid for tangible items such as tee shirts and "; + $inttxt .= "hoodies. It cannot be used to buy other coupons or intangible items "; + $inttxt .= "such as paid accounts.\n\n"; + } + + my $storetxt; + unless ($type eq 'int') { + $storetxt .= "$LJ::SITENAMESHORT store:\n"; + $storetxt .= " - $LJ::SITEROOT/store/\n\n"; + } + + # print dollars + my $damt = sub { sprintf("\$%.02f", shift()) }; + + return LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Coupon", + 'body' => + "$LJ::SITENAMESHORT coupon code:\n\n". + " $token\n\n". + + # possibly a notice saying this is an intangible coupon + $inttxt . + + "You can redeem it for " . $damt->($amt) . " USD in $LJ::SITENAMESHORT " . + "merchandise and/or services:\n\n". + + "$LJ::SITENAMESHORT services:\n" . + " - $LJ::SITEROOT/pay/\n\n" . + + $storetxt . + + "NOTE: Your coupon is only valid for one use, so be sure that your order's " . + "value is greater than or equal to " . $damt->($amt) . " USD.\n\n" . + + "$LJ::SITENAMESHORT Team", + }); +} + +# somewhat generic function, but for now it just sets allow_pay once we have received a +# valid payment from a user... so they don't run into open proxy + etc restrictions later +sub LJ::Pay::note_payment_from_user { + my $u = shift; + return undef unless LJ::isu($u); + + # need to load the userprop unless it exists + unless (exists $u->{allow_pay}) { + LJ::load_user_props($u, 'allow_pay') + or return undef;; + } + + # nothing to do if allow_pay is already set + return 1 if $u->{allow_pay} eq 'Y'; + + # set allow_pay on this user if necessary + if (LJ::set_userprop($u, 'allow_pay', 'Y')) { + + # log to statushistory + my $sys_id = LJ::get_userid('system'); + LJ::statushistory_add($u, $sys_id, "allow_pay", "automatically allowing payments after successful transaction"); + + # successfully set + return 1; + } + + # error setting userprop above + return undef; +} + +sub LJ::Pay::send_fraud_email { + my ($cartobj, $u) = @_; + return undef unless $cartobj; + + # assure $u is valid with 'fraud_watch' loaded, + # or undef if the cart has no rcptid + if ($cartobj->{userid}) { + $u ||= LJ::load_userid($cartobj->{userid}); + + LJ::load_user_props($u, 'fraud_watch') + unless $u && exists $u->{fraud_watch}; + + } else { + undef $u; + } + + # find items in cart, then load userids for items which have rcptids + my @items = @{$cartobj->{items}||[]}; + my $ru = LJ::load_userids(map { $_->{rcptid} } grep { $_->{rcptid} } @items); + + # build array of fraud-watched recipient user objects and the items they are purchasing + my @fraud_rcpt = (); + foreach my $it (@items) { + my $ruobj = $ru->{$it->{rcptid}} or next; + + LJ::load_user_props($ruobj, 'fraud_watch'); + push @fraud_rcpt, [$it, $ruobj] if $ruobj->{fraud_watch}; + } + + # if there's anything to mail, do it now + if (my $u_watch = $u && $u->{fraud_watch} or @fraud_rcpt) { + + # if there are recipients on fraud watch, make a list of + # their usernames and what they're trying to buy + my $rcpt_txt = ""; + if (@fraud_rcpt) { + $rcpt_txt .= "Cart recipient information: (only users with active fraud watches)\n\n"; + foreach (@fraud_rcpt) { + my ($it, $fu) = @$_; + $rcpt_txt .= " User: $fu->{user}\n"; + $rcpt_txt .= " Item: " . LJ::Pay::product_name($it) . "\n\n"; + } + } + + LJ::send_mail({ + 'to' => $LJ::ACCOUNTS_EMAIL, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Fraud alert: Payment #$cartobj->{payid}", + 'body' => "This warning has been sent because a payment transaction has been " . + "processed on $LJ::SITENAMESHORT. One or more of the users involved " . + "with this payment are on a fraud watch.\n\n" . + + "For full information about this payment, see the link below:\n\n" . + + " $LJ::SITEROOT/admin/accounts/paiddetails.bml?payid=$cartobj->{payid}\n\n" . + + "Cart owner information:\n\n" . + + " User: " . ($u ? $u->{user} : $cartobj->{rcptemail}) . "\n" . + " Watch: " . ($u_watch ? "yes" : "no") . "\n" . + " Payid: $cartobj->{'payid'}\n" . + " Time: " . LJ::mysql_time() . "\n\n" . + + $rcpt_txt, + + }) or return undef; + } + + return 1; +} + +sub LJ::Pay::update_cart_total { + my $cartobj = shift; + return 0 unless $cartobj; + my $dbh = LJ::get_db_writer(); + + # clothing piids which have been coupon'ed already + my %free_clothes; + + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'item'} eq "coupon"; + my ($type, $arg) = split(/-/, $it->{'subitem'}); + next unless $type eq "freeclothingitem"; + + my $amt = 0; + + # find most expensive item of clothing that + # hasn't been given free already + my ($max, $maxid); + foreach my $clit (@{$cartobj->{'items'}}) { + next unless $clit->{'item'} eq "clothes"; + next if $free_clothes{$clit->{'piid'}}; + next if $clit->{'amt'} < $max; + + # check to see if this product type is flagged as not + # being valid for free clothing items + my $cltype = (split("-", $clit->{'subitem'}))[0]; + next if $LJ::Pay::product{"clothes-$cltype"}->[2]; + + $max = $clit->{'amt'}; + $maxid = $clit->{'piid'}; + } + if ($max) { + $amt = $max; + $free_clothes{$maxid} = 1; + } + + # remove zero dollar coupons from cart + if ($amt == 0) { + $dbh->do("DELETE FROM payitems WHERE piid=?", undef, $it->{'piid'}); + next; + } + + if ($amt != $it->{'amt'}) { + $it->{'amt'} = -$amt; + $dbh->do("UPDATE payitems SET amt=? WHERE piid=?", undef, $it->{'amt'}, $it->{'piid'}); + } + } + + # analyze cart items to find total amounts + my $amts = LJ::Pay::coupon_reduce($cartobj); + + # update payments with adjusted price of cart after coupons are applied + $dbh->do("UPDATE payments SET amount=? WHERE payid=? AND mailed='C' AND forwhat='cart'", + undef, $amts->{'adj_amt_tot'}, $cartobj->{'payid'}); + return 1; +} + +sub LJ::Pay::can_mod_cart { + my $cartobj = shift; + return 0 unless $cartobj; + return 0 if $cartobj->{method}; + return 1; +} + +sub LJ::Pay::can_checkout_cart { + my $cartobj = shift; + return 0 unless $cartobj; + return 0 unless $cartobj->{mailed} eq 'C'; + return 0 unless @{$cartobj->{items}}; + return 1; +} + +sub LJ::Pay::cart_contains_coppa { + my $cartobj = shift; + return 0 unless $cartobj && @{$cartobj->{items}}; + return scalar grep { $_->{item} eq 'coppa' } @{$cartobj->{items}}; +} + +sub LJ::Pay::cart_needs_shipping { + my $cartobj = shift; + return 0 unless $cartobj && @{$cartobj->{'items'}}; + return scalar grep { LJ::Pay::item_needs_shipping($_) } @{$cartobj->{'items'}}; +} + +sub LJ::Pay::item_needs_shipping { + return ($_[0]->{'item'} eq "clothes"); +} + +sub LJ::Pay::reserve_items { + my $cartobj = shift; + my $out_list = shift; # listref to push out of stock product names onto + die "Can't reserve items in undef cart.\n" unless $cartobj; + my @prods = grep { $_->{'item'} eq "clothes" } @{$cartobj->{'items'}}; + return 1 unless @prods; + + my $dbh = LJ::get_db_writer(); + + my %need; + foreach my $pr (@prods) { + next if $pr->{'qty_res'} >= $pr->{'qty'}; + my $pkey = "$pr->{'item'}-$pr->{'subitem'}"; + + $need{$pkey}->{'count'} += $pr->{'qty'} - $pr->{'qty_res'}; + push @{$need{$pkey}->{'items'}}, $pr; + $need{$pkey}->{'item'} = $pr->{'item'}; + $need{$pkey}->{'subitem'} = $pr->{'subitem'}; + } + + foreach my $pr (keys %need) { + my $n = $need{$pr}; + my $avail = $dbh->selectrow_array("SELECT avail FROM inventory WHERE item=? AND subitem=?", + undef, $n->{'item'}, $n->{'subitem'}); + next if $avail >= $n->{'count'}; + push @$out_list, LJ::Pay::product_name($n->{'item'}, $n->{'subitem'}); + } + + # fail if items were out of stock + return 0 if @$out_list; + + # reserve items if they're in stock (yes, this is racy, but that's + # the least of the hellish inventory management problems) + foreach my $pr (keys %need) { + my $n = $need{$pr}; + $dbh->do("UPDATE inventory SET avail=avail-? WHERE item=? AND subitem=?", + undef, $n->{'count'}, $n->{'item'}, $n->{'subitem'}); + foreach my $it (@{$n->{'items'}}) { + $dbh->do("UPDATE payitems SET qty_res=qty WHERE piid=? AND payid=?", + undef, $it->{'piid'}, $it->{'payid'}); + } + } + return 1; +} + +sub LJ::Pay::product_name { + # @_: item, subitem, qty, short? + + my $item = shift; + my ($subitem, $qty, $short) = @_; + + # case 1: $it, $short + if (ref $item eq 'HASH') { + # allow 'subitem' or size key so that we can pass either + # a row from payitems or a row from paidexp with the "short" flag + $subitem = $item->{'subitem'} || $item->{'size'}; + $qty = $item->{'qty'}; + $item = $item->{'item'}; + $short = shift; + } + # otherwise, case 2: $item, $subitem, $qty, $short? + + # now we should have all the right vars + + if ($item eq "clothes") { + my ($type, $color, $size) = split(/-/, $subitem); + return join(' ', + $LJ::Pay::size{$size}->[1], + $LJ::Pay::color{$color}, + $LJ::Pay::product{"clothes-$type"}->[0]); + } + + if ($item eq "paidacct") { + return "Paid Account" . ($short ? "" : " - $LJ::Pay::account{$qty}->{'name'}"); + } + + if ($item eq "perm") { + return "Permanent Account"; + } + + if ($item eq "rename") { + return "Rename Token"; + } + + if ($item eq "coppa") { + return "Age Verification (for COPPA)"; + } + + if ($item eq "coupon") { + my ($type) = split(/-/, $subitem); + if ($type eq "freeclothingitem") { + return "Free clothing item"; + } + if ($type =~ /^dollaroff(int|tan)?/) { + return "Coupon" . ($1 ? ($1 eq 'tan' ? ", tangible" : ", intangible") : ""); + } + } + + if (LJ::Pay::is_bonus($item, 'bool')) { + my $bitem = $LJ::Pay::bonus{$item}; + return $bitem->{'name'} . ($short ? "" : (" - " . ($bitem->{'items'}->{$qty}->{'name'} || $qty))); + } + + if (LJ::Pay::is_bonus($item, 'sized')) { + my $bitem = $LJ::Pay::bonus{$item}; + + my $size = (split("-", $subitem))[0]; + my $sizeit = $bitem->{'items'}->{$size}; + my $qtyit = $sizeit->{'qty'}->{$qty}; + + return ($sizeit->{'name'} || $size) . " " . $bitem->{'name'} . + ($short ? "" : (" - " . ($sizeit->{'qty'}->{$qty}->{'name'} || $qty))); + } + + return "$item-$subitem"; +} + +# there was a race condition when 'pay_updateaccounts' and 'expiring' ran at the same time, +# so now we get a lock and re-verify our data afterwards; closures to make things simple +sub LJ::Pay::get_lock { + my $u = shift; + my $userid = LJ::want_userid($u); + return undef unless $userid; + + my $key = "acctupdate:$userid"; + my $dbh = LJ::get_db_writer(); + return LJ::get_lock($dbh, "global", $key); +}; + +sub LJ::Pay::release_lock { + my $u = shift; + my $userid = LJ::want_userid($u); + return undef unless $userid; + + my $dbh = LJ::get_db_writer(); + my $key = "acctupdate:$userid"; + return LJ::release_lock($dbh, "global", $key); +}; + +# is the given item a paidaccount add-on? +# thereby requiring checks for paid account existence? +sub LJ::Pay::is_bonus { + my ($it, $type) = @_; + my $item = ref $it eq 'HASH' ? $it->{'item'} : $it; + return undef unless defined $LJ::Pay::bonus{$item}; + return undef if $type && $LJ::Pay::bonus{$item}->{'type'} ne $type; + return 1; +}; + +# given a cart can we add a given item? +sub LJ::Pay::can_apply_sized_bonus { + my ($u, $cartobj, $item, $size, $qty) = @_; + my $userid = LJ::want_userid($u); + + # easy/obvious checks + return undef unless $userid && LJ::Pay::is_bonus($item, 'sized'); + + # if the caller doesn't specify a qty they are trying to add, just + # validate items already in the cart + $qty ||= 0; + + # is there immediately applying paid time in the cart? + my $cart_paid_immed = undef; + + # now go through the current cart and see what they have already + if ($cartobj) { + + # will be used for checks later on "dimension signature" + my ($prev_exp, $prev_size) = LJ::Pay::get_bonus_dim($userid, $item); + + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'rcptid'} == $userid; + + # collect information on when paid account starts in this cart + $cart_paid_immed = 1 + if $it->{'item'} eq 'paidacct' && ! $it->{'giveafter'}; + + next unless $it->{'item'} eq $item; + + # can't have a giveafter date on sized items + return undef if $it->{'giveafter'}; + + # subitem field contains a few useful bits of info + my ($itsize, $curr_exp, $curr_size) = split("-", $it->{'subitem'}); + + # if no size specified, then just verify that all sizes in the cart are equal + $size ||= $itsize; + + # can buy multiple items, but only of the same size + return undef if $itsize != $size; + + # when applying sized bonus, we have to make sure that no other sized bonus features have been + # applied since this one was added to the cart, so check the previous "dimension signature" + # to decide if this item can be legally applied + return undef unless $prev_exp == $curr_exp && $prev_size == $curr_size; + + # this is an extension to something already in the cart + $qty += $it->{'qty'}; + + # can't have more than 12 months in cart + return undef if $qty > 12; + } + } + + # now time to run some checks on the database + my $dbh = LJ::get_db_writer(); + + # if no paid account in cart starting immediately, check in the database + # to see if there is currently paid time there + unless ($cart_paid_immed) { + + # sometimes users have the paid cap with no paiduser row in the database, eg when + # they have a permanent account ... assume if they have a perm account then + # they are paid forever + unless ($dbh->selectrow_array("SELECT COUNT(*) FROM paiduser WHERE userid=? AND paiduntil>NOW()", undef, $userid)) { + + # if the query above failed, check to see if they have the paid cap + $u = LJ::want_user($u); + return undef unless $u && $u->{'caps'} & (1 << $LJ::Pay::capinf{'perm'}->{'bit'}); + } + } + + # now let's see what's in the database, with regards to this bonus item + my $row = $dbh->selectrow_hashref("SELECT *, " . + "(NOW() + INTERVAL ? MONTH <= expdate) AS 'is_short', " . + "(IF(size=?, expdate, NOW()) + INTERVAL ? MONTH > NOW() + INTERVAL 12 MONTH) AS 'is_long' " . + "FROM paidexp WHERE userid=? AND item=?", undef, $qty, $size, $qty, $userid, $item); + + # if nothing in database, the checks we've already done are sufficient + return 1 unless $row; + + # now we know there was a $row in the db + + # can't apply if they already have stored, therefore presumably no paid account? + return undef if $row->{'daysleft'}; + + # can't apply if expiration date won't extend past that of their current time + # unless the size is the same as their current size + return undef if $row->{'is_short'} && $row->{'size'} != $size; + + # can't apply more than one year in the future + return undef if $row->{'is_long'}; + + # can't downgrade to a lower size + return undef if $size < $row->{'size'}; + + return 1; +}; + +sub LJ::Pay::can_apply_bool_bonus { + my ($u, $cartobj, $item) = @_; + my $userid = LJ::want_userid($u); + + # easy/obvious checks + return undef unless $userid && LJ::Pay::is_bonus($item, 'bool'); + + # when does paid time in the cart begin? + my $cart_paid_start = undef; + my $cart_bonus_start = undef; + + if ($cartobj) { + + # check the cart to see if we can immediately exonerate this bonus feature + # without even looking in the database. + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'rcptid'} == $userid; + + # can't buy bool bonus features for permanent accounts + return undef if $it->{'item'} eq 'perm'; + + # calculate starting time of first applying amount of paid time in the cart + if ($it->{'item'} eq 'paidacct') { + + if ($it->{'giveafter'}) { + $cart_paid_start = $it->{'giveafter'} if ! defined $cart_paid_start || $it->{'giveafter'} < $cart_paid_start; + next; + } + + # no giveafter time, applies immediately + $cart_paid_start = 0; + next; + } + + # calculate starting time of this bonus item + if ($it->{'item'} eq $item) { + + if ($it->{'giveafter'}) { + $cart_bonus_start = $it->{'giveafter'} if ! defined $cart_bonus_start || $it->{'giveafter'} < $cart_bonus_start; + next; + } + + # no giveafter time, applies immediately + $cart_bonus_start = 0; + next; + } + } + + # immediately applying paid account == we're in the clear + # - note that undef == 0 returns true since undef gets converted to numeric + # context (0) before the comparison is done, blah perl + return 1 if defined $cart_paid_start && $cart_paid_start == 0; + return 1 if defined $cart_bonus_start && defined $cart_paid_start && + $cart_bonus_start >= $cart_paid_start; + } + + # is the specified userid a permanent account? if so there's a problem + $u = LJ::load_userid($userid, "force"); + return undef if ! $u || $u->{'caps'} & (1 << $LJ::Pay::capinf{'perm'}->{'bit'}); + + # can be applied if they have a currently unexpired paid account + my $dbh = LJ::get_db_writer(); + my $paiduntil = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP(paiduntil) FROM paiduser WHERE userid=? AND paiduntil>NOW()", + undef, $userid); + + # at this point we know that paid time in the cart doesn't immediately + # exonerate the bonus feature, because we would have returned already + return undef if ! $paiduntil || $paiduntil < $cart_bonus_start; + + # everything checked out + return 1; +} + +# get dimensions of current sized bonus block +sub LJ::Pay::get_bonus_dim { + my ($u, $itemname) = @_; + my $userid = LJ::want_userid($u); + return undef unless $userid; + + my $dbh = LJ::get_db_writer(); + my ($exptime, $size) = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP(expdate), size " . + "FROM paidexp WHERE userid=? AND item=?", + undef, $userid, $itemname); + return ($exptime || 0, $size || 0); +} + +# upgrade or extend the length of a bonus item +sub LJ::Pay::apply_bonus_item { + my ($u, $item, $subitem, $qty, $payid) = @_; + + # allow u/payitem objects passed optionally + my $userid = LJ::want_userid($u); + if (ref $item) { + $subitem = $item->{'subitem'}; + $qty = $item->{'qty'}; + $payid = $item->{'payid'}; + $item = $item->{'item'}; + } + + # userid and item are required regardless of bonus feature type + return undef unless $userid && $item; + + my $dbh = LJ::get_db_writer(); + + # does an existing paidexp row exist? + my $exp = $dbh->selectrow_hashref("SELECT userid, item, size, expdate, daysleft, " . + "UNIX_TIMESTAMP(expdate) AS 'exptime', " . + "(expdate > NOW()) AS 'unexpired' " . + "FROM paidexp WHERE userid=? AND item=?", + undef, $userid, $item); + + # if no row in database, fill in $exp with good values + $exp ||= { + 'userid' => $userid, + 'item' => $item, + 'size' => 0, + 'expdate' => undef, + 'daysleft' => 0, + 'exptime' => 0, + 'unexpired' => 0, + }; + + my $new_size = $exp->{'size'}; + + # activate cap if necessary + if (my $cap = $LJ::Pay::bonus{$item}->{'cap'}) { + LJ::modify_caps($userid, [$cap], []) + or return undef; + } + + # actions for 'sized' bonus feature type + # -- need to check that account is still in size/exp state it was in + # when this item was purchased so people can't be comp'd more than + # once for existing paid time on upgrades + + my $sized_upgrade = 0; + + if (LJ::Pay::is_bonus($item, 'sized')) { + return undef unless $subitem; + + # make sure exp/size signature in subitem still matches + my ($it_size, $old_exptime, $old_size) = split("-", $subitem); + + # if a payid is passed, then first check to make sure that no other payitems + # in this cart have been applied, altering the exp/size signature and making + # this check return false-positives + + unless ($payid && + $dbh->selectrow_array("SELECT COUNT(*) FROM payitems " . + "WHERE payid=? AND item=? AND subitem=? AND status='done'", + undef, $payid, $item, $subitem)) + { + + # zero-fill + $old_exptime ||= 0; + $old_size ||= 0; + + # check for exptime/size mismatch, now that we know it's necessary + unless ($old_exptime == $exp->{'exptime'} && $old_size == $exp->{'size'}) { + + # all bonus items of this type have the same size and exptime/oldsize signature + # by the rules applied to them when they entered the cart. + # + # so if one item fails, we go ahead and mark them all as having failed. + # the caller (pay.pl) will have to be smart enough to know to not try to process + # subsequent items of the failed bonus type + + LJ::statushistory_add($userid, undef, 'pay_modify', + "ERROR: cannot apply bonus feature: $item, " . + "${old_exptime}x${old_size} != $exp->{'exptime'}x$exp->{'size'}"); + + $dbh->do("UPDATE payitems SET status='done' WHERE payid=? AND item=? AND subitem=?", + undef, $payid, $item, $subitem); + + return undef; + } + } + + # could either be upgrade or extension, but either way we adopt the item's size + $new_size = $it_size; + + # means that we are upgrading a sized bonus item, so the time added should start + # from now, not the current expdate + $sized_upgrade = 1 unless $old_size == $new_size; + } + + # insert a new row, or add time to old one + # - this code somewhat duplicates functionality from LJ::Pay::activate_frozen_bonus + # but we need to extend the expdate by $qty months anyway, so we'll just do the + # daysleft activation here as well, avoiding some queries + { + # expdate calculation is tricky + # [(expdate || NOW()) + INTERVAL $qty MONTH] + INTERVAL $daysleft DAY + + # expiration extends off current expdate if there's a currently unexpired item of + # the same size. otherwise it's an upgrade and starts from NOW() + my $expdate = $exp->{'unexpired'} && ! $sized_upgrade + ? $dbh->quote($exp->{'expdate'}) : "NOW()"; + + if ($qty) { + my $qqty = $dbh->quote($qty || 0); + $expdate = "($expdate + INTERVAL $qqty MONTH)"; + } + if ($exp->{'daysleft'}) { + my $qdaysleft = $dbh->quote($exp->{'daysleft'}); + $expdate = "($expdate + INTERVAL $qdaysleft DAY)"; + } + + # update / insert paidexp row + $dbh->do("REPLACE INTO paidexp (userid, item, size, expdate, daysleft) " . + "VALUES (?, ?, ?, $expdate, 0)", undef, $userid, $item, $new_size); + return undef if $dbh->err; + } + + # call any application hooks for this bonus feature + my $apply_hook = $LJ::Pay::bonus{$item}->{'apply_hook'}; + if ($apply_hook && ref $apply_hook eq 'CODE') { + # apply_hook needs a real $u object + $u = ref $u ? $u : LJ::load_userid($u); + $apply_hook->($u, $item); + } + + # log this bonus feature activation + { + my $msg = "adding bonus feature: item=$item; "; + if (LJ::Pay::is_bonus($item, 'sized')) { + $msg .= "size=$exp->{'size'}"; + $msg .= "=>$new_size" if $exp->{'size'} != $new_size; + $msg .= "; "; + } + $msg .= "old_expdate=$exp->{'expdate'}; applying $qty months, $exp->{'daysleft'} existing days"; + + LJ::statushistory_add($userid, undef, 'pay_modify', $msg); + } + + return 1; +} + +sub LJ::Pay::expire_bonus { + my ($u, $item) = @_; + + # allow u/payitem objects passed optionally + my $userid = LJ::want_userid($u); + $item = $item->{'item'} if ref $item; + return undef unless $userid; + + my $dbh = LJ::get_db_writer(); + + # we can either operate on one given item or all items for a user + my $itemand = (" AND item=" . $dbh->quote($item)) if $item; + + # hard-validate constraints on the paidexp table in here + # - this is probably done by the caller too, but outside of a lock + my $sth = $dbh->prepare("SELECT item FROM paidexp WHERE userid=?$itemand " . + "AND (daysleft=0 OR daysleft IS NULL) " . + "AND expdate < NOW() AND expdate > '0000-00-00'"); + $sth->execute($userid); + my @activated = (); + while (my ($item) = $sth->fetchrow_array) { + next unless LJ::Pay::is_bonus($item); + + # remove cap if there's one associated with this bonus item + if (my $cap = $LJ::Pay::bonus{$item}->{'cap'}) { + LJ::modify_caps($userid, [], [$cap]) + or return undef; + } + + # remove paidexp row + $dbh->do("DELETE FROM paidexp WHERE userid=? AND item=?", undef, $userid, $item); + + # log this bonus feature expiration + LJ::statushistory_add($u, undef, 'pay_modify', "expiring bonus feature: $item"); + } + + return 1; +} + +# activates frozen bonus features +# - returns array of hashrefs: { item => { itemname, size, days_activated } +sub LJ::Pay::activate_frozen_bonus { + my ($u, $item) = @_; # item is optional + + # allow u/payitem objects passed optionally + my $userid = LJ::want_userid($u); + $item = $item->{'item'} if ref $item; + return undef unless $userid; + + my $dbh = LJ::get_db_writer(); + + # we can either operate on one given item or all items for a user + my $itemand = (" AND item=" . $dbh->quote($item)) if $item; + + # see if there is existing time + my $sth = $dbh->prepare("SELECT item, size, expdate, daysleft, (expdate > NOW()) AS 'unexpired' " . + "FROM paidexp WHERE daysleft>0 AND userid=?$itemand"); + $sth->execute($userid); + my @activated = (); + while (my ($item, $size, $expdate, $daysleft, $unexpired) = $sth->fetchrow_array) { + next unless LJ::Pay::is_bonus($item); + + # it would generally suffice to set expdate to NOW() + INTERVAL daysleft DAY, but to be more + # robust we want to handle the case where there are daysleft in the db, but the item isn't + # expired yet + my $base = $unexpired ? $dbh->quote($expdate) : "NOW()"; + + # update database if we found some (need select above to fetch daysleft) + $dbh->do("UPDATE paidexp SET expdate=($base + INTERVAL ? DAY), daysleft=0 " . + "WHERE userid=? AND item=?", undef, $daysleft, $userid, $item); + return undef if $dbh->err; + + # reactivate caps if necessary + if (my $cap = $LJ::Pay::bonus{$item}->{'cap'}) { + LJ::modify_caps($userid, [$cap], []) + or return undef; + } + + # log this bonus feature activation + LJ::statushistory_add($userid, undef, 'pay_modify', + "adding bonus feature: item=$item; old_expdate=$expdate; " . + "applying $daysleft existing days"); + + push @activated, { 'item' => $item, 'size' => $size, 'daysleft' => $daysleft }; + } + + return @activated; +} + +# activates frozen bonus features +# - returns array of hashrefs: { item, size, daysleft frozen } +sub LJ::Pay::freeze_bonus { + my ($u, $item) = @_; # item is optional + + # allow u/payitem objects passed optionally + my $userid = LJ::want_userid($u); + $item = $item->{'item'} if ref $item; + return undef unless $userid; + + my $dbh = LJ::get_db_writer(); + + # we can either operate on one given item or all items for a user + my $itemand = $item ? (" AND item=" . $dbh->quote($item)) : ""; + + # see if there is existing time + my $sth = $dbh->prepare("SELECT item, size, (TO_DAYS(expdate)-TO_DAYS(NOW())+daysleft) AS 'new_daysleft' " . + "FROM paidexp WHERE expdate>NOW() AND userid=?$itemand"); + $sth->execute($userid); + my @deactivated = (); + while (my ($item, $size, $new_daysleft) = $sth->fetchrow_array) { + + # this shouldn't ever get triggered + next unless LJ::Pay::is_bonus($item); + + # remove cap (if necessary) and run applicable hooks + if (my $cap = $LJ::Pay::bonus{$item}->{'cap'}) { + LJ::modify_caps($userid, [], [$cap]) + or return 0; + } + + # set expdate to now and save current time in daysleft + # - to be robust, handle the case where there are currently daysleft but the expdate>NOW(), + # even though it technically shouldn't happen. + if ($new_daysleft) { + $dbh->do("UPDATE paidexp SET daysleft=?, expdate=NOW() " . + "WHERE userid=? AND item=?", undef, $new_daysleft, $userid, $item); + + # if daysleft ended up being 0 above, delete the row + } else { + $dbh->do("DELETE FROM paidexp WHERE userid=? AND item=? AND (daysleft=0 OR daysleft IS NULL)", + undef, $userid, $item); + } + + # log this bonus feature expiration + LJ::statushistory_add($u, undef, 'pay_modify', + "deactivating bonus feature due to paid account expiration: item=$item; ". + "saving $new_daysleft extra days"); + + # return a list of deactivated rows + push @deactivated, { 'item' => $item, 'size' => $size, 'daysleft' => $new_daysleft }; + } + + return @deactivated; +} + +# returns 1 on success, undef on error +# - bonus_ref: opt, reference in which to return output of LJ::Pay::freeze_bonus +# - perm: opt, set to remove permanent status +sub LJ::Pay::remove_paid_account { + my ($userid, $bonus_ref, $perm) = @_; + my $u = ref $userid ? $userid : LJ::load_userid($userid, "force"); + return undef unless $u; + + # remove paid user cap + { + my @cap_remove = 'paid'; + push @cap_remove, 'perm' if $perm; + + LJ::modify_caps($u, [], [ @cap_remove ]) + or return undef; + } + + # delete paiduser/email alias rows + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM paiduser WHERE userid=?", undef, $u->{'userid'}); + $dbh->do("DELETE FROM email_aliases WHERE alias=?", undef, "$u->{'user'}\@$LJ::USER_DOMAIN") + unless exists $LJ::FIXED_ALIAS{$u->{'user'}}; + + # note the transition for stats + LJ::Pay::update_paytrans($userid, 'paidaccount', 'X') + or return undef; + + # log this paid account expiration + my $name = $perm ? "perm" : "paid"; + LJ::statushistory_add($u, undef, 'pay_modify', "expiring $name account"); + + # returns list/hash of item => { paidexp row } + @$bonus_ref = LJ::Pay::freeze_bonus($u); + + return 1; +} + +sub LJ::Pay::is_valid_cart { + my $cartobj = shift; + + # do some checks on the cart to make sure that it is valid/intact? + my $dbh; + + # iterate over all items and make sure that each one is allowed to be there + my %done = (); + my $found_coppa = undef; + foreach my $it (@{$cartobj->{'items'}}) { + + # cache that we checked this userid, item combination + { + my $key = "$it->{'rcptid'}-$it->{'item'}"; + next if $done{$key}; + $done{$key} = 1; + } + + # run checks for 'sized' bonus item types + if (LJ::Pay::is_bonus($it, 'sized')) { + return undef unless LJ::Pay::can_apply_sized_bonus($it->{'rcptid'}, $cartobj, $it->{'item'}); + + # run checks for 'bool' bonus item types + } elsif (LJ::Pay::is_bonus($it, 'bool')) { + return undef unless LJ::Pay::can_apply_bool_bonus($it->{'rcptid'}, $cartobj, $it->{'item'}); + + # check for attempted use of already used coupons + } elsif ($it->{'item'} eq 'coupon' && $it->{'amt'} < 0) { + $dbh ||= LJ::get_db_writer(); + my $payid = $dbh->selectrow_array("SELECT payid FROM coupon WHERE cpid=?", + undef, $it->{'tokenid'}); + return undef unless $payid && $payid == $cartobj->{'payid'}; + + + } elsif ($it->{'item'} eq 'coppa') { + return undef if $found_coppa; + return undef unless $it->{'rcptid'}; + + my $rcpt = LJ::load_userid($it->{'rcptid'}); + return undef unless $rcpt->{userid} == $cartobj->{userid} && $rcpt->underage; + + $found_coppa = 1; + } + } + + if ($cartobj->{userid} && ! $found_coppa) { + my $u = LJ::load_userid($cartobj->{userid}) or return undef; # invalid user on cart + + # no coppa found and cart owner is underage + return undef if $u->underage; + } + + return 1; +} + +sub LJ::Pay::get_bool_bonus_price { + my ($item, $qty) = @_; + + # allow passing of an $it hash + if (ref $item eq 'HASH') { + $qty = $item->{'qty'}; + $item = $item->{'item'}; + } + + return undef unless $item && $qty && LJ::Pay::is_bonus($item, 'bool'); + + return $LJ::Pay::bonus{$item}->{'items'}->{$qty}->{'amount'}; +} + +sub LJ::Pay::get_sized_bonus_price { + my ($u, $cartobj, $item, $size, $qty) = @_; + + my $userid = LJ::want_userid($u); + + # allow passing of an $it hash + if (ref $item eq 'HASH') { + # get size from subitem + $size = (split("-", $item->{'subitem'}))[0]; + $qty = $item->{'qty'}; + $item = $item->{'item'}; + } + + # easy/obvious checks + return undef unless $userid && LJ::Pay::is_bonus($item, 'sized') && $size > 0; + + # total price of this item with no comp + my $total_price = $LJ::Pay::bonus{$item}->{'items'}->{$size}->{'qty'}->{$qty}->{'amount'}; + + # no negative prices allowed + $total_price = 0 if $total_price < 0; + + # if there is already an item of this size in the cart, it already received a comp, so don't do it again + return $total_price + if grep { $_->{'rcptid'} == $userid && $_->{'item'} eq $item && + (split("-", $_->{'subitem'}))[0] == $size } @{$cartobj->{'items'}}; + + my $dbh = LJ::get_db_writer(); + my $row = $dbh->selectrow_hashref("SELECT TO_DAYS(expdate)-TO_DAYS(NOW()) AS 'curr_days', " . + "TO_DAYS(NOW() + INTERVAL ? MONTH)-TO_DAYS(NOW()) AS 'new_days', " . + "size AS 'curr_size' FROM paidexp WHERE userid=? AND item=?", + undef, $qty, $userid, $item); + $row->{'new_size'} = $size; + $row->{'curr_days'} = 0 if $row->{'curr_days'} < 0; + + # if current size is what they're trying to buy or there are no current days, there is no comp'ing to be done + return $total_price if $row->{'curr_size'} == $row->{'new_size'} || $row->{'curr_days'} == 0; + + # find areas of new/existing rectangles to be bought + my $old_area = $row->{'curr_size'} * $row->{'curr_days'}; + my $new_area = $row->{'new_size'} * $row->{'new_days'}; + my $rate = $old_area / ($new_area || 1); + + # calculate comp'd price to subtract from the total + my $comp_amt = $total_price * $rate; + + # return final price to user. + my $final_price = sprintf("%.02f", $total_price - $comp_amt); + + # don't let final price be < 0 + $final_price = 0 if $final_price < 0; + + return $final_price; +} + +# return list of bonus items available for purchase, +# to be plugged into LJ::html_select() +sub LJ::Pay::bonus_item_list { + my ($u, $cartobj) = @_; # purchasing user + + my @bool; + my @sized; + foreach my $itemname (keys %LJ::Pay::bonus) { + my $bitem = $LJ::Pay::bonus{$itemname}; + next unless ref $bitem eq 'HASH' && ref $bitem->{'items'} eq 'HASH'; # eh? + + # bool type + if ($bitem->{'type'} eq 'bool') { + foreach my $qty (sort { $b <=> $a } keys %{$bitem->{'items'}}) { + my $amt = $bitem->{'items'}->{$qty}->{'amount'}; + push @bool, ("$itemname-$qty", + LJ::Pay::product_name($itemname, undef, $qty) . " (\$$amt.00 USD)"); + } + + next; + } + + # sized type + if ($u && $bitem->{'type'} eq 'sized') { + foreach my $size (reverse sort { $a <=> $b } keys %{$bitem->{'items'}}) { + my $sizeit = $bitem->{'items'}->{$size}; + foreach my $qty (sort { $b <=> $a } keys %{$sizeit->{'qty'}}) { + + # do a bunch of checks, $u probably is $remote since gifts aren't allowed + next unless LJ::Pay::can_apply_sized_bonus($u, $cartobj, $itemname, $size, $qty); + + # will be interpretted as item-subitem-qty + my $amt = $sizeit->{'qty'}->{$qty}->{'amount'}; + my $amt_comp = LJ::Pay::get_sized_bonus_price($u, $cartobj, $itemname, $size, $qty); + push @sized, ("$itemname-$size-$qty", + LJ::Pay::product_name($itemname, $size, $qty) . " (\$$amt.00 USD" . + ($amt == $amt_comp ? "" : "; to upgrade: \$$amt_comp") . ")"); + } + } + + next; + } + } + + return (@bool, @sized); +} + +sub LJ::Pay::postal_address_text { + return join("\n", @LJ::PAY_POSTAL_ADDRESS, @_); +} + +sub LJ::Pay::postal_address_html { + return join('
    ', @LJ::PAY_POSTAL_ADDRESS, @_); +} + +sub LJ::Pay::account_summary { + my $u = shift; + return undef unless $u; + + # find account name + my $acctname; + my $eff_cap; + foreach my $capkey (sort { $LJ::Pay::capinf{$a}->{'bit'} <=> $LJ::Pay::capinf{$b}->{'bit'} } keys %LJ::Pay::capinf) { + my $cap = $LJ::Pay::capinf{$capkey}; + next unless $u->{'caps'} & 1 << $cap->{'bit'}; + $acctname = $cap->{'name'}; + $eff_cap = $capkey; + } + + # get paid account expiration date, but only if the user is paid (not perm) + my $dbh = LJ::get_db_writer(); + my $paid_exp; + if ($eff_cap eq 'paid') { + $paid_exp = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=? " . + "AND paiduntil > NOW()", + undef, $u->{'userid'}); + } + + my $trim = sub { return substr($_[0], 0, 10); }; + + my $ret; + + # account type + $ret .= "
      "; + $ret .= "
    • $acctname"; + $ret .= " - expiring " . $trim->($paid_exp) . "" if $paid_exp; + $ret .= "
    • "; + + # bonus features + my $sth = $dbh->prepare("SELECT * FROM paidexp WHERE userid=? AND (expdate>NOW() OR daysleft>0)"); + $sth->execute($u->{'userid'}); + my $bonus = "
        "; + my $ct; + while (my $exp = $sth->fetchrow_hashref) { + + $bonus .= "
      • " . LJ::Pay::product_name($exp, "short") . " - "; + + # enabled has 2 cases: + # - item has associated cap and it's enabled on $u + # - daysleft == 0, meaning expdate > NOW() by query above + my $bit = $LJ::Pay::bonus{$exp->{'item'}}->{'cap'}; + my $has_cap = $u->{'caps'} & 1 << $bit; + my $enabled = defined $bit && $has_cap || $exp->{'daysleft'} == 0; + + # active + if ($enabled) { + $bonus .= "Active, expiring " . $trim->($exp->{'expdate'}) . ""; + + # inactive + } else { + $bonus .= "Inactive, $exp->{'daysleft'} days remaining"; + } + $bonus .= "
      • "; + + $ct++; + } + $ret .= "$bonus
      " if $ct; + + $ret .= "
    "; + + return $ret; +} + +sub LJ::Pay::quota_summary { + my $u = shift; + + # disk quota usage + my $diskquota = LJ::Blob::get_disk_usage($u); + my $diskmax = LJ::get_cap($u, "disk_quota") * 1024**2; + return undef unless $diskquota && $diskmax; + + my $size = sub { + my $bytes = shift; + + # print in mb + return sprintf("%.2f MiB", $bytes / 1024**2) + if $bytes > 1024**2; + + # print in k + return sprintf("%.2fkb", $bytes / 1024); + }; + + my $pct = sub { + return sprintf("%.2f%%", ($_[0] / $_[1]) * 100); + }; + + my $ret; + + $ret .= "
      "; + $ret .= "
    • Total: " . $size->($diskquota) . " of " . $size->($diskmax); + $ret .= " (" . $pct->($diskquota, $diskmax) . ")
    • "; + + $ret .= "
        "; + my @blobtypes = (['userpic', "Userpics"], ['phonepost', 'PhonePost']); + push @blobtypes, ['fotobilder', 'Photo Hosting'] if LJ::get_cap($u, 'fb_account'); + foreach (@blobtypes) { + my ($domain, $name) = @$_; + + my $used = LJ::Blob::get_disk_usage($u, $domain); + $ret .= "
      • $name: " . $size->($used); + $ret .= " (" . $pct->($used, $diskmax) . ")
      • "; + } + $ret .= "
    "; + + return $ret; + +}; + +sub LJ::Pay::render_cart { + my $cartobj = shift; + + my $ret = shift; + my $opts = shift; + + my $remote = LJ::get_remote(); + + $$ret .= < + + + Item + Type + Recipient + Amount + +HDR + +my $is_items = 0; +unless ($cartobj && @{$cartobj->{'items'}}) { + $$ret .= "(no items)"; +} else { + $is_items = 1; + my %name = ( + 'paidacct' => 'Paid Account', + 'coupon' => "Coupon", + 'perm' => 'Permanent Account', + 'rename' => 'Rename Token', + 'shipping' => "Shipping Cost", + 'diskquota' => "Disk Quota", + 'userpic' => "Extra Userpics", + 'coppa' => "Age Verification (for COPPA)", + ); + + # load user objects & pics + my (%user, %pic); + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'rcptid'}; + $user{$it->{'rcptid'}} = \$user{$it->{'rcptid'}}; + } + LJ::load_userids_multiple([ %user ], [ $remote ]); + if ($opts->{'pics'}) { + LJ::load_userpics(\%pic, [ map { [ $_, $_->{'defaultpicid'} ] } values %user ]); + } + + my $ljuopts = {}; + $ljuopts->{'imgroot'} = "$LJ::SSLROOT/img" if $opts->{'secureimg'}; + + foreach my $it (sort { $b->{'amt'} <=> $a->{'amt'} } @{$cartobj->{'items'}}) { + my $size; + + $$ret .= ""; + $$ret .= LJ::html_check({ 'type' => 'check', 'name' => "del_$it->{'piid'}", + 'id' => "del_$it->{'piid'}", 'disabled' => $it->{'item'} eq 'coppa' }) + if $opts->{'remove'}; + $$ret .= ""; + + # default item name + my $name = $name{$it->{'item'}} || $it->{'item'}; + + # bonus features + if (LJ::Pay::is_bonus($it)) { + $name = LJ::Pay::product_name($it, "short"); + } + + # clothing items + if ($it->{'item'} eq "clothes") { + my ($style, $col, $sz) = split(/-/, $it->{'subitem'}); + if ($LJ::Pay::product{"clothes-$style"}) { + $name = $LJ::Pay::product{"clothes-$style"}->[0]; + } + $name ||= "Unknown Clothing: $name"; + $name .= ", " . $LJ::Pay::color{$col}; + $name = "$name" if $opts->{shipping_labels}; + if ($opts->{'pics'}) { + $name .= "
    "; + } + $size = $LJ::Pay::size{$sz}->[1]; + + } + + # discount coupons + if ($it->{'item'} eq "coupon") { + $name = LJ::Pay::product_name($it->{'item'}, $it->{'subitem'}); + $name .= "
    ($it->{'token'})" if $it->{'token'} && $it->{'amt'} < 0; + } + $$ret .= ""; + + # is this an anonymous gift? + if ($it->{'anon'}) { + $$ret .= ", anonymous"; + } + + # is there a delivery date? + if ($it->{'giveafter'}) { + $$ret .= ", to be delivered "; + my @gmt = gmtime($it->{'giveafter'}); + $$ret .= sprintf("%04d-%02d-%02d %02d:%02d", + $gmt[5]+1900, $gmt[4]+1, $gmt[3], + $gmt[2], $gmt[1]); + } + + # if this is being called from an admin page, optionally show tokens associated + # with renames, coupons, etc. + if ($opts->{'tokens'} && $it->{'token'} ne "") { + my $token = $it->{'token'}; + if ($it->{'item'} eq "paidacct" || $it->{'item'} eq "perm") { + $token = "$token"; + } + + # link between payid that bought + # the coupon and payid which used the coupon + if ($it->{'item'} eq "coupon") { + my $dbh = LJ::get_db_writer(); + my ($payid, $ppayid) = + $dbh->selectrow_array("SELECT payid, ppayid FROM coupon WHERE cpid=?", + undef, $it->{'tokenid'}); + + my $id = $it->{'amt'} < 0 ? $ppayid : $payid; + $token = "$token" if $id; + } + + if ($it->{'item'} eq "rename") { + my $dbh = LJ::get_db_writer(); + my ($from, $to, $date) = + $dbh->selectrow_array("SELECT fromuser, touser, rendate FROM renames " . + "WHERE payid=? AND renid=?", + undef, $it->{'payid'}, $it->{'tokenid'}); + if ($from && $to && $date) { + $token .= "
    " . + LJ::ljuser($from, { 'no_follow' => 1 }) . " => " . + LJ::ljuser($to, { 'no_follow' => 1 }) . "
    @ $date"; + } else { + $token .= " (unused)"; + } + } + + $$ret .= "
    $token"; + } + if ($opts->{'piids'}) { + $$ret .= "
    [piid: $it->{'piid'} {$it->{'status'}}]"; + } + $$ret .= ""; + + # item type column + if ($it->{'item'} eq "paidacct" || + defined $LJ::Pay::bonus{$it->{'item'}}) { + + $$ret .= "$it->{'qty'} months"; + } elsif ($it->{'item'} eq "clothes") { + $$ret .= $opts->{shipping_labels} ? "$size" : $size; + } elsif ($it->{'item'} eq "coupon") { + $$ret .= "\$$it->{'amt'} USD"; + } + + $$ret .= ""; + if ($it->{'rcptid'}) { + my $u = $user{$it->{'rcptid'}}; + $$ret .= LJ::ljuser($u->{'user'}, $ljuopts) . " - " . LJ::ehtml($u->{'name'}); + if ($u->{'defaultpicid'} && $opts->{'pics'}) { + my $p = $pic{$u->{'defaultpicid'}}; + $$ret .= "
    {'userid'}' width='$p->{'width'}' height='$p->{'height'}'>"; + } + + } else { + $$ret .= "" . LJ::ehtml($it->{'rcptemail'}) . ""; + } + $$ret .= ""; + $$ret .= sprintf("\$%0.02f", $it->{'amt'}); + $$ret .= ""; + } + +} + + # analyze various amounts in this cart + my $amts = LJ::Pay::coupon_reduce($cartobj); + + # print dollars + my $damt = sub { sprintf("\$%.02f", shift()) }; + + if ($amts->{'cp_used_tot'} > 0) { + $$ret .= "Subtotal:"; + $$ret .= "" . $damt->($amts->{'cart_amt_tot'}) . ""; + if ($amts->{'cp_used_gen'} > 0) { + $$ret .= "General Coupon:"; + $$ret .= "" . $damt->(-$amts->{'cp_used_gen'}) . ""; + } + if ($amts->{'cp_used_int'} > 0) { + $$ret .= "Intangible Coupon:"; + $$ret .= "" . $damt->(-$amts->{'cp_used_int'}) . ""; + } + if ($amts->{'cp_used_tan'} > 0) { + $$ret .= "Tangible Coupon:"; + $$ret .= "" . $damt->(-$amts->{'cp_used_tan'}) . ""; + } + } + $$ret .= "Total (USD):"; + $$ret .= "" . $damt->($amts->{'adj_amt_tot'}) . ""; + + if ($opts->{'remove'} || ($opts->{'checkout'} && LJ::Pay::can_checkout_cart($cartobj))) { + + # warning of coupons in cart which are not fully utilized + if ($amts->{'cp_unused_gen'} > 0) { + $$ret .= ""; + $$ret .= "Warning: You are using " . $damt->($amts->{'cp_amt_gen'}); + $$ret .= " worth of general-purpose coupons on this order. However, "; + $$ret .= $damt->($amts->{'cp_unused_gen'}) . " of that is currently unused. "; + $$ret .= "If you choose to check out now, the " . $damt->($amts->{'cp_unused_gen'}); + $$ret .= " will be wasted!"; + $$ret .= "\n"; + } + + # warning of intangible coupons in cart which are not fully utilized + if ($amts->{'cp_unused_int'} > 0) { + $$ret .= ""; + $$ret .= "Warning: You are using " . $damt->($amts->{'cp_amt_int'}); + $$ret .= " worth of coupons which are only valid for intangible "; + $$ret .= "purchases such as Paid Accounts and Bonus Features. However, "; + $$ret .= $damt->($amts->{'cp_unused_int'}) . " of that is currently unused. "; + $$ret .= "If you choose to check out now, the " . $damt->($amts->{'cp_unused_int'}); + $$ret .= " will be wasted!"; + $$ret .= "\n"; + } + + # warning of tangible coupons in cart which are not fully utilized + if ($amts->{'cp_unused_tan'} > 0) { + $$ret .= ""; + $$ret .= "Warning: You are using " . $damt->($amts->{'cp_amt_tan'}); + $$ret .= " worth of coupons which are only valid for tangible "; + $$ret .= "purchases such as Tee Shirts and Hoodies. However, "; + $$ret .= $damt->($amts->{'cp_unused_tan'}) . " of that is currently unused. "; + $$ret .= "If you choose to check out now, the " . $damt->($amts->{'cp_unused_tan'}); + $$ret .= " will be wasted!"; + $$ret .= "\n"; + } + + if (grep { $_->{'item'} eq 'rename' || $_->{'item'} eq 'coupon' && $_->{'amt'} > 0 } + @{$cartobj->{'items'}}) { + + $$ret .= ""; + $$ret .= "AOL Users: To prevent difficulties receiving your rename token "; + $$ret .= "and/or coupon, please adjust your email settings to allow email from "; + $$ret .= "$LJ::ACCOUNTS_EMAIL.\n"; + } + + my $has_coppa = LJ::Pay::cart_contains_coppa($cartobj); + if ($has_coppa) { + $$ret .= ""; + $$ret .= "Note: Because your cart contains a COPPA Verification item, "; + $$ret .= "you must pay for this cart via credit card.\n"; + } + + my $disabled = $is_items ? "" : "disabled='disabled'"; + $$ret .= ""; + if ($opts->{'remove'}) { + $$ret .= ""; + } + $$ret .= ""; + if ($opts->{'checkout'} && LJ::Pay::can_checkout_cart($cartobj)) { + + if ($amts->{'adj_amt_tot'} > 0 || $has_coppa || LJ::Pay::cart_needs_shipping($cartobj)) { + $$ret .= "Payment method: "; + + my @pay_list = (cc => "Credit Card"); + + # if the cart contains a special "coppa" item, then the only vaid method of payment + # is credit card. + unless ($has_coppa) { + push @pay_list, ( "paypal" => "PayPal", + "check" => "Check", + "moneyorder" => "Money Order", + "cash" => "Cash", ); + } + + $$ret .= LJ::html_select({'name' => 'paymeth', }, @pay_list); + $$ret .= "\n"; + + } else { + $$ret .= "No charge. "; + } + } + $$ret .= "\n"; + } + + $$ret .= ""; + + return 1; +} + +sub revoke_payitems +{ + my $dbh = LJ::get_db_writer(); + foreach my $it (@_) { + next unless $it->{'status'} eq "done"; + + # revoke a rename token + if ($it->{'item'} eq "rename") { + + # the rename token might've been used already, in which case it's kinda + # too late. but we'll mark the rename as refunded regardless, so maybe + # later we can write something to flop things back... we'll see. + $dbh->do("UPDATE renames SET token='----------' WHERE renid=?", undef, + $it->{'tokenid'}); + + # log to statushistory, but only if there's a userid to associate it with + LJ::statushistory_add($it->{'rcptid'}, undef, "revoke", "revoking rename token: $it->{'token'}") + if $it->{'rcptid'}; + + next; + } + + # revoke a paid or permanent account + if ($it->{'item'} eq "paidacct" || $it->{'item'} eq "perm") { + my $revid = $it->{'rcptid'}; + if ($it->{'tokenid'}) { + $dbh->do("UPDATE acctcode SET auth='-----' WHERE acid=?", undef, + $it->{'tokenid'}); + # but maybe the code wasn't used yet, so let's check and + # cancel the revoke, since we stopped it in time + $revid = $dbh->selectrow_array("SELECT rcptid FROM acctcode WHERE ". + "acid=?", undef, $it->{'tokenid'}); + } + my $months = $it->{'item'} eq "perm" ? 99 : $it->{'qty'}; + LJ::Pay::remove_paid_months($revid, $months, $it) if $revid; + next; + } + + # revoke a tangible shipping item + if (LJ::Pay::item_needs_shipping($it)) { + # delete from shipping so this shipping label won't show up anymore + $dbh->do("DELETE FROM shipping WHERE payid=?", undef, $it->{'payid'}); + + # log to statushistory, but only if there's a userid to associate it with + LJ::statushistory_add($it->{'rcptid'}, undef, "revoke", + "revoking shipping item: " . LJ::Pay::product_name($it)) + if $it->{'rcptid'}; + + next; + } + + # revoke bonus features + if (LJ::Pay::is_bonus($it)) { + + # this function will handle messiness and log to statushistory + LJ::Pay::remove_bonus_item($it); + next; + } + } + + my $in = join(',', map { $_->{'piid'}+0 } @_); + $dbh->do("UPDATE payitems SET status='refund' WHERE piid IN ($in)") if $in; +} + +sub LJ::Pay::remove_bonus_item { + my $it = shift; + return undef unless ref $it eq 'HASH'; + return undef unless LJ::Pay::is_bonus($it); + + my $dbh = LJ::get_db_writer(); + + # update paidexp + $dbh->do("UPDATE paidexp SET expdate=expdate - INTERVAL ? MONTH " . + "WHERE userid=? AND item=?", + undef, $it->{'qty'}, $it->{'rcptid'}, $it->{'item'}); + + # if they're now totally out of time for this bonus feature, we need to + # delete their paidexp row altogether and possibly remove their cap + + my $newrow = $dbh->selectrow_hashref("SELECT *, (expdate>NOW()) AS 'timeleft' " . + "FROM paidexp WHERE userid=? AND item=?", + undef, $it->{'rcptid'}, $it->{'item'}); + + unless ($newrow->{'timeleft'}) { + + # delete empty row + $dbh->do("DELETE FROM paidexp WHERE userid=? AND item=? AND expdate{'rcptid'}, $it->{'item'}); + + # update user's cap if necessary + my $cap = $LJ::Pay::bonus{$it->{'item'}}->{'cap'}; + LJ::modify_caps($it->{'rcptid'}, [], [$cap]) if $cap; + } + + # log to statushistory + LJ::statushistory_add($it->{'rcptid'}, undef, 'revoke', + LJ::Pay::product_name($it, "shoort") . "; $it->{'qty'} months"); + + return 1; +} + +sub bazaar_do_expirations { + my $uid = shift; + my $dbh = LJ::get_db_writer(); + + my $userclause; + if ($uid) { + $uid += 0; + $userclause = "userid=$uid AND "; + } + + # do expirations + $dbh->do("UPDATE bzrbalance SET expired=owed, owed=0 WHERE $userclause ". + "owed > 0 AND date < DATE_SUB(NOW(), INTERVAL 93 DAY)"); +} + +sub bazaar_remove_balance { + my ($u, $amt) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $u; + + my $key = "bzrbaldecr-$u->{'userid'}"; + my $r = $dbh->selectrow_array("SELECT GET_LOCK(?, 3)", undef, $key); + return 0 unless $r; + my $unlock = sub { + $dbh->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $key); + }; + + LJ::Pay::bazaar_do_expirations($u->{'userid'}); + + my @owed; + my $bal; + my $sth = $dbh->prepare("SELECT bzid, owed FROM bzrbalance ". + "WHERE userid=? AND owed > 0 ORDER BY date"); + $sth->execute($u->{'userid'}); + while (my ($bzid, $owed) = $sth->fetchrow_array) { + push @owed, [ $bzid, $owed ]; + $bal += $owed; + } + + if ($bal < $amt) { + $unlock->(); + return 0; + } + + my $remain = $amt; + while ($remain >= 0.01 && @owed) { + my $rec = shift @owed; + my $remove = $rec->[1] < $remain ? $rec->[1] : $remain; + my $rv = $dbh->do("UPDATE bzrbalance SET owed=GREATEST(0,owed-?) WHERE userid=? AND bzid=?", + undef, $remove, $u->{'userid'}, $rec->[0]); + $remain -= $remove if $rv; + } + + $unlock->(); + return 1; +} + +sub new_coupon { + my ($type, $amt, $rcptid, $ppayid) = @_; + + my $dbh = LJ::get_db_writer() or return undef; + my $auth = LJ::make_auth_code(10); + $dbh->do("INSERT INTO coupon (auth, type, arg, rcptid, ppayid) " . + "VALUES (?, ?, ?, ?, ?)", undef, $auth, $type, $amt, $rcptid, $ppayid); + return undef if $dbh->err; + + my $tokenid = $dbh->{'mysql_insertid'}; + return ($tokenid, "$tokenid-$auth"); +} + +# to be called as &nodb; (so this function sees caller's @_) +sub nodb { + shift @_ if + ref $_[0] eq "LJ::DBSet" || ref $_[0] eq "DBI::db" || + ref $_[0] eq "DBIx::StateKeeper" || ref $_[0] eq "Apache::DBI::db"; +} + + +1; diff --git a/ljcom/cgi-bin/phonepost.pl b/ljcom/cgi-bin/phonepost.pl new file mode 100644 index 0000000..fdfce03 --- /dev/null +++ b/ljcom/cgi-bin/phonepost.pl @@ -0,0 +1,321 @@ +#!/usr/bin/perl +# vim: set ts=4 sw=4 et : + +# some variable names: +# - phonepostid, bid, blobid: all refer to a blob id. +# - dppid: display phonepost id; comparable to a ditemid, but for a phone post. + +use strict; + +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJ::Blob; + +package LJ::PhonePost; + +my $datatypes = { + 0 => { ext => 'mp3', mime => 'audio/mp3' }, + 1 => { ext => 'ogg', mime => 'application/ogg' }, + 2 => { ext => 'wav', mime => 'audio/wav' }, +}; + +sub may_transcribe { + my ($u, $remote) = @_; + return 0 if $remote && $remote->{journaltype} ne 'P'; + return 1 if $remote && $remote->{userid} == $u->{userid}; + LJ::load_user_props($u, 'pp_transallow'); + return 0 if $u->{pp_transallow} == -1; + my $groupmask = LJ::get_groupmask($u, $remote); + return 1 if ! $u->{pp_transallow} && $groupmask; + return ($groupmask & (1 << $u->{pp_transallow})) ? 1 : 0; +} + +sub get_phonepost_entry { + my ($u, $bid) = @_; + my ($ppe, $memkey); + + $memkey = [$u->{userid}, "ppe:$u->{userid}:$bid"]; + $ppe = LJ::MemCache::get($memkey); + + return $ppe if $ppe; + + my $dbcr = LJ::get_cluster_def_reader($u); + $ppe = $dbcr->selectrow_hashref(qq{ + SELECT ppe.jitemid, ppe.posttime, ppe.anum, + ppe.filetype, ub.length, ppe.lengthsecs, ppe.location + FROM phonepostentry ppe, userblob ub + WHERE ub.journalid=? AND ppe.userid=ub.journalid + AND ub.domain=? AND ub.blobid=? AND ppe.blobid=ub.blobid + }, undef, $u->{'userid'}, LJ::get_blob_domainid("phonepost"), $bid); + LJ::MemCache::set($memkey, $ppe || 0); + return $ppe; +} + +sub apache_content { + my ($r, $u, $dppid) = @_; + my $bid = $dppid >> 8; + my $ppe = get_phonepost_entry($u, $bid); + return 404 unless $ppe && $ppe->{jitemid} && $ppe->{anum} == $dppid % 256; + + # check security of item + my $logrow = LJ::get_log2_row($u, $ppe->{jitemid}); + return 404 unless $logrow; + + if ($u->{statusvis} eq 'S' || $logrow->{security} ne "public") { + # get the remote, ignoring IP, since the request is coming + # from Akamai/Speedera/etc and the IP won't match + my $remote = LJ::get_remote({ ignore_ip => 1 }); + + my %GET = $r->args; + + my $viewall = 0; + my $viewsome = 0; + if ($remote && $GET{viewall} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "phonepost: $u->{user}, itemid: $ppe->{jitemid}, statusvis: $u->{'statusvis'}"); + + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + unless ($viewall || $viewsome && $logrow->{security} eq 'public') { + return 403 unless LJ::can_view($remote, $logrow); + } + } + + # future: if length is NULL, then it's an external reference and we redirect + $r->header_out("Cache-Control", "must-revalidate, private"); + $r->header_out("Content-Length", $ppe->{length}); + $r->content_type( $datatypes->{ $ppe->{filetype} }->{mime} ); + + # handle IMS requests + my $last_mod = LJ::time_to_http($ppe->{posttime}); + if (my $ims = $r->header_in("If-Modified-Since")) { + return 304 if $ims eq $last_mod; + } + + $r->header_out("Last-Modified", $last_mod); + if ($r->header_only) { + $r->send_http_header(); + return 200; + } + + my $buffer; + if ($ppe->{location} eq 'mogile') { + # Mogile + if ( !$LJ::REPROXY_DISABLE{phoneposts} && + $r->header_in('X-Proxy-Capabilities') && + $r->header_in('X-Proxy-Capabilities') =~ /\breproxy-file\b/i ) + { + my @paths = LJ::mogclient()->get_paths( "pp:$u->{userid}:$bid", 1 ); + + # reproxy url + if ($paths[0] =~ m/^http:/) { + $r->header_out('X-REPROXY-URL', join(' ', @paths)); + } + # reproxy file + else { + $r->header_out('X-REPROXY-FILE', $paths[0]); + } + $r->send_http_header(); + } + else { + $buffer = LJ::mogclient()->get_file_data("pp:$u->{userid}:$bid"); + $r->send_http_header(); + return 500 unless $buffer && ref $buffer; + $r->print($$buffer); + } + + } + else { + # BlobServer + $r->send_http_header(); + my $ret = LJ::Blob::get_stream($u, 'phonepost', + $datatypes->{ $ppe->{filetype} }->{ext}, $bid, sub { + $buffer .= $_[0]; + if (length($buffer) > 50_000) { + $r->print($buffer); + undef $buffer; + } + }); + $r->print($buffer) if length($buffer); + return 500 unless $ret; + } + + return 200; +} + +# if $u_embed and $ditemid are given, they represent an entry +# in which a phonepost tag has been embedded. + +sub make_link { + my ($remote, $uuid, $phonepostid, $mode, $u_embed, $ditemid) = @_; + $phonepostid += 0; + + # mode can either be 'notrans', 'bare', or 'rss' + $mode = "notrans" if $mode && $mode !~ /bare|rss/; + + my $u = ref $uuid ? $uuid : LJ::load_userid($uuid); + return $mode eq 'rss' ? "" : "[Invalid user]" unless $u; + my $userid = $u->{'userid'}; + + my $ppe = get_phonepost_entry($u, $phonepostid); + return $mode eq 'rss' ? "" : "[Invalid audio link]" unless $ppe; + + if ($u_embed && $ditemid) { + # have to check whether the link is embeddable in this entry + if ($u_embed->{'userid'} == $userid && + $ditemid>>8 == $ppe->{'jitemid'}) { + + # it's the original entry, we're ok + } else { + my $accdenied = "[Access to audio link denied]"; + + # log2 row in which the tag is embedded + my $row = LJ::get_log2_row($u_embed, $ditemid >> 8); + + # the original log2 row of this tag + my $row_orig = LJ::get_log2_row($u, $ppe->{'jitemid'}); + return $mode eq 'rss' ? "" : $accdenied unless $row && $row_orig; + + if ($row_orig->{'security'} eq "public" && + $row->{'posterid'} == $userid && + $u_embed->{'userid'} != $userid) { + + # it's public and moved by the same + # user to a different journal, we're okay + } else { + return $mode eq 'rss' ? "" : $accdenied; + } + } + } + + my $link; + my $dppid = ($phonepostid << 8) + $ppe->{anum}; + my $ext = $datatypes->{ $ppe->{filetype} }->{ext}; + my $path = LJ::run_hook("url_phonepost", $u, $dppid, $ext) || + LJ::journal_base($u) . "/data/phonepost/$dppid.$ext"; + + # make link and just return that if in bare mode + $link = $ppe->{location} eq 'none' ? + "" : + ""; + return $link if $mode eq 'bare'; + + my $K = $ppe->{length} ? int($ppe->{length} / 1024) . "K" : ""; + my $secs = $ppe->{lengthsecs}; + my $duration = $secs ? sprintf("%d:%02d", int($secs/60), $secs%60) : ""; + + # support rss 'enclosures' - podcasting. + if ($mode eq 'rss') { + $link = "{length}\" " . + "type=\"$datatypes->{ $ppe->{filetype} }->{mime}\" />"; + return $link; + } + + # return full table + my $ret = ""; + $ret .= ""; + $ret .= ""; + + unless ($mode eq 'notrans') { + my $trans_url = "$LJ::SITEROOT/phonepost/transcribe.bml?user=$u->{user}&ppid=$dppid"; + $ret .= ""; + my $trans = LJ::PhonePost::get_latest_trans($u, $phonepostid); + if ($trans) { + my $by; + if ($trans->{revid} == 1) { + $by = LJ::ljuser(LJ::get_username($trans->{posterid})); + } else { + # multiple users transcribing, or just multiple transcriptions of one user? + my $memkey = [$u->{userid},"ppetu:$u->{userid}:$phonepostid"]; + my $tu = LJ::MemCache::get($memkey); + unless (defined $tu) { + my $dbr = LJ::get_cluster_reader($u); + $tu = $dbr->selectrow_array("SELECT COUNT(DISTINCT(posterid)) " . + "FROM phoneposttrans " . + "WHERE journalid=? AND blobid=?", + undef, $u->{'userid'}, $phonepostid + 0); + LJ::MemCache::set($memkey, $tu); + } + $by = ($tu == 1) ? LJ::ljuser(LJ::get_username($trans->{posterid})) : "multiple users"; + } + my $text = LJ::ehtml($trans->{body}); + $text =~ s/\n/
    /g; + + $ret .= ""; + } elsif (LJ::PhonePost::may_transcribe($u, $remote)) { + $ret .= ""; + } else { + $ret .= ""; + } + } + + $ret .= "
    $link"; + $ret .= $ppe->{location} eq 'none' ? "PhonePost" : "PhonePost"; + $ret .= "
    $K $duration
    (Help)
    “$text”

    ". + "Transcribed by: $by
    (transcribe)(no transcription available)
    "; + return $ret; + +} + +sub get_latest_trans { + my ($u, $id) = @_; + $id += 0; + + my $memkey = [$u->{userid},"ppelt:$u->{userid}:$id"]; + my $lt = LJ::MemCache::get($memkey); + unless (defined $lt) { + my $dbcr = LJ::get_cluster_def_reader($u); + return undef unless $dbcr; + + $lt = ""; + my $latest = $dbcr->selectrow_array("SELECT MAX(revid) FROM phoneposttrans ". + "WHERE journalid=? AND blobid=?", undef, + $u->{userid}, $id); + if ($latest) { + $lt = $dbcr->selectrow_hashref("SELECT revid,posterid,posttime,subject,body ". + "FROM phoneposttrans WHERE journalid=? ". + "AND blobid=? AND revid=?", undef, + $u->{userid}, $id, $latest); + } + LJ::MemCache::set($memkey, $lt); + } + return $lt; +} + +sub show_phoneposts { + my ($u_embed, $ditemid, $remote, $eventref) = @_; + + my $replace = sub { + my $tag = shift; + my ($user, $userid, $uobj, $phid, $blobid, $dpid); + + # old tag + # new tag + if ($tag =~ m!^journalid=['"](\d+)['"]\s*dpid=['"](\d+)['"]\s*/?$!) { + ($userid, $dpid)=($1,$2); + + # prefer phonepostid and userid + $phid = $dpid >> 8 if $dpid; + + } elsif ($tag =~ m!^(user=['"](\S+)['"])?\s*(phonepostid=['"](\d+)['"])?\s*(userid=['"](\d+)['"])?\s*(blobid=['"](\d+)['"])?\s*/?$!) { + ($user,$phid,$userid,$blobid)=($2,$4,$6,$8); + + # prefer phonepostid and userid + $phid = $blobid >> 8 + unless $phid or not $blobid; + do { + $uobj = LJ::load_user($user); + $userid = $uobj->{'userid'}; + } unless $userid or $user eq ""; + } + + return "[Invalid audio link]" unless $phid and $userid; + + return make_link($remote, $userid, $phid, 0, $u_embed, $ditemid); + }; + $$eventref =~ s!]*)>!$replace->($1)!eg; +} + +1; diff --git a/ljcom/cgi-bin/portal-local.pl b/ljcom/cgi-bin/portal-local.pl new file mode 100644 index 0000000..82844ea --- /dev/null +++ b/ljcom/cgi-bin/portal-local.pl @@ -0,0 +1,125 @@ +#!/usr/bin/perl +# + +use strict; + +package LJ::Portal; +use vars qw(%box); + +$box{'newtolj'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $b = $opts->{'body'}; + + box_start($b, $box, { 'title' => "About $LJ::SITENAME", + 'align' => "left", + 'url' => '/site/about.bml', }); + + $$b .= "New to $LJ::SITENAME?"; + my @links = ("What is $LJ::SITENAME?", "/site/about.bml", + "Create an account!", "/create.bml"); + while (@links) { + my $link = shift @links; + my $url = shift @links; + $$b .= "
  • $link\n"; + } + + box_end($b, $box); + $$b .= "\n"; + }, +}; + +############################################################################ + +$box{'goat'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'opts' => [ { 'key' => 'misbehaved', + 'name' => '', + 'des' => '', + 'type' => 'check', + 'value' => 1, + 'default' => 0, }, + { 'key' => 'goattext', + 'name' => '', + 'des' => '', + 'type' => 'text', + 'default' => "Baaaaah", + 'size' => 40, + 'maxlength' => 40, }, + ], + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $b = $opts->{'body'}; + my $bo = $opts->{'bodyopts'}; + my $h = $opts->{'head'}; + my $pic; + + if ($opts->{'form'}->{'frank'} eq "urinate" || $box->{'args'}->{'misbehaved'}) { + $pic = "pee"; + } else { + $pic = "hover"; + } + + box_start($b, $box, { 'title' => "Frank", + 'align' => "center", + 'url' => "/site/goat.bml", }); + + my $imgname = "frankani" . $box->{'uniq'}; + my $goattext = $box->{'args'}->{'goattext'} || "Baaaah"; + + $$b .= <<"GOAT_STUFF"; +Frank, the LiveJournal mascot goat.
    +"$goattext" says Frank. +GOAT_STUFF + + box_end($b, $box); + + $opts->{'onload'}->{"MM_preloadImages('$LJ::IMGPREFIX/goat-$pic.gif');"} = 1; + + unless ($opts->{'did'}->{'image_javascript'}) + { + $opts->{'did'}->{'image_javascript'} = 1; + + $$h .= <<'JAVASCRIPT'; + +JAVASCRIPT + + } # end unless + + + }, # end handler + +}; + +############################################################################ diff --git a/ljcom/cgi-bin/redirect-local.dat b/ljcom/cgi-bin/redirect-local.dat new file mode 100644 index 0000000..ff02ce7 --- /dev/null +++ b/ljcom/cgi-bin/redirect-local.dat @@ -0,0 +1,12 @@ +/legal/coppa.bml /legal/privacy.bml +/site/contract.bml /legal/principles.bml +/todo.bml /todo/?user=lj_biz +/press.bml /press/ +/site/map.bml /site/ +/goat.bml /site/goat.bml +/clients /download/ +/download/win32/source.bml /code/clients/win32/ +/sitemap.bml /site/ +/contributors.bml /site/contributors.bml +/supporters.bml /paidaccounts/ +/free.bml /site/about.bml diff --git a/ljcom/cvs/multicvs-local.conf b/ljcom/cvs/multicvs-local.conf new file mode 100644 index 0000000..bece8c3 --- /dev/null +++ b/ljcom/cvs/multicvs-local.conf @@ -0,0 +1,13 @@ +ljcom/htdocs/legal/tos-mini.bml ssldocs/legal/tos-mini.bml +ljcomint/site? . +ljcomint/other_sites? other_sites +ljcomint/other_sites/phonepost/cgi-bin/mp3encode.pl? cgi-bin/mp3encode.pl +ljcomint/doc/sysban-notes? doc/sysban-notes +ljcomint/site/htdocs/stc/xc? ssldocs/img/xc +ljcomint/config/diskless/hostsdir/web/etc/init.d/ljstatscasterd? bin/lj-init.d/ljstatscasterd +wcmtools/mogilefs? src/mogilefs +wcmtools/lib/Danga-Socket? src/perlbal/lib/Danga +ljcomint/doc/abuse/policies.xml? doc/abuse/policies.xml +ljcomint/doc/abuse/policies.dtd? doc/abuse/policies.dtd +ljcomint/tools/webnoded/webnoded.pl? bin/webnoded.pl +ljcomint/tools/dsri.pl? bin/dsri.pl diff --git a/ljcom/doc/raw/build/style.css b/ljcom/doc/raw/build/style.css new file mode 100644 index 0000000..78aecd2 --- /dev/null +++ b/ljcom/doc/raw/build/style.css @@ -0,0 +1,95 @@ +li { margin-top: 10px; } +body { + font-family: sans-serif; + background: #eeeeee; + margin: 0; padding: 0; +} +/* IE hack, works around no child-selector bug */ +* html body { + margin: 15px; + m\argin: 15px; +} +body > * { margin: 15px; padding: auto; } +body > div.navheader { margin: 0; padding: 0;} + +a { color: #b77f4e; } +a:visited { color: #a84510; } +h1, h2, h3 { color: #000000; } + +a.linkhere, a.linkhere:visited { + color: black; text-decoration: none; + margin-right: 5px; +} + +h2 a { color: black; } +h3 a { color: black; } +dt a { color: black; } + +dt { font-weight: bold; font-style: italic; margin-top: 7px; } +dl { margin-left: 40px; } + +h2 { + border-top: 2px solid #8fc3f7; + border-left: 2px solid #8fc3f7; + padding: 3px; + background: #69c; +} +h3 { + border-bottom: 2px dotted #a84510; + margin-bottom: 3px; +} +h3+p { margin-top: 4px; } + +p.toplink { font-size: 0.8em; } + +hr { display: none; } + +div.navheader +{ + width: 100%; + background-color: #036; + color: #fff; + border-top-style: solid; + border-top-width: 1px; +} + +/* FIXME: make bottom bar prettier */ +div.navfooter +{ + border-top: 1px solid #036; +} + +div.navheader a, div.navheader a:visited { + color: #fff; +} + +.question { font-weight: bold; } + +.toc dt { font-weight: normal; } +.toc dt a { font-weight: bold; } + +.ulink { color: #00f; } +.ulink img { border: 0; } + +.informaltable table tr td { + padding-right: 5px; +} + +.programlisting { + background-color: #9cc; + padding-left: 15px; + border-left: 2px solid #000; +} + +.screen { font-weight: bold; } + +.guibutton { + border: 1px solid #000; + padding-left: 2px; + padding-right: 2px; + background-color: #aaf; + color: #000; + font-weight: bold; + font-family: monospace; +} +.guilabel { font-family: monospace; } diff --git a/ljcom/doc/raw/local/build-webslave.txt b/ljcom/doc/raw/local/build-webslave.txt new file mode 100644 index 0000000..5bd0c5f --- /dev/null +++ b/ljcom/doc/raw/local/build-webslave.txt @@ -0,0 +1,219 @@ +Installing Debian on a new LJ web slave +======================================= + +Rebuilding an existing machine? + + * Take machine down on BIG-IP (optional. if not, one or two + dropped connections before BIG-IP does it for us) + +Setting up a new machine? + + * allocate an IP address, set it up on internal DNS server + + * let that IP address SNAT out of the BIG-IP + +* Reboot machine with Debian CD. If machine has no CD-ROM, open case + and attach CD-ROM to an IDE channel. + +* at "boot:" prompt, press + +Debian installation menu: + +* Configure keyboard: qwerty + +* Partition hard disk: + + hda1 4000 / * bootable + hda2 15000 /home + hda3 1500 (swap) + + (make swap double ram, / 4G, and the rest to /home) + +* Init swap partition + +* Init Linux Partitions: + + /, then /home + (hit enter a lot, but but 'no' to linux 2.0 compatibility) + +* Install operating system kernel & modules + + from cdrom + where does it reside? hit enter (universal solution) + 'default': The default stable archive + +* Configure Device Driver modules + + - skip the floppy module step, yes, + - net: eepro100, enter, enter, enter + - exit, exit. + +* Configure the network + + hostname: lj-foo + DHCP config? no. + IP: 10.0.0.n + Netmask: 255.255.255.0 + Gateway: 10.0.0.14 + Domain name: lj + DNS: 10.2.0.1 + +* Install the base system + + from cdrom, enter, enter, where reside? enter. + default stable archive + +* Configure the base system + + US/Pacific + Hardware clock to GMT? Yes. + +* Make Linux Bootable directly from hard disk + + on /dev/hda + +* Take out CDROM + +* Reboot the System + +Debian System Configuration: + +* MD5 passwords? yes. + +* Shadow passwords? yes. + +* Root password: ************* + +* Normal user account? yes: + + username: lj + fullname: LiveJournal + password: *********** + +* Remove PCMCIA? yes. + +* PPP? no. + +* Select method apt will access Debian archive: http + + non-US? yes. + non-free? yes. + contrib? yes. + country: US, http.us.washington.edu + proxy: http://10.0.0.17:3128/ + +* Add other apt source? no. + +* Addition software method? simple. + +* Tab, enter... Finish. (get nothing now) + +* new packages need to be installed? continue? + +* exim configuration: 5 (we're gonna scrap it later) + +* erase debs? , yes. + +* "Have fun!", debian says. (Aren't we already?) + +Out of the installer: + +* login as root + +lj-foo:~# ae /etc/apt/sources.list + + Make the file be these two lines: + + deb http://http.us.debian.org/debian/ unstable main non-free contrib + deb http://non-us.debian.org/debian-non-US unstable/non-US main contrib non-free + +lj-foo:~# export http_proxy="http://10.0.0.17:3128/" +lj-foo:~# apt-get update +lj-foo:~# apt-get dist-upgrade + +More debconf! + +System readable homes? sure. (no public user accounts anyway) +Restart services? yeah. +use installer's conf file for PAM? I (yeah) (and whenever else) +exim config: 5 again +groff-base: I + +lj-foo:~# apt-get install ssh +enter, enter, enter. + +lj-foo:~# apt-get install lynx + +lj-foo:~# lynx -source http://www.livejournal.com/misc/pkg-webslave.txt | xargs apt-get -y install + +If Squid cache is being a bitch, disable it for any missing packages: + +lj-foo:~# lynx -source http://www.livejournal.com/misc/pkg-webslave.txt | http_proxy='' xargs apt-get -y install + +Ntpdate debconf: + + Timeserver? 'timeserver' (internal DNS name) + + +######### Warning: non-hax0rs can stop here ################ + +lj-foo:~# mount +# Then for each ext2 mount do: +lj-foo:~# tune2fs -i 0 -c 0 -j /dev/hda1 +lj-foo:~# tune2fs -i 0 -c 0 -j /dev/hda2 + +* change /etc/fstab to be 'auto' instead of 'ext2' + +* vga=1 in /etc/lilo.conf + +* put new kernel on machine with ext3 (static), smp, etc. + +* copy /etc/init.d/mii-tool from another machine + +* update-rc.d mii-tool start 41 S . + +* reboot + +* add ulimit -u 1024 to the bottom of /etc/profile + +* apt-get install postfix + copy /etc/postfix/* over from another debian machine. + Modify the bottom of /etc/postfix/main.cf to match the host. + Run "postalias /etc/aliases" + Restart postfix. + +* copy /etc/apache/* over from another debian machine. + Replace in the machine's IP and hostnamee. + +* copy /etc/snmp/snmpd.conf over from another debian machine. + Restart snmpd. + +* /etc/init.d/inetd.stop + chmod -x /etc/init.d/inetd (update-rc.d -f inetd remove ?) + +* rsync as user lj + mkdir logs + mkdir temp + mkdir var + rm .procmailrc + +* copy /etc/init.d/ljrpcd over from another debian machine. + run update-rc.d ljrpcd defaults 50 + /etc/init.d/ljrpcd start + +* restart apache + +* run ssh-keygen, put slave:~/.ssh/identity.pub in + masterweb:~/.ssh/authorized_keys + +* put masterweb:~/.ssh/id_rsa.pub in + slave:~/.ssh/authorized_keys2 + +* copy lj cron and root cron from another debian web slave over. + +(work in progress ... much more coming soon) + + + + + diff --git a/ljcom/doc/raw/local/cabinets.txt b/ljcom/doc/raw/local/cabinets.txt new file mode 100755 index 0000000..ca6aa67 --- /dev/null +++ b/ljcom/doc/raw/local/cabinets.txt @@ -0,0 +1,53 @@ +Switch Ports: +3 - Wendy +4 - Terrance +5 - Kyle +6 - Mackey +7 - Bebe +8 - Ike +9- Pip +10- phillip +11- Stan +12- Hat +13 - Marklar +14- Gerald +15- blank +16- Sheila +17 blank +18- Mayor +19- Jesus +20- blank +21- blank +22- blank +23- blank +24- Timmy +25- blank +26- Gobbles +27- blank +28- BIG/ip +29 blank +30- Cartman + +Order of stuff in cabinet: +OLD CISCO +Wendy +Terrance +Kyle +Mackey +Bebe +Ike +Pip +Philip +Stan +Hat +BIG/IP +Timmy +Gobbles +Mayor +CISCO +Marklar +Jesus +Kenny +Gerald +Sheila +RAID ENCLOSURE diff --git a/ljcom/doc/raw/local/goals-visualize.pl b/ljcom/doc/raw/local/goals-visualize.pl new file mode 100755 index 0000000..fea7916 --- /dev/null +++ b/ljcom/doc/raw/local/goals-visualize.pl @@ -0,0 +1,96 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; + +my $dir = "$ENV{'LJHOME'}/doc/raw/local/"; +my $outdir = "$ENV{'LJHOME'}/htdocs/misc/goals"; + +my $opt_rand = 0; +exit 1 unless + GetOptions('random' => \$opt_rand); + +my @ltime = localtime(); +my $basefile = sprintf("goals-%04d%02d%02d", $ltime[5]+1900, $ltime[4]+1, $ltime[3]); + +print "basefile: $basefile\n"; + +exit 1 + unless ($opt_rand || + (stat("$dir/goals.dat"))[9] > (stat("$outdir/$basefile.html"))[9]); + +open (I, "$dir/goals.dat"); + +open (O, ">$dir/goals.dot"); +print O "digraph goals {\n"; +print O "bgcolor=\"white\";\n"; +print O "size=\"20,15\";\n"; +print O "node [fontsize=17,fontname=\"Verdana\"]\n"; +my %notes; +my %nodeid; +my $num = 0; +my @lines = ; +close I; + +my @no_notes; +foreach (@lines) +{ + chomp; + s/\#.+//; + + if (/:/) { + my ($k, $n) = split(/\s*:\s*/); + $notes{$k} = $n; + next; + } + push @no_notes, $_; +} +@lines = @no_notes; + +if ($opt_rand) { + srand; + for (my $i=0; $i<@lines; $i++) { + unshift @lines, splice(@lines, $i + int(rand(@lines-$i)), 1); + } +} + +foreach (@lines) +{ + my ($a, $b) = split(/\s*\-\>\s*/); + next unless $a and $b; + foreach my $t ($a, $b) { + next if $nodeid{$t}; + my $id = "n" . (++$num); + $nodeid{$t} = $id; + my $label = "$t"; + my $color = "lightgray"; + if ($notes{$t} =~ s/\(X\)//) { + $color = "green"; + } elsif ($notes{$t} =~ s/\(\+\)//) { + $color = "yellow"; + } elsif ($notes{$t} =~ s/\(\-\)//) { + $color = "white"; + } + + if ($notes{$t}) { + $label .= "\\n($notes{$t})"; + } + + $color = $color ? ", color=\"black\", style=\"filled\", fillcolor=\"$color\"" : ""; + print O "$id [label=\"$label\" $color]\n"; + } + print O "$nodeid{$a} -> $nodeid{$b}\n"; +} + +print O "}\n"; +close O; + +$ENV{'DOTFONTPATH'} = "/usr/share/fonts/truetype"; +system("dot", "-Tgif", "-o", "$outdir/$basefile.gif", "$dir/goals.dot"); +open (O, ">$outdir/$basefile.html"); +printf O "Goals as of: %04d-%02d-%02d

    ", + $ltime[5]+1900, $ltime[4]+1, $ltime[3]; +close O; + +print "Rebuilt.\n"; diff --git a/ljcom/doc/raw/local/goals.dat b/ljcom/doc/raw/local/goals.dat new file mode 100644 index 0000000..fc02ac0 --- /dev/null +++ b/ljcom/doc/raw/local/goals.dat @@ -0,0 +1,47 @@ +S2: mart, bradfitz +screening/moderation: avva (+) +stats daemon: dormando (+) +tech docs: jproulx (+) + +bandwidth -> keep site running +employees -> keep site running + +screening/moderation -> no invite codes +S2 -> customization +S2 -> S2 paid features +S2 paid features -> paid features +backup client -> happy customers +backup client -> reliable service +config 2nd bigip -> redundancy +correctness -> happy customers +customization -> ease of use +customization -> happy customers +tech docs -> releases +tech docs -> more installations +ease of use -> growth +ease of use -> happy customers +growth -> money +happy customers -> money +english removal -> releases +releases -> more installations +english removal -> translation +translation -> growth +limits -> no invite codes +limits -> reliable service +money -> bandwidth +money -> employees +cool stuff -> happy customers +no invite codes -> growth +paid features -> money +rate limiting -> limits +redundancy -> reliable service +more installations -> more developers +reliable service -> growth +reliable service -> happy customers +size limits -> limits +stats daemon -> user stats +stats daemon -> rate limiting +user stats -> paid features +syndication -> growth +syndication -> cool stuff + diff --git a/ljcom/doc/raw/local/hardware.dtd b/ljcom/doc/raw/local/hardware.dtd new file mode 100644 index 0000000..dd79a8a --- /dev/null +++ b/ljcom/doc/raw/local/hardware.dtd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ljcom/doc/raw/local/hardware.xml b/ljcom/doc/raw/local/hardware.xml new file mode 100644 index 0000000..9bfc337 --- /dev/null +++ b/ljcom/doc/raw/local/hardware.xml @@ -0,0 +1,633 @@ + + + + + + + server + Dell + 6 + Dual P3 (Coppermine) 933 Mhz + 2 GB + SCSI: 2x9 GB, 2x18 GB + AMI MegaRAID card + eepro100 + + + db + Debian + 9 GB + 36 GB + 10.0.0.1 + 2 + + +Kenny was one of our first two servers. We bought it at the +same time as Cartman. Kenny was our web server and +named so we could say "You killed Kenny, you bastard!" since +we anticipated growth faster than we could buy new servers. + + + + + + server + Dell + 6 + Dual P3 (Coppermine) 866 Mhz + 2 GB + SCSI: 2x9 GB, 2x18 GB, 2x18 GB 10k + AMI MegaRAID card + eepro100 + + + cluster master + Debian + 9 GB + 36 GB (1 hotspare) + 10.0.0.2 + 1 + + +Cartman was one of our first two servers along with Kenny. +Cartman's a big fat ass, and so was this thing, both in +physical size and disk space. It was our master database +server until we got Jesus and Kyle's mom. Now it's a +cluster master. + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 800 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + web + Debian + 10.0.0.3 + + +Stan and Kyle were bought at the same time. No front panel. +hda serial: IBM-DTLA-307020 - Model: IBM 75GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 800 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + web + mail backup + FreeBSD + 10.0.0.4 + + +Stan and Kyle were bought at the same time. No front panel. +hda serial: IBM-DTLA-307020 - Model: IBM 75GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 800 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + web + Debian + 10.0.0.5 + + +Bought with Bebe. Named as such because we have a 60% female user base and had no female servers. + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 800 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + mail + userpic + Debian + 10.0.0.6 + + +Bought with Wendy. They're best friends. +hda serial: IBM-DTLA-307020 - Model: IBM 75GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 866 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + web + FreeBSD + 10.0.0.7 + + +Bought with Phillip. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 866 Mhz + 512 MB + IDE: 18 GB + eepro100 + + + web + Debian + 10.0.0.8 + + +Bought with Terrance. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 1 Ghz + 3.5 GB + SCSI: 3x18 GB (IBM: DDYS-T18350M) + 64 MB Mylex AcceleRAID 170 PCI RAID Controller + eepro100 + + + db + dns + Debian + 36 GB + 10.0.0.9 + 4 + + +Mackey and Hat (Mr. Mackey and Mr. Hat) were our first 1U db slaves. + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 1 Ghz + 3 GB + SCSI: 3x18 GB (IBM: DDYS-T18350M) + 64 MB Mylex AcceleRAID 170 PCI RAID Controller + eepro100 + + + db + Debian + 36 GB + 10.0.0.10 + 5 + + +Mackey and Hat (Mr. Mackey and Mr. Hat) were our first 1U db slaves. + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 1Ghz + 512 MB + IDE: 18GB + eepro100 + + + web + Debian + 10.0.0.11 + + +Bought with Pip. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Coppermine) 1Ghz + 512 MB + IDE: 18GB + eepro100 + + + userpic + Debian + 10.0.0.12 + + +Bought with Ike. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ESS + 1 + Dual P3 (Coppermine) 1 Ghz + 2 GB + SCSI: 2x18 GB (IBM) + 64 MB Mylex AcceleRAID 170 PCI RAID Controller + eepro100 + + + db + Debian + 36G + 10.0.0.13 + 6 + + +Timmy and Gobbles. They took more than a month to ship, and arrived +in a non-working state, with some broken hardware. + +One drive died. Now only has 2, in a raid 0 config. + + + + + + server + ASL + 2 + Dual P3 (Coppermine) 933 Mhz + 3.5 GB + SCSI: 6x18 GB (IBM DDYS-T18350M) + Mylex AcceleRAID 352, 64 MB (dac960) + eepro100 + + + misc + Debian + 85G + 10.0.0.15 + 3 + + +Brad bought this to replace his old machine at Virtualis, and serves many +misc roles: slave database when needed (if another dies), file backup machine, +log processing, etc. + + + + + + server + ESS + 1 + Dual P3 (Coppermine) 1 Ghz + 3 GB + SCSI: 3x18 GB (IBM) + 64 MB Mylex AcceleRAID 170 PCI RAID Controller + eepro100 + + + db + Debian + 54G + 10.0.0.16 + 7 + + +Timmy and Gobbles. They took more than a month to ship, and arrived +in a non-working state, with some broken hardware. + + + + + + server + ASL + 1 + P3 (Coppermine) 866 Mhz + 256 MB + IDE: 18G + eepro100 + + + staging + dns + netsaint + statserv + Debian + 10.0.0.17 + + +We bought this machine as an 'el cheapo box to run all of the +monitorying/syncronizing software. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Tualatin) 1.26 Ghz + 512 MB + IDE: 18G + eepro100 + + + web + Debian + 10.0.0.18 + + +Bought with sheila. First ones to go above 1 Ghz, and will +function as the new paid web slaves. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 1 + Dual P3 (Tualatin) 1.26 Ghz + 512 MB + IDE: 18G + eepro100 + + + web + Debian + 10.0.0.19 + + +Bought with gerald. First ones to go above 1 Ghz, and will +function as the new paid web slaves. +hda serial: IC35L020AVER07-0 - Model: IBM 60GXP 20.57GB + + + + + + server + ASL + 4 + Dual P3 (Xeon) 700 Mhz (2 MB L2 cache) + 12 GB + SCSI: 1x18 GB + 64 MB IBM ServeRAID-4Mx PCI RAID Controller + eepro100 + + + db + Debian + 10.0.0.20 + 8 + + +This monster is the new master DB. We bought it with room to grow, +still. An identical machine named "santa" will be purchased to run +as a hot spare and slave DB. + + + + + + disk array + IBM + 3 + SCSI: 8x36 GB 10k + + + 139G + + +This is the IBM drive enclosure for Jesus. + + + + + + load balancer + 2 + + + 10.0.0.14 + + +Best frickin' load balancer ever made. + + + + + + switch + lanblvd + 1 + 10/100 mbps port + + + 10.0.0.200 + + +External switch. (2924) + + + + + + switch + lanblvd + 1 + 10/100 mbps port + GBIC port + + + 10.0.0.201 + + +Internal switch. (2948G) +Linked with Multimode (SC-SC) fiber to cisco3. + + + + + + switch + lanblvd + 1 + 10/100 mbps port + GBIC port + + + 10.0.0.201 + + +Internal switch #2 (3500XL) +Linked with Multimode (SC-SC) fiber to cisco2. + + + + + + server + ASL + 1 + Dual P3 (Tualatin) 1.24 Ghz + 4 GB + SCSI: 1x36 GB + eepro100 + + + db + Debian + 10.0.0.21 + 10 + + + + + + server + ASL + 1 + Dual P3 (Tualatin) 1.26 Ghz + 768 MB + IDE: 36G + eepro100 + + + web + Debian + 10.0.0.22 + + +Bought with hankey. +hda serial: IC35L040AVER07 - Model: IBM 60GXP 41.17GB + + + + + + server + ASL + 1 + Dual P3 (Tualatin) 1.26 Ghz + 768 MB + IDE: 36G + eepro100 + + + web + Debian + 10.0.0.23 + + +Bought with marvin. +hda serial: IC35L040AVER07 - Model: IBM 60GXP 41.17GB + + + + + + server + ASL + 2 + Dual P3 (Tualatin) 1.26 Ghz + 4 GB + SCSI: 4x18 GB (IBM: DDYS-T18350M) 2x9 GB + 32 MB Mylex AcceleRAID 352 PCI RAID Controller + eepro100 + redundant power supply + + + cluster master + Debian + 9 GB + 36 GB (1 hotspare) + 10.0.0.24 + 11 + + +First wave of new cluster masters. Bought with Chef. The system +disks were bought separately. + + + + + + server + ASL + 2 + Dual P3 (Tualatin) 1.26 Ghz + 4 GB + SCSI: 4x18 GB (IBM: DDYS-T18350M) 2x9 GB + 32 MB Mylex AcceleRAID 352 PCI RAID Controller + eepro100 + redundant power supply + + + cluster master + Debian + 9 GB + 36 GB (1 hotspare) + 10.0.0.25 + 12 + + +First wave of new cluster masters. Bought with Santa. The system +disks were bought separately. + + + + diff --git a/ljcom/doc/raw/memcache-keys-local.txt b/ljcom/doc/raw/memcache-keys-local.txt new file mode 100644 index 0000000..086c2e0 --- /dev/null +++ b/ljcom/doc/raw/memcache-keys-local.txt @@ -0,0 +1,4 @@ + ppe:: == The phonepostentry row. See phonepost.pl. + ppelt:: == Where bid = blobid of phone post, returns hashref. See phonepost.pl. + ppetu:: == Number of unique transcribers to a post. + cctry: == Array of last 20 times when the user has attempted to pay diff --git a/ljcom/htdocs/404-error.html b/ljcom/htdocs/404-error.html new file mode 100644 index 0000000..1c79f13 --- /dev/null +++ b/ljcom/htdocs/404-error.html @@ -0,0 +1,65 @@ + + +

    Not Found

    +The requested URL was not found on this server. +

    +You may be receiving this error as a result from maintenance or other site problems; please refer to http://status.livejournal.org to keep updated on the status of the site. + + + diff --git a/ljcom/htdocs/500-error.html b/ljcom/htdocs/500-error.html new file mode 100644 index 0000000..688e686 --- /dev/null +++ b/ljcom/htdocs/500-error.html @@ -0,0 +1,65 @@ + + +

    Sorry...

    +We're currently experiencing some technical difficulties. Please try again in a few moments. +

    +You may be receiving this error as a result from maintenance or other site problems; please refer to http://status.livejournal.org to keep updated on the status of the site. + + + diff --git a/ljcom/htdocs/_config-local.bml b/ljcom/htdocs/_config-local.bml new file mode 100644 index 0000000..92c9312 --- /dev/null +++ b/ljcom/htdocs/_config-local.bml @@ -0,0 +1,4 @@ +DoGZIP 1 +DefaultLanguage en_LJ +DefaultScheme xcolibur + diff --git a/ljcom/htdocs/admin/abuse/index.bml b/ljcom/htdocs/admin/abuse/index.bml new file mode 100644 index 0000000..0386e14 --- /dev/null +++ b/ljcom/htdocs/admin/abuse/index.bml @@ -0,0 +1,30 @@ + + If you need to file an abuse request, please do so at: + http://www.livejournal.com/abuse/report.bml p?>"; + } else { + $body .= <<"BLURB"; +Current Tools:
    +

    +BLURB + } + + return; +_code?> +body=> +page?> +link: htdocs/admin/abuse/mail.bml +link: htdocs/support/submit.bml + _c?> diff --git a/ljcom/htdocs/admin/abuse/query.bml b/ljcom/htdocs/admin/abuse/query.bml new file mode 100644 index 0000000..983b6ce --- /dev/null +++ b/ljcom/htdocs/admin/abuse/query.bml @@ -0,0 +1,10 @@ + +<=body +page?> diff --git a/ljcom/htdocs/admin/abuse/send_mail.bml b/ljcom/htdocs/admin/abuse/send_mail.bml new file mode 100644 index 0000000..3a2861a --- /dev/null +++ b/ljcom/htdocs/admin/abuse/send_mail.bml @@ -0,0 +1,12 @@ + +<=body +page?> +link: htdocs/admin/abuse/index.bml + _c?> diff --git a/ljcom/htdocs/admin/accounts/acctedit.bml b/ljcom/htdocs/admin/accounts/acctedit.bml new file mode 100644 index 0000000..945e5b7 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/acctedit.bml @@ -0,0 +1,309 @@ +log in." + unless $remote; + + return LJ::no_access_error("You don't have access to use this tool.", "moneyenter") + unless LJ::remote_has_priv($remote, "moneyenter"); + + # heading + my $ret = "

    Account Management

    "; + + # no user specified, get one + unless ($GET{'user'}) { + $ret .= "
    "; + $ret .= "User: " . LJ::html_text({ 'name' => 'user', 'size' => 15, 'maxlength' => 15 }) . " "; + $ret .= LJ::html_submit('Load'); + $ret .= "
    "; + return $ret; + } + + # load user + my $user = LJ::canonical_username($GET{'user'}); + my $u = LJ::load_user($user, "force"); + return "Invalid user: '$user'" unless $u; + + # establish some cap bit -> item mappings + my %bonus_caps = map { $LJ::Pay::bonus{$_}->{'cap'}, $_ } keys %LJ::Pay::bonus; + + my $zerodate = "0000-00-00 00:00:00"; + + my $dbh = LJ::get_db_writer(); + + # save chanes + if (LJ::did_post()) { + + # 'notes' field is required + return "" unless $POST{'notes'}; + + my @bits_set; + my @bits_del; + my $logmsg; + + # save bit-only features + foreach my $bit (0..14) { + + # make sure $bit is a valid cap as specified by %LJ::CAP (for general caps), + # or either %LJ::Pay::capinf or %LJ::Pay::bonus (for local caps) + next unless + ( ref $LJ::CAP{$bit} eq 'HASH' || + (grep { defined $_->{cap} && $_->{cap} == $bit } values %LJ::Pay::bonus) || + (grep { defined $_->{cap} && $_->{cap} == $bit } values %LJ::Pay::capinf) ); + + # build bit mask to set at the end + unless ($POST{"cap_${bit}_set"}) { + push @bits_del, $bit; + next; + } + + push @bits_set, $bit; + } + + # save paid account expiration + { + my $exp = $POST{'paid_exp'}; + + # check expiration date format + if (defined $exp) { + return "Error: Invalid expiration date format, expecting: yyyy-mm-dd hh:mm:ss" + unless $exp =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/; + } + + # does a paiduser row already exist? + my $paiduntil = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=?", + undef, $u->{'userid'}); + + # update existing row + if ($paiduntil) { + + # if expdate is 0000-00-00 00:00:00, just delete the row + if ($exp eq $zerodate) { + $dbh->do("DELETE FROM paiduser WHERE userid=?", undef, $u->{'userid'}); + + $logmsg .= "[delete] item: paid_account, paiduntil: $exp\n"; + } + + # unnecessary query? + next if $paiduntil eq $exp; + + # otherwise do an update + $dbh->do("UPDATE paiduser SET paiduntil=? WHERE userid=?", + undef, $exp, $u->{'userid'}); + + $logmsg .= "[update] item: paid_account, paiduntil: $exp\n"; + + # insert new, non-blank, row + } elsif ($exp ne $zerodate) { + $dbh->do("INSERT INTO paiduser (userid, paiduntil) " . + "VALUES (?, ?)", undef, $u->{'userid'}, $exp); + + $logmsg .= "[insert] item: paid_account, paiduntil: $exp\n"; + } + } + + + # update bonus feature + foreach my $itemname (sort keys %LJ::Pay::bonus) { + my $bitem = $LJ::Pay::bonus{$itemname}; + next unless ref $bitem eq 'HASH'; + + my ($exp, $size, $days) = map { $POST{"${itemname}_$_"} } qw(exp size daysleft); + + # check expiration date format + if (defined $exp) { + return "Error: Invalid expiration date format, expecting: yyyy-mm-dd hh:mm:ss" + unless $exp =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/; + } + + # see if row exists + my $dbrow = $dbh->selectrow_hashref("SELECT expdate, size, daysleft FROM paidexp " . + "WHERE userid=? AND item=?", + undef, $u->{'userid'}, $itemname); + + # row exists, do an update + if ($dbrow) { + + # if a zero row, just delete + if ($exp eq $zerodate && ! $size && ! $days) { + $dbh->do("DELETE FROM paidexp WHERE userid=? AND item=?", undef, $u->{'userid'}, $itemname); + $logmsg .= "[delete] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; + + next; + } + + # prepare update query + my $sets; + $sets .= "expdate=" . $dbh->quote($exp) . "," if defined $exp && $dbrow->{'expdate'} ne $exp; + $sets .= "size=" . $dbh->quote($size) . "," if defined $size && $dbrow->{'size'} != $size; + $sets .= "daysleft=" . $dbh->quote($days) . "," if defined $days && $dbrow->{'daysleft'} != $days; + chop $sets if $sets; + + # unnecessary query? + next unless $sets; + + # otherwise do an update + $dbh->do("UPDATE paidexp SET $sets WHERE userid=? AND item=?", + undef, $u->{'userid'}, $itemname); + + $logmsg .= "[update] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; + + # if no rows, then we need to insert a new row, but not an empty one + } elsif ($exp ne $zerodate || $size > 0 || $days > 0) { + $exp ||= $zerodate; + $size ||= 0; + $days ||= 0; + + $dbh->do("INSERT INTO paidexp (userid, item, size, expdate, daysleft) VALUES (?, ?, ?, ?, ?)", + undef, $u->{'userid'}, $itemname, $size, $exp, $days); + + $logmsg .= "[insert] item: $itemname, expdate: $exp, size: $size, daysleft: $days\n"; + } + + # call any necessary apply_hooks + my $apply_hook = $bitem->{apply_hook}; + if ($apply_hook && ref $apply_hook eq 'CODE') { + $apply_hook->($u, $itemname); + } + } + + # note which caps were changed and log $logmsg to statushistory + { + my $caps_add = join(",", @bits_set); + my $caps_del = join(",", @bits_del); + $logmsg .= "[caps] add: $caps_add, del: $caps_del\n"; + $logmsg .= "[notes] $POST{'notes'}"; + + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "acctedit", $logmsg); + } + + # done looping through possible bits + LJ::modify_caps($u, \@bits_set, \@bits_del); + + return ""; + } + + + ### update form + + $ret .= "
    "; + $ret .= ""; + $ret .= ""; + + # so we know which bits to skip when going through %LJ::CAP hash + my %special_bit = ($LJ::Pay::capinf{'paid'}->{'bit'} => 1); + while (my ($itemname, $ref) = each %LJ::Pay::bonus) { + $special_bit{$ref->{'cap'}} = 1; + } + + # do bit-only features + foreach my $bit (sort { $a <=> $b } keys %LJ::CAP) { + next unless ref $LJ::CAP{$bit} eq 'HASH'; + next if $special_bit{$bit}; + + my $has_cap = $u->{'caps'} & 1 << $bit || 0; + my $name = $LJ::CAP{$bit}->{'_name'} || "(no name)"; + $name = "$name" if $has_cap; + $ret .= ""; + + # expiration + $ret .= ""; + } + + # paid account status + { + my $bit = $LJ::Pay::capinf{'paid'}->{'bit'}; + my $has_cap = $u->{'caps'} & 1 << $bit || 0; + my $name = "Paid Account"; + $name = "$name" if $has_cap; + $ret .= ""; + + $ret .= ""; + + # get paid account status from database + my $exp = $dbh->selectrow_array("SELECT paiduntil FROM paiduser WHERE userid=?", + undef, $u->{'userid'}); + + # expiration text box + $ret .= ""; + } + + # bonus features + foreach my $itemname (sort { $LJ::Pay::bonus{$a}->{'bit'} <=> $LJ::Pay::bonus{$b}->{'bit'} } keys %LJ::Pay::bonus) { + my $bitem = $LJ::Pay::bonus{$itemname}; + next unless ref $bitem eq 'HASH'; + + my $bit = $bitem->{'cap'}; + my $has_cap = $u->{'caps'} & 1 << $bit || 0; + my $name = $bitem->{'name'}; + $name = "$name" if $has_cap; + $ret .= ""; + + $ret .= ""; + + # get activation status from the db + my ($exp, $size, $daysleft) = + $dbh->selectrow_array("SELECT expdate, size, daysleft FROM paidexp " . + "WHERE userid=? AND item=?", + undef, $u->{'userid'}, $itemname); + $size += 0; + $daysleft += 0; + + # expire text box + $ret .= ""; + } + + + $ret .= ""; + + $ret .= "
    BitClassSet?Expiration
    $bit"; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", + 'id' => "cap_${bit}_set", 'value' => 1, + 'selected' => $has_cap }) . " 
    $bit"; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", + 'id' => "cap_${bit}_set", 'value' => 1, + 'selected' => $has_cap }) . ""; + $ret .= LJ::html_text({ 'name' => "paid_exp", 'value' => $exp || $zerodate, + 'size' => 19, 'maxlength' => 19 }); + + $ret .= "
    $bit"; + if (defined $bit) { + $ret .= LJ::html_check({ 'type' => 'check', 'name' => "cap_${bit}_set", + 'id' => "cap_${bit}_set", 'value' => 1, + 'selected' => $has_cap }); + } else { + $ret .= " "; + } + $ret .= ""; + $ret .= LJ::html_text({ 'name' => "${itemname}_exp", 'value' => $exp || $zerodate, + 'size' => 19, 'maxlength' => 19 }); + + # need a size box? + if (LJ::Pay::is_bonus($bonus_caps{$bit}, 'sized')) { + $ret .= "
    Size: "; + $ret .= LJ::html_text({ 'name' => => "${itemname}_size", 'value' => $size, + 'size' => 5, 'maxlength' => 5 }); + } + + # daysleft text box + $ret .= "
    Daysleft: "; + $ret .= LJ::html_text({ 'name' => => "${itemname}_daysleft", 'value' => $daysleft, + 'size' => 3, 'maxlength' => 3 }); + + $ret .= "
    Notes: (required)
    "; + $ret .= LJ::html_textarea({ 'name' => 'notes', 'rows' => 3, 'cols' => 60, 'wrap' => 'soft' }); + $ret .= "
    "; + $ret .= LJ::html_submit('Update') . "
    "; + $ret .= "
    "; + + return $ret; + +} + +_code?> + diff --git a/ljcom/htdocs/admin/accounts/delivernow.bml b/ljcom/htdocs/admin/accounts/delivernow.bml new file mode 100644 index 0000000..f4d0175 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/delivernow.bml @@ -0,0 +1,43 @@ +log in." + unless $remote; + + return "You don't have access to use this tool." + unless LJ::remote_has_priv($remote, "moneyenter"); + + if ($POST{'payid'} && $POST{'piid'}) { + my $dbh = LJ::get_db_writer(); + + my ($piid, $status) = + $dbh->selectrow_array("SELECT piid, status FROM payitems " . + "WHERE piid=? AND payid=?", + undef, $POST{'piid'}, $POST{'payid'}); + + return "Error: Payid/Piid pair not found!" + unless $piid; + + return "Error: Status = '$status' (not 'pending')" + unless $status eq 'pend'; + + $dbh->do("UPDATE payitems SET giveafter=NULL " . + "WHERE piid=? AND payid=? AND status='pend'", + undef, $POST{'piid'}, $POST{'payid'}); + + return "Success: Delivery date set to now. " . + "(PAYID: $POST{'payid'}, PIID: $POST{'piid'})"; + } + + return "This tool will will set an item's delivery date to be now." . + "
    \n" . + "

    Payid: " . LJ::html_text({ 'name' => 'payid', 'size' => 10 }) . "\n" . + "Piid: " . LJ::html_text({ 'name' => 'piid', 'size' => 10 }) . "

    \n" . + LJ::html_submit(undef, 'Change'); + "
    \n"; + +} +_code?> diff --git a/ljcom/htdocs/admin/accounts/depositslip.bml b/ljcom/htdocs/admin/accounts/depositslip.bml new file mode 100644 index 0000000..4c8b774 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/depositslip.bml @@ -0,0 +1,88 @@ + +Deposit Slip + + + +log in."; + } + } + + my $from = $GET{'from'}; + unless (defined $from) { + $ret .= "
    after (yyyy-mm-dd[ hh:mm[:ss]]): Opt. end:
    "; + return $ret; + } + + my $to = $GET{'to'} || $dbh->selectrow_array("SELECT NOW()"); + + $sth = $dbh->prepare("SELECT p.payid, u.user, p.daterecv, p.amount, p.months, p.forwhat, p.used, p.mailed, p.method FROM payments p LEFT JOIN useridmap u ON u.userid=p.userid WHERE p.mailed<>'C' AND method IN ('cash', 'check', 'moneyorder') AND p.daterecv > ? AND p.daterecv <= ? ORDER BY p.daterecv"); + $sth->execute($from, $to); + my @pays; + push @pays, $_ while $_ = $sth->fetchrow_hashref; + + return "(none)" unless @pays; + + my $in = join(',', map { $_->{'payid'} } @pays); + $sth = $dbh->prepare("SELECT payid, pval FROM payvars WHERE payid IN ($in) AND pkey='notes'"); + $sth->execute; + my %notes; + while (my ($id, $v) = $sth->fetchrow_array) { + $notes{$id} .= ", " if $notes{$id}; + $notes{$id} = $v; + } + + $ret .= "

    Received Payments

    " . $pays[0]->{'daterecv'} . " to " . + $pays[-1]->{'daterecv'} . ""; + + $ret .= "

    \n"; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + my $tot = 0; + + foreach my $p (@pays) + { + my $amount = sprintf("\$%.02f", $p->{'amount'}); + $tot += $p->{'amount'}; + my $date = substr($p->{'daterecv'}, 0, 10); + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + } + + $ret .= "\n"; + $ret .= "
    Order#DateTypeUserNotesAmount
    $p->{'payid'}$date$p->{'method'}$p->{'user'}$notes{$p->{'payid'}}$amount
    \$" . sprintf("%.02f", $tot) . "
    "; + + return $ret; + +} +_code?> + + diff --git a/ljcom/htdocs/admin/accounts/enterbatch.bml b/ljcom/htdocs/admin/accounts/enterbatch.bml new file mode 100644 index 0000000..2406a5b --- /dev/null +++ b/ljcom/htdocs/admin/accounts/enterbatch.bml @@ -0,0 +1,115 @@ + +Enter Batch + +"; + } + + my $do_proc = LJ::did_post() && ! $POST{'new'}; + + my $dbh = LJ::get_db_writer(); + + my $row = sub { + my $i = shift; + my ($cart, $amt, $meth, $country, $state, $notes) = + $POST{'new'} ? () : map { LJ::trim($POST{"${_}_$i"}) } qw(cart amt meth country state notes); + + my $rowhtml = sub { + my $col = shift; + $ret .= $col ? "" : ""; + $ret .= "#" . LJ::html_text({ name => "cart_$i", value => $cart, size => 13 }) . ""; + $ret .= "\$" . LJ::html_text({ name => "amt_$i", value => $amt, size => 6 }) . ""; + $ret .= "" . LJ::html_select({ name => "meth_$i", selected => $meth, }, + qw(check check cash cash moneyorder moneyorder)) . ""; + $ret .= "" . LJ::html_text({ name => "country_$i", value => defined $country ? $country : 'US', + size => 2, maxlength => 70 }) . ""; + $ret .= "" . LJ::html_text({ name => "state_$i", value => $state, + size => 2, maxlength => 70 }) . ""; + $ret .= "" . LJ::html_text({ name => "notes_$i", value => $notes, + size => 60, maxlength => 255 }) . ""; + $ret .= "\n"; + return undef; + }; + + my $err = sub { + my $errmsg = shift; + $rowhtml->("#ff5050"); + $ret .= "$errmsg\n"; + }; + + return $rowhtml->() unless $do_proc && $cart; + return $err->("Invalid order format (should be like 1234-342)") + unless $cart =~ /^\d+-\d+$/; + return $err->("Invalid payment amount") + unless $amt =~ /^\d+(\.\d\d)?$/; + + my $cartobj = LJ::Pay::load_cart($cart); + return $err->("Cannot find order number") unless $cartobj; + return $err->("Order price of \$$cartobj->{'amount'} doesn't match paid amount") + unless $cartobj->{'amount'}*100 == $amt*100; + + # make sure that the cart is valid and ready for processing, but don't do + # checks if the cart is already completely processed, since it doesn't matter + # in that case anyway and errors will likely be found + unless ($cartobj->{'used'} eq 'Y') { + return $err->("Cart is no longer valid. Cannot process payment.") + unless LJ::Pay::is_valid_cart($cartobj); + } + + # validate state/country + { + my $errstr; + my ($ctry, $st) = LJ::Pay::check_country_state($country, $state, \$errstr); + return $err->("Error: $errstr") if $errstr; + + LJ::Pay::payid_set_state($cartobj->{payid}, $ctry, $st); + } + + # only update once (from cart to 'N' (pending)) + $dbh->do("UPDATE payments SET used='N', mailed='N', daterecv=NOW() ". + "WHERE payid=? AND mailed='C'", undef, $cartobj->{'payid'}); + + # allow method to be updated multiple times (to fix error) + $dbh->do("UPDATE payments SET method=? WHERE payid=?", undef, + $meth, $cartobj->{'payid'}); + + # likewise, keep letting notes be added (as long as they're different) + if ($notes && + ! $dbh->selectrow_array("SELECT COUNT(*) FROM payvars WHERE ". + "payid=? AND pkey='notes' AND pval=?", + undef, $cartobj->{'payid'}, $notes)) + { + $dbh->do("INSERT INTO payvars (payid, pkey, pval) VALUES (?,?,?)", undef, + $cartobj->{'payid'}, "notes", $notes); + } + + # Note that we've received a valid payment from this user + # * FIXME: could be faster, but this page is seldom-used + if (my $u = LJ::load_userid($cartobj->{userid})) { + LJ::Pay::note_payment_from_user($u); + } + + return $rowhtml->("#c0ffc0"); + }; + + $ret .= "

    "; + $ret .= "\n"; + for (1..20) { $row->($_); } + $ret .= "
    order numberamt paidmethodcountry,
    state
    internal notes (name, return addr)
    "; + $ret .= "

    "; + return $ret; + +} +_code?> + + diff --git a/ljcom/htdocs/admin/accounts/enternew.bml b/ljcom/htdocs/admin/accounts/enternew.bml new file mode 100644 index 0000000..ca78860 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/enternew.bml @@ -0,0 +1,371 @@ +" unless $remote; + + return "You don't have access to enter payments: need 'moneyenter' priv." + unless LJ::remote_has_priv($remote, "moneyenter"); + + my $grant_perm = LJ::check_priv($remote, "grantperm"); + + my %methods = + ( 'paypal' => 'PayPal', + 'moneybookers' => 'Money Bookers', + 'cash' => 'Cash', + 'check' => 'Check', + 'moneyorder' => 'Money Order', + 'free' => 'Free', + ); + + if (LJ::did_post() && $POST{'submit'}) { + + # determine purchase user and recipient user/email + my $user = LJ::canonical_username($POST{'user'}); + my $giftfrom = LJ::canonical_username($POST{'giftfrom'}); + my $rcptemail = $POST{'email'}; + my $userid = 0; + my $rcptuser = $user; + my $rcptuserid = 0; + + # user, no email + unless ($rcptemail) { + return LJ::bad_input("Invalid user specified.") + unless $user; + + $userid = LJ::get_userid($user) + or return LJ::bad_input("User $user doesn't exist."); + $rcptuserid = $userid; + } + + if ($giftfrom) { + $rcptuser = $user; + $rcptuserid = $userid; + + $user = $giftfrom; + $userid = LJ::get_userid($giftfrom); + + return LJ::bad_input("Gift user $giftfrom doesn't exist.") + unless $userid; + } + + return LJ::bad_input("Invalid recipient specified") + unless $rcptuserid || $rcptemail; + + my %pay; # payments row + my %payit; # payitems row + + return LJ::bad_input("Must enter a dollar amount for this order.") + unless defined $POST{'amount'}; + + # handle $11.11 as well as '11.11' + $POST{'amount'} =~ s/^\$//; + $POST{'amount'} += 0; + $pay{'amount'} = $POST{'amount'}; + $payit{'amt'} = $POST{'amount'}; + + # check for valid method + $pay{'method'} = lc($POST{'method'}); + return LJ::bad_input("Invalid payment method: $pay{'method'}") + unless grep { $pay{'method'} } keys %methods; + + # check datesent format + return LJ::bad_input("Invalid date format.") + unless $POST{'datesent'} =~ /^\d\d\d\d-\d\d-\d\d/; + $pay{'datesent'} = $POST{'datesent'}; + + # paid account + if ($POST{'item'} eq "paidacct") { + + return LJ::bad_input("No months specified or auto-detected. Payment not entered.") + unless $POST{'paidacct_mo'}; + + $payit{'subitem'} = undef; + $payit{'qty'} = $POST{'paidacct_mo'}; + + # perm account + } elsif ($POST{'item'} eq 'perm') { + + # need a special priv to grant perm accounts + return LJ::bad_input("You do not have permission to create permanent accounts.") + unless $grant_perm; + + # coupons + } elsif ($POST{'item'} eq 'coupon') { + + return LJ::bad_input("You selected a coupon but didn't enter a dollar amount.") + unless $POST{'amount'}; + + $payit{'subitem'} = "dollaroff"; + $payit{'subitem'} .= $POST{'coupon_type'} =~ /^(tan|int)$/ ? $POST{'coupon_type'} : ''; + + $payit{'qty'} = undef; + + # userpics + } elsif ($POST{'item'} eq 'userpic') { + + return LJ::bad_input("Cannot send userpics to an email address") + unless $rcptuserid; + + return LJ::bad_input("Must specify a number of months for userpics") + unless $POST{'userpic_mo'}; + + return LJ::bad_input("Cannot apply userpics to the account.") + unless LJ::Pay::can_apply_bool_bonus($rcptuserid, undef, 'userpic'); + + $payit{'qty'} = $POST{'userpic_mo'}; + $payit{'subitem'} = undef; + + # disk quota + } elsif ($POST{'item'} eq 'diskquota') { + + return LJ::bad_input("Cannot send disk quota to an email address") + unless $rcptuserid; + + return LJ::bad_input("Must specify a number of months for disk quota.") + unless $POST{'diskquota_mo'}; + + return LJ::bad_input("Must specify a size (in megabytes) for disk quota.") + unless $POST{'diskquota_size'}; + + return LJ::bad_input("Cannot apply disk quota to account.") + unless LJ::Pay::can_apply_sized_bonus($rcptuserid, undef, 'diskquota', + $POST{'diskquota_size'}, $POST{'diskquota_mo'}); + + $payit{'qty'} = $POST{'diskquota_mo'}; + my ($prev_exp, $prev_size) = LJ::Pay::get_bonus_dim($rcptuserid, 'diskquota'); + $payit{'subitem'} = "$POST{'diskquota_size'}-$prev_exp-$prev_size"; + + # rename token + } elsif ($POST{'item'} eq 'rename') { + + # subitem, qty need to be undef, so that's already fine + + # verify it's a valid item + } else { + return LJ::bad_input("Must select the item the user is paying for."); + } + $payit{'item'} = $POST{'item'}; + $payit{'rcptemail'} = $rcptemail || undef; + $payit{'rcptid'} = $rcptuserid || 0; + + # at this point, the following should be properly set and validated: + # - %pay: (datesent, amount) + # - %payit: (rcptid, rcptemail, amt, item, subitem, qty) + + ### now, insert a payment + + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO payments (anum, userid, datesent, daterecv, amount, " . + "used, mailed, notes, method, forwhat) " . + "VALUES (0, ?, ?, NOW(), ?, 'N', 'N', ?, ?, 'cart')", + undef, $userid, $pay{'datesent'}, $pay{'amount'}, + $POST{'notes'}, $pay{'method'}); + return "errstr . " p?>" if $dbh->err; + + my $payid = $dbh->{'mysql_insertid'}; + $payit{'payid'} = $payid; + $dbh->do("INSERT INTO payvars (payid, pkey, pval) VALUES (?, 'notes', ?)", + undef, $payid, $POST{'inote'}) if $POST{'inote'}; + + # create a coupon if necessary + if ($payit{'item'} eq "coupon") { + + my $type = "dollaroff"; + my $cptype = $POST{'coupon_type'} =~ /^(tan|int)$/ ? $POST{'coupon_type'} : ''; + $type .= $cptype; + + ($payit{'tokenid'}, $payit{'token'}) = + LJ::Pay::new_coupon($type, $payit{'amt'}, $rcptuserid, $payid); + return "" + unless $payit{'tokenid'} && $payit{'token'}; + + my $cpemail = $rcptemail; + if ($rcptuserid) { + my $u = LJ::load_userid($rcptuserid); + $cpemail = $u->{'email'} if $u; + + # we kindasorta trust this user now + LJ::Pay::note_payment_from_user($u); + } + + LJ::Pay::send_coupon_email($cpemail, $payit{'token'}, $payit{'amt'}, $cptype); + } + + # now that we've optionally created a coupon token, log a payitem row + { + my $cartobj = LJ::Pay::load_cart("$payid-0"); + LJ::Pay::add_cart_item($cartobj, \%payit) + or return ""; + } + + # log a statushistory row if there's a userid to associate it with + if ($userid) { + my $mo = $POST{'months'}+0; + my $rcpt = "rcptemail=$rcptemail"; + if ($rcptuserid) { + my $u = LJ::load_userid($rcptuserid); + $rcpt = "rcptuser=$u->{'user'}" if $u; + } + LJ::statushistory_add($userid, $remote->{'userid'}, "payenter", + "item=$payit{'item'}, subitem=$payit{'subitem'}, qty=$payit{'qty'}, amt=$payit{'amt'}, $rcpt"); + } + + # send email notification of this action + my $rcpt = $rcptuser || $rcptemail; + my $msgbody = "Entered by $remote->{'user'}: payment \#$payid for $rcpt\n\n"; + foreach my $k (sort keys %POST) { + $msgbody .= "$k:\n===============\n$POST{$k}\n\n"; + } + LJ::send_mail({ 'to' => "paypal\@$LJ::DOMAIN", # TODO: not paypal + 'from' => $LJ::BOGUS_EMAIL, + 'subject' => "Payment \#$payid -- $rcpt", + 'body' => $msgbody, + }); + + $dbh->do("INSERT INTO paymentsearch (payid, ikey, ival) VALUES (?,?,?)", + undef, $payid, "handemail", $rcptemail) + unless $userid; + + return "$rcpt
    for \$$pay{'amount'} for: p?>
      " . + join("", map { "
    • $_->[0]=$_->[1]
    • " } + (['user' => $user], ['rcptuser' => $rcptuser], ['rcptemail' => $rcptemail], + ['method' => lc($POST{'method'})], ['item' => $payit{'item'}], + ['subitem' => $payit{'subitem'}], ['qty' => $payit{'qty'}], ['token' => $payit{'token'} ]) + ) . + "
    "; + + } + + + # payment form + my $ret; + + $ret = "Hello, $remote->{'user'}! Enter a payment:"; + + $ret .= "
    "; + $ret .= ""; + $row_html .= ""; + } + } + if ($row_ct eq 0) { $body .= ""; return; } + + $body .= "
    "; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= $GET{'newacct'} ? + ("" . + "") : + ("" . + ""); + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + + # notes + $ret .= ""; + + $ret .= ""; + + $ret .= "
    Payment Type:" . LJ::html_select({ 'name' => 'method' }, + '', '(select)', map { $_ => $methods{$_} } keys %methods) . "
    Rcpt Email:" . LJ::html_text({ 'name' => 'email', 'size' => '40', 'maxlength' => 50 }) . + "(back)Rcpt Username:" . LJ::html_text({ 'name' => 'user', 'size' => 15, 'maxlength' => 15 }) . + "(new account?)
    Gift From (Opt):"; + $ret .= LJ::html_text({ 'name' => 'giftfrom', 'size' => 15, 'maxlength' => 15 }); + $ret .= "
    Date Sent:"; + $ret .= LJ::html_text({ 'name' => 'datesent', 'size' => 23, 'maxlength' => 19, 'value' => LJ::mysql_time() }); + $ret .= "
    yyyy-mm-dd [hh:mm:ss]
    Amount:"; + $ret .= "\$" . LJ::html_text({ 'name' => 'amount', 'size' => 6, 'maxlength' => 6 }) . " USD
    Internal note:"; + $ret .= LJ::html_text({ 'name' => 'inote', 'size' => 40, 'maxlength' => 255 }); + $ret .= "
    Note to user:"; + $ret .= LJ::html_textarea({ 'name' => 'notes', 'rows' => 10, 'cols' => 40, 'wrap' => 'soft' }); + $ret .= "
     "; + $ret .= LJ::html_submit('submit', "Process Payment"); + $ret .= "
    "; + + $ret .= "
    "; + + # indivual item types + $ret .= ""; + + my $sep = ""; + + # paid time + $ret .= ""; + + $ret .= ""; + + $ret .= $sep; + + # permanent account + if ($grant_perm) { + $ret .= ""; + + $ret .= ""; + $ret .= $sep; + } + + + # userpics + $ret .= ""; + $ret .= ""; + $ret .= ""; + + $ret .= $sep; + + # quota + $ret .= ""; + $ret .= ""; + + $ret .= " + + + + + + + + + +
     
    "; + $ret .= " "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'item', 'value' => 'paidacct', + 'id' => 'item-paidacct' }) . "Months: "; + $ret .= LJ::html_text({ 'name' => 'paidacct_mo', 'size' => 2, 'maxlength' => 2 }); + $ret .= "
    "; + $ret .= " "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'item', 'value' => 'perm', + 'id' => 'item-perm' }) . " 
    "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'item', 'value' => 'userpic', + 'id' => 'item-userpic' }) . " Months: "; + $ret .= LJ::html_text({ 'name' => 'userpic_mo', 'size' => 2, 'maxlength' => 2 }); + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'item', 'value' => 'diskquota', + 'id' => 'item-diskquota' }) . " 'radio', 'name' => 'item', 'value' => 'coupon', + 'id' => 'item-coupon' }) . ""; + + $ret .= ""; + + $ret .= $sep; + + # rename + $ret .= ""; + $ret .= ""; + $ret .= ""; + + $ret .= "
    Size:"; + $ret .= LJ::html_text({ 'name' => 'diskquota_size', 'size' => 4, 'maxlength' => 4 }); + $ret .= "
    Months:"; + $ret .= LJ::html_text({ 'name' => 'diskquota_mo', 'size' => 2, 'maxlength' => 2 }); + $ret .= "
    ". LJ::html_select({ 'type' => 'check', 'name' => 'coupon_type', + 'id' => 'coupon_type', 'value' => 'gen' }, + 'gen' => "General", + 'int' => "Intangible only", + 'tan' => "Tangible only", ); + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'item', 'value' => 'rename', + 'id' => 'item-rename' }) . " 
    "; + + return $ret; +} +_code?> diff --git a/ljcom/htdocs/admin/accounts/fraud_suspects.bml b/ljcom/htdocs/admin/accounts/fraud_suspects.bml new file mode 100644 index 0000000..2c89c5a --- /dev/null +++ b/ljcom/htdocs/admin/accounts/fraud_suspects.bml @@ -0,0 +1,66 @@ + +Fraud suspects + + +selectall_hashref($sql, 'payid', undef); + +$ret .= "

    Possible fraudulent payments

    "; +foreach my $row (sort { $a->{dateadd} <=> $b->{dateadd} } values %$data) { + my $added = gmtime($row->{dateadd}); + my $reason = $row->{reason}; + $reason =~ s#\n#
    #mg; + $ret .= < +
    Payid:$row->{payid}
    Date added:$added
    Reason:$reason
    +EOF +} + +return $ret; + +_code?> + diff --git a/ljcom/htdocs/admin/accounts/notes.html b/ljcom/htdocs/admin/accounts/notes.html new file mode 100644 index 0000000..3eaf48f --- /dev/null +++ b/ljcom/htdocs/admin/accounts/notes.html @@ -0,0 +1,3 @@ +

    Other resources to know:

    + +http://www.livejournal.com/paidaccounts/apply.bml -- apply a code towards an account (the logged in user must do it) diff --git a/ljcom/htdocs/admin/accounts/paiddetails.bml b/ljcom/htdocs/admin/accounts/paiddetails.bml new file mode 100644 index 0000000..f410b91 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/paiddetails.bml @@ -0,0 +1,213 @@ + +Paid Details + + +Enter payid (or order number): "; +} + + my $payid = $FORM{'payid'}+0; + + ## for people without moneyview priv, they have to have userid arg + my $extrawhere = ""; + if (! $viewall) { + my $userid = $FORM{'userid'}+0; + $extrawhere = "AND p.userid=$userid"; + } + + if ($FORM{'userid'} eq "0") { # not == 0 + $sth = $dbh->prepare("SELECT * FROM payments WHERE payid=$payid AND userid=0"); + } else { + $sth = $dbh->prepare("SELECT p.*, u.user FROM payments p LEFT JOIN useridmap u ON u.userid=p.userid WHERE p.payid=$payid $extrawhere"); + } + $sth->execute; + my $pm = $sth->fetchrow_hashref; + +return "Invalid payment ID, or missing arguments" unless $pm; + + +# see if a code is associated with this payment: +my $cd = $dbh->selectrow_hashref("SELECT ac.* FROM acctpay ap, acctcode ac ". + "WHERE ap.payid=$payid AND ap.acid=ac.acid"); +if ($cd) { + my $code = LJ::acct_code_encode($cd->{'acid'}, $cd->{'auth'}); + $ret .= "From code: $code"; + if ($cd->{'userid'}) { + $ret .= " (created by " . LJ::ljuser(LJ::get_username($dbh, $cd->{'userid'})) . ")"; + } + if ($cd->{'rcptid'}) { + $ret .= " (used by " . LJ::ljuser(LJ::get_username($dbh, $cd->{'rcptid'})) . ")"; + } else { + $ret .= " (code is unused)"; + } +} + + +# see if a rename is associated with this payment +if ($pm->{'forwhat'} eq "rename") { + my $rn = $dbh->selectrow_hashref("SELECT renid, token, fromuser, touser, rendate ". + "FROM renames WHERE payid=?", undef, $payid); + if ($rn) { + my $code = sprintf("%06x%s", $rn->{'renid'}, $rn->{'token'}); + $ret .= "

    Rename Code: $code (from: $rn->{'fromuser'}, to: $rn->{'touser'}, rendate: $rn->{'rendate'})

    "; + } +} + +$ret .= "

    Payment \#$pm->{'payid'}

    "; +$ret .= "Amount: \$$pm->{'amount'} Method: $pm->{'method'} For: $pm->{'forwhat'} "; +if ($pm->{'giftafter'}) { + $ret .= " (to be delivered: " . scalar(gmtime($pm->{'giftafter'})) . " (GMT)"; +} +$ret .= "
    Date sent: $pm->{'datesent'} Recv: $pm->{'daterecv'}"; +$ret .= "
    Used: $pm->{'used'} Mailed: $pm->{'mailed'}"; +$ret .= "
    Buyer: "; +if ($pm->{'user'}) { + $ret .= LJ::ljuser($pm->{'user'}); +} +if ($pm->{'notes'}) { + my $not = LJ::eall($pm->{'notes'}); + $not =~ s/\n/
    \n/g; + $ret .= "
    Notes: $not"; +} + +# clear fraud flag +if (LJ::did_post() && $FORM{fraudclear}) { + LJ::Pay::payvar_set($payid, "fraud_status", "clear"); + $dbh->do("DELETE FROM fraudsuspects WHERE payid=?", undef, $payid); +} + +# vars +$ret .= "

    "; +$sth = $dbh->prepare("SELECT pkey, pval FROM payvars WHERE payid=?"); +$sth->execute($payid); +my ($refund, $fraud_status); +while (my ($k, $v) = $sth->fetchrow_array) { + if ($k eq "an-refund") { + my @parts = split(/,/, $v); + $refund = $v; $v = "(hidden) expir=$parts[1]"; + } + $fraud_status = $v if $k eq 'fraud_status'; + $ret .= "$k = $v
    \n"; +} + +if ($fraud_status eq 'suspect') { + my $sql = q{ + SELECT dateadd, reason + FROM fraudsuspects + WHERE payid=? + }; + my ($added, $reason) = $dbh->selectrow_array($sql, undef, $payid); + $added = $added ? gmtime($added) . ' GMT' : 'unknown'; + $reason ||= '?'; + $reason =~ s#\n#
    #mg; + $ret .= < +

    + This payment has been flagged as possible fraud. +

    + Date added: $added
    + Reason(s):
    +
    $reason
    +
    + + +
    + +EOF +} + +$sth = $dbh->prepare("SELECT ikey, ival FROM paymentsearch WHERE payid=?"); +$sth->execute($payid); +while (my ($k, $v) = $sth->fetchrow_array) { + $ret .= "$k = $v
    \n"; +} +$ret .= "

    "; + +my $cartobj; +if ($pm->{'forwhat'} eq "cart") { + my $cart = "$pm->{'payid'}-$pm->{'anum'}"; + $ret .= "

    Order $cart

    "; + $cartobj = LJ::Pay::load_cart($cart); + LJ::Pay::render_cart($cartobj, \$ret, { + 'tokens' => 1, + 'piids' => 1, + }); + $ret .= "all piids: " . join(", ", map { $_->{'piid'} } @{$cartobj->{'items'}}) . ""; +} + +$ret .= "

    Authorize.net Transaction Log

    "; +my @anet; +$sth = $dbh->prepare("SELECT cmd, datesent, ip, amt, result, response, cmdnotes ". + "FROM authnetlog WHERE payid=?"); +$sth->execute($payid); +push @anet, $_ while $_ = $sth->fetchrow_hashref; +if (@anet) { + $ret .= ""; + foreach (qw(date/ip cmd amt result extra)) { + $ret .= ""; + } + $ret .= ""; + foreach my $an (@anet) { + my @fields = split(/,/, $an->{'response'}); + my $extra; + if ($an->{'cmd'} eq "authcap") { + $extra = "authnet_txn = $fields[6]"; + } + $ret .= "\n"; + } + $ret .= "
    $_
    $an->{'datesent'}
    $an->{'ip'}
    $an->{'cmd'}\$$an->{'amt'}$an->{'result'}: $fields[3]$extra
    "; +} else { + $ret .= "No Authorize.net history"; +} + +$ret .= "

    Revoke & Refund

    "; +$ret .= "
    "; +$ret .= LJ::html_hidden("cart", "${payid}-$cartobj->{'anum'}"); +$ret .= "Item piids to revoke/refund: (comma or space separated)"; +if ($cartobj->{'method'} eq "cc") { + if (! $refund) { + $ret .= "
    Partial Card Number: (1234***5678) Exp. Date: (mm/yyyy)"; + } + $ret .= "
    \n"; +} +$ret .= "
    Opt. notes: \n"; +$ret .= "
    \n"; +$ret .= "[ Only press once and wait! ]"; +$ret .= "
    "; + + return $ret; + +_code?> + diff --git a/ljcom/htdocs/admin/accounts/paidsearch.bml b/ljcom/htdocs/admin/accounts/paidsearch.bml new file mode 100644 index 0000000..b176ee2 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/paidsearch.bml @@ -0,0 +1,161 @@ + +Paid Search + +login." + unless $remote; + + unless (LJ::remote_has_priv($remote, "moneysearch") || + LJ::remote_has_priv($remote, "moneyview")) + { + return "You don't have access to see this."; + } + + my $ret; + + my $user = $GET{'user'}; + $ret .= "

    Search for payments.

    \n"; + $ret .= "
    "; + $ret .= "Search method: "; + $ret .= LJ::html_select({ 'name' => 'method', 'selected' => $GET{'method'} }, + 'user' => "Username", + 'email' => "Email", + 'lastname' => "Last Name", + 'pptxnid' => "PayPal - transaction ID", + 'cpid' => "Coupon", +# 'ppemail' => "Email", +# 'pplastname' => "PayPal - last name", +# 'handemail' => "Manually entered email", + ); + $ret .= " Search value: "; + $ret .= LJ::html_text({ 'name' => 'value', + 'value' => $GET{'value'}, + 'size' => 30 }); + $ret .= "

    "; + + return $ret unless $GET{'method'}; + + my $dbh = LJ::get_db_writer(); + my $sth; + + my %matched; + my @ps_vars; # payment search vars; + + # by-user search + if ($GET{'method'} eq "user") { + my $user = $GET{'value'}; + my $userid = LJ::get_userid($user); + unless ($userid) { + $ret .= "

    Error: Username not found."; + return $ret; + } + + # include payments created by the user + $sth = $dbh->prepare("SELECT payid FROM payments WHERE userid=?"); + $sth->execute($userid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + + # include payments with payment items for that user + $sth = $dbh->prepare("SELECT payid FROM payitems WHERE rcptid=?"); + $sth->execute($userid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + + # HACK: mysql doesn't optimize these queries properly, so we'll do it by hand: much faster + { + my @acid = ( + @{ $dbh->selectcol_arrayref + ("SELECT acid FROM acctcode WHERE userid=? LIMIT 5000", undef, $userid)||[] }, + @{ $dbh->selectcol_arrayref + ("SELECT acid FROM acctcode WHERE rcptid=? LIMIT 5000", undef, $userid)||[] }, + ); + my $bind = join(",", map { "?" } @acid); + + # include payments tied to account codes either purchased by or used by the user (new payment system) + $sth = $dbh->prepare("SELECT pi.payid FROM acctpayitem p, payitems pi " . + "WHERE pi.piid=p.piid AND p.acid IN ($bind) LIMIT 5000"); + $sth->execute(@acid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + + # include payments tied to account codes either purchased by or used by the user (new payment system) + $sth = $dbh->prepare("SELECT payid FROM acctpay WHERE acid IN ($bind) LIMIT 5000"); + $sth->execute(@acid); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + } + } + + # by-email search + if ($GET{'method'} eq "email") { + my $email = $GET{'value'}; + + # payment search vars: ppemail (from a paypal payment notification) + # and 'handemail' (manually entered (before cart system)) + push @ps_vars, qw(ppemail handemail); + + # from rcptemail + $sth = $dbh->prepare("SELECT payid FROM payitems WHERE ". + "rcptemail=?"); + $sth->execute($email); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + } + + # coupon search + if ($GET{'method'} eq "cpid") { + my $cpid = $GET{'value'}; + + # accept $cpid-$auth, but only care about $cpid + $cpid =~ s/^(\d+).*/$1/; + + # get the payid that used/bought this coupon + my ($payid, $ppayid) = + $dbh->selectrow_array("SELECT payid, ppayid FROM coupon " . + "WHERE cpid=?", undef, $1); + + $matched{$payid} = 1 if $payid; # transaction coupon was used on + $matched{$ppayid} = 1 if $ppayid; # transaction where coupon was purchased + } + + # paypal transaction ID or last name + push @ps_vars, "pplastname" if $GET{'method'} eq "lastname"; + push @ps_vars, "pptxnid" if $GET{'method'} eq "pptxnid"; + + # include any paymentsearch vars the above modes might want + for my $var (@ps_vars) { + $sth = $dbh->prepare("SELECT payid FROM paymentsearch WHERE ". + "ikey=? AND ival=?"); + $sth->execute($var, $GET{'value'}); + $matched{$_} = 1 while $_ = $sth->fetchrow_array; + } + + return $ret. "No matches" unless %matched; + + my $in = join(',', keys %matched); + $sth = $dbh->prepare("SELECT p.*, u.user ". + "FROM payments p LEFT JOIN useridmap u ". + "ON p.userid=u.userid ". + "WHERE p.payid IN ($in) ORDER BY p.payid"); + $sth->execute; + + $ret .= "\n"; + while (my $row = $sth->fetchrow_hashref) + { + my $amount = sprintf("\$%.02f", $row->{'amount'}); + my $usedmailed = "$row->{'used'}/$row->{'mailed'}"; + + if ($row->{'mailed'} eq "C") { + $usedmailed = "Unpaid! Still in cart!"; + } + + $ret .= ""; + } + $ret .= "
    Pay ID#UserDate Sent/RecvAmountMonthsUsed/MailedMethod
    {'payid'}&userid=$row->{'userid'}\">#$row->{'payid'}{'user'}\">$row->{'user'}$row->{'datesent'}
    $row->{'daterecv'}
    $amount$row->{'months'}$usedmailed$row->{'method'}
    \n"; + + return $ret; +} +_code?> + + diff --git a/ljcom/htdocs/admin/accounts/paidsummary.bml b/ljcom/htdocs/admin/accounts/paidsummary.bml new file mode 100644 index 0000000..62628c2 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/paidsummary.bml @@ -0,0 +1,209 @@ +log in." + unless $remote; + + return "You don't have access to see this." + unless LJ::remote_has_priv($remote, "moneyview"); + + my $dbh = LJ::get_dbh("slow", "slave", "master") + or return "database unavailable"; + + my ($ret, $sth); + + my $wholemonth = 0; + if ($GET{'day'} eq "*") { $wholemonth = 1; } + + my $year = $GET{'year'}+0; + my $month = $GET{'month'}+0; + my $day = $GET{'day'}+0; + + unless ($year && $month) { + my @time = localtime(); + $year = $time[5]+1900; + $month = $time[4]+1; + $day = $time[3]; + } + + if ($wholemonth) { $day = "*"; } + $ret .= "

    "; + $ret .= "Year: " . LJ::html_text({ 'name' => 'year', 'size' => 4, 'value' => $year }) . " "; + $ret .= "Month: " . LJ::html_text({ 'name' => 'month', 'size' => 2, 'value' => $month }) . " "; + $ret .= "Day: " . LJ::html_text({ 'name' => 'day', 'size' => 2, 'value' => $day }) . " "; + $ret .= LJ::html_submit('View') . "
    (enter * for day to get month report)"; + + my ($date_low, $date_high); + + # whole month + my $fmt = sub { $dbh->quote(sprintf("%02d-%02d-%02d 00:00:00", @_)) }; + if ($day eq '*') { + $date_low = $fmt->($year, $month, '01'); + if ($month+1 > 12) { + $date_high = $fmt->($year+1, 1, '01'); + } else { + $date_high = $fmt->($year, $month+1, '01'); + } + } else { + $date_low = $fmt->($year, $month, $day); + if ($day+1 > LJ::days_in_month($month, $year)) { + if ($month+1 > 12) { + $date_high = $fmt->($year+1, 1, '01'); + } else { + $date_high = $fmt->($year, $month+1, '01'); + } + } else { + $date_high = $fmt->($year, $month, $day+1); + } + } + + $sth = $dbh->prepare("SELECT * FROM payments WHERE mailed<>'C' AND daterecv>$date_low AND daterecv<$date_high"); + $sth->execute; + my @rows = (); + push @rows, $_ while $_ = $sth->fetchrow_hashref; + + my $u = LJ::load_userids( map { $_->{userid} } @rows ); + + $ret .= "\n"; + + my $totalmoney = 0; + my %methodcount = (); + my %methodtotal = (); + my %daycount = (); + my %daytotal = (); + + my $row_ct = 0; + my $row_show = 0; + my $row_skip = 0; + my $row_html; + + foreach my $row (@rows) + { + my $amount = sprintf("\$%.02f", $row->{'amount'}); + $totalmoney += $row->{'amount'}; + $methodcount{$row->{'method'}}++; + $methodtotal{$row->{'method'}} += $row->{'amount'}; + + if ($row->{'daterecv'} =~ /^(\d\d\d\d-\d\d-\d\d)/) { + my $day = $1; + $daycount{$day}++; + $daytotal{$day} += $row->{'amount'}; + } + + $row_ct++; + next if $GET{'skip'} && ++$row_skip <= $GET{'skip'}; + + if ($row_show < 500) { + my $user = $u->{$row->{userid}}->{user}; + + $row_show++; + $row_html .= ""; + } + } + + my $slinks; + if ($GET{'skip'}) { + $slinks .= " $GET{'skip'} - 500}) . "\"><< Back "; + } + if ($row_show != $row_ct) { + my $from = $GET{'skip'}+1; + my $to = $row_show+$GET{'skip'}; + $slinks .= "(Records $from-$to of $row_ct) "; + } + if ($GET{'skip'} + $row_show < $row_ct) { + $slinks .= " $GET{'skip'} + 500}) . "\">Forward >> "; + } + + my $bar_html; + $bar_html .= "\n" + if $slinks; + + $ret .= $bar_html; + $ret .= $row_html; + $ret .= $bar_html; + + $ret .= "
    Pay ID#UserDate Sent/RecvAmountUsed/MailedMethod
    {'payid'}\">#$row->{'payid'}$user$row->{'datesent'}
    $row->{'daterecv'}
    $amount$row->{'used'}/$row->{'mailed'}$row->{'method'}
    $slinks
    \n"; + + return $ret unless @rows; + + $ret .= "

    Statistics:

      "; + $ret .= "
    • Total money: " . sprintf("\$%.02f", $totalmoney) . "
    • \n"; + + $ret .= "
    • Break-down by payment method:
        "; + foreach my $method (sort keys %methodcount) { + $ret .= "
      • $method: $methodcount{$method} = " . sprintf("\$%.02f", $methodtotal{$method}) . "
      • \n"; + } + $ret .= "
    • "; + + $ret .= "
    • Break-down by day:
        "; + foreach my $day (sort keys %daycount) { + $ret .= "
      • $day: $daycount{$day} = " . sprintf("\$%.02f", $daytotal{$day}) . "
      • \n"; + } + $ret .= "
    • "; + + $ret .= "
    • Break-down by item type:
        "; + + my @payid_in = map { $_->{payid} } @rows; + my $payid_bind = join(",", map { '?' } @rows); + $sth = $dbh->prepare("SELECT * FROM payitems WHERE status='done' AND payid IN ($payid_bind)"); + $sth->execute(@payid_in); + die $dbh->errstr if $dbh->err; + + my %idata = (); + while (my $it = $sth->fetchrow_hashref) { + + my $item = $it->{item}; + my $subkey = $item . (LJ::Pay::is_bonus($it, 'sized') ? ('-' . (split('-', $it->{subitem}))[0]) : '') . ($it->{qty} ? "-$it->{qty}" : ''); + + foreach my $ref ($idata{$item}, $idata{$item}->{sub}->{$subkey}) { + $ref->{ct}++; + $ref->{sum_pos} += $it->{amt} if $it->{amt} > 0; + $ref->{sum_neg} += $it->{amt} if $it->{amt} < 0; + } + delete $idata{$item}->{sub} if $item eq $subkey; + } + + # sorts with proper string/integer comparisons on key parts + my $sort_sub = sub { + my ($aname, $asize, $aqty) = split('-', $a); + if ($asize && ! $aqty) { $aqty = $asize; $asize = 0; } + + my ($bname, $bsize, $bqty) = split('-', $b); + if ($bsize && ! $bqty) { $bqty = $bsize; $bsize = 0; } + + return $bname cmp $aname || $bsize <=> $asize || $bqty <=> $aqty; + }; + + # recursive closure to display items, counts, totals + my $show_item; + $show_item = sub { + my ($itemname, $ref) = @_; + return '' unless $ref; + + my $r = "
      • $itemname: $ref->{ct} = " . sprintf("\$%.02f", $ref->{sum_pos}); + $r .= ", " . sprintf("\$%.02f", $ref->{sum_neg}) if $ref->{sum_neg}; + if (%{$ref->{sub}||{}}) { + $r .= "
          "; + $r .= $show_item->($_, $ref->{sub}->{$_}) + foreach sort $sort_sub keys %{$ref->{sub}}; + $r .= "
        "; + } + $r .= "
      • "; + + return $r; + }; + + # build tree of items + foreach my $item (sort $sort_sub keys %idata) { + $ret .= $show_item->($item, $idata{$item}); + } + $ret .= "
    • \n"; + + $ret .= "

    "; + + return $ret; +} +_code?> diff --git a/ljcom/htdocs/admin/accounts/rr.bml b/ljcom/htdocs/admin/accounts/rr.bml new file mode 100644 index 0000000..115a3e2 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/rr.bml @@ -0,0 +1,199 @@ +" unless $remote; + + unless (LJ::remote_has_priv($remote, "moneyenter")) { + return "You don't have rights to refund/revoke payments."; + } + + return "POST required" unless LJ::did_post(); + + my $cartobj = LJ::Pay::load_cart($POST{'cart'}); + return "Invalid cart." unless $cartobj; + return "Can't refund/revoke items that weren't paid for." + unless $cartobj->{'used'} eq "Y"; + + my %refund; + foreach my $n (split(/[\s\,]+/, $POST{'plist'})) { + next if $n =~ /\D/; + unless (grep { $_->{'piid'} == $n } @{$cartobj->{'items'}}) { + return "Invalid piid ($n) for this order."; + } + $refund{$n} = 1; + } + + my @revoke; + my $refund_amt; + my $total_refund = 1; + foreach my $it (@{$cartobj->{'items'}}) { + if ($refund{$it->{'piid'}} && ($it->{'status'} eq "done" || $it->{'status'} eq "pend")) { + push @revoke, $it; + $refund_amt += $it->{'amt'}; + + # note we've already refunded shipping for this item + $it->{'ship_refund_done'}++; + + } else { + $total_refund = 0; + } + } + unless (@revoke) { + return "No items selected to refund/revoke"; + } + + # if we revoked any items in need of shipping, just refund all shipping costs + foreach my $it (@revoke) { + next unless LJ::Pay::item_needs_shipping($it); + + foreach (@{$cartobj->{'items'}}) { + next unless $_->{'item'} eq 'shipping'; + next if $_->{'ship_refund_done'}; + $refund_amt += $_->{'amt'}; + + push @revoke, $_; + last; + } + + last; + } + + my $cardnum = $POST{'partialnum'}; + my $expdate = $POST{'expdate'}; + + # refund if Auth.net + my $transid; + my $refund = sub { + my $type = shift; # "VOID" or "CREDIT"; + + unless (defined $transid) { + my $res; + $res = $dbh->selectrow_array("SELECT pval FROM payvars WHERE payid=? AND pkey='an-refund'", + undef, $cartobj->{'payid'}); + if ($res) { + # if payment is relatively new, we still have the refund data around + my @f = split(/,/, $res); + $transid = $f[0]; + $expdate = $f[1]; + # $cardnum = "$f[2]***$f[3]"; # old way. + $cardnum = "$f[3]"; # new way. stupid authorize.net. + } else { + # otherwise the refund info's probably been purged, so we'll get the transid + # and card fingerprint from the user + $res = $dbh->selectrow_array("SELECT response FROM authnetlog WHERE payid=? AND cmd='authcap' AND result='pass' ORDER BY datesent DESC LIMIT 1", undef, $cartobj->{'payid'}); + return 0 unless $res; + $transid = (split(/,/, $res))[6]; + } + } + + my $ua = new LWP::UserAgent; + $ua->agent("LJ-AuthNet/1.0"); + my $vars = { + 'x_Version' => '3.1', + 'x_Delim_Data' => 'True', + 'x_Login' => $LJ::AUTHNET_USER, + 'x_Password' => $LJ::AUTHNET_PASS, + 'x_Type' => $type, + 'x_Merchant_Email' => $LJ::AUTHNET_MERCHANT, + 'x_Trans_ID' => $transid, + 'x_Card_Num' => $cardnum, + #'x_Exp_Date' => $expdate, # no longer required + }; + if ($type eq "CREDIT") { + $vars->{'x_Amount'} = $refund_amt; + } + + my $req = new HTTP::Request POST => 'https://secure.authorize.net/gateway/transact.dll'; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(join("&", map { LJ::eurl($_) . "=" . LJ::eurl($vars->{$_}) } keys %$vars)); + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + my ($ct, $err); + if ($res->is_success) { + $ct = $res->content; + } else { + return 0; + } + + my @fields = split(/,/, $ct); + my $pass = $fields[0] == 1; + + $dbh->do("INSERT INTO authnetlog (cmd, payid, datesent, amt, result, response) ". + "VALUES (?,?,NOW(),?,?,?)", undef, lc($type), + $cartobj->{'payid'}, $refund_amt, $pass ? "pass" : "fail", $ct); + die $dbh->errstr if $dbh->err; + + return $pass; + }; + + if ($cartobj->{'method'} eq "cc" && ! $POST{'no_refund'}) { + return "Error: merchant gateway is currently down, please try again later." + if $LJ::AUTHNET_DOWN > 0.5; + unless (($total_refund && $refund->("VOID")) || + $refund->("CREDIT")) { + return "Error: unable to refund. Check error messages. Not revoking items."; + } + } + + my $piids = join(",", map { $_->{'piid'} } @revoke); + LJ::Pay::payvar_add($cartobj->{'payid'}, "revoke", + LJ::mysql_time(time()) . ": (piid $piids) $POST{'refreason'}"); + + # group revoked items by userid for locking + my %revoke_uid = (); + foreach my $it (@revoke) { + my $uid = $it->{'rcptid'} || 'anon'; + push @{$revoke_uid{$uid}}, $it; + } + + # remove items from account, one userid at a time + foreach my $uid (keys %revoke_uid) { + + unless ($uid eq 'anon') { + LJ::Pay::get_lock($uid) + or return "Could not obtain lock on account, please try again later"; + } + + LJ::Pay::revoke_payitems(@{$revoke_uid{$uid}}); + + unless ($uid eq 'anon') { + LJ::Pay::release_lock($uid); + } + } + + # if any coupons were revoked, display the payids they were used on + # so the admin can make a human judgement if anything else needs to + # be revoked + my @cp_rev = map { $_->{'tokenid'} } grep { $_->{'item'} eq 'coupon' && $_->{'amt'} > 0 } @revoke; + my $bind = join(",", map { "?" } @cp_rev); + my $cp_ids = $dbh->selectcol_arrayref("SELECT payid FROM coupon WHERE cpid IN ($bind)", + undef, @cp_rev) || []; + + my $cp_ret; + if (@$cp_ids) { + $cp_ret = "

    Coupons have revoked. Below are the payment IDs on which they were used. " . + "You may wish to review these payments to determine if further action should " . + "be taken.

    "; + $cp_ret .= ""; + } + + # if this was a fraudulent payment, mark it as refunded. + my $fraud = $dbh->selectrow_array("SELECT pval FROM fraudstatus ". + "WHERE payid=? AND pkey='fraud_status'", + undef, $cartobj->{'payid'}); + LJ::Pay::payvar_set($cartobj->{'payid'}, "fraud_status", "refunded") if $fraud eq 'suspect'; + + return "Success. Press back and reload for details.$cp_ret"; + +} +_code?> diff --git a/ljcom/htdocs/admin/accounts/shipping_finish.bml b/ljcom/htdocs/admin/accounts/shipping_finish.bml new file mode 100644 index 0000000..b5e0d43 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/shipping_finish.bml @@ -0,0 +1,82 @@ + + + + + +" unless $remote; + + return "You don't have access to finish payments" + unless LJ::remote_has_priv($remote, "moneyenter") || LJ::remote_has_priv($remote, "shipping"); + + my $ret; + + unless (LJ::did_post() && $POST{'ids'}) { + $ret .= "
    Enter order numbers that have been shipped:
    "; + $ret .= "\n"; + $ret .= "
    "; + return $ret; + } + + my $dbh = LJ::get_db_writer(); + + my $ids = $POST{'ids'}; + $ids =~ s/\r//g; + my @ids = split(/\n/, $ids); + foreach my $id (@ids) { + next unless $id =~ /\S/; + $id =~ s/\s+//g; + unless ($id =~ /^(\d+)-(\d+)$/) { + $ret .="Error! -- invalid order number: $id
    "; + next; + } + my ($payid, $anum) = ($1, $2); + my $pay = $dbh->selectrow_hashref("SELECT * FROM payments WHERE payid=? AND anum=?", + undef, $payid, $anum); + unless ($pay) { + $ret .="Error! -- invalid order number: $id
    "; + next; + } + + my ($status, $date) = $dbh->selectrow_array("SELECT status, dateshipped FROM shipping ". + "WHERE payid=?", undef, $payid); + unless ($status eq "needs") { + if ($status eq "shipped") { + $ret .="Error! -- Order already shipped on $date
    "; + } else { + $ret .="Error! -- Order is valid, but has no physical items
    "; + } + next; + } + + my $rv = $dbh->do("UPDATE shipping SET status='shipped', dateshipped=NOW() WHERE payid=?", undef, + $payid); + if ($rv > 0) { + $ret .= "Order $payid-$anum marked as shipped.
    \n"; + + # decrement inventory + my $sth = $dbh->prepare("SELECT item, subitem FROM payitems ". + "WHERE payid=? AND item IN ('clothes')"); + $sth->execute($payid); + while (my ($item, $subitem) = $sth->fetchrow_array) { + $dbh->do("UPDATE inventory SET qty=qty-1 WHERE item=? AND subitem=?", + undef, $item, $subitem); + } + + } else { + $ret .="Error! -- some db error updating $payid-$anum
    \n"; + } + } + return $ret; + +} +_code?> + + diff --git a/ljcom/htdocs/admin/accounts/shipping_labels.bml b/ljcom/htdocs/admin/accounts/shipping_labels.bml new file mode 100644 index 0000000..6e4d393 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/shipping_labels.bml @@ -0,0 +1,193 @@ + + + + + + +log in." + unless $remote; + + return "You don't have access to see this." + unless LJ::remote_has_priv($remote, "moneyview") || LJ::remote_has_priv($remote, "shipping"); + + my $ret; + + unless (LJ::did_post()) { + $ret .= "
    "; + $ret .= "All labels past date: "; + $ret .= "

    (be sure to set printer margins to 0.5\" at top and left, with no header or footer.)

    "; + $ret .= "
    "; + return $ret; + } + + my $dbh = LJ::get_db_writer(); + my $sth; + + my %country; + LJ::load_codes($dbh, { "country" => \%country }); + + $sth = $dbh->prepare("SELECT payid, dateready FROM shipping ". + "WHERE dateready > ? AND status='needs' ". + "ORDER BY dateready"); + $sth->execute($POST{'date'}); + my @ship; + push @ship, $_ while $_ = $sth->fetchrow_hashref; + + my $ct; + foreach my $sh (@ship) { + $ct++; + my $cartobj = $dbh->selectrow_hashref("SELECT * FROM payments WHERE payid=?", + undef, $sh->{'payid'}); + next unless $cartobj; + # load all the cart + my $cart = "$cartobj->{'payid'}-$cartobj->{'anum'}"; + $cartobj = LJ::Pay::load_cart($cart); + next unless $cartobj; + + if ($ct == 1) { + $ret .= "
    "; + } else { + $ret .= "
    "; + } + + $ret .= "

    Order \#$cart

    "; + $ret .= "
    $sh->{'dateready'}
    "; + + $ret .= "

    Enclosed are the items you ordered. If you have any questions, email accounts\@livejournal.com and reference the order number above.

    "; + + LJ::Pay::render_cart($cartobj, \$ret, { shipping_labels => 1 }); + + + $ret .= "

    $cart

    "; + + + $ret .= "
    " . LJ::Pay::postal_address_html() . "
    \n"; + + $ret .= "
    "; + + my %payvar; + my $sth = $dbh->prepare("SELECT pkey, pval FROM payvars WHERE payid=? AND pkey LIKE 'ship%'"); + $sth->execute($cartobj->{'payid'}); + while (my ($k, $v)= $sth->fetchrow_array) { $payvar{$k} = $v; } + + my $ctry = uc($payvar{'ship_country'}); + + # Canadian shipping labels need to be printed in all caps, ugh + if ($ctry eq 'CA') { + $payvar{$_} = uc($payvar{$_}) + foreach grep { $_ =~ /^ship_/ } keys %payvar; + $country{'CA'} = uc($country{'CA'}); + } + + $ret .= "$payvar{'ship_name'}
    "; + $ret .= "$payvar{'ship_addr1'}
    "; + $ret .= "$payvar{'ship_addr2'}
    " if $payvar{'ship_addr2'}; + $ret .= "$payvar{'ship_city'}, $payvar{'ship_state'} $payvar{'ship_zip'}
    "; + if ($ctry ne "US") { + $ret .= $country{$ctry}; + } + + $ret .= "
    "; + $ret .= "
    [$cart]
    "; + + + $ret .= "
    "; # end page + } + + $ret .= "no orders found past $POST{'date'}" unless $ct; + + return $ret; + +} +_code?> + + diff --git a/ljcom/htdocs/admin/accounts/unclaimed_payments.bml b/ljcom/htdocs/admin/accounts/unclaimed_payments.bml new file mode 100644 index 0000000..3e83495 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/unclaimed_payments.bml @@ -0,0 +1,29 @@ +log in."; + } + } + + $sth = $dbh->prepare("SELECT p.payid, a.acid, ac.auth FROM acctcode ac, acctpay a, payments p WHERE p.userid=0 AND a.payid=p.payid AND ac.acid=a.acid"); + $sth->execute; + while (my ($payid, $acid, $auth) = $sth->fetchrow_array) + { + my $code = LJ::acct_code_encode($acid, $auth); + $ret .= "

    #$payid - $code\n"; + } + + return $ret; + +_code?> diff --git a/ljcom/htdocs/admin/accounts/xfer_remaining.bml b/ljcom/htdocs/admin/accounts/xfer_remaining.bml new file mode 100644 index 0000000..94ecb11 --- /dev/null +++ b/ljcom/htdocs/admin/accounts/xfer_remaining.bml @@ -0,0 +1,8 @@ + diff --git a/ljcom/htdocs/admin/codetrace.bml b/ljcom/htdocs/admin/codetrace.bml new file mode 100644 index 0000000..7b00f4e --- /dev/null +++ b/ljcom/htdocs/admin/codetrace.bml @@ -0,0 +1,172 @@ +Error: You don't have finduser(codetrace) priv." + unless LJ::check_priv($remote, "finduser", "codetrace"); + + if ($FORM{'user'} ne "") { $mode = "user"; $FORM{'code'} = ""; } + elsif ($FORM{'code'}) { $mode = "code"; } + + p("

    code tracer

    \n"); + p("
    "); + $ev = LJ::ehtml($FORM{'user'}); + p("User: or "); + $ev = LJ::ehtml($FORM{'code'}); + p("Code: "); + p("
    "); + return $ret if $mode eq "intro"; + + my $do_how = sub { + my $self = shift; + my $u = shift; + + my $whyhere = $dbr->selectrow_hashref(qq{ + SELECT acid, userid FROM acctcode WHERE rcptid=$u->{'userid'} LIMIT 1 + }); + $whyhere->{'user'} = LJ::get_username($whyhere->{'userid'}) + if $whyhere && $whyhere->{'userid'}; + + p("How $u->{'user'} joined: "); + unless ($whyhere) { + p("No invite code"); + } else { + my $acid = LJ::acid_encode($whyhere->{'acid'}); + p("$acid"); + + my $reason = $dbr->selectrow_array(qq{ + SELECT reason FROM acctinvite WHERE acid=$whyhere->{'acid'} + }); + p(" ($reason)") if defined $reason; + + if (exists $whyhere->{'user'}) { + p(" from $whyhere->{'user'}."); + p("
    "); + $self->($self, $whyhere); + return; + } + } + p("
    "); + }; + + if ($mode eq "user") + { + my $user = LJ::canonical_username($FORM{'user'}); + my $u = LJ::load_user($user) if $user; + return "Unknown user" unless $u; + $do_how->($do_how, $u); + + my %invite; + $sth = $dbr->prepare(qq{ + SELECT acid, reason, dateadd FROM acctinvite WHERE userid=$u->{'userid'} + LIMIT 5000 + }); + $sth->execute; + $invite{$_->{'acid'}} = $_ while $_ = $sth->fetchrow_hashref; + + my $total_children = 0; + + # limit recursion + my %did_userid; + my $total_calls = 0; + + my $rec_user = sub { + my $self = shift; + my $userid = shift; + my $unused = shift; + + # limit recursion (we were seeing runaways) + return if ++$total_calls > 50; + return if $did_userid{$userid}++; + + my $sth = $dbr->prepare(qq{ + SELECT a.acid, a.rcptid, u.user FROM acctcode a LEFT JOIN useridmap u ON a.rcptid=u.userid + WHERE a.userid=$userid + LIMIT 5000 + }); + $sth->execute; + my $open; + while (my ($acid, $rcptid, $user) = $sth->fetchrow_array) + { + next unless $unused || $user; + $total_children++ if defined $user; + unless ($open++) { p("
      "); } + my $acide = LJ::acid_encode($acid); + p("
    • "); + p("$user ") if $user; + p("($acide)"); + if ($invite{$acid}) { + p(" ($invite{$acid}->{'reason'}; $invite{$acid}->{'dateadd'})"); + } + $self->($self, $rcptid, 0) if $rcptid; + p("
    • "); + } + p("
    ") if $open; + }; + + p("

    Codes made/used by $user:"); + $rec_user->($rec_user, $u->{'userid'}, 1); + p("

    Total children: $total_children"); + + return $ret; + } + + if ($mode eq "code") + { + my $code = $FORM{'code'}; + my $acid; + if ($code =~ /^\#(\d+)$/) { + $acid = $1; + $code = LJ::acid_encode($acid); + } else { + return "Bogus code." if length($code) != 7 && length($code) != 12; + $code =~ s/^.....(.......)$/$1/; + $acid = LJ::acid_decode($code); + } + p("Code: $code = $acid
    "); + + my $ac = $dbr->selectrow_hashref("SELECT userid, rcptid FROM acctcode WHERE acid=$acid"); + unless ($ac) { + p("Code doesn't exist"); + return $ret; + } + my $ai = $dbr->selectrow_hashref("SELECT reason, dateadd FROM acctinvite WHERE acid=$acid"); + $ac->{'user'} = LJ::get_username($ac->{'userid'}) + if $ac->{'userid'}; + $ac->{'ruser'} = LJ::get_username($ac->{'rcptid'}) + if $ac->{'rcptid'}; + + p("Creator of code: $ac->{'user'} ($ai->{'reason'}, $ai->{'dateadd'})
    ") + if $ac->{'user'}; + unless ($ac->{'userid'}) { + my $ap = $dbr->selectrow_hashref(qq{ + SELECT p.userid, p.payid FROM payments p, acctpay ap + WHERE ap.payid=p.payid AND ap.acid=$acid + }); + $ap ||= $dbr->selectrow_hashref(qq{ + SELECT p.userid, p.payid FROM payments p, payitems pi, acctpayitem api + WHERE api.piid=pi.piid AND api.acid=$acid AND pi.payid=p.payid + }); + if ($ap) { + p("Payment which generated code: {'userid'}'>$ap->{'payid'}
    "); + } + } + + p("Code recipient: $ac->{'ruser'}
    "); + + return $ret; + } + + $ret; + +_code?> diff --git a/ljcom/htdocs/admin/feedback/index.bml b/ljcom/htdocs/admin/feedback/index.bml new file mode 100644 index 0000000..558b2ac --- /dev/null +++ b/ljcom/htdocs/admin/feedback/index.bml @@ -0,0 +1,139 @@ +"; + return BML::redirect("/feedback/"); + } + + $body .= "\n"; + $body .= '

    '; + $body .= ""; + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= "
    "; + + return unless $GET{'mode'}; + + if ($GET{'mode'} eq "list") { + my @where; + my $dbr = LJ::get_db_reader(); + $body .= ""; + if ($GET{'viewall'} ne "") { + # Do nothing extra + } + if ($GET{'username'} ne "") { + my $userid = LJ::get_userid($GET{'username'}); + unless ($userid) + { + $body .= " "; + return; + } + push @where, "userid=$userid"; + } + if ($GET{'url'} ne "") { + my $qvalue = $dbr->quote($GET{'url'}); + push @where, "url=$qvalue"; + } + if ($GET{'state'} ne "") { + my $qvalue = $dbr->quote($GET{'state'}); + push @where, " state=$qvalue"; + } + + my $where; my $i; + if (@where > 0) { + $where = "WHERE "; + foreach (@where) { + $i++; + $where .= $i == 1 ? $_ : " && " . $_; + } + } + + my $sth = $dbr->prepare("SELECT * FROM fotobilder_feedback $where"); + $sth->execute; + + my $show_total = 50; + my $row_ct = 0; + my $row_show = 0; + my $row_skip = 0; + my $row_html; + my @rows; while (my $row = $sth->fetchrow_hashref) { push @rows, $row; } + foreach my $row ( reverse @rows ) { + next if LJ::trim($row->{'body'}) eq ""; + $row_ct++; + next if $GET{'skip'} && ++$row_skip <= $GET{'skip'}; + if ($row_show < $show_total) { + $row_show++; + my $username = LJ::get_username($row->{'userid'}); + $row_html .= "
    " . LJ::ljuser($username) . "

    "; + if ($row->{'datetime'} ne "0000-00-00 00:00:00") { + $row_html .= "Filed at: $row->{'datetime'}
    "; + } + $row_html .= "
    "; + my $abstract = LJ::ehtml($row->{'body'}); + $abstract =~ s/\n/
    /g; + $row_html .= "$abstract
    "; + $body .= ""; + $body .= $row_html; + my $slinks; + if ($GET{'skip'}) { + $slinks .= " $GET{'skip'} - $show_total}) . "\"><< Back "; + } + if ($row_show != $row_ct) { + my $from = $GET{'skip'}+1; + my $to = $row_show + $GET{'skip'}; + $slinks .= "(Records $from-$to of $row_ct) "; + } + if ($GET{'skip'} + $row_show < $row_ct) { + $slinks .= " $GET{'skip'} + $show_total}) . "\">Forward >> "; + } + $body .= ""; + if ($slinks ne "") { $body .= " "; } + } else { + $body .= ""; + } + return; +} +_code?> + +body=> +head<= + +<=head +page?> diff --git a/ljcom/htdocs/admin/sendmail/query.bml b/ljcom/htdocs/admin/sendmail/query.bml new file mode 100644 index 0000000..61d102c --- /dev/null +++ b/ljcom/htdocs/admin/sendmail/query.bml @@ -0,0 +1,230 @@ +Query Sent Mail +body<= + "Sent (does not guarantee that the message didn't bounce)", + 'F' => "Failed to send", }; + + my $remote = LJ::get_remote(); + + my %canview; + $canview{'abuse'} = 1 if (LJ::check_priv($remote, "supportread", "abuse")); + $canview{'support'} = 1 if (LJ::check_priv($remote, "supportread", "support")); + + # Grouping this check for now, but leaving it so + # it could be split up in the future should a need + # arise + if (LJ::check_priv($remote, "supportread", "accounts")) { + $canview{'accounts'} = 1; + $canview{'coppa'} = 1; + } + + unless ($canview{'abuse'} || $canview{'support'} || $canview{'accounts'}) { + return " + If you need to file an abuse request, please do so at: + $LJ::SITEROOT/abuse/report.bml
    + If you need to file a support request, please do so at: + $LJ::SITEROOT/support/submit.bml p?>"; + } + + if ($GET{'mode'} eq "view") { + my $dbr = LJ::get_db_reader(); + my $qmailid = $dbr->quote($GET{'mailid'}); + $sth = $dbr->prepare("SELECT mailid, userid, spid, status, timesent, mailto, " . + "subject, message, type FROM abuse_mail " . + "WHERE mailid=$qmailid"); + $sth->execute; + + my $mail = $sth->fetchrow_hashref; + if ($canview{$mail->{'type'}}) { + $ret .= "{'mailid'} h1?>"; + + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + if ($mail->{'spid'} != 0) { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + my $message = $mail->{message}; + $message = LJ::auto_linkify($message); + $message =~ s/\r?\n/
    \n/g; + + $ret .= ""; + + $ret .= "
    Mail ID:$mail->{'mailid'}
    Status:$status->{$mail->{'status'}}
    Request #:"; + $ret .= "$mail->{'spid'}N/A
    Sent By:" . LJ::ljuser(LJ::get_username($mail->{'userid'})) . "
    From:$mail->{'type'}\@$LJ::DOMAIN
    Recipient:$mail->{'mailto'}
    Sent:$mail->{'timesent'}
    Subject:$mail->{'subject'}
    Message:$message
    "; + + $ret .= ""; + $ret .= "<< View Results"; + } else { + $ret .= LJ::bad_input('You are not authorized to view this message'); + } + } else { + $ret .= "\n"; + $ret .= '
    '; + $ret .= ''; + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    Restrict:"; + + my @type = ("", "All"); + push @type, ('abuse' => "abuse\@$LJ::DOMAIN") if $canview{'abuse'}; + push @type, ('accounts' => "accounts\@$LJ::DOMAIN") if $canview{'accounts'}; + push @type, ('coppa' => "coppa\@$LJ::DOMAIN") if $canview{'coppa'}; + push @type, ('support' => "support\@$LJ::DOMAIN") if $canview{'support'}; + $ret .= LJ::html_select({ 'name' => 'restrict', 'selected' => $GET{'restrict'} }, @type); + + + $ret .= "
    Method:"; + $ret .= LJ::html_select({'name' => 'method', 'selected' => $GET{'method'}}, + 'sender' => "Username of Sender", + 'spid' => "Tied to Request #", + 'mailto' => "Sent to address or user", + ); + $ret .= "
    Value:"; + $ret .= LJ::html_text({ 'name' => 'value', + 'value' => $GET{'value'}, + 'size' => 30 }); + $ret .= "
     
    "; + + return $ret unless $GET{'mode'}; + + if ($GET{'mode'} eq "list") { + my $dbr = LJ::get_db_reader(); + $ret .= ""; + + # Default condition of nothing versus everything + my $where = "WHERE 0"; + + if ($GET{'method'} eq "sender") { + my $userid = LJ::get_userid($GET{'value'}); + unless ($userid) { + $ret .= " "; + return $ret; + } + $where = "WHERE userid=$userid"; + } elsif ($GET{'method'} eq "spid") { + $where = "WHERE spid=" . $dbr->quote($GET{'value'}); + } elsif ($GET{'method'} eq "mailto") { + my $email; + + my $u = LJ::load_user($GET{'value'}); + if ($u) { + $email = $u->{'email'}; + } else { # Assume we got an email address + $email = $GET{'value'}; + my @email_errors; + LJ::check_email($email, \@email_errors); + if (@email_errors) { + $ret .= " "; + return $ret; + } + } + + $where = "WHERE mailto=" . $dbr->quote($email); + } + + # See if they are limiting the search and + # make sure they are able to view that type + if ($GET{'restrict'} ne '') { + return LJ::bad_input('Not authorized to view that type') + unless $canview{$GET{'restrict'}}; + my $r = $dbr->quote($GET{'restrict'}); + $where .= " AND type=$r"; + } else { #Limit them to the types they can see + $where .= " AND type IN(" . join(',', map { $dbr->quote($_) } keys %canview) . ')'; + } + + $sth = $dbr->prepare("SELECT mailid, userid, spid, status, " . + "timesent, mailto, subject, type " . + "FROM abuse_mail $where"); + $sth->execute; + + my $show_total = 50; + my $row_ct = 0; + my $row_show = 0; + my $row_skip = 0; + my $row_html; + while (my $row = $sth->fetchrow_hashref) { + $row_ct++; + next if $GET{'skip'} && ++$row_skip <= $GET{'skip'}; + + if ($row_show < $show_total) { + $row_show++; + $row_html .= "(link)"; + + my $username = LJ::get_username($row->{'userid'}); + $row_html .= "" . LJ::ljuser($username) . ""; + + if ($row->{'spid'} != 0) { + $row_html .= "$row->{'spid'}"; + } else { + $row_html .= "N/A"; + } + $row_html .= "$row->{'status'}"; + $row_html .= "$row->{'type'}"; + $row_html .= "$row->{'timesent'}$row->{'mailto'}"; + $row_html .= "$row->{'subject'}"; + } + } + if ($row_ct eq 0) { $ret .= ""; return $ret; } + + $ret .= ""; + $ret .= "DetailsSent ByRequest #"; + $ret .= "StatusFromSentRecipientSubject"; + $ret .= $row_html; + my $slinks; + if ($GET{'skip'}) { + $slinks .= " $GET{'skip'} - $show_total}) . "\"><< Back "; + } + if ($row_show != $row_ct) { + my $from = $GET{'skip'}+1; + my $to = $row_show+$GET{'skip'}; + $slinks .= "(Records $from-$to of $row_ct) "; + } + if ($GET{'skip'} + $row_show < $row_ct) { + $slinks .= " $GET{'skip'} + $show_total}) . "\">Forward >> "; + } + $ret .= " p?>"; + if ($slinks ne "") { $ret .= " "; } + } else { + $ret .= ""; + } + } + return $ret; +_code?> +<=body +page?> diff --git a/ljcom/htdocs/admin/sendmail/send.bml b/ljcom/htdocs/admin/sendmail/send.bml new file mode 100644 index 0000000..2fd04c6 --- /dev/null +++ b/ljcom/htdocs/admin/sendmail/send.bml @@ -0,0 +1,381 @@ + +function form_switch() +{ + var form = document.getElementById('preview'); + form.action='send.bml?action=edit'; + form.submit(); +} + +function fill_subject() +{ + var request = document.getElementById('request'); + var subject = document.getElementById('subject'); + + var id = request.value; + + subject.value = 'Your Account [##-'+id+']'; +} + +<=head + +body<= + + + If you need to file an abuse request, please do so at: + $LJ::SITEROOT/abuse/report.bml
    + If you need to file a support request, please do so at: + $LJ::SITEROOT/support/submit.bml p?>"; + } + + my $compose = sub { + my $edit_mode = shift; + + $body .= "\n"; + $body .= "
    \n"; + + $body .= "\n"; + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= "
    "; + + my @from = ("", "-- Select One --"); + push @from, ('abuse' => "abuse\@$LJ::DOMAIN") if $cansend{'abuse'}; + push @from, ('accounts' => "accounts\@$LJ::DOMAIN") if $cansend{'accounts'}; + push @from, ('coppa' => "coppa\@$LJ::DOMAIN") if $cansend{'coppa'}; + push @from, ('support' => "support\@$LJ::DOMAIN") if $cansend{'support'}; + + my $selfrom = $edit_mode == 1 ? $POST{'from'} : $GET{'from'}; + $selfrom = "abuse" if !$selfrom && $cansend{'abuse'}; + $selfrom = "support" if !$selfrom && $cansend{'support'}; + $selfrom = "accounts" if !$selfrom && $cansend{'accounts'}; + + $body .= LJ::html_select({ 'name' => 'from', 'selected' => $selfrom }, @from); + $body .= "

    Mail to:"; + $body .= ""; + + $body .= "
    "; + + # Since we expose the address we'd be sending to + # don't let them mail by user or community maints + # if they couldn't go look it up themselves + if (LJ::check_priv($remote, 'finduser')) { + $body .= ""; + + my $user = $edit_mode == 1 ? $POST{'user'} : $GET{'user'}; + $body .= LJ::html_text({ 'name' => 'user', 'type' => 'text', + 'raw' => 'style="background: url('.$LJ::IMGPREFIX.'/userinfo.gif) no-repeat; background-position: 0px 1px; padding-left: 18px;" size="37"', + 'value' => $user}); + $body .= " (OR)"; + $body .= "
    "; + + my $maints = $edit_mode == 1 ? $POST{'maints'} : $GET{'maints'}; + $body .= LJ::html_text({ 'name' => 'maints', 'type' => 'text', + 'raw' => 'style="background: url('.$LJ::IMGPREFIX.'/community.gif) no-repeat; background-position: 0px 1px; padding-left: 18px;" size="37"', + 'value' => $maints}); + $body .= " (OR)"; + $body .= "
    "; + } + + $body .= ""; + + my $email = $edit_mode == 1 ? $POST{'email'} : $GET{'email'}; + $body .= LJ::html_text({ 'name' => 'email', 'type' => 'text', + 'raw' => 'size="40"', 'value' => $email}); + $body .= "
    "; + $body .= "
    "; + + my $bcc = $edit_mode == 1 ? $POST{'bcc'} : $GET{'bcc'}; + if ($edit_mode == 0 && ! $bcc) { + $bcc = $remote->{'email'}; + } + $body .= LJ::html_text({'name' => 'bcc', 'type' => 'text', + 'raw' => "size='45' maxlength='100'", + 'value' => $bcc}); + $body .= " Limit One
    "; + my $request = $edit_mode == 1 ? $POST{'request'} : $GET{'request'}; + $body .= LJ::html_text({'name' => 'request', 'type' => 'text', + 'raw' => "size='45' maxlength='100'", + 'value' => $request, + 'id' => 'request'}); + $body .= " "; + $body .= "
    "; + my $subject = $edit_mode == 1 ? $POST{'subject'} : $GET{'subject'}; + $body .= LJ::html_text({'name' => 'subject', 'type' => 'text', + 'raw' => "size='45' maxlength='100'", + 'value' => $subject, + 'id' => 'subject'}); + $body .= "
    "; + my $message = $edit_mode == 1 ? $POST{'message'} : $GET{'message'}; + $body .= LJ::html_textarea({'name' => 'message', + 'raw' => "rows='20' cols='80' wrap='soft'", + 'value' => $message}); + $body .= "
     "; + my $extra = $edit_mode == 1 ? $POST{'extra'} : $GET{'extra'}; + $body .= LJ::html_hidden('extra', $extra) if $extra; + $body .= LJ::html_submit ('reset', '<- Reset', {'type' => 'reset'}); + $body .= "  "; + $body .= LJ::html_submit ('submit', 'Preview ->'); + $body .= "
    "; + $body .= "
    "; + }; + + my $preview = sub { + + my $errors = 0; + + $body .= ""; + $body .= ""; + } + + my $request = LJ::trim($POST{'request'}); + $body .= ""; + + my $subject = LJ::trim($POST{'subject'}); + $body .= ""; + + my $message = LJ::trim($POST{'message'}); + $body .= ""; + + $body .= "
    From:"; + + my $from = LJ::trim($POST{'from'}); + if ($cansend{$from}) { + $body .= "$from\@$LJ::DOMAIN"; + } else { + $errors = 1; + $body .= "Invalid address chosen"; + } + + $body .= "
    To:"; + + my @to; + if (LJ::trim($POST{'user'}) ne '') { + my $u = LJ::load_user($POST{'user'}); + unless ($u) { + $errors = 1; + $body .= "Invalid username $POST{user}"; + } else { + push @to, $u->{'email'}; + $body .= LJ::ljuser($u) . " ($u->{email})";; + } + } elsif (LJ::trim($POST{'maints'}) ne '') { + my $u = LJ::load_user($POST{'maints'}); + if ($u->{journaltype} ne 'C') { + $body .= "Community specified is not a community"; + } else { + my $ids = LJ::load_rel_user($u->{userid}, 'A'); + foreach (@$ids) { + my $maint = LJ::load_userid($_); + push @to, $maint->{'email'} + } + $body .= "Maintainers of "; + $body .= LJ::ljuser($u) . " ("; + $body .= join(", ", @to) . ")"; + } + } elsif (LJ::trim($POST{'email'}) ne '') { + my $addr = LJ::trim($POST{'email'}); + my @email_errors; + LJ::check_email($addr, \@email_errors); + if (@email_errors) { + $errors = 1; + $body .= ""; + $body .= join(", ", @email_errors); + $body .= ""; + } else { + push @to, $addr; + $body .= $addr; + } + } else { + $errors = 1; + $body .= "You must enter a recipient"; + } + + my $bcc = LJ::trim($POST{'bcc'}); + if ($bcc ne '') { + $body .= "
    Bcc:"; + + my @bcc_errors; + LJ::check_email($bcc, \@bcc_errors); + if (@bcc_errors) { + $errors = 1; + $body .= ""; + $body .= join(", ", @bcc_errors); + $body .= ""; + } else { + $body .= $bcc; + } + + $body .= "
    Request #:"; + if ($request ne '') { + unless ($request =~ /^\d+$/) { + $body .= "Request id must be numeric"; + $errors = 1; + } else { + $body .= $request; + } + } else { + $body .= "No request specified"; + } + $body .= "
    Subject:"; + if ($subject eq '') { + $body .= "You must specify a subject"; + $errors = 1; + } else { + $body .= $subject; + } + $body .= "
    Message:"; + if ($message eq '') { + $body .= "You must specify a message"; + $errors = 1; + } else { + my $tmp_mess = $message; + $tmp_mess =~ s/\r?\n/
    \n/g; + $body .= $tmp_mess; + } + $body .= "
    "; + + $body .= "
    "; + $body .= LJ::html_hidden('from', $from, 'to', join(',', @to), 'bcc', $bcc, + 'subject', $subject, 'message', $message, 'email', $POST{'email'}, + 'maints', $POST{'maints'}, 'user', $POST{'user'}, 'request', + $request); + $body .= LJ::html_hidden('extra', $POST{'extra'}) if $POST{'extra'}; + $body .= LJ::form_auth(); + + $body .= '
    '; + + $body .= LJ::html_submit('edit', '<- Edit', {'raw' => "onclick='form_switch()'"}); + $body .= LJ::html_submit('send', 'Send ->', {'disabled' => $errors}); + + $body .= "
    "; + $body .= "
    "; + + }; + + my $send = sub { + my @errors; + my $dbh = LJ::get_db_writer(); + return $body = LJ::bad_input('No database connection present. Please go back and try again.') + unless $dbh; + + return $body = LJ::bad_input($ML{'error.invalidform'}) + unless LJ::check_form_auth(); + + return $body = LJ::bad_input('Invalid sender') + unless $cansend{$POST{'from'}}; + + # Already did sanity checking in the previous step + my @addrs = split(',', $POST{'to'}); + + my %prettynames; + $prettynames{'abuse'} = "$LJ::SITENAMESHORT Abuse Team"; + $prettynames{'accounts'} = "$LJ::SITENAMESHORT Accounts"; + $prettynames{'coppa'} = "$LJ::SITENAMESHORT COPPA Enforcement"; + $prettynames{'support'} = "$LJ::SITENAMESHORT Support Team"; + + my $fromname = $prettynames{$POST{'from'}}; + + foreach my $email (@addrs) { + my $status = "S"; + # status "S" means send_mail returned true, but this does *not* guarantee + # that the message didn't bounce, only that the sendmail process didn't croak + + if(!LJ::send_mail({ + 'to' => $email, + 'bcc' => $POST{'bcc'}, + 'from' => "$POST{'from'}\@$LJ::DOMAIN", + 'fromname' => $fromname, + 'charset' => "utf-8", + 'subject' => $POST{'subject'}, + 'body' => $POST{'message'}, + })) + { + $status = "F"; + push @errors, "Error:
    Mail not sent to $email"; + } + + my $query = "INSERT INTO abuse_mail (mailid, userid, spid, status, timesent, mailto, " . + "subject, message, type) " . + "VALUES (NULL, ?, ?, ?, NOW(), ?, ?, ?, ?)"; + + $dbh->do($query, undef, $remote->{'userid'}, $POST{'request'}, $status, + $email, $POST{'subject'}, $POST{'message'}, $POST{'from'}); + + if ($dbh->err) { + my $error = $dbh->errstr; + push @errors, "Error: Unable to record mailing to $email
    $error"; + } + + # take extra actions if necessary + if ($POST{'extra'} =~ /^spam-notification;(\d+)$/) { + my $u = LJ::load_userid($1+0); + + push @errors, "Email was sent, statushistory not logged. p?>" + unless $u; + + LJ::statushistory_add($u->{userid}, $remote->{userid}, 'spam_warning', 'Sent email warning') + if $u; + } + } + + if (@errors) { + $body .= join("

    ", @errors); + } else { + $body .= "Email(s) sent succesfully"; + } + }; + + + # What to do aka "What it is" + if (LJ::did_post()) { + if ($GET{'action'} eq 'preview') { + $preview->(); + } elsif ($GET{'action'} eq 'edit') { + $compose->(1); + } elsif ($GET{'action'} eq 'send') { + $send->(); + } + } else { + $compose->(0); + } +} +_code?> +<=body +title=>Send User Mail +page?> diff --git a/ljcom/htdocs/admin/servers.bml b/ljcom/htdocs/admin/servers.bml new file mode 100644 index 0000000..9a790b3 --- /dev/null +++ b/ljcom/htdocs/admin/servers.bml @@ -0,0 +1,151 @@ +Error: You don't have access to see servers." + unless LJ::check_priv($remote, "siteadmin", "serverview"); + + # YAML parser is slow as fuck. + my $realfile = "$LJ::HOME/cgi-bin/servers.yaml"; + my $cached = "$LJ::HOME/var/servers.yaml.cache"; + + my $servers; + + if (-e $cached && (stat(_))[9] > (stat($realfile))[9]) { + # use the pre-parsed version from Storable, which doesn't suck. + $servers = Storable::retrieve($cached); + } else { + $servers = YAML::LoadFile($realfile); + Storable::store($servers, $cached); + } + + my $ret; + $ret .= "

    Servers

    "; + + my $name = $GET{'name'}; + my $mode = $GET{'mode'}; + my $job = $GET{'job'}; + $mode = "1job" if $job; + $mode = "1name" if $name; + + foreach (['', 'By Name'], + ['job', 'By Job'], + ['ip', 'By IP'], + ['cab', 'By Cabinet'], + ) { + if ($mode eq $_->[0]) { + $ret .= "[$_->[1]]\n"; + } else { + $ret .= "[$_->[1]]\n"; + } + } + + # sanitize the data structure a bit, and pick up on jobs/etc + my %jobs; + my %ip; + foreach my $name (keys %$servers) { + my $s = $servers->{$name}; + $s->{'jobs'} = [ $s->{'jobs'} ] unless ref $s->{'jobs'} eq "ARRAY"; + foreach (@{$s->{'jobs'}}) { $jobs{$_}->{$name} = 1; } + + my $ip = $s->{'ip'}; + my $hip = join(':', map { sprintf("%02x", $_) } split(/\./, $ip)); + $ip{$hip} = $name; + } + + # show a single server + if ($name) { + unless ($servers->{$name}) { $ret .= "bogus name"; return $ret; } + my $dp = Data::Dumper::Dumper($servers->{$name}); + my $link = sub { + my $roles = shift; + $roles =~ s/\'(.+?)\'/\'$1<\/a>\'/g; + return "'jobs' => [$roles]"; + }; + $dp =~ s/\'jobs\' => \[(.+?)\]/$link->($1)/se; + $ret .= "

    $name

    $dp
    "; + return $ret; + } + + my $serv_line = sub { + my $name = shift; + my $text = shift; + unless ($text) { + my $s = $servers->{$name}; + my $pip = $s->{'ip'}; + my $jobs = join(', ', map { "
    $_" } @{$s->{'jobs'}}); + $text = "[$pip] $jobs"; + } + return "

    $name $text

    \n"; + }; + + # show a single job + if ($job) { + unless ($jobs{$job}) { $ret .= "bogus job"; return $ret; } + $ret .= "

    Job: $job

      "; + foreach my $name (sort keys %{$jobs{$job}}) { + $ret .= $serv_line->($name); + } + $ret .= "
    "; + return $ret; + } + + # by job + if ($mode eq "job") { + foreach my $job (sort keys %jobs) { + $ret .= "

    Job: $job

      \n"; + foreach my $name (sort keys %{$jobs{$job}}) { + $ret .= $serv_line->($name); + } + $ret .= "
    "; + } + return $ret; + } + + # by cabinet + if ($mode eq "cab") { + my %cab; + my %u; + foreach my $name (keys %$servers) { + my $s = $servers->{$name}; + next unless $s->{'rack'}; + $cab{$s->{'rack'}->{'cabinet'}}->{$name} = 0; # not sure where for now + next unless $s->{'rack'}->{'size'} =~ /\d+/; + $u{$s->{'rack'}->{'cabinet'}} += $&; + } + foreach my $cab (sort { $a <=> $b } keys %cab) { + $ret .= "

    Cabinet: $cab ($u{$cab}U)

      \n"; + my $ch = $cab{$cab}; + foreach my $name (sort { $ch->{$a} <=> $ch->{$b} } keys %$ch) { + my $s = $servers->{$name}; + $ret .= $serv_line->($name, $s->{'rack'}->{'size'}); + } + $ret .= "
    "; + } + return $ret; + } + + # by ip + if ($mode eq "ip") { + foreach my $ip (sort keys %ip) { + my $dip = join('.', map { hex $_ } split(/:/, $ip)); + my $name = $ip{$ip}; + $ret .= $serv_line->($name, "[$dip]"); + } + return $ret; + } + + # by name + foreach my $name (sort keys %$servers) { + $ret .= $serv_line->($name); + } + + return $ret; +} +_code?> diff --git a/ljcom/htdocs/admin/support/index.bml b/ljcom/htdocs/admin/support/index.bml new file mode 100644 index 0000000..999e65b --- /dev/null +++ b/ljcom/htdocs/admin/support/index.bml @@ -0,0 +1,70 @@ +LiveJournal Support Tools +body<= +" . + "http://www.livejournal.com/support/." unless $remote && $canhelp; + + my $ret; + + $ret .= ""; + + $ret .= ""; + $ret .= ""; + + + my @scomms = ( + 'lj_support', 'helpscreening', 'support_interim', + 'support_clients', 'support_comms', 'support_embed', + 'support_general', 'support_mobile', 'support_ssystem', + 'support_syn', 'support_upi', 'support_web', 'web_ui', + 'web_training', 'lj_supportadmin' + ); + + $ret .= ""; + $ret .= "
      "; + + foreach (@scomms) { + $ret .= "
    • " . LJ::ljuser("$_") . + " (Post)
    • "; + } + $ret .= "
    "; + + + $ret .= ""; + $ret .= ""; + + return $ret; + + +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/agecheck/altform.bml b/ljcom/htdocs/agecheck/altform.bml new file mode 100644 index 0000000..0ce1f32 --- /dev/null +++ b/ljcom/htdocs/agecheck/altform.bml @@ -0,0 +1,154 @@ + + +Alternate Age Verification (for COPPA Compliance) + + + + +underage; + + my $ljuser = LJ::ljuser($remote); + my $datetime = LJ::time_to_http(); + my $postal_addr = LJ::Pay::postal_address_html('Attention: COPPA Verifications'); + + return qq{ +

    Alternate Age Verification

    +Please mail, fax, or scan & email this form using the contact information below. +
    + +

    + Fax: 415-294-5054
    + Email: coppa\@$LJ::DOMAIN (Please attach either PNG or JPG)

    + + $postal_addr +

    + + + + + + + + + + + + + + + + + + + + +
    User:$ljuser$remote->{user}
    Time:$datetime
    Notes: 
     
     
     
    + +

    Affix a copy of your government-issued photo ID or birth certificate here:

    +

    +

    Please direct all inquiries to $LJ::SITENAME Support. (http://www.livejournal.com/support/)

    + +}; # end qq{} +} +_code?> + + diff --git a/ljcom/htdocs/agecheck/consent.bml b/ljcom/htdocs/agecheck/consent.bml new file mode 100644 index 0000000..2c572cd --- /dev/null +++ b/ljcom/htdocs/agecheck/consent.bml @@ -0,0 +1,58 @@ +Age Verification (for COPPA Compliance) +body<= +"; + } + + my ($aaid, $auth) = ($1, $2); + my $aa = LJ::is_valid_authaction($aaid, $auth); + unless ($aa) { + return ""; + } + + # so, it's verified + my $u = LJ::load_userid($aa->{userid}); + unless ($u) { + return ""; + } + + # now do the work + LJ::mark_authaction_used($aa); + LJ::set_userprop($u, 'parent_email', $aa->{arg1}); + $u->underage(0, undef, "parent email verification; email=$aa->{arg1}"); + + # and now we have to send an email validation notice to the child's email + my $aa = LJ::register_authaction($u->{userid}, "validateemail", $u->{email}); + + my $body = BML::ml('email.newacct2.body', { + "email" => $u->{email}, + "regurl" => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}", + "username" => $u->{user}, + "sitename" => $LJ::SITENAME, + "siteroot" => $LJ::SITEROOT, + "admin_email" => $LJ::ADMIN_EMAIL, + "bogus_email" => $LJ::BOGUS_EMAIL, + }); + + LJ::send_mail({ + 'to' => $u->{email}, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => BML::ml('email.newacct.subject', {'sitename' => $LJ::SITENAME}), + 'body' => $body, + }); + + # queue up a message + return ""; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/agecheck/index.bml b/ljcom/htdocs/agecheck/index.bml new file mode 100644 index 0000000..0f46a7e --- /dev/null +++ b/ljcom/htdocs/agecheck/index.bml @@ -0,0 +1,177 @@ +Age Verification +body<= +" + unless $remote; + return "" + unless $remote->underage; + + if (LJ::did_post()) { + # make the cart and add our verification item + unless ($POST{cartid}) { + my $cart = LJ::Pay::new_cart($remote); + LJ::Pay::add_cart_item($cart, { + item => 'coppa', + rcptid => $remote->{userid}, + }); + $POST{cartid} = "$cart->{payid}-$cart->{anum}"; + } + + # redirect to it + return BML::redirect("$LJ::SSLROOT/pay/cc.bml?c=$POST{cartid}"); + } + + # throw in extra boxes + my ($extra, $cartid); + if ($GET{o}) { + $extra = ""; + } elsif ($GET{s}) { + $extra = ""; + } else { + $extra = ""; + } + if ($GET{c}) { + # verify input before putting in our output + $cartid = $1 + if $GET{c} =~ /^(\d+-\d+)$/; + } + + return qq{ +$extra + + + + + + + +
      +
    1. complete the registration;
    2. + +
    3. review our privacy policy and to submit a valid credit card number to +verify that the child's parent or guardian knows about and authorizes our +information practices related to children protected by COPPA; and
    4. + +
    5. verify through the use of an email confirmation and second +authorization that the parent or guardian consents to the Terms of +Service and LiveJournal.com's privacy policy.
    6. +
    + +Once parental notice and consent has been verified, the +information we collect will be treated the same as information collected +from any other user of LiveJournal.com.
    p?> + + + + + +
      + +
    • We do not transfer personal information we collect to people or +organizations outside the LiveJournal.com family of companies for their +direct marketing purposes.
    • + +
    • We do share this information within the LiveJournal.com family of +companies but any use or disclosure of this information is controlled by +our privacy policy.
    • + +
    • We may use or share account users' personal information where it +is necessary for us to complete a transaction, to operate or improve +LiveJournal.com and related products and services, to do something that the +user has asked us to do, or to tell the user of products and services that +we think may be of interest.
    • + +
    • We may occasionally contact our users with offers. When we do this, we +will do our best to provide you with an opportunity to opt-out of receiving +such further communications at the time you are contacted.
    • + +
    + +Detailed information on our complete privacy practices is available +here. + + + + + +privacy +policy. p?> + + + + + +
      + +
    • You can edit your child's LiveJournal.com Account Information at any +time. Most personal information provide to LiveJournal.com is entirely +optional. For example, to the extent that parents are considering whether +to permit their children to use the Service, we do not condition a child's +participation based upon their provision of any more personal information +than is necessary to operate the Service.
    • + +
    • You can delete your LiveJournal.com account by visiting our Account +Deletion page; however, please note that some personal information, +primarily your contact information, may remain in LiveJournal.com's records +to the extent necessary to protect LiveJournal's legal interests or +document compliance with regulatory requirements.
    • + +
    + + +printable form. p?> + + +
    +} . + +LJ::html_submit("Continue Electronic Verification") . "\n" . +LJ::html_hidden(cartid => $cartid) . "\n" . +"
    \n"; + +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/banners.bml b/ljcom/htdocs/banners.bml new file mode 100644 index 0000000..6386bd4 --- /dev/null +++ b/ljcom/htdocs/banners.bml @@ -0,0 +1,250 @@ +LiveJournal Banners + +body<= + + + +! h1?> + is by placing one of these banners on your website! The HTML is below, all you have to do is copy & paste into your HTML... +p?> + + + + +
    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner1.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner2.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner3.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner4.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner5.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner6.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner7.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner8.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner9.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner_metal.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/LJbanner_pastel.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out ! It's Free! +
    + + +<CENTER> +<A HREF="<?siteroot?>/"><IMG +SRC="<?imgprefix?>/banners/firebindy1.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="<?siteroot?>">Check out +<?sitename?>! It's Free!</A> +</CENTER> + +

    + + + + +<=body +page?> diff --git a/ljcom/htdocs/banners/firebindy1.gif b/ljcom/htdocs/banners/firebindy1.gif new file mode 100755 index 0000000000000000000000000000000000000000..e464c2e65f0779d95626a1134fbe707d97c4cf99 GIT binary patch literal 11433 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 hZKBvGG4pI?lIGq3h literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/bazaar/balance.bml b/ljcom/htdocs/bazaar/balance.bml new file mode 100644 index 0000000..82dbfe2 --- /dev/null +++ b/ljcom/htdocs/bazaar/balance.bml @@ -0,0 +1,110 @@ +Your Balance +body<= + +

    [<< Back]

    +{'userid'}); + + $sth = $dbh->prepare("SELECT date, amt, method, note FROM bzrpayout WHERE userid=?"); + $sth->execute($remote->{'userid'}); + my $hist; + while (my $po = $sth->fetchrow_hashref) { + unless ($hist) { + $hist .= ""; + $hist .= "\n"; + } + $hist .= "\n"; + } + if ($hist) { + $ret .= $hist; + $ret .= "
    DateAmountMethodNote
    $po->{'date'}\$" . sprintf("%0.02f", $po->{'amt'}) . "$po->{'method'}$po->{'note'}
    \n"; + } + + + $sth = $dbh->prepare("SELECT bzid, date, amt, owed, expired ". + "FROM bzrbalance WHERE userid=? ORDER BY bzid"); + $sth->execute($remote->{'userid'}); + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + my $owed; + my $rows = 0; + my $now = time(); + while (my $r = $sth->fetchrow_hashref) { + $rows++; + $ret .= ""; + $owed += $r->{'owed'}; + $ret .= sprintf("", $r->{'amt'}); + $ret .= sprintf("", $r->{'owed'}); + my $extra; + if ($r->{'expired'} > 0) { + $extra .= sprintf(" (\$%0.02f expired after 3 months unclaimed)", $r->{'expired'}); + } + my $time = LJ::mysqldate_to_time($r->{'date'}); + my $exptime = $time + 86400*93; + if ($r->{'owed'} > 0 && $now < $exptime) { + $extra .= ", balance will expire in " . int(($exptime - $now) / 86400) . " days"; + } + $ret .= ""; + $ret .= "\n"; + } + unless ($rows) { + return "No balance or history."; + } + $ret .= ""; + $ret .= "
    DateAmountBalanceNote
    $r->{'date'}\$%0.02f\$%0.02fBazaar \#$r->{'bzid'}$extra
    Amount owed:" . + sprintf("\$%0.02f", $owed) . "
    "; + + return $ret unless $owed; + + unless ($remote->{'legal_assignagree'}) { + $ret .= ""; + $ret .= ""; + $ret .= "Mailing address:
    " . LJ::Pay::postal_address_text() . "
    "; + $ret .= "Include your LiveJournal username, as well as a mailing address to send your check if your balance is over \$50. If you'd prefer to not get paid (and instead generate coupons later at this URL), indicate as such in your letter."; + + $ret .= ""; + $ret .= ""; + return $ret; + } + + if ($owed >= 50) { + $ret .= ""; + } else { + $ret .= ""; + } + + $ret .= "Important note: coupons are either used or unused... they don't maintain a balance. As such, only generate a coupon for the amount you intend to use. For your protection, we only allow coupons to be generated for the amounts \$5.00 - \$25.00. You may use multiple coupons in an order, if your order will be more than \$25.00. p?>"; + $ret .= "
    \n"; + $ret .= "Amount: \$ "; + $ret .= "
    "; + + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/bazaar/details.bml b/ljcom/htdocs/bazaar/details.bml new file mode 100644 index 0000000..4151aba --- /dev/null +++ b/ljcom/htdocs/bazaar/details.bml @@ -0,0 +1,97 @@ +Bazaar Details +body<= + +

    [<< Back]

    + + + + + + + + + + + +payment +coupons. A minimum $5 coupon may be generated. p?> + + +
  • Voter only -- not eligible to receive money (full-time LiveJournal employees, and anybody who contacts us and tells us that they don't wish to receive money)
  • +
  • Part-time employees -- details above. can vote, and can get some of the earned pot.
  • +
  • Money Queuing -- (default state) You haven't done the paperwork to receive money yet, but your earnings are being held for up to three months. If after 5 months you do the paperwork, you'll receive the money you earned in the previous three months.
  • +
  • Money Recipient -- you've done the paperwork and you'll get paid at the end of the month, after votes are tallied and reviewed. Money will be held indefinitely until you earn at least $25. (except if you live outside of the US and wire fees are high, in which case we won't pay until you've earned at least double what it'd cost to wire the money) + +p?> + + + + + + + + + + + + + + + + +<=body +page?> diff --git a/ljcom/htdocs/bazaar/gencoupon.bml b/ljcom/htdocs/bazaar/gencoupon.bml new file mode 100644 index 0000000..e1830c9 --- /dev/null +++ b/ljcom/htdocs/bazaar/gencoupon.bml @@ -0,0 +1,46 @@ +Generate Coupon +body<= +{'legal_assignagree'}; + + if ($GET{'cpid'}) { + my $cp = $dbh->selectrow_hashref("SELECT * FROM coupon WHERE cpid=? AND rcptid=?", + undef, $GET{'cpid'}, $remote->{'userid'}); + return "Error: Coupon not found" unless $cp; + return "\$$cp->{'arg'}:
    $cp->{'cpid'}-$cp->{'auth'}
    p?>payment history. p?>"; + } + + my $amt = $POST{'amt'}; + unless ($amt =~ /^(\d+)(\.(\d\d))?$/) { + return "Error: Invalid format."; + } + if ($amt < 5 || $amt > 25) { + return "Error: Amount must be between \$5.00 and \$25.00."; + } + + if (LJ::Pay::bazaar_remove_balance($remote, $amt)) { + my $auth = LJ::make_auth_code(10); + $dbh->do("INSERT INTO coupon (auth, type, arg, rcptid, locked, payid) VALUES (?, 'dollaroff', ?, ?, '0', 0)", + undef, $auth, $amt, $remote->{'userid'}); + die $dbh->errstr if $dbh->err; + my $id = $dbh->{'mysql_insertid'}; + my $coupon = "$id-$auth"; + $dbh->do("INSERT INTO bzrpayout (userid, date, amt, method, note) VALUES (?, NOW(), ?, 'coupon', ?)", + undef, $remote->{'userid'}, $amt, "coupon: $coupon"); + return BML::redirect("gencoupon.bml?cpid=$id"); + } else { + return "You don't have \$$amt in your balance. If you did a double submit, you can get your coupon code on your payment history."; + } + +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/bazaar/index.bml b/ljcom/htdocs/bazaar/index.bml new file mode 100644 index 0000000..1d9d252 --- /dev/null +++ b/ljcom/htdocs/bazaar/index.bml @@ -0,0 +1,43 @@ +The Bazaar +body<= + +The bazaar isn't really used anymore because it was too tedious to +maintain. We'd like to fix it and bring it back, but fixing it would +require analyzing what went wrong. + + + +details, but the basic gist is that each month there is a virtual pot, with so much money in it. At the end of the month the pot is divided up between the different contributors, based on weightings determined by the pot recipients of the previous month. The LiveJournal staff increases the pot amount as the month goes on when key goals are met and projects completed. +p?> + +
  • It gets money out to people who deserve it, without LiveJournal.com needing to hire and manage tons of people, who might have fluctuating amounts of free time, with school or other life commitments.
  • +
  • It lets us assign rough dollar amounts to projects we'd like to see done, without having to figure out exactly what everything's worth. We just commit to increasing the pot by, say, $200 for some project. The community's votes may end up making it worth $150 or $300.
  • +
  • It encourages communication. People have to let other people know what they're doing, and when they've finished it, to get acknowledged.
  • +
  • It encourages projects getting done. If somebody disappears for a few weeks, it's likely somebody else will finish their project first. Maybe the second person did it from scratch so the first person gets nothing, or maybe the second person worked off the former's ideas/code, and the community awards the first person some fraction. In any case, it relieves the need for anybody to hassle people to finish projects.
  • +
  • It encourages people to list their contributions. Even if they choose to not work for money, getting acknowledged at least gives them voting power for the next month. + +p?> + + + + +<=items +itemsb<= + + +<=itemsb +choices?> + +_c?> + +<=body +page?> diff --git a/ljcom/htdocs/bazaar/status.bml b/ljcom/htdocs/bazaar/status.bml new file mode 100644 index 0000000..521f764 --- /dev/null +++ b/ljcom/htdocs/bazaar/status.bml @@ -0,0 +1,112 @@ +Bazaar Status +body<= + +

    [<< Back]

    + +selectrow_hashref("SELECT * FROM bzrs WHERE open='1' ". + "ORDER BY datestart LIMIT 1"); + return "No bazaar session is currently active." unless $bz; + } else { + $bz = $dbh->selectrow_hashref("SELECT * FROM bzrs WHERE bzid=?", + undef, $bzid); + return "Invalid bazaar ID" unless $bz; + } + $bzid = $bz->{'bzid'}; + + my (@pot, $pot); + $sth = $dbh->prepare("SELECT dateadd, amt, reason FROM bzrpot ". + "WHERE bzid=? ORDER BY dateadd"); + $sth->execute($bzid); + while ($_ = $sth->fetchrow_hashref) { + push @pot, $_; + $pot += $_->{'amt'}; + } + + my $is_voter; + $sth = $dbh->prepare("SELECT u.user, u.name, v.weight FROM bzrvoter v, user u ". + "WHERE u.userid=v.userid AND v.bzid=? ". + "ORDER BY v.weight DESC"); + $sth->execute($bzid); + my @voters; + while ($_ = $sth->fetchrow_hashref) { + push @voters, $_; + $_->{'_votelink'} = 1 if $bz->{'open'} && $remote && + $remote->{'user'} eq $_->{'user'}; + } + + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + my $state = $bz->{'open'} ? "In progress" : "Completed"; + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "
    Bazaar Session:\#$bzid: $bz->{'name'}
    Start Time:$bz->{'datestart'}
    State:$state
    Pot:\$" . sprintf("%0.02f", $pot) . ""; + + if (@pot > 1) { + $ret .= "

    Details:"; + foreach (@pot) { + my $reason = $_->{'reason'}; + if ($LJ::ZILLA_ROOT) { + $reason =~ s/bug (\d+)/$&<\/a>/gi; + } + $ret .= sprintf("\n", + substr($_->{'dateadd'}, 0, 10), + $_->{'amt'}, $reason); + } + $ret .= "
    %s\$%0.02f%s
    "; + } + + $ret .= "

    \n"; + + $ret .= "the details to find out how the system works. p?>"; + + $ret .= "
    "; + $ret .= "\n"; + foreach my $v (@voters) { + my $name = LJ::eall($v->{'name'}); + $ret .= ""; + $ret .= "\n"; + } + $ret .= "
    UserWeight
    " . LJ::ljuser($v->{'user'}) . " - $name" . + sprintf("%0.02f%%", $v->{'weight'}*100) . ""; + if ($v->{'_votelink'}) { + $ret .= "[Vote]"; + } + $ret .= "
    "; + + $ret .= ""; + $ret .= "
    "; + $sth = $dbh->prepare("SELECT DISTINCT u.user, c.coid, c.cat, c.des, c.url, c.dateadd ". + "FROM contributed c, useridmap u, bzrvote v, bzrvoter vr ". + "WHERE u.userid=c.userid AND v.bzid=? AND vr.bzid=v.bzid ". + "AND vr.userid=v.userid AND v.coid=c.coid AND v.weight > 0 ". + "ORDER BY c.dateadd"); + $sth->execute($bzid); + while (my $c = $sth->fetchrow_hashref) { + my $des = LJ::eall($c->{'des'}); + $des = "$des" if $c->{'url'}; + $ret .= "

    [$c->{'coid'}] "; + $ret .= LJ::ljuser($c->{'user'}) . ": $des ($c->{'cat'}; $c->{'dateadd'})

    \n"; + } + $ret .= "
    "; + + return $ret; + +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/bazaar/vote.bml b/ljcom/htdocs/bazaar/vote.bml new file mode 100644 index 0000000..e222990 --- /dev/null +++ b/ljcom/htdocs/bazaar/vote.bml @@ -0,0 +1,154 @@ +Bazaar Voting +body<= + +

    [<< Back]

    + +login." unless $remote; + + my $bz = $dbh->selectrow_hashref("SELECT * FROM bzrs WHERE open='1' ". + "ORDER BY datestart LIMIT 1"); + return "No bazaar session is currently active." unless $bz; + my $bzid = $bz->{'bzid'}; + + return "You aren't a voter for the current bazaar session." + unless $dbh->selectrow_array("SELECT weight FROM bzrvoter WHERE bzid=? AND userid=?", + undef, $bzid, $remote->{'userid'}); + + # load votes (if voter) + my %votes; + $sth = $dbh->prepare("SELECT u.user, v.coid, v.weight, c.cat, c.des, c.url, c.dateadd ". + "FROM bzrvote v, contributed c, useridmap u ". + "WHERE v.bzid=? AND v.userid=? AND v.coid=c.coid ". + "AND u.userid=c.userid"); + $sth->execute($bzid, $remote->{'userid'}); + while (my $v = $sth->fetchrow_hashref) { + $votes{$v->{'coid'}} = $v; + } + + my @unvote; + $sth = $dbh->prepare("SELECT u.user, c.coid, c.cat, c.des, c.url, c.dateadd ". + "FROM contributed c, useridmap u ". + "WHERE u.userid=c.userid AND c.dateadd > ? ". + "AND c.userid <> ?"); + $sth->execute($bz->{'datestart'}, $remote->{'userid'}); + while (my $v = $sth->fetchrow_hashref) { + next if defined $votes{$v->{'coid'}}; + push @unvote, $v; + } + + if (LJ::did_post()) { + + foreach my $id (keys %votes) { + next if $POST{"weight_$id"} eq ""; + my $new = int($POST{"weight_$id"}); + $new = 0 if $new < 0; + next if $POST{"weight_$id"} eq $votes{$id}->{'weight'}; + $votes{$id}->{'weight'} = $new; + $dbh->do("REPLACE INTO bzrvote (bzid, userid, coid, weight) VALUES (?,?,?,?)", + undef, $bzid, $remote->{'userid'}, $id, $new); + } + + foreach my $v (@unvote) { + my $id = $v->{'coid'}; + next if $POST{"weight_$id"} eq ""; + + # delete contribution (so much stupid crap get submitted, like: + # "I gave my friend a code!") + if ($POST{"weight_$id"} eq "d") { + if (LJ::check_priv($dbh, $remote, "contrib_delete")) { + $dbh->do("DELETE FROM contributed WHERE coid=?", undef, $id); + $dbh->do("DELETE FROM contributedack WHERE coid=?", undef, $id); + } + $v->{'_deleted'} = 1; + next; + } + + $votes{$id} = $v; + my $new = int($POST{"weight_$id"}); + $new = 0 if $new < 0; + $votes{$id}->{'weight'} = $new; + $dbh->do("REPLACE INTO bzrvote (bzid, userid, coid, weight) VALUES (?,?,?,?)", + undef, $bzid, $remote->{'userid'}, $id, $new); + if ($new) { + $dbh->do("INSERT IGNORE INTO contributedack (coid, ackuserid) VALUES (?,?)", + undef, $v->{'coid'}, $remote->{'userid'}); + } + } + + # remove items that were just voted for + @unvote = grep { ! $votes{$_->{'coid'}} && ! $_->{'_deleted'} } @unvote; + + if ($POST{'new_id'}) { + my $c = $dbh->selectrow_hashref("SELECT u.user, c.coid, c.cat, c.des, c.url, c.dateadd ". + "FROM contributed c, useridmap u WHERE c.coid=? ". + "AND c.dateadd > DATE_SUB(NOW(), INTERVAL 60 DAY) ". + "AND u.userid=c.userid", + undef, $POST{'new_id'}); + return "Error: invalid contribution ID. Either does not exist, or is too old." + unless $c; + return "Error: can't vote for your own contributions" + if $c->{'user'} eq $remote->{'user'}; + $c->{'weight'} = ($POST{'new_weight'}+0) || 1; + $dbh->do("REPLACE INTO bzrvote (bzid, userid, coid, weight) VALUES (?,?,?,?)", + undef, $bzid, $remote->{'userid'}, $c->{'coid'}, $c->{'weight'}); + LJ::Contrib::ack($c->{'coid'}, $remote->{'userid'}); + $votes{$c->{'coid'}} = $c; + } + } + + $ret .= "this bazaar session, you can add contributions you'd like to recognize here, and weight them all appropriately in regards to each other. p?>"; + + $ret .= "
    "; + $ret .= "\n"; + my $tw = 0; + foreach (values %votes) { $tw += $_->{'weight'}; } + + my $row = sub { + my $v = shift; + my $des = LJ::eall($v->{'des'}); + if ($v->{'url'}) { + $v->{'url'} = LJ::eall($v->{'url'}); + $des = "$des"; + } + my $per = $v->{'weight'} ne "" ? sprintf("%0.02f%%", $v->{'weight'}*100/($tw||1)) : ""; + $ret .= ""; + }; + + # the ones that have been voted for, skipping zero weight + foreach my $v (sort { $b->{'weight'} <=> $a->{'weight'} } values %votes) { + next unless $v->{'weight'}; + $row->($v); + } + + $ret .= "\n"; + $ret .= "\n"; + + # unweighted contributions + if (@unvote) { + $ret .= "\n"; + foreach my $v (@unvote) { + $row->($v); + } + $ret .= "\n"; + } + + $ret .= "
    ContributionWeight
    [$v->{'coid'}] "; + $ret .= LJ::ljuser($v->{'user'}) . ": "; + $ret .= "$des
    $v->{'cat'}, $v->{'dateadd'}
    $per
    New vote item: Contribution ID:
    Contributions you haven't weighted:
    (set to 0 to remove from this list)
    "; + + return $ret; + +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/betatest.bml b/ljcom/htdocs/betatest.bml new file mode 100644 index 0000000..3df5c6f --- /dev/null +++ b/ljcom/htdocs/betatest.bml @@ -0,0 +1,87 @@ +Beta Test Page +body<= + +{'userid'}, "P"); + + if (LJ::did_post()) { + my $u; + if ($POST{fb_on} || $POST{pb_off}) { + return "Not allowed." unless $is_admin; + $u = LJ::load_user($POST{fbbeta}); + $betatext = "

    No such user $POST{fbbeta}.

    " unless $u; + $capname = '_fbbeta'; + if ($u && $POST{fb_on}) { + $set = 1; + $betatext = "

    " . LJ::ljuser($u) . " is now in the beta."; + } elsif ($u && $POST{fb_off}) { + $set = 0; + $betatext = "

    " . LJ::ljuser($u) . " is no longer in the beta."; + } + } else { + $capname = '_betatest'; + if ($POST{'no'}) { + BML::set_cookie("betatest", "", undef, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + $set = 0; + } + if ($POST{'yes'}) { + BML::set_cookie("betatest", "1", time()+60*60*24, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + $set = 1; + } + $u = $remote; + } + + # now set any sort of cap needed + if (defined $set) { + return "No such user to set cap for." unless $u; + my @cap = grep { $LJ::CAP{$_}->{'_name'} eq $capname } keys %LJ::CAP; + if ($u && scalar @cap == 1) { + my $capnum = $cap[0]+0; + if ($set) { + LJ::update_user($u, { raw => "caps=caps|(1<<$capnum)" }); + return "Beta-test mode is now ON."; + } else { + LJ::update_user($u, { raw => "caps=caps&~(1<<$capnum)" }); + return "Beta-test mode is now off."; + } + } + } + } + + my $ret = < + +

    +

    - Turn me on. +

    - No, stop the pain! +

    + +EOF + + if ($is_admin) { + $ret .= < +
    +

    Username: +

    +$betatext +

    +EOF + } + + $ret .= ""; + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/bots/index.bml b/ljcom/htdocs/bots/index.bml new file mode 100644 index 0000000..f0b44a2 --- /dev/null +++ b/ljcom/htdocs/bots/index.bml @@ -0,0 +1,28 @@ +LiveJournal Bot Policy +body<= + are subject to the following policy. If you have been redirected to this page it is because we believe you to be in control of an automated bot. If that is not the case, please contact us at webmaster@livejournal.com. p?> + + +
    +
    RSS:
    A user's recent entries syndicated using the Real Simple Syndication XML format. Available at the URL http://www.livejournal.com/users/username/data/rss
    +
    Atom:
    A user's recent entries syndicated using the Atom XML format. Available at the URL http://www.livejournal.com/users/username/data/atom
    +
    FOAF:
    A user's information page using the Friend of a Friend XML format. Available at the URL http://www.livejournal.com/users/username/data/foaf
    +
    Friend-Data
    A line separated list of usernames which are friends or friends-of a user. Available at the URL http://www.livejournal.com/misc/fdata.bml?user=username
    +
    Interest-Data
    Interests in a line separated format. Available at the URL http://www.livejournal.com/misc/interestdata.bml?user=username
    +
    + + + + +
    http://example.com/ljtoy.html; bob@example.com
    + +webmaster@livejournal.com. If we've blocked your bot and you'd like to contact us about it, please email us at webmaster@livejournal.com. p?> +<=body +head<= + +<=head +page?> diff --git a/ljcom/htdocs/code/cache/html b/ljcom/htdocs/code/cache/html new file mode 100644 index 0000000..96c4385 --- /dev/null +++ b/ljcom/htdocs/code/cache/html @@ -0,0 +1,75 @@ + + +LJ::Cache - LRU Cache + + + + + + + + + + +
    +

    +

    NAME

    +

    +LJ::Cache - LRU Cache + +

    +


    +

    SYNOPSIS

    +

    +

      use LJ::Cache;
    +  my $cache = new LJ::Cache { 'maxsize' => 20 };
    +  my $value = $cache->get($key);
    +  unless (defined $value) {
    +      $val = "load some value";
    +      $cache->set($key, $value);
    +  }
    +
    +

    +


    +

    DESCRIPTION

    +

    +This class implements an LRU dictionary cache. The two operations on it are +get() and set(), both of which promote the key +being referenced to the ``top'' of the cache, so it will stay alive +longest. + +

    +When the cache is full and and a new item needs to be added, the oldest one +is thrown away. + +

    +You should be able to regenerate the data at any time, if +get() returns undef. + +

    +This class is useful for caching information from a slower data source +while also keeping a bound on memory usage. + +

    +


    +

    AUTHOR

    +

    +Brad Fitzpatrick, bradfitz@bradfitz.com + +

    +


    +

    SEE ALSO

    +

    +perl(1). + + + + diff --git a/ljcom/htdocs/code/cache/index.bml b/ljcom/htdocs/code/cache/index.bml new file mode 100644 index 0000000..b405632 --- /dev/null +++ b/ljcom/htdocs/code/cache/index.bml @@ -0,0 +1,25 @@ +LJ::Cache +body<= + +<< Code | +Download: + + +LGPL, also available in the distribution. +p?> + +(.+?)<\/H1>//g; + $doc =~ s/

    (.+?)<\/H2>//g; + $doc =~ s/
    //g; + return $doc; + +_code?> + + +<=body +page?> diff --git a/ljcom/htdocs/code/clients/win32/index.bml b/ljcom/htdocs/code/clients/win32/index.bml new file mode 100644 index 0000000..334f944 --- /dev/null +++ b/ljcom/htdocs/code/clients/win32/index.bml @@ -0,0 +1,18 @@ +Windows Client Source +body<= + + +. +p?> +GPL. +p?> + changes to include in the core distribution. +p?> + +<=body +page?> \ No newline at end of file diff --git a/ljcom/htdocs/code/index.bml b/ljcom/htdocs/code/index.bml new file mode 100644 index 0000000..a320b77 --- /dev/null +++ b/ljcom/htdocs/code/index.bml @@ -0,0 +1,38 @@ +Code +body<= + + + + +Open Source / Free Software (depending which label you prefer), as are most the client apps. +p?> + + +latest snapshots in *.tar.gz format, or from CVS. The snapshots are taken pretty regularly, and CVS is almost always stable, so use whatever's easiest for you. Whatever you do, though, read the documentation. You can consult current issues and pending feature requests in our bug database. +p?> + + + +> + + + + + +
    NameDescription
    LJ::CachePerl module to do caching of images and other data from the database, while keeping a bound on memory usage.
    LJ::TextMessagePerl module to send people text messages on their cellphones and pagers
    LJ::SpellCheckPerl module to check spelling, using ispell or aspell
    HTML CleanerRemoves JavaScript and other harmful markup from HTML.
    BMLServer-side markup language and templating engine.
    +p?> + +<=body +page?> + + + + + diff --git a/ljcom/htdocs/code/mylj/ljsync-0.1.pl.txt b/ljcom/htdocs/code/mylj/ljsync-0.1.pl.txt new file mode 100755 index 0000000..2789d57 --- /dev/null +++ b/ljcom/htdocs/code/mylj/ljsync-0.1.pl.txt @@ -0,0 +1,287 @@ +#!/usr/bin/perl +# -*-perl-*- +# +# LiveJournal Sync Client +# (see http://www.livejournal.com/) +# (protocol information at http://www.livejournal.com/developer/) +# +# Brad Fitzpatrick +# bradfitz@bradfitz.com +# +# For this to work, make a ~/.livejournal.rc file like: +# +# user: username +# password: password +# syncdir: /path/to/syncdir/ +# +# use_proxy: 1 (optional) +# proxy_host: my.proxy.com (optional) +# proxy_port: 81 (optional) +# +# And, if not using livejournal.com's servers: +# +# server_host: ... +# server_port: ... +# server_uri: ... + +use strict; + +my $VERSION = "0.1"; +my $SERVER_HOST = "www.livejournal.com"; +my $SERVER_PORT = 80; +my $SERVER_URI = "/cgi-bin/log.cgi"; + +########################################################## + +use URI::Escape; +use LWP::UserAgent; + +# load the ~/.livejournal.rc file +my %rc = (); +load_rc_file(\%rc); +$rc{'server_host'} ||= $SERVER_HOST; +$rc{'server_port'} ||= $SERVER_PORT; +$rc{'server_uri'} ||= $SERVER_URI; + +unless ($rc{'user'}) { + die "Error: No username (user) specified in ~/.livejournal.rc\n"; +} +unless ($rc{'password'}) { + die "Error: No password specified in ~/.livejournal.rc\n"; +} +unless ($rc{'syncdir'}) { + die "Error: No sync directory specified in ~/.livejournal.rc\n"; +} + +unless (-d $rc{'syncdir'}) { + die "Sync dir does not exist ($rc{'syncdir'})\n"; +} +unless (-w $rc{'syncdir'}) { + die "Sync dir is not writable ($rc{'syncdir'})\n"; +} + +print "Starting sync.\n"; +my %last; +if (open (LAST, "$rc{'syncdir'}/lastsyncs.dat")) { + print "lastsync file opened.\n"; + while () { + chomp; + if (/^(\w+):\s*(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)/) { + $last{$1} = $2; + } + } + close LAST; +} else { + print "no lastsync file found (first use?)\n"; +} + +my $ua = make_lj_agent(); + +my $get_sync_items = 1; + +while ($get_sync_items) +{ + print "Getting some sync items...\n"; + print " last{L} = $last{'L'}\n"; + my %ljres = lj_request($ua, { + "mode" => "syncitems", + "user" => $rc{'user'}, + "password" => $rc{'password'}, + "lastsync" => $last{'L'}, + }); + + if ($ljres{'success'} eq "OK") + { + print "Got $ljres{'sync_count'} sync items of $ljres{'sync_total'} total.\n"; + if ($ljres{'sync_count'} == $ljres{'sync_total'}) { + print "Done getting sync items!\n"; + $get_sync_items = 0; + } + + my %syncitem; + + for (my $i=1; $i<=$ljres{'sync_count'}; $i++) { + next unless ($ljres{"sync_${i}_item"} =~ /^(.+?)-(\d+)/); + my $type = $1; + my $id = $2; + my $time = $ljres{"sync_${i}_time"}; + $syncitem{$type}->{$id} = $time; + } + + # currently there's only type "L" (journal entries), but + # this later could be "C"omment or "T"odo, etc.. + foreach my $type (keys %syncitem) + { + print "Syncing type: $type\n"; + + # journal entries + if ($type eq "L") { + + # rebuild journal entry here ($entry{$itemid}->{$key} = $val) + # before writing it to disk. + my %entry; + + # keep track of the most recent journal entry saved, + # but only use in the case when there are no left to + # find the minimum from. (for sending "lastsync") + my $maxtime = "0000-00-00 00:00:00"; + + # we want to keep fetching more items until no more of + # this type exist (we'll delete the key after we write + # it to disk) + while (keys %{$syncitem{$type}}) + { + print "Getting a batch of log entries...\n"; + print " keys = ", scalar(keys %{$syncitem{$type}}), "\n"; + print " lastsync = $last{'L'}\n"; + + my %sres = lj_request($ua, { + "mode" => "getevents", + "selecttype" => "syncitems", + "user" => $rc{'user'}, + "password" => $rc{'password'}, + "lastsync" => $last{'L'}, + }); + + if ($sres{"success"} ne "OK") { + die "getevents failed: $sres{'errmsg'}\n"; + } + + # these next two loops reconstruct the journal entry + # from the response + for (my $i=1; $i<=$sres{'events_count'}; $i++) { + my $itemid = $sres{"events_${i}_itemid"}; + $entry{$itemid} = { + 'itemid' => $itemid, + 'eventtime' => $sres{"events_${i}_eventtime"}, + 'event' => $sres{"events_${i}_event"}, + 'security' => $sres{"events_${i}_security"}, + 'allowmask' => $sres{"events_${i}_allowmask"}, + }; + } + for (my $i=1; $i<=$sres{'prop_count'}; $i++) { + my $itemid = $sres{"prop_${i}_itemid"}; + my $prop = $sres{"prop_${i}_name"}; + my $value = $sres{"prop_${i}_value"}; + $entry{$itemid}->{"prop_$prop"} = $value; + } + + # now, write each journal entry to disk, then erase + # its from the $syncitem{'L'} hash + print "Writing journal entries to disk...\n"; + print "Wrote: "; + foreach my $itemid (sort { $a <=> $b } keys %entry) + { + if (open(E, ">$rc{'syncdir'}/$itemid.entry")) { + foreach (sort keys %{$entry{$itemid}}) { + print E "$_: $entry{$itemid}->{$_}\n"; + } + close E; + print "$itemid, "; + + # increment maxtime if this sync item was newer. + if ($syncitem{'L'}->{$itemid} gt $maxtime) { + $maxtime = $syncitem{'L'}->{$itemid}; + } + delete $entry{$itemid}; + delete $syncitem{'L'}->{$itemid}; + } else { + die "Couldn't open $itemid.entry for write!\n"; + } + } + print "\n"; + + # now that's stuff written to disk, we need to update + # the $last{'L'} time + print "Find new LastL...\n"; + if (keys %{$syncitem{'L'}}) { + # find the earliest that isn't yet synced + my @times = sort values %{$syncitem{'L'}}; + $last{'L'} = $times[0]; + print "New LastL (keys) = $last{'L'}\n"; + } else { + $last{'L'} = $maxtime; # FIXME: subtract a second + # in case two entries were on + # same second. + print "New LastL (maxtime) = $last{'L'}\n"; + } + if (open (LAST, ">>$rc{'syncdir'}/lastsyncs.dat")) { + print LAST "L: $last{'L'}\n"; + close LAST; + } else { + die "Couldn't append lastsyncs.dat file.\n"; + } + } + + } + } + } + else + { + die "Error getting sync items: $ljres{'errmsg'}\n"; + } +} +print "DONE!\n"; + +sub load_rc_file +{ + my $rcref = shift; + my $file = "$ENV{'HOME'}/.livejournal.rc"; + return unless (-e $file); + open (RC, $file); + while () + { + s/^\s+//; + s/\s+$//; + next unless /\S/; + my ($var, $val) = split(/\s*:\s*/, $_); + $rcref->{$var} = $val; + } + close RC; +} + +sub make_lj_agent +{ + my $ua = new LWP::UserAgent; + $ua->agent("PerlLiveJournalClient/$VERSION"); + $ua->timeout(10); + return $ua; +} + +sub lj_request +{ + my $ua = shift; + my $vars = shift; + my %ljres = (); + + # Create a request + my $req = new HTTP::Request POST => "http://$SERVER_HOST:$SERVER_PORT/$SERVER_URI"; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(request_string($vars)); + + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + + # Check the outcome of the response + if ($res->is_success) { + %ljres = split(/\n/, $res->content); + } else { + $ljres{'success'} = "FAIL"; + $ljres{'errmsg'} = "Client error: Error contacing server."; + } + return %ljres; +} + +sub request_string +{ + my ($vars) = shift; + my $req = ""; + foreach (sort keys %{$vars}) + { + my $val = uri_escape($vars->{$_},"\+\=\&"); + $val =~ s/ /+/g; + $req .= "&" if $req; + $req .= "$_=$val"; + } + return $req; +} diff --git a/ljcom/htdocs/code/spellcheck/index.bml b/ljcom/htdocs/code/spellcheck/index.bml new file mode 100644 index 0000000..99bed0f --- /dev/null +++ b/ljcom/htdocs/code/spellcheck/index.bml @@ -0,0 +1,25 @@ +LJ::SpellCheck +body<= + +<< Code | +Download: + + +LGPL, also available in the distribution. +p?> + +(.+?)<\/H1>//g; + $doc =~ s/

    (.+?)<\/H2>//g; + $doc =~ s/
    //g; + return $doc; + +_code?> + + +<=body +page?> diff --git a/ljcom/htdocs/code/textmessage/index.bml b/ljcom/htdocs/code/textmessage/index.bml new file mode 100644 index 0000000..f7065d8 --- /dev/null +++ b/ljcom/htdocs/code/textmessage/index.bml @@ -0,0 +1,25 @@ +LJ::TextMessage +body<= + +<< Code | +Download: + + +LGPL, also available in the distribution. +p?> + +(.+?)<\/H1>//g; + $doc =~ s/

    (.+?)<\/H2>//g; + $doc =~ s/
    //g; + return $doc; + +_code?> + + +<=body +page?> diff --git a/ljcom/htdocs/comment_post.bml b/ljcom/htdocs/comment_post.bml new file mode 100644 index 0000000..b962a9b --- /dev/null +++ b/ljcom/htdocs/comment_post.bml @@ -0,0 +1,104 @@ +Comments Posted +body<= + +Down for Maintenance
    This page used database queries that were horribly unoptimized and killed the rest of the site. This is currently being fixed on the LiveJournal development server, and when it's fixed, the main server will be updated and this page will be available again."; + + my $dbh = LJ::get_db_writer(); + + my $ret = ""; + + my $user = lc($FORM{'user'}); + my $quser = $dbh->quote($user); + my $month = $FORM{'month'}; + my $year; + + if ($month =~ /^(\d\d\d\d)-(\d\d)$/) { + $year = $1; + $month = $2; + } else { + my @nowtime = localtime(); + $year = $nowtime[5]+1900; + $month = sprintf("%02d", $nowtime[4]+1); + } + my $qyear = $dbh->quote($year); + my $qmonth = $dbh->quote($month); + + $sth = $dbh->prepare("SELECT * FROM user WHERE user=$quser"); + $sth->execute; + my $u = $sth->fetchrow_hashref; + + unless ($u) { + return "$user. Sorry. p?>"; + } + + # get number of posts per month + $sth = $dbh->prepare("SELECT DATE_FORMAT(datepost, '%Y-%m') AS 'month', DATE_FORMAT(datepost, '%Y-%M') AS 'monthpretty', COUNT(*) AS 'count' FROM talk WHERE posterid=$u->{'userid'} GROUP BY 1, 2 ORDER BY 1"); + $sth->execute; + %permonth = (); + while ($_ = $sth->fetchrow_hashref) { + $permonth{$_->{'month'}} = { format => $_->{'monthpretty'}, + count => $_->{'count'} }; + } + + $ret .= "$u->{'name'}. You can also view other months this user has posted comments: p?>"; + $ret .= "
    Month:

    "; + + + # load the comment numbers + $sth = $dbh->prepare("SELECT t.datepost, uj.user as 'userjournal', t.nodeid AS 'itemid', t.parenttalkid, tt.subject FROM talk t, talktext tt, user uj WHERE t.talkid=tt.talkid AND t.journalid=uj.userid AND t.posterid=$u->{'userid'} AND t.state<>'D' AND t.nodetype='L' AND YEAR(t.datepost)=$qyear AND MONTH(t.datepost)=$qmonth ORDER BY t.datepost"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + @posts = (); + push @posts, $_ while ($_ = $sth->fetchrow_hashref); + + $TRUNCATE_SIZE = 50; + + # load the comments + my $itemid_in = join(", ", 0, map { $_->{'itemid'} } @posts); + $sth = $dbh->prepare("SELECT l.itemid, l.eventtime, LEFT(lt.event, $TRUNCATE_SIZE) AS 'eventtrunc', LENGTH(lt.event) as 'eventlength' FROM log l, logtext lt WHERE l.itemid IN ($itemid_in) AND l.itemid=lt.itemid"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + my %item = (); + $item{$_->{'itemid'}} = $_ while ($_ = $sth->fetchrow_hashref); + + $ret .= "

    \n"; + $ret .= "\n"; + + foreach my $p (@posts) + { + $id = $p->{'itemid'}; + $date = $p->{'datepost'}; + $date =~ s/ /
    /; + $ret .= ""; + + if ($p->{'parenttalkid'} == 0) { + $event = $item{$id}->{'eventtrunc'}; + $event =~ s/\<[^\>]*$//; + LJ::CleanHTML::clean_event(\$event); + if ($item{$id}->{'eventlength'} > $TRUNCATE_LENGTH) { $event .= "..."; } + $ret .= ""; + } else { + $ret .= ""; + } + + $p->{'subject'} ||= "(no subject)"; + $ret .= "\n"; + + } + $ret .= "
    DateEntrySubject
    $date{'userjournal'}\">$p->{'userjournal'}: $event(reply to other comment)$p->{'subject'}
    \n"; + return $ret; + +_code?> + + + +<=body +page?> diff --git a/ljcom/htdocs/comment_recv.bml b/ljcom/htdocs/comment_recv.bml new file mode 100644 index 0000000..61e8113 --- /dev/null +++ b/ljcom/htdocs/comment_recv.bml @@ -0,0 +1,102 @@ +Comments Received +body<= + +Down for Maintenance
    This page used database queries that were horribly unoptimized and killed the rest of the site. This is currently being fixed on the LiveJournal development server, and when it's fixed, the main server will be updated and this page will be available again."; + + my $dbh = LJ::get_db_writer(); + + my $ret = ""; + + my $user = lc($FORM{'user'}); + my $quser = $dbh->quote($user); + my $month = $FORM{'month'}; + my $year; + + if ($month =~ /^(\d\d\d\d)-(\d\d)$/) { + $year = $1; + $month = $2; + } else { + my @nowtime = localtime(); + $year = $nowtime[5]+1900; + $month = sprintf("%02d", $nowtime[4]+1); + } + my $qyear = $dbh->quote($year); + my $qmonth = $dbh->quote($month); + + $sth = $dbh->prepare("SELECT * FROM user WHERE user=$quser"); + $sth->execute; + my $u = $sth->fetchrow_hashref; + + unless ($u) { + return "$user. Sorry. p?>"; + } + + # get number of posts per month + $sth = $dbh->prepare("SELECT DATE_FORMAT(datepost, '%Y-%m') AS 'month', DATE_FORMAT(datepost, '%Y-%M') AS 'monthpretty', COUNT(*) AS 'count' FROM talkpost WHERE userjournal=$quser GROUP BY 1, 2 ORDER BY 1"); + $sth->execute; + %permonth = (); + while ($_ = $sth->fetchrow_hashref) { + $permonth{$_->{'month'}} = { format => $_->{'monthpretty'}, + count => $_->{'count'} }; + } + + $ret .= "$u->{'name'} which have been commented on by others, in reverse chronological order. You can also view other months this user has received comments: p?>"; + $ret .= "

    Month:

    "; + + # load the comment numbers + $sth = $dbh->prepare("SELECT itemid, COUNT(*) AS 'count' FROM talkpost WHERE userjournal=$quser AND YEAR(datepost)=$qyear AND MONTH(datepost)=$qmonth GROUP BY 1 ORDER BY datepost DESC"); + $sth->execute; + @items = (); + push @items, $_ while ($_ = $sth->fetchrow_hashref); + + $TRUNCATE_SIZE = 100; + + # load the comments + my $itemid_in = join(", ", 0, map { $_->{'itemid'} } @items); + $sth = $dbh->prepare("SELECT l.itemid, l.subject, l.eventtime, LEFT(l.event, $TRUNCATE_SIZE) AS 'eventtrunc', LENGTH(l.event) as 'eventlength' FROM log l LEFT JOIN friends f ON l.ownerid=f.userid AND f.friendid=$qremuid WHERE l.ownerid=$u->{'userid'} AND l.itemid IN ($itemid_in) AND ((l.security='public') OR (l.security='usemask' AND l.allowmask & f.groupmask) OR (l.ownerid=$qremuid))"); + $sth->execute; + + if ($dbh->err) { return "I'm working on this work now, I know it's an error.....: " . $dbh->errstr; } + + my %item = (); + $item{$_->{'itemid'}} = $_ while ($_ = $sth->fetchrow_hashref); + + $ret .= "

    \n"; + $ret .= "\n"; + + foreach my $i (@items) + { + $id = $i->{'itemid'}; + next unless (defined $item{$id}->{'eventtime'}); + $date = $item{$id}->{'eventtime'}; + $date =~ s/ /
    /; + $ret .= ""; + $ret .= "\n"; + + } + $ret .= "
    DateComment# Comments
    $date"; + $event = $item{$id}->{'eventtrunc'}; + $event =~ s/\<[^\>]*$//; + LJ::CleanHTML::clean_event(\$event); + + if ($item{$id}->{'eventlength'} > $TRUNCATE_LENGTH) { $event .= "..."; } + if ($item{$id}->{'subject'}) { + $ret .= "$item{$id}->{'subject'}
    "; + } + $ret .= "$event
    $i->{'count'}
    \n"; + return $ret; + +_code?> + + + +<=body +page?> diff --git a/ljcom/htdocs/dev/mailtest.bml b/ljcom/htdocs/dev/mailtest.bml new file mode 100644 index 0000000..493bdc3 --- /dev/null +++ b/ljcom/htdocs/dev/mailtest.bml @@ -0,0 +1,14 @@ + 'bradfitz@bradfitz.com', + 'from' => 'lj_dontreply@livejournal.com', + 'fromname' => 'Happy Happy Place', + 'subject' => 'this is but a test', + 'body' => 'this is all.' + }); + return "mailed"; + } + return "enter code."; + +_code?> diff --git a/ljcom/htdocs/dev/s2/2001-02-03.txt b/ljcom/htdocs/dev/s2/2001-02-03.txt new file mode 100644 index 0000000..0b3c58c --- /dev/null +++ b/ljcom/htdocs/dev/s2/2001-02-03.txt @@ -0,0 +1,287 @@ +# -*-perl-*- +# +# Miscalleneous notes on S2, the 2nd major +# version of the LiveJournal style system. +# +# Brad Fitzpatrick +# 2001-02-03 +# +########### +## goals +# +# 1. flexible/extensible: +# - layers +# - full programming language (*) +# - allows for internationalization +# - not specific to one view: +# - describe how to format objects +# - makes new views automatically supported, +# at least mostly. +# 2. safe: +# - (*) programming language has no unsafe +# looping/branching. only foreach +# on finite lists, ifs, etc. +# 3. fast: +# - precompiled +# 4. easy: +# - wizards/tools to generate each layer +# of S2 +# +# +########### +## layers +# +# +# core (definitions, defaults) +# style - the "style" +# colors - tied to a style. +# i18n - not tied to a style +# custom - changing comment links, counters, +# page.insert_html shit. +# +# layers are parsed and compiled before use. +# compiled into native language of appserver +# this is perl now, but easy to change later: +# parser -> AST stays the same. +# just change AST -> pretty printer. +# S2 is not tied to perl, then. can move to +# something faster later... C, anybody? +# S2 parser will be written in java, and +# tools will be provided for users to run and +# test styles on their own machines +# +########### +## core layer +# +# only layer where classes can be declared. + +set layertype "core"; +set author "webmaster"; + +class image { + var string url, + var int w, + var int h, + method void print (), # allow trailing commas: so nice. +}; + +method image::print { + """"""; +}; + +class comment_read { + var string urlread, + var int comment_count, + method void print (), +}; + +method comment_read::print () +{ + $noun = "Comments"; + if ($comment_count ==1 ) { + $noun = "Comment"; + } + """Read $comment_count $noun"""; +}; + +class comment_post { + var string urlpost, + method void print (), +}; + +method comment_post::print () +{ + """Leave a comment!"""; +} + +class comment_info { + var bool can_comment, + var comment_post post, + var comment_read read, + method void print (), +}; + +method comment_info::print () +{ + if ($can_comment == false) { + return; + } + if ($comment_count != 0) { + call $read print; + print " | "; + } + call $post print; +} + +# ack! There's English in there! ^^^^^^^^^ +# +# English will be default, everywhere, since it +# is anyway, right? Later we can have our +# master team of translators make new i18n layers +# that override these defaults. still, users +# can then override those i18n layers later, with +# their own words. users won't write in S2: +# we'll have stupid little wizards that ask them +# questions and generate/compile the S2 behind +# the scenes for them. for them, the process will +# be like: +# +# Pick Style: [ \/ ] +# Pick Language: [ \/ ] +# +# [ Continue--> ] +# +# Pick Style color theme: [ \/] +# or, enter your own: +# +# [ Finish ] [ More Customization -->] +# +# What do you want the comment links to say? +# ____________________ +# How many items on a page at once? _______ +# More stupid questions: _____________ + + +class journal_entry { + var string event, + var string subject, + var datetime eventtime, + var string current_mood, + var string mood_image, + var string current_music, + var bool opt_nocomments, + var user userpost, + var user userjournal, + var image userpic, + var comment_info comments, + var string urlself, + var string head, + method void print, +}; + +method journal_entry::print { + print "

    \n"; + ""; call $eventtime print_long; "
    "; + print $event; + if ($comments.can_comment) { + "

    "; + call $comments print; + } + "

    \n"; +}; + +class page { + var string view, + var bool remote_logged_in, # logged in user? + var bool remote_is_owner, # is it the journal owner? + var journal_entry[] entries, # + method void print, +}; + +method page::print +{ + local string title; + if ($view == "lastn") { + + } + """$title$head"""; + print "\n"; + + + print ""; +} + +######## +### style layer +## + +set layertype "style"; +set layername "Generator"; +set author "evan"; + +var string colitemborder = "#00f033"; +var string colpageback = "#a0a0a0"; + + +######## +### color layer +## + +set layertype "colors"; +set overlays "Generator"; # only for style layers +set author "bradfitz"; + +var string colitemborder = "#ff0000"; +var string colpageback = "#00cc00"; + +######## +### i18n layer +## + +set layertype "i18n"; +set layerlang "de"; +set author "mausal"; + +method comment_read::print () +{ + $noun = "Kommentar"; # warning: probably wrong. + if ($comment_count ==1 ) { + $noun = "Kommentar"; # probably wrong. + } + """Lesen $comment_count $noun"""; +}; + +method comment_post::print () +{ + """Schrieben eine Kommentar!"""; +} + +###### +### custom layer +## +## - auto-generated from a wizard +## ... or written by hand. (unlikely) + +set layertype "custom"; +set author "ibrad"; + +# ibrad-style popcorn links +method comment_read::print () +{ + $noun = "Kernels"; + if ($comment_count ==1 ) { + $noun = "Kernel"; + } + """$comment_count $noun."""; +}; + +# ibrad-style popcorn links +method comment_post::print () +{ + """Pop!"""; +} + +######## +### implementation +# +# + +request in: /users/bradfitz/ + +make_journal("bradfitz", "lastn"); + +my %methods; +foreach $layers ("core", @user_layers) { + load_layer($layers, +} + +$pageob = new S2::ob::page; +$pageob->setup_all_datastructures($dbh, $user, $view); +$journal = $methods{'page'}->{'print'}->($pageob); + + + + + + + diff --git a/ljcom/htdocs/dev/s2/goals.bml b/ljcom/htdocs/dev/s2/goals.bml new file mode 100644 index 0000000..a02fc46 --- /dev/null +++ b/ljcom/htdocs/dev/s2/goals.bml @@ -0,0 +1,80 @@ +Design Goals +body<= + +<< Back + + + +

    +> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FeatureS1S2
    Flexible & Extensible +The current style system forces users to define a template +for each new type of view: recent entries, friends page, +day view, calendar, etc. If we want to add a new view +type, users have to basically write their style. + +In the new style system you describe the formatting of objects, +not the formatting of views. Thus, we can easily add new views +in the future, and making a "lastn" view pretty much makes ally +your other views automatically. +
    Safe +The current system is completely safe. It's so brain-dead +that it can't be anything but but safe. You have +to have some intelligence to be harmful. + +The new style system is its own language that gets compiled into another language, and run on the webserver. Letting users run code on the server is inherently dangerous... it obviously has to be free of things "rm -rf /", but also, it has to be free from infinite loops, and anything that could consume large amounts of resources. +

    The S2 language does not have while loops, gotos, or any other control construct that would permit an infinite loops. It only has if/else blocks, and foreach over finite lists. Also, you can only call methods and functions defined in the core layer, so users can't write functions foo and bar which simply call each other. +

    Fast +The current system is a CPU hog, doing tons of parsing, text munging and substitutions and run-time. + +In the new system, S2 code will be parsed, checked, and compiled before the page is loaded. When a page is loaded in the future, the code will just be run, which will already be in the language that the LiveJournal server runs on. For LiveJournal.com, this will be Perl but in the future we could write a PHP or Java servlet backend to the S2 compiler. +
    Internationalizablilty +The current style system can support non-English languages and locales, but hardly: +

    -- The server injects a lot of English into S1 variables, especially in dates. +
    -- The calendar always begins weeks on Sunday. +
    -- The system to make nouns plural (2 Comments, 3 Replies) is very English-specific. +
    -- Porting a style to a new language involves forking the style and modifying away, losing all future changes to the original style. +

    +The new style system is being design for internationalization. One of the S2 layers is an "i18n layer", which overrides English method definitions from the core and sets properties, like the day weeks start on. +
    Easy +Hahah ... the currently style system was never designed to be easy. It was designed for a few people (me, maybe a friend or two) to make styles, which we'd then make public. I never envisioned everybody using LiveJournal to begin with, much less trying to make styles. + +Wizards and tools will generate S2 behind the scenes for most users. The hard-core users can write their styles and overlay layers in the raw S2 language. +
    + +<=body +page?> diff --git a/ljcom/htdocs/dev/s2/index.bml b/ljcom/htdocs/dev/s2/index.bml new file mode 100644 index 0000000..91f7660 --- /dev/null +++ b/ljcom/htdocs/dev/s2/index.bml @@ -0,0 +1,19 @@ +S2 +body<= + + +bradfitz to join the lj_dev group. +p?> + + + +

  • Design Goals -- with a comparison to the existing style language +
  • 2001-02-03.txt -- misc notes, with some hints as to what S2's syntax may look like + +p?> + +<=body +page?> diff --git a/ljcom/htdocs/developer/embedding.bml b/ljcom/htdocs/developer/embedding.bml new file mode 100644 index 0000000..b00a137 --- /dev/null +++ b/ljcom/htdocs/developer/embedding.bml @@ -0,0 +1,470 @@ + "short lowercase 'group of methods' name", +# 'title' => "full title", +# 'detail' => "optional extra description", +# 'methods' => +# [ +# 'name' => "optional method name", +# 'author' => "optional method author", +# 'text' => "mandatory paragraph", +# 'explanation' => "optional 'why this does such and such'", +# 'note' => "optional 'warning' or 'caution'", +# 'example' => "mandatory example", +# ] +# }; + +my $method_javascript = +{ + 'text' => + "", + 'explanation' => + "document.write("...."); JavaScript command. p?>', + 'example' => <<"EOT", +<script language="JavaScript" +src="http://www.livejournal.com/customview.cgi?username=[[username]]&amp;styleid=101&amp;enc=js"> +<noscript><a href="http://[[username]].livejournal.com/">View my LiveJournal</a></noscript> +</script> +EOT +}; + +my $method_frameslayers = +{ + 'text' => + "www.livejournal.com from the URL and make your journal ". + "look like part of your site is using frames... put the HTML page with the ". + "<frameset> on your own server, and then make one of the frames be ". + "your journal. This method will work with any frame-supporting browser, ". + "including Netscape and Internet Explorer. p?>". + "<iframe>. Internet Explorer supports this, as do ". + "Netscape 6, Mozilla and all recent Opera versions. Inline frames ". + "aren't as compatible as normal frames, and won't work in Netscape 4. ". + "The following example shows an iframe: p?>", + 'note' => + "<iframe>, see ". + "the HTML 4.0 spec. p?>", + 'example' => <<"EOT", +<center> +<iframe name="livejournal" +src="http://www.livejournal.com/users/[[username]]/" +frameborder="0" +scrolling="auto" height="400" width="460"> +<a href="http://[[username]].livejournal.com/">View my LiveJournal</a> +</iframe> +</center> +EOT +}; + +my $method_cgi_script = +{ + 'name' => "Basic CGI Script", + 'text' => + "", + 'explanation' => + "www.livejournal.com, because your server is ". + "actually the one that's downloading it. p?>", + 'note' => + "LibWWW module for perl, which you may need to install on your server, ". + "or have your admin do it. p?>", + 'example' => + <<"EOT", +#!/usr/bin/perl + +use LWP::Simple; +print "Content-type: text/html\\n\\n"; +print get('http://www.livejournal.com/customview.cgi' . + '?username=[[username]]&styleid=101'); +EOT +}; + +my $method_cgi_ssi = +{ + 'name' => "Server Side Includes and CGI", + 'text' => + "", + 'note' => + ".shtml, ". + "or set its execute bit; it depends on your webserver and how it's configured. ". + "In order to figure that out you might need to talk to your sysadmin. p?>", + 'example' => + <<"EOT", +<!--#exec cgi="/cgi-bin/livejournal.cgi" --> +EOT +}; + +my $method_bml = +{ + 'text' => + "BML on your server, you need ". + "to do two things in your document. First, you need to set the NOCACHE flag (example included), so that the visitor's ". + "browser doesn't store old states of the page in cache. Then you simply need to add in the given ". + "_CODE block somewhere on your page. p?>\n". + "", + 'note' => + "LibWWW module for Perl, which you may need to install on your server, ". + "or have your admin do it. p?>", + 'example' => + "1\n_info?>\n\n". + BML::ehtml(""), +}; + +my $method_python = +{ + 'author' => " Jeremy Tribby", + 'text'=> + "", + 'example' => <<"EOT", +<% +import urllib +u = urllib.open('http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101') +print 'Content-type: text/html\\n\\n' +print u.read() +%> +EOT +}; + +my $method_flash = +{ + 'text' => + "One of our users informed us that it is possible to have Flash download a list of ". + "variables to prefill into text elements in a Flash file. The formatting of these ". + "variable=value pairs are the same as in URLs. To accomodate this need, we provide ". + "a style which does this formatting for you. As an example, see the URL below.", + 'example' => + 'http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=103', +}; +my $method_php_fpassthru = +{ + 'name' => "Using fpassthru()", + 'author' => "Bill Humpries", + 'text' => "", + 'explanation' => + "fopen() to open the journal URL, and then uses fpassthru() ". + "to pass the journal content to stdout. p?>", + 'example' => <<"EOT", +<?php +\$journalURL = "http://www.livejournal.com/". + "customview.cgi?username=[[username]]&styleid=101"; + +if (\$fh = fopen(\$journalURL,"r")) { + fpassthru(\$fh); +} else { + echo "<p>Unable to load journal.</p>\\n"; +} +?> +EOT +}; + +my $method_php_fsockopen = +{ + 'name' => "Using fsockopen()", + 'author' => "Elliot Schlegelmilch", + 'text' => "", + 'explanation' => + "fsockopen() to open a network socket to the journal site, and then uses the HTTP protocol to ". + "request the journal's content. Given that it doesn't fail, it will simply fetch each line of the server's response. p?>", + 'example' => <<"EOT", +<?php +\$fp = fsockopen("www.livejournal.com", 80, &\$errno, \&\$errstr, 30); +if(\$fp) { + fputs(\$fp,"GET /customview.cgi?". + "username=[[username]]&styleid=101 HTTP/1.0\\n\\n"); + while(!feof(\$fp)) { + echo fgets(\$fp,128); + } + fclose(\$fp); +} +?> +EOT +}; + +my $method_php_file = +{ + 'name' => "Using file()", + 'author' => "Jay Cuthrell", + 'text' => "This method is useful for those that want a line by line parse of their journal, with line number references.", + 'explanation' => + "file() function to read in the journal content as a large array, and then it prints ". + "it back out line by line. p?>", + 'example' => <<"EOT", +<?php +\$page = "http://www.livejournal.com/customview.cgi". + "?username=[[username]]&styleid=101"; +\$content = file(\$page); +\$slurp = ""; +while (list(\$foo,\$bar) = each(\$content)) { + \$slurp .= \$bar; +} +echo \$slurp; +?> +EOT +}; + +my $method_php_include = +{ + 'name' => "Using include()", + 'author' => "Jon Parise", + 'text' => "", + 'note' => "", + 'example' => <<"EOT", +<?php +include "http://www.livejournal.com/customview.cgi". + "?username=[[username]]&styleid=101"; +?> +EOT +}; + +my $method_asp_xmlhttp = +{ + 'name' => "Using the Microsoft.XMLHTTP component", + 'author' => "Pavel Titov", + 'text' => "Microsoft.XMLHTTP component and IIS. p?>", + 'example' => <<"EOT", +<% + Response.Buffer = True + Dim xml + + ' Create an xmlhttp object: + Set xml = Server.CreateObject("Microsoft.XMLHTTP") + ' Or, for version 3.0 of XMLHTTP, use: + ' Set xml = Server.CreateObject("MSXML2.ServerXMLHTTP") + + ' Opens the connection to the remote server. + xml.Open "GET", + "http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101", + False + + ' Actually Sends the request and returns the data: + xml.Send + + Response.Write xml.responseText + + Set xml = Nothing +%> +EOT +}; + +my $method_asp_perlscript = +{ + 'name' => "Using PerlScript", + 'author' => "Ansley Ingram", + 'text' => "", + 'note' => + "ActivePerl ". + "installation for NT from ActiveState. p?>", + 'example' => <<"EOT", +<%\@language=perlscript%> +<% + use LWP::Simple; + \$Response->Write(get 'http://www.livejournal.com/customview.cgi?' . + 'username=[[username]]&styleid=101'); +%> +EOT +}; + +my $method_aolserver = +{ + 'author' => "", + 'text' => "", + 'note' => + "not for people using AOL's Internet Access service; ". + "it is for people using the AOLServer web server. p?>", + 'example' => <<"EOT", +<% + ns_puts "[ns_geturl http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101 ]" +%> +EOT +}; + +my $method_coldfusion = +{ + 'author' => "", + 'text' => "", + 'example' => <<"EOT", +<CFHTTP +URL="http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101" + METHOD="GET"> +</CFHTTP> +<CFOUTPUT>\#cfhttp.filecontent\#</CFOUTPUT> +EOT +}; + +my @methods = +( + {'group' => "js", + 'title' => "JavaScript", + 'detail' => "The easiest way to embed", + 'methods' => [$method_javascript], + }, + {'group' => "frameslayers", + 'title' => "HTML Frames", + 'detail' => "The next easiest way", + 'methods' => [$method_frameslayers], + }, + {'group' => "cgi", + 'title' => "CGI Scripts", + 'detail' => "Easy server side programming", + 'methods' => [$method_cgi_script, $method_cgi_ssi,], + }, + {'group' => "bml", + 'title' => "Better Markup Language", + 'detail' => "Using the language of LiveJournal", + 'methods' => [$method_bml], + }, + {'group' => "flash", + 'title' => "Macromedia Flash", + 'methods' => [$method_flash], + }, + {'group' => "php", + 'title' => "PHP", + 'methods' => [$method_php_fpassthru, $method_php_fsockopen, $method_php_file, $method_php_include], + }, + {'group' => "python", + 'title' => "Python", + 'methods' => [$method_python], + }, + {'group' => "asp", + 'title' => "Active Server Pages", + 'methods' => [$method_asp_xmlhttp, $method_asp_perlscript], + }, + {'group' => "coldfusion", + 'title' => "Cold Fusion", + 'methods' => [$method_coldfusion], + }, + {'group' => "adp", + 'title' => "AOLServer .adp pages", + 'methods' => [$method_aolserver], + }, +); + +my $selected_method_group = $FORM{'method'}; +my $valid_selection = (defined $selected_method_group and + ($selected_method_group eq "all" or + grep { $selected_method_group eq $_->{'group'} } @methods)); + +unless ($valid_selection) +{ + $ret .= <<"EOT"; + + + +paid account feature, +and so these instructions will not work for users with free accounts. p?> + +Listed below are some of the different ways that you can embed your journal. +
      +EOT + foreach my $method (@methods) { + my $group = LJ::eurl($method->{'group'}); + $ret .= "
    • $method->{'title'}"; + if (defined $method->{'detail'}) { + $ret .= " - $method->{detail}\n"; + } + } + $ret .= <<"EOT"; +
    + +view all of the methods on +one page. +p?> + +<< Back to the developer area +EOT + $body = $ret; + return; +} + +my $remote = LJ::get_remote_noauth(); +my $ru=$remote->{'user'} || "username"; + +my $display_method = sub +{ + my $method = shift; + my $heading = (shift() ? "H1" : "H2"); + + next if not defined $method->{'methods'}; + foreach $method (@{$method->{'methods'}}) { + if (defined $method->{'name'}) { + $ret .="{'name'} $heading?>\n"; + } + if (defined $method->{'author'}) { + $ret .="Contributed by: "; + $ret .= $method->{'author'} . " p?>"; + } + $ret .= "$method->{text}\n"; + if (defined $method->{'explanation'}) { + $ret .= "$method->{'explanation'}\n"; + } + if (defined $method->{'note'}) { + $ret .= "$method->{'note'}\n"; + } + my $example=$method->{'example'}; + $example=~s/\[\[username\]\]/$ru/gs; + $ret .= '
    ';
    +         $ret .= $example;
    +         $ret .= '
    '; + } + }; + +if ($selected_method_group eq "all") { + $title .= " - All Methods"; + foreach my $method (@methods) { + $ret .= "{'title'} h1?>\n"; + $display_method->($method); + $ret .= ""; + } + + } else { + foreach my $method (@methods) { + if ($method->{'group'} eq $selected_method_group) { + $title .= " - $method->{'title'}"; +# $ret .= "{'title'} h1?>\n"; + $display_method->($method,1); + $ret .= ""; + } + } + } +$ret .= '<< Back to the embedding page'; +$body = $ret; +return; +_code?> + + +body=> +page?> diff --git a/ljcom/htdocs/developer/exporting.bml b/ljcom/htdocs/developer/exporting.bml new file mode 100644 index 0000000..3406335 --- /dev/null +++ b/ljcom/htdocs/developer/exporting.bml @@ -0,0 +1,155 @@ +Exporting Comments +body<= + + +LiveJournal Bot Policy page, which discusses more general +rules on how to download information from our servers without getting yourself banned. Also please +follow the directions contained in this guide. p?> + +sessiongenerate protocol mode or by posting login information to the +login.bml page. p?> + + + + + +W3C Date and Time format.' ], + [ 'property', '', 'body', 'no', 'The property tag has one attribute, name, that indicates the name of this property. The content of the tag is the value of that property.' ], + ); + + my $ret = ''; + foreach my $r (@elements) { + $ret .= "\n"; + $ret .= "\n" foreach @$r; + $ret .= "\n"; + } + return $ret; +} +_code?> + +
    ElementAttributeModeMutableDescription
    $_
    + + +NOTE: Please cache metadata, but note that it does contain things that + can change about a comment. You should follow these instructions to update your cache once in a while. +standout?> + + + + GET /export_comments.bml?get=comment_meta&startid=0 p?> + + + + + <?xml version="1.0" encoding='utf-8'?> + <livejournal> + <maxid>100</maxid> + <comments> + <comment id='71' posterid='3' state='D' /> + <comment id='70' state='D' /> + <comment id='99' /> + <comment id='100' posterid='3' /> + <comment id='92' state='D' /> + <comment id='69' posterid='3' state='S' /> + <comment id='98' posterid='3' /> + <comment id='73' state='D' /> + <comment id='86' state='S' /> + </comments> + <usermaps> + <usermap id='6' user='test2' /> + <usermap id='3' user='test' /> + <usermap id='2' user='xb95' /> + </usermaps> + </livejournal> +p?> + + + + + + + sub gather_metadata + get largest comment id known about from my cache + GET /export_comments.bml?get=comment_meta&startid=maxid+1 + add results to metadata cache + if maximum id returned is less than maxid returned, call gather_metadata again + end sub + p?> + + +WARNING: Comment body data is to be heavily cached. None of + this data can change. Once you have downloaded a comment, you do not need to do so again. +standout?> + + + + + sub download_comments + get largest comment id we have fully downloaded + GET /export_comments.bml?get=comment_body&startid=maxid+1 + add results to comment cache + if maximum id returned is less than maxid in metadata cache, call download_comments again + if nothing was returned, and startid+1000 < maxid from metadata, call download_comments again + end sub + p?> + + + + + <?xml version="1.0" encoding='utf-8'?> + <livejournal> + <comments> + <comment id='68' posterid='3' state='S' jitemid='34'> + <body>we should all comment all day</body> + <date>2004-03-02T18:14:06Z</date> + </comment> + <comment id='69' posterid='3' state='S' jitemid='34'> + <body>commenting is fun</body> + <date>2004-03-02T18:16:08Z</date> + </comment> + <comment id='99' jitemid='43' parentid='98'> + <body>anonynote!</body> + <date>2004-03-16T19:06:31Z</date> + <property name='poster_ip'>127.0.0.1</property> + </comment> + <comment id='100' posterid='3' jitemid='43' parentid='98'> + <subject>subject!#@?</subject> + <body>&lt;b&gt;BOLD!&lt;/b&gt;</body> + <date>2004-03-16T19:19:16Z</date> + </comment> + </comments> + </livejournal> + p?> + +Bot Policy page. p?> + +<=body +page?> diff --git a/ljcom/htdocs/developer/index.bml b/ljcom/htdocs/developer/index.bml new file mode 100644 index 0000000..f68cf22 --- /dev/null +++ b/ljcom/htdocs/developer/index.bml @@ -0,0 +1,52 @@ + +body<= + h1?> + p?> + p?> + + h1?> + p?> + + h1?> + p?> + + h1?> + p?> + h2?> +
    +
    +
    +
    +
    +
    +
    +
    + + h2?> +
    +
    +
    +
    +
    +
    + + h1?> + p?> + + h1?> + p?> + + + +comment exporting tutorial for more +information. p?> + +<=body +head<= + +<=head +page?> diff --git a/ljcom/htdocs/developer/lj-icons.zip b/ljcom/htdocs/developer/lj-icons.zip new file mode 100644 index 0000000000000000000000000000000000000000..6cdd7b80df0bd4b3c88604c20fedeaea830a643f GIT binary patch literal 1637 zcmWIWW@Zs#U|`^2kmV0oPu{#+>nxD>kBNbSi$Q=PFTW(!z*sLcIX^UlhhajnkVRC5 zpv4!)FN||1ZRBe*5OK|SZ1#KfNUOQIe&PHBui`ft-kLb^h{X@{zcTJ-k3#NO=W?nx zHr_73eP`Ys0gi@6p(2(M_gO41R;r3Wv5rhs_EDcPaa!ZGcMpz+Z;?!XaqQHAsPYew zwC^pubu=*4EF(3qNo`O3v)a8UepgKtp7%WVOP%jxd&jjO-ddmd_*dEE*WHHbhgAob zekh##bBCYhs^Gp?Qx;o2UBS0>vDJj>Tsx&t9_N`ld*^&rp?aO>D_JW<-CoVDl;3my zp85Ob=C<8y-@N}cY5o)b0F*#*R!FXSi5>_h*aBhcMBBbY1_G_~6BoB|WvmD;;^}jE z9lc|5kM*`Cg$HwsL{8~yu9UcU<7e@bjPP6O_SVMtGm>sLJY4ZwHpE{0!GXUX*S~a{ z{pdQgeuIL%`X2w;e7=R5x2H*V3M*w^UZ@#ccePGwUSa*-o}vSJQPGS?*Phw2`MKf8 z6km?*udG)l=B$y`YT3x0xZ;AuwQr(}HU`SQ3q2qEWLt>N%KBrz=T!^MAHUd9QnT>? zw&&b`+4o(jw|;GZ@21+Pld58t{-QT0i&$Roy16*_--iu>mpaw8qZ53kx4!?=pZ|7i z-GYhYf0rG-%>T=E|Lh<4(E_NaecxVPM$}Ydh&_OUtb-042*k1*ZQ|-((7-u0wy3*+ zWxJiHm5!Cwa?giNyMM5)D0TN-dC65R$^P1rZ#*Vzw(PE|x^!7w;c(Eja))nw87q$b z>4{ske?fY|={dI#=s(-hR6J=#fOy-!_Z!uVS|wBi7wU0kpMJOAt)P5|)ce$(Iw65P zFWDB}y2aue8~%Rs)*gAkFt*dLyslquxPxpTomoHlttp^=__$V7>BY^;+-ihtv8N^|PPl%=Z6far;J0h3cNqo!8Iww-qel zEj49({fEV|T*N*3@>An&2bV`*opk0`>L0HE^$Z{6JK`CtZ4w`5%zt6wXO`PiO z7HA#h=OMtjt;Oq{n69JVGEU|{HV1VUCa<2yo5em&)Xj1K!F#;YGXLA2zwFr^ckP+= zy@X{Y`>wyVtu?y&Q}w!gYIR%lK+^zjGf*=qvKeZ?f*oWAEW6@112z32o6*h8 XfR-AOO<`pN`IQ9-g@Eq0Wd-p7HC32* literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/developer/logo.gif b/ljcom/htdocs/developer/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..2ffc6e9e6b348234404da0a35c135fec3a6cf704 GIT binary patch literal 7326 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 +_info?> +body<= + + request mode. +p?> + +{'name'} eq $v } @vars) + { + my $mode = $v->{'name'}; + $ret .= "

    $mode
    \n\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + unshift (@{$v->{'props'}->{'request'}}, + { 'name' => "mode", 'props' => { 'des' => "The protocol request mode: $mode", } }, + { 'name' => "user", 'props' => { 'des' => "Username. Leading and trailing whitespace is ignored, as is case.", } }, + { 'name' => "password", 'props' => { 'des' => "Password in plain-text. Either this needs to be sent, or hpassword.", } }, + { 'name' => "hpassword", 'props' => { 'des' => "Alternative to plain-text password. Password as an MD5 hex digest. Not perfectly secure, but defeats the most simple of network sniffers.", } }, + { 'name' => "ver", 'props' => { 'des' => "Protocol version supported by the client; assumed to be 0 if not specified. See this document for details on the protocol version.", 'optional' => 1, } }, + ); + unshift (@{$v->{'props'}->{'response'}}, + { 'name' => "success", 'props' => { 'des' => "OK on success or FAIL when there's an error. When there's an error, see errmsg for the error text. The absence of this variable should also be considered an error.", } }, + { 'name' => "errmsg", 'props' => { 'des' => "The error message if success was FAIL, not present if OK. If the success variable isn't present, this variable most likely won't be either (in the case of a server error), and clients should just report \"Server Error, try again later.\".", } }, + ); + + foreach my $rr (qw(request response)) + { + $ret .= "\n"; + foreach (@{$v->{'props'}->{$rr}}) + { + my $des = $_->{'props'}->{'des'}; + $des =~ s!\[special\[logprops\]\]!logprops!; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + } + } + + $ret .= "
    Description
    $v->{'props'}->{'des'}
    " . ucfirst($rr) . "
    $_->{'name'}"; + if ($_->{'props'}->{'optional'}) { + $ret .= "(Optional) "; + } + $ret .= $des; + $ret .= "
    \n"; + } + return $ret; + +_code?> + + +Back to Protocol Modes.
    +Back to Protocol Documentation.
    +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/modelist.bml b/ljcom/htdocs/developer/modelist.bml new file mode 100644 index 0000000..3ad24b3 --- /dev/null +++ b/ljcom/htdocs/developer/modelist.bml @@ -0,0 +1,37 @@ +1 +_info?>Protocol Mode List +body<= + + +LiveJournal protocol. Click one for more information, including request and response variables. +p?> + + + +{'name'} cmp $b->{'name'} } @vars) + { + $ret .= "

    {'name'}\">$v->{'name'}"; + $ret .= "
    " . $v->{'props'}->{'des'} . "\n"; + } + return $ret; + +_code?> + +p?> + + +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/moods.txt b/ljcom/htdocs/developer/moods.txt new file mode 100755 index 0000000..e98a406 --- /dev/null +++ b/ljcom/htdocs/developer/moods.txt @@ -0,0 +1,105 @@ +### +### server-supported moods vs. custom moods +### + +users will be able to use either server-supported moods or their +own custom moods. + +to use a server-supported mood, clients will use metadata property: + + current_moodid (numeric) + +to use a custom mood, clients will use metadata property: + + current_mood + +Or, use them both. Why? The current_moodid will indicte the picture to use, the current_mood will have the text to display. Clients may decide how they'd like to do it (using neither, one, or both) + +If only a current_moodid is given, the text will be from the server. + +### a list of all server-supported moods +### each mood has a parent (base) mood. at the top of the tree would be +### "positive" or "negative", but since those are boring, maybe "happy" and "sad" + +CREATE TABLE moods ( + moodid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + mood VARCHAR(40), + parentmood INT UNSIGNED NOT NULL DEFAULT '0' +); + +### I think the moods should be displayed with a picture with ALIGN=ABSMIDDLE, a space, +### and then the mood in text. + +### people will of course want to customize the images for the moods, so there +### will be mood themes + +CREATE TABLE moodthemes ( + moodthemeid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + ownerid INT UNSIGNED NOT NULL + name VARCHAR(50), + des VARCHAR(100), + is_public ENUM('Y', 'N') NOT NULL DEFAULT 'N' +); + +### users don't have to define pictures for every mood ... just certain base ones +### LiveJournal will find the picture by working up the tree until it finds one +### with a picture defined that's either gender neutral or matching gender + +CREATE TABLE moodthemedata ( + moodthemeid INT UNSIGNED NOT NULL, + KEY (moodthemeid), + moodid INT UNSIGNED NOT NULL, + gender ENUM('m', 'f', 'n') NOT NULL DEFAULT 'n', + UNIQUE (moodthemeid, moodid, gender), + picurl VARCHAR(100), + width TINYINT UNSIGNED NOT NULL, + height TINYINT UNSIGNED NOT NULL +); + +### how to get moods: +### + +extending the "login" protocol: + +if you send the request key "getmoods" with a value of the highest moodid you have +cached locally, the server will send you back the newer ones, if any: + + mood_count + mood_n_id -- mood ID number + mood_n_name -- mood text + +if you're lazy, you can send getmoods=0 to get all the moods everytime, or you can +send no getmoods key at all, and not have them returned, so it doesn't slow old +clients. + +#### some moods (these need to be put into a tree, showing which moods +#### are base moods of each other..... volunteers?) + +aggravated +angry +annoyed +anxious +bored +confused +depressed +exhausted +happy +lonely +pissed +sad +stressed +tired +sore +energetic +enraged +infuriated +jubilant +horny +hungry +discontent +thirsty +satisfied +thoughtful +..... + +tons more needed. if you send me some, don't just rip off another site's list... use your head and think of them independently. diff --git a/ljcom/htdocs/developer/protocol.bml b/ljcom/htdocs/developer/protocol.bml new file mode 100644 index 0000000..640f267 --- /dev/null +++ b/ljcom/htdocs/developer/protocol.bml @@ -0,0 +1,154 @@ +LiveJournal Protocol +body<= + + +do not need +to know any of this, and are probably better off not knowing it.   ;) +p?> + + + + + + +
      +
    1. Open a socket to www.livejournal.com on port 80 +
    2. Send an HTTP POST request, containing the request variables (mode, user, password, etc...) +
    3. Read the socket to get the response. The response is really easy to parse. +
    4. Close the socket. Do any approriate action based on the server's response. +
    + + + +
      + + +POST /interface/flat HTTP/1.0 +Host: www.livejournal.com +Content-type: application/x-www-form-urlencoded +Content-length: 34 + +mode=login&user=test&password=test + + +
    +As you can pretty easily see, the variables TO the webserver are encoded in the form var1=val1&var2=val2&..... Note +that you must quote all values or the values can interfere with the encoding form. For example, what if somebody's +password was "blah&=2+&something=yeah". It's an ugly password, sure, but somebody may have it. And if they do, it'll mess +up the pretty format of the encoding format. So, here are the rules on how to encode values: +
      +
    • Leave all values from a-z, A-Z, and 0-9 alone. These are fine. +
    • Convert spaces to a + sign. +
    • Convert everything else to %hh where hh is the hex representation of the character's ASCII value. +
    +So, for example, the phrase "I'm going to the mall" could encoded as "I%27m+going+to+the+mall". There should +be CGI libraries for all major languages which do this encoding for you. If not, it isn't that hard to do it yourself. +Content-length field, as in the example above. Then send a blank line, then the big long ugly string. +p?> +Note about line endings: Please note that the end of lines should be a carriage return (ASCII 13, 0x0D) and then a newline (ASCII 10, 0x0A). +In Perl, C/C++ or Java this is "\r\n". In Basic, this is Chr(13) & Chr(10). Sending just the newline may work too, but +it's generally better to send both. +p?> + + + + +HTTP/1.1 200 OK +Date: Sat, 23 Oct 1999 21:32:35 GMT +Server: Apache/1.3.4 (Unix) +Connection: close +Content-Type: text/plain + +name +Mr. Test Account +success +OK +message +Hello Test Account! + + + +The top stuff is headers from the HTTP request. There may be a lot of other stuff in there too. +First thing to do is make sure the first lines ends with "200 OK". If the first line +does not end with 200 OK, tell the user that an error occured on the server and that it's not their fault. +If you see 200 OK at the end, proceed with parsing the output. The format is as follows: +
      + +variable +value +someothervariable +someothervalue + +
    +The ordering of the variable/value pairs does not matter. As you read them in, read them into a hash +structure. (associative array, dictionary, collection... whatever it's called in your language. Just +a data structure that links one string variable key to another string variable value.) +p?> + + + + +

    +Protocol Mode Documentation +
    + + +very easy. Give the user a checkbox if they want to use a proxy or not, and if so, ask +the proxy host and proxy port. Now, if they selected to use a proxy, do not connect to +www.livejournal.com and port 80, but instead connect to their proxy host on whatever proxy +port they specified. The rest is basically the same, except for one difference. Instead of doing: +
      + +POST /interface/flat HTTP/1.0 + +
    +

    You would do... +

      + +POST http://www.livejournal.com/interface/flat HTTP/1.0 + +
    +

    That's it! That line tells the proxy what host it needs to connect to in order to make the real request. +The rest of the HTTP you should leave just as you did before. +This should be all you need to know to make a LiveJournal client. +p?> + + + + community, where all the client authors hang out. +p?> + +<=body +page?> diff --git a/ljcom/htdocs/developer/rawmode.bml b/ljcom/htdocs/developer/rawmode.bml new file mode 100644 index 0000000..9bfa023 --- /dev/null +++ b/ljcom/htdocs/developer/rawmode.bml @@ -0,0 +1,49 @@ +Raw Mode +body<= + + + + + + + + +=>, and the value. For example: +

      + +lastn_opt_items=>25 + +
    +That will tell the server that for the "lastn" page (the recent journal history) that you want 25 items to be displayed. +p?> +=> you do a <= and go to the next line. Then, type all the lines that you want in that variable and go to a new line and type <=VARIABLE. For example: +
      + +lastn_page<= +<HTML> +<BODY BGCOLOR=yellow> +Here's what I've been doing lately... <P> +%%events%% +<HR> +Back to my +<A HREF="http://www.myserver.com/"> + my home page +</A>. +</HTML> +<=lastn_page + +
    +The variable begins at the <HTML> line and ends with the </HTML> line. +p?> +%%events%% property. All things enclosed in double percent signs are properties that the server will fill in. All variables and properties are documented. See the list of variables for more information. + page. +p?> + +<=body +page?> \ No newline at end of file diff --git a/ljcom/htdocs/developer/styles.bml b/ljcom/htdocs/developer/styles.bml new file mode 100644 index 0000000..1953ff7 --- /dev/null +++ b/ljcom/htdocs/developer/styles.bml @@ -0,0 +1,51 @@ +Style System +body<= + + + + + + + + + + + + +variable is something that a style defines (and that a user can override) and is either: +
      +
    1. A page setup option, like how many items to show, how to sort something, or the format of dates and times. +
    2. Some HTML that the page contruction engine will use to make the page, with properties that it will fill in. +
    +A property is something that the server will generate (usually based on other variables) and prefill into your variables. Properties are mixed in variables like %%property%% and will be replaced by what they represent before being sent to the users' web-browsers. +p?> + + + +
  • Create Style +
  • Edit Style -- (for changing it later) + +p?> + + +support team. +p?> + + +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/time-problem.txt b/ljcom/htdocs/developer/time-problem.txt new file mode 100644 index 0000000..d7d527e --- /dev/null +++ b/ljcom/htdocs/developer/time-problem.txt @@ -0,0 +1,173 @@ +=============================== + LIVEJOURNAL'S TIME PROBLEM +=============================== + +Brad Fitzpatrick +brad@livejournal.com +August 10, 2000 + ++------+ +| Goal | ++------+ + +LiveJournal.com needs to handle time better, in particular to be aware of time +zones. There are too many problems that arise by neglecting them. If I knew of +an easy solution, I'd have implemented it already. This document is a plea for +help. All suggestions (however seemingly stupid) are likely to help, if only to +spark ideas for others. + +Confession: I know very little about the details of time zones, daylight +saving's time, etc... but I've read tons on the topic, enough to know there's +a lot to know. In other words, the solution is likely complex as well. + ++---------------+ +| Current Setup | ++---------------+ + +LiveJournal's servers, and the primary developers are all on the west coast of +the United States, in the PST/PDT (Pacific Standard/Daylight Time) timezone, +which is -0800 GMT (and sometimes -0700 GMT, in daylight savings time, I +believe). Here is how LiveJournal currently stores the dates/time for different +events: + + * journal creation date, update date --- PST/PDT local time. + + * comment post dates --- PST/PDT local time. + + * journal entries: + + 1) the "eventtime" is stored, whatever time you say it is wherever you're + at. you specify the year, month, day, hour and minute. no time zone + is recorded. + + 2) the "logtime" ... the time LiveJournal logs it to the database, in + PST/PDT local time. + ++-------------------------+ +| Description of problems | ++-------------------------+ + +Outlined below are the problems that LiveJournal currently faces: + + 1. Friends view ordering + 2. Incorrect user clocks + 3. Offline journaling/queueing + 4. Comments post times + +1. Friends view ordering +~~~~~~~~~~~~~~~~~~~~~~~~ + +The friends view is currently sorted according to the "logtime". In other +words, regardless of what time you said the journal event happened, the server +will sort them in the reverse order they were received. This has the advantages +that if you have friends scattered all over different timezones the journal +entries will still show in the order they actually happened. + +The problem occurs though near midnight ... you can have friends in one +timezone posting entries on one day interleaved with friends in another +timezone posting commments on the previous day. The resultant friends view +looks really messed up, going back and forth between days. + +This leads me to topic 2 ... + +2. Incorrect user clocks +~~~~~~~~~~~~~~~~~~~~~~~~ + +The friends view shows the time the user reported (the "eventtime"), even +though it's sorted by the "logtime". So if a friend in your same timezone +is posting comments near the same time as you, it's possible their post +that happened after you has an earlier displayed time, because their computer +clock is messed up. + +The worst is when their computer clock is months/years behind/ahead (very very +common because Windows users like to double-click their clock and use it as +a calendar ... then hit "OK" instead of "Cancel"). Then, the users complain +that "my journal entries are showing up on my friends page, but not on my +recent events view". This is because the recent events view (and the day +view, and the calendar) are all sorted by the "eventtime", the time the user +said the event happened. + +3. Offline journaling/queueing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many people have been asking for and patiently awaiting the "offline journaling" +feature ... being able to enter journal entries on your no-Internet laptop or +PDA and HotSync (or whatever) them later to LiveJournal's servers. + +Now, how should the friends view be formatted? Say the user submits 10 journal +entries ranging over a two week vacation. Should all 10 show up at once on +all of that user's friends' friends views? Because under the current scheme, +the "logtime" of all those entries would be seconds apart, and that's what the +friends view uses to sort. + +Should offline/queued entries not show up on friends lists? Should posts +with eventtimes more than 'n' days in the past not show up on friends lists? + +Both those solutions suck, because they're both ugly hacks that avoid fixing the +real problem -- adding timezone support to livejournal. + +4. Comment times +~~~~~~~~~~~~~~~~ +Blah. You know the problem. Keep reading ... time for solutions: + ++----------------+ +| Ideal Solution | ++----------------+ + +Ideally what would happen is that LiveJournal would store all posts with a +GMT time (that doesn't have daylight savings time) and the friends views +would sort by the GMT time of the eventtime ... so the user that went on +vacation and is dumping 10 entries into the system has them all intermixed +with her friends' old entries. Then, the friends view should display both +the remote browsing users's time and the time it was when the user posted the +item. + +So the problem turns into -- how do we convert the "eventtime" the user +submits into a GMT time? But ... let's assume the user's computer clock +is wrong, or we don't want to use it because it's not perfectly synchronized. +So then we need to pass along to LiveJournal a timezone field. + +So the problem is: + + --- I need a list of all timezones. What format are these in? + When does daylight savings time occur? Each country and states + within those countries have different rules. + + --- given a timezone code, how do I convert it to GMT? Are there + good packages already in existence (preferrably in Perl) to + do these conversions? I've looked around a lot, but haven't + found anything perfect. + + --- how do we deal with legacy clients? it'll be some time + before all clients start sending timezone info. + +Once the database is storing the eventtime in GMT and the timezone +code as well, then the style system needs to be updated to allow style +authors to show times in both the poster's time, and the journal owner +or remote user's time. + +But perhaps there's a better solution? I really don't know. I hate the +dependency on users' system clocks, and I hate the misordering of friends +items. + ++----------------------+ +| Good example problem | ++----------------------+ + +I have a journal I wrote from 1990 that I typed up, but I don't want +to post it, because it'll show up on all my friends' friends views. I'd +prefer it just went to my calendar, and I can make a single post to tell +my friends to go read it (and link to the day it starts). + +Sure, I could add a meta-data flag or something new on the protocol that +says, "don't add this to my friends view" but then people will start using +that for other purposes, and start asking for stupid stuff like, "can I have +it not show up on certain people's friends view?", not understanding the +point of it. It's just not clean. :/ + + +_____________________________________________________________________________ +Feedback requested: + brad@livejournal.com + + diff --git a/ljcom/htdocs/developer/varinfo.bml b/ljcom/htdocs/developer/varinfo.bml new file mode 100644 index 0000000..94d0cda --- /dev/null +++ b/ljcom/htdocs/developer/varinfo.bml @@ -0,0 +1,79 @@ +1 +_info?> +body<= + + variable. For more information on modifying this variable, see the information about the style system. +p?> + +{'name'} eq $v } @vars) + { + LJ::xlinkify(\$v->{'props'}->{'des'}); + + $ret .= "

    $v->{'name'}
    \n\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + # overrideable? + $ret .= "\n"; + + if (defined $v->{'props'}->{'type'}) + { + $ret .= "\n"; + } + if (defined $v->{'props'}->{'default'}) + { + $ret .= "\n"; + } + if (defined $v->{'props'}->{'props'}) + { + $ret .= "\n"; + } + + $ret .= "
    view types:"; + foreach (split (/\s*\,\s*/, $v->{'props'}->{'scope'})) + { + $ret .= "$_, "; + } + chop $ret; chop $ret; + $ret .= "
    description:$v->{'props'}->{'des'}
    can override:"; + if ($v->{'props'}->{'override'} eq "yes") { + $ret .= "Yes; users of this style may override this"; + } elsif ($v->{'props'}->{'override'} eq "only") { + $ret .= "Only; Only users of this style may override this, it cannot be defined in a style."; + } else { + $ret .= "No; users of the style cannot override this. It may only be defined in the style."; + } + $ret .= "
    variable type:$v->{'props'}->{'type'}
    default value:$v->{'props'}->{'default'}
    properties:\n"; + $ret .= "\n"; + foreach my $p (@{$v->{'props'}->{'props'}}) + { + LJ::xlinkify(\$p->{'props'}->{'des'}); + $ret .= "\n"; + $ret .= "\n"; + } + $ret .= "
    $p->{'name'}$p->{'props'}->{'des'} "; + if ($p->{'props'}->{'min'} > 0) + { + $ret .= "[required]"; + } + $ret .= "
    \n"; + } + return $ret; + +_code?> + + +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/varlist.bml b/ljcom/htdocs/developer/varlist.bml new file mode 100644 index 0000000..366ba2f --- /dev/null +++ b/ljcom/htdocs/developer/varlist.bml @@ -0,0 +1,34 @@ +1 +_info?>Variable List +body<= + +information about the style system, which includes information on how to define variables and values. +p?> + + + +{'name'} cmp $b->{'name'} } @vars) { + $ret .= "

  • {'name'}\">$v->{'name'}
  • \n"; + } + return $ret; + +_code?> + +p?> + + +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/versions.bml b/ljcom/htdocs/developer/versions.bml new file mode 100755 index 0000000..7a9b901 --- /dev/null +++ b/ljcom/htdocs/developer/versions.bml @@ -0,0 +1,40 @@ +LiveJournal Protocol Versions +body<= + +ver attribute; version 0 is implicit if the client does not +send the ver attribute. Currently there are two versions of the protocol, +and the Unicode-enabled server code supports both of them. +p?> + +
      +
    • Version 0
      +If a client does not send a ver key on a request, it assumed to support +protocol Version 0. In protocol Version 0, textual information transmitted from or to the +server is always assumed to be a stream of 8-bit bytes, not necessarily ASCII, but without +any guarantee that the non-ASCII bytes are presented in any particular encoding. +
    • Version 1
      +Version 1 differs from Version 0 only by imposing additional requirements on the text +transmitted through requests and responses; there aren't any changes in protocol modes. +The additional requirements are that in a Version 1 request, the client must transmit +all textual information as a stream of Unicode data encoded in UTF-8; the server must +respond to Version 1 requests with Version 1 responses; in such Version 1 responses, the server +must also transmit all textual information encoded in UTF-8; and the client must expect +that and handle such responses correctly. + +In other words, all information transmitted via protocol when Version 1 is used is always encoded +in UTF-8. UTF-8 is a representation of Unicode in a bytestream format compatible with ASCII. See +the Unicode Consortium website for more information on Unicode +and UTF-8.
    • +
    + +<=body +page?> diff --git a/ljcom/htdocs/developer/views.bml b/ljcom/htdocs/developer/views.bml new file mode 100644 index 0000000..0854ef3 --- /dev/null +++ b/ljcom/htdocs/developer/views.bml @@ -0,0 +1,51 @@ +1 +_info?>View Types +body<= + +view is just our terminology for a page type, or a mode. There are a lot of different ways to look at one's journal --- the default way is the "lastn" view, where it shows the last 'n' most recent events, in reverse order. However, there's also a calendar view, a day view when you click a day on the calendar, and more coming soon (a search page, and a search results page). Each and every view type is customizable through the style system, which you should read up on if you haven't already. +p?> +variables that affect them. +p?> + +{'name'}\">
    $vi->{'name'}: $vi->{'props'}->{'name'}
    \n\n"; + LJ::xlinkify(\$vi->{'props'}->{'des'}); + $ret .= $vi->{'props'}->{'des'}; + + $ret .= "
    {'props'}->{'url'}\">Example page.\n" + if (defined $vi->{props}->{url}); + + $ret .= "

    Variables affecting this view:

      \n"; + foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars) + { + next unless ($v->{'props'}->{'scope'} =~ /\b$vi->{'name'}\b/); + $ret .= "
    • {'name'}\">$v->{'name'}\n"; + } + + $ret .= "
    \n"; + + } + return $ret; + +_code?> + + +Back to Developer Area. + +<=body +page?> diff --git a/ljcom/htdocs/developer/winamp.txt b/ljcom/htdocs/developer/winamp.txt new file mode 100755 index 0000000..33742e1 --- /dev/null +++ b/ljcom/htdocs/developer/winamp.txt @@ -0,0 +1,42 @@ +// gets playing music from WinAmp, and returns +BOOL CPostOptionsDlg::GetPlayingMusic(CString &song) +{ + // is WinAMP open? + HWND hwndWinamp = ::FindWindow("Winamp v1.x",NULL); + if (hwndWinamp == NULL) return FALSE; + + // in WinAMP playing? + int ret = ::SendMessage(hwndWinamp, WM_USER, 0, 104); + if (ret != 1) return FALSE; + + // it is, let's find out what the title bar is: + char this_title[2048],*p; + ::GetWindowText(hwndWinamp,this_title,sizeof(this_title)); + p = this_title+strlen(this_title)-8; + while (p >= this_title) + { + if (!strnicmp(p,"- Winamp",8)) break; + p--; + } + if (p >= this_title) p--; + while (p >= this_title && *p == ' ') p--; + *++p=0; + + char *iter, *start; + start = this_title; + iter = start; + + // remove leading s/^\d+\. //; + int numhead = 0; + while (*iter) { + if (isdigit(*iter)) { iter++; numhead++; } + else break; + } + if (numhead && *iter=='.' && *(iter+1)==' ') { + start = iter+2; + } + + song = start; + return TRUE; +} + diff --git a/ljcom/htdocs/doc/find/index.bml b/ljcom/htdocs/doc/find/index.bml new file mode 100755 index 0000000..a7ae370 --- /dev/null +++ b/ljcom/htdocs/doc/find/index.bml @@ -0,0 +1,35 @@ +$LJ::SITEROOT/doc/find/?guide=docname + where docname is a document ID consisting only of ASCII letters, digits, + underscores, and hyphens. + }; + return; + } + + if ($guide =~ /[^\w\-]/) { + $title = "Error"; + $body = 'Illegal characters in identifier of requested guide.'; + return; + } + + my $location = "$LJ::SITEROOT/doc/html/$guide.html"; # temporary + return BML::redirect($location); + +_code?>1 +_info?> +body=> +page?> +link: htdocs/doc/find/index.bml + _c?> + diff --git a/ljcom/htdocs/doc/guide/index.bml b/ljcom/htdocs/doc/guide/index.bml new file mode 100644 index 0000000..dc4d1f0 --- /dev/null +++ b/ljcom/htdocs/doc/guide/index.bml @@ -0,0 +1,11 @@ +LiveJournal Guides +body<= +
    +
    So You Want to be a Support Volunteer
    +
    LiveJournal can always use more volunteers, and helping out in Support is a great way to learn more about how LiveJournal works. However, it is a time-consuming task that requires patience and professionalism. Don't expect to just jump in answering questions and get a bunch of points. For many volunteers it will take weeks to earn their first support point.
    +
    Mood Icons
    +
    You can indicate your mood in any of your journal entries. The mood you enter will normally be displayed with your entry, and if it's one of the server-supported moods, a matching picture (a mood icon) will usually appear too.
    +
    +<=body +page?> diff --git a/ljcom/htdocs/doc/guide/moodicons.bml b/ljcom/htdocs/doc/guide/moodicons.bml new file mode 100644 index 0000000..b8175db --- /dev/null +++ b/ljcom/htdocs/doc/guide/moodicons.bml @@ -0,0 +1,98 @@ +Mood Icons +body<= + + + + + +How mood icons are displayed h1?> +server-supported moods, a matching picture (a mood icon) will usually appear too. p?> + +full version of the Update Journal page. You can choose a server-supported mood by scrolling through the list. Alternatively, you can leave the selection set to “None, or other”; then your mood will be whatever you type in the box labelled “Other” (which you can leave empty if you don't wish to indicate your mood). Later, you can edit your mood selection, the same way you would edit any other part of your journal entry. p?> + + + +mood theme), and how to create your own if you want to. p?> + +Choosing a mood theme h1?> +LiveJournal Moods page. p?> +Modify Journal page. Make sure you're logged in under the correct user name, click “Proceed...”, and on the next page scroll down to “Mood Icons”. Select a mood icon set. After you click “Save Changes”, icons from the set you selected should appear on your Recent Entries page, your Day view, and your message boards, wherever one of the server-supported moods is indicated. Optionally, you can also force the same icons to appear on your Friends page, in place of the icons selected by your Friends. p?> + + +Modify Journal page, the same way you would select a public theme. However, personal themes aren't listed on the LiveJournal Moods page, so they can't be previewed. p?> +Creating mood icons h1?> + + + + +LiveJournal Moods page to see the relationships. p?> + + +LiveJournal Moods page). Later in this process, you'll need to know the ID of the mood to which each of your images should be assigned. p?> + +
      +
    • GIFs are a popular format, because they allow both transparency and animation.
    • +
    • The images can be any size, though large images are both visually obtrusive and time-consuming to load.
    • +
    • They don't all need to be the same size.
    • +
    • Remember that your images can be used on a variety of backgrounds! Don't assume that everyone has their text over white (or black). Or, you can decide that your icons will only work against a certain background, and design accordingly... but this will restrict your user base.
    • +
    • Remember that these images will be imported into the LiveJournal database by name, either by you or by someone else. Give descriptive names to your image files (the mood name will suffice: for example, ‘aggravated.gif’ for the “aggravated” mood).
    • + +
    + + +Turning your icons into a mood theme h1?> +paid LiveJournal accounts is the ability to make personal mood themes, special to your journal, by entering data about the images yourself. If you don't want your theme to be a public theme, or if you want to see how your theme will look before it becomes a public theme, then you'll need to create it yourself. p?> +FAQ #6 for more information). Also, you must know the dimensions (width and height, in pixels) of each image. p?> + +command console, where you can enter the commands to define your mood theme. (There is a reference, in case you need it, which describes all of the console commands, and explains how to escape double-quote and backslash characters.) p?> + + +
    +moodtheme_create name des
    +
    + + + +
    +name = the name of your new theme, which will be displayed in the lists from which users select.
    +des = a short description for your theme, which will be accessible through the console's moodtheme_list command.
    +
    + + +
    +moodtheme_create "Munch's Screamers" "You've seen 'distressed'. Now see the rest."
    +
    + +moodtheme_list command to find out the IDs of all the themes available to you.) p?> + +
    +moodtheme_setpic themeID moodID picURL width height
    +
    + + + +
    +themeID = the number given to you after you created the mood theme.
    + moodID = the number of a mood for which you created an icon; you can find these numbers in parentheses on the LiveJournal Moods page (example: 15 for “happy”).
    + +picURL = the full URL (Web address) of your mood icon.
    +width = width of the image, in pixels.
    +height = height of the image, in pixels.
    +
    + + +
    +moodtheme_setpic 180 15 http://www.yoursite.com/happy.gif 20 20
    +
    + + +Modify Journal page, and select the new theme as the mood icon set for your journal. p?> + +<=body +page?> diff --git a/ljcom/htdocs/doc/guide/support.bml b/ljcom/htdocs/doc/guide/support.bml new file mode 100644 index 0000000..38c48a9 --- /dev/null +++ b/ljcom/htdocs/doc/guide/support.bml @@ -0,0 +1,1676 @@ +So You Want to be a Support Volunteer +body<= + + + + + + + + +

    LiveJournal can always use more volunteers, and helping out in +Support is a great way to learn more about how LiveJournal works. +However, it is a time-consuming task that requires patience and +professionalism. Don't expect to just jump in answering questions and +get a bunch of points. For many volunteers it will take weeks to earn +their first support point.

    + +

    However, if you're reading this, you're already off to a good start. +The information in this document is designed to help you understand +Support and get your answers approved. Some +other good resources are the following communities:

    + +
      + +
    • - the main Support community where policies are announced. New +volunteers cannot join, but they can and should friend +it. Reading lj_support is required for all support volunteers.
    • + +
    • - the community for new Support volunteers. Volunteers are encouraged to +join +and post questions here. The guidelines for HelpScreening are linked to +from its userinfo. Both of the above communities have particularly +helpful posts saved as memories. Reading through the memories is a very +good way to learn more.
    • + +
    + +

    Please note that there is a lot of material you can read, and +reading it will almost surely help you do better in Support. But +don't feel as though you need to read through everything right now. +It's generally best to take things at your own pace. Start with the +first three sections of this guide, and then read the rest as you feel +ready to learn more.

    + +

    This guide is designed to answer most of the common questions asked +by Support volunteers at all different experience levels. While reading +the sections for more experienced volunteers is fine, there is no reason +to feel you should. This is a very long document, and is meant to be +read in small pieces as you progress in Support.

    + + + +

    There are many Support policies, but only a few that are really +important to keep in mind when you're just starting out. For a more +detailed listing of support policies, check out the Support communities +and later parts of this Guide.

    + +

    Never contact users off of the Support board. If there is a reason +why it is important to do so, then someone who is authorized to do so +will. We do not want users to feel harassed or stalked because of their +Support requests.

    + +

    Treat people with respect. This goes for both the people who submit +requests and your fellow volunteers. Do not make fun of people who +submit Support requests. If you have a question to ask, ask it politely. +If someone offends you, contact someone about it privately rather than +starting a flamewar. Most problems are caused by misunderstandings that +can be sorted out if everyone just discusses the issue calmly. If you +notice mistakes in Support answers, email support@livejournal.com about +it and it will be forwarded to the appropriate person or people.

    + +

    Do not copy other volunteers' answers. You can use other people's +answers as a guide to what content yours should include, but write your +own answers. If you need help with the wording, ask in +HelpScreening.

    + +

    If a request contains any private information or reports a security +bug, do not discuss the request with anyone. As you become more +experienced with Support, you will learn how to handle these requests, +but until you do, it's simplest to just keep quiet about them. +Volunteers who are found discussing private information on the board or +using it for their own purposes may be banned from Support.

    + +
    + +

    Users submit Support requests that are then opened on the board as +green requests. They remain green until an answer is approved, and then +they turn yellow. If they re-open because the user needs more help, they +will turn green again until re-answered and say "answered still needs +help". When a request is closed it will be moved to the closed section +and turn a pinkish red. Eventually it will disappear from the board +entirely, but still be findable by the specific URL to the request. The +exact colors may vary from browser to browser.

    + +

    As a new Support volunteer your answers will be screened. This means that someone with more +experience in Support will read them over and only allow them to be sent +to the users if they meet Support's guidelines. There are several +Support guidelines both for the board as a whole and individual +categories. These will be explained in more depth later.

    + +

    There are many forms of information in Support requests that you will +not be able to see at first. The most notable are other volunteers' +screened responses. This means that sometimes you will answer a question +that already has an acceptable answer in it. The earlier answer will +appear on the request later, when an experienced volunteer approves it. +Don't let this discourage you. As a new volunteer you should focus on +learning as much as you can. In time you will be able to see these +responses.

    + +

    Sometimes instead of an answer, a volunteer will make a comment. +Comments are used primarily to request more information. Sometimes they +are used to point out additional information that was left out of a +previous answer, or to follow up on a request. Comments can never earn +Support points.

    + +

    If you see a comment in a request asking for more information, you +should not attempt to answer the request until the user has replied +back. While sometimes an answer will be approved before then, especially +if the user seems unwilling to reply back, most of the time attempting +to answer such questions will just be a waste of effort.

    + +

    If you see a request that needs a comment, you can leave a screened +response intended to go through as a comment to the user. Support +volunteers can approve screened responses as comments, and will do so +when appropriate.

    + +

    If it's an unusual request and you have information that shouldn't go +through to the user, but may be helpful to other volunteers, you can +write it in a screened response with the words INTERNAL COMMENT +all in capitals at the top. These internal comments can also never earn +points, but they do help to get requests resolved. Internal comments +should only be used if you have good reason to believe that the +information you can provide is not common knowledge. In most cases +experienced Support volunteers will know enough to handle requests.

    + +

    After a request has been answered, the user may reply back with more +questions. These further questions must then be answered, but not +necessarily by the person who answered the first question. It's a good +idea to check back on Support requests you have answered both to see +what sort of answer was approved and to check for follow-up questions. +Once the user is fully helped, either the user will close the request or +it will sit until one of the Support closers comes to close it.

    + +

    Requests, regardless of who closes them, can be closed with credit to +any approved answer in the request or without credit. Support closers +will attempt to assign credit fairly, but only one person can receive +credit for each request. The users may assign points fairly, but they +also may close without credit. This is a natural part of Support. Not +all requests are expected to yield points for anyone.

    + +

    Most requests will take about a week to close. Many will take longer +if they involve asking users for clarification, or answering new +problems. Closed requests can also be re-opened by users or by +administrators. This does not happen often, but when it does the points +will be revoked. They may then be re-assigned when the request closes +again.

    + +

    The value of a request is based upon the time the answer was +submitted. The value of that answer, if the request is closed with +credit to it, will be the amount showing at the time the answer was +submitted, regardless of when it is approved or closed. Most requests +are worth one or two points, and the maximum they can be worth is ten +points.

    + +

    Once you have earned points, they will show on your full user info +page between the number of journal entries and the number of comments. +You can also see your point total and how it compares to that of every +volunteer who has earned Support points at the High Scores +page. On that page there will be little numbers in red or green next to +many of the scores. This indicates how much their rank has changed since +the last time it was calculated. Points and rank are updated more or +less instantaneously. Changes in rank are usually updated weekly, but +sometimes problems happen and changes in rank will freeze and not be +updated for a while.

    + +

    You can find the specific requests which earned you points in public +categories through use of the Support Office. This is not an official +LiveJournal tool, but is very useful for Support volunteers. In addition +to finding your approved answers, you can also search for screened +responses, comments, and internal comments. Support Office is located at +http://www.supportoffice.org/.

    + + + +

    Support is divided into categories, each of which is run by one or +more category admins who can set policies for +that category. Thus there are rules that apply in all public categories +and rules that are category-specific. This Guide focuses on overall +rules. The best way to learn category-specific rules is through +'s memories +and the communities for the specific +categories.

    + +

    The first rule of Support is that any policy might have an exception +if a good enough reason comes up. Policies are there to improve how +Support works, not bind us in cases where they don't fit. If you believe +that an exception is needed in a specific case, you should contact the +relevant category admins or email +support@livejournal.com to ask about it. Sometimes exceptions will be +made.

    + +

    The most important rules of Support were presented in the Basic Support Rules section. This section +goes into detail on more policies. If there is ever a conflict between +this guide and information given in official Support communities, then +the communities take precedence. This guide cannot be constantly +updated, whereas the communities can deal with issues as they occur.

    + +

    There are some exceptions to the rules in the short rules section. +Answer copying is allowed with the permission of the person who wrote +the original answer, but it is highly discouraged. Answer copying makes +it harder to learn how to do Support, and thus is generally used by +those who already have enough experience to not need more work on answer +writing. Reusing your own answers is perfectly acceptable so long as you +modify them to fit the specific request you are answering.

    + +

    Contacting users off the board is rarely allowed, but if a user +writes a thank you post in their journal, you may comment politely to +it. If the user friends you, you may then comment to them or friend them +if you wish.

    + +

    Support strives to be courteous, professional, and helpful. While +some rules work toward more than one goal at a time, the rules divide up +fairly well based on those concepts. This section also explores what +those ideas mean.

    + + + +

    Courtesy is fairly simple. No matter what you think of a user's +request, answer it with the respect you'd want if you had asked it. If +you can't do that, do not touch the request in any way. You are always +free to ignore requests that you dislike. Even in discussions outside +the Support center, don't ridicule questions.

    + +

    Be courteous toward other volunteers. Learn from answers by other +volunteers (when you can tell that they're right), but don't just copy +them word for word. If you feel compelled to complain about a common +mistake, criticize the mistake, not the individuals who made it. Make +corrections privately. Don't ridicule answers.

    + +

    Specific rules:

    + +
    + + + +

    Professionalism gives people a good impression of both LiveJournal +and the Support team. You are expected to act professionally in all +Support-related contexts. If you are commenting in an official community +and represent yourself as a Support volunteer, then your comment should +be professional and courteous. However, when you are outside Support +contexts, your actions may be whatever you wish.

    + +

    Specific rules:

    + +
      + +
    • Don't use an obscene user picture or username. +LiveJournal can have members as young as thirteen, and as such the +Support board should remain PG-13. In any case, an answer from someone +with an offensive name or picture does not inspire confidence.
    • + +
    • Do not use the words we or us. +Support volunteers are rarely allowed to speak officially on behalf of +LiveJournal. We do not want to give the impression that we are doing so. +We do represent LiveJournal in the sense that we are what users see when +they come to Support for help, but we do not make official decisions. +Support volunteers do not control LiveJournal policies and should not +give the impression that they can.
    • + +
    • Do not point requesters to other places when they have +support problems. If they have a suggestion, point them to the +Suggestions +FAQ. If it is a suggestion that has been shot down many times, you +can simply tell them that it has been suggested before and the reasons +why it will not be implemented. If it is currently in Zilla or has received positive feedback, then say +that the idea has been considered before and may be implemented at some +point in the future. Do not point them to the Zilla item. (The one +exception to this: If a user is having problems with text messaging, it +is appropriate to point them to the "lj_textmessage" community.)
    • + +
    • Do not give support for things outside of the domain of +LiveJournal. We can't support everything. If something falls +outside the domain of LiveJournal, inform the user and try to give them +a pointer of where to go. For example, with complex HTML, suggest they +do a web search with their favorite search engine for HTML +tutorial or similar phrases.
    • + +
    • If you have a choice of references, always pick the most +official one. Journals intended for the public such as news are +ideal. If there is none, then go with an official LiveJournal community. +If there is none, try for a LiveJournal or goathack site with a disclaimer. If not, then an outside site. Try to +avoid linking to Zilla, lj_support, helpscreening, and other sites +intended to help volunteers/staff. When including links to LiveJournal +posts use the regular URL, not the URL with "?mode=reply". You want to +encourage users to read comments in the post rather than to +comment.
    • + +
    • Whenever you link to a page that is not an official +LiveJournal page, you should include a disclaimer that it is not +affiliated with LiveJournal and LiveJournal cannot be held responsible +for its content. This is useful for many reasons. If the page +changes, it makes it less likely users will complain. If the page has +ads, it's important for users to know that those ads have no connection +with LiveJournal and LiveJournal does not benefit from them in any +way.
    • + +
    • Be sure of your answer. Don't write something like, +Well, I'm not sure, but when my friend had a problem like this, blah +blah blah worked... Professional answers give the user an +answer--ideally, the correct answer. The exception to this is when the +request is very vague but you think you know what the user is asking +about. Then you can say something like, If you mean FOO, then you +should do BAR. If you had something else in mind, +please reply back so someone can help you further. Asking for more +information or clarification belongs in comments, which can be useful in +these situations. However, it is better to answer the question whenever +possible than to comment for more information. So, if a simple if FOO +then BAR might resolve it, that should be tried.
    • + +
    • Slang and idioms should be avoided in all Support +answers. It not only looks unprofessional, but not all users +will understand such expressions. Support helps people around the world, +including non-native English speakers. Slang and idioms will often +confuse such users.
    • + +
    • In general, avoid sentence fragments. All the +standard rules of good writing apply to Support answers. Nobody is +likely to mind if you split an infinitive here or there or end a +sentence with a preposition, but try to write clearly and +concisely.
    • + +
    • Avoid phrases like Hope this helps. It looks +unprofessional and some users will read it as a sign of +uncertainty.
    • + +
    • Avoid emoticons. It looks unprofessional and may +confuse some users.
    • + +
    • Don't sign your answers or use a greeting to begin +them. Greetings and signatures are reserved for answers that +are officially from LiveJournal, to make the distinction clearer. It is +also unnecessary as the public categories have answers that go out with +your username and user picture.
    • + +
    • Put your entire answer into one reply. We don't +want to flood people with e-mails in reply to their support requests. If +your answer has already been sent to the user and you left something out +or made a mistake, then you need to post a follow-up, but try to prevent +that from happening. If your incorrect answer is still a Screened +Response, no harm has been done; rewrite it completely and correctly +rather than submitting a follow-up. If your answer was incorrect or +incomplete, approved, and you do not have supporthelp privs, then submit +a correction and email support@livejournal.com with a link to the +request and a brief note that you were approved with a mistake that you +need to correct. Don't worry that you made a mistake; no one expects you +to be perfect. Just do your best to fix it.
    • + +
    • Don't link back to the request itself. The link is +added automatically to the response sent by e-mail.
    • + +
    + + + +

    Helpfulness involves actually giving the user an answer they can use +in response to their request. The entire point of Support is to help +people. We want to do it kindly and without offense, but we +must make sure that we help them.

    + +

    Specific rules:

    + +
    + + + +

    The main journal for Support is . +Every Support volunteer should read it. Official policies are announced +there and relevant LiveJournal news is relayed there. Sometimes the +direction that LiveJournal Support should take is discussed there. Any +volunteer may read it, but only experienced volunteers are granted +posting access. Posting access and membership is given when a volunteer +earns supporthelp priv in any category of +Support.

    + +

    The next community to consider is . +This community is open to all volunteers. It is used for asking +Support-related questions, and for supporthelps to give tips to less +experienced volunteers.

    + +

    All of the public Support categories have communities. They are: +, +, +, +, +, +, +, +, and +. +Information about them can be found on their respective userinfo +pages.

    + +

    Other Support Communities:

    + +
      + +
    • is the administrative community. Only category admins and LiveJournal +staff have membership there. While any volunteer may watch it, and +sometimes posts are made publicly, there is generally little there for +non-members to see.
    • + +
    • is the community for interim privs. When you earn +interim privs, you will be added; until then it +is not worth watching.
    • + +
    • is an unofficial community where many Support volunteers post about +their Support experience, amusing Support-related events, or +particularly impressive requests.
    • + +
    • is an official community for the discussion of tutorials for inclusion +in . +While it does not directly affect work on the Support Board, it is +closely tied to Support and considered a part of the Support +system.
    • + +
    • is a journal where the addition and removal of Support privs is announced. No one is required to watch it, +but many volunteers wish to know about priv changes.
    • + +
    • is an unofficial community with tutorials about writing Support answers +and understanding various aspects of LiveJournal that frequently come up +in Support.
    • + +
    + +

    Other Helpful Communities:

    + +

    All of these are helpful in their own way, but most volunteers will +not want to watch them all. You should see which you find to be most +useful for you.

    + +
      + +
    • is for the discussion of LiveJournal business matters.
    • + +
    • is where changes to the LiveJournal code are announced.
    • + +
    • is where development changes are discussed.
    • + +
    • is where outages and network problems are announced.
    • + +
    • is for discussing the FAQs and guides.
    • + +
    • is where important LiveJournal news is announced.
    • + +
    • where news related to paid user accounts is announced.
    • + +
    + + + +

    Support takes patience and dedication and new volunteers should not +expect to get approvals or points quickly. How long it takes will depend +on what skills you enter Support with, what you read, and how much +effort you put into it. Keep in mind that only approved answers can earn +points and that not every request closes with credit. For more details +about how the Support system works check over the section about it.

    + +

    One common reason for not getting approved is not being first. As a +new volunteer, you can't see other answers. When an answer gets +approved, compare the timestamp. If it is earlier than yours, then it +was already there when you wrote your answer.

    + +

    Another common reason for new volunteers not being approved is that +their writing style doesn't meet Support standards. Support requires a +very professional appearance. Things like emoticons (e.g. :)), Hope +this helps., slang, poor spelling, and incomplete sentences can keep +an accurate answer from being approved.

    + +

    Answers should always be in one complete screened response. If you +notice you made a mistake, resubmit a new complete answer without the +mistake. Do not submit a correction. Since your answer hasn't been +approved yet, the corrected version can be sent to the user. Almost +every volunteer will mess up sometimes and re-submit. There is no reason +to worry about resubmissions. However, if you find you are constantly +resubmitting answers, then you should proofread more carefully before +you answer. You may wish to write your answers in a text editor so that +you can see them more clearly.

    + +

    Another possibility is that the answer required more information. +There are three issues that must be considered in every request. First, +the user's explicit question must be addressed. Second, any +misconceptions that the user has must be addressed. An example of this +is a user asking for a source code to start a journal. The user probably +means they want an invitation code, so there should be a brief +explanation of what each code is and how each is used. Finally, the +answer must address any other issues the user needs to be informed of, +but wouldn't have known enough to ask about. One example of this is a +user asking an unrelated question, but the account is not validated. +Validation must always be addressed when it comes up as not being +validated will lead to several problems for the user.

    + +

    For more information on why your answers weren't approved you can ask +in . Please read the community's guidelines. +Remember, if no answer has been approved yet, then wait to find out what +the approved answer is. Sometimes no one qualified to handle the request +has gotten to it yet. If no answer is approved yet, your answer may be +fine.

    + + + +

    There are several things you can do to improve at Support. By reading +this, you've already started. Another is to go through the memories for +various Support communities. A good way to learn +what to include in your answers is to look over approved answers. Don't +copy them, but see how they're written and what sort of information they +contain.

    + +

    While answering requests, read them carefully. What things might the +user mean? If the user may be referring to multiple things, address them +all. If the user asks multiple questions, answer them all.

    + +

    Read over your answer carefully. Is it well-written? Is it spaced +nicely? Does it include references when needed? Did you mention every +FAQ you used?

    + +

    Think about what the user knows and what the user needs to know. Try +to make sure your answer provides all the information the user will need +to resolve the issue. Also make sure you address any misconceptions the +user has and alternate methods of accomplishing the goal.

    + +

    Learn the FAQs and check them every so often, since they do change. +An answer that doesn't include a relevant FAQ will almost never be +approved. Part of being able to answer most Support requests is knowing +where the relevant information is.

    + +

    Look over the information provided with the request. Is this a logged +in user? Is the account validated? Is the user free or paid? These +things may have an effect on the answer.

    + +

    Try to answer questions and check back to see what was approved. How +was it different from your answer? If it was your answer, then great. +Look at requests you can't answer, and check back on them to see how +they do get answered. Ask questions in HelpScreening and get a review. After you have learned the basics of a +category, you may wish to inquire about getting a mentor.

    + + + +

    Reviews are a wonderful way of learning how to improve your answers +in Support. They involve an experienced volunteer looking over many +requests you have recently tried to answer in a category and giving you +feedback. It allows Support volunteers to get feedback that is more +personalized to their needs, and it helps the category admins keep track +of your progress.

    + +

    Since Support is divided up into different categories, each run by +its own category admin(s), reviews are generally done for one category +at a time. To get a review, contact the admin(s) of the category you are +interested in. They may not review you themselves, but they will make +sure someone competent does. If you do not know the admin(s) for a +category you are interested in, submit the request to +support@livejournal.com and ask them to forward it to the relevant +admins.

    + +

    There are four basic methods used for reviewing. The first is that +you collect requests to be reviewed. The second is that you collect +requests to be reviewed that are then supplemented by the category +admin. The third is that you request a review and the category admin +collects all of the information. The fourth is that you are given +example requests to answer, which will then be reviewed. In any of these +cases, you may also be asked to comment on what you did and why and +anything you learned from the request. If you do not know which type of +review a category uses, ask an admin.

    + +

    To gather requests for a review that uses requests from the board, go +to the Support board and filter to You Replied and whatever +category you want a review in. Do not remove any requests from this +filter unless you are specifically instructed to do so.

    + +

    Then write an email with the URLs to each request in that filter. +Include your username and whether you have any privs in that category, +and if so, which privs. If you have any specific questions about some of +the requests, include those as well, so that the reviewer can address +them.

    + +

    How helpful a review is varies. Some volunteers find them to be the +best way to learn, while others do fine on their own. Sometimes a review +happens at just the right time to help a volunteer improve further, +while other reviews for the same volunteer don't help much. New +volunteers should generally get a review in any category they've been +working in to a moderate extent for two weeks or more. Then get another +after about three more weeks, longer if you spend a significant amount +of time away from Support during that time. Volunteers with all of the +interim privs should generally be reviewed more +often. These are just rules of thumb and will vary from person to person +and category to category. Always feel free to ask a category admin about +what they think is best for you.

    + +

    When you get your review, you should expect comments on how your +answers could be improved. But do not expect every request you submitted +to be mentioned in the review. Often several requests have the same +problem or were all done well. In these cases, there is little to say, +and they will often simply be removed. If a large number of your +requests are removed, you either likely do a lot of similar request +types or are doing very well.

    + +

    A review can take a while to get done, depending on the size of the +review, the time of year (around holidays many volunteers may be away or +busy), and the category. If you haven't received a response to your +review after a week, send an email asking if it was received and whether +everything is okay. Sometimes emails get lost or misplaced, and we don't +want any volunteers being ignored through such accidents. If another +week passes, send another reminder. The admin may need to get in touch +with the volunteer doing the review to make sure no problems came +up.

    + +

    Your review or its summary will usually be shared with the +supporthelp privs for that category. This is to help the supporthelps to +better teach you about Support, and because in most categories the +supporthelp privs help to decide when new volunteers are ready for +different levels of privs.

    + +

    If for any reason the requested review format causes problems for +you, discuss it with the admins for the categories you are interested +in. These formats tend to be easiest and work best for most volunteers, +but special arrangements can be worked out at times to meet a particular +volunteer's needs.

    + + + +

    Some categories have mentoring programs. Having a mentor will give +you someone to go to with questions. Your mentor will also likely review +you, and may bring up issues for you to try to work on. You do not need +a mentor to improve at Support, but some volunteers will feel more +comfortable having someone specific they know they can go to for advice +and answers.

    + +

    Some categories may have a waiting list for mentors. Some categories +may limit mentoring to those who have already earned at least I1. You +should check with the category admin(s) for specific and current +information. As always, if you don't know who they are, you can have +support@livejournal.com forward the request for you.

    + +
    + +

    There are many privileges or privs associated with Support. A +priv is what gives someone permission to take a particular action on a +request. Most privs are publicly viewable at http://www.livejournal.com/admin/priv/.

    + +

    Support volunteers will also refer to someone with the priv as a +priv. So, the group of people with any of the interim Support privileges +is collectively referred to as the interim privs.

    + +

    All Support privileges are given on a per category basis. Some people +will have privileges in all categories, but they either are in +administrative positions or have earned privs in each category.

    + +

    There are four interim privs. They are:

    + +
      + +
    • supportviewscreened - the ability to see other screened responses in requests
    • + +
    • supportmakeinternal - the ability to make internal comments in requests
    • + +
    • supportviewinternal - the ability to see internal comments in requests
    • + +
    • supportmovetouch - the ability to change the category of a request +and insert a request into or remove a request from the queue
    • + +
    + +

    +Interim privs will be explained more fully in the sections on I1s and I2s. They stand for interim +level one and interim level two. Level one consists of having +supportviewscreened and supportmakeinternal. Level two consists of +having all of the interim privs.

    + +

    Supporthelp is the priv that allows a volunteer to approve screened +responses as either answers or comments. It also allows the volunteer to +submit an answer or comment that does not need to be approved, but this +is rarely used. It is generally reserved for times when the board is +flooded with requests, such as during technical difficulties, to quickly +answer numerous requests on the same subject. Another function of the +supporthelp priv is the ability to change the summary of a request. The +summary is the text that appears on the Support board describing the +request. Supporthelps generally help to teach newer volunteers how to +answer in Support.

    + +

    Supportclose allows a volunteer to close requests and assign points. +This priv is generally reserved for Support administrators.

    + +

    There are also admin privs that allow someone to give privs to other +people.

    + + + +

    The following are the public Support categories: clients, +communities, embedding, general/unknown, syndication, user picture +icons, and web user interface.

    + +

    The following are the private Support categories: abuse, account +payments, feedback, press, privacy, support@, and webmaster.

    + +

    The public categories are best understood by looking through relevant +communities and Support community memories.

    + +

    The communities for each category are listed below and an explanation +of who should read the community and how it should be used can be found +in the userinfo of each community.

    + +
      + +
    • Clients:
    • + +
    • Communities:
    • + +
    • Embedding:
    • + +
    • General/Unknown:
    • + +
    • Style Systems:
    • + +
    • Syndication:
    • + +
    • User Picture Icons:
    • + +
    • Web User Interface: and
    • + +
    + +

    +There is also which supports the journal. + is affiliated with Support, but not a part of +the Support Board itself.

    + +

    An explanation of the private categories and how they affect Support +volunteers is below.

    + +
      + +
    • Abuse - this is the team that handles reported violations +of the Terms of +Service. All requests reporting specific journals for suspected +abuse such as harassment or copyright violations, reporting "hacked" +journals, asking questions about suspended accounts, asking legal +questions, or asking about the Terms of Service should be moved to the +abuse category. Requests from the parents of minors should also +generally be moved to Abuse as they need more delicate handling. If you +see an abuse request in Support and do not have the ability to move it, +check the userinfo for . +Contact people who are members of the community and one of them will +move it for you, if it is deemed to be abuse-related.
    • + +
    • Account Payments - this category handles problems with +account payments. If a user didn't have a payment go through, or had a +problem with how their payment was processed, it is handled by Accounts. +Unless the request contains personal information, such as a credit card +number, it can generally sit on the board until someone with the ability +to move requests sees it. If it does contain personal information, +contact a supporthelp priv to move it. You can start by contacting +category admins, as they generally are around and have LiveJournal email +addresses that are easy to find. You can use the members list for +as a guide for who can be contacted, but do not email bradfitz about a +routine Support issue such as a request needing to be moved.
    • + +
    • Feedback - is not currently being used, but might be used +at some point to allow people to provide feedback to LiveJournal.
    • + +
    • Press - handles requests from the press for information. If +someone wants an interview or quotes from LiveJournal staff members, it +should be moved to Press. These requests can generally sit on the public +board until a volunteer capable of moving them sees them.
    • + +
    • Privacy - handles questions about the LiveJournal privacy +policy or concerns about LiveJournal sending out spam. These are rarely +urgent and can sit until moved.
    • + +
    • Support@ - handles junk requests such as duplicates and +nonsense. For those who can move requests, duplicates should contain an +internal comment linking to the other request by the user. These +requests can sit until moved by someone with the privs to do so. +Support@ also handles forwarding private requests when the category is +unclear. If you have the ability to move requests and know a request +should be private, but don't know where it should go, move it to +support@ with an internal comment asking them to forward it. Support@ +also handles requests that would be on the general board, except they +contain personal information that must be kept private. These requests +need to be moved quickly, and if you see one, but do not have the privs +to move the request, contact a supporthelp as explained in accounts +category. Finally, support@ handles requests about Support itself. If +you need to report a complaint or problem with a Support volunteer or +the Support system, you can open a request in support@. You can also use +support@ to ask private questions about Support that you don't know +where to ask. Support@ should be contacted if you wish to leave Support +and have your Support privs removed.
    • + +
    • Webmaster - requests about business issues, security holes, +or the death of a LiveJournal user. Security holes need to be moved off +the public board immediately; see the Accounts category for details on +how this is done.
    • + +
    + +

    +Special Note: Sometimes we get reports that a +LiveJournal user may be committing suicide. While there is only so much +that LiveJournal can do in such cases, they need to be handled +immediately. Sometimes the authorities can be contacted. Abuse can +handle such issues. The most important thing to do in such cases is to +make sure it is brought to the attention of the people who can deal with +it. Please, do not be shy about emailing Abuse volunteers or staff. We +would rather more people be contacted than necessary than that the +request be overlooked.

    + +

    Some requests are unclear about whether they should be public or +private. In these cases, always err on the side of privacy. A request +can easily be moved back to the public board. If the request has already +been moved to a private category and sent back, everyone with the +ability to move requests will be able to see that.

    + +

    Also, with requests that should be private, it is even more important +that you respect the privacy of the requesters, and you are expected not +to discuss such requests at all. Do not post about them, even to get +them moved, as this just causes more people to see them. Ideally, all +private requests would go only to private categories, but when they +don't, we expect volunteers to act respectfully toward the +requesters.

    + +

    For more information on each category you can see this +post.

    + + + +

    After a volunteer has been helping in Support for a while they may be +given I1, the first interim priv level, in one or more of the Support +categories. I1 conveys two privileges, supportviewscreened and +supportmakeinternal.

    + +

    I1 makes Support a bit easier by allowing a volunteer to focus on +requests that have not yet been adequately answered. It also includes +some responsibilities.

    + +

    I1s are expected to keep screened responses confidential. They can +see them for their own benefit, so they can concentrate their efforts. +They should not be discussing these screened responses. If they have +questions about them, they can either email the category admin(s) for +the category or bring them up in reviews. If an I1 is part of a +mentoring program, then they can also ask their mentor.

    + +

    I1s are expected to understand that not all screened responses are +good models. Try not to pick up bad habits from other volunteers. If a +screened response isn't approved, there may be a good reason for that. +Some volunteers will find that other screened responses offer them a +better perspective on how ambiguous requests may be interpreted or what +information might be useful to include.

    + +

    I1s are expected to use internal comments wisely. While unprivved +volunteers have the ability to add internal comments as screened +responses, these internal comments will be labeled as such. They are +more eye-catching, and volunteers expect them to be important. Interim +privs should not be commenting about shortcomings in other screened +responses, what should be approved, or what needs to be in an approved +answer. But internal comments can be used to share information on +unusual requests.

    + +

    The general guideline for internal comments is only post them if +there is something beyond the routine that you feel other volunteers +need to know about. Some good examples of internal comment use would be +linking to related requests by the same user, or linking to Zilla items +that relate to the request. Another good use would be linking to a +suggestion that is related to the request. However, don't link to +standard well-known resources, since most volunteers will already be +aware of them and it will just add clutter.

    + +

    Internal comments are expected to be professional. The general +guideline is that every time you leave an internal comment, you should +be prepared for what you would tell the user if somehow it became +visible. If you would not be able to handle that situation, you may want +to re-think your comment.

    + +

    Internal comments are not to be used for irrelevant chatter or to +talk about a user behind his/her back. When you reach I2, you may see +some internal comments that are humorous. Many of the internal actions +require some text be left, as such, privs are allowed to leave off-topic +comments in these cases, but they still must not be offensive.

    + +

    When you earn your first I1 priv, you will be given access to . +This community is a good place to ask questions specific to using +interim privs.

    + +
    + +

    By the time you are given interim level two in a category, you +probably have a great deal of Support experience and a good feel for how +Support is done. Many volunteers will find themselves at I2 level for +longer than they were unprivved or I1. This will vary from person to +person, but it's a common occurrence. Try not to let it frustrate you. +The step to supporthelp is a difficult one as mistakes made as a +supporthelp can harm the users. As such, it is given out very carefully. +We prefer to err on the side of taking longer.

    + +

    The primary responsibilities of an I2 are to keep the screened +responses and internal comments confidential, to move requests to their +proper categories, and to refrain from trying to train new volunteers. +Training is left to supporthelps, to lessen the chance of people being +given inaccurate information. While I2s tend to be very advanced and +knowledgeable volunteers, they are not quite ready to take on +training.

    + +

    Since I2s can change the category of requests and touch requests, +they are expected to do so when appropriate. If a request is in the +wrong category, the category should be changed first. Always check the +category of a request before doing anything else with the request. +Please read over the section on the purpose of each private category. It is very important that requests +that should be in private categories get moved into them as quickly as +possible. Remember, when in doubt, move the request to support@.

    + +

    To change the category of a request, select "Internal Comment/Action" +and the new category from the drop down, and include some text. This can +be as little as . if the change is obvious or a brief note about +the request if you have anything to say, and then submit.

    + +

    Touching a request will re-green it and mark it as still needs +help. To touch a request, select "Internal Comment/Action" and check +the box to touch a request. Then include some text and submit.

    + +

    Since I2s can see other internal comments, they can see whether +something has been pointed out yet or not. As such, they can use +internal comments a bit more broadly. Useful things to leave internal +comments about would include the current state of the user's information +as it relates to the request. For example, if the user is trying to add +memories, you can leave an IC about how many +memories the user has. If the user is trying to change the bio, you can +leave an IC about what the text of the bio currently is. This makes it +easier to tell when the user has succeeded and the request can be +closed.

    + +

    You may see internal comments about things missing in Support answers +or what is needed in an answer, but you should not make internal +comments like this until you have the supporthelp priv. If you have made +it to I2, you definitely have the ability to become a supporthelp priv +if you keep working.

    + + + +

    Summary tags can only be added by supporthelp +privs, but understanding them may prove useful to any volunteer. Summary +tags are designed such that no one needs to remember them or use them, +but doing so can save you time and effort. Not all tags are used in all +categories. A listing of the tags can be found here.

    + + + +

    There are many aspects to being a supporthelp priv. In its simplest +form, you answer and approve things on the board. In reality, most +supporthelps do much more than that.

    + +

    Supporthelps have all the obligations of interim privs. They are +expected to keep private information confidential and to treat all +volunteers and users with respect. They are required to change the +category of requests, if necessary, before doing anything else in the +request. They do not have to handle any request they do not want to, +even if they know how to, but if they do handle a request they must +approve an acceptable screened response rather than writing their own if +an acceptable one is already present.

    + +

    The abilities of a supporthelp are:

    + +
    + +

    Supporthelps are also given membership and the ability to post in .

    + +

    When you first gain supporthelp, you should look over the Support +policy memories in . +Some of the entries about policies will be friends-only. You will be +expected to know and follow them. You should receive an e-mail that will +make this a little easier. The Useful Extra category also has some +helpful friends-only material.

    + +

    Many supporthelps will do more than just work on the board. +Supporthelps may be involved in giving reviews, +mentoring, answering questions in the Support +communities, suggesting good volunteers for privs, bringing up issues +for discussion, and reporting volunteers when +there are problems. To get involved in these activities, discuss it with +the relevant category admins.

    + +

    Remember, if you do a review you should send it to the volunteer and +cc it to the category admin(s). For most categories you will then also +be expected to post a summary in the category's community. To find out +the specifics of your category, ask the admin(s).

    + +

    If you do decide to mentor someone, please make sure that you keep in +touch with your mentoree/manatee. If you cannot +do the reviews yourself, ask someone else to. But it is vital that +manatees not be ignored. By accepting one, you are stating that you will +handle this volunteer's questions and reviews. If you do not feel +capable of doing this, either do not offer to mentor or make special +arrangements for the parts you can't handle.

    + +

    As a supporthelp priv you will be expected to serve as a good example +to the other volunteers. While all volunteers are expected to be +courteous and respectful, it is more strictly enforced on supporthelps. +Other volunteers are considered to still be in training, and as such, +mistakes are more understandable. We do not expect supporthelp privs to +never make mistakes though. It's perfectly fine if some mistakes happen. +You may be informed of such mistakes by e-mail, but it doesn't mean +anyone thinks you're a bad priv. It just means we want you to learn from +it and improve. Mistakes of fact or policy are completely +understandable. We simply don't expect supporthelps to make mistakes +such as leaking confidential information or harassing volunteers or +requesters.

    + +

    While we like all volunteers to follow up on the requests they try to +answer, we especially encourage supporthelp privs to do so. A +supporthelp priv can see a request through its entire life-cycle, from +possible commenting, to approval, to potential touching, any necessary +summary changes, validation nags, and closing comments. By following up on requests, you +learn what information is most important to include, both for answers +and internal comments.

    + +

    A validation nag is a follow-up comment that reminds a user of the +importance of validating. It is used after the request has been sitting +for a few days (how long may vary by category; check with the admin(s) +if you intend to leave validation comments) and the account is still not +validated. The current version of the validation nag will be sent to you +when you earn supporthelp in the general/unknown category. If you need +the nag and do not have it, please request a copy. Requests should not +be given more than one validation nag.

    + + + +

    Comments are used to ask questions or give additional information. +Comments should only be used when necessary. If a request is ambiguous, +it does not necessarily need a comment. Whenever possible, an answer +should simply address all possible interpretations. This is usually +faster and simpler.

    + +

    However, sometimes a request will not contain sufficient information +to resolve it. In these cases a supporthelp should comment requesting +the additional information.

    + +

    Comments are also used to correct mistakes. If the approved answer +neglects to mention something important, a comment can add that +information. Comments are commonly used in validation nags, as explained +in the supporthelp section.

    + + + +

    Deciding which answer to approve is not always easy, and there are no +firm rules that will always work. However, this section provides some +basic concepts to make it a little clearer.

    + +

    Do not approve answers that violate any of the Support policies as +explained here or here.

    + +

    Do not approve incoherent or poorly written answers, but in general a +single typo is okay. If the typo causes the answer to be offensive or +confusing, then that would make it unapprovable.

    + +

    If information that is important to the request is in a FAQ included +in the answer, or in a FAQ linked to from the FAQ included in the +answer, then that is generally acceptable. However, if it requires +following links beyond that, it is not reasonable to expect the user to +find the information and the answer cannot be considered complete.

    + +

    If an answer is close to approvable, but not quite so, it is +encouraged for supporthelps to email the volunteer to improve the +answer. It is never required to do so, but doing so helps both the +request get answered and the volunteer improve.

    + +

    If the volunteer is an I2, you can leave an IC stating how you would +want to see the answer improved. This is generally easier than emailing, +and will usually result in the volunteer seeing the information and +correcting the answer.

    + +

    Supporthelps are expected to approve the first good answer. However, +if a user re-submits an answer with small improvements whether to count +that new answer as later or based on the time of the original answer is +up to the particular supporthelp. As long as you are consistent, it +should affect all screened volunteers equally and still be fair.

    + +

    It is good, but not required to leave explanations of why you +approved what you did. In some cases this will be obvious. If it is, you +do not need to leave any sort of note. But these notes are helpful both +to I2s, so they can learn what the standards are, and to other +supporthelps, so they can answer questions about approval easier. They +can also save time and effort during reviews.

    + + + +

    Any volunteer may report anyone who they feel is violating Support +policies, causing problems, or simply making mistakes. All reports +should be sent to support@livejournal.com. Some volunteers are reluctant +to report mistakes. Please keep in mind that a report does not mean that +the volunteer in question will necessarily lose privs or have any other +action taken. But mistakes need to be reported so that the volunteer can +be corrected. Most reports will be handled simply with a reminder to the +volunteer of the correct way to handle the situation. Warnings and +removal of privs are usually reserved for people who continue to make +the same mistakes after being informed of what they should be doing.

    + +

    Particularly good volunteers and Support requests handled +particularly well should also be pointed out. However, only those with +supporthelp priv in the relevant category should be pointing out such +things. These can also be reported to support@livejournal.com. Pointing +out particularly good volunteers is often most appropriately done in the +community for that category. By the time you have supporthelp, you +should know which is appropriate for your category.

    + +
    + +

    Should you wish to stop volunteering, you can do so at any time. If +you have privs, you should contact support@livejournal.com to have them +removed. If you simply go inactive for a long time, you may find that +your privs have been removed for you. This is not personal; it is simply +because privs are given to people so that they can perform certain +tasks. If you stop doing the tasks, you stop needing the privs.

    + +

    If you wish to re-join Support after a long absence, you should again +contact support@livejournal.com so that you can be caught up as quickly +and easily as possible. The Catching +Up category of 's +memories is specifically designed to assist returning volunteers.

    + + + +

    Sometimes weird things happen on the Support board. These can startle +or disturb volunteers who haven't seen them before. This section +attempts to list some of the unusual things known to happen from time to +time.

    + +
    + +

    Probably the oddest is when Support requests get labeled with +negative time. Support requests normally show how long ago they were +opened. Sometimes the clocks desynchronize and cause the requests to be +labeled with impossible times. This will usually get noticed and fixed +pretty quickly.

    + +
    + +

    Similarly to negative time, if a request is less than a second old or +believes it is, it will show up on the Support board as posted +NEVER. In the normal course of Support, you will see these from +time to time. It means you happened to catch the request just as it came +onto the board. It will appear with the correct time at the next +refresh.

    + +

    Requests Disappearing

    + +

    Sometimes you will do something in a request, and then not be able to +find that request again. It may vanish from both the open and closed +requests. This generally means it was moved into a private category. +Usually you won't get points for such requests, but every so often an +answer given publicly will be used in support@. This means you can get +points that you then can't find. If a request is moved to a private +category, you generally will not be told why, as the reason is +confidential. Requests can also be moved to private categories if +further issues came up on the request that made it confidential or if +the request had abuse implications. Similarly, requests can appear on +the board already several hours or even days old if they came from a +private category but were able to be handled by the public board.

    + +

    Requests with Multiple Answers or +Comments

    + +

    Some requests will have two answers about the same thing or two +comments doing the same thing. This can be caused in two different ways. +First, multiple Support answers and comments can happen because of +technical problems just as multiple entries can. The other, and more +common, reason is that two different people were trying to work on the +request at the same time. The screening system keeps most collisions, as they are called in Support, from +happening, but a few still get through. To reduce the chance of +collisions and to encourage error-checking supporthelp privs are +encouraged to always post screened first and then approve.

    + +

    Requesters Talking to Themselves

    + +

    Sometimes you'll see comments from the user who opened a request that +look like half of a conversation. They may say that the problem isn't +something that wasn't brought up yet or add additional information +without prompting. These requests can look very odd. What they tend to +be are requests opened by someone with support privs. They are replying +to screened responses or internal comments that they can see.

    + +
    + +

    This section does not contain any information that a volunteer needs +to know. However, whenever a large group of people work together for a +while, they will create references that can be rather confusing. This +section attempts to outline the tangential creations of Support.

    + +

    #lj_support and IRC

    + +

    Several Support volunteers hang out on an Internet Relay Chat (IRC) +channel. This is not an official channel in any way. It is currently +located on irc.lazynet.org on the channel #lj_support. It can also be +found through http://irc.callete.com/. +You can check its current location or ask questions about using IRC in +.

    + +

    Answered With Elegance (AWE)

    + +

    Every so often a list of particularly well-answered requests is +posted to . Any supporthelp priv may +submit a request to be included in AWE +unless they answered the request themselves.

    + +

    Support Bunnies

    + +

    Like many other things in this section, there is really no good +reason for Support bunnies. One volunteer, , +once answered a request quickly, and the requester came back and said +that she was "quick like bunneh". It spread when one volunteer, , +created a cute bunny moodtheme. Then several people edited their icons +to also include that bunny. The bunny became a sort of mascot of the +Support team. Now many volunteers have user pictures that include one or +more bunnies. When someone answers requests quickly, they are said to be +"bunnies" or "bunnehs", and "bunnying" is when someone always answers a +request a few seconds before you.

    + +

    Support Cats

    + +

    The cat is a natural mascot for the categories, because the word +"category" is often shortened to "cat". While the exact type of cats +that represent each category is not currently known, general/unknown is +a calico cat.

    + +

    Chinchillas

    + +

    One volunteer, , +became very interested in having a pet chinchilla. Somehow it worked its +way into posts and comments enough that many people started making +references to chinchillas. The user picture for +is at the time of this writing, a chinchilla. Her name is Koala! and the +exclamation mark is part of her name.

    + +

    The French Toast Support Category

    + +

    This is purely a joke. Before category admins had the ability to add +and remove privs directly, they would post what changes they want to + and +would then make them. +included in a normal batch of priv changes that she should be given +"SuperGodlyPowerOverAllBowBeforeMeMereMortalsAndFeedMeFrenchToast" priv. + added supporthelp in FrenchToast to her privs to play along. The priv +doesn't do anything and the category does not actually exist, although +there have been some discussions about the best way to make french toast +and some user pictures of french toast spawned from this.

    + +
    + +

    There are many links that you may find helpful, both for your own +reference and to refer to in Support requests. However, before +referencing any link, you should always check that the link currently +works and contains the expected information. Some of these links aren't +official; they are included because volunteers find them helpful.

    + +
    + + + +

    Support has a lot of terms and abbreviations that volunteers will use +without thinking. This can be confusing to new volunteers. In an attempt +to make it clearer, here is a glossary of many of the terms used. Some +of these are directly related to Support, others simply tend to come up +in conversation with Support volunteers or in Support posts or comments. +Some of these are terms that are used elsewhere, but since we get +questions about them, they are included.

    + +
    +
    admin
    +
    Someone in an administrative role. The meaning of this word can be +fuzzy. Sometimes people only refer to staff (employees of LiveJournal) +as LiveJournal admins. Others refer to the category administrators as +admins. Basically, it's just someone in an official leadership position, +and the specifics vary.
    +
    approve
    +
    The act of turning a screened response into an answer or comment +that the user will see. Privs approve answers and comments in +requests.
    +
    AWE
    +
    Answered With Elegance - a posting of particularly well-answered +requests in +to share with all of the volunteers. AWE posts are made +irregularly.
    +
    BAR
    +
    This is a variable, like FOO is. It is used to represent that +something gets filled in where it is used. FOO and BAR are the most +commonly used, although others you may see are BAZ, QUX, GIN, and +TONIC.
    +
    bastard freaky
    +
    An unusual request that can't be solved through the normal means and +requires special attention and investigation.
    +
    BBB
    +
    Big Blue Box - for a long time the box of known issues was blue. +People are likely to still refer to it this way even though the color +has changed. At the time of this writing, it is yellow, but it may +change again. Some people are now calling it the Big Bright Box.
    +
    BYB
    +
    Big Yellow Box - another name for the known issues box.
    +
    canned answer
    +
    A saved answer to a common request that is reused. These need to be +modified to fit the particular request if the request is somehow +different. A good volunteer knows when to edit a canned answer.
    +
    category admin
    +
    Someone who oversees one of the Support categories. Category Admins are usually the best +contacts for information about their categories.
    +
    cats
    +
    While Support volunteers will sometimes discuss felines, this +usually is referring to the public Support categories. People will ask a question like, What +cat is it in?
    +
    close faery
    +
    This refers to anyone with the ability to close requests and assign +points who has been actively closing the board. When closing isn't done +regularly, it causes volunteers to get a large increase in points in a +short time. Some volunteers refer to these points as coming from the +close faery.
    +
    closing comments
    +
    This refers to going through requests and researching whether they +are ready to be closed. Often internal comments are left pointing to +evidence of the user having been helped. The name comes from before the +ability to make summary changes, when all such requests needed comments +to mark them as ready to be closed.
    +
    collision
    +
    When two supporthelps act at around the same time as each other, +they can cause multiple comments/answers to go through. These are +referred to as collisions. When multiple people comment answering the +same question in a community, it is also referred to as a collision. +Basically, a collision is any time that two or more people, by trying to +be helpful, end up with a slightly less desirable effect.
    +
    comms
    +
    Short for communities. Usually used when referring to the +communities Support category.
    +
    cust
    +
    Short for customization. Customization used to be a Support category +and is still closely tied to Support.
    +
    custy gunk
    +
    Requests in the general/unknown category that would have been in the +customization category when it existed.
    +
    degreening
    +
    The act of approving answers so that the requests turn from green to +yellow.
    +
    disclaimer
    +
    A string of text in a Support answer used to warn a user about an +issue. There are a few more or less standard disclaimers needed for +certain types of requests. An example would be that links to external +site requires a disclaimer about it not being affiliated with +LiveJournal.
    +
    filters
    +
    While this often will refer to things like custom friends groups or +email filters, it can be used to refer to filtering the Support Board. +Above the requests at the Support board +are two drop down menus that let you see the Support board with only +requests that meet certain criteria visible.
    +
    FOO
    +
    This is a variable. For more information see BAR.
    +
    IANASH
    +
    I Am Not A SupportHelp. Used to explain why the person is only +answering part of a question. Only supporthelp privs can answer specific +questions about requests.
    +
    IC
    +
    Internal Comment.
    +
    interim priv
    +
    Someone with some or all of the interim privs +or a referral to one of the privs. Such as, WonderfulVolunteer is now an +interim priv, because she just got two interim privs.
    +
    je
    +
    A single person gender neutral pronoun. Its object form is jer. An +example would be: Je didn't explain what further help je needed. Jer +comments were very confusing.
    +
    manatee
    +
    Someone who is being mentored. Mentoree and +manatee sound similar, so the more amusing form stuck.
    +
    mentor
    +
    Someone who is helping to train a manatee. A manatee can go to jer +mentor to ask various Support related +questions.
    +
    PAF/Paid Accout Faery
    +
    Sometimes long-time support volunteers find that they randomly have +more paid time than they used to, or suddenly have a paid account. The +Paid Account Faery lurks around the edges of the support board, looking +for people to gift with paid time.
    +
    priv faery
    +
    Similar to the close faery, someone who grants a volunteer +privs.
    +
    screened
    +
    Refers to answers or comments that cannot yet be seen by the user. +Screened people can also be used to refer to volunteers with no +supporthelps privs.
    +
    snerk
    +
    A cross between a snicker, a sneer, and a smirk; the amount of each +can vary.
    +
    summary tag
    +
    A string of text put in the summary of a request to allow some +information to be viewable from the main Support board. See the section +on summary tags.
    +
    validation nag
    +
    A comment left on a request to remind the user to validate jer +account.
    +
    whomp
    +
    Refers to handling users who need to be told that they are somehow +taking advantage of the Support system. Repeat abusers are said to be +whomped. The whomping is traditionally done with a whompy thing. When +large numbers of requests are handled in a small span of time, they may +also be said to be whomped regardless of what kind of requests they +are.
    +
    YASC
    +
    Yet Another Support Community. There are rather a lot and when new +ones are made people will sometimes use this acronym.
    +
    YAUIC
    +
    Yet Another Useless Invite Code. Many volunteers have far more +invite codes than they could ever use, so when they earn more they may +refer to them as YAUIC.
    +
    Zilla
    +
    LiveJournal's Bugzilla server. This is where bugs are reported and +proposed improvements are worked on. A Zilla item refers to a specific +bug or change under discussion on the Zilla server. See Useful Links for the URL.
    +
    +<=body +page?> diff --git a/ljcom/htdocs/doc/index.bml b/ljcom/htdocs/doc/index.bml new file mode 100644 index 0000000..7fef6ea --- /dev/null +++ b/ljcom/htdocs/doc/index.bml @@ -0,0 +1,35 @@ + +body<= + h1?> + p?> + h1?> +
      +
    • + h2?> + p?> +
    • +
    • + h2?> + p?> +
    • +
    • + h2?> + p?> +
    • + + p?> +
    • +
    • + h2?> + p?> +
    • +
    + h1?> + p?> +
      +
    • -
    • +
    • -
    • +
    +<=body +page?> diff --git a/ljcom/htdocs/doc/internal/fcgi-acheck.bml b/ljcom/htdocs/doc/internal/fcgi-acheck.bml new file mode 100644 index 0000000..ccff606 --- /dev/null +++ b/ljcom/htdocs/doc/internal/fcgi-acheck.bml @@ -0,0 +1,9 @@ + diff --git a/ljcom/htdocs/doc/pay/diskupgrades.bml b/ljcom/htdocs/doc/pay/diskupgrades.bml new file mode 100644 index 0000000..d1b1308 --- /dev/null +++ b/ljcom/htdocs/doc/pay/diskupgrades.bml @@ -0,0 +1,85 @@ +Disk Space Upgrades +body<= +Paid +Account package, we offer a certain amount of +disk space for +hosting things like +ScrapBook images, +Phone Posts, and +User Picture Icons. +Every paid account starts with 100 MiB of disk space, with the option +to purchase more later on. +p?> + +
    + +Disk space
+upgrades that overlap will receive a prorated rate for unused time. + +Note: We do not offer "downgrades" for accounts. You cannot +purchase a smaller amount of disk space (or more disk space for a shorter amount +of time) until after your current upgrade expires. +p?> +More +details can be found in our +Frequently Asked Questions. +p?> +
    +
    + + +
    + + +
    + $b } keys %{$LJ::Pay::bonus{'diskquota'}->{'items'}} ) { + my $sizeit = $LJ::Pay::bonus{'diskquota'}->{'items'}->{$size}; + $ret .= "
    $sizeit->{'name'}
      "; + foreach my $qty (sort { $a <=> $b } keys %{$sizeit->{'qty'}}) { + # will be interpretted as item-subitem-qty + my $amt = $sizeit->{'qty'}->{$qty}->{'amount'}; + $ret .= "
    • "; + $ret .= "
      \$$amt.00 USD
    • "; + } + $ret .= "
    "; + } + return $ret; +} +_code?> +
    + +Paid Account. Upgrades can be purchased directly from our payment center. p?> +<=body +head<= + +<=head +page?> diff --git a/ljcom/htdocs/doc/tour/index.bml b/ljcom/htdocs/doc/tour/index.bml new file mode 100644 index 0000000..4b42491 --- /dev/null +++ b/ljcom/htdocs/doc/tour/index.bml @@ -0,0 +1,118 @@ + + { + source => "intro.png", + href => "/", + next => 'create', + }, + create => + { + source => "create.png", + href => "/create.bml", + prev => 'about', + next => 'profile', + }, + profile => + { + source => "profile.png", + href => "/editinfo.bml", + prev => 'create', + next => 'update', + }, + update => + { + source => "update.png", + href => "/update.bml", + prev => 'profile', + next => 'modify', + }, + modify => + { + source => "modify.png", + href => "/modify.bml", + prev => 'update', + next => 'friends', + }, + friends => + { + source => "friends.jpg", + href => "/friends/", + prev => 'modify', + next => 'comms', + }, + comms => + { + source => "comms.jpg", + href => "/community/", + prev => 'friends', + next => 'clients', + }, + clients => + { + source => "clients.png", + href => "/download/", + prev => 'comms', + next => 'support', + }, + support => + { + source => "support.png", + href => "/support/", + prev => 'clients', + next => 'sitemap', + }, + sitemap => + { + source => "sitemap.png", + href => "/site/", + prev => 'support', + }, + }; + + my $display = sub + { + my ($page, $code) = @_; + $ret .= ''; + $ret .= "\n"; + if ($page->{'prev'}) { + $ret .= ""; + if ($page->{'next'}) { + $ret .= "
    "; + $ret .= ""; + $ret .= "
    {'prev'}\">"; + $ret .= $ML{'.nav.prev'} . ""; + } + $ret .= "" . $ML{".$code.title"} . "{'next'}\">"; + $ret .= $ML{'.nav.next'} . ""; + } + $ret .= "
    " . $ML{".$code.caption"}; + $ret .= "
    "; + + return $ret; + }; + + unless (defined $FORM{'page'} and exists $tour->{$FORM{'page'}}) + { + $body = $display->($tour->{'intro'}, "intro"); + $title = BML::ml('.title', { 'title' => $ML{'.intro.title'} }); + } else { + $body = $display->($tour->{$FORM{'page'}}, $FORM{'page'}); + $title = BML::ml('.title', { 'title' => $ML{".$FORM{'page'}.title"} }); + } + return; +_code?> + + +body=> +page?> diff --git a/ljcom/htdocs/download/index.bml b/ljcom/htdocs/download/index.bml new file mode 100644 index 0000000..1119aeb --- /dev/null +++ b/ljcom/htdocs/download/index.bml @@ -0,0 +1,452 @@ + 'Semagic', + author => ', , , ', + text => " has been updating and enhancing the Visions Client with various features. For example, this client supports posting in non-Roman languages, and lets you preview your entry before you post it. Pick up a copy from the journal listed below.", + journal => 'ljwin32_sema', + }; + + my $c_win32_visions = + { + name => 'Visions Client', + author => ', ', + text => "This is one branch of the first Windows client. Instructions on how to download it are offered in its journal.
    Note: This client is no longer being actively developed.", + journal => 'lj_win32', + }; + + my $c_win32_lochj = + { + name => 'LochJournal', + author => '', + text => "LochJournal is a client that lets you use LiveJournal more easily. A popular feature of LochJournal is that it has support for many accounts on different LiveJournal-based sites. Please see the community to download this client.", + journal => 'lochj_announce', + }; + + my $c_win32_ljnet = + { + name => 'LJ.NET', + author => '', + text => "LJ.NET provides a simple and powerful user interface to LiveJournal's services. It is currently in beta testing, and is not feature complete yet.", + homepage => 'http://lj-net.sourceforge.net/', + journal => 'ljnetdev', + }; + + +# MAC SECTION + + my $c_mac_phoenix = + { + name => 'Phoenix', + author => '', + text => "A LiveJournal client for both PowerPC and 68k Macs. Phoenix works on Macs running anything from System 6 through OS 9; a Carbon version is also available for Mac OS X users.", + homepage => 'http://homepage.mac.com/thorshammer/phoenix.html', + journal => 'phoenix_lj', + }; + + my $c_mac_ijournal = + { + name => 'iJournal', + author => '', + text => "iJournal is a client for Mac OS X. This client can auto-detect the music that you are currently listening to, if you are using iTunes or Audion. It also supports custom friends groups, friends list editing, and can periodically check your friends page for new posts.", + homepage => 'http://www.os10.org/osx/iJournal.html', + journal => 'ijournal', + }; + + my $c_mac_xjournal = + { + name => 'Xjournal', + author => '', + text => "A full-featured client for Mac OS X. It supports offline operation, local saving of posts, history browsing, checking for changes in specific friends groups and multiple-group security. Also supports all the other things you might expect, like music auto-detection and friends list editing.", + homepage => 'http://www.speirs.org/xjournal/', + journal => 'xjournal', + }; + + my $c_mac_journalert = + { + name => 'Journalert', + author => '', + text => "A Mac OS X client, featuring WYSIWYG (What You See Is What You Get) editing and immediate notification of friends' posts.", + homepage => 'http://www.sprote.com/journalert/', + journal => 'sprote', + }; + + my $c_mac_zljpost = + { + name => 'zlj post', + author => '', + text => 'A lightweight Dashboard Widget designed to quickly update your journal. Supports other common features such as mood setting, iTunes music detection, community posting, and security settings.', + homepage => 'http://www.dmitrykirillov.com/', + journal => 'zlj', + }; + +# X WINDOW SYSTEM SECTION + + my $c_xwin_gtk_logjam = + { + name => 'LogJam', + author => '', + text => "A feature-loaded GTK+ client which runs under many different flavors of UNIX, and Linux. Binary packages for Debian and Red Hat are available. A limited-functionality, unsupported version of LogJam is also available for Windows here.", + homepage => 'http://logjam.danga.com/', + journal => 'logjam', + }; + + my $c_xwin_kde_kluje = + { + name => 'KLuJe', + author => ', ', + text => "A LiveJournal client for the K Desktop Environment. Requires the Qt 3 graphics toolkit, and can be run independently from KDE.", + homepage => 'http://kluje.sourceforge.net/', + journal => 'kluje', + }; + + my $c_xwin_gnome_drivel = + { + name => 'Drivel', + author => '', + text => "Drivel is a LiveJournal client for the GNOME desktop environment. It is designed to utilize some of the new features of GNOME 2 including GConf, GnomeVFS, and GTK+ 2.", + homepage => 'http://sourceforge.net/projects/drivel/', + }; + + +# HANDHELD SECTION + + my $c_handheld_palm_pocketlj = + { + name => 'PocketLJ', + author => '', + text => "With this, you can update your LiveJournal from your Palm/PocketPC/WinCE device. This client also supports offline posting for when you don't have an Internet connection, sending your posts when you sync (HotSync/ActiveSync) or directly connect to the Internet. Requires AvantGo.", + homepage => 'http://www.pocketlj.com/', + journal => 'pocketlj', + }; + + my $c_handheld_wap_mojo = + { + name => 'Mojo', + author => '', + text => "Mojo is a LiveJournal client which can be used to update your journal from your WAP-enabled phone. Visit the URL below from your phone to use it.", + homepage => 'http://www.binaryuprising.com/mojo/', + }; + + my $c_handheld_wap_tapjam = + { + name => 'TapJam', + author => '', + text => "With this client you can update your LiveJournal from your WAP cell phone. Visit the URL below from your phone to use it.", + homepage => 'http://www.tapjam.net/lj/', + }; + + my $c_handheld_java_mobilelj = + { + name => 'MobileLJ', + author => '', + text => "A J2ME (Java 2 Micro Edition) LiveJournal client, which can be used on mobile devices which support the language.", + homepage => 'http://netninja.com/files/mobilelj/', + }; + + my $c_handheld_java_lj2me = + { + name => 'LJ2ME', + author => '', + text => "A J2ME LiveJournal client that offers a variety of useful features and has internal support for UTF-8 character encoding.", + homepage => 'http://www.xfyre.com/sw/lj2me/', + }; + +# COMMAND-LINE INTERFACE SECTION + + my $c_cli_python_charm = + { + name => 'Charm', + author => '', + text => "Charm is a menu-driven, text-only, cross-platform client written in Python. It supports the full array of posting and editing options, can run in a polling check-friend-updates-only mode, supports multiple usernames and other various features.", + homepage => 'http://ljcharm.sourceforge.net/', + journal => 'ljcharm', + }; + + my $c_cli_perl_jlj = + { + name => 'JLJ', + author => '', + text => "JLJ is an interactive Perl client with numerous features, including friends-list checking, multiple profiles and several offline posting options. It can be run in a non-interactive mode for automated posts. Requires perl 5.002.", + homepage => 'http://www.cis.rit.edu/~jerry/Software/perl/#jlj', + journal => 'jlj', + }; + + my $c_cli_perl_sclj = + { + name => 'SCLJ', + author => '', + text => "SCLJ is a Perl program, based on the original Perl client by , which can be used to update your LiveJournal from your Linux or BSD-based box. Requires perl 5.005 and the URI and LWP Perl modules.", + homepage => 'http://sclj.sourceforge.net/', + journal => 'sclj', + }; + + my $c_cli_posix_clive = + { + name => 'Clive', + author => '', + text => "clive is a console-based UNIX client for LiveJournal, written in C. It can be used in a number of ways: on a pipe (like a filter), interactively, or just as a command. It supports both file-based and command-line configuration.", + homepage => 'http://sourceforge.net/projects/ljclive/', + }; + + my $c_cli_posix_centericq = + { + name => 'centericq', + author => '', + text => "centericq is a text-mode window-driven instant messaging application that supports many different IM networks, and integrates LiveJournal support into its IM interface. It supports posting, watching for friend view updates, announcements about friends' birthdays, reading journals via an internal RSS reader and many other options. It runs under a variety of UNIX variants, Windows, and Mac OS/X.", + homepage => 'http://thekonst.net/centericq/', + }; + +# APPLICATION SECTION + + my $c_app_mozilla_livelizard = + { + name => 'Livelizard', + author => '', + text => "Livelizard is a client for LiveJournal-based sites that integrates into the popular Mozilla web browser.", + homepage => 'http://livelizard.mozdev.org/', + journal => 'livelizard', + }; + + my $c_app_mozilla_deepest_sender = + { + name => 'Deepest Sender', + author => '', + text => "Deepest Sender is a LiveJournal client plugin for Mozilla and Mozilla Firefox.", + homepage => 'http://deepestsender.mozdev.org', + journal => 'deepestsender', + }; + + my $c_app_emacs_ljupdate = + { + name => 'ljupdate', + author => '', + text => "Update your journal from within Emacs with this lisp extension.", + homepage => 'http://www.freesoftware.fsf.org/ljupdate/', + journal => 'ljupdate', + }; + + my $c_app_mirc_mirc = + { + name => 'mIRC Client', + author => '', + text => "You can update your LiveJournal from within the popular mIRC IRC client with this script.
    Note: This client is no longer being actively developed.", + journal => 'mirclj', + }; + +# MISCELLANEOUS SECTION + + my $c_other_beos_alivejournal = + { + name => 'AliveJournal', + author => ', ', + text => "For users of the now-defunct BeOS operating system.
    Note: This client is no longer being actively developed.", + homepage => 'http://codeninja.net/alivejournal/', + journal => 'alivejournal', + }; + + + +# INDEXES + + my $p_win32 = + { + name => 'Windows', + detail => '95 / 98 / Me / NT / 2000 / XP', + clients => [ $c_win32_sema, $c_win32_visions, $c_win32_lochj, $c_win32_ljnet ], + }; + + my $p_mac = + { + name => 'Macintosh', + detail => 'System 6 - OS 9, OS X', + clients => [ $c_mac_phoenix, $c_mac_ijournal, $c_mac_xjournal, $c_mac_journalert, $c_mac_zljpost ], + }; + + my $p_xwindow = + { + name => 'X Window System', + detail => 'GTK+, Qt / GNOME, KDE', + clients => [ $c_xwin_gtk_logjam, $c_xwin_kde_kluje, $c_xwin_gnome_drivel ], + }; + + my $p_handheld = + { + name => 'Handhelds', + detail => 'Palm OS™, Windows CE, cell phones', + clients => [ $c_handheld_palm_pocketlj, $c_handheld_wap_mojo, $c_handheld_wap_tapjam, $c_handheld_java_lj2me, $c_handheld_java_mobilelj ], + }; + + my $p_cli = + { + name => 'Command-line', + detail => 'Multiplatform', + clients => [ $c_cli_python_charm, $c_cli_posix_centericq, $c_cli_perl_jlj, $c_cli_perl_sclj, $c_cli_posix_clive ], + }; + + my $p_app = + { + name => 'Application-level', + detail => 'Plug-ins, extensions', + clients => [ $c_app_mozilla_deepest_sender, $c_app_emacs_ljupdate, $c_app_mirc_mirc ], + }; + + my $p_other = + { + name => 'Miscellaneous', + clients => [ $c_other_beos_alivejournal ], + }; + + + + my @platforms = + ( + $p_win32, + $p_mac, + $p_xwindow, + $p_handheld, + $p_cli, + $p_app, + $p_other, + ); + + my $form_platform = $FORM{'platform'}; + my $ret; + + my $valid_selection = (defined $form_platform and + ($form_platform eq "all" or + grep { $form_platform eq $_->{'name'} } @platforms)); + + # mode: pick platform + unless ($valid_selection) { + $ret .= <<"EOT"; + + + check out the FAQ. p?> + + + + +EOT + foreach my $platform (@platforms) { + my $uplat = LJ::eurl($platform->{'name'}); + $ret .= "
  • $platform->{name}"; + if (defined $platform->{detail}) { + $ret .= " ($platform->{detail})"; + } + $ret .= "\n"; + } + + $ret .= <<"EOT"; + + + Or, view all of the clients on one page. + p?> + + + Web update page. p?> + + + APIs should be able to work + with LiveJournal, provided you can change which server they post to. p?> + + + developer section. p?> + +EOT + + $body = $ret; + return; + } + + # mode: list clients + my $display_platform = sub + { + my $platform = shift; + + next if not defined $platform->{clients}; + foreach my $client (@{$platform->{clients}}) { + $ret .= "{name} h1?>\n"; + $ret .= ''; + + my ($t1, $t2, $t3); + $t1 = '\n"; + + $ret .= ($t1 . "Name:" . $t2 . + "$client->{name}
    by $client->{author}" . + $t3); + + $ret .= $t1 . "Description:" . $t2 . $client->{text} . $t3; + + if (defined $client->{downloads}) { + $ret .= $t1 . "Downloads:" . $t2 . "
      "; + + foreach my $download (@{$client->{downloads}}) { + $ret .= "
    • {url}\">$download->{title} $download->{text}

    • \n"; + } + $ret .= "
    " . $t3; + } + + if (defined $client->{homepage}) { + $ret .= $t1 . "Home Page:" . $t2 . "{homepage}\">$client->{homepage}" . $t3; + } + + if (defined $client->{journal}) { + $ret .= "$t1 Journal: $t2 Watch " . LJ::ljuser($client->{journal}) . " for updates.$t3"; + } + $ret .= "
    '; + $t2 = ''; + $t3 = "
    "; + $ret .= ""; + } + }; + + if ($form_platform eq "all") { + $title = "All Clients"; + foreach my $platform (@platforms) { + $display_platform->($platform); + } + + } else { + $title = "$form_platform Clients"; + foreach my $platform (@platforms) { + if ($platform->{'name'} eq $form_platform) { + $display_platform->($platform); + } + } + } + $ret .= "Back to the Platform Selection page."; + + $body = $ret; + return; + +_code?> +body=> +page?> +img: htdocs/img/download.gif +link: htdocs/download/index.bml, htdocs/update.bml, htdocs/developer/index.bml + _c?> diff --git a/ljcom/htdocs/favicon.ico b/ljcom/htdocs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f3d21ec5e8f629b77c77615982cef929802fbde4 GIT binary patch literal 5222 zcmdT{3s6+o89vBPQIq*$1QbbvAP7Q0Tpmk!l@)pHf>>S> z1vbL6JXf&Eq~nt$W+Y}?NhYbg%X2}TX`y3UlPS(H)68fPIsMMP%d)ZvOQtiO{(Js= z?m7Sef9JdZJ&(JD*bxy~wQ3b%;$cU~E2vFPBC#hV6@5-lg8iE%gba#Un|TxR-jjq} zb3h#KnTHdU;W5$jSK%T=Pj@H?K_Lo-P~nPOqSb0qGXv!dp_JW0@nc==!i$LGD~{u9 zt~8U?B2Fd~qvpC~M^KA`gqqWJF*i|=E@%ujnuad%Of!pb5`P(QC7kR#SP2OTzQ<#W zlv%8aIKD~feX!6nCX`OuQ922|4;{CsbQG#}pj5FEW=E(mRL;B7LWEq0KANYW^3Y=B z_y|vmH;?ldeDaRw*8J(~hC!qOw?4H%Oa?Y1JnqbNZuG{_4-W8zh5g(k>k33gQDw%FD{ne3XB@ z!rC7_g|Gdhw<&R;HMK*r`+|J;KQGI_{V?zIn&?P3mLE&uo!9m>GUrS3pvy(U5A^kP z_$(c0u8#D!b_R{U=43cu$bYTlSjYsNjhYF)s`QQZ*3Ky}xtxmjy4jX?u^{kLVeo`r zO$S;h4E5!2dRRN72QywCwpkgq;m=hECwm&HvGsd>T}g=BENAdX&yl^G;15ZD@oDXe za5~)ny+KtH;%e1SDcr|-+q7@ZKZGT0tS19Bm$;2T93LRj8^{4y675bB zwk%H%+bJ)|KhfTK`uexou|aVjGo#E;Z%!+~BizWLXGzMgwI!$9Yp#x{^ivH+c7UV2 ztG$yM@p8QPk{Hi9qZjA|_iy0IrBz^V2FDGCt7!c=X2YVB&%j+s%GRZq6}$VIQ&2P#@0_gE zNAUFwKQH_3h_#F3ZUXmN_F>UpAnQ~Ky-mq~NZp*1ER$dEt(TrWr;qctLx_#Sm^+j7oj?A#I7DC$ zaD!T6s6Sj3{L6HyM1HcisHVO0oT2v1d(D5PMI|R99BoZLz$4vBrg+7t)3*@)h!oupL+wwg_YH%9vj*4aIjHXba4{8xkuc);A<= z{dZS2HK=KK!_1Gt{0T^;r%|h@D@A zwEWI*^|gxqvzS+eyR}HSKjd>V18&q9+tQP_E(>?D2|U7;$hbAy$_UJGbI$ekhw(yN zQ(t@t+Lp`(@GUljJClQ+q->vynK|C(jk-g{A&xDnJEp9_2N%N}naK~`m>>4s;pgp< z9QJ=jEdleAH`nptjkB2FdOtgL+Y^|;w&WZ>d7<84e)0JS>Jtat2~yqPk^=D3P?xq0 z@f7|6Jern%&D$w>p*GAGyl#LeY+CZk`Lq2)w{GZkg^@2rdyw`F-&0YZ?HMmk^)y+7 zCvI74%WRnjCpgYpE3*5H!##ZipIx~q^<9GpuZi7A2hXs1Zk~!pO}{2J>4l}(OBYOw zFj0B(Bt6hCeb>`pT-SE@^z{x5U2Ln3-?S|8w?F!!Jf|8`_0G@Mi{w$ z=X|SDy7MOoto~1%!)>|A@LPpZ)J;^~NDC9o;+|ify5q^Z+~}r~bWFtv8#b;5N6F%T zh9Q2R{a&r|U)2@;IgyF6UTmI3tzX1!nST@^QP$V_qZVtm#9wTzwZCbi{LlWU{0Anp BEK2|Y literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/feedback/fotobilder.bml b/ljcom/htdocs/feedback/fotobilder.bml new file mode 100644 index 0000000..e6b9c8b --- /dev/null +++ b/ljcom/htdocs/feedback/fotobilder.bml @@ -0,0 +1,50 @@ +{'body'}; + + my $remote = LJ::get_remote(); + my $userid = $remote && $remote->{'userid'} ? $remote->{'userid'} : 0; + + if ($POST{'action:submit'}) { + if (LJ::trim($POST{'survey'}) ne "") { + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("INSERT INTO fotobilder_feedback VALUES (?,?,'N',NOW(),?)"); + $POST{'survey'} .= "\n\nUser-agent: " . BML::get_client_header('User-Agent'); + $sth->execute($POST{'url'}, $userid, $POST{'survey'}); + + $$body .= $dbh->err ? "errstr . " p?>" : + ". p?>"; + return; + } + } + + unless ($POST{'url'}) { + $$body = "http://pics.livejournal.com, provided at the bottom of each page. ". + "If there wasn't a button for you to press, or you have some other related feedback, please post about it to ". + "the community . Thank you! p?>"; + } else { + $$body .= "
    • Was the page easy to use?
    • ". + "
    • Were any aspects of the page confusing to follow?
    • Was it easy to stop and pick up where you left off?
    • ". + "
    • Did the page keep your interest until you were done?
    "; + + $$body .= ""; + + $$body .= ""; + $$body .= LJ::html_hidden('url',$POST{'url'}); + $$body .= LJ::html_textarea({ 'name' => "survey", 'rows' => 10, 'cols' => 40, 'style' => "width: 100%; border-top: 1px solid #000; border-left: 1px solid #000; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd", }); + $$body .= "
    " . LJ::html_submit('action:submit',"Send Survey") . "
    "; + $$body .= ""; + } + + return; +} +_code?> +FotoBilder Feedback Survey +body=>{'body'}; _code?> +page?> diff --git a/ljcom/htdocs/feedback/index.bml b/ljcom/htdocs/feedback/index.bml new file mode 100644 index 0000000..3161735 --- /dev/null +++ b/ljcom/htdocs/feedback/index.bml @@ -0,0 +1,25 @@ +Feedback +body<= + + +
    +
    Have a suggestion?
    +
    +For suggestions about our site or service, feel free to check out the suggestions area. +
    +
    Have a technical problem?
    +
    +If you have a technical problem with the site or service, check out the support area. +Here you can check out the list of Frequently Asked Questions, or submit your own question. +
    +
    Report a Bug
    +
    +If you feel you have come across a bug on our pages or in our service, please report it to our +support team for verification. +
    +
    +<=body +page?> diff --git a/ljcom/htdocs/friends/popwithfriends.bml b/ljcom/htdocs/friends/popwithfriends.bml new file mode 100644 index 0000000..6d61660 --- /dev/null +++ b/ljcom/htdocs/friends/popwithfriends.bml @@ -0,0 +1,89 @@ + +body<= + $LIMIT; + + my $fus = LJ::load_userids(@ids); + @ids = grep { $fus->{$_}{journaltype} eq "P" } @ids; + + my %count; + + my $MAX_DELAY = 4; + + my $start = time(); + while (@ids && time() < $start + $MAX_DELAY) { + my $fid = shift @ids; + + my $fr = LJ::get_friends($fid); + next unless $fr; + $count{$_}++ foreach (keys %$fr); + } + + my @pop = sort { $count{$b} <=> $count{$a} } keys %count; + + my $ret = $GET{'own'} ? "" : ""; + + my $rows; + my $MAX_DISPLAY = 50; + my $shown; + foreach my $popid (@pop) { + next if $fr->{$popid} && ! $GET{'own'}; + last if ++$shown > $MAX_DISPLAY; + my $u = LJ::load_userid($popid); + my $count = $count{$popid}; + $rows .= "" . LJ::ljuser($u) . " - " . LJ::ehtml($u->{name}) . + "$count\n"; + } + + if ($rows) { + $ret .= "\n"; + $ret .= "\n"; + $ret .= $rows; + $ret .= "
    $ML{'.user'}$ML{'.count'}
    \n"; + + $ret .= $GET{'own'} ? "" : ""; + + } else { + $ret .= "
    $ML{'.no_users'}
    \n"; + + $ret .= "" unless $GET{'own'}; + } + + return $ret; +} +_code?> +<=body +page?> + diff --git a/ljcom/htdocs/img/2004_webbywinner.gif b/ljcom/htdocs/img/2004_webbywinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..57594a668b45f0ca3042ef6f9562744c7d48476c GIT binary patch literal 2619 zcmdVXhhI|%0>JV2vJ*0%7#TtF1pe$gkQR%A!E<0i8a%2dQ;~m()|C`+0vB!^p7#zHJ_ip#CTb(yeZ|1>FLSI$%%=HpMU;&baYg&*AEX54-F0V_xEeH+Mb@CuCA{3_V(-7udCJS z#>U1oXU?2Fd9t#yQYw{}l$0DjdbFURAR{9qB_$;xAt5R%YU|dmUS3}A?(VLxuKzOt z|8FrrVL$)~1zi4y|NR8OuLv!~5^1TdOfDx=ndMd0ikjNGdWi$u-kogkz+zZ4jyE;8 zsBK;4_EzfFW_O#bWtN_B**fR;+cjqV?jDI9M{Y~~z8)qy)OqnYSk^FCnVUbX_H>au zx^)bc!59Lo#)V6~sc`XwoXiOJ)#fkCXisJ9ttVv^e(;s5wHsxj@_HREglppF|6V0Q zGfOPe$D9`%>vxiHIy4H$ z5YZ^xQ^JUF6r?CkUxYf7MWPEKocMnWkf!BKhG?B9sJIA6P8qbs7*H)r_~m0a_$fg51poY0>Jm z@j*ewYEIhVwr~c++ke5O540}#Tmr<}O=PYQnVrZ%$5eI66qkH*dCqErI&UL6+~Czh zhNH#owpFv$7^{6dhH8>9GHVh(Unq>!iuy}qjr!BcVIuS9aLn}X%;$>XmUxTqBXTqf zWp8MENFYA5e;O-R>LnnNy)?q~oc>E5-xUdYqXHrw+9Siq*#bRLgD664ZC~7*Z;XARmM#|)ii^Mpz+UHCG3skprBFl521A9k5SUNLQRqns znu+-o33>@7AjRG3Ft0$Of-i#NO3z7%TMrLn)J%U;bBIeUMlqzTBvP>uxKATks9M>6_2(5hkTNpO#xUBfaSnHkacVL0$JkwQGzW#n zEwwq-;bx4yn`an$^a*d}*T4$4_g+FdMtzpGH|yJ-P5-?AC`iS_A>M(54dNGNTocoW zM!K(%!4a86`6#%gfbg|k(5zetKn|TIZEV;2bRmIaJkE5aA-|I;Q@1~AVSft&0%E;Y zA`+q*M@ilwZJlW1Ed)*0?@{f|vq%f>^UJAC(G~GpA<1a!PEYVub)<3IzI#bfZYp^> z8cEm)o2ykR7cna(Vc>!M zAc2Em))wL>KBPK9N)0BvNJ`nl2W%+Ql>_>ygxDRygpOZVuy~;rPLX_P{hSI#kyC91 z>A>ZNY}1zJZ5?hlVtZXnA+~K2-UfhX5eOK$4WOlKgwxN|N47JtSu%KN>sKsv-7oTz z%NHDZX$ZzNUZ^4nPGxULWnkiKJ&)VpXF}~(9;#z_v%}}ONp*V&8WDPVGqLmL4f+~( zB2Uy+nEP; zz>eLc$Je9Y*x0vez`~o?OuRJ>?H83x;UbsfZTksfS|Tn4La+Y})ZGS3;q1e)vEgIN z!Q^z>dgk4*LKW7}paruH;E@h7#%m=SB<-5!ikUy)k!;c9%L{AI*J{8udXSo#UqjmA zfM)muD2A3qWvRSZv$aJs!^2R80b{!a;C=PrssILC`fi7?3c7l3nyM2i@x93-nuDSD7r+$A|*!NYDpipP~jJB}|O zg658DDzBh|CEU4NvI+aUEVKe@2|P*>zPb14ZQ`+Ivar60AaY3(~ej6BaEnX-efA$(r I!vKN*1#&O&nE(I) literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner1.gif b/ljcom/htdocs/img/LJbanner1.gif new file mode 100644 index 0000000000000000000000000000000000000000..44cdd4d9f45549ea4dba89eb5f4108feee5a538d GIT binary patch literal 4627 zcmV+u6720qNk%w1VblRU0J8u93Jf0{B~&0Wq%vl-8zty2O7cL1+e3}?kdU>1jQ4bU z|FEM)j$~<`XsWJk>rziF z&vb3yc&_if?jVQ=-;k+ne3x~^R0ra1_I~u@bgBnV4hmT5-MD% zquP@w2-aMCqiY+QXTq!$F@v#(vx)xEmdOFqBv`PFT&|E|0Lqc9ftbW~LS)K-O>gY{ z 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner4.gif b/ljcom/htdocs/img/LJbanner4.gif new file mode 100644 index 0000000000000000000000000000000000000000..82656b4224813d4148fc455d7f9adbc03cd5319f GIT binary patch literal 3001 zcmV;q3r6%uNk%w1VblRU0J8u91ONmO2oM+ART_y7O@EC2ui0Mr3I000F35XecZy*TU5yZ>M)j$~<`XsWJk>r%=i z&vb3yc&_h!@BhG{P^TywkI1BQ$!t2G(5Q4uty-_xtad3GdcWYXcudA^&*-#z&2GEV z-Lia6uiJrd_Fk^}+;2Ewy%u(HW(wYfG037`xG4A5iJ zH3bD@TfEFpl&-|a$jxlazUXO$2(YjV*a8Tk3j*>&3)4RZ@Wt2U(5q2Q4i<3hnot^- zgyEz{56>wncZ|uxB@h`&FYzKUn$jobhM zPz0EJ=#-HF-;BeFZA=#JGq7A41x`yQ97YP#Ca{144X1z@fk(mw+)hZqm;s)?-5Q}9 za(96Ny(%hrz5En2ga!yCA6^U+&)vL@BM*C|?3Mw>u5(|mJ$WmN$9*5i-K3Ua9{z}S zlkrYAzX$c<8K9AXm~O%S!TxjK13bZ_8V>QzP}DsG7)XNw|J+v%P~6P7!)6b3R#$aTO&Ol1EnwMsYo0X?vaQCgpv*QPClLGQ{POT@zX#o z4K(0SO%2=@CxjacFb$bJ@cF=-HQhtNOz$X$Kms#Gw~d9G^;Y0%{_H6L4TmNglnieg z5a*nW4b(saVhSOSiz)V!M1x@wW26GQ$wK6kOMF?xcIyDco{*+8Lh3R{P_z!J%B_No zbgLFI+Rv4h1(SzAL za`6#Bsc?xjjjvShL_%eufFDD`W_CM)>Vc=r2f*d5fI|Y>TVEM z2Ud=`jK~2mIKiiD7Kd}txjS|d_n(HJm z_9zT`6;=pR5wcPnC08?pTd96tt0`wuHWG4UHFM0#&1`L4KipGbgZYFz zgXCSyQ0}?L@xV=t0tzpnK9DO097@D4;00C8A@Sg|oumFUSjs4=;X45un z$4TOjo@}!<6iM6`GgbG;$m5R0-f+LH74MG#d(N>(;a#zB#?Od&i`8;bv*kA%)*;wj zv!1S+lY0I1pmh#aCjr-h>cGC8@4&$LunY#ey-NpJgJp3N8|N^!xvL4xGycOAP~tSA z#b{%73e&~ybcYe^L8uo4pcr+q$ApLtPjSuB;PY;UJPtNTd3lQx^BTrHl>LotC^44v zQoEXc-a_fcz7S(g9HiLd+l2ruZ~?G^hp) zV50tJ{?W7gwGS3oyq6NgC#PaG&?pmJQA4Z;xJUG6Zng?XBQA&=V$Dq*zv5sV&x4(3 zp^!Rya~^Z5G&cnROO0G<%Bgs#74G2C2!w2&v=Y}n9@eZcK4HvaWb%>-0%k8X@C&9& zBTBoJ@&Sj@2PZWdnm?5iGB3FSYj}XkS$-yhhFRrbNLjlaV6vABLtApXvc^9e5_)cl z4OpIqOxoCn72H@A9v^`uKT=SVDx4u64-n12Jrffpo0f1qNKN0YtyQ?`=6PNwvr4`N z8}N*$Jm-+cWu~!$yxRyEku*0EnNtZjipuhShzXuNhmFz7rjdv-%;@|L7=$b&bpBSP zBqW_9po+vMbawd8d3yAtAmzb}xcHB%z#>O7)Qv?N1V#d|BuTMp0uwXHl9{>`79(|n zss<{RnMNlT7-1r_)(8)j>IjT0vZ=^`3XJCsm1ZH0s#HPB4j884Z6PtL8?fpJuF{Ye z-`K_e z8ukcy6)X}r2}~hC=uo{;tU(S-*~+Fhv3Ui|dq$H>Te=dJr*tJ^M5!CnNft$xO|5E^ zfmyZ&=s$9)4^Rf=!_(yFMEA0yz2+4Vcb!%dX~o8Bhl_;Pjx|%8G86xH{;R$svPn-e zxSyulhm#pZ2baI~fgrNm1L9sbtcradx*i}oZyo48g;HO7S65vKau*M4@If`O`-RK^ zVZLpJYiqnK3FC^ja;5>F6K#NAA_jP9`fKk3_WIr}{2&1X0Kfq5vj70JHw>!NL4_|& z0|_t~xcqencm*rop_G@r=e4bYFBg!dy%)Y!_(B2z09gPy#=>&Qa1J)CVNH4>#9Hw0 zRNu!y<+hl)0zP7MXB(jQ=Ig_3jWHQA7+t??xG&iC>}PyTp!r~VF&6%EXSwW3GT#Bn zQxNi0Uwg)(8Iiy$Mq*`*ai(n)g}YO*0|NjczFYdj7Ddi_+Ntx<~c3wypvtp@m2p-#@!tle7jSW_SO|9Bn@SC$@ zxG`f*%>@9dM!>5(e3}Z^qcTt)tfh^h<`;+Iem&_=z*2LK`{oy+_F_W1=P!P)aWg&X^RBM0fdXCnd=K;f zfVB6YZhh-gKy0@Exbj19`Wra^{j~4=%{)J2e*Q?D)vm_nvr*2Oh=0Fb7#DC{gKP0K zb@+h*Goddskbd(NdF%&&5NLVww*#Kn0J!EY12BNph5*)fYW{`_GysCChI|CFYy(&q z^oJP&NP@2SdJhb9)wB_Et0=h!dXYGyfNL+VX=^#|;ry0}M!T4(NU{ zxP+pY3rDzssxf1jv1|9|f%WigA}9kQsB51Ae)YqJGoW?4);eMJgt=f?n8k!l2n}Xv zd%8hopP?HshX66RXWig)C)j^#f@6l(E?+2w{5NPdkU`ir0bqxQBSr&ixQ4fI0XATJ zx@Lgs(sbsxZbQ>V*p4p{0RR9y`N@q5 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner5.gif b/ljcom/htdocs/img/LJbanner5.gif new file mode 100644 index 0000000000000000000000000000000000000000..e71126c58eab76dcd7441ac26529b3de97bdb4c2 GIT binary patch literal 2481 zcmV;i2~PG$Nk%w1VblRU0J8u9000082nY}m5EvL3EiElMIXOy7N>Wl%Vq#)*b90T2 zjk~+M*4EbM=H~bJ_y7O@EC2ui0Mr3I000F35XecZy*TU5yZ>M)j$~<`XsWJk>%MR- z&vb3yc&_h!@BhG{a7Yv;j)_5W={q8r(5Q53dRQL?supHlY`@^}D`8EDuGryK9P6^* z@c4%OFo)1t;aa|O^Z$Thbas4ufmIJ)hl`9wgMfyOcZrgfmO76e0|lI&1xgkKoS+q( zpBDoLNCY5}7X?TLq!prh6sEHhxB#jN2B@O|1F;*aNC>$WelP^Y8?Z;Rz@NKv{V1`Xg3<`(D=7TlWpsO1FO7u(RvMg4X<;EaitwypIN&jXf`AP0 z$*jPSP)3dkaPllUF`4bdy+-ALUK-ZO7{K_cdYfsr%UGzRWmb^kE zE2!m$K7c7KpI-oU%%QZR#DL(is8NjkkPj`}hX6X}YJDqUGROLKnw&6zo=OUUHT#sH z5x5m`i3?NkU5b;@;1^)0=)IZLumqn0(5}6Cut`5XQ;R>b+Qashq6bt&@^?+UDJO5q{dWN3kH zD)Knug6?^e3j#-w5>J(J`b6c5VQNsNfF=%P9F!GEry7!iO6en#XAY<4q{OkgftwX@ z2*5$EjmF@mjK(wCjaDAICYph|xT1jh!p-4+U$+!}QYfD#bEB}TEOS3$NveU~em z;&Quyw=%jL>p1R`yXz3Wg4*H*0rg5pT=_Y1sv>P2D9=^195mcP4Pgc-v^z>FAg8=V zmBB&pdIQdt)H>xbxrHWt8m@{|>EXVoUVEsb_X5GrhsHweodf1xz|{g#**n^1QDq0? zX4cFIu6ilq434C!VlZg6a3KIoK-JD!qtY8|5Ny#jFWiiWQq zwYI9FaP}X*Khy*_~)>-**a!^nN+Jug;OEdZfeCS`1zkgs&%RMMT?Hs_BS_&; zRL2Gq5(#IV0LX9DXT!Xl0yr=f!3kF|#1WM(80HCL2#Odb8j7KZ6)K`>(1Ju-{O}f4 z6bAlsX0eNXT=5y=*o1YmxQVxTuY|O!#TT`s2vHDZjm!&5SC)rGIAUNJ4VWV#Sm;J8 zlJOdA9AY0eK}I=}4s!(QoJiVm$LGMp3Aq;3G1 zRoJ0nwNyeB95~VJAIXQ7Xvxwiwrks)qwa+;7 z3ii4{H&Y@GWqxLy)2viL8h{oO+S3E7d-Z(ncC)%>nS`9lLaB?EXlR zC++O;muSSC8Lq>dhCY-7y;;_S@<4_>(1fH=f+8?AFeWb1gl`??+ea~UqmoMCq)7~n zp~#U8ZiX|N%lyj%UMfnP0#zJL#N19F0E*to6dmtC#}m-e0Wv&Qq{8qhR4ZjtlUUWE z&YT6BoC?+lh;RZC9l%60ayn-kXR0D1>r8FnOeEw{9b{0z5y)YOU@@~7RCQ%Wt(CF; z=+!1Fl|WmP&;YwM03(kTY=nZT49WtarLf8CUK4x4H$gU@=eQ9I5n0*6=!p>dP$ITI z3&gO?A??#T3|QMPxTJEAX$~**B1SKfVh(&Lnhb!iiBqYaj{==PfJQs}& z!7qaz%9AkNl~1o@GByszWO!U0Nw4|Tqh7ughq-}ZLGYr${sRPTnCzD@I}6l~_O`qI v?QoB~+~-dBy4(Hkc+b1u_s;je`~B~L54_+9Px!(c{_u!Tyy8I;0RR9yMmmzS literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner6.gif b/ljcom/htdocs/img/LJbanner6.gif new file mode 100644 index 0000000000000000000000000000000000000000..66a9ff4c838f208f76cde5277107ec329857688e GIT binary patch literal 2630 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner7.gif b/ljcom/htdocs/img/LJbanner7.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ffe4c998ec6f85864895685ad6bc7b5bfddbbf1 GIT binary patch literal 2545 zcmVM)j$~<`XsWJk>%MR- z&vb3yc&_h!@BhG{a7Zi~kH}=m(Kt06%BWPca4c5Osj|`3)*O#(squi89L&(-Y5t|X zAn;>8H!s52hik3mtI%*WWO^oGT_kgd9)^lN4~>CT3wI5ZVs~OGWG;Y7ohhF|mK38B zrKXb=mZ=k`qhyt=sii2QnaO(zs`BY3?4rp=`(+l)1 z-lLSiX^TdO=@qdTxpcH(;2Eca1aFITNy6M|4KLDO+^FquDu&4t|U%m0*ib%T< z9aJ{H*Q6EH4Kw-_XUcS>G5*(ve$Qnv(QXzcsK_wbmFC}c>d9AGdB<6h+=K$k^hS0l zNvPq5Pt@@jW7!Q7om6vFFqLN4F$NNe7MusxhaPGuVTT;>BNI!B@TX&B-BHL9S}95( z)@=3AXXG$LhHxN$3g)NCCk^)YV1G6qg=2-txrO0$Aw;(xh4CncT?Q`Y!yI#}WVMKk z3l^wiO&L8m5PB2J8Dv0y?dj%KeUet-ReM_1lt=(R3(v^3D z)lMVSu^7pP?c@blVH@1F*IP=FT7`tou;a%D>4cb6TuP3mSdPW;xMl}v&~*r^+gTTE zf5qK;!B4hvH4{L|{w8{Ck@e*>U`)^owJd%gKq{$}ci4Hy`tg7z#O3GFhg1Vfa zDP^}7SO1~t;G?ddjyXzW({t4qIm+eMEtt!-xJVc+gVOF{av&C=&rW^}r#tb*>xaS_j zN6V5}ITa>$^AAI_+%8ZwiqPy$%vbB~{PQ0mYwL5M&m7Yy6hDbB<|O$e&w^!~#jf4Z zmyf$&q7CzKo2Ac5x@}?($E()l^#&XvmhEN!{?OyA)7hAL6X`+)q4q$Aev|^)P@1DJ z{y9)}D1sJm%#*rr4RBpp+K~Valt4^{MT1{600Krxst2+_gbW~`YLf89rgm%8Ba zz$Aj&DWHBa3{C^T27n#{poAt=K@SmdImtmK6BP4D5^*(&Uwuh9qcWbWo`XXLj>~vB zFhKqfQy2mt{t$~Z@FBJcH^d@F?kCA(n8n55LP`H3(E|Zj8GbINO;6)z-QUL`RA|%oYfXqo? zk6t8zJEPgdF}`yE6o=|g!o1E3=;r$L#?&T{UPoy0BcH9*iDb-lmj$XKuVJ}(WOpcr~kBTO|RMnlV*;nY^|$48{tE` z3P7JQYHAAhSb$1ARh<-=s~7}Z$xix}n0obUg}~|ovTA0J5uE@*-O0|sj+SY0E$u<^ z*-{GNHL{saYY*Ql0nZ+juM{|}N+UZ=*ZOm&h;6|E4r@_wDnhl9Wo=US{#Y170`!}j z4F+dBU|VJucCtEoZXg=+! z0Q;Jt!eIrlI4k^L1_$`71KvP^*PBV*@^rztZ7_Nz@Zh|fSi&{l>lZC-;`55P0!b}^ zkO|6R50?PM8OU*Z`$*#8D*42bm@a{PSXK!fww>LCENlTl0Pc3Tw>2f97#s}X9OIb6 zRA$D$rFVORo2CION$@Z%Uw1q@B;Nn^PJx^**G zGx69S%U01zhV+l`I%AV^IM#4G00D$7gF)ItDIhQdJ5g1Cg`$nZBcaU zHQJx1wi4h8V-70-+nWx+tTB+$0Te*P`?fQeH4I&LYLx*A@aTKD%;krdbD8Y6@iOVV zRt8|yiyT&Pt7&{vPnp!=8J(xapP6y}>bSX1PO-p~K=7{x8yw;F1^{hy`BL(Jqvwde zK+y+#^n4Bg0cgfGopsIVd=lWz@7(az{|Gb#T-k@+e$LYO*$jZ|eCJ1?CN0-a!VK(^ z-tTm#nhikgY9^WP%AWQy@t${=c<=igKK_OR|U@yvWY*-OfI zY~H=@(2OkMuYkh79v}OB=+S~s2xX=9& HA^-q8SA)TP literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner8.gif b/ljcom/htdocs/img/LJbanner8.gif new file mode 100644 index 0000000000000000000000000000000000000000..7a7239cae0fe286b70cd3513dfa06eb0e409bdee GIT binary patch literal 1821 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 KK=_LQ002AE{Dn6F literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner_metal.gif b/ljcom/htdocs/img/LJbanner_metal.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e2153681653e5fb4e26dacff80c16c51aedbf49 GIT binary patch literal 10901 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/LJbanner_pastel.gif b/ljcom/htdocs/img/LJbanner_pastel.gif new file mode 100644 index 0000000000000000000000000000000000000000..1e6ef946c1a0928022b60baa0519c2c7953986f7 GIT binary patch literal 14923 zcmX|{cT^MK^Y@bgNhk>ky#+$AV(48$kMt@iMXG|d&;&&=K!i{Y5CsG@NLSF%q)X^X ziGYZph;&d?K=}yP{P_OyJb&z-b7yAn`?WK>XV1>PR%b1B_59|5hJYg`fXQSA1O$YJ zhQ`FiBqk;jiNu_o914X}R#sMBUESE&*w)t8+uOUmyu7`=y|=e_w719X?LDflKB7>L za&nHU%b1LjBMR~8VQw!UwUr$)dXIXmnahm5#+)NY+g@+kUUkgT z^2pvu*>+>h9;141gt9l1bF|GkT5j9!J#jT|_l9ndB<{^qwnsvb_C~hniQDsu+w(Eo z%f#*F#O>vny}fM;C8w;6Qhg%L+-qw)fjoiDsjjB%?aePQk8E!CdALT3`1spNw z_n3{_M`g=LG0R7xd(5^Y=JNbXZ4lPp+tL9613wsosgeNo^U7<&lx)w#Jc>-g!pv{74&val+a-(p%Ox zQr$a$qJ0v6GNd#zs(X8h)qBg^^KB!&iDldK%Z&d?_Ri-tGKkd-%1MF#2fAF=#>{CO z3C-E-Wo(}eDUI_v)y%Tqy_2vLV@w&tIdPjY&txngjht}wGEaCya~J_cW&nj@9mBLH z?zN3%!3*iVe60n8KZfJEknMCOV2#Lk#M z$|*ZKvGk4{#Soc|ZAUSQ002Pcz(;LUmlBT$}Sq)~i~_O8rg$TS`TbJzAoXgKdx9W&P<{u-|5r+_IN%)_G6-$PjIh zSQ{@F6(ooPt{!}PKhgg5Lmz>KQ{1+LwmL}SRrZ-&cuF7jeTZM*y1ine0`Bt-*@^s? zKE*5V->-1XKO{>;Bl^$S+W=faVW*v1X7uKGk)t#**Y+rG_uNzO{&eQ{g&(6mFaAzG^WHo6#nXSIL#xtLQ0VEk z#CIz|!ewK?nIvEbzfZZZ=yPi(h`7U65m06VrqO!zsv zn$8Vgc#{eco2|%X7w}lS#qm{VEgM|0aPgKVh+J_|`a0D2rl-feu#S_*U4%e!QpL+a zYRDEsKn!6tmsBE#MkUVdLLOC>drejKa*GmA6Am=!k7R zb1q&Y?X$9r;jse+OI3g+JNqGRpc6^E;-yico1-P$QXqj6^IA)5(O@=w(2nz**HM4q zk!u`EPz5i^2sHPyAPRj@(=QP+ATzD*^L(+Dn}T1duRUkHWc&SYqOq4oiSFUlEqCux zYmM_7H?>+CM3*&RabY5CuX6b;dR4v&TwIZD&`G$aA*_~ULbo%>t$zHq>+`c+Re%Yc z?;Y4eoNpLx)8&W|AUq@t!^-nx(t<0Th;W@>RoCuWs0~>$z`DV$18g=0X&@Xb6SK%B z+ndQ_T$t%A&lWOHo{i`T8HeeMVXX70{lfyH`sR0lF9UfoZ^T?|6({V@yqWPO#+Ba- zc>MS;Ud^P4r|j)+y#I!@hRz}l5qjP}^3`plgSM8tkAKqso4?kCWO4WU4V|!)O>FJW z5S_*kj;jlOU1e8p&?QTy{|;hml$=&x+dLaK!L{@3{fZ+hT>DAF?6aF0hfNtb5f`8p z??gUzKqLxT_UT(C@p-=Q$~+eWE*8WvGBzoN%X%3G^FpgW0PE+SJJ&mVyL=J|;t8Zq z(c@#E`s`%VUgv0NRX)_OX8MwyDW8)CuU{+j%A1>=`2xxSePLrQl1%a_e*T=N^{M_q z&&WQuS{M5fehA+~KZ?`MzY|)5-my-w_aB+&uk0UnVCW4r4nrs_H`3pN=$7f1LVKIS zIy?<-!_rfu^gO-44)lL`A7r9%51DphP7snAVItK-{(LA^AsRAf(xj2kab8G@N!mGG zD~-J9SS7`sOUBA_`Q$Lq@C`}LPT$hYlKc`qghnGbGTB4Kg$gJ#AJ6umoqIesfGN25 zCFrTvI`7$0L$Lh2g|kUr*D^)Yc+2hsZpj~NWc}T!)2PA>>p3AWxIWQPdK_!*1`gyu zCw`2TD(;7pR7{cc_;d~GYX0p&fRvIG`}KwZ)MW6m{^S9{OqUMi$#D}!jgVI z89o~zAfWZzohLc6Dwo+Ox?9y%+bNrpOO6vgtp%pnfY{Tji<~Q~!y;`8qq2QK0=_3L zzNdBKlqA6>hhUGqj4JkOuX4R_D!zOoWOkyOJIixp5tpz*Q>iY1NPJ zJ~?LMjZ|Xbck4_)%(>;Uj>Px3Rd!l}=vHVhWM z8dwDH_!1Rb)i|$X9`gM2hDd8WWx5sz@OM(HRG-=0_S%u+uNE4T-69ZJSU(P;a@VZX zSVYpzpH|8D4g{+-5AO!O%vK4XvI$UnRkC(T$H(`gee`6hiSVerxe5Fqxmm2j{!!iQ zlq@E#vfMa&l(4*L{fH~%mYIMbSDq~hLDOfItXrK3a~wo1I1;3be?qV5f<)odY1&5s zCeZUg6A%vu!Zzs#kGcE3?BgGH3$HbvJjWra{W5^T=MqM|_@UI9rX35e>+q{I77zk+ z*-0n+4VbqzmL@=bnjvzF#!YIx5tj8HS;siB76ZAP(Yxrz6_uF z%r)28ftmLeyotZYeCR>FIC1?hN|B-}6d!fM!jskjALeoJ?j;J!#PWS;mrPMB0 zlyARdnR6Hx-Emsp4-I5&LHH_dSH$&fta<+kh{jO-Sa}jMSnvC@iY&Z8cVj8<+-J3t z@TIharTz2TVfMe8Riw|1j`4dERG%H$%1InH*?7ZsI=erw0;fo#Qv2yTSB^pHzn#Ep zPx>2JIxF~_URa80wnMBZrJ^b%P~UXryT;j0#}7&`fBEsf^S#kn^b-vflUJ)&fBtM= zthwtNmz8VxJ}39JKL_RiT~PC>9E~p0Z!RHN z`0}s*aztK0i2hsQ79@Zir=7(Q;7}Ji$rSlN==k#pQSB`@hkYZ%EuJUQAYDIRdo1wR z3TtE$=nRmL524_P5#FM~WE`ywUBEok3LAK?b1TMg)Iii`l-ogCAu!0f5-0>vT0w%w zo4H3Z!YYp9SDLuqkzpOp0+9y-O;KFK-yELBs}!2Rey2!FIGB?qdMz!PE$ilDubo)rElU0Txn>a5ia4da{tCB@F1CtjQMm<4YUn|= z0M|1j?K~d`1D-eWs_5oK4Dreyx%{lu(8Rc^=xCO_v2qZIalDId0x4S~l>L#)2wwqz z0I*{%#u#t%RWjDB-DEU6&#@@)Q%BzCu{=>W3pXo&m!Yg#7tE=vY)5s@80~CTEz9UP z*&Q=Hx;2&|t*PNdE+$uVtkeP(+H+>|1Dy|YKvmb?AGivfjd?taz2u7{1+r!x=3DrJ zqxJ#Z2>2R>D`FZPPGdnhnjHGU59sjU0Imrd*Bu0e#Kagz5DcDa7}7KJOLxFZvxOZR z`US7_>+qaA1bE$w)D65~GXc7TR|)5ZbYfs{k8~rjNpy;VfGLGf9rghrnFIiQpxY(@ z@A{P7&1jK;4?w9NcMo;YN!arii;~5ag88rX>U?1~nQ(`ayN_E77cUDME$W9$Cq`h| zCFJ7VE+e3$2stpa)Ja772VPh*`*Htmq33eNn54!N-T-oNkWu2>1@u7dB5w=V0UN#lp7GP6#Y)xzlln2G1bF=V|cu zY0ei2_yG;xjb;CUg>_?{gyWzI)11HSz521#{d)LPCWKFx^TFKNg#8C^skU%yCq4_< zs^0zi{rh}voV|4TAex$ig$>}LGQt&n|G|qk;Jak%jw7c~Rz))g{sF-~w-1|Np(5g- zT34uZ)0}&l%6FL$duf!d6#(c_6`zGIx9@$vxT>L8=oa3wdmr#on93UmJ;YN5f5CR~ z58>1YyXXtOXfF0&fcVX`F#Ll9G*|BmSH$bGNIC%h%us5}kgQl@_b~3qG22nGGeRMX zPd>n()kRC--ZM#FZDuvE(U16VF}yMv3Qx{k{jQ9Do#KkDceT~Rrt-P5nzLpSgPwN= zg`inYr&&@E>|`wGxH)G&;&HMgG#3j^!*af)aS+fDE*c<`04*hO%v8gJ+t?$?&`KJ6 z>B_}*U$58HhUu<`aaUNSuh%mg`&$6#CmKg707^we3TW(^H24^x@e#fJ5YI7w{Yhd_ z!we1n&6jKZ7uT)ohHehl2ZX1bXb1rVrP1J>H1+~CJH4ynrC#{%e#7_$+G|W>C4p9t zrbW{Lcc~4h9zB`tWaqMOEX8m7Fgy?v6X^`+y zwoEZkhgwhnalE0d*cn;ATeV{5HGH-Q7^Qiov(NJH!Bopsmi6Cf^;U2 zAPTMW&X@Z)fqROo-Gi>wSwnMz^#88jjXrD6Oo1fP^m|>T_OqoV3nXt$o4#uo{4rtr zBfGD35b|9)t2ZrK_CijdibL{t7)phF|^{ghl#TXSpJ4EU10pFqttHd;G{WreXyRJg} zKox|zxi2u%E2dcr>^25N(FE>wi}$U8k1@j2j(M!9vG-q*+@P=(kknr$GE6ucsS+mgowu#6WNx<>SNdvWkF)cpBnlST}82#eU z+NHMR@eAV*chEP`aT?P%A?>xk00mWY94w#3tQi>Ti3}Tn>C$BRdDY&e$%{>kNYSq< zV}v*MOB9>BP;>?b%9K!gEqXSzt3`jiw>w8ca;^39ZnTiOyHRH>Md(4MN7 z4_Yx4mO)38Oy~Jm7((21*salIW(UP%wQN^w}jxF4+t02R7`< zW?T_;j>YN4BJW#D;eE-&9FyM$q;2WEJ#;A7M8|u&vRL1JufFbb1F6qw&&5TNoEKTe z1KqHJ-;X7Kl=jPt(f>YvH!(G!%qKN(gmz$R%3KbO^To&?7886dv5%b>k*J6Zun;330pkglQO?)7m z2uUO8kFh5CrCSPcc12@p+Vz1HOb!ipI9BqV;l8KN?S&M5KbG6(ul;#dpiD1ieUke zgh3<>E!#r5W*Hj5g114ctr$U>F~IiVI-BO9tKCyq88Am%m)uW`B@FPZnV6voh#w2W z%JJFZF&kJb&6VMoey+S<`OJ@v-}J-B)q!%3*y(uH`e>|U8qg9T9@NkO3Vr?eG}u^B zXB5EYb9~E~#zmFa7=m=Mt%0ZZr#1jETewip8$mP1Omfs{MbVhn`!CDSW5-!6E-y#}yFViT-^fjs<7^2QbvbLn^xzIgbYV{PpN=Iub7=I5io_yD%s56pb zqj|%%^vWNr+2H)!Hn}vO1EkD>3cIo~jfK8^OJGhsb;+b0Ha=gwv^UY;s_|Yx%y7nN zU~cL?*Nyj#aQfTc_kGO225^<7H}d@=Iq1=(eyP)aQ+7+>hCZoD1DQ#K`6&sph5^Z? zceaP`mXm5Ff80E)Zt=+DHp~hc5h~ki(=CF0{kyn(ef@S2aZlt;6!|*&re`!ospF}h z>+hEOlI>{F`+cXYSdOYvnm_Im?I>dda3iuD$)6{9`gl$=Zz?&@Cl7sL`2{aeCfizO z=FKg1Pk*cJ=JigqL8GGV+dtbHiZ0!k@@4$Yz9IGK^Z0|?o6Uxs;r8Rw1AT?T4y)xJRRg{$Lv1&@3dTd`>wO!=^p{csVH|Boz*CC<~*L#!>MOw4Me3s4oq|{Ey>`A zJt%b^;fEb!6F=ljFgwAa81Ql*IEEi`SBCo#17GMY5HhyDoF<5x=2Y#1?;swgolVD} zY=z62qOtZ(5JUu^L(;<$4FCvTZ}iN7uMWmf2t8prnqJb6p?AT=g2|PmsZf|WD?P%y zGlN_9$1eqZ)kNND3!WUkSF(0QL3w*yh~%c-JxN~GFcKowA@9tcE+-BEXsXtpP5c%f zI*@kClO8<9F|zAU^Jyae1=XnBJsr|V^-kQ(_EdCV^Qo|LxAE?Y|IcS;_RZc0l?$ND zlC}%kt13Qxr_cQ{Z{i*H?um_(TKpC`?%hR<;z^Gwmb-73rpj9rD?C?MTBT}MnZvLA z)X!5*{T&B0|J}Kco##_QI>-RxqFksx6+3<;`1T~lW1oRux%S3@5e>-jb zS6kC@g!_PWKsK}FqM6i0RJ}x{*S$C`bbbMtQRn@w5O4PP(ZfBHbb_8tapY|NCK(J1 zeDnw+mf&kEUcGUEfQSVH^0Zpkt~`F)%AwrQ{K-}Ml*&?<)XVn$Z?9hV9`hWYHvKKq zKpTL&Fk{tT2$hDZjVUF%Hjk@6&S{zM5(NEPuS)O|+;3;nKhY!xB(LMZ zhOwXsdf_<{(mMIpcAWf*a>>CD1b#IR4Hsyy++KaOh^ZQ;{r-TRW$uC;>j zrEWi^&ZDxHm+(;w2ZeefGVa;naH2IePyTw4u=*`zx$}W4()_u@rp%tw*-ek|Ps}$0 zdpjwcK6_;kMRxHQzYF29V8R+~+3B3_C-=;l4jkWqX^Z-?tEm0e2?Nf>JjI^xOt53l zTH-rNYP`7`GTb#yJO_7CRouhaa>L(1^~UOvPyuH+WKMKq5J)<)CeG1G%me3*<*MPDG5JS6f42X$0g;e9a8q5xf;v}0D8@_V-u#U6!Z zuHVYf^^29$6g2bEKqZQuoF0Q1F<6!h29oTCqy)k! z#DlJ4PRf>)z)SN=CG#simI_jp0Dc97v(}^}`@(ylW91FsEkemY1IWB!b7_JFbPdQ^ zbX&pPO=5=K>*@fqlgN5XcjmRniZgEsf)!|LV%6RMA}?Wb{leFc`S$&@s%a`-k`Olq zQ{<)moY=qs^ijuzErY#i(o0Aoz=M$~r)lQ_+tHWpnoWvkYHRAE!kkA-=c>QCdErrb za*NnD_Od>9`aNO}|5m!{TwA>xOXzDli#F5*YD5hW56uR=T@wIyeCdx!`t7*_cJCOJ zjfl!k^xBYf?;LC!j3}M(+Wyy{@GcXq2yG&&mpqUiuuGyyQz7;&YX*K^drw*3(sK31#D82$1uI9-GMrvyfIl`l03C9kX{(^iI0f5jSm z{b3Q?_88T>I>_xK#amouK4vBtou7LnP)7dz3mfL8=)&?pfeKdV$1Udf&OM|7lg#}Z zue0u#|A7jcaHu*G4e&m&Hun*&1*d|{r7D?v;nR+~F#-{(HGHM3ukZ!n2j4bAv0+Nc z+PtAg>w`-fgZ{FgeTS{_O+s7!Fq~DFgu!yu?ZnRk5=kbtD}LCc!I<)f~KA-RY=PUTo83X zrwUqHGC3!#S=zrJtUbAUW^n5zfiYEoZuGoqZS(M{fBkUE{+gu(%Pgu`ty(!eBw@W0 zHA~X0dg_#&x&oA!I?JAN_j9BSi`X1UUW;i8RozJAR#>sKKPHQ+Zf2NW>$`9kqBGVM zWSF-JRzUv%`<(K{rvG$EZ{>V3Wy_X~6+sPcfg!Fm5I>&4ayv|;<%5b}@WokL`Cv=B z@$1!@YaZH^>Zvg2p!1W-@7!nxhaJN2gJa_Xv!nE=%6Hh0Hn*#U$v=jszxgyUaV((#Xsl0|1G%4aGn1QB4ykA`+ei?`gRNpu9BYTwN+|7 zmICVQz2nd>zEKRhg`=10acU`O`;(b=-^X+>Mdvs1`6)|>b6uX*s9u%Hu+utRoCAMs z`~=&@2zHT5|*8esD~jMFOndUxA_dL4jOcOMt42@#Dw`fdodrE{8hfLrO1uO%h{Z++cEthv>>>jpJg~(pw)JL{1M~ z!eEC=4PGc43LXx<$Ts-R+1vTJ+atDr%EdsaXV_uVVweTs*)#ly#RMH?;YJ+xBGUiR zyZ>f^aNi+4ot01NAeC1T72oW>PRnRQs}Mp=awA=2C0h)wouoTJCk@=Skr^PhD()MN zB2&UQz)4g<$-8u1B1AZ$Mcz?wV2w+@7=V*b(eP3k$sn%SBfije9sJtU=&3@s z*aldTp!^KadDB-fnrhUAeil#7hT)9N{5yrv6#n2&l@$PP9rFAe2uadJCX~rj0omPS z*Ew-E>J1#Ei4D&Ny2_w^2_QrWIKMBWOu{J(0kdTE$2QUv5v?m25N;x4N(!##o1z_< zV&SP~5jqI(P%G+557TXLU@^W`W==iUKU`0T3aeivXqJDT2*W~yR?=Nr0Z|0ad~!N7 zd;tnA)|YyxUzK3J>1Dt5xwUSR<8I6N3A#Tgrga(^y`Q0cJOZQk#;>HqsGJ?FFHM9U zlBgilvz`1LY7=}oz4N#+Oq_Ybd3+@6!2w+rqtG2808!nDi zI*acDICyO8sWd|H*3j||(%MFP6H9skS)i8M9snQ&t$_WhNMG8FBrhZcXD^%Gkz&xC z5#uax(IJOwQw&#sqHBbEM+l}^wib`WR>oU(Z5ArC8zxh_#!UF?vY83yki@EXxgn!d zB-5K1$}`HSX16JB!YU{rhqwX$*^qM}lX9t)7G4baXPd&sk{iB|F6S{24gf|tPEsed zNwH?^^f8x`$pA-w*UV9qR!23$5LV23-4P^9ATTK45QO7FshZF_I1#U-L(=4btyzRK zNFlWPkZdC9l?Lhpw+A+DP!sWD?HqKBaDeYI!mvo zm=Q~?p%?3LAeVc{-`7YlgCIV4w^qZhY?H|UhQg){=$yR|@WU;MjD|AczfY&1j*U0= z6uP!pb}TUFx>Lo_kR`yp*v?PQwFNq`E<*{HYV1IMdukOs#A|VD39O1_KSu>$SztRyzRR7% z; z02>zAVAwi1)G=kuMlnehr6)_1`w|(r>_WX6ARoOF_r26rIzzNrtMmGZ>nldrFZ*bP z32cALK@Z^2utky38ou&)sLm!r_t~i57&fuKjdcVDnIj6=O?e`gW*W!Rl{*jL4`LwZD9ZRFz6@Ni*IcVc(< z`2pN3h&W^X6kB$EgU-zz(Kcw+X@HFspIGc?8(g6`tJ$cJ4TbG{s^YN=hhs`{i&X*+ z2<;YopQ{;-OVJBW-TCs;BDYm=g~puQufoOPz6>wo3c&_4srMRnqIY~4pKa|Z>B;!= z+TSVnzf7EWYn32rMg_mEiA(d}u?g--_jSWXqS^DI^ZxtbAT$_91k3R^<21%8$5RzD z%@Mw9qT%)~XM$YMHFqy&31floS2qIynN$ocmBW|zLqDYQ0Rf%0rFLlLWS>8mo% z=^6cc2#3L$se0|{`j4Sz)APr)Xt?GwA}{V-bq(hf{FKg&tNC>S7AQIpN^g2>;FQ40 zP7a=-cDz$|(^YJntpUa}->8TO>_Ju$gGX{FtlwcMp$=%O{N3GcBHZg1j~upk*fUU3sVEWFFx zZ&0)!GHEF6^M(2H-8rut;UWCHNt-4u_Pb}s3!kW%f|N1&&p8!HDg67{{f-~+%!l?D zV7}bdu=~h0wc0t|@$v4Ls)b{XhZ-onf$S$6wRPyHs9lu}GQS2o^_ycJ3d^k)oHh}` zVixwvT%27pzzeov@Us#-$ZwL-($~x4#}~FVs7xQb;|0^!?f%cxlVaFgj)mxSu-_!n z-_zl-eFK|#);Gr7dwt-&cb%uOZZi9we?2*#dX2`p8#*fMeRS>xX16Q^tD$Jm;2~(M zt)=eJAzzwS_Eu>&pKc|W%`BIi>+_LWjFx@wxA~AI?4GkT>UGn!yI+%8O!>NQ-cM~7 z_0!)sG2BeG5SEai20uEws{cg-5;E)rdPf`k-3{NgcbmKMHH%jmBD8g%75Z`CBsWN{M|N&BY%-SeFtDK8n0NmBdu{n@c|ahFN4P`rH_ zJ2MlqQ(VlEnqdD=DlWt}y9GR8e1&rhOd+dk1j>CgY#TUpD+d>??e((kZie;-OXS_& zk6{{-PF>&bpOIyMt#bM%YBTs`=gJQa0(^(`<5CG*IuzpPkrBEYIbOptl?=VQkazv* zaeexy$3@3vQdW%zN7epyHYal04qMCu{N}dKRXhuR0Zst`&U<7;9%s__esxMfyCf3R z5$aGHSmc{nJ{`bIhooQ|K zS+_OU?L~vB%TN1;a;?Acbhr0sWNIF`xt{t8Br8_?fmh?KN-5tsjWL}<`)#cn6 z%kK?5@c*fP>9n_sK~v9ScA;v8RXh@PAy!D8vn!yD!z%>-9%p?tf^s41_lJ$~XH&l2> z&q+gZzcs|i97y+jtDHYWuD-*R{B5#mh#5oZUt!N$8aw&yOO0n_f!0z2Rp=Ul$9BGX%fWMwb*; zRWlr2sCNJQg;t3M$PIga6CVmyg|+FGbegcy;i^S9mzm=!K~w>AG9yTz`mh8Z_+Mqd zggzc82BW8ND1|l-&zDEOXsh+U_A^tEntY(;;Y;AREcQ!3Ra1A;oco~=l<)sTIQV|Z z)sMloAxaknANT*L5A~x+ehTX-xpF1)*?)3n$U&H(7k*q)r#yOUF-r{DdBJ^1_%eRm zTg0rY2`Wh@IN#TAHFV)IX>e@LIDbi#dI{6JumQ$>o*S5x)UHW`n`}`+WL$S{KpB#( zQIDte+b9}2TDw#iPS;&Wmp%OtIimJ@t2CB~n$T$A3>H~A?5$!VXJpxO5i@n6hCE!a;8-1O-g|9t=z_#C5+6al8 zx~%MJdzql8(k~?=AIVRa8ol%6GikqpJKH{qv6)t(ID#MwT$t&*IkO+~o;BcaMnqpgL?JB#IuK@MJ@ZY`IF&kNU96r zpORP9xuGjwQ4_B}dBu#CG=*M$2h0cansKRFNt4OVjMIG$l^il_z=sq1pIlAPis9)q zfW%$sdLG6*CDd+)o69S&G;zq2q1)q{z|j9X1T<6@ekHD27DeQ>7h@naxypJp6QOfa zj%%5EV-ucvucB5!Uo}?Vz(+-%xr1u29}*n;oTB!lnEMAWTxJPB%C>WKCrz(M?X!vv zY{OGYPZc(OEtS0_&zvcizS_HhG7-TVSi3r+1apePt3xzAv{Gg(nBdePcV^#hTC4{u zF*k`+I|zwHEoG-2&Cg`PoAQ|`yF@j{e3bESK1L+~|!Ax5%Ghi)fkozYqlqvRqS?Gd@8Ms zo>^)?9I)e!h#lbx-`=|FJJr=Q*g&z# zD10ad`N{W|!MLB6c~3HFstN0-wYNZK(;6Sp}_kAi=H_)$0Uw*pCO^*Hk49s zmUX4b;<1p z=R0^1Z3KS?vZ}t1g2!ziP9 zs#mx=?s=AA3g_(j3c{*oS=afaCcb=Buy)F$Mx?eazqWAjYtOqZl=h5u^$Qw{WSo4A z+fB8y;&s$G;&t(SD;BqsHLmbE5svsuX>2Adkvjzymqg1I}+GE1s8lboQx8*7zO&$Ctj=iFAI8dO~86DSnK9^q#90 zdOPioRMczSgvItbFANJ(w;d$|kc>6mF$s`HW}5o0Bl9uls2x1OKxF_)M6)U!(g17( z2%`7D`Xr^l9n zE{*y`D$6LtAy9DSuVuR|4`a=Ze!;MsJk$k)XPS+gzS^8_Qo>aPIP>jJ^FGi$H4+th zLCBwnRR~KiSK8>98_vF|FDmfs;j@y`gB)!u+ogpa1s&&_hLWb{3r&;t&$jX>ye+-f z_~gfy5Z`p3FYZRkY`a@EpQlat^KajHjT+`ifkAY!a-YeW*bfx|D+Pi`Pac3(h7O51 zG68K-0Y1E-0>>!2a=6~KQab~UD~FR=nl!> zZXOS9vfs>P&L;IBv)zXz1k`@gjn4qXE_b8Q#*i0J&wOP^-;jn+`I~A!Jh)xdBgOGD zbLwL1L7uzO*BFQElY(cCIzRl83w&_H^za`~8ToI;u=MXM4blPyy0Kr*J^&aT6Mom< zPF%@#`1Q`_{z=h(}ui{i_(-b z^hOFGaHf2NeF5jT;CSc32={$F6GXhmv)QG$5Yh{`OrK|@!s^A zPH;FS%X@PqToWZ#asHm0ee}wB^g@=e5d_I6AS-#UJTp(^&&nby1p!}O{EHS9lN3E9 z@F+=wj+t0)&DFOSetZ!U{Bl@y*aH-3*4GA)t^iAU5}n!U{;BMClU$MO$BCNe&ft zVSnNsu<5vHKk@?+jS3R32^^nBF}!lKIPw;~+oK(uN{yyG9?B%LXdE zWlZ^p*CmytjMX0kF|Xw=tjYLD$@%+Z#W%1%YcF5~04o*?02l-XU}s&H)kL0|uozUK zpPi!W%F)FV=B?fa=v}Eaj$Sv&S~pPI(Eio0EtQIff}~YI(q04N$0-u6Ys%v$vaYET zWBp>sDSNq+ZF(T-$yJG^6u?flv+AbFF{g?7%j$#GjJo*@fPZZg>w5n=$*;3ElVkNx z%ehNXwfYOc8g7$&M37@58b-HVNIrswFWkx|3mskD>%{Nir7o1+iVe>!x=|Q+a7z)C z+gxJ8eMnaU0sZB+R0OtQRG`QTAkb1y^_w_o#XrdB(&?+~4&&=$Xu{=WInV}^aQW(% z80C^t>Q?Z>nk!jbEXf;U`wy>-)Py~(xfER)I#Lt7RTEsZ74~Gy@Slv$KxOzAHso!f zjg+aJZz+bxqPX&2b}S&$Qa<=<&6PER7#aW86 zj&WOGhJMKu;*st7cBUNpl-i+8PFG;0xy2$d)Gu* z?2`Wvz$t-Crr9glAt83WXzv^yV*OK9i`2zL%;)(?#^*YWNkOXZ&W|CKS qBcOoeBQW98ooM-Z5kOVN_O+VJ*RCpFPyd)8fCVD3DER+-7XA-=-z|gy literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/blue_check.gif b/ljcom/htdocs/img/blue_check.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ce3be02d42bc85e7af27d66b4eb038618d61782 GIT binary patch literal 160 zcmZ?wbhEHb34I>6yCA;&rsO?_tHhl$jOxOf_=4x4tP{G=I-7DV@u~ zN=+6l+=ZDZjaCW<1cq?TJ*&LX;CDvY(dFAJW)|5sZ>T7^$k#5B&lK?S;Ec}A!G0l| zZ?i{C^E-a$qhn2Rvv_?&K~q|Byk|#Oe@3XRT`CtNqt5i^Gzk;^;_1^T6fjK6Elis= zdm@92#?;Q zFXSKQ-gPeh+T9xuTkhmvvb{3<@ymPn-#EQ{zwG1UFJCo}{rvU&{K-o{e;;2ojj@rr bI8~q_Kw*!Rs*+d8qs-=`-92J13=Gx)<6o55 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/downarrow.gif b/ljcom/htdocs/img/downarrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..d035f1ac416f32e0643c1de35e670c1e4b83b866 GIT binary patch literal 61 zcmZ?wbhEHb6ky0f#JE&t*CDsA8K)f*8rs%fyZq=w;-tfIy?a(3eYEVz!?@nP&z?Q| z`t@tdw3Bb&zFm3vu9ib+`}%7t=3YO3{wP>*KD221?mfH1Dwa-Ne|pM>%klmD*PM7< zH}AM>YEO92zIX55d8O3M+InH%-o5P$_eT^=-n(z#{rmT0%4dK1@@4k6OCLUb2v2P8 zSh)Yhm513?(^nn2w{`2bu!70WYpy;3s=NQdC8*pts;;DO-ESbcFe5jo;qjBlG2J_J zYUYMFuTRPEc?ty2p01iZ_tmRcWlJvZ+_@{Nee0LcpW}-rnWRj8|Ni~1ojc1XZq#-N zQ@8ei_3Gu^d7GaM6gn@l!gA@l#OKV#ThcGixPF%}GyLU1JBU5*;X}Ev1 z!j!4gdl;16#R5h2rc9f`z$YUsEupq*;be`-m=GJY$*ULjDtS0s=)3MMVdQdRW93%Y&g25U9%|!@V literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/b_blue.gif b/ljcom/htdocs/img/dys/b_blue.gif new file mode 100755 index 0000000000000000000000000000000000000000..734c583ad973dc5ece5967e03adea0638fb369df GIT binary patch literal 64 zcmZ?wbhEHbv%oQ5D z?))=2<@uUL;lV!Z literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/bg2.gif b/ljcom/htdocs/img/dys/bg2.gif new file mode 100755 index 0000000000000000000000000000000000000000..70fc1dd7c8b955694b69f1e3c1bac577c67f31d9 GIT binary patch literal 38891 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/bg_top.gif b/ljcom/htdocs/img/dys/bg_top.gif new file mode 100755 index 0000000000000000000000000000000000000000..d8e7692c40819434034845186fee3e3244d18a8c GIT binary patch literal 10247 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/corn_ne.gif b/ljcom/htdocs/img/dys/corn_ne.gif new file mode 100644 index 0000000000000000000000000000000000000000..2337fa42dfee8eac943f568e7ed1a87c8ab118b1 GIT binary patch literal 102 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4f1f`6`~LkO5WINt?>`Qp_>+Z^fq{cT ihXDvcW-zb_3$Pe^7%DU;mp+R#YiV#`QxRZfum%7fy*G{k literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/corn_nw.gif b/ljcom/htdocs/img/dys/corn_nw.gif new file mode 100644 index 0000000000000000000000000000000000000000..72ccbcb0d4bd95cc2d79f9b8e1e589c77448e255 GIT binary patch literal 102 zcmZ?wbhEHbWM^P!c+9}?@87@g-~WC3^zZH4e~%yiyLj>6^5ZXFy!iJY2T=UU!pOkD k!Jxwc1RygQScC;w3_T1#&&X|gc8nqKNJh*uNk#^107l6<_y7O^ literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/corn_se.gif b/ljcom/htdocs/img/dys/corn_se.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1132508078b59feebde2d7e373a8d45d3de1388 GIT binary patch literal 101 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4e=lDA`}FDG_wWCJ;6Dza_>+Z^fq{cT hhXDvcW-zb_37qguU*Yf|&~xEDMwUYX67DPv)&T!~IQ{?t literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/corn_sw.gif b/ljcom/htdocs/img/dys/corn_sw.gif new file mode 100644 index 0000000000000000000000000000000000000000..f7b1c257990b594ec4a7ddeb10a6e6495fd13e95 GIT binary patch literal 100 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4f1f`6d-3Am_wWCJ;6Dza_>+Z^fq{cT ghXDvcW-zb_3Y_3%n);||q36yvciD#u5rPcX0LCIYEdT%j literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/lg_crnrgif.gif b/ljcom/htdocs/img/dys/lg_crnrgif.gif new file mode 100755 index 0000000000000000000000000000000000000000..3069c11446fd387256ab707e2bcdfc8a1ce51952 GIT binary patch literal 130 zcmZ?wbhEHb$yqW?0e5z+epkUKu8# literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/login_but.gif b/ljcom/htdocs/img/dys/login_but.gif new file mode 100755 index 0000000000000000000000000000000000000000..2438aad8ceaf8db84a405d602119034915c7a74f GIT binary patch literal 347 zcmZ?wbhEHbG+^LoIKsg2|Ns9F-+n%L^ZCN#HwSJ$+i>Cjf@3!)?77^q`AoseV+jlP z2Ta@P(6iZ~d5uElGJ%5m3~4j}F)}d_4HSQ}u!=AUGU$MGfb3*oy`iAcmy$Uz!^ z^}Yg~^AkMoSLAIz^3jf?DWjlbi$rTf$ASdY857bEp0E;#+I?&5R|y7=?$&^W5C$fW zHm8@#3<3h?2QCODG2YPC{#eQ>Ea1hX%gfcASCE%uQ=t=CTgt$##~shhz+}`>n9s)G zTh`YbRmafm9-mjGJ-Z`z*+SFB6G9p6bmwvKEAi>@@Gw=Z%@^QjVmw$L!MuMzpH~Ba z4dY&RhBJYzW`_#`y*5A4_E%xy)#XrOx;3Zs$iDu?#{Bz3^v_uuM*jHy}*y*TU5yZ>M)j+{cCXsWJk>%OpN#&m7pc&@+m?*G7` za2V-&I#Wq*Q&hF64#ii=5!jE|5z00ohimO=mnmz$h7009P_qN6GX0GXtzsviTV00gVC TvJ?carvjm~y0QiWrwIT%v0Y_` literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/logo1.gif b/ljcom/htdocs/img/dys/logo1.gif new file mode 100755 index 0000000000000000000000000000000000000000..9462af8423f21e38ccacd332deddac3b113f01de GIT binary patch literal 2733 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/logo2.gif b/ljcom/htdocs/img/dys/logo2.gif new file mode 100755 index 0000000000000000000000000000000000000000..95e3d0c4cf1135ade7b6f7831115fc019dbed49c GIT binary patch literal 3874 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 kr6l@@@MFuHn<*rl0?6az{iEf5F*J1cMLO#lD@ literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/logo3-lang.gif b/ljcom/htdocs/img/dys/logo3-lang.gif new file mode 100755 index 0000000000000000000000000000000000000000..911f4b164724a8d4cb8b59b3af27f20020c7cdb8 GIT binary patch literal 2136 zcmV-e2&eZ)Nk%w1VR`^G0OkMyyu{dshK80{8_#bK5<6rD3h&Iu+`+@fWC>-)v(Zs2 zQj=Gc=gY9$;_Bh0YBOe;yt}-5o4u8DRZ0g-0RRE2yUs2`Ri~$_wT!sf)8pi`gGEI} zM029%+s`H>CwO;v*S3`H?CRaz+=HUQkgCVo&cnsg-TeIhG!Hk{gE3oTY3JwWgEoWC z($$cryy(D~#JH*f1$#6zGu*e3Tdy$a@aW7q$n3yk;QI3OACSr|IIZ&RbsHu*B ztgU|zP${khB@r{OxVbn4l9Nc5nV6CSxvV=KCbzf@VI~g6(9zP<#SAOBKou20)VOoJ zy?b~dnIL%J#JK|uCJY0(DJx(d@7?zI(PALDGhlA@`2Gm65N?kOHeEn~i-e=t3lsEk z4VV#ukC%WL19~BIvDJVdUrJ7O|SgAQf2&cqR%tr(DK!Og1KV*L(uG+Qz# zS9VMPi#c!;6YSZu9XPZ&diM`dNqkF%^*T z+=W(kAfPRy@m9hOxp_z;O+Wy!VGH3c<^UOBWT4E8)2K4Y5;;7O10y~biO3QFEMnyU zl1wt`$CFS-Ddhq(3MmE)Qf8^;mQON)K?Yz{kO7ulmTBghXr^gq86<3&g8@M_p(dA2 z1kncxIf#J4oMs|`zyuQ{L4_6y6l&<9g=#@X5r85fC!c59kiZBVasWUXHb4p`3tv`{ zLj?&epsAEw6oG;QPk1211{)ahK>)DEDl4oX7}3K97I^T40w@%*#iOG}$pnrYwg*M1 zbK0;#0s!Di0-Q_)>qiqhSm8kyJPdI_3n7S+#*!z9K}HJ)4Do>s9(bSyu+mCO0tdxL zV1NM_EMNn>Pd35A0vIGT~lQLK<8Q~mvAOQmWAPZ0s0v({>0X}%( zbv(F0A4Kqh%teq8J}mKH!5VK^e*< z`anxtutEV3P&OY0?GS=U!(e=*1U?|a3QxGgF@cxNWros@e0Zjo5cUKL$UqMdQ-u=T zZ~-LrKvzXD<~Wh5%uk-vnPt)e1&jdCcoIShE8xQch=2#Sfis``tYA6)+01lq=?W;= zz#Tw1h$--)o;*;2NMALpS=EYFSlAT`Cg8@14zZIImK?vL+2YaGx zS564369|PUMCl+2jcS5ET{^@#@?isXl<5X;md7U{;0YtOltTcFumK^UzzV)vDpSXL zCVeGSnIGst2R?AeddV*dR&b{bu%H7#iIc2&RZ|f&NP#m3Ag-Oupbr#A0Y&*qta(jr znVjkY3dEoQ1)u;0AX|VKP@skzY^h>5t0oM3AO>TgY-9^?hSEZ|hNR@IYR{C+&xRJV zW1s*U#z0#%prLc>T&-@m95;I}bQgIr}m+_r6Sx5&*B3m~Au<~kPwRZT8(+xNce OTGzVqlbmh?0RTH7%$zj< literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/dys/logo3.gif b/ljcom/htdocs/img/dys/logo3.gif new file mode 100755 index 0000000000000000000000000000000000000000..18498bbc654e204e125e0ac798bec15f4535fb64 GIT binary patch literal 1717 zcmeH`{X5eM0KmWIYvd&(Y%R;ug*z!T$CR$IwNlh1deO@kMrXz1YI)t-kWx`1@9Mlf z+%S>oI2%K0=A~h7rXkjyWs=Y(?&+_%U+(i4e4fwqeD-^haBkEXz!_KqfVH)?<)x+h z#m}?zi*p*yJGDkVJ+4ws%iqpUk1NI|RjRSUA?3`JykDl6d?S}l%U;Qcr-p~5V}s%~ zan8%(siFP}MQ>a8YlW((zGq-)`X%pOSLv`=AQp=yT?&Cj-Y$`8+OkI5d7T~dv9>Zv zM{{HM=#(I@qkUxRkF1tOn(bN8#mRGzMsglnYR`--W7f!R%z*z=h; zY-|sGZ-5^ay`=8fLy>+xSa5JKELj`Jevz(KQhCVn(&9qef$4pn@L=YuSJ1ITP}nBE zl71Q84RJX8@$UkpQb%G+{_fa_+^MIaHc`4#%pzPA;Yj|J6OOWNS*G6Z=q=)$Ia5ep z;LkafDNj{a*fcsJD3oWJe~OG_kw><{j0rCJV`m0+AWaV0e9A=jRk$NVWSzy-EmyB| zVjTQSAQEkultl$F*nVAiQ0`Ca)`Fv$O@&$hE)++yd@31@e15YiqMm4G@kmvERx;oK z-Eb7q!2vyjS@3wh22hAV5>tv14BVnF!Us`|hrWL*6@g?}x-#VqB}0HT4!(ij6hn;e z(9t)`z8^>mgPyQ#9m=TQC8E^dqZiunU}%JcpRdn9R7hzAwY3X zsVGygpMa7FzD8jncv>>dg@)@{(2n5`P>8z21*wXM;Yt-PKo@U<&x@M3NxJRA%?^co zG6h`l$m&Rr1(Zj9UF0gw!6zio4hayUi1hOHn~5KQl8nLz53}$W2pSz3+bExO4yyq1Sf84dcQu5g_>jVw0+2=F;y8B705qLNew(@+{Z~ZCP2IiD+h; zQ9aDCM82j~&z3jWW@xJ>z#3ybAm;JTD-l+Q0hq{Qy&3gG7doXm67?g3J%g}cCa1he z5HN_K3zJGP4B^v1_H3EVaHzg%0T6nOhE1S`_TYyOm=%t#EAe)%ibP>R2DH~ZeNJc+ zBK5_z#0yN4O)+tO9CMnQEHJU(UA6evzQNYMb@wwj617dW`~2GOZW=I0&?>);*~m^S>H-E7lDJXg51-Zu{OX_9t=$~CeQ zDM8D?#2v8{zmUhZ-&paAzvy3WFD4=`^zK+uGX>N*RDp5L%DmWBv+}WT|IV)q(&G_d pKgmLCzAlbl)qGu2rtDl@ew!V!`uSaX&FVkuXPVV73SAJ`{V&5Yj41#B literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat-hiring.png b/ljcom/htdocs/img/goat-hiring.png new file mode 100644 index 0000000000000000000000000000000000000000..61568fa96561d485db5e3fa7245f7239375d775e GIT binary patch literal 9440 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 udj$BstL=kz#p#@cb{yC&XC* literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat-irish.gif b/ljcom/htdocs/img/goat-irish.gif new file mode 100755 index 0000000000000000000000000000000000000000..c3307cfd90e38a55e21aba32b72601241b50e59b GIT binary patch literal 2157 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 I`%drw05Qi@B>(^b literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat-newyear.gif b/ljcom/htdocs/img/goat-newyear.gif new file mode 100644 index 0000000000000000000000000000000000000000..a49d7383cf6cd42b930f4b10b93d8b44d39372be GIT binary patch literal 2324 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat-pee.gif b/ljcom/htdocs/img/goat-pee.gif new file mode 100755 index 0000000000000000000000000000000000000000..dd0b37033b315e809c65566c813721f095ceca35 GIT binary patch literal 2985 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat-val.gif b/ljcom/htdocs/img/goat-val.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef2df2c1f9f7fc4376d89e40dfde5299df84af45 GIT binary patch literal 5266 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 ihCCHqjZ%Ee%Z57z$X}|Tu zVXmx)oRj596w$8-g=+o!Cw`yT`ww`(-XB|go8#u>D?l*N4*-Ipp1c6r4(ss4Azax>m znws0EPVJbOeAUguWC;Vc^MWhZ-nh__r=xP!wHJv|W!gtfJ`hlj_=$VhNd(DlH; zq?nk-vWk(8_PN2q_YB7N>C+t@9qQ`p0)b$2bF-$VCMqflgTXxS>=aB-3nnH6V`Bmy zZ-T=yHa0#4gHb|5U)0yX85j`E&2hTAMxH;P?eC}4=>P!u`}_YD5HQ8%=I7_z*x1~r zP@X(`#Qz=V|2(xlum}L$1@wM90GEG%0!RpB@5bMwCeZHF6O)otQq$5iGP52qvU76t z@)-aVC@9GhDSucYa=)m$xU@EcAsbr zfUu-Wg#R)S^MPCfCnB-Vr3>G5%CIzrla(%<*d^`ce0trbu^z6Jf}%M$BQs6Kj!+He zmAdx!!w#C?__QzvdYFC~OX&0w!_Z->mb5ul%L;m?hFzBS`5x-x=sC-R2?h0vTB54c zHA>gwGL)e`U4KEzO#|ZAAiNxWqstXzhfs5?a(SHPppVrhvPTkhm-|Vocsk{&FD5xB zFGd#@81Cmdt&V$(eB1e6GS}e3bJ^rmfe@IIuhYfAru=n(HGKUj+j91Gs;+4}(!6eW zCs-9%051D8+HJKp0{8tIOxZ5X{=w%+LHX^yV9q}pXz2Rn)18l9tG+`_!B~#!;tQ0& z1Lg77zsZqA;+g5BnN1wK_uLH)y5IgfIqa~H*^D7m)mOzAgt#YL<>>?ks;ZumcRjjutHu1Kj8bHrUi+LnXLhCVuy%%kqLY)zFofiQoK z-Rn3T%SLM>TM|m?kE0uVQw`dNTgk;*9|rZJB<45;kjzcuV&q8ZOZfpCAFMSv>~KWF zl3p{~ll30GL2;gfZM2QAC72-|&D%~rPci~O z8pbgj-pFqiBqr9!ByGXaOVU)BO~cNyNtq75k=NOZzkEt=MxQ>`LAfq|5F35Hh%%nY zFIrEG%uO1C&x^j=d}&JesfBAzv9;l$NxTZK#-o|ZwslXt%M6h3mmp31h{D2AC$SpM zjy9+rAC3F7ovY;~9bhU~4%+oAK3J3QPb*Qly2quzZ#9V6Hlh?S3JaJ-mARKqn#wT3 z%B|i9cV?-@$1F>yw_)4!?HiFVwo-X=H*jZ~{#{Eh@p^?~UA;t(iqa_X3HP9?;W&g< zuZxfCR|^fG!zW2=e7WN`93G+CjMP1QX88}$I498D*WMj|T#Th87GSUFJ-^Hvf6_N8 zc6$uy35th<=O;ADy3&LI3Pmg)p-xREIj1fdnTp3@OtbkZ%^6M4buB_6Z}`J%X_t%C zK7DjIeHM>G8Rd6VQchMRyG>=qLta543Hf|N$bL@7tI|f@q5{Vf$wB%DSdf`9MzA3a z(>Dp1i7Qfkr_tY%J^hI$K6%9QzD19miF%;j>8w96Y~dyDG_Z2H%0U*azrXOtrI1kX$ z7Bf^)0?Qg_4^hLLR7c3hRLL-A`2n|LWxbo$p{3~xG255blFH4P(Mz+c@aE}ha)$ga zU<)bRD`xLMq8XY5(}5>cnT7@Bx;|9FDqBN`d&Hd3cOazj<3AZa)q|0&>rovaQ)O%) zx70OmI{eMyIWB!Gx#HoTn@vyUUK<6&FT|y9EWpw42eRSi4CIMsh0so;;<8YdZoi2p z-6*VZ+S)N)L~JM|)&WG*JcsINbAB6nPuLqu|2t$|ZS~@2b>Z$6~wI|X!(vyS`{j}x%gQD-ic;(b_DE4z{`harHNl* z1w>4l=tz*`vuA%yl_T+khQ(P=CeCy55?9Wh0P8r7N%N`e3pGgF1*eFJ0gU_@mko;ax g)-5)P_p$Om2ktLx<(1ErDKk~qe0&lu0N~{R0H@?n6#xJL literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat.gif b/ljcom/htdocs/img/goat.gif new file mode 100644 index 0000000000000000000000000000000000000000..0266e7fb1d10ee4542e03bbd5d7e4ace942f53af GIT binary patch literal 2668 zcmbu8`#)6qAICq6NF|a=+vb+cMoFhlS>rm4h7wZ9CYL#kEh4Qb?6fYUSmm}Iw_GNf zF|xia%BpV?Lr3OIk`#l@ZHr1W<1%MI$G`CX{Pupl-|yG^`F_36p&zzCc*xfmFu@oA z1o?1+zz6~*2!tR28R0mAV+4*8I6~lnOky~JVFZQ}7(!rxtVMAG#RwE7P=r7M*^1x< zf)NNxAP9i~s6+sq02l#K0w4r{0n~=lPzyH0YCz5*ABN*7jw3h@$gwcOFdRd148bu# zQotmN;V6ou2#x|03f3YRj-WV#;0S<>uoVXw4p1B*IDk_jH57x;kP>3S92^X_p)}Nj z&465pjNwBu48br!?gz)h2t_dz!B9Z13n^d{K`{iu5CFG_P_PyQCW>2&thMgod3E3v$50P#a1E@pOCb9`6^`XveBgL%ifW#%XW}QSl*CST81WXvdlpW zFH6JE0bU832X~qR;4J_R0Pq3e01yd)I{-8QbOBI<82?9lYHI53+qVr34SYVI!{J0m zM!LJZ(`YnZU0pRbQd>u+a>O@)sU69R2-2n>K5`7`Naf`Km;pvG3&_6&D9OOs>TM2x zh|Moc1RjqgD+?Ycsp>KE9IA$!qop3we|kFyAEmOtOjL(=7Pni#R#PCNU{iy{9I*NGsb9ytPo`7Y_2TdyRNft`x+`zPxqW*gN3y>fHRoT< zjf!$*+NQVVM``TimfA@qBivktT`fQU^5gSEE-bxaDXQ&Tp!xE*8KFdE@o;r~VbUV_ zj&e2s-3&L%X<}rn_1rk+7?W-FidEf^z_!8ckfNKugf64mgW`o_vxHf#hyi8;ibJlzIS!M%Q8$U#T>eq zM*gtumvcg?t4-STu#9VcCj{X6yo+Uwa=eSB%EB&6xz3;1r{wO`vJ=!3@y)u{0^LO8 z3;e{o&TEFD$)}H@?5FK6_g1|6sYUavQJD=}e5doG(V<0ON7LIu8C@QMytEs!LmAGe z98acxUm)=|jVKA8(5Kk?*X{OcTKZVB$wta)4D7#z1a6o8!c_C1JdIL(xXn;tPVWgR zE2iitHYpDr2#l{}_FUOp!mJz7?DglqaqGMAXXAudwCU(MtwhSHDnHK;)Za4-!q7y= z9$x7;{P)q~to*5rcyVp)Li^qYw;G0A*RHPVI>JrBkR04*`uX0p`rz?d^Y>hS$lz4r z@i4ZL$*4Fzw$q|&M!q^zH2rmHlD7{!OPXFalXCT*kL~k?kLGzw*(1XEKoa=(& zhJte;TB*62DP2$3|5BxL4tLD{u;O?AyBFnw*{_xTlr=avc=6`SH#0|`Uoa+awjuG# zF5#+_-F$gn6VV#l3L;RwgVpjAGt7t40B@d*dfS_MU0g#&c^EUeEzXVmOGYZa@>&(7;i z^$NvC8e4}YjNvD&?+)N5%}k^u3bf6|%|-^B{-b;KXT8Ft3gL++oxIY?dduCjCb8ot z!~Rp&hQFz?Qw?1Cl5yIZww<0uC3^pxnn(!d$-0wk!@F!AC?eabntyuT6H>I|IPEBQYL!?#+&%jC`Njo0N&`tfKRPwe8x3+EWZx~I#5I?} zIi9UuJipQ`tf(j7&##JpB%#Rs;?BrLyXR+0_muCDUO&CYPM9cE@=nT`rccFZw7!^l zB23P--&EVts{OsmXw;c#nX8|HG|1Oj?hgwe#>$cdq0L%3lQ~Z|cwnC&j@p}ke(fN$ s!PiHQRmRRc&d>tX6EZ98*{eDPugxpt^tbM3wzt}R>0xHc%Yz^O1t7K^l>h($ literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/goat.jpg b/ljcom/htdocs/img/goat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4e4c9baed9bc17c1d16685496686d3aa96925b73 GIT binary patch literal 21823 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/index.html b/ljcom/htdocs/img/index.html new file mode 100644 index 0000000..e303092 --- /dev/null +++ b/ljcom/htdocs/img/index.html @@ -0,0 +1,3 @@ +You've reached the LiveJournal image server. + +

    You're probably trying to go to LiveJournal, so click here. diff --git a/ljcom/htdocs/img/mood-local.tgz b/ljcom/htdocs/img/mood-local.tgz new file mode 100644 index 0000000000000000000000000000000000000000..79f3721bbab6ef242b29944f3de7a3c9c62489f3 GIT binary patch literal 25056 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 H02l!Pyn+!Z literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/overlap.png b/ljcom/htdocs/img/overlap.png new file mode 100644 index 0000000000000000000000000000000000000000..c094812b22fdc34809f3ec8000285f624f8d6f8f GIT binary patch literal 7209 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/phonepost.gif b/ljcom/htdocs/img/phonepost.gif new file mode 100644 index 0000000000000000000000000000000000000000..693fd72e874f01d8781f1649873a688a7aa60e79 GIT binary patch literal 234 zcmZ?wbhEHb6lM@**v!LVU|_KC@|(!WNQR<43?a*Em){f-5h*S%-m+!OvuDr#|NpP3 zs0bt(U_kLF3nK#q4}%U!0AvOO%k&AJJ6G*3J=Znq|NTXV-kTJuiXmBjD4GpF>@;zEK9)&LMiS(pF- literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/phonepost2.gif b/ljcom/htdocs/img/phonepost2.gif new file mode 100644 index 0000000000000000000000000000000000000000..377aafc5857a3356ce348eddeadab450cac3c10a GIT binary patch literal 456 zcmZ?wbhEHbRAx|QI3mWdb^GT2{{ELQUj_sO?7RFXHa2$4mMvGVTyb)8+O}iMu01<; z?ApG4=hn!`$US>^F@!AJv1?oH@|(||Ju5CQ{{R0!10kUJlZBCiL5x8Mq!45$1MB|< zs(nu)=4Py#mwG#_P33$^?9LsfQX%gb@0<5zns#X0p7~l9I+OZ5o+egV{A^n(W8!7$ zD3{={Rmp}??a1`5=d}VH6WecOxhqHXO$ zje|sIurhDaEQTfJ^E4P%_N?LOV_?=<7E!iYWa}&eu3fvM z)P+x`iSQoe7vMh1xFPH0wQjqf^8%Mbmx-Qay57Bcl>pCCR(4;D6A!PIHE-d3$td#X zs_>%^k2mjBXMJ;b@iOK+yPN;Mie30DPu`~eQ~*oLp$oH|J3fd6)f_y($hA<)TA*U hmwX1fuToqaSGv!gwc_AbZQiv?VI8vFi(EJutO488z-s^i literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/schemethumb/dystopia.png b/ljcom/htdocs/img/schemethumb/dystopia.png new file mode 100644 index 0000000000000000000000000000000000000000..afed72ca406dd90e17e3438a092992a2ce2fcbe3 GIT binary patch literal 35617 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/3column/comments.gif b/ljcom/htdocs/img/style/3column/comments.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b0ee4c9f1bc12b496a14fb1ff43ff26be0bdd0e GIT binary patch literal 973 zcmchW%}bSG5XBGGB9q8WgFpx~3ZoV_BuX2TvW$p|G$RO&8YrP6iW1tG7rcuIi3$dz z4=^x6Gf)uPB)PcAU<5&JU9@c(w3^Pm^*8ivF2g*}ncq3{-lN@JZS4bFQHN3dJpw3T zfCB+mA`pcb#37MQ6{tcD>d?r$CNPB=%wdsFUEm5gxWj`=2tg>q5RPC$ZAw#%k9j+C zP97C85f_OZ%Su($L|rtJf=yE~6LYahDBg7yH*psaGV-Z}N|=O8a4M-OMrcwJi#-me zHl?Y>$B~Az<}p=Qjr7N{tjyG0Ez&M2*mP5O^`Lt~@veqxxCZSp4`T8)+&>^WQ zMrcyM=1RMyVAH}am?M*B0OaCz22Hn&l6er5 zuNeoKXqXO3O)*0AC9%lC!PKU7M9$q zbUtkCnb}#HYHBSFqw>6aOUKG!?a<8q^391;Bg3t0Hr}4=KU3N?Ui+k6Gg<$3_vTAq z7alZ!o@lzUYw20fjw8MMUtZjI_5F{oM-9`DFAttxJuufkxbo)0-GP(icUpeUfB3T8 Zzc{k}=X`nL`lrR})#EQt4BhI$!9Sp6l@R~{ literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/3column/editentry.gif b/ljcom/htdocs/img/style/3column/editentry.gif new file mode 100644 index 0000000000000000000000000000000000000000..b24fdc5c0e006b160dc6fad78d76eeb46a1e6221 GIT binary patch literal 1018 zcmchW%}dmA5XJ}cklkvfL)jZBwqb$|LJ}*sMXmH=C!;7qlZjqVDO3c3bO>Y#+=LqI z;6Ve$MGJxsol1ITl?KS%&$3pZPq`{Pu9$p}oyr8>xzJ z)8E5HLZn1S#*V3= zh8Unh2`uz57}}7A79M*TiW)~nOvJ+<#-dUcHBk?{pg_}9%)}h-0foEbDsJMihdh9Z z*N6lD0Re}gh8UnhiL2niU}!@cS{}(o8#RupdISl77>mkG&5GWS?uvi_h* zHX8d(mK0D)?y=q^%3w^=iESr_13B>!%TKVvK{5%__#Ch$ga=O;l}!8hIsVU|9lt8p z5S6JuhQ@z_)|P0hvN|_CvY$%R>F2Lz7gII&Htc$sTmL27(Yt&mo6X)oIFQ=i{qov{ zb5DBO3;mNjKcouz(n#%%w-?8Ol@&?B3&BX)LzJ~`+k1@!Rb?(#^K9F8{an9ed~9{Wa)8k z>Fbv9y0N)DA8CG?zItbFv~;tf^Lp{)-9qEk*#*`s$KSkI?(3{94sD(3E$1KE#L$77 XT*v3C@`=@B^sM*W(!0&At+ekCl)`Ki5R#Fq;O^-gz@Ye(g^_`QpFsy?BFJzCmK=kVo~v13zC2rfJWir1Nt{I{ zGOJNx!K^4Y_fL669{j8_>6@9)f1j-=V9TF*Acv2M#iijVBcEDZ%R`X~0fpCATPT+C w9gtG1G*UC~=Ks3mjosm=uN|*t@1Om@wm@6SvRTui&5NPCr?;=4L6E^306~ykK>z>% literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/3column/leavecomment.gif b/ljcom/htdocs/img/style/3column/leavecomment.gif new file mode 100644 index 0000000000000000000000000000000000000000..71beacedd5d0e5343147a9c0f29c5e20da81fb03 GIT binary patch literal 1034 zcmchW%}bSG5XGmu;T0@QG%;Fea-~QKnu;QVL@5)AT3CS^8Zj2_qE(x`kbMb}1=d6h zX%SYESEUvbL1v;dL@vrcD9DIv5!Av(tLe;Je?!maGR*Uw`JFTG-Mwem)@>atshG~w z-@`;gq(nyKgo>G1h?UrgJ(|KKLZT!_;&E4*R7jQ7NIjk!lL?uU8JR^>GJjQL0IdOzpnT^?FEGiKeWib{H3N%$%mDN~1pm5iOP1%gi!HB2q!mjMbj;WxA z7@$E3Ec7rK+K`489(x#y8b?J;#KRxPqEZz#Q4hPIK+{yr#2oGcg}dS^ZsM?qJb;PU zhy(rs0f(T57@$FktKh(3XhRxW9?3-;HIAuz1POl_i^@#Rkt^(i0!?*OM~+Au0e}nF z5j5N)O5_1dyha>gf?+rWHN*gom%suC216Ut9xIC5Xrsn)Yz#rdAI73G_gG-E{-8)U z8v9I^6i`X-vEC%gU`*19Z6}5UIq?w7Pq4y4G6~Z79Iz#X2TvH4O#Ama{?DI^->D@; zZ>Tzk#(#p+Uuh_RbwjSdmgaKnTBm;AEKQ}ya*YFp70-I+QWfnT-Omf^i)#+IUPx#A zubv*X_U7LCh6CL6Xl$~#`+8sH@bK99;{CSs^^uPgRU@D3>PMxv`c)=derws%w@sT) zoLj!3y69B?_oDZkZyX%hvM`@{TGF?#Wc+CF+7)XSU3_eZrgH;zsfNz{@}80({w6N(DZ})w#J%F-DJT?`o-nynbCKno&3ZWTIRkKl=a=e+e8~XXY;c6np-lJ+0uzK oZBXD+qZzC3xS``fD7`VYq+?mfGstn1h3scY-=3JYobAK3P?;s5{u literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/3column/memories.gif b/ljcom/htdocs/img/style/3column/memories.gif new file mode 100644 index 0000000000000000000000000000000000000000..13f1fcf46e590b0dbfc405f6fe013f8da9a3d886 GIT binary patch literal 982 zcmchWu}jop7{?#bp(}@ql#C**LE#*(9zBX{@FeZBA;&Ts6nhY%twEQlBN2h^OqruI$E+si1}! zpg{>N^e`COkcJi>dl-ruM@3A;!ym??QWZ5(54)g1(^SmF9PR;yyW%Qt;;@H2fQi?L z1O5R4hoFWSph1bN;J{#LLmFBh$weDAj;VSC34a)i%1q6XE9`;-O?6X8jz}5-fD6|V zG~6OeH5>!LbOf2 zF*N=YwC^3g%^WYSuNJAXKG8x0&o>tiwx4>kom(4PY#g0=GyAh^<8fPIaOM5d>3p{5 z#9DoKX{t1zZQXz4P|vsitJ&OeU7O3@4;mvkC#%&LBhyVp_eUM{ hzo>(!e4+9nLq#l literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/3column/permalink.gif b/ljcom/htdocs/img/style/3column/permalink.gif new file mode 100644 index 0000000000000000000000000000000000000000..f14af37a7a50de23b7a9f5e2305b697965bbc17e GIT binary patch literal 973 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 E0{j*GQUCw| literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/content-header.gif b/ljcom/htdocs/img/style/cuteness/content-header.gif new file mode 100644 index 0000000000000000000000000000000000000000..79da70f7025bc0c2bc84ca954c99dc5d13a1f733 GIT binary patch literal 6271 zcmZ{oRag@Y`^Lv$j2JRsauOl}f}qqZEhWl}pi(LzT_PeNC`t&UbJ8(FKx(9fbd8P; zK@4ih=+UDWuzm0M9sJM!_rZO5U)Oy-&&mDMH@K&w>c9p330MOF&d?L*O(PV{Zz_>| z)`lT1AJez?Nh_P@y7CC#1EL)7?WF zl}f7}IHyof*VoU<BiCN z<`H>khqSp#-rc3_?UA>)NgErat*ui6;dJNllyF2^KPIgmQ%Pjf>hXE^IEiq4c5q0> z6G$t^r^_p(rIYi9p|gL}@Jp28AJqMW^RGiR3Y9jsbh=HX?(b83#;L@8TGzi$r0x-E zW3#7(9opJ9?f8_kyGPyIqwMTbc6Z6RmD7LgZ*7w|Hpv?sxal|>!*8%bQ^WLE>>E2eySmXmy?rqjqR_`uqZlcus73$x$sa#|{qD86GJ?g8J{D}BT3TLN zU0aV9otxht^_n2;9~>SX7h4GKP%w{0Pv`(fHtv{`-mdUb5wyT?ZDC(@7n^9V#VVjb zo?p?O$;JD#eu%)GI6;FHW6eZK)impodU3QO7ppl+8&IN~sp7kt8|5OTE(t8I;&1DX z1xRv9%iu=7mj8I-b#f7U|7*qfV%~iB`O!u${_=+vaYENi)_US>epJ}ZvA{Kf4)meX zyfEmEx%T%zl%~tHYZiD|lXe?&nrjzxug$QMs84m^4VIjSpE~wmwgVDi>hhI|a;xJ7 zpnI>LUujtTn0GbWcI;B#BiF14&!YgXjXQI{^$5~80#ABa3}3Tf{uX~Sjx|GNE7d%b z+FzfrvvgICd>zJZ{MV7|pKtz0dw2sIuQKahCzoF?zR$rT9n{lYW8bUjX<#$k>koTo ztlixq|NMB{mt&WEgE2Dz+_}FH1`$>eRwpA$wAGo88gV)zw@`~Ao^?ear!9HL$jEG- z;cqa3Qj#!lyS#*j`qk{F8T*QIw`K3PMy^7O6CrLV*N3@N4|#g#-NatT&JShLdAZJq zvw*Vo%k#E-+1=jc>do@zJrPl^Bl9fj zFlf zZAKu4?BNH2xuvtFEc5cN?%B{RiO52%Bx7=r4c#DVfh-mY8+N9r0&Pr1SiIv9DHyfEj^V;~GwqwF5{7? zt6QGRtSn4}uq)mGc)OI|zkhz^Z)34`h;6x1Q{cBbL&m==5p^!Jw-D3NVs(uVS?lBPjGh>7q&y6d-t2NT>}1QQ;kvvc7mc8v@rZZ*>}* zwVeJgSnzc!uTWCyjZ6yIebl2ti1|C`lp*&l)?DrZBVZY^_-EV%!@-?Un4^RD2+?lT zzwEvxA)la5tE^61X7*Grrh!z}Jf78&^@y~{Mg~;3HnDEnT>%8lK9BQ&eiS-eGiDqStx-%;C{oP}RPYO&ddcXiCw&#}& zQG%z4=hnIcl79^#rdR9z^9inZo1Mj;jfYq? z1wfDJK+G;16JfH=v04yjvm2dMLjf%~)>$|rg3DYR$W#D&aZ?(|3J3GEj3A^mOcb|@ z4NAV+Gf>MP!4{m^X?~VNmKnZqG5#f`=%omdy;q!Mxh~6JL~R#ye0rw|n%lKG!NdLD zWiJTf36^QZ#e2V?Px_B$f%o_uHIbD1ZPcY}k|2hbhP(AI!E$%oct&3LJ;t;M-p7=g ze&F^k?9SA4l6=yZ*cbQsCL3JaAw<{shu}cWlF_zfepsDxjeSCIss~w9TP4BP?~#ePtKHMu zCpe+n=pFu7W`Z+_(Ho5J6*fCMEZUuNUAzr(DN@{g_P<}gy4Bpa!+o88@EIRgn_^H7 z=VijfLHtjvB3y>dT_r(Tt_Q8#F}n|;nLy3KS1{q)n=D`OazKyffFX`O1sQ7Q_#n4B zVJ9l!t?raf1Q5g%%h<( zx^#h!leP=VD_ANuIqu#a5DQdENS&lbs;-FbJ4**tlaVJa?0~9e(iVn&vPHb(e8bMT z$O#&Z?-hzfCpK?H@ZBM&hq#yG+vZnZVF7NyOT=Qbj6Y>-<*N1`k(R?-Dk#hVZ zjA*F73guPej)CS;9*xRf6Tdn>t35Du_ia`50c4IKB@gZkw1Y_u_kGcf zyBCz0MimFITZabqlz3Ism%h30=3KG(hcu}G!G*4yK$t}sSpFV!D^TfS6^hkn7V)%^ zF6ggwWPPvf;r|*grVN4xZYyl=?1#r)fjlL`vl)r}(GAu;y7@72bXaJ%)(UPOaMfvW z`Vb!sXR;s2`Mx9bT4Oaw=$T)DHX5(c5?gY0zq&1`4**1@#{Vg0_OrM7d96;-Id+uf z{rH=&X(Q&8@zpziKDAG7bVj58#<3^NV>`l}s42617~`CU9LW3TeDTKLN*z;l3GqR2 z@ii~0UtZVp33ARt+xn-CYtnNYR{p{w-*?^O<4r|Ar3PaiTY!tA-X4BmY%kaFWC+-K zanfHiuKCD+-ud1~XL_ zor#pEYRX=%|8shKLMI zI(dQ1DdI=1&h|uT>`=s`>Bv>Ruwn-D?TI%}R4&BznpT%VtO=1GS^7RhIv0z~TqG|T zG`%*<(qfv93K&-VS_+|MTE{C#_u$`SpbnEi0|T>SJeC!r6eHrqVx|C3nt#d7L*a4n zV@(dDHcT&HV~PCda#AxS9?$zVj5 zB(uuh@Ok2kDH5HXW17P(U2A+8@ra=0P2l?&qqfY?5fS5C{XBLP70v%6ba#j&j5qNs zJY0fHcHTblbU3Ov3uqw8d#xBwlY}6S`Tk}M0nJ45#)#*lyf~yFp3kk!#Y4F^A{3@g z2+I%kQj(`x6nsK&Zjh2ir=w}7k1Cu~dW@qn+V30(Q)~$ctx(Md-vosXwk`d{iay9m zOzLeyN<#8`d2(tuG!0BJ6md%v{U=^s_0_gjaWtr;FO8J^?}Z&;>}YUUfuOh5n3_sGnE*36*R4Esipps=TQGvVg3o=69sB?7Cx z2$1%f4*p2aN`fI%RFP?x$P9mE7804=ip-rsej+0aVA-Elv-4EJMWv7z%2~4f8LBA6 ziUgZQ62MP8`>SP6lYdSNGN-LIry~|wy1}KASzGmUPitM5Rc4f4k%#BE@*1a2Q?yS8y|LFh#(#OV_&dd zC@A31F1*xMm;y_3>bW*WE_gijF=|BOqpDLLnnAGbv&`)0VPh;3pWs09s47)OEH*7;0Z`S$vx>CGnb6k|p>I%?dUy$b>QY)&c@+%YtUh zf+=P2OQI?(GzFIBQvs&h76^EOA zy1H?v?$5JkIWSFMQY^u=`>d??NPnN&OYL=nb9F&hRlYqC>6zM!yPql0x-`qWRAPB5 z5+F>imlJ51VXJ@M2N5=?KPai9!s}CCAd&&h8Av7t^{;x*zLsa#`s|DT726;m1JzHz zn+5}9;)~OzDv|;iY-^dU+8eFs8f~eK_5w|g>P^ninp^{$+;W=S+nYS*nmnmZR)LJa z>mgS$UnN&dt)=+bjgc**EQISw;16SldqvE}0|M8|%|m z!H71d$hnqm_Hf0d`(drE6_HT5B~p{hlJTN3#)=uq-d3d^dL7Nb8y!;}Z}geUr=f;) znPIW8N5;sETtd^sIRP?iljqGJ zongs}HAL#hqblP&S1_LMlhUxp<*Vu%OB6n?iOw`)XDX~Kimh`iu)C{?@d*-GAK$GS z-n_luMO0@!kVYOEqGa*iY#Od|@Gj;?vPvzyF;Ixz2JnG|)=zMPWy*z^5Qbs6+iC)bFQ-2XAv&^n5 zXSLXZcgjJ%$;Rm9*dBOWua@9Im0qXSU*ZXsXqG}pE_h$siypio>XOWWBkrzFP%;J@ zzba5eNlMbI8@LZ)HG&`?ZkL^?5Bgbanx9p?d)(YznMWPq52OqxLWdGnhdu-h#aL?! z3(A_*f8BbP?CabYn%l?J(H9!P5Su#^`UCA+1yQi-xTR(jTsL5?fwa}=4sT=1?ie*G z>bB!ECmHrBO7a!U41d%f{`g`zuwt~TWAsZU?9`_dZK!hHuP+rhpmsJ8Hj3%28u3ri zFfj$WX|#i59dlE0V{^grMzLpdV^uHx+57m5tw&S*N11a+@g1Ww z_Lt1X$0nbR@ec4024PEcv8WF0e#hweHs6}dIQk`skPFmm`nD~I+{N`11t+ovnY0~6 znQylT=Z>e~%4V=EbGWgEe|Jm*Sl3$gqDs3vBxrNHOsJFPve0+Yyx|)n0XXl0Xm-yA z4PH0&1P2F_^Tv>z(2p2gD>7LFM+60VlV+^Bs<{$5GN+q)#k< zd^D-}PTh}?*~vKKB;diXMWgRL9~7fyZc!R8-!KBX*?pdl+V7I)iO?fxrjnK&2yCG7+;Cc_USMu!FUDgWJh4 zqBc#L+Z!G#8RRJ9cAWyjuLH{;OV% zMoFM7VhMOMs5q344)=MRJiV&?@U zn>k5iDNnou^koEI*rNcpEWkfyOtyHfD&R7f{{p~-JvdR!*o52ll2R?xU%P+8Aq$Kj z7m>MOw;KWvjT59A=sswEX4Y3CDYvbx))vlyI2f^?wS`KT^ zFARk2E{E3O%7hjoYesBr9qNu}MUob}B$#1%ymsHZ-gm|{+l|M;8+&;h(p?*`X-mF0 zuL}c!4rqdyE64*pVj%D0ShpNnv=%nH7LH$Qm)WY)nCQF$GOM+8A~2+{P22JN*x|Ph zmVX6bWURVF-`?5Tl)A8`TeIC|w8d5YM7N3aqR5M<+CXM|z|R`Ry@$Z3M3C51J0VFv zT{N(7d8g^ssxV@8#5oDvvV=YB-!cmr zx!T2-X#i-_ZcmhBpu~N}+Rck!4tKW4Z$BbvEnsii6F-ZAc#V$~zd)GeKpf-zI`Bgq z=L12+fm8K?mFBTuF8DFs$}|Zukw!cOf_Ov#$KmF>=$$IPlVOfs?VGz^H7EPIV4V6%$9%G+eF&qh7s=H7Hc$i*tHt$Mi;^!3;MKkz zWyhlg*awS~Usr>D$Hv|w$T#d(%0sA*jTGBe%HU0w;jV+Pmw)&}8Fdq>gLFP!W5%j( z>chPWW6tlIm(S#@flBtrLm}tVP$oI_(VYRRtJjR1?0NJ&@K@sbkSvpu@lem|d2q-o zT#LA*MN=|9TMPMzu-C3ONK;ST;N@fq3=205`G0|J@^yK2>Hh<^B^pXM@)3sNjZJ|8 zt!?eW{{yy0?fnMLjgj@E80;AC+xW!4#5P9eR#ElL?5yr>`RhNw4mI`n_pB58R$B*` z14n-TkJz4^Vy??6PS4S*bUe@idI$LiFpOFmb+x(XCi#h+)eIAJCS6!?dOdRU= zP!IU&rbGPH6VB=@Z@p0~*zfe0;%KfxL+Jy5e~a1}lcM#H`P$*TwcmZk;#2q@wHcN_ z7r(U{{H^`{r~^}A^8LW000L7 zEC2ui02Bfz000C3csJY~B+4m@y*TU5yZ>M)j$~<`XsWJk>%MRt3sXHg_@L~3@9(*X zjUp==kI1BQ$!t2GOxmy(Z2Yd*>Hsn&RG{FncuX#v&t_>iqSayFz$$n8MceQAynfGj zsn>0Af?9J!b$y75ii?bmFMnNuf^URthmM$;nwy+yYZ8)^S#p-0rl+W>swI$9p`t#O zU6-r1wzs%_twXP{JhF7T!o$SHO}jR|z6!vG#?R2v(jv%ITFbGdv(wz&-o({6*Vw<> z!QbfV>YCx8u%W{d1rPd4NaUf# zix@LR+((Z8qJ)JRLyDxgu?oC6K??aB$+G3Tl0iOv>~a0ch8=Xw#})%eJlCw{YXO z{R&nhEV2a5%H7Miuiw9b0}BRB_mf>wc=Zlm%($`R$B-jqEewbww#1S%Yu?Pcv*)gq zBUwi1vxef&s8g$6%{p*sSEDDEo^ZOg?c2C>>t6brSM0m9CDh(cytwh>k$WfmjW~E& z-*`!mrQ2 zzyHQl_Zh_8B-;IF;DHFT72sh6?w8<$5JpJVf&&iXpoAD^sNql)x_8-y8-^(2fgR?T o9f%{QsG@o$?xY`0UBtKIj5I>mA`UziSmTa77I&iqCnW#?JBWp4SpWb4 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/entry-bottombg.gif b/ljcom/htdocs/img/style/cuteness/entry-bottombg.gif new file mode 100644 index 0000000000000000000000000000000000000000..99a42c39bdd8e861f603f7d4aedc941bf2821505 GIT binary patch literal 1744 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/face-cute.gif b/ljcom/htdocs/img/style/cuteness/face-cute.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8ff696eb28cd53b213e55ca5c8de6f82f1db765 GIT binary patch literal 678 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/face-japanese.gif b/ljcom/htdocs/img/style/cuteness/face-japanese.gif new file mode 100644 index 0000000000000000000000000000000000000000..73fbdef24b453b34d98b3f73dca4c4077489b665 GIT binary patch literal 909 zcmV;819JRFNk%w1Vaou;0K^ag{;+t{K>Hfsj{?6O}y3GIZ z^#Aqv{>j(>+~)u0?f%o=|Ns900000000000000000000000000000000000000000 z000000000000000A^8LW000mGEC2ui0LuWy000I5AS8}tX`X1Ru59bRa4gSsZQppV z?|kq7z@TtQEE41ejE#5D@qSD9{}NfCK0mSQj9nyM^Tf zBycA{T{#5;C|V?kk>b5%1sG&>#{gms2l_t$77K8Io=X4+7RbowZr@6WFX>g3(a+t# zVl8vN95ACGfS3Vmr3hS7t<7%a_6bOz3*zNQLQ`Jy2`2Tv9hFhGF80Rd1EY0X)H zhD3J)*q!&P0Ao?+PpB^f6y2|(Zf6$UEC$vpLBG2mVZ(vw*g|Lql^Cb}U7LjcwB z5Wq-=^~Z@)7q-w4Ye2ZR7k-@BhFDh#Z3u*XYps`wQVXsi8~`c)fa6l|X%f^OhN z04&~UpHK0J_x^A}^1XW#x8DE9|hu7HjOW j$R?}ovdlK??6c5DEA6z@R%`7Fwb*8>?Y7)18v+13M~|<7 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/face-square.gif b/ljcom/htdocs/img/style/cuteness/face-square.gif new file mode 100644 index 0000000000000000000000000000000000000000..782d30a662ba783629c0919720894248465a84f1 GIT binary patch literal 704 zcmb8o=`Wjc0KoC5Q`FI<6OzUdGRbPX&8Vf$@dgtSOO`F^-b`F2wJ<`XX6C4~jG4{Y zbW_$@)j2xqYPCht*0rjl?K3n(pISm}UGiJ}3H!ePcIR4*xCmGK>w51Z!`*ma1ikvoj)OK z;OSkLoc^BL&8HnqWDym)nLBhoQiy;lc2*40wSJcKWR4cxuH@#%_E37&ygd0)!KAK_ z9(TP}VH_%0d_1;e78J(!ZX##GA_Zar#m`Gh%gUJ*l~vU>wXC}O7Y&Usn_e})e$(={ zwe8*ecJ_yl9h}atPu$PlUwA$I-oE~U!J)6iBZ6e~8u^@e6syS2Te(;MI)yA(9q+RA1Z10jg573^R(JHXgeaf|`lUy$?&UbV|8`FrWNOYh*E>!wx2XzU3>O+oFMq=|Vt^of~fJCwiEM^x*grDB= zsfFN_)7LM(%|Nl-)iRxDWU0gv7ne}lInJE%FgYZM4dJyCl4($-+Kx{0I%4teF5_bv zSJTPm`vdqmhJTt;o0fx*X9TC1wHb$3glrO1<4d9G!Z`s=rX&jOD1__J(R5H2y2E$@ zLmJq4krUHsiCZQ++_-jA25FY)424=d7ibd6eQ8K)J5+DSjHWXa8I=_cMKZcg#;nL& z+z~4F7mkWZ3cku^`$3Y8jWZ^wIcg&X)9Q2&YdZOrJ*;oo#Aa)=Aj!1PGnrdkZV@aJ z9eC7*K`Vyj5qBuNPm4@1bvzFeX713pUTxU-SUk33Qs1%Q0d)F fHB=G0xQ1%tu+dQCCndnOq;)FHBJT-eF;K`qtsH38 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/footerbg.gif b/ljcom/htdocs/img/style/cuteness/footerbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..38c2a4a4b17f4ce0d298d863c64ed0dc28dfb83a GIT binary patch literal 669 zcmZ?wbhEHb{KIIfZr~iNa`v1VC|8GA2-*fK&`8)r={rG?C z=Kn{p{$F|U|M|QBcc1^?bo}SD=l}ozXCN9V{$ycfU=U=`0qFqQ$-w$QL8ULn(=KDx zx}4Yh3Utnw zS+nQNoi~5M!bOXhEM2yI#mZHy*Q{N)e#6F1o43ph7v!0$w{_3neftj_JaqWT(PR6! z3$pXGatSh=zj#4;_wj4jZ`{0f`_A3lCr=r%3tqkV?D>nAuU@~|_&|`^`t9d0U%!3- zvFH60tDpb=Gca@cZ1;EE-^d}X6?4Mis$GSpl-C@Ojf?iT|H+HEb7JG-2mkf)@+TXMS7L8-euZ1gtSjjjXizs`Axyoaa-nki$A-~!J2gC z?&8w@9uAEHw|)LU+axta_#Pc_|tj@!LA=3ulTQYK}l@q=d z?|kq7z#uInEEB~WC1{dcL1KBpr9C|q@|{(sHv)} ztgWk_W(z)@uC=zexVg2kVhTJ7bO5@;#Kp#`ykEXLlxCjC(9zPk$;&v-)7jeFr~qBE zEm~|Pb7S1+=+fR@D+yO#nj)NH!s+(+)bJ(|3-4kgis<1RNbuDcNh17}c_XHv!-u5c zkWgr+9>k0I4wayo#v;a#=>BZX1F~dDFnmV;Ry4^{+d3}@PH-gCvZgwbCd#3)$Xjsd( zt=qS7F}Q8cUu`neJm0kt=K7 zEcx<@%$!4u2JG1c=+UTC$1PprwCdNYS(9)LyLM>VBfw}XW4pI#-15ADbW}Zn|nre0y<_crBNf?`Q zE=FgaiQS3kV0!KuSf76W1!$nZqWQhKJ~+-&K0vrI?bY zX?vV@n%AJB!bNJS@r^N`q^PdYth=__E2_Vi8my?pc3Lc^ z$4;88qsu1RETPW^8m*tx?pZDWp4Zlyt(@Do*{z!2o*6Eg<9=B#m*-}gu9fRf*)Ejt zE*bBU^A1_BkN4`BuZ{c0*l&yfq8KoV1AkcXh6i7m@PrFL*sy{R7Z@>s6Yp2CeHYi4 z@q(&0$m*?cZOk9719}LuT_UTOa)2Zwc;d+@w;U(TE0b3konBnxQc=NnB-+-L)fZDA(KzA8~(=Zd-5-^Ub z0}`}thIZGa@jwF>?CfV*1r{{$_!&Pmg~{ryKLU;q&9pB2>~~o6L+rHYu6r1^1A+VQ zz|Y=$5UK}n{3Wj=G5PV#-@*A2M>jA19g#N?{q)#3?M57DXFvTO+pD0(^4_x^z&JC6 G0029Np^y*& literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/style/cuteness/userpicbg.gif b/ljcom/htdocs/img/style/cuteness/userpicbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed92de58d1931c905184093dea3162636661d260 GIT binary patch literal 1776 zcmVGb#Q^Z&BP_~-Ta==AvJ_4wuW_~iBY-hQX_xtht`RVxl^ZWSZ_xkeq z`P}9E@%i}a_WA1f`t14m?DqT3+WP7E`s(=k>Gt>P@cG~9_v`Tb?D+ZZ_WIM``_kO` z<@fmJ?fcBy{K(h%=k5La{Q2ki`0e)i>h<{L_xbAf`RMlg@%Z@Z_4woV`||nx`1|-6{R^!euJ_wMue@ALov|M&3oEC2ui0HXk@000O7 zfPaF6goTEOh>41ejE#lJp$jj2x70%C4)7i<^&cNE=v{2mL;N`7F zbADjwNKxBjjDbuT1v;LbPWaI=Sk5a(YO17-og4i0p=z6xT+qO>s)v|m` zx9(DTa_#Eft26DQ7jyXv9t_XhBDRDRCqChK(LIqPKm_@*r?TbCm@{kM%(=7Y&!9Q~ z2m)dRNtGZcs5HC?$yj(3c#sH9ySDAyxH*&H@jBhtN><^Gn4P=0@#Dz%kT6}a0wrJn zKqQ||y?SR53X4JtJ`Rla@8GM0X)Xy#LFwVstIv)7A6Q7u@QqkczkX=u@Nz+dI&K1S z`v3-L840~P^V1_a{KJEQ3<}7@KQuA&SUUeTXrX!}{G*Q}=m>Y=hwI@tP7#lA=L~uv zrf6MzF+EbCF+r#(BXvRGGeJW5P&VU^#{KXQj_~j(WN|+_^3RY++E!%$BS$9bEWmhVa<(5@;naG!5J}D+5WR{uanTMpQ=8$X};^vz?##zXmbk1le zA$aDg;+})_=_iPQ3L@yB7Z&=*p@=r9D5H%E_$WS+3OQ+zmF{?HI+<#U50IR8D&wZ( zh&t-0Mp9~OillP0Dyyh6sp_kV#wz8kv^r`lmbm6B>8@V(>MMY)S~IM!@PJzCvA-sp zDyGa53+$M}Myp=2&R8q0v$8^~?RwZ6^KE_M4lpi#<(>=fv}jhVE_La?8(zHfen)S; z)!mElbo%a#T)+Mr2XMf-4NUND1|M8o!U~7RaKlit+orn^J1nvPoD^3aF}JsRtMS4Y z-HRN3FEeLqjcf)KruF&(%_A{qfdZH*NFHV23^R*fN)GcF|}b4bR$V@60pG zRtbNzS2fnPni!i9I;_S0{}&9>Zg&)hiNhaa3c){9p?x!sv- zUANwyfBm`Nq2oQe;HC3@y5Xq{h;xdF--ZE;jFx`@VGL1PdSc z?YLuReA2`Ryu9tpCa=8izauaG?BmqlyuZ(Hzi;=g6HfjA@Zlpq{_)XYk3Bcqmv8y` z%)4Ja{LpiwqxwG5|Kb2Ks=r5#u&JGijDe!-v1l9>s2v&P3sM zA1SC^9TcR#2jQa*wd(_axZxk^5eOeA2w@+_@Q?W^Ntj}!R9CPzt1F*Na$b*z9GNXg1k zZsC-u983ka(8^klQVe4lVJro6f-$VpmcSfk9lk(@3V3ptOi>LPzEFo?I`f&(jHWcF SNzH0n^P1SqrZ)Ky2mm|DTP||| literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/stylecontest2/3collumn_thumb.jpg b/ljcom/htdocs/img/stylecontest2/3collumn_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f326372279cd8f9a17f284bb60e69c04b450792 GIT binary patch literal 5045 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 QkB8@M0r7TeN?V`)3vaK?C;$Ke literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/stylecontest2/applyexternally_thumb.jpg b/ljcom/htdocs/img/stylecontest2/applyexternally_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fd926f0a1389ba74390425d90fefe44390f987d7 GIT binary patch literal 2387 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/stylecontest2/bob_thumb.jpg b/ljcom/htdocs/img/stylecontest2/bob_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a126135fd84dfe02fbd7d17ed4d1920e5072f99 GIT binary patch literal 3217 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 W8t&?sW{JznjwXqbzSt<%+R>G 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/stylecontest2/dinky_thumb.jpg b/ljcom/htdocs/img/stylecontest2/dinky_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3eb4d3144627168adea670e3c97b7d4c843bd5ea GIT binary patch literal 4352 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 UNw%(7r|#fnG?-4vW;>kzAIXl(ZU6uP literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/img/stylecontest2/divified_thumb.jpg b/ljcom/htdocs/img/stylecontest2/divified_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d856d932835ce88f245b968a84fed41077658df1 GIT binary patch literal 16003 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

    +p?> \ No newline at end of file diff --git a/ljcom/htdocs/inc/community b/ljcom/htdocs/inc/community new file mode 100644 index 0000000..7aafc27 --- /dev/null +++ b/ljcom/htdocs/inc/community @@ -0,0 +1,56 @@ + + + + +The 'Newbies' Lounge, where you'll find answers to many of the questions you may have. Visit , explore a bit, and you'll be a pro in no time at all! +p?> + + +
    +Add to your friends page to keep up with events and issues that are relevant to the entire LiveJournal community.
    +Add to your friends page to be informed when downtime is planned, and reports on unplanned interruptions of service. +p?> + + +AIM, ICQ, Yahoo!, MSN, or Jabber instant messengers. If you do, be sure to list it in your personal info settings. If you have a Paid Account, you can also enable your cell phone or pager to receive text messages. +p?> + + +Paid Account. There are, of course, loads of other ways you help out. +

    +LiveJournal is an Open Source project; if you have experience with programming languages or server side applications you can check out the LiveJournal Development Community, . If you have ideas about how LiveJournal could be better, check out the LiveJournal Suggestions Area, . If you would like to help with just about anything, visit the LiveJournal Business Community, . If you like helping people, visit our technical support center and help someone out. If you are savy with graphic design, check out the LiveJournal Art Community, . +p?> + + +Anime to Zen Buddhism, from Astronomy to Zim. You'll also find regional communities for places all around the world. There's probably a LiveJournal community for where you live too! +p?> + + +FAQ that will explain how to create your very own community. There are also two FAQ Categories (General Community FAQs and Community Management FAQs) covering just about everything you'll ever need to know about communities. If you still need more information, feel free to submit a support request. +p?> + + +by interest! If the interest you search under is listed by 1000 or more users, the results returned to you will be limited, so try to define your search. The more specific you can be when searching, the more chance you have of finding just the right community for you! +

    +There are two official LiveJournal Communities specifically created to help you find the community you're looking for. + +
      +
    • Check out the Promotions Community ()
    • +
    • Check out the Search Community ()
    • +
    +p?> + + +E-mail Jesse Proulx, () the Community Director. +p?> \ No newline at end of file diff --git a/ljcom/htdocs/inc/foobar b/ljcom/htdocs/inc/foobar new file mode 100644 index 0000000..db08bf0 --- /dev/null +++ b/ljcom/htdocs/inc/foobar @@ -0,0 +1,3 @@ +bananas taste good. + +as does chicken. diff --git a/ljcom/htdocs/inc/legal-tos b/ljcom/htdocs/inc/legal-tos new file mode 100644 index 0000000..06bc25d --- /dev/null +++ b/ljcom/htdocs/inc/legal-tos @@ -0,0 +1,553 @@ + + +
      + +
    1. ACCEPTANCE OF TERMS + +

      Danga Interactive, Inc., dba LiveJournal.com, (.LiveJournal.com.) +provides the following service to you, subject to these Terms of Service +("TOS"), which may be updated periodically without notice.

      + +

      You can review the current version of the TOS at: http://www.livejournal.com/legal/tos.bml. +Failure to comply with these TOS may result in account revocation.

      + +
    2. + +
    3. DESCRIPTION OF SERVICE + +

      LiveJournal.com is a web-based service that allows its users to create +and update online journals (herein referred to as "LiveJournal", or +"the Service"). The Service may be used through a web browser or by +the use of downloadable clients ("the Software"). Once registered with +LiveJournal.com, each user receives his or her own journal space to post +text, data, messages, or information concerning or linked to software, +music, sound, photography, graphics, and video ("the Content"). This +Content may reside on LiveJournal's servers or on the servers of a third +party.

      + +
    4. + +
    5. ACCOUNT STRUCTURE + +

      LiveJournal currently has a four-tier account structure.

      + +
        + +
      • Free Accounts: LiveJournal.com accounts are available for free +to all valid registrants. Free accounts offer a limited number of features +in relation to the other accounts offered. + +
      • Early Adopter: No longer open to new users, this account +was created and made available to users registered before September 14, +2000. Early Adopters are offered extended features over free account users, +but do not receive any new pay features.
      • + +
      • Paid Accounts: Paid accounts are available +for term-based fee and offer users all extended and basic +features that LiveJournal.com offers. These accounts +are issued in accordance with the terms set forth by http://www.livejournal.com/paidaccounts/. +Paid accounts are nontransferable and +non-refundable. Once a username is chosen and paid for, that user generally +retains it until the journal is deleted, whether by LiveJournal.com or the +user.
      • + +
      • Permanent Accounts: These accounts have access to all +the paid account features for as long as the Service continues to +run, with no recurring fees. These accounts are generally bestowed +upon the LiveJournal.com founders, administrators, or those that +have earned a Permanent Account by virtue of "Work Excellence" for +LiveJournal.com. LiveJournal administrative communities such as news, +development, et al. are also established as Permanent Accounts for the +benefit of LiveJournal users.
      • + +
      + +

      For a full overview of the features offered to each account type, +see http://www.livejournal.com/paidaccounts/. You hereby agree to this +structure, and to LiveJournal.com's right to change, modify, or discontinue +any type of account and/or its respective services.

      + +
    6. + +
    7. YOUR REGISTRATION OBLIGATIONS + +

      Account registration and verification is required in order to create +a LiveJournal.com account. During registration, all users are required +to provide accurate, complete and current information about themselves +in all required fields. Should any of your own information change after +submitting it to LiveJournal, you are hereby required to update that +information as soon as possible. Should LiveJournal.com suspect that +your personal information is not complete, current, or accurate, your +account may be subject to suspension or termination. Should you feel that +LiveJournal.com's privacy policy is not sufficient for you to complete +the registration form truthfully, please email your policy concerns to privacy@livejournal.com. Users +under 13 years of age are required to have a parent or guardian review and +complete the registration process.

      + +
    8. + +
    9. LIVEJOURNAL.COM PRIVACY POLICY + +

      Your use of the Service is subject to LiveJournal.com's +privacy policy. For information on LiveJournal's privacy +practices, please see the entire privacy policy at http://www.livejournal.com/legal/privacy.bml.

      + +
    10. + +
    11. INDEMNITY + +

      You agree to indemnify and hold LiveJournal.com, and its subsidiaries, +affiliates, officers, agents, co-branders or other partners, and employees, +harmless from any alleged claim or demand, including reasonable attorney +fees, made by any third party due to or arising out of your Content, +your use of the Service, your connection to the Service, your violation +of the TOS, or your violation of any rights of another, whether you are +a registered user or not. The user is solely responsible for his or her +actions when using the Service, including, but not limited to, costs +incurred for Internet access.

      + +
    12. + +
    13. SPECIAL ADMONITIONS FOR INTERNATIONAL USE + +

      Recognizing the global nature of the Internet, you agree to +comply with all local rules regarding online conduct and acceptable +Content. Specifically, you agree to comply with all applicable laws +regarding the transmission of technical data exported from the United +States or the country in which you reside.

      + +
    14. + +
    15. GENERAL PRACTICES REGARDING USE AND STORAGE + +

      You acknowledge that LiveJournal.com may establish limits concerning use +of the Service and may modify these limits at any time.

      + +
    16. + +
    17. MODIFICATIONS TO SERVICE + +

      LiveJournal.com reserves the right to modify or discontinue, temporarily +or permanently, the Service (or any part thereof) with or without notice at +any time. You agree that LiveJournal.com shall not be liable to you or to +any third party for any modification, suspension or discontinuance of the +Service.

      + +
    18. + +
    19. NO RESALE OF SERVICE + +

      You agree not to reproduce, duplicate, copy, sell, resell or exploit any +portion of the Service, use of the Service, or access to the Service.

      + +
    20. + +
    21. TERMINATION + +

      You agree that LiveJournal.com, in its sole discretion, may terminate +your password, journal, or account, and remove and discard any content +within the Service, for any reason, including and without limitation, the +lack of use, or if LiveJournal.com believes that you have violated or +acted inconsistently with the letter or spirit of the TOS. Any contracts, +verbal or written or assumed, in conjunction with your deleted journal +and all its parts, at LiveJournal.com's discretion, will be terminated as +well. LiveJournal.com may also in its sole discretion and at any time, +discontinue providing the Service, or any part thereof, with or without +notice. You agree that any termination of your access to the Service +under any provision of this TOS may be effected without prior notice, and +acknowledge and agree that LiveJournal.com may immediately deactivate +or delete your LiveJournal.com journal and all related information and +files. LiveJournal.com reserves the right to bar any further access to +such files or the Service. You agree that LiveJournal.com shall not be +liable to you or any third-party for any termination of your access to the +Service. Paid accounts that are terminated will not be refunded.

      + +
    22. + +
    23. ADVERTISEMENTS AND PROMOTIONS + +

      LiveJournal.com has decided to remove all banner advertisements and +promotions on LiveJournal.com journals. However, LiveJournal.com reserves +the right to run advertisements and promotions on the LiveJournal.com +service in the future. By using LiveJournal.com, you agree that +LiveJournal.com has the right to run such advertisements and promotions +with or without prior notice, and without recompense to you or any other +user. The manner, mode and extent of advertising by LiveJournal.com on your +journal are subject to change. You agree that LiveJournal.com shall not +be responsible or liable for any loss or damage of any sort incurred as +the result of any such dealings or as the result of the presence of such +advertisers on the Service.

      + +
    24. + +
    25. LINKS + +

      The Service, or relevant third parties, may provide links to other +web sites or resources. Because LiveJournal.com has no control over such +sites and resources, you acknowledge and agree that LiveJournal.com is +not responsible for the availability of such external sites or resources, +and does not endorse and is not responsible or liable for any content, +advertising, products, or other materials on or available from such sites +or resources. You further acknowledge and agree that LiveJournal.com shall +not be responsible or liable, directly or indirectly, for any damage or +loss caused or alleged to be caused by or in connection with use of or +reliance on any such content, goods or services available on or through any +such site or resource.

      + +
    26. + +
    27. JOURNAL CONTENT + +

      Guidelines for posting to your online journal shall be as follows:

      + +
        + +
      1. All Content posted to LiveJournal.com in any way, is the responsibility +and property of the author. LiveJournal is committed to keeping the +Service in decent standing for all audiences but is not responsible for +the monitoring or filtering of any journal Content. Within the confines +of international and local law, LiveJournal.com will generally not +place a limit on the type, or appropriateness of user content within +journals. Those users posting material not suitable for all audiences +must agree that they are fully responsible for all the content they have +posted anywhere on the service. Should content be deemed illegal by such +law having jurisdiction over the user, LiveJournal.com is committed to +submitting all necessary information to the proper authorities;
      2. + +
      3. Should any Content be reported to LiveJournal.com as being offensive +or inappropriate, LiveJournal.com might call upon the poster to retract, +modify, or protect (by means of private and friends only settings) the +Content in question within a reasonable amount of time, as set forth by the +LiveJournal.com staff. Should the poster fail to meet such a request from +LiveJournal.com staff, LiveJournal.com has the full authority to terminate +any such reported and verified account holding such inappropriate content. +LiveJournal.com, however, is under no obligation to restrict or monitor +journal Content in any way;
      4. + +
      5. LiveJournal.com claims no ownership or control over any Content +posted by its users. The author retains all patent, trademark, and +copyright to all Content posted within available fields, and is responsible +for protecting those rights, but is not entitled to the help of the +LiveJournal.com staff in protecting such Content. The user posting any +Content represents that the poster has all rights necessary to post such +Content (and for LiveJournal to serve such Content) without violation of +any intellectual property or other rights or any laws or regulations;
      6. + +
      7. LiveJournal.com reserves the right, without limitation except by law, +to serve any user Content on the web, through the downloadable clients and +otherwise. LiveJournal.com also reserves the right, without limitation, to +resell any portion of a user's LiveJournal back to that individual;
      8. + +
      9. You acknowledge that LiveJournal.com does not pre-screen Content, but +that LiveJournal.com and its designates shall have the right (but not +the obligation) on their sole discretion to refuse or remove any Content +that is available through the Service. Without limiting the foregoing, +LiveJournal.com and its designates shall have the right, but not the +obligation, to remove any content that violates the TOS or is otherwise +objectionable, or that infringes or is alleged to infringe intellectual +property rights. You agree that you must evaluate, and bear all risks +associated with, the use of any content, including any reliance on the +accuracy, completeness, or usefulness of such content. Furthermore, +LiveJournal.com reserves the right to limit access to your journal, if +found in violation of the TOS, by removing the journal and related user +information from the member directory, search engine, and all other methods +used in conjunction with finding LiveJournal.com's users.
      10. + +
      + +
    28. + +
    29. LIVEJOURNAL.COM PROPRIETARY RIGHTS + +

      You acknowledge and agree that the Service, and any necessary software used in +connection with the Service (referred to as "Software"), may contain proprietary and +confidential information that is protected by applicable laws governing intellectual +property, proprietary rights and the like. All LiveJournal code and specifications, and +all other code and specifications for the Software and the operation of the Service, are +subject to their express or implied licenses.

      + +Submission of Unsolicited Ideas and Information + +

      LiveJournal.com does not want to receive confidential or proprietary information +from you through this Site or by email. Unless otherwise agreed in writing by an +authorized LiveJournal.com representative, any material, information or idea you +transmit to LiveJournal.com by any means may be disseminated or used by +LiveJournal.com or its affiliates without compensation or liability to you for any +purpose whatsoever, including, but not limited to, developing, manufacturing and +marketing products. However, this provision does not apply to Content (as defined +herein), or to personal information that is subject to our privacy policy.

      + +Trademarks + +

      A partial list of U.S. trademarks owned by LiveJournal.com +follows. Any questions concerning the use of these trademarks or +whether a trademark that does not appear on this list is a trademark +of LiveJournal.com should be referred to LiveJournal Legal at trademarks@livejournal.com. +Failure of a mark to appear on this page does not mean that LiveJournal.com +does not use the mark nor does it mean that the product is not actively +marketed or is not significant within its relevant market. Any trademarks +followed by ® are registered trademarks of LiveJournal.com in the United +States; all others are trademarks or common law marks of LiveJournal.com in +the United States.

      + +
        +
      • LiveJournal
      • +
      • LiveJournal logo:
        LiveJournal.com logo
      • +
      + +
    30. + +
    31. MEMBER CONDUCT + +

      You understand that all information, data, text, software, music, +sound, photographs, graphics, video, messages or other materials, whether +publicly posted or privately transmitted, are the sole responsibility of +the person from which such Content originated. LiveJournal.com does not +control Content posted via the Service and, as such, does not guarantee +the validity of such Content. You also understand that by using the +Service, you may be exposed to Content that is offensive, indecent or +objectionable. Should Content be found or reported to be in violation with, +but not limited to, the following terms, it will be LiveJournal.com's sole +discretion as to what action should be taken.

      + +

      You agree to NOT use the Service to:

      + +
        + +
      1. Upload, post or otherwise transmit any content that is in +LiveJournal.com's opinion to be unlawful, harmful, threatening, abusive, +harassing, tortious, defamatory, vulgar, obscene, libelous, invasive to +another's privacy (up to, but not excluding any address, email, phone +number, or any other contact information with out the written consent +of the owner of such information), hateful, or racially, ethnically or +otherwise objectionable;
      2. + +
      3. Harm minors in any way, as seen by LiveJournal.com or applicable +law;
      4. + +
      5. Impersonate any person or entity, including, but not limited to, a +LiveJournal.com staff member or volunteer, or falsely state or otherwise +misrepresent your affiliation with a person or entity;
      6. + +
      7. Forge headers or otherwise manipulate identifiers in order to disguise +the origin of any Content transmitted through the Service;
      8. + +
      9. Upload, post or otherwise transmit any content that you do not have +a right to transmit under any law or under contractual or fiduciary +relationships (such as inside information, proprietary and confidential +information learned or disclosed as part of employment relationships or +under nondisclosure agreements);
      10. + +
      11. Upload, post or otherwise transmit any content that infringes any +patent, trademark, trade secret, copyright or other proprietary rights of +any party;
      12. + +
      13. Upload, post or otherwise transmit any unsolicited or unauthorized +advertising, promotional materials, "junk mail," "spam," "chain letters," +"pyramid schemes," or any other form of solicitation;
      14. + +
      15. Upload, post or otherwise transmit any material that contains software +viruses or any other computer code, files or programs designed to +interrupt, destroy or limit the functionality of any computer software or +hardware or telecommunications equipment;
      16. + +
      17. Interfere with or disrupt the Service or servers or networks connected +to the Service, or disobey any requirements, procedures, policies or +regulations of networks connected to the Service;
      18. + +
      19. Intentionally or unintentionally violate any applicable local, state, +national or international law, including, but not limited to, regulations +promulgated by the U.S. Securities and Exchange Commission, any rules of +any national or other securities exchange, including, without limitation, +the New York Stock Exchange, the American Stock Exchange or the NASDAQ, and +any regulations having the force of law;
      20. + +
      21. "Stalk" or otherwise harass another person or company;
      22. + +
      23. Collect or store personal data about other users for business +purposes;
      24. + +
      25. Promote or provide instructional information about illegal activities, +promote physical harm or injury against any group or individual, or promote +any act of cruelty to animals. This may include, but is not limited to, +providing instructions on how to assemble bombs, grenades and other weapons +or incendiary devices;
      26. + +
      27. Use LiveJournal.com as a forwarding service to another website;
      28. + +
      29. Allow usage by others in such a way as to violate LiveJournal.com's +TOS;
      30. + +
      31. Engage in commercial activities within LiveJournal or on behalf of +LiveJournal.com without prior approval. This includes, but is not limited +to, the following activities: + +
          + +
        1. Displaying a banner that is designed to profit you or any other +business or organization; and
        2. + +
        3. Displaying banners for services that provide cash or cash-equivalent +prizes to users in exchange for hyperlinks to their web sites.
        4. + +
        +
      32. +
      +
    32. + +

      If any user is reported to be in violation with the letter or spirit of +these terms, LiveJournal.com retains the right to terminate such account at +any time without further warning.

      + + + +
    33. VOLUNTEERS AND LIVEJOURNAL.COM + +

      LiveJournal.com appreciates the significant contributions made by +volunteers, who assist LiveJournal.com in its efforts to provide high +quality, community driven online services. To help achieve this goal, +LiveJournal.com volunteers perform a variety of technical and non-technical +tasks, including, but not limited to, programming, the creation of +web-based content (HTML, BML, and other formats), graphic design, audio +and/or visual content creation, technical writing, managing electronic data +libraries and/or databases, technical support, reviewing, categorizing, +legal assistance, archiving and/or forwarding electronic data, providing +expert advice, administration, management, accounting, research, content +creation, promotions, or other assignments, as needed. All volunteers are +expected to be of legal age, or volunteering with the consent of a legal +parent or guardian.

      + +

      By accepting these Terms of Service, any LiveJournal.com member agrees +that the intellectual content created as a result of volunteer work for +LiveJournal.com constitutes intellectual property of LiveJournal.com and +that all rights in said content shall vest in LiveJournal.com at the +time that it is created, to the extent permitted by law. If laws prevent +such vesting, the volunteer makes assignment of all such rights to +LiveJournal.com at the time of creation. If laws prevent such assignment, +the volunteer grants a perpetual world wide irrevocable license to +LiveJournal.com to use said content. If laws prevent such licensing, +the volunteer agrees never to sue LiveJournal.com for the use of said +content.

      + +

      The volunteer certifies that any electronic data he/she submits is +his/her work and that to the best of the volunteer's knowledge, the +electronic data is not claimed by another. The volunteer agrees to insure +that any work provided is correct, error free and does not contain any +inflammatory language, indecency or obscenities. Furthermore, if said work +is found to be illegally presented, claimed, or forged, LiveJournal.com +may remove such material and, at LiveJournal.com's discretion, seek +action against the individual(s) from which the work originated. No +LiveJournal user is required to become a volunteer to this service, +and users without volunteer status will receive reasonable support and +attention as well. Without the expressed written confirmation to the +contrary, all LiveJournal.com positions are assumed to be taken without pay +or future consideration.

      + +
    34. + +
    35. DISCLAIMER OF WARRANTIES + +

      YOU EXPRESSLY UNDERSTAND AND AGREE THAT:

      + +

      (a) YOUR USE OF THE SERVICE IS AT YOUR SOLE RISK. THE SERVICE IS +PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS. LIVEJOURNAL.COM EXPRESSLY +DISCLAIMS ALL WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.

      + +

      (b) LIVEJOURNAL.COM MAKES NO WARRANTY THAT (i) THE SERVICE WILL MEET +YOUR REQUIREMENTS, (ii) THE SERVICE WILL BE UNINTERRUPTED, TIMELY, SECURE, +OR ERROR-FREE, (iii) THE RESULTS THAT MAY BE OBTAINED FROM THE USE OF THE +SERVICE WILL BE ACCURATE OR RELIABLE, (iv) THE QUALITY OF ANY PRODUCTS, +SERVICES, INFORMATION, OR OTHER MATERIAL PURCHASED OR OBTAINED BY YOU +THROUGH THE SERVICE WILL MEET YOUR EXPECTATIONS, AND (V) ANY ERRORS IN THE +SOFTWARE WILL BE CORRECTED.

      + +

      (c) ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE +SERVICE IS DONE AT YOUR OWN DISCRETION AND RISK AND THAT YOU WILL BE SOLELY +RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR LOSS OF DATA OR OTHER +LIABILITYTHAT RESULTS FROM THE DOWNLOAD OF ANY SUCH MATERIAL.

      + +

      (d) NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY +YOU FROM LIVEJOURNAL.COM OR THROUGH OR FROM THE SERVICE SHALL CREATE ANY +WARRANTY NOT EXPRESSLY STATED IN THE TOS.

      + +
    36. + +
    37. LIMITATION OF LIABILITY + +

      YOU EXPRESSLY UNDERSTAND AND AGREE THAT LIVEJOURNAL.COM SHALL NOT +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL +OR EXEMPLARY DAMAGES, INCLUDING BUT NOT LIMITED TO, DAMAGES FOR LOSS +OF PROFITS, GOODWILL, USE, DATA OR OTHER INTANGIBLE LOSSES (EVEN IF +LIVEJOURNAL.COM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES), +RESULTING FROM: (i) THE USE OR THE INABILITY TO USE THE SERVICE; (ii) THE +COST OF PROCUREMENT OF SUBSTITUTE GOODS AND SERVICES RESULTING FROM ANY +GOODS, DATA, INFORMATION OR SERVICES PURCHASED OR OBTAINED OR MESSAGES +RECEIVED OR TRANSACTIONS ENTERED INTO THROUGH OR FROM THE SERVICE; (iii) +UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA; (iv) +STATEMENTS OR CONDUCT OF ANY THIRD PARTY ON THE SERVICE; OR (v) ANY OTHER +MATTER RELATING TO THE SERVICE.

      + +
    38. + +
    39. U.S. GOVERNMENT RESTRICTED RIGHTS + +

      The materials on LiveJournal.com are provided with "RESTRICTED RIGHTS." +Use, duplication, or disclosure by the U.S. Government is subject to +restrictions as set forth in applicable laws and regulations. Use of +the materials by the U.S. Government constitutes acknowledgment of +LiveJournal's proprietary rights in them.

      + +
    40. + +
    41. GENERAL INFORMATION + +

      The TOS constitutes the entire agreement between you and LiveJournal.com +and governs your use of the Service, superseding any prior agreements +between you and LiveJournal.com (including, but not limited to, any prior +versions of the TOS) and any prior representations by LiveJournal.com. The +laws of the State of California, U.S.A, shall govern the TOS and the +relationship between you and LiveJournal.com. without regard to its +conflict of law provisions. You and LiveJournal.com agree to submit to the +personal and exclusive jurisdiction of the courts located within the county +of San Francisco, California, U.S.A. The failure of LiveJournal.com to +exercise or enforce any right or provision of the TOS shall not constitute +a waiver of such right or provision. If any provision of the TOS is +found by a court of competent jurisdiction to be invalid, the parties +nevertheless agree that the court should endeavor to give effect to the +parties' intentions as reflected in the provision, and the other provisions +of the TOS remain in full force and effect. You agree that regardless of +any statute or law to the contrary, any claim or cause of action arising +out of or related to use of the Service or the TOS must be filed within +one (1) year after such claim or cause of action arose or be forever +barred. The section titles in the TOS are for convenience only and have no +legal or contractual effect.

      + +
    42. + +
    43. VIOLATIONS + +

      Instructions on how to report violations of these +Terms of Service may be located at the FAQ "How do +I contact the Abuse team?" To expedite the processing of your report, +please carefully follow these instructions.

      + +
    44. + +
    45. REVISIONS + +

      LiveJournal.com may at any time revise these Terms of Service by +updating this posting. By using this Site, you agree to be bound by any +such revisions and should therefore periodically visit this page to +determine the then-current Terms of Service to which you are bound.

      + +
    46. + +
    diff --git a/ljcom/htdocs/inc/resources-homonyms b/ljcom/htdocs/inc/resources-homonyms new file mode 100644 index 0000000..75a94c5 --- /dev/null +++ b/ljcom/htdocs/inc/resources-homonyms @@ -0,0 +1,144 @@ + +Learn it right! +p?> + + + + + +There is usually used to describe a physical place or location, or at least a noun. It can also be used in other ways, but I don't know how to best describe it. The following examples should help: +p?> +
      +
    • Over there is my brain! I left it on the side of the road.
    • +
    • There exists a time when every man must learn his homonyms.
    • +
    • Do you see now that there is a difference?
    • +
    + + +Their
    is used to show possesion. Just as 'his' shows possesion +of an object by 'him', and 'her' shows possesion of 'her', their shows +possesion of an object by a group, they. +P?> +
      +
    • It's their crap, not yours. +
    • Their idea to teach people homonyms was wonderful. +
    + + +They're
    is a contraction of the words "they" and "are", as indicated +by its apostrophe. You use it to describe a group of objects or whatnot. If +your sentence doesn't sound right by replacing they're with they are, +then you're using the wrong form of there/their/they're. +P?> +
      +
    • They're stupid; they don't even know their homonyms. +
    • It's good that they're reading this page though. +
    + + + + + +To is hard to explain. It's kinda like an implied verb prefix. Read the examples. +P?> +
      +
    • To be, or not to be, that is the question. +
    • I have to go to the bathroom. +
    • You want to go to the concert with me? +
    + + +Two is the spelling of the number 2. Use it when referring to +2 elements of something. +P?> +
      +
    • There were two ducks in the pond, not three. +
    • What do you call a blonde with two brain cells? Pregnant! +
    + + +Too can mean either 1) also, or 2) an excess of. +P?> +
      +
    • I have to go to the bathroom too. (case 1) +
    • You go to the bathroom too much. (case 2) +
    • Hey, I want some beer too! (case 1) +
    • You are too young to go in the bar! (case 2) +
    + + + + + +Are is hard to explain also. Read the examples. +P?> +
      +
    • Are you going to the concert? +
    • There are five ducks swimming around the pond. +
    • I bet you are tired after that long drive! +
    + + +Our shows possesion. Use it when you are referring to a group +you are in that 'owns' something. +P?> +
      +
    • Hey, that is our money, don't touch! +
    • Our pineapples are the best in town. +
    • Would you like to tour our factory? +
    + + + + + +Your shows possession. +P?> +
      +
    • Is this your money sitting here? +
    • Can I have some of your Coke? +
    + + +You're is a contraction for "You Are". If you can't replace +you're with you are and have your sentence work, then you've messed up.P?> +
      +
    • After that run, I bet you're tired as hell. +
    • Hey baby, you're pretty hot. (don't try this one in real life) +
    + + + + + +Its is the possesive form of it.P?> +
      +
    • The vase lost its shine over the years. +
    + + + +
      +
    • It's going to be a nice day today. +
    • Come inside... it's raining! +
    + + + + +
      +
    1. Your pretty nice to help us invest are money like that. +
    2. You're pretty nice two help us invest our money like that. +
    3. Your pretty nice to help us invest are money like that. +
    4. You're pretty nice to help us invest our money like that. +
    5. You're pretty nice too help us invest are money like that. +
    6. Your pretty nice to help us invest our money like that. +
    diff --git a/ljcom/htdocs/inc/resources-index b/ljcom/htdocs/inc/resources-index new file mode 100644 index 0000000..1af36ad --- /dev/null +++ b/ljcom/htdocs/inc/resources-index @@ -0,0 +1,9 @@ + + +
  • Homonyms
    Learn the difference between words that sound the same but have different spellings.
  • +
  • Dictionary.com
    Check your spelling or look up words. + + +p?> diff --git a/ljcom/htdocs/inc/spam-warning b/ljcom/htdocs/inc/spam-warning new file mode 100644 index 0000000..c95402d --- /dev/null +++ b/ljcom/htdocs/inc/spam-warning @@ -0,0 +1,21 @@ +Dear [[user]], + +We have recently become aware that your LiveJournal account has been +used to make a number of identical unsolicited comments or entries in others' +journals. This practice is forbidden by LiveJournal's Terms of Service, as +it qualifies as spam. + +This email serves as a warning that any further reports of this +behavior will result in the suspension of all of your LiveJournal +accounts. LiveJournal does not permit spam, and does not tolerate it when +it is reported to us. + +If you have any questions about LiveJournal's policy +regarding commercial activity and promotion, please see +http://www.livejournal.com/support/faqbrowse.bml?faqid=197. This +FAQ contains instructions on how to file an Abuse query if you need +clarification on any elements of the policy. + + +Regards, +LiveJournal Team diff --git a/ljcom/htdocs/inc/validationreminder b/ljcom/htdocs/inc/validationreminder new file mode 100644 index 0000000..60d07de --- /dev/null +++ b/ljcom/htdocs/inc/validationreminder @@ -0,0 +1,9 @@ +Your e-mail address has not been validated. You will not have full functionality of your LiveJournal account until you have validated your email address. You will also not be able to reclaim your account if your account security is ever compromised, or obtain your password if you forget it. + +To validate your e-mail address, you will need to follow a link that is sent to you in an e-mail from LiveJournal. If you need that mail re-sent to you, please see http://www.livejournal.com/support/faqbrowse.bml?faqid=11. + +You may first need to adjust or temporarily disable any bulk mail filters on your email account in order to receive the email. + +Please see this FAQ if there are problems when you try to validate: http://www.livejournal.com/support/faqbrowse.bml?faqid=36. + +If you have any questions or problems, or don't understand these instructions, please open an additional support request so that a support volunteer can help you. diff --git a/ljcom/htdocs/index.bml b/ljcom/htdocs/index.bml new file mode 100644 index 0000000..ac877f5 --- /dev/null +++ b/ljcom/htdocs/index.bml @@ -0,0 +1,225 @@ + +head<= + + + + + + +<=head +bodyopts<= +/goat-pee.gif')\""; + } else { + return "onload=\"MM_preloadImages('/goat-hover.gif')\""; + } +_code?> +<=bodyopts +pretitle<= +
    +

    +$ML{
    $ML{'.frank.logo'}"; +} +_code?> +

    + + $now-600)) { + my $db = LJ::get_db_reader(); + $LJ::CACHE_STAT_ACCTS = $db->selectrow_array("SELECT statval FROM stats WHERE statcat='size' AND statkey='accounts'")+0; + $LJ::CACHE_STAT_ACCTS_ACTIVE = $db->selectrow_array("SELECT statval FROM stats WHERE statcat='size' AND statkey='accounts_active'")+0; + $LJ::CACHE_STAT_ACCTS_TIME = $now; + } + return unless $LJ::CACHE_STAT_ACCTS && $LJ::CACHE_STAT_ACCTS_ACTIVE; + return <<"END_BOX"; + + +
     
    + + +
    $LJ::CACHE_STAT_ACCTS
    $LJ::CACHE_STAT_ACCTS_ACTIVE
    + +
    +
    + +END_BOX + +} +_code?> + +[1] - $stat->[2]; + return unless $delta; + + my $rate_sec = $stat->[0] / $delta; + + my $rate_min = $rate_sec * 60; + my $fmt_min = $rate_min > 10 ? "%.0f" : "%.2f"; + + my $rate_hour = $rate_min * 60; + my $fmt_hour = $rate_hour > 10 ? "%.0f" : "%.2f"; + + my $post_min = sprintf($fmt_min, $rate_min); + my $post_hour = sprintf($fmt_hour, $rate_hour); + + return <<"END_BOX"; + + +
     $ML{'.post'}
    + + + + + +
    $ML{'.post.hour'}$post_hour
    $ML{'.post.min'}$post_min
    +$ML{'.post.latest'} +RSS version +
    + +
    +
    + +END_BOX + + return $ret; + +} +_code?> + +
    +<=pretitle +body<= +"; + $text .= ''href="http://www.livejournal.org"'}).' p?>'; + $text .= ''href="/paidaccounts/"', 'aopts2'=>'href="/site/accounts.bml"'}).' p?>'; + $text .= ""; + $text .= ''href="/site/about.bml"', 'aopts2'=>'href="/create.bml"'}).' p?>'; + return $text; +_code?> +"; + $hdr .= "'href="/news.bml"'}) . " p?>"; + + my $news = LJ::MemCache::get('frontnews'); + if (defined $news) { + return "$hdr $news" if $news; + return ""; + } + $news = ""; + + my $set = sub { + my $news = shift; + LJ::MemCache::set('frontnews', $news||"", 60*5); + return $news ? "$hdr $news" : ""; + }; + + my $u = LJ::load_user("news"); + return $set->("") unless $u; + my @items = LJ::get_recent_items({ + 'userid' => $u->{'userid'}, + 'clusterid' => $u->{'clusterid'}, + 'clustersource' => 'slave', + 'order' => 'logtime', + 'itemshow' => 1, + 'dateformat' => 'S2', + 'friendsview' => 1, # so we get rlogtime + }); + + return $set->("") unless @items; + my $item = $items[0]; + + my $delta = time() - ($LJ::EndOfTime - $item->{rlogtime}); + return $set->("") unless $delta < 86400 * 7; + + my $pd = LJ::get_posts_raw([ $u->{'clusterid'}, $u->{'userid'}, $item->{itemid} ]); + my $key = "$u->{userid}:$item->{itemid}"; + my $text = $pd->{'text'}->{$key}; + my $props = $pd->{'prop'}->{$key}; + $item->{'replycount'} = int($pd->{'replycount'}->{$key}); + + return $set->("") unless $text; + + LJ::CleanHTML::clean_subject(\$text->[0]); + LJ::CleanHTML::clean_event(\$text->[1], { 'preformatted' => $props->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $item->{itemid}, $item->{'anum'}), }); + my $ditemid = $item->{itemid}*256+$item->{anum}; + LJ::expand_embedded($u, $ditemid, undef, \$text->[1]); + + $news .= "
    "; + + my $date = substr($item->{'alldatepart'}, 0, 10); + $date =~ s/ /-/g; + $news .= "$text->[0]
    $date

    "; + $news .= $text->[1]; + + my $link = LJ::item_link($u, $item->{itemid}, $item->{anum}); + + $news .= "
    ( "; + if ($item->{'replycount'}) { + $news .= "" . (($item->{'replycount'} == 1) ? "1 comment" : "$item->{'replycount'} comments") . ""; + } else { + $news .= "Link"; + } + unless ($props->{'opt_nocomments'}) { + $news .= " | Leave a comment"; + } + + $news .= " )
    "; + $news .= "
    "; + return $set->($news); +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/invite/claim.bml b/ljcom/htdocs/invite/claim.bml new file mode 100644 index 0000000..769f54a --- /dev/null +++ b/ljcom/htdocs/invite/claim.bml @@ -0,0 +1,119 @@ +($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u; + + if ($u->{'statusvis'} eq "S") { + $title = "Suspended Account"; + $body = ""; + return; + } + + # find out how much we owe them + my $get_amt = sub { + my $rowct = shift; + + my $amt = 0; + if ($rowct > 10) { + $amt += 0.50*10; + $amt += 0.25*($rowct-10); + } else { + $amt += 0.50*$rowct; + } + $amt = 25.00 if $amt > 25.00; + + return $amt; + }; + + # print dollars + my $damt = sub { sprintf("\$%.02f", shift()) }; + + my $dbh = LJ::get_db_writer(); + + unless (LJ::did_post()) { + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + + my $rowct = $dbh->selectrow_array("SELECT COUNT(*) FROM acctcode WHERE userid=? AND rcptid=0", + undef, $u->{'userid'}); + unless ($rowct > 0) { + $body .= ""; + return; + } + + my $amt = $get_amt->($rowct); + + $body .= ""; + $body .= "LiveJournal "; + $body .= "Store. p?>"; + + $body .= "($amt) . ". p?>"; + + $body .= "$u->{'email'}. Please be sure this email "; + $body .= "address is correct. p?>"; + + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + $body .= "
    "; + $body .= "

    "; + $body .= LJ::html_submit(undef, "Generate Coupon", + { 'disabled' => $amt <= 0 }); + $body .= "

    "; + + return; + } + + + my $system_id = LJ::get_userid("system") or die; + my $rowct = $dbh->do("UPDATE acctcode SET rcptid=? WHERE userid=? AND rcptid=0", + undef, $system_id, $u->{'userid'}); + unless ($rowct > 0) { + $body = ""; + return; + } + + my $amt = $get_amt->($rowct); + + my ($tokenid, $token) = + LJ::Pay::new_coupon('dollaroffint', $amt, $u->{'userid'}, 0); + return "" + unless $tokenid && $token; + + # send the coupon to the user in an email + LJ::Pay::send_coupon_email($u, $token, $amt, "int"); + + # log to statushistory + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, "invitecp", + "generated " . $damt->($amt) . " intangible coupon ($token) for " . + "$rowct invite codes"); + + $body = "($amt) . + " in exchange for your $rowct invite codes. p?>"; + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/invite/gen.bml b/ljcom/htdocs/invite/gen.bml new file mode 100644 index 0000000..c120393 --- /dev/null +++ b/ljcom/htdocs/invite/gen.bml @@ -0,0 +1,211 @@ +($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u && $u->{'user'} ne "test"; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + my $dbr = LJ::get_db_reader(); + my $sth; + + if ($u->{'statusvis'} eq "S") { + $title = "Suspended Account"; + $body = ""; + return; + } + + $sth = $dbr->prepare("SELECT reason FROM acctinvite WHERE userid=? ORDER BY dateadd"); + $sth->execute($u->{'userid'}); + + my @prev; + my %reason; + while ($_ = $sth->fetchrow_array) { + $reason{$_} = 1; + push @prev, [ split(/-/, $_) ]; + } + + my @added; + + # REASONS TO GET INVITATION CODES REASON FORMAT + # -------------------------------------------------------- + # 1 in a week "week" + # 1 per acked contribution "con-0123456789" + # 1 per month of paid account time "pay-2342343243-nn + # "" "" (payitem rcpt) "pay2---nn" + # 1 per 20 support points "sup-20/40/60" + # 5 per month for perm accounts "perm-200108-n" + # 15 base for early adopters "early-nn" + + my $dbh; + my $gen_code = sub { + my $reasonlist = shift; + my $reason = join("-", @$reasonlist); + + return 0 if $reason{$reason}; # duplicate + $dbh ||= LJ::get_db_writer(); + my $qr = $dbh->quote($reason); + $dbh->do("INSERT INTO acctinvite (userid, reason, dateadd, acid) ". + "VALUES ($u->{'userid'}, $qr, NOW(), 0)"); + return 0 if $dbh->err; # already exists (race / slave behind) + + my $code = LJ::acct_code_generate($u->{'userid'}); + my ($acid, $auth) = LJ::acct_code_decode($code); + $dbh->do("UPDATE acctinvite SET acid=$acid WHERE ". + "userid=$u->{'userid'} AND reason=$qr"); + push @added, $reasonlist; + return 1; + }; + + my $reason_name = sub { + my $r = shift; + if ($r->[0] eq "week") { + return "For having an account for at least a week."; + } + if ($r->[0] eq "con") { + return "For [1]\">this contribution"; + } + if ($r->[0] eq "early") { + return "For being an early adopter (#$r->[1])"; + } + if ($r->[0] eq "pay") { + return "For payment #$r->[1] (#$r->[2])"; + } + if ($r->[0] eq "pay2") { + return "For payment #$r->[1], item $r->[2] (#$r->[3])"; + } + if ($r->[0] eq "perm") { + return "For having a permanent account ($r->[1], #$r->[2])"; + } + if ($r->[0] eq "sup") { + return "For reaching $r->[1] support points."; + } + + }; + + #### try to make some new ones + + ## for being a member for a week + if (0 && ! $reason{'week'}) { # off + $sth = $dbr->prepare("SELECT (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timecreate)) > (86400*7) FROM userusage WHERE userid=$u->{'userid'}"); + $sth->execute; + my ($been_week) = $sth->fetchrow_array; + if ($been_week) { $gen_code->(['week']); } + } + + ## one for every acked contribution + $sth = $dbr->prepare("SELECT coid FROM contributed WHERE userid=$u->{'userid'} AND acks > 0"); + $sth->execute; + while (my ($coid) = $sth->fetchrow_array) { + next if $reason{"con-$coid"}; + $gen_code->(['con', $coid]); + } + + ## one for each month of paid account time + $sth = $dbr->prepare("SELECT payid, months FROM payments WHERE mailed<>'C' AND userid=$u->{'userid'}"); + $sth->execute; + while (my ($payid, $months) = $sth->fetchrow_array) { + next if ($months > 24); + for (1..$months) { $gen_code->(['pay', $payid, $_]); } + } + + # and the new payment system: + $sth = $dbr->prepare("SELECT payid, piid, qty FROM payitems ". + "WHERE rcptid=? AND status='done' ". + "AND item='paidacct'"); + $sth->execute($u->{'userid'}); + while (my ($payid, $piid, $months) = $sth->fetchrow_array) { + next if $payid > 422525; # approx. last payid before invite codes were removed + for (1..$months) { $gen_code->(['pay2', $payid, $piid, $_]); } + } + $sth = $dbr->prepare("SELECT pi.payid, pi.piid, pi.qty ". + "FROM acctcode a, acctpayitem api, payitems pi ". + "WHERE a.rcptid=? AND api.acid=a.acid ". + "AND pi.piid=api.piid AND pi.status='done' ". + "AND pi.item='paidacct'"); + $sth->execute($u->{'userid'}); + while (my ($payid, $piid, $months) = $sth->fetchrow_array) { + next if $payid > 422525; # approx. last payid before invite codes were removed + for (1..$months) { $gen_code->(['pay2', $payid, $piid, $_]); } + } + + ## 15 for early adopters + if (LJ::get_cap($u, "earlyadopter")) { + for (1..15) { $gen_code->(['early', $_]); } + } + + ## 1 per 20 support points + $sth = $dbr->prepare("SELECT SUM(points) FROM supportpoints WHERE userid=$u->{'userid'}"); + $sth->execute; + { + my ($points) = $sth->fetchrow_array; + my $p = 20; + while ($p <= $points) { + $gen_code->(['sup', $p]); + $p += 20; + } + } + + ## 5 per month for permanent accounters + if ($u->{'caps'} & 0x10) { + for (1..5) { $gen_code->(['perm', $now, $_]); } + } + + #### apologize if they couldn't get more + my $ct = scalar @added; + unless ($ct) + { + $body .= "read this. p?>"; + } + + #### show which new ones they got + else + { + my $s = $ct == 1 ? " was" : "s were"; + $body .= "$ct more code$s generated for the following reasons:
      "; + foreach my $r (@added) { + $body .= "
    • " . $reason_name->($r) . "
    • \n"; + } + $body .= "
    p?>"; + } + + #### show previous codes + $body .= ""; + foreach my $r (@prev) { + $body .= "
  • " . $reason_name->($r) . "
  • \n"; + } + $body .= " p?>"; + + $body .= "Back to your list of codes."; + + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/invite/index.bml b/ljcom/htdocs/invite/index.bml new file mode 100644 index 0000000..86d13d5 --- /dev/null +++ b/ljcom/htdocs/invite/index.bml @@ -0,0 +1,80 @@ +($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + + $body .= ""; + $body .= ""; + $body .= BML::ml('.how_detail', { 'factors_url' => "$LJ::SITEROOT/support/faqbrowse.bml?faqid=103" }); + + $body .= "

    "; + $body .= ""; + + $body .= "\n"; + + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT acid, rcptid, auth FROM acctcode WHERE userid=? ORDER BY rcptid"); + $sth->execute($u->{'userid'}); + my $ct = 0; + + while (my ($acid, $rcptid, $auth) = $sth->fetchrow_array) + { + my $code = LJ::acct_code_encode($acid, $auth); + my $rcpt; + if ($rcptid) { + $rcpt = LJ::get_username($rcptid); + next unless $rcpt; + } + $ct++; + + $body .= "\n"; + } + + unless ($ct) { + $body .= "\n"; + } + + $body .= "\n"; + + $body .= "
    $ML{'.code'}$ML{'.redeemed'}
    $code"; + if ($rcpt) { + $body .= ""; + } else { + $body .= "$ML{'.unused'}"; + $body .= " " . BML::ml('Actionlink', { 'link' => "$ML{'.use'}" }); + } + $body .= "
    $ML{'.none'}
    $ML{'.genmore '}
    "; + $body .= "
    "; + + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/legal/coppa.bml b/ljcom/htdocs/legal/coppa.bml new file mode 100644 index 0000000..8f35825 --- /dev/null +++ b/ljcom/htdocs/legal/coppa.bml @@ -0,0 +1,3 @@ + diff --git a/ljcom/htdocs/legal/disclaimer.bml b/ljcom/htdocs/legal/disclaimer.bml new file mode 100644 index 0000000..a3a8b78 --- /dev/null +++ b/ljcom/htdocs/legal/disclaimer.bml @@ -0,0 +1,45 @@ +Disclaimer +body<= + + + + +Notice: This page is old, and was never too official. The new terms of service document is what you should read. + +standout?> + +
      +
    • LiveJournal.com is not responsible for the content found on user journals on this server. Notify us if you find inapproriate content. +
    • LiveJournal.com will not tolerate inproper use of the LiveJournal service. Improper use includes anything illegal, or anything extremely offensive. Use your best judgement, and ask us if you have questions. +
    • Although we do have extensive backups, LiveJournal.com is not responsible for lost data. Note: we are also developing a personal backup system, so you can download your entire journal to your local machine for your own backup purposes. +
    + + + + + +
      +
    • LiveJournal.com reserves the right to publish on the web any public entries the journal owners post. (if we didn't, it'd be hard to run a journal website) +
    • For private entries, only the authenticated author will have access to them either on the web. +
    • For protected entries, only the authenticated author or users authorized by the author will have access to them on the web. +
    + + +
      +
    • Journal owners may republish their journals without restrictions. You can even sell your journal and make profit off of it. (You just can't go into the business of republishing or selling other users' journals, without their permission.) +
    + + + + +<=body +page?> diff --git a/ljcom/htdocs/legal/dmca.bml b/ljcom/htdocs/legal/dmca.bml new file mode 100644 index 0000000..1698967 --- /dev/null +++ b/ljcom/htdocs/legal/dmca.bml @@ -0,0 +1,86 @@ +DMCA Information + +body<= + + + + + + + + + + + + +
      +
    • An electronic signature (your full legal name) of a person authorized to act on behalf of the copyright holder;
    • +
    • Identification of the copyrighted work claimed to have been infringed, in the form of the original URL of the image or work being infringed upon;
    • +
    • Identification of the material that is infringing upon your copyright, with reasonable information for LiveJournal to locate the material (you must include the username of the person who is infringing upon your copyright, and links to the allegedly infringing material);
    • +
    • Information reasonably sufficient for LiveJournal to contact you (a valid email address);
    • +
    • A statement that you in good faith believe that the material is not authorized for use in such a manner;
    • +
    • And finally, a statement, made under penalty of perjury, that the information given is accurate and you are authorized to act on behalf of the copyright holder.
    • +
    + +Report Abuse form and following the directions given there. Further information regarding LiveJournal's DMCA procedures may be found in this FAQ. +p?> + +Online +Policy Group v. Diebold, Inc. for more details), +a company claimed their copyrighted material was being +infringed upon and sent notification requiring the removal of this +material. It was determined in court that the company knowingly and +materially misrepresented the claim, and as such was ordered to pay +damages and attorneys fees; the company has agreed to pay $125,000 in +total. +p?> + + + + + + + + +
      +
    • Your electronic signature (your full legal name);
    • +
    • Identification of the material in question, including the location at which the material appears;
    • +
    • A statement, made under penalty of perjury, that you have a good faith belief that the material in question was identified as a copyright violation as a result of mistake or misidentification, including the reasons why you believe this;
    • +
    • Your full name, address, and telephone number, along with a statement that you consent to the jurisdiction of Federal District Court for the judicial district in which your address is located, and that you will accept service of process from the person who provided the initial notification.
    • +
    + + + +<=body +page?> diff --git a/ljcom/htdocs/legal/index.bml b/ljcom/htdocs/legal/index.bml new file mode 100644 index 0000000..f9b8cfd --- /dev/null +++ b/ljcom/htdocs/legal/index.bml @@ -0,0 +1,36 @@ + +head<= + +<=head +body<= + + h1?> + p?> + + h1?> + + +
    +
    +
    +
    +
    +
    + + +<=body +page?> +link: htdocs/legal/tos.bml, htdocs/legal/privacy.bml +link: htdocs/legal/coppa.bml + +_c?> diff --git a/ljcom/htdocs/legal/principles.bml b/ljcom/htdocs/legal/principles.bml new file mode 100644 index 0000000..5b558c1 --- /dev/null +++ b/ljcom/htdocs/legal/principles.bml @@ -0,0 +1,94 @@ +LiveJournal.com Guiding Principles +head<= + +<=head +body<= + + + + + + + + +
    + +
    Work with the community, for the community
    + +
    We will strive to keep you informed of changes to the best of our +abilities without being intrusive, and to run our business based on +feedback from the LiveJournal community, with the LiveJournal community's +best interests in mind.
    + +
    Honor the status of every account
    + +
    We fully intend to honor the status of our users' accounts, as +follows: Permanent accounts will be honored for the life of the +service. Paid accounts will remain as paid accounts until they expire, +unless they are renewed in advance. Early adopters will be granted access +to the paid features that were freely available in the early history of the +site. (Account status valid with the exception of account termination by +means of Terms of Service violation.)
    + +
    Maintain reliable uptime
    + +
    We try to keep things running smoothly for everyone, especially since +we use the system, too. Unfortunately, server hangups do occur, but we will +plan ahead to try to avoid them.
    + +
    Avoid banner advertisements
    + +
    As it's one of our larger pet peeves, we have avoided putting banner +advertisements on the site. Although our Terms of Service permits us to +change our policy in the future, we've found throughout the past few years +that our "paid accounts" business model has, so far, made banners ads +unnecessary.
    + +
    Avoid spam
    + +
    We strongly believe that spam has no place on the internet, and +we endeavor not to send you e-mail without your implied or explicit +consent. When you sign up for the Service, we understand that to mean +you want to communicate with us and hear from us about our products and +services. If we do send you a message or contact you, we give you an option +to opt-out so that we won't send you similar messages in the future. We are +not in the business of selling lists of users' e-mail addresses or personal +information, though we may share users' information under certain special +circumstances, such as with an entity that owns or is owned by LiveJournal, +with our service providers and vendors in connection with the operation of +the service and our business, where we think it is appropriate or required +by law or to protect our legal rights, or if the business is being sold or +reorganized. (For more information on these special circumstances, click +here.)
    + +
    Support the Free Software movement
    + +
    We're big supporters of Open Source software - we have used it and +contributed to it extensively. As part of our contribution to the Open +Source community, we have made available to the public a large amount of +source code for software that we've used to run the LiveJournal service, +and that contributed source code will remain free and open. We plan to +continue to give back to the community by contributing certain bug fixes, +testing, documentation and new code. In addition, we continue to encourage +people to innovate using the open source code we have contributed.
    + +
    + +<=body +page?> diff --git a/ljcom/htdocs/legal/privacy.bml b/ljcom/htdocs/legal/privacy.bml new file mode 100644 index 0000000..f9b0a44 --- /dev/null +++ b/ljcom/htdocs/legal/privacy.bml @@ -0,0 +1,328 @@ +LiveJournal.com Privacy Policy +body<= + + + + + + +
      + +
    • LiveJournal.com collects personal information when you register +with us, use LiveJournal.com products or services or post content on a +LiveJournal.com Blog site as a guest with authoring rights.
    • + +
    • LiveJournal.com may also collect personal information when you enter +into promotions or sweepstakes.
    • + +
    • LiveJournal.com may combine information about you that we have with +information we obtain from business partners or others.
    • + +
    • LiveJournal.com may also collect information about your transactions +with us and with some of our business partners. This information might +include information necessary to process payments due to us from you such +as your credit card number.
    • + +
    • LiveJournal.com automatically receives and records information on our +server logs from your browser, including your IP address, cookies, and the +pages you request.
    • + +
    • LiveJournal.com uses information for the following general +purposes: products and services provision, billing, identification and +authentication, services improvement, contact, research, and anonymous +reporting.
    • + +
    + + + +
      + +
    • LiveJournal.com may occasionally obtain IP addresses from users +depending upon how you access our web site. IP addresses, browser and +session information may be used for various purposes, including to:
    • + +
        + +
      • Diagnose and prevent service or technology problems reported by our +users or engineers that are associated with the IP addresses controlled by +a specific web company or ISP.
      • + +
      • Estimate the total number of users visiting LiveJournal.com from +specific geographical regions.
      • + +
      • Help determine which users have access privileges to certain content, +services or resources that we offer.
      • + +
      • Monitor and prevent fraud and abuse.
      • + +
      + +
    • LiveJournal.com may display your IP address to the owners or +maintainers of certain LiveJournal journals when you post to those journals +and the owner or maintainer has enabled functionality on the site for this +purpose.
    • + +
    + + + +
      + +
    • A cookie is a small amount of data, which often includes an anonymous +unique identifier that is sent to your browser from a web site's computers +and stored on your computer's hard drive.
    • + +
    • If you reject all cookies, you may not be able to use LiveJournal.com +products or services that require you to "sign in," and you may not be able +to take full advantage of all offerings.
    • + +
    • You can configure your browser to accept all cookies, reject all +cookies, or notify you when a cookie is set.
    • + +
    • LiveJournal.com uses its own cookies for a number of purposes, +including to:
    • + +
        + +
      • Require you to re-enter your LiveJournal.com password after a certain +period of time has elapsed to protect you against others accidentally +accessing your account contents.
      • + +
      • Keep track of preferences you specify while you are using +LiveJournal.com's services.
      • + +
      • Estimate and report our total audience size and traffic.
      • + +
      • Conduct research to improve LiveJournal.com's content and +services.
      • + +
      + +
    + + + +
      + +
    • The Children's Online Privacy Protection Act ("COPPA") requires that we +inform parents and legal guardians about how we collect, use, and disclose +personal information from children under 13 years of age. LiveJournal.com +is not directed at children under 13 years of age but, we recognize that +with proper adult supervision some parents might permit their children to +visit LiveJournal.com and use our Service. COPPA requires that we obtain +the consent of parents and guardians in order for children under 13 years +of age to use certain features of LiveJournal.com.
    • + +
    • When your child attempts to register and/or provide personal +information to LiveJournal.com, we require a parent or legal guardian +to:
    • + +
        + +
      1. complete the registration;
      2. + +
      3. review our privacy policy and to submit a valid credit card number to +verify that the child's parent or guardian knows about and authorizes our +information practices related to children protected by COPPA; and
      4. + +
      5. verify through the use of an email confirmation and second +authorization that the parent or guardian consents to the Terms of Service +and this privacy policy.
      6. + +
      + +
    • Once parental notice and consent has been verified, the information we +collect will be treated the same as information collected from any other +user of LiveJournal.com. Without verified parental notice and consent, +we will not knowingly collect personal information of children under 13 +years of age, and if we learn that we have inadvertently collected such +information, we will promptly delete it.
    • + +
    + + + + + +Changing your Preferences and Personal Information
    , or +you may contact us by letter, phone or email using the address information +provided at the bottom of this page. p?> + + + + + +
      + +
    • LiveJournal.com does not share personal information we learn about +you from your use of the Service or this web site with others except as +described in this policy. We do not share your information with unrelated +third parties for their direct marketing purposes.
    • + +
    • When you provide personal information through using the Service you +are however sharing your personal information with LiveJournal.com, +organizations that may hold a majority interest in LiveJournal.com, their +divisions or subsidiaries and, LiveJournal.com and any of its divisions or +subsidiaries. The use of your personal information by these organizations +is subject to this policy.
    • + +
    • LiveJournal.com may use or share your personal information where it +is necessary for us to complete a transaction, to operate or improve +LiveJournal.com and related products and services, to do something that you +have asked us to do, or tell you of products and services that we think may +be of interest.
    • + +
    • Where you are contacted with an offer or service based on information +you have shared with LiveJournal.com, we will do our best to provide you +with an opportunity to opt-out of receiving such further communications at +the time you are contacted.
    • + +
    • When you post a message, your LiveJournal.com ID or alias that you are +posting under may be visible to other users.
    • + +
    • When you post a message on LiveJournal.com Blog Sites, you have the +ability to post a message which may include personally identifiable +information about yourself.
    • + +
    • If you post personal information online that is accessible to the +public, you may receive unsolicited messages from other parties in return. +
    • + +
    • LiveJournal.com does or may share personally identifiable information +about you under the following circumstances:
    • + +
        + +
      • In the course of operating our business it may be necessary or +appropriate for us to provide access to your personal information to +others such as our service providers, contractors and select vendors so +that we can operate the Service and our business. Where practical, we +seek to obtain confidentiality agreements that are consistent with this +policy and that limit others' use or disclosure of the information you have +shared.
      • + +
      • We may share your personal information to respond to subpoenas, court +orders, or legal process, to establish or exercise our legal rights or, +defend against legal claims and if in our judgment in such circumstances +disclosure is required or appropriate.
      • + +
      • We may share your personal information if we believe it is necessary in +order to investigate, prevent, or take action regarding illegal activities, +suspected fraud, situations involving potential threats to the physical +safety of any person, violations of LiveJournal.com's terms of use, or as +otherwise required by law.
      • + +
      • As we continue to develop our business, we might also buy or sell all +or part of our business. In such transactions, personally identifiable +information you have shared with us is generally one of the business +assets that will be transferred. The transferred personally identifiable +information will remain subject to the promises made in this privacy policy +or subsequent policies to which you have consented.
      • + +
      + +
    + + + + + + + +
      + +
    • We use physical, electronic, and procedural safeguards to protect +personal information about you.
    • + +
    • Your LiveJournal.com Account Information is password-protected.
    • + +
    • In certain areas, LiveJournal.com uses industry-standard SSL-encryption +to protect data transmissions. However, please note that this is not a +guarantee that such information may not be accessed, disclosed, altered or +destroyed by breach of such firewalls and secure server software.
    • + +
    + +privacy@livejournal.com. p?> + + + +
      + +
    • You can edit your LiveJournal.com Account Information at any time. +Most personal information you may provide is entirely optional. For +example, to the extent that parents are considering whether to permit their +children to use the Service, we do not condition a child's participation +based upon their provision of any more personal information than is +necessary to operate the Service.
    • + +
    • You can delete your LiveJournal.com account by visiting our Account +Deletion page; however, please note that some personal information, +primarily your contact information, may remain in LiveJournal.com's records +to the extent necessary to protect LiveJournal's legal interests or +document compliance with regulatory requirements.
    • + +
    + +Contacting LiveJournal h1?> + +privacy@livejournal.com. +Alternatively, we can be reached by telephone at 415-344-0056 or our postal +mail address: p?> + +
    + +
    + + + + + +Effective Date: January 5th, 2005 p?> + +<=body +page?> diff --git a/ljcom/htdocs/legal/tos-mini.bml b/ljcom/htdocs/legal/tos-mini.bml new file mode 100644 index 0000000..6dcaa25 --- /dev/null +++ b/ljcom/htdocs/legal/tos-mini.bml @@ -0,0 +1,25 @@ + + + + + + +0 +code=>0 +file=>legal-tos +_include?> + + diff --git a/ljcom/htdocs/legal/tos.bml b/ljcom/htdocs/legal/tos.bml new file mode 100644 index 0000000..a78520e --- /dev/null +++ b/ljcom/htdocs/legal/tos.bml @@ -0,0 +1,67 @@ +Terms of Service +head<= + +<=head +body<= + +tosagree_verify) { + + if (LJ::did_post()) { + my $err; + unless ($remote->tosagree_set(\$err)) { + return LJ::bad_input($err); + } + return + "" . + "" . + ""; + } + + my $htmlstr = LJ::tosagree_str('tos.bml' => 'html'); + return + " 'title') . " h1?>" . + ($htmlstr ? "" : '') . ""; + } + + return ''; +} +_code?> + +0 +code=>0 +file=>legal-tos +_include?> + +tosagree_verify) { + return + "" . + "

    " . + LJ::html_submit('agree_tos' => BML::ml('tos.haveread')) . + "

    "; + } + + return ''; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/manage/files.bml b/ljcom/htdocs/manage/files.bml new file mode 100644 index 0000000..a0bcf8d --- /dev/null +++ b/ljcom/htdocs/manage/files.bml @@ -0,0 +1,679 @@ +File Manager +body<= +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + # KiB vs MiB byte conversions / printing + my %shift = ( MiB => 1 << 20, KiB => 1 << 10 ); + my $size = sub { + my $bytes = shift; + # Display in Mb or Kb? + return sprintf("%.2f MiB", $bytes / $shift{MiB}) if $bytes >= $shift{MiB}; + return sprintf("%.2f KiB", $bytes / $shift{KiB}); + }; + + # for reporting error + my $err = sub { return "" }; + + # what type of blob to show + my $showtype = $GET{'showtype'}; + + # extra arguments for get requests + # how to make links back to this page + my $self_link = sub { + my $page = shift || $GET{'page'}; + my $sort = shift || $GET{'sort'}; + + my $uri = "files.bml?"; + $uri .= "authas=$authas&" if $authas ne $remote->{'user'}; + $uri .= "showtype=$showtype&" if $showtype; + $uri .= "page=$page&" if $page > 1; + $uri .= "sort=$sort&" if $sort; + chop $uri; + + return $uri; + }; + + # how to make a sort link back to this page, + # given a sort type and name + my $sort_link = sub { + my ($sort, $name) = @_; + return $name unless $sort; + + my $type = $GET{'sort'} eq "${sort}_asc" + ? "${sort}_desc" : "${sort}_asc"; + return "$name"; + }; + + # declare these up here so closures below can use them + my %blobs = (); # { 'blobid' => blob object }, references into @blobs + my @blobs = (); # [ { blob object }, { ... }, ... ] + my ($domain, $domainid); # blob domain/id + my ($dbh, $dbcm); + + my %btype = (); + + ### + ### Userpic handler functions + ### + $btype{'userpic'} = { + 'name' => "Userpics", + + # how to sort various columns + 'sort' => sub { + my $sort = $GET{'sort'}; + my $cmp = sub { $b->{'length'} <=> $a->{'length'} }; + + # numeric <=> comparison + if ($sort =~ /^(kw_ct|width|height|length)_(asc|desc)$/) { + my ($meth, $dir) = ($1, $2); + + if ($dir eq 'desc') { + $cmp = sub { $b->{$meth} <=> $a->{$meth} }; + } elsif ($dir eq 'asc') { + $cmp = sub { $a->{$meth} <=> $b->{$meth} }; + } + + # string 'cmp' comparison + } elsif ($sort =~ /^(picdate|ext)_(asc|desc)$/) { + my ($meth, $dir) = ($1, $2); + + if ($dir eq 'desc') { + $cmp = sub { $b->{$meth} cmp $a->{$meth} }; + } elsif ($dir eq 'asc') { + $cmp = sub { $a->{$meth} cmp $b->{$meth} }; + } + } + + return sort $cmp @blobs; + }, + + # how to fetch userpic objects from the database + 'fetch' => sub { + my @ids = map { $_->{'blobid'} } @blobs; + my $bind = join(",", map { "?" } @ids); + my $sth; + if ($u->{'dversion'} > 6) { + my $dbcr = LJ::get_cluster_def_reader($u); + $sth = $dbcr->prepare("SELECT picid, fmt, width, height, " . + "state, picdate FROM userpic2 " . + "WHERE userid=$u->{'userid'} AND picid IN ($bind)"); + } else { + $sth = $dbh->prepare("SELECT picid, contenttype, width, height, " . + "state, picdate FROM userpic " . + "WHERE picid IN ($bind)"); + } + $sth->execute(@ids); + while (my $row = $sth->fetchrow_hashref) { + my $picid = $row->{'picid'}; + $row->{'length'} = $blobs{$picid}->{'length'}; + $blobs{$picid} = $row; + } + @blobs = values %blobs; + + # add in keywords + my $upicinf = LJ::get_userpic_info($u); + while (my ($k, $v) = each %{$upicinf->{'kw'}}) { + push @{$blobs{$v->{'picid'}}->{'kw'}}, $k; + } + + # don't need keyword array though, + # 'kw_str' => comma separated keywords + # 'kw_ct' => count of keywords, for sorting + foreach my $bl (@blobs) { + $bl->{'kw_str'} = join(", ", @{$bl->{'kw'}||[]}); + $bl->{'kw_ct'} = scalar(@{$bl->{'kw'}||[]}); + delete $bl->{'kw'}; + + # convert mime type to filetype (ext) + if ($u->{'dversion'} > 6) { + $bl->{'ext'} = { + 'G' => 'gif', + 'J' => 'jpg', + 'P' => 'png', + }->{$bl->{'contenttype'}}; + } else { + $bl->{'ext'} = { + 'image/gif' => 'gif', + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + }->{$bl->{'contenttype'}}; + } + delete $bl->{'contenttype'}; + } + }, + + # deletes blobs which need to be deleted based on %POST + 'delete' => sub { + + # find picids to delete + my @del = (); + foreach my $id (map { $_->{'picid'} } @blobs) { + push @del, $id if $POST{"del_${id}"}; + } + return 0 unless @del; + + # try and delete from either the blob server or database, + my $deleted = 0; + my $bind = join(",", map { "?" } @del); + if ($LJ::USERPIC_BLOBSERVER) { + + # delete blobs from blobserver + foreach my $picid (@del) { + LJ::Blob::delete($u, $domain, $blobs{$picid}->{'ext'}, $picid); + } + $deleted = 1; + + } elsif ($u->do("DELETE FROM userpicblob2 WHERE ". + "userid=? AND picid IN ($bind)", undef, + $u->{userid}, @del) > 0) { + $deleted = 1; + } + if ($deleted) { + if ($u->{'dversion'} > 6) { + $u->do("DELETE FROM userpic2 WHERE userid=? IN ($bind)", + undef, $u->{'userid'}, @del); + } else { + $dbh->do("DELETE FROM userpic WHERE picid IN ($bind)", + undef, @del); + } + $u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " . + "AND blobid IN ($bind)", undef, $u->{'userid'}, + $domain, @del); + + # userpics changed, need to reactivate + LJ::activate_userpics($u); + } + + return scalar(@del); + }, + + # renders userpic rows in the table (including column headings) + 'render' => sub { + my $ret; + + $ret .= " "; + + my $eff_sort = + $GET{'sort'} =~ /^(kw_ct|picdate|width|height|length|ext)_(asc|desc)$/ + ? $GET{'sort'} : "length_desc"; + + # display column headings + foreach ([undef, "Image"], ['kw_ct', "Keywords"], ['picdate', "Date Uploaded"], + ['width', "Width"], ['height', "Height"], ['length', "Filesize"], + ['ext', "Type"]) { + + $ret .= "[0] eq 'subject'; + $ret .= ">" . $sort_link->(@$_); + + if ($eff_sort =~ /^$_->[0]_(asc|desc)$/) { + my $pref = $1 eq 'asc' ? "down" : "up"; + $ret .= "{'picid'}; + + # delete checkbox + $ret .= ""; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => "del_${picid}", + 'id' => "del_${picid}", 'value' => 1 }) . ""; + + # display userpic + $ret .= ""; + + # keywords, date/time + $bl->{'kw_str'} ||= "none"; + foreach (qw(kw_str picdate)) { + $ret .= "$bl->{$_}"; + } + + # width/height + foreach (qw(width height)) { + $ret .= "$bl->{$_}px"; + } + + # file size + my $len = sprintf("%.1fk", $bl->{'length'} / 1000); + $ret .= "$len"; + + # typs + $ret .= ""; + $ret .= uc($bl->{'ext'}) . ""; + } + + # delete button + $ret .= ""; + $ret .= LJ::html_submit('action:delete', "Delete Selected") . ""; + $ret .= "["; + $ret .= "Upload new userpics]"; + + return $ret; + }, + }; + + ### + ### PhonePost handler functions + ### + $btype{'phonepost'} = { + 'name' => "Phone Posts", + + # how to sort phonepost rows, for each column type + 'sort' => sub { + my $sort = $GET{'sort'}; + my $cmp = sub { $b->{'length'} <=> $a->{'length'} }; + + # numeric <=> comparison + if ($sort =~ /^(length|lengthsecs|posttime)_(asc|desc)$/) { + my ($meth, $dir) = ($1, $2); + + if ($dir eq 'desc') { + $cmp = sub { $b->{$meth} <=> $a->{$meth} }; + } elsif ($dir eq 'asc') { + $cmp = sub { $a->{$meth} <=> $b->{$meth} }; + } + + # string 'cmp' comparison + } elsif ($sort =~ /^subject_(asc|desc)$/) { + if ($1 eq 'desc') { + $cmp = sub { $b->{'subject'} cmp $a->{'subject'} }; + } else { + $cmp = sub { $a->{'subject'} cmp $b->{'subject'} }; + } + } + + return sort $cmp @blobs; + }, + + # populates @/%blobs from database + 'fetch' => sub { + + # get data from phonepostentry + my $bind = join(",", map { "?" } @blobs); + my $sth = $dbcm->prepare("SELECT blobid, jitemid, anum AS pp_anum, " . + "lengthsecs, posttime, filetype FROM phonepostentry " . + "WHERE userid=? AND blobid IN ($bind)"); + $sth->execute($u->{'userid'}, map { $_->{'blobid'} } @blobs); + while (my $row = $sth->fetchrow_hashref) { + my $bid = $row->{'blobid'}; + $row->{'length'} = $blobs{$bid}->{'length'}; + + # convert filetype to extension + $row->{'ext'} = $row->{'filetype'} == 1 ? "ogg" : "mp3"; + delete $row->{'filetype'}; + + $blobs{$bid} = $row; + } + @blobs = values %blobs; + + # now get subject from logtext2 + my $logtext = LJ::get_logtext2($u, map { $_->{'jitemid'} } @blobs); + foreach my $bl (@blobs) { + my $jitemid = $bl->{'jitemid'}; + next unless ref $logtext->{$jitemid} eq 'ARRAY'; + + # subject and has_entry keys + $bl->{'subject'} = $logtext->{$jitemid}->[0]; + $bl->{'has_entry'} = 1; + + # also get log2 row so we can see security + my $log = LJ::get_log2_row($u, $jitemid); + if (ref $log eq 'HASH') { + $bl->{'security'} = $log->{'security'}; + $bl->{'l_anum'} = $log->{'anum'}; + } + } + + return; + }, + + # deletes blobs which need to be deleted based on %POST + 'delete' => sub { + + # find picids to delete + my @del = (); + foreach my $id (map { $_->{'blobid'} } @blobs) { + push @del, $id if $POST{"del_${id}"}; + } + return 0 unless @del; + + return 0 unless $u->writer; + + # delete from userblob (journalid, domain, blobid) + my $bind = join(",", map { "?" } @del); + $u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " . + "AND blobid IN ($bind)", undef, $u->{'userid'}, + $domainid, @del); + + # delete blobs from blobserver + foreach my $bid (@del) { + my $ppe = LJ::PhonePost::get_phonepost_entry($u, $bid); + if ($ppe->{location} eq 'mogile') { + LJ::mogclient()->delete("pp:$u->{userid}:$bid"); + } else { + LJ::Blob::delete($u, $domain, $blobs{$bid}->{'ext'}, $bid); + } + } + + # update phonepost entry locations to be 'none' + $u->do("UPDATE phonepostentry SET location='none' WHERE userid=? AND blobid IN ($bind)", + undef, $u->{userid}, @del); + + return scalar(@del); + }, + + # generate phonepost table rows + 'render' => sub { + my $ret; + + $ret .= " "; + + my $eff_sort = + $GET{'sort'} =~ /^(subject|length|lengthsecs|posttime)_(asc|desc)$/ + ? $GET{'sort'} : "length_desc"; + + # table heading + foreach ([undef, "Audio"], ['subject', "Subject"], ['posttime', "Date/Time"], + ['lengthsecs', "Duration"], ['length', "Filesize"]) { + + $ret .= "[0] eq 'subject'; + $ret .= ">" . $sort_link->(@$_); + + if ($eff_sort =~ /^$_->[0]_(asc|desc)$/) { + my $pref = $1 eq 'asc' ? "down" : "up"; + $ret .= "{'blobid'}; + + # delete checkbox + $ret .= ""; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => "del_${blobid}", + 'value' => 1, 'selected' => 0 }) . ""; + + # link to phonepost + { + $ret .= ""; + $ret .= LJ::PhonePost::make_link($remote, $u, $bl->{'blobid'}, 'bare'); + } + + # link to original entry + my $subject = "No associated journal entry"; + if ($bl->{'has_entry'}) { + $subject = "{'l_anum'}); + $subject .= "'>" . ($bl->{'subject'} || "no subject") . ""; + } + $ret .= "$subject"; + + # date/time + my $datetime = LJ::mysql_time($bl->{'posttime'}); + $ret .= "$datetime"; + + # length + my $secs = int($bl->{'lengthsecs'} / 60) . ":"; + $secs .= sprintf("%02ds", $bl->{'lengthsecs'} % 60); + $ret .= "$secs"; + + # file size + my $len = sprintf("%.1fk", $bl->{'length'} / 1000); + $ret .= "$len"; + + # security + $ret .= ""; + if ($bl->{'security'} && $bl->{'security'} ne 'public') { + $ret .= ""; + + return $ret; + } + }; + + # All of this is managed on the FotoBilder side of things, so just give total + # usage info, and a link to where they can manage it. + if (LJ::get_cap($u, 'fb_account')) { + $btype{'fotobilder'} = { + 'name' => "Photo Hosting", + 'sort' => sub {}, + 'delete' => sub {}, + 'fetch' => sub {}, + 'render' => sub + { + my $ret; + + my $pp_bytes = LJ::Blob::get_disk_usage($u, 'fotobilder'); + my $pp_display = $size->($pp_bytes); + + my $max_size = LJ::get_cap($u, "disk_quota") * $shift{MiB}; + my $ret; + + $ret .= ''; + foreach (' ', 'Images', 'Filesize Totals') { + $ret .= "$_"; + } + $ret .= ''; + + $ret .= " "; + $ret .= ""; + $ret .= " $showtype) if $showtype; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "\n\n"; + + # domain type selector + $ret .= "
    File Type: "; + $ret .= LJ::html_hidden('authas' => $authas) if $authas ne $remote->{'user'}; + $ret .= LJ::html_select({ 'name' => 'showtype', 'selected' => $showtype }, + '' => '---', + map { $_ => $btype{$_}->{'name'} } sort keys %btype) . " "; + $ret .= LJ::html_submit("Show") . "
    "; + + # show quota info + my $used_size = LJ::Blob::get_disk_usage($u); + my $max_size = LJ::get_cap($u, "disk_quota") * $shift{MiB}; + + if ($max_size) { + + $ret .= ""; + $ret .= "

    You are currently using " . $size->($used_size) . " ("; + $ret .= sprintf("%.2f%%", ($used_size / $max_size) * 100); + $ret .= ") of your " . $size->($max_size) . " quota.

    "; + } + + return $ret unless defined $btype{$showtype}; + + ### + ### LOAD DATA + ### + + # now we have a showtype + $domain = $showtype; + $domainid = LJ::get_blob_domainid($domain); + my $bobj = $btype{$showtype}; + + # get db handle now + $dbh = LJ::get_db_writer(); + $dbcm = LJ::get_cluster_master($u); + return $err->($ML{'error.nodb'}) unless $dbh && $dbcm; + + # fetch data from userblob + my $sth = $dbcm->prepare("SELECT blobid, length FROM userblob " . + "WHERE journalid=? AND domain=?"); + $sth->execute($u->{'userid'}, $domainid); + while (my $row = $sth->fetchrow_hashref) { + push @blobs, $row; + } + + # no blobs? + unless (@blobs) { + $ret .= ""; + $ret .= ""; + return $ret; + } + + # generate paging object and make a navbar + my $page_size = 25; + my %items = BML::paging(\@blobs, $GET{'page'}, $page_size); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}, + { 'self_link' => $self_link }); + @blobs = @{$items{'items'}}; + + # get only this page of blobids + $blobs{$_->{'blobid'}} = $_ foreach @blobs; + + # call data-getter to fill in the rest of blob data + $bobj->{'fetch'}->(); + + # sort blobs into specified order + @blobs = $bobj->{'sort'}->(); + + + # if a blob's id is in the blobid list, but we got nothing from the + # database, then we'll remove its entry from userblob because we + # forgot to remove the row in editpics.bml + if ($showtype eq 'userpic') { + my @del; + foreach my $bl (@blobs) { + + # see if required 'picdate' column was added in + push @del, $bl->{'blobid'} unless + $bl->{'picdate'}; + } + if (@del) { + return $err->($ML{'error.nodb'}) unless $u->writer; + + my $bind = join(",", map { "?" } @del); + $u->do("DELETE FROM userblob WHERE journalid=? AND domain=? " . + "AND blobid IN ($bind)", undef, $u->{'userid'}, $domainid, @del); + + return BML::redirect($self_link->()); + } + } + + ### + ### Perform actions + ### + if (LJ::did_post() && $POST{'action:delete'}) { + + my $res = $bobj->{'delete'}->(); + if ($res) { + # now the database has been modified and deleted, but our current + # memory state isn't accurate, so we'll have to redirect and start + # over before displaying anything below + return BML::redirect($self_link->()); + } + } + + ### + ### Generate page + ### + + # output table + $ret .= $navbar; + $ret .= "
    "; + + $ret .= ""; + $ret .= $bobj->{'render'}->(); + $ret .= "
    "; + + $ret .= $navbar; + + return $ret; +} +_code?> +<=body +head<= + +<=head +page?> diff --git a/ljcom/htdocs/manage/phonepost.bml b/ljcom/htdocs/manage/phonepost.bml new file mode 100644 index 0000000..613bcd1 --- /dev/null +++ b/ljcom/htdocs/manage/phonepost.bml @@ -0,0 +1,138 @@ + +body<= +" + if $remote && $remote->{journaltype} ne 'P'; + + return $LJ::MSG_READONLY_USER if LJ::get_cap($remote, "readonly"); + + my ($ret, $saved); + my %errors; + my $error_msg = sub { + my $key = shift; + my $msg = $errors{$key}; + return unless $msg; + return ""; + }; + + my %formats = ( + 'ogg', 'Ogg Vorbis', + 'wav', 'Wav (GSM encoded)' + ); + $formats{'mp3'} = 'Mp3' if $LJ::PHONEPOST_MP3; + + POST: + while ($remote && LJ::did_post()) { + my $phone = $POST{phone}; + my $trans = $POST{trans}; + my $format = $POST{format}; + my $pin = $POST{pin}; + + if ($POST{delete}) { + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM phonepostlogin WHERE userid=?", undef, $remote->{userid}); + return ""; + } + + $phone =~ s/\D//g; + $errors{'.phone'} = $ML{'.error.phone.length'} + unless length $phone >= 10; + + $errors{'.pin'} = $ML{'.error.pin'} if $pin =~ /\D/ or + length $pin < 1; + + my $dbh = LJ::get_db_writer(); + my $prevuserid = $dbh->selectrow_array("SELECT userid FROM phonepostlogin ". + "WHERE phone=? AND pin=?", undef, + $phone, $pin); + $errors{'.pin'} = $ML{'.error.inuse'} if $prevuserid && $prevuserid != $remote->{userid}; + + my $grouplist = LJ::get_friend_group($remote); + $errors{'.transcribers'} = $ML{'.error.transcription'} + unless $trans == -1 || $trans == 0 || defined $grouplist->{$trans}; + + $errors{'.format'} = "Bad format selected." unless $formats{$format}; + + last POST if %errors; + + $dbh->do("REPLACE INTO phonepostlogin ". + "(phone, pin, userid) VALUES (?, ?, ?)", undef, + $phone, $pin, $remote->{userid}); + + LJ::set_userprop($remote, 'pp_transallow', $trans); + LJ::set_userprop($remote, 'pp_format', $format); + + $saved .= ""; + $saved .= ""; + $saved .= ""; + last; + } + + my $grouplist = LJ::get_friend_group($remote); + + my $tableline = sub { + my ($mlcaption, $content) = @_; + my $err = $error_msg->($mlcaption); + return "$ML{$mlcaption}$content\n$err"; + }; + + my $dbr = LJ::get_db_reader(); + my ($phone, $pin); + + if ($remote) { + ($phone, $pin) = $dbr->selectrow_array( + "SELECT phone, pin FROM phonepostlogin ". + "WHERE userid=?", undef, + $remote->{userid}); + LJ::load_user_props($remote, qw/ pp_transallow pp_format /); + $ret .= $ML{'.intro.loggedin'}; + } else { + $ret .= ""; + } + + $phone = $POST{'phone'} ? $POST{'phone'} : $phone; + $pin = $POST{'pin'} ? $POST{'pin'} : $pin; + + $ret .= "
    \n"; + $ret .= ""; + $ret .= $tableline->('.phone', + LJ::html_text({name => 'phone', value => $phone, + maxlength => 25, disabled => !$remote})); + + $ret .= $tableline->('.pin', + LJ::html_text({name => 'pin', value => $pin, type => 'password', + maxlength => 8, disabled => !$remote})); + + my $default_format = $remote->{pp_format} || ($LJ::PHONEPOST_MP3 ? 'mp3' : 'ogg'); + + $ret .= $tableline->('.format', + LJ::html_select({ name => 'format', selected => $default_format }, %formats)); + + $ret .= $tableline->('.transcribers', + LJ::html_select({ name=>'trans', selected=>$remote->{pp_transallow} }, + 0,'All friends',-1,'No one but you', + map { $_, $grouplist->{$_}->{groupname} } + sort {$grouplist->{$a}->{groupname} cmp $grouplist->{$b}->{groupname}} + keys %$grouplist)); + + $ret .= '
     ' . LJ::html_submit('save', $ML{'.save'}, { disabled => !$remote }) . ''; + $ret .= LJ::html_submit('delete', $ML{'.delete'}, { disabled => !$remote}) . '

    '; + $ret .= "
    "; + + $ret .= $saved if $saved; + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/misc/clusterlj/index.html b/ljcom/htdocs/misc/clusterlj/index.html new file mode 100644 index 0000000..4ee3e6a --- /dev/null +++ b/ljcom/htdocs/misc/clusterlj/index.html @@ -0,0 +1,66 @@ + + + + Clustering LiveJournal + + + +

    Clustering LiveJournal

    +

    Brad Fitzpatrick & lj_dev crew

    + +

    Introduction

    +

    +LiveJournal was originally designed to be used by 10 people, myself +and a few friends. Over time the design has been tweaked to let it +scale further, but the basic design is still the same. We're fast +approaching the time when there's nothing left to optimize, other than +the architecture itself. That's what this page is about. +

    + +

    Current Architecture

    +

    +Currently, there is one master database, 5 slave databases, and a ton +of web servers. A request comes in to the load balancer where it is +then given to the "best" web server. Each web server runs tons of +processes which all maintain a database connection to the master and +to a slave. All update operations go to the master. Read operations +go to a slave, or fall through to the master if the slave is behind. +

    +

    +The problem with this setup is that we're evenly dividing our reads +between slaves but each slave db has to do every write. Imagine that each database server has t units of time. Further imagine that a write takes 2 units of time and a read takes 1 unit. Say we're doing n reads & writes. Now, let us have s slaves. As n increases, each slave is requiring n*2 + (n/s) units of time. Even if we keep increasing s, the number of slave databases, the real problem is that n*2 keeps growing, taking away time those database servers could be serving read requests. +

    +

    +Worse, each slave won't have the disk capacity to hold the entire database. Even if it did, though, the bigger problem is that the machines' memory is finite, so if the db size on disk is growing and the memory size is fixed (all our slaves have a 2GB or 4GB limit... only our master can go up to 16GB), then as the on-disk size grows, the cache hit rate drops incredibly fast. Once you're not hitting the cache, things start to suck with a quickness. The speed of a disk seek compared to a fetch from memory is astronomical. Disks suck. +

    +

    Tricks

    +

    +Right now, we do some tricks to get by with the above +architecture. The largest tables we only replicate (from master to +slave) a subset of the data. That's why we have the +recent_logtext and recent_talktext tables. A cron +job deletes everything older than 2 weeks from this table every day. +The web servers try the recent tables on the slave dbs first, then +fall back to using the master tables. +

    +

    +The next thing we did was have one database that replicated nothing but the recent tables, then all the web servers had 3 db connections open... text slave, general slave, and master. This improved the cache hits everywhere, since the dbs were now specialized. The general slaves even improved, since they didn't have all that text getting in the way of the selects from the log table, notably. +

    + +

    The Plan

    +

    +The plan has undergone modification over time as we refine it. +

    +

    + +
    +
    Brad Fitzpatrick
    + + +Last modified: Wed Dec 12 09:32:13 PST 2001 + + + diff --git a/ljcom/htdocs/misc/clusterlj/ljarch.png b/ljcom/htdocs/misc/clusterlj/ljarch.png new file mode 100644 index 0000000000000000000000000000000000000000..09f6fd8f213025c65828f092d9aa3cab8e6cbcdf GIT binary patch literal 4149 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 + + + Clustering LiveJournal + + + +

    Clustering LiveJournal

    +

    Brad Fitzpatrick & lj_dev crew

    + +

    Introduction

    +

    +The problem is described here. The following solution is a rough draft. Future refinements of this solution are posted below the aforelinked introduction. +

    + +

    The Plan; Revision 1

    +

    +The ultimate ideal would be to have LiveJournal to scale linearly with the number of servers we buy. And that's exactly what this aims to do. +

    +

    +The new plan is to have a bunch of indepedent clusters, each with a pool of ~5 web servers and at least 2 database servers. All of a user's data would be confined to one cluster. A new 'clusterid' column in the user table would specify which cluster that user is on. As new users join, we simply build a new cluster and start putting users there, keeping the old clusters running as they were. If people stop using the service, older clusters will free up, so we can put users there. +

    +

    Before I go further, a picture I whipped up in ViSiO:

    +

    mad art skills

    +

    +What's it all mean? +

      +
    • Cloud -- this is the Internet. It's always drawn as a cloud.

      + +
    • Load Balancer -- this is our pair of BIG/ips... it redirects requests places and monitors servers, etc, etc.

      + +
    • BH: redir -- the logic to redirect a request to a certain cluster is too much work for the BIG/ip. We'll need to do database lookups and stuff from the given user field, which'll be in any one of 10 places. Writing candidacy functions for mod_backhand is pretty easy and can be written in C or Perl. Actually, these machines can be on any/all of the cluster web slaves.... there's no need to have them be physically seperate, but it makes for a prettier abstraction on the above picture.

      + +
    • Controller Master -- this is the master database, but now it'll hold a whole ton less than it did before. No log info, no journal text, no comment info, no comment text, no journal styles, no memories, etc, etc. The two important things it'll have will be the user table (for maintaining unique usernames and userids) and the userusage table, so all clusters will be able to know when a friend on a different cluster updated their journal. All of this data is replicated down, but it's incredibly light.

      + +
    • Cluster Master -- all data about a user that isn't stored on the controller master (site global), will be put on that user's cluster master, where it'll replicate down to the cluster's slave(s).

      + +
    • Cluster Slaves -- will only ever need to:

      • write to controller master
      • write to cluster master
      • read from cluster slave (or fallback to cluster master)

      +
    + +Time for another picture: +

    +

    disk usage graph

    + +See that 1% slice for userinterests? That's the largest thing that'll be stored on the controller master. All the other larger stuff (and a bunch of the <1% slices, even) will only be stored on the cluster masters. + +

    Notes

    + +

    Maintaining globally unique AUTO values. +Without everything in one logical database, the AUTO_INCREMENT +columns would have no coordination and multiple clusters could use the same +unique IDs for posts, comments, pictures, memories, etc. To prevent +this, and to make it easier to delete & move users (move is copy + delete), we need to change all these unique primary key auto columns to be dual column primary keys: (userid, autovalue). You just insert the given userid and a NULL for the autovalue and each userid has its own count. That means that people will no longer have itemids with 9 digits and such... everybody's numbers will unique and small to just them. +

    + +

    Legacy ID snapshot. So as to not break links, we'll need a table to map old unique IDs to the (userid, unique) tuples. When these requests are received, the backhander won't know where to throw it, so it'll throw it to any one, which'll then look up its userid, and HTTP redirect it, so the next request (to, say, /talkread.bml?user=test&itemid=32) will know which cluster to assign it to. +

    + +

    Cache benefit. The coolest thing about this is that the +caches on every webserver process and every database server will be a +lot more valid. If MySQL needs to pull in 10 pages from disk to find +4 records, we don't have to worry that all that other data on those +pages is worthless. Now we know that those other records we now have +sitting in memory are also valid for somebody on our cluster. And +because we cap the number of users per cluster, we can ensure that the +cache performance of a cluster stays the same over time. +

    + +

    RPC between clusters. Obivously there's going to need to be +communication between clusters. We started to play with this already, +actually ... just wrap DB calls over HTTP. We'll need this to get +things like get_recent_items for friends view and getting the text +from everything. +

    +

    +It'll be important to request everything that'll be needed to each +cluster in one transaction, so as to maintain round trip latencies +from serializing a bunch of requests. While the number of clusters is +low (~3 - 6) we'll be able to get away with enumerating over the +clusters we need to do RPC with and doing the requests one by one. +In the future it might be nice to parallelize these requests. +

    +

    Actually, I'm probably worrying about this too much. We already do +dozens of DB calls serialized in places. This'll be faster, +as each DB call (albeit over HTTP) will execute faster due to better +cache hits.

    +

    +Another concern you may be having: "But Brad, won't an increased +number of users across all the clusters cause a bunch more RPC +requests to each cluster, thus diminishing the quality of a cluster, +which this whole plan was supposed to address?" Ah, clever you +are. Yes, reads will increase to all clusters as total users and +total clusters grow. But remember, reads are easy to load balance.. +all we have to do is buy more cluster db slaves and spread the +reads evenly. So initially we can start with only 1 or 2 cluster +slaves per cluster. Once our total number of clusters hits 5-6, +it'd be wise to add another db slave to each cluster. +

    + +

    Friends view logic. The userusage table is replicated everywhere, so each cluster will know when their friends updated, and which clusters +to do RPC on. +

    + +

    Backhander. +The backhander will have to look several places in the HTTP request to determine which cluster to throw it to:

      +
    • REQUEST_URI =~ m!^/(users|community|~)/(\w+)! +
    • REQUEST_URI =~ m![\?\&]user=(\w+)! +
    • Post data: user +
    +Anything that doesn't match those, we'll need to make sure it does, or add other rules. +

    + +

    Stats aggregation. + +Each cluster will have to run its own statistics, and then something on mayor wil have to aggregate those. +

    + +

    recent_* tables. +Recent tables could and should probably die. +

    + +

    Moving users between clusters. +It'll be easy to move users between clusters. Now that all data is prefixed with the itemid, finding it and deleting it is easy. The only issue is locking which isn't too hard. We can use GET/RELEASE_LOCK on the controller master as a global mutex mechanism. +

    +

    +When might it be necessary to move users? Imagine we're getting heavy growth and we must temporarily overload the newest cluster while we wait for parts from some slow vendor. Once the new cluster is up, we'll want to move users over. Or, consider that users stop using the site over time. It'd be nice to be able to move users from the busiest cluster over to the ones that are dropping in traffic due to users quitting. etc.., etc... +

    + +

    What's where? +The major things, at least: + + + + + + + + + +
    ClusterEverywhere
    +log, logprop, talk, logtext, talktext, userpicblob (userpic images) + +user, userusuage, generic files, site images +
    +This isn't meant as a definitive list. If you want to start hacking on some part (see the implementation plan below), then check with the code@ mailing list to see where the table/service in question will live. +

    + +

    Directory implications. +
    (22:39:01) Foobar: So here's a question that may or may not be relevant: how would the directory fit into this? +
    (22:39:30) Foobar: just query each cluster and aggregate and sort them after they all return? +
    (22:39:35) brad: basically, yeah +
    (22:39:53) Foobar: sounds potentially ugly, but I guess it's workable +

    + +

    What cluster do new users go to? +The least loaded/newest cluster. +

    + +

    Are there still free/paid servers? +We could have a paid cluster, but it seems quite silly, since that paid cluster would have to RPC over to the free clusters. Plus, having a paid cluster would involve moving tons of people each day both back and forth. So the plan is to NOT have seperate clusters, and just make everything incredibly fast. If bandwidth gets too expensive, we could force free users to have an obligatory 30ms latency, which would still be about 3870ms better than what it is now. Please, don't compain about this ... we have no obligation to give away infinite CPU and bandwidth to everybody for free. We realize that free users constitute the overwhelming majority, so free service will always be good (that's our goal), but we want to be able to give paid users a little bit extra always, so if we artificially limit the speed of free access while lower our costs, so be it. +

    +

    +But won't this bring down paid account sales, if free servers are fast enough? Perhaps, but who cares... having shitty service is a poor excuse to profit. We'll make up for the lost sales due to fast servers by offering all the features we've been saying we're going to do forever. Hell, a bunch of them are already 80% written but we've been too busy keeping the site alive. Once the site is permanently alive we can focus on spending time writing fun stuff instead. +

    + +

    So now the BIG/ips don't do much, huh? Yeah, not quite as much. Right now we have a huge ruleset that gets run on the BIG/ip for each request. That'd be simplified quite a bit and the mod_backhand code will do the work now. +

    + + +

    Implementation Plan

    +

    +This is a lot of tedious work, but it's all very trivial. Luckily though, it's high parallelizable. +

    +
      +
    • Unique ID Split. The first thing that needs to happen is splitting all the unique IDs into (userid, unique) tuples. We can and should put this live after testing before we do the rest. The side benefit is that we'll be able to delete users incredibly easy then, so we'll be able to delete a lot of data before we later move everybody onto their clusters.

      + +
    • Backhander. We need to write the backhander candidacy function. It might be easiest to hire a backhand guru to do it. I know two people that'd probably be down. Otherwise it shouldn't be too hard.

      + +
    • clusterid column. We need to add the clusterid column to the user table, set to 0 for everybody inititally. 0 will mean "the big monolithic cluster", which is how much LJ sites will run. I haven't decided yet if we'll need to special-case 0 to mean no cluster (on the old system) or if it'll just be another cluster, much larger than the others at first.

      + +
    • RPC code. Any code that depends on accessing data from table for a userid that doesn't exist on that cluster will need to be rewritten to do RPC to the appropriate cluster. The main place is friends views. There are a ton of smaller areas, but to begin with we'll replicate a bunch of the <1% slice tables, even though they could later be cluster-only, just to make our lives easier at first.

      + +
    • Ton of testing. We'll need to run test transitions over and over until we're sure it's perfect. I'll be setting up a few machines to simulate different clusters (each with web & db server).

      +
    + +

    Conclusion

    +

    +It's time to get serious. I'm sick of dumb hacks. All those dumb hacks were nice, and a large number of them will still be applicable and carry over and benefit us in the new code, but the root problem (dbs sucking over time) needs to be solved. +

    +

    +Please help me out with this. I can't wait until we can just buy 4-6 more machines and put a new cluster online, letting us grow with diminishing the quality of service for the other clusters. I can't wait until I can spend my time programming fun new features instead of just keeping the site alive. +

    + +
    +
    Brad Fitzpatrick
    + + +Last modified: Mon Jan 21 19:34:50 PST 2002 + + + diff --git a/ljcom/htdocs/misc/clusterlj/rev02.html b/ljcom/htdocs/misc/clusterlj/rev02.html new file mode 100644 index 0000000..a1c4f42 --- /dev/null +++ b/ljcom/htdocs/misc/clusterlj/rev02.html @@ -0,0 +1,90 @@ + + +Clustering LiveJournal Take 2 + + + +

    Differences from Revision 1

    +

    The following are the major differences from revision 1 of our clustering plan. +

    + +

    No clustering of web slaves; no backhand redirection

    +

    +This is the main difference. We're only clustering databases. +This means we don't need the backhand redirector machines to look at URIs +and redirect requests to the right pool of webslaves. And this also means +we can still have premium faster paid servers. +

    + +

    No RPC between clusters

    +

    +Each webslave will talk directly to the DB it needs to using DBI, +rather than doing some HTTP wrapper kludge. The point of the RPC +wrapper before was to prevent the cluster master DBs from having five +billion connections from a half billion web slaves. But really, MySQL +handles insane numbers of connections anyway (if thy're mostly idle, +as they will be). If we need to serialize requests later between a +smaller number of db connections, we'll just do that, making each +machine have a pool of connections they have to share. +

    +

    +Why all idle you say? Well, web slaves continues to grow over time, +but we limit the number of users/traffic/load per db cluster. So +divide. Each web slave will eventually get a master connection, and +the master traffic is fixed, so over time, a smaller number of those +connections will be active. When it gets too extreme, we either +cluster web slaves or make the DB connection pool. But we can deal +with this later. Both solutions are easy enough, but they're boring +to care about now. +

    + +

    Cluster Tables

    + +Tables that can be found on each cluster are as follows: + + +
      +
    • talk2
    • +
    • talktext2
    • +
    • talkprop2
    • +
    • log2
    • +
    • logsec2
    • +
    • logtext2
    • +
    • logsubject2
    • +
    • logprop2
    • +
    • syncupdates2
    • +
    • userbio
    • +
    • talkleft
    • +
    +
    + +These tables will replace the tables on the original master server with the +similar names (i.e. without the 2 appended.) userbio is the same. + +

    Currently, a user can conceivably be on either the original master database +or in one of the myriad clusters available. To detect what the case may be, +examine the clusterid element of the user's entry in the user +table. If clusterid == 0 then the user is located on the old +master database and their data needs to be loaded from the old tables; otherwise, +the data is located on cluster #clusterid using the new table names +above.

    + +

    For future expansion, the element dversion is also added to +the user table. If dversion == 0 then the user is not +on a cluster, i.e. they're on the original master system. dversion == 1 +implies that the user is located on a cluster. As more of the user's data is +moved to the clusters, dversion will increase. Note that any dversion >= 1 means +the user is on a cluster. The plan is for higher dversion numbers to indicate +that more per user data is moved from the original setup to the clustering system.

    + +

    Conversion from dversion 0 to dversion 1 will be a lazy conversion. This +involves the READ_ONLY capability code. Basically, the user's READ_ONLY +capability bit will be set and then the code will pause for a minute or +two to allow any pending transactions to go through. After this, all +data will be copied from the old database system into the appropriate +cluster. After everything is copied, the data is deleted from the old +system and the users's READ_ONLY capability bit is toggled off.

    + + + + diff --git a/ljcom/htdocs/misc/clusterlj/usagepie-large.png b/ljcom/htdocs/misc/clusterlj/usagepie-large.png new file mode 100644 index 0000000000000000000000000000000000000000..57851e335975e8cfd8a010f3e07e66f4b4258a2d GIT binary patch literal 11624 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 + + + LiveJournal.com Goals + + + +

    LiveJournal.com Goals

    + +

    + Every so often make a graph visualizing where we are and what we need to do. +

    + + + + + diff --git a/ljcom/htdocs/misc/goals/goals-20020209.gif b/ljcom/htdocs/misc/goals/goals-20020209.gif new file mode 100644 index 0000000000000000000000000000000000000000..48fc0644381d2c985ea08079fe9d43788a88d878 GIT binary patch literal 150529 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 z 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 X9miC!K&JI#Db-`1iHZ#myZ!$Fp6eKB literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/misc/goals/goals-20020209.html b/ljcom/htdocs/misc/goals/goals-20020209.html new file mode 100644 index 0000000..53358b7 --- /dev/null +++ b/ljcom/htdocs/misc/goals/goals-20020209.html @@ -0,0 +1 @@ +Goals as of 2002-02-09

    \ No newline at end of file diff --git a/ljcom/htdocs/misc/goals/goals-20020605.gif b/ljcom/htdocs/misc/goals/goals-20020605.gif new file mode 100644 index 0000000000000000000000000000000000000000..5661f9ad9c85d1928a49c3e59b4f5a3f5a2e64b5 GIT binary patch literal 131547 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

    BEpZK68e$%D*g*=D(^|27g4v;j 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 T_B&zB&4~|Pc0|UHy667^l4uzu literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/misc/goals/goals-20020605.html b/ljcom/htdocs/misc/goals/goals-20020605.html new file mode 100644 index 0000000..24ad2f5 --- /dev/null +++ b/ljcom/htdocs/misc/goals/goals-20020605.html @@ -0,0 +1 @@ +Goals as of: 2002-06-05

    \ No newline at end of file diff --git a/ljcom/htdocs/misc/index.html b/ljcom/htdocs/misc/index.html new file mode 100644 index 0000000..d4b0426 --- /dev/null +++ b/ljcom/htdocs/misc/index.html @@ -0,0 +1 @@ + diff --git a/ljcom/htdocs/misc/ljlogo/lj.ico b/ljcom/htdocs/misc/ljlogo/lj.ico new file mode 100644 index 0000000000000000000000000000000000000000..f3d21ec5e8f629b77c77615982cef929802fbde4 GIT binary patch literal 5222 zcmdT{3s6+o89vBPQIq*$1QbbvAP7Q0Tpmk!l@)pHf>>S> z1vbL6JXf&Eq~nt$W+Y}?NhYbg%X2}TX`y3UlPS(H)68fPIsMMP%d)ZvOQtiO{(Js= z?m7Sef9JdZJ&(JD*bxy~wQ3b%;$cU~E2vFPBC#hV6@5-lg8iE%gba#Un|TxR-jjq} zb3h#KnTHdU;W5$jSK%T=Pj@H?K_Lo-P~nPOqSb0qGXv!dp_JW0@nc==!i$LGD~{u9 zt~8U?B2Fd~qvpC~M^KA`gqqWJF*i|=E@%ujnuad%Of!pb5`P(QC7kR#SP2OTzQ<#W zlv%8aIKD~feX!6nCX`OuQ922|4;{CsbQG#}pj5FEW=E(mRL;B7LWEq0KANYW^3Y=B z_y|vmH;?ldeDaRw*8J(~hC!qOw?4H%Oa?Y1JnqbNZuG{_4-W8zh5g(k>k33gQDw%FD{ne3XB@ z!rC7_g|Gdhw<&R;HMK*r`+|J;KQGI_{V?zIn&?P3mLE&uo!9m>GUrS3pvy(U5A^kP z_$(c0u8#D!b_R{U=43cu$bYTlSjYsNjhYF)s`QQZ*3Ky}xtxmjy4jX?u^{kLVeo`r zO$S;h4E5!2dRRN72QywCwpkgq;m=hECwm&HvGsd>T}g=BENAdX&yl^G;15ZD@oDXe za5~)ny+KtH;%e1SDcr|-+q7@ZKZGT0tS19Bm$;2T93LRj8^{4y675bB zwk%H%+bJ)|KhfTK`uexou|aVjGo#E;Z%!+~BizWLXGzMgwI!$9Yp#x{^ivH+c7UV2 ztG$yM@p8QPk{Hi9qZjA|_iy0IrBz^V2FDGCt7!c=X2YVB&%j+s%GRZq6}$VIQ&2P#@0_gE zNAUFwKQH_3h_#F3ZUXmN_F>UpAnQ~Ky-mq~NZp*1ER$dEt(TrWr;qctLx_#Sm^+j7oj?A#I7DC$ zaD!T6s6Sj3{L6HyM1HcisHVO0oT2v1d(D5PMI|R99BoZLz$4vBrg+7t)3*@)h!oupL+wwg_YH%9vj*4aIjHXba4{8xkuc);A<= z{dZS2HK=KK!_1Gt{0T^;r%|h@D@A zwEWI*^|gxqvzS+eyR}HSKjd>V18&q9+tQP_E(>?D2|U7;$hbAy$_UJGbI$ekhw(yN zQ(t@t+Lp`(@GUljJClQ+q->vynK|C(jk-g{A&xDnJEp9_2N%N}naK~`m>>4s;pgp< z9QJ=jEdleAH`nptjkB2FdOtgL+Y^|;w&WZ>d7<84e)0JS>Jtat2~yqPk^=D3P?xq0 z@f7|6Jern%&D$w>p*GAGyl#LeY+CZk`Lq2)w{GZkg^@2rdyw`F-&0YZ?HMmk^)y+7 zCvI74%WRnjCpgYpE3*5H!##ZipIx~q^<9GpuZi7A2hXs1Zk~!pO}{2J>4l}(OBYOw zFj0B(Bt6hCeb>`pT-SE@^z{x5U2Ln3-?S|8w?F!!Jf|8`_0G@Mi{w$ z=X|SDy7MOoto~1%!)>|A@LPpZ)J;^~NDC9o;+|ify5q^Z+~}r~bWFtv8#b;5N6F%T zh9Q2R{a&r|U)2@;IgyF6UTmI3tzX1!nST@^QP$V_qZVtm#9wTzwZCbi{LlWU{0Anp BEK2|Y literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/misc/ljlogo/lj_logo.svg b/ljcom/htdocs/misc/ljlogo/lj_logo.svg new file mode 100644 index 0000000..3ed11ec --- /dev/null +++ b/ljcom/htdocs/misc/ljlogo/lj_logo.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ljcom/htdocs/misc/ljlogo/lj_logo_bw.svg b/ljcom/htdocs/misc/ljlogo/lj_logo_bw.svg new file mode 100644 index 0000000..f5626cd --- /dev/null +++ b/ljcom/htdocs/misc/ljlogo/lj_logo_bw.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ljcom/htdocs/misc/pkg-webslave.txt b/ljcom/htdocs/misc/pkg-webslave.txt new file mode 100644 index 0000000..f744762 --- /dev/null +++ b/ljcom/htdocs/misc/pkg-webslave.txt @@ -0,0 +1,25 @@ +apache-perl +aspell +aspell-en +less +libcompress-zlib-perl +libcrypt-ssleay-perl +libdbd-mysql-perl +libdbi-perl +libdigest-md5-perl +libgd-graph-perl +libgd-perl +libgd-text-perl +libimage-size-perl +libmime-lite-perl +libnet-perl +libproc-process-perl +libsoap-lite-perl +libssl09 +libunicode-maputf8-perl +liburi-perl +libwww-perl +ntpdate +postfix +rsync +snmpd diff --git a/ljcom/htdocs/misc/whereami.bml b/ljcom/htdocs/misc/whereami.bml new file mode 100644 index 0000000..de898fc --- /dev/null +++ b/ljcom/htdocs/misc/whereami.bml @@ -0,0 +1,79 @@ +Where are you? +body<= +{statusvis} ne 'L'; + + return $u; + }; + + my $remote = LJ::get_remote(); + my $remote_is_fake = 0; + unless ($remote) { + $remote_is_fake = 1; + $remote = $get_fake_remote->(); + } + return "Not logged in." unless $remote; + + my $ret = ""; + + my $authas = $remote->{user}; + my $u = $remote; + + # authas only works if $remote is not fake + unless ($remote_is_fake) { + + # logic to authenticate as alternate user + $authas = $GET{'authas'} || $remote->{'user'}; + $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + # authas switcher form + $ret .= "

    "; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= ""; + } + + # human-readable cluster name + my $name = LJ::get_cluster_description($u->{clusterid}, 1); + + if ($remote_is_fake) { + $ret .= "

    You appear to be logged in as " . LJ::ljuser($authas) . ", which is on " . + "$name, but your login session was unable to be retrieved, most likely " . + "because $name is currently down. If you own any communities, you won't be able to " . + "see where they are during this time. If they won't load, they're probably down for " . + "maintenance.

    "; + } else { + $ret .= "

    " . LJ::ljuser($authas) . " is on $name.

    "; + } + + # is their cluster down? + unless (LJ::get_cluster_master($u)) { + $ret .= ""; + $ret .= " 'C' }) . " journal for " . + "further status updates. p?>"; + + $ret .= "status.livejournal.org. p?>"; + } + + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/news.bml b/ljcom/htdocs/news.bml new file mode 100644 index 0000000..e687f53 --- /dev/null +++ b/ljcom/htdocs/news.bml @@ -0,0 +1,50 @@ + + + +%%data2%% + +RSS Feed + +<=feed +<=localblocks +_info?>News +body<= + +Welcome to LiveJournal news. If you crave more frequent and detailed news, check out the following journals: + +

    + + + + _c?> + + + + + + + +
    +
    + +


    + + 'customview', + 'styleid' => 5624, + }); +} +_code?> + +<=body +page?> +link: htdocs/customview.cgi + _c?> diff --git a/ljcom/htdocs/news/2000-11-23/index.bml b/ljcom/htdocs/news/2000-11-23/index.bml new file mode 100644 index 0000000..d906f44 --- /dev/null +++ b/ljcom/htdocs/news/2000-11-23/index.bml @@ -0,0 +1,91 @@ +LiveJournal News +body<= + + + + + + + + + + + + + +The two most organized areas are the support area run by dakus and the topic directory run by patrick. Those guys are doing a wonderful job. User pdxseraph is also helping a lot in the support area, keeping the FAQ up-to-date when I change things around. +p?> +revjim helping me with system maintenance things from time to time, I deal with everything. That really sucks, for two reasons: +

      +
    1. No time. See all the arrows coming in to me but not going back? Those represent the hundreds of emails I get from people asking for help that I end up just deleting because I don't have time to get back to them. +
    2. I suck. I'm not that good at dealing with people. Worse, I don't like to. I'd prefer to sit in my little dark room and just program all day and all night. I can't help but fear that I'm risking LiveJournal's future success by trying to handle it all myself. +
    +As much as I don't like business and marketing, I realize its importance. Just look at Microsoft ... they don't always have wonderful products but they market them all very well. Does this mean I want LiveJournal to becoming a business and marketing machine? No. However, we have to do more than we're doing right now, which is essentially zero. +p?> + + + + + +Many things are the same, but here are the biggest changes: +
      +
    • Mark Kraft, user insomnia. and lj_biz (user lj_biz)
      +Mark is going to be the new all-things-business manager, essentially. Basically, I'm handing over all the stuff I hate to him, because he can do it a lot better than I can. Whatever he doesn't want to do I'll either still do, or he'll find somebody else to do it. Mark's a damn cool guy ... whenever I ask a question on one of the mailing lists he always replies with a several page reply, filled with nothing but good ideas. +

      Mark's now in charge of the lj_biz discussion area, where users can go and discuss the business aspects of the site. + +

    • Evan Martin, user evan
      +Evan's a friend of mine at school, and a wonderful programmer. He currently develops the Linux LiveJournal client, but we've been meeting up every so often to work on LiveJournal server stuff... he's a fun guy to work with. + +

    • More development
      Now that Mark will be dealing with more stuff, I'll have more free time to work on the code, along with Evan. This is what I'm good at (when I have enough time) and is what I like to do. Unstressed Brad --> Happy Brad --> Better LiveJournal. :-) Another good thing -- I'm only taking 12 credits next quarter at school, the minimum. Only 5 of those are even "real" classes, too, as opposed to my 17 real credits this quarter. In other words, I'll have a ton of free time. +
    +p?> + + + + + + + +ekashp has offered to let me use some hardware of his so we can have servers all over the country, and you'll automatically use the one that's closest to you. Best, if one goes down, you'll automatically use the next closest one in under a minute. More on that later, though. +p?> + + +colin is redesigning the entire site... check out his design survey. I can't wait! +p?> + + + + + + + + + + + +<=body +page?> diff --git a/ljcom/htdocs/news/2000-11-23/now.gif b/ljcom/htdocs/news/2000-11-23/now.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b3bbaaaed6821cc12d7b274c278465b6da4b2b4 GIT binary patch literal 7108 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 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/news/2000-11-23/proposed.gif b/ljcom/htdocs/news/2000-11-23/proposed.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad0158ecd06578a87ed400ecd9a1b5ee12f30768 GIT binary patch literal 7271 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 + my $count = ++$scratch->{"count"}; + my $lastnum = $scratch->{"perma_$ljuser"}; + $scratch->{"perma_$ljuser"} ||= 1; + $scratch->{"perma_$ljuser"}++; + $ljuser .= ".$lastnum" if $lastnum; + return "" . + "
    \n" . + "\#$count, " . + LJ::ljuser($args->{LJUSER}) . ": “$args->{QUESTION}”" . + "
    "; + +} +_code?> + +<=reply +<=localblocks +_info?>State of the Goat 2004 Questions and Concerns +body<= + +darksoul +question=>What is the status on some of the much talked about projects like journal statistics, photo-hosting, etc? +answer=>Photo hosting: We have disk space and bandwidth handled now, so we just need to do quota integration since both fotobilder/picpix and LJ have their own system. We've already integrated the different systems' authentication methods via modules for the two services, so it should be a fairly easy task.
    Statistics: Nobody's working on it, but it'd be nice. we really need more manpower or hours in the day. +reply?> + +quasidan +question=>I'd like a WYSIWYG layout helper for S1/S2 styles. +answer=>We don't really see that happening, at least not in the web interface. There's nothing that would stop someone from writing an offline editor though. What we'd really like to see is an S1 type editor for S2, building a complete layout layer from static HTML. However, that's not a top priority for us right now. +reply?> + +axiem +question=>I'd like some more information on the state of S2. How much is completed, how far along are the docs, when is it expected to be everything? If I'm behind the times, some sort of formal announcement would be useful, I think. +answer=>S2 is pretty much done. We're happy with what we've done so far, but we can see what is left to finished. We need a lot more decent styles, and we need to start helping translators translate the styles, since that's one major thing that S2 supports that S1 doesn't. We'd also like to hold a style contest some time soon, like the one we had for S1 (which gave us the Punquin Elegant style). +reply?> + +axiem +question=>I would also like to know of other plans for paid users, and other things that increments of cash can be used for (such as userpics right now). +answer=>We'll be offering photo hosting as a paid service in the near future, and we'll also have an option to increase your disk space quota for a fee. When we finish support for journal statistics and logging, we plan to offer basic stats for current paid users, and comprehensive stats for an additional fee. +reply?> + +jadedunoir +question=>I would like to know if there is any plan to add more permenant accounts. +answer=>There are no current plans to sell more. It's a delicate issue: we don't want to sell them too cheap, or too expensive, and finding the right number to sell isn't easy. Although selling more permanent accounts isn't entirely out of the question, we don't have any plans for another sale. +reply?> + +prom +question=>Personally, i was concerned that frank the goat wasn't decorated for the holidays this year. +answer=>We were fairly busy last holiday season, and the undecorated Frank was an oversight. We've been discussing having more Franks for different holidays and occassions, much like Google's Holiday Logos. +reply?> + +legolas +question=>Doing something with (or about) the suggestions perhaps? I always get the feeling they disappear into /dev/null … +answer=>Not all developers read suggestions, but there are staff members and volunteers who compile suggestions into zilla or email. The Life of a Suggestion explains more about the approval/filing process. +reply?> + +tulipswallow +question=>Things I'd like to see in the future are all along those lines. New layouts, site tracking, options, options, options. +answer=>Yes. :-) +reply?> + +sherm +question=>What's the current climate around encouraging people to buy paid accounts? Are we going to see really compelling new features, or free-user limits in the next year? Or is 5% paid accounts an acceptable rate? +answer=>We don't want to limit or bug free users, coercing them to upgrade. Our plan is to offer enough fun stuff to paid users to make people want to pay. 5% paid accounts includes the inactive accounts. If you look at active accounts, about 10-12% of users are paying, and that's perfectly acceptable. Those 10-12% pay for everybody else just fine, and the site doesn't have any financial problems. We spend money very conservatively and make sure we keep spare money around "just in case". +reply?> + +rho +question=>I'm concerned about the community/volunteer aspect of things, which seems to be in something of a shambles, with a lot of unnecessary conflict between staff and volunteers. Are there any plans to try to resolve this and improve communication, or is the volunteer aspect of LJ being considered less important these days, with the ever-increasing number of paid employees? +answer<= +While we are making an effort to hire more employees to help with the workload, we're not trying to ignore volunteers. We want to start having weekly meetings on IRC so that volunteers can catch up with all of the employees and developers, so hopefully that'll solve most communication issues. We'll post more details in as we set this up. +<=answer +reply?> + +beginning +question=>My one big concern is that, all too often, something is announced in News, then Drama Ensues, then whatever poorly thought-out idea was first proposed has to be retracted, then something only marginally better is proposed, then people are still upset with staff because of the fact that drama ensued in the first place.

    So, to fix this, how about having much more discussion before things are announced/finalized? I know that there's probably a lot of discussion now as it is, but to many of us, things just look horribly disorganized where management is concerned. Perhaps, before posting anything to News, it should be posted to lj_core to have everyone look over it first to make sure you're all certain that's what you want to go ahead with, and that your plan doesn't have huge flaws in it? +answer=>We discuss issues in lj_core constantly, and we often draft our news posts there so that all of the employees can review them. Sometimes it just takes the whole community to chime in with their opinions for us to change our minds - we like being flexible and adaptive in that respect. +reply?> + +technodummy +question=>Why on earth can I *still* not purchase extra syndication points? +answer=>While we could offer to buy more points, we'd rather find a good upper limit so that users don't feel hampered by it. Our opinion is that syndication points are not interesting enough to make someone pay for. If you have a suggestion for a better limit, bring it up in and we can discuss it. +reply?> + +technodummy +question=>I'd really like to see LJ catch up to the other blog tools in terms of categories. We already have memories, but they're not flexible, never automatic, and have a lot of limits. I would pay extra for categories. +answer=>Categories are a feature we plan to have support for sometime in the next few months. Right now it's a matter of deciding how we will handle them internally. There have been a few recent discussions in that you might be interested in. +reply?> + +jiggery_pokery +question=>Are the main LJ staff happy to continue to work on LJ? +answer=>Most of the time. There are periods of time when it's hard to find motivation (especially during loud periods of community bickering and server problem stress), but generally we're a happy lot. +reply?> + +jiggery_pokery +question=>What if Brad, or you, or anyone else on the LJ team, got bored and decided she/he didn't want to work on the site any more? I'm sure you all have minor niggles and annoyances about the site and about working with people; is there a danger that any of you will say "right, that's it, I've had enough" and quit? What if - heaven forbid - there was a freak traffic accident and a senior developer or two was lost? What if Google headhunted senior staff members $10^5-$10^6 p.a. to go and work on Blogger instead? +answer=>If Brad ever got absolutely bored with the site, he'd try to find someone trustworthy and knowledgable enough to take it over. Another possibility would be to sell the project to the general LiveJournal community, offer to setup a board of trustees (or something similar) and let the service exist as run by its community. That's not something we're concerned about however, because we're still very eager to work on LiveJournal.

    If we lost a few employees at a time, for whatever reason, we'd hopefully have enough left over to cover the workload until we hired more. +reply?> + +jiggery_pokery +question=>What if the US government cracks down on the content that is being stored on LJ's servers? (Probably not a big problem now, but if you start doing picture hosting and the like, potentially a big problem.) +answer=>We do try to comply with the law, but we never volunteer any information without a proper subpoena, court order, or search warrant. We purge our web traffic and statistics often, only keeping an anonymous digest for research purposes. If the government ever cracks down on the website, we'd work through it as best as we can, while keeping the interests of the community in mind. +reply?> + +jiggery_pokery +question=>Do you intend to let expansion continue at its current rate, especially with the removal of invite codes? Would you like to expand faster? If so, what do you intend to do about it? What can we do to help? (I can guess what the answer is to that question.) +answer=>At this point, we're not trying to speed up or slow down expansion, but let it evolve naturally. Our main concern is just to keep the site reliable for all users. As such, we've been spending tons of money on servers lately and will continue to do so. We won't be happy until the site's totally fast and reliable, and we know you won't either. +reply?> + +jiggery_pokery +question=>Do you see yourself in competition with other sites that use the LJ codebase, or with other online journaling sites that use other codebases? +answer=>The other LiveJournal based sites mostly carve niche markets for themselves, offering only a few variations of our service, as well as fewer users. We understand our code best, so we don't feel that we're in much competition with them. As for other social networking and journaling services there's plenty of competition, but we're trying to find a good balance between the two types of services so that we remain unique. +reply?> + +jiggery_pokery +question=>Do you have any plans to try to expand your share of the online journal market at the expense of other online journal systems? +answer=>On the contrary, we're constantly trying to find ways to make them work together. +reply?> + +jiggery_pokery +question=>How will the possible adoption of Atom affect matters; is there any chance that we will be able to use the same rich possibilities of Friends-list-based interaction with people who currently use other online journalling systems? +answer=>Yes, that's exactly the goal. +reply?> + +virga +question=>One thing to be noticing is the namespace. Keep it up-to-date and clean. Wipe out inactive users after a while to keep everything fresh. That was the largest concern I had..people making up tons and tons of livejournals just because they could. Poluting the namespace and diluting the community. +answer=>We've never really had a policy for deleting inactive accounts, but recently drafted one in . It's still being reviewed, and is subject to change at any time. +reply?> + +maelkann +question=>Phone posts: Will they be expanded to other countries, and if so how can we help? +answer=>Right now we're at the mercy of phone companies offering specific services in different locations. Expanding phone post access numbers depends on if we can get cheap IAX2 access in that country. You can read more about how the phone post feature works and how you can help in . +reply?> + +rho +question=>In terms of direction, I'd like to see more minor bugs getting fixed in a timely manner. New features are great, and increased backend stability is also great, but I'd like to see the little things fixed. A lot of the time it seems as if LJ works "well enough" rather than it being sparkly and shiny and just working. Especially with more employees to get things done, I think that some polishing could be very beneficial. +answer=>We agree, but stability is always our main concern. You're right though, we have more in-house developers on hand, so having time to polish features is becoming more of a possibility. +reply?> + +rho +question=>I'm also very interested to know when the splitting up of the friends list into trusted and watched journals is going to happen, as that's a feature I've been wanting for a long time. +answer=>This is one of our major priorities, since in the process we'll be refining slow queries, and taking the friend information off of the global databases and memcaching it. Solving this fixes many minor issues along the way. +reply?> + +flashfire +question=>What steps can LJ take (or what steps is LJ already taking) to improve lines of communication with users in general? How much emphasis is put on to-do lists and timeframes? Without timeframes and reminders that a set date goal for a certain project is approaching, it's probably easy for things to slip to the background when other more immediate issues pop up.

    What are your (LJ as a whole) thoughts on something like a monthly status report that could be posted, something that would list the main projects being worked on with their current levels of progress and expected completion times? I'm sure something like that would go a long ways towards soothing the concerns/complaints of some. +answer=>We've been working hard to improve our internal communication, and to move most of our employees to the office in Portland so that we're always in contact with each other. We put a lot of emphasis on to-do lists, but most projects are dependant on others which constantly push back projected timeframes. The idea of a monthly status sounds good, so we'll try that for a while and see how it goes. +reply?> + +rho +question=>I would really really like to see the FAQ engine updated. It works at the moment, but it doesn't work nicely. It's a byzantine monstrosity, where it can be a pain to find a certain bit of information, even if you know the FAQ inside out. +answer=>We've talked about developing a search engine for the FAQs, now that MySQL supports full text searching with Unicode character sets. Although it's not top priority, it's something that we feel will cut out a lot of complaints regarding our documentation. +reply?> + +lovewithnoface +question=>My biggest issue with LiveJournal is the large amount of non-LJ specific code. It is very easy for users to go from action to action without anything being explained and without them being pointed towards the FAQ. +answer=>We're working on navigation issues in the current site schemes, and we'll be adding a bread crumb line of links for most pages. +reply?> + +icon_goddess +question=>It would be great if the limit on our friends could be lifted...it is hard having to either create a separate account to accomidate the overflow or having to pick and choose who gets to stay. Does the limit apply for communities as well? +answer=>The limit on friends can probably be lifted after the friends watching/split concept, as most of that information will be stored in memcache objects and not on the global databases. +reply?> + +twistedchick +question=>I'd like to have a way to go back to a specific date and read forward in my friends page. For instance, if I'm away on vacation, I'd like to be able to go back to the day I left and read forward, however many posts that is, rather than having to read *backward* from the present. +answer=>That would take up a lot of space just for that specific task. That's really something that'd better be handled in an offline client. +reply?> + +harry711 +question=>Search. I know I can do some things with google or other 3rd parties, but I want something built in. It would be nice (for example) to get a list of all my posts that are friends only, or available to a certain filter. +answer=>We had been waiting for MySQL to catch up with full text search features, and now that they support full text searching with Unicode character sets, it's certainly a possibility. However, it's not on anyone's to-do list at the moment. +reply?> + +fool_in_spirit +question=>S2 power over memories. Possibility to edit memories page, possibility to show a page with the body of all memories. +answer=>That's a good idea, but it's not a priority for lead developers right now. +reply?> + +mystery544 +question=>Why not make entries easier to move (Friends,Private,etc)/delete/etc?

    I'd like to move a lot of my entries to Private or Friends, but it would mean going through every entry and seeing which group it's defined under. +answer=>Yeah we should, but more people want journal-wide security, which is easier to code. Also, we don't really want to offer mass deletion capabilities, in case an account is hijacked. However, that becomes less of an issue after we start offering user-level backups for accounts. +reply?> + +digitalised +question=>Make the renaming system a bit more lenient. I'd really like to see an option to switch two journal names without having to purchase 3 rename tokens. Perhaps this could be an option for paid accounts or something of the sort. Right now, it's absurd to try and swap journal names. +answer=>We don't really want to make the rename process any easier, because we frown on account renaming in general. Right now we have no interest in offering easy username swaps, but if someone wanted to write support for it we'd accept a patch. +reply?> + +digitalized +question=>I've always thought that blogging sites that allowed you to download your journal onto your homepage without having to go through embedding problems and such were a good idea. It would be nice to see LiveJournal become a service somewhat like Movable Type in addition to what you guys provide on your own servers. +answer=>We'd eventually like to provide a backup program with an upload feature. We don't want to keep your website's passwords, and CGI wouldn't be required on your server in order for it to work. That's a far off plan though, because it's not an oft-requested feature. +reply?> + +madshrubbery +question=>I love the LJ store, but are there any plans on expanding the available products? I can't wear any of the shirts, but I'd love to have some other kinds of products with LJ logos/slogans. +answer=>We're soon going to offer a limited run of sweatshirts and baseball hats in the store, to see how well they sell. Our expansion into other products really depends on how well our current stock appeals to the users. We are still working on researching some new items, but getting styles, and good prices, can be a challenge. Our logo has a 7 color screen print process, and does not work on all items. We will continue to look into new options. +reply?> + +<=body +page?> diff --git a/ljcom/htdocs/news/index.bml b/ljcom/htdocs/news/index.bml new file mode 100644 index 0000000..0e4c2b8 --- /dev/null +++ b/ljcom/htdocs/news/index.bml @@ -0,0 +1,5 @@ + diff --git a/ljcom/htdocs/news/tshirt-poll.bml b/ljcom/htdocs/news/tshirt-poll.bml new file mode 100644 index 0000000..ebce4ad --- /dev/null +++ b/ljcom/htdocs/news/tshirt-poll.bml @@ -0,0 +1,82 @@ +T-shirt poll +body<= +login."; + } + + my %pro = ('short' => 'Short-sleeved', + 'long' => 'Long-sleeved', + 'baby' => 'Baby Doll', + 'polo' => 'Embroidered Polo'); + my %col = ('black' => "Black", + 'gray' => "Gray", + 'blue' => "Royal Blue"); + my @sizes = qw(S M L XL XXL XXXL); # no /XX+/ for baby doll + + if (LJ::did_post()) { + $dbh->do("DELETE FROM tshirtpoll WHERE userid=?", undef, $remote->{'userid'}); + my @values; + foreach my $style (keys %pro) { + foreach my $col (keys %col) { + foreach my $size (@sizes) { + my $k = "${style}_${col}_${size}"; + if ($POST{$k} =~ /^\d+$/) { + push @values, "($remote->{'userid'}, '$style', '$col', '$size', $POST{$k})"; + } + } + } + } + if (@values) { + $dbh->do("REPLACE INTO tshirtpoll (userid,style,color,size,qty) ". + "VALUES " . join(',', @values)); + return $dbh->errstr if $dbh->err; + } + return ""; + } + + my %prefill; + my $sth = $dbh->prepare("SELECT style, color, size, qty FROM tshirtpoll WHERE userid=?"); + $sth->execute($remote->{'userid'}); + while (my ($st, $c, $si, $qt) = $sth->fetchrow_array) { + $prefill{"${st}_${c}_${si}"} = $qt; + } + + my $ret; + $ret .= ""; + + + $ret .= "

    "; + $ret .= ""; + foreach (@sizes) { + $ret .= ""; + } + $ret .= "\n"; + + foreach my $style (qw(short long baby polo)) { + foreach my $color (qw(black gray blue)) { + $ret .= ""; + foreach my $size (@sizes) { + $ret .= ""; + } + $ret .= "\n"; + } + } + $ret .= "
    Type / Color$_
    $pro{$style} ($col{$color})"; + unless ($style eq "baby" && $size =~ /XX+/) { + my $k = "${style}_${color}_${size}"; + $ret .= ""; + } else { + $ret .= "--"; + } + $ret .= "
    "; + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/paidaccounts/2004_december_promo.bml b/ljcom/htdocs/paidaccounts/2004_december_promo.bml new file mode 100644 index 0000000..81c61e7 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/2004_december_promo.bml @@ -0,0 +1,180 @@ + $time_end) { + $title = "Offer Expired"; + $body = "Sorry, the 2004 Holidays Promotion offer expired at the end of December, GMT."; + return; + } + + my $err = sub { + $title = "Error"; + $body = LJ::bad_input(@_); + return; + }; + + # no authas for this page + my $u = LJ::get_remote(); + return $err->($ML{'error.noremote'}) + unless $u; + + my $dbh = LJ::get_db_writer(); + my $sys_id = LJ::get_userid("system") or die "No system id"; + + # form output + $body = ""; + + # no suspended accounts + if ($u->{statusvis} eq "S") { + $body .= ""; + $body .= ""; + return; + } + + # statusvis must be v, and journaltype C || P + unless ($u->{statusvis} eq 'V' && $u->{journaltype} eq 'P') { + $body .= ""; + $body .= ""; + return; + } + + # Find the following payitems: + # -- belong to this user + # -- between $time_start and $time_end + # -- checked out (used='Y') + # -- not clothes (intangible ... coupons are allowed) + # -- positive amount + + my $has_already = sub { + return $dbh->selectrow_array + ("SELECT COUNT(*) FROM statushistory WHERE userid=? AND adminid=? AND shtype=?", + undef, $u->{userid}, $sys_id, $shtype)+0; + }; + + my $amt = $dbh->selectrow_array + ("SELECT SUM(pi.amt) FROM payments p, payitems pi WHERE p.userid=? AND pi.payid=p.payid " . + "AND p.daterecv>=FROM_UNIXTIME(?) AND p.daterecv<=FROM_UNIXTIME(?) " . + "AND p.used='Y' AND pi.amt>0 AND pi.item IN ('rename','paidacct','perm','userpic')", + undef, $u->{userid}, $time_start, $time_end); + + my $total = POSIX::floor($amt/$dollar_req); + my $have = $has_already->() + 0; + my $need = $total - $have; + + # posting a form submission + if (LJ::did_post() && $POST{submit} && $need > 0) { + + # get a lock on this userid + my $lockkey = "$shtype:$u->{userid}"; + LJ::get_lock($dbh, "global", $lockkey) + or return $err->("Couldn't get lock: $lockkey"); + + # revalidate count inside of lock + $have = $has_already->(); + $need = $total - $have; + + my @tokens = (); + foreach my $ct ($have+1..$total) { + + my ($tokenid, $token) = LJ::Pay::new_coupon('dollarofftan', $dollar_value, $u->{userid}, 0); + unless ($tokenid && $token) { + return $err->("There has been an error generating your coupon. Please try again later."); + } + push @tokens, $token; + + # log this action in statushistory. note that this is also what signifies the action + # has already been performed + LJ::statushistory_add + ($u->{userid}, $sys_id, $shtype, "($ct) generated coupon: $token"); + + } + + # we're done working, release lock + LJ::release_lock($dbh, "global", $lockkey); + + $body = ""; + $body .= "
      "; + foreach ( @tokens ) { + $body .= "
    • $_
    • "; + } + $body .= "
    "; + + my $coup_amt = $dollar_value * $need; + $body .= "$LJ::SITENAMESHORT merchandise. p?>"; + $body .= "Note: A coupon is only valid for one use, so be sure that your order's "; + $body .= " value is greater than or equal to \$$coup_amt USD. p?>"; + + return; + } + + # claim form + $body .= "
    "; + + $body .= ""; + $body .= "clothing coupons "; + $body .= "for every \$$dollar_req USD spent on service items in our store. "; + $body .= "Store purchases are cumulative, so you don't have to spend \$$dollar_req at once -- separate "; + $body .= "purchases can be saved up until there's enough to generate a coupon. p?>"; + $body .= ""; + + $body .= ""; + if ($need > 0) { + my $s = $total == 1 ? "" : "s"; + $body .= ""; + + my $s = $need == 1 ? "" : "s"; + $body .= "
    "; + $body .= LJ::html_submit('submit' => "Claim $need Coupon$s"); + $body .= "
    "; + + } else { + my $goal = sprintf("%0.02f", $dollar_req - ($amt % $dollar_req)); + if ($have == 0) { + $body .= "services from our store. p?>"; + } else { + my $s = $have == 1 ? "" : "s"; + $body .= ""; + } + } + + if ($have > 0) { + $body .= ""; + $body .= "coupon retrieval page. p?>"; + } + + $body .= "
    "; + + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/paidaccounts/apply.bml b/ljcom/htdocs/paidaccounts/apply.bml new file mode 100644 index 0000000..a0ecf17 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/apply.bml @@ -0,0 +1,97 @@ +Apply Payment +body<= +login " . + "first. Otherwise, go create an account using your payment code, and the payment will be " . + "automatically applied to the newly created account. p?>" + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my $ret = ''; + + # authas switcher form + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "
    \n\n"; + + $ret .= ""; + + # handle form submission + if ($POST{'code'}) { + my $dbh = LJ::get_db_writer(); + + my $code = $POST{'code'}; + return LJ::bad_input("Invalid code") unless length($code) == 12; + my ($acid, $auth) = LJ::acct_code_decode($code); + my ($usedby, $realauth) = + $dbh->selectrow_array("SELECT rcptid, auth FROM acctcode ". + "WHERE acid=?", undef, $acid); + return LJ::bad_input("Invalid code") unless $realauth && $auth eq $realauth; + return LJ::bad_input("You've already applied this payment") if $usedby == $u->{'userid'}; + return LJ::bad_input("Somebody else has already applied this payment") if $usedby; + + my $months; + + if (my $pi = $dbh->selectrow_hashref("SELECT pi.item, pi.qty ". + "FROM payitems pi, acctpayitem api ". + "WHERE pi.piid=api.piid AND api.acid=?", + undef, $acid)) { + $months = 99 if $pi->{'item'} eq "perm"; + $months = $pi->{'qty'} if $pi->{'item'} eq "paidacct"; + } else { + $months = $dbh->selectrow_array("SELECT p.months ". + "FROM payments p, acctpay ap ". + "WHERE p.payid=ap.payid ". + "AND ap.acid=?", undef, $acid); + } + + return "The code provided has no paid time associated with it." unless $months > 0; + + if ($u->{'caps'} & 16) { + return "You already have a permanent account, so applying this ". + "second permanent account code would do nothing." if $months == 99; + return "You already have a permament account, so applying $months ". + "extra paid account months would do nothing."; + } + + # double click protection + my $rows = $dbh->do("UPDATE acctcode SET rcptid=? WHERE acid=?", undef, + $u->{'userid'}, $acid); + if ($rows) { + LJ::Pay::add_paid_months($dbh, $u->{'userid'}, $months); + } + + return "" if $months == 99; + return ""; + } + + # show form before post + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + $ret .= "
    "; + $ret .= "{'user'} ljuser?> account. p?>"; + + $ret .= " 'code', 'size' => 13, 'maxlength' => 12, 'value' => $GET{'code'} }) . " "; + $ret .= LJ::html_submit("Apply") . " standout?>"; + + $ret .= "
    "; + + return $ret; + + +} +_code?> +<=body +page?> + + diff --git a/ljcom/htdocs/paidaccounts/buy.bml b/ljcom/htdocs/paidaccounts/buy.bml new file mode 100644 index 0000000..73f9ecf --- /dev/null +++ b/ljcom/htdocs/paidaccounts/buy.bml @@ -0,0 +1 @@ + diff --git a/ljcom/htdocs/paidaccounts/friends.bml b/ljcom/htdocs/paidaccounts/friends.bml new file mode 100644 index 0000000..8136b1c --- /dev/null +++ b/ljcom/htdocs/paidaccounts/friends.bml @@ -0,0 +1,125 @@ +Buy for friends! +body<= + +login."; + } + my $ret; + $ret .= ""; + $ret .= "paid account for one of the people on your friends list! p?>"; + + # get status of all friends + # TAG:FR:bml_paidaccts_friends:get_friend_statuses + my $sth = $dbr->prepare("SELECT u.userid, u.user, u.name, u.caps, u.journaltype ". + "FROM friends f, user u, userusage uu ". + "WHERE f.userid=? AND u.userid=f.friendid AND uu.userid=f.friendid ". + "AND u.statusvis='V' LIMIT 500"); + $sth->execute($remote->{'userid'}); + + my %f; + while (my $f = $sth->fetchrow_hashref) { + next unless $f->{'journaltype'} eq "P" || $f->{'journaltype'} eq "C"; + $f{$f->{'userid'}} = $f; + } + + # when are people's paid accounts expiring? + # TAG:FR:bml_paidaccts_friends:get_friend_expiring + $sth = $dbr->prepare("SELECT p.userid, UNIX_TIMESTAMP(p.paiduntil) AS 'paiduntil' ". + "FROM friends f, paiduser p ". + "WHERE f.userid=? AND f.friendid=p.userid"); + $sth->execute($remote->{'userid'}); + while (my $f = $sth->fetchrow_hashref) { + next unless $f{$f->{'userid'}}; + $f{$f->{'userid'}}->{'paiduntil'} = $f->{'paiduntil'}; + } + + # who has pending gifts? + # TAG:FR:bml_paidaccts_friends:get_pending_gifts + $sth = $dbr->prepare("SELECT p.userid, p.months ". + "FROM friends f, payments p ". + "WHERE f.userid=? AND f.friendid=p.userid AND ". + " p.used='N' AND p.giveafter > 0"); + $sth->execute($remote->{'userid'}); + while (my $f = $sth->fetchrow_hashref) { + next unless $f{$f->{'userid'}}; + $f{$f->{'userid'}}->{'pending'} += $f->{'months'}; + } + + unless (%f) { + $ret .= ""; + return $ret; + } + + my $now = time; + my $one_month = 60*60*24*30; + + # separate users into two groups: those needy and those who aren't + my (@needy_paid, @needy_free, @not); + foreach my $f (sort { $a->{'user'} cmp $b->{'user'} } values %f) + { + my $paid_months; + if ($f->{'caps'} & 8) { + $paid_months += ($f->{'paiduntil'} - $now) / $one_month; + $paid_months = 0 if $paid_months < 0; + } + + $paid_months += $f->{'pending'}; + + # permanent account holders or those with 6 months of real or pending gift payments + # aren't needy + if ($f->{'caps'} & 16 || $paid_months > 6) { + push @not, $f; + next; + } + + # now, they're needy, but do they already have a paid account? + if ($f->{'caps'} & 8) { + push @needy_paid, $f; + } else { + push @needy_free, $f; + } + } + + my $dump_table = sub { + my $list = shift; + $ret .= "
      \n"; + foreach my $f (@$list) { + $ret .= "\n"; + } + $ret .= "
      "; + $ret .= LJ::ljuser($f->{'user'}, { 'type' => $f->{'journaltype'} }); + $ret .= " - " . LJ::ehtml($f->{'name'}); + unless ($f->{'caps'} & 16) { # unless a permanent account + $ret .= " [buy gift]"; + } + $ret .= "
    "; + }; + + if (@needy_free) { + $ret .= ""; + $dump_table->(\@needy_free); + } + + if (@needy_paid) { + $ret .= ""; + $dump_table->(\@needy_paid); + } + + if (@not) { + $ret .= ""; + $dump_table->(\@not); + } + + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/paidaccounts/index.bml b/ljcom/htdocs/paidaccounts/index.bml new file mode 100644 index 0000000..1717508 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/index.bml @@ -0,0 +1,50 @@ + +head<= + +<=head +body<= + h1?>"; + $ret .= " p?>"; + $ret .= " p?>"; + + $ret .= " h1?> "; + $ret .= " p?>"; + $ret .= ""; + $ret .= ""; + + foreach my $prid (sort { $b <=> $a } keys %LJ::Pay::account) { + $ret .= ""; + } + $ret .= "
     
    $LJ::Pay::account{$prid}->{'name'}\$$LJ::Pay::account{$prid}->{'amount'}.00 US
    "; + $ret .= " p?>"; + + $ret .= ""; + $ret .= "Paid Account Status page. p?>"; + + my $remote = LJ::get_remote(); my $ru; + if ($remote) { + $ru = $remote->{'user'} + } else { + $ru = ""; + } + $ret .= "$ML{'.features.header'} h1?>"; + $ret .= "Features by Account Type comparison chart. p?>"; + $ret .= "
    "; + $ret .= BML::ml('.features', { 'username' => $ru, }); + $ret .= "
    "; + + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/paidaccounts/joincommunity.bml b/ljcom/htdocs/paidaccounts/joincommunity.bml new file mode 100644 index 0000000..2647d77 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/joincommunity.bml @@ -0,0 +1,55 @@ +log in. p?>"; + return; + } + + my $u = LJ::load_userid($remote->{'userid'}); + unless (LJ::get_cap($u, "paid")) { + $title = "Join Paidmembers"; + $body = "paid account to join the community. p?>"; + return; + } + + if ($FORM{'mode'} eq "join") { + unless (LJ::did_post()) { + $title = "Error"; + $body = ""; + return; + } + my $puserid = LJ::get_userid("paidmembers"); + if (LJ::is_friend($puserid, $remote->{'userid'}) || + LJ::add_friend($puserid, $remote->{'userid'})) { + $title = "Joined"; + $body = " community p?>"; + } else { + $title = "Error"; + $body = "paidmembers community doesn't exist?"; + } + return; + } + + $title .= "Join Paidmembers?"; + $body .= " community, click the button below. p?>"; + $body .= "
    "; + $body .= ""; + $body .= "
    "; + $body .= "
    "; + + return; + +_code?> + +body<= + +<=body +page?> diff --git a/ljcom/htdocs/paidaccounts/newacct.bml b/ljcom/htdocs/paidaccounts/newacct.bml new file mode 100644 index 0000000..f39ae46 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/newacct.bml @@ -0,0 +1,49 @@ +Purchase new account +body<= +Error: Invalid months value." unless $LJ::Pay::account{$months}; + my $amount = $LJ::Pay::account{$months}->{'amount'}; + my $name = "New account, with paid benefits for $months months"; + + if (LJ::did_post()) { + if ($FORM{'email'}) { + my @errors; + if ($FORM{'email'} =~ /\s/) { push @errors, "Email address shouldn't contain spaces."; } + LJ::check_email($FORM{'email'}, \@errors); + return LJ::bad_input(@errors) if @errors; + } + + my $url = "https://www.paypal.com/cgi-bin/webscr?amount=$amount&return=http%3A//www.livejournal.com/paidaccounts/thankyou.bml&item_name=" . LJ::eurl($name) . "&custom=months%3D$months%26newacct%3D1%26email%3D" . LJ::eurl($FORM{'email'}) . "&business=paypal%40livejournal.com&cmd=_xclick&cmd=_xclick&no_shipping=1&no_note=1¬ify_url=http%3A//www.livejournal.com/paidaccounts/pp_notify.bml"; + return BML::redirect($url); + } + + return <<"FORM"; +
    + + + +
    +Example: bob3984\@yourisp.com + +If you leave the box blank, the code will be mailed to your PayPal email address (if you have an existing PayPal account), or the email address PayPal will ask you for if you don't have an account. +p?> + +
    + + + +FORM + +} +_code?> +<=body +page?> + + diff --git a/ljcom/htdocs/paidaccounts/pp_notify.bml b/ljcom/htdocs/paidaccounts/pp_notify.bml new file mode 100644 index 0000000..2e25a30 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/pp_notify.bml @@ -0,0 +1,111 @@ +Payment Processing Error
  • " . $error; + }; + + my $dbh = LJ::get_db_writer(); + + return $err500->("Couldn't connect to database.") unless $dbh; + + my $body = "REMOTE_ADDR = " . BML::get_remote_ip() . "\n\n"; + $body .= join("\n", map { "$_ = $FORM{$_}" } sort keys %FORM); + + my $error; + my $ok = 0; + + # FIXME: automatically call LJ::revoke_payitems on these in LJ::Pay::verify_paypal_transaction + if ($FORM{payment_status} eq 'Reversed') { + $body = "Paypal has reversed the following transaction, please revoke the items manually\n\n$body"; + LJ::send_mail({ to => $LJ::PAYPAL_ERROR_EMAIL || $LJ::ACCOUNTS_EMAIL, + from => $LJ::BOGUS_EMAIL, + fromname => 'Paypal Reversal', + subject => "Paypal Reversal: $FORM{custom}", + body => $body, + }); + return "notified"; + } + + if ($FORM{payment_status} eq 'Canceled_Reversal') { + $body = "Paypal has canceled reversal of the following transaction, please take appropriate action\n\n$body"; + LJ::send_mail({ to => $LJ::PAYPAL_ERROR_EMAIL || $LJ::ACCOUNTS_EMAIL, + from => $LJ::BOGUS_EMAIL, + fromname => 'Paypal Canceled Reversal', + subject => "Paypal Canceled Reversal: $FORM{custom}", + body => $body, + }); + return "notified"; + } + + if ($FORM{payment_status} eq 'Refunded') { + $body = "Paypal has refunded the following transaction, please revoke the items manually\n\n$body"; + LJ::send_mail({ to => $LJ::PAYPAL_ERROR_EMAIL || $LJ::ACCOUNTS_EMAIL, + from => $LJ::BOGUS_EMAIL, + fromname => 'Paypal Refund', + subject => "Paypal Refund: $FORM{custom}", + body => $body, + }); + return "notified"; + } + + if (LJ::Pay::verify_paypal_transaction(\%FORM, { 'error' => \$error })) + { + $ok = LJ::Pay::register_paypal_payment($dbh, \%FORM, + { 'error' => \$error }); + } + + if ($FORM{custom}) { + if (my $custom = LJ::Pay::paypal_parse_custom($FORM{custom})) { + if (my $cartobj = LJ::Pay::load_cart($custom->{cart})) { + LJ::Pay::send_fraud_email($cartobj); + + if (my $u = LJ::load_userid($cartobj->{userid})) { + LJ::Pay::note_payment_from_user($u); + } + } + } + } + + my $errorsub; + unless ($ok) { + + # paypal sends us duplicate notifications fairly often, so when one is received, + # send an email to $LJ::PAYPAL_ERROR_EMAIL and tell paypal everything's okay + if ($error =~ /already paid/i) { + $body = "Paypal has sent notification of the following transaction, which has already been paid for\n\n$body"; + LJ::send_mail({ to => $LJ::PAYPAL_ERROR_EMAIL || $LJ::ACCOUNTS_EMAIL, + from => $LJ::BOGUS_EMAIL, + fromname => 'Paypal Duplicate Notification', + subject => "Paypal Duplicate Notification: $FORM{custom}", + body => $body, + }); + return "notified"; + } + + $errorsub = " (ERROR)"; + $body = "ERROR: $error\n\n$body"; + } + + $FORM{'custom'} =~ /user=(\w+)/; + my $user = $1; + + LJ::send_mail({ 'to' => $LJ::PAYPAL_ERROR_EMAIL || $LJ::ACCOUNTS_EMAIL, + 'from' => 'lj_dontreply@livejournal.com', + 'fromname' => 'LiveJournal', + 'subject' => "PayPal Notify - $user$errorsub", + 'body' => $body, + }); + + if ($ok) { + return "notified"; + } else { + return $err500->($error); + } +} +_code?> diff --git a/ljcom/htdocs/paidaccounts/status.bml b/ljcom/htdocs/paidaccounts/status.bml new file mode 100644 index 0000000..2f10a43 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/status.bml @@ -0,0 +1,53 @@ +Paid Account Status +body<= +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + return LJ::bad_input("Account has been deleted") + if $u->{'statusvis'} eq 'D' || $u->{'statusvis'} eq 'X'; + + my $ret; + + # authas switcher form + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'}, + 'cap' => 'paid' }) . "\n"; + $ret .= "
    \n\n"; + + my $getextra = "?authas=$authas" unless $authas eq $remote->{'user'}; + + $ret .= ""; + + # render account summary + $ret .= LJ::Pay::account_summary($u); + + # disk quota summary + my $qsummary = LJ::Pay::quota_summary($u); + return $ret unless $qsummary; + + $ret .= ""; + $ret .= ""; + + $ret .= $qsummary; + + return $ret; +} +_code?> +<=body +page?> + diff --git a/ljcom/htdocs/paidaccounts/thankyou.bml b/ljcom/htdocs/paidaccounts/thankyou.bml new file mode 100644 index 0000000..c2e7a2e --- /dev/null +++ b/ljcom/htdocs/paidaccounts/thankyou.bml @@ -0,0 +1,20 @@ +Thanks! +body<= + + + + +create a new account, an account creation code will be emailed to the same email address you used for PayPal. +p?> + + +<=body +page?> diff --git a/ljcom/htdocs/paidaccounts/usepaypal.bml b/ljcom/htdocs/paidaccounts/usepaypal.bml new file mode 100644 index 0000000..e9f91ce --- /dev/null +++ b/ljcom/htdocs/paidaccounts/usepaypal.bml @@ -0,0 +1,99 @@ +Pay using PayPal +body<= + +"; + } + + if ($FORM{'loggedin'}) { + my $remote = LJ::get_remote(); + unless ($remote && $remote->{'user'} eq $user) { + return ""; + } + } else { + unless (LJ::auth_okay($u, $FORM{'password'}, $FORM{'hpassword'})) { + return ""; + } + } + + my $giftfor = LJ::canonical_username($FORM{'giftfor'}); + + if ($FORM{'giftfor'} && ! $giftfor) { + return ""; + } + + # can't buy a gift for yourself. + undef $giftfor if ($giftfor eq $user); + + if ($giftfor) { + my $gu = LJ::load_user($giftfor); + unless ($gu) { + return ""; + } + if ($gu->{'caps'} & 16) { + return "{'user'} ljuser?> has a permanent account. You can't buy them a gift payment. p?>"; + } + } + + + my $months = $FORM{'months'}; + my $amount; + if (defined $LJ::Pay::account{$months}) { + $amount = $LJ::Pay::account{$months}->{'amount'}; + } + + unless ($amount) { + return ""; + } + + my $forkey = $giftfor ? "&for=$giftfor" : ""; + my $forwho = $giftfor ? ", for $giftfor" : ""; + my $anonkey = $FORM{'anon'} ? "&anon=1" : ""; + my $datekey; + if ($FORM{'giveafter'}) { + return "" + unless ($FORM{'giveafter'} =~ /^(\d\d\d\d)\-(\d\d)\-(\d\d)(?: (\d\d):(\d\d))?/); + + my $dtime = 0; + eval { $dtime = Time::Local::timegm(0, $5, $4, $3, $2-1, $1); }; + return "" if @$; + + my $delay = $dtime - time(); + return "" if $delay < 0; + return "" + if $delay > 60*60*24*31; + + $datekey = "&giveafter=$dtime"; + } + + $ret .= "All your LiveJournal data has been validated. To continue the purchase, click the PayPal icon below to go to PayPal's secure server and pay. PayPal then sends us a notification of the payment and your account will be automatically setup."; + $ret .= "
    "; + $ret .= "
    \n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + $ret .= "
    "; + + return $ret; + _code?> +<=body +page?> + diff --git a/ljcom/htdocs/paidaccounts/whyextra.bml b/ljcom/htdocs/paidaccounts/whyextra.bml new file mode 100644 index 0000000..28f4d91 --- /dev/null +++ b/ljcom/htdocs/paidaccounts/whyextra.bml @@ -0,0 +1,26 @@ +Philosophy +body<= + + +paid accounts and support the project. +p?> + + +
  • Users with paid accounts can make private and friends-only to-do items, but regular users can only make public items, and are limited to 25 to-do items at a time. +
  • Users with paid accounts can have 10 mini pictures to represent themselves in various parts of the site, while regular users can only have 3. + +In the future we'll probably continue this strategy. If you buy a paid account now, you'll be able to use future features as they become available. However, if you don't feel like buying an account, then don't ... we'll still make everything available to you, albeit in a slightly crippled fashion. +p?> + + + +<=body +page?> \ No newline at end of file diff --git a/ljcom/htdocs/palimg/anovelconundrum/dingbar.gif b/ljcom/htdocs/palimg/anovelconundrum/dingbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc1dfcccc13ac084a771ee5a7c6ceb4adee1c212 GIT binary patch literal 907 zcmb`GJ!_S548?O_S}#?!h=^##D_ts7CdMB(>gMK~?d`WaJMZ@PJ{%l;Iy%}vKK_xJ&BXuusECQUNQk76sfwDY zi-u@c(NxUDTr9-0dR@g$+{HsYYcy2CBwQjS5+q5LG)b2XNfNMu28&_3v-VV&s;h=- z)><+%HCGF@EEW{q)LlK)vq;e!rr{c)k#J;G(==T(G}#Jkz#t7vXi;M^*g%8DaF(FT z2{#L~EPbpcb2kt3EV;0t7;X_3iF!!UYw4C@i9Gy(Cezq~en_AY)__48mbAiy#b5&s zR+e*BCMUu@%SiOGmMp>}@fEqSpy(N%_=wXO0594x8nsx7AJAkPJK%(16v7%XNHYm7 zc(533ptDX?-IU3R&^T^8A=H69oPFOZKSE=5{=yJXBu0|U>>IjX(LTX6Y zO&T5r+(7djxDw_yn&j%=ZcF5}%+{N(e?odM<#KOo@o>~0?_Qdkd$l#(9qV+vll{rt z(mr{<-#_e+_FhlO<{9 literal 0 HcmV?d00001 diff --git a/ljcom/htdocs/pay/checkout.bml b/ljcom/htdocs/pay/checkout.bml new file mode 100644 index 0000000..49c83d1 --- /dev/null +++ b/ljcom/htdocs/pay/checkout.bml @@ -0,0 +1,69 @@ +{'userid'}) { + + my $remote = LJ::get_remote(); + return "You must be logged in as this cart's owner to proceed with checkout." + unless $remote; + return "You do not own this cart. If you'd like to start a new cart, please click " . + "here." + unless $cartobj->{'userid'} == $remote->{'userid'}; + } + + unless (LJ::Pay::is_valid_cart($cartobj)) { + return "The given cart contains items that are no longer valid. This could be caused by conflicts with other " . + "carts created during the same time. Please try again with a new cart."; + } + + my $ret; + $ret .= "Payment $cart"; + $ret .= ""; + $ret .= ""; + $ret .= "

    Order ($cart)

    "; + LJ::Pay::render_cart($cartobj, \$ret); + + if ($cartobj->{'amount'} > 0) { + $ret .= "

    Pay

    "; + $ret .= "If the above is correct, send your payment to:
    "; + $ret .= "
    " . LJ::Pay::postal_address_text() . "
    "; + + $ret .= "Please note the following guidelines:"; + $ret .= "
      "; + $ret .= "
    • Make checks or money orders payable to LiveJournal.com.
    • "; + $ret .= "
    • Checks will only be accepted from the United States and Canada and must be made out in United States fund (Your bank will calculate the exchange rate if you suffix the amount field with \"US Funds\").
    • "; + $ret .= "
    • Orders received later than 1 month from order creation date will not be accepted.
    • "; + $ret .= "
    • Include with payment either a print-out of this page or a note referencing:
      Payment $cart.
    • "; + $ret .= "
    "; + + $ret .= "

    "; + if (LJ::Pay::cart_needs_shipping($cartobj)) { + $ret .= "Your shipping address is on file, associated with your order number. "; + } + + $ret .= "Thank you for your order!

    "; + + } else { + + # mark cart as 'free' and ready for processing + my $dbh = LJ::get_db_writer(); + $dbh->do("UPDATE payments SET used='N', mailed='N', ". + "method='free', daterecv=NOW() WHERE payid=?", undef, + $cartobj->{'payid'}); + + $ret .= ""; + $ret .= ""; + } + + $ret .= ""; + return $ret; + + +} +_code?> diff --git a/ljcom/htdocs/pay/coupons.bml b/ljcom/htdocs/pay/coupons.bml new file mode 100644 index 0000000..cc4add5 --- /dev/null +++ b/ljcom/htdocs/pay/coupons.bml @@ -0,0 +1,68 @@ +($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u; + + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + + $body .= ""; + $body .= ""; + $body .= "$LJ::SITENAMESHORT Store. Used coupons are marked out, but "; + $body .= "still appear in the table. p?>"; + + my $tbl; + $tbl .= ""; + $tbl .= ""; + $tbl .= ""; + + # print dollars + my $damt = sub { sprintf("\$%.02f", shift()) }; + + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT * FROM coupon WHERE rcptid=?"); + $sth->execute($u->{'userid'}); + my $ct = 0; + while (my $row = $sth->fetchrow_hashref) { + my $str = sub { $row->{'payid'} ? "$_[0]" : $_[0] }; + $tbl .= ""; + $ct++; + } + if ($ct) { + $tbl .= "
    ItemAmountCode
    "; + $tbl .= $str->(LJ::Pay::product_name('coupon', $row->{'type'})); + $tbl .= "" . $str->($damt->($row->{'arg'})) . ""; + $tbl .= $str->($row->{'cpid'} . "-" . $row->{'auth'}); + $tbl .= "
    "; + $body .= $tbl; + } else { + $body .= "
    No Coupons
    "; + } + + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/pay/history.bml b/ljcom/htdocs/pay/history.bml new file mode 100644 index 0000000..d6d3350 --- /dev/null +++ b/ljcom/htdocs/pay/history.bml @@ -0,0 +1,62 @@ +($ML{'error.noremote'}) + unless $remote; + + $body .= ""; + + $body .= ""; + + # print dollars + my $damt = sub { sprintf("\$%.02f", shift()) }; + + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT * FROM payments " . + "WHERE userid=? AND anum IS NOT NULL AND (used='Y' OR used='N' " . + "OR (used='C' AND datesent>(NOW() - INTERVAL 1 MONTH)))"); + $sth->execute($remote->{'userid'}); + my @rows = (); + push @rows, $_ while $_ = $sth->fetchrow_hashref; + + unless (@rows) { + $body .= "
    No Orders
    "; + return; + } + + $_->{'datesent'} = substr($_->{'datesent'}, 0, 10) foreach @rows; + + $body .= ""; + $body .= ""; + $body .= ""; + + foreach my $row (sort { $b->{'datesent'} cmp $a->{'datesent'} } @rows) { + $body .= ""; + $body .= ""; + $body .= ""; + my $id = "$row->{'payid'}-$row->{'anum'}"; + $body .= ""; + } + + $body .= "
    DateStatusAmountOrder ID
    $row->{'datesent'}" . ($row->{'used'} eq 'C' ? "pending" : "completed") . "" . $damt->($row->{'amount'}) . "[$id]
    "; + + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/pay/index.bml b/ljcom/htdocs/pay/index.bml new file mode 100644 index 0000000..bfeca43 --- /dev/null +++ b/ljcom/htdocs/pay/index.bml @@ -0,0 +1,207 @@ +1 +_info?>Payment Center +body<= + + +LiveJournal services or clothing items, and then pay using a credit card, PayPal account, or mailing in a check with your order number. You can review the current status of any of your paid accounts or services by checking the Paid Account Status page. +p?> + +identity) { + return ""; + } + + if (! $COOKIE{'cart'} && $cart =~ /^(\d+)-(\d+)$/) { + $COOKIE{'cart'} = $cart; + } + + # FIXME: remove after ugly hack is gone + if ($LJ::PAY_INCLUDE_DISKQUOTA && $GET{include}) { + $COOKIE{'ljpayinclude'} = $GET{include}; + } + + my $cartobj = LJ::Pay::load_cart($cart); + if ($cartobj && $cartobj->{'userid'}) { + return "You must be logged in as this cart's owner to proceed with checkout." + unless $remote; + return "You do not own this cart. If you'd like to start a new cart, please click " . + "here." + unless $cartobj->{'userid'} == $remote->{'userid'}; + } + + if ($GET{'c'} eq "new") { + delete $COOKIE{'cart'}; + undef $cart; + } + + # see if cart's dead or c=new (invalid, so load new cart) + if (! $cartobj && $cart) { + delete $COOKIE{'cart'}; + undef $cart; + } + + # don't let them modify the cart if they've already started + # any sort of checkout process + my $can_mod = ! $cartobj || LJ::Pay::can_mod_cart($cartobj); + + # display a configurable banner if it exists + $ret .= ref $LJ::PAY_MARQUEE_HTML eq 'CODE' ? $LJ::PAY_MARQUEE_HTML->() : $LJ::PAY_MARQUEE_HTML . ''; + + $ret .= "
    "; + $ret .= LJ::html_hidden("cart", $cart); + + $ret .= "
    "; + LJ::Pay::render_cart($cartobj, \$ret, { + 'checkout' => 1, + 'pics' => 1, + 'remove' => $can_mod, + }); + $ret .= "
    "; + + # let 'em know if cart is paid for (if they're actually viewing a cart) + if ($cartobj && $cartobj->{'mailed'} ne "C") { + $ret .= "{'daterecv'}. p?>"; + $ret .= "
    "; + $ret .= "
    "; + return $ret; + } + + # let 'em know if cart is locked + unless ($can_mod) { + $ret .= ""; + $ret .= ""; + $ret .= " p?>"; + return $ret; + } + + if (LJ::Pay::cart_needs_shipping($cartobj)) { + $ret .= "Notice: To minimize costs, we have a strict no return policy. If you're buying clothing items, be sure to consult the size chart first. p?>"; + } + + # current account summary + if ($remote) { + $ret .= ""; + $ret .= "account status page. p?>"; + $ret .= LJ::Pay::account_summary($remote); + } + + # add items to order + $ret .= "underage) { + push @items, ("coppa", "Age Verification (for COPPA Compliance)"); + } + + # permanent account + if ($LJ::PERM_SALE) { + push @items, ("perm", + LJ::Pay::product_name("perm") . " (\$150.00 USD)"); + } + + # paid accounts + foreach my $mo (sort { $b <=> $a } keys %LJ::Pay::account) { + next unless $mo && $LJ::Pay::account{$mo}; + push @items, ("paidacct-$mo", + LJ::Pay::product_name("paidacct", undef, $mo) . + " (\$$LJ::Pay::account{$mo}->{'amount'}.00 USD)"); + } + + # bonus features + + # FIXME: this is an ugly hack just so we can give out ?include=diskquota + # urls for a limited beta of the disk quota purchase service. + # should be removed later. + my @bonus_list = LJ::Pay::bonus_item_list($remote, $cartobj); + while (my ($k, $v) = splice(@bonus_list, 0, 2)) { + next unless ! $LJ::PAY_INCLUDE_DISKQUOTA || $COOKIE{'ljpayinclude'} eq 'diskquota' || $k !~ /diskquota/; + + push @items, $k, $v; + } + + # pre-hack code + #push @items, LJ::Pay::bonus_item_list($remote, $cartobj); + + # rename tokens + push @items, ("rename", + LJ::Pay::product_name("rename") . " (\$15.00 USD)"); + + # coupons + foreach my $amt (@LJ::Pay::coupon) { + push @items, ("coupon-$amt", + LJ::Pay::product_name("coupon", "dollaroff", $amt) . " (\$$amt USD)"); + } + + # item drop-down + $ret .= ""; + $ret .= ""; + + # recipient + $ret .= ""; + $ret .= ""; + + # gift options + $ret .= ""; + + # add + $ret .= ""; + + $ret .= "
    Item:" . + LJ::html_select({ name => 'item', + selected => $GET{'item'}, + }, @items) . + LJ::help_icon("pay_item", " ") . + "
    Recipient:"; + if ($remote) { + my $checked = $GET{'for'} ? "" : "checked='checked'"; + $ret .= " : " . LJ::ljuser($remote->{'user'}) . "
    "; + } else { + $ret .= " : (you must first login)
    "; + } + + # other user + my $checked = $GET{'for'} ? "checked='checked'" : ""; + my $val_otheruser = LJ::ehtml($GET{'for'}); + $ret .= "
    "; + $ret .= "
    "; + $ret .= "      (new users: use this last option)"; + + $ret .= "
    Other options:"; + $ret .= " \n"; + $ret .= "

    $ML{'.deliverydate.label'}
    $ML{'.deliverydate.details'}"; + $ret .= "

    p?>"; + $ret .= "\n"; # close add form + + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_hidden("action:coupon", 1); + $ret .= LJ::html_hidden("cart", $cart); + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + + # Tshirt stuff + $ret .= ""; + $ret .= "LiveJournal Store. p?>"; + + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/pay/modify.bml b/ljcom/htdocs/pay/modify.bml new file mode 100644 index 0000000..88c3484 --- /dev/null +++ b/ljcom/htdocs/pay/modify.bml @@ -0,0 +1,973 @@ +{'r'}; + + ($title, $body) = ("", ""); + my $err = sub { + my @err = @_; + $title = $ML{'Error'}; + $body = LJ::bad_input(@err); + return; + }; + + my $dbh = LJ::get_db_writer(); + my $remote = LJ::get_remote(); + my $cart = $POST{'cart'}; + + LJ::load_user_props($remote, 'allow_pay') if $remote; + + # if coming from the /store/ area, pick up their cart cookie for 'em, + # save the /store/ code a bit of work (and redundancy) + if ($POST{'action:addinventory'}) { + $cart ||= $COOKIE{'cart'}; + } + + my $cartobj = LJ::Pay::load_cart($cart); + + # make sure they own this cart + if ($cartobj && $cartobj->{'userid'}) { + return "You must be logged in as this cart's owner to proceed with checkout." + unless $remote; + return "You do not own this cart. If you'd like to start a new cart, please click " . + "here." + unless $cartobj->{'userid'} == $remote->{'userid'}; + } + + my $ensurecart = sub { + return if $cartobj; + $cartobj = LJ::Pay::new_cart($remote); + $cart = "$cartobj->{'payid'}-$cartobj->{'anum'}"; + }; + + # don't let them modify the cart if they've already started + # any sort of checkout process + my $can_mod = ! $cartobj || ! $cartobj->{'method'}; + + # new order + if ($POST{'action:neworder'}) { + delete $BML::COOKIE{'cart'}; + return BML::redirect("/pay/?c=new&old=$cart"); + } + + # no cart... senseless action + if (($POST{'action:checkout'} || $POST{'action:removesel'}) + && ! $cartobj) { return BML::redirect("/pay/"); } + + # remove item(s) from cart + if ($POST{'action:removesel'}) { + return $err->("Can't modify checked-out cart.") unless $can_mod; + + my @remove; # piids to be removed, based on %POST submission + my %extra_remove; # piid => userid + + my %paid_in_cart; # userid => unixtime when earliest paid account will apply + my %bonus_in_cart; # userid => unixtime when earliest bonus feature will apply + my %userids_in_cart; # userid => 1, hash for fast lookups + foreach my $it (@{$cartobj->{'items'}}) { + + # the item they are trying to remove + if ($POST{"del_$it->{'piid'}"}) { + push @remove, $it; + next; + } + + my $ga = $it->{'giveafter'} || 0; + my $uid = $it->{'rcptid'}; + $userids_in_cart{$uid} = 1; + + # bonus feature + if (LJ::Pay::is_bonus($it)) { + + # find which instance of this bonus feature takes effect first + if (! defined $bonus_in_cart{$uid} || + $ga < $bonus_in_cart{$uid}) { + + $bonus_in_cart{$uid} = $ga; + } + + # paid account + } elsif ($it->{'item'} eq "paidacct") { + + # find which paid account takes effect sooner + if (! defined $paid_in_cart{$uid} || + $ga < $paid_in_cart{$uid}) { + + $paid_in_cart{$uid} = $ga; + } + } + } + + if (%bonus_in_cart) { + + # get expiration dates of paid accounts for users who have bonus in this cart + my %paid_in_db; + my $in = join(",", map { $dbh->quote($_) } keys %userids_in_cart); + my $sth = $dbh->prepare("SELECT userid, UNIX_TIMESTAMP(paiduntil) AS 'paiduntil' " . + "FROM paiduser WHERE userid IN ($in)"); + $sth->execute(); + $paid_in_db{$_->{'userid'}} = $_->{'paiduntil'} while $_ = $sth->fetchrow_hashref; + + # remove free users with no paid time in their cart + foreach my $it (@{$cartobj->{'items'}}) { + next if $POST{"del_$it->{'piid'}"}; # skip item if being deleted + next unless LJ::Pay::is_bonus($it); + + my $ga = $it->{'giveafter'} || 0; + my $uid = $it->{'rcptid'}; + + if ((! defined $paid_in_cart{$uid} || + ($paid_in_cart{$uid} > 0 && $ga < $paid_in_cart{$uid})) && + (! defined $paid_in_db{$uid} || $ga > $paid_in_db{$uid})) { + + $extra_remove{$it->{'piid'}} = $uid; + } + } + + # extra items were removed, notify the user why + if (%extra_remove) { + $body .= ""; + $body .= ""; + + $body .= "
      "; + + # load usernames so we can report them below + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } values %extra_remove ], + [$remote]); + + foreach my $it (@{$cartobj->{'items'}}) { + next unless $extra_remove{$it->{'piid'}} && LJ::Pay::is_bonus($it); + + $body .= "
    • " . LJ::ljuser($users{$it->{'rcptid'}}) . " - "; + $body .= LJ::Pay::product_name($it, "short") . "
    • "; + } + $body .= "
    "; + + $body .= "
    "; + $body .= LJ::html_hidden('c', $cart); + $body .= "

    " . LJ::html_submit("Acknowledged") . "

    "; + $body .= "
    "; + } + } + + LJ::Pay::remove_cart_items($cartobj, @remove, keys %extra_remove); + + if (%extra_remove) { + # body was filled in above + return; + } else { + return BML::redirect("/pay/?c=$cart"); + } + } + + # checkout + if ($POST{'action:checkout'}) { + return $err->("invalid payment method") unless + $POST{'paymeth'} =~ /^check|moneyorder|cash|cc|paypal$/ || $cartobj->{'amount'} == 0; + return $err->("invalid payment method for age verification") if + $POST{'paymeth'} ne 'cc' && LJ::Pay::cart_contains_coppa($cartobj); + $POST{'paymeth'} = "free" if $cartobj->{'amount'} == 0 && ! LJ::Pay::cart_needs_shipping($cartobj) && ! LJ::Pay::cart_contains_coppa($cartobj); + + if ($cartobj->{userid} && $remote && $remote->underage && + ! scalar grep { $_->{item} eq 'coppa' } @{$cartobj->{items}}) { + + return $err->("Your account is marked as underage (see COPPA requirements). " . + "You must go back and add a COPPA verification item to your account before continuing."); + } + + + # mark all coupons as used - though we've changed to updating payids on coupons when they are added + # to the cart rather than when the cart is checked out, we still need to catch coupons that were + # already in carts at the time the change was made... we'll just do that fixup here + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'item'} eq "coupon" && $it->{'amt'} < 0; + $dbh->do("UPDATE coupon SET payid=? WHERE cpid=? AND payid=0", undef, $cartobj->{'payid'}, $it->{'tokenid'}); + } + + # open proxy check (disabled if remote has allow_pay set) + unless ($remote && $remote->{allow_pay} eq 'Y') { + my $remote_ip = LJ::get_remote_ip(); + if (LJ::is_open_proxy($remote_ip)) { + $title = "Open Proxy Detected"; + $body = "Your IP address ($remote_ip) is detected as an open proxy (a common source of fraud) so access to placing orders is denied. If you do not believe you're accessing the net through an open proxy, please contact your ISP or this site's tech support to help resolve the problem."; + return; + } + } + + # verify cart (check for items that have been invalidated since adding) + unless (LJ::Pay::is_valid_cart($cartobj)) { + $title = $ML{'Sorry'}; + $body .= "The given cart contains items that are no longer valid. This could be caused by conflicts with other carts " . + "created during the same time. Please try again with a new cart"; + $body .= " or continue one of your existing carts" if $remote; + $body .= "."; + return; + } + + my $needs_shipping = LJ::Pay::cart_needs_shipping($cartobj); + + if ($POST{'paymeth'} eq "paypal" && $needs_shipping) { + $title = $ML{'Sorry'}; + $body .= "Paying for clothing items with PayPal is not supported. Please go back and choose an alternate means of payment."; + return; + } + + my @out_of_stock; + if ($needs_shipping && ! LJ::Pay::reserve_items($cartobj, \@out_of_stock)) { + $title = "Out of Stock"; + $body .= ""; + $body .= "
      "; + foreach (@out_of_stock) { $body .= "
    • $_
    • "; } + $body .= "
    "; + if (@out_of_stock > 1) { + $body .= ""; + } else { + $body .= "LiveJournal Store -- out of stock items are indicated there. p?>"; + } + return; + } + + $dbh->do("UPDATE payments SET method=? WHERE payid=? AND used='C'", + undef, $POST{'paymeth'}, $cartobj->{'payid'}); + + # if they've logged in since making the cart, update the cart's ownership + if ($cartobj->{'userid'} == 0 && $remote) { + $dbh->do("UPDATE payments SET userid=? WHERE payid=? AND used='C'", + undef, $remote->{'userid'}, $cartobj->{'payid'}); + } + + if ($needs_shipping) { + my %payvar; + my $sth = $dbh->prepare("SELECT pkey, pval FROM payvars WHERE payid=? AND pkey LIKE 'ship%'"); + $sth->execute($cartobj->{'payid'}); + while (my ($k, $v)= $sth->fetchrow_array) { $payvar{$k} = $v; } + + if ($POST{'save_shipping'}) { + foreach my $v (qw(name addr1 addr2 city state zip country)) { + my $k = "ship_$v"; + if ($POST{$k} ne $payvar{$k}) { + LJ::Pay::payvar_set($cartobj->{'payid'}, $k, $POST{$k}); + } + } + return $err->("Shipping address needed") unless $POST{'ship_addr1'}; + return $err->("City needed") unless $POST{'ship_city'}; + if ($POST{'ship_country'} eq "us") { + return $err->("5 digit zip code required") unless $POST{'ship_zip'} =~ /^\d\d\d\d\d/; + return $err->("State needed") unless $POST{'ship_state'}; + } + + LJ::Pay::update_shipping_cost($cartobj, $POST{'ship_country'}); + + } else { + + my %countries; + LJ::load_codes({ "country" => \%countries }); + + $title = "Shipping Address"; + $body .= ""; + $body .= "
    "; + $body .= ""; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= "\n"; + $body .= "
    Name:" . LJ::html_text({ name => 'ship_name', + size => 30, + value => $payvar{'ship_name'} }) . "
    Address:" . LJ::html_text({ name => 'ship_addr1', + size => 30, + value => $payvar{'ship_addr1'} }) . "
    " . LJ::html_text({ name => 'ship_addr2', + size => 30, + value => $payvar{'ship_addr2'} }) . "
    City" . LJ::html_text({ name => 'ship_city', + size => 30, + value => $payvar{'ship_city'} }) . "
    State" . LJ::html_text({ name => 'ship_state', + size => 30, + value => $payvar{'ship_state'} }) . "
    Zip" . LJ::html_text({ name => 'ship_zip', + size => 30, + value => $payvar{'ship_zip'} }) . "
    Country:"; + $body .= LJ::html_select({ 'name' => 'ship_country', + 'selected' => $payvar{'ship_country'}, }, + map { $_, $countries{$_} } + ("US", sort { $countries{$a} cmp $countries{$b} } + keys %countries)); + $body .= "
    (extra shipping cost outside US & Canada)" + unless $cartobj->{'amount'} == 0; + $body .= "
    \n"; + + $body .= LJ::html_hidden('save_shipping', 1); + foreach (keys %POST) { + $body .= LJ::html_hidden($_, $POST{$_}); + } + $body .= "
    "; + + $body .= ""; + $body .= ""; + $body .= "
    T-shirt value: \$14.00
    "; + return; + } + } + + # for debugging, log the browser + my $ua = BML::get_client_header("User-Agent"); + LJ::Pay::payvar_add($cartobj->{'payid'}, "browser", $ua) if $ua; + + # log uniq + my $uniq = $r->notes('uniq'); + LJ::Pay::payvar_add($cartobj->{'payid'}, "uniq", LJ::mysql_time() . " - $uniq") if $uniq; + + if ($POST{'paymeth'} eq "cash") { + $title = "Cash Warning"; + $body = ""; + $body .= "
    "; + $body .= LJ::html_hidden("c", $cart); + $body .= LJ::html_hidden("meth", "cash"); + $body .= "
    "; + return; + } + + if ($POST{'paymeth'} eq "check" || + $POST{'paymeth'} eq "moneyorder") { + return BML::redirect("/pay/checkout.bml?c=$cart&meth=$POST{'paymeth'}"); + } + + my $pp_url; + { + my $count = scalar(@{$cartobj->{'items'}}); + my $amount = $cartobj->{'amount'}; + $pp_url = "https://www.paypal.com/cgi-bin/webscr?amount=$amount&return=http%3A//www.livejournal.com/paidaccounts/thankyou.bml&item_name=" . LJ::eurl("Cart ID $cart ($count item(s))") . "&custom=" . LJ::eurl("cart=$cart") . "&business=paypal%40livejournal.com&cmd=_xclick&cmd=_xclick&no_shipping=1&no_note=1¬ify_url=http%3A//www.livejournal.com/paidaccounts/pp_notify.bml"; + } + + if ($POST{'paymeth'} eq "paypal") { + + # is paypal gateway down? + if ($LJ::PAYPAL_DOWN) { + $title = "PayPal Temporarily Unavailable"; + $body .= "" . + ""; + return; + } + + return BML::redirect($pp_url); + } + + if ($POST{'paymeth'} eq "cc") { + if ($LJ::AUTHNET_DOWN) { + $title = "Primary Credit Card Processor Unavailable"; + $body = ""; + + unless ($LJ::PAYPAL_DOWN) { + $body .= "
    Pay with PayPal
    "; + } + + return; + } + + return BML::redirect("$LJ::SSLROOT/pay/cc.bml?c=$cart"); + } + + if ($POST{'paymeth'} eq "free") { + $dbh->do("UPDATE payments SET mailed='N', used='N', method='free', daterecv=NOW() ". + "WHERE payid=? AND mailed='C' AND used='C'", + undef, $cartobj->{'payid'}); + $title = "Success"; + $body = "Order placed. For reference, your order number is $cart."; + return; + } + } + + my $msg_already_out = "Your currently active order has already been checked out. To add items you must first start a new order."; + + # add coupon to cart + if ($POST{'action:coupon'}) { + return $err->($msg_already_out) unless $can_mod; + return $err->("Can't add a coupon to an empty order. Add items first, then apply your coupon.") + unless $cartobj; + + my $coupon = $POST{'coupon'}; + return $err->("Invalid coupon format") unless $coupon =~ /^(\d+)-(.+)$/; + my ($cpid, $auth) = ($1, $2); + my $cp = $dbh->selectrow_hashref("SELECT * FROM coupon WHERE cpid=? AND auth=?", undef, + $cpid, $auth); + return $err->("Invalid coupon") unless $cp; + return $err->("Coupon belongs to somebody else") if $cp->{'locked'} && (! $remote || $remote->{'userid'} != $cp->{'rcptid'}); + + # see if coupon is already in this cart + if (grep { $_->{'item'} eq "coupon" && $_->{'tokenid'} == $cp->{'cpid'} } + @{$cartobj->{'items'}}) { + return BML::redirect("/pay/?c=$cart"); + } + + # can only add freeclothingitem coupons to carts with clothes in them + if ($cp->{'type'} eq "freeclothingitem") { + return $err->("There does not exist a clothing item for which this coupon can be used.") unless + grep { $_->{'item'} eq "clothes"} @{$cartobj->{'items'}}; + } + + # coupon is already attached to a cart + if ($cp->{'payid'}) { + + # error generically if they're not logged in + return $err->("Coupon has already been used") unless $remote; + + # see who owns the cart the coupon is attached to + my $oldcart = $dbh->selectrow_hashref("SELECT userid, used, method, anum " . + "FROM payments WHERE payid=?", + undef, $cp->{'payid'}); + + # can't give a link to a cart they don't own + return $err->("Coupon has already been used by another user") + unless $remote->{'userid'} == $oldcart->{'userid'}; + + # now we know they own the cart, so we'll give them a link to view/modify it. + # modify is only possible if 'used' = 'C' and 'method' = '' + my $cart = "$cp->{'payid'}-$oldcart->{'anum'}"; + my $verb = ($oldcart->{'used'} eq 'C' && ! $oldcart->{'method'}) + ? "modify" : "view"; + + return $err->("The coupon you have entered has already been used on another one of your carts. " . + "If you'd like, you can $verb the existing cart or " . + "go back and enter a new coupon for the current cart."); + } + + my $item = { + 'item' => 'coupon', + 'subitem' => $cp->{'type'}, + 'tokenid' => $cpid, + 'token' => $coupon, + 'amt' => -$cp->{'arg'}, + 'rcptid' => 0, + }; + $item = LJ::Pay::add_cart_item($cartobj, $item); + + return $err->("Error adding coupon to order: " . LJ::last_error()) unless $item; + + # mark coupon as used by this cart + $dbh->do("UPDATE coupon SET payid=? WHERE cpid=?", undef, $cartobj->{'payid'}, $cp->{'cpid'}); + + return BML::redirect("/pay/?c=$cart"); + } + + # add item to cart + if ($POST{'action:additem'}) { + return $err->($msg_already_out) unless $can_mod; + $ensurecart->(); + + # itemname-subitem?-qty, subitem is optional + my ($itemname, $subitem, $qty) = split(/\-/, $POST{'item'}); + unless ($qty) { + $qty = $subitem; + undef $subitem; + } + + my $good_bonus = sub { + return 0 unless LJ::Pay::is_bonus($itemname); + + my $brec = $LJ::Pay::bonus{$itemname}; + if (LJ::Pay::is_bonus($itemname, 'sized')) { + return exists $brec->{items}->{$subitem} && + exists $brec->{items}->{$subitem}->{qty}->{$qty}; + } + + return exists $brec->{items}->{$qty}; + }; + + # valid item? + my $bad_item = 1; + $bad_item = 0 if $good_bonus->(); # bonus features + $bad_item = 0 if $itemname eq "paidacct" && defined $LJ::Pay::account{$qty}; + $bad_item = 0 if $itemname eq "coupon" && grep { $_ eq $qty } @LJ::Pay::coupon; + $bad_item = 0 if $itemname eq "perm" && $LJ::PERM_SALE; + $bad_item = 0 if $itemname eq "coppa"; + $bad_item = 0 if $itemname eq "rename"; + return BML::redirect("/pay/?c=$cart") if $bad_item; + + my $item = { + 'item' => $itemname, + 'rcptid' => 0, + }; + + ### Decide pricing/qty information depending on item type + + # paid account + if ($itemname eq "paidacct") { + $item->{'qty'} = $qty; + $item->{'amt'} = $LJ::Pay::account{$qty}->{'amount'}; + } + + # sized bonus feature + elsif (LJ::Pay::is_bonus($itemname, 'sized')) { + + # essentially the subitem for sized bonus features is the 'size', but to make sure that + # multiple orders don't get comp'd time, we'll store the previous size/qty as well, so + # the actual stored subitem will be: + # new_size-prev_exp-prev_size + + my ($prev_exp, $prev_size) = LJ::Pay::get_bonus_dim($remote, $itemname); + $item->{'subitem'} = "$subitem-$prev_exp-$prev_size"; + $item->{'amt'} = LJ::Pay::get_sized_bonus_price($remote, $cartobj, $itemname, $subitem, $qty); + $item->{'qty'} = $qty; + } + + # bool bonus feature + elsif (LJ::Pay::is_bonus($itemname, 'bool')) { + $item->{'qty'} = $qty; + $item->{'amt'} = LJ::Pay::get_bool_bonus_price($itemname, $qty); + } + + # coupons + elsif ($itemname eq "coupon") { + $item->{'amt'} = $qty; + $item->{'subitem'} = "dollaroff"; + } + + # rename token + elsif ($itemname eq "rename") { + $item->{'amt'} = 15; + } + + # permanent account + elsif ($itemname eq "perm") { + $item->{'amt'} = 150; + } + + # coppa verification + elsif ($itemname eq "coppa") { + $item->{'amt'} = 0; + } + + ### Decide recipient + + if ($POST{'redemail'} && $POST{'for'} ne "email") { + return $err->("Redemption email entered, but not selected. Not sure what you meant."); + } + + my $rcptuser = {}; + if ($POST{'for'} eq "remote") { + return $err->("No longer logged in, but paying for logged in account") unless $remote; + return $err->("Can't buy a coupon for yourself") if $itemname eq 'coupon'; + $item->{'rcptid'} = $remote->{'userid'}; + $rcptuser = $remote; + } elsif ($POST{'for'} eq "other") { + my $ou = LJ::load_user($POST{'otheruser'}); + return $err->("Invalid gift recipient username") unless $ou; + return $err->("Cannot buy paid features for syndicated accounts") + if $ou->{'journaltype'} eq 'Y'; + return $err->("Cannot buy paid features for renamed accounts") + if $ou->{'journaltype'} eq 'R'; + return $err->("Cannot buy paid features for " . LJ::ljuser($ou) . " due to account status") + unless $ou->{'statusvis'} eq 'V' || $ou->{'statusvis'} eq 'M'; + + $item->{'rcptid'} = $ou->{'userid'}; + $rcptuser = $ou; + + # don't let them easily check to see if they're blocked + unless ($remote && $remote->{'user'} eq $ou->{'user'}) { + my $pay_user = $remote ? $remote->{'user'} : 'anonymous'; + my $pay_userid = $remote ? $remote->{'userid'} : undef; + if (LJ::sysban_check('pay_user', $ou->{'user'})) { + LJ::sysban_note($pay_userid, + "Gift blocked based on user", + { 'item' => $itemname, + 'pay_user' => $pay_user, + 'rcpt_user' => $ou->{'user'}, + 'cart' => $cart }); + return $err->("You are not allowed to buy gifts for " . LJ::ljuser($ou->{'user'})); + } + } + } elsif ($POST{'for'} eq "email") { + + # can't buy bonus features for an email address + return $err->("Extra features can only be purchased for existing users.") + if LJ::Pay::is_bonus($itemname); + + my @email_errors; + LJ::check_email($POST{'redemail'}, \@email_errors); + return $err->(@email_errors) if @email_errors; + $item->{'rcptemail'} = $POST{'redemail'}; + + # don't let them easily check to see if they're blocked + unless ($remote && $remote->{'email'} eq $item->{'rcptemail'}) { + my $pay_user = $remote ? $remote->{'user'} : 'anonymous'; + my $pay_userid = $remote ? $remote->{'userid'} : undef; + if (LJ::sysban_check('pay_email', $item->{'rcptemail'})) { + LJ::sysban_note($pay_userid, + "Gift blocked based on email", + { 'item' => $itemname, + 'pay_user' => $pay_user, + 'rcpt_email' => $item->{'rcptemail'}, + 'cart' => $cart }); + return $err->("You are not allowed to buy gifts for '$item->{'rcptemail'}'"); + } + } + } + + unless ($item->{'rcptid'} || $item->{'rcptemail'}) { + return $err->("No specified recipient for item"); + } + + # must be logged in and purchasing 'sized' bonus features for self + if (LJ::Pay::is_bonus($itemname, 'sized')) { + my $dispname = LJ::Pay::product_name($item, "short"); + + # must be logged in + return $err->("Must be logged in to buy $dispname.") + unless $remote; + + # can't buy as a gift + return $err->("Can't buy $dispname as a gift.") + unless $remote->{'userid'} == $item->{'rcptid'}; + + # shouldn't get this far, did they spoof the form values? + return $err->("Cannot buy $dispname.") + unless LJ::Pay::can_apply_sized_bonus($rcptuser, $cartobj, $item->{'item'}, $item->{'subitem'}, $item->{'qty'}); + } + + # can't buy paid time for permanent accounts + if ($item->{'rcptid'} && ($itemname eq 'paidacct' || $itemname eq 'perm')) { + return $err->("Cannot buy paid time for permanent accounts") + if $rcptuser->{'caps'} & 1 << $LJ::Pay::capinf{'perm'}->{'bit'}; + } + + # can't have more than one permanent account per recipient + if ($itemname eq 'perm') { + foreach (@{$cartobj->{items}}) { + return $err->("Cannot purchase more than one permanent account for a given recipient.") + if $item->{rcptid} && $item->{rcptid} == $_->{rcptid} || + $item->{rcptemail} && $item->{rcptemail} eq $_->{rcptemail}; + } + } + + # can't do coppa verifications except on $remote + if ($itemname eq 'coppa') { + return $err->("Cannot perform age verification on non-logged-in users") + if ! $remote || $remote->{userid} != $item->{rcptid}; + + return $err->("Age verification not required for " . LJ::ljuser($remote)) + unless $remote->underage; + } + + $item->{'anon'} = $POST{'anongift'} ? 1 : 0; + + # delayed gift + if ($POST{'giveafter'}) { + return $err->("Cannot specify a Delivery Date on orders for yourself.") + if $item->{'rcptid'} && $remote && $item->{'rcptid'} == $remote->{'userid'}; + + return $err->($ML{'/paidaccounts/usepaypal.bml.delivery.badformat'}) + unless ($POST{'giveafter'} =~ /^(\d\d\d\d)\-(\d\d)\-(\d\d)(?: (\d\d):(\d\d))?/); + + my $dtime = 0; + eval { $dtime = Time::Local::timegm(0, $5, $4, $3, $2-1, $1); }; + return $err->($ML{'/paidaccounts/usepaypal.bml.delivery.badformat'}) if @$; + + my $delay = $dtime - time(); + return $err->($ML{'/paidaccounts/usepaypal.bml.delivery.past'}) if $delay < 0; + return $err->($ML{'/paidaccounts/usepaypal.bml.delivery.toofuture'}) + if $delay > 60*60*24*31; + + $item->{'giveafter'} = $dtime; + } else { + $item->{'giveafter'} = undef; + } + + # buying bonus-feature, lots of extra checks + if (LJ::Pay::is_bonus($itemname) && ! $POST{'action:additem:confirm'}) { + + # check to see if the user is trying to buy bonus features that extend + # past the expiration of their paid account... factor in any paid time + # currently in the cart as well. if so, ask for confirmation + + my $cart_bonus_months = $item->{'qty'}; # months of bonus feat. in cart + my $cart_paid_months = 0; # months of paidacct in cart + my $cart_bonus_start = $item->{'giveafter'}; # start of bonus feature in cart + my $cart_paid_start = undef; # start of paid account in cart + my $cart_perm_acct = 0; # can't buy bool bonus features for perms + + foreach my $it (@{$cartobj->{'items'}}) { + next unless $it->{'rcptid'} == $item->{'rcptid'}; + + my $ga = $it->{'giveafter'} || 0; + + # bonus item + if ($it->{'item'} eq $itemname) { + $cart_bonus_months += $it->{'qty'}; + + # find which instance of this bonus feature takes effect first + if (! defined $cart_bonus_start || + $ga < $cart_bonus_start) { + + $cart_bonus_start = $ga; + } + + # paid account + } elsif ($it->{'item'} eq "paidacct") { + $cart_paid_months += $it->{'qty'}; + + # find which paid account takes effect sooner + if (! defined $cart_paid_start || + $ga < $cart_paid_start) { + + $cart_paid_start = $ga; + } + + } elsif ($it->{'item'} eq 'perm') { + $cart_perm_acct = 1; + } + } + $cart_paid_start ||= 0; + + my $is_perm = ($cart_perm_acct || $rcptuser->{'caps'} & 1 << $LJ::Pay::capinf{'perm'}->{'bit'}); + + # give error if trying to buy bonus feature for permanent account + # -- but we do allow buying disk quota for permanent accounts + if (LJ::Pay::is_bonus($itemname, 'bool') && $is_perm) { + + my $dispname = LJ::Pay::product_name($item, "short"); + return $err->("You cannot buy $dispname for permanent accounts."); + } + + # return max of arguments, undef if none + my $max = sub { @_ ? (sort { $b <=> $a } @_)[0] : undef; }; + + + my $db_paid_time = $is_perm ? $LJ::EndOfTime : + $dbh->selectrow_array("SELECT UNIX_TIMESTAMP(paiduntil) " . + "FROM paiduser WHERE userid=?", + undef, $item->{'rcptid'}) || 0; + + # used in messages, $rcptuser is always defined here + my $utag = LJ::ljuser($rcptuser); + + # no paid account at all + my $dispname = LJ::Pay::product_name($item, "short"); + unless ($db_paid_time || $cart_paid_months) { + return $err->("You can only buy extra features for an existing " . + "paid account. If you would like to buy $dispname for " . + "$utag, put a paid account for them to your cart and try again."); + } + + my $ga = $item->{'giveafter'} || 0; + + # fix bonus giveafter to coincide with earliest paid account + if ($cart_paid_start > 0 && + (! $ga && ! $db_paid_time || $ga > $db_paid_time && $ga < $cart_paid_start)) { + + # can't adjust giveafter if recipient == remote + if ($remote && $remote->{'userid'} == $item->{'rcptid'}) { + return $err->("You are attempting to buy $dispname, but your paid " . + "account will expire before the first paid account " . + "currently in your cart will take effect. Since $dispname " . + "cannot be applied to a free account, it cannot be added to your cart."); + } + + # cart_paid_start is a localtime, convert it to gmtime in mysql format + # to post back to ourselves + $item->{'giveafter'} = LJ::mysql_time(Time::Local::timelocal(gmtime($cart_paid_start))); + + $POST{'giveafter'} = $item->{'giveafter'}; + + # pass on post variables + $body .= "
    "; + $body .= LJ::html_hidden( map { $_ => $POST{$_} } + qw(redemail otheruser paymeth action:additem + for item giveafter cart anongift) ); + + # explain expiration + my $utag = LJ::ljuser(LJ::load_userid($item->{'rcptid'})); + $body .= "" . + "$dispname, but ${utag}'s paid " . + "account (if they have one) will expire before the first paid account " . + "currently in your cart will take effect. Since $dispname " . + "cannot be applied to a free account, this is a problem. p?>" . + "$dispname " . + "to be the same as the delivery time of the first paid account in your " . + "cart: $item->{'giveafter'} GMT. p?>"; + + $body .= "

    " . LJ::html_submit('action:additem:confirm', + 'Acknowledged') . "

    "; + $body .= "
    "; + + return; + } + + # remove giveafter if no paid account in cart and it is after the + # expiration of their current paid account + if ($db_paid_time > 0 && $ga > $db_paid_time && + (! $cart_paid_months || $ga < $cart_paid_start)) { + + # get rid of giveafter date in memory, to be clean + delete $item->{'giveafter'}; + delete $POST{'giveafter'}; + + # pass on post variables + $body .= "
    "; + $body .= LJ::html_hidden( map { $_ => $POST{$_} } + qw(redemail otheruser paymeth action:additem + for item cart anongift) ); + + # explain expiration + my $utag = LJ::ljuser(LJ::load_userid($item->{'rcptid'})); + $body .= "" . + "$dispname, but ${utag}'s paid " . + "account will expire after the specified delivery date. Since you do " . + "not have a paid account in your cart for ${utag} and " . + "$dispname cannot be applied to a free account, this is a" . + "problem. p?>" . + "$dispname " . + "to be immediately. p?>"; + + $body .= "

    " . LJ::html_submit('action:additem:confirm', + 'Acknowledged') . "

    "; + $body .= "
    "; + + return; + } + + my $db_bonus_time = + $max->($dbh->selectrow_array("SELECT UNIX_TIMESTAMP(), " . + "UNIX_TIMESTAMP(expdate), " . + "UNIX_TIMESTAMP(NOW() + INTERVAL daysleft DAY) " . + "FROM paidexp WHERE userid=? AND item=?", + undef, $item->{'rcptid'}, $itemname)); + $db_bonus_time ||= 0; + + # the following check doesn't produce a warning in the case that there + # is paid time set to be applied at a later date, but the bonus feature + # being added is starting during the small amount of paid time still in + # the db which will expire before the delayed paid time will be applied. + + # |--- won't catch if 2 months of bonus applied here + # V + # [DBTIME...[NOW] 2 DAYS] ... [NON-P-TIME] ... [2 MONTHS CART-P-TIME DELAYED] + + # since this is just a warning mechanism, we won't kill ourselves trying + # to catch this situation + + + # we add $cart_paid_months to the $paid_base to determine if it is after + # when the bonus features will expire. if so, no error. + + my $paid_base = $db_paid_time || "NOW()"; + + # paid time in cart + if ($cart_paid_start && $cart_paid_months) { + + # paid base is the max of when the cart paid time starts + # and when the db paid time ends, since cart paid time + # only applies once db paid time ends. + + $paid_base = $max->($cart_paid_start, $db_paid_time); + } + + # we add $cart_bonus_months to the $bonus_base to determine if it is after + # when the paid account will expire. if so, error. + my $bonus_base = $db_bonus_time || "NOW()"; + + # bonus time in cart + if ($cart_bonus_start && $cart_bonus_months) { + + # bonus base is the max of when the cart bonus time starts, + # and when the db bonus time ends, since the delivery date + # of the item currently being added is already figured in. + + $bonus_base = $max->($cart_bonus_start, $db_bonus_time); + } + + my $bonus_base_stamp = LJ::mysql_time($bonus_base); + my $paid_base_stamp = LJ::mysql_time($paid_base); + + # is bonus expiration before or on the same day as paid expiration? + my $allow = $dbh->selectrow_array + ("SELECT TO_DAYS(? + INTERVAL ? MONTH) <= TO_DAYS(? + INTERVAL ? MONTH)", + undef, $bonus_base_stamp, $cart_bonus_months, $paid_base_stamp, $cart_paid_months); + + unless ($allow) { + + # pass on post variables + $body .= "
    "; + $body .= LJ::html_hidden( map { $_ => $POST{$_} } + qw(redemail otheruser paymeth action:additem + for item giveafter cart anongift) ); + + # explain expiration + my $utag = LJ::ljuser(LJ::load_userid($item->{'rcptid'})); + $body .= ""; + $body .= "$dispname, but the subscription "; + $body .= "time extends past the expiration date of ${utag}'s paid account. p?>"; + + my $currently; + if ($db_paid_time && $item->{'rcptid'} == $remote->{'rcptid'}) { + $currently = " (currently on " . LJ::time_to_http($db_paid_time) . ", " . + "not including additional time currently in your shopping cart)"; + } + + $body .= "

    You can continue, but the new feature will be deactivated when "; + $body .= "${utag}'s paid account expires$currently. However, if $utag gets "; + $body .= "additional paid account time later, then the remaining $dispname "; + $body .= "time will be applied to their account.

    "; + + $body .= "

    " . LJ::html_submit('action:additem:confirm', + 'Acknowledged') . "

    "; + $body .= "
    "; + + return; + } + } + + # add the item + LJ::Pay::add_cart_item($cartobj, $item); + + return BML::redirect("/pay/?c=$cart"); + } + + # add a physical item + if ($POST{'action:addinventory'}) { + my $prod = $POST{'product'}; + return $err->("Invalid product.") unless $prod =~ /^(\w+?)-(.+)$/; + return $err->($msg_already_out) unless $can_mod; + my ($item_type, $subitem) = ($1, $2); + + # they need to be logged in (no gift products for now at least) + return $err->("You need to log in before adding items to your cart.") + unless $remote; + + # see if it's available, and its price + my $inv = $dbh->selectrow_hashref("SELECT qty, avail, price FROM inventory WHERE ". + "item=? AND subitem=?", undef, $item_type, $subitem); + return $err->("Invalid product.") unless $inv; + return $err->("Sorry, selected product is out of stock.") unless $inv->{'avail'}; + + my $item = { + 'item' => $item_type, + 'subitem' => $subitem, + 'qty' => 1, + 'amt' => $inv->{'price'}, + 'rcptid' => $remote->{'userid'}, + }; + + $ensurecart->(); + my $rt = LJ::Pay::add_cart_item($cartobj, $item); + return "Failed to add item to cart: " . $dbh->errstr unless $rt; + + return BML::redirect("/pay/?c=$cart"); + } + +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/phonepost/about.bml b/ljcom/htdocs/phonepost/about.bml new file mode 100644 index 0000000..7de73aa --- /dev/null +++ b/ljcom/htdocs/phonepost/about.bml @@ -0,0 +1,9 @@ +About Post by Phone +body<= + +paid account perk; paying members can make up to 15 posts a month. p?> + +Ogg Vorbis files. There are a lot of media players for different operating systems that will play .ogg files, and most are free to download and use. p?> +<=body +page?> diff --git a/ljcom/htdocs/phonepost/encodings.bml b/ljcom/htdocs/phonepost/encodings.bml new file mode 100644 index 0000000..0bfdd5c --- /dev/null +++ b/ljcom/htdocs/phonepost/encodings.bml @@ -0,0 +1,29 @@ +Encoding Choices +body<= + + + + + + + +Ogg Vorbis page. +p?> + + + + +<=body +page?> + diff --git a/ljcom/htdocs/phonepost/index.bml b/ljcom/htdocs/phonepost/index.bml new file mode 100644 index 0000000..4b7dfc0 --- /dev/null +++ b/ljcom/htdocs/phonepost/index.bml @@ -0,0 +1,56 @@ +Post by Phone +head<= + +<=head +body<= + +
      +
    1. Call one of our designated numbers
    2. +
    3. Use your PIN to authorize your phone number
    4. Record your post
    5. +
    +compress and post the audio file to your journal as a new entry. p?> +Settings page. p?>
    + + 0) { + my $dbcr = LJ::get_cluster_reader($remote); + my $phoneusage = $dbcr->selectrow_array + ("SELECT COUNT(*) FROM phonepostentry ". + "WHERE userid=? AND ". + "MONTH(FROM_UNIXTIME(posttime)) = MONTH(NOW()) AND ". + "YEAR(FROM_UNIXTIME(posttime)) = YEAR(NOW())", + undef, $remote->{userid}); + + my $diskmax = LJ::get_cap($remote, 'disk_quota'); + my $diskusage = sprintf("%0.2f", LJ::Blob::get_disk_usage($remote, 'phonepost') / 1024**2); + return "Status". + "Disk Space:". + "You are currently using $diskusage MB out of $diskmax MB". + "Phone Posts:You have made $phoneusage posts out of $phonemax standout?>"; + } else { + return "Purchase a paid account to start using Post by Phone standout?>"; + } +} +_code?> + +
    +
    +
    Manage your authorized phone number and post by phone identification number
    + +
    File Manager
    +
    Manage your available disk space & phone posts
    + +
    Audio encodings
    +
    The different audio formats we support for your posts
    +
    +<=body +page?> diff --git a/ljcom/htdocs/phonepost/numbers.bml b/ljcom/htdocs/phonepost/numbers.bml new file mode 100644 index 0000000..94b4c11 --- /dev/null +++ b/ljcom/htdocs/phonepost/numbers.bml @@ -0,0 +1,90 @@ +Post by Phone Access Numbers +body<= + 0) { + if ($remote) { + $ret .= "Post by Phone service, ". + "so only the area code and city of each number is displayed. If you'd like to make ". + "posts to your journal through your phone, see the Paid Accounts ". + "page for information on purchasing a paid account. p?>"; + } else { + $ret .= "Post by Phone number. Paid Accounts can ". + "log in to see the complete set of phone numbers. p?>"; + } + } else { + $ret .= "Post by Phone interface can be reached by calling any of the following numbers: p?>"; + } + + my $nums = LJ::MemCache::get("phonepost_nums"); + unless ($nums) { + my %sname; + LJ::load_codes({ "state" => \%sname }); + $nums = {}; # state code -> [ [number, city]* ] + open (NUM, "$ENV{LJHOME}/other_sites/phonepost/numbers.csv"); + while () { + next unless /^(\w\w+)\s*,\s*(\d\d\d\-\d\d\d)\s*[,\-]\s*(\d\d\d\d)\s*\,\s*(.+?)\s*\n/; + my ($state, $exch, $number, $city) = ($1, $2, $3, $4); + if ($city eq uc($city)) { + $city = lc($city); + $city =~ s/\b(\w)/\u$1/g; + } + my $sname = $sname{$state} || $state; + $city =~ s/\s*Zone.+//; + $nums->{$sname} ||= []; + push @{$nums->{$sname}}, [ "$exch-$number", $city ]; + } + foreach my $st (keys %$nums) { + $nums->{$st} = [ sort { lc($a->[1]) cmp lc($b->[1]) } @{$nums->{$st}} ]; + } + LJ::MemCache::set("phonepost_nums", $nums, 60*5); + } + + my $tot = 0; + $tot += scalar(@{$nums->{$_}}) foreach (keys %$nums); + + $ret .= "Jump to: " . join(" | ", map { + "$_" } sort { lc($a) cmp lc($b) } keys %$nums); + + + my $shown = 0; + my $col = 1; + $ret .= "
    "; + $ret .= "Caution:
    Some local telephone companies charge for local calls that are outside of your selected calling plan."; + $ret .= "

    If you are not sure that an access number is within your calling plan, contact your local telephone company."; + $ret .= "

    You are responsible for all charges associated with calling this service.
    "; + + $ret .= " p?>"; + + $ret .= "
    "; + foreach my $sname (sort { lc($a) cmp lc($b) } keys %$nums) { + $ret .= "\n"; + foreach my $rec (@{$nums->{$sname}}) { + my $shownum = $rec->[0]; + $shownum =~ s/^(\d{3})[-\s.](\d{3})[-\s.](\d{4})/$1-xxx-xxxx/ unless $quota > 0; + $ret .= "$shownum: $rec->[1]
    \n"; + $shown++; + } + if ($col == 1 && $shown > ($tot / 2)) { + $col++; + $ret .= "
    "; + } + + } + $ret .= "
    "; + + $ret .= "" if $quota > 0; + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/phonepost/ogg.bml b/ljcom/htdocs/phonepost/ogg.bml new file mode 100644 index 0000000..d363a43 --- /dev/null +++ b/ljcom/htdocs/phonepost/ogg.bml @@ -0,0 +1,28 @@ +Ogg Vorbis +body<= + +Ogg Vorbis is an audio compression format, comparable to other formats like mp3, aac, wma, and ra. Ogg is different from others however, because it is an open specification, is free to use by any person or business, and is not encumbered by any patent. p?> +.ogg files because Ogg Vorbis is an open source project, an ideal we strongly believe in. p?> +.ogg files? h1?> +.ogg files, are available for a variety of media players on various operating systems, including: p?> +Windows h2?> + +MacOS / MacOS X h2?> + +Linux / BSD h2?> + +a list of instructions on achieving Ogg Vorbis playback in other media players. p?> +<=body +page?> diff --git a/ljcom/htdocs/phonepost/transcribe.bml b/ljcom/htdocs/phonepost/transcribe.bml new file mode 100644 index 0000000..485f62e --- /dev/null +++ b/ljcom/htdocs/phonepost/transcribe.bml @@ -0,0 +1,146 @@ +PhonePost transcription +body<= +{userid} == $u->{userid}; + + my $bid = $dppid >> 8; + my $ppe = LJ::PhonePost::get_phonepost_entry($u, $bid); + return "Invalid phone post entry." unless $ppe && $ppe->{jitemid} && $ppe->{anum} == $dppid % 256; + + # check security of item + my $logrow = LJ::get_log2_row($u, $ppe->{jitemid}); + return "Invalid phone post entry. (Phone post exists, entry has been deleted.)" unless $logrow; + unless ($logrow->{security} eq "public") { + my $remote = LJ::get_remote(); + return "Access denied." unless LJ::can_view($remote, $logrow); + } + + my $jlink = LJ::item_link($u, $logrow->{jitemid}, $logrow->{anum}); + my $may_trans = LJ::PhonePost::may_transcribe($u, $remote); + + return "Database unavailable." unless $u->writer; + + my @trans_log; + my $max_revid = 0; + my $sth = $u->prepare("SELECT revid,posterid,posttime,subject,body " . + "FROM phoneposttrans WHERE journalid=? AND blobid=?"); + $sth->execute($u->{userid}, $bid); + while (my $r = $sth->fetchrow_hashref) { + push @trans_log, $r; + + # Once the owner has transcribed, no one else is allowed to. + $may_trans = 0 if $r->{posterid} == $u->{userid} && !$is_owner; + + # Everyone but the owner can only transcribe once. + $may_trans = 0 if $remote && + $remote->{userid} != $u->{userid} && + $r->{posterid} == $remote->{userid}; + $max_revid = $r->{revid} > $max_revid ? $r->{revid} : $max_revid; + } + @trans_log = sort { $b->{revid} <=> $a->{revid} } @trans_log; + + # The last revision 'slot' is reserved for the owner. + $may_trans = 0 if $max_revid >= $MAX_REVS - 1 && !$is_owner; + + # Save new revision. + my $midair; + if (LJ::did_post() && $may_trans) { + + # Sanity check the rev id, make sure someone isn't faking it. + my $revid = $POST{revid} + 0; + my $new_revid = $max_revid + 1; + return "Invalid revision ID." unless $revid >= 1 && $revid <= $new_revid && $revid <= $MAX_REVS; + return "Last revision reserved for owner." if $revid == $MAX_REVS && !$is_owner; + + my $body = LJ::trim($POST{body}); + my $subject = LJ::trim($POST{subj}); + return LJ::bad_input('Empty transcription') unless $body =~ /\S/; + return LJ::bad_input('Invalid encoding') unless LJ::is_utf8($body) && LJ::is_utf8($subject); + return LJ::bad_input('Subject too long.') if length($subject) > 200; + return LJ::bad_input('Body too long.') if length($body) > 4096; + + my $verb = 'INSERT'; + $verb = 'REPLACE' if $revid == $MAX_REVS && $is_owner; + my $rv = $u->do("$verb IGNORE INTO phoneposttrans SET " . + "revid=?, posterid=?, posttime=UNIX_TIMESTAMP(), subject=?, body=?, " . + "journalid=?, blobid=?", undef, + $new_revid, $remote->{userid}, $subject, + $body, $u->{userid}, $bid); + + # Duplicate revision numbers. Force user to review. + $midair = $new_revid unless $rv > 0; + + my $newr = { 'revid'=>$new_revid, 'posterid'=>$remote->{userid}, + 'subject'=>$subject, 'body'=>$body }; + + unless ($midair) { + # Add post to display. + unshift @trans_log, $newr; + $may_trans = 0 unless $is_owner; + + # Modify journal subject. + $u->do("UPDATE logtext2 SET subject=? WHERE journalid=? AND jitemid=?", undef, + LJ::ehtml("Phone Post: $subject"), $u->{userid}, $logrow->{jitemid}); + my $memkey = [ $u->{userid}, "logtext:$u->{clusterid}:$u->{userid}:$logrow->{jitemid}" ]; + LJ::MemCache::delete($memkey); + + # and delete the latest info + $memkey = [$u->{userid},"ppelt:$u->{userid}:$bid"]; + LJ::MemCache::delete($memkey); + $memkey = [$u->{userid},"ppetu:$u->{userid}:$bid"]; + LJ::MemCache::delete($memkey); + } + } + + + $ret .= "
    [<< Back to this entry from " . LJ::ljuser($u) . ']
    '; + # Purty icon + $ret .= '
    ' . LJ::PhonePost::make_link($remote, $u->{userid}, $bid, 'notrans') . '
    '; + + if ($midair) { + $ret .= ""; + $ret .= "
    "; + $ret .= "" . LJ::ehtml($POST{subj}) . '
    ' if $POST{subj}; + $ret .= LJ::ehtml($POST{body}) . '
    '; + } + + # Display form. + if ($may_trans) { + $ret .= "
    "; + $ret .= LJ::html_hidden('revid', $max_revid + 1); + $ret .= ""; + $ret .= "
    "; + $ret .= 'Subject:  ' . LJ::html_text({ name=>'subj', size=>50 }) . '
    '; + $ret .= LJ::html_textarea({ name=>'body', cols=>70, rows=>5 }) . '
    '; + $ret .= "
    '; + } + + # Display previous translations. + foreach my $r (@trans_log) { + $ret .= "$r->{revid} by " . LJ::ljuser(LJ::get_username($r->{posterid})) . ' h2?>'; + $ret .= "
    "; + $ret .= '' . LJ::ehtml($r->{subject}) . '
    ' if $r->{subject}; + my $body = LJ::ehtml($r->{body}); + $body =~ s/\n/
    /g; + $ret .= $body; + $ret .= "
    "; + } + + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/poll/goatvote.bml b/ljcom/htdocs/poll/goatvote.bml new file mode 100644 index 0000000..f858bbb --- /dev/null +++ b/ljcom/htdocs/poll/goatvote.bml @@ -0,0 +1,270 @@ +("This is the address to view information from a GoatVote poll. It doesn't seem like you got here in the normal way. You should go to the GoatVote poll you're interested in viewing and click the link to view the GoatVote results.") unless $pollid; + + my $dbr = LJ::get_db_reader(); + my $po = $dbr->selectrow_hashref("SELECT * FROM poll WHERE pollid=?", undef, $pollid); + return $err->('Poll not found.') unless $po; + + # verify they can be here + my ($can_vote, $can_view) = LJ::Poll::find_security($po, $remote); + return $err->('You don\'t have access to view these poll results.') + unless $can_view; + + my $u = LJ::load_userid($po->{journalid}); + my $jarg = $u->{clusterid} ? "journal=$u->{user}&" : ""; + + # temporary: verify the author of the poll is allowed to post GoatVote polls + return $err->('The poll you have specified is not a GoatVote poll.') + unless LJ::check_priv($u, 'siteadmin', 'goatvote'); + + # load the item being shown to verify the post is still around + my $log = LJ::get_log2_row($u, $po->{itemid} >> 8); + $log->{ownerid} = $log->{journalid}; + return $err->('Owning post deleted, so poll is no longer accessible.') unless $log; + + # verify that the user can see this poll + return $err->('Sorry, you\'re not permitted to see this poll.') + unless LJ::can_view($remote, $log); + + # at this point we need to gather the data we need to compute things... + my @qs; + my $sth = $dbr->prepare("SELECT pollqid, type FROM pollquestion WHERE pollid=?"); + $sth->execute($pollid); + push @qs, $_ while $_ = $sth->fetchrow_hashref; + @qs = sort { $a->{pollqid} <=> $b->{pollqid} } @qs; + + # make sure it IS a goatvote poll + return $err->('This poll is not a GoatVote poll.') + unless LJ::LJcom::is_goatvote_poll($po, \@qs); + + # put in a link to go discuss the goatvote results + $body .= "{jitemid}, $log->{anum}) . "'>discussion. p?>"; + $body .= "Disclaimer: GoatVotes are for the gathering of opinions on the issues. This isn't technically voting, but it's close enough. p?>"; + + # this might be useful for some kinds of polls, but not usually + my $filter = 0; + if (LJ::check_priv($remote, 'siteadmin', 'goatvote')) { + # get filter + $filter = $FORM{filter}+0; + + # now put in demographic links + $body .= "all, " : 'all, '; + $body .= $filter ? 'paid users' : "paid users"; + $body .= ". p?>
    "; + } + + # now we need to pitch out anything that's not a text input or our first radio so as + # not to confuse us later in the process + my $i = @qs; + while ($i > 1) { + # shame you can't do postfix notation on a line with postfix notation... + delete $qs[$i] if + $qs[--$i]->{type} ne 'text'; + } + + # get all of the choices for these questions + my $ids = join(',', map { $_->{pollqid}+0 } @qs); + my $sql = "SELECT pollqid, userid, value FROM pollresult WHERE pollid=? AND pollqid IN ($ids)"; + my $choices = $dbr->selectall_arrayref($sql, undef, $pollid); + return $err->($dbr->errstr) if $dbr->err; + + # get all of the poll submission times...but only for the past day + my $sql = 'SELECT userid, datesubmit FROM pollsubmission '. + 'WHERE pollid=? AND datesubmit > DATE_SUB(NOW(), INTERVAL 1 DAY)'; + my $times = $dbr->selectall_arrayref($sql, undef, $pollid); + return $err->($dbr->errstr) if $dbr->err; + my %submits = (submittime => {}, urls => {}); + $submits{submittime}{$_->[0]} = $_->[1] foreach (@$times); # assemble, my minion hashrefs! + + # now calculate the choices that users made + my @urls; + my %voters; + my %votecount; + my $rqid = $qs[0]->{pollqid}; + foreach my $choice (@$choices) { + my ($cqid, $userid, $val) = @$choice; + if ($cqid == $rqid) { + # radio, so count a vote towards one item + $voters{$userid} = $val+0; + $votecount{$val+0}++; + } else { + # url, push for later parsing once we know who voted for what + push @urls, [ $userid+0, $val ]; + } + } + + # now we need to load all the users + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } keys %voters ]); + + # if we're viewing only data from one demographic of user, then we want to + # delete anybody who doesn't fit into that mold ... demographics are either + # all people or paid users (paid+permanent) + if ($filter) { + foreach my $uid (keys %users) { + next unless $voters{$uid}; + next if ($users{$uid}{caps}+0) & (1 << 3 | 1 << 4); + $votecount{$voters{$uid}}--; # retract their vote + delete $voters{$uid}; + } + } + + # sub to fix our URLs + my $fix_url = sub { + # throw out anything that isn't a URL, then escape any HTML and trim any + # spaces around the edges + my $url = shift; + return unless $url =~ m!^https?://[^\s\'\"\<\>]+[a-zA-Z0-9_/&=\-]$!; + return LJ::ehtml(LJ::trim($url)); + }; + + # let's take a moment to do some quick explaining of the hashes we're using + # in various spots in this file, above and below. + # + # %voters{ $userid } = $pollitid; # from pollitem -- what the user has voted for + # + # %votecount{ $val } = #; number of votes for $val, another pollitid + # + # %votes{ + # $val => { -- again, $val is pollitid + # urls => { + # $url => #; the number of votes for $url + # }, + # text => string; the text of the item $val + # } + # } + # + # %recent_votes is the same as %votes, just only includes information that + # is from the past 24 hours. + # + # %submits{ + # byurl => { + # $url => { + # $userid => 1; says $userid referenced $url at least once, this is used to + # track duplicate URLs, which are ignored + # } + # }, + # urls => { + # $userid => []; array containing all the URLs that $userid has referenced + # }, + # submittime => { + # $userid => string; string representing the date the user submitted (but only if + # the user has submitted in the last 24 hours) + # } + # } + + # now we go back through the urls and stack those up in all of our hashes + my %votes; + my %recent_votes; + foreach my $url (@urls) { + my $val = $voters{$url->[0]}; + next unless $val; # they might provide a URL and not actually vote above... rejected! + + # can't vote up the same URL twice + my $fixed = $fix_url->($url->[1]); + next unless $fixed; + next if $submits{byurl}{$fixed}{$url->[0]}; + + # increment the vote + $votes{$val}{urls}{$fixed}++; + + # was it recent? + $recent_votes{$val}{urls}{$fixed}++ if $submits{submittime}{$url->[0]}; + + # now we list the URL that this person voted for with their time voted + $submits{byurl}{$fixed}{$url->[0]} = 1; + push @{$submits{urls}{$url->[0]}}, $fixed; + } + + # now we can get all of these items + my $items = $dbr->selectall_arrayref('SELECT item, pollitid FROM pollitem '. + 'WHERE pollid=? AND pollqid=?', undef, $pollid, $rqid); + return $err->($dbr->errstr) if $dbr->err; + foreach my $item (@$items) { + $votes{$item->[1]}{text} = $item->[0]; + } + + # print out the data + foreach my $val (sort keys %votes) { + my $count = $votecount{$val}+0; + my $s = $count == 1 ? '' : 's'; + $body .= '' if $val > 1; + $body .= "\n"; + + # maybe nobody's voted for it + unless ($votes{$val}{urls}) { + $body .= "No votes for this choice."; + next; + } + + # most popular, total + $body .= "Most Popular (Total)
      \n"; + my $count = 0; + foreach my $url (sort { $votes{$val}{urls}{$b} <=> $votes{$val}{urls}{$a} } + keys %{$votes{$val}{urls}}) { + last if ++$count > $limit; + my $s = $votes{$val}{urls}{$url} == 1 ? '' : 's'; + my $link = LJ::auto_linkify($url); + $body .= "
    1. $link (" . $votes{$val}{urls}{$url} . " mention$s)
    2. \n"; + } + $body .= "
    \n"; + + # most popular, recent + $body .= "Most Popular (Last 24 Hours)
      \n"; + $count = 0; + foreach my $url (sort { $recent_votes{$val}{urls}{$b} <=> $recent_votes{$val}{urls}{$a} } + keys %{$recent_votes{$val}{urls}}) { + last if ++$count > $limit; + my $s = $votes{$val}{urls}{$url} == 1 ? '' : 's'; + my $link = LJ::auto_linkify($url); + $body .= "
    1. $link (" . $recent_votes{$val}{urls}{$url} . " mention$s)
    2. \n"; + } + $body .= "
    \n"; + + # most recent, period ... but only in the last 24 hours, as that's the only data + # we gathered into the submittime hash + $body .= "10 Most Recent Submissions (Last 24 Hours Only)
      \n"; + $count = 0; + foreach my $userid (sort { $submits{submittime}{$b} cmp $submits{submittime}{$a} } + grep { $voters{$_} == $val } # make sure they voted for THIS item ;) + keys %{$submits{submittime}}) { + # check if they had URLs + next unless @{$submits{urls}{$userid} || []}; + last if ++$count > $limit; + $body .= "
    1. "; + foreach my $url (@{$submits{urls}{$userid}}) { + my $link = LJ::auto_linkify($url); + $body .= "$link
      "; + } + $body .= "
    2. "; + } + $body .= "
    \n"; + } + + # whew... all done + return; +} +_code?> +body=> +page?> diff --git a/ljcom/htdocs/press/articles.bml b/ljcom/htdocs/press/articles.bml new file mode 100644 index 0000000..57405db --- /dev/null +++ b/ljcom/htdocs/press/articles.bml @@ -0,0 +1,24 @@ +LiveJournal in the Press +body<= + +. On this page we list the 5 latest +press mentions for your convenience. +p?> + + 'customview', 'styleid' => 137396 }); + $ret .= " "; + $ret .= LJ::make_journal("press", "", undef, { 'vhost' => 'customview', 'styleid' => 137833 }); + $ret .= " "./", text => "Back to the Press Area" }) . " p?>"; + return $ret; +} +_code?> +<=body +page?> diff --git a/ljcom/htdocs/press/index.bml b/ljcom/htdocs/press/index.bml new file mode 100644 index 0000000..f72f29b --- /dev/null +++ b/ljcom/htdocs/press/index.bml @@ -0,0 +1,30 @@ +LiveJournal Press Area +body<= + +
    + +
    2004 & 2001 People's Voice
    Award Winner
    +
    + + + + + + + +press@livejournal.com. +p?> +<=body +page?> diff --git a/ljcom/htdocs/press/staff.bml b/ljcom/htdocs/press/staff.bml new file mode 100644 index 0000000..e61f189 --- /dev/null +++ b/ljcom/htdocs/press/staff.bml @@ -0,0 +1,169 @@ + + + + + %%position%% +

    + %%fullname%%
    + %%username%% +
    %%quip%% +

    + +<=employee + +<=localblocks +_info?> +body<= + p?> + +
  • Customer Service & Technical Support
  • +
  • Terms of Service Violations
  • +
  • Press Information
  • +
  • Feedback & Suggestions
  • + +standout?> + + + + + + +Brad Fitzpatrick +username=> +userpic=>http://userpic.livejournal.com/2101580/2 +position=> +quip=> +employee?> + +Anatoly Vorobey +username=> +userpic=>http://userpic.livejournal.com/1510131/111931 +position=> +employee?> + + + +Mark Smith +username=> +userpic=>http://userpic.livejournal.com/10630385/1767539 +position=> +employee?> + +Mahlon Smith +username=> +userpic=>http://userpic.livejournal.com/8297438/1388180 +position=> +quip=> +employee?> + + + +Brad Whitaker +username=> +userpic=>http://userpic.livejournal.com/28673/15 +position=> +quip=> +employee?> + +David Recordon +username=> +userpic=>http://userpic.livejournal.com/19057448/1356357 +position=> +employee?> + + + + + + + +Lisa Phillips +username=> +userpic=>http://userpic.livejournal.com/23389645/17750 +position=> +employee?> + +Matthew Wilson +username=> +userpic=>http://www.livejournal.com/userpic/11102420/1494231 +position=> +employee?> + + + + + + +Denise Paolucci +username=> +userpic=>http://userpic.livejournal.com/3338120/819197 +position=> +quip=> +employee?> + +Jesse Proulx +username=> +userpic=>http://userpic.livejournal.com/2576480/472111 +position=> +quip=> +employee?> + + +Mark Ferrell +username=> +userpic=>http://userpic.livejournal.com/7008939/1314111 +position=> +employee?> + +Frank the Goat +username=> +userpic=>http://stat.livejournal.com/img/goat.gif +position=>Mascot +employee?> + + + + + + + +Ryan Fitzpatrick +username=> +userpic=>http://userpic.livejournal.com/9660051/21 +position=> +employee?> + +Sandy Fitzpatrick +username=> +userpic=>http://userpic.livejournal.com/3522/4652 +position=> +employee?> + +
    h2?>
    h2?>
    h2?>
    h2?>
    + + '/press/', text => $ML{'.back2'} }); _code?> p?> + +<=body +page?> diff --git a/ljcom/htdocs/rename/buy.bml b/ljcom/htdocs/rename/buy.bml new file mode 100644 index 0000000..26c007e --- /dev/null +++ b/ljcom/htdocs/rename/buy.bml @@ -0,0 +1,5 @@ + diff --git a/ljcom/htdocs/rename/index.bml b/ljcom/htdocs/rename/index.bml new file mode 100644 index 0000000..158f01f --- /dev/null +++ b/ljcom/htdocs/rename/index.bml @@ -0,0 +1,38 @@ + +body<= + + h1?> + '$15 USD'}); + _code?> +p?> + + h1?> + p?> + p?> + p?> + "href='$LJ::HELPURL{renaming}'"}) . " p?>" + : "") +_code?> + + h1?> + p?> + p?> + +|/pay/?item=rename| choice?> +<=items +itemsb<= +|use.bml| choice?> +<=itemsb +choices?> + + +<=body +page?> + diff --git a/ljcom/htdocs/rename/use.bml b/ljcom/htdocs/rename/use.bml new file mode 100644 index 0000000..212d9b1 --- /dev/null +++ b/ljcom/htdocs/rename/use.bml @@ -0,0 +1,365 @@ + +body<= + + 'href="/login.bml?ret=1"'})) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + return "" + unless $u->{'journaltype'} =~ /[PCS]/; + + my %err; + + my ($ren, $newuser); + + my $ret = ''; + + # authas switcher form + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "
    \n\n"; + + $ret .= BML::ml('.intent', {'aopts0' => 'href="./"', 'aopts1' => 'href="/pay/?item=rename"'}); + + my $err = sub { + my $area = shift; + return unless defined $err{$area}; + $ret .= "
    $err{$area}"; + }; + + my $form = sub { + $ret .= "
    "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}); + + $ret .= "

    $ML{'.label.username'} $u->{'user'}"; + $err->("user"); + + $ret .= "

    "; + $ret .= LJ::html_text({ 'name' => 'newuser', + 'value' => $FORM{'newuser'}, + 'size' => 18, 'maxlength' => 15, + 'raw' => 'id="newuser"' }); + $err->("newuser"); + + $ret .= "

    "; + $ret .= LJ::html_text({ 'name' => 'token', + 'value' => $FORM{'token'}, + 'size' => 18, 'maxlength' => 16, + 'raw' => 'id="token"' }); + $err->("token"); + + # these options don't apply to communities + if ($u->{journaltype} eq 'P') { + $ret .= "

    $ML{'.options'}

    "; + $ret .= "

    "; + $ret .= LJ::html_check({ 'name' => 'opt_delfriends', + 'type' => 'radio', + 'selected' => $FORM{'opt_delfriends'}, + 'value' => '1', + 'raw' => 'id="del_yes"' }); + $ret .= "
    "; + $ret .= LJ::html_check({ 'name' => 'opt_delfriends', + 'type' => 'radio', + 'selected' => ! LJ::did_post() || ! $FORM{'opt_delfriends'}, + 'value' => '0', + 'raw' => 'id="del_no"' }); + $ret .= " "; + + $ret .= "

    "; + $ret .= LJ::html_check({ 'name' => 'opt_delfriendofs', + 'type' => 'radio', + 'selected' => $FORM{'opt_delfriendofs'}, + 'value' => '1', + 'raw' => 'id="rem_no"' }); + $ret .= "
    "; + $ret .= LJ::html_check({ 'name' => 'opt_delfriendofs', + 'type' => 'radio', + 'selected' => ! LJ::did_post() || ! $FORM{'opt_delfriendofs'}, + 'value' => '0', + 'raw' => 'id="rem_yes"' }); + $ret .= " "; + + $ret .= "

    "; + $ret .= LJ::html_check({ 'name' => 'opt_redir', + 'type' => 'radio', + 'selected' => LJ::did_post() && ! $FORM{'opt_redir'}, + 'value' => '0', + 'raw' => 'id="keep_no"' }); + $ret .= "
    "; + $ret .= LJ::html_check({ 'name' => 'opt_redir', + 'type' => 'radio', + 'selected' => ! LJ::did_post() || $FORM{'opt_redir'}, + 'value' => '1', + 'raw' => 'id="keep_yes"' }); + $ret .= "
    "; + } + + $ret .= "

    " . LJ::html_submit($ML{'.label.proceed'}) . "

    "; + + $ret .= "

    "; + + $ret .= "
    "; + return $ret; + }; + + return $form->() unless LJ::did_post(); + + my $dbh = LJ::get_db_writer(); + + unless ($FORM{'userid'} == $u->{'userid'}) { + $err{'user'} = $ML{'.error.differentusername'}; + } + $newuser = LJ::canonical_username($FORM{'newuser'}); + if (! $newuser) { + $err{'newuser'} = $ML{'.error.username'}; + } elsif ($newuser eq $u->{'user'}) { + $err{'newuser'} = $ML{'.error.same'}; + } + $ren; + if ($FORM{'token'} =~ /^([0-9a-f]{6,6})(\w{10,10})$/) { + $ren = $dbh->selectrow_hashref("SELECT * FROM renames WHERE renid=? AND token=?", + undef, hex $1, $2); + if (! $ren) { + $err{'token'} = $ML{'.error.token'}; + } elsif ($ren->{'rendate'}) { + if ($ren->{'fromuser'} eq $u->{'user'} && + $ren->{'touser'} eq $newuser) { + return $ML{'.success.usernamerenamed'}; + } else { + $err{'token'} = $ML{'.error.usedtoken'}; + } + } + } else { + $err{'token'} = $ML{'.error.token'}; + } + return $form->() if %err; + + my $tou = LJ::load_user($newuser); + my $move_away = 0; + my $exname = undef; + if ($tou) { + # decide if we can move away the existing destination username + + if ($tou->{'statusvis'} eq "X") { + # expunged usernames can be moved away. they're already deleted. + $move_away = 1; + } elsif (lc($tou->{'email'}) eq lc($u->{'email'}) && + $tou->{'statusvis'} eq "V" && + $tou->{'journaltype'} eq "P") { + if ($tou->{'password'} eq $u->{'password'}) { + if ($tou->{'status'} ne 'A' || $u->{'status'} ne 'A') { + $err{'newuser'} = $ML{'.error.notvalidated'}; + } else { + $move_away = 1; + } + } else { + $err{'newuser'} = $ML{'.error.badpass'}; + } + } else { + $err{'newuser'} = $ML{'.error.usernametaken'}; + } + + # if we will be moving the destination username away, + # we need to allocate a name for it + if ($move_away) { + my $tempname = $tou->{'user'}; + $tempname = substr($tempname, 0, 9) if length($tempname) > 9; + for (1..10) { + + # if it exists, first try the exname found on the + # previous (confirmation) page + if ($_ == 1 && $FORM{'exname'}) { + $exname = $FORM{'exname'}; + + # otherwise we either didn't have one or it's been + # taken in the meantime? + } else { + $exname = "ex_$tempname" . int(rand(999)); + } + + # check to see if this exname already exists + unless ($dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE user=?", + undef, $exname)) { + # name doesn't already exist, use this one + last; + } + # name existed, try and get another + + if ($_ >= 10) { + return $ML{'.error.allocating'}; + } + } + } + } + return $form->() if %err; + + my $confirm = sub { + $ret .= "
    "; + + # carry on submitted data in hidden elements + $ret .= LJ::html_hidden("userid" => $u->{'userid'}, + "exname" => $exname, + map { $_, $FORM{$_} } + qw(newuser token opt_delfriends opt_delfriendofs + opt_redir)); + + $ret .= ""; + $ret .= "
      "; + $ret .= "
    • " . BML::ml('.changes.move', {'newuser' => $newuser, 'exname' => $exname}) . "
    • " + if $move_away; + $ret .= "
    • " . BML::ml('.changes.rename', {'newuser' => $newuser, 'oldname' => $u->{'user'}}) . "
    • "; + $ret .= "
    "; + + $ret .= ""; + $ret .= " 'YES'}) . "
    "; + $ret .= LJ::html_text({ 'name' => 'yes', 'size' => 10, 'maxlength' => 3 }); + $err->("yes"); + $ret .= "
    $ML{'.confirm.click'} p?>"; + + $ret .= "

    " . LJ::html_submit($ML{'.label.rename'}) . "

    "; + $ret .= "
    "; + return $ret; + }; + + # display confirmation page if "form" is okay and no confirmation sent + return $confirm->() if LJ::did_post && ! exists $FORM{'yes'}; + + # error check confirmation + unless ($FORM{'yes'} eq "YES") { + $err{'yes'} = $ML{'.error.readit'}; + } + return $confirm->() if %err; + + my $do_rename = sub { + my ($from, $to) = map { LJ::canonical_username($_) } @_; + return 0 unless $from ne "" && $to ne ""; + my $u = LJ::load_user($from); + return 0 unless $u; + foreach my $table (qw(user useridmap overrides style)) + { + $dbh->do("UPDATE $table SET user=? WHERE user=?", + undef, $to, $from); + return 0 if $dbh->err; + } + + LJ::memcache_kill($u, "userid"); + LJ::MemCache::delete("uidof:$from"); + LJ::MemCache::delete("uidof:$to"); + + LJ::infohistory_add($u, 'username', $from); + + # tell all web machines to clear their caches for this userid/name mapping + LJ::procnotify_add("rename_user", { 'userid' => $u->{'userid'}, + 'user' => $u->{'user'} }); + return 1; + }; + + if ($tou && $move_away) { + # time to move this one out of the way we already + # have a valid $exname from above + unless ($exname && $do_rename->($tou->{'user'}, $exname) && + $dbh->do("INSERT INTO renames (token, payid, userid, fromuser, touser, rendate) " . + "VALUES (?,?,?,?,?,NOW())", + undef, "[moveaway]", 0, $tou->{'userid'}, $tou->{'user'}, $exname)) + { + return $ML{'.error.reserved'}; + } + } + + unless ($do_rename->($u->{'user'}, $newuser)) { + return $ML{'.error.unknown'}; + } + + $dbh->do("UPDATE renames SET userid=?, fromuser=?, touser=?, rendate=NOW() WHERE renid=?", + undef, $u->{'userid'}, $u->{'user'}, $newuser, $ren->{'renid'}); + + if ($u->{journaltype} eq 'P') { + if ($FORM{'opt_delfriends'}) { + # delete friends + my $friends = LJ::get_friends($u, undef, undef, 'force') || {}; + LJ::remove_friend($u, [ keys %$friends ]); + + # delete access to post to communities + LJ::clear_rel('*', $u, 'P'); + + # delete friend-ofs that are communities + # TAG:fr:bml_rename_use:get_member_of + my $users = $dbh->selectcol_arrayref(qq{ + SELECT u.userid FROM friends f, user u + WHERE f.friendid=$u->{'userid'} AND + f.userid=u.userid and u.journaltype <> 'P' + }); + if ($users && @$users) { + my $in = join(',', @$users); + $dbh->do("DELETE FROM friends WHERE friendid=$u->{'userid'} AND userid IN ($in)"); + LJ::memcache_kill($_, "friends") foreach @$users; + } + } + + if ($FORM{'opt_delfriendofs'}) { + # delete people (only people) who list this user as a friend + my $users = $dbh->selectcol_arrayref(qq{ + SELECT u.userid FROM friends f, user u + WHERE f.friendid=$u->{'userid'} AND + f.userid=u.userid and u.journaltype = 'P' + }); + if ($users && @$users) { + my $in = join(',', @$users); + $dbh->do("DELETE FROM friends WHERE friendid=$u->{'userid'} AND userid IN ($in)"); + LJ::memcache_kill($_, "friends") foreach @$users; + } + } + + # delete friend of memcaching, as either path might have done it + LJ::MemCache::delete([ $u->{userid}, "friendofs:$u->{userid}" ]); + } + + my $id = LJ::create_account({ + 'user' => $u->{'user'}, + 'password' => '', + 'name' => '[renamed acct]', + }); + + my $alias_changed = $dbh->do("UPDATE email_aliases SET alias=? WHERE alias=?", + undef, "$newuser\@$LJ::USER_DOMAIN", + "$u->{'user'}\@$LJ::USER_DOMAIN"); + if ($u->{journaltype} ne 'P' || $FORM{'opt_redir'}) { + LJ::update_user($id, { raw => "journaltype='R', statusvis='R', statusvisdate=NOW()" }); + LJ::set_userprop($dbh, $id, "renamedto", $newuser); + if ($alias_changed > 0) { + $dbh->do("INSERT INTO email_aliases VALUES (?,?)", undef, + "$u->{'user'}\@$LJ::USER_DOMAIN", + $u->{'email'}); + } + } else { + LJ::update_user($id, { journaltype => $u->{journaltype}, raw => "statusvis='D', statusvisdate=NOW()" }); + } + + $u->kill_session; + + # overwrite $ret and give success page + $ret = "
      "; + $ret .= "
    • " . BML::ml('.success.moved', {'newuser' => $newuser, 'exname' => $exname}). "
    • " + if $move_away; + $ret .= "
    • " . BML::ml('.success.renamed', {'newuser' => $newuser, 'olduser' => $u->{'user'}}) . "
    • "; + $ret .= "
    "; + $ret .= " 'href="/login.bml"'}) . "p?>" + if $u->{userid} == $remote->{userid}; + return $ret; + +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/resources/homonyms.bml b/ljcom/htdocs/resources/homonyms.bml new file mode 100644 index 0000000..2a71d4f --- /dev/null +++ b/ljcom/htdocs/resources/homonyms.bml @@ -0,0 +1,11 @@ +Homonyms +body<= + +1 +file=>resources-homonyms +_include?> + +<=body +page?> \ No newline at end of file diff --git a/ljcom/htdocs/resources/index.bml b/ljcom/htdocs/resources/index.bml new file mode 100644 index 0000000..d808e86 --- /dev/null +++ b/ljcom/htdocs/resources/index.bml @@ -0,0 +1,13 @@ +Writing Resources +body<= + +resources-index +bml=>1 +_include?> + +<=body +page?> + + diff --git a/ljcom/htdocs/resources/whowhom.bml b/ljcom/htdocs/resources/whowhom.bml new file mode 100644 index 0000000..c289a2b --- /dev/null +++ b/ljcom/htdocs/resources/whowhom.bml @@ -0,0 +1,11 @@ +Who and Whom +body<= + +1 +file=>resources-whowhom +_include?> + +<=body +page?> diff --git a/ljcom/htdocs/singles/index.bml b/ljcom/htdocs/singles/index.bml new file mode 100644 index 0000000..1d4b1e8 --- /dev/null +++ b/ljcom/htdocs/singles/index.bml @@ -0,0 +1,34 @@ +LiveJournal Singles +body<= + + + + + +selectrow_array("SELECT statval FROM stats WHERE statcat='singles' AND statkey='total'")+0; +} _code?> single people looking for love! +standout?> + + +<=items +itemsb<= + +<=itemsb +choices?> + + + + +<=body +page?> diff --git a/ljcom/htdocs/singles/mod.bml b/ljcom/htdocs/singles/mod.bml new file mode 100644 index 0000000..c8d65e6 --- /dev/null +++ b/ljcom/htdocs/singles/mod.bml @@ -0,0 +1,129 @@ +Your Availability +body<= + + + + +login to proceed. p?>"; + } + + LJ::load_user_props($u, "single_status", "single_pickw", "city", "country", "state"); + + my %countries; + my %states; + LJ::load_codes({ "country" => \%countries, "state" => \%states }); + + my $ret; + + # save mode: + if (LJ::did_post()) + { + unless ($POST{'status'}) { + LJ::set_userprop($u, "single_status", ""); + return "Saved. You won't show up as available."; + } + + if ($POST{'country'} eq "US" && length($POST{'state'}) > 2) { + foreach (keys %states) { + $POST{'state'} = $_ + if (lc($states{$_}) eq $POST{'state'}); + } + } + + # clean/verify + $POST{'age'} += 0; + return "You need to provide an age." unless + $POST{'age'}; + return "Sorry, you're too young to use this service." unless + $POST{'age'} >= 18; + return $ML{'Error'} unless ($POST{'status'} =~ /^[MF][MF]$/); + + LJ::set_userprop($u, "single_status", + join("|", map { $POST{$_} } qw(status country state city age))); + LJ::set_userprop($u, "single_pickw", + $POST{'single_pickw'}); + + $ret .= "Saved. Now, go search for somebody!"; + return $ret; + } + + $ret .= "
    "; + + # edit mode: + my ($status, $country, $state, $city, $age) = split(/\|/, $u->{'single_status'}); + + my $dbr = LJ::get_db_reader(); + + $country ||= $u->{'country'}; + $state ||= $u->{'state'}; + $city ||= $u->{'city'}; + if (! $age && $u->{'bdate'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/ && $3) { + $age = int($dbr->selectrow_array("SELECT (unix_timestamp()-unix_timestamp('$u->{'bdate'}'))/(60*60*24*365)")); + $age = "" unless $age; + } + + + $ret .= " 'status', + 'selected' => $status, }, + "", "Not Available", + "MF", "Male; seeking female", + "FM", "Female; seeking male", + "MM", "Male; seeking male", + "FF", "Female; seeking female", + ); + $ret .= " p?>\n"; + + $ret .= ""; + + $ret .= "Country: "; + $ret .= LJ::html_select({ 'name' => 'country', + 'selected' => $country }, + '', '(Select Country)', + map { $_, $countries{$_} } + "US", sort { $countries{$a} cmp $countries{$b} } keys %countries); + $ret .= " p?>"; + my $estate = LJ::ehtml($state); + $ret .= "State: p?>\n"; + + my $ecity = LJ::ehtml($city); + $ret .= "City: p?>\n"; + + $ret .= " p?>\n"; + + # sexiest userpic + my $upinf = LJ::get_userpic_info($u); + my %keywords = ("" => "(Default Picture)", + map { $_ => $_ } keys %{$upinf->{kw}} ); + + $ret .= "userpic keyword do you want to try to seduce people with? p?>
    "; + $ret .= LJ::html_select({ 'name' => 'single_pickw', + 'selected' => $u->{'single_pickw'} }, + map { $_, $keywords{$_} } sort keys %keywords); + $ret .= "
    \n"; + + # done + $ret .= ":) p?>"; + $ret .= "

    "; + + $ret .= "
    "; + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/singles/search.bml b/ljcom/htdocs/singles/search.bml new file mode 100644 index 0000000..c66c907 --- /dev/null +++ b/ljcom/htdocs/singles/search.bml @@ -0,0 +1,216 @@ +Search Singles +body<= + + + + + \%countries, "state" => \%states }); + + # query page. + unless ($GET{'status'}) + { + my ($status, $country, $state, $city, $age); + if ($remote) { + LJ::load_user_props($remote, "single_status", "single_pickw", "city", "country", "state"); + ($status, $country, $state, $city, $age) = split(/\|/, $remote->{'single_status'}); + $country ||= $remote->{'country'}; + $state ||= $remote->{'state'}; + $city ||= $remote->{'city'}; + if (! $age && $remote->{'bdate'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/ && $3) { + $age = int($dbr->selectrow_array("SELECT (unix_timestamp()-unix_timestamp('$remote->{'bdate'}'))/(60*60*24*365)")); + $age = "" unless $age; + } + } + + $ret .= "
    "; + $ret .= " 'status', + 'selected' => $status, }, + "", "(Select Search Mode)", + "MF", "Male; seeking female", + "FM", "Female; seeking male", + "MM", "Male; seeking male", + "FF", "Female; seeking female", + ); + $ret .= "p?>"; + + $ret .= ""; + + $ret .= "Country: "; + $ret .= LJ::html_select({ 'name' => 'country', + 'selected' => $country }, + '', '(Select Country)', + map { $_, $countries{$_} } + "US", sort { $countries{$a} cmp $countries{$b} } keys %countries); + $ret .= " p?>"; + my $estate = LJ::ehtml($state); + $ret .= "State: p?>\n"; + + my $ecity = LJ::ehtml($city); + $ret .= "City: p?>\n"; + + $ret .= " and p?>\n"; + + # search results + $ret .= "
    "; + if (LJ::get_cap($remote, "paid")) { + $ret .= " Text "; + $ret .= " Pictures"; + } else { + $ret .= " Text "; + $ret .= " Pictures (paid users only)"; + } + + + $ret .= "
    "; + + # done + $ret .= ""; + $ret .= "

    "; + + $ret .= "
    "; + return $ret; + } + + # verify/clean search data. + if ($GET{'country'} eq "US" && length($GET{'state'}) > 2) { + foreach (keys %states) { + $GET{'state'} = $_ + if (lc($states{$_}) eq $GET{'state'}); + } + } + + return LJ::bad_input("Must enter min and max ages") + unless ($GET{'age1'} && $GET{'age2'}); + return LJ::bad_input("LiveJournal Singles is for users 18 years of age and older.") + unless ($GET{'age1'} >= 18 && $GET{'age2'} >= 18); + + my $revstatus = { + 'MF' => 'FM', + 'FM' => 'MF', + 'MM' => 'MM', + 'FF' => 'FF', + }->{$GET{'status'}}; + + my $prefix = join("|", $revstatus, map { $GET{$_} } qw(country state city)); + my $propid = $dbr->selectrow_array("SELECT upropid FROM userproplist WHERE name='single_status'"); + return "Missing db lookup info" unless $propid; + my $matches = $dbr->selectcol_arrayref("SELECT userid FROM userprop WHERE upropid=$propid ". + "AND value BETWEEN ? AND ? LIMIT 5000", undef, + "$prefix|$GET{'age1'}", "$prefix|$GET{'age2'}"); + unless ($matches && @$matches) { + return ""; + } + + my %page = BML::paging($matches, $GET{'page'}, 100); + $ret .= "

    << New Search"; + $ret .= "Page $page{'page'} of $page{'pages'} $page{'nextlink'} standout?>"; + + my @userids = @{$page{'items'}}; # who's on this page. + my $userid_in = join(",", @userids); + my %user; # info on those people + my $sth; + + # pics to load + my %userpic; + + # base info. + $sth = $dbr->prepare("SELECT * FROM user WHERE userid IN ($userid_in) AND statusvis = 'V'"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $user{$_->{'userid'}} = $_; + $userpic{$_->{'defaultpicid'}} = undef if $_->{'defaultpicid'}; + } + + unless (%user) { + return ""; + } + + # get ages of just this page + $sth = $dbr->prepare("SELECT userid, value FROM userprop WHERE upropid=$propid ". + "AND userid IN ($userid_in)"); + $sth->execute; + while (my ($id, $val) = $sth->fetchrow_array) { + next unless $val =~ /\|(\d+)$/; + next unless $user{$id}; + $user{$id}->{'age'} = $1; + } + + # preferred pictures? + $propid = $dbr->selectrow_array("SELECT upropid FROM userproplist WHERE name='single_pickw'"); + return "Missing db lookup info" unless $propid; + $sth = $dbr->prepare(qq{ + SELECT m.userid, m.picid FROM + userpicmap m, + userproplite u, + keywords k + WHERE + u.userid IN ($userid_in) AND upropid=$propid AND + u.value=k.keyword AND u.userid=m.userid AND m.kwid=k.kwid + }); + $sth->execute; + my @userpic_load; + while (my ($userid, $picid) = $sth->fetchrow_array) { + next unless $user{$userid}; + delete $userpic{$user{$userid}->{'defaultpicid'}}; + $user{$userid}->{'defaultpicid'} = $picid; + $userpic{$picid} = undef; + push @userpic_load, [ $user{$userid}, $picid ]; + } + + # load pictures + LJ::load_userpics(\%userpic, \@userpic_load); + + my $with_pics = $GET{'mode'} eq "pics" && LJ::get_cap($remote, "paid"); + if ($with_pics) { + $ret .= "\n"; + } else { + $ret .= "
      "; + } + + foreach my $userid (@userids) { + my $u = $user{$userid}; + next unless $u; + if ($with_pics) { + $ret .= "
    "; + } else { + $ret .= "
  • " . LJ::ljuser($u) . ", $u->{'age'} - " . LJ::ehtml($u->{'name'}) . ""; + } + } + + if ($with_pics) { + $ret .= "
  • "; + if ($u->{'defaultpicid'}) { + my $id = $u->{'defaultpicid'}; + $ret .= ""; + } + $ret .= "" . LJ::ljuser($u) . ", $u->{'age'} - " . LJ::ehtml($u->{'name'}) . "
    \n"; + } else { + $ret .= ""; + } + + return $ret; + +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/site/about.bml b/ljcom/htdocs/site/about.bml new file mode 100644 index 0000000..629973e --- /dev/null +++ b/ljcom/htdocs/site/about.bml @@ -0,0 +1,150 @@ +About LiveJournal +head<= + +<=head +body<= + + +Features by Account Type comparison chart. p?> + + +
    +
      +
    • Your Journal +
        +
      • Entries can include: +
          +
        • The basics: subject, text, and date. +
        • Small pictures used to represent you.
        • +
        • Current mood + text/icon and your current music.
        • +
        • Polls that automatically tabulate votes.
        • +
        +
      • +
      • Per-entry security lets you restrict entries to just yourself or groups + of your friends.
      • +
      • Comments on each entry support paging and threading (comments replying to other comments).
      • +
      • A user profile includes: +
          +
        • A mini-biography. +
        • A list of your interests, another way to + find other users.
        • +
        • A link to our text message gateway that won't reveal your cell phone number.
        • +
        • Who you've befriended, who's befriended you.
        • +
        • What communities you read and participate in.
        • +
        +
      • +
      • Fully integrated photo storage with basic image and photo editing.
      • +
      +
    • +
    • Privacy +
        +
      • You control: +
          +
        • Who can see each individual entry.
        • +
        • Who can see your contact information.
        • +
        • Who can text message you.
        • +
        • Who can leave comments, and whose comments are screened pending your approval.
        • +
        • Who can participate in individual polls.
        • +
        +
      • +
      • Ban other users from your journal or community.
      • +
      +
    • +
    • Customization +
        +
      • Easily modify the look of your journal, using either a template-based + style system or a higher-level customization wizard.
      • +
      • For more control, program your own style with the S2 + programming language.
      • +
      • Embed your + journal into your own web page.
      • +
      +
    • +
    +
    + +
      +
    • Friends +
        +
      • A built-in aggregator (called the "friends view") shows all of + your friends' entries in one page.
      • +
      • Friend groups let you classify + people for both filtering and security.
      • +
      • Syndication lets you read offsite news sources (RSS) + just like they were other users.
      • +
      +
    • +
    • Software +
        +
      • Client programs (for Windows, MacOS, Linux, and more) let you update + journals without opening a web browser.
      • +
      +
    • +
    • Social Networking + +
    • +
    • Interoperability +
        +
      • The RSS + feed of every journal lets other sites/tools aggregate your content.
      • +
      • Full Unicode support allows you to write in any language.
      • +
      • Our site is available in many languages. +
      +
    • +
    • Open Process + +
    • +
    +
    + +let us know! p?> + + +frequently asked questions (and answers!) about LiveJournal can be found on our FAQ page. p?> + +<=body +page?> +link: htdocs/site/contributors.bml, htdocs/support/submit.bml +link: htdocs/paidaccounts/index.bml + +_c?> diff --git a/ljcom/htdocs/site/banners.bml b/ljcom/htdocs/site/banners.bml new file mode 100644 index 0000000..09cd182 --- /dev/null +++ b/ljcom/htdocs/site/banners.bml @@ -0,0 +1,250 @@ +LiveJournal Banners + +body<= + + + + + + + + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner1.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner2.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner3.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner4.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner5.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner6.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner7.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner8.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner9.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner_metal.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/LJbanner_pastel.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + +

    +
    +Check out LiveJournal.com! It's Free! +
    + + +<CENTER> +<A HREF="http://www.livejournal.com/"><IMG +SRC="http://www.livejournal.com/img/banners/firebindy1.gif" + WIDTH=468 HEIGHT=60 BORDER=0></A><BR> +<A HREF="http://www.livejournal.com">Check out +LiveJournal.com! It's Free!</A> +</CENTER> + +

    + + + + +<=body +page?> diff --git a/ljcom/htdocs/site/contract.bml b/ljcom/htdocs/site/contract.bml new file mode 100644 index 0000000..f5ff4ae --- /dev/null +++ b/ljcom/htdocs/site/contract.bml @@ -0,0 +1,40 @@ + +head<= + +<=head +body<= + + h1?> + p?> + h1?> +

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +<=body +page?> diff --git a/ljcom/htdocs/site/contributors.bml b/ljcom/htdocs/site/contributors.bml new file mode 100644 index 0000000..001dc47 --- /dev/null +++ b/ljcom/htdocs/site/contributors.bml @@ -0,0 +1,436 @@ + 'Code/Programming', + 'doc' => 'Documentation', + 'creative' => 'Creative (Styles/Art/Presentation)', + 'biz' => 'Business Issues & Leadership', + 'other' => 'Other'); + my @cats = qw(code doc creative biz other); + + my $user = LJ::canonical_username($FORM{'user'}); + if (!$mode && $user) { $mode = "user"; } + if (!$mode && $FORM{'cat'}) { $mode = "cat"; } + + my $table = sub { + my ($list, $title, $des) = @_; + $body .= "" if $title; + $body .= "" if $des; + $body .= "

    "; + my $inccat = $list->[0]->{'cat'} ? "" : ""; + $body .= "$inccat\n"; + foreach my $it (@$list) { + my $item = LJ::eall($it->{'des'}); + if ($it->{'url'} =~ m!^https?://!) { + $item = "{'url'}\">$item"; + } + my $date = substr($it->{'dateadd'}, 0, 10); + my $user = $it->{'user'} ? LJ::ljuser($it->{'user'}) . ": " : ""; + my $cat = exists $it->{'cat'} ? "" : ""; + $body .= "$cat"; + } + $body .= "
    Category
    ItemDate
    $it->{'cat'}
    $user$item [{'coid'}\">detail]$date
    "; + }; + + if ($mode eq "") + { + $title = "Contributors"; + $body = "senior staff who oversee all operations. p?>". + ""; + + $body .= ""; + $body .= "

  • Category:
      "; + foreach my $cat (@cats) { + $body .= "
    • $cats{$cat}
    • \n"; + } + $body .= "
  • "; + + $body .= "
  • Last 60 Days
  • "; + + $body .= "
  • By user
      "; + $body .= "
      Enter username:
  • "; + + $body .= " p?>"; + + $body .= "add yourself. p?>"; + + return; + } + + if ($mode eq "user") + { + my $u = LJ::load_user($user); + unless ($u) { + $title = "Error"; + $body = "Invalid username."; + return; + } + + $title = "Contributions from $user"; + $body .= "

    [<< Back]

    "; + + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT coid, cat, des, url, dateadd, acks ". + "FROM contributed WHERE userid=?"); + $sth->execute($u->{'userid'}); + my (@ack, @unack); + while ($_ = $sth->fetchrow_hashref) { + push @ack, $_ if $_->{'acks'}; + push @unack, $_ unless $_->{'acks'}; + } + + unless (@ack || @unack) { + $body .= " has not declared any contributions."; + } + + $table->(\@ack, "Acknowledged Contributions", + "These contributions have been acknowledged by others in the community:") if @ack; + $table->(\@unack, "Unacknowledged Contributions", + "These contributions have been declared, but not yet acknowledged by anyone:") if @unack; + + return; + } + + if ($mode eq "recent") + { + $title = "Recent Contributions"; + + $body .= "

    [<< Back]

    "; + + my $extra = $FORM{'unack'} ? "" : "AND c.acks > 0"; + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT u.user, c.coid, c.cat, c.des, c.url, c.dateadd, c.acks ". + "FROM contributed c, useridmap u ". + "WHERE u.userid=c.userid ". + "AND c.dateadd > DATE_SUB(NOW(), INTERVAL 60 DAY) $extra ". + "ORDER BY c.dateadd DESC"); + $sth->execute(); + my (@ack, @unack); + while ($_ = $sth->fetchrow_hashref) { + push @ack, $_ if $_->{'acks'}; + push @unack, $_ unless $_->{'acks'}; + } + + unless (@ack || @unack) { + $body .= "No contributions filed in last 60 days."; + } + + $table->(\@ack, "Acknowledged Contributions", + "These recent contributions have been acknowledged by others in the community:") if @ack; + $table->(\@unack, "Unacknowledged Contributions", + "These recent contributions have been declared, but not yet acknowledged by anyone:") if @unack; + + return; + } + + if ($mode eq "cat") + { + my $cat = $FORM{'cat'}; + $body .= "

    [<< Back]

    "; + + unless ($cats{$cat}) { + $body .= "Invalid category"; + return; + } + + $title = $cats{$cat}; + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT u.user, c.coid, c.des, c.url, c.dateadd ". + "FROM contributed c, useridmap u ". + "WHERE u.userid=c.userid ". + "AND c.cat=? AND c.acks>0 ". + "ORDER BY c.dateadd"); + $sth->execute($cat); + my (@con); + while ($_ = $sth->fetchrow_hashref) { + push @con, $_; + } + + unless (@con) { + $body .= "No contributions in this category"; + return; + } + + $table->(\@con); + + $body .= "

    [<< Back]

    "; + return; + } + + + + if ($mode eq "delete") + { + my $coid = $FORM{'coid'}+0; + + unless ($remote) { + $title = "Delete Contribution - Error"; + $body .= "login. p?>"; + return; + } + + my $admin = LJ::check_priv($remote, "contrib_delete"); + unless ($admin) { + $title = "Delete Contribution - Error"; + $body .= ""; + return; + } + + unless ($coid) { + $title = "Delete Contribution - Error"; + $body .= ""; + return; + } + + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM contributed WHERE coid=$coid"); + $dbh->do("DELETE FROM contributedack WHERE coid=$coid"); + + $title = "Delete Contribution - Success"; + $body .= ""; + return; + } + + if ($mode eq "add") + { + $title = "Add Contribution(s)"; + + unless ($remote) { + $body .= "login. p?>"; + return; + } + $body .= "
    \n"; + $body .= "\n"; + for (my $i = 0; $i < 5; $i++) { + $body .= "

    "; + $body .= "\n"; + $body .= ""; + $body .= ""; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Add who?{'user'}\">
    Category:
    Description:
    Optional URL:

    "; + } + $body .= " standout?>\n"; + $body .= "
    "; + $body .= "Back to the contributions list."; + return; + } + + if ($mode eq "add_do") + { + $title = "Add Contribution"; + + unless ($remote) { + $body .= "login. p?>"; + return; + } + unless (LJ::did_post()) { + $body .= ""; + return; + } + for (my $i = 0; $i < 5; $i++) + { + my $des = $FORM{"des_${i}"}; + my $user = $FORM{"user_${i}"}; + my $cat = $FORM{"cat_${i}"}; + my $url = $FORM{"url_${i}"}; + + $des = LJ::trim($des); + next if $des eq ""; + + my $userid = LJ::get_userid($user); + unless ($userid) { + $body .= "
    $user - $des
    Can not find user $user
    "; + next; + } + + # must be ack'ed to add somebody other than yourself. + my $acks = 0; + if ($userid != $remote->{'userid'}) { + unless (LJ::Contrib::is_acked($remote->{'userid'})) { + $body .= "
    - $des
    You have to be an acknowledged contributor before you can add someone else.
    "; + next; + } + $acks = 1; + } + + my $dbh = LJ::get_db_writer(); + + $dbh->do("INSERT INTO contributed (userid, cat, des, url, dateadd, acks) VALUES ". + "($userid, ?, ?, ?, NOW(), $acks)", undef, $cat, $des, $url); + my $coid = $dbh->{'mysql_insertid'}; + if ($coid) { + if ($acks) { + $dbh->do("REPLACE INTO contributedack (coid, ackuserid) VALUES ($coid, $remote->{'userid'})"); + } + + $body .= "
    - " . LJ::ehtml($des) . "
    Added. You can view it here
    "; + } else { + $body .= "
    - " . LJ::ehtml($des) . "
    Error... not added.
    "; + } + } + $body .= ""; + $body .= "Back to the contributions list."; + return; + } + + if ($mode eq "detail") + { + $title = "Contribution Detail"; + my $coid = $FORM{'coid'}+0; + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT userid, cat, des, url, dateadd, acks FROM contributed WHERE coid=$coid"); + $sth->execute; + my $co = $sth->fetchrow_hashref; + + unless ($co) { + $body = "Contribution not found."; + return; + } + + my $admin = LJ::check_priv($remote, "contrib_delete"); + my $u = LJ::load_userid($co->{'userid'}); + my $url = $co->{'url'} ? "{'url'}\">$co->{'url'}" : "-"; + my $edes = LJ::ehtml($co->{'des'}); + + $body .= < +User:{'user'} ljuser?> - $u->{'name'} +Category:$cats{$co->{'cat'}} ({'user'}\">view all) +Description:$edes +URL:$url +Date Added:$co->{'dateadd'} +# Acks:$co->{'acks'} + + +TABLE + + $body .= ""; + $body .= ""; + + $sth = $dbr->prepare("SELECT u.user FROM contributedack c, useridmap u WHERE u.userid=c.ackuserid AND c.coid=$coid ORDER BY u.user"); + $sth->execute; + my $a_ct = 0; + while (my ($userack) = $sth->fetchrow_array) { + $body .= "
  • \n"; + $a_ct++; + } + unless ($a_ct) { + $body .= "(None)"; + } + $body .= ""; + + $body .= "A contribution isn't shown on the main page unless it's acknowledged by other contributors. To acknowledge this item, click the button below. Only acknowledge it if you know for a fact it was done and if you were related to the item. For instance, if you were a leader of a group and gave somebody the project, then you should acknowledge it. Another reason to acknowledge a contribution is if that contribution was very notable and you just want to give them props. Just don't acknowledge a contribution you weren't involved with and didn't even know about. p?>"; + + $body .= "
    "; + $body .= "
    \n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= "
    "; + if ($admin) { + $body .= "
    \n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= "
    "; + } + $body .= "
    "; + + $body .= ""; + $body .= "Back to the contributions list."; + + return; + } + + if ($mode eq "ack") + { + $title = "Acknowledge"; + + unless ($remote) { + $body .= "login before acknowledging contributions. p?>"; + return; + } + unless (LJ::did_post()) { + $body .= ""; + return; + } + + my $dbr = LJ::get_db_reader(); + my $coid = $FORM{'coid'}+0; + my $sth = $dbr->prepare("SELECT userid, cat, des, url, dateadd, acks FROM contributed WHERE coid=$coid"); + $sth->execute; + my $co = $sth->fetchrow_hashref; + + unless ($co) { + $body = "Contribution not found."; + return; + } + + if ($co->{'userid'} == $remote->{'userid'}) { + $body .= ""; + return; + } + + unless (LJ::Contrib::is_acked($remote->{'userid'})) { + $body .= ""; + return; + } + + LJ::Contrib::ack($coid, $remote->{'userid'}); + + $body = "this contribution. p?>"; + + $body .= ""; + $body .= "Back to the contributions list."; + + return; + } + + $title = "Unknown mode"; + $body = "Unknown mode."; + + return; + +} +_code?> +body=> +page?> +lib: cgi-bin/ljlib.pl +link: htdocs/login.bml + +_c?> diff --git a/ljcom/htdocs/site/free.bml b/ljcom/htdocs/site/free.bml new file mode 100644 index 0000000..84447f9 --- /dev/null +++ b/ljcom/htdocs/site/free.bml @@ -0,0 +1,21 @@ +It's Free. +body<= + + + + +paid account to show your support and to help us afford better hardware and bring you new features, but you don't have to. +p?> +let me know! +p?> + +<=body +page?> +link: htdocs/paidaccounts/index.bml +mailto: webmaster@livejournal.com + _c?> diff --git a/ljcom/htdocs/site/goat.bml b/ljcom/htdocs/site/goat.bml new file mode 100644 index 0000000..8824a9d --- /dev/null +++ b/ljcom/htdocs/site/goat.bml @@ -0,0 +1,19 @@ + +body<= + + + + h1?> + +<?_ml .image.alt _ml?> +
    + + +p?> + +<=body +page?> diff --git a/ljcom/htdocs/site/hardware.bml b/ljcom/htdocs/site/hardware.bml new file mode 100644 index 0000000..c3292bd --- /dev/null +++ b/ljcom/htdocs/site/hardware.bml @@ -0,0 +1,8 @@ +Hardware +body<= + +This page wasn't updated in many years, so is now devoid of information to be more accurate. We have lots of servers. + +<=body +page?> diff --git a/ljcom/htdocs/site/index.bml b/ljcom/htdocs/site/index.bml new file mode 100644 index 0000000..d56b21c --- /dev/null +++ b/ljcom/htdocs/site/index.bml @@ -0,0 +1,255 @@ +{s}✔ +pef=>{s}☺ +<=localblocks +_info?> + + +<=head +title=>Site Map +body<= + + = Paid Only Feature
    + = Enhanced for Paid Users + + + + +
    + + +
    + + + + +
    + + + + +
    + + +Thanks go to for the initial version of this page. + +<=body +page?> diff --git a/ljcom/htdocs/site/search.bml b/ljcom/htdocs/site/search.bml new file mode 100644 index 0000000..65e470b --- /dev/null +++ b/ljcom/htdocs/site/search.bml @@ -0,0 +1,42 @@ +{s}✔ +<=localblocks +_info?>Search +body<= + + + = Paid Only Feature + + +
      +
    • + View a Random Journal h2?> + +
    • +
    • + Search By Region h2?> + +
    • +
    • + Search By Interests h2?> + +
    • +
    • +Advanced Search h2?> + +
    • +
    + + +<=body +page?> + +link: htdocs/random.bml, htdocs/directory.bml +link: htdocs/interests.bml, htdocs/directorysearch.bml + +_c?> diff --git a/ljcom/htdocs/site/software.bml b/ljcom/htdocs/site/software.bml new file mode 100644 index 0000000..addea76 --- /dev/null +++ b/ljcom/htdocs/site/software.bml @@ -0,0 +1,15 @@ +Software +body<= + +This page wasn't updated in many years, so is now devoid of information to be more accurate. In summary: +
      +
    • Linux (Debian)
    • +
    • MySQL
    • +
    • Perl
    • +
    • Apache (mod_perl)
    • +
    • memcached
    • +
    + +<=body +page?> diff --git a/ljcom/htdocs/static/style/syn.css b/ljcom/htdocs/static/style/syn.css new file mode 100644 index 0000000..84e3359 --- /dev/null +++ b/ljcom/htdocs/static/style/syn.css @@ -0,0 +1,70 @@ + +body, html { +padding: 0; +margin: 0; +background: #FFFFFF none; +color: #000000; +} + +#top { +margin: 0; +padding: 0; +background: #6666CC none; +color: #FFFFFF; +} + +#top img { +margin: 0; border: 0; padding: 0; +} + +#top #feedtitle { +margin-left: 0.5em; +margin-right: 0.5em; +} + +#middle { +margin: 0.5em; +} + +.entry { +margin-top: 0.5em; +margin-bottom: 0.5em; +} + +.entry h2 { +font-size: 1.1em; font-weight: bold; +margin: 0; +} +.entry .dateline { +font-size: 0.9em; +} + +.entry .entrylinks { +font-size: 0.75em; +text-align: right; +} +.entry .entrylinks:before { +content: "\BB\ "; +} + +.entry .entryheading { +background: #C0C0FF none; +color: #000000; +padding: 0.25em; +margin-bottom: 0.5em; +} +.entry .entryheading a { +background: #C0C0FF none; +color: #000000; +text-decoration: underline; +} + +#bottom { +margin: 0; +padding: 0.5em; +background: #6666CC none; +color: #FFFFFF; +} +#bottom p { +margin: 0; +} diff --git a/ljcom/htdocs/stats/latest-img.bml b/ljcom/htdocs/stats/latest-img.bml new file mode 100644 index 0000000..8cb4581 --- /dev/null +++ b/ljcom/htdocs/stats/latest-img.bml @@ -0,0 +1,39 @@ +\n"; + $ret .= <<"EOT"; + +EOT + +$ret .= "\n"; + + my $rimg = LJ::MemCache::get("blob:ljcom_latestimg"); +unless (ref $rimg eq "ARRAY" && @$rimg) { + $ret .= "\n"; + $ret .= "\n"; + return $ret; +} + +$ret .= "\n"; + +foreach my $ri (reverse @$rimg) { + my ($img, $ju, $jitemid, $anum) = @$ri; + $img = LJ::exml($img); + my $url = LJ::item_link($ju, $jitemid, $anum); + $ret .= "\n"; +} + + +$ret .= "\n"; +$ret .= "\n"; + + return $ret; +} +_code?> diff --git a/ljcom/htdocs/stats/latest-rss.bml b/ljcom/htdocs/stats/latest-rss.bml new file mode 100644 index 0000000..23b1b61 --- /dev/null +++ b/ljcom/htdocs/stats/latest-rss.bml @@ -0,0 +1,111 @@ +\n"; + $ret .= <<"EOT"; + +EOT + $ret .= "\n"; + + $ret .= "Latest $LJ::SITENAME Posts$LJ::SITEROOT/stats/latest.bmlLatest public posts at $LJ::SITENAME.\n"; + + # setup for security logging + my %securities = ( + public => 0, + private => 0, + friends => 0, + custom => 0, + ); + + # retrieve posts. + my @postids; + foreach my $p (@$recent) { + $securities{$p->{security}}++; + next unless $p->{security} eq 'public'; + $p->{ditemid} = $p->{itemid}*256 + $p->{anum}; + $p->{urn} = "urn:$LJ::DOMAIN:entry:$p->{journalu}{user}:$p->{ditemid}"; + + push @postids, [ $p->{clusterid}, $p->{journalu}{userid}, $p->{itemid} ]; + } + my $rawposts = LJ::get_posts_raw({memcache_only=>1}, @postids); + + my $rdftoc = "\n"; + my $rdfitems = ""; + + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $uj = $p->{'journalu'}; + my $up = $p->{'journalp'}; + my $id = "$uj->{userid}:$p->{itemid}"; + my $props = $rawposts->{prop}{$id}; + + # we shouldn't expect every post to be in the memcache. + next unless $rawposts->{text}{$id}; + + # skipping unknown8bit users sucks, but we can't load users here. + next if $props->{unknown8bit}; + + $rdftoc .= " \n"; + + my $url = LJ::journal_base($uj) . "/$p->{ditemid}.html"; + my ($subject, $body) = @{$rawposts->{text}{$id}}; + + $rdfitems .= "\n"; + + # first, the required RDF elements. + # we use title to represent all the metadata in one string, + # then dublin core for the data in pieces. + $rdfitems .= "$up->{'user'}"; + $rdfitems .= " (in $uj->{'user'})" if $uj->{userid} != $up->{userid}; + $rdfitems .= ": " . LJ::exml($subject) if $subject; + $rdfitems .= "\n"; + $rdfitems .= "" . LJ::exml($body) . "\n"; + $rdfitems .= "$_\n" foreach map { LJ::exml($_) } @{$p->{tags} || []}; + $rdfitems .= "$url\n"; + + # use dc for the rest. + $rdfitems .= "" . LJ::exml($subject) . "\n" if $subject; + $rdfitems .= "" . LJ::exml($up->{name}) . " ($up->{user})\n"; + $rdfitems .= "" . LJ::exml($uj->{user}) . "\n" + if $uj->{userid} != $up->{userid}; + $rdfitems .= "" . LJ::time_to_w3c($p->{timepost}) . "Z\n"; + + # and lj for the lj-specific data. + my $mood = $props->{current_mood}; + $mood ||= LJ::mood_name($props->{current_moodid}) if $props->{current_moodid}; + + my $moodid = " id='$props->{current_moodid}'" if $props->{current_moodid}; + $rdfitems .= "" . LJ::exml($mood) . "\n" + if $mood or $moodid; + $rdfitems .= "" . LJ::exml($props->{current_music}) . "\n" + if $props->{current_music}; + $rdfitems .= "" . LJ::exml($props->{picture_keyword}) . "\n" + if $props->{picture_keyword}; + + $rdfitems .= "\n"; + } + $rdftoc .= "\n"; + + $ret .= $rdftoc . $rdfitems; + $ret .= "\n"; + + $ret .= <<"EOT"; + +EOT + return BML::noparse($ret); +} +_code?> diff --git a/ljcom/htdocs/stats/latest.bml b/ljcom/htdocs/stats/latest.bml new file mode 100644 index 0000000..9c81f6f --- /dev/null +++ b/ljcom/htdocs/stats/latest.bml @@ -0,0 +1,90 @@ +Latest Posts +head<= + +<=head +body<= +[1] - $stat->[2]) { + + my $rate_sec = $stat->[0] / $delta; + + my $rate_min = $rate_sec * 60; + my $fmt_min = $rate_min > 10 ? "%.0f" : "%.2f"; + + my $rate_hour = $rate_min * 60; + my $fmt_hour = $rate_hour > 10 ? "%.0f" : "%.2f"; + + my $post_min = sprintf($fmt_min, $rate_min); + my $post_hour = sprintf($fmt_hour, $rate_hour); + + $ret .= "Current posting stats: $post_hour per hour, $post_min per minute\n"; + } + + my @postids; + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + $p->{ditemid} = $p->{itemid}*256 + $p->{anum}; + push @postids, [ $p->{clusterid}, $p->{journalu}{userid}, $p->{itemid} ]; + } + my $rawposts = LJ::get_posts_raw({memcache_only=>1}, @postids); + + $ret .= "RSS version"; + $ret .= "\n"; + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $uj = $p->{'journalu'}; + my $up = $p->{'journalp'}; + my $id = "$uj->{userid}:$p->{itemid}"; + + # we shouldn't expect every post to be in the memcache. + next unless $rawposts->{text}{$id}; + + # this sucks, but we can't load users here. + next if $rawposts->{prop}{$id}{unknown8bit}; + + my $url = LJ::journal_base($uj) . "/$p->{'ditemid'}.html"; + my ($subject, $body) = @{$rawposts->{text}{$id}}; + + $ret .= ""; + $ret .= "\n"; + + } + $ret .= "
    " . substr(scalar(gmtime($p->{timepost})), 4, 12) . "\n"; + + $ret .= LJ::ljuser($up->{user}); + if ($up->{userid} != $uj->{userid}) { + $ret .= " (in " . LJ::ljuser($uj->{user}, {type => $uj->{journaltype}}) . ")"; + } + $ret .= ":
    \n"; + + $ret .= "
    "; + LJ::CleanHTML::clean_subject(\$subject); + LJ::CleanHTML::clean_event(\$body, {'cuturl' => LJ::item_link($uj, $p->{'itemid'}, $p->{'anum'})}); + $ret .= "$subject
    \n" if $subject; + $ret .= $body; + $ret .= "
    \n"; + + BML::noparse(); + return $ret; +} +_code?> + +<=body +page?> diff --git a/ljcom/htdocs/stats/weblog-updates-xml.bml b/ljcom/htdocs/stats/weblog-updates-xml.bml new file mode 100644 index 0000000..2849487 --- /dev/null +++ b/ljcom/htdocs/stats/weblog-updates-xml.bml @@ -0,0 +1,34 @@ +\n"; + $ret .= <<"EOT"; + +EOT + + $ret .= "\n"; + + # retrieve posts. + my @postids; + my %done; # journalid -> 1 + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $u = $p->{journalu} or next; + next if $done{$u->{userid}}++; + my $base = LJ::journal_base($u); + $ret .= "\n"; + } + + $ret .= "\n"; + + return BML::noparse($ret); +} +_code?> diff --git a/ljcom/htdocs/store/index.bml b/ljcom/htdocs/store/index.bml new file mode 100644 index 0000000..8dbe080 --- /dev/null +++ b/ljcom/htdocs/store/index.bml @@ -0,0 +1,32 @@ +LiveJournal Store +body<= + + +[<< View Current Order] + + +Sizing Chart]p?> + + + + +
    + +
    Short Sleeve +
    + +
    Long Sleeve +
    + +
    "Baby Doll" +
    + +
    Embroidered Polo +
    + +<=body +page?> + diff --git a/ljcom/htdocs/store/sizechart.bml b/ljcom/htdocs/store/sizechart.bml new file mode 100644 index 0000000..d4ed63a --- /dev/null +++ b/ljcom/htdocs/store/sizechart.bml @@ -0,0 +1,135 @@ +Sizing Chart +body<= + + +[<< View Current Order] [<< Back to store] + + +Gildan Ultra 100% cotton preshrunk Jersey, 6.1oz per Sq Yd. Size 3XL is JersyZT 6.0 oz. Size 4XL is Bayside. p?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SMLXLXXL3XL4XL
    Width + 18"20"22"24"26"28"30"
    Length + 28"29"30"31"32"33"34"
    + + + +Outer Banks Pique Polo 6.5 oz. +p?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SMLXLXXL3XL
    Length + 28"30"31"32"33"34"
    Sleeve Length + 10"10.5"11"11.5"12"12.5"
    Width + 19.5"21.5"23.5"25"26.5"28.5"
    + + + + +American Apparel Girly Crew women's t-shirts: +p?> + + + + + + +
    SmallMediumLargeX-Large
    2/46/810/1212/14
    bust33"/34"35"/36"37"/38"39"
    waist25"/26"27"/28"29"/30"31"/32"
    + + + + +Hanes Hooded Sweatshirt. Pre-shrunk with a drawstring hood, +pouch pocket, spandex ribbed cuffs and waistband. 90% cotton, 10% polyester +heavyweight fabric. Sorry, dimensions are not currently available. +p?> + + + + +<=body +page?> + diff --git a/ljcom/htdocs/store/view.bml b/ljcom/htdocs/store/view.bml new file mode 100644 index 0000000..9854c8e --- /dev/null +++ b/ljcom/htdocs/store/view.bml @@ -0,0 +1,71 @@ +[0]; + + $ret .= "[<< View Current Order]\n"; + $ret .= "[<< Back to store]"; + + if ($item =~ /^clothes-(.+)$/) { + my $type = $1; + my $colors = $it->[1]; + + my %inv; + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT subitem, avail, price FROM inventory ". + "WHERE item='clothes' AND subitem LIKE '$type%'"); + $sth->execute; + while (my ($si, $avail, $price) = $sth->fetchrow_array) { + my ($style, $color, $size) = split(/-/, $si); + $inv{$color}->{$size} = [ $avail, $price ]; + } + + $ret .= "Size Chart for details about the sizes. p?>"; + + $ret .= "
    "; + foreach my $col (@$colors) { + $ret .= "
    $LJ::Pay::color{$col}"; + foreach my $size (sort { $LJ::Pay::size{$a}->[0] <=> $LJ::Pay::size{$b}->[0] } keys %{$inv{$col}}) { + my $inv = $inv{$col}->{$size}; + my $price = sprintf("\$%.02f", $inv->[1]); + my $avail = $inv->[0]; + $ret .= "\n"; + } + $ret .= "
    $LJ::Pay::size{$size}->[1]$price  \n"; + if ($avail) { + $ret .= "
    "; + $ret .= LJ::html_hidden("product", "clothes-$type-$col-$size"); + $ret .= "
    "; + } else { + $ret .= " [Out of Stock]"; + } + $ret .= "
    "; + $ret .= "
    \n"; + + } + $ret .= "
    "; + + $ret .= ""; + $ret .= ""; + } + + + return $ret; +} +_code?> +<=body +title=> +page?> diff --git a/ljcom/htdocs/suggestions/generator.bml b/ljcom/htdocs/suggestions/generator.bml new file mode 100755 index 0000000..e7efdad --- /dev/null +++ b/ljcom/htdocs/suggestions/generator.bml @@ -0,0 +1,155 @@ +Suggestion Proposal Generator +body<= + +" unless LJ::text_in(\%FORM); + + my $remote = LJ::get_remote(); + + my $post_comm = 'suggestions'; + + unless ($remote) { + return "login. p?>"; + } + + if ($FORM{'completed'}) { + my $ret = ""; + my @errors = (); + my @fields = ("title","description","fulldescription","benefits","issues","sugglist"); + my $CRLF = "\x0D\x0A"; + unless (LJ::did_post()) { + return ""; + } + + foreach $field (@fields) { + if (! $FORM{$field} ) { + push(@errors,"You forgot to fill out the $field field."); + } + } + + return LJ::bad_input(@errors) if @errors; + + my $out = ""; + $out .= "

    Title\n"; + $out .= "$FORM{'title'}

    "; + $out .= "

    Short, concise description of the idea\n"; + $out .= "$FORM{'description'}

    "; + $out .= "

    Full description of the idea\n"; + $out .= "$FORM{'fulldescription'}

    "; + + $out .= "An ordered list of benefits"; + my @benefits = split(/$CRLF$CRLF/, $FORM{'benefits'}); + $out .= "
      \n"; + foreach my $benefit (@benefits) { + $benefit =~ s!$CRLF!
      !g; + $out .= "
    • $benefit
    • \n"; + } + $out .= "
    "; + + $out .= "
    An ordered list of problems/issues involved"; + my @issues = split(/$CRLF$CRLF/, $FORM{'issues'}); + $out .= "
      \n"; + foreach my $issue (@issues) { + $issue =~ s!$CRLF!
      \n!g; + $out .= "
    • $issue
    • \n"; + } + $out .= "
    "; + + $out .= "
    An organized list, or a few short paragraphs detailing suggestions for implementation"; + my @suggs = split(/$CRLF$CRLF/, $FORM{'sugglist'}); + $out .= "
      \n"; + foreach my $sugg (@suggs) { + $sugg =~ s!$CRLF!
      \n!g; + $out .= "
    • $sugg
    • \n"; + } + $out .= "
    "; + + # post it + { + my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time()); + $year = $year + 1900; + $mon=sprintf("%02d", $mon+1); + $mday=sprintf("%02d", $mday); + my $rs = LJ::Protocol::do_request("postevent", { + 'ver' => $LJ::PROTOCOL_VER, + 'year' => $year, + 'mon' => $mon, + 'day' => $mday, + 'hour' => $hour, + 'min' => $min, + 'username' => $remote->{'user'}, + 'event' => $out, + 'usejournal' => $post_comm, + 'props' => { 'opt_preformatted' => 0 }, + 'subject' => $FORM{'title'}, + }, \$err, { + 'noauth' => 1, + 'usejournal_okay' => 1, + }); + if ($err) { + my $errstr = LJ::Protocol::error_message($err); + $ret .= ""; + } else { + $ret .= "\n"; + + my $user = LJ::ljuser($post_comm); + + if ($rs->{'itemid'}) { + my $u = LJ::load_user($post_comm); + my $link = LJ::item_link($u, $rs->{'itemid'}, $rs->{'anum'}); + + $ret .= "view your suggestion. p?>"; + } else { + $ret .= ""; + } + } + } + + return $ret; + } else { + return <<__EOF__ + + + + + +
    + + p?> + +
    p?> + +
    p?> + +List each item, pressing <Enter> twice after each one
    p?> + +List each item, pressing <Enter> twice after each one.
    p?> + +List each item, pressing <Enter> twice after each one.
    p?> + community. p?> + + + + + + + +standout?> +
    +__EOF__ + } + +_code?> + +<=body +page?> +post: htdocs/suggestions/generator.bml +link: htdocs/talkread.bml + _c?> diff --git a/ljcom/htdocs/suggestions/index.bml b/ljcom/htdocs/suggestions/index.bml new file mode 100644 index 0000000..301f444 --- /dev/null +++ b/ljcom/htdocs/suggestions/index.bml @@ -0,0 +1,21 @@ + +body<= + + + h1?> + p?> + p?> + h1?> + p?> + h1?> + p?> + + +<=body +page?> _c?> diff --git a/ljcom/htdocs/suggestions/prior.bml b/ljcom/htdocs/suggestions/prior.bml new file mode 100644 index 0000000..e0afe04 --- /dev/null +++ b/ljcom/htdocs/suggestions/prior.bml @@ -0,0 +1,13 @@ +Prior Suggestions +body<= + + + + + +<=body +page?> + _c?> diff --git a/ljcom/htdocs/suggestions/template.bml b/ljcom/htdocs/suggestions/template.bml new file mode 100644 index 0000000..b6f4f3f --- /dev/null +++ b/ljcom/htdocs/suggestions/template.bml @@ -0,0 +1,30 @@ +Proposal Template +body<= + + +suggestions page. +p?> + + + + + + + + + + + + + + + + + community. p?> + +<=body +page?> +link: htdocs/suggestions/index.bml + _c?> diff --git a/ljcom/htdocs/template.bml b/ljcom/htdocs/template.bml new file mode 100644 index 0000000..7515fcf --- /dev/null +++ b/ljcom/htdocs/template.bml @@ -0,0 +1,13 @@ + +body=> +page?> diff --git a/ljcom/htdocs/tools/xfer_remaining.bml b/ljcom/htdocs/tools/xfer_remaining.bml new file mode 100644 index 0000000..8e73bfa --- /dev/null +++ b/ljcom/htdocs/tools/xfer_remaining.bml @@ -0,0 +1,181 @@ +Paid Time Transfer + +body<= +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + my $ret = ""; + my $dbh = LJ::get_db_writer(); + + my $is_perm = sub { return $_[0]->{caps} & (1 << $LJ::Pay::capinf{perm}->{bit}) }; + my $paid_bit = (1 << $LJ::Pay::capinf{paid}->{bit}); + + my $get_days = sub { return sprintf("%0.02f", $_[0] / 86400) }; + my $get_secs = sub { + return $dbh->selectrow_array + ("SELECT UNIX_TIMESTAMP(paiduntil)-UNIX_TIMESTAMP() " . + "FROM paiduser WHERE userid=?", undef, $_[0]->{userid}); + }; + + if (LJ::did_post() && $POST{'submit'}) { + my $u_from = ($has_priv ? LJ::load_user($POST{user}) : $remote) + or return LJ::bad_input("User $POST{user} doesn't exist."); + my $u_to = LJ::load_user($POST{userto}) + or return LJ::bad_input("User $POST{userto} doesn't exist."); + + return LJ::bad_input("Source and destination users must be different") + if LJ::u_equals($u_from, $u_to); + + return LJ::bad_input("Source user must be currently logged in user") + unless $has_priv || LJ::u_equals($u_from, $u); + + return LJ::bad_input("Destination user already has a permanent account!") + if $is_perm->($u_to); + + return LJ::bad_input("You must have purchased a permanent account to transfer paid time to another user.") + unless $has_priv || $is_perm->($u_from); + + my $secs = $get_secs->($u_from); + my $days = $get_days->($secs); + return "" + unless $secs > 0; + + $ret .= "Transferred $days days from " . LJ::ljuser($u_from) . " to " . LJ::ljuser($u_to) . "\n"; + + # first try inserting in the case of a new paid account + LJ::update_user($u_to, { raw => "caps=caps|$paid_bit" }); + $dbh->do("INSERT INTO paiduser (userid, paiduntil) " . + "VALUES (?, FROM_UNIXTIME(UNIX_TIMESTAMP()+?))", + undef, $u_to->{userid}, $secs); + + # already a paid user, just extend their existing row + if ($dbh->err) { + $dbh->do("UPDATE paiduser " . + "SET paiduntil=FROM_UNIXTIME(UNIX_TIMESTAMP(paiduntil)+?) " . + "WHERE userid=?", undef, $secs, $u_to->{userid}); + } + + # log to statushistory so there's a record of this action + my $logmesg = "Transferred $days days: $u_from->{user} => $u_to->{user}"; + LJ::statushistory_add($u_from, $remote->{'userid'}, "acct_xfer_src", $logmesg); + LJ::statushistory_add($u_to, $remote->{'userid'}, "acct_xfer_dest", $logmesg); + + ### take away time from source + if ($is_perm->($u_from)) { + # take away their paid until time so they can't give it away again. + # don't remove them from paiduser though, since they're permanent and need + # to be here to get the email alias generated. + $dbh->do("UPDATE paiduser SET paiduntil='0000-00-00' WHERE userid=?", + undef, $u_from->{userid}); + } else { + $dbh->do("DELETE FROM paiduser WHERE userid=?", + undef, $u_from->{userid}); + + LJ::update_user($u_from->{userid}, { raw => "caps=caps&~$paid_bit" }); + } + + my $source = $has_priv && $POST{'anon'} ? "(ANONYMOUS)" : $u_from->{user}; + + LJ::send_mail({ 'to' => $u_to->{email}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => 'LiveJournal', + 'subject' => "Gift! Paid account left-overs...", + 'body' => "Hey,\n\nUser $source has decided to transfer his/her remaining paid time to you. So, you now have a paid account (if you didn't have one already) and $days more days of paid account status.\n\nYou can find out more about paid accounts and their benefits at http://www.livejournal.com/paidaccounts/\n\nEnjoy!\n", + }); + + return $ret; + } + + # authas switcher form -- makes no sense if user is priv'd + unless ($has_priv) { + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { authas => $GET{'authas'} }) . "\n"; + $ret .= "
    \n\n"; + } + + $ret .= ""; + + # standard intro paragraph for users + if ($has_priv) { + $ret .= ""; + + # only available to admins and perm account holders + } elsif (! $is_perm->($u)) { + $ret .= ""; + return $ret; + + # standard form for normal permanent accounts + } else { + + my $secs = $get_secs->($u); + my $days = $get_days->($secs); + + $ret .= " 0; + $ret .= "to any other non-permanent account. p?>"; + + unless ($secs > 0) { + $ret .= ""; + return $ret; + } + } + + # begin submission form + $ret .= "
    "; + + # from user + $ret .= ""; + + # to user + $ret .= ""; + $ret .= ""; + + # anonymous option for admins + if ($has_priv) { + $ret .= ""; + $ret .= ""; + } + + $ret .= "
    From:"; + if ($has_priv) { + $ret .= LJ::html_text({ size => 15, maxlength => 15, name => 'user' }); + } else { + $ret .= LJ::ljuser($u); + } + $ret .= "
    To:" . LJ::html_text({ size => 15, maxlength => 15, name => 'userto' }); + $ret .= "
    Anonymous?" . LJ::html_check({ value => 1, name => 'anon' }); + $ret .= "
     "; + $ret .= LJ::html_submit('submit' => "Transfer"); + $ret .= "
    "; + + return $ret; +} +_code?> +<=body + +page?> diff --git a/ljcom/sites/mrtg/index.cgi b/ljcom/sites/mrtg/index.cgi new file mode 100755 index 0000000..534444d --- /dev/null +++ b/ljcom/sites/mrtg/index.cgi @@ -0,0 +1,868 @@ +#!/usr/bin/perl -w +# +# 14all.cgi +# +# create html pages and graphics with rrdtool for mrtg + rrdtool +# +# (c) 1999,2000 Rainer.Bawidamann@informatik.uni-ulm.de +# +# use freely, but: NO WARRANTY - USE AT YOUR OWN RISK! + +# if RRDs (rrdtool perl module) is not in the module search path (@INC) +# uncomment the following line and change the path appropriatly: +#use lib qw(/usr/local/mrtg290/lib/mrtg2); + +# RCS History - removed as it's available on the web + +#my $rcsid = '$Id: index.cgi,v 1.4 2002/03/06 01:54:12 bradfitz Exp $'; + +my $subversion = (split(/ /,$rcsid))[2]; +$subversion =~ m/^\d+\.(\d+)$/; +my $version = "14all.cgi 1.1p$1"; + +# my $DEBUG = 0; has gone - use config "14all*GraphErrorsToBrowser: 1" + + +use strict; +use CGI; +my $remote; + +BEGIN { +if ($^O !~ m/Win/i) { + eval { require CGI::Carp; import CGI::Carp qw/fatalsToBrowser/ } + } +unshift @INC, "/usr/local/mrtg-2/lib/mrtg2/"; +unshift @INC, "/home/lj"; + +}; + +require '/home/lj/cgi-bin/ljlib.pl'; + +use RRDs 1.000011; +use MRTG_lib "2.090003"; + +sub print_error($@); +sub intmax(@); +sub yesorno($); +sub get_graph_params($$$); +sub getdirwriteable($$); +sub getpngsize($); +sub errorpng(); +sub gettextpic($); +sub log_rrdtool_call($$@); + +my ($q, $cfgfile, $cfgfiledir); +my ($cgidir, @author, @style); + +$cfgfile = '/etc/mrtg/mrtg.cfg'; + +### cusotmize the html pages +@author = ( -author => 'Rainer.Bawidamann@informatik.uni-ulm.de'); +# one possibility to enable stylesheets (second is to use "AddHead[_]:..." in mrtg.cfg) +#@style = ( -style => { -src => 'general.css' }); +### + +if (!$cfgfile && $#ARGV == 0) { + $cfgfile = shift @ARGV; +} + +# initialize CGI +$q = new CGI; + +my $dbh = LJ::get_dbh("slave"); + +$remote = LJ::get_remote($dbh, undef, $q); +unless (LJ::check_priv($dbh, $remote, "siteadmin", "mrtg")) { + if ($remote) { + print "Content-type: text/html\n\n"; + print "You don't have access to see this. If you need access, contact us."; + exit 0; + } else { + print "Content-type: text/html\n\n"; + print "You must first log in."; + exit 0; + } + } + + +# change for mrtg-2.9.* +my (@sorted, %config, %targets); +my %myrules = ( + '14all*errorpic' => + [sub{$_[0] && (-r $_[0] )}, sub{"14all*ErrorPic '$_[0]' not found/readable"}], + '14all*grapherrorstobrowser' => [sub{1}, sub{"Internal Error"}], + '14all*columns' => + [sub{int($_[0]) >= 1}, sub{"14all*Columns must be at least 1 (is '$_[0]')"}], + '14all*rrdtoollog' => + [sub{$_[0] && (!-d $_[0] )}, sub{"14all*RRDToolLog must be a writable file"}], + '14all*background' => + [sub{$_ =~ /^#[0-9a-f]{6}$/i}, sub{"14all*backgroud colour not in form '#xxxxxx', x in [a-f0-9]"}], + '14all*logarithmic[]' => [sub{1}, sub{"Internal Error"}], + '14all*graphtotal[]' => [sub{1}, sub{"Internal Error"}], + '14all*dontshowindexgraph[]' => [sub{1}, sub{"Internal Error"}], + '14all*indexgraph[]' => [sub{1}, sub{"Internal Error"}], + '14all*indexgraphsize[]' => + [sub{$_[0] =~ m/^\d+[,\s]+\d+$/o}, sub{"14all*indexgraphsize: need two numbers"}], +); + +my %graphparams = ( + 'daily' => ['-2000m', 'now', 300], + 'weekly' => ['-12000m','now', 1800], + 'monthly' => ['-800h', 'now', 7200], + 'yearly' => ['-400d', 'now', 86400], + 'daily.s' => ['-1250m', 'now', 300], +); + +# look for the config file +my $meurl = $q->url(); +ensureSL(\$cfgfiledir); +if (defined $q->param('cfg')) { + $cfgfile = $q->param('cfg'); + $cfgfile = $cfgfiledir.$cfgfile unless -r $cfgfile; + print_error($q, "Cannot find the given config file: \$cfgfile\") + unless -r $cfgfile; +} elsif (!$cfgfile) { + $meurl =~ m{\Q$MRTG_lib::SL\E([^\Q$MRTG_lib::SL\E]*)\.(cgi|pl)$}; + $cfgfile = $1 . '.cfg'; + $cfgfile = $cfgfiledir.$cfgfile unless -r $cfgfile; +} + +$meurl = "";# if ($meurl eq "/index.cgi") { $meurl = ""; } + +# read the config file + +readcfg($cfgfile, \@sorted, \%config, \%targets, "14all", \%myrules); +my @processed_targets; +cfgcheck(\@sorted, \%config, \%targets, \@processed_targets); + +# set some defaults +if (exists $config{refresh} && yesorno($config{refresh}) + && $config{refresh} !~ m/^\d*[1-9]\d*$/o) { + $config{refresh} = $config{interval} * 60; +} + +my @headeropts = (@author, @style); + +# the footer we print on every page +my $footer = ""; + +(undef) = <<"EOT" . $q->end_html; + + + + + + +
    + + + + + + + +
    Version ${MRTG_lib::VERSION} + Tobias Oetiker + <oetiker\@ee.ethz.ch> and + Dave Rand  + <dlr\@bungi.com> +
    $version + Rainer Bawidamann  + <rb1\@informatik.uni-ulm.de> +
    +EOT + +### the main switch +# the modes: +# if parameter "dir" is given show a list of the targets in this "directory" +# elsif parameter "png" is given show a graphic for the target given w/ parameter "log" +# elsif parameter "log" is given show the page for this target +# else show a list of directories and of targets w/o directory +# parameter "cfg" can hold the name of the config file to use +if (defined $q->param('dir')) { + # show a list of targets in the given directory + my $dir = $q->param('dir'); + my @httphead; + push @httphead, (-expires => '+' . int($config{interval}) . 'm'); + if (yesorno($config{refresh})) { + push @httphead, (-refresh => $config{refresh}); + } + push @headeropts, (-bgcolor => ($config{'14all*background'} || '#ffffff')); + my @htmlhead = (-title => "MRTG/RRD - Group $dir", @headeropts); + #if ($targets{addhead}{_}) { + # push @htmlhead, (-head => $targets{addhead}{_}); + #} + print $q->header(@httphead), $q->start_html(@htmlhead); + print $q->h1("Available Targets"),"\n\\n"; + my $cfgstr = (defined $q->param('cfg') ? "&cfg=".$q->param('cfg') : ''); + my $column = 0; + my $pngdir = getdirwriteable($config{imagedir},$dir); + my $confcolumns = $config{'14all*columns'} || 2; + foreach my $tar (@sorted) { + my $small = 0; + unless (yesorno($targets{'14all*dontshowindexgraph'}{$tar})) { + $small = $targets{'14all*indexgraph'}{$tar}; + $small = 'daily.s' unless $small; + } + next if $tar =~ m/^[\$\^\_]$/; # _ is not a real target + next if $targets{directory}{$tar} ne $dir; + print '' if $column == 0; + print '\n"; + $column++; + if ($column >= $confcolumns) { + $column = 0; + print ''; + } + } + if ($column != 0 and $column < $confcolumns) { + print '' x ($confcolumns - $column),"\\n"; + } + print '
    ', + $q->p($q->a({href => "$meurl?log=$tar$cfgstr"}, $targets{title}{$tar})); + print $q->a({href => "$meurl?log=$tar$cfgstr"}, + $q->img({src => "$meurl?log=$tar&png=$small&small=1$cfgstr", + alt => "index-graph", + getpngsize("$pngdir$tar-$small-i.png")}) + ) if $small; + print "\
     
    ', $footer; +} elsif (defined $q->param('png')) { + # send a graphic, create it if necessary + my $errstr = ''; + if (!defined $q->param('log')) { + $errstr="CGI call error: missing param 'log'"; + goto ERROR; + } + my $png = $q->param('png'); + my $log = $q->param('log'); + unless (exists $targets{target}{$log}) { + $errstr="target '$log' unknown"; + goto ERROR; + } + # fix a problem with indexmaker + if (defined $q->param('small')) { + my %imaker = qw/day.s daily.s week.s weekly month.s monthly year.s yearly/; + if (exists $imaker{$png}) { + $png = $imaker{$png}; + } + } + my ($start, $end, $maxage); + my $graphparams = $targets{"graph*$png"}{$log}; + if ($graphparams) { + ($start, $end, $maxage) = split(/[,\s]+/, $graphparams, 3); + } + unless ($start && $end && $maxage) { + unless (exists $graphparams{$png}) { + $errstr="CGI call error: graph '$png' unknown"; + goto ERROR; + } + ($start, $end, $maxage) = @{$graphparams{$png}}; + } + my ($xs, $ys); + if (defined $q->param('small')) { + ($xs, $ys) = (250, 100); + ($xs, $ys) = ($targets{'14all*indexgraphsize'}{$log} =~ m/\d+[,\s]+\d+/) + if $targets{'14all*indexgraphsize'}{$log}; + } else { + ($xs, $ys) = ($targets{xsize}{$log}, $targets{ysize}{$log}); + } + unless ($xs && $ys) { + $errstr="cannot get image sizes for graph $png / target $log"; + goto ERROR; + } + my $rrd = $config{logdir}.$targets{directory}{$log} . $log . '.rrd'; + # escape ':' and '\' with \ in $rrd + # (rrdtool replaces '\:' by ':' and '\\' by '\') + $rrd =~ s/([:\\])/\\$1/g; + my $pngdir = getdirwriteable($config{imagedir}, $targets{directory}{$log}); + $png .= '-i' if defined $q->param('small'); + my $pngfile = "${pngdir}${log}-${png}.png"; + + # build the rrd command line: set the starttime and the graphics format (PNG) + my @args = ($pngfile, '-s', $start, '-e', $end, '-a', 'PNG'); + # if it's not a small picture set the legends + my ($l1,$l2,$l3,$l4,$li,$lo) = ('','','','','',''); + my ($ri, $ro) = ('',''); + + push @args, '-w', $xs, '-h', $ys; + if (!defined $q->param('small')) { + foreach (qw/legend1 legend2 legend3 legend4 legendi legendo legendy shortlegend/) { + if ($targets{$_}{$log}) { + $targets{$_}{$log} =~ s' ' 'go; #' + $targets{$_}{$log} =~ s/%/%%/go; + } + } + my $persec = $targets{options}{bits}{$log} ? 'Bits' : 'Bytes'; + if ($targets{ylegend}{$log}) { + push @args, '-v', $targets{ylegend}{$log}; } + + if ($targets{legend1}{$log}) { + $l1 = ":".$targets{legend1}{$log}."\\l"; } + else { + $l1 = ":Incoming Traffic in $persec per Second\\l"; } + if ($targets{legend2}{$log}) { + $l2 = ":".$targets{legend2}{$log}."\\l"; } + else { + $l2 = ":Outgoing Traffic in $persec per Second\\l"; } + if ($targets{legend3}{$log}) { + $l3 = ":".$targets{legend3}{$log}."\\l"; } + else { + $l3 = ":Maximal 5 Minute Incoming Traffic\\l"; } + if ($targets{legend4}{$log}) { + $l4 = ":".$targets{legend4}{$log}."\\l"; } + else { + $l4 = ":Maximal 5 Minute Outgoing Traffic\\l"; } + + if (exists $targets{legendi}{$log}) { + $li = $targets{legendi}{$log}; } + else { $li = "In: "; } + $li =~ s':'\\:'; # ' quote : + if (exists $targets{legendo}{$log}) { + $lo = $targets{legendo}{$log}; } + else { $lo = "Out:"; } + $lo =~ s':'\\:'; # ' quote : + + if ($targets{options}{integer}{$log}) { + $li .= ' %9.0lf'; + $lo .= ' %9.0lf'; + $ri = '%3.0lf%%'; + $ro = '%3.0lf%%'; + } else { + $li .= ' %8.3lf'; + $lo .= ' %8.3lf'; + $ri = '%6.2lf%%'; + $ro = '%6.2lf%%'; + } + if (!defined($targets{kmg}{$log}) || $targets{kmg}{$log}) { + $li .= ' %s'; + $lo .= ' %s'; + if ($targets{kilo}{$log}) { + push @args, '-b', $targets{kilo}{$log}; + } + if ($targets{shortlegend}{$log}) { + $li .= $targets{shortlegend}{$log}; + $lo .= $targets{shortlegend}{$log}; + } + } + } + my $factor = 1; # should we scale the values? + if ($targets{options}{perminute}{$log}) { + $factor = 60; # perminute -> 60x + } elsif ($targets{options}{perhour}{$log}) { + $factor = 3600; # perhour -> 3600x + } + if ($targets{options}{bits}{$log}) { + $factor *= 8; # bits instead of bytes -> 8x + } + # let the user give an arbitrary factor: + if ($targets{factor}{$log} and + $targets{factor}{$log} =~ m/^[-+]?\d+(.\d+)?([eE][+-]?\d+)?$/) + { + $factor *= 0+$targets{factor}{$log}; + } + my $pngchar = substr($png,0,1); + if ($pngchar and $targets{unscaled}{$log} and + $targets{unscaled}{$log} =~ m/$pngchar/) { + my $max = intmax($targets{maxbytes}{$log}, + $targets{maxbytes1}{$log}, + $targets{maxbytes2}{$log}, + $targets{absmax}{$log}); + $max *= $factor; + push @args, '-l', 0, '-u', $max, '-r'; + } elsif (yesorno($targets{'14all*logarithmic'}{$log})) { + push @args, '-o'; + } + push @args,'--alt-y-grid','--lazy','-c','MGRID#ee0000','-c','GRID#000000'; + # now build the graph calculation commands + # ds0/ds1 hold the normal data sources to graph/gprint + my ($ds0, $ds1) = ('in', 'out'); + push @args, "DEF:$ds0=$rrd:ds0:AVERAGE", "DEF:$ds1=$rrd:ds1:AVERAGE"; + if (defined $targets{options}{unknaszero}{$log}) { + push @args, "CDEF:uin=$ds0,UN,0,$ds0,IF", + "CDEF:uout=$ds1,UN,0,$ds1,IF"; + ($ds0, $ds1) = ('uin', 'uout'); + } + if ($factor != 1) { + # scale the values. we need a CDEF for this + push @args, "CDEF:fin=$ds0,$factor,*","CDEF:fout=$ds1,$factor,*"; + ($ds0, $ds1) = ('fin', 'fout'); + } + my $maximum0 = $targets{maxbytes1}{$log} || $targets{maxbytes}{$log}; + my $maximum1 = $targets{maxbytes2}{$log} || $targets{maxbytes}{$log}; + $maximum0 = 1 unless $maximum0; + $maximum1 = 1 unless $maximum1; + # ps0/ps1 hold the percentage data source for gprint + my ($ps0, $ps1) = ('pin', 'pout'); + push @args, "CDEF:pin=$ds0,$maximum0,/,100,*,$factor,/", + "CDEF:pout=$ds1,$maximum1,/,100,*,$factor,/"; + + if (yesorno($targets{'14all*graphtotal'}{$log})) { + push @args, "CDEF:total=$ds0,$ds1,+", "LINE1:total#ffa050:Total AVG\\l"; + } + # now for the peak graphs / maximum values + # mx0/mx1 hold the maximum data source for graph/gprint + my ($mx0, $mx1) = ($ds0, $ds1); + # px0/px1 hold the maximum pecentage data source for gprint + my ($px0, $px1) = ($ps0, $ps1); + if (!defined $q->param('small')) { + # the defs for the maximum values: for the legend ('MAX') and probabely + # for the 'withpeak' graphs + push @args, "DEF:min=$rrd:ds0:MAX", "DEF:mout=$rrd:ds1:MAX"; + ($mx0, $mx1) = ('min', 'mout'); + if (defined $targets{options}{unknaszero}{$log}) { + push @args, "CDEF:umin=$mx0,UN,0,$mx0,IF", + "CDEF:umout=$mx1,UN,0,$mx1,IF"; + ($mx0, $mx1) = ('umin', 'umout'); + } + if ($factor != 1) { + # scale the values. we need a CDEF for this + push @args, "CDEF:fmin=$mx0,$factor,*","CDEF:fmout=$mx1,$factor,*"; + ($mx0, $mx1) = ('fmin', 'fmout'); + } + # draw peak lines if configured + if ($targets{withpeak}{$log} && + substr($png,0,1) =~ /[$targets{withpeak}{$log} ]/) { + push @args, "AREA:".$mx0.$targets{rgb3}{$log}.$l3, + "LINE1:".$mx1.$targets{rgb4}{$log}.$l4; + push @args, "CDEF:pmin=$mx0,$maximum0,/,100,*,$factor,/", + "CDEF:pmout=$mx1,$maximum1,/,100,*,$factor,/"; + ($px0, $px1) = ('pmin', 'pmout'); + if (yesorno($targets{'14all*graphtotal'}{$log})) { + push @args, "CDEF:mtotal=$mx0,$mx1,+", "LINE1:mtotal#ff5050:Total MAX\\l"; + } + } + } + # the commands to draw the values + push @args, "AREA:".$ds0.$targets{rgb1}{$log}.$l1, + "LINE1:".$ds1.$targets{rgb2}{$log}.$l2; + if (!defined $q->param('small')) { + # print the legends + if ($targets{options}{nopercent}{$log}) { + push @args, + "GPRINT:$mx0:MAX:Maximal $li", + "GPRINT:$mx1:MAX:Maximal $lo\\l", + "GPRINT:$ds0:AVERAGE:Average $li", + "GPRINT:$ds1:AVERAGE:Average $lo\\l", + "GPRINT:$ds0:LAST:Current $li", + "GPRINT:$ds1:LAST:Current $lo\\l"; + } else { + push @args, + "GPRINT:$mx0:MAX:Maximal $li", + "GPRINT:$px0:MAX:($ri)", + "GPRINT:$mx1:MAX:Maximal $lo", + "GPRINT:$px1:MAX:($ro)\\l", + "GPRINT:$ds0:AVERAGE:Average $li", + "GPRINT:$ps0:AVERAGE:($ri)", + "GPRINT:$ds1:AVERAGE:Average $lo", + "GPRINT:$ps1:AVERAGE:($ro)\\l", + "GPRINT:$ds0:LAST:Current $li", + "GPRINT:$ps0:LAST:($ri)", + "GPRINT:$ds1:LAST:Current $lo", + "GPRINT:$ps1:LAST:($ro)"; + } + } + # fire up rrdtool + my ($a, $rrdx, $rrdy) = RRDs::graph(@args); + my $e = RRDs::error(); + log_rrdtool_call($config{'14all*rrdtoollog'},$e,'graph',@args); + if ($e) { + if (!-w $pngdir) { + $errstr = "cannot write to graph dir $pngdir\nrrdtool error: $e"; + } elsif (-e $pngfile and !-w _) { + $errstr = "cannot write $pngfile\nrrdtool error: $e"; + } elsif (-e $pngfile) { + if (unlink($pngfile)) { + # try rrdtool a second time + ($a, $rrdx, $rrdy) = RRDs::graph(@args); + $e = RRDs::error(); + log_rrdtool_call($config{'14all*rrdtoollog'},$e,'graph',@args); + $errstr = $e ? $errstr."\nrrdtool error from 2. call: $e" : ''; + } else { + $errstr = "cannot delete file $pngfile: $!"; + } + } else { + $errstr = "cannot create graph\nrrdtool error: $e"; + } + } + unless ($errstr) { + if (open(PNG, "<$pngfile")) { + print $q->header(-type => "image/png", -expires => "+${maxage}s"); + binmode(PNG); binmode(STDOUT); + while(read PNG, my $buf, 16384) { print STDOUT $buf; } + close PNG; + exit 0; + } + $errstr = "cannot read graph file: $!"; + } + ERROR: + if (yesorno($config{'14all*grapherrorstobrowser'})) { + my ($errpic, $format) = gettextpic($errstr); + print $q->header(-type => $format, -expires => 'now'); + binmode(STDOUT); + print $errpic; + exit 0; + } + $log ||= '_'; + if (defined $targets{options}{'14all*errorpic'}{$log} && + open(PNG, $targets{options}{'14all*errorpic'}{$log})) { + print $q->header(-type => "image/png", -expires => 'now'); + binmode(PNG); binmode(STDOUT); + while(read PNG, my $buf,16384) { print STDOUT $buf; } + close PNG; + exit 0; + } + print $q->header(-type => "image/png", -expires => 'now'); + binmode(STDOUT); + print pack("C*", errorpng()); + exit 0; +} elsif (defined $q->param('log')) { + # show the graphics for one target + my $log = $q->param('log'); + print_error($q,"Target '$log' unknown") if (!exists $targets{target}{$log}); + my $title; + # user defined title? + if ($targets{title}{$log}) { + $title = $targets{title}{$log}; + } else { + $title = "MRTG/RRD - Target $log"; + } + my @httphead; + push @httphead, (-expires => '+' . int($config{interval}) . 'm'); + if (yesorno($config{refresh})) { + push @httphead, (-refresh => $config{refresh}); + } + my @htmlhead = (-title => $title, @headeropts, + -bgcolor => $targets{background}{$log}); + if ($targets{addhead}{$log}) { + push @htmlhead, (-head => $targets{addhead}{$log}); + } + print $q->header(@httphead), $q->start_html(@htmlhead); + # user defined header line? (should exist as mrtg requires it) + print $targets{pagetop}{$log},"\n"; + my $rrd = $config{logdir}.$targets{directory}{$log} . $log . '.rrd'; + my $lasttime = RRDs::last($rrd); + log_rrdtool_call($config{'14all*rrdtoollog'},'','last',$rrd); + print $q->hr, + "The statistics were last updated: ",$q->b(scalar(localtime($lasttime))), + $q->hr if $lasttime; + my $sup = $targets{suppress}{$log} || ''; + my $url = "$meurl?log=$log"; + my $tmpcfg = $q->param('cfg'); + $url .= "&cfg=$tmpcfg" if defined $tmpcfg; + $url .= "&png"; + # the header lines and tags for the graphics + my $pngdir = getdirwriteable($config{imagedir}, $targets{directory}{$log}); + if ($sup !~ /d/) { + print $q->h2("'Daily' graph (5 Minute Average)"),"\n", + $q->img({src => "$url=daily", alt => "daily-graph", + getpngsize("$pngdir$log-daily.png")} + ), "\n"; + } + if ($sup !~ /w/) { + print $q->h2("'Weekly' graph (30 Minute Average)"),"\n", + $q->img({src => "$url=weekly", alt => "weekly-graph", + getpngsize("$pngdir$log-weekly.png")} + ), "\n"; + } + if ($sup !~ /m/) { + print $q->h2("'Monthly' graph (2 Hour Average)"),"\n", + $q->img({src => "$url=monthly", alt => "monthly-graph", + getpngsize("$pngdir$log-monthly.png")} + ), "\n"; + } + if ($sup !~ /y/) { + print $q->h2("'Yearly' graph (1 Day Average)"),"\n", + $q->img({src => "$url=yearly", alt => "yearly-graph", + getpngsize("$pngdir$log-yearly.png")} + ), "\n"; + } + if ($targets{pagefoot}{$log}) { + print $targets{pagefoot}{$log}; + } + print $footer; +} else { + # no parameter - show a list of directories and targets without "Directory[...]" (aka root-targets) + my @httphead; + push @httphead, (-expires => '+1d'); # how often do you add targets? + if (yesorno($config{refresh})) { + push @httphead, (-refresh => $config{refresh}); + } + push @headeropts, (-bgcolor => ($config{'14all*background'} || '#ffffff')); + my @htmlhead = (-title => "MRTG/RRD $version", @headeropts); + #if ($targets{addhead}{_}) { + # push @htmlhead, (-head => $targets{addhead}{_}); + #} + print $q->header(@httphead), $q->start_html(@htmlhead); + my (@dirs, %dirs, @logs); + # get the list of directories and "root"-targets + foreach my $tar (@sorted) { + next if $tar =~ m/^[_\$\^]$/; # pseudo targets + if ($targets{directory}{$tar}) { + next if exists $dirs{$targets{directory}{$tar}}; + $dirs{$targets{directory}{$tar}} = $tar; + push @dirs, $targets{directory}{$tar}; + } else { + push @logs, $tar; + } + } + my $cfgstr = (defined $q->param('cfg') ? "&cfg=".$q->param('cfg') : ''); + print $q->h1("Available Targets"),"\n"; + my $confcolumns = $config{'14all*columns'} || 2; + if ($#dirs > -1) { + print $q->h2("Directories"),"\n\\n"; + my $column = 0; + foreach my $tar (@dirs) { + print '' if $column == 0; + (my $link = $tar) =~ s/ /\+/g; + chop $tar; # remove / for display (from ensureSL) + print $q->td($q->a({href => "$meurl?dir=$link$cfgstr"}, + $tar)),"\n"; + $column++; + if ($column >= $confcolumns) { + $column = 0; + print ''; + } + } + if ($column != 0 and $column < $confcolumns) { + print '' x ($confcolumns - $column),"\\n"; + } + print '
     

    '; + } + if ($#logs > -1) { + print $q->h2("Targets"),"\n\\n"; + my $column = 0; + foreach my $tar (@logs) { + my $small = 0; + unless (yesorno($targets{'14all*dontshowindexgraph'}{$tar})) { + $small = $targets{'14all*indexgraph'}{$tar}; + $small = 'daily.s' unless $small; + } + next if $tar =~ m/^[\$\^_]$/; + print '' if $column == 0; + print '\n"; + $column++; + if ($column >= $confcolumns) { + $column = 0; + print ''; + } + } + if ($column != 0 and $column < $confcolumns) { + print '' x ($confcolumns - $column),"\\n"; + } + print '
    ', + $q->p($q->a({href => "$meurl?log=$tar$cfgstr"},$targets{title}{$tar})); + print $q->a({href => "$meurl?log=$tar$cfgstr"}, + $q->img({src => "$meurl?log=$tar&png=$small&small=1$cfgstr", + alt => "index-graph", + getpngsize(getdirwriteable($config{imagedir},'')."$tar-$small-i.png")})) + if $small; + print "\
     
    '; + } + print $footer; +} +exit 0; + +sub print_error($@) +{ + my $q = shift; + print $q->header(), + $q->start_html( + -title => 'MRTG/RRD index.cgi - Script error', + -bgcolor => '#ffffff' + ), + $q->h1('Script Error'), + @_, $q->end_html(); + exit 0; +} + +sub intmax(@) +{ + my (@p) = @_; + my $max = 0; + foreach my $n (@p) { + $max = int($n) if defined $n and int($n) > $max; + } + return $max; +} + +sub yesorno($) +{ + my $opt = shift; + return 0 unless defined $opt; + return 0 if $opt =~ /^((no?)|(false)|0)$/i; + return 1; +} + +sub getdirwriteable($$) +{ + my ($base, $sub) = @_; + $base .= $MRTG_lib::SL . $sub if $sub; + ensureSL(\$base); + if (!-w $base) { + if ($^O =~ m/Win/i) { + $base = $ENV{'TEMP'}; + $base = $ENV{'TMP'} unless $base; + $base = $MRTG_lib::SL unless $base; + ensureSL(\$base); + } else { + $base = '/tmp/'; + } + } + return $base; +} + +use IO::File; + +sub pngstring() { return chr(137)."PNG".chr(13).chr(10).chr(26).chr(10); }; + +sub getpngsize($) +{ + my ($file) = @_; + my $fh = new IO::File $file; + return () unless defined $fh; + my $line; + if (sysread($fh, $line, 8) != 8 or $line ne pngstring()) { + $fh->close; + return (); + } + CHUNKS: while(1) { + last CHUNKS if (sysread($fh, $line, 8) != 8); + my ($chunksize, $type) = unpack "Na4", $line; + if ($type ne "IHDR") { + last CHUNKS if (sysread($fh, $line, $chunksize + 4) != $chunksize + 4); + next CHUNKS; + } + last CHUNKS if (sysread($fh, $line, 8) != 8); + $fh->close; + my ($x, $y) = unpack("NN", $line); + return ('-width' => "$x", '-height' => "$y"); + } + $fh->close; + return (); +} + +# this data contains a small png with the text: +# "error: cannot create graph" + +sub errorpng() +{ + return ( + 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,187,0,0,0,29,4,3,0, + 0,0,0,251,0,170,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,30,80, + 76,84,69,255,0,0,255,93,93,255,128,128,255,155,155,255,176,176,255,195, + 195,255,212,212,255,227,227,255,241,241,255,255,255,17,191,146,253,0,0, + 0,56,116,69,88,116,83,111,102,116,119,97,114,101,0,88,86,32,86,101,114, + 115,105,111,110,32,51,46,49,48,97,32,32,82,101,118,58,32,49,50,47,50,57, + 47,57,52,32,40,80,78,71,32,112,97,116,99,104,32,49,46,50,41,221,21,46,73, + 0,0,2,40,73,68,65,84,120,218,237,147,177,107,219,64,20,198,159,34,233,92, + 109,130,180,132,108,55,180,78,189,169,113,8,220,166,80,106,208,230,102, + 48,237,118,56,246,153,219,28,7,2,183,165,77,23,109,142,101,157,244,254, + 219,62,73,198,113,106,211,150,144,108,254,166,143,167,79,63,221,125,167, + 3,216,107,175,189,94,65,136,56,223,26,58,166,224,207,71,6,114,3,175,148, + 220,10,136,66,47,183,134,44,254,115,114,48,252,55,126,87,192,92,248,24, + 254,237,173,70,110,246,95,120,182,184,17,231,242,4,103,160,79,34,213,12, + 117,148,224,204,205,211,159,96,205,18,24,254,162,26,105,189,198,66,29,149, + 96,80,10,172,29,64,154,91,55,83,30,22,92,124,43,33,152,60,86,75,229,196, + 172,204,68,42,83,85,114,157,70,4,97,182,218,121,121,150,187,56,41,0,111, + 75,254,253,54,141,197,13,64,203,154,184,138,78,114,223,158,47,222,229,156, + 28,128,95,104,235,150,182,115,159,244,133,53,211,160,208,215,27,71,43,153, + 253,36,238,223,23,96,250,250,42,84,43,188,55,58,180,174,117,16,202,208, + 156,166,97,114,87,237,185,211,239,72,138,230,78,217,30,126,200,220,204, + 35,199,225,227,67,139,240,167,189,11,33,197,244,120,17,60,180,178,39,229, + 60,128,136,217,156,74,211,117,227,53,30,18,164,29,211,115,11,186,155,1, + 155,87,120,93,157,123,204,104,77,145,65,194,215,14,68,228,90,119,9,30,173, + 148,108,22,72,246,20,63,167,4,91,64,71,234,213,48,116,204,89,193,31,241, + 57,28,173,240,46,167,104,214,237,30,229,135,21,158,92,8,162,239,85,209, + 100,22,72,17,251,187,241,94,93,14,64,151,6,250,171,143,108,225,173,241, + 235,114,146,233,177,172,162,142,13,174,91,85,57,228,160,41,39,3,205,147, + 166,156,77,60,98,86,227,65,163,13,117,243,189,35,196,31,30,150,107,124, + 36,176,228,111,170,67,71,12,235,232,172,133,101,118,128,146,28,253,160, + 77,52,193,84,138,20,227,77,188,82,106,232,73,104,115,120,171,46,160,71, + 3,26,58,131,49,135,193,229,136,238,141,130,17,244,184,171,46,193,165,39, + 78,239,170,142,142,67,71,125,30,194,32,38,71,249,193,200,82,212,31,183, + 99,241,101,76,247,207,219,125,223,158,41,49,111,126,134,202,70,47,9,110, + 228,151,230,238,21,241,123,237,245,162,250,13,181,158,203,16,233,3,210, + 153,0,0,0,7,116,73,77,69,7,208,1,19,13,28,15,223,54,180,209,0,0,0,0,73, + 69,78,68,174,66,96,130 + ); +} + +sub gettextpic($) { + my ($text) = @_; + my @textsplit = split(/\n/, $text); + my $len = 0; + my $max = sub { $_[0] > $_[1] ? $_[0] : $_[1] }; + my @rrdargs; + foreach (@textsplit) { + $len = &$max($len, length($_)); + push @rrdargs, "COMMENT:$_\\l"; + } + eval { require GD; 1; }; + unless ($@) { + my $ys = @textsplit * (GD::gdMediumBoldFont()->height + 5); + my $xs = $len * GD::gdMediumBoldFont()->width(); + my $im = new GD::Image($xs + 20, $ys + 20); + my $back = $im->colorAllocate(255,255,255); + $im->transparent($back); + my $red = $im->colorAllocate(255,0,0); + $im->filledRectangle(0,0,$xs-1,$ys-1,$back); + my $starty = 10; + foreach $text (@textsplit) { + $im->string(GD::gdMediumBoldFont(), 10, $starty, $text, $red); + $starty += 5 + GD::gdMediumBoldFont()->height; + } + binmode(STDOUT); + if ($GD::VERSION lt '1.20') { + #eval 'print $im->gif'; + return ($im->gif(), 'image/gif'); + } elsif ($GD::VERSION ge '1.20') { + return ($im->png(), 'image/png'); + } + } + if ($ENV{MOD_PERL}) { + # forking a RRDs child doesn't work with mod_perl + return (pack("C*", errorpng()), 'image/png'); + } + # create a graphic with rrdtool + $len = &$max($len*6-60,50); + unshift @rrdargs, ('-', '-w', $len, '-h', 10, '-c', 'FONT#ff0000'); + my $pid = open(P, "-|"); + unless (defined $pid) { + return (pack("C*", errorpng()), 'image/png'); + } + unless ($pid) { + RRDs::graph(@rrdargs); + exit 0; + } + local $/ = undef; + my $png =

    ; + close P; + unless (defined $png) { + return (pack("C*", errorpng()), 'image/png'); + } + return ($png, 'image/png'); +} + +sub log_rrdtool_call($$@) { + my $logfile = shift; + my $error = shift; + return unless yesorno($logfile); + unless (open(LOG, '>>'.$logfile)) { + print STDERR "cannot log rrdtool call: $!\n"; + return; + } + print LOG "\n# call to rrdtool:\nrrdtool @_\n"; + if ($error) { + print LOG "# gave ERROR: $error\n"; + } else { + print LOG "# completed without error\n"; + } + close LOG; +} + + diff --git a/ljcom/src/ibill-templates/generate.pl b/ljcom/src/ibill-templates/generate.pl new file mode 100755 index 0000000..e70fb06 --- /dev/null +++ b/ljcom/src/ibill-templates/generate.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl +# + +use strict; +use Net::FTP; + +my $dir = "$ENV{'LJHOME'}/src/ibill-templates/"; +my @accts = qw(100 101 102); + +foreach my $acct (@accts) +{ + my $file = "g91961$acct.hmf"; + print "Generating $file...\n"; + open (T, "$dir/template.html") + or die "Can't open $dir/template.html.\n"; + open (P, ">>$dir/$file") + or die "Can't write to $file\n"; + while () { + s/\[SACCT\]/$acct/g; + print P $_; + } +} + +print "Uploading to ftp.ibill.com...\n"; +print "Enter password (will echo): "; +my $pass = ; +chop $pass; + +my $ftp = Net::FTP->new("ftp.ibill.com"); +unless ($ftp->login("a91961", $pass)) { + die "Couldn't login.\n"; +} +foreach my $acct (@accts) +{ + my $file = "g91961$acct.hmf"; + print "Putting: $file\n"; + $ftp->put($file); +} +$ftp->quit; +print "Done.\n"; + + diff --git a/ljcom/src/ibill-templates/template.html b/ljcom/src/ibill-templates/template.html new file mode 100755 index 0000000..ec629ec --- /dev/null +++ b/ljcom/src/ibill-templates/template.html @@ -0,0 +1,67 @@ + + +Webgood Page + + + + +

    + + +
    + +
    +
    + +Approved + +
    +
    + + +Write down the following information immediately: +
    +
    +Transaction #: %%TRAN? +
    +PIN Code: [SACCT]-%%CODE? +
    +
    +You will NOT see this information again! +
    +
    +
    + +If you ever have any billing questions, you will need to refer to the numbers above. +
    +
    +
    +
    + + + + + +
    + + +
    +
    + + +If you have any questions, comments or encounter any problems, please contact accounts@livejournal.com + +
    +
    +
    + + +  +
    + +
    + + + + + diff --git a/ljcom/src/ljcom/myoverlap.pl b/ljcom/src/ljcom/myoverlap.pl new file mode 100755 index 0000000..52835d3 --- /dev/null +++ b/ljcom/src/ljcom/myoverlap.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# + +use File::Copy; + +unless (-e "/etc/my.cnf") { + symlink "/etc/mysql/my.cnf", "/etc/my.cnf"; +} + +my %dfile; +foreach my $p (qw(mysql-common mysql-client mysql-server)) +{ + foreach my $f (`dpkg -L $p`) { + chomp $f; + next unless -f $f; + die "Dup: $f\n" if defined $dfile{$f}; + $dfile{$f} = $p; + } +} +die "No mysql-server package installed?\n" unless %dfile; + +my $mdir = readlink '/usr/src/mysql'; +die "Symlink /usr/src/mysql does not point to binary mysql untar dir.\n" unless $mdir; +chdir $mdir or die; + +my @mfiles; +my %cp; +foreach (`find . -type f`) { + chomp; + s!^\./!!; + next if /^(mysql-test|sql-bench|support-files|tests|include|man)\//; + next if m!^bin/safe_mysqld!; + + my $d = "/usr/$_"; + if ($_ eq "bin/mysqld") { $d = "/usr/sbin/mysqld"; } + + if ($dfile{$d}) { + $cp{$_} = $d; + print " MATCH: $_ -> $cp{$_}\n"; + copy ($_, $d) or die "error copying file $_"; + next; + } + push @mfiles, $_; +} +foreach (@mfiles) { + print "not copied: $_\n"; +} + diff --git a/ljcom/src/mod_latency/mod_latency.c b/ljcom/src/mod_latency/mod_latency.c new file mode 100644 index 0000000..1201e05 --- /dev/null +++ b/ljcom/src/mod_latency/mod_latency.c @@ -0,0 +1,90 @@ +/* + * mod_latency.c -- + * + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_main.h" + +#include + +module MODULE_VAR_EXPORT latency_module; + +typedef struct lcfg { + int timeset; /* This is basically pointless, but in the future + * it could be used to see if the default values + * being used or not. + */ + struct timespec latency_val; +} lcfg; + +const char *latency_set(cmd_parms *cmd, void *mconfig, const char *arg) +{ + lcfg *cfg = (lcfg *) mconfig; + + cfg->timeset = 1; + cfg->latency_val.tv_nsec = atoi(arg) * 1e6 - 1; + return NULL; +} + +static int do_pause (request_rec *r) +{ + lcfg *cfg; + + cfg = ap_get_module_config(r->per_dir_config, &latency_module); + nanosleep(&cfg->latency_val, NULL); + return OK; +} + +/* Note the ACCESS_CONF bit there. That means the directive can be + * set anywhere inside a or thing. If this + * is too restricting, I suggest changing it to "OR_OPTIONS" + * That allows you to set it anywhere, and in .htaccess files where + * AllowOverride Options is set in the directory. + */ +command_rec latency_cmds[] = { + { "SetLatency", latency_set, NULL, ACCESS_CONF, TAKE1, NULL }, + { NULL } +}; + +/* Directory based values. I won't write merge functions, since there is + * only one value to care about. It defaults to the nearest one. + */ +static void *latency_create_dir_config(pool *p, char *dirspec) +{ + lcfg *cfg; + /* Allocate memory out of the supplied pool. */ + cfg = (lcfg *) ap_pcalloc(p, sizeof(lcfg)); + /* Set default values. */ + cfg->timeset = 1; + cfg->latency_val.tv_sec = 0; + cfg->latency_val.tv_nsec = 350 * 1e6; + /* All done. Return it. */ + return (void *) cfg; +} + +module MODULE_VAR_EXPORT latency_module = { + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + latency_create_dir_config, /* per-dir config creator */ + NULL, /* per-dir config merger (default: override) */ + NULL, /* per-server config creator */ + NULL, /* per-server config merger (default: override) */ + latency_cmds, /* command table */ + NULL, /* [9] content handlers */ + NULL, /* [2] URI-to-filename translation */ + NULL, /* [5] authenticate user_id */ + NULL, /* [6] authorize user_id */ + NULL, /* [4] check access (based on src & http headers) */ + NULL, /* [7] check/set MIME type */ + NULL, /* [8] fixups */ + NULL, /* [10] logger */ + do_pause, /* [3] header-parser */ + NULL, /* process initialization */ + NULL, /* process exit/cleanup */ + NULL /* [1] post read-request handling */ +}; diff --git a/ljcom/src/phonepost/README b/ljcom/src/phonepost/README new file mode 100644 index 0000000..e3c691d --- /dev/null +++ b/ljcom/src/phonepost/README @@ -0,0 +1,4 @@ +These files are mostly provided as a reference for someone following +in our footsteps. There is some work left to do, but this should put +you well on your way. + diff --git a/ljcom/src/phonepost/agi-bin/livejournal b/ljcom/src/phonepost/agi-bin/livejournal new file mode 100755 index 0000000..6d8b2fc --- /dev/null +++ b/ljcom/src/phonepost/agi-bin/livejournal @@ -0,0 +1,167 @@ +#!/usr/bin/perl +# vim: set ts=4 sw=4 et : + +use strict; +use POSIX qw(strftime); + +use lib "$ENV{LJHOME}/cgi-bin"; +BEGIN { + require "phonepost-asterisk.pl"; + require "mp3encode.pl"; + + $LJ::PHONESPOOL = $ENV{'LJ_PHONESPOOL'} || $LJ::PHONESPOOL; +} + +use Asterisk::AGI; + +# in milliseconds. +use constant POST_TIME_LIMIT => 3 * 60 * 1_000; + +use constant MENU_REPLAY => 1; +use constant MENU_RECORD => 2; +use constant MENU_POST_PUBLIC => 3; +use constant MENU_POST_FRIENDS => 4; +use constant MENU_POST_PRIVATE => 5; +use constant MENU_POST_REPEAT => 9; + +my $AGI = new Asterisk::AGI; + +my %input = $AGI->ReadParse(); +while (my ($k, $v) = each %input) { + print STDERR " $k -> $v\n"; +} + +$AGI->setcallback(\&hangup); +sub hangup { + my ($returncode) = @_; + print STDERR "HANGUP: User Hungup ($returncode)\n"; + exit($returncode); +} + + +$AGI->stream_file('livejournal/welcome'); + +my $phone; +my $u; + +foreach my $i (1..3) { + if ($input{callerid} =~ /(\d{10,})/) { + $phone = $1; + + # if they have caller id, offer to use it. + # they'll hit pound if they want it, causing this to return zero. + my $res = $AGI->get_data('livejournal/phonecid', 30_000, 15); + + # maybe they entered a phone number. + $phone = $res if $res; + } + + unless ($phone) { + $phone = $AGI->get_data('livejournal/phone', 30_000, 15); + } + + $phone = LJ::PhonePost::canonicalize_phone($phone); + + my $pin = $AGI->get_data('livejournal/pin', 20_000, 6); + $u = LJ::PhonePost::get_user($phone, $pin); + if ($u) { + last; + } else { + $AGI->stream_file('livejournal/badlogin'); + } +} + +exit(0) unless $u; + +if (LJ::PhonePost::over_disk_quota($u)) { + $AGI->stream_file('livejournal/space'); + $AGI->stream_file('livejournal/support'); + exit(0); +} +if (LJ::PhonePost::over_post_quota($u)) { + $AGI->stream_file('livejournal/quota'); + $AGI->stream_file('livejournal/support'); + exit(0); +} + +my $posttime = time(); +my $filename = "$u->{userid}-$posttime"; +my $inpath = $PHONESPOOL . "/in/$filename"; + +my $menuoption = MENU_RECORD; +my $security; +while ($menuoption) { + if ($menuoption == MENU_REPLAY) { + # use get_data here to play the message back, + # so they can quit out of the playback by pressing a key. + # we wait 1ms after the message is done, + # because waiting 0ms means wait forever (i think)? + $AGI->get_data($inpath, 1, 1); + } elsif ($menuoption == MENU_RECORD) { + $AGI->get_data('livejournal/record', 1, 1); + # XXX record this. $AGI->stream_file('livejournal/beep1'); + $AGI->stream_file('beep'); + $AGI->record($inpath, "wav", '#', POST_TIME_LIMIT); + } elsif ($menuoption == MENU_POST_PUBLIC) { + $security = 'public'; + last; + } elsif ($menuoption == MENU_POST_FRIENDS) { + $security = 'friends'; + last; + } elsif ($menuoption == MENU_POST_PRIVATE) { + $security = 'private'; + last; + } elsif ($menuoption == MENU_POST_REPEAT) { + # do nothing. + } else { + $AGI->stream_file('livejournal/unknown'); + } + $menuoption = $AGI->get_data('livejournal/menu', 10_000, 1); +} + +# did they manage to exit the menu without choosing to post. +# (timeout? the pound key?) anyway, hangup. +exit(0) unless $security; + +my $wavpath = $PHONESPOOL . "/in/$filename.wav"; +my $mp3path = $PHONESPOOL . "/out/$filename.mp3"; + +my $tzoffset = LJ::PhonePost::get_user_timezone($u); + +# mp3 id3 tag information. text fields must be <= 30 chars. +my $attr = { + title => strftime("%F %R", gmtime($posttime + $tzoffset*3600)), + artist => substr($u->{user}, 0, 30), + comment => substr($LJ::SITENAME, 0, 30), + year => (gmtime($posttime + $tzoffset*3600))[5]+1900, +}; + +unless (LJ::PhonePost::encode_mp3($attr, $wavpath, $mp3path)) { + $AGI->stream_file('livejournal/error'); + # XXX unlink files? + exit(-1); +} + +unlink($wavpath); + +my $bid = LJ::PhonePost::store_audio($u, $mp3path); +unless ($bid) { + $AGI->stream_file('livejournal/error'); + exit(-1); +} + +unless (LJ::PhonePost::post_audio($u, $posttime, $security, $bid)) { + # XXX can this return an error, too? + #$AGI->stream_file('livejournal/queued'); + $AGI->stream_file('livejournal/error'); + exit(-1); +} + +unlink($mp3path); + +$AGI->stream_file('livejournal/posted'); + +$AGI->stream_file('livejournal/goat') if rand() < 0.1; + +exit(0); + diff --git a/ljcom/src/phonepost/debian/README b/ljcom/src/phonepost/debian/README new file mode 100644 index 0000000..9e93273 --- /dev/null +++ b/ljcom/src/phonepost/debian/README @@ -0,0 +1,5 @@ +This is a patch against Asterisk CVS: + - Debian package (had to apply a lot of the existing Debian patch by hand) + - Snip off the end of a phone conversation from AGI's record when there's a + DTMF digit so it doesn't show up in a recording. + diff --git a/ljcom/src/phonepost/debian/asterisk-deb-20030912.patch b/ljcom/src/phonepost/debian/asterisk-deb-20030912.patch new file mode 100644 index 0000000..41853fd --- /dev/null +++ b/ljcom/src/phonepost/debian/asterisk-deb-20030912.patch @@ -0,0 +1,719 @@ +? build-arch-stamp +? build-indep-stamp +? configure-stamp +? debian +? doc/api +? include/linux +Index: Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/Makefile,v +retrieving revision 1.27 +diff -u -r1.27 Makefile +--- Makefile 2 Sep 2003 00:33:42 -0000 1.27 ++++ Makefile 13 Sep 2003 00:36:00 -0000 +@@ -19,10 +19,10 @@ + OSARCH=$(shell uname -s) + + ifeq (${OSARCH},Linux) +-PROC=$(shell uname -m) ++#PROC=$(shell uname -m) + endif + # Pentium Pro Optimize +-#PROC=i686 ++PROC=i686 + + # Pentium & VIA processors optimize + #PROC=i586 +@@ -39,7 +39,7 @@ + #K6OPT = -DK6OPT + + #Tell gcc to optimize the asterisk's code +-OPTIMIZE=-O6 ++OPTIMIZE=-O2 + + #Include debug symbols in the executables (-g) and profiling info (-pg) + DEBUG=-g #-pg +@@ -64,7 +64,7 @@ + + # Where to install asterisk after compiling + # Default -> leave empty +-INSTALL_PREFIX= ++INSTALL_PREFIX=$(DESTDIR) + + # Original busydetect routine + BUSYDETECT = #-DBUSYDETECT +@@ -87,9 +87,14 @@ + ASTCONFPATH=$(ASTETCDIR)/asterisk.conf + ASTBINDIR=$(INSTALL_PREFIX)/usr/bin + ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin +-ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run +- ++ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run/asterisk + ++# By default asterisk installs sound files under /var/lib/asterisk, ++# according to the FHS these files should be in /usr/share/asterisk ++# As they are architecture independant, thus: ++# ++ASTDATADIR=$(INSTALL_PREFIX)/usr/share/asterisk ++ + MODULES_DIR=$(ASTLIBDIR)/modules + AGI_DIR=$(ASTVARLIBDIR)/agi-bin + +@@ -97,14 +102,14 @@ + CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY + CFLAGS+=$(OPTIMIZE) + CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) +-CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) ++CFLAGS+=$(shell if uname -m | grep -q "ppc\|arm\|s390"; then echo "-fsigned-char"; fi) + ifeq (${OSARCH},OpenBSD) + CFLAGS+=-pthread + endif + + CFLAGS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi) + +-LIBEDIT=editline/libedit.a ++LIBEDIT=-ledit + + ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then echo "CVS-`date +"%D-%T"`"; fi; fi) + HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi) +@@ -116,6 +121,7 @@ + CFLAGS+=-DASTVARLIBDIR=\"$(ASTVARLIBDIR)\" + CFLAGS+=-DASTVARRUNDIR=\"$(ASTVARRUNDIR)\" + CFLAGS+=-DASTSPOOLDIR=\"$(ASTSPOOLDIR)\" ++CFLAGS+=-DASTDATADIR=\"$(ASTDATADIR)\" + CFLAGS+=-DASTLOGDIR=\"$(ASTLOGDIR)\" + CFLAGS+=-DASTCONFPATH=\"$(ASTCONFPATH)\" + CFLAGS+=-DASTMODDIR=\"$(MODULES_DIR)\" +@@ -152,17 +158,6 @@ + + all: depend asterisk subdirs + +-editline/config.h: +- @if [ -d editline ]; then \ +- cd editline && unset CFLAGS LIBS && ./configure ; \ +- else \ +- echo "You need to do a cvs update -d not just cvs update"; \ +- exit 1; \ +- fi +- +-editline/libedit.a: editline/config.h +- $(MAKE) -C editline libedit.a +- + db1-ast/libdb1.a: + @if [ -d db1-ast ]; then \ + $(MAKE) -C db1-ast libdb1.a ; \ +@@ -199,7 +194,7 @@ + ./make_build_h + endif + +-asterisk: editline/libedit.a db1-ast/libdb1.a $(OBJS) ++asterisk: db1-ast/libdb1.a $(OBJS) + $(CC) $(DEBUG) -o asterisk -rdynamic $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a + + subdirs: +@@ -214,10 +209,10 @@ + $(MAKE) -C db1-ast clean + + datafiles: all +- mkdir -p $(ASTVARLIBDIR)/sounds/digits ++ mkdir -p $(ASTDATADIR)/sounds/digits + for x in sounds/digits/*.gsm; do \ + if grep -q "^%`basename $$x`%" sounds.txt; then \ +- install $$x $(ASTVARLIBDIR)/sounds/digits ; \ ++ install -m 644 $$x $(ASTDATADIR)/sounds/digits ; \ + else \ + echo "No description for $$x"; \ + exit 1; \ +@@ -225,16 +220,16 @@ + done + for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-*; do \ + if grep -q "^%`basename $$x`%" sounds.txt; then \ +- install $$x $(ASTVARLIBDIR)/sounds ; \ ++ install -m 644 $$x $(ASTDATADIR)/sounds ; \ + else \ + echo "No description for $$x"; \ + exit 1; \ + fi; \ + done +- mkdir -p $(ASTVARLIBDIR)/mohmp3 +- mkdir -p $(ASTVARLIBDIR)/images ++ mkdir -p $(ASTDATADIR)/mohmp3 ++ mkdir -p $(ASTDATADIR)/images + for x in images/*.jpg; do \ +- install $$x $(ASTVARLIBDIR)/images ; \ ++ install -m 644 $$x $(ASTDATADIR)/images ; \ + done + mkdir -p $(AGI_DIR) + +@@ -254,14 +249,15 @@ + mkdir -p $(ASTBINDIR) + mkdir -p $(ASTSBINDIR) + mkdir -p $(ASTVARRUNDIR) ++ mkdir -p $(ASTDATADIR) + mkdir -p $(ASTSPOOLDIR)/voicemail + install -m 755 asterisk $(ASTSBINDIR)/ + install -m 755 astgenkey $(ASTSBINDIR)/ + install -m 755 safe_asterisk $(ASTSBINDIR)/ + for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done + install -d $(ASTHEADERDIR) +- install include/asterisk/*.h $(ASTHEADERDIR) +- rm -f $(ASTVARLIBDIR)/sounds/vm ++ install -m 644 include/asterisk/*.h $(ASTHEADERDIR) ++ rm -f $(ASTDATADIR)/sounds/vm + rm -f $(ASTVARLIBDIR)/sounds/voicemail + if [ ! -h $(ASTSPOOLDIR)/vm ] && [ -d $(ASTSPOOLDIR)/vm ]; then \ + mv $(ASTSPOOLDIR)/vm $(ASTSPOOLDIR)/voicemail/default; \ +@@ -272,12 +268,11 @@ + ln -s $(ASTSPOOLDIR)/voicemail/default $(ASTSPOOLDIR)/vm + rm -f $(MODULES_DIR)/chan_ixj.so + rm -f $(MODULES_DIR)/chan_tor.so +- mkdir -p $(ASTVARLIBDIR)/sounds ++ mkdir -p $(ASTDATADIR)/sounds + mkdir -p $(ASTLOGDIR)/cdr-csv + mkdir -p $(ASTVARLIBDIR)/keys + install -m 644 keys/iaxtel.pub $(ASTVARLIBDIR)/keys +- ( cd $(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . ) +- ( cd $(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . ) ++ ( cd $(ASTDATADIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . ) + @echo " +---- Asterisk Installation Complete -------+" + @echo " + +" + @echo " + YOU MUST READ THE SECURITY DOCUMENT +" +@@ -318,7 +313,7 @@ + if [ -f $(ASTETCDIR)/`basename $$x .sample` ]; then \ + mv -f $(ASTETCDIR)/`basename $$x .sample` $(ASTETCDIR)/`basename $$x .sample`.old ; \ + fi ; \ +- install $$x $(ASTETCDIR)/`basename $$x .sample` ;\ ++ install -m 644 $$x $(ASTETCDIR)/`basename $$x .sample` ;\ + done + echo "[directories]" > $(ASTETCDIR)/asterisk.conf + echo "astetcdir => $(ASTETCDIR)" >> $(ASTETCDIR)/asterisk.conf +@@ -330,23 +325,23 @@ + echo "astlogdir => $(ASTLOGDIR)" >> $(ASTETCDIR)/asterisk.conf + for x in sounds/demo-*; do \ + if grep -q "^%`basename $$x`%" sounds.txt; then \ +- install $$x $(ASTVARLIBDIR)/sounds ; \ ++ install $$x $(ASTDATADIR)/sounds ; \ + else \ + echo "No description for $$x"; \ + exit 1; \ + fi; \ + done + for x in sounds/*.mp3; do \ +- install $$x $(ASTVARLIBDIR)/mohmp3 ; \ ++ install -m 644 $$x $(ASTDATADIR)/mohmp3 ; \ + done + mkdir -p $(ASTSPOOLDIR)/voicemail/default/1234/INBOX +- :> $(ASTVARLIBDIR)/sounds/voicemail/default/1234/unavail.gsm ++ :> $(ASTSPOOLDIR)/vm/1234/unavail.gsm + for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \ +- cat $(ASTVARLIBDIR)/sounds/$$x.gsm >> $(ASTVARLIBDIR)/sounds/voicemail/default/1234/unavail.gsm ; \ ++ cat $(ASTDATADIR)/sounds/$$x.gsm >> $(ASTSPOOLDIR)/vm/1234/unavail.gsm ; \ + done +- :> $(ASTVARLIBDIR)/sounds/voicemail/default/1234/busy.gsm ++ :> $(ASTSPOOLDIR)/vm/1234/busy.gsm + for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \ +- cat $(ASTVARLIBDIR)/sounds/$$x.gsm >> $(ASTVARLIBDIR)/sounds/voicemail/default/1234/busy.gsm ; \ ++ cat $(ASTDATADIR)/sounds/$$x.gsm >> $(ASTSPOOLDIR)/vm/1234/busy.gsm ; \ + done + + webvmail: +Index: astconf.h +=================================================================== +RCS file: /usr/cvsroot/asterisk/astconf.h,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 astconf.h +--- astconf.h 12 Feb 2003 13:59:13 -0000 1.1.1.1 ++++ astconf.h 13 Sep 2003 00:36:00 -0000 +@@ -28,5 +28,6 @@ + extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH]; + extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH]; + extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH]; ++extern char ast_config_AST_DATA_DIR[AST_CONFIG_MAX_PATH]; + + #endif +Index: asterisk-ng-doxygen +=================================================================== +RCS file: /usr/cvsroot/asterisk/asterisk-ng-doxygen,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 asterisk-ng-doxygen +--- asterisk-ng-doxygen 12 Feb 2003 13:59:13 -0000 1.1.1.1 ++++ asterisk-ng-doxygen 13 Sep 2003 00:36:01 -0000 +@@ -707,7 +707,7 @@ + # toolkit from AT&T and Lucent Bell Labs. The other options in this section + # have no effect if this option is set to NO (the default) + +-HAVE_DOT = YES ++HAVE_DOT = NO + + # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen + # will generate a graph for each documented class showing the direct and +Index: asterisk.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/asterisk.c,v +retrieving revision 1.20 +diff -u -r1.20 asterisk.c +--- asterisk.c 8 Sep 2003 16:48:06 -0000 1.20 ++++ asterisk.c 13 Sep 2003 00:36:02 -0000 +@@ -104,6 +104,7 @@ + char ast_config_AST_PID[AST_CONFIG_MAX_PATH]; + char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH]; + char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH]; ++char ast_config_AST_DATA_DIR[AST_CONFIG_MAX_PATH]; + + int ast_register_atexit(void (*func)(void)) + { +@@ -1152,6 +1153,7 @@ + strncpy((char *)ast_config_AST_PID,AST_PID,sizeof(ast_config_AST_PID)-1); + strncpy((char *)ast_config_AST_SOCKET,AST_SOCKET,sizeof(ast_config_AST_SOCKET)-1); + strncpy((char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,sizeof(ast_config_AST_RUN_DIR)-1); ++ strncpy((char *)ast_config_AST_DATA_DIR,AST_DATA_DIR,sizeof(ast_config_AST_DATA_DIR)-1); + + /* no asterisk.conf? no problem, use buildtime config! */ + if (!cfg) { +@@ -1213,13 +1215,6 @@ + tdd_init(); + if (getenv("HOME")) + snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME")); +- /* Check if we're root */ +- /* +- if (geteuid()) { +- ast_log(LOG_ERROR, "Must be run as root\n"); +- exit(1); +- } +- */ + /* Check for options */ + while((c=getopt(argc, argv, "hfdvqprgcinx:C:")) != EOF) { + switch(c) { +Index: asterisk.h +=================================================================== +RCS file: /usr/cvsroot/asterisk/asterisk.h,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 asterisk.h +--- asterisk.h 12 Feb 2003 13:59:13 -0000 1.1.1.1 ++++ asterisk.h 13 Sep 2003 00:36:02 -0000 +@@ -28,11 +28,12 @@ + #define AST_AGI_DIR ASTAGIDIR + #define AST_KEY_DIR ASTVARLIBDIR "/keys" + #define AST_DB ASTVARLIBDIR "/astdb" ++#define AST_DATA_DIR ASTDATADIR + + #define AST_CONFIG_FILE ASTCONFPATH + +-#define AST_SOUNDS AST_VAR_DIR "/sounds" +-#define AST_IMAGES AST_VAR_DIR "/images" ++#define AST_SOUNDS ASTDATADIR "/sounds" ++#define AST_IMAGES ASTDATADIR "/images" + + /* Provided by module.c */ + extern int load_modules(void); +Index: cli.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/cli.c,v +retrieving revision 1.9 +diff -u -r1.9 cli.c +--- cli.c 13 Aug 2003 15:25:16 -0000 1.9 ++++ cli.c 13 Sep 2003 00:36:02 -0000 +@@ -25,7 +25,7 @@ + #include + #include + /* For rl_filename_completion */ +-#include "editline/readline/readline.h" ++#include "readline/readline.h" + /* For module directory */ + #include "asterisk.h" + #include "build.h" +Index: file.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/file.c,v +retrieving revision 1.21 +diff -u -r1.21 file.c +--- file.c 16 Aug 2003 05:10:35 -0000 1.21 ++++ file.c 13 Sep 2003 00:36:03 -0000 +@@ -275,7 +275,7 @@ + { + char *fn; + char tmp[AST_CONFIG_MAX_PATH]; +- snprintf(tmp,sizeof(tmp)-1,"%s/%s",(char *)ast_config_AST_VAR_DIR,"sounds"); ++ snprintf(tmp,sizeof(tmp)-1,"%s/%s",(char *)ast_config_AST_DATA_DIR,"sounds"); + fn = malloc(strlen(tmp) + strlen(filename) + strlen(ext) + 10); + if (fn) { + if (filename[0] == '/') +Index: image.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/image.c,v +retrieving revision 1.3 +diff -u -r1.3 image.c +--- image.c 16 Aug 2003 05:10:35 -0000 1.3 ++++ image.c 13 Sep 2003 00:36:03 -0000 +@@ -95,9 +95,9 @@ + snprintf(buf, len, "%s.%s", filename, ext); + } else { + if (preflang && strlen(preflang)) +- snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_VAR_DIR, "images", filename, preflang, ext); ++ snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_DATA_DIR, "images", filename, preflang, ext); + else +- snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_VAR_DIR, "images", filename, ext); ++ snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_DATA_DIR, "images", filename, ext); + } + } + +Index: apps/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/Makefile,v +retrieving revision 1.16 +diff -u -r1.16 Makefile +--- apps/Makefile 4 Sep 2003 04:40:37 -0000 1.16 ++++ apps/Makefile 13 Sep 2003 00:36:03 -0000 +@@ -40,10 +40,10 @@ + #APPS+=app_sql_postgres.so + #APPS+=app_sql_odbc.so + +-APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so" ; fi) ++APPS+=$(shell if [ -f ../include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so" ; fi) + #APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi) + +-CFLAGS+=-fPIC ++CFLAGS+=-fPIC -DPIC + + all: $(APPS) + +@@ -60,7 +60,7 @@ + for x in $(APPS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done + + app_todd.o: app_todd.c +- gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c ++ gcc -pipe $(OPTIMIZE) -g -Iinclude -I../include -D_REENTRANT -march=$(PROC) -DDO_CRASH -c -o app_todd.o app_todd.c + + app_todd.so: app_todd.o + $(CC) -shared -Xlinker -x -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto +@@ -82,7 +82,7 @@ + $(CC) -shared -Xlinker -x -o $@ $< -lodbc + + look: look.c +- gcc -pipe -O6 -g look.c -o look -lncurses ++ gcc -pipe -O2 -g look.c -o look -lncurses + + ifneq ($(wildcard .depend),) + include .depend +Index: apps/app_agi.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/app_agi.c,v +retrieving revision 1.12 +diff -u -r1.12 app_agi.c +--- apps/app_agi.c 8 Sep 2003 16:48:06 -0000 1.12 ++++ apps/app_agi.c 13 Sep 2003 00:36:04 -0000 +@@ -547,6 +547,10 @@ + case AST_FRAME_DTMF: + if (strchr(argv[4], f->subclass)) { + /* This is an interrupting chracter */ ++ /* Strip off the last 1/4 second of it ++ * to get rid of the beep. */ ++ ast_stream_rewind(fs, 250); ++ ast_truncstream(fs); + sample_offset = ast_tellstream(fs); + fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); + ast_closestream(fs); +@@ -581,12 +585,12 @@ + gettimeofday(&tv, NULL); + if (gotsilence) + break; +- } ++ } + + if (gotsilence) { + ast_stream_rewind(fs, silence-1000); + ast_truncstream(fs); +- } ++ } + fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); + ast_closestream(fs); + } else +Index: apps/app_flash.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/app_flash.c,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 app_flash.c +--- apps/app_flash.c 12 Feb 2003 13:59:13 -0000 1.1.1.1 ++++ apps/app_flash.c 13 Sep 2003 00:36:04 -0000 +@@ -21,7 +21,7 @@ + #include + #include + #include +-#include ++#include "linux/zaptel.h" + #include + #include + #include +Index: apps/app_meetme.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/app_meetme.c,v +retrieving revision 1.4 +diff -u -r1.4 app_meetme.c +--- apps/app_meetme.c 20 Aug 2003 23:32:23 -0000 1.4 ++++ apps/app_meetme.c 13 Sep 2003 00:36:04 -0000 +@@ -30,7 +30,7 @@ + #include + + #include +-#include ++#include "linux/zaptel.h" + + static char *tdesc = "Simple MeetMe conference bridge"; + +Index: apps/app_zapbarge.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/app_zapbarge.c,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 app_zapbarge.c +--- apps/app_zapbarge.c 12 Feb 2003 13:59:14 -0000 1.1.1.1 ++++ apps/app_zapbarge.c 13 Sep 2003 00:36:05 -0000 +@@ -33,7 +33,7 @@ + #include + + #include +-#include ++#include "linux/zaptel.h" + static char *tdesc = "Barge in on Zap channel application"; + + static char *app = "ZapBarge"; +Index: apps/app_zapras.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/apps/app_zapras.c,v +retrieving revision 1.1.1.1 +diff -u -r1.1.1.1 app_zapras.c +--- apps/app_zapras.c 12 Feb 2003 13:59:14 -0000 1.1.1.1 ++++ apps/app_zapras.c 13 Sep 2003 00:36:05 -0000 +@@ -33,7 +33,7 @@ + #include + + /* Need some zaptel help here */ +-#include ++#include "linux/zaptel.h" + + static char *tdesc = "Zap RAS Application"; + +Index: cdr/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/cdr/Makefile,v +retrieving revision 1.6 +diff -u -r1.6 Makefile +--- cdr/Makefile 19 Aug 2003 16:42:30 -0000 1.6 ++++ cdr/Makefile 13 Sep 2003 00:36:05 -0000 +@@ -13,7 +13,7 @@ + + MODS=cdr_csv.so + +-CFLAGS+=-fPIC ++CFLAGS+=-fPIC -DPIC + + # + # MySQL stuff... Autoconf anyone?? +Index: channels/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/channels/Makefile,v +retrieving revision 1.10 +diff -u -r1.10 Makefile +--- channels/Makefile 11 Sep 2003 19:45:43 -0000 1.10 ++++ channels/Makefile 13 Sep 2003 00:36:05 -0000 +@@ -27,6 +27,7 @@ + CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so) + CHANNEL_LIBS+=$(shell [ -f h323/libchanh323.a ] && echo chan_h323.so) + ++CFLAGS+=-fPIC -DPIC + CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations + CFLAGS+=$(shell [ ! -f /usr/include/linux/if_wanpipe.h ] && echo " -DOLD_SANGOMA_API") + CHANNEL_LIBS+=$(shell [ -f /usr/include/alsa/asoundlib.h ] && echo "chan_alsa.so") +@@ -37,7 +38,7 @@ + ZAPR2=$(shell [ -f /usr/lib/libmfcr2.so.1 ] && echo "-lmfcr2") + CHANZAP=$(shell if [ -f .oldzap ]; then echo "chan_zap_old.c"; else echo "chan_zap.c"; fi) + ZAPLIB=$(shell if [ -f .oldzap ]; then echo "-lzap"; fi) +-CFLAGS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "-DIAX_TRUNKING") ++CFLAGS+=$(shell [ -f ../include/linux/zaptel.h ] && echo "-DIAX_TRUNKING") + CHANNEL_LIBS+=$(shell [ -f /usr/include/vpbapi.h ] && echo "chan_vpb.so" ) + + ALSA_SRC=chan_alsa.c +@@ -50,7 +51,8 @@ + + ZAPDIR=/usr/lib + +-CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "chan_zap.so") ++# XXX evan disable zaptel ++# CHANNEL_LIBS+=$(shell [ -f ../include/linux/zaptel.h ] && echo "chan_zap.so") + + CHANNEL_LIBS+=$(shell [ -f /usr/include/nbs.h ] && echo "chan_nbs.so" ) + +Index: channels/chan_zap.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v +retrieving revision 1.98 +diff -u -r1.98 chan_zap.c +--- channels/chan_zap.c 12 Sep 2003 17:09:44 -0000 1.98 ++++ channels/chan_zap.c 13 Sep 2003 00:36:10 -0000 +@@ -44,7 +44,7 @@ + #include + #include + #include +-#include ++#include "linux/zaptel.h" + #include + #include + #include +Index: codecs/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/codecs/Makefile,v +retrieving revision 1.5 +diff -u -r1.5 Makefile +--- codecs/Makefile 6 May 2003 00:00:20 -0000 1.5 ++++ codecs/Makefile 13 Sep 2003 00:36:10 -0000 +@@ -25,9 +25,8 @@ + + LIBG723=g723.1/libg723.a + LIBG723B=g723.1b/libg723b.a +-LIBGSM=gsm/lib/libgsm.a +-LIBGSM=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; else echo "-lgsm" ; fi) +-LIBGSMT=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; fi) ++LIBGSM=-lgsm ++LIBGSMT=-lgsm + LIBMP3=mp3/libmp3.a + LIBLPC10=lpc10/liblpc10.a + LIBSPEEX=-lspeex -lm +Index: codecs/codec_gsm.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/codecs/codec_gsm.c,v +retrieving revision 1.2 +diff -u -r1.2 codec_gsm.c +--- codecs/codec_gsm.c 13 Aug 2003 15:25:16 -0000 1.2 ++++ codecs/codec_gsm.c 13 Sep 2003 00:36:10 -0000 +@@ -31,8 +31,8 @@ + #include + #include + #include ++#include + +-#include "gsm/inc/gsm.h" + #include "../formats/msgsm.h" + + /* Sample frame data */ +Index: codecs/gsm/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/codecs/gsm/Makefile,v +retrieving revision 1.3 +diff -u -r1.3 Makefile +--- codecs/gsm/Makefile 27 Apr 2003 18:13:11 -0000 1.3 ++++ codecs/gsm/Makefile 13 Sep 2003 00:36:10 -0000 +@@ -55,7 +55,7 @@ + # CCFLAGS = -c -O + + CC = gcc -ansi -pedantic $(OPTIMIZE) -march=$(PROC) -fschedule-insns2 -fomit-frame-pointer +-CCFLAGS += -c -DNeedFunctionPrototypes=1 -finline-functions -funroll-loops -fPIC ++CCFLAGS += -c -DNeedFunctionPrototypes=1 -finline-functions -funroll-loops -fPIC -DPIC + + LD = $(CC) + +Index: codecs/lpc10/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/codecs/lpc10/Makefile,v +retrieving revision 1.3 +diff -u -r1.3 Makefile +--- codecs/lpc10/Makefile 27 Apr 2003 18:13:11 -0000 1.3 ++++ codecs/lpc10/Makefile 13 Sep 2003 00:36:10 -0000 +@@ -22,13 +22,8 @@ + # + + WARNINGS = -Wall -Wno-comment -Wno-error +-CFLAGS = $(OPTIMIZE) -I$(LIB_TARGET_DIR) $(WARNINGS) -fPIC ++CFLAGS = $(OPTIMIZE) -I$(LIB_TARGET_DIR) $(WARNINGS) -fPIC -DPIC + #CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi) +- +-#fix for PPC processors +-ifneq ($(PROC),ppc) +- CFLAGS+= -march=$(PROC) +-endif + + LIB = $(LIB_TARGET_DIR)/liblpc10.a + +Index: formats/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/formats/Makefile,v +retrieving revision 1.7 +diff -u -r1.7 Makefile +--- formats/Makefile 19 Aug 2003 16:42:30 -0000 1.7 ++++ formats/Makefile 13 Sep 2003 00:36:11 -0000 +@@ -20,9 +20,9 @@ + # + #FORMAT_LIBS+=format_g723.so + +-GSMLIB=../codecs/gsm/lib/libgsm.a ++GSMLIB=-lgsm + +-CFLAGS+=-fPIC ++CFLAGS+=-fPIC -DPIC + + all: depend $(FORMAT_LIBS) + +Index: pbx/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/pbx/Makefile,v +retrieving revision 1.4 +diff -u -r1.4 Makefile +--- pbx/Makefile 19 Aug 2003 16:42:30 -0000 1.4 ++++ pbx/Makefile 13 Sep 2003 00:36:11 -0000 +@@ -27,7 +27,7 @@ + MOC=$(QTDIR)/bin/moc + KDE_FLAGS=-I$(KDEDIR)/include -I$(KDEDIR)/include/kde -I$(QTDIR)/include + KDE_LIBS=-L$(KDEDIR)/lib -L$(QTDIR)/lib -lqt -lkdecore -lkdeui +-CFLAGS+=-fPIC ++CFLAGS+=-fPIC -DPIC + + KDE_CONSOLE_OBJS=pbx_kdeconsole_main.o pbx_kdeconsole.o + +Index: pbx/pbx_wilcalu.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/pbx/pbx_wilcalu.c,v +retrieving revision 1.4 +diff -u -r1.4 pbx_wilcalu.c +--- pbx/pbx_wilcalu.c 28 Apr 2003 22:00:30 -0000 1.4 ++++ pbx/pbx_wilcalu.c 13 Sep 2003 00:36:11 -0000 +@@ -12,7 +12,7 @@ + * the GNU General Public License + + * Autodialer for Asterisk +- * Redirect dialstring thru fifo "/var/run/autodial.ctl" ++ * Redirect dialstring thru fifo "/var/run/asterisk/autodial.ctl" + * Format of string is : + * "tech/tele,filename&" ie. "tor1/23,file&" + */ +Index: res/Makefile +=================================================================== +RCS file: /usr/cvsroot/asterisk/res/Makefile,v +retrieving revision 1.7 +diff -u -r1.7 Makefile +--- res/Makefile 19 Aug 2003 16:42:30 -0000 1.7 ++++ res/Makefile 13 Sep 2003 00:36:11 -0000 +@@ -15,8 +15,8 @@ + + CRYPTO_LIBS=-lssl -lcrypto + +-CFLAGS+= +-CFLAGS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo " -DZAPATA_MOH") ++CFLAGS+=-fPIC -DPIC ++CFLAGS+=$(shell [ -f ../include/linux/zaptel.h ] && echo " -DZAPATA_MOH") + # + # Work around buggy RedHat 9.0 + # +Index: res/res_musiconhold.c +=================================================================== +RCS file: /usr/cvsroot/asterisk/res/res_musiconhold.c,v +retrieving revision 1.8 +diff -u -r1.8 res_musiconhold.c +--- res/res_musiconhold.c 8 Sep 2003 16:48:07 -0000 1.8 ++++ res/res_musiconhold.c 13 Sep 2003 00:36:11 -0000 +@@ -36,7 +36,7 @@ + #include + #include + #ifdef ZAPATA_MOH +-#include ++#include "linux/zaptel.h" + #endif + #include + #include diff --git a/ljcom/src/phonepost/doc/code b/ljcom/src/phonepost/doc/code new file mode 100644 index 0000000..855af2d --- /dev/null +++ b/ljcom/src/phonepost/doc/code @@ -0,0 +1,54 @@ + +=== Blob Client +BlobClient.pm, and BlobClient/* provide an interface to the blob +server, both a local file path and a remote mod_perl server. They +generally use a clusterid, userid, domain, file extension, and blobid to +refer to a given blob. + + +On top of this, we have LJ/Blob.pm: + - LJ::Blob is the LJ-specific blob code, and it's the only interface + external clients care about. It takes in stuff like $u objects and + handles all of the cluster-related mapping for you. It uses a bunch + of settings in ljconfig to set up all the blob clusters. + +So the code path is like this: + - asterisk script calls + - phonepost-asterisk.pl's LJ::PhonePost::store_audio, which calls + - LJ::Blob::put, which calls + - BlobClient::put, which is a virtual function that maps to + - BlobClient::Local::put or BlobClient::Remote::put. + +A note on the "domain"s. The blob clients all use domains in string form. +LJ uses integer ids in its own userblob table, but that's a layer on top +of the blob client, and all of the functions exposed by LJ/Blob.pm take +strings. (The mapping from string->id is LJ-specific, and so it's in +ljconfig.pl.) + +The LJ::get_blob_domainid() function in ljlib.pl controls the user +clusterid => blob clusterid mappings. + + +=== Database Tables +userblob is the LJ table used to track blobs. It knows the bare minimum +that is shared by all blobs: owner, domain, id, and size. + +phonepostlogin is the phone number and pin for users to interact with +journals. There's space in there to work with communities, too, but +it's not implemented. + +phonepostentry stores extra information about a phonepost: not only its +blobid, but also a jitemid (used to find the entry it's associated with, +which controls its security), an anum, the posttime, etc. lengthsecs +should store the length of the audio in seconds but it's not used yet; +I think the unix "file" command can be used to retreive this from the +wavs. + + +=== Files +See also the documents "paths" and "symlinks" for asterisk stuff. + - cgi-bin/ + phonepost.pl provides the main functions, and is used by ljlib. + phonepost-asterisk.pl provides extra functions used by asterisk. + +vim: set tw=72 : diff --git a/ljcom/src/phonepost/doc/overview b/ljcom/src/phonepost/doc/overview new file mode 100644 index 0000000..1713479 --- /dev/null +++ b/ljcom/src/phonepost/doc/overview @@ -0,0 +1,35 @@ + +steps that happen when a phone call comes in +-------------------------------------------- + + - Phone call goes to the VoicePulse number. + + - They do some magic and pass the communication via IAX (Inter-AsteriSK + protocol) to our Asterisk. + + - iax.conf specifies that the VoicePulse IAX goes to the "livejournal" + extension. + + - extensions.conf specifies that the "livejournal" extension answers the + phone, waits a second, and then runs the AGI (Asterisk Gateway + Interface) script called "livejournal". + + - The livejournal script lives in agi-bin/. It does these steps: + + - First, it runs through the appropriate menus and eventually spits + out a wav file in + PHONESPOOL/in/$userid-$currentunixtime.wav. + (PHONESPOOL is hard-coded into the livejournal script; it + probably ought to be on whichever machine does the mp3 encoding.) + + - Next, it runs the MP3 encoder, which encodes the file + into PHONESPOOL/out/$userid-$currentunixtime.mp3, and + deletes the wav file out of the in/ directory. + + - Then we pass that file to the blob server to store, and finally + post to LJ with the blobid. + + - When the interface script returns, we hang up. + + +vim: tw=72 diff --git a/ljcom/src/phonepost/doc/script b/ljcom/src/phonepost/doc/script new file mode 100644 index 0000000..35c9e9d --- /dev/null +++ b/ljcom/src/phonepost/doc/script @@ -0,0 +1,33 @@ +Sound files needed (script negotiable): + + welcome: "Welome to the LiveJournal phone gateway." + welgoat: "Welome to the LiveJournal phone goatway." + [make it subtle, so most people don't notice, and we can + use it randomly] + + phone: "Enter your phone number, followed by pound." + phonecid: "To log in using your caller id, press pound. + Otherwise enter your phone number, followed by pound." + pin: "Enter your PIN, followed by pound." + badlogin: "Invalid login." + quota: "We're sorry, you have reached your phone post limit." + space: "We're sorry, you have reached your disk space limit." + error: "We're sorry, there was an error processing your request." + support: "For more information, visit LiveJournal dot com slash phonepost." + queued: "Your entry has been saved. It will be posted soon." + + record: "Record your entry after the beep. Hanging up will + cancel your post. Press pound when you're done recording." + menu: "Press 1 to replay your message, 2 to re-record it, 3 to post + it public, 4 to post it friends-only, and 5 to post it private. + To hear your options again, press 9." + + unknown: "You have entered an unknown menu option." + posted: "Your entry has been posted." + + goat: "Frank the goat appreciates your call." + + goodbye: "Goodbye!" + + +vim: set tw=72 : diff --git a/ljcom/src/phonepost/etc/extensions.conf b/ljcom/src/phonepost/etc/extensions.conf new file mode 100644 index 0000000..359a4ae --- /dev/null +++ b/ljcom/src/phonepost/etc/extensions.conf @@ -0,0 +1,12 @@ + +; NOTE: this is only a sample. +; your extensions.conf needs a dialplan +; that runs a goto into the livejournal dialplan + +[livejournal] +exten => s,1,Answer +exten => s,2,AGI(livejournal) +exten => s,3,Wait(1) +exten => s,4,Background(livejournal/goodbye) +exten => s,5,Hangup + diff --git a/ljcom/src/rewrite-balancer/README.txt b/ljcom/src/rewrite-balancer/README.txt new file mode 100644 index 0000000..f5ff34e --- /dev/null +++ b/ljcom/src/rewrite-balancer/README.txt @@ -0,0 +1,19 @@ +To be used like: + +RewriteEngine on +RewriteLock /tmp/apache-rewrite.lock +RewriteLog /var/log/apache/rewrite.log +RewriteLogLevel 0 + +RewriteMap lb prg:/home/lj/bin/rewrite-balance-intweb +RewriteRule ^/(.*)$ http://${lb:$1}/$1 [NS,P,L] + + +Where rewrite-balance-intweb is like: + +#!/usr/bin/perl + +use FindBin qw($Bin); +exec("$Bin/rewrite-balancer", "-f", "$Bin/../cgi-bin/pool_int_web.txt"); + +And pool_int_web.txt is just one IP address per line. diff --git a/ljcom/src/rewrite-balancer/rewrite-balancer.c b/ljcom/src/rewrite-balancer/rewrite-balancer.c new file mode 100644 index 0000000..15abec7 --- /dev/null +++ b/ljcom/src/rewrite-balancer/rewrite-balancer.c @@ -0,0 +1,521 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * rewrite-balancer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* constants */ +#define BUFFER_UDP 2000 +#define BUFFER_STDIN 20000 + +/* maximal no. of servers */ +#define SERVERS_MAX 256 + +/* max timeout before discarding server info */ +#define SERVER_TIMEOUT 20 + +/* who we setuid/setgid to */ +#define SETUID_USER "nobody" + +/* globals */ +int udp_socket = 0; /* socket which listens to udp stats broadcasts */ +int port = 4446; /* port to listen on */ + +char *fname = 0; /* name of the config file */ + +#define MAX_UDP_PARSE 10 + +unsigned char udp_buffer[MAX_UDP_PARSE][BUFFER_UDP]; +unsigned char stdin_buffer[BUFFER_STDIN]; + +typedef struct { + struct in_addr addr; + int free; + int active; + time_t heardfrom; +} server; + +typedef struct { + int numservers; /* how many servers */ + int total_free; /* how many free children in all servers */ + int check_servers; /* check against a list of permissible servers */ + int codever; /* if non-zero, incoming messages must match */ + server servers[SERVERS_MAX]; +} sconfig; /* server config structure */ + +sconfig *config; /* global server config */ + +/* + * Generally we use the global variable config to access the list + * of servers and other current data. High-level functions don't hesitate + * to access this global variable directly. However, lower-level functions + * for manipulating server data accept an explicit pointer to sconfig, + * so they can be used by read_config() for cleanly changing configs + * on-the-fly. + */ + +int read_config(void); + +int init_config(void) { + config = (sconfig *)malloc(sizeof(sconfig)); + if (config == 0) return 0; + config->numservers = 0; + config->total_free = 0; + config->check_servers = 0; + config->codever = 0; + return 1; +} + +int server_cmp(const void *arg1, const void *arg2) { + server *s1 = (server *)arg1; + server *s2 = (server *)arg2; + + if (s1->addr.s_addr == s2->addr.s_addr) return 0; + return (s1->addr.s_addr > s2->addr.s_addr ? 1 : -1); +} + +server *find_server(sconfig *conf, struct in_addr addr) { + int down = 0; + int up = conf->numservers-1; + + while (down < up) { + int middle = (down+up)/2; + if (conf->servers[middle].addr.s_addr == addr.s_addr) + return &(conf->servers[middle]); + else { + if (conf->servers[middle].addr.s_addr > addr.s_addr) + up = (middle == up ? middle-1 : middle); + else + down = ( middle == down ? middle+1: middle); + } + } + if (conf->servers[down].addr.s_addr == addr.s_addr) + return &(conf->servers[down]); + + if (conf->check_servers) + return 0; + + if (conf->numservers >= SERVERS_MAX) + return 0; + + down = conf->numservers++; + conf->servers[down].addr = addr; + conf->servers[down].active = conf->servers[down].free = 0; + conf->servers[down].heardfrom = 0; + + qsort(conf->servers, conf->numservers, sizeof(server), server_cmp); + return find_server(conf, addr); /* recursive! */ +} + +void clear_server (sconfig *conf, server *sp) { + if (sp->free) { + conf->total_free -= sp->free; + if (conf->total_free < 0) conf->total_free =0; + } + sp->free = sp->active = sp->heardfrom = 0; +} + +int get_server (sconfig *conf, struct in_addr *addr) { + int choice, i, count; + + if (conf->total_free == 0) return 0; + choice = (rand() % conf->total_free) + 1; + + count = 0; + + for (i=0; inumservers; i++) { + count += conf->servers[i].free; + if (count >= choice) { + time_t now = time(0); + if (conf->servers[i].heardfrom && + (now - conf->servers[i].heardfrom > SERVER_TIMEOUT)) { + int j; + + clear_server(conf, &(conf->servers[i])); + + /* this should happen rarely, so better walk them + all now instead of potentially a very deep recursion */ + for (j=0; jnumservers; j++) { + if (conf->servers[j].heardfrom && + (now - conf->servers[j].heardfrom > SERVER_TIMEOUT)) + clear_server(conf, &(conf->servers[j])); + } + + /* now recurse */ + return get_server(conf, addr); + } + conf->servers[i].free--; + conf->total_free--; + *addr = conf->servers[i].addr; + return 1; + } + } + return 0; +} + +void parse_message (char *buffer, int blen, + struct in_addr inaddr) { + char name[80]; + int val, len; + int res; + int bcast_ver = 0; + server *sp; + sconfig *conf = config; + int codever = 0; + + buffer[blen]='\0'; + + /* should we reread config? */ + if (strncmp(buffer, "RELOAD CONFIG", 13) == 0) { + read_config(); + return; + } + + sp = find_server(conf, inaddr); + if (sp==0) return; + + clear_server(conf, sp); + + while ((res = sscanf(buffer, " %[^=]=%u %n", name, &val, &len))!=-1) { + buffer += len; + if (!strcmp(name, "bcast_ver")) + bcast_ver = val; + if (!strcmp(name, "active")) + sp->active = val; + if (!strcmp(name, "free")) + sp->free = val; + if (!strcmp(name, "codever")) + codever = val; + } + if (bcast_ver != 1) { + clear_server(conf, sp); + return; + } + if (codever && conf->codever && conf->codever != codever) { + clear_server(conf, sp); + return; + } + + conf->total_free += sp->free; + + return; +} + +void prepare_rfds(fd_set *prfds, int *n) { + int max = 0; + + FD_ZERO(prfds); + FD_SET(udp_socket, prfds); + if (udp_socket > max) max = udp_socket; + FD_SET(0, prfds); + *n = max + 1; +} + +int handle_url(void) { + struct in_addr srv; + sconfig *conf = config; + + if (get_server(conf, &srv) == 0) + return 0; + + printf("%s\n", inet_ntoa(srv)); + fflush(stdout); + return 1; +} + +enum bufstate_t { EMPTY = 0, FILLING, FULL }; + +void loop (void) { + struct sockaddr_in addr; + int socklen; + fd_set rfds; + unsigned char *buf = stdin_buffer; + enum bufstate_t bufstate = EMPTY; + + /* time in Unix seconds when we last checked config */ + long last_conf_check = 0; + struct timeval tv; + struct timezone tz; + + stdin_buffer[0] = '\0'; + + while(1) { + int n, res; + + if (bufstate == FULL && handle_url()) { + buf = stdin_buffer; + bufstate = EMPTY; + } + + prepare_rfds(&rfds, &n); + tv.tv_sec = 3; tv.tv_usec = 0; + res = select(n, &rfds, 0, 0, &tv); + + /* check if need to reread config */ + if (gettimeofday(&tv, &tz)==0) { + if (tv.tv_sec - last_conf_check >3) { + last_conf_check = tv.tv_sec; + read_config(); + } + } + + if (res) { + if (FD_ISSET(0, &rfds)) { + int len, size; + unsigned char *newline; + + /* If we had a full buffer and got more, assume a child was killed + or something, and mod_rewrite isn't obeying its usual locking + behavior. */ + if (bufstate == FULL) { + buf = stdin_buffer; + bufstate = EMPTY; + } + + size = BUFFER_STDIN-1 - (buf - stdin_buffer); + + while (size && ((len = read(0, buf, size)) > 0)) { + buf+=len; + size-=len; + } + *buf = '\0'; + + if (newline = strchr(stdin_buffer, '\n')) { + bufstate = FULL; + *newline = '\0'; + } else { + bufstate = FILLING; + } + } + if (FD_ISSET(udp_socket, &rfds)) { + int pos = 0; /* position in ring buffer */ + int ct = 0; /* total items we read from network */ + int to_parse; /* MIN(10, ct) */ + int i; + + /* ring buffer areas: */ + struct sockaddr_in addrs[MAX_UDP_PARSE]; + int lens[MAX_UDP_PARSE]; + + /* load everything into our ring buffer first, then + * parse things later. */ + socklen = sizeof(addr); + while((lens[pos] = recvfrom(udp_socket, udp_buffer[pos], + BUFFER_UDP-1, 0, + (struct sockaddr *) &addrs[pos], + &socklen)) > 0) { + ct++; + if (++pos == MAX_UDP_PARSE) + pos = 0; + } + + /* process last MAX_UDP_PARSE messages */ + to_parse = (ct > MAX_UDP_PARSE) ? MAX_UDP_PARSE : ct; + pos = (pos + MAX_UDP_PARSE - to_parse) % MAX_UDP_PARSE; + + for (i=0; inumservers = new_conf->total_free = 0; + new_conf->codever = 0; + + new_conf->check_servers = 0; /* for now, to allow adding */ + + check_old = config->check_servers; + config->check_servers = 1; /* disallow adding temporarily */ + + /* read servers into the new config, copying their children + information from the old one if available */ + + while (!feof(f)) { + char name[80]; + int len; + char optname[80]; + int res; + unsigned int val; + + if (fgets(name, 80, f) == 0) { + if (feof(f)) + break; + /* error, retain old config */ + failed = 1; + break; + } + + if ((res = sscanf(name, " %[^=]=%u ", optname, &val))==2) { + if (!strcmp(optname, "codever")) { + new_conf->codever=val; + continue; + } + else { /* unknown config option */ + failed = 1; + break; + } + } + len = strlen(name); + if (len && name[len-1]=='\n') + name[len-1]='\0'; + snew = add_server(new_conf, name); + if (snew) { + sold = add_server(config, name); + if (sold) { + /* copy activity info from the old config */ + snew->free = sold->free; + snew->active = sold->active; + snew->heardfrom = sold->heardfrom; + new_conf->total_free += snew->free; + } + } + } + + fclose(f); + + if (failed) { + config->check_servers = check_old; + free(new_conf); + return 0; + } + + /* success, replace old config with new */ + free(config); + config = new_conf; + config->check_servers = 1; + + last_config = buf.st_mtime; + return 1; +} + +int main (int argc, char **argv) { + struct sockaddr_in addr; + char c; + + if (init_config() == 0) { + printf("couldn't initialize server config\n"); + exit(1); + } + + while ((c = getopt(argc, argv, "p:f:")) != -1) { + switch (c) { + case 'p': + port = atoi(optarg); + break; + case 'f': + if ((fname = malloc(strlen(optarg)+1))==0) { + printf("couldn't allocate space for file name\n"); + exit(1); + } + strcpy(fname, optarg); + if (read_config() == 0) { + printf("error reading the config file"); + exit(1); + } + break; + default: + fprintf(stderr, "Illegal argument \"%c\"\n", c); + return 1; + } + } + + /* create and bind the udp socket */ + + udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udp_socket == -1) { + printf("couldn't create the UDP socket\n"); + exit(1); + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + if (bind(udp_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + printf("couldn't bind the UDP socket\n"); + exit(1); + } + + /* make stdin line-buffered and stdout unbuffered */ + setlinebuf(stdin); + setbuf(stdout, 0); + + /* enable nonblocking behavior */ + fcntl(0, F_SETFL, O_NONBLOCK); + fcntl(udp_socket, F_SETFL, O_NONBLOCK); + + /* lose root privileges if we have them */ + if (getuid()== 0 || geteuid()==0) { + struct passwd *pw; + + if ((pw = getpwnam(SETUID_USER)) == 0) { + fprintf(stderr, "can't find the user %s to switch to\n", SETUID_USER); + return 1; + } + if (setgid(pw->pw_gid)<0 || setuid(pw->pw_uid)<0) { + fprintf(stderr, "failed to assume identity of user %s\n", SETUID_USER); + return 1; + } + } + + /* enter the loop */ + loop(); + + return 0; +} + diff --git a/ljcom/src/testfile b/ljcom/src/testfile new file mode 100644 index 0000000..b03eef2 --- /dev/null +++ b/ljcom/src/testfile @@ -0,0 +1,18 @@ +this is a test file. test test. + +take two, with libraries installed on danga + +whoa, this is bad-ass. + +blah blah. + +testtest + +test again + +will it work? +sdfdsf + +sdlkfjsdlfsdf +sd +f diff --git a/ljcom/ssldocs/_config.bml b/ljcom/ssldocs/_config.bml new file mode 100644 index 0000000..d73135f --- /dev/null +++ b/ljcom/ssldocs/_config.bml @@ -0,0 +1,12 @@ +LookRoot $LJHOME/cgi-bin/bml/scheme +ForceScheme xcolibur_ssl +DefaultLanguage en_LJ +IncludePath $LJHOME/htdocs/inc + +ExtraConfig $LJHOME/cgi-bin/lj-bml-init.pl +AllowCode 1 +AllowTemplateCode 1 + + + + diff --git a/ljcom/ssldocs/img/amex.jpg b/ljcom/ssldocs/img/amex.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ce5b758ec6b3f2afb3b13837cabcee30cc61d058 GIT binary patch literal 46539 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 H{}%rj%)N@a literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/5x5.gif b/ljcom/ssldocs/img/dys/5x5.gif new file mode 100755 index 0000000000000000000000000000000000000000..06373fa28b86a543515694ccffd26822dde37b39 GIT binary patch literal 45 vcmZ?wbhEHbWMyDwXkcJClLkVHKUr8s7#J9IfEXyw%D}+H($c>&g25U9%|!@V literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/b_blue.gif b/ljcom/ssldocs/img/dys/b_blue.gif new file mode 100755 index 0000000000000000000000000000000000000000..734c583ad973dc5ece5967e03adea0638fb369df GIT binary patch literal 64 zcmZ?wbhEHbv%oQ5D z?))=2<@uUL;lV!Z literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/bg2.gif b/ljcom/ssldocs/img/dys/bg2.gif new file mode 100755 index 0000000000000000000000000000000000000000..70fc1dd7c8b955694b69f1e3c1bac577c67f31d9 GIT binary patch literal 38891 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 literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/bg_top.gif b/ljcom/ssldocs/img/dys/bg_top.gif new file mode 100755 index 0000000000000000000000000000000000000000..d8e7692c40819434034845186fee3e3244d18a8c GIT binary patch literal 10247 zcmeH}bypJ(z_vHo7%eHI8%ar#7}79Ox|QybmS!VIjBWvkbV+xO?(R|qK|nwd{0V~Y zd7e-4{`20S;6B$m_jPV{4K*og+dQB+;5PuUfqAi$%Q}-UK9**)7X5N24mK98G=kJz zh@>6!bLk5;%tQs2#+b}{nKT8wX^)T^2xa*g;G7W}8WEB|=%kn8pXeB!SLqty7ZUr? zM#Chiy2FlABdD*=0g85T&36*7)q7KD&u!-YuG#W&ypw*iac;R*qLWj8l6laRklFV} zrfK>~ZVs^+Gj4yA4@f&Dd#g&`z<$&#$r`yRn9DHQTujcnGea@g)!ISaX-3*%I8`+! zLtivs#WdDPI^0B2+^%2Gu*1_#t3oUottn*<@6>ta;9zK^WYj3;7#60fB4Zn>p^rgG zeuxzFg z&B6SkvU*w2JP`U!#y(D;n=;E~wqP~>5%_fi%9u@g4B6~F%}_O%Q;+O`?e{;U$W=$- zft8L&896SH0|CJgp7*~M(4rhvNtAweq6PA4tT@GJf+vjBc|HXwszbbQbA_>Z;F|FS z>dNvWBWzUpklPyV4e>&#X@hBl&70pR(N1sQOl9EG*zxb?^ACjnGRY5Dc3q1s^aTOg zi~jf%)0DY<)W{!RB8=J{)3THNZnrHZ{m)0lK zT>KlK(}Zg31Z3%(V=C0qe(-1U#u#Jlk3AyE*SnKVKa= z`-~7lHtB^ZYpk?vrPQqhl65|x6^*!XQu-a_mPB#^HIGxxYo(6x-v4O8ZIVFd-c)H7S@Nr2Md(wwC zvlV>}{pl>U)agX2u|gn;iPu58aZb9k=;oSLKnWvVvHpMDP@4$axbhsU#652Nl=M5O zx6A9miULgV(UHcR0w;#5nzo}Y_oi48%h&p!{>vWe2adnX8zQ4S_MN2XulbN*GVT$u zA;+&8`04KCTTrf@1p#3}vARg5;wZ$;we+a4CA{Jk0zpvxdTxV+aJaa^vQl22W5%*}n0u$&{wCk~ABlxC-do~tvsd+FA|B1>v`xh{wGWo8 z2&ML`l30!!7eDrw>%4?K?sTqiihmFO46-}9@tyHln0cM_KH?N~S|<6{dcNvUWsL%e zJ|<0xTvJ-+_WyqU^tNp}HyhbwK-Qd97P3pCJ!rne`e#%DA?@uXm_Z#@sP`n!@#7nC z+D37hNOh71k6tO~uCH#q%!|4dhfPuQw_E{DyE7?)?a}5T9v@_*`o`a0^RZus9Elr) zQ3@b_I1?^;43+@BLa7y|Q9U;(;Ym~>US~+U>Tb+kYEAEQ2V+-rJDc{GU!4Gz%HthV+CFw z4^yjkze}ewvQImq5dC{8Y7ol~%*)c1qQ(>vc#Kzso6ULU9B4F2V1S}4lVGZlXvW?X z0$s%#maNmIZ^vwq+exI+Rc4g2$ulq?l!A&_49u}*n?wE~+e{!z>s8!{l8!%+ri5OV zGJ`xnfY;3m9g<0f6fT%Q+b1sTT4%Y-RzD%}*s2&Rtwm86ItzZ2X4HEeSYb$j?_J6K zO~br@QdIa&;gd%XljcEg2rZx-Fi(M3M&6B}gvdBkiIG@8K7}Cur-nn3OX(sS7l$on zqvaz}=CArx(du6ookFfmu$;GaQ(@3pP2<~bcr-PaNk)-G>L_I-3H?>2HTyA;nzr}o zm`z@9_NDQ?pD}P#flLw(H%;h#T?+ovr-)Jx`^Fg0Jp|wsXHXm=o>; zFkwQFd0<9GbeobLnEfn#c%Zjkcb&` zy`cB~6ED*V;4$szC}{VHVwevC2~>Dm?(oHky^}7&znm$c2>}u~#o@?&QP&L-w9XKP z!MVVGaT*y41o`dVJWwRxw_K!#ha@P$X%C>rV*?ft*;-T+iL&@rrB1h3LX^wnO)beB zBZuu+4&4|I`ixk;3Pj>pUJO-B+eBYitdpOs>eW$GS>J7Svt6|bM<_O1r(h7zNDj3T zB-(qxgD+SjHScEDZwOwP)KFfTceh9(9~mxYSdLrC|D~WE_4~ZBr(Rb{uO9Y=L+^H; ze@t>ZNRVe8&YZZE{F$Df{FU>qsZj~%aaK`iA-}Wqw8Z95*8!M4TC<(NLDDZDqUZDs zvLsGAVpn*$hbO&GKS(~&Qgrv=tUwYXE3?f0fz~rl{T*y66IXEq7ek+DACxR(2->RZ zr>2ZbWmb>57XSvCDhwYaZC+L19 zbO-UB$x__jflS(OC}$qT#w510)lvQ)XT5k?I>34@u2@$e!iP1&c%!`|+N(W4+FRUWIAwCnK! zryb##mGDn=5zf!;57i_7eTzIDw-3CDxOfr?he!VRHu82I^2ZcHfTI2fLELg8h}98= zl(F792x_`$!Zk$Xe~6esO)5AN?S!P`B@n(1W7>#gG4o^RjZ#pFdhHlB8Xv`Xi)V(w zoB0N`z668*i$|a!EP5zH6BG;9hQAS|--zPJ0c_VhQ1p6q^dbpcmDF-+3GJLhZ%loZFz6>hpmjwe1%|HQ4FA9k zpT*XRRL_YNOOKjJ(QiZ(@IqFld`u~v6Qsfuj-4qMfP2Tz{Fl5qLS*G|au^l_wM~Oa zBb_Gj1Z_ZeSiBHW`lGveBs@I`i`1rY)5d}n_K@Xcp==XCCXpzA7l}ZZu<_jZkcs%H zuRtL}R5UdFcMxi&67T&LN)v~{OP8|su}#Qvk(EOv$b2ElxTeOyW!3KhoE3@H@I)a@ zmg_fk9bu9YUs7kDU29&_w{iR)DD;(dip^#ODO<9`BzVjv*=h1Es4FM3QaB8R4yQo7 z>N#$>pjY$IQYGl^pomYrDIUO_Q)r%2V+zYc#*eC8Go#d>Q0GMH%&8pIJv5)0E^SLO zpGzf;uq)jOlTSkLO2L=@s0%6x2#+R2LA#LJd+D{HjOsNomw5(}Pli%VJYQ#gxJ!Bz zZ|2h5RP+QYg)kwnER%mPQ!Y5cks@ncI!kraHXE8~2h1*m7FD1UIoY!7QAx(qNn82Z z9i7>)%;~VVxs^C*vi%+Yp?Pu`gwmxtc~&uPl#)psn)_2acO?k@D;Ruvt1gSp#nIvQ z5#~kn<;Bp0V<%Eryr~GP@`x?aDH@p>o2kqS`35%m_?t}Bc4^R>wA%GFHMaEk^y!_h z>6O*#Z&1c>umx3;8GeNCn)u!+#fR{_z7x932%^XoInL{K%`Ch^rFLe%Rw#sBW-8?u zIx1vI;M2^VB+PeZmEUG@n-uXqPBJ)6+}bQ^ugVr1%kG88eBCIw)5tlx!*@-{`Mz1~ zWD)7`GpC0=*GD7wzXUX4&HIOw+}D2qcr_`Y)0E(X_mO3oWY<&@!u$uRsz{y^ni^hE za7p4;J~NKLpoFiW%)AsN`5`o|;0@f3x5iCvIZ7xGQv9bHb6Q;}Q&Y+xX5!+c_rKE4 z$}H&0uXlqqMX@z8Ko}=Mtrir7T`G(kNYZL>{~sWBD+&7tsD=PSFGCvE-6U=J>v?La z)xo}cr8JWeP&LGBfo9#UKE%81X-56#DGk4(Dr*Ll^#awQ+eeT_z4cy6{}f*TmNoBQ ztp%V#AtCx#V&QB3gu7E(1I-At0=rMQl}Yr@q?5IRHeg2+l+zJV2?M@3{rIy6EQSH> zi#0hmrIHZ>HBS>}H9$(~xr7#yVjRu$7R|6$R&R>*tTDXUAdvbV@F_`4&I4Gu2+RIvbFxvAU3dk{u-)xcs~()x?lIl&HQnGXkaVox8PF5*ma!*vx+DC) z11Zqyr_dSqF3#?<6E@u`{=IXm2NpR|9VOMZXxSPGt!+%~BYoFMPHL3QIo(ukU1 zo8S3)Hfl6SKvD?&+KzrH40!MlV34@3IH8U#fz<}947sYizYp_VAeg-x_;gCMKE4ME!T@$Fr8qVlwN~MLBhn{;9X6_8!fL5*9e2)Aqq_1 z4ZIQT9>-v5y1?X?B>-7@DH$23ZBOCME~vycy{c zYXANuHU|xf5df{K@=UxN1MY{01cx07nkWPsq+m~FwX155hvj}5=2H6bh^WCbMtp5% z*B)MZU%uL^!`JJD%5Jyp@3dfkncLgUy&{F26t?VZkE$amjMB!IL&u_A`m7hm8vl&> z^v?ShqCQWzo>PB&gQ;`&DnU) zRW#38pUv5YLEJsYoWjOjty)70=K~x2hy~X5F6Y1WE#{G88O~{#&KEIt^`(MKlxNuL83<-`34?BD)Lw3cm9h0U zQ29+a5ti4zDv}d|4D|L4!)BDcXU^SLrs`%i>r=JQ4HZdOoj6wg5VJlxv)hHM+r6u= zhc-1(elB<#9e~!iIUz09t1ZWHXaN1nVGCNjuku@Wt~ z)tsEr6t?w3Z~FeUK^omtJF!f3JT33p(aJnLcD6SOdpf%_%nV4>W`0$|dWUT^k>+YVE)83Eu_|F~*Kq_WFhP zqH23(=6bF6dsFX2)#kSeqDKFL3XUwHl9;=Z<3p!s_p1k|a)ixhxZ6AUBn~ z%pC7LCy-jV5S`BTxAC$1df(=6;YIz(IIYgQi&#C19<5s1fY+MN z)YNslCs-Cd&AnK^B$(S}hI{f_FdKe{qCNkn1 zUi}jM2-x2*H?A}g{VJI%2FJ0&ddsf4JL(+A_fG_W(3Nf{Nx;6%|tLs{I`!-v& zSJ!j+>M{#-Q=TcOb zeG}_zD@@u|cQ~c^L5&QTA!~iH(*J6E?qa92`s|84Vs>n z{PGXvFS&W)Kte);%d;m>0zb~y?N)6X)|I`m!Wcch8ls*jzh07Ufc*!x`w=&PRQnQh z|AGPz7$n4BkOx*m8x`;=Z-z>&wLI@*45DyVq%%|EkG7k& zgx^2|mBsESE;S{V{WGh}(x`~%1e@xjm)@O1jnJQXKFy{i{HT&T*yT{`kWPK?F5v)I zKll7J6QA)ecqN}V$^1rrZ>Pwe{>3};DajW%qedM#w&JvX-jSUq zdslL-w(P@5P_*BE9Qw|#$o4>@juw}YDY+KtM>`7xd^ zH)tEuKoEvrRSoqsQjfbX0dWpN5O8loVO0wa*8#BJQC6lM9GbC zH4B?`jXeb_E@=&NZzM@}ZyC3AT0Be&nHkKcwasOpp?|6vSy`r0bgBYiX#WWjjd3Id zD1ca2G60}P?ycS>(2GkdKOF#3gIH$%Bt;2uj7v!@b&`NuB$I5;LAgmqg+tg1w@C83 zQ-P+LZ<@xJ8t@F@EH$VBc$DBxKFY5cza$M5MInnWJSy=SZ?SU$D#S!-N-uup0|2cU z@ZYm<@}86UR{PC4kY~J4sco`j)k;b}`slcOiBbQfMaP7&@u+c^3Wo=mV<2)>6e|2n z;ADwH5XBRqWMdue-ST@-kSp`|pep4r`uNXR4|M*z;1`o8rhU3D_SnmtkP>T7Pfh;H z#hsv0;g*r9i{MWayH>0z5OaL@Q<6~kwEFbCNR+{hw$9P{G0b0A)dHWFP?qgKL5I-WXs0@9ieB`-m^ci zp5^d9@Ysy=nc35t6g_%fXLoR?5aKpld|P%V_g7kBn%KXE_0U5pctMZKlKVq_IzA~6 zf2NF?gi7t`j9T9aG}SAorLC=A1DIrx-MpeQ$ov#|>|&+No|`JYic|2zzgzxBZrr{6 zYzUMbvU}#1i*MRq#v^dIQk5|(RxaomEF17Cu6#Y)z_kJ3?5-Czl%oEq`iF(+gvDPD z!;fQi0^-+&Ta=6J4WRZZu-%3Z%|&2G_pWD?%@RAL_PX&RtkUj@P0M(5wrOambKJAu zFJ!-|`#lJ%Q7ses0x3DI^`b)ByfR9Zwl~wYhZ*kfXPe0V+jb?X6QS`t%d$(*M281b zyOu&KhH!g>QaP|0a@Z+jv|hDk?3PpRIr%c`t)QFzP9C!<{+b-vmmS0H?9SIKtwQ0~ zx*ffB(R<kg~kKEI&x&`)Xag2*o9WFqKxKR?3{!j^mcz!an|9zX4lBbh&; zT=(e{=$EK~^rSp7)78o4#G_nEKXbIcz~J4D@3$85$Ob_PQrtl5ng;k=tBBV8DWrtA z7+K`FMI2jZte}Xl-1id0BCDZuR^C0n6dbTkle)lxAN!LnyndBsDed*v+eaJss5nCF z83zOGjqmQ4$hXj0W}4bx5d_HID_t(Hub904?Im$yTU21N&F3+B zU|q^nOq*Q+-d$KfjkYx)*WmMeaMdA@+mx1LoT5Xqnr$spD!&AeOW$V9`93SACyKqc<|;df902CK7g*<<76u)<;-9a_E+PNoo{ z89%A*7iChGKN}V|8jdC&2;>?-aR}WQ4)E9ve5zHK!79rI32p2Ti$5rDcRy1URB?l; zP*W-3E5PwQo;=%%pfR0%EeTg}!pytc38 zLE8Be$64~nGm!op%koKyxt z%tkK-pvP!W70wh*X0u@n@vFPcH#Le2@#2F%@P0|++ny3#K!_^ntZM5>ngOGObYkF| zVmlpiBY2OnIx&}scikz8g>anx@C5(H#7P&~b|*9yq>(A8k;$b&syF#fA}Yt>!vG8q zQ&;`LM_vZNAc55=0?ihKrVgQ+F@jU2Oo`uH`b7m1RX$Ud2u<-c&D*l6y0ZD&83kR5 zsE@sTjc1z8f?6#g{5C5spy%{r$aH7n^h32)Ppj6@#x(YUE%mU7gWGA6e32^-co5cig)YGi&MJ63yOwWDm#}y-;l@WbOY!od@ zXOnCA`@wVcFy8PWc}iw=ul~}`E&Rye;E1M6HDn=&YiaSW5Ob#;$+NP&j@&Y=-e9rI;0LT*sHoFT zdR{oZOO$q5Y_~%^z_8KE5D>oF5VP!&x$IGDh?_Bl%`W%tEIXVo8^kgxFzYMMqLj|H zBbALlNiVB8uBek0ezczm?4I2To7g^^_2^5%hauUi=k~wCahR(n0{z%R)HX;mBB`l}`ejwfW$%Upc%iPkM|DJ^S&wq*# zp;_FFG!9_J)wRxlFEIN^s@3o?1!dDpl~{**FAIE+l8RA==4t5?k<=M1^p0q~+SP&t zXb|sC2Z3jX>R{6chGeSnw51ogK1x7|VkbeL|mo@^y0 z)qi9fU0n5_Wkt`%&>D!^07W}>c9Y?WXS0bgY(vk=ek)oSy54q<{%WL~0h>&>(nyas z&C|yA8jpQ;A1Hh%EV>yp^BLh_+!*54Twp^-pLG9vK*og=$A@o-_D%h1o$BiO*!ZA{ zezx9pvyn=((59_*ouquNXMVGhwfrkO$8obMZ1dZ()VI*|N|C>yXfYHqW-Ii{k%doGWmCHqjXUBZkgEoa*|UZj!xWbU(7 eJi>Am{)rd)n$fXLt#9izRwsJT;*^9CAp1Y~Cv<@T literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/corn_ne.gif b/ljcom/ssldocs/img/dys/corn_ne.gif new file mode 100644 index 0000000000000000000000000000000000000000..2337fa42dfee8eac943f568e7ed1a87c8ab118b1 GIT binary patch literal 102 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4f1f`6`~LkO5WINt?>`Qp_>+Z^fq{cT ihXDvcW-zb_3$Pe^7%DU;mp+R#YiV#`QxRZfum%7fy*G{k literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/corn_nw.gif b/ljcom/ssldocs/img/dys/corn_nw.gif new file mode 100644 index 0000000000000000000000000000000000000000..72ccbcb0d4bd95cc2d79f9b8e1e589c77448e255 GIT binary patch literal 102 zcmZ?wbhEHbWM^P!c+9}?@87@g-~WC3^zZH4e~%yiyLj>6^5ZXFy!iJY2T=UU!pOkD k!Jxwc1RygQScC;w3_T1#&&X|gc8nqKNJh*uNk#^107l6<_y7O^ literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/corn_se.gif b/ljcom/ssldocs/img/dys/corn_se.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1132508078b59feebde2d7e373a8d45d3de1388 GIT binary patch literal 101 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4e=lDA`}FDG_wWCJ;6Dza_>+Z^fq{cT hhXDvcW-zb_37qguU*Yf|&~xEDMwUYX67DPv)&T!~IQ{?t literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/corn_sw.gif b/ljcom/ssldocs/img/dys/corn_sw.gif new file mode 100644 index 0000000000000000000000000000000000000000..f7b1c257990b594ec4a7ddeb10a6e6495fd13e95 GIT binary patch literal 100 zcmZ?wbhEHbWM^P!c+9}C{P>HD7ymte^zZH4f1f`6d-3Am_wWCJ;6Dza_>+Z^fq{cT ghXDvcW-zb_3Y_3%n);||q36yvciD#u5rPcX0LCIYEdT%j literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/lg_crnrgif.gif b/ljcom/ssldocs/img/dys/lg_crnrgif.gif new file mode 100755 index 0000000000000000000000000000000000000000..3069c11446fd387256ab707e2bcdfc8a1ce51952 GIT binary patch literal 130 zcmZ?wbhEHb$yqW?0e5z+epkUKu8# literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/lock.gif b/ljcom/ssldocs/img/dys/lock.gif new file mode 100644 index 0000000000000000000000000000000000000000..aad54f938706d530ea01a6f291aadbd2ce712546 GIT binary patch literal 141 zcmZ?wbhEHb`jom)e47o@88c_Ex{OYV=+UDyKv&km{lg5xF(A2wOKta IfQ7*t0R6T_hX4Qo literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/login_but.gif b/ljcom/ssldocs/img/dys/login_but.gif new file mode 100755 index 0000000000000000000000000000000000000000..2438aad8ceaf8db84a405d602119034915c7a74f GIT binary patch literal 347 zcmZ?wbhEHbG+^LoIKsg2|Ns9F-+n%L^ZCN#HwSJ$+i>Cjf@3!)?77^q`AoseV+jlP z2Ta@P(6iZ~d5uElGJ%5m3~4j}F)}d_4HSQ}u!=AUGU$MGfb3*oy`iAcmy$Uz!^ z^}Yg~^AkMoSLAIz^3jf?DWjlbi$rTf$ASdY857bEp0E;#+I?&5R|y7=?$&^W5C$fW zHm8@#3<3h?2QCODG2YPC{#eQ>Ea1hX%gfcASCE%uQ=t=CTgt$##~shhz+}`>n9s)G zTh`YbRmafm9-mjGJ-Z`z*+SFB6G9p6bmwvKEAi>@@Gw=Z%@^QjVmw$L!MuMzpH~Ba z4dY&RhBJYzW`_#`y*5A4_E%xy)#XrOx;3Zs$iDu?#{Bz3^v_uuM*jHy}*y*TU5yZ>M)j+{cCXsWJk>%OpN#&m7pc&@+m?*G7` za2V-&I#Wq*Q&hF64#ii=5!jE|5z00ohimO=mnmz$h7009P_qN6GX0GXtzsviTV00gVC TvJ?carvjm~y0QiWrwIT%v0Y_` literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/logo1.gif b/ljcom/ssldocs/img/dys/logo1.gif new file mode 100755 index 0000000000000000000000000000000000000000..9462af8423f21e38ccacd332deddac3b113f01de GIT binary patch literal 2733 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 literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/logo2.gif b/ljcom/ssldocs/img/dys/logo2.gif new file mode 100755 index 0000000000000000000000000000000000000000..95e3d0c4cf1135ade7b6f7831115fc019dbed49c GIT binary patch literal 3874 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 kr6l@@@MFuHn<*rl0?6az{iEf5F*J1cMLO#lD@ literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/dys/logo3.gif b/ljcom/ssldocs/img/dys/logo3.gif new file mode 100755 index 0000000000000000000000000000000000000000..18498bbc654e204e125e0ac798bec15f4535fb64 GIT binary patch literal 1717 zcmeH`{X5eM0KmWIYvd&(Y%R;ug*z!T$CR$IwNlh1deO@kMrXz1YI)t-kWx`1@9Mlf z+%S>oI2%K0=A~h7rXkjyWs=Y(?&+_%U+(i4e4fwqeD-^haBkEXz!_KqfVH)?<)x+h z#m}?zi*p*yJGDkVJ+4ws%iqpUk1NI|RjRSUA?3`JykDl6d?S}l%U;Qcr-p~5V}s%~ zan8%(siFP}MQ>a8YlW((zGq-)`X%pOSLv`=AQp=yT?&Cj-Y$`8+OkI5d7T~dv9>Zv zM{{HM=#(I@qkUxRkF1tOn(bN8#mRGzMsglnYR`--W7f!R%z*z=h; zY-|sGZ-5^ay`=8fLy>+xSa5JKELj`Jevz(KQhCVn(&9qef$4pn@L=YuSJ1ITP}nBE zl71Q84RJX8@$UkpQb%G+{_fa_+^MIaHc`4#%pzPA;Yj|J6OOWNS*G6Z=q=)$Ia5ep z;LkafDNj{a*fcsJD3oWJe~OG_kw><{j0rCJV`m0+AWaV0e9A=jRk$NVWSzy-EmyB| zVjTQSAQEkultl$F*nVAiQ0`Ca)`Fv$O@&$hE)++yd@31@e15YiqMm4G@kmvERx;oK z-Eb7q!2vyjS@3wh22hAV5>tv14BVnF!Us`|hrWL*6@g?}x-#VqB}0HT4!(ij6hn;e z(9t)`z8^>mgPyQ#9m=TQC8E^dqZiunU}%JcpRdn9R7hzAwY3X zsVGygpMa7FzD8jncv>>dg@)@{(2n5`P>8z21*wXM;Yt-PKo@U<&x@M3NxJRA%?^co zG6h`l$m&Rr1(Zj9UF0gw!6zio4hayUi1hOHn~5KQl8nLz53}$W2pSz3+bExO4yyq1Sf84dcQu5g_>jVw0+2=F;y8B705qLNew(@+{Z~ZCP2IiD+h; zQ9aDCM82j~&z3jWW@xJ>z#3ybAm;JTD-l+Q0hq{Qy&3gG7doXm67?g3J%g}cCa1he z5HN_K3zJGP4B^v1_H3EVaHzg%0T6nOhE1S`_TYyOm=%t#EAe)%ibP>R2DH~ZeNJc+ zBK5_z#0yN4O)+tO9CMnQEHJU(UA6evzQNYMb@wwj617dW`~2GOZW=I0&?>);*~m^S>H-E7lDJXg51-Zu{OX_9t=$~CeQ zDM8D?#2v8{zmUhZ-&paAzvy3WFD4=`^zK+uGX>N*RDp5L%DmWBv+}WT|IV)q(&G_d pKgmLCzAlbl)qGu2rtDl@ew!V!`uSaX&FVkuXPVV73SAJ`{V&5Yj41#B literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/userinfo.gif b/ljcom/ssldocs/img/userinfo.gif new file mode 100644 index 0000000000000000000000000000000000000000..87c10f652192c0dd104df8425bfedd3d45768fe4 GIT binary patch literal 258 zcmZ?wbhEHb6l4%&I3mpe2H6Z8Qy4hzad0GaaJ=W>_|GA5OaKTZzDr01DJm*zYHAvS zz*r2V(@;Nm}H90nN+a~GY$U>X>X7k=J zi}Q06{@1l#al_P}*lDU9I>n6_0)%#BtNU$^<%}^{5x%0X) n&EDdKc?o|Wrx1gnP=}CUY6A}!BO?nh1Mk#nJ>hDK3=Gx)?5#@N literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/visa.jpg b/ljcom/ssldocs/img/visa.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ee5c46de006cdca165de5e03bf14828e29a070df GIT binary patch literal 33434 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 literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/xc/allbars.gif b/ljcom/ssldocs/img/xc/allbars.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a649bd42e3224b174e9fef694db2423119312bf GIT binary patch literal 231 zcmV`jom)e47o@88c_Ex{OYV=+UDyKv&km{lg5xF(A2wOKta IfQ7*t0R6T_hX4Qo literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/xc/logocombined.gif b/ljcom/ssldocs/img/xc/logocombined.gif new file mode 100644 index 0000000000000000000000000000000000000000..4277bb9d23e40e9762b6e89f02a19a65f7543d70 GIT binary patch literal 3004 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 literal 0 HcmV?d00001 diff --git a/ljcom/ssldocs/img/xc/normal-fonts.css b/ljcom/ssldocs/img/xc/normal-fonts.css new file mode 100644 index 0000000..76ceb0d --- /dev/null +++ b/ljcom/ssldocs/img/xc/normal-fonts.css @@ -0,0 +1,4 @@ +body, dd, dt, th, td, p, div, li, pre, code, kbd { font-size: small; } +h3 { font-size: medium; } +h2 { font-size: large; } +h1 { font-size: x-large; } \ No newline at end of file diff --git a/ljcom/ssldocs/img/xc/small-fonts.css b/ljcom/ssldocs/img/xc/small-fonts.css new file mode 100644 index 0000000..2ab5417 --- /dev/null +++ b/ljcom/ssldocs/img/xc/small-fonts.css @@ -0,0 +1,4 @@ +body, dd, dt, th, td, p, div, li, pre, code, kbd { font-size: x-small; } +h3 { font-size: small; } +h2 { font-size: medium; } +h1 { font-size: large; } \ No newline at end of file diff --git a/ljcom/ssldocs/index.bml b/ljcom/ssldocs/index.bml new file mode 100644 index 0000000..bae0e16 --- /dev/null +++ b/ljcom/ssldocs/index.bml @@ -0,0 +1,35 @@ +LiveJournal Secure Server +head<= + +<=head +body<= + + + + + + + +
      + +
    • Payments -- you build your order unencrypted first, then the "check out" action leads you into the secure server where you send your credit card info.
    • + +
    • Logging in -- you can log in with encryption so your password isn't sent across the net unprotected. Alternatively, if you have JavaScript support in your browser and no SSL access (perhaps due to a corporate firewall) we also implement "challenge/response" logins, which does crytography in JavaScript to avoid sending your password in cleartext across the net. Doing challenge/response only works when both parties (your browser and our server) already know your existing password. It does not work for creating accounts or changing passwords, when you have to send a new password to our servers. In those cases, you'll have to use SSL (the secure server) or risk a cleartext transmission.
    • + +
    • Creating an account -- you can create an account on the secure server, since creating an account requires a password which should be protected.
    • + +
    • Changing your password -- you can change your password on the secure server, since changing your password involves both sending your old and new passwords across the net, which should both be protected.
    • + +
    + + +<=body +page?> diff --git a/ljcom/ssldocs/pay/cc.bml b/ljcom/ssldocs/pay/cc.bml new file mode 100644 index 0000000..a99f871 --- /dev/null +++ b/ljcom/ssldocs/pay/cc.bml @@ -0,0 +1,194 @@ +Process Credit Card +body<= +{'r'}; + + my $cart = $GET{'c'}; + my $cartobj = LJ::Pay::load_cart($cart); + return BML::redirect("$LJ::SITEROOT/pay/") unless $cartobj; + + # cart tied to user? + if ($cartobj->{'userid'}) { + + my $remote = LJ::get_remote(); + return "You must be logged in as this cart's owner to proceed with checkout." + unless $remote; + return "You do not own this cart. If you'd like to start a new cart, please click " . + "here." + unless $cartobj->{'userid'} == $remote->{'userid'}; + } + + # if there is no userid, then we know it's clean because we checked + # each individual item for email blocks when they were added to the cart + + # is merchant gateway down? + return "" . + "" + if $LJ::AUTHNET_DOWN; + + my $needs_shipping = LJ::Pay::cart_needs_shipping($cartobj); + my $has_coppa = LJ::Pay::cart_contains_coppa($cartobj); + + my $amt_total = $cartobj->{amount}; + if ($amt_total <= 0 && $has_coppa) { + $amt_total = '0.01'; + } + + my $amt_charge = sprintf("%0.02f", $amt_total); + my $amt_pretty = "\$${amt_charge} USD"; + + my $ret; + $ret .= " 1 }); + $ret .= " p?>"; + + if ($cartobj->{'mailed'} ne "C") { + $ret .= ""; + return $ret; + } + + if ($needs_shipping && ! $POST{'confirm_address'}) { + my %payvar; + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT pkey, pval FROM payvars WHERE payid=? AND pkey LIKE 'ship%'"); + $sth->execute($cartobj->{'payid'}); + while (my ($k, $v)= $sth->fetchrow_array) { $payvar{$k} = $v; } + + my %country; + LJ::load_codes({ "country" => \%country }); + + $ret .= ""; + $ret .= "back to your order and check out again, correcting the shipping address. p?>
    "; + $ret .= "$payvar{'ship_name'}
    "; + $ret .= "$payvar{'ship_addr1'}
    "; + $ret .= "$payvar{'ship_addr2'}
    " if $payvar{'ship_addr2'}; + $ret .= "$payvar{'ship_city'}, $payvar{'ship_state'} $payvar{'ship_zip'}
    "; + my $ctry = uc($payvar{'ship_country'}); + if ($ctry ne "US") { + $ret .= $country{$ctry}; + } + $ret .= "
    "; + } + + unless (LJ::Pay::is_valid_cart($cartobj)) { + return "The given cart contains items that are no longer valid. This could be caused by conflicts with other " . + "carts created during the same time. Please try again with a new cart."; + } + + # if the amount is free then it was probably free before, but needed shipping + # so we had to get to this point before deciding whether to charge them anything + # or not. dont' need to collect credit card information + if ($cartobj->{'amount'} <= 0 && $needs_shipping && !$has_coppa) { + + unless ($POST{'confirm_address'}) { + $ret .= "
    "; + $ret .= LJ::html_submit('confirm_address', "Complete Order"); + $ret .= "
    "; + return $ret; + } + + # set this cart as ready to be processed, and 'free' method + my $dbh = LJ::get_db_writer(); + $dbh->do("UPDATE payments SET used='N', mailed='N', ". + "method='free', daterecv=NOW() WHERE payid=?", undef, + $cartobj->{'payid'}); + + $ret .= ""; + $ret .= ""; + return $ret; + } + + # tab index + my $tidx = 0; + $ret .= "
    "; + + # coppa stuff if cart contains age verification + if ($has_coppa) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + + $ret .= "
    "; + $ret .= "Parent or Guardian's Email Address: "; + $ret .= LJ::html_text({ name => 'paremail', size => '30', maxlength => '255', tabindex => ++$tidx }); + $ret .= "
    "; + } + + $ret .= ""; + if ($has_coppa && $cartobj->{amount} <= 0) { + $ret .= "Danga Interactive, "; + $ret .= "which is the legal name of the company that runs LiveJournal.com. Some banks do "; + $ret .= "not show authorization requests on billing statements. p?>"; + $ret .= "COPPA Age Verification item, "; + $ret .= "we will attempt verify that the information you have entered is correct and that at least $amt_pretty "; + $ret .= "is available on your card. However, you will not be charged. p?>"; + } else { + $ret .= "Danga Interactive, which is the legal name of the company that runs LiveJournal.com. p?>"; + } + $ret .= LJ::html_hidden("cart", $cart); + $ret .= LJ::html_hidden("amt_charge", $amt_charge); + $ret .= "
    "; + + $ret .= "\n"; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + if ($LJ::USE_CARD_CODE) { + $ret .= ""; + } + + $ret .= "\n"; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + my %countries; + LJ::load_codes({ "country" => \%countries }); + + $ret .= ""; + + $ret .= "\n"; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    Card Info
    Name on card:"; + $ret .= LJ::html_text({ name => 'cardname', size => '30', maxlength => '40', tabindex => ++$tidx}) . "
    Card Number:"; + $ret .= LJ::html_text({ name => 'cardnum', size => '22', maxlength => '22', tabindex => ++$tidx }) . "
    Expiration Date:"; + $ret .= LJ::html_text({ name => 'expdate_mm', size => '3', maxlength => '2', tabindex => ++$tidx }) . " / "; + $ret .= LJ::html_text({ name => 'expdate_yy', size => '4', maxlength => '4', tabindex => ++$tidx }) . " (mm/yy)
    Card Verification Number:"; + $ret .= LJ::html_text({ name => 'cardcode', size => '4', maxlength => '4', tabindex => ++$tidx }) . "
    Billing Address (for card verification)
    Address:"; + $ret .= LJ::html_text({ name => 'bill_addr', size => '30', maxlength => '40', tabindex => ++$tidx }) . "
    City:"; + $ret .= LJ::html_text({ name => 'bill_city', size => '30', maxlength => '40', tabindex => ++$tidx }) . "
    State:"; + $ret .= LJ::html_text({ name => 'bill_state', size => '20', maxlength => '40', tabindex => ++$tidx }) . " (code or full name)
    Zip/Postal Code:"; + $ret .= LJ::html_text({ name => 'bill_zip', size => '9', maxlength => '10', tabindex => ++$tidx }) . "
    Country:"; + $ret .= LJ::html_select({ name => 'bill_country', tabindex => ++$tidx }, + map { $_, $countries{$_} } + ("US", sort { $countries{$a} cmp $countries{$b} } keys %countries)); + $ret .= "
    Other Info
    Optional Receipt Email:"; + $ret .= LJ::html_text({ name => 'email', size => '30', maxlength => '50', tabindex => ++$tidx }) . "
    Amount:$amt_pretty
    "; + if ($has_coppa && $cartobj->{amount} <= 0) { + $ret .= LJ::html_submit(undef, 'Perform Authorization (No Charge)', { tabindex => ++$tidx }); + } else { + $ret .= LJ::html_submit(undef, 'Make Payment', { tabindex => ++$tidx }); + } + $ret .= "
    (Click once and wait)
    "; + + $ret .= ""; + return $ret; + +} +_code?> + +<=body +page?> + + diff --git a/ljcom/ssldocs/pay/ccpay.bml b/ljcom/ssldocs/pay/ccpay.bml new file mode 100644 index 0000000..5a5fa3c --- /dev/null +++ b/ljcom/ssldocs/pay/ccpay.bml @@ -0,0 +1,660 @@ +Pay with Credit Card +body<= +{r}; + my $uniq = $r->notes('uniq'); + + my $dbh = LJ::get_db_writer(); + my $cart = $POST{'cart'}; + my $remote = LJ::get_remote(); + my $remote_ip = LJ::get_remote_ip(); + + return BML::redirect("$LJ::SITEROOT/pay") unless LJ::did_post(); + + my $no_charge = "As a result of this error, your credit card has not been charged."; + + my $error = sub { + return LJ::bad_input($_[0], $no_charge); + }; + + # is merchant gateway down? + return "" . + "" + if $LJ::AUTHNET_DOWN; + + unless ($POST{'bill_country'} =~ /^\w+$/) { + return $error->("Please Go back and enter your country."); + } + + if ($POST{'bill_country'} eq "US") { + return $error->("Zip code required for credit card verification. Please go back and enter your zip code.") + unless $POST{'bill_zip'} =~ /\d+/; + } + + my $lockname = "authnet-$cart"; + my $gotlock = $dbh->selectrow_array("SELECT GET_LOCK(?,5)", undef, $lockname); + unless ($gotlock) { + return $error->("Error getting lock."); + } + my $unlock = sub { + $dbh->do("SELECT RELEASE_LOCK(?)", undef, $lockname); + }; + + # make $error unlock now + $error = sub { + $unlock->(); + return LJ::bad_input($_[0], $no_charge); + }; + + my $cartobj = LJ::Pay::load_cart($cart) + or return $error->("Order not found."); + + # do time-based rate-limiting + if (@LJ::MEMCACHE_SERVERS) { + + # start by checking rate keys for this cart + my @memkeys = ([$cartobj->{payid}, "cctry_payid:$cartobj->{payid}"]); + push @memkeys, [$cartobj->{userid}, "cctry_uid:$cartobj->{userid}"] + if $cartobj->{userid}; + push @memkeys, [$uniq, "cctry_uniq:$uniq"] + if $uniq; + + # now check rate keys for all of the items, but don't note duplicate + # email addresses/uids + my %emails = (); + my %userids = (); + foreach my $it (@{$cartobj->{items}}) { + if (my $uid = $it->{rcptid}) { + next if $userids{$uid} || $uid == $cartobj->{userid}; + $userids{$uid}++; + push @memkeys, [$uid, "cctry_uid:$uid"]; + } elsif (my $email = $it->{rcptemail}) { + next if $emails{$email}; + $emails{$email}++; + push @memkeys, [$email, "cctry_email:$email"]; + } + } + + my $now = time(); + my $cctry = LJ::MemCache::get_multi(@memkeys) || {}; + + my $exceeded = 0; # is the rate exceeded based on one of the time queues? + my $sendmail = 0; # was the 10 try threshold passed? eg: send an email + foreach my $memkey (@memkeys) { + + my $val = $cctry->{$memkey->[1]} || []; + my @try = grep { $_ >= $now - 3600*6 } @$val; + my $tries = scalar @try; + my $lasttry = $try[-1]; + + my $toofast = LJ::run_hook("ccpay_rate_check", $tries, $lasttry); + $exceeded = 1 if $toofast; + $sendmail = 1 if $tries == 10; # passed into "probably bot" territory + + # save this try + push @try, $now; + @try = @try[-20..-1] if @try > 20; + LJ::MemCache::set($memkey, \@try); + } + + # send an email if it's a moderately severe violation + # we send an email when they go over the 10 try mark, + # then not again since if they got this far they'll try + # multiple times and we don't want a flood of emails + if ($sendmail) { + my $passtxt; + $passtxt = "NOTE: Although this user has made 10+ tries to process their credit card, " . + "the most recent attempt (which triggered this email) has passed rate-limit " . + "checks. The behavior is still fishy and may require further investigation.\n\n" + unless $exceeded; + + LJ::send_mail({ + 'to' => $LJ::ACCOUNTS_EMAIL, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'wrap' => 1, + 'subject' => "CC rate limiting: payid: $cartobj->{payid}", + 'body' => "This warning has been sent because there have been at least 10 " . + "attempts to pay for order \#$cartobj->{payid} via credit card. " . + "No further emails will be sent about this incident since they are likely " . + "to continue trying, but here is relevant sysban information: \n\n" . + " Payid: $cartobj->{payid}\n" . + " Remote User: " . ($remote ? $remote->{user} : 'unknown') . "\n" . + " Remote IP: " . ($remote_ip || 'unknown') . "\n" . + " Uniq Cookie: " . ($uniq || 'unknown') . "\n\n" . + "Email addresses and userids have also been included in the rate checking. " . + "See $LJ::SITEROOT/admin/accounts/paiddetails.bml?payid=$cartobj->{payid} " . + "for more information.\n\n" . + $passtxt, + }); + } + + # see if they're voilating rate limits + if ($exceeded) { + return $error->("You are attempting to process credit card transactions too frequently. " . + "Your credit card has not been charged. Please wait a while then try again " . + "later. If the problem persists, please contact $LJ::ACCOUNTS_EMAIL."); + } + } + + # verify cart (check for items that have been invalidated since adding) + unless (LJ::Pay::is_valid_cart($cartobj)) { + return $error->("The given cart contains items that are no longer valid. This could be caused by conflicts with other " . + "carts created during the same time. Please try again with a new cart."); + } + + # now we have a cart object + if ($cartobj->{'userid'}) { + + return $error->("You must be logged in as this cart's owner to proceed with checkout.") + unless $remote; + + return $error->("You do not own this cart.") + unless $cartobj->{'userid'} == $remote->{'userid'}; + + if (LJ::sysban_check('pay_email', $remote->{'email'})) { + LJ::sysban_note($remote->{'userid'}, + "Payment blocked based on email", + { 'email' => $remote->{'email'}, + 'user' => $remote->{'user'}, + 'cart' => $cart }); + + return $error->("Sorry, we were unable to process your request."); + } + + if (LJ::sysban_check('pay_user', $remote->{'user'})) { + LJ::sysban_note($remote->{'userid'}, + "Payment blocked based on user", + { 'user' => $remote->{'user'}, 'cart' => $cart }); + + return $error->("Sorry, we were unable to process your request."); + } + } + + if ($uniq && LJ::sysban_check('pay_uniq', $uniq)) { + LJ::sysban_note($remote ? $remote->{'userid'} : 0, + "Payment blocked based on uniq", + { 'user' => $remote ? $remote->{'user'} : "(anon)", + 'uniq' => $uniq, + 'cart' => $cart }); + return $error->("Sorry, we were unable to process your request."); + } + + # if there is no userid, then we know it's clean because we checked + # each individual item for email blocks when they were added to the cart + + my $has_coppa = LJ::Pay::cart_contains_coppa($cartobj); + my $needs_shipping = LJ::Pay::cart_needs_shipping($cartobj); + + # coppa requires remote + if ($has_coppa && ! $remote) { + return $error->("You must be logged in as the account being verified (the child's account) in order to process an order containing an Age Verification item."); + } + + my $amt_total = $cartobj->{amount}; + my $coppa_only = 0; + if ($amt_total <= 0 && $has_coppa) { + $amt_total = '0.01'; + $coppa_only = 1; + } + + return $error->("Order amount is zero.") + unless $amt_total > 0; + + my $u; + if ($cartobj->{'userid'}) { + $u = LJ::load_userid($cartobj->{'userid'}); + LJ::load_user_props($u, 'allow_pay', 'fraud_watch'); + } + + my $country = LJ::LJcom::country_of_ip($remote_ip); + my $now = LJ::mysql_time(time()); + LJ::Pay::payvar_add($cartobj->{'payid'}, "geoip-country", "$now: country=$country ($remote_ip)"); + + # attempt to gather and store user's country/state + if ($POST{bill_country}) { + my $err; + my ($ctry, $st) = LJ::Pay::check_country_state($POST{bill_country}, $POST{bill_state}, \$err); + return $error->($err) if $err; + + # now save country and state in database + LJ::Pay::payid_set_state($cartobj->{payid}, $ctry, $st); + } + + my $from = sub { return lc($country) eq $_[0] || lc($POST{'bill_country'}) eq $_[0] }; + + # stop Russian/Ukrainian credit card theft + if ($from->('ru') || $from->('ua')) { + + # see if we should force the user to be allowed to pay + unless ($u && $u->{'allow_pay'} eq 'Y') { + + # if cart needs shipping, don't accept any card or address from Russia/Ukraine + return $error->("We do not currently accept credit card payments from Russia or the Ukraine on shipped goods.") + if $needs_shipping; + + # if cart doesn't need shipping, bill country and country must match if either is Russia/Ukraine + return $error->("The country of your Internet address does not match the country of your credit card. From here you can:
      " . + "
    • Use a different payment method or credit card.
    • Pay using an Internet connection in your credit card's country.
    • " . + "
    • Contact $LJ::SITENAME support and explain your situation. We may be able to help.
    ") + unless lc($country) eq lc($POST{'bill_country'}); + } + + # otherwise we've decided to allow this user, log + LJ::Pay::payvar_add($cartobj->{'payid'}, "allow_pay", + "$now: cc=$POST{'bill_country'}, actual=$country, user=$u->{'user'} (allowed)"); + } + + # throw an error if they didn't provide a parent's email + my $paremail; + if ($has_coppa) { + $paremail = $POST{paremail}; + + my @email_errors; + push @email_errors, "You must enter a parent email address to proceed with COPPA Age Verification." + unless $paremail; + push @email_errors, "The parental email address must not match your account's email address." + if lc $remote->{email} eq lc $paremail; # ignore case changes + + LJ::check_email($paremail, \@email_errors); + + # throw message if necessary + return $error->(@email_errors) if @email_errors; + } + + my $setup_coppa_email_validation = sub { + # register an auth action + my $aa = LJ::register_authaction($remote->{userid}, "parentemail", $paremail) + or return $error->("Unable to register authaction."); + + # now send the verification email + LJ::send_mail({ + to => $paremail, + from => $LJ::SUPPORT_EMAIL, + subject => "$LJ::SITENAME Parent Email Verification", + wrap => 1, + body => qq{ +Welcome, you have attempted to create a $LJ::SITENAME account for your child. + +By activating this account you certify that you have read our Children's +Online Privacy Protection Act disclosure, Terms of Service and Privacy +Policy and that you agree to them. + + COPPA Disclosure + $LJ::SITEROOT/legal/coppa.bml + + Terms of Service + $LJ::SITEROOT/legal/tos.bml + + Privacy Policy + $LJ::SITEROOT/legal/privacy.bml + +To complete your child's journal creation and verify your email address, +you must click on the link below. + +$LJ::SITEROOT/agecheck/consent.bml?c=$aa->{aaid}.$aa->{authcode} + +(If you are unable to click on the link, copy it into your browser.) + +Your child may access his or her journal at the following two URLs: + + $LJ::SITEROOT/users/$remote->{user}/ + $LJ::SITEROOT/~$remote->{user}/ + +Below is the $LJ::SITENAME username that was registered: + + Username: $remote->{user} + +If your child needs to retrieve his or her password, they can do so at any +time by visiting the following URL: + + $LJ::SITEROOT/lostinfo.bml + +Enjoy! + +$LJ::SITENAME Team +$LJ::SITEROOT/ +}, + }); + + }; + + my $success = sub { + my $ret; + + if ($coppa_only) { + $ret .= ""; + $ret .= "COPPA Age Verification. Parents, please check your email: you should shortly receive a verification message. As soon as you get the email and click the link inside, your child's account will be fully active. p?>"; + $setup_coppa_email_validation->(); + + } else { + $ret .= ""; + $ret .= ""; + + if ($has_coppa) { + $ret .= "COPPA Age Verification. Parents, please check your email: you should shortly receive a verification email. As soon as you get the email and click the link inside, your child's account will be fully active. p?>"; + $setup_coppa_email_validation->(); + } + } + + if ($needs_shipping) { + $ret .= "Notice: Your email receipt from Authorize.net (our credit card processor) won't contain shipping information. Don't worry... that information is stored in our database. p?>"; + } + + $ret .= " 1 }); + $ret .= " p?>"; + + $unlock->(); + return $ret; + }; + + if ($cartobj->{'mailed'} ne "C") { + # not in cart state anymore. + # double-clicked? tell them it's all good. + return $success->(); + } + + my $amt_charge = sprintf("%0.02f", $amt_total); + if ($amt_charge ne $POST{'amt_charge'}) { + return $error->("Unexpected error: order amount changed from time you entered card info until now."); + } + + my $cardnum = $POST{'cardnum'}; + $cardnum =~ s![^\d]!!g; # remove non-numbers + my $expdate = sprintf("%02d%02d", $POST{'expdate_mm'}, $POST{'expdate_yy'} % 100); + + my $cardcode = $POST{'cardcode'}; + $cardcode =~ s!\s+!!g; # remove non-numbers + if ($LJ::USE_CARD_CODE) { + return $error->("You must provide your full card verification number for this transaction.") + unless $cardcode =~ /^\d{3,}$/; + } + + # blocked credit card? + $cardnum =~ /^(\d\d\d\d).*(\d\d\d\d)$/; + if (LJ::sysban_check('pay_cc', "$1-$2")) { + + my $vars = { 'cart' => $cart }; + + # no remote, there's not much useful information + # so we'll see who they were buying for + unless ($remote) { + # get usernames of people they're trying to buy for + my %rcpt_users = (); + my $ct = 0; + LJ::load_userids_multiple([ map { $_->{'rcptid'} => \$rcpt_users{"rcpt_user_" . ++$ct} } @{$cartobj->{'items'}} ]); + + # fill in vars to log + $ct = 0; + map { $ct++, $vars->{"rcpt_email_$ct"} = $_->{'rcptemail'} + if $_->{'rcptemail'} } @{$cartobj->{'items'}}; + $ct = 0; + map { $ct++, $vars->{"rcpt_user_$ct"} = $rcpt_users{$_}->{'user'} + if $rcpt_users{$_}->{'user'} } keys %rcpt_users; + } else { + $vars->{'email'} => $remote->{'email'}; + $vars->{'user'} => $remote->{'user'}; + } + + LJ::sysban_note($remote ? $remote->{'userid'} : 0, + "Payment blocked based on credit card", $vars); + + return $error->("We are unable to process the card given."); + } + + # send fraud watch emails if necessary + LJ::Pay::send_fraud_email($cartobj, $u); + + # AUTHORIZE: see if the AVS information is accurate the the account is in good standing + my $ua = new LWP::UserAgent; + $ua->agent("LJ-AuthNet/1.0"); + my $vars = { + 'x_Version' => '3.1', + 'x_Delim_Data' => 'True', + 'x_Login' => $LJ::AUTHNET_USER, + 'x_Password' => $LJ::AUTHNET_PASS, + 'x_Card_Num' => $cardnum, + 'x_Exp_Date' => $expdate, + 'x_Amount' => $amt_charge, + 'x_Email' => $POST{'email'}, + 'x_Email_Customer' => ($coppa_only ? 'FALSE' : 'TRUE'), # don't email receipts for coppa verifications + 'x_Customer_IP' => $remote_ip, + 'x_Cust_ID' => $cartobj->{'userid'}, + 'x_Type' => 'AUTH_ONLY', + 'x_Invoice_Num' => $cart, # max 20, big enough + 'x_Address' => $POST{'bill_addr'}, + 'x_City' => $POST{'bill_city'}, + 'x_State' => $POST{'bill_state'}, + 'x_Zip' => $POST{'bill_zip'}, + 'x_Country' => $POST{'bill_country'}, + 'x_Merchant_Email' => $LJ::AUTHNET_MERCHANT, + }; + $vars->{'x_Card_Code'} = $cardcode if $LJ::USE_CARD_CODE; + $vars->{'x_Test_Request'} = 'TRUE' if $LJ::AUTHNET_TEST; + + my $req = new HTTP::Request POST => 'https://secure.authorize.net/gateway/transact.dll'; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(join("&", map { LJ::eurl($_) . "=" . LJ::eurl($vars->{$_}) } keys %$vars)); + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + + my ($ct, $auth_pass, $err); + my @fields; + if ($res->is_success) { + $ct = $res->content; + + # did authorization pass? + @fields = split(/,/, $ct); + $auth_pass = $fields[0] == 1; + $err = $fields[3] unless $auth_pass; + + } else { + $err = "Could not contact payment gateway."; + } + + my $txn_id = $fields[6]; + + $dbh->do("INSERT INTO authnetlog (payid, cmd, datesent, ip, amt, result, response) ". + "VALUES (?,'authonly',NOW(),?,?,?,?)", undef, + $cartobj->{'payid'}, $remote_ip, $amt_charge, $auth_pass ? "pass" : "fail", $ct); + + my %payvars = ( + 'an-ip' => $remote_ip, + 'an-email' => $POST{'email'}, + 'an-cardname' => $POST{'cardname'}, + ); + + $payvars{'an-avs'} = join('|', map { $POST{"bill_$_"} } qw(addr city state zip country)); + + my $cap_pass; + my $cap_txn_id; + + # CAPTURE: now it's time to get the money, if there were no AVS errors + if ($auth_pass && ! $coppa_only) { + my $vars = { + 'x_Version' => '3.1', + 'x_Delim_Data' => 'True', + 'x_Login' => $LJ::AUTHNET_USER, + 'x_Password' => $LJ::AUTHNET_PASS, + 'x_Trans_ID' => $txn_id, + 'x_Type' => 'PRIOR_AUTH_CAPTURE', + }; + $vars->{'x_Test_Request'} = 'TRUE' if $LJ::AUTHNET_TEST; + my $req = new HTTP::Request POST => 'https://secure.authorize.net/gateway/transact.dll'; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(join("&", map { LJ::eurl($_) . "=" . LJ::eurl($vars->{$_}) } keys %$vars)); + my $res = $ua->request($req); + my $ct; + my @fields; + if ($res->is_success) { + $ct = $res->content; + + # did capture pass? + @fields = split(/,/, $ct); + $cap_pass = $fields[0] == 1; + $err = $fields[3] unless $cap_pass; + + } else { + $err = "Could not contact payment gateway."; + } + + $cap_txn_id = $fields[6]; + + $dbh->do("INSERT INTO authnetlog (payid, cmd, datesent, ip, amt, result, response) ". + "VALUES (?,'priorcap',NOW(),?,?,?,?)", undef, + $cartobj->{'payid'}, $remote_ip, $amt_charge, $cap_pass ? "pass" : "fail", $ct); + + # keep track of trans ID & card fingerprint to enable refunds if necessary + if ($cap_pass) { + $cardnum =~ /^(\d\d\d\d).*(\d\d\d\d)$/; + $payvars{'an-refund'} = join(",", $cap_txn_id, $expdate, $1, $2); + $dbh->do("UPDATE payments SET used='N', mailed='N', ". + "method='cc', daterecv=NOW() WHERE payid=?", undef, + $cartobj->{'payid'}); + } + + # VOID: if capture failed, uncapture their fund + # 0: 2 means declined + # 1: 2 means declined + # 3: 27 means AVS mismat + if ($fields[0] == 2 && $fields[1] == 2 && $fields[2] == 27 && $txn_id) { + my $vars = { + 'x_Version' => '3.1', + 'x_Delim_Data' => 'True', + 'x_Login' => $LJ::AUTHNET_USER, + 'x_Password' => $LJ::AUTHNET_PASS, + 'x_Trans_ID' => $txn_id, + 'x_Type' => 'VOID', + }; + $vars->{'x_Test_Request'} = 'TRUE' if $LJ::AUTHNET_TEST; + my $req = new HTTP::Request POST => 'https://secure.authorize.net/gateway/transact.dll'; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(join("&", map { LJ::eurl($_) . "=" . LJ::eurl($vars->{$_}) } keys %$vars)); + my $res = $ua->request($req); + my $ct; + if ($res->is_success) { + $ct = $res->content; + } + my @fields = split(/,/, $ct); + my $pass = $fields[0] == 1; + + $dbh->do("INSERT INTO authnetlog (payid, cmd, datesent, ip, amt, result, response) ". + "VALUES (?,'void',NOW(),?,?,?,?)", undef, + $cartobj->{'payid'}, $remote_ip, 0.00, $pass ? "pass" : "fail", $ct); + } + } + + # save payvars in db now + foreach (keys %payvars) { + next unless $payvars{$_}; + LJ::Pay::payvar_add($cartobj->{'payid'}, $_, $payvars{$_}); + } + + # if a failure, note in ccfail table and possibly notify admins + unless ($auth_pass && ($coppa_only || $cap_pass)) { + + # note that we've failed once again + my %done; + my $emailtxt; + foreach my $it ([$cartobj->{'userid'}, $cartobj->{'rcptemail'}], + map { [ $_->{'rcptid'}, $_->{'rcptemail'} ] } @{$cartobj->{'items'}}) { + + my $userid = $it->[0]; + my $email = $it->[1]; + my $user = $email; + if ($userid) { + my $u = LJ::load_userid($userid); + $email = $u->{'email'}; + $user = $u->{'user'}; + } + + next if $done{$email}; + $done{$email}++; + + # get failures within the last 30 days + my $failct = $dbh->selectrow_array("SELECT COUNT(*) FROM ccfail " . + "WHERE email=? AND time>UNIX_TIMESTAMP()-3600*24*30", + undef, $email); + + # see if we've passed the threshold + $failct++; + if ($LJ::CCFAIL_NOTIFY && $failct % $LJ::CCFAIL_NOTIFY == 0) { + my $now = LJ::mysql_time(); + + my $lastmailct = $failct - $LJ::CCFAIL_NOTIFY; # pretty good guess + $emailtxt .= + " User: " . ($user || $email) . "\n" . + " Failures: $failct\n" . + " Last Mail: $lastmailct failures\n" . + " Payid: $cartobj->{'payid'}\n" . + " Time: $now\n\n"; + + } + + # now update table in db + $dbh->do("REPLACE INTO ccfail (email, time, userid) " . + "VALUES (?, UNIX_TIMESTAMP(), ?)", + undef, $email, $userid); + } + + # send out the combined email now + LJ::send_mail({ + 'to' => $LJ::ACCOUNTS_EMAIL, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'wrap' => 1, + 'subject' => "CC Payment Failure Notification: Payment #$cartobj->{'payid'}", + 'body' => "This warning has been sent because the following AVS failure " . + "has occurred on $LJ::SITENAMESHORT.\n\n" . + + " Payid: $cartobj->{'payid'}\n" . + " Time: " . LJ::mysql_time() . "\n\n" . + + "Below are failure stats for each user listed on this cart.\n\n" . + + $emailtxt, + + }) if $emailtxt; + + } + + if ($err) { + $unlock->(); + return "Error processing payment: $err" . + "

    It is possible that your bank has placed a temporary hold on the funds ". + "for this authorization, but they should be released after a short ". + "period of time. Your card has not been charged.

    " . + + "

    For more information on AVS and credit card transactions, " . + "" . + "please see the FAQ.

    "; + } + + # if the order amount is 0, mark this cart as free. this catches + # coppa-only orders and orders containing coppa which needed to + # continue to the cc.bml page + if ($cartobj->{amount} <= 0) { + $dbh->do("UPDATE payments SET used='N', mailed='N', ". + "method='free', daterecv=NOW() WHERE payid=?", undef, + $cartobj->{'payid'}); + } + + # if the order was processed successfully, we'll mark the user with allow_pay + LJ::Pay::note_payment_from_user($u); + + # $success->() will call $unlock->() for us + return $success->(); +} +_code?> +<=body +page?> + + diff --git a/ljcom/ssldocs/pay/cvv2.bml b/ljcom/ssldocs/pay/cvv2.bml new file mode 100644 index 0000000..cdf4c9b --- /dev/null +++ b/ljcom/ssldocs/pay/cvv2.bml @@ -0,0 +1,17 @@ +Credit Card Verification +body<= + + +
      +
    • Your credit card is in your possession.
    • +
    • Your credit card account is legitimate.
    • +
    + + +
    +On a Visa, Eurocard/MasterCard, or Discover credit card, the verification number is the three digits to the right of the credit card number in the signature area on the back of the card. p?> +
    +On an American Express credit card, the verification number is the four digits printed (not embossed) on the front of the card above the credit card number. p?> +<=body +page?> diff --git a/ljcom/ssldocs/pay/index.bml b/ljcom/ssldocs/pay/index.bml new file mode 100644 index 0000000..cab37a9 --- /dev/null +++ b/ljcom/ssldocs/pay/index.bml @@ -0,0 +1,3 @@ + diff --git a/local/bin/checkconfig.pl b/local/bin/checkconfig.pl new file mode 100755 index 0000000..0f74f40 --- /dev/null +++ b/local/bin/checkconfig.pl @@ -0,0 +1,206 @@ +#!/usr/bin/perl +# + +my @errors; +my $err = sub { + return unless @_; + die "Problem:\n" . join('', map { " * $_\n" } @_); +}; + +my %dochecks; # these are the ones we'll actually do +my @checks = ( # put these in the order they should be checked in + "modules", + "modules_print", + "env", + "database" +); +foreach my $check (@checks) { $dochecks{$check} = 1; } + +my $only = 0; + +arg: foreach my $arg (@ARGV) { + ($w, $c) = ($arg =~ /^-(no|only)(.*)/) or die "unknown option $arg"; + die "only one '-onlyfoo' option may be specified" if $w eq "only" and $only++; + foreach my $check (@checks) { + if ($check eq $c) { + if ($w eq "only") { %dochecks = ( $check => 1 ); } + else { $dochecks{$check} = 0 } + next arg; + } + } + die "unknown check '$c' (known checks: " . join(", ", @checks) . ")\n"; +} + +my %modules = ( + "DBI" => { 'deb' => 'libdbi-perl', }, + "DBD::mysql" => { 'deb' => 'libdbd-mysql-perl', }, + "Digest::MD5" => { 'deb' => 'libdigest-md5-perl', }, + "Digest::SHA1" => { 'deb' => 'libdigest-sha1-perl', }, + "Image::Size" => { 'deb' => 'libimage-size-perl', }, + "MIME::Lite" => { 'deb' => 'libmime-lite-perl', }, + "MIME::Words" => { 'deb' => 'libmime-perl', }, + "Compress::Zlib" => { 'deb' => 'libcompress-zlib-perl', }, + "Net::SMTP" => { + 'deb' => 'libnet-perl', + 'opt' => "Alternative to piping into sendmail to send mail.", + }, + "Net::DNS" => { + 'deb' => 'libnet-dns-perl', + }, + "MIME::Base64" => { 'deb' => 'libmime-base64-perl' }, + "URI::URL" => { 'deb' => 'liburi-perl' }, + "HTML::Tagset" => { 'deb' => 'libhtml-tagset-perl' }, + "HTML::Parser" => { 'deb' => 'libhtml-parser-perl', }, + "LWP::Simple" => { 'deb' => 'libwww-perl', }, + "LWP::UserAgent" => { 'deb' => 'libwww-perl', }, + "GD" => { 'deb' => 'libgd-perl' }, + "GD::Graph" => { + 'deb' => 'libgd-graph-perl', + 'opt' => 'Required to make graphs for the statistics page.', + }, + "Mail::Address" => { 'deb' => 'libmailtools-perl', }, + "Proc::ProcessTable" => { + 'deb' => 'libproc-process-perl', + 'opt' => "Better reliability for starting daemons necessary for high-traffic installations.", + }, + "RPC::XML" => { + 'deb' => 'librpc-xml-perl', + 'opt' => 'Required for outgoing XMLRPC support', + }, + "SOAP::Lite" => { + 'deb' => 'libsoap-lite-perl', + 'opt' => 'Required for XML-RPC support.', + }, + "Unicode::MapUTF8" => { 'deb' => 'libunicode-maputf8-perl', }, + "Storable" => { + 'deb' => 'libstorable-perl', + }, + "XML::RSS" => { + 'deb' => 'libxml-rss-perl', + 'opt' => 'Required for retrieving RSS off of other sites (syndication).', + }, + "XML::Simple" => { + 'deb' => 'libxml-simple-perl', + 'ver' => 2.12, + }, + "String::CRC32" => { + 'deb' => 'libstring-crc32-perl', + 'opt' => 'Required for palette-altering of PNG files. Only necessary if you plan to make your own S2 styles that use PNGs, not GIFs.', + }, + "Time::HiRes" => { 'deb' => 'libtime-hires-perl' }, + "IO::WrapTie" => { 'deb' => 'libio-stringy-perl' }, + "XML::Atom" => { + 'deb' => 'libxml-atom-perl', + 'opt' => 'Required for AtomAPI support.', + }, + "Math::BigInt::GMP" => { + 'opt' => 'Aides Crypt::DH so it isn\'t crazy slow.', + }, + "URI::Fetch" => { + 'opt' => 'Required for OpenID support.', + }, + "Crypt::DH" => { + 'opt' => 'Required for OpenID support.', + }, + ); + +sub check_modules_print { + print "[Printing required Perl Modules...]\n"; + foreach my $mod (sort keys %modules) { + print $mod . + ($modules{$mod}->{'ver'} ? " >= " . $modules{$mod}->{'ver'} : "") . + ($modules{$mod}->{'opt'} ? " -- " . $modules{$mod}->{'opt'} : "") . + "\n"; + } +} + +sub check_modules { + print "[Checking for Perl Modules....]\n"; + + my @debs; + + foreach my $mod (sort keys %modules) { + my $rv = eval "use $mod;"; + if ($@) { + my $dt = $modules{$mod}; + if ($dt->{'opt'}) { + print STDERR "Missing optional module $mod: $dt->{'opt'}\n"; + } else { + push @errors, "Missing perl module: $mod"; + } + push @debs, $dt->{'deb'} if $dt->{'deb'}; + next; + } + + my $ver_want = $modules{$mod}{ver}; + my $ver_got = $mod->VERSION; + if ($ver_want && $ver_got && $ver_got < $ver_want) { + push @errors, "Out of date module: $mod (need $ver_want, $ver_got installed)"; + } + } + if (@debs && -e '/etc/debian_version') { + print STDERR "\n# apt-get install ", join(' ', @debs), "\n\n"; + } + + $err->(@errors); +} + +sub check_env { + print "[Checking LJ Environment...]\n"; + + $err->("\$LJHOME environment variable not set.") + unless $ENV{'LJHOME'}; + $err->("\$LJHOME directory doesn't exist ($ENV{'LJHOME'})") + unless -d $ENV{'LJHOME'}; + + # before ljconfig.pl is called, we want to call the site-local checkconfig, + # otherwise ljconfig.pl might load ljconfig-local.pl, which maybe load + # new modules to implement site-specific hooks. + my $local_config = "$ENV{'LJHOME'}/bin/checkconfig-local.pl"; + if (-e $local_config) { + my $good = eval { require $local_config; }; + exit 1 unless $good; + } + + $err->("No ljconfig.pl file found at $ENV{'LJHOME'}/cgi-bin/ljconfig.pl") + unless -e "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + + eval { require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; }; + $err->("Failed to load ljlib.pl: $@") if $@; + + # if SMTP_SERVER is set, then Net::SMTP is required, not optional. + if ($LJ::SMTP_SERVER && ! defined $Net::SMTP::VERSION) { + $err->("Net::SMTP isn't available, and you have \$LJ::SMTP_SERVER set."); + } +} + +sub check_database { + print "[Checking Database...]\n"; + + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + my $dbh = LJ::get_dbh("master"); + unless ($dbh) { + $err->("Couldn't get master database handle."); + } + foreach my $c (@LJ::CLUSTERS) { + my $dbc = LJ::get_cluster_master($c); + next if $dbc; + $err->("Couldn't get db handle for cluster \#$c"); + } + + if (%LJ::MOGILEFS_CONFIG && $LJ::MOGILEFS_CONFIG{hosts}) { + print "[Checking MogileFS client.]\n"; + my $mog = LJ::mogclient(); + die "Couldn't create mogilefs client." unless $mog; + } +} + +foreach my $check (@checks) { + next unless $dochecks{$check}; + my $cn = "check_".$check; + &$cn; +} +print "All good.\n"; +print "NOTE: checkconfig.pl doesn't check everything yet\n"; + + diff --git a/local/bin/ljr-tools/clean_cached_comments.pl b/local/bin/ljr-tools/clean_cached_comments.pl new file mode 100755 index 0000000..4968fac --- /dev/null +++ b/local/bin/ljr-tools/clean_cached_comments.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +# remote user id of user to clean +my $ru_id = 491; + +# database connection +my $queue_db = "livejournal"; +my $queue_host = "localhost"; +my $queue_login = "lj"; +my $queue_pass = "lj-upyri"; + + +use strict; # preventing my program from doing bad things +use DBI; # http://dbi.perl.org + +$| = 1; # unbuffered (almost) output + +my $dbh = DBI->connect( + "DBI:mysql:$queue_db:$queue_host", + $queue_login, $queue_pass, + {RaiseError => 0, AutoCommit => 1} + ) || die "Can't open database connection: $DBI::errstr"; + +my $sth = $dbh->prepare("select * from ljr_remote_users where ru_id = $ru_id"); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) { + if ($row->{created_comments_maxid} > 0) { + die "User has created comments. Cannot clean cached comments (IMPLEMENT THIS!)\n"; + } + + my $sth1 = $dbh->prepare("select * from ljr_cached_users where ru_id = $ru_id"); + $sth1->execute(); + my $row1 = $sth1->fetchrow_hashref; + + print + "You're about to delete cached comments for user [" . + $row1->{remote_username} . "].\n" . + "Please confirm by typing their username: " + ; + while (<>) { + my $iu = $_; + + if ($iu =~ /\s*(.*)\s*/) { + $iu = $1; + } + + if ($iu ne $row1->{remote_username}) { + die "You have to learn to type letters to use this tool.\n"; + } + last; + } + $sth1->finish; + + print "deleting cached comprops...\n"; + $sth1 = $dbh->prepare("select * from ljr_cached_comments where ru_id = $ru_id"); + $sth1->execute(); + while ($row1 = $sth1->fetchrow_hashref) { + my $sth2 = $dbh->prepare( + "delete from ljr_cached_comprops where cc_id = " . $row1->{cc_id} + ); + $sth2->execute(); + $sth2->finish; + print "."; + } + $sth1->finish; + + print "deleting cached comments...\n"; + $sth1 = $dbh->prepare( + "delete from ljr_cached_comments where ru_id = " . $ru_id + ); + $sth1->execute(); + $sth1->finish; + + print "resetting cached counters...\n"; + $sth1 = $dbh->prepare( + "update ljr_cached_users + set remote_meta_maxid = 0, cached_comments_maxid = 0 + where ru_id = " . $ru_id); + $sth1->execute(); + $sth1->finish; +} +$sth->finish; + +$dbh->disconnect; diff --git a/local/bin/ljr-tools/copy_openid_infos.pl b/local/bin/ljr-tools/copy_openid_infos.pl new file mode 100755 index 0000000..316052a --- /dev/null +++ b/local/bin/ljr-tools/copy_openid_infos.pl @@ -0,0 +1,94 @@ +#!/usr/bin/perl + +# database connection +my $queue_db = "livejournal"; +my $queue_host = "localhost"; +my $queue_login = "lj"; +my $queue_pass = "lj-upyri"; + + +use strict; # preventing my program from doing bad things +use DBI; # http://dbi.perl.org + +$| = 1; # unbuffered (almost) output + +my $dbh = DBI->connect( + "DBI:mysql:$queue_db:$queue_host", + $queue_login, $queue_pass, + {RaiseError => 0, AutoCommit => 1} + ) || die "Can't open database connection: $DBI::errstr"; + + +my $username; +my $new_identity; + +my $sth = $dbh->prepare( + "select * from identitymap where idtype='O' and identity like 'http://www.livejournal.com/%'"); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) { + $username = ""; + + if ($row->{"identity"} =~ /\/users\/(.+[^\/])\/??/ || $row->{"identity"} =~ /\/\~(.+[^\/])\/??/) { + my $new_id; + my $old_email; + my $new_email; + my $sth2; + + $username = $1; + $new_identity = ""; + + if ($username =~ /^_/ || $username =~ /_$/) { + $new_identity = "http://users.livejournal.com/" . $username . "/"; + } + else { + $new_identity = "http://" . $username . ".livejournal.com/"; + } + + $sth2 = $dbh->prepare("select email from user where userid = " . $row->{"userid"}); + $sth2->execute; + if (my $row1 = $sth2->fetchrow_hashref) { + $old_email = $row1->{"email"}; + } + $sth2->finish; + + $sth2 = $dbh->prepare( + "select * from identitymap where idtype='O' and identity ='" . $new_identity . "'"); + $sth2->execute(); + if (my $row1 = $sth2->fetchrow_hashref) { + $new_id = $row1->{"userid"}; + + my $sth3 = $dbh->prepare("select email from user where userid = " . $new_id); + $sth3->execute; + if (my $row2 = $sth3->fetchrow_hashref) { + $new_email = $row2->{"email"}; + } + $sth3->finish; + + print + $username . "(" . + $row->{"userid"} . ", " . $old_email . "):(" . + $new_id . "," . $new_email . ")\n"; + } + $sth2->finish; + + if (!$new_id) { + $sth2 = $dbh->prepare( + "update identitymap set identity = '" . $new_identity . "' " . + "where idtype='O' and userid = " . $row->{"userid"} + ); + $sth2->execute(); + $sth2->finish; + } + else { + if (!$new_email) { + $sth2 = $dbh->prepare("update user set email = '" . $old_email . "' " . + "where userid = " . $new_id); + $sth2->execute(); + $sth2->finish; + } + } + } +} +$sth->finish; + +$dbh->disconnect; diff --git a/local/bin/ljr-tools/delete_imported.pl b/local/bin/ljr-tools/delete_imported.pl new file mode 100755 index 0000000..e9606df --- /dev/null +++ b/local/bin/ljr-tools/delete_imported.pl @@ -0,0 +1,113 @@ +#!/usr/bin/perl + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl"; + + +# remote user id of user to clean +my $ru_id = 27850; + +# database connection +my $queue_db = "livejournal"; +my $queue_host = "localhost"; +my $queue_login = "lj"; +my $queue_pass = "lj-upyri"; + + +use strict; # preventing my program from doing bad things +use DBI; # http://dbi.perl.org + +$| = 1; # unbuffered (almost) output + +my $dbh = DBI->connect( + "DBI:mysql:$queue_db:$queue_host", + $queue_login, $queue_pass, + {RaiseError => 0, AutoCommit => 1} + ) || die "Can't open database connection: $DBI::errstr"; + +my $sth = $dbh->prepare("select * from ljr_remote_users where ru_id = $ru_id"); +$sth->execute; +while (my $row = $sth->fetchrow_hashref) { + if (! $row->{ru_id}) { + die "User not found.\n"; + } + + my $sth1 = $dbh->prepare("select * from ljr_cached_users where ru_id = $ru_id"); + $sth1->execute(); + my $row1 = $sth1->fetchrow_hashref; + + print + "You're about to delete user [" . + $row1->{remote_username} . "].\n" . + "Please confirm by typing their username: " + ; + while (<>) { + my $iu = $_; + if ($iu =~ /\s*(.*)\s*/) { $iu = $1; } + if ($iu ne $row1->{remote_username}) { + die "You have to learn to type letters to use this tool.\n"; + } + last; + } + $sth1->finish; + + print "deleting cached comprops and remote comments...\n"; + $sth1 = $dbh->prepare("select * from ljr_cached_comments where ru_id = $ru_id"); + $sth1->execute(); + while ($row1 = $sth1->fetchrow_hashref) { + my $sth2 = $dbh->prepare("delete from ljr_cached_comprops where cc_id = " . $row1->{cc_id}); + $sth2->execute(); + $sth2->finish; + + $sth2 = $dbh->prepare("delete from ljr_remote_comments where cc_id = " . $row1->{cc_id}); + $sth2->execute(); + $sth2->finish; + + print "."; + } + $sth1->finish; + + print "deleting cached comments...\n"; + $sth1 = $dbh->prepare("delete from ljr_cached_comments where ru_id = $ru_id"); + $sth1->execute(); + $sth1->finish; + + print "deleting ljr_cached_userpics...\n"; + $sth1 = $dbh->prepare("delete from ljr_cached_userpics where ru_id = $ru_id"); + $sth1->execute(); + $sth1->finish; + + print "deleting ljr_cached_users...\n"; + $sth1 = $dbh->prepare("delete from ljr_cached_users where ru_id = $ru_id"); + $sth1->execute(); + $sth1->finish; + + print "deleting local entries...\n"; + my $lu; + $sth1 = $dbh->prepare("select * from ljr_remote_entries where ru_id = $ru_id"); + $sth1->execute(); + while ($row1 = $sth1->fetchrow_hashref) { + $lu = LJ::load_userid($row1->{"local_journalid"}) unless $lu; + LJ::delete_entry($lu, $row1->{"local_jitemid"}); + } + $sth1->finish; + + print "deleting ljr_remote_entries...\n"; + $sth1 = $dbh->prepare("delete from ljr_remote_entries where ru_id = $ru_id"); + $sth1->execute(); + $sth1->finish; + + print "deleting ljr_remote_userpics...\n"; + $sth1 = $dbh->prepare("delete from ljr_remote_userpics where ru_id = $ru_id"); + $sth1->execute(); + $sth1->finish; +} +$sth->finish; + +$sth = $dbh->prepare("delete from ljr_remote_users where ru_id = $ru_id"); +$sth->execute; +$sth->finish; + +$dbh->disconnect; diff --git a/local/bin/ljr-tools/import_pics_for_user.pl b/local/bin/ljr-tools/import_pics_for_user.pl new file mode 100755 index 0000000..afea9d0 --- /dev/null +++ b/local/bin/ljr-tools/import_pics_for_user.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl -w + +use strict; +use Simple; # corrected LJ::Simple +use XML::Parser; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl"; + +require "ljr-defaults.pl"; +require "ljr-links.pl"; +require LJR::Distributed; +require "ipics.pl"; + +#require "ijournal.pl"; +#require "icomments.pl"; + + +my $e = import_pics( + "http://www.livejournal.com", + "sharlei", + "", + "imp_5204", + "", 1); + +print $e->{errtext} ."\n" if $e->{err}; diff --git a/local/bin/ljr-tools/mass_update_journal.pl b/local/bin/ljr-tools/mass_update_journal.pl new file mode 100755 index 0000000..4190945 --- /dev/null +++ b/local/bin/ljr-tools/mass_update_journal.pl @@ -0,0 +1,50 @@ +#!/usr/bin/perl -w +# +# replaces text in all journal entries. use with caution. +# + +BEGIN { + $ENV{'LJHOME'} = "/home/lj-admin/lj"; +}; + +use strict; +use lib $ENV{'LJHOME'}."/cgi-bin"; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbh = LJ::get_dbh("master"); + +my ($journal, $from_text, $to_text, $do) = @ARGV; + +die("usage: $0 journal_name from_text to_text") + unless $journal && $from_text && $to_text; + +$do = 'no' unless $do; + +my $u = LJ::load_user($journal); + +die("Invalid journal [$journal]") unless $u; + +print "Loaded: $u->{'name'} [$u->{'userid'}] \n"; + +my $sth = $dbh->prepare("select * from logtext2 where journalid = ?"); +$sth->execute($u->{'userid'}); + +while (my $r = $sth->fetchrow_hashref()) { + if ($r->{'event'} =~ /$from_text/) { + print "journal entry [$r->{'jitemid'}] matches\n"; +# print "journal entry [$r->{'jitemid'}] matches:\n$r->{'event'}\n"; + $r->{'event'} =~ s/$from_text/$to_text/g; +# print "replaced:\n$r->{'event'}\n\n"; + + if ($do eq 'process') { + $dbh->do("UPDATE logtext2 set event = ? where journalid=? and jitemid=?", + undef, $r->{'event'}, $r->{'journalid'}, $r->{'jitemid'}); + if ($dbh->err) { + die("Error while updating entry [$r->{'jitemid'}]: " . $dbh->errstr); + } + } + } +} + +print "do not forget to restart memcache" if $do eq 'process'; +print "finished\n"; diff --git a/local/bin/ljr-tools/mysql-convert-storable.pl b/local/bin/ljr-tools/mysql-convert-storable.pl new file mode 100755 index 0000000..397e9ea --- /dev/null +++ b/local/bin/ljr-tools/mysql-convert-storable.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl -w +# +# converts s1usercache and s1stylecache blob fields +# which store Storable::freeze data from ::freeze to ::nfreeze +# +# 14oct07 petya@nigilist.ru +# initial revision +# + +sub convert { + my ($dbh, $table, $unique, $field) = @_; + + print "convert $table.$field ($unique)\n"; + + my $sql = "select * from $table;"; + + my $sth = $dbh->prepare($sql) or die "preparing: ", $dbh->errstr; + $sth->execute or die "executing: ", $dbh->errstr; + + while (my $row = $sth->fetchrow_hashref) { + if ($row->{"$field"}) { + my $obj = Storable::thaw($row->{"$field"}); + if ($obj) { + print $row->{"$unique"} . "\n"; + $dbh->do("UPDATE $table SET $field=? WHERE $unique=?", undef, + Storable::nfreeze($obj), $row->{"$unique"}) || + die "Error updating $table. Unique id: " . $row->{"$unique"} . "\n"; + } + } + } + print "\n"; +} + +use strict; +use DBI; +use Storable; + +$ENV{'LJHOME'} = "/home/lj-admin"; +do $ENV{'LJHOME'} . "/lj/cgi-bin/ljconfig.pl"; +my $host = $LJ::DBINFO{'master'}->{'host'}; +my $user = $LJ::DBINFO{'master'}->{'user'}; +my $pwd = $LJ::DBINFO{'master'}->{'pass'}; +my $db = "prod_livejournal"; + +$| = 1; # turn off buffered output + +# connect to the database. +my $dbh = DBI->connect( "DBI:mysql:mysql_socket=/tmp/mysql.sock;hostname=$host;port=3306;database=$db", $user, $pwd) + or die "Connecting : $DBI::errstr\n "; + +#convert ($dbh, "s1stylecache", "styleid", "vars_stor"); +#convert ($dbh, "s1usercache", "userid", "color_stor"); +#convert ($dbh, "s1usercache", "userid", "override_stor"); diff --git a/local/bin/ljr-tools/rlj2-ljrgate.pl b/local/bin/ljr-tools/rlj2-ljrgate.pl new file mode 100755 index 0000000..27a8a66 --- /dev/null +++ b/local/bin/ljr-tools/rlj2-ljrgate.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl + +use strict; +use XMLRPC::Lite; +use Digest::MD5 qw(md5_hex); +use DBI; +use Time::Local; +use lib "$ENV{'LJHOME'}/cgi-bin"; + +do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +use LJR::Viewuserstandalone; +use LJR::Gate; +use LJR::Distributed; + +# +#îÁÓÔÒÏÊËÉ +# + +#ó×ÏÊÓÔ×Á ÓÏÅÄÉÎÅÎÉÑ Ó ÂÁÚÏÊ +my $qhost = $LJ::DBINFO{'master'}->{'host'}; +my $quser = $LJ::DBINFO{'master'}->{'user'}; +my $qpass = $LJ::DBINFO{'master'}->{'pass'}; +my $qsock = $LJ::DBINFO{'master'}->{'sock'}; +my $qport = $LJ::DBINFO{'master'}->{'port'}; + +my $dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=prod_ljgate", + $quser, $qpass, ) || die localtime(time) . ": Can't connect to database\n"; + +my $dbhljr = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=prod_livejournal", + $quser, $qpass, ) || die localtime(time) . ": Can't connect to database\n"; + +my $get_our = sub { + my ($userid) = @_; + my $sqh = $dbh->prepare("SELECT * FROM our_user where userid=?"); + $sqh->execute($userid); + my $res = $sqh->fetchrow_hashref; + $sqh->finish; + return $res; +}; + +my $get_alien = sub { + my ($userid) = @_; + my $sqh = $dbh->prepare("SELECT * FROM alien where alienid=?"); + $sqh->execute($userid); + my $res = $sqh->fetchrow_hashref; + $sqh->finish; + return $res; +}; + +my $get_lj_user = sub { + my ($user) = @_; + $user =~ s/\-/\_/g; + my $sqh = $dbhljr->prepare("SELECT * FROM user where user=?"); + $sqh->execute($user); + my $res = $sqh->fetchrow_hashref; + $sqh->finish; + return $res; +}; + +my $count_gated_records = sub { + my ($userid) = @_; + my $sqh = $dbh->prepare("SELECT count(*) FROM rlj_lj_id where userid=?"); + $sqh->execute($userid); + my ($res) = $sqh->fetchrow_array; + $sqh->finish; + return $res; +}; + +my $sqh = $dbh->prepare("SELECT userid,alienid FROM rlj2lj"); +$sqh->execute; +my $result; +while ($result = $sqh->fetchrow_hashref) { + my $our = $get_our->($result->{'userid'}); + my $alien = $get_alien->($result->{'alienid'}); + + if ($our && $alien && $alien->{'alienpass'}) { + my $ljuser = $get_lj_user->($our->{'our_user'}); + + my $ru = LJR::Distributed::get_remote_server("www.livejournal.com"); + die $ru->{"errtext"} if $ru->{"err"}; + $ru->{'username'} = $alien->{'alien'}; + $ru = LJR::Distributed::get_cached_user($ru); + die $ru->{"errtext"} if $ru->{"err"}; + + print + $our->{'our_user'} . + " -> " . + $alien->{'alien'} . " ($ru->{'ru_id'}) " . "pass: " . $alien->{'alienpass'} . + "\n" + ; + + my $r = LJR::Distributed::update_export_settings($our->{'our_user'}, $ru->{'ru_id'}, $alien->{'alienpass'}); + die $r->{'errtext'} if $r->{'err'}; + + if ($ljuser) { + print "ljr id: " . $ljuser->{'userid'}; + } + else { + print "ljr id: error"; + } + print "; "; + + my $gated_records = $count_gated_records->($our->{'userid'}); + print $gated_records; + + print "\n"; +# my $xmlrpc = LJR::Gate::Authenticate ("www.livejournal.com", +# $alien->{'alien'}, $alien->{'alienpass'}); +# if ($xmlrpc->{'err_text'}) { +# print "err\n"; +# } +# else { +# print "ok\n"; +# } + } + else { + print + $result->{'userid'} . "($our->{'our_user'})" . " -> " . + $result->{'alienid'} . "($alien->{'alien'})" . "\n" + ; + } +} +$sqh->finish; +$dbh->disconnect; +$dbhljr->disconnect; diff --git a/local/bin/ljrimport/Simple.pm b/local/bin/ljrimport/Simple.pm new file mode 100755 index 0000000..4a5bbf8 --- /dev/null +++ b/local/bin/ljrimport/Simple.pm @@ -0,0 +1,4596 @@ +package LJ::Simple; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); + +require Exporter; +require AutoLoader; + +@ISA = qw(Exporter AutoLoader); +@EXPORT_OK = qw(); +@EXPORT = qw(); +$VERSION = '0.01'; + +## Bring in modules we use +use strict; # Silly not to be strict +use Socket; # Required for talking to the LJ server +use POSIX; # For errno values and other POSIX functions + +## Helper function prototypes +sub Debug(@); +sub EncVal($$); +sub DecVal($); +sub SendRequest($$$$); +sub dump_list($$); +sub dump_hash($$); + +=pod + +=head1 NAME + +LJ::Simple - A perl module to access LiveJournal via its flat protocol + +=head1 SYNOPSIS + +C is an object based C module which is used to access +LiveJournal-based web logs. This module implements most of the +flat protocol LiveJournal uses; for details of this protocol please +see: L + +=head1 REQUIREMENTS + +This module requires nothing other than the modules which come with the +standard perl 5.6.1 distribution. The only modules it B are +C and C. + +If you have the C module available then the code will make use of +encrypted passwords automatically. However C is not required for +this module to work. + +=head1 DESCRIPTION + +C is a trival API to access LiveJournal. Currently it +allows you to: + +=over 2 + +=item Login + +Log into the LiveJournal system + +=item Post + +Post a new journal entry in the LiveJournal system + +=item Synchronise + +Returns a list of journal entries created or modified from a given +date. + +=item Edit + +Edit the contents of an existing entry within the LiveJournal system + +=item Delete + +Delete an existing post from the LiveJournal system + +=back + +=head1 EXAMPLE + +The following simple examples shows you how to use the module to post a +simple LiveJournal entry. + +=head2 Using LJ::Simple::QuickPost() + +C is a routine which allows you to quickly post an entry into +LiveJournal; as such it lacks a lot of the abilities which using the object-based +interface provides. The C routine is explained in depth below, however +the following example shows how it can be used to easily post to LiveJournal: + + use LJ::Simple; + + LJ::Simple::QuickPost( + user => "test", + pass => "test", + entry => "Just a simple entry", + ) || die "$0: Failed to post entry: $LJ::Simple::error\n"; + +=head2 Using the standard calls + + use LJ::Simple; + + # Log into the server + my $lj = new LJ::Simple ({ + user => "test", + pass => "test", + site => undef, + }); + (defined $lj) + || die "$0: Failed to log into LiveJournal: $LJ::Simple::error\n"; + + # Prepare the event + my %Event=(); + $lj->NewEntry(\%Event) || + die "$0: Failed to create new entry: $LJ::Simple::error\n"; + + # Put in the entry + my $entry=<LJ::Simple version $LJ::Simple::VERSION + EOF + $lj->SetEntry(\%Event,$entry) + || die "$0: Failed to set entry: $LJ::Simple::error\n"; + + # Say we are happy + $lj->SetMood(\%Event,"happy") + || die "$0: Failed to set mood: $LJ::Simple::error\n"; + + # Post the event + my ($item_id,$anum,$html_id)=$lj->PostEntry(\%Event); + (defined $item_id) + || die "$0: Failed to post journal entry: $LJ::Simple::error\n"; + +=head1 VARIABLES + +There are various variables which can be used to control certain +aspects of the module. It is generally recommended that if you +wish to change these variables that you do so B you +create the initial object. + +The variable you are most likely to use is C<$LJ::Simple::error> +which holds error messages if any of the C calls +fail. + +=over 4 + +=item $LJ::Simple::error + +Holds error messages, is set with a blank string at the +start of each method. Whilst the messages are relatively free-form, +there are some prefixes which are sometimes used: + + CODE: An error in the code calling the API + INTERNAL: An internal error in this module + +=item $LJ::Simple::debug + +If set to C<1>, debugging messages are sent to stderr. + +=item $LJ::Simple::protocol + +If set to C<1> the protocol used to talk to the remote server is sent to stderr. + +=item $LJ::Simple::raw_protocol + +If set to C<1> the raw protocol used to talk to the remote server is sent to stderr; +this is only useful if you are doing debugging on C itself as the protocol +is shown as the module gets it from the server; non-printable characters are converted +to their octal presentation form, I a newline becomes C<\012>. + +It should be noted that if C<$LJ::Simple::raw_protocol> is set along with +C<$LJ::Simple::protocol> then the raw protocol display takes precedence for data +returning from the LJ server. + +=item $LJ::Simple::UTF + +If set to C<1> the LiveJournal server is told to expect UTF-8 encoded characters. +If you enable this the module will attempt to use the utf8 perl module. + +The default is see if we have a version of Perl with UTF-8 support and use +it if its available. + +=item $LJ::Simple::challenge + +If set to C<1> we make use of the challenge-response system instead of using +plain or hashed passwords. This does add some overhead into processing requests +since every action has to be preceeded by a request for a challenge value from +the server. + +The default is to see if we have the C module available and if +so we make use of the challenge-response system. This can be disabled by +setting the variable to C<0>. + +=item $LJ::Simple::timeout + +The time - specified in seconds - to wait for data from the server. If +given a value of C the API will block until data is avaiable. + +=item $LJ::Simple::NonBlock + +By default this is set to C. When given a reference to a sub-routine this +module will call the given sub-routine at various stages of processing the responses +to the LiveJournal server. This is intended for GUI applications which need to process +event queues, update progress bars, I. When called the sub-routine is passed a +number of variables which maybe useful; the calling method is: + + &{sub}($mode,$status,$action,$bytes_in,$bytes_out,$time,$waiting) + + $mode - The mode sent to the LJ server + $status - The status of the request; ranges from 0 to 1 + $action - The action performed + $bytes_in - The number of bytes read from the remote server + $bytes_out - The number of bytes written to the remote server + $time - The time taken so far in seconds + $waiting - Are we waiting for a response from the server ? + +It should be noted that if C<$waiting> is set to C<1> then it is B recommended +that the sub-routine calls C itself to provide at least some time delay. If +this is not done it is likely that this module will consume far more CPU than necessary. + +An example sub-routine follows: + + sub LJStatus { + my ($mode,$status,$action,$bytes_in,$bytes_out,$time,$waiting) = @_; + print "\$mode = $mode\n"; + print "\$status = $status\n"; + print "\$action = $action\n"; + print "\$bytes_in = $bytes_in\n"; + print "\$bytes_out = $bytes_out\n"; + print "\$time = $time\n"; + print "\$waiting = $waiting\n"; + print "\n"; + ($waiting) && select(undef,undef,undef,0.5); + } + + $LJ::Simple::NonBlock=\&LJStatus; + +=item $LJ::Simple::ProtoSub + +By default this points to a sub-routine within the module; this is called when +the protocol between the module and LiveJournal server is to be shown, in other +words when C<$LJ::Simple::protocol> is set to C<1>. The sub-routine called must +take two variables; it is called in the following way: + + &{sub}($direction,$data,$server,$ip_addr) + + $direction - The direction of the flow; 0 means from client to server + and 1 means from server to client + $data - The data which has flowed; there should not be any newlines + with the data, but do not rely on this. + $server - The name of the LJ server we are talking to + $ip_addr - The IP address of the LJ server we are talking to + +If both variables are C then data is about to flow. If just C<$direction> is +C then C<$data> holds an informational message. + +The standard sub-routine which is called is: + + sub DefaultProtoSub { + my ($direct,$data,$server,$ip_addr)=@_; + my $arrow="--> "; + if (!defined $direct) { + if (!defined $data) { + print STDERR "Connecting to $server [$ip_addr]\n"; + print STDERR "Lines starting with \"-->\" is data SENT to the server\n"; + print STDERR "Lines starting with \"<--\" is data RECEIVED from the server\n"; + return; + } + $arrow=""; + } else { + ($direct) && ($arrow="<-- "); + } + print STDERR "$arrow$data\n"; + } + + $LJ::Simple::ProtoSub=\&DefaultProtoSub; + +=item $LJ::Simple::buffer + +The number of bytes to try and read in on each C call. + +=back + +=cut + +sub DefaultProtoSub { + my ($direct,$data,$server,$ip_addr)=@_; + my $arrow="--> "; + if (!defined $direct) { + if (!defined $data) { + print STDERR "Connecting to $server [$ip_addr]\n"; + print STDERR "Lines starting with \"-->\" is data SENT to the server\n"; + print STDERR "Lines starting with \"<--\" is data RECEIVED from the server\n"; + return; + } + $arrow=""; + } else { + ($direct) && ($arrow="<-- "); + } + print STDERR "$arrow$data\n"; +} + + +## Global variables - documented +# Debug ? +$LJ::Simple::debug=0; +# Show protocol ? +$LJ::Simple::protocol=0; +# Protocol handling code +$LJ::Simple::ProtoSub=\&DefaultProtoSub; +# Show raw protocol ? +$LJ::Simple::raw_protocol=0; +# Use UTF-8 ? +$LJ::Simple::UTF = undef; +# Use challenge-response ? +$LJ::Simple::challenge = undef; +# Use non-block sub-routine +$LJ::Simple::NonBlock = undef; +# Errors +$LJ::Simple::error=""; +# Timeout for reading from sockets - default is 5 minutes +$LJ::Simple::timeout = 300; +# How much data to read from the socket in one read() +$LJ::Simple::buffer = 8192; + +# How much times to retry if some network error occurs +$LJ::Simple::network_retries = 10; +# How much seconds to wait before each retry +$LJ::Simple::network_sleep = 2; +# LJ Client string +$LJ::Simple::LJ_Client = "LJ::Simple/$VERSION"; +# UserAgent string +$LJ::Simple::UserAgent = "LJ::Simple/$VERSION; http://www.bpfh.net/computing/software/LJ::Simple/; lj-simple\@bpfh.net"; + +## Global variables - internal and undocumented +# Should we not fully run the QuickPost routine ? +$LJ::Simple::TestStopQuickPost = 0; + +## Internal variables - private to this module +# Standard ports +my %StdPort = ( + http => 80, + http_proxy => 3128, +); + +=pod + +=head1 AVAILABLE METHODS + +=head2 LJ::Simple::QuickPost() + +C is a routine which allows you to quick post to LiveJournal. +However it does this by hiding a lot of the details involved in using +C to do this. This routine will do all of the work involved in +logging into the LiveJournal server, preparing the entry and then posting it. +If at any stage there is a failure then C<0> is returned and C<$LJ::Simple::error> +will contain the reason why. If the entry was successfully posted to the LiveJournal +server then the routine will return C<1>. + +There are a number of options to the C routine: + + LJ::Simple::QuickPost( + user => Username + pass => Password + entry => Contents of the entry + subject => Subject line of the entry + mood => Current mood + music => Current music + html => HTML content ? + protect => Security settings of the entry + groups => Friends groups list + ); + +Of these, only the C, C and C options are required; all of the other +options are optional. The option names are all case insensitive. + +=over 4 + +=item user + +The username who owns the journal the entry should be posted to; +this option is B. + +=item pass + +The password of the C; +this option is B. + +=item entry + +The actual entry itself; +this option is B. + +=item subject + +The subject line of the post. + +=item mood + +The mood to associate with the post; the value is given to the C method +for processing. + +=item music + +The music to associate with the post. + +=item html + +This is a boolean value of either C<1> or C<0>. If you want to say that the entry +contains HTML and thus should be considered to be preformatted then set C to +C<1>. Otherwise you can either set it to C<0> or not give the option. + +=item protect + +By default the new entry will be public unless you give the C option. This +option should be given the protection level required for the post and can be one of +the following: + + public - The entry is public + friends - Entry is friends-only + groups - Entry is restricted to friends groups + private - Entry is restricted to the journal's owner + +If you set the C option to C you must also include the C +option - see below for details. + +=item groups + +If the C option is set to C then this option should contain a +list reference which contains the list of groups the entry should be restricted to. +This option is B if the C option is set to C. + +=back + +Example code: + + # Simple test post + LJ::Simple::QuickPost( + user => "test", + pass => "test", + entry => "Just a simple entry", + ) || die "$0: Failed to post entry: $LJ::Simple::error\n"; + + # A friends-only preformatted entry + LJ::Simple::QuickPost( + user => "test", + pass => "test", + entry => "

    Friends-only, preformatted, entry

    ", + html => 1, + protect => "friends", + ) || die "$0: Failed to post entry: $LJ::Simple::error\n"; + + # A entry restricted to several friends groups + LJ::Simple::QuickPost( + user => "test", + pass => "test", + entry => "Entry limited to friends groups", + protect => "groups", + groups => [qw( one_group another_group )], + ) || die "$0: Failed to post entry: $LJ::Simple::error\n"; + +=cut +sub QuickPost(@) { + my %opts=(); + my @prot_opts=(); + while($#_>-1) { + my $k=lc(shift(@_)); + my $v=shift(@_); + (defined $v) || next; + $opts{$k}=$v; + } + foreach (qw( user pass entry )) { + (exists $opts{$_}) && next; + $LJ::Simple::error="CODE: QuickPost() called without the required $_ option"; + return 0; + } + if ((exists $opts{html}) && ($opts{html}!~/^[01]$/)) { + $LJ::Simple::error="CODE: QuickPost() not given either 0 or 1 for html option"; + return 0; + } + if ((exists $opts{protect}) && ($opts{protect} eq "groups")) { + if (!exists $opts{groups}) { + $LJ::Simple::error="CODE: QuickPost() given protect=groups, but no groups option"; + return 0; + } + if (ref($opts{groups}) ne "ARRAY") { + $LJ::Simple::error="CODE: QuickPost() not given a list reference for the groups option"; + return 0; + } + @prot_opts=@{$opts{groups}}; + } + + # Kludge so we can test the input validation + ($LJ::Simple::TestStopQuickPost) && return 1; + + my $lj = new LJ::Simple({ + user => $opts{user}, + pass => $opts{pass}, + }); + (defined $lj) || return 0; + + my %Event=(); + $lj->NewEntry(\%Event) || return 0; + $lj->SetEntry(\%Event,$opts{entry}) || return 0; + (exists $opts{subject}) && + ($lj->SetSubject(\%Event,$opts{subject}) || return 0); + (exists $opts{mood}) && + ($lj->SetMood(\%Event,$opts{mood}) || return 0); + (exists $opts{music}) && + ($lj->Setprop_current_music(\%Event,$opts{music}) || return 0); + (exists $opts{html}) && + ($lj->Setprop_preformatted(\%Event,$opts{html}) || return 0); + (exists $opts{protect}) && + ($lj->SetProtect(\%Event,$opts{protect},@prot_opts) || return 0); + + my ($item_id,$anum,$html_id)=$lj->PostEntry(\%Event); + (defined $item_id) || return 0; + + return 1; +} + +=pod + +=head2 Object creation + +=over 4 + +=item login + +Logs into the LiveJournal system. + + ## Simplest logon method + my $lj = new LJ::Simple ( { + user => "username", + pass => "password", + } ); + + ## Login with options + my $lj = new LJ::Simple ( { + user => "username", + pass => "password", + site => "hostname[:port]", + proxy => "hostname[:port]", + moods => 0 | 1, + pics => 0 | 1, + fast => 0 | 1, + } ); + + ## Login by using login() + my $lj = LJ::Simple->login ( { + user => "username", + pass => "password", + site => "hostname[:port]", + proxy => "hostname[:port]", + moods => 0 | 1, + pics => 0 | 1, + fast => 0 | 1, + } ); + +Where: + + user is the username to use + pass is the password associated with the username + site is the remote site to use + proxy is the HTTP proxy site to use; see below. + moods is set to 0 if we do not want to download the mood + list. Defaults to 1 + pics is set to 0 if we do not want to download the user + picture information. Defaults to 1 + fast is set to 1 if we want to perform a fast login. + Default is 0. See below for details of this. + +Sites defined in C or C are a hostname with an +optional port number, separated by a C<:>, i.e.: + + www.livejournal.com + www.livejournal.com:80 + +If C is given C then the code assumes that you wish to +connect to C. If no port is given then port +C<80> is the default. + +If C is given C then the code will go directly to the +C<$site> unless a suitable environment variable is set. +If no port is given then port C<3128> is the default. + +C also supports the use the environment variables C +and C to store the HTTP proxy server details. The format of these +environment variables is assumed to be: + + http://server[:port]/ + +Where C is the name of the proxy server and the optional C the +proxy server is on - port C<3128> is used if no port is explicitly given. + +It should be noted that the proxy environment variables are B checked +if the C value is B given to the C object creation. +Thus to disable looking at the proxy environment variables use +Cundef> in C or C. + +If C is set to C<0> then the mood list will not be pulled from +the LiveJournal server and the following functions will be affected: + + o moods() will always return undef (error) + o Setprop_current_mood_id() will not validate the mood_id + given to it. + o SetMood() will not attempt to convert the string it is + given into a given mood_id + +If C is set to C<0> then the data on the user pictures will +not be pulled from the LiveJournal server and the following +functions will be affected: + + o pictures() will always return undef (error) + o Setprop_picture_keyword() will blindly set the picture keyword + you give it - no validation will be performed. + o DefaultPicURL() will always return undef (error) + +If C is set to C<1> then we will perform a I. Essentially +all this does is to set up the various entries in the object hash which +the routines called after C expect to see; at no time does it talk to +the LiveJournal servers. What this means is that it is very fast. However it +also means that when you use parts of the API which B talk to the LiveJournal +servers its quite possible that you will get back errors associated with +authentication errors, network outages, I. In other words, in C mode +the login will always succeed, no matter what the state the LiveJournal +server we're talking is in. It should be noted that the following functions +will be affected if you enable the I: + + o moods() will always return undef (error) + o Setprop_current_mood_id() will not validate the mood_id + given to it + o SetMood() will not attempt to convert the string it is + given into a given mood_id + o pictures() will always return undef (error) + o Setprop_picture_keyword() will blindly set the picture keyword + you give it - no validation will be performed + o communities() will always return an empty list + o MemberOf() will always return 0 (error) + o UseJournal() will not validate the shared journal name you + give it + o groups() will always return undef (error) + o MapGroupToId() will always undef (error) + o MapIdToGroup() will always undef (error) + o SetProtectGroups() will always 0 (error) + o message() will always return undef (error) + o The key of "groups" in the list of hashes returned by + GetFriends() will always point to an empty list + o CheckFriends() will return undef (error) if you give it a + list of groups + +On success this sub-routine returns an C object. On +failure it returns C with the reason for the failure being +placed in C<$LJ::Simple::error>. + +Example code: + + ## Simple example, going direct to www.livejournal.com:80 + my $lj = new LJ::Simple ({ user => "someuser", pass => "somepass" }); + (defined $lj) || + die "$0: Failed to access LiveJournal - $LJ::Simple::error\n"; + + ## More complex example, going via a proxy server on port 3000 to a + ## a LiveJournal system available on port 8080 on the machine + ## www.somesite.com. + my $lj = new LJ::Simple ({ + user => "someuser", + pass => "somepass", + site => "www.somesite.com:8080", + proxy => "proxy.internal:3000", + }); + (defined $lj) || + die "$0: Failed to access LiveJournal - $LJ::Simple::error\n"; + + ## Another complex example, this time saying that we do not want + ## the mood list or user pictures downloaded + my $lj = new LJ::Simple ({ + user => "someuser", + pass => "somepass", + pics => 0, + moods => 0, + }); + (defined $lj) || + die "$0: Failed to access LiveJournal - $LJ::Simple::error\n"; + + ## Final example - this one shows the use of the fast logon + my $lj = new LJ::Simple ({ + user => "someuser", + pass => "somepass", + fast => 1, + }); + (defined $lj) || + die "$0: Failed to access LiveJournal - $LJ::Simple::error\n"; + +=cut +## +## Log into the LiveJournal system. Given that the LJ stuff is just +## layered over HTTP, its not essential to do this. However it does +## mean that we can check the auth details, get some useful info for +## later, etc. +## +sub login($$) { + # Handle the OOP stuff + my $this=shift; + $LJ::Simple::error=""; + if ($#_ != 0) { + $LJ::Simple::error="CODE: Incorrect usage of login() for argv - see docs"; + return undef; + } + # Get the hash + my $hr = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self,$class; + if ((!exists $hr->{user})||($hr->{user} eq "") || + (!exists $hr->{pass})||($hr->{pass} eq "")) { + $LJ::Simple::error="CODE: Incorrect usage of login() - see docs"; + return undef; + } + $self->{auth}={ + user => $hr->{user}, + pass => $hr->{pass}, + challenge => {}, + }; + if (! defined $LJ::Simple::UTF) { + eval { require utf8 }; + if (!$@) { + $LJ::Simple::UTF=1; + Debug("UTF-8 support found"); + } else { + $LJ::Simple::UTF=0; + Debug("No UTF-8 support found"); + } + } elsif ($LJ::Simple::UTF) { + eval { require utf8 }; + if (!$@) { + Debug("Using UTF-8 as requested"); + } else { + $LJ::Simple::error="CODE: no UTF-8 support in your version of perl"; + return undef; + } + } + eval { require Digest::MD5 }; + if (!$@) { + Debug("Using Digest::MD5"); + my $md5=Digest::MD5->new; + $md5->add($hr->{pass}); + $self->{auth}->{hash}=$md5->hexdigest; + delete $self->{auth}->{pass}; + (!defined $LJ::Simple::challenge) && ($LJ::Simple::challenge=1); + } else { + if ((defined $LJ::Simple::challenge)&&($LJ::Simple::challenge)) { + $LJ::Simple::error="Challenge-response auth requested, no Digest::MD5 found"; + return undef; + } + $LJ::Simple::challenge=0; + } + if ((exists $hr->{site})&&(defined $hr->{site})&&($hr->{site} ne "")) { + my $site_port=$StdPort{http}; + if ($hr->{site}=~/\s*(.*?):([0-9]+)\s*$/) { + $hr->{site} = $1; + $site_port = $2; + } + $self->{lj}={ + host => $hr->{site}, + port => $site_port, + } + } else { + $self->{lj}={ + host => "www.livejournal.com", + port => $StdPort{http}, + } + } + if ((exists $hr->{proxy})&&(defined $hr->{proxy})&&($hr->{proxy} ne "")) { + my $proxy_port=$StdPort{http_proxy}; + if ($hr->{proxy}=~/\s*(.*?):([0-9]+)\s*$/) { + $hr->{proxy} = $1; + $proxy_port = $2; + } + $self->{proxy}={ + host => $hr->{proxy}, + port => $proxy_port, + }; + } elsif (!exists $hr->{proxy}) { + # Getting proxy details from the environment; assumes that the proxy is + # given as http://site[:port]/ + # The first matching env is used. + foreach my $env (qw( http_proxy HTTP_PROXY )) { + (exists $ENV{$env}) || next; + ($ENV{$env}=~/^(?:http:\/\/)([^:\/]+)(?::([0-9]+)){0,1}/o) || next; + $self->{proxy}={ + host => $1, + port => $2, + }; + (defined $self->{proxy}->{port}) || ($self->{proxy}->{port}=$StdPort{http_proxy}); + } + } else { + $self->{proxy}=undef; + } + + # Set fastserver to 0 until we know better + $self->{fastserver}=0; + + if ((exists $hr->{fast}) && ($hr->{fast}==1)) { + ## Doing fast login, so return object + Debug(dump_hash($self,"")); + return $self; + } + + my $GetMoods=1; + if ((exists $hr->{moods}) && ($hr->{moods}==0)) { + $GetMoods=0; + } + my $GetPics=1; + if ((exists $hr->{pics}) && ($hr->{pics}==0)) { + $GetPics=0; + } + + # Perform the actual login + $self->SendRequest("login", { + "moods" => $GetMoods, + "getpickws" => $GetPics, + "getpickurls" => $GetPics, + },undef) || return undef; + + # Now see if we can set fastserver + if ( (exists $self->{request}->{lj}->{fastserver}) && + ($self->{request}->{lj}->{fastserver} == 1) ) { + $self->{fastserver}=1; + } + + # Moods + $self->{moods}=undef; + $self->{mood_map}=undef; + # Shared access journals + $self->{access}=undef; + # User groups + $self->{groups}=undef; + # Images defined + $self->{pictures}=undef; + # Default URL + $self->{defaultpicurl}=undef; + # Message from LJ + $self->{message}=undef; + + # Handle moods, etc. + my ($k,$v)=(undef,undef); + while(($k,$v) = each %{$self->{request}->{lj}}) { + + # Message from LJ + if ($k eq "message") { + $self->{message}=$v; + + # Moods + } elsif ($k=~/^mood_([0-9]+)_([a-z]+)/o) { + my ($id,$type)=($1,$2); + if (!defined $self->{moods}) { + $self->{moods}={}; + } + if (!exists $self->{moods}->{$id}) { + $self->{moods}->{$id}={}; + } + if ($type eq "id") { + $self->{moods}->{$id}->{id}=$v; + } elsif ($type eq "name") { + $self->{moods}->{$id}->{name}=$v + } + + # Picture key words + } elsif ($k=~/^(pickw_count)/o) { + if (!defined $self->{pictures}) { + $self->{pictures}={}; + } + } elsif ($k eq "defaultpicurl") { + $self->{defaultpicurl}=$v; + } elsif ($k=~/^(pickw[^_]*)_([0-9]+)/o) { + my ($type,$id)=($1,$2); + if (!defined $self->{pictures}) { + $self->{pictures}={}; + } + if (!exists $self->{pictures}->{$id}) { + $self->{pictures}->{$id}={}; + } + if ($type eq "pickwurl") { + $self->{pictures}->{$id}->{url}=$v; + } elsif ($type eq "pickw") { + $self->{pictures}->{$id}->{name}=$v + } + + # Shared access journals + } elsif ($k=~/^access_([0-9]+)/) { + if (!defined $self->{access}) { + $self->{access}={}; + } + $self->{access}->{$v}=1; + + # Groups + } elsif ($k=~/^frgrp_([0-9]+)_(.*)/) { + my ($id,$type)=($1,$2); + if (!defined $self->{groups}) { + $self->{groups}={ + src => {}, # Source data + id => {}, # Id -> name mapping + name => {}, # Real data, name keyed + }; + } + if (!exists $self->{groups}->{src}->{$id}) { + $self->{groups}->{src}->{$id}={}; + } + if ($type eq "sortorder") { + $self->{groups}->{src}->{$id}->{sort}=$v; + } elsif ($type eq "name") { + $self->{groups}->{src}->{$id}->{name}=$v + } + } + } + + ## We now handle the group hash fully. Note in the case + ## of groups having the same name, only the first will + ## go into the name hash. + ($k,$v)=(undef,undef); + while(($k,$v)=each %{$self->{groups}->{src}}) { + $self->{groups}->{id}->{$k}=$v->{name}; + if (!exists $self->{groups}->{name}->{$v->{name}}) { + $self->{groups}->{name}->{$v->{name}} = { + id => $k, + name => $v->{name}, + sort => $v->{sort}, + }; + } + } + + ## + ## And now we handle the mood map fully + ## + if ($GetMoods) { + $self->{mood_map}={}; + foreach (values %{$self->{moods}}) { + $self->{mood_map}->{lc($_->{name})}=$_->{id}; + } + } + + Debug(dump_hash($self,"")); + + ## Logged in, so return self. + return $self; +} + +## Define reference from new to login +*new=""; +*new=\&login; + + +=pod + +=back + +=head2 Getting data from the LiveJournal login + +=over 4 + +=item $lj->message() + +Returns back a message set in the LiveJournal system. Either +returns back the message or C if no message is set. + +Example code: + + my $msg = $lj->message(); + (defined $msg) && + print "LJ Message: $msg\n"; + +=cut +sub message($) { + my $self=shift; + return $self->{message}; +} + +=pod + +=item $lj->moods($hash_ref) + +Takes a reference to a hash and fills it with information about +the moods returned back by the server. Either returns back the +same hash reference or C on error. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will always return +an error. + +The hash the given reference is pointed to is emptied before +it is used and after a successful call the hash given will +contain: + + %hash = ( + list => [ list of mood names, alphabetical ] + moods => { + mood_name => mood_id + } + idents => { + mood_id => mood_name + } + ) + + +Example code: + + my %Moods=(); + if (!defined $lj->moods(\%Moods)) { + die "$0: LJ error - $LJ::Simple::error"; + } + foreach (@{$Moods{list}}) { + print "$_ -> $Moods{moods}->{$_}\n"; + } + + +=cut +sub moods($$) { + my $self=shift; + my ($hr) = @_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + $LJ::Simple::error="CODE: moods() not given a hash reference"; + return undef; + } + if (!defined $self->{moods}) { + $LJ::Simple::error="Unable to return moods - not requested at login"; + return undef; + } + %{$hr}=( + list => [], + moods => {}, + idents => {}, + ); + my ($k,$v); + while(($k,$v)=each %{$self->{moods}}) { + push(@{$hr->{list}},$v->{name}); + $hr->{moods}->{$v->{name}}=$v->{id}; + $hr->{idents}->{$v->{id}}=$v->{name}; + } + $hr->{list} = [ (sort { $a cmp $b } @{$hr->{list}}) ]; + return $hr; +} + +=pod + +=item $lj->communities() + +Returns a list of shared access communities the user logged in can +post to. Returns an empty list if no communities are available + +Example code: + + my @communities = $lj->communities(); + print join("\n",@communities),"\n"; + +=cut +sub communities($) { + my $self=shift; + $LJ::Simple::error=""; + (defined $self->{access}) || return (); + return sort {$a cmp $b} (keys %{$self->{access}}); +} + + +=pod + +=item $lj->MemberOf($community) + +Returns C<1> if the user is a member of the named community. Returns +C<0> otherwise. + +Example code: + + if ($lj->MemberOf("some_community")) { + : + : + : + } + +=cut +sub MemberOf($$) { + my $self=shift; + my ($community)=@_; + $LJ::Simple::error=""; + (defined $self->{access}) || return 0; + return (exists $self->{access}->{$community}); +} + +=pod + +=item $lj->groups($hash_ref) + +Takes a reference to a hash and fills it with information about +the friends groups the user has configured for themselves. Either +returns back the hash reference or C on error. + +The hash the given reference points to is emptied before it is +used and after a successful call the hash given will contain +the following: + + %hash = ( + "name" => { + "Group name" => { + id => "Number of the group", + sort => "Sort order", + name => "Group name (copy of key)", + }, + }, + "id" => { + "Id" => "Group name", + }, + ); + +Example code: + + my %Groups=(); + if (!defined $lj->groups(\%Groups)) { + die "$0: LJ error - $LJ::Simple::error"; + } + my ($id,$name)=(undef,undef); + while(($id,$name)=each %{$Groups{id}}) { + my $srt=$Groups{name}->{$name}->{sort}; + print "$id\t=> $name [$srt]\n"; + } + +=cut +sub groups($$) { + my $self=shift; + my ($hr) = @_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + $LJ::Simple::error="CODE: groups() not given a hash reference"; + return undef; + } + if (!defined $self->{groups}) { + $LJ::Simple::error="Unable to return groups - none defined"; + return undef; + } + %{$hr}=( + name => {}, + id => {}, + ); + my ($k,$v); + while(($k,$v)=each %{$self->{groups}->{id}}) { + $hr->{id}->{$k}=$v; + } + while(($k,$v)=each %{$self->{groups}->{name}}) { + $hr->{name}->{$k}={}; + my ($lk,$lv); + while(($lk,$lv)=each %{$self->{groups}->{name}->{$k}}) { + $hr->{name}->{$k}->{$lk}=$lv; + } + } + return $hr; +} + + +=pod + +=item $lj->MapGroupToId($group_name) + +Used to map a given group name to its identity. On +success returns the identity for the group name. On +failure it returns C and sets +C<$LJ::Simple::error>. + +=cut +sub MapGroupToId($$) { + my $self=shift; + my ($grp)=@_; + $LJ::Simple::error=""; + if (!defined $self->{groups}) { + $LJ::Simple::error="Unable to map group to id - none defined"; + return undef; + } + if (!exists $self->{groups}->{name}->{$grp}) { + $LJ::Simple::error="No such group"; + return undef; + } + return $self->{groups}->{name}->{$grp}->{id}; +} + + +=pod + +=item $lj->MapIdToGroup($id) + +Used to map a given identity to its group name. On +success returns the group name for the identity. On +failure it returns C and sets +C<$LJ::Simple::error>. + +=cut +sub MapIdToGroup($$) { + my $self=shift; + my ($id)=@_; + $LJ::Simple::error=""; + if (!defined $self->{groups}) { + $LJ::Simple::error="Unable to map group to id - none defined"; + return undef; + } + if (!exists $self->{groups}->{id}->{$id}) { + $LJ::Simple::error="No such group ident"; + return undef; + } + return $self->{groups}->{id}->{$id}; +} + +=pod + + +=item $lj->pictures($hash_ref) + +Takes a reference to a hash and fills it with information about +the pictures the user has configured for themselves. Either +returns back the hash reference or C on error. Note that +the user has to have defined picture keywords for this to work. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will always return +an error. + +The hash the given reference points to is emptied before it is +used and after a successful call the hash given will contain +the following: + + %hash = ( + "keywords" => "URL of picture", + ); + +Example code: + + my %pictures=(); + if (!defined $lj->pictures(\%pictures)) { + die "$0: LJ error - $LJ::Simple::error"; + } + my ($keywords,$url)=(undef,undef); + while(($keywords,$url)=each %pictures) { + print "\"$keywords\"\t=> $url\n"; + } + + +=cut +sub pictures($$) { + my $self=shift; + my ($hr)=@_; + $LJ::Simple::error=""; + if (!defined $self->{pictures}) { + $LJ::Simple::error="Unable to return pictures - none defined"; + return undef; + } + if (ref($hr) ne "HASH") { + $LJ::Simple::error="CODE: pictures() not given a hash reference"; + return undef; + } + %{$hr}=(); + foreach (values %{$self->{pictures}}) { + $hr->{$_->{name}}=$_->{url}; + } + return $hr; +} + +=pod + +=item $lj->DefaultPicURL() + +Returns the URL of the default picture used by the user. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will always return +an error. + +Example code: + + print $lj->DefaultPicURL(),"\n"; + +=cut +sub DefaultPicURL($) { + my $self=shift; + $LJ::Simple::error=""; + if (!defined $self->{defaultpicurl}) { + $LJ::Simple::error="Unable to return default picture URL - none defined"; + return undef; + } + return $self->{defaultpicurl}; +} + +=pod + +=item $lj->user() + +Returns the username used to log into LiveJournal + +Example code: + + my $user = $lj->user(); + +=cut +sub user($) { + my $self=shift; + $LJ::Simple::error=""; + return $self->{auth}->{user}; +} + + +=pod + +=item $lj->fastserver() + +Used to tell if the user which was logged into the LiveJournal system can use the +fast servers or not. Returns C<1> if the user can use the fast servers, C<0> +otherwise. + +Example code: + + if ($lj->fastserver()) { + print STDERR "Using fast server for ",$lj->user(),"\n"; + } + +=cut +sub fastserver($) { + my $self=shift; + $LJ::Simple::error=""; + return $self->{fastserver}; +} + +=pod + +=back + +=head2 Dealing with friends + +=over 4 + +=item $lj->GetFriendOf() + +Returns a list of the other LiveJournal users who list the current +user as a friend. The list returned contains a least one entry, the +number of entries in the list. This value can range from 0 to however +many users are in the list. In the event of a failure this value is +undefined. + +The list of friends is a list of hash references which contain data +about the users who list the current user as a friend. Each hash +referenced will contain the following: + + { + user => The LiveJournal username + name => The full name of the user + fg => The foreground colour which represents the user + bg => The background colour which represents the user + status => The status of the user + type => The type of the user + } + +Both the C and C values are stored in the format of "C<#>III" +where the I, I, I values are given as two digit hexadecimal numbers which +range from C<00> to C. + +The C of a user can be one of C, C, C or C. + +The C of a user can either be C which means that the user is a normal +LiveJournal user or it can be C which means that the user is actually a +community which the current LJ user is a member of. + +It should be noted that any of the values in the hash above can be undefined if +that value was not returned from the LiveJournal server. + +The returned list is ordered by the LiveJournal login names of the users. + +Example code: + + my ($num_friends_of,@FriendOf)=$lj->GetFriendOf(); + (defined $num_friends_of) || + die "$0: Failed to get friends of user - $LJ::Simple::error\n"; + print "LJ login\tReal name\tfg\tbg\tStatus\tType\n"; + foreach (@FriendOf) { + print "$_->{user}\t", + "$_->{name}\t", + "$_->{fg}\t", + "$_->{bg}\t", + "$_->{status}\t", + "$_->{type}\n"; + } + +=cut +sub GetFriendOf($) { + my $self=shift; + $LJ::Simple::error=""; + my %Event=(); + my %Resp=(); + $self->SendRequest("friendof",\%Event,\%Resp) || return undef; + my %Friends=(); + my ($k,$v); + while(($k,$v)=each %Resp) { + ($k=~/^friendof_([0-9]+)_(.*)/) || next; + my ($id,$type)=($1,$2); + if (!exists $Friends{$id}) { + $Friends{$id}={ + user => undef, + name => undef, + bg => undef, + fg => undef, + status => "active", + type => "user", + }; + } + $Friends{$id}->{$type}=$v; + } + my @lst=sort {$a->{user} cmp $b->{user}} (values %Friends); + return ($#lst+1,@lst); +} + + +=pod + +=item $lj->GetFriends() + +Returns a list of the other LiveJournal user who are listed as friends of +the current user. The list returned contains a least one entry, the +number of entries in the list. This value can range from 0 to however +many users are in the list. In the event of a failure this value is +undefined. + +The list of friends is a list of hash references which contain data +about the users who list the current user as a friend. Each hash +referenced will contain the following: + + { + user => The LiveJournal username + name => The full name of the user + fg => The foreground colour which represents the user + bg => The background colour which represents the user + dob => The date of birth for the user + birthday => The birthday of the user + groups => The list of friends groups this user is in + groupmask => The actual group mask for this user + status => The status of the user + type => The type of the user + } + +Both the C and C values are stored in the format of "C<#>III" +where the I, I, I values are given as two digit hexadecimal numbers which +range from C<00> to C. + +The C value is stored as a Unix timestamp; that is seconds since epoch. If the +user has no date of birth defined B they have only given their birthday then this +value will be C. + +The C value is the date of the user's next birthday given as a Unix timestamp. + +The C value is a reference to a list of the friends group this user is a member +of. It should be noted that to have any items in the list the user must be a +member of a friends group and the C method must B have been called +with the fast login option. + +The C value is the actual group mask for the user. This is used to build +the C list. It is a 32-bit number where each bit represents membership of a +given friends group. Bits 0 and 31 are reserved; all other bits can be used. The bit +a group corresponds to is taken by bit-shifting 1 by the group id number. + +The C of a user can be one of C, C, C or C. + +The C of a user can either be C which means that the user is a normal +LiveJournal user or it can be C which means that the user is actually a +community which the current LJ user is a member of. + +It should be noted that any of the values in the hash above can be undefined if +that value was not returned from the LiveJournal server. + +The returned list is ordered by the LiveJournal login names of the users. + +Example code: + + use POSIX; + + my ($num_friends,@Friends)=$lj->GetFriends(); + (defined $num_friends) || + die "$0: Failed to get friends - $LJ::Simple::error\n"; + + my $f=undef; + foreach $f (@Friends) { + foreach (qw(dob birthday)) { + (defined $f->{$_}) || next; + $f->{$_}=strftime("%Y/%m/%d",gmtime($f->{$_})); + } + my ($k,$v)=(undef,undef); + while(($k,$v)=each %{$f}) { + (!defined $v) && ($f->{$k}="[undefined]"); + } + print "$f->{user}\n"; + print " Name : $f->{name}\n"; + print " Colors : fg->$f->{fg} bg->$f->{bg}\n"; + print " DOB : $f->{dob}\n"; + print " Next birthday: $f->{birthday}\n"; + print " Status : $f->{status}\n"; + print " Type : $f->{type}\n"; + if ($#{$f->{groups}}>-1) { + print " Friend groups:\n"; + print " + ",join("\n + ",@{$f->{groups}}),"\n"; + } else { + print " Friend groups: [none]\n"; + } + print "\n"; + } + +=cut +sub GetFriends($) { + my $self=shift; + $LJ::Simple::error=""; + my %Event=( + includegroups => 1, + includebdays => 1, + ); + my %Resp=(); + $self->SendRequest("getfriends",\%Event,\%Resp) || return undef; + my %Friends=(); + my ($k,$v); + while(($k,$v)=each %Resp) { + ($k=~/^friend_([0-9]+)_(.*)/) || next; + my ($id,$type)=($1,$2); + if (!exists $Friends{$id}) { + $Friends{$id}={ + user => undef, + name => undef, + bg => undef, + fg => undef, + dob => undef, + birthday => undef, + groups => [], + groupmask => undef, + status => "active", + type => "user", + }; + } + if ($type eq "birthday") { + ($v=~/([0-9]+)-([0-9]{2})-([0-9]{2})/o) || next; + my @tm=(0,0,0,$3,$2,$1-1900); + if ($tm[5]>0) { + $Friends{$id}->{dob}=mktime(@tm); + if (!defined $Friends{$id}->{dob}) { + $LJ::Simple::error="Failed to convert time $v into Unix timestamp"; + return undef; + } + } + $tm[5]=(gmtime(time()))[5]; + $Friends{$id}->{birthday}=mktime(@tm); + if (!defined $Friends{$id}->{birthday}) { + $LJ::Simple::error="Failed to convert time $v into Unix timestamp"; + return undef; + } + } else { + $Friends{$id}->{$type}=$v; + } + } + if (defined $self->{groups}) { + my $id=undef; + foreach $id (values %Friends) { + (defined $id->{groupmask}) || next; + foreach (values %{$self->{groups}->{name}}) { + my $bit=1 << $_->{id}; + if (($id->{groupmask} & $bit) == $bit) { + push(@{$id->{groups}},$_->{name}); + } + } + } + } + my @lst=sort {$a->{user} cmp $b->{user}} (values %Friends); + return ($#lst+1,@lst); +} + + +=pod + +=item $lj->CheckFriends(@groups) + +This routine is used to poll the LiveJournal server to see if your friends list +has been updated or not. This routine returns a list. The first item in the +list is a value which holds C<1> if there has been an update +to your friends list and C<0> if not. The second item in the list holds the number +of seconds you must wait before calling C again. +In the event of an error C is returned in the first item of the list. + +The routine can be given an optional list of friends group to check instead of +just looking at all of the friends for the user. + +Example code: + + while(1) { + my ($new_friends,$next_update)=$lj->CheckFriends(); + (defined $new_friends) || + die "$0: Failed to check friends - $LJ::Simple::error\n"; + ($new_friends) && print "Friends list updated\n"; + sleep($next_update+1); + } + +=cut +sub CheckFriends($$) { + my $self=shift; + my (@groups)=@_; + my %Event=(); + my %Resp=(); + if ($#groups>-1) { + if (!defined $self->{groups}) { + $LJ::Simple::error="Groups not requested at login"; + return 0; + } + my $g; + my $mask=0; + foreach $g (@groups) { + if (!exists $self->{groups}->{name}->{$g}) { + $LJ::Simple::error="Group \"$g\" does not exist"; + return 0; + } + $mask=$mask | (1 << $self->{groups}->{name}->{$g}->{id}); + } + $Event{mask}=$mask; + } + if (exists $self->{checkfriends}) { + $Event{lastupdate}=$self->{checkfriends}->{lastupdate}; + my $currtime=time(); + if ($currtime<$self->{checkfriends}->{interval}) { + $LJ::Simple::error="Insufficent time left between CheckFriends() call"; + return undef; + } + } else { + $self->{checkfriends}={}; + } + $self->SendRequest("checkfriends",\%Event,\%Resp) || return undef; + $self->{checkfriends}->{lastupdate}=$Resp{lastupdate}; + $self->{checkfriends}->{interval}=time() + $Resp{interval}; + return ($Resp{new},$Resp{interval}); +} + + +=pod + +=item $lj->GetDayCounts($hash_ref,$journal) + +This routine is given a reference to hash which it fills with information +on the journal entries posted to the LiveJournal we are currently associated +with. On success the reference to the hash will be returned. On error +C is returned. + +There is an optional argument - C<$journal> - which can be used to gather this +data for a shared journal the user has access to. If not required then this +value should be C or an empty string. + +The key to the hash is a date, given as seconds since epoch (I C) +and the value is the number of entries made on that day. Only dates which have +journal entries made against them will have values in the hash; thus it can be +assumed that if a date is B in the hash then no journal entries were made +on that day. + +The hash will be emptied before use. + +Example code: + + use POSIX; + (defined $lj->GetDayCounts(\%gdc_hr,undef)) + || die "$0: Failed to get day counts - $LJ::Simple::error\n"; + + foreach (sort {$a<=>$b} keys %gdc_hr) { + printf("%s %03d\n",strftime("%Y/%m/%d",gmtime($_)),$gdc_hr{$_}); + } + +=cut +sub GetDayCounts($$$) { + my $self=shift; + my ($hr,$journal)=@_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + my $r=ref($hr); + $LJ::Simple::error="CODE: GetDayCounts() given \"$r\", not a hash reference"; + return undef; + } + %{$hr}=(); + my %Event=(); + my %Resp=(); + if ((defined $journal) && ($journal ne "")) { + $Event{usejournal}=$journal; + } + $self->SendRequest("getdaycounts",\%Event,\%Resp) || return undef; + my ($k,$v); + while(($k,$v)=each %Resp) { + ($k=~/([0-9]+)-([0-9]+)-([0-9]+)/o) || next; + ($v==0) && next; + my $timet=mktime(0,0,0,$3,$2-1,$1-1900); + if (!defined $timet) { + $LJ::Simple::error="Failed to convert date $k into Unix timestamp"; + return undef; + } + if (exists $hr->{$timet}) { + $hr->{$timet}=$hr->{$timet}+$v; + } else { + $hr->{$timet}=$v; + } + } + return $hr; +} + + +=pod + +=item $lj->GetFriendGroups($hash_ref) + +This routine is given a reference to a hash which it fills with information +on the friends groups the user has defined. On success the reference to the +hash will be returned. On error C is returned. + +The hash key is the id number of the friends group as it is possible to +have multiple friends groups with the same name. Each hash value is a hash +reference which points to the following hash: + + { + id => Id of the group; used to create permission masks + name => Name of the group + sort => Sort order number from 0 to 255 + public => Public group ? 1 for yes, 0 for no + } + +The hash given will be emptied before use. + +Example code: + + my %fg=(); + (defined $lj->GetFriendGroups(\%fg)) || + die "$0: Failed to get groups - $LJ::Simple::error\n"; + + my $format="| %-4s | %-2s | %-6s | %-40s |\n"; + my $line=sprintf($format,"","","",""); + $line=~s/\|/+/go; + $line=~s/ /-/go; + print $line; + printf($format,"Sort","Id","Public","Group"); + print $line; + + foreach (sort {$fg{$a}->{sort}<=>$fg{$b}->{sort}} keys %fg) { + my $hr=$fg{$_}; + my $pub="No"; + $hr->{public} && ($pub="Yes"); + printf($format,$hr->{sort},$hr->{id},$pub,$hr->{name}); + } + + print $line; + +In case you're wondering, the above code outputs something similar to +the following: + + +------+----+--------+------------------------------------------+ + | Sort | Id | Public | Group | + +------+----+--------+------------------------------------------+ + | 5 | 1 | Yes | Good Friends | + | 10 | 2 | No | Communities | + +------+----+--------+------------------------------------------+ + +=cut +sub GetFriendGroups($$) { + my $self=shift; + my ($hr)=@_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + my $r=ref($hr); + $LJ::Simple::error="CODE: GetFriendGroups() given \"$r\", not a hash reference"; + return undef; + } + %{$hr}=(); + my %Event=(); + my %Resp=(); + $self->SendRequest("getfriendgroups",\%Event,\%Resp) || return undef; + my ($k,$v); + while(($k,$v)=each %Resp) { + $k=~/^frgrp_([0-9]+)_(.*)$/o || next; + my ($id,$name)=($1,$2); + if (!exists $hr->{$id}) { + $hr->{$id}={ + id => $id, + public => 0, + }; + } + ($name eq "sortorder") && ($name="sort"); + $hr->{$id}->{$name}=$v; + } + return $hr; +} + +=pod + +=item $lj->CreateFriendGroups($hash_ref) + +This routine modifies user friend groups according to $hash_ref + +=cut + +sub CreateFriendGroups($$) { + my $self=shift; + my ($hr)=@_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + my $r=ref($hr); + $LJ::Simple::error="CODE: CreateFriendGroups() given \"$r\", not a hash reference"; + return undef; + } + my %Event=(); + my %Resp=(); + + my $i = 0; + foreach my $grpid (keys %{$hr}) { + if ($grpid > 0 && $grpid < 31) { + my $pname = "efg_set_" . $grpid . "_name"; + $Event{$pname} = $hr->{$grpid}->{name}; + $i++; + } + } + + $self->SendRequest("editfriendgroups",\%Event,\%Resp) || return undef; + return $i; +} + +=pod + +=back + +=head2 The creation and editing of entries + +=over 4 + +=item $lj->NewEntry($event) + +Prepares for a new journal entry to be sent into the LiveJournal system. +Takes a reference to a hash which will be emptied and prepared for use +by the other routines used to prepare a journal entry for posting. + +On success returns C<1>, on failure returns C<0> + +Example code: + + my %Entry=(); + $lj->NewEntry(\%Entry) + || die "$0: Failed to prepare new post - $LJ::Simple::error\n"; + +=cut +sub NewEntry($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + ## Build the event hash - put defaults in + my $ltime=time(); + my @ltime=localtime($ltime); + %{$event}=( + __new_entry => 1, + event => undef, + lineenddings => "unix", + subject => undef, + year => $ltime[5]+1900, + mon => $ltime[4]+1, + day => $ltime[3], + hour => $ltime[2], + min => $ltime[1], + __timet => $ltime, + ); + return 1; +} + + +=pod + +=item $lj->SetDate($event,$time_t) + +Sets the date for the event being built from the given C (i.e. seconds +since epoch) value. Bare in mind that you may need to call +C<$lj-ESetprop_backdate(\%Event,1)> to backdate the journal entry if the journal being +posted to has events more recent than the date being set here. Returns C<1> on +success, C<0> on failure. + +If the value given for C is C then the current time is used. +If the value given for C is negative then it is taken to be relative +to the current time, i.e. a value of C<-3600> is an hour earlier than the +current time. + +Note that C is called to convert the C value into +the year, month, day, hours and minute values required by LiveJournal. +Thus the time given to LiveJournal will be the local time as shown on +the machine the code is running on. + +Example code: + + ## Set date to current time + $lj->SetDate(\%Event,undef) + || die "$0: Failed to set date of entry - $LJ::Simple::error\n"; + + ## Set date to Wed Aug 14 11:56:42 2002 GMT + $lj->SetDate(\%Event,1029326202) + || die "$0: Failed to set date of entry - $LJ::Simple::error\n"; + + ## Set date to an hour ago + $lj->SetDate(\%Event,-3600) + || die "$0: Failed to set date of entry - $LJ::Simple::error\n"; + +=cut +sub SetDate($$$) { + my $self=shift; + my ($event,$timet)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + (defined $timet) || ($timet=time()); + if ($timet<0) { + $timet=time() + $timet; + } + my @ltime=localtime($timet); + $event->{__timet}=$timet; + $event->{year}=$ltime[5]+1900; + $event->{mon}=$ltime[4]+1; + $event->{day}=$ltime[3]; + $event->{hour}=$ltime[2]; + $event->{min}=$ltime[1]; + return 1; +} + + +=pod + +=item $lj->SetMood($event,$mood) + +Given a mood this routine sets the mood for the journal entry. Unlike the +more direct C<$lj-ESetprop_current_mood()> and C<$lj-ESetprop_current_mood_id(\%Event,)> +routines, this routine will attempt to first attempt to find the mood given +to it in the mood list returned by the LiveJournal server. If it is unable to +find a suitable mood then it uses the text given. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will not attempt to find the +mood name given in C<$mood> in the mood list. + +Returns C<1> on success, C<0> otherwise. + +Example code: + + $lj->SetMood(\%Event,"happy") + || die "$0: Failed to set mood - $LJ::Simple::error\n"; + +=cut +sub SetMood($$$) { + my $self=shift; + my ($event,$mood) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + ## Simple opt - none of the mood names have a space in them + if (($mood!~/\s/)&&(defined $self->{mood_map})) { + my $lc_mood=lc($mood); + if (exists $self->{mood_map}->{$lc_mood}) { + return $self->Setprop_current_mood_id($event,$self->{mood_map}->{$lc_mood}) + } + } + return $self->Setprop_current_mood($event,$mood); +} + + + +=pod + +=item $lj->UseJournal($event,$journal) + +The journal entry will be posted into the shared journal given +as an argument rather than the default journal for the user. + +Returns C<1> on success, C<0> otherwise. + +Example code: + + $lj->UseJournal(\%Event,"some_community") + || die "$0: Failed to - $LJ::Simple::error\n"; + +=cut +sub UseJournal($$$) { + my $self=shift; + my ($event,$journal) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if ((defined $self->{access})&&(!exists $self->{access}->{$journal})) { + $LJ::Simple::error="user unable to post to journal \"$journal\""; + return 0; + } + $event->{usejournal}=$journal; + return 1; +} + + +=pod + +=item $lj->SetSubject($event,$subject) + +Sets the subject for the journal entry. The subject has the following +limitations: + + o Limited to a length of 255 characters + o No newlines are allowed + +Returns C<1> on success, C<0> otherwise. + +Example code: + + $lj->SetSubject(\%Event,"Some subject") + || die "$0: Failed to set subject - $LJ::Simple::error\n"; + +=cut +sub SetSubject($$$) { + my $self=shift; + my ($event,$subject) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if ($subject) { + if (length($subject)>255) { + my $len=length($subject); + $LJ::Simple::error="Subject length limited to 255 characters [given $len]"; + return 0; + } + if ($subject=~/[\r\n]/) { + $LJ::Simple::error="New lines not allowed in subject"; + return 0; + } + $event->{subject}=$subject; + } + else { + $event->{subject}=""; + } + return 1; +} + + +=pod + +=item $lj->SetEntry($event,@entry) + +Sets the entry for the journal; takes a list of strings. It should be noted +that this list will be Ced together with a newline between each +list entry. + +If the list is null or C then any existing entry is removed. + +Returns C<1> on success, C<0> otherwise. + +Example code: + + # Single line entry + $lj->SetEntry(\%Event,"Just a simple entry") + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + + # Three lines of text + my @stuff=( + "Line 1", + "Line 2", + "Line 3", + ); + $lj->SetEntry(\%Event,@stuff) + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + + # Clear the entry + $lj->SetEntry(\%Event,undef) + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + $lj->SetEntry(\%Event) + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + +=cut +sub SetEntry($$@) { + my $self=shift; + my ($event,@entry) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if ((!defined $entry[0]) || ($#entry == -1)) { + $event->{event}=undef; + } else { + $event->{event}=join("\n",@entry); + } + return 1; +} + + +=pod + +=item $lj->AddToEntry($event,@entry) + +Adds a string to the existing journal entry being worked on. The new data +will be appended to the existing entry with a newline separating them. +It should be noted that as with C<$lj-ESetEntry()> the list given to +this routine will be Ced together with a newline between each +list entry. + +If C<$lj-ESetEntry()> has not been called then C<$lj-EAddToEntry()> acts +in the same way as C<$lj-ESetEntry()>. + +If C<$lj-ESetEntry()> has already been called then calling C<$lj-EAddToEntry()> +with a null list or a list which starts with C is a NOP. + +Returns C<1> on success, C<0> otherwise. + +Example code: + + # Single line entry + $lj->AddToEntry(\%Event,"Some more text") + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + + # Three lines of text + my @stuff=( + "Line 5", + "Line 6", + "Line 7", + ); + $lj->AddToEntry(\%Event,@stuff) + || die "$0: Failed to set entry - $LJ::Simple::error\n"; + +=cut +sub AddToEntry($$@) { + my $self=shift; + my ($event,@entry) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if (!defined $event->{event}) { + if ((!defined $entry[0]) || ($#entry == -1)) { + $event->{event}=undef; + } else { + $event->{event}=join("\n",@entry); + } + } else { + if ((!defined $entry[0]) || ($#entry == -1)) { + return 1; + } + $event->{event}=join("\n",$event->{event},@entry); + } + return 1; +} + + +=pod + +=back + +=head2 Setting of journal entry security levels + +=over 4 + +=item $lj->SetProtect($event,$type,@args) + +A wrapper function which calls the underlying C routines +for the caller. This takes two or more arguments; the first argument is +the hash reference of the current event. The second argument is the +type of security we are setting. Subsequent arguments are related to +the security type. Available types and their arguments are: + + +---------+------------------+------------------------------------+ + | Type | Additional args | Security | + +---------+------------------+------------------------------------+ + | public | None | Public - the default | + | friends | None | Friends only | + | groups | A list of groups | Restricted to groups of friends | + | private | None | Private - only the user can access | + +---------+------------------+------------------------------------+ + +On success this routine returns C<1>; otherwise it returns C<0> and +sets C<$LJ::Simple::error> to the reason why. + +Example code: + + ## Make entry public (the default) + $lj->SetProtect(\%Event,"public") + || die "$0: Failed to make entry public - $LJ::Simple::error\n"; + + ## Make entry friends only + $lj->SetProtect(\%Event,"friends") + || die "$0: Failed to make entry friends only - $LJ::Simple::error\n"; + + ## Make entry only readable by friends in the groups "close" and "others" + $lj->SetProtect(\%Event,"groups","close","others") + || die "$0: Failed to make entry public - $LJ::Simple::error\n"; + + ## Make entry private so only the journal owner can view it + $lj->SetProtect(\%Event,"private") + || die "$0: Failed to make entry private - $LJ::Simple::error\n"; + +=cut +sub SetProtect($$$@) { + my $self=shift; + my ($event,$type,@args)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if ($type eq "public") { + return $self->SetProtectPublic($event); + } elsif ($type eq "friends") { + return $self->SetProtectFriends($event); + } elsif ($type eq "groups") { + return $self->SetProtectGroups($event,@args); + } elsif ($type eq "private") { + return $self->SetProtectPrivate($event); + } else { + $LJ::Simple::error="CODE: type \"$type\" not recognised by SetProtect()"; + return 0; + } +}; + +=pod + +=item $lj->SetProtectPublic($event) + +Sets the current post so that anyone can read the journal entry. Note that this +is the default for a new post created by C - this method is most +useful when working with an existing post. Returns C<1> on success, C<0> +otherwise. + +Example code: + + $lj->SetProtectPublic(\%Event) + || die "$0: Failed to make entry public - $LJ::Simple::error\n"; + +=cut +sub SetProtectPublic($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + (exists $event->{security}) && delete $event->{security}; + (exists $event->{allowmask}) && delete $event->{allowmask}; + return 1; +} + + +=pod + + +=pod + +=item $lj->SetProtectFriends($event) + +Sets the current post so that only friends can read the journal entry. Returns +C<1> on success, C<0> otherwise. + +Example code: + + $lj->SetProtectFriends(\%Event) + || die "$0: Failed to protect via friends - $LJ::Simple::error\n"; + +=cut +sub SetProtectFriends($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + $event->{security}="usemask"; + $event->{allowmask}=1; + return 1; +} + + +=pod + +=item $lj->SetProtectGroups($event,$group1, $group2, ... $groupN) + +Takes a list of group names and sets the current entry so that only those +groups can read the journal entry. Returns +C<1> on success, C<0> otherwise. + +Example code: + + $lj->SetProtectGroups(\%Event,"foo","bar") + || die "$0: Failed to protect via group - $LJ::Simple::error\n"; + +=cut +sub SetProtectGroups($$@) { + my $self=shift; + my ($event,@grps) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if (!defined $self->{groups}) { + $LJ::Simple::error="Groups not requested at login"; + return 0; + } + if ($#grps==-1) { + $LJ::Simple::error="No group names given"; + return 0; + } + $event->{security}="usemask"; + my $g; + my $mask=0; + foreach $g (@grps) { + if (!exists $self->{groups}->{name}->{$g}) { + $LJ::Simple::error="Group \"$g\" does not exist"; + return 0; + } + $mask=$mask | (1 << $self->{groups}->{name}->{$g}->{id}); + } + $event->{allowmask}=$mask; + return 1; +} + +=pod + +=item $lj->SetProtectPrivate($event) + +Sets the current post so that the owner of the journal only can read the +journal entry. Returns C<1> on success, C<0> otherwise. + +Example code: + + $lj->SetProtectPrivate(\%Event) + || die "$0: Failed to protect via private - $LJ::Simple::error\n"; + +=cut +sub SetProtectPrivate($$) { + my $self=shift; + my ($event) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + $event->{security}="private"; + (exists $event->{allowmask}) && + delete $event->{allowmask}; + return 1; +} + + +## +## Helper function used to set meta data +## +sub Setprop_general($$$$$$) { + my ($self,$event,$prop,$caller,$type,$data)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + my $nd=undef; + if ($type eq "bool") { + if (($data == 1)||($data == 0)) { + $nd=$data; + } else { + $LJ::Simple::error="INTERNAL: Invalid value [$data] for type bool [from $caller]"; + return 0; + } + } elsif ($type eq "char") { + $nd=$data; + } elsif ($type eq "num") { + if ($data!~/^[0-9]+$/o) { + $LJ::Simple::error="INTERNAL: Invalid value [$data] for type num [from $caller]"; + return 0; + } + $nd=$data; + } else { + $LJ::Simple::error="INTERNAL: Unknown type \"$type\" [from $caller]"; + return 0; + } + if (!defined $nd) { + $LJ::Simple::error="INTERNAL: Setprop_general did not set \$nd [from $caller]"; + return 0; + } + $event->{"prop_$prop"}=$nd; + return 1; +} + +=pod + +=back + +=head2 Setting journal entry properties + +=over 4 + +=item $lj->Setprop_taglist($event,@tags) + +Set the tags for the entry; C<@tags> is a list of the tags to give the +entry. + +Example code: + + $lj->Setprop_taglist(\%Event,qw( gabe pets whatever )) || + die "$0: Failed to set back date property - $LJ::Simple::error\n"; + +=cut +sub Setprop_taglist($$@) { + my ($self,$event,@tags)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"taglist","Setprop_taglist","char",join(", ",@tags)); +} + +=pod + +=item $lj->Setprop_backdate($event,$onoff) + +Used to indicate if the journal entry being written should be back dated or not. Back dated +entries do not appear on the friends view of your journal entries. The C<$onoff> +value takes either C<1> for switching the property on or C<0> for switching the +property off. Returns C<1> on success, C<0> on failure. + +You will need to set this value if the journal entry you are sending has a +date earlier than other entries in your journal. + +Example code: + + $lj->Setprop_backdate(\%Event,1) || + die "$0: Failed to set back date property - $LJ::Simple::error\n"; + +=cut +sub Setprop_backdate($$$) { + my ($self,$event,$onoff)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"opt_backdated","Setprop_backdate","bool",$onoff); +} + + +=pod + +=item $lj->Setprop_current_mood($event,$mood) + +Used to set the current mood for the journal being written. This takes a string which +describes the mood. + +It is better to use C<$lj-ESetMood()> as that will automatically use a +mood known to the LiveJournal server if it can. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_current_mood(\%Event,"Happy, but tired") || + die "$0: Failed to set current_mood property - $LJ::Simple::error\n"; + +=cut +sub Setprop_current_mood($$$) { + my ($self,$event,$mood)=@_; + $LJ::Simple::error=""; + if ($mood=~/[\r\n]/) { + $LJ::Simple::error="Mood may not contain a new line"; + return 0; + } + return $self->Setprop_general($event,"current_mood","Setprop_current_mood","char",$mood); +} + +=pod + +=item $lj->Setprop_current_mood_id($event,$id) + +Used to set the current mood_id for the journal being written. This takes a number which +refers to a mood_id the LiveJournal server knows about. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will not attempt to validate +the C given to it. + +It is better to use C<$lj-ESetMood()> as that will automatically use a +mood known to the LiveJournal server if it can. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_current_mood_id(\%Event,15) || + die "$0: Failed to set current_mood_id property - $LJ::Simple::error\n"; + +=cut +sub Setprop_current_mood_id($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + if (defined $self->{moods}) { + if (!exists $self->{moods}->{$data}) { + $LJ::Simple::error="The mood_id $data is not known by the LiveJournal server"; + return 0; + } + } + return $self->Setprop_general($event,"current_moodid","Setprop_current_mood_id","num",$data); +} + + +=pod + +=item $lj->Setprop_current_music($event,$music) + +Used to set the current music for the journal entry being written. This takes +a string. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_current_music(\%Event,"Collected euphoric dance") || + die "$0: Failed to set current_music property - $LJ::Simple::error\n"; + +=cut +sub Setprop_current_music($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"current_music","Setprop_current_music","char",$data); +} + +=pod + +=item $lj->Setprop_preformatted($event,$onoff) + +Used to set if the text for the journal entry being written is preformatted in HTML +or not. This takes a boolean value of C<1> for true and C<0> for false. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_preformatted(\%Event,1) || + die "$0: Failed to set property - $LJ::Simple::error\n"; + +=cut +sub Setprop_preformatted($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"opt_preformatted","Setprop_preformatted","bool",$data); +} + + +=pod + +=item $lj->Setprop_nocomments($event,$onoff) + +Used to set if the journal entry being written can be commented on or not. This takes +a boolean value of C<1> for true and C<0> for false. Thus if you use a value +of C<1> (true) then comments will not be allowed. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_nocomments(\%Event,1) || + die "$0: Failed to set property - $LJ::Simple::error\n"; + +=cut +sub Setprop_nocomments($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"opt_nocomments","Setprop_nocomments","bool",$data); +} + + +=pod + +=item $lj->Setprop_picture_keyword($event,$keyword) + +Used to set the picture keyword for the journal entry being written. This takes +a string. We check to make sure that the picture keyword exists. + +Note that if the LiveJournal +object was created with either C set to C<0> or +with C set to C<1> then this function will B validate +the picture keyword before setting it. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_picture_keyword(\%Event,"Some photo") || + die "$0: Failed to set property - $LJ::Simple::error\n"; + +=cut +sub Setprop_picture_keyword($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + if (defined $self->{pictures}) { + my $match=0; + foreach (values %{$self->{pictures}}) { + if ($_->{name} eq $data) { + $match=1; + last; + } + } + if (!$match) { + $LJ::Simple::error="Picture keyword not associated with journal"; + return 0; + } + } + return $self->Setprop_general($event,"picture_keyword","Setprop_picture_keyword","char",$data); +} + + +=pod + +=item $lj->Setprop_noemail($event,$onoff) + +Used to say that comments on the journal entry being written should not be emailed. +This takes boolean value of C<1> for true and C<0> for false. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_noemail(\%Event,1) || + die "$0: Failed to set property - $LJ::Simple::error\n"; + +=cut +sub Setprop_noemail($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"opt_noemail","Setprop_noemail","bool",$data); +} + + +=pod + +=item $lj->Setprop_unknown8bit($event,$onoff) + +Used say that there is 8-bit data which is not in UTF-8 in the journal entry +being written. This takes a boolean value of C<1> for true and C<0> for false. + +Returns C<1> on success, C<0> on failure. + +Example code: + + $lj->Setprop_unknown8bit(\%Event,1) || + die "$0: Failed to set property - $LJ::Simple::error\n"; + +=cut +sub Setprop_unknown8bit($$$) { + my ($self,$event,$data)=@_; + $LJ::Simple::error=""; + return $self->Setprop_general($event,"unknown8bit","Setprop_unknown8bit","bool",$data); +} + + +=pod + +=back + +=head2 Posting, editing and deleting journal entries + +=over 4 + +=item $lj->PostEntry($event) + +Submit a journal entry into the LiveJournal system. This requires you to have +set up the journal entry with C<$lj-ENewEntry()> and to have at least called +C<$lj-ESetEntry()>. + +On success a list containing the following is returned: + + o The item_id as returned by the LiveJournal server + o The anum as returned by the LiveJournal server + o The item_id of the posted entry as used in HTML - that is the + value of C<($item_id * 256) + $anum)> + +On failure C is returned. + + # Build the new entry + my %Event; + $lj->NewEntry(\%Event) || + die "$0: Failed to create new journal entry - $LJ::Simple::error\n"; + + # Set the journal entry + $lj->SetEntry(\%Event,"foo") || + die "$0: Failed set journal entry - $LJ::Simple::error\n"; + + # And post it + my ($item_id,$anum,$html_id)=$lj->PostEntry(\%Event); + defined $item_id || + die "$0: Failed to submit new journal entry - $LJ::Simple::error\n"; + +=cut +## +## PostEntry - actually submit a journal entry. +## +sub PostEntry($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{"__new_entry"}) { + $LJ::Simple::error="CODE: NewEntry not called"; + return undef; + } + + ## Blat any key in $event which starts with a double underscore + map {/^__/ && delete $event->{$_}} (keys %{$event}); + + if (!defined $event->{event}) { + $LJ::Simple::error="CODE: No journal entry set - call SetEntry() or AddToEntry() first"; + return undef; + } + + ## Blat any entry in $self->{event} with an undef value + map {defined $event->{$_} || delete $event->{$_}} (keys %{$event}); + + ## Finally send the actual request + my %Resp=(); + $self->SendRequest("postevent",$event,\%Resp) || return undef; + + if (!exists $Resp{itemid}) { + $LJ::Simple::error="LJ server did not return itemid"; + return undef; + } + if (!exists $Resp{anum}) { + $LJ::Simple::error="LJ server did not return anum"; + return undef; + } + + return ($Resp{itemid},$Resp{anum},($Resp{itemid} * 256) + $Resp{anum}); +} + +=pod + +=item $lj->EditEntry($event) + +Edit an entry from the LiveJournal system which has the givem C. +The entry should have been fetched from LiveJournal using the +C<$lj-EGetEntries()> function and then adjusted using the various +C<$lj-ESet...()> functions. + +It should be noted that this function can be used to delete a journal entry +by setting the entry to a blank string, I by using +C<$lj-ESetEntry(\%Event,undef)> + +Returns C<1> on success, C<0> on failure. + +Example: + + # Fetch the most recent event + my %Events = (); + (defined $lj->GetEntries(\%Events,undef,"one",-1)) || + die "$0: Failed to get entries - $LJ::Simple::error\n"; + + # Mark it as private + foreach (values %Entries) { + $lj->SetProtectPrivate($_); + $lj->EditEntry($_) || + die "$0: Failed to edit entry - $LJ::Simple::error\n"; + } + + # Alternatively we could just delete it... + my $event=(values %Entries)[0]; + $lj->SetEntry($event,undef); + $lj->EditEntry($event) || + die "$0: Failed to edit entry - $LJ::Simple::error\n"; + +=cut +sub EditEntry($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return 0; + } + if (!exists $event->{"__itemid"}) { + $LJ::Simple::error="CODE: Not an existing entry; use GetEntry()"; + return 0; + } + $event->{itemid}=$event->{"__itemid"}; + + ## Blat any key in $event which starts with a double underscore + map {/^__/ && delete $event->{$_}} (keys %{$event}); + + if (!defined $event->{event}) { + $LJ::Simple::error="CODE: No journal entry set"; + return 0; + } + + ## Blat any entry in $event with an undef value + map {defined $event->{$_} || delete $event->{$_}} (keys %{$event}); + + ## Make the request + return $self->SendRequest("editevent",$event,undef); +} + +=pod + +=item $lj->DeleteEntry($item_id) + +Delete an entry from the LiveJournal system which has the given C. +On success C<1> is returned; on failure C<0> is returned. + +Example: + + $lj->DeleteEntry($some_item_id) || + die "$0: Failed to delete journal entry - $LJ::Simple::error\n"; + +=cut +sub DeleteEntry($$) { + my $self=shift; + my ($item_id) = @_; + $LJ::Simple::error=""; + if (!defined $item_id) { + $LJ::Simple::error="CODE: DeleteEntry() given undefined item_id"; + return 0; + } + if ($item_id!~/^[0-9]+$/) { + $LJ::Simple::error="CODE: DeleteEntry() given invalid item_id"; + return 0; + } + my %Event=( + itemid => $item_id, + event => "", + ); + return $self->SendRequest("editevent",\%Event,undef); +} + +=pod + +=back + +=head2 Retriving journal entries + +=over 4 + +=item $lj->SyncItems($timestamp) + +This routine returns a list of all of the items (journal entries, to-do items, +comments) which have been created or updated on LiveJournal. There is an optional +timestamp value for specifying the time you last synchronised with the server. +This timestamp value can either be a Unix-style C value or a previously +returned timestamp from this routine. If not used specify the undefined value +C. + +When specifying the time you must take into account the fact that the modification +or creation times of the entries in the LiveJournal database are stored as the +time local to the computer running the database rather than GMT. Due to this +it is safest to use the time from the latest item downloaded from the LiveJournal +from a previous C call. + +On success this routine will return a list which contains first the number of +valid items in the list and then a list of hashes which contain the details +of the items found. This routine can return an empty list which signifies that +no new items could be found. On failure C is returned. + +The format of the returned list is as follows. The list of hashes is ordered +by the timestamps of the entries, oldest to newest. + + @list = ( + number of items returned, + { + item_id => Item_id of the entry changed + type => Type of entry + action => What happened to the entry + time_t => Time of change in Unix time (see note below) + timestamp => Timestamp from server + }, + ); + +The C of entry can be one of the following letters: + + L: Journal entries + C: Comments + T: To-do items + +It should be noted that currently the LiveJournal system will only ever +return C types due to the C and C types not having been implemented +in the LiveJournal code yet. + +The C of the entry can be either C for a new entry, +C for an entry which has been modified or C for a deleted entry. + +The C value is probably going to be wrong; as far as the author of +this code can tell, you can not get the timezone of the server which is +serving out the request. This means that converting the timestamps +returned by the server from their format of C into +a Unix C value is inaccurate at best since C is defined +as the number of seconds since 00:00 1st January 1970 B. Functions +like C which can be used to create C values have to +assume that the data they are being given is valid for the timezone the +machine it is running on is actually in. Given the nature of the net +this is rarely the case. I I wish that the LJ developers had stored +timestamps in pure C in the database... and if they have done they +should provide a way for developers to get access to this as its B +more useful IMHO. + +Given the above you're probably wondering why I included the C +value. Well, whilst the value isn't much use when it really comes down +to it, it B useful when it comes to sorting the list of entries as +all of the entries from the same server will be inaccurate to the same +amount. + +The C from server takes the format of C + +It should be noted that this routine can take a long time to return +if there are large numbers of entries to be returned. This is especially +true if you give C as the timestamp. + +Example code: + + # All entries in the last day or so; this is fudged due to timezone + # differences (WTF didn't they store stuff in GMT ?) + my ($num_of_items,@lst)=$lj->SyncItems(time() - (86400 * 2)); + + (defined $num_of_items) || + die "$0: Failed to sync - $LJ::Simple::error\n"; + + my $hr=undef; + print "Number of items: $num_of_items\n"; + print "Item_id\tType\tAction\tTime_t\t\tTimestamp\n"; + foreach $hr (@lst) { + print "$hr->{item_id}\t" . + "$hr->{type}\t" . + "$hr->{action}\t" . + "$hr->{time_t}\t" . + "$hr->{timestamp}\n"; + } + +There is also an example of how to work with all of the entries of a LiveJournal +shown in the C script which accompanies the C +distribution. This example script looks at a LiveJournal and makes sure that every +journal entry is at the very least marked as being friends-only. + +=cut +sub SyncItems($$) { + my $self=shift; + my ($timet)=@_; + $LJ::Simple::error=""; + if ($LJ::Simple::debug) { + my $ts=undef; + if (defined $timet) { + $ts="\"$timet\""; + } else { + $ts="undef"; + } + Debug "SyncItems($ts)"; + } + my %Event=(); + my %Resp=(); + if (defined $timet) { + if ($timet=~/^[0-9]+$/) { + my @tm=gmtime($timet); + if ($#tm==-1) { + $LJ::Simple::error="CODE: Invalid timestamp"; + return undef; + } + $Event{lastsync}=strftime("%Y-%m-%d %H:%M:%S",@tm); + } else { + $Event{lastsync}=$timet; + } + } + $self->SendRequest("syncitems",\%Event,\%Resp) || return undef; + my %Mh=(); + my $sync_count; + my $sync_total; + my $latest=0; + my $latest_ts; + my ($key,$val); + while(($key,$val)=each %Resp) { + if ($key=~/sync_([0-9]+)_(.*)$/o) { + my ($id,$name)=($1,$2); + (exists $Mh{$id}) || ($Mh{$id}={}); + if ($name eq "item") { + my ($type,$item_id)=split(/-/,$val,2); + $Mh{$id}->{item_id}=$item_id; + $Mh{$id}->{type}=$type; + } elsif ($name eq "action") { + $Mh{$id}->{action}=$val; + } elsif ($name eq "time") { + $Mh{$id}->{timestamp}=$val; + if ($val!~/([0-9]+)-([0-9]+)-([0-9]+)\s([0-9]+):([0-9]+):([0-9]+)/io) { + $LJ::Simple::error="INTERNAL: failed to parse timestamp \"$val\""; + return undef; + } + $Mh{$id}->{time_t}=mktime($6,$5,$4,$3,$2-1,$1-1900,0,0,0); + if (!defined $Mh{$id}->{time_t}) { + $LJ::Simple::error="INTERNAL: failed to create time_t from \"$val\""; + return undef; + } + if ($Mh{$id}->{time_t}>$latest) { + $latest_ts=$val; + $latest=$Mh{$id}->{time_t}; + } + } else { + $LJ::Simple::error="INTERNAL: Unrecognised sync_[0-9]_* \"$key\""; + return undef; + } + } elsif ($key eq "sync_total") { + $sync_total=$val; + } elsif ($key eq "sync_count") { + $sync_count=$val; + } + } + Debug "sync_count=$sync_count\n"; + Debug "sync_total=$sync_total\n"; + my @lst=(); + push(@lst,values %Mh); + if ($sync_count != $sync_total) { + my ($num,@nl)=$self->SyncItems($latest_ts); + (defined $num) || return undef; + push(@lst,@nl); + } + @lst=sort { $a->{time_t} <=> $b->{time_t} } @lst; + map { $_->{kv}=join(":",$_->{item_id},$_->{type},$_->{action},$_->{time_t}) } @lst; + my %seen=(); + @lst=grep((!exists $seen{$_->{kv}}) && ($seen{$_->{kv}}=1),@lst); + my $tot=$#lst+1; + return ($tot,@lst); +} + +=pod + +=item $lj->GetEntries($hash_ref,$journal,$type,@opt) + +This routine allows you to pull events from the user's LiveJournal. There are +several different ways this routine can work depending on the value given in +the C<$type> argument. + +This routine will currently only allow you to get a B +thanks to restrictions imposed by LiveJournal servers. If you want to perform work +on I journal entry within a LiveJournal account then you should look at the +C routine documented above. + +The first argument - C<$hash_ref> is a reference to a hash which will be filled +with the details of the journal entries downloaded. The key to this hash is the +C of the journal entries. The value is a hash reference which points to +a hash of the same type created by C and used by C and +C. The most sensible way to access this hash is to use the various +C routines. + +The second argument - C<$journal> - is an optional argument set if the journal +to be accessed is a shared journal. If this is set then the name of shared journal +will be propogated into the entries returned in the hash reference C<$hash_ref> as +if C<$lj->UseJournal($event,$journal)> was called. If not required set this to C. + +The third argument - C<$type> - specifies how the journal entries are to be +pulled down. The contents of the fourth argument - C<@opt> - will depend on the +value in the C<$type> variable. Thus: + + +-------+------------+------------------------------------------+ + | $type | @opt | Comments | + +-------+------------+------------------------------------------+ + | day | $timestamp | Download a single day. $timestamp is a | + | | | Unix timestamp for the required day | + +-------+------------+------------------------------------------+ + | lastn |$num,$before| Download a number of entries. $num has a | + | | | maximum value of 50. If $num is undef | + | | | then the default of 20 is used. $before | + | | | is an optional value which specifies a | + | | | date before which all entries must occur.| + | | | The date is specified as a Unix | + | | | timestamp. If not specified the value | + | | | should be undef. | + +-------+------------+------------------------------------------+ + | one | $item_id | The unique ItemID for the entry to be | + | | | downloaded. A value of -1 means to | + | | | download the most recent entry | + +-------+------------+------------------------------------------+ + | sync | $date | Get journal entries since the given date.| + | | | The date should be specified as a Unix | + | | | timestamp. | + +-------+------------+------------------------------------------+ + +If the operation is successful then C<$hash_ref> is returned. On failure +C is returned and C<$LJ::Simple::error> is updated with the +reason for the error. + +Example code: + +The following code only uses a single C<$type> from the above list; C. +However the hash of hashes returned is the same in every C<$type> used. The +code below shows how to pull down the last journal entry posted and then uses +all of the various C routines to decode the hash returned. + + use POSIX; + + my %Entries=(); + (defined $lj->GetEntries(\%Entries,undef,"one",-1)) || + die "$0: Failed to get entries - $LJ::Simple::error\n"; + + my $Entry=undef; + my $Format="%-20s: %s\n"; + + foreach $Entry (values %Entries) { + + # Get URL + my $url=$lj->GetURL($Entry); + (defined $url) && print "$url\n"; + + # Get ItemId + my ($item_id,$anum,$html_id)=$lj->GetItemId($Entry); + (defined $item_id) && printf($Format,"Item_id",$item_id); + + # Get the subject + my $subj=$lj->GetSubject($Entry); + (defined $subj) && printf($Format,"Subject",$subj); + + # Get the date entry was posted + my $timet=$lj->GetDate($Entry); + if (defined $timet) { + printf($Format,"Date", + strftime("%Y-%m-%d %H:%M:%S",gmtime($timet))); + } + + # Is entry protected ? + my $EntProt=""; + my ($protect,@prot_opt)=$lj->GetProtect($Entry); + if (defined $protect) { + if ($protect eq "public") { + $EntProt="public"; + } elsif ($protect eq "friends") { + $EntProt="friends only"; + } elsif ($protect eq "groups") { + $EntProt=join("","only groups - ",join(", ",@prot_opt)); + } elsif ($protect eq "private") { + $EntProt="private"; + } + printf($Format,"Journal access",$EntProt); + } + + ## Properties + # Backdated ? + my $word="no"; + my $prop=$lj->Getprop_backdate($Entry); + if ((defined $prop) && ($prop==1)) { $word="yes" } + printf($Format,"Backdated",$word); + + # Preformatted ? + $word="no"; + $prop=$lj->Getprop_preformatted($Entry); + if ((defined $prop) && ($prop==1)) { $word="yes" } + printf($Format,"Preformatted",$word); + + # No comments allowed ? + $word="no"; + $prop=$lj->Getprop_nocomments($Entry); + if ((defined $prop) && ($prop==1)) { $word="yes" } + printf($Format,"No comments",$word); + + # Do not email comments ? + $word="no"; + $prop=$lj->Getprop_noemail($Entry); + if ((defined $prop) && ($prop==1)) { $word="yes" } + printf($Format,"No emailed comments",$word); + + # Unknown 8-bit ? + $word="no"; + $prop=$lj->Getprop_unknown8bit($Entry); + if ((defined $prop) && ($prop==1)) { $word="yes" } + printf($Format,"Any 8 bit, non UTF-8",$word); + + # Current music + $word="[None]"; + $prop=$lj->Getprop_current_music($Entry); + if ((defined $prop) && ($prop ne "")) { $word=$prop } + printf($Format,"Current music",$word); + + # Current mood [text] + $word="[None]"; + $prop=$lj->Getprop_current_mood($Entry); + if ((defined $prop) && ($prop ne "")) { $word=$prop } + printf($Format,"Current mood",$word); + + # Current mood [id] + $word="[None]"; + $prop=$lj->Getprop_current_mood_id($Entry); + if ((defined $prop) && ($prop ne "")) { $word=$prop } + printf($Format,"Current mood_id",$word); + + # Picture keyword + $word="[None]"; + $prop=$lj->Getprop_picture_keyword($Entry); + if ((defined $prop) && ($prop ne "")) { $word=$prop } + printf($Format,"Picture keyword",$word); + + # Finally output the actual journal entry + printf($Format,"Journal entry",""); + my $text=$lj->GetEntry($Entry); + (defined $text) && + print " ",join("\n ",split(/\n/,$text)),"\n\n"; + } + +=cut +sub GetEntries($$@) { + my $self=shift; + my ($hr,$journal,$type,@opts)=@_; + $LJ::Simple::error=""; + if (ref($hr) ne "HASH") { + $LJ::Simple::error="CODE: GetEntries() not given a hash reference"; + return undef; + } + %{$hr}=(); + my %Event=(); + my %Resp=(); + if (defined $journal) { + $Event{usejournal}=$journal; + } + my $ctype=lc($type); + if ($ctype eq "day") { + if ($#opts<0) { + $LJ::Simple::error="CODE: GetEntries($type) requires year,month,day in \@opts"; + return undef; + } + my ($timestamp)=@opts; + if ($timestamp!~/^[0-9]+$/) { + $LJ::Simple::error="CODE: GetEntries($type) given invalid timestamp"; + return undef; + } + my @tm=localtime($timestamp); + if ($#tm==-1) { + $LJ::Simple::error="CODE: GetEntries($type) given invalid timestamp"; + return undef; + } + $Event{selecttype}=$ctype; + $Event{year}=$tm[5]+1900; + $Event{month}=$tm[4]+1; + $Event{day}=$tm[3]; + } elsif ($ctype eq "lastn") { + if ($#opts<1) { + $LJ::Simple::error="CODE: GetEntries($type) requires num and beforedate in \@opts"; + return undef; + } + $Event{selecttype}=$ctype; + my ($num,$beforedate)=@opts; + if (defined $num) { + if ($num!~/^[0-9]{1,2}$/) { + $LJ::Simple::error="CODE: GetEntries($type) requires valid number for num"; + return undef; + } + if ($num>50) { + $LJ::Simple::error="Maximum number of journal entries returned is 50"; + return undef; + } + } else { + $num=20; + } + $Event{howmany}=$num; + if (defined $beforedate) { + if ($beforedate!~/^[0-9]+$/) { + $LJ::Simple::error="Invalid Unix timestamp"; + return undef; + } + my @tm=gmtime($beforedate); + if ($#tm==-1) { + $LJ::Simple::error="CODE: GetEntries($type) given invalid timestamp"; + return undef; + } + $Event{beforedate}=strftime("%Y-%m-%d %H:%M:%S",@tm); + } + } elsif ($ctype eq "one") { + if ($#opts<0) { + $LJ::Simple::error="CODE: GetEntries($type) requires item_id in \@opts"; + return undef; + } + my ($item_id)=@opts; + if ($item_id!~/^-*[0-9]+$/) { + $LJ::Simple::error="Invalid item_id"; + return undef; + } + if ($item_id<-1) { + $LJ::Simple::error="Invalid item_id"; + return undef; + } + $Event{selecttype}=$ctype; + $Event{itemid}=$item_id; + } elsif ($ctype eq "sync") { + if ($#opts<0) { + $LJ::Simple::error="CODE: GetEntries($type) requires timestamp in \@opts"; + return undef; + } + my ($lastsync)=@opts; + if ($lastsync!~/^[0-9]+$/) { + $LJ::Simple::error="Invalid Unix timestamp"; + return undef; + } + my @tm=gmtime($lastsync); + if ($#tm==-1) { + $LJ::Simple::error="CODE: GetEntries($type) given invalid timestamp"; + return undef; + } + $Event{lastsync}=strftime("%Y-%m-%d %H:%M:%S",@tm); + $Event{selecttype}="syncitems"; + } else { + $LJ::Simple::error="CODE: GetEntries() does not understand type $type\n"; + return undef; + } + $self->SendRequest("getevents",\%Event,\%Resp) || return undef; + my %Ev=(); + my %Pr=(); + my ($k,$v); + while(($k,$v)=each %Resp) { + my ($num,$key,$hash)=(undef,undef,undef); + if ($k=~/^events_([0-9]+)_(.*)$/) { + ($num,$key,$hash)=($1,$2,\%Ev); + } elsif ($k=~/^prop_([0-9]+)_(.*)$/) { + ($num,$key,$hash)=($1,$2,\%Pr); + } + if (defined $hash) { + (exists $hash->{$num}) || ($hash->{$num}={}); + $hash->{$num}->{$key}=$v; + } + } + my $ehr=undef; + foreach $ehr (values %Ev) { + my $itemid=$ehr->{itemid}; + $hr->{$itemid}={}; + my $nhr=$hr->{$itemid}; + %{$nhr}=( + __htmlid => ($ehr->{itemid} * 256) + $ehr->{anum}, + __anum => $ehr->{anum}, + __itemid => $itemid, + event => $ehr->{event}, + lineenddings => "unix", + ); + (defined $journal) && ($nhr->{usejournal}=$journal); + (exists $ehr->{subject}) && ($nhr->{subject}=$ehr->{subject}); + (exists $ehr->{allowmask}) && ($nhr->{allowmask}=$ehr->{allowmask}); + (exists $ehr->{security}) && ($nhr->{security}=$ehr->{security}); + if ($ehr->{eventtime}=~/([0-9]+)-([0-9]+)-([0-9]+)\s([0-9]+):([0-9]+):([0-9]+)/o) { + $nhr->{year}=int($1); + $nhr->{mon}=int($2); + $nhr->{day}=int($3); + $nhr->{hour}=int($4); + $nhr->{min}=int($5); + my $timet=mktime($6,$5,$4,$3,$2-1,$1-1900); + if (!defined $timet) { + $LJ::Simple::error="Failed to mktime() from \"$ehr->{eventtime}\" for itemid $hr->{$ehr->{itemid}}->{__htmlid}"; + return undef; + } + $nhr->{__timet}=$timet; + } else { + $LJ::Simple::error="Failed to parse eventtime \"$ehr->{eventtime}\" for itemid $hr->{$ehr->{itemid}}->{__htmlid}"; + return undef; + } + } + my $phr=undef; + foreach $phr (values %Pr) { + if (!exists $hr->{$phr->{itemid}}) { + $LJ::Simple::error="Protocol error: properties returned for itemid not seen"; + return undef; + } + my $nhr=$hr->{$phr->{itemid}}; + my $k=join("_","prop",$phr->{name}); + if (!exists $nhr->{$k}) { + $nhr->{$k}=$phr->{value}; + } + } + return $hr; +} + +=pod + +=back + +=head2 Getting information from an entry + +=over 4 + +=item $lj->GetDate($event) + +Gets the date for the event given. The date is returned as a C (i.e. seconds +since epoch) value. Returns C on failure. + +Example code: + + use POSIX; # For strftime() + + ## Get date + my $timet=$lj->GetDate(\%Event); + (defined $timet) + || die "$0: Failed to set date of entry - $LJ::Simple::error\n"; + + # Get time list using gmtime() + my @tm=gmtime($timet); + ($#tm<0) && + die "$0: Failed to run gmtime() on time_t $timet\n"; + + # Format date in the normal way used by LJ "YYYY-MM-DD hh:mm:ss" + my $jtime=strftime("%Y-%m-%d %H:%M:%S",@tm); + +=cut +sub GetDate($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{__timet}) { + $LJ::Simple::error="No time value stored"; + return undef; + } + return $event->{__timet}; +} + + +=pod + +=item $lj->GetItemId($event) + +Returns a list which contains the real C, C and HTMLised C which +can be used to contruct a URL suitable for accessing the item via the web. +Returns C on failure. Note that you must only use this +routine on entries which have been returned by the C +routine. + +Example code: + + my ($item_id,$anum,$html_id)=$lj->GetItemId(\%Event); + (defined $item_id) + || die "$0: Failed to get item id - $LJ::Simple::error\n"; + +=cut +sub GetItemId($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{__itemid}) { + $LJ::Simple::error="item_id does not exist - must use GetEntries()"; + return undef; + } + if (!exists $event->{__anum}) { + $LJ::Simple::error="anum does not exist - must use GetEntries()"; + return undef; + } + if (!exists $event->{__htmlid}) { + $LJ::Simple::error="HTML id does not exist - must use GetEntries()"; + return undef; + } + return ($event->{__itemid},$event->{__anum},$event->{__htmlid}); +} + + +=pod + +=item $lj->GetURL($event) + +Returns the URL which can be used to access the journal entry via a web +browser. Returns C on failure. Note that you must only use this +routine on entries which have been returned by the C +routine. + +Example code: + + my $url=$lj->GetURL(\%Event); + (defined $url) + || die "$0: Failed to get URL - $LJ::Simple::error\n"; + system("netscape -remote 'openURL($url)'"); + +=cut +sub GetURL($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{__htmlid}) { + $LJ::Simple::error="HTML id does not exist - must use GetEntries()"; + return undef; + } + my $user=$self->user(); + my $server=$self->{lj}->{host}; + my $port=$self->{lj}->{port}; + my $htmlid=$event->{__htmlid}; + return "http://$server:$port/talkpost.bml\?journal=$user\&itemid=$htmlid"; +} + +=pod + +=item $lj->GetSubject($event) + +Gets the subject for the journal entry. Returns the subject if it is +available, C otherwise. + +Example code: + + my $subj=$lj->GetSubject(\%Event) + if (defined $subj) { + print "Subject: $subj\n"; + } + +=cut +sub GetSubject($$) { + my $self=shift; + my ($event) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{subject}) { + $LJ::Simple::error="No subject set"; + return undef; + } + return $event->{subject}; +} + + +=pod + +=item $lj->GetEntry($event) + +Gets the entry for the journal. Returns either a single string which contains +the entire journal entry or C on failure. + +Example code: + + my $ent = $lj->GetEntry(\%Event); + (defined $ent) + || die "$0: Failed to get entry - $LJ::Simple::error\n"; + print "Entry: $ent\n"; + +=cut +sub GetEntry($$) { + my $self=shift; + my ($event) = @_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if (!exists $event->{event}) { + $LJ::Simple::error="No journal entry set"; + return undef; + } + return $event->{event}; +} + + +=pod + +=item $lj->GetProtect($event) + +Gets the protection information on the event given. Returns a list with +details of the protection set on the post. On failure C is returned. + +There are several different types of protection which can be returned for a +journal entry. These include public, friends only, specific friends groups +and private. The list returned will always have the type of protection listed +first followed by any details of that protection. Thus the list can contain: + + ("public") + A publically accessable journal entry + + ("friends") + Only friends may read the entry + + ("groups","group1" ...) + Only users listed in the friends groups given after the "groups" + may read the entry + + ("private") + Only the owner of the journal may read the entry + +Example code: + + my ($protect,@prot_opt)=$lj->GetProtect(\%Event); + (defined $protect) || + die "$0: Failed to get entry protection type - $LJ::Simple::error\n"; + if ($protect eq "public") { + print "Journal entry is public\n"; + } elsif ($protect eq "friends") { + print "Journal entry only viewable by friends\n"; + } elsif ($protect eq "groups") { + print "Journal entry only viewable by friends in the following groups:\n"; + print join(", ",@prot_opt),"\n"; + } elsif ($protect eq "private") { + print "Journal entry only viewable by the journal owner\n"; + } + +=cut +sub GetProtect($$) { + my $self=shift; + my ($event)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + if ((!exists $event->{security})||($event->{security} eq "")) { + return "public"; + } + if ($event->{security} eq "private") { + return "private"; + } + if ($event->{security} ne "usemask") { + $LJ::Simple::error="INTERNAL: security contains unknown value \"$event->{security}\""; + return undef; + } + if (($event->{allowmask} & 1) == 1) { + return "friends"; + } + my @lst=("groups"); + my $g=undef; + foreach $g (keys %{$self->{groups}->{name}}) { + my $bit=1 << $self->{groups}->{name}->{$g}->{id}; + if (($event->{allowmask} & $bit) == $bit) { + push(@lst,$g); + } + } + return @lst; +} + + +## +## Helper function used to get meta data +## +sub Getprop_general($$$$$) { + my ($self,$event,$prop,$caller,$type)=@_; + $LJ::Simple::error=""; + if (ref($event) ne "HASH") { + $LJ::Simple::error="CODE: Not given a hash reference"; + return undef; + } + my $key=join("_","prop",$prop); + if (!exists $event->{$key}) { + if ($type eq "bool") { + return 0; + } + return ""; + } + return $event->{$key}; +} + +=pod + +=item $lj->Getprop_taglist($event) + +Get tags for given entry. + +=cut +sub Getprop_taglist($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"taglist","Getprop_taglist","char"); +} + +=pod + +=item $lj->Getprop_backdate($event) + +Indicates if the journal entry is back dated or not. Back dated +entries do not appear on the friends view of your journal entries. Returns +C<1> if the entry is backdated, C<0> if it is not. C is returned in the +event of an error. + +Example code: + + my $prop=$lj->Getprop_backdate(\%Event); + (defined $prop) || + die "$0: Failed to get property - $LJ::Simple::error\n"; + if ($prop) { + print STDERR "Journal is backdated\n"; + } else { + print STDERR "Journal is not backdated\n"; + } + + +=cut +sub Getprop_backdate($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"opt_backdated","Getprop_backdate","bool"); +} + + +=pod + +=item $lj->Getprop_current_mood($event) + +Used to get the current mood for the journal being written. This returns the +mood if one exists, an empty string if none exists or C in the event +of an error. + +Example code: + + my $prop=$lj->Getprop_current_mood(\%Event); + (defined $prop) || + die "$0: Failed to get property - $LJ::Simple::error\n"; + if ($prop ne "") { + print STDERR "Journal has mood of $prop\n"; + } else { + print STDERR "Journal has no mood set\n"; + } + + +=cut +sub Getprop_current_mood($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"current_mood","Getprop_current_mood","char"); +} + +=pod + +=item $lj->Getprop_current_mood_id($event) + +Used to get the current mood_id for the journal being written. Will return +the mood_id if one is set, a null string is one is not set and C in +the event of an error. + +Example code: + + my $prop=$lj->Getprop_current_mood_id(\%Event); + (defined $prop) || + die "$0: Failed to get property - $LJ::Simple::error\n"; + if ($prop ne "") { + print STDERR "Journal has mood_id of $prop\n"; + } else { + print STDERR "Journal has no mood_id set\n"; + } + + +=cut +sub Getprop_current_mood_id($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"current_moodid","Getprop_current_mood_id","num"); +} + + +=pod + +=item $lj->Getprop_current_music($event) + +Used to get the current music for the journal entry being written. Returns +the music if one is set, a null string is one is not set and C in +the event of an error. + +Example code: + + my $prop=$lj->Getprop_current_music(\%Event); + (defined $prop) || + die "$0: Failed to get property - $LJ::Simple::error\n"; + if ($prop) { + print STDERR "Journal has the following music: $prop\n"; + } else { + print STDERR "Journal has no music set for it\n"; + } + +=cut +sub Getprop_current_music($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"current_music","Getprop_current_music","char"); +} + +=pod + +=item $lj->Getprop_preformatted($event) + +Used to see if the text for the journal entry being written is preformatted in HTML +or not. This returns true (C<1>) if so, false (C<0>) if not. + +Example code: + + $lj->Getprop_preformatted(\%Event) && + print "Journal entry is preformatted\n"; + +=cut +sub Getprop_preformatted($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"opt_preformatted","Getprop_preformatted","bool"); +} + + +=pod + +=item $lj->Getprop_nocomments($event) + +Used to see if the journal entry being written can be commented on or not. +This returns true (C<1>) if so, false (C<0>) if not. + +Example code: + + $lj->Getprop_nocomments(\%Event) && + print "Journal entry set to disallow comments\n"; + +=cut +sub Getprop_nocomments($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"opt_nocomments","Getprop_nocomments","bool"); +} + + +=pod + +=item $lj->Getprop_picture_keyword($event) + +Used to get the picture keyword for the journal entry being written. Returns +the picture keyword if one is set, a null string is one is not set and C in +the event of an error. + +Example code: + + my $prop=$lj->Getprop_picture_keyword(\%Event); + (defined $prop) || + die "$0: Failed to get property - $LJ::Simple::error\n"; + if ($prop) { + print STDERR "Journal has picture keyword $prop set\n"; + } else { + print STDERR "Journal has no picture keyword set\n"; + } + + +=cut +sub Getprop_picture_keyword($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"picture_keyword","Getprop_picture_keyword","char"); +} + + +=pod + +=item $lj->Getprop_noemail($event) + +Used to see if comments on the journal entry being written should be emailed or +not. This returns true (C<1>) if so comments should B be emailed and false +(C<0>) if they should be emailed. + +Example code: + + $lj->Getprop_noemail(\%Event) && + print "Comments to journal entry not emailed\n"; + +=cut +sub Getprop_noemail($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"opt_noemail","Getprop_noemail","bool"); +} + + +=pod + +=item $lj->Getprop_unknown8bit($event) + +Used see if there is 8-bit data which is not in UTF-8 in the journal entry +being written. This returns true (C<1>) if so, false (C<0>) if not. + +Example code: + + $lj->Getprop_unknown8bit(\%Event) && + print "Journal entry contains 8-bit data not in UTF-8 format\n"; + +=cut +sub Getprop_unknown8bit($$) { + my ($self,$event)=@_; + $LJ::Simple::error=""; + return $self->Getprop_general($event,"unknown8bit","Getprop_unknown8bit","bool"); +} + + + +##### Start of helper functions + +## +## A helper function which takes a key and value pair; +## both are encoded for HTTP transit. +## +sub EncVal($$) { + my ($key,$val)=@_; + $key=~s/ /\+/go; + $key=~s/([^a-z0-9+])/sprintf("%%%x",ord($1))/egsi; + $val=~s/ /\+/go; + $val=~s/([^a-z0-9+])/sprintf("%%%02x",ord($1))/egsi; + return "$key=$val"; +} + +## +## A helper function which takes an encoded value from HTTP +## transit and decodes it +## +sub DecVal($) { + my ($val)=@_; + $val=~s/\+/ /go; + $val=~s/%([0-9A-F]{2})/pack("C", hex($1))/egsi; + return "$val"; +} + +## +## Actually make the LJ request; could be called directly, but isn't +## documented. +## +## The first argument is the the mode to use. The list of currently +## supported modes is: +## o login +## o postevent +## +## The second argument is a hash reference to arguments specific to the +## mode. +## +## The third argument is a reference to a hash which contain the response +## from the LJ server. This can be undef. +## +## Returns 1 on success, 0 on failure. On failure $LJ::Simple::error is +## populated. +## +sub SendRequest($$$$) { + my ($self,$mode,$args,$req_hash)=@_; + my ($oself, $omode, $oargs, $oreq_hash, $oretry) = @_; + $oretry = 0 unless defined($oretry); + + $LJ::Simple::error=""; + my $sub=$LJ::Simple::NonBlock; + my $bytes_in=0; + my $bytes_out=0; + my $timestart=time(); + if ((defined $sub) && (ref($sub) ne "CODE")) { + my $reftype=ref($sub); + $LJ::Simple::error="\$LJ::Simple::NonBlock given a $reftype reference, not CODE"; + return 0; + } + $self->{request}={}; + if ((ref($args) ne "HASH")&&($mode ne "getchallenge")) { + $LJ::Simple::error="INTERNAL: SendRequest() not given hashref for arguments"; + return 0; + } + if ((defined $req_hash) && (ref($req_hash) ne "HASH")) { + $LJ::Simple::error="INTERNAL: SendRequest() not given hashref for responses"; + return 0; + } + $mode=lc($mode); + my @request=( + "mode=$mode", + ); + if ($mode ne "getchallenge") { + push(@request, + EncVal("user",$self->{auth}->{user}), + ); + # Much fun here - see if we use the challenge-response stuff + if ($LJ::Simple::challenge) { + Debug("Trying to use challenge-response system"); + Debug(" Getting new challenge"); + my %chall=(); + $self->SendRequest("getchallenge",undef,\%chall) || return 0; + if ($chall{auth_scheme} ne "c0") { + $LJ::Simple::error="Server returned unsupported auth_scheme \"$chall{auth_scheme}\""; + return 0; + } + Debug(" Got challenge from server:"); + Debug(" challenge: $chall{challenge}"); + Debug(" expire_time: $chall{expire_time}"); + Debug(" server_time: $chall{server_time}"); + + # Work out our own timeout point, basically the livetime of the + # challenge less 10 seconds of fudge factor. + my $chall_livetime=$chall{expire_time} - $chall{server_time} - 10; + my $ctime=time(); + $self->{auth}->{challenge}->{timeout}=$ctime + $chall_livetime; + Debug(" Challenge lifetime is $chall_livetime seconds"); + Debug(" Current: $ctime"); + Debug(" Expire: $self->{auth}->{challenge}->{timeout}"); + + $self->{auth}->{challenge}->{challenge}=$chall{challenge}; + # We assume that the Digest::MD5 module is loaded already; also + # means that we have an MD5 hash of the password to hand. + my $md5=Digest::MD5->new; + $md5->add($chall{challenge}); + $md5->add($self->{auth}->{hash}); + $self->{auth}->{challenge}->{hash}=$md5->hexdigest; + } + if (exists $self->{auth}->{challenge}->{hash}) { + push(@request, + EncVal("auth_method","challenge"), + EncVal("auth_challenge",$self->{auth}->{challenge}->{challenge}), + EncVal("auth_response",$self->{auth}->{challenge}->{hash}), + ); + } else { + if (exists $self->{auth}->{hash}) { + push(@request,EncVal("hpassword",$self->{auth}->{hash})); + } else { + push(@request,EncVal("password",$self->{auth}->{pass})); + } + } + my $ljprotver=0; + if ($LJ::Simple::UTF) { $ljprotver=1; } + push(@request, + "ver=$ljprotver", + ); + } + (defined $sub) && &{$sub}($mode,0.1,"Preparing request data",$bytes_in,$bytes_out,time()-$timestart,0); + if ($mode eq "login") { + push(@request,EncVal("clientversion",$LJ::Simple::LJ_Client)); + if ((exists $args->{moods}) && ($args->{moods} == 1)) { + push(@request,EncVal("getmoods",0)); + } + if ((exists $args->{getpickws}) && ($args->{getpickws} == 1)) { + push(@request,EncVal("getpickws",1)); + push(@request,EncVal("getpickwurls",1)); + } + } elsif ( ($mode eq "postevent") + || ($mode eq "editevent") + || ($mode eq "syncitems") + || ($mode eq "getevents") + || ($mode eq "getfriends") + || ($mode eq "friendof") + || ($mode eq "checkfriends") + || ($mode eq "getdaycounts") + || ($mode eq "getfriendgroups") + || ($mode eq "editfriendgroups") + ) { + if (defined $args) { + my ($k,$v); + while(($k,$v)=each %{$args}) { + if (!defined $k) { + $LJ::Simple::error="CODE: SendRequest() given undefined key value"; + return 0; + } + if (!defined $v) { + $LJ::Simple::error="CODE: SendRequest() given undefined value for \"$k\""; + return 0; + } + push(@request,EncVal($k,$v)); + } + } + } elsif ( ($mode eq "getchallenge") + || ($mode eq "sessiongenerate") + ) { + # NOP - nothing required + } elsif ($mode eq "getrawdata") { + if (! $args->{url}) { + $LJ::Simple::error="CODE: SendRequest() given undefined url value with getrawdata;"; + return 0; + } + if (! $self->{auth}->{ljsession}) { + $LJ::Simple::error="CODE: SendRequest(getrawdata) called without previous sessiongenerate;"; + return 0; + } + } else { + $LJ::Simple::error="INTERNAL: SendRequest() given unsupported mode \"$mode\""; + return 0; + } + my $req=join("&",@request); + my $ContLen=length($req); + + (defined $sub) && &{$sub}($mode,0.2,"Preparing connection to server",$bytes_in,$bytes_out,time()-$timestart,0); + + ## Now we've got the request ready, time to start talking to the web + # Work out where we're talking to and the URI to do it with + my $server=$self->{lj}->{host}; + my $host=$server; + my $port=$self->{lj}->{port}; + + my $uri="/interface/flat"; + $uri = $args->{url} if $mode eq "getrawdata"; + + if (defined $self->{proxy}) { + $uri="http://$server:$port$uri"; + $server=$self->{proxy}->{host}; + $port=$self->{proxy}->{port}; + } + + # Prepare the HTTP request now we've got the URI + my @HTTP = (); + if ($mode eq "getrawdata") { + + my $post_data = "user=" . $self->{auth}->{user} . "&auth_method=cookie"; + + if ($args->{"post-data"}) { + foreach (keys %{$args->{"post-data"}}) { + $post_data .= "&" . $_ . "=" . $args->{"post-data"}->{$_}; + } + } + my $method = "POST"; + if ($args->{"http_method"}) { + $method = $args->{"http_method"}; + } + + @HTTP=( + "$method $uri HTTP/1.0", + "Host: $host", + "Content-type: application/x-www-form-urlencoded", + "User-Agent: " . $LJ::Simple::UserAgent, + "Content-length: " . length($post_data), + "X-LJ-Auth: cookie", + "Cookie: ljsession=" . $self->{auth}->{ljsession}, + ); + + push(@HTTP, + "", + $post_data, + "", + ); + } + else { + @HTTP=( + "POST $uri HTTP/1.0", + "Host: $host", + "Content-type: application/x-www-form-urlencoded", + "User-Agent: " . $LJ::Simple::UserAgent, + "Content-length: $ContLen", + ); + if ($self->{fastserver}) { + push(@HTTP,"Cookie: ljfastserver=1"); + } + push(@HTTP, + "", + $req, + "", + ); + } + + # Prepare the socket + my $tcp_proto=getprotobyname("tcp"); + socket(SOCK,PF_INET,SOCK_STREAM,$tcp_proto); + + # Resolve the server name we're connecting to + (defined $sub) && &{$sub}($mode,0.3,"Starting to resolve $server to IP address",$bytes_in,$bytes_out,time()-$timestart,0); + my $addr=inet_aton($server); + if (!defined $addr) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to resolve server $server"; + return 0; + } + } + my $sin=sockaddr_in($port,$addr); + + my $ip_addr=join(".",unpack("CCCC",$addr)); + + my $proto=$LJ::Simple::ProtoSub; + ($LJ::Simple::protocol) && &{$proto}(undef,undef,$server,$ip_addr); + if ($LJ::Simple::raw_protocol) { + print STDERR "Connecting to $server [$ip_addr]\n"; + print STDERR "Lines starting with \"-->\" is data SENT to the server\n"; + print STDERR "Lines starting with \"<--\" is data RECEIVED from the server\n"; + } + + # Connect to the server + (defined $sub) && &{$sub}($mode,0.4,"Trying to connect to server $server",$bytes_in,$bytes_out,time()-$timestart,0); + if (!connect(SOCK,$sin)) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to connect to $server - $!"; + return 0; + } + } + + ($LJ::Simple::protocol) && &{$proto}(undef,"Connected to $server [$ip_addr]",$server,$ip_addr); + ($LJ::Simple::raw_protocol) && + print STDERR "Connected to $server [$ip_addr]\n"; + + # Send the HTTP request + (defined $sub) && &{$sub}($mode,0.5,"Starting to send HTTP request to $server",$bytes_in,$bytes_out,time()-$timestart,0); + my $cp=0.5; + foreach (@HTTP) { + my $line="$_\r\n"; + my $len=length($line); + my $pos=0; + my $fail=0; + while($pos!=$len) { + my $nbytes=syswrite(SOCK,$line,$len,$pos); + if (!defined $nbytes) { + if ( ($! == EAGAIN) || ($! == EINTR) ) { + $fail++; + if ($fail>4) { + $LJ::Simple::error="Write to socket failed with EAGAIN/EINTR $fail times"; + shutdown(SOCK,2); + close(SOCK); + return 0; + } + next; + } else { + $LJ::Simple::error="Write to socket failed - $!"; + shutdown(SOCK,2); + close(SOCK); + return 0; + } + } + $pos+=$nbytes; + $bytes_out+=$nbytes; + $cp=$cp+0.001; + (defined $sub) && &{$sub}($mode,$cp,"Sending HTTP request to $server",$bytes_in,$bytes_out,time()-$timestart,0); + } + ($LJ::Simple::protocol) && &{$proto}(0,$_,$server,$ip_addr); + ($LJ::Simple::raw_protocol) && print STDERR "--> $_\n"; + } + + # Read the response from the server - use select() + (defined $sub) && &{$sub}($mode,0.6,"Getting HTTP response from $server",$bytes_in,$bytes_out,time()-$timestart,0); + $cp=0.6001; + my ($rin,$rout,$eout)=("","",""); + vec($rin,fileno(SOCK),1) = 1; + my $ein = $rin; + my $response=""; + my $done=0; + while (!$done) { + my $nfound; + if (defined $sub) { + $nfound = select($rout=$rin,undef,$eout=$ein,0); + my $ttaken=time()-$timestart; + if ($nfound!=1) { + if ($ttaken>$LJ::Simple::timeout) { + &{$sub}($mode,1,"Connection with server $server timed out",$bytes_in,$bytes_out,$ttaken,0); + $LJ::Simple::error="Failed to receive data from $server [$ip_addr]"; + shutdown(SOCK,2); + close(SOCK); + + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + return 0; + } + } + &{$sub}($mode,$cp,"Waiting for response from $server",$bytes_in,$bytes_out,time()-$timestart,1); + next; + } + } else { + $nfound = select($rout=$rin,undef,$eout=$ein,$LJ::Simple::timeout); + if ($nfound!=1) { + $LJ::Simple::error="Failed to receive data from $server [$ip_addr]"; + shutdown(SOCK,2); + close(SOCK); + + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + return 0; + } + } + } + my $resp=""; + my $nbytes=sysread(SOCK,$resp,$LJ::Simple::buffer); + + if (!defined $nbytes) { + $LJ::Simple::error="Error in getting data from $server [$ip_addr] - $!"; + shutdown(SOCK,2); + close(SOCK); + (defined $sub) && &{$sub}($mode,1,$LJ::Simple::error,$bytes_in,$bytes_out,time()-$timestart,0); + + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + return 0; + } + } elsif ($nbytes==0) { + $done=1; + } else { + $bytes_in=$bytes_in+$nbytes; + (defined $sub) && &{$sub}($mode,$cp,"Getting response from server $server",$bytes_in,$bytes_out,time()-$timestart,0); + $cp=$cp+0.001; + $response="$response$resp"; + if ($LJ::Simple::raw_protocol) { + print STDERR "<-- "; + foreach (split(//,$resp)) { + s/([\x00-\x20\x7f-\xff])/sprintf("\\%o",ord($1))/ei; + print "$_"; + } + print STDERR "\n"; + } elsif ($LJ::Simple::protocol) { + foreach (split(/[\r\n]{1,2}/o,$resp)) { + &{$proto}(1,$_,$server,$ip_addr); + } + } + } + } + (defined $sub) && &{$sub}($mode,0.7,"Finished getting data from server $server",$bytes_in,$bytes_out,time()-$timestart,0); + + # Shutdown the socket + if (!shutdown(SOCK,2)) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to shutdown socket - $!"; + (defined $sub) && &{$sub}($mode,1,$LJ::Simple::error,$bytes_in,$bytes_out,time()-$timestart,0); + return 0; + } + } + + # Close the socket + close(SOCK); + + (defined $sub) && &{$sub}($mode,0.8,"Parsing data from server $server",$bytes_in,$bytes_out,time()-$timestart,0); + ## We've got the response from the server, so we now parse it + if (!defined $response) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to get result from server"; + return 0; + } + } + + ## Ensure that response isn't zero length + if (length($response) == 0) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Zero length response from server"; + (defined $sub) && &{$sub}($mode,1,"$LJ::Simple::error $server",$bytes_in,$bytes_out,time()-$timestart,0); + return 0; + } + } + + # Split into headers and body + my ($http,$body)=split(/\r\n\r\n/,$response,2); + + if (!defined $http) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to get HTTP headers from server"; + (defined $sub) && &{$sub}($mode,1,"$LJ::Simple::error $server",$bytes_in,$bytes_out,time()-$timestart,0); + return 0; + } + } + + if (!defined $body) { + if ($oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + $LJ::Simple::error="Failed to get HTTP body from server"; + (defined $sub) && &{$sub}($mode,1,"$LJ::Simple::error $server",$bytes_in,$bytes_out,time()-$timestart,0); + return 0; + } + } + + # First lets see if we got a valid response + $self->{request}->{http}={}; + $self->{request}->{http}->{headers}=[(split(/\r\n/,$http))]; + my $srv_resp=$self->{request}->{http}->{headers}->[0]; + $srv_resp=~/^HTTP\/[^\s]+\s([0-9]+)\s+(.*)/; + my ($srv_code,$srv_msg)=($1,$2); + $self->{request}->{http}->{code}=$srv_code; + $self->{request}->{http}->{msg}=$srv_msg; + if ($srv_code != 200) { + $LJ::Simple::error="HTTP request failed with $srv_code $srv_msg"; + return 0; + } + + if ($mode eq "getrawdata") { + return {"content" => $body}; + } + else { + # We did, so lets pull in the LJ stuff for processing + $self->{request}->{lj}={}; + + # The response from LJ takes the form of a key\nvalue\n + # Note that the value can be null tho + $done=0; + while (!$done) { + if ($body=~/^([^\n]+)\n([^\n]*)\n(.*)$/so) { + my ($k,$v)=(undef,undef); + ($k,$v,$body)=(lc($1),DecVal($2),$3); + $v=~s/\r\n/\n/go; + $self->{request}->{lj}->{$k}=$v; + } else { + $done=1; + } + } + + # Got it into a hash - lets see if we made a successful request + if ( (!exists $self->{request}->{lj}->{success}) || + ($self->{request}->{lj}->{success} ne "OK") ) { + + if ($omode ne "login" && $oretry < $LJ::Simple::network_retries) { + $oretry++; + sleep $LJ::Simple::network_sleep; + return $oself->SendRequest($omode, $oargs, $oreq_hash, $oretry); + } + else { + my $errmsg="Server Error, try again later"; + if (exists $self->{request}->{lj}->{errmsg}) { + $errmsg=$self->{request}->{lj}->{errmsg}; + } + $LJ::Simple::error="($mode) LJ request failed: $errmsg"; + (defined $sub) && &{$sub}($mode,1,"$LJ::Simple::error $server",$bytes_in,$bytes_out,time()-$timestart,0); + return 0; + } + } + + # We did! + # Now to populate the hash we were given (if asked to) + if (defined $req_hash) { + %{$req_hash}=(); + my ($k,$v); + while(($k,$v)=each %{$self->{request}->{lj}}) { + $req_hash->{$k}=$v; + } + } + } + + (defined $sub) && &{$sub}($mode,1,"Finished processing request to server $server",$bytes_in,$bytes_out,time()-$timestart,0); + return 1; +} + +sub GenerateCookie() { + my ($self) = @_; + + $self->SendRequest("sessiongenerate", {}, undef) || return undef; + $self->{auth}->{ljsession} = $self->{request}->{lj}->{ljsession}; + + return undef unless $self->{auth}->{ljsession}; + return $self->{auth}->{ljsession}; +} + +sub GetRawData() { + my ($self,$args)=@_; + + return $self->SendRequest("getrawdata", $args, undef) || return undef; +} + +## +## Output debugging info +## +sub Debug(@) { + ($LJ::Simple::debug) || return; + my $msg=join("",@_); + foreach (split(/\n/,$msg)) { + print STDERR "DEBUG> $_\n"; + } +} + + +## +## Dump out a list recursively. Will call dump_hash +## for any hash references in the list. +## +## Generally used for debugging +## +sub dump_list($$) { + my ($lr,$sp)=@_; + my $le=""; + my $res=""; + foreach $le (@{$lr}) { + if (ref($le) eq "HASH") { + $res="$res$sp\{\n"; + $res=$res . dump_hash($le,"$sp "); + $res="$res$sp},\n"; + } elsif (ref($le) eq "ARRAY") { + $res="$res$sp\[\n" . dump_list($le,"$sp ") . "$sp],\n"; + } else { + my $lv=$le; + if (defined $lv) { + $lv=~s/\n/\\n/go; + $lv=quotemeta($lv); + $lv=~s/\\-/-/go; + $lv="\"$lv\""; + } else { + $lv="undef"; + } + $res="$res$sp$lv,\n"; + } + } + return $res; +} + +## +## Dump out a hash recursively. Will call dump_list +## for any list references in the hash values. +## +## Generally used for debugging +## +sub dump_hash($$) { + my ($hr,$sp)=@_; + my ($k,$v)=(); + my $res=""; + while(($k,$v)=each %{$hr}) { + $k=quotemeta($k); + $k=~s/\\-/-/go; + if (ref($v) eq "HASH") { + $res="$res$sp\"$k\"\t=> {\n"; + $res=$res . dump_hash($v,"$sp "); + $res="$res$sp},\n"; + } elsif (ref($v) eq "ARRAY") { + $res="$res$sp\"$k\"\t=> \[\n" . dump_list($v,"$sp ") . "$sp],\n"; + } else { + if (defined $v) { + $v=~s/\n/\\n/go; + $v=quotemeta($v); + $v=~s/\\\\n/\\n/go; + $v=~s/\\-/-/go; + $v="\"$v\""; + } else { + $v="undef"; + } + my $out="$sp\"$k\"\t=> $v,"; + $res="$res$out\n"; + } + } + return $res; +} + +1; +__END__ + +=pod + +=back + +=head1 AUTHOR + +Simon Burr Esimes@bpfh.netE + +=head1 SEE ALSO + +perl +L + +=head1 LICENSE + +Copyright (c) 2002, Simon Burr EFE +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=cut diff --git a/local/bin/ljrimport/icomments.pl b/local/bin/ljrimport/icomments.pl new file mode 100755 index 0000000..252a41d --- /dev/null +++ b/local/bin/ljrimport/icomments.pl @@ -0,0 +1,647 @@ +#!/usr/bin/perl -w + +use strict; +use Simple; # corrected LJ::Simple +use XML::Parser; +use POSIX; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "ljr-defaults.pl"; +require "ljr-links.pl"; +require LJR::Distributed; +require LJR::unicode; +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl"; +require "ipics.pl"; + +my $err = sub { + my %res = (); + + $res{"err"} = 1; + $res{"errtext"} = join ("\n", @_); + return \%res; +}; +my $xmlerrt; +my $xmlerr = sub { + my $expat = shift; + + my $cstack = "\ncallstack:"; + my $i = 0; + while ( 1 ) { + my $tfunc = (caller($i))[3]; + if ($tfunc && $tfunc ne "") { + if ($tfunc !~ /\_\_ANON\_\_/) { + $cstack .= " " . $tfunc; + } + $i = $i + 1; + } + else { + last; + } + } + + $xmlerrt = join("\n", @_); + $xmlerrt .= $cstack; + $expat->finish(); +}; + +my $dumpxml = sub { + my ($xdata, $username) = @_; + + my $t = `date +"%T"`; + $t = substr($t, 0, length($t) - 1); + open(my $outfile, ">$ENV{'LJHOME'}/logs/err_" . $username . "_" . $t . ".xml"); + print $outfile "$xdata"; + close($outfile); +}; + +# kind of global variables +my $DEBUG=1; + +my $got_max_commentid; +my $empty_num = 0; + +my $ru; # current remote user (the one being cached and imported) +my $cmode; +my $xml_maxid = 0; +my $soft_cached_default_pics; +my $soft_cached_keyworded_pics; +my $posters_without_names; # lj bug workaround: http://rt.livejournal.org/Ticket/Display.html?id=762 + +sub cstatus_print { + my $statustr = join("", @_); + + eval { LJR::Import::import_log($statustr); }; + + if ($@) { + print $@ . "\n"; + } + + if ($DEBUG) { + eval { LJR::Import::log_print($statustr); }; + + if ($@) { + print $statustr . "\n"; + } + } +} + + +# comment processing +my $skip_tags = qr/^(livejournal|comments|usermaps|nextid)$/; +my $maxid = qr/^(maxid)$/; +my $comment_tag = qr/^(comment)$/; +my $usermap_tag = qr/^(usermap)$/; +my $data_tags = qr/^(subject|body|date)$/; +my $prop_tag = qr/^(property)$/; + +LJ::load_props("talk"); +return $err->("Can't load talkprops.") unless $LJ::CACHE_PROP{talk}; +my @tprops; +foreach my $k (keys %{$LJ::CACHE_PROP{talk}}) { + push(@tprops, $k); +} +my $tprops = join("|", @tprops); +my $known_props = qr/^($tprops)$/; + +my %comment = (); # current comment structure +my $cid = ""; # current tag (inside comment tag) +my $ctext = ""; # current value of $cid + + +# export_comments.bml xml handling routines +sub xmlh_comment_start() { + my $expat = shift; + my @params = @_; + + if ($params[0] =~ /$skip_tags/) { + # skip valid but meaningless tags + } + elsif ($cmode eq "comment_meta" && $params[0] =~ /$usermap_tag/) { + shift @params; # skip "usermap" + + my %usermap = (); + %usermap = @params; + + if ($usermap{id} && $usermap{user}) { + my $r = { + serverid => $ru->{serverid}, + userid => $usermap{id}, + username => $usermap{user}, + }; + + $r = LJR::Distributed::get_cached_user($r); + return $xmlerr->($expat, $r->{errtext}) if $r->{err}; + + $r = LJR::Distributed::get_imported_user($r); + return $xmlerr->($expat, $r->{errtext}) if $r->{err}; + + $r = LJR::Distributed::set_cu_field($r, "local_commenterid", $r->{commenterid}); + return $xmlerr->($expat, $r->{errtext}) if $r->{err}; + + if (!$soft_cached_default_pics->{$usermap{id}}) { + my $iu = LJ::load_userid ($r->{local_commenterid}); +# cstatus_print( +# "caching default userpic for " . $r->{username} . +# " (" . $r->{local_commenterid} . ":" . $iu->{user} . ")" +# ); + + my $e = import_pics( + $ru->{servername}, + $usermap{user}, + "", + $iu->{user}, + "", 1); + return $xmlerr->($expat, "importing default userpic for [" . $usermap{user} . "]:", $e->{errtext}) + if $e->{err}; + + $soft_cached_default_pics->{$usermap{id}} = 1; + } + } + elsif ($usermap{id} && !$usermap{user}) { + $posters_without_names->{$usermap{id}} = 1; + } + else { + return $xmlerr->($expat, + "Unknown XML-structure: " . join (" ", @params), + "at line " . $expat->current_line); + } + } + elsif ($params[0] =~ /$comment_tag/) { + # we're starting to process new comment + shift @params; + + %comment = (); + %comment = @params; # grab all comment attributes + } + elsif ($cmode eq "comment_body" && $params[0] =~ /$data_tags/) { + $cid = $params[0]; + $ctext = ""; + } + elsif ($cmode eq "comment_body" && $params[0] =~ /$prop_tag/) { + shift @params; # skip "property" + + # skip "name" attribute name + if (shift @params && $params[0] =~ /$known_props/) { + $cid = $params[0]; + $ctext = ""; + } + } + elsif ($params[0] =~ /$maxid/) { + $ctext = ""; + } + else { + return $xmlerr->($expat, + "Unknown XML-structure: " . join (" ", @params), + "at line " . $expat->current_line); + } +} +sub xmlh_comment_end() { + my $expat = shift; + my @params = @_; + + if ($params[0] =~ /$skip_tags/) { + # almost finished + } + elsif ($cmode eq "comment_meta" && $params[0] =~ /$usermap_tag/) { + # nop + } + elsif ($params[0] =~ /$comment_tag/) { + if ($cmode eq "comment_body") { + +# print $comment{"id"} . "\n"; +# print "COMMENT\n"; +# while ((my $k, my $v) = each(%comment)) { +# print $k . ":" . $v . "\n"; +# } +# print "/COMMENT\n"; + + $comment{ru_id} = $ru->{ru_id}; + + if ( + $comment{props} && + $comment{props}->{"picture_keyword"} && + $comment{posterid} && + !$soft_cached_keyworded_pics->{$comment{posterid}}->{$comment{props}->{"picture_keyword"}} + ) { + + my $r = { + serverid => $ru->{serverid}, + userid => $comment{posterid}, + }; + + $r = LJR::Distributed::get_cached_user($r); + return $xmlerr->($expat, $r->{errtext}) if $r->{err}; + + $r = LJR::Distributed::get_imported_user($r); + return $xmlerr->($expat, $r->{errtext} . "(userid: " . $comment{'posterid'} . ")") if $r->{err}; + + $r = LJR::Distributed::get_cu_field($r, "local_commenterid"); + return $xmlerr->($expat, $r->{errtext}) if $r->{err}; + + my $iu = LJ::load_userid ($r->{local_commenterid}); + #cstatus_print ("caching userpic " . $comment{props}->{"picture_keyword"} . " for " . $r->{username} . ":" . $iu->{user}); + + my $e = import_pics ( + $ru->{servername}, + $r->{username}, + "", + $iu->{user}, + $comment{props}->{"picture_keyword"}, + 0); + return $xmlerr->($expat, $e->{errtext}) if $e->{err}; + + $soft_cached_keyworded_pics->{$comment{posterid}}->{$comment{props}->{"picture_keyword"}} = 1; + } + + LJR::Links::make_ljr_hrefs( + LJR::Links::get_server_url($ru->{"servername"}, "base"), + $ru->{"servername"}, \$comment{body} + ); + + if ($comment{'posterid'} && $posters_without_names->{$comment{'posterid'}}) { + $comment{'posterid'} = undef; + } + if (!$comment{'body'} && $comment{'state'} ne "D") { + $comment{'body'} = "LJR::Import warning: no comment body during import."; + } + + my $c = LJR::Distributed::cache_comment (\%comment); + return $xmlerr->($expat, $c->{'errtext'}) if $c->{'err'}; + + if (!$ru->{cached_comments_maxid} || + $comment{id} > $ru->{cached_comments_maxid}) { + $ru->{cached_comments_maxid} = $comment{id}; + } + } + + $got_max_commentid++; + $empty_num = 0; + } + elsif ($params[0] =~ /$data_tags/) { + $comment{$cid} = $ctext; + } + elsif ($params[0] =~ /$prop_tag/) { + $comment{props}->{$cid} = $ctext; + } + elsif ($params[0] =~ /$maxid/) { + $xml_maxid = $ctext; + + if ($cmode eq "comment_body" && $xml_maxid > $ru->{remote_meta_maxid}) { + my $tmid = $got_max_commentid; + my $txid = $xml_maxid; + my $tempty = $empty_num; + + $got_max_commentid = $ru->{remote_meta_maxid}; + my $e = get_usermaps_cycled( + $ru->{servername}, + $ru->{username}, + $ru->{pass}, + $got_max_commentid + 1); + return $xmlerr->($expat, $e->{errtext}) if $e->{err}; + + # restore comment_body xml-parsing mode + $xml_maxid = $txid; + $got_max_commentid = $tmid; + $empty_num = $tempty; + $cmode = "comment_body"; + } + } + else { + return $xmlerr->($expat, + "Unknown tag: " . join (" ", @params), + "at line " . $expat->current_line + ); + } +} +sub xmlh_comment_char() { + my $expat = shift; + my $tt = join("", @_); + $ctext = $ctext . $tt; +} + +sub get_usermaps_cycled { + my ($server, $username, $pass, $startid) = @_; + + my $comments_map = {}; + my $do_login = 1; + + $LJ::Simple::network_retries = $LJR::NETWORK_RETRIES; + $LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP; + $LJ::Simple::LJ_Client = $LJR::LJ_CLIENT; + $LJ::Simple::UserAgent = $LJR::USER_AGENT; + + my $i = 0; + my $remote_lj; + + while (1) { + if ($do_login) { + $remote_lj = new LJ::Simple ({ + site => $server, + user => $username, + pass => $pass, + pics => 0, + moods => 0, + }); + return $err->("Can't login to remote site.", $LJ::Simple::error) unless defined $remote_lj; + + if (!$remote_lj->GenerateCookie()) { + if (!$remote_lj->GenerateCookie()) { + return $err->("Can't generate login cookie.", $LJ::Simple::error); + } + } + + $do_login = 0; + } + + # do not process those which were processed once + if ($comments_map->{$startid}) { + $startid++; + next; + } + + my $res = $remote_lj->GetRawData( + {"url" => "/export_comments.bml?get=comment_meta&startid=" . $startid} + ); + + if ($res && $res->{content}) { + $cmode = "comment_meta"; + + my $xdata = $res->{content}; + LJR::unicode::force_utf8(\$xdata); + eval { LJ::text_out(\$xdata); }; + + my $p1 = new XML::Parser ( + Handlers => { + Start => \&xmlh_comment_start, + End => \&xmlh_comment_end, + Char => \&xmlh_comment_char + }); + + $xml_maxid = 0; + $xmlerrt = ""; + + eval { $p1->parse($xdata); }; + if ($@) { + if ($i < $LJR::NETWORK_RETRIES) { + if ($xdata =~ /Login Required/) { + $do_login = 1; + } + + $i++; + LJR::NETWORK_SLEEP; + next; + } + else { + $dumpxml->($xdata, $username); + return $err->("Runtime error parsing XML (meta, $startid): ", $@); + } + } + if ($xmlerrt) { + $dumpxml->($xdata, $username); + return $err->("Error parsing XML (meta, $startid): ", $xmlerrt); + } + + # xml was processed successfully + $comments_map->{$startid} = 1; + + cstatus_print ("prefetched $got_max_commentid (skipped $empty_num) of $xml_maxid comments"); + if ($got_max_commentid + $empty_num < $xml_maxid) { + $empty_num++; + $startid = $got_max_commentid + $empty_num; + next; + } + else { + $got_max_commentid = 0 unless $got_max_commentid; + $ru = LJR::Distributed::set_cu_field($ru, "remote_meta_maxid", $got_max_commentid); + return $err->($ru->{errtext}) if $ru->{err}; + return undef; + } + } + else { + if ($i < $LJR::NETWORK_RETRIES) { + LJR::NETWORK_SLEEP; $i++; next; + } + else { + return $err->("can't get comments metadata: " . $LJ::Simple::error); + } + } + } +} + +sub get_usermaps { + my ($server, $username, $pass, $startid) = @_; + + $ru = LJR::Distributed::get_remote_server($server); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + $ru->{username} = $username; + $ru->{pass} = $pass; + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $got_max_commentid = $startid - 1; + + cstatus_print ("caching commented users."); + + my $e = get_usermaps_cycled($server, $username, $pass, $startid); + return $err->($e->{errtext}) if $e->{err}; +} + +sub get_comments_cycled { + my ($server, $username, $pass, $startid) = @_; + + my $comments_map = {}; + my $do_login = 1; + + $ru = LJR::Distributed::get_remote_server($server) unless $ru->{serverid}; + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{username} = $username; + + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $LJ::Simple::network_retries = $LJR::NETWORK_RETRIES; + $LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP; + $LJ::Simple::LJ_Client = $LJR::LJ_CLIENT; + $LJ::Simple::UserAgent = $LJR::USER_AGENT; + + my $i = 0; + my $h_counter; + my $remote_lj; + + while (1) { + if ($do_login) { + $remote_lj = new LJ::Simple ({ + site => $server, + user => $username, + pass => $pass, + pics => 0, + moods => 0, + }); + return $err->("Can't login to remote site.", $LJ::Simple::error) unless defined $remote_lj; + + if (!$remote_lj->GenerateCookie()) { + if (!$remote_lj->GenerateCookie()) { + return $err->("Can't generate login cookie.", $LJ::Simple::error); + } + } + + $do_login = 0; + } + + # do not process those which were processed once + if ($comments_map->{$startid}) { + $startid++; + next; + } + + my $res = $remote_lj->GetRawData( + {"url" => "/export_comments.bml?get=comment_body&props=1&startid=" . $startid} + ); + + if ($res && $res->{content}) { + my $xdata = $res->{content}; + LJR::unicode::force_utf8(\$xdata); + eval { LJ::text_out(\$xdata); }; + + $cmode = "comment_body"; + my $p1 = new XML::Parser ( + Handlers => { + Start => \&xmlh_comment_start, + End => \&xmlh_comment_end, + Char => \&xmlh_comment_char + }); + + $xmlerrt = ""; + eval { $p1->parse($xdata); }; + if ($@) { + if ($i < $LJR::NETWORK_RETRIES) { + if ($xdata =~ /Login Required/) { + $do_login = 1; + } + + $i++; + LJR::NETWORK_SLEEP; + next; + } + else { + $dumpxml->($xdata, $username); + return $err->("Runtime error parsing XML (body, $startid): ", $@); + } + } + if ($xmlerrt) { + $dumpxml->($xdata, $username); + return $err->("Error parsing XML (body, $startid): ", $xmlerrt); + } + + # remember last cached comment number (which is equal to its id) + $ru = LJR::Distributed::set_cu_field( + $ru, "cached_comments_maxid", + $ru->{cached_comments_maxid}); + return $err->($ru->{errtext}) if $ru->{err}; + + # xml was processed successfully + $comments_map->{$startid} = 1; + + cstatus_print ("getting comments. last id: $ru->{cached_comments_maxid}, skipping: $empty_num, just walked: $startid, max: $ru->{remote_meta_maxid}"); + if ($ru->{cached_comments_maxid} + $empty_num < $ru->{remote_meta_maxid}) { + if ($empty_num > 0) { + $empty_num = + (POSIX::floor($ru->{cached_comments_maxid} / 100) + 1) * 100 - + $ru->{cached_comments_maxid} + + $h_counter * 100; + + $h_counter++; + } + else { + $empty_num++; + $h_counter = 0; + } + + $startid = $ru->{cached_comments_maxid} + $empty_num; + next; + } + else { + return undef; + } + } + else { + if ($i < $LJR::NETWORK_RETRIES) { + LJR::NETWORK_SLEEP; $i++; next; + } + else { + return $err->("can't get comments: " . $LJ::Simple::error); + } + } + } +} + +sub get_comments { + my ($server, $username, $pass, $startid) = @_; + + cstatus_print ("caching comments"); + + LJ::disconnect_dbs(); + + $soft_cached_keyworded_pics = {}; + $soft_cached_default_pics = {}; + $posters_without_names = {}; + + $ru = LJR::Distributed::get_remote_server($server); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + $ru->{username} = $username; + $ru->{pass} = $pass; + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + my $e; # for possible errors + + $ru = LJR::Distributed::get_cu_field($ru, "cached_comments_maxid"); + $ru->{cached_comments_maxid} = 0 if not defined $ru->{cached_comments_maxid}; + + # don't want to download cached comments again + $startid = $ru->{cached_comments_maxid} + 1 + if $ru->{cached_comments_maxid} > $startid; + + $ru = LJR::Distributed::get_cu_field($ru, "remote_meta_maxid"); + $ru->{remote_meta_maxid} = 0 if not defined $ru->{remote_meta_maxid}; + + # try to minimize possible further delays + $got_max_commentid = $ru->{remote_meta_maxid}; + $e = get_usermaps_cycled($server, $username, $pass, $got_max_commentid + 1); + return $err->($e->{errtext}) if $e->{err}; + + # get remote comments and cache them + $got_max_commentid = $startid - 1; + $e = get_comments_cycled($server, $username, $pass, $startid); + return $err->($e->{errtext}) if $e->{err}; + + $soft_cached_keyworded_pics = {}; + $soft_cached_default_pics = {}; + $posters_without_names = {}; + + return undef; +} + +sub create_imported_comments { + my ($remote_site, $remote_user, $local_user) = @_; + + LJ::disconnect_dbs(); + + my $ru = LJR::Distributed::get_remote_server($remote_site); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{username} = $remote_user; + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + cstatus_print("creating comments."); + + $ru = LJR::Distributed::create_imported_comments($ru, $local_user); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + return undef; +} + + +return 1; diff --git a/local/bin/ljrimport/ijournal.pl b/local/bin/ljrimport/ijournal.pl new file mode 100755 index 0000000..2f12429 --- /dev/null +++ b/local/bin/ljrimport/ijournal.pl @@ -0,0 +1,839 @@ +#!/usr/bin/perl -w + +use strict; +use Simple; # corrected LJ::Simple +use POSIX; +use XML::Parser; +use Unicode::String; +use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset); + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "ljr-defaults.pl"; +require "ljr-links.pl"; +require LJR::Distributed; +require LJR::unicode; +require LWPx::ParanoidAgent; +require "ipics.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl"; + +my $DEBUG=1; + +# shared variables (between flat and xml mode) +my $ru; # remote user +my %rfg=(); # remote friend groups +my ($ritem_id, $ranum, $rhtml_id); # remote entry ids +my $local_u; # local user being imported into +my $flags; # ljprotocol.pl flags +my $do_overwrite; # overwrite entries + +my $warns; + +# flat mode parameters +my $REMOTE_MAX_GET = 50; # livejournal.com lets us download no more than 50 events for a given day + +# XML mode functions and variables +my $xmlerrt; +my $xmlerr = sub { + my $expat = shift; + + my $cstack = "\ncallstack:"; + my $i = 0; + while ( 1 ) { + my $tfunc = (caller($i))[3]; + if ($tfunc && $tfunc ne "") { + if ($tfunc !~ /\_\_ANON\_\_/) { + $cstack .= " " . $tfunc; + } + $i = $i + 1; + } + else { + last; + } + } + + $xmlerrt = join("\n", @_); + $xmlerrt .= $cstack; + $expat->finish(); +}; + +my $dumptofile = sub { + my ($fdata, $filename, $ext) = @_; + + my $t = `date +"%T"`; + $t = substr($t, 0, length($t) - 1); + open(my $outfile, ">$ENV{'LJHOME'}/logs/" . $filename . "_" . $t . $ext); + print $outfile "$fdata"; + close($outfile); +}; + +my %xentry = (); # current entry +my $ctext = ""; # current field value + +my $root_tags = qr/^(livejournal)$/; +my $entry_tag = qr/^(entry)$/; +my $entry_data_tag = qr/^(itemid|eventtime|logtime|subject|event|security|allowmask|current_music|current_mood)$/; + + +# error handling +my $err = sub { + my %res = (); + + $res{"err"} = 1; + $res{"errtext"} = join ("\n", @_); + + if ($warns) { + $res{"warns"} = $warns; + } + + return \%res; +}; + +my $warn = sub { + print "WARNING: " . join ("\n", @_); + print "\n"; + + if (!$warns || length($warns) < 255) { + $warns .= $warns . join(" ", @_); + if (substr($warns, 0, 244) ne $warns) { + $warns = substr($warns, 0, 244) + "; and more"; + } + } +}; + +sub jstatus_print { + my $statustr = join("", @_); + + if ($DEBUG) { + eval { LJR::Import::import_log($statustr); }; + + if ($@) { + print $@ . "\n"; + print $statustr . "\n"; + } + } +} + +# overwrite entry +sub check_overwrite { + my ($local_u, $ru_id, $ritem_id, $overwrite) = @_; + + my $r = LJR::Distributed::get_local_itemid ($local_u, $ru_id, $ritem_id. "I"); + return $err->($r->{"errtext"}) if $r->{"err"}; + + if ($r->{"itemid"} && $overwrite eq "1") { + my %req = ( + 'username' => $local_u->{'user'}, + 'ownerid' => $local_u->{'user'}, + 'clientversion' => $LJR::LJ_CLIENT, + 'ver' => $LJ::PROTOCOL_VER, + 'selecttype' => 'one', + 'itemid' => $r->{"itemid"}, + 'getmenus' => 0, + 'lineendings' => "unix", + 'truncate' => 0, + ); + + my $err1; + my $items = LJ::Protocol::do_request("getevents", \%req, \$err1, $flags); + if ($err1) { + my $errstr = LJ::Protocol::error_message($err1); + return $err->($errstr); + } + + my $h = @{$items->{events}}[0]; + LJ::delete_entry($local_u, $h->{itemid}); + + $r = LJR::Distributed::get_local_itemid ($local_u, $ru_id, $ritem_id, "I"); + return $err->($r->{"errtext"}) if $r->{"err"}; + } + elsif ($r->{"itemid"} && $overwrite eq "0") { + return {"continue" => 0}; + } + + return {"continue" => 1}; +} + +# XML handlers +sub xmlh_entry_start() { + my $expat = shift; + my @params = @_; + + if ($params[0] =~ /$root_tags/) { + # skip valid but meaningless tags + } + elsif ($params[0] =~ /$entry_tag/) { + # we're starting to process new entry + shift @params; + + %xentry = (); + } + elsif ($params[0] =~ /$entry_data_tag/) { + $ctext = ""; + } + else { + return $xmlerr->($expat, + "Unknown XML-structure: " . join (" ", @params), + "at line " . $expat->current_line); + } +} +sub xmlh_entry_end() { + my $expat = shift; + my @params = @_; + + if ($params[0] =~ /$root_tags/) { + # almost finished + } + elsif ($params[0] =~ /$entry_tag/) { + my $xe = xml_create_entry(\%xentry); + return $xmlerr->($expat, "xml_create_entry: " . $xe->{errtext}) if $xe && $xe->{err}; + } + elsif ($params[0] =~ /$entry_data_tag/) { + $xentry{$params[0]} = $ctext; +# print $params[0] . " => " . $ctext . "\n"; + } + else { + return $xmlerr->($expat, + "Unknown tag: " . join (" ", @params), + "at line " . $expat->current_line + ); + } +} +sub xmlh_entry_char() { + my $expat = shift; + my $tt = join("", @_); + $ctext = $ctext . $tt; +} + +# should be called after populating shared variables (see section above) +sub xml_create_entry { + my ($xentry) = @_; + + return $err->("XML import: can't extract remote itemid.") unless $xentry->{"itemid"}; + $ritem_id = int($xentry->{"itemid"} / 256); # export.bml returns html_id instead of item_id + + my $is_gated = LJR::Distributed::get_local_itemid($local_u, $ru->{'ru_id'}, $ritem_id, "E"); + return $err->($is_gated->{"errtext"}) if $is_gated->{"err"}; + return {"err" => 0} if $is_gated->{'itemid'}; + + my $r = check_overwrite($local_u, $ru->{'ru_id'}, $ritem_id, $do_overwrite); + return $err->($r->{"errtext"}) if $r->{"err"}; + return unless $r->{"continue"}; + + my ($min,$hour,$mday,$mon,$year); + + if ($xentry->{"eventtime"} =~ /(\d\d\d\d)\-(\d\d)\-(\d\d)\ (\d\d)\:(\d\d)/o) { + $year = $1; + $mon = $2; + $mday = $3; + $hour = $4; + $min = $5; + } + else { + return $err->("XML import: can't extract eventtime. remote itemid = " . $ritem_id); + } + + my $moodid; + if ($xentry->{"current_mood"}) { + $moodid = LJ::mood_id($xentry->{"current_mood"}); + } + + LJR::Links::make_ljr_hrefs( + LJR::Links::get_server_url($ru->{"servername"}, "base"), + $ru->{"servername"}, \$xentry->{"event"} + ); + +# LJR::unicode::utf8ize(\$xentry->{"event"}); +# LJR::unicode::utf8ize(\$xentry->{"subject"}); +# LJR::unicode::utf8ize(\$xentry->{"current_mood"}); +# LJR::unicode::utf8ize(\$xentry->{"current_music"}); + + # LJ now exports lj-polls (previously + # they exported only links to polls) + $xentry->{'event'} =~ s/.+<\/lj-poll>//sog; + + my %req = ( + 'mode' => 'postevent', + 'ljr-import' => 1, + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $LJR::LJ_CLIENT, + 'user' => $local_u->{'user'}, + 'username' => $local_u->{'user'}, + 'usejournal' => $local_u->{'user'}, + 'getmenus' => 0, + 'lineendings' => "unix", + 'event' => $xentry->{"event"}, + 'subject' => $xentry->{"subject"}, + 'year' => $year, + 'mon' => $mon, + 'day' => $mday, + 'hour' => $hour, + 'min' => $min, + 'props' => { + 'current_moodid' => $moodid, + 'current_mood' => $xentry->{"current_mood"}, + 'current_music' => $xentry->{"current_music"}, + 'opt_preformatted' => 0, + 'opt_nocomments' => 0, + 'taglist' => "", + 'picture_keyword' => "", + 'opt_noemail' => 0, + 'unknown8bit' => 0, + 'opt_backdated' => 1, + }, + ); + + if ($xentry->{"security"} eq "public" || $xentry->{"security"} eq "private") { + $req{'security'} = $xentry->{"security"}; + $req{'allowmask'} = 0; + } + elsif ($xentry->{"security"} eq "usemask" && $xentry->{"allowmask"} == 1) { + $req{'security'} = 'usemask'; + $req{'allowmask'} = 1; + } + else { + $req{'security'} = 'usemask'; + + my @groups = (); + foreach my $grp_id (keys %rfg) { + if ($xentry->{"allowmask"}+0 & 1 << $grp_id) { + push @groups, $rfg{$grp_id}->{name}; + } + } + + my $mask = 0; + while (my $grpname = shift @groups) { + my $group = LJ::get_friend_group($local_u, {'name' => $grpname}); + if ($group) { + $mask = $mask | (1 << $group->{groupnum}); + } + } + $req{'allowmask'} = $mask; + } + + my %res = (); + LJ::do_request(\%req, \%res, $flags); + if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Missing required argument") { + $warn->($res{"errmsg"} . " while processing " . $xentry->{"eventtime"}); + return; + } + if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Post too large") { + $dumptofile->($req{'event'}, "large_" . $local_u->{'user'}, ".raw"); + } + + return $err->($xentry->{"eventtime"} . ": " . $res{"errmsg"}) unless $res{"success"} eq "OK"; + + $r = LJR::Distributed::store_remote_itemid( + $local_u, + $res{"itemid"}, + $ru->{ru_id}, + $ritem_id, + $xentry->{"itemid"}); + return $err->($xentry->{"eventtime"} . ": " . $r->{"errtext"}) if $r->{"err"}; + + return {"err" => 0}; +} + +# do the actual import +sub import_journal { + my ( + $throttle_speed, + $remote_site, $remote_protocol, $remote_user, $remote_pass, $remote_shared_journal, + $local_user, $local_shared_journal, $overwrite + ) = @_; + + $do_overwrite = $overwrite; + LJ::disconnect_dbs(); # force reconnection to the database + + if ($remote_shared_journal eq "") { + $remote_shared_journal = undef; + } + if ($local_shared_journal eq "") { + $local_shared_journal = undef; + } + + my %gdc_hr = (); + my %req = (); + my %lfg = (); + my %res = (); + + if ($remote_protocol ne "flat" && $remote_protocol ne "xml") { + return $err->("Unsupported remote protocol $remote_protocol."); + } + + $LJ::Simple::network_retries = $LJR::NETWORK_RETRIES; + $LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP; + $LJ::Simple::LJ_Client = $LJR::LJ_CLIENT; + $LJ::Simple::UserAgent = $LJR::USER_AGENT; + + # login to the remote site + my $remote_lj = new LJ::Simple ({ + site => $remote_site, + user => $remote_user, + pass => $remote_pass, + pics => 0, + moods => 0, + }); + if (! defined $remote_lj) { + return $err->("Can't login to remote site.", $LJ::Simple::error); + } + + if (!$remote_lj->GenerateCookie()) { + if (!$remote_lj->GenerateCookie()) { + return $err->("Can't generate login cookie.", $LJ::Simple::error); + } + } + + # since we're able to login with supplied credentials -- + # get and/or cache remote server and remote user ident + $ru = LJR::Distributed::get_remote_server($remote_site); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + # try to get userid + my $idres; + my $i1 = 0; + while(1) { + my $ua = LWPx::ParanoidAgent->new(timeout => 60); + $ua->agent($LJR::USER_AGENT); + # TODO: parameterize allpics.bml + my $url = $ru->{"servername"} . "/users/" . $remote_user . "/info/" ; + $idres = $ua->get($url); + + if (!($idres && ($idres->is_success || $idres->code == 403)) && $i1 < $LJR::NETWORK_RETRIES) { + my $txt; + #foreach my $k (keys %$idres) { + # $txt .= $k . "->(" . $idres->{$k} ."), "; + #} +###_content->(500 DNS lookup timeout), _rc->(500), _headers->(HTTP::Headers=HASH(0x2d2ec70)), _msg->(DNS lookup timeout), _request->(HTTP::Request=HASH(0x2c61ac0)), + + $txt .= "_msg->" . $idres->{'_msg'} . ", "; + foreach my $k (keys %{$idres->{'_headers'}}) { + $txt .= "\n" . $k . ": " . $idres->{'_headers'}->{$k} ; + } + print STDERR "*** $url $txt\n"; + + LJR::NETWORK_SLEEP(); $i1++; next; + } + else { last; } + } + + if (!($idres && ($idres->is_success || $idres->code == 403))) { + return $err->("LWPx: Can't get remote user id: $remote_user\n"); + } + if ($idres->content && $idres->content =~ /\$remote_user\<\/b\>\<\/a\>\ \((\d+)\)/s) { + $ru->{"userid"} = $1; + } + + $ru->{"username"} = $remote_user; + $ru = LJR::Distributed::get_cached_user($ru); # populates $ru->{ru_id} + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + # get local user object for user being imported into + $local_u = LJ::load_user($local_user, 1); + return $err->("Can't load local user $local_user.") unless $local_u; + + $ru = LJR::Distributed::remote_local_assoc($ru, $local_u); + return $err->("error while getting remote-local association: " . $ru->{errtext}) + if $ru->{err}; + + jstatus_print ("getting userpics"); + my $e = import_pics( + $ru->{servername}, + $ru->{username}, + $remote_pass, + $local_user, + "", 0); + return $err->("Can't import " . $ru->{username} . ": " . $e->{errtext}) + if $e->{err}; + + # clear duplicate protection + LJ::set_userprop($local_u, "dupsig_post", undef); + + # needed everywhere + $flags = { + 'u' => $local_u, + 'noauth' => 1, + 'BMAX_EVENT' => 150000, + 'CMAX_EVENT' => 150000, + 'no-cache' => 1, + 'omit_underscore_check' => 1, + }; + + %req = ( 'mode' => 'login', + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $LJR::LJ_CLIENT, + 'user' => $local_u->{'user'}, + 'getmenus' => 0, + ); + %res = (); + LJ::do_request(\%req, \%res, $flags); + return $err->($res{'errmsg'}) unless $res{'success'} eq 'OK'; + + jstatus_print ("getting friend groups"); + + # get remote and local friend groups, mix them up, update on local server + if (! defined $remote_lj->GetFriendGroups(\%rfg)) { + return $err->("Failed to get groups on the remote site.", $LJ::Simple::error); + } + + LJ::Protocol::do_request( + { + 'mode' => 'getfriendgroups', + 'user' => $local_u->{'user'}, + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $LJR::LJ_CLIENT, + 'includegroups' => 1, + 'getmenus' => 0, + }, + \%res, + $flags + ); + if (! $res{'success'} eq "OK") { + return $err->("Unable to get local user" . $local_u->{'user'} . "groups", + $res{'success'} . ":" . $res{'errmsg'}); + } + + # convert it to LJ::Simple hash + while((my $k, my $v) = each %res) { + $k=~/^frgrp_([0-9]+)_(.*)$/o || next; + my ($id, $name) = ($1, $2); + if (!exists $lfg{$id}) { + $lfg{$id}={ + id => $id, + public => 0, + }; + } + ($name eq "sortorder") && ($name="sort"); + $lfg{$id}->{$name}=$v; + } + + # add nonexisting remote groups (identified by name) to local server + foreach my $grp_id (keys %rfg) { + my $e = 0; + foreach my $lg (values %lfg) { + if ($lg->{name} eq $rfg{$grp_id}->{name}) { + $e = 1; + } + if ($lg->{name} =~ /default view/i) { + $e = 1; + } + } + + if (!$e) { + my $egroup = 1; + foreach my $cgroup (sort { $a <=> $b } keys %lfg) { + if ($egroup == $cgroup) { + $egroup++; + } + } + if ($egroup < 31) { + $lfg{$egroup} = $rfg{$grp_id}; + } + } + } + + # create local friend groups (existing + copied) + my $i = 0; + %req = ( + 'mode' => "editfriendgroups", + 'user' => $local_u->{'user'}, + 'clientversion' => $LJR::LJ_CLIENT, + 'ver' => $LJ::PROTOCOL_VER, + ); + + # convert LJ::Simple hash back to ljprotocol hash + foreach my $grpid (keys %lfg) { + if ($grpid > 0 && $grpid < 31) { + + my $pname = "efg_set_" . $grpid . "_name"; + $req{$pname} = $lfg{$grpid}->{name}; + $i++; + } + } + + # do the actual request + LJ::do_request(\%req, \%res, $flags); + if (! $res{'success'} eq "OK") { + return $err->( + "Unable to update local user" . $local_u->{'user'} . "groups", + $res{'success'} . ":" . $res{'errmsg'} + ); + } + + # get remote days with entries + if (! defined $remote_lj->GetDayCounts(\%gdc_hr, undef)) { + return $err->("can't get day counts: ", $LJ::Simple::error); + } + + # import entries by means of export.bml (XML format) + if ($remote_protocol eq "xml") { + my $mydc = {}; + + foreach (sort {$a<=>$b} keys %gdc_hr) { + my $timestamp = $_; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime($timestamp); + + $mon++; + $year = $year + 1900; + + $mydc->{$year}->{$mon} = 0; + $mydc->{$year}->{$mon} = $mydc->{$year}->{$mon} + $gdc_hr{$timestamp}; + } + + foreach (sort {$a <=> $b} keys %{$mydc}) { + my $y = $_; + + foreach (sort {$a <=> $b} keys %{$mydc->{$y}}) { + jstatus_print ("getting XML data and creating local entries for " . $_ . "/" . $y); + + my $do_login = 0; + + while (1) { + if ($do_login) { + $remote_lj = new LJ::Simple ({ + site => $remote_site, + user => $remote_user, + pass => $remote_pass, + pics => 0, + moods => 0, + }); + if (! defined $remote_lj) { + return $err->("Can't login to remote site.", $LJ::Simple::error); + } + if (!$remote_lj->GenerateCookie()) { + if (!$remote_lj->GenerateCookie()) { + return $err->("Can't generate login cookie.", $LJ::Simple::error); + } + } + } + + my $res = $remote_lj->GetRawData({ + "url" => "/export_do.bml", + "post-data" => { + "authas" => $remote_user, # "nit", + "format" => "xml", + "encid" => 2, # utf-8; for full listing see htdocs/export.bml + "header" => 1, + "year" => $y, + "month" => $_, + "field_itemid" => 1, + "field_eventtime" => 1, + "field_logtime" => 1, + "field_subject" => 1, + "field_event" => 1, + "field_security" => 1, + "field_allowmask" => 1, + "field_currents" => 1, + }}); + + if ($res && $res->{content}) { + my $xdata = $res->{content}; + LJR::unicode::force_utf8(\$xdata); + + my $p1 = new XML::Parser ( + Handlers => { + Start => \&xmlh_entry_start, + End => \&xmlh_entry_end, + Char => \&xmlh_entry_char + }); + + eval { $p1->parse($xdata); }; + if ($@) { + if ($i < $LJR::NETWORK_RETRIES) { + if ($@ =~ /not\ well\-formed\ \(invalid\ token\)/) { +# $xdata + } + + if ($xdata =~ /Login Required/) { + $do_login = 1; + } + + LJR::NETWORK_SLEEP(); $i++; next; + } + else { + $dumptofile->($xdata, "err_" . $remote_user, ".xml"); + return $err->("Runtime error while parsing XML data: ", $@); + } + } + + if ($xmlerrt) { + $dumptofile->($xdata, "err_" . $remote_user, ".xml"); + return $err->("Error while parsing XML data: ", $xmlerrt); + } + + last; + } + else { + return $err->("Can't get XML data.."); + } + } + } + } + } + + # import entries by means of flat protocol + if ($remote_protocol eq "flat") { + # process them, day by day, sleeping a little + foreach (sort {$a<=>$b} keys %gdc_hr) { + my $timestamp = $_; + + # download all the entries for a day + if ($gdc_hr{$timestamp} < $REMOTE_MAX_GET) { + jstatus_print ( + "getting remote and creating local entries for " . + strftime ("%a %b %e %Y", localtime($timestamp)) + ); + + my %r_entries=(); # remote entries + + if (! defined $remote_lj->GetEntries(\%r_entries,$remote_shared_journal,"day",($timestamp))) { + if ($LJ::Simple::error =~ "Cannot display this post") { + $warn->(strftime ("%a %b %e %Y", localtime($timestamp)) . ":" . $LJ::Simple::error); + next; + } + return $err->("can't get remote entries: " . strftime ("%a %b %e %Y", localtime($timestamp)) . ": ", + $LJ::Simple::error); + } + + my $rkey=undef; + my $rentry=undef; + my $r; + + ENTRIES: while (($rkey, $rentry) = each(%r_entries)) { + ($ritem_id, $ranum, $rhtml_id) = $remote_lj->GetItemId($rentry); + my $tevent = $remote_lj->GetEntry($rentry); + + my $is_gated = LJR::Distributed::get_local_itemid($local_u, $ru->{'ru_id'}, $ritem_id, "E"); + return $err->($is_gated->{"errtext"}) if $is_gated->{"err"}; + next ENTRIES if $is_gated->{'itemid'}; + + $r = check_overwrite($local_u, $ru->{'ru_id'}, $ritem_id, $do_overwrite); + return $err->($r->{"errtext"}) if $r->{"err"}; + + next ENTRIES unless $r->{"continue"}; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = + localtime($remote_lj->GetDate($rentry)); + + $mon++; + $year = $year + 1900; + + LJR::Links::make_ljr_hrefs( + LJR::Links::get_server_url($ru->{"servername"}, "base"), + $ru->{"servername"}, + \$tevent + ); + + my $tsubject = $remote_lj->GetSubject($rentry); + my $tcurrent_mood = $remote_lj->Getprop_current_mood($rentry); + my $tcurrent_music = $remote_lj->Getprop_current_music($rentry); + my $ttaglist = $remote_lj->Getprop_taglist($rentry); + $ttaglist = LJ::trim($ttaglist); + + my $tpicture_keyword = $remote_lj->Getprop_picture_keyword($rentry); + +# LJR::unicode::utf8ize(\$tevent); +# LJR::unicode::utf8ize(\$tsubject); +# LJR::unicode::utf8ize(\$tcurrent_mood); +# LJR::unicode::utf8ize(\$tcurrent_music); +# LJR::unicode::utf8ize(\$ttaglist); +# LJR::unicode::utf8ize(\$tpicture_keyword); + + %req = ( 'mode' => 'postevent', + 'ljr-import' => 1, + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $LJR::LJ_CLIENT, + 'user' => $local_u->{'user'}, + 'username' => $local_u->{'user'}, + 'usejournal' => $local_u->{'user'}, + 'getmenus' => 0, + 'lineendings' => "unix", + 'event' => $tevent, + 'subject' => $tsubject, + 'year' => $year, + 'mon' => $mon, + 'day' => $mday, + 'hour' => $hour, + 'min' => $min, + 'props' => { + 'current_moodid' => $rentry->{prop_current_moodid}, + 'current_mood' => $tcurrent_mood, + 'current_music' => $tcurrent_music, + 'opt_preformatted' => $remote_lj->Getprop_preformatted($rentry), + 'opt_nocomments' => $remote_lj->Getprop_nocomments($rentry), + 'taglist' => $ttaglist, + 'picture_keyword' => $tpicture_keyword, + 'opt_noemail' => $remote_lj->Getprop_noemail($rentry), + 'unknown8bit' => $remote_lj->Getprop_unknown8bit($rentry), + 'opt_backdated' => 1, + }, + ); + + my @r_protection = $remote_lj->GetProtect($rentry); + if ($r_protection[0] eq "public" || $r_protection[0] eq "private") { + $req{'security'} = $r_protection[0]; + $req{'allowmask'} = 0; + } + elsif ($r_protection[0] eq "friends") { + $req{'security'} = 'usemask'; + $req{'allowmask'} = 1; + } + elsif ($r_protection[0] eq "groups") { + $req{'security'} = 'usemask'; + shift @r_protection; + + my $mask=0; + while (my $grpname = shift @r_protection) { + my $group = LJ::get_friend_group($local_u, {'name' => $grpname}); + $mask = $mask | (1 << $group->{groupnum}); + } + $req{'allowmask'} = $mask; + } + + %res = (); + LJ::do_request(\%req, \%res, $flags); + if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Post too large") { + $dumptofile->($req{'event'}, "large_" . $local_u->{'user'}, ".raw"); + } + if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Invalid text encoding") { + $warn->($res{"errmsg"}); + next; + } + + if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Invalid or malformed tag list") { + return $err->($res{"errmsg"} . ": [$ttaglist]"); + } + + return $err->($res{'errmsg'}) unless $res{'success'} eq 'OK'; + + $r = LJR::Distributed::store_remote_itemid( + $local_u, + $res{"itemid"}, + $ru->{ru_id}, + $ritem_id, + $rhtml_id); + return $err->($r->{"errtext"}) if $r->{"err"}; + } + + sleep($throttle_speed); + } + else { + $warn->("Too much entries for a day. " . $local_u->{'user'} . " " . + strftime ("%a %b %e %Y", localtime($timestamp)) + ); + } + } # process them day by day + } + + if ($warns) { + my %warns = ('warns' => $warns); + return \%warns; + } + else { + return undef; + } +} + + +return 1; diff --git a/local/bin/ljrimport/ipics.pl b/local/bin/ljrimport/ipics.pl new file mode 100755 index 0000000..a7f7010 --- /dev/null +++ b/local/bin/ljrimport/ipics.pl @@ -0,0 +1,533 @@ +#!/usr/bin/perl + +use strict; +use Image::Size (); +use Simple; # corrected LJ::Simple +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "ljr-defaults.pl"; +require "ljr-links.pl"; +require LJR::Distributed; +require LWPx::ParanoidAgent; + +# error handling +my $err = sub { + my %res = (); + + my $cstack = "\ncallstack:"; + my $i = 0; + while ( 1 ) { + my $tfunc = (caller($i))[3]; + if ($tfunc && $tfunc ne "") { + if ($tfunc !~ /\_\_ANON\_\_/) { + $cstack .= " " . $tfunc; + } + $i = $i + 1; + } + else { + last; + } + } + + $res{"err"} = 1; + $res{"errtext"} = join ("\n", @_); + $res{"errtext"} .= $cstack; + + return \%res; +}; + +# example: +my $DEBUG = 0; + +sub cache_remote_pics { + my ($remote_site, $remote_user, $remote_pass, $local_userid) = @_; + my $ua; + my $res; + my %remote_urls = (); + my %remote_keywords = (); + my %remote_comments = (); + my $default_pic = ""; + + my $i = 0; + my $content; + + # get remote pictures list with keywords + if ($remote_pass ne "") { + $LJ::Simple::network_retries = $LJR::NETWORK_RETRIES; + $LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP; + $LJ::Simple::LJ_Client = $LJR::LJ_CLIENT; + $LJ::Simple::UserAgent = $LJR::USER_AGENT; + + my $ljs_site = $remote_site; + if ($ljs_site =~ /^http\:\/\/(.*)/) { + $ljs_site = $1; + } + + my $remote_lj = new LJ::Simple ({ + site => $ljs_site, + user => $remote_user, + pass => $remote_pass, + pics => 0, + moods => 0, + }); + return $err->("Can't login to remote site.", $LJ::Simple::error) + unless defined($remote_lj); + + if (!$remote_lj->GenerateCookie()) { + return $err->("Can't generate login cookie.", $LJ::Simple::error); + } + + $res = $remote_lj->GetRawData({ + "url" => "/allpics.bml", + }); + if (!($res && $res->{content})) { + return $err->("LJ::Simple: Can't get remote user pictures: $remote_user\n"); + } + + $content = $res->{content}; + } + else { + while(1) { + $ua = LWPx::ParanoidAgent->new(timeout => 60); + $ua->agent($LJR::USER_AGENT); + # TODO: parameterize allpics.bml + $res = $ua->get($remote_site . "/allpics.bml?user=" . $remote_user); + + if (!($res && $res->is_success) && $i < $LJR::NETWORK_RETRIES) { + LJR::NETWORK_SLEEP(); $i++; next; + } + else { + last; + } + } + if (!($res && $res->is_success)) { + return $err->("LWPx: Can't get remote user pictures: $remote_user\n"); + } + + $content = $res->content; + } + + my $ru = LJR::Distributed::get_remote_server($remote_site); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{username} = $remote_user; + $ru = LJR::Distributed::get_cached_user($ru); + + $i = 0; + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do("DELETE FROM ljr_cached_userpics WHERE ru_id=?", undef, $ru->{ru_id}); + return $err->($dbh->errstr) if $dbh->err; + + my $iru; + my $userpic_base = LJR::Links::get_server_url($remote_site, "userpic_base"); + + # extract pic urls and keywords + + if ($content =~ m!<\s*?body.*?>(.+)!si) { + $content = $1; + + while ($content =~ + /\G.*?($userpic_base\/(\d+)\/(\d+))(.*?)($userpic_base\/(\d+)\/(\d+)|$)(.*)/sg + ) { + my $picurl = $1; + my $props = $4; + my $cuserid = $3; + my $cpicid = $2; + $content = $5 . $8; + + my $is_default = 0; + + # save userid + if (!$iru->{ru_id}) { + $iru = LJR::Distributed::get_remote_server($remote_site); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $iru->{username} = $remote_user; + $iru->{userid} = $cuserid; + + $iru = LJR::Distributed::get_cached_user($iru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + } + + if ($props =~ /(.*?)Keywords\:\<\/b\>\ (.*?)\(.*?)\<\/td\>/s) { + $remote_keywords{$picurl} = $2; + $remote_comments{$picurl} = $3; + $remote_comments{$picurl} =~ s/^\s+|\s+$//; + } + if ($props =~ /\Default\<\/u\>/s) { + $default_pic = $picurl; + $is_default = 1; + } + + my @keywords = ""; + if ($remote_keywords{$picurl}) { + @keywords = split(/\s*,\s*/, $remote_keywords{$picurl}); + @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords; + } + elsif ($is_default) { + @keywords = (""); + } + + foreach my $kw (@keywords) { + if($remote_urls{$cpicid}) { + $dbh->do("UPDATE ljr_cached_userpics set keyword=?, is_default=?, comments=? + where ru_id=? and remote_picid=?", + undef, $kw, $is_default, $remote_comments{$picurl}, + $ru->{ru_id}, $cpicid); + return $err->($dbh->errstr) if $dbh->err; + } + else { + $dbh->do("INSERT INTO ljr_cached_userpics VALUES (?,?,?,?,?)", + undef, $ru->{ru_id}, $cpicid, $kw, + $is_default, $remote_comments{$picurl}); + return $err->($dbh->errstr) if $dbh->err; + } + } + $remote_urls{$cpicid} = $picurl; + } + } + return undef; +} + +sub import_pics { + my ( + $remote_site, $remote_user, $remote_pass, + $local_user, $o_keyword, $o_default + ) = @_; + + my $MAX_UPLOAD = 40960; + + my %remote_ids = (); + my %remote_urls = (); + my %remote_keywords = (); + my %remote_comments = (); + my $default_pic = ""; + + my $ru = LJR::Distributed::get_remote_server($remote_site); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{username} = $remote_user; + $ru = LJR::Distributed::get_cached_user($ru); + + # load user object (force, otherwise get error outside of apache) + my $u = LJ::load_user($local_user, 1); + return $err->("Invalid local user: " . $local_user) unless $u; + + # prepare database connections (for different versions of user objects) + my ($dbcm, $dbcr, $sth); + $dbcm = LJ::get_cluster_master($u); + return $err->("Can't get cluster master!") unless $dbcm; + $dbcr = LJ::get_cluster_def_reader($u); + return $err->("Can't get cluster reader!") unless $dbcr; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $e; + + if (!$o_keyword && !$o_default) { + $e = cache_remote_pics($remote_site, $remote_user, $remote_pass, $u->{userid}); + return $e if $e->{err}; + } + else { + $sth = $dbr->prepare( + "SELECT ru_id FROM ljr_cached_userpics WHERE ru_id=? GROUP BY ru_id"); + $sth->execute($ru->{ru_id}); + my $ruid = $sth->fetchrow_hashref; + $sth->finish; + + if (!$ruid) { + $e = cache_remote_pics($remote_site, $remote_user, $remote_pass, $u->{userid}); + return $e if $e->{err}; + } + } + + # get ru->{userid} which should come up after caching remote pic props + $ru = LJR::Distributed::get_cached_user($ru); + + if ($o_keyword) { + $sth = $dbr->prepare( + "SELECT remote_picid, keyword, is_default, comments " . + "FROM ljr_cached_userpics WHERE ru_id=? and keyword=?"); + $sth->execute($ru->{ru_id}, $o_keyword); + } + elsif ($o_default) { + $sth = $dbr->prepare( + "SELECT remote_picid, keyword, is_default, comments " . + "FROM ljr_cached_userpics WHERE ru_id=? and is_default=1"); + $sth->execute($ru->{ru_id}); + } + else { + $sth = $dbr->prepare( + "SELECT remote_picid, keyword, is_default, comments " . + "FROM ljr_cached_userpics WHERE ru_id=?"); + $sth->execute($ru->{ru_id}); + } + + my $i = 0; + while (my $rpic = $sth->fetchrow_hashref) { + my $picurl = $remote_site . "/userpic/" . $rpic->{remote_picid} . "/" . $ru->{userid}; + + $remote_ids{$i} = $rpic->{remote_picid}; + $remote_urls{$rpic->{remote_picid}} = $picurl; + + $remote_comments{$picurl} = $rpic->{comments}; + $remote_keywords{$picurl} = + (($remote_keywords{$picurl}) ? $remote_keywords{$picurl} . "," : "") . + $rpic->{keyword}; + + if ($rpic->{is_default}) { + $default_pic = $picurl; + } + + print + $picurl . ":" . + $remote_ids{$i} . ":" . + $remote_comments{$picurl} . ":" . + $remote_keywords{$picurl} . "\n" + if $DEBUG; + + $i++; + } + $sth->finish; + + RPICID: foreach my $rpicid (sort {$a <=> $b} values %remote_ids) { + my $local_picid = $dbr->selectrow_array( + "SELECT local_picid FROM ljr_remote_userpics " . + "WHERE ru_id=? and remote_picid=? and local_userid = ?", + undef, $ru->{ru_id}, $rpicid, $u->{userid}); + + if ($local_picid) { + my $r_picid = $dbr->selectrow_array( + "SELECT picid FROM userpic2 WHERE picid=?", + undef, $local_picid); + + if (!$r_picid) { + $u->do("DELETE FROM ljr_remote_userpics WHERE local_picid=?", undef, $local_picid); + $local_picid = undef; + } + else { + next RPICID; + } + } + + my %POST = (); + + $POST{urlpic} = $remote_urls{$rpicid}; + $POST{keywords} = $remote_keywords{$remote_urls{$rpicid}}; + $POST{comments} = $remote_comments{$remote_urls{$rpicid}}; + $POST{url} = ""; + if ($default_pic eq $remote_urls{$rpicid}) { + $POST{make_default} = 1; + } + + # get remote picture and validate it + my $ua; + my $res; + my ($sx, $sy, $filetype); + + $i = 0; + while(1) { + $ua = LWPx::ParanoidAgent->new( + timeout => 60, + max_size => $MAX_UPLOAD + 1024); + $ua->agent($LJR::USER_AGENT); + $res = $ua->get($POST{urlpic}); + + # if the picture doesn't exist on the remote server + # then we get 404 http error and remove it from our cache + if ($res && + ($res->{"_rc"} eq 404 || $res->{"_rc"} eq 503) + ) { + $dbh->do("DELETE FROM ljr_cached_userpics WHERE ru_id=? and remote_picid=?", + undef, $ru->{ru_id}, $rpicid); + return $err->($dbh->errstr) if $dbh->err; + + next RPICID; + } + + $POST{userpic} = $res->content if $res && $res->is_success; + + ($sx, $sy, $filetype) = Image::Size::imgsize(\$POST{'userpic'}); + + if (!( + $res && $res->is_success && defined($sx) && + length($POST{'userpic'}) <= $MAX_UPLOAD && + ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG") && + $sx <= 100 && $sy <= 100 + ) && + $i < $LJR::NETWORK_RETRIES) { + LJR::NETWORK_SLEEP(); $i++; next; + } + else { + last; + } + } + if (!($res && $res->is_success)) { + return $err->("Can't get remote user picture: ", + $remote_user, $local_user, $o_keyword, $o_default, $POST{urlpic}, + $res->status_line); + } + if (!defined $sx) { + print ("Invalid image: " . $POST{urlpic} . "\n"); + next RPICID; + } + + if (length($POST{'userpic'}) > $MAX_UPLOAD) { + return $err->("Picture " . $POST{urlpic} . "is too large"); + } + + return $err->("Unsupported filetype: " . $POST{urlpic}) + unless ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG"); + return $err->("Image too large: " . $POST{urlpic}) if ($sx > 150 || $sy > 150); + + my $base64 = Digest::MD5::md5_base64($POST{'userpic'}); + + # see if it's a duplicate + my $picid; + my $contenttype; + if ($filetype eq "GIF") { $contenttype = 'G'; } + elsif ($filetype eq "PNG") { $contenttype = 'P'; } + elsif ($filetype eq "JPG") { $contenttype = 'J'; } + + $picid = $dbcr->selectrow_array( + "SELECT picid FROM userpic2 WHERE userid=? AND fmt=? AND md5base64=?", + undef, $u->{'userid'}, $contenttype, $base64); + $picid = 0 unless defined($picid); + + print "trying to insert into db\n" if $DEBUG; + + # if picture isn't a duplicate, insert it + if ($picid == 0) { + + # Make a new global picid + $picid = LJ::alloc_global_counter('P') or + return $err->('Unable to allocate new picture id'); + + $u->do( + "INSERT INTO userpic2 (picid, userid, fmt, width, height, " . + "picdate, md5base64, location, state) " . + "VALUES (?, ?, ?, ?, ?, NOW(), ?, ?, 'N')", + undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64, undef); + return $err->($u->errstr) if $u->err; + + my $clean_err = sub { + if ($picid) { + $u->do( + "DELETE FROM userpic2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $picid); + + $u->do( + "DELETE FROM userpicblob2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $picid); + } + return $err->(@_); + }; + + ### insert the blob + $u->do( + "INSERT INTO userpicblob2 (userid, picid, imagedata) VALUES (?,?,?)", + undef, $u->{'userid'}, $picid, $POST{'userpic'}); + return $clean_err->($u->errstr) if $u->err; + + # make it their default pic? + if ($POST{'make_default'}) { + LJ::update_user($u, { defaultpicid => $picid }); + $u->{'defaultpicid'} = $picid; + } + + # set default keywords? + if ($POST{'keywords'} && $POST{'keywords'} ne '') { + print "storing keywords\n" if $DEBUG; + + $sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?"); + $sth->execute($u->{'userid'}); + + my @exist_kwids; + while (my ($kwid, $picid) = $sth->fetchrow_array) { + $exist_kwids[$kwid] = $picid; + } + + my @keywords = split(/\s*,\s*/, $POST{'keywords'}); + @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords; + + my (@bind, @data); + my $c = 0; + + foreach my $kw (@keywords) { + my $kwid = LJ::get_keyword_id($u, $kw); + next unless $kwid; # Houston we have a problem! This should always return an id. + + if ($c > $LJ::MAX_USERPIC_KEYWORDS) { + return $clean_err->("Too many userpic keywords: " . LJ::ehtml($kw)); + } + + if ($exist_kwids[$kwid]) { # Already used on another picture + # delete existing pic while there's newer one + $u->do(" + delete ljr_remote_userpics, ljr_cached_userpics + from ljr_cached_userpics, ljr_remote_userpics + where + ljr_cached_userpics.ru_id = ljr_remote_userpics.ru_id and + ljr_cached_userpics.remote_picid = ljr_remote_userpics.remote_picid and + ljr_remote_userpics.local_userid = ? and local_picid = ?", + undef, $u->{'userid'}, $exist_kwids[$kwid]); + + $u->do("DELETE FROM userpicmap2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $exist_kwids[$kwid]); + + $u->do("DELETE FROM userpicblob2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $exist_kwids[$kwid]); + + $u->do("DELETE FROM userpic2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $exist_kwids[$kwid]); + } + + push @bind, '(?, ?, ?)'; + push @data, $u->{'userid'}, $kwid, $picid; + + $c++; + } + + if (@data && @bind) { + my $bind = join(',', @bind); + + $u->do( + "INSERT INTO userpicmap2 (userid, kwid, picid) VALUES $bind", + undef, @data); + } + } + + # set default comments and the url + my (@data, @set); + if ($POST{'comments'} && $POST{'comments'} ne '') { + push @set, 'comment=?'; + push @data, LJ::text_trim($POST{'comments'}, $LJ::BMAX_UPIC_COMMENT, $LJ::CMAX_UPIC_COMMENT); + } + + if ($POST{'url'} ne '') { + push @set, 'url=?'; + push @data, $POST{'url'}; + } + + if (@set) { + my $set = join(',', @set); + + $u->do("UPDATE userpic2 SET $set WHERE userid=? AND picid=?", + undef, @data, $u->{'userid'}, $picid); + return $err->($u->errstr) if $u->err; + } + + $u->do("INSERT INTO ljr_remote_userpics VALUES (?,?,?,?)", + undef, $ru->{ru_id}, $rpicid, $u->{userid}, $picid); + return $err->($u->errstr) if $u->err; + } + } + + return undef; +} + +return 1; diff --git a/local/bin/ljrimport/ljr-defaults.pl b/local/bin/ljrimport/ljr-defaults.pl new file mode 100755 index 0000000..93e1d2b --- /dev/null +++ b/local/bin/ljrimport/ljr-defaults.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +package LJR; + +$LJ_CLIENT = "LJR::Import/0.01"; +$USER_AGENT = "LJR::Import/0.01; http://lj.rossia.org/; lj-admin\@rossia.org"; + +# How much times to retry if any network related error occurs +$NETWORK_RETRIES = 10; #was: 20 + +# Hom much seconds to wait before each retry +$NETWORK_SLEEP = 30; #was: 5 + +$DEBUG = 1; + +sub NETWORK_SLEEP { + my $msg = shift; + + if ($msg) { + $msg = " (" . $msg . ")"; + } + else { + $msg = ""; + } + + my $t = `date +"%D %T"`; + print + substr($t, 0, length($t) - 1) . + " sleeping $NETWORK_SLEEP seconds due to network related error" . $msg . ".\n" + if $DEBUG; + + sleep $NETWORK_SLEEP; +}; + +return 1; diff --git a/local/bin/ljrimport/ljr-import.pl b/local/bin/ljrimport/ljr-import.pl new file mode 100755 index 0000000..fe07103 --- /dev/null +++ b/local/bin/ljrimport/ljr-import.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl -w + +package LJR::Import; + +use strict; # preventing my program from doing bad things +use DBI; # http://dbi.perl.org +use POSIX (); + +do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl"; + +my $qhost = $LJ::DBINFO{'master'}->{'host'}; +my $quser = $LJ::DBINFO{'master'}->{'user'}; +my $qpass = $LJ::DBINFO{'master'}->{'pass'}; +my $qdb = $LJ::DBINFO{'master'}->{'dbname'}; +my $qsock = $LJ::DBINFO{'master'}->{'sock'}; +my $qport = $LJ::DBINFO{'master'}->{'port'}; + +$| = 1; # unbuffered (almost) output + +# global database handle +$LJR::Import::global_dbh = 0; +# global shutdown request received flag +$LJR::Import::cool_stop = 0; + +my $history_id; + +# POSIX unmasks the sigprocmask properly +my $sigset = POSIX::SigSet->new(); +my $action = POSIX::SigAction->new( + 'LJR::Import::sigTERM_handler', $sigset, &POSIX::SA_NODEFER); + +POSIX::sigaction(&POSIX::SIGTERM, $action); + +sub log_print { + my $msg = shift; + my $t = `date +"%D %T"`; + print substr($t, 0, length($t) - 1) . " $msg\n"; +} + +sub sigTERM_handler { + my $t = `date +"%D %T"`; + print substr($t, 0, length($t) - 1) . " ljr-import.pl: received shutdown request\n"; + $LJR::Import::cool_stop = 1; +} + +# configuration +my $speed_throttle = 10; # seconds + +print "\n"; + +LJR::Import::log_print("started"); + +# main loop, throttled +while (!process_exit()) { + process_queue(); # process new requests for import if any + sleep ($speed_throttle); # sleep for a while +} + +LJR::Import::log_print("ljr-import.pl: shutting down due to safe shutdown request"); + +sub import_log { + my ($istatus) = @_; + + my $sth2 = $LJR::Import::global_dbh->prepare ( + "update ljr_ihistory set + istatus = ?, + idate = now() + where importid = ?"); + $sth2->execute($istatus, $history_id); + $sth2->finish; +} + +sub process_exit { + return ($LJR::Import::cool_stop); +} + +sub process_queue { + my $row; + my $row1; + my $sth2; + my $e; + + $LJR::Import::global_dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb", + $quser, $qpass, + {RaiseError => 0, AutoCommit => 1} + ) || die "Can't open database connection: $DBI::errstr"; + + my $sth = $LJR::Import::global_dbh->prepare("SELECT * from ljr_iqueue order by priority, importid"); + $sth->execute; + + while (($row = $sth->fetchrow_hashref) && !process_exit()) { + my $r = system ("nice -n 19 ./ljr-importdo.pl"); + if ($r != 0) { + $sth->finish; + $LJR::Import::global_dbh->disconnect; + return; + } + + sleep($speed_throttle); # do not hurry + $sth->execute; # refresh the query + } + $sth->finish; + + $LJR::Import::global_dbh->disconnect; +} diff --git a/local/bin/ljrimport/ljr-importdo.pl b/local/bin/ljrimport/ljr-importdo.pl new file mode 100755 index 0000000..c1c8bdd --- /dev/null +++ b/local/bin/ljrimport/ljr-importdo.pl @@ -0,0 +1,218 @@ +#!/usr/bin/perl -w + +package LJR::Import; + +use strict; # preventing my program from doing bad things +use DBI; # http://dbi.perl.org +use POSIX (); + +do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl"; + +my $qhost = $LJ::DBINFO{'master'}->{'host'}; +my $quser = $LJ::DBINFO{'master'}->{'user'}; +my $qpass = $LJ::DBINFO{'master'}->{'pass'}; +my $qdb = $LJ::DBINFO{'master'}->{'dbname'}; +my $qsock = $LJ::DBINFO{'master'}->{'sock'}; +my $qport = $LJ::DBINFO{'master'}->{'port'}; + + +require "ijournal.pl"; +require "icomments.pl"; + +$| = 1; # unbuffered (almost) output + +# global database handle +$LJR::Import::global_dbh = 0; +# global shutdown request received flag +$LJR::Import::cool_stop = 0; + +my $history_id; + +# POSIX unmasks the sigprocmask properly +my $sigset = POSIX::SigSet->new(); +my $action = POSIX::SigAction->new( + 'LJR::Import::sigTERM_handler', $sigset, &POSIX::SA_NODEFER); + +POSIX::sigaction(&POSIX::SIGTERM, $action); + +sub log_print { + my $msg = shift; + my $t = `date +"%D %T"`; + print substr($t, 0, length($t) - 1) . " $msg\n"; +} + +sub sigTERM_handler { + my $t = `date +"%D %T"`; + print substr($t, 0, length($t) - 1) . " ljr-import-do.pl: received shutdown request\n"; + $LJR::Import::cool_stop = 1; +} + +# configuration +my $speed_throttle = 10; # seconds + + +process_queue_alone(); # there must be something there! +if (process_exit()) { + exit 1; +} +else { + exit 0; +} + +sub import_log { + my ($istatus) = @_; + + my $sth2 = $LJR::Import::global_dbh->prepare ( + "update ljr_ihistory set + istatus = ?, + idate = now() + where importid = ?"); + $sth2->execute($istatus, $history_id); + $sth2->finish; +} + +sub process_exit { + return ($LJR::Import::cool_stop); +} + +sub process_queue_alone { + my $row; + my $row1; + my $sth2; + my $e; + + $LJR::Import::global_dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb", + $quser, $qpass, + {RaiseError => 0, AutoCommit => 1} + ) || die "Can't open database connection: $DBI::errstr"; + + my $sth = $LJR::Import::global_dbh->prepare("SELECT * from ljr_iqueue order by priority, importid"); + $sth->execute; + + while (($row = $sth->fetchrow_hashref) && !process_exit()) { + my $sth1 = $LJR::Import::global_dbh->prepare ( + "SELECT * from ljr_iqueue where + local_user = '" . $row->{'local_user'} . "' + order by local_user desc, importid desc limit 1"); + $sth1->execute; # find last user request for import + $row = $sth1->fetchrow_hashref; + + # create history record + $sth2 = $LJR::Import::global_dbh->prepare ( + "insert into ljr_ihistory values ('',?,?,'',?,?,?,?,now(),'STARTED',now())"); + $sth2->execute ( + $row->{'remote_site'}, $row->{'remote_user'}, $row->{'remote_protocol'}, + $row->{'local_user'}, $row->{'opt_overwrite'}, $row->{'opt_comments'} + ); # save import history (parameters, time when started) + + $history_id = $LJR::Import::global_dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + $sth2->finish; + + LJR::Import::log_print( + $row->{'local_user'} . " <- " . + $row->{'remote_site'} . "::" . $row->{'remote_user'} . + " (entries)" + ); + + $e = ""; + $e = import_journal( + 0, # throttle_speed (seconds) + $row->{'remote_site'}, # remote_site + $row->{'remote_protocol'},# remote_protocol + $row->{'remote_user'}, # remote_user + $row->{'remote_pass'}, # remote_pass + "", # remote shared journal (if any) + $row->{'local_user'}, # local_user + "", # local shared journal (if any) + $row->{'opt_overwrite'} # overwrite entries + ); + + if ($row->{'opt_comments'} && (!$e || !$e->{'err'})) { + LJR::Import::log_print( + $row->{'local_user'} . " <- " . + $row->{'remote_site'} . "::" . $row->{'remote_user'} . + " (caching comments)" + ); + + $e = get_comments( + $row->{'remote_site'}, + $row->{'remote_user'}, + $row->{'remote_pass'}, + 1); + + if (!$e || !$e->{'err'}) { + LJR::Import::log_print( + $row->{'local_user'} . " <- " . + $row->{'remote_site'} . "::" . $row->{'remote_user'} . + " (creating comments)"); + + $e = create_imported_comments ( + $row->{'remote_site'}, + $row->{'remote_user'}, + $row->{'local_user'}); + } + } + + if ($e->{'err'}) { + $sth2 = $LJR::Import::global_dbh->prepare ( + "update ljr_ihistory " . + "set remote_pass = '" . $row->{'remote_pass'} . "' " . + "where importid = " . $history_id . " ;" + ); + $sth2->execute; # save remote pass for debugging purposes + $sth2->finish; + + my $boo = $e->{errtext}; + $boo =~ s/\n//; + + LJR::Import::log_print( + $row->{'local_user'} . " <- " . + $row->{'remote_site'} . "::" . $row->{'remote_user'} . " " . $boo + ); + + import_log($e->{errtext}); + } + else { + $sth2 = $LJR::Import::global_dbh->prepare ( + "update ljr_ihistory " . + "set remote_pass = '' " . + "where remote_site = '" . $row->{'remote_site'} . "' and " . + "remote_user = '" . $row->{'remote_user'} . "' ;" + ); + $sth2->execute; # remove remote pass since the journal was imported successfully + $sth2->finish; + + LJR::Import::log_print( + $row->{'local_user'} . " <- " . + $row->{'remote_site'} . "::" . $row->{'remote_user'} . + ": successful" + ); + + if ($e->{'warns'}) { + import_log("SUCCESSFUL, but " . $e->{'warns'}); + } + else { + import_log("SUCCESSFUL"); + } + } + + $sth1 = $LJR::Import::global_dbh->prepare ( + "delete from ljr_iqueue " . + "where local_user = '" . $row->{'local_user'} . "'" + ); # empty all the user's request after processing last one + $sth1->execute; + $sth1->finish; + + $sth->finish; + +# we're quitting! +# if (process_exit()) { + $LJR::Import::global_dbh->disconnect; + return; +# } + } + $sth->finish; + + $LJR::Import::global_dbh->disconnect; +} diff --git a/local/bin/ljrimport/ljr-links.pl b/local/bin/ljrimport/ljr-links.pl new file mode 100755 index 0000000..9b40d5c --- /dev/null +++ b/local/bin/ljrimport/ljr-links.pl @@ -0,0 +1,117 @@ +#!/usr/bin/perl + +use strict; + +package LJR::Links; + +sub get_server_url { + my ($canonical_url, $type) = @_; + + if ($canonical_url eq "http://www.livejournal.com") { + if ($type eq "base") { + return "livejournal.com"; + } + if ($type eq "userpic_base") { + return "http://userpic.livejournal.com"; + } + } +} + +sub make_ljr_hrefs { + my ($server_patt, $server_full, $text) = @_; + + my $content = $$text; + $$text = ""; + my $url; + my $orig_url; + my $orig_url_text; + + return unless $content; + + # replace valid html hyperlinks (url_text) + # with url_text + # + while ($content =~ + /\G(.*?)(\(.*?)\<\/a\>)(.*)/sgi + ) { + $$text .= $1; + $orig_url = $2; + $orig_url_text = $6; + $url = $4; + $content = $7; + + # relative link (to the server from which we're importing) + if ($url =~ /^(\/users\/.*?\/\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$ + $$text .= "$orig_url_text"; + } + # relative link to oldstyle talkread.bml + elsif ($url =~ /^\/talkread.bml?\?journal=(.*?)\&itemid=(\d+)/) { + $$text .= "$orig_url_text"; + } + # absolute link to oldstyle talkread.bml + elsif ($url =~ /^http:\/\/(www\.|)$server_patt\/talkread.bml\?journal=(.*?)\&itemid=(\d+)/) { + $$text .= "$orig_url_text"; + } + # free users own two types of urls (first is canonical) + # http://www.livejournal.com/users/free_user/123456.html + # http://www.livejournal.com/~free_user/123456.html + elsif ($url =~ /^http:\/\/(www\.|)$server_patt(((\/~(\w*?)\/)|(\/users\/.*?\/))(\d*?\.html(.*?$)))/) { # (\?thread=\d*\#t\d*)|$ + if ($5) { + $$text .= "$orig_url_text"; + } + else { + $$text .= "$orig_url_text"; + } + } + # payed users might own http://payeduser.livejournal.com/123456.html urls + elsif ($url =~ /^http:\/\/(\w*?)\.$server_patt\/(\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$ + $$text .= "$orig_url_text"; + } + else { + $$text .= $orig_url; + } + } + $$text .= $content; + + $content = $$text; + $$text = ""; + + + # replace strings like http://www.livejournal.com/users/lookslikeentry/123456.html with + # http://www.livejournal.com/users/lookslikeentry/123456.html + # + # now these can be only absolute links starting with http:// + while ($content =~ + /\G(.*?(^|[\ \t\r\n\f]))(http:\/\/.*?)(($|[\ \t\r\n\f]).*)/sg + ) { + $$text .= $1; + $orig_url = $3; + $orig_url_text = $3; + $url = $3; + $content = $4; + + # free users (copied from above) + if ($url =~ /^http:\/\/(www\.|)$server_patt(((\/~(\w*?)\/)|(\/users\/.*?\/))(\d*?\.html(.*?$)))/) { # (\?thread=\d*\#t\d*)|$ + if ($5) { + $$text .= "$orig_url_text"; + } + else { + $$text .= "$orig_url_text"; + } + } + # oldstyle talkread.bml + elsif ($url =~ /^http:\/\/(www\.|)$server_patt\/talkread.bml\?journal=(.*?)\&itemid=(\d+)/) { + $$text .= "$orig_url_text"; + } + # payed users (copied from above) + elsif ($url =~ /^http:\/\/(\w*?)\.$server_patt\/(\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$ + $$text .= "$orig_url_text"; + } + else { + $$text .= $orig_url; + } + } + $$text .= $content; +} + +return 1; diff --git a/local/bin/ljrimport/ljr-start.sh b/local/bin/ljrimport/ljr-start.sh new file mode 100755 index 0000000..42813b2 --- /dev/null +++ b/local/bin/ljrimport/ljr-start.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +export LJHOME=/home/lj-admin/lj +IMPORT_NAME=ljr-import + +ipid=`ps -e --format=pid,cmd | grep $IMPORT_NAME | grep -v grep | cut --bytes=1-5` + +if [ ! "$ipid" == "" ]; then + echo "LJR::Import found, PID: $ipid; shutdown with ljr-stop.sh first." +else + if [ "$LJHOME" != "" ]; then + cd $LJHOME/bin/ljrimport + ./ljr-import.pl >> $LJHOME/logs/ljr-import.log 2>&1 & + else + echo \$LJHOME is not set. + fi +fi diff --git a/local/bin/ljrimport/ljr-stop.sh b/local/bin/ljrimport/ljr-stop.sh new file mode 100755 index 0000000..c89ba5d --- /dev/null +++ b/local/bin/ljrimport/ljr-stop.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +IMPORT_NAME=ljr-import + +ipid=`ps -e --format=pid,cmd | grep $IMPORT_NAME | grep -v grep | cut --bytes=1-5` + +if [ ! "$ipid" == "" ]; then + echo "LJR::Import found, PID: $ipid; sending shutdown signal." + kill $ipid +else + echo "LJR::Import is not running." +fi diff --git a/local/bin/maint/clean_challenges.pl b/local/bin/maint/clean_challenges.pl new file mode 100755 index 0000000..e4432cf --- /dev/null +++ b/local/bin/maint/clean_challenges.pl @@ -0,0 +1,21 @@ +#!/usr/bin/perl +# + +$maint{'clean_challenges'} = sub +{ + my $dbh = LJ::get_db_writer(); + my $sth; + + my $ctime = time(); + my $deltime = $ctime - 60*60*24*14; # two weeks + + print "current time: $ctime\n"; + print "deleting challenges older than: $deltime\n"; + $sth = $dbh->prepare("delete from challenges where challenge < 'c0:$deltime'"); + $sth->execute(); + if ($dbh->err) { die $dbh->errstr; } + + print "done.\n"; +}; + +1; diff --git a/local/bin/maint/stats.pl b/local/bin/maint/stats.pl new file mode 100755 index 0000000..4f68eee --- /dev/null +++ b/local/bin/maint/stats.pl @@ -0,0 +1,548 @@ +#!/usr/bin/perl +# + +use strict; +use vars qw(%maint); + +require "$ENV{'LJHOME'}/cgi-bin/statslib.pl"; + +# filled in by ljmaint.pl, 0=quiet, 1=normal, 2=verbose +$LJ::Stats::VERBOSE = $LJ::LJMAINT_VERBOSE >= 2 ? 1 : 0; + +$maint{'genstats'} = sub +{ + my @which = @_ || qw(users countries + states gender clients + pop_interests meme pop_faq); + + # popular faq items + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "popfaq", + 'statname' => "pop_faq", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + my $sth = $db->prepare("SELECT faqid, COUNT(*) FROM faquses WHERE " . + "faqid<>0 GROUP BY 1 ORDER BY 2 DESC LIMIT 50"); + $sth->execute; + die $db->errstr if $db->err; + + my %ret; + while (my ($id, $count) = $sth->fetchrow_array) { + $ret{$id} = $count; + } + + return \%ret; + }, + + }); + + # popular interests + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "pop_interests", + 'statname' => "pop_interests", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + return {} if $LJ::DISABLED{'interests-popular'}; + + # see what the previous min was, then subtract 20% of max from it + my ($prev_min, $prev_max) = $db->selectrow_array("SELECT MIN(statval), MAX(statval) " . + "FROM stats WHERE statcat='pop_interests'"); + my $stat_min = int($prev_min - (0.2*$prev_max)); + $stat_min = 1 if $stat_min < 1; + + my $sth = $db->prepare("SELECT interest, intcount FROM interests WHERE intcount>? " . + "ORDER BY intcount DESC, interest ASC LIMIT 400"); + $sth->execute($stat_min); + die $db->errstr if $db->err; + + my %ret; + while (my ($int, $count) = $sth->fetchrow_array) { + $ret{$int} = $count; + } + + return \%ret; + }, + + }); + + # popular memes + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "meme", + 'statname' => "popmeme", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + return {} if $LJ::DISABLED{'meme'}; + + my $sth = $db->prepare("SELECT url, count(*) FROM meme " . + "GROUP BY 1 ORDER BY 2 DESC LIMIT 100"); + $sth->execute; + die $db->errstr if $db->err; + + my %ret; + while (my ($url, $count) = $sth->fetchrow_array) { + $ret{$url} = $count; + } + + return \%ret; + }, + }); + + # clients + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "clients", + 'statname' => "client", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + return {} if $LJ::DISABLED{'clientversionlog'}; + + my $tsql = "SELECT MAX(userid) FROM user"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + my $usertotal = $db->selectrow_array($tsql); + my $blocks = LJ::Stats::num_blocks($usertotal); + + my %ret; + foreach my $block (1..$blocks) { + my ($low, $high) = LJ::Stats::get_block_bounds($block); + + $db = $db_getter->(); # revalidate connection + my $sth = $db->prepare("SELECT c.client, COUNT(*) AS 'count' FROM clients c, clientusage cu " . + "WHERE c.clientid=cu.clientid AND cu.userid BETWEEN $low AND $high " . + "AND cu.lastlogin > DATE_SUB(NOW(), INTERVAL 30 DAY) GROUP BY 1 ORDER BY 2"); + $sth->execute; + die $db->errstr if $db->err; + + while ($_ = $sth->fetchrow_hashref) { + $ret{$_->{'client'}} += $_->{'count'}; + } + + print LJ::Stats::block_status_line($block, $blocks); + } + + return \%ret; + }, + }); + + + # user table analysis + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "users", + 'statname' => ["account", "newbyday", "age", "userinfo"], + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + my $tsql = "SELECT MAX(userid) FROM user"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + my $usertotal = $db->selectrow_array($tsql); + my $blocks = LJ::Stats::num_blocks($usertotal); + + my %ret; # return hash, (statname => { arg => val } since 'statname' is arrayref above + + # iterate over user table in batches + foreach my $block (1..$blocks) { + + my ($low, $high) = LJ::Stats::get_block_bounds($block); + + # user query: gets user,caps,age,status,allow_getljnews + $db = $db_getter->(); # revalidate connection + my $sth = $db->prepare + ("SELECT user, caps, " . + "FLOOR((TO_DAYS(NOW())-TO_DAYS(bdate))/365.25) AS 'age', " . + "status, allow_getljnews " . + "FROM user WHERE userid BETWEEN $low AND $high"); + $sth->execute; + die $db->errstr if $db->err; + while (my $rec = $sth->fetchrow_hashref) { + + # account types + my $capnameshort = LJ::name_caps_short($rec->{'caps'}); + $ret{'account'}->{$capnameshort}++; + + # ages + $ret{'age'}->{$rec->{'age'}}++ + if $rec->{'age'} > 4 && $rec->{'age'} < 110; + + # users receiving news emails + $ret{'userinfo'}->{'allow_getljnews'}++ + if $rec->{'status'} eq "A" && $rec->{'allow_getljnews'} eq "Y"; + } + + # userusage query: gets timeupdate,datereg,nowdate + my $sth = $db->prepare + ("SELECT DATE_FORMAT(timecreate, '%Y-%m-%d') AS 'datereg', " . + "DATE_FORMAT(NOW(), '%Y-%m-%d') AS 'nowdate', " . + "UNIX_TIMESTAMP(timeupdate) AS 'timeupdate' " . + "FROM userusage WHERE userid BETWEEN $low AND $high"); + $sth->execute; + die $db->errstr if $db->err; + + while (my $rec = $sth->fetchrow_hashref) { + + # date registered + $ret{'newbyday'}->{$rec->{'datereg'}}++ + unless $rec->{'datereg'} eq $rec->{'nowdate'}; + + # total user/activity counts + $ret{'userinfo'}->{'total'}++; + if (my $time = $rec->{'timeupdate'}) { + my $now = time(); + $ret{'userinfo'}->{'updated'}++; + $ret{'userinfo'}->{'updated_last30'}++ if $time > $now-60*60*24*30; + $ret{'userinfo'}->{'updated_last7'}++ if $time > $now-60*60*24*7; + $ret{'userinfo'}->{'updated_last1'}++ if $time > $now-60*60*24*1; + } + } + + print LJ::Stats::block_status_line($block, $blocks); + } + + return \%ret; + }, + }); + + + LJ::Stats::register_stat + ({ 'type' => "clustered", + 'jobname' => "countries", + 'statname' => "country", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + my $cid = shift; + return undef unless $db && $cid; + + my $upc = LJ::get_prop("user", "country"); + die "Can't find country userprop. Database populated?\n" unless $upc; + + my $tsql = "SELECT MAX(userid) FROM userproplite2"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + my $usertotal = $db->selectrow_array($tsql); + my $blocks = LJ::Stats::num_blocks($usertotal); + + my %ret; + foreach my $block (1..$blocks) { + my ($low, $high) = LJ::Stats::get_block_bounds($block); + + $db = $db_getter->(); # revalidate connection + my $sth = $db->prepare("SELECT u.value, COUNT(*) AS 'count' FROM userproplite2 u " . + "LEFT JOIN clustertrack2 c ON u.userid=c.userid " . + "WHERE u.upropid=? AND u.value<>'' AND u.userid=c.userid " . + "AND u.userid BETWEEN $low AND $high " . + "AND (c.clusterid IS NULL OR c.clusterid=?)" . + "GROUP BY 1 ORDER BY 2"); + $sth->execute($upc->{'id'}, $cid); + die "clusterid: $cid, " . $db->errstr if $db->err; + + while ($_ = $sth->fetchrow_hashref) { + $ret{$_->{'value'}} += $_->{'count'}; + } + + print LJ::Stats::block_status_line($block, $blocks); + } + + return \%ret; + }, + }); + + + LJ::Stats::register_stat + ({ 'type' => "clustered", + 'jobname' => "states", + 'statname' => "stateus", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + my $cid = shift; + return undef unless $db && $cid; + + my $upc = LJ::get_prop("user", "country"); + die "Can't find country userprop. Database populated?\n" unless $upc; + + my $ups = LJ::get_prop("user", "state"); + die "Can't find state userprop. Database populated?\n" unless $ups; + + my $tsql = "SELECT MAX(userid) FROM userproplite2"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + my $usertotal = $db->selectrow_array($tsql); + my $blocks = LJ::Stats::num_blocks($usertotal); + + my %ret; + foreach my $block (1..$blocks) { + my ($low, $high) = LJ::Stats::get_block_bounds($block); + + $db = $db_getter->(); # revalidate connection + my $sth = $db->prepare("SELECT ua.value, COUNT(*) AS 'count' " . + "FROM userproplite2 ua, userproplite2 ub " . + "WHERE ua.userid=ub.userid AND ua.upropid=? AND " . + "ub.upropid=? and ub.value='US' AND ub.value<>'' " . + "AND ua.userid BETWEEN $low AND $high " . + "GROUP BY 1 ORDER BY 2"); + $sth->execute($ups->{'id'}, $upc->{'id'}); + die $db->errstr if $db->err; + + while ($_ = $sth->fetchrow_hashref) { + $ret{$_->{'value'}} += $_->{'count'}; + } + + print LJ::Stats::block_status_line($block, $blocks); + } + + return \%ret; + }, + + }); + + + LJ::Stats::register_stat + ({ 'type' => "clustered", + 'jobname' => "gender", + 'statname' => "gender", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + my $cid = shift; + return undef unless $db && $cid; + + my $upg = LJ::get_prop("user", "gender"); + die "Can't find gender userprop. Database populated?\n" unless $upg; + + my $tsql = "SELECT MAX(userid) FROM userproplite2"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + my $usertotal = $db->selectrow_array($tsql); + my $blocks = LJ::Stats::num_blocks($usertotal); + + my %ret; + foreach my $block (1..$blocks) { + my ($low, $high) = LJ::Stats::get_block_bounds($block); + + $db = $db_getter->(); # revalidate connection + my $sth = $db->prepare("SELECT value, COUNT(*) AS 'count' FROM userproplite2 up " . + "LEFT JOIN clustertrack2 c ON up.userid=c.userid " . + "WHERE up.upropid=? AND up.userid BETWEEN $low AND $high " . + "AND (c.clusterid IS NULL OR c.clusterid=?) GROUP BY 1"); + $sth->execute($upg->{'id'}, $cid); + die "clusterid: $cid, " . $db->errstr if $db->err; + + while ($_ = $sth->fetchrow_hashref) { + $ret{$_->{'value'}} += $_->{'count'}; + } + + print LJ::Stats::block_status_line($block, $blocks); + } + + return \%ret; + }, + + }); + + # run stats + LJ::Stats::run_stats(@which); + + #### dump to text file + print "-I- Dumping to a text file.\n"; + + { + my $dbh = LJ::Stats::get_db("dbh"); + my $sth = $dbh->prepare("SELECT statcat, statkey, statval FROM stats ORDER BY 1, 2"); + $sth->execute; + die $dbh->errstr if $dbh->err; + + open (OUT, ">$LJ::HTDOCS/stats/stats.txt"); + while (my @row = $sth->fetchrow_array) { + next if grep { $row[0] eq $_ } @LJ::PRIVATE_STATS; + print OUT join("\t", @row), "\n"; + } + close OUT; + } + + print "-I- Done.\n"; + +}; + +$maint{'genstats_size'} = sub { + + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "size-accounts", + 'statname' => "size", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + my $tsql = "SELECT MAX(userid) FROM user"; + $tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS; + + # not that this isn't a total of current accounts (some rows may have + # been deleted), but rather a total of accounts ever created + my $size = $db->selectrow_array($tsql); + return { 'accounts' => $size }; + }, + }); + + LJ::Stats::register_stat + ({ 'type' => "clustered", + 'jobname' => "size-accounts_active", + 'statname' => "size", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + my $period = 30; # one month is considered active + my $active = $db->selectrow_array + ("SELECT COUNT(*) FROM clustertrack2 WHERE ". + "timeactive > UNIX_TIMESTAMP()-86400*$period"); + + return { 'accounts_active' => $active }; + }, + }); + + print "-I- Generating account size stats.\n"; + LJ::Stats::run_stats("size-accounts", "size-accounts_active"); + print "-I- Done.\n"; +}; + + +$maint{'genstats_weekly'} = sub +{ + LJ::Stats::register_stat + ({ 'type' => "global", + 'jobname' => "supportrank", + 'statname' => "supportrank", + 'handler' => + sub { + my $db_getter = shift; + return undef unless ref $db_getter eq 'CODE'; + my $db = $db_getter->(); + return undef unless $db; + + my %supportrank; + my $rank = 0; + my $lastpoints = 0; + my $buildup = 0; + + my $sth = $db->prepare + ("SELECT u.userid, SUM(sp.points) AS 'points' " . + "FROM user u, supportpoints sp " . + "WHERE u.userid=sp.userid GROUP BY 1 ORDER BY 2 DESC"); + $sth->execute; + die $db->errstr if $db->err; + + while ($_ = $sth->fetchrow_hashref) { + if ($lastpoints != $_->{'points'}) { + $lastpoints = $_->{'points'}; + $rank += (1 + $buildup); + $buildup = 0; + } else { + $buildup++; + } + $supportrank{$_->{'userid'}} = $rank; + } + + # move old 'supportrank' stat to supportrank_prev + # no API for this :-/ + { + my $dbh = LJ::Stats::get_db("dbh"); + $dbh->do("DELETE FROM stats WHERE statcat='supportrank_prev'"); + $dbh->do("UPDATE stats SET statcat='supportrank_prev' WHERE statcat='supportrank'"); + } + + return \%supportrank; + } + }); + + print "-I- Generating weekly stats.\n"; + LJ::Stats::run_stats('supportrank'); + print "-I- Done.\n"; +}; + +$maint{'build_randomuserset'} = sub +{ + ## this sets up the randomuserset table daily (or whenever) that htdocs/random.bml uses to + ## find a random user that is both 1) publicly listed in the directory, and 2) updated + ## within the past 24 hours. + + ## note that if a user changes their privacy setting to not be in the database, it'll take + ## up to 24 hours for them to be removed from the random.bml listing, but that's acceptable. + + my $dbh = LJ::get_db_writer(); + + print "-I- Building randomuserset.\n"; + $dbh->do("TRUNCATE TABLE randomuserset"); + $dbh->do("REPLACE INTO randomuserset (userid) " . + "SELECT uu.userid FROM userusage uu, user u " . + "WHERE u.userid=uu.userid AND u.allow_infoshow='Y' " . + "AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY RAND() LIMIT 5000"); + my $num = $dbh->selectrow_array("SELECT MAX(rid) FROM randomuserset"); + $dbh->do("REPLACE INTO stats (statcat, statkey, statval) " . + "VALUES ('userinfo', 'randomcount', $num)"); + + print "-I- Done.\n"; +}; + +$maint{'memeclean'} = sub +{ + my $dbh = LJ::get_db_writer(); + + print "-I- Cleaning memes.\n"; + my $sth = $dbh->prepare("SELECT statkey FROM stats WHERE statcat='popmeme'"); + $sth->execute; + die $dbh->errstr if $dbh->err; + + while (my $url = $sth->fetchrow_array) { + my $copy = $url; + LJ::run_hooks("canonicalize_url", \$copy); + unless ($copy) { + my $d = $dbh->quote($url); + $dbh->do("DELETE FROM stats WHERE statcat='popmeme' AND statkey=$d"); + print " deleting: $url\n"; + } + } + print "-I- Done.\n"; +}; + +1; diff --git a/local/bin/maint/synsuck.pl b/local/bin/maint/synsuck.pl new file mode 100755 index 0000000..c6b0e12 --- /dev/null +++ b/local/bin/maint/synsuck.pl @@ -0,0 +1,655 @@ +#!/usr/bin/perl +# + +use strict; +use vars qw(%maint %maintinfo); +use lib "$ENV{'LJHOME'}/cgi-bin"; # extra XML::Encoding files in cgi-bin/XML/* +use LWP::UserAgent; +use XML::RSS; +use HTTP::Status; +use Image::Size; +require "ljprotocol.pl"; +require "parsefeed.pl"; +require "cleanhtml.pl"; +require "talklib.pl"; +require LWPx::ParanoidAgent; +require LJR::unicode; + +use utf8; +binmode STDOUT, ":utf8"; + +my $dumpxml = sub { + my ($xdata, $username) = @_; + + open(my $outfile, ">$ENV{'LJHOME'}/logs/syn_err_" . $username . ".xml"); + print $outfile "$xdata"; + close($outfile); +}; + +my $err = sub { + my ($msg) = @_; + print $msg . "\n"; + return; +}; + +my $get_picture = sub { + my ($userid, $url) = @_; + + my $MAX_UPLOAD = 102400; + + my $ua = LWPx::ParanoidAgent->new(timeout => 30, max_size => $MAX_UPLOAD + 1024); + $ua->agent("Synsuck::Userpic; $LJ::SITENAME; $LJ::ADMIN_EMAIL"); + + my $res = $ua->get($url); + my $picdata = $res->content; + + return $err->("some error while getting userpic") if !($res && $res->is_success); + return $err->("404 while getting userpic") if ($res && $res->{"_rc"} eq 404); + return $err->("userpic size is bigger than we want") if length($picdata) > $MAX_UPLOAD; + + my ($sx, $sy, $filetype) = Image::Size::imgsize(\$picdata); + return $err->("can't ge userpic size") unless defined $sx; + return $err->("unknown userpic filetype") unless $filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG"; + return $err->("userpic is bigger than we want") if $sx > 150 || $sy > 150; + + my $contenttype; + if ($filetype eq "GIF") { $contenttype = 'G'; } + elsif ($filetype eq "PNG") { $contenttype = 'P'; } + elsif ($filetype eq "JPG") { $contenttype = 'J'; } + + my $base64 = Digest::MD5::md5_base64($picdata); + + my $picid = LJ::alloc_global_counter('P') or return; + + my $dbh = LJ::get_db_writer(); + $dbh->do( + "INSERT INTO userpic2" . + "(picid, userid, fmt, width, height, picdate, md5base64, location, state, url) " . + "VALUES (?, ?, ?, ?, ?, NOW(), ?, ?, 'N', ?)", + undef, $picid, $userid, $contenttype, $sx, $sy, $base64, undef, $url); + $dbh->do( + "INSERT INTO userpicblob2 (userid, picid, imagedata) VALUES (?,?,?)", + undef, $userid, $picid, $picdata); + + my $su = LJ::load_userid($userid); + LJ::update_user($su, { defaultpicid => $picid }); +}; + +$maintinfo{'synsuck'}{opts}{locking} = "per_host"; +$maint{'synsuck'} = sub +{ + my $maxcount = shift || 0; + my $verbose = $LJ::LJMAINT_VERBOSE; + + my %child_jobs; # child pid => [ userid, lock ] + + my $process_user = sub { + my $urow = shift; + return unless $urow; + + my ($user, $userid, $synurl, $lastmod, $etag, $lastmod_feed, $readers) = + map { $urow->{$_} } qw(user userid synurl lastmod etag lastmod_feed numreaders); + + # we're a child process now, need to invalidate caches and + # get a new database handle + LJ::start_request(); + + my $dbh = LJ::get_db_writer(); + + # see if things have changed since we last looked and acquired the lock. + # otherwise we could 1) check work, 2) get lock, and between 1 and 2 another + # process could do both steps. we don't want to duplicate work already done. + my $now_checknext = $dbh->selectrow_array("SELECT checknext FROM syndicated ". + "WHERE userid=?", undef, $userid); + return if $now_checknext ne $urow->{checknext}; + + my $ua = LWP::UserAgent->new("timeout" => 30); + my $reader_info = $readers ? "; $readers readers" : ""; + $ua->agent("$LJ::SITENAME ($LJ::ADMIN_EMAIL; for $LJ::SITEROOT/users/$user/" . $reader_info . ")"); + + my $delay = sub { + my $minutes = shift; + my $status = shift; + + # add some random backoff to avoid waves building up + $minutes += int(rand(5)); + + $dbh->do("UPDATE syndicated SET lastcheck=NOW(), checknext=DATE_ADD(NOW(), ". + "INTERVAL ? MINUTE), laststatus=? WHERE userid=?", + undef, $minutes, $status, $userid); + }; + + print "[$$] Synsuck: fetching $user ($synurl)\n" if $verbose; + + my $req = HTTP::Request->new("GET", $synurl); + $req->header('If-Modified-Since', $lastmod) + if $lastmod; + $req->header('If-None-Match', $etag) + if $etag; + + my ($content, $too_big); + my $max_size = $LJ::SYNSUCK_MAX_SIZE || 500; # in kb + my $res = eval { + $ua->request($req, sub { + if (length($content) > 1024*$max_size) { $too_big = 1; return; } + $content .= $_[0]; + }, 4096); + }; + if ($@) { $delay->(120, "lwp_death"); return; } + if ($too_big) { $delay->(60, "toobig"); return; } + + if ($res->is_error()) { + # http error + print " HTTP error! " . $res->status_line() . "\n" if $verbose; + + $delay->(3*60, "httperror"); + + # overload rssparseerror here because it's already there -- we'll + # never have both an http error and a parse error on the + # same request + + LJ::set_userprop($userid, "rssparseerror", $res->status_line()); + return; + } + + # check if not modified + if ($res->code() == RC_NOT_MODIFIED) { + print " not modified.\n" if $verbose; + $delay->($readers ? 30 : 12*60, "notmodified"); + return; + } + + my $r_lastmod = $res->header('Last-Modified'); + my $r_etag = $res->header('ETag'); + + # check again (feedburner.com, blogspot.com, etc.) + if (($etag && $etag eq $r_etag) || ($lastmod && $lastmod eq $r_lastmod)) { + print " not modified.\n" if $verbose; + $delay->($readers ? 30 : 12*60, "notmodified"); + return; + } + + # force utf8; this helps from time to time ??? + LJR::unicode::force_utf8(\$content); + + # parsing time... + my ($feed, $error) = LJ::ParseFeed::parse_feed($content); + if ($error) { + # parse error! + print "Parse error! $error\n" if $verbose; + $delay->(3*60, "parseerror"); + $error =~ s! at /.*!!; + $error =~ s/^\n//; # cleanup of newline at the beggining of the line + LJ::set_userprop($userid, "rssparseerror", $error); + $dumpxml->($content, $user); + return; + } + + my $r_lastmod_feed = $feed->{'lastmod'}; + my $r_lastmod_lastBuildDate = $feed->{'lastBuildDate'}; + + print " $lastmod \n $r_lastmod \n $etag \n $r_etag \n $lastmod_feed \n $r_lastmod_feed \n $r_lastmod_lastBuildDate \n "; + + # check last-modified for bogus web-servers + if ($lastmod_feed && $lastmod_feed eq $r_lastmod_feed) { + print " not modified..\n" if $verbose; + $delay->($readers ? 30 : 12*60, "notmodified"); + return; + } + +# print " $lastmod \n $r_lastmod \n $etag \n $r_etag \n $lastmod_feed \n $r_lastmod_feed \n $r_lastmod_lastBuildDate \n "; + + # another sanity check + unless (ref $feed->{'items'} eq "ARRAY") { + $delay->(3*60, "noitems"); + return; + } + + # update userpic + my $cur_pic = $dbh->selectrow_array( + "SELECT url FROM userpic2, user WHERE user.userid=? and + userpic2.userid=user.userid and userpic2.picid=user.defaultpicid", + undef, $userid); + if ( + ($feed->{'image'} && $cur_pic && $cur_pic ne $feed->{'image'}) || + ($feed->{'image'} && !$cur_pic) + ) { + $dbh->do("delete from userpic2 WHERE userid=?", undef, $userid); + $dbh->do("delete from userpicblob2 WHERE userid=?", undef, $userid); + $dbh->do("update user set user.defaultpicid=NULL where userid=?", undef, $userid); + + print "[$$] Synsuck: $user -- trying to fetch userpic from: " . + $feed->{'image'} . " \n" if $verbose; + + $get_picture->($userid, $feed->{'image'}); + } + + my @items = reverse @{$feed->{'items'}}; + + + # delete existing items older than the age which can show on a + # friends view. + my $su = LJ::load_userid($userid); + my $udbh = LJ::get_cluster_master($su); + unless ($udbh) { + $delay->(15, "nodb"); + return; + } + + # TAG:LOG2:synsuck_delete_olderitems +# my $secs = ($LJ::MAX_FRIENDS_VIEW_AGE || 3600*24*14)+0; # 2 week default. +# my $sth = $udbh->prepare("SELECT jitemid, anum FROM log2 WHERE journalid=? AND ". +# "logtime < DATE_SUB(NOW(), INTERVAL $secs SECOND)"); +# $sth->execute($userid); +# die $udbh->errstr if $udbh->err; +# while (my ($jitemid, $anum) = $sth->fetchrow_array) { +# print "DELETE itemid: $jitemid, anum: $anum... \n" if $verbose; +# if (LJ::delete_entry($su, $jitemid, 0, $anum)) { +# print "success.\n" if $verbose; +# } else { +# print "fail.\n" if $verbose; +# } +# } + + + my $count = $udbh->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=$userid"); + print "count = $count \n"; + + my $extra = $count - $LJ::MAX_SCROLLBACK_FRIENDS_SINGLE_USER_ACTIVITY; + if ($extra > 0) { + my $sth = $udbh->prepare("SELECT jitemid FROM logprop2 WHERE journalid=$userid". + " ORDER BY jitemid ASC LIMIT $extra"); + $sth->execute(); + while (my ($jitemid) = $sth->fetchrow_array) { + + print "DELETE itemid: $jitemid... \n" if $verbose; + if (LJ::delete_entry($su, $jitemid)) { + print "success.\n" if $verbose; + } else { + print "fail.\n" if $verbose; + } + } + } + + # determine if link tags are good or not, where good means + # "likely to be a unique per item". some feeds have the same + # element for each item, which isn't good. + # if we have unique ids, we don't compare link tags + + my ($compare_links, $have_ids) = 0; + { + my %link_seen; + foreach my $it (@items) { + $have_ids = 1 if $it->{'id'}; + next unless $it->{'link'}; + $link_seen{$it->{'link'}} = 1; + } + $compare_links = 1 if !$have_ids and $feed->{'type'} eq 'rss' and + scalar(keys %link_seen) == scalar(@items); + } + + # if we have unique links/ids, load them for syndicated + # items we already have on the server. then, if we have one + # already later and see it's changed, we'll do an editevent + # instead of a new post. + my %existing_item = (); + if ($have_ids || $compare_links) { + my $p = $have_ids ? LJ::get_prop("log", "syn_id") : + LJ::get_prop("log", "syn_link"); + my $sth = $udbh->prepare("SELECT jitemid, value FROM logprop2 WHERE ". + "journalid=? AND propid=? ORDER BY jitemid DESC LIMIT 1000"); # need last 100 + $sth->execute($su->{'userid'}, $p->{'id'}); + + while (my ($jitemid, $id) = $sth->fetchrow_array) { + + if (!defined $existing_item{$id}) { + $existing_item{$id} = $jitemid; +# print "Got it: $jitemid, $id\n" if $verbose; + } else { + # remove duplicates - if any: + print "DELETE duplicated itemid: $jitemid, $id ...\n" if $verbose; + if (LJ::delete_entry($su, $jitemid)) { + print "success.\n" if $verbose; + } else { + print "fail.\n" if $verbose; + } + } + } + } + + # post these items + my $newcount = 0; + my $errorflag = 0; + my $mindate; # "yyyy-mm-dd hh:mm:ss"; + my $notedate = sub { + my $date = shift; + $mindate = $date if ! $mindate || $date lt $mindate; + }; + + LJ::load_user_props($su, { use_master => 1 }, "newesteventtime"); + ### if ($su->{'newesteventtime'} eq $oldevent->{'eventtime'}) { + ### LJ::set_userprop($su, "newesteventtime", undef); + ### } + + foreach my $it (@items) { + + if ($it->{'time'} && $it->{'time'} lt $su->{'newesteventtime'}) { +## print "---- " . $it->{'subject'} . "\n" if $verbose; + next; + } elsif ($it->{'time'} && $it->{'time'} eq $su->{'newesteventtime'}) { + print "==== " . $it->{'subject'} . "\n" if $verbose; + } else { + print "++++ " . $it->{'subject'} . "\n" if $verbose; + } + + + my $dig = LJ::md5_struct($it)->b64digest; + my $prevadd = $dbh->selectrow_array("SELECT MAX(dateadd) FROM synitem WHERE ". + "userid=? AND item=?", undef, + $userid, $dig); + if ($prevadd) { + $notedate->($prevadd); + next; + } + + my $now_dateadd = $dbh->selectrow_array("SELECT NOW()"); + die "unexpected format" unless $now_dateadd =~ /^\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d$/; + + $dbh->do("INSERT INTO synitem (userid, item, dateadd) VALUES (?,?,?)", + undef, $userid, $dig, $now_dateadd); + $notedate->($now_dateadd); + + $newcount++; + print "[$$] $dig - $it->{'subject'}\n" if $verbose; + $it->{'text'} =~ s/^\s+//; + $it->{'text'} =~ s/\s+$//; + + # process lj-cuts + while ($it->{'text'} =~ /\G(.*?)\<\/a\>(.*)/sg) { + my $before = $1; + my $cutid = $2; + my $rcut = $3; + $rcut =~ s/\<\/a\>/\<\/lj\-cut\>/; + $it->{'text'} = $before . "" . $rcut; + } + + my $htmllink; + if (defined $it->{'link'}) { + $htmllink = ""; + } + + # Show the link if it's present and different than the + # . + # [zilla: 267] Patch: Chaz Meyers + if ( defined $it->{'id'} && $it->{'id'} ne $it->{'link'} + && $it->{'id'} =~ m!^http://! ) + { + $htmllink .= ""; + } + + # rewrite relative URLs to absolute URLs, but only invoke the HTML parser + # if we see there's some image or link tag, to save us some work if it's + # unnecessary (the common case) + if ($it->{'text'} =~ /<(?:img|a)\b/i) { + # TODO: support XML Base? http://www.w3.org/TR/xmlbase/ + my $base_href = $it->{'link'} || $synurl; + LJ::CleanHTML::resolve_relative_urls(\$it->{'text'}, $base_href); + } + + + + # $own_time==1 means we took the time from the feed rather than localtime + my ($own_time, $year, $mon, $day, $hour, $min); + + if ($it->{'time'} && + $it->{'time'} =~ m!^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)!) { + $own_time = 1; + ($year, $mon, $day, $hour, $min) = ($1,$2,$3,$4,$5); + } else { + $own_time = 0; + my @now = localtime(); + ($year, $mon, $day, $hour, $min) = + ($now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1]); + } + + + my $command = "postevent"; + my $req = { + 'username' => $user, + 'ver' => 1, + 'subject' => $it->{'subject'}, + 'event' => "$it->{'text'}", + 'year' => $year, + 'mon' => $mon, + 'day' => $day, + 'hour' => $hour, + 'min' => $min, + 'props' => { + 'syn_link' => $it->{'link'}, + 'opt_nocomments' => 1, + }, + }; + $req->{'props'}->{'syn_id'} = $it->{'id'} + if $it->{'id'}; + + my $flags = { + 'nopassword' => 1, + }; + + # if the post contains html linebreaks, assume it's preformatted. + if ($it->{'text'} =~ /<(?:p|br)\b/i) { + $req->{'props'}->{'opt_preformatted'} = 1; + } + + # do an editevent if we've seen this item before + my $id = $have_ids ? $it->{'id'} : $it->{'link'}; + my $old_itemid = $existing_item{$id}; + if ($id && $old_itemid) { + $newcount--; # cancel increment above + $command = "editevent"; + $req->{'itemid'} = $old_itemid; + + # the editevent requires us to resend the date info, which + # we have to go fetch first, in case the feed doesn't have it + + # TAG:LOG2:synsuck_fetch_itemdates + unless($own_time) { + my $origtime = + $udbh->selectrow_array("SELECT eventtime FROM log2 WHERE ". + "journalid=? AND jitemid=?", undef, + $su->{'userid'}, $old_itemid); + $origtime =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/; + $req->{'year'} = $1; + $req->{'mon'} = $2; + $req->{'day'} = $3; + $req->{'hour'} = $4; + $req->{'min'} = $5; + } + } + + my $err; + + my $res = LJ::Protocol::do_request($command, $req, \$err, $flags); + + unless ($res && ! $err) { + print " Error: $err\n" if $verbose; + $errorflag = 1; + } + } + + # delete some unneeded synitems. the limit 1000 is because + # historically we never deleted and there are accounts with + # 222,000 items on a myisam table, and that'd be quite the + # delete hit. + # the 14 day interval is because if a remote site deleted an + # entry, it's possible for the oldest item that was previously + # gone to reappear, and we want to protect against that a + # little. + if ($LJ::SYNITEM_CLEAN) { + $dbh->do("DELETE FROM synitem WHERE userid=? AND ". + "dateadd < ? - INTERVAL 14 DAY LIMIT 1000", + undef, $userid, $mindate); + } + $dbh->do("UPDATE syndicated SET oldest_ourdate=? WHERE userid=?", + undef, $mindate, $userid); + + # bail out if errors, and try again shortly + if ($errorflag) { + $delay->(30, "posterror"); + return; + } + + # update syndicated account's userinfo if necessary + LJ::load_user_props($su, "url", "urlname"); + { + my $title = $feed->{'title'}; + $title = $su->{'user'} unless LJ::is_utf8($title); + $title =~ s/[\n\r]//g; + if ($title && $title ne $su->{'name'}) { + LJ::update_user($su, { name => $title }); + } + if ($title) { + LJ::set_userprop($su, "urlname", $title); + } else { + LJ::set_userprop($su, "urlname", $su->{'url'}); + } + + my $link = $feed->{'link'}; + if ($link && $link ne $su->{'url'}) { + LJ::set_userprop($su, "url", $link); + } + + my $des = $feed->{'description'}; + if ($des) { + my $bio; + if ($su->{'has_bio'} eq "Y") { + $bio = $udbh->selectrow_array("SELECT bio FROM userbio WHERE userid=?", undef, + $su->{'userid'}); + } + if ($bio ne $des && $bio !~ /\[LJ:KEEP\]/) { + if ($des) { + $su->do("REPLACE INTO userbio (userid, bio) VALUES (?,?)", undef, + $su->{'userid'}, $des); + } else { + $su->do("DELETE FROM userbio WHERE userid=?", undef, $su->{'userid'}); + } + LJ::update_user($su, { has_bio => ($des ? "Y" : "N") }); + LJ::MemCache::delete([$su->{'userid'}, "bio:$su->{'userid'}"]); + } + } + } + + # decide when to poll next (in minutes). + # FIXME: this is super lame. (use hints in RSS file!) + my $int = $newcount ? 15 : 30; + my $status = $newcount ? "ok" : "nonew"; + my $updatenew = $newcount ? ", lastnew=NOW()" : ""; + + # update reader count while we're changing things, but not + # if feed is stale (minimize DB work for inactive things) + if ($newcount || ! defined $readers) { + $readers = $dbh->selectrow_array("SELECT COUNT(*) FROM friends WHERE ". + "friendid=?", undef, $userid); + } + + # if readers are gone, don't check for a whole day + $int = 60*24 if $readers && $readers < 2 || !$readers; + + $dbh->do("UPDATE syndicated SET checknext=DATE_ADD(NOW(), INTERVAL $int MINUTE), ". + "lastcheck=NOW(), lastmod=?, etag=?, lastmod_feed=? , laststatus=?, numreaders=? $updatenew ". + "WHERE userid=$userid", undef, $r_lastmod, $r_etag, $r_lastmod_feed, $status, $readers); + }; + + ### + ### child process management + ### + + # get the next user to be processed + my @all_users; + my $get_next_user = sub { + return shift @all_users if @all_users; + + # need to get some more rows + my $dbh = LJ::get_db_writer(); + my $current_jobs = join(",", map { $dbh->quote($_->[0]) } values %child_jobs); + my $in_sql = " AND u.userid NOT IN ($current_jobs)" if $current_jobs; + my $sth = $dbh->prepare("SELECT u.user, s.userid, s.synurl, s.lastmod, " . + " s.etag, s.lastmod_feed, s.numreaders, s.checknext " . + "FROM user u, syndicated s " . + "WHERE u.userid=s.userid AND u.statusvis='V' " . + "AND s.checknext < NOW()$in_sql " . + "ORDER BY RAND() LIMIT 500"); + $sth->execute; + while (my $urow = $sth->fetchrow_hashref) { + push @all_users, $urow; + } + + return undef unless @all_users; + return shift @all_users; + }; + + # fork and manage child processes + my $max_threads = $LJ::SYNSUCK_MAX_THREADS || 1; + print "[$$] PARENT -- using $max_threads workers\n" if $verbose; + + my $threads = 0; + my $userct = 0; + my $keep_forking = 1; + while ( $maxcount == 0 || $userct < $maxcount ) { + + if ($threads < $max_threads && $keep_forking) { + my $urow = $get_next_user->(); + unless ($urow) { + $keep_forking = 0; + next; + } + + my $lockname = "synsuck-user-" . $urow->{user}; + my $lock = LJ::locker()->trylock($lockname); + next unless $lock; + print "Got lock on '$lockname'. Running\n" if $verbose; + + # spawn a new process + if (my $pid = fork) { + # we are a parent, nothing to do? + $child_jobs{$pid} = [$urow->{'userid'}, $lock]; + $threads++; + $userct++; + } else { + # handles won't survive the fork + LJ::disconnect_dbs(); + $process_user->($urow); + exit 0; + } + + # wait for child(ren) to die + } else { + my $child = wait(); + last if $child == -1; + delete $child_jobs{$child}; + $threads--; + } + } + + # Now wait on any remaining children so we don't leave zombies behind. + while ( %child_jobs ) { + my $child = wait(); + last if $child == -1; + delete $child_jobs{ $child }; + $threads--; + } + + print "[$$] $userct users processed\n" if $verbose; + return; +}; + +1; + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/local/bin/maint/taskinfo.txt b/local/bin/maint/taskinfo.txt new file mode 100755 index 0000000..cc0f7b4 --- /dev/null +++ b/local/bin/maint/taskinfo.txt @@ -0,0 +1,30 @@ +bday.pl: + bdaymail - Sends people birthday wishes & notifications + +stats.pl: + build_randomuserset - builds/cleans table of users applicable for inclusion in random listings + genstats - Generates the nightly statistics + genstats_size - Generates the site size stats + genstats_weekly - Generates the weekly statistics + memeclean - Removes things from meme summary that are excluded by new URL cleaner rules + +statspics.pl: + genstatspics - Makes a bunch of graphs to show on the statistics page. + +clean_caches.pl: + clean_caches - removes old cache files + +synsuck.pl: + synsuck - Polls needed remote, syndicated RSS/etc and updates journals. + +captcha.pl: + gen_audio_captchas - Generate any needed new audio challenges. + gen_image_captchas - Generate any needed new graphical challenges. + clean_captchas - Purge old challenges from the database. + +generic.pl: + joinmail - Generates daily email digests for community join requests + clean_spamreports - Clean out data from the spamreports table older than 90 days. + +clean_challenges.pl: + clean_challenges - Deletes old records from challenges table diff --git a/local/bin/qbufferd.pl b/local/bin/qbufferd.pl new file mode 100755 index 0000000..55addb9 --- /dev/null +++ b/local/bin/qbufferd.pl @@ -0,0 +1,254 @@ +#!/usr/bin/perl +# +# +# lib: Proc::ProcessTable, cgi-bin/ljlib.pl +# + +use strict; +use Getopt::Long +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/supportlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl"; +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl"; + +my $opt_foreground; +my $opt_debug; +my $opt_stop; +exit 1 unless GetOptions('foreground' => \$opt_foreground, + 'debug' => \$opt_debug, + 'stop' => \$opt_stop, + ); + +BEGIN { + $LJ::OPTMOD_PROCTABLE = eval "use Proc::ProcessTable; 1;"; +} + +my $DELAY = $LJ::QBUFFERD_DELAY || 15; + +my $pidfile = $LJ::QBUFFERD_PIDFILE || "$ENV{'LJHOME'}/var/qbufferd.pid"; +my $pid; +if (-e $pidfile) { + open (PID, $pidfile); + chomp ($pid = ); + close PID; + if ($opt_stop) { + if (kill 15, $pid) { + print "Shutting down qbufferd.\n"; + } else { + print "qbufferd not running?\n"; + } + exit; + } + + if ($LJ::OPTMOD_PROCTABLE) { + my $processes = Proc::ProcessTable->new()->table; + if (grep { $_->cmndline =~ /perl.+qbufferd/ && $_->pid != $$ } @$processes) { + exit; + } + } else { + if (kill 0, $pid) { + # seems to still be running (at least something is with that pid) + exit; + } + } +} +if ($opt_stop) { + print "qbufferd not running?\n"; + exit; +} + +$SIG{'INT'} = \&stop_qbufferd; +$SIG{'TERM'} = \&stop_qbufferd; +$SIG{'HUP'} = sub { + # nothing. maybe later make a HUP force a flush? +}; + +if (!$opt_foreground && ($pid = fork)) +{ + unless (open (PID, ">$pidfile")) { + kill 15, $pid; + die "Couldn't write PID file. Exiting.\n"; + } + print PID $pid, "\n"; + close PID; + print "qbufferd started with pid $pid\n"; + if (-s $pidfile) { print "pid file written ($pidfile)\n"; } + exit; +} + +# Close filehandles unless running in --debug or --foreground mode. +unless ( $opt_debug || $opt_foreground ) { + close STDIN && open STDIN, "&STDIN"; + close STDERR && open STDERR, "+>&STDIN"; +} + +# fork off a separate qbufferd process for all specified +# job types in @LJ::QBUFFERD_ISOLATE, and then +# another process for all other job types. The current process +# will keep tabs on all of those + +my %isolated; +my %pids; # job -> pid +my %jobs; # pid -> job +my $working = 0; # 1 for processes that do actual work + +my $my_job; + +foreach my $job (@LJ::QBUFFERD_ISOLATE) { + $isolated{$job} = 1; +} + +foreach my $job (@LJ::QBUFFERD_ISOLATE, "_others_") { + if (my $child = fork) { + # parent. + $pids{$job} = $child; + $jobs{$child} = $job; + next; + } else { + # child. + $0 .= " [$job]"; + $my_job = $job; + $working = 1; + last; + } +} + +# at this point, $my_job is either the specialized 'cmd' to run, or +# '_others_' to mean everything besides stuff with their own processes. +# $working is 1 for nonempty values of $my_job . + +sub stop_qbufferd +{ + # stop children + unless ($working) { + foreach my $job (keys %pids) { + my $child = $pids{$job}; + print "Killing child pid $child job: $job\n" if $opt_debug; + kill 15, $child; + } + + unlink $pidfile; + } + + print "Quitting: " . ($working ? "job $my_job" : "parent") . "\n" if $opt_debug; + exit; +} + + +while(not $working) { + # controlling process's cycle + my $pid; + + $pid = wait(); + + print "Child exited, pid $pid, job $jobs{$pid}\n" if $opt_debug; + if ($jobs{$pid}) { + my $job = $jobs{$pid}; + print "Restarting job $job\n" if $opt_debug; + delete $pids{$job}; + delete $jobs{$pid}; + if (my $child = fork) { + # parent. + $pids{$job} = $child; + $jobs{$child} = $job; + } else { + # child. + $0 .= " [$job]"; + $my_job = $job; + $working = 1; # go work + } + } +} + +# the actual work begins here +my @all_jobs = qw(delitem weblogscom send_mail support_notify dirty); +foreach my $hook (keys %LJ::HOOKS) { + next unless $hook =~ /^cmdbuf:(\w+):run$/; + push @all_jobs, $1; +} + +while (LJ::start_request()) +{ + my $cycle_start = time(); + print "Starting cycle. Job $my_job\n" if $opt_debug; + + # syndication (checks RSS that need to be checked) + if ($my_job eq "synsuck") { + system("$ENV{'LJHOME'}/bin/ljmaint.pl", "-v0", "synsuck"); + print "Sleeping. Job $my_job\n" if $opt_debug; + my $elapsed = time() - $cycle_start; + sleep ($DELAY-$elapsed) if $elapsed < $DELAY; + next; + } + + # do main cluster updates + my $dbh = LJ::get_dbh("master"); + unless ($dbh) { + sleep 10; + next; + } + + # keep track of what commands we've run the start hook for + my %started; + + # handle clusters + foreach my $c (@LJ::CLUSTERS) { + print "Cluster: $c Job: $my_job\n" if $opt_debug; + my $db = LJ::get_cluster_master($c); + next unless $db; + + my @check_jobs = ($my_job); + if ($my_job eq "_others_") { @check_jobs = grep { ! $isolated{$_} } @all_jobs; } + + foreach my $cmd (@check_jobs) { + my $have_jobs = $db->selectrow_array("SELECT cbid FROM cmdbuffer WHERE cmd=? LIMIT 1", + undef, $cmd); + next unless $have_jobs; + + print " Starting $cmd...\n" if $opt_debug; + unless ($started{$cmd}++) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:start"); + } + LJ::Cmdbuffer::flush($dbh, $db, $cmd); + print " Finished $cmd.\n" if $opt_debug; + + # monitor process size and job counts to suicide if necessary + my $size = 0; + if (open(S, "/proc/$$/status")) { + my $file; + { local $/ = undef; $file = ; } + $size = $1 if $file =~ /VmSize:.+?(\d+)/; + close S; + } + + # is it our time to go? + my $kill_job_ct = LJ::Cmdbuffer::get_property($cmd, 'kill_job_ct') || 0; + my $kill_mem_size = LJ::Cmdbuffer::get_property($cmd, 'kill_mem_size') || 0; + if ($kill_job_ct && $started{$cmd} >= $kill_job_ct || + $kill_mem_size && $size >= $kill_mem_size) + { + + # trigger reload of current child process + print "Job suicide: $cmd. (size=$size, rpcs=" . ($started{dirty}+0) . ")\n" + if $opt_debug; + + # run end hooks before dying + foreach my $cmd (keys %started) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish"); + } + + exit 0; + } + } + } + + # run the end hook for all commands we've run + foreach my $cmd (keys %started) { + LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish"); + } + + print "Sleeping. Job $my_job\n" if $opt_debug; + my $elapsed = time() - $cycle_start; + sleep ($DELAY-$elapsed) if $elapsed < $DELAY; +}; diff --git a/local/bin/upgrading/en.dat b/local/bin/upgrading/en.dat new file mode 100755 index 0000000..624d97a --- /dev/null +++ b/local/bin/upgrading/en.dat @@ -0,0 +1,5240 @@ +;; -*- coding: utf-8 -*- +#/talkpost.bml.opt.ljuser=LJR user: + +#/talkpost.bml.opt.ljuser2=LJR user + +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Change Status + +/accountstatus.bml.error.db=There has been a database error processing your request. + +/accountstatus.bml.error.invalid=Invalid status type + +/accountstatus.bml.error.nochange.expunged=This account has been purged from the system. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Cannot change journal status from suspended. + +/accountstatus.bml.header.success=Success + +/accountstatus.bml.journalstatus.about=If you want to delete or undelete your journal, this is where you do it. Once you delete your journal you have 30 days to undelete it, just in case you change your mind. After 30 days, the journal will be permanently deleted and there will be no way to recover it. + +/accountstatus.bml.journalstatus.head=Journal Activation Status + +/accountstatus.bml.journalstatus.select.activated=Activated + +/accountstatus.bml.journalstatus.select.deleted=Deleted + +/accountstatus.bml.journalstatus.select.head=Status: + +/accountstatus.bml.journalstatus.select.suspended=Suspended + +/accountstatus.bml.message.nochange=Your journal status has been left as [[statusvis]]. + +/accountstatus.bml.message.success=Your journal status has been successfully changed to [[statusvis]]. + +/accountstatus.bml.title=Account Status + +/allpics.bml.current=Current Pictures + +/allpics.bml.default=Default + +/allpics.bml.edit2=You may be interested in editing your picture keywords or uploading a new picture. + +/allpics.bml.error.noparam=You need to specify a user parameter. + +/allpics.bml.keywords=Keywords: + +/allpics.bml.nopics.text.other=This user has not uploaded any user pictures. + +/allpics.bml.nopics.text2=You have no pictures uploaded. To upload one, go here. + +/allpics.bml.nopics.title=No Pictures + +/allpics.bml.pics=Here are the user pictures for [[user]]. + +/allpics.bml.title=User Pictures + +/approve.bml.comm.success=Success + +/approve.bml.comm.text<< +You have been added to [[comm]]. +Click here to add the community to your friends list. +. + +/approve.bml.commjoin.text<< +You have approved the membership request of [[user]] in [[comm]]. +Click here to visit the member list for this community to set +other options for this user. +. + +/approve.bml.error.actionperformed=This action has already been performed + +/approve.bml.error.approving=There was an error approving this request to join. + +/approve.bml.error.internerr.invalidaction=Internal error: invalid action + +/approve.bml.error.invalidargument=Invalid argument given + +/approve.bml.error.unknownactiontype=Unknown action type + +/approve.bml.shared.success=Success + +/approve.bml.shared.text<< +You have been given posting access to [[shared]]. +Click here to add the shared journal to your friends list. +. + +/approve.bml.title=Action Approval + +/birthdays.bml.description=Below are the birthdays for everyone that you list as a friend. + +/birthdays.bml.description.others=Below are the birthdays for everyone that [[user]] lists as a friend. + +/birthdays.bml.error.badstatus=[[user]] is not a currently active account. + +/birthdays.bml.error.invaliduser=Invalid user: [[user]]. The specified account does not exist. + +/birthdays.bml.findothers=If you would like to see the birthdays of the friends of another user, or of the members of a community, enter a username below: + +/birthdays.bml.nobirthdays=There are no birthdays to display. This happens when a user doesn't have anyone added to their Friends list, or if none of the user's friends list their birthday publically. + +/birthdays.bml.title=Birthdays + +/birthdays.bml.view=View + +/changepassword.bml.btn.proceed=Proceed + +/changepassword.bml.changepassword.header=Change Password + +/changepassword.bml.changepassword.instructions=Fill out the form below to change your password. + +/changepassword.bml.email.body<< +Your password has been changed at [[sitename]]. + +To retrieve it in the future, visit: + + [[siteroot]]/lostinfo.bml + +Regards, +[[sitename]] Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Change of Password + +/changepassword.bml.error.badcheck=Bad new password: [[error]] + +/changepassword.bml.error.badnewpassword=Your new passwords do not match. Retype both again... you made a typo on one of them. + +/changepassword.bml.error.badoldpassword=Your old password is not correct. + +/changepassword.bml.error.blankpassword=Your new password cannot be blank. + +/changepassword.bml.error.changetestaccount=Cannot change the test account's password. + +/changepassword.bml.error.characterlimit=Passwords are limited to a maximum of 30 characters. + +/changepassword.bml.error.invaliduser=Invalid user [[user]]. This user does not exist. Are you sure you typed it correctly? + +/changepassword.bml.error.mustenterusername=You must enter your username. + +/changepassword.bml.error.nonascii=Passwords are restricted to ASCII symbols. Please choose a password that does not use non-ASCII symbols. + +/changepassword.bml.error.notvalidated=You cannot change your password if your current email address has not been validated. + +/changepassword.bml.newpassword=New Password: + +/changepassword.bml.newpasswordagain=New Password (again): + +/changepassword.bml.oldpassword=Old Password: + +/changepassword.bml.proceed.instructions=Press the button below and your password will be changed. You will receive an email as well, noting the password change. + +/changepassword.bml.relogin=In addition, you have been logged out from all your existing sessions. You should log in again before continuing. + +/changepassword.bml.success.text=Your password has been changed and email has been sent to you with a reminder message. + +/changepassword.bml.title=Change Password + +/community/create.bml.btn.create=Create Community + +/community/create.bml.btn.proceed=Proceed... + +/community/create.bml.create.text=Creating a new community is easy, just follow the instructions below. + +/community/create.bml.error.notactive=Your account must be active in order to create a community. Please make sure your account is not currently marked as deleted or suspended and try again. + +/community/create.bml.error.notperson=You must be logged in as a personal account to create a community. + +/community/create.bml.error.postrequired=POST required. + +/community/create.bml.error.username.inuse=Account name already in use; please select a different one. + +/community/create.bml.error.username.mustenter=You must enter an account name. + +/community/create.bml.error.username.reserved=Sorry, that is a reserved account name. + +/community/create.bml.errors.label=Please note the following problems and resubmit: + +/community/create.bml.name.head=Community Name + +/community/create.bml.name.text=What's the name of this community? This will appear at the top of the community, and in the user directory should you choose to list the community in it. + +/community/create.bml.person=Would you rather create a personal journal? + +/community/create.bml.success.btn.enterinfo=Enter Community Information + +/community/create.bml.success.head=Success! + +/community/create.bml.success.text1=Your community has been created. Additionally, your account has been made an administrator of it. + +/community/create.bml.success.text2=Your community will be available at: + +/community/create.bml.success.text3=Now, please take the time to fill in some information about the community. It's mostly optional, but it lets other users have an idea of what this community is for. + +/community/create.bml.title=Create New Community + +/community/create.bml.username.charsallowed=The community account name may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_). Additionally, it must not be longer than 15 characters. + +/community/create.bml.username.head=Account name + +/community/create.bml.username.text=Each [[sitename]] account must have their own unique account name. The account name is what appears in the address to the community. + +/community/index.bml.main<< + + + + + + +

    Create a Community Now!

    +. + +/community/index.bml.title=Community Center + +/community/join.bml.button.join=Join Community + +/community/join.bml.error.already.member=You are already a member of this community. + +/community/join.bml.error.closed=This community is closed to new members. If you wish to join, please contact one of the following maintainers: [[admins]] + +/community/join.bml.error.statusvis.body=The account you are logged in as is not an active account. + +/community/join.bml.error.statusvis.title=Unable to Join Communities + +/community/join.bml.label.addtofriends=Add "[[maintainer]]" to friends list.
    + +/community/join.bml.label.allowposting=This community allows posting by all members, so you now have access to post in it. If you already have a LiveJournal client open on your computer, you'll have to log out and log back in for this journal to show up in your list of journals you can post to. + +/community/join.bml.label.auth=Although you are now listed as a member, this community only allows posting by authorized users. Contact one of the maintainers if you desire posting access. Below is the list of maintainers for this community: [[admins]] + +/community/join.bml.label.banned=The maintainer(s) of this community have banned you from joining. + +/community/join.bml.label.closed=This community is closed. If you're interested in joining it, please contact one of its maintainers. Below is the list of maintainers for this community: [[admins]] + +/community/join.bml.label.commlogged=You're logged in as a shared/community account, not your personal account. + +/community/join.bml.label.errorcomminfo=The specified community information is not valid. + +/community/join.bml.label.expls=Press the button below to join the "[[maintainer]]" community. Uncheck the box below if you want to join the community without seeing community entries on your friends page. + +/community/join.bml.label.loginfirst=To join a community you must first log in. + +/community/join.bml.label.membernow=You are now a member of the [[commname]] Community + +/community/join.bml.label.sure=You sure? + +/community/join.bml.reqsubmitted.body=Your request to join has been submitted to the maintainers: + +/community/join.bml.reqsubmitted.title=Join Request Submitted + +/community/join.bml.request.body=The [[comm]] community does not have open membership. Please verify that you wish to join this community by clicking below. + +/community/join.bml.request.reason=Optionally, enter a reason you would like to join this community: + +/community/join.bml.request.title=Request to Join + +/community/join.bml.success=Success + +/community/join.bml.title=Join Community + +/community/leave.bml.button.leave=Leave Community + +/community/leave.bml.label.buttontoleave=Press the button below to leave the "[[commname]]" community. + +/community/leave.bml.label.infoerror=The specified community information is not valid. + +/community/leave.bml.label.lastmaintainer=You are not allowed to leave this community because you are the sole maintainer. If you wish to leave the community, please appoint another maintainer and then try leaving again. + +/community/leave.bml.label.logoutfirst=To leave a community you must first log in. + +/community/leave.bml.label.removed=You are now removed from the [[commname]] Community + +/community/leave.bml.label.removefromfriends=Also remove "[[user]]" from friends list. + +/community/leave.bml.success=Success + +/community/leave.bml.sure=You sure? + +/community/leave.bml.title=Leave Community + +/community/manage.bml.commlist.actinfo=Info + +/community/manage.bml.commlist.actinvites=Invitations + +/community/manage.bml.commlist.actions=Actions + +/community/manage.bml.commlist.actmembers=[Members] + +/community/manage.bml.commlist.actmembers2=Members + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] pending + +/community/manage.bml.commlist.actsettings=[Settings] + +/community/manage.bml.commlist.actsettings2=Settings + +/community/manage.bml.commlist.header=Your communities + +/community/manage.bml.commlist.moderation=Awaiting Moderation + +/community/manage.bml.commlist.moderation.num=[[[num]] in queue] + +/community/manage.bml.commlist.none=You are not managing any communities. + +/community/manage.bml.commlist.text=Here are the communities that you manage or co-manage: + +/community/manage.bml.commlist.title=Title + +/community/manage.bml.commlist.username=Username + +/community/manage.bml.create.header=Create a community + +/community/manage.bml.create.text=You can also create a new community. + +/community/manage.bml.error.badaccounttype=You must be logged in as a regular user account in order to access this page. + +/community/manage.bml.joinmail.body=For communities with closed memberships, you have several e-mail options: + +/community/manage.bml.joinmail.email.all=E-mail every time someone requests to join + +/community/manage.bml.joinmail.email.digest=One e-mail each day with a list of all pending requests + +/community/manage.bml.joinmail.email.none=No e-mail, I will use this page to look for new requests + +/community/manage.bml.joinmail.save=Save Settings + +/community/manage.bml.joinmail.title=Administrative options + +/community/manage.bml.modemail.body=For moderated communities, you can choose whether to send emails or not: + +/community/manage.bml.modemail.no=No email, I will manage the moderation queue manually + +/community/manage.bml.modemail.yes=Email me every time someone submits a post to the queue + +/community/manage.bml.title=Community Management + +/community/members.bml.error.adding=[[user]] has banned this community from sending them invitations. + +/community/members.bml.error.alreadyadded=[[user]] was not added because they already have access to this community. + +/community/members.bml.error.alreadysent=[[user]] could not be added because they were already sent a confirmation email on: [[datetime]]. Please wait for them to respond. + +/community/members.bml.error.invaliduser=Cannot add community or syndicated account: [[user]] + +/community/members.bml.error.limit=Unable to invite [[user]], the outstanding invitation limit for this community has been exceeded. + +/community/members.bml.error.noaccess=Only community maintainers are able to edit membership lists. You are not a maintainer of community [[comm]]. + +/community/members.bml.error.noattr=No attributes selected for user: [[user]] + +/community/members.bml.error.nocomm=Community not found. + +/community/members.bml.error.notactive=Account is not active: [[user]] + +/community/members.bml.error.nouser=User does not exist: [[user]] + +/community/members.bml.error.unknown=Error inviting [[user]]. Please make sure they're not already a member and try again. + +/community/members.bml.key.admin=Maintainer + +/community/members.bml.key.member=Member + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Posting Access + +/community/members.bml.key.preapprove=Unmoderated + +/community/members.bml.key.user=User + +/community/members.bml.manage2=Manage communities + +/community/members.bml.name=Community name: [[name]] + +/community/members.bml.nextlink=(Next page...) + +/community/members.bml.prevlink=(Previous page...) + +/community/members.bml.reinvited2=[[user]] has been reinvited to join this community. They will need to accept the invite from the Community Invitation Page. + +/community/members.bml.settings=[Settings] + +/community/members.bml.success.added=added: [[list]] + +/community/members.bml.success.deleted=removed: [[list]] + +/community/members.bml.success.header=Success + +/community/members.bml.success.invited2=The following users have been successfully invited to this community with the listed privileges. They will need to accept the invite from the Community Invitation Page before they can become a member of the community. + +/community/members.bml.success.message2=The following changes have been made: + +/community/members.bml.success.nochanges=No changes have been made. + +/community/members.bml.success.return=Return to the list + +/community/members.bml.title=Community Members + +/community/members.bml.update=Update settings + +/community/moderate.bml.approve.button=Yes, approve it + +/community/moderate.bml.approve.header=Approve this entry? + +/community/moderate.bml.approve.preapprove=Also, add user [[user]] to the list of pre-approved users for this community. + +/community/moderate.bml.approve.text=Are you sure you want to approve this entry? + +/community/moderate.bml.brlist.actions=Actions + +/community/moderate.bml.brlist.poster=Poster + +/community/moderate.bml.brlist.subject=Subject begins + +/community/moderate.bml.brlist.time=Time + +/community/moderate.bml.brlist.view=View + +/community/moderate.bml.browse.empty=The moderation queue is empty. + +/community/moderate.bml.browse.header=Moderate Community + +/community/moderate.bml.browse.text=Here is the moderation queue for the community [[link]] + +/community/moderate.bml.choice.approve=Approve + +/community/moderate.bml.choice.bkapprove=#82dd88 + +/community/moderate.bml.choice.bkreject=#e08291 + +/community/moderate.bml.choice.reject=Reject + +/community/moderate.bml.error.noaccess=You do not moderate the community [[comm]]. + +/community/moderate.bml.error.noentry=Entry not found (perhaps already handled by another moderator). + +/community/moderate.bml.error.nolist=You do not moderate any communities. + +/community/moderate.bml.error.notfound=Community account not found. + +/community/moderate.bml.manage=Manage communities + +/community/moderate.bml.moderate=Moderate this community + +/community/moderate.bml.modlist.actions=Actions + +/community/moderate.bml.modlist.actmodempty=[Moderate] + +/community/moderate.bml.modlist.actmoderate=Moderate + +/community/moderate.bml.modlist.count=Queue size + +/community/moderate.bml.modlist.header=Moderate Communities + +/community/moderate.bml.modlist.title=Title + +/community/moderate.bml.modlist.username=Username + +/community/moderate.bml.posted.appheader=Preapproved + +/community/moderate.bml.posted.apptext=Additionally, the user [[user]] has been added to the list of pre-approved users for this community. + +/community/moderate.bml.posted.header=Success + +/community/moderate.bml.posted.proterror=The entry has not been posted due to this protocol error: [[err]] + +/community/moderate.bml.posted.text=The entry has been successfully posted. + +/community/moderate.bml.reject.button=Yes, reject it + +/community/moderate.bml.reject.header=Reject this entry? + +/community/moderate.bml.reject.reason=You can also explain to the poster your reasons for rejecting their entry. They will be sent to the poster by email. + +/community/moderate.bml.reject.text=Are you sure you want to reject this entry? + +/community/moderate.bml.rejected.header=Rejected + +/community/moderate.bml.rejected.text=The entry has been rejected. + +/community/moderate.bml.title=Community Moderation + +/community/pending.bml.approve.title=Approve Membership? + +/community/pending.bml.no=No + +/community/pending.bml.nopending.body=There are no pending membership requests for this community. + +/community/pending.bml.nopending.title=Nobody Pending + +/community/pending.bml.success.added=You have added [[num]] [[?num|person|persons]] to this community. + +/community/pending.bml.success.ignored=[[num]] [[?num|request is|requests are]] still on file pending decisions. + +/community/pending.bml.success.previous=[[num]] [[?num|request has|requests have]] not been processed, as they were no longer pending. Another maintainer might have already processed [[?num|it|them]]. + +/community/pending.bml.success.rejected=You have rejected [[num]] [[?num|request|requests]] to join this community. + +/community/pending.bml.title=Pending Membership Requests + +/community/pending.bml.yes=Yes + +/community/search.bml.button.clear=Clear Form + +/community/search.bml.button.search=Search! + +/community/search.bml.checkbox.onlywithpics=Only communities with pictures + +/community/search.bml.label.byinterest=By Interest + +/community/search.bml.label.bylocation=By Location + +/community/search.bml.label.bytime=By Journal Update Time + +/community/search.bml.label.city=City: + +/community/search.bml.label.country=Country: + +/community/search.bml.label.displayoptions=Display Options + +/community/search.bml.label.hasmember=Has Member + +/community/search.bml.label.othercriteria=Other Criteria + +/community/search.bml.label.outputformat=Output Format: + +/community/search.bml.label.records=Records per page: + +/community/search.bml.label.searchcomm=Search Communities + +/community/search.bml.label.selecriteria=Select the criteria below that you'd like to find communities by. The results returned are the intersection of all search criteria. In other words, each checkbox you click means "AND", not "OR". + +/community/search.bml.label.sortmethod=Sorting Method: + +/community/search.bml.label.stateprovince=State/Province: + +/community/search.bml.label.updated=Updated in last + +/community/search.bml.sel.bypicture=By Picture + +/community/search.bml.sel.communityname=Community Name + +/community/search.bml.sel.commview=Community View + +/community/search.bml.sel.day=day + +/community/search.bml.sel.month=month + +/community/search.bml.sel.simple=Simple + +/community/search.bml.sel.updatetime=Update Time + +/community/search.bml.sel.username=User Name + +/community/search.bml.sel.week=week + +/community/search.bml.title=Community Search + +/community/sentinvites.bml.date=Date Sent + +/community/sentinvites.bml.key.date=Date + +/community/sentinvites.bml.key.sentby=Sent By + +/community/sentinvites.bml.key.status=Status + +/community/sentinvites.bml.none.body=No invites have been sent in the past 30 days. If you wish to invite people to this community, please visit the Members page. + +/community/sentinvites.bml.none.title=No Invites Found + +/community/sentinvites.bml.send=Send Invitations + +/community/sentinvites.bml.title=Sent Invitations + +/community/settings.bml.button.changecommunity=Update Settings + +/community/settings.bml.button.createcommunity=Create Community + +/community/settings.bml.error.alreadycomm=Account is already a community. + +/community/settings.bml.error.badpassword=Invalid community password + +/community/settings.bml.error.hasentries=This account already has entries and cannot be converted. + +/community/settings.bml.error.maintainertype=Maintainer account must be a person, not another shared account. + +/community/settings.bml.error.noaccess=Only community maintainers are able to edit community settings. You are not a maintainer of community [[comm]]. + +/community/settings.bml.error.notcomm=Not a community account. + +/community/settings.bml.error.notfound=Community account not found. + +/community/settings.bml.error.samenames=Maintainer account and community account cannot be the same. + +/community/settings.bml.label.anybodycan=All Members
    Anybody can post immediately once a member. + +/community/settings.bml.label.changeheader=Change Community Settings + +/community/settings.bml.label.changetext=Here you can change the settings for the community you own or maintain. + +/community/settings.bml.label.closedmemb2=Closed Membership
    Nobody can join the community. + +/community/settings.bml.label.commchanged=Your community settings have been changed. + +/community/settings.bml.label.commcreate=This is the account that you want to turn into a community. It must already be created, but should not already be in use by an individual, because after this, many different people will potentially be able to post in it. + +/community/settings.bml.label.commcreated=Your community is now set up. + +/community/settings.bml.label.commheader=Community Account + +/community/settings.bml.label.comminfo=Community info + +/community/settings.bml.label.commopts=Community Options + +/community/settings.bml.label.commsite=Community website + +/community/settings.bml.label.community=Community: + +/community/settings.bml.label.createheader=Create Community + +/community/settings.bml.label.createtext=From here you can create a community account. A community is a special type of account that other users can join and post in. For an example of a community, check out the Seattle Party Community. + +/community/settings.bml.label.howoperates=Choose how your community operates. You can change these later. + +/community/settings.bml.label.maintainer=Maintainer: + +/community/settings.bml.label.maintainer.login=If this is not the maintainer account, login as somebody else. + +/community/settings.bml.label.managepage=Community Management - to add members, grant posting access, appoint moderators, etc. + +/community/settings.bml.label.membership=Membership + +/community/settings.bml.label.moderatedmemb=Moderated Membership
    Requests to join are emailed to you for approval. + +/community/settings.bml.label.modheader=Moderation + +/community/settings.bml.label.modis=Moderated
    New entries must be approved by a moderator. + +/community/settings.bml.label.modisnt=Unmoderated
    New entries appear immediately. + +/community/settings.bml.label.modtext=Are submissions to this community moderated? + +/community/settings.bml.label.nmcan=Non-Members Can Post
    Users can post to this community without having to join it. + +/community/settings.bml.label.nmcant=Non-Members Cannot Post
    Users have to join this community in order to post in it. + +/community/settings.bml.label.nmheader=Non-Member Posting + +/community/settings.bml.label.nmtext=Can users post to this community without having to join it? + +/community/settings.bml.label.openmemb=Open Membership
    Anybody can join without getting approved. + +/community/settings.bml.label.password=Password: + +/community/settings.bml.label.postaccess=Posting Access + +/community/settings.bml.label.rellinks=Relevant links: + +/community/settings.bml.label.selcan=Select Members
    Only some members are able to post, once they've been given access by the maintainer account. + +/community/settings.bml.label.username=Username: + +/community/settings.bml.label.whocanjoin=Who can join your community? + +/community/settings.bml.label.whocanpost=Who can post to this community? + +/community/settings.bml.manage2=Manage communities + +/community/settings.bml.members=[Members] + +/community/settings.bml.name=Community name: [[name]] + +/community/settings.bml.success=Success + +/community/settings.bml.title.create=Create Community + +/community/settings.bml.title.modify=Community Settings + +/community/transfer.bml.account=Community Account + +/community/transfer.bml.badstatus.body=The account you are logged in as is not active and cannot use this page at this time. + +/community/transfer.bml.badstatus.title=Account Status + +/community/transfer.bml.body=If you have the password to a community and are not currently a maintainer, you can make yourself a maintainer by filling out the following form. + +/community/transfer.bml.button.title=Transfer Community + +/community/transfer.bml.error.alreadyadmin=Already a maintainer of community. + +/community/transfer.bml.error.badstatus=Community is not active. + +/community/transfer.bml.error.mismatch=Password does not match. + +/community/transfer.bml.error.nopassword=No password provided. + +/community/transfer.bml.error.notcomm=Account not a community. + +/community/transfer.bml.error.notfound=Account not found. + +/community/transfer.bml.password=Community Password + +/community/transfer.bml.success.body=You have successfully added yourself as a maintainer of [[comm]]. + +/community/transfer.bml.success.title=Success + +/community/transfer.bml.title=Transfer Community + +/create.bml.birthday.birthdate=Birthdate: + +/create.bml.birthday.head=Age Verification + +/create.bml.birthday.question=Please select the month, day, and year you were born. We require this information to create an account in order to comply with the Children's Online Privacy Protection Act (COPPA). This information is not stored in our database and is only used during account creation. Read our privacy policy for more information on our information practices. + +/create.bml.birthday.required=(required) + +/create.bml.birthday.security=Security: + +/create.bml.btn.create=Create Journal + +/create.bml.btn.proceed=Proceed... + +/create.bml.captcha.answer=Answer: + +/create.bml.captcha.audiodesc=Type the numbers you hear to prove that you're not a spam robot: + +/create.bml.captcha.desc=Type the letters and numbers you see below, to prove that you're not a spam robot. If you can't read the text, type "AUDIO" and take a sound test instead. + +/create.bml.captcha.invalid=Invalid answer to previous challenge. Try another. + +/create.bml.captcha.play=Play the sound + +/create.bml.captcha.prove=Prove that you're a human + +/create.bml.clusterselect.cluster=Cluster: + +/create.bml.clusterselect.clusternum=Cluster [[number]] + +/create.bml.clusterselect.head=Cluster Selection + +/create.bml.clusterselect.nocluster=No Cluster + +/create.bml.clusterselect.text=Please select the cluster you want to create this account on. Note: This is a debugging/test option only. In production, users won't pick this, or know anything about it. + +/create.bml.community=Would you rather create a community? + +/create.bml.create.head=Creating a New Journal + +/create.bml.create.text=Creating a new Journal is easy, just follow the instructions below! + +/create.bml.email.head=Your email address + +/create.bml.email.input.head=Email Address: + +/create.bml.email.text3=For verification and security purposes, we need your email address. Read our privacy policy for more information on our information practices. + +/create.bml.error.birthday.invalid=You must enter a valid birthday. + +/create.bml.error.coppa.under13=Sorry, due to COPPA restrictions, you cannot use the service until you're 13 years old. Please come back on your 13th birthday. + +/create.bml.error.email.blank=You must provide your email address. + +/create.bml.error.email.lj_domain=You cannot use a [[domain]] alias when creating an account. Please enter a different email address. + +/create.bml.error.email.nospaces=No spaces allowed in email address. If you're on AOL, remember that your Internet Email address is your screen name with all spaces removed, followed by @aol.com + +/create.bml.error.password.asciionly=You can only use ASCII symbols in the password. + +/create.bml.error.password.blank=You must enter a password. + +/create.bml.error.password.nomatch=Passwords do not match. + +/create.bml.error.postrequired=POST required. + +/create.bml.error.username.blank=Please supply a name or handle/alias. + +/create.bml.error.username.inuse=Username already in use; please select a different one. + +/create.bml.error.username.iscode=Username appears to be an invite code, not a username. + +/create.bml.error.username.mustenter=You must enter a username. + +/create.bml.error.username.reserved=Sorry, that is a reserved username. + +/create.bml.errors.label=Please note the following problems and resubmit: + +/create.bml.initialfriends=Add these journals to your friends list to be kept up to date on site news and information. + +/create.bml.initialfriends.heading=Starter Friends + +/create.bml.name.head=Your Name + +/create.bml.name.input.head=Name: + +/create.bml.name.text=What's your name or handle? This will appear at the top of your journal, and in the user directory should you choose to be listed in it. You do not have to provide your full name or even your real name. + +/create.bml.password.head=Password + +/create.bml.password.input.head1=Password: + +/create.bml.password.input.head2=Re-type password: + +/create.bml.password.secure=You must choose a secure password that is not based on a dictionary word, your username, or your email address. + +/create.bml.password.text=Select a password. + +/create.bml.success.btn.enterinfo=Enter Personal Information + +/create.bml.success.head=Success! + +/create.bml.success.text1=Your journal has been created. Important registration information has been emailed to [[email]] containing further instructions. Be sure to confirm your journal creation by clicking on the link sent to you in email. + +/create.bml.success.text2=Your Journal will be available at: + +/create.bml.success.text3=Now, please take the time to fill in some information about yourself. It's mostly optional, but it lets us get an idea of who's using [[sitename]]. + +/create.bml.title=Create New Journal + +/create.bml.tos.heading=Terms of Service + +/create.bml.tos.p1.3=Before continuing you must read and agree to the Terms of Service (which includes our privacy policy). + +/create.bml.useacctcodes.entercode=To create a new account, enter an account creation code: + +/create.bml.useacctcodes.welcome=Welcome + +/create.bml.username.box.head=Username: + +/create.bml.username.charsallowed=Your username may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_). Additionally, it must not be longer than 15 characters. + +/create.bml.username.forpaidaccts=Or, for paid accounts: + +/create.bml.username.head=Username + +/create.bml.username.ljaddress=Your journal will be at these addresses: + +/create.bml.username.text=Each [[sitename]] user must have their own unique username. Your username is what appears in the address to your journal and what you use to log into the [[sitename]] server. It also shows up when you post comments in other people's journals. + +/create.bml.username.username=username + +/customize/index.bml.change=Change + +/customize/index.bml.choose=Do you want to use the old style system, or the new one? + +/customize/index.bml.choose.header=Choose style system + +/customize/index.bml.choose.s1=Old system (S1) + +/customize/index.bml.choose.s2=New system (S2) + +/customize/index.bml.error.cant_generate_user_layer=Could not generate user layer + +/customize/index.bml.error.disallowed_custom_layer=Your account status does not allow access to this custom layer + +/customize/index.bml.error.fail_create_style=Failed to create new style. + +/customize/index.bml.error.not_your_layout=Not your layout. + +/customize/index.bml.error.not_your_theme=Not your theme + +/customize/index.bml.error.no_core_parent=No core parent? + +/customize/index.bml.previews=(Previews) + +/customize/index.bml.s1.2=The old style system is configured through the Modify Journal page. + +/customize/index.bml.s1.header=Using S1 + +/customize/index.bml.s2.advanced.denied=Your account is not permitted to use the advanced customization features. + +/customize/index.bml.s2.advanced.header=Advanced Customizations + +/customize/index.bml.s2.advanced.permitted=To create new layers and styles from scratch, visit the advanced customization center. + +/customize/index.bml.s2.customize=The following settings are layout-dependent. + +/customize/index.bml.s2.customize.header=Step 2: Customize Layout + +/customize/index.bml.s2.customize.language=The following languages are fully or partially supported by this layout. + +/customize/index.bml.s2.customize.language.custom=(Custom) + +/customize/index.bml.s2.customize.language.default=(Default) + +/customize/index.bml.s2.customize.language.header=Language + +/customize/index.bml.s2.customize.settings=If you want to customize your journal further, here you can tweak individual settings to get it looking exactly how you want. + +/customize/index.bml.s2.customize.settings.delete=Remove Customizations + +/customize/index.bml.s2.customize.settings.delete.confirm=Are you sure you want to remove these customizations? + +/customize/index.bml.s2.customize.settings.edit=Edit Customizations + +/customize/index.bml.s2.customize.settings.header=Change Individual Settings + +/customize/index.bml.s2.customize.settings.new=Customize + +/customize/index.bml.s2.customize.themes=Choose from the following optional themes for this layout. + +/customize/index.bml.s2.customize.themes.default=(Layout Default) + +/customize/index.bml.s2.customize.themes.header=Themes + +/customize/index.bml.s2.layout<< +Pick your layout. Because theme selection and custom modifications depend +on your layout, changing this setting discards all other edits you may have made. +. + +/customize/index.bml.s2.layout.header=Step 1: Layout + +/customize/index.bml.s2.related.editinfo.about=Set your journal's titles and various options. + +/customize/index.bml.s2.related.header=Related Pages + +/customize/index.bml.s2.related.links.about=Some styles can include your managed link list. + +/customize/index.bml.s2.related.modify.about=Set your journal's mood icon set. + +/customize/index.bml.title=Customize Journal + +/delcomment.bml.changeoptions<< +Note: From the [[link]] page, you can choose +whether to allow all, registered users, or +friends only to post comments. +. + +/delcomment.bml.confirm.banuser=Ban [[user]] from commenting in your journal + +/delcomment.bml.confirm.body=Are you sure you want to delete this comment? + +/delcomment.bml.confirm.delthread=Delete thread (all subcomments) + +/delcomment.bml.confirm.head=Delete this comment? + +/delcomment.bml.confirm.spam=Mark this comment as spam + +/delcomment.bml.confirm.submit=Delete Comment + +/delcomment.bml.error.alreadydeleted=The specified comment has already been deleted. + +/delcomment.bml.error.cantdelete=A comment may only be deleted by its author or the journal owner. + +/delcomment.bml.error.cantdelete.comm=A comment may only be deleted by its author, the author of the journal entry, or a community maintainer. + +/delcomment.bml.error.invalidtype=Invalid comment type. This page only handles comments on journal entries. + +/delcomment.bml.error.nocomment=The specified comment does not exist. + +/delcomment.bml.error.suspended=You are not allowed to delete comments while your account is suspended. + +/delcomment.bml.success.andban=The comment has been deleted, and user [[user]] has been banned from commenting in your journal. + +/delcomment.bml.success.head=Deleted + +/delcomment.bml.success.noban=The comment has been deleted. + +/delcomment.bml.success.spam=Additionally, the administrators of this site have been notified that this comment was spam. Thank you for your report. + +/delcomment.bml.title=Delete Comment + +/directory.bml.browse.country.desc=Select a country to read journals from that country... + +/directory.bml.browse.country.title=Browse Journals by Country + +/directory.bml.browse.usa.desc=Click a US state below to read journals from that state, or click a country name below the map to read journals from that country. + +/directory.bml.browse.usa.title=Browse Journals by US State + +/directory.bml.error.accounttype<< +Sorry, your account type doesn't permit usage of the +directory, or you aren't currently logged in. If your account type permits +directory usage, be sure that you are logged in and then try again. +. + +/directory.bml.navcrap.matches=[[count]] matches + +/directory.bml.navcrap.xofy=Page [[curpage]] of [[totpages]] shown (records [[reca]]-[[recb]]) + +/directory.bml.open=Open + +/directory.bml.post=Post + +/directory.bml.search.monkey=Hundreds of trained monkeys are currently running about finding your search results. Please stand by. + +/directory.bml.search.new=New Query + +/directory.bml.search.overflow=Search results limited to [[count]] results. Please refine your query. + +/directory.bml.search.title=Searching + +/directory.bml.update=Update: + +/directory.bml.user=User + +/doc/index.bml.about<< +Welcome to [[sitename]] documentation repository, where you can find information +on most topics regarding our service or server software. Please select +a topic from below: +. + +/doc/index.bml.about.header=Welcome + +/doc/index.bml.docs.faq.about=Frequently Asked Questions + +/doc/index.bml.docs.faq.title=FAQ + +/doc/index.bml.docs.guides.about=Supplemental FAQ information + +/doc/index.bml.docs.guides.title=Guides + +/doc/index.bml.docs.header=Documents + +/doc/index.bml.docs.howto.about=Tips and tricks to help customize your [[sitename]] account + +/doc/index.bml.docs.tour.about=Designed for new visitors to become familiar with the site + +/doc/index.bml.docs.tour.title=Tour + +/doc/index.bml.title=Documentation + +/doc/index.bml.volunteering.about=If you'd like to help out with [[sitename]] documentation, check out the following forums: + +/doc/index.bml.volunteering.header=Volunteering + +/doc/tour/index.bml.comms.caption<< +It shouldn't be a surprise to you that there are many members with interests similar to yours. +To this end, we offer the ability to create communities, or journals that many people can post to. +. + +/doc/tour/index.bml.comms.title=Communities + +/doc/tour/index.bml.create.caption<< +We are a membership-based blogging community. This page explains what membership entails, +why membership is important, and the benefits of membership. It also includes a form to create +your own account. +. + +/doc/tour/index.bml.create.title=Creating an Account + +/doc/tour/index.bml.friends.caption<< +You can keep track of your friends as well, by using the built–in "friends" feature. +If you find a journal you think is interesting, add it to your friends list, which will let you read all of +your friends' entries from the same page. +. + +/doc/tour/index.bml.friends.title=Friends + +/doc/tour/index.bml.intro.caption<< +This tour is designed for new visitors to become familiar with the site. +It will show you where the most important sections are located, as well +as some of the more interesting features. +. + +/doc/tour/index.bml.intro.title=Welcome + +/doc/tour/index.bml.modify.caption<< +It is also possible to format your journal in a number of different ways, by making use +of predefined styles and color schemes. Make your journal as unique as you want! +. + +/doc/tour/index.bml.modify.title=Personalizing + +/doc/tour/index.bml.nav.next=Next --> + +/doc/tour/index.bml.nav.prev=<-- Prev + +/doc/tour/index.bml.profile.caption<< +Our members are encouraged to add information about themselves into their profiles, so that +we can get an idea of who uses the site and how we can best serve them. However, none of this is required +— the only information that is required to start using [[sitename]] is a name, an e-mail address, and a password. +. + +/doc/tour/index.bml.profile.title=Profiles + +/doc/tour/index.bml.sitemap.caption<< +Hopefully this tour gave you some helpful starting information about our site and service. +If you need help with anything related to [[sitename]], feel free to contact +our support department. If you want to explore further, please +refer to the site map to see a list of all the pages on this site. +. + +/doc/tour/index.bml.sitemap.title=Site Map + +/doc/tour/index.bml.support.caption<< +The support page lists areas that help explain what [[sitename]] is, +frequently asked questions about the site, and other helpful information +about the service, the company, and the community at large. +. + +/doc/tour/index.bml.support.title=Getting Help + +/doc/tour/index.bml.title=Tour - [[title]] + +/doc/tour/index.bml.update.caption<< +Updating a journal is the core of our service. Updating a journal is simple. Simply write +an entry in the supplied box and press the "Update Journal" button. We also offer some +additional features on our update page, like the ability to supply extra information +about your entries, such as your current music or current mood. +. + +/doc/tour/index.bml.update.title=Updating + +/editinfo.bml.advanced.about=Don't worry about this stuff if you don't know what it is. + +/editinfo.bml.advanced.title=Advanced Options + +/editinfo.bml.allowshowcontact.about<< +You should keep this option enabled. This lets other people be able to contact +you by showing your email address, ICQ number, and screenname +all on your [[sitename]]. +. + +/editinfo.bml.allowshowcontact.email=If visible, email address to be displayed: + +/editinfo.bml.allowshowcontact.email.actual_only=Actual address only + +/editinfo.bml.allowshowcontact.email.both=Both (actual + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Site address only + +/editinfo.bml.allowshowcontact.email.neither=Neither. Don't show any email address. + +/editinfo.bml.allowshowcontact.email.no_show=Don't show email address + +/editinfo.bml.allowshowcontact.email.show=Show email address + +/editinfo.bml.allowshowcontact.email.withdomainaddr<< +With the option above, you may also choose to hide your email address +(while still showing other contact information), only show your site email address, +only show your real address, or show them both. +. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr<< +With the option above, you may also choose to hide your email address +(while still showing other contact information). +. + +/editinfo.bml.allowshowcontact.title=Show your contact information on your Journal? + +/editinfo.bml.allowshowinfo.about=Turn this on if you want your city/state/country and birthday to be visible to other users. + +/editinfo.bml.allowshowinfo.title=Show location & birthday? + +/editinfo.bml.bday.title=Birthday + +/editinfo.bml.bday.year.opt=year is optional + +/editinfo.bml.bdayreminders.about=If you want to get email reminding you of birthdays for your friends on [[sitename]], click this box. + +/editinfo.bml.bdayreminders.header=Send me birthday reminders (currently disabled) + +/editinfo.bml.bio.about=Here you can enter a little mini-biography about yourself. This will show up on your User Info page. + +/editinfo.bml.bio.header=About You + +/editinfo.bml.blockrobots.about<< +If you check this option, robots will be told to go away. +Not all robots respect the rules. +. + +/editinfo.bml.blockrobots.header=Block Robots/Spiders from indexing your journal + +/editinfo.bml.chat.aolim.title=AOL IM + +/editinfo.bml.chat.icquin.title=ICQ UIN + +/editinfo.bml.chat.jabber.title=Jabber + +/editinfo.bml.chat.msnusername.title=MSN Username + +/editinfo.bml.chat.yahooid.title=Yahoo! ID + +/editinfo.bml.city.title=City + +/editinfo.bml.country.choose=Pick a country + +/editinfo.bml.country.title=Country + +/editinfo.bml.donotlog=No + +/editinfo.bml.email.title=Email + +/editinfo.bml.enableboards.about=Check this if you want people to be able to reply to journal entries you post. + +/editinfo.bml.enableboards.header=Enable message boards + +/editinfo.bml.encoding.about=Don't worry about this stuff. In general, only international users that write in several different languages will need to change anything here. + +/editinfo.bml.encoding.header=Encoding Options + +/editinfo.bml.error.day.notinmonth=Invalid day for that month. + +/editinfo.bml.error.day.outofrange=Invalid birthday day. Enter a day from 1-31. + +/editinfo.bml.error.email.lj_domain<< +You cannot enter an @[[domain]] email address. +Enter your real address in that field. +If you're a paid user, your [[user]]@[[domain]] address will forward to your real address. +To choose which email address (or both) is displayed publicly, see the option below the "Show your Contact Information" option. +. + +/editinfo.bml.error.email.none=You must provide your email address + +/editinfo.bml.error.email.no_space<< +No spaces are allowed in an email address. +If you're on AOL, remember that your Internet Email address is your screen name with all spaces removed, followed by @aol.com +. + +/editinfo.bml.error.excessive_int<< +Sorry, you listed too many interests. The limit is 150, but you've listed [[intcount]]. +Any changes you made to your interests were not saved. Go back and cut down your list, +then save again. +. + +/editinfo.bml.error.locale.country_ne_state=You specified United States as your country, but you typed in a non-US state in the "other state" field. + +/editinfo.bml.error.locale.invalid_country=Somehow you selected an invalid country. + +/editinfo.bml.error.locale.state_ne_country=You specified a non-US country but selected a US state. + +/editinfo.bml.error.locale.zip_ne_state<< +Your zip code does not match the state you specified. +Either correct the information, or erase one or both of the state and zip code fields. +. + +/editinfo.bml.error.locale.zip_requires_us<< +You entered a zip code but you did not select United States as your country. +We only collect zip code information about people in the US. +Please go back and remove the zip code or select United States as your country. +. + +/editinfo.bml.error.month.outofrange=Invalid birthday month. Enter a month from 1-12. (Jan-Dec) + +/editinfo.bml.error.noname=Your name is a required field. At least provide your first name, or a nickname or handle. + +/editinfo.bml.error.tm.require.number=If you're going to use text messaging, you must enter your phone number. + +/editinfo.bml.error.tm.require_provider<< +If you're going to use text messaging, you must select your service provider. +If yours is not listed, please contact us with information about how your service's text messaging feature works so we can add support for it. +. + +/editinfo.bml.error.year.notenoughdigits=Invalid birthday year. Enter a 4-digit year. + +/editinfo.bml.error.year.outofrange=Invalid birthday year. + +/editinfo.bml.finished.about=When done, press the "Save Changes" button below: + +/editinfo.bml.finished.header=Done? + +/editinfo.bml.finished.save_button=Save Changes + +/editinfo.bml.foafurl.about=If you do not want to use the default FOAF page we provide, any URL you enter above will be used as your FOAF resource instead. We will redirect FOAF requests to the specified URL. + +/editinfo.bml.foafurl.title=External FOAF URL: + +/editinfo.bml.gender.title=Gender + +/editinfo.bml.getreplies.about=Check this if you want to get email updates when people reply to your journal entries in the message boards. + +/editinfo.bml.getreplies.header=Get message board replies + +/editinfo.bml.getselfemails.about=Check this if you wish to get an email every time you post a comment in a journal or community. You will not get email for anonymous comments. + +/editinfo.bml.getselfemails.header=Get comments you post emailed to you + +/editinfo.bml.hidefriendof.about=If you check this, the list of people that list you as a friend is hidden on your profile page. + +/editinfo.bml.hidefriendof.header=Hide "Friend of" list + +/editinfo.bml.howhear.about<< +Just for curiosity's sake, where did you hear about [[sitename]] from? +If it was a specific person, enter their username; if it +was from another source/article/link/website, enter the appropriate information. +. + +/editinfo.bml.howhear.header=Curiosity + +/editinfo.bml.htmlemail.about<< +Check this if your email program fully supports HTML in your email. +Many clients try to support it but fail horribly. +If you uncheck it, [[sitename]] will only send text emails. +. + +/editinfo.bml.htmlemail.header=Send HTML Emails + +/editinfo.bml.imagelinks.about=Placeholders are useful if you are browsing at work or over a slow connection, replacing inline images with links. What size images do you want placeholders to be used for? + +/editinfo.bml.imagelinks.header=Use image placeholders on your friends page + +/editinfo.bml.imagelinks.size.all=Use placeholders for all images + +/editinfo.bml.imagelinks.size.custom=Custom: use placeholders for images larger than [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=Use placeholders for large images (over [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Use placeholders for medium images (over [[width]]x[[height]]) + +/editinfo.bml.int.about<< +If you want other people to be able to search the directory and find you by interest, +list below everything you're interested in, separated by commas. +Short single-word phrases are best. Rule of thumb: You should be able to put +the interest in the sentence "I like ________". When referring to nouns, use the +plural form for consistency. "I like DVDs" instead of "I like DVD". +. + +/editinfo.bml.int.ex.bad=BAD Example: I like lots of bands and watching movies and talking to friends and going to clubs. That sort of stuff goes in your bio above. + +/editinfo.bml.int.ex.good=GOOD Example: biking, snow skiing, computers, dvds, mp3s, cheese, women + +/editinfo.bml.int.header=Interests + +/editinfo.bml.login.enterinfo=Enter your username and password to modify your personal information. + +/editinfo.bml.login.forgot.header=Forget something? + +/editinfo.bml.login.forgot.recover=If you forgot your username or password, recover it here!. + +/editinfo.bml.logip.always=Always + +/editinfo.bml.logip.anon_only=Anonymous posters only + +/editinfo.bml.logip.header=Log IP addresses of people replying? + +/editinfo.bml.mangleaddress.about<< +If you have the above option selected and are afraid spam-robots will find your email +address on [[sitename]], select this option. Your email address will be modified +so your email address won't be found by email-collecting robots. +. + +/editinfo.bml.mangleaddress.header=Mangle your displayed email address + +/editinfo.bml.mutualfriends.about=This option adds a new list to your profile page: the mutual friends list. People who you list as a friend and who also list you as a friend will be put on this list. + +/editinfo.bml.mutualfriends.header=Display mutual friends on profile page + +/editinfo.bml.name.title=Name + +/editinfo.bml.newemail.body2<< +You have just changed the email address for your [[sitename]] account "[[username]]". To validate the change, please go to this address: + +[[conflink]] + +Regards, +[[sitename]] Team +[[sitelink]] +. + +/editinfo.bml.newemail.subject=Email Address Changed + +/editinfo.bml.numcomments.about=Check this if you want to append the comment count to URLs to make your browser possibly display the links in a different color. + +/editinfo.bml.numcomments.header=Add &nc=xx to comment URLs + +/editinfo.bml.optional=Optional + +/editinfo.bml.opt_in.about<< +If you want to know when we add some cool new feature to LiveJournal, check this box. +We aren't currently using this feature, but we might in the future. +Your email address will not be visible to other users, and you can turn this off at anytime. +. + +/editinfo.bml.opt_in.header=Send me [[sitename]] news. + +/editinfo.bml.persinfo.disclaimer<< +Fill in some quick information about yourself, for our own curiosity and statistical purposes. +We're not going to do anything evil or annoying with this information, we'd just like to see +who and where our users are. Please, fill it in correctly. If you're concerned, +read our privacy policy. +. + +/editinfo.bml.persinfo.header=Personal Information + +/editinfo.bml.screen.all=All + +/editinfo.bml.screen.anon=Anonymous + +/editinfo.bml.screen.header=Which replies do you want screened by default? + +/editinfo.bml.screen.none=None + +/editinfo.bml.screen.nonfriends=By non-friends + +/editinfo.bml.screen.nonmembers=By non-members + +/editinfo.bml.security.header=Security + +/editinfo.bml.security.visibility.anybody=Anybody + +/editinfo.bml.security.visibility.everybody=Everybody + +/editinfo.bml.security.visibility.friends=Friends only + +/editinfo.bml.security.visibility.regusers=Registered Users + +/editinfo.bml.settings.friendspage.title=Friends Page Title: + +/editinfo.bml.settings.friendspage.title.optional=Optionally, enter a title for your friends view pages. (no HTML) + +/editinfo.bml.settings.header=Options + +/editinfo.bml.settings.journal.subtitle=Journal Subtitle: + +/editinfo.bml.settings.journal.subtitle.optional=Optionally, enter a title and subtitle for your journal. (no HTML). + +/editinfo.bml.settings.journal.title=Journal Title: + +/editinfo.bml.settings.privacy.about=Select below your personal privacy options and preferences. + +/editinfo.bml.settings.privacy.header=Privacy Options + +/editinfo.bml.state.other=Or, type other state/province/territory + +/editinfo.bml.state.title=State + +/editinfo.bml.state.us=US States + +/editinfo.bml.stylemine.about=Check this option to view comment pages in your journal style when following links from your friends page. + +/editinfo.bml.stylemine.header=View comment pages in your journal style? + +/editinfo.bml.success.header=Success! + +/editinfo.bml.success.message=Your information and journal settings and profile have been updated. + +/editinfo.bml.switch.button=Switch + +/editinfo.bml.switch.header=Switch Journal + +/editinfo.bml.switch.workwith=Work with journal: + +/editinfo.bml.title=Edit Personal Information + +/editinfo.bml.tm.details=details + +/editinfo.bml.tm.phonenum=Full phone number: + +/editinfo.bml.tm.sec.about=Enable text messaging from other users. + +/editinfo.bml.tm.sec.title=Security Level: + +/editinfo.bml.tm.servprov=Service Provider + +/editinfo.bml.tm.title=Text Messaging + +/editinfo.bml.translatemailto.about<< +By default, [[sitename]] sends all cyrillic e-mail using KOI8 encoding +(this is the standard way, and it works with pretty much all mail +clients). If you wish, you may change the e-mail encoding here, for +instance to CP1251 (Windows) or UTF-8 (Unicode). Do this only if you +are absolutely sure this is what you want. +. + +/editinfo.bml.translatemailto.header=Translate email notifications into: + +/editinfo.bml.unbanusers.about=You have the following users banned from posting in your journal. Check the checkbox by their username to remove the ban on them. + +/editinfo.bml.unbanusers.header=Unban Users + +/editinfo.bml.userpic.about<< +Below is the miniature picture you have uploaded to represent you +throughout [[sitename]] and in your journal and in your friends' journals: +. + +/editinfo.bml.userpic.edit=To delete this picture, or upload a new one, go here. + +/editinfo.bml.userpic.header=Your Picture + +/editinfo.bml.userpic.none=no image uploaded + +/editinfo.bml.weblogscom.about=Select this option if you would like to have Weblogs.com list your journal when you post new public entries. + +/editinfo.bml.weblogscom.header=Notify Weblogs.com of updates + +/editinfo.bml.webpagename.title=Webpage Name + +/editinfo.bml.webpageurl.title=Webpage URL + +/editinfo.bml.whoreply.header=Who can reply to your entries? + +/editinfo.bml.zip.title=ZIP Code + +/editinfo.bml.zip.usonly=5 digit ZIP code; US residents only + +/editjournal.bml.auth.poster=Poster: + +/editjournal.bml.btn.proceed=Proceed... + +/editjournal.bml.certainday=Certain Day: + +/editjournal.bml.desc=Please use the form below to find the entry you would like to edit. + +/editjournal.bml.in=In community: + +/editjournal.bml.recententries=most recent entries + +/editjournal.bml.recententry=Most recent entry + +/editjournal.bml.success.delete=Journal entry was deleted. + +/editjournal.bml.success.deletespam=Additionally, the entry was marked as spam. Thank you for your report. + +/editjournal.bml.success.head=Success + +/editjournal.bml.title=Edit Journal Entries + +/editjournal.bml.viewwhat=View What Entries: + +/editjournal_do.bml.body<< +Edit the fields of your journal entry you'd like to modify and press the save button at the +bottom of the page. Alternately, you can press the delete button to delete the entry. +. + +/editjournal_do.bml.btn.delete=Delete Entry + +/editjournal_do.bml.btn.deletespam=Delete and Mark As Spam + +/editjournal_do.bml.btn.edit=Edit Selected Entry + +/editjournal_do.bml.btn.preview=Preview Entry + +/editjournal_do.bml.btn.save=Save Journal Entry + +/editjournal_do.bml.continue.head=Press to continue... + +/editjournal_do.bml.continue.text=After you select an item to edit or delete, press the Edit button below. + +/editjournal_do.bml.currmood=Current Mood: + +/editjournal_do.bml.currmusic=Current Music: + +/editjournal_do.bml.date=Date: + +/editjournal_do.bml.default=default + +/editjournal_do.bml.delete.confirm=Are you sure you want to delete this entry? + +/editjournal_do.bml.deletespam.confirm=Are you sure you want to delete this entry and mark it as spam? + +/editjournal_do.bml.edit.text=Edit the fields of your journal entry you'd like to modify and press the save button at the bottom of the page. To delete the entry, just delete all the text and press save... the entry will be deleted. + +/editjournal_do.bml.error.getting=There was an error getting the journal entries to edit: + +/editjournal_do.bml.error.modify=An error occurred modifying your journal: + +/editjournal_do.bml.error.nofind=Could not find selected journal entry. + +/editjournal_do.bml.event=Event: + +/editjournal_do.bml.localtime=Local time: + +/editjournal_do.bml.noneother=None, or other: + +/editjournal_do.bml.opt.backdate=Backdate Entry: + +/editjournal_do.bml.opt.backdate.about=won't show on friends view + +/editjournal_do.bml.opt.nocomments=Disallow Comments: + +/editjournal_do.bml.opt.noemail=Don't email Comments: + +/editjournal_do.bml.opt.noformat=Don't auto-format: + +/editjournal_do.bml.opt.spellcheck=Spell check entry before saving + +/editjournal_do.bml.other=Other: + +/editjournal_do.bml.pickentry.head=Pick an entry to edit + +/editjournal_do.bml.pickentry.text=Select which item you want to edit and press the edit button at the bottom of the page. + +/editjournal_do.bml.picture=Picture to use: + +/editjournal_do.bml.preview.header=Preview Entry + +/editjournal_do.bml.preview.text=This is how the entry will look when posted. Using the form below, you can edit the entry further, or you can submit it as is. + +/editjournal_do.bml.save.head=Press to save... + +/editjournal_do.bml.save.text=After you're done editing your journal entry, press Save. + +/editjournal_do.bml.spellchecked=Your spell-checked post: + +/editjournal_do.bml.subject=Subject: (optional, for use on longer entries) + +/editjournal_do.bml.success.delete=Journal entry was deleted. + +/editjournal_do.bml.success.deletespam=Additionally, the entry was marked as spam. Thank you for your report. + +/editjournal_do.bml.success.head=Success + +/editjournal_do.bml.timeformat=24 hour time + +/editjournal_do.bml.title=Edit Journal Entries + +/editpics.bml.btn.proceed=Proceed + +/editpics.bml.btn.save=Save Settings + +/editpics.bml.curpics=Current Pictures + +/editpics.bml.curpics.desc=Here are the pictures you've uploaded in the past. You can assign keywords to them so you can use them by keyword later, select which one to use as your default, or delete old ones. To upload a new one, use the form at the bottom of the page. + +/editpics.bml.error.badurl=The address for the picture to be uploaded does not look correct. It should start with http:// + +/editpics.bml.error.filetoolarge=Image uploaded is too large. File size cannot exceed [[maxsize]]. + +/editpics.bml.error.imagetoolarge=The dimensions of your image ([[imagesize]]) exceed maximum size. Your picture can only be 100x100 pixels large. Use a image/photo editing program to reduce the image to thumbnail-size. + +/editpics.bml.error.invalidimage=Invalid image file. + +/editpics.bml.error.keywords=You used the keyword "[[ekw]]" for multiple pictures. One was randomly chosen, but likely not the one you wanted. You may want to go back and fix that. + +/editpics.bml.error.toomanykeywords=The [[?numwords|keyword|keywords]] "[[words]]" [[?numwords|has|have]] not been saved as [[?numwords|its|their]] user picture icon already has [[max]] keywords. + +/editpics.bml.error.toomanypics2=You are already at your limit of [[maxpics]] pictures. You cannot upload this picture until you delete one of your existing ones. + +/editpics.bml.error.toomanypics3=You are currently at your limit of [[max]] [[?max|picture|pictures]]. You will not be able to upload additional pictures until you delete one or more of your current pictures. + +/editpics.bml.error.unsupportedtype=Files of type [[filetype]] are not supported. You can only upload GIF, PNG or JPG files. Nearly all image/photo programs can do this conversion for you. + +/editpics.bml.error.urlerror=An error ocurred while trying to fetch your image. + +/editpics.bml.fromfile=From File: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=f + +/editpics.bml.fromurl=From URL: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=r + +/editpics.bml.imagesize.by|notes=This character is inserted between two numbers to indicate "by" when specifying image dimensions, for example "100x100". +/editpics.bml.imagesize.by=x + +/editpics.bml.kilobytes=KB + +/editpics.bml.label.comment=Comment: + +/editpics.bml.label.default=Default: + +/editpics.bml.label.delete=Delete: + +/editpics.bml.label.keywords=Keywords: + +/editpics.bml.makedefault=Make this your default picture + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=d + +/editpics.bml.nodefault=No Default Picture + +/editpics.bml.noneupload=You have no pictures uploaded. Please upload one using the form below. + +/editpics.bml.nopics=No Pictures + +/editpics.bml.piclimitstatus=Currently uploaded: [[current]] out of [[max]]. + +/editpics.bml.restriction.fileformat=File format must be either PNG, GIF or JPG + +/editpics.bml.restriction.filesize=File size must be less than 40k + +/editpics.bml.restriction.imagesize=Image dimensions must be no larger than 100x100 pixels + +/editpics.bml.restriction.keywords=Picture will be unusable if keywords are not supplied + +/editpics.bml.restriction.keywords.faq=Picture will be unusable if keywords are not supplied + +/editpics.bml.title=Edit User Pictures + +/editpics.bml.uploaddesc=Use the form below to upload a new picture. + +/editpics.bml.uploaddesc.fb=Upload a thumbnail of an image hosted on your [[sitename]] account as a new user picture. + +/editpics.bml.uploadheader=Upload a New Picture + +/editpics.bml.uploadheader.fb=Upload a New Picture From Fotobilder + +/editpics.bml.warning.keywords=One or more of your pictures do not have keywords defined and thus cannot currently be used + +/editpics.bml.warning.keywords.faq=One or more of your pictures do not have keywords defined and thus cannot currently be used + +/edittags.bml.button.save=Save changes + +/edittags.bml.current=Current tags: + +/edittags.bml.disabled=Sorry, the tags system is currently disabled. + +/edittags.bml.entry=Entry: + +/edittags.bml.error.db=Sorry, we encountered a database error. Please try again. + +/edittags.bml.intro=Use the form below to edit the tags on this entry. + +/edittags.bml.invalid.entry=Specified entry is invalid. + +/edittags.bml.invalid.journal=Specified journal is invalid. + +/edittags.bml.invalid.link=You have reached this page in an invalid way. Please follow a link from an entry to edit tags. + +/edittags.bml.invalid.notauthorized=You do not have access to view that entry. + +/edittags.bml.permissions.add.yes=You may add tags from the list above. + +/edittags.bml.permissions.control.yes=You may remove tags or create new ones. + +/edittags.bml.permissions.none=(You do not have permission to edit tags on this entry.) + +/edittags.bml.subject=Subject: + +/edittags.bml.title=Edit Tags on Entry + +/edittags.bml.users=User's tags: + +/edittags.bml.view=View this entry. + +/export.bml.btn.proceed=Proceed... + +/export.bml.description=This feature lets you download your entire journal to a custom format for backup purposes. + +/export.bml.fields=Fields: + +/export.bml.format.csv=CSV (Comma Separated Values) + +/export.bml.format.xml=XML + +/export.bml.label.encoding=Encoding: + +/export.bml.label.field.allowmask=Allow Mask + +/export.bml.label.field.currents=Current Mood & Music + +/export.bml.label.field.event=Event + +/export.bml.label.field.eventtime=Event Time (from user's clock) + +/export.bml.label.field.itemid=ID Number + +/export.bml.label.field.logtime=Log Time (from system's clock) + +/export.bml.label.field.security=Security Level + +/export.bml.label.field.subject=Subject + +/export.bml.label.format=Format: + +/export.bml.label.header=Header + +/export.bml.label.month=Select month: + +/export.bml.label.month.month=mm: + +/export.bml.label.month.year=yyyy: + +/export.bml.label.notranslation=Do not translate between encodings + +/export.bml.label.what=Export what: + +/export.bml.title=Export Journal + +/export.bml.what.entries=Journal entries + +/export_do.bml.error.encoding=Invalid encoding selected + +/friends/add.bml.add.header=Success + +/friends/add.bml.add.text=User [[ljuser]] was added to your friend list. You can view your friends page here. + +/friends/add.bml.add.title=Friend Added! + +/friends/add.bml.btn.add=Add [[user]] + +/friends/add.bml.btn.modify=Modify + +/friends/add.bml.btn.remove=Remove + +/friends/add.bml.colors.bg=Background + +/friends/add.bml.colors.fg=Foreground + +/friends/add.bml.colors.header=Colors + +/friends/add.bml.colors.hover=(Hover your mouse over a color to see its name) + +/friends/add.bml.colors.text=You may also optionally select the colors that will represent [[user]] in your friends list. + +/friends/add.bml.confirm.header=Add [[user]] as a friend? + +/friends/add.bml.confirm.syn.header=Add syndicated feed [[user]] as a friend? + +/friends/add.bml.confirm.syn.title=Add Syndicated Feed + +/friends/add.bml.confirm.text=To add [[user]] to your friends list, click the button below. + +/friends/add.bml.confirm.title=Add Friend + +/friends/add.bml.error1.header=Log In First + +/friends/add.bml.error1.text<< +To add a user to your friends list you must first go and log in. If you don't +already have an account you can create one to track your friend's journals. +. + +/friends/add.bml.error1.title=Add Friend + +/friends/add.bml.error2.text=Invalid or missing username given. To add a friend, go to the edit friends page. + +/friends/add.bml.error3.text=You already have [[user]] listed as a friend. However, you can modify the colors you've chosen to represent him/her. + +/friends/add.bml.error3.title=Modify Friend + +/friends/add.bml.groups.header=Friends Groups + +/friends/add.bml.groups.nogroup=No friend groups setup. + +/friends/add.bml.groups.text=What friend groups do you want to put this user in? Friend groups are used for filtering your friends list view and also for group-based viewing security of items. + +/friends/add.bml.remove.header=Success + +/friends/add.bml.remove.text=User [[ljuser]] was removed from your friend list. You can view your friends page here. + +/friends/add.bml.remove.title=Friend Removed! + +/friends/edit.bml.title=Edit Friends + +/friends/editgroups.bml.btn.ge.del=Delete + +/friends/editgroups.bml.btn.ge.new=New + +/friends/editgroups.bml.btn.ge.ren=Rename + +/friends/editgroups.bml.btn.gs.private=Private + +/friends/editgroups.bml.btn.gs.public=Public + +/friends/editgroups.bml.btn.mv.down=Move down + +/friends/editgroups.bml.btn.mv.up=Move up + +/friends/editgroups.bml.confirm.delete=Are you sure you wish to delete this custom friends group? + +/friends/editgroups.bml.done.btn=Save Changes + +/friends/editgroups.bml.done.header=Done? + +/friends/editgroups.bml.done.text=When you are done, press the button below to save your changes. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=You have reached the maximum limit of 30 custom friends groups. If you have deleted one or more groups but have not saved the changes yet, do so now, then come back to this page and reload it. You will then be able to create new custom friends groups. + +/friends/editgroups.bml.error.text=The server returned the following error message: + +/friends/editgroups.bml.group.public=(public) + +/friends/editgroups.bml.ingroup=In group: + +/friends/editgroups.bml.ingroup.not=Not in group: + +/friends/editgroups.bml.prompt.newname=Enter the name for the new custom friends group: + +/friends/editgroups.bml.prompt.rename=Rename this custom friends group to: + +/friends/editgroups.bml.saved.header=Saved + +/friends/editgroups.bml.saved.text=Your custom friends groups are now saved. + +/friends/editgroups.bml.text<< +This page allows you to edit your custom friends groups. Custom friends groups are used +for setting security on items and for filtering your friends page. +This page requires JavaScript to work. +. + +/friends/editgroups.bml.text.sec<< +Security note: If you wish to delete a group and make a new group, +do not do this by renaming one group and then editing it. +If you do this, all your old entries which are accessible to the old group will +then be accessible to the new group. +. + +/friends/editgroups.bml.title=Edit Custom Friends Groups + +/friends/editgroups.bml.yourgroups=Your custom friends groups: + +/friends/edit_do.bml.addfriends.head=Add Friends + +/friends/edit_do.bml.addfriends.text=Enter your friends' [[sitename]] user names in the boxes below, and pick what background and foreground colors you want to associate with them.... + +/friends/edit_do.bml.background=Background + +/friends/edit_do.bml.bgcolor=Background Color: + +/friends/edit_do.bml.btn.close=Close + +/friends/edit_do.bml.btn.save=Save Changes + +/friends/edit_do.bml.btn.toggle=Toggle Preview Window + +/friends/edit_do.bml.done.head=Done? + +/friends/edit_do.bml.done.text=When done, press the "Save Changes" button below... + +/friends/edit_do.bml.error.updating=There was an error updating your friends list: + +/friends/edit_do.bml.fellowfriends.head=Fellow Friends + +/friends/edit_do.bml.fellowfriends.text=The following people have listed you as a friend. You may want to list them as your friend too. This is provided as a reference, so that you know their [[sitename]] usernames. You are under no obligation to add them to your list. + +/friends/edit_do.bml.foreground=Foreground + +/friends/edit_do.bml.friend=Friend + +/friends/edit_do.bml.hover=Hover your mouse over a color to see its name + +/friends/edit_do.bml.mrcolor=Mr. Color Viewer + +/friends/edit_do.bml.name=Name + +/friends/edit_do.bml.needmore=If you need to add more friends than you have room for on this form, save the changes below, then come back to add more. + +/friends/edit_do.bml.nofriends.head=No Friends? + +/friends/edit_do.bml.nofriends.text=You do not currently have any friends defined. However, we're sure you have to have a few friends! :) Just enter their [[sitename]] names below.... + +/friends/edit_do.bml.opt.addtolist=Add friend + +/friends/edit_do.bml.opt.delete=Delete? + +/friends/edit_do.bml.success.head=Success + +/friends/edit_do.bml.success.text=Your friends have been updated. You may view your newly updated friends page here. + +/friends/edit_do.bml.textcolor=Text Color: + +/friends/edit_do.bml.title=Edit Friends + +/friends/edit_do.bml.user=User + +/friends/edit_do.bml.viewer=Color Viewer + +/friends/edit_do.bml.yourfriends.head=Your Friends + +/friends/edit_do.bml.yourfriends.text=You have the following friends currently defined: + +/friends/filter.bml.editgroups=If you want to edit your friends groups, go to the [[link]] page. + +/friends/filter.bml.error.nogroups=You cannot filter your friends list because you must first setup your friend groups. + +/friends/filter.bml.error.nogroups.header=No Groups Defined + +/friends/filter.bml.reset=Clear + +/friends/filter.bml.select=Check the group(s) of friends you want to view on your friends list. + +/friends/filter.bml.select.header=Select Groups + +/friends/filter.bml.submit=View! + +/friends/filter.bml.title=Friends Filter + +/friends/index.bml.about<< +Here we have the concept of a "friends list". +By adding other users to your friends list, you can easily keep +track of what is going on in their lives from your friends page. +Friends aren't limited by individuals, you can add communities and +syndicated feeds to your friends list as well. +. + +/friends/index.bml.edit.about=Add, edit, or remove users from your friends list. + +/friends/index.bml.editgroups.about=Create, edit, or delete sub groups of your friends. + +/friends/index.bml.filter<< +These friend groups can be used to filter your friends list: you can +pick a specific friend group to view. +. + +/friends/index.bml.filter.about=Filter your friends list according to specific sub groups. + +/friends/index.bml.groups=In addition, subgroups of friends can be specified. + +/friends/index.bml.security=Your friends list is also used for posts with restricted access. + +/friends/index.bml.security.custom=With "Custom" posts, you can specify which friend groups can view your post. + +/friends/index.bml.security.header=Security + +/friends/index.bml.security.only=With "Friends-Only" posts, all of the other users on your friends list can view your post. + +/friends/index.bml.title=Friends Tools + +/friends/index.bml.tools=Tools + +/go.bml.defaultbody=No parameters given. + +/go.bml.defaulttitle=Error + +/go.bml.error.noentry.next=There is no entry following this one. + +/go.bml.error.noentry.prev=There is no entry preceding this one. + +/go.bml.error.noentrytitle=No Entry + +/go.bml.error.redirkey=Bogus redir_key. + +/go.bml.error.usernotfound=User not found. + +/index.bml.about.header=About [[sitename]] + +/index.bml.about.joining=Joining the site is free. Users can choose to upgrade their accounts for extra features. + +/index.bml.about.us=LiveJournal is a simple-to-use (but extremely powerful and customizable) personal publishing ("blogging") tool, built on open source software developed by Brad Fitzpatrick. By far the largest site using this software is www.livejournal.com. We're running the same software (slightly rewritten) and offering the same service (slightly more censorship-free). + +/index.bml.boldcreate=Create your own blog at [[sitename]]! + +/index.bml.learnmore.header= Want to learn more? + +/index.bml.learnmore.text=Please read our feature overview. Convinced? Create your own blog as [[sitename]]! + +/index.bml.meta.desc=[[sitename]] is a place where you can share your valuable thoughts with the world (whether it wants it, or not). + +/index.bml.meta.keywords=diary, journal, online journal, diaries, writing, online diary, web diary + +/index.bml.news.text=The latest site news: + +/index.bml.news.title=Latest News + +/index.bml.post=Live Post Stats + +/index.bml.post.hour=Per Hour: + +/index.bml.post.latest=Latest Posts + +/index.bml.post.min=Per Minute: + +/interests.bml.add.added.head=Added! + +/interests.bml.add.added.text=The interest has been added to your list. + +/interests.bml.add.btn.text=Add [[interest]] + +/interests.bml.add.confirm.head=Confirm + +/interests.bml.add.confirm.text=To add [[interest]] as an interest, click the button below. + +/interests.bml.add.toomany.head=Sorry... + +/interests.bml.add.toomany.text=You already have [[maxinterests]] interests defined. + +/interests.bml.addint=If you're also interested in this and would like to be added to this list, click here. + +/interests.bml.btn.switch=Switch + +/interests.bml.communities.head=Relevant Communities + +/interests.bml.communities.text=The following communities are also interested in "[[interest]]". + +/interests.bml.count=Count + +/interests.bml.enmasse.body.other<< +Below are the interests of [[user]]. Check the boxes next to the interests you would like +to add to your own, and uncheck the checkboxes next to the interests you would like to remove +from your own. When you're done, click "Save Changes". +. + +/interests.bml.enmasse.body.other_authas<< +Below are the interests of [[user]]. Check the boxes next to the interests you would like +to add to those of [[target]], and uncheck the checkboxes next to the interests you would +like to remove. When you're done, click "Save Changes". +. + +/interests.bml.enmasse.body.you<< +Uncheck the checkboxes next to the interests you would like to remove. +When you're done, click "Save Changes". +. + +/interests.bml.enmasse.btn=Show list + +/interests.bml.enmasse.header=Add/Remove interests + +/interests.bml.enmasse.intro=Modify your interests based on those of: + +/interests.bml.error.add.mustlogin=You have to be logged in to add an interest this way. + +/interests.bml.error.enmasse.mustlogin=You must be logged in to use this feature. + +/interests.bml.error.enmasse.noaccess=You do not appear to have access to the journal [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Interest wasn't found. + +/interests.bml.error.nointerests=The selected user does not exist or has not specified any interests. + +/interests.bml.findsim.searchwait=Please note: Search will take several seconds. Be patient. + +/interests.bml.findsim_do.account.notallowed=Sorry, your account type doesn't let you use this tool. + +/interests.bml.findsim_do.magic=Magic
    Index + +/interests.bml.findsim_do.magic.head=Magic Index? + +/interests.bml.findsim_do.magic.text=Each matching user gets computed a magic index, which is a weighting of two factors: the raw number of like interests, and some extra points for sharing uncommon interests. + +/interests.bml.findsim_do.nomatch.head=No Matches + +/interests.bml.findsim_do.nomatch.text=No users are similar to [[user]]. + +/interests.bml.findsim_do.notdefined=User [[user]] has no defined interests. + +/interests.bml.findsim_do.similar.head=Similar Users + +/interests.bml.findsim_do.similar.text=The following are the most related users to [[user]] + +/interests.bml.finished.about=When you're done, press the "Save Changes" button below: + +/interests.bml.finished.header=Done? + +/interests.bml.finished.save_button=Save Changes + +/interests.bml.interest=Interest + +/interests.bml.interested.btn.find=Find + +/interests.bml.interested.in=Find people interested in: + +/interests.bml.interests.findsim=Find users with interests similar to those of: + +/interests.bml.interests.head=Interests + +/interests.bml.interests.text=Here are some fun things you can do with interests. + +/interests.bml.interests.viewpop=View popular interests + +/interests.bml.login.enterinfo=Enter your username and password to modify your interests. + +/interests.bml.login.proceed=Proceed... + +/interests.bml.match=[[count]] match: + +/interests.bml.matches=[[count]] matches: + +/interests.bml.morestuff=More fun stuff can be found on the interests page. + +/interests.bml.nointerests.text=Don't have any interests listed? Add some by going to the Edit Personal Info & Settings page. + +/interests.bml.popular.disabled=Sorry, the popular interests feature has been disabled. + +/interests.bml.popular.head=Popular Interests + +/interests.bml.popular.text=The following are the most popular interests. + +/interests.bml.results.added=The interests you selected were successfully added to your interests list. + +/interests.bml.results.both=The interests you selected were successfully added to your interests list, and those you deselected were removed. + +/interests.bml.results.deleted=The interests you deselected were successfully removed from your interests list. + +/interests.bml.results.del_and_toomany<< +The interests you deselected were successfully removed from your interests list. +However, you selected too many interests to add. You may only have [[intcount]] +interests in total. None of the selected interests were added to your interests list. +You may wish to go back and try again, selecting fewer interests to add. +. + +/interests.bml.results.goback=You may wish to go back to [[user]]'s profile which you were viewing previously. + +/interests.bml.results.header=Results + +/interests.bml.results.message=See your updated profile page. + +/interests.bml.results.nothing=You did not make any changes. + +/interests.bml.results.toomany<< +You selected too many interests to add. You may only have [[intcount]] interests +in total. None of the selected interests were added to your interests list. +You may wish to go back and try again, selecting fewer interests to add. +. + +/interests.bml.title=Interests + +/interests.bml.toomany.body=There are [[intcount]] people and/or communities listing this as an interest. A list will not be shown. + +/interests.bml.toomany.head=Many matches + +/interests.bml.users.head=Interested users + +/interests.bml.users.text=The following users are also interested in [[interest]]. + +/invite/index.bml.code=Code + +/invite/index.bml.error=Error + +/invite/index.bml.genmore=Generate more codes + +/invite/index.bml.how_detail=Depending on a number of factors, existing users are allowed to invite a certain number of other users to join the site. To invite somebody you need to generate an invitation code and then give it to them. + +/invite/index.bml.how_header=How does it work? + +/invite/index.bml.invite_header=Invitations? + +/invite/index.bml.none=None + +/invite/index.bml.redeemed=Redeemed by + +/invite/index.bml.title=Invite others to [[sitename]]... + +/invite/index.bml.unused=Unused + +/invite/index.bml.use=use + +/invite/index.bml.why_codes=Unofrtunately, as a means to control growth and prevent server overload, creating an account now requires either buying an account or getting invited by an existing user. + +/legal/tos.bml.title=Terms of Service + +/login.bml.bindip.label=Bind to IP address: + +/login.bml.bindip.no=No (works with all ISPs) + +/login.bml.bindip.yes=Yes (safer) + +/login.bml.error.mustenterusername=You must enter a username. + +/login.bml.expire.btn.neverexpire=Change expiration mode to NEVER + +/login.bml.expire.btn.sessiononly=Change expiration mode to SESSION ONLY + +/login.bml.expire.neverexpire.text=Your login will never expire, so if you're at a public internet terminal, a school, library, or other place where people may be using this computer shortly, make sure you log out when you're done! Or, change your login mode to expire when you close your browser: + +/login.bml.expire.sessiononly.text=Your login will expire after you close your browser. If this is your own computer and you're the only user, you may want to set your login expiration such that it never expires: + +/login.bml.links.head=Links + +/login.bml.links.link1=Your friends page. + +/login.bml.links.link2=Your to-do list. + +/login.bml.links.text=In the future this page will have all sorts of links and relevant information, but for now here are a few places you may want to go: + +/login.bml.loggedin.head=Logged in! + +/login.bml.loggedin.text=You are now logged in. + +/login.bml.login.btn.changeopts=Change Options + +/login.bml.login.btn.login=Login... + +/login.bml.login.expiration=Expiration: + +/login.bml.login.forget=Forget? + +/login.bml.login.head=Login + +/login.bml.login.never=Never + +/login.bml.login.otheropts=Other Options: + +/login.bml.login.password=Password: + +/login.bml.login.text1=To login to [[sitename]], enter your username and password below. New Users: To create an account, go here. + +/login.bml.login.text2=By default your login will expire when you close your browser, which is best on public computers. However, if you're the only user of your computer and nobody else has access to it, you may choose to remain logged in forever. + +/login.bml.login.text3=[[username]], you are now logged in to [[sitename]]. + +/login.bml.login.username=Username: + +/login.bml.login.whenbrowsercloses=When browser closes + +/login.bml.logout.btn=Log Out + +/login.bml.title=Login + +/login.bml.whylogin.benefit1=You won't have to enter your username/password anywhere on the site anymore. + +/login.bml.whylogin.benefit2=You'll be able to view "protected" journal entries from your friends that give you access to read them. + +/login.bml.whylogin.benefit3=A lot of features are only visible or accessible when you're logged in. + +/login.bml.whylogin.head=Why Login? + +/login.bml.whylogin.text=Here are some of the main benefits of logging in: + +/logout.bml.already.head=Already logged out + +/logout.bml.already.text=You are already logged out. + +/logout.bml.killall.btn=Expire all my sessions + +/logout.bml.killall.head=Other sessions + +/logout.bml.killall.text=You have other active sessions, from other computers. Do you want to expire all your sessions, and not just this one? + +/logout.bml.loggedout.already=Already logged out. + +/logout.bml.loggedout.head=Logged out + +/logout.bml.loggedout.killedall=All your sessions have been expired. + +/logout.bml.loggedout.success=Logged out. + +/logout.bml.loggedout.text=You are now logged out. + +/logout.bml.logout.btn=Log out + +/logout.bml.logout.head=Log out? + +/logout.bml.logout.text=Click the button below to log out. + +/logout.bml.title=Logout + +/lostinfo.bml.btn.proceed=Proceed + +/lostinfo.bml.enter_email=Enter your email address: + +/lostinfo.bml.enter_email_optional=Email address: (optional) + +/lostinfo.bml.enter_username=Enter your username: + +/lostinfo.bml.error.commnopassword=The account you are trying to retrieve the password for is a community. This kind of account does not have a password to retrieve. All community management can be accomplished by logging in as a maintainer of the community. + +/lostinfo.bml.error.no_email=You must enter an email address in order to recover your username. + +/lostinfo.bml.error.purged=Cannot retrieve password for a deleted account once it has been purged. + +/lostinfo.bml.error.renamed=Cannot retrieve password for a renamed account. + +/lostinfo.bml.error.syndicated=The account you are trying to retrieve the password for is a syndicated account. This kind of account does not have a password to retrieve. + +/lostinfo.bml.error.sysbanned=Your account is not allowed to e-mail passwords. + +/lostinfo.bml.error.toofrequent=You are trying to send too many e-mails at once. You may only request three lost information e-mails within twenty-four hours. + +/lostinfo.bml.lostpassword.text=If you've lost your password, enter your username and optionally, the email address you'd like the password sent to. Note that the email address must be one you've used at [[sitename]] before and had confirmed at one point. If you leave the email field blank, it'll be mailed to your current address. + +/lostinfo.bml.lostpassword.title=Lost your password? + +/lostinfo.bml.lostusername.text=If you've lost your username, enter your email address and we'll send you your username. + +/lostinfo.bml.lostusername.title=Lost your username? + +/lostinfo.bml.title=Lost Information + +/lostinfo_do.bml.error.no_usernames_for_email=No username(s) for this email address: [[address]] . + +/lostinfo_do.bml.error1.text=You never used that email address with this account or it was never validated. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** This is an automated email. You do not need to respond to it. *** + +This is your requested password reminder from [[sitename]]. +Below is your username, password, and email address your journal is +registered under. + + Username: [[username]] + Password: [[password]] + EMail Address: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=To validate your email address, go here: + +/lostinfo_do.bml.lostpasswordmail.part3<< +This information was requested on the website from [[remoteip]]. + +If you didn't request to have this password emailed to you, don't panic. +After all, you're the one who's seeing this email, and not the other person. +It's possible that the user who made the request is mistaken and +believes that he or she controls this username. It's also possible that +someone made a typo in a username or email address. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4= + +/lostinfo_do.bml.lostpasswordmail.part5<< +Useful links: + + Your Journal: + [[journalurl]] + + Update your journal online: + [[updateurl]] + +Regards, +The site team + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Lost Password + +/lostinfo_do.bml.password_mailed.text=Success. Your password has been mailed. + +/lostinfo_do.bml.password_mailed.title=Password mailed! + +/lostinfo_do.bml.title=Lost Information + +/lostinfo_do.bml.username_mailed.text=Success. Your username has been mailed. + +/lostinfo_do.bml.username_mailed.title=Username mailed! + +/manage/index.bml.about=Managing your account is easy. Just choose from the following areas below: + +/manage/index.bml.communities=Create and manage your own communities: + +/manage/index.bml.communities.create.about=Create a new community + +/manage/index.bml.communities.header=Communities + +/manage/index.bml.communities.invites.about=View any pending invitations you have received to join communities. + +/manage/index.bml.communities.manage.about=Manage your communities' settings and members + +/manage/index.bml.customization=Customize the look of your journal pages: + +/manage/index.bml.customization.advanced=Advanced Customization + +/manage/index.bml.customization.advanced.about=Browse, create, and edit your S2 layouts and styles + +/manage/index.bml.customization.customize=Customize Journal + +/manage/index.bml.customization.customize.about=Change the appearance of your journal + +/manage/index.bml.customization.header=Customization + +/manage/index.bml.customization.links=Links List + +/manage/index.bml.customization.links.about=Create a list of links to appear in your journal + +/manage/index.bml.customization.modify.about=Modify your journal's display properties + +/manage/index.bml.customization.moodtheme.editor=Create and edit your custom mood themes + +/manage/index.bml.customization.moodtheme.editor.header=Mood Theme Editor + +/manage/index.bml.customization.moodtheme.header=Mood Themes + +/manage/index.bml.customization.moodtheme.set=Select which mood theme set your journal will use + +/manage/index.bml.customization.moodtheme.set.header=Set Your Mood Theme + +/manage/index.bml.customization.s1.header=S1 Style System + +/manage/index.bml.customization.s2.header=S2 Style System + +/manage/index.bml.entries=Work with entries you have made in your account's journal: + +/manage/index.bml.entries.edit.about=Edit and delete entries in your journal + +/manage/index.bml.entries.header=Journal Entries + +/manage/index.bml.entries.memories.about=View and work with your memorable posts + +/manage/index.bml.friends=Manage your friends and friend groups, or filter your friends page according to your saved friend groups: + +/manage/index.bml.friends.edit.about=Add, edit, or remove users from your friends list + +/manage/index.bml.friends.filter=Filter Friends Page + +/manage/index.bml.friends.filter.about=Filter your friends list to display a specific friend group + +/manage/index.bml.friends.groups.about=Create, edit, or delete subgroups of your friends list + +/manage/index.bml.friends.header=Friends + +/manage/index.bml.information=Choose what information is displayed on your account: + +/manage/index.bml.information.changepass=Change Account Password + +/manage/index.bml.information.changepass.about=Change your account's password + +/manage/index.bml.information.editinfo.about=Edit your account information and various options + +/manage/index.bml.information.emailpost=Email Gateway Settings + +/manage/index.bml.information.emailpost.about=Manage your email addresses and PIN for post-by-email support + +/manage/index.bml.information.header=Account Information + +/manage/index.bml.information.siteopts.about=Select your preferred site layout & language + +/manage/index.bml.information.status=Account Status + +/manage/index.bml.information.status.about=Set your account's activation status + +/manage/index.bml.login<< +The following links will navigate you to pages where your login information +is required. To save yourself some time, you can log in beforehand. +. + +/manage/index.bml.title=Manage Accounts + +/manage/index.bml.userpictures=Upload and manage user picture icons for your account: + +/manage/index.bml.userpictures.edit.about=Upload and Manage Your User Picture Icons + +/manage/index.bml.userpictures.header=User Picture Icons + +/manage/invites.bml.abilities.title=Abilities + +/manage/invites.bml.accept=Accept + +/manage/invites.bml.accepted.body=You have joined the following communities, with the mentioned abilities: + +/manage/invites.bml.accepted.title=Invitations Accepted + +/manage/invites.bml.actions.title=Actions + +/manage/invites.bml.back=Manage invites + +/manage/invites.bml.community.title=Community + +/manage/invites.bml.decline=Decline + +/manage/invites.bml.fromline=From [[user]] ([[date]]) + +/manage/invites.bml.label.admin=Maintainer + +/manage/invites.bml.label.member=Member + +/manage/invites.bml.label.moderate=Moderator + +/manage/invites.bml.label.post=Can Post + +/manage/invites.bml.label.preapprove=Unmoderated + +/manage/invites.bml.manage=Manage account + +/manage/invites.bml.none.body=You have no pending community invitations at this time. + +/manage/invites.bml.none.title=Nothing Pending + +/manage/invites.bml.rejected.body=You have rejected the following community invitations: + +/manage/invites.bml.rejected.title=Invitations Rejected + +/manage/invites.bml.submit=Submit Selections + +/manage/invites.bml.title=Manage Community Invitations + +/manage/invites.bml.undecided.body=You have not decided on actions for the following invitations: + +/manage/invites.bml.undecided.title=Invitations Still Pending + +/manage/links.bml.about=Use the form below to create a list of links to appear on your journal. Links will only appear if this feature is supported by your S2 style. + +/manage/links.bml.about.blank=To create a blank line, enter a "-" for the title. + +/manage/links.bml.about.heading=To create a heading, enter a title with no URL. + +/manage/links.bml.about.reorder=To reorder links in the list, modify the order number at left (decimal numbers are ok). + +/manage/links.bml.error.s2required=The link list is only available on supported S2 styles. To switch to S2, see the [[link]] page. + +/manage/links.bml.error.s2required.header=S2 Required + +/manage/links.bml.success=Success! Your links have been saved. + +/manage/links.bml.title=Links List + +/manage/pubkey.bml.error.invalidkey=That doesn't appear to be a valid PGP/GPG key. + +/manage/pubkey.bml.error.notconfigured=This site is not configured with PGP support. + +/manage/pubkey.bml.header=PGP/GPG key + +/manage/pubkey.bml.info=Publishing your public key allows others to view it via your userinfo page, and you can post to the email gateway with signed messages. See instructions here. + +/manage/pubkey.bml.pastekey=Paste your key in its entirety (ascii armored format) into the below field: + +/manage/pubkey.bml.save=Save + +/manage/pubkey.bml.successhead=Success + +/manage/pubkey.bml.successtext=Your public key been saved. You may view it here. + +/manage/pubkey.bml.title=Set Public Key + +/manage/pubkey.bml.whatis=Don't know what a public key is? Need help exporting your key? Read more about PGP and GPG. + +/manage/siteopts.bml.btn.lang=Switch Language + +/manage/siteopts.bml.btn.scheme=Switch Scheme + +/manage/siteopts.bml.head.lang=Select Your Language + +/manage/siteopts.bml.head.scheme=Select Your Preferred Scheme + +/manage/siteopts.bml.scheme.preview=[Preview of [[title]] scheme] + +/manage/siteopts.bml.title=Browse Preferences + +/manage/tags.bml.addnew=Add new tags here! + +/manage/tags.bml.button.delete=Remove selected tag(s) + +/manage/tags.bml.button.rename=Rename + +/manage/tags.bml.button.show=Show journal entries + +/manage/tags.bml.confirm.delete=Are you sure you want to remove the selected tags? This operation is not reversible. + +/manage/tags.bml.hint.create=You can create multiple tags by separating them with commas. + +/manage/tags.bml.hint.delete=Remove all references to the selected tag(s). + +/manage/tags.bml.hint.entries=Display journal entries marked with the selected tag(s). + +/manage/tags.bml.hint.rename=Change a tag name. + +/manage/tags.bml.intro=Use this page to review and edit tags you have defined. + +/manage/tags.bml.label.tags=Tag properties + +/manage/tags.bml.label.yours=Your tags + +/manage/tags.bml.none=You haven't created any tags yet. + +/manage/tags.bml.sort.a=sort: alphabetically or by usage + +/manage/tags.bml.sort.b=sort: alphabetically or by usage + +/manage/tags.bml.title=Tags Management + +/meme.bml.meme.disabled=The site administrator has disabled this feature. + +/modify.bml.title=Modify Journal + +/modify_do.bml.availablestyles.disabledstyles=Disabled Styles: + +/modify_do.bml.availablestyles.head=Available Styles + +/modify_do.bml.availablestyles.userstyles=User Styles: + +/modify_do.bml.colortheme.about=Here you can select what color theme will be applied to the layout options you pick above. Or, if you don't like the provided colors, specify your own! If you come up with something really sexy looking, let us know and we'll name a theme after it. + +/modify_do.bml.colortheme.area.head=Usage Area + +/modify_do.bml.colortheme.color.head1=Color + +/modify_do.bml.colortheme.color.head2=(#rrggbb or name) + +/modify_do.bml.colortheme.customcolors=Custom Colors + +/modify_do.bml.colortheme.defaulttheme=Default Theme + +/modify_do.bml.colortheme.head=Color Theme + +/modify_do.bml.domainalias.about=If you have a domain name already registered (or which you're planning on registering) and would like it to automatically load your Journal, enter it here: + +/modify_do.bml.domainalias.domainname=Domain name: + +/modify_do.bml.domainalias.example=Example: my-journal.com + +/modify_do.bml.domainalias.head=Domain Aliasing + +/modify_do.bml.domainalias.helptext=For this to work, you'll need to arrange to have your domain name's DNS point to the same IP address of [[sitename]]. + +/modify_do.bml.done.btn.savechanges=Save Changes + +/modify_do.bml.done.head=Done? + +/modify_do.bml.done.text=When done, press the "Save Changes" button below... + +/modify_do.bml.error.dupdomainalias=Another user has already registered themselves as using your selected domain alias. + +/modify_do.bml.error.stylenotavailable=One of the styles you've selected is not available. This is either the result of somebody deleting the style, or you trying to pick one that you don't have access to. + +/modify_do.bml.friends.about=Here are options that control how your friends page looks. + +/modify_do.bml.friends.head=Friends View + +/modify_do.bml.friends.opt.usesharedpic.about=This option controls what picture you see on your friends page when a user posts in a shared or community journal. If you check it, then you'll see the community's icon. If you leave it unchecked, then you'll see the person that's actually posting's personal user icon. + +/modify_do.bml.friends.opt.usesharedpic.head=Use shared journal pictures instead of poster's user picture + +/modify_do.bml.journaloptions.about=From here you can customize the look of your [[sitename]] pages. If you're really curious how everything works, read the developer information. Otherwise, we'll assume you're satisfied with the basic options below: + +/modify_do.bml.journaloptions.head=Journal Options + +/modify_do.bml.journalstatus.about=If you want to delete or undelete your journal, this is where you do it. Once you delete your journal you have 30 days to undelete it, just in case you change your mind. After 30 days, the journal will be permanently deleted and there will be no way to recover it. + +/modify_do.bml.journalstatus.head=Journal Activation Status + +/modify_do.bml.journalstatus.select.activated=Activated + +/modify_do.bml.journalstatus.select.deleted=Deleted + +/modify_do.bml.journalstatus.select.head=Status: + +/modify_do.bml.journalstatus.select.suspended=Suspended + +/modify_do.bml.moodicons.about=When posting journal entries you can also specify your current mood. Different users have submitted different sets of mood icons that you can use. Or, select "None" if you don't want any pictures beside your moods. (or, you don't even have to use the Current Mood feature at all.) + +/modify_do.bml.moodicons.head=Mood Icons + +/modify_do.bml.moodicons.opt.forcefriends.about=Force this mood theme for all friends on your friends page + +/modify_do.bml.moodicons.personal=Personal Themes: + +/modify_do.bml.moodicons.preview=preview + +/modify_do.bml.moodicons.select=Select mood icon set: + +/modify_do.bml.overrides.about=You can ignore this section. This is for tweaking very specific things about your page layout. See the developer section for details. Also note that overrides are for overriding only one or two things about a style. If you'd like to override everything, you need to create your own style. + +/modify_do.bml.overrides.box.head=Overrides: + +/modify_do.bml.overrides.head=Style Overrides + +/modify_do.bml.overrides.note=Please note that not all style variables can be overridden. See the documentation for more details. + +/modify_do.bml.overrides.warning=THIS IS NOT WHERE YOU TYPE YOUR JOURNAL!! + +/modify_do.bml.pagelayoutstyle.about=Setting this controls how your journal is laid out on the screen. + +/modify_do.bml.pagelayoutstyle.head=Page Layout Style + +/modify_do.bml.pagelayoutstyle.warning=Your account type only permits you to select between a small number of default styles. + +/modify_do.bml.success.head=Success + +/modify_do.bml.success.text=Your journal settings have been updated. You can view your journal here. + +/multisearch.bml.formaterror=Format Error + +/multisearch.bml.noaddress.text=You did not enter an email address. + +/multisearch.bml.noaddress.title=No Address + +/multisearch.bml.nointerest.text=You did not enter an interest. + +/multisearch.bml.nointerest.title=No Interest + +/multisearch.bml.nomatch.text=There were no results for the criteria you specified. + +/multisearch.bml.nomatch.title=No Match + +/multisearch.bml.region.bodytext<< +You can search by region in one of the following formats: +
      +
    • Country
    • +
    • City *
    • +
    • City, State *
    • +
    • State, Country
    • +
    • City, State, Country
    • +
    +Notes: +
      +
    • * searching for only a city or a city and state defaults to assuming the country is the United States.
    • +
    • Country can either be the country's full name, or its two letter country code
    • +
    +If you want to do a different type of search, check out the directory search. +. + +/multisearch.bml.region.head=Search by Region + +/poll/create.bml.button.editpoll=Edit Poll + +/poll/create.bml.button.insert=Insert + +/poll/create.bml.button.postpoll=Post Poll + +/poll/create.bml.button.preview=Preview Poll + +/poll/create.bml.button.seecode=See Code + +/poll/create.bml.button.startover=Start Over + +/poll/create.bml.elements.limitreached=Element limit reached + +/poll/create.bml.error.accttype=Your account type does not permit you to use the poll creation feature. + +/poll/create.bml.error.allitemsblank=All items cannot be blank. + +/poll/create.bml.error.notext=You need text explaining your question + +/poll/create.bml.error.parsing=Error parsing poll: + +/poll/create.bml.error.pqmaxlengthinvalid=Maxlength attribute on lj-pq text tags must be an integer from [[min]] to [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Size attribute on lj-pq text tags must be an integer from [[min]] to [[max]]. + +/poll/create.bml.error.scalemaxlessmin=Scale 'from' value must be less than 'to' value. + +/poll/create.bml.error.scalemininvalid=Scale increment must be at least [[min]]. + +/poll/create.bml.error.scaletoobig=Limit of [[max]] selections (to-from)/by > 20 + +/poll/create.bml.error.texttoolong=The text of your option is too long and has been truncated. + +/poll/create.bml.haserrors=You have one or more errors with your poll. Please scroll down for more details. + +/poll/create.bml.insertquestion=Insert question here: + +/poll/create.bml.options=Options: + +/poll/create.bml.options.limitreached=Option limit reached + +/poll/create.bml.pollname=Poll Name: (opt.) + +/poll/create.bml.preview.desc=Below is a preview of your poll. This is exactly how it will look once it is placed on your journal. Use the buttons below to go back and make changes or post this poll to your journal. + +/poll/create.bml.preview.options=Options + +/poll/create.bml.properties=Poll Properties + +/poll/create.bml.question=Question: + +/poll/create.bml.questionnum=Question #[[num]] + +/poll/create.bml.questions=Poll Questions + +/poll/create.bml.title=Poll Creator + +/poll/create.bml.type.check=Check Boxes + +/poll/create.bml.type.drop=Drop-down box + +/poll/create.bml.type.radio=Radio Buttons + +/poll/create.bml.type.scale=Scale + +/poll/create.bml.type.text=Text entry + +/poll/create.bml.whoview=Who can view this poll? + +/poll/create.bml.whovote=Who can vote in this poll? + +/poll/index.bml.discuss=Discuss Results + +/poll/index.bml.error.cantview=Sorry, you're not permitted to see this poll. + +/poll/index.bml.error.postdeleted=Owning post deleted, so poll no longer accessible. + +/poll/index.bml.filloutpoll=Fill out Poll + +/poll/index.bml.gotocreate=This is the address to participate in a poll. You've stumbled onto an address which does nothing right now. If you'd like, you can create a new poll. + +/poll/index.bml.pollnotfound=Poll not found. + +/poll/index.bml.submitted.head=Thanks + +/poll/index.bml.submitted.text=Your poll answers have been submitted. + +/poll/index.bml.submitted.title=Submitted! + +/poll/index.bml.title=Poll + +/poll/index.bml.viewresults=View Poll Results + +/pubkey.bml.error.notconfigured=This site is not configured with PGP support. + +/pubkey.bml.error.nousername=No username specified. + +/pubkey.bml.info.desc=Don't know what a public key is? Read more about PGP and GPG. + +/pubkey.bml.info.head=Information + +/pubkey.bml.info.upload=Want to upload your key? Click here. + +/pubkey.bml.label=Public key for [[user]]: + +/pubkey.bml.nokey=[[user]] has not uploaded a public key yet. + +/pubkey.bml.title=View Public Key + +/register.bml.ask.body=Click the button below to have send a validation email to [[email]]. + +/register.bml.ask.button=Send + +/register.bml.ask.header=Validate Email + +/register.bml.asterisk.comment=(Please note that accounts marked with an * have not yet been validated) + +/register.bml.asterisk.name=* [[journal]] + +/register.bml.email.body|notes=This string is used to create an option in the "Work as user" drop down list to allow a user to view all of their journals. The * signifies that the acount, specified by [[journal]], is not validated yet. +/register.bml.email.body<< +This is the validation email as you have requested. +To complete validating your account, please visit this URL: + + [[conflink]] + +You may have to copy and paste this link into your browser's window. + +Sincerely, +[[sitename]] +[[siteroot]] +. + +/register.bml.email.subject=Validate Email + +/register.bml.error.emailchanged=This verification link is out of date. Please request a new verification email. + +/register.bml.error.invalidcode=Invalid validation code. + +/register.bml.error.useralreadyvalidated=The email address for [[user]] has already been validated. + +/register.bml.error.usernotfound=User not found. + +/register.bml.new.bodyuser=Thanks! The email address for [[user]] has now been verified. From here, you may be interested in doing the following things: + +/register.bml.new.editinfo=Edit Information -- Fill out your user profile and set various settings. + +/register.bml.new.header=Success + +/register.bml.new.login=Login -- So you don't have to enter your username and password everywhere. + +/register.bml.new.modify=Modify Journal -- Modify the look of your journal. + +/register.bml.new.update=Update Journal -- Write in your journal. + +/register.bml.sent.body=A validation email has been sent to [[email]]. In order to complete validation, you need to click the link in that email. + +/register.bml.sent.header=Success + +/register.bml.title=Validate Email + +/register.bml.trans.body=Your new email address has been validated. + +/register.bml.trans.header=Success + +/styles/create.bml.choosebase=Choose base style to start with and edit: + +/styles/create.bml.createstyle.head=Create a Style + +/styles/create.bml.createstyle.text=From here you can create a new personal-style, useful if you're going to either embed your journal in your homepage or you want to make a public style that everybody can use and you need to work on it here first, rather than in your overrides section. + +/styles/create.bml.enterstyleid=Or, enter a non-system public Style ID#: + +/styles/create.bml.noneorother=(None, or other below:) + +/styles/create.bml.selecttype.head=Select Style Type + +/styles/create.bml.selecttype.text=A style only affects one view type. If you want to create a matching set of styles for your journal, you have to create your style for each view type. + +/styles/create.bml.submit=Create Style + +/styles/create.bml.title=Create Style + +/styles/create_do.bml.editstyle=Edit Style + +/styles/create_do.bml.error.accounttype=Your account type doesn't permit you to make styles. + +/styles/create_do.bml.error.invalidview=You did not select a valid style type. + +/styles/create_do.bml.error.styleexists=You already have a style of this type named [[des]]. If you really want to create a new style of type [[view]], then go modify your old [[view]] style, change its name, and then come back here to create a new style of this type. + +/styles/create_do.bml.error.stylenotfound=The style you're trying to make a new style from ([[baseid]]) does not seem to exist. + +/styles/create_do.bml.error.stylenotpublic=The style you're trying to make a new style from ([[baseid]]) is not public, so you cannot copy it. + +/styles/create_do.bml.success.head=Success + +/styles/create_do.bml.success.text=Your style has been created and has been temporarily named [[des]]. You can begin editing it by pressing the button below. + +/styles/create_do.bml.title=Create Style + +/styles/index.bml.about<< +

    This section of the site allows you to create, edit and delete +customised styles. This allows you to control the look of your account to a great extent, +whether you want to make it look like your website, or just feel like being different. +

    +

    You can also create embedded styles which, rather than +creating a full page, include only the entries and leave +you to embed your journal in another site.

    +. + +/styles/index.bml.about.header=Creating and Using Custom Styles + +/styles/index.bml.nav.browse=Style Browser + +/styles/index.bml.nav.browse.about=The style browser lets you browse through public styles created by other users. + +/styles/index.bml.nav.create=Create a new style + +/styles/index.bml.nav.create.about=Create a new style from scratch, or base your style on an existing public style. + +/styles/index.bml.nav.edit=Edit or Delete an existing style + +/styles/index.bml.nav.edit.about<< +You may only edit styles “owned” by your account. In order to customize +a system style, you must first create a new style based on that system style. +. + +/styles/index.bml.nav.modify=Modify your account + +/styles/index.bml.nav.modify.about=Change your account's default style, either one of the system provided styles + +/styles/index.bml.title=Custom Styles + +/suggestions/index.bml.howto.text<< +
    +
    Check prior suggestions
    +First, read over past suggestions to make sure that something similar hasn't already been brought up. If it has, you can read the comments on the entry. Sometimes, things might look as though they've been ignored, but they might be in development. Sometimes, ideas are rejected or delayed due to other concerns. +
    +
    Couldn't find your idea? Share it with us!
    +The template must be used for all suggestions. Be sure to fill out all areas of the template, and make sure your suggestion is correct and complete before you post it. Also, the suggestion generator does not add in line breaks, so you can use the <br> tag to produce whitespace. This makes your suggestion easier to read. +
    +
    Submit It!
    +You can add the community to your Friends list here. Once a suggestion is posted, people will discuss it. If we think it's a good idea, it will be added to the list of developer projects, and will be worked on as time permits. Not all suggestions can be implemented immediately, so please be patient with the process. +
    +. + +/suggestions/index.bml.howto.title=How do I make a suggestion? + +/suggestions/index.bml.rules<< +There are a few things to keep in mind: +
      +
    • Many suggestions have already been proposed and discussed, but simply not implemented yet. Be sure that you're not submitting a duplicate.
    • +
    • Flaming will not be tolerated. Everyone has different ideas about how LiveJournal should work; remember that promoting your opinion is all right, but flaming someone else's opinion is not.
    • +
    • Be as thorough as possible with your suggestion. A suggestion that contains detailed implementation notes is more likely to be accepted than one that doesn't. You don't need to know how to program; just try to think about what else your idea would affect, and bring up any problems you can see with it.
    • +
    • Be sure to read the FAQs first, to see if your idea already exists, or if an existing aspect of the site can be used to do what you want.
    • +
    • If you want to ask a question about how the software works, aren't certain if something exists or not, or are having a problem, don't submit a suggestion. Ask Support instead.
    • +
    +. + +/suggestions/index.bml.title=Suggestion Area + +/suggestions/index.bml.welcome.text=In many respects, we're starting from scratch, so, user suggestions are important for us. If you have something that you think would be a useful idea, you can follow these procedures to bring it to the attention of the people who run the site. + +/suggestions/index.bml.welcome.title=Welcome! + +/support/append_request.bml.back.requests=Back to the list of open requests. + +/support/append_request.bml.back.support=Back to the support area. + +/support/append_request.bml.bounce.noemail=No email address specified for bounce. + +/support/append_request.bml.bounce.notauth=You are not authorized to bounce this request. + +/support/append_request.bml.bounce.toomany=You can only send to up to 5 email addresses. You have specified more than 5. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=This support request has since been closed. + +/support/append_request.bml.closed.title=Closed + +/support/append_request.bml.internal.approve=To approve an answer, you must select "Internal Comment / Action" and optionally explain why you're approving it. + +/support/append_request.bml.internal.changecat=To change a request's category, you must select "Internal Comment / Action" and optionally explain why you're changing it. + +/support/append_request.bml.internal.changesum=To change the summary of a request, you must select "Internal Comment / Action" and enter in the new summary. + +/support/append_request.bml.internal.touch=To touch a request, you must select "Internal Comment / Action" and explain why you're touching it. + +/support/append_request.bml.invalid.blank=Your message was blank. Please type at least something in the message field. + +/support/append_request.bml.invalid.noanswer=Invalid screened response to approve. + +/support/append_request.bml.invalid.nocat=That category doesn't seem to exist. + +/support/append_request.bml.invalid.noid=This action requires a support request ID. + +/support/append_request.bml.invalid.nosummary=You must enter a request summary. + +/support/append_request.bml.invalid.type=Invalid Reply Type. + +/support/append_request.bml.logged.text=Your action/comment/response has been recorded. Thanks. + +/support/append_request.bml.logged.title=Success + +/support/append_request.bml.login.required=You must login to help people out. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Append Comment/Response + +/support/append_request.bml.unknown.request=Unknown support request. + +/support/encodings.bml.edit.header=I cannot edit my entries in the web interface! + +/support/encodings.bml.edit.text<< +Short answer: (applicable if you write your journal in English): Go to your +personal settings page. Find an option +neat the bottom of the page that is called Auto-convert older entries from:. Choose +"Western European (Windows)" from the pull-down menu and save your settings. Your entries should +now be editable. p?> + +Long answer: In order to allow you to edit a non-Unicode entry, LiveJournal code needs to +know which encoding that entry has been posted in. For users of English and other West European +languages, this will normally be "Western European (Windows)", although if that doesn't work well +for quote characters and other similar meta-characters, try "Western European (ISO)". Users +writing in other languages should select their encoding; if it isn't in the supplied list, +contact Support and explain the problem. p?> + + +. + +/support/encodings.bml.editcl.header=I cannot edit my entries in the client program! + +/support/encodings.bml.editcl.text<< + +. + +/support/encodings.bml.groups.header=I cannot edit my friend lists with my client program! + +/support/encodings.bml.groups.text<< +group editing page and then use your client program. p?> +. + +/support/encodings.bml.overview.header=What is this all about? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Still stumped? + +/support/encodings.bml.still.text=Support Area. p?> + +/support/encodings.bml.title=Encodings + +/support/faqbrowse.bml.backfaq=Back to the FAQ. + +/support/faqbrowse.bml.backfaqcat=Back to the parent FAQ category. + +/support/faqbrowse.bml.backsupport=Back to the support area. + +/support/faqbrowse.bml.edit.faq=Edit this FAQ + +/support/faqbrowse.bml.error.nofaq=The specified FAQ does not exist. + +/support/faqbrowse.bml.lastupdated=Last Updated: + +/support/faqbrowse.bml.title_cat=FAQ - [[catname]] + +/support/faqbrowse.bml.title_num=FAQ Question #[[num]] + +/support/help.bml.interim=The support queue is intended for use by people with support privileges. + +/support/see_overrides.bml.error.noprivs=Only users with the supportviewinternal or supporthelp privilege can view another user's overrides. + +/support/see_overrides.bml.error.nos1=This user is not using S1. + +/support/see_overrides.bml.header=Overrides for : + +/support/see_overrides.bml.nooverrides=No overrides found for . + +/support/see_overrides.bml.title=User Overrides + +/syn/index.bml.account=Account: + +/syn/index.bml.add=Add Feed + +/syn/index.bml.add.byurl.text=Add a feed to your friends list by entering the feed URL below. + +/syn/index.bml.add.byurl.title=Add Feed by URL + +/syn/index.bml.add.pop.text=The following are some popular feeds you're not currently watching: + +/syn/index.bml.add.pop.title=Add Popular Feed + +/syn/index.bml.add.selected=Add Selected + +/syn/index.bml.back=Back + +/syn/index.bml.create=Create Feed + +/syn/index.bml.create.name=The URL you have entered is not currently being syndicated on this site. Please enter an account name to use to syndicate this feed. + +/syn/index.bml.error.nocreate=The URL you have entered is not currently being syndicated on this site. Your account type does not have the ability to create new syndicated feeds. + +/syn/index.bml.error.unknown=Unknown Error + +/syn/index.bml.feed.url=Feed URL: + +/syn/index.bml.invalid.accountname=Invalid account name. + +/syn/index.bml.invalid.cantadd=You can't add RSS feeds from this site. + +/syn/index.bml.invalid.http.text=There was an error retrieving this URL. The server may be down or the content unavailable at this time. Please verify the URL you have provided and try again. + +/syn/index.bml.invalid.http.title=Error retrieving content + +/syn/index.bml.invalid.inuse.text=That account name is already in use. + +/syn/index.bml.invalid.inuse.title=Username in use + +/syn/index.bml.invalid.needname.text=To add a syndicated account that doesn't exist, go back and give it an account name. + +/syn/index.bml.invalid.needname.title=Need an account name + +/syn/index.bml.invalid.needurl=You must enter either a syndicated account's username or URL to add a new feed. + +/syn/index.bml.invalid.notexist=No syndicated account exists with that username. + +/syn/index.bml.invalid.notrss.text=The URL provided does not appear to contain XML formatted data. + +/syn/index.bml.invalid.notrss.title=Data not XML formatted + +/syn/index.bml.invalid.port=Non-standard port number not allowed + +/syn/index.bml.invalid.reserved=This account name is reserved. Please choose a different account name. + +/syn/index.bml.invalid.submission=Invalid form submission + +/syn/index.bml.invalid.url=The URL you have typed is invalid. Please make sure you have typed the URL correctly and try again. + +/syn/index.bml.loginrequired.text=To manage your syndicated accounts, first login. + +/syn/index.bml.loginrequired.title=Login Required + +/syn/index.bml.promo.text=After you've created a syndicated account, share it with others! The more people there are watching a syndicated account, the more points are freed up to read and create syndicated accounts. Please don't create syndicated accounts unless you are sure they will have many readers. It's prohibited to make a syndication for your own blog. Ask someone else, if you need. + +/syn/index.bml.remove=Remove Selected + +/syn/index.bml.table.account=Account + +/syn/index.bml.table.feed=Feed + +/syn/index.bml.table.watchers=Watchers + +/syn/index.bml.title=Syndication + +/syn/index.bml.user.nomatch=User posting doesn't match user that filled out the form. + +/syn/index.bml.using.text=Here you can add syndicated feeds (RSS) from other sites to your friends list, removing the need to check a dozen sites every day. + +/syn/index.bml.using.title=Using [[sitename]] for syndication + +/syn/list.bml.error.nofeeds=Error: No syndicated feeds have been updated in the past 24 hours. + +/syn/list.bml.feeddesc=Feed Description + +/syn/list.bml.feedurl=Feed URL + +/syn/list.bml.numreaders=Number of readers + +/syn/list.bml.title=Syndicated Feeds + +/syn/list.bml.username=Username + +/syn/list.bml.xml_icon.alt=[View Raw Feed] + +/talkmulti.bml.deleted.body=The comments have been deleted. You can view the rest of the thread here. + +/talkmulti.bml.deleted.title=Comments deleted + +/talkmulti.bml.error.comms_deleted=One of the comments has been deleted since you selected it. For security reasons, please go back and try again. + +/talkmulti.bml.error.inconsistent_data=The supplied data is inconsistent. + +/talkmulti.bml.error.invalid=Invalid parameters specified. + +/talkmulti.bml.error.invalid_mode<< +You have not selected one of the actions. Please go back and choose +if you would like to screen, unscreen, or delete the comments. +. + +/talkmulti.bml.error.login=You are not logged in. + +/talkmulti.bml.error.none_selected=You have not selected any comments. + +/talkmulti.bml.error.privs.delete=You do not have permission to delete these comments. + +/talkmulti.bml.error.privs.screen=You do not have permission to screen these comments. + +/talkmulti.bml.error.privs.unscreen=You do not have permission to unscreen these comments. + +/talkmulti.bml.screened.body=The comments have been screened. You can view them here. + +/talkmulti.bml.screened.title=Comments screened + +/talkmulti.bml.title.delete=Delete Multiple Comments + +/talkmulti.bml.title.screen=Screen Multiple Comments + +/talkmulti.bml.title.unscreen=Unscreen Multiple Comments + +/talkmulti.bml.unscreened.body=The comments have been unscreened. You can view them here. + +/talkmulti.bml.unscreened.title=Comments unscreened + +/talkpost.bml.allowedhtml=Allowed HTML + +/talkpost.bml.error.cannotreplynopost=You cannot reply to a non-existent post + +/talkpost.bml.error.nocommentsjournal=User has disabled comments in their journal. + +/talkpost.bml.error.nocommentspost=User has disabled comments for this particular post. + +/talkpost.bml.error.noreplypost=Replyto post not found (deleted?) + +/talkpost.bml.error.noreply_deleted=This comment had been deleted. You cannot reply to it. + +/talkpost.bml.error.noreply_frozen=This comment is frozen and cannot be replied to. + +/talkpost.bml.error.noreply_screened=This comment is screened and you have no permissions to see it or reply to it. + +/talkpost.bml.label.picturetouse2=Picture to use: + +/talkpost.bml.loganonip=Notice! This user has turned on the option that logs IP addresses of anonymous posters. + +/talkpost.bml.loginq=Login? + +/talkpost.bml.logyourip=Notice! This user has turned on the option that logs your IP address when posting. + +/talkpost.bml.noaccount=Don't have an account? Create one now. + +/talkpost.bml.nosubjecthtml=No HTML allowed in subject + +/talkpost.bml.opt.anonymous=Anonymous + +/talkpost.bml.opt.bannedfrom= - you have been banned from commenting in this journal. + +/talkpost.bml.opt.defpic=(default) + +/talkpost.bml.opt.friendsonly=- this user has disabled anonymous and non-friend posting. You may post here if [[username]] lists you as a friend. + +/talkpost.bml.opt.from=From: + +/talkpost.bml.opt.ljuser=[[sitename]] user: + +/talkpost.bml.opt.ljuser2=[[sitename]] user + +/talkpost.bml.opt.loggedin=Logged in user: [[username]] + +/talkpost.bml.opt.message=Message: + +/talkpost.bml.opt.noanonpost=- this user has disabled anonymous posting. + +/talkpost.bml.opt.noautoformat=Don't auto-format: + +/talkpost.bml.opt.noimage=No Image + +/talkpost.bml.opt.preview=Preview + +/talkpost.bml.opt.spellcheck=Spell check entry before posting + +/talkpost.bml.opt.subject=Subject: + +/talkpost.bml.opt.submit=Post Comment + +/talkpost.bml.opt.willscreen=(will be screened) + +/talkpost.bml.opt.willscreenfriend=(will be screened if not a friend) + +/talkpost.bml.paraformat=Paragraphs will be automatically formatted by default. + +/talkpost.bml.postresponse=Post a comment in response: + +/talkpost.bml.title=Post Comment + +/talkpost.bml.usermismatch<< +You have entered a username, but you have deselected the '[[sitename]] user' option. + +Please either clear the user textbox or select the relevant posting mode and try again. +. + +/talkpost.bml.warnscreened=Notice: This comment is screened. Replying to it will automatically un-screen it and make it visible. + +/talkpost_do.bml.error.badpassword=Incorrect password given for the username specified. You can recover your password here if you've forgotten it. + +/talkpost_do.bml.error.badusername=The [[sitename]] username you specified does not exist. You can recover your username here if you've forgotten it, or you may post as "Anonymous" instead. + +/talkpost_do.bml.error.banned=You are not allowed to post in this user's journal. + +/talkpost_do.bml.error.blankmessage=Your message was blank. Please type at least something in the message field. + +/talkpost_do.bml.error.confused_identity=You entered a username, but selected to post anonymously or as the currently logged in user. Go back and decide which you really want to do. + +/talkpost_do.bml.error.deleted=Your journal has been deleted. You can't post messages. + +/talkpost_do.bml.error.friendsonly=Only friends of [[user]] may post in this journal. + +/talkpost_do.bml.error.lostcookie=Your login cookie seems to have disappeared? + +/talkpost_do.bml.error.manybytes=Sorry, but your comment of [[current]] exceeds the maximum byte length of [[limit]]. Please go back, shorten it, and try posting it again. + +/talkpost_do.bml.error.manychars=Sorry, but your comment of [[current]] characters exceeds the maximum character length of [[limit]]. Please go back, shorten it, and try posting it again. + +/talkpost_do.bml.error.mustlogin=You must be logged in or using a username/password to reply to this protected entry. + +/talkpost_do.bml.error.noanon=You can't post anonymously in this person's journal. + +/talkpost_do.bml.error.noauth=You are not authorized to reply to this protected entry. + +/talkpost_do.bml.error.nocomments=User has disabled commenting on this journal entry. + +/talkpost_do.bml.error.noparent=Cannot reply to a non-existent comment. + +/talkpost_do.bml.error.notafriend=Sorry, user [[user]] does not list you as a friend, and they've set the "friends only" option for who can reply to their journal. + +/talkpost_do.bml.error.nousername=You did not enter your [[sitename]] username. You can choose to post as "Anonymous" if you don't have a [[sitename]] user account. + +/talkpost_do.bml.error.noverify=Sorry, you aren't allowed to post comments in other people's journals until your email address has been verified. If you've lost the confirmation email to do this, you can have it resent from the lost information page. + +/talkpost_do.bml.error.postshared=You can't post as a shared or community account. Shared accounts represent groups of people, not individual people. + +/talkpost_do.bml.error.screened=You have no permission to reply to this screened comment. + +/talkpost_do.bml.error.suspended=Your journal has been suspended. You can't post messages. + +/talkpost_do.bml.error.testacct=Test accounts can only be used in test account journals. + +/talkpost_do.bml.opt.preview=Preview + +/talkpost_do.bml.preview=This is how your comment will look when posted. Using the form below, you can edit your comment further, or you can submit it as is. + +/talkpost_do.bml.preview.subject=Subject: + +/talkpost_do.bml.preview.submit=Submit + +/talkpost_do.bml.preview.title=Preview + +/talkpost_do.bml.success.loggedin=You are now logged in. + +/talkpost_do.bml.success.message=Your comment has been added. You can view it here. + +/talkpost_do.bml.success.screened.comm=Your comment has been added. According to this community's settings, it was marked as screened, and will be visible only to you and the community maintainers until they choose to unscreen it. You can view your comment here. + +/talkpost_do.bml.success.screened.comm.anon=Your anonymous comment has been added. According to this community's settings, it was marked as screened, and will be visible only to the community maintainers until they choose to unscreen it. You can go back to the comment thread here. + +/talkpost_do.bml.success.screened.user=Your comment has been added. According to this journal's settings, it was marked as screened, and will be visible only to you and the journal's owner until the owner chooses to unscreen it. You can view your comment here. + +/talkpost_do.bml.success.screened.user.anon=Your anonymous comment has been added. According to this journal's settings, it was marked as screened, and will be visible only to the journal's owner until the owner chooses to unscreen it. You can go back to the comment thread here. + +/talkpost_do.bml.success.title=Success + +/talkpost_do.bml.success.unscreened=Additionally, the screened comment you were replying to has been unscreened and is now visible. + +/talkpost_do.bml.title=Post Comment + +/talkpost_do.bml.title.error=Comment Not Posted + +/talkpost_do.bml.title.preview=Comment Preview + +/talkread.bml.anonuser=(Anonymous) + +/talkread.bml.button.more=More Options... + +/talkread.bml.button.post=Post Comment + +/talkread.bml.confirm.action=Are you sure you wish to delete the selected comments? + +/talkread.bml.deletedpost=(Deleted post) + +/talkread.bml.deleteduser=(Deleted user: [[username]]) + +/talkread.bml.fromip=(from [[ip]]) + +/talkread.bml.noreplies=No replies + +/talkread.bml.nosubject=(no subject) + +/talkread.bml.posted=Comment Posted Successfully + +/talkread.bml.qr.spellcheck=Check spelling and preview + +/talkread.bml.replysuspended=(Reply from suspended user) + +/talkread.bml.screenedpost=(Screened Post) + +/talkread.bml.select=Select + +/talkread.bml.subjectdeleted=[deleted] + +/talkread.bml.talkmulti.delete=Delete + +/talkread.bml.talkmulti.des=Mass action on selected comments: + +/talkread.bml.talkmulti.screen=Screen + +/talkread.bml.talkmulti.submit=Perform Action + +/talkread.bml.talkmulti.unscreen=Unscreen + +/talkread.bml.title=Read Comments + +/talkscreen.bml.error.login=You must be logged in to work with screened comments. + +/talkscreen.bml.error.privs.freeze=You do not have permission to freeze this thread. + +/talkscreen.bml.error.privs.screen=You do not have permission to screen this comment. + +/talkscreen.bml.error.privs.unfreeze=You do not have permission to unfreeze this thread. + +/talkscreen.bml.error.privs.unscreen=You do not have permission to unscreen this comment. + +/talkscreen.bml.freeze.doit=Yes, freeze this thread + +/talkscreen.bml.freeze.sure.body=Are you sure you want to freeze this thread? No further responses will be allowed to it or any of the comments underneath it. + +/talkscreen.bml.freeze.sure.title=Freeze this thread? + +/talkscreen.bml.frozen.body=The thread has been frozen. + +/talkscreen.bml.frozen.title=Success + +/talkscreen.bml.link=Go back to the post. + +/talkscreen.bml.screen.doit=Yes, screen this comment + +/talkscreen.bml.screen.sure.body=Are you sure you want to screen this comment? + +/talkscreen.bml.screen.sure.title=Screen this comment? + +/talkscreen.bml.screened.body=The comment has been screened. + +/talkscreen.bml.screened.title=Success + +/talkscreen.bml.title2=Change Comment Status + +/talkscreen.bml.unfreeze.doit=Yes, unfreeze this thread + +/talkscreen.bml.unfreeze.sure.body=Are you sure you want to unfreeze this thread? + +/talkscreen.bml.unfreeze.sure.title=Unfreeze this thread? + +/talkscreen.bml.unfrozen.body=The thread has been unfrozen. + +/talkscreen.bml.unfrozen.title=Success + +/talkscreen.bml.unscreen.doit=Yes, unscreen this comment + +/talkscreen.bml.unscreen.sure.body=Are you sure you want to unscreen this comment? + +/talkscreen.bml.unscreen.sure.title=Unscreen this comment? + +/talkscreen.bml.unscreened.body=The comment has been unscreened. + +/talkscreen.bml.unscreened.title=Success + +/tools/emailmanage.bml.address.current.title=Current Address + +/tools/emailmanage.bml.address.old.none=None + +/tools/emailmanage.bml.address.old.text<< +The following is a list of email addresses that were used with your account, +and the time they were deactivated as the primary email address. Check the ones +you wish to delete. +. + +/tools/emailmanage.bml.address.old.title=Previous Addresses + +/tools/emailmanage.bml.delete_selected=Delete Selected + +/tools/emailmanage.bml.desc.notfirst<< +This page only lets you remove email addresses that were used after the first time +you used the email address your account is currently validated with. In particular, +this means the attacker isn't able to remove your original email address. +. + +/tools/emailmanage.bml.desc.text<< +This page lets you remove past email addresses that were used with your account. +By removing them, they'll no longer be able to have your password mailed to them. +This is useful if somebody discovered your password and hijacked your journal. Simply +have the new password mailed to your old address, change it back, and remove the +attacker's email address. +. + +/tools/emailmanage.bml.desc.title=Description + +/tools/emailmanage.bml.log.deleted=Deleted: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Changes Saved + +/tools/emailmanage.bml.notvalidated.text<< +To use this tool, your current email address [[email]] must be validated. +To do this, visit the lost info page, which will +send you an authorization URL. After visiting it, come back here. +. + +/tools/emailmanage.bml.notvalidated.title=Email not validated + +/tools/emailmanage.bml.title=Email Management + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body2=Your list of memorable posts has been updated. You may return to the entry just added. + +/tools/memadd.bml.body.added.header=Success + +/tools/memadd.bml.description=Description: + +/tools/memadd.bml.description.text<< + Give this journal entry a description that you can remember it by. + To delete this entry from your list of memorable posts, enter a blank description. +. + +/tools/memadd.bml.error.deleted.body=The journal entry previously described as "[[desc]]" has been removed from your list of memorable posts. + +/tools/memadd.bml.error.deleted.title=Memory deleted + +/tools/memadd.bml.error.entry_deleted=Journal entry no longer exists. Memory deleted. + +/tools/memadd.bml.error.fivekeywords=Only 5 keywords/categories are allowed per memorable post. + +/tools/memadd.bml.error.invalid_security=Invalid or missing security option. + +/tools/memadd.bml.error.login=You must be logged in to use this feature. Go login and you'll be brought back here. + +/tools/memadd.bml.error.maxsize=This keyword exceeds the maximum allowed size: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +To add a journal entry to your list of memories, you need to provide a description. +To delete a memory, you can edit it and remove the description, but you didn't already have this entry in your memories. +. + +/tools/memadd.bml.error.nodescription.title=No description + +/tools/memadd.bml.form.reset=Reset + +/tools/memadd.bml.form.submit=Submit + +/tools/memadd.bml.keywords=Keywords: + +/tools/memadd.bml.keywords.example=Example: Funny, Geeky, Romantic + +/tools/memadd.bml.keywords.select=Or, you can also select keywords you've used in the past: + +/tools/memadd.bml.keywords.text<< + Why is this post memorable? + Enter up to five comma separated keywords or categories so you can find it later. You can also select keywords you've used in the past. +. + +/tools/memadd.bml.login.enterinfo=Enter username and password of the account you wish to save the memory into. + +/tools/memadd.bml.login.forgot.header=Forget something? + +/tools/memadd.bml.login.forgot.recover=If you forgot your username or password, recover it here!. + +/tools/memadd.bml.multiple_selections=Hold down 'Control' while clicking keywords to select multiple ones. + +/tools/memadd.bml.security=Security: + +/tools/memadd.bml.security.friendsonly=Friends Only + +/tools/memadd.bml.security.private=Private + +/tools/memadd.bml.security.public=Public + +/tools/memadd.bml.title=Add to Memories + +/tools/memadd.bml.title.added=Added + +/tools/memadd.bml.title.add_memory=Add Memorable Entry + +/tools/memadd.bml.title.deleted=Deleted + +/tools/memadd.bml.title.edit_memory=Edit Memorable Entry + +/tools/memadd.bml.whocansee<< + Who can see that you've marked this post as memorable? + Everybody, only people you list as a friend, or just you? +. + +/tools/memadd.bml.whocansee.comm<< + Who can see that you've marked this post as memorable? + Everybody, only members of the community, or only maintainers of the community? +. + +/tools/memories.bml.back=Back + +/tools/memories.bml.body.keyword<< + +[[user]] found memorable. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] has placed memorable journal entries in. p?> +. + +/tools/memories.bml.body.memorable=The following is a list of uncategorized journal entries that user [[user]] found memorable. + +/tools/memories.bml.delete=Delete Selected + +/tools/memories.bml.delete.confirm=You are about to delete one or more memories. Are you sure you want to do this? + +/tools/memories.bml.delete.deleted.head=Success + +/tools/memories.bml.delete.deleted.text=The selected memories have been deleted. You may return to your list of memorable posts. + +/tools/memories.bml.delete.deleted.title=Memories Deleted + +/tools/memories.bml.delete.error.dberror=There was a database error while deleting your memories. The error is [[error]]. Please try again. + +/tools/memories.bml.delete.error.noneselected=You did not select any memories to delete. + +/tools/memories.bml.edit=edit + +/tools/memories.bml.error.noentries.body<< +This could be because:
      +
    1. the user hasn't defined any memorable events,
    2. +
    3. the user's memorable events are protected and you don't have access to view them, or
    4. +
    5. the user doesn't have any memories that match your filter criteria.
    +. + +/tools/memories.bml.error.noentries.title=No memories found. + +/tools/memories.bml.filter.all=All memories + +/tools/memories.bml.filter.other=Only other entries + +/tools/memories.bml.filter.own=Only '[[user]]' entries + +/tools/memories.bml.form.filter=Filter entries by: + +/tools/memories.bml.form.sort=Sort entries by: + +/tools/memories.bml.form.switch=Switch + +/tools/memories.bml.login=In order to view your own memories, please log in. + +/tools/memories.bml.plur_entry=[[num]] [[?num|entry|entries]] + +/tools/memories.bml.sort.description=Description + +/tools/memories.bml.sort.journal=Journal + +/tools/memories.bml.sort.orderadded=Order Added + +/tools/memories.bml.title.keyword=Memorable [[keyword]] Posts + +/tools/memories.bml.title.memorable=Memorable Posts + +/tools/memories.bml.uncategorized=Uncategorized + +/tools/recent_comments.bml.maxnotshown=Your account is only permitted to see the latest [[current]] entries, not the full limit of [[max]]. + +/update.bml.altpost=Journal to post in: + +/update.bml.auth.poster=Poster: + +/update.bml.btn.preview=Preview + +/update.bml.btn.update=Update Journal + +/update.bml.currmood=Current Mood: + +/update.bml.currmusic=Current Music: + +/update.bml.date=Date: + +/update.bml.default=default + +/update.bml.defaultjournal=([[user]]) -- default + +/update.bml.error.cantpost=Sorry, you cannot post at this time. + +/update.bml.error.disabled=Your account type does not permit posting. + +/update.bml.error.disabled.title=Posting access disabled + +/update.bml.error.login=Error logging on: + +/update.bml.error.nopass=Enter Password + +/update.bml.error.update=Error updating journal: + +/update.bml.event=Event: + +/update.bml.full=Full Update Page + +/update.bml.htmlokay.norich=(HTML okay; by default, newlines will be auto-formatted to <br>) + +/update.bml.htmlokay.rich=(HTML okay; by default, newlines will be auto-formatted to <br> - or, use the rich text mode.) + +/update.bml.htmlokay.rte_nosupport=(Sorry, your browser does not currently support the rich text environment.) + +/update.bml.localtime=Local time: + +/update.bml.loggedinas=You are currently logged in as [[user]].
    To post as another user, click here. + +/update.bml.loggingin=Logging in to server... + +/update.bml.noneother=None, or other: + +/update.bml.note=Note: The time/date above is from our server. Correct them for your timezone before posting. + +/update.bml.opt.backdate=Backdate Entry: + +/update.bml.opt.backdate.about=won't show on friends view + +/update.bml.opt.defpic=(default) + +/update.bml.opt.nocomments=Disallow Comments: + +/update.bml.opt.noemail=Don't email Comments: + +/update.bml.opt.noformat=Don't auto-format: + +/update.bml.opt.spellcheck=Spell check entry before posting + +/update.bml.options=Optional Settings + +/update.bml.other=Other: + +/update.bml.password=Password: + +/update.bml.picture=Picture to use: + +/update.bml.preview.header=Preview + +/update.bml.preview.text=This is how the entry will look when posted. Using the form below, you can edit the entry further, or you can submit it as is. + +/update.bml.rowarn=Warning: Your account is currently in [[a_open]]read-only mode[[a_close]]. Due to this maintenance you may be unable to post to your journal at this time. + +/update.bml.security.custom=Custom... + +/update.bml.security.friends=Friends + +/update.bml.security.head=Security Level: + +/update.bml.security.private=Private + +/update.bml.security.public=Public + +/update.bml.servermsg=Also, the server has a message for you: + +/update.bml.simple=You're looking at the simple page. For more options, click here. + +/update.bml.spellchecked=Your spell-checked post: + +/update.bml.subject=Subject: (optional, for use on longer entries) + +/update.bml.success.links=Now that you've posted, you can: + +/update.bml.success.links.edit=Edit the entry + +/update.bml.success.links.memories=Add the entry to your memories + +/update.bml.success.links.tags=Edit this entry's tags + +/update.bml.success.links.view=View the entry + +/update.bml.timeformat=24 hour time + +/update.bml.title=Update Journal + +/update.bml.title.readonly=Read-only mode + +/update.bml.update.alternate=If you don't want to download a client for your computer, or if one doesn't exist for your computer, you may use this page to update your journal. This is also useful if you're on vacation or away from your primary computer. + +/update.bml.update.head=Update your Journal... + +/update.bml.update.success=Update successful. You may view your updated journal here. + +/update.bml.updating=Updating journal... + +/update.bml.username=Username: + +/uploadpic.bml.error.unsupportedtype=Files of type [[filetype]] are not supported. You can only upload GIF, PNG or JPG files. Nearly all image/photo programs can do this conversion for you. + +/userinfo.bml.about.comm=About: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.body.leave= You may leave the community at any time. + +/userinfo.bml.comminfo.body=Below is information about the "[[commname]]" community on [[sitename]]. + +/userinfo.bml.comminfo.name=Community Information + +/userinfo.bml.date.never=Never. + +/userinfo.bml.error.malfname=Malformed username. + +/userinfo.bml.error.notloggedin=If you wish to view your own user profile, you need to login. + +/userinfo.bml.fbpictures.lessthan=less than [[count]] public + +/userinfo.bml.fbpictures.over=over [[count]] public + +/userinfo.bml.friendof.comm=Watched by: + +/userinfo.bml.friendof.hidden=(hidden) + +/userinfo.bml.friendof.syndreadcount=Number of Readers + +/userinfo.bml.friendof.user=Friend of: + +/userinfo.bml.friends.comm=Members + +/userinfo.bml.friends.user=Friends + +/userinfo.bml.label.addbuddy=Add Buddy + +/userinfo.bml.label.adduser=Add User + +/userinfo.bml.label.alsofriendof=Also Friend of: + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=Birthdate: + +/userinfo.bml.label.clientsused=Clients used: + +/userinfo.bml.label.comments=Comments: + +/userinfo.bml.label.composted=Posted: [[num]] - + +/userinfo.bml.label.comreceived=Received: [[num]] + +/userinfo.bml.label.datecreated=Date created: + +/userinfo.bml.label.dateupdated=Date updated: + +/userinfo.bml.label.email=Email: + +/userinfo.bml.label.fbpictures=Pictures: + +/userinfo.bml.label.frcommunity=Communities + +/userinfo.bml.label.frpeople=People + +/userinfo.bml.label.frsyndication2=Feeds + +/userinfo.bml.label.icquin=ICQ UIN: + +/userinfo.bml.label.interests=Interests + +/userinfo.bml.label.interests.modifyyours=Modify yours + +/userinfo.bml.label.interests.removesome=Remove some + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] interests not shown + +/userinfo.bml.label.jabber=Jabber: + +/userinfo.bml.label.journalentrs=Journal entries: + +/userinfo.bml.label.location=Location: + +/userinfo.bml.label.memberof=Member of + +/userinfo.bml.label.memories=Memories: + +/userinfo.bml.label.moredetails=(more details...) + +/userinfo.bml.label.msnusername=MSN Username: + +/userinfo.bml.label.mutual=Mutual Friends: + +/userinfo.bml.label.name=Name: + +/userinfo.bml.label.nofriends=None listed. + +/userinfo.bml.label.post=Post to "[[journal]]" + +/userinfo.bml.label.postalt=Update your journal + +/userinfo.bml.label.reqfinduser=Only users with 'finduser' priv can lookup users by userid. + +/userinfo.bml.label.searchjournal=Search This Journal + +/userinfo.bml.label.sendmessage=Send Message + +/userinfo.bml.label.shared=Posting Access: + +/userinfo.bml.label.supportpoints=Support points + +/userinfo.bml.label.syndicatedfrom=Syndicated from: + +/userinfo.bml.label.syndicatedstatus=Syndication Status: + +/userinfo.bml.label.textmessage=Text
    Message
    : + +/userinfo.bml.label.todo=To-Do List + +/userinfo.bml.label.user=User: + +/userinfo.bml.label.userprofile=User Profile + +/userinfo.bml.label.viewfriends=View Friends + +/userinfo.bml.label.viewmembers=View Members + +/userinfo.bml.label.website=Website: + +/userinfo.bml.label.yahooid=Yahoo! ID: + +/userinfo.bml.membership.body=To join this community, click here. + +/userinfo.bml.memories.entries=[[count]] entries + +/userinfo.bml.memories.entry=[[count]] entry + +/userinfo.bml.monitor.comm=Monitor Community + +/userinfo.bml.monitor.user=Add this user to your friends list + +/userinfo.bml.nonexist.body=The username [[user]] is not currently registered. + +/userinfo.bml.nonexist.name=Unknown user + +/userinfo.bml.sendmessage.body=Send [[user]] a text message
    on his/her cellphone/pager. + +/userinfo.bml.syn.last.never=Never + +/userinfo.bml.syn.lastcheck=Last checked: + +/userinfo.bml.syn.nextcheck=Next check: + +/userinfo.bml.syn.parseerror=Error Message: + +/userinfo.bml.syndinfo.body<< +If you would like articles from the syndicated site to appear on your friends page, +you can add this journal to your friends list. +. + +/userinfo.bml.syndinfo.name=Syndication Journal + +/userinfo.bml.tellafriend=Tell a Friend! + +/userinfo.bml.timeupdate.dayago=1 day ago + +/userinfo.bml.timeupdate.daysago=[[num]] days ago + +/userinfo.bml.timeupdate.hourago=1 hour ago + +/userinfo.bml.timeupdate.hoursago=[[num]] hours ago + +/userinfo.bml.timeupdate.minuteago=1 minute ago + +/userinfo.bml.timeupdate.minutesago=[[num]] minutes ago + +/userinfo.bml.timeupdate.secondago=1 second ago + +/userinfo.bml.timeupdate.secondsago=[[num]] seconds ago + +/userinfo.bml.timeupdate.weekago=1 week ago + +/userinfo.bml.timeupdate.weeksago=[[num]] weeks ago + +/userinfo.bml.title=User Info + +/userinfo.bml.title.communityinfo=Community Info + +/userinfo.bml.title.syndicated=Syndicated Account + +/userinfo.bml.userinfo.body=Below is user information for [[username]]. If you are this user, you can edit your information (or choose what information is considered public) at the Edit Info page. + +/userinfo.bml.userinfo.name=User Information + +Actionlink=[[[link]]] + +Backlink=[<< [[text]]] + +bml.badcontent.body=One or more errors occurred processing your request. Please go back, correct the necessary information, and submit your data again. + +bml.badinput.body=Your browser sent some text which is not recognised as valid text in the UTF-8 encoding, as it should be. This might happen if you forced your browser to view the previous page in some other encoding rather than UTF-8. It may also indicate a bug in the browser. If you cannot get around this error, contact us. + +bml.badinput.head=Bad Unicode Input + +bml.needlogin.body2=In order to view this page, you must log in. + +bml.needlogin.head=Login Required + +BML.parse_multipart.parse=Error parsing upload + +BML.parse_multipart.toolarge=Upload too large + +BML.parse_multipart.unknowntype=Unknown content type + +bml.requirepost=As a security precaution, the page you're viewing requires a POST request, not a GET. If you're trying to submit this form legitimately, please contact us. + +btn.search=Search + +crumb.about=About [[sitename]] + +crumb.abusereport=Report Abuse to the local KGB (you sure you want to do this?) + +crumb.acctfeatures=Features By Account Type + +crumb.acctstatus=Account Status + +crumb.addfriend=Add Friend + +crumb.addtodo=Add To-Do Item + +crumb.advcustomize=Customize Advanced S2 Settings + +crumb.advsearch=Advanced + +crumb.banners=Advertising Banners + +crumb.birthdays=Birthdays + +crumb.changepass=Change Password + +crumb.comminvites=Community Invitations + +crumb.commmembers=Community Membership + +crumb.commpending=Pending Memberships + +crumb.commsearch=Community Search + +crumb.commsentinvites=Sent Invitations + +crumb.commsettings=Community Settings + +crumb.community=Community Center + +crumb.contract=Our Social Contract + +crumb.contributors=Contributors + +crumb.createcommunity=Create Community + +crumb.createjournal=Create Journal + +crumb.createstyle=Create Style + +crumb.customize=Customize S2 Settings + +crumb.delcomment=Delete Comment + +crumb.editentries=Edit Entries + +crumb.editentries_do=Edit Entry + +crumb.editfriendgrps=Edit Friends Groups + +crumb.editfriends=Edit Friends + +crumb.editinfo=Personal Info + +crumb.editpics=User Pictures + +crumb.editstyle=Edit Style + +crumb.emailgateway=Email Gateway + +crumb.emailmanage=Email Management + +crumb.encodings=About Encodings + +crumb.export=Export Journal + +crumb.faq=Frequently Asked Questions + +crumb.feedstersearch=Search a Journal + +crumb.filemanager=File Manager + +crumb.friends=Friends Tools + +crumb.friendsfilter=Friends Filter + +crumb.guidingprinciples=Our Guiding Principles + +crumb.home=Home + +crumb.itsfree=It's Free? + +crumb.joincomm=Join Community + +crumb.latestposts=Latest Posts + +crumb.layerbrowse=Public Layer Browser + +crumb.leavecomm=Leave Community + +crumb.linkslist=Your Links + +crumb.login=Login + +crumb.logout=Logout + +crumb.lostinfo=Lost Info + +crumb.manage=Manage Accounts + +crumb.managecommunity=Community Management + +crumb.meme=Meme Tracker + +crumb.memories=Memorable Posts + +crumb.moderate=Community Moderation + +crumb.modify=Journal Settings + +crumb.moodlist=Mood Viewer + +crumb.news=News + +crumb.paidaccounts=Paid Accounts + +crumb.paidacctstatus=Paid Account Status + +crumb.phonepostsettings=Phone Post + +crumb.popfaq=Popular FAQs + +crumb.preview=Layout Previews + +crumb.privacy=Privacy Policy + +crumb.register=Validate Email + +crumb.search=Search + +crumb.searchinterests=By Interest + +crumb.searchregion=By Region + +crumb.securechangepass=Change Password + +crumb.securecreatejournal=Create Journal + +crumb.securelogin=Login + +crumb.securemanage=Manage Accounts + +crumb.seeoverrides=View User Overrides + +crumb.setpgpkey=Public Key + +crumb.singles=LiveJournal Singles + +crumb.singlesopts=Modify Availability + +crumb.singlessearch=Search for Singles + +crumb.sitemap=Site Map + +crumb.siteopts=Browse Preferences + +crumb.sizechart=Sizing Chart + +crumb.stats=Statistics + +crumb.styles=Styles + +crumb.suggestions=Suggestions Generator + +crumb.suggview=Suggestions + +crumb.support=Support + +crumb.supportact=Request Action + +crumb.supportappend=Append to Request + +crumb.supporthelp=Request Board + +crumb.supportnotify=Notification Settings + +crumb.supportscores=High Scores + +crumb.supportsubmit=Submit Request + +crumb.textmessage=Send Text Message + +crumb.themes=Theme Previews + +crumb.todo=Todo List + +crumb.tos=Terms of Service + +crumb.transfercomm=Transfer Community + +crumb.unsubscribe=Unsubscribe + +crumb.update=Update Journal + +crumb.utf8convert=UTF-8 Converter + +crumb.yourlayers=Your Layers + +crumb.yourstyles=Your Styles + +date.day.friday.long=Friday + +date.day.friday.short=Fri + +date.day.monday.long=Monday + +date.day.monday.short=Mon + +date.day.saturday.long=Saturday + +date.day.saturday.short=Sat + +date.day.sunday.long=Sunday + +date.day.sunday.short=Sun + +date.day.thursday.long=Thursday + +date.day.thursday.short=Thu + +date.day.tuesday.long=Tuesday + +date.day.tuesday.short=Tue + +date.day.wednesday.long=Wednesday + +date.day.wednesday.short=Wed + +date.month.april.long=April + +date.month.april.short=Apr + +date.month.august.long=August + +date.month.august.short=Aug + +date.month.december.long=December + +date.month.december.short=Dec + +date.month.february.long=February + +date.month.february.short=Feb + +date.month.january.long=January + +date.month.january.short=Jan + +date.month.july.long=July + +date.month.july.short=Jul + +date.month.june.long=June + +date.month.june.short=Jun + +date.month.march.long=March + +date.month.march.short=Mar + +date.month.may.long=May + +date.month.may.short=May + +date.month.november.long=November + +date.month.november.short=Nov + +date.month.october.long=October + +date.month.october.short=Oct + +date.month.september.long=September + +date.month.september.short=Sep + +dystopia.btn.login=LOGIN + +dystopia.hello_anonymous=Welcome to [[sitename]]! + +dystopia.hello_loggedin=Hello, [[username]]! + +dystopia.nav.contact=Contact Info + +dystopia.nav.createjournal=Create a Journal + +dystopia.nav.developer=Developer Area + +dystopia.nav.editentries=Edit Entries + +dystopia.nav.editfriends=Your Friends + +dystopia.nav.editpassword=Your Password + +dystopia.nav.editpics=Your Pictures + +dystopia.nav.editstyle=Edit Style + +dystopia.nav.faq=FAQ + +dystopia.nav.findcomm=By Community + +dystopia.nav.finddir=Directory Search + +dystopia.nav.findint=By Interest + +dystopia.nav.findrandom=Random + +dystopia.nav.findregion=By Region + +dystopia.nav.home=Home + +dystopia.nav.journalcalendar=Calendar + +dystopia.nav.journalfriends=Friends + +dystopia.nav.journalinfo=User Info + +dystopia.nav.journalrecent=Recent + +dystopia.nav.legaltos=Terms of Service + +dystopia.nav.login=Login + +dystopia.nav.logout=Logout + +dystopia.nav.lostinfo=Lost Password + +dystopia.nav.manage=Manage Accounts + +dystopia.nav.memories=Memories + +dystopia.nav.modifyjournal=Modify Journal + +dystopia.nav.news=News + +dystopia.nav.paidaccts=Paid Accounts + +dystopia.nav.paymentarea=Payment Area + +dystopia.nav.personalinfo=Personal Info + +dystopia.nav.sitemap=Site Map + +dystopia.nav.siteopts=Browse Options + +dystopia.nav.support=Have a question? + +dystopia.nav.updatejournal=Update Journal + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=122 + +dystopia.navhead.findusers=Find Users + +dystopia.navhead.help=Help & Support + +dystopia.navhead.journal=Your Journal + +dystopia.navhead.settings=Your Settings + +dystopia.navhead.welcome=Welcome! + +dystopia.search.icq=ICQ Number + +dystopia.search.int=Interest + +dystopia.search.jabber=Jabber + +dystopia.search.region=Region + +dystopia.searchlj=Search [[sitename]]: + +Email=Email + +email.newacct.body|notes=This string is no longer in use, please translate email.newacct2.body instead. +email.newacct.body<< +Congratulations, you have a new [[sitename]] account! + +To complete your journal creation and verify your email address, go +here: + + [[regurl]] + +The URL that your new journal is located at is: + + [[siteroot]]/users/[[username]]/ + +and also: + + [[siteroot]]/~[[username]]/ + +Below is your [[sitename]] username and password: + + Username: [[username]] + Password: [[password]] + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Welcome to [[sitename]] + +email.newacct2.body|notes=This string replaces email.newacct.body. You may refer to the old string while translating if you wish. +email.newacct2.body<< +Congratulations, you have a new [[sitename]] account! + +To complete your journal creation and verify your email address, +please visit the following location. Verifying your email address +will help to protect your account as well as allow you to utilize +more features within your journal. + + [[regurl]] + +You may access your journal at the following two URLs: + + [[siteroot]]/users/[[username]]/ + [[siteroot]]/~[[username]]/ + +Below is your [[sitename]] username that you registered: + + Username: [[username]] + +If you need to retrieve your password, you can do so at any time by +visiting the following URL: + + [[siteroot]]/lostinfo.bml + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +entryform.backdated=Entry is Backdated: + +entryform.comment.screening=Screen Comments: + +entryform.comment.settings=Comment Settings: + +entryform.comment.settings.default=Default + +entryform.comment.settings.nocomments=Disabled + +entryform.comment.settings.noemail=Don't E-mail + +entryform.date=Date: + +entryform.date.24hournote=(24 hour time) + +entryform.delete=Delete Entry + +entryform.delete.confirm=Are you sure you want to delete this entry? + +entryform.deletespam=Delete and Mark as Spam + +entryform.deletespam.confirm=Are you sure you want to delete this entry and mark it as spam? + +entryform.entry=Entry: + +entryform.format=Text Formatting: + +entryform.format.auto=Auto + +entryform.format.preformatted=None + +entryform.htmlokay.norich=(HTML okay; by default, newlines will be auto-formatted to <br>) + +entryform.htmlokay.rich=(HTML okay; by default, newlines will be auto-formatted to <br> - or, use the rich text mode.) + +entryform.htmlokay.rte_nosupport=rte_nosupport=(Sorry, your browser does not currently support the rich text environment.) + +entryform.mood=Mood: + +entryform.mood.noneother=None, or other: + +entryform.music=Music: + +entryform.nojstime.note=Note: The time/date above is from our server. Correct them for your timezone before posting. + +entryform.opt.defpic=(default) + +entryform.options=Options: + +entryform.postto=Post to: + +entryform.preview=Preview + +entryform.save=Save Entry + +entryform.security=Security: + +entryform.spellcheck=Spell check + +entryform.spellcheck.noerrors=No spelling errors found + +entryform.spellchecked=Spell checked entry: + +entryform.subject=Subject: + +entryform.tags=Tags: + +entryform.update=Update Journal + +entryform.userpics=User Picture Icon: + +error.badpassword=Incorrect Password. + +error.code.comm_not_comm=Account is not a community + +error.code.comm_not_found=Community not found + +error.code.comm_not_member=User is not a member of this community + +error.dberror=A database error occurred: + +error.deleted.name=Deleted + +error.deleted.text=This journal has been deleted. If you are [[user]], you have a period of 30 days from the deletion time to undelete the journal. After 30 days we will delete all content permanently from our servers. + +error.deleted.title=Deleted Account + +error.expiredchal=Login window expired. Please try again. + +error.invalidauth=You could not be authenticated as the specified user. + +error.invalidform=Invalid form submission. Please refresh and try again. + +error.ipbanned=Your IP address is temporarily banned for exceeding the login failure rate. + +error.malformeduser=Malformed username. + +error.nobutton=No button pressed? + +error.nocommlogin=Logging in as a community has been disabled. + +error.nodb=Database temporarily unavailable. + +error.nodbmaintenance=This part of the database is temporarily down for maintenance. Try again in a few minutes. + +error.noentry=No such journal entry. + +error.nojournal=Unknown Journal + +error.noremote=You have to login in order to use this page. + +error.procrequest=There was an error processing your request: + +error.purged.name=Deleted + +error.purged.text=This journal has been deleted and purged. + +error.purged.title=Purged Account + +error.suspended.name=Suspended + +error.suspended.text=This journal has been either temporarily or permanently suspended by [[sitename]] for policy violation. If you are [[user]], contact us for more information. + +error.suspended.title=Suspended Account + +error.tempdisabled=This is disabled temporarily. + +error.unknownmode=Unknown mode. + +error.usernameinvalid=Username contains invalid characters. + +error.usernamelong=Username is too long, 15 character max. + +error.username_notfound=Username not found. + +Help=Help + +label.screening.all=All comments + +label.screening.anonymous=Anonymous only + +label.screening.default=Default + +label.screening.header=Screened Comments: + +label.screening.none=None + +label.screening.nonfriends=By non-friends + +label.security.custom=Custom... + +label.security.friends=Friends + +label.security.head=Security Level: + +label.security.maintainers=Maintainers + +label.security.members=Members + +label.security.private=Private + +label.security.public=Public + +label.switch.button=Switch + +label.switch.header=Switch Journal + +label.switch.workwith=Work with journal: + +label.warning=Warning: + +langname.en=English + +langname.ru=Russian + +langname.sb=Siberian + +langname.uk=Ukrainian + +ljcom.account.feature=Feature + +ljcom.account.feature.email=[[sitename]] e-mail address + +ljcom.account.feature.full2=For the full table, see this page. + +ljcom.account.feature.limit=limited + +ljcom.account.feature.ownblog=Your own journal/weblog + +ljcom.account.feature.photo=100MiB Integrated photo hosting + +ljcom.account.feature.pp=Phone Posting + +ljcom.account.feature.search=Directory search + +ljcom.account.feature.styles=Create/customize styles + +ljcom.account.feature.syn=Friends and syndicated feeds aggregator + +ljcom.account.free=Free Account + +ljcom.account.paid=Paid Account + +ljcom.account.paid12=Paid for 12 Months + +ljcom.account.paid2=Paid for 2 Months + +ljcom.account.paid6=Paid for 6 Months + +ljcom.accounttype=Account Type + +ljcom.badpass.email=Your password cannot be based on your e-mail address. + +ljcom.badpass.realname=Your password cannot be based on your real name. + +ljcom.badpass.username=Your password cannot be based on your username. + +ljcom.menu.upgrade=Upgrade your account + +ljcom.userinfo.accounttype=Account type + +ljcom.userinfo.paiduser=Paid User + +ljcom.userinfo.types.early=Early Adopter + +ljcom.userinfo.types.free=Free Account + +ljcom.userinfo.types.paid=Paid Account + +ljcom.userinfo.types.paid_early=Paid Account, previously an Early Adopter + +ljcom.userinfo.types.paid_early_expiring=Paid Account, expiring [[paiduntil]], previously an Early Adopter + +ljcom.userinfo.types.paid_expiring=Paid Account, expiring [[paiduntil]] + +ljcom.userinfo.types.permanent=Permanent Account + +ljcom.userinfo.types.permanent_early=Permanent Account, previously an Early Adopter + +ljlib.pageofpages=Page [[page]] of [[total]] + +ljrlook.nav.calendar=Calendar + +ljrlook.nav.changepassword=Password + +ljrlook.nav.communities.manage=Communities + +ljrlook.nav.create=Create journal + +ljrlook.nav.createstyle=Create style + +ljrlook.nav.customize=Customize S2 + +ljrlook.nav.edit=Edit... + +ljrlook.nav.editfriends=Friends + +ljrlook.nav.editinfo=Info & Settings + +ljrlook.nav.editjournal=Journal entries + +ljrlook.nav.editpics=Pictures + +ljrlook.nav.editstyle=Edit style + +ljrlook.nav.friends=Friends + +ljrlook.nav.frills=Frills + +ljrlook.nav.fullupdate=Full update + +ljrlook.nav.hello=Hello + +ljrlook.nav.ljfif=ljr_fif + +ljrlook.nav.login=Log in + +ljrlook.nav.logout=Log out + +ljrlook.nav.lostinfo=Lost password? + +ljrlook.nav.memories=Memories + +ljrlook.nav.modify=Modify journal + +ljrlook.nav.needhelp=Help + +ljrlook.nav.news=News + +ljrlook.nav.paidaccounts=Paid Accounts + +ljrlook.nav.recent=Recent + +ljrlook.nav.site=[[sitename]] + +ljrlook.nav.siteopts=Options + +ljrlook.nav.support=Support + +ljrlook.nav.support.faq=FAQ + +ljrlook.nav.update=Update journal + +ljrlook.nav.userinfo=User Info + +ljrlook.nav.yourjournal=Your journal + +lostinfo.head=Forget something? + +lostinfo.text=If you forgot your username or password, recover it here. + +lynx.nav.friends=Friends + +lynx.nav.help=Technical Support + +lynx.nav.home=Home + +lynx.nav.login=Login + +lynx.nav.logout=Logout + +lynx.nav.recent=Recent Entries + +lynx.nav.sitemap=Site Map + +lynx.nav.siteopts=Browse Options + +lynx.nav.update=Update Journal + +Password=Password + +password.max30=Passwords may not be longer than 30 characters. + +poll.dberror=Database error: [[errmsg]] + +poll.dberror.items=Database error inserting items: [[errmsg]] + +poll.dberror.questions=Database error inserting questions: [[errmsg]] + +poll.error.badmaxlength=Maxlength attribute on lj-pq text tags must be an integer from 1-255. + +poll.error.badsize=Size attribute on lj-pq text tags must be an integer from 1-100. + +poll.error.cantview=Error: you don't have access to view these poll results. + +poll.error.cantvote=Sorry, you don't have permission to vote in this particular poll. + +poll.error.missingljpoll=All lj-pq tags must be nested inside an enclosing lj-poll tag. + +poll.error.missingljpq=All lj-pi tags must be nested inside an enclosing lj-pq tag. + +poll.error.nested=You cannot nest [[tag]] tags. Did you forget to close one? + +poll.error.noentry=Error: this poll is not attached to this journal entry + +poll.error.noitems=You must have at least one item in a non-text poll question. + +poll.error.noitemstext=lj-pq tags of type 'text' cannot have poll items in them. + +poll.error.nopollid=pollid parameter is missing. + +poll.error.noquestions=You must have at least one question in a poll. + +poll.error.notext=Need text inside an lj-pq tag to say what the question is about. + +poll.error.pitoolong=Text inside an lj-pi tag must be between 1 and 255 characters. Yours is [[len]]. + +poll.error.pollnotfound=Error: poll #[[num]] not found + +poll.error.questionnotfound=Error: this poll question doesn't exist. + +poll.error.scalefromlessto=Scale 'from' value must be less than 'to' value. + +poll.error.scaleincrement=Scale increment must be at least 1. + +poll.error.scaletoobig=Your scale exceeds the limit of 20 selections (to-from)/by > 20. + +poll.error.tagnotopen=You cannot close an [[tag]] tag that's not open. + +poll.error.truncated=... truncated + +poll.error.unknownpqtype=Unknown type on lj-pq tag. + +poll.error.unlockedtag=Unlocked [[tag]] tag. + +poll.error.whoview=whoview must be 'all', 'friends', or 'none'. + +poll.error.whovote=whovote must be 'all' or 'friends'. + +poll.pollnum=Poll #[[num]] + +poll.scaleanswers=Mean: [[mean]] Median: [[median]] Std. Dev [[stddev]] + +poll.security=Open to: [[whovote]], results viewable to: [[whoview]] + +poll.security.all=All + +poll.security.friends=Friends + +poll.security.none=None + +poll.submit=Submit Poll + +poll.viewanswers=View Answers + +portal.bdays.count.des=By default, the 5 friends with the soonest birthdays are shown. + +portal.bdays.count.name=Birthdays to Display + +portal.bdays.portalname=Birthdays + +portal.bdays.portaltitle=Birthdays + +portal.login.portalname=Login Box + +portal.memories.entriesnoun=entries + +portal.memories.entrynoun=entry + +portal.memories.portalname=Memorable Posts + +portal.memories.portaltitle=Memorable Posts + +portal.ministats.active=Active: + +portal.ministats.title=User Stats + +portal.ministats.total=Total: + +portal.newtolj.name=Site Links + +portal.popfaq.portalname=10 Most Viewed FAQs + +portal.popfaq.portaltitle=10 Most Viewed FAQs + +portal.randuser.count.des=By default, 1 random user is shown, but you can have up to 10 vertically in the narrow columns, or 5 horizontally in a wide column + +portal.randuser.count.name=Number of random users to show + +portal.randuser.error.tableempty=There are no random users. Contact admin. + +portal.randuser.hidename.des=By default, the random user name is shown. Check this to remove it. + +portal.randuser.hidename.name=Hide Name + +portal.randuser.hidepic.des=By default, the random user picture is shown, if available. Check this to remove it. + +portal.randuser.hidepic.name=Hide User Picture + +portal.randuser.portalname=Random User + +portal.randuser.portaltitle=Random User + +portal.randuser.portaltitleplural=Random Users + +portal.recent.error.noentries=Sorry. No entries. + +portal.recent.error.notsetup=You have to configure this box. Click the plus symbol to setup the journal you'd like to watch here. + +portal.recent.error.userstatus=User has deleted or suspended their account. + +portal.recent.items.description=By default, only the most recent entry is shown. + +portal.recent.items.name=Items to display + +portal.recent.journal.description=What journal do you want to see the recent items from? + +portal.recent.journal.name=Journal + +portal.recent.nosubject=(No Subject) + +portal.recent.permlink=Link + +portal.recent.portalname=Recent Entry View + +portal.recent.portaltitle=Recent Entry Box + +portal.recent.showtext.description=By default only subjects will be shown. + +portal.recent.showtext.name=Include Text + +portal.stats.journalentyest=Journal entries yesterday + +portal.stats.portalname=Site Statistics + +portal.stats.portaltitle=Statistics + +portal.stats.totalusers=Total users + +portal.update.mode.des=Full mode gives you a ton of extra posting options ... including posting in communities and setting your current mood, music, and picture. Simple mode is nicer if you hardly use those features and would prefer not to see it all. + +portal.update.mode.full=Full + +portal.update.mode.name=Mode + +portal.update.mode.simple=Simple + +portal.update.portalname=Journal Update + +portal.update.portaltitle=Update Your Journal + +protocol.bad_password=Your password is too easy to guess. It's recommended that you change it, otherwise you risk having your journal hijacked. Visit [[siteroot]]/changepassword.bml to change your password. + +protocol.hello_test=Hello Test Account! + +protocol.mail_bouncing=You are currently using a bad email address. All mail we try to send you is bouncing. We require a valid email address for continued use. Visit the support area for more information. + +protocol.modpost=Your entry has been put into the moderation queue. It will be accepted or rejected by one of the community moderators. + +protocol.must_revalidate=You need to validate your new email address. Your old one was good, but since you've changed it, you need to re-validate the new one. Visit [[siteroot]]/support for more information. + +protocol.not_validated=You are currently not validated. You may continue to use [[sitename]], but please validate your email address for continued use. See the instructions that were mailed to you when you created your journal, or see [[siteroot]]/support/ for more information. + +protocol.old_win32_client=There are significantly newer Windows LiveJournal clients available, and we recommend that you upgrade. Visit [[siteroot]]/download/ to download a newer client. + +protocol.readonly=Your account is temporarily in read-only mode. Some operations will fail for a few minutes. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Sorry + +talk.anonwrote=Someone wrote, + +talk.anonwrote_comm=Someone wrote in [[commlink]], + +talk.btn.preview=Preview + +talk.commentpermlink=link + +talk.commentpost=Post a new comment + +talk.commentsread=Read comments + +talk.curname_Mood=Current mood: + +talk.curname_Music=Current music: + +talk.curname_Tags=Entry tags: + +talk.error.bogusargs=Bogus arguments + +talk.error.comm_deleted=This comment has been deleted. + +talk.error.deleted=This journal is deleted. + +talk.error.deleted.title=Deleted + +talk.error.mustlogin=You must be logged in to view this protected entry. + +talk.error.nocomment=The comment does not exist. + +talk.error.noentry=No such entry. + +talk.error.nojournal=Error: couldn't determine journal from arguments. + +talk.error.nosuchjournal=No such journal + +talk.error.notauthorised=You are not authorized to view this protected entry. + +talk.error.suspended=This journal/poster is suspended. + +talk.error.suspended.title=Suspended + +talk.frozen=Replies frozen + +talk.parentlink=Parent + +talk.readsimilar=Read similar journal entries: + +talk.replytothis=Reply to this + +talk.somebodywrote=[[realname]] ([[userlink]]) wrote, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) wrote in [[commlink]], + +talk.spellcheck=Check spelling during preview + +talk.threadlink=Thread + +tos.error=You must read and agree to the terms of service. + +tos.haveread=I have read and agree to the Terms of Service. + +tos.mustread=Before continuing you must read and agree to the Terms of Service. + +Username=Username + +userpic.inactive=Inactive + +xcolibur.greeting.anon=Welcome! + +xcolibur.greeting.logged_in=Welcome, [[name]]! [[logout]] + +xcolibur.login=Login? + +xcolibur.logout=Log out? + +xcolibur.nav.about=About + +xcolibur.nav.about.general=General Info + +xcolibur.nav.about.paidaccounts=Paid Accounts + +xcolibur.nav.about.sitenews=Site News + +xcolibur.nav.about.stats=Statistics + +xcolibur.nav.footer.sitemap=Site Map + +xcolibur.nav.help=Help + +xcolibur.nav.help.ask=Ask a Question + +xcolibur.nav.help.contact=Contact Info + +xcolibur.nav.help.faq=FAQthis FAQ. + +/changepassword.bml.email.body<< +Your password has been changed at [[sitename]]. + +To retrieve it in the future, visit: + + [[siteroot]]/lostinfo.bml + +Regards, +[[sitename]] Team +[[siteroot]] +. + +/changepassword.bml.error.badnewpassword=Your new password confirmation does not match your new password. You may have made a mistake in typing. Please type and confirm your new password again. + +/changepassword.bml.error.notvalidated=You cannot change your password if your current e-mail address has not been validated. Please see the FAQ for instructions on doing this. + +/changepassword.bml.proceed.instructions=Press the button below and your password will be changed. You will receive an e-mail noting the password change. + +/changepassword.bml.success.text=Your password has been changed and an e-mail has been sent to you with a reminder message. + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge, where you'll find answers to many of the questions you may have. Visit , explore a bit, and you'll be a pro in no time at all! +p?> + + +
    +Add to your friends page to keep up with events and issues that are relevant to the entire LiveJournal community.
    +Add to your friends page to be informed when downtime is planned, and reports on unplanned interruptions of service. +p?> + + +AIM, ICQ, Yahoo!, MSN, or Jabber instant messengers. If you do, be sure to list it in your personal info settings. If you have a Paid Account, you can also enable your cell phone or pager to receive text messages. +p?> + + +Paid Account. There are, of course, loads of other ways you help out. +

    +LiveJournal is an Open Source project; if you have experience with programming languages or server side applications you can check out the LiveJournal Development Community, . If you have ideas about how LiveJournal could be better, check out the LiveJournal Suggestions Area, . If you would like to help with just about anything, visit the LiveJournal Business Community, . If you like helping people, visit our technical support center and help someone out. If you are savy with graphic design, check out the LiveJournal Art Community, . +p?> + + +Anime to Zen Buddhism, from Astronomy to Zim. You'll also find regional communities for places all around the world. There's probably a LiveJournal community for where you live too! +p?> + + +FAQ that will explain how to create your very own community. There are also two FAQ Categories (General Community FAQs and Community Management FAQs) covering just about everything you'll ever need to know about communities. If you still need more information, feel free to submit a support request. +p?> + + + + +
      +
    • Community Search
    • +
    • Check out the Promotions Community ()
    • +
    • Check out the Search Community ()
    • +
    + + +E-mail Jesse Proulx, () the Community Director. +p?> +. + +/community/join.bml.label.allowposting=This community allows posting by all members, so you now have access to post in it. If you already have a LiveJournal client open on your computer, you'll have to log out and log back in for this journal to show up in your list of journals you can post to. + +/community/members.bml.error.alreadysent=[[user]] could not be added because they were already sent a confirmation e-mail on [[datetime]]. Please wait for them to respond. + +/community/members.bml.key.admin=Maintainer + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Posting Access + +/community/moderate.bml.reject.reason=You can also explain to the poster your reasons for rejecting their entry. The reasons will be sent to the poster by e-mail. + +/community/search.bml.label.city=City: + +/community/settings.bml.label.anybodycan=All Members
    Anybody can post immediately once a member. + +/community/settings.bml.label.commcreate=This is the account that you want to turn into a community. It must already be created, but should not already be in use by an individual, because after this, many different people will potentially be able to post in it. + +/community/settings.bml.label.createtext=From here you can create a community account. A community is a special type of account that other users can join and post in. For an example of a community, check out the Seattle Party Community. + +/community/settings.bml.label.maintainer.login=If this is not the maintainer account, log in as somebody else. + +/community/settings.bml.label.nmheader=Non-Member Posting + +/community/settings.bml.label.selcan=Select Members
    Only some members are able to post, once they've been given access by the maintainer account. + +/create.bml.email.head=Your e-mail address + +/create.bml.email.input.head=E-mail Address: + +/create.bml.email.text2=For verification and security purposes, we need your e-mail address. It will never ever, under any circumstances, be sold or given away to spammers. We hate that more than anything. Read our privacy policy for more information. + +/create.bml.error.email.blank=You must provide your e-mail address. + +/create.bml.error.email.lj_domain=You cannot use a [[domain]] alias when creating an account. Please enter a different e-mail address. + +/create.bml.error.email.nospaces=No spaces allowed in e-mail address. If you're on AOL, remember that your Internet E-mail address is your screen name with all spaces removed, followed by @aol.com. + +/create.bml.error.username.purged=The username you entered is that of an account which has been deleted and purged. If you wish to use this username you must first purchase a rename token for an existing account. + +/create.bml.initial.friend.lj_maintenance=Reports of both planned & unplanned downtimes and maintenance + +/create.bml.initial.friend.news=LiveJournal news and events + +/create.bml.password.input.head2=Confirm password: + +/create.bml.password.secure=You must choose a secure password that is not based on a dictionary word, your username, or your email address. + +/create.bml.success.text1=Your journal has been created. Important registration information has been e-mailed to [[email]] containing further instructions. Be sure to confirm your journal creation by clicking on the link sent to you in e-mail. + +/create.bml.useacctcodes.entercode=To create a new account, enter an account creation code. For more information, see How do I create an account? + +/create.bml.username.charsallowed=Your username may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_).
    Additionally, it must not be longer than 15 characters. + +/customize/index.bml.s2.advanced.denied=Only paid, permanent, and early adopter account holders may use the advanced customization area. Find out the benefits of getting a paid account. + +/customize/index.bml.s2.customize.language=The following languages are fully or partially supported by this layout. + +/developer/index.bml.clients<< +So you want to create or improve a LiveJournal client on your platform? Wonderful! +Below are some necessary resources to let you know how LiveJournal works. +. + +/developer/index.bml.clients.header=Writing LiveJournal Clients + +/developer/index.bml.clients.links<< +
    +
    LiveJournal Server<->Client Protocol
    +
    Learn how the LiveJournal client on your desktop talks to the LiveJournal server and vice versa. + Understanding this is the primary thing you need to understand before developing or improving + a client for your platform.
    +
    Complete Protocol Docs
    +
    All the different protocol modes & methods.
    +
    List of Clients
    +
    A list of most clients used to connect to LiveJournal. The majority of these clients are + open source, and all of them are free to use. This is a great place to get examples for your + client.
    +
    +. + +/developer/index.bml.code<< +To see the backend that makes LiveJournal tick, and to see the innards of a few +of the available clients, go to the Code page. +. + +/developer/index.bml.code.header=LiveJournal Code Repository + +/developer/index.bml.dbschema<< +Curious about the database schema? +The SQL to create all the tables and populate them is included with the server code. +. + +/developer/index.bml.dbschema.header=Database Schema + +/developer/index.bml.embedding<< +Want to embed your journal right into your homepage? There are +several ways to do it, depending on what sort of control +you have over your server. You only have to worry about this if you don't like having +www.livejournal.com appear in your journal URL. +. + +/developer/index.bml.embedding.header=Embedding LiveJournal + +/developer/index.bml.notice.header=Notice + +/developer/index.bml.notice1<< +The following information is intended for programmers and advanced users only. +If you just want to use LiveJournal to keep your journal, great! Normal users +do not have to worry about this stuff. +. + +/developer/index.bml.notice2<< +That said, the content below is split up into two sections: information on how +to customize the look of LiveJournal pages, and information on writing +LiveJournal clients to the LiveJournal server. +. + +/developer/index.bml.styles<< +Don't like the way your journal pages look? Never you fear... everything is +flexible and if you read the documentation below you'll know all you need to make +your pages look any which way you want. +. + +/developer/index.bml.styles.header=Customizing the look of a LiveJournal + +/developer/index.bml.styles.s1.header=Style System 1 + +/developer/index.bml.styles.s1.system=Style System + +/developer/index.bml.styles.s1.system.about=General overview of how the first style system is setup. + +/developer/index.bml.styles.s1.varlist=Variable List + +/developer/index.bml.styles.s1.varlist.about=Straight alphabetical list of all variables that you can customize. + +/developer/index.bml.styles.s1.views=View Types + +/developer/index.bml.styles.s1.views.about=A list of the different types of ways you can view your journal, and details on each. + +/developer/index.bml.styles.s2.header=Style System 2 + +/developer/index.bml.styles.s2.layerbrowse=S2 Layer Browser + +/developer/index.bml.styles.s2.layerbrowse.about<< +A full list of public S2 layers that comprise the S2 system styles. Of importance here +are the core layers, that define the base variables, functions, and classes that make +S2 the powerful design language that it is. +. + +/developer/index.bml.styles.s2.manual=The S2 Manual + +/developer/index.bml.styles.s2.manual.about=Comprehensive information about using S2 on LiveJournal. + +/developer/index.bml.title=Developer Information + +/doc/index.bml.about<< +Welcome to LiveJournal's documentation repository, where you can find information +on most topics regarding LiveJournal's service or server software. Please select +a topic from below: +. + +/doc/index.bml.about.header=Welcome + +/doc/index.bml.docs.faq.about=Frequently Asked Questions about LiveJournal.com + +/doc/index.bml.docs.faq.title=FAQ + +/doc/index.bml.docs.guides.about=Supplemental FAQ information + +/doc/index.bml.docs.guides.title=Guides + +/doc/index.bml.docs.header=Documents + +/doc/index.bml.docs.howto.about=Tips and tricks to help customize your LiveJournal account + +/doc/index.bml.docs.server.about=All you need to know to install, administrate, and hack a LiveJournal setup + +/doc/index.bml.docs.server.title=LiveJournal Server Manual + +/doc/index.bml.docs.tour.about=Designed for new visitors to become familiar with the site + +/doc/index.bml.docs.tour.title=Tour + +/doc/index.bml.title=Documentation + +/doc/index.bml.volunteering.about=If you'd like to help out with LiveJournal's documentation, check out the following forums: + +/doc/index.bml.volunteering.header=Volunteering + +/doc/index.bml.volunteering.ljsysdoc=Discussions regarding the LiveJournal documentation system + +/doc/index.bml.volunteering.ljuserdoc=End user documentation discussions + +/doc/tour/index.bml.clients.caption<< +LiveJournal clients are small programs that run on your computer, allowing you to update your journal +whenever you're online, without having to open a browser window. +Clients are available for just about any platform, and many are easily customizable. +. + +/doc/tour/index.bml.clients.title=Clients + +/doc/tour/index.bml.comms.caption<< +LiveJournal is a large interactive community, so it shouldn't be a surprise that there are many members +with similar interests. To this end, we offer the ability to create communities, or journals that many +people can post to. +. + +/doc/tour/index.bml.comms.title=Communities + +/doc/tour/index.bml.create.caption<< +LiveJournal is a membership-based journaling community. This page explains what membership entails, +why membership is important, and the benefits of membership. It also includes a form to create +your own account. +. + +/doc/tour/index.bml.create.title=Creating an Account + +/doc/tour/index.bml.friends.caption<< +You can keep track of your friends through LiveJournal as well, by using the built–in "friends" feature. +If you find a journal you think is interesting, add it to your friends list, which will let you read all of +your friends' entries from the same page. +. + +/doc/tour/index.bml.friends.title=Friends + +/doc/tour/index.bml.intro.caption<< +This tour is designed for new visitors to become familiar with the site. +It will show you where the most important sections are located, as well +as some of the more interesting features. +. + +/doc/tour/index.bml.intro.title=Welcome + +/doc/tour/index.bml.modify.caption<< +It is also possible to format your journal in a number of different ways, by making use +of predefined styles and color schemes. Make your journal as unique as you want! +. + +/doc/tour/index.bml.modify.title=Personalizing + +/doc/tour/index.bml.nav.next=Next --> + +/doc/tour/index.bml.nav.prev=<-- Prev + +/doc/tour/index.bml.profile.caption<< +LiveJournal members are encouraged to add information about themselves into their profiles, so that +we can get an idea of who uses the site and how we can best serve them. However, none of this is required +— the only information that is required to start using LiveJournal is a name, an e-mail address, and a password. +. + +/doc/tour/index.bml.profile.title=Profiles + +/doc/tour/index.bml.sitemap.caption<< +Hopefully this tour gave you some helpful starting information about the LiveJournal site and service. +If you need help with anything LiveJournal related, feel free to contact +our support department. If you want to explore further, please +refer to the site map to see a list of all the pages on this site. +. + +/doc/tour/index.bml.sitemap.title=Site Map + +/doc/tour/index.bml.support.caption<< +The support page lists areas that help explain what LiveJournal is, +frequently asked questions about the site, and other helpful information +about the service, the company, and the community at large. +. + +/doc/tour/index.bml.support.title=Getting Help + +/doc/tour/index.bml.title=Tour - [[title]] + +/doc/tour/index.bml.update.caption<< +Updating a LiveJournal is the core of the LiveJournal service; here is where we offer members a chance to share their +lives and say what's on their minds. Updating a journal is simple. Simply write an entry in the supplied +box and press the "Update Journal" button. Of course, we also offer advanced features on our update page, like +the ability to check for spelling mistakes, and the ability to supply extra information about your +entries, such as your current music or current mood. +. + +/doc/tour/index.bml.update.title=Updating + +/editinfo.bml.allowshowcontact.about<< +You should keep this option enabled. This lets other people be able to contact +you by showing your e-mail address, ICQ number, and AOL Instant Messenger screenname +all on your LiveJournal. +. + +/editinfo.bml.allowshowcontact.email=If visible, e-mail address to be displayed: + +/editinfo.bml.allowshowcontact.email.neither=Neither. Don't show any e-mail address. + +/editinfo.bml.allowshowcontact.email.no_show=Don't show e-mail address + +/editinfo.bml.allowshowcontact.email.show=Show e-mail address + +/editinfo.bml.allowshowcontact.email.withdomainaddr<< +With the option above, you may also choose to hide your e-mail address +(while still showing other contact information), only show your +LiveJournal e-mail address (paid accounts +only), only show your real address, or show them both. +. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr<< +With the option above, you may also choose to hide your e-mail address +(while still showing other contact information). +. + +/editinfo.bml.autotranslate.header=Auto-convert older entries from: + +/editinfo.bml.bdayreminders.about=If you want to get e-mail reminding you of birthdays for your friends on LiveJournal, click this box. + +/editinfo.bml.bdayreminders.header=Send me birthday reminders (currently disabled) + +/editinfo.bml.bio.about=Here you can enter a little mini-biography about yourself. This will show up on your User Info page. + +/editinfo.bml.blockrobots.about<< +If you check this option, robots will be told to go away. +Not all robots respect the rules. +. + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=Check this if you want people to be able to reply to journal entries you post. + +/editinfo.bml.error.email.lj_domain<< +You cannot enter an @[[domain]] e-mail address. +Enter your real address in that field. +If you're a paid user, your [[user]]@[[domain]] address will forward to your real address. +To choose which e-mail address(es) are displayed publicly, see the option below the "Show your contact information" option. +. + +/editinfo.bml.error.email.none=You must provide your e-mail address. + +/editinfo.bml.error.email.no_space<< +No spaces are allowed in an e-mail address. +If you're on AOL, remember that your Internet E-mail address is your screen name with all spaces removed, followed by @aol.com +. + +/editinfo.bml.error.locale.zip_requires_us<< +You entered a zip code but you did not select United States as your country. +We only collect zip code information about people in the US. +Please go back and remove the zip code or select United States as your country. +. + +/editinfo.bml.error.tm.require_provider<< +If you're going to use text messaging, you must select your service provider. + +If yours is not listed, please contact us with information about how your service's text messaging feature so we can add support for it. +. + +/editinfo.bml.getreplies.about=Check this if you want to get e-mail updates when people reply to your journal entries using the message boards (comments). + +/editinfo.bml.getselfemails.about=Check this if you wish to get an e-mail every time you post a comment in a journal or community. You will not get e-mail for anonymous comments. + +/editinfo.bml.getselfemails.header=Get comments you post e-mailed to you + +/editinfo.bml.howhear.about<< +Just for curiosity's sake, where did you hear about [[sitename]] from? +If it was a specific person, enter their username; if it +was from another source/article/link/website, enter the appropriate information. +. + +/editinfo.bml.htmlemail.about<< +Check this if your e-mail program fully supports HTML in your e-mail. +Some clients try to support it, but fail to display it properly. +If you uncheck it, LiveJournal will only send text e-mails. +. + +/editinfo.bml.htmlemail.header=Send HTML E-mails + +/editinfo.bml.mangleaddress.about<< +If you are afraid spam-robots will find your e-mail +address on LiveJournal, select this option. Your e-mail address will be modified +so it won't be found by address-collecting robots. +. + +/editinfo.bml.mangleaddress.header=Mangle your displayed e-mail address + +/editinfo.bml.newemail.body2<< +You have just changed the e-mail address for your [[sitename]] account "[[username]]". To validate the change, please go to this address: + +[[conflink]] + +Regards, +[[sitename]] Team +[[sitelink]] +. + +/editinfo.bml.newemail.subject=E-mail Address Changed + +/editinfo.bml.opt_in.about<< +If you want to know when we add some cool new feature to LiveJournal, check this box. +We aren't currently using this feature, but we might in the future. +Your e-mail address will not be visible to other users, and you can turn this off at anytime. +. + +/editinfo.bml.security.header=Who can view your contact info? + +/editinfo.bml.translatemailto.about<< +In case you chose to receive message board replies by e-mail, and your e-mail client doesn't handle Unicode (UTF-8) +messages very well, use this option to specify a different encoding into which LiveJournal will automatically translate the text of comments sent to you. +. + +/editinfo.bml.translatemailto.header=Translate e-mail notifications into: + +/editinfo.bml.userpic.about<< +Below is the miniature picture you have uploaded to represent you +throughout the LiveJournal site, in your journal, and in your friends' journals: +. + +/editinfo.bml.userpic.edit=To delete this picture, or upload a new one, go here. + +/editjournal_do.bml.btn.delete=Delete Journal Entry + +/editjournal_do.bml.currmood=Current Mood: + +/editjournal_do.bml.edit.text=This is the journal entry you selected to be edited. Change all the information you would like to modify, then click the "Save Journal Entry" button at the bottom.

    To delete the entry, delete all the text in the text box and click the "Save Journal Entry" button at the bottom. + +/editjournal_do.bml.error.modify=An error occurred modifying your journal: + +/editjournal_do.bml.opt.noemail=Don't e-mail comments: + +/editjournal_do.bml.subject=Subject: (optional) + +/export.bml.description=This feature lets you download your entire journal to a custom format for backup purposes. For more information about backing up your journal, see this FAQ. + +/friends/add.bml.add.text=User [[ljuser]] was added to your friend list. You can view your friends page here. + +/friends/add.bml.error1.header=Log In First + +/friends/add.bml.error1.text<< +To add a user to your friends list you must first go and log in. If you don't +already have an account you can create one to track your friend's journals. +. + +/friends/add.bml.error2.text=Invalid or missing username given. To add a friend, go to the edit friends page. + +/friends/add.bml.groups.nogroup=No friend groups set up. + +/friends/add.bml.remove.text=User was removed from your friend list. You can view your friends page here. + +/friends/editgroups.bml.text<< +This page allows you to edit your custom friends groups. Custom friends groups are used for setting security on items and for filtering your friends page. For help, see What are custom friends groups? How do I use them? + +This page requires JavaScript to work. +. + +/friends/edit_do.bml.fellowfriends.text=The following people have listed you as a friend. You may want to list them as your friend too. This is provided as a reference, so that you know their LiveJournal usernames. You are under no obligation to add them to your list. + +/friends/edit_do.bml.success.text=Your friends have been updated. You can view your newly updated friends page here. + +/friends/filter.bml.error.nogroups=You cannot filter your friends list because you must first set up your friend groups. + +/friends/index.bml.about<< +This page allows you to manage your friends list. +By adding other users to your friends list, you can easily see their entries from your friends page. You can also add communities and syndicated feeds to your friends list so that you see their entries on your friends page. +. + +/friends/index.bml.edit.about=Add or remove users from your friends list, or edit the colors used to represent them. + +/friends/index.bml.editgroups.about=Create, edit, or delete subgroups of your friends. + +/friends/index.bml.filter=These friend groups can be used to filter your friends view: you can view only the entries of a certain group. They can also be used for group-based security (see below). + +/friends/index.bml.filter.about=Filter your friends list according to specific subgroups. + +/friends/index.bml.security=Your friends list is also used for entries with restricted access. You can find out more about friends list security at Friends & Security Levels. + +/friends/index.bml.security.custom=With "Custom" entries, you can specify which friend groups can view your entry. However, not all clients currently support custom security. + +/friends/index.bml.security.only=With "Friends-Only" entries, any user on your friends list can view your entries. + +/friends/popwithfriends.bml.account_type=Sorry, your account type doesn't permit you to use this tool. + +/friends/popwithfriends.bml.count=Count + +/friends/popwithfriends.bml.exclude_own=Optionally, you may exclude your friends. + +/friends/popwithfriends.bml.include_own=Optionally, you may include your friends. + +/friends/popwithfriends.bml.intro=The following friends are listed often by your friends, but not by you. + +/friends/popwithfriends.bml.intro_own=The following friends are listed often by your friends. The list also includes your own friends. + +/friends/popwithfriends.bml.no_users=No users + +/friends/popwithfriends.bml.title=Popular Users Amongst Your Friends + +/friends/popwithfriends.bml.user=User + +/index.bml.about.header=About LiveJournal + +/index.bml.about.joining=Joining the site is free. Users can choose to upgrade their accounts for extra features. + +/index.bml.about.us=LiveJournal is a simple-to-use (but extremely powerful and customizable) personal publishing ("blogging") tool, built on open source software. + +/index.bml.boldcreate=Create your own LiveJournal! + +/index.bml.frank.image.alt=Frank, the LiveJournal mascot goat. + +/index.bml.frank.logo="Baaaaah", says Frank. + +/index.bml.learnmore.header= Want to learn more? + +/index.bml.learnmore.text=Please read our feature overview. Convinced? Create your own LiveJournal! + +/index.bml.meta.desc=LiveJournal.com is a place where you can share your thoughts with the world. + +/index.bml.meta.keywords=diary, journal, online journal, diaries, writing, online diary, web diary + +/index.bml.news.text=The latest site news: + +/index.bml.news.title=Latest News + +/index.bml.post=Live Post Stats + +/index.bml.post.hour=Per Hour: + +/index.bml.post.latest=Latest Posts + +/index.bml.post.min=Per Minute: + +/interests.bml.add.btn.text=Add [[interest]] + +/interests.bml.interested.in=Find people and communities interested in: + +/interests.bml.interests.text=Here are some fun things you can do with interests. + +/interests.bml.morestuff=More fun stuff can be found on the interests page. + +/interests.bml.users.text=The following users are interested in [[interest]]. + +/invite/index.bml.code=Code + +/invite/index.bml.error=Error + +/invite/index.bml.genmore=Generate more codes + +/invite/index.bml.how_detail=Depending on a number of factors, existing users are allowed to invite a certain number of other users to join the site. To invite somebody you need to generate an invitation code and then give it to them. + +/invite/index.bml.how_header=How does it work? + +/invite/index.bml.invite_header=Invitations? + +/invite/index.bml.none=None + +/invite/index.bml.redeemed=Redeemed by + +/invite/index.bml.title=Invite others to LiveJournal... + +/invite/index.bml.unused=Unused + +/invite/index.bml.use=use + +/invite/index.bml.why_codes=As a means to keep the community tight, control growth, and prevent abuse, creating an account now requires either buying an account or getting invited by an existing user. The point of this is to make this community a better place for the people that use it, at the added cost of a little inconvenience for new users. + +/legal/dmca.bml.title=Copyright Information (DMCA) + +/legal/index.bml.about<< +LiveJournal is dedicated to offering a stable and meaningful experience for members from all +backgrounds and nations, so we have a few rules we've laid out to provide this. +Our documents here contain reasonable terms and information regarding how we will do our best to serve you, +and how we expect members to behave to us and others. LiveJournal works best when people +follow these rules. Here are some important ones to remember: +
      +
    • Do not harass, abuse, or threaten others.
    • +
    • Do not harm minors in any way.
    • +
    • Do not spam the site or any account on the site.
    • +
    • Do not post copyrighted content without permission.
    • +
    • Do not invade the privacy of others.
    • +
    • Do not violate U.S. law or your local laws in any way.
    • +
    +The complete list of rules and policies can be found below: +. + +/legal/index.bml.about.header=Overview + +/legal/index.bml.docs.dmca.about<< +The Digital Millenium Copyright Act (DMCA) describes the manner in which +service providers must react to copyright infringement. Our DMCA page +describes how you may notify us that a user on our service is infringing +upon your copyright. +. + +/legal/index.bml.docs.header=Documents + +/legal/index.bml.docs.privacy.about2<< +The Privacy Policy outlines what information we gather from our members +and explains how we use that information. This page also describes how +we handle the Children's Online Privacy Protection Act (COPPA) and our +policies about children on our site. +. + +/legal/index.bml.docs.tos.about<< +The Terms of Service outlines our usage policies, as well as the general terms and conditions +of membership. Membership and/or use of the system constitutes an agreement to abide by these +and all other agreed-upon terms. +. + +/legal/index.bml.title=Legal Information + +/legal/privacy.bml.title=Privacy Policy + +/legal/tos.bml.title=Terms of Service + +/login.bml.expire.sessiononly.text=Your login will expire after you close your browser. If this is your own computer and you're the only user, you may want to set your login expiration such that it never expires: + +/login.bml.login.btn.login=Log in... + +/login.bml.login.head=Log in + +/login.bml.login.text1=To log in to [[sitename]], enter your username and password below. New Users: To create an account, go here. + +/login.bml.login.text2=You may also specify when your login expires. By default your login will expire when you close your browser, which is best on public computers. However, if you're the only user of your computer and nobody else has access to it, you may choose to remain logged in forever. For more information on this and other options, see What are the options when I log in? + +/login.bml.login.text3=[[username]], you are now logged in to [[sitename]]. Feel free to browse the site by using our Site Map. + +/login.bml.title=Log in + +/login.bml.whylogin.head=Why log in? + +/logout.bml.killall.text=You have other active sessions. Do you want to expire all your sessions, and not just this one? (See this FAQ for more information.) + +/logout.bml.logout.btn=Log out + +/lostinfo.bml.enter_email=Enter your e-mail address: + +/lostinfo.bml.enter_email_optional=E-mail address: (optional) + +/lostinfo.bml.error.no_email=You must enter an e-mail address in order to recover your username. + +/lostinfo.bml.lostpassword.text=If you've lost your password, enter your username and optionally the e-mail address you'd like the password sent to. In order to have your password sent to a previously listed e-mail address, that address must have been validated. If you leave the e-mail field blank, it will be mailed to your current address. + +/lostinfo.bml.lostpassword.title=Lost your password? + +/lostinfo.bml.lostusername.text=If you've lost your username, enter your e-mail address and we'll send you your username. + +/lostinfo.bml.lostusername.title=Lost your username? + +/lostinfo_do.bml.error.no_usernames_for_email=No username(s) for this e-mail address: [[address]] . + +/lostinfo_do.bml.error1.text=You never used that e-mail address with this account or it was never validated. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** This is an automated e-mail. You do not need to respond to it. *** + +This is your requested password reminder from [[sitename]]. +Below are the username, password, and e-mail address your journal is registered under. + + Username: [[username]] + Password: [[password]] + E-mail Address: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=To validate your e-mail address, go here: + +/lostinfo_do.bml.lostpasswordmail.part3<< +This information was requested on the website from [[remoteip]]. + +If you didn't request to have this password e-mailed to you, don't panic. +After all, you're the one who's seeing this e-mail, and not the other person. +It's possible that the user who made the request is mistaken and +believes that he or she controls this username. It's also possible that +someone made a typo in a username or e-mail address. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +If you truly believe that your account isn't secure, read + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +for some information on how to re-secure it. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Useful links: + + Your LiveJournal: + [[journalurl]] + + Update your journal online: + [[updateurl]] + +Regards, +LiveJournal Team + +[[rooturl]] +. + +/manage/index.bml.customization.customize.about=Change the appearance of your journal and switch between S1 and S2 style systems + +/manage/index.bml.customization.moodtheme.editor=Create and edit your custom mood themes + +/manage/index.bml.customization.moodtheme.editor.header=Mood Theme Editor + +/manage/index.bml.customization.moodtheme.header=Mood Themes + +/manage/index.bml.customization.moodtheme.set=Select which mood theme set your journal will use + +/manage/index.bml.customization.moodtheme.set.header=Set Your Mood Theme + +/manage/index.bml.entries.memories.about=View and work with your memorable entries + +/manage/index.bml.entries.tags.about=Organize your journal entry categories + +/manage/index.bml.entries.tags.header=Manage Entry Tags + +/manage/index.bml.friends.edit.about=Add or remove users from your friends list, or change the colors used to represent them. + +/manage/index.bml.information.emailpost=E-mail Gateway Settings + +/manage/index.bml.information.emailpost.about=Manage your e-mail addresses and PIN for post-by-email support + +/manage/index.bml.information.phonepost=Phonepost Settings + +/manage/index.bml.information.phonepost.about=Manage your post-by-phone phone number and PIN. + +/manage/index.bml.information.siteopts.about=Select your preferred site layout and language + +/manage/index.bml.information.status.about=Set your account's activation status (delete or undelete your account) + +/manage/phonepost.bml.delete=Delete Settings + +/manage/phonepost.bml.deleted=Your phone post settings have been deleted. + +/manage/phonepost.bml.deleted.header=Deleted + +/manage/phonepost.bml.error.inuse=Invalid PIN, please try another + +/manage/phonepost.bml.error.phone.length=Your phone number must be at least ten digits long. + +/manage/phonepost.bml.error.pin=Your PIN must be numeric. + +/manage/phonepost.bml.error.transcription=Invalid friend group for transcription + +/manage/phonepost.bml.format=Recorded Post Format: + +/manage/phonepost.bml.format.help='Ogg Vorbis' is less supported, but creates a higher quality file. 'Wav' is smaller and doesn't sound as nice, but plays natively nearly everywhere. + +/manage/phonepost.bml.intro.loggedin<< +Post by Phone, fill out your phone number and PIN below. p?> +Privacy Policy for more information) +Calls made from numbers other than your authorized phone number will still be accepted, but you'll have to enter your authorized phone number before you can record your post. p?> + +. + +/manage/phonepost.bml.intro.loggedout=Members of can log in and change their Post by Phone settings here: + +/manage/phonepost.bml.phone=Authorized Phone Number: + +/manage/phonepost.bml.phone.help=(515) 555-5555 + +/manage/phonepost.bml.pin=Personal Identification Number: + +/manage/phonepost.bml.pin.help=4-6 digits recommended + +/manage/phonepost.bml.save=Save Settings + +/manage/phonepost.bml.saved=Saved + +/manage/phonepost.bml.success.moreinfo=For more information on recording a Post by Phone entry, see How do I record an audio post to my journal?. + +/manage/phonepost.bml.success.text=Your phone settings have been saved. + +/manage/phonepost.bml.title=Post by Phone Settings + +/manage/phonepost.bml.transcribers=Allowed Transcribers: + +/manage/phonepost.bml.transcribers.help=Edit Friend Groups + +/manage/pubkey.bml.info=Publishing your public key allows others to view it via your userinfo page, and you can post to the e-mail gateway with signed messages. See instructions here. + +/modify_do.bml.colortheme.about=Here you can select what color theme will be applied to the layout options you pick above. Or, if you don't like the provided colors, specify your own! + +/modify_do.bml.domainalias.helptext=For this to work, you'll need to arrange to have your domain name's DNS point to the same IP address as [[sitename]]. For more information, see this FAQ. + +/modify_do.bml.friends.opt.usesharedpic.about=This option controls what picture you see on your friends page when a user posts in a shared or community journal. If you check it, then you'll see the community's icon. If you leave it unchecked, then you'll see the user icon of the person who's actually posting. + +/modify_do.bml.journaloptions.about=From here you can customize the look of your LiveJournal pages. If you're really curious how everything works, read the developer information. Otherwise, we'll assume you're satisfied with the basic options below: + +/modify_do.bml.moodicons.about=When posting journal entries you can also specify your current mood. Different users have submitted different sets of mood icons that you can use. Or, select "None" if you don't want any pictures beside your moods. (or, you don't even have to use the Current Mood feature at all.) + +/modify_do.bml.overrides.about=If you are happy with the journal layout options above, you can ignore this section. This is for tweaking very specific things about your page layout. See What are overrides? How do they work? for an overview, and visit the developer section for details. Also note that overrides are for overriding only one or two things about a style. If you'd like to override everything, you need to create your own style. For an overview of how to create a style, see How do I make a custom style? + +/modify_do.bml.overrides.note=Please note that not all style variables can be overridden. See the documentation for more details.
    Also, be aware that if you attempt to edit your overrides and you have used a tag that is not allowed in the head of the document – such as <DIV>, <SPAN>, <IMG>, and many other tags – that tag will be stripped. The only HTML elements that can be used in the *_HEAD overrides are those elements that are valid in the head of a HTML document. This is limited to <title>, <base>, <style>, <link>, and <meta>. + +/multisearch.bml.noaddress.text=You did not enter an e-mail address. + +/paidaccounts/index.bml.costs.header=Well, how much does it cost? + +/paidaccounts/index.bml.costs.rates=The rates are as follows: + +/paidaccounts/index.bml.costs.rates.amount.header=Amount + +/paidaccounts/index.bml.costs.rates.inexpensive<< +That works out to a little over $2/month for the year plan. +That'll hardly break your pocketbook. +The most annoying part will likely be pulling out your wallet, finding your credit card, and typing in your information. +. + +/paidaccounts/index.bml.costs.rates.time.header=Time + +/paidaccounts/index.bml.features<< +
    To show appreciation for users who have made contributions, there are a number of features that are only available to paid accounts. These features include, but aren't limited to:
    + +
    New! Post by E-mail
    +
    Paid accounts can post to their journals and communities quickly and securely through our e-mail gateway.
    + +
    Customizing your Journal
    +
    In addition to just being able to pick the style of your journal and the colors, you'll also be able to create your own style using whatever HTML you like. This will also let you be able to make new styles that match your website that you can then easily embed, never revealing that you're using LiveJournal.com as your journal mechanism.
    + +
    Polls
    +
    Paid accounts have the ability to create polls in their own journals and in any communities they are a part of and can post to.
    + +
    More User Picture Icons
    +
    Paid accounts are allowed 15 user picture icons, rather than the 3 allotted to free users.
    + +
    LiveJournal.com E-mail Alias
    +
    Paid accounts are given a LiveJournal.com e-mail address ([[username]]@livejournal.com) that can be turned on or off.
    + +
    Directory Searches
    +
    Paid accounts are given access to use the directory to search for other users.
    + +
    LiveJournal.com Subdomain
    +
    Instead of having your journal at +http://www.livejournal.com/users/[[username]]/, it'll also be available at http://[[username]].livejournal.com/, much shorter and more personal.
    + +
    Syndication
    +
    Paid accounts have the ability to create new syndicated accounts, which are RSS feeds that are incarnated on LiveJournal.
    + +
    Text Messaging Interface
    +
    Paid accounts are given access to the text messaging feature, which will allow them to receive text messages on their phone or pager through LiveJournal's custom interface.
    + +
    More To-Do Items
    +
    Paid accounts can set up to 150 to-do list items in their to-do lists, and can set differing security levels on each item.
    + +
    Embedding
    +
    Paid accounts have access to the complete range of options for embedding your journal into your home page, as explained on the "Embedding" page.
    + +
    Domain Forwarding
    +
    Paid users can set up domain forwarding, so that their internet domain points to their LiveJournal.
    + +
    More...
    +
    For a complete list of Paid Account benefits, please read What are the Paid Account benefits?
    +. + +/paidaccounts/index.bml.features.header=So what cool features will I get? + +/paidaccounts/index.bml.title=About Paid Accounts + +/paidaccounts/index.bml.whypay.argument<< +No, of course not. Paying for web services is annoying, we agree. +That's why nearly all of LiveJournal's functionality is available free of charge. +However, if you're happy with the service you're being provided, show your support and get a paid account. +. + +/paidaccounts/index.bml.whypay.header=I have to pay to use LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads<< +It takes money to run websites (for servers, colocation, and bandwidth), and this seems like a +better way to pay for it than blasting you with pop-up banner ads and spamming you with advertisements. +. + +/paidaccounts/index.bml.your_username=your_username + +/paidaccounts/usepaypal.bml.delivery.badformat=Invalid delivery date format. Must be of form yyyy-mm-dd or yyyy-mm-dd hh:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Delivery date cannot be in the past. To send immediately, leave the delivery date box blank. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Delivery date cannot be more than a month in the future. + +/pay/index.bml.deliverydate.details=Format: yyyy-mm-dd hh:mm (GMT time)
    (enter nothing for no delayed delivery) + +/pay/index.bml.deliverydate.label=Delivery Date: + +/pay/index.bml.gift.anonymous=Anonymous gift + +/press/staff.bml.accountserv=Account Services + +/press/staff.bml.administration=Administration + +/press/staff.bml.administration.about<< +LiveJournal.com started in 1999 as a project of Brad Fitzpatrick, and during the first two years of its life, +was sustained by a large and loyal group of volunteers. While a lot of +LiveJournal.com is still run by teams of volunteers, we now have a small senior staff who oversee all +operations: +. + +/press/staff.bml.avva.title=Senior Developer + +/press/staff.bml.back2=Back to the Press area + +/press/staff.bml.bleything.title=Senior Support Monkey + +/press/staff.bml.bradfitz.quip=Focus on your product and not just on making money. + +/press/staff.bml.bradfitz.title=President / Lead Developer + +/press/staff.bml.contact=If you need to get in touch with any of us, please e-mail webmaster@livejournal.com. + +/press/staff.bml.custserv=Customer Service / Usability Research + +/press/staff.bml.david.title=The Intern + +/press/staff.bml.denisep.quip=I'll have that to you next Thursday + +/press/staff.bml.denisep.title=Volunteer Relations / Usability Specialist + +/press/staff.bml.deveiant.title=Remote Developer + +/press/staff.bml.developers=Developers + +/press/staff.bml.ferrell.title=Customer Service Manager + +/press/staff.bml.jproulx.quip=Geek to User Liaison + +/press/staff.bml.jproulx.title=Community Site Supervisor / Press Relations + +/press/staff.bml.lisa.title=Lead Systems Administrator + +/press/staff.bml.mahlon.quip=Eek eek! + +/press/staff.bml.mahlon.title=Code Monkey + +/press/staff.bml.matthew.title=Systems Administrator + +/press/staff.bml.ryanfitz.title=Payment Services + +/press/staff.bml.sandy.title=Accounting and Administration + +/press/staff.bml.smithy.title=Apprentice Hacker + +/press/staff.bml.sysadmin=Systems Administrators + +/press/staff.bml.title=Senior Staff + +/press/staff.bml.whitaker.quip=What next? + +/press/staff.bml.whitaker.title=Remote Developer + +/register.bml.ask.body=Click the button below to have send a validation e-mail to [[email]]. + +/register.bml.ask.header=Validate E-mail + +/register.bml.email.body<< +This is the validation e-mail you have requested. +To complete validation of your account, please visit this URL: + + [[conflink]] + +You may have to copy and paste this link into your browser's window. + +Regards, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Validate E-mail + +/register.bml.error.useralreadyvalidated=The e-mail address for [[user]] has already been validated. + +/register.bml.sent.body=A validation e-mail has been sent to [[email]]. In order to complete validation, you need to click the link in that e-mail. + +/register.bml.title=Validate E-mail + +/register.bml.trans.body=Your new e-mail address has been validated. + +/rename/index.bml.does=Renaming the account only changes the username. Everything else - paid or permanent account status, user privileges, personal info, friends, and other account-related data - remains the same, and will be associated with the new username. All existing comments in other journals and entries in communities will display the new username. + +/rename/index.bml.faqurl=For more details on the rename process, see the rename FAQ. + +/rename/index.bml.fee=There is a fee of [[fee]] to change your LiveJournal username. + +/rename/index.bml.heading.cost=Cost + +/rename/index.bml.heading.details=Details + +/rename/index.bml.heading.how=How To Buy + +/rename/index.bml.option=You have the option to either redirect the old username to the new username or mark it as deleted. You may also choose to either have people who list you as a friend continue to list your new username as a friend, or be removed from the friends lists of all other users. + +/rename/index.bml.options.buy=Buy Token + +/rename/index.bml.options.buy.desc=Buy a rename token. + +/rename/index.bml.options.use=Use Token + +/rename/index.bml.options.use.desc=Use a rename token. + +/rename/index.bml.redeem=You first buy a rename token, which is e-mailed to you, then use that token to do the actual rename when you receive it. Rename tokens are non-refundable, but are transferrable. That is, you can buy a rename token for another user. + +/rename/index.bml.reserve=You do not have to create an account with your new username in order to be renamed to it. However, if you are worried that someone might take the name before you have a chance to buy and use your token, you should create an account with the new username. Be sure to use the same e-mail address and password that you use for your current account for the new one. + +/rename/index.bml.title=Account Renaming Service + +/rename/index.bml.whatrename=You may only rename your personal account, not a community you run. + +/rename/use.bml.changes=The following changes will be made once the rename is completed: + +/rename/use.bml.changes.move="[[newuser]]" will be moved out of the way to "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" will be renamed to "[[newuser]]" + +/rename/use.bml.confirm2=After you click 'Rename' below, there is no way to undo the change. As a means of confirmation, type the word "[[confirmword]]" in the box below in uppercase. + +/rename/use.bml.confirm.click=And then, click 'Rename': + +/rename/use.bml.error.allocating=Error allocating name to move away destination account. + +/rename/use.bml.error.badpass=The passwords for the old and new usernames do not match. + +/rename/use.bml.error.differentusername=This isn't the username you were logged in as when you loaded this form. + +/rename/use.bml.error.login=But first, you have to login. + +/rename/use.bml.error.notvalidated=The email address on one or more of the accounts involved has not been validated. Before you rename your journal, you must first validate your email address. Please see How do I validate my email address? for information on how to validate your email address. + +/rename/use.bml.error.readit=Read the paragraph above. + +/rename/use.bml.error.reserved=Error moving away reserved account name. + +/rename/use.bml.error.same=This is the same as your old username. + +/rename/use.bml.error.token=Invalid rename token. + +/rename/use.bml.error.type=Only normal accounts can be renamed, not community accounts. + +/rename/use.bml.error.unknown=Unknown error renaming. + +/rename/use.bml.error.usedtoken=This token has already been used. + +/rename/use.bml.error.username=Invalid username. + +/rename/use.bml.error.usernametaken=That username is already taken. + +/rename/use.bml.heading.changes=Changes + +/rename/use.bml.heading.success=Success + +/rename/use.bml.heading.sure=Are you sure? + +/rename/use.bml.intent=This page is for renaming an account after you've read the introduction and bought a rename token. + +/rename/use.bml.label.desired=Desired username: + +/rename/use.bml.label.proceed=Proceed ... + +/rename/use.bml.label.rename=Rename + +/rename/use.bml.label.token=Rename token: + +/rename/use.bml.label.username=Current username: + +/rename/use.bml.options=Rename options: + +/rename/use.bml.options.delfriends=Remove all users from your Friends list and leave all communities. + +/rename/use.bml.options.forward=Automatically forward users from [[oldname]] to new username. + +/rename/use.bml.options.keepfriends=Keep all users and communities on your Friends list. + +/rename/use.bml.options.keepself=Keep everyone on your Friend Of list. + +/rename/use.bml.options.removeself=Remove everyone from your Friend Of list. + +/rename/use.bml.options.unlink=Do not keep a connection between [[oldname]] and the new journal. + +/rename/use.bml.success.login=You'll need to login again now. + +/rename/use.bml.success.moved="[[newuser]]" has been moved out of the way to "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" has been renamed to "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Username renamed. + +/rename/use.bml.title=Use A Rename Token + +/site/contract.bml.promise=We stand firm in saying that we will: + +/site/contract.bml.promise.account=Honor the status of every account + +/site/contract.bml.promise.account.about<< +Permanent accounts will be honored for the life of the site. Paid accounts will remain as +paid accounts until they expire, unless they are renewed in advance. Early adopters will be granted access to the paid +features that were freely available in the early history of the site. (Account status valid +with the exception of account termination by means of Terms of Service +violation.) +. + +/site/contract.bml.promise.ads=Stay advertisement free + +/site/contract.bml.promise.ads.about<< +It may be because it's one of our biggest pet peeves, or it may be because they don't +garner a lot of money, but nonetheless, we promise to never offer advertising space in our +service or on our pages. +. + +/site/contract.bml.promise.community=Work with the community, for the community + +/site/contract.bml.promise.community.about<< +We promise to keep you informed of changes to the best of our abilities without being intrusive. +We promise to run our business based on feedback from the LiveJournal community, and with the +LiveJournal community's best interests in mind. +. + +/site/contract.bml.promise.opensource=Support the Free Software movement + +/site/contract.bml.promise.opensource.about<< +All of the code that is used to run a complete, highly-customizable LiveJournal installation +is available to the public. We promise to keep this source free and open so that we can give +something back to the Free Software community. +. + +/site/contract.bml.promise.spam=Never send you unsolicited e-mail + +/site/contract.bml.promise.spam.about<< +We strongly believe that spam has no place on the internet, and we promise never to send you +any e-mail without your implied or explicit consent. We promise to never sell lists of users' e-mail +addresses or personal information, and we promise never to spam on the behalf of an interested +third party. +. + +/site/contract.bml.promise.uptime=Maintain reliable uptime within the limits of technical considerations + +/site/contract.bml.promise.uptime.about<< +We try to keep things running smoothly for everyone, especially since we use the system just +as much as anyone else. Unfortunately server hangups do occur, but we will plan ahead as best +as possible to avoid them. +. + +/site/contract.bml.promisetoyou<< +We at LiveJournal try to ensure that our service is as pleasant as possible for each user, +so we've assembled a list of promises we will keep. +. + +/site/contract.bml.promisetoyou.header=Our Promise to You + +/site/contract.bml.title=Social Contract + +/site/goat.bml.image.alt=Frank, the LiveJournal mascot goat. + +/site/goat.bml.image.caption="Baaaah," says Frank. + +/site/goat.bml.meet.body<< +This is Frank. Frank is the LiveJournal.com mascot. He helps us with random programming +when we get behind, and occasionally he answers tech support requests. Frank's really quite versatile.... he even does the yardwork sometimes. When the lawn gets overgrown we go, "Hey Frank! It's lunch time.... go eat the lawn!". It's really a win-win situation. +. + +/site/goat.bml.meet.header=Meet Frank + +/site/goat.bml.title=Frank the Goat + +/styles/create.bml.createstyle.text=From here you can create a new personal-style, useful if you're going to either embed your journal in your homepage or you want to make a public style that everybody can use and you need to work on it here first, rather than in your overrides section. Note that only users with paid accounts can create their own styles. + +/styles/index.bml.about<< +

    This section of the site allows you to create, edit, and delete customized S1 styles. This +allows you to control the look of your account to a great extent, whether you want to make it look +like your website, or just feel like being different.

    + +

    You can also create embedded styles which, rather than +creating a full page, include only the Journal entries and leave +you to embed your journal in another site.

    + +

    You can read more about the style system in the +style +documentation in the +developer area.

    + +

    Please note that only paid accounts +may create and use custom styles. Free Accounts have a selection of predefined +LiveJournal styles which you can select from the +Modify Your Journal page.

    +. + +/styles/index.bml.nav.edit=Edit or delete an existing style + +/suggestions/index.bml.howto.text<< +
    +
    Check prior suggestions
    +First, read over past suggestions to make sure that something similar hasn't already been brought up. If it has, you can read the comments on the entry. Sometimes, things might look as though they've been ignored, but they might be in development. Sometimes, ideas are rejected or delayed due to other concerns. +
    +
    Couldn't find your idea? Share it with us!
    +The template must be used for all suggestions. Be sure to fill out all areas of the template, and make sure your suggestion is correct and complete before you post it. Also, the suggestion generator does not add in line breaks, so you can use the <br> tag to produce whitespace. This makes your suggestion easier to read. +
    +
    Submit It!
    +You can add the community to your Friends list here. Once a suggestion is posted, people will discuss it. If we think it's a good idea, it will be added to the list of developer projects, and will be worked on as time permits. Not all suggestions can be implemented immediately, so please be patient with the process. +
    +. + +/suggestions/index.bml.howto.title=How do I make a suggestion? + +/suggestions/index.bml.info.text<< +Feel that you can contribute to the implementation of your suggestions? Feel free to 'watch' or join the communities below: +
    +
    LiveJournal Developer's Forum -- talking about technical things.
    +
    +
    LiveJournal Business Forum -- talking about general LiveJournal business opportunities and related areas.
    +
    +
    LiveJournal User Documentation Forum -- discussing and editing most forms of end user documentation.
    +
    +
    LiveJournal Art Forum -- discussing and sharing icons, mood themes, color themes and userpics.
    +
    +
    +Please remember that the people who implement LiveJournal changes and additions are fellow users like yourself. These things can take time and the more you can help with implementing, the more that can be achieved. +. + +/suggestions/index.bml.info.title=Other Information + +/suggestions/index.bml.rules<< +There are a few things to keep in mind: +
      +
    • Many suggestions have already been proposed and discussed, but simply not implemented yet. Be sure that you're not submitting a duplicate.
    • +
    • Flaming will not be tolerated. Everyone has different ideas about how LiveJournal should work; remember that promoting your opinion is all right, but flaming someone else's opinion is not.
    • +
    • Be as thorough as possible with your suggestion. A suggestion that contains detailed implementation notes is more likely to be accepted than one that doesn't. You don't need to know how to program; just try to think about what else your idea would affect, and bring up any problems you can see with it.
    • +
    • Be sure to read the FAQs first, to see if your idea already exists, or if an existing aspect of the site can be used to do what you want.
    • +
    • If you want to ask a question about how LiveJournal works, aren't certain if something exists or not, or are having a problem, don't submit a suggestion. Ask Support instead.
    • +
    +. + +/suggestions/index.bml.title=Suggestion Area + +/suggestions/index.bml.welcome.text=User suggestions are an important part of LiveJournal. If you have something that you think would be a cool idea, you can follow these procedures to bring it to the attention of the people who run the site. + +/suggestions/index.bml.welcome.title=Welcome! + +/support/append_request.bml.bounce.noemail=No e-mail address specified for bounce. + +/support/append_request.bml.bounce.toomany=You can only send to up to five e-mail addresses. You have specified more than five. + +/support/append_request.bml.internal.touch=To change a request's status, you must select "Internal Comment / Action" and explain why you're changing it. + +/support/append_request.bml.successlinks<< + +. + +/support/encodings.bml.edit.text<< +Short answer: (applicable if you write your journal in English): Go to your +personal settings page. Find an option +near the bottom of the page that is called Auto-convert older entries from:. Choose +"Western European (Windows)" from the pull-down menu and save your settings. Your entries should +now be editable. p?> + +Long answer: In order to allow you to edit a non-Unicode entry, LiveJournal code needs to +know which encoding that entry has been posted in. For users of English and other West European +languages, this will normally be "Western European (Windows)", although if that doesn't work well +for quote characters and other similar meta-characters, try "Western European (ISO)". Users +writing in other languages should select their encoding; if it isn't in the supplied list, +contact Support and explain the problem. p?> + + +. + +/support/encodings.bml.overview.text<< + + + +. + +/support/help.bml.interim<< + + + + +Getting +Started category in HelpScreening's memories +is an especially good place for new +volunteers to get information. p?> + + + +
    • Be professional and courteous.
    • +
    • Don't contact people submitting requests outside the Support +board to discuss their request or give them information.
    • +
    • Keep information in Support requests private.
    • +
    • Don't copy other people's answers.
    + + + +, but +please wait until there is an approved answer in the request. p?> + + + + + +Support +board. p?> +. + +/support/see_overrides.bml.error.noprivs=Only users with the supportviewscreened or supporthelp privilege can view another user's overrides. + +/syn/index.bml.loginrequired.text=To manage your syndicated accounts, first log in. + +/syn/index.bml.promo.text=If you would like to see a list of the syndicated feeds that users have advertised in the past, you may wish to visit , where users post announcements of feeds they create and watch. + +/talkmulti.bml.error.comms_deleted=One of the comments has been deleted since you selected it. For security reasons, please go back and try again. + +/talkpost.bml.error.noreply_deleted=This comment has been deleted. You cannot reply to it. + +/talkpost.bml.loginq=Log in? + +/talkpost.bml.opt.friendsonly=- this user has disabled anonymous and non-friend posting. You may post here if [[username]] lists you as a friend. + +/talkpost_do.bml.error.noverify=Sorry, you aren't allowed to post comments in other people's journals until your e-mail address has been verified. If you've lost the confirmation e-mail to do this, you can have it re-sent. + +/talkpost_do.bml.preview=This is how your comment will look when posted. Using the form below, you can edit your comment further, or you can submit it as is. + +/talkpost_do.bml.title=Comment Posted + +/talkscreen.bml.screened.body=The comment has been screened. You can view it here. + +/talkscreen.bml.unscreened.body=The comment has been unscreened. You can view it here. + +/tools/emailmanage.bml.address.old.text<< +The following is a list of e-mail addresses that were used with your account, +and the time they were deactivated as the primary e-mail address. Check the ones +you wish to delete. +. + +/tools/emailmanage.bml.desc.notfirst<< +This page only lets you remove e-mail addresses that were used after the first time +you used the e-mail address your account is currently validated with. In particular, +this means an attacker isn't able to remove your original e-mail address. +. + +/tools/emailmanage.bml.desc.text<< +This page lets you remove past e-mail addresses that were used with your account. +If you remove an address, it will no longer be possible to have your password mailed to that address. +This is useful if somebody discovered your password and hijacked your journal. Simply +have the new password mailed to your old address, change the password, and remove the +attacker's e-mail address. +. + +/tools/emailmanage.bml.notvalidated.text=To use this tool, your current e-mail address, [[email]] , must be validated. If you've lost the confirmation e-mail to do this, you can have it re-sent. After you validate your email, come back here. + +/tools/emailmanage.bml.notvalidated.title=E-mail not validated + +/tools/emailmanage.bml.title=E-mail Management + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.description.text<< + Give this journal entry a description that you can remember it by. + To delete this entry from your list of memorable entries, enter a blank description. +. + +/tools/memadd.bml.error.deleted.body=The journal entry previously described as "[[desc]]" has been removed from your list of memorable entries. + +/tools/memadd.bml.error.fivekeywords=Only 5 keywords/categories are allowed per memorable entry. + +/tools/memadd.bml.error.login=You must be logged in to use this feature. Go log in and you'll be brought back here. + +/tools/memadd.bml.keywords.select=You can also select keywords you've used in the past: + +/tools/memadd.bml.keywords.text=Why is this entry memorable? Enter up to five comma-separated keywords or categories so you can find it later. + +/tools/memadd.bml.whocansee<< + Who can see that you've marked this entry as memorable? + Everybody, only people you list as a friend, or just you? +. + +/tools/memories.bml.body.keyword<< + +[[user]] found memorable. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] has placed memorable journal entries in. p?> +. + +/tools/memories.bml.error.noentries.body<< +This could be because:
      +
    1. the user hasn't defined any memorable events,
    2. +
    3. the user's memorable events are protected and you don't have access to view them, or
    4. +
    5. the user doesn't have any memories that match your filter criteria.
    +. + +/tools/memories.bml.title.keyword=Memorable [[keyword]] Entries + +/tools/memories.bml.title.memorable=Memorable Entries + +/tools/recent_comments.bml.maxnotshown=Upgrade to a Paid Account to see [[max]] recent comments, instead of [[current]]. + +/update.bml.note=Note: The time and date above are from our server. Correct them for your timezone before posting. + +/update.bml.opt.noemail=Don't e-mail comments: + +/update.bml.subject=Subject: (optional) + +/update.bml.update.alternate=If you don't want to download a client for your computer, or if one doesn't exist for your computer, you may use this page to update your LiveJournal. This is also useful if you're on vacation or away from your primary computer. If you have a paid account, you may update your journal via e-mail, record phone posts when away from a computer, or create polls for your entries. + +/update.bml.update.success=Update successful. You can view your updated journal here. + +/userinfo.bml.about.comm=About: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.error.malfname=Malformed username: too long, or contains invalid characters. + +/userinfo.bml.error.notloggedin=If you wish to view your own user profile, you need to log in. + +/userinfo.bml.friendof.comm=Watched by: + +/userinfo.bml.friendof.user=Friend of: + +/userinfo.bml.friends.user=Friends + +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.interests.modifyyours=Modify yours + +/userinfo.bml.label.interests.removesome=Remove some + +/userinfo.bml.label.shared= Posting Access: + +/userinfo.bml.membership.paidmembers=After your paid account is set up, you may join the paidmembers community. + +/userinfo.bml.nonexist.body=The username [[user]] is not currently registered. + +/userinfo.bml.syn.parseerror=Error Message: + +crumb.about=About LiveJournal + +crumb.abusereport=Report Abuse + +crumb.acctfeatures=Features By Account Type + +crumb.advsearch=Advanced + +crumb.banners=Advertising Banners + +crumb.code=LiveJournal Code + +crumb.contract=Our Social Contract + +crumb.contributors=Contributors + +crumb.coppa=COPPA + +crumb.dmca=DMCA Information + +crumb.download=Download a Client + +crumb.emailgateway=E-mail Gateway + +crumb.emailmanage=E-mail Management + +crumb.filemanager=File Manager + +crumb.goat=About Frank + +crumb.guidingprinciples=Our Guiding Principles + +crumb.itsfree=It's Free? + +crumb.legal=Legal Information + +crumb.ljhome=Home + +crumb.memories=Memorable Entries + +crumb.paidaccounts=Paid Accounts + +crumb.paidacctstatus=Paid Account Status + +crumb.press=LiveJournal Press Area + +crumb.pressarticles=LiveJournal in the Press + +crumb.privacy=Privacy Policy + +crumb.register=Validate E-mail + +crumb.search=Search + +crumb.searchinterests=By Interest + +crumb.searchregion=By Region + +crumb.securechangepass=Change Password + +crumb.securecreatejournal=Create Journal + +crumb.securelogin=Login + +crumb.securemanage=Manage Accounts + +crumb.singles=LiveJournal Singles + +crumb.singlesopts=Modify Availability + +crumb.singlessearch=Search for Singles + +crumb.sitemap=Site Map + +crumb.sizechart=Sizing Chart + +crumb.staff=Senior Staff + +crumb.stats=Statistics + +crumb.store=LiveJournal Store + +crumb.storeitem=View Item Detail + +crumb.suggestions=Suggestions Generator + +crumb.suggview=Suggestions + +crumb.tos=Terms of Service + +dystopia.btn.login=LOGIN + +dystopia.hello_anonymous=Welcome to LiveJournal! + +dystopia.hello_loggedin=Hello, [[username]]! + +dystopia.nav.contact=Contact Info + +dystopia.nav.createjournal=Create a Journal + +dystopia.nav.developer=Developer Area + +dystopia.nav.download=Download + +dystopia.nav.editentries=Edit Entries + +dystopia.nav.editfriends=Your Friends + +dystopia.nav.editpassword=Your Password + +dystopia.nav.editpics=Your Pictures + +dystopia.nav.editstyle=Edit Style + +dystopia.nav.faq=LiveJournal FAQ + +dystopia.nav.findcomm=By Community + +dystopia.nav.finddir=Directory Search + +dystopia.nav.findint=By Interest + +dystopia.nav.findrandom=Random + +dystopia.nav.findregion=By Region + +dystopia.nav.home=Home + +dystopia.nav.journalcalendar=Calendar + +dystopia.nav.journalfriends=Friends + +dystopia.nav.journalinfo=User Info + +dystopia.nav.journalrecent=Recent + +dystopia.nav.legaldmca=DMCA + +dystopia.nav.legalprivacy=Privacy + +dystopia.nav.legaltos=Terms of Service + +dystopia.nav.login=Login + +dystopia.nav.logout=Logout + +dystopia.nav.lostinfo=Lost Password + +dystopia.nav.manage=Manage Accounts + +dystopia.nav.memories=Memories + +dystopia.nav.modifyjournal=Modify Journal + +dystopia.nav.news=News + +dystopia.nav.paidaccts=Paid Accounts + +dystopia.nav.paymentarea=Payment Area + +dystopia.nav.personalinfo=Personal Info + +dystopia.nav.sitemap=Site Map + +dystopia.nav.siteopts=Browse Options + +dystopia.nav.support=Have a question? + +dystopia.nav.updatejournal=Update Journal + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=122 + +dystopia.navhead.findusers=Find Users + +dystopia.navhead.help=Help & Support + +dystopia.navhead.journal=Your Journal + +dystopia.navhead.legal=Legal + +dystopia.navhead.settings=Your Settings + +dystopia.navhead.welcome=Welcome! + +dystopia.search.aolim=AOL IM + +dystopia.search.icq=ICQ Number + +dystopia.search.int=Interest + +dystopia.search.jabber=Jabber + +dystopia.search.msn=MSN Username + +dystopia.search.region=Region + +dystopia.search.yahoo=Yahoo! ID + +dystopia.searchlj=Search LiveJournal: + +Email=E-mail + +email.newacct.body<< +Congratulations, you have a new LiveJournal account! + +To complete your journal creation and verify your e-mail address, go +here: + + [[regurl]] + +The URL that your new journal is located at is: + + [[siteroot]]/users/[[username]]/ + +and also: + + [[siteroot]]/~[[username]]/ + +Below is your LiveJournal username and password: + + Username: [[username]] + Password: [[password]] + +You can go to [[siteroot]]/ to access your account, create +new journal entries, and modify your journal options, but we recommend +downloading a LiveJournal client. It's the easiest way to update your +journal, and there are clients available for many platforms! Get one at: + + [[siteroot]]/download/ + +Getting started on LiveJournal can be difficult when you don't know +anyone. Visit http://newbies.livejournal.com for smart, helpful advice... +with a little luck, you'll be a LiveJournal pro in no time! + +We hope you appreciate LiveJournal as much as we appreciate bringing it to +you. If you have any questions regarding how to use LiveJournal, please +visit the support area at: + + [[siteroot]]/support/ + +There you'll find answers to almost any question you could ask about +LiveJournal. + +Our goal is to make LiveJournal totally rock... if we can do anything to +make it easier, more powerful, more customizable, whatever... let us know. +We're not running the site to make money. We're not a dot-com company +funded by venture-capital hoping to go IPO ... this site is run by all the +people that use it. Let us know what you want out of it. + +If you have questions, the support team will get you an answer usually +in less than 24 hours. + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Welcome to LiveJournal + +error.nodb=Database temporarily unavailable. + +error.noremote=You have to log in in order to use this page. + +error.purged.text=This journal has been deleted and purged. + +error.suspended.text=This account has been either temporarily or permanently suspended. If you are [[user]], please refer to the FAQ entitled My account has been suspended! How can I get it back? for more information. Please note that in order to maintain our users' privacy, [[sitename]] cannot discuss the reasons for any suspension with anyone except the account's owner. + +langname.be=Belarusian + +langname.da=Danish + +langname.de=German + +langname.en_GB=English (UK) + +langname.en_LJ=English + +langname.eo=Esperanto + +langname.es=Spanish + +langname.et=Estonian + +langname.fi=Finnish + +langname.fr=French + +langname.ga=Irish + +langname.gd=Gaelic + +langname.gr=Greek + +langname.he=Hebrew + +langname.hi=Hindi + +langname.hu=Hungarian + +langname.is=Icelandic + +langname.it=Italian + +langname.ja=Japanese + +langname.la=Latin + +langname.lv=Latvian + +langname.ms=Malay + +langname.nb=Norwegian BokmÃ¥l + +langname.nl=Dutch + +langname.nn=Norwegian Nynorsk + +langname.pl=Polish + +langname.pt=Portuguese + +langname.ru=Russian + +langname.sv=Swedish + +langname.tr=Turkish + +langname.uk=Ukrainian + +langname.zh=Chinese Simplified + +ljcom.account.feature=Feature + +ljcom.account.feature.email=LiveJournal e-mail address + +ljcom.account.feature.full2=For the full table, see this page. + +ljcom.account.feature.limit=limited + +ljcom.account.feature.ownblog=Your own journal/weblog + +ljcom.account.feature.photo=100MiB Integrated photo hosting + +ljcom.account.feature.pp=Phone Posting + +ljcom.account.feature.search=Directory search + +ljcom.account.feature.styles=Create/customize styles + +ljcom.account.feature.syn=Friends and syndicated feeds aggregator + +ljcom.account.free=Free Account + +ljcom.account.paid=Paid Account + +ljcom.account.paid12=Paid for 12 Months ($25 USD) + +ljcom.account.paid2=Paid for 2 Months ($5 USD) + +ljcom.account.paid6=Paid for 6 Months ($15 USD) + +ljcom.accounttype=Account Type + +ljcom.badpass.email=Your password cannot be based on your e-mail address. + +ljcom.badpass.realname=Your password cannot be based on your real name. + +ljcom.badpass.username=Your password cannot be based on your username. + +ljcom.meetup.head=Meetup! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=International [[name]] Meetup Day + +ljcom.meetup.moreinfo=(more info) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Want to meet people in real life from around your area to discuss this interest? Check out the [[link]]! + +ljcom.menu.upgrade=Upgrade your account + +ljcom.userinfo.accounttype=Account type + +ljcom.userinfo.paiduser=Paid User + +ljcom.userinfo.types.early=Early Adopter + +ljcom.userinfo.types.free=Free Account + +ljcom.userinfo.types.paid=Paid Account + +ljcom.userinfo.types.paid_early=Paid Account, previously an Early Adopter + +ljcom.userinfo.types.paid_early_expiring=Paid Account, expiring [[paiduntil]], previously an Early Adopter + +ljcom.userinfo.types.paid_expiring=Paid Account, expiring [[paiduntil]] + +ljcom.userinfo.types.permanent=Permanent Account + +ljcom.userinfo.types.permanent_early=Permanent Account, previously an Early Adopter + +portal.goat.name=Site Mascot + +portal.goattext.des=What do you want your goat to say? The only true thing goats can say is 'Baaaaah', but you can pretend your goat can say something else if you really want. + +portal.goattext.name=Goat Text + +portal.memories.portalname=Memorable Entries + +portal.memories.portaltitle=Memorable Entries + +portal.misbehaved.des=You really wanted to leave this unchecked. Goats that aren't housetrained are nothing but trouble. + +portal.misbehaved.name=Mishaved Goat + +portal.newtolj.name=Site Links + +portal.recent.items.description=By default, only the most recent entry is shown. + +portal.recent.showtext.description=By default only subjects will be shown. + +protocol.mail_bouncing=You are currently using a bad e-mail address. All mail we try to send you is bouncing. [[sitename]] requires a valid e-mail address for continued use. Visit [[siteroot]]/support/faqbrowse.bml?faqid=19 for how to change your e-mail address. + +protocol.must_revalidate=You need to validate your new e-mail address. Your old one was good, but since you've changed it, you need to revalidate the new one. If you don't validate your address, you will not have access to all of the functions of [[sitename]]. Visit [[siteroot]]/support/faqbrowse.bml?faqid=11 for more information. + +protocol.not_validated=Your e-mail address has not been validated. You may continue to use [[sitename]], but if you do not validate your address, you will not have access to all functions of the site. See the instructions that were mailed to you when you created your journal, or visit [[siteroot]]/support/faqbrowse.bml?faqid=11 for more information. + +talk.spellcheck=Check spelling during preview + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_english + +xcolibur.greeting.anon=Welcome to LiveJournal! + +xcolibur.greeting.logged_in=Welcome, [[name]]! [[logout]] + +xcolibur.login=Login? + +xcolibur.logout=Log out? + +xcolibur.nav.about=About + +xcolibur.nav.about.download=Download + +xcolibur.nav.about.general=General Info + +xcolibur.nav.about.paidaccounts=Paid Accounts + +xcolibur.nav.about.press=Press + +xcolibur.nav.about.sitenews=Site News + +xcolibur.nav.about.stats=Statistics + +xcolibur.nav.footer.sitemap=Site Map + +xcolibur.nav.help=Help + +xcolibur.nav.help.ask=Ask a Question + +xcolibur.nav.help.contact=Contact Info + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Lost Password + +xcolibur.nav.home=Home + +xcolibur.nav.journal=Journal + +xcolibur.nav.journal.archive=Archive + +xcolibur.nav.journal.edit.entries=Edit Entries + +xcolibur.nav.journal.friends=Friends + +xcolibur.nav.journal.info=Info + +xcolibur.nav.journal.memories=Memories + +xcolibur.nav.journal.recent=Recent + +xcolibur.nav.journal.update=Update + +xcolibur.nav.manage=Manage + +xcolibur.nav.manage.community=Communities + +xcolibur.nav.manage.customize=Customize + +xcolibur.nav.manage.entries=Entries + +xcolibur.nav.manage.friends=Friends + +xcolibur.nav.manage.info=Info + +xcolibur.nav.manage.password=Password + +xcolibur.nav.manage.pics=User Pictures + +xcolibur.nav.manage.styles=Styles + +xcolibur.nav.manage.tags=Tags + +xcolibur.nav.search=Search + +xcolibur.nav.search.directory=Region + +xcolibur.nav.search.directory.search=Advanced + +xcolibur.nav.search.interests=Interests + +xcolibur.nav.search.random=Random + +xcolibur.nav.siteopts=Browse Options + +xcolibur.nav.title=Navigate: + +xcolibur.nav.welcome=Welcome + +xcolibur.nav.welcome.create=Create an Account + +xcolibur.nav.welcome.login=Login + +xcolibur.nav.welcome.update=Update Your Journal + +xcolibur.search=Search: + +xcolibur.search.aolim=AOL IM + +xcolibur.search.category=Category: + +xcolibur.search.icq=ICQ Number + +xcolibur.search.int=Interest + +xcolibur.search.jabber=Jabber + +xcolibur.search.msn=MSN Username + +xcolibur.search.region=Region + +xcolibur.search.yahoo=Yahoo! ID + +xcolibur.upgrade=Upgrade Your Account + diff --git a/local/bin/upgrading/ru.dat b/local/bin/upgrading/ru.dat new file mode 100755 index 0000000..5d11d12 --- /dev/null +++ b/local/bin/upgrading/ru.dat @@ -0,0 +1,5072 @@ +;; -*- coding: utf-8 -*- +#/talkpost.bml.opt.ljuser=пользователь LJR: + +#/talkpost.bml.opt.ljuser2=пользователь LJR + +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Изменить ÑÑ‚Ð°Ñ‚ÑƒÑ + +/accountstatus.bml.error.db=Ошибка базы данных во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ вашего запроÑа + +/accountstatus.bml.error.invalid=ÐедейÑтвительный тип ÑтатуÑа + +/accountstatus.bml.error.nochange.expunged=Этот аккаунт удален из ÑиÑтемы + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Ваш дневник заморожен -- вы не можете Ñтого изменить. + +/accountstatus.bml.header.success=ПолучилоÑÑŒ + +/accountstatus.bml.journalstatus.about=Именно на Ñтой Ñтранице можно удалить либо воÑÑтановить ваш дневник. ЕÑли вы удалите дневник, у Ð²Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ 30 дней на то, чтобы передумать и воÑÑтановить его. По иÑтечении Ñтого Ñрока, дневник будет окончательно и беÑповоротно удалён, так что воÑÑтановить его уже не удаÑÑ‚ÑÑ. + +/accountstatus.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ°: + +/accountstatus.bml.journalstatus.select.activated=Ðктивен + +/accountstatus.bml.journalstatus.select.deleted=Удалён + +/accountstatus.bml.journalstatus.select.head=СтатуÑ: + +/accountstatus.bml.journalstatus.select.suspended=Заморожен + +/accountstatus.bml.message.nochange=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐµÐ³Ð¾ дневника оÑталÑÑ [[statusvis]]. + +/accountstatus.bml.message.success=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐµÐ³Ð¾ дневника уÑпешно изменен на [[statusvis]]. + +/accountstatus.bml.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° + +/allpics.bml.current=ИмеющиеÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ + +/allpics.bml.default=Картинка по умолчанию + +/allpics.bml.edit2=Еще можно редактировать ключевые Ñлова к картинкам или закачать новую картинку. + +/allpics.bml.error.noparam=Вам необходимо указать Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/allpics.bml.keywords=Ключевые Ñлова: + +/allpics.bml.nopics.text.other=Этот пользователь не загрузил ни одной картинки. + +/allpics.bml.nopics.text2=Ð’Ñ‹ не закачали ни одной картинки. Это можно Ñделать здеÑÑŒ. + +/allpics.bml.nopics.title=Ðет картинок + +/allpics.bml.pics=Это картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. + +/allpics.bml.title=Картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/approve.bml.comm.success=ПолучилоÑÑŒ + +/approve.bml.comm.text<< +Ð’Ñ‹ добавлены к [[comm]]. +Ðажмите здеÑÑŒ, чтобы добавить ÑообщеÑтво к ÑпиÑку ваших друзей. +. + +/approve.bml.commjoin.text=Ð’Ñ‹ одобрили Ð·Ð°Ð¿Ñ€Ð¾Ñ [[user]] о вÑтуплении в [[comm]]. Ðажмите здеÑÑŒ, чтобы увидеть ÑпиÑок членов данного ÑообщеÑтва и определить другие привилегии Ñтого пользователÑ. + +/approve.bml.error.actionperformed=Это дейÑтвие уже выполнено + +/approve.bml.error.approving<< +Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Ñтого запроÑа о вÑтуплении в ÑообщeÑтво произошла ошибка. + +. + +/approve.bml.error.internerr.invalidaction=Ошибка: неизвеÑтное дейÑтвие + +/approve.bml.error.invalidargument=Ðекорректный аргумент + +/approve.bml.error.unknownactiontype=ÐеизвеÑтный тип дейÑÑ‚Ð²Ð¸Ñ + +/approve.bml.shared.success=ПолучилоÑÑŒ + +/approve.bml.shared.text<< +Теперь вы можете пиÑать в [[shared]]. +Ðажмите здеÑÑŒ, чтобы добавить дневник к ÑпиÑку ваших друзей. +. + +/approve.bml.title=Подтверждение дейÑÑ‚Ð²Ð¸Ñ + +/birthdays.bml.description=Внизу перечиÑлены дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚ÐµÑ…, кого вы выбрали в качеÑтве друзей + +/birthdays.bml.title=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +/changepassword.bml.btn.proceed=Продолжить + +/changepassword.bml.changepassword.header=Сменить пароль + +/changepassword.bml.changepassword.instructions=Чтобы изменить ваш пароль, заполните Ñту форму внизу. + +/changepassword.bml.email.body<< +Ваш пароль на Ñайте [[sitename]] был изменен. + +Чтобы воÑÑтановить его в будущем, зайдите на Ñтраницу: + +[[siteroot]]/lostinfo.bml + +Такие дела, +Команда [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ + +/changepassword.bml.error.badcheck=Ðеверный новый пароль: [[error]] + +/changepassword.bml.error.badnewpassword=Ваше новое подтверждение Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ ÑоответÑтвует вашему новому паролю. Ð’Ñ‹ могли допуÑтить ошибку при наборе. ПожалуйÑта, наберите и подтвердите Ñвой новый пароль еще раз. + +/changepassword.bml.error.badoldpassword=Ваш Ñтарый пароль неверен. + +/changepassword.bml.error.blankpassword=Ðовый пароль не может быть пуÑтым. + +/changepassword.bml.error.changetestaccount=ÐÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ пароль теÑтового дневника. + +/changepassword.bml.error.characterlimit=Пароль не может быть длиннее 30 Ñимволов. + +/changepassword.bml.error.invaliduser=Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем не ÑущеÑтвует. Ð’Ñ‹ уверены, что набрали Ð¸Ð¼Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾? + +/changepassword.bml.error.mustenterusername=Ðеобходимо ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/changepassword.bml.error.nonascii=Символы Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ принадлежать таблице ASCII. Выберите пароль, не Ñодержащий не-ASCII-Ñимволов. + +/changepassword.bml.error.notvalidated=Ð’Ñ‹ не можете изменить пароль, пока ваш текущий Ð°Ð´Ñ€ÐµÑ e-mail не подтверждён. + +/changepassword.bml.newpassword=Ðовый пароль: + +/changepassword.bml.newpasswordagain=Ðовый пароль (ещё раз): + +/changepassword.bml.oldpassword=Старый пароль: + +/changepassword.bml.proceed.instructions=Ðажмите кнопку "Продолжить", чтобы изменить пароль. Ð’Ñ‹ также получите e-mail Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸ÐµÐ¼ о Ñмене паролÑ. + +/changepassword.bml.relogin=К тому же вы вышли из вÑех ÑущеÑтвовавших ÑеÑÑий. Чтобы продолжитЬ, вам придетÑÑ Ð¾Ð¿ÑÑ‚ÑŒ войти. + +/changepassword.bml.success.text=Ваш пароль был изменен. Вам был отправлен e-mail Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸ÐµÐ¼. + +/changepassword.bml.title=Сменить пароль + +/community/create.bml.btn.create=Создать ÑообщеÑтво + +/community/create.bml.btn.proceed=Продолжаем... + +/community/create.bml.create.text=Создать новое ÑообщеÑтво неÑложно -- проÑто Ñледуйте приведенным на Ñтой Ñтранице инÑтрукциÑм. + +/community/create.bml.error.notactive=Ð’Ñ‹ можете Ñоздать ÑообщеÑтво только еÑли ваш аккаунт активен. ПожалуйÑта, убедитеÑÑŒ, что ваш аккаунт не удален и не заморожен -- а потом попробуйте еще раз. + +/community/create.bml.error.notperson=Чтобы Ñоздать ÑообщеÑтво, нужно войти в ваш личный аккаунт. + +/community/create.bml.error.postrequired=ТребуетÑÑ Ð¼ÐµÑ‚Ð¾Ð´ POST. + +/community/create.bml.error.username.inuse=Пользователь Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует; выберите, пожалуйÑта, другое имÑ. + +/community/create.bml.error.username.mustenter=ОбÑзательно надо ввеÑти пользовательÑкое имÑ. + +/community/create.bml.error.username.reserved=Извините -- Ñто пользовательÑкое Ð¸Ð¼Ñ Ð·Ð°Ñ€ÐµÐ·ÐµÑ€Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¾. + +/community/create.bml.errors.label=ПожалуйÑта, иÑправьте Ñледующие ошибки и повторие запроÑ: + +/community/create.bml.name.head=Ðазвание ÑообщеÑтва + +/community/create.bml.name.text=Как будет называтьÑÑ Ð²Ð°ÑˆÐµ ÑообщеÑтво? Это название будет показано в заголовке ÑообщеÑтва, а еÑли вы захотите, будет внеÑено и в каталог пользователей. + +/community/create.bml.person=Может быть, вы на Ñамом деле хотите Ñоздать личный денвник? + +/community/create.bml.success.btn.enterinfo=Введите информацию о ÑообщеÑтве + +/community/create.bml.success.head=ПолучилоÑÑŒ! + +/community/create.bml.success.text1=Ваше ÑообщеÑтво Ñоздано. Кроме того, вы запиÑаны в качеÑтве его ÑмотрителÑ. + +/community/create.bml.success.text2=Ваше ÑообщеÑтво доÑтупно по Ñледующему адреÑу: + +/community/create.bml.success.text3=Ртеперь, заполните пожалуйÑта форму Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ информацией про ÑообщеÑтво. Большую чаÑÑ‚ÑŒ граф заполнÑÑ‚ÑŒ необÑзательно -- но они помогут других пользователÑм понÑÑ‚ÑŒ, Ð´Ð»Ñ ÐºÐ¾Ð³Ð¾ ваше ÑообщеÑтво и зачем оно нужно. + +/community/create.bml.title=Создать новое ÑообщеÑтво + +/community/create.bml.username.charsallowed=ПользовательÑкое Ð¸Ð¼Ñ ÑообщеÑтва (Ð¸Ð¼Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°) должно ÑоÑтоÑÑ‚ÑŒ из Ñтрочных латинÑких букв (a-z), цифр (0-9) и Ñимвола Ð¿Ð¾Ð´Ñ‡ÐµÑ€ÐºÐ¸Ð²Ð°Ð½Ð¸Ñ (_). Кроме того, оно должно быть не длиннее 15 Ñимволов. + +/community/create.bml.username.head=ПользовательÑкое Ð¸Ð¼Ñ + +/community/create.bml.username.text=Каждый аккаунт [[sitename]] -- будь то личный дневник, или ÑообщеÑтво -- должен иметь Ñвое ÑобÑтвенное пользовательÑкое имÑ. Это то имÑ, которое войдет в Ð°Ð´Ñ€ÐµÑ ÑообщеÑтва. + +/community/index.bml.main<< + + + + + + +

    Создайте Ñвое ÑообщеÑтво!

    +. + +/community/index.bml.title=Центр СообщеÑтв + +/community/join.bml.button.join=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +/community/join.bml.error.already.member=Ð’Ñ‹ уже ÑвлÑетеÑÑŒ членом Ñтого ÑообщеÑтва. + +/community/join.bml.error.closed=Это ÑообщеÑтво больше не принимает новых членов. ЕÑли вы хотите в него вÑтупить, пожалуйÑта, напишите одному из Ñмотрителей: + +/community/join.bml.error.statusvis.body=Ðккаунт, в который вы хотите зайти, не активен (удален или заморожен). + +/community/join.bml.error.statusvis.title=Ðевозможно вÑтупить в ÑообщеÑтво + +/community/join.bml.label.addtofriends=Добавить "[[maintainer]]" в ленту друзей.
    + +/community/join.bml.label.allowposting=Это ÑообщеÑтво открыто и принимает ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ вÑех Ñвоих учаÑтников, поÑтому теперь и вы можете отправлÑÑ‚ÑŒ запиÑи в дневник ÑообщеÑтва. ЕÑли у Ð²Ð°Ñ Ð·Ð°Ð¿ÑƒÑ‰ÐµÐ½Ð° программа-клиент, вам доÑтаточно выйти из дневника и Ñнова войти в него, чтобы Ð¸Ð¼Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ ÑообщеÑтва поÑвилоÑÑŒ в ÑпиÑке дневников, доÑтупных вам Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸ Ñвоих запиÑей. + +/community/join.bml.label.auth=ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° то, что вы ÑвлÑетеÑÑŒ учаÑтником Ñтого ÑообщеÑтва, вы не можете пиÑать. ЕÑли вы хотите получить право пиÑать в Ñто ÑообщеÑтво, ÑвÑжитеÑÑŒ Ñ Ð¾Ð´Ð½Ð¸Ð¼ из его Ñмотрителей. Ðиже приведён их ÑпиÑок: [[admins]] + +/community/join.bml.label.banned=Смотритель Ñтого ÑообщеÑтва запрещает вам приÑоединÑÑ‚ÑŒÑÑ Ðº ÑообщеÑтву. + +/community/join.bml.label.closed=Это закрытое ÑообщеÑтво. ЕÑли вы хотите приÑоединитьÑÑ Ðº нему, ÑвÑжитеÑÑŒ, пожалуйÑта, Ñ Ð¾Ð´Ð½Ð¸Ð¼ из его Ñмотрителей. Ðиже приведён их ÑпиÑок: [[admins]] + +/community/join.bml.label.commlogged=Ð’Ñ‹ вошли в ÑиÑтему, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑкое Ð¸Ð¼Ñ ÑообщеÑтва, а не под вашим перÑональным пользовательÑким именем. + +/community/join.bml.label.errorcomminfo=Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве некорректна. + +/community/join.bml.label.expls=Чтобы приÑоединитьÑÑ Ðº ÑообщеÑтву "[[maintainer]]", нажмите на кнопку внизу. ЕÑли вы хотите приÑоединитьÑÑ Ðº ÑообщеÑтву, но не хотите видеть запиÑи оттуда в Ñвоей ленте друзей, уберите галочку в поле внизу. + +/community/join.bml.label.loginfirst=Чтобы приÑоединитьÑÑ Ðº ÑообщеÑтву, вы должны вначале войти в ÑиÑтему. + +/community/join.bml.label.membernow=Теперь вы ÑвлÑетеÑÑŒ учаÑтником ÑообщеÑтва [[commname]] + +/community/join.bml.label.sure=Ð’Ñ‹ уверены? + +/community/join.bml.reqsubmitted.body=Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° вÑтупление в ÑообщеÑтво отправлен ÑмотрителÑм + +/community/join.bml.reqsubmitted.title=Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° вÑтупление в ÑообщеÑтво отправлен + +/community/join.bml.request.body=ÑообщеÑтво не открытое. ПожалуйÑта, подтвердите, что вы хотите приÑоединитьÑÑ, нажав ÑÑылку внизу. + +/community/join.bml.request.reason=ÐеобÑзательно: укажите причину, по которой вы хотите вÑтупить в ÑообщеÑтво: + +/community/join.bml.request.title=Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾ вÑтуплении + +/community/join.bml.success=УÑпешное завершение + +/community/join.bml.title=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +/community/leave.bml.button.leave=Покинуть ÑообщеÑтво + +/community/leave.bml.label.buttontoleave=Ðажмите на кнопку внизу, чтобы покинуть ÑообщеÑтво "[[commname]]". + +/community/leave.bml.label.infoerror=Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве некорректна. + +/community/leave.bml.label.lastmaintainer=Ð’Ñ‹ не можете покинуть ÑообщеÑтво -- вы поÑледний оÑтавшийÑÑ Ñƒ него Ñмотритель! ЕÑли вы вÑе-таки хотите уйти, назначьте, пожалуйÑта, другого ÑмотрителÑ, а потом уходите. + +/community/leave.bml.label.logoutfirst=Чтобы покинуть ÑообщеÑтво, вы должны вначале войти в ÑиÑтему. + +/community/leave.bml.label.removed=Теперь вы иÑключены из ÑообщеÑтва [[commname]] + +/community/leave.bml.label.removefromfriends=Также удалить "[[user]]" из ÑпиÑка друзей. + +/community/leave.bml.success=Ð’Ñ‹ уÑпешно покинули ÑообщеÑтво + +/community/leave.bml.sure=Ð’Ñ‹ уверены? + +/community/leave.bml.title=Покинуть ÑообщеÑтво + +/community/manage.bml.commlist.actinfo=Инфо + +/community/manage.bml.commlist.actinvites=ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ + +/community/manage.bml.commlist.actions=ДейÑтвиÑ: + +/community/manage.bml.commlist.actmembers=[УчаÑтники] + +/community/manage.bml.commlist.actmembers2=УчаÑтники + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] ожидающие Ð¿Ð¾Ð´Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ + +/community/manage.bml.commlist.actsettings=[ÐаÑтройки] + +/community/manage.bml.commlist.actsettings2=ÐаÑтройки + +/community/manage.bml.commlist.header=Ваши ÑообщеÑтва + +/community/manage.bml.commlist.moderation=ÐаходитÑÑ Ð² очереди на модерирование + +/community/manage.bml.commlist.moderation.num=[[[num]]в очереди] + +/community/manage.bml.commlist.none=Ð’Ñ‹ не управлÑете никакими ÑообщеÑтвами. + +/community/manage.bml.commlist.text=ЗдеÑÑŒ перечиÑлены ÑообщеÑтва, которыми вы управлÑете или помогаете управлÑÑ‚ÑŒ: + +/community/manage.bml.commlist.title=Ðазвание + +/community/manage.bml.commlist.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/community/manage.bml.create.header=Создать ÑообщеÑтво + +/community/manage.bml.create.text=Также вы можете Ñоздать новое ÑообщеÑтво. + +/community/manage.bml.joinmail.body=Ð”Ð»Ñ ÑообщеÑтв Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ членÑтвом еÑÑ‚ÑŒ Ñледующие варианты оповещениÑний по email: + +/community/manage.bml.joinmail.email.all=ПриÑылать email каждый раз, когда кто-то хочет вÑтупить + +/community/manage.bml.joinmail.email.digest<< +Раз в день приÑылать email Ñо ÑпиÑком желающих вÑтупить + +. + +/community/manage.bml.joinmail.email.none=Вообще не приÑылать email, Ð´Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации новых запроÑов Ñ Ð±ÑƒÐ´Ñƒ иÑпользовать Ñту Ñтраницу + +/community/manage.bml.joinmail.save=Сохранить наÑтройки + +/community/manage.bml.joinmail.title=ÐдминиÑтративные возможноÑти + +/community/manage.bml.modemail.body=ЕÑли ÑообщеÑтво модерируемое, вы можете выбрать, получать ли email: + +/community/manage.bml.modemail.no=Ðе надо; Ñ Ñам буду Ñледить за очередью на модерацию + +/community/manage.bml.modemail.yes=Сообщайте мне по e-mail каждый раз, когда кто-то добавил поÑтинг к очереди + +/community/manage.bml.title=Управление ÑообщеÑтвами + +/community/members.bml.error.adding=[[user]] запретил Ñтому ÑообщеÑтву приÑылать Ñебе приглашениÑ. + +/community/members.bml.error.alreadyadded=[[user]] не был добавлен, поÑкольку уже имеет доÑтуп в ÑообщеÑтво. + +/community/members.bml.error.alreadysent=[[user]] не может быть добавлен, поÑкольку [[datetime]] ему было выÑлано подтверждающее пиÑьмо. Подождите ответа. + +/community/members.bml.error.invaliduser=Ðе могу добавить транÑлируемый аккаунт или ÑообщеÑтво: [[user]] + +/community/members.bml.error.limit=Ðе могу приглаÑить [[user]] -- лимит неподтвержденных приглашений, отведенный Ð´Ð»Ñ Ñтого ÑообщеÑтва, иÑчерпан. + +/community/members.bml.error.noaccess=Только Ñмотрители ÑообщеÑтва могут редактировать ÑпиÑок его учаÑтников. Ð’Ñ‹ не ÑвлÑетеÑÑŒ Ñмотрителем ÑообщеÑтва [[comm]]. + +/community/members.bml.error.noattr=Ðе выбран ни один атрибут Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] + +/community/members.bml.error.nocomm=СообщеÑтво не найдено + +/community/members.bml.error.notactive=Ðккаунт не активен: [[user]] + +/community/members.bml.error.nouser=Такого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ ÑущеÑтвует: [[user]] + +/community/members.bml.error.unknown=Ошибке при попытке приглаÑить [[user]]. ПожалуйÑта, убедитеÑÑŒ, что Ñто еще не член ÑообщеÑтва, и попробуйте еще раз. + +/community/members.bml.key.admin=Смотритель + +/community/members.bml.key.member=УчаÑтник + +/community/members.bml.key.moderate=Модератор + +/community/members.bml.key.post=Может пиÑать + +/community/members.bml.key.preapprove=Ðе модерируетÑÑ + +/community/members.bml.key.user=Пользователь + +/community/members.bml.manage2=Управление ÑообщеÑтвами + +/community/members.bml.name=Ðазвание ÑообщеÑтва: [[name]] + +/community/members.bml.nextlink=(Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница...) + +/community/members.bml.prevlink=(ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница...) + +/community/members.bml.reinvited2=[[user]] Ñнова приглаÑили вÑтупить в ÑообщеÑтво. Чтобы вÑтупить, нужно принÑÑ‚ÑŒ приглашение на Странце приглашений в ÑообщеÑтво. + +/community/members.bml.settings=[ÐаÑтройки] + +/community/members.bml.success.added=добавлены: [[list]] + +/community/members.bml.success.deleted=удалены: [[list]] + +/community/members.bml.success.header=Ð’Ñ‹ Ñделали Ñто! + +/community/members.bml.success.invited2=ÐижеперечиÑленные пользователи приглашены в Ñто ÑообщеÑтво, Ñ Ð¿ÐµÑ€ÐµÑ‡Ð¸Ñленными правами. Чтобы Ñтать членом Ñообщетва, им Ñледует принÑÑ‚ÑŒ приглашение на Странице приглашений в ÑообщеÑтва. + +/community/members.bml.success.message2=Сделаны Ñледующие изменениÑ: + +/community/members.bml.success.nochanges=Ðичего не изменено. + +/community/members.bml.success.return=ВернутьÑÑ Ðº ÑпиÑку + +/community/members.bml.title=УчаÑтники ÑообщеÑтва + +/community/members.bml.update=Обновить наÑтройки + +/community/moderate.bml.approve.button=Да, одобрить + +/community/moderate.bml.approve.header=Одобрить Ñту запиÑÑŒ? + +/community/moderate.bml.approve.preapprove=Кроме того, добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок немодерируемых учаÑтников. + +/community/moderate.bml.approve.text=Ð’Ñ‹ уверены, что одобрÑете Ñту запиÑÑŒ? + +/community/moderate.bml.brlist.actions=ДейÑÑ‚Ð²Ð¸Ñ + +/community/moderate.bml.brlist.poster=Ðвтор + +/community/moderate.bml.brlist.subject=Ðачало заголовка + +/community/moderate.bml.brlist.time=Ð’Ñ€ÐµÐ¼Ñ + +/community/moderate.bml.brlist.view=ПоÑмотреть + +/community/moderate.bml.browse.empty=Очередь на модерацию пуÑта. + +/community/moderate.bml.browse.header=Модерировать ÑообщеÑтво + +/community/moderate.bml.browse.text=СпиÑок запиÑей Ð´Ð»Ñ Ð¼Ð¾Ð´ÐµÑ€Ð°Ñ†Ð¸Ð¸ в ÑообщеÑтве [[link]] + +/community/moderate.bml.choice.approve=Одобрить + +/community/moderate.bml.choice.bkapprove=#82dd88 + +/community/moderate.bml.choice.bkreject=#e08291 + +/community/moderate.bml.choice.reject=Отклонить + +/community/moderate.bml.error.noaccess=Увы, Ð’Ñ‹ не модератор ÑообщеÑтва [[comm]]. + +/community/moderate.bml.error.noentry=ЗапиÑÑŒ не найдена (возможно, уже обработана другим модератором). + +/community/moderate.bml.error.nolist=Ð’Ñ‹ не модератор ни одного ÑообщеÑтва. + +/community/moderate.bml.error.notfound=Ðккаунт ÑообщеÑтва не найден + +/community/moderate.bml.manage=Управление ÑообщеÑтвами + +/community/moderate.bml.moderate=Модерировать ÑообщеÑтво + +/community/moderate.bml.modlist.actions=ДейÑÑ‚Ð²Ð¸Ñ + +/community/moderate.bml.modlist.actmodempty=[Модерировать] + +/community/moderate.bml.modlist.actmoderate=Модерировать + +/community/moderate.bml.modlist.count=Размер очереди + +/community/moderate.bml.modlist.header=Модерировать ÑообщеÑтва + +/community/moderate.bml.modlist.title=Заголовок + +/community/moderate.bml.modlist.username=Пользователь + +/community/moderate.bml.posted.appheader=Одобрено автоматичеÑки + +/community/moderate.bml.posted.apptext=[[user]] также был добавлен к ÑпиÑку немодерируемых пользователей. + +/community/moderate.bml.posted.header=ПолучилоÑÑŒ + +/community/moderate.bml.posted.proterror=ЗапиÑÑŒ не была добавлена из-за Ñледующей ошибки протокола: [[err]] + +/community/moderate.bml.posted.text=ЗапиÑÑŒ была уÑпешно добавлена + +/community/moderate.bml.reject.button=Да, отклонить + +/community/moderate.bml.reject.header=Отклонить Ñту запиÑÑŒ? + +/community/moderate.bml.reject.reason=Ð’Ñ‹ также можете объÑÑнить причину, по которой вы отклонили данную запиÑÑŒ. Пользователь получит Ñто объÑÑнение по e-mail. + +/community/moderate.bml.reject.text=Ð’Ñ‹ уверены, что хотите отклонить Ñту запиÑÑŒ? + +/community/moderate.bml.rejected.header=Отклонена + +/community/moderate.bml.rejected.text=ЗапиÑÑŒ была отклонена. + +/community/moderate.bml.title=Модерирование ÑообщеÑтва + +/community/pending.bml.approve.title=Подвердить вÑтупление в члены ÑообщеÑтва? + +/community/pending.bml.no=Ðет + +/community/pending.bml.nopending.body=Ожидающих зачиÑÐ»ÐµÐ½Ð¸Ñ Ð² ÑообщеÑтво нет. + +/community/pending.bml.nopending.title=Ждущих Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð½ÐµÑ‚ + +/community/pending.bml.success.added=Ð’Ñ‹ добавили [[num]] [[?num|человека|человек]] к членам Ñтого ÑообщеÑтва + +/community/pending.bml.success.ignored=[[num]] [[?num|пользователь|пользователей]] вÑе еще ожидают Ñ€ÐµÑˆÐµÐ½Ð¸Ñ + +/community/pending.bml.success.previous=[[num]] [[?num|Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ обработан|запроÑов не обработано]], поÑкольку они больше не ожидают утверждениÑ. Возможно, другой Ñмотритель уже обработал [[?num|его|их]]. + +/community/pending.bml.success.rejected=Ð’Ñ‹ отказали [[num]] [[?num|пользователю|пользователÑм]] во вÑтуплении в Ñто ÑообщÑтво + +/community/pending.bml.title=Ожидают зачиÑÐ»ÐµÐ½Ð¸Ñ Ð² члены ÑообщеÑтва + +/community/pending.bml.yes=Да + +/community/search.bml.button.clear=ОчиÑтить форму + +/community/search.bml.button.search=ИÑкать! + +/community/search.bml.checkbox.onlywithpics=Только ÑообщеÑтва Ñ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ°Ð¼Ð¸ + +/community/search.bml.label.byinterest=По интереÑам + +/community/search.bml.label.bylocation=По меÑтоположению + +/community/search.bml.label.bytime=По времени поÑледнего Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ + +/community/search.bml.label.city=Город: + +/community/search.bml.label.country=Страна: + +/community/search.bml.label.displayoptions=Показывать + +/community/search.bml.label.hasmember=По учаÑтнику + +/community/search.bml.label.othercriteria=По другому критерию + +/community/search.bml.label.outputformat=Формат вывода: + +/community/search.bml.label.records=Ðа Ñтранице: + +/community/search.bml.label.searchcomm=Ðайти ÑообщеÑтва + +/community/search.bml.label.selecriteria=Выберите критерий, по которому хотите найти ÑообщеÑтво. Ð’Ñ‹ получите переÑечение результатов поиÑка по вÑем выбранным критериÑм. Другими Ñловами, критерии объединÑÑŽÑ‚ÑÑ Ð¿Ð¾ принципу "И", не "ИЛИ". + +/community/search.bml.label.sortmethod=Сортировать по: + +/community/search.bml.label.stateprovince=Штат/ПровинциÑ: + +/community/search.bml.label.updated=ПоÑледний раз обновлÑлоÑÑŒ в течение + +/community/search.bml.sel.bypicture=По картинке + +/community/search.bml.sel.communityname=По названию ÑообщеÑтва + +/community/search.bml.sel.commview=Вид ÑообщеÑтва + +/community/search.bml.sel.day=Ð´Ð½Ñ + +/community/search.bml.sel.month=меÑÑца + +/community/search.bml.sel.simple=ПроÑтой + +/community/search.bml.sel.updatetime=По времени Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ + +/community/search.bml.sel.username=По имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/community/search.bml.sel.week=недели + +/community/search.bml.title=ПоиÑк по ÑообщеÑтвам + +/community/sentinvites.bml.date=Дата Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + +/community/sentinvites.bml.key.date=Дата + +/community/sentinvites.bml.key.sentby=Кем отоÑлано + +/community/sentinvites.bml.key.status=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/community/sentinvites.bml.none.body=Ð’ поÑледние 30 дней приглашений не раÑÑылалоÑÑŒ. ЕÑли вы хотите приглаÑить людей в Ñто ÑообщеÑтво, пожалуйÑта, зайдите на Страницу учаÑтников. + +/community/sentinvites.bml.none.title=Приглашений не найдено + +/community/sentinvites.bml.send=ПоÑлать Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ + +/community/sentinvites.bml.title=ОтоÑланные Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ + +/community/settings.bml.button.changecommunity=Обновить наÑтройки + +/community/settings.bml.button.createcommunity=Создать ÑообщеÑтво + +/community/settings.bml.error.alreadycomm=Этот аккаунт уже принадлежит ÑообщеÑтву. + +/community/settings.bml.error.badpassword=Ðеверный пароль к ÑообщеÑтву + +/community/settings.bml.error.hasentries=Ð’ Ñтом дневнике уже еÑÑ‚ÑŒ запиÑи и его тип не может быть изменён. + +/community/settings.bml.error.maintainertype=Ðккаунт ÑÐ¼Ð¾Ñ‚Ñ€Ð¸Ñ‚ÐµÐ»Ñ ÑообщеÑтва должен быть чаÑтным, а не общеÑтвенным. + +/community/settings.bml.error.noaccess=Только Ñмотрители ÑообщеÑтва могут редактировать наÑтройки ÑообщеÑтва. Ð’Ñ‹ не ÑвлÑетеÑÑŒ Ñмотрителем ÑообщеÑтва [[comm]], + +/community/settings.bml.error.notcomm=Это не аккаунт ÑообщеÑтва. + +/community/settings.bml.error.notfound=Ðккаунт ÑообщеÑтва не найден. + +/community/settings.bml.error.samenames=Ðккаунты ÑÐ¼Ð¾Ñ‚Ñ€Ð¸Ñ‚ÐµÐ»Ñ Ð¸ ÑообщеÑтва не могут Ñовпадать. + +/community/settings.bml.label.anybodycan=Ð’Ñе учаÑтники
    Кто угодно может пиÑать в Ñто ÑообщеÑтво Ñразу поÑле вÑтуплениÑ. + +/community/settings.bml.label.changeheader=Изменить наÑтройки ÑообщеÑтва + +/community/settings.bml.label.changetext=ЗдеÑÑŒ можно изменить наÑтройки принадлежащего вам ÑообщеÑтва или ÑообщеÑтва, Ñмотрителем которого вы ÑвлÑетеÑÑŒ. + +/community/settings.bml.label.closedmemb2=Закрытое ÑообщеÑтво
    Больше никто не может в него вÑтупить . + +/community/settings.bml.label.commchanged=ÐаÑтройки ÑообщеÑтва изменены. + +/community/settings.bml.label.commcreate=Это аккаунт, который вы пожелали превратить в ÑообщеÑтво. Он должен быть предварительно Ñоздан, но не должен иÑпользоватьÑÑ ÐºÐµÐ¼-то перÑонально, так как потом в Ñтом дневнике Ñмогут пиÑать множеÑтво разных людей. + +/community/settings.bml.label.commcreated=СообщеÑтво Ñоздано. + +/community/settings.bml.label.commheader=Ðккаунт ÑообщеÑтва + +/community/settings.bml.label.comminfo=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/community/settings.bml.label.commopts=ÐаÑтройки ÑообщеÑтва + +/community/settings.bml.label.commsite=Сайт ÑообщеÑтва + +/community/settings.bml.label.community=СообщеÑтво: + +/community/settings.bml.label.createheader=Создать ÑообщеÑтво + +/community/settings.bml.label.createtext=ЗдеÑÑŒ вы можете Ñоздать ÑообщеÑтво. СообщеÑтво - Ñто Ñпециальный вид аккаунта, который позволÑет людÑм приÑоединÑÑ‚ÑŒÑÑ Ð¸ пиÑать в него. Ðапример, поÑмотрите на ÑообщеÑтво "Убей ÐÐТО". + +/community/settings.bml.label.howoperates=Укажите, в каком режиме ваше ÑообщеÑтво будет работать (потом Ñти наÑтройки можно изменить). + +/community/settings.bml.label.maintainer=Смотритель: + +/community/settings.bml.label.maintainer.login=ЕÑли Ñто не Ð¸Ð¼Ñ Ð±ÑƒÐ´ÑƒÑ‰ÐµÐ³Ð¾ ÑмотрителÑ, войдите под другим. + +/community/settings.bml.label.managepage=Управление ÑообщеÑтвом - добавить членов ÑообщеÑтва, разрешить оÑтавлÑÑ‚ÑŒ запиÑи, назначить модераторов и Ñ‚.п. + +/community/settings.bml.label.membership=УчаÑтие + +/community/settings.bml.label.moderatedmemb=Модерируемое ÑообщеÑтво
    ЗапроÑÑ‹ о вÑтуплении приÑылаютÑÑ Ð²Ð°Ð¼ по еmail Ð´Ð»Ñ ÑƒÑ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ. + +/community/settings.bml.label.modheader=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ð¸Ñ + +/community/settings.bml.label.modis=Модерируемое
    Ðовые запиÑи должны быть одобрены модератором. + +/community/settings.bml.label.modisnt=Ðемодерируемое
    Ðовые запиÑи ÑтановÑÑ‚ÑÑ Ð²Ð¸Ð´Ð½Ñ‹ Ñразу. + +/community/settings.bml.label.modtext=Модерируемое ли Ñто ÑообщеÑтво? + +/community/settings.bml.label.nmcan=Ð’Ñе могут пиÑать
    Пользователи могут пиÑать в Ñто ÑообщеÑтво даже не приÑоединÑÑÑÑŒ к нему. + +/community/settings.bml.label.nmcant=Только учаÑтники могут пиÑать
    Пользователи могут пиÑать в Ñто ÑообщеÑтво только Ñтав его учаÑтниками. + +/community/settings.bml.label.nmheader=ДоÑтуп Ð´Ð»Ñ Ð½Ðµ-учаÑтников + +/community/settings.bml.label.nmtext=Можно ли пиÑать в Ñто ÑообщеÑтво, не приÑоединÑÑÑÑŒ к нему? + +/community/settings.bml.label.openmemb=Свободное учаÑтие
    Ð’Ñе желающие могут приÑоединитьÑÑ Ðº Ñтому ÑообщеÑтву. + +/community/settings.bml.label.password=Пароль: + +/community/settings.bml.label.postaccess=Кто может пиÑать + +/community/settings.bml.label.rellinks=Важные ÑÑылки: + +/community/settings.bml.label.selcan=Только избранные
    ПиÑать могут только те учаÑтники ÑообщеÑтва, которым Ñто разрешит Ñмотритель. + +/community/settings.bml.label.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/community/settings.bml.label.whocanjoin=Кто может приÑоединитьÑÑ Ðº Ñтому ÑообщеÑтву? + +/community/settings.bml.label.whocanpost=Кто может пиÑать в Ñто ÑообщеÑтво? + +/community/settings.bml.manage2=Управление ÑообщеÑтвами + +/community/settings.bml.members=[УчаÑтники] + +/community/settings.bml.name=Ðазвание ÑообщеÑтва: [[name]] + +/community/settings.bml.success=ПолучилоÑÑŒ! + +/community/settings.bml.title.create=Создать ÑообщеÑтво + +/community/settings.bml.title.modify=ÐаÑтройки ÑообщеÑтва + +/community/transfer.bml.account=Ðккаунт ÑообщеÑтва + +/community/transfer.bml.badstatus.body=ПользовательÑкое имÑ, под которым вы вошли в ÑиÑтему, ÑоответÑтвует деактивированному аккаунту; поÑтому пользоватьÑÑ Ñтой Ñтраницей вы, увы, не можете. + +/community/transfer.bml.badstatus.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° + +/community/transfer.bml.body=ЕÑли вы знаете пароль ÑообщеÑтвева, но в наÑтоÑщий момент вы не его Ñмотритель, вы можете Ñтать Ñмотрителем -- Ð´Ð»Ñ Ñтого надо заполнить форму: + +/community/transfer.bml.button.title=Передать ÑообщеÑтво + +/community/transfer.bml.error.alreadyadmin=Ð’Ñ‹ уже Ñмотритель ÑообщеÑтва + +/community/transfer.bml.error.badstatus=СообщеÑтво не активно. + +/community/transfer.bml.error.mismatch=Пароли не Ñовпадают. + +/community/transfer.bml.error.nopassword=Ðе вееден пароль. + +/community/transfer.bml.error.notcomm=Это не аккаунт ÑообщеÑтва. + +/community/transfer.bml.error.notfound=Ðккаунт не найден. + +/community/transfer.bml.password=Пароль ÑообщеÑтва + +/community/transfer.bml.success.body=ПолучилоÑÑŒ -- вы теперь Ñмотритель [[comm]]. + +/community/transfer.bml.success.title=ПолучилоÑÑŒ! + +/community/transfer.bml.title=Передать ÑообщеÑтво + +/create.bml.birthday.birthdate=Дата рождениÑ: + +/create.bml.birthday.head=Проверка возраÑта + +/create.bml.birthday.question=ЗдеÑÑŒ нужно ввеÑти день, меÑÑц и год вашего рождениÑ. Этот куÑок кода нужен в livejournal.com Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы не противоречить какому-то идиотÑкому ÑевероамериканÑкому закону. Ð’Ñкоре он будет удален. Пока что, мы может только заверить ваÑ, что Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ðµ попадает ни в какую базу данных. Ðапишите что угодно (нужно только, чтобы на момент ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° вам было больше 13 лет). + +/create.bml.birthday.required=(required) + +/create.bml.birthday.security=Security (что бы Ñто ни значило): + +/create.bml.btn.create=Создать дневник + +/create.bml.btn.proceed=Продолжить... + +/create.bml.captcha.answer=Ответ: + +/create.bml.captcha.audiodesc=Чтобы доказать, что дневник региÑтрирует не робот, наберите цифры, которые вы уÑлышали: + +/create.bml.captcha.desc=Ðам нужно убедитьÑÑ, что дневник региÑтрирует не робот. ПожалуйÑта, наберите буквы и цифры, которые вы видите на картинке. ЕÑли вы не можете прочитать текÑÑ‚, наберите Ñлово "AUDIO" и пройдите звуковой теÑÑ‚. + +/create.bml.captcha.invalid=Ðеправильный ответ. Попробуйте еще раз. + +/create.bml.captcha.play=ВоÑпроизведение звука + +/create.bml.captcha.prove=Проверим, что вы - не робот + +/create.bml.clusterselect.cluster=КлаÑтер: + +/create.bml.clusterselect.clusternum=КлаÑтер [[number]] + +/create.bml.clusterselect.head=Выбор клаÑтера + +/create.bml.clusterselect.nocluster=Без клаÑтера + +/create.bml.clusterselect.text=Выберите клаÑтер, в котором хотите Ñоздать пользователÑ. Внимание: Эта наÑтройка только Ð´Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸/теÑтированиÑ. Реальные пользователи не Ñмогут выбрать Ñту наÑтройку и ничего не будут знать о ней. + +/create.bml.community=Рможет быть, вы на Ñамом деле хотите Ñоздать ÑообщеÑтво? + +/create.bml.create.head=Создание нового дневника + +/create.bml.create.text=Создать новый дневник легко, проÑто Ñледуйте инÑтрукциÑм. + +/create.bml.email.head=Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты + +/create.bml.email.input.head=E-mail адреÑ: + +/create.bml.email.text2=Из Ñоображений безопаÑноÑти нам требуетÑÑ Ð²Ð°Ñˆ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты. Ðикогда и ни при каких обÑтоÑтельÑтвах он не будет продан или иным ÑпоÑобам передан Ñпаммерам. Мы их ненавидим больше, чем вы (и чем ÐÐТО). Чтобы узнать подробноÑти, прочтите наше положение о конфиденциальноÑти. + +/create.bml.error.birthday.invalid=Ð’ качеÑтве Ð´Ð½Ñ Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð°Ð´Ð¾ указать реально ÑущеÑтвующий день. + +/create.bml.error.coppa.under13=Извините -- мы пока что не уÑпели убрать идиотÑкий запрет, введенный авторами кода из-за американÑкого законодательÑтва. ПожалуйÑта, Ñделайте вид, что вам больше 13 лет. + +/create.bml.error.email.blank=Ð’Ñ‹ должны указать Ñвой Ð°Ð´Ñ€ÐµÑ e-mail. + +/create.bml.error.email.lj_domain=К Ñожалению, иÑпользовать e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ð° [[domain]] нельзÑ. Введите другой Ð°Ð´Ñ€ÐµÑ e-mail. + +/create.bml.error.email.nospaces=Ð’ e-mail адреÑе Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать пробелы. ЕÑли вы пользователь AOL, учтите, что ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð² интернете -- Ñто ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² AOL без пробелов, за которым Ñледует @aol.com + +/create.bml.error.password.asciionly=Ð’ пароле можно иÑпользовать только Ñимволы ASCII (и Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать кириллицу). + +/create.bml.error.password.blank=Ð’Ñ‹ должны ввеÑти пароль. + +/create.bml.error.password.nomatch=Пароли не Ñовпадают. + +/create.bml.error.postrequired=Ðужно иÑпользовать метод POST. + +/create.bml.error.username.blank=ПожалуйÑта, введите имÑ, название или пÑевдоним. + +/create.bml.error.username.inuse=Такой пользователь уже еÑÑ‚ÑŒ -- выберите, пожалуйÑта, другое имÑ. + +/create.bml.error.username.iscode=Это, кажетÑÑ, приглаÑительной код, а не имÑ! + +/create.bml.error.username.mustenter=Ð’Ñ‹ должны ввеÑти имÑ. + +/create.bml.error.username.reserved=Извините, Ñто Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°Ñ€ÐµÐ·ÐµÑ€Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¾. + +/create.bml.errors.label=ПожалуйÑта, Ñделайте Ñледующие иÑÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ повторите Ð·Ð°Ð¿Ñ€Ð¾Ñ + +/create.bml.initial.friend.lj_maintenance=Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ запланированных и незапланированных отключениÑÑ…, а также профилактике. + +/create.bml.initial.friend.news=ÐовоÑти и ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ [[sitename]] + +/create.bml.initialfriends=Добавьте Ñти дневники в ÑпиÑок ваших друзей, чтобы быть в курÑе новоÑтей и информации Ñайта. + +/create.bml.initialfriends.heading=ДрузьÑ, иногда полезные новым пользователÑм + +/create.bml.name.head=Ваше Ð¸Ð¼Ñ + +/create.bml.name.input.head=ИмÑ: + +/create.bml.name.text=Как Ð²Ð°Ñ Ð·Ð¾Ð²ÑƒÑ‚? Это Ð¸Ð¼Ñ Ð±ÑƒÐ´ÐµÑ‚ показано в заголовке вашего дневника, а еÑли вы захотите, то и в каталоге пользователей. Ð’Ñ‹ не обÑзаны указывать полное или даже Ñвоё наÑтоÑщее имÑ. + +/create.bml.password.head=Пароль + +/create.bml.password.input.head1=Пароль: + +/create.bml.password.input.head2= Повторите пароль: + +/create.bml.password.secure=Пароль должен быть надежным -- Ñлова, которые еÑÑ‚ÑŒ в Ñловаре, а также ваше пользовательÑкое имÑ, Ð°Ð´Ñ€ÐµÑ Ð¸ производные от них, не годÑÑ‚ÑÑ. + +/create.bml.password.text=Выберите пароль. + +/create.bml.proceed.btn.proceed=Продолжить... + +/create.bml.proceed.warning=Ðажмите Продолжить только один раз!!! + +/create.bml.success.btn.enterinfo=Введите личные данные + +/create.bml.success.head=УÑпешно + +/create.bml.success.text1=Ваш дневник Ñоздан. Ðа ваш Ð°Ð´Ñ€ÐµÑ [[email]] выÑлана Ð²Ð°Ð¶Ð½Ð°Ñ Ñ€ÐµÐ³Ð¸ÑÑ‚Ñ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¸ дальнейшие инÑтрукции. Ðе забудьте подтвердить Ñоздание нового дневника, Ð¿Ñ€Ð¾Ð¹Ð´Ñ Ð¿Ð¾ ÑÑылке, ÑодержащейÑÑ Ð² пиÑьме. + +/create.bml.success.text2=Ваш Дневник доÑтупен по адреÑу: + +/create.bml.success.text3=ПожалуйÑта, заполните небольшую анкету о Ñебе. Ð’ оÑновном, Ñто необÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, но так мы получаем предÑтавление о том, кто пользуетÑÑ [[sitename]] + +/create.bml.title=Создать новый дневник + +/create.bml.tos.heading=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг + +/create.bml.useacctcodes.entercode=Введите код Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ пользователÑ. Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации Ñмотрите: Как мне Ñоздать новый аккаунт? + +/create.bml.useacctcodes.welcome=Добро пожаловать! + +/create.bml.username.box.head=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/create.bml.username.charsallowed=Ваше пользовательÑкое Ð¸Ð¼Ñ Ð¼Ð¾Ð¶ÐµÑ‚ ÑоÑтоÑÑ‚ÑŒ только из Ñтрочных букв (a-z), цифр (0-9), и знака Ð¿Ð¾Ð´Ñ‡ÐµÑ€ÐºÐ¸Ð²Ð°Ð½Ð¸Ñ (_).
    Длина имени не может быть больше 15 Ñимволов. + +/create.bml.username.forpaidaccts=Или, Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ñ… пользователей: + +/create.bml.username.head=ПользовательÑкое Ð¸Ð¼Ñ + +/create.bml.username.ljaddress=Ваш дневник будет находитьÑÑ Ð¿Ð¾ Ñтим адреÑам: + +/create.bml.username.text=У каждого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[sitename]] должно быть уникальное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ñ€Ð¸ÑутÑтвует в адреÑе, по которому раÑположен ваш дневник, и должно иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему. Его также видно, когда вы оÑтавлÑете комментарии в других дневниках. + +/create.bml.username.username=имÑ_Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/customize/index.bml.change=Изменить + +/customize/index.bml.choose=Ð’Ñ‹ хотите иÑпользовать Ñтарую ÑиÑтему Ñтилей, или новую? + +/customize/index.bml.choose.header=Выбрать ÑиÑтему Ñтилей + +/customize/index.bml.choose.s1=Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÑиÑтема (S1) + +/customize/index.bml.choose.s2=ÐÐ¾Ð²Ð°Ñ ÑиÑтема (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ðе могу Ñгенерировать Ñлой Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/customize/index.bml.error.disallowed_custom_layer=К Ñожалению, Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð¾Ð¼ вашего типа Ñтот дополнительный Ñлой недоÑтупен + +/customize/index.bml.error.fail_create_style=Увы, не удалоÑÑŒ Ñоздать новый Ñтиль + +/customize/index.bml.error.not_your_layout=Ðе ваша Ñхема. + +/customize/index.bml.error.not_your_theme=Ðе ваша тема + +/customize/index.bml.error.no_core_parent=ОтÑуÑтвует начавший тему? + +/customize/index.bml.previews=(Предварительный проÑмотр) + +/customize/index.bml.s1.header=Как пользоватьÑÑ S1 + +/customize/index.bml.s2.advanced.denied=РаÑширенные наÑтройки доÑтупны только пользователÑм Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼Ð¸ и поÑтоÑнными аккаунтами, а также первопользователÑм (early adopters). О преимущеÑтвах платного аккаунта. + +/customize/index.bml.s2.advanced.header=РаÑширенные наÑтройки + +/customize/index.bml.s2.advanced.permitted=Создать новые Ñхемы и Ñтили Ñ Ð½ÑƒÐ»Ñ Ð¼Ð¾Ð¶Ð½Ð¾ на Ñтранице раÑширенных наÑтроек. + +/customize/index.bml.s2.customize=Эти параметры завиÑÑÑ‚ от Ñхемы. + +/customize/index.bml.s2.customize.header=Шаг 2: Изменить вид Ñтраницы + +/customize/index.bml.s2.customize.language=Данной Ñхемой полноÑтью или чаÑтично поддерживаютÑÑ Ñледующие Ñзыки: + +/customize/index.bml.s2.customize.language.custom=(Дополнительно) + +/customize/index.bml.s2.customize.language.default=(По умолчанию) + +/customize/index.bml.s2.customize.language.header=Язык + +/customize/index.bml.s2.customize.settings=ЕÑли Ð’Ñ‹ хотите еще больше изменить вид Ñвоего дневника, здеÑÑŒ вы можете подкрутить отдельные параметры, пока не получите то, что Вам нужно. + +/customize/index.bml.s2.customize.settings.delete=Удалить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/customize/index.bml.s2.customize.settings.delete.confirm=Vy tochno hotite udalit' ehti nastrojki? + +/customize/index.bml.s2.customize.settings.edit=Редактировать наÑтройки + +/customize/index.bml.s2.customize.settings.header=Изменить отдельные параметры + +/customize/index.bml.s2.customize.settings.new=ÐаÑтроить + +/customize/index.bml.s2.customize.themes=Ð’Ñ‹ можете выбрать одну из Ñледующих тем Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ Ñхемы. + +/customize/index.bml.s2.customize.themes.default=(По умолчанию Ð´Ð»Ñ Ñхемы) + +/customize/index.bml.s2.customize.themes.header=Темы + +/customize/index.bml.s2.layout=Выберите Ñхему. Выбрав новую Ñхему, вы потерÑете вÑе другие изменениÑ, которые могли Ñделать, так как набор доÑтупных тем и отдельные наÑтройки завиÑÑÑ‚ от выбранной Ñхемы. + +/customize/index.bml.s2.layout.header=Шаг 1: Схема + +/customize/index.bml.s2.related.editinfo.about=УÑтановите название Вашего дневника и другие ÑвойÑтва. + +/customize/index.bml.s2.related.header=СвÑзанные Ñтраницы. + +/customize/index.bml.s2.related.links.about=Ðекоторые Ñтили могут включатÑÑ Ð² Ваш ÑпиÑок ÑÑылок. + +/customize/index.bml.s2.related.modify.about=УÑтановите набор картинок Ð´Ð»Ñ Ð½Ð°ÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ (mood icons) Вашего дневника. + +/customize/index.bml.title=Оформление дневника + +/delcomment.bml.changeoptions=Внимание: Ðа Ñтранице "[[link]]" вы можете выбрать, разрешаете ли вы вÑем, зарегиÑтрированным пользователÑм, или только друзьÑм комментировать ваши запиÑи. + +/delcomment.bml.confirm.banuser=Запретить [[user]] пиÑать комментарии в вашем дневнике + +/delcomment.bml.confirm.body=Ð’Ñ‹ точно хотите удалить Ñтот комментарий? + +/delcomment.bml.confirm.delthread=Удалить ветвь диÑкуÑÑии целиком + +/delcomment.bml.confirm.head=Удалить Ñтот комментарий? + +/delcomment.bml.confirm.spam=Отметить Ñтот комментарий как Ñпам + +/delcomment.bml.confirm.submit=Удалить комментарий + +/delcomment.bml.error.alreadydeleted=Этот комментарий уже удален + +/delcomment.bml.error.cantdelete=Комментарий может быть удален только его автором или автором дневника + +/delcomment.bml.error.cantdelete.comm=Комментарий может быть удален только его автором, автором запиÑи в дневнике или Ñмотрителем ÑообщеÑтва + +/delcomment.bml.error.invalidtype=Ðеправильный тип комментариÑ. Ð”Ð°Ð½Ð½Ð°Ñ Ñтраница иÑпользуетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸ÐµÐ² к запиÑÑм в дневнике. + +/delcomment.bml.error.nocomment=Этого комментарий не ÑущеÑтвует. + +/delcomment.bml.error.suspended=Увы, пока ваш аккаунт заморожен, удалÑÑ‚ÑŒ комментарии вам нельзÑ. + +/delcomment.bml.success.andban=Комментарий удален, и пользователь [[user]] лишён права оÑтавлÑÑ‚ÑŒ комментарии в вашем дневнике. + +/delcomment.bml.success.head=Удалено + +/delcomment.bml.success.noban=Комментарий удален + +/delcomment.bml.success.spam=Кроме того, админиÑтраторы Ñайта извещены о том, что данный комментарий - Ñпам. СпаÑибо за Ñообщение. + +/delcomment.bml.title=Удаление ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/directory.bml.browse.country.desc=Выберите, из какой Ñтраны вы хотите найти дневники. + +/directory.bml.browse.country.title=Показать дневники, упорÑдоченные по Ñтранам + +/directory.bml.browse.usa.desc=Ðажмите на штат СШРили на название Ñтраны из ÑпиÑка, приведенного под картой, чтобы увидеть дневники из выбранного штата или Ñтраны. + +/directory.bml.browse.usa.title=Показать дневники ÑоответÑтвенно штату СШР+ +/directory.bml.error.accounttype=К Ñожалению, ваш аккаунт не позволÑет производить поиÑк в каталоге, или же вы не вошли в ÑиÑтему. ЕÑли ваш аккаунт позволÑет работу Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼, убедитеÑÑŒ, что вы вошли в ÑиÑтему и попробуйте ещё раз. + +/directory.bml.navcrap.matches=Ðайдено: [[count]] + +/directory.bml.navcrap.xofy=Показана Ñтраница [[curpage]] из [[totpages]] (Ñ [[reca]] по [[recb]] запиÑÑŒ) + +/directory.bml.open=Открыть + +/directory.bml.post=ÐапиÑать + +/directory.bml.search.monkey=Выше вы можете видеть трёх вошек, которые в данный момент выполнÑÑŽÑ‚ поиÑк по вашему запроÑу. Ждите ответа. + +/directory.bml.search.new=Ðовый Ð·Ð°Ð¿Ñ€Ð¾Ñ + +/directory.bml.search.overflow=Ð’ результатах поиÑка выводитÑÑ Ð½Ðµ более [[count]] дневников. ПожалуйÑта, уточните запроÑ. + +/directory.bml.search.title=ПоиÑк + +/directory.bml.update=Обновить + +/directory.bml.user=Пользователь + +/doc/index.bml.about=Добро пожаловать в хранилище документации [[sitename]]. ЗдеÑÑŒ вы можете найти информацию о многом из того, что каÑаетÑÑ ÑервиÑов и программного обеÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ñервера [[sitename]]. ПожалуйÑта, выберите интереÑующую Ð²Ð°Ñ Ñ‚ÐµÐ¼Ñƒ: + +/doc/index.bml.about.header=Добро пожаловать + +/doc/index.bml.docs.faq.about=ВопроÑÑ‹ о [[sitename]] и ответы на них + +/doc/index.bml.docs.faq.title=Справка (FAQ) + +/doc/index.bml.docs.guides.about=Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/doc/index.bml.docs.guides.title=ИнÑтрукции + +/doc/index.bml.docs.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ + +/doc/index.bml.docs.howto.about=Разные штуки, Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ которых можно изменить наÑторйки вашего дневника + +/doc/index.bml.docs.tour.about=Путеовдитель по Ñайту Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… пользователей + +/doc/index.bml.docs.tour.title=Путеводитель + +/doc/index.bml.title=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ + +/doc/index.bml.volunteering.ljsysdoc=ОбÑуждение ÑиÑтемы Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ [[sitename]] + +/doc/index.bml.volunteering.ljuserdoc=ОбÑуждение документации Ð´Ð»Ñ ÐºÐ¾Ð½ÐµÑ‡Ð½Ñ‹Ñ… пользователей + +/doc/tour/index.bml.comms.caption=Ð”Ð»Ñ Ð²Ð°Ñ, вероÑтно, не будет Ñюрпризом, что множеÑтво других пользователей имеют интереÑÑ‹, Ñхожие Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸. Ðа данный момент мы предлагаем возможноÑÑ‚ÑŒ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð² ÑообщеÑтва по интереÑам, либо Ñоздание Ñпециализированных дневников общего доÑтупа. + +/doc/tour/index.bml.comms.title=СообщеÑтва + +/doc/tour/index.bml.create.caption=[[sitename]] -- ÑообщеÑтво, оÑнованное на региÑтрации учаÑтников. Ðа данной Ñтранице объÑÑнÑетÑÑ, что такое региÑтрациÑ, почему она важна и какие преимущеÑтва она даёт. Ðа ней вы также найдёте форму Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ аккаунта. + +/doc/tour/index.bml.create.title=Создание аккаунта + +/doc/tour/index.bml.friends.caption=Ð’Ñ‹ можете Ñледить за ÑобытиÑми, о которых пишут в Ñвоих дневниках ваши друзьÑ, Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ функции "СпиÑок друзей". ЕÑли какой-то дневник показалÑÑ Ð²Ð°Ð¼ заÑлуживающим Ð²Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ -- добавьте его в Ñвой ÑпиÑок друзей. Это даÑÑ‚ вам возможноÑÑ‚ÑŒ читать вÑе интереÑующие Ð²Ð°Ñ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ¸ на одной Ñтранице. + +/doc/tour/index.bml.friends.title=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/doc/tour/index.bml.intro.caption=Этот путеводитель адреÑован новым пользователÑм и предназначен Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ [[sitename]]. Вам будет раÑÑказано, где раÑположены наиболее важные разделы, а также дана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ функциÑÑ… и возможноÑÑ‚ÑÑ…, которые могут вам пригодитьÑÑ. + +/doc/tour/index.bml.intro.title=Добро пожаловать! + +/doc/tour/index.bml.modify.caption=Ð’Ñ‹ можете оформить ваш дневник разными ÑпоÑобами, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ñтроенную ÑиÑтему Ñтилей и заранее определенные цветовые Ñхемы. Сделайте ваш дневник уникальным! + +/doc/tour/index.bml.modify.title=ПерÑÐ¾Ð½Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ + +/doc/tour/index.bml.nav.next=Далее --> + +/doc/tour/index.bml.nav.prev=<-- ВернутьÑÑ + +/doc/tour/index.bml.profile.caption=Ðами приветÑтвуетÑÑ Ð¿Ñ€Ð°ÐºÑ‚Ð¸ÐºÐ° Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñми [[sitename]] Ñтранички Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ о Ñебе: Ñто даёт нам предÑтавление о нашей аудитории, на базе которого мы развиваем и улучшаем ÑервиÑ. Тем не менее, Ñта практика не ÑвлÑетÑÑ Ð¾Ð±Ñзательной -- Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы иÑпользовать [[sitename]], от Ð²Ð°Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð»Ð¸ÑˆÑŒ Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, e-mail и пароль. + +/doc/tour/index.bml.profile.title=ПерÑÐ¾Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/doc/tour/index.bml.sitemap.caption=Мы надеемÑÑ, что Ñтот путеводитель помог вам в знакомÑтве Ñ Ð½Ð°ÑˆÐ¸Ð¼Ð¸ ÑервиÑами. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÐµÐµ подробной информации, вы в любой момент можете обратитьÑÑ Ðº Ñтраницам Ñлужбы техничеÑкой поддержки. ЕÑли вы захотите иÑÑледовать [[sitename]] более подробно -- обратите внимание на карту Ñайта. + +/doc/tour/index.bml.sitemap.title=Карта Ñайта + +/doc/tour/index.bml.support.caption=Ðа Ñтраницах Ñлужбы поддержки вы найдете ответы на чаÑто задаваемые вопроÑÑ‹ о Живом Журнале и множеÑтво другой полезной информации о ÑервиÑе, компании и ÑообщеÑтве в целом. + +/doc/tour/index.bml.support.title=Помощь + +/doc/tour/index.bml.title=Ознакомление - [[title]] + +/doc/tour/index.bml.update.caption=Добавление новых запиÑей -- Ñто главное, что позволÑет делать [[sitename]]. Добавить новую запиÑÑŒ очень проÑто: доÑтаточно впиÑать текÑÑ‚ в окошко на Ñтранице и нажать кнопку "Добавить запиÑÑŒ". MÑ‹ предлагаем и дополнительные возможноÑти: например, можно указать, какую музыку вы Ñлушаете или какое у Ð²Ð°Ñ Ð½Ð°Ñтроение в данный момент. + +/doc/tour/index.bml.update.title=Добавление новых запиÑей + +/editinfo.bml.advanced.about=ЕÑли вы не знаете, что Ñто такое, не обращайте вниманиÑ. + +/editinfo.bml.advanced.title=Дополнительные наÑтройки + +/editinfo.bml.allowshowcontact.about=Эту наÑтройку лучше оÑтавить включённой. Ð’ Ñтом Ñлучае другие пользователи Ñмогут ÑвÑзатьÑÑ Ñ Ð²Ð°Ð¼Ð¸, узнав Ð°Ð´Ñ€ÐµÑ e-mail или номер ICQ в вашем дневнике. + +/editinfo.bml.allowshowcontact.email=Отображение e-mail адреÑа: + +/editinfo.bml.allowshowcontact.email.actual_only=Только дейÑтвительный e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.both=Оба (дейÑтвительный и [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Только e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ð° нашем Ñайте + +/editinfo.bml.allowshowcontact.email.neither=Ðе показывать никаких адреÑов + +/editinfo.bml.allowshowcontact.email.no_show=Ðе показывать e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.show=Показывать e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Ð’Ñ‹ можете никому не показывать ваш Ð°Ð´Ñ€ÐµÑ e-mail (при Ñтом вÑÑ Ð¾ÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ выводитьÑÑ). Также можно выводить только адреÑ, предоÑтавленный нашим Ñайтом (доÑтупно только платным пользователÑм), наÑтоÑщий адреÑ, либо показывать и тот, и другой одновременно. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Ð’Ñ‹ можете никому не показывать ваш Ð°Ð´Ñ€ÐµÑ e-mail (при Ñтом вÑÑ Ð¾ÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ выводитьÑÑ). + +/editinfo.bml.allowshowcontact.title=Показывать контактную информацию в вашем дневнике? + +/editinfo.bml.allowshowinfo.about=ЕÑли хотите, чтобы другие пользователи могли видеть, где вы живёте (город, регион, Ñтрану) и когда вы родилиÑÑŒ, поÑтавьте здеÑÑŒ галочку. + +/editinfo.bml.allowshowinfo.title=Показывать меÑто жительÑтва и день рождениÑ? + +/editinfo.bml.bday.title=День Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +/editinfo.bml.bday.year.opt=год — необÑзательно + +/editinfo.bml.bdayreminders.about=ЕÑли вы хотите получать Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ днÑÑ… Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ñ… друзей по Ñайту, отметьте Ñтот пункт. + +/editinfo.bml.bdayreminders.header=ПриÑылать Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ днÑÑ… Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ (отключено) + +/editinfo.bml.bio.about=ЗдеÑÑŒ вы можете ввеÑти Ñвою мини-биографию. Она будет показана на вашей Ñтраничке "О пользователе". + +/editinfo.bml.bio.header=О Ð²Ð°Ñ + +/editinfo.bml.blockrobots.about<< +ЕÑли вы поÑтавите здеÑÑŒ галочку, поиÑковым роботам будет дано указание не индекÑировать Ñодержимое вашего дневника. +Ðекоторые роботы на такие ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¿Ð»ÑŽÑŽÑ‚. +. + +/editinfo.bml.blockrobots.header=Запретить поиÑковыми ÑиÑтемам индекÑирование моего дневника + +/editinfo.bml.chat.icquin.title=Ðомер ICQ + +/editinfo.bml.chat.jabber.title=Jabber + +/editinfo.bml.city.title=Город + +/editinfo.bml.country.choose=Выберите Ñтрану + +/editinfo.bml.country.title=Страна + +/editinfo.bml.donotlog=Ðет + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=ПоÑтавьте галочку, еÑли хотите, чтобы люди могли оÑтавлÑÑ‚ÑŒ комментарии к вашим запиÑÑм. + +/editinfo.bml.enableboards.header=Включить комментарии + +/editinfo.bml.encoding.about=Эти наÑтройки Ñтоит менÑÑ‚ÑŒ только в том Ñлучае, еÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ какие-то проблемы Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ°Ð¼Ð¸, Ñ Ð¿Ñ€Ð¾Ñ‡Ñ‚ÐµÐ½Ð¸ÐµÐ¼ Ñтарых дневникьных запиÑей или пиÑем, приÑылаемых [[sitename]]. + +/editinfo.bml.encoding.header=ÐаÑтройка кодировок + +/editinfo.bml.error.day.notinmonth=Ð’ указанном меÑÑце такого Ð´Ð½Ñ Ð½ÐµÑ‚! + +/editinfo.bml.error.day.outofrange=Ðеправильный день. Введите чиÑло от 1 до 31. + +/editinfo.bml.error.email.lj_domain<< +E-mail Ð°Ð´Ñ€ÐµÑ @[[domain]] вводить запрещено. +Ð’Ñ‹ должны ввеÑти в Ñтой Ñтроке Ñвой наÑтоÑщий адреÑ. +ЕÑли вы платный пользователь, пиÑьма по адреÑу [[user]]@[[domain]] будут перенаправлÑÑ‚ÑŒÑÑ Ð½Ð° ваш наÑтоÑщий адреÑ. +Ð’ наÑтройке "Показывать контактную информацию" также можно указать, какой (какие) e-mail адреÑ(а) вы хотите Ñделать видимым(и) другим пользователÑм. +. + +/editinfo.bml.error.email.none=Ð’Ñ‹ должны указать Ñвой Ð°Ð´Ñ€ÐµÑ e-mail + +/editinfo.bml.error.email.no_space<< +Ð’ e-mail адреÑах пробелы запрещены. +ЕÑли вы пользователь AOL, учтите, что ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð² интернете -- Ñто ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² AOL без пробелов, за которым Ñледует @aol.com +. + +/editinfo.bml.error.excessive_int<< +Извините, вы указали Ñлишком много интереÑов. Их может быть не больше 150, а у Ð²Ð°Ñ — [[intcount]]. +Ð’Ñе изменениÑ, Ñделанные в интереÑах, Ñохранены не будут. ВернитеÑÑŒ и Ñократите ÑпиÑок, поÑле чего попробуйте Ñохранить ещё раз. +. + +/editinfo.bml.error.locale.country_ne_state=Ð’Ñ‹ указали СШР(United States) в качеÑтве вашей Ñтраны, но ввели штат в поле "другой штат", а не выбрали его из ÑпиÑка штатов СШÐ. + +/editinfo.bml.error.locale.invalid_country=Каким-то образом вы выбрали неÑущеÑтвующую Ñтрану. ЧудеÑа! + +/editinfo.bml.error.locale.state_ne_country=Ð’Ñ‹ указали Ñтрану, отличную от СШÐ, но выбрали штат из ÑпиÑка штатов СШÐ. + +/editinfo.bml.error.locale.zip_ne_state<< +Почтовый Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ ÑоответÑтвует выбранному штату. +ИÑправьте информацию или Ñотрите одно из полей штата и почтового индекÑа, или оба Ñтих полÑ. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Ð’Ñ‹ ввели почтовый индекÑ, но вы не выбрали СШРв качеÑтве Ñвоей Ñтраны. +Мы храним только почтовые индекÑÑ‹ людей, проживающих в СШÐ. +ПожалуйÑта, вернитеÑÑŒ и либо Ñотрите почтовый индекÑ, либо выберите СШРв качеÑтве Ñвоей Ñтраны. +. + +/editinfo.bml.error.month.outofrange=Ðеправильный меÑÑц. Введите чиÑло от 1 до 12. + +/editinfo.bml.error.noname=Ваше Ð¸Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть указано. Укажите по меньшей мере проÑто Ð¸Ð¼Ñ Ð¸Ð»Ð¸ пÑевдоним. + +/editinfo.bml.error.tm.require.number=ЕÑли вы хотите пользоватьÑÑ ÑƒÑлугой текÑтовых Ñообщений, вы должны ввеÑти Ñвой номер телефона. + +/editinfo.bml.error.tm.require_provider<< +ЕÑли вы хотите пользоватьÑÑ ÑƒÑлугой текÑтовых Ñообщений, вы должны указать Ñвоего поÑтавщика уÑлуг. +ЕÑли ваш поÑтавщик не указан, пожалуйÑта, Ñообщите нам, как наÑтроить Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ уÑлугу текÑтовых Ñообщений, чтобы мы могли добавить его в наш ÑпиÑок. +. + +/editinfo.bml.error.year.notenoughdigits=Ðеправильный год. Введите четыре цифры. + +/editinfo.bml.error.year.outofrange=Ðеправильный год. + +/editinfo.bml.finished.about=Когда закончите, нажмите кнопку "Сохранить изменениÑ" ниже: + +/editinfo.bml.finished.header=Готово? + +/editinfo.bml.finished.save_button=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/editinfo.bml.foafurl.about=Ð’Ñ‹ точно хотите удалить Ñти наÑтройки? + +/editinfo.bml.foafurl.title=Внешний интернет-Ð°Ð´Ñ€ÐµÑ FOAF + +/editinfo.bml.gender.title=Пол + +/editinfo.bml.getreplies.about=ПоÑтавьте галочку, еÑли хотите получать по почте ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± ответах на ваши запиÑи или комментарии. + +/editinfo.bml.getreplies.header=Получать комментарии по почте + +/editinfo.bml.getselfemails.about=ПоÑтавьте галочку, еÑли вы хотите получать e-mail поÑле каждого вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð² дневниках пользователей или ÑообщеÑтв. Ваши анонимные комментарии ÑопровождатÑÑ e-mail не будут. + +/editinfo.bml.getselfemails.header=Получать Ñвои ÑобÑтвенные комментарии по e-mail + +/editinfo.bml.hidefriendof.about=ЕÑли вы уÑтановите Ñтот флаг, ÑпиÑок людей, добавивших Ð²Ð°Ñ Ð² друзьÑ, не будет выводитьÑÑ Ð½Ð° вашей Ñтранице "О пользователе". + +/editinfo.bml.hidefriendof.header=СпрÑтать ÑпиÑок "Ð’ друзьÑÑ… у" + +/editinfo.bml.howhear.about<< +ПроÑто из любопытÑтва -- откуда вы узнали о [[sitename]]. +ЕÑли вам о нем Ñообщил пользователь, введите его имÑ, еÑли вы получили информацию из другого иÑточника (газеты, веб-Ñайта и Ñ‚.п.), введите ÑоответÑтвующие названиÑ, хорошо? +. + +/editinfo.bml.howhear.header=Любопытно + +/editinfo.bml.htmlemail.about=EÑли ваша Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° корректно показывает пиÑьма в формате HTML, можете поÑтавить Ñту галочку. Почти вÑе программы пытаютÑÑ Ñто делать, но получаетÑÑ, как правило, нечитаемое безобразие. Рекомендуем Ñту опцию отключить (тогда вÑе пиÑьма будут в текÑтовом виде). Включайте только еÑли Ñовершенно точно знаете, что делаете. + +/editinfo.bml.htmlemail.header=ПоÑылать пиÑьма в формате HTML + +/editinfo.bml.imagelinks.about=Заменители картинок полезны, еÑли вы ходите в Сеть Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹, или у Ð²Ð°Ñ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾Ðµ Ñоединение; они замeнÑÑŽÑ‚ картинки их адреÑами. Картинки какого размерa вы бы хотели бы замеÑтить заменителÑми? + +/editinfo.bml.imagelinks.header=ИÑпользовать заменители картинок на Ñтранице друзей + +/editinfo.bml.imagelinks.size.all=ИÑпользовать заменители картинок вмеÑто любых картинок + +/editinfo.bml.imagelinks.size.custom=Выбрать: иÑпользовать заменители картинок вмеÑто картинок больше [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=ИÑпользовать заменители картинок вмеÑто больших картинок (больше [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=ИÑпользовать заменители картинок вмеÑто картинок Ñреднего размера (больше [[width]]x[[height]]) + +/editinfo.bml.int.about<< +ЕÑли хотите, чтобы другие люди могли найти Ð²Ð°Ñ Ð² каталоге по вашим интереÑам, перечиÑлите ниже вÑÑ‘, чем вы интереÑуетеÑÑŒ, разделÑÑ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑÑ‹ запÑтыми. +Лучше вÑего иÑпользовать короткие Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² одно Ñлово. ПроÑтое правило: ваш Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ впиÑыватьÑÑ Ð² предложение "Мне нравитÑÑ/нравÑÑ‚ÑÑ __________". Ð”Ð»Ñ ÑущеÑтвительных иÑпользуйте множеÑтвенное чиÑло, именительный падеж ("мумзики", а не "мумзик" или "мумзиков") (кроме Ñлучаев, когда множеÑтвенное чиÑло не употреблÑетÑÑ), Ð´Ð»Ñ Ð³Ð»Ð°Ð³Ð¾Ð»Ð¾Ð² — неопределённую форму ("любить"). +. + +/editinfo.bml.int.ex.bad=ПЛОХОЙ пример: Я люблю беÑитьÑÑ, колбаÑитьÑÑ, убивать мумзиков, любить природу. Такой текÑÑ‚ лучше напиÑать в вашей биографии (Ñм. выше). + +/editinfo.bml.int.ex.good=ХОРОШИЙ пример: беÑитьÑÑ, колбаÑитьÑÑ, мумзики, женщины, мужчины, Ð¿Ð¾Ð»Ð¾Ð²Ð°Ñ Ð´Ð¸ÑкриминациÑ, кошки + +/editinfo.bml.int.header=ИнтереÑÑ‹ + +/editinfo.bml.login.enterinfo=Чтобы изменить личную информацию, введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. + +/editinfo.bml.login.forgot.header=КажетÑÑ, вы что-то забыли? + +/editinfo.bml.login.forgot.recover=ЕÑли вы забыли Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, можете воÑÑтановить их здеÑÑŒ. + +/editinfo.bml.logip.always=Ð’Ñегда + +/editinfo.bml.logip.anon_only=Только анонимных пользователей + +/editinfo.bml.logip.header=ЗапиÑывать IP-адреÑа отвечающих людей? + +/editinfo.bml.mangleaddress.about=ЕÑли вы опаÑаетеÑÑŒ, что ÑпаммерÑкие программы могут найти ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ð° нашем Ñайте, поÑтавьте галочку -- тогда мы его так обработаем, что люди поймут, а роботы оÑтанутÑÑ Ð½Ð¸ Ñ Ñ‡ÐµÐ¼. + +/editinfo.bml.mangleaddress.header=ИÑказить показываемый e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.mutualfriends.about=Эта наÑтройка добавит новый ÑпиÑок к вашей Ñтранице "О пользователе": взаимные друзьÑ. Ð’ Ñто ÑпиÑке будут перечиÑлены те, кто занеÑен в ваш ÑпиÑок друзей и одновременно включил Ð²Ð°Ñ Ð² их ÑпиÑок друзей. + +/editinfo.bml.mutualfriends.header=Показать взaимных друзей на Ñтранице "О пользователе" + +/editinfo.bml.name.title=Ð˜Ð¼Ñ + +/editinfo.bml.newemail.body2<< +ЗдравÑтвуйте! Ð’Ñ‹ зарегиÑтрировали +Ваш е-мÑйл на [[sitename]]. Это +позволит Вам получать комментарии +по е-мÑйлу. Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ работы +нового адреÑа, нажмите, пожалуйÑта, +на линк: + +[[conflink]] + +ЕÑли Ð’Ñ‹ не региÑтрировали у Ð½Ð°Ñ Ðµ-мÑйл, +Ñто Ñделал от Вашего лица кто-то, имеющий +доÑтуп к аккаунту [[username]]. + +С уважением, +Команда [[sitename]] +[[sitelink]] + +. + +/editinfo.bml.newemail.subject=ÐÐ´Ñ€ÐµÑ e-mail изменен. + +/editinfo.bml.numcomments.about=Отметьте Ñтот флаг, еÑли хотите, чтобы к URL-адреÑам добавлÑлоÑÑŒ чиÑло оÑтавленных комментариев. Ð’ Ñтом Ñлучае, еÑли чиÑло комментариев изменилоÑÑŒ Ñ Ñ‚ÐµÑ… пор, как вы поÑледний раз заходили на Ñтраницу, браузер, возможно, покажет ÑÑылку другим цветом. + +/editinfo.bml.numcomments.header=ДобавлÑÑ‚ÑŒ &nc=xx к URL-адреÑам Ñтраниц Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñми + +/editinfo.bml.optional=необÑзательно + +/editinfo.bml.opt_in.about<< +Отметьте Ñтот флаг, еÑли хотите вÑегда узнавать о поÑвлении на [sitename] новых возможноÑтей. +Эти пиÑьма будут приходить довольно редко -- хорошо еÑли раз в год. Ваш Ð°Ð´Ñ€ÐµÑ Ð½Ðµ будет виден другим пользователÑм, и вы вÑегда можете отключить Ñту возможноÑÑ‚ÑŒ. +. + +/editinfo.bml.opt_in.header=ПриÑылать мне новоÑти [[sitename]] + +/editinfo.bml.persinfo.disclaimer<< +Будьте добры, заполните небольшую анкету о Ñебе Ð´Ð»Ñ Ñбора ÑтатиÑтики. +Мы не ÑобираемÑÑ Ð¸Ñпользовать полученную информацию Ñ ÐºÐ°ÐºÐ¸Ð¼Ð¸-либо Ñомнительными целÑми, мы проÑто хотим знать, кто наши пользователи и откуда они. ПоÑтому, пожалуйÑта, не указывайте ложную информацию. ЕÑли вы ÑомневаетеÑÑŒ, прочтите наше положение о конфиденциальноÑти. +. + +/editinfo.bml.persinfo.header=Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/editinfo.bml.screen.all=Ð’Ñе + +/editinfo.bml.screen.anon=Ðнонимные + +/editinfo.bml.screen.header=Чьи ответы вы хотите Ñкрывать Ñразу? + +/editinfo.bml.screen.none=Ðичьи + +/editinfo.bml.screen.nonfriends=ÐапиÑанные не друзьÑми + +/editinfo.bml.screen.nonmembers=ÐапиÑанные не членами ÑообщеÑтва + +/editinfo.bml.security.header=Кто может видеть: + +/editinfo.bml.security.visibility.anybody=Ð’Ñе + +/editinfo.bml.security.visibility.everybody=Ð’Ñе + +/editinfo.bml.security.visibility.friends=Только Ð´Ñ€ÑƒÐ·ÑŒÑ + +/editinfo.bml.security.visibility.regusers=Только зарегиÑтрированные пользователи + +/editinfo.bml.settings.friendspage.title=Заголовок ленты друзей: + +/editinfo.bml.settings.friendspage.title.optional=ЕÑли хотите, введите заголовок Ð´Ð»Ñ Ñтраниц Ñвоей ленты друзей (без HTML) + +/editinfo.bml.settings.header=ÐаÑтройки дневника + +/editinfo.bml.settings.journal.subtitle=Подзаголовок дневника: + +/editinfo.bml.settings.journal.subtitle.optional=ЕÑли хотите, введите заголовок и подзаголовок Ñвоего дневника (без HTML) + +/editinfo.bml.settings.journal.title=Заголовок дневника: + +/editinfo.bml.settings.privacy.about=Далее Ñледуют наÑтройки и предпочтениÑ, Ñлужащие обеÑпечению вашей уединённоÑти и анонимноÑти. + +/editinfo.bml.settings.privacy.header=ÐаÑтройки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð´Ð¾Ñтупа + +/editinfo.bml.state.other=Или введите штат/провинцию/облаÑÑ‚ÑŒ другого гоÑударÑтва + +/editinfo.bml.state.title=Штат + +/editinfo.bml.state.us=Штаты СШР+ +/editinfo.bml.stylemine.about=ПоÑтавьте галочку, чтобы видеть Ñтраницы комментариев в Ñтиле вашего дневника при переходе по ÑÑылкам Ñ Ð²Ð°ÑˆÐµÐ¹ ленты друзей. + +/editinfo.bml.stylemine.header=Форматировать комментарии в Ñтиле вашего дневника? + +/editinfo.bml.success.header=ПолучилоÑÑŒ! + +/editinfo.bml.success.message=Ваша Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, наÑтройки дневника и Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±Ñ‹Ð»Ð¸ уÑпешно изменены. + +/editinfo.bml.switch.button=Выбрать + +/editinfo.bml.switch.header=Выбрать другой дневник + +/editinfo.bml.switch.workwith=С каким дневником работать: + +/editinfo.bml.title=Изменение личных наÑтроек + +/editinfo.bml.tm.details=подробнее + +/editinfo.bml.tm.phonenum=Полный номер телефона: + +/editinfo.bml.tm.sec.about=Разрешить другим пользователÑм отправление текÑтовых Ñообщений. + +/editinfo.bml.tm.sec.title=Кто может отправлÑÑ‚ÑŒ: + +/editinfo.bml.tm.servprov=ПоÑтавщик уÑлуг: + +/editinfo.bml.tm.title=ТекÑтовые ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ + +/editinfo.bml.translatemailto.about=По умолчанию, [[sitename]] поÑылает почту в кодировке KOI8-R (Ñто Ñтандарт, и работает без проблем практичеÑки на вÑех почтовых программах). ЕÑли хотите, можете изменить здеÑÑŒ кодировку отÑылаемых вам пиÑем, например на CP1251 (Windows) или UTF-8 (Юникод). Ðо мы очень не Ñоветуем делать Ñтого без нужды. + +/editinfo.bml.translatemailto.header=Перекодировать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте в: + +/editinfo.bml.unbanusers.about=Ð’Ñ‹ запретили комментировать ваши запиÑи нижеприведенным пользователÑм (заблокировали их). ПоÑтавьте флаги напротив имён тех пользователей, которых вы хотите разблокировать. + +/editinfo.bml.unbanusers.header=Разблокировать пользователей + +/editinfo.bml.userpic.about=Ðиже показана Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð°Ñ Ð²Ð°Ð¼Ð¸ картинка, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð²Ñюду на Ñайте Ñтоит Ñ€Ñдом Ñ Ð²Ð°ÑˆÐ¸Ð¼ именем: в вашем ÑобÑтвенном дневнике и в дневниках ваших друзей. + +/editinfo.bml.userpic.edit=Удалить Ñту картинку или загрузить новую можно здеÑÑŒ. + +/editinfo.bml.userpic.header=Ваша картинка + +/editinfo.bml.userpic.none=картинка не загружена + +/editinfo.bml.weblogscom.about=Включите, еÑли хотите, чтобы Ñайт Weblogs.com вноÑил ваш дневник в ÑпиÑок обновлений при добавлении новых общедоÑтупных запиÑей. + +/editinfo.bml.weblogscom.header=УведомлÑÑ‚ÑŒ Weblogs.com об изменениÑÑ… + +/editinfo.bml.webpagename.title=Ðазвание веб-Ñтраницы + +/editinfo.bml.webpageurl.title=ÐÐ´Ñ€ÐµÑ Ð²ÐµÐ±-Ñтраницы + +/editinfo.bml.whoreply.header=Кто может отвечать на ваши запиÑи? + +/editinfo.bml.zip.title=Почтовый Ð¸Ð½Ð´ÐµÐºÑ + +/editinfo.bml.zip.usonly=Ð¸Ð½Ð´ÐµÐºÑ Ð¸Ð· 5-ти цифр; только Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð¶Ð¸Ð²Ð°ÑŽÑ‰Ð¸Ñ… в СШР+ +/editjournal.bml.btn.proceed=Продолжить... + +/editjournal.bml.certainday=За определённый день: + +/editjournal.bml.desc=ПожалуйÑта, иÑпользуйте форму внизу Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° запиÑи, которую вы хотите редактировать. + +/editjournal.bml.in=Ð’ ÑообщеÑтве + +/editjournal.bml.recententries=Ñамые новые запиÑи + +/editjournal.bml.recententry=Ð¡Ð°Ð¼Ð°Ñ Ð½Ð¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ + +/editjournal.bml.success.delete=ЗапиÑÑŒ удалена. + +/editjournal.bml.success.deletespam=Кроме того, она помечена как Ñпам, о чем Ñообщено по инÑтанциÑм. СпаÑибо! + +/editjournal.bml.success.head=Success + +/editjournal.bml.title=Редактировать запиÑи + +/editjournal.bml.viewwhat=Какие запиÑи: + +/editjournal_do.bml.body=Отредактируйте то, что хотите, поÑле чего нажмите на кнопку "Сохранить" внизу Ñтраницы, или нажмите на кнопку "Удалить", чтобы удалить запиÑÑŒ. + +/editjournal_do.bml.btn.delete=Удалить запиÑÑŒ из дневника + +/editjournal_do.bml.btn.edit=Редактировать выбранную запиÑÑŒ + +/editjournal_do.bml.btn.preview=Предварительный проÑмотр запиÑи + +/editjournal_do.bml.btn.save=Сохранить запиÑÑŒ + +/editjournal_do.bml.continue.head=Ðажмите Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶ÐµÐ½Ð¸Ñ... + +/editjournal_do.bml.continue.text=ПоÑле того, как вы выберете запиÑÑŒ Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ удалениÑ, нажмите кнопку "Редактировать выбранную запиÑÑŒ". + +/editjournal_do.bml.currmood=ÐаÑтроение: + +/editjournal_do.bml.currmusic=Музыка: + +/editjournal_do.bml.date=Дата + +/editjournal_do.bml.default=по умолчанию + +/editjournal_do.bml.delete.confirm=Ð’Ñ‹ дейÑтвительно хотите удалить Ñту запиÑÑŒ? + +/editjournal_do.bml.edit.text=Перед вами запиÑÑŒ, которую вы выбрали Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. Отредактируйте запиÑÑŒ по Ñвоему уÑмотрению и нажмите кнопку "Сохранить запиÑÑŒ" внизу Ñтраницы.

    Ð”Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи проÑто удалите веÑÑŒ текÑÑ‚ и нажмите "Сохранить запиÑÑŒ". ЗапиÑÑŒ будет удалена. + +/editjournal_do.bml.error.getting=Ошибка при выборе запиÑей Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ: + +/editjournal_do.bml.error.modify=Ошибка при редактировании дневника: + +/editjournal_do.bml.error.nofind=Ðевозможно найти выбранную запиÑÑŒ в дневнике. + +/editjournal_do.bml.event=Событие: + +/editjournal_do.bml.localtime=МеÑтное времÑ: + +/editjournal_do.bml.noneother=Ðи одно из Ñтих, или другое: + +/editjournal_do.bml.opt.backdate=ЗапиÑÑŒ задним чиÑлом: + +/editjournal_do.bml.opt.backdate.about=Ðе будет поÑвлÑÑ‚ÑŒÑÑ Ð² лентах друзей + +/editjournal_do.bml.opt.nocomments=Запретить комментировать запиÑÑŒ: + +/editjournal_do.bml.opt.noemail=Ðе отправлÑÑ‚ÑŒ комментарии по e-mail: + +/editjournal_do.bml.opt.noformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/editjournal_do.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/editjournal_do.bml.other=Другое: + +/editjournal_do.bml.pickentry.head=Выберите запиÑÑŒ Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. + +/editjournal_do.bml.pickentry.text=Выберите запиÑÑŒ, которую Ð’Ñ‹ хотите отредактировать и нажмите кнопку "Редактировать выбранную запиÑÑŒ" внизу Ñтраницы. + +/editjournal_do.bml.picture=Ваша картинка: + +/editjournal_do.bml.preview.header=Предварительный проÑмотр запиÑи + +/editjournal_do.bml.preview.text=Это внешний вид вашей будущей запиÑи в дневнике. ИÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ„Ð¾Ñ€Ð¼Ñƒ внизу, вы можете редактировать запиÑÑŒ или поÑлать ее в нынешнем виде. + +/editjournal_do.bml.save.head=Ðажмите, чтобы Ñохранить... + +/editjournal_do.bml.save.text=ПоÑле того, как вы закончите редактировать ваши запиÑи, нажмите кнопку "Сохранить". + +/editjournal_do.bml.spellchecked=Ваша Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ: + +/editjournal_do.bml.subject=Тема: (не обÑзательно) + +/editjournal_do.bml.success.delete=ЗапиÑÑŒ в дневнике удалена. + +/editjournal_do.bml.success.deletespam=Кроме того, она помечена как Ñпам, о чем Ñообщено по инÑтанциÑм. СпаÑибо! + +/editjournal_do.bml.success.head=ЗапиÑÑŒ уÑпешно отредактирована. + +/editjournal_do.bml.timeformat=Ð’Ñ€ÐµÐ¼Ñ Ð² 24-чаÑовом формате + +/editjournal_do.bml.title=Редактировать запиÑи дневника + +/editpics.bml.btn.proceed=Продолжить + +/editpics.bml.btn.save=Сохранить наÑтройки + +/editpics.bml.curpics=ИмеющиеÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ + +/editpics.bml.curpics.desc=ЗдеÑÑŒ показаны загруженные ранее картинки. Ð’Ñ‹ можете указать, какую из них иÑпользовать по умолчанию, удалить ненужные или назначить картинкам названиÑ, чтобы потом указывать, ÐºÐ°ÐºÐ°Ñ Ð½ÑƒÐ¶Ð½Ð°. Чтобы загрузить новую картинку, иÑпользуйте форму внизу Ñтраницы. + +/editpics.bml.error.badurl=КажетÑÑ, Ð°Ð´Ñ€ÐµÑ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ указан неправильно. Он должен начинатьÑÑ Ñ http:// + +/editpics.bml.error.filetoolarge=Слишом большой файл изображениÑ. МакÑимальный размер файла -- [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Размер Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ([[imagesize]]) Ñлишком большой, он не может быть больше 100x100 точек. Ð’Ñ‹ можете уменьшить изображение в графичеÑком редакторе. + +/editpics.bml.error.invalidimage=Ðеверный файл изображениÑ. + +/editpics.bml.error.keywords=Ð’Ñ‹ иÑпользовали название "[[ekw]]" Ð´Ð»Ñ Ð½ÐµÑкольких картинок Ñразу, и оно было назначено одной картинке, Ñлучайно выбранной из них. ВероÑтно, Ñто не та, которую вы имели в виду, поÑтому можете вернутьÑÑ Ð¸ иÑправить названиÑ. + +/editpics.bml.error.toomanypics2=МакÑимально разрешённое вам чиÑло картинок ([[maxpics]]) уже загружено. Чтобы загрузить новую картинку, Удалите одну из Ñтарых. + +/editpics.bml.error.toomanypics3=У Ð²Ð°Ñ Ñ…Ñ€Ð°Ð½Ð¸Ñ‚ÑÑ Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ðµ вам количеÑтво картинок - [[max]] [[?max|picture|pictures]]. Ð’Ñ‹ не Ñможете загрузить дополнительные картинки, пока не удалите одну или неÑколько из имеющихÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½Ð¾Ðº. + +/editpics.bml.error.unsupportedtype=Файлы типа [[filetype]] не поддерживаютÑÑ. Ð’Ñ‹ можете загрузить файлы только Ñледующих типов: GIF, PNG или JPG. Преобразовать файл в одним из Ñтих типов можно практичеÑки в любом графичеÑком редакторе. + +/editpics.bml.error.urlerror=При загрузке Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка. + +/editpics.bml.fromfile=Из файла + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=Ñ„ + +/editpics.bml.fromurl=Из Сети: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=Ñ + +/editpics.bml.kilobytes= килобайт + +/editpics.bml.label.default=По умолчанию: + +/editpics.bml.label.delete=Удалить: + +/editpics.bml.label.keywords=Ключевые Ñлова: + +/editpics.bml.makedefault=Сделать картинкой по умолчанию + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=у + +/editpics.bml.nodefault=Ðе назначать картинку по умолчанию + +/editpics.bml.noneupload=Ð’Ñ‹ не загрузили ни одной картинки. Ð’Ñ‹ можете загрузить их Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ приведённой ниже формы. + +/editpics.bml.nopics=Картинок нет + +/editpics.bml.piclimitstatus=Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñƒ Ð²Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð¾ [[current]] из положенных [[max]]. + +/editpics.bml.restriction.fileformat=Файл должен быть формата PNG, GIF или JPG + +/editpics.bml.restriction.filesize=Размер файла должен быть меньше 40 килобайт + +/editpics.bml.restriction.imagesize=Размеры Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ быть не более 100x100 точек + +/editpics.bml.restriction.keywords=ЕÑли не придумать Ð´Ð»Ñ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ название, иÑпользовать ее не удаÑÑ‚ÑÑ + +/editpics.bml.restriction.keywords.faq=ЕÑли не придуматьназваниÑ, картинки иÑпользовать не удаÑÑ‚ÑÑ + +/editpics.bml.title=Редактировать картинки + +/editpics.bml.uploaddesc=ИÑпользуйте форму внизу Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ новой картинки + +/editpics.bml.uploaddesc.fb=Загрузить в качеÑтве новой картинки уменьшенную копию большого файла, который лежит на вашем Ñайте [[sitename]]. + +/editpics.bml.uploadheader=Загрузить новую картинку + +/edittags.bml.button.save=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/edittags.bml.current=Текущие метки: + +/edittags.bml.disabled=Извините -- ÑиÑтема меток в наÑтоÑщий момент не работает + +/edittags.bml.entry=ЗапиÑÑŒ: + +/edittags.bml.error.db=Извините -- в нашей базе данных произошел Ñбой. ПожалуйÑта, попробуйте еще раз. + +/edittags.bml.intro=Чтобы редактировать метки Ð´Ð»Ñ Ñтой запиÑи, изпользуйте форму внизу. + +/edittags.bml.invalid.entry=Указанной запиÑи нет. + +/edittags.bml.invalid.journal=Указанного дневника нет. + +/edittags.bml.invalid.link=Ð’Ñ‹ попали на Ñту Ñтраницу каким-то не тем путем. ПожалуйÑта, уйдите, и приходите по ÑÑылке "редактировать метки". + +/edittags.bml.invalid.notauthorized=Вам не разрешено читать Ñту запиÑÑŒ. + +/edittags.bml.permissions.add.yes=Можно добавить метки из вышепреведенного ÑпиÑка. + +/edittags.bml.permissions.control.yes=Метки можно удалÑÑ‚ÑŒ, или Ñоздавать новые. + +/edittags.bml.permissions.none=(Редактировать метки Ð´Ð»Ñ Ñтой запиÑи вам не разрешено.) + +/edittags.bml.subject=Тема: + +/edittags.bml.title=Редактировать метки Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи + +/edittags.bml.users=Метки, введенные пользователем: + +/edittags.bml.view=Читать Ñту запиÑÑŒ. + +/export.bml.btn.proceed=Продолжить... + +/export.bml.description=ЗдеÑÑŒ вы можете Ñохранить резервную копию Ñвоего дневника в выбранном формате. Подробную информацию о резервном копировании Ñвоего дневника, читайте в Справке. + +/export.bml.fields=ПолÑ: + +/export.bml.format.csv=CSV (Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· запÑтую) + +/export.bml.format.xml=XML + +/export.bml.label.encoding=Кодировка: + +/export.bml.label.field.allowmask=МаÑка прав доÑтупа + +/export.bml.label.field.currents=ÐаÑтроение и музыка + +/export.bml.label.field.event=Событие + +/export.bml.label.field.eventtime=Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи (по чаÑам пользователÑ) + +/export.bml.label.field.itemid=Ðомер ID + +/export.bml.label.field.logtime=Ð’Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ³Ð¸Ñтрации (по чаÑам ÑиÑтемы) + +/export.bml.label.field.security=Уровень безопаÑноÑти + +/export.bml.label.field.subject=Тема + +/export.bml.label.format=Форматирование: + +/export.bml.label.header=Заголовок + +/export.bml.label.month=МеÑÑц: + +/export.bml.label.month.month=мм: + +/export.bml.label.month.year=гггг: + +/export.bml.label.notranslation=Ðе изменÑÑ‚ÑŒ кодировку + +/export.bml.label.what=Что ÑкÑпортировать: + +/export.bml.title=ЭкÑпортировать веÑÑŒ дневник + +/export.bml.what.entries=ЗапиÑи в дневнике + +/export_do.bml.error.encoding= Выбрана Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ° + +/friends/add.bml.add.header=УÑпешно + +/friends/add.bml.add.text=Пользователь [[user]] был добавлен в ваш ÑпиÑок друзей. Свою ленту друзей вы можете поÑмотреть здеÑÑŒ. + +/friends/add.bml.add.title=Друг добавлен! + +/friends/add.bml.btn.add=Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] + +/friends/add.bml.btn.modify=Изменить + +/friends/add.bml.btn.remove=Удалить + +/friends/add.bml.colors.bg=Цвет фона + +/friends/add.bml.colors.fg=Цвет букв + +/friends/add.bml.colors.header=Цвета + +/friends/add.bml.colors.hover=(Подведите курÑор к цвету, чтобы увидеть его название во вÑплывающей подÑказке) + +/friends/add.bml.colors.text=Ð’Ñ‹ можете также выбрать цвета, которыми пользователь [[user]] будет предÑтавлен в вашей ленте друзей. + +/friends/add.bml.confirm.header=Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок друзей? + +/friends/add.bml.confirm.syn.header=Добавить транÑлируемую ленту [[user]] в ÑпиÑок друзей? + +/friends/add.bml.confirm.syn.title=Добавить транÑлируемую ленту + +/friends/add.bml.confirm.text=Чтобы добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок друзей, нажмите кнопку: + +/friends/add.bml.confirm.title=Добавить друга + +/friends/add.bml.error1.header=Сперва войдите в ÑиÑтему + +/friends/add.bml.error1.text=Прежде чем добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² Ñвой ÑпиÑок друзей, вы должны войти в ÑиÑтему под Ñвоим именем Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ паролем. ЕÑли у Ð²Ð°Ñ ÐµÑ‰Ñ‘ нет дневника, то вы можете Ñоздать его, чтобы читать чужие запиÑи в Ñвоей ленте друзей. + +/friends/add.bml.error1.title=Добавить друга + +/friends/add.bml.error2.text=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾Ñ‚ÑутÑтвует или было введено неправильно. Добавить друга вы можете на Ñтранице Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑпиÑка друзей. + +/friends/add.bml.error3.text=Пользователь [[user]] уже добавлен в ваш ÑпиÑок друзей. Ðо вы можете изменить цвета, которыми отображаетÑÑ ÐµÐ³Ð¾ Ð¸Ð¼Ñ Ð² вашей ленте друзей (а также ÑпиÑок групп, в которые он входит). + +/friends/add.bml.error3.title=ВнеÑти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/add.bml.groups.header=Группы друзей + +/friends/add.bml.groups.nogroup=Группы друзей не заданы. + +/friends/add.bml.groups.text=Ð’ какие группы друзей вы хотите добавить Ñтого пользователÑ? Группы друзей иÑпользуютÑÑ Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ Ñообщений в ленте друзей, а также Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ выÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð°Ð² проÑмотра дневниковых запиÑей. + +/friends/add.bml.remove.header=УÑпешно + +/friends/add.bml.remove.text=Пользователь был удалён из ÑпиÑка ваших друзей. Свою ленту друзей вы можете поÑмотреть здеÑÑŒ. + +/friends/add.bml.remove.title=Удален! + +/friends/edit.bml.title=Редактировать ÑпиÑок друзей + +/friends/editgroups.bml.btn.ge.del=Удалить + +/friends/editgroups.bml.btn.ge.new=Создать + +/friends/editgroups.bml.btn.ge.ren=Переименовать + +/friends/editgroups.bml.btn.gs.private=ÐŸÑ€Ð¸Ð²Ð°Ñ‚Ð½Ð°Ñ + +/friends/editgroups.bml.btn.gs.public=ОбщедоÑÑ‚ÑƒÐ¿Ð½Ð°Ñ + +/friends/editgroups.bml.btn.mv.down=Подвинуть вниз + +/friends/editgroups.bml.btn.mv.up=Подвинуть вверх + +/friends/editgroups.bml.confirm.delete=Ð’Ñ‹ уверены, что хотите удалить группу друзей? + +/friends/editgroups.bml.done.btn=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/editgroups.bml.done.header=Готово? + +/friends/editgroups.bml.done.text=Когда вÑе будет готово, Ñохраните изменениÑ, нажав раÑположенную ниже кнопку. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Ð’Ñ‹ доÑтигли предельного количеÑтва из 30 групп друзей. ЕÑли вы удалили одну или неÑколько групп, но не Ñохранили изменениÑ, Ñделайте Ñто ÑейчаÑ, вернитеÑÑŒ на Ñту Ñтраницу и перезагрузите её. ПоÑле Ñтого вы Ñможете Ñоздавать новые группы. + +/friends/editgroups.bml.error.text=Сервер вернул Ñообщение об ошибке: + +/friends/editgroups.bml.group.public=(общедоÑтупнаÑ) + +/friends/editgroups.bml.ingroup=ВходÑÑ‚ в группу: + +/friends/editgroups.bml.ingroup.not=Ðе входÑÑ‚ в группу: + +/friends/editgroups.bml.prompt.newname=Ðазвание новой группы: + +/friends/editgroups.bml.prompt.rename=Переименовать Ñту группу в: + +/friends/editgroups.bml.saved.header=Сохранено + +/friends/editgroups.bml.saved.text=Ваши группы друзей уÑпешно Ñохранены. + +/friends/editgroups.bml.text<< +Ðа Ñтой Ñтранице вы можете редактировать группы Ñвоих друзей. Группы друзей предназначены Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа к запиÑÑм, а также Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð»ÐµÐ½Ñ‚Ñ‹ друзей. Это подробно опиÑано в вопроÑе "Что такое наÑтраиваемые группы друзей? Как ими пользоватьÑÑ?". + +К Ñожалению, Ð´Ð»Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð¾Ð¹ работы Ñтой Ñтраницы у Ð²Ð°Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть включен JavaScript. +. + +/friends/editgroups.bml.text.sec=Обратите внимание: ЕÑли вы хотите удалить группу и Ñделать новую, не делайте Ñтого поÑредÑтвом Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ ÑущеÑтвующей и удалениÑ/Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² неё пользователей. ЕÑли вы поÑтупите подобным образом, то вÑе запиÑи, доÑтупные "Ñтарой" группе, будут также доÑтупны и "новой". + +/friends/editgroups.bml.title=Редактирование групп друзей + +/friends/editgroups.bml.yourgroups=Ваши группы друзей: + +/friends/edit_do.bml.addfriends.head=Добавить друзей + +/friends/edit_do.bml.addfriends.text=Введите имена пользователей ваших друзей по [[sitename]] в Ð¿Ð¾Ð»Ñ Ð²Ð²Ð¾Ð´Ð°, раÑположенные ниже, поÑле чего выберите, какие цвета будут аÑÑоциированны Ñ Ð½Ð¸Ð¼Ð¸... + +/friends/edit_do.bml.background=Фон + +/friends/edit_do.bml.bgcolor=Цвет фона: + +/friends/edit_do.bml.btn.close=Закрыть + +/friends/edit_do.bml.btn.save=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/edit_do.bml.btn.toggle=Открыть окно проÑмотра + +/friends/edit_do.bml.done.head=Ð’ÑÑ‘? + +/friends/edit_do.bml.done.text=Когда закончите, нажмите на кнопку "Сохранить изменениÑ", раÑположенную ниже... + +/friends/edit_do.bml.error.updating=Во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑпиÑка друзей произошла ошибка: + +/friends/edit_do.bml.fellowfriends.head=Ð’ друзьÑÑ… + +/friends/edit_do.bml.fellowfriends.text<< +Эти люди занеÑли Ð²Ð°Ñ Ð² Ñвои ÑпиÑки друзей. ЕÑли хотите, вы тоже можете добавить их в Ñвой ÑпиÑок. Ð”Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð° только Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ удобÑтва, чтобы вы тоже знали их имена; вам не обÑзательно добавлÑÑ‚ÑŒ их! + +. + +/friends/edit_do.bml.foreground=Передний план + +/friends/edit_do.bml.friend=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/friends/edit_do.bml.hover=Чтобы узнать название нужного цвета, наведите на него курÑор мыши. + +/friends/edit_do.bml.mrcolor=ПроÑмотрщик Цветов + +/friends/edit_do.bml.name=Ð˜Ð¼Ñ + +/friends/edit_do.bml.needmore=ЕÑли здеÑÑŒ не хватает Ñтрочек Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы добавить вÑех друзей, которых вы хотите, проÑто Ñохраните Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ вернитеÑÑŒ на Ñту Ñтраницу Ñнова. + +/friends/edit_do.bml.nofriends.head=Ðет друзей? + +/friends/edit_do.bml.nofriends.text=Увы, у Ð²Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½Ðµ задано ни одного друга. ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° Ñто, мы уверены, что у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ неÑколько друзей :) ЕÑли хотите, введите здеÑÑŒ имена их дневников...а нет, так нет. + +/friends/edit_do.bml.opt.addtolist=Добавить в Ð´Ñ€ÑƒÐ·ÑŒÑ + +/friends/edit_do.bml.opt.delete=Удалить? + +/friends/edit_do.bml.success.head=ИÑполнено + +/friends/edit_do.bml.success.text=Ваш ÑпиÑок друзей изменён. Ð’Ñ‹ можете увидеть обновлённую ленту друзей здеÑÑŒ. + +/friends/edit_do.bml.textcolor=Цвет текÑта: + +/friends/edit_do.bml.title=Изменить ÑпиÑок друзей + +/friends/edit_do.bml.user=Пользователь + +/friends/edit_do.bml.viewer=ПроÑмотрщик цветов + +/friends/edit_do.bml.yourfriends.head=Ваши Ð´Ñ€ÑƒÐ·ÑŒÑ + +/friends/edit_do.bml.yourfriends.text=Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñƒ Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ñледующие друзьÑ: + +/friends/filter.bml.editgroups=ЕÑли вы хотите отредактировать ÑпиÑок групп ваших друзей [[link]] + +/friends/filter.bml.error.nogroups=Ð’Ñ‹ не можете фильтровать ÑпиÑок друзей, поÑкольку Ñначала вам надо завеÑти группы друзей. + +/friends/filter.bml.error.nogroups.header=Группы не указаны + +/friends/filter.bml.reset=ОчиÑтить + +/friends/filter.bml.select=Отметьте группу(-Ñ‹) друзей, которую вы хотите видеть в Ñвоей ленте друзей. + +/friends/filter.bml.select.header=Выбрать группы + +/friends/filter.bml.submit=Показать! + +/friends/filter.bml.title=Фильтр Друзей + +/friends/index.bml.about=Ðа Ñтой Ñтранице вы можете управлÑÑ‚ÑŒ Ñвоим "ÑпиÑком друзей". Добавив других пользователей к Ñтому ÑпиÑку, вы Ñможете Ñледить за обновлениÑми в их дневниках через Ñвою ленту друзей. ДрузьÑми могут быть не только индивидуальные пользователи: добавлÑÑ‚ÑŒ можно и ÑообщеÑтва, и транÑлируемые дневники. + +/friends/index.bml.edit.about=Добавление, изменение или удаление пользователей из вашего ÑпиÑка друзей, а также изменение цветовых ÑоответÑтвий друзей. + +/friends/index.bml.editgroups.about=Создание, изменение или удаление групп друзей. + +/friends/index.bml.filter=Группы друзей можно иÑпользовать Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ ÑпиÑка друзей: Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра можно выбирать отдельную группу. Также их можно иÑпользовать Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупом к запиÑÑм (Ñм. ниже). + +/friends/index.bml.filter.about=Фильтровать ÑпиÑок друзей по заданным группам. + +/friends/index.bml.groups=Кроме того, можно задавать группы друзей. + +/friends/index.bml.security=Ваш ÑпиÑок друзей также иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¼ доÑтупом. Ð’Ñ‹ можете подробнее узнать про ограничение доÑтупа через ÑпиÑкок друзей, тут: Ð”Ñ€ÑƒÐ·ÑŒÑ Ð¸ Уровни ДоÑтупа. + +/friends/index.bml.security.custom=При Ñоздании запиÑи, вы можете выбрать группу друзей, которые Ñмогут прочитать Ñту запиÑÑŒ. Ðо не вÑе программы-клиенты поддерживают наÑтройку групп друзей. + +/friends/index.bml.security.header=БезопаÑноÑÑ‚ÑŒ + +/friends/index.bml.security.only=ЗапиÑи "Только Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹" будут видны вÑем вашим друзьÑм. + +/friends/index.bml.title=ÐаÑтройка ÑпиÑка друзей + +/friends/index.bml.tools=ИнÑтрументы + +/friends/popwithfriends.bml.account_type=Извините, но ваш тип аккаунта не позволÑет иÑпользовать Ñтот ÑервиÑ. + +/friends/popwithfriends.bml.count=Сколько? + +/friends/popwithfriends.bml.exclude_own=Ð’Ñ‹ можете также иÑключить Ñвоих друзей из ÑпиÑка. + +/friends/popwithfriends.bml.include_own=Ð’Ñ‹ можете также включить Ñвоих друзей в ÑпиÑок. + +/friends/popwithfriends.bml.intro=Эти пользователи добавлены многими вашими друзьÑми, но не добавлены вами. + +/friends/popwithfriends.bml.intro_own=Эти пользователи добавлены многими вашими друзьÑми. СпиÑок также включает тех, кого добавили и вы. + +/friends/popwithfriends.bml.no_users=Ðет пользователей + +/friends/popwithfriends.bml.title=ПопулÑрные Ñреди ваших друзей пользователи + +/friends/popwithfriends.bml.user=Пользователь + +/go.bml.defaultbody=Ðе заданы параметры + +/go.bml.defaulttitle=Ошибка. + +/go.bml.error.noentry.next=Это поÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ, поÑле нее запиÑей нет. + +/go.bml.error.noentry.prev=Это Ð¿ÐµÑ€Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ, до нее запиÑей нет + +/go.bml.error.noentrytitle=ЗапиÑÑŒ отÑуÑÑ‚Ñтвует + +/go.bml.error.redirkey=Ðеправильный redir_key. + +/go.bml.error.usernotfound=Пользователь не найден + +/index.bml.about.header=О проекте + +/index.bml.about.joining<< +Это беÑплатный Ñайт. Пользователи могут Ñтать платными пользователÑми Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… возможноÑтей. + +. + +/index.bml.about.us=Livejournal - Ñто проÑÑ‚Ð°Ñ Ð² обращении (но очень Ð¼Ð¾Ñ‰Ð½Ð°Ñ Ð¸ легко Ð°Ð´Ð°Ð¿Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ð°Ñ Ðº вашим потребноÑÑ‚Ñм) программа Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸ ваших текÑтов в интернете (блогинга), оÑÐ½Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° открытом иÑходном коде. Она напиÑана БрÑдом Фицпатриком и впервые иÑпользована на Ñайте http://www.livejournal.com. Ðаш Ñервер иÑпользует ту же программу (только улучшенную). + +/index.bml.boldcreate=Создать Ñвой дневник на [[sitename]]! + +/index.bml.learnmore.header=Хотите узнать больше? + +/index.bml.learnmore.text=ПожалуйÑта, прочитайте опиÑание возможноÑтей [[sitename]] . УбедилиÑÑŒ? Создайте ваш личный дневник! + +/index.bml.meta.desc=[[sitename]] -- Ñто меÑто, где вы можете поделитьÑÑ Ñвоими ценными мыÑлÑми Ñо вÑем миром (хочет он того, или нет). + +/index.bml.meta.keywords=дневник, дневник, онлайн-дневник, дневники, пиÑательÑтво, онлайн-дневники, веб-дневник + +/index.bml.news.text=ПоÑледние новоÑти [[sitename]]: + +/index.bml.news.title=ПоÑледние новоÑти + +/index.bml.post=Ð–Ð¸Ð²Ð°Ñ ÑтатиÑтика + +/index.bml.post.hour=За чаÑ: + +/index.bml.post.latest=Свежие запиÑи + +/index.bml.post.min=За минуту: + +/interests.bml.add.added.head=Добавлено! + +/interests.bml.add.added.text=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ Ð±Ñ‹Ð» добавлен к ÑпиÑку ваших интереÑов. + +/interests.bml.add.btn.text=Добавить [[interest]] + +/interests.bml.add.confirm.head=Подтверждение + +/interests.bml.add.confirm.text=Чтобы добавить [[interest]] к ÑпиÑку интереÑов, нажмите на кнопку ниже. + +/interests.bml.add.toomany.head=Извините... + +/interests.bml.add.toomany.text=У Ð²Ð°Ñ ÑƒÐ¶Ðµ определено макÑимальное количеÑтво ([[maxinterests]]) интереÑов. + +/interests.bml.addint=ЕÑли вам Ñто тоже интереÑно, и вы хотите добавить его в Ñвой ÑпиÑок, нажмите тут. + +/interests.bml.btn.switch=Выбрать + +/interests.bml.communities.head=ЗаинтереÑованные ÑообщеÑтва + +/interests.bml.communities.text=Следующие ÑообщеÑтва также заинтереÑованы в "[[interest]]". + +/interests.bml.count=Кол-во + +/interests.bml.enmasse.body.other=Ðиже показаны интереÑÑ‹ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. Пометьте галочками те интереÑÑ‹, которые вы хотите добавить к ÑобÑтвенным, и уберите галочки у тех, которые вы хотите удалить из Ñвоих интереÑов. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.body.other_authas=Ðиже показаны интереÑÑ‹ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. Пометьте галочками те интереÑÑ‹, которые вы хотите добавить к интереÑам [[target]], и уберите галочки у тех, которые вы хотите удалить. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.body.you=Уберите галочки у тех интереÑов, которые вы хотите удалить. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.btn=Показать ÑпиÑок + +/interests.bml.enmasse.header=Добавление/удаление интереÑов + +/interests.bml.enmasse.intro=Изменить ÑпиÑок Ñвоих интереÑов, взÑв за оÑнову интереÑÑ‹ пользователÑ: + +/interests.bml.error.add.mustlogin=Ð’Ñ‹ должны войти в ÑиÑтему, чтобы добавить интереÑ. + +/interests.bml.error.enmasse.mustlogin=Чтобы воÑпользоватьÑÑ Ñтой возможноÑтью, вы должны войти в ÑиÑтему. + +/interests.bml.error.enmasse.noaccess=У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к дневнику [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ðµ был найден. + +/interests.bml.error.nointerests=Либо Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½ÐµÑ‚, либо ему не интереÑно вообще ничего. + +/interests.bml.findsim.searchwait=Обратите внимание: ПоиÑк займет неÑколько Ñекунд. Потерпите. + +/interests.bml.findsim_do.account.notallowed=Извините, ваш тип аккаунта не позволÑет иÑпользовать Ñту возможноÑÑ‚ÑŒ. + +/interests.bml.findsim_do.magic=Волшебное
    чиÑло + +/interests.bml.findsim_do.magic.head=Что такое Волшебное чиÑло? + +/interests.bml.findsim_do.magic.text=Ð”Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пользователÑ, Ñравниваемого Ñ Ð²Ð°Ð¼Ð¸, вычиÑлÑетÑÑ Ð²Ð¾Ð»ÑˆÐµÐ±Ð½Ð¾Ðµ чиÑло, на которое ÑоÑтоит из двух чаÑтей: проÑтого чиÑла Ñовпадений интереÑов и некоторых дополнительных очков за Ñовпадение редких интереÑов. + +/interests.bml.findsim_do.nomatch.head=Ðичего не найдено + +/interests.bml.findsim_do.nomatch.text=Ðет пользователей, Ñходных Ñ [[user]]. + +/interests.bml.findsim_do.notdefined=Пользователь [[user]] не указал Ñвои интереÑÑ‹. + +/interests.bml.findsim_do.similar.head=Сходные пользователи + +/interests.bml.findsim_do.similar.text=Ðиже Ñледуют наиболее Ñходные Ñ [[user]] пользователи + +/interests.bml.finished.about=Когда закончите, нажмите ниже кнопку "Сохранить изменениÑ": + +/interests.bml.finished.header=Готово? + +/interests.bml.finished.save_button=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/interests.bml.interest=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +/interests.bml.interested.btn.find=ПоиÑк + +/interests.bml.interested.in=Ðайти людей и ÑообщеÑтва, заинтереÑованных в: + +/interests.bml.interests.findsim=Ðайти пользователей Ñ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑами, похожими на интереÑÑ‹ пользователÑ: + +/interests.bml.interests.head=ИнтереÑÑ‹ + +/interests.bml.interests.text=Вот какие забавные вещи можно Ñделать Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ интереÑами. + +/interests.bml.interests.viewpop=ПроÑмотреть популÑрные интереÑÑ‹ + +/interests.bml.login.enterinfo=Чтобы изменить Ñвои интереÑÑ‹, введите Ð¸Ð¼Ñ Ð¸ пароль. + +/interests.bml.login.proceed=Продолжить... + +/interests.bml.match=[[count]] Ñовпадение: + +/interests.bml.matches=[[count]] Ñовпадений: + +/interests.bml.morestuff=Другие интереÑные возможноÑти -- на Ñтранице интереÑов. + +/interests.bml.nointerests.text=Ðе указали ни одного интереÑа? Ð’Ñ‹ можете добавить Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° Ñтранице Личной информации. + +/interests.bml.popular.disabled=Извините, возможноÑÑ‚ÑŒ Ñмотреть популÑрные интереÑÑ‹ отключена. + +/interests.bml.popular.head=ПопулÑрные интереÑÑ‹ + +/interests.bml.popular.text=Ðиже указаны наиболее популÑрные интереÑÑ‹. + +/interests.bml.results.added=Выбранные интереÑÑ‹ были добавлены к ÑпиÑку ваших интереÑов. + +/interests.bml.results.both=Выбранные вами интереÑÑ‹ были добавлены в ваш ÑпиÑок, а отменённые были удалены. + +/interests.bml.results.deleted=Отменённые вами интереÑÑ‹ были удалены из вашего ÑпиÑка. + +/interests.bml.results.del_and_toomany=ИнтереÑÑ‹, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… вы ÑнÑли отметку, были удалены из вашего ÑпиÑка. Тем не менее, вы хотите добавить Ñлишком много интереÑов. Общее количеÑтво ваших интереÑов не может превышать [[intcount]]. Ðи один из выбранных интереÑов не был добавлен к вашему ÑпиÑку. Попробуйте вернутьÑÑ Ð½Ð°Ð·Ð°Ð´ и попытатьÑÑ Ñнова, выбрав меньшее чиÑло интереÑов Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ. + +/interests.bml.results.goback=Ð’Ñ‹ можете вернутьÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾ к Ñтранице информации о пользователе [[user]], Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ вы пришли. + +/interests.bml.results.header=Результаты + +/interests.bml.results.message=ПоÑмотреть обновлённую Ñтраницу Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹. + +/interests.bml.results.nothing=Ð’Ñ‹ ничего не изменили. + +/interests.bml.results.toomany=Ð’Ñ‹ хотите добавить Ñлишком много интереÑов. Общее количеÑтво ваших интереÑов не может превышать [[intcount]]. Ðи один из выбранных интереÑов не был добавлен к вашему ÑпиÑку. Попробуйте вернутьÑÑ Ð½Ð°Ð·Ð°Ð´ и попытатьÑÑ Ñнова, выбрав меньшее чиÑло интереÑов. + +/interests.bml.title=ИнтереÑÑ‹ + +/interests.bml.toomany.body=[[intcount]] людей и/или ÑообщеÑтв заинтереÑованы в Ñтом. СпиÑок не будет показан. + +/interests.bml.toomany.head=Ðайдено Ñлишком много запиÑей + +/interests.bml.users.head=ЗаинтереÑованные пользователи + +/interests.bml.users.text=Следующие пользователи также заинтереÑованы в [[interest]]. + +/invite/index.bml.code=Код + +/invite/index.bml.error=Ошибка + +/invite/index.bml.genmore=Сгенерировать дополнительные коды + +/invite/index.bml.how_detail=ПриглаÑительные коды отменены, поÑтому их генерирование отключено. + +/invite/index.bml.how_header=Как Ñто уÑтроено? + +/invite/index.bml.invite_header=ПриглашениÑ? + +/invite/index.bml.none=Ðи одного + +/invite/index.bml.redeemed=ИÑпользован + +/invite/index.bml.title=ПриглаÑи друзей приÑоединитьÑÑ Ðº [[sitename]] + +/invite/index.bml.unused=ÐеиÑпользован + +/invite/index.bml.use=ИÑпользовать + +/invite/index.bml.why_codes=К Ñожалению, чтобы контролировать роÑÑ‚ [[sitename]] и не перегружать Ñервер, в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð°ÐºÐºÑƒÐ½Ñ‚Ð° вам нужно за него заплатить или получить приглаÑительный код от уже ÑущеÑтвующего пользователÑ. + +/legal/tos.bml.title=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг + +/login.bml.bindip.label=ПривÑзать к IP-адреÑу: + +/login.bml.bindip.no=Ðет (работает Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ провайдера) + +/login.bml.bindip.yes=Да (безопаÑнее) + +/login.bml.error.mustenterusername=Ð’Ñ‹ должны ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/login.bml.expire.btn.neverexpire=УÑтановите Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ ÐÐВСЕГДР+ +/login.bml.expire.btn.sessiononly=УÑтановите Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ ТОЛЬКО ÐРТЕКУЩИЙ СЕÐÐС + +/login.bml.expire.neverexpire.text=Срок дейÑÑ‚Ð²Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не иÑтечет, поÑтому еÑли вы пользуетеÑÑŒ публичным интернет-терминалом, выходите в интернет из школы, библиотеки или другого меÑта, где люди в Ñкором времени могут воÑпользоватьÑÑ Ñтим компьютером, убедитеÑÑŒ, что вы вышли из ÑиÑтемы поÑле Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹! Или же Ñмените Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ только на текущий ÑеанÑ, то еÑÑ‚ÑŒ до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°. + +/login.bml.expire.sessiononly.text=Ваша Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ дейÑтвовать до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°. ЕÑли Ñто ваш личный компьютер и вы единÑтвенный пользователь, то вы можете уÑтановить Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ навÑегда: + +/login.bml.links.head=СÑылки + +/login.bml.links.link1=Ваша лента друзей. + +/login.bml.links.link2=Ваш ÑпиÑок задач. + +/login.bml.links.text=Ð’ будущем, на Ñтой Ñтранице будут вÑевозможные ÑÑылки и Ð²Ð°Ð¶Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, но пока что тут вÑего неÑколько ÑÑылок, которые могут вам пригодитьÑÑ: + +/login.bml.loggedin.head=Ð’Ñ‹ вошли в ÑиÑтему! + +/login.bml.loggedin.text=Ð’Ñ‹ теперь в ÑиÑтеме, под Ñвоим пользовательÑким именем и паролем. + +/login.bml.login.btn.changeopts=Изменить наÑтройки + +/login.bml.login.btn.login=Вход в ÑиÑтему... + +/login.bml.login.expiration=Срок Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸: + +/login.bml.login.forget=Забыли? + +/login.bml.login.head=Вход + +/login.bml.login.never=Ðикогда + +/login.bml.login.otheropts=Другие опции: + +/login.bml.login.password=Пароль: + +/login.bml.login.text1=Чтобы войти в [[sitename]], введите ниже ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. Ðовые пользователи: Чтобы Ñоздать Ñвой дневник, нажмите Ñюда. + +/login.bml.login.text2=Ð’Ñ‹ также можете указать Ñрок Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ авторизации. По умолчанию Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´ÐµÐ¹Ñтвительна до момента Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°, что ÑвлÑетÑÑ Ð»ÑƒÑ‡ÑˆÐ¸Ð¼ вариантом Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… компьютеров. Однако, еÑли вы единÑтвенный пользователь компьютера, и больше никто не имеет к нему доÑтупа -- вы можете выбрать вариант беÑÑрочной авторизации. Подробнее об Ñтой и других наÑтройках можно прочитать в Ñтатье Ñправки "ÐаÑтройки при входе в ÑиÑтему". + +/login.bml.login.text3=[[username]], вы вошли в [[sitename]]. ПутешеÑтвие по Ñайту можно начать Ñ ÐµÐ³Ð¾ карты. + +/login.bml.login.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/login.bml.login.whenbrowsercloses=ПоÑле Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° + +/login.bml.logout.btn=Выйти + +/login.bml.title=Вход в ÑиÑтему + +/login.bml.whylogin.benefit1=Вам больше не нужно будет вводить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ/пароль вÑюду на Ñайте. + +/login.bml.whylogin.benefit2=Ð’Ñ‹ Ñможете проÑматривать "защищенные" запиÑи в дневниках ваших друзей, которые дали вам доÑтуп Ð´Ð»Ñ Ð¸Ñ… чтениÑ. + +/login.bml.whylogin.benefit3=ПоÑле входа в ÑиÑтему Вам Ñтанут видны и доÑтупны многие дополнительные функции. + +/login.bml.whylogin.head=Зачем входить в ÑиÑтему? + +/login.bml.whylogin.text=Вот неÑколько оÑновных преимущеÑтв входа в ÑиÑтему: + +/logout.bml.already.head=Ð’Ñ‹ уже вышли из ÑиÑтемы + +/logout.bml.already.text=Ð’Ñ‹ уже вышли из ÑиÑтемы + +/logout.bml.killall.btn=Завершить вÑе ÑеанÑÑ‹ + +/logout.bml.killall.head=Другие ÑеанÑÑ‹ + +/logout.bml.killall.text=У Ð²Ð°Ñ ÐµÑÑ‚ÑŒ другие активные ÑеанÑÑ‹, Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… компьютеров. Хотите ли вы завершить не только данный ÑеанÑ, но и вÑе оÑтальные ÑеанÑÑ‹? (Подробнее Ñм. Ñправку). + +/logout.bml.loggedout.already=Ð’Ñ‹ уже вышли из ÑиÑтемы. + +/logout.bml.loggedout.head=Выход из ÑиÑтемы + +/logout.bml.loggedout.killedall=Ð’Ñе ÑеанÑÑ‹ завершены. + +/logout.bml.loggedout.success=Ð’Ñ‹ вышли из ÑиÑтемы. + +/logout.bml.loggedout.text=Ð’Ñ‹ уÑпешно вышли из ÑиÑтемы. + +/logout.bml.logout.btn=Выход + +/logout.bml.logout.head=Выйти? + +/logout.bml.logout.text=Ðажмите кнопку, чтобы выйти из ÑиÑтемы. + +/logout.bml.title=Выход + +/lostinfo.bml.btn.proceed=Продолжить + +/lostinfo.bml.enter_email=Введите Ñвой e-mail адреÑ: + +/lostinfo.bml.enter_email_optional=E-mail адреÑ: (необÑзательный) + +/lostinfo.bml.enter_username=Введите ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/lostinfo.bml.error.commnopassword=Ðккаунт, который Ð²Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑует -- Ñто не личный дневник, а ÑообщеÑтво. У таких аккаунтов Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½ÐµÑ‚. Ð’Ñе, что нужно, можно Ñделать, Ð²Ð¾Ð¹Ð´Ñ Ð² ÑиÑтему как Ñмотритель ÑообщеÑтва. + +/lostinfo.bml.error.no_email=Чтобы воÑÑтановить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, вы должны ввеÑти Ð°Ð´Ñ€ÐµÑ Ñлектронной почты. + +/lostinfo.bml.error.purged=Ðевозможно воÑÑтановит пароль Ð´Ð»Ñ ÑƒÐ´Ð°Ð»Ñ‘Ð½Ð½Ð¾Ð³Ð¾ аккаунта, так как он уже окончательно удалён. + +/lostinfo.bml.error.renamed=ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð¾ÑÑтановить пароль Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ аккаунта. + +/lostinfo.bml.error.syndicated=Ðккаунт, пароль которого вы пытаетеÑÑŒ получить, транÑлируемый. У аккаунта данного типа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½ÐµÑ‚. + +/lostinfo.bml.error.sysbanned=Ваш аккаунт не имеет полномочий Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾ почте. + +/lostinfo.bml.error.toofrequent=Слишком много за один раз! Можно запроÑить не более трех пиÑем Ñ Ð¿Ð¾Ñ‚ÐµÑ€Ñнной информацией в течение 24 чаÑов. + +/lostinfo.bml.lostpassword.text=ЕÑли вы забыли Ñвой пароль, введите ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸, необÑзательно, e-mail адреÑ, на который будет выÑлан пароль. Указанный е-mail Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть предварительно подтвержден. ЕÑли вы оÑтавите поле e-mail пуÑтым, пароль будет выÑлан вам на текущий адреÑ. + +/lostinfo.bml.lostpassword.title=Забыли пароль? + +/lostinfo.bml.lostusername.text=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, введите Ñвой e-mail Ð°Ð´Ñ€ÐµÑ Ð¸ мы вышлем вам ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/lostinfo.bml.lostusername.title=Забыли Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ? + +/lostinfo.bml.title=Ð—Ð°Ð±Ñ‹Ñ‚Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/lostinfo_do.bml.error.no_usernames_for_email=Ðет пользователÑ(ей) Ñ Ñ‚Ð°ÐºÐ¸Ð¼ email адреÑом: [[address]] . + +/lostinfo_do.bml.error1.text=Или вы никогда не иÑпользовали Ñтот email Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñтого аккаунта, или Ð°Ð´Ñ€ÐµÑ Ð½Ðµ был подтвержден. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Это пиÑьмо поÑлано автоматичеÑки. Ðе отвечайте на него. *** + +Ð’Ñ‹ запрашивали утерÑнный пароль Ñ [[sitename]]. +Далее Ñледуют Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, пароль и e-mail, +на которые зарегиÑтрирован ваш дневник. + + Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: [[username]] + Пароль: [[password]] + ÐÐ´Ñ€ÐµÑ e-mail: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ e-mail адреÑа нажмите Ñюда: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±Ñ‹Ð»Ð° запрошена Ñ IP-адреÑа [[remoteip]]. + +ЕÑли вы не терÑли Ñвой пароль - не переживайте. Ð’ конце концов, +Ñто пиÑьмо пришло к вам, а не к кому-то другому. Возможно, произошла +накладка и какой-то пользователь отправил Ñтот запроÑ, +думаÑ, что данный аккаунт принадлежит ему. Также возможно, что +кто-то проÑто Ñделал опечатку в имени или адреÑе e-mail. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +ЕÑли вы дейÑтвительно полагаете, что вашему аккаунту может что-то +угрожать, прочтите информацию + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +о том, как обеÑпечить его безопаÑноÑÑ‚ÑŒ. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Полезные ÑÑылки: + + Ваш дневник: + [[journalurl]] + + Сделать запиÑÑŒ в дневник: + [[updateurl]] + +Такие дела, +команда [[sitename]] + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Zabytyj parol' + +/lostinfo_do.bml.password_mailed.text=ПоздравлÑем. Ваш пароль был выÑлан вам по e-mail. + +/lostinfo_do.bml.password_mailed.title=Пароль выÑлан! + +/lostinfo_do.bml.title=Ð—Ð°Ð±Ñ‹Ñ‚Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/lostinfo_do.bml.username_mailed.text=ПоздравлÑем. Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð»Ð¾ выÑлано вам по e-mail. + +/lostinfo_do.bml.username_mailed.title=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð²Ñ‹Ñлано! + +/manage/index.bml.about=УправлÑÑ‚ÑŒ Ñвоим дневником легко. ПроÑто выберите нужный пункт из Ñтого ÑпиÑка: + +/manage/index.bml.communities=Создайте ÑообщеÑтва и управлÑйте ими: + +/manage/index.bml.communities.create.about=Создать новое ÑообщеÑтво + +/manage/index.bml.communities.header=СообщеÑтва + +/manage/index.bml.communities.invites.about=ПроÑмотреть вÑе полученные вами Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð² ÑообщеÑтва, на которые вы не ответили. + +/manage/index.bml.communities.manage.about=ПоменÑÑ‚ÑŒ наÑтройки и ÑпиÑок учаÑтников ÑообщеÑтва + +/manage/index.bml.customization=Измените внешний вид Ñтраниц Ñвоего дневника: + +/manage/index.bml.customization.advanced=РаÑширенные возможноÑти + +/manage/index.bml.customization.advanced.about=ПроÑмотреть, Ñоздать или изменить Ñхемы и Ñтили в ÑиÑтеме S2 + +/manage/index.bml.customization.customize=Оформление дневника + +/manage/index.bml.customization.customize.about=ÐаÑтроить внешний вид дневника и преключитьÑÑ Ð¼ÐµÐ¶Ð´Ñƒ S1 и S2 + +/manage/index.bml.customization.header=Оформление + +/manage/index.bml.customization.links=СпиÑок ÑÑылок + +/manage/index.bml.customization.links.about=Создать ÑпиÑок ÑÑылок, отображаемых в дневнике + +/manage/index.bml.customization.modify.about=Изменить внешний вид дневника + +/manage/index.bml.customization.moodtheme.editor=Создать и редактировать Ñвои ÑобÑтвенные темы Ð´Ð»Ñ Ð½Ð°Ñтроений (mood themes) + +/manage/index.bml.customization.moodtheme.editor.header=Редактор Mood Themes + +/manage/index.bml.customization.moodtheme.header=Mood Themes + +/manage/index.bml.customization.moodtheme.set=Выбрать, какой из наборов mood themes будет иÑпользован в вашем дневнике + +/manage/index.bml.customization.moodtheme.set.header=Выбрать Mood Theme + +/manage/index.bml.customization.s1.header=СиÑтема Ñтилей S1 + +/manage/index.bml.customization.s2.header=СиÑтема Ñтилей S2 + +/manage/index.bml.entries=Работать Ñ Ð·Ð°Ð¿Ð¸ÑÑми, Ñделанными в вашем дневнике: + +/manage/index.bml.entries.edit.about=Редактировать или удалить запиÑи в дневнике + +/manage/index.bml.entries.header=ЗапиÑи в дневнике + +/manage/index.bml.entries.memories.about=ПроÑмотреть и изменить избранные запиÑи + +/manage/index.bml.friends=УправлÑÑ‚ÑŒ ÑпиÑком и группами друзей, отфильтровать ленту друзей ÑоглаÑно выбранным группам: + +/manage/index.bml.friends.edit.about=Добавить или удалить пользователей в ÑпиÑке друзей; изменить цвет, которым они обозначены. + +/manage/index.bml.friends.filter=Страница фильтров Ð´Ð»Ñ Ð»ÐµÐ½Ñ‚Ñ‹ друзей + +/manage/index.bml.friends.filter.about=Отобрать пользователей из ÑпиÑка друзей и показать определенную группу + +/manage/index.bml.friends.groups.about=Создать, отредактировать или удалить подгруппу из ÑпиÑка друзей + +/manage/index.bml.friends.header=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/manage/index.bml.information=Выберите, какие данные будут отображатьÑÑ Ð² вашем дневнике: + +/manage/index.bml.information.changepass=Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ + +/manage/index.bml.information.changepass.about=Изменить пароль к Ñвоему дневнику + +/manage/index.bml.information.editinfo.about=Редактировать личные данные и разные наÑтройки + +/manage/index.bml.information.emailpost=ÐаÑтройки email-шлюза + +/manage/index.bml.information.emailpost.about=Управление email-адреÑами и ПИÐ-кодами Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñей через email + +/manage/index.bml.information.header=Данные дневника + +/manage/index.bml.information.siteopts.about=Выбрать желаемую Ñхему и Ñзык Ñайта + +/manage/index.bml.information.status=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° + +/manage/index.bml.information.status.about=ПоменÑÑ‚ÑŒ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° (удалить или отменить удаление) + +/manage/index.bml.login=ÐижеÑледующие ÑÑылки ведут на Ñтраницы, где требуетÑÑ Ð¸Ð¼Ñ Ð¸ пароль. Чтобы не делать Ñто каждый раз, вы можете заранее войти в ÑиÑтему. + +/manage/index.bml.title=Управление дневниками + +/manage/index.bml.userpictures=Загрузите или измените картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² Ñвоем дневнике: + +/manage/index.bml.userpictures.edit.about=Загрузить или изменить картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/manage/index.bml.userpictures.header=Картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/manage/invites.bml.abilities.title=ВозможноÑти + +/manage/invites.bml.accept=ПринÑÑ‚ÑŒ + +/manage/invites.bml.accepted.body=Ð’Ñ‹ вÑтупили в Ñледующие ÑообщеÑтва, Ñо Ñледующими возможноÑÑ‚Ñми: + +/manage/invites.bml.accepted.title=Приглашений принÑто + +/manage/invites.bml.actions.title=ДейÑÑ‚Ð²Ð¸Ñ + +/manage/invites.bml.back=УправлÑÑ‚ÑŒ приглашениÑми + +/manage/invites.bml.community.title=СообщеÑтво + +/manage/invites.bml.decline=Отказать + +/manage/invites.bml.fromline=From [[user]] ([[date]]) + +/manage/invites.bml.label.admin=Смотритель + +/manage/invites.bml.label.member=УчаÑтник + +/manage/invites.bml.label.moderate=Модератор + +/manage/invites.bml.label.post=Может пиÑать + +/manage/invites.bml.label.preapprove=Без модерации + +/manage/invites.bml.manage=УправлÑÑ‚ÑŒ аккаунтом + +/manage/invites.bml.none.body=ÐераÑÑмотренных приглашений в ÑообщеÑтва на наÑтоÑщий момент нет. + +/manage/invites.bml.none.title=Ðичего нераÑÑмотренного + +/manage/invites.bml.rejected.body=Ð’Ñ‹ отклонили Ñледующие Ð¿Ñ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð² ÑообщеÑтва: + +/manage/invites.bml.rejected.title=Приглашений отклонено + +/manage/invites.bml.submit=Отправить + +/manage/invites.bml.title=УправлÑÑ‚ÑŒ приглашениÑми в ÑообщеÑтва + +/manage/invites.bml.undecided.body=Ð’Ñ‹ не решили, что делать Ñо Ñледующими приглашениÑми: + +/manage/invites.bml.undecided.title=Приглашений до Ñих пор не раÑÑмотрено + +/manage/links.bml.about<< +ИÑпользуйте форму внизу Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑпиÑка ÑÑылок, которые будут видны в вашем дневнике. СÑылки будут видны, еÑли Ñта возможноÑÑ‚ÑŒ поддерживаетÑÑ Ð²Ð°ÑˆÐµÐ¼ S2 Ñтилем. + +. + +/manage/links.bml.about.blank=Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑка Ñтроки введите "-" в заголовке. + +/manage/links.bml.about.heading=Чтобы Ñоздать подзаголовок раздела, введите заголовок без адреÑа. + +/manage/links.bml.about.reorder<< +Чтобы поменÑÑ‚ÑŒ раÑположение ÑÑылок в ÑпиÑке, измените порÑдковые номера Ñлева от них (можно вводить и деÑÑтичные дроби). + +. + +/manage/links.bml.error.s2required=СпиÑок ÑÑылок доÑтупен только в ÑтилÑÑ… S2. Чтобы переключитьÑÑ Ð² S2, Ñмотрите Ñтраницу [[link]]. + +/manage/links.bml.error.s2required.header=Ðеобходим Ñтиль S2 + +/manage/links.bml.success=Ваши ÑÑылки Ñохранены! + +/manage/links.bml.title=СпиÑок ÑÑылок + +/manage/phonepost.bml.delete=Удалить наÑтройки + +/manage/phonepost.bml.deleted=Ваша Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была удалена + +/manage/phonepost.bml.deleted.header=Удалено + +/manage/phonepost.bml.error.inuse=Ðеправильный PIN-код, иÑправьте, пожалуйÑта. + +/manage/phonepost.bml.error.phone.length=Ð’ вашем номере телефона должно быть менее 10 цифр. + +/manage/phonepost.bml.error.pin=Ваш ПИРдолжен быть цифровым. + +/manage/phonepost.bml.error.transcription=Указана Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° друзей + +/manage/phonepost.bml.intro.loggedin<< +запиÑи по телефону, нашишите ваш номер телефона и ПИÐ-код ниже. p?> +Положение о конфиденциальноÑти). +Ð’ можете звонить и Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ номера, но тогда вам будет нужно ввеÑти авторизованный номер прежде, чем вы Ñможете запиÑать аудиозапиÑÑŒ. p?> + + +. + +/manage/phonepost.bml.intro.loggedout=Члены могут войти в ÑиÑтему и изменить наÑтройки ÐудиозапиÑейздеÑÑŒ: + +/manage/phonepost.bml.phone=Санкционированный номер телефона: + +/manage/phonepost.bml.phone.help=(515)555-5555 + +/manage/phonepost.bml.pin= ПИÐ-код + +/manage/phonepost.bml.pin.help=Желательно, длиной от 4 до 6 цифр + +/manage/phonepost.bml.save=Сохранить наÑтройки + +/manage/phonepost.bml.saved=Сохранен + +/manage/phonepost.bml.success.moreinfo=Чтобы больше узнать о том, как запиÑывать аудиозапиÑи по телефону, Ñмотрите раздел Ñправки Как мне помеÑтить в дневник аудиозапиÑÑŒ по телефону?. + +/manage/phonepost.bml.success.text=ÐаÑтройки вашего телефона Ñохранены + +/manage/phonepost.bml.title=ÐаÑтройки при Ñоздании запиÑей по телефону + +/manage/phonepost.bml.transcribers=Утвержденные операторы + +/manage/phonepost.bml.transcribers.help=Редактировать группы друзей + +/manage/pubkey.bml.error.invalidkey=КажетÑÑ, Ñто не PGP/GPG ключ. + +/manage/pubkey.bml.error.notconfigured=Увы, на Ñтом Ñайте PGP не поддерживаетÑÑ. + +/manage/pubkey.bml.header=PGP/GPG ключ + +/manage/pubkey.bml.info=ÐŸÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ открытого ключа позволит другим пользователÑм увидеть его через вашу Ñтраницу О пользователе, и вы Ñможете пиÑать через email-шлюз Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ идентифицированных email. ИнÑтрукции здеÑÑŒ. + +/manage/pubkey.bml.pastekey=Ð’Ñтавьте ваш полный ключ (ascii уÑиленный формат) в форму внизу + +/manage/pubkey.bml.save=Сохранить + +/manage/pubkey.bml.successhead=Готово + +/manage/pubkey.bml.successtext=Ваш открытый ключ Ñохранен. Ð’Ñ‹ можете eго увидеть здеÑÑŒ. + +/manage/pubkey.bml.title=Задать открытый ключ + +/manage/pubkey.bml.whatis=Ð’Ñ‹ не знаете, что такое открытый ключ? ÐуждаетеÑÑŒ в помощи по переноÑу вашего ключа? Читайте дополнительную информацию о PGP и GPG. + +/manage/siteopts.bml.btn.lang=ПоменÑÑ‚ÑŒ Ñзык + +/manage/siteopts.bml.btn.scheme=ПоменÑÑ‚ÑŒ Ñхему + +/manage/siteopts.bml.head.lang=Выберите Ñзык + +/manage/siteopts.bml.head.scheme=Выберите Ñхему + +/manage/siteopts.bml.scheme.preview=[ПроÑмотр [[title]] Ñхемы] + +/manage/siteopts.bml.title=ÐаÑтройки Ñайта + +/manage/tags.bml.addnew=ЗдеÑÑŒ можно добавить метки! + +/manage/tags.bml.button.delete=Удалить выбранные метки. + +/manage/tags.bml.button.rename=Переименовать + +/manage/tags.bml.button.show=Показать запиÑи в дневнике + +/manage/tags.bml.confirm.delete=Ð’Ñ‹ уверены, что хотите удалить выбранные метки? Эта Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ€Ð°Ñ‚Ð¸Ð¼Ð°. + +/manage/tags.bml.hint.create=Можно Ñоздать неÑколько меток Ñразу, Ð´Ð»Ñ Ñтого нужно перечиÑлить их через запÑтую. + +/manage/tags.bml.hint.delete=Удалить вÑе ÑÑылки на выбранные метки. + +/manage/tags.bml.hint.entries=Показать запиÑи в дневнике, отмеченные выбранными метками. + +/manage/tags.bml.hint.rename=Переименовать метку. + +/manage/tags.bml.intro=Ðа Ñтой Ñтранице можно поÑмотреть и поправить определенные вами метки. + +/manage/tags.bml.label.tags=СвойÑтва меток + +/manage/tags.bml.label.yours=Ваши метки + +/manage/tags.bml.none=Ð’Ñ‹ пока не Ñоздали ни одной метки. + +/manage/tags.bml.sort.a=Сортировать: по алфавиту или по иÑпользованию + +/manage/tags.bml.sort.b=Сортировать: по алфавиту или по иÑпользованию + +/manage/tags.bml.title=Управление метками + +/meme.bml.meme.disabled=ÐдминиÑтратор Ñайта отключил Ñту возможноÑÑ‚ÑŒ. + +/modify.bml.title=Изменение дневника + +/modify_do.bml.availablestyles.head=ДоÑтупные Ñтили + +/modify_do.bml.availablestyles.userstyles=Стили пользователÑ: + +/modify_do.bml.colortheme.about=ЗдеÑÑŒ вы можете выбрать цветовую гамму, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ иÑпользоватьÑÑ Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¼Ð¸ выше компоновками Ñтраниц. ЕÑли вам не нравÑÑ‚ÑÑ Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ðµ цветовые ÑочетаниÑ, выберите Ñвои ÑобÑтвенные. + +/modify_do.bml.colortheme.area.head=ОблаÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ + +/modify_do.bml.colortheme.color.head1=Цвет + +/modify_do.bml.colortheme.color.head2=(цвет в виде #rrggbb или его название) + +/modify_do.bml.colortheme.customcolors=Произвольные цвета + +/modify_do.bml.colortheme.defaulttheme=Гамма по умолчанию + +/modify_do.bml.colortheme.head=Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° + +/modify_do.bml.domainalias.about=ЕÑли у Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑÑ‚ÑŒ Ñвоё зарегиÑтрированное доменное Ð¸Ð¼Ñ (или еÑли вы планируете таковое завеÑти) и хотите, чтобы по его адреÑу открывалÑÑ Ð²Ð°Ñˆ дневник, введите его здеÑÑŒ: + +/modify_do.bml.domainalias.domainname=Доменное имÑ: + +/modify_do.bml.domainalias.example=Ðапример: my-journal.com + +/modify_do.bml.domainalias.head=Совмещение доменных имён + +/modify_do.bml.domainalias.helptext=Чтобы Ñта возможноÑÑ‚ÑŒ заработала, вы также должны наÑтроить IP-Ð°Ð´Ñ€ÐµÑ DNS вашего домена так, чтобы он указывал на [[sitename]]. Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации читайте Справку. + +/modify_do.bml.done.btn.savechanges=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/modify_do.bml.done.head=Готово? + +/modify_do.bml.done.text=Когда закончите, нажмите ниже кнопку "Сохранить изменениÑ": + +/modify_do.bml.error.dupdomainalias=Указанное вами альтернативное доменное Ð¸Ð¼Ñ ÑƒÐ¶Ðµ зарегиÑтрировано другим пользователем. + +/modify_do.bml.error.stylenotavailable=Один из выбранных вами Ñтилей недоÑтупен. Причиной Ñтого может быть или еÑли кто-то удалил Ñтиль, или еÑли вы выбрали Ñтиль, который вы не имеете права иÑпользовать. + +/modify_do.bml.friends.about=Эти наÑтройки влиÑÑŽÑ‚ на то, как выглÑдит ваша лента друзей. + +/modify_do.bml.friends.head=Лента друзей + +/modify_do.bml.friends.opt.usesharedpic.about=Этот флаг определÑет, чью картинку вы видите в Ñвоей ленте друзей, когда пользователь помещает запиÑÑŒ в ÑовмеÑтно иÑпользуемый дневник или дневник ÑообщеÑтва. ЕÑли вы уÑтановите флаг, вы будете видеть картинку ÑообщеÑтва. ЕÑли вы уберёте флаг, вы будете видеть картинку пользователÑ, оÑтавившего запиÑÑŒ. + +/modify_do.bml.friends.opt.usesharedpic.head=Показывать картинки ÑовмеÑтно иÑпользуемых дневников вмеÑто картинок пользователей, оÑтавлÑющих там запиÑи. + +/modify_do.bml.journaloptions.about=ЗдеÑÑŒ вы можете переделать внешний вид Ñтраниц вашего дневника. ЕÑли вам интереÑно как вÑÑ‘ Ñто работает, читайте информацию Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð². Однако мы предполагаем, что в большинÑтве Ñлучаев доÑтаточно оÑновных наÑтроек, приведённых ниже: + +/modify_do.bml.journaloptions.head=ÐаÑтройки дневника + +/modify_do.bml.journalstatus.about=ЗдеÑÑŒ вы можете удалить или воÑÑтановить Ñвой дневник. С момента ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ 30 дней, чтобы передумать и воÑÑтановить его. По иÑтечении 30 дней, дневник будет удалён навÑегда и воÑÑтановить его будет нельзÑ, ÑовÑем никак нельзÑ. + +/modify_do.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ñти дневника + +/modify_do.bml.journalstatus.select.activated=Ðктивен + +/modify_do.bml.journalstatus.select.deleted=Удалён + +/modify_do.bml.journalstatus.select.head=СоÑтоÑние: + +/modify_do.bml.journalstatus.select.suspended=Заморожен + +/modify_do.bml.moodicons.about=ÐŸÐ¾Ð¼ÐµÑ‰Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в дневник, вы можете указать Ñвое текущее наÑтроение. Разные пользователи Ñоздали множеÑтво наборов Ñо значками наÑтроений. Их можете иÑпользовать и вы. ЕÑли вы не хотите, чтобы Ñ€Ñдом Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ наÑтроениÑми были картинки (или еÑли вы вообще не хотите пользоватьÑÑ Ñтой возможноÑтью), выберите "(None)". + +/modify_do.bml.moodicons.head=Значки наÑтроений + +/modify_do.bml.moodicons.opt.forcefriends.about=ИÑпользовать Ñтот набор Ð´Ð»Ñ Ð²Ñех пользователей в вашей ленте друзей. + +/modify_do.bml.moodicons.personal=ПерÑональные темы: + +/modify_do.bml.moodicons.preview=предварительный проÑмотр + +/modify_do.bml.moodicons.select=Выберите набор значков наÑтроений: + +/modify_do.bml.overrides.about=Вам необÑзательно что-то менÑÑ‚ÑŒ в Ñтом разделе. Он предназначен Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… ÑпецифичеÑких деталей в компоновке ваших Ñтраниц. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ÑодержитÑÑ Ð² разделе Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð². Учтите, что перекрывающими кодами вы можете переопределить лишь некоторые фрагменты Ñтилей. ЕÑли вы хотите переопределить вÑÑ‘, вам Ñледует Ñоздать Ñвой ÑобÑтвенный Ñтиль. + +/modify_do.bml.overrides.box.head=Перекрывающие коды: + +/modify_do.bml.overrides.head=Переопределение ÑÑ‚Ð¸Ð»Ñ + +/modify_do.bml.overrides.note=Учтите, что не вÑе переменные ÑÑ‚Ð¸Ð»Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть переопределены. Дополнительную информацию Ñмотрите в документации. Также, обратите внимание, что еÑли вы, Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÑ Ð¿ÐµÑ€ÐµÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð¸Ðµ коды, иÑпользовали Ñ‚Ñг, не разрешённый в заголовке HTML-документа (например, <DIV>, <SPAN>, <IMG> и многие другие), то Ñтот Ñ‚Ñг будет вырезан. Ð’ перекрывающих кодах вида *_HEAD могут быть иÑпользованы только те Ñлементы HTML, которые разрешены в заголовке HTML-документа. Это Ñ‚Ñги: <title>, <base>, <style>, <link>, и <meta>. + +/modify_do.bml.overrides.warning=ЭТО ÐЕ ТО МЕСТО, ГДЕ МОЖÐО ПИСÐТЬ Ð’ СВОЙ ДÐЕВÐИК! + +/modify_do.bml.pagelayoutstyle.about=Эта наÑтройка определÑет то, как ваш дневник выглÑдит на Ñкране. + +/modify_do.bml.pagelayoutstyle.head=Стиль компоновки Ñтраницы + +/modify_do.bml.pagelayoutstyle.warning=Ваш тип Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет выбирать только Ñреди небольшого количеÑтва Ñтилей-по-умолчание. + +/modify_do.bml.success.head=ПолучилоÑÑŒ + +/modify_do.bml.success.text=ÐаÑтройки вашего дневника обновлены. Ð’Ñ‹ можете поÑмотреть Ñвой дневник здеÑÑŒ. + +/multisearch.bml.formaterror=Ðеправильный формат + +/multisearch.bml.noaddress.text=Ð’Ñ‹ не указали email Ð°Ð´Ñ€ÐµÑ + +/multisearch.bml.noaddress.title=Ðет адреÑа + +/multisearch.bml.nointerest.text=Ð’Ñ‹ не указали Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ + +/multisearch.bml.nointerest.title=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ oÑ‚ÑуÑтвует + +/multisearch.bml.nomatch.text=ПоиÑк по заданным вами параметрам безрезультатен + +/multisearch.bml.nomatch.title=Совпадений нет + +/multisearch.bml.region.bodytext<< +Ð’Ñ‹ можете проводить поиÑк по региону в Ñледующих форматах: +
      +
    • Страна
    • +
    • Город*
    • +
    • Город, штат
    • +
    • Штат, Ñтрана
    • +
    • Город, штат, Ñтрана
    • +
    +ПримечаниÑ: +
      +
    • *поиÑк Ñ Ð¸Ñпользованием только Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð³Ð¾Ñ€Ð¾Ð´Ð° или города + штата по умолчанию подразумевает СШÐ.
    • +
    • Страна может определÑÑ‚ÑŒÑÑ Ð»Ð¸Ð±Ð¾ названием Ñтраны, либо двухбуквенным кодом Ñтраны.
    • +
    +ЕÑли вы хотите иÑпользовать другой тип поиÑка, поÑмотрите поиÑк по директориÑм. +. + +/multisearch.bml.region.head=ПоиÑк по региону + +/poll/create.bml.button.editpoll=Редактировать Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.button.insert=Ð’Ñтавить + +/poll/create.bml.button.postpoll=Опубликовать Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.button.preview=Предварительный проÑмотр опроÑа + +/poll/create.bml.button.seecode=ПроÑмотреть код + +/poll/create.bml.button.startover=Ðачать Ñначала + +/poll/create.bml.elements.limitreached=ИÑпользовано макÑимальное количеÑтво возможных Ñлементов + +/poll/create.bml.error.accttype=Ваш тип аккаунта не позволÑет Ñоздавать опроÑÑ‹. + +/poll/create.bml.error.allitemsblank=Ð’Ñе Ñтрочки не могут быть незаполненными + +/poll/create.bml.error.notext=Вам придетÑÑ ÑƒÑ‚Ð¾Ñ‡Ð½Ð¸Ñ‚ÑŒ ваш Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.error.parsing=Ошибка при анализе опроÑа: + +/poll/create.bml.error.pqmaxlengthinvalid=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° атрибута lj-pq тегов должна быть чиÑлом от [[min]] до [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Ðтрибут размера lj-pq текÑта дожен быть целым чиÑлом от [[min]] до [[max]]. + +/poll/create.bml.error.scalemaxlessmin=Значение "от" должно быть меньше Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ "до" + +/poll/create.bml.error.scalemininvalid=Увеличение на шкале должно быть минимум [[min]]. + +/poll/create.bml.error.scaletoobig=Лимит [[max]] выборов (до-от)/количеÑтво >20 + +/poll/create.bml.error.texttoolong=ТекÑÑ‚ варианта Ñлишком длинный и был укорочен + +/poll/create.bml.haserrors=Ð’ вашем опроÑе обнаружена одна или неÑколько ошибок. Прокрутите Ñтраницу вниз, чтобы увидеть подробноÑти. + +/poll/create.bml.insertquestion=Введите ваш Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð·Ð´ÐµÑÑŒ: + +/poll/create.bml.options=Варианты: + +/poll/create.bml.options.limitreached=Вами доÑтигнут лимит количеÑтва вариантов + +/poll/create.bml.pollname=Ðазвание опроÑа: + +/poll/create.bml.preview.desc=Внизу находитÑÑ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ð¹ проÑмотр вашего опроÑа. Он будет выглÑдеть точно так же и в вашем дневнике. ИÑпользуйте кнопки, чтобы вернутьÑÑ Ðº предыдущей Ñтранице и внеÑти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð½Ð¸Ñ Ð¸Ð»Ð¸ чтобы помеÑтить Ð¾Ð¿Ñ€Ð¾Ñ Ð²Ð°Ñˆ дневник. + +/poll/create.bml.preview.options=Варианты: + +/poll/create.bml.properties=ХарактериÑтики опроÑа: + +/poll/create.bml.question=ВопроÑ: + +/poll/create.bml.questionnum=Ð’Ð¾Ð¿Ñ€Ð¾Ñ #[[num]] + +/poll/create.bml.questions=ВопроÑÑ‹ Ð´Ð»Ñ Ð¾Ð¿Ñ€Ð¾Ñа + +/poll/create.bml.title=Создание опроÑа + +/poll/create.bml.type.check=Check Boxes + +/poll/create.bml.type.drop=Drop-down box + +/poll/create.bml.type.radio=Radio Buttons + +/poll/create.bml.type.scale=Scale + +/poll/create.bml.type.text=Text entry + +/poll/create.bml.whoview=Кому можно видеть Ñтот опроÑ? + +/poll/create.bml.whovote=Кому можно голоÑовать в Ñтом опроÑе? + +/poll/index.bml.discuss=ОбÑудить результаты + +/poll/index.bml.error.cantview=Извините, вам не разрешено видеть Ñтот опроÑ. + +/poll/index.bml.error.postdeleted=ÐÐ°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ удалена, Ð¾Ð¿Ñ€Ð¾Ñ Ð½ÐµÐ´Ð¾Ñтупен. + +/poll/index.bml.filloutpoll=Заполнить Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/index.bml.gotocreate=Это приглашение принÑÑ‚ÑŒ учаÑтие в опроÑе. Ð’Ñ‹ наткнулиÑÑŒ на Ñтраницу, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½Ð¸Ñ‡ÐµÐ¼ не занÑта. ЕÑли хотите, вы можете Ñоздать новый опроÑ. + +/poll/index.bml.pollnotfound=ÐžÐ¿Ñ€Ð¾Ñ Ð½Ðµ найден. + +/poll/index.bml.submitted.head=СпаÑибо + +/poll/index.bml.submitted.text=Ваши ответы на вопроÑÑ‹ отправлены. + +/poll/index.bml.submitted.title=Отправлено! + +/poll/index.bml.title=ÐžÐ¿Ñ€Ð¾Ñ + +/poll/index.bml.viewresults=Показать результаты опроÑа + +/pubkey.bml.error.notconfigured=Этот Ñайт не Ñконфигурирован Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ PGP. + +/pubkey.bml.error.nousername=Ðе указано Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/pubkey.bml.info.desc=Ðе знаете, что такое открытый ключ? Прочитайте дополнительную информацию о PGP и GPG. + +/pubkey.bml.info.head<< +Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/pubkey.bml.info.upload=Хотите загрузить ваш ключ? Ðажмите здеÑÑŒ. + +/pubkey.bml.label=Открытый ключ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]: + +/pubkey.bml.nokey=[[user]] пока не загрузил открытый ключ. + +/pubkey.bml.title=Показать открытый ключ + +/register.bml.ask.body=Ðажмите на кнопку внизу, чтобы поÑлал подверждающий email [[email]]. + +/register.bml.ask.button=ПоÑлать + +/register.bml.ask.header=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.asterisk.comment=(аккаунты, отмеченные * еще не подверждены) + +/register.bml.email.body<< +Это подтверждающий еmail, который вы запроÑили. +Ð”Ð»Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ аккаунта, пожалуйÑта, откройте Ñтраницу: + + [[conflink]] + +Возможно, вам придетÑÑ Ñкопировать Ñтот Ð°Ð´Ñ€ÐµÑ Ð¸ вÑтавить его в окошко вашего браузера. + +Привет, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.error.invalidcode=Ðеправильный подтверждающий код + +/register.bml.error.useralreadyvalidated=ÐÐ´Ñ€ÐµÑ Ð¿Ð¾Ñ‡Ñ‚Ñ‹ [[user]] уже был подтверждён. + +/register.bml.error.usernotfound=Пользователеь не найден + +/register.bml.new.editinfo=Редактировать информацию -- Заполните анкету Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ выберите наÑтройки. + +/register.bml.new.header=ПолучилоÑÑŒ! + +/register.bml.new.login=Login -- И вам не придетÑÑ Ð¿Ð¾Ð²Ñюду вводить ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. + +/register.bml.new.modify=Изменить дневник -- Изменить внешний вид вашего дневника + +/register.bml.new.update=ÐÐ¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ -- ÐапиÑать в вашем дневнике + +/register.bml.sent.body=Еmail, подтверждающий региÑтрацию, был поÑлан. Ð”Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации вам нужно нажать на ÑÑылку в email. + +/register.bml.sent.header=ПолучилоÑÑŒ! + +/register.bml.title=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.trans.body=Ваш новый email Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½ + +/register.bml.trans.header=ПолучилоÑÑŒ + +/site/contract.bml.title=Социальный контракт + +/styles/create.bml.choosebase=Выберите начальный Ñтиль, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ вы начнете и редактируйте: + +/styles/create.bml.createstyle.head=Создать Ñтиль + +/styles/create.bml.createstyle.text=ЗдеÑÑŒ вы можете Ñоздать ваш ÑобÑтвенный Ñтиль, который может быть вÑтроен в ваш дневник на вашей домашней Ñтранице или, еÑли хотите, Ñделан общедоÑтупнум Ñтилем и иÑпользован другими людьми. Вам придетÑÑ Ñ€Ð°Ð±Ð¾Ñ‚Ð°Ñ‚ÑŒ здеÑÑŒ, а не в Ñекции перекрывающихÑÑ ÐºÐ¾Ð´Ð¾Ð². Только пользователи Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼ аккaунтом могут Ñоздавать ÑобÑтвенные Ñтили. + +/styles/create.bml.enterstyleid=Или введите номер внеÑиÑтемного общедоÑтупного ÑÑ‚Ð¸Ð»Ñ (ID): + +/styles/create.bml.noneorother=(Ðикакой или один из перечиÑленных ниже:) + +/styles/create.bml.selecttype.head=Выберите тип ÑÑ‚Ð¸Ð»Ñ + +/styles/create.bml.submit=Создать Ñтиль + +/styles/create.bml.title=Создать Ñтиль + +/styles/create_do.bml.editstyle=Редактировать Ñтиль + +/styles/create_do.bml.error.accounttype=Тип вашего аккунта не позволÑет вам Ñоздавать новые Ñтили + +/styles/create_do.bml.error.invalidview=Ð’Ñ‹ не выбрали правильный тип ÑÑ‚Ð¸Ð»Ñ + +/styles/create_do.bml.error.styleexists=Ð’Ñ‹ уже Ñоздали Ñтиль Ñтого типа и назвали его [[des]]. ЕÑли вы дейÑтвительно хотите Ñоздать новый Ñтиль типа [[view]], измените ваш Ñтарый Ñтиль [[view], переименйте его, а потом возращайтеÑÑŒ и Ñоздавайте Ñтиль Ñтого типа. + +/styles/create_do.bml.error.stylenotfound=Ð¡Ñ‚Ð¸Ð»Ñ Ð½Ð° котором вы хотите базировать Ñвой новый Ñтиль ([[baseid]]), не ÑущеÑтвует! + +/styles/create_do.bml.error.stylenotpublic=Стиль, на котором вы базируете Ñвой новый Ñтиль ([[baseid]]), не общедоÑтупный, вы не можете его Ñкопировать, увы. + +/styles/create_do.bml.success.head=ПолучилоÑÑŒ + +/styles/create_do.bml.success.text=Ваш Ñтиль Ñоздан и временно назван [[des]]. Ðажав клавиши внизу, вы можете начать его редактировать. + +/styles/create_do.bml.title=Создать Ñтиль + +/styles/index.bml.about<< +

    Данный раздел Ñайта позволÑет Ñоздавать, редактировать и удалÑÑ‚ÑŒ наÑтраиваемые Ñтили S1. Это позволÑет изменить вид вашего дневника, в ÑоответÑтвии Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ потребноÑÑ‚Ñми. Ð’Ñ‹ можете Ñделать дневник неотличимым от Ñвоего Ñайта или проÑто Ñделать его отличным от других дневников.

    + +

    Ð’Ñ‹ можете Ñоздать вÑтраиваемые Ñтили, которые позволÑÑŽÑ‚ добавить только запиÑи из дневника Ð´Ð»Ñ Ð²ÑÑ‚Ñ€Ð°Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° в другой Ñайт, вмеÑто ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ Ñтраницы.

    + +

    Больше информации о ÑиÑтеме Ñтилей, вы прочитаете в документации по ÑтилÑм из +раздела Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð².

    + +

    Обратите внимание, что только платные пользователи +могут Ñоздавать и иÑпользовать Ñвои Ñтили. БеÑплатные пользователи могут выбрать один из Ñтандартных Ñтилей, Ñделать Ñто можно на Ñтранице +Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ°.

    +. + +/styles/index.bml.about.header=Создание и иÑпользование наÑтраиваемых Ñтилей + +/styles/index.bml.nav.browse=ПроÑмотрщик Ñтилей + +/styles/index.bml.nav.browse.about=ПроÑмотрщик Ñтилей позволÑет проÑмотреть открытые Ñтили, Ñозданные другими пользователÑми. + +/styles/index.bml.nav.create=Создать новый Ñтиль + +/styles/index.bml.nav.create.about=Создание нового ÑÑ‚Ð¸Ð»Ñ "Ñ Ð½ÑƒÐ»Ñ" или на оÑнове одного из ÑущеÑтвующих открытых Ñтилей. + +/styles/index.bml.nav.edit=Редактирование или Удаление ÑущеÑтвующего ÑÑ‚Ð¸Ð»Ñ + +/styles/index.bml.nav.edit.about=Ð’Ñ‹ можете редактировать только ÑобÑтвенные Ñтили. Чтобы изменить ÑиÑтемный Ñтиль, вы Ñначала должны Ñоздать ÑобÑтвенный Ñтиль, оÑнованный на одном из ÑиÑтемных Ñтилей. + +/styles/index.bml.nav.modify=Изменение вашего аккаунта + +/styles/index.bml.nav.modify.about=Измените Ñтиль по умолчанию Ð´Ð»Ñ Ñвоего аккаунта, в одной из ÑиÑтем готовых Ñтилей. + +/styles/index.bml.title=ÐаÑтраиваемые Ñтили + +/suggestions/index.bml.howto.text<< +
    +
    Проверьте предшеÑтвующие предложениÑ
    +Вначале, прочитайте предыдущие предложениÑ, чтобы удоÑтоверитьÑÑ, что что-то подобное не предлагалоÑÑŒ ранее. ЕÑли такое предложение было, вы можете прочитать комментарии к Ñтой запиÑи. Иногда, какое-то предложение может выглÑдеть как проигнорированное, но на Ñамом деле мы над ним работаем. Иногда идеи отклонÑÑŽÑ‚ÑÑ Ð¸Ð»Ð¸ откладываютÑÑ Ð¸Ð·-за других дел. +
    +
    Ðе можете найти Ñвою идею? ПоделитеÑÑŒ ею Ñ Ð½Ð°Ð¼Ð¸!
    +Шаблон должен иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ñех предложений. УбедитеÑÑŒ, что заполнили вÑе Ð¿Ð¾Ð»Ñ Ð² шаблоне, а также проверьте правильноÑÑ‚ÑŒ заполнениÑ, прежде чем отправить предложение. Генератор предложений не добавлÑет переводы Ñтрок автоматичеÑки, поÑтому вы должны иÑпользовать Ñ‚Ñг <br> Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ð¾Ð´Ð° Ñтроки. Это Ñделает ваше предложение более легким Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ.
    +
    Отправьте Его!
    +Ð’Ñ‹ можете добавить ÑообщеÑтво в Ñвой ÑпиÑок Друзей здеÑÑŒ. Как только предложение отправлено, люди начинают его обÑуждать. ЕÑли нам понравитÑÑ Ñта идеÑ, мы добавим её в ÑпиÑок проектов разработчиков и начнем работать, как только поÑвитÑÑ Ð²Ñ€ÐµÐ¼Ñ. Ðе вÑе Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾ÑущеÑтвлÑÑŽÑ‚ÑÑ Ð½ÐµÐ¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾, поÑтому наберитеÑÑŒ терпениÑ. +
    +. + +/suggestions/index.bml.howto.title=Как мне внеÑти Ñвоё предложение? + +/suggestions/index.bml.rules<< +ПожалуйÑта, имейте в виду что: +
      +
    • Многие Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑƒÐ¶Ðµ Ñделаны и обÑуждаютÑÑ, но еще не воплощены в реальноÑÑ‚ÑŒ. УбедитеÑÑŒ, что не повторÑете чью-то идею. +
    • Флейм будет Ñтерт +
    • ОпиÑывайте Ñвоё предложение наиболее детально. Предложение, Ñодержащее наиболее детальную информацию о его воплощении, будет оÑущеÑтвлено Ñ Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ вероÑтноÑтью, чем предложение, не имеющее детального опиÑаниÑ. Ð’Ñ‹ необÑзательно должны знать, как оÑущеÑтвить Ñто техничеÑки; попробуйте поразмыÑлить, что затронет ваше предложение и какие проблемы могут возникнуть. +
    • УбедитÑÑŒ, что прочитали Ñправку, чтобы узнать какие идеи уже воплощены или какие чаÑти Ñайта могут иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… нужд. +
    • ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð¿Ð¾ функционированию Ñайта, вы не уверены в ÑущеÑтвовании какой-то возможноÑти или ÑтолкнулиÑÑŒ Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¾Ð¹ - не отправлÑйте предложение. ВмеÑто Ñтого ÑпроÑите Центр поддержки. +
    +. + +/suggestions/index.bml.title=МеÑто Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹ + +/suggestions/index.bml.welcome.text=Ð’ некотором ÑмыÑле, мы начинаем Ñ Ð½ÑƒÐ»Ñ -- поÑтому вÑе Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ будут раÑÑмотрены. ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ дельные Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ -- что добавить, или наоборот, что убрать из зачем-то добавленного на livejournal.com -- то пройдите Ñти процедуры, чтобы привлечь внимание разработчиков Ñтого Ñайта. + +/suggestions/index.bml.welcome.title=Добро пожаловать! + +/support/append_request.bml.back.requests=ВернутьÑÑ Ðº ÑпиÑку проÑьб. + +/support/append_request.bml.back.support=ВернутьÑÑ Ð² Поддержку. + +/support/append_request.bml.bounce.noemail=Ðе указан email Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + +/support/append_request.bml.bounce.notauth=Ð’Ñ‹ не имеете права перенаправить Ñтот Ð·Ð°Ð¿Ñ€Ð¾Ñ + +/support/append_request.bml.bounce.toomany=Ð’Ñ‹ можете отправить Ñообщение макÑимум по пÑти адреÑам. Ð’Ñ‹ указали больше пÑти. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Эта проÑьба о помощи уже закрыта + +/support/append_request.bml.closed.title=Закрыто + +/support/append_request.bml.internal.approve=Чтобы утвердить ответ, вам нужно выбрать "Internal Comment / Action" и, желательно, обьÑÑнить, почему вы утвердили ответ. + +/support/append_request.bml.internal.changecat=Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ð¸, в которую отнеÑена проÑьба, вам нужно выбрать "Internal Comment / Action" и, желательно, обьÑÑнить, почему вы ее изменÑете. + +/support/append_request.bml.internal.changesum=Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÑ€Ð°Ñ‚ÐºÐ¾Ð³Ð¾ Ð¸Ð·Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñьбы, вам нужно выбрать "Internal Comment / Action" и ввеÑти новое изложение. + +/support/append_request.bml.internal.touch=Чтобы изменить ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ð¿Ñ€Ð¾Ñа, вам нужно выбрать "Internal Comment / Action" и объÑÑнить, зачем вы его менÑете. + +/support/append_request.bml.invalid.blank=Ваша запиÑÑŒ пуÑтаÑ. ПожалуйÑта, напишите хоть что-нибудь в теле пиÑьма. + +/support/append_request.bml.invalid.noanswer=Ðа утверждение был направлен неправильный Ñкрытый ответ. + +/support/append_request.bml.invalid.nocat=Эта ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ Ð½Ðµ ÑущеÑтвует + +/support/append_request.bml.invalid.noid=Ð”Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñтого Ð´ÐµÐ¹Ñ‚Ð²Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼ идентификационный номер проÑьбы о техничеÑкой поддержке. + +/support/append_request.bml.invalid.type=Ðеправильный тип ответа + +/support/append_request.bml.logged.text=Ваше дейÑтвие/комментарий/ответ зарегиÑтрирован. СпаÑибо. + +/support/append_request.bml.logged.title=Сделано + +/support/append_request.bml.login.required=Чтобы помочь другим, вы должны login + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Изменить комментарий/ответ + +/support/append_request.bml.unknown.request=ÐеизвеÑтный тип запроÑа техничеÑкой поддержки + +/support/encodings.bml.edit.header=Я не могу редактировать Ñвои запиÑи через веб-интерфейÑ! + +/support/encodings.bml.edit.text<< +Кратко: (Ð´Ð»Ñ Ñ‚ÐµÑ…, кто ведёт дневник по-руÑÑки): Зайдите на +Ñтраницу личных наÑтроек. Внизу Ñтраницы найдите наÑтройку под названием ÐвтоматичеÑки перекодировать Ñтарые запиÑи из кодировки. Выберите +из выпадающего ÑпиÑка "Cyrillic (Windows)" и Ñохраните наÑтройки. ПоÑле Ñтого ваши запиÑи должны редактироватьÑÑ ÑƒÑпешно. p?> + +Подробно: Чтобы разрешить редактирование Ñтарой неюникодной запиÑи, Живой Журнал должен знать в какой кодировке Ñта запиÑÑŒ была Ñделана. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹, пишущих по-английÑки или на других западноевропейÑких Ñзыках, Ñта кодировка, как правило, "Western European (Windows)", но еÑли кавычки и другие мета-Ñимволы показываютÑÑ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾, попробуйте "Western European (ISO)". Пользователи, пишущие на других Ñзыках, должны выбрать Ñвою кодировку; Ð´Ð»Ñ Ñ€ÑƒÑÑкоÑзычных пользователей Ñто Ñкорее вÑего "Cyrillic (Windows)", возможно "Cyrillic (KOI8)"; еÑли Ð½ÑƒÐ¶Ð½Ð°Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ° отÑутÑтвует в предложенном ÑпиÑке, обратитеÑÑŒ в Ñлужбу поддержки и объÑÑните проблему. p?> + + + +. + +/support/encodings.bml.editcl.header=Я не могу редактировать запиÑи через клиентÑкую программу! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Я не могу редактировать ÑпиÑок друзей в клиентÑкой программе! + +/support/encodings.bml.groups.text<< +Ñтранице Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¿, чтобы оÑтавить в названиÑÑ… только ASCII Ñимволы, а затем воÑпользоватьÑÑ Ð¸Ð¼ÐµÑŽÑ‰ÐµÐ¹ÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ñкой программой. p?> + +. + +/support/encodings.bml.overview.header=К чему Ñто вÑÑ‘? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=По-прежнему в затруднении? + +/support/encodings.bml.still.text=Службе поддержки. p?> + +/support/encodings.bml.title=Кодировки + +/support/faqbrowse.bml.backfaq=ВернутьÑÑ Ð½Ð° Ñтраницу вопроÑов и ответов. + +/support/faqbrowse.bml.backfaqcat=Перейти на уровень выше. + +/support/faqbrowse.bml.backsupport=ВернутьÑÑ Ð² раздел "Помощь". + +/support/faqbrowse.bml.edit.faq=Править Ñту Ñправку + +/support/faqbrowse.bml.error.nofaq=Такого вопроÑа в Справке нет. + +/support/faqbrowse.bml.lastupdated=ПоÑледний раз обновлен: + +/support/faqbrowse.bml.title_cat=Справка - [[catname]] + +/support/faqbrowse.bml.title_num=Ð’Ð¾Ð¿Ñ€Ð¾Ñ Ð½Ð¾Ð¼ÐµÑ€ [[num]] + +/support/help.bml.interim=Эта ÑÑылка -- только Ð´Ð»Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтраторов Ñайта. + +/support/see_overrides.bml.error.noprivs=Только пользователи Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸Ñми supportviewscreened или supporthelp privilege могут увидеть перекрывающие коды других пользователей. + +/support/see_overrides.bml.error.nos1=Этот пользователь не иÑпользует S1. + +/support/see_overrides.bml.header=Перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ : + +/support/see_overrides.bml.nooverrides=Пользователь не иÑпользует перекрывающие коды. + +/support/see_overrides.bml.title=Перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/syn/index.bml.account=Ðккаунт + +/syn/index.bml.add=Добавить транÑлируемую ленту (feed) + +/syn/index.bml.add.byurl.text=Добавить транÑлируемую ленту к ÑпиÑку друзей, впечатав веб-Ð°Ð´Ñ€ÐµÑ Ð»ÐµÐ½Ñ‚Ñ‹ внизу: + +/syn/index.bml.add.byurl.title=Добавить транÑлируемую ленту по веб-адреÑу + +/syn/index.bml.add.pop.text=Ðекоторые популÑрные ленты, за которыми вы не Ñледите + +/syn/index.bml.add.pop.title=Добавить популÑрную ленту + +/syn/index.bml.add.selected=Добавить выбранное + +/syn/index.bml.back=Обратно + +/syn/index.bml.create=Создать транÑлируемую ленту + +/syn/index.bml.create.name=Добавленный веб-Ð°Ð´Ñ€ÐµÑ Ð² наÑтоÑщий момент нашим Ñайтом не транÑлируетÑÑ. Ðапишите название аккаунта, который будет иÑпользован Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ ленты. + +/syn/index.bml.error.nocreate=Добавленный веб-Ð°Ð´Ñ€ÐµÑ Ð² наÑтоÑщий момент нашим Ñайтом не транÑлируетÑÑ. Ваш тип аккаунта не позволÑет Ñоздавать новые транÑлируемые ленты. + +/syn/index.bml.error.unknown=ÐеизвеÑтный тип ошибки + +/syn/index.bml.feed.url=Интернет-Ð°Ð´Ñ€ÐµÑ Ñ‚Ñ€Ð°Ð½Ñлируемого потока + +/syn/index.bml.invalid.accountname=Ðеправильное название дневника + +/syn/index.bml.invalid.cantadd=Ð’Ñ‹ не можете добавить RSS-поток Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñайта + +/syn/index.bml.invalid.http.text=Удалить комментарий + +/syn/index.bml.invalid.http.title=Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ + +/syn/index.bml.invalid.inuse.text=Это название дневника уже иÑпользуетÑÑ + +/syn/index.bml.invalid.inuse.title=Это Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ иÑпользуетÑÑ + +/syn/index.bml.invalid.needname.text=Чтобы добавить транÑлируемый аккаунт, который пока не открыт, вернитеÑÑŒ и дайте ему название + +/syn/index.bml.invalid.needname.title=Ðеобходимо название аккунта + +/syn/index.bml.invalid.needurl=Ð”Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¹ транÑлируемой ленту, нужно ввеÑти или Ð¸Ð¼Ñ Ñ‚Ñ€Ð°Ð½Ñлируемого аккаунта, или его веб-адреÑ. + +/syn/index.bml.invalid.notexist=ТранÑлируемого аккаунта Ñ Ñ‚Ð°ÐºÐ¸Ð¼ названием не ÑущеÑтвует + +/syn/index.bml.invalid.notrss.text=Заданный интернет-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ Ñодержит данных в формате XML + +/syn/index.bml.invalid.notrss.title=Данные не в формате XML + +/syn/index.bml.invalid.port=ÐеÑтандартный номер порта не разрешен + +/syn/index.bml.invalid.reserved=Это название аккаунта зарезервировано. ПожалуйÑта, выберите другое нзвание. + +/syn/index.bml.invalid.submission=Введеннаы форма некорректна + +/syn/index.bml.invalid.url=ÐдреÑ, который вы ввели - ошибочный. Проверьте URL, который вы ввели и попробуйте Ñнова. + +/syn/index.bml.loginrequired.text=Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñвоими транÑлируемыми аккаунтами, Ñначала нужно Войти. + +/syn/index.bml.loginrequired.title=Введите пароль + +/syn/index.bml.promo.text|staleness=1 +/syn/index.bml.promo.text<< +Открыв транÑлируемый аккаунт, Ñообщите о нем другим! Чем больше людей читают транÑлируемый аккаунт, тем больше реÑурÑов выÑвобождаетÑÑ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ…. + +ПожалуйÑта, не Ñоздавайте транÑлируемые аккаунты, +которые вы не планируете читать. Создание транÑлируемого +аккаунта Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… ÑобÑтвенных проектов запрещаетÑÑ. +ПопроÑите кого-нибудь еще. +. + +/syn/index.bml.remove=Удалить отмеченное + +/syn/index.bml.table.account=Ðккаунт + +/syn/index.bml.table.feed=Лента + +/syn/index.bml.table.watchers=ЧиÑло читателей + +/syn/index.bml.title=ТранÑлÑÑ†Ð¸Ñ + +/syn/index.bml.user.nomatch=Данные автора ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð½Ðµ Ñовпадают Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ заполнившего анкету. + +/syn/index.bml.using.text=ЗдеÑÑŒ вы можете добавить транÑлируемые ленты (RSS) Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… Ñайтов к вашему ÑпиÑку друзей, и вам больше не нужно будет поÑещать деÑÑтки Ñайтов каждый день. + +/syn/index.bml.using.title=ИÑпользовать [[sitename]] Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² транÑлируемую ленту + +/syn/list.bml.error.nofeeds=Ошибка: Ðе один из транÑлируемых потоков не обновлÑлÑÑ Ð² течение поÑледних Ñуток. + +/syn/list.bml.feeddesc=ОпиÑание ленты + +/syn/list.bml.feedurl=ÐÐ´Ñ€ÐµÑ Ð»ÐµÐ½Ñ‚Ñ‹ + +/syn/list.bml.numreaders=ЧиÑло читателей + +/syn/list.bml.title=ТранÑлируемые аккаунты + +/syn/list.bml.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/syn/list.bml.xml_icon.alt=[Смотреть иÑходный поток] + +/talkmulti.bml.deleted.body=Комментарии были удалены. Ð’Ñ‹ можете увидеть оÑтавшиеÑÑ Ð·Ð´ÐµÑьздеÑьздеÑькартинкой: + +/talkpost.bml.loganonip=Обратите внимание! Этот пользователь включил опцию ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ IP-адреÑов тех, кто пишет анонимно. + +/talkpost.bml.loginq=Войти? + +/talkpost.bml.logyourip=Обратите внимание! Этот пользователь включил опцию ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ IP-адреÑов пишущих комментарии к его дневнику. + +/talkpost.bml.nosubjecthtml=HTML Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в теме ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ + +/talkpost.bml.opt.anonymous=анонимно + +/talkpost.bml.opt.bannedfrom= - в Ñтом дневнике вам пиÑать запретили. + +/talkpost.bml.opt.defpic=(по умолчанию) + +/talkpost.bml.opt.friendsonly=- Ñтот пользователь отключил возможноÑÑ‚ÑŒ пиÑать к его дневнику комментарии вÑем не-друзьÑм или анонимно. Ð’Ñ‹ Ñможете пиÑать здеÑÑŒ, еÑли [[username]] включит Ð²Ð°Ñ Ð² Ñвои друзьÑ. + +/talkpost.bml.opt.from=Как: + +/talkpost.bml.opt.ljuser=пользователь [[sitename]]: + +/talkpost.bml.opt.ljuser2=пользователь [[sitename]] + +/talkpost.bml.opt.loggedin=как [[username]] + +/talkpost.bml.opt.message=Сообщение: + +/talkpost.bml.opt.noanonpost=- Ñтот пользователь отключил возможноÑÑ‚ÑŒ пиÑать комментарии анонимно + +/talkpost.bml.opt.noautoformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/talkpost.bml.opt.noimage=Без значка + +/talkpost.bml.opt.preview=Предварительный проÑмотр + +/talkpost.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/talkpost.bml.opt.subject=Тема: + +/talkpost.bml.opt.submit=Добавить комментарий + +/talkpost.bml.opt.willscreen=(комментарий будет Ñкрыт) + +/talkpost.bml.opt.willscreenfriend=(комментарий будет Ñкрыт, еÑли вы не в ÑпиÑке друзей) + +/talkpost.bml.paraformat=По умолчанию текÑÑ‚ будет отформатирован. + +/talkpost.bml.postresponse=Добавить комментарий: + +/talkpost.bml.title=Добавление ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/talkpost.bml.usermismatch<< +Ð’Ñ‹ ввели Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, но не выбрали режим "пользователь [[sitename]]". + +ПожалуйÑта, либо очиÑтите поле имени, либо выберите нужный режим и попробуйте Ñнова. +. + +/talkpost.bml.warnscreened=Внимание: Этот комментарий Ñкрыт. ÐžÑ‚Ð²ÐµÑ‡Ð°Ñ Ð½Ð° него, вы автоматичеÑки раÑкроете его и Ñделаете видимым. + +/talkpost_do.bml.error.badpassword=Введённый Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ неверен. ЕÑли вы забыли Ñвой пароль, то можете воÑÑтановить его здеÑÑŒ. + +/talkpost_do.bml.error.badusername=Такого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° Ñайте нет. ЕÑли вы забыли Ñвоё Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, вы можете воÑÑтановить его здеÑÑŒ или вы можете оÑтавить комментарий анонимно. + +/talkpost_do.bml.error.banned=Вам запретили пиÑать комментарии в дневнике Ñтого пользователÑ. + +/talkpost_do.bml.error.blankmessage=Ваше Ñообщение пуÑто. ПожалуйÑта, введите хоть что-нибудь в поле ÑообщениÑ. + +/talkpost_do.bml.error.confused_identity=Ð’Ñ‹ ввели Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, но выбрали режим анонимного ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð¸Ð»Ð¸ как текущий пользователь. ВернитеÑÑŒ назад и решите, как вы вÑÑ‘-таки хотите отправить комментарий. + +/talkpost_do.bml.error.deleted=Ваш дневник был удален. Ð’Ñ‹ не можете пиÑать ÑообщениÑ. + +/talkpost_do.bml.error.friendsonly=Только Ð´Ñ€ÑƒÐ·ÑŒÑ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] могут оÑтавлÑÑ‚ÑŒ запиÑи в Ñтом дневнике. + +/talkpost_do.bml.error.lostcookie=КажетÑÑ, ваш cookie Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему потерÑлÑÑ. + +/talkpost_do.bml.error.manybytes=Извините, но длина вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ ([[current]]) превыÑила макÑимальную длину в байтах ([[limit]]). ПожалуйÑта, вернитеÑÑŒ назад, укоротите его и попробуйте ещё раз. + +/talkpost_do.bml.error.manychars=Извините, но длина вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ ([[current]]) превыÑила макÑимальную длину в Ñимволах ([[limit]]). ПожалуйÑта, вернитеÑÑŒ назад, укоротите его и попробуйте ещё раз. + +/talkpost_do.bml.error.mustlogin=Чтобы оÑтавить комментарий к Ñтой защищённой запиÑи, вы должны войти под Ñвоим именем и паролем. + +/talkpost_do.bml.error.noanon=Ð’ Ñтом дневнике оÑтавлÑÑ‚ÑŒ анонимные комментарии запрещено. + +/talkpost_do.bml.error.noauth=Вам запрещено оÑтавлÑÑ‚ÑŒ комментарии к Ñтой защищённой запиÑи. + +/talkpost_do.bml.error.nocomments=Ðвтор запретил комментировать Ñту запиÑÑŒ. + +/talkpost_do.bml.error.noparent=ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð²ÐµÑ‚Ð¸Ñ‚ÑŒ на неÑущеÑтвующий комментарий. + +/talkpost_do.bml.error.notafriend=Извините, пользователь [[user]] не добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок друзей, а оÑтавлÑÑ‚ÑŒ комментарии в его дневнике могут только друзьÑ. + +/talkpost_do.bml.error.nousername=Ð’Ñ‹ не ввели никакого имени пользователÑ. ЕÑли у Ð²Ð°Ñ Ð½ÐµÑ‚ Ñвоего аккаунта на нашем Ñайте, вы можете оÑтавить комментарий анонимно. + +/talkpost_do.bml.error.noverify=Извините, но вы не можете оÑтавлÑÑ‚ÑŒ комментарии в чужих дневниках, пока ваш Ð°Ð´Ñ€ÐµÑ e-mail не проверен. ЕÑли вы потерÑли пиÑьмо подтверждениÑ, вы можете повторно поÑлать его Ñебе. + +/talkpost_do.bml.error.postshared=Ð’Ñ‹ не можете оÑтавлÑÑ‚ÑŒ комментарии под ÑовмеÑтно иÑпользуемым именем или именем ÑообщеÑтва. СовмеÑтно иÑпользуемые аккаунты предÑтавлÑÑŽÑ‚ группу людей, а не отдельного человека. + +/talkpost_do.bml.error.screened=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав отвечать на Ñтот Ñкрытый комментарий. + +/talkpost_do.bml.error.suspended=Ваш дневник заморожен. Ð’Ñ‹ не можете оÑтавлÑÑ‚ÑŒ комментарии. + +/talkpost_do.bml.error.testacct=ТеÑтовые аккаунты можно иÑпользовать только в теÑтовых дневниках. + +/talkpost_do.bml.opt.preview=Предварительный проÑмотр + +/talkpost_do.bml.preview=Вот как будет выглÑдеть ваш комментарий. Ð’Ñ‹ можете продолжить его редактирование в форме внизу Ñтраницы, или отправить в текущем виде. + +/talkpost_do.bml.preview.subject=Тема: + +/talkpost_do.bml.preview.submit=Отправить + +/talkpost_do.bml.preview.title=ПроÑмотр + +/talkpost_do.bml.success.loggedin=Ð’Ñ‹ вошли в ÑиÑтему. + +/talkpost_do.bml.success.message=Ваш комментарий добавлен. Ð’Ñ‹ можете поÑмотреть его здеÑÑŒ. + +/talkpost_do.bml.success.screened.comm=Ваш комментарий добавлен. СоглаÑно наÑтройкам Ñтого ÑообщеÑтва, он был помечен как Ñкрытый и будет виден только вам и ÑмотрителÑм ÑообщеÑтва, пока они не решат его раÑкрыть. Ð’Ñ‹ можете увидеть Ñвой комментарий здеÑÑŒ. + +/talkpost_do.bml.success.screened.comm.anon=Ваш анонимный комментарий был добавлен. СоглаÑно правилам данного ÑообщеÑтва, он был Ñкрыт и будет видим только ÑмотрителÑм ÑообщеÑтва до тех пор, пока они не решат раÑкрыть его. Ð’Ñ‹ можете вернутьÑÑ Ðº ветке обÑуждениÑ. + +/talkpost_do.bml.success.screened.user=Ваш комментарий добавлен. СоглаÑно наÑтройкам Ñтого дневника, он был помечен как Ñкрытый и будет виден только вам и хозÑину дневника, пока он не решит его раÑкрыть. Ð’Ñ‹ можете увидеть Ñвой комментарий здеÑÑŒ. + +/talkpost_do.bml.success.screened.user.anon=Ваш анонимный комментарий был добавлен. СоглаÑно наÑтройкам данного дневника, он был Ñкрыт и будет видим только владельцу дневника до тех пор, пока он не решит раÑкрыть его. Ð’Ñ‹ можете вернутьÑÑ Ðº ветке обÑуждениÑ. + +/talkpost_do.bml.success.title=Сообщение уÑпешно добавлено + +/talkpost_do.bml.success.unscreened=Кроме того, Ñкрытый комментарий, на который вы отвечали, теперь раÑкрыт и будет виден вÑем. + +/talkpost_do.bml.title=Добавить комментарий + +/talkpost_do.bml.title.error=Комментарий не был добавлен + +/talkpost_do.bml.title.preview=Предварительный проÑмотр ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/talkread.bml.anonuser=(Ðнонимно) + +/talkread.bml.confirm.action=Ð’Ñ‹ уверены, что хотите удалить выделенные комментарии? + +/talkread.bml.deletedpost=(Комментарий удалён) + +/talkread.bml.deleteduser=(Пользователь [[username]] удалён) + +/talkread.bml.fromip=(от [[ip]]) + +/talkread.bml.noreplies=Комментариев нет + +/talkread.bml.nosubject=(без темы) + +/talkread.bml.replysuspended=(Ответ от Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ð¼ аккаунтом) + +/talkread.bml.screenedpost=(Скрытый комментарий) + +/talkread.bml.select=Выбрать + +/talkread.bml.subjectdeleted=[удалено] + +/talkread.bml.talkmulti.delete=Удалить + +/talkread.bml.talkmulti.des=Ð“Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð°Ð´ выбранными комментариÑми: + +/talkread.bml.talkmulti.screen=Скрыть + +/talkread.bml.talkmulti.submit=Выполнить + +/talkread.bml.talkmulti.unscreen=РаÑкрыть + +/talkread.bml.title=Комментарии + +/talkscreen.bml.error.login=Чтобы работать Ñо Ñкрытыми комментариÑми, вы должны войти под Ñвоим именем и паролем. + +/talkscreen.bml.error.privs.freeze=У Ð²Ð°Ñ Ð½ÐµÑ‚ права разморозить Ñту ветвь диÑкуÑÑии. + +/talkscreen.bml.error.privs.screen=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав Ñкрывать Ñтот комментарий. + +/talkscreen.bml.error.privs.unscreen=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав раÑкрывать Ñтот комментарий. + +/talkscreen.bml.freeze.doit=Да, заморозить ветвь. + +/talkscreen.bml.freeze.sure.body=Ð’Ñ‹ уверены, что хотите заморозить Ñту ветвь диÑкуÑÑии? ÐÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ ответить ни на Ñтом комментарий, ни на комментарии ниже по дереву! + +/talkscreen.bml.freeze.sure.title=Заморозить ветвь? + +/talkscreen.bml.frozen.body=Ветвь диÑкуÑÑи заморожена. + +/talkscreen.bml.frozen.title=Success + +/talkscreen.bml.link=Обратно к запиÑи. + +/talkscreen.bml.screen.doit=Да, Ñкрыть Ñтот комментарий + +/talkscreen.bml.screen.sure.body=Ð’Ñ‹ уверены, что хотите Ñкрыть Ñтот комментарий? + +/talkscreen.bml.screen.sure.title=Скрыть Ñтот комментарий? + +/talkscreen.bml.screened.body=Комментарий Ñкрыт. Ð’Ñ‹ можете его увидеть здеÑÑŒ. + +/talkscreen.bml.screened.title=ПолучилоÑÑŒ! + +/talkscreen.bml.title2=Изменить ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/talkscreen.bml.unfreeze.doit=Да, разморозить Ñту ветвь + +/talkscreen.bml.unfreeze.sure.body=Ð’Ñ‹ уверены, что хотите разморозить ветвь? + +/talkscreen.bml.unfreeze.sure.title=Разморозить ветвь? + +/talkscreen.bml.unfrozen.body=Ветвь разморожена. + +/talkscreen.bml.unfrozen.title=ПолучилоÑÑŒ + +/talkscreen.bml.unscreen.doit=Да, раÑкрыть Ñтот комментарий + +/talkscreen.bml.unscreen.sure.body=Ð’Ñ‹ уверены, что хотите раÑкрыть Ñтот комментарий? + +/talkscreen.bml.unscreen.sure.title=РаÑкрыть Ñтот комментарий? + +/talkscreen.bml.unscreened.body=Комментарий раÑкрыт. Ð’Ñ‹ можете его увидеть здеÑÑŒ. + +/talkscreen.bml.unscreened.title=ПолучилоÑÑŒ! + +/tools/emailmanage.bml.address.current.title=Текущий Ð°Ð´Ñ€ÐµÑ + +/tools/emailmanage.bml.address.old.none=Ðет адреÑа + +/tools/emailmanage.bml.address.old.text=Ðиже Ñледует ÑпиÑок адреÑов, которые иÑпользовалиÑÑŒ вашим дневником, и даты, когда они переÑтавали быть оÑновным адреÑом. Пометьте те из них, которые вы хотели бы удалить. + +/tools/emailmanage.bml.address.old.title=Предыдущие адреÑа + +/tools/emailmanage.bml.delete_selected=Удалить выбранные + +/tools/emailmanage.bml.desc.notfirst=Ðа Ñтой Ñтранице вы можете удалить только те адреÑа e-mail, которые иÑпользовалиÑÑŒ поÑле того, как вы подтвердили Ñвой текущий адреÑ. Ð’ чаÑтноÑти Ñто означает, что злоумышленник не Ñможет удалить ваш Ñамый первый адреÑ. + +/tools/emailmanage.bml.desc.text=Ðа Ñтой Ñтранице вы можете удалить адреÑа e-mail, которые иÑпользовалиÑÑŒ вашим дневником. Ðа удалённые адреÑа больше Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ выÑлать забытый пароль. Это может помочь, еÑли кто-то узнал ваш пароль и приÑвоил ваш дневник. ПроÑто запроÑите новый пароль на ваш Ñтарый Ð°Ð´Ñ€ÐµÑ e-mail, измените его обратно на Ñвой и удалите Ð°Ð´Ñ€ÐµÑ e-mail злоумышленника. + +/tools/emailmanage.bml.desc.title=ОпиÑание + +/tools/emailmanage.bml.log.deleted=Удалён: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñохранены + +/tools/emailmanage.bml.notvalidated.text=Ваш текущий Ð°Ð´Ñ€ÐµÑ Ñлектронной почты [[email]] должен быть проверен, чтобы вы могли иÑпользовать Ñтот ÑервиÑ. ЕÑли вы потерÑли пиÑьмо подтверждениÑ, вы можете повторно поÑлать его Ñебе. ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñвоего адреÑа, вы можете вернутьÑÑ Ð½Ð° Ñту Ñтраницу. + +/tools/emailmanage.bml.notvalidated.title=Ваш email-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ подтверждён + +/tools/emailmanage.bml.title=Управление адреÑами e-mail + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body2=ЗапиÑÑŒ в избранное добавлена. Чтобы поÑмотреть на нее, пойдите Ñюда. + +/tools/memadd.bml.body.added.header=Удачно + +/tools/memadd.bml.description=ОпиÑание: + +/tools/memadd.bml.description.text<< +Дайте опиÑание Ñтой запиÑи, Ñ Ð½Ð¸Ð¼ она будет Ñохранена в ÑпиÑке. +Чтобы удалить запиÑÑŒ из избранного, удалите опиÑание. + +. + +/tools/memadd.bml.error.deleted.body=ЗапиÑÑŒ, ранее Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ ÐºÐ°Ðº "[[desc]]" была удалена из избранного. + +/tools/memadd.bml.error.deleted.title=ЗапиÑÑŒ удалена + +/tools/memadd.bml.error.entry_deleted=ЗапиÑÑŒ больше не ÑущеÑтвует. Отметка в избранном удалена. + +/tools/memadd.bml.error.fivekeywords=Ð”Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи избранного можно указать только 5 ключевых Ñлов или категорий. + +/tools/memadd.bml.error.invalid_security=ÐедейÑтвительный или отÑутÑтвующий параметр наÑтроек безопаÑноÑти. + +/tools/memadd.bml.error.login=Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтой функции вы должны ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. ПоÑле ввода Ñтих данных вы Ñнова окажетеÑÑŒ здеÑÑŒ. + +/tools/memadd.bml.error.nodescription.title=Ðет опиÑÐ°Ð½Ð¸Ñ + +/tools/memadd.bml.form.reset=ОчиÑтить + +/tools/memadd.bml.form.submit=Добавить + +/tools/memadd.bml.keywords=Ключевые Ñлова: + +/tools/memadd.bml.keywords.example=Пример: ВеÑёлое, Свихнутое, РомантичеÑкое + +/tools/memadd.bml.keywords.select=Ð’Ñ‹ можете также указать ключевые Ñлова, иÑпользованные вами ранее. + +/tools/memadd.bml.keywords.text=Почему вы хотите добавить Ñту запиÑÑŒ в избранное? Введите до пÑти разделённых запÑтыми ключевых Ñлов или категорий, по которым Ñможете найти данную запиÑÑŒ позже. + +/tools/memadd.bml.login.enterinfo=Введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль того аккаунта, куда хотите добавить запиÑÑŒ в избранное. + +/tools/memadd.bml.login.forgot.header=Забыли что-нибудь? + +/tools/memadd.bml.login.forgot.recover=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, воÑÑтановите их здеÑÑŒ. + +/tools/memadd.bml.multiple_selections=Чтобы выбрать неÑколько Ñлементов Ñразу, нажмите и держите клавишу "Control" и щелкайте по ключевым Ñловам. + +/tools/memadd.bml.security=БезопаÑноÑÑ‚ÑŒ: + +/tools/memadd.bml.security.friendsonly=Только Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹ + +/tools/memadd.bml.security.private=Личное + +/tools/memadd.bml.security.public=Открытое + +/tools/memadd.bml.title=Добавление в избранное + +/tools/memadd.bml.title.added=Добавлено + +/tools/memadd.bml.title.add_memory=Добавить запиÑÑŒ в избранное + +/tools/memadd.bml.title.deleted=Удалено + +/tools/memadd.bml.title.edit_memory=Редактирование запиÑи избранного + +/tools/memadd.bml.whocansee<< +Кому можно видеть Ñту запиÑÑŒ в вашем избранном? +Ð’Ñем, только друзьÑм или никому, кроме ваÑ? +. + +/tools/memadd.bml.whocansee.comm=Кто может видеть, что вы занеÑли Ñту запиÑÑŒ в Избранное? Ð’Ñе, только члены ÑообщеÑтва или модераторы ÑообщеÑтва? + +/tools/memories.bml.back=Ðазад + +/tools/memories.bml.body.keyword<< + + +[[user]], в опиÑании которых вÑтречаетÑÑ Ñлово "[[keyword]]". p?> +. + +/tools/memories.bml.body.list_categories<< + + +[[user]] помеÑтил Ñвои избранные запиÑи. p?> +. + +/tools/memories.bml.body.memorable=Это неÑортированный ÑпиÑок избранного Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. + +/tools/memories.bml.delete=Удалить из Избранного + +/tools/memories.bml.delete.confirm=Ð’Ñ‹ ÑобираетеÑÑŒ удалить запиÑÑŒ из Избраннго. Ð’Ñ‹ точно хотите Ñто Ñделать? + +/tools/memories.bml.delete.deleted.head=ПолучилоÑÑŒ + +/tools/memories.bml.delete.deleted.text=ЗапиÑи из Избранного были удалены. Ð’Ñ‹ можете вернутьÑÑ Ðº ÑпиÑку. + +/tools/memories.bml.delete.deleted.title=ЗапиÑи из Избранного удалены + +/tools/memories.bml.delete.error.dberror=Во Ð²Ñ€ÐµÐ¼Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ñ… запиÑей произошел Ñбой в базе данных. Тип ошибки - [[error]] . ПожалуйÑта, попробуйте еще раз + +/tools/memories.bml.delete.error.noneselected=Ð’Ñ‹ не выбрали ни одной запиÑи Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ + +/tools/memories.bml.edit=редактировать + +/tools/memories.bml.error.noentries.body<< +Это могло произойти потому, что:
      +
    1. пользователь не добавлÑл никакие запиÑи в избранное,
    2. +
    3. избранное Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð¾, и у Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к нему или
    4. +
    5. в избранном Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½ÐµÑ‚ запиÑей, ÑоответÑтвующих вашему критерию.
    +. + +/tools/memories.bml.error.noentries.title=СпиÑок избранных запиÑей пуÑÑ‚. + +/tools/memories.bml.filter.all=Ð’Ñе избранное + +/tools/memories.bml.filter.other=Только запиÑи других пользователей + +/tools/memories.bml.filter.own=Только запиÑи Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ "[[user]]" + +/tools/memories.bml.form.filter=Отобрать запиÑи по: + +/tools/memories.bml.form.sort=Сортировать запиÑи по: + +/tools/memories.bml.form.switch=Выбрать + +/tools/memories.bml.login=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы увидеть ваше Избранное, пожалуйÑта, войдите + +/tools/memories.bml.plur_entry=вÑего [[num]] + +/tools/memories.bml.sort.description=ОпиÑанию + +/tools/memories.bml.sort.journal=Дневнику + +/tools/memories.bml.sort.orderadded=Времени Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + +/tools/memories.bml.title.keyword=Избранные запиÑи Ñ ÐºÐ»ÑŽÑ‡ÐµÐ²Ñ‹Ð¼ Ñловом [[keyword]] + +/tools/memories.bml.title.memorable=Избранные запиÑи + +/tools/memories.bml.uncategorized=ÐеупорÑдоченное + +/update.bml.altpost=Ð’ какой дневник помеÑтить запиÑÑŒ: + +/update.bml.btn.preview=Предварительный проÑмотр + +/update.bml.btn.update=ÐапиÑать в дневник + +/update.bml.currmood=Текущее наÑтроение: + +/update.bml.currmusic=Играет музыка: + +/update.bml.date=Дата: + +/update.bml.default=по умолчанию + +/update.bml.defaultjournal=([[user]]) - по умолчанию + +/update.bml.error.cantpost=Извините, в данный момент вы не можете добавить. + +/update.bml.error.disabled=С вашим типом аккаунта добавлÑÑ‚ÑŒ запиÑи нельзÑ. + +/update.bml.error.disabled.title=Добавление запиÑей отключено + +/update.bml.error.login=Ошибка при входе: + +/update.bml.error.nopass=Введите пароль + +/update.bml.error.update=Ошибка при запиÑи: + +/update.bml.event=Событие: + +/update.bml.full=Полный вариант + +/update.bml.htmlokay.norich=(Ð”Ð»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¾ иÑпользовать теги HTML. Учтите, что новые Ñтроки будут автоматичеÑки отформатированы тегом <br>) + +/update.bml.htmlokay.rich=(Ð”Ð»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¾ иÑпользовать теги HTML (учтите, что новые Ñтроки будут автоматичеÑки отформатированы тегом <br>). ЕÑли Ð’Ñ‹ не знаете HTML - можете иÑпользовать наш визуальный редактор) + +/update.bml.htmlokay.rte_nosupport=(Извините, ваш браузер не поддерживает rich text формат) + +/update.bml.localtime=МеÑтное времÑ: + +/update.bml.loggedinas=Ð’Ñ‹ на Ñайте под именем [[user]].
    Чтобы Ñделать запиÑÑŒ под другим именем, нажмите здеÑÑŒ. + +/update.bml.loggingin=Вход на Ñервер... + +/update.bml.noneother=ПуÑто, или другое: + +/update.bml.note=Обратите внимание: Ð’Ñ€ÐµÐ¼Ñ Ð¸ дата, напиÑанные выше "по умолчанию", выбираютÑÑ Ð½Ð°ÑˆÐ¸Ð¼ Ñервером. Поправьте их, чтобы учеÑÑ‚ÑŒ вашу временную зону. + +/update.bml.opt.backdate=ЗапиÑÑŒ задним чиÑлом: + +/update.bml.opt.backdate.about=не показывать в лентах друзей + +/update.bml.opt.defpic=(по умолчанию) + +/update.bml.opt.nocomments=Отменить комментарии: + +/update.bml.opt.noemail=Ðе приÑылать комментарии: + +/update.bml.opt.noformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/update.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/update.bml.options=ÐаÑтройки + +/update.bml.other=Другое: + +/update.bml.password=Пароль: + +/update.bml.picture=Картинка: + +/update.bml.preview.header=Предварительный проÑмотр + +/update.bml.preview.text=Так ваша запиÑÑŒ будет выглÑдеть в дневнике. ИÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ„Ð¾Ñ€Ð¼Ñƒ внизу, вы можете редактировать запиÑÑŒ или отоÑлать ее в нынешнем виде. + +/update.bml.security.custom=Выборочно... + +/update.bml.security.friends=Ð”Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹ + +/update.bml.security.head=Уровень доÑтупа: + +/update.bml.security.private=Личное + +/update.bml.security.public=Открытое + +/update.bml.servermsg=КÑтати, у Ñервера еÑÑ‚ÑŒ Ð´Ð»Ñ Ð²Ð°Ñ Ñообщение: + +/update.bml.simple=Это упрощенный вид Ñтраницы. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… возможноÑтей по редактированию ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð°Ð¶Ð¼Ð¸Ñ‚Ðµ здеÑÑŒ. + +/update.bml.spellchecked=Ваша запиÑÑŒ Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ð¾Ð¹ орфографией: + +/update.bml.subject=Тема: (необÑзательно) + +/update.bml.timeformat=24-чаÑовое Ð²Ñ€ÐµÐ¼Ñ + +/update.bml.title=ÐапиÑать + +/update.bml.title.readonly=Только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ + +/update.bml.update.alternate=ЕÑли вы не хотите уÑтановить программу-клиент Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ компьютера, или еÑли Ñ‚Ð°ÐºÐ°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° не Ñоздана, вы можете обновлÑÑ‚ÑŒ ваш дневник на Ñтой Ñтранице. Ее же можно иÑпользовать, когда вы в отъезде или на чужом компьютере. ЕÑли у Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¹ аккаунт, вы можете обновить ваш дневник по email, по телефону или Ñоздать опроÑÑ‹. + +/update.bml.update.head=Добавить запиÑÑŒ в дневник... + +/update.bml.update.success=ЗапиÑÑŒ обновлена. Ð’Ñ‹ можете увидеть ваш обновленный дневник здеÑÑŒ. + +/update.bml.updating=Отправка запиÑи... + +/update.bml.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/uploadpic.bml.error.unsupportedtype=Данный тип файлов ([[filetype]]) не поддерживаетÑÑ. Картинки должны быть в формате GIF, PNG или JPG. ПрактичеÑки любой графичеÑкий редактор может преобразовать вашу картинку к одному из Ñтих типов. + +/userinfo.bml.about.comm=ОпиÑание: + +/userinfo.bml.about.user=БиографиÑ: + +/userinfo.bml.body.leave=Ð’Ñ‹ можете покинуть ÑообщеÑтво в любое времÑ. + +/userinfo.bml.comminfo.body=Ðиже указана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве "[[commname]]". + +/userinfo.bml.comminfo.name=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/userinfo.bml.date.never=Ðикогда. + +/userinfo.bml.error.malfname=Ðеправильно ÑоÑтавленное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: Ñлишком длинное или Ñодержит недопуÑтимые знаки + +/userinfo.bml.error.notloggedin=ЕÑли вы хотите увидеть Ñвою Ñтраницу Ñ Ð¿ÐµÑ€Ñональной информацией, вам надо войти в ÑиÑтему. + +/userinfo.bml.fbpictures.lessthan=Открытых Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ¸ -- менее [[count]] + +/userinfo.bml.fbpictures.over=Открытых Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ¸ -- более [[count]] + +/userinfo.bml.friendof.comm=Читают: + +/userinfo.bml.friendof.hidden=(Ñкрыто) + +/userinfo.bml.friendof.syndreadcount=КоличеÑтво читателей + +/userinfo.bml.friendof.user=Ð’ друзьÑÑ… у: + +/userinfo.bml.friends.comm=УчаÑтники + +/userinfo.bml.friends.user=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/userinfo.bml.label.addbuddy=Добавить + +/userinfo.bml.label.adduser=Добавить + +/userinfo.bml.label.alsofriendof=Также в друзьÑÑ… у: + +/userinfo.bml.label.birthdate=Дата рождениÑ: + +/userinfo.bml.label.clientsused=ИÑпользованные клиенты: + +/userinfo.bml.label.comments=Комментариев: + +/userinfo.bml.label.composted=ÐапиÑано: [[num]] - + +/userinfo.bml.label.comreceived=Получено: [[num]] + +/userinfo.bml.label.datecreated=Дата ÑозданиÑ: + +/userinfo.bml.label.dateupdated=ПоÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ: + +/userinfo.bml.label.email=ÐÐ´Ñ€ÐµÑ e-mail: + +/userinfo.bml.label.frcommunity=СообщеÑтва + +/userinfo.bml.label.frpeople=Люди + +/userinfo.bml.label.frsyndication2=ТранÑлируемые ленты + +/userinfo.bml.label.icquin=Ðомер ICQ: + +/userinfo.bml.label.interests=ИнтереÑÑ‹ + +/userinfo.bml.label.interests.modifyyours=Изменить Ð²Ð°ÑˆÐ¸ + +/userinfo.bml.label.interests.removesome=Удалить + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] интереÑов не показано + +/userinfo.bml.label.journalentrs=ЗапиÑей в дневнике: + +/userinfo.bml.label.location=МеÑтоположение: + +/userinfo.bml.label.memberof=СоÑтоит в + +/userinfo.bml.label.memories=Избранное: + +/userinfo.bml.label.moredetails=(подробнее...) + +/userinfo.bml.label.msnusername=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ MSN: + +/userinfo.bml.label.mutual=Взаимные друзьÑ: + +/userinfo.bml.label.name=ИмÑ: + +/userinfo.bml.label.nofriends=ОтÑутÑтвуют. + +/userinfo.bml.label.post=ÐапиÑать в "[[journal]]" + +/userinfo.bml.label.postalt=Сделать новую запиÑÑŒ + +/userinfo.bml.label.reqfinduser=Только пользователи Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸ÐµÐ¹ "findpriv" могут иÑкать пользователей по идентификатору. + +/userinfo.bml.label.searchjournal=ПоиÑк в Ñтом дневнике + +/userinfo.bml.label.sendmessage=ПоÑлать Ñообщение + +/userinfo.bml.label.shared=ДоÑтуп на добавление запиÑей: + +/userinfo.bml.label.supportpoints=Баллы помощника + +/userinfo.bml.label.syndicatedfrom=ТранÑлируетÑÑ Ð¸Ð·: + +/userinfo.bml.label.syndicatedstatus=СоÑтоÑние транÑлÑции: + +/userinfo.bml.label.textmessage=ТекÑтовое
    Ñообщение
    : + +/userinfo.bml.label.todo=СпиÑок задач + +/userinfo.bml.label.user=Пользователь: + +/userinfo.bml.label.viewfriends=СпиÑок друзей + +/userinfo.bml.label.viewmembers=СпиÑок учаÑтников + +/userinfo.bml.label.website=Сайт: + +/userinfo.bml.label.yahooid=Ð˜Ð¼Ñ Ð² Yahoo!: + +/userinfo.bml.membership.body=Чтобы вÑтупить в Ñто ÑообщеÑтво, нажмите здеÑÑŒ. + +/userinfo.bml.membership.paidmembers=ПоÑле того как ваш платный аккаунт Ñоздан, вы можете вÑтупить в ÑообщеÑтво платных пользователей. + +/userinfo.bml.memories.entries=[[count]] запиÑей + +/userinfo.bml.memories.entry=[[count]] запиÑÑŒ + +/userinfo.bml.monitor.comm=Добавить ÑообщеÑтво в вашу ленту друзей + +/userinfo.bml.monitor.user=Добавить Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² вашу ленту друзей + +/userinfo.bml.nonexist.body=ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ [[user]] не ÑущеÑтвует. Ð’Ñ‹ уж извините. + +/userinfo.bml.nonexist.name=ÐеизвеÑтный пользователь + +/userinfo.bml.sendmessage.body=ПоÑлать [[user]] текÑтовое Ñообщение
    на его/ее мобильный телефон/пейджер. + +/userinfo.bml.syn.last.never=Ðикогда + +/userinfo.bml.syn.lastcheck=ПоÑледнÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.nextcheck=Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.parseerror=Сообщение об ошибке: + +/userinfo.bml.syndinfo.body=ЕÑли вы хотели бы чтобы Ñтатьи Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾, поддерживающего транÑлÑцию, Ñайта поÑвлÑлиÑÑŒ в вашей ленте друзей, добавьте Ñтот дневник к Ñвоему ÑпиÑку друзей. + +/userinfo.bml.syndinfo.name=ТранÑлируемый дневник + +/userinfo.bml.tellafriend=Сообщить другу! + +/userinfo.bml.timeupdate.dayago=один день назад + +/userinfo.bml.timeupdate.daysago=прошло дней: [[num]] + +/userinfo.bml.timeupdate.hourago=один Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´ + +/userinfo.bml.timeupdate.hoursago=прошло чаÑов: [[num]] + +/userinfo.bml.timeupdate.minuteago=одну минуту назад + +/userinfo.bml.timeupdate.minutesago=прошло минут: [[num]] + +/userinfo.bml.timeupdate.secondago=одну Ñекунду назад + +/userinfo.bml.timeupdate.secondsago=прошло Ñекунд: [[num]] + +/userinfo.bml.timeupdate.weekago=одну неделю назад + +/userinfo.bml.timeupdate.weeksago=прошло недель: [[num]] + +/userinfo.bml.title=О пользователе + +/userinfo.bml.title.communityinfo=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/userinfo.bml.title.syndicated=ТранÑлÑционный Ðккаунт + +/userinfo.bml.userinfo.body=Ðиже указана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ пользователе [[username]]. ЕÑли вы -- Ñтот пользователь, вы можете отредактировать её (или выбрать, какую информацию показывать общеÑтвенноÑти) на Ñтранице Редактировать личную информацию. + +/userinfo.bml.userinfo.name=О пользователе + +bml.badcontent.body<< + +При обработке вашего запроÑа произошла одна или неÑколько ошибок. ПoжалуйÑта, вернитеÑÑŒ на предыдущую Ñтраницу, Ñделайте необходимые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ отошлите ваши данные еще раз. +. + +bml.badinput.body=Ваш браузер поÑлал текÑÑ‚, который не ÑвлÑетÑÑ Ñ‚ÐµÐºÑтом в требуемом формате UTF-8. Это могло ÑлучиитьÑÑ Ð¸Ð·-за того, что вы заÑтавили ваш браузер открыть предыдущую Ñтраницу в формате, отличном отUTF-8. Или же Ñто может быть вызвано неполадкой в браузере. ЕÑли вы не можете ничего Ñделать в Ñтой Ñитуации, напишите нам. + +bml.badinput.head=Ðекорректный Юникод + +bml.needlogin.body2=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы увидеть Ñту Ñтраницу, вы должны войти в дневник. + +bml.needlogin.head=Ðеобходимо войти + +BML.parse_multipart.parse=Ошибка при ÑинтакÑичеÑком разборе загруженной на Ñервер информации + +BML.parse_multipart.toolarge=Загрузка на Ñервер Ñлишком большого объема информации + +BML.parse_multipart.unknowntype=ÐеизвеÑтный тип информации + +bml.requirepost=По ÑоображениÑм безопаÑноÑти Ñта Ñтраница требует метода POST, а не GET. ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ñ€ÐµÐ·Ð¾Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½Ð° делать то, что вы попыталиÑÑŒ Ñделать, напишите нам, + +btn.search=ПоиÑк + +crumb.about=О LiveJournal + +crumb.abusereport=ÐапиÑать по инÑтанциÑм о нарушениÑÑ… правил (вы точно Ñтого хотите?) + +crumb.acctfeatures=ВозможноÑти разных типов аккаунтов + +crumb.acctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° + +crumb.addfriend=Добавить друга + +crumb.addtodo=Добавить в "Сделать" (To-Do) + +crumb.advcustomize=Выбрать дополнительные наÑтройки S2 + +crumb.advsearch=Продвинутый + +crumb.banners=Баннеры + +crumb.birthdays=Дни рождений + +crumb.changepass=Изменить пароль + +crumb.comminvites=ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð² ÑообщеÑтва + +crumb.commmembers=Члены ÑообщеÑтва + +crumb.commpending=Ожидают зачиÑÐ»ÐµÐ½Ð¸Ñ + +crumb.commsearch=ПоиÑк ÑообщеÑтва + +crumb.commsentinvites=ПоÑланные ÐŸÑ€Ð¸Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ + +crumb.community=Центр СообщеÑтв + +crumb.contract=Ðаш Ñоциальный контракт + +crumb.contributors=УчаÑтники + +crumb.createcommunity=Создать СообщеÑтво + +crumb.createjournal=Создать дневник + +crumb.createstyle=Создать Ñтиль + +crumb.customize=ÐаÑтройки S2 + +crumb.delcomment=Удалить комментарий + +crumb.editentries=Редактировать запиÑи + +crumb.editentries_do=Редактировать запиÑÑŒ + +crumb.editfriendgrps=Редактировать группы друзей + +crumb.editfriends=Редактировать ÑпиÑок друзей + +crumb.editinfo=О пользователе + +crumb.editpics=Кaртинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +crumb.editstyle=Редактировать Ñтиль + +crumb.emailgateway=Email шлюз + +crumb.emailmanage=Управление email + +crumb.encodings=О кодировках + +crumb.export=ПеренеÑти дневник + +crumb.faq=ВопроÑÑ‹ и ответы + +crumb.feedstersearch=ПоиÑк в дневнике + +crumb.filemanager=File Manager + +crumb.friends= Редактировать друзей + +crumb.friendsfilter=Фильтр друзей + +crumb.guidingprinciples=РуководÑщие принципы + +crumb.home=Домой + +crumb.itsfree=БеÑплатно? + +crumb.joincomm=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +crumb.latestposts=Свежие запиÑи + +crumb.layerbrowse=ПроÑмотр общедоÑтупного ÑÐ»Ð¾Ñ + +crumb.leavecomm=Выйти из ÑообщеÑтва + +crumb.legal=ÐŸÑ€Ð°Ð²Ð¾Ð²Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +crumb.linkslist=Ваши закладки + +crumb.login=Вход + +crumb.logout=Выход + +crumb.lostinfo=УтерÑÐ½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +crumb.manage=Управление аккаунтами + +crumb.managecommunity=Управление ÑообщеÑтвом + +crumb.meme=ПоиÑк по meme + +crumb.memories=Избранное + +crumb.moderate=Модерирование ÑообщеÑтва + +crumb.modify=ÐаÑтройки дневника + +crumb.moodlist=Показать наÑтроение + +crumb.news=ÐовоÑти + +crumb.paidaccounts=Платные аккаунты + +crumb.paidacctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ аккаунта + +crumb.phonepostsettings=ЗапиÑÑŒ по телефону + +crumb.popfaq=ЧаÑто задаваемые вопроÑÑ‹ + +crumb.preview=ПроÑмотр внешнего вида + +crumb.privacy=Положение о конфиденциальноÑти + +crumb.register=Подтвердить email + +crumb.search=ПоиÑк + +crumb.searchinterests=По интереÑам + +crumb.searchregion=По региону + +crumb.seeoverrides=Показать перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +crumb.setpgpkey=Открытый ключ PGP + +crumb.singles=Одинокие, Желающие ПознакомитьÑÑ + +crumb.singlesopts=Изменить доÑтупноÑÑ‚ÑŒ + +crumb.singlessearch=ПоиÑк вашей половинки + +crumb.sitemap=Карта Ñайта + +crumb.siteopts=Показать наÑтройки + +crumb.sizechart=Таблица размеров + +crumb.stats=СтатиÑтика + +crumb.styles=Стили + +crumb.suggestions=Генератор предложений + +crumb.suggview=ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + +crumb.support=Поддержка + +crumb.supportact=ЗапроÑите ответ + +crumb.supportappend=Добавить к запроÑу + +crumb.supporthelp=Форум ЗапроÑов + +crumb.supportnotify=ÐаÑтройки ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ + +crumb.supportscores=Ðаибольшее количеÑтво очков + +crumb.supportsubmit=ПоÑлать Ð·Ð°Ð¿Ñ€Ð¾Ñ + +crumb.textmessage=ПоÑлать текÑтовое Ñообщение + +crumb.themes=ПроÑмотреть гаммы + +crumb.todo=СпиÑок задaч + +crumb.tos=Правила + +crumb.transfercomm=Передать СообщеÑтво + +crumb.unsubscribe=Отменить подпиÑку + +crumb.update=ÐапиÑать в дневник + +crumb.utf8convert=Конвертер UTF-8 + +crumb.yourlayers=Ваши Ñлои + +crumb.yourstyles=Ваши Ñтили + +date.day.friday.long=ПÑтница + +date.day.friday.short=Пт + +date.day.monday.long=Понедельник + +date.day.monday.short=Пн + +date.day.saturday.long=Суббота + +date.day.saturday.short=Сб + +date.day.sunday.long=ВоÑкреÑенье + +date.day.sunday.short=Ð’Ñ + +date.day.thursday.long=Четверг + +date.day.thursday.short=Чт + +date.day.tuesday.long=Вторник + +date.day.tuesday.short=Ð’Ñ‚ + +date.day.wednesday.long=Среда + +date.day.wednesday.short=Ср + +date.month.april.long=Ðпрель + +date.month.april.short=Ðпр + +date.month.august.long=ÐвгуÑÑ‚ + +date.month.august.short=Ðвг + +date.month.december.long=Декабрь + +date.month.december.short=Дек + +date.month.february.long=Февраль + +date.month.february.short=Фев + +date.month.january.long=Январь + +date.month.january.short=Янв + +date.month.july.long=Июль + +date.month.july.short=Июл + +date.month.june.long=Июнь + +date.month.june.short=Июн + +date.month.march.long=Март + +date.month.march.short=Мар + +date.month.may.long=Май + +date.month.may.short=Май + +date.month.november.long=ÐоÑбрь + +date.month.november.short=ÐÐ¾Ñ + +date.month.october.long=ОктÑбрь + +date.month.october.short=Окт + +date.month.september.long=СентÑбрь + +date.month.september.short=Сен + +dystopia.btn.login=ВХОД + +dystopia.hello_anonymous=Добро пожаловать на [[sitename]]! + +dystopia.hello_loggedin=Привет, [[username]]! + +dystopia.nav.contact=Контактный Ð°Ð´Ñ€ÐµÑ + +dystopia.nav.createjournal=Создать Журнал + +dystopia.nav.developer=Разработчикам + +dystopia.nav.editentries=Редактировать + +dystopia.nav.editfriends=Ваши Ð´Ñ€ÑƒÐ·ÑŒÑ + +dystopia.nav.editpassword=Ваш пароль + +dystopia.nav.editpics=Ваши картинки + +dystopia.nav.editstyle=Свой Ñтиль + +dystopia.nav.faq=Справка + +dystopia.nav.findcomm=По ÑообщеÑтву + +dystopia.nav.finddir=ПоиÑк по каталогу + +dystopia.nav.findint=По интереÑам + +dystopia.nav.findrandom=Случайно + +dystopia.nav.findregion=По региону + +dystopia.nav.home=Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница + +dystopia.nav.journalcalendar=Календарь + +dystopia.nav.journalfriends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +dystopia.nav.journalinfo=О пользователе + +dystopia.nav.journalrecent=Свежие запиÑи + +dystopia.nav.legaltos=Правила + +dystopia.nav.login=Вход + +dystopia.nav.logout=Выход + +dystopia.nav.lostinfo=Ðапомнить пароль + +dystopia.nav.manage=Работать Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°Ð¼Ð¸ + +dystopia.nav.memories=Избранное + +dystopia.nav.modifyjournal=Изменить дневник + +dystopia.nav.news=ÐовоÑти + +dystopia.nav.paidaccts=Оплата + +dystopia.nav.paymentarea=Платежи + +dystopia.nav.personalinfo=ПерÑональные + +dystopia.nav.sitemap=Карта Ñайта + +dystopia.nav.siteopts=ÐаÑтройки Ñайта + +dystopia.nav.support=Задать Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +dystopia.nav.updatejournal=ÐапиÑать + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=130 + +dystopia.navhead.findusers=Ðайти пользователей + +dystopia.navhead.help=Справка и помощь + +dystopia.navhead.journal=Ваш дневник + +dystopia.navhead.settings=Ваши наÑтройки + +dystopia.navhead.welcome=Добро пожаловать! + +dystopia.search.icq=Ðомер ICQ + +dystopia.search.int=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +dystopia.search.region=Регион + +dystopia.searchlj=Ðайти в ЖЖ: + +Email=Email + +email.newacct.subject=Welcome to [[sitename]] + +email.newacct2.body|notes=This string replaces email.newacct.body. You may refer to the old string while translating if you wish. +email.newacct2.body<< +ПоздравлÑем, теперь у Ð’Ð°Ñ ÐµÑÑ‚ÑŒ Дневник на [[sitename]]! + +Чтобы завершить процедуру региÑтрации и подтвердить ваш e-mail, нажмите на ÑÑылку: + +[[regurl]] + +Ваш дневник находитÑÑ Ð¿Ð¾ адреÑу: + +[[siteroot]]/users/[[username]]/ + +или: + +[[siteroot]]/~[[username]]/ + +Вот Ваши Ð¸Ð¼Ñ Ð¸ пароль Ð´Ð»Ñ Ð½Ð°ÑˆÐµÐ³Ð¾ Ñайта: + +ИмÑ: [[username]] +Пароль: [[password]] + +ÐаÑлаждайтеÑÑŒ! + +Команда [[sitename]] +[[siteroot]]/ +. + +entryform.backdated=ЗапиÑÑŒ задним чиÑлом: + +entryform.comment.screening=Скрыть комментарии: + +entryform.comment.settings=ÐаÑтройки комментариев: + +entryform.comment.settings.default=По умолчанию + +entryform.comment.settings.nocomments=Отключено + +entryform.comment.settings.noemail=Ðе поÑылать E-mail + +entryform.date=Дата: + +entryform.date.24hournote=(24 чаÑа) + +entryform.delete=Удалить запиÑÑŒ + +entryform.delete.confirm=Ð’Ñ‹ точно хотите удалить Ñту запиÑÑŒ? + +entryform.deletespam=Удалить и пометить как Ñпам. + +entryform.deletespam.confirm=Ð’Ñ‹ точно хотите удалить Ñту запиÑÑŒ и пометить ее как Ñпам? + +entryform.entry=ЗапиÑÑŒ: + +entryform.format=Форматирование текÑта: + +entryform.format.auto=ÐвтоматичеÑкие + +entryform.format.preformatted=Ðе выполнÑÑ‚ÑŒ + +entryform.htmlokay.norich=(ДопуÑкаютÑÑ Ñ‚Ñги HTML; Ñимволы новой Ñтроки по умолчанию заменÑÑŽÑ‚ÑÑ Ð½Ð° <br>) + +entryform.htmlokay.rich=(ДопуÑкаютÑÑ Ñ‚Ñги HTML; Ñимволы новой Ñтроки по умолчанию заменÑÑŽÑ‚ÑÑ Ð½Ð° <br> -- или иÑпользуйте режим rich text.) + +entryform.htmlokay.rte_nosupport=rte_nosupport=(Извините -- ваш бразуер не поддерживает режим rich text.) + +entryform.mood=ÐаÑтроение: + +entryform.mood.noneother=Ðикакое, или Другое: + +entryform.music=Играет музыка: + +entryform.nojstime.note=Обратите внимание: Ð’Ñ€ÐµÐ¼Ñ Ð¸ дата, напиÑанные выше "по умолчанию", выбираютÑÑ Ð½Ð°ÑˆÐ¸Ð¼ Ñервером. Поправьте их, чтобы учеÑÑ‚ÑŒ вашу временную зону. + +entryform.opt.defpic=(по умолчанию) + +entryform.options=ÐаÑтройки: + +entryform.postto=Отправить в: + +entryform.preview=ПроÑмотр + +entryform.save=Сохранить запиÑÑŒ + +entryform.security=Уровень безопаÑноÑти: + +entryform.spellcheck=Проверить правопиÑание (английÑкое) + +entryform.spellcheck.noerrors=ПравопиÑание в порÑдке + +entryform.spellchecked=Проверил правопиÑание в запиÑи: + +entryform.subject=Тема: + +entryform.tags=Метки: + +entryform.update=Обновить дневник + +entryform.userpics=Иконка Ð´Ð»Ñ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ пользователÑ: + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Ошибка + +error.badpassword=Ðеверный пароль. + +error.code.comm_not_comm=Этот аккаунт не ÑвлÑетÑÑ ÑообщеÑтвом + +error.code.comm_not_found=СообщеÑтво не найдено + +error.code.comm_not_member=Пользователь не ÑвлÑетÑÑ Ñ‡Ð»ÐµÐ½Ð¾Ð¼ данного ÑообщеÑтва + +error.dberror=Произошла ошибка в работе базы данных: + +error.deleted.name=Удалено + +error.deleted.text=Этот дневник был удален. ЕÑли вы [[user]], то у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ 30 дней Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы отменить удаление дневника. ПоÑле 30 дней мы навÑегда удалим Ñодержимое вашего дневника Ñо вÑех наших Ñерверов. + +error.deleted.title=Удаленный аккаунт + +error.expiredchal=Ваше Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ иÑтекло. ПожалуйÑта, загрузитеÑÑŒ еще раз. + +error.invalidauth=Ð’Ñ‹ не можете войти Ñ Ð¿Ð°Ñ€Ð¾Ð»ÐµÐ¼ Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +error.ipbanned=Ваш IP-Ð°Ð´Ñ€ÐµÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ заблокирован (вы Ñлишком много раз подрÑд неудачно пыталиÑÑŒ войти). + +error.malformeduser=Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +error.nobutton=Ðе нажата кнопка? + +error.nodb=База данных временно недоÑтупна. + +error.nodbmaintenance=Эта чаÑÑ‚ÑŒ базы данных временно на обÑлуживании. Попробуйте ещё раз через неÑколько минут. + +error.noentry=Ðет такой запиÑи в дневнике. + +error.nojournal=ÐеизвеÑтный дневник + +error.noremote=Чтобы работать Ñ Ñтой Ñтраницей, вам придётÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ в ÑиÑтему. + +error.procrequest=Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ вашего запроÑа: + +error.purged.name=Удален + +error.purged.text=Этот дневник был удален вмеÑте Ñо вÑем его Ñодержимым. + +error.purged.title=Удаленный аккаунт + +error.suspended.name=Заморожен + +error.suspended.text=Этот дневник был заморожен (временно или навÑегда). ЕÑли вы [[user]], дополнительную информацию вы можете получить в Ñтатье Справки: Мой аккаунт был заморожен! Что Ñ Ð¼Ð¾Ð³Ñƒ Ñделать, чтобы вернуть его? Учтите, что по ÑоображениÑм конфиденциальноÑти [[sitename]] не может обÑуждать причины, по которым аккаунт был заморожен, Ñ ÐºÐµÐ¼ бы то ни было кроме владельца аккаунта. + +error.suspended.title=Замороженный аккаунт + +error.tempdisabled=Временно не работает. + +error.unknownmode=ÐеизвеÑтный режим + +error.usernameinvalid=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñодержит неразрешённые Ñимволы. + +error.usernamelong=Слишком длинное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, макÑимум 15 Ñимволов. + +error.username_notfound=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ найдено + +Help=Помощь + +label.screening.all=Ð’Ñе комментарии + +label.screening.anonymous=Только анонимные + +label.screening.default=По умолчанию + +label.screening.header=Скрыть комментарии: + +label.screening.none=Ðе Ñкрывать ничего + +label.screening.nonfriends=От тех, кто не в ÑпиÑке друзей + +label.security.custom=Выборочно... + +label.security.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +label.security.head=Уровень доÑтупа: + +label.security.maintainers=Смотрители + +label.security.members=Члены + +label.security.private=Личное + +label.security.public=Ð”Ð»Ñ Ð²Ñех + +label.switch.button=Переключить + +label.switch.header=Выбрать дневник + +label.switch.workwith=С каким дневником работать: + +langname.be=БелоруÑÑкий + +langname.da=ДатÑкий + +langname.de=Ðемецкий + +langname.en=ÐнглийÑкий + +langname.en_GB=ÐнглийÑкий (ВеликобританиÑ) + +langname.en_LJ=ÐнглийÑкий (LJ) + +langname.eo=ЭÑперанто + +langname.es=ИÑпанÑкий + +langname.et=ЭÑтонÑкий + +langname.fi=ФинÑкий + +langname.fr=ФранцузÑкий + +langname.ga=ИрландÑкий + +langname.gd=ГальÑкий + +langname.he=Иврит + +langname.hi=Хинди + +langname.hu=ВенгерÑкий + +langname.is=ИÑландÑкий + +langname.it=ИтальÑнÑкий + +langname.ja=ЯпонÑкий + +langname.la=Латынь + +langname.lv=ЛатышÑкий + +langname.ms=МалайÑкий + +langname.nb=ÐорвежÑкий - Bokmal + +langname.nl=ГолландÑкий + +langname.nn=ÐорвежÑкий - Nynorsk + +langname.pl=ПольÑкий + +langname.pt=ПортугальÑкий + +langname.ru=РуÑÑкий + +langname.sb=СибирÑкий + +langname.sv=ШведÑкий + +langname.tr=Турецкий + +langname.uk=УкраинÑкий + +langname.zh=КитайÑкий (упрощенный) + +ljcom.account.feature=ВозможноÑÑ‚ÑŒ + +ljcom.account.feature.email=ÐÐ´Ñ€ÐµÑ email на [[sitename]] + +ljcom.account.feature.full2=ПодробноÑти можно найти на Ñтой Ñтранице. + +ljcom.account.feature.limit=ограничено + +ljcom.account.feature.ownblog=Ваш дневник/веблог + +ljcom.account.feature.search=ПоиÑк по каталогу + +ljcom.account.feature.styles=Создание/редактирование Ñтилей + +ljcom.account.feature.syn=Лента друзей и импорт новоÑтей в формате RSS + +ljcom.account.free=БеÑплатный аккаунт + +ljcom.account.paid=Платный аккаунт + +ljcom.account.paid12=Оплата за 12 меÑÑцев + +ljcom.account.paid2=Оплата за 2 меÑÑца + +ljcom.account.paid6=Оплата за 6 меÑÑцев + +ljcom.accounttype=Тип аккаунта + +ljcom.badpass.email=Ваш пароль не может быть оÑнован на вашем e-mail'е. + +ljcom.badpass.realname=Ваше наÑтоÑщее Ð¸Ð¼Ñ Ð½Ðµ может быть чаÑтью вашего Ð¿Ð°Ñ€Ð¾Ð»Ñ + +ljcom.badpass.username=Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ может быть чаÑтью вашего Ð¿Ð°Ñ€Ð¾Ð»Ñ + +ljcom.menu.upgrade=Изменить тип аккаунта + +ljcom.userinfo.accounttype=Тип аккаунта + +ljcom.userinfo.paiduser=Платный пользователь + +ljcom.userinfo.types.early=Коренной пользователь + +ljcom.userinfo.types.free=БеÑплатный аккаунт + +ljcom.userinfo.types.paid=Платный аккаунт + +ljcom.userinfo.types.paid_early=Платный аккаунт, до Ñтого -- Ранний пользователь + +ljcom.userinfo.types.paid_early_expiring=Платный аккаунт, заканчиваетÑÑ [[paiduntil]], до Ñтого был первопользователем + +ljcom.userinfo.types.paid_expiring=Платный аккаунт, заканчиваетÑÑ [[paiduntil]] + +ljcom.userinfo.types.permanent=ПоÑтоÑнный аккаунт, + +ljcom.userinfo.types.permanent_early=ПоÑтоÑнный аккаунт, до Ñтого -- первопользователь + +ljlib.pageofpages=[[page]]-Ñ Ñтраница из [[total]] + +ljrlook.nav.calendar=ЗапиÑи по днÑм + +ljrlook.nav.changepassword=Пароль + +ljrlook.nav.communities.manage=СообщеÑтва + +ljrlook.nav.create=Создать дневник + +ljrlook.nav.createstyle=Создать Ñтиль + +ljrlook.nav.customize=ÐаÑтроить S2 + +ljrlook.nav.edit=Редактировать... + +ljrlook.nav.editfriends=СпиÑок друзей + +ljrlook.nav.editinfo=ÐаÑтройки + +ljrlook.nav.editjournal=Дневник + +ljrlook.nav.editpics=Картинки + +ljrlook.nav.editstyle=Редактировать Ñтили + +ljrlook.nav.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +ljrlook.nav.frills=Финтифлюшки + +ljrlook.nav.fullupdate=Подробный режим + +ljrlook.nav.hello=Привет + +ljrlook.nav.login=Войти в ÑиÑтему + +ljrlook.nav.logout=Выйти из ÑиÑтемы + +ljrlook.nav.lostinfo=Забыли пароль? + +ljrlook.nav.memories=Избранное + +ljrlook.nav.modify=Вид дневника + +ljrlook.nav.needhelp=Помощь + +ljrlook.nav.news=ÐовоÑти Ñайта + +ljrlook.nav.paidaccounts=Оплата + +ljrlook.nav.recent=ПоÑледние запиÑи + +ljrlook.nav.site=[[sitename]] + +ljrlook.nav.siteopts=Общие наÑтройки + +ljrlook.nav.support=Тех. поддержка + +ljrlook.nav.support.faq=FAQ + +ljrlook.nav.update=ÐапиÑать в дневник + +ljrlook.nav.userinfo=Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +ljrlook.nav.yourjournal=Ваш дневник + +lostinfo.head=Забыли что-нибудь? + +lostinfo.text=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, воÑÑтановите их здеÑÑŒ. + +lynx.nav.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +lynx.nav.help=ТехничеÑÐºÐ°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ° + +lynx.nav.home=Домой + +lynx.nav.login=Войти + +lynx.nav.logout=Выход + +lynx.nav.recent=Свежие запиÑи + +lynx.nav.sitemap=Карта Ñайта + +lynx.nav.siteopts=ПроÑмотреть ÑпиÑок возможноcтей + +lynx.nav.update=ÐапиÑать + +Password=Пароль + +password.max30=Пароль не может быть длинее 30 Ñимволов + +poll.dberror=Ошибка в базе данных: [[errmsg]] + +poll.dberror.items=Ошибка базы данных при вÑтавке: [[errmsg]] + +poll.dberror.questions=Ошибка базы данных при вÑтавке вопроÑов: [[errmsg]] + +poll.error.badmaxlength=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° атрибута на lj-pq Ñ‚Ñгах текÑта должна быть целым чиÑлом от 1 до 255. + +poll.error.badsize=Ðтрибут размера на Ñ‚Ñгах текÑта должен быть целым чиÑлом от 1 до 100. + +poll.error.cantview=Ошибка: вам не разрешен доÑтуп к результатам Ñтого опроÑа. + +poll.error.cantvote=Извините, вам не разрешено голоÑовать в Ñтогм опроÑе. + +poll.error.missingljpoll=Ð’Ñе lj-pq Ñ‚Ñги дожны находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ внешних Ñ‚Ñгов lj-опроÑа. + +poll.error.missingljpq=Ð’Ñе lj-pi Ñ‚Ñги дожны находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ внешних lj-pq Ñ‚Ñгов + +poll.error.nested=Ð’Ñ‹ не можете вкладывать [[tag]] Ñ‚Ñги друг в друга. Может, вы забыли закрыть один из них? + +poll.error.noentry=Ошибка: данный Ð¾Ð¿Ñ€Ð¾Ñ Ð½Ðµ приÑоединен к Ñтой запиÑи в дневнике + +poll.error.noitems=Ð’ нетекÑтовой вопроÑе должна быть по меньшей мере одна чаÑÑ‚ÑŒ. + +poll.error.noitemstext=lj-pq теги типа 'текÑÑ‚' не могут Ñодержать чаÑти опроÑа. + +poll.error.nopollid=Ðе хватает параметра pollid. + +poll.error.noquestions=Ð’ опроÑе должен быть по меньшей мере один вопроÑ. + +poll.error.notext=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы указать о чем вопроÑ, необходим текÑÑ‚ внутри lj-pq Ñ‚Ñга. + +poll.error.pitoolong=ТекÑÑ‚ внутри Ñ‚Ñга должен быть от 1 до 255 знаков. Длина вашего + +poll.error.pollnotfound=Ошибка: Ð¾Ð¿Ñ€Ð¾Ñ #[[num]] не найден + +poll.error.questionnotfound=Ошибка: такого вопроÑа нет. + +poll.error.scalefromlessto=Значение "от" должно быть меньше Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ "до" + +poll.error.scaleincrement=Увеличение шкалы должно быть не меньше 1. + +poll.error.scaletoobig=Ваша шкала вревышает лимит в 20 выборов (до-от)/через >20 + +poll.error.tagnotopen=Ð’Ñ‹ не можете закрыть [[tag]] Ñ‚Ñг, который не был открыт + +poll.error.truncated=...укорочен + +poll.error.unknownpqtype=ÐеизвеÑтный шрифт на lj-pq Ñ‚Ñге. + +poll.error.unlockedtag=Ðезакрытый [[tag]] Ñ‚Ñг + +poll.error.whoview=Можно видеть (whoview) должно быть "вÑем" ('all'), "друзьÑм" ('friends') или "никому"('none') + +poll.error.whovote=Можно голоÑовать (whovote) должно быть "вÑем" ('all') или "друзьÑм" ('friends') + +poll.pollnum=ÐžÐ¿Ñ€Ð¾Ñ #[[num]] + +poll.scaleanswers<< +Среднее [[mean]] Срединное значение: [[median]] Ð¡Ñ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° [[stddev]] + + +. + +poll.security=Открыт:[[whovote]], результаты видны:[[whoview]] + +poll.security.all<< +Ð’Ñем + +. + +poll.security.friends<< +ДрузьÑм + +. + +poll.security.none=Ðикому + +poll.submit=ОтоÑлать Ð¾Ð¿Ñ€Ð¾Ñ + +poll.viewanswers=Показать ответы + +portal.bdays.count.des=По умолчанию показываютÑÑ Ð±Ð»Ð¸Ð¶Ð°Ð¹ÑˆÐ¸Ðµ дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ 5-ти друзей. + +portal.bdays.count.name=Сколько дней Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ + +portal.bdays.portalname=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +portal.bdays.portaltitle=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +portal.login.portalname=Вход + +portal.memories.entriesnoun=запиÑи + +portal.memories.entrynoun=запиÑÑŒ + +portal.memories.portalname=ПамÑтные запиÑи + +portal.memories.portaltitle=ПамÑтные запиÑи + +portal.ministats.active=Пишущих: + +portal.ministats.title=Пользователи + +portal.ministats.total=Ð’Ñего: + +portal.newtolj.name=СÑылки по Ñайту + +portal.popfaq.portalname=10 Ñамых популÑрных вопроÑов Ñправки + +portal.popfaq.portaltitle=10 Ñамых популÑрных вопроÑов Ñправки + +portal.randuser.count.des=По умолчанию будет показан 1 Ñлучайный пользователь, но выможете показать до 10 по вертикали в узких колонках, либо до 5 по горизонтали в широкой колонке. + +portal.randuser.count.name=ЧиÑло Ñлучайных пользователей + +portal.randuser.error.tableempty=Случайных пользователей не найдено. СвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором. + +portal.randuser.hidename.des=По умолчанию выводитÑÑ Ð¸Ð¼Ñ Ñлучайного пользователÑ. Отметьте галочку, еÑли хотите ÑпрÑтать его. + +portal.randuser.hidename.name=Скрыть Ð¸Ð¼Ñ + +portal.randuser.hidepic.des=По умолчанию выводитÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ° Ñлучайного пользователÑ. ЕÑли хотите ÑпрÑтать её, отметьте галочку. + +portal.randuser.hidepic.name=Скрыть картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +portal.randuser.portalname=Случайный пользователь + +portal.randuser.portaltitle=Случайный пользователь + +portal.randuser.portaltitleplural=Случайные пользователи + +portal.recent.error.noentries=ПроÑтите. Ðет запиÑей. + +portal.recent.error.notsetup=Ð’Ñ‹ должны наÑтроить Ñто окно. Ðажмите на Ñимвол плюÑа и выберите дневник, который вы хотели бы видеть в Ñтом окне. + +portal.recent.error.userstatus=Дневник Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð» удалён или заморожен. + +portal.recent.items.description=По умолчанию отображаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ ÑÐ°Ð¼Ð°Ñ Ð¿Ð¾ÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ. + +portal.recent.items.name=Сколько показывать + +portal.recent.journal.description=ЗапиÑи какого дневника вы хотите видеть? + +portal.recent.journal.name=Дневник + +portal.recent.nosubject=(Без темы) + +portal.recent.permlink=СÑылка + +portal.recent.portalname=Свежие запиÑи + +portal.recent.portaltitle=Свежие запиÑи + +portal.recent.showtext.description=По умолчанию отображаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ заголовки + +portal.recent.showtext.name=Показывать текÑÑ‚ + +portal.stats.journalentyest=Вчерашние запиÑи + +portal.stats.portalname=СтатиÑтика Ñайта + +portal.stats.portaltitle=СтатиÑтика + +portal.stats.totalusers=Ð’Ñего пользователей + +portal.update.mode.des=РаÑширенный режим предоÑтавлÑет множеÑтво дополнительных наÑтроек, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ добавлÑÑ‚ÑŒ запиÑи в дневники ÑообщеÑтв, возможноÑÑ‚ÑŒ выбрать текущее наÑтроение, музыку и картинку. ПроÑтой режим удобнее, еÑли вы врÑд ли воÑпользуетеÑÑŒ Ñтими возможноÑÑ‚Ñми и предпочли бы не видеть их ÑовÑем. + +portal.update.mode.full=РаÑширенный + +portal.update.mode.name=Режим + +portal.update.mode.simple=ПроÑтой + +portal.update.portalname=Добавление запиÑи + +portal.update.portaltitle=Добавьте запиÑÑŒ в Ñвой дневник + +protocol.bad_password=Ваш пароль Ñлишком проÑтой, его легко угадать или подобрать. Мы рекомендуем вам Ñменить пароль, в противном Ñлучае ваш дневник может быть взломан. Зайдите на Ñтраницу [[siteroot]]/changepassword.bml , чтобы Ñменить пароль. + +protocol.hello_test=ЗдравÑтвуйте, Пробный Пользователь! + +protocol.mail_bouncing=Ð’ наÑтоÑщий момент ваш e-mail не работает. ПиÑьма, отправленные вам, возвращаютÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾. Чтобы продолжать иÑпользовать [[sitename]], вам нужен работающий e-mail. Зайдите на Ñтраницу [[siteroot]]/support/faqbrowse.bml?faqid=19 , чтобы узнать, как Ñменить Ñвой Ð°Ð´Ñ€ÐµÑ e-mail. + +protocol.modpost=Ваша запиÑÑŒ была помещена в очередь на модерирование. Она будет принÑта или отклонена одним из модераторов ÑообщеÑтва. + +protocol.must_revalidate=Ваш новый e-mail Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть подвержден. Старый был в порÑдке, но поÑкольку вы его Ñменили - вы должны подтвердить новый адреÑ. Ðе Ñделав Ñтого, вы не получите доÑтупа ко вÑем функциÑм [[sitename]]. Подробнее - по адреÑу [[siteroot]]/support/faqbrowse.bml?faqid=11 . + +protocol.not_validated=Ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ðµ был подвержден. Ð’Ñ‹ можете продолжать иÑпользовать [[sitename]], но до тех пор, пока Ð°Ð´Ñ€ÐµÑ Ð½Ðµ подтвержден, вы не получите доÑтупа ко вÑем функциÑм Ñайта. ОбратитеÑÑŒ к инÑтрукции, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° выÑлана вам при Ñоздании дневника, или по адреÑу [[siteroot]]/support/faqbrowse.bml?faqid=11 . + +protocol.old_win32_client=Мы рекомендуем вам обновить клиентÑкую программу на более новую верÑию. Чтобы Ñкачать ее, перейдите на Ñтраницу [[siteroot]]/download/ . + +protocol.readonly=Ваш дневник временно находитÑÑ Ð² режиме запрета запиÑи. Ðекоторые команды будут недоÑтупны в течение неÑкольких минут. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Извините + +talk.anonwrote=Ðекто напиÑал, + +talk.anonwrote_comm=Ðекто напиÑал в [[commlink]], + +talk.btn.preview=ПроÑмотр + +talk.commentpermlink=ÑÑылка + +talk.commentpost=Добавить комментарий + +talk.commentsread=Читать комментарии + +talk.curname_Mood=ÐаÑтроение: + +talk.curname_Music=Музыка: + +talk.error.bogusargs=Ðеверные аргументы + +talk.error.comm_deleted=Комментарий был удалён. + +talk.error.deleted=Этот дневник удалён. + +talk.error.deleted.title=Удалён + +talk.error.mustlogin=Чтобы Ñмотреть Ñту защищённую запиÑÑŒ, вы должны войти в ÑиÑтему под Ñвоим именем и паролем. + +talk.error.nocomment=Комментарий не ÑущеÑтвует. + +talk.error.noentry=Ðет такой запиÑи. + +talk.error.nojournal=Ошибка: по аргументам невозможно уÑтановить дневник. + +talk.error.nosuchjournal=Ðет такого дневника + +talk.error.notauthorised=У Ð²Ð°Ñ Ð½ÐµÑ‚ полномочий Ñмотреть Ñту защищённую запиÑÑŒ. + +talk.error.suspended=Этот дневник/комментатор заморожен. + +talk.error.suspended.title=Заморожен + +talk.parentlink=Уровень выше + +talk.readsimilar=Читать похожие дневникьные запиÑи: + +talk.replytothis=Ответить + +talk.somebodywrote=Пишет [[realname]] ([[userlink]]) + +talk.somebodywrote_comm=Пишет [[realname]] ([[userlink]]) в [[commlink]] + +talk.spellcheck=Проверка правопиÑÐ°Ð½Ð¸Ñ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ñмотра + +talk.threadlink=Ветвь диÑкуÑÑии + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_russian + +Username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +userpic.inactive=Ðеактивна + +xcolibur.greeting.anon=Добро пожаловать! + +xcolibur.greeting.logged_in=Привет, [[name]]! [[logout]] + +xcolibur.login=Вход + +xcolibur.logout=Выход + +xcolibur.nav.about=О Ñайте + +xcolibur.nav.about.general=ÐžÐ±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +xcolibur.nav.about.paidaccounts=Оплата + +xcolibur.nav.about.sitenews=ÐовоÑти + +xcolibur.nav.about.stats=СтатиÑтика + +xcolibur.nav.footer.sitemap=Карта Ñайта + +xcolibur.nav.help=Помощь + +xcolibur.nav.help.ask=Задать Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +xcolibur.nav.help.contact=Контакты и Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +xcolibur.nav.help.faq=Справка + +xcolibur.nav.help.lostpassword=Забыли пароль? + +xcolibur.nav.home=Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница + +xcolibur.nav.journal=Дневник + +xcolibur.nav.journal.archive=Календарь + +xcolibur.nav.journal.edit.entries=Редактировать запиÑи + +xcolibur.nav.journal.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +xcolibur.nav.journal.info=О пользователе + +xcolibur.nav.journal.memories=Избранное + +xcolibur.nav.journal.recent=Свежие запиÑи + +xcolibur.nav.journal.update=ÐапиÑать + +xcolibur.nav.manage=Редактировать + +xcolibur.nav.manage.community=СообщеÑтва + +xcolibur.nav.manage.customize=Оформление + +xcolibur.nav.manage.entries=ЗапиÑи + +xcolibur.nav.manage.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +xcolibur.nav.manage.info=О пользователе + +xcolibur.nav.manage.password=Сменить пароль + +xcolibur.nav.manage.pics=Картинки + +xcolibur.nav.manage.styles=Стили + +xcolibur.nav.search=ПоиÑк + +xcolibur.nav.search.directory=По региону + +xcolibur.nav.search.directory.search=По каталогу + +xcolibur.nav.search.interests=По интереÑам + +xcolibur.nav.search.random=Случайно + +xcolibur.nav.siteopts=ÐаÑтройки Ñайта + +xcolibur.nav.title=БыÑтрый переход: + +xcolibur.nav.welcome=Добро пожаловать + +xcolibur.nav.welcome.create=Создать дневник + +xcolibur.nav.welcome.login=Вход + +xcolibur.nav.welcome.update=Добавить запиÑÑŒ + +xcolibur.search=Ðайти на [[sitename]]: + +xcolibur.search.category=Что именно: + +xcolibur.search.icq=Ðомер ICQ + +xcolibur.search.int=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +xcolibur.search.region=Регион + +xcolibur.upgrade=Стань платным пользователем + diff --git a/local/bin/upgrading/s2layers-local.dat b/local/bin/upgrading/s2layers-local.dat new file mode 100755 index 0000000..6f9e198 --- /dev/null +++ b/local/bin/upgrading/s2layers-local.dat @@ -0,0 +1,39 @@ +################################################################ +# LiveJournal.com's non-free (not GPL) layers. You can use the +# source to learn from, but not copy. +################################################################ +# base filename layer type parent + +3column/layout layout core1 +3column/themes theme+ 3column/layout + +anovelconundrum/layout layout core1 +anovelconundrum/themes theme+ anovelconundrum/layout + +boxer/layout layout core1 +boxer/themes theme+ boxer/layout + +component/layout layout core1 +component/themes theme+ component/layout + +cuteness/layout layout core1 + +flexiblesquares/layout layout core1 +flexiblesquares/themes theme+ flexiblesquares/layout + +nebula/layout layout core1 +nebula/themes theme+ nebula/layout + +opal/layout layout core1 +opal/themes theme+ opal/layout + +smoothsailing/layout layout core1 +smoothsailing/themes theme+ smoothsailing/layout + +tranquilityii/layout layout core1 +tranquilityii/themes theme+ tranquilityii/layout + +unearthed/layout layout core1 +unearthed/themes theme+ unearthed/layout + +s2layers-ljcomint.dat INCLUDE diff --git a/local/bin/upgrading/s2layers/3column/layout.s2 b/local/bin/upgrading/s2layers/3column/layout.s2 new file mode 100755 index 0000000..befd9b0 --- /dev/null +++ b/local/bin/upgrading/s2layers/3column/layout.s2 @@ -0,0 +1,1102 @@ +layerinfo "type" = "layout"; +layerinfo "name" = "3 column"; +layerinfo author_name = "Louise (unfloopy)"; +layerinfo author_email = "unfloopy@gmail.com"; +layerinfo des = "3 column layout by Louise (/~unfloopy)."; +layerinfo redist_uniq = "3column/layout"; + +################################## PROPERTIES #################################### + +propgroup prez = "Presentation"; +propgroup prez { + property bool show_entry_userpic { des = "Always display userpic?"; } + property use use_shared_pic; + property use view_entry_disabled; + property int page_recent_items { des = "Recent Entries: Number of Posts"; } + set page_recent_items = 10; + property int page_friends_items{ des = "Friends Page: Number of Posts"; } + set page_friends_items= 20; + set show_entry_userpic = true; +} + +propgroup text = "Text"; +propgroup text { + property string t_forward { des = "Entries Navigation: Forward link"; } + set t_forward = " forward >"; + property string t_back { des = "Entries Navigation: Back link"; } + set t_back = "< back "; + property string t_post_comment{ des = "Entries Navigation: Post A Comment text"; } + set t_post_comment= "reply"; + property string t_reply_back{ des = "Entries Navigation: Comments text"; } + set t_reply_back= "comments"; + property string t_perma{ des = "Entries Navigation: Perma Link text"; } + set t_perma= "link"; + property string t_divider { des = "Entries Navigation: Links divider"; } + set t_divider = " "; + property string t_comment_reply{ des = "Comments Navigation: Reply text"; } + set t_comment_reply= "reply"; + property string t_read_comments{ des = "Comments Navigation: Read Comments"; } + set t_read_comments= "#"; + property string t_view_recent{ des = "Navigation Bar: The Recent Entries Item"; } + set t_view_recent = "recent"; + property string t_view_archive{ des = "Navigation Bar: The Archive Item"; } + set t_view_archive= "archive"; + property string t_view_userinfo { des = "Navigation Bar: The Userinfo Item"; } + set t_view_userinfo = "userinfo"; + property string t_view_friends{ des = "Navigation Bar: The Friends Item"; } + set t_view_friends= "friends"; + property string t_nosubject{ des = "No Subject Text"; } + set t_nosubject= "(no subject)"; + property string t_noentries_day{ des = "Text for a day without posts"; } + set t_noentries_day= "I didn't post on this day. Sorry!"; + property string t_meta_music{ des = "Music Text"; } + set t_meta_music= "current song"; + property string t_meta_mood { des = "Mood Text"; } + set t_meta_mood= "current mood"; + property string t_view_month{ des = "Archive Navigation: View Subjects link text"; } + set t_view_month= "view all"; + property string t_read_comments_friends{ des = "Friends Page: Read Comments"; } + set t_read_comments_friends= "#"; + property string links_header { des = "Links header"; } + set links_header = "links"; + property string about_title { des = "About box title"; } + set about_title= "about"; + property string nav_title { des = "Navigation title"; } + set nav_title= "navigate"; + property string blurb_title { des = "Blurb Title"; note = "Only used if you enter some blurb text below."; } + set blurb_title= "blurb"; + property string blurb_text { des = "Blurb Text"; + note = "You can write here about anything you want. It'll be displayed in a box on your journal pages."; } + set blurb_text= ""; + +} + +propgroup images = "Images"; +propgroup images { + property string bg_image { des = "Background Image URL [optional]"; } + set bg_image = ""; + property string bg_repeat { des = "Background Image Repeat"; values = "repeat|Tile image|no-repeat|Do not tile image"; } + set bg_repeat = "repeat"; + property string header_image { des = "Header: Image URL [optional]"; note = "If you set this, you must also enter the height of your image below."; } + set header_image = ""; + property string header_height { des = "Header: Height"; note = "You must set this if you've entered a header image URL above."; } + set header_height = "0px"; + property string i_comment { des = "Icon: Comments"; note = "If you don't set this, a default image will be used."; } + set i_comment = ""; + property string i_perma { des = "Icon: PermaLink"; note = "If you don't set this, a default image will be used."; } + set i_perma = ""; + property string i_mem { des = "Icon: Add To Memories"; note = "If you don't set this, a default image will be used."; } + set i_mem = ""; + property string i_leave { des = "Icon: Leave A Comment"; note = "If you don't set this, a default image will be used."; } + set i_leave = ""; + property string i_edit { des = "Icon: Edit Entry"; note = "If you don't set this, a default image will be used."; } + set i_edit = ""; +} + +propgroup stylesheet = "Styles"; +propgroup stylesheet { + property string font_size { des = "Overall: Text Size"; } + set font_size = "8pt"; + property string font_family { des = "Overall: Font Family"; } + set font_family = "Arial"; + property string link_weight { des = "Overall: Link Weight"; values = "normal|Normal|bold|Bold"; } + set link_weight = "normal"; + property string link_side_w { des = "Sidebar: Link weight"; values = "normal|Normal|bold|Bold"; } + set link_side_w = "normal"; + property string side_h_size { des = "Sidebar: Header Font Size"; } + set entries_size = "9pt"; + property string entries_size { des = "Entries: Text Size"; } + set c_sub_size = "10pt"; + property string sub_size { des = "Entries: Subject Text Size"; } + set side_h_size = "13px"; + property string c_sub_size { des = "Comments: Subject Text Size"; } + set sub_size = "15pt"; +} + +propgroup colors = "Color"; +propgroup colors { + property Color color_bg { des = "Background Color"; } + set color_bg = "#E6CABE"; + property Color font_color { des = "Overall: Font Color"; } + set font_color = "#4B3730"; + property Color link_color { des = "Overall: Link Color"; } + set link_color = "#78534B"; + property Color link_hover { des = "Overall: Link Hover Color"; } + set link_hover = "#78534B"; + property Color link_side { des = "Sidebar: Link color"; } + set link_side = "#4B3730"; + property Color link_side_h { des = "Sidebar: Link hover color"; } + set link_side_h = "#4B3730"; + property Color side_bg { des = "Sidebar: Background color"; } + set side_bg = "#E6CABE"; + property Color side_t_color { des = "Sidebar: Text color"; } + set side_t_color = "#4B3730"; + property Color side_border { des = "Sidebar: Borders"; } + set side_border = "#DAB5AC"; + property Color side_h_color { des = "Sidebar: Header Color"; } + set side_h_color = "#333333"; + property Color side_h_border { des = "Sidebar: Header Border"; } + set side_h_border = "#333333"; + property Color side_h_bg { des = "Sidebar: Header Background"; } + set side_h_bg = "#DAB5AC"; + property Color entries_bg { des = "Entries: Background color"; } + set entries_bg = "#E6CABE"; + property Color entries_border { des = "Entries: Border color"; } + set entries_border = "#DAB5AC"; + property Color button_bg { des = "Entries: Buttons background"; } + set button_bg = "#E6CABE"; + property Color button_bg_h { des = "Entries: Buttons Background hover"; } + set button_bg_h = "#ECD7C7"; + property Color entries_font_color { des = "Entries: Font Color"; } + set entries_font_color = "#4B3730"; + property Color sub_color { des = "Entries: Subject Color"; } + set sub_color = "#78534B"; + property Color c_sub_color { des = "Comments: Subject Text Color"; } + set c_sub_color = "#4B3730"; + property Color c_sub_bg { des = "Comments: Subject Background"; } + set c_sub_bg = "#DAB5AC"; +} + +set tags_aware = true; +property string i_tags { des = "Icon: Edit Tags"; } + +####################################### STYLESHEET ####################################### + +function print_stylesheet () {""" +body { background: $*color_bg; font: $*font_size $*font_family; color: $*font_color; +"""; if (clean_url($*bg_image) != "") { + """ background-image: url('$*bg_image'); + background-repeat: $*bg_repeat; +"""; } """ } +a { color: $*link_color; font-weight: $*link_weight; } +a:hover { color: $*link_hover; font-weight: $*link_weight; } +h1{ color: $*sub_color; font-size: $*sub_size; text-align:left; padding:5px; margin:0px; border-bottom: 1px dashed $*entries_border; } +h2{ border: 1px solid $*side_h_border; font-size: $*side_h_size; text-align:center; margin:3px 0px; padding:0px; background-color: $*side_h_bg; color: $*side_h_color; } +h3{ color: $*sub_color; text-align:left; font: bold arial; padding:5px; margin:0px; border-top: solid 1px $*entries_border;} +ul.links{ margin: 1px 0px; padding: 3px; color: $*side_t_color; list-style-type:none; } +li.links { margin-left: 5px; } +li.links a{ text-decoration:none; } +li.links_header{ font: 11px; border-bottom: 1px solid $*side_t_color; padding-top:7px; } + +#container{position:absolute; top: $*header_height;} +#leftbar{ position:absolute; top: 10px; left: 10px; width: 170px;} +#rightbar{ position:absolute; top: 10px; right: 0px; width: 170px;} +#leftbar a, #rightbar a {color: $*link_side; font-weight: $*link_side_w;} +#leftbar a:hover, #rightbar a:hover {color: $*link_side_h; } +#entries{ position:relative; margin: 10px 170px 10px 180px; text-align:center; background: $*entries_bg; border: 3px double $*entries_border; padding: 10px; } +#readme { text-align:justify; padding: 2px; } +#header { position:absolute; width: 100%; top: 0px; left: 0px; height: $*header_height; +"""; if (clean_url($*header_image) != "") { + """ background-image: url('$*header_image'); + background-repeat: no-repeat; background-position: center; +"""; } """ } + +div.entrylinks { font: 8pt Verdana; text-align:right; padding:2px 10px 2px 10px; line-height:20px; margin-bottom:0px; margin-top:5px; border-top: 1px dashed $*entries_border; } +div.entrylinks a { background-color: $*button_bg; text-decoration:none; margin:2px; padding:2px; } +div.entrylinks a:hover {background-color: $*button_bg_h;} +div.entrylinks img { border:0px; text-decoration:none; } +div.entry{ margin-bottom:35px;} + +.entrytext{ font: $*entries_size Arial; text-align:justify; color: $*entries_font_color; } +.aboutentry{ text-align: left; margin-right:10px; } +.userpic{ margin:5px; } +.sidebox{ border: 3px double $*side_border; background: $*side_bg; margin: 10px; padding:5px; } +.userpic2{ position:relative; float:left; padding: 5px; margin:0px 0px 0px 0px;} +.userpic_reply{ position:relative; float:left; padding: 5px;} +.moodpic{ position:relative; float:right; padding: 0px; padding-left: 5px; margin:0px; margin-top: -10px; margin-right: -5px; } +.calendarActive{ font-weight:bold; } +.blurb { color: $*side_t_color; } +.nosubject { font-style:italic; } +.replyform { text-align:left; clear: both; } +.replyform textarea { width: 100% ! important; } +.comment_postedby { text-align:left; font-weight:bold; } +.comment_date{ text-align:left; } +.comment_subject { color: $*c_sub_color; background: $*c_sub_bg; font: $*c_sub_size; font-weight:bold; letter-spacing:1.5px; text-align:left; padding:3px; margin-right: 0;} +.comment_wrapper{ border: 1px solid $*entries_border; background: $*entries_bg; padding:5px; margin: 0px 0px 5px 0px; } +.comment_info { width:95%; } +.comment_links { text-align:right; padding:3px; margin:0px; border-top: 1px dashed $*entries_border; } +.comment_links a { padding:2px; text-decoration:none; } +.comment_child { margin: 0px 0px 0px 20px; } +.minicomment {padding: 4px; border: 1px solid $*entries_border; } +.minicommentholder { border: 1px solid $*entries_border; } + +"""; } + +############################# FUNCTIONS ######################################## + +function prop_init() +{ + if ($*i_comment == "") { $*i_comment = "$*IMGDIR/style/3column/comments.gif"; } + if ($*i_perma == "") { $*i_perma = "$*IMGDIR/style/3column/permalink.gif"; } + if ($*i_mem == "") { $*i_mem = "$*IMGDIR/style/3column/memories.gif"; } + if ($*i_leave == "") { $*i_leave = "$*IMGDIR/style/3column/leavecomment.gif"; } + if ($*i_edit == "") { $*i_edit = "$*IMGDIR/style/3column/editentry.gif"; } + if ($*i_tags == "") { $*i_tags = "$*IMGDIR/style/3column/edittags.gif"; } +} + +function generateDots (string un) : string { + var string dots; + if($un != "") { + foreach var string s ($un) { + if($s == "a" or $s == "c" or $s == "e" or $s == "f" or $s == "h" or $s == "k" or $s == "m" or $s == "n" or $s == "p" or $s == "r" or $s == "t" or $s == "v" or $s == "x" or $s == "z") { + $dots = $dots + ":"; + } elseif($s == " ") { + + $dots = $dots + " "; + } else { + $dots = $dots + "."; + } + } + } + return $dots; +} + +function print_linkbox (string header, string text) { + """ + + """; + +} + +function box_item (string text) : string { + return """$text\n"""; +} + +function print_box (string header, string text) { + """ + + """; + +} + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function Page::lay_print_userpic() { + if(defined $.journal.default_pic) { + """ +
    +$.journal.name +
    + """; + } +} + + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var string links; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + $links = $links + """
  • """; + } else { + $links = $links + box_item(""""""); + } + } + } + + print_linkbox($*links_header, $links); +} + +function Page::lay_print_calendar () { + var YearMonth m = $this->get_latest_month(); + var string mon = $m->month_format(); + var string text; + $text = """ + """; + foreach var YearWeek w ($m.weeks) { + $text = $text + """ + """; + if($w.pre_empty > 0) { + foreach var int empty (1..$w.pre_empty) { + $text = $text + """ + """; + } + } + foreach var YearDay d ($w.days) { + if($d.num_entries > 0) { + $text = $text + """ + """; + } else { + $text = $text + """ + """; + } + } + $text = $text + "\n"; + } + $text = $text + "
     $d.day$d.day
    "; + print_box($mon, $text); +} + + +function Page::lay_print_subnav () { } + +function RecentPage::lay_print_subnav () { + var string back; + if($.nav.backward_url != "") { + $back = """$*t_back"""; + } else { + $back = " "; + } + var string forward; + if($.nav.forward_url != "") { + $forward = """$*t_forward"""; + } else { + $forward = " "; + } + + var int start = $.nav.skip; + var int end = $.nav.skip + size $.entries; + var string text = "$start - $end"; + """ +
    $back | $text | $forward
    + """; +} + +function FriendsPage::lay_make_username (Entry e) { + var Friend f = $.friends{$e.journal.username}; + var string url = $e.poster->base_url(); + """ + $e.poster.username + """; + if($e.poster.username != $e.journal.username) { + """ $e.journal"""; + } + +} +function EntryPage::print_body() { + """ """; + $this->print_entry($.entry); + if ($this.multiform_on) { + $this->print_multiform_start(); + } + + if ($.entry.comments.count > 0) { + """ +

    Comments

    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($.entry.comments.enabled) { + $this->print_comments($.comments); + } + + + if ($.entry.comments.count > 0) { + """ +
    + """; + + $.entry.comments->print(); + + """ +
    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($this.multiform_on and ($.entry.comments.count > 0)) { + """ +
    + """; + $this->print_multiform_actionline(); + """ +
    + """; + $this->print_multiform_end(); + } + """ """; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + } +} + +function EntryPage::print_comment(Comment c) { + var string datetime; + $datetime = $c.time->date_format("long")+", " + $c.time->time_format(); + var string picword; + if (defined $c.userpic and $*comment_userpic_style !="off") { + $picword = $c.metadata{"picture_keyword"}; + } + var string parent; + var string thread; + if($c.parent_url != "") { + $parent = """$*text_comment_parent$*t_divider"""; + } + if($c.thread_url != "") { + $thread = """$*text_comment_thread$*t_divider"""; + } + var string subjecticon; + if (defined $c.subject_icon) { + $subjecticon = """"""; + } + var string ip; + if ($c.metadata{"poster_ip"}) { + $ip = """   """ + $c.metadata{"poster_ip"}; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string poster_name; $poster_name= $c.poster.name; + var string pic; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $pic = """ + $picword"""; + } + + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
    + + +
    +
    Posted by: $poster_name ($poster) $ip
    +
    Posted at: $subjecticon $datetime
    + """; + + if ($.multiform_on) { + """
    """; + $c->print_multiform_check(); + """
    + """; + } + + """ +
    $c.subject
    $pic
    + +

    $c.text

    + + """; + + if ((size $c.replies) > 0 and $c.replies[0].full == false) { + """
    \n"""; + $this->print_comments($c.replies); + "
    \n"; + } + + """ +
    + """; + if ((size $c.replies) > 0 and $c.replies[0].full == true) { + """
    """; + $this->print_comments($c.replies); + """
    """; + } + +} + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string subj = $c.subject != "" ? $c.subject : """$*t_nosubject"""; + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
    +
    $poster - $subj
    + """; + $this->print_comments($c.replies); +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ +
    + """; + print lang_page_of_pages($.current, $.total); + " — "; + foreach var int i (1..$.total) { + if ($i == $.current) { """[$i]"""; + + } else { + var string url_of = $this->url_of($i); + "[$i]"; + } + } + """
    """; +} +function Page::print_entry (Entry e) { + # Print an anchor + print """"""; + # Get the right time and date of the post + var string time = $e.time->time_format(); + var string date = $e.time->date_format("long"); + # Get the Locked or Private icon, if needed. + var string security; + if ($e.security != "") { + $security = """"""; + } + + var UserLite name; + var string pname; + var string poster_name; $poster_name= $e.poster.name; + var string poster = defined $e.poster ? $e.poster->as_string() : "$*text_poster_anonymous"; + var bool show_name = ($.view == "friends" or $e.poster.username != $.journal.username or $.view == "entry") ? true : false; + var bool show_pic = (defined $e.userpic and ($.view == "friends" or $*show_entry_userpic or $e.poster.username != $e.journal.username or $.view == "entry")) ? true : false; + + if ($.view == "friends"){ """ + +
    + """; if($show_pic) { + """ +
    +$e.poster.name [userpic] +
    """; } """ + +
    $security $e.subject
    +
    """; + if($e.poster.username != $e.journal.username) { + """ in $e.journal
    """; + } """ by $poster_name ($poster)
    +
    at $date ($time)"""; + + $e->print_metadata(); """ +
    + + +

    $e.text

    + +
    """; + + } else { + +if($show_pic) { + """ +
    +$e.poster.name [userpic] +
    + """; + } """ + +
    +

    $e.subject

    +
    $security $date ($time) +"""; + + $e->print_metadata(); + + """ +
    +
    +

    $e.text

    +
    + +
    + """; + } +} + + +function CommentInfo::print() { + if ($.enabled) { + if ($.count > 0 or $.screened) { + $this->print_readlink(); + } + $this->print_postlink(); + } +} + +function CommentInfo::print_postlink() { + var Page p = get_page(); + """$*t_post_comment $*t_divider """; +} + +function CommentInfo::print_readlink { + var Page p = get_page(); + ""+ + get_plural_phrase($.count, $p.view == "friends" ? + "t_read_comments_friends" : "t_read_comments")+ + "\"$*t_divider"; +} + +function DayPage::lay_print_subnav () { + var string back; + if($.prev_url != "") { + $back = """$*t_back"""; + } else { + $back = " "; + } + var string forward; + if($.next_url != "") { + $forward = """$*t_forward"""; + } else { + $forward = " "; + } + + var string text = $.date->date_format("long"); + + """ +
    $back | $text | $forward
    + """; + +} + + + +############################# REPLY PAGE ######################################### + +function ReplyPage::print_body() { + + var EntryLite e = $.replyto; + var string poster = defined $e.poster ? $e.poster->as_string() : "$*text_poster_anonymous"; + var string datetime; + var string time = $e.time->time_format(); + var string date = $e.time->date_format("long"); + + var UserLite name; + """ +
    +

    $date

    """; +if(defined $e.userpic and $*comment_userpic_style != "off") { + $name = $e.poster; + """
    """; + if (defined $e.userpic or (defined $e.userpic and $.view == "entry" and $*show_entry_userpic)) { + """"""; + } + """
    """; + } """ + +

    $e.subject

    +
    +

    $e.text

    + +
    + """; + $.form->print(); + """ +
    + """; +} + +function Entry::print_metadata() { + var string caption; + var string val; + var Image i; + print $this->get_tags_text(); + if (size $.metadata == 0) { return; } + foreach var string k ($.metadata) { + $caption = $k; + $val = $.metadata{$k}; + if ($k == "music") { + $caption = $*t_meta_music; + } + elseif ($k == "mood") { + $caption = $*t_meta_mood; + if (defined $.mood_icon) { + $i = $.mood_icon; + $val = """
    $val
    $val"""; + } + } + println """
    $caption: $val"""; + } +} + + +################################ VIEWS ######################################### + +function RecentPage::print_body () { + """ +
    + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """ +
    + """; +} + + +function DayPage::print_body() { + + """
    """; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + "

    $*t_noentries_day

    "; + } + """
    """; + +} + +function MonthPage::view_title : string { + return $.date->date_format($*lang_fmt_month_long); +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + var string back; + var string forward; + if ($.prev_url != "") { $back = """$*t_back"""; } + if ($.next_url != "") { $forward = """$*t_forward"""; } + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
    + + + + + + +
    $back$select$forward
    +
    + """; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + +
    +
    + +
    +
    + """; + $d->print_subjectlist(); + """ +
    +
    +
    + + """; + } + } +} + +function MonthDay::print_subjectlist() { + + foreach var Entry e ($.entries) { + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + """ $*t_nosubject"""; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "t_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
    \n"; + } +} + +function YearPage::print_body { + $this->print_year_links(); + """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
    """; +} + +function YearPage::print_year_links() { + """
    """; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """$y.year"""; + } else { + """$*t_divider$y.year$*t_divider"""; + } + } + """
    """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
    +
    + + +
    +
    + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
    $*lang_dayname_short[$d]
    +
    +
    + """; + +} + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + """ + +
    $day
    + """; + if ($d.num_entries > 0) { + var string num = $d.num_entries < 10 ? " " + string($d.num_entries) : string($d.num_entries); + """ + + """; + } else { + """ +
    -
    + """; + +} + """ + + """; + } + """ + + """; +} + +# Override the view names to be all short and lowercase-like +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*t_view_recent; } + if ($viewid == "archive") { return $*t_view_archive; } + if ($viewid == "friends") { return $*t_view_friends; } + if ($viewid == "day") { return "day"; } + if ($viewid == "month") { return "month"; } + if ($viewid == "userinfo") { return $*t_view_userinfo; } + if ($viewid == "entry") { return "read comments"; } + if ($viewid == "reply") { return "post comment"; } + return "Unknown View"; +} + +############################## COMMON HTML ############################################ + +function Page::print () { + + var string title = $this->title(); + + """ + + + + $title + + """; + + $this->print_head(); + + + if ($*external_stylesheet) { + println """"""; + } + else { + println """"""; + } + + """ + + + + +
    + + +
    +"""; + $this->lay_print_subnav(); + $this->print_body(); + $this->lay_print_subnav(); + """ + +
    + +
    + + + + +"""; +$this->print_linklist(); +""" + +
    + +
    + + + + + +"""; +$this->lay_print_calendar(); +""" + +
    + +
    + +
    + + + """; +} diff --git a/local/bin/upgrading/s2layers/3column/themes.s2 b/local/bin/upgrading/s2layers/3column/themes.s2 new file mode 100755 index 0000000..886bba9 --- /dev/null +++ b/local/bin/upgrading/s2layers/3column/themes.s2 @@ -0,0 +1,233 @@ +#NEWLAYER: 3column/blue +layerinfo "type" = "theme"; +layerinfo "name" = "Blue"; +layerinfo "redist_uniq" = "3column/blue"; + +set color_bg = "#e9f3fa"; +set font_color = "#0d446b"; +set link_color = "#0d446b"; +set link_hover = "#0d446b"; +set link_side = "#0d446b"; +set link_side_h = "#0d446b"; +set side_bg = "#e9f3fa"; +set entries_bg = "#e9f3fa"; +set entries_border = "#0d446b"; +set side_t_color = "#0d446b"; +set button_bg = "#e9f3fa"; +set button_bg_h = "#b0cce0"; +set entries_font_color = "#0d446b"; +set side_border = "#0d446b"; +set c_sub_color = "#b0cce0"; +set c_sub_bg = "#0d446b"; +set side_h_color = "#0d446b"; +set side_h_border = "#0d446b"; +set side_h_bg = "#b0cce0"; +set sub_color = "#0d446b"; + +#NEWLAYER: 3column/dark +layerinfo "type" = "theme"; +layerinfo "name" = "Dark"; +layerinfo "redist_uniq" = "3column/dark"; + +set color_bg = "#000000"; +set font_color = "#c0c0c0"; +set link_color = "#202020"; +set link_hover = "#FFFFFF"; +set link_side = "#95432D"; +set link_side_h = "#BA7625"; +set side_bg = "#000000"; +set side_t_color = "C0C0C0"; +set side_border = "#000000"; +set side_h_color = "#C0C0C0"; +set side_h_border = "#C0C0C0"; +set side_h_bg = "#000000"; +set entries_bg = "#58494E"; +set entries_border = "#FFFFFF"; +set button_bg = "#FFFFFF"; +set button_bg_h = "#c0c0c0"; +set entries_font_color = "#000000"; +set c_sub_color = "#000000"; +set c_sub_bg = "#ffffff"; +set sub_color = "#C0C0C0"; + +#NEWLAYER: 3column/earth +layerinfo "type" = "theme"; +layerinfo "name" = "Earth"; +layerinfo "redist_uniq" = "3column/earth"; + +set color_bg = "#ECECEA"; +set font_color = "#4F4637"; +set link_color = "#4F4637"; +set link_hover = "#1D4629"; +set link_side = "#7B6E59"; +set link_side_h = "#1D4629"; +set side_bg = "#DBCEB9"; +set side_t_color = "4F4637"; +set side_border = "#7B6E59"; +set side_h_color = "#ECECEA"; +set side_h_border = "#ECECEA"; +set side_h_bg = "#7B6E59"; +set entries_bg = "#AB9F8B"; +set entries_border = "#7B6E59"; +set button_bg = "#ECECEA"; +set button_bg_h = "#4F4637"; +set entries_font_color = "#4F4637"; +set c_sub_color = "#4F4637"; +set c_sub_bg = "#ECECEA"; +set sub_color = "#4F4637"; + +#NEWLAYER: 3column/unnamed +layerinfo "type" = "theme"; +layerinfo "name" = "Unnamed"; +layerinfo "redist_uniq" = "3column/unnamed"; + +set color_bg = "#E5D5C6"; +set font_color = "#000000"; +set link_color = "#202020"; +set link_hover = "#000000"; +set link_side = "#95432D"; +set link_side_h = "#D63C3C"; +set side_bg = "#E5D5C6"; +set side_t_color = "#000000"; +set side_border = "#E5D5C6"; +set side_h_color = "#000000"; +set side_h_border = "#000000"; +set side_h_bg = "#E5D5C6"; +set entries_bg = "#E5D5C6"; +set entries_border = "#E5D5C6"; +set button_bg = "#E5D5C6"; +set button_bg_h = "#ccab8a"; +set entries_font_color = "#000000"; +set c_sub_color = "#ccab8a"; +set c_sub_bg = "#E5D5C6"; +set sub_color = "#000000"; + +#NEWLAYER: 3column/greenenvy +layerinfo "type" = "theme"; +layerinfo "name" = "Green of Envy"; +layerinfo "redist_uniq" = "3column/greenenvy"; + +set color_bg = "#d8ece7"; +set font_color = "#1b2d29"; +set link_color = "#1b2d29"; +set link_hover = "#1b2d29"; +set link_side = "#1b2d29"; +set link_side_h = "#1b2d29"; +set side_bg = "#d8ece7"; +set entries_bg = "#d8ece7"; +set entries_border = "#1b2d29"; +set side_t_color = "#1b2d29"; +set button_bg = "#d8ece7"; +set button_bg_h = "#b1d5cb"; +set entries_font_color = "#1b2d29"; +set side_border = "#1b2d29"; +set c_sub_color = "#b1d5cb"; +set c_sub_bg = "#1b2d29"; +set side_h_color = "#1b2d29"; +set side_h_border = "#1b2d29"; +set side_h_bg = "#b1d5cb"; +set sub_color = "#1b2d29"; + +#NEWLAYER: 3column/blackwhite +layerinfo "type" = "theme"; +layerinfo "name" = "Black and White"; +layerinfo "redist_uniq" = "3column/blackwhite"; + +set color_bg = "#FFFFFF"; +set font_color = "#808080"; +set link_color = "#808080"; +set link_hover = "#202020"; +set link_side = "#c0c0c0"; +set link_side_h = "#FFFFFF"; +set side_bg = "#000000"; +set side_t_color = "808080"; +set side_border = "#ffffff"; +set side_h_color = "#c0c0c0"; +set side_h_border = "#c0c0c0"; +set side_h_bg = "#808080"; +set entries_bg = "#ffffff"; +set entries_border = "#000000"; +set button_bg = "#c0c0c0"; +set button_bg_h = "#808080"; +set entries_font_color = "#000000"; +set c_sub_color = "#ffffff"; +set c_sub_bg = "#000000"; +set sub_color = "#202020"; + +#NEWLAYER: 3column/agentorange +layerinfo "type" = "theme"; +layerinfo "name" = "Agent Orange"; +layerinfo "redist_uniq" = "3column/agentorange"; + +set color_bg = "#f7e6d3"; +set font_color = "#582604"; +set link_color = "#582604"; +set link_hover = "#582604"; +set link_side = "#582604"; +set link_side_h = "#582604"; +set side_bg = "#f7e6d3"; +set entries_bg = "#f7e6d3"; +set entries_border = "#582604"; +set side_t_color = "#582604"; +set button_bg = "#f7e6d3"; +set button_bg_h = "#e0c7aa"; +set entries_font_color = "#582604"; +set side_border = "#582604"; +set c_sub_color = "#e0c7aa"; +set c_sub_bg = "#582604"; +set side_h_color = "#582604"; +set side_h_border = "#582604"; +set side_h_bg = "#e0c7aa"; +set sub_color = "#b64c06"; + +#NEWLAYER: 3column/purple +layerinfo "type" = "theme"; +layerinfo "name" = "Purple"; +layerinfo "redist_uniq" = "3column/purple"; + +set color_bg = "#e8cff1"; +set font_color = "#410458"; +set link_color = "#410458"; +set link_hover = "#410458"; +set link_side = "#410458"; +set link_side_h = "#410458"; +set side_bg = "#e8cff1"; +set entries_bg = "#e8cff1"; +set entries_border = "#410458"; +set side_t_color = "#410458"; +set button_bg = "#e8cff1"; +set button_bg_h = "#d1aae0"; +set entries_font_color = "#410458"; +set side_border = "#410458"; +set c_sub_color = "#d1aae0"; +set c_sub_bg = "#410458"; +set side_h_color = "#410458"; +set side_h_border = "#410458"; +set side_h_bg = "#d1aae0"; +set sub_color = "#410458"; + +#NEWLAYER: 3column/mellowyellow +layerinfo "type" = "theme"; +layerinfo "name" = "Mellow Yellow"; +layerinfo "redist_uniq" = "3column/mellowyellow"; + +set color_bg = "#f8f6da"; +set font_color = "#42331e"; +set link_color = "#42331e"; +set link_hover = "#8d452f"; +set link_side = "#8d452f"; +set link_side_h = "#42331e"; +set side_bg = "#f2c98e"; +set entries_bg = "#f8f6da"; +set entries_border = "#42331e"; +set side_t_color = "#42331e"; +set button_bg = "#f2c98e"; +set button_bg_h = "#e8c098"; +set entries_font_color = "#42331e"; +set side_border = "#42331e"; +set c_sub_color = "#42331e"; +set c_sub_bg = "#f2c98e"; +set side_h_color = "#333333"; +set side_h_border = "#333333"; +set side_h_bg = "#f8f6da"; +set sub_color = "#d39945"; diff --git a/local/bin/upgrading/s2layers/anovelconundrum/layout.s2 b/local/bin/upgrading/s2layers/anovelconundrum/layout.s2 new file mode 100755 index 0000000..9792cb9 --- /dev/null +++ b/local/bin/upgrading/s2layers/anovelconundrum/layout.s2 @@ -0,0 +1,999 @@ +# -*-s2-*- + +layerinfo "type" = "layout"; +layerinfo "name" = "A Novel Conundrum"; +layerinfo "source_viewable" = 1; +layerinfo "redist_uniq" = "anovelconundrum/layout"; +layerinfo "author_name" = "taion"; + +propgroup colors { + property Color page_back { + des = "Page background"; + } + property Color entry_text { + des = "Entry text color"; + } + property Color text_weaker { + des = "Weaker text color"; + } + property Color page_link { + des = "Link color"; + } + property Color page_vlink { + des = "Visited link color"; + } + property Color page_alink { + des = "Active link color"; + } +} + +# From my last e-mail with Taion, the plan was to rasterize the leading fonts so that +# appearance issues could be avoided. However, I don't have access to many of the fonts +# that he tested with, so I'll have to put that off for later. + +# You will need access to Microsoft provided fonts for most accurate rendering, but +# we are working on specifying usable alternatives that are cross platform friendly. +propgroup fonts { + property use font_base; + property string font_fallback { + des = "Alternative font style"; + } + property string font_type { + des = "Body font type"; + note = "General font class for body text"; + } + property int font_size { + des = "Body font size (points)"; + } + property int font_leading { + des = "Body font leading (points)"; + } + property string title_letterspacing { + des = "Letterspacing in titles"; + } + property bool title_smallcaps { + des = "Smallcaps in titles"; + } + property bool title_underline { + des = "Underlined titles"; + } + property string font_flourish_base { + des = "Font face for decorative flourishes"; + } + property string font_flourish_fallback { + des = "Alternate font face for decorative flourishes"; + } + property string font_flourish_type { + des = "Font type for decorative flourishes"; + } + property string font_secondary_base { + des = "Font face for secondary text"; + } + property string font_secondary_fallback { + des = "Alternate font face for secondary text"; + } + property string font_secondary_type { + des = "Font type for secondary text"; + } + property int font_secondary_size { + des = "Secondary font size (points)"; + note = "For best results, match optical x-height with the body font"; + } + property string flourish_rm { + des = "Right margin for flourishes"; + } + property string dc_rm { + des = "Right margin for drop caps"; + } +} + +propgroup presentation { + property string dingbar_url { + des = "URL to spacer image between portions of content"; + note = "A default will be chosen for you if left blank."; + } + + property use page_recent_items; + property use page_friends_items; + + property string body_width { + des = "Text body width"; + } + + property int dcLen { + des = "Minimum length in characters before using drop caps"; + } + + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; +} + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property string text_dingbar_alt { + des = "Alternative text for dingbar images"; + noui = 1; + } +} + +# Set default colors +set entry_text = "#000000"; +set text_weaker = "#666666"; +set page_link = "#000000"; +set page_vlink = "#666666"; +set page_alink = "#333333"; +set page_back = "#F5F5DC"; + +set body_width = "35em"; +set dcLen = 200; +set show_entrynav_icons = true; +set page_background_image = ""; + +set font_base = "Palatino Linotype"; +set font_fallback = "Book Antiqua"; +set font_type = "serif"; +set font_flourish_base = "Edwardian Script ITC\", \"Edwardian Script ITC Semi-Expanded"; +set font_flourish_fallback = "Zapfino\", \"Viner Hand ITC"; +set font_flourish_type = "cursive"; +set font_secondary_base = "Frutiger Linotype"; +set font_secondary_fallback = "Tahoma"; +set font_secondary_type = "sans-serif"; +set font_size = 10; +set font_leading = 14; +set title_smallcaps = true; +set title_underline = false; +set title_letterspacing = "0.08em"; +set font_secondary_size = 9; +set flourish_rm = "0.093em"; +set dc_rm = "0.2em"; +set dingbar_url = ""; + +set text_poster_anonymous = "an anonymous reader"; +set text_dingbar_alt = "* * *"; +set text_view_recent = "Entries"; +set text_view_friends = "Friends"; +set text_view_archive = "Archive"; +set text_view_userinfo = "Profile"; + +function prop_init() { + var PalItem start = PalItem(0, $*entry_text); + var PalItem end = PalItem(13, $*page_back); + if ($*dingbar_url == "") { $*dingbar_url = palimg_gradient("anovelconundrum/dingbar.gif", $start, $end); } +} + +function print_stylesheet() { + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; +""" +body { + margin-top: 1in; + margin-bottom: 0.6in; +} + +body, td, h2, .caption, h1, h3 { +"""; +if ($*font_base != "" or $*font_fallback != "" or $*font_type != "") { + "font-family: "; + if ($*font_base != "") { + "\"$*font_base\""; + if ($*font_fallback != "" or $*font_type != "") { + ", "; + } + } + if ($*font_fallback != "") { + "\"$*font_fallback\""; + if ($*font_type != "") { + ", "; + } + } + if ($*font_type != "") { + "$*font_type"; + } + ";\n"; +} +""" + font-size: ${*font_size}pt; + line-height: ${*font_leading}pt; + font-weight: normal; +} + +.caption, h1, h3 { +"""; if($*title_smallcaps) {""" + font-variant: small-caps; + text-transform: lowercase; +"""; } +""" letter-spacing: $*title_letterspacing; +} +h1 { font-size: 16pt; } +h3 { font-size: 12pt; } +h2, .noul, .ult { + font-style: italic; + margin: 0px; +} + +.caption { +"""; if($*title_underline) {""" + text-decoration: underline; +"""; } +""" } + +.flourish, .bodyl:first-letter { +"""; +if ($*font_flourish_base != "" or $*font_flourish_fallback != "" or $*font_flourish_type != "") { + "font-family: "; + if ($*font_flourish_base != "") { + "\"$*font_flourish_base\""; + if ($*font_flourish_fallback != "" or $*font_flourish_type != "") { + ", "; + } + } + if ($*font_flourish_fallback != "") { + "\"$*font_flourish_fallback\""; + if ($*font_flourish_type != "") { + ", "; + } + } + if ($*font_flourish_type != "") { + "$*font_flourish_type"; + } + ";\n"; +} +""" +} + +.flourish { + margin-right: ${*flourish_rm}; + z-index: 1; + font-size: 34pt; + position: relative; + top: 0.1em; + text-transform: uppercase; +} + +.sfon, .index, .author, select, input { +"""; +if ($*font_secondary_base != "" or $*font_secondary_fallback != "" or $*font_secondary_type != "") { + "font-family: "; + if ($*font_secondary_base != "") { + "\"$*font_secondary_base\""; + if ($*font_secondary_fallback != "" or $*font_secondary_type != "") { + ", "; + } + } + if ($*font_secondary_fallback != "") { + "\"$*font_secondary_fallback\""; + if ($*font_secondary_type != "") { + ", "; + } + } + if ($*font_secondary_type != "") { + "$*font_secondary_type"; + } + ";\n"; +} +""" font-size: ${*font_secondary_size}pt; + line-height: ${*font_leading}pt; +} + +.index { + width: 10em; + margin-right: 1.2em; +} + +.bodybox { width: $*body_width; } + +.body, .bodyl, .bodyns { + text-align: justify; +} +.bodyl:first-letter { + font-size: """ + (2* $*font_leading) + """pt; + margin-bottom: -""" + $*font_size + """pt; + margin-right: ${*dc_rm}; + float: left; + border-bottom: none; + text-transform: uppercase; + line-height: """ + (2* $*font_leading) + """pt; +} +.bodyns:first-line, .sc, small, .sct { +"""; if($*title_smallcaps) {""" + font-variant: small-caps; + text-transform: lowercase; +"""; } + if($*title_underline) {""" + text-decoration: underline; +"""; } +""" letter-spacing: 0.05em; +} + +.sct { + letter-spacing: $*title_letterspacing; + text-align: center; +} + +.author { + float: right; + text-align: center; + margin-left: 1.5em; + margin-bottom: 0.5em; +} + +.ywp { + width: 2em; + margin-left: 0.5em; + margin-right: 0.5em; +} + +blockquote { + margin-top: ${*font_leading}pt; + margin-bottom: ${*font_leading}pt; + margin-left: 2em; +} + +tt, pre, textarea { +font-family: "Lucida Console", monospace; +font-size:"""+ ((${*font_size}*4)/5) + """pt; +} + +a {text-decoration: none;} +.body a, .bodyl a, .bodyns a, .bodynsl a, .author a, .ult a, .uts a { border-bottom: 1px dotted; } +.ljuser a, a img, .smallbar a, .noul a { border-bottom: none; } +a:hover, .ljuser a:hover { border-bottom: 1px solid; } + +p { + text-indent: 1.5em; + margin: 0px; + padding: 0px; +} + +blockquote + p { text-indent: 0px; } + +.uts { + font-size: 80%; + font-style: italic; + text-align: center; + line-height: """ + $*font_size + """pt; + margin-bottom: """ + ($*font_leading-$*font_size) + """pt; +} + +.smallbar { + font-size: 80%; + font-style: italic; + text-align: center; + line-height: """ + (2*$*font_leading) + """pt; + clear: right; +} + +.ljcomsel { + position: relative; + top: 0.75pt; + height: 7.5pt; + padding-left: 1pt; +} +input#username, input#password { margin-right: 0.5em; } + +.bs { + margin-top: """ + (2*$*font_leading) + """pt; + margin-bottom: """ + (2*$*font_leading) + """pt; + text-align: center; + line-height: ${*font_leading}pt; +} +"""; +} + +function find_lpar(string t) : int { + foreach var int i (reverse (0 .. ($t->length()-1))) { + if($t->substr($i,1)=="(") { return $i; } + } + return -1; +} + +function render_title(string t, int len) { + foreach var int i (0 .. ($len-1)) { + var string pc = $t->substr($i-1,1); + var string cc = $t->substr($i,1); + if($cc==" ") { " · "; } + elseif( $i > 0 and $pc != " ") { "$cc"; } + elseif ($cc=="A" or $cc=="B" or $cc=="C" or $cc=="D" or $cc=="E" or $cc=="F" or $cc=="G" or $cc=="H" or $cc=="I" or $cc=="J" or $cc=="K" or $cc=="L" or $cc=="M" or $cc=="N" or $cc=="O" or $cc=="P" or $cc=="Q" or $cc=="R" or $cc=="S" or $cc=="T" or $cc=="U" or $cc=="V" or $cc=="W" or $cc=="X" or $cc=="Y" or $cc=="Z") { + "$cc"; + } + else { "$cc"; } + } +} + +function render_body(string t) { + var int str=0; + var bool par=false; + var bool pars=false; + $str = ($t->substr(0,6) == "
    " ? 6 : 0); + if($t->substr(0,3) == "

    ") { $str = 3; $pars=true; } + foreach var int i ($str .. ($t->length()-1)) { + if($t->substr($i,12) == "

    ") { + $str=$i+12; + if($par) { "

    "; } + else { "

    "; $par=true; } + } + elseif($pars and $t->substr($i,4) == "

    ") { $str=$i+4; $pars=false; } + elseif($i >= $str) { print $t->substr($i,1); } + } + if($par) { "

    "; } +} + +function display_title(Page p) { + var string dtitle = $p.global_title; + var string stitle = $p->view_title(); + $stitle = ($p.view == "recent" ? $p.global_subtitle : $stitle); + var int lenm=$stitle->length()-1; + var int i=$dtitle->length()+1; + if ($dtitle == "") { + $dtitle = $p.journal.name; + $i=$dtitle->length()+1; + } + if ($p.view == "friends") { + $dtitle = $p->view_title(); + $i=find_lpar($dtitle); + if($i==-1) { $i = $lenm+2; } + } + +"""
    +

    """; render_title($dtitle,$i-1); """

    """; +if($p.view != "friends" and $stitle != "") { """

    $stitle

    """; } +elseif($p.view == "friends" and $i<$lenm) { "

    " + $dtitle->substr($i+1,($lenm-$i)-1) + "

    "; } +"""
    """; +} + +function Page::print() { + var string title = $this->title(); + + var string links; + var bool firstlink = true; + foreach var string v ($.views_order) { + if ($firstlink == false) { + $links = "$links · "; + } + else { + $firstlink = false; + } + $links = $links + (""+lang_viewname($v)+""); + } + +"""\n\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + +"""$title + +"""; +display_title($this); +"""
    +

    $links

    +
    +"""; +$this->print_body(); +""" + + +"""; +} + +function print_entry(Page p, Entry e) { + var string date=$e.time->date_format("short"); + var string time=$e.time->time_format(); + """ + + + + + +"""; + + if ($p.view == "entry" and $*show_entrynav_icons) + { +""" +"""; + } +"
    $*text_dingbar_alt
    """; +""" $time
    + $date


    + """; + $e.comments->print(); + +"""
    +
    +
    """; + + if (defined $e.userpic) { + """
    """; + } + elseif ($e.poster.journal_type == "C") { + """
    """; + + } + elseif ($e.poster.journal_type == "Y") { + """
    """; + } + else { + """
    """; + } + "base_url() + "/\">$e.poster.username"; + if ($e.security != "") { + $e.security_icon->print(); + } + if ($e.poster.username != $e.journal.username and $e.journal.journal_type =="C") { +""",
    + +base_url() + """/">$e.journal.username"""; + } + + var string subject=$e.subject; + if($p.view=="entry") { $subject=""; } +"""
    +
    + $subject +
    """; + if ($subject == "" and $p.view!="entry") {"
    ";} + elseif ($e.text->length() > $*dcLen) {"
    ";} + else {"
    ";} + render_body($e.text); + var string metadata; + if ($e.metadata) { + $metadata = "
    "; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "$val $val"; + } + $metadata = """$metadata\n + """; + } + $metadata = """$metadata
    $text:
    $val
    """; + } + """$metadata
    $*text_dingbar_alt
    """; + $e->print_linkbar(); +"""
    "; +} # print_entry(Page,Entry,Color,Color) + +function Entry::print_linkbar() { + ## There's no point in showing previous/next links on pages which show + ## multiple entries anyway, so we only print them on EntryPage and ReplyPage. + + var Page p = get_page(); + var Link link; + var bool show_interentry = ($p.view == "entry" or $p.view == "reply"); + + "

    "; + if ($show_interentry) { + var Link prev = $this->get_link("nav_prev"); + """$prev.caption · """; + } + + if ($p.view == "entry" and $.comments.enabled) { + if ($.comments.maxcomments) { + "Maximum Comments Reached"; + } else { + "Leave a Comment"; + } + " · "; + } + + var int i=0; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + if($link.caption != "") { + if($i>0) { " · "; } + "$link.caption"; + $i++; + } + } + + if ($show_interentry) { + var Link next = $this->get_link("nav_next"); + """ · $next.caption"""; + } + "

    "; +} + +function Page::print_entry(Entry e) { + print_entry($this, $e); +} + +function FriendsPage::print_entry(Entry e) { + print_entry($this, $e); +} + + +function RecentPage::print_body() { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +""" +
    $*text_dingbar_alt
    +

    +"""; + + # go forward/backward if possible + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + var string sep; + var string back; + var string forward; + if ($.nav.backward_url != "") { + $back = """Previous"""; + } + if ($.nav.forward_url != "") { + $forward = """Next"""; + } + if ($back != "" and $forward != "") { $sep = " · "; } + "$back$sep$forward"; + } + "

    "; +} + +function CommentInfo::print() { + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); "
    "; + } + $this->print_postlink(); +} + +function YearPage::print_year_links() { + """
    + $*text_dingbar_alt +
    Years

    """; + + var bool d=false; + foreach var YearYear y ($.years) { + if($d) { " · "; } + else { $d=true; } + if ($y.displayed) { + "$y.year"; + } else { + "$y.year"; + } + } + "

    "; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """
    + +
    +"""; + print $m->month_format(); + """ + +
    + +"""; + foreach var int d (weekdays()) { + "\n"; + } + ""; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + """
    "+$*lang_dayname_short[$d]+"
    """; +} + +function YearWeek::print() { + ""; + if ($.pre_empty) { ""; } + foreach var YearDay d ($.days) { + """
    $d.day
    """; + if ($d.num_entries) { + """"""; + } else { + " "; + } + "
    "; + } + if ($.post_empty) { ""; } + ""; +} + +function DayPage::print_body() { + if (not $.has_entries) { print "
    " + ehtml($*text_noentries_day) + "
    "; } + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """
    + $*text_dingbar_alt +
    """; + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + """

    $tprev · $tnext

    """; + +} + +function MonthPage::print_body() { + """
    + $*text_dingbar_alt +
    """; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + ":
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n"; + """
    + $*text_dingbar_alt +
    """; + "
    "; + $.redir->print_hiddens(); + if ($.prev_url != "") { " "; } + if (size $.months > 1) { + "\n"; + } + if ($.next_url != "") { " \n"; } + "
    "; +} + +function EntryPage::print_body() { + print_entry($this, $.entry); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + + $this->print_multiform_start(); + "
    "; + "
    "; + $this->print_comments($.comments); + "
    "; + + $.comment_pages->print(); + + if ($*show_entrynav_icons) { + """
    + $*text_dingbar_alt +
    """; + """
    """; + $.entry->print_linkbar(); + """
    """; + } + + if ($this.multiform_on) {""" +
    + $*text_dingbar_alt +
    +
    """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
    "; + } + } +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """
    + $*text_dingbar_alt +
    """; + "
    "; + "
    "; + "

    " + lang_page_of_pages($.current, $.total) + "

    "; + var string url_prev = $this->url_of($.current - 1); + "
    "; + if ($.current != 1) { + print ""; + } else { + print "☜"; + } + print " "; + foreach var int i (1..$.total) { + if ($i == $.current) { "$i"; } + else { + var string url_of = $this->url_of($i); + "$i"; + } + if ($i != $.total) { ", "; } + } + " "; + var string url_next = $this->url_of($.current + 1); + if ($.current != $.total) { + print ""; + } else { + print "☞"; + } + "
    "; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if($c.depth==1) { + ""; + """
    + $*text_dingbar_alt +
    """; + " + + + """; +} + +function DayPage::lay_viewspec_nav() { + """ + + + + """; +} + +function MonthPage::lay_viewspec_nav() { + """ + + + + """; +} + +function RecentPage::lay_viewspec_nav() { + """ + + + + """; + +} + + +############################################# +# +# Top Navigation +# +############################################# + +function print_nav(Page p) { + + # figure out the width of each table cell in the navigation based on total page width + var int blank = $*page_width - 512; + if($p.journal.website_url) { + $blank = $blank - 102; + } + + """ + + +
    "; + } + var int indent = ($c.depth - 1) * 21; + "
    \n"; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + "
    "; + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + ""; + "
    1? " style='margin-top:${*font_leading}pt;'" : "") + ">"; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + "[User Picture]"; + } + + ### From, date, etc + "
    "; + if ($c.screened) { "(Screened) "; } + "On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + ""; + if ($c.depth == 1) { "commented"; } + else { "replied"; } + ":
    "; + + print (defined $c.subject_icon or $c.subject != "") ? "
    $c.subject_icon $c.subject
    " : ""; + + "
    "; + render_body($c.text); + print "
    "; + if ($c.frozen) { + "Replies Frozen"; + } else { + "Reply"; + } + if ($c.parent_url != "") { " · Parent"; } + if ($c.thread_url != "") { " · Thread"; } + $c->print_linkbar(); + if ($this.multiform_on) { + " · "; + ""; + $c->print_multiform_check(); + } + "
    "; +} + + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + var bool subj = $c.subject != ""; + "
    "; + "— On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + if($subj) { """replied, “$c.subject”"""; } + else { """posted a reply"""; } + ".
    "; +} + +function Comment::print_linkbar() { + var Link link; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + ($link.caption != "") ? " · $link.caption" : ""; + } +} + +function ReplyPage::print_body() { + var bool ent = $.replyto.permalink_url == $.entry.permalink_url; + + if($ent) { + print_entry($this, $.entry); + } + else { + """
    + $*text_dingbar_alt +
    """; + + var EntryLite c = $.replyto; + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + "
    "; + + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + "[User Picture]"; + + } + + ### From, date, etc + + "
    "; + "On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + "commented:
    "; + + print ($c.subject != "") ? "
    $c.subject
    " : ""; + + "
    "; + render_body($c.text); + "
    "; + } + + """
    + $*text_dingbar_alt +
    """; + ""; + """
    + $*text_dingbar_alt +
    """; + + if (not $.entry.comments.enabled) { + print "
    $*text_reply_nocomments
    "; + return; + } + + + "

    Reply " + ($ent ? "to this entry" : "to this comment") + ":

    "; + $.form->print(); + "
    "; +} diff --git a/local/bin/upgrading/s2layers/anovelconundrum/themes.s2 b/local/bin/upgrading/s2layers/anovelconundrum/themes.s2 new file mode 100755 index 0000000..79e516b --- /dev/null +++ b/local/bin/upgrading/s2layers/anovelconundrum/themes.s2 @@ -0,0 +1,179 @@ +#NEWLAYER: anovelconundrum/renaissance +layerinfo "type" = "theme"; +layerinfo "name" = "Renaissance"; +layerinfo "redist_uniq" = "anovelconundrum/renaissance"; + +set font_secondary_fallback = ""; +set font_secondary_size = 10; +set font_secondary_type = "serif"; +set font_leading = 12; +set page_back = "#FAF2C8"; +set font_fallback = ""; +set font_secondary_base = "Garamond"; +set font_base = "Garamond"; + +#NEWLAYER: anovelconundrum/modern +layerinfo "type" = "theme"; +layerinfo "name" = "Modern"; +layerinfo "redist_uniq" = "anovelconundrum/modern"; + +set font_leading = 14; +set page_back = "#F5F5E8"; +set font_fallback = ""; +set font_base = "Georgia"; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.1em"; +set dcLen = 5000; + +#NEWLAYER: anovelconundrum/clippy +layerinfo "type" = "theme"; +layerinfo "name" = "Clippy"; +layerinfo "redist_uniq" = "anovelconundrum/clippy"; + +set font_leading = 13; +set page_back = "#FFFFFF"; +set font_fallback = "Times"; +set font_base = "Times New Roman"; +set font_secondary_base = "Helvetica"; +set font_secondary_fallback = "Arial"; +set font_secondary_type = "sans-serif"; +set font_secondary_size = 8; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.1em"; +set flourish_rm = "0.08em"; +set dcLen = 99999; +set body_width = "65ex"; + +#NEWLAYER: anovelconundrum/childsplay +layerinfo "type" = "theme"; +layerinfo "name" = "Child's Play"; +layerinfo "redist_uniq" = "anovelconundrum/childsplay"; + +set page_back = "#FFE6FF"; +set font_base = "Comic Sans"; +set font_fallback = "Chalkboard"; +set font_type = "cursive"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.08em"; +set dcLen = 1000; + +#NEWLAYER: anovelconundrum/laketahoe +layerinfo "type" = "theme"; +layerinfo "name" = "Lake Tahoe"; +layerinfo "redist_uniq" = "anovelconundrum/laketahoe"; + +set page_back = "#E6E6FF"; +set font_base = "Tahoma"; +set font_fallback = "Verdana"; +set font_type = "sans-serif"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.14em"; +set flourish_rm = "0.08em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/deardiary +layerinfo "type" = "theme"; +layerinfo "name" = "Dear Diary"; +layerinfo "redist_uniq" = "anovelconundrum/deardiary"; + +set page_back = "#f9f7d6"; +set font_base = "Lucida Handwriting"; +set font_fallback = ""; +set font_type = "cursive"; +set font_leading = 16; +set body_width = "38em"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/scribal +layerinfo "type" = "theme"; +layerinfo "name" = "Scribal"; +layerinfo "redist_uniq" = "anovelconundrum/scribal"; + +set page_back = "#FAF2C8"; +set font_base = "Lucida Calligraphy"; +set font_fallback = ""; +set font_type = "cursive"; +set font_leading = 15; +set title_smallcaps = false; +set title_underline = true; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/glossy +layerinfo "type" = "theme"; +layerinfo "name" = "Glossy Magazine"; +layerinfo "redist_uniq" = "anovelconundrum/glossy"; + +set page_back = "#F4FBFF"; +set font_base = "Lucida Bright"; +set font_fallback = "Georgia"; +set font_type = "serif"; +set font_secondary_base = "Lucida Sans"; +set font_secondary_fallback = ""; +set font_secondary_type = "sans-serif"; +set font_secondary_size = 9; +set font_flourish_base = "Agency FB"; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.08em"; +set flourish_rm = "0.02em"; +set dcLen = 1200; + +#NEWLAYER: anovelconundrum/retro +layerinfo "type" = "theme"; +layerinfo "name" = "Retrossential"; +layerinfo "redist_uniq" = "anovelconundrum/retro"; + +set page_back = "#f9f9e3"; +set font_base = "Rockwell"; +set font_fallback = ""; +set font_type = "serif"; +set font_size = 11; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_secondary_size = 10; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; diff --git a/local/bin/upgrading/s2layers/boxer/boxer.jpg b/local/bin/upgrading/s2layers/boxer/boxer.jpg new file mode 100755 index 0000000000000000000000000000000000000000..9299e77bf752a8accddab1d1438ef424f96d513b GIT binary patch literal 12699 zcmdUVWmH^Cv*^I!PH-nU!QCwc2=4CA;4VQzAh-p03m)7V+zIXsuE8Aw1b>|K-E;2x za?gG5uD9NwS9{Nz?&|8U>h9{Q>hAqK|GW;skdc&@1VBLp0A?=_;Q0uE`OeMM#tQ%i zfB^sif-k5O0GgPYgNZr7tn&o}^}Gc541j}yfq{jAgN21dgnRiRBf!BSAfq55AtNE7 zV4(a77$|7y80csySXkKDSXjhFL`1}7e*+XeJUl82Dn14VJ|PY!4&mPg|I@^CCjb)x za0kT*gu(+O`dOQ2dp z9nYDGb6kyTEhiWE#(99LYd5uo8v+gHiww{&;{ykT0=&F00EG#y{0fNmS_KB1O^gHQ z%s9829o8w9;?ssR=j8Ju0Of@Y8WV^K5CQzm^0*!7Z{m&|TT(S}C1cpKr-U5yW?ig8 zl(O&%S_X+o#U)HZoFojFZ63-c_I17bY-GRu@~&2x6Bltu=X%G|!1gE~&!=BGxRhS7y3l=my{y{@ zRY9o^u2{=>88)rBT8eXLnN7ojQneNkpsVXP&JusRktpOFvf(NA z3frgWPi69^HV9Lf-<$UNp1K8(Cosf#l#Vh#CdE*9OkNK}2&^7XVV_)iZvN+Q&a?I9AphQ9dO>GVg!FCX|(n;fNdQz z*xzbE-<^DmiD#WP~ACAz5$0QIv@lT|bRNgR31>Ke~Q{yJ` zccVGx&7h!EO51!Wtu%RfX+woZbf5^zA!!jXSv_k}Tk#+3U%P~aRsxb!O>rhR5T^oZ>v z>5YntO6-IS!2sxAah*mKMYj7grz_aST%te?EZcM2G&Vg0R-DJ4Uii5$`c(OLZ23L5 z{Tx%+df^9=O+s&6c35j{vc0vWbt)O9wJREiUwYy>U0Rd-al*xyf9wi2_R8?;FH&sx zg0Q&se~%z(a}(oWCG>%{ANBrqo-A-@$D8sDV4aJx(sPG}>+pf!%}Br5qF>s-==R+> zU;DWB!IGiFkKO&wrz*x%&rRp?qp#sOpZxuKeB<Iu{o<1IHH>;_`S&zSliyU6$Y!wzby+4)vvDQH# z;47?UY4zaSf3YI7z_kRa(^+W+GQ?;nP4N}2JHon7&9&Q~CkyE#Q>bNh9m&_t`v7DZ}414N$KPN=6>Z0E$FqMcqde~CM&NdRKW ze{I2KP6u`KHtX8WZVBQ$9AyQ7Wy{z-^B(;!3$i!3e1#NCL`W5r^M7t_jYb)BXA_y( z{Xk0*nw+Te*XdNa_zZbPS8cXL%DS4bFA_N!OZ6bUN33hdV6R^V??x2pZW_(k@W9~W zo+(IECefUD9?p2+403S&sM)`_NC>=~D~tk;c`!+9&!k(PJIJua44U*jJXY@JJJ0k1Jp-nM)xqZ`f&`8rO&-j*dvF(^%al#vnQ4WI!H1kH1!Sip4r1by z+0fL=xT3ue5%2Q|*RLJ4#1~YCH0sJF@h2`A_%$)hts^quT&$AZFRpZ!4nOr*f!wzHp|ZmVo>n?k2xP(Dmx^eur#-y z0j7s5&j8`^dB4hMK-Sv*4T#Ainzr>jgs;-rQf-?&%~a1TdC+_kz2V-%hoEeZY4Lkk zbp)rq6UfTOTO$96$hjeKpx!OYYCD8rA`4_{puaeZZ5zB$#aC2zJx$1oCdwzF!O~8{ zD?!3ovzNu8L3B@>Q=xK*lJzqChOPUSzvK-SRSy&g;Mbdp?UCcIP4FKkBuHGkRcjmJrqDq$#_)&FHPB^-~x7{x>YH_ z{zH}X%Q$#@{y~$A$VlyYsR#q#vcb4iDD1CF%UHU>0n|#>atto$^xot9OTU(Qi}Wk` zv9IJA@MHL~raj7V$dEf`gRI8@($rCkn#T{8EYT&fbZc z!9UR{uCkDnprO&ToDAUyi*0T+1Fm8b*;RNXcQGZoTExy+D8D`0EvCi0>SJm)PCm`8 zF!9#drRFK0JlUVeOp0vj34MLC@)f?ZWPAoVdUvF^n*LP$HND8P6S#V`oqdAtad8vr z7xoMw^p;qj@LtKNeeCqjmJ=h>8i;u;dH@~WT)w^Ee!+I{RCdO#S#zw^Dn)Y->4=jM z4H9S()saCTmfp2gG+T1=?mew8F-16!!_l^Y?uS_3Jp-a#t|P#?(|<6^Jz4a-jChep z(W)g4-Mco)FXV43p|2-aLMLO|cg(u?0%;7P1^fx`B(GaPVVw`Hd(Adp@x1HZ`P_2D zEhlH5MERJk2ku+b5uc-)cB7@=*U6q;8ATa5VcJgcE(f2!_r=a8^wwXVXg{}P%sRC9 zo+6W=?a!L^;G}KU9;R(x%K8~HDScj4zcPw^it9W?a#XWd7gPSa_oEwae^I^uD17U} zFvHzit!$K(dQ+Q45w>kgT`)gAB7xT21=&u;Vs>ToVX2nm)MIAD5@wQ?@ILeXBDy$j zfAw*ri@4vh17p@-n5-oaPSXDoqIA|bUf&17;Aa<)JJU3?AM%c`;l>_Yh#k4i)Pz7d~W=fqC*S5(A287(5S&pFKMu1 zlu-MT(T%K^*$tQX8pa0#Vb1IO>cADI?ZmlzvR2$=C0_?vd&2(urBpih_mHiaOO5h9 z=J4}i`^TtS#Y;vJXP(C^hduLOvq$#*Sj%?Zihm)dt22ylh#cdWqn-i2x_1PAoG%pU zPK}6`*6rUbPTQnt%7H>EV?}*I!IISwe{wU;Ap5?d{Oi zo2phud`(D7?Rfe)(*?S_hCqwFW})qFTpVM(i4B}w#~|eMM?Ur{5fv31KgiyFF|bA7 zF^fU%O^r4gG&Wyx93!tUfA}3ua2JBXxYlnhO6+fM#B03SA>XX=rD8td6c0s9N)wqG zmlD639>Y-c|KC7>my(-acnvu@`Rcix&*UqRur2e_) zEA)R4h}&YbnkHqT2nc+S8d)7IU5{U)#PI}Lx3)w_Z1nnDuar1i#)P@vsnOve{NFzO z%_!(^{$Rn$pHahoCrT{ZgYHi$r~k9vONnRdcDMgid-6CP(Z0{cpNTio+Hz&Ey^%db z{5O4+46TWv$_hu1f7T-gW(%IfOy|;phFa3_~wu z*R&`@u$W0dOmFa=!tiTahG_g*IO22bG1o$RQ&YX2W^!vQSPp2=x@zcXEj!x=L{t#^ zq|~c=_j*_<|=*3m3X>}WI)$CH9Xdm8t}bsgjEF9wj>(H-S3@#o*J5-V$z*KlTD z>7goMZ}UQ_ee$iSMu(~Ig$Ih)GV!Yh(A$*POdh#O(e3|=Rn=wuP|*+eA#>xU7{0J{ zmm@H!eES9)<4?5=xElD;!MWBRhy&3Wr6M3i=nT){-&x78pW?*)gfkyV3*mI$wRDV( zWQU-@GvSm`gsg((L+dNyWZc8%Z4AUm5`)wa@3cT5Z)^IwoFBax7X`++7A>`}h-)}` z(2TzqsLNKAr&*a<3AkTw2CS1$M2h9Y!fQqoFMs<(>n9G#4(#_GzR=AGGF1wD`|6yJ zCBdiIJ5c9(mHN9XqR{4jgBNF5dT0Gm4nAN8TX-{MkY2I$i>a{ka}Ay z@z|d3OP%qR&(t$o8hO#|aA=2jVrHFE*uX8c?A+$Fqg`P~byI+)y=kLeo%t8sULC3^ zaLO{@*hM`x4KCsC!YInuAH%q^U;<9#?XFCzVBEBmR%z?QKLr!dpqG^ml=)3?Hwf(?(QF)RV!Ge{k6`ChGj91=IatzF{s`hwKCfJD;ITj%L9W zf9T~Z{?tx5-Loze>T}-Av}A(POFXZM^h=OlT^bx30wg%Rj&fQ=Tl9QYTmo?f-$tV5 z%rDaquAfoMuvM@R;S(L%PJFg73$n%FM(VOPykv0 z(V^9$1YbV`*r&!sL53u+zBO_NNbR5w0RU)`7`jRr7zRxb$vaCo6GrJN=|p)fP(7># zUea__dVTmV#An2a-K~2}Jx;{R!aPk}v+g*=MKG9lf=;^jtLu>PD{DSAOgkrRje9UD z;kiyjUh;+*+sOQ8RCN4nBfbUwdV8eLF5KMx5a}=Vc^nK4Wl(T>zQL~O6lk@v8t-6W z2uZ{r?bSd8E9(8PL@%FIit6FIext(7ZJQ{W%zmWTgDnD&tRGQY0 zGTLMtg~PQRvOV(t4ANbX$kgI0Z2`V2=^+4z!;RzPlLUQEyV$m~l1h~69+B7PapZ@{ zjZG{Vhq9e`s1e8U)&(Gnd=`ccKex}oXRdWAjEXc<9)yW8i&fZMf2f(^VWOX1nfO_f zzKJ9hbF?3A3FA0SjNrm~&;7-bJT#3BX*>e;XEyIi{I-(H?>7I>b;kX&&Y)%nh=B&g z%PrD08KL+gk)lS-tDJRlHZ?)8O~sRQe4^|Y#`cTX3VkrT(DP{|q7!79K}Bq|HSXj; zu7rfoZ#<|Q;zZc&rGj~ntST6=kPb}_`Y@bOQH@`*Hokg~{X_TNz^s{36Av9xf6`nY zIq~vAWYay$9_c$0b9J*9kCrP!ML?uh+B+eVaxn~FbS zc>F~pDkEiXd$Pdm+7&-Rc1uM1E_QCnDP3=+ja=1=Hh@F*2J{L@+1rWQ+6#tz?{5S!|}T$ zQ$EG?qQ8OIhph|4bcZ#uPV1x-{-BK&83S{Hnz^P%t1}m7=fZlJikXvTiZ5}O3H23} zrl2a<{OCfuhaC=DU15v5=BCT=OQyWUnd4=9d+A`+*FtaSnlpo^jf(htONvG1XS-Zg z@nUBfZ9*%K!G6aoQkuj@JvcfeggmKf$f1QJ5?)D@j7Ch+Wzh*l%g3-Y-?`P{Y(H|3 zefpv1mNE1%8z*w$@TZOA#pk@v1j?{$@HEqX|GpTa9{qiTcAYmw<+HQ82?N%7ME+D{ zrs>V@Xf1<@%44VJJZi@{KzwQyIP6%n;~ z+2#JdY+~oWLuSvF)Lf_6W#n@~>0W!yx~__(j4O7$o^6Up2Rss8#2i>r`lQ(w1DG}C zVL9a^V4f+Tt!BkUF`3_k3uFjc+{2RJ9jZ&N%_k=t&>XW9er9X^o)``JK0}L5ifnD` z@pjQ0WVT*IOQVmj zPun5XHOF?aECjM0fVNw=GL1IXW(Uu7ehRjBuFx2@Pw86xRZz`a%N0dXyN|mVsVb=r z#3#L=v!VQ~=ACgO9WN)r=23cP7?sxkPznUO zGBj7?P6+4c<|bfGaK?9xp4LddNe5tyBC{i@Efq``N>||-S2Tl2UW08iC`!=?m`(f(u_&KuBk`MojSQm3lNK*!%8%j=f%;s z^(}lmjwUx=f6>SC1txIp_Cl09@23!da$VgTT^GvXTEZhIAUZ%yO=EJjZ4GfUgrQrVu^esuEC4gyj_MgAPf_QM$xNA~pH+J3Vwr>Oa1)Oa6Yc z=!1=?IRmU!kZ(?lZ(agy#({56OJN8^q33z;;jM6pltcqq>4?Ne-arHXN+2#v$-sT# zR(b^ux1A1rPu!gsml4VUod7W6CO;^x{=*HEx?I=y5zCt%1J&wlW-FP>^OjH6gT3(k z=ism;>-^uyYnD!fmiV1GFfKln%jT(=(CCFM*|VRnh+n6EB=A_MMew1sVOn6~xeILta)nJD9ViusKOOzdmg0 z{SA1`CBlg+KFpA7(H+vY4_f0hjj%aP{J_izVKD~cA>(MHdb>xu#j{LfSR^s6mVE1${mPvB2^;~;AgKe2ht5mmQ-PKO zg92G|#Gg)znH|x}K~>mM0*>14 z+qfBG#ozUY3+3%ECieCW&Q9aeJ?Gg##b^2ZOP>hi28d-V2y|fBQ{;s;;v!K|owIjl z96iXHi9rFe%H-V#R#hkDm#xKTPib)6x5Xg;Ay97)4-8W#Yj;s-$v); zBy{SvUTo68z>QmYnzy-s2${hqG~L0zi&&nu>dRa>QhdFM>&7D2N$A&SKwC8Tqcxdm zA9t>I#JD%H-QA4vr?7f>C$Ce}s1BWw2{!JW6BeN(r^Z92J2;vdlD^&lsL{I^*wlJc z-M>~YzK5T#)15P zKL`97&G;Yb9R8vk_ZD>cPf;vi&XWF9mh-=5*>|Xq=4Q6KDt4m0K-vAH{nb2Bsg76Y z1qX_ z|Bx9IGn}GsO5dH5M})HVn7HRhP5dIGJ$ZpyXn1Mdz+3ZN7dO=7>AaD-;I=ZGOSIBY z(M6>jiv{K&>~q6_;h+encaSlgVN(0hS4Nxs{-|rTJS#Foy}A*YXI7v437oHagtdvq zGn{c}_*02O-C+$Fr|^Pe&_W}k^Dpk2qcEE^jqT?yU!e!d3{5R7qgJBhj#0OG>ych} zuM*dZ%I#3 z&^`lPV3MjwtYBx+;0nuaYNi5#F^LQe+)ELJ$oh!g%3O!@>ld$GbT*MeftfRBo;YRs z?@R{Mr8lm{+U!eHE28?}aK@RV!n^Nmqgj;{+8aVACZ^lkY|3x z3EUtT0tlc?hxKfvh!-TWHELAoH`}f}(AvfsXY{@=LImNt`sSe$++n3Fx+XVNYQT1V z7Rd5I7yJ8&eUup5If`f=6n}x(zKT(e(mo2NK0FP60aKUb$^#ux;<3{R$e^4M6>jJY z+gA1g5O4*Q9)oA6e964t9(x5Z@+P2Pl&f4P!x^5w0O4$-rDcIhx|_fNU>Ll*T@Q zVKyROA{mZSx2+le(v$DpdVCr@hwvx`n^M7oJAjO!Jo5fPOO{W6OsvLM-NfgDIK$+s zen0iWV62Q>m$I#1;qjoT9KB^7Ft|wSf&2TIfbN%-r~Ae~9=pP)RhE za%XU~`RVSS>@%bw8*n4NTioWI%fI~fszzm5W4C4^uihy}X-#h(fD%vFmmfPr9Mq*V z$cBBc=a!7p0HP#}jEN5P;FjW4i`8j-&5Lxg6_6O0v>C?OPhmCSjAD#k{N0J7wRH{J$?)>hV6e+s zme@qLc#%k)nvhTronFYkN&pn#B+^61f|Ra;k}MB4@`T~a7u+dDTXc6^6o%Q%-gc%r zvs4?T-ea;FnVM4`BamLGBCWcAIAM4awsCF@lE_;kPL^EXb|H&x!c^KxOFAxApntMz zV_OFkBcm=eLG9An$lGYLzEY$?eFnriX@4(VXeBj|pQCEV1dn4*Mjh1TG-9S)hClXh zN^0O1j$(q*QW;O@scc69C~U90Gg=dVsfX9P38uUp@cug_T`x@u77GWat zmjHvb^^Vl=dh|hh_8A~{-)b|z@5}4CVpzgV?~9)D@0+vVb7D-#jrm?m-tujKT*f`z z|CD|?gn7AAuwCoTH2g`{(%%-HJRK4>dl$FER9Ti66gzA-nALgrT^>22RAyr^h#&6* z@4J5FJhkbxIjF*ZSt~@Ra#0sWZYqCC!F`EQe0bF=$JdKKCb>-w0YUX6ItV$V`suI2 z(pafxj)k0eJj*3ziGl5NhbOD1uz{Q}ei>N=p;Iz(LiMogqr=^dq z)56!Gl{qAlRafSR`pxSw+M-=Dv>ZKM4&TyO@cxm27KPbqy>D0Ps$X5RyNry3ZR8}=pGje~<6$bo1F#kr)|oWLQj1=8bw)A_eI{yXuv zTlQw!BbB(l*^Be{4;+44=m_KQ*c0)H@+M&^LMJM{qV8kKz5Hz#`FobSt>I_Pn}0I~ z*nR)#;Kg#!X0NNL;^5hNja_sZR-FhMzD!0D!b;EcL1eEe<~Zvtt{XP0YBn|A>g}a% z&hf3oW1zA@*$Wa^gjT}-a^2gS>YKg#sl0-lT(c1A9g(L0{v03r=mTBTSUpYr=ACKL zC_!FV3=sb|WsoE>+7ZozwSx28u^XuCasl(@vo%W_9f7(9Q^o{E8(!uBYo)9AXr=>{ z>B{QkimE&phn0D8o}P^RA3j#DN!Z#`)-kcoR`ivpvkLv4w`jq#7(sV$g6!6m*OJ_DyUM=in_R{Jrs6w zXDK9<&lj#{k-0{rT^qS;NxX%sxIRcA&jdf?(OThVqYQ=S zk#&ZskB-2iq&sgWw!Gr3JG(Df#ypy>8ON%dPrJAMYGl!Lu#4lc%@@x#pRVJ{)DrlZ z!acKs$`|t)+IoX8%1aryRsYGAZMhZ2-}mmjyElW0!gq z=q)_=YC8HRvw*>!zOg9q^)l+w`BxqiqEfoh`laD;6;nybwht)nNYi=*?u?~&SMLry zDQ=k3P^i7HG`dUGZcm?fBwxx(zMgFnukhVuI?r_s_Q>LT?-ilb;(6#ck&4BUUoQx> zapUW0OM*Q3f#T(35|(?5C#r*IK+fYT*O6;`hM;}rO!6DfHnGv5$HnFYp2KJ%(=hRkeoaNm~8_R3y-Gzo5qsK@MaxU-xm;MJrFDxUB~{Ev3*!PX_xAN z^Pqps_kCsiFn0LE`^?fgdr@kVW_;xLqJpO-@>sB8?v9;UZWD}}?L%CPYPg3Xb% z+%_3Ay2fW!d~g(&wUfdQtNzCZZ$45;hbWpiEa9#KB9K_vraN6V{6;w-#z)6bljrEt zxve0E=z5}lN$i%HF%vlxmiq z;Czddq9;j0l$tIW3;sM6ESP6cKGOnIf;$`LV#n0l0;Ufw)nkJpRZ^D@XQKE$ zg8D1}Un401Ir+sipuu5Nq4ExWWy@edcE6|p;8EJiD7I=k_9fV6cH*Ln-=HJN+$Bj^ nbcaF8av41%SKEjl4SoIhApe)d-=iK~>h$CPefTHxyzsvO2D}Xh literal 0 HcmV?d00001 diff --git a/local/bin/upgrading/s2layers/boxer/layout.s2 b/local/bin/upgrading/s2layers/boxer/layout.s2 new file mode 100755 index 0000000..9dccf86 --- /dev/null +++ b/local/bin/upgrading/s2layers/boxer/layout.s2 @@ -0,0 +1,1997 @@ +# -*-s2-*- + +# Copyright (c) 2003-2005 Danga Interactive. All rights reserved. +# +# NOTICE: The Boxer style is not licensed for general use, and may not be +# used in any production sites. We provide the source to The Boxer so that our +# users and designers can learn the proper way to extend and customize the +# style. + +layerinfo type = "layout"; +layerinfo name = "The Boxer"; +layerinfo author_name = "Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo redist_uniq = "boxer/layout"; +layerinfo previews = "boxer/boxer.jpg"; +layerinfo source_viewable = 0; +layerinfo is_public = 0; + +############################################# +# +# Properties +# +############################################# + +propgroup presentation = "Presentation"; +propgroup presentation { + property int page_width { + des = "Page Width"; + note = "Set in pixels what you want the page width to be."; + min = 400; + } + + property string page_align { + des = "Page Alignment"; + values = "left|Left|center|Center|right|Right"; + } + + property use text_view_recent; + property use text_view_friends; + property use text_view_month; + property use text_view_archive; + + property use linklist_support; + + property string links_name { + des = "Links Title"; + } + + + property string links_divider { + des = "Links Divider"; + note = "This appears between each link to seperate them."; + } + + property use page_recent_items; + property use page_friends_items; + + + property string my_date { + des = "Date format"; + note = "Choose the date format that will appear by each entry and each comment, followed by the time."; + values = "short|2/5/80|med|Feb. 5th, 1980|med_day|Tue, Feb. 5th, 1980|long|February 5th, 1980|long_day|Tuesday, February 5th, 1980"; + } + + property bool color_forms { + des = "Form Elements"; + note = "Select Yes to use customized form elements."; + } + + property bool show_mini_calendar { + des = "Enable Mini-Calendar"; + } + + property bool show_entry_userpic { + des = "Recent userpics"; + note = "Select this if you want your userpic to show up on each entry of your Recent page."; + } + + property use use_shared_pic; + +} + +propgroup color = "Colors"; +propgroup colors { + property Color bg_color { + des = "Background Color"; + } + + property Color color_nav_bg { + des = "Navigation Background"; + note = "This is the base color for the navigation bar. After selecting a color, select if you want that color to get darker or lighter (from left to right)."; + } + + property string nav_scale { + des = "Navigation Background Progression"; + note = "Select if you want the background of the navigation to get lighter, darker or all the same color starting from the color you selected above."; + values = "lighter|Lighter|darker|Darker|same|Same"; + } + + property Color nav_link { + des = "Navigation Text Color"; + } + + property Color info_bg { + des = "Info Background"; + note = "The background to the area where the user information and calendar are presented."; + } + + property Color info_font { + des = "Info Font"; + note = "The color of the font for the text in the information area."; + } + + property Color info_link { + des = "Info Link Color"; + } + + property Color info_link_visited { + des = "Visited Info Link Color"; + note = "The color of a visited link in the info section."; + } + + property Color entry_bg { + des = "Entry Background"; + note = "The background color for each entry."; + } + + property Color entry_font { + des = "Entry Font"; + note = "The font color for color for entry text."; + } + + property Color entry_link { + des = "Entry Link Color"; + } + + property Color entry_link_visited { + des = "Visited Entry Link Color"; + note = "The color of a visited link in the entries section."; + } + + + # Non-visible properties go here. + + property Color nav1_bg { noui = 1; } + property Color nav2_bg { noui = 1; } + property Color nav3_bg { noui = 1; } + property Color nav4_bg { noui = 1; } + property Color nav5_bg { noui = 1; } + property Color nav6_bg { noui = 1; } + property Color nav7_bg { noui = 1; } + property string backarrow { noui = 1; } + property string forwardarrow { noui = 1; } + property string leave_comment { noui = 1; } + property string comment { noui = 1; } + property string memories { noui = 1; } + property string edit { noui = 1; } + property string mail { noui = 1; } + property string delete { noui = 1; } + property string screen { noui = 1; } + property string unscreen { noui = 1; } + property string freeze { noui = 1; } + property string unfreeze { noui = 1; } + property string parent { noui = 1; } + property int half_width { noui = 1; } + property int half_width_pixel { noui = 1; } + property bool show_links { noui = 1; } + property string bg_pattern { noui = 1; } +} + +propgroup background = "Background"; +propgroup Background { + + property string page_background_pattern { + des = "Background Pattern"; + note = "Select a premade background or enter a background image below"; + values = "none|None|background-horz-stripes.gif|Horizontal Stripes|background-vert-stripes.gif|Vertical Stripes|background-diag-stripes.gif|Diagnal Stripes|background-diamond.gif|Diamonds|background-hearts.gif|Hearts|background-lg-boxes.gif|Large Boxes|background-stitched.gif|Stitched"; + } + + property string page_background_image { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + + property string background_repeat { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + + property string background_position { + des = "Background image position"; + note = "Does not apply if Background Image Repeat is set to 'Repeat'."; + values = "top|Top|top left|Top-left|top right|Top-right|center|Center|center left|Center-left|center right|Center-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + + property string background_scrolling { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + +} + +propgroup fontsettings = "Font Settings"; +propgroup fontsettings { + + property string font_family { + des = "Font Family"; + note = "The default font to use for all journal pages."; + values = "Arial, sans-serif|Arial|Tahoma, sans-serif|Tahoma|Verdana, sans-serif|Verdana|Trebuchet MS, sans-serif|Trebuchet MS|Georgia, serif|Georgia|Times New Romans, serif|Times New Roman|sans-serif|sans-serif|serif|serif"; + } + + + property string font_size { + des = "Adjust font size"; + values = "small|Small|normal|Normal|large|Large|larger|Larger|hulk|Hulk!"; + } + + property int lineheight { + des = "Line Height"; + note = "This specifies the distance between each text line on all pages."; + } + + property string underline_links { + des = "Show link underline"; + values = "no|No|yes|Yes|hover|Only on mouse over"; + } + + +} + + +# setting layout +set page_width = 667; +set page_align = "center"; +set text_view_recent = "Recent Entries"; +set text_view_friends = "Friends Entries"; +set text_view_userinfo = "User Info"; +set text_view_month = "Calendar"; +set links_name = "Links"; +set linklist_support = true; +set links_divider = "/"; +set my_date = "long_day"; +set color_forms = false; +set show_mini_calendar = true; +set view_entry_disabled = false; +set show_entry_userpic = false; +set tags_aware = true; + +# setting colors +set nav_scale = "darker"; +set bg_color = "#f1ede2"; +set info_bg = "#d3ccc1"; +set color_nav_bg = "#da712b"; +set nav_link = "#ffffff"; +set entry_bg = "#275974"; +set entry_font = "#bfcadd"; +set entry_link = "#efe397"; +set entry_link_visited = "#f0ffc0"; +set info_font = "#9a927e"; +set info_link = "#ffffff"; +set info_link_visited = "#ffffff"; + +# setting Background +set page_background_pattern = "background-diamond.gif"; +set background_repeat = "repeat"; +set background_position = "center"; +set background_scrolling = "scroll"; + +# setting Font_Settings +set font_family = "Trebuchet MS, sans-serif"; +set lineheight = 17; +set font_size = "normal"; +set underline_links = "hover"; + +############################################# +# +# Printing +# +############################################# + + + + +############################################# +# +# Forward and back nav functions +# +############################################# + +function Page::lay_viewspec_nav() { + """ +
    + + + + + + + + + + """; + if($p.journal.website_url) { + """ + + + """; + } + + $p->lay_viewspec_nav(); + + if($blank > 0) { + """ + + + """; + } + """ + +
    + """; + +} + +############################################# +# +# Mini-calendar +# +############################################# + +function print_calendar_day_top(string style) { + """ + + + + + + + + + + + + + + +
    + """; + +} + +function print_calendar_day_bottom() { + """
    + + """; +} + +function print_active_day(YearDay day) { + + var string style = "calendarcontent"; + var string dayentry; + + if($day.num_entries > 0) { + $style = "calendarcontentactive"; + $dayentry = """$day.date.day"""; + } else { + $dayentry = "" + $day.date.day; + } + + print_calendar_day_top($style); + print $dayentry; + print_calendar_day_bottom(); + +} + +function print_inactive_day(int day) { + var string style = "calendarcontent"; + print_calendar_day_top($style); + print " "; + print_calendar_day_bottom(); +} + +function print_calendar(Page p) { + + var YearMonth y = $p->get_latest_month(); + + var string m = $y->month_format(); + + var YearWeek[] w = $y.weeks; + + var bool multiple = false; + if($p.journal.default_pic) { + $multiple = true; + } elseif($*linklist_support and size $p.linklist > 0) { + $multiple = true; + } + + if($multiple) { + """ + $m + + + """; + } else { + """ +
    + + + + """; + } + + foreach var YearWeek weeks ($w) { + var YearDay[] d = $weeks.days; + if($multiple) { + var int pre = $weeks.pre_empty; + if($pre > 0) { + foreach var int num (1..$pre) { + print_inactive_day($num); + } + } + } + foreach var YearDay days ($d) { + print_active_day($days); + } + if($multiple) { + var int post = $weeks.post_empty; + if($post > 0) { + foreach var int num (1..$post) { + print_inactive_day($num); + } + } + } + + if($multiple) { + print ""; + } + + } + """ + +
    $m
    + """; + + + +} + + +############################################# +# +# Built-in Links +# +############################################# + +function Page::print_linklist() { + + if (size $.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + var int link_width = $*page_width - 290; + """ + $*links_name + """; + var bool slash = false; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + "$l.title "; + $slash = false; + } else { + if($slash) { + """ $*links_divider """; + } + """ $l.title """; + $slash = true; + } + } else { + "
    "; + } + } + """ + + """; + +} + +############################################# +# +# Print and Print Bodies +# +############################################# + +function Page::print() { + + var string title = $this->title(); + + """ + + + + + """; + $this->print_head(); + """ + $title + + +
    + + """; + + print_nav($this); + + + """ + + + + + + + +
    +
    $title
    + +
    + + """; + + + var bool linkl = false; + if(size $.linklist > 0) { $linkl = true; } + if(not $*linklist_support) { $linkl = false; } + + var bool box = false; + if($.journal.default_pic) { $box = true; } + if($*show_mini_calendar) { $box = true; } + if($linkl) { $box = true; } + + if($box) { + """ + + + """; + + if($.journal.default_pic) { + """ + + """; + if($linkl or $*show_mini_calendar) { + """ + + """; + } + } + + $this->print_linklist(); + if($*show_mini_calendar) { + if($linkl) { + """ + + """; + } + """ + + """; + } + """ + +
    + """; + + print_calendar($this); + + """ +
    + + + + """; + } + + $this->print_body(); + + print_nav($this); + + """ +
    + + + """; +} + + +############## +# recent page +############## + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + + +############################################# +# +# Print Entries +# +############################################# + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) { + + var int entry_page_width = $*page_width; + var int entry_half_width = $entry_page_width / 2; + var bool userpic_view = false; + + if($p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username or $*show_entry_userpic) { + $userpic_view = true; + } + + if($p.view != "friends" and $*show_entry_userpic) { + $bgcolor = $*entry_bg; + $fgcolor = $*entry_font; + } + + + if($userpic_view) { + var string url = $e.journal->base_url(); + var string url2 = $e.poster->base_url(); + $entry_page_width = $*page_width - 122; + $entry_half_width = $entry_page_width / 2; + + """ + + + + + + +
    + """; + if($e.journal.username != $e.poster.username) { + """$e.poster.username:
    """; + } + """ + $e.journal.username + """; + + + if($e.userpic) { + """
    $e.journal.username"""; + } + + """ +
    $e.journal.name
    + """; + } + + """ + + + + + + + + + + + +
    + """; + + if ($e.security) { print "
    $e.security_icon
    "; } + + """ +
    + + + + + + + +
    + """; + + print $e.time->date_format($*my_date); + print " " + $e.time->time_format(); + + + """ +
    +
    +
    """; + + if($e.subject) { + """ +
    $e.subject

    + """; + } + + + var string metadata; + + if ($e.metadata) { + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { $text = $*text_meta_mood; } + if ($k == "music") { $text = $*text_meta_music; } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $metadata = $metadata + """$text: $val
    """; + } + } + + var string tags; + if ($e.tags) { + var int tcount = 0; + var string user = $e.journal.username; + $tags = """Tags: """; + foreach var Tag t ($e.tags) { + $tags = """$tags"""; + $tcount++; + if ($tcount != size $e.tags) { $tags = """$tags, """; } + } + $tags = "$tags
    "; + } + + if (not $hide_text) { print "
    $e.text

    "; print "$tags $metadata"; } + + """

    """; + + $e.comments->print(); + + var Link mem; + $mem = $e->get_link("mem_add"); + if(defined $mem) { + """ + Add to Memories + """; + } + + var Link lnk; + $lnk = $e->get_link("edit_entry"); + if(defined $lnk) { + """ + Edit entry + """; + } + + var Link tag; + $lnk = $e->get_link("edit_tags"); + if(defined $tag) { + """ + Edit entry + """; + } + + var Link tell; + $tell = $e->get_link("tell_friend"); + if(defined $tell) { + """ + Email this entry to a friend + """; + } + + """ +

    +
    + + + + """; + + if($userpic_view) { + """ +
    + """; + } +} + + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +############################################# +# +# Reply Page +# +############################################# + +function ReplyPage::print_body () { + + if (not $.entry.comments.enabled) { + """ + + + + + + +
    + + + + + + + +
     
    +
    +
    +

    $*text_reply_nocomments

    +
    +
    + """; + return; + } + + + """ + + + + + + + + + + +
    """; + + + if ($.entry.security) { print "
    $.entry.security_icon
    "; } + + """
    + + + + + + + +
    """; + + + print $.replyto.time->date_format($*my_date); + print " " + $.replyto.time->time_format(); + + + """
    +
    +
    + """; + if($.replyto.subject) { + """ +

    $.replyto.subject

    + """; + } + + + var string metadata; + + if ($.entry.metadata) { + foreach var string k ($.entry.metadata) { + var string text = $k; + var string val = $.entry.metadata{$k}; + if ($k == "mood") { $text = $*text_meta_mood; } + if ($k == "music") { $text = $*text_meta_music; } + if ($k == "mood" and defined $.entry.mood_icon) { + var Image i = $.entry.mood_icon; + $val = " $val"; + } + $metadata = $metadata + """$text $val
    """; + } + } + + print "

    $.replyto.text

    "; print "

    $metadata

    "; + + """ +
    + + Comment + Add to Memories + """; + + if(viewer_is_owner()) { + """ + Edit entry + """; + } + """ + Email this entry to a friend + +
    +
    + + + + + +
    + """; + $.form->print(); + """ +
    + """; +} + + +############################################# +# +# Entry Page +# +############################################# + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ + + +
    + """; + + print lang_page_of_pages($.current, $.total); + + """
    """; + + foreach var int i (1..$.total) { + if ($i == $.current) { "[$i] "; } + else { + var string url_of = $this->url_of($i); + """[$i] """; + } + } + print "
    "; +} + +function EntryPage::print_body () { + + set_handler("screen_comment_#", [ [ "set_image", "sus_#", "$*unscreen", ], ]); + set_handler("unscreen_comment_#", [ [ "set_image", "sus_#", "$*screen", ], ]); + set_handler("freeze_comment_#", [ [ "set_image", "fuf_#", "$*unfreeze", ], ]); + set_handler("unfreeze_comment_#", [ [ "set_image", "fuf_#", "$*freeze", ], ]); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $this->print_multiform_start(); + $this->print_comments($.comments); + + if ($this.multiform_on) { + """ + + +
    Mass Action
    + """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
    "; + } + + } +} + + +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment_partial (Comment c) { + var int count = $c.depth / 7; # get how many times greater is the depth than our 8 color choices + $count = $count + (($count*10%10 >= 5) ? 1 : 0); # round that number + + var int subtract = $count * 7; # figure out how many times we need to subtract 8 from the depth + + var Color mybg; + + var int multiplier = (($c.depth - 1) - $subtract) * 15; + + var int sidewidth = 122 + ($c.depth - 1) * 25; + var int entry_page_width = $*page_width - $sidewidth; + var int entry_half_width = $entry_page_width / 2; + + if($*nav_scale == "darker") { + $mybg = $*color_nav_bg->darker($multiplier); + } else { + $mybg = $*color_nav_bg->lighter($multiplier); + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + + """ + + + + + + +

    $subj - $poster
    +
    + """; +} + +function EntryPage::print_comment (Comment c) { + + var int count = $c.depth / 7; # get how many times greater is the depth than our 8 color choices + $count = $count + (($count*10%10 >= 5) ? 1 : 0); # round that number + + var int subtract = $count * 7; # figure out how many times we need to subtract 8 from the depth + + var Color mybg; + + var int multiplier = (($c.depth - 1) - $subtract) * 15; + + if($*nav_scale == "darker") { + $mybg = $*color_nav_bg->darker($multiplier); + } else { + $mybg = $*color_nav_bg->lighter($multiplier); + } + + var string poster; + var string url; + if(defined $c.poster) { + $poster = $c.poster.name; + $url = $c.poster->base_url(); + } else { + $poster = "(Anonymous)"; + } + var string sub_icon; + + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + var string ip; + if ($c.metadata{"poster_ip"}) { $ip = " (" + $c.metadata{"poster_ip"} + ")"; } + + var int sidewidth = 122 + ($c.depth - 1) * 25; + var int entry_page_width = $*page_width - $sidewidth; + var int entry_half_width = $entry_page_width / 2; + + + """ + + + + + """; + } else { + """ +
    $poster + """; + } + """ + + + +
    $c.poster.username + """; + + if(defined $c.userpic) { + """
    $c.poster.username"""; + } + + if($c.journal) { + """ +
    $poster
    + + + + + + + +
    $sub_icon $ip + + + + + + + +
    + """; + + print $c.time->date_format($*my_date); + print " " + $c.time->time_format(); + if ($this.multiform_on) { + $c->print_multiform_check(); + } + + """ +
    +
    +
    """; + + if($c.subject) { + """ +
    $c.subject

    + """; + } + var string replyurl; + if (not $c.frozen) { + $replyurl = """ +Reply + """; + } else { + $replyurl = """ +Frozen + """; + + } + """ +

    $c.text


    + + $replyurl + Thread + """; + + if ($c.parent_url != "") { """ Parent """; } + var Link lnk; + $lnk = $c->get_link("delete_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("screen_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("unscreen_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("freeze_thread"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("unfreeze_thread"); if($lnk) { """ $lnk.caption\n"""; } + + """ + + +
    +
    +
    + """; + +} + + +############################################# +# +# Calendar Pages +# +############################################# + +### Day view + +function DayPage::print_body() { + if ($.has_entries) { + """ + + + + +
    +
    + + """; + print $.date->date_format("long"); + """ +
    +
    + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + """ + + + + +
    +
    + + """; + print $.date->date_format("long"); + """ +
    +
    + + + + +
    $*text_noentries_day
    + """; + } +} + +### Month View + +function MonthPage::print_body { + """ + + + + +
    +
    + + """; + "
    "; + $.redir->print_hiddens(); + if (size $.months > 1) { + """ + \n"""; + } + "
    \n
    "; + "
    \n"; + """ +
    +
    + """; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + + """ + + + + +
    +
    + + + + +
    + """; + $d->print_subjectlist(); + """ +
    + """; + + } + } +} + +### Year View +function YearPage::print_year_links () +{ + """ + + + + +
    +
    Years: + + """; + var int count = 0; + + foreach var YearYear y ($.years) { + if($count != 0) { + " | "; + } + $count = $count + 1; + if ($y.displayed) { + " $y.year "; + } else { + """ $y.year """; + } + } + + """ +
    +
    + """; +} + +function YearPage::print_body { + $this->print_year_links(); + var bool toggle = false; + """ + + + """; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + """"; + if($toggle) { + """ + + + + """; + $toggle = false; + } else { + $toggle = true; + """ + + """; + } + } + } + if($toggle) { + """ + + """; + } + """ + +
    """; + $this->print_month($m); + "
     
    + """; +} + +function YearPage::print_month (YearMonth m) { + """ + + + + +
    + + + + +
    + + + """; + + foreach var int d (weekdays()) { + " "; + } + + """ + + """; + + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + """ +
    " + $*lang_dayname_short[$d] + "
    +
    + """; + +} + + +############################################# +# +# Comment Links +# +############################################# + +function CommentInfo::print_readlink { + var Page p = get_page(); + var string count; + if($.count > 0) { + $count = "" + $.count; + } else { + $count = ""; + } + + + """$countComment"""; +} + +function CommentInfo::print_postlink() { + var Page p = get_page(); + """Leave a comment"""; +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + $this->print_postlink(); + $this->print_readlink(); + +} + + + +############################################# +# +# Property Initialization +# +############################################# +function prop_init() { + + # initialize the colors of the navigation bar. + $*nav1_bg = $*color_nav_bg; + + if($*nav_scale == "lighter") { + $*nav2_bg = $*nav1_bg->lighter(10); + $*nav3_bg = $*nav1_bg->lighter(20); + $*nav4_bg = $*nav1_bg->lighter(30); + $*nav5_bg = $*nav1_bg->lighter(40); + $*nav6_bg = $*nav1_bg->lighter(50); + $*nav7_bg = $*nav1_bg->lighter(70); + } elseif($*nav_scale == "darker") { + $*nav2_bg = $*nav1_bg->darker(10); + $*nav3_bg = $*nav1_bg->darker(20); + $*nav4_bg = $*nav1_bg->darker(30); + $*nav5_bg = $*nav1_bg->darker(40); + $*nav6_bg = $*nav1_bg->darker(50); + $*nav7_bg = $*nav1_bg->darker(70); + } else { + $*nav2_bg = $*color_nav_bg; + $*nav3_bg = $*color_nav_bg; + $*nav4_bg = $*color_nav_bg; + $*nav5_bg = $*color_nav_bg; + $*nav6_bg = $*color_nav_bg; + $*nav7_bg = $*color_nav_bg; + } + + # change the colors of the graphics using palimg + var Color dk_arrow = $*nav6_bg->darker(50); + + $*backarrow = palimg_modify("boxer/back.gif", [PalItem(0, $dk_arrow), PalItem(1, $*nav_link)]); + $*forwardarrow = palimg_modify("boxer/forward.gif", [PalItem(0, $dk_arrow), PalItem(1, $*nav_link)]); + + # tint the icons + + var Color entry_bg_tint; + var int entry_lightness = $*entry_bg->lightness(); + + if($entry_lightness > 120) { + $entry_bg_tint = $*entry_bg->lighter(); + } else { + $entry_bg_tint = $*entry_font; + } + + $*leave_comment = palimg_tint("boxer/leave_comment.gif", $entry_bg_tint); + $*comment = palimg_tint("boxer/comment.gif", $entry_bg_tint); + $*edit = palimg_tint("boxer/edit.gif", $entry_bg_tint); + $*memories = palimg_tint("boxer/memories.gif", $entry_bg_tint); + $*mail = palimg_tint("boxer/mail.gif", $entry_bg_tint); + $*delete = palimg_tint("boxer/delete.gif", $entry_bg_tint); + $*screen = palimg_tint("boxer/screen.gif", $entry_bg_tint); + $*unscreen = palimg_tint("boxer/unscreen.gif", $entry_bg_tint); + $*freeze = palimg_tint("boxer/freeze.gif", $entry_bg_tint); + $*unfreeze = palimg_tint("boxer/unfreeze.gif", $entry_bg_tint); + $*parent = palimg_tint("boxer/parent.gif", $entry_bg_tint); + + # background pattern + + var Color bg_lt = $*bg_color->lighter(); + var Color bg_dk = $*bg_color->darker(); + + if($*page_background_pattern != "" and $*page_background_pattern != "none") { + $*bg_pattern = palimg_modify("boxer/$*page_background_pattern", [PalItem(1, $bg_lt), PalItem(0, $bg_dk)]); + } + + $*half_width = $*page_width / 2; + $*half_width_pixel = $*half_width - 1; + +} + + + +############################################# +# +# Stylesheet +# +############################################# + +function appended_to_stylesheet() { + +} + +function print_stylesheet () { + + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + + + """ + body { + background-color: $*bg_color; + """; + + if(clean_url($*page_background_image) != "") { + """ + background-image: url("$*page_background_image"); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_scrolling; + """; + } elseif ($*page_background_pattern != "none" and $*page_background_pattern != "") { + """ + background-image: url("$*bg_pattern"); + background-attachment: $*background_scrolling; + """; + } + + """ + font-family: $*font_family; + line-height: """; print $*lineheight; """px; + font-size: """; print 12 + $inc; """px; + color: $*entry_font; + margin-top: 2px; + } + + tr, td { + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + + + + a { + color: $*entry_link; + """; + if($*underline_links != "yes") { "text-decoration: none;"; } + """ + } + + """; + if($*underline_links == "hover") { + " a:hover { text-decoration: underline;}"; + } + + """ + + a:visited { + color: $*entry_link_visited; + } + + a:visited.link { + color: $*info_link_visited; + } + + a:visited.subtitle { + color: $*info_link_visited; + } + + a.nav, a:visited.nav { + text-decoration: none; + color: $*nav_link; + } + + a.link { + color: $*info_link; + } + + + a.dayentry, a:visited.dayentry { + color: $*info_bg; + text-decoration: none; + } + + a.comments, a:visited.comments { + color: $*entry_font; + text-decoration: none; + font-weight: bold; + } + + + + .nav1 { + background-color: $*nav1_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav2 { + background-color: $*nav2_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav3 { + background-color: $*nav3_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav4 { + background-color: $*nav4_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav5 { + background-color: $*nav5_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav6 { + background-color: $*nav6_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav7 { + background-color: $*nav7_bg; + } + + .info { + background-color: $*info_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + color: $*info_font; + } + + .title { + font-size: """; print 18 + $inc; """px; + font-weight: bold; + } + + .subtitle { + font-size: """; print 14 + $inc; """px; + font-weight: bold; + color: $*info_link; + } + + .new { + margin-top: 2px; + } + + .entry { + background-color: $*entry_bg; + + } + + .newentry { + margin-top: 2px; + padding-left: 5px; + padding-top: 5px; + padding-right: 5px; + padding-bottom: 5px; + background-color: $*entry_bg; + } + + .entrycontent { + padding-left: 20px; + padding-right: 20px; + padding-bottom: 6px; + padding-top: 6px; + line-height: 18px; + } + + .date { + background-color: $*entry_font; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + color: $*entry_bg; + } + + .entryinfo, a.entryinfo, a:visited.entryinfo { + color: $*entry_bg; + } + + + + .bgcolor { + background-color: $*bg_color; + } + + .icon { + margin-right: 10px; + } + + .calendarborder { + background-color: $*info_font;; + } + + .calendarcontent { + padding-top: 2px; + padding-left: 1px; + padding-bottom: 2px; + padding-right: 2px; + font-family: Tahoma, sans-serif; + font-size: """; print 8 + $inc; """px; + color: $*info_font; + } + + .calendarcontentactive { + padding-top: 2px; + padding-left: 1px; + padding-bottom: 2px; + padding-right: 2px; + font-family: Tahoma, sans-serif; + font-size: """; print 8 + $inc; """px; + background-color: $*info_font; + color: $*info_bg; + } + + """; + + if($*color_forms) { + """ + .infoform { + background-color: $*info_bg; + color: $*info_font; + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + input, select, submit, textarea { + background-color: $*entry_font; + color: $*entry_bg; + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + """; + } + + appended_to_stylesheet(); +} + +############################################# +# +# Theme Preview +# +############################################# + + +function print_theme_preview () +{ + + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + +var int bigsize = $*page_width + 100; + """ + + + + +
    + + + + + + + + + + + + + + + + + + +
    Recent EntriesFriends EntriesCalendarMemoriesMy Website
    + + + + + +
    +
    Lou Reed
    + +
    + + + + + + + +
    + + + + + + + +
    8/10/06 12:09 am
    +
    +
    +

    $*text_reply_nocomments

    +
    +
    + +
    + """; +} diff --git a/local/bin/upgrading/s2layers/boxer/themes.s2 b/local/bin/upgrading/s2layers/boxer/themes.s2 new file mode 100755 index 0000000..bab3382 --- /dev/null +++ b/local/bin/upgrading/s2layers/boxer/themes.s2 @@ -0,0 +1,225 @@ +#NEWLAYER: boxer/lipstick +layerinfo "type" = "theme"; +layerinfo "name" = "Lipstick"; +layerinfo redist_uniq = "boxer/lipstick"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#B46F60"; +set entry_link = "#ffeae5"; +set entry_bg = "#eebbaf"; +set nav_scale = "darker"; +set info_font = "#A55745"; +set bg_color = "#fac7bb"; +set entry_font = "#A55745"; +set info_link_visited = "#ffeae5"; +set page_background_pattern = "background-hearts.gif"; +set entry_link_visited = "#ffffff"; +set info_bg = "#e5a799"; +set info_link = "#FFF9F8"; + + +#NEWLAYER: boxer/greyskies +layerinfo "type" = "theme"; +layerinfo "name" = "Grey Skies"; +layerinfo redist_uniq = "boxer/greyskies"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#9aaeb6"; +set entry_link = "#997D63"; +set entry_bg = "#f2eae2"; +set nav_scale = "lighter"; +set info_font = "#627a84"; +set bg_color = "#dde1e3"; +set entry_font = "#7f97a0"; +set info_link_visited = "#CEDBDF"; +set page_background_pattern = "background-vert-stripes.gif"; +set entry_link_visited = "#b4a18f"; +set info_bg = "#8c9ca2"; +set info_link = "#b9c7cc"; + +#NEWLAYER: boxer/eggplant +layerinfo "type" = "theme"; +layerinfo "name" = "Eggplant"; +layerinfo redist_uniq = "boxer/eggplant"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#4e6559"; +set entry_link = "#9FAE8D"; +set entry_bg = "#635A48"; +set nav_scale = "lighter"; +set info_font = "#899BA3"; +set bg_color = "#9fae8d"; +set entry_font = "#E7DFCF"; +set info_link_visited = "#b9c7cc"; +set entry_link_visited = "#A6B2AC"; +set info_bg = "#464640"; +set info_link = "#b9c7cc"; + + +#NEWLAYER: boxer/lonelyturquoise +layerinfo "type" = "theme"; +layerinfo "name" = "Lonely Turquoise"; +layerinfo redist_uniq = "boxer/lonelyturquoise"; +layerinfo "source_viewable" = 0; +set page_background_pattern = "background-lg-boxes.gif"; +set color_nav_bg = "#7f7f7f"; +set entry_link_visited = "#ededed"; +set entry_link = "#ffffff"; +set entry_bg = "#ABABAB"; +set info_font = "#000000"; +set info_bg = "#00b1ae"; +set bg_color = "#ffffff"; +set entry_font = "#363636"; +set info_link = "#006260"; + + +#NEWLAYER: boxer/legallypink +layerinfo "type" = "theme"; +layerinfo "name" = "Legally Pink"; +layerinfo redist_uniq = "boxer/legallypink"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#ff089b"; +set entry_link_visited = "#70086F"; +set entry_link = "#4D0870"; +set entry_bg = "#ec008c"; +set nav_scale = "lighter"; +set info_font = "#ec008c"; +set bg_color = "#f49ac1"; +set entry_font = "#fbdbee"; +set info_link_visited = "#CE1182"; +set page_background_pattern = "background-hearts.gif"; +set info_bg = "#ffadde"; +set info_link = "#E3026A"; + +#NEWLAYER: boxer/greybrowngreen +layerinfo "type" = "theme"; +layerinfo "name" = "Grey Brown Green"; +layerinfo redist_uniq = "boxer/greybrowngreen"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#2f372e"; +set entry_link = "#212919"; +set entry_bg = "#586C44"; +set nav_scale = "lighter"; +set info_font = "#A1926C"; +set bg_color = "#000000"; +set entry_font = "#D9E1D2"; +set info_link_visited = "#B1AD9B"; +set entry_link_visited = "#2C3F28"; +set info_bg = "#433a1e"; +set info_link = "#B1AD9B"; + +#NEWLAYER: boxer/precious +layerinfo "type" = "theme"; +layerinfo "name" = "Precious"; +layerinfo redist_uniq = "boxer/precious"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#A17682"; +set entry_link = "#0F486E"; +set entry_bg = "#c6cfd5"; +set nav_scale = "lighter"; +set info_font = "#F7FDFC"; +set bg_color = "#d9e1d9"; +set entry_font = "#6C7982"; +set info_link_visited = "#E4ECEB"; +set entry_link_visited = "#3F6A86"; +set info_bg = "#a2b2b1"; +set info_link = "#E4ECEB"; + +#NEWLAYER: boxer/purple +layerinfo "type" = "theme"; +layerinfo "name" = "Purple"; +layerinfo redist_uniq = "boxer/purple"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#78629C"; +set entry_link = "#F9F5FC"; +set entry_bg = "#62536C"; +set nav_scale = "lighter"; +set info_font = "#A38FA3"; +set bg_color = "#8B77A9"; +set entry_font = "#DCD3E2"; +set info_link_visited = "#A799BF"; +set entry_link_visited = "#ffffff"; +set info_bg = "#472B47"; +set info_link = "#A799BF"; + +#NEWLAYER: boxer/green +layerinfo "type" = "theme"; +layerinfo "name" = "Green"; +layerinfo redist_uniq = "boxer/green"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#748A25"; +set entry_link = "#EAF9D4"; +set entry_bg = "#748A25"; +set nav_scale = "lighter"; +set info_font = "#004C3C"; +set bg_color = "#254634"; +set entry_font = "#E2EED0"; +set info_link_visited = "#00EEBC"; +set entry_link_visited = "#EAF9D4"; +set info_bg = "#0E9B7D"; +set info_link = "#61EFD1"; + +#NEWLAYER: boxer/purpange +layerinfo "type" = "theme"; +layerinfo "name" = "Purpange"; +layerinfo redist_uniq = "boxer/purpange"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#151e1a"; +set nav_scale = "lighter"; +set entry_link = "#ffffff"; +set entry_bg = "#E7513E"; +set info_font = "#f6cab7"; +set bg_color = "#ffffff"; +set entry_font = "#FDE9E6"; +set info_link_visited = "#afe900"; +set page_background_pattern = "background-stitched.gif"; +set entry_link_visited = "#ffffff"; +set info_bg = "#91125f"; +set info_link = "#afe900"; + +#NEWLAYER: boxer/purplesalmon +layerinfo "type" = "theme"; +layerinfo "name" = "Purple Salmon"; +layerinfo redist_uniq = "boxer/purplesalmon"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#AA6B90"; +set entry_link = "#633F4B"; +set entry_bg = "#CEADB8"; +set nav_scale = "same"; +set info_font = "#F0B4AA"; +set bg_color = "#151E1A"; +set entry_font = "#6D5B61"; +set info_link_visited = "#7E3D33"; +set entry_link_visited = "#633F4B"; +set info_bg = "#D26E5E"; +set info_link = "#7E3D33"; + +#NEWLAYER: boxer/refriedtribute +layerinfo "type" = "theme"; +layerinfo "name" = "Refried Tribute"; +layerinfo redist_uniq = "boxer/refriedtribute"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#666666"; +set entry_link = "#336699"; +set entry_bg = "#e6e6e6"; +set info_font = "#999966"; +set bg_color = "#ffffff"; +set entry_font = "#656565"; +set info_link_visited = "#4d4d4d"; +set page_background_pattern = "none"; +set entry_link_visited = "#336699"; +set info_bg = "#cccc99"; +set info_link = "#666666"; + +#NEWLAYER: boxer/blue +layerinfo "type" = "theme"; +layerinfo "name" = "Blue"; +layerinfo redist_uniq = "boxer/blue"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#3A6A74"; +set entry_link = "#E0DFCE"; +set entry_bg = "#4F7B8A"; +set info_font = "#908F78"; +set bg_color = "#435754"; +set entry_font = "#E7EEF0"; +set info_link_visited = "#5D5C50"; +set entry_link_visited = "#E0DFCE"; +set info_bg = "#E0DFCE"; +set info_link = "#4E5964"; diff --git a/local/bin/upgrading/s2layers/component/component.jpg b/local/bin/upgrading/s2layers/component/component.jpg new file mode 100755 index 0000000000000000000000000000000000000000..c24108da4b02a63dec44eda30a19fa1b889f609f GIT binary patch literal 9585 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 HlZpQYSxnGu literal 0 HcmV?d00001 diff --git a/local/bin/upgrading/s2layers/component/layout.s2 b/local/bin/upgrading/s2layers/component/layout.s2 new file mode 100755 index 0000000..9873f94 --- /dev/null +++ b/local/bin/upgrading/s2layers/component/layout.s2 @@ -0,0 +1,2806 @@ +# -*-s2-*- + +# Copyright (c) 2003-2005 Danga Interactive. All rights reserved. +# +# NOTICE: The Component style is not licensed for general use, and may not be +# used in any production sites. We provide the source to Component so that our +# users and designers can learn the proper way to extend and customize the +# style. + +layerinfo type = "layout"; +layerinfo name = "Component"; +layerinfo author_name = "Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo redist_uniq = "component/layout"; +layerinfo previews = "component/component.jpg"; +layerinfo source_viewable = 0; + + +############################################# +# +# Properties +# +############################################# + + + +propgroup layout = "Layout"; +propgroup layout { + property string comp_state { + des = "Component Position"; + values = "right|Right|left|Left|none|None"; + note = "Components are the boxes on the side of the layout."; + } + property bool comp_friends { + des = "Enable Friends View Components"; + note = "Select No if you don't want components on your friends page."; + } + + property bool comp_navbar { + des = "Enable Navigation Component"; + note = "Select Yes if you want the main navigation to be in a component instead of the top bar. If components are not active, the navigation will remain at the top regardless of this value."; + } + property bool show_profile { + des = "Enable Profile"; + note = "Select Yes to make the profile component visible."; + } + property bool show_calendar { + des = "Enable Mini-Calendar"; + note = "Select Yes to make the mini-calendar component visible."; + } + + property bool icalendar { + des = "Enable Interactive Mini-Calendar"; + note = "Select Yes to enable forward and back buttons on the mini-calendar. Uses inline frames and javascript."; + } + + property bool show_links { + des = "Enable Links"; + note = "Select Yes to make the links component visible."; + } + + property bool show_summary { + des = "Enable Page Summary"; + note = "Select Yes to make the page summary component visible."; + } + property bool show_free_text { + des = "Enable Free Text"; + note = "Select Yes to show the free text component. The text that will be shown in this component needs to be added below."; + } + property string free_text { + des = "Free Text Component"; + note = "Add text that will appear in the Free Text component if it is enabled. Good for poetry, friends only warnings, general descriptions. HTML is disabled in all properties."; + rows = 10; + cols = 25; + } + + property string first_position { + des = "First Component"; + note = "Select what component you want to be on the top. Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string second_position { + des = "Second Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string third_position { + des = "Third Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string fourth_position { + des = "Fourth Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string fifth_position { + des = "Fifth Component"; + note = "Only applies if component is activated"; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string sixth_position { + des = "Sixth Component"; + note = "Only applies if component is activated"; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } +} + +set comp_friends = true; +set first_position = "navigation_order"; +set second_position = "profile_order"; +set third_position = "calendar_order"; +set fourth_position = "links_order"; +set fifth_position = "free_text_order"; +set sixth_position = "summary_order"; +set comp_navbar = false; +set comp_state = "right"; +set show_calendar = true; +set show_profile = true; +set show_links = true; +set show_summary = false; +set show_free_text = false; +set icalendar = true; + +propgroup colors = "Colors"; +propgroup colors { + + property string topnavcolor { noui = 1; } + property string backarrow { noui = 1; } + property string forwardarrow { noui = 1; } + property string backarrow2 { noui = 1; } + property string forwardarrow2 { noui = 1; } + property string ctl { noui = 1; } + property string ctr { noui = 1; } + property string cbl { noui = 1; } + property string cbr { noui = 1; } + property string url { noui = 1; } + property string mem_img { noui = 1; } + property string edit_img { noui = 1; } + property string tellfriend_img { noui = 1; } + property string tags_img { noui = 1; } + property Color outside_border { noui = 1; } + property Color inside_border { noui = 1; } + property Color system_border { noui = 1; } + + property Color main_bgcolor { + des = "Page background"; + s1color = "page_back"; + } + + property Color entry_bgcolor { + des = "Entry background"; + note = "Background color of each entry."; + } + + property Color entry_fgcolor { + des = "Entry font"; + note = "Font color for text that will appear on top of 'Entry background color'."; + s1color = "page_text"; + } + + property Color entry_link { + des = "Main link"; + note = "Font color of any links that appear within each journal entry or within each component. Should be visible on Entry Background Color and Component Background Color."; + } + + property Color entry_link_visited { + des = "Main visited link"; + note = "Font color of any visited links that appear within each journal entry or within each component. Should be visible on Entry Background Color and Component Background Color."; + } + + property Color comp_bgcolor { + des = "Component background"; + note = "Background color of all component boxes."; + } + + property Color comp_fgcolor { + des = "Component font"; + note = "Font color for text that will appear on top of 'Component background color'. (leave blank to use 'Entry font color')"; + } + + + property Color header_bgcolor { + des = "Header background"; + note = "Background color of all component headers."; + } + + property Color header_fgcolor { + des = "Header font"; + note = "Font color for text that will appear on top of 'Component header background color'. (leave blank to use 'Entry font color')"; + } + + property Color header_fgcolor_lt { + des = "Header font alternative"; + note = "Font color used for information that deserves a different accent, like the date and journal sub-title. {leave blank to use 'Component font color')"; + } + + property Color header_link { + des = "Header link"; + note = "Font color of any links that appear within each component header. For example, the navigation. (leave blank to use 'Main link')"; + } + + property Color comments_bgcolor { + des = "Comments header"; + note = "Background color of the header information for each comment."; + } + + property Color comments_screened_bgcolor { + des = "Screened comments header"; + note = "Background color of the header information for each screened comment."; + } + + + property Color calendar_inactive { + des = "Calendar inactive background"; + note = "Background color of inactive dates on calendar component."; + } + + property Color calendar_active { + des = "Calendar active background"; + note = "Background color of active dates on calendar component."; + } + + property Color calendar_fgcolor { + des = "Calendar inactive font"; + note = "Color of font on each inactive calendar date. Appears on top of 'Calendar inactive background'. (leave blank to use 'Entry font color')"; + } + + property Color calendar_link { + des = "Calendar active font"; + note = "Color of font on each active calendar date. Appears on top of 'Calendar active background'. (leave blank to use 'Main link')."; + } +} + +set main_bgcolor = "#ffffff"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#6D6D6D"; +set entry_link = "#333333"; +set entry_link_visited = "#555555"; +set comp_bgcolor = "#F4F4F4"; +set header_bgcolor = "#e5e5e5"; +set header_fgcolor = "#4D4D4D"; +set comments_bgcolor = "#E5E5E5"; +set comments_screened_bgcolor = "#ECECEC"; +set calendar_inactive = "#C8C8C8"; +set calendar_active = "#DFDFDF"; + +set outside_border = "#7f7f7f"; +set inside_border = "#ffffff"; +set system_border = "#cccccc"; + + +propgroup presentation = "Presentation"; +propgroup presentation { + + property use page_recent_items; + property use page_friends_items; + + property string page_background_image { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Only the default component background image will change colors as they are set in the Color properties (http://www.livejournal.com/palimg/component/bg.gif)."; + } + + property string background_repeat { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + + property string background_position { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + + property string background_scrolling { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + + property string font_size { + des = "Adjust font size"; + values = "small|Small|normal|Normal|large|Large|larger|Larger|hulk|Hulk!"; + } + + property string underline_links { + des = "Show link underline"; + values = "no|No|yes|Yes|hover|Only on mouse over"; + } + + property use view_entry_disabled; + + property bool show_entry_userpic { + des = "Recent userpics"; + note = "Select this if you want your userpic to show up on each entry of your Recent page."; + } + + property use use_shared_pic; + + property bool show_entrynav_icons { + des = "Enable Entry icons"; + note = "Toggle to show the memory, edit, etc icons on the Entry View page."; + } + + property bool show_recentnav_icons { + des = "Enable Recent View icons"; + note = "Toggle to show the memory, edit, etc icons on the Recent and Friend's View page."; + } + + property int lineheight { + des = "Line Height"; + note = "This specifies the distance between each text line on all pages."; + } + + property string path { + noui = 1; + } + + property string font_family { + des = "Font Family"; + note = "The default font to use for all journal pages."; + values = "Arial, sans-serif|Arial|Tahoma, sans-serif|Tahoma|Verdana, sans-serif|Verdana|Trebuchet MS, sans-serif|Trebuchet|Georgia, serif|Georgia|Times New Romans, serif|Times New Roman|sans-serif|sans-serif|serif|serif"; + } + + property bool color_forms { + des = "Form Elements"; + note = "Select No to disable the customized form elements."; + } + + property string base_font { noui = 1; } + property bool show_entrypage_userpic { noui = 1; } + +} +set font_family = "Arial, sans-serif"; +set lineheight = 22; +set show_entry_userpic = false; +set font_size = "normal"; +set background_repeat = "repeat"; +set background_position = "center"; +set background_scrolling = "scroll"; +set page_recent_items = 10; +set page_friends_items = 10; +set page_background_image = "http://www.livejournal.com/palimg/component/bg.gif"; +set view_entry_disabled = false; +set show_entrynav_icons = true; +set show_recentnav_icons = true; +set underline_links = "hover"; +set color_forms = true; +set base_font = ""; +set show_entrypage_userpic = true; + +propgroup Text { + + property use text_post_comment; + property use text_read_comments; + property use text_reply_back; + + property string comment_divider { + des = "Comment divider"; + note = "This is the text that divides the read comments and the post comments. For example 'OR' as in 'read 2 comments OR leave a comment'."; + } + + property use text_post_comment_friends; + property use text_read_comments_friends; + property string profile_text { + des = "Profile Component Title"; + maxlength = 50; + } + + property string page_summary_text { + des = "Page Summary Title"; + } + + property string links_text { + des = "Links Component Title"; + } + property string calendar_text { + des = "Calendar Component Title"; + note = "This is for the title of the component box, not the link to the calendar from the navigation. This title will only be visible if the Interactive mini-calendar is on. Otherwise the title of the component will be the current month and year."; + } + property string free_text_text { + des = "Free Text Component Title"; + } + + property string nav_entries_text { + des = "Navigation Recent Entries Text"; + maxlength = 50; + } + property string nav_friends_text { + des = "Navigation Friends View Text"; + maxlength = 50; + } + property string nav_calendar_text { + des = "Navigation Calendar Text"; + note = "This is the text for the link to the calendar from the navigation, not the title of the calendar component."; + maxlength = 50; + } + property string nav_info_text { + des = "Navigation User Info Text"; + maxlength = 50; + } + + property string nav_text_forward { + des = "Navigation Forward Text"; + note = "The text that appears in the navigation component or header when the user can navigate forward."; + } + + property string nav_text_back { + des = "Navigation Back Text"; + note = "The text that appears in the navigation component or header when the user can navigate back."; + } + + property use text_meta_mood; + property use text_meta_music; + property use text_permalink; + +} + + +set free_text_text = "About this journal"; +set calendar_text = "calendar"; +set nav_entries_text = "entries"; +set nav_friends_text = "friends"; +set nav_calendar_text = "calendar"; +set nav_info_text = "user info"; +set page_summary_text = "Page Summary"; +set links_text = "links"; +set profile_text = "profile"; +set comment_divider = "or"; +set nav_text_forward = "Next"; +set nav_text_back = "Previous"; +set tags_aware = true; + + +############################################# +# +# Stylesheet +# +############################################# + +function print_stylesheet () +{ + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + + """ + body { background-color: $*main_bgcolor; +"""; + + if(clean_url($*page_background_image) != "") { + """ + background-image: url("$*page_background_image"); + background-repeat: $*background_repeat; + background-position: $*background_position; + background-attachment: $*background_scrolling; + """; + } + +""" + margin-top: 0px; margin-left: 0px; + margin-right: 0px; + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + color: $*entry_fgcolor; + } + + td, tr { + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + color: $*entry_fgcolor; + line-height: """; print $*lineheight; """px; + } + + a { + color: $*entry_link; + """; + if($*underline_links != "yes") { "text-decoration: none;"; } + """ + } + + a:visited { + color: $*entry_link_visited; + } + + a.calendarLink { + color: $*calendar_link; + } + + a.header { + color: $*header_link; + } + a.headerLinks { + color: $*header_link; + } + + """; + if($*underline_links == "hover") { + " a:hover { text-decoration: underline;}"; + } + $*topnavcolor = clean_url($*topnavcolor); + + if ($*color_forms) { + """ + select { + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + background-color: $*comp_bgcolor; + } + + input { + line-height: normal; + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + } + + textarea { + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + } + """; + } + + """ + + .subject { font-weight: bold; } + .small { margin-top: 3px;} + + .header { + background-image: url("$*topnavcolor"); + background-repeat: repeat-x; + height: 25px; + } + + .userTitle { + font-size: """; print 18 + ($inc * 2); """px; + text-weight: bolder; + color: $*header_fgcolor; + line-height: 17px; + } + + .userSubTitle { + font-size: """; print 12 + $inc; """px; + color: $*header_fgcolor_lt; + line-height: """; print $*lineheight; """px; + } + + .header-item { + padding-left: 15px; + position: relative; + top: 5px; + } + + .dkLine { background-color: $*outside_border; } + .ltLine { background-color: $*inside_border; } + .medLine { background-color: $*system_border; } + .divLine { background-color: $*header_fgcolor; } + .tabBg { background-color: $*header_bgcolor; } + + .entryDate { + font-size: """; print 11 + $inc; """px; + color: $*header_fgcolor_lt; + } + + .entryHolderBg { + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + padding-top: 7px; + padding-right: 7px; + padding-left: 7px; + padding-bottom: 7px; + } + + .entry { + padding-top: 7px; + padding-right: 7px; + padding-left: 7px; + padding-bottom: 7px; + background-color: $*entry_bgcolor; + font-size: """; print 12 + $inc; """px; + } + + .entryHeader { + font-size: """; print 12 + $inc; """px; + font-weight: bold; + } + + .entryComments { + font-size: """; print 11 + $inc; """px; + margin-top: 8px; + margin-left: 8px; + color: $*comp_fgcolor; + } + + .entryDash { + background-color: $*system_border; + width: 100%; + height: 1px; + } + + .sideHeader { + font-size: """; print 11 + $inc; """px; + color: $*header_fgcolor; + } + + .comp { margin-bottom: 3px; } + + .compBg { background-color: $*comp_bgcolor; } + + .compContent { + padding-left: 6px; + padding-right: 6px; + padding-bottom: 6px; + padding-top: 3px; + line-height: 18px; + color: $*comp_fgcolor; + } + + .compFont { + color: $*comp_fgcolor; + } + + .compList { + line-height: """; + + print $*lineheight - 2; + + """px; + padding-left: 6px; + } + + .userPic { border-color: $*system_border; } + + .shortLine { + width: 20px; + background-color: $*system_border; + margin-bottom: 1px; + } + + .calendarInactive { + background-color: $*calendar_inactive; + font-size: 9px; + letter-spacing: 2px; + color: $*calendar_fgcolor; + } + + .calendarActive { + color: $*calendar_link; + background-color: $*calendar_active; + font-size: 9px; + letter-spacing: 2px; + } + + """; +} + + +function prop_init() { + + $*path = "http://www.livejournal.com"; + + $*outside_border = $*header_bgcolor->darker(50); + $*inside_border = $*header_bgcolor->lighter(); + $*system_border = $*comp_bgcolor->darker(); + + if($*page_background_image == "http://www.livejournal.com/palimg/component/bg.gif") { + $*page_background_image = palimg_modify("component/bg.gif", [PalItem(0, $*system_border)]); + } + $*topnavcolor = palimg_tint("component/top-bg.gif", $*header_bgcolor); + $*forwardarrow = palimg_modify("component/forward.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*backarrow = palimg_modify("component/back.gif", [PalItem(1, $*inside_border), PalItem(0, $*outside_border)]); + $*forwardarrow2 = palimg_modify("component/forwardarrow.gif", [PalItem(1, $*inside_border), PalItem(0, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*backarrow2 = palimg_modify("component/backarrow.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border)]); + $*ctl = palimg_modify("component/curve-top-left.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*ctr = palimg_modify("component/curve-top-right.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*cbl = palimg_modify("component/curve-bottom-left.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*cbr = palimg_modify("component/curve-bottom-right.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*mem_img = palimg_modify("component/btn_memories.gif", [PalItem(10, $*inside_border), PalItem(14, $*outside_border)]); + $*tellfriend_img = palimg_modify("component/btn_tellfriend.gif", [PalItem(3, $*inside_border), PalItem(2, $*outside_border)]); + $*edit_img = palimg_modify("component/btn_edit.gif", [PalItem(12, $*inside_border), PalItem(14, $*outside_border)]); + $*tags_img = palimg_modify("component/btn_tags.gif", [PalItem(12, $*inside_border), PalItem(14, $*outside_border)]); + + if($*comp_fgcolor.as_string == "") { $*comp_fgcolor = $*entry_fgcolor; } + if($*header_fgcolor.as_string == "") { $*header_fgcolor = $*entry_fgcolor; } + if($*header_fgcolor_lt.as_string == "") { $*header_fgcolor_lt = $*header_fgcolor; } + if($*header_link.as_string == "") { $*header_link = $*entry_link; } + if($*calendar_fgcolor.as_string == "") { $*calendar_fgcolor = $*entry_fgcolor; } + if($*calendar_link.as_string == "") { $*calendar_link = $*entry_link; } + +} + + + + +############################################# +# +# Navigation +# +############################################# + +function Page::lay_viewspec_nav() { + # Intentionally blank +} + +function RecentPage::lay_viewspec_nav() { + # FIXME: There is currently no decent way to i18nize this + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.forward_url != "") { + if($side) { + $forward_link = $forward_link + """
    + """; + } else { + $forward_link = $forward_link + """$*nav_text_forward $*nav_text_forward"""; + } + } + if ($.nav.backward_url != "") { + if($side) { + $back_link = $back_link + """
    + """; + } else { + $back_link = $back_link + """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function EntryPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + var Link forward = $.entry->get_link("nav_next"); + var Link backward = $.entry->get_link("nav_prev"); + + if (defined $forward or defined $backward) { + if (defined $forward) { + if($side) { + $forward_link = """
    + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if (defined $backward) { + if($side) { + $back_link = """
    + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function ReplyPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + var Link forward = $.entry->get_link("nav_next"); + var Link backward = $.entry->get_link("nav_prev"); + + if (defined $forward or defined $backward) { + if (defined $forward) { + if($side) { + $forward_link = """
    + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if (defined $backward) { + if($side) { + $back_link = """
    + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function DayPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + if ($.prev_url != "" or $.next_url != "") { + if ($.next_url != "") { + if($side) { + $forward_link = """
    + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if ($.prev_url != "") { + if($side) { + $back_link = """
    + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + + +function print_bottom_nav(RecentPage p) { + if ($p.nav.forward_url != "" or $p.nav.backward_url != "") { + """ +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + """; + + if($p.nav.backward_url != "") { + """$*nav_text_back $*nav_text_back """; + } + + if($p.nav.forward_url != "" and $p.nav.backward_url != "") { + """     """; + } + + if ($p.nav.forward_url != "") { + """$*nav_text_forward $*nav_text_forward"""; + } + + """ +
    +
    + """; + } +} + + + +############################################# +# +# Common snippets of HTML in print statements +# +############################################# + +# Top of the table for each comment +function print_content_top() { + """ + + + + +
    + + + + + + + + + + + + + + + + +
    + """; + +} + +# Bottom of the table for each comment +function print_content_bottom() { + """ +
    +
    +
    + """; +} + + +# Top of the table to each new thread +function print_comment_bottom() { + """ + + + + +
    + """; +} + +# Bottom of the table to each new thread +function print_comment_top() { + """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"""; +} + +############################################# +# +# Component Setups +# +############################################# + +#### PAGE SUMMARY #### +function Page::lay_entry_nav (Entry e) : string { + var string line; + var string link = "item"; + var string subject = ($e.subject != "") ? " $e.subject" : """ $*text_nosubject"""; + if($.view == "friends") { $line = "$e.poster : "; $link = $e.journal.username; } + if($e.journal.username != $e.poster.username) { $line = $line + " $e.journal : "; } + $line = """
    $line $subject
    """; + return $line; +} + +function Page::lay_print_summary () { +} + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function EntryPage:: lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Comment e ($.comments) { + if($sep) { + $text = $text + """ +
    +
    + """; + } + var string subject = ($e.subject != "") ? " $e.subject" : """$*text_nosubject"""; + var string poster = defined $e.poster ? $e.poster->as_string() : "Anonymous"; + $text = $text + """
    $poster $subject"""; + $sep = true; + var int num = num_comments_in_thread($e.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + "
    "; + } + print $text; + print_comp_footer(); +} + + +function MonthPage::lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + if($sep) { + $text = $text + """ +
    +
    + """; + } + var string day = lang_ordinal($d.day); + $text = $text + """"""; + $sep = true; + } + } + print $text; + print_comp_footer(); +} + +function DayPage::lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Entry e ($.entries) { + if($sep) { + $text = $text + """ +
    +
    + """; + } + $text = $text + $this->lay_entry_nav($e); + $sep = true; + } + print $text; + print_comp_footer(); +} + + + +function RecentPage:: lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Entry e ($.entries) { + if($sep) { + $text = $text + """ +
    +
    + """; + } + $text = $text + $this->lay_entry_nav($e); + $sep = true; + } + print $text; + print_comp_footer(); +} + + +#### TYPE #### +function print_free_text(Page p) { + print_comp_header($*free_text_text); + """ +
    + """; +} + +# Top of lt gray table +function print_system_box_top() { + """ + + + + + + + + + +
    + """; +} + +# Bottom of lt gray table +function print_system_box_bottom() { + """ +
    + """; +} + +function print_spacer() { + """"""; +} + + +# prints out tab header with $content being the text in it + +function print_entry_header(string content) { + var int cspan = 1; + var int cspan2 = 4; + var int cspan3 = 5; + +""" + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +"""; +} + +# couldn't use the print above because comp column must be all one table for width issues +# this starts a comp with $content being its header + +function print_comp_header(string content) { + +""" +
    +"""; + print safe $content; +""" +
    +"""; +} + +# this ends a comp +function print_comp_footer() { +""" +
    + + + +
    """; + + print $*free_text; + + """
    """; + print_comp_footer(); +} + +#### LINKS #### + +function print_link(string link, string name) { + print safe ""; + if($name != "") { print safe "$name"; } else { "no name"; } +} + + + +function Page::print_linklist() { + + if (size $.linklist <= 0) { + return; + } + + + var string endHTML = """ +
    +
    + """; + + + var int count = 0; + + foreach var UserLink l ($.linklist) { + $count = $count + 1; + if ($l.title) { + if ($l.is_heading) { + if($count != 1) { + "
    "; + } + "
    $l.title
    "; + } else { + print_link($l.url, $l.title); + } + + if($count != size $.linklist) { + print $endHTML; + } + + } else { + "
    "; + } + } + +} + + +function print_links(Page p) { + + print_comp_header($*links_text); + + """ + + + + + + +
    + """; + + $p->print_linklist(); + + """ +
    + """; + + print_comp_footer(); +} + + +#### CALENDAR COMPONENT #### +function print_calendar(Page p) { + +var YearMonth m = $p->get_latest_month(); + +if($m.has_entries) { + + var string month = $m->month_format(); + var string header = ""; + if($*icalendar) { + $header = "$*calendar_text"; + } else { + $header = "$month"; + } + print_comp_header($header); + + if($*icalendar) { + + """ +
    +
    + """; + + } + + if($*icalendar) { + var int lastm; + $lastm = $m.month - 1; + var int lasty; + $lasty = $m.year; + var string journal; + $journal = $p.base_url; + var string link; + + if($lastm == 0) { + $lasty = $m.year - 1; + $lastm = 12; + } + + var string myM; + if($lastm < 10) { $myM = "0" + $lastm; } + else { $myM = string($lastm); } + + $link = $journal + "/" + $lasty + "/" + $myM + "/"; + + """ + + + + + + + + + + """; + + } else { + """
    \"Back\"$month
    """; + } + + + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + ""; + } + foreach var YearDay d ($theDays) { + var int num = $d.num_entries; + if($num > 0) { + ""; + } else { + ""; + } + } + ""; + } + + + """ +
    \"\"$d.date.day$d.date.day
    +"""; + if($*icalendar) { + + "
    "; + } + print_comp_footer(); + } +} + +#### PROFILE COMPONENT #### +function print_profile(Page p) { + + + var string jtype; + + var string comphead = "$*profile_text"; + print_comp_header($comphead); + + """"""; + + if($p.journal.default_pic) { + """ + + + + + """; + } + +""" + + +
    +
    +
    +
    $p.journal.name +
    +
    +
    + + """; + + "
    User: $p.journal
    "; + + if($p.journal.name) { + "
    Name: $p.journal.name
    "; + } + + if($p.journal.website_url) { + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + "
    Website: $website_name
    "; + } + +""" +
    +"""; + + print_comp_footer(); + +} + + +#### PROFILE COMPONENT #### +function print_nav_comp (Page p) { + var string title = $p->title(); + var string website = ""; + if($p.journal.website_url) { + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + $website = "
    \"\"
    \n"; + $website = $website + " \n"; + } + + +""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + +
    + + $website"""; + $p->lay_viewspec_nav(); + """
    + + + + + + +"""; +} + +function print_my_components (Page p) { + if($p.view == "friends" and $*comp_friends == false) { + return; + } + if($*comp_state != "none") { +""" + + +"""; + + if($*first_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*first_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*first_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*first_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*first_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*first_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*second_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*second_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*second_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*second_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*second_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*second_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*third_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*third_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*third_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*third_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*third_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*third_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*fourth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*fourth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*fourth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*fourth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*fourth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*fourth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + + if($*fifth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*fifth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*fifth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*fifth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*fifth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*fifth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + + if($*sixth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*sixth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*sixth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*sixth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*sixth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*sixth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + "
    \n "; + } +} + +############################################# +# +# Entries +# +############################################# + +function print_my_entries (Page p, string title) { + +""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +"""; + +print safe $title; + +""" +
    + """; + + if($p.global_subtitle != "") { +"
    $p.global_subtitle
    "; + } + + """ + +
    + + + +
    + """; + + $p->print_body(); + + """ + + """; +} + +function page_layout(Page p) { + + var string title = $p->title(); + + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + var string website = ($p.journal.website_url != "" ? "$website_name" : ""); + +""" + + + + + """; + $p->print_head(); + """ + $title + + +"""; + if($*comp_state == "none" or $*comp_navbar == false or ($p.view == "friends" and $*comp_friends == false)) { + +""" +
    + $*nav_entries_text + $*nav_friends_text + $*nav_calendar_text + $*nav_info_text + $website +"""; + + $p->lay_viewspec_nav(); + + "
    "; + + } + +""" +
    + + + + +"""; + if($*comp_state == "right" or $*comp_state == "none") { + print_my_entries($p, $title); + } elseif($*comp_state == "left") { + print_my_components($p); + } +""" + +"""; + + if($*comp_state == "right") { + print_my_components($p); + } elseif($*comp_state == "left") { + print_my_entries($p, $title); + } +""" + + +
    + + + +"""; +} + +function Page::print () { + page_layout($this); +} + + +function Page::lay_print_linkbar() : bool { + return false; +} + +function Entry::lay_print_linkbar() : bool { + var Page p = get_page(); + if (($*show_entrynav_icons and $p.view == "entry") or ($*show_recentnav_icons and ($p.view == "recent" or $p.view == "friends"))) { + print "
    "; + var Link link; + var string icon; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + if($link) { + if($k == "edit_entry") { $icon = $*edit_img; } + elseif($k == "mem_add") { $icon = $*mem_img; } + elseif($k == "tell_friend") { $icon = $*tellfriend_img; } + elseif($k == "edit_tags") { $icon = $*tags_img; } + if ($icon != "") { print "\"$link.caption\"
    "; } + } + $icon = ""; + } + print "
    "; + return true; + } else { + return false; + } +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + var string userpic = (defined $e.userpic ? "\"$e.poster.username\"" : ""); + + var string header = ""; + if (($p.view != "entry" and $e.new_day) or $p.view == "entry") { + $header = "$time " + $e.time->date_format("long") + ""; + } else { + $header = "$time " + $e.time->date_format("long"); + } + if ($e.security) { $header = $e.security_icon + "   " + $header; } + var string link = ($p.view == "friends") ? $e.journal.username : "item"; +""" + + +"""; + print_entry_header($header); + + var string fgstyle = "class=\"userpic\""; + var string bgstyle; + if($p.view == "friends") { + $fgstyle = "style=\"border-color: $fgcolor;\""; + $bgstyle = "style=\"padding-top: 3px; padding-left: 3px; padding-right: 3px; padding-bottom: 3px; background-color: $bgcolor;\""; + } + + +""" + + + +"""; + if($p.view == "friends" or $p.journal_type == "c" or $e.poster.username != $e.journal.username or ($p.view == "entry" and $*show_entrypage_userpic)) { + """"""; + } elseif($*show_entry_userpic and (($p.view == "entry" and ($*show_entrypage_userpic == false)) == false)) { + """"""; + } + var int cs = 4; + var bool test = $e->lay_print_linkbar(); + if($test) { $cs = 5; } + +""" + + + + + +
    """; + + if(defined $e.userpic) { + """"""; + } +""" $e.journal"""; + + if($e.journal.username != $e.poster.username) { + print "
    $e.poster"; + } + +"""
    """; + if(defined $e.userpic) { + """
    $e.poster.username
    """; + } +"""
    + + + + + + + """; + + # Subject + if($e.subject != "") { + """ + + + + + +"""; + + } + + if (not $hide_text) + { + # Entry + """ + + + + + + """; + } + + """ + + + + + +
    +
    $e.subject
    +"""; + if($e.text != "") { + "
    \"\"
    "; + } +""" +
    +
    + $e.text +"""; + if (size $e.tags or size $e.metadata) { print "

    "; } + if ($e.tags) { + var int tcount = 0; + "Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    "; + } + + if (size $e.metadata) + { + foreach var string k ($e.metadata) + { + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { $key = $*text_meta_mood; } + if ($k == "music") { $key = $*text_meta_music; } + if ($k == "mood" and defined $e.mood_icon) + { + var Image i = $e.mood_icon; + $val = " $val"; + } + "$key: $val
    "; + } + } + if (size $e.tags or size $e.metadata) { print "

    "; } +""" +
    +
    + """; + + # Comments + "
    "; + $e.comments->print(); + """ +
    +
    + +
    + """; + +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); " $*comment_divider "; + } + $this->print_postlink(); +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function RecentPage::print_body +{ + + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + print_bottom_nav($this); + +} + + +function FriendsPage::print_entry (Entry e) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function FriendsPage::print_body +{ + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + + print_bottom_nav($this); +} + + +############################################# +# +# Calendar: +# Year, Month, Week, and Day View +# +############################################# + + +function YearPage::print_year_links () +{ + print_system_box_top(); + "Year: "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + " ($y.year) "; + } else { + " ($y.year) "; + } + } + print_system_box_bottom(); + print_spacer(); +} + +function YearPage::print_body { + $this->print_year_links(); + var bool toggle = false; + "\n \n "; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + "\n "; + if($toggle) { + "\n "; + $toggle = false; + } else { + $toggle = true; + } + } + } + "\n \n
    "; + $this->print_month($m); + "\n
    "; +} + +# prints out the multiple month calendar view +function YearPage::print_month(YearMonth m) +{ + var string header; + $header = $header + ""; + $header = $header + $m->month_format(); + $header = $header + ""; + print_entry_header($header); + print_comment_top(); + "\n "; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + "\n
    \n "; + print_comment_bottom(); +} + +function YearWeek::print() { + "\n "; + if ($.pre_empty) { "\n "; } + foreach var YearDay d ($.days) + { + if ($d.num_entries) { + "\n $d.day"; + ""; + } else { + "\n $d.day"; + "
     "; + } + "\n"; + } + if ($.post_empty) { "\n "; } + "\n "; +} + + +# Has two views. A normal one, and one for the iCalendar. +function MonthPage::print() { + + if($*icalendar and $.args{"ical"} == "true") { + var string title = $this->title(); + var MonthDay[] theM = $this.days; + """ + + + + + + $.head_content + $title + + + + + \n \n \n "; + + var int count = 1; + var int first = 0; + var int colspan = 0; + foreach var MonthDay d ($theM) { + if($first == 0) { + $first = $d.date->day_of_week(); + $count = $first; + $colspan = $first - 1; + } + if($d.day == 1) { + if($first > 1) { + """ \n"""; + } + } + if($count == 8) { + " \n"; + $count = 1; + } + if($d.has_entries) { + " "; + } else { + " "; + } + + $count ++; + + } + + + """ + +
    """; + + if ($.prev_url != "") { "\"Back\""; } + ""; + var string current = $.date->date_format($*lang_fmt_month_long); + var int mm = $.date.month; + var string mms; + if($mm < 10) { + $mms = "0" + $mm; + } else { + $mms = string($mm); + } + + "$current"; + ""; + if ($.next_url != "") { "\"Forward\""; } + "
    $d.date.day$d.date.day
    + + + """; + } else { + page_layout($this); + } +} + +function MonthPage::print_body() { + "
    "; + $.redir->print_hiddens(); + print_system_box_top(); + """ + + + + +
    + """; + if ($.prev_url != "") { "\"Back\"\n"; } + ""; + if (size $.months > 1) { + "\n"; + } + ""; + if ($.next_url != "") { "\n\"Forward\"\n"; } + """ +
    + """; + print_system_box_bottom(); + print_spacer(); + + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + var string head = """"""; + $head = $head + ""; + $head = $head + lang_ordinal($d.day); + $head = $head + ""; + print_entry_header($head); + $d->print_subjectlist(); + print_spacer(); + } + } + "
    "; + +} + +function MonthDay::print_subjectlist() { + print_comment_top(); + foreach var Entry e ($.entries) { + print_content_top(); + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + " ($*text_nosubject)"; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
    \n"; + print_content_bottom(); + } + print_comment_bottom(); +} + +### Day + +function DayPage::print_body () +{ + + if (not $.has_entries) { + var string sub = $.date->date_format("med"); + + print_system_box_top(); + "
    $*text_noentries_day
    "; + print_system_box_bottom(); + + } else { + + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } +} + + + + + + + + + +############################################# +# +# Entry and Comments +# +############################################# + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + "
    "; + print lang_page_of_pages($.current, $.total); + "
    "; + foreach var int i (1..$.total) { + if ($i == $.current) { + "[$i] "; + } else { + var string url_of = $this->url_of($i); + """[$i] """; + } + } +} + +function EntryPage::print_body () +{ + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comments_bgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comments_screened_bgcolor", ], + ]); + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + """ + + + + + + + + + + +
    Comments + """; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + """ +
    + """; + print_spacer(); + + if ($.comment_pages.total_subitems > 0) { + $this->print_comments($.comments); + } +""" + + + + + +
    + + + + + + + + + + + +
    +"""; + + $.entry.comments->print(); + +""" + +"""; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } +""" +
    + + +
    +"""; + if ($this.multiform_on) { +""" + + + + + + + + + +
    +"""; + "

    Mass Action

    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
    "; +"""
    +"""; + } + } +} + + +# Top of the table for each comment +function print_comment_content_top(Comment c) { + + var int indent = ($c.depth - 1) * 25; + + """ + + + + + +
    + + + + + + + + + + + + + + + + +
    + """; + +} + +# Bottom of the table for each comment +function print_comment_content_bottom() { + """ +
    +
    +
    + """; + "\n\n\n\n"; +} + +# partial entries such as collapsed and screened. +function EntryPage::print_comment_partial (Comment c) { + if($c.depth == 1) { + var Comment[] replies; + $replies = $c.replies; + var int count = 0; + foreach var Comment reply ($replies) { + $count ++; + } + var string head; + if($count > 0) { + $head = "Thread started by a screened user"; + } else { + $head = "Comment by screened user"; + } + print_entry_header($head); + print_comment_top(); + } + var string content; + if($c.screened) { + $content = "Screened comment"; + } else { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + $content = "$subj - $poster"; + } + print_comment_content_top($c); + "$content"; + print_comment_content_bottom(); +} + +# called from entry page. loops through entries and runs EntryPage::print_comment +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + var bool first = true; + foreach var Comment c ($cs) { + if($c.depth == 1) { + if($first != true) { + print_comment_bottom(); + } else { + $first = false; + } + } + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + $this->print_comments($c.replies); + } +} + +# Runs for every entry found +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + + $color = $*entry_fgcolor; + + if ($c.screened) { + $background = $*comments_screened_bgcolor; + } else { + $background = $*comments_bgcolor; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + + if ($c.depth == 1) { + var string poster_name = defined $c.poster ? $c.poster.name : "Anonymous"; + + var Comment[] replies; + $replies = $c.replies; + var int count = 0; + foreach var Comment reply ($replies) { + $count ++; + } + + var string head; + + if($count > 0) { + $head = "Thread started by $poster_name"; + } else { + $head = "Comment by $poster_name"; + } + print_entry_header($head); + print_comment_top(); + } + + print ""; + print_comment_content_top($c); + + "\n\n
    \n"; + " \n \n"; + var int td = 6; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $td = 7; + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + " \n"; + } + " \n"; + " \n"; + + "\n \n"; + " \n \n \n
    \"$c.poster.username\"From: $posterDate: " + $c.time->date_format("long") + " - " + $c.time->time_format() + ""; + + # action links (screen, unscreen, delete, freeze, etc) + foreach var string k ($c.link_keyseq) { + var Link link = $c->get_link($k); + if ($link) { + " $link "; + } + } + + " ($*text_permalink)
    "; + if (defined $c.subject_icon or $c.subject != "") { "

    $c.subject_icon $c.subject

    \n"; } + if ($c.metadata{"poster_ip"}) { " (IP Address: " + $c.metadata{"poster_ip"} + ")
    "; } + + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + + "
    \n
    \n"; + "
    $c.text
    \n"; + "
    "; + if ($c.frozen) { + "(Replies frozen) "; + } else { + "(Reply to this) "; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    \n"; + print_comment_content_bottom(); + +} + +# The ReplyPage is without any comments...just the item being replied to and form. +function ReplyPage::print_body () +{ + var string time = $.replyto.time->time_format(); + + if (not $.entry.comments.enabled) + { + print "

    $*text_reply_nocomments_header

    $*text_reply_nocomments

    "; + return; + } + + var string posttime = "$time " + $.replyto.time->date_format("med"); + if ($.entry.security) { $posttime = $.entry.security_icon + "   " + $posttime; } + var string subject = ($.replyto.subject ? "$.replyto.subject" : ""); + var string poster = defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + var string pic = ""; + if (defined $.replyto.userpic) { $pic = "
    \"$.replyto.poster.username\"
    "; } + + print_entry_header($posttime); + +""" + + + + + + + + + + + +
    $pic
    $poster
    +
    + + + + + + +"""; + if($subject != "") { + +""" + + + + + +"""; + + } + + +""" + + + + + + + + + + + + +
    +
    $subject
    +"""; + + if($.replyto.text != "") { + "
    \"\"
    "; + } + +""" +
    +
    $.replyto.text
    +
    + +
    + +
    + +"""; + print_system_box_top(); + "

    Reply

    "; + $.form->print(); + print_system_box_bottom(); + +} + + + +############################################# +# +# Preview +# +############################################# + + +function print_theme_preview () +{ + """ + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Component Header
    +
    + + + + + +
    + + + + + + + + + + + + + + + + +
    +

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

    +
    +
    +
    + """; +} diff --git a/local/bin/upgrading/s2layers/component/themes.s2 b/local/bin/upgrading/s2layers/component/themes.s2 new file mode 100755 index 0000000..4b96ccc --- /dev/null +++ b/local/bin/upgrading/s2layers/component/themes.s2 @@ -0,0 +1,187 @@ +#NEWLAYER: component/aquatic +layerinfo "type" = "theme"; +layerinfo "name" = "Aquatic"; +layerinfo redist_uniq = "component/aquatic"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#515151"; +set comp_bgcolor = "#51ada6"; +set header_link = "#ffffff"; +set entry_link = "#0C5D57"; +set entry_bgcolor = "#ffffff"; +set header_fgcolor = "#c7d1cc"; +set main_bgcolor = "#51ada6"; +set calendar_active = "#318D86"; +set header_bgcolor = "#0e3b4a"; +set calendar_inactive = "#ffffff"; +set comp_fgcolor = "#F7FEFF"; + +#NEWLAYER: component/bluetiful +layerinfo "type" = "theme"; +layerinfo "name" = "Bluetiful"; +layerinfo redist_uniq = "component/bluetiful"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#606060"; +set comp_bgcolor = "#f4f4f4"; +set header_link = "#f7fcfb"; +set entry_link = "#2d3679"; +set entry_bgcolor = "#eff5ff"; +set header_fgcolor = "#327192"; +set main_bgcolor = "#a2c5e3"; +set header_bgcolor = "#6da6c4"; +set comments_bgcolor = "#84b5d2"; + +#NEWLAYER: component/darkness +layerinfo "type" = "theme"; +layerinfo "name" = "Darkness"; +layerinfo redist_uniq = "component/darkness"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#22620e"; +set calendar_fgcolor = "#5b6c7a"; +set calendar_active = "#5b6c7a"; +set calendar_inactive = "#adbac5"; +set comp_fgcolor = "#dadde0"; +set entry_fgcolor = "#dddcd6"; +set comp_bgcolor = "#758491"; +set entry_link = "#adb6be"; +set header_link = "#c7ccd1"; +set entry_bgcolor = "#32343d"; +set main_bgcolor = "#71837A"; +set header_fgcolor = "#c7d1cc"; +set header_bgcolor = "#728d80"; +set comments_bgcolor = "#5a5a5a"; + +#NEWLAYER: component/jedicloak +layerinfo "type" = "theme"; +layerinfo "name" = "Jedi Cloak"; +layerinfo redist_uniq = "component/jedicloak"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#F1EDE5"; +set comp_bgcolor = "#988b67"; +set header_link = "#dddbd6"; +set entry_link = "#615020"; +set entry_bgcolor = "#ada386"; +set comments_screened_bgcolor = "#a29f97"; +set header_fgcolor = "#bcb59f"; +set main_bgcolor = "#6e5845"; +set calendar_active = "#817452"; +set header_bgcolor = "#6e6449"; +set calendar_inactive = "#988b67"; +set comp_fgcolor = "#383325"; +set comments_bgcolor = "#948B6F"; + +#NEWLAYER: component/mellow +layerinfo "type" = "theme"; +layerinfo "name" = "Mellow"; +layerinfo redist_uniq = "component/mellow"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#D6C8CC"; +set page_background_image = ""; +set calendar_active = "#D9E1D9"; +set calendar_inactive = "#A2B2B1"; +set comp_fgcolor = "878D8D"; +set entry_fgcolor = "#355351"; +set comp_bgcolor = "#C6CFD5"; +set entry_link = "#6B7F8D"; +set header_link = "6B7F8D"; +set entry_bgcolor = "#A2B2B1"; +set main_bgcolor = "#D6C8CC"; +set header_fgcolor = "#96A891"; +set header_bgcolor = "#D9E1D9"; +set comments_bgcolor = "#BCC4C3"; + +#NEWLAYER: component/mocha +layerinfo "type" = "theme"; +layerinfo "name" = "Mocha"; +layerinfo redist_uniq = "component/mocha"; +layerinfo "source_viewable" = 0; +set page_background_image = ""; +set entry_fgcolor = "#807C75"; +set comp_bgcolor = "#b1bbb4"; +set comp_fgcolor = "#78746e"; +set header_link = "#716C53"; +set entry_link = "#67716a"; +set entry_bgcolor = "#ebe6d1"; +set comments_screened_bgcolor = "#b2c9b9"; +set header_fgcolor = "#7a6f43"; +set main_bgcolor = "#d8d0ae"; +set calendar_active = "#8da193"; +set header_bgcolor = "#d8d0ae"; +set calendar_inactive = "#d3e1d7"; +set comments_bgcolor = "#dbdedc"; + +#NEWLAYER: component/orangesoda +layerinfo "type" = "theme"; +layerinfo "name" = "Orange Soda"; +layerinfo redist_uniq = "component/orangesoda"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#8a5b33"; +set comp_bgcolor = "#c4bd8e"; +set header_link = "#FFFFFF"; +set entry_link = "#613815"; +set entry_bgcolor = "#dbd7b9"; +set comments_screened_bgcolor = "#cbc9b9"; +set header_fgcolor = "#d7d2af"; +set main_bgcolor = "#cd9338"; +set calendar_active = "#cd9338"; +set header_bgcolor = "#c6710a"; +set calendar_inactive = "#dbd7b9"; +set comments_bgcolor = "#e4deb5"; + +#NEWLAYER: component/pinkelephants +layerinfo "type" = "theme"; +layerinfo "name" = "Pink Elephants"; +layerinfo redist_uniq = "component/pinkelephants"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#e29994"; +set page_background_image = ""; +set calendar_active = "#a8a8a7"; +set calendar_inactive = "#e29994"; +set comp_fgcolor = "#ad5a55"; +set entry_fgcolor = "#ffffff"; +set comp_bgcolor = "#f7b3ae"; +set entry_link = "#777776"; +set header_link = "#FFFFFF"; +set entry_bgcolor = "#a8a8a7"; +set main_bgcolor = "#e29994"; +set header_fgcolor = "#ad5a55"; +set header_bgcolor = "#e29994"; +set comments_bgcolor = "#9c9c9c"; + +#NEWLAYER: component/sugarspice +layerinfo "type" = "theme"; +layerinfo "name" = "Sugar and Spice"; +layerinfo redist_uniq = "component/sugarspice"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#927DAD"; +set comp_bgcolor = "#D5EBFA"; +set header_link = "#6e5593"; +set entry_link = "#759EBA"; +set entry_bgcolor = "#D5E9D7"; +set comments_screened_bgcolor = "#BEC9BF"; +set header_fgcolor = "#6E5593"; +set main_bgcolor = "#FCD9C4"; +set calendar_active = "#FCD9C4"; +set header_bgcolor = "#D4CAE1"; +set calendar_inactive = "#D4CAE1"; +set comp_fgcolor = "AA9ABF"; +set comments_bgcolor = "#B9DABC"; + +#NEWLAYER: component/greensuperhero +layerinfo "type" = "theme"; +layerinfo "name" = "That Green Superhero"; +layerinfo redist_uniq = "component/greensuperhero"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#c99bd7"; +set page_background_image = ""; +set calendar_active = "#bc6ed4"; +set calendar_inactive = "#c99bd7"; +set comp_fgcolor = "#bc87cb"; +set entry_fgcolor = "#424242"; +set comp_bgcolor = "#efefe1"; +set entry_link = "#027040"; +set header_link = "#ffffff"; +set entry_bgcolor = "#e4ede9"; +set main_bgcolor = "#16b16c"; +set header_fgcolor = "#d0efe2"; +set header_bgcolor = "#049957"; +set comments_bgcolor = "#bed8cc"; diff --git a/local/bin/upgrading/s2layers/cuteness/layout.s2 b/local/bin/upgrading/s2layers/cuteness/layout.s2 new file mode 100755 index 0000000..433c45e --- /dev/null +++ b/local/bin/upgrading/s2layers/cuteness/layout.s2 @@ -0,0 +1,1507 @@ +layerinfo "type" = "layout"; +layerinfo "name" = "Cuteness Attack"; +layerinfo "des" = "OMFG Kittens and Flowers"; +layerinfo "author_name" = "Andy Mai"; +layerinfo "redist_uniq" = "cuteness/layout"; + +# First style from our new design intern Andy, based loosely on Tranquility II +# +# Todo: index layout images and use palimg_tint/gradient instead of just pink +# Todo: minor gap between "Comments {#}" heading and comments +# Todo: Add different face outlines +# Todo: Add themes + +# PROPERTIES: STYLES +propgroup Style { + # odd + property Color c_header_background { des = "Header Background Color"; } + property Color c_header_border { des = "Header Border Color"; } + # page + property Color c_page_background { des = "Page Background Color"; } + property string c_page_background_img { des = "Page Background Image"; note = "If left blank, an appropriate default will be chosen for you."; } + property string c_page_background_position { des = "Page Background Position (i.e Top Left)"; } + property string c_page_background_repeat { des = "Repeat Background"; values = "no-repeat|No|repeat-x|Repeat Horizontally|repeat-y|Repeat Vertically| |Tile"; } + property string c_page_background_attach { des = "Background Attachment"; values = "fixed|Fixed|scroll|Scroll"; } + property Color c_page_title { des = "Page Title color"; } + property Color c_page_text { des = "Page Text color"; } + property Color c_page_link { des = "Page Link color"; } + property Color c_page_link_visited { des = "Page Visited Link Color"; } + property Color c_page_link_hover { des = "Page Hover Link Color"; } + property Color c_page_link_active { des = "Page Active Link Color"; } + # menu + property Color c_menu_link { des = "Side Menu Link Color"; } + property Color c_menu_link_visited { des = "Side Menu Visited Link Color"; } + property Color c_menu_link_hover { des = "Side Menu Hover Link Color"; } + property Color c_menu_link_active { des = "Side Menu Active Link Color"; } + property Color c_menu_text_color { des = "Side Menu Text Color"; } + property Color c_menu_header_color { des = "Side Menu Header Color"; } + property Color c_menu_current { des = "Current Menu Item color"; } + # entry + property Color c_entry_background { des = "Entry Background Color"; } + property Color c_entry_link { des = "Entry Link Color"; } + property Color c_entry_link_visited { des = "Entry Visited Link Color"; } + property Color c_entry_link_hover { des = "Entry Hover Link Color"; } + property Color c_entry_link_active { des = "Entry Active Link Color"; } + property Color c_entry_text_color { des = "Entry Text Color"; } + property Color c_entry_title_color { des = "Entry Title Color"; } + property Color c_entry_border { des = "Entry Bottom Border Color"; } + # metadata + property Color c_meta_background { des = "Entry Metadata Background Color"; } + property Color c_meta_link { des = "Entry Metadata Link Color"; } + property Color c_meta_link_visited { des = "Entry metadata visited link color"; } + property Color c_meta_link_hover { des = "Entry Metadata Hover Link Color"; } + property Color c_meta_link_active { des = "Entry Metadata Active Link Color"; } + property Color c_meta_text_color { des = "Entry Metadata Text Color"; } + # footer + property Color c_footer_background { des = "Page Footer Background Color"; } + property Color c_footer_link { des = "Page Footer Link Color"; } + property Color c_footer_link_visited { des = "Page Footer Visited Link Color"; } + property Color c_footer_link_hover { des = "Page Footer Hover Link Color"; } + property Color c_footer_link_active { des = "Page Footer Active Link Color"; } + property Color c_footer_text_color { des = "Page Footer Text Color"; } + # comments + property Color c_comment_one_link { des = "Comment Link Color"; } + property Color c_comment_one_link_visited { des = "Comment Visited Link Color"; } + property Color c_comment_one_link_hover { des = "Comment Hover Link Color"; } + property Color c_comment_one_link_active { des = "Comment Active Link Color"; } + property Color c_comment_one_text_color { des = "Comment Text Color"; } + property Color c_comment_one_title_color { des = "Comment Title Color"; } + property Color c_comment_one_background { des = "Comment Bar Background Color"; } + property Color c_comment_one_border { des = "Comment Bottom Border Color"; } + property Color c_comment_screened_link { des = "Comment Screened Link Color"; } + property Color c_comment_screened_link_visited { des = "Comment Screened Visited Link Color"; } + property Color c_comment_screened_link_hover { des = "Comment Screened Hover Link Color"; } + property Color c_comment_screened_link_active { des = "Comment Screened Active Link Color"; } + property Color c_comment_screened_text_color { des = "Comment Screened Text Color"; } + property Color c_comment_screened_title_color { des = "Comment Screened Title Color"; } + property Color c_comment_screened_background { des = "Comment Screened Background Color"; } + property Color c_comment_screened_border { des = "Comment Screened Bottom Border Color"; } +} + + +# PROPERTIES: FONTS +propgroup Fonts { + # page + property string f_page { des = "Generic Main Page Font"; } + property string f_page_size { des = "Main Page Font Size"; } + property string f_page_title { des = "Main Page Title Font"; } + property string f_page_title_size { des = "Main Page Title Font Size"; } + property string f_page_link { des = "Generic Font for Page Links"; } + property string f_page_link_size { des = "Page Link Font Size"; } + # menu + property string f_menu_link { des = "Menu Link Font"; } + property string f_menu_link_size { des = "Menu Fink Font Size"; } + property string f_menu { des = "Menu Font"; } + property string f_menu_size { des = "Menu Font Size"; } + property string f_menu_header { des = "Menu Title Font"; } + property string f_menu_header_size { des = "Menu Title Font Size"; } + property string f_menu_current { des = "Current Menu Item Font"; } + property string f_menu_current_size { des = "Current Menu Item Font Size"; } + # entry + property string f_entry { des = "Entry Font"; } + property string f_entry_size { des = "Entry Font Size"; } + property string f_entry_link { des = "Entry Link Font"; } + property string f_entry_link_size { des = "Entry Link Font Size"; } + property string f_entry_title { des = "Entry Title Font"; } + property string f_entry_title_size { des = "Entry Title Font Size"; } + # metadata + property string f_meta { des = "Entry metadata font"; } + property string f_meta_size { des = "Entry metadata font size"; } + property string f_meta_link { des = "Entry metadata link font"; } + property string f_meta_link_size { des = "Entry metadata link font size"; } + # footer + property string f_footer { des = "Footer font"; } + property string f_footer_size { des = "Footer font size"; } + property string f_footer_link { des = "Footer link font"; } + property string f_footer_link_size { des = "Footer link font size"; } + # comments + property string f_comment { des = "Comment font"; } + property string f_comment_size { des = "Comment font size"; } + property string f_comment_title { des = "Comment title font"; } + property string f_comment_title_size { des = "Comment title font size"; } + property string f_comment_link { des = "Comment link font"; } + property string f_comment_link_size { des = "Comment link font size"; } +} + + +# PROPERTIES: PRESENTATION +propgroup Format { + property string face { des = "Choose a face style"; values = "cute|Cute Eyes|square|Square Eyes|dizzy|Dizzy|doll|Doll Face|happy|Happy|japanese|Japanese Style|curious|Curious"; note = "Choose wisely, you do not wish to see a permanent scowl!"; } + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; } + property string time_format { des = "Format for the time"; example = "%%hh%%:%%min%%:%%sec%% %%a%%m"; } + property string date_format { des = "Format for the date"; example = "%%m%%/%%d%%/%%yy%%"; } + property bool menu_disable_summary { des = "Disable menu summary view"; } + property string css_style_overrides { des = "include any CSS here to override the default CSS"; } +} + + +# PROPERTIES: TEXT +propgroup Text { + property string text_page_title { des = "Title of your Live Journal"; } + property string text_summary_header { des = "Menu text header"; } + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + property use text_reply_nocomments_header; + property use text_reply_nocomments; + property use text_comment_from; + property use text_comment_ipaddr; + property use text_comment_parent; + property use text_comment_reply; + property use text_comment_thread; + property use text_nosubject; + property use text_post_comment; + property use text_post_comment_friends; + property use text_max_comments; + property use text_view_month; + property string text_comment_anonymous { des = "Text to substitute for anonymous commenters"; } + property string text_comment_viewall { des = "Text for view all comments"; } + property string text_links_header { des = "Sidebar links header text"; } + property string text_links_spacer { des = "String to act as links list spacer";} +} + + +# ------------------------------- +# default property settings +# ------------------------------- +# Style +set c_header_background = ""; +set c_header_border = ""; +set c_page_title = "#ffb2c7"; +set c_page_background = "#f7f0f3"; +set c_page_background_img = ""; +set c_page_background_position = "bottom"; +set c_page_background_repeat = "repeat-x"; +set c_page_background_attach = "fixed"; +set c_page_text = "#9F74A5"; +set c_page_link = "#9F74A5"; +set c_page_link_visited = "#9F74A5"; +set c_page_link_hover = "#c47a8e"; +set c_page_link_active = "#c47a8e"; +set c_menu_link = "#9F74A5"; +set c_menu_link_visited = "#9F74A5"; +set c_menu_link_hover = "#c47a8e"; +set c_menu_link_active = "#9F74A5"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#9F74A5"; +set c_entry_background = "#fff"; +set c_entry_link = "#9F74A5"; +set c_entry_link_visited = "#9F74A5"; +set c_entry_link_hover = "#c47a8e"; +set c_entry_link_active = "#9F74A5"; +set c_entry_text_color = "#9F74A5"; +set c_entry_title_color = "#9F74A5"; +set c_entry_border = "#ccc"; +set c_meta_background = "#fff"; +set c_meta_link = "#9F74A5"; +set c_meta_link_visited = "#9F74A5"; +set c_meta_link_hover = "#c47a8e"; +set c_meta_link_active = "#9F74A5"; +set c_meta_text_color = "#9F74A5"; +set c_footer_background = "#333"; +set c_footer_link = "#9F74A5"; +set c_footer_link_visited = "#9F74A5"; +set c_footer_link_hover = "#c47a8e"; +set c_footer_link_active = "#9F74A5"; +set c_footer_text_color = "#9F74A5"; +set c_comment_one_link = "#9F74A5"; +set c_comment_one_link_visited = "#9F74A5"; +set c_comment_one_link_hover = "#c47a8e"; +set c_comment_one_link_active = "#9F74A5"; +set c_comment_one_text_color = "#9F74A5"; +set c_comment_one_title_color = "#9F74A5"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#f7f0f3"; +set c_comment_screened_link = "#9F74A5"; +set c_comment_screened_link_visited = "#9F74A5"; +set c_comment_screened_link_hover = "#c47a8e"; +set c_comment_screened_link_active = "#9F74A5"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#333"; +set c_comment_screened_background = "#fff"; +set c_comment_screened_border = "#999"; + +# FONTS +set f_page = "Tahoma, Verdana, san-serif"; +set f_page_title = "Arial Black, Arial, Verdana, San-serif"; +set f_page_title_size = "250%"; +set f_page_size = "12px"; +set f_page_link = "Tahoma, Verdana, san-serif"; +set f_page_link_size = "100%"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu_link_size = "80%"; +set f_menu = "Verdana, Helvetica, sans-serif"; +set f_menu_size = "100%"; +set f_menu_header = "Tahoma, Verdana, san-serif"; +set f_menu_header_size = "120%"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_menu_current_size = "80%"; +set f_entry = "Tahoma, Verdana, san-serif"; +set f_entry_size = "100%"; +set f_entry_link = "Tahoma, Verdana, san-serif"; +set f_entry_link_size = "100%"; +set f_entry_title = "Tahoma, Verdana, san-serif"; +set f_entry_title_size = "125%"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_size = "80%"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_meta_link_size = "100%"; +set f_footer = "GTahoma, Verdana, san-serif"; +set f_footer_size = "100%"; +set f_footer_link = "Tahoma, Verdana, san-serif"; +set f_footer_link_size = "100%"; +set f_comment = "Tahoma, Verdana, san-serif"; +set f_comment_size = "100%"; +set f_comment_title = "Georgia, serif"; +set f_comment_title_size = "130%"; +set f_comment_link = "Georgia, serif"; +set f_comment_link_size = "100%"; + +# OTHER +set face = "cute"; +set show_entrynav_icons = true; +set time_format = "%%hh%%:%%min%% %%a%%m"; +set date_format = "%%mon%%. %%dayord%%, %%yyyy%%"; +set menu_disable_summary = false; +set css_style_overrides = ""; + +# TEXT +set text_page_title = "My LiveJournal"; +set text_meta_music = "music"; +set text_links_header = "links"; +set text_meta_mood = "mood"; +set text_read_comments = "{#}"; +set text_read_comments_friends = "{#}"; +set text_comment_anonymous = "anonymous"; +set text_comment_viewall = "view all comments"; +set text_links_header = "Links"; +set text_summary_header = "Menu"; +set text_links_spacer = "_______________"; + + + +# ======================================== +# METHODS +# ======================================== + + +# ------------------------------- +# prop_init +# ------------------------------- + +function prop_init() { + if ($*c_page_background_img == "") { $*c_page_background_img = "$*IMGDIR/style/cuteness/bg-pink.gif"; } + + # Determine which "face" to use + if ($*face == "cute") { + $*face = "$*IMGDIR/style/cuteness/face-cute.gif"; + } elseif ($*face == "square") { + $*face = "$*IMGDIR/style/cuteness/face-square.gif"; + } elseif ($*face == "dizzy") { + $*face = "$*IMGDIR/style/cuteness/face-dizzy.gif"; + } elseif ($*face == "doll") { + $*face = "$*IMGDIR/style/cuteness/face-doll.gif"; + } elseif ($*face == "happy") { + $*face = "$*IMGDIR/style/cuteness/face-happy.gif"; + } elseif ($*face == "japanese") { + $*face = "$*IMGDIR/style/cuteness/face-japanese.gif"; + } elseif ($*face == "curious") { + $*face = "$*IMGDIR/style/cuteness/face-curious.gif"; + } +} + +# ------------------------------- +# stylesheet +# ------------------------------- +function print_stylesheet ( ) +{ + """ + @media screen, print { + * { + margin: 0; + padding: 0; + } + hr { + display: none; + } + + html>body { + background-color: $*c_page_background; + background-image: url($*c_page_background_img); + background-position: $*c_page_background_position; + background-repeat: $*c_page_background_repeat; + background-attachment: $*c_page_background_attach; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + } + + body { + background-color: $*c_page_background; + background-image: url($*c_page_background_img); + background-position: $*c_page_background_position; + background-repeat: $*c_page_background_repeat; + background-attachment: $*c_page_background_attach; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + margin-top: 30px; + } + a { + font-family: $*f_page_link; + font-size: $*f_page_link_size; + color: $*c_page_link; + text-decoration: none; + } + a:visited { color: $*c_page_link_visited; } + a:hover, a:visited:hover { color: $*c_page_link_hover; text-decoration: underline; } + a:active { color: $*c_page_link_active; } + a img { border: none; } + a.comm { + background: transparent url($*IMGDIR/community.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + a.user { + background: transparent url($*IMGDIR/userinfo.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + p { + margin: 5px; + padding: 5px; + } + + + form { + display: inline; + margin-left: 00px; + padding: 0px; + width: 425px; + } + + + input, select, textarea { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + padding: 2px; + margin: 3px; + } + + #container { + position: relative; + width: 700px; + margin: 0 auto; + text-align: left; + } + html>body #header { + position: absolute; + margin-top: 65px; + margin-left: 5px; + z-index: 5; + background-color: $*c_header_background; + } + + #header { + position: absolute; + margin-top: 50px; + margin-left: -180px; + z-index: 5; + padding: 10px; + background-color: $*c_header_background; + } + + #header h1 { + font-family: $*f_page_title; + font-size: $*f_page_title_size; + color: $*c_page_title; + } + + #face { + position: absolute; + width: 203px; + height: 197px; + background-image: url($*face); + background-repeat: no-repeat; + z-index: 10; + margin-left: 290px; + margin-top: -10px; + } + + html>body #face { + position: absolute; + width: 203px; + height: 197px; + background-image: url($*face); + background-repeat: no-repeat; + z-index: 10; + margin-left: 485px; + margin-top: 10px; + } + + + #comments h3 img { + border: 5px solid #f7f0f3; + background-color: #fff; + } + + + + #userpicbg { + position: relative; + background-image: url($*IMGDIR/style/cuteness/userpicbg.gif); + background-repeat: no-repeat; + width: 163px; + height: 169px; + margin-left: 5px; + } + + html>body #userpicbg img { + padding-top: 43px; + padding-right: 10px; + } + + #userpicbg img { + padding-top: 23px; + padding-right: 10px; + } + + .ind-entry h3.userpic img { + float: left; + margin-top: 10px; + } + + #menu { + position: relative; + float: left; + font-family: $*f_menu; + font-size: $*f_menu_size; + color: $*c_menu_text_color; + padding: 4px; + margin-top: 80px; + + } + + #menu-links { + background-image: url($*IMGDIR/style/cuteness/menubg.gif); + background-repeat: no-repeat; + margin-left: -10px; + margin-top: 5px; + width: 164px; + height: 179px; + padding-left: 30px; + padding-top: 3px; + } + html>body #content { + position: relative; + margin-top: 5px; + margin-left: 160px; + width: 532px; + z-index: 4; + } + + #content { + position: relative; + margin-top: -475px; + margin-left: 160px; + width: 532px; + z-index: 4; + } + + #entries { + position: relative; + background-image: url($*IMGDIR/style/cuteness/entry-bg.gif); + background-repeat: repeat-y; + width: 532px; + + } + + #entriesbg { + position: relative; + background-image: url($*IMGDIR/style/cuteness/content-header.gif); + background-position: top left; + background-repeat: no-repeat; + margin-left: 1px; + width: 532px; + } + + #entries-content { + position: relative; + padding-top: 130px; + width: 532px; + } + + #menu h2 { + margin: 20px 0; + font-family: $*f_menu_header; + font-size: $*f_menu_header_size; + color: $*c_menu_header_color; + } + #menu h2.userpic { + text-align: center; + } + #menu a { + font-family: $*f_menu_link; + font-size: $*f_menu_link_size; + color: $*c_menu_link; + } + #menu a:visited { color: $*c_menu_link_visited; } + #menu a:hover, #menu a:visited:hover { color: $*c_menu_link_hover; } + #menu a:active { color: $*c_menu_link_active; } + #menu ul { + margin: 3px; + list-style: none; + } + #menu ul li { + margin: 3px; + padding: 2px; + list-style: none; + } + #menu ul li.active { + font-family: $*f_menu_current; + font-size: $*f_menu_current_size; + color: $*c_menu_current; + font-weight: bold; + } + + #content h2 { + margin: 20px 0; + } + #entries, #comments { + margin: 10px; + } + + #entrybottom { + position: relative; + background-image: url($*IMGDIR/style/cuteness/entry-bottombg.gif); + background-repeat: no-repeat; + width: 528px; + height: 47px; + margin-left: 11px; + margin-top: -10px; + } + + #comment-info { + background-color: #f7f0f3; + } + + #comments div.entry-item { + padding: 5px; + } + + #comments div.ind-comment-one { + border: 2px solid $*c_comment_one_border; + background-color: $*c_comment_one_background; + + } + + .ind-entry { + width: 440px; + border-bottom: 1px solid $*c_entry_border; + margin-left: 25px; + padding: 10px; + } + .ind-entry h3 img, .ind-comment-one h3 img, .ind-comment-two h3 img, .ind-comment-screened h3 img { + position: relative; + float: right; + padding: 5px; + } + .ind-entry h2 { + font-family: $*f_entry_title; + font-size: $*f_entry_title_size; + color: $*c_entry_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-entry h4, .ind-comment-one h4, .ind-comment-two h4, .ind-comment-screened h4 { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + } + + .ind-entry h4 a, .ind-comment-one h4 a, .ind-comment-two h4 a, .ind-comment-screened h4 a { + font-family: $*f_meta_link; + font-size: $*f_meta_link_size; + color: $*c_meta_link; + text-decoration: underline; + } + .ind-entry h4 a:visited, .ind-comment-one h4 a:visited, .ind-comment-two h4 a:visited, .ind-comment-screened h4 a:visited { color: $*c_meta_link_visited; } + .ind-entry h4 a:hover, .ind-comment-one h4 a:hover, .ind-comment-two h4 a:hover, .ind-comment-screened h4 a:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:visited:hover, .ind-comment-one h4 a:visited:hover, .ind-comment-two h4 a:visited:hover, .ind-comment-screened h4 a:visited:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:active, .ind-comment-one h4 a:active, .ind-comment-two h4 a:active, .ind-comment-screened h4 a:active { color: $*c_meta_link_active; } + .ind-entry div.entry-item, .ind-entry div.month-entries { + font-family: $*f_entry; + font-size: $*f_entry_size; + color: $*c_entry_text_color; + margin: 15px 0px; + } + .ind-entry div.entry-item a, .ind-entry div.month-entries a { + font-family: $*f_entry_link; + font-size: $*f_entry_link_size; + color: $*c_entry_link; + text-decoration: underline; + } + .ind-entry div.entry-item a:visited, .ind-entry div.month-entries a:visited { color: $*c_entry_link_visited; } + .ind-entry div.entry-item a:hover, .ind-entry div.entry-item a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.month-entries a:hover, .ind-entry div.month-entries a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.entry-item a:active, .ind-entry div.month-entries a:active { color: $*c_entry_link_active; } + + .ind-comment-one, .ind-comment-two, .ind-comment-screened { + margin: 10px 0; + padding: 5px; + } + .ind-comment-screened { background-color: $*c_comment_screened_background; border-bottom: 1px solid $*c_comment_screened_border; } + + .ind-comment-one h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_one_title_color; + margin: 20px 0px; + } + .ind-comment-one div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_one_text_color; + margin: 15px 0px; + } + .ind-comment-one div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_one_link; + text-decoration: underline; + } + .ind-comment-one div.entry-item a:visited { color: $*c_comment_one_link_visited; } + .ind-comment-one div.entry-item a:hover, .ind-comment-one div.entry-item a:visited:hover { color: $*c_comment_one_link_hover; } + .ind-comment-one div.entry-item a:active { color: $*c_comment_one_link_active; } + + + .ind-comment-screened h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_screened_title_color; + margin: 20px 0px; + } + .ind-comment-screened div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_screened_text_color; + margin: 10px 0px; + } + .ind-comment-screened div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_screened_link; + text-decoration: underline; + } + .ind-comment-screened div.entry-item a:visited { color: $*c_comment_screened_link_visited; } + .ind-comment-screened div.entry-item a:hover, .ind-comment-screened div.entry-item a:visited:hover { color: $*c_comment_screened_link_hover; } + .ind-comment-screened div.entry-item a:active { color: $*c_comment_screened_link_active; } + + #comments { + width: 425px; + margin-left: 40px; + } + + .month-entries { + margin: 10px 0; + } + .month-entries ul { + list-style: none; + margin: 10px; + } + .month-entries ul li { + list-style: none; + padding: 3px; + } + + + #footer { + position: relative; + font-family: $*f_footer; + font-size: $*f_footer_size; + color: $*c_footer_text_color; + background-image: url($*IMGDIR/style/cuteness/footerbg.gif); + background-repeat: no-repeat; + width: 508px; + height: 53px; + margin-top: 20px; + } + #footer p { + padding-top: 10px; + padding-left: 30px; + vertical-align: middle; + } + #footer a { + font-family: $*f_footer_link; + font-size: $*f_footer_link_size; + color: $*c_footer_link; + } + #footer a:visited { color: $*c_footer_link_visited; } + #footer a:hover, #footer a:visited:hover { color: $*c_footer_link_hover; } + #footer a:active { color: $*c_footer_link_active; } + } + + @media print { + #menu { + display: none; + } + #content { + margin-left: 0px; + } + #entries, .ind-entry, .ind-comment, #footer, #header { + border: none; + } + + } + + $*css_style_overrides + + """; +} + + +# ------------------------------- +# user pic main page +# ------------------------------- +function Page::lay_top_userpic ( ) +{ + var Image up_img = $.journal.default_pic; + if ( defined $up_img ) { + print "

    \"$.journal.name\"

    "; + } +} + + +# ------------------------------- +# returns a permalink link based on +# the url passed +# ------------------------------- +function get_permalink ( string url ) : string +{ + return("$*text_permalink"); +} + + + +# ------------------------------- +# prints the user's 'link-list' +# ------------------------------- +function Page::print_linklist ( ) +{ + + if ( size $.linklist > 0 ) { + print "

    $*text_links_header

    "; + print "
      "; + foreach var UserLink l ( $.linklist ) { + if ( $l.title == "spacer" ) { + print "
    • $*text_links_spacer
    • "; + } elseif ($l.is_heading) { + print "
    • $l.title
    • "; + } elseif ( $l.title ) { + print "
    • $l.title
    • "; + } + } + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# prints the LJ specific links (recent, friends, etc) +# ------------------------------- +function print_lj_links ( Page p ) +{ + var string links; + $links = $links + ($p.view == "recent" ? "
  • $*text_view_recent
  • " : "
  • $*text_view_recent
  • "); + if ( $p.journal_type == "C" ) { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends_comm
  • " : "
  • $*text_view_friends_comm
  • "); + } else { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends
  • " : "
  • $*text_view_friends
  • "); + } + $links = $links + ($p.view == "archive" ? "
  • $*text_view_archive
  • " : "
  • $*text_view_archive
  • "); + $links = $links + "
  • $*text_view_userinfo
  • "; + $links = $links + ($p.journal.website_url != "" ? "
  • lower() + "\">" + $p.journal.website_name->lower() + "
  • " : ""); + + print "
      "; + print $links; + print "
    "; + print "
    "; +} + +function Page::lay_sidebar_view_summary() : string +{ + return(""); +} + + +# ------------------------------- +# main page layout +# ------------------------------- +function Page::print ( ) +{ + var string title = $this->title(); + + # generate page id: + var string current_view = $.view; + if ( $.view == "month" or $.view == "day" ) { + $current_view = "archive"; + } + if ( $.view == "entry" or $.view == "reply" ) { + $current_view = "recent"; + } + + # begin main page html: + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + $this->print_head(); + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$*text_page_title\n"; + print "\n"; + print "\n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    $*text_page_title

    \n"; + print "
    "; + print "
    \n"; + print "
    \n"; + + print "
    \n"; + print "
    \n"; + $this->lay_top_userpic(); + print "\n"; + print "
    \n"; + print "
    \n"; + print "

    $*text_summary_header

    \n"; + print_lj_links($this); + print "
    \n"; + print "\n"; + print "
    \n"; + print "
    \n"; + $this->print_body(); + print "
    \n"; + print "
    \n"; + print "\n"; + print "\n"; +} + + +# ------------------------------- +# main page display entries and +# footer +# ------------------------------- +function RecentPage::print_body ( ) +{ + + + # print all entries + print "
    \n"; + print "
    \n"; + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + + var string range = "most recent entries"; + if ( $.nav.skip > 0 ) { + $range = "$.nav.skip entries back"; + } + + print "

    "; + print "viewing: $range
    "; + # go forward/backward if possible + if ( $.nav.forward_url != "" or $.nav.backward_url != "" ) { + var string sep; + var string back; + var string forward; + if ( $.nav.backward_url != "" ) { + $back = "earlier"; + } + if ( $.nav.forward_url != "" ) { + $forward = "later"; + } + if ( $back != "" and $forward != "" ) { + $sep = " | "; + } + print "go: $back$sep$forward
    "; + } + print "

    "; + +} + + +# ------------------------------- +# entry view (show comments) +# ------------------------------- +function EntryPage::print_body ( ) +{ + print "
    \n"; + print "
    \n"; + print "
    \n"; + $this->print_entry ( $.entry ); + if ( $.entry.comments.enabled ) { + print "
    "; + print "

    Comments {$.entry.comments.count}

    "; + + if ( $.comment_pages.total_subitems > 0 ) { + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + $.comment_pages->print(); + $this->print_comments($.comments); + if ( $this.multiform_on ) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } + print "
    "; + + } + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + print "

    "; + print "$*text_post_comment\n"; + print "

    "; +} + + +# ------------------------------- +# day view +# ------------------------------- +function DayPage::print_body ( ) +{ + if ( not $.has_entries ) { + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    " + $.date->date_format("long") + "

    "; + print "

    $*text_noentries_day

    "; + print "
    "; + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + print "
    "; + } else { + print "
    \n"; + print "
    \n"; + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + print "

    "; + print "« $*text_day_prev | $*text_day_next »"; + print "

    "; +} + + +# ------------------------------- +# year view +# ------------------------------- +function YearPage::print_body ( ) +{ + print "
    \n"; + print "
    \n"; + print "
    \n"; + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; +} + + +# ------------------------------- +# display an entry (all views ) +# ------------------------------- +function print_entry ( Page p, Entry e ) +{ + # get date/time + var string datetime; + $datetime = $e.time->date_format($*date_format) + " | " + $e.time->time_format($*time_format); + + # get metadata + var string metadata; + if ( $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string text = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $text = $*text_meta_mood; + } elseif ( $k == "music" ) { + $text = $*text_meta_music; + } + if ( $k == "mood" and defined $e.mood_icon ) { + var Image i = $e.mood_icon; + $val = "\"$val\" $val"; + } + $metadata = "$metadata\n$text: $val
    "; + } + } + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( $p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username ) { + if ( $e.poster.username != $e.journal.username ) { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username in base_url() + "\" title=\"$e.journal.username\" >$e.journal.username"; + } else { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username"; + } + $poster = "posted by: $poster"; + if ( defined $e.userpic ) { + $userpic = "

    \"$e.journal.username\"

    "; + } + } + + # print the entry now: + print "
    "; + + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + + print "

    "; + if ( $e.security != "" ) { + $e.security_icon->print(); + print " "; + } + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + print "

    "; + + print "

    "; + if ( $p.view == "entry" and $*show_entrynav_icons ) { + var string item_link = ""; + foreach var string key (["nav_prev","nav_next"]) { + var Link link = $e->get_link($key); + if ( $link ) { + if ( $key == "nav_prev" ) { + $item_link = $item_link + "lower() + "\">« " + $link.caption->lower() + " | "; + } elseif ( $key == "nav_next" ) { + $item_link = $item_link + "lower() + "\">" + $link.caption->lower() + " »"; + } + } + } + print $item_link; + print "
    "; + } + print "$datetime
    "; + print "$metadata"; + if ( $poster != "" ) { + print "$poster"; + } + print "

    "; + + print "
    $e.text
    \n"; + + print "

    "; + print get_permalink($e.permalink_url); + if ( $p.view != "entry" and $p.view != "reply" ) { + print " | "; + $e.comments->print(); + } elseif ( $e.comments.enabled ) { + print " | "; + $e.comments->print_postlink(); + } + var Link tmp; + if ( viewer_is_owner() and $p.view != "friends" ) { + $tmp = $e->get_link("edit_entry"); + print " | $tmp.caption"; + } + $tmp = $e->get_link("mem_add"); + print " | $tmp.caption"; + print "

    "; + print "
    "; + print "
    "; +} + + +# ------------------------------- +# entry wrapper for main page +# ------------------------------- +function Page::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# entry wrapper for friends page +# ------------------------------- +function FriendsPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +function EntryPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + + +# ------------------------------- +# comments +# ------------------------------- +function CommentInfo::print ( ) +{ + if ( not $.enabled ) { + return; + } + + $this->print_postlink(); + if ( $.count > 0 or $.screened ) { + print " "; + print ""; + $this->print_readlink(); + print ""; + } +} + + +# ------------------------------- +# comment post link +# ------------------------------- +function CommentInfo::print_postlink ( ) +{ + var Page p = get_page(); + var string linktext = ( $p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment ); + if ( $.maxcomments ) { + "$*text_max_comments"; + } else { + "$linktext"; + } +} + + +# ------------------------------- +# print comment +# ------------------------------- +function EntryPage::print_comment ( Comment c ) +{ + var string comment_class = ""; + if ( $c.screened ) { + $comment_class = "ind-comment-screened"; + } elseif ( $c.depth % 2 == 0 ) { + $comment_class = "ind-comment-two"; + } else { + $comment_class = "ind-comment-one"; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_comment_anonymous"; + var string poster_text = defined $c.poster ? $c.poster.name : "$*text_comment_anonymous"; + var string sub_icon; + var int indent = (($c.depth - 1) * 5); + if ( defined $c.subject_icon ) { + $sub_icon = $c.subject_icon->as_string(); + } + + print "
    \n"; + + var string userpic; + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + $userpic = "

    \"$poster_text\"

    "; + } + var string commentdate = $c.time->date_format($*date_format) + " - " + $c.time->time_format($*time_format); + + + + # subject: + if ( $c.subject == "" ) { + print ""; + } else { + print "

    $c.subject_icon $c.subject

    "; + } + + print "
    "; + print "

    "; + #userpic + print "$userpic\n"; + print "From: $poster
    \n"; + print "Date: $commentdate
    \n"; + if ( $c.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $c.metadata{"poster_ip"} + "
    "; + } + print get_permalink($c.permalink_url) + "\n"; + var Link lnk; + $lnk = $c->get_link("delete_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("screen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("unscreen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + print "


    \n"; + + if ( $this.multiform_on ) { + print ""; + $c->print_multiform_check(); + } + + print "
    $c.text
    \n"; + print "

    "; + print "$*text_comment_reply"; + if ( $c.parent_url != "" ) { print " | $*text_comment_parent"; } + if ( $c.thread_url != "" ) { print " | $*text_comment_thread"; } + print "

    "; + print "
    \n\n"; + print "
    "; + + +} + + +# ------------------------------- +# print reply form page +# ------------------------------- +function ReplyPage::print_body ( ) +{ + if ( not $.entry.comments.enabled ) { + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    "; + print "

    $*text_reply_nocomments_header

    "; + print "$*text_reply_nocomments"; + print "
    "; + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + + } else { + print "
    \n"; + print "
    \n"; + print "
    \n"; + # get date + var string datetime; + $datetime = $.replyto.time->date_format($*date_format) + " | " + $.replyto.time->time_format($*time_format); + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( defined $.replyto.poster ) { + $poster = "base_url() + "\" title=\"$.replyto.poster.username\">$.replyto.poster.username"; + if ( defined $.replyto.userpic ) { + $userpic = "

    \"$.replyto.poster.username\"

    "; + } + } else { + $poster = "$*text_comment_anonymous"; + } + + + # print the entry now: + print "
    "; + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + print "

    "; + if ( $.replyto.subject == "" ) { + print ""; + } else { + print "$.replyto.subject"; + } + print "

    "; + + print "

    \n"; + print "$datetime
    "; + print "$*text_comment_from: $poster"; + if ( $.replyto.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $.replyto.metadata{"poster_ip"} + "
    "; + } + print "

    "; + print "
    $.replyto.text
    \n"; + print "

    "; + print get_permalink($.replyto.permalink_url) + " | $*text_comment_viewall\n"; + print "

    "; + print "
    \n"; + print "
    "; + print "
    \n"; + print "

    Reply

    \n"; + $.form->print(); + print "
    "; + print "
    "; + print "
    "; + print "
    "; + print "
    \n"; + print "
    "; + } +} + + +# ------------------------------- +# print available years +# ------------------------------- +function YearPage::print_year_links ( ) +{ + print "
    \n"; + print "

    "; + print "available years:
    "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + print "$y.year "; + } else { + print "$y.year "; + } + } + print "

    "; + +} + + +# ------------------------------- +# print available month +# ------------------------------- +function YearPage::print_month ( YearMonth m ) +{ + if ( not $m.has_entries ) { + return; + } + + + print "

    " + $m->month_format() + "

    \n"; + print "

    $*text_view_month

    "; + print "
    "; + foreach var YearWeek w ( $m.weeks ) { + foreach var YearDay d ( $w.days ) { + if ( $d.num_entries > 0 ) { + var string date = $d.date->date_format("%%dayord%%"); + print "$date {$d.num_entries}
    \n"; + } + } + } + print "
    \n"; + print "
    \n"; + print "
    "; +} + + +# ------------------------------- +# month view +# ------------------------------- +function MonthPage::print_body ( ) +{ + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    " + $.date->date_format($*lang_fmt_month_long) + "

    "; + + print "
    "; + $.redir->print_hiddens(); + if ( $.prev_url != "" ) { + print "[«]\n"; + } + if ( size $.months > 1 ) { + print "\n"; + } + if ( $.next_url != "" ) { + print "\n[»]\n"; + } + print "


    "; + + # print dates: + foreach var MonthDay d ( $.days ) { + if ( $d.has_entries ) { + print "
    \n"; + print "" + lang_ordinal($d.day) + "
    "; + print "
      "; + foreach var Entry e ( $d.entries ) { + print "
    • "; + print "" + $e.time->time_format("short") + " "; + if ( $e.poster.username != $e.journal.username ) { + $e.poster->print(); " : "; + } + "$e.security_icon "; + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + if ( $e.comments.count > 0 ) { + print " {" + $e.comments.count + "}"; + } + print "
    • "; + } + print "
    "; + print "
    "; + print "
    "; + } + } + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "
    "; + print "
    "; + +} diff --git a/local/bin/upgrading/s2layers/flexiblesquares/layout.s2 b/local/bin/upgrading/s2layers/flexiblesquares/layout.s2 new file mode 100755 index 0000000..04dd629 --- /dev/null +++ b/local/bin/upgrading/s2layers/flexiblesquares/layout.s2 @@ -0,0 +1,2076 @@ +# ----------------------------------- +# LAYER INFO +# ----------------------------------- +layerinfo type = "layout"; +layerinfo name = "Flexible Squares"; +layerinfo lang = "en"; +layerinfo author_name = "Yati Mansor"; +layerinfo redist_uniq = "flexiblesquares/layout"; + +# ----------------------------------- +# PROPGROUPS +# ----------------------------------- + + +### PRESENTATION +propgroup presentation = "Presentation"; +propgroup presentation +{ + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property bool show_entry_userpic + { + des = "Show user picture icons with each of your entries?"; + } + property string userpic_position + { + des = "Set the user picture position for each entry"; + values = "left|Left|right|Right"; + } + property bool use_friends_colours + { + des = "Use friends colours when viewing friends list?"; + } + set show_entry_userpic = true; + set userpic_position = "left"; + set use_friends_colours = true; + property use use_shared_pic; + property string page_alignment + { + des = "Set page alignment"; + values= "right|Right|center|Center|left|Left"; + } + set page_alignment = "center"; + property int journal_width + { + des = "Journal width"; + note = "Journal width can be set in either percentage of the browser window or in pixels (see next option)"; + min = 1; + } + property string journal_width_unit + { + des = "Unit of journal width"; + note = "Journal width can be set either in percentage of the browser window or in pixels"; + values = "%|%|px|px"; + } + set journal_width = 80; + set journal_width_unit = "%"; + +} + + +### SIDEBAR +propgroup sidebar = "Sidebar"; +propgroup sidebar +{ + property bool show_sidebar + { + des = "Show the sidebar?"; + } + set show_sidebar = true; + property string sidebar_position + { + des="Set sidebar position"; + values="left|Left|right|Right"; + } + set sidebar_position="right"; + property bool show_default_userpic + { + des = "Show the default user picture on the sidebar?"; + } + set show_default_userpic = true; + property bool show_blurb + { + des = "Show the blurb/free text in the sidebar?"; + } + property string text_sidebar_blurb + { + des = "Title of the blurb sidebar box"; + } + property string sidebar_blurb { + des = "Text to be added to the sidebar"; + note = "Appears in the sidebar 'Blurb'"; + rows = 10; + cols = 25; + } + set show_blurb = true; + set text_sidebar_blurb = "Blurb"; + property bool show_linklist + { + des = "Show the link list in the sidebar?"; + } + property string text_sidebar_links + { + des = "Title of the links sidebar box"; + } + set show_linklist = true; + set text_sidebar_links = "Links"; + property bool show_calendar + { + des = "Show the calendar in the sidebar?"; + } + set show_calendar = true; + property int sidebar_width + { + des = "Set sidebar width, in pixels"; + min = 0; + } + set sidebar_width = 160; + property string sidebar_order_1 + { + des = "First box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_2 + { + des = "Second box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_3 + { + des = "Third box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_4 + { + des = "Fourth box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + set sidebar_order_1 = "userpic"; + set sidebar_order_2 = "blurb"; + set sidebar_order_3 = "linklist"; + set sidebar_order_4 = "calendar"; +} + + +### BACKGROUND +propgroup background = "Background"; +propgroup background +{ + property string page_background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + property string page_background_repeat + { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string page_background_position + { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + property string page_background_scrolling + { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set page_background_image = ""; + set page_background_repeat = "repeat"; + set page_background_position = "center"; + set page_background_scrolling = "scroll"; +} + + + +### FONTS +propgroup fonts = "Fonts"; +propgroup fonts +{ + property string font_unit + { + des = "Font unit"; + values = "pt|Points|px|Pixels|em|Em"; + } + set font_unit = "px"; + property string main_font + { + des = "Preferred/base font"; + maxlength = 25; + size = 10; + example = "Tahoma"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int main_font_size + { + des = "Base font size"; + } + set main_font = "Verdana"; + set main_font_fallback = "sans-serif"; + set main_font_size= 11; + property string content_font + { + des = "Font for the entry/date/entry subject"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int content_font_size + { + des = "Entry/date/subject font size"; + } + property int date_font_size + { + des = "Date font size"; + } + property int subject_font_size + { + des = "Subject font size"; + } + set content_font = "Verdana"; + set content_font_fallback = "sans-serif"; + set content_font_size= 11; + set date_font_size= 11; + set subject_font_size= 11; + + + property string sidebar_font + { + des = "Font for the sidebar"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string sidebar_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int sidebar_font_size + { + des = "Sidebar font size"; + } + + set sidebar_font = "Verdana"; + set sidebar_font_fallback = "sans-serif"; + set sidebar_font_size= 11; + + property string header_footer_font + { + des = "Font for the header and footer"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string header_footer_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int header_footer_font_size + { + des = "Header and footer font size"; + } + + set header_footer_font = "Verdana"; + set header_footer_font_fallback = "sans-serif"; + set header_footer_font_size= 11; + + property string title_font + { + des = "Font for the title and subtitle"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string title_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int title_font_size + { + des = "Title font size"; + } + property int subtitle_font_size + { + des = "Subtitle font size"; + } + set title_font = "Verdana"; + set title_font_fallback = "sans-serif"; + set title_font_size= 11; + set subtitle_font_size= 11; +} + + +### COLOURS +propgroup colors = "Colours"; +propgroup colors +{ + property Color page_bgcolor + { + des = "Background color for the page"; + } + property Color page_fgcolor + { + des = "Text color for the page"; + } + property Color content_bgcolor + { + des = "Background color for box containing the main contents of the page"; + } + + property Color outer_table_bgcolor + { + des = "Background color of the outer table"; + } + + property Color entry_bgcolor + { + des = "Background color of the entries"; + } + property Color entry_fgcolor + { + des = "Text color of the entries"; + } + property Color border_color + { + des = "Border color of the content and header/footer boxes"; + } + + property Color entrytitle_bgcolor + { + des = "Background color of the subject, date and comment links"; + } + + property Color sidebar_header_bgcolor + { + des = "Background color for the headers in the sidebar"; + } + + property Color sidebar_fgcolor + { + des = "Text color for the sidebar"; + } + + property Color header_footer_bgcolor + { + des = "Background color of the header and footer"; + } + + property Color header_footer_fgcolor + { + des = "Text color for the header and footer"; + } + + property Color subject_fgcolor + { + des = "Text color for the subject of the entries"; + } + + property Color date_fgcolor + { + des = "Text color for the date of the entries"; + } + + set page_bgcolor = "#99AECE"; + set page_fgcolor = "#000000"; + set content_bgcolor = "#C2CDE0"; + set entry_bgcolor = "#D4DCE8"; + set entry_fgcolor = "#000000"; + set border_color = "#999999"; + set entrytitle_bgcolor = "#919BAD"; + set outer_table_bgcolor = "#A9B3C4"; + set sidebar_fgcolor = "#000000"; + set sidebar_header_bgcolor = "#919BAD"; + set header_footer_bgcolor = "#D4DCE8"; + set header_footer_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + set date_fgcolor = "#000000"; + + property Color link_color + { + des = "Link color for both visited and unvisited links"; + } + + property Color link_hover_color + { + des = "Link color on hover"; + } + + property Color comments_link_color + { + des = "Link color for visited and unvisited comment links"; + } + + property Color comments_link_hover + { + des = "Link color for comment links on hover"; + } + + property Color sidebar_link_color + { + des = "Link color for visited and unvisited sidebar links"; + } + + property Color sidebar_link_hover + { + des = "Link color for sidebar links on hover"; + } + + property Color header_footer_link_color + { + des = "Link color for visited and unvisited links for the header and footer"; + } + + property Color header_footer_link_hover + { + des = "Link color for comment links on hover for the header and footer"; + } + + + set link_color = "#5674B9"; + set link_hover_color = "#7AA1F8"; + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#B0B9C8"; + set sidebar_link_color = "#5674B9"; + set sidebar_link_hover = "#7AA1F8"; + set header_footer_link_color = "#5674B9"; + set header_footer_link_hover = "#7AA1F8"; +} + + +### TEXT +propgroup text = "Text"; +propgroup text +{ + property use text_meta_music; + property use text_meta_mood; + + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + + property use text_website_default_name; + property use text_view_recent; + property use text_view_friends; + property use text_view_userinfo; + property use text_view_archive; + set text_view_archive = "Archive"; + set text_view_friends = "Friends"; + set text_view_recent = "Recent Entries"; + set text_view_userinfo = "User Info"; + set text_website_default_name = "Website"; + + property use text_nosubject; + property string text_edit + { + des = "Text for an entry's edit link"; + } + property string text_memories + { + des = "Text to add an entry to the memories"; + } + property string text_previous_entry + { + des = "Text to link to the previous entry"; + } + property string text_next_entry + { + des = "Text to link to the next entry"; + } + set text_nosubject = "(no subject)"; + set text_permalink = "Link"; + set text_edit = "Edit"; + set text_memories = "Mem"; + set text_next_entry = "Next"; + set text_previous_entry = "Previous"; + + property use text_skiplinks_back; + property use text_skiplinks_forward; + set text_skiplinks_back = "go earlier"; + set text_skiplinks_forward = "go later"; +} + + + +### STYLESHEET OPTIONS +propgroup stylesheet = "Stylesheet"; +propgroup stylesheet +{ + property bool external_stylesheet + { + des = "Use linked stylesheet"; + } + property string external_stylesheet_url + { + des="External stylesheet URL"; + } + set external_stylesheet = true; +} + + + +# ----------------------------------- +# STYLESHEET +# ----------------------------------- + + +function css_font_family(string base, string fallback) : string +{ + var string return; + if ($base != "" or $fallback != "none") { + $return = $return + "font-family: "; + if ($base != "") { + $return = $return + "\"$base\""; + if ($fallback != "none") { + $return = $return + ", "; + } + } + if ($fallback != "none") { + $return = $return + $fallback; + } + } + return $return; +} + +function print_stylesheet () +{ + var string body_font_family = css_font_family($*main_font, $*main_font_fallback); + var string content_font_family = css_font_family($*content_font, $*content_font_fallback); + var string sidebar_font_family = css_font_family($*sidebar_font, $*sidebar_font_fallback); + var string header_footer_font_family = css_font_family($*header_footer_font, $*header_footer_font_fallback); + var string title_font_family = css_font_family($*title_font, $*title_font_fallback); + var string body_background = ""; + if ($*page_background_image != "") { + $body_background = """ + background-image: url("$*page_background_image"); + background-repeat: $*page_background_repeat; + background-position: $*page_background_position; + background-attachment: $*page_background_scrolling; + """; + } + + var string page_align = ""; + var string body_align = ""; + if ($*page_alignment == "left") + { + $page_align = "margin-left: 20px; margin-right: auto"; + } + if ($*page_alignment == "right") + { + $page_align = "margin-left: auto; margin-right: 20px"; + $body_align = "text-align: right"; + } + if ($*page_alignment == "center") + { + $page_align = "margin-left: auto; margin-right: auto"; + $body_align = "text-align: center"; + } + + var string maincontent_prop = ""; + var string sidebar_prop = ""; + var int float_margin = $*sidebar_width + 20; + if ($*show_sidebar and $*sidebar_position == "right") + { + $maincontent_prop = "margin-right: ${float_margin}px;"; + $sidebar_prop = "float: right;"; + + } + + if ($*show_sidebar and $*sidebar_position == "left") + { + $maincontent_prop = "margin-left: ${float_margin}px;"; + $sidebar_prop = "float: left;"; + } + if (not $*show_sidebar) + { + $maincontent_prop = ""; + } + + var string sidebar_pos = ""; + if ($*sidebar_position == "left") + { + $sidebar_pos = "clear: right"; + } + if ($*sidebar_position == "right") + { + $sidebar_pos = "clear: left"; + } + + print """ + + body { + background-color: $*page_bgcolor; + $body_background + $body_align; + color: $*page_fgcolor; + $body_font_family; + font-size: $*main_font_size$*font_unit; + margin: 20px 0 20px 0; + } + + a, a:link, a:visited { + color: $*link_color; + text-decoration: none; + } + + a:hover { + color: $*link_hover_color; + text-decoration: underline; + } + + p, td, blockquote { + font-size: $*content_font_size$*font_unit; + } + + code, kbd, pre, tt { + font-family: monospace; + } + + #content + { + width: $*journal_width$*journal_width_unit; + $page_align; + background-color: $*outer_table_bgcolor; + border-width: 1px; + border-style: solid; + border-color: $*border_color; + padding: 15px; + } + + #maincontent { + margin-top: 15px; + $content_font_family; + font-size: $*content_font_size$*font_unit; + background-color: $*content_bgcolor; + color: $*page_fgcolor; + border-style: solid; + border-color: $*border_color; + border-width: 1px; + $maincontent_prop + text-align: left; + } + + #sidebar { + + padding-top: 15px; + margin-top: 15px; + background-color: $*content_bgcolor; + border-color: $*border_color; + border-width: 1px; + border-style: solid; + font-size: $*sidebar_font_size$*font_unit; + $sidebar_font_family; + color: $*sidebar_fgcolor; + width: ${*sidebar_width}px; + $sidebar_prop + text-align: left; + } + + #header { + width: 100%; + padding: 10px 0px 20px 0px; + margin: 0px; + text-align: center; + $header_footer_font_family; + font-size: $*header_footer_font_size$*font_unit; + font-weight: bold; + letter-spacing: 2px; + border-style: solid; + border-color: $*border_color; + border-width: 1px; + background-color: $*header_footer_bgcolor; + color: $*header_footer_fgcolor; + } + + #footer { + width: 100%; + text-align: center; + $header_footer_font_family; + font-size: $*header_footer_font_size$*font_unit; + font-weight: bold; + letter-spacing: 1px; + background-color: $*header_footer_bgcolor; + color: $*header_footer_fgcolor; + border-color: $*border_color; + border-width: 1px; + border-style: solid; + z-index: 100; + clear: both; + } + + /* header -- links to views; title of journal; subtitle of journal */ + + div#header a, div#header a:link, div#header a:visited, div#footer a, div#footer a:link, div#footer a:visited { + color: $*header_footer_link_color; + } + + div#header a:hover, div#footer a:hover { + color: $*header_footer_link_hover; + text-decoration: none; + } + + ul.navheader + { + padding: 0px; + margin: 0px; + } + + ul.navheader li { + display: inline; + padding: 0 3px 0 3px; + } + + .title { + $title_font_family; + font-size: $*title_font_size$*font_unit; + font-weight: normal; + line-height: 200%; + top: 10px; + } + + .subtitle{ + $title_font_family; + font-size: $*subtitle_font_size$*font_unit; + font-weight: normal; + top: 10px; + } + + + /* sidebar */ + + div#sidebar a, div#sidebar a:link, div#sidebar a:visited{ + color: $*sidebar_link_color; + } + + div#sidebar a:hover { + color: $*sidebar_link_hover; + text-decoration: none; + } + + .defaultuserpic { + text-align: center; + } + + .sbarheader { + padding: 0px 5px 0px 5px; + } + + .sbarbody { + padding: 0px 5px 0px 5px; + } + + .sbarbody2 { + padding: 0 15px 0 15px; + } + + table.calendar { + margin-right: auto; + margin-left: auto; + } + + .sbarcalendar { + border-color: $*page_fgcolor; + border-width: 1px; + border-style: solid; + text-align: center; + $sidebar_font_family; + font-size: $*sidebar_font_size$*font_unit; + } + + .sbarcalendarposts { + border-color: $*page_fgcolor; + border-width: 1px; + border-style: solid; + background-color: $*entry_bgcolor; + text-align: center; + $sidebar_font_family; + font-size: $*sidebar_font_size$*font_unit; + } + + ul.sbarlist + { + padding-left: 0px; + margin-left: 0px; + list-style: none; + } + + li.sbaritem + { + padding-left: 15px; + list-style: none; + } + + li.sbartitle + { + padding-left: 15px; + list-style: none; + border-style: solid; + border-width: 1px; + border-color: $*border_color; + background-color: $*sidebar_header_bgcolor; + margin-bottom: 10px; + margin-top: 10px; + } + + + /* maincontent */ + + .subcontent { + } + + .entry { + margin: 0px 10px 10px 30px; + padding: 10px; + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + $content_font_family; + font-size: $*content_font_size$*font_unit; + text-align: left; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .entry ul li + { + padding-left: 5px; + margin-left: 15px; + } + + .entry ol li + { + padding-left: 5px; + margin-left: 15px; + } + + .userpic { + position: relative; + float: $*userpic_position; + background-color: $*entry_bgcolor; + padding: 5px; + margin: 10px; + z-index: 15; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .userpicfriends { + position: relative; + float: $*userpic_position; + padding: 5px; + margin: 10px; + text-align: center; + border-style: solid; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + $content_font_family; + font-size: $*content_font_size$*font_unit; + z-index: 15; + } + + .date { + line-height: 200%; + top: 5px; + color: $*date_fgcolor; + $content_font_family; + font-size: $*date_font_size$*font_unit; + } + + .subject { + font-weight: bold; + padding: 10px; + color: $*subject_fgcolor; + $content_font_family; + font-size: $*subject_font_size$*font_unit; + } + + .subject a, .subject a:link, .subject a:visited { + color: $*comments_link_color; + } + + .subject a:hover { + color: $*comments_link_hover; + } + + .datesubject { + background-color: $*entrytitle_bgcolor; + padding: 5px; + } + + .currents, .currentmood, .currentmusic { + $content_font_family; + font-size: $*content_font_size$*font_unit; + } + + .comments { + $content_font_family; + font-size: $*content_font_size$*font_unit; + text-align: right; + background-color: $*entrytitle_bgcolor; + padding: 0px 5px 0px 5px; + position: relative; + top: 15px; + } + + div.comments a, div.comments a:link, div.comments a:visited{ + color: $*comments_link_color; + } + + div.comments a:hover { + color: $*comments_link_hover; + text-decoration: none; + } + + + /* maincontent -- entry, reply pages */ + + .datesubjectcomment { + background-color: $*entrytitle_bgcolor; + padding: 5px; + margin-top: 20px; + } + + .userpiccomment { + position: relative; + border-width: 5px; + border-style: solid; + border-color: $*entry_bgcolor; + background-color: $*entry_bgcolor; + top: -30px; + left: 0px; + padding: 5px; + margin: 10px 10px -20px 10px; + z-index: 15; + float: $*userpic_position; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .box { + border-style: solid; + border-width: 1px 0px 0px 0px; + border-color: $*border_color; + padding: 10px; + $sidebar_pos; + } + + input, textarea { + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + } + + textarea.textbox { + width: 100% !important; + } + + .reply { + position: relative; + margin: 20px 30px 10px 30px; + padding: 25px 10px 10px 10px; + text-align: left; + $content_font_family; + font-size: $*content_font_size$*font_unit; + line-height: 125%; + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + } + + .replytosubject { + font-weight: bold; + } + + + .commentreply { + position: relative; + margin: 10px; + font-size: $*content_font_size$*font_unit; + $content_font_family; + color: $*entry_fgcolor; + } + + .commentbox { + + border-color: $*border_color; + border-width: 1px; + border-style: solid; + padding: 10px; + margin: 10px; + background-color: $*entry_bgcolor; + } + + .datesubjectcomment a:link, .datesubjectcomment a:visited { + color: $*comments_link_color; + } + + .datesubjectcomment a:hover { + color: $*comments_link_hover; + } + + .commentboxpartial { + border-color: $*border_color; + border-width: 1px; + border-style: solid; + padding: 10px; + margin: 10px; + background-color: $*entry_bgcolor; + } + + .commentinfo { + background-color: $*entry_bgcolor; + margin-top: 10px; + width: 100%; + } + + + /* maincontent -- year/achive pages */ + + ul.year { + text-align: center; + padding-bottom: 40px; + } + + ul.year li { + display: inline; + } + + table.yeartable { + margin-left: auto; + margin-right: auto; + } + + table.yeartable td.yeardate, table.yeartable td.yearday { + border-width: 1px; + border-style: solid; + border-color: $*border_color; + } + + table.yeartable td.yearday { + background-color: $*entry_bgcolor; + text-align: center; + } + + td.yearmonth { + border-style: none; + } + + + /* footer */ + + ul.navfooter{ + padding: 0px; + margin: 0px; + } + + ul.navfooter li { + display: inline; + margin: 0 5px 0 5px; + } + + + .clearfoot { + clear: both; + } + + + /* misc */ + + .clear { + height: 15px; + } + + .skiplinks { + text-align: center; + } + + .headerimage { + /* for formatting header image */ + } + + .separator{ + /* for formatting separators between entries */ + height: 35px; + } + """; +} + +function print_custom_stylesheet() +{ + # override +} + +# ----------------------------------- +# SIDEBAR +# ----------------------------------- + + +function print_sidebar_box(string title, string body) +{ + + print safe """ +
      $title$body
    + """; + +} + + +function print_userpic () { + var Page p= get_page(); + var Image up_img = $p.journal.default_pic; + if (defined $up_img) { + """
    + $p.journal.name +
    """; + } +} + + + +function print_sidebar_calendar() +{ + var string calendar; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """
    """; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + if ($d.num_entries) { + $calendar = $calendar + """"""; + } else { + $calendar = $calendar + """"""; + } + } + $calendar = $calendar + "\n"; + } + $calendar = $calendar + "
     $d.day$d.day
    "; + } + $month = """
    • $month
    """; + if ($calendar != "") { + print $month; + print $calendar; + } +} + + +function print_sidebar_blurb () +{ + var string blurb_title = ""; + if ($*text_sidebar_blurb == "") + { + $blurb_title = ""; + } + else + { + $blurb_title = """
    • $*text_sidebar_blurb
    """; + } + var string blurb = ""; + $blurb = """
    $*sidebar_blurb
    """; + + if ($*show_blurb and ($*sidebar_blurb != "")) + { + print $blurb_title; + print $blurb; + } +} + +function print_sidebar_linklist() +{ + var Page p = get_page(); + if (size $p.linklist <= 0) + { + return; + } + elseif (not $*linklist_support) + { + return; + } + + var string list = ""; + foreach var UserLink l ($p.linklist) + { + if ($l.title) { + if ($l.is_heading) + { + $list = $list + """
  • $l.title
  • """; + } + else + { + $list = $list + """
  • $l.title
  • """; + } + } + else + { + $list = $list; + } + } + + var string list_title = ""; + if ($*text_sidebar_links != "") + { + $list_title = """
  • $*text_sidebar_links
  • """; + } + else + { + $list_title = ""; + } + print_sidebar_box($list_title, $list); +} + +function sidebar_order(string order) +{ + if ($order == "userpic" and $*show_default_userpic) + { + print_userpic(); + } + if ($order == "blurb" and $*show_blurb) + { + print_sidebar_blurb(); + } + if ($order == "linklist" and $*show_linklist) + { + print_sidebar_linklist(); + } + if ($order == "calendar" and $*show_calendar) + { + print_sidebar_calendar(); + } +} + +function print_sidebar() +{ + sidebar_order($*sidebar_order_1); + sidebar_order($*sidebar_order_2); + sidebar_order($*sidebar_order_3); + sidebar_order($*sidebar_order_4); +} + + + +# ----------------------------------- +# PAGE +# ----------------------------------- + +# Header +function Page::lay_print_header() +"Prints header" +{ + var Page page = get_page(); + var string title = $this->title(); + + print """ + +"""; +} + +# Footer +function Page::lay_print_footer() +{ + """ +
     
    + """; +} + + + +function Page::print () { + var Page page = get_page(); + var string title = $this->title(); + + """ + + + + $title"""; + $this->print_head(); + if ($*external_stylesheet and $*external_stylesheet_url !="") + { + println """"""; + } + elseif ($*external_stylesheet) + { + println """"""; + } + else + { + println """"; + } + + $this->print_custom_head(); + """ + + + +
    +
    + """; + $this->lay_print_header(); + + if ($*show_sidebar) + { + """ + + """; + } + """ +
    """; + $this->print_body(); + " +
    "; + $this->lay_print_footer(); + "
    + + "; +} + + + + +function Entry::print_linkbar() +{ + # Links (memories, edit, prev, next) + var Page p = get_page(); + var Link prev; + var Link edit; + var Link mem; + var Link next; + if ($p.view == "entry" or $p.view == "reply") + { + $prev = $this->get_link("nav_prev"); + $edit = $this->get_link("edit_entry"); + $mem = $this->get_link("mem_add"); + $next = $this->get_link("nav_next"); + """ +
     
    + +
     
    """; + } + +} + + +function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor) +{ + $e->print_linkbar(); + + + # Userpic + + var string userpic = ""; + if ($*show_entry_userpic) + { + if ($p.view == "friends" or $p.view == "entry") + { + if (defined $e.userpic) + { + $userpic = $userpic + """$e.poster.name"; + } + } + elseif ($p.journal_type == "C" and $p.view == "recent") + { + if (defined $e.userpic) + { + $userpic = $userpic + """$e.poster.name"""; + } + } + else + { + if (defined $e.userpic) + { + $userpic = $userpic + """
    $e.poster.name
    """; + } + } + } + print """ +
    + """; + if (($p.view == "recent" and $p.journal_type != "C" ) or $p.view == "day") + { + print """$userpic"""; + } + else + { + if ($p.view == "recent" and $p.journal_type == "C" ) + { + """
    """; + } + else + { + """
    """; + } + print """$userpic"""; + + + # Poster + + if ($p.view == "friends" or $p.view == "entry") + { + var UserLite linkto; + $linkto = $e.poster; + #print "$e.poster.username"; + """
    base_url() + "\">"; + "$linkto.username"; + } + elseif ($p.journal_type == "C" and $p.view == "recent") + { + var UserLite linkto; + $linkto = $e.poster; + #print "$e.poster.username"; + """
    base_url() + "\">"; + "$linkto.username"; + } + if (($p.view == "friends" or $p.view == "entry") and $e.poster.username != $e.journal.username) + { + var UserLite linkto; + $linkto = $e.journal; + """
    [base_url() + "\">"; + "$linkto.username]"; + } + if ($p.view == "recent" and $p.journal_type == "C") + { + print "
    "; + } + if ($p.view != "recent" and $p.view != "day") + { + print """
    """; + } + } + + + # Date, time, subject + + var string time = ""; + $time = $time + """ @ """; + $time = $time + $e.time->time_format("short"); + var string date = ""; + $date = $date + $e.time->date_format("long_day"); + """ +
    """; + print $e.time->date_format("%%dd%% %%month%% %%yyyy%%"); + "$time +
    "; + """ +
    """; + if ($e.security != "") + { + $e.security_icon->print(); + } + """ + $e.subject   +
    +
    + """; + + """ +
    +
    $e.text
    """; + + # Currents + + var string currents =""; + $e->print_metadata(); + + # Comments + + """ +
     
    +
    """; + if ($p.view != "entry" or $p.view != "reply") + { + $e.comments->print(); + } + elseif ($e.comments.enabled) + { + $e.comments->print_postlink(); + } + else + { + " "; + } + """ +
    +
    +
    + +
    +
     
    """; +} + + +function Page::print_entry(Entry e) { + print_entry($this, $e, null Color, null Color); +} + + +function FriendsPage::print_entry (Entry e) +{ + if ($*use_friends_colours) + { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor); + } + else + { + print_entry($this, $e, $*entry_bgcolor, $*entry_fgcolor); + } +} + +function EntryPage::print_entry(Entry e) { + print_entry($this, $e, $*entry_bgcolor, $*entry_fgcolor); +} + +function Entry::print_metadata() { + if (size $.metadata) + { + print """
     
     
    +
    """; + var string currents; + foreach var string k ($.metadata) + { + var string text = $k; + var string val = $.metadata{$k}; + if ($k == "mood") + { + $text = $*text_meta_mood; + } + elseif ($k == "music") + { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $.mood_icon) + { + var Image i = $.mood_icon; + $val = " $val"; + } + $currents = $currents + """
    $text: $val
    """; + } + $currents = $currents + "
    "; + println "$currents"; + } +} + + +function RecentPage::lay_print_footer() +{ + var string range = "most recent entries"; + var string sep; + var string back; + var string forward; + + if ($.nav.skip > 0) + { + $range = "$.nav.skip entries back"; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") + { + if ($.nav.backward_url != "") + { + $back = """
  • $*text_skiplinks_back
  • """; + } + if ($.nav.forward_url != "") + { + $forward = """
  • $*text_skiplinks_forward
  • """; + } + } + """ +
     
    + +
     
    + """; +} + +function RecentPage::print_body +{ + foreach var Entry e ($.entries) + { + $this->print_entry($e); + } +} + + +function EntryPage::print_body() +{ + $this->print_entry($.entry); + if ($.multiform_on and $.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + } + if ($.entry.comments.enabled) + { + """ +
    + +
    """; + $.comment_pages->print(); + """ + ( Post a new comment ) +
    """; + $this->print_comments($.comments); + """ +
    """; + } + + if ($this.multiform_on and $.entry.comments.enabled and $.entry.comments.count > 0) + { + """ +
    """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + """ +
    + ( Post a new comment )"""; + $.comment_pages->print(); + """ +
    +
    +
    """; + } +} + + + +# ----------------------------------- +# ENTRY +# ----------------------------------- + +function EntryPage::print_comments( Comment[] comments ) +{ + if ( size $comments == 0 ) + { + return; + } + + foreach var Comment c ( $comments ) + { + var int indent = ($c.depth - 1) * 30; + var string partialcomment = $c.full ? "" : "partial"; + var string margin = ""; + if ($*userpic_position == "left") + { + $margin = "right"; + } + else + { + $margin = "left"; + } + + """"""; + """
    \n"""; + if ( $c.full ) + { + $this->print_comment( $c ); + } + else + { + $this->print_comment_partial( $c ); + } + "
    "; + $this->print_comments( $c.replies ); + } +} + + +function EntryPage::print_comment (Comment comment) { + + var string subject = $comment.subject ? $comment.subject : $*text_nosubject; + var string date = $comment.time->date_format(); + var string poster = isnull $comment.poster ? $*text_poster_anonymous : $comment.poster->as_string(); + + #Comment Userpic + if (defined $comment.userpic and $*show_entry_userpic) + { + var int w = $comment.userpic.width; + var int h = $comment.userpic.height; + var string alt = $comment.metadata{"picture_keyword"}; + if ($*comment_userpic_style == "small") + { + $w = $w / 2; + $h = $h / 2; + } + if ($alt != "") + { + $alt = ": " + $alt; + } + """ +
    + $comment.poster.name$alt"""; + print """$poster on """; + print $comment.time->date_format("long") + " - " + $comment.time->time_format(); + } + else + { + print """ +
    $poster on """; + print $comment.time->date_format("long") + " - " + $comment.time->time_format(); + } + if (defined $comment.subject_icon or $comment.subject != "") + { + print "
    $comment.subject_icon $comment.subject" + "
    "; + } + if ($comment.metadata{"poster_ip"}) + { + print "
    " + $*text_comment_ipaddr + "(" + $comment.metadata{"poster_ip"} + ")" + "
    "; + } + "
    "; + + print """ +
    $comment.text
    \n"""; + var string alignlinks = ""; + if ($*userpic_position == "left") + { + $alignlinks = "right"; + } + else + { + $alignlinks = "left"; + } + "
    "; + + if ($comment.frozen) + { + "($*text_comment_frozen)"; + } + else + { + "($*text_comment_reply) "; + } + + if ($comment.parent_url != "") + { + "($*text_comment_parent) "; + } + + if ($comment.thread_url != "") + { + """($*text_comment_thread) """; + } + + "($*text_permalink)"; + + + """
    """; + if ($this.multiform_on) + { + """"""; + $comment->print_multiform_check(); + } + $comment->print_linkbar(); + + + "
    \n"; +} + +function EntryPage::print_comment_partial( Comment c ) +{ + var string subject = $c.subject ? $c.subject : $*text_nosubject; + var string date = $c.time->date_format("long") + " - " + $c.time->time_format(); + var string poster = isnull $c.poster ? $*text_poster_anonymous : $c.poster->as_string(); + + """$subject - $poster on $date"""; +} + +# ----------------------------------- +# DAY +# ----------------------------------- + + +function DayPage::print_body() { + """ +
     
    + +
     
    """; + if ($.has_entries) + { + foreach var Entry e ($.entries) + { + $this->print_entry($e); + } + } + else { + """

    $*text_noentries_day

    """; + } + """ +
     
    + +
     
    + """; +} + +function CommentInfo::print() { + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); + " | "; + } + $this->print_postlink(); +} + + +# ----------------------------------- +# REPLY +# ----------------------------------- + + +function ReplyPage::print_body +{ + if (not $.entry.comments.enabled) + { + print " +

    $*text_reply_nocomments_header

    +

    $*text_reply_nocomments

    "; + return; + } + + $.entry->print_linkbar(); + + """
    """; + if (defined $.replyto.userpic) + { + print """
    $.replyto.userpic
    """; + } + + var string poster = isnull $.replyto.poster ? $*text_poster_anonymous : $.replyto.poster->as_string(); + var Page p; + print """ +
    +
    """; + print $.replyto.poster.name + " ("; + print $poster + ") "; + print "wrote"; + if ($.journal_type == "C") + { + print " in "; + print $.replyto.journal; + print " "; + } + print " "+lang_at_datetime($.replyto.time); + + print """ +
    +
    $.replyto.subject
    +
    +
    $.replyto.text
    +
    +
     
    +
    +
    ( Read comments )
    + Post a comment in response:
    """; + $.form->print(); + " +
    + "; +} + + + +# ----------------------------------- +# MONTH +# ----------------------------------- + +function MonthPage::print_body { + "
    +

    "; + $.redir->print_hiddens(); + if ($.prev_url != "") + { + "[<<<]\n"; + } + if (size $.months > 1) + { + "\n"; + } + if ($.next_url != "") + { + "\n[>>>]\n"; + } + """ +
    \n +

    +
    +
    """; + foreach var MonthDay d ($.days) + { + if ($d.has_entries) + { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    +
    +
    "; +} + + + + +# ----------------------------------- +# YEAR +# ----------------------------------- + + +function YearPage::print_body +{ + $this->print_year_links(); + foreach var YearMonth m ($.months) + { + $this->print_month($m); + } +} + +function YearPage::print_year_links() { + """
      \n"""; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """
    • $y.year
    • \n"""; + } else { + """
    • $y.year
    • \n"""; + } + } + """
    \n"""; +} + + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) + { + return; + } + """\n + + + \n"""; + foreach var int d (weekdays()) { + """\n"; + } + "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + "
    """; + print $m->month_format(); + """$*text_view_month
    """+$*lang_dayname_short[$d]+"
    +


    "; +} + +function YearWeek::print() +{ + """\n"""; + if ($.pre_empty > 0) + { + """ \n"""; + } + foreach var YearDay d ($.days) + { + """\n"""; + """
    $d.day
    \n"""; + if ($d.num_entries > 0) + { + """\n"""; + } + else + { + """
     
    """; + } + """\n"""; + } + if ($.post_empty > 0) + { + """ \n"""; + } + ""; +} + + diff --git a/local/bin/upgrading/s2layers/flexiblesquares/themes.s2 b/local/bin/upgrading/s2layers/flexiblesquares/themes.s2 new file mode 100755 index 0000000..bd785cc --- /dev/null +++ b/local/bin/upgrading/s2layers/flexiblesquares/themes.s2 @@ -0,0 +1,615 @@ +#NEWLAYER: flexiblesquares/autumn +layerinfo "redist_uniq" = "flexiblesquares/autumn"; +layerinfo "type" = "theme"; +layerinfo "name" = "Autumn"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#351805"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#6a3106"; + + set entry_bgcolor = "#eee293"; + set entry_fgcolor = "#661f0c"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#8b4e1d"; + + set outer_table_bgcolor = "#c47b51"; + + set sidebar_header_bgcolor = "#8b4e1d"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#eee293"; + set header_footer_fgcolor = "#661f0c"; + + set link_color = "#608729"; + set link_hover_color = "#661f0c"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#c47b51"; + + set sidebar_link_color = "#608729"; + set sidebar_link_hover = "#eee293"; + + set header_footer_link_color = "#608729"; + set header_footer_link_hover = "#661f0c"; + +#NEWLAYER: flexiblesquares/blackwhite +layerinfo "redist_uniq" = "flexiblesquares/blackwhite"; +layerinfo "type" = "theme"; +layerinfo "name" = "Black and White and Red All Over"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#cccccc"; + set page_fgcolor = "#ff0000"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#cc0000"; + + set outer_table_bgcolor = "#666666"; + + set sidebar_header_bgcolor = "#cc0000"; + set sidebar_fgcolor = "#ffffff"; + + set header_footer_bgcolor = "#000000"; + set header_footer_fgcolor = "#cc0000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#999999"; + set link_hover_color = "#000000"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#999999"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#ffffff"; + set header_footer_link_hover = "#999999"; + +#NEWLAYER: flexiblesquares/freshpaint +layerinfo "redist_uniq" = "flexiblesquares/freshpaint"; +layerinfo "type" = "theme"; +layerinfo "name" = "Fresh Paint"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#993366"; + set page_fgcolor = "#006633"; + + set content_bgcolor = "#ff9933"; + + set entry_bgcolor = "#ffff99"; + set entry_fgcolor = "#000000"; + + set border_color = "#6699cc"; + + set entrytitle_bgcolor = "#ccff66"; + + set outer_table_bgcolor = "#330033"; + + set sidebar_header_bgcolor = "#ccff66"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffff99"; + set header_footer_fgcolor = "#006633"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#993333"; + set link_hover_color = "#330033"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#330033"; + + set sidebar_link_color = "#993333"; + set sidebar_link_hover = "#330033"; + + set header_footer_link_color = "#993333"; + set header_footer_link_hover = "#330033"; + +#NEWLAYER: flexiblesquares/nautical +layerinfo "redist_uniq" = "flexiblesquares/nautical"; +layerinfo "type" = "theme"; +layerinfo "name" = "Nautical"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#bad2f6"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#213659"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#d4e2f8"; + + set entrytitle_bgcolor = "#f0ef8e"; + + set outer_table_bgcolor = "#335288"; + + set sidebar_header_bgcolor = "#f0ef8e"; + set sidebar_fgcolor = "#7fa1d5"; + + set header_footer_bgcolor = "#213659"; + set header_footer_fgcolor = "#f0ef8e"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#7fa1d5"; + set link_hover_color = "#000000"; + + set comments_link_color = "#335288"; + set comments_link_hover = "#7fa1d5"; + + set sidebar_link_color = "#f0ef8e"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#7fa1d5"; + set header_footer_link_hover = "#ffffff"; + +#NEWLAYER: flexiblesquares/machine +layerinfo "redist_uniq" = "flexiblesquares/machine"; +layerinfo "type" = "theme"; +layerinfo "name" = "Machine"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#C1C1C1"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#000000"; + set entry_fgcolor = "#cbd3d8"; + + set border_color = "#7e8997"; + + set entrytitle_bgcolor = "#555a60"; + + set outer_table_bgcolor = "#000000"; + + set sidebar_header_bgcolor = "#555a60"; + set sidebar_fgcolor = "#C1C1C1"; + + set header_footer_bgcolor = "#000000"; + set header_footer_fgcolor = "#C1C1C1"; + + set date_fgcolor = "#C1C1C1"; + set subject_fgcolor = "#C1C1C1"; + + set link_color = "#8797a0"; + set link_hover_color = "#ffffff"; + + set comments_link_color = "#8797a0"; + set comments_link_hover = "#ffffff"; + + set sidebar_link_color = "#8797a0"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#8797a0"; + set header_footer_link_hover = "#ffffff"; + +#NEWLAYER: flexiblesquares/pastelspring +layerinfo "redist_uniq" = "flexiblesquares/pastelspring"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pastel Spring"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#ffffff"; + set page_fgcolor = "#993333"; + + set content_bgcolor = "#ffffcc"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#ebccb1"; + + set entrytitle_bgcolor = "#ebccb1"; + + set outer_table_bgcolor = "#dae3b2"; + + set sidebar_header_bgcolor = "#ebccb1"; + set sidebar_fgcolor = "#993333"; + + set header_footer_bgcolor = "#ffffff"; + set header_footer_fgcolor = "#9FA876"; + + set date_fgcolor = "#993333"; + set subject_fgcolor = "#993333"; + + set link_color = "#9d7980"; + set link_hover_color = "#000000"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#ffffff"; + + set sidebar_link_color = "#9d7980"; + set sidebar_link_hover = "#9FA876"; + + set header_footer_link_color = "#9F3E3E"; + set header_footer_link_hover = "#ebccb1"; + +#NEWLAYER: flexiblesquares/pinkpunk +layerinfo "redist_uniq" = "flexiblesquares/pinkpunk"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pink Punk"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#cc0066"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#ffccff"; + set entry_fgcolor = "#000000"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#ff6699"; + + set outer_table_bgcolor = "#cc0066"; + + + set sidebar_header_bgcolor = "#ff6699"; + set sidebar_fgcolor = "#ffccff"; + + set header_footer_bgcolor = "#ffccff"; + set header_footer_fgcolor = "#000000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#6666cc"; + set link_hover_color = "#ff6699"; + + set comments_link_color = "#ffccff"; + set comments_link_hover = "#6666cc"; + + set sidebar_link_color = "#6666cc"; + set sidebar_link_hover = "#ff6699"; + + set header_footer_link_color = "#6666cc"; + set header_footer_link_hover = "#ff6699"; + +#NEWLAYER: flexiblesquares/purpleperiwinkle +layerinfo "redist_uniq" = "flexiblesquares/purpleperiwinkle"; +layerinfo "type" = "theme"; +layerinfo "name" = "Purple Periwinkle"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#2f0b31"; + set page_fgcolor = "#2f0b31"; + + set content_bgcolor = "#671368"; + + set entry_bgcolor = "#f4a3e9"; + set entry_fgcolor = "#2f0b31"; + + set border_color = "#2f0b31"; + + set entrytitle_bgcolor = "#9488d8"; + + set outer_table_bgcolor = "#a13ea7"; + + set sidebar_header_bgcolor = "#9488d8"; + set sidebar_fgcolor = "#DADADA"; + + set header_footer_bgcolor = "#f4a3e9"; + set header_footer_fgcolor = "#2f0b31"; + + set date_fgcolor = "#2f0b31"; + set subject_fgcolor = "#2f0b31"; + + set link_color = "#dc039d"; + set link_hover_color = "#7e025a"; + + set comments_link_color = "#7e025a"; + set comments_link_hover = "#f4a3e9"; + + set sidebar_link_color = "#dc039d"; + set sidebar_link_hover = "#FFCCCC"; + + set header_footer_link_color = "#dc039d"; + set header_footer_link_hover = "#7e025a"; + +#NEWLAYER: flexiblesquares/grays +layerinfo "redist_uniq" = "flexiblesquares/grays"; +layerinfo "type" = "theme"; +layerinfo "name" = "Grays"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#111111"; + set page_fgcolor = "#ffffff"; + + set content_bgcolor = "#333333"; + + set entry_bgcolor = "#666666"; + set entry_fgcolor = "#ffffff"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#000000"; + + set outer_table_bgcolor = "#222222"; + + set sidebar_header_bgcolor = "#000000"; + set sidebar_fgcolor = "#ffffff"; + + set header_footer_bgcolor = "#666666"; + set header_footer_fgcolor = "#ffffff"; + + set date_fgcolor = "#ffffff"; + set subject_fgcolor = "#ffffff"; + + set link_color = "#ffcc33"; + set link_hover_color = "#ff9933"; + + set comments_link_color = "#ffcc33"; + set comments_link_hover = "#ff9933"; + + set sidebar_link_color = "#ffcc33"; + set sidebar_link_hover = "#ff9933"; + + set header_footer_link_color = "#ffcc33"; + set header_footer_link_hover = "#ff9933"; + +#NEWLAYER: flexiblesquares/lemongrapetang +layerinfo "redist_uniq" = "flexiblesquares/lemongrapetang"; +layerinfo "type" = "theme"; +layerinfo "name" = "Lemon Grapefruit Tangerine"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#ffff66"; + set page_fgcolor = "#993333"; + + set content_bgcolor = "#cc3333"; + + set entry_bgcolor = "#ffffcc"; + set entry_fgcolor = "#000000"; + + set border_color = "#ff9999"; + + set entrytitle_bgcolor = "#ff9933"; + + set outer_table_bgcolor = "#ffcc33"; + + set sidebar_header_bgcolor = "#ff9933"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffffcc"; + set header_footer_fgcolor = "#993333"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#ff9999"; + set link_hover_color = "#993333"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#ff9999"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#ff9999"; + set header_footer_link_hover = "#993333"; + +#NEWLAYER: flexiblesquares/tanteal +layerinfo "redist_uniq" = "flexiblesquares/tanteal"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tan and Teal"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#003333"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#cc9966"; + + set entry_bgcolor = "#ffffcc"; + set entry_fgcolor = "#000000"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#996633"; + + set outer_table_bgcolor = "#ffcc99"; + + set sidebar_header_bgcolor = "#996633"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffffcc"; + set header_footer_fgcolor = "#000000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#993333"; + set link_hover_color = "#603913"; + + set comments_link_color = "#ffffcc"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#993333"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#993333"; + set header_footer_link_hover = "#000000"; + +#NEWLAYER: flexiblesquares/gentledawn +layerinfo "redist_uniq" = "flexiblesquares/gentledawn"; +layerinfo "type" = "theme"; +layerinfo "name" = "Gentle Dawn"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#747D86"; + set page_fgcolor = "#605734"; + + set content_bgcolor = "#FCCA7D"; + + set entry_bgcolor = "#FFD3B9"; + set entry_fgcolor = "#605734"; + + set border_color = "#908350"; + + set entrytitle_bgcolor = "#BAA969"; + + set outer_table_bgcolor = "#DABD63"; + + set sidebar_header_bgcolor = "#BAA969"; + set sidebar_fgcolor = "#605734"; + + set header_footer_bgcolor = "#FFD3B9"; + set header_footer_fgcolor = "#605734"; + + + set link_color = "#7E858D"; + set link_hover_color = "#C68DA5"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#605734"; + + set sidebar_link_color = "#7E858D"; + set sidebar_link_hover = "#C68DA5"; + + set header_footer_link_color = "#7E858D"; + set header_footer_link_hover = "#C68DA5"; + +#NEWLAYER: flexiblesquares/icyblue +layerinfo "redist_uniq" = "flexiblesquares/icyblue"; +layerinfo "type" = "theme"; +layerinfo "name" = "Icy Blue"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#C6C2F8"; + set page_fgcolor = "#4F4D65"; + + set content_bgcolor = "#D3DCFC"; + + set entry_bgcolor = "#DDEFFF"; + set entry_fgcolor = "#4F4D65"; + + set border_color = "#FFFFFF"; + + set entrytitle_bgcolor = "#FFFFFF"; + set date_fgcolor = "#4F4D65"; + set subject_fgcolor = "#4F4D65"; + + + set outer_table_bgcolor = "#CED2FA"; + + set sidebar_header_bgcolor = "#FFFFFF"; + set sidebar_fgcolor = "#4F4D65"; + + set header_footer_bgcolor = "#FFFFFF"; + set header_footer_fgcolor = "#4F4D65"; + + + set link_color = "#5DABAA"; + set link_hover_color = "#779595"; + + set comments_link_color = "#5DABAA"; + set comments_link_hover = "#779595"; + + set sidebar_link_color = "#5DABAA"; + set sidebar_link_hover = "#779595"; + + set header_footer_link_color = "#5DABAA"; + set header_footer_link_hover = "#779595"; + +#NEWLAYER: flexiblesquares/chocolatemilkshake +layerinfo "redist_uniq" = "flexiblesquares/chocolatemilkshake"; +layerinfo "type" = "theme"; +layerinfo "name" = "Chocolate Milkshake"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#746E4A"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#BEA16D"; + + set entry_bgcolor = "#ECD6B2"; + set entry_fgcolor = "#000000"; + + set border_color = "#FFFFFF"; + + set entrytitle_bgcolor = "#867A52"; + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + + set outer_table_bgcolor = "#A18D5F"; + + set sidebar_header_bgcolor = "#867A52"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ECD6B2"; + set header_footer_fgcolor = "#000000"; + + + set link_color = "#867A52"; + set link_hover_color = "#790000"; + + set comments_link_color = "#ECD6B2"; + set comments_link_hover = "#790000"; + + set sidebar_link_color = "#790000"; + set sidebar_link_hover = "#ECD6B2"; + + set header_footer_link_color = "#867A52"; + set header_footer_link_hover = "#790000"; + + + +#NEWLAYER: flexiblesquares/eclipse +layerinfo "redist_uniq" = "flexiblesquares/eclipse"; +layerinfo "type" = "theme"; +layerinfo "name" = "Eclipse"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#EEA802"; + + set entry_bgcolor = "#FBE274"; + set entry_fgcolor = "#000000"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#CA5D00"; + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + + set outer_table_bgcolor = "#921800"; + + set sidebar_header_bgcolor = "#CA5D00"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#EEA802"; + set header_footer_fgcolor = "#000000"; + + + set link_color = "#790000"; + set link_hover_color = "#000000"; + + set comments_link_color = "#ECD6B2"; + set comments_link_hover = "#790000"; + + set sidebar_link_color = "#790000"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#790000"; + set header_footer_link_hover = "#ffffff"; diff --git a/local/bin/upgrading/s2layers/nebula/layout.s2 b/local/bin/upgrading/s2layers/nebula/layout.s2 new file mode 100755 index 0000000..48047c4 --- /dev/null +++ b/local/bin/upgrading/s2layers/nebula/layout.s2 @@ -0,0 +1,1690 @@ +# -*-s2-*- + + +## -- n e b u l a ! -- ###################################################### + +layerinfo type = "layout"; +layerinfo name = "Nebula"; +layerinfo redist_uniq = "nebula/layout"; + +layerinfo author_name = "jc"; +layerinfo author_email = "jc@livejournal.com"; +layerinfo des = "A simple but incredibly flexible design with sidebar, that can look as simple or as complicated as you like."; +layerinfo lang = "en"; + + +## -- p r o p e r t i e s -- ################################################ + +propgroup colors = "Colors"; +propgroup colors { + property Color col_weaker_fg { + des = "Default text color for the page"; + note = "This only really affects the calendar strip, although it is used elsewhere. Text color on content areas is more important."; + } + property Color col_weak_fg { + des = "Text color on content areas"; + } + property Color col_stronger_fg { + des = "Text color on headers"; + } + property Color col_strong_fg { + des = "Text color on menus"; + } + property Color col_neutral_fg { + des = "Text color on titles"; + } + + property Color col_cmtbarone_fg { + des = "Text color on comment bars"; + } + property Color col_cmtbartwo_fg { + des = "Text color on alternating comment bars"; + } + property Color col_cmtbarscrn_fg { + des = "Text color for screened comments"; + } + + + property Color col_entry_link { + des = "Link color in entries"; + } + property Color col_entry_vlink { + des = "Visited link color in entries"; + } + + property Color col_sidebar_link { + des = "Link color in sidebar"; + } + property Color col_sidebar_vlink { + des = "Visited link color in sidebar"; + } + + property string img_delete { noui = 1; } + property string img_screen { noui = 1; } + property string img_unscreen { noui = 1; } + property string img_freeze { noui = 1; } + property string img_unfreeze { noui = 1; } +} + +set col_weaker_fg = "#000000"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; +set col_strong_fg = "#5b4b26"; +set col_stronger_fg = "#5b4b26"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbartwo_fg = "#ffffff"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; + +propgroup backgrounds = "Backgrounds"; +propgroup backgrounds { + property Color col_weaker_bg { + des = "Default background color for the page"; + } + property Color col_weak_bg { + des = "Background color on content areas"; + } + property Color col_stronger_bg { + des = "Background color on headers"; + } + property Color col_strong_bg { + des = "Background color on menus"; + } + property Color col_neutral_bg { + des = "Background color on titles"; + } + property Color col_entry_bg { + des = "Background color on entries"; + } + property Color col_border { + des = "Color for content area borders"; + note = "Content areas affected include sidebar boxes and the mini calendar."; + } + property string background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Page texture won't be used if an image is defined."; + } + property string background_repeat { + des = "Background image repeat"; + note = "This does not affect whether your background scrolls with the page. That option is coming up next."; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string background_attachment { + des = "Should the background image scroll with the page?"; + values = "scroll|Yes|fixed|No"; + } + property string background_position { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + set background_image = ""; + set background_repeat = "repeat"; + set background_position = "center"; + set background_attachment = "scroll"; + + property string pres_txtr_bg { + des = "Texture to use for page background"; + note = "Won't be used if a background image is defined above."; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property string pres_txtr_h { + des = "Texture to use for page header"; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property string pres_txtr_c { + des = "Texture to use for main content areas"; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property Color col_cmtbarone_bg { + des = "Background color for comment bars"; + } + property Color col_cmtbartwo_bg { + des = "Background color for alternating comment bars"; + } + property Color col_cmtbarscrn_bg { + des = "Background color for screened comment bars"; + } +} + + +set col_weaker_bg = "#effe8f"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_strong_bg = "#fbe46a"; +set col_stronger_bg = "#fbe46a"; +set col_cmtbarone_bg = "#e2c956"; +set col_cmtbartwo_bg = "#afb13e"; +set col_cmtbarscrn_bg = "#fcda3e"; +set col_entry_bg = "#977e3b"; +set col_border = "#000000"; + +propgroup fonts { + property string main_font { + des = "Preferred Font"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + + property string header_font + { + des = "Font for the top header box"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string header_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property string header_font_size { noui = 1; } + + property string content_font + { + des = "Font for the content boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback { noui = 1; } + + property string subheading_font + { + des = "Font for subheadings"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string subheading_font_fallback { noui = 1; } + + property string entryheading_font + { + des = "Font for entry headings"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string entryheading_font_fallback { noui = 1; } +} + +set main_font = "Georgia"; +set main_font_fallback = "serif"; +set header_font = "Georgia"; +set header_font_fallback = "serif"; +set header_font_size = "2em"; +set content_font = "Georgia"; +set content_font_fallback = "sans-serif"; +set subheading_font = "Arial"; +set subheading_font_fallback = "sans-serif"; +set entryheading_font = "Georgia"; +set entryheading_font_fallback = "sans-serif"; + +propgroup pres = "Presentation"; +propgroup pres { + property int summary_items { + des = "Summary Items"; + note="Maximum number of items in the Page Summary list. Set to 0 to turn off the Page Summary. Set to 100 to show all available items."; + } + + property bool pres_show_entry_list { + des = "Show links to entries on page?"; + } + property string pres_page_width { + des = "Page Width"; + note = "The width of the total page content, including the sidebar."; + values = "90%|90%|80%|80%|70%|70%|60%|60%|50%|50%|40%|40%"; + } + property string pres_page_align { + des = "Page Alignment"; + values = "left|Left|center|Center|right|Right"; + } + property string pres_sidebar_width { + des = "Sidebar Width"; + note = "How much of the page width is taken up by the sidebar."; + values = "30%|30%|25%|25%|20%|20%|15%|15%"; + } + property string pres_sidebar_align { + des = "Which side of the page should the sidebar show up on?"; + values = "left|Left|right|Right"; + } + property string header_image { + des = "URL of image to be used as page header"; + example = "http://example.com/your_image.jpg"; + } + property bool pres_show_cal { + des = "Show calendar strip on journal pages?"; + } + property bool show_entry_userpic { + des = "Show entry-specific userpic next to each entry?"; + } + property bool pres_use_gradients { + des = "Use gradients when displaying entry headers and sidebar boxes?"; + } + property use comment_userpic_style; + property use use_shared_pic; + property use page_recent_items; + property use page_friends_items; +} +set show_entry_userpic = true; +set pres_show_cal = true; +set pres_sidebar_align = "left"; +set pres_show_entry_list = true; +set pres_page_width = "80%"; +set pres_sidebar_width = "20%"; +set pres_txtr_bg = "none"; +set pres_txtr_h = "none"; +set pres_txtr_c = "none"; +set pres_page_align = "center"; +set summary_items = 100; +set pres_use_gradients = true; + +propgroup text { + property string text_date_format { + des = "Date format:"; + example = "%%yyyy%%.%%mm%%.%%dd%%"; + } + property string text_time_format { + des = "Time format:"; + example = "%%HH%%:%%min%%"; + } + property string text_navigation { + des = "Navigation menu title"; + } + property string text_navigation_extra { + des = "Page-specific navigation menu title"; + example = "This page"; + } + property string page_summary_title { + des = "Page Summary menu title"; + } + property string text_entry_plural { + des = "Text to describe entries in month view"; + format = "plurals"; + example = "1 entry // # entries"; + } + + property use text_nosubject; + property use text_meta_mood; + property use text_meta_music; + property use text_noentries_day; + property use text_max_comments; + property string text_comment_from { + des = "Text to indicate when comment was posted"; + example = "at"; + maxlength = "20"; + } + property use text_comment_date; + property use text_comment_ipaddr; + property use text_comment_frozen; + property use text_reply_nocomments_header; + property use text_reply_nocomments; +} +propgroup linktext = "Link text"; +propgroup linktext { + property string text_view_memories { + des = "View memories"; + } + property string text_add_mem { + des = "Add to memories"; + } + property string text_edit_entry { + des = "Edit entry"; + } + property string text_edit_tags { + des = "Edit tags"; + } + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_permalink; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_reply_back; + property use text_comment_reply; + property use text_comment_parent; + property use text_comment_thread; + property string text_link_separator { + des = "Text or image to separate links with"; + note = "If you use a URL of an image (starting with 'http://'), Nebula will use the image as a separator. It helps to use a small image for this purpose, and your image might break if the URL contains any spaces."; + example = "&nbsp;|&nbsp; or http://www.example.com/your_image.jpg"; + } + +} +set text_date_format = "%%yyyy%%.%%mm%%.%%dd%%"; +set text_time_format = "%%HH%%:%%min%%"; +set text_view_memories = "Memories"; +set text_add_mem = "Add to Memories"; +set page_summary_title = "Summary"; +set text_entry_plural = "1 entry // # entries"; +set text_edit_entry = "Edit"; +set text_edit_tags = "Tags"; +set tags_aware = true; +set text_link_separator = "  "; +set text_navigation = "Navigation"; +set text_navigation_extra = "This page"; +set text_comment_from = ""; +set text_comment_date = "at"; + + +## -- p r o p e r t y h a n d l e r s -- ################################## + +function prop_init () { + var int entry_lightness = $*col_weaker_bg->lightness(); + var Color col_entry_bg_tint = $entry_lightness > 120 ? $*col_weaker_bg->lighter(): $*col_weaker_fg; + + # these shouldn't be limited to a The Boxer subfolder + $*img_delete = palimg_tint("boxer/delete.gif", $col_entry_bg_tint); + $*img_screen = palimg_tint("boxer/screen.gif", $col_entry_bg_tint); + $*img_unscreen = palimg_tint("boxer/unscreen.gif", $col_entry_bg_tint); + $*img_freeze = palimg_tint("boxer/freeze.gif", $col_entry_bg_tint); + $*img_unfreeze = palimg_tint("boxer/unfreeze.gif", $col_entry_bg_tint); + + # textures! lovely textures. + if ($*pres_txtr_bg != "none") { $*pres_txtr_bg = palimg_tint("textures/$*pres_txtr_bg", $*col_stronger_fg, $*col_weaker_bg); } + + var Color hfg = "#ffffff"; + if ($*pres_txtr_h != "none") { $*pres_txtr_h = palimg_tint("textures/$*pres_txtr_h", $hfg, $*col_stronger_bg); } + + if ($*pres_txtr_c != "none") { $*pres_txtr_c = palimg_tint("textures/$*pres_txtr_c", $*col_weaker_fg, $*col_weak_bg); } + +} + + +## -- s t y l e s h e e t f u n c t i o n s -- ############################ + +function appended_to_stylesheet() { + # This function intentionally left blank. Override in user layer. +} + +function print_stylesheet () { + + var string pres_sidebar_boxbg; + var string pres_minical_boxbg; + var string pres_page_margins; + + # figure out the shade applied to weekends on the MiniCal + var int minical_lightness = $*col_strong_bg->lightness(); + var Color col_minical_weekend = $minical_lightness > 120 ? $*col_strong_bg->darker(50) : $*col_strong_bg->lighter(50); + + # figuring out the widths and margins the ghetto way + var int width_page = int($*pres_page_width); + var int width_sidebar = int($*pres_sidebar_width); + var int width_content = $width_page - $width_sidebar - 5; + var int width_margin = 100 - $width_page; + + if ($*pres_page_align == "center") { + var string str_width_margin = string($width_margin / 2); + $pres_page_margins = "margin-left: $str_width_margin%;"; + } else { + var string str_width_margin = string($width_margin); + $pres_page_margins = "margin-$*pres_page_align: $str_width_margin%;"; + } + var string pres_content_width = string($width_content) + "%"; + + # death to IE + var string pres_sidebar_width_ie = string($width_sidebar - 3) + "%"; + var string pres_content_width_ie = string($width_content - 3) + "%"; + + # another ghetto method to align the sidebar properly + var string pres_sidebar_opp = $*pres_sidebar_align == "left" ? "right" : "left"; + + + # gradients! lovely gradients. + if ($*pres_use_gradients) { + var Color col_black = "#000000"; + var Color col_white = "#ffffff"; + # Let's determine some colours first + var int tmp_boxborder_lightness = $*col_border->lightness(); + var Color tmp_boxborder_avg = $tmp_boxborder_lightness > 120 ? $*col_border->darker(70) : $*col_border->lighter(70); + var string tmp_gstart = $tmp_boxborder_avg.as_string->substr(1, 6); + var string tmp_gend = $*col_strong_bg.as_string->substr(1, 6); + + # Now to generate the gradients + $pres_sidebar_boxbg = "background: url($*PALIMGROOT/shadow/t.gif/pt$tmp_gstart$tmp_gend) repeat-x;"; + $pres_minical_boxbg = "background: $*col_strong_bg url($*PALIMGROOT/shadow/b.gif/pt$tmp_gstart$tmp_gend) repeat-x scroll bottom;"; + } else { + $pres_minical_boxbg = "background-color: $*col_strong_bg;"; + } + + +""" + body { + margin: 0; + padding: 0; + font-family: $*main_font, $*main_font_fallback; + font-size: 0.75em; +"""; + if (clean_url($*background_image) != "") { + """ background-image: url('$*background_image'); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_attachment; + """; + } elseif ($*pres_txtr_bg != "none") { """ background: url($*pres_txtr_bg);"""; } +""" + background-color: $*col_weaker_bg; + color: $*col_weaker_fg; + } + #mainContainer { + width: $*pres_page_width; + $pres_page_margins + min-width: 300px; + } + #header { + padding: 0 1em; + min-height: 110px; + margin: 0 0 10px 0; +"""; + if ($*pres_txtr_h != "none") { """ background: url($*pres_txtr_h);"""; } +""" + background-color: $*col_stronger_bg; + color: $*col_stronger_fg; + } + #header h1 { + margin: 0 0 -10px 0; + padding: 15px 0; + } + #header a { + font-family: $*header_font, $*header_font_fallback; + font-size: $*header_font_size; + text-decoration: none; + color: $*col_stronger_fg; + } + #header p { + color: $*col_neutral_fg; + font-size: 18px; + font-style: italic; + margin: 0 0 0 20px; + } + #content { + float: $pres_sidebar_opp; + background-color: $*col_weak_bg; + color: $*col_weak_fg; + padding: 5px; + margin: 20px 1% 20px 1%; +"""; + if ($*pres_txtr_c != "none") { """ background: url($*pres_txtr_c);"""; } +""" + width: $pres_content_width; + voice-family: "\"}\""; + voice-family:inherit; + width: $pres_content_width_ie; + } + html>body #content { + width: $pres_content_width_ie; + } + #content p { + margin-top: 0px; + margin-bottom: 0px; + padding: 8px; + } + #sideBar { + float: $*pres_sidebar_align; + padding: 5px; + margin: 20px 1% 20px 1%; + background-color: $*col_weak_bg; + color: $*col_weak_fg; +"""; + if ($*pres_txtr_c != "none") { """background: url($*pres_txtr_c);"""; } +""" + width: $*pres_sidebar_width; + voice-family: "\"}\""; + voice-family:inherit; + width: $pres_sidebar_width_ie; + } + html>body #sideBar { + width: $pres_sidebar_width_ie; + } + #sideBarHeader { + min-height: 100px; + background-color: $*col_stronger_bg; + color: $*col_stronger_fg; +"""; + if ($*pres_txtr_h != "none") { """background: url($*pres_txtr_h);"""; } +""" + vertical-align: bottom; + margin-bottom: 10px; + } + #sideBar h4 { + color: $*col_neutral_fg; + text-transform: uppercase; + font-weight: normal; + font-family: $*subheading_font, $*subheading_font_fallback; + display: block; + text-align: center; + padding: 5px; + padding-bottom: 0; + $pres_sidebar_boxbg + } + #sideBar ul { + margin: 0 0 1em 1em; + padding: 0; + list-style-type: none; + } + .sideBarBox { + border: 2px solid $*col_border; + margin-bottom: 5px; + background-color: $*col_strong_bg; + color: $*col_strong_fg; + } + .sideBarBox a, .sideBarBox a:active { + color: $*col_sidebar_link; + } + .sideBarBox a:visited { + color: $*col_sidebar_vlink; + } + .sideBarBox h5 { + font-family: $*subheading_font, $*subheading_font_fallback; + margin: 10px 0 0 0; + } + .sideBarUpi { + margin: 0; + padding: 2px; + } + + .entry { + padding: 5px; + background-color: $*col_entry_bg; + font-family: $*content_font, $*content_font_fallback; + } + .entry a { + color: $*col_entry_link; + } + .entry a:visited { + color: $*col_entry_vlink; + } + .entry h3 { + font-family: $*entryheading_font, $*entryheading_font_fallback; + font-size: 1.5em; + padding: 3px; + margin: 10px 0; + } + .entryBar { + clear: both; + overflow: auto; + font-size: 0.9em; + } + .entryText { + margin-top: 5px; + margin-bottom: 5px; + } + .entryFooter { + padding-top: 1em; + } + .commentsInfo { + float: right; + } + form#postform textarea { + width: 100%; max-width: 99%; + } + form#postform input { + max-width: 100%; + } + + .commentBoxOne { + border: 5px solid $*col_cmtbarone_bg; + } + .commentBoxTwo { + border: 5px solid $*col_cmtbartwo_bg; + } + .commentBoxScreened { + border: 5px solid $*col_cmtbarscrn_bg; + } + .commentBoxOne .commentInfo { + background-color: $*col_cmtbarone_bg; + color: $*col_cmtbarone_fg; + } + .commentBoxTwo .commentInfo { + background-color: $*col_cmtbartwo_bg; + color: $*col_cmtbartwo_fg; + } + .commentBoxScreened .commentInfo { + background-color: $*col_cmtbarscrn_bg; + color: $*col_cmtbarscrn_fg; + } + .commentBoxOne, .commentBoxTwo, .commentBoxScreened { + background-color: $*col_weak_bg; + color: $*col_weak_fg; + border-right: none; + border-bottom: none; + width: 99%; + } + .commentBoxOne a, .commentBoxTwo a, .commentBoxScreened a { + color: $*col_entry_link; + } + .commentBoxOne a:visited, .commentBoxTwo a:visited, .commentBoxScreened a:visited { + color: $*col_entry_vlink; + } + .commentUpi { + float: left; + margin-right: 10px; + margin-bottom: 10px; + } + .commentUpi img { + border: 0; + } + .commentInfo { + width: 100%; + vertical-align: bottom; + padding-botttom: 5px; + background-color: #ccf; + } + .commentButs { + vertical-align: bottom; + text-align: right; + } + .commentText { + padding-top: 5px; + padding-left: 5px; + } + .commentLinks { + clear: both; + margin-left: 5px; + } + + #footer { + float: left; + width: """+$pres_content_width+"""px; + font-size: 0.8em; + margin-top: 10px; + margin-bottom: 10px; + } + + h2, h3, h4 { + margin-top: 0; + } + a { + color: $*col_entry_link; + text-decoration: none; + } + a:hover { + text-decoration: underline; + } + a:visited { + color: $*col_entry_vlink; + } + .userpic { + float: right; + margin-left: 5px; + margin-bottom: 5px; + } + div.entrysub h3 { + margin: 0; + } + div.MiniCalContainer { + border: 2px solid $*col_border; + width: 98%; + height: 3em; + overflow: auto; + margin-top: 10px; + margin-left: 1%; + $pres_minical_boxbg + } + .MiniCalDayPosts { + font-weight: bold; + } + td.MiniCalWeekend { + background-color: $col_minical_weekend; + } + td.MiniCalDay, td.MiniCalDayPosts { + font-family: Trebuchet, Verdana, sans-serif; + font-size: 0.95em; + color: $*col_strong_fg; + } + .MiniCalDay a, .MiniCalDay a:active, .MiniCalDayPosts a, .MiniCalDayPosts a:active { + color: $*col_sidebar_link; + } + .MiniCalDay a:visited, .MiniCalDayPosts a:visited { + color: $*col_sidebar_vlink; + } + .monthWrapper { + display: table; + border: 1px solid black; + width: 100%; + } + .monthRow { + display: table-row; + border: 1px solid black; + } + .monthCell, .monthDay { + display: table-cell; + border: 1px solid black; + padding: 3px; + } + .monthDay { + font-family: $*subheading_font, $*subheading_font_fallback; + font-size: 2em; + text-align: right; + } + #cal a { + text-decoration: none; + color: $*col_entry_link; + } + .calrow { + clear: both; + font-family: Arial, sans-serif; + } + + .calempty { + width: 24px; + font-size: 11px; + margin: 1px; + float: left; + } + .calactitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + background-color: white; + border-right: 1px solid black; + border-bottom: 1px solid black; + } + .calDayEntries { + font-size: 1.5em; + font-weight: bold; + } + .calDay, .calDayEntries, .bigday { + font-family: $*subheading_font, $*subheading_font_fallback; + text-align: center; + vertical-align: middle; + } + .bigday { + font-weight: bold; + } + .cal td { + padding: 3px; + } + .calinitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + border-right: 1px solid black; + border-bottom: 1px solid black; + } + +"""; + appended_to_stylesheet(); +} + + +## -- i m a g e l i n k s e p a r a t o r -- ############################ + +function separator() : string { + # Would do this in prop_init, except you can't use HTML in + # $* variables. Poo. + if ($*text_link_separator->starts_with("http://")) { + return " \" "; + } else { + return $*text_link_separator; + } +} + +## -- p r i n t l i n k l i s t -- ######################################## + +function linklist() : string { + var string return = ""; + var Page p = get_page(); + if (size $p.linklist <= 0) { + return ""; + } + var bool section_open = false; + $return = $return + "
    \n"; + var int count = 0; + foreach var UserLink l ($p.linklist) { + $count = $count + 1; + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + $return = $return + " \n
    \n"; + } + $return = $return + """
    \n

    $l.title

    \n
      \n"""; + $section_open = true; + } else { + if ($count == 1) { + $return = $return + """
      \n

       

      \n
        \n"""; + } + $return = $return + """
      • $l.title
      • \n"""; + } + } + } + $return = $return + "
      \n
      \n"; + return $return; +} + + +## -- p a g e s u m m a r i e s -- ######################################## + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function Page::lay_entry_nav (Entry e) : string { + + var string date = $e.time->date_format($*text_date_format); + var string time = $e.time->time_format($*text_time_format); + var string line; + var string subject = ($e.subject != "") ? " $e.subject" : """ $*text_nosubject"""; + var string j = ($.view == "friends" and $e.journal.username != $e.poster.username) ? " in $e.journal: " : ""; + var string item = ($.view == "friends" or $e.journal.username != $e.poster.username) ? "
      $date @ $time
      " + $e.poster->as_string() + "$j " : "
      $date @ $time
      "; + $line = """
    • $item $subject
    • \n"""; + + return $line; +} + +function Page::lay_print_summary () { } + +function RecentPage::lay_print_summary () { + var int count = $*summary_items; + if ($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + if($count > 0) { + $text = $text + $this->lay_entry_nav($e); + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + print $text; + } +} + +function EntryPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + $text = $this->lay_entry_nav($.entry); + $count = $count - 1; + + foreach var Comment c ($.comments) { + if($count > 0) { + var string subject = ($c.subject != "") ? $c.subject : """$*text_nosubject """; + $text = $text + """
    • $c.poster: $subject"""; + var int num = num_comments_in_thread($c.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + $text = $text + """
    • \n"""; + } + $count = $count - 1; + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + if($count != ($*summary_items - 1)) { + print $text; + } + } +} + +function DayPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + $text = $text + $this->lay_entry_nav($e); + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + print $text; + } +} + + +function MonthPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string entrytext = "1 entry // # entries"; + var string text; + foreach var MonthDay d ($.days) { + if($count > 0) { + var string day = lang_ordinal($d.day); + if ($d.has_entries) { + var string entries = get_plural_phrase($d.num_entries, "text_entry_plural"); + $text = $text + """
    • $day [$entries]
    • \n"""; + } + } + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • """; + } + print $text; + } +} + + +## -- e x t r a n a v i g a t i o n l i n k s -- ######################## + +function Page::lay_nav_links() : string[] { + var string[] ret = []; + return $ret; +} + +function RecentPage::lay_nav_links() : string[] { + var string[] ret = []; var int i = 0; + if (viewer_is_owner()) { + $ret[$i] = """Update Journal"""; $i++; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function EntryPage::lay_nav_links() : string[] { + var string[] ret; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $ret[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $ret[$i] = """$next.caption"""; + } + } + return $ret; +} + +function YearPage::lay_nav_links() : string[] { + var string[] ret; var int i = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + $ret[$i] = """$y.year\n"""; + } else { + $ret[$i] = """$y.year\n"""; + } + $i++; + } + return $ret; +} + +function MonthPage::lay_nav_links() : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """"""+$.prev_date->date_format($*lang_fmt_month_long)+""""""; $i++; } + if ($.next_url != "") { $ret[$i] = """"""+$.next_date->date_format($*lang_fmt_month_long)+""""""; $i++; } + + return $ret; +} + +function DayPage::lay_nav_links() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + + +## -- p r i n t s i d e b a r -- ########################################## + +function Page::lay_print_sidebar() { + var Page p = get_page(); + + var string userpic; + var Image up_img = $.journal.default_pic; + if (defined $up_img) { + $userpic = """
      +
      +
      +
      +
      + """; + } + var string website; + if ($.journal.website_url != "") { + $website = """
    • $.journal.website_name
    • \n"""; + } + + """ + + """; +} + + +## -- p r i n t c a l e n d a r -- ######################################## + +function print_calendar() : string { + var string calendar = ""; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """ +
      + + + """; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + var YearDay[] theDays = $w.days; + var int start = $w.pre_empty; + foreach var YearDay d ($theDays) { + $start = $start + 1; + $calendar = $calendar + "\n "; + } else { + $calendar = $calendar + """MiniCalDay">""" + $d.day->zeropad(2) + ""; + } + } + } + $calendar = $calendar + "\n \n
      $month  """ + $d.day->zeropad(2) + "
      \n
      \n"; + } + if ($calendar == "") { + return "Nothing to see here."; + } + return $calendar; +} + + +## -- p r i n t p a g e -- ################################################ + +function Page::print () +{ + var string title = $this->title(); + var string headerimg = $*header_image ? "" : ""; + + # HEAD + """\n + + + + + """; + $this->print_head(); + """ + + $title + + """; + + # BODY + """ + + +
      + """; + if ($*pres_show_cal and $this.view != "friends") { + print print_calendar(); + } + + if ($*pres_sidebar_align == "left") { + $this->lay_print_sidebar(); + } + """ + +
      + + + + """; + + $this->print_body(); + + var string[] submenu = $this->lay_nav_links(); + if (size $submenu > 0) { + "
      "; + foreach var string subitem ($submenu) { + print """$subitem  """; + } + "
      "; + } + "
      "; + + if ($*pres_sidebar_align == "right") { + $this->lay_print_sidebar(); + } +"
      "; +""" + +"""; +} + + +## -- p r i n t e n t r y -- ############################################## + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string date = $e.time->date_format($*text_date_format); + var string time = $e.time->time_format($*text_time_format); + var string entrybarstyle = ""; + var string h3style = ""; + var string link_separator = separator(); + + if ($bgcolor and $fgcolor) { + if ($e.subject->length() > 0 and $p.view == "friends" and $*pres_use_gradients) { + var Color gbg = $fgcolor->average($bgcolor); + var string gstart = $gbg.as_string->substr(1, 6); + var string gend = $bgcolor.as_string->substr(1, 6); + var string gradient = "$*PALIMGROOT/shadow/t.gif/pt" + $gstart + $gend; + $entrybarstyle = " style=\"background: url($gradient) repeat-x;\""; + $h3style = " style=\"background-color: $bgcolor; color: $fgcolor;\""; + } else { + if (not defined $bgcolor) { + $bgcolor = $*col_border; + } + } + } else { + if (not defined $bgcolor) { + $bgcolor = $*col_border; + } + } + + "\n \n
      \n
      \n"; + if (defined $e.userpic and ($*show_entry_userpic or $p.view == "friends")) { + "
      \n "; + print $e.userpic->as_string(); + "\n
      \n"; + } + if ( $e.subject ) { + " $e.subject

    \n"; + } + + " Posted $e.security "; + if ($e.poster.username != $e.journal.username) { + if ($e.journal.journal_type == "C" or $e.journal.journal_type == "S") { "by " + $e.poster->as_string(); } + if ($p.view == "friends") { " in " + $e.journal->as_string(); } + } else { + if ($p.view == "friends") { + if ($e.journal.journal_type == "Y") { + "in "; + } else { + "by "; + } + print $e.journal->as_string(); + } + } + " on $date at $time\n"; + + if ( not $hide_text ) { + # current mood, music etc + if ( size $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string key = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $key = $*text_meta_mood; + } elseif ( $k == "music" ) { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "\"\" $val"; + } + "
    \n $key: $val\n"; + } + } + # entry tags (why isn't this in $e.metadata?) + if ($e.tags) { + var int tcount = 0; + "
    Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + ""; + } + " \n
    \n "; + # entry text! + print $e.text;"\n
    \n"; + "
    \n"; + $e.comments->print(); + + var Link l = new Link; + var int c = 0; + var string ca = ""; + foreach var string ls ($e.link_keyseq) { + $l = $e->get_link($ls); + if (defined $l) { + if ($c > 0) { print $link_separator; } + # Need a switch/case statement here, or core + # string properties for the following link text + if ($ls == "mem_add") { $ca = $*text_add_mem; } + elseif ($ls == "edit_tags") { $ca = $*text_edit_tags; } + elseif ($ls == "edit_entry") { $ca = $*text_edit_entry; } + else { $ca = $l.caption; } + """$ca """; + $c++; + } + } + "
    "; + + } + "
    "; +} + +function Page::print_entry ( Entry e ) +{ + print_entry( $this, $e, null Color, null Color, false ); +} + +function FriendsPage::print_entry ( Entry e ) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry( $this, $e, $f.bgcolor, $f.fgcolor, false ); +} + +function RecentPage::print_body { + foreach var Entry e ( $.entries ) { + $this->print_entry( $e ); + } +} + +function FriendsPage::print_body +{ + foreach var Entry e ( $.entries ) { + $this->print_entry( $e ); + } +} + +## -- p r i n t c o m m e n t i n f o -- ################################ + +function CommentInfo::print () +{ + var Page p = get_page(); + var string link_separator = separator(); + + "
    \n "; + if ( not $.enabled ) { + "$*text_permalink"; + "\n
    "; + return; + } + if ( $.count > 0 or $.screened and $p.view != "entry") { + $this->print_readlink(); + } else { + "$*text_permalink"; + } + "$link_separator"; $this->print_postlink(); + "\n "; +} + + +## -- p r i n t e n t r y p a g e -- #################################### + +function EntryPage::print_body () +{ + +# disabled until someone can figure out why these guys aren't working +# set_handler("unscreen_comment_#", [ [ "set_class", "cmtbox#", "commentBoxOne", ], ]); +# set_handler("screen_comment_#", [ [ "set_class", "cmtbox#", "commentBoxScreened", ], ]); + + print_entry ( $this, $.entry, null Color, null Color, $.viewing_thread ); + if ( $.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + print "

    Comments:


    "; + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + if ( $.comment_pages.total_subitems > 0 ) { + $.comment_pages->print(); + $this->print_comments( $.comments ); + } + if ($this.multiform_on) { + print "

    Mass Action:

    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "

    "; + } + "
    "; + } +} + + +## -- p r i n t e n t r y c o m m e n t -- ############################## + +function EntryPage::print_comment ( Comment c ) +{ + var string userpic; + var string boxclass = ""; + var string boxheight = ""; + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string sub_icon = defined $c.subject_icon ? $c.subject_icon->as_string() : "" ; + + if ( $c.screened ) { + $boxclass = "commentBoxScreened"; + } else { + $boxclass = $c.depth % 2 ? "commentBoxOne" : "commentBoxTwo"; + } + + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ( $*comment_userpic_style == "small" ) { + $w = $w / 2; + $h = $h / 2; + } + $userpic = "
    \"$c.poster.name\"
    "; + } + """ + +
    + $userpic + "; + if ( $c.subject != "" ) { print "

    $c.subject $c.subject_icon

    "; } + "
    $c.text
    "; + "
    "; + if ( $this.multiform_on ) { + "
    "; + $c->print_multiform_check(); + "
    "; + } + if ( $c.frozen ) { + print $*text_comment_frozen + " :: "; + } else { + "($*text_comment_reply) "; + } + if ( $c.parent_url != "" ) { + "($*text_comment_parent) "; + } + if ( $c.thread_url != "" ) { + "($*text_comment_thread) "; + } + "
    \n\n"; +} + + +## -- p r i n t r e p l y p a g e -- #################################### + +function ReplyPage::print_body () +{ + if ( not $.entry.comments.enabled ) { + "$*text_reply_nocomments_header
    $*text_reply_nocomments"; + return; + } + + var string time = $.replyto.time->time_format($*text_time_format); + var string date = $.replyto.time->date_format($*text_date_format); + """
    """; + if (defined $.replyto.userpic) { + """
    """; + } + if ( $.replyto.subject ) { print "

    $.replyto.subject

    "; } + "Posted by "; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + " on $date at $time
    "; + "
    "; + print $.replyto.text + "
    "; + """

    "; + """
    """; + var string what = $.replyto.permalink_url == $.entry.permalink_url ? "entry" : "comment" ; + "

    Reply to this $what:

    "; + $.form->print(); + "
    "; +} + + +## -- p r i n t m o n t h p a g e -- #################################### + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
    $select
    + """; + "
    "; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + + +
    + +
    +
    + """; + $d->print_subjectlist(); + """ +
    +
    +
    + + """; + } + } + "
    "; +} + + +## -- p r i n t y e a r p a g e -- ###################################### + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + ""; + if ($d.num_entries > 0) { + var string num = string($d.num_entries); + """ + + """; + } else { + """
    $day
    """; + } + """ + + """; + } + """ + + """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
    +

    + """; + + print $m->month_format(); + + """ +

    + +   $*text_view_month   :: ^

    +
    + + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
    $*lang_dayname_short[$d]
    +
    +

    + """; + +} + + +function YearPage::print_body { + """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
    """; +} + + +## -- p r i n t d a y p a g e -- ######################################## + +function DayPage::print_body() { + """

    """; + print $.date->date_format("long"); "


    "; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } else { + """
    $*text_noentries_day
    """; + } +} + +## -- t h e e n d ! -- #################################################### \ No newline at end of file diff --git a/local/bin/upgrading/s2layers/nebula/themes.s2 b/local/bin/upgrading/s2layers/nebula/themes.s2 new file mode 100755 index 0000000..f3157e4 --- /dev/null +++ b/local/bin/upgrading/s2layers/nebula/themes.s2 @@ -0,0 +1,269 @@ +#NEWLAYER: nebula/ohblue +layerinfo "type" = "theme"; +layerinfo "name" = "Oh blue"; +layerinfo "redist_uniq" = "nebula/ohblue"; + +set col_entry_bg = "#44366d"; +set col_stronger_fg = "#1b0c66"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_cmtbarone_bg = "#9f9cfd"; +set col_neutral_fg = "#2f2e55"; +set col_cmtbartwo_bg = "#adb3e5"; +set col_sidebar_link = "#2f2e55"; +set col_weaker_bg = "#d9dcff"; +set col_strong_fg = "#2f2e55"; +set col_neutral_bg = "#ab5c90"; +set col_cmtbarscrn_fg = "#1b0c66"; +set col_stronger_bg = "#b8bef8"; +set col_cmtbartwo_fg = "#000000"; +set col_weak_bg = "#404380"; +set col_cmtbarone_fg = "#000000"; +set col_weaker_fg = "#04025a"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#7e7cb1"; +set col_weak_fg = "#9ba2e8"; +set col_sidebar_vlink = "#1f1d46"; + +#NEWLAYER: nebula/ohgreen +layerinfo "type" = "theme"; +layerinfo "name" = "Oh green"; +layerinfo "redist_uniq" = "nebula/ohgreen"; + +set col_entry_bg = "#4ca65b"; +set col_stronger_fg = "#12661a"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_cmtbarone_bg = "#bffdbe"; +set col_neutral_fg = "#12661a"; +set col_cmtbartwo_bg = "#72e580"; +set col_sidebar_link = "#12661a"; +set col_weaker_bg = "#0d6315"; +set col_strong_fg = "#12661a"; +set col_neutral_bg = "#000000"; +set col_cmtbarscrn_fg = "#000000"; +set col_stronger_bg = "#9df89f"; +set col_cmtbartwo_fg = "#000000"; +set col_weak_bg = "#08390b"; +set col_cmtbarone_fg = "#000000"; +set col_weaker_fg = "#0e2a05"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#4f9f58"; +set col_weak_fg = "#08390b"; +set col_sidebar_vlink = "#12661a"; + +#NEWLAYER: nebula/ohpurple +layerinfo "type" = "theme"; +layerinfo "name" = "Oh purple"; +layerinfo "redist_uniq" = "nebula/ohpurple"; + +set col_cmtbartwo_bg = "#D89EE5"; +set col_cmtbarscrn_fg = "#000000"; +set col_entry_bg = "#eebfed"; +set col_weaker_bg = "#eebfed"; +set col_stronger_bg = "#efd5f8"; +set col_cmtbartwo_fg = "#000000"; +set col_sidebar_link = "#592b7d"; +set col_strong_bg = "#9c6e9f"; +set col_cmtbarone_bg = "#EECCFD"; +set col_stronger_fg = "#c459d1"; +set col_weaker_fg = "#0e2a05"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#2d1e41"; +set col_strong_fg = "#614a62"; +set col_weak_bg = "#614a62"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#000000"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_weak_fg = "#a1319a"; +set col_neutral_fg = "#614a62"; + +#NEWLAYER: nebula/ohblack +layerinfo "type" = "theme"; +layerinfo "name" = "Oh black"; +layerinfo "redist_uniq" = "nebula/ohblack"; + +set col_cmtbartwo_bg = "#ffffff"; +set col_cmtbarscrn_fg = "#000000"; +set col_entry_bg = "#ffffff"; +set col_weaker_bg = "#ffffff"; +set col_stronger_bg = "#ffffff"; +set col_cmtbartwo_fg = "#000000"; +set col_sidebar_link = "#606060"; +set col_strong_bg = "#ffffff"; +set col_cmtbarone_bg = "#ffffff"; +set col_stronger_fg = "#000000"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#606060"; +set col_entry_vlink = "#606060"; +set col_sidebar_vlink = "#606060"; +set col_strong_fg = "#000000"; +set col_weak_bg = "#ffffff"; +set col_neutral_bg = "#ffffff"; +set col_cmtbarone_fg = "#000000"; +set col_cmtbarscrn_bg = "#ffffff"; +set col_weak_fg = "#000000"; +set col_neutral_fg = "#000000"; + +#NEWLAYER: nebula/ohcontrast +layerinfo "type" = "theme"; +layerinfo "name" = "Oh contrast"; +layerinfo "redist_uniq" = "nebula/ohcontrast"; + +set col_cmtbartwo_bg = "#000000"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#000000"; +set col_weaker_bg = "#000000"; +set col_stronger_bg = "#000000"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#c0c0c0"; +set col_strong_bg = "#000000"; +set col_cmtbarone_bg = "#000000"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#c0c0c0"; +set col_entry_vlink = "#c0c0c0"; +set col_sidebar_vlink = "#c0c0c0"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#000000"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#000000"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#ffffff"; + +#NEWLAYER: nebula/ohbedtime +layerinfo "type" = "theme"; +layerinfo "name" = "Oh bed time"; +layerinfo "redist_uniq" = "nebula/ohbedtime"; + +set col_cmtbartwo_bg = "#5c60b6"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#ffffff"; +set col_weaker_bg = "#5e5b7d"; +set col_stronger_bg = "#8381da"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#8381da"; +set col_cmtbarone_bg = "#605f9a"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#ffffff"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#879afa"; +set col_weak_fg = "#3c3c60"; +set col_neutral_fg = "#080255"; + +#NEWLAYER: nebula/ohgreenywhite +layerinfo "type" = "theme"; +layerinfo "name" = "Oh greeny white"; +layerinfo "redist_uniq" = "nebula/ohgreenywhite"; + +set col_entry_bg = "#ffffff"; +set col_stronger_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#93f390"; +set col_cmtbarone_bg = "#7fe278"; +set col_neutral_fg = "#550301"; +set col_cmtbartwo_bg = "#4a8f41"; +set col_sidebar_link = "#000000"; +set col_weaker_bg = "#546847"; +set col_strong_fg = "#ffffff"; +set col_neutral_bg = "#000000"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_stronger_bg = "#69ac59"; +set col_cmtbartwo_fg = "#ffffff"; +set col_weak_bg = "#ffffff"; +set col_cmtbarone_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_strong_bg = "#69ac59"; +set col_weak_fg = "#366030"; +set col_sidebar_vlink = "#000000"; + +#NEWLAYER: nebula/ohchocchip +layerinfo "type" = "theme"; +layerinfo "name" = "Oh choc chip"; +layerinfo "redist_uniq" = "nebula/ohchocchip"; + +set col_cmtbartwo_bg = "#4A8F41"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#977e3b"; +set col_weaker_bg = "#546847"; +set col_stronger_bg = "#69ac59"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#69ac59"; +set col_cmtbarone_bg = "#7FE278"; +set col_stronger_fg = "#5b4b26"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#5b4b26"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#93F390"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; + +#NEWLAYER: nebula/ohcoffee +layerinfo "type" = "theme"; +layerinfo "name" = "Oh coffee"; +layerinfo "redist_uniq" = "nebula/ohcoffee"; + +set col_cmtbartwo_bg = "#AFB13E"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#977e3b"; +set col_weaker_bg = "#effe8f"; +set col_stronger_bg = "#fbe46a"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#fbe46a"; +set col_cmtbarone_bg = "#E2C956"; +set col_stronger_fg = "#5b4b26"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#5b4b26"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#FCDA3E"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; + +#NEWLAYER: nebula/ohred +layerinfo "type" = "theme"; +layerinfo "name" = "Oh red"; +layerinfo "redist_uniq" = "nebula/ohred"; + +set col_cmtbartwo_bg = "#983035"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_entry_bg = "#d90d12"; +set col_weaker_bg = "#fe0410"; +set col_stronger_bg = "#dd6568"; +set col_cmtbartwo_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_strong_bg = "#dd6568"; +set col_cmtbarone_bg = "#d25c64"; +set col_stronger_fg = "#ffffff"; +set col_weaker_fg = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; +set col_strong_fg = "#ffffff"; +set col_weak_bg = "#bc0811"; +set col_neutral_bg = "#000000"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbarscrn_bg = "#D38086"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; diff --git a/local/bin/upgrading/s2layers/opal/layout.s2 b/local/bin/upgrading/s2layers/opal/layout.s2 new file mode 100755 index 0000000..fc6f7d9 --- /dev/null +++ b/local/bin/upgrading/s2layers/opal/layout.s2 @@ -0,0 +1,1625 @@ +# -*-s2-*- +layerinfo type = "layout"; +layerinfo name = "Opal (Libra OSWD)"; +layerinfo lang = "en"; + +layerinfo author_name = "Ported by Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo des = "Based on the Libra and Pasilda design available from Open Source Web Designs. Originally written by whompy."; +layerinfo redist_uniq = "opal/layout"; +layerinfo previews = "opal/opal.jpg"; + + + +################################################################################ +# +# Properties +# + + +propgroup prez = "Presentation"; +propgroup prez { + + property use font_base; + property use font_fallback; + property string static_font_size { noui = 1; } + property string static_font_measurement { noui = 1; } + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + + property bool show_entry_userpic { + des = "Always display userpic?"; + } + + property int summary_items { + des = "Summary Items"; + note="Maximum number of items in the Page Summary list. Set to 0 to turn off the Page Summary. Set to 100 to show all available items."; + } + + property bool use_count { + noui=1; + } + + set static_font_size = "12"; + set static_font_measurement = "px"; + set summary_items = 100; + set show_entry_userpic = false; + set font_fallback = "sans-serif"; +} + + +propgroup colors = "Colors"; + +propgroup colors { + property Color color_bg { + des = "Background Color"; + } + + property Color color_bg_font { + des = "Background Font Color"; + note = "The color of any font appearing on the background color."; + } + + property Color color_med { + des = "Page Holder Background"; + note = "This is the background of the main body, but within the outer borders."; + } + + property Color color_med_font { + des = "Page Holder Font Color"; + note="The color of the font appearing on the Page Holder Background color."; + } + + property Color color_fg { + des = "Content Background Color"; + note = "This is the background to the main content where the entries and side elements are."; + } + + property Color color_fg_font { + des = "Content Font Color"; + note = "The color of the font that appears on in the main Content area."; + } + + property Color color_link { + des = "Link Color"; + } + + property Color color_visited { + des = "Visited Link Color"; + } + + set color_bg = "#2d3851"; + set color_bg_font = "#ffffff"; + set color_med = "#7C8AA4"; + set color_med_font = "#e9f2fc"; + set color_fg = "#BFC4CB"; + set color_fg_font = "#333333"; +} + +propgroup text = "Text"; +propgroup text { + + property string free_text_header { + des = "Free Text Header"; + } + + property string free_text_text { + des = "Free Text Text"; + cols = 30; + rows = 10; + } + + property string links_header { + des = "Links Header"; + } + + property string page_summary_title { + des = "Page Summary Header"; + } + + property use text_view_userinfo; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property string text_forward { + des = "Text to show in a link to skip forward through entries"; + } + property string text_back { + des = "Text to show in a link to skip backward through entries"; + } + property use text_read_comments; + property use text_read_comments_friends; + property use text_post_comment; + property use text_post_comment_friends; + property use text_comment_reply; + property use text_reply_back; + property use text_nosubject; + property use text_noentries_day; + property use text_meta_music; + property use text_meta_mood; + + set page_summary_title = "Page Summary"; + set links_header = "Links"; + set free_text_header = "About this journal"; + set free_text_text = ""; + set text_back = "Back"; + set text_forward = "Forward"; +} + +set tags_aware = true; + + +################################################################################ +# +# Prop Init +# + +function prop_init () { + if($*color_bg.as_string == "") { $*color_bg = "#000000"; } + if($*color_fg.as_string == "") { $*color_fg = "#000000"; } + if($*color_fg_font.as_string == "") { $*color_fg_font = "#000000"; } +} + + +################################################################################ +# +# Stylesheet +# + +function getAltColor (Color color, string dir, int num) : Color { + var int lt = $color->lightness(); + if($dir == "light") { + if($lt > 200) { + $color = $color->darker($num); + } else { + $color = $color->lighter($num); + } + } elseif($dir == "dark") { + if($lt < 55) { + $color = $color->lighter($num); + } else { + $color = $color->darker($num); + } + } + return $color; +} + +function print_stylesheet () { + + + var Color color_bg_lt = getAltColor($*color_bg, "light", 30); + var Color color_fg_dk = getAltColor($*color_fg, "dark", 20); + var Color color_fg_dk_font = getAltColor($*color_fg_font, "dark", 20); + var Color color_divider = getAltColor($color_fg_dk, "dark", 30); + var Color color_fg_dk_dk_font = getAltColor($color_fg_dk, "dark", 50); + var Color color_border = getAltColor($*color_bg, "light", 90); + var string base = ($*font_base != "") ? "$*font_base, " : ""; + + """ + body { + font-family: $base $*font_fallback; + background-color: $*color_bg; + margin: 10px; + } + + .border4 { border: 1px solid $*color_bg; } + .border3 { border: 1px solid $*color_fg; } + .border2 { border: 2px solid $color_border; } + + """; + if($*color_link.as_string != "") { + """ + A { color: $*color_link; } + """; + } + + if($*color_visited.as_string != "") { + """ + A:Visited { color: $*color_visited; } + """; + } + """ + #bodycontent { background-color: $*color_med; border: 1px solid $*color_bg; padding: 3px; } + + #headerinfo { + background-color: $*color_bg; + color: $*color_bg_font; + text-align: right; + font-size: 10px; + padding: 2px; + margin-top: 1px; + } + #header { color: $*color_med_font; } + #header h3 { font-weight: normal; } + #userpic { float: right; } + + .userpic2 { + float: right; + text-align: right; + margin-top: 2px; + margin-right: 3px; + } + + #nav { + white-space: nowrap; + margin-bottom: 10px; + font-size: $*static_font_size$*static_font_measurement; + } + + #nav A { + border: 1px solid $*color_bg; + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + padding-bottom: 2px; + height: 20px; + text-decoration: none; + color: $*color_bg_font; + background-color: $color_bg_lt; + } + + #nav A:Hover { background-color: $*color_bg; } + + #content { + background-color: $*color_fg; + border: 1px solid $color_fg_dk; + padding: 4px; + } + + .columncontent { + background-color: $color_bg_lt; + border: 1px solid $*color_bg; + padding: 3px; + width: 200px; + font-size: $*static_font_size$*static_font_measurement; + color: $*color_bg_font; + } + + .columnitem { + background-color: $color_fg_dk; + padding: 3px; + margin-top: 5px; + color: $*color_fg_font; + border-top: 1px solid $color_divider; + border-bottom: 1px solid $color_divider; + overflow: hidden; + } + + .entries { color: $*color_fg_font; } + + .entrydivider { + border-top: 1px solid $color_divider; + border-bottom: 1px solid $*color_fg; + } + + .minicomment { + background-color: $color_fg_dk; + padding: 4px; + color: $*color_fg_font; + border: 1px solid $*color_fg; + font-size: $*static_font_size$*static_font_measurement; + } + + .minicommentholder { border: 1px solid $color_divider; } + + .entryinfo { + background-color: $color_fg_dk; + font-size: $*static_font_size$*static_font_measurement; + padding: 4px; + color: $*color_fg_font; + } + + .postedby { + background-color: $color_fg_dk; + padding: 6px; + font-size: $*static_font_size$*static_font_measurement; + } + + .entrylinks { + border-bottom: 1px solid $*color_fg; + background-color: $color_fg_dk; + padding-top: 4px; + padding-bottom: 4px; + font-size: $*static_font_size$*static_font_measurement; + } + + .entrylinks A { + text-decoration: none; + padding-top: 4px; + padding-bottom: 4px; + white-space: nowrap; + color: $*color_fg_font; + border-right: 1px solid $*color_fg; + } + + .entrylinks A:Hover { + background-color: $*color_fg; + } + + .messageholder { + border: 1px solid $*color_bg;; + margin-bottom: 5px; + margin-top: 5px; + } + + .systemmessage { + background-color: $color_bg_lt; + color: $*color_bg_font; + border: 1px solid $color_border; + font-size: $*static_font_size$*static_font_measurement; + } + + .systemtext { + font-weight: normal; + padding-left: 10px; + padding-right: 10px; + } + + .systemmessage A { + text-decoration: none; + padding-left: 10px; + padding-right: 10px; + color: $*color_bg_font; + padding-top: 4px; + padding-bottom: 4px; + } + + .systemmessage A:Hover { + background-color: $*color_bg; + } + + .systemmessage input, .systemmessage textarea, .systemmessage select { + background-color: $*color_fg; + color: $*color_fg_font; + } + + .systemmessage TD { + padding: 4px; + font-size: $*static_font_size$*static_font_measurement; + color: $*color_bg_font; + } + + .entry { margin-bottom: 30px; } + .entrytext { margin: 10px; } + .subject { font-weight: bold; } + + .meta { + font-size: $*static_font_size$*static_font_measurement; + padding: 4px; + } + + .meta A { + text-decoration: none; + color: $*color_link; + } + + .systemmessage A:Hover { + background-color: $*color_bg; + } + + #sidecolumn TD { color: $*color_bg_font; } + + #sidecolumn A { + text-decoration: none; + color: $*color_fg_font; + } + + .sidetd { + width: 200px; + } + + .backtop { + text-align: right; + } + + .backtop A { + color: $*color_fg_font; + font-size: $*static_font_size$*static_font_measurement; + text-decoration: none; + padding-bottom: 1px; + } + + #cal A { + text-decoration: none; + color: $*color_fg_font; + } + + .calrow { + clear: both; + font-family: Arial, sans-serif; + } + + .calempty { + width: 24px; + font-size: 11px; + margin: 1px; + float: left; + } + + .calactitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + background-color: $color_fg_dk; + border-right: 1px solid $color_bg_lt; + border-bottom: 1px solid $color_bg_lt; + } + + .calinitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + border-right: 1px solid $color_fg_dk; + border-bottom: 1px solid $color_fg_dk; + } + + .friendcolor { + width: 10px; + height: 10px; + border: 2px solid $*color_fg; + } + + .multiform { + font-weight: bold; + } + + .ip { + color: $color_fg_dk_dk_font; + } + + .friendname { + padding: 4px; + text-decoration: none; + border-left: 1px solid $*color_fg; + border-right: 1px solid $*color_fg; + } + + .bigday { + font-size: 2em; + color: $color_fg_dk; + float: left; + font-weight: bolder; + } + + .notablemessage { + padding: 4px; + } + + """; +} + + + +################################################################################ +# +# Global functions +# + +function generateDots (string un) : string { + var string dots; + if($un != "") { + foreach var string s ($un) { + if($s == "a" or $s == "c" or $s == "e" or $s == "f" or $s == "h" or $s == "k" or $s == "m" or $s == "n" or $s == "p" or $s == "r" or $s == "t" or $s == "v" or $s == "x" or $s == "z") { + $dots = $dots + ":"; + } elseif($s == " ") { + $dots = $dots + " "; + } else { + $dots = $dots + "."; + } + } + } + return $dots; +} + + + + +function print_box (string header, string text) { + """ + +
    +
    +
    +
    + """; + print safe """$header"""; + print safe """$text"""; + + """ +
    +
    +
    +
    +
    + """; + +} + +function box_item (string text) : string { + return """
    $text
    \n"""; +} + + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + + +################################################################################ +# +# Layout specific functions +# + +function Page::lay_print_userpic() { + if(defined $.journal.default_pic) { + """ +
    $.journal.name
    + """; + } +} + +function Page::lay_print_username () { + + var string dots = generateDots($.global_title); + + """ +
    + $.journal.username
    $dots +
    + """; +} + +function Page::lay_print_header () { + var string title = $this->title(); + """ + + """; +} + +function Page::lay_print_freetext () { + if($*free_text_text != "") { + var string text = box_item($*free_text_text); + print_box($*free_text_header, $text); + } +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var string links; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + $links = $links + """
    $l.title
    """; + } else { + $links = $links + box_item("""$l.title"""); + } + } + } + + print_box($*links_header, $links); +} + + +function Page::lay_print_calendar () { + var YearMonth m = $this->get_latest_month(); + var string mon = $m->month_format(); + var string text; + $text = """ + """; + foreach var YearWeek w ($m.weeks) { + $text = $text + """ + """; + if($w.pre_empty > 0) { + foreach var int empty (1..$w.pre_empty) { + $text = $text + """ + """; + } + } + foreach var YearDay d ($w.days) { + if($d.num_entries > 0) { + $text = $text + """ + """; + } else { + $text = $text + """ + """; + } + } + $text = $text + "\n"; + } + $text = $text + "
     $d.day$d.day
    "; + print_box($mon, $text); +} + + +function Page::lay_entry_nav (Entry e) : string { + + var string line; + var string date; + if($e.new_day) { + $date = $e.time->date_format("short"); + } + var string time = $e.time->time_format(); + var string subject = ($e.subject != "") ? " :: $e.subject" : """ :: $*text_nosubject"""; + var string j = ($.view == "friends" and $e.journal.username != $e.poster.username) ? " : $e.journal " : ""; + var string item = ($.view == "friends" or $e.journal.username != $e.poster.username) ? $e.poster->as_string() + """$j """ : """$date $time"""; + $line = """"""; + + return $line; +} + +function Page::lay_print_summary () { + #blank because there's shouldn't be a box if there's nothing specific about the page. +} + + +function RecentPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + if($count > 0) { + $text = $text + $this->lay_entry_nav($e); + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function EntryPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + $text = $this->lay_entry_nav($.entry); + $count = $count - 1; + + foreach var Comment c ($.comments) { + if($count > 0) { + var string subject = ($c.subject != "") ? $c.subject : """$*text_nosubject """; + $text = $text + """
    $c.poster :: $subject"""; + var int num = num_comments_in_thread($c.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + $text = $text + """
    """; + } + $count = $count - 1; + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + if($count != ($*summary_items - 1)) { + print_box($*page_summary_title, $text); + } + } +} + +function YearPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + var int num_entries; + foreach var YearMonth m ($.months) { + if($count > 0) { + var string mon = $m->month_format(); + if($m.has_entries) { + $num_entries = 0; + foreach var YearWeek w ($m.weeks) { + foreach var YearDay d ($w.days) { + $num_entries = $num_entries + $d.num_entries; + } + } + $text = $text + """"""; + } + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } + +} + +function MonthPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var MonthDay d ($.days) { + if($count > 0) { + var string day = lang_ordinal($d.day); + if ($d.has_entries) { + $text = $text + """"""; + } + } + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function DayPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + $text = $text + $this->lay_entry_nav($e); + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    +$count more
    """; + } + print_box($*page_summary_title, $text); + } +} + +function Page::lay_print_subnav () { + # +} + +function RecentPage::lay_print_subnav () { + var string back; + if($.nav.backward_url != "") { + $back = """$*text_back"""; + } else { + $back = " "; + } + var string forward; + if($.nav.forward_url != "") { + $forward = """$*text_forward"""; + } else { + $forward = " "; + } + + var int start = $.nav.skip; + var int end = $.nav.skip + size $.entries; + var string text = "Viewing $start - $end"; + """ +
    + + + + + + +
    $back$text$forward
    +
    + """; +} + +function DayPage::lay_print_subnav () { + var string back; + if($.prev_url != "") { + $back = """$*text_back"""; + } else { + $back = " "; + } + var string forward; + if($.next_url != "") { + $forward = """$*text_forward"""; + } else { + $forward = " "; + } + + var string text = $.date->date_format("long"); + + """ +
    + + + + + + +
    $back$text$forward
    +
    + """; + +} + + +function Page::lay_print_sidebar () { + $this->lay_print_summary(); + $this->print_linklist(); + $this->lay_print_freetext(); + $this->lay_print_calendar(); +} + + +function Page::lay_make_username(Entry e) { + """ + +
    + """; +} + +function FriendsPage::lay_make_username (Entry e) { + var Friend f = $.friends{$e.journal.username}; + var string url = $e.poster->base_url(); + """ + +
    + """; +} + +function Page::print_entry (Entry e) { + + print """"""; + var string time = $e.time->time_format(); + var string date = $e.time->date_format(); + var string security; + if ($e.security != "") { + $security = """"""; + } + + var UserLite name; + var string pname; + + var bool show_name = ($.view == "friends" or $e.poster.username != $.journal.username or $.view == "entry") ? true : false; + var bool show_pic = (defined $e.userpic and ($.view == "friends" or $*show_entry_userpic or $e.poster.username != $e.journal.username or $.view == "entry")) ? true : false; + + + + + """ +
    +
    + """; + if($show_pic) { + """ +
    + $e.poster.name [userpic] +
    + """; + } + + if($show_name) { + $this->lay_make_username($e); + } + """ + +
    + +
    +
    $e.subject
    +

    $e.text

    + """; + + $e->print_metadata(); + + """ +
    +
    + + + """; +} + + + +function CommentInfo::print() { + if ($.enabled) { + $this->print_postlink(); + if ($.count > 0 or $.screened) { + $this->print_readlink(); + } + } +} + +function CommentInfo::print_postlink() { + var Page p = get_page(); + "   "+($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment)+"   "; +} + +function CommentInfo::print_readlink { + var Page p = get_page(); + "   "+ + get_plural_phrase($.count, $p.view == "friends" ? + "text_read_comments_friends" : "text_read_comments")+ + "   "; +} + + +################################################################################ +# +# EntryPage and Comments +# + +function EntryPage::print_body() { + """
    """; + $this->print_entry($.entry); + if ($this.multiform_on) { + $this->print_multiform_start(); + } + + if ($.entry.comments.count > 0) { + """ +
    Comments
    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($.entry.comments.enabled) { + $this->print_comments($.comments); + } + + + if ($.entry.comments.count > 0) { + """ +
    +
    +
    + """; + + $.entry.comments->print(); + + """ +
    +
    +
    + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($this.multiform_on and ($.entry.comments.count > 0)) { + """ +
    +
    +
    +
    + """; + $this->print_multiform_actionline(); + """ +
    +
    +
    +
    + """; + $this->print_multiform_end(); + } + """
    """; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + } +} + +function EntryPage::print_comment(Comment c) { + + var string datetime; + $datetime = $c.time->date_format()+", " + $c.time->time_format(); + + + var string parent; + var string thread; + if($c.parent_url != "") { + $parent = """   $*text_comment_parent   """; + } + if($c.thread_url != "") { + $thread = """   $*text_comment_thread   """; + } + + var string subjecticon; + if (defined $c.subject_icon) { + $subjecticon = """"""; + } + + var string ip; + if ($c.metadata{"poster_ip"}) { + $ip = """   """ + $c.metadata{"poster_ip"}; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + + var string pic; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $pic = """
    """; + } + + var string indent = ($c.depth - 1) * 25 + "px"; + + """ +
    + + $pic +
    +
    +
    $poster $ip
    +
    + +
    + + """; + + if ($.multiform_on) { + """ +
    + """; + } + + var string replyurl; + if ($c.frozen) { + $replyurl = """   $*text_comment_frozen   """; + } else { + $replyurl = """   $*text_comment_reply   """; + } + + """ + +
    +
    $c.subject
    +

    $c.text

    +
    + """; + + + if ((size $c.replies) > 0 and $c.replies[0].full == false) { + """
    \n"""; + $this->print_comments($c.replies); + "
    \n"; + } + + """ +
    + +
    + """; + + if ((size $c.replies) > 0 and $c.replies[0].full == true) { + $this->print_comments($c.replies); + } + +} + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : """$*text_nosubject"""; + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
    $poster - $subj
    + """; + $this->print_comments($c.replies); +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ +
    + """; + print lang_page_of_pages($.current, $.total); + " — "; + foreach var int i (1..$.total) { + if ($i == $.current) { """[$i]"""; + + } else { + var string url_of = $this->url_of($i); + "[$i]"; + } + } + """
    """; +} + +################################################################################ +# +# ReplyPage +# + +function ReplyPage::print_body() { + + var EntryLite e = $.replyto; + var string poster = defined $e.poster ? $e.poster->as_string() : "(Anonymous)"; + var string datetime; + var string time = $e.time->time_format(); + var string date = $e.time->date_format(); + + var UserLite name; + if(defined $e.userpic and $*comment_userpic_style != "off") { + $name = $e.poster; + """
    """; + if (defined $e.userpic or (defined $e.userpic and $.view == "entry" and $*show_entry_userpic)) { + """"""; + } + """
    """; + } + """ +
    +
    + +
    + +
    + + """; + + """ +
    +
    $e.subject
    +

    $e.text

    +
    + +
    + """; + $.form->print(); + """ +
    + """; +} + + +function Entry::print_metadata() { + var string caption; + var string val; + var Image i; + if ($this.tags) { + """
    """; + print $this->get_tags_text(); + "
    "; + } + if (size $.metadata == 0) { return; } + foreach var string k ($.metadata) { + $caption = $k; + $val = $.metadata{$k}; + if ($k == "music") { + $caption = $*text_meta_music; + } + elseif ($k == "mood") { + $caption = $*text_meta_mood; + if (defined $.mood_icon) { + $i = $.mood_icon; + $val = """$val $val"""; + } + } + println """
    $caption: $val
    """; + } +} + + +################################################################################ +# +# RecentPage +# + +function RecentPage::print_body () { + """ + +
    + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """ +
    + """; +} + +################################################################################ +# +# YearPage +# + + +function YearPage::print_body { + $this->print_year_links(); + """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
    """; +} + +function YearPage::print_year_links() { + """
    """; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """$y.year"""; + } else { + """   $y.year   """; + } + } + """
    """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
    +
    + +
    + +
    + + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
    $*lang_dayname_short[$d]
    +
    +
    + + """; + +} + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + """ + +
    $day
    + """; + if ($d.num_entries > 0) { + var string num = $d.num_entries < 10 ? " " + string($d.num_entries) : string($d.num_entries); + """ + + """; + } + """ + + """; + } + """ + + """; +} + + + + +################################################################################ +# +# MonthPage +# + + +function MonthPage::view_title : string { + return $.date->date_format($*lang_fmt_month_long); +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + var string back; + var string forward; + if ($.prev_url != "") { $back = """$*text_back"""; } + if ($.next_url != "") { $forward = """$*text_forward"""; } + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
    + + + + + + +
    $back$select$forward
    +
    + """; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + +
    +
    + +
    +
    + """; + $d->print_subjectlist(); + """ +
    +
    +
    + + """; + } + } +} + +function MonthDay::print_subjectlist() { + # Too many tables... + foreach var Entry e ($.entries) { + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + """ $*text_nosubject"""; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
    \n"; + } +} + + +################################################################################ +# +# DayPage +# + +function DayPage::print_body() { + + """
    """; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + "

    $*text_noentries_day

    "; + } + """
    """; +} + +################################################################################ +# +# Page +# + +function Page::print () { + + var string title = $this->title(); + + """ + + + + $title + + """; + + $this->print_head(); + + """ + + + + + + + +
    +
    +
    +
    + """; + + $this->lay_print_userpic(); + $this->lay_print_username(); + $this->lay_print_header(); + + """ +
    + + + + + + +
    +
    + """; + + $this->lay_print_sidebar(); + + """ +
    +
    + """; + + $this->lay_print_subnav(); + $this->print_body(); + $this->lay_print_subnav(); + + """ +
    +
    +
    +
    +
    +
    + + + """; +} + + + +function print_theme_preview() { + + var Color color_bg_lt = getAltColor($*color_bg, "light", 30); + var Color color_fg_dk = getAltColor($*color_fg, "dark", 20); + var Color color_fg_dk_font = getAltColor($*color_fg_font, "dark", 20); + var Color color_divider = getAltColor($color_fg_dk, "dark", 30); + var Color color_fg_dk_dk_font = getAltColor($color_fg_dk, "dark", 50); + var Color color_border = getAltColor($*color_bg, "light", 90); + + """ +
    +
    +
    Username - Title
    +
    +
    +
    +
    + Welcome +
    This is my new journal using a cool new style!
    +
    +
    + """; + +} diff --git a/local/bin/upgrading/s2layers/opal/opal.jpg b/local/bin/upgrading/s2layers/opal/opal.jpg new file mode 100755 index 0000000000000000000000000000000000000000..4c11fb314e1dedc9c0a9e16e7bd01dbba1e82387 GIT binary patch literal 13075 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 krAR}U$=z`~g+ - \". The Custom Date Formats section of the S2 Documentation at http://www.livejournal.com/doc/s2/siteapi.core1.html#siteapi.core1.dateformats will list the pieces that you can use to construct your format. You must wrap each piece in two percent signs (%%) in your format."; + } + property string text_format_entry_time { + des = "Format for Date and Time (Day page only)"; + note = "This is provided as a separate customisation from the previous because users may want to supress the printing of the Date part of the subject line on Day pages. On these pages, only entries from that certain Date will be printed and the Page's header will reflect that under the menu. Putting the date on the subject line is unnecessary and is left out by default. If you would like it to appear just as on other pages, use the same format as the previous setting."; + } + set text_nosubject = "(no subject)"; + set text_entry_username_seperator = ""; + set text_meta_music = "Music"; + set text_meta_mood = "Mood"; + set text_meta_tags = "Tags"; + set text_read_comments = "Read 1 // Read #"; + set text_post_comment = "Speak"; + set text_post_comment_guestbook = "Sign Guestbook"; + set text_permalink = "Link"; + set text_edit = "Edit"; + set text_edittag = "Edit Tags"; + set text_add_to_memories = "Remember"; + set text_comment_thread = "Thread"; + set text_comment_parent = "Parent"; + set text_comment_reply = "Reply"; + set text_comment_permalink = "Link"; + set text_multiform_opt_delete = "Delete"; + set text_multiform_opt_screen = "Screen"; + set text_multiform_opt_unscreen = "Unscreen"; + set text_multiform_opt_freeze= "Freeze"; + set text_multiform_opt_unfreeze = "Unfreeze"; + set text_multiform_check = "Select"; + set text_poster_anonymous = "Anonymous"; + set text_format_entry_date_and_time = "%%dayord%%-%%mon%%-%%yyyy%% %%hh%%:%%min%% %%a%%m"; + set text_format_entry_time = "%%hh%%:%%min%% %%a%%m"; +} + + +function print_stylesheet() "Prints the CSS that goes into the stylesheet for the layout" { + """ + body { + font-family: $*font_base, sans-serif; + font-size: """; print $*font_base_size; """px; + margin: 0px; + background-color: $*color_body_background; + color: $*color_body_text; + background-image: url('$*layout_background'); + } + a { + color: $*color_body_links; + } + a:visited { + color: $*color_body_links_visited; + } + .entryHeaderDate a { + color : $*color_body_entrytitle_links; + text-decoration : none; + } + .entryHeaderDate a:hover { + color : $*color_body_entrytitle_links; + text-decoration : underline; + } + .header-title { + background-color: $*color_header_title_background; + font-family: $*font_header_title; + font-size: """; print $*font_header_title_size; """px; + color: $*color_header_title_text; + padding: 0px 20px 0px 20px; + } + .header-subtitle { + background-color: $*color_header_title_background; + color: $*color_header_subtitle_text; + font-family: $*font_header_subtitle; + font-size: """; print $*font_header_subtitle_size; """px; + padding: 0px 24px 0px 24px; + } + .header-icon { + top: 0px; + right: 0px; + position: absolute; + z-index: 1; + border-left: 2px solid $*color_header_borders; + border-bottom: 2px solid $*color_header_borders; + } + .pageheaderblock { + text-align: $*layout_header_alignment; + } + .pagefooterblock { + border-top: 2px solid $*color_body_entrytitle_border; + background-color: $*color_body_footer_background; + color: $*color_body_footer_text; + padding: 4px 4px 4px 24px; + margin-top: 4px; + } + .pagefooterblock a, .pagefooterblock a:visited { + color: $*color_body_footer_text; + } + .bodyblock { + padding: 10px """;print $*layout_margin_right;"""px 0px """;print $*layout_margin_left;"""px; + } + .bodyheaderblock { + border-top: 2px solid $*color_header_borders; + background-color: $*color_body_titlebar_background; + padding: 4px 0px 4px 0px; + } + .bodynavblock { + border-top: 2px solid $*color_header_borders; + background-color: $*color_body_titlebar_background; + color: $*color_body_titlebar_text; + margin: 10px 0px 4px 0px; + padding: 8px; + } + .bodynavblock a, .bodynavblock a:visited { + color: $*color_body_titlebar_text; + } + .body-title { + font-family: $*font_body_title; + font-size: """; print $*font_body_title_size; """px; + color: $*color_body_titlebar_text; + text-align: $*layout_header_alignment; + padding-left: 24px; + } + .body-midtitle { + font-family: $*font_body_title; + font-size: """; print $*font_body_title_size; """px; + color: $*color_body_titlebar_text; + text-align: left; + padding-left: 8px; + } + .entryHolder { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + font-family: $*font_entry_text; + font-size: """; print $*font_entry_text_size; """px; + border-top: 2px solid $*color_body_entrytitle_border; + margin: 4px 0px 4px 0px; + } + .entryUserinfo { + text-align: center;"""; + if ($*layout_position_userinfo_entry=="left") { """ + margin: 0px 8px 8px 0px; + """;}elseif($*layout_position_userinfo_entry=="right") { """ + margin: 0px 0px 8px 8px; + """;}""" + background-color: $*color_body_entry_userinfo_background; + } + .entryUserinfo-usericon img { + border: 0; + } + .entryText { + padding: 6px; + } + .entryHeader { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + padding: 4px 0px 4px 8px; + } + .entryHeader a{ + color: $*color_body_entrytitle_links; + } + .entryHeaderSubject { + font-weight: bold; + } + .entryMetadata { + padding-left: 6px; + } + .entryMetadata ul { + margin: 0px; + padding: 0px; + } + .entryMetadata li { + list-style: none; + display: inline; + padding-right: 10px; + } + .entryMetadata-label { + font-weight: bold; + padding-right: 4px; + } + .entryLinkbar { + font-family: $*font_entry_linkbar; + font-size: """; print $*font_entry_linkbar_size; """px; + color: $*color_body_entry_text; + text-align: $*layout_linkbar_alignment_entry; + padding: 4px 0px 4px 0px; + } + .entryLinkbar ul { + margin: 0px; + padding: 0px; + } + .entryLinkbar li { + padding: 0px 5px 0px 5px; + margin: 0px; + display: inline; + } + .commentHolder { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + border-top: 2px solid $*color_body_entrytitle_border; + font-family: $*font_entry_text; + font-size: """; print $*font_entry_text_size; """px; + margin: 4px 0px 4px 0px; + } + .commentUserinfo { + text-align: center; """; + if ($*layout_position_userinfo_comment=="left") { """ + margin: 0px 8px 8px 0px; + """;}elseif($*layout_position_userinfo_comment=="right") { """ + margin: 0px 0px 8px 8px; + """;}""" + background-color: $*color_body_entry_userinfo_background; + } + .commentUserinfo-usericon img { + border: 0; + } + .commentText { + padding: 6px; + } + .commentHeader { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + padding: 4px 0px 4px 8px; + } + .commentHeader a{ + color: $*color_body_entrytitle_links; + } + .commentHeaderScreened { + font-family: $*font_entry_title; + font-size: """; print $*font_entry_title_size; """px; + background-color: $*color_body_entrytitle_background_alternate; + padding: 4px 0px 4px 8px; + } + .commentHeaderSubject { + font-weight: bold; + } + .commentLinkbar { + font-family: $*font_entry_linkbar; + font-size: """; print $*font_entry_linkbar_size; """px; + color: $*color_body_entry_text; + text-align: $*layout_linkbar_alignment_comment; + padding-top: 4px; + padding-bottom: 4px; + } + .commentLinkbar ul { + margin: 0px; + padding: 0px; + } + .commentLinkbar li { + padding: 0px 5px 0px 5px; + margin: 0px; + display: inline; + } + .replyform { + padding-left: 10px; + } + .yearlinks{ + text-align: right; + } + .yearlink{ + padding-left:4px; + padding-right: 4px; + } + .month { + width: 500px; + border: 1px solid $*color_month_borders; + margin: 8px 8px 8px 40px; + } + .daysubjects { + color: $*color_body_entry_text; + padding: 8px 8px 8px 40px; + } + .daytitles { + text-align: center; + border: 1px solid $*color_month_borders; + background: $*color_month_title_background; + color: $*color_month_title_text; + } + .day-blank { + border: 1px solid $*color_month_borders; + } + .day { + border: 1px solid $*color_month_borders; + } + .day-date { + border-right: 1px solid $*color_month_borders; + border-bottom: 1px solid $*color_month_borders; + color: $*color_month_dates; + width: 50%; + text-align: center; + } + .day-count { + width: 50%; + text-align: center; + float: right; + font-size: """; print $*font_archive_daycount_size; """px; + } + .day-count a { + text-decoration: none; + color: $*color_month_postcount; + } + """; + + # print sidebar css only if we need to + if ($*layout_sidebar_position!="none") { """ + .sidebar { + font-family: $*font_sidebar_text; + font-size: """; print $*font_sidebar_text_size; """px; + margin-"""; if($*layout_sidebar_position=="left"){print "right";}else{print "left";}""": 20px; + width: """; print $*layout_sidebar_width; """px; + } + .sidebox { + color: $*color_body_entry_text; + background-color: $*color_body_entry_background; + margin: 4px 0px 4px 0px; + } + .sideboxTitle { + background-color: $*color_body_entrytitle_background; + color: $*color_body_entrytitle_text; + border-top: 2px solid $*color_body_entrytitle_border; + font-family: $*font_sidebar_title; + font-size: """; print $*font_sidebar_title_size; """px; + padding: 4px 0px 4px 8px; + text-align: $*layout_sidebox_title_alignment; + } + .sideboxContent { + text-align: left; + padding: 2px 4px 2px 4px; + } + .sidebox #profile, sidebox #latestmonth, .sidebox #search, .sidebox #tags_sidebox { + text-align: center; + } + .sidebox #systemlinks { + text-align: $*layout_sidebox_links_alignment; + } + .sidebox #latestmonth table{ + width: 90%; + margin-left: auto; + margin-right: auto; + margin-top: 4px; + } + .listtitle { + font-weight: bold; + } + .profile-label { + font-weight: bold; + } + """;} + + """ + .header-menu { + padding: 0px; + background-color: $*color_header_menubar_background; + border-top: 2px solid $*color_header_borders; + padding-left: 19px; + font-family: $*font_header_menu; + font-size: """; print $*font_header_menu_size; """px; + line-height: """; print ($*font_header_menu_size+8); """px; + } + .header-menu a, .header-menu a:visited { + white-space: nowrap; + text-align: left; + padding: 2px 6px 2px 6px; + color: $*color_header_menubar_text; + text-decoration: none; + } + .header-menu a:hover { + background-color: $*color_header_menubar_background_hover; + color: $*color_header_menubar_text_hover; + } + #footer-menu { + font-size: 11px; + } + #footer-menu a, .footer-menu a:visited { + color: $*color_body_titlebar_text; + white-space: nowrap; + padding: 6px; + text-align: left; + } + .header-menu ul, #footer-menu ul { + margin: 0px; + padding: 0px; + } + .header-menu li, #footer-menu li { + display: inline; + } + """; + + if ($*layout_replyform_textarea_width>0) { """ + .replyform textarea { + width: """; print $*layout_replyform_textarea_width; """px; + } + """; } + + print $*layout_custom_css; +} + +function Page::lay_get_previous_url():string { return ""; } +function Page::lay_get_next_url():string { return ""; } +function Page::lay_get_previous_title():string { return $*text_nav_prev_page; } +function Page::lay_get_next_title():string { return $*text_nav_next_page; } + +function RecentPage::lay_get_previous_url():string { return $.nav.backward_url; } +function RecentPage::lay_get_next_url():string { return $.nav.forward_url; } +function RecentPage::lay_get_previous_title():string { + return get_plural_phrase($.nav.backward_count,"text_nav_prev_recentpage"); +} +function RecentPage::lay_get_next_title():string { + return get_plural_phrase($.nav.forward_count,"text_nav_next_recentpage"); +} + + +function DayPage::lay_get_previous_url():string { return $.prev_url; } +function DayPage::lay_get_next_url():string { return $.next_url; } +function DayPage::lay_get_previous_title():string { + if (defined $.prev_date) { return $.prev_date->date_format($*text_nav_format_daypage); } else { return ""; } +} +function DayPage::lay_get_next_title():string { + if (defined $.next_date) { return $.next_date->date_format($*text_nav_format_daypage); } else { return ""; } +} + +function MonthPage::lay_get_previous_url():string { return $.prev_url; } +function MonthPage::lay_get_next_url():string { return $.next_url; } +function MonthPage::lay_get_previous_title():string { + if (defined $.prev_date) { + return $.prev_date->date_format($*text_nav_format_monthpage); + } else { + return ""; + } +} +function MonthPage::lay_get_next_title():string { + if (defined $.next_date) { + return $.next_date->date_format($*text_nav_format_monthpage); + } else { + return ""; + } +} + +function EntryPage::lay_get_previous_url():string { + var Link prev = $.entry->get_link("nav_prev"); + if (defined $prev and $.entry.itemid!=int($*layout_guestbook_entryid)) { return $prev.url; } else { return ""; } +} +function EntryPage::lay_get_next_url():string { + var Link next= $.entry->get_link("nav_next"); + if (defined $next and $.entry.itemid!=int($*layout_guestbook_entryid)) { return $next.url; } else { return ""; } +} +function EntryPage::lay_get_previous_title():string { return "$*text_nav_prev_entrypage"; } +function EntryPage::lay_get_next_title():string { return "$*text_nav_next_entrypage"; } + +function YearPage::lay_get_previous_url():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==0) { + return ""; + }else{ + var YearYear prevyear = $.years[$pos-1]; + return $prevyear.url; + } + } + } + return ""; +} +function YearPage::lay_get_next_url():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==$i) { + return ""; + }else{ + var YearYear nextyear = $.years[$pos+1]; + return $nextyear.url; + } + } + } + return ""; +} + +function YearPage::lay_get_previous_title():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==0) { + return ""; + }else{ + var YearYear prevyear = $.years[$pos-1]; + return ""+$prevyear.year; + } + } + } + return ""; +} +function YearPage::lay_get_next_title():string { + var int i = size $.years - 1; + foreach var int pos (0..$i) { + var YearYear year = $.years[$pos]; + if ($year.displayed) { + if ($pos==$i) { + return ""; + }else{ + var YearYear nextyear = $.years[$pos+1]; + return ""+$nextyear.year; + } + } + } + return ""; +} + +function Page::lay_print_header_links() { + # Menu start + """
      """; + + # Journal Navigation (Previous page, Next Page) + var string prev_link = $this->lay_get_previous_url(); + var string prev_title = $this->lay_get_previous_title(); + var string next_link = $this->lay_get_next_url(); + var string next_title = $this->lay_get_next_title(); + print ($prev_link==""?"":"
    • $prev_title
    • "); + print ($next_link==""?"":"
    • $next_title
    • "); + + # Standard Journal Pages (Recent, Archive, Friends, Userinfo) + foreach var string v ($.views_order) { + if (lang_viewname($v)!="") { + print "
    • "+lang_viewname($v)+"
    • "; + } + } + + # Memories + if ($*layout_menubar_memories) { + """
    • $*text_view_memories
    • """; + } + + # Need to add a link to scrapbook account in user links, not do this manually + # Scrapbook (picture Galleries) + #if ($*layout_menubar_scrapbook) { + # """
    • $*text_view_scrapbook
    • """; + # + #} + + # Guestbook + if (int($*layout_guestbook_entryid)!=0) { + var string guestbook_url = "$*SITEROOT/users/$.journal.username/"+$*layout_guestbook_entryid+".html"; + """
    • $*text_view_guestbook
    • """; + } + + # Website from Userinfo page + if ($*layout_menubar_website) { + """
    • $.journal.website_name
    • """; + } + + # Menu end + """
    """; +} + +function Page::lay_print_header() { + + var string title = $.global_title; + var string subtitle = $.global_subtitle; + """ +
    + """; + if ($*layout_header_usericon=="show") {"""
    $this.journal.default_pic
    """; } + """
    $title
    """; + if ($.global_subtitle!="") { """
    $subtitle
    """; } + $this->lay_print_header_links(); + """ +
    + """; +} + +function EntryLite::lay_show_usericon():bool { return true; } + +function EntryLite::lay_print_subjectline() { #will only ever be used for a comment, so we can use comment settings. + """
    """; + # print $.time->date_format("%%dayord%%-%%mon%%-%%yyyy%%")+" "+$.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + print ($.subject==""?"":" - $.subject"); + """
    """; +} + +function EntryLite::lay_print_userinfo() { #will only ever be used for a comment, so we can use comment settings. + """ +
    + """; + if (defined $.userpic and $*layout_position_usernames_comment=="below") {"""""";} + """
    """; + if (defined $.poster) { + """$.poster"""; + }else{ + """$*text_poster_anonymous"""; + } + if (viewer_is_owner() and $.metadata{"poster_ip"}!="") { + """
    ($.metadata{"poster_ip"})"""; + } + """
    """; + if (defined $.userpic and $*layout_position_usernames_comment=="above") {"""
    $.userpic
    """;} + """ +
    + """; +} + +function EntryLite::print_linkbar() { + """ + + """; +} + +function EntryLite::lay_print() { #will only ever be used for a comment, so we can use comment settings. + """ +
    + """; + $this->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_comment=="left" or $*layout_wrapping_userinfo_comment ) { + $this->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_comment) {"""""";} + } + """
    $.text
    """; + if ($*layout_position_userinfo_comment=="right" and not $*layout_wrapping_userinfo_comment) { + """
    """; + $this->lay_print_userinfo(); + } + + """
    """; + $this->print_linkbar(); + """
    +
    + """; +} + +function Entry::lay_show_usericon():bool { + var Page p = get_page(); + return $*layout_show_usericons=="all" or ($*layout_show_usericons=="nonrecent" and $p.view!="recent") or ($*layout_show_usericons=="friends" and $p.view=="friends"); +} + +function Entry::lay_print_userinfo() { + var Page p = get_page(); + if ($p.view=="friends" or $p.journal_type=="C" or ($this->lay_show_usericon() and defined $.userpic)) { + """
    """; + if (defined $.userpic and $this->lay_show_usericon() and $*layout_position_usernames_entry=="below") { + """"""; + } + if ($p.view=="friends" or $p.journal_type=="C") { + """
    """; + """$.poster"""; + if ($.journal->as_string()!=$.poster->as_string() and $p.view=="friends") { + print "
    "; + if ($*text_entry_username_seperator != "") { + print $*text_entry_username_seperator + "
    "; + } + """$.journal"""; + } + """
    """; + } + if (defined $.userpic and $this->lay_show_usericon() and $*layout_position_usernames_entry=="above") { """
    $.userpic
    """; } + """
    """; + } +} + +function Entry::lay_print_subjectline() { + var Page p = get_page(); + if ($.itemid!=int($*layout_guestbook_entryid)) { + """
    """; + if ($p.view!="day") { + # print "base_url()+"/calendar/$.time.year/"+zeropad($.time.month,2)+"/"+zeropad($.time.day,2)+"/\">"+$.time->date_format("%%dayord%%")+"-"; + # print "base_url()+"/calendar/$.time.year/"+zeropad($.time.month,2)+"/\">"+$.time->date_format("%%mon%%")+"-"; + # print "base_url()+"/calendar/$.time.year/\">"+$.time->date_format("%%yyyy%%")+" "; + # print $.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + }else{ + # print $.time->time_format(); + print $.time->time_format($*text_format_entry_time); + } + """"""; + if ($p.view=="entry") { + print (defined $.security_icon?" - $.security_icon":""); + }else{ + print (defined $.security_icon or $.subject!=""?" - ":"")+(defined $.security_icon?"$.security_icon ":"")+($.subject==""?"":"$.subject"); + } + """"""; + if ((size $.tags>0)and($*layout_position_entrytags=="subject")) { + """ [$.tags[0].name"""; + foreach var int i (1 .. (size $.tags - 1)) { + """, $.tags[$i].name"""; + } + """]"""; + } + """
    """; + }else{ + """
    """; + print (defined $.security_icon?""+$.security_icon:" "); + """
    """; + } +} + +function Entry::print_metadata() { + if (($.metadata{"mood"}!="" or $.metadata{"music"}!="" or ((size $.tags>0)and($*layout_position_entrytags=="metadata"))) and ($.itemid!=int($*layout_guestbook_entryid))) { + """"""; + } +} + +function Entry::print_linkbar() { + """ + + """; +} + +function Page::print_entry(Entry e) { + if ( $e.itemid==int($*layout_guestbook_entryid) and ($.view=="recent" or $.view=="day" )) { return; } + if ( $.args{"noshow"}==$e.journal.username ) { return; } + """ + +
    + """; + $e->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_entry=="left" or $*layout_wrapping_userinfo_entry ) { + $e->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_entry) {"""""";} + } + if ($*layout_position_metadata=="above") { $e->print_metadata(); } + """
    """; print $e.text; """
    """; + if ($*layout_position_metadata=="below") { $e->print_metadata(); } + if ($*layout_position_userinfo_entry=="right" and not $*layout_wrapping_userinfo_entry) { + """
    """; + $e->lay_print_userinfo(); + } + """
    """; + $e->print_linkbar(); + """
    +
    + """; +} + +function Comment::lay_print_subjectline() { + """
    "; + #print $.time->date_format("%%dayord%%-%%mon%%-%%yyyy%%")+" "+$.time->time_format(); + print $.time->time_format($*text_format_entry_date_and_time); + print (defined $.subject_icon?""+$.subject_icon:"")+($.subject==""?"":" - $.subject"); + + """
    """; +} + +function Comment::print_linkbar() { + """ + + """; +} + +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + var int indent = ($c.depth - 1) * 25; + "
    \n"; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + "
    "; + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment(Comment comment) { + """ +
    """; + $comment->lay_print_subjectline(); + """
    """; + if ($*layout_position_userinfo_comment=="left" or $*layout_wrapping_userinfo_comment) { + $comment->lay_print_userinfo(); + if (not $*layout_wrapping_userinfo_comment) {"""""";} + } + """
    $comment.text
    """; + if ($*layout_position_userinfo_comment=="right" and not $*layout_wrapping_userinfo_comment) { + """
    """; + $comment->lay_print_userinfo(); + } + """
    """; + $comment->print_linkbar(); + """
    +
    + """; +} + + +function EntryPage::print_comment_partial(Comment comment) { + """ +
    """; + print ""+($comment.subject==""?"(no subject)":"$comment.subject")+" - "; + print (defined $comment.poster?"$comment.poster":"Anonymous"); + """
    """; +} + +function Page::lay_print_bodytitlebox(string title, string titletype) { + """ +
    +
    $title 
    +
    + """; +} + +function MonthPage::view_title : string { + return $.date->date_format($*text_nav_format_monthpage); +} + +function DayPage::view_title : string { + return $.date->date_format($*text_nav_format_daypage); +} + +function Page::lay_print_bodytop() { + $this->lay_print_bodytitlebox($this->view_title(),"title"); +} + +function ReplyPage::lay_print_bodytop() { + if ($.entry.itemid==int($*layout_guestbook_entryid) and $.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_signing_guestbook,"title"); + }elseif ($.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_comment_to,"title"); + }else { + $this->lay_print_bodytitlebox($*text_reply_to,"title"); + } +} + +function MonthPage::lay_print_bodytop_monthselector() { + """
    """; + $.redir->print_hiddens(); + if (size $.months > 1) { + """"""; + } + """
    """; +} + +function Page::lay_print_sidebox_top(string title) { + """ + + """; +} + +function Page::lay_print_sidebar_profile() { + $this->lay_print_sidebox_top($*text_sidebox_profile_title); + """ +
    + """; + if ($.journal.default_pic.url!="") { + """
    """; + } + """ +
    $*text_sidebox_profile_userlabel$.journal
    +
    $*text_sidebox_profile_namelabel$.journal.name
    + """; + if ($*text_sidebox_profile_info!="") { """
    """; print $*text_sidebox_profile_info; """
    """; } + """ +
    + """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_systemlinks() { + var int num_links = size $.linklist - 1; + if ($num_links<0) { return; } + $this->lay_print_sidebox_top($*text_sidebox_links_title); + """ + + """; + $this->lay_print_sidebox_bottom(); +} + +function Entry::lay_print_summaryline(Page p) { + """
    """; + print ($*text_sidebox_summary_bullet_bold?"$*text_sidebox_summary_bullet":$*text_sidebox_summary_bullet); + if ($p.view=="friends") { + """$.poster"""; + if ($.journal.username!=$.poster.username) { print $*text_sidebox_summary_username_seperator; """$.journal"""; } + """ - """; + }elseif ($p.view=="day") { + print $.time->time_format(); """ - """; + }else{ + #nothing + } + + if (defined $.security_icon) { """$.security_icon """; } + """"""; + if ($.subject!="") { print $this->plain_subject(); } else { """$*text_nosubject"""; } + """"""; + if ($.comments.count>0 or $.comments.screened) { """ [+$.comments.count]"""; } + """
    + """; + +} + +function Comment::lay_count_replies() : int { + var int total = 0; + foreach var Comment reply ($.replies) { + $total = $total + 1 + $reply->lay_count_replies(); + } + return $total; +} + +function Comment::lay_print_summaryline(Page p) { + """
    """; + print ($*text_sidebox_summary_bullet_bold?"$*text_sidebox_summary_bullet":$*text_sidebox_summary_bullet); + print (defined $.poster?""+$.poster:"$*text_poster_anonymous"); + """ - """; + if ($.subject!="") { """$.subject"""; } else { """$*text_nosubject"""; } + """"""; + var int count = $this->lay_count_replies(); + if ($count>0) { """ [+$count]"""; } + """
    """; +} + +function Page::lay_print_sidebar_summary() {} + +function RecentPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[$pos]; + if ($e.itemid!=int($*layout_guestbook_entryid)) {$e->lay_print_summaryline($this);} + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +function FriendsPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_friends_sortorder=="newest"?$pos:$i-$pos)]; + $e->lay_print_summaryline($this); + } + """ """; + $this->lay_print_sidebox_bottom(); +} + +function DayPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + var int i = size $.entries - 1; + if ($i<0) { """
    """; return; } + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_day_sortorder=="newest"?$i-$pos:$pos)]; + if ($e.itemid!=int($*layout_guestbook_entryid)) {$e->lay_print_summaryline($this);} + } + """ """; + $this->lay_print_sidebox_bottom(); +} + +function EntryPage::lay_print_sidebar_summary() { + $this->lay_print_sidebox_top($*text_sidebox_summary_title); + """
    """; + $.entry->lay_print_summaryline($this); + foreach var Comment c ($.comments) { + $c->lay_print_summaryline($this); + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_tags() { + var Tag[] pagetags = $this->visible_tag_list(); + if (size $pagetags==0) { return; } + $this->lay_print_sidebox_top($*text_sidebox_tags_title); + """
    """; + """$pagetags[0].name"""; + foreach var int i (1 .. (size $pagetags - 1)) { + """, $pagetags[$i].name"""; + } + """
    """; + $this->lay_print_sidebox_bottom(); +} + +# TODO: Interesting, maybe add as a builtin function later? +function Page::lay_print_sidebar_multisearch() { + $this->lay_print_sidebox_top($*text_sidebox_multisearch_title); + """ + + """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_latestmonth() { + $this->lay_print_sidebox_top($*text_sidebox_latestmonth_title); + var YearMonth month = $this->get_latest_month(); + """
    + + + """; + foreach var YearWeek week ($month.weeks) { + """"""; + if ($week.pre_empty>0) { """"""; } + foreach var YearDay day ($week.days) { + if ($day.num_entries==0) { + """"""; + }else{ + """"""; + } + } + if ($week.post_empty>0) { """"""; } + """"""; + } + """ +
    $*lang_monthname_long[$month.month] $month.year
    $day.day
    +
    """; + $this->lay_print_sidebox_bottom(); +} + + +function Page::lay_print_sidebar_freetextbox() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_title); + """
    """; print $*text_sidebox_freetext_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_2() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_2_title); + """
    """; print $*text_sidebox_freetext_2_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_3() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_3_title); + """
    """; print $*text_sidebox_freetext_3_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_4() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_4_title); + """
    """; print $*text_sidebox_freetext_4_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_5() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_5_title); + """
    """; print $*text_sidebox_freetext_5_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_6() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_6_title); + """
    """; print $*text_sidebox_freetext_6_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + + +function Page::lay_print_sidebar_freetextbox_7() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_7_title); + """
    """; print $*text_sidebox_freetext_7_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_8() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_8_title); + """
    """; print $*text_sidebox_freetext_8_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_9() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_9_title); + """
    """; print $*text_sidebox_freetext_9_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_10() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_10_title); + """
    """; print $*text_sidebox_freetext_10_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar_freetextbox_private() { + $this->lay_print_sidebox_top($*text_sidebox_freetext_private_title); + """
    """; $*text_sidebox_freetext_private_text; """
    """; + $this->lay_print_sidebox_bottom(); +} + +function Page::lay_print_sidebar() { + """ """; +} + +function Page::lay_print_bodymiddle() { + """ +
    This page does not have an implementation.
    + """; +} + +function RecentPage::lay_print_bodymiddle() { + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_recent
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[$pos]; + $this->print_entry($e); + } + } +} + +function FriendsPage::lay_print_bodymiddle() { + + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_recent
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_friends_sortorder=="newest"?$pos:$i-$pos)]; + $this->print_entry($e); + } + } +} + +function DayPage::lay_print_bodymiddle() { + var int i = size $.entries - 1; + if ($i<0) { + """
    $*text_noentries_day
    """; + }else{ + foreach var int pos (0..$i) { + var Entry e = $.entries[($*layout_day_sortorder=="newest"?$i-$pos:$pos)]; + $this->print_entry($e); + } + } +} + +function ReplyPage::lay_print_bodymiddle() { + if ($.replyto.depth==0) { + $this->print_entry($.entry); + }else{ + $.replyto->lay_print(); + } + if ($.entry.itemid==int($*layout_guestbook_entryid) and $.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_signing_form,"midtitle"); + }elseif ($.replyto.depth==0) { + $this->lay_print_bodytitlebox($*text_comment_form,"midtitle"); + }else{ + $this->lay_print_bodytitlebox($*text_reply_form,"midtitle"); + } + """ + """; + if ($.replyto.depth==0 and int($*layout_guestbook_entryid)!=0 and $.entry.itemid!=int($*layout_guestbook_entryid) and $*text_replypage_warning!="") { + + print $*text_replypage_warning; + } + """ +
    """; + $.form->print(); + """
    """; +} + +function EntryPage::lay_print_bodymiddle() { + $this->print_entry($.entry); + if (size $.comments >0) { + if ($.entry.itemid!=int($*layout_guestbook_entryid)) { + $this->lay_print_bodytitlebox($*text_comment_seperator,"midtitle"); + }else { + $this->lay_print_bodytitlebox($*text_signature_seperator,"midtitle"); + } + if (viewer_is_owner()) { $this->print_multiform_start(); } + $this->print_comments($.comments); + if (not $.comment_pages.all_subitems_displayed) { + """
    """; + $.comment_pages->print(); + """
    """; + } + """
    """; + if (viewer_is_owner()) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + }else{ + if ($.entry.itemid!=int($*layout_guestbook_entryid)) { + """$*text_post_comment_entrypage"""; + }else{ + """$*text_post_comment_guestbook"""; + } + } + """
    """; + } +} + +function MonthDay::print_subjectlist() { + foreach var Entry e ($.entries) { + if ($e.itemid!=int($*layout_guestbook_entryid)) { + print $e.time->time_format(); + print " - "+(defined $e.security_icon?"$e.security_icon ":""); + """"""; + print ($e.subject==""?"(no subject)":$e->plain_subject()); + """"""; + if ($e.comments.count>0) { """   [ $e.comments.count Comments ]"""; } + """
    """; + } + } +} + +function MonthPage::lay_print_bodymiddle() { + foreach var MonthDay day ($.days) { + if ($day.has_entries) { + """ +
    + +
    """; + $day->print_subjectlist(); + """
    +
    """; + } + } +} + +function YearPage::print_month(YearMonth month) { + """ + +
    + + + """; foreach var int i (1..7) { """"""; } """ + """; + foreach var YearWeek week ($month.weeks) { + """"""; + if ($week.pre_empty>0) { """"""; } + foreach var YearDay day ($week.days) { + """"""; + } + if ($week.post_empty>0) { """"""; } + """"""; + } + """ +
    $*lang_dayname_short[$i]
    +
    $day.day
    +
    """; + print ($day.num_entries==0?" ":""+$day.num_entries+""); + """
    +
    +
    + """; +} + +function YearPage::lay_print_bodymiddle() { + var int i = size $.months - 1; + if ($i<0) { return; } + + foreach var int pos (0..$i) { + var YearMonth month = $.months[($*layout_year_sortorder=="newest"?$i-$pos:$pos)]; + if ($month.has_entries) { + $this->print_month($month); + } + } +} + +function Page::lay_print_bodybottom() { + var string prev_link = $this->lay_get_previous_url(); + var string prev_title = $this->lay_get_previous_title(); + var string next_link = $this->lay_get_next_url(); + var string next_title = $this->lay_get_next_title(); + """"""; +} + +function EntryPage::lay_print_bodybottom() {} +function ReplyPage::lay_print_bodybottom() {} + +function Page::lay_print_body() { + $this->lay_print_bodytop(); + """
    """; + """"""; + if ($*layout_sidebar_position=="left") { + """"""; + } + """"""; + if ($*layout_sidebar_position=="right") { + """"""; + } + """
    """; + $this->lay_print_sidebar(); + """"""; + $this->lay_print_bodymiddle(); + $this->lay_print_bodybottom(); + """"""; + $this->lay_print_sidebar(); + """
    """; + """
    """; +} + +function Page::lay_print_footer() { + if ($*text_footer_signature!="") { + var string footer_signature = $*text_footer_signature; + $footer_signature = $.time->time_format($footer_signature); + """
    """; print $footer_signature; """
    """; + } +} + +function Page::print_body() { + """
    """; + $this->lay_print_header(); + $this->lay_print_body(); + $this->lay_print_footer(); + """
    """; +} + +function Page::print() { + var string title = $this->title(); + """ + + + $title +"""; +if ($*layout_stylesheet=="") { + """ """; +}else{ + """ """; +} +$this->print_head(); +""" + + + +"""; $this->print_body(); """ + + +"""; +} + + + + diff --git a/local/bin/upgrading/s2layers/smoothsailing/themes.s2 b/local/bin/upgrading/s2layers/smoothsailing/themes.s2 new file mode 100755 index 0000000..0fd9e57 --- /dev/null +++ b/local/bin/upgrading/s2layers/smoothsailing/themes.s2 @@ -0,0 +1,612 @@ +#NEWLAYER: smoothsailing/starry +layerinfo "redist_uniq" = "smoothsailing/starry"; +layerinfo "type" = "theme"; +layerinfo "name" = "Starry Night"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#000000"; + set color_header_title_text = "#FFFFB9"; + set color_header_subtitle_text = "#dddddd"; + set color_header_menubar_background = "#000044"; + set color_header_menubar_text = "#FFFFB9"; + set color_header_menubar_background_hover = "#000000"; + set color_header_menubar_text_hover = "#dddddd"; + set color_header_borders = "#89a2be"; + + set color_body_links = "#ffffb9"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#aaaaaa"; + set color_body_titlebar_text = "#000044"; + set color_body_footer_background = "#000000"; + set color_body_footer_text = "#ffffb9"; + set color_body_background = "#000044"; + set color_body_text = "#FFFFB9"; + + set color_body_entrytitle_background = "#000000"; + set color_body_entrytitle_background_alternate = "#aaaaaa"; + set color_body_entrytitle_border = "#89A2BE"; + set color_body_entrytitle_text = "#89a2be"; + set color_body_entrytitle_links = "#89a2be"; + set color_body_entry_background = "#000044"; + set color_body_entry_userinfo_background = "#000044"; + set color_body_entry_text = "#FFFFB9"; + + set color_month_borders = "#89A2BE"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#FFFFB9"; + + + +#NEWLAYER: smoothsailing/pink +layerinfo "redist_uniq" = "smoothsailing/pink"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pretty in Pink"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#CC4E5C"; + set color_header_title_text = "#FFEEFF"; + set color_header_subtitle_text = "#FFB6C1"; + set color_header_menubar_background = "#e6828f"; + set color_header_menubar_text = "#FFEEFF"; + set color_header_menubar_background_hover = "#CC4E5C"; + set color_header_menubar_text_hover = "#FFEEFF"; + set color_header_borders = "#FFEEFF"; + + set color_body_links = "#CC4E5C"; + set color_body_links_visited = "#CC4E5C"; + set color_body_titlebar_background = "#FFB6C1"; + set color_body_titlebar_text = "#CC4E5C"; + set color_body_footer_background = "#FFB6C1"; + set color_body_footer_text = "#CC4E5C"; + set color_body_background = "#FFEEFF"; + set color_body_text = "#CC4E5C"; + set color_body_entrytitle_background = "#FFB6C1"; + set color_body_entrytitle_background_alternate = "#e6828f"; + set color_body_entrytitle_border = "#CC4E5C"; + set color_body_entrytitle_text = "#CC4E5C"; + set color_body_entrytitle_links = "#CC4E5C"; + set color_body_entry_text = "#CC4E5C"; + set color_body_entry_background = "#FFEEFF"; + set color_body_entry_userinfo_background = "#FFEEFF"; + + set color_month_borders = "#CC4E5C"; + set color_month_title_background = "#FFB6C1"; + set color_month_title_text = "#CC4E5C"; + set color_month_dates = "#CC4E5C"; + set color_month_postcount = "#e6828f"; + + + + +#NEWLAYER: smoothsailing/easter +layerinfo "redist_uniq" = "smoothsailing/easter"; +layerinfo "type" = "theme"; +layerinfo "name" = "Easter Basket"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#00B789"; + set color_header_title_text = "#FFFF82"; + set color_header_subtitle_text = "#005100"; + set color_header_menubar_background = "#FFFF82"; + set color_header_menubar_text = "#005100"; + set color_header_menubar_background_hover = "#C7A0CB"; + set color_header_menubar_text_hover = "#005100"; + set color_header_borders = "#009300"; + + set color_body_links = "#005100"; + set color_body_links_visited = "#005100"; + set color_body_titlebar_background = "#C7A0CB"; + set color_body_titlebar_text = "#005100"; + set color_body_footer_background = "#C7A0CB"; + set color_body_footer_text = "#005100"; + set color_body_background = "#DDDFF0"; + set color_body_text = "#005100"; + set color_body_entrytitle_background = "#FFFF82"; + set color_body_entrytitle_background_alternate = "#C7A0CB"; + set color_body_entrytitle_border = "#009300"; + set color_body_entrytitle_text = "#005100"; + set color_body_entrytitle_links = "#005100"; + set color_body_entry_text = "#005100"; + set color_body_entry_background = "#DDDFF0"; + set color_body_entry_userinfo_background = "#DDDFF0"; + + set color_month_borders = "#00B789"; + set color_month_title_background = "#FFFF82"; + set color_month_title_text = "#005100"; + set color_month_dates = "#C7A0CB"; + set color_month_postcount = "#005100"; + + + + +#NEWLAYER: smoothsailing/mocha +layerinfo "redist_uniq" = "smoothsailing/mocha"; +layerinfo "type" = "theme"; +layerinfo "name" = "Mochachino"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#666666"; + set color_header_title_text = "#e6e6e6"; + set color_header_subtitle_text = "#B1A68B"; + set color_header_menubar_background = "#635a48"; + set color_header_menubar_text = "#b1a68b"; + set color_header_menubar_background_hover = "#b1a68b"; + set color_header_menubar_text_hover = "#666666"; + set color_header_borders = "#e6e6e6"; + + set color_body_links = "#464640"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#B1A68B"; + set color_body_titlebar_text = "#e6e6e6"; + set color_body_footer_background = "#b1a68b"; + set color_body_footer_text = "#e6e6e6"; + set color_body_background = "#e6e6e6"; + set color_body_entrytitle_background = "#b1a68b"; + set color_body_entrytitle_background_alternate = "#796D51"; + set color_body_entrytitle_border = "#666666"; + set color_body_entrytitle_text = "#e6e6e6"; + set color_body_entrytitle_links = "#e6e6e6"; + set color_body_entry_text = "#464640"; + set color_body_entry_background = "#e6e6e6"; + set color_body_entry_userinfo_background = "#e6e6e6"; + + set color_month_borders = "#666666"; + set color_month_title_background = "#e6e6e6"; + set color_month_title_text = "#464640"; + set color_month_dates = "#464640"; + set color_month_postcount = "#796D51"; + +#NEWLAYER: smoothsailing/yellow +layerinfo "redist_uniq" = "smoothsailing/yellow"; +layerinfo "type" = "theme"; +layerinfo "name" = "Insane Yellow"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#202020"; + set color_header_title_text = "#FFFF04"; + set color_header_subtitle_text = "#dddddd"; + set color_header_menubar_background = "#000000"; + set color_header_menubar_text = "#FFFFB9"; + set color_header_menubar_background_hover = "#202020"; + set color_header_menubar_text_hover = "#FFFFB9"; + set color_header_borders = "#FFFF04"; + + set color_body_links = "#aaaaaa"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#aaaaaa"; + set color_body_titlebar_text = "#000000"; + set color_body_footer_background = "#202020"; + set color_body_footer_text = "#ffffb9"; + set color_body_background = "#000000"; + set color_body_text = "#FFFFB9"; + + set color_body_entrytitle_background = "#202020"; + set color_body_entrytitle_background_alternate = "#aaaaaa"; + set color_body_entrytitle_border = "#FFFF04"; + set color_body_entrytitle_text = "#FFFF04"; + set color_body_entrytitle_links = "#FFFF04"; + set color_body_entry_background = "#000000"; + set color_body_entry_userinfo_background = "#000000"; + set color_body_entry_text = "#aaaaaa"; + + set color_month_borders = "#FFFFB9"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#FFFFB9"; + + +#NEWLAYER: smoothsailing/forest +layerinfo "redist_uniq" = "smoothsailing/forest"; +layerinfo "type" = "theme"; +layerinfo "name" = "In the Forest"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#635a48"; + set color_header_title_text = "#e7dfcf"; + set color_header_subtitle_text = "#607c6d"; + set color_header_menubar_background = "#899ba3"; + set color_header_menubar_text = "#464640"; + set color_header_menubar_background_hover = "#e7dfcf"; + set color_header_menubar_text_hover = "#464640"; + set color_header_borders = "#464640"; + + set color_body_links = "#e7dfcf"; + set color_body_links_visited = "#e7dfcf"; + set color_body_titlebar_background = "#e7dfcf"; + set color_body_titlebar_text = "#464640"; + set color_body_footer_background = "#e7dfcf"; + set color_body_footer_text = "#464640"; + set color_body_background = "#607c6d"; + set color_body_text = "#e7dfcf"; + + set color_body_entrytitle_background = "#635a48"; + set color_body_entrytitle_background_alternate = "#464640"; + set color_body_entrytitle_border = "#e7dfcf"; + set color_body_entrytitle_text = "#e7dfcf"; + set color_body_entrytitle_links = "#e7dfcf"; + set color_body_entry_userinfo_background = "#626b5b"; + set color_body_entry_background = "#626b5b"; + set color_body_entry_text = "#e7dfcf"; + + set color_month_borders = "#464640"; + set color_month_title_background = "#e7dfcf"; + set color_month_title_text = "#464640"; + set color_month_dates = "#899ba3"; + set color_month_postcount = "#e7dfcf"; + + + +#NEWLAYER: smoothsailing/red +layerinfo "redist_uniq" = "smoothsailing/red"; +layerinfo "type" = "theme"; +layerinfo "name" = "Seeing Red"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#bb0000"; + set color_header_title_text = "#ffffff"; + set color_header_subtitle_text = "#ffffff"; + set color_header_menubar_background = "#880000"; + set color_header_menubar_text = "#ffffff"; + set color_header_menubar_background_hover = "#ffffff"; + set color_header_menubar_text_hover = "#bb0000"; + set color_header_borders = "#ffffff"; + set color_body_links = "#880000"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#bb0000"; + set color_body_titlebar_text = "#ffffff"; + set color_body_footer_background = "#bb0000"; + set color_body_footer_text = "#ffffff"; + set color_body_background = "#f6f6f6"; + set color_body_text = "#880000"; + set color_body_entrytitle_background = "#bb0000"; + set color_body_entrytitle_background_alternate = "#880000"; + set color_body_entrytitle_border = "#000000"; + set color_body_entrytitle_text = "#ffffff"; + set color_body_entrytitle_links = "#ffffff"; + set color_body_entry_background = "#f6f6f6"; + set color_body_entry_text = "#880000"; + set color_month_borders = "#880000"; + set color_month_title_background = "#bb0000"; + set color_month_title_text = "#ffffff"; + set color_month_dates = "#880000"; + set color_month_postcount = "#bb0000"; + + + +#NEWLAYER: smoothsailing/army +layerinfo "redist_uniq" = "smoothsailing/army"; +layerinfo "type" = "theme"; +layerinfo "name" = "Army Attire"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#444444"; + set color_header_title_text = "#cccc99"; + set color_header_subtitle_text = "#e6e6e6"; + set color_header_menubar_background = "#665d34"; + set color_header_menubar_text = "#cccc99"; + set color_header_menubar_background_hover = "#cccc99"; + set color_header_menubar_text_hover = "#444444"; + set color_header_borders = "#e6e6e6"; + + set color_body_links = "#444444"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#cccc99"; + set color_body_titlebar_text = "#665d34"; + set color_body_footer_background = "#cccc99"; + set color_body_footer_text = "#665d34"; + set color_body_background = "#e6e6e6"; + + set color_body_entrytitle_background = "#cccc99"; + set color_body_entrytitle_background_alternate = "#665d34"; + set color_body_entrytitle_border = "#444444"; + set color_body_entrytitle_text = "#665d34"; + set color_body_entrytitle_links = "#665d34"; + set color_body_entry_text = "#444444"; + set color_body_entry_background = "#e6e6e6"; + set color_body_entry_userinfo_background = "#e6e6e6"; + + set color_month_borders = "#444444"; + set color_month_title_background = "#e6e6e6"; + set color_month_title_text = "#444444"; + set color_month_dates = "#444444"; + set color_month_postcount = "#665d34"; + + + +#NEWLAYER: smoothsailing/midnight +layerinfo "redist_uniq" = "smoothsailing/midnight"; +layerinfo "type" = "theme"; +layerinfo "name" = "Midnight"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#000000"; + set color_header_title_text = "#BEAA61"; + set color_header_subtitle_text = "#76456B"; + set color_header_menubar_background = "#76456B"; + set color_header_menubar_text = "#dddddd"; + set color_header_menubar_background_hover = "#000000"; + set color_header_menubar_text_hover = "#dddddd"; + set color_header_borders = "#dddddd"; + + set color_body_links = "#aaaaaa"; + set color_body_links_visited = "#dddddd"; + set color_body_titlebar_background = "#BEAA61"; + set color_body_titlebar_text = "#000000"; + set color_body_footer_background = "#76456B"; + set color_body_footer_text = "#dddddd"; + set color_body_background = "#000000"; + set color_body_text = "#aaaaaa"; + + set color_body_entrytitle_background = "#76456B"; + set color_body_entrytitle_background_alternate = "#888888"; + set color_body_entrytitle_border = "#cccccc"; + set color_body_entrytitle_text = "#dddddd"; + set color_body_entrytitle_links = "#dddddd"; + set color_body_entry_userinfo_background = "#000000"; + set color_body_entry_background = "#000000"; + set color_body_entry_text = "#aaaaaa"; + + set color_month_borders = "#dddddd"; + set color_month_title_background = "#aaaaaa"; + set color_month_title_text = "#000000"; + set color_month_dates = "#aaaaaa"; + set color_month_postcount = "#BEAA61"; + + + +#NEWLAYER: smoothsailing/violet +layerinfo "redist_uniq" = "smoothsailing/violet"; +layerinfo "type" = "theme"; +layerinfo "name" = "Very Violet"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#7c52ab"; + set color_header_subtitle_text = "#dbcfe9"; + set color_header_menubar_background = "#bfaad7"; + set color_header_menubar_background_hover = "#7c52ab"; + set color_body_links_visited = "#563976"; + set color_body_titlebar_background = "#dbcfe9"; + set color_body_footer_background = "#bfaad7"; + set color_body_entrytitle_background = "#dbcfe9"; + +#NEWLAYER: smoothsailing/purple +layerinfo "redist_uniq" = "smoothsailing/purple"; +layerinfo "type" = "theme"; +layerinfo "name" = "Bruised Purple"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_body_entrytitle_border = "#d4ddee"; + set color_body_footer_text = "#454b74"; + set color_month_title_text = "#8792bd"; + set color_header_borders = "#8792bd"; + set color_body_links_visited = "#dddddd"; + set color_header_menubar_text_hover = "#ffffff"; + set color_body_titlebar_text = "#454b74"; + set color_body_entrytitle_background_alternate = "#d4ddee"; + set color_body_entrytitle_links = "#6b7da6"; + set color_body_entry_background = "#454b74"; + set color_header_title_background = "#454b74"; + set color_body_entry_userinfo_background = "#454b74"; + set color_month_dates = "#8792bd"; + set color_body_links = "#ececec"; + set color_body_background = "#6b7da6"; + set color_month_postcount = "#8792bd"; + set color_body_entry_text = "#8792bd"; + set color_body_text = "#ffffff"; + set color_body_entrytitle_background = "#d4ddee"; + set color_header_menubar_text = "#ffffff"; + set color_body_entrytitle_text = "#454b74"; + +#NEWLAYER: smoothsailing/parrot +layerinfo "redist_uniq" = "smoothsailing/parrot"; +layerinfo "type" = "theme"; +layerinfo "name" = "Parrot Feathers"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#009900"; + set color_header_title_text = "#f8f8f8"; + set color_header_subtitle_text = "#66ff66"; + set color_header_menubar_background = "#33cc33"; + set color_header_menubar_text = "#ffffff"; + set color_header_menubar_background_hover = "#66ff66"; + set color_header_menubar_text_hover = "#ffffff"; + set color_header_borders = "#ffffff"; + + set color_body_links = "#006600"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#66cc66"; + set color_body_titlebar_text = "#ffffff"; + set color_body_footer_background = "#66cc66"; + set color_body_footer_text = "#ffffff"; + set color_body_background = "#f8f8f8"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#66cc66"; + set color_body_entrytitle_background_alternate = "#66ff66"; + set color_body_entrytitle_border = "#006600"; + set color_body_entrytitle_text = "#000000"; + set color_body_entrytitle_links = "#000000"; + set color_body_entry_background = "#f8f8f8"; + set color_body_entry_userinfo_background = "#f8f8f8"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#006600"; + set color_month_title_background = "#f8f8f8"; + set color_month_title_text = "#000000"; + set color_month_dates = "#000000"; + set color_month_postcount = "#006600"; + +#NEWLAYER: smoothsailing/toxic +layerinfo "redist_uniq" = "smoothsailing/toxic"; +layerinfo "type" = "theme"; +layerinfo "name" = "Toxic Teal"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#7cb3b0"; + set color_header_title_text = "#496a68"; + set color_header_subtitle_text = "#c9eae8"; + set color_header_menubar_background = "#aededb"; + set color_header_menubar_text = "#496a68"; + set color_header_menubar_background_hover = "#c9eae8"; + set color_header_menubar_text_hover = "#496a68"; + set color_header_borders = "#496a68"; + + set color_body_links = "#496a68"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#c9eae8"; + set color_body_titlebar_text = "#496a68"; + set color_body_footer_background = "#c9eae8"; + set color_body_footer_text = "#496a68"; + set color_body_background = "#496a68"; + set color_body_text = "#aededb"; + + set color_body_entrytitle_background = "#7cb3b0"; + set color_body_entrytitle_background_alternate = "#6e9e9b"; + set color_body_entrytitle_border = "#c9eae8"; + set color_body_entrytitle_text = "#000000"; + set color_body_entrytitle_links = "#000000"; + set color_body_entry_background = "#aededb"; + set color_body_entry_userinfo_background = "#aededb"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#496a68"; + set color_month_title_background = "#c9eae8"; + set color_month_title_text = "#000000"; + set color_month_dates = "#000000"; + set color_month_postcount = "#496a68"; + +#NEWLAYER: smoothsailing/banana +layerinfo "redist_uniq" = "smoothsailing/banana"; +layerinfo "type" = "theme"; +layerinfo "name" = "Banana Tree"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#3D5D2E"; + set color_header_title_text = "#F6F6BB"; + set color_header_subtitle_text = "#E1D751"; + set color_header_menubar_background = "#E1D751"; + set color_header_menubar_text = "#3D5D2E"; + set color_header_menubar_background_hover = "#9A722E"; + set color_header_menubar_text_hover = "#F6F6BB"; + set color_header_borders = "#F6F6BB"; + + set color_body_links = "#3D5D2E"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#9A722E"; + set color_body_titlebar_text = "#F6F6BB"; + set color_body_footer_background = "#3D5D2E"; + set color_body_footer_text = "#F6F6BB"; + set color_body_background = "#F6F6BB"; + set color_body_text = "#3D5D2E"; + + set color_body_entrytitle_background = "#3D5D2E"; + set color_body_entrytitle_background_alternate = "#9A722E"; + set color_body_entrytitle_border = "#9A722E"; + set color_body_entrytitle_text = "#E1D751"; + set color_body_entrytitle_links = "#E1D751"; + set color_body_entry_background = "#F6F6BB"; + set color_body_entry_userinfo_background = "#F6F6BB"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#9A722E"; + set color_month_title_background = "#F6F6BB"; + set color_month_title_text = "#3D5D2E"; + set color_month_dates = "#000000"; + set color_month_postcount = "#3D5D2E"; + +#NEWLAYER: smoothsailing/fire +layerinfo "redist_uniq" = "smoothsailing/fire"; +layerinfo "type" = "theme"; +layerinfo "name" = "Under Fire"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#95261F"; + set color_header_title_text = "#F5EBC2"; + set color_header_subtitle_text = "#CA6036"; + set color_header_menubar_background = "#CA6036"; + set color_header_menubar_text = "#F5EBC2"; + set color_header_menubar_background_hover = "#DEB450"; + set color_header_menubar_text_hover = "#95261F"; + set color_header_borders = "#F5EBC2"; + + set color_body_links = "#95261F"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#DEB450"; + set color_body_titlebar_text = "#95261F"; + set color_body_footer_background = "#95261F"; + set color_body_footer_text = "#F5EBC2"; + set color_body_background = "#F5EBC2"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#95261F"; + set color_body_entrytitle_background_alternate = "#CA6036"; + set color_body_entrytitle_border = "#DEB450"; + set color_body_entrytitle_text = "#F5EBC2"; + set color_body_entrytitle_links = "#F5EBC2"; + set color_body_entry_background = "#F5EBC2"; + set color_body_entry_userinfo_background = "#F5EBC2"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#95261F"; + set color_month_title_background = "#F5EBC2"; + set color_month_title_text = "#95261F"; + set color_month_dates = "#95261F"; + set color_month_postcount = "#CA6036"; + +#NEWLAYER: smoothsailing/chocolate +layerinfo "redist_uniq" = "smoothsailing/chocolate"; +layerinfo "type" = "theme"; +layerinfo "name" = "Chocolate Caramel Creme"; +layerinfo author_name = "Michael Raffoul"; +layerinfo author_email = "masterslacker@livejournal.com"; + + set color_header_title_background = "#6D4506"; + set color_header_title_text = "#E1D6C0"; + set color_header_subtitle_text = "#CF9B48"; + set color_header_menubar_background = "#A2701F"; + set color_header_menubar_text = "#E1D6C0"; + set color_header_menubar_background_hover = "#CF9B48"; + set color_header_menubar_text_hover = "#E1D6C0"; + set color_header_borders = "#E1D6C0"; + + set color_body_links = "#6D4506"; + set color_body_links_visited = "#000000"; + set color_body_titlebar_background = "#CF9B48"; + set color_body_titlebar_text = "#E1D6C0"; + set color_body_footer_background = "#6D4506"; + set color_body_footer_text = "#E1D6C0"; + set color_body_background = "#E1D6C0"; + set color_body_text = "#000000"; + + set color_body_entrytitle_background = "#A2701F"; + set color_body_entrytitle_background_alternate = "#CF9B48"; + set color_body_entrytitle_border = "#6D4506"; + set color_body_entrytitle_text = "#E1D6C0"; + set color_body_entrytitle_links = "#E1D6C0"; + set color_body_entry_background = "#E1D6C0"; + set color_body_entry_userinfo_background = "#E1D6C0"; + set color_body_entry_text = "#000000"; + + set color_month_borders = "#A2701F"; + set color_month_title_background = "#E1D6C0"; + set color_month_title_text = "#6D4506"; + set color_month_dates = "#6D4506"; + set color_month_postcount = "#A2701F"; diff --git a/local/bin/upgrading/s2layers/tranquility2/layout.s2 b/local/bin/upgrading/s2layers/tranquility2/layout.s2 new file mode 100755 index 0000000..7a5537f --- /dev/null +++ b/local/bin/upgrading/s2layers/tranquility2/layout.s2 @@ -0,0 +1,1342 @@ +# LAYER INFO +layerinfo "redist_uniq" = "tranquilityii/layout"; +layerinfo "type" = "layout"; +layerinfo "name" = "Tranquility II"; +layerinfo "des" = "XHTML/CSS Compliant layout. Relax."; +layerinfo "author_name" = "Matthew Vince"; +layerinfo "lang" = "en"; + + +# PROPERTIES: COLORS +propgroup Colors { + # odd + property Color c_main_border { des = "Border color of main column"; } + property Color c_main_background { des = "Background color of main column"; } + property Color c_menu_border { des = "Border color of menu"; } + property Color c_header_background { des = "Header background color"; } + property Color c_header_border { des = "Header border color"; } + # page + property Color c_page_background { des = "Page background color"; } + property Color c_page_title { des = "Page title color"; } + property Color c_page_text { des = "Page text color"; } + property Color c_page_link { des = "Page link color"; } + property Color c_page_link_visited { des = "Page visited link color"; } + property Color c_page_link_hover { des = "Page hover link color"; } + property Color c_page_link_active { des = "Page active link color"; } + # menu + property Color c_menu_background { des = "Side Menu background color"; } + property Color c_menu_link { des = "Side Menu link color"; } + property Color c_menu_link_visited { des = "Side Menu visited link color"; } + property Color c_menu_link_hover { des = "Side Menu hover link color"; } + property Color c_menu_link_active { des = "Side Menu active link color"; } + property Color c_menu_text_color { des = "Side Menu text color"; } + property Color c_menu_header_color { des = "Side Menu header color"; } + property Color c_menu_current { des = "Current menu item color"; } + # entry + property Color c_entry_background { des = "Entry background color"; } + property Color c_entry_link { des = "Entry link color"; } + property Color c_entry_link_visited { des = "Entry visited link color"; } + property Color c_entry_link_hover { des = "Entry hover link color"; } + property Color c_entry_link_active { des = "Entry active link color"; } + property Color c_entry_text_color { des = "Entry text color"; } + property Color c_entry_title_color { des = "Entry title color"; } + property Color c_entry_border { des = "Entry bottom border color"; } + # metadata + property Color c_meta_background { des = "Entry metadata background color"; } + property Color c_meta_link { des = "Entry metadata link color"; } + property Color c_meta_link_visited { des = "Entry metadata visited link color"; } + property Color c_meta_link_hover { des = "Entry metadata hover link color"; } + property Color c_meta_link_active { des = "Entry metadata active link color"; } + property Color c_meta_text_color { des = "Entry metadata text color"; } + # footer + property Color c_footer_background { des = "Page footer background color"; } + property Color c_footer_link { des = "Page footer link color"; } + property Color c_footer_link_visited { des = "Page footer visited link color"; } + property Color c_footer_link_hover { des = "Page footer hover link color"; } + property Color c_footer_link_active { des = "Page footer active link color"; } + property Color c_footer_text_color { des = "Page footer text color"; } + # comments + property Color c_comment_one_link { des = "Comment one link color"; } + property Color c_comment_one_link_visited { des = "Comment one visited link color"; } + property Color c_comment_one_link_hover { des = "Comment one hover link color"; } + property Color c_comment_one_link_active { des = "Comment one active link color"; } + property Color c_comment_one_text_color { des = "Comment one text color"; } + property Color c_comment_one_title_color { des = "Comment one title color"; } + property Color c_comment_one_background { des = "Comment bar one background color"; } + property Color c_comment_one_border { des = "Comment one bottom border color"; } + property Color c_comment_two_link { des = "Comment two link color"; } + property Color c_comment_two_link_visited { des = "Comment two visited link color"; } + property Color c_comment_two_link_hover { des = "Comment two hover link color"; } + property Color c_comment_two_link_active { des = "Comment two active link color"; } + property Color c_comment_two_text_color { des = "Comment two text color"; } + property Color c_comment_two_title_color { des = "Comment two title color"; } + property Color c_comment_two_background { des = "Comment two background color"; } + property Color c_comment_two_border { des = "Comment two bottom border color"; } + property Color c_comment_screened_link { des = "Comment screened link color"; } + property Color c_comment_screened_link_visited { des = "Comment screened visited link color"; } + property Color c_comment_screened_link_hover { des = "Comment screened hover link color"; } + property Color c_comment_screened_link_active { des = "Comment screened active link color"; } + property Color c_comment_screened_text_color { des = "Comment screened text color"; } + property Color c_comment_screened_title_color { des = "Comment screened title color"; } + property Color c_comment_screened_background { des = "Comment screened background color"; } + property Color c_comment_screened_border { des = "Comment screened bottom border color"; } +} + + +# PROPERTIES: FONTS +propgroup Fonts { + # page + property string f_page { des = "Generic font for use on the page"; } + property string f_page_size { des = "Generic font size for use on the page"; } + property string f_page_title { des = "Page title font"; } + property string f_page_title_size { des = "Page title font size"; } + property string f_page_link { des = "Generic font for links on the page"; } + property string f_page_link_size { des = "Generic font size for links on the page"; } + # menu + property string f_menu_link { des = "Menu link font"; } + property string f_menu_link_size { des = "Menu link font size"; } + property string f_menu { des = "Menu font"; } + property string f_menu_size { des = "Menu font size"; } + property string f_menu_header { des = "Menu title font"; } + property string f_menu_header_size { des = "Menu title font size"; } + property string f_menu_current { des = "Current menu item font"; } + property string f_menu_current_size { des = "Current menu item font size"; } + # entry + property string f_entry { des = "Entry font"; } + property string f_entry_size { des = "Entry font size"; } + property string f_entry_link { des = "Entry link font"; } + property string f_entry_link_size { des = "Entry link font size"; } + property string f_entry_title { des = "Entry title font"; } + property string f_entry_title_size { des = "Entry title font size"; } + # metadata + property string f_meta { des = "Entry metadata font"; } + property string f_meta_size { des = "Entry metadata font size"; } + property string f_meta_link { des = "Entry metadata link font"; } + property string f_meta_link_size { des = "Entry metadata link font size"; } + # footer + property string f_footer { des = "Footer font"; } + property string f_footer_size { des = "Footer font size"; } + property string f_footer_link { des = "Footer link font"; } + property string f_footer_link_size { des = "Footer link font size"; } + # comments + property string f_comment { des = "Comment font"; } + property string f_comment_size { des = "Comment font size"; } + property string f_comment_title { des = "Comment title font"; } + property string f_comment_title_size { des = "Comment title font size"; } + property string f_comment_link { des = "Comment link font"; } + property string f_comment_link_size { des = "Comment link font size"; } +} + + +# PROPERTIES: PRESENTATION +propgroup Presentation { + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; } + property string time_format { des = "Format for the time"; example = "%%hh%%:%%min%%:%%sec%% %%a%%m"; } + property string date_format { des = "Format for the date"; example = "%%m%%/%%d%%/%%yy%%"; } + property bool menu_disable_summary { des = "Disable menu summary view"; } + property string css_page_width { des = "Width of the main page (increasing this will increase the main column's width)"; } + property string css_style_overrides { des = "include any CSS here to override the default CSS"; } +} + + +# PROPERTIES: TEXT +propgroup Text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_reply_nocomments_header; + property use text_reply_nocomments; + property use text_comment_from; + property use text_comment_ipaddr; + property use text_comment_parent; + property use text_comment_reply; + property use text_comment_thread; + property use text_nosubject; + property use text_post_comment; + property use text_post_comment_friends; + property use text_max_comments; + property use text_view_month; + property string text_comment_anonymous { des = "Text to substitute for anonymous commenters"; } + property string text_comment_viewall { des = "Text for view all comments"; } + property string text_links_header { des = "Sidebar links header text"; } + property string text_summary_header { des = "Page summary text header"; } + property string text_links_spacer { des = "String to act as links list spacer";} +} + + +# ------------------------------- +# default property settings +# ------------------------------- +# ODD +set c_main_border = "#000"; +set c_main_background = "#fff"; +set c_menu_border = "#333"; +set c_header_background = "#333"; +set c_header_border = "#333"; +set c_page_title = "#fff"; +set c_page_background = "#333"; +set c_page_text = "#333"; +set c_page_link = "#5ab300"; +set c_page_link_visited = "#5ab300"; +set c_page_link_hover = "#336600"; +set c_page_link_active = "#336600"; +set c_menu_background = "#333"; +set c_menu_link = "#999"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#fff"; +set c_menu_link_active = "#fff"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#fff"; +set c_entry_background = "#fff"; +set c_entry_link = "#5ab300"; +set c_entry_link_visited = "#5ab300"; +set c_entry_link_hover = "#336600"; +set c_entry_link_active = "#336600"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#333"; +set c_entry_border = "#ccc"; +set c_meta_background = "#fff"; +set c_meta_link = "#5ab300"; +set c_meta_link_visited = "#5ab300"; +set c_meta_link_hover = "#336600"; +set c_meta_link_active = "#336600"; +set c_meta_text_color = "#000"; +set c_footer_background = "#333"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#5ab300"; +set c_comment_one_link_visited = "#5ab300"; +set c_comment_one_link_hover = "#336600"; +set c_comment_one_link_active = "#336600"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#333"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#5ab300"; +set c_comment_two_link_visited = "#5ab300"; +set c_comment_two_link_hover = "#336600"; +set c_comment_two_link_active = "#336600"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#333"; +set c_comment_two_background = "#fff"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#708CC4"; +set c_comment_screened_link_visited = "#5ab300"; +set c_comment_screened_link_hover = "#336600"; +set c_comment_screened_link_active = "#336600"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#333"; +set c_comment_screened_background = "#fff"; +set c_comment_screened_border = "#999"; + +# FONTS +set f_page = "Georgia, serif"; +set f_page_title = "Georgia, serif"; +set f_page_title_size = "190%"; +set f_page_size = "12px"; +set f_page_link = "Georgia, serif"; +set f_page_link_size = "100%"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu_link_size = "80%"; +set f_menu = "Georgia, serif"; +set f_menu_size = "100%"; +set f_menu_header = "Georgia, serif"; +set f_menu_header_size = "120%"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_menu_current_size = "80%"; +set f_entry = "Georgia, serif"; +set f_entry_size = "100%"; +set f_entry_link = "Georgia, serif"; +set f_entry_link_size = "100%"; +set f_entry_title = "Georgia, serif"; +set f_entry_title_size = "150%"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_size = "80%"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_meta_link_size = "100%"; +set f_footer = "Georgia, serif"; +set f_footer_size = "100%"; +set f_footer_link = "Georgia, serif"; +set f_footer_link_size = "100%"; +set f_comment = "Georgia, serif"; +set f_comment_size = "100%"; +set f_comment_title = "Georgia, serif"; +set f_comment_title_size = "130%"; +set f_comment_link = "Georgia, serif"; +set f_comment_link_size = "100%"; + +# OTHER +set show_entrynav_icons = true; +set time_format = "%%hh%%:%%min%% %%a%%m"; +set date_format = "%%mon%%. %%dayord%%, %%yyyy%%"; +set menu_disable_summary = false; +set css_style_overrides = ""; +set css_page_width = "800px"; + +# TEXT +set text_meta_music = "music"; +set text_links_header = "links"; +set text_meta_mood = "mood"; +set text_read_comments = "{#}"; +set text_read_comments_friends = "{#}"; +set text_comment_anonymous = "anonymous"; +set text_comment_viewall = "view all comments"; +set text_links_header = "Links"; +set text_summary_header = "Page Summary"; +set text_links_spacer = "_______________"; + + + +# ======================================== +# METHODS +# ======================================== + + +# ------------------------------- +# stylesheet +# ------------------------------- +function print_stylesheet ( ) +{ + """ + @media screen, print { + * { + margin: 0; + padding: 0; + } + hr { + display: none; + } + body { + background-color: $*c_page_background; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + text-align: center; + } + a { + font-family: $*f_page_link; + font-size: $*f_page_link_size; + color: $*c_page_link; + text-decoration: none; + } + a:visited { color: $*c_page_link_visited; } + a:hover, a:visited:hover { color: $*c_page_link_hover; text-decoration: underline; } + a:active { color: $*c_page_link_active; } + a img { border: none; } + a.comm { + background: transparent url(http://stat.livejournal.com/img/community.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + a.user { + background: transparent url(http://stat.livejournal.com/img/userinfo.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + p { + margin: 5px; + padding: 5px; + } + + form { + display: inline; + margin: 0px; + padding: 0px; + } + input, select, textarea { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + padding: 2px; + margin: 3px; + } + + #container { + position: relative; + width: $*css_page_width; + margin: 0 auto; + text-align: left; + } + #header { + margin-bottom: 15px; + border: 1px solid $*c_header_border; + background-color: $*c_header_background; + } + + #header h1 { + padding: 20px; + font-family: $*f_page_title; + font-size: $*f_page_title_size; + color: $*c_page_title; + } + + #menu { + position: relative; + background-color: $*c_menu_background; + float: left; + width: 150px; + font-family: $*f_menu; + font-size: $*f_menu_size; + color: $*c_menu_text_color; + border: 1px solid $*c_menu_border; + padding: 4px; + } + #content { + position: relative; + margin-left: 160px; + } + + #entries { + border: 1px solid $*c_main_border; + padding: 15px; + background-color: $*c_main_background; + } + + #menu h2 { + margin: 20px 0; + font-family: $*f_menu_header; + font-size: $*f_menu_header_size; + color: $*c_menu_header_color; + } + #menu h2.userpic { + text-align: center; + } + #menu a { + font-family: $*f_menu_link; + font-size: $*f_menu_link_size; + color: $*c_menu_link; + } + #menu a:visited { color: $*c_menu_link_visited; } + #menu a:hover, #menu a:visited:hover { color: $*c_menu_link_hover; } + #menu a:active { color: $*c_menu_link_active; } + #menu ul { + margin: 3px; + list-style: none; + } + #menu ul li { + margin: 3px; + padding: 2px; + list-style: none; + } + #menu ul li.active { + font-family: $*f_menu_current; + font-size: $*f_menu_current_size; + color: $*c_menu_current; + font-weight: bold; + } + #content h2 { + margin: 20px 0; + } + #entries, #comments { + margin: 10px; + } + .ind-entry { + padding: 5px; + padding-bottom: 15px; + border-bottom: 1px solid $*c_entry_border; + background-color: $*c_entry_background; + } + .ind-entry h3 img, .ind-comment-one h3 img, .ind-comment-two h3 img, .ind-comment-screened h3 img { + position: relative; + float: right; + padding: 5px; + } + .ind-entry h2 { + font-family: $*f_entry_title; + font-size: $*f_entry_title_size; + color: $*c_entry_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-entry h4, .ind-comment-one h4, .ind-comment-two h4, .ind-comment-screened h4 { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + } + .ind-entry h4 { + background-color: $*c_meta_background; + } + .ind-entry h4 a, .ind-comment-one h4 a, .ind-comment-two h4 a, .ind-comment-screened h4 a { + font-family: $*f_meta_link; + font-size: $*f_meta_link_size; + color: $*c_meta_link; + text-decoration: underline; + } + .ind-entry h4 a:visited, .ind-comment-one h4 a:visited, .ind-comment-two h4 a:visited, .ind-comment-screened h4 a:visited { color: $*c_meta_link_visited; } + .ind-entry h4 a:hover, .ind-comment-one h4 a:hover, .ind-comment-two h4 a:hover, .ind-comment-screened h4 a:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:visited:hover, .ind-comment-one h4 a:visited:hover, .ind-comment-two h4 a:visited:hover, .ind-comment-screened h4 a:visited:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:active, .ind-comment-one h4 a:active, .ind-comment-two h4 a:active, .ind-comment-screened h4 a:active { color: $*c_meta_link_active; } + .ind-entry div.entry-item, .ind-entry div.month-entries { + font-family: $*f_entry; + font-size: $*f_entry_size; + color: $*c_entry_text_color; + margin: 15px 0px; + } + .ind-entry div.entry-item a, .ind-entry div.month-entries a { + font-family: $*f_entry_link; + font-size: $*f_entry_link_size; + color: $*c_entry_link; + text-decoration: underline; + } + .ind-entry div.entry-item a:visited, .ind-entry div.month-entries a:visited { color: $*c_entry_link_visited; } + .ind-entry div.entry-item a:hover, .ind-entry div.entry-item a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.month-entries a:hover, .ind-entry div.month-entries a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.entry-item a:active, .ind-entry div.month-entries a:active { color: $*c_entry_link_active; } + + .ind-comment-one, .ind-comment-two, .ind-comment-screened { + margin: 10px 0; + padding: 5px; + } + .ind-comment-one { background-color: $*c_comment_one_background; border-bottom: 1px solid $*c_comment_one_border; } + .ind-comment-two { background-color: $*c_comment_two_background; border-bottom: 1px solid $*c_comment_two_border; } + .ind-comment-screened { background-color: $*c_comment_screened_background; border-bottom: 1px solid $*c_comment_screened_border; } + + .ind-comment-one h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_one_title_color; + margin: 20px 0px; + } + .ind-comment-one div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_one_text_color; + margin: 15px 0px; + } + .ind-comment-one div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_one_link; + text-decoration: underline; + } + .ind-comment-one div.entry-item a:visited { color: $*c_comment_one_link_visited; } + .ind-comment-one div.entry-item a:hover, .ind-comment-one div.entry-item a:visited:hover { color: $*c_comment_one_link_hover; } + .ind-comment-one div.entry-item a:active { color: $*c_comment_one_link_active; } + + .ind-comment-two h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_two_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-comment-two div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_two_text_color; + margin: 10px 0px; + } + .ind-comment-two div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_two_link; + text-decoration: underline; + } + .ind-comment-two div.entry-item a:visited { color: $*c_comment_two_link_visited; } + .ind-comment-two div.entry-item a:hover, .ind-comment-two div.entry-item a:visited:hover { color: $*c_comment_two_link_hover; } + .ind-comment-two div.entry-item a:active { color: $*c_comment_two_link_active; } + + .ind-comment-screened h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_screened_title_color; + margin: 20px 0px; + } + .ind-comment-screened div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_screened_text_color; + margin: 10px 0px; + } + .ind-comment-screened div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_screened_link; + text-decoration: underline; + } + .ind-comment-screened div.entry-item a:visited { color: $*c_comment_screened_link_visited; } + .ind-comment-screened div.entry-item a:hover, .ind-comment-screened div.entry-item a:visited:hover { color: $*c_comment_screened_link_hover; } + .ind-comment-screened div.entry-item a:active { color: $*c_comment_screened_link_active; } + + .month-entries { + margin: 10px 0; + } + .month-entries ul { + list-style: none; + margin: 10px; + } + .month-entries ul li { + list-style: none; + padding: 3px; + } + + + #footer { + position: relative; + font-family: $*f_footer; + font-size: $*f_footer_size; + color: $*c_footer_text_color; + background-color: $*c_footer_background; + } + #footer p { + padding: 20px; + } + #footer a { + font-family: $*f_footer_link; + font-size: $*f_footer_link_size; + color: $*c_footer_link; + } + #footer a:visited { color: $*c_footer_link_visited; } + #footer a:hover, #footer a:visited:hover { color: $*c_footer_link_hover; } + #footer a:active { color: $*c_footer_link_active; } + } + + @media print { + #menu { + display: none; + } + #content { + margin-left: 0px; + } + #entries, .ind-entry, .ind-comment, #footer, #header { + border: none; + } + + } + + $*css_style_overrides + + """; +} + + +# ------------------------------- +# user pic main page +# ------------------------------- +function Page::lay_top_userpic ( ) +{ + var Image up_img = $.journal.default_pic; + if ( defined $up_img ) { + print "

    \"$.journal.name\"

    "; + } +} + + +# ------------------------------- +# returns a permalink link based on +# the url passed +# ------------------------------- +function get_permalink ( string url ) : string +{ + return("$*text_permalink"); +} + + +# ------------------------------- +# prints the user's 'link-list' +# ------------------------------- +function Page::print_linklist ( ) +{ + if ( size $.linklist > 0 ) { + print "

    $*text_links_header

    "; + print "
      "; + foreach var UserLink l ( $.linklist ) { + if ( $l.title == "spacer" ) { + print "
    • $*text_links_spacer
    • "; + } elseif ($l.is_heading) { + print "
    • $l.title
    • "; + } elseif ( $l.title ) { + print "
    • $l.title
    • "; + } + } + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# prints the LJ specific links (recent, friends, etc) +# ------------------------------- +function print_lj_links ( Page p ) +{ + var string links; + $links = $links + ($p.view == "recent" ? "
  • $*text_view_recent
  • " : "
  • $*text_view_recent
  • "); + if ( $p.journal_type == "C" ) { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends_comm
  • " : "
  • $*text_view_friends_comm
  • "); + } else { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends
  • " : "
  • $*text_view_friends
  • "); + } + $links = $links + ($p.view == "archive" ? "
  • $*text_view_archive
  • " : "
  • $*text_view_archive
  • "); + $links = $links + "
  • $*text_view_userinfo
  • "; + $links = $links + ($p.journal.website_url != "" ? "
  • lower() + "\">" + $p.journal.website_name->lower() + "
  • " : ""); + + print "
      "; + print $links; + print "
    "; + print "
    "; +} + +function Page::lay_sidebar_view_summary() : string +{ + return(""); +} + + +# ------------------------------- +# main page layout +# ------------------------------- +function Page::print ( ) +{ + var string title = $this->title(); + + # generate page id: + var string current_view = $.view; + if ( $.view == "month" or $.view == "day" ) { + $current_view = "archive"; + } + if ( $.view == "entry" or $.view == "reply" ) { + $current_view = "recent"; + } + + # begin main page html: + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + $this->print_head(); + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$title\n"; + print "\n"; + print "\n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    $title

    \n"; + print "
    "; + print "
    \n"; + print "
    \n"; + print "
    \n"; + $this->lay_top_userpic(); + print "\n"; + print_lj_links($this); + print($this->lay_sidebar_view_summary()); + $this->print_linklist(); + print "
    \n"; + print "
    \n"; + $this->print_body(); + print "
    \n"; + print "
    \n"; + print "\n"; + print "\n"; +} + + +# ------------------------------- +# main page display entries and +# footer +# ------------------------------- +function RecentPage::print_body ( ) +{ + # print all entries + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + + var string range = "most recent entries"; + if ( $.nav.skip > 0 ) { + $range = "$.nav.skip entries back"; + } + + print "

    "; + print "viewing: $range
    "; + # go forward/backward if possible + if ( $.nav.forward_url != "" or $.nav.backward_url != "" ) { + var string sep; + var string back; + var string forward; + if ( $.nav.backward_url != "" ) { + $back = "earlier"; + } + if ( $.nav.forward_url != "" ) { + $forward = "later"; + } + if ( $back != "" and $forward != "" ) { + $sep = " | "; + } + print "go: $back$sep$forward
    "; + } + print "

    "; +} + + +# ------------------------------- +# entry view (show comments) +# ------------------------------- +function EntryPage::print_body ( ) +{ + print "
    \n"; + $this->print_entry ( $.entry ); + if ( $.entry.comments.enabled ) { + print "

    Comments {$.entry.comments.count}

    "; + print "
    "; + if ( $.comment_pages.total_subitems > 0 ) { + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + $.comment_pages->print(); + $this->print_comments($.comments); + if ( $this.multiform_on ) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } + print "
    "; + } + print "
    "; + print "

    "; + print "$*text_post_comment\n"; + print "

    "; +} + + +# ------------------------------- +# day view +# ------------------------------- +function DayPage::print_body ( ) +{ + if ( not $.has_entries ) { + print "
    \n"; + print "
    \n"; + print "

    " + $.date->date_format("long") + "

    "; + print "

    $*text_noentries_day

    "; + print "
    "; + print "
    "; + print "
    "; + } else { + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + print "

    "; + print "« $*text_day_prev | $*text_day_next »"; + print "

    "; +} + + +# ------------------------------- +# year view +# ------------------------------- +function YearPage::print_body ( ) +{ + print "
    \n"; + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print "
    "; +} + + +# ------------------------------- +# page summary for recent page +# ------------------------------- +function RecentPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for day page +# ------------------------------- +function DayPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for entry page +# ------------------------------- +function EntryPage::lay_sidebar_view_summary() : string { + var string return; + if ( not $*menu_disable_summary ) { + foreach var Comment c ( $.comments ) { + if ( $c.depth == 1 ) { + $return = $return + "
  • " + ($c.subject != "" ? "$c.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# display an entry (all views ) +# ------------------------------- +function print_entry ( Page p, Entry e ) +{ + # get date/time + var string datetime; + $datetime = $e.time->date_format($*date_format) + " | " + $e.time->time_format($*time_format); + + # get metadata + var string metadata; + if ( $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string text = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $text = $*text_meta_mood; + } elseif ( $k == "music" ) { + $text = $*text_meta_music; + } + if ( $k == "mood" and defined $e.mood_icon ) { + var Image i = $e.mood_icon; + $val = "\"$val\" $val"; + } + $metadata = "$metadata\n$text: $val
    "; + } + } + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( $p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username ) { + if ( $e.poster.username != $e.journal.username ) { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username in base_url() + "\" title=\"$e.journal.username\" >$e.journal.username"; + } else { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username"; + } + $poster = "posted by: $poster"; + if ( defined $e.userpic ) { + $userpic = "

    \"$e.journal.username\"

    "; + } + } + + # print the entry now: + print "
    "; + + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + + print "

    "; + if ( $e.security != "" ) { + $e.security_icon->print(); + print " "; + } + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + print "

    "; + + print "

    "; + if ( $p.view == "entry" and $*show_entrynav_icons ) { + var string item_link = ""; + foreach var string key (["nav_prev","nav_next"]) { + var Link link = $e->get_link($key); + if ( $link ) { + if ( $key == "nav_prev" ) { + $item_link = $item_link + "lower() + "\">« " + $link.caption->lower() + " | "; + } elseif ( $key == "nav_next" ) { + $item_link = $item_link + "lower() + "\">" + $link.caption->lower() + " »"; + } + } + } + print $item_link; + print "
    "; + } + print "$datetime
    "; + print "$metadata"; + if ( $poster != "" ) { + print "$poster"; + } + print "

    "; + + print "
    $e.text
    \n"; + + print "

    "; + print get_permalink($e.permalink_url); + if ( $p.view != "entry" and $p.view != "reply" ) { + print " | "; + $e.comments->print(); + } elseif ( $e.comments.enabled ) { + print " | "; + $e.comments->print_postlink(); + } + var Link tmp; + if ( viewer_is_owner() and $p.view != "friends" ) { + $tmp = $e->get_link("edit_entry"); + print " | $tmp.caption"; + } + $tmp = $e->get_link("mem_add"); + print " | $tmp.caption"; + print "

    "; + print "
    "; + print "
    "; +} + + +# ------------------------------- +# entry wrapper for main page +# ------------------------------- +function Page::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# entry wrapper for friends page +# ------------------------------- +function FriendsPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +function EntryPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# comments +# ------------------------------- +function CommentInfo::print ( ) +{ + if ( not $.enabled ) { + return; + } + + $this->print_postlink(); + if ( $.count > 0 or $.screened ) { + print " "; + print ""; + $this->print_readlink(); + print ""; + } +} + + +# ------------------------------- +# comment post link +# ------------------------------- +function CommentInfo::print_postlink ( ) +{ + var Page p = get_page(); + var string linktext = ( $p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment ); + if ( $.maxcomments ) { + "$*text_max_comments"; + } else { + "$linktext"; + } +} + + +# ------------------------------- +# print comment +# ------------------------------- +function EntryPage::print_comment ( Comment c ) +{ + var string comment_class = ""; + if ( $c.screened ) { + $comment_class = "ind-comment-screened"; + } elseif ( $c.depth % 2 == 0 ) { + $comment_class = "ind-comment-two"; + } else { + $comment_class = "ind-comment-one"; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_comment_anonymous"; + var string poster_text = defined $c.poster ? $c.poster.name : "$*text_comment_anonymous"; + var string sub_icon; + var int indent = (($c.depth - 1) * 5); + if ( defined $c.subject_icon ) { + $sub_icon = $c.subject_icon->as_string(); + } + + print "
    \n"; + + var string userpic; + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + $userpic = "

    \"$poster_text\"

    "; + } + var string commentdate = $c.time->date_format($*date_format) + " - " + $c.time->time_format($*time_format); + + #userpic + print "$userpic\n"; + + # subject: + if ( $c.subject == "" ) { + print "

    $c.subject_icon $*text_nosubject

    "; + } else { + print "

    $c.subject_icon $c.subject

    "; + } + + print "

    "; + print "from: $poster
    \n"; + print "date: $commentdate
    \n"; + if ( $c.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $c.metadata{"poster_ip"} + "
    "; + } + print get_permalink($c.permalink_url) + "
    \n"; + var Link lnk; + $lnk = $c->get_link("delete_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("screen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("unscreen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + print "

    \n"; + + if ( $this.multiform_on ) { + print ""; + $c->print_multiform_check(); + } + + print "
    $c.text
    \n"; + print "

    "; + print "$*text_comment_reply"; + if ( $c.parent_url != "" ) { print " | $*text_comment_parent"; } + if ( $c.thread_url != "" ) { print " | $*text_comment_thread"; } + print "

    "; + print "
    \n\n"; + print "
    "; +} + + +# ------------------------------- +# print reply form page +# ------------------------------- +function ReplyPage::print_body ( ) +{ + if ( not $.entry.comments.enabled ) { + print "
    \n"; + print "
    "; + print "

    $*text_reply_nocomments_header

    "; + print "$*text_reply_nocomments"; + print "
    "; + print "
    "; + + } else { + print "
    \n"; + + # get date + var string datetime; + $datetime = $.replyto.time->date_format($*date_format) + " | " + $.replyto.time->time_format($*time_format); + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( defined $.replyto.poster ) { + $poster = "base_url() + "\" title=\"$.replyto.poster.username\">$.replyto.poster.username"; + if ( defined $.replyto.userpic ) { + $userpic = "

    \"$.replyto.poster.username\"

    "; + } + } else { + $poster = "$*text_comment_anonymous"; + } + + + # print the entry now: + print "
    "; + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + print "

    "; + if ( $.replyto.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$.replyto.subject"; + } + print "

    "; + + print "

    \n"; + print "$datetime
    "; + print "$*text_comment_from: $poster"; + if ( $.replyto.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $.replyto.metadata{"poster_ip"} + "
    "; + } + print "

    "; + print "
    $.replyto.text
    \n"; + print "

    "; + print get_permalink($.replyto.permalink_url) + " | $*text_comment_viewall\n"; + print "

    "; + print "
    \n"; + print "
    "; + print "
    \n"; + print "

    Reply

    \n"; + $.form->print(); + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# print available years +# ------------------------------- +function YearPage::print_year_links ( ) +{ + print "

    "; + print "available years:
    "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + print "$y.year "; + } else { + print "$y.year "; + } + } + print "

    "; +} + + +# ------------------------------- +# print available month +# ------------------------------- +function YearPage::print_month ( YearMonth m ) +{ + if ( not $m.has_entries ) { + return; + } + + print "
    \n"; + print "

    " + $m->month_format() + "

    \n"; + print "

    $*text_view_month

    "; + print "
    "; + foreach var YearWeek w ( $m.weeks ) { + foreach var YearDay d ( $w.days ) { + if ( $d.num_entries > 0 ) { + var string date = $d.date->date_format("%%dayord%%"); + print "$date {$d.num_entries}
    \n"; + } + } + } + print "
    \n"; + print "
    \n"; + print "
    "; +} + + +# ------------------------------- +# month view +# ------------------------------- +function MonthPage::print_body ( ) +{ + print "
    "; + print "
    \n"; + print "

    " + $.date->date_format($*lang_fmt_month_long) + "

    "; + + print "
    "; + $.redir->print_hiddens(); + if ( $.prev_url != "" ) { + print "[«]\n"; + } + if ( size $.months > 1 ) { + print "\n"; + } + if ( $.next_url != "" ) { + print "\n[»]\n"; + } + print "


    "; + + # print dates: + foreach var MonthDay d ( $.days ) { + if ( $d.has_entries ) { + print "
    \n"; + print "" + lang_ordinal($d.day) + "
    "; + print "
      "; + foreach var Entry e ( $d.entries ) { + print "
    • "; + print "" + $e.time->time_format("short") + " "; + if ( $e.poster.username != $e.journal.username ) { + $e.poster->print(); " : "; + } + "$e.security_icon "; + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + if ( $e.comments.count > 0 ) { + print " {" + $e.comments.count + "}"; + } + print "
    • "; + } + print "
    "; + print "
    "; + print "
    "; + } + } + print "
    \n"; + print "
    "; +} + diff --git a/local/bin/upgrading/s2layers/tranquilityii/layout.s2 b/local/bin/upgrading/s2layers/tranquilityii/layout.s2 new file mode 100755 index 0000000..10a0546 --- /dev/null +++ b/local/bin/upgrading/s2layers/tranquilityii/layout.s2 @@ -0,0 +1,1341 @@ +# LAYER INFO +layerinfo "redist_uniq" = "tranquilityii/layout"; +layerinfo "type" = "layout"; +layerinfo "name" = "Tranquility II"; +layerinfo "des" = "XHTML/CSS Compliant layout. Relax."; +layerinfo "author_name" = "Matthew Vince"; +layerinfo "lang" = "en"; + + +# PROPERTIES: COLORS +propgroup Colors { + # odd + property Color c_main_border { des = "Border color of main column"; } + property Color c_main_background { des = "Background color of main column"; } + property Color c_menu_border { des = "Border color of menu"; } + property Color c_header_background { des = "Header background color"; } + property Color c_header_border { des = "Header border color"; } + # page + property Color c_page_background { des = "Page background color"; } + property Color c_page_title { des = "Page title color"; } + property Color c_page_text { des = "Page text color"; } + property Color c_page_link { des = "Page link color"; } + property Color c_page_link_visited { des = "Page visited link color"; } + property Color c_page_link_hover { des = "Page hover link color"; } + property Color c_page_link_active { des = "Page active link color"; } + # menu + property Color c_menu_background { des = "Side Menu background color"; } + property Color c_menu_link { des = "Side Menu link color"; } + property Color c_menu_link_visited { des = "Side Menu visited link color"; } + property Color c_menu_link_hover { des = "Side Menu hover link color"; } + property Color c_menu_link_active { des = "Side Menu active link color"; } + property Color c_menu_text_color { des = "Side Menu text color"; } + property Color c_menu_header_color { des = "Side Menu header color"; } + property Color c_menu_current { des = "Current menu item color"; } + # entry + property Color c_entry_background { des = "Entry background color"; } + property Color c_entry_link { des = "Entry link color"; } + property Color c_entry_link_visited { des = "Entry visited link color"; } + property Color c_entry_link_hover { des = "Entry hover link color"; } + property Color c_entry_link_active { des = "Entry active link color"; } + property Color c_entry_text_color { des = "Entry text color"; } + property Color c_entry_title_color { des = "Entry title color"; } + property Color c_entry_border { des = "Entry bottom border color"; } + # metadata + property Color c_meta_background { des = "Entry metadata background color"; } + property Color c_meta_link { des = "Entry metadata link color"; } + property Color c_meta_link_visited { des = "Entry metadata visited link color"; } + property Color c_meta_link_hover { des = "Entry metadata hover link color"; } + property Color c_meta_link_active { des = "Entry metadata active link color"; } + property Color c_meta_text_color { des = "Entry metadata text color"; } + # footer + property Color c_footer_background { des = "Page footer background color"; } + property Color c_footer_link { des = "Page footer link color"; } + property Color c_footer_link_visited { des = "Page footer visited link color"; } + property Color c_footer_link_hover { des = "Page footer hover link color"; } + property Color c_footer_link_active { des = "Page footer active link color"; } + property Color c_footer_text_color { des = "Page footer text color"; } + # comments + property Color c_comment_one_link { des = "Comment one link color"; } + property Color c_comment_one_link_visited { des = "Comment one visited link color"; } + property Color c_comment_one_link_hover { des = "Comment one hover link color"; } + property Color c_comment_one_link_active { des = "Comment one active link color"; } + property Color c_comment_one_text_color { des = "Comment one text color"; } + property Color c_comment_one_title_color { des = "Comment one title color"; } + property Color c_comment_one_background { des = "Comment bar one background color"; } + property Color c_comment_one_border { des = "Comment one bottom border color"; } + property Color c_comment_two_link { des = "Comment two link color"; } + property Color c_comment_two_link_visited { des = "Comment two visited link color"; } + property Color c_comment_two_link_hover { des = "Comment two hover link color"; } + property Color c_comment_two_link_active { des = "Comment two active link color"; } + property Color c_comment_two_text_color { des = "Comment two text color"; } + property Color c_comment_two_title_color { des = "Comment two title color"; } + property Color c_comment_two_background { des = "Comment two background color"; } + property Color c_comment_two_border { des = "Comment two bottom border color"; } + property Color c_comment_screened_link { des = "Comment screened link color"; } + property Color c_comment_screened_link_visited { des = "Comment screened visited link color"; } + property Color c_comment_screened_link_hover { des = "Comment screened hover link color"; } + property Color c_comment_screened_link_active { des = "Comment screened active link color"; } + property Color c_comment_screened_text_color { des = "Comment screened text color"; } + property Color c_comment_screened_title_color { des = "Comment screened title color"; } + property Color c_comment_screened_background { des = "Comment screened background color"; } + property Color c_comment_screened_border { des = "Comment screened bottom border color"; } +} + + +# PROPERTIES: FONTS +propgroup Fonts { + # page + property string f_page { des = "Generic font for use on the page"; } + property string f_page_size { des = "Generic font size for use on the page"; } + property string f_page_title { des = "Page title font"; } + property string f_page_title_size { des = "Page title font size"; } + property string f_page_link { des = "Generic font for links on the page"; } + property string f_page_link_size { des = "Generic font size for links on the page"; } + # menu + property string f_menu_link { des = "Menu link font"; } + property string f_menu_link_size { des = "Menu link font size"; } + property string f_menu { des = "Menu font"; } + property string f_menu_size { des = "Menu font size"; } + property string f_menu_header { des = "Menu title font"; } + property string f_menu_header_size { des = "Menu title font size"; } + property string f_menu_current { des = "Current menu item font"; } + property string f_menu_current_size { des = "Current menu item font size"; } + # entry + property string f_entry { des = "Entry font"; } + property string f_entry_size { des = "Entry font size"; } + property string f_entry_link { des = "Entry link font"; } + property string f_entry_link_size { des = "Entry link font size"; } + property string f_entry_title { des = "Entry title font"; } + property string f_entry_title_size { des = "Entry title font size"; } + # metadata + property string f_meta { des = "Entry metadata font"; } + property string f_meta_size { des = "Entry metadata font size"; } + property string f_meta_link { des = "Entry metadata link font"; } + property string f_meta_link_size { des = "Entry metadata link font size"; } + # footer + property string f_footer { des = "Footer font"; } + property string f_footer_size { des = "Footer font size"; } + property string f_footer_link { des = "Footer link font"; } + property string f_footer_link_size { des = "Footer link font size"; } + # comments + property string f_comment { des = "Comment font"; } + property string f_comment_size { des = "Comment font size"; } + property string f_comment_title { des = "Comment title font"; } + property string f_comment_title_size { des = "Comment title font size"; } + property string f_comment_link { des = "Comment link font"; } + property string f_comment_link_size { des = "Comment link font size"; } +} + + +# PROPERTIES: PRESENTATION +propgroup Presentation { + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; } + property string time_format { des = "Format for the time"; example = "%%hh%%:%%min%%:%%sec%% %%a%%m"; } + property string date_format { des = "Format for the date"; example = "%%m%%/%%d%%/%%yy%%"; } + property bool menu_disable_summary { des = "Disable menu summary view"; } + property string css_page_width { des = "Width of the main page (increasing this will increase the main column's width)"; } + property string css_style_overrides { des = "include any CSS here to override the default CSS"; } +} + + +# PROPERTIES: TEXT +propgroup Text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_reply_nocomments_header; + property use text_reply_nocomments; + property use text_comment_from; + property use text_comment_ipaddr; + property use text_comment_parent; + property use text_comment_reply; + property use text_comment_thread; + property use text_nosubject; + property use text_post_comment; + property use text_post_comment_friends; + property use text_max_comments; + property use text_view_month; + property string text_comment_anonymous { des = "Text to substitute for anonymous commenters"; } + property string text_comment_viewall { des = "Text for view all comments"; } + property string text_links_header { des = "Sidebar links header text"; } + property string text_summary_header { des = "Page summary text header"; } + property string text_links_spacer { des = "String to act as links list spacer";} +} + + +# ------------------------------- +# default property settings +# ------------------------------- +# ODD +set c_main_border = "#000"; +set c_main_background = "#fff"; +set c_menu_border = "#333"; +set c_header_background = "#333"; +set c_header_border = "#333"; +set c_page_title = "#fff"; +set c_page_background = "#333"; +set c_page_text = "#333"; +set c_page_link = "#5ab300"; +set c_page_link_visited = "#5ab300"; +set c_page_link_hover = "#336600"; +set c_page_link_active = "#336600"; +set c_menu_background = "#333"; +set c_menu_link = "#999"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#fff"; +set c_menu_link_active = "#fff"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#fff"; +set c_entry_background = "#fff"; +set c_entry_link = "#5ab300"; +set c_entry_link_visited = "#5ab300"; +set c_entry_link_hover = "#336600"; +set c_entry_link_active = "#336600"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#333"; +set c_entry_border = "#ccc"; +set c_meta_background = "#fff"; +set c_meta_link = "#5ab300"; +set c_meta_link_visited = "#5ab300"; +set c_meta_link_hover = "#336600"; +set c_meta_link_active = "#336600"; +set c_meta_text_color = "#000"; +set c_footer_background = "#333"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#5ab300"; +set c_comment_one_link_visited = "#5ab300"; +set c_comment_one_link_hover = "#336600"; +set c_comment_one_link_active = "#336600"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#333"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#5ab300"; +set c_comment_two_link_visited = "#5ab300"; +set c_comment_two_link_hover = "#336600"; +set c_comment_two_link_active = "#336600"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#333"; +set c_comment_two_background = "#fff"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#708CC4"; +set c_comment_screened_link_visited = "#5ab300"; +set c_comment_screened_link_hover = "#336600"; +set c_comment_screened_link_active = "#336600"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#333"; +set c_comment_screened_background = "#fff"; +set c_comment_screened_border = "#999"; + +# FONTS +set f_page = "Georgia, serif"; +set f_page_title = "Georgia, serif"; +set f_page_title_size = "190%"; +set f_page_size = "12px"; +set f_page_link = "Georgia, serif"; +set f_page_link_size = "100%"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu_link_size = "80%"; +set f_menu = "Georgia, serif"; +set f_menu_size = "100%"; +set f_menu_header = "Georgia, serif"; +set f_menu_header_size = "120%"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_menu_current_size = "80%"; +set f_entry = "Georgia, serif"; +set f_entry_size = "100%"; +set f_entry_link = "Georgia, serif"; +set f_entry_link_size = "100%"; +set f_entry_title = "Georgia, serif"; +set f_entry_title_size = "150%"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_size = "80%"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_meta_link_size = "100%"; +set f_footer = "Georgia, serif"; +set f_footer_size = "100%"; +set f_footer_link = "Georgia, serif"; +set f_footer_link_size = "100%"; +set f_comment = "Georgia, serif"; +set f_comment_size = "100%"; +set f_comment_title = "Georgia, serif"; +set f_comment_title_size = "130%"; +set f_comment_link = "Georgia, serif"; +set f_comment_link_size = "100%"; + +# OTHER +set show_entrynav_icons = true; +set time_format = "%%hh%%:%%min%% %%a%%m"; +set date_format = "%%mon%%. %%dayord%%, %%yyyy%%"; +set menu_disable_summary = false; +set css_style_overrides = ""; +set css_page_width = "800px"; + +# TEXT +set text_meta_music = "music"; +set text_links_header = "links"; +set text_meta_mood = "mood"; +set text_read_comments = "{#}"; +set text_read_comments_friends = "{#}"; +set text_comment_anonymous = "anonymous"; +set text_comment_viewall = "view all comments"; +set text_links_header = "Links"; +set text_summary_header = "Page Summary"; +set text_links_spacer = "_______________"; + + + +# ======================================== +# METHODS +# ======================================== + + +# ------------------------------- +# stylesheet +# ------------------------------- +function print_stylesheet ( ) +{ + """ + @media screen, print { + * { + margin: 0; + padding: 0; + } + hr { + display: none; + } + body { + background-color: $*c_page_background; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + text-align: center; + } + a { + font-family: $*f_page_link; + font-size: $*f_page_link_size; + color: $*c_page_link; + text-decoration: none; + } + a:visited { color: $*c_page_link_visited; } + a:hover, a:visited:hover { color: $*c_page_link_hover; text-decoration: underline; } + a:active { color: $*c_page_link_active; } + a img { border: none; } + a.comm { + background: transparent url(http://stat.livejournal.com/img/community.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + a.user { + background: transparent url(http://stat.livejournal.com/img/userinfo.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + p { + margin: 5px; + padding: 5px; + } + + form { + display: inline; + margin: 0px; + padding: 0px; + } + input, select, textarea { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + padding: 2px; + margin: 3px; + } + + #container { + position: relative; + width: $*css_page_width; + margin: 0 auto; + text-align: left; + } + #header { + margin-bottom: 15px; + border: 1px solid $*c_header_border; + background-color: $*c_header_background; + } + + #header h1 { + padding: 20px; + font-family: $*f_page_title; + font-size: $*f_page_title_size; + color: $*c_page_title; + } + + #menu { + position: relative; + background-color: $*c_menu_background; + float: left; + width: 150px; + font-family: $*f_menu; + font-size: $*f_menu_size; + color: $*c_menu_text_color; + border: 1px solid $*c_menu_border; + padding: 4px; + } + #content { + position: relative; + margin-left: 160px; + } + + #entries { + border: 1px solid $*c_main_border; + padding: 15px; + background-color: $*c_main_background; + } + + #menu h2 { + margin: 20px 0; + font-family: $*f_menu_header; + font-size: $*f_menu_header_size; + color: $*c_menu_header_color; + } + #menu h2.userpic { + text-align: center; + } + #menu a { + font-family: $*f_menu_link; + font-size: $*f_menu_link_size; + color: $*c_menu_link; + } + #menu a:visited { color: $*c_menu_link_visited; } + #menu a:hover, #menu a:visited:hover { color: $*c_menu_link_hover; } + #menu a:active { color: $*c_menu_link_active; } + #menu ul { + margin: 3px; + list-style: none; + } + #menu ul li { + margin: 3px; + padding: 2px; + list-style: none; + } + #menu ul li.active { + font-family: $*f_menu_current; + font-size: $*f_menu_current_size; + color: $*c_menu_current; + font-weight: bold; + } + #content h2 { + margin: 20px 0; + } + #entries, #comments { + margin: 10px; + } + .ind-entry { + padding: 5px; + padding-bottom: 15px; + border-bottom: 1px solid $*c_entry_border; + background-color: $*c_entry_background; + } + .ind-entry h3 img, .ind-comment-one h3 img, .ind-comment-two h3 img, .ind-comment-screened h3 img { + position: relative; + float: right; + padding: 5px; + } + .ind-entry h2 { + font-family: $*f_entry_title; + font-size: $*f_entry_title_size; + color: $*c_entry_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-entry h4, .ind-comment-one h4, .ind-comment-two h4, .ind-comment-screened h4 { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + } + .ind-entry h4 { + background-color: $*c_meta_background; + } + .ind-entry h4 a, .ind-comment-one h4 a, .ind-comment-two h4 a, .ind-comment-screened h4 a { + font-family: $*f_meta_link; + font-size: $*f_meta_link_size; + color: $*c_meta_link; + text-decoration: underline; + } + .ind-entry h4 a:visited, .ind-comment-one h4 a:visited, .ind-comment-two h4 a:visited, .ind-comment-screened h4 a:visited { color: $*c_meta_link_visited; } + .ind-entry h4 a:hover, .ind-comment-one h4 a:hover, .ind-comment-two h4 a:hover, .ind-comment-screened h4 a:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:visited:hover, .ind-comment-one h4 a:visited:hover, .ind-comment-two h4 a:visited:hover, .ind-comment-screened h4 a:visited:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:active, .ind-comment-one h4 a:active, .ind-comment-two h4 a:active, .ind-comment-screened h4 a:active { color: $*c_meta_link_active; } + .ind-entry div.entry-item, .ind-entry div.month-entries { + font-family: $*f_entry; + font-size: $*f_entry_size; + color: $*c_entry_text_color; + margin: 15px 0px; + } + .ind-entry div.entry-item a, .ind-entry div.month-entries a { + font-family: $*f_entry_link; + font-size: $*f_entry_link_size; + color: $*c_entry_link; + text-decoration: underline; + } + .ind-entry div.entry-item a:visited, .ind-entry div.month-entries a:visited { color: $*c_entry_link_visited; } + .ind-entry div.entry-item a:hover, .ind-entry div.entry-item a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.month-entries a:hover, .ind-entry div.month-entries a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.entry-item a:active, .ind-entry div.month-entries a:active { color: $*c_entry_link_active; } + + .ind-comment-one, .ind-comment-two, .ind-comment-screened { + margin: 10px 0; + padding: 5px; + } + .ind-comment-one { background-color: $*c_comment_one_background; border-bottom: 1px solid $*c_comment_one_border; } + .ind-comment-two { background-color: $*c_comment_two_background; border-bottom: 1px solid $*c_comment_two_border; } + .ind-comment-screened { background-color: $*c_comment_screened_background; border-bottom: 1px solid $*c_comment_screened_border; } + + .ind-comment-one h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_one_title_color; + margin: 20px 0px; + } + .ind-comment-one div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_one_text_color; + margin: 15px 0px; + } + .ind-comment-one div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_one_link; + text-decoration: underline; + } + .ind-comment-one div.entry-item a:visited { color: $*c_comment_one_link_visited; } + .ind-comment-one div.entry-item a:hover, .ind-comment-one div.entry-item a:visited:hover { color: $*c_comment_one_link_hover; } + .ind-comment-one div.entry-item a:active { color: $*c_comment_one_link_active; } + + .ind-comment-two h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_two_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-comment-two div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_two_text_color; + margin: 10px 0px; + } + .ind-comment-two div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_two_link; + text-decoration: underline; + } + .ind-comment-two div.entry-item a:visited { color: $*c_comment_two_link_visited; } + .ind-comment-two div.entry-item a:hover, .ind-comment-two div.entry-item a:visited:hover { color: $*c_comment_two_link_hover; } + .ind-comment-two div.entry-item a:active { color: $*c_comment_two_link_active; } + + .ind-comment-screened h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_screened_title_color; + margin: 20px 0px; + } + .ind-comment-screened div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_screened_text_color; + margin: 10px 0px; + } + .ind-comment-screened div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_screened_link; + text-decoration: underline; + } + .ind-comment-screened div.entry-item a:visited { color: $*c_comment_screened_link_visited; } + .ind-comment-screened div.entry-item a:hover, .ind-comment-screened div.entry-item a:visited:hover { color: $*c_comment_screened_link_hover; } + .ind-comment-screened div.entry-item a:active { color: $*c_comment_screened_link_active; } + + .month-entries { + margin: 10px 0; + } + .month-entries ul { + list-style: none; + margin: 10px; + } + .month-entries ul li { + list-style: none; + padding: 3px; + } + + + #footer { + position: relative; + font-family: $*f_footer; + font-size: $*f_footer_size; + color: $*c_footer_text_color; + background-color: $*c_footer_background; + } + #footer p { + padding: 20px; + } + #footer a { + font-family: $*f_footer_link; + font-size: $*f_footer_link_size; + color: $*c_footer_link; + } + #footer a:visited { color: $*c_footer_link_visited; } + #footer a:hover, #footer a:visited:hover { color: $*c_footer_link_hover; } + #footer a:active { color: $*c_footer_link_active; } + } + + @media print { + #menu { + display: none; + } + #content { + margin-left: 0px; + } + #entries, .ind-entry, .ind-comment, #footer, #header { + border: none; + } + + } + + $*css_style_overrides + + """; +} + + +# ------------------------------- +# user pic main page +# ------------------------------- +function Page::lay_top_userpic ( ) +{ + var Image up_img = $.journal.default_pic; + if ( defined $up_img ) { + print "

    \"$.journal.name\"

    "; + } +} + + +# ------------------------------- +# returns a permalink link based on +# the url passed +# ------------------------------- +function get_permalink ( string url ) : string +{ + return("$*text_permalink"); +} + + +# ------------------------------- +# prints the user's 'link-list' +# ------------------------------- +function Page::print_linklist ( ) +{ + if ( size $.linklist > 0 ) { + print "

    $*text_links_header

    "; + print "
      "; + foreach var UserLink l ( $.linklist ) { + if ( $l.title == "spacer" ) { + print "
    • $*text_links_spacer
    • "; + } elseif ($l.is_heading) { + print "
    • $l.title
    • "; + } elseif ( $l.title ) { + print "
    • $l.title
    • "; + } + } + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# prints the LJ specific links (recent, friends, etc) +# ------------------------------- +function print_lj_links ( Page p ) +{ + var string links; + $links = $links + ($p.view == "recent" ? "
  • $*text_view_recent
  • " : "
  • $*text_view_recent
  • "); + if ( $p.journal_type == "C" ) { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends_comm
  • " : "
  • $*text_view_friends_comm
  • "); + } else { + $links = $links + ($p.view == "friends" ? "
  • $*text_view_friends
  • " : "
  • $*text_view_friends
  • "); + } + $links = $links + ($p.view == "archive" ? "
  • $*text_view_archive
  • " : "
  • $*text_view_archive
  • "); + $links = $links + "
  • $*text_view_userinfo
  • "; + $links = $links + ($p.journal.website_url != "" ? "
  • lower() + "\">" + $p.journal.website_name->lower() + "
  • " : ""); + + print "
      "; + print $links; + print "
    "; + print "
    "; +} + +function Page::lay_sidebar_view_summary() : string +{ + return(""); +} + + +# ------------------------------- +# main page layout +# ------------------------------- +function Page::print ( ) +{ + var string title = $this->title(); + + # generate page id: + var string current_view = $.view; + if ( $.view == "month" or $.view == "day" ) { + $current_view = "archive"; + } + if ( $.view == "entry" or $.view == "reply" ) { + $current_view = "recent"; + } + + # begin main page html: + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + $this->print_head(); + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$title\n"; + print "\n"; + print "\n"; + print "
    \n"; + print "
    \n"; + print "
    \n"; + print "

    $title

    \n"; + print "
    "; + print "
    \n"; + print "
    \n"; + print "
    \n"; + $this->lay_top_userpic(); + print "\n"; + print_lj_links($this); + print($this->lay_sidebar_view_summary()); + $this->print_linklist(); + print "
    \n"; + print "
    \n"; + $this->print_body(); + print "
    \n"; + print "
    \n"; + print "\n"; + print "\n"; +} + + +# ------------------------------- +# main page display entries and +# footer +# ------------------------------- +function RecentPage::print_body ( ) +{ + # print all entries + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + + var string range = "most recent entries"; + if ( $.nav.skip > 0 ) { + $range = "$.nav.skip entries back"; + } + + print "

    "; + print "viewing: $range
    "; + # go forward/backward if possible + if ( $.nav.forward_url != "" or $.nav.backward_url != "" ) { + var string sep; + var string back; + var string forward; + if ( $.nav.backward_url != "" ) { + $back = "earlier"; + } + if ( $.nav.forward_url != "" ) { + $forward = "later"; + } + if ( $back != "" and $forward != "" ) { + $sep = " | "; + } + print "go: $back$sep$forward
    "; + } + print "

    "; +} + + +# ------------------------------- +# entry view (show comments) +# ------------------------------- +function EntryPage::print_body ( ) +{ + print "
    \n"; + $this->print_entry ( $.entry ); + if ( $.entry.comments.enabled ) { + print "

    Comments {$.entry.comments.count}

    "; + print "
    "; + if ( $.comment_pages.total_subitems > 0 ) { + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + $.comment_pages->print(); + $this->print_comments($.comments); + if ( $this.multiform_on ) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } + print "
    "; + } + print "
    "; + print "

    "; + print "$*text_post_comment\n"; + print "

    "; +} + + +# ------------------------------- +# day view +# ------------------------------- +function DayPage::print_body ( ) +{ + if ( not $.has_entries ) { + print "
    \n"; + print "
    \n"; + print "

    " + $.date->date_format("long") + "

    "; + print "

    $*text_noentries_day

    "; + print "
    "; + print "
    "; + print "
    "; + } else { + print "
    \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
    "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + print "

    "; + print "« $*text_day_prev | $*text_day_next »"; + print "

    "; +} + + +# ------------------------------- +# year view +# ------------------------------- +function YearPage::print_body ( ) +{ + print "
    \n"; + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print "
    "; +} + + +# ------------------------------- +# page summary for recent page +# ------------------------------- +function RecentPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for day page +# ------------------------------- +function DayPage::lay_sidebar_view_summary() : string +{ + var string return; + if ( not $*menu_disable_summary ) { + foreach var Entry e ( $.entries ) { + $return = $return + "
  • $e.security_icon " + ($e.subject != "" ? "$e.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# page summary for entry page +# ------------------------------- +function EntryPage::lay_sidebar_view_summary() : string { + var string return; + if ( not $*menu_disable_summary ) { + foreach var Comment c ( $.comments ) { + if ( $c.depth == 1 ) { + $return = $return + "
  • " + ($c.subject != "" ? "$c.subject" : "$*text_nosubject") + " [#]
  • "; + } + } + } + if ( $return != "" ) { + $return = "

    $*text_summary_header

      " + $return + "

    "; + } + return($return); +} + + +# ------------------------------- +# display an entry (all views ) +# ------------------------------- +function print_entry ( Page p, Entry e ) +{ + # get date/time + var string datetime; + $datetime = $e.time->date_format($*date_format) + " | " + $e.time->time_format($*time_format); + + # get metadata + var string metadata; + if ( $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string text = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $text = $*text_meta_mood; + } elseif ( $k == "music" ) { + $text = $*text_meta_music; + } + if ( $k == "mood" and defined $e.mood_icon ) { + var Image i = $e.mood_icon; + $val = "\"$val\" $val"; + } + $metadata = "$metadata\n$text: $val
    "; + } + } + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( $p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username ) { + if ( $e.poster.username != $e.journal.username ) { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username in base_url() + "\" title=\"$e.journal.username\" >$e.journal.username"; + } else { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username"; + } + $poster = "posted by: $poster"; + if ( defined $e.userpic ) { + $userpic = "

    \"$e.journal.username\"

    "; + } + } + + # print the entry now: + print "
    "; + + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + + print "

    "; + if ( $e.security != "" ) { + $e.security_icon->print(); + print " "; + } + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + print "

    "; + + print "

    "; + if ( $p.view == "entry" and $*show_entrynav_icons ) { + var string item_link = ""; + foreach var string key (["nav_prev","nav_next"]) { + var Link link = $e->get_link($key); + if ( $link ) { + if ( $key == "nav_prev" ) { + $item_link = $item_link + "lower() + "\">« " + $link.caption->lower() + " | "; + } elseif ( $key == "nav_next" ) { + $item_link = $item_link + "lower() + "\">" + $link.caption->lower() + " »"; + } + } + } + print $item_link; + print "
    "; + } + print "$datetime
    "; + print "$metadata"; + if ( $poster != "" ) { + print "$poster"; + } + print "

    "; + + print "
    $e.text
    \n"; + + print "

    "; + print get_permalink($e.permalink_url); + if ( $p.view != "entry" and $p.view != "reply" ) { + print " | "; + $e.comments->print(); + } elseif ( $e.comments.enabled ) { + print " | "; + $e.comments->print_postlink(); + } + var Link tmp; + if ( viewer_is_owner() and $p.view != "friends" ) { + $tmp = $e->get_link("edit_entry"); + print " | $tmp.caption"; + } + $tmp = $e->get_link("mem_add"); + print " | $tmp.caption"; + print "

    "; + print "
    "; + print "
    "; +} + + +# ------------------------------- +# entry wrapper for main page +# ------------------------------- +function Page::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# entry wrapper for friends page +# ------------------------------- +function FriendsPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +function EntryPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# comments +# ------------------------------- +function CommentInfo::print ( ) +{ + if ( not $.enabled ) { + return; + } + + $this->print_postlink(); + if ( $.count > 0 or $.screened ) { + print " "; + print ""; + $this->print_readlink(); + print ""; + } +} + + +# ------------------------------- +# comment post link +# ------------------------------- +function CommentInfo::print_postlink ( ) +{ + var Page p = get_page(); + var string linktext = ( $p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment ); + if ( $.maxcomments ) { + "$*text_max_comments"; + } else { + "$linktext"; + } +} + + +# ------------------------------- +# print comment +# ------------------------------- +function EntryPage::print_comment ( Comment c ) +{ + var string comment_class = ""; + if ( $c.screened ) { + $comment_class = "ind-comment-screened"; + } elseif ( $c.depth % 2 == 0 ) { + $comment_class = "ind-comment-two"; + } else { + $comment_class = "ind-comment-one"; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_comment_anonymous"; + var string poster_text = defined $c.poster ? $c.poster.name : "$*text_comment_anonymous"; + var string sub_icon; + var int indent = (($c.depth - 1) * 5); + if ( defined $c.subject_icon ) { + $sub_icon = $c.subject_icon->as_string(); + } + + print "
    \n"; + + var string userpic; + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + $userpic = "

    \"$poster_text\"

    "; + } + var string commentdate = $c.time->date_format($*date_format) + " - " + $c.time->time_format($*time_format); + + #userpic + print "$userpic\n"; + + # subject: + if ( $c.subject == "" ) { + print "

    $c.subject_icon $*text_nosubject

    "; + } else { + print "

    $c.subject_icon $c.subject

    "; + } + + print "

    "; + print "from: $poster
    \n"; + print "date: $commentdate
    \n"; + if ( $c.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $c.metadata{"poster_ip"} + "
    "; + } + print get_permalink($c.permalink_url) + "
    \n"; + var Link lnk; + $lnk = $c->get_link("delete_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("screen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("unscreen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + print "

    \n"; + + if ( $this.multiform_on ) { + print ""; + $c->print_multiform_check(); + } + + print "
    $c.text
    \n"; + print "

    "; + print "$*text_comment_reply"; + if ( $c.parent_url != "" ) { print " | $*text_comment_parent"; } + if ( $c.thread_url != "" ) { print " | $*text_comment_thread"; } + print "

    "; + print "
    \n\n"; + print "
    "; +} + + +# ------------------------------- +# print reply form page +# ------------------------------- +function ReplyPage::print_body ( ) +{ + if ( not $.entry.comments.enabled ) { + print "
    \n"; + print "
    "; + print "

    $*text_reply_nocomments_header

    "; + print "$*text_reply_nocomments"; + print "
    "; + print "
    "; + + } else { + print "
    \n"; + + # get date + var string datetime; + $datetime = $.replyto.time->date_format($*date_format) + " | " + $.replyto.time->time_format($*time_format); + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( defined $.replyto.poster ) { + $poster = "base_url() + "\" title=\"$.replyto.poster.username\">$.replyto.poster.username"; + if ( defined $.replyto.userpic ) { + $userpic = "

    \"$.replyto.poster.username\"

    "; + } + } else { + $poster = "$*text_comment_anonymous"; + } + + + # print the entry now: + print "
    "; + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + print "

    "; + if ( $.replyto.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$.replyto.subject"; + } + print "

    "; + + print "

    \n"; + print "$datetime
    "; + print "$*text_comment_from: $poster"; + if ( $.replyto.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $.replyto.metadata{"poster_ip"} + "
    "; + } + print "

    "; + print "
    $.replyto.text
    \n"; + print "

    "; + print get_permalink($.replyto.permalink_url) + " | $*text_comment_viewall\n"; + print "

    "; + print "
    \n"; + print "
    "; + print "
    \n"; + print "

    Reply

    \n"; + $.form->print(); + print "
    "; + print "
    "; + } +} + + +# ------------------------------- +# print available years +# ------------------------------- +function YearPage::print_year_links ( ) +{ + print "

    "; + print "available years:
    "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + print "$y.year "; + } else { + print "$y.year "; + } + } + print "

    "; +} + + +# ------------------------------- +# print available month +# ------------------------------- +function YearPage::print_month ( YearMonth m ) +{ + if ( not $m.has_entries ) { + return; + } + + print "
    \n"; + print "

    " + $m->month_format() + "

    \n"; + print "

    $*text_view_month

    "; + print "
    "; + foreach var YearWeek w ( $m.weeks ) { + foreach var YearDay d ( $w.days ) { + if ( $d.num_entries > 0 ) { + var string date = $d.date->date_format("%%dayord%%"); + print "$date {$d.num_entries}
    \n"; + } + } + } + print "
    \n"; + print "
    \n"; + print "
    "; +} + + +# ------------------------------- +# month view +# ------------------------------- +function MonthPage::print_body ( ) +{ + print "
    "; + print "
    \n"; + print "

    " + $.date->date_format($*lang_fmt_month_long) + "

    "; + + print "
    "; + $.redir->print_hiddens(); + if ( $.prev_url != "" ) { + print "[«]\n"; + } + if ( size $.months > 1 ) { + print "\n"; + } + if ( $.next_url != "" ) { + print "\n[»]\n"; + } + print "


    "; + + # print dates: + foreach var MonthDay d ( $.days ) { + if ( $d.has_entries ) { + print "
    \n"; + print "" + lang_ordinal($d.day) + "
    "; + print "
      "; + foreach var Entry e ( $d.entries ) { + print "
    • "; + print "" + $e.time->time_format("short") + " "; + if ( $e.poster.username != $e.journal.username ) { + $e.poster->print(); " : "; + } + "$e.security_icon "; + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + if ( $e.comments.count > 0 ) { + print " {" + $e.comments.count + "}"; + } + print "
    • "; + } + print "
    "; + print "
    "; + print "
    "; + } + } + print "
    \n"; + print "
    "; +} diff --git a/local/bin/upgrading/s2layers/tranquilityii/themes.s2 b/local/bin/upgrading/s2layers/tranquilityii/themes.s2 new file mode 100755 index 0000000..407654f --- /dev/null +++ b/local/bin/upgrading/s2layers/tranquilityii/themes.s2 @@ -0,0 +1,707 @@ +#NEWLAYER: tranquilityii/plain +layerinfo "redist_uniq" = "tranquilityii/plain"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Plain Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#fff"; +set c_menu_border = "#fff"; +set c_header_background = "#fff"; +set c_header_border = "#fff"; +set c_page_title = "#000"; +set c_page_background = "#fff"; +set c_page_text = "#333"; +set c_page_link = "#036"; +set c_page_link_visited = "#036"; +set c_page_link_hover = "#069"; +set c_page_link_active = "#069"; +set c_menu_background = "#fff"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#000"; +set c_menu_link_hover = "#f00"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#000"; +set c_menu_current = "#000"; +set c_entry_background = "#fff"; +set c_entry_link = "#000"; +set c_entry_link_visited = "#000"; +set c_entry_link_hover = "#000"; +set c_entry_link_active = "#000"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#999"; +set c_meta_background = "#fff"; +set c_meta_link = "#000"; +set c_meta_link_visited = "#000"; +set c_meta_link_hover = "#000"; +set c_meta_link_active = "#000"; +set c_meta_text_color = "#000"; +set c_footer_background = "#fff"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#000"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#000"; +set c_comment_one_link_visited = "#000"; +set c_comment_one_link_hover = "#000"; +set c_comment_one_link_active = "#000"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#000"; +set c_comment_two_link_visited = "#000"; +set c_comment_two_link_hover = "#000"; +set c_comment_two_link_active = "#000"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#000"; +set c_comment_screened_link_visited = "#000"; +set c_comment_screened_link_hover = "#000"; +set c_comment_screened_link_active = "#000"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/earth +layerinfo "redist_uniq" = "tranquilityii/earth"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Earth Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#424B15"; +set c_header_background = "#667320"; +set c_header_border = "#667320"; +set c_page_title = "#fff"; +set c_page_background = "#667320"; +set c_page_text = "#333"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#424B15"; +set c_menu_background = "#88992B"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#424B15"; +set c_menu_link_hover = "#424B15"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#fff"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#99602B"; +set c_entry_link_visited = "#BF7836"; +set c_entry_link_hover = "#734820"; +set c_entry_link_active = "#734820"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#000"; +set c_entry_border = "#BFBFBF"; +set c_meta_background = "#fff"; +set c_meta_link = "#99602B"; +set c_meta_link_visited = "#BF7836"; +set c_meta_link_hover = "#734820"; +set c_meta_link_active = "#734820"; +set c_meta_text_color = "#666"; +set c_footer_background = "#667320"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#99602B"; +set c_comment_one_link_visited = "#BF7836"; +set c_comment_one_link_hover = "#734820"; +set c_comment_one_link_active = "#734820"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#99602B"; +set c_comment_two_link_visited = "#BF7836"; +set c_comment_two_link_hover = "#734820"; +set c_comment_two_link_active = "#734820"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#99602B"; +set c_comment_screened_link_visited = "#BF7836"; +set c_comment_screened_link_hover = "#734820"; +set c_comment_screened_link_active = "#734820"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/money +layerinfo "redist_uniq" = "tranquilityii/money"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Money Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#68754D"; +set c_header_background = "#ACC280"; +set c_header_border = "#ACC280"; +set c_page_title = "#3D3D3D"; +set c_page_background = "#ACC280"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#68754D"; +set c_menu_background = "#8A9C67"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#000"; +set c_menu_link_hover = "#EBF7D4"; +set c_menu_link_active = "#ebf7d4"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#000"; +set c_menu_current = "#EBF7D4"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#679C67"; +set c_entry_link_visited = "#80C280"; +set c_entry_link_hover = "#4D754D"; +set c_entry_link_active = "#4D754D"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#3D3D3D"; +set c_meta_background = "#fff"; +set c_meta_link = "#679C67"; +set c_meta_link_visited = "#80C280"; +set c_meta_link_hover = "#4D754D"; +set c_meta_link_active = "#4D754D"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#ACC280"; +set c_footer_link = "#000"; +set c_footer_link_visited = "#000"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#000"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#679C67"; +set c_comment_one_link_visited = "#80C280"; +set c_comment_one_link_hover = "#4D754D"; +set c_comment_one_link_active = "#4D754D"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#679C67"; +set c_comment_two_link_visited = "#80C280"; +set c_comment_two_link_hover = "#4D754D"; +set c_comment_two_link_active = "#4D754D"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#679C67"; +set c_comment_screened_link_visited = "#80C280"; +set c_comment_screened_link_hover = "#4D754D"; +set c_comment_screened_link_active = "#4D754D"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/winterice +layerinfo "redist_uniq" = "tranquilityii/winterice"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - WinterIce Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#000"; +set c_header_background = "#694D73"; +set c_header_border = "#694D73"; +set c_page_title = "#000"; +set c_page_background = "#694D73"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#694D73"; +set c_menu_background = "#694D73"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#fff"; +set c_menu_link_hover = "#C5A2D0"; +set c_menu_link_active = "#C5A2D0"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#C5A2D0"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#5E71AE"; +set c_entry_link_visited = "#5E71AE"; +set c_entry_link_hover = "#808FBF"; +set c_entry_link_active = "#808FBF"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#3D3D3D"; +set c_meta_background = "#fff"; +set c_meta_link = "#B080BF"; +set c_meta_link_visited = "#C29FCB"; +set c_meta_link_hover = "#854D93"; +set c_meta_link_active = "#854D93"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#694D73"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#5E71AE"; +set c_comment_one_link_visited = "#5E71AE"; +set c_comment_one_link_hover = "#808FBF"; +set c_comment_one_link_active = "#808FBF"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#5E71AE"; +set c_comment_two_link_visited = "#5E71AE"; +set c_comment_two_link_hover = "#808FBF"; +set c_comment_two_link_active = "#808FBF"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#5E71AE"; +set c_comment_screened_link_visited = "#5E71AE"; +set c_comment_screened_link_hover = "#808FBF"; +set c_comment_screened_link_active = "#808FBF"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/fire +layerinfo "redist_uniq" = "tranquilityii/fire"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Fire Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#A65000"; +set c_header_background = "#A65000"; +set c_header_border = "#A65000"; +set c_page_title = "#000"; +set c_page_background = "#A65000"; +set c_page_text = "#3D3D3D"; +set c_page_link = "#000"; +set c_page_link_visited = "#666"; +set c_page_link_hover = "#999"; +set c_page_link_active = "#999"; +set c_menu_border = "#A68700"; +set c_menu_background = "#CCA700"; +set c_menu_link = "#fff"; +set c_menu_link_visited = "#FFD100"; +set c_menu_link_hover = "#CC4100"; +set c_menu_link_active = "#CC4100"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#CC4100"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#CC6300"; +set c_entry_link_visited = "#F27500"; +set c_entry_link_hover = "#A65000"; +set c_entry_link_active = "#A65000"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#333"; +set c_entry_border = "#666"; +set c_meta_background = "#fff"; +set c_meta_link = "#CCA700"; +set c_meta_link_visited = "#F2C600"; +set c_meta_link_hover = "#A68700"; +set c_meta_link_active = "#A68700"; +set c_meta_text_color = "#3D3D3D"; +set c_footer_background = "#A65000"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#CC6300"; +set c_comment_one_link_visited = "#F27500"; +set c_comment_one_link_hover = "#A65000"; +set c_comment_one_link_active = "#A65000"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#CC6300"; +set c_comment_two_link_visited = "#F27500"; +set c_comment_two_link_hover = "#A65000"; +set c_comment_two_link_active = "#A65000"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#CC6300"; +set c_comment_screened_link_visited = "#F27500"; +set c_comment_screened_link_hover = "#A65000"; +set c_comment_screened_link_active = "#A65000"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; + +#NEWLAYER: tranquilityii/mobile +layerinfo "redist_uniq" = "tranquilityii/mobile"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Mobile Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#fff"; +set c_header_background = "#fff"; +set c_header_border = "#fff"; +set c_page_title = "#000"; +set c_page_background = "#fff"; +set c_page_text = "#000"; +set c_page_link = "#00f"; +set c_page_link_visited = "#999"; +set c_page_link_hover = "#f00"; +set c_page_link_active = "#f00"; +set c_menu_border = "#fff"; +set c_menu_background = "#fff"; +set c_menu_link = "#00f"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#f00"; +set c_menu_link_active = "#f00"; +set c_menu_text_color = "#000"; +set c_menu_header_color = "#00"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#00f"; +set c_entry_link_visited = "#999"; +set c_entry_link_hover = "#f00"; +set c_entry_link_active = "#f00"; +set c_entry_text_color = "#000"; +set c_entry_title_color = "#000"; +set c_entry_border = "#fff"; +set c_meta_background = "#fff"; +set c_meta_link = "#00f"; +set c_meta_link_visited = "#999"; +set c_meta_link_hover = "#f00"; +set c_meta_link_active = "#f00"; +set c_meta_text_color = "#000"; +set c_footer_background = "#fff"; +set c_footer_link = "#00f"; +set c_footer_link_visited = "#999"; +set c_footer_link_hover = "#f00"; +set c_footer_link_active = "#f00"; +set c_footer_text_color = "#000"; +set c_comment_one_link = "#00f"; +set c_comment_one_link_visited = "#999"; +set c_comment_one_link_hover = "#f00"; +set c_comment_one_link_active = "#f00"; +set c_comment_one_text_color = "#000"; +set c_comment_one_title_color = "#000"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#fff"; +set c_comment_two_link = "#00f"; +set c_comment_two_link_visited = "#999"; +set c_comment_two_link_hover = "#f00"; +set c_comment_two_link_active = "#f00"; +set c_comment_two_text_color = "#000"; +set c_comment_two_title_color = "#000"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#fff"; +set c_comment_screened_link = "#00f"; +set c_comment_screened_link_visited = "#999"; +set c_comment_screened_link_hover = "#f00"; +set c_comment_screened_link_active = "#f00"; +set c_comment_screened_text_color = "#000"; +set c_comment_screened_title_color = "#000"; +set c_comment_screened_background = "#999"; +set c_comment_screened_border = "#fff"; +set menu_disable_summary = true; +set css_style_overrides = "hr { display: block; } #menu { float: none; width: auto; } #content { margin-left: 0; } #container { margin: 0; padding: 0; text-align: left; width: 100%; }"; + +#NEWLAYER: tranquilityii/pinky +layerinfo "redist_uniq" = "tranquilityii/pinky"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Pinky Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#242E35"; +set c_header_background = "#242E35"; +set c_header_border = "#242E35"; +set c_page_title = "#fff"; +set c_page_background = "#242E35"; +set c_page_text = "#fff"; +set c_page_link = "#f0c"; +set c_page_link_visited = "#FF82E5"; +set c_page_link_hover = "#B30090"; +set c_page_link_active = "#B30090"; +set c_menu_border = "#B4A361"; +set c_menu_background = "#ECE9D8"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#F8F7F1"; +set c_entry_link = "#f0c"; +set c_entry_link_visited = "#FF82E5"; +set c_entry_link_hover = "#B30090"; +set c_entry_link_active = "#B30090"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#666"; +set c_entry_border = "000"; +set c_meta_background = "#F8F7F1"; +set c_meta_link = "#f0c"; +set c_meta_link_visited = "#FF82E5"; +set c_meta_link_hover = "#B30090"; +set c_meta_link_active = "#B30090"; +set c_meta_text_color = "#666"; +set c_footer_background = "#242E35"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#f0c"; +set c_comment_one_link_visited = "#FF82E5"; +set c_comment_one_link_hover = "#B30090"; +set c_comment_one_link_active = "#B30090"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#666"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#f0c"; +set c_comment_two_link_visited = "#FF82E5"; +set c_comment_two_link_hover = "#B30090"; +set c_comment_two_link_active = "#B30090"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#666"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#f0c"; +set c_comment_screened_link_visited = "#FF82E5"; +set c_comment_screened_link_hover = "#B30090"; +set c_comment_screened_link_active = "#B30090"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#666"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/fresh +layerinfo "redist_uniq" = "tranquilityii/fresh"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Fresh Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#7A97B2"; +set c_header_background = "#7A97B2"; +set c_header_border = "#7A97B2"; +set c_page_title = "#273849"; +set c_page_background = "#242E35"; +set c_page_text = "#fff"; +set c_page_link = "#036"; +set c_page_link_visited = "#036"; +set c_page_link_hover = "#069"; +set c_page_link_active = "#069"; +set c_menu_border = "#CFE0E6"; +set c_menu_background = "#CFE0E6"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#036"; +set c_entry_link_visited = "#036"; +set c_entry_link_hover = "#069"; +set c_entry_link_active = "#069"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#999"; +set c_entry_border = "000"; +set c_meta_background = "#fff"; +set c_meta_link = "#036"; +set c_meta_link_visited = "#036"; +set c_meta_link_hover = "#069"; +set c_meta_link_active = "#069"; +set c_meta_text_color = "#999"; +set c_footer_background = "#7A97B2"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#036"; +set c_comment_one_link_visited = "#036"; +set c_comment_one_link_hover = "#069"; +set c_comment_one_link_active = "#069"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#999"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#036"; +set c_comment_two_link_visited = "#036"; +set c_comment_two_link_hover = "#069"; +set c_comment_two_link_active = "#069"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#999"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#036"; +set c_comment_screened_link_visited = "#036"; +set c_comment_screened_link_hover = "#069"; +set c_comment_screened_link_active = "#069"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#999"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; +set f_page = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_entry = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_footer = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif"; +set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif"; + +#NEWLAYER: tranquilityii/auto +layerinfo "redist_uniq" = "tranquilityii/auto"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tranquility II - Auto Theme"; +layerinfo "author_name" = "Matthew Vince"; + +set c_main_border = "#515151"; +set c_header_background = "#515151"; +set c_header_border = "#515151"; +set c_page_title = "#fff"; +set c_page_background = "#515151"; +set c_page_text = "#333"; +set c_page_link = "#00B4FF"; +set c_page_link_visited = "#00B4FF"; +set c_page_link_hover = "#006894"; +set c_page_link_active = "#006894"; +set c_menu_border = "#ccc"; +set c_menu_background = "#eee"; +set c_menu_link = "#000"; +set c_menu_link_visited = "#999"; +set c_menu_link_hover = "#000"; +set c_menu_link_active = "#000"; +set c_menu_text_color = "#333"; +set c_menu_header_color = "#333"; +set c_menu_current = "#000"; +set f_menu_header_size = "140%"; +set c_entry_background = "#fff"; +set c_entry_link = "#00B4FF"; +set c_entry_link_visited = "#00B4FF"; +set c_entry_link_hover = "#006894"; +set c_entry_link_active = "#006894"; +set c_entry_text_color = "#333"; +set c_entry_title_color = "#999"; +set c_entry_border = "000"; +set c_meta_background = "#fff"; +set c_meta_link = "#036"; +set c_meta_link_visited = "#036"; +set c_meta_link_hover = "#069"; +set c_meta_link_active = "#069"; +set c_meta_text_color = "#999"; +set c_footer_background = "#515151"; +set c_footer_link = "#fff"; +set c_footer_link_visited = "#fff"; +set c_footer_link_hover = "#fff"; +set c_footer_link_active = "#fff"; +set c_footer_text_color = "#fff"; +set c_comment_one_link = "#00B4FF"; +set c_comment_one_link_visited = "#00B4FF"; +set c_comment_one_link_hover = "#006894"; +set c_comment_one_link_active = "#006894"; +set c_comment_one_text_color = "#333"; +set c_comment_one_title_color = "#999"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#999"; +set c_comment_two_link = "#00B4FF"; +set c_comment_two_link_visited = "#00B4FF"; +set c_comment_two_link_hover = "#006894"; +set c_comment_two_link_active = "#006894"; +set c_comment_two_text_color = "#333"; +set c_comment_two_title_color = "#999"; +set c_comment_two_background = "#f2f2f2"; +set c_comment_two_border = "#999"; +set c_comment_screened_link = "#00B4FF"; +set c_comment_screened_link_visited = "#00B4FF"; +set c_comment_screened_link_hover = "#006894"; +set c_comment_screened_link_active = "#006894"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#999"; +set c_comment_screened_background = "#ccc"; +set c_comment_screened_border = "#999"; diff --git a/local/bin/upgrading/s2layers/unearthed/layout.s2 b/local/bin/upgrading/s2layers/unearthed/layout.s2 new file mode 100755 index 0000000..502135b --- /dev/null +++ b/local/bin/upgrading/s2layers/unearthed/layout.s2 @@ -0,0 +1,1555 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Unearthed"; +layerinfo redist_uniq = "unearthed/layout"; + +layerinfo author_name = "Jesse Proulx"; +layerinfo author_email = "jproulx@livejournal.com"; +layerinfo des = "Based loosely on the design of the Unearthing T. rex website."; + +propgroup presentation { + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + + property int content_width + { + des = "Entire width of the main content, in percentages"; + values = "60|60%|70|70%|80|80%|90|90%"; + } + property string content_align { + des = "Content alignment"; + values = "right|Left|center|Center|left|Right"; + } + set content_width = 90; + set content_align = "center"; + + property use use_shared_pic; + property bool show_entry_userpic + { + des = "Show user picture icons with each of your entries?"; + } + set show_entry_userpic = true; + + property string dropshadow { + des = "Show drop shadows on content boxes"; + values = "none|No drop shadows|bottomright|Bottom-Right|bottomleft|Bottom-Left|topright|Top-Right|topleft|Top-Left"; + } + set dropshadow = "bottomright"; + + property string title_texture { + des = "Select a background texture for the page title:"; + values = "none|None|brushed_metal|Brushed Metal|burlap|Burlap|camouflage|Camouflage|canvas|Canvas|chalk|Chalk|cork|Cork|explosion|Explosion|fibers|Fibers|floral|Floral|ice|Ice|manila|Manila|marble|Marble|paper|Paper|ridge|Ridge|rough|Rough|stucco|Stucco|terracotta|Terracotta|type|Type|wavy|Wavy|weave|Weave|wood|Wood"; + } + set title_texture = "marble"; + property string free_text { + des = "Short introductory blurb or description"; + rows = 10; + cols = 40; + } + property string show_top_box { + des = "Show the introduction box (located at the top)?"; + values = "no|No|all|Yes, on all pages|recent|Yes, only on the Recent Entries page|friends|Yes, only on the Friends Entries page"; + } + set show_top_box = "recent"; + + property string box_sidebar_align { + des = "Show box sidebars on which side?"; + values = "left|Left|right|Right"; + } + set box_sidebar_align = "right"; +} + +propgroup colors = "Colors"; +propgroup colors { + property Color stronger_bgcolor { + des = "Header background color"; + } + set stronger_bgcolor = "#336699"; + property Color stronger_fgcolor { + des = "Text color on headers"; + } + property Color strong_bgcolor { + des = "Menu background color"; + } + set strong_bgcolor = "#6699cc"; + property Color strong_fgcolor { + des = "Text color on menus"; + } + property Color neutral_bgcolor { + des = "Title background color"; + } + set neutral_bgcolor = "#dddddd"; + property Color neutral_fgcolor { + des = "Text color on titles"; + } + property Color weak_bgcolor { + des = "Content background color"; + } + set weak_bgcolor = "#c1c1c1"; + property Color weak_fgcolor { + des = "Text color on content areas"; + } + property Color weaker_bgcolor { + des = "Page background color"; + } + set weaker_bgcolor = "#ffffff"; + property Color weaker_fgcolor { + des = "Default text color for the page"; + } + property Color link_color { + des = "Link color"; + noui = 1; + } + property Color vlink_color { + des = "Visited link color"; + noui = 1; + } + set link_color = "#0000ff"; + set vlink_color = "#ff00ff"; + property Color comment_bar_one_bgcolor + { + des = "Background color for comment bars"; + } + property Color comment_bar_one_fgcolor + { + des = "Text color on comment bars"; + } + property Color comment_bar_two_bgcolor + { + des = "Alternating background color for comment bars"; + } + property Color comment_bar_two_fgcolor + { + des = "Text color on alternating comment bars"; + } + property Color comment_bar_screened_bgcolor + { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor + { + des = "Text color on background bar for screened comments"; + } + set comment_bar_one_bgcolor = "#dddddd"; + set comment_bar_one_fgcolor = "#000000"; + set comment_bar_two_bgcolor = "#999999"; + set comment_bar_two_fgcolor = "#000000"; + set comment_bar_screened_bgcolor = "#f1f1f1"; + set comment_bar_screened_fgcolor = "#000000"; +} + +propgroup background = "Background"; +propgroup background +{ + property string background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Background's aren't recommended with this style due to non-transparent drop-down shadows."; + } + property string background_repeat + { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string background_position + { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + property string background_scrolling + { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set background_image = ""; + set background_repeat = "repeat"; + set background_position = "center"; + set background_scrolling = "scroll"; +} +propgroup fonts +{ + property string main_font + { + des = "Preferred Font"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set main_font = "Georgia"; + set main_font_fallback = "serif"; + + property string header_font + { + des = "Font for the top header box"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string header_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property string header_font_size + { + des = "Font size for the top header box"; + values = "2em|Small|3em|Medium|4em|Large"; + } + set header_font = "Trebuchet MS"; + set header_font_fallback = "sans-serif"; + set header_font_size = "3em"; + + property string content_font + { + des = "Font for the content boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set content_font = "Georgia"; + set content_font_fallback = "sans-serif"; +} +propgroup text +{ + property string text_linksheader { + des = "Title text for link lists"; + } + property string text_topboxheader { + des = "Title text for the top box"; + } + property string text_minicalheader { + des = "Title for the mini-calendar"; + } + property string text_metaentryheader { + des = "Title for entry sidebars"; + } + property string text_entrytitle { + des = "Navigation menu title for single entries"; + noui = 1; + } + property string text_prevyear { noui = 1; } + property string text_nextyear { noui = 1; } + property string text_prevmonth { noui = 1; } + property string text_nextmonth { noui = 1; } + property use text_view_userinfo; + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_read_comments; + property use text_read_comments_friends; + property use text_post_comment; + property use text_post_comment_friends; + property use text_comment_reply; + property use text_reply_back; + property use text_nosubject; + property use text_noentries_day; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + set text_linksheader = "Links:"; + set text_permalink = "Permanent Link"; + set text_topboxheader = "About this Journal"; + set text_minicalheader = "Current Month"; + set text_metaentryheader = "About this Entry"; + set text_entrytitle = "Entry"; + set text_prevyear = "Previous Year"; + set text_nextyear = "Next Year"; + set text_prevmonth = "Previous Month"; + set text_nextmonth = "Next Month"; +} + +set tags_aware = true; + +################################################################################ +# +# Color scheme functions +# + +function color_ideal_foreground(Color bg) : Color +"Used to determine the best text color (out of white and black currently) given a single solid background color" +{ + var Color fg = $bg->inverse(); + var int saturation = $fg->saturation(); + $saturation = $saturation >= 127 ? 255 : 0; + $fg->saturation($saturation); + var int lightness = $fg->lightness(); + $lightness = $lightness >= 120 ? 255 : 0; + $fg->lightness($lightness); + return $fg; +} + +function color_offset(Color color) : Color +"Create an offset color for black or white text" +{ + var Color ret = $color->clone(); + if ($color.as_string == "#000000") { + $ret = "#333333"; + } else { + $ret = "#999999"; + } + return $ret; +} + +function color_link_colors(Color bg) : Color[] +"Determine sound link colors based on background color" +{ + ### Default link colors are blue and purple + var Color link = $*link_color->clone(); + var Color visited = $*vlink_color->clone(); + + ### Thing is, strong colors on strong colors looks silly + if ($bg->saturation() > 230) { + if ($bg->lightness() > 97 and $bg->lightness() < 161) { + var int lightness = $bg->lightness() > 50 ? 161 : 97; + $link->lightness($lightness); + $visited->lightness($lightness); + } + } + return [$bg, $link, $visited]; +} + +################################################################################ +# +# Property initialization +# + +function prop_init() { + if (isnull $*stronger_fgcolor) { $*stronger_fgcolor = color_ideal_foreground($*stronger_bgcolor); } + if (isnull $*strong_fgcolor) { $*strong_fgcolor = color_ideal_foreground($*strong_bgcolor); } + if (isnull $*neutral_fgcolor) { $*neutral_fgcolor = color_ideal_foreground($*neutral_bgcolor); } + if (isnull $*weak_fgcolor) { $*weak_fgcolor = color_ideal_foreground($*weak_bgcolor); } + if (isnull $*weaker_fgcolor) { $*weaker_fgcolor = color_ideal_foreground($*weaker_bgcolor); } + + ### Hack! + if ($*title_texture == "type") { $*title_texture = palimg_tint("textures/$*title_texture" + ".png", $*stronger_fgcolor, $*stronger_bgcolor); } + elseif ($*title_texture != "none") { $*title_texture = palimg_tint("textures/$*title_texture" + ".png", $*stronger_bgcolor); } +} + +################################################################################ +# +# Drop shadow functions +# + +function dropshadow_open(string{} opts) : string { + var string ret = ""; + var string tint = $opts{"bgcolor"}->substr(1, 6) + $opts{"fgcolor"}->substr(1, 6); + var string width = $opts{"width"} ? $opts{"width"} : "100%"; + var string height = $opts{"height"} ? $opts{"height"} : ""; + var string style = $opts{"style"}; + + if ($*dropshadow == "none") { return ""; } + + $ret = $ret + """"""; + + if ($*dropshadow == "topright" or $*dropshadow == "topleft") { + $ret = $ret + "" + + "" + + ""; + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomleft" or $*dropshadow == "topleft") { + if ($*dropshadow == "bottomleft") { + $ret = $ret + ""; + } + if ($*dropshadow == "topleft") { + $ret = $ret + ""; + } + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomright" or $*dropshadow == "topright") { + if ($*dropshadow == "bottomright") { + $ret = $ret + ""; + } + if ($*dropshadow == "topright") { + $ret = $ret + ""; + } + } + + $ret = $ret + ""; + + if ($*dropshadow == "bottomright" or $*dropshadow == "bottomleft") { + $ret = $ret + "" + + "" + + ""; + } + + $ret = $ret + "
    " + + "" + + ""; + return $ret; +} + +function dropshadow_close(string{} opts) : string { + var string ret = ""; + var string tint = $opts{"bgcolor"}->substr(1, 6) + $opts{"fgcolor"}->substr(1, 6); + var string width = $opts{"width"} ? $opts{"width"} : "100%"; + var string height = $opts{"height"} ? $opts{"height"} : "100%"; + var string style = $opts{"style"}; + + if ($*dropshadow == "none") { return ""; } + + $ret = $ret + "" + + "" + + "
    "; + return $ret; +} + +function dropshadow (string content, string{} opts) : string +"Given a string, prints a table around it that emulates a drop-shadow" +{ + var string ret = ""; + + if ($*dropshadow == "none") { return """
    $content
    """; } + + $ret = $ret + dropshadow_open($opts); + $ret = $ret + $content; + $ret = $ret + dropshadow_close($opts); + return $ret; +} + +function format_box(string id, string title, string contents, string sidebar_title, string sidebar) : string { + var string ret = """"""; + $ret = $ret + """"""; + if ($*box_sidebar_align == "left") { + $ret = $ret + """"""; + } + $ret = $ret + """"""; + if ($*box_sidebar_align == "right") { + $ret = $ret + """"""; + } + $ret = $ret + """
    $title
    """; + $ret = $ret + """"""; + $ret = $ret + """"""; + $ret = $ret + """
    $sidebar_title
    $sidebar
    $contents"""; + $ret = $ret + """"""; + $ret = $ret + """"""; + $ret = $ret + """
    $sidebar_title
    $sidebar
    """; + return $ret; +} + +################################################################################ +# +# Stylesheet +# + +function appended_to_stylesheet() { + +} + +function css_fontspec(string base, string fallback) + "Prints a CSS font-family specification based on the base and fallback given" +{ + if ($base != "" or $fallback != "none") { + "font-family: "; + if ($base != "") { + "\"$base\""; + if ($fallback != "none") { + ", "; + } + } + if ($fallback != "none") { + print $fallback; + } + ";"; + } +} + +function print_stylesheet () { + + println +""" +body { + font-size: 1em; + margin: 0; + padding: 0; + background-color: $*weaker_bgcolor; + color: $*weaker_fgcolor; +"""; + print " "; css_fontspec($*main_font, $*main_font_fallback); println ""; + if(clean_url($*background_image) != "") { + println +""" + background-image: url('$*background_image'); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_scrolling; +"""; + } + println +""" +} +#Content { + background-color: $*weaker_bgcolor; + width: $*content_width%; + padding: 0; +"""; + var int margin = 100 - $*content_width; + if ($margin > 0) { + if ($*content_align == "center") { + $margin = $margin / 2; + println """ margin-right: $margin%;"""; + println """ margin-left: $margin%"""; + } else { + println """ margin-$*content_align: $margin%;"""; + } + } + println +""" +} +#Title { + color: $*stronger_fgcolor; + background-color: $*stronger_bgcolor; +"""; + if ($*title_texture != "none") { println """ background-image: url("$*title_texture");"""; } +println +""" +} +"""; + + println +""" +#GlobalTitle { + width: 80%; + margin-left: 20%; + font-size: $*header_font_size; + margin-bottom: 0; + margin-top: 0; +} +#GlobalSubtitle { + width: 75%; + margin-left: 25%; + font-size: .80em; + margin-top: 2px; + margin-bottom: 0; + font-style: italic; +} +.overflow, .BoxContent { + overflow: auto; +} +#Header { +"""; + print " "; css_fontspec($*header_font, $*header_font_fallback); println ""; +println +""" + width: 100%; + background-color: $*strong_bgcolor; + color: $*strong_fgcolor; + margin-bottom: 10px; +} +.Box { +"""; + print " "; css_fontspec($*content_font, $*content_font_fallback); println ""; +println +""" + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; + width: 100%; +} +.BoxContents { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; + width: 100%; +} +.DropShadow { + margin-bottom: 10px +} +.BoxSideBar { + width: 175px; + height: 100%; + background-color: $*strong_bgcolor; + color: $*strong_fgcolor; +} +"""; + var Color[] sidebar_links = color_link_colors($*strong_bgcolor); +println +""" +.BoxSideBar table { + width: 175px; + height: 100%; +} +.BoxSidebar table a { + background-color: $*strong_bgcolor; + color: $sidebar_links[1]; +} +.BoxSidebar table a:visited { + background-color: $*strong_bgcolor; + color: $sidebar_links[2]; +} +.BoxSideBar table th { + background-color: $*stronger_bgcolor; + color: $*stronger_fgcolor; +} +.BoxSideBarContents { + height: 100%; + padding: 5px; +} +.BoxTitle { + text-align: left; + background-color: $*neutral_bgcolor; + color: $*neutral_fgcolor; + padding: 5px; +} +.BoxContents { + padding: 5px; +} +"""; +var string headernav_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$*strong_bgcolor); +println +""" +.HeaderNavMenu { + background: $*strong_bgcolor url("$headernav_bg") top center repeat-x; + width: 100%; + background-color: $*strong_bgcolor; + margin: 0; + padding-left: 0; + padding-top: 5px; +} +.HeaderNavSubMenu { + width: 100%; + background-color: $*neutral_bgcolor; + margin: 0; + padding-left: 20px; +} +.HeaderNavMenu li, .HeaderNavSubMenu li { + margin-right: 10px; + display: inline; + padding-left: 5px; + padding-right: 5px; + padding-top: 5px; +} +"""; + var string headernavactive_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$*neutral_bgcolor); + var Color inactive = $*strong_bgcolor->lighter(); + var string headernavinactive_bg = palimg_tint("shadow/t.gif",$*stronger_bgcolor,$inactive); +println +""" +.HeaderNavMenu li.inactive { + background: $inactive url("$headernavinactive_bg") top repeat-x; + margin-right: 25px; + display: inline; +} +.HeaderNavMenu li#active { + background: $*neutral_bgcolor url("$headernavactive_bg") top repeat-x; + color: $*neutral_fgcolor; + font-weight: bold; + margin-right: 25px; + display: inline; +} +.HeaderNavMenu li#active a { + color: $*neutral_fgcolor; +} +.HeaderNavMenuFirst { + margin-left: 50px; + padding: 0; + visibility: hidden; +} +.HeaderNavMenu li { + color: $*strong_fgcolor; +} +.HeaderNavMenu li a { + color: $*strong_fgcolor; + text-decoration: none; +} +.HeaderNavSubMenu li { + color: $*neutral_fgcolor; +} +.HeaderNavSubMenu li a { + color: $*neutral_fgcolor; + text-decoration: none; +} +#FooterNavMenu { + text-align: center; + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +#FooterNavMenu a { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +#FooterNavMenu a:visited { + background-color: $*weak_bgcolor; + color: $*weak_fgcolor; +} +.CommentBarOne, .CommentBarTwo, .CommentBarScreened +{ + width: 100%; margin-top: 1em; height: 100%; +} +.CommentBarOne +{ + background-color: $*comment_bar_one_bgcolor; + color: $*comment_bar_one_fgcolor; +} +.CommentBarTwo +{ + background-color: $*comment_bar_two_bgcolor; + color: $*comment_bar_two_fgcolor; +} +.CommentBarScreened +{ + background-color: $*comment_bar_screened_bgcolor; + color: $*comment_bar_screened_fgcolor; +} +"""; +var Color highlightday = $*strong_bgcolor->lighter(); +println +""" +#MiniCal { + width: 175px; height: 3em; +} +.MiniCalDayPosts, .MiniCalDay +{ + text-align: center; + font-size: .8em; + border: 1px inset #000; + width: 14%; +} +.MiniCalDayPosts { + background-color: $highlightday; +} +.MiniCalDayPosts a +{ + color: $*strong_fgcolor; + display: block; + text-decoration: none; + width: 100%; +} +"""; + appended_to_stylesheet(); +} + +################################################################################ +# +# Page +# + +function Page::lay_add_header_nav() : string +{ + return ""; +} + +function Page::lay_sub_menu() : string[] +{ + var string[] ret = []; + + return $ret; +} + +function Page::lay_footer_menu() : string[] +{ + var string[] ret = []; + + return $ret; +} + +function Page::lay_entry_sidebar(Entry e) : string +{ + var string ret; + if ($e.poster.username != $e.journal.username) { + if (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + $ret = $ret + $e.poster->as_string() + ":
    "; + } elseif (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + return $ret; +} + +function Page::lay_show_entry_text : bool +{ + return true; +} + +function Page::lay_entry_sidebar_nav() : string +{ + return ""; +} + +function linklist() : string { + var string return = ""; + var Page p = get_page(); + if (size $p.linklist <= 0) { + return ""; + } + var bool section_open = false; + $return = $return + """$*text_linksheader
    """; + foreach var UserLink l ($p.linklist) { + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + $return = $return + """
    """; + } + $return = $return + """$l.title """; + $section_open = true; + } else { + $return = $return + """$l.title """; + } + } + } + return $return; +} + +function mini_calendar() : string +{ + var string calendar = ""; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """"""; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + if ($d.num_entries) { + $calendar = $calendar + """"""; + } else { + $calendar = $calendar + """"""; + } + } + $calendar = $calendar + "\n"; + } + $calendar = $calendar + "
     $d.day$d.day
    "; + } + if ($calendar == "") { + return "No entries to show"; + } + return $calendar; +} + +function top_box() : string { + var string return = ""; + var string contents = ""; + + if ($*free_text) { $contents = $contents + $*free_text + "
    "; } + $contents = $contents + linklist(); + $contents = format_box("TopBox", $*text_topboxheader, $contents, $*text_minicalheader, mini_calendar()); + + var Color offset = color_offset($*weaker_fgcolor); + $return = dropshadow($contents, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + return $return; +} + +function Page::lay_print_top_box() +{ + if ($*show_top_box != "all") { + return; + } + print top_box(); +} + +function Page::print_entry(Entry e) +{ + var string id = "entry_$e.itemid"; + var string title = "$e.security_icon" + ($e.subject != "" ? " $e.subject" : " $*text_nosubject"); + var string contents = ""; + var string sidebar = ""; + + var string date = $e.time->date_format("med"); + var string time = $e.time->time_format("short"); + $title = """$date @ $time """ + $title; + + if (size $e.metadata) { + $contents = $contents + """
    """; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $contents = $contents + """$text: $val
    """; + } + $contents = $contents + "
    "; + } + if ($e.tags) { + var int tcount = 0; + $contents = $contents + "
    Tags: "; + foreach var Tag t ($e.tags) { + $contents = $contents + """"""; + $tcount++; + if ($tcount != size $e.tags) { $contents = $contents + ", "; } + } + $contents = $contents + "
    "; + } + + if (size $e.metadata or size $e.tags) { $contents = $contents + "
    "; } + $contents = $contents + ($this->lay_show_entry_text() ? $e.text : ""); + + $sidebar = $sidebar + $this->lay_entry_sidebar($e); + + # Comments + $sidebar = $sidebar + """
    """; + if ($e.comments.enabled) { + if (($e.comments.count > 0 or $e.comments.screened) and $.view != "entry") { + $sidebar = $sidebar + """""" + + get_plural_phrase($e.comments.count, $.view == "friends" ? + "text_read_comments_friends" : "text_read_comments") + + ""; + $sidebar = $sidebar + "
    "; + } + if ($.view != "reply") { + $sidebar = $sidebar + """""" + + ($.view == "friends" ? $*text_post_comment_friends : $*text_post_comment) + "
    "; + } + } + $sidebar = $sidebar + """$*text_permalink
    """; + if ($.view == "entry" or $.view == "reply") { + $sidebar = $sidebar + "
    "; + var Link l = new Link; + foreach var string ls ($e.link_keyseq) { + $l = $e->get_link($ls); + if (defined $l) { + $sidebar = $sidebar + """$l.caption
    """; + } + } + } + $sidebar = $sidebar + $this->lay_entry_sidebar_nav(); + $sidebar = $sidebar + "
    "; + + var string entry = format_box($id, $title, $contents, $*text_metaentryheader, $sidebar); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($entry, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); +} + +function Page::print() { + var string title = $this->title(); + + println """"""; + println """"""; + println """$title"""; + println """"""; + + $this->print_head(); + + println """"""; + + println """
    """; + + $this->lay_print_top_box(); + + $this->print_body(); + + var string footer = ""; + foreach var string v ($.views_order) { + $footer = $footer + """""" + lang_viewname($v) + " | "; + } + var string[] footermenu = $this->lay_footer_menu(); + if (size $footermenu > 0) { + foreach var string menuitem ($footermenu) { + $footer = $footer + """$menuitem | """; + } + } + $footer = $footer + """Top"""; + + println dropshadow("""
    $footer
    """, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "style" => "margin-left: 10%; margin-right: 10%; ", + "width" => "80%", + }); + + println """
    """; +} + +################################################################################ +# +# RecentPage +# + +function RecentPage::lay_print_top_box() +{ + if ($*show_top_box != "recent" and $*show_top_box != "all") { + return; + } + print top_box(); +} + +function RecentPage::lay_sub_menu() : string[] { + var string[] ret = []; var int i = 0; + if (viewer_is_owner()) { + $ret[$i] = """
  • Update Journal
  • """; $i++; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function RecentPage::lay_footer_menu() : string[] { + var string[] ret = []; var int i = 0; + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +################################################################################ +# +# FriendsPage +# + +function FriendsPage::lay_print_top_box() +{ + if ($*show_top_box == "friends" or $*show_top_box == "all") { + print top_box(); + } +} + +function FriendsPage::lay_entry_sidebar(Entry e) : string { + var string ret; + if (defined $e.userpic and $*show_entry_userpic) { + var int margin = (175 - $e.userpic.width) / 2; + $ret = dropshadow($e.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($e.userpic.width) + "px", + "height" => string($e.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + if ($e.poster.username != $e.journal.username) { + $ret = $ret + $e.poster->as_string() + ", posting in "; + } + $ret = $ret + $e.journal->as_string() + "
    "; + return $ret; +} + +################################################################################ +# +# EntryPage +# + +function EntryPage::lay_show_entry_text : bool { + return not $.viewing_thread; +} + +function EntryPage::lay_add_header_nav() : string +{ + var string ret = ""; + $ret = """
  • $*text_entrytitle
  • """; + return $ret; +} + +function EntryPage::lay_entry_sidebar_nav() : string +{ + var string return; + if ($.comment_pages.all_subitems_displayed) { return ""; } + $return = "
    "; + foreach var int i (1 .. $.comment_pages.total) { + if ($i == $.comment_pages.current) { + $return = $return + "[Page $i]
    "; + } else { + var string url_of = $.comment_pages->url_of($i); + $return = $return + """[Page $i]
    """; + } + } + return $return; +} + +function EntryPage::lay_sub_menu() : string[] { + var string[] return; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $return[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $return[$i] = """$next.caption"""; + } + } + return $return; +} + +function EntryPage::lay_footer_menu() : string[] { + var string[] return; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $return[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $return[$i] = """$next.caption"""; + } + } + return $return; +} + +function EntryPage::print_body +{ + set_handler("unscreen_comment_#", [ + [ "set_class", "cmtbar#", "CommentBarOne", ], + ]); + set_handler("screen_comment_#", [ + [ "set_class", "cmtbar#", "CommentBarScreened", ], + ]); + + var Entry e = $.entry; + $this->print_entry($e); + + if ($.entry.comments.enabled and ($.entry.comments.count > 0 or $.entry.comments.screened)) + { + var string{} opts = { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "width" => "95%", + }; + print dropshadow_open($opts); + print """
    """; + if ($.comment_pages.total_subitems > 0) { + $this->print_multiform_start(); + $this->print_comments($.comments); + print """
    """; $this->print_multiform_actionline(); print "
    "; + $this->print_multiform_end(); + } + print "
    "; + print dropshadow_close($opts); + } elseif (not $.entry.comments.enabled) { + print dropshadow("""
    $*text_reply_nocomments
    """, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $*weaker_fgcolor.as_string, + "width" => "95%", + }); + } +} + +function EntryPage::print_comment(Comment c) +{ + var string class = ""; + if ($c.screened) { + $class = "CommentBarScreened"; + } elseif ($c.depth % 2) { + $class = "CommentBarOne"; + } else { + $class = "CommentBarTwo"; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + println """
    """; + println """"""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + println """"""; + } + + println """
    [User Picture Icon]"""; + + println """"; + + println """"; + + println """"; + + println """"""; + + println "
    """; + println ""; + println """"""; + println """"; + if ($c.metadata{"poster_ip"}) { println """"; } + println "
    From:$poster
    Date:"""; + println $c.time->date_format("long") + " - " + $c.time->time_format() + "
    $*text_comment_ipaddr(""" + $c.metadata{"poster_ip"} + ")
    """; + if ($this.multiform_on) { + println """ """; + $c->print_multiform_check(); + } + $c->print_linkbar(); + println "
    """; + println (defined $c.subject_icon or $c.subject != "") ? """

    $c.subject_icon $c.subject

    """ : ""; + println "
    ($*text_permalink)
    "; + println """
    $c.text
    """; + println """
    """; + if ($c.frozen) { + println """($*text_comment_frozen) """; + } else { + println """($*text_comment_reply) """; + } + if ($c.parent_url != "") { println """($*text_comment_parent) """; } + if ($c.thread_url != "") { println """($*text_comment_thread) """; } + println "
    "; +} + +################################################################################ +# +# ReplyPage +# +function ReplyPage::lay_add_header_nav() : string +{ + var string ret = ""; + $ret = """
  • $*text_entrytitle
  • """; + return $ret; +} + +function ReplyPage::lay_show_entry_text : bool { + return $.entry.permalink_url == $.replyto.permalink_url; +} + +function ReplyPage::print_body +{ + + $this->print_entry($.entry); + + if (not $.entry.comments.enabled) { + print "

    $*text_reply_nocomments_header/h2>

    $*text_reply_nocomments

    "; + return; + } + var Color offset = color_offset($*weaker_fgcolor); + if ($.entry.permalink_url != $.replyto.permalink_url) { + var string sidebar; + if (defined $.replyto.userpic) { + var int margin = (175 - $.replyto.userpic.width) / 2; + $sidebar = $sidebar + dropshadow($.replyto.userpic->as_string(), { + "bgcolor" => $*strong_bgcolor.as_string, + "fgcolor" => "#000000", + "width" => string($.replyto.userpic.width) + "px", + "height" => string($.replyto.userpic.height) + "px", + "style" => "margin-left: " + $margin + "px; margin-right: " + $margin + "px;", + }); + } + $sidebar = $sidebar + lang_user_wrote($.replyto.poster); + $sidebar = $sidebar + "
    "+lang_at_datetime($.replyto.time); + + var string box = format_box("", $.replyto.subject != "" ? $.replyto.subject : $*text_nosubject, $.replyto.text, "", $sidebar); + print dropshadow($box, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + } + print dropshadow_open({ + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + print """
    """; + $.form->print(); + print """
    """; + print dropshadow_close({ + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + }); +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" replied to "; + } + else { + return "An anonymous user wrote"; + } +} + +################################################################################ +# +# YearPage +# + +function YearPage::lay_footer_menu() : string[] { + var string[] ret; var int i = 0; var int menu = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + if (defined $.years[$i - 1]) { + var YearYear prev = $.years[$i - 1]; + $ret[$menu] = """$*text_prevyear"""; $menu++; + } + if (defined $.years[$i + 1]) { + var YearYear next = $.years[$i + 1]; + $ret[$menu] = """$*text_nextyear"""; $menu++; + } + } + $i++; + } + return $ret; +} + +function YearPage::lay_sub_menu() : string[] { + var string[] ret; + var int i = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + $ret[$i] = """$y.year\n"""; + } else { + $ret[$i] = """$y.year\n"""; + } + $i++; + } + return $ret; +} + +function YearPage::print_body { + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + var string month; + $month = $month + """"""; + foreach var int d (weekdays()) { + $month = $month + "\n"; + } + $month = $month + "\n"; + foreach var YearWeek w ($m.weeks) { + $month = $month + """\n"""; + if ($w.pre_empty > 0) { + $month = $month + """\n"""; + } + foreach var YearDay d ($w.days) { + $month = $month + """\n"""; + } + if ($w.post_empty > 0) { + $month = $month + """\n"""; + } + $month = $month + ""; + } + $month = $month + "
    " + $*lang_dayname_short[$d] + "
     \n"""; + $month = $month + """
    $d.day
    \n"""; + if ($d.num_entries > 0) { + $month = $month + """\n"""; + } + $month = $month + """
     
    "; + $month = format_box("", $m->month_format(), $month, "Links", """$*text_view_month"""); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($month, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); +} + +################################################################################ +# +# MonthPage +# + +function MonthPage::lay_sub_menu () : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """$*text_prevmonth"""; $i++; } + if ($.next_url != "") { $ret[$i] = """$*text_nextmonth"""; $i++; } + return $ret; +} + +function MonthPage::lay_footer_menu () : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """$*text_prevmonth"""; $i++; } + if ($.next_url != "") { $ret[$i] = """$*text_nextmonth"""; $i++; } + return $ret; +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + if (size $.months > 1) { + "\n"; + } + "
    \n"; + + var string days = "
    "; var string links = "
      "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + $days = $days + """
      """ + lang_ordinal($d.day) + """
      """; + $links = $links + """
    • """ + $d.date->date_format("short") + """
    • """; + var string subjects = ""; + foreach var Entry e ($d.entries) { + $subjects = $subjects + $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $subjects = $subjects + $e.poster.username + " "; + } + $subjects = $subjects + "$e.security_icon"; + if ($e.subject != "") { + $subjects = $subjects + " $e.subject"; + } else { + $subjects = $subjects + " ($*text_nosubject)"; + } + if ($e.comments.count > 0) { + $subjects = $subjects + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + $subjects = $subjects + " $*text_month_screened_comments"; + } + $subjects = $subjects + "
      "; + } + $days = $days + """
      $subjects
      """; + } + } + $days = $days + """
    """; + $links = $links + """"""; + var string month = format_box("",$.date->date_format($*lang_fmt_month_long),$days,"Links",$links); + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow($month, { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "100%", + }); +} + +################################################################################ +# +# DayPage +# + +function DayPage::lay_sub_menu() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + +function DayPage::lay_footer_menu() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + +function DayPage::print_body() { + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } else { + var Color offset = color_offset($*weaker_fgcolor); + print dropshadow("

    $*text_noentries_day

    ", { + "bgcolor" => $*weaker_bgcolor.as_string, + "fgcolor" => $offset.as_string, + "width" => "95%", + }); + } +} diff --git a/local/bin/upgrading/s2layers/unearthed/themes.s2 b/local/bin/upgrading/s2layers/unearthed/themes.s2 new file mode 100755 index 0000000..ad0b2cb --- /dev/null +++ b/local/bin/upgrading/s2layers/unearthed/themes.s2 @@ -0,0 +1,118 @@ +#NEWLAYER: unearthed/rampant +layerinfo "type" = "theme"; +layerinfo "name" = "Rampant Tenderfoot"; +layerinfo redist_uniq = "unearthed/rampant"; + +set stronger_bgcolor = "#ff3300"; +set strong_bgcolor = "#ff8000"; +set neutral_bgcolor = "#ffb200"; +set weak_bgcolor = "#ffb380"; +set weaker_bgcolor = "#ffcc80"; + +#NEWLAYER: unearthed/acrid +layerinfo "type" = "theme"; +layerinfo "name" = "Acrid Slide"; +layerinfo redist_uniq = "unearthed/acrid"; + +set title_texture = "rough"; +set stronger_bgcolor = "#33ff00"; +set strong_bgcolor = "#0066b2"; +set neutral_bgcolor = "#00B266"; +set weak_bgcolor = "#99ff80"; +set weaker_bgcolor = "#ccffbf"; + +#NEWLAYER: unearthed/leisure +layerinfo "type" = "theme"; +layerinfo "name" = "Leisure Renewal"; +layerinfo redist_uniq = "unearthed/leisure"; + +set title_texture = "camouflage"; +set stronger_bgcolor = "#285577"; +set strong_bgcolor = "#3c3773"; +set neutral_bgcolor = "#287755"; +set weak_bgcolor = "#c0c0ec"; +set weaker_bgcolor = "#b1ecd3"; + +#NEWLAYER: unearthed/craftis +layerinfo "type" = "theme"; +layerinfo "name" = "Craftis"; +layerinfo redist_uniq = "unearthed/craftis"; + +set title_texture = "camouflage"; +set stronger_bgcolor = "#dd0000"; +set strong_bgcolor = "#aa4f39"; +set neutral_bgcolor = "#d2d2d2"; +set weak_bgcolor = "#fcffcf"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/unveiled +layerinfo "type" = "theme"; +layerinfo "name" = "Unveiled Metal"; +layerinfo redist_uniq = "unearthed/unveiled"; + +set title_texture = "brushed_metal"; +set stronger_bgcolor = "#666666"; +set strong_bgcolor = "#999999"; +set neutral_bgcolor = "#333333"; +set weak_bgcolor = "#cccccc"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/wait +layerinfo "type" = "theme"; +layerinfo "name" = "Wait Screw"; +layerinfo redist_uniq = "unearthed/wait"; + +set title_texture = "chalk"; +set stronger_bgcolor = "#009999"; +set strong_bgcolor = "#ff6600"; +set neutral_bgcolor = "#66cccc"; +set weak_bgcolor = "#ffb380"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/drinkdna +layerinfo "type" = "theme"; +layerinfo "name" = "Drinking DNA"; +layerinfo redist_uniq = "unearthed/drinkdna"; + +set title_texture = "cork"; +set stronger_bgcolor = "#4C9978"; +set strong_bgcolor = "#468C8C"; +set neutral_bgcolor = "#53A653"; +set weak_bgcolor = "#ACE6E6"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/gainful +layerinfo "type" = "theme"; +layerinfo "name" = "Gainful Magic"; +layerinfo redist_uniq = "unearthed/gainful"; + +set title_texture = "fibers"; +set stronger_bgcolor = "#DFDFA7"; +set strong_bgcolor = "#FFFF80"; +set neutral_bgcolor = "#AAAA39"; +set weak_bgcolor = "#eeeeee"; +set weaker_bgcolor = "#FFFFBF"; + +#NEWLAYER: unearthed/inaccurate +layerinfo "type" = "theme"; +layerinfo "name" = "Inaccurate Lingo"; +layerinfo redist_uniq = "unearthed/inaccurate"; + +set title_texture = "stucco"; +set stronger_bgcolor = "#FF8080"; +set strong_bgcolor = "#FF9980"; +set neutral_bgcolor = "#E572A5"; +set weak_bgcolor = "#F2B6D0"; +set weaker_bgcolor = "#eeeeee"; + +#NEWLAYER: unearthed/current +layerinfo "type" = "theme"; +layerinfo "name" = "Current Protector"; +layerinfo redist_uniq = "unearthed/current"; + +set title_texture = "type"; +set stronger_bgcolor = "#B5D9D9"; +set strong_bgcolor = "#285577"; +set neutral_bgcolor = "#226666"; +set weak_bgcolor = "#7DA0BB"; +set weaker_bgcolor = "#B5D9D9"; diff --git a/local/bin/upgrading/sb.dat b/local/bin/upgrading/sb.dat new file mode 100644 index 0000000..a567a0d --- /dev/null +++ b/local/bin/upgrading/sb.dat @@ -0,0 +1,25 @@ +;; -*- coding: utf-8 -*- +/manage/siteopts.bml.btn.lang=Сменити Ñзык + +dystopia.hello_loggedin=Здорово буть + +langname.en=Ðглицкий + +langname.ru=РуÑкой + +langname.sb=СибирÑкой + +ljrlook.nav.editfriends=Тамыри + +ljrlook.nav.friends=Тамыри + +ljrlook.nav.hello=Здорово буть + +lynx.nav.friends=Тамыри + +poll.security.friends=Тамыри + +xcolibur.nav.journal.friends=Тамыри + +xcolibur.nav.manage.friends=Тамыри + diff --git a/local/bin/upgrading/text-local.dat b/local/bin/upgrading/text-local.dat new file mode 100755 index 0000000..9acba36 --- /dev/null +++ b/local/bin/upgrading/text-local.dat @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +domain:100:faq +domain:101:journal/news + +# EnglishLJ is child of English for general domain: +#lang:100:en_LJ:English (LJ):sim:en +#langdomain:en_LJ:general + +# EnglishLJ is root of FAQ & news journal: +#langdomain:en_LJ:faq:1 +#langdomain:en_LJ:journal/news:1 + +# Russian +lang:106:ru:Russian:diff:en +langdomain:ru:general +langdomain:ru:journal/news +langdomain:ru:faq + +# Ukrainian +lang:131:uk:Ukrainian:diff:en +langdomain:uk:general +langdomain:uk:journal/news +langdomain:uk:faq + +# Siberian +lang:206:sb:Siberian:diff:en +langdomain:sb:general +langdomain:sb:journal/news +langdomain:sb:faq diff --git a/local/bin/upgrading/texttool-overrides b/local/bin/upgrading/texttool-overrides new file mode 100644 index 0000000..a9bad99 --- /dev/null +++ b/local/bin/upgrading/texttool-overrides @@ -0,0 +1,84 @@ +# +# texttool.pl newitems override +# format: +# +# + +/modify.bml.colortheme.defaulttheme /modify_do.bml.colortheme.defaulttheme +/modify.bml.colortheme.color.head2 /modify_do.bml.colortheme.color.head2 +/modify.bml.colortheme.customcolors /modify_do.bml.colortheme.customcolors +/modify.bml.overrides.warning /modify_do.bml.overrides.warning +/modify.bml.moodicons.head /modify_do.bml.moodicons.head +/modify.bml.availablestyles.userstyles /modify_do.bml.availablestyles.userstyles +/modify.bml.overrides.head /modify_do.bml.overrides.head +/modify.bml.moodicons.personal /modify_do.bml.moodicons.personal +/modify.bml.domainalias.example /modify_do.bml.domainalias.example +/modify.bml.friends.opt.usesharedpic.about /modify_do.bml.friends.opt.usesharedpic.about +/modify.bml.overrides.note /modify_do.bml.overrides.note +/modify.bml.colortheme.about /modify_do.bml.colortheme.about +/modify.bml.done.text /modify_do.bml.done.text +/modify.bml.success.head /modify_do.bml.success.head +/modify.bml.pagelayoutstyle.warning /modify_do.bml.pagelayoutstyle.warning +/modify.bml.friends.head /modify_do.bml.friends.head +/modify.bml.error.stylenotavailable /modify_do.bml.error.stylenotavailable +/modify.bml.colortheme.color.head1 /modify_do.bml.colortheme.color.head1 +/modify.bml.friends.opt.usesharedpic.head /modify_do.bml.friends.opt.usesharedpic.head +/modify.bml.pagelayoutstyle.about /modify_do.bml.pagelayoutstyle.about +/modify.bml.domainalias.head /modify_do.bml.domainalias.head +/modify.bml.moodicons.opt.forcefriends.about /modify_do.bml.moodicons.opt.forcefriends.about +/modify.bml.colortheme.head /modify_do.bml.colortheme.head +/modify.bml.moodicons.preview /modify_do.bml.moodicons.preview +/modify.bml.pagelayoutstyle.head /modify_do.bml.pagelayoutstyle.head +/modify.bml.moodicons.about /modify_do.bml.moodicons.about +/modify.bml.friends.about /modify_do.bml.friends.about +/modify.bml.colortheme.area.head /modify_do.bml.colortheme.area.head +/modify.bml.availablestyles.head /modify_do.bml.availablestyles.head +/modify.bml.success.text /modify_do.bml.success.text +/modify.bml.domainalias.about /modify_do.bml.domainalias.about +/modify.bml.error.dupdomainalias /modify_do.bml.error.dupdomainalias +/modify.bml.journaloptions.about /modify_do.bml.journaloptions.about +/modify.bml.moodicons.select /modify_do.bml.moodicons.select +/modify.bml.domainalias.domainname /modify_do.bml.domainalias.domainname +/modify.bml.done.head /modify_do.bml.done.head +/modify.bml.overrides.about /modify_do.bml.overrides.about +/modify.bml.overrides.box.head /modify_do.bml.overrides.box.head +/modify.bml.journaloptions.head /modify_do.bml.journaloptions.head +/modify.bml.availablestyles.disabledstyles /modify_do.bml.availablestyles.disabledstyles +/modify.bml.domainalias.helptext /modify_do.bml.domainalias.helptext +/modify.bml.done.btn.savechanges /modify_do.bml.done.btn.savechanges + +/friends/edit.bml.opt.delete /friends/edit_do.bml.opt.delete +/friends/edit.bml.name /friends/edit_do.bml.name +/friends/edit.bml.friend /friends/edit_do.bml.friend +/friends/edit.bml.needmore /friends/edit_do.bml.needmore +/friends/edit.bml.success.text /friends/edit_do.bml.success.text +/friends/edit.bml.btn.toggle /friends/edit_do.bml.btn.toggle +/friends/edit.bml.success.head /friends/edit_do.bml.success.head +/friends/edit.bml.error.updating /friends/edit_do.bml.error.updating +/friends/edit.bml.yourfriends.text /friends/edit_do.bml.yourfriends.text +/friends/edit.bml.user /friends/edit_do.bml.user +/friends/edit.bml.nofriends.head /friends/edit_do.bml.nofriends.head +/friends/edit.bml.fellowfriends.head /friends/edit_do.bml.fellowfriends.head +/friends/edit.bml.foreground /friends/edit_do.bml.foreground +/friends/edit.bml.done.text /friends/edit_do.bml.done.text +/friends/edit.bml.addfriends.text /friends/edit_do.bml.addfriends.text +/friends/edit.bml.addfriends.head /friends/edit_do.bml.addfriends.head +/friends/edit.bml.fellowfriends.text /friends/edit_do.bml.fellowfriends.text +/friends/edit.bml.btn.save /friends/edit_do.bml.btn.save +/friends/edit.bml.hover /friends/edit_do.bml.hover +/friends/edit.bml.opt.addtolist /friends/edit_do.bml.opt.addtolist +/friends/edit.bml.yourfriends.head /friends/edit_do.bml.yourfriends.head +/friends/edit.bml.background /friends/edit_do.bml.background +/friends/edit.bml.done.head /friends/edit_do.bml.done.head +/friends/edit.bml.nofriends.text /friends/edit_do.bml.nofriends.text + +.opt.bannedfrom /talkpost.bml.opt.bannedfrom +.opt.loggedin /talkpost.bml.opt.loggedin +.label.picturetouse2 /talkpost.bml.label.picturetouse2 +.noaccount /talkpost.bml.noaccount + +/editjournal.bml.pickentry.head /editjournal_do.bml.pickentry.head +/editjournal.bml.error.modify /editjournal_do.bml.error.modify +/editjournal.bml.pickentry.text /editjournal_do.bml.pickentry.text +/editjournal.bml.error.nofind /editjournal_do.bml.error.nofind +/editjournal.bml.error.getting /editjournal_do.bml.error.getting diff --git a/local/bin/upgrading/texttool.pl b/local/bin/upgrading/texttool.pl new file mode 100755 index 0000000..c4c8452 --- /dev/null +++ b/local/bin/upgrading/texttool.pl @@ -0,0 +1,758 @@ +#!/usr/bin/perl +# +# This program deals with inserting/extracting text/language data +# from the database. +# + +use strict; +use Getopt::Long; + +my $opt_help = 0; +my $opt_local_lang; +my $opt_extra; +my $opt_only; +my $opt_override; +my $opt_verbose; +my $opt_do; +my @additems; +exit 1 unless +GetOptions( + "help" => \$opt_help, + "local-lang=s" => \$opt_local_lang, + "extra=s" => \$opt_extra, + "override|r" => \$opt_override, + "verbose" => \$opt_verbose, + "only=s" => \$opt_only, + "do" => \$opt_do, + "additems:s{,}" => \@additems, + ); + +my $mode = shift @ARGV; + +help() if $opt_help or not defined $mode; + +sub help +{ + die "Usage: texttool.pl [options] + +Where 'command' is one of: + load Runs the following four commands in order: + popstruct Populate lang data from text[-local].dat into db + poptext Populate text from en.dat, etc into database. + --extra= specifies an alternative input file + --override (-v) specifies existing values should be overwritten + for all languages. (for developer use only) + copyfaq If site is translating FAQ, copy FAQ data into trans area + loadcrumbs Load crumbs from ljcrumbs.pl and ljcrumbs-local.pl. + makeusable Setup internal indexes necessary after loading text + dumptext Dump lang text based on text[-local].dat information + check Check validity of text[-local].dat files + wipedb Remove all language/text data from database, including crumbs. + wipecrumbs Remove all crumbs from the database, leaving other text alone. + newitems Search files in htdocs, cgi-bin, & bin and insert + necessary text item codes in database + remove takes two extra arguments: domain name and code, and removes + that code and its text in all languages + +Optional `options`: + --help The page you're looking at + --verbose More output + --local-lang=.. If given, works on local site files too + --do If given, lets newitems actually create items in database + --additems Takes multiple parameters. If given specifies + what exactly new items should be added. +"; +} + +## make sure $LJHOME is set so we can load & run everything +unless (-d $ENV{'LJHOME'}) { + die "LJHOME environment variable is not set, or is not a directory.\n". + "You must fix this before you can run this database update script."; +} +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; +require "$ENV{'LJHOME'}/cgi-bin/weblib.pl"; + +my %dom_id; # number -> {} +my %dom_code; # name -> {} +my %lang_id; # number -> {} +my %lang_code; # name -> {} +my @lang_domains; + +my $set = sub { + my ($hash, $key, $val, $errmsg) = @_; + die "$errmsg$key\n" if exists $hash->{$key}; + $hash->{$key} = $val; +}; + +foreach my $scope ("general", "local") +{ + my $file = $scope eq "general" ? "text.dat" : "text-local.dat"; + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + unless (-e $ffile) { + next if $scope eq "local"; + die "$file file not found; odd: did you delete it?\n"; + } + open (F, $ffile) or die "Can't open file: $file: $!\n"; + while () { + s/\s+$//; s/^\#.+//; + next unless /\S/; + my @vals = split(/:/, $_); + my $what = shift @vals; + + # language declaration + if ($what eq "lang") { + my $lang = { + 'scope' => $scope, + 'lnid' => $vals[0], + 'lncode' => $vals[1], + 'lnname' => $vals[2], + 'parentlnid' => 0, # default. changed later. + 'parenttype' => 'diff', + }; + $lang->{'parenttype'} = $vals[3] if defined $vals[3]; + if (defined $vals[4]) { + unless (exists $lang_code{$vals[4]}) { + die "Can't declare language $lang->{'lncode'} with missing parent language $vals[4].\n"; + } + $lang->{'parentlnid'} = $lang_code{$vals[4]}->{'lnid'}; + } + $set->(\%lang_id, $lang->{'lnid'}, $lang, "Language already defined with ID: "); + $set->(\%lang_code, $lang->{'lncode'}, $lang, "Language already defined with code: "); + } + + # domain declaration + if ($what eq "domain") { + my $dcode = $vals[1]; + my ($type, $args) = split(m!/!, $dcode); + my $dom = { + 'scope' => $scope, + 'dmid' => $vals[0], + 'type' => $type, + 'args' => $args || "", + }; + $set->(\%dom_id, $dom->{'dmid'}, $dom, "Domain already defined with ID: "); + $set->(\%dom_code, $dcode, $dom, "Domain already defined with parameters: "); + } + + # langdomain declaration + if ($what eq "langdomain") { + my $ld = { + 'lnid' => + (exists $lang_code{$vals[0]} ? $lang_code{$vals[0]}->{'lnid'} : + die "Undefined language: $vals[0]\n"), + 'dmid' => + (exists $dom_code{$vals[1]} ? $dom_code{$vals[1]}->{'dmid'} : + die "Undefined domain: $vals[1]\n"), + 'dmmaster' => $vals[2] ? "1" : "0", + }; + push @lang_domains, $ld; + } + } + close F; +} + +if ($mode eq "check") { + print "all good.\n"; + exit 0; +} + +## make sure we can connect +my $dbh = LJ::get_dbh("master"); +my $sth; +unless ($dbh) { + die "Can't connect to the database.\n"; +} + +# indenter +my $idlev = 0; +my $out = sub { + my @args = @_; + while (@args) { + my $a = shift @args; + if ($a eq "+") { $idlev++; } + elsif ($a eq "-") { $idlev--; } + elsif ($a eq "x") { $a = shift @args; die " "x$idlev . $a . "\n"; } + else { print " "x$idlev, $a, "\n"; } + } +}; + +my @good = qw(load popstruct poptext dumptext newitems wipedb makeusable copyfaq remove + wipecrumbs loadcrumbs); + +popstruct() if $mode eq "popstruct" or $mode eq "load"; +poptext(@ARGV) if $mode eq "poptext" or $mode eq "load"; +copyfaq() if $mode eq "copyfaq" or $mode eq "load"; +loadcrumbs() if $mode eq "loadcrumbs" or $mode eq "load"; +makeusable() if $mode eq "makeusable" or $mode eq "load"; +dumptext(@ARGV) if $mode eq "dumptext"; +newitems() if $mode eq "newitems"; +wipedb() if $mode eq "wipedb"; +wipecrumbs() if $mode eq "wipecrumbs"; +remove(@ARGV) if $mode eq "remove" and scalar(@ARGV) == 2; +help() unless grep { $mode eq $_ } @good; +exit 0; + +sub makeusable +{ + $out->("Making usable...", '+'); + my $rec = sub { + my ($lang, $rec) = @_; + my $l = $lang_code{$lang}; + $out->("x", "Bogus language: $lang") unless $l; + my @children = grep { $_->{'parentlnid'} == $l->{'lnid'} } values %lang_code; + foreach my $cl (@children) { + $out->("$l->{'lncode'} -- $cl->{'lncode'}"); + + my %need; + # push downwards everything that has some valid text in some language (< 4) + $sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$l->{'lnid'} AND staleness < 4"); + $sth->execute; + while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) { + $need{"$dmid:$itid"} = $txtid; + } + $sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$cl->{'lnid'}"); + $sth->execute; + while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) { + delete $need{"$dmid:$itid"}; + } + while (my $k = each %need) { + my ($dmid, $itid) = split(/:/, $k); + my $txtid = $need{$k}; + my $stale = $cl->{'parenttype'} eq "diff" ? 3 : 0; + $dbh->do("INSERT INTO ml_latest (lnid, dmid, itid, txtid, chgtime, staleness) VALUES ". + "($cl->{'lnid'}, $dmid, $itid, $txtid, NOW(), $stale)"); + die $dbh->errstr if $dbh->err; + } + $rec->($cl->{'lncode'}, $rec); + } + }; + $rec->("en", $rec); + $out->("-", "done."); +} + +sub copyfaq +{ + my $faqd = LJ::Lang::get_dom("faq"); + my $ll = LJ::Lang::get_root_lang($faqd); + unless ($ll) { return; } + + my $domid = $faqd->{'dmid'}; + + $out->("Copying FAQ...", '+'); + + my %existing; + $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l ". + "WHERE l.lnid=$ll->{'lnid'} AND l.dmid=$domid AND l.itid=i.itid AND i.dmid=$domid"); + $sth->execute; + $existing{$_} = 1 while $_ = $sth->fetchrow_array; + + # faq category + $sth = $dbh->prepare("SELECT faqcat, faqcatname FROM faqcat"); + $sth->execute; + while (my ($cat, $name) = $sth->fetchrow_array) { + next if exists $existing{"cat.$cat"}; + my $opts = { 'childrenlatest' => 1 }; + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "cat.$cat", $name, $opts); + } + + # faq items + $sth = $dbh->prepare("SELECT faqid, question, answer FROM faq"); + $sth->execute; + while (my ($faqid, $q, $a) = $sth->fetchrow_array) { + next if + exists $existing{"$faqid.1question"} and + exists $existing{"$faqid.2answer"}; + my $opts = { 'childrenlatest' => 1 }; + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.1question", $q, $opts); + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.2answer", $a, $opts); + } + + $out->('-', "done."); +} + +sub wipedb +{ + $out->("Wiping DB...", '+'); + foreach (qw(domains items langdomains langs latest text)) { + $out->("deleting from $_"); + $dbh->do("DELETE FROM ml_$_"); + } + $out->("-", "done."); +} + +sub wipecrumbs +{ + $out->('Wiping DB of all crumbs...', '+'); + + # step 1: get all items that are crumbs. [from ml_items] + my $genid = $dom_code{'general'}->{'dmid'}; + my @crumbs; + my $sth = $dbh->prepare("SELECT itcode FROM ml_items + WHERE dmid = $genid AND itcode LIKE 'crumb.\%'"); + $sth->execute; + while (my ($itcode) = $sth->fetchrow_array) { + # push onto list + push @crumbs, $itcode; + } + + # step 2: remove the items that have these unique dmid/itids + foreach my $code (@crumbs) { + $out->("deleting $code"); + remove("general", $code); + } + + # done + $out->('-', 'done.'); +} + +sub loadcrumbs +{ + $out->('Loading all crumbs into DB...', '+'); + + # get domain id of 'general' and language id of 'en' + my $genid = $dom_code{'general'}->{'dmid'}; + my $loclang = $LJ::LANGS[0] || 'en'; + + # list of crumbs + my @crumbs; + foreach (keys %LJ::CRUMBS_LOCAL) { push @crumbs, $_; } + foreach (keys %LJ::CRUMBS) { push @crumbs, $_; } + + # begin iterating, order doesn't matter... + foreach my $crumbkey (@crumbs) { + $out->("inserting crumb.$crumbkey"); + my $crumb = LJ::get_crumb($crumbkey); + my $local = $LJ::CRUMBS_LOCAL{$crumbkey} ? 1 : 0; + + # see if it exists + my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items + WHERE dmid = $genid AND itcode = 'crumb.$crumbkey'")+0; + LJ::Lang::set_text($genid, $local ? $loclang : 'en', "crumb.$crumbkey", $crumb->[0]) + unless $itid; + } + + # done + $out->('-', 'done.'); +} + +sub popstruct +{ + $out->("Populating structure...", '+'); + foreach my $l (values %lang_id) { + $out->("Inserting language: $l->{'lnname'}"); + $dbh->do("INSERT INTO ml_langs (lnid, lncode, lnname, parenttype, parentlnid) ". + "VALUES (" . join(",", map { $dbh->quote($l->{$_}) } qw(lnid lncode lnname parenttype parentlnid)) . ")"); + } + + foreach my $d (values %dom_id) { + $out->("Inserting domain: $d->{'type'}\[$d->{'args'}\]"); + $dbh->do("INSERT INTO ml_domains (dmid, type, args) ". + "VALUES (" . join(",", map { $dbh->quote($d->{$_}) } qw(dmid type args)) . ")"); + } + + $out->("Inserting language domains ..."); + foreach my $ld (@lang_domains) { + $dbh->do("INSERT IGNORE INTO ml_langdomains (lnid, dmid, dmmaster) VALUES ". + "(" . join(",", map { $dbh->quote($ld->{$_}) } qw(lnid dmid dmmaster)) . ")"); + } + $out->("-", "done."); +} + +sub poptext +{ + my @langs = @_; + push @langs, (keys %lang_code) unless @langs; + + $out->("Populating text...", '+'); + my %source; # lang -> file, or "[extra]" when given by --extra= argument + if ($opt_extra) { + $source{'[extra]'} = $opt_extra; + } else { + foreach my $lang (@langs) { + my $file = "$ENV{'LJHOME'}/bin/upgrading/${lang}.dat"; + next if $opt_only && $lang ne $opt_only; + next unless -e $file; + $source{$lang} = $file; + } + } + + my %existing_item; # langid -> code -> 1 + + foreach my $source (keys %source) + { + $out->("$source", '+'); + my $file = $source{$source}; + open (D, $file) + or $out->('x', "Can't open $source data file"); + + # fixed language in *.dat files, but in extra files + # it switches as it goes. + my $l; + if ($source ne "[extra]") { $l = $lang_code{$source}; } + + my $bml_prefix = ""; + + my $addcount = 0; + my $lnum = 0; + my ($code, $text); + my %metadata; + while (my $line = ) { + $lnum++; + my $del; + my $action_line; + + if ($line =~ /^==(LANG|BML):\s*(\S+)/) { + $out->('x', "Bogus directives in non-extra file.") + if $source ne "[extra]"; + my ($what, $val) = ($1, $2); + if ($what eq "LANG") { + $l = $lang_code{$val}; + $out->('x', 'Bogus ==LANG switch to: $what') unless $l; + $bml_prefix = ""; + } elsif ($what eq "BML") { + $out->('x', 'Bogus ==BML switch to: $what') + unless $val =~ m!^/.+\.bml$!; + $bml_prefix = $val; + } + } elsif ($line =~ /^(\S+?)=(.*)/) { + ($code, $text) = ($1, $2); + $action_line = 1; + } elsif ($line =~ /^\!\s*(\S+)/) { + $del = $code; + $action_line = 1; + } elsif ($line =~ /^(\S+?)\<\<\s*$/) { + ($code, $text) = ($1, ""); + while () { + $lnum++; + last if $_ eq ".\n"; + s/^\.//; + $text .= $_; + } + chomp $text; # remove file new-line (we added it) + $action_line = 1; + } elsif ($line =~ /^[\#\;]/) { + # comment line + next; + } elsif ($line =~ /\S/) { + $out->('x', "$source:$lnum: Bogus format."); + } + + if ($code =~ m!^\.!) { + $out->('x', "Can't use code with leading dot: $code") + unless $bml_prefix; + $code = "$bml_prefix$code"; + } + + if ($code =~ /\|(.+)/) { + $metadata{$1} = $text; + next; + } + + next unless $action_line; + + $out->('x', 'No language defined!') unless $l; + + # load existing items for target language + unless (exists $existing_item{$l->{'lnid'}}) { + $existing_item{$l->{'lnid'}} = {}; + my $sth = $dbh->prepare(qq{ + SELECT i.itcode + FROM ml_latest l, ml_items i + WHERE i.dmid=1 AND l.dmid=1 AND i.itid=l.itid AND l.lnid=$l->{'lnid'} + }); + $sth->execute; + $existing_item{$l->{'lnid'}}->{$_} = 1 + while $_ = $sth->fetchrow_array; + } + + # do deletes + if (defined $del) { + remove("general", $del) + if delete $existing_item{$l->{'lnid'}}->{$del}; + next; + } + + # if override is set (development option) then delete + if ($opt_override && $existing_item{$l->{'lnid'}}->{$code}) { + remove("general", $code); + delete $existing_item{$l->{'lnid'}}->{$code}; + } + + unless ($existing_item{$l->{'lnid'}}->{$code}) { + $addcount++; + my $staleness = $metadata{'staleness'}+0; + my $res = LJ::Lang::set_text($dbh, 1, $l->{'lncode'}, $code, $text, + { 'staleness' => $staleness, + 'notes' => $metadata{'notes'}, }); + $out->("set: $code") if $opt_verbose; + unless ($res) { + $out->('x', "ERROR: " . LJ::Lang::last_error()); + } + } + %metadata = (); + } + close D; + $out->("added: $addcount", '-'); + } + $out->("-", "done."); + + # dead phrase removal + $out->("Removing dead phrases...", '+'); + foreach my $file ("deadphrases.dat", "deadphrases-local.dat") { + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + next unless -s $ffile; + $out->("File: $file"); + open (DP, $ffile) or die; + while (my $li = ) { + $li =~ s/\#.*//; + next unless $li =~ /\S/; + $li =~ s/\s+$//; + my ($dom, $it) = split(/\s+/, $li); + next unless exists $dom_code{$dom}; + my $dmid = $dom_code{$dom}->{'dmid'}; + + my @items; + if ($it =~ s/\*$/\%/) { + my $sth = $dbh->prepare("SELECT itcode FROM ml_items WHERE dmid=? AND itcode LIKE ?"); + $sth->execute($dmid, $it); + push @items, $_ while $_ = $sth->fetchrow_array; + } else { + @items = ($it); + } + foreach (@items) { + remove($dom, $_, 1); + } + } + close DP; + } + $out->('-', "Done."); +} + +sub dumptext +{ + my @langs = @_; + unless (@langs) { @langs = keys %lang_code; } + + $out->('Dumping text...', '+'); + foreach my $lang (@langs) + { + $out->("$lang"); + my $l = $lang_code{$lang}; + open (D, ">$ENV{'LJHOME'}/bin/upgrading/${lang}.dat") + or $out->('x', "Can't open $lang.dat"); + print D ";; -*- coding: utf-8 -*-\n"; + my $sth = $dbh->prepare("SELECT i.itcode, t.text, l.staleness, i.notes FROM ". + "ml_items i, ml_latest l, ml_text t ". + "WHERE l.lnid=$l->{'lnid'} AND l.dmid=1 ". + "AND i.dmid=1 AND l.itid=i.itid AND ". + "t.dmid=1 AND t.txtid=l.txtid AND ". + # only export mappings that aren't inherited: + "t.lnid=$l->{'lnid'} ". + "ORDER BY i.itcode"); + $sth->execute; + die $dbh->errstr if $dbh->err; + my $writeline = sub { + my ($k, $v) = @_; + if ($v =~ /\n/) { + $v =~ s/\n\./\n\.\./g; + print D "$k<<\n$v\n.\n"; + } else { + print D "$k=$v\n"; + } + }; + while (my ($itcode, $text, $staleness, $notes) = $sth->fetchrow_array) { + $writeline->("$itcode|staleness", $staleness) + if $staleness; + $writeline->("$itcode|notes", $notes) + if $notes =~ /\S/; + $writeline->($itcode, $text); + print D "\n"; + } + close D; + } + $out->('-', 'done.'); +} + +sub newitems +{ + $out->("Searching for referenced text codes...", '+'); + my $top = $ENV{'LJHOME'}; + + my %overrides; + if (open (O, "$top/bin/upgrading/texttool-overrides")) { + while () { + my $l = $_; + if ($l !~ /^#/ && $l !~ /^[\s]*$/) { + $l =~ s/[\r\n]//; + my @a = split ,$l; + $overrides{$a[0]} = $a[1]; + } + } + close O; + } + + my @files; + push @files, qw(htdocs cgi-bin bin); + my %items; # $scope -> $key -> 1; + while (@files) + { + my $file = shift @files; + my $ffile = "$top/$file"; + next unless -e $ffile; + if (-d $ffile) { + $out->("dir: $file") if $opt_verbose; + opendir (MD, $ffile) or die "Can't open $file"; + while (my $f = readdir(MD)) { + next if $f eq "." || $f eq ".." || + $f =~ /^\.\#/ || $f =~ /(\.png|\.gif|~|\#)$/; + unshift @files, "$file/$f"; + } + closedir MD; + } + if (-f $ffile) { + my $scope = "general"; +# $scope = "general" if -e "$top/cvs/livejournal/$file"; + + open (F, $ffile) or die "Can't open $file"; + my $line = 0; + + my $correct_code = sub { + my ($code, $file) = @_; + + if ($code =~ /^\./ && $file =~ m!^htdocs/!) { + $code = "$file$code"; + $code =~ s!^htdocs!!; + } + if ($overrides{$code}) { + $code = $overrides{$code}; + } + return $code; + }; + my $valid_code = sub { + my ($code, $file) = @_; + + if ($code =~ /\$/ || $file eq "bin/upgrading/texttool.pl") { + print STDERR "SKIPPING: $file [$code]\n"; + return 0; + } + return 1; + }; + + while () { + $line++; + + if (/^#/) { + next; + } + + while (/BML::ml\([\"\'](.+?)[\"\']/g) { + my $code = $1; + $code = $correct_code->($code, $file); + $out->("BML::ml: $file $code") if $opt_verbose; + $items{$scope}->{$code} = 1 if $valid_code->($code, $file); + } + while (/\(=_ML\s+(.+?)\s+_ML=\)/g) { + my $code = $1; + $code = $correct_code->($code, $file); + $out->("_ML: $code") if $opt_verbose; + $items{$scope}->{$code} = 1 if $valid_code->($code, $file); + } + while (/\$ML{'(.+?)'}/g) { + my $code = $1; + $code = $correct_code->($code, $file); + $out->("\$ML: $file $code") if $opt_verbose; + $items{$scope}->{$code} = 1 if $valid_code->($code, $file); + } + } + close F; + } + } + + $out->(sprintf("%d general and %d local found.", + scalar keys %{$items{'general'}}, + scalar keys %{$items{'local'}})); + + # [ General ] + my %e_general; # code -> 1 + $out->("Checking which general items already exist in database..."); + my $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ". + "l.dmid=1 AND l.lnid=1 AND i.dmid=1 AND i.itid=l.itid "); + $sth->execute; + while (my $it = $sth->fetchrow_array) { $e_general{$it} = 1; } + $out->(sprintf("%d found", scalar keys %e_general)); + foreach my $it (keys %{$items{'general'}}) { + next if exists $e_general{$it}; + + if (@additems && grep(/^$it$/, @additems)) { + if ($opt_do) { + my $res = LJ::Lang::set_text($dbh, 1, "en", $it, undef, { 'staleness' => 4 }); + $out->("Adding general: $it ... $res"); + } + else { + $out->("Would add general: $it"); + } + } + else { + $out->("Skipped: $it"); + } + } + + if ($opt_local_lang) { + my $ll = $lang_code{$opt_local_lang}; + die "Bogus --local-lang argument\n" unless $ll; + die "Local-lang '$ll->{'lncode'}' parent isn't 'en'\n" + unless $ll->{'parentlnid'} == 1; + $out->("Checking which local items already exist in database..."); + + my %e_local; + $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ". + "l.dmid=1 AND l.lnid=$ll->{'lnid'} AND i.dmid=1 AND i.itid=l.itid "); + $sth->execute; + while (my $it = $sth->fetchrow_array) { $e_local{$it} = 1; } + $out->(sprintf("%d found\n", scalar keys %e_local)); + foreach my $it (keys %{$items{'local'}}) { + next if exists $e_general{$it}; + next if exists $e_local{$it}; + my $res = LJ::Lang::set_text($dbh, 1, $ll->{'lncode'}, $it, undef, { 'staleness' => 4 }); + $out->("Adding local: $it ... $res"); + } + } + $out->('-', 'done.'); +} + +sub remove { + my ($dmcode, $itcode, $no_error) = @_; + my $dmid; + if (exists $dom_code{$dmcode}) { + $dmid = $dom_code{$dmcode}->{'dmid'}; + } else { + $out->("x", "Unknown domain code $dmcode."); + } + + my $qcode = $dbh->quote($itcode); + my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items WHERE dmid=$dmid AND itcode=$qcode"); + return if $no_error && !$itid; + $out->("x", "Unknown item code $itcode.") unless $itid; + + $out->("Removing item $itcode from domain $dmcode ($itid)...", "+"); + + # need to delete everything from: ml_items ml_latest ml_text + + $dbh->do("DELETE FROM ml_items WHERE dmid=$dmid AND itid=$itid"); + + my $txtids = ""; + my $sth = $dbh->prepare("SELECT txtid FROM ml_latest WHERE dmid=$dmid AND itid=$itid"); + $sth->execute; + while (my $txtid = $sth->fetchrow_array) { + $txtids .= "," if $txtids; + $txtids .= $txtid; + } + $dbh->do("DELETE FROM ml_latest WHERE dmid=$dmid AND itid=$itid"); + $dbh->do("DELETE FROM ml_text WHERE dmid=$dmid AND txtid IN ($txtids)"); + + $out->("-","done."); +} + + + diff --git a/local/bin/upgrading/uk.dat b/local/bin/upgrading/uk.dat new file mode 100644 index 0000000..8b54ad6 --- /dev/null +++ b/local/bin/upgrading/uk.dat @@ -0,0 +1,15252 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Змінити Ñтан + +/accountstatus.bml.error.db=Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ вашого запиту виникла помилка бази даних. + +/accountstatus.bml.error.invalid=ÐеприпуÑтимий тип ÑтатуÑу + +/accountstatus.bml.error.nochange.expunged=Цей рахунок було вичищено з ÑиÑтеми. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Ðеможливо змінити Ñтан журналу з припиненого. + +/accountstatus.bml.feedback.1=1. Чому ви видалÑєте Ñвій журнал? Виберіть, будь лаÑка, кілька пунктів, Ñкі вам підходÑÑ‚ÑŒ: + +/accountstatus.bml.feedback.1.features=МожливоÑÑ‚Ñ–: + +/accountstatus.bml.feedback.1.features.difficult=У мене виникають труднощі з навігацією Ñайту й викориÑтаннÑм певних можливоÑтей + +/accountstatus.bml.feedback.1.features.difficult.more=Розкажіть нам детальніше: + +/accountstatus.bml.feedback.1.features.notright=[[sitename]] не виправдав моїх Ñподівань Ñ–/або не має можливоÑтей, Ñкі мені потрібні + +/accountstatus.bml.feedback.1.features.notright.more=Розкажіть нам детальніше: + +/accountstatus.bml.feedback.1.features.wrongequipment=Я не маю необхідного комп’ютерного Ð¾Ð±Ð»Ð°Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ [[sitename]] + +/accountstatus.bml.feedback.1.general=У загальному: + +/accountstatus.bml.feedback.1.general.differentaccount=Я викориÑтовую інший рахунок [[sitename]] заміÑÑ‚ÑŒ цього + +/accountstatus.bml.feedback.1.general.mistake=Я Ñтворив цей журнал помилково + +/accountstatus.bml.feedback.1.general.notinterested=Мені більше не цікаво веÑти журнал + +/accountstatus.bml.feedback.1.general.switchedservice=Я перейшов на інший Ñхожий ÑÐµÑ€Ð²Ñ–Ñ + +/accountstatus.bml.feedback.1.general.switchedservice.more=Який Ñаме? + +/accountstatus.bml.feedback.1.general.temporary=Це тимчаÑово, Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÑƒÑÑ Ð²Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ 30 днів + +/accountstatus.bml.feedback.1.other=Інше: + +/accountstatus.bml.feedback.1.other.death=Людина, Ñка Ñтворила цей журнал (або Ñкій його приÑвÑчено) померла + +/accountstatus.bml.feedback.1.other.nofriends=Мої друзі не кориÑтуютьÑÑ [[sitename]] + +/accountstatus.bml.feedback.1.other.other=Причина тут не вказана + +/accountstatus.bml.feedback.1.other.other.more=Розкажіть нам детальніше: + +/accountstatus.bml.feedback.1.other.parents=Мої батьки не дозволÑÑŽÑ‚ÑŒ мені кориÑтуватиÑÑŒ [[sitename]] + +/accountstatus.bml.feedback.1.other.policy=Я не згоден з діловою чи Ñоціальною політикою, Ñку здійÑнює [[sitename]] + +/accountstatus.bml.feedback.1.other.unwantedfriend=Певним оÑобам Ñтало відомо про мій журнал, а Ñ Ñ…Ð¾Ñ‚Ñ–Ð² зберегти це в таємниці + +/accountstatus.bml.feedback.1.service=СервіÑ: + +/accountstatus.bml.feedback.1.service.buggy=Сайт повільний, глючний або неправильно відображаєтьÑÑ + +/accountstatus.bml.feedback.1.service.journalbroken=ЩоÑÑŒ розладналоÑÑŒ у моєму журналі, Ñ– Ñ Ð½Ðµ знаю, Ñк це виправити + +/accountstatus.bml.feedback.1.service.support=Я маю неприємний доÑвід ÑÐ¿Ñ–Ð»ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ñ– Ñлужбою підтримки чи розглÑдачами Ñкарг + +/accountstatus.bml.feedback.1.service.user=Я маю неприємний доÑвід ÑÐ¿Ñ–Ð»ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð· іншим кориÑтувачем + +/accountstatus.bml.feedback.2=2. Як ми можемо покращити роботу нашого ÑервіÑу? + +/accountstatus.bml.feedback.btn.submit=ÐадіÑлати + +/accountstatus.bml.feedback.intro=Також нам цікаво, чому ви Ð½Ð°Ñ Ð·Ð°Ð»Ð¸ÑˆÐ°Ñ”Ñ‚Ðµ. Як що це пов'Ñзано з проблемою, Ñку ми можемо вирішити, ми хочемо Ñпробувати вам допомогти! + +/accountstatus.bml.header.success=УÑпішно + +/accountstatus.bml.journalstatus.about=Якщо ви бажаєте видалити або відновити Ñвій журнал, це робитьÑÑ Ñаме тут. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви видалÑєте Ñвій журнал, у Ð²Ð°Ñ Ñ” 30 днів, щоб відновити його, Ñкщо раптом передумаєте. За 30 днів журнал буде видалено назавжди Ñ– відновити його буде вже неможливо. + +/accountstatus.bml.journalstatus.head=Стан активації журналу + +/accountstatus.bml.journalstatus.select.activated=Ðктивований + +/accountstatus.bml.journalstatus.select.deleted=Видалений + +/accountstatus.bml.journalstatus.select.head=Стан: + +/accountstatus.bml.journalstatus.select.suspended=Призупинений + +/accountstatus.bml.message.deleted=Якщо ви захочете відновити Ñвій журнал, ви можете повернутиÑÑ Ð´Ð¾ цієї Ñторінки впродовж 30 днів. + +/accountstatus.bml.message.nochange=Стан вашого журналу залишивÑÑ [[statusvis]]. + +/accountstatus.bml.message.success=Стан вашого журналу уÑпішно змінено на [[statusvis]]. + +/accountstatus.bml.title=Стан рахунку + +/accountstatus_feedback.bml.success.contactsupport=Можливо, ви бажаєте зв’ÑзатиÑÑ Ð·Ñ– Ñлужбою підтримки щодо технічних проблем, Ñкі у Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ»Ð¸. + +/accountstatus_feedback.bml.success.feedbacksent=Ваш відгук про роботу Ñайту був надіÑланий учаÑникам команди. Хоча ми й не відповідаємо на кожного отриманого лиÑта, ми читаємо Ñ—Ñ… уÑÑ– й цінуємо чаÑ, витрачений вами на те, щоб Ð½Ð°Ñ Ð¿Ð¾Ñ–Ð½Ñ„Ð¾Ñ€Ð¼ÑƒÐ²Ð°Ñ‚Ð¸. + +/accountstatus_feedback.bml.success.header=УÑпішно + +/admin/sponsors/create.bml.community.in.use=Вказана Ñпільнота уже викориÑтовуєтьÑÑ + +/admin/sponsors/create.bml.community.name.caption=Ðазва Ñпільноти + +/admin/sponsors/create.bml.create.caption=Створити + +/admin/sponsors/create.bml.invalid.community=Ðеправильна назва Ñпільноти + +/admin/sponsors/create.bml.no.domains.to.manage=Ðемає ÑпонÑорÑьких доменів Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ + +/admin/sponsors/domain_sponsors.bml.cannot.manage.domain=Ви не можете керувати доменом "[[domain]]" + +/admin/sponsors/domain_sponsors.bml.community.caption=Спільнота + +/admin/sponsors/domain_sponsors.bml.create.caption=Створити + +/admin/sponsors/domain_sponsors.bml.domain.caption=Домен + +/admin/sponsors/domain_sponsors.bml.edit.caption=Змінити + +/admin/sponsors/domain_sponsors.bml.id.caption=Унікальний код + +/admin/sponsors/domain_sponsors.bml.name.caption=Ðазва + +/admin/sponsors/domain_sponsors.bml.no.domains.to.manage=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” ÑпонÑорÑьких доменів Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ + +/admin/sponsors/domain_sponsors.bml.slots.caption=Слоти + +/admin/sponsors/domain_sponsors.bml.status.caption=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/admin/sponsors/edit.bml.activate.caption=Ðктивувати + +/admin/sponsors/edit.bml.cannot.manage=Ви не можете керувати ÑпонÑорÑьким доменом + +/admin/sponsors/edit.bml.community.caption=Спільнота + +/admin/sponsors/edit.bml.deleted.caption=Вилучити + +/admin/sponsors/edit.bml.deleted.duration.caption=Період Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ (дні) + +/admin/sponsors/edit.bml.domain.caption=Домен + +/admin/sponsors/edit.bml.emailconfirm.duration.caption=Період Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою (дні) + +/admin/sponsors/edit.bml.hold.caption=Затримати + +/admin/sponsors/edit.bml.invalid.max.slots=Ðеправильна макÑимальна кількіÑÑ‚ÑŒ Ñлотів + +/admin/sponsors/edit.bml.logo.caption=Лого + +/admin/sponsors/edit.bml.save.changes.caption=Зберегти зміни + +/admin/sponsors/edit.bml.slots.caption=Слоти (викориÑтані/макÑимальні) + +/admin/sponsors/edit.bml.sponsor.deleted=СпонÑора вилучено + +/admin/sponsors/edit.bml.sponsor.not.found=СпонÑора не знайдено + +/admin/sponsors/edit.bml.status.caption=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/admin/sponsors/edit.bml.trial.duration.caption=Ознайомлювальний період (дні) + +/admin/sponsors/edit.bml.trusted.duration.caption=Довірений період (дні) + +/admin/sponsors/index.bml.cannot.manage.domain=Ви не можете керувати доменом "[[domain]]" + +/admin/sponsors/index.bml.community.caption=Спільнота + +/admin/sponsors/index.bml.create.caption=Створити + +/admin/sponsors/index.bml.domain.caption=Домен + +/admin/sponsors/index.bml.edit.caption=Змінити + +/admin/sponsors/index.bml.id.caption=Унікальний код + +/admin/sponsors/index.bml.name.caption=Ðазва + +/admin/sponsors/index.bml.no.domains.to.manage=Ðемає ÑпонÑорÑьких доменів Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ + +/admin/sponsors/index.bml.slots.caption=Слоти + +/admin/sponsors/index.bml.status.caption=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/affiliates.bml.disclaimer1-2=Six Apart - це батьківÑька ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ [[sitename]]. + +/affiliates.bml.disclaimer2-2=ЗаÑтоÑовуєтьÑÑ Ð´Ð¾ покупців, Ñкі обирають автоматичну оплату. Ви отримаєте коміÑÑ–ÑŽ тільки з першої проплати, зробленої покупцем, а з уÑÑ–Ñ… наÑтупних автоматичних проплат - ні. [[sitename]] та Six Apart залишають за Ñобою право відмовити у виплаті коміÑій на рахунки, Ñкі ми підозрюємо у шахрайÑтві чи іншій неприйнÑтній діÑльноÑÑ‚Ñ–. КоміÑійні Ñтавки можуть змінюватиÑÑ Ñƒ будь-Ñкий чаÑ. + +/affiliates.bml.head1=Як мені взÑти учаÑÑ‚ÑŒ? + +/affiliates.bml.head2=КориÑні поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/affiliates.bml.link1=ПартнерÑька Ñторінка Six Apart + +/affiliates.bml.link2=Зв'ÑзатиÑÑ Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾ÑŽ Програми партнерÑтва Six Apart + +/affiliates.bml.link3=Commission Junction FAQ + +/affiliates.bml.link4-2=Щоб повідомити про ваші підозри щодо неправомірного викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸ партнерÑтва, пишіть на email [[email]]. + +/affiliates.bml.step1-2=Перейдіть на веб-Ñайт Commission Junction та заповніть Publisher Application ("РеєÑтрацію публікатора"). Ви маєте бути Ñтарші за 18 років. + +/affiliates.bml.step2-2=Як тільки вашу заÑвку буде Ñхвалено, перейдіть за поÑиланнÑм у вашому email про прийнÑÑ‚Ñ‚Ñ Ð°Ð±Ð¾ увійдіть до ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ¾Ð¼ публікатора (Publisher Account Manager) на веб-Ñайті Commission Junction. + +/affiliates.bml.step3-2=Якщо Ð²Ð°Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ не відіÑлано на правильну Ñторінку, знайдіть Six Apart на закладці "Get Links" ("Отримати поÑиланнÑ"). Оберіть текÑтове чи банерне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° [[sitename]] та додайте код до вашого Ñайту. + +/affiliates.bml.step4=Commission Junction відÑлідковує уÑÑ– нові покупки платних рахунків, що зроблені за рекомендацією з вашого Ñайту, та вишле вам чек Ñк тільки об'єм коміÑійних перевищить $25. + +/affiliates.bml.table.autopay=з автоматичними проплатами + +/affiliates.bml.table.col1=Платні рахунки + +/affiliates.bml.table.col2=Юзерпики + +/affiliates.bml.table.col3=ДиÑковий проÑÑ‚Ñ–Ñ€ + +/affiliates.bml.table.row=[[num]] [[?num|міÑÑць|міÑÑці|міÑÑців]] + +/affiliates.bml.table.title=Структура коміÑійних + +/affiliates.bml.text1-2=Програма партнерÑтва [[sitename]]/Six Apart[[superscript]] дозволÑÑ” вам отримувати гроші за кожного Ð¿Ð¾ÐºÑƒÐ¿Ñ†Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку [[sitename]], залученого вами. Ви можете заробити [[percent]]% коміÑійних за кожен залучений платний рахунок. + +/affiliates.bml.text2=Щоб взÑти учаÑÑ‚ÑŒ у Програмі партнерÑтва, вам необхідно відкрити рахунок у Commission Junction та додати невеликий фрагмент коду до вашого веб-Ñайту або журналу. + +/affiliates.bml.text3-2=Commission Junction - це веб-Ñайт третьої Ñторони, Ñкий відÑлідковує та оброблÑÑ” уÑÑ– проплати у рамках Програми партнерÑтва [[sitename]]. Якщо у Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ»Ð¸ Ð·Ð°Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ проблеми з рахунком у Commission Junction, будь лаÑка звернітьÑÑ Ð´Ð¾ них через Ñ—Ñ… веб-Ñайт. + +/affiliates.bml.title2=Про Програму партнерÑтва [[sitename]] + +/allpics.bml.current=Поточні юзерпики + +/allpics.bml.default=За замовчуваннÑм + +/allpics.bml.edit3=Ви можете змінити ключові Ñлова Ñвоїх юзерпик, завантажити нову юзерпику або збільшити кількіÑÑ‚ÑŒ ваших юзерпик. + +/allpics.bml.edit4=Ви можете бути зацікавлен у зміні ключових Ñлів до ваших юзерпик або завантаженні нових юзерпик. + +/allpics.bml.error.noparam=Ðеобхідно вказати кориÑтувача. + +/allpics.bml.keywords=Ключові Ñлова: + +/allpics.bml.nopics.text.other=Цей кориÑтувач не завантажив жодної юзерпики. + +/allpics.bml.nopics.text.other2=Цей кориÑтувач не завантажив жодної юзерпики. Отримайте ÑповіщеннÑ, коли це ÑтанетьÑÑ. + +/allpics.bml.nopics.text3=Ви не маєте завантажених картинок. Ð”Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ–Ñ‚ÑŒ Ñюди. + +/allpics.bml.nopics.title=Ðемає картинок + +/allpics.bml.pics=Це юзерпики [[user]]. + +/allpics.bml.pics.owner=ОÑÑŒ юзерпики кориÑтувача [[user]]. + +/allpics.bml.pics2=Це юзерпики [[user]]. Отримайте ÑповіщеннÑ, коли цей кориÑтувач завантажить нову. + +/allpics.bml.title=Юзерпики + +/announce.bml.intro=Ми виÑтрибували з штанців, щоб переробити меню та макет шапки вÑÑ–Ñ… оÑновних Ñторінок. + +/announce.bml.line.announcement=У вереÑні ми запуÑкаємо новий дизайн Ñайту "HORIZON" Ñкий: + +/announce.bml.line1=ПідÑвічує вÑÑ– найпопулÑрніші можливоÑÑ‚Ñ– LJ + +/announce.bml.line2=ПриÑтоÑований до нових можливоÑтей + +/announce.bml.line3=Легший Ð´Ð»Ñ Ñ€Ð¾Ð·ÑƒÐ¼Ñ–Ð½Ð½Ñ Ð½Ð¾Ð²Ð°Ñ‡ÐºÐ°Ð¼Ð¸ LJ + +/announce.bml.line4=Зменшує викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ»Ð°Ð²Ñ–Ð°Ñ‚ÑƒÑ€Ð¸ на 75% + +/announce.bml.login=Будь лаÑка, увійдіть до LJ перед вибором дизайну + +/announce.bml.note.line1=Якщо піÑÐ»Ñ Ð²Ð¸Ð¿Ñ€Ð¾Ð±ÑƒÐ²Ð°Ð½ÑŒ нового дизайну ви вирішите що Ñтарий зручніше, то завжди зможете повернути вÑе назад. Однак вам Ñлід врахувати, що в новому дизайні значно покращено навігацію, а це ÑпроÑтить ваше кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñайтом при подальшому зроÑтанні LJ. + +/announce.bml.note.line2=Ð’ÑÑ– кориÑтувачі, що не увійшли до LJ, будуть бачити новий дизайн починаючи з 14 вереÑнÑ. + +/announce.bml.switch=Бажаєте Ñпробувати зараз? + +/announce.bml.switch.button=ÐатиÑніть Ñюди + +/announce.bml.testimonial="Я шалено закохалаÑÑŒ у це. Якщо б це був плюшевий мишка, Ñ Ð± ÑтиÑкала його до неÑÑ‚Ñми." + +/announce.bml.user_testimonial=Ð’Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів: + +/announce.bml.windowtitle=ÐнонÑи [[sitename]] + +/approve.bml.comm.success=УÑпішно + +/approve.bml.comm.text<< +Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð½Ð¾ до [[comm]]. +ÐатиÑніть тут щоб додати Ñпільноту до вашого ÑпиÑку друзів. +. + +/approve.bml.commjoin.text<< +Ви Ñхвалили запит [[user]] на Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ [[comm]]. +ÐатиÑніть тут Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду ÑпиÑку учаÑників цієї Ñпільноти Ñ– Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ñ… налаштувань Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача. +. + +/approve.bml.error.actionperformed=Ð¦Ñ Ð´Ñ–Ñ Ð²Ð¶Ðµ була виконана + +/approve.bml.error.approving=Під Ñ‡Ð°Ñ ÑƒÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту про Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð±ÑƒÐ»Ð°ÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° + +/approve.bml.error.internerr.invalidaction=Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: невірна Ð´Ñ–Ñ + +/approve.bml.error.invalidargument=Задано невірний аргумент + +/approve.bml.error.unknownactiontype=Ðевідомий тип дії + +/approve.bml.shared.success=УÑпішно + +/approve.bml.shared.text<< +Вам дозволено додавати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ [[shared]]. +ÐатиÑніть тут щоб додати Ñпільний журнал до ÑпиÑку ваших друзів. +. + +/approve.bml.title=Ð¡Ñ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ñ–Ñ— + +/betafeatures.bml.nofeatures=Зараз тут немає новинок, Ñкі можна теÑтувати. + +/betafeatures.bml.staytuned=Слідкуйте за [[news]], щоб знати про нові можливоÑÑ‚Ñ– Ð´Ð»Ñ Ñ‚ÐµÑтуваннÑ. ДÑкуємо. + +/betafeatures.bml.title=[[sitename]] Бета + +/birthdays.bml.description=Ðижче подано дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ…, хто Ñ” у вашому ÑпиÑку друзів. Шукаєте подарунок? Відправте віртуальний подарунок. + +/birthdays.bml.description.others=Ðижче подано дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ…, хто Ñ” у ÑпиÑку друзів [[user]]. Шукаєте подарунок? Відправте віртуальний подарунок. + +/birthdays.bml.error.badstatus=Рахунок [[user]] наразі не Ñ” активним. + +/birthdays.bml.error.invaliduser=Ðевірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[user]]. Зазначений рахунок не Ñ–Ñнує. + +/birthdays.bml.findothers=Якщо ви хотіли б побачити дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² іншого кориÑтувача або учаÑників Ñпільноти, введіть нижче ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ: + +/birthdays.bml.nobirthdays=Ðемає дней Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ. Таке траплÑєтьÑÑ, коли в кориÑтувач не додав нікого до Ñвого ÑпиÑку друзів або Ñкщо ніхто з його друзів не показує публічно Ñвій день народженнÑ. + +/birthdays.bml.title=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/birthdays.bml.view=ПереглÑнути + +/changeemail.bml.btn.change=Змінити email-адреÑу + +/changeemail.bml.error.invalidemail=Ðевірна email-адреÑа. + +/changeemail.bml.error.invalidpassword=Ðевірний пароль. + +/changeemail.bml.error.lj_domain=Ви не можете надрукувати @[[domain]] email-адреÑу. Ðадрукуйте у цьому полі вашу дійÑну адреÑу. Якщо ви Ñ” платним кориÑтувачем, ваша [[user]]@[[domain]] адреÑа буде перенаправлена на вашу дійÑну адреÑу. Щоб обрати, Ñку адреÑу (чи обидві) публічно відображати, знайдіть відповідний параметр під параметром "Показувати ваші контактні дані у вашому LiveJournal". + +/changeemail.bml.error.nospace=Пробіли недозволені у email-адреÑах + +/changeemail.bml.error.notvalidated=Ваш рахунок не перевірено. + +/changeemail.bml.error.suspended=Ви не можете змінити email, коли ваш рахунок призупинено. + +/changeemail.bml.instructions=Ð”Ð»Ñ ÐºÑ€Ð°Ñ‰Ð¾Ð³Ð¾ захиÑту ми вимагаємо ваш поточний пароль, коли ви змінюєте вашу email-адреÑу. Через те, що ваша адреÑа викориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб підтвердити ваш рахунок, будь лаÑка, переÑвідчітьÑÑ, що ви також захиÑтили вашу поштову Ñкриньку. ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ ж Ñаме паролю, Ñк Ñ– Ð´Ð»Ñ [[sitename]] та вашої поштової Ñкриньки - не найкращий варіант. + +/changeemail.bml.instructions.identity=Ðби вÑтановити email Ð´Ð»Ñ Ñвого рахунку OpenID, заповніть форму. + +/changeemail.bml.label.newemail=Ðова email-адреÑа: + +/changeemail.bml.label.oldemail=Стара email-адреÑа: + +/changeemail.bml.label.password2=[[remote]] поточний пароль + +/changeemail.bml.label.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/changeemail.bml.noemail=(немає) + +/changeemail.bml.success.header=УÑпішно + +/changeemail.bml.success.text=Зміна email-адреÑи пройшла уÑпішно. + +/changeemail.bml.title=Змінити email-адреÑу + +/changepassword.bml.btn.proceed=Продовжити + +/changepassword.bml.changepassword.header=Змінити пароль + +/changepassword.bml.changepassword.instructions<< +Заповніть форму внизу, щоб змінити Ñвій пароль. При Ñтворенні нового Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ¾Ð½Ð°Ð¹Ñ‚ÐµÑÑ, що: +
      +
    • він ÑкладаєтьÑÑ Ñ‰Ð¾Ð½Ð°Ð¹Ð¼ÐµÐ½ÑˆÐµ з 6 Ñимволів;
    • +
    • він має принаймні 4 різних Ñимволи;
    • +
    • він міÑтить принаймні одну цифру або Ñимвол;
    • +
    • він не заÑнований на вашому імені кориÑтувача, email-адреÑÑ– або прізвиÑьку;
    • +
    • також візьміть до уваги, що ми відкинемо ваш пароль, Ñкщо він Ñ” Ñеред найпоширенійших паролів, Ñкими кориÑтуютьÑÑ Ñ‚Ð¸ÑÑчи людей.
    • +
    + +Ð”Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ у виборі гарного Ð¿Ð°Ñ€Ð¾Ð»Ñ Ñ‚Ð° утриманні вашого рахунку в безпеці, дивітьÑÑ Ñ†Ðµ поширене питаннÑ. +. + +/changepassword.bml.email.body2<< +Доброго днÑ, [[username]]! + +Ðа Ñайті [[sitename]] було змінено ваш пароль. + +Щоб отримати його у майбутньому, завітайте до: + + [[siteroot]]/lostinfo.bml + +Якщо Ви не робили цієї зміни, то, будь лаÑка, подивітьÑÑ Ñ†Ðµ поширене питаннÑ, щоб дізнатиÑÑ Ñк зробити Ñвій рахунок безпечним: + + [[siteroot]]/support/faqbrowse.bml?faqid=117 + +З повагою, +Команда [[sitename]] +[[siteroot]] +. + +/changepassword.bml.email.subject=Зміна паролю + +/changepassword.bml.error.actionalreadyperformed=Ви вже ÑкориÑталиÑÑŒ цим поÑиланнÑм, щоб змінити Ñвій пароль. Якщо вам потрібно змінити Ñвій пароль знову, необхідно виконати запит на нову зміну паролю. + +/changepassword.bml.error.badcheck=Поганий новий пароль: [[error]] + +/changepassword.bml.error.badnewpassword=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ паролю не Ñпівпадає з новим паролем. Можливо ви помилилиÑÑ Ð¿Ñ€Ð¸ наборі. Будь лаÑка, наберіть та підтвердіть новий пароль знову. + +/changepassword.bml.error.badoldpassword=Ваш Ñтарий пароль невірний. + +/changepassword.bml.error.blankpassword=Ваш новий пароль не може бути пуÑтим. + +/changepassword.bml.error.changetestaccount=Ðеможливо змінити пароль теÑтового рахунку. + +/changepassword.bml.error.characterlimit=Довжина Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð° 30 Ñимволами. + +/changepassword.bml.error.emailchanged=Ви змінили адреÑу електронної пошти з моменту оÑтаннього запиту ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ. необхідно зробити інший запит ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб змінити пароль. + +/changepassword.bml.error.identity=КориÑтувачі OpenID не викориÑтовують паролів Ð´Ð»Ñ Ñвоїх рахунків. + +/changepassword.bml.error.invalidarg=ПоÑиланнÑ, Ñке ви викориÑтовуєте Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ паролю, виглÑдає неправильним. ВпевнітьÑÑ, що ви повніÑÑ‚ÑŽ Ñкопіювали адреÑу з отриманого лиÑта. + +/changepassword.bml.error.invaliduser=Ðевірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[user]]. Такого кориÑтувача не Ñ–Ñнує. Чи ви впевнені, що вірно його надрукували? + +/changepassword.bml.error.mustenterusername=Ви муÑите ввеÑти ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/changepassword.bml.error.nonascii=Паролі можуть ÑкладатиÑÑ Ð»Ð¸ÑˆÐµ з Ñимволів ASCII. ПроÑимо вибрати пароль, в Ñкому б не викориÑтовувалиÑÑŒ Ñимволи не ÑуміÑні з ASCII. + +/changepassword.bml.error.notvalidated=Ви не можете змінити ваш пароль, Ñкщо вашу поточну email-адреÑу не перевірено. ДивітьÑÑ, будь лаÑка, це поширене питаннÑ, щоб дізнатиÑÑ, Ñк це зробити. + +/changepassword.bml.forcechange<< + + + + + +
  • Має більше, ніж шіÑÑ‚ÑŒ Ñимволів
  • +
  • МіÑтить щонайменше чотири різні Ñимволи
  • +
  • МіÑтить принаймні один знак чи літеру
  • +
  • Ðе базуєтьÑÑ Ð½Ð° вашому імені кориÑтувача, електронній адреÑÑ– чи прізвиÑьку
  • +
  • Також зверніть увагу, що ми відхилимо ваш пароль, Ñкщо він збігатиметьÑÑ Ð· найпоширенішими паролÑми, Ñкі викориÑтовуютьÑÑ Ñ‚Ð¸ÑÑчами оÑіб.
  • + +p?> + +support@livejournal.com. Будь лаÑка, не додавайте Ñвій пароль до цього лиÑта. p?> +. + +/changepassword.bml.newpassword=Ðовий пароль: + +/changepassword.bml.newpasswordagain=Ðовий пароль (повторно): + +/changepassword.bml.oldpassword=Поточний пароль: + +/changepassword.bml.proceed.instructions=Якщо ваш пароль буде прийнÑто, ви отримаєте лиÑта з повідомленнÑм про зміну паролÑ. Якщо пароль не відповідає будь-Ñкій з зазначених вимог, вам буде необхідно Ñтворити інший. + +/changepassword.bml.relogin=Крім того, ви вийшли зі вÑÑ–Ñ… Ñ–Ñнуючих ÑеанÑів. Ви маєте увійти знов, перш ніж продовжити. + +/changepassword.bml.success.text=Ваш пароль змінено, а вам було надіÑлано лиÑта з відповідним повідомленнÑм. + +/changepassword.bml.title=Змінити пароль + +/community/account.bml.basic.header=Зараз Ñпільнота має базовий рахунок. + +/community/account.bml.basic.text=Багато можливоÑтей [[sitename]] доÑтупні Ð´Ð»Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ–Ð² базового типу. + +/community/account.bml.btn.stayplus=ЗалишитиÑÑŒ на розширеному рахунку + +/community/account.bml.btn.tobasic=Перейти на базовий рахунок + +/community/account.bml.btn.toplus=Перейти на розширений рахунок + +/community/account.bml.choose=Виберіть Ñпільноту + +/community/account.bml.confirm.text=Впевнені, що бажаєте перейти на базовий рахунок? + +/community/account.bml.confirm.title=Впевнені? + +/community/account.bml.main.change=Змінити рахунок + +/community/account.bml.main.switch=Тип рахунку можна змінити в будь-Ñкий чаÑ. + +/community/account.bml.paid.header=Спільнота має платний рахунок. + +/community/account.bml.paid.text=Платний тип рахунку надає вÑÑ– можливоÑÑ‚Ñ– Ñпільнот, Ñ– без реклами. + +/community/account.bml.plus.header=Спільнота має розширений рахунок. + +/community/account.bml.plus.text=Розширений тип рахунку надає більшіÑÑ‚ÑŒ можливоÑтей Ñпільнот [[sitename]], з рекламою, завдÑки Ñкій вам не потрібно платити. + +/community/account.bml.plus.text2=Редагувати Рекламні категорії Ñпільноти. + +/community/account.bml.saved.text=Спільнота має розширений рахунок. + +/community/account.bml.saved.title=Зміни збережено + +/community/account.bml.switchto.basic.header=Базовий рахунок + +/community/account.bml.switchto.basic.text=БільшіÑÑ‚ÑŒ можливоÑтей Ñпільнот [[sitename]] доÑтупні Ð´Ð»Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ–Ð² базового типу. + +/community/account.bml.switchto.plus.header=Платний рахунок + +/community/account.bml.switchto.plus.text=Більше можливоÑтей, ніж у базовому рахунку, з рекламою, завдÑки Ñкій вам не потрібно платити. + +/community/account.bml.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ñпільноти + +/community/create.bml.btn.create=Створити Ñпільноту + +/community/create.bml.btn.proceed=Продовжити... + +/community/create.bml.create.text=Створити нову Ñпільноту легко, проÑто дотримуйтеÑÑŒ інÑтрукцій, що надані нижче. + +/community/create.bml.error.notactive=Ваш рахунок має бути активним, щоб Ñтворити Ñпільноту. ПереконайтеÑÑ, будь лаÑка, що ваш рахунок зараз не помічений Ñк видалений або припинений Ñ– Ñпробуйте ще раз. + +/community/create.bml.error.notperson=Ви маєте увійти до оÑобиÑтого рахунку, щоб Ñтворити Ñпільноту. + +/community/create.bml.error.notvalidated=Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñпільноти вам необхідно підтвердити Ñвою email-адреÑу. + +/community/create.bml.error.notvalidated2=Ðобхідно підтвердити Ñвою адреÑу, щоб Ñтворити Ñпільноту. + +/community/create.bml.error.postrequired=Потрібний метод POST. + +/community/create.bml.error.username.inuse=Ð†Ð¼â€™Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ вже викориÑтовуєтьÑÑ; виберіть інше, будь лаÑка. + +/community/create.bml.error.username.mustenter=Ви маєте ввеÑти Ñ–Ð¼â€™Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/community/create.bml.error.username.reserved=Вибачте, це зарезервоване Ñ–Ð¼â€™Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/community/create.bml.errors.label=Будь лаÑка, зверніть увагу на наÑтупні проблеми та надішліть дані ще раз. + +/community/create.bml.name.head=Ім'Ñ Ñпільноти + +/community/create.bml.name.text=Яке Ñ–Ð¼â€™Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти? Воно з’ÑвитьÑÑ Ð²Ð³Ð¾Ñ€Ñ– Ñпільноти та у каталозі кориÑтувачів, Ñкщо ви оберете, щоб Ñпільнота була додана до нього. + +/community/create.bml.person=Може ви радше бажаєте Ñтворити оÑобиÑтий журнал? + +/community/create.bml.success.btn.enterinfo=Введіть дані Ñпільноти + +/community/create.bml.success.head=УÑпішно! + +/community/create.bml.success.text1=Ваша Ñпільнота було Ñтворено. Додатково, ваш рахунок був зроблений Ñ—Ñ— адмініÑтратором. + +/community/create.bml.success.text2=Ваша Ñпільнота буде доÑтупна тут: + +/community/create.bml.success.text3=Тепер, будь лаÑка, витратьте чаÑ, щоб заповнити деÑкі дані Ñпільноти. Це, здебільшого, необов'Ñзково, але це дозволÑÑ” іншим кориÑтувачам мати уÑÐ²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‡Ð¾Ð³Ð¾ Ñ†Ñ Ñпільнота. + +/community/create.bml.title=Створити нову Ñпільноту + +/community/create.bml.username.charsallowed=Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ñпільноти може міÑтити тільки Ñ€Ñдкові латинÑькі літери (a-z), цифри (0-9) та Ñимвол підкреÑÐ»ÐµÐ½Ð½Ñ (_).
    Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ не може починатиÑÑ Ð°Ð±Ð¾ закінчуватиÑÑ Ð¿Ñ–Ð´ÐºÑ€ÐµÑленнÑм, а також не може мати більше одного Ñимволу підкреÑÐ»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ñ€Ñд.
    Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ не повинно бути довшим за 15 Ñимволів. + +/community/create.bml.username.head=Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/community/create.bml.username.text=Кожний рахунок на [[sitename]] муÑить мати Ñвоє унікальне ім'Ñ. Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ñ” тим, що з'ÑвлÑєтьÑÑ Ð² адреÑÑ– Ñпільноти. + +/community/index.bml.main<< + + + + +новачків, почитайте Ñ—Ñ— Ñ– Ñкоро ви вже Ñамі Ñтанете профі! +p?> + + +
    +Додайте (або українÑький переклад - ) до Ñвоєї Ñтрічки друзів, щоб бути в курÑÑ– уÑÑ–Ñ… подій, що ÑтоÑуютьÑÑ Ñпільноти LiveJournal. +Додайте (або українÑький переклад - ) до Ñвоєї Ñтрічки друзів, щоб бути в курÑÑ– планованного чаÑу проÑтою або ÑкихоÑÑŒ непередбачених збоїв ÑервіÑу.
    +p?> + + +AIM, ICQ, Yahoo!, MSN, та Jabber. Якщо ви також, переÑвідчитьÑÑ, що вказали Ñ—Ñ… Ñеред Ñвоєї перÑональної інформації. Якщо ви маєте платний рахунок, ви також можете отримувати текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° Ñвій Ñтільниковий телефон чи інший мобільний приÑтрій. +p?> + + +платний рахунок. Хоча, звичайно, Ñ” й інші ÑпоÑоби допомоги. +

    +LiveJournal - це проект з відкритим кодом; Ñкщо ви маєте доÑвід Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ розробки Ñерверного програмного забезпеченнÑ, ви можете завітати до LiveJournal Development Community, . Якщо ви маєте ідеї ÑтоÑовно Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ LiveJournal, можете зайти у Розділ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¹ LiveJournal, . Хочете допомогти хоч чимоÑÑŒ? Завітайте до LiveJournal Business Community, . Якщо маєте потребу допомагати людÑм, Ñходіть на Ñторінку нашого центру підтримки - Ñ– допомагайте! Ви знаєтеÑÑŒ на дизайні? Ð”Ð»Ñ Ð²Ð°Ñ Ñ” LiveJournal Art Community, . +p?> + + +музики до фотографії, від мови Ñ– літератури до політики. Також ви можете знайти Ñпільноту про будь-Ñкий куточок нашої кулі. Можливо, що в LiveJournal знайдетьÑÑ Ñпільнота, що приÑвÑчена міÑцю вашого помешканнÑ! +p?> + + +FAQ, де вам поÑÑнÑÑ‚ÑŒ, Ñк Ñтворити влаÑну Ñпільноту. Також Ñ” два розділи FAQ: "Спільноти" та "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами", в Ñких поÑÑнюєтьÑÑ ÑƒÑе, що треба знати про Ñпільноти. Якщо хочетьÑÑ Ð·Ð½Ð°Ñ‚Ð¸ ще більше, ви можете відправити відповідний запит до Ñлужби підтримки. +p?> + + + + +
      +
    • Пошук по Ñпільнотах
    • +
    • Завітайте до Ñпільноти реклами інших Ñпільнот ()
    • +
    • Завітайте до Ñпільноти пошуку ()
    • +
    • Ðбо в Ñпільноту ()
    • +
    + + +Пишіть Jesse Proulx, () Керівникові Ñпільнот. +p?> +. + +/community/index.bml.main2<< + + + + +Ðовачків, де ви знайдете відповіді на більшіÑÑ‚ÑŒ питань, що ви хотіли б задаÑти. Завітайте до Ñпільноти , почитайте Ñ—Ñ—, Ñ– Ñкоро ви вже Ñамі Ñтанете профі! +p?> + + +
    +Додайте (або українÑький переклад - ) до Ñвоєї Ñтрічки друзів, щоб бути в курÑÑ– уÑÑ–Ñ… подій, що мають Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ Ñпільноти [[sitename]].
    +Додайте (або українÑький переклад - ) до вашої Ñтрічки друзів, щоб бути в курÑÑ– планованого чаÑу проÑтою або ÑкихоÑÑŒ непередбачених збоїв ÑервіÑу. +p?> + + +AIM, ICQ, Yahoo!, MSN, та Jabber. Якщо ви також, переÑвідчитьÑÑ, що вказали Ñ—Ñ… Ñеред Ñвоєї перÑональної інформації. Якщо у Ð²Ð°Ñ Ñ” Платний рахунок, ви також можете отримувати текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° Ñвій Ñтільниковий телефон чи інший мобільний приÑтрій. +p?> + + +/paidaccounts/">Платний рахунок. Хоча, звичайно, Ñ” й інші ÑпоÑоби допомогти нам. +

    +[[sitename]] - це проект з відкритим кодом; Ñкщо ви маєте доÑвід Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ розробки Ñерверного програмного забеÑпеченнÑ, ви можете завітати до [[sitename]] Development Community, . Якщо ви маєте ідеї ÑтоÑовно Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ [[sitename]], можете зайти у [[sitename]] Розділ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¹, . Хочете допомогти хоч чимоÑÑŒ? Завітайте до [[sitename]] Business Community, . Якщо маєте потребу допомагати людÑм, Ñходіть на Ñторінку нашого центру підтримки - Ñ– допомагайте! Ви знаєтеÑÑŒ на дизайні? Ð”Ð»Ñ Ð²Ð°Ñ Ñ” [[sitename]] Art Community, . +p?> + + +музики до фотографії, від мови Ñ– літератури до політики. Також ви можете знайти Ñпільноту про будь-Ñкий куточок нашо] кулі. Можливо, що в [[sitename]] знайдетьÑÑ Ñпільнота, що приÑвÑчена міÑцю, де ви живете! +p?> + + +/support/faqbrowse.bml?faqid=78">FAQ, де вам поÑÑнÑÑ‚ÑŒ, Ñк Ñтворити влаÑну Ñпільноту. Також Ñ” два розділи FAQ: "Спільноти" та "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами ", в Ñких поÑÑнюєтьÑÑ ÑƒÑе що вам треба знати про Ñпільноти. Якщо ви вÑе ще хочете дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ, ви можете відправити відповідний запит до Ñлужби підтримки. +p?> + + + + +
      +
    • Пошук по Ñпільнотах
    • +
    • Завітайте до Ñпільноти реклами інших Ñпільнот ()
    • +
    • Завітайте до Ñпільноти пошуку()
    • +
    • Ðбо в Ñпільноту
    • +
    + + +Пишіть Jesse Proulx, () Керівникові Ñпільнот. +p?> +. + +/community/index.bml.title=Центр Ñпільнот + +/community/join.bml.btn.cancel=СкаÑувати + +/community/join.bml.button.join=ПриєднатиÑÑ Ð´Ð¾ Ñпільноти + +/community/join.bml.button.join2=ПриєднатиÑÑ Ð´Ð¾ Ñпільноти + +/community/join.bml.error.already.member=Ви вже Ñ” учаÑником цієї Ñпільноти. + +/community/join.bml.error.closed=Ð¦Ñ Ñпільнота закрита Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… учаÑників. Якщо ви бажаєте приєднатиÑÑ, напишіть, будь лаÑка, одному з наÑтупних наглÑдачів: [[admins]] + +/community/join.bml.error.ischild=[[comm]] може міÑтити інформацію Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих, Ñка, можливо, Ñ” неприпуÑтимою Ð´Ð»Ñ Ð½ÐµÐ¿Ð¾Ð²Ð½Ð¾Ð»Ñ–Ñ‚Ð½Ñ–Ñ…. Ви повинні бути Ñтаршими, ніж 14 років, Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб приєднатиÑÑŒ до цієї Ñпільноти. + +/community/join.bml.error.isminor=[[comm]] може міÑтити матеріали, припуÑтимі лише Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих. Вам повинно бути більше 18 років Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб приєднатиÑÑŒ до цієї Ñпільноти. + +/community/join.bml.error.setage=Відредагуйте Ñвій профіль, щоб зареєÑтрувати Ñвій вік. + +/community/join.bml.error.statusvis.body=Рахунок, під Ñким ви увйшли, Ñ” неактивним рахунком. + +/community/join.bml.error.statusvis.title=Ðеможливо приєднатиÑÑ Ð´Ð¾ Ñпільнот. + +/community/join.bml.label.addtofriends=Додати "[[maintainer]]" до ÑпиÑку друзів.
    + +/community/join.bml.label.addtofriends.note=ПідпиÑка на цю Ñпільноту дозволить вам бачити запиÑи з неї у Ñвоїй Ñтрічці друзів. + +/community/join.bml.label.addtofriends.note2=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñпільноти дозволить вам бачити запиÑи з неї у Ñвоїй Ñтрічці друзів. + +/community/join.bml.label.addtofriends2=ПідпиÑатиÑÑ Ð½Ð° [[comm]] разом з долученнÑм до неї. + +/community/join.bml.label.addtofriends2.modify=ПриєднатиÑÑ Ð´Ð¾ [[comm]], а також змінити передплату Ñпільноти. + +/community/join.bml.label.addtofriends3=Так, Ñ Ñ‚Ð°ÐºÐ¾Ð¶ хочу ÑпоÑтерігати за [[comm]] Ñ– перейти до наÑтупного кроку: Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð². + +/community/join.bml.label.allowposting=Ð¦Ñ Ñпільнота дозволÑÑ” пиÑати вÑім учаÑникам, тому тепер ви маєте дозвіл пиÑати до неї. Якщо на вашому комп'ютері вже запущено клієнтÑьку програму, вам треба перезапуÑтити Ñ—Ñ—, щоб цей журнал з’ÑвивÑÑ Ñƒ ÑпиÑку журналів, до Ñких ви можете пиÑати. + +/community/join.bml.label.allowposting2=Окрім того, Ñ†Ñ Ñпільнота дозволÑÑ” робити запиÑи вÑім учаÑникам. Якщо у Ð²Ð°Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð° клієнтÑька програма [[sitename]], вийдіть з неї та повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñ†Ñ Ñпільнота з’ÑвилаÑÑ Ñƒ ній. + +/community/join.bml.label.auth=Хоча ви тепер лічитеÑÑ ÑƒÑ‡Ð°Ñником, Ñ†Ñ Ñпільнота дозволÑÑ” пиÑати лише авторизованим учаÑникам. Зв'ÑжітьÑÑ Ð· одним із наглÑдачів, Ñкщо ви бажаєте мати доÑтуп до публікуваннÑ. Ðижче надано ÑпиÑок наглÑдачів цієї Ñпільноти: [[admins]] + +/community/join.bml.label.auth2=Завважте, що в цю Ñпільноту можуть пиÑати лише авторизовані кориÑтувачі, проÑто приєднавшиÑÑŒ, ви не отримаєте права пиÑати в Ñпільноту. Щоб отримати право публікації запиÑів, зверніÑÑ‚ÑŒÑÑ Ð´Ð¾ наглÑдачів Ñпільноти: [[admins]] + +/community/join.bml.label.banned=ÐаглÑдач цієї Ñпільноти заборонив вам приєднуватиÑÑ. + +/community/join.bml.label.closed=Ð¦Ñ Ñпільнота Ñ” закритою. Якщо ви зацікавлені в тому, щоб приєднатиÑÑ Ð´Ð¾ неї, то зв'ÑжітьÑÑ, будь лаÑка, з одним із Ñ—Ñ— наглÑдачів. Ðижче надано ÑпиÑок наглÑдачів цієї Ñпільноти: [[admins]] + +/community/join.bml.label.commlogged=Ви увійшли під ім'Ñм Ñпільного рахунку або Ñпільноти, а не під ім'Ñм вашого оÑобиÑтого рахунку. + +/community/join.bml.label.errorcomminfo=Вказані дані Ñпільноти неприпуÑтимі. + +/community/join.bml.label.expls=ÐатиÑніть кнопку нижче, щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти "[[maintainer]]". Зніміть позначку, Ñкщо ви не бажаєте бачити запиÑи Ñпільноти у Ñвоїй Ñтрічці друзів. + +/community/join.bml.label.expls2=Ð”Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ цієї Ñпільноти дозволить вам читати запиÑи, напиÑані лише Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників. Це не дозволить учаÑникам Ñпільноти чи Ñ—Ñ— доглÑдачам читати ваші захищені запиÑи у вашому влаÑному журналі. + +/community/join.bml.label.locked=Ð¦Ñ Ñпільнота не приймає нових учаÑників, тому ви не можете до неї приєднатиÑÑŒ. + +/community/join.bml.label.loginfirst2=Щоб долучитиÑÑ Ð´Ð¾ Ñпільноти Ñпочатку треба увійти. + +/community/join.bml.label.membernow2=Відтепер ви учаÑник Ñпільноти [[commname]]. + +/community/join.bml.label.membernow3=Тепер ви учаÑник Ñпільноти [[commname]]. + +/community/join.bml.label.membernow6=Ви Ñтали учаÑником Ñпільноти [[commname]]. + +/community/join.bml.label.notcomm=Вказаний журнал не Ñ” Ñпільнотою. + +/community/join.bml.label.sure=Ви впевнені? + +/community/join.bml.label.sure2=ПриєднатиÑÑ Ð´Ð¾ [[comm]]? + +/community/join.bml.reqsubmitted.body=Ваш запит на Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ² переданий наглÑдачам.Коли вони підтвердÑÑ‚ÑŒ- ви буде автоматично приєднані до Ñпільноти + +/community/join.bml.reqsubmitted.title=Запит на Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ² переданий + +/community/join.bml.request.body=Спільнота [[comm]] не має відкритої учаÑÑ‚Ñ–. Підтвердіть, будь лаÑка, що ви бажаєте приєднатиÑÑ Ð´Ð¾ цієї Ñпільноти, натиÑнув нижче. + +/community/join.bml.request.reason=Ðеобов'Ñзково, введіть причину, чому ви бажаєте приєднатиÑÑ Ð´Ð¾ цієї Ñпільноти: + +/community/join.bml.request.title=Запит на Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ + +/community/join.bml.success=УÑпішно + +/community/join.bml.title=ПриєднатиÑÑ Ð´Ð¾ Ñпільноти + +/community/join.bml.toomanyfriends=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ [[community]] до друзів перевищить макÑимальну кількіÑÑ‚ÑŒ друзів, Ñка дозволена Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку. Втім, ви наразі приєдналиÑÑ Ð´Ð¾ цієї Ñпільноти. + +/community/leave.bml.button.leave=Покинути Ñпільноту + +/community/leave.bml.button.stopwatch=ВідмовитиÑÑ Ð²Ñ–Ð´ ÑпоÑÑ‚ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð° Ñпільнотою + +/community/leave.bml.label.buttontoleave=ÐатиÑніть кнопку унизу, щоби покинути Ñпільноту "[[commname]]". + +/community/leave.bml.label.buttontostopwatch=ВідмовитиÑÑ Ð²Ñ–Ð´ ÑпоÑÑ‚ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð° Ñпільнотою + +/community/leave.bml.label.infoerror=Ðевірно вказано інформацію про Ñпільноту. + +/community/leave.bml.label.lastmaintainer=Вам не дозволено залишати цю Ñпільноту, оÑкільки ви Ñ” єдиним наглÑдачем. Якщо ви бажаєте залишити Ñпільноту, то призначте іншого наглÑдача, будь лаÑка, а потім Ñпробуйте залишити Ñпільноту ще раз. + +/community/leave.bml.label.logoutfirst2=Щоб покинути Ñпільноту Ñпочатку ви повинні увійти. + +/community/leave.bml.label.removed.stopwatch=Ви більше не ÑпоÑтерігаєте за Ñпільотою [[commname]] . + +/community/leave.bml.label.removed.stopwatch4=Ви більше не ÑпоÑтерігаєте за Ñпільнотою [[commname]]. + +/community/leave.bml.label.removed2=Ð’Ð°Ñ Ð²Ð¸ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¾ зі Ñпільноти [[commname]]. + +/community/leave.bml.label.removed5=Ð’Ð°Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð¾ зі Ñпільноти [[commname]]. + +/community/leave.bml.label.removefromfriends=Також вилучити "[[user]]" зі ÑпиÑку друзів. + +/community/leave.bml.success=УÑпішно + +/community/leave.bml.sure=Ви впевнені? + +/community/leave.bml.title=Покинути Ñпільноту + +/community/leave.bml.title.stopwatch=ВідмовитиÑÑ Ð²Ñ–Ð´ ÑпоÑÑ‚ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð° Ñпільнотою + +/community/manage.bml.commlist.actinfo=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/community/manage.bml.commlist.actinvites=Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +/community/manage.bml.commlist.actions=Дії + +/community/manage.bml.commlist.actmembers2=УчаÑники + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] очікуючих + +/community/manage.bml.commlist.actsettings2=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/community/manage.bml.commlist.customize=ВиглÑд + +/community/manage.bml.commlist.header=Ваші Ñпільноти + +/community/manage.bml.commlist.moderation=Очікують ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ + +/community/manage.bml.commlist.moderation.num2=[[[num]] у черзі] + +/community/manage.bml.commlist.none=Ви не керуєте жодною Ñпільнотою. + +/community/manage.bml.commlist.text=Цими Ñпільнотами ви керуєте або допомагаєте керувати: + +/community/manage.bml.commlist.title=Ðазва + +/community/manage.bml.commlist.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/community/manage.bml.create.header=Створити Ñпільноту + +/community/manage.bml.create.text2=Також ви можете Ñтворити нову Ñпільноту. + +/community/manage.bml.error.badaccounttype=Ви маєте увійти під звичайним рахунком кориÑтувача, щоб мати доÑтуп до цієї Ñторінки. + +/community/manage.bml.joinmail.body=Ð”Ð»Ñ Ñпільнот з модерованою учаÑÑ‚ÑŽ Ñ” кілька параметрів email: + +/community/manage.bml.joinmail.body2=У Ñпільнотах з модерованою учаÑÑ‚ÑŽ ви можете отримувати повідомленнÑ, коли хто-небудь бажає Ñтати учаÑником. + +/community/manage.bml.joinmail.email.all=надÑилати лиÑта щоразу, коли хтоÑÑŒ запитує про приєднаннÑ; + +/community/manage.bml.joinmail.email.digest=Один лиÑÑ‚ Ñ‰Ð¾Ð´Ð½Ñ Ð·Ñ– ÑпиÑком уÑÑ–Ñ… запитів про Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ + +/community/manage.bml.joinmail.email.none=не треба лиÑтів, Ñ ÐºÐ¾Ñ€Ð¸ÑтуватимуÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою, щоб знаходити нові запити. + +/community/manage.bml.joinmail.save=Зберегти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/community/manage.bml.joinmail.title=ÐдмініÑтративні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/community/manage.bml.modemail.body=Ð”Ð»Ñ Ð¼Ð¾Ð´ÐµÑ€Ð¾Ð²Ð°Ð½Ð¸Ñ… Ñпільнот, ви можете обрати, надÑилати лиÑти або ні: + +/community/manage.bml.modemail.no=не треба лиÑтів, Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸Ð¼Ñƒ чергою на модерацію вручну. + +/community/manage.bml.modemail.yes=надÑилати мені лиÑта щоразу, Ñк хтоÑÑŒ додає Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ черги; + +/community/manage.bml.title=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами + +/community/manage.bml.title2=Керувати Ñпільнотами + +/community/members.bml.error.adding=[[user]] заборонив цієї Ñпільноті надÑилати йому запрошеннÑ. + +/community/members.bml.error.alreadyadded=[[user]] не був доданий тому, що він вже маєть доÑтуп до Ñпільноти. + +/community/members.bml.error.alreadysent=[[user]] не може бути доданий тому, що ймоу [[datetime]] вже було надіÑлано лиÑÑ‚-підтвердженнÑ. Будь лаÑка, почекайте на його відповідь. + +/community/members.bml.error.invaliduser=Ðеможливо додати Ñпільноту чи об'єднаний рахунок: [[user]] + +/community/members.bml.error.ischild=Вибачте, але кориÑтувача [[user]] не можна запроÑити до цієї Ñпільноти, оÑкільки його зареєÑтрований день Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ Ñвідчить принаймні про 14-річний вік. + +/community/members.bml.error.isminor=Вибачте, але кориÑтувача [[user]] не можна запроÑити до цієї Ñпільноти, оÑкільки його зареєÑтрований день Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ Ñвідчить принаймні про 18-річний вік. + +/community/members.bml.error.limit=Ðеможливо запроÑити [[user]], доÑÑгнута макÑимальна межа запрошувань Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти. + +/community/members.bml.error.noaccess=Тільки наглÑдачі Ñпільноти можуть змінювати ÑпиÑки учаÑників. Ви не Ñ” наглÑдачем Ñпільноти [[comm]]. + +/community/members.bml.error.noattr=Ðе вибрано атрибутів Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[user]] + +/community/members.bml.error.nocomm=Спільноту не знайдено. + +/community/members.bml.error.notactive=Рахунок не активний: [[user]] + +/community/members.bml.error.notcomm=[[user]] не Ñ” Ñпільнотою. + +/community/members.bml.error.nouser=КориÑтувач не Ñ–Ñнує: [[user]] + +/community/members.bml.error.unknown=Помилка при запрошенні [[user]]. ПереконайтеÑÑ, будь лаÑка, що він не Ñ” вже учаÑником Ñ– Ñпробуйте ще раз. + +/community/members.bml.key.admin=ÐаглÑдач + +/community/members.bml.key.member=УчаÑник + +/community/members.bml.key.moderate=Модератор + +/community/members.bml.key.post=Дозволено пиÑати + +/community/members.bml.key.preapprove=Ðе цензоруєтьÑÑ + +/community/members.bml.key.user=КориÑтувач + +/community/members.bml.manage2=Керувати Ñпільнотами + +/community/members.bml.name=Ім'Ñ Ñпільноти: [[name]] + +/community/members.bml.nextlink=(ÐаÑтупна Ñторінка...) + +/community/members.bml.prevlink=(ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ñторінка...) + +/community/members.bml.reinvited2=[[user]] було знов запрошено приєднатиÑÑ Ð´Ð¾ цієї Ñпільноти. Йому буде необхідно прийнÑти Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ð° Ñторінці запрошень Ñпільноти. + +/community/members.bml.settings2=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/community/members.bml.success.added=додані: [[list]] + +/community/members.bml.success.deleted=вилучені: [[list]] + +/community/members.bml.success.header=УÑпішно + +/community/members.bml.success.invited=ÐаÑтупні кориÑтувачі були уÑпішно запрошені до цієї Ñпільноти з переліченими привілеÑми: + +/community/members.bml.success.invited2=ÐаÑтупні кориÑтувачі були уÑпішно запрошені до цієї Ñпільноти із переліченими привілеÑми. Їм буде необхідно прийнÑти Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð½Ð° Ñторінці запрошень Ñпільноти, перш ніж вони зможуть Ñтати учаÑниками Ñпільноти. + +/community/members.bml.success.message2=Зроблено такі зміни: + +/community/members.bml.success.nochanges=Жодних змін не було зроблено. + +/community/members.bml.success.return2=ПовернутиÑÑ Ð´Ð¾ ÑпиÑку + +/community/members.bml.title=УчаÑники Ñпільноти + +/community/members.bml.update=Поновити параметри + +/community/moderate.bml.approve.button=Так, Ñхвалити + +/community/moderate.bml.approve.header=Схвалити цей запиÑ? + +/community/moderate.bml.approve.preapprove=Ðвтоматично Ñхвалювати запиÑи [[user]] у цій Ñпільноті. + +/community/moderate.bml.approve.text=Чи ви впевнені, що бажаєте Ñхвалити цей запиÑ? + +/community/moderate.bml.brlist.actions=Дії + +/community/moderate.bml.brlist.poster=Ðвтор + +/community/moderate.bml.brlist.subject=Початок теми + +/community/moderate.bml.brlist.time=Ð§Ð°Ñ + +/community/moderate.bml.brlist.view=ДивитиÑÑŒ + +/community/moderate.bml.browse.empty=Черга на Ñ†ÐµÐ½Ð·Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ. + +/community/moderate.bml.browse.header=Модерувати Ñпільноту + +/community/moderate.bml.browse.text=ОÑÑŒ черга на модерацію Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти [[link]] + +/community/moderate.bml.choice.approve=Схвалити + +/community/moderate.bml.choice.reject=Відхилити + +/community/moderate.bml.error.noaccess=Ви не модеруєте Ñпільноту [[comm]]. + +/community/moderate.bml.error.noentry=Ð—Ð°Ð¿Ð¸Ñ Ð½Ðµ знайдено (можливо, він обролений іншим модератором). + +/community/moderate.bml.error.nolist=Ви не модеруєте жодної Ñпільноти + +/community/moderate.bml.error.notfound=Рахунок Ñпільноти не знайдено. + +/community/moderate.bml.manage=Керувати Ñпільнотами + +/community/moderate.bml.moderate=Модерувати цю Ñпільноту + +/community/moderate.bml.modlist.actions=Дії + +/community/moderate.bml.modlist.actmodempty=[Модерувати] + +/community/moderate.bml.modlist.actmoderate=Модерувати + +/community/moderate.bml.modlist.count=Розмір черги + +/community/moderate.bml.modlist.header=Модерувати Ñпільноти + +/community/moderate.bml.modlist.title=Ðазва + +/community/moderate.bml.modlist.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/community/moderate.bml.posted.appheader=Без модерації + +/community/moderate.bml.posted.apptext=Крім того, запиÑи [[user]] будуть автоматично ÑхвалюватиÑÑ Ñƒ цій Ñпільноті. + +/community/moderate.bml.posted.header=УÑпішно + +/community/moderate.bml.posted.proterror=Ð—Ð°Ð¿Ð¸Ñ Ð½Ðµ було опубліковано через помилку протокола: [[err]] + +/community/moderate.bml.posted.text=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² уÑпішно опубліковано. + +/community/moderate.bml.reject.button=Так, відхилити + +/community/moderate.bml.reject.header=Відхилити цей запиÑ? + +/community/moderate.bml.reject.reason=Ви також можете поÑÑнити автору причини, з Ñких ви відхилÑєте його запиÑ. Їх буде надіÑлано автору електронною поштою. + +/community/moderate.bml.reject.text=Чи ви впевнені, що хочете відхилити цей запиÑ? + +/community/moderate.bml.rejected.header=Відхилено. + +/community/moderate.bml.rejected.text=Ð—Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÐµÐ½Ð¾. + +/community/moderate.bml.title=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ñ–Ñ Ñпільноти + +/community/pending.bml.approve.title=Схвалити учаÑÑ‚ÑŒ? + +/community/pending.bml.no=ÐÑ– + +/community/pending.bml.nopending.body=Ðемає очікуючих запитів на учаÑÑ‚ÑŒ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти. + +/community/pending.bml.nopending.title=Жодних очікуючих + +/community/pending.bml.success.added=Ви додали [[num]] [[?num|оÑобу|оÑіб]] до цієї Ñпільноти. + +/community/pending.bml.success.ignored=Є [[num]] [[?num|request is|requests are]], що вÑе ще очікують рішень. + +/community/pending.bml.success.previous=[[num]] [[?num|request has|requests have]] не було оброблено, оÑкільки вони вже не очікували рішеннÑ. Інший наглÑдач міг вже обробити [[?num|it|them]]. + +/community/pending.bml.success.rejected=Ви відхилили [[num]] [[?num|request|requests]] приєднатиÑÑ Ð´Ð¾ цієї Ñпільноти. + +/community/pending.bml.title=Очікуючі запити на учаÑÑ‚ÑŒ + +/community/pending.bml.yes=Так + +/community/search.bml.button.clear=ОчиÑтити форму + +/community/search.bml.button.search=Шукати! + +/community/search.bml.checkbox.onlywithpics=Тільки Ñпільноти з юзерпиками + +/community/search.bml.label.byinterest=За зацікавленнÑм + +/community/search.bml.label.bylocation=За міÑцем Ð·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/community/search.bml.label.bytime=За чаÑом Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/community/search.bml.label.city=МіÑто: + +/community/search.bml.label.country=Країна: + +/community/search.bml.label.displayoptions=Показати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/community/search.bml.label.hasmember=Має учаÑників + +/community/search.bml.label.othercriteria=Інші критерії + +/community/search.bml.label.outputformat=Формат виводу: + +/community/search.bml.label.records=ЗапиÑів на Ñторінці: + +/community/search.bml.label.searchcomm=Шукати Ñпільноти + +/community/search.bml.label.selecriteria=Оберіть критерії, за Ñкими ви бажаєте шукати Ñпільноти. Результатом буде перетин по вÑÑ–Ñ… критеріÑÑ… пошуку. Інакше кажучи, кожна позначка, Ñку ви Ñтавите, означає "І", а не "ÐБО". + +/community/search.bml.label.sortmethod=Метод ÑортуваннÑ: + +/community/search.bml.label.stateprovince=Штат/облаÑÑ‚ÑŒ: + +/community/search.bml.label.updated=ВоÑтаннє оновлювалоÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом + +/community/search.bml.sel.bypicture=За юзерпиками + +/community/search.bml.sel.communityname=За назвою Ñпільноти + +/community/search.bml.sel.commview=Показувати Ñпільноту + +/community/search.bml.sel.day=Ð´Ð½Ñ + +/community/search.bml.sel.month=міÑÑÑ†Ñ + +/community/search.bml.sel.simple=ПроÑтий + +/community/search.bml.sel.updatetime=За чаÑом Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/community/search.bml.sel.username=За іменем кориÑтувача + +/community/search.bml.sel.week=Ñ‚Ð¸Ð¶Ð½Ñ + +/community/search.bml.title=Пошук Ñпільноти + +/community/sentinvites.bml.date=Дата надÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/community/sentinvites.bml.error.notcomm=[[user]] не Ñ” Ñпільнотою. + +/community/sentinvites.bml.key.date=Дата + +/community/sentinvites.bml.key.sentby=ÐадіÑлав + +/community/sentinvites.bml.key.status=Стан + +/community/sentinvites.bml.none.body=Жодних запрошень не було надіÑлано за оÑтанні 30 днів. Якщо ви бажаєте запроÑити людей до цієї Ñпільноти, завітайте, будь лаÑка, до Сторінки кориÑтувачів. + +/community/sentinvites.bml.none.title=Жодних запрошень не знайдено + +/community/sentinvites.bml.send=ÐадіÑлати Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +/community/sentinvites.bml.title=ÐадіÑлані Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +/community/settings.bml.button.changecommunity=Поновити параметри + +/community/settings.bml.button.createcommunity=Створити Ñпільноту + +/community/settings.bml.error.alreadycomm=Рахунок вже Ñ” Ñпільнотою. + +/community/settings.bml.error.badpassword=Ðевірний пароль Ñпільноти + +/community/settings.bml.error.hasentries=Цей рахунок вже має запиÑи Ñ– не може бути перетворений. + +/community/settings.bml.error.maintainertype=ДоглÑдачем має бути оÑоба, а не інший Ñпільний рахунок. + +/community/settings.bml.error.noaccess=Тільки доглÑдач Ñпільноти може змінювати параметри Ñпільноти. Ви не Ñ” доглÑдачем Ñпільноти [[comm]]. + +/community/settings.bml.error.notcomm=Це не рахунок Ñпільноти. + +/community/settings.bml.error.notfound=Рахунок Ñпільноти не знайдено. + +/community/settings.bml.error.samenames=Рахунок доглÑдача та рахунок Ñпільноти не можуть бути однакові. + +/community/settings.bml.label.adultcontentconcepts=ДеÑкі елементи Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/community/settings.bml.label.adultcontentexplicit=Відверті елементи Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/community/settings.bml.label.adultcontentheader=Ð”Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/community/settings.bml.label.adultcontentnone=Без елементів Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/community/settings.bml.label.adultcontentnote=Це параметр Ð´Ð»Ñ Ñ†Ñ–Ð»Ð¾Ñ— Ñпільноти. Ð”Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ "Відверті елементи Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих", кориÑтувачі віком до [[explicitage]] років будуть недопущені до переглÑду Ñпільноти. УÑтановка Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ "ДеÑкі елементи Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих" не допуÑкатиме кориÑтувачів віком до [[conceptsage]] років. + +/community/settings.bml.label.adultcontenttext=Чи міÑтить ваша Ñпільнота інформацію Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих? + +/community/settings.bml.label.anybodycan=Ð’ÑÑ– учаÑники
    Будь-хто може пиÑати одразу Ñк Ñтає учаÑником. + +/community/settings.bml.label.changeheader=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти + +/community/settings.bml.label.changetext=Тут ви можете змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти, Ñкою ви керуєте або за Ñкою доглÑдаєте. + +/community/settings.bml.label.closedmemb2=Закрита учаÑÑ‚ÑŒ
    Ðіхто не може приєднуватиÑÑ Ð´Ð¾ Ñпільноти. + +/community/settings.bml.label.commchanged=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñпільноти змінено. + +/community/settings.bml.label.commcreate=Це - рахунок, Ñкий ви бажаєте перетворити на Ñпільноту. Він має бути вже Ñтвореним, але ще не викориÑтаним, бо піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ багато різних людей потенційно зможе туди пиÑати. + +/community/settings.bml.label.commcreate2=Це - рахунок, Ñкий ви хочете перетворити на Ñпільноту. Він має бути вже Ñтвореним, але ще не вживаним Ñк індивідуальний, бо піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ різні люди потенційно зможуть пиÑати туди. + +/community/settings.bml.label.commcreated=Спільноту Ñтворено. + +/community/settings.bml.label.commheader=Рахунок Ñпільноти + +/community/settings.bml.label.comminfo=Дані Ñпільноти + +/community/settings.bml.label.commopts=Параметри Ñпільноти + +/community/settings.bml.label.commsite=Сайт Ñпільноти + +/community/settings.bml.label.community=Спільнота: + +/community/settings.bml.label.createheader=Створити Ñпільноту + +/community/settings.bml.label.createtext=ЗвідÑи ви можете Ñтворити рахунок Ñпільноти. Спільнота - це Ñпеціальний тип рахунка, що дозволÑÑ” іншим кориÑтувачам приєднуватиÑÑ Ñ– пиÑати до неї. Як приклад Ñпільноти, ви можете подивитиÑÑ Ñпільноту українÑької мови. + +/community/settings.bml.label.createtext2=Тут ви можете Ñтворити рахунок Ñпільноти. Спільнота - це оÑобливий тип рахунка, до Ñкого інші кориÑтувачі можуть приєднуватиÑÑ Ñ‚Ð° пиÑати. + +/community/settings.bml.label.createtext2_example=Як приклад Ñпільноти дивітьÑÑ Ñпільноту [[commname]]. + +/community/settings.bml.label.howoperates=Оберіть, Ñким чином діє ваша Ñпільнота. Ви можете змінити це пізніше. + +/community/settings.bml.label.maintainer=ДоглÑдач: + +/community/settings.bml.label.maintainer.login=Якщо це не рахунок доглÑдача, увійдіть Ñк хто-небудь інший. + +/community/settings.bml.label.maintainer.login2=Якщо це не рахунок доглÑдача, увійдіть Ñк хто-небудь інший. + +/community/settings.bml.label.managepage=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами - додати кориÑтувачів, надати право пиÑати до Ñпільноти, призначити модераторів, тощо. + +/community/settings.bml.label.membership=УчаÑÑ‚ÑŒ + +/community/settings.bml.label.moderatedmemb=Модерована учаÑÑ‚ÑŒ
    Запити на учаÑÑ‚ÑŒ надÑилаютьÑÑ Ð²Ð°Ð¼ Ð´Ð»Ñ ÑхваленнÑ. + +/community/settings.bml.label.modheader=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ñ–Ñ + +/community/settings.bml.label.modis=Модерована
    Ðові запиÑи мають бути Ñхвалені модератором. + +/community/settings.bml.label.modisnt=Ðемодерована
    Ðові запиÑи з'ÑвлÑÑŽÑ‚ÑŒÑÑ Ð¾Ð´Ñ€Ð°Ð·Ñƒ. + +/community/settings.bml.label.modtext=Чи модеруютьÑÑ Ð½Ð¾Ð²Ñ– запиÑи до цієї Ñпільноти? + +/community/settings.bml.label.nmcan=Ðе-учаÑники можуть пиÑати
    КориÑтувачі можуть пиÑати до цієї Ñпільноти, не приєднуючиÑÑŒ до неї. + +/community/settings.bml.label.nmcan2=Дозволити робити запиÑи вÑім кориÑтувачам
    КориÑтувачі можуть робити запиÑи до цієї Ñпільноти, не приєднуючиÑÑŒ до неї. + +/community/settings.bml.label.nmcant=Тільки учаÑники можуть пиÑати
    КориÑтувачі мають приєднатиÑÑ Ð´Ð¾ Ñпільноти, щоби мати право пиÑати до неї. + +/community/settings.bml.label.nmcant2=ЗапиÑи можуть робити тільки учаÑники Ñпільноти
    КориÑтувачі повинні приєднатиÑÑŒ до цієї Ñпільноти, щоб робити запиÑи. + +/community/settings.bml.label.nmheader=ДоÑтуп Ð´Ð»Ñ Ð½Ðµ-учаÑників + +/community/settings.bml.label.nmtext=Чи можуть кориÑтувачі пиÑати до Ñпільноти, не приєднуючиÑÑŒ до неї? + +/community/settings.bml.label.openmemb=Відкрита учаÑÑ‚ÑŒ
    Будь-хто може приєднуватиÑÑ Ð±ÐµÐ· ÑхваленнÑ. + +/community/settings.bml.label.password=Пароль: + +/community/settings.bml.label.postaccess=ДоÑтуп до напиÑÐ°Ð½Ð½Ñ + +/community/settings.bml.label.rellinks=Важливі поÑиланнÑ: + +/community/settings.bml.label.selcan=Обрати учаÑників
    Тільки деÑкі учаÑники можуть пиÑати, коли наглÑдач надав їм доÑтуп. + +/community/settings.bml.label.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/community/settings.bml.label.whocanjoin=Хто може приєднуватиÑÑ Ð´Ð¾ вашої Ñпільноти? + +/community/settings.bml.label.whocanpost=Хто може пиÑати до цієї Ñпільноти? + +/community/settings.bml.manage2=Керувати Ñпільнотами + +/community/settings.bml.members2=УчаÑники + +/community/settings.bml.name=Ðазва Ñпільноти: [[name]] + +/community/settings.bml.success=УÑпішно + +/community/settings.bml.title.create=Створити Ñпільноту + +/community/settings.bml.title.modify=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти + +/community/transfer.bml.account=Рахунок Ñпільноти + +/community/transfer.bml.badstatus.body=Рахунок, під Ñким ви увійшли, не активний Ñ– не може зараз кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою. + +/community/transfer.bml.badstatus.title=Стан рахунку + +/community/transfer.bml.body=Якщо ви маєте пароль до Ñпільноти Ñ– наразі не Ñ” наглÑдачем, то ви можете зробити Ñебе наглÑдачем, заповнивши наÑтупну форму. + +/community/transfer.bml.button.title=ПеренеÑти Ñпільноту + +/community/transfer.bml.error.alreadyadmin=Вже наглÑдач Ñпільноти. + +/community/transfer.bml.error.badstatus=Спільнота не активна. + +/community/transfer.bml.error.mismatch=Пароль не підходить. + +/community/transfer.bml.error.nopassword=Пароль не наданий. + +/community/transfer.bml.error.notcomm=Рахунок не Ñ” Ñпільнотою. + +/community/transfer.bml.error.notfound=Рахунок не знайдений. + +/community/transfer.bml.password=Пароль Ñпільноти + +/community/transfer.bml.success.body=Ви уÑпішно додали Ñебе Ñк наглÑдчача [[comm]]. + +/community/transfer.bml.success.title=УÑпішно + +/community/transfer.bml.title=ПеренеÑти Ñпільноту: + +/create.bml.acctinfo=Дані рахунку + +/create.bml.birthday.birthdate=День народженнÑ: + +/create.bml.birthday.head=Перевірка віку + +/create.bml.birthday.question=Оберіть, будь лаÑка, міÑÑць, день та рік, коли ви народилиÑÑ. Ми вимагаємо ці дані Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ, щоб відповідати Ðкту "Про захиÑÑ‚ прав дитини в інтернеті" (COPPA). Ці дані не зберігаютьÑÑ Ð² нашої базі даних Ñ– викориÑтовуютьÑÑ Ð»Ð¸ÑˆÐµ протÑгом ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. Прочитайте нашу політику приватноÑÑ‚Ñ–, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про те, Ñк ми поводимоÑÑ Ð· даними. + +/create.bml.birthday.question_1=Ми вимагаємо цю інформацію у відповідноÑÑ‚Ñ– із Ðктом "Про захиÑÑ‚ прав дитини в інтернеті" (COPPA). + +/create.bml.birthday.question_3=Будь лаÑка, оберіть міÑÑць, день та рік Ñвого народженнÑ. Ми вимагаємо цю інформацію при Ñтворенні рахунку у відвовідноÑÑ‚Ñ– із Ðктом "Про захиÑÑ‚ прав дитини в інтернеті" (COPPA). Якщо вам ще немає 13 років, ви не можете кориÑтуватиÑÑ Ð½Ð°ÑˆÐ¸Ð¼ ÑервіÑом. Прочитайте наші правила приватноÑÑ‚Ñ–, щоб дізнатиÑÑ Ð¿Ñ€Ð¾ нашу роботу з інформацією. + +/create.bml.birthday.required=(обов'Ñзково) + +/create.bml.birthday.security=Рівень безпеки: + +/create.bml.birthday.warning=Ð’Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ñ…Ð¸Ð±Ð½Ð¾Ð³Ð¾ Ð´Ð½Ñ Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ завадити вам Ñтворити новий рахунок або кориÑтуватиÑÑ Ñвоїм рахунком у майбутньому. + +/create.bml.btn.create=Створити журнал + +/create.bml.btn.proceed=Продовжити... + +/create.bml.captcha.answer=Відповідь: + +/create.bml.captcha.audiodesc=Введіть цифри, Ñкі ви чуєте, щоб довеÑти, що ви не Ñ” Ñпам-роботом: + +/create.bml.captcha.desc=Введіть літери та цифри, Ñкі ви бачите нижче, щоб довеÑти, що ви не Ñ” Ñпам-роботом. Якщо ви не можете читати текÑÑ‚, введіть "AUDIO" Ñ– пройдіть заміÑÑ‚ÑŒ цього звуковий теÑÑ‚. + +/create.bml.captcha.hear=Введіть цифри, Ñкі ви чуєте. + +/create.bml.captcha.invalid=ÐеприпуÑтима відповідь на попереднє питаннÑ. Спробуйте ще. + +/create.bml.captcha.play=Відтворити звук + +/create.bml.captcha.prove=Доведіть, що ви - людина + +/create.bml.captcha.vis=Введіть літери та цифри, що зображені вище. Якщо ви не можете читати текÑÑ‚, введіть "Audio" Ñ– пройдіть заміÑÑ‚ÑŒ цього звуковий теÑÑ‚. + +/create.bml.clusterselect.cluster=КлаÑтер: + +/create.bml.clusterselect.clusternum=КлаÑтер [[number]] + +/create.bml.clusterselect.head=Вибір клаÑтера + +/create.bml.clusterselect.nocluster=Ðемає клаÑтера + +/create.bml.clusterselect.text=Будь лаÑка, оберіть клаÑтер, в Ñкому бажаєте Ñтворити новий рахунок. Зверніть увагу: це відладовий/теÑтовий параметр. Його не бачитимуть та не знатимуть кінцеві кориÑтувачі. + +/create.bml.community=Може ви радше бажаєте Ñтворити Ñпільноту? + +/create.bml.coppa.required=ÐÐ°Ð´Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— інформації вимагає закон.Якщо ви бажаєте приховати ваш вік, ви це можете зробити на Ñторінці вашого профілю. + +/create.bml.create.head=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ журналу + +/create.bml.create.text=Створити новий LiveJournal легко, проÑто дотримуйтеÑÑŒ наÑтанов, наведених нижче! + +/create.bml.create.text_1=ОÑÑŒ інформаціÑ, Ñку ми потребуємо, щоб Ñтворити ваш рахунок. УÑÑ– Ð¿Ð¾Ð»Ñ Ñ” обов'Ñзковими. + +/create.bml.email.head=Ваша e-mail адреÑа + +/create.bml.email.input.head=E-mail адреÑа: + +/create.bml.email.invite.body<< +Шановний [[username]], + +Один з тих, кого ви запроÑили приєднатиÑÑ Ð´Ð¾ [[sitename]], прийнÑв ваше запрошеннÑ. ОÑÑŒ поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ його нового профілю: +[[infolink]] + +Якщо ви бажаєте запроÑити більше друзів, то перейдіть за цим поÑиланнÑм: +[[invitelink]] + +ДÑкуємо за підтримку [[sitename]]! +. + +/create.bml.email.invite.subject=Друг прийнÑв Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ [[sitename]] + +/create.bml.email.promise=Ми ніколи не передавитимемо та не продаватимемо вашу електронну адреÑу. Політика конфіденційноÑÑ‚Ñ– + +/create.bml.email.text2=З метою перевірки та безпеки, нам потрібна ваша e-mail адреÑа. За жодних обÑтавин вона не буде продана або передана Ñпамерам. Ми ненавидимо Ñ—Ñ… більше, ніж будь що. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації прочитайте нашу політику конфіденційноÑÑ‚Ñ–. + +/create.bml.email.text3=З метою перевірки та безпеки, нам потрібна ваша e-mail адреÑа. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації щодо викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¸Ñ… даних прочитайте нашу політику конфіденційноÑÑ‚Ñ–. + +/create.bml.email.text_1=Ми ніколи нікому не надаємо чи продаємо вашу адреÑу електронної пошти. Прочитайте наші правила приватноÑÑ‚Ñ–, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ. + +/create.bml.error.birthday.invalid=Ви маєте ввеÑти дійÑний день народженнÑ. + +/create.bml.error.coppa.under13=Вибачте, але за заборонами COPPA, ви не можете кориÑтуватиÑÑ Ð¿Ð¾Ñлугою LiveJournal, поки вам не буде 13 років. Будь лаÑка, повертайтеÑÑ Ð½Ð° Ñвою 13-ту річницю. + +/create.bml.error.email.blank=Ви маєте надати вашу email-адреÑу. + +/create.bml.error.email.lj_domain=Ви не можете кориÑтуватиÑÑ Ð¿Ñевдонімом на [[domain]] Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. Будь лаÑка, вкажіть іншу email-адреÑу. + +/create.bml.error.email.nospaces=Ð’ email-адреÑÑ– не дозволені пробіли. Якщо ви абонент провайдера AOL, пам’Ñтайте, що вашою email-адреÑою Ñ” ваше ÐОL-ім'Ñ Ð· видаленими пробілами, що закінчуєтьÑÑ Ð½Ð° @aol.com + +/create.bml.error.password.asciionly=Ви можете викориÑтовувати лише Ñимволи ASCII у паролі. + +/create.bml.error.password.blank=Ви маєте ввеÑти пароль. + +/create.bml.error.password.nomatch=Паролі не збігаютьÑÑ. + +/create.bml.error.postrequired=Ðеобхідний метод POST. + +/create.bml.error.tos=Ви маєте прочитати та погодитиÑÑŒ з Умовами викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ð° Політикою конфіденційноÑÑ‚Ñ–. + +/create.bml.error.username.blank=Будь лаÑка, вкажіть Ñ–Ð¼â€™Ñ Ð°Ð±Ð¾ пÑевдонім. + +/create.bml.error.username.inuse=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже викориÑтовуєтьÑÑ; будь лаÑка, виберіть інше. + +/create.bml.error.username.iscode=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ñ” кодом-запрошеннÑм, не ім’Ñм кориÑтувача. + +/create.bml.error.username.mustenter=Ви маєте ввеÑти Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/create.bml.error.username.purged=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, Ñке ви ввели, належало рахунку, Ñкий було видалено, а його дані було знищено. Якщо ви бажаєте ÑкориÑтатиÑÑ Ñ†Ð¸Ð¼ ім’Ñм кориÑтувача, то ви муÑите Ñпочатку придбати знак Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ–Ñнуючого рахунку. + +/create.bml.error.username.reserved=Вибачте, це зарезервоване Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/create.bml.errors.label=Будь лаÑка, зверніть увагу на наÑтупні проблеми та відішліть дані ще раз. + +/create.bml.field.birthday=День Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/create.bml.field.catchap=Підтвердіть, що ви людина + +/create.bml.field.confirmpass=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ + +/create.bml.field.email=Email-адреÑа + +/create.bml.field.legal=Юридичні деталі + +/create.bml.field.news=Ðовини Ñайту + +/create.bml.field.password=Пароль + +/create.bml.field.username=КориÑтувач + +/create.bml.getnews=Так, Ñ‡Ð°Ñ Ð²Ñ–Ð´ чаÑу повідомлÑйте мені про Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ [[sitename]] + +/create.bml.initial.friend.lj_maintenance=Звіти про заплановані та незаплановані проÑтої та профілактику Ñерверів + +/create.bml.initial.friend.lj_spotlight=Відкрийте Ð´Ð»Ñ Ñебе нових друзів та Ñпільноти + +/create.bml.initial.friend.news=Ðовини та події LiveJournal + +/create.bml.initial.friend.tipoftheday=Поради щодо кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ новим журналом + +/create.bml.initialfriends=Додати ці журнали до вашого ÑпиÑку друзів, щоб бути в курÑÑ– новин та інформації про Ñайт. + +/create.bml.initialfriends.heading=Початкові друзі + +/create.bml.intro=Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ LiveJournal заповніть форму нижче, або ви можете Ñтворити Ñпільноту. + +/create.bml.jointitle=ПриєднатиÑÑ Ð´Ð¾ [[sitename]] + +/create.bml.name.head=Ваше ім'Ñ + +/create.bml.name.input.head=Ім'Ñ: + +/create.bml.name.text=Яке ваше Ñ–Ð¼â€™Ñ Ñ‡Ð¸ прізвиÑько? Воно з’ÑвитьÑÑ Ð²Ð³Ð¾Ñ€Ñ– вашого журналу та у каталозі кориÑтувачів, Ñкщо ви оберете бути занеÑеним до нього. Ви не повинні надавати ваше повне Ñ–Ð¼â€™Ñ Ð°Ð±Ð¾ навіть ваше реальне ім’Ñ. + +/create.bml.password.head=Пароль + +/create.bml.password.input.head1=Пароль: + +/create.bml.password.input.head2=Підтвердіть пароль: + +/create.bml.password.secure.pt1=має ÑкладатиÑÑ Ñ‰Ð¾Ð½Ð°Ð¹Ð¼ÐµÐ½ÑˆÐµ з 6 Ñимволів. + +/create.bml.password.secure.pt2=ÑкладаєтьÑÑ Ñ‰Ð¾Ð½Ð°Ð¹Ð¼ÐµÐ½ÑˆÐµ з чотирьох різних Ñимволів. + +/create.bml.password.secure.pt3=міÑтить щонайменше один Ñимвол чи цифру. + +/create.bml.password.secure.pt4=не може збігатиÑÑ Ð· ім'Ñм кориÑтувача чи електронною поштою. + +/create.bml.password.secure2=Ð”Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— ж безпеки ви муÑите обрати безпечний пароль. Він має бути щонайменше 6 Ñимволів довжиною та міÑтити принаймні чотири різних Ñимволи. Він також повинен міÑтити принаймні одну цифру або Ñимвол, він не повинен бути заÑнований на вашому імені кориÑтувача, прізвиÑьку або електронній адреÑÑ–. Подальші наÑтанови читайте у нашіх поширених питаннÑÑ… про те, Ñк обрати безпечний пароль. + +/create.bml.password.secure_1=Ви маєте обрати безпечний пароль, Ñкий: + +/create.bml.password.text=Оберіть пароль. + +/create.bml.proceed.btn.proceed=Продовжити... + +/create.bml.proceed.warning=ÐатиÑкайте Продовжити лише один раз!! + +/create.bml.readandagree=Я прочитав(ла) та погоджуюÑÑŒ з Умовами викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ð° Політикою конфіденційноÑÑ‚Ñ– + +/create.bml.success.btn.enterinfo=Введіть оÑобиÑÑ‚Ñ– дані + +/create.bml.success.head=УÑпішно! + +/create.bml.success.text1=Ваш журнал було Ñтворено. Важливі реєÑтраційні дані, Ñкі міÑÑ‚ÑÑ‚ÑŒ подальші наÑтанови, було надіÑлано до [[email]]. Обов'Ñзково підтвердіть ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу, натиÑнуши на поÑиланнÑ, Ñке надіÑлано вам в електронному лиÑÑ‚Ñ–. + +/create.bml.success.text2=Ваш LiveJournal буде доÑтупний тут: + +/create.bml.success.text3=Ртепер, будь лаÑка, витратьте чаÑ, щоб заповнити деÑкі дані про Ñебе. Це, здебільшого, необов'Ñзково, але це дає нам можливіÑÑ‚ÑŒ зрозуміти, хто кориÑтуєтьÑÑ LiveJournal. + +/create.bml.title=Створити новий журнал + +/create.bml.title_1=Створити Ваш [[siteabbr]] Рахунок + +/create.bml.tos.heading=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +/create.bml.tos.p1.3=Перш ніж продовжити, ви маєте прочитати та погодитиÑÑ Ð· Умовами Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг (до Ñких входить наша політика приватноÑÑ‚Ñ–). + +/create.bml.useacctcodes.entercode=Щоб Ñтворити новий рахунок, введіть код ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. Щою дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ, читайте Як мені Ñтворити рахунок? + +/create.bml.useacctcodes.welcome=ЛаÑкаво проÑимо + +/create.bml.username.box.head=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/create.bml.username.charsallowed=Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача може міÑтити тільки латинÑькі Ñ€Ñдкові літери (a-z), цифри (0-9) та Ñимвол підкреÑÐ»ÐµÐ½Ð½Ñ (_).
    Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ не може починатиÑÑ Ð°Ð±Ð¾ закінчуватиÑÑ Ð¿Ñ–Ð´ÐºÑ€ÐµÑленнÑм, також не повинно бути декількох підкреÑлень підрÑд.
    ПідкреÑÐ»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ замінено на Ð´ÐµÑ„Ñ–Ñ (-) в адреÑÑ– вашого журналу.
    Ім'Ñ Ð½Ðµ повинно бути довшим за 15 Ñимволів. + +/create.bml.username.charsallowed_1=Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача може міÑтити лише латинÑькі літери (a-z), цифри (0-9) та знак підкреÑÐ»ÐµÐ½Ð½Ñ (_). + +/create.bml.username.forpaidaccts=Ðбо, Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків: + +/create.bml.username.head=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/create.bml.username.ljaddress=Ваш журнал буде за цими адреÑами: + +/create.bml.username.maxchars=15 Ñимволів макÑимум + +/create.bml.username.text=Кожний кориÑтувач [[sitename]] муÑить мати Ñвоє унікальне ім'Ñ. Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ñ” тим, що відображаєтьÑÑ Ð² адреÑÑ– вашого журналу, та тим, що ви викориÑтовуєте Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ на Ñервер [[sitename]]. Воно також відображаєтьÑÑ, коли ви публікуєте коментарі до журналів інших людей. + +/create.bml.username.text_1=Ви викориÑтовуєте ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, щоб увійти до [[sitename]]. Воно Ñ” чаÑтиною адреÑи вашого журналу (username.[[lc_sitename]]), а також міÑтитьÑÑ Ð±Ñ–Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… запиÑів чи коментарів. + +/create.bml.username.username=ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/customize/advanced.bml.advancedoptions.header=Додаткові параметри + +/customize/advanced.bml.disclaimer=Якщо ви не програміÑÑ‚ чи веб-дизайнер, вам, швидше за вÑе, нічого робити на цій Ñторінці. Ліпше ÑкориÑтайтеÑÑ Ð¾Ñновною Ñторінкою налаштувань, Ñка Ñтворена Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´ÑŒ-ким. + +/customize/advanced.bml.disclaimer.header=Відмова + +/customize/advanced.bml.noauth=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +/customize/advanced.bml.s1.browse=ПереглÑдач Ñтилю + +/customize/advanced.bml.s1.browse.about=ПереглÑдач Ñтилю дозволÑÑ” здійÑнювати переглÑд загальнодоÑтупних Ñтилів, Ñтворених іншими кориÑтувачами. + +/customize/advanced.bml.s1.create=Створити новий Ñтиль + +/customize/advanced.bml.s1.create.about=Створіть Ñвій Ñтиль "з нулÑ" або на оÑнові вже Ñ–Ñнуючого загальнодоÑтупного Ñтилю. + +/customize/advanced.bml.s1.documentation.text=ДоÑвічені кориÑтувачі можуть дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про ÑиÑтему Ñтилів із документації зі Ñтилів. + +/customize/advanced.bml.s1.edit=Змінити або Видалити Ñ–Ñнуючий Ñтиль + +/customize/advanced.bml.s1.edit.about=Ви можете змінювати тільки “влаÑні” Ñтилі. Ð”Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ ÑиÑтемного Ñтилю Вам необхідно Ñпочатку Ñтворити влаÑний Ñтиль, Ñкий буде базуватиÑÑ Ð½Ð° ÑиÑтемному. + +/customize/advanced.bml.s1.embedding=Інтегруйте Ñвій журнал до влаÑного веб-Ñайту + +/customize/advanced.bml.s1.embedding.about=ІÑнує багато різних шлÑхів Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— вашого журналу до влаÑного веб-Ñайту. + +/customize/advanced.bml.s2.doc.desc=у розробці, але міÑтить деÑкі цікаві речі + +/customize/advanced.bml.s2.doc.link=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð· S2 + +/customize/advanced.bml.s2.documentation.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/customize/advanced.bml.s2.documentation.text=Перш ніж ви поринете в Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S2, ви маєте зрозуміти, Ñк це працює. + +/customize/advanced.bml.s2.publiclayers.desc=ÑиÑтемні шари (гарна довідка та міÑце Ð´Ð»Ñ Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ) + +/customize/advanced.bml.s2.publiclayers.link=ЗагальнодоÑтупні шари + +/customize/advanced.bml.s2.yourlayers.desc=ÑтвореннÑ/Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… шарів + +/customize/advanced.bml.s2.yourlayers.link=Ваші шари + +/customize/advanced.bml.s2.yourstyles.desc=ÑтвореннÑ/Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… Ñтилів + +/customize/advanced.bml.s2.yourstyles.link=Ваші Ñтилі + +/customize/advanced.bml.title=ÐžÑ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/customize/advanced.bml.upsell=Ваш тип рахунку не дозволÑÑ” ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñобливих Ñтилів. + +/customize/advanced/index.bml.advancedoptions.header=Додаткові параметри + +/customize/advanced/index.bml.disclaimer.header=Відмова + +/customize/advanced/index.bml.disclaimer.text=Якщо ви не програміÑÑ‚ чи веб-дизайнер, вам, швидше за вÑе, нічого робити на цій Ñторінці. Ліпше ÑкориÑтайтеÑÑ Ð¾Ñновною Ñторінкою налаштувань, Ñка Ñтворена Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´ÑŒ-ким. + +/customize/advanced/index.bml.documentation.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/customize/advanced/index.bml.documentation.text=До того, Ñк ви поринете у Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S2, ви повинні зрозуміти Ñк це працює. + +/customize/advanced/index.bml.publiclayers.desc=ÑиÑтемні шари (гарна довідка та міÑце Ð´Ð»Ñ Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ) + +/customize/advanced/index.bml.publiclayers.link=ЗагальнодоÑтупні шари + +/customize/advanced/index.bml.s2doc.desc=у розробці, але має деÑкі цікаві речі + +/customize/advanced/index.bml.s2doc.link=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ð¾ ÑиÑтемі Ñтилів S2 + +/customize/advanced/index.bml.title=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/advanced/index.bml.yourlayers.desc=Ñтворити/редагувати ваші шари + +/customize/advanced/index.bml.yourlayers.link=Ваші шари + +/customize/advanced/index.bml.yourstyles.desc=Ñтворити/редагувати ваші Ñтилі + +/customize/advanced/index.bml.yourstyles.link=Ваші Ñтилі + +/customize/advanced/layerbrowse.bml.back2=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/advanced/layerbrowse.bml.classes.header=КлаÑи + +/customize/advanced/layerbrowse.bml.classes.sort.alphabetical=За алфавитом + +/customize/advanced/layerbrowse.bml.classes.sort.hierarchical=За ієрахією + +/customize/advanced/layerbrowse.bml.classname.childclass=Дочірній ÐºÐ»Ð°Ñ Ð²Ñ–Ð´ [[name]]. + +/customize/advanced/layerbrowse.bml.classname.header=ÐšÐ»Ð°Ñ [[name]] + +/customize/advanced/layerbrowse.bml.error.cantviewlayer=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цього шару. + +/customize/advanced/layerbrowse.bml.error.layerdoesntexist=Указаний шар не Ñ–Ñнує. + +/customize/advanced/layerbrowse.bml.globalfunctions.header=Глобальні функції + +/customize/advanced/layerbrowse.bml.layerchildren=[[numchildren]] [[?numchildren|дочірній|дочірніх|дочірніх]]... + +/customize/advanced/layerbrowse.bml.layerinfo.header=Дані шару + +/customize/advanced/layerbrowse.bml.members.header=УчаÑники + +/customize/advanced/layerbrowse.bml.members.readonly=(Лише читаннÑ) + +/customize/advanced/layerbrowse.bml.methods.header=СпоÑоби + +/customize/advanced/layerbrowse.bml.nav.editlayer=Змінити шар + +/customize/advanced/layerbrowse.bml.nav.parentlayer=БатьківÑький шар + +/customize/advanced/layerbrowse.bml.nav.publiclayers=ЗагальнодоÑтупні шари + +/customize/advanced/layerbrowse.bml.nav.viewsource=ПереглÑнути код: + +/customize/advanced/layerbrowse.bml.nav.viewsource.highlighted=ПідÑвічений ÑинтакÑÐ¸Ñ + +/customize/advanced/layerbrowse.bml.nav.viewsource.raw=Вихідний код шару + +/customize/advanced/layerbrowse.bml.nav.yourlayers=Ваші шари + +/customize/advanced/layerbrowse.bml.propertiesset.header=ВлаÑтивоÑÑ‚Ñ– + +/customize/advanced/layerbrowse.bml.propformat.empty=(немає) + +/customize/advanced/layerbrowse.bml.propformat.object=[[type]] об'єкт + +/customize/advanced/layerbrowse.bml.title=ЗагальнодоÑтупні шари + +/customize/advanced/layers.bml.back2=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/advanced/layers.bml.back2layers=Ваші шари + +/customize/advanced/layers.bml.btn.delete=Видалити + +/customize/advanced/layers.bml.btn.delete2=Видалити... + +/customize/advanced/layers.bml.btn.edit=Змінити... + +/customize/advanced/layers.bml.btn.layoutspecific.create=Створити + +/customize/advanced/layers.bml.btn.toplevel.create=Створити + +/customize/advanced/layers.bml.createlayer.header=Створити шар + +/customize/advanced/layers.bml.createlayer.layoutspecific=Створити шар на оÑнові вже Ñ–Ñнуючого + +/customize/advanced/layers.bml.createlayer.layoutspecific.label.layout=Схема: + +/customize/advanced/layers.bml.createlayer.layoutspecific.label.type=Тип: + +/customize/advanced/layers.bml.createlayer.layoutspecific.select.language=Мова + +/customize/advanced/layers.bml.createlayer.layoutspecific.select.theme=Тема + +/customize/advanced/layers.bml.createlayer.layoutspecific.select.user=КориÑтувач + +/customize/advanced/layers.bml.createlayer.toplevel=Створити шар верхнього Ñ€Ñ–Ð²Ð½Ñ + +/customize/advanced/layers.bml.createlayer.toplevel.label.coreversion=ВерÑÑ–Ñ Ñдра: + +/customize/advanced/layers.bml.createlayer.toplevel.label.type=Тип: + +/customize/advanced/layers.bml.createlayer.toplevel.select.language=Мова + +/customize/advanced/layers.bml.createlayer.toplevel.select.layout=Схема + +/customize/advanced/layers.bml.delete.layername="[[name]]" + +/customize/advanced/layers.bml.delete.text=Ви дійÑно бажаєте видалити шар [[name]] (тип [[type]])? + +/customize/advanced/layers.bml.delete.title=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÑˆÐ°Ñ€Ñƒ [[name]] + +/customize/advanced/layers.bml.error.badparentid=Ðомер батьківÑького шару відÑутній або підроблений (Ð´Ð»Ñ Ñхем та базових мов, викориÑтовуйте номер базового шару, а Ð´Ð»Ñ Ñ‚ÐµÐ¼ та базових Ñхем викориÑтовуйте номер cхеми). + +/customize/advanced/layers.bml.error.cantbeauthenticated=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +/customize/advanced/layers.bml.error.cantcreatelayer=Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑˆÐ°Ñ€Ñƒ + +/customize/advanced/layers.bml.error.cantsetuplayer=Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° ÑÐºÐ»Ð°Ð´Ð°Ð½Ð½Ñ ÑˆÐ°Ñ€Ñƒ: [[errormsg]] + +/customize/advanced/layers.bml.error.cantuseonsystem=Привілеї не можуть викориÑтовуватиÑÑ Ð´Ð»Ñ ÑиÑтемного рахунку. + +/customize/advanced/layers.bml.error.invalidlayertype=Помилковий тип шару. + +/customize/advanced/layers.bml.error.layerdoesntexist=Зазначений шар не Ñ–Ñнує. + +/customize/advanced/layers.bml.error.maxlayers=Ви доÑÑгли макÑимальної кількоÑÑ‚Ñ– дозволених шарів. + +/customize/advanced/layers.bml.error.nolayertypeselected=Ðе зазначено тип шару. + +/customize/advanced/layers.bml.error.notloggedin=Ви повинні увійти, що дивитиÑÑ Ñвої шари. + +/customize/advanced/layers.bml.error.notyourlayer=Ви не Ñ” влаÑником зазначеного шару. + +/customize/advanced/layers.bml.error.usercantuseadvanced=Тип рахунку обраного кориÑтувача не дозволÑÑ” кориÑтуватиÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼Ð¸ налаштуваннÑми. + +/customize/advanced/layers.bml.error.youcantuseadvanced=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупні виключно влаÑникам платних рахунків. Придбайте платний рахунок, Ñкщо бажаєте кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. + +/customize/advanced/layers.bml.nav.yourstyles=Ваші Ñтилі + +/customize/advanced/layers.bml.title=Ваші шари + +/customize/advanced/layers.bml.yourlayers.childof=Дочірні від шару [[layerid]]: [[name]] + +/customize/advanced/layers.bml.yourlayers.header=Ваші шари + +/customize/advanced/layers.bml.yourlayers.noname=(немає) + +/customize/advanced/layers.bml.yourlayers.none=Ðемає + +/customize/advanced/layers.bml.yourlayers.table.actions=Дії + +/customize/advanced/layers.bml.yourlayers.table.layerid=Ðомер шару + +/customize/advanced/layers.bml.yourlayers.table.name=Ім'Ñ + +/customize/advanced/layers.bml.yourlayers.table.type=Тип + +/customize/advanced/styles.bml.back2=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/advanced/styles.bml.back2styles=Ваші Ñтилі + +/customize/advanced/styles.bml.btn.change=Змінити + +/customize/advanced/styles.bml.btn.create=Створити + +/customize/advanced/styles.bml.btn.delete=Видалити + +/customize/advanced/styles.bml.btn.edit=Змінити + +/customize/advanced/styles.bml.btn.savechanges=Зберегти зміни + +/customize/advanced/styles.bml.btn.use=КориÑтуватиÑÑ + +/customize/advanced/styles.bml.createstyle.header=Створити Ñтиль + +/customize/advanced/styles.bml.createstyle.label.name=Ім'Ñ: + +/customize/advanced/styles.bml.delete.confirm=Ви дійÑно бажаєте видалити Ñтиль â„–[[id]]? + +/customize/advanced/styles.bml.editstyle.title=Змінити Ñтиль + +/customize/advanced/styles.bml.error.cantbeauthenticated=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +/customize/advanced/styles.bml.error.cantcreatestyle=Стиль не Ñтворено: Помилка бази даних + +/customize/advanced/styles.bml.error.invalidlayertype=Помилковий тип шару: [[name]] не Ñ” [[type]] шаром + +/customize/advanced/styles.bml.error.layerhierarchymismatch=Помилка ієрархії шару: [[layername]] не Ñ” дочірнім шаром [[parentname]] типу [[type]] + +/customize/advanced/styles.bml.error.layernotfound=Шар не знайдено: [[layer]] + +/customize/advanced/styles.bml.error.layernotpublic=Шар не Ñ” публічним: [[layer]] + +/customize/advanced/styles.bml.error.maxstyles=Лиміт ваших Ñтилів вичерпано. + +/customize/advanced/styles.bml.error.notloggedin=Ви повинні увійти, щоб передивитиÑÑ Ð²Ð°ÑˆÑ– Ñтилі. + +/customize/advanced/styles.bml.error.notyourstyle=Цей Ñтиль належить не вам. + +/customize/advanced/styles.bml.error.stylenotfound=Стиль не знайдено. + +/customize/advanced/styles.bml.error.usercantuseadvanced=Тип рахунку обраного кориÑтувача не дозволÑÑ” кориÑтуватиÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼Ð¸ налаштуваннÑми. + +/customize/advanced/styles.bml.error.youcantuseadvanced=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупні виключно влаÑникам платних рахунків. Придбайте платний рахунок, Ñкщо бажаєте кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. + +/customize/advanced/styles.bml.layerid=â„–[[id]] + +/customize/advanced/styles.bml.nav.yourlayers=Ваші шари + +/customize/advanced/styles.bml.stylelayers.header=Шари Ñтилю + +/customize/advanced/styles.bml.stylelayers.label.corelanguage=Мова (i18nc): + +/customize/advanced/styles.bml.stylelayers.label.coreversion=ВерÑÑ–Ñ Ñдра: + +/customize/advanced/styles.bml.stylelayers.label.language=Мова (i18n): + +/customize/advanced/styles.bml.stylelayers.label.layerid=Ðомер шару: + +/customize/advanced/styles.bml.stylelayers.label.layout=Схема: + +/customize/advanced/styles.bml.stylelayers.label.theme=Тема: + +/customize/advanced/styles.bml.stylelayers.label.user=КориÑтувач: + +/customize/advanced/styles.bml.stylelayers.select.layout.other=Інше ... + +/customize/advanced/styles.bml.stylelayers.select.layout.user=[[layername]] (â„–[[id]]) + +/customize/advanced/styles.bml.styleoptions.header=Параметри Ñтилю + +/customize/advanced/styles.bml.title=Ваші Ñтилі + +/customize/advanced/styles.bml.yourstyles.header=Ваші Ñтилі + +/customize/advanced/styles.bml.yourstyles.layername=[[name]] (â„–[[id]]) + +/customize/advanced/styles.bml.yourstyles.none=немає + +/customize/index.bml.btn.nextpage=Ðалаштувати обрану тему + +/customize/index.bml.change=Змінити + +/customize/index.bml.choose=Ви бажаєте кориÑтуватиÑÑ Ñтарою ÑиÑтемою Ñтилів чи новою? + +/customize/index.bml.choose.header=Оберіть ÑиÑтему Ñтилів + +/customize/index.bml.choose.s1=Стара ÑиÑтема (S1) + +/customize/index.bml.choose.s2=Ðова ÑиÑтема (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ðе вдаєтьÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ шар кориÑтувача. + +/customize/index.bml.error.disallowed_custom_layer=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку не дозволÑÑ” доÑтуп до цього оÑобливого шару + +/customize/index.bml.error.disallowed_theme_layer=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— теми. + +/customize/index.bml.error.disallowed_theme_layer2=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— теми. Оберіть іншу тему. + +/customize/index.bml.error.fail_create_style=Ðеможливо Ñтворити новий Ñтиль. + +/customize/index.bml.error.not_your_layout=Це не ваша Ñхема. + +/customize/index.bml.error.not_your_layout2=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— Ñхеми. Оберіть іншу Ñхему. + +/customize/index.bml.error.not_your_theme=Ðе ваша тема + +/customize/index.bml.error.no_core_parent=без базового предка? + +/customize/index.bml.previews=(Попередній переглÑд) + +/customize/index.bml.s1.2=Стара ÑиÑтема Ñтилів налаштовуєтьÑÑ Ñ‡ÐµÑ€ÐµÐ· Ñторінку Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ. + +/customize/index.bml.s1.header=ВикориÑтовуєтьÑÑ S1 + +/customize/index.bml.s2.advanced.denied=Тільки влаÑники платних, поÑтійних рахунків та рані кориÑтувачі можуть викориÑтовувати розділ розширених налаштувань. ДізнайтеÑÑ Ð¿Ñ€Ð¾ переваги платних рахунків. + +/customize/index.bml.s2.advanced.denied2=Лише влаÑники платних, поÑтійних рахунків а також ранні кориÑтувачі можуть викориÑтовувати розширені налаштуваннÑ. ДізнатиÑÑŒ про переваги платного рахунку. + +/customize/index.bml.s2.advanced.header=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.advanced.permitted2=Щоб Ñтворювати нові шари та Ñтилі з чернетки, завітайте до центру розширених налаштувань. + +/customize/index.bml.s2.customize=ÐаÑтупні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð°Ñ‚ÑŒ від обраної Ñхеми. + +/customize/index.bml.s2.customize.header=Крок 2: ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñхеми + +/customize/index.bml.s2.customize.language=Ці мови чаÑтково або повніÑÑ‚ÑŽ підтримуютьÑÑ Ñ†Ñ–Ñ”ÑŽ Ñхемою. + +/customize/index.bml.s2.customize.language.custom=(ОÑоблива) + +/customize/index.bml.s2.customize.language.default=(За замовчуваннÑм) + +/customize/index.bml.s2.customize.language.header=Мова + +/customize/index.bml.s2.customize.settings=Якщо ви бажаєте ще більше налаштувати Ñвій журнал, то тут ви можете змінити індивідуальні налаштуваннÑ, щоб він виглÑдав Ñаме так, Ñк ви бажаєте. + +/customize/index.bml.s2.customize.settings.delete=Видалити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.settings.delete.confirm=Чи Ви впевнені, що бажаєте вилучити ці налаштуваннÑ? + +/customize/index.bml.s2.customize.settings.edit=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.settings.header=Змінити індивідуальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/index.bml.s2.customize.settings.new=Ðалаштувати + +/customize/index.bml.s2.customize.themes=Оберіть одну з наÑтупних доÑтупних тем Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñхеми. + +/customize/index.bml.s2.customize.themes.default=(Схема за замовчуваннÑм) + +/customize/index.bml.s2.customize.themes.header=Теми + +/customize/index.bml.s2.customlayers=ВлаÑні Ñтилі: + +/customize/index.bml.s2.disabledlayers=Заборонені Ñтилі: + +/customize/index.bml.s2.layout=Оберіть Ñвою Ñхему. ОÑкільки обрана тема та оÑобливі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð°Ñ‚ÑŒ від вашої Ñхеми, зміна цього параметру ÑкаÑує вÑÑ– попередні зміни, Ñкі ви могли зробити. + +/customize/index.bml.s2.layout.header=Крок 1: Схема + +/customize/index.bml.s2.related.editinfo.about=Ð’Ñтановити назву журналу та різні налаштуваннÑ. + +/customize/index.bml.s2.related.header=Пов'Ñзані Ñторінки + +/customize/index.bml.s2.related.links.about=ДеÑкі Ñтилі можуть включати ваш керований ÑпиÑок поÑилань. + +/customize/index.bml.s2.related.modify.about=Вказати набір зображень наÑтроїв Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу. + +/customize/index.bml.switcher.btn=Вперед + +/customize/index.bml.switcher.label=Перейти до: + +/customize/index.bml.title=Ðалаштувати журнал + +/customize/layer.bml.btn.save=Зберегти + +/customize/layer.bml.error.cantsavelayer=Помилка Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñтилю: [[errormsg]] + +/customize/layer.bml.error.invalidlayer=Шар - це не тип кориÑтувача чи теми. + +/customize/layer.bml.error.nocorelayer=ОÑновний шар Ð´Ð»Ñ Ñхеми не знайдено. + +/customize/layer.bml.error.nolayoutlayer=Шар-Ñхему Ð´Ð»Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ типу шару не знайдено: [[layertype]] + +/customize/layer.bml.error.notloggedin.header=Треба увійти. + +/customize/layer.bml.error.notloggedin.text=Перед тим, Ñк налаштовувати Ñвій журнал, ви Ñпочатку повинні увійти. + +/customize/layer.bml.error.notyourlayer=Шар належить іншому кориÑтувачу. + +/customize/layer.bml.error.stylenotfound=Стиль не знайдено. + +/customize/layer.bml.finished.header=Закінчили? + +/customize/layer.bml.finished.text=Коли зробите, натиÑніть кнопку Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð½Ð¸Ð·Ñƒ. + +/customize/layer.bml.label.default=За замовчуваннÑм: + +/customize/layer.bml.label.override=Змінити: + +/customize/layer.bml.label.overridedefault=Змінити Ñтандартне + +/customize/layer.bml.prop.misc=Різне + +/customize/layer.bml.saved=Збережено. + +/customize/layer.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/customize/layer.bml.type.bool.no=ÐÑ– + +/customize/layer.bml.type.bool.yes=Так + +/customize/layer.bml.type.text.nothing=(нічого) + +/customize/options.bml.switcher.btn=Вперед + +/customize/options.bml.switcher.label=Перейти до: + +/customize/options.bml.title=Ðалаштувати Ñтиль журналу + +/customize/preview.bml.back2=Ðазад + +/customize/preview.bml.nopreview=(попередній переглÑд недоÑтупний) + +/customize/preview.bml.nopreviews=Попередній переглÑд недоÑтупний + +/customize/preview.bml.specialstyles.header=СпонÑоровані Ñтилі + +/customize/preview.bml.title=Попередній переглÑд Ñхем + +/customize/preview.bml.unavailable=Ð¦Ñ Ñхема доÑтупна тільки Ð´Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ… та платних рахунків. + +/customize/preview.bml.unavailable_haveuser=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ макету. + +/customize/preview.bml.unavailable_nouser=Цей макет відÑутній у деÑких типах рахунків. + +/customize/preview.bml.viewmore=ПереглÑнути інші теми + +/customize/preview.bml.viewthemes=ДивитиÑÑ Ñ‚ÐµÐ¼Ð¸ + +/customize/s1/advanced.bml.advancedoptions.header=Розширені параметри + +/customize/s1/advanced.bml.disclaimer=БільшоÑÑ‚Ñ– кориÑтувачів, за винÑтком програміÑтів чи веб-дизайнерів, краще не кориÑтуватиÑÑŒ цією функціональніÑÑ‚ÑŽ, а викориÑтувати оÑновні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду журналу, Ñкі Ñ” більш проÑтими та доÑтупними. + +/customize/s1/advanced.bml.disclaimer.header=ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ + +/customize/s1/advanced.bml.noauth=Ви не можете бути автентифіковані Ñк вказаний кориÑтувач. + +/customize/s1/advanced.bml.s1.browse=ОглÑдач Ñтилів + +/customize/s1/advanced.bml.s1.browse.about=ОглÑдач Ñтилів дає вам можливіÑÑ‚ÑŒ проглÑдати загальнодоÑтупні Ñтилі, Ñтворені іншими кориÑтувачами. + +/customize/s1/advanced.bml.s1.create=Створити новий Ñтиль + +/customize/s1/advanced.bml.s1.create.about=Створити новий Ñтиль з Ð½ÑƒÐ»Ñ Ð°Ð±Ð¾ на базі Ñ–Ñнуючого загальнодоÑтупного Ñтилю. + +/customize/s1/advanced.bml.s1.documentation.text=ДоÑвідчені кориÑтувачі можуть дізнатиÑÑŒ білбше про ÑиÑтему Ñтилів на Ñторінці документації. + +/customize/s1/advanced.bml.s1.edit=Змінити або вилучити Ñ–Ñнуючий Ñтиль + +/customize/s1/advanced.bml.s1.edit.about<< +Ви можете змінювати Ñтилі, Ñкими “володієте”. Щоб налаштувати ÑиÑтемний Ñтиль за влаÑним Ñмаком, Ñпочатку необхідно Ñтворити новий Ñтиль, що базуєтьÑÑ Ð½Ð° цьому ÑиÑтемному Ñтилі. + +. + +/customize/s1/advanced.bml.s1.embedding=Включіть Ñвій журнал у влаÑний Ñайт + +/customize/s1/advanced.bml.s1.embedding.about=ІÑнує кілька різних шлÑхів включити Ñвій журнал у влаÑний вебÑайт. + +/customize/s1/advanced.bml.s2.doc.desc=у Ñтадії розробки, але буде гарно + +/customize/s1/advanced.bml.s2.doc.link=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð· S2 + +/customize/s1/advanced.bml.s2.documentation.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/customize/s1/advanced.bml.s2.documentation.text=Перед тим, Ñк почати налаштовувати чи програмувати S2, необхідно уÑвідомити, Ñк це працює + +/customize/s1/advanced.bml.s2.publiclayers.desc=ÑиÑтемні шари (хороше міÑце, щоб навчатиÑÑŒ) + +/customize/s1/advanced.bml.s2.publiclayers.link=ЗагальнодоÑтупні Ñтилі + +/customize/s1/advanced.bml.s2.yourlayers.desc=Ñтворити/керувати Ñвоїми шарами + +/customize/s1/advanced.bml.s2.yourlayers.link=ВлаÑні шари + +/customize/s1/advanced.bml.s2.yourstyles.desc=Ñтворити/керувати Ñвоїми ÑтилÑми + +/customize/s1/advanced.bml.s2.yourstyles.link=ВлаÑні Ñтилі + +/customize/s1/advanced.bml.title=ВиглÑд журналу + +/customize/s1/advanced.bml.upsell=Ваш тип рахунку не дає можливоÑÑ‚Ñ– Ñтворювати влаÑні Ñтилі. + +/customize/switch_system.bml.tos1.btn.s1=Я хочу перейти до S1 в будь-Ñкому випадку. + +/customize/switch_system.bml.tos1.btn.s2=Я залишуÑÑŒ у S2. + +/customize/switch_system.bml.tos1.intro=СиÑтема Ñтилів S1 більше не підтримуєтьÑÑ. Рекомендуємо залишитиÑÑŒ у ÑиÑтемі S2 Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¹Ð½Ð¾Ð²Ñ–ÑˆÐ¸Ð¼Ð¸ можливоÑÑ‚Ñми та темами. + +/customize/switch_system.bml.tos1.title=Ви впевнені? + +/customize/switch_system.bml.tos2.benefits=Переваги S2 + +/customize/switch_system.bml.tos2.benefits.current=Діюча ÑиÑтема, Ñка поÑтійно оновлюєтьÑÑ + +/customize/switch_system.bml.tos2.benefits.features=Теґи та вибір міÑÑ†Ñ Ð´Ð»Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ + +/customize/switch_system.bml.tos2.benefits.management=ПроÑте ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð°Ð¼Ð¸ + +/customize/switch_system.bml.tos2.benefits.themes=Та Ñ€Ð¾Ð·Ð¼Ð°Ñ—Ñ‚Ñ‚Ñ Ð½Ð¾Ð²Ð¸Ñ… тем + +/customize/switch_system.bml.tos2.benefits.wizard=ПеренеÑти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою проÑтого помічника + +/customize/switch_system.bml.tos2.btn.s1=ÐÑ–, Ñ Ð±Ð°Ð¶Ð°ÑŽ викориÑтовувати S1. + +/customize/switch_system.bml.tos2.btn.s2=Так, Ñ Ñ…Ð¾Ñ‡Ñƒ покращити журнал до ÑиÑтеми S2. + +/customize/switch_system.bml.tos2.intro=Зараз ви кориÑтуєтеÑÑŒ S1, нашою попередньою ÑиÑтемою Ñтилів, Ñка вже заÑтаріла. Рекомендуємо вам перейти до S2, щоб повніÑÑ‚ÑŽ викориÑтовувати переваги нових можливоÑтей, Ñкі не підтримуютьÑÑ Ð² S1. + +/customize/switch_system.bml.tos2.title=Перейти до S2! + +/customize/themes.bml.back2=Ðазад + +/customize/themes.bml.default=Схема за замовчуваннÑм + +/customize/themes.bml.error.notloggedin.header=Ðеобхідно увійти + +/customize/themes.bml.error.notloggedin.text=Перед тим, Ñк налаштовувати ваш журнал, ви Ñпочатку повинні увійти. + +/customize/themes.bml.error.s2required=Треба викориÑтовувати S2 + +/customize/themes.bml.title=Попередні переглÑди тем + +/customize2/index.bml.btn.nextpage=Ðалаштувати виглÑд обраної теми + +/customize2/index.bml.switcher.btn=Далі + +/customize2/index.bml.switcher.label=Перейти до: + +/customize2/index.bml.title=Вибрати Ñтиль журналу + +/customize2/options.bml.switcher.btn=Перейти + +/customize2/options.bml.switcher.label=Перейти до: + +/customize2/options.bml.title=Ðалаштувати виглÑд Ñтилю журналу + +/customize2/switch_system.bml.tos1.btn.s1=ÐÑ–, Ñ Ð±Ð°Ð¶Ð°ÑŽ викориÑтовувати S1 у будь-Ñкому випадку. + +/customize2/switch_system.bml.tos1.btn.s2=Я залишуÑÑŒ у S2. + +/customize2/switch_system.bml.tos1.intro=СиÑтема Ñтилів S1 більше не підтримуєтьÑÑ. Рекомендуємо залишитиÑÑŒ у ÑиÑтемі S2 Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¹Ð½Ð¾Ð²Ñ–ÑˆÐ¸Ð¼Ð¸ можливоÑÑ‚Ñми та темами. + +/customize2/switch_system.bml.tos1.title=Ви впевнені? + +/customize2/switch_system.bml.tos2.benefits=Переваги S2 + +/customize2/switch_system.bml.tos2.benefits.current=Діюча ÑиÑтема, Ñка поÑтійно оновлюєтьÑÑ + +/customize2/switch_system.bml.tos2.benefits.features=Теґи та вибір міÑÑ†Ñ Ð´Ð»Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ + +/customize2/switch_system.bml.tos2.benefits.management=ПроÑте ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð°Ð¼Ð¸ + +/customize2/switch_system.bml.tos2.benefits.themes=Ð Ð¾Ð·Ð¼Ð°Ñ—Ñ‚Ñ‚Ñ Ð½Ð¾Ð²Ð¸Ñ… тем + +/customize2/switch_system.bml.tos2.benefits.wizard=ПеренеÑти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою проÑтого помічника + +/customize2/switch_system.bml.tos2.btn.s1=ÐÑ–, Ñ Ð±Ð°Ð¶Ð°ÑŽ викориÑтовувати S1. Перейти до Ñторінки Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S1. + +/customize2/switch_system.bml.tos2.btn.s2=Так, Ñ Ñ…Ð¾Ñ‡Ñƒ покращити ÑиÑтему до S2. + +/customize2/switch_system.bml.tos2.intro=Ви викориÑтовуєте нашу попередню ÑиÑтему Ñтилів S1, Ñка вже заÑтаріла. Рекомендуємо перейти до ÑиÑтеми S2, щоб викориÑтовувати переваги нових можливоÑтей, Ñкі не підтримуютьÑÑ Ñƒ S1. + +/customize2/switch_system.bml.tos2.title=Перейти до S2! + +/delcomment.bml.changeoptions<< +Примітка. Ðа Ñторінці [[link]] ви можете обрати, чи дозволÑти залишати коментарі вÑім, або тільки зареєÑтрованим кориÑтувачам, або +тільки друзÑм. +. + +/delcomment.bml.confirm.banuser=Заборонити [[user]] коментувати у вашому журналі + +/delcomment.bml.confirm.body=Ви Ñправді хочете видалити цей коментар? + +/delcomment.bml.confirm.delthread=Видалити гілку (вÑÑ– підкоментарі) + +/delcomment.bml.confirm.head=Видалити цей коментар? + +/delcomment.bml.confirm.spam=Помітити цей коментар Ñк Ñпам + +/delcomment.bml.confirm.submit=Видалити коментар + +/delcomment.bml.error.alreadydeleted=Вказаний коментар уÑпішно видалено. + +/delcomment.bml.error.cantdelete=Коментар може видалити тільки його автор або влаÑник журналу. + +/delcomment.bml.error.cantdelete.comm=Коментар може видалити його автор, автор нитки діалогу або влаÑник Ñпільноти.. + +/delcomment.bml.error.invalidtype=Ðевірний тип коментарÑ. Ð¦Ñ Ñторінка ÑтоÑуєтьÑÑ Ð»Ð¸ÑˆÐµ коментарів запиÑів до у журналах. + +/delcomment.bml.error.nocomment=Обраний коментар відÑутній. + +/delcomment.bml.error.suspended=Вам не дозволено видалÑти коментарі в той чаÑ, коли ваш рахунок Ñ” припиненим. + +/delcomment.bml.success.andban=Коментар видалено, кориÑтувачу [[user]] заборонено коментувати в вашому журналі. + +/delcomment.bml.success.head=Видалено + +/delcomment.bml.success.noban=Коментар видалено. + +/delcomment.bml.success.spam=Додатково, адмініÑтратори цього Ñайту були повідомлені, що цей коментар був Ñпамом. ДÑкуємо вам за повідомленнÑ. + +/delcomment.bml.title=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +/developer/index.bml.clients=То ви бажаєте Ñтворити або покращити клієнт до LiveJournal Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— платформи? Чудово! Ðижче наведено деÑкі необхідні інформаційні реÑурÑи, щоб дати вам змогу дізнатиÑÑ, Ñк працює LiveJournal. + +/developer/index.bml.clients.header=ÐапиÑÐ°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñ–Ð² Ð´Ð»Ñ LiveJournal + +/developer/index.bml.clients.links2<< +
    +
    Протокол Сервер<-> Протокол клієнта LiveJournal
    +
    ДізнайтеÑÑ, Ñким чином клієнт Ð´Ð»Ñ [[sitename]] на вашому комп’ютері звертаєтьÑÑ Ð´Ð¾ Ñервера [[sitename]] Ñ– навпаки. + Це найперше, що вам необхідно зрозуміти, перш ніж розроблÑти або вдоÑконалювати клієнта Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— платформи.
    +
    Повна Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ протокол
    +
    Ð’ÑÑ– різноманітні режими та методи протоколу.
    +
    СпиÑок клієнтів
    +
    СпиÑок більшоÑÑ‚Ñ– клієнтів, що викориÑтовуютьÑÑ Ð´Ð»Ñ Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· [[sitename]]. БільшіÑÑ‚ÑŒ цих клієнтів з відкритим кодом Ñ– вÑÑ– вони безкоштовні Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑтуваннÑ. Саме тут ви знайдете приклади Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ клієнту.
    +
    +. + +/developer/index.bml.code.header=Сховище коду LiveJournal + +/developer/index.bml.code2=Щоб побачити внутрішній механізм, завдÑки Ñкому працює [[sitename]], Ñ– щоб зазирнути вÑередину деÑких доÑтупних клієнтів, перейдіть на Ñторінку коду. + +/developer/index.bml.dbschema.header=Схема бази даних + +/developer/index.bml.dbschema2<< +Ð’Ð°Ñ Ñ†Ñ–ÐºÐ°Ð²Ð»ÑÑ‚ÑŒ деталі про Ñхему бази даних? +До Ñерверного коду включено код SQL Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… таблиць та Ñ—Ñ… наповненнÑ. + +. + +/developer/index.bml.embedding.header=Ð†Ð½Ñ‚ÐµÐ³Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ LiveJournal + +/developer/index.bml.embedding2=Бажаєте правильно інтегрувати ваш журнал до Ñвоєї домашньої Ñторінки? ІÑнує кілька шлÑхів зробити це, в залежноÑÑ‚Ñ– від того, Ñкий тип доÑтупу ви маєте Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ Ñервером. Це ÑтоÑуєтьÑÑ Ð²Ð°Ñ Ð»Ð¸ÑˆÐµ в тому разі, Ñкщо вам не хочетьÑÑ, аби [[domainurl]] було приÑутнє в адреÑÑ– вашого журналу. + +/developer/index.bml.exportingcomments=ЕкÑпорт коментарів, зроблених у журналі чи Ñпільноті, можна здійÑнити через інÑтрумент екÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð². Докладну інформацію читайте у нашому довіднику з екÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð². + +/developer/index.bml.exportingcomments.header=ЕкÑпорт коментарів + +/developer/index.bml.notice.header=Примітка + +/developer/index.bml.notice1=ÐаÑтупна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð° тільки Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ñ–Ñтів та доÑвідчених кориÑтувачів. Якщо Ви лише бажаєте кориÑтовуватиÑÑ LiveJournal Ð´Ð»Ñ Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу, то це чудово! Звичайні кориÑтувачі не зобов’Ñзані турбуватиÑÑ Ð¿Ñ€Ð¾ такі речі. + +/developer/index.bml.notice2=Отже, зміÑÑ‚ нижче поділено на два розділи: Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‰Ð¾Ð´Ð¾ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду Ñторінок LiveJournal та Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ напиÑÐ°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñ–Ð² Ð´Ð»Ñ Ñервера LiveJournal. + +/developer/index.bml.styles=Вам не подобаєтьÑÑ Ñк виглÑдають Ñторінки вашого журналу? Ðе лÑкайтеÑÑ... вÑе піддаєтьÑÑ ÐºÐ¾Ñ€ÐµÐ³ÑƒÐ²Ð°Ð½Ð½ÑŽ Ñ– Ñкщо ви прочитаєте документацію, наведену нижче, ви знатимете вÑе, що потрібно, щоб ваші Ñторінки виглÑдали будь-Ñким чином, Ñк ви забажаєте. + +/developer/index.bml.styles.header=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду LiveJournal + +/developer/index.bml.styles.s1.header=СиÑтема Ñтилів 1 + +/developer/index.bml.styles.s1.system=СиÑтема Ñтилів + +/developer/index.bml.styles.s1.system.about=Загальний оглÑд того, Ñк налаштовано першу ÑиÑтему Ñтилів. + +/developer/index.bml.styles.s1.varlist=СпиÑок змінних + +/developer/index.bml.styles.s1.varlist.about=Ðбетковий ÑпиÑок вÑÑ–Ñ… змінних, Ñкі ви можете налаштувати. + +/developer/index.bml.styles.s1.views=ПодивитиÑÑ Ñ‚Ð¸Ð¿Ð¸ + +/developer/index.bml.styles.s1.views.about=СпиÑок різних ÑпоÑобів, за допомогою Ñких ви можете переглÑдати ваш журнал, та деталі по кожному з них. + +/developer/index.bml.styles.s2.header=СиÑтема Ñтилів 2 + +/developer/index.bml.styles.s2.layerbrowse=ОглÑдач шарів S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Повний ÑпиÑок публічних шарів S2, Ñкий охоплює Ñтилі ÑиÑтеми S2. Ðайважливішими тут Ñ” оÑновні шари, Ñкі задають базові змінні, функції та клаÑи, Ñкі роблÑÑ‚ÑŒ S2 потужною мовою дизайну, Ñкою вона Ñ– Ñ”. + +/developer/index.bml.styles.s2.manual=Підручник з S2 + +/developer/index.bml.styles.s2.manual.about=Ð’Ñебічна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ S2 у LiveJournal. + +/developer/index.bml.title=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² + +/didyouknow/index.bml.available.subtitle=Цап Френк гадає що вам ÑподобаютьÑÑ Ñ†Ñ– можливоÑÑ‚Ñ–: + +/didyouknow/index.bml.available.title=Зараз доÑтупні + +/didyouknow/index.bml.noshow.text=Ðе показувати мені це знову + +/didyouknow/index.bml.notdisplayed.subtitle=Ви можете вже знати про це або воно не ÑтоÑуєтьÑÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ поточного типу рахунку. + +/didyouknow/index.bml.notdisplayed.title=Ðе відображаютьÑÑ + +/didyouknow/index.bml.notips.text=Вибачте, ви знаєте вÑе. Ми не маємо порад Ð´Ð»Ñ Ð²Ð°Ñ. Якщо ви Ñтраждаєте від цього, то можете вÑе відновити: + +/didyouknow/index.bml.notips.title=Приховані поради + +/didyouknow/index.bml.notips.value=Відновити вÑе + +/didyouknow/index.bml.title=Чи знаєте ви? + +/didyouknow/navigationstrip.bml.about=Ðавігаційний Ñ€Ñдок - це маленька панель, що відображаєтьÑÑ Ð½Ð° горі вашого журналу/Ñпільноти, а також під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду інших журналів та Ñпільнот. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ з цієї презентації: + +/didyouknow/navigationstrip.bml.title=ÐŸÑ€ÐµÐ·ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ð¹Ð½Ð¾Ð³Ð¾ Ñ€Ñдку + +/directory.bml.browse.country.desc=Оберіть країну, щоб читати журнали з цієї країни... + +/directory.bml.browse.country.title=ПроглÑдати журнали за країною + +/directory.bml.browse.usa.desc=ÐатиÑніть штат СШРнижче, щоб читати журнали з цього штату, або натиÑніть на ім'Ñ ÐºÑ€Ð°Ñ—Ð½Ð¸ нижче, щоб читати журнали з цієї країни. + +/directory.bml.browse.usa.title=ПроглÑдати журнали за штатом СШР+ +/directory.bml.error.accounttype=Розширений пошук - це функціÑ, Ñка доÑтупна уÑім кориÑтувачам із платними рахунками. Якщо ви хочете дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ до платного, завітайте на Ñторінку платних рахунків. + +/directory.bml.error.accounttype2=Вибачте, але ваш тип рахунку не дозволÑÑ” викориÑÑ‚Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ñƒ або ви ще не увійшли. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу до каталогу, ви маєте придбати платний рахунок. + +/directory.bml.error.notloggedin=Щоб викориÑтовувати каталог, необхідно увійти. + +/directory.bml.navcrap.matches=[[count]] [[?count|збіг|збіги|збігів]]: + +/directory.bml.navcrap.xofy=Сторінка [[curpage]] з [[totpages]] (запиÑи [[reca]]-[[recb]]) + +/directory.bml.open=Відкрита + +/directory.bml.post=ÐапиÑати + +/directory.bml.search.monkey=Сотні тренованих мавп зараз бігають Ñ– шукають результати Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ пошуку. Зачекайте, будь лаÑка. + +/directory.bml.search.new=Ðовий запит + +/directory.bml.search.overflow=Результати пошуку обмежені [[count]] результатами. Уточніть ваш запит, будь лаÑка. + +/directory.bml.search.title=Шукаю + +/directory.bml.update=ОновленнÑ: + +/directory.bml.user=КориÑтувач + +/directorysearch.bml.error.notloggedin=Щоб викориÑтовувати каталог, необхідно увійти. + +/doc/index.bml.about=ЛаÑкаво проÑимо до Ñховища документації LiveJournal. Тут ви зможете знайти більшіÑÑ‚ÑŒ опиÑів поÑлуг або Ñерверного програмного забезпеченнÑ. Оберіть нижче розділ: + +/doc/index.bml.about.header=ЛаÑкаво проÑимо + +/doc/index.bml.docs.faq.about=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ LiveJournal.com + +/doc/index.bml.docs.faq.title=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/doc/index.bml.docs.guides.about=Додаткова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð¾ ÐайчаÑтіших питань + +/doc/index.bml.docs.guides.title=ПоÑібники + +/doc/index.bml.docs.header=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/doc/index.bml.docs.howto.about=Підказки та прийоми, щоб допомогти вам налаштувати Ñвій рахунок + +/doc/index.bml.docs.server.about=Ð’Ñе, що вам потрібно знати, щоб інÑталювати, адмініÑтрувати та хакати уÑтановку LiveJournal + +/doc/index.bml.docs.server.title=ПоÑібник кориÑтувача LiveJournal + +/doc/index.bml.docs.tour.about=Створено Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів, щоб познайомити з Ñайтом. + +/doc/index.bml.docs.tour.title=ОглÑд + +/doc/index.bml.title=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/doc/index.bml.volunteering.about=Якщо ви потребуєте допомоги, а в документації шукати ліньки, відвідайте наші форуми: + +/doc/index.bml.volunteering.header=ВолонтерÑтво + +/doc/index.bml.volunteering.ljsysdoc=ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑиÑтеми документації LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ— Ð´Ð»Ñ ÐºÑ–Ð½Ñ†ÐµÐ²Ð¸Ñ… кориÑтувачів + +/doc/tour/index.bml.clients.caption<< +Програми-клієнти LiveJournal - це невеликі програми, що запуÑкаютьÑÑ Ð½Ð° вашому компю'тері, тим Ñамим дозволÑючи вам пиÑати у ваш журнал не відкриваючи вікна браузера. +Програми-клієнти доÑтупні майже Ð´Ð»Ñ Ð²ÑÑ–Ñ… платформ та проÑÑ‚Ñ– у налаштуванні та викориÑтанні. +. + +/doc/tour/index.bml.clients.title=Клієнти + +/doc/tour/index.bml.comms.caption=LiveJournal Ñ” велетенÑькою інтерактивною Ñпільнотою, тому не дивуйтеÑÑŒ, що Ñ” багато учаÑників зі Ñхожими інтереÑами. Також ми надаємо змогу Ñтворити Ñпільноту або журнал, щоб люди могли допиÑувати туди. + +/doc/tour/index.bml.comms.title=Спільноти + +/doc/tour/index.bml.create.caption=LiveJournal - Ñпільнота журналів, Ñка потребує реєÑтрації. Ðа цій Ñторінці поÑÑнюєтьÑÑ, що учаÑÑ‚ÑŒ у цій Ñпільноті Ñ‚Ñгне за Ñобою, чим воно важливе, Ñкі переваги учаÑÑ‚Ñ–. Також тут міÑтитьÑÑ Ñ„Ð¾Ñ€Ð¼Ð° Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñного рахунку. + +/doc/tour/index.bml.create.title=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/doc/tour/index.bml.friends.caption=Ви можете також відÑтежувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñвоїх друзів у LiveJournal, викориÑтовуючи вбудовану можливіÑÑ‚ÑŒ "друзі". Коли ви знаходите журнал, Ñкий ви вважаєте цікавим, додайте його до Ñвого ÑпиÑку друзів, Ñкий дозволить вам читати запиÑи вÑÑ–Ñ… ваших друзів на одній Ñторінці. + +/doc/tour/index.bml.friends.title=Друзі + +/doc/tour/index.bml.intro.caption=Цей оглÑд Ñтворено Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… відвідувачів, щоб допомогти познайомитиÑÑŒ з Ñайтом. Тут буде вказано де знаходÑÑ‚ÑŒÑÑ Ð½Ð°Ð¹Ð²Ð°Ð¶Ð»Ð¸Ð²Ñ–ÑˆÑ– розділи, та деÑкі цікаві можливоÑÑ‚Ñ–. + +/doc/tour/index.bml.intro.title=ЛаÑкаво проÑимо + +/doc/tour/index.bml.modify.caption=Також можливо формувати ваш журнал багатьма різними ÑпоÑобами, викориÑтовуючи готові Ñтилі, та ÑиÑтеми кольорів. Зробіть ваш журнал таким же унікальним та неповторним, Ñк ви Ñамі! + +/doc/tour/index.bml.modify.title=ПерÑÐ¾Ð½Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ + +/doc/tour/index.bml.nav.next=Далі --> + +/doc/tour/index.bml.nav.prev=<-- Ðазад + +/doc/tour/index.bml.profile.caption=ВітаєтьÑÑ Ð·Ð³Ð¾Ð´Ð° кориÑтувачів LiveJournal залишити трохи інформації про Ñебе в їхніх профайлах, щоб ми мали уÑвленнÑ, хто кориÑтуєтьÑÑ Ñайтом, Ñ– Ñк ми може найкраще допомогти їм. Проте, це не Ñ” обовÑзковою вимогою — єдиною обовÑзковою інформацією, щоб почати кориÑтуватиÑÑ LiveJournal, Ñ” ім'Ñ, e-mail та пароль. + +/doc/tour/index.bml.profile.title=Профіль + +/doc/tour/index.bml.sitemap.caption<< +СподіваємоÑÑŒ, що оглÑд дав вам трохи кориÑної початкової інформації про Ñайт LiveJournal та його поÑлуги. +Якщо потребуєте допомоги пов'Ñзаної з LiveJournal звернітьÑÑ Ð´Ð¾ нашого відділу підтримки. Якщо бажаєте продовжити ознайомленнÑ, звернітьÑÑ Ð´Ð¾ мапи Ñайту щоб побачити вÑÑ– Ñторінки на цьому Ñайті. +. + +/doc/tour/index.bml.sitemap.title=Мапа Ñайту + +/doc/tour/index.bml.support.caption=Сторінка підтримки міÑтить перелік розділів, що допоможуть поÑÑнити що таке LiveJournal, поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ Ñайт та інша кориÑна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ поÑлуги, компанію та Ñпільноту в цілому. + +/doc/tour/index.bml.support.title=ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ + +/doc/tour/index.bml.title=ОглÑд - [[title]] + +/doc/tour/index.bml.update.caption<< +ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ LiveJournal Ñ” оÑновою його обÑлуговуваннÑ; оÑÑŒ де ми даємо кориÑтувачам ÑˆÐ°Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð»Ð¸Ñ‚Ð¸ÑÑ Ñвоїм життÑм Ñ– думками. +Оновлювати журнал неÑкладно. ПроÑто напишіть Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñƒ запропонованій формі Ñ– натиÑніть кнопку "Оновити журнал". Також ви можете викориÑтовувати при оновленні журналу розширені можливоÑÑ‚Ñ–, такі Ñк перевірка правопиÑу, додаткова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð¾ вашого Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (Ñку музику наразі Ñлухаєте чи Ñкий у Ð²Ð°Ñ Ð·Ð°Ñ€Ð°Ð· наÑтрій). +. + +/doc/tour/index.bml.update.title=ÐŸÐ¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/editinfo.bml.advanced.about=Ðе хвилюйтеÑÑ Ð¿Ñ€Ð¾ цю річ, Ñкщо ви не знаєте, що це таке. + +/editinfo.bml.advanced.title=Додаткові параметри + +/editinfo.bml.allowshowcontact.about=Краще тримати цей параметр увімкненим. Це дозволÑÑ” іншим людÑм зв'ÑзатиÑÑ Ð· вами, бо показує ваші email-адреÑу, номер ICQ та ім'Ñ AOL у вашому LiveJournal. + +/editinfo.bml.allowshowcontact.email=Якщо можна бачити, то email-адреÑа відображаєтьÑÑ Ð½Ð°Ñтупним чином: + +/editinfo.bml.allowshowcontact.email.actual_only=Тільки дійÑну адреÑу + +/editinfo.bml.allowshowcontact.email.both=Обидві (дійÑну та [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Тільки адреÑу LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=Ðе показувати жодної email-адреÑи. + +/editinfo.bml.allowshowcontact.email.no_show=Ðе показувати email-адреÑу + +/editinfo.bml.allowshowcontact.email.show=Показувати email-адреÑу + +/editinfo.bml.allowshowcontact.email.withdomainaddr=За допомогою цього параметра ви можете також визначити: приховати Ñвою email-адреÑу (при цьому інша важлива Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ), показувати тільки email-адреÑу LiveJournal (тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків), показувати тільки вашу реальну адреÑу чи обидві одразу. + +/editinfo.bml.allowshowcontact.email.withdomainaddr2=Цей параметр дозволÑÑ” вам приховати Ñвою email-адреÑу (але показувати іншу контактну інформацію), показувати тільки вашу email-адреÑу [[sitename]] (тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків), показувати тільки дійÑну адреÑу або показувати обидві. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=КориÑтуючиÑÑŒ параметром, наведеним вище, ви також можете обрати чи приховувати вашу email-адреÑу (в той же Ñ‡Ð°Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑŽÑ‡Ð¸ інші контактні дані). + +/editinfo.bml.allowshowcontact.title=Показувати ваші контактні дані у вашому LiveJournal? + +/editinfo.bml.allowshowinfo.about=Увімкніть це, Ñкщо ви бажаєте, щоб ваші міÑто/штат/країну та день Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð³Ð»Ð¸ бачити інші кориÑтувачі. + +/editinfo.bml.allowshowinfo.title=Показувати міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° день народженнÑ? + +/editinfo.bml.autotranslate.about<< +ВикориÑтовуйте цей параметр, щоб вказати LiveJournal, Ñке ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸Ñтовувати Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… запиÑів Ñ– коментарів, що були напиÑані до переходу Ñайту на Unicode. +Якщо ви пишете англійÑькою, оберіть тут "Western European". +. + +/editinfo.bml.autotranslate.header=Ðвто-ÐºÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ñ–Ñ Ñтарих запиÑів з: + +/editinfo.bml.bday.title=День Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/editinfo.bml.bday.year.opt=вказувати рік не обов'Ñзково + +/editinfo.bml.bdayreminders.about=Якщо ви бажаєте отримувати на email Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñвоїх друзів по LiveJournal, то поÑтавте тут позначку. Цю можливіÑÑ‚ÑŒ зараз вимкнено, але може бути увімкнено у майбутньому. + +/editinfo.bml.bdayreminders.header=ПоÑилати мені Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ (тимчаÑово відключено) + +/editinfo.bml.bio.about=Тут ви можете напиÑати маленьку Ñ–Ñторію про Ñебе. Вона з’ÑвитьÑÑ Ñƒ вашому профілі. + +/editinfo.bml.bio.header=Про Ð²Ð°Ñ + +/editinfo.bml.blockrobots.about=Якщо ви увімкнете цей параметр, то пошуковим ÑиÑтемам буде дано наÑтанову не включати запиÑи вашого журналу до їхніх результатів пошуку. Ðе вÑÑ– пошукові ÑиÑтеми розпізнають таке проханнÑ; Ñкщо ви не бажаєте, щоб Ð·Ð°Ð¿Ð¸Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу показувавÑÑ Ð² результатах пошуку, то переконайтеÑÑ, що його опубліковано Ñк приватний Ð·Ð°Ð¿Ð¸Ñ Ð°Ð±Ð¾ Ð·Ð°Ð¿Ð¸Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð².. + +/editinfo.bml.blockrobots.header=Зробити Ñкомога меншим Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу до результатів пошукових ÑиÑтем. + +/editinfo.bml.chat.gizmo.title=Проект "Gizmo" + +/editinfo.bml.chat.icquin.title=Ðомер ICQ + +/editinfo.bml.chat.msnusername.title=MSN ім'Ñ + +/editinfo.bml.chat.yahooid.title=Yahoo! ID + +/editinfo.bml.city.title=МіÑто + +/editinfo.bml.country.choose=Оберіть країну + +/editinfo.bml.country.title=Країна + +/editinfo.bml.donotlog=ÐÑ– + +/editinfo.bml.email.address=[[email]] (змінити) + +/editinfo.bml.email.title=Email + +/editinfo.bml.enableboards.about=ПоÑтавте тут позначку, щоб дозволити людÑм коментувати запиÑи вашого журналу. + +/editinfo.bml.enableboards.header=Дозволити коментарі у моєму журналі + +/editinfo.bml.encoding.about=Якщо ви пишете англійÑькою, залиште наÑтупні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ· змін. Ð’ іншому випадку вÑтановіть відповідні параметри. + +/editinfo.bml.encoding.header=Параметри кодувань + +/editinfo.bml.error.day.notinmonth=Ðевірний день Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ міÑÑцÑ. + +/editinfo.bml.error.day.outofrange=Ðевірний день народженнÑ. Введіть день від 1 до 31. + +/editinfo.bml.error.email.lj_domain<< +Ðе можна вводити адреÑу @[[domain]]. +Введіть вашу реальну адреÑу у цьому полі. +Якщо ви платний кориÑтувач, уÑÑ– лиÑти на адреÑу [[user]]@[[domain]] переÑилатимутьÑÑ Ð½Ð° вашу реальну адреÑу. +Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб вибрати, Ñку email-адреÑу (адреÑи) показувати публічно, дивітьÑÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€ "Показувати ваші контактні дані". +. + +/editinfo.bml.error.email.none=Ви муÑите вказати вашу email-адреÑу. + +/editinfo.bml.error.email.no_space<< +Ð’ email-адреÑÑ– пропуÑки заборонені. +Якщо ви Ñ” кориÑтувачем AOL, пам'Ñтайте, що вашою e-mail адеÑою Ñ” ваше ім'Ñ AOL без пропуÑків, за Ñким Ñлідує @aol.com +. + +/editinfo.bml.error.excessive_int=Вибачте, але ви вказали занадто багато зацікавлень. Межею Ñ” 150, а ви вказали [[intcount]]. Зміни, Ñкі ви зробили, не збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ та Ñкоротіть ваш ÑпиÑок, а потім збережіть знову. + +/editinfo.bml.error.invalidbio2=Ваша Ñ–ÑÑ‚Ð¾Ñ€Ñ–Ñ Ð¿Ñ€Ð¾ Ñебе міÑтить помилкові Ñимволи. Ви повинні перейти до Ñторінки перекодуваннÑ, щоб змінити Ñ—Ñ… до Unicode. + +/editinfo.bml.error.invalidname2=Ваше ім'Ñ Ð¼Ñ–Ñтить помилкові Ñимволи. Ви повинні перейти до Ñторінки перекодуваннÑ, щоб змінити Ñ—Ñ… до Unicode. + +/editinfo.bml.error.locale.country_ne_state=Ви вказали Сполучені Штати Ñк країну Ñвого перебуваннÑ, але вказали в розділі "інший штат" штат Ñкого в СШРнема. + +/editinfo.bml.error.locale.invalid_country=ЯкимоÑÑŒ чином ви обрали невірну країну. + +/editinfo.bml.error.locale.state_ne_country=Ви обрали країну не-СШÐ, але вибрали штат що належить Сполученим Штатам. + +/editinfo.bml.error.locale.zip_ne_state=Поштовий Ñ–Ð½Ð´ÐµÐºÑ Ñ‚Ð° регіон вказані вами не відповідають одне одному. Введіть вірну інформацію, або витріть індекÑÑ‚ або\Ñ– регіон. + +/editinfo.bml.error.locale.zip_requires_us=Ви вказали поштовий індекÑ, але не вказали СШРÑк вашу країну. Ð’ Ð½Ð°Ñ Ð·Ñ–Ð±Ñ€Ð°Ð½Ñ– тільки індекÑи регіонів СШÐ. ПовернітьÑÑ Ñ‚Ð° видаліть поштовий Ñ–Ð½Ð´ÐµÐºÑ Ð°Ð±Ð¾ вкажіть СШРÑк вашу країну. + +/editinfo.bml.error.month.outofrange=Ðевірний міÑÑць народженнÑ. Введіть міÑÑць від 1 до 12 (Ñічень-грудень). + +/editinfo.bml.error.noname=Ваше ім'Ñ Ñ” обов'Ñзковою інформацією. Вкажіть ваше ім'Ñ, або прізвиÑько, або пÑевдонім. + +/editinfo.bml.error.tm.require.number=Якщо ви збираєтеÑÑ ÐºÐ¾Ñ€Ð¸ÑтуватиÑÑ Ñ‚ÐµÐºÑтовими повідомленнÑми, ви маєте вказати Ñвій номер телефону. + +/editinfo.bml.error.tm.require_provider<< +Якщо ви бажаєте кориÑтуватиÑÑ Ñ‚ÐµÐºÑтовими повідомленнÑми, то вам треба вказати Ñвого оператора. + +Якщо вашого оператора нема в ÑпиÑку, то зв'ÑжітьÑÑ Ð· нами Ñ– повідомте, Ñким чином працює поÑлуга текÑтових повідомлень вашого оператора, щоб ми могли додати його до ÑпиÑку підтримуємих операторів. +. + +/editinfo.bml.error.year.notenoughdigits=Ðевірний рік народженнÑ. Вкажіть 4-Ñ… значний рік + +/editinfo.bml.error.year.outofrange=Ðевірний рік народженнÑ. + +/editinfo.bml.finished.about=Коли закінчите, натиÑніть кнопку "Зберегти зміни", наведену нижче: + +/editinfo.bml.finished.header=Готово? + +/editinfo.bml.finished.save_button=Зберегти зміни + +/editinfo.bml.foafurl.about=Якщо ви не бажаєте кориÑтуватиÑÑ Ñторінкою FOAF за замовчуваннÑм, Ñку ми надаємо, то будь-Ñка адреÑа, що ви введете вище, буде викориÑтана заміÑÑ‚ÑŒ неї Ñк Ваш FOAF реÑурÑ. Ми перенаправимо FOAF запити до зазначеної адреÑи. + +/editinfo.bml.foafurl.title=Ð—Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ Ð°Ð´Ñ€ÐµÑа FOAF: + +/editinfo.bml.gender.female=Жіноча + +/editinfo.bml.gender.male=Чоловіча + +/editinfo.bml.gender.title=Стать + +/editinfo.bml.gender.unspecified=(Ðевідома) + +/editinfo.bml.getreplies.about=ПоÑтавте тут позначку, щоб отримувати на email Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‰Ð¾Ñ€Ð°Ð·Ñƒ, Ñк хтоÑÑŒ коментує один з ваших запиÑів. + +/editinfo.bml.getreplies.header=Отримувати на email Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ коментарі + +/editinfo.bml.getselfemails.about=ПоÑтавте тут позначку, Ñкщо ви бажаєте отримувати лиÑÑ‚ з копією коментарю, зробленого від Ñвого імені. Ви не отримуватимете жодних копій анонімних коментарів, зроблених вами. Щоб одержувати на поштову Ñкриньку відповіді від інших людей, поÑтавте позначку Ð±Ñ–Ð»Ñ "Отримувати на email Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ коментарі". + +/editinfo.bml.getselfemails.header=Отримувати копії моїх влаÑних коментарів на email + +/editinfo.bml.hidefriendof.about=Якщо ви поÑтавите тут позначку, то ÑпиÑок людей, Ñкі додали Ð²Ð°Ñ Ð´Ð¾ ÑпиÑку друзів, буде прихований на вашій Ñторінці оÑобиÑтих даних. + +/editinfo.bml.hidefriendof.header=Сховати ÑпиÑок "У друзÑÑ…" + +/editinfo.bml.howhear.about<< +Лише заради цікавоÑÑ‚Ñ–, звідки ви довідалиÑÑŒ про [[sitename]]? +Якщо це була певна оÑоба, вкажіть Ñ—Ñ— ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача; Ñкщо це було інше джерело/ÑтаттÑ/поÑиланнÑ/веб-Ñайт, то введіть відповідні дані. +. + +/editinfo.bml.howhear.header=ЦікавіÑÑ‚ÑŒ + +/editinfo.bml.htmlemail.about<< +ПоÑтавте тут позначку, Ñкщо ваша поштова програма повніÑÑ‚ÑŽ підтримує HTML у email. +ДеÑкі програми намагаютьÑÑ Ð¹Ð¾Ð³Ð¾ підтримувати, але не впораютьÑÑ Ð· тим, щоб відображати його Ñк Ñлід. +Якщо ви знімете позначку, LiveJournal буде надÑилати лише текÑтові лиÑти. +. + +/editinfo.bml.htmlemail.header=ÐадÑилати лиÑти у форматі HTML + +/editinfo.bml.imagelinks.about=Замінники кориÑні, Ñкщо ви проглÑдаєте LiveJournal на роботі або через повільне з'єднаннÑ, вони замінюють внутрішні Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÑиланнÑми. Ð”Ð»Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ Ñкого розміру ви бажаєте кориÑтувати замінники? + +/editinfo.bml.imagelinks.header=ВикориÑтовувати замінники зображень у вашій Ñтрічці друзів + +/editinfo.bml.imagelinks.size.all=ВикориÑтовувати замінники Ð´Ð»Ñ Ð²ÑÑ–Ñ… зображень + +/editinfo.bml.imagelinks.size.custom=ОÑобливе: викориÑтовувати замінники Ð´Ð»Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ більше [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=ВикориÑтовувати замінники Ð´Ð»Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ… зображень (більше [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=ВикориÑтовувати замінники Ð´Ð»Ñ Ñередніх зображень (більше [[width]]x[[height]]) + +/editinfo.bml.int.about<< +Якщо ви бажаєте, щоб інші люди могли знайти Ð²Ð°Ñ Ñƒ каталозі за зацікавленнÑм, перелічіть Ñвої ÑƒÐ¿Ð¾Ð´Ð¾Ð±Ð°Ð½Ð½Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, відокремлюючи Ñ—Ñ… комами. +Ðайкраще викориÑтовувати окремі Ñлова, короткі виÑлови. Загальне правило: Ваше Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð°Ñ” легко доповнювати Ñ€ÐµÑ‡ÐµÐ½Ð½Ñ "Мені подобаєтьÑÑ ________". Ð—Ð°Ð´Ð»Ñ ÐºÑ€Ð°Ñ‰Ð¾Ð³Ð¾ узгодженнÑ, іменники подавайте у формі множини: "фільми" заміÑÑ‚ÑŒ "фільм". +. + +/editinfo.bml.int.ex.bad=ПОГÐÐИЙ приклад: Мені подобаєтьÑÑ Ð±Ð°Ð³Ð°Ñ‚Ð¾ гуртів та дивитиÑÑ ÐºÑ–Ð½Ð¾ та базікати з друзÑми та ходити по клубах. Такі речі відноÑÑÑ‚ÑŒÑÑ Ð´Ð¾ розділу "Про Ñебе", розташованого вище. + +/editinfo.bml.int.ex.good=ГÐРÐИЙ приклад: їздити на велоÑипеді, кататиÑÑ Ð½Ð° лижах, комп'ютери, фільми, музика, Ñир, дівчата + +/editinfo.bml.int.header=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/editinfo.bml.logip.always=Завжди + +/editinfo.bml.logip.anon_only=Тільки анонімних кориÑтувачів + +/editinfo.bml.logip.header=ЗапиÑувати IP-адреÑи кориÑтувачів, що відповідають? + +/editinfo.bml.mangleaddress.about=Якщо ви боїтеÑÑ, що Ñпам-роботи знайдуть вашу email-адреÑу на Ñторінках LiveJournal, то оберіть цей параметр. Ваша email-адреÑа буде змінена таким чином, щоб зменшити шанÑи того, що Ñ—Ñ— знайдуть. + +/editinfo.bml.mangleaddress.header=Спотворити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ñ— email-адреÑи + +/editinfo.bml.mutualfriends.about=Цей параметр додає новий ÑпиÑок до вашої Ñторінки оÑобиÑтих даних: ÑпиÑок взаємних друзів. Люди, Ñких ви додали Ñк друзів Ñ– Ñкі додали Ð²Ð°Ñ Ñк друга, будуть поміщені до цього ÑпиÑку. + +/editinfo.bml.mutualfriends.header=Відображати взаємних друзів на Ñторінці оÑобиÑтих даних + +/editinfo.bml.name.title=Ім'Ñ + +/editinfo.bml.navstrip.about=Ðавігаційна Ñтрічка - це маленька панель, що відображаєтьÑÑ Ð·Ð²ÐµÑ€Ñ…Ñƒ вашого журналу/Ñпільноти, а також коли ви переглÑдаєте інші журнали та Ñпільноти. Вона міÑтить: + +/editinfo.bml.navstrip.about.provides.links=Швидкі поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ вашого журналу, напиÑÐ°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів та вашої Ñтрічки друзів + +/editinfo.bml.navstrip.about.provides.management=Параметри ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотою та інше + +/editinfo.bml.navstrip.about.provides.options=Параметри, що залежать від Ñторінки, Ñку ви переглÑдаєте, наприклад, фільтри Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñтрічки друзів + +/editinfo.bml.navstrip.choose=Оберіть бажаний колір навігаційної Ñтрічки: + +/editinfo.bml.navstrip.choose.dark=Темно-Ñірий + +/editinfo.bml.navstrip.choose.light=Світло-Ñірий + +/editinfo.bml.navstrip.header=Параметри навігаційної Ñтрічки + +/editinfo.bml.navstrip.options=Параметри Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ð¹Ð½Ð¾Ñ— Ñтрічки + +/editinfo.bml.navstrip.options.myjournal=Завжди відображати навігаційну Ñтрічку вÑім, хто дивитьÑÑ Ð²Ð°Ñˆ журнал чи Ñпільноту + +/editinfo.bml.navstrip.options.viewjournals=Показувати мені навігаційну Ñтрічку, коли Ñ Ð´Ð¸Ð²Ð»ÑŽÑÑ Ð±ÑƒÐ´ÑŒ-Ñкий журнал чи Ñпільноту + +/editinfo.bml.newemail.body2<< +Ви тільки-но змінили email Ñвого рахунку [[sitename]] "[[username]]". Щоб підтвердити зміну, будь лаÑка, перейдіть за цією адреÑою: + +[[conflink]] + +З найкращими побажаннÑми, +Команда [[sitename]] +[[sitelink]] +. + +/editinfo.bml.newemail.subject=Email-адреÑу змінено. + +/editinfo.bml.numcomments.about=ПоÑтавте тут позначку, Ñкщо ви бажаєте додавати кількіÑÑ‚ÑŒ коментарів до Ð°Ð´Ñ€ÐµÑ Ñторінок, щоб ваш браузер, можливо, відображав поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ð¼ кольором. + +/editinfo.bml.numcomments.header=Додати &nc=xx до адреÑи коментарів + +/editinfo.bml.optional=Ðеобов'Ñзково + +/editinfo.bml.opt_in.about<< +Якщо ви бажаєте дізнаватиÑÑŒ про Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… клаÑних можливоÑтей до LiveJournal, поÑтавте тут позначку. +Ваша email-адреÑа не буде видима Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… кориÑтувачів Ñ– ви зможете будь-коли вимкнути цю опцію. +. + +/editinfo.bml.opt_in.header=ÐадÑилати мені новини LiveJournal + +/editinfo.bml.persinfo.disclaimer2=Заповніть інформацію про Ñебе Ð´Ð»Ñ Ð·Ð°Ð´Ð¾Ð²Ð¾Ð»ÐµÐ½Ð½Ñ Ð½Ð°ÑˆÐ¾Ñ— цікавоÑÑ‚Ñ– та ÑтатиÑтичних цілей. Ми не зробимо нічого жахливого з цією інформацією, нам проÑто цікаво знати, хто Ñ” нашими кориÑтувачами. Будь лаÑка, заповніть чеÑно. Якщо ви маєте Ñумніви, ознайомтеÑÑ Ð· нашою політикою конфіденційноÑÑ‚Ñ– . + +/editinfo.bml.persinfo.header=ОÑобиÑÑ‚Ñ– дані + +/editinfo.bml.schools.des=Цей параметр дозволÑÑ” вам обмежити або приховати дані про навчальні заклади, Ñкі відображаютьÑÑ Ñƒ вашому профілі. Люди завжди зможуть побачити навчальні заклади, Ñкі ви відвідували, Ñкщо перейдуть до них через каталог навчальних закладів. + +/editinfo.bml.schools.title2=Показувати інформацію про ваші навчальні заклади у вашому профілі? + +/editinfo.bml.schools.who=Хто може бачити ці дані? + +/editinfo.bml.screen.all=УÑÑ– + +/editinfo.bml.screen.anon=Ðнонімні + +/editinfo.bml.screen.header=Які коментарі приховувати за замовчуваннÑм? + +/editinfo.bml.screen.none=Жодні + +/editinfo.bml.screen.nonfriends=ÐапиÑані не друзÑми + +/editinfo.bml.screen.nonmembers=ÐапиÑані не учаÑниками + +/editinfo.bml.security.header=Хто може бачити ваші контактні дані? + +/editinfo.bml.security.visibility.anybody=УÑÑ– + +/editinfo.bml.security.visibility.everybody=УÑÑ– + +/editinfo.bml.security.visibility.friends=Тільки друзі + +/editinfo.bml.security.visibility.regusers=ЗареєÑтровані кориÑтувачі + +/editinfo.bml.settings.friendspage.title=Заголовок Ñтрічки друзів: + +/editinfo.bml.settings.friendspage.title.optional=Ðеобов'Ñзково, вкажіть заголовок Ñторінки друзів (без HTML). + +/editinfo.bml.settings.header=Параметри LiveJournal + +/editinfo.bml.settings.journal.subtitle=Підзаголовок журналу: + +/editinfo.bml.settings.journal.subtitle.optional=Ðеобов'Ñзково, вкажіть заголовок та підзаголовок Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу (без HTML) + +/editinfo.bml.settings.journal.title=Заголовок журналу: + +/editinfo.bml.settings.privacy.about=Оберіть нижче Ñвої Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° параметри приватноÑÑ‚Ñ–. + +/editinfo.bml.settings.privacy.header=Параметри приватноÑÑ‚Ñ– + +/editinfo.bml.state.other=Ðбо надрукуйте інший штат/провінцію/облаÑÑ‚ÑŒ + +/editinfo.bml.state.title=Штат + +/editinfo.bml.state.us=Штати СШР+ +/editinfo.bml.stylemine.about=ПоÑтавте тут позначку, щоб дивитиÑÑ Ñторінки коментарів у Ñтилі вашого журналу при переході за поÑиланнÑми зі Ñвоєї Ñтрічки друзів. + +/editinfo.bml.stylemine.header=Показувати Ñторінки коментарів у Ñтилі вашого журналу? + +/editinfo.bml.success.header=УÑпішно! + +/editinfo.bml.success.message2=Ваші дані, Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ та профіль збережені. + +/editinfo.bml.switch.button=Змінити + +/editinfo.bml.switch.header=Змінити журнал + +/editinfo.bml.switch.workwith=З Ñким журналом працювати + +/editinfo.bml.timezone.select=(Оберіть Ñвій чаÑовий поÑÑ) + +/editinfo.bml.timezone.title=ЧаÑовий поÑÑ + +/editinfo.bml.title=Змінити оÑобиÑÑ‚Ñ– дані + +/editinfo.bml.tm.details2=(докладніше) + +/editinfo.bml.tm.phonenum=Повний номер телефону: + +/editinfo.bml.tm.sec.about=Дозволити текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ інших кориÑтувачів. + +/editinfo.bml.tm.sec.title=Рівень безпеки: + +/editinfo.bml.tm.servprov=СервіÑ-провайдер + +/editinfo.bml.tm.title=ТекÑтові повідомленні + +/editinfo.bml.translatemailto.about=Якщо ви обрали отримувати коментарі на email, але ваша поштова програма не дуже добре підтримує Unicode (UTF-8), то викориÑтовуйте цей параметр, щоб визначити інше кодуваннÑ, до Ñкого LiveJournal автоматично перекодовуватиме текÑÑ‚ коментарів, Ñкі надÑилатимутьÑÑ Ð²Ð°Ð¼. + +/editinfo.bml.translatemailto.header=Змінювати ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ email-повідомлень до: + +/editinfo.bml.unbanusers.about=ÐаÑтупним кориÑтувачам заборонено коментувати у вашому журналі. ПоÑтавте позначку проти імен кориÑтувачів, щоб знÑти з них заборону. + +/editinfo.bml.unbanusers.header=Розблокувати кориÑтувачів + +/editinfo.bml.userpic.about=Ðижче наведено маленьку картинку, Ñку ви завантажили, щоб вона предÑтавлÑла Ð²Ð°Ñ Ð½Ð° Ñайті LiveJournal, у вашому журналі та в журналах ваших друзів: + +/editinfo.bml.userpic.edit=Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ або Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¹Ð´Ñ–Ñ‚ÑŒ Ñюди. + +/editinfo.bml.userpic.edit2=Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— або Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ— юзерпики перейдіть Ñюди. + +/editinfo.bml.userpic.header=Ваша картинка + +/editinfo.bml.userpic.none=жодних картинок не завантажено + +/editinfo.bml.weblogscom.about=Оберіть цю опцію, Ñкщо бажаєте, щоб ваші запиÑи додавалиÑÑŒ Ñ– до Weblogs.com. + +/editinfo.bml.weblogscom.header=ПовідомлÑти Weblogs.com про Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/editinfo.bml.webpagename.title=Ðазва Ñайту + +/editinfo.bml.webpageurl.title=ÐдреÑа Ñайту + +/editinfo.bml.whoreply.header=Хто може відповідати на ваші запиÑи? + +/editinfo.bml.zip.title=Поштовий Ñ–Ð½Ð´ÐµÐºÑ + +/editinfo.bml.zip.usonly=5-ти значний поштовий індекÑ; тільки Ð´Ð»Ñ Ð¼ÐµÑˆÐºÐ°Ð½Ñ†Ñ–Ð² СШР+ +/editjournal.bml.auth.poster=Відправник: + +/editjournal.bml.btn.proceed=Продовжити... + +/editjournal.bml.certainday=За певний день: + +/editjournal.bml.desc=Будь лаÑка, кориÑтуйтеÑÑ Ñ„Ð¾Ñ€Ð¼Ð¾ÑŽ, наведеною нижче, щоб знайти запиÑ, Ñкий ви бажаєте змінити. + +/editjournal.bml.in=У Ñпільноті: + +/editjournal.bml.recententries=найÑвіжіших запиÑів + +/editjournal.bml.recententry=ОÑтанній Ð·Ð°Ð¿Ð¸Ñ + +/editjournal.bml.success.delete=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ видалено з журналу. + +/editjournal.bml.success.deletespam=Додатково, Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² помічений Ñк Ñпам. ДÑкуємо за повідомленнÑ. + +/editjournal.bml.success.head=УÑпішно + +/editjournal.bml.title=Змінити журнальний Ð·Ð°Ð¿Ð¸Ñ + +/editjournal.bml.viewwhat=Показати запиÑи: + +/editjournal_do.bml.body=Змініть Ð¿Ð¾Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ запиÑу та натиÑніть кнопку "Зберегти" унизу Ñторінки. Ðбо натиÑніть кнопку видаленнÑ, щоб видалити цей Ð·Ð°Ð¿Ð¸Ñ Ð· вашого журналу. + +/editjournal_do.bml.btn.delete=Видалити Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.btn.deletespam=Видалити Ñ– позначити Ñк Ñпам + +/editjournal_do.bml.btn.edit=Змінити обраний Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.btn.preview=Попередньо переглÑнути Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.btn.save=Зберегти Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.continue.head=ÐатиÑніть Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ... + +/editjournal_do.bml.continue.text=Коли оберете запиÑ, Ñкий ви хочете змінити чи видалити, натиÑніть кнопку "Змінити" унизу. + +/editjournal_do.bml.currmood=ÐаÑтрій: + +/editjournal_do.bml.currmusic=Зараз грає: + +/editjournal_do.bml.date=Дата: + +/editjournal_do.bml.default=за замовчуваннÑм + +/editjournal_do.bml.delete.confirm=Ви впенені, що хочете видалити цей запиÑ? + +/editjournal_do.bml.deletespam.confirm=Чи Ви впевнені, що бажаєте видалити цей Ð·Ð°Ð¿Ð¸Ñ Ñ– помітити його Ñк Ñпам? + +/editjournal_do.bml.edit.text=Це запиÑ, Ñкий ви вибрали Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸. ВнеÑÑ–Ñ‚ÑŒ зміни та натиÑніть кнопку "Зберегти запиÑ" нижче.

    Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу, видаліть веÑÑŒ текÑÑ‚ та натиÑніть кнопку "Зберегти запиÑ" нижче. + +/editjournal_do.bml.error.getting=Помилка при виборі запиÑів Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸: + +/editjournal_do.bml.error.modify=Помилка при редагуванні журналу: + +/editjournal_do.bml.error.nofind=Ðеможливо знайти вказаний запиÑ. + +/editjournal_do.bml.event=ТекÑÑ‚ запиÑу: + +/editjournal_do.bml.localtime=МіÑцевий чаÑ: + +/editjournal_do.bml.noneother=Інший + +/editjournal_do.bml.opt.backdate=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом: + +/editjournal_do.bml.opt.backdate.about=не з'ÑвитьÑÑ Ð½Ð° Ñторінці друзів + +/editjournal_do.bml.opt.nocomments=Заборонити коментувати + +/editjournal_do.bml.opt.noemail=Ðе надÑилати коментарі до e-mail: + +/editjournal_do.bml.opt.noformat=Ðе автоформатувати: + +/editjournal_do.bml.opt.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´ збереженнÑм (тільки англійÑькою) + +/editjournal_do.bml.other=Інше: + +/editjournal_do.bml.pickentry.head=Оберіть Ð·Ð°Ð¿Ð¸Ñ Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ + +/editjournal_do.bml.pickentry.text=Оберіть елемент Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ та натиÑніть кнопку "Змінити" унизу Ñторінки. + +/editjournal_do.bml.preview.header=Попередньо переглÑнути Ð·Ð°Ð¿Ð¸Ñ + +/editjournal_do.bml.preview.text=Так виглÑдатиме запиÑ, коли його буде опубліковано. ВикориÑтовуючи форму, наведену нижче, ви можете змінити Ð·Ð°Ð¿Ð¸Ñ Ð´Ð°Ð»Ñ– або ви можете надіÑлати його таким, Ñк Ñ”. + +/editjournal_do.bml.save.head=ÐитиÑніть Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ... + +/editjournal_do.bml.save.text=ПіÑÐ»Ñ Ð·Ð¼Ñ–Ð½Ð¸ запиÑу, натиÑніть "Зберегти". + +/editjournal_do.bml.spellchecked=Ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ правопиÑу: + +/editjournal_do.bml.subject=Тема: (необов'Ñзково) + +/editjournal_do.bml.success.delete=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ видалено. + +/editjournal_do.bml.success.deletespam=Додатково, Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² помічений Ñк Ñпам. ДÑкуємо за повідомленнÑ. + +/editjournal_do.bml.success.head=УÑпішно + +/editjournal_do.bml.timeformat=Ð§Ð°Ñ Ñƒ 24-годинному форматі + +/editjournal_do.bml.title=Змінити запиÑи + +/editpics.bml.btn.proceed=Продовжити + +/editpics.bml.btn.save=Зберегти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/editpics.bml.curpics=Поточні юзерпики + +/editpics.bml.curpics.desc2=Це зображеннÑ, додані раніше. Ви можете призначити їм ключові Ñлова, щоб пізніше кориÑтуватиÑÑ ÑŽÐ·ÐµÑ€Ð¿Ð¸ÐºÐ°Ð¼Ð¸ за ключовим Ñловом, або обрати, Ñке з них викориÑтовувати за замовчуваннÑм, або видалити Ñтарі. Ð”Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ— кориÑтуйтеÑÑ Ñ„Ð¾Ñ€Ð¼Ð¾ÑŽ вгорі цієї Ñторінки. + +/editpics.bml.error.badurl=ÐдреÑа юзерпики Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ виглÑдає вірною. Вона муÑить починатиÑÑ Ð· http:// + +/editpics.bml.error.filetoolarge=Завантажене Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ñ Ð½Ð°Ð´Ñ‚Ð¾ велике. Розмір файла не може перевищувати [[maxsize]]. + +/editpics.bml.error.giffiletoolarge=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ GIF, Ñке ви завантажили, занадто велике. Розмір файлу GIF перевищує [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Розмір вашого Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ([[imagesize]]) перевищує макÑимальний розмір. Ваша картинка може бути макÑимум 100x100 пікÑелів. СкориÑтуйтеÑÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¾ÑŽ Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ зображень/фото, щоб зменшити розмір зображеннÑ. + +/editpics.bml.error.invalidimage=Ðевірний файл зображеннÑ. + +/editpics.bml.error.keywords=Ви викориÑтали ключове Ñлово "[[ekw]]" Ð´Ð»Ñ ÐºÑ–Ð»ÑŒÐºÐ¾Ñ… картинок. Випадково було вибрано одну з них, але радше за вÑе не ту, що ви хотіли. Можливо, в Ð²Ð°Ñ Ñ” Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÑƒÑ‚Ð¸ÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– виправити це. + +/editpics.bml.error.nomediauploads.delete=Цього разу не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ юзерпику. Ð’ даний Ñ‡Ð°Ñ Ð½Ð° Ñайті заборонено зміну подібних даних. + +/editpics.bml.error.toomanykeywords=[[?numwords|Ключове Ñлово|Ключові Ñлова]] "[[words]]" [[?numwords|не було збережено|не були збережені]], оÑкільки [[?numwords|його|їхнÑ]] юзерпика вже має [[max]] ключових Ñлів. + +/editpics.bml.error.toomanypics4=Ви доÑÑгли межи в [[num]] [[?num|юзерпику|юзерпики|юзерпик]]. Ви не можете завантажити цю юзерпику поки не видалити одну з раніше доданих. + +/editpics.bml.error.toomanypics_standout=Ви доÑÑгли межі в [[num]] [[?num|юзерпику|юзерпики|юзерпик]]. Ви не зможете більше завантажити жодної юзерпики, поки не видалите одну з Ñ–Ñнуючих. + +/editpics.bml.error.unsupportedtype=Файли типу [[filetype]] не підтримуютьÑÑ. Ви можете завантажити лише файли типу GIF, PNG або JPG. Майже вÑÑ– редактори зображень/фото можуть виконати Ð´Ð»Ñ Ð²Ð°Ñ Ñ‚Ð°ÐºÐµ перетвореннÑ. + +/editpics.bml.error.urlerror=Виникла помилка при Ñпробі отримати ваше зображеннÑ. + +/editpics.bml.fromfile=З файлу: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=Ñ„ + +/editpics.bml.fromurl=З адреÑи: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=а + +/editpics.bml.kilobytes=КБ + +/editpics.bml.label.comment=Коментар: + +/editpics.bml.label.comment.desc=Додатковий Ð¾Ð¿Ð¸Ñ Ñ†Ñ–Ñ”Ñ— картинки Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… друзів. + +/editpics.bml.label.default=За замовчуваннÑм: + +/editpics.bml.label.delete=Видалити: + +/editpics.bml.label.formats.desc=Дозволені формати - GIF, JPG та PNG. + +/editpics.bml.label.keywords=Ключові Ñлова: + +/editpics.bml.label.keywords.desc=Перелік Ñлів, через кому, що викориÑтовуватимутьÑÑ Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ цієї картинки. + +/editpics.bml.makedefault=Зробити юзерпикою за замовчуваннÑм + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=з + +/editpics.bml.nodefault=Без картинки за замовчуваннÑм + +/editpics.bml.noneupload=Ви не маєте жодної завантаженої картинки. Будь лаÑка, завантажте картинку, кориÑтуючиÑÑŒ формою унизу. + +/editpics.bml.noneupload2=У Ð²Ð°Ñ Ð²Ñ–Ð´Ñутні юзерпики. Будь лаÑка, завантажте юзерпику, викориÑтавши форму зверху. + +/editpics.bml.nopics=Ðемає картинок + +/editpics.bml.piclimitstatus=Ðаразі завантажено: [[current]] з [[max]]. + +/editpics.bml.restriction.fileformat=Формат файла має бути PNG, GIF або JPG + +/editpics.bml.restriction.filesize=Розмір файла має бути менше 40 КБ + +/editpics.bml.restriction.imagesize2=Якщо розмір Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ±Ñ–Ð»ÑŒÑˆÑƒÑ” 100Ñ…100 пікÑелів, ви будете переадреÑовані до Ñторінки "Створити юзерпику" + +/editpics.bml.restriction.keywords=Картинкою не можна буде ÑкориÑтатиÑÑ, Ñкщо не задані ключові Ñлова. + +/editpics.bml.restriction.keywords.faq=Ви повинні вказати ключове Ñлово Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— юзерпики + +/editpics.bml.title=Змінити юзерпики + +/editpics.bml.title2|notes=This is the new page title. .title is used by multisearch.bml. +/editpics.bml.title2=Змінити юзерпики + +/editpics.bml.title3|notes=This is the new page title. .title is used by multisearch.bml. +/editpics.bml.title3=Керувати юзерпиками + +/editpics.bml.uploaddesc=Юзерпики - це аватари чи іконки розміром 100Ñ…100 пікÑелів, Ñкі предÑтавлÑÑŽÑ‚ÑŒ ваÑ, ваш наÑтрій або почуттÑ, ваші зацікавленнÑ, тощо. Вони відображаютьÑÑ Ð² багатьох міÑцÑÑ… LiveJournal, включаючи ваш профіль, ваші журнальні запиÑи та коментарі, зроблені вами. + +/editpics.bml.uploaddesc.fb=Завантажити зменшену копію зображеннÑ, Ñке розташовано на вашому рахунку [[sitename]], Ñк нову юзерпику. + +/editpics.bml.uploaddesc.userpicfactory=Ви також можете завантажити JPG-Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑŒ-Ñкого розміру Ñ– ми відправимо Ð²Ð°Ñ Ð´Ð¾ Фабрики юзерпик, де ви легко зможете змінити його розмір. + +/editpics.bml.uploadheader=Завантажити нову юзерпику + +/editpics.bml.uploadheader.fb=Завантажити нову картинку із ScrapBook + +/editpics.bml.warning.keywords=Одна чи більше з ваших юзерпик не мають ключових Ñлів Ñ– тому не можуть бути викориÑтані. + +/editpics.bml.warning.keywords.faq=Одна чи більше з ваших юзерпик не мають ключових Ñлів Ñ– тому не можуть бути викориÑтані. + +/editprivacy.bml.button.update=Оновити запиÑи + +/editprivacy.bml.button.ya.rly=Так, оновити ці запиÑи + +/editprivacy.bml.calendar=Календар вашого журналу дає зручну можливіÑÑ‚ÑŒ переглÑнути Ñвої запиÑи за міÑÑць. + +/editprivacy.bml.intro=Змініть рівень конфіденційноÑÑ‚Ñ– уÑÑ–Ñ… запиÑів за певний період, вказавши початкову та кінцеву дату. Також ви можете вказати, що рівень конфіденційноÑÑ‚Ñ– буде змінено в уÑÑ–Ñ… запиÑах із певним рівнем конфіденційноÑÑ‚Ñ–. + +/editprivacy.bml.matching=Знайдено [[posts]] відповідних [[?запиÑів|запиÑ|запиÑи]]. + +/editprivacy.bml.notified=Рівень доÑтупу ваших запиÑів буде змінено найближчим чаÑом. ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ це ви отримаєте на електронною поштою. + +/editprivacy.bml.privacy=КонфіденційніÑÑ‚ÑŒ + +/editprivacy.bml.rusure=Ви впевнені, що бажаєте змінити ці запиÑи? + +/editprivacy.bml.timeframe=Період + +/editprivacy.bml.timeframe.all=ВеÑÑŒ Ñ‡Ð°Ñ + +/editprivacy.bml.timeframe.range=Між + +/editprivacy.bml.timeframe.range.end=Кінцева дата + +/editprivacy.bml.timeframe.range.start=Початкова дата + +/editprivacy.bml.title=Змінити рівень конфіденційноÑÑ‚Ñ– журналу + +/editprivacy.bml.unable=Вибачте, Ñ†Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ доÑтупна лише Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів. Якщо ви бажаєте дізнатиÑÑŒ більше про Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ñвого рахунку, відвідайте Ñвою Ñторінку "Стан рахунку". + +/edittags.bml.button.save=Зберегти зміни + +/edittags.bml.current=Поточні теґи: + +/edittags.bml.disabled=Вибачте, ÑиÑтему теґів наразі вимкнуто. + +/edittags.bml.entry=ЗапиÑ: + +/edittags.bml.error.db=Вибачте, трапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° бази даних. Спробуйте ще раз, будь лаÑка. + +/edittags.bml.intro=КориÑтуйтеÑÑ Ñ„Ð¾Ñ€Ð¼Ð¾ÑŽ, наведеною нижче, щоб змінити теґи цього запиÑу. + +/edittags.bml.invalid.entry=Зазначений Ð·Ð°Ð¿Ð¸Ñ Ñ” невірним. + +/edittags.bml.invalid.journal=Зазначений журнал Ñ” невірним. + +/edittags.bml.invalid.link=Ви потрапили до цієї Ñторінки невірним шлÑхом. Будь лаÑка, йдіть за поÑиланнÑм у запиÑу, щоб змінити теґи. + +/edittags.bml.invalid.notauthorized=Ви не маєте дозволу дивитиÑÑ Ñ†ÐµÐ¹ запиÑ. + +/edittags.bml.permissions.add.yes=Ви можете додати теґи зі ÑпиÑку вище. + +/edittags.bml.permissions.control.yes=Ви можете видалити або Ñтворити нові теґи. + +/edittags.bml.permissions.none=(Ви не маєте дозволу змінювати теґи цього запиÑу.) + +/edittags.bml.subject=Тема: + +/edittags.bml.title=Змінити теґи запиÑу + +/edittags.bml.users=Теґи кориÑтувача: + +/edittags.bml.view=ПереглÑнути цей запиÑ. + +/explore/index.bml.main.recententries=ОÑтанні запиÑи на [[sitenameabbrev]] + +/explore/index.bml.title=ОглÑнути [[sitenameabbrev]] + +/export.bml.btn.proceed=Продовжити... + +/export.bml.description=Ð¦Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ дозволÑÑ” Ñкачати ваші запиÑи в оÑобливому форматі Ð´Ð»Ñ Ñ€ÐµÐ·ÐµÑ€Ð²ÑƒÐ²Ð°Ð½Ð½Ñ. Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформації про Ñ€ÐµÐ·ÐµÑ€Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу зазирніть Ñюди. + +/export.bml.fields=ПолÑ: + +/export.bml.format.csv=CSV (значеннÑ, розділені комами) + +/export.bml.label.encoding=КодуваннÑ: + +/export.bml.label.field.allowmask=Дозволити маÑÐºÑƒÐ²Ð°Ð½Ð½Ñ + +/export.bml.label.field.currents=ÐаÑтрій та музика + +/export.bml.label.field.event=ÐŸÐ¾Ð´Ñ–Ñ + +/export.bml.label.field.eventtime=Ð§Ð°Ñ Ð¿Ð¾Ð´Ñ–Ñ— (за годинником кориÑтувача) + +/export.bml.label.field.itemid=ID Ðомер + +/export.bml.label.field.logtime=Ð§Ð°Ñ Ð·Ð°Ð¿Ð¸Ñу (за ÑиÑтемним годинником) + +/export.bml.label.field.security=Рівень безпеки + +/export.bml.label.field.subject=Тема: + +/export.bml.label.format=Формат: + +/export.bml.label.header=Заголовок: + +/export.bml.label.month=Оберіть міÑÑць: + +/export.bml.label.month.month=мм: + +/export.bml.label.month.year=рррр: + +/export.bml.label.notranslation=Ðе перекодовувати + +/export.bml.label.what=Що екÑпортувати: + +/export.bml.title=ЕкÑпорт журналу + +/export.bml.what.entries=ЗапиÑи журналу + +/export_do.bml.error.encoding=Обране невірне ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + +/feedback/ads.bml.confirm.line1=Ваші відгуки відправлені Ñ– будуть прочитані членами рекламної команди LiveJournal. + +/feedback/ads.bml.confirm.line2=Що ви бажаєте робити далі? + +/feedback/ads.bml.confirm.opt1=ПовернутиÑÑ Ð´Ð¾ того, що Ñ Ñ€Ð¾Ð±Ð¸Ð² + +/feedback/ads.bml.confirm.opt2=Перейти до моєї Ñтрічки друзів + +/feedback/ads.bml.confirm.opt3=Перейти до Мого LJ + +/feedback/ads.bml.input1=Бренд/назва продукту: + +/feedback/ads.bml.input2=Короткий Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸: + +/feedback/ads.bml.input2.example=(наприклад, ключові Ñлова, кольори, зображеннÑ) + +/feedback/ads.bml.input3=Відзначте вÑе, що вважаєте за потрібне: + +/feedback/ads.bml.input3.agegroup=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° не відповідає моїй віковій групі + +/feedback/ads.bml.input3.badbrand=Я не люблю цей бренд + +/feedback/ads.bml.input3.badplacement=Ðедоречне міÑце Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— реклами + +/feedback/ads.bml.input3.badproduct=Я не люблю цей продукт + +/feedback/ads.bml.input3.distracting=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° занадто набридлива + +/feedback/ads.bml.input3.language=Я не знаю мову цієї реклами + +/feedback/ads.bml.input3.likead=Я дійÑно люблю цю рекламу + +/feedback/ads.bml.input3.offensive=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° ображає мене + +/feedback/ads.bml.input3.other=Інше + +/feedback/ads.bml.input3.relevance=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° не відповідає міÑцю, де Ñ Ð¶Ð¸Ð²Ñƒ + +/feedback/ads.bml.input4=Повідомте нам, чи відповідає реклама категоріÑм, Ñкі ви обрали. + +/feedback/ads.bml.input4.nocat=Я не обирав(ла) жодну рекламну категорію. Оберіть ваші рекламні категорії. + +/feedback/ads.bml.input4.rightcat=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° відповідає одній з обраних мною категорій + +/feedback/ads.bml.input4.wrongcat=Ð¦Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð° не відповідає жодній з обраних мною категорій + +/feedback/ads.bml.lastline=Ми приділÑємо увагу кожному відправленому вами відгуку, але Ð½Ð°Ñ Ð½Ðµ дуже багато, тому ми не можемо відповідати на кожний відгук. Ми збираємо вÑÑ– відгуки Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб разом з нашими рекламодавцÑми покращити ваш доÑвід кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼ типом рахунку. Ð”Ð»Ñ ÐºÑ€Ð°Ñ‰Ð¾Ð³Ð¾ Ñ€Ð¾Ð·ÑƒÐ¼Ñ–Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… відгуківнадавайте, будь лаÑка, адреÑу реклами, Ñ—Ñ— Ð¾Ð¿Ð¸Ñ Ñ‚Ð° торговельну марку, що рекламуєтьÑÑ, інакше ми не зможемо правильно ідентифікувати рекламний блок Ñ– надати вам відповідь.

    ДÑкуємо! + +/feedback/ads.bml.line1=ДÑкуємо за чаÑ, Ñкий ви витратили Ð´Ð»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð³ÑƒÐºÑ–Ð² з цієї реклми. + +/feedback/ads.bml.line2=Повідомте нам про рекламу, Ñку щойно бачили. + +/feedback/ads.bml.notloggedin.line1=ВлаÑники рахунків [[sitename]] можуть вказати вподобаннÑ, рекламу з Ñких категорій вони хочуть бачити. + +/feedback/ads.bml.notloggedin.line2=Увійдіть або Ñтворіть рахунок, щоб вÑтановити вподобаннÑ. + +/feedback/ads.bml.where=Де ви бачили цю рекламу? + +/friends/add.bml.add.header=УÑпішно + +/friends/add.bml.add.next.friends=Читати Ñтрічку друзів + +/friends/add.bml.add.next.subscribe=Отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ нові запиÑи + +/friends/add.bml.add.text=КориÑтувача [[ljuser]] було додано до вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою Ñтрічку друзів тут/a>. + +/friends/add.bml.add.text.community2=Спільноту [[ljuser]] було додано до вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою оновлену Ñтрічку друзів. + +/friends/add.bml.add.text.feed2=Потік [[ljuser]] було додано до вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою оновлену Ñтрічку друзів. + +/friends/add.bml.add.text2=КориÑтувача [[ljuser]] було додано до вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою Ñтрічку друзів. + +/friends/add.bml.add.title=Друга додано! + +/friends/add.bml.btn.add=Додати [[user]] + +/friends/add.bml.btn.add.friend=Додати + +/friends/add.bml.btn.cancel=СкаÑувати + +/friends/add.bml.btn.modify=Змінити + +/friends/add.bml.btn.remove=Видалити + +/friends/add.bml.colors.bg=Тло + +/friends/add.bml.colors.disclaimer=Ðе вÑÑ– Ñтилі підтримують цей параметр + +/friends/add.bml.colors.fg=ТекÑÑ‚ + +/friends/add.bml.colors.header=Кольори + +/friends/add.bml.colors.help.text1=Ð”Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ раніше заданого коліру натиÑніть кольоровий квадратик праворуч. Щоб вказати оÑобливий колір, введіть його hex-код або натиÑніть квадратик ліворуч. + +/friends/add.bml.colors.help.text2=Ðаведіть курÑор вашої мишки на колір, щоб побачити його назву та hex-код. + +/friends/add.bml.colors.hover=(Ðаведіть мишу на колір, щоб побачити його назву) + +/friends/add.bml.colors.text=Оберіть кольори, що будуть предÑтавлÑти [[user]] у вашому ÑпиÑку друзів. + +/friends/add.bml.confirm.action1.person=ви можете читати Ñ—Ñ… запиÑи у Ñвоїй Ñтрічці друзів + +/friends/add.bml.confirm.action2.person=вони зможуть читати ваші запиÑи "тількі Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²" + +/friends/add.bml.confirm.syn.header=Додати транÑльоване Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ [[user]] Ñк друга? + +/friends/add.bml.confirm.syn.title1=Додати [[icon]][[user]] до вашої Ñтрічки друзів? + +/friends/add.bml.confirm.text=ÐатиÑніть кнопку, розміщену нижче, щоб додати [[user]] до Ñвого ÑпиÑку друзів. + +/friends/add.bml.confirm.text1.community2=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñпільноти дозволить вам бачити публічні запиÑи цієї Ñпільноти у влаÑній Ñтрічці друзів. Якщо ви хочете пиÑати до цієї Ñпільноти та Ñтати Ñ—Ñ— учаÑником, вам потрібно приєднатиÑÑ Ð´Ð¾ неї. + +/friends/add.bml.confirm.text1.feed=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÑƒ дозволÑÑ” вам читати його новий вміÑÑ‚ у Ñвоїй Ñтрічці друзів. + +/friends/add.bml.confirm.text1.news=Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ [[user]] дозволить вам читати його (Ñ—Ñ—) нові запиÑи у Ñвоїй Ñтрічці друзів. + +/friends/add.bml.confirm.text1.person=Коли ви когоÑÑŒ додаєте до друзів: + +/friends/add.bml.confirm.text2.person=Ви бажаєте додати [[user]]? + +/friends/add.bml.confirm.title.community=Додати [[icon]][[user]] до вашої Ñтрічки друзів? + +/friends/add.bml.confirm.title.news=Додати [[icon]][[user]] до вашої Ñтрічки друзів? + +/friends/add.bml.confirm.title.person=Додати [[icon]][[user]] до друзів? + +/friends/add.bml.disclaimer=Це не дає права доглÑдачам або учаÑникам Ñпільноти перегладати у вашому журналі запиÑи "лише Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²". + +/friends/add.bml.error.notvisible=КориÑтувач [[user]] не може бути доданий до друзів, оÑкільки рахунок видалено, знищено або призупинено. + +/friends/add.bml.error.sessionchanged=Дані ÑеÑÑ–Ñ— було змінено. Спробуйте ще раз. + +/friends/add.bml.error1.header=Спочатку увійдіть + +/friends/add.bml.error1.text=Щоб додати кориÑтувача до влаÑного ÑпиÑку друзів ви маєте Ñпочатку увійти. Якщо у Ð²Ð°Ñ Ñ‰Ðµ немає рахунку, ви можете його Ñтворити Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб Ñлідкувати за журналами Ñвоїх друзів. + +/friends/add.bml.error1.title=Додати друга + +/friends/add.bml.error2.text=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача неправильне або відÑутнє. Щоб додати друга, йдіть на Ñторінку Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð². + +/friends/add.bml.error2.text2=Введено помилкове Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Щоб додати друга перейдіть на Ñторінку "Редагувати друзів". + +/friends/add.bml.error3.text1=Ви вже маєте [[user]] у друзÑÑ…. Однак, ви можете змінити оÑобливі групи друзів, в Ñких ви бажаєте його/Ñ—Ñ— бачити. + +/friends/add.bml.error3.text2=[[user]] вже Ñ” у вашому ÑпиÑку друзів. Ви можете видалити його/Ñ—Ñ—, Ñкщо бажаєте. + +/friends/add.bml.error3.title=редагувати друга + +/friends/add.bml.groups.header=Групи друзів + +/friends/add.bml.groups.nogroup=Групи друзів не задано. + +/friends/add.bml.groups.text1=Ðеобов'Ñзково: Додати до однієї (чи більше) окремих груп друзів. + +/friends/add.bml.optional=Ðеобов'Ñзково + +/friends/add.bml.remove.header=УÑпішно + +/friends/add.bml.remove.text=КориÑтувач [[ljuser]] був видалений з вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою Ñтрічку друзів тут. + +/friends/add.bml.remove.text2=[[ljuser]] видалено з вашого ÑпиÑку друзів. Ви можете переглÑнути Ñвою оновлену Ñтрічку друзів або повернутиÑÑ Ð´Ð¾ Ñвого профілю. + +/friends/add.bml.remove.title=Друг Видалений! + +/friends/edit.bml.addfriends.head=Ð’ÑÑ– друзі + +/friends/edit.bml.addfriends.text=Щоб додати людей до Ñвоєї Ñтрічки друзів або щоб змінити кольори, Ñкі відповідають вже доданому другові, введіть їхні імена у Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ. Ви можете також запроÑити друга приєднатиÑÑŒ до LiveJournal. + +/friends/edit.bml.background=Тло + +/friends/edit.bml.bgcolor=Колір тла + +/friends/edit.bml.btn.close=Закрити + +/friends/edit.bml.btn.save=Зберегти зміни + +/friends/edit.bml.btn.toggle=ПереглÑнути + +/friends/edit.bml.editfriends.friend=Друг? + +/friends/edit.bml.editfriends.head=Редагувати друзів + +/friends/edit.bml.editfriends.name=Ð†Ð¼â€™Ñ + +/friends/edit.bml.editfriends.text=Ви можете будь-коли додати або видалити друга зі ÑпиÑку. Зелені Ñтрілочки ([[img1]]) вказують, що кориÑтувач у вашому ÑпиÑку друзів, а блакитна Ñтрілка ([[img2]]) вказує що ви у ÑпиÑку друзів. + +/friends/edit.bml.editfriends.username=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/friends/edit.bml.error.badjournaltype=Ðеможливо змінити друзів Ð´Ð»Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ такого типу. + +/friends/edit.bml.error.updating=Виникла помилка при оновленні вашого ÑпиÑку друзів: + +/friends/edit.bml.foreground=Фон + +/friends/edit.bml.friend=Друг + +/friends/edit.bml.hover=Проведіть мишкою над кольором, щоб побачити його назву. + +/friends/edit.bml.invite=Бажаєте запроÑити друга? + +/friends/edit.bml.mrcolor=МіÑтер КолориÑÑ‚ + +/friends/edit.bml.name=Ð†Ð¼â€™Ñ + +/friends/edit.bml.success.editfriends=Керувати ÑпиÑком друзів + +/friends/edit.bml.success.editgroups=Редагувати влаÑні групи друзів + +/friends/edit.bml.success.friendspage=Читати Ñтрічку друзів + +/friends/edit.bml.success.fromhere=Тут ви можете: + +/friends/edit.bml.success.head=УÑпішно + +/friends/edit.bml.textcolor=Колір текÑту: + +/friends/edit.bml.title=Змінити друзів + +/friends/edit.bml.title2=Керувати ÑпиÑком друзів + +/friends/edit.bml.user=КориÑтувач + +/friends/edit.bml.viewer=ПереглÑд кольору + +/friends/editgroups.bml.btn.ge.del=Видалити + +/friends/editgroups.bml.btn.ge.new=Ðова + +/friends/editgroups.bml.btn.ge.ren=Перейменувати + +/friends/editgroups.bml.btn.gs.private=Приватна + +/friends/editgroups.bml.btn.gs.public=Публічна + +/friends/editgroups.bml.btn.mv.down=ЗÑунути додолу + +/friends/editgroups.bml.btn.mv.up=ЗÑунути догори + +/friends/editgroups.bml.confirm.delete=Ви впевнені, що хочете видалити цю окрему групу друзів? + +/friends/editgroups.bml.done.btn=Зберегти зміни + +/friends/editgroups.bml.done.header=Готово? + +/friends/editgroups.bml.done.text=Коли закінчите, натиÑніть кнопку внизу, щоб зберегти зміни. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Ви доÑÑгли макÑимальної кількоÑÑ‚Ñ– оÑобливих груп друзів (30). Якщо ви видалили одну чи більше груп, але ще не зберегли зміни, то зробіть це зараз, а потім повернітьÑÑ Ð´Ð¾ цієї Ñторінки та перезавантажте Ñ—Ñ—. Тоді ви зможете Ñтворювати нові окремі групи друзів. + +/friends/editgroups.bml.error.text=Сервер видав таке Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку: + +/friends/editgroups.bml.group.public=(публічна) + +/friends/editgroups.bml.ingroup=У групі: + +/friends/editgroups.bml.ingroup.not=Ðе в групі: + +/friends/editgroups.bml.prompt.newname=Введіть Ñ–Ð¼â€™Ñ Ð½Ð¾Ð²Ð¾Ñ— окремої групи друзів: + +/friends/editgroups.bml.prompt.rename=Перейменувати цю окрему групу друзів у: + +/friends/editgroups.bml.saved.header=Збережено + +/friends/editgroups.bml.saved.text=Ваші окремі групи друзів збережено. + +/friends/editgroups.bml.text<< +Ðа цій Ñторінці ви можете редагувати окремі групи друзів. Окремі групи друзів потрібні Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ ваших запиÑів та ÑÐ¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñтрічки друзів. Докладніше у поширеному питанні "Що таке окремі групи друзів? Як мені ними кориÑтуватиÑÑ?" +

    +Ми пропонуємо декілька Ñтандартних груп друзів. Ви можете Ñортувати Ñвоїх друзів за роботою чи за навчаннÑм, друзів, Ñких знаєте тільки в мережі, чи в реальному житті, також, друзів, Ñкі Ñ” членами вашої родини. ПочувайтеÑÑ Ð²Ñ–Ð»ÑŒÐ½Ð¾ при зміні назв кожної з груп, Ñтворюйте додаткові групи друзів або видалÑйте, коли вони Ñтають непотрібними. +. + +/friends/editgroups.bml.text.sec=Щодо безпеки: Ñкщо ви хочете вилучити одну групу, а потім Ñтворити іншу, не треба перейменовувати одну групу в іншу. Якщо ви так зробите, то вÑÑ– запиÑи, Ñкі були видимі Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² Ñтарої групи, будуть видимі Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² з нової групи. + +/friends/editgroups.bml.title=Змінити окремі групи друзів + +/friends/editgroups.bml.title2=Керувати окремими групами друзів + +/friends/editgroups.bml.yourgroups=Ваші окремі групи друзів: + +/friends/edit_do.bml.addfriends.head=Додати друзів + +/friends/edit_do.bml.addfriends.text=Введіть імена кориÑтувачів ваших друзів у LiveJournal до полів, наведених нижче, та оберіть кольори тла та текÑту, Ñкі ви бажаєте, щоб були з ними пов'Ñзані.... + +/friends/edit_do.bml.background=Тло + +/friends/edit_do.bml.bgcolor=Колір тла: + +/friends/edit_do.bml.btn.close=Закрити + +/friends/edit_do.bml.btn.save=Зберегти зміни + +/friends/edit_do.bml.btn.toggle=Увімкнути вікно попереднього переглÑду + +/friends/edit_do.bml.done.head=Готово? + +/friends/edit_do.bml.done.text=Коли закінчите, натиÑніть кнопку "Зберегти зміни", наведену нижче... + +/friends/edit_do.bml.error.updating=Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ ÑпиÑку друзів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: + +/friends/edit_do.bml.fellowfriends.head=Чиїм другом ви Ñ” + +/friends/edit_do.bml.fellowfriends.text=ÐаÑтупні оÑоби додали Ð²Ð°Ñ Ð´Ð¾ ÑпиÑку Ñвоїх друзів. Можливо ви також бажаєте внеÑти Ñ—Ñ… до Ñвого ÑпиÑку друзів. Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ” довідковою, щоб ви знали Ñ—Ñ… імена кориÑтувачів у LiveJournal, але Ви не зобов'Ñзані додавати Ñ—Ñ… до Ñвого ÑпиÑку друзів. + +/friends/edit_do.bml.foreground=ТекÑÑ‚ + +/friends/edit_do.bml.friend=Друг + +/friends/edit_do.bml.hover=Ðаведіть мишу на колір, щоб побачити його назву + +/friends/edit_do.bml.mrcolor=ПереглÑд кольорів + +/friends/edit_do.bml.name=Ім'Ñ + +/friends/edit_do.bml.needmore=Якщо вам треба додати більше друзів, ніж Ñ” міÑÑ†Ñ Ñƒ цій формі, то збережіть зміни, а потім повернітьÑÑ Ð½Ð°Ð·Ð°Ð´, щоб додати ще. + +/friends/edit_do.bml.nofriends.head=Ðемає друзів? + +/friends/edit_do.bml.nofriends.text=Ðаразі у Ð²Ð°Ñ Ð½Ðµ визначено жодного друга. Однак ми впевнені, що в Ð²Ð°Ñ Ð¼Ð°Ñ” бути кілька друзів! :) ПроÑто введіть Ñ—Ñ… імена у LiveJournal... + +/friends/edit_do.bml.opt.addtolist=Додати друга + +/friends/edit_do.bml.opt.delete=Видалити? + +/friends/edit_do.bml.success.head=УÑпішно + +/friends/edit_do.bml.success.text=СпиÑок ваших друзів було оновлено. Ви можете переглÑнути Ñвою оновлену Ñтрічку друзів. + +/friends/edit_do.bml.success.text2=СпиÑок ваших друзів було оновлено. Ви можете переглÑнути Ñвою оновлену Ñтрічку друзів. + +/friends/edit_do.bml.textcolor=Колір текÑту: + +/friends/edit_do.bml.title=Редагувати друзів + +/friends/edit_do.bml.user=КориÑтувач + +/friends/edit_do.bml.viewer=ПереглÑд кольорів + +/friends/edit_do.bml.yourfriends.head=Ваші друзі + +/friends/edit_do.bml.yourfriends.text=Ðаразі в Ð²Ð°Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ñ– наÑтупні друзі: + +/friends/filter.bml.editgroups=Якщо ви бажаєте відредагувати групи ваших друзів, ідіть на Ñторінку [[link]]. + +/friends/filter.bml.error.nogroups=Ви не можете групувати друзів, оÑкільки Ñпочатку необхідно вÑтановити групи друзів. + +/friends/filter.bml.error.nogroups.header=Ðемає груп + +/friends/filter.bml.error.nogroups2=Ви не можете фільтрувати Ñвій ÑпиÑок друзів, поки не Ñтворити влаÑні групи друзів. + +/friends/filter.bml.reset=ОчиÑтити + +/friends/filter.bml.select=Оберіть групу(и) друзів, Ñкі ви хотіли б бачити на Ñвоїй Ñторінці друзів. + +/friends/filter.bml.select.header=Обрати групи друзів + +/friends/filter.bml.submit=ПереглÑнути! + +/friends/filter.bml.title=Фільтр друзів + +/friends/filter.bml.title2=Сторінка "Фільтр друзів" + +/friends/graph.bml.error.unknownuser.header=Ðевідомий кориÑтувач + +/friends/graph.bml.error.unknownuser.text=Ðемає кориÑтувачі з таким ім'Ñм. Вибачте. + +/friends/graph.bml.reloadnote=Якщо Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ завантажуєтьÑÑ, натіÑÑ‚ÑŒ "Оновити" (Reload). + +/friends/graph.bml.user=КориÑтувач: [[user]] (профіль) + +/friends/index.bml.about<< +Ð¦Ñ Ñторінка дозволÑÑ” вам керувати Ñвоїм ÑпиÑком друзів. +Додаючи інших кориÑтувачів до Ñвого ÑпиÑку друзів, ви можете легко бачити їхні запиÑи у Ñвоїй Ñтрічці друзів. Ви також можете додавати Ñпільноти та Ñиндикативні потоки до Ñвого ÑпиÑку друзів, щоб бачити їхні запиÑи у Ñвоїй Ñтрічці друзів. +. + +/friends/index.bml.edit.about=Додати або видалити кориÑтувачів з вашого ÑпиÑку друзів або змінити колір Ñ—Ñ… предÑтавленнÑ. + +/friends/index.bml.editgroups.about=СтвореннÑ, Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð³Ñ€ÑƒÐ¿ ваших друзів. + +/friends/index.bml.filter=Ці групи друзів можуть викориÑтовуватиÑÑ, щоб Ñортувати виглÑд вашої Ñторінки дрзуів: ви можете бачити тільки запиÑи певної групи. Їх також можна викориÑтовувати Ð´Ð»Ñ Ñ€Ñ–Ð²Ð½ÐµÐ¹ безпеки, заÑнованих на групах (дивітьÑÑ Ð½Ð¸Ð¶Ñ‡Ðµ). + +/friends/index.bml.filter.about=Фільтрувати ваш ÑпиÑок друзів згідно з визначеними підгрупами. + +/friends/index.bml.groups=Крім того, можуть бути визначені підгрупи друзів. + +/friends/index.bml.invite.about2=ЗапроÑити друга Ñтворити рахунок на [[sitename]] + +/friends/index.bml.invite.title=ЗапроÑити друга + +/friends/index.bml.nudge.about=Штурхнути взаємних друзів, Ñкі давно нічого не пиÑали, аби дати їм знати про ваше Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ Ñ—Ñ…. + +/friends/index.bml.nudge.title=Штурхнути друга + +/friends/index.bml.security=Ваш ÑпиÑок друзів також викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñів із обмеженним доÑтупом. Ви можете більше довідатиÑÑŒ про безпеку вашого ÑпиÑку друзів у розділі Друзі та рівні доÑтупу. + +/friends/index.bml.security.custom=ЗапиÑи з рівнем безпеки "ОÑобливий" може дивитиÑÑ Ð³Ñ€ÑƒÐ¿Ð° друзів, Ñку ви визначили. Проте, не вÑÑ– клієнтÑькі програми наразі підтримують оÑобливі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸. + +/friends/index.bml.security.header=Безпека + +/friends/index.bml.security.only=ЗапиÑи з рівнем безпеки "Тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²" може дивитиÑÑ Ð±ÑƒÐ´ÑŒ-Ñкий кориÑтувач з вашого ÑпиÑку друзів. + +/friends/index.bml.title=ЗаÑоби ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñми + +/friends/index.bml.tools=ЗаÑоби + +/friends/invite.bml.abook.empty=ÐŸÐ¾Ñ€Ð¾Ð¶Ð½Ñ Ð°Ð´Ñ€ÐµÑна книга + +/friends/invite.bml.btn.add_contacts=Додати вибрані контакті + +/friends/invite.bml.btn.invite=ЗапроÑити! + +/friends/invite.bml.error.abook.passwd=Помилка авторизації.Перевірьте, будь лаÑка, Ñвої логін та пароль + +/friends/invite.bml.error.abook.problem=Технічна помилка, код помилки = + +/friends/invite.bml.error.bademail=Підроблена email-адреÑа: [[errormsg]] + +/friends/invite.bml.error.early_bad_email=Помилка: Поганий email + +/friends/invite.bml.error.limit_exceeded=Ліміт перевищено.Ðе надіÑлано + +/friends/invite.bml.error.needcreatelink=Ð”Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ вашим другом вам необхідно додати поÑиланнÑ:[[link]] + +/friends/invite.bml.error.noemail=Будь лаÑка, введіть email-адреÑу Ñвого друга: + +/friends/invite.bml.error.noimagesallowed=Ð’ цьому лиÑÑ‚Ñ– Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ підтримуютьÑÑ. + +/friends/invite.bml.error.noname=Будь лаÑка, введіть ім'Ñ Ñвого друга. + +/friends/invite.bml.error.nooffsitelinksallowed=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° інші Ñайти, крім [[sitename]], не дозволені в цьому лиÑÑ‚Ñ–. + +/friends/invite.bml.error.overratelimit=Схоже, що ви збираєтеÑÑ Ð·Ð°Ð¿Ñ€Ð¾Ñити багатьох друзів до [[sitename]]. Щоб допомогти нам у боротьбі зі Ñпамом, ви можете надіÑлати решту запрошень з вашої email-адреÑи. ПереконайтеÑÑ, що додали запрошувальне поÑÐ¸Ð»Ð°Ð½Ð½Ñ (його можна знайти зверху Ñторінки) до Ñвого лиÑта. + +/friends/invite.bml.error.useralreadyhasaccount=Ви відправлÑєте Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачу, Ñкий вже має рахунок. + +/friends/invite.bml.form.add_line=Додати лінію + +/friends/invite.bml.form.delete_line=Видалити лінію + +/friends/invite.bml.form.header=Заповніть цю форму, щоб запроÑити когоÑÑŒ до [[sitename]]: + +/friends/invite.bml.form.import.head=Імпорт контактів + +/friends/invite.bml.form.import.login=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/friends/invite.bml.form.import.password=Пароль + +/friends/invite.bml.form.import.service=Ð¡ÐµÑ€Ð²Ñ–Ñ + +/friends/invite.bml.form.import.submit=Імпорт контактів + +/friends/invite.bml.form.input.email=Email-адреÑа вашого друга: + +/friends/invite.bml.form.input.message=Ваш лиÑÑ‚ до нього: + +/friends/invite.bml.form.input.name=Ім'Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ друга: + +/friends/invite.bml.form.note=Якщо ви бажаєте запроÑити друга до окремої Ñпільноти, то можете тут вказати назву та адреÑу Ñпільноти. + +/friends/invite.bml.head=ЗапроÑити друзів + +/friends/invite.bml.import=Імпортувати контакти з веб- Ñкриньки + +/friends/invite.bml.import.desc=Ð¦Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° дозволить імпортувати ваші контакти з різних поштових ÑиÑтем + +/friends/invite.bml.init_text=ЗапуÑкаємо, прошу зачекати + +/friends/invite.bml.intro=За цим поÑиланнÑм ваш друг зможе потрапити на Ñторінку Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ [[sitename]]. Ваш журнал буде автоматично додано до його друзів, також на Ñторінці буде можливіÑÑ‚ÑŒ долучитиÑÑ Ð´Ð¾ Ñпільнот, в Ñких ви берете активну учаÑÑ‚ÑŒ. + +/friends/invite.bml.intro.link=ПоÑиланнÑ: [[createlink]] + +/friends/invite.bml.intro.useform=Ви можете кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ формою так чаÑто, Ñк вам потрібно, або проÑто Ñкопіювати наведене поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ‚Ð° надіÑлати його з влаÑної поштової Ñкриньки. [[sitename]] не зберігає жодних даних піÑÐ»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²ÐºÐ¸ запрошеннÑ. + +/friends/invite.bml.message_body<< +[[username]] запроÑив Ð²Ð°Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑŒ до [[sitenameshort]]. +[sitenameshort]]- це міÑце де люди розміщуєть Ñ– поширюють думки в перÑональних шоденниках та Ñпільнотах. Розпочніть Ñвій влаÑний журнал або проÑто розÑлабтеÑÑŒ Ñ– наÑлолоджуйтеÑÑŒ атмоÑферою +Створити разунок (так, це безкоштовно!): +[[create_link]] +[[username]] буде автоматично даданий до вашого ÑпиÑку друзів, Ñ– ми йому повідомимо коли ви Ñтоврете Ñвій рахунок, щоб він також міг Ð²Ð°Ñ Ð´Ð¾Ð´Ð°Ñ‚Ð¸. +Ваш, +[[longname]] + +. + +/friends/invite.bml.presented_only_newbies=Тут тільки Ñ‚Ñ– адреÑи, Ñкі буди знайдені в вашій адреÑній книзі Ñ– не приÑутні в жж + +/friends/invite.bml.processed_as=Цей лиÑÑ‚ вже оброблено + +/friends/invite.bml.running=ЗапуÑкаємо, прошу зачекати.... + +/friends/invite.bml.same_as=Ð¦Ñ Ñкринька вже Ñ” в ÑпиÑку + +/friends/invite.bml.subject=[[username]]запроÑив Ð²Ð°Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑŒ до [[sitenameshort]]! + +/friends/invite.bml.success=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¾ до [[email]]! Бажаєте запроÑити когоÑÑŒ іншого? + +/friends/invite.bml.title=ЗапроÑити друга! + +/friends/invite.bml.too_many=Ви не можете вибрати так багато контактів + +/friends/nudge.bml.btn.nudge=Штурхнути! + +/friends/nudge.bml.email.body.closing=Щиро ваша, + +/friends/nudge.bml.email.body.greeting=Гей, [[user]]! + +/friends/nudge.bml.email.body.info=ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про штурхани: [[helpurl]] + +/friends/nudge.bml.email.body.lastupdated|notes=[[timeago]] will be one of the strings "time.ago.week", "time.ago.day", "time.ago.hour", "time.ago.minute", or "time.ago.second". +/friends/nudge.bml.email.body.lastupdated=Ваш взаємний друг [[user]] повідомлÑÑ”, що оÑтанній раз ви оновлювали Ñвій журнал на [[sitename]] деÑÑŒ [[timeago]]! Будьте ґречні - Ñтворіть новий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° ([[updateurl]]) + +/friends/nudge.bml.email.body.neverupdated=Ваш взаємний друг [[user]] зауважив, що ви ніколи не пиÑали до Ñвого журналу на [[sitename]]! Будьте ґречні - Ñтворіть новий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° ([[updateurl]]) + +/friends/nudge.bml.email.body.team=Команда [[sitename]] + +/friends/nudge.bml.email.subject=Ваш друг надіÑлав вам штурхана з [[sitename]] + +/friends/nudge.bml.error.cantloaduser=Ðеможливо завантажити даного кориÑтувача. + +/friends/nudge.bml.error.cantnudgeuser=КориÑтувача, Ñкого ви бажаєте шутрхнути, ÑтурÑати неможна. + +/friends/nudge.bml.error.disabled=Штурхани зараз відключені. + +/friends/nudge.bml.error.invalidacctstatus.header=Штурхани відключені + +/friends/nudge.bml.error.invalidacctstatus.text=Ми знаємо, що ви б хотіли почути [[user]], але тип рахунка цього кориÑтувача не передбачає штурханнÑ. + +/friends/nudge.bml.error.invalidaccttype.header=Ðе людина + +/friends/nudge.bml.error.invalidaccttype.text=Ми знаємо, що ви б хотіли почути [[user]], але ви можете штурхати тільки інших кориÑтувачів. + +/friends/nudge.bml.error.nonudge.header=Штурхани відключені + +/friends/nudge.bml.error.nonudge.text=Ми знаємо, що ви б хотіли почути [[user]], але цей кориÑтувач не дозволÑÑ” Ñебе штурхати. + +/friends/nudge.bml.error.notmutual.header=Ðе взаємні друзі + +/friends/nudge.bml.error.notmutual.text=Ми знаємо, що ви б хотіли почути [[user]], але Ñхоже, ви не взаємні друзі. Зараз тільки взаємні друзі можуть штурхати одне одного. + +/friends/nudge.bml.intro=Ви заÑмучені тим, що хтоÑÑŒ з ваших взаємних друзів давно не оновлював Ñвій журнал? Ðадішліть йому штурхана, аби нагадати про Ñвоє Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ його! + +/friends/nudge.bml.mutualfriends.header=Ваші взаємні друзі + +/friends/nudge.bml.mutualfriends.none=Схоже ви не маєте взаємних друзів. Ðаразі ÑˆÑ‚ÑƒÑ€Ñ…Ð°Ð½Ð½Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾ тільки взаємними друзÑми. + +/friends/nudge.bml.mutualfriends.sort.lastupdated=Сортувати за: оÑтаннім оновленнÑм чи за ім’Ñм кориÑтувача? + +/friends/nudge.bml.mutualfriends.sort.username=Сортувати за: оÑтанім оновленнÑм чи за ім’Ñм кориÑтувача? + +/friends/nudge.bml.mutualfriends.text=Вам здаєтьÑÑ, що ви давно когоÑÑŒ не чули, але не знаєте, кого Ñаме? Це вÑÑ– ваші взаємні друзі, Ñкі не оновлювали Ñвої журнали упродовж тижнÑ. + +/friends/nudge.bml.mutualfriends.userinfo|notes=[[timeago]] will be either of the strings ".mutualfriends.userinfo.lastupdated" or ".mutualfriends.userinfo.neverupdated". +/friends/nudge.bml.mutualfriends.userinfo=[[user]] - [[timeago]] (штурхнути) + +/friends/nudge.bml.mutualfriends.userinfo.lastupdated|notes=[[timeago]] will be one of the strings "time.ago.week", "time.ago.day", "time.ago.hour", "time.ago.minute", or "time.ago.second". +/friends/nudge.bml.mutualfriends.userinfo.lastupdated=допиÑував(ла) [[timeago]] + +/friends/nudge.bml.mutualfriends.userinfo.neverupdated=жодних запиÑів + +/friends/nudge.bml.nudgeuser.header=Штурхнути [[user]]? + +/friends/nudge.bml.nudgeuser.lastupdated|notes=[[timeago]] will be one of the strings "time.ago.week", "time.ago.day", "time.ago.hour", "time.ago.minute", or "time.ago.second". +/friends/nudge.bml.nudgeuser.lastupdated=Схоже, що кориÑтувач [[user]] воÑтаннє оновлював Ñвій журнал [[timeago]]. Якщо бажаєте, ми відправимо йому цей короткий лиÑÑ‚ його мовою: + +/friends/nudge.bml.nudgeuser.neverupdated=Схоже, що кориÑтувач [[user]] ніколи не оновлював Ñвій журнал. Якщо бажаєте, ми відправимо йому цей короткий лиÑÑ‚ його мовою: + +/friends/nudge.bml.nudgeuser.recentlyupdated=Схоже, що кориÑтувач [[user]] оновлював Ñвій журнал на цьому тижні. Ми знаємо, що ви бажаєте його чути, але ви не можете його зараз штурхнути. + +/friends/nudge.bml.success.header=Штурхана відправлено + +/friends/nudge.bml.success.text=Ви штурхнули [[user]]. + +/friends/nudge.bml.success.text2=Ви штурхнули [[user]]. Отримайте ÑповіщеннÑ, коли цей кориÑтувач оновить Ñвій журнал. + +/friends/nudge.bml.title=Штурхнути друга! + +/friends/popwithfriends.bml.count=КількіÑÑ‚ÑŒ + +/friends/popwithfriends.bml.error.cantfetchfriends=Помилка при отриманні переліку ваших друзів. + +/friends/popwithfriends.bml.error.disabled=Цю можливіÑÑ‚ÑŒ вимкнено. + +/friends/popwithfriends.bml.exclude_own=Додатково, ви можете виключити ваших друзів. + +/friends/popwithfriends.bml.include_own=Додатково, ви можете включити ваших друзів. + +/friends/popwithfriends.bml.intro=ÐаÑтупні друзі чаÑто вноÑÑÑ‚ÑŒÑÑ Ð´Ð¾ ÑпиÑку вашими друзÑми, але не вами. + +/friends/popwithfriends.bml.intro_own=ÐаÑтупні друзі чаÑто вноÑÑÑ‚ÑŒÑÑ Ð´Ð¾ ÑпиÑку вашими друзÑми. СпиÑок також включає ваших влаÑних друзів. + +/friends/popwithfriends.bml.invalidaccttype=Пошук популÑрних кориÑтувачів Ñеред ваших друзів доÑтупний тільки Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів з платним рахунком. Якщо ви бажаєте детальніше дізнатиÑÑ Ð¿Ñ€Ð¾ перехід до платного рахунку, завітайте на Ñторінку про платні рахунки. + +/friends/popwithfriends.bml.no_users=Ðема кориÑтувачів. + +/friends/popwithfriends.bml.title=ПопулÑрні кориÑтувачі Ñеред ваших друзів + +/friends/popwithfriends.bml.user=КориÑтуач + +/go.bml.defaultbody=Жодних параметрів не передано. + +/go.bml.defaulttitle=Помилка + +/go.bml.error.noentry.next=Ðемає запиÑу, розташованого піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾. + +/go.bml.error.noentry.prev=Ðемає запиÑу, розташованого до цього. + +/go.bml.error.noentrytitle=Ðемає запиÑу + +/go.bml.error.redirkey=Підроблений redir_key. + +/go.bml.error.usernotfound=КориÑтувач не знайдений. + +/imgupload.bml.gallery.label=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ–Ð· галереї ScrapBook + +/imgupload.bml.login.message2=Ðеобхідно увійти, щоб завантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ–Ð· файлу або вÑтавити його із Scrapbook. + +/imgupload.bml.size=Коли Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð±ÑƒÐ²Ð°Ñ”Ñ‚ÑŒÑÑ Ð· файлу або з Ðльбому, Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ Ñƒ розмірі 320 Ñ… 240 (Ñередній) та робитьÑÑ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ повнорозмірного зображеннÑ. + +/index.bml.about.header=Про LiveJournal + +/index.bml.about.joining=ÐŸÑ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ Ñайту Ñ” безкоштовним. КориÑтувачі можуть вирішити зробити платними Ñвої рахунки, щоб отримати додаткові можливоÑÑ‚Ñ–. + +/index.bml.about.us=LiveJournal - проÑтий у кориÑтуванні (але надзвичайно потужний Ñ– зручний Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ) заÑіб Ð´Ð»Ñ Ð¾ÑобиÑтих публікацій ("блоґ"), побудований на програмному забезпеченні з відкритим кодом. + +/index.bml.boldcreate=Створіть влаÑний LiveJournal ! + +/index.bml.frank.image.alt=Цап Френк - таліÑман LiveJournal. + +/index.bml.frank.logo2="Ме-е-е", - каже Френк. + +/index.bml.frank.logo3="Ме-е-е", — каже Френк. + +/index.bml.frank.logo4="Ме-е-е", — + +/index.bml.learnmore.header=Бажаєте дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ? + +/index.bml.learnmore.text=ОзнайомтеÑÑ, будь лаÑка, з оглÑдом наших можливоÑтей. Задоволені? Створіть Ñвій влаÑний LiveJournal! + +/index.bml.loggedin.explore=ДоÑлідити + +/index.bml.loggedin.explore.directorysearch=Пошук у каталозі + +/index.bml.loggedin.explore.feeds=ПроглÑнути потоки + +/index.bml.loggedin.explore.interests=Пошук за інтереÑами + +/index.bml.loggedin.explore.latestposts=ОÑтанні загальнодоÑтупні запиÑи + +/index.bml.loggedin.explore.new=(Ðове) + +/index.bml.loggedin.explore.random=Випадковий журнал + +/index.bml.loggedin.explore.upgrade=Покращити + +/index.bml.loggedin.greeting=Зручні поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/index.bml.loggedin.greeting.account=Керувати рахунком + +/index.bml.loggedin.greeting.alert=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² [[user]]! + +/index.bml.loggedin.greeting.friendspage=Стрічка друзів + +/index.bml.loggedin.greeting.inbox=Вхідні + +/index.bml.loggedin.greeting.inboxcount=[[num]] нових [[?num|повідомленнÑ|повідомленнÑ|повідомленнÑ]] + +/index.bml.loggedin.greeting.lastupdated=ВоÑтаннє оновлювалоÑÑŒ [[timeago]] + +/index.bml.loggedin.greeting.manage=Мій рахунок + +/index.bml.loggedin.greeting.neverupdated=Ви ще не робили запиÑів у Ñвій журнал + +/index.bml.loggedin.greeting.post=Створити Ð·Ð°Ð¿Ð¸Ñ + +/index.bml.loggedin.heading=З поверненнÑм до LiveJournal! + +/index.bml.loggedin.heading2=Здоровенькі були, [[user]] + +/index.bml.loggedin.link1=ÐапиÑати до журналу + +/index.bml.loggedin.link1.text=Чи знаєте ви, що тепер можна швидко додати фото? + +/index.bml.loggedin.link2=Читати Ñтрічку друзів + +/index.bml.loggedin.link2.text=ДивітьÑÑ Ð¾Ñтанні зміни в журналах Ñвоїх друзів. + +/index.bml.loggedin.link3=Мій LJ + +/index.bml.loggedin.link3.text=Ðалаштуйте LJ за влаÑними вподобаннÑми. + +/index.bml.loggedin.quicklink=Швидкі поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/index.bml.loggedin.quicklink1=Змінити журнальні запиÑи + +/index.bml.loggedin.quicklink2=Редагувати юзерпики + +/index.bml.loggedin.quicklink3=Шукати за зацікавленнÑми + +/index.bml.loggedin.quicklink3.text=Знайдіть інших людей з подібними інтереÑами. + +/index.bml.loggedin.quicklink4=Читати оÑтанні новини LJ + +/index.bml.loggedout.bullet1=ДілітьÑÑ Ð· обмеженим колом або з уÑіма + +/index.bml.loggedout.bullet2=Тримайте зв'Ñзок зі Ñвоїми друзÑми та читайте улюблені блоґи + +/index.bml.loggedout.bullet3=Беріть учаÑÑ‚ÑŒ у Ñпільнотах + +/index.bml.loggedout.bullet4=Пишіть до Ñвого журналу звідки завгодно + +/index.bml.loggedout.bullet5=ЗалишайтеÑÑ Ñобою + +/index.bml.loggedout.button=Створіть рахунок + +/index.bml.loggedout.button2=Створити журнал + +/index.bml.loggedout.facts=Ð’Ñередині [[sitename]] + +/index.bml.loggedout.facts.news=Читайте про оÑтанні можливоÑÑ‚Ñ– у новинах. + +/index.bml.loggedout.facts.open=Відкриті люди та відкритий код. ВолонтерÑька підтримка від людей, Ñкі люблÑÑ‚ÑŒ [[sitename]]. + +/index.bml.loggedout.free=ПриєднатиÑÑŒ до [[sitename]] можна безкоштовно. + +/index.bml.loggedout.free.more=Пройдіть оглÑдовий тур, щоб ознайомитиÑÑŒ із приємними можливоÑÑ‚Ñми, Ñкі ви можете викориÑтовувати Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñів та обміну із бувалими та новими друзÑми. + +/index.bml.loggedout.heading=Що таке [[sitename]]? + +/index.bml.loggedout.loginnote=Прощу увійти Ð´Ð»Ñ Ð´Ð¾Ñтупу до Ñайту + +/index.bml.loggedout.mobile.alt=Мобільні можливоÑÑ‚Ñ– + +/index.bml.loggedout.principles.community=Ð¡Ð¿Ñ€Ð°Ð²Ð¶Ð½Ñ Ñпільнота + +/index.bml.loggedout.principles.content=Важлива Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/index.bml.loggedout.principles.journal=Ваш оÑобиÑтий журнал + +/index.bml.loggedout.principles.stayingintouch=Завжди в курÑÑ– + +/index.bml.loggedout.promos.title=Круті штучки + +/index.bml.loggedout.taketour=ОглÑдовий тур + +/index.bml.loggedout.text.beyou=LiveJournal - це міÑце, де ви можете бути Ñобою. Ви можете налаштувати виглÑд Ñвого журналу згідно Ñвоїх уподобань. У кожному зі Ñвоїх запиÑів ви можете вказати Ñвій наÑтрій та музику, що зараз грає. Ми знаємо що ви унікальні Ñ– нам подобаєтьÑÑ Ð²Ð°Ñˆ шлÑÑ…. + +/index.bml.loggedout.text.connect=КориÑтувачі LiveJournal Ñтворили Ñпільноти, приÑвÑчені вÑім зацікавленнÑм, Ñкі тільки можна уÑвити. ДолучітьÑÑ Ð´Ð¾ вже Ñ–Ñнуючої Ñпільноти або Ñтворіть нову, приÑвÑчену вашому клаÑу, зацікавленню чи хоббі. Ð¡Ð¿Ñ–Ð»ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ Ñпільноті — це чудова нагода дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ цікавих речей Ñ– знайти нових друзів. + +/index.bml.loggedout.text.keepup=Кожен журнал має Ñтрічку друзів, на Ñкій можна читати вÑÑ– оÑтанні запиÑи Ñвоїх друзів. Ви також можете до неї додати потоки веб-Ñайтів, щоб читати улюблені блоґи та журнали в одному міÑці. + +/index.bml.loggedout.text.main=LiveJournal - це проÑтий Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸ÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñіб, Ñкий дозволÑÑ” вам ÑамовиражатиÑÑ Ñ‚Ð° ÑпілкуватиÑÑ Ð·Ñ– Ñвоїми друзÑми.

    Ви можете викориÑтовувати LiveJournal в багатьох напрÑмках: веÑти оÑобиÑтий журнал, блоґ, Ñоціальну мережу та багато чого іншого.

    LJ побудовано на програмному забезпеченні з відкритим кодом.

    + +/index.bml.loggedout.text.main1=LiveJournal - це проÑтий у кориÑтуванні заÑіб, Ñкий дозволÑÑ” вам ÑамовиражатиÑÑ Ñ‚Ð° ÑпілкуватиÑÑ Ð·Ñ– Ñвоїми друзÑми.

    Ви можете викориÑтовувати LiveJournal у багатьох напрÑмках: Ñк оÑобиÑтий журнал, блоґ, Ñоціальну мережу та багато чого іншого.

    LJ побудовано на програмному забезпеченні з відкритим кодом.

    + +/index.bml.loggedout.text.post=Іноді вам треба щоÑÑŒ напиÑати, коли поруч немає комп'ютера. З платним рахунком, ви можете публікувати фотографії та текÑти, викориÑтовуючи Ñвій мобільний телефон або інші мобільні приÑтрої. Також ви можете ÑкориÑтатиÑÑ Ð±ÑƒÐ´ÑŒ-Ñким телефоном, щоб зробити голоÑове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ Ñвого журналу. + +/index.bml.loggedout.text.share=ДілітьÑÑ Ñвоїми думками та фотографіÑми лише зі Ñвоїми друзÑми або ведіть публічний журнал, зміÑÑ‚ Ñкого зможе побачити будь-хто. Ви можете вÑтановити рівень безпеки Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ запиÑу, Ñаме ви визначаєте, хто зможе читати або коментувати. Створюйте оÑобливі групи, щоб ділитиÑÑ Ð·Ð°Ð¿Ð¸Ñами з кращими друзÑми, колегами або кимоÑÑŒ оÑобиÑто. + +/index.bml.loggedout.whatislj=[[sitename]] - це проÑтий у кориÑтуванні заÑіб ÑпілкуваннÑ, Ñкий дозволить вам виÑловитиÑÑŒ та ÑпілкуватиÑÑŒ із друзÑми в мережі. + +/index.bml.loggedout.whatislj.more=Ви можете викориÑтовувати [[sitename]] по-різному: Ñк приватний щоденник, Ñк блоґ, Ñк форум Ð´Ð»Ñ Ð´Ð¸ÑкуÑій, Ñк Ñоціальну мережу та багато іншого. + +/index.bml.loggedout.whatislj2=LiveJournal дає вам можливіÑÑ‚ÑŒ ÑамовиразитиÑÑŒ, розповіÑти про Ñвоє Ð¶Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° ÑпілкуватиÑÑŒ з друзÑми в мережі. + +/index.bml.loggedout.xclaimr=ÐŸÑ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð‘Ð•Ð—ÐŸÐ›ÐТÐЕ! + +/index.bml.meta.desc=LiveJournal.com - це міÑце, де ви можете поділитиÑÑ Ñвоїми думками зі Ñвітом. + +/index.bml.meta.keywords=щоденник, журнал, онлайн журнал, щоденники, пиÑати, онлайн щоденник, веб щоденник + +/index.bml.news.head=Ðовини + +/index.bml.news.text=ОÑтанні новини Ñайту: + +/index.bml.news.title=ОÑтанні новини + +/index.bml.post=Жива ÑтатиÑтика публікацій + +/index.bml.post.hour=За годину: + +/index.bml.post.latest=ОÑтанні запиÑи + +/index.bml.post.min=За хвилину: + +/index.bml.promo.esn=Покращіть рахунок до платного, щоб відÑлідковувати Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² гілках + +/index.bml.promo.expressive_upgrade=Покращіть рахунок до платного, щоб отримати доÑтуп до вÑÑ–Ñ… Ñтилів! + +/index.bml.promo.feeds.checkit=1000 популÑрних потоків + +/index.bml.promo.feeds.feed1=[[ljuser]]
    Слово Ð´Ð½Ñ Ð²Ñ–Ð´ Dictionary.com + +/index.bml.promo.feeds.feed2=[[ljuser]]
    Таємниці анонімних лиÑтівок + +/index.bml.promo.feeds.head=Синдикативні потоки + +/index.bml.promo.feeds.text1=Читайте вибрані блоґи проÑто у влаÑній Ñтрічці друзів + +/index.bml.promo.gift_shop1=ЗалишайтеÑÑ Ñ„Ð°Ð¹Ð½Ð¸Ð¼Ð¸ цього літа у футболці від LJ вÑього за $11 (включаючи доÑтавку) з нашої крамниці. + +/index.bml.promo.invitefriend=ЗапроÑÑ–Ñ‚ÑŒ друга Ñтворити рахунок у LiveJournal, щоб він міг читати ваші запиÑи "тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²" + +/index.bml.promo.new_styles.announce=Ðові Ñтилі журналів! + +/index.bml.promo.new_styles.announce2=Ðові Ñтилі з конкурÑу
    вже у наÑ. + +/index.bml.promo.new_styles.upgrade=Отримайте нові Ñтилі журналу! + +/index.bml.promo.paid.expressive=Понад 70 нових тем у макеті "Expressive" + +/index.bml.promo.paid_acct1=Отримайте Платний рахунок та 2 Òб Ð´Ð»Ñ Ñ…Ð¾Ñтинґу фотографій менше ніж за $2 на міÑÑць! + +/index.bml.promo.paid_express=МожливіÑÑ‚ÑŒ вклинитиÑÑŒ під Ñ‡Ð°Ñ Ð·Ð½Ð°Ñ‡Ð½Ð¾Ð³Ð¾ Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ + +/index.bml.promo.plus.bonus1=+ юзерпики + +/index.bml.promo.plus.bonus2=+ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/index.bml.promo.plus.bonus3=+ безкоштовно! + +/index.bml.promo.plus.button=Розширений рахунок + +/index.bml.promo.plus.head=Покращіть Ñвій LJ + +/index.bml.promo.plus.question=Зацікавило? + +/index.bml.promo.pop_interest.checkit=Інші популÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/index.bml.promo.pop_interest.head=ПопулÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/index.bml.promo.pop_interest.interests<< +music (музика) +movies (фільми) +reading (читаннÑ) +writing (пиÑаннÑ) +friends (друзі) +. + +/index.bml.promo.pop_interest.text1=ÐайпопулÑрніші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñƒ LiveJournal це + +/index.bml.promo.userpic=Розширений рахунок дає 15 юзерпик! + +/index.bml.promo.volunteer.checkit=ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ + +/index.bml.promo.volunteer.head=Чи знаєте ви? + +/index.bml.promo.volunteer.text1=LiveJournal підтримуєтьÑÑ Ð²Ð¾Ð»Ð¾Ð½Ñ‚ÐµÑ€Ð°Ð¼Ð¸ (це такі ж кориÑтувачі Ñк Ñ– ви) + +/index.bml.promo.volunteer.text2=Бажаєте Ñтати волонтером? + +/index.bml.promo.volunteer.text3=  Це новий доÑвід
      Ðові друзі
      Краща Ñ€ÐµÐ¿ÑƒÑ‚Ð°Ñ†Ñ–Ñ Ð² LJ + +/index.bml.sidebar.sponcomm.content1= + +/index.bml.sidebar.sponcomm.head.multiple=Підтримувані
    Ñпільноти + +/index.bml.sidebar.sponcomm.head.single=Підтримувана
    Ñпільнота + +/index.bml.sidebar.spotlight.content<< +
    + [info]frankthecomic
    + Цап Френк тепер зірка влаÑних комікÑів, Ñкі виготовлÑÑ” Райан ЕÑтрада (Ryan Estrada) +
    + +
    + [info]ohnotheydidnt
    + Обговоріть оÑтанні плітки про знаменитоÑтей +
    + +
    + [info]cooking
    + ОбмінюйтеÑÑ Ñ€ÐµÑ†ÐµÐ¿Ñ‚Ð°Ð¼Ð¸ та покращуйте доÑвід Ð¿Ñ€Ð¸Ð³Ð¾Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ—Ð¶Ñ– +
    +. + +/index.bml.sidebar.spotlight.content1<< +
    +
    + Вчимо німецьку +
    + +
    +
    + Вчимо Ñ–ÑпанÑьку +
    + +
    +
    + Пишемо твори з 6 Ñлів +
    +. + +/index.bml.sidebar.spotlight.head=Родзинки LiveJournal + +/index.bml.sidebar.spotlight.suggest=Запропонуйте родзинку + +/index.bml.sidebar.stats.day=запиÑів за оÑтанній день + +/index.bml.sidebar.stats.head=СтатиÑтика LiveJournal + +/index.bml.sidebar.stats.sincestart=журналів та Ñпільнот Ñтворено з 1999 року + +/index.bml.widget.publicstats.day=запиÑи оÑтаннього Ð´Ð½Ñ + +/index.bml.widget.publicstats.latestposts=ОÑтанні запиÑи + +/index.bml.widget.publicstats.sincestart=журнали Ñ– Ñпільноти, Ñтворені піÑÐ»Ñ 1999 + +/index.bml.windowtitle=[[sitename]] - Заведіть безкоштовний блоґ (журнал) зараз + +/interests.bml.add.added.head=Додано! + +/interests.bml.add.added.text=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ додано до ÑпиÑку. + +/interests.bml.add.btn.text=Додати [[interest]] + +/interests.bml.add.confirm.head=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ + +/interests.bml.add.confirm.text=Щоб додати [[interest]] Ñк зацікавленнÑ, натиÑніть кнопку нижче. + +/interests.bml.add.toomany.head=Вибачте... + +/interests.bml.add.toomany.text=Ви вже внеÑли [[maxinterests]] до ÑпиÑку. + +/interests.bml.addint2=Якщо ви також цікавитиÑÑŒ цим Ñ– бажаєте потрапити в цей ÑпиÑок, натиÑніть Ñюди. + +/interests.bml.btn.switch=Перемикач + +/interests.bml.communities.head=Відповідні Ñпільноти + +/interests.bml.communities.header=Спільноти, у Ñких цікавлÑÑ‚ÑŒÑÑ: "[[interest]]" + +/interests.bml.communities.text=ÐаÑтупні Ñпільноти також цікавлÑÑ‚ÑŒÑÑ Ñ‚ÐµÐ¼Ð¾ÑŽ "[[interest]]". + +/interests.bml.count=КількіÑÑ‚ÑŒ + +/interests.bml.enmasse.body.other=Ðижче наведено Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ [[user]]. ПоÑтавте позначки порÑд з тими зацікавленнÑми, Ñкі ви бажаєте додати до Ñвоїх, та зніміть позначки порÑд з тими, Ñкі ви бажаєте вилучити. Коли закінчите, натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.body.other_authas=Ðижче наведено Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ [[user]]. ПоÑтавте позначки порÑд з тими зацікавленнÑми, що ви бажаєте додати до зацікавлень [[target]], та зніміть позначки порÑд з тими, Ñкі ви бажаєте вилучити. Коли закінчите, натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.body.you=Зніміть позначки порÑд з тими зацікавленнÑми, Ñкі ви бажаєте вилучити. Коли закінчите, натиÑніть "Зберегти зміни". + +/interests.bml.enmasse.btn=Показати ÑпиÑок + +/interests.bml.enmasse.header=Додати/вилучити Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.enmasse.intro=Змінити ваші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð° підÑтаві цих: + +/interests.bml.error.add.mustlogin=Ви не увійшли до LiveJournal, щоб додавати Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð°ÐºÐ¸Ð¼ чином. + +/interests.bml.error.enmasse.noaccess=Вам не доÑтупний журнал [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ було знайдено. + +/interests.bml.error.nointerests=Обраний кориÑтувач не Ñ–Ñнує або не визначив жодного зацікавленнÑ. + +/interests.bml.findsim.searchwait=Зверніть увагу, будь лаÑка: пошук триватиме декілька Ñекунд. Будьте терплÑчі. + +/interests.bml.findsim_do.account.notallowed=Вибачте, тип вашого рахунку не дозволÑÑ” вам кориÑтуватиÑÑ Ñ†Ð¸Ð¼ заÑобом. + +/interests.bml.findsim_do.magic=Чарівний
    Ñ–Ð½Ð´ÐµÐºÑ + +/interests.bml.findsim_do.magic.head=Чарівний індекÑ? + +/interests.bml.findsim_do.magic.text=Ð”Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ кориÑтувача вираховуєтьÑÑ Ñ‡Ð°Ñ€Ñ–Ð²Ð½Ð¸Ð¹ індекÑ, утворений з двох параметрів: загальна кількіÑÑ‚ÑŒ зацікавлень та кілька додаткових очок за незвичайні зацікавленнÑ. + +/interests.bml.findsim_do.nomatch.head=Збігів немає + +/interests.bml.findsim_do.nomatch.text=Жоден кориÑтувач не Ñхожий на [[user]]. + +/interests.bml.findsim_do.notdefined=КориÑтувач [[user]] не визначив інтереÑи. + +/interests.bml.findsim_do.similar.head=Схожі кориÑтувачі + +/interests.bml.findsim_do.similar.text=ÐаÑтупні кориÑтувачі повÑзані з [[user]] + +/interests.bml.finished.about=Коли закінчите, натиÑніть кнопку "Зберегти зміни", розташованну нижче: + +/interests.bml.finished.header=Готово? + +/interests.bml.finished.save_button=Зберегти зміни + +/interests.bml.interest=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.interested.btn.find=Знайти + +/interests.bml.interested.in=Знайти людей та Ñпільноти, що цікавлÑÑ‚ÑŒÑÑ: + +/interests.bml.interests.findsim=Знайти кориÑтувачів із зацікавленнÑми, подібними до: + +/interests.bml.interests.head=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.interests.text=ОÑÑŒ деÑкі речі, Ñкі ви можете зробити з зацікавленнÑми. + +/interests.bml.interests.viewpop=ПереглÑнути популÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.login.enterinfo=Введіть ваші ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль щоб редагувати інтереÑи. + +/interests.bml.login.proceed=Продовжити... + +/interests.bml.matches2=[[num]] [[?num|збіг|збіги|збігів]]: + +/interests.bml.morestuff=Більше прикольних речей можна знайти на Ñторінці зацікавлень. + +/interests.bml.morestuff2=Більше прикольних речей можна знайти на Ñторінці зацікавлень. + +/interests.bml.nointerests.text2=Ðе вказали жодних зацікавлень? Додайте Ñ—Ñ… на Ñторінці Зміна профілю. + +/interests.bml.popular.disabled=Вибачте, можливіÑÑ‚ÑŒ переглÑнути популÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ” недоÑтупною. + +/interests.bml.popular.head=ПопулÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.popular.text=ÐаÑтупні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ” вельми популÑрними. + +/interests.bml.popular.textmode=ДивитиÑÑ Ñƒ виглÑді таблиці. + +/interests.bml.results.added=Виділені Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ð½Ð¾ до вашого ÑпиÑку зацікавлень. + +/interests.bml.results.both=Виділені Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ð½Ð¾ до вашого ÑпиÑку зацікавлень. ЗацікавленнÑ, з Ñких було знÑто виділеннÑ, видалено із вашого ÑпиÑку зацікавлень. + +/interests.bml.results.deleted=ЗацікавленнÑ, з Ñких було знÑто виділеннÑ, видалено із вашого ÑпиÑку зацікавлень. + +/interests.bml.results.del_and_toomany<< +ЗацікавленнÑ, з Ñких було знÑто виділеннÑ, видалено із вашого ÑпиÑку зацікавлень. Однак ви виділили занадто багато зацікавлень Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ. Загалом ви можете мати не більше [[intcount]] зацікавлень. Жодне із виділених зацікавлень не додано до вашого ÑпиÑку зацікавлень. Ви можете повернутиÑÑŒ назад Ñ– вибрати меншу кількіÑÑ‚ÑŒ зацікавлень + +. + +/interests.bml.results.goback2=Ви можете бажати повернутиÑÑ Ð½Ð°Ð·Ð°Ð´ до Ñторінки даних [[user]], Ñку до цього переглÑдали. + +/interests.bml.results.header=Результати + +/interests.bml.results.message2=ДивітьÑÑ Ñвою оновлену Ñторінку даних. + +/interests.bml.results.nothing=Ви не зробили жодної зміни. + +/interests.bml.results.toomany=Ви виділили занадто багато зацікавлень Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ. Загалом ви можете мати не більше [[intcount]] зацікавлень. Жодне із виділених зацікавлень не додано до вашого ÑпиÑку зацікавлень. Ви можете повернутиÑÑŒ назад Ñ– вибрати меншу кількіÑÑ‚ÑŒ зацікавлень. + +/interests.bml.title=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/interests.bml.toomany.body=Ð’Ñього [[intcount]] оÑіб та/або Ñпільнот вказало це зацікавленнÑ. СпиÑок не буде показано. + +/interests.bml.toomany.head=Багато значень + +/interests.bml.users.head=Зацікавлені кориÑтувачі + +/interests.bml.users.header=КориÑтувачі, Ñкі цікавлÑÑ‚ÑŒÑÑ: "[[interest]]" + +/interests.bml.users.text=ÐаÑтупні кориÑтувачі цікавлÑÑ‚ÑŒÑÑ Ñ‚ÐµÐ¼Ð¾ÑŽ "[[interest]]". + +/invite/index.bml.code=Код + +/invite/index.bml.error=Помилка + +/invite/index.bml.genmore=Генерувати код(и) + +/invite/index.bml.how_detail=Ð’ залежноÑÑ‚Ñ– від деÑких факторів, кориÑтувачі можуть запроÑити певну кількіÑÑ‚ÑŒ людей Ð´Ð»Ñ ÑƒÑ‡Ð°ÑÑ‚Ñ– у LiveJournal. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб запроÑити когоÑÑŒ, вам потрібно згенерувати код-Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ñ‚Ð° віддати його майбутьному кориÑтувачу. + +/invite/index.bml.how_header=Як це працює? + +/invite/index.bml.invite_header=ЗапрошеннÑ? + +/invite/index.bml.none=Ðемає + +/invite/index.bml.redeemed=ВикориÑтав + +/invite/index.bml.title=ЗапроÑити інших до LiveJournal... + +/invite/index.bml.unused=Ðе викориÑтан + +/invite/index.bml.use=викориÑтати + +/invite/index.bml.why_codes=Щоб підтримувати Ñпільноту, контролювати його розвиток та запобігати неправильному викориÑтанню, на даний момент Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ вам потрібно отримати Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð²Ñ–Ð´ Ñ–Ñнуючого кориÑтувача або купити рахунок. Це правило введено Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб покращити умови Ð´Ð»Ñ Ñ–Ñнуючих авторів за рахунок незручноÑÑ‚Ñ– Ñку відчувають нові кориÑтувачі. + +/legal/dmca.bml.title=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ авторÑькі права (DMCA) + +/legal/index.bml.about<< +LiveJournal приÑвÑчений наданню Ñтабыльного та значущого доÑвіду учаÑникам вÑÑ–Ñ… походжень та націй, Ñ–, щоб надати це, ми виклали декілька правил. +Ðаші документи, предÑтавлені тут, міÑÑ‚ÑÑ‚ÑŒ помірковані вимоги та інформацію ÑтоÑовно ÑтоÑовно того, Ñк ми робитиме вÑе, що від Ð½Ð°Ñ Ð·Ð°Ð»ÐµÐ¶Ñ–Ñ‚ÑŒ, щоб Ñлужити вам, Ñ– Ñк ми очікуємо, що учаÑники поводитимутьÑÑ Ð· нами та іншими. LiveJournal працює найкраще, коли люди дотримуютьÑÑ Ñ†Ð¸Ñ… правил. ОÑÑŒ деÑкі важливі з них, що варто запам'Ñтати: +
      +
    • Ðе турбуйте, не ображайте та не погрожуйте іншим.
    • +
    • Ðе наноÑÑ–Ñ‚ÑŒ шкоду неповнолітнім будь-Ñким чином.
    • +
    • Ðе Ñпамте на Ñайті або будь-Ñкому рахунку Ñайту.
    • +
    • Ðе публікуйте без дозволу зміÑÑ‚, захищений авторÑьким правом.
    • +
    • Ðе втручайтеÑÑŒ у приватніÑÑ‚ÑŒ інших.
    • +
    • Ðе порушуйте закон СШРабо ваші міÑцеві закони будь-Ñким чином.
    • +
    +Повний ÑпиÑок правил та політик можна знайти нижче: +. + +/legal/index.bml.about.header=Короткий оглÑд + +/legal/index.bml.docs.dmca.about=Закон "Про захиÑÑ‚ авторÑьких прав у цифрову епоху" (DMCA) опиÑує ÑпоÑіб, у Ñкий провайдери поÑлуг мають реагувати на Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ñьких прав. Ðаша Ñторінка DMCA опиÑує, Ñк ви можете повідомлÑти наÑ, що кориÑтувач нашого ÑервіÑу порушує ваші авторÑькі права. + +/legal/index.bml.docs.header=Документи + +/legal/index.bml.docs.privacy.about2=Політика конфіденційноÑÑ‚Ñ– визначає, Ñку інформацію ми збираємо від наших учаÑників, та поÑÑнює, Ñк ми викориÑтовуємо цю інформацію. Ð¦Ñ Ñторінка також опиÑує, Ñк ми викориÑтовуємо Ðкт "Про захиÑÑ‚ прав дитини в інтернеті" (COPPA), та нашу політику ÑтоÑовно дітей на нашому Ñайті. + +/legal/index.bml.docs.tos.about<< +Умови викориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡Ð°ÑŽÑ‚ÑŒ нашу політику кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлугами, а також загальні умови учаÑÑ‚Ñ–. УчаÑÑ‚ÑŒ та/або кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑиÑтемою підтверджує угоду дотримуватиÑÑ Ñ†Ñ–Ñ… +та вÑÑ–Ñ… іншіх узгоджених умов. +. + +/legal/index.bml.title=Правова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/legal/privacy.bml.title=Політика конфіденційноÑÑ‚Ñ– + +/legal/tos.bml.title=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +/login.bml.bindip.label=Прив'Ñзати до IP-адреÑи + +/login.bml.bindip.no=ÐÑ– (працює з уÑіма провайдерами) + +/login.bml.bindip.yes=Так (безпечніше) + +/login.bml.createaccount.button=Створити рахунок + +/login.bml.createaccount.header=Ви не учаÑник LiveJournal? + +/login.bml.createaccount.tour=ОглÑдовий тур + +/login.bml.createaccount.whylogin.benefit1=Читати запиÑи "тільки-длÑ-друзів", що адреÑовані вам. + +/login.bml.createaccount.whylogin.benefit2=Залишати коментарі у будь-Ñких журналах та Ñпільнотах. + +/login.bml.createaccount.whylogin.benefit3=Сворювати запиÑи у Ñвоєму влаÑному журналі. + +/login.bml.createaccount.whylogin.benefit4=Додавати будь-Ñкий журнал чи Ñпільноту до Ñтрічки друзів. + +/login.bml.createaccount.whylogin.benefit5=Отримати можливоÑÑ‚Ñ–, що доÑтупні лише зареєÑтрованим кориÑтувачам. + +/login.bml.error.notuser=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача не знайдено. Бажаєте Ñтворити новий рахунок з цим іменем? + +/login.bml.expire.btn.neverexpire=Змінити режим на "ÐІКОЛИ" + +/login.bml.expire.btn.sessiononly=Змінити режим на "ОДÐРСЕСІЯ" + +/login.bml.expire.neverexpire.text=Термін вашого входу до LiveJournal ніколи не завершитьÑÑ, тому Ñкщо ви працюєте на публічному комп'ютері, в школі, в бібліотеці або в іншому міÑці, де люди можуть незабаром ÑкориÑтатиÑÑ Ñ†Ð¸Ð¼ комп'ютером, то переконайтеÑÑ, що ви вийшли з LiveJournal по закінченні роботи! Ðбо змініть режим входу, щоб термін входу завершувавÑÑ, коли ви закриваєте Ñвій браузер: + +/login.bml.expire.sessiononly.text=Термін вашого входу до Ñайту закінчитьÑÑ, коли ви закриєте Ñвій браузер. Якщо це ваш влаÑний комп'ютер Ñ– ви Ñ” єдиним кориÑтувачем, ви можете вÑтановити термін входу до Ñайту таким, що ніколи не закінчуєтьÑÑ. + +/login.bml.links.head=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/login.bml.links.text=Ð’ майбутньому Ñ†Ñ Ñторінка міÑтитиме вÑÑ– короткі поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ‚Ð° пов'Ñзану інформацію, але вже зараз Ñ” кілька міÑць що ви захочете відвідати: + +/login.bml.loggedin.head2=З поверненнÑм до [[sitename]]! + +/login.bml.loggedin.suggest1=Чи знаєте ви, що відтепер можна легко додати фотографію? + +/login.bml.loggedin.suggest2=ДивітьÑÑ Ð¾Ñтанні зміни в журналах ваших друзів. + +/login.bml.loggedin.suggest4=Ðалаштуйте [[siteabbrev]] на влаÑний Ñмак. + +/login.bml.loggedin.suggesthead1=Поновіть Ñвій журнал + +/login.bml.loggedin.suggesthead2=Читайте Ñтрічку друзів + +/login.bml.loggedin.suggesthead3=Мій [[siteabbrev]] + +/login.bml.loggedin.text2=Ви увійшли Ñк [[username]]. ÐаÑолоджуйтеÑÑ! Рзараз кілька пропозицій... + +/login.bml.login.autologin=Ðвтоматично входити з цього комп'ютера + +/login.bml.login.bindcookie=Прив'Ñзати до IP-адреÑи + +/login.bml.login.bindcookie.learnmore=ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про ці опції + +/login.bml.login.btn.changeopts=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/login.bml.login.btn.create=Створити рахунок + +/login.bml.login.btn.login=Увійти... + +/login.bml.login.btn.save=Зберегти + +/login.bml.login.changelog=Змінити опції входу + +/login.bml.login.expiration=ЗавершеннÑ: + +/login.bml.login.forget2=Загубили пароль? + +/login.bml.login.head=Увійти + +/login.bml.login.never=Ðіколи + +/login.bml.login.openid=Увійти з Open ID + +/login.bml.login.optionssaved=Опції входу збережені. + +/login.bml.login.otheropts=Інші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/login.bml.login.password=Пароль: + +/login.bml.login.remember=Запам'Ñтати мене + +/login.bml.login.secure=Безпечно + +/login.bml.login.standard=Стандартно + +/login.bml.login.text1=Щоб увійти, введіть Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль у формі нижче. Ðові кориÑтувачі: Створіть влаÑний рахунок + +/login.bml.login.text2=Ви також можете зазначити, коли ви вийдете з Ñайта. За замовчуваннÑм, ÑеÑÑ–Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡ÑƒÑ”Ñ‚ÑŒÑÑ, коли ви закриваєте Ñвій браузер, що Ñ” найкращим варіантом Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… комп’ютерів. Проте Ñкщо ви Ñ” єдиним кориÑтувачем комп’ютера, то можете обрати варіант - залишатиÑÑ Ð½Ð° Ñайті завжди. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб отримати більше інформації, переглÑньте Які Ñ” варіанти входу? + +/login.bml.login.text3=[[username]], тепер ви увійшли до [[sitename]]. Мандруйте Ñторінками Ñайта, викориÑтовуючи нашу мапу. + +/login.bml.login.text4=ПіÑÐ»Ñ Ð²Ñ…Ð¾Ð´Ñƒ до Ñвого рахунку [[sitename]] ви зможете: + +/login.bml.login.text5=Ви можете вільно Ñтворити рахунок [[sitename]]. + +/login.bml.login.text6=Увійти до Ñвого рахунку [[sitename]] : + +/login.bml.login.text7=РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð² [[sitename]] безкоштовна. + +/login.bml.login.title=Вхід + +/login.bml.login.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/login.bml.login.welcome=Увійти до [[sitename]] + +/login.bml.login.whenbrowsercloses=Коли браузер буде закрито + +/login.bml.logout.btn=Вийти + +/login.bml.logout.btn1=Вийти + +/login.bml.logout.loggedout=Ви вийшли + +/login.bml.title=Вхід + +/login.bml.whylogin.benefit10=Додавати журнали та Ñпільноти до Ñвоєї Ñтрічки друзів. + +/login.bml.whylogin.benefit11=Отримати доÑтуп до можливоÑтей, недоÑтупних Ð´Ð»Ñ Ð½ÐµÐ·Ð°Ñ€ÐµÑ”Ñтрованих кориÑтувачів. + +/login.bml.whylogin.benefit4=Читати запиÑи тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð², адреÑовані вам. + +/login.bml.whylogin.benefit5=Залишати коментарі в будь-Ñких журналах чи Ñпільнотах. + +/login.bml.whylogin.benefit6=Додавати будь-Ñкі журнали чи Ñпільноти до Ñвоєї Ñтрічки друзів. + +/login.bml.whylogin.benefit7=Мати доÑтуп до функцій, що доÑтупні тільки піÑÐ»Ñ Ð²Ñ…Ð¾Ð´Ñƒ. + +/login.bml.whylogin.benefit8=Читати запиÑи "Лише Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²". + +/login.bml.whylogin.benefit9=Залишати коментарі у журналах Ñ– Ñпільнотах. + +/login.bml.whylogin.head=Ðавіщо входити? + +/logout.bml.already.head=УÑпішно вийшли + +/logout.bml.already.text=Ви уÑпішно вийшли. + +/logout.bml.killall.btn=Завершити вÑÑ– мої ÑеанÑи + +/logout.bml.killall.head=Інші ÑеанÑи + +/logout.bml.killall.text=Ви маєте інші активні ÑеанÑи входу до LiveJournal. Чи ви хотіли б завершити вÑÑ– Ñвої ÑеанÑи, а не тільки цей? (ДивітьÑÑ Ñ†Ðµ поширене питаннÑ, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.) + +/logout.bml.loggedout.already=УÑпішно вийшли. + +/logout.bml.loggedout.head=Вийшли + +/logout.bml.loggedout.killedall=Ð’ÑÑ– ваші ÑеанÑи було завершено. + +/logout.bml.loggedout.text=Ви вийшли. + +/logout.bml.logout.btn=Вийти + +/logout.bml.logout.head=Вийти? + +/logout.bml.logout.text=ÐатиÑніть кнопку, щоб вийти. + +/logout.bml.title=Вихід + +/logout.bml.title.loggedout=Вихід здійÑнено уÑпішно! + +/logout.bml.widget.publicstats.day=запиÑи попереднього Ð´Ð½Ñ + +/logout.bml.widget.publicstats.latestposts=ОÑтанні запиÑи + +/logout.bml.widget.publicstats.sincestart=журнали Ñ– Ñпільноти, Ñтворені піÑÐ»Ñ 1999 + +/lostinfo.bml.btn.proceed=Продовжити + +/lostinfo.bml.enter_email=Введіть вашу e-mail адреÑу: + +/lostinfo.bml.enter_email_optional=E-mail адреÑа (необов'Ñзково) + +/lostinfo.bml.enter_username=Введіть Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/lostinfo.bml.error.commnopassword=Рахунок, Ð´Ð»Ñ Ñкого Ви намагєтеÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ пароль, Ñ” Ñпільнотою. Цей тип рахунку не має паролÑ, що можна було б отримати. Ð’Ñе ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотою може бути здійÑнено через вхід до LiveJournal Ñк наглÑдача Ñпільноти. + +/lostinfo.bml.error.no_email=Ви муÑите ввеÑти e-mail адреÑу, щоб відновити Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/lostinfo.bml.error.purged=Ðеможливо отримати пароль Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ рахунку піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк він був знищений. + +/lostinfo.bml.error.renamed=Ðеможливо отримати пароль Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ рахунку. + +/lostinfo.bml.error.syndicated=Рахунок, Ð´Ð»Ñ Ñкого Ви намагєтеÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ пароль, Ñ” рахунком, що траÑлюєтьÑÑ. Цей тип рахунку не має паролÑ, що можна було б отримати. + +/lostinfo.bml.error.sysbanned=Вашому рахунку не дозволено надÑилати паролі поштою. + +/lostinfo.bml.error.toofrequent=Ви намагаєтеÑÑ Ð½Ð°Ð´Ñ–Ñлати забагато лиÑтів одразу. Ви можете запроÑити три лиÑта з втраченою інформацією протÑгом двадцÑти чотирьох годин. + +/lostinfo.bml.lostpassword.text=Введіть Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та email-адреÑу, що пов'Ñзана з вашим рахунком, Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ паролю. Якщо ви залишите поле Ð´Ð»Ñ email-адреÑи порожнім, пароль буде надіÑлано до вашої поточної адреÑи. + +/lostinfo.bml.lostpassword.title=Загубили Ñвій пароль? + +/lostinfo.bml.lostusername.text=Якщо ви загубили Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, введіть вашу e-mail адреÑу, Ñ– ми надішлемо вам ваше ім'Ñ. + +/lostinfo.bml.lostusername.title=Загубили Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача? + +/lostinfo.bml.title=Загублені дані + +/lostinfo_do.bml.error.no_usernames_for_email=Ðема кориÑтувача з такою адреÑою: [[address]] . + +/lostinfo_do.bml.error1.text=Ви ніколи не викориÑтовували цю адреÑу з цим рахунком, або ніколи Ñ—Ñ— не підтверджували. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð³ÐµÐ½ÐµÑ€Ð¾Ð²Ð°Ð½Ðµ автоматично. Ðе потрібно на нього відповідати *** + +Це замовлений Вами пароль Ð´Ð»Ñ [[sitename]]. +Ðижче Ваші ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, пароль, та e-mail, Ñкі Ви вказали при реєÑтрації. + + Ім'Ñ : [[username]] + Пароль : [[password]] + ÐдреÑа : [[emailadr]] + + + +. + +/lostinfo_do.bml.lostpasswordmail.part2=Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ ходіть Ñюди: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ»Ð° запитана на Ñайті з адреÑи [[remoteip]]. + +Якщо Ви не запитували надÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð’Ð°Ð¼ паролÑ, не паникуйте. Ð’ решті решт, оÑобою, що бачіть цей лиÑÑ‚, Ñ” Ви, а не ÑкаÑÑŒ інша оÑоба. Можливо, що кориÑтувач, що зробив цей запит, помилÑвÑÑ Ñ– вважав, що це він чи вона керує цим ім'Ñм кориÑтувача. Також можливо, що хтоÑÑŒ зробив похибку в імені чи e-mail адреÑÑ–. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Якщо ви дійÑно вважаєте, що ваш рахунок незахищений, прочитайте http://www.livejournal.com/support/faqbrowse.bml?faqid=117 щоб отримати деÑку інформацію Ñк зміцнити його захиÑÑ‚. + +/lostinfo_do.bml.lostpasswordmail.part5<< +КориÑні поÑиланнÑ: + + Ваш LiveJournal : + [[journalurl]] + + ÐапиÑати до Вашого журналу: + [[updateurl]] + +З найкращими побажаннÑми, +Команда LiveJournal + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.reset<< +Ðа Ñторінці [[lostinfolink]] було зроблено запит на зміну вашого паролю до рахунку [[sitename]], що пов'Ñзаний з цією email-адреÑою. + +Дані рахунку: + + Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[username]] + Email-адреÑа: [[emailadr]] + +Перейдіть за цим поÑиланнÑм Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½Ð¸ вашого паролю: + + [[resetlink]] + +Якщо ви не робили такого запиту, будь лаÑка, проігноруйте цей лиÑÑ‚, Ñ– ваш пароль залишитьÑÑ Ñтарим. + +З повагою, +команда [[sitename]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Загублений пароль + +/lostinfo_do.bml.password_mailed.text=УÑпішно. ІнÑтрукції Ð´Ð»Ñ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ паролю відіÑлані на ваш email. + +/lostinfo_do.bml.password_mailed.title=Пароль надіÑлано! + +/lostinfo_do.bml.title=Загублені дані + +/lostinfo_do.bml.username_mailed.text=УÑпішно. Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача надіÑлано. + +/lostinfo_do.bml.username_mailed.title=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача надіÑлано! + +/manage/comments/index.bml.commentnotify=Отримувати поштою копії коментарів, що ви зробили + +/manage/comments/index.bml.commentnotify.text=Ви можете отримувати поштою копії коментарів, що ви зробили під Ñвоїм іменем. Ви не отримуватимете копії будь-Ñких напиÑаних вами анонімних коментарів. + +/manage/comments/index.bml.disablecomment1=Якщо ви забороните коментуваннÑ, вÑÑ– Ñтарі коментарі у вашому журналі будуть приховані. Вони з'ÑвлÑÑ‚ÑŒÑÑ Ð·Ð½Ð¾Ð²Ñƒ Ñкщо ви дозволите коментуваннÑ. + +/manage/comments/index.bml.disablecomment1.comm=Якщо ви вимкнули можливіÑÑ‚ÑŒ коментуваннÑ, уÑÑ– минулі коментарі у Ñпільноті будуть приховані. Вони з'ÑвлÑÑ‚ÑŒÑÑ Ð·Ð½Ð¾Ð²Ñƒ, коли ви увімкнете можливіÑÑ‚ÑŒ коментуваннÑ. + +/manage/comments/index.bml.disablecomment2.1=Якщо ви хочете заборонити ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ окремих Ñвоїх запиÑів, змініть Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ запиÑу його "Параметри коментарів". + +/manage/comments/index.bml.emailnotify=Отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ чужі коментарі. + +/manage/comments/index.bml.enablecommenting=Дозволити коментувати + +/manage/comments/index.bml.finished.save_button=Зберегти зміни + +/manage/comments/index.bml.fn.commentnotify=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ коментарі + +/manage/comments/index.bml.fn.emailformat=Формат email + +/manage/comments/index.bml.fn.emailnotify=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑ‚Ð¾ÑŽ + +/manage/comments/index.bml.fn.enablecomments=Ð”Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð² + +/manage/comments/index.bml.fn.iplog=Ð—Ð°Ð¿Ð¸Ñ Ð°Ð´Ñ€ÐµÑи IP + +/manage/comments/index.bml.fn.screening=ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð² + +/manage/comments/index.bml.fn.unban=Розблокувати кориÑтувачів + +/manage/comments/index.bml.formathtml=Формат HTML + +/manage/comments/index.bml.formatplain=Звичайний текÑÑ‚ + +/manage/comments/index.bml.intro=Визначте нижче Ñвої параметри коментуваннÑ. + +/manage/comments/index.bml.logip=ЗапиÑувати IP у відповідÑÑ… від + +/manage/comments/index.bml.logip.text=Ви можете вÑтановити цей параметр Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу IP Ð°Ð´Ñ€ÐµÑ Ñ‚Ð¸Ñ…, кто коментує ваш журнал. + +/manage/comments/index.bml.logip.text.comm=Ви можете викориÑтовувати цю опцію, щоб запиÑувати IP адреÑи тих, хто лишає коментарі у Ñпільноті. + +/manage/comments/index.bml.screen=Приховувати коментарі від + +/manage/comments/index.bml.screen.text=ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” вам переглÑнути коментарі перед тим, Ñк інші зможуть Ñ—Ñ… бачити. + +/manage/comments/index.bml.section.banned=Заблоковані кориÑтувачі + +/manage/comments/index.bml.section.commcomments=Коментарі у вашій Ñпільноті + +/manage/comments/index.bml.section.journalcomments=Коментарі у вашому журналі + +/manage/comments/index.bml.section.makecomments=Коментарі, що ви зробили + +/manage/comments/index.bml.security.visibility.anon=Ðнонімних допиÑувачів + +/manage/comments/index.bml.security.visibility.everybody=Будь-кому + +/manage/comments/index.bml.security.visibility.everyone=Будь-кого + +/manage/comments/index.bml.security.visibility.friends=Тільки друзÑм + +/manage/comments/index.bml.security.visibility.members=Лише Ð´Ð»Ñ Ñ‡Ð»ÐµÐ½Ñ–Ð² + +/manage/comments/index.bml.security.visibility.nobody=Ðікого + +/manage/comments/index.bml.security.visibility.noone=Ðікого + +/manage/comments/index.bml.security.visibility.notfriends=Будь-кого, хто не Ñ” в моєму ÑпиÑку друзів + +/manage/comments/index.bml.security.visibility.notmember=Будь-кого, хто не Ñ” учаÑником + +/manage/comments/index.bml.security.visibility.regusers=ЗареєÑтрованим кориÑтувачам + +/manage/comments/index.bml.success.header=УÑпішно! + +/manage/comments/index.bml.success.text=Ваші параметри ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ оновлено. + +/manage/comments/index.bml.title=Параметри ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/comments/index.bml.title2=Керувати налаштуваннÑми коментарів + +/manage/comments/index.bml.unban=Ви заблокували Ð´Ð»Ñ Ñ†Ð¸Ñ… кориÑтувачів можливіÑÑ‚ÑŒ коментувати у вашому журналі. ÐатиÑніть на кнопку поруч з іменем Ð´Ð»Ñ Ñ€Ð¾Ð·Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ. + +/manage/comments/index.bml.unban.comm=Ви заборонили цим кориÑтувачам пиÑати до Ñпільноти. Зніміть позначку навпроти імені кориÑтувача щоб знÑти заборону. + +/manage/emailpost.bml.addresses.header=Дозволені адреÑи відправників + +/manage/emailpost.bml.addresses.table.address=ÐдреÑа + +/manage/emailpost.bml.addresses.table.errors=ВідправлÑти помилки? + +/manage/emailpost.bml.addresses.text=Тільки адреÑи, що перелічені нижче, мають дозвіл Ð´Ð»Ñ Ð½Ð°Ð¿Ð¸ÑÐ°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів у вашому журналі через email-шлюз. Якщо не вказано жодної адреÑи, напиÑÐ°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів через email-шлюз буде вимкнено Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку. У разі поÑви будь-Ñких помилок, вони будуть надÑилатиÑÑ Ð´Ð¾ відзначених адреÑ. + +/manage/emailpost.bml.error.invalidemail=Ðевірна email-адреÑа: [[email]] + +/manage/emailpost.bml.error.invalidimagesize=Розмір Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ бути [[size]] або менше, щоб не з'ÑвлÑвÑÑ lj-cut. + +/manage/emailpost.bml.error.invalidpin=Ваш ПІÐ-код може ÑкладатиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ з був або цифр, а також повинен мати щонайменше [[num]] [[?num|Ñимвол|Ñимволи|Ñимволів]]. + +/manage/emailpost.bml.error.invalidpinaccount=Цей ПІÐ-код невірний. Ви повинні його змінити на щоÑÑŒ, що ÐЕ має Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ вашого рахунку [[sitename]]. + +/manage/emailpost.bml.error.notloggedin.header=Будь лаÑка, увійдіть! + +/manage/emailpost.bml.error.sitenotconfigured=Вибачте, цей Ñайт не підтримує напиÑÐ°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів до журналу через email. + +/manage/emailpost.bml.help.advanced.header=Розширене викориÑÑ‚Ð°Ð½Ð½Ñ + +/manage/emailpost.bml.help.advanced.pgp.body=Цей текÑÑ‚ повинен бути підпиÑаний моїм оÑобиÑтим ключем. + +/manage/emailpost.bml.help.advanced.pgp.header=ПідпиÑка Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ PGP/GPG + +/manage/emailpost.bml.help.advanced.pgp.text1=Якщо ви зазначити "[[pgp]]" заміÑÑ‚ÑŒ ПІÐ-коду, дозволені адреÑи відправника та збережений ПІÐ-код не будуть викориÑтовуватиÑÑ. Ваш лиÑÑ‚ буде вважатиÑÑ Ð´Ñ–Ð¹Ñним тільки Ñкщо він підпиÑаний вірним оÑобиÑтим PGP/GPG ключем. + +/manage/emailpost.bml.help.advanced.pgp.text2=Спочатку ви повинні завантажити Ñвій публічний ключ Ñюди. + +/manage/emailpost.bml.help.allowedsenderemail|notes=A made-up email address for users that haven't specified an allowed email address for email posts to be sent from. +/manage/emailpost.bml.help.allowedsenderemail=dozvolenyi_vidpravnyk@example.com + +/manage/emailpost.bml.help.body|notes=Example body text for the example email. +/manage/emailpost.bml.help.body=Це текÑÑ‚ мого запиÑу. + +/manage/emailpost.bml.help.body_images|notes=Example body text for the example picture email. +/manage/emailpost.bml.help.body_images=Це текÑÑ‚ мого запиÑу із долученими зображеннÑми. + +/manage/emailpost.bml.help.from|notes=The "email" variable will be replaced with the .help.allowedsenderemail string if the user has not specified an allowed sender. +/manage/emailpost.bml.help.from=Від: [[email]] + +/manage/emailpost.bml.help.header=Як це працює? + +/manage/emailpost.bml.help.headers.header=[[sitenameabbrev]]-заголовки та безпека + +/manage/emailpost.bml.help.headers.options.comments.example=("[[off]]" або "[[noemail]]") + +/manage/emailpost.bml.help.headers.options.header=Параметри журнального запиÑу + +/manage/emailpost.bml.help.headers.options.mood.example=щаÑливий + +/manage/emailpost.bml.help.headers.options.music.example=Брати Гадюкини: Ð’Ñьо чотко! + +/manage/emailpost.bml.help.headers.options.tags.example=музика, відпочинок, друзі + +/manage/emailpost.bml.help.headers.options.text=БільшіÑÑ‚ÑŒ оÑобливих можливоÑтей журналу може бути вказана за допомогою "lj-заголовків" в текÑÑ‚Ñ– вашого повідомленнÑ. LJ-заголовки повинні бути зверху Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° починатиÑÑ Ð· нового Ñ€Ñдка. Ð’ÑÑ– lj-заголовки Ñ” необов'Ñзковими Ñ– проÑто змінюють Ñтандартні параметри журналу. + +/manage/emailpost.bml.help.headers.options.userpic.example=ключові Ñлова юзерпики + +/manage/emailpost.bml.help.headers.security.friends.desc=Ð—Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ бачити тільки Ñ‚Ñ–, хто у вашому ÑпиÑку друзів. + +/manage/emailpost.bml.help.headers.security.group.desc=Це точна назва групи друзів. Тільки друзі з цієї групи зможуть побачити цей запиÑ. + +/manage/emailpost.bml.help.headers.security.group.example=Приклад: [[header]] мої друзі + +/manage/emailpost.bml.help.headers.security.group.word|notes=A single word that tells the person to put a friend group name in its place. +/manage/emailpost.bml.help.headers.security.group.word=групадрузів + +/manage/emailpost.bml.help.headers.security.header=Безпека журнального запиÑу + +/manage/emailpost.bml.help.headers.security.private.desc=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ´Ðµ приватним. + +/manage/emailpost.bml.help.headers.security.public.desc=Ð—Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ´Ðµ публічним. + +/manage/emailpost.bml.help.headers.security.text=Параметри безпеки вÑтановлюютьÑÑ lj-заголовком "[[header]]". Якщо буде вказано невідомий тип безпеки, то журнальний Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ´Ðµ приватним. Якщо тип безпеки не буде зазначено, то Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ´Ðµ мати Ñтандартний тип безпеки. + +/manage/emailpost.bml.help.images.gallery.example=веÑільні фотографії + +/manage/emailpost.bml.help.images.gallery.header=Вибір галереї + +/manage/emailpost.bml.help.images.gallery.text=Ви можете зазначити в Ñку галерею бажаєте поміÑтити долучені Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð° допомогою заголовка [[header]]. Якщо назву галереї не вказано, то буде викориÑтано галерею "[[name]]". Якщо у Ð²Ð°Ñ Ð¿Ñ–Ð·Ð½Ñ–ÑˆÐµ виникне Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñтити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð² іншу галерею, то вони вÑе рівно будуть відображатиÑÑ Ñƒ вашому журналі. + +/manage/emailpost.bml.help.images.header=Долучені Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/manage/emailpost.bml.help.images.layout.header=Зміна Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ + +/manage/emailpost.bml.help.images.layout.text1=Якщо ви долучаєте декілька зображень, то можете змінити Ñ—Ñ… Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñƒ Ñвоєму журналі за допомогою заголовка [[header]]. + +/manage/emailpost.bml.help.images.layout.text2=За замовчуваннÑм декілька зображень відображаютьÑÑ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾: + +/manage/emailpost.bml.help.images.layout.text3=Зараз Ñ–Ñнує тільки один інший параметр - "[[horizontal]]". + +/manage/emailpost.bml.help.images.ljcut.header=Поведінка lj-cut + +/manage/emailpost.bml.help.images.ljcut.text=За замовчуваннÑм, Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ [[ljcutsize]] або менші відображаютьÑÑ Ð±ÐµÐ· lj-cut. Ви можете змінити цю поведінку за допомогою заголовка [[header]]. Можливі параметри - "[[count]]" та "[[titles]]". КориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ "[[count]]" відобразить "( 3 images )" ( 3 зображеннÑ), Ñкщо ви долучаєте 3 зображеннÑ. Вказавши "[[titles]]" у заголовку [[header]] ви отримаєте окремі підпиÑані поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° кожне зображеннÑ. "( emo.jpg ) ( pict002.jpg ) ( Nastya.jpg )" + +/manage/emailpost.bml.help.images.security.header=Безпека Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/manage/emailpost.bml.help.images.security.text1=За замовчуваннÑм Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ бачити вÑÑ–. КориÑтуйтеÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð¼ [[header]], щоб змінити таку поведінку. Будь лаÑка, зауважте, що безпека зображень непов'Ñзана з безпекою журнальних запиÑів! Ðаприклад, ви можете мати приватний журнальний Ð·Ð°Ð¿Ð¸Ñ Ð· публічними зображеннÑми. Ð¦Ñ Ð¾ÑобливіÑÑ‚ÑŒ змінює тільки безпеку зображень, а не журнального запиÑу. + +/manage/emailpost.bml.help.images.security.text2=Можливі параметри - "[[option1]]", "[[option2]]" та "[[option3]]" + +/manage/emailpost.bml.help.images.size.header=Зміна розміру зображеннÑ, Ñкий відображаєтьÑÑ + +/manage/emailpost.bml.help.images.size.text1=Ви можете долучати Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑŒ-Ñкого розміру. МакÑимальний розмір - [[maxsize]]. Стандартний розмір - [[defaultsize]]. Ви можете вказати розмір за допомогою заголовка [[header]]. Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÑ– за [[ljcutsize]] будуть автоматично поміщені під lj-cut. + +/manage/emailpost.bml.help.images.size.text2=Можливі розміри - "[[size1]]", "[[size2]]" та "[[size3]]". + +/manage/emailpost.bml.help.images.text=Якщо ви маєте доÑтуп до [[scrapbook]] та доÑтатньо диÑкового проÑтору, вÑÑ– зображеннÑ, Ñкі ви долучаєте, будуть автоматично завантажені до вашого рахунку [[scrapbook]] Ñ– відображені у журнальному запиÑÑ–. Ð’ÑÑ– Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÑ– за [[dimensions]] будуть поміщені під lj-cut. КориÑтуючиÑÑŒ lj-заголовками ви зможете змінити виглÑд зображень у Ñвоєму журналі. + +/manage/emailpost.bml.help.manage.header=Зміна налаштувань мобільних повідомлень + +/manage/emailpost.bml.help.optionalfeatures.header=Додаткові можливоÑÑ‚Ñ– + +/manage/emailpost.bml.help.optionalfeatures.hyphens.header=ДефіÑи та Ñимволи підкреÑÐ»ÐµÐ½Ð½Ñ + +/manage/emailpost.bml.help.optionalfeatures.hyphens.text=Якщо ваш мобільний телефон не має кнопки із Ñимволом підкреÑленнÑ, ви можете замінити його дефіÑом у відповідному міÑці імені кориÑтувача чи Ñпільноти. ДефіÑи будуть автоматично змінені на Ñимволи підкреÑленнÑ. + +/manage/emailpost.bml.help.optionalfeatures.posttocommunity.header=ЗапиÑи до Ñпільноти + +/manage/emailpost.bml.help.optionalfeatures.posttocommunity.text=ПроÑто вкажіть назву Ñпільноти в email-адреÑÑ–. + +/manage/emailpost.bml.help.optionalfeatures.removetext.example=Цей текÑÑ‚ Ñ– вÑе що знаходитьÑÑ Ð½Ð¸Ð¶Ñ‡Ðµ буде виключено, включно з автоматичними підпиÑами, Ñкі додають безкоштовні email-ÑервіÑи.
    __________________________________________________
    Спробуйте нову, 17, верÑÑ–ÑŽ БЕЗКОШТОВÐОЇ СУПЕР ПОШТИ Ñьогодні!!! + +/manage/emailpost.bml.help.optionalfeatures.removetext.header=Ð’Ð¸ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð½ÐµÐ¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ð¾Ð³Ð¾ текÑту + +/manage/emailpost.bml.help.optionalfeatures.removetext.text=Любий текÑÑ‚, нижчий за два чи більше дефіÑи або Ñимволи підкреÑÐ»ÐµÐ½Ð½Ñ ("[[dashes]]" або "[[underscores]]") на окремому Ñ€Ñдку буде автоматично видалений. Червоний текÑÑ‚, зазначений нижче, не з'ÑвитьÑÑ Ñƒ вашому запиÑÑ–. + +/manage/emailpost.bml.help.pin=ПІÐ-код + +/manage/emailpost.bml.help.pinusage.header=Приклади викориÑÑ‚Ð°Ð½Ð½Ñ ÐŸÐ†Ð-коду + +/manage/emailpost.bml.help.pinusage.inbody.header=ПІÐ-код у текÑÑ‚Ñ– + +/manage/emailpost.bml.help.pinusage.inemail.header=ПІÐ-код в email-адреÑÑ– + +/manage/emailpost.bml.help.pinusage.insubject.header=ПІÐ-код у темі + +/manage/emailpost.bml.help.subject|notes=An example subject line for the example email. The "pin" variable is only filled in in certain cases. +/manage/emailpost.bml.help.subject=Тема: [[pin]] Ð’ÐУ! Я можу пиÑати через email. + +/manage/emailpost.bml.help.subject_images|notes=An example subject line for the example picture email. +/manage/emailpost.bml.help.subject_images=Тема: Ð’ÐУ! Я можу відправлÑти Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· email. + +/manage/emailpost.bml.help.text1=За допомогою звичайної email-Ñкриньки ви можете оновлювати Ñвій журнал чи Ñпільноту. Ваш ПІÐ-код повинен бути включений до email-адреÑи, теми чи текÑту лиÑта. Додавайте Ñвій ПІÐ-код разом з Ñимволом [[plus]]. Ви повинні відÑилати лиÑÑ‚ з email-адреÑи, Ñка зазначена в переліку "Дозволених Ð°Ð´Ñ€ÐµÑ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð½Ð¸ÐºÐ°". Якщо ви включите ПІÐ-код до теми чи текÑту лиÑта, його буде автоматично виключено перед надÑиланнÑм. + +/manage/emailpost.bml.help.text2=ЗапиÑи через email дозволÑÑŽÑ‚ÑŒ вÑтановлювати багато параметрів Ð´Ð»Ñ Ð¾ÐºÑ€ÐµÐ¼Ð¸Ñ… лиÑтів. Через Ñ—Ñ… різноманітніÑÑ‚ÑŒ ми зробили декілька розділів. Будь лаÑка, оберіть будь-Ñкий з нижченаведеного ÑпиÑку: + +/manage/emailpost.bml.help.to|notes=The "email" variable will be replaced with the .help.exampleusername string + @post.livejournal.com OR .help.exampleusername + .help.pin + @post.livejournal.com (unless the user is logged in and/or has specified a PIN, in which case it uses the user's actual username and/or PIN). +/manage/emailpost.bml.help.to=До: [[email]] + +/manage/emailpost.bml.instructions.header=ІÑнтрукції + +/manage/emailpost.bml.intro=Якщо ви бажаєте оновлювати Ñвій журнал через email, будь лаÑка, заповніть наведені полÑ. Ð”Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації по викориÑтанню цієї можливоÑÑ‚Ñ–, дивітьÑÑ Ñ–Ð½Ñтрукції. + +/manage/emailpost.bml.pin.header=ПІÐ-код + +/manage/emailpost.bml.pin.text=Ваш ПІÐ-код викориÑтовуєтьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ð´Ð»Ñ email-шлюзу. Ðе викориÑтовуйте тут звичайний пароль. У випадку, Ñкщо хтоÑÑŒ дізнаєтьÑÑ Ð²Ð°Ñˆ ПІÐ-код, він не зможе отримати повний доÑтуп до вашого журналу. ПІÐ-код повинен ÑкладатиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ з букв та/або цифр Ñ– мати щонайменше [[num]] [[?num|Ñимвол|Ñимволи|Ñимволів]]. + +/manage/emailpost.bml.settings.entry.comments=Коментарі: + +/manage/emailpost.bml.settings.entry.comments.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.entry.comments.select.noemail=Без email + +/manage/emailpost.bml.settings.entry.comments.select.off=вимкнуто + +/manage/emailpost.bml.settings.entry.header=Стандартні Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ð¸Ñ… запиÑів + +/manage/emailpost.bml.settings.entry.security=Безпека + +/manage/emailpost.bml.settings.entry.security.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.entry.security.select.friends=друзі + +/manage/emailpost.bml.settings.entry.security.select.private=приватно + +/manage/emailpost.bml.settings.entry.security.select.public=публічно + +/manage/emailpost.bml.settings.entry.userpic=Юзерпика: + +/manage/emailpost.bml.settings.entry.userpic.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.header=Стандартні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/emailpost.bml.settings.image.cut=Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñкрадених зображень: + +/manage/emailpost.bml.settings.image.cut.select.count=кількіÑÑ‚ÑŒ + +/manage/emailpost.bml.settings.image.cut.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.image.cut.select.titles=назви + +/manage/emailpost.bml.settings.image.galname=Ðазва галереї: + +/manage/emailpost.bml.settings.image.header=Стандартні Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ + +/manage/emailpost.bml.settings.image.layout=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ: + +/manage/emailpost.bml.settings.image.layout.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.image.layout.select.horizontal=горизонтально + +/manage/emailpost.bml.settings.image.layout.select.vertical=вертикально + +/manage/emailpost.bml.settings.image.security=Безпека Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +/manage/emailpost.bml.settings.image.security.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.image.security.select.friends=друзі + +/manage/emailpost.bml.settings.image.security.select.private=приватно + +/manage/emailpost.bml.settings.image.security.select.public=публічно + +/manage/emailpost.bml.settings.image.security.select.regusers=зареєÑтровані кориÑтувачі + +/manage/emailpost.bml.settings.image.size=Розмір зображеннÑ: + +/manage/emailpost.bml.settings.image.size.select.default=за замовчуваннÑм + +/manage/emailpost.bml.settings.text=Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð¿Ð¾Ð²ÑюджуютьÑÑ Ð½Ð° вÑÑ– журнальні запиÑи, що додаютьÑÑ Ñ‡ÐµÑ€ÐµÐ· email. Ви можете залишити ці параметри без змін, щоб кориÑтуватиÑÑ Ñтандартними, або вказувати параметри Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¾ÐºÑ€ÐµÐ¼Ð¾ за допомогою lj-заголовків. Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ (та lj-заголовки) детально опиÑані тут. + +/manage/emailpost.bml.sorry.acct=Вибачте, ви муÑите покращити Ñвій рахунок, щоб кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. + +/manage/emailpost.bml.success.header=УÑпішно + +/manage/emailpost.bml.success.info=ÐатиÑніть Ñюди Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації з кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. + +/manage/emailpost.bml.success.saved=Ваші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ email-шлюзу уÑпішно збережені. + +/manage/emailpost.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¸Ñ… повідомлень + +/manage/horizon.bml.youraccount.validated.no=(Ðепідтверджений) + +/manage/horizon.bml.youraccount.validated.yes=(Підтверджений) + +/manage/index.bml.about=Керувати Ñвоїм рахунком дуже легко. ПроÑто оберіть із наведених нижче розділів: + +/manage/index.bml.communities=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð»Ð°Ñними Ñпільнотами: + +/manage/index.bml.communities.create.about=Створити нову Ñпільноту + +/manage/index.bml.communities.header=Спільноти + +/manage/index.bml.communities.invites.about=ДивитиÑÑ Ð²ÑÑ– очікуючі Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ Ñпільнот, що Ви отримали. + +/manage/index.bml.communities.manage.about=Керувати налаштуваннÑми та учаÑниками ваших Ñпільнот + +/manage/index.bml.customization=Змінити виглÑд Ñторінок вашого журналу: + +/manage/index.bml.customization.advanced=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/index.bml.customization.advanced.about=ПереглÑнути, Ñтворити та змінити ваші Ñхеми та Ñтилі S2 + +/manage/index.bml.customization.customize=Ðалаштувати журнал + +/manage/index.bml.customization.customize.about=Зміна виглÑду вашого журналу та Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ ÑиÑтемами Ñтилів S1 та S2 + +/manage/index.bml.customization.header=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/index.bml.customization.links=СпиÑок поÑилань + +/manage/index.bml.customization.links.about=Створити ÑпиÑок поÑилань Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу + +/manage/index.bml.customization.modify.about=Змінити влаÑтивоÑÑ‚Ñ– виглÑду вашого журналу + +/manage/index.bml.customization.moodtheme.editor=Створити та змінити ваші оÑобливі теми наÑтроїв + +/manage/index.bml.customization.moodtheme.editor.header=Редактор Тем ÐаÑтрою + +/manage/index.bml.customization.moodtheme.header=Теми наÑтрою + +/manage/index.bml.customization.moodtheme.set=Оберіть тему наÑтроїв, Ñку викориÑтовуватиме ваш журнал + +/manage/index.bml.customization.moodtheme.set.header=Визначити вашу тему наÑтроїв + +/manage/index.bml.customization.navstrip=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ð¹Ð½Ð¾Ñ— Ñтрічки + +/manage/index.bml.customization.s1.header=СиÑтема Ñтилів S1 + +/manage/index.bml.customization.s2.header=СиÑтема Ñтилів S2 + +/manage/index.bml.customizeadsettings=Ðалаштувати рекламні параметри + +/manage/index.bml.deleteaccount=Видалити рахунок + +/manage/index.bml.entries=Працювати із запиÑами, що ви зробили у журналі Ñвого рахунку: + +/manage/index.bml.entries.edit.about=Змінити та видалÑти запиÑи з вашого журналу + +/manage/index.bml.entries.header=ЗапиÑи журналу + +/manage/index.bml.entries.memories.about=ДивитиÑÑ Ñ‚Ð° працювати з вибраними запиÑами + +/manage/index.bml.entries.tags.about=Организувати категорії запиÑів вашого журналу + +/manage/index.bml.entries.tags.header=Керувати тегами запиÑів + +/manage/index.bml.friends=Керувати Ñвоїми друзÑми та групами друзів, або Ñортувати Ñвою Ñтрічку друзів згідно зі збереженими групами друзів: + +/manage/index.bml.friends.edit.about=Додати або вилучити кориÑтувачів з вашого ÑпиÑку друзів або змінити кольори, що викориÑтовуютьÑÑ Ð´Ð»Ñ Ñ—Ñ…Ð½ÑŒÐ¾Ð³Ð¾ предÑтавленнÑ. + +/manage/index.bml.friends.filter=Фільтрувати Ñтрічку друзів + +/manage/index.bml.friends.filter.about=Фільтрувати ваш ÑпиÑок друзів, щоб відобразити певну групу друзів + +/manage/index.bml.friends.groups.about=Створити, змінити або видалити підгрупи вашого ÑпиÑку друзів + +/manage/index.bml.friends.header=Друзі + +/manage/index.bml.information=Оберіть, Ñку інформацію відображати на вашому рахунку: + +/manage/index.bml.information.about=Додаткова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‚Ð° параметри Ð´Ð»Ñ ÐŸÐ»Ð°Ñ‚Ð½Ð¸Ñ… та Розширених рахунків. + +/manage/index.bml.information.changepass=Змінити пароль рахунку + +/manage/index.bml.information.changepass.about=Змінити пароль вашого рахунку + +/manage/index.bml.information.comments.about=Змініти параметри ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/index.bml.information.editinfo.about=Змінити інформацію про рахунок та інші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/index.bml.information.header=Дані рахунку + +/manage/index.bml.information.mobilepost=Ðалаштувати мобільні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/manage/index.bml.information.mobilepost.about=Керувати вашими електронними адреÑами та ПІÐ-кодами Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ мобільних повідомлень + +/manage/index.bml.information.profile.about=Змінити профіль + +/manage/index.bml.information.pubkey=Публічний ключ PGP/GPG + +/manage/index.bml.information.pubkey.about=Завантажити Ñвій публічний ключ + +/manage/index.bml.information.settings.about=Змінити параметри переглÑду та інші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/manage/index.bml.information.siteopts.about=Оберіть улюблену Ñхему Ñайту та мову + +/manage/index.bml.information.status=Стан рахунку + +/manage/index.bml.information.status.about=Ð’Ñтановіть Ñтан активноÑÑ‚Ñ– Ñвого рахунку (видалити або відновити Ñвій рахунок) + +/manage/index.bml.information.voicepost=Ðалаштувати голоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/manage/index.bml.information.voicepost.about=Керувати номером телефону та ПІÐ-кодом Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень + +/manage/index.bml.login2=Ðижченаведені поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²ÐµÐ´ÑƒÑ‚ÑŒ до Ñторінок, що потребують входу до LiveJournal. Щоб зберегти Ñвій, ви можете увійти заздалегідь. + +/manage/index.bml.manage.subscriptions=Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ñ€Ð¾Ð·Ñилками + +/manage/index.bml.schools=Керувати даними про навчальні заклади, Ñкі ви відвідували + +/manage/index.bml.settings_pref=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° переваги + +/manage/index.bml.title=Керувати рахунками + +/manage/index.bml.undeleteaccount=Відновити рахунок + +/manage/index.bml.userpics=Завантажити юзерпики Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку та керувати ними: + +/manage/index.bml.userpics.edit.about=Завантажити та керувати влаÑними юзерпиками + +/manage/index.bml.userpics.header=Юзерпики + +/manage/index.bml.youraccount.email=Email-адреÑа: + +/manage/index.bml.youraccount.header=Ваш рахунок + +/manage/index.bml.youraccount.name=Ім'Ñ: + +/manage/index.bml.youraccount.setemail=Ð’Ñтановити + +/manage/index.bml.youraccount.user=КориÑтувач: + +/manage/index.bml.youraccount.validated.no=Ðе перевірено + +/manage/index.bml.youraccount.validated.yes=Перевірено + +/manage/invites.bml.abilities.title=МожливоÑÑ‚Ñ– + +/manage/invites.bml.accept=ПрийнÑти + +/manage/invites.bml.accepted.body=Ви приєдналиÑÑ Ð´Ð¾ наÑтупних Ñпільнот із зазначеними можливоÑÑ‚Ñми: + +/manage/invites.bml.accepted.title=ПрийнÑÑ‚Ñ– Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +/manage/invites.bml.actions.title=Дії + +/manage/invites.bml.back=Керувати запрошеннÑми + +/manage/invites.bml.community.title=Спільнота + +/manage/invites.bml.decline=Відхилити + +/manage/invites.bml.fromline=Від [[user]] ([[date]]) + +/manage/invites.bml.label.admin=ÐаглÑдач + +/manage/invites.bml.label.member=УчаÑник + +/manage/invites.bml.label.moderate=Модератор + +/manage/invites.bml.label.post=Може пиÑати + +/manage/invites.bml.label.preapprove=Ðемодероване + +/manage/invites.bml.manage=Керувати рахунком + +/manage/invites.bml.none.body=Ви наразі не маєте очікуючих запрошень до Ñпільнот. + +/manage/invites.bml.none.title=Жодних очікуючих + +/manage/invites.bml.rejected.body=Ви відхилили наÑтупні Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ Ñпільнот: + +/manage/invites.bml.rejected.title=Ð—Ð°Ð¿Ñ€ÑˆÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÐµÐ½Ñ– + +/manage/invites.bml.submit=ВідіÑлати обране + +/manage/invites.bml.title=Керувати запрошеннÑми до Ñпільнот + +/manage/invites.bml.undecided.body=Ви не визначилиÑÑ, що робити із наÑтупними запрошеннÑми: + +/manage/invites.bml.undecided.title=Ð’Ñе ще очікуючі Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +/manage/links.bml.about=ВикориÑтовуйте форму унизу, щоб Ñтворити ÑпиÑок поÑилань, Ñкий з'ÑвитьÑÑ Ñƒ вашому журналі. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·'ÑвлÑÑ‚ÑŒÑÑ, тільки Ñкщо Ñ†Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ підтримуєтьÑÑ Ð²Ð°ÑˆÐ¸Ð¼ Ñтилем S2. + +/manage/links.bml.about.blank=Щоб Ñтворити порожній Ñ€Ñдок, введіть "-" в ÑкоÑÑ‚Ñ– заголовку + +/manage/links.bml.about.heading=Щоб Ñтворити заголовок введіть заголовок без URL. + +/manage/links.bml.about.reorder=Щоб змінити порÑдок Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñилань у ÑпиÑк змініть чиÑло зліва (можна вживати деÑÑткові чиÑла) + +/manage/links.bml.error.s2required=СпиÑок поÑилань наÑвний тільки Ð´Ð»Ñ Ñтилів, котрі підтримуютьÑÑ ÑиÑтемою Ñтилів S2. Щоб переключитиÑÑ Ð´Ð¾ ÑиÑтеми S2, дивітьÑÑ Ñторінку [[link]]. + +/manage/links.bml.error.s2required.header=Потрібен S2 + +/manage/links.bml.success=УÑпішно! Ваше поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ збережене. + +/manage/links.bml.title=СпиÑок поÑилань + +/manage/logins.bml.intro=Ðа цій Ñторінці відображуютьÑÑ Ð²ÑÑ– ваші поточні ÑеанÑи входу до [[sitename]], а також деÑкі з попередніх. Ви можете ÑамоÑтійно завершити будь-Ñкі поточні ÑеанÑи, наприклад, Ñкщо ви забули вийти, піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ÑкориÑталиÑÑ ÐºÐ¾Ð¼Ð¿â€™ÑŽÑ‚ÐµÑ€Ð¾Ð¼ Ñвого друга. + +/manage/logins.bml.loggedin.header=Поточні ÑеанÑи входу + +/manage/logins.bml.loggedin.header.user=Поточні ÑеанÑи входу [[user]] + +/manage/logins.bml.loggedin.table.bound=Прив'Ñзати до IP-адреÑи + +/manage/logins.bml.loggedin.table.create=Ð§Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ + +/manage/logins.bml.loggedin.table.current=Поточний ÑÐµÐ°Ð½Ñ + +/manage/logins.bml.loggedin.table.expire=Ð§Ð°Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ + +/manage/logins.bml.loggedin.table.exptype=Тип Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ + +/manage/logins.bml.loggedin.table.ip=IP адреÑа + +/manage/logins.bml.loggedin.table.logout=Вийти + +/manage/logins.bml.loggedin.table.time=Ð§Ð°Ñ Ð²Ñ…Ð¾Ð´Ñƒ + +/manage/logins.bml.loggedin.table.useragent=Ðгент кориÑтувача + +/manage/logins.bml.prior.header=Попередні ÑеанÑи входу + +/manage/logins.bml.prior.header.user=Попередні ÑеанÑи входу [[user]] + +/manage/logins.bml.prior.table.ip=IP адреÑа + +/manage/logins.bml.prior.table.time=Ð§Ð°Ñ Ð²Ñ…Ð¾Ð´Ñƒ + +/manage/logins.bml.prior.table.useragent=Ðгент кориÑтувача + +/manage/logins.bml.title=Керувати Ñвоїми ÑеанÑами входу + +/manage/logins.bml.user=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/manage/moodthemes.bml.back2=ПовернутиÑÑ Ð”Ð¾ Редактора + +/manage/moodthemes.bml.btn.create=Створити + +/manage/moodthemes.bml.btn.delete=Видалити + +/manage/moodthemes.bml.btn.edit=Змінити + +/manage/moodthemes.bml.btn.savechanges=Зберегти Зміни + +/manage/moodthemes.bml.btn.use=ВикориÑтовувати + +/manage/moodthemes.bml.createtheme.header=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ðової Теми + +/manage/moodthemes.bml.createtheme.label.name=Ðазва: + +/manage/moodthemes.bml.editingtheme.header=Змінити тему [[name]] + +/manage/moodthemes.bml.editingtheme.label.name=Ðазва Теми: + +/manage/moodthemes.bml.error.cantcreatetheme=Помилка при Ñтворенні цієї теми наÑтрою. + +/manage/moodthemes.bml.error.cantcreatethemes=Вибачте, Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñобливих тем наÑтрою ви маєте обрати безкоштовний Розширений рахунок або придбати платний рахунок. + +/manage/moodthemes.bml.error.cantdeletetheme=Помилка при видаленні цієї теми наÑтрою. + +/manage/moodthemes.bml.error.cantupdatetheme=Помилка при поновленні цієї теми наÑтрою. + +/manage/moodthemes.bml.error.nonamegiven=Ви повинні вказати ім'Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— теми. + +/manage/moodthemes.bml.error.notyourtheme=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу змінювати цю тему. + +/manage/moodthemes.bml.mood.deleted=ÐаÑтрій "[[mood]]" було видалено, відтепер його предÑтавлÑтиме материнÑький наÑтрій. + +/manage/moodthemes.bml.mood.label.height=ВиÑота: + +/manage/moodthemes.bml.mood.label.inherit=УÑпадкувати від [[mood]]: + +/manage/moodthemes.bml.mood.label.width=Ширина: + +/manage/moodthemes.bml.mood.setpic=Ð”Ð»Ñ [[mood]] вÑтановлено [[url]]. + +/manage/moodthemes.bml.saved=Зміни уÑпішно збережено. + +/manage/moodthemes.bml.title=Редактор ВлаÑних Тем ÐаÑтрою + +/manage/moodthemes.bml.usepublictheme=Оберіть Ñвою Ñтандартну тему наÑтроїв у розділі "ВиглÑд журналу". + +/manage/moodthemes.bml.yourthemes.delete.confirm=Ви впевнені, що хочете видалити цю тему наÑтрою? + +/manage/moodthemes.bml.yourthemes.example.angry=Злий + +/manage/moodthemes.bml.yourthemes.example.happy=ЩаÑливий + +/manage/moodthemes.bml.yourthemes.example.none=[без зображеннÑ] + +/manage/moodthemes.bml.yourthemes.example.sad=Сумний + +/manage/moodthemes.bml.yourthemes.header=Ваші теми наÑтрою + +/manage/moodthemes.bml.yourthemes.nothemes=Ви ще не Ñтворили жодної оÑобливої теми наÑтрою. + +/manage/payments/adsettings.bml.about.head=Про рекламні параметри + +/manage/payments/adsettings.bml.about.head_1=Про категорії реклами + +/manage/payments/adsettings.bml.about.para1=Тривалий Ñ‡Ð°Ñ ÑƒÐ¿Ð¾Ð´Ð¾Ð±Ð°Ð½Ð½Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ð¹ реклами будуть впливати на тип реклами, Ñку ви бачитимете, але ви можете також бачити рекламу з інших категорій. ÐžÐ±Ñ€Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— кількоÑÑ‚Ñ– категорій не збільшить кількіÑÑ‚ÑŒ реклами, а тільки збільшить Ñ—Ñ— розмаїттÑ. ЗнÑÑ‚Ñ‚Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð¾Ðº з категорій не призведе до зміни вашого типу рахунку. + +/manage/payments/adsettings.bml.about.para2=Ð”Ð»Ñ Ñ‚Ð¾Ñ‡Ð½Ñ–ÑˆÐ¾Ð³Ð¾ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ переконайтеÑÑ, що заповнили Ñторінку профілю. LiveJournal не надає ваші оÑобиÑÑ‚Ñ– дані третім оÑобам. + +/manage/payments/adsettings.bml.about.para3=Ð”Ð»Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації про рекламні параметри перейдіть за поÑиланнÑм. + +/manage/payments/adsettings.bml.accountlevel.change=Змінити + +/manage/payments/adsettings.bml.accountlevel.label=Тип рахунку + +/manage/payments/adsettings.bml.adlayout.intro=Оберіть варіант Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ у Ñвоєму журналі та у Ñтрічці друзів. Оберіть "Горизонтальне розміщеннÑ" Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ð°Ð½ÐµÑ€Ñ–Ð² нагорі та внизу Ñторінки, або "Вертикальне розміщеннÑ" Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ð°Ð½ÐµÑ€Ñ–Ð² ліворуч та праворуч журналу. Ðе забудьте натиÑнути "Зберегти" внизу Ñторінки Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ†Ð¸Ñ… налаштувань. + +/manage/payments/adsettings.bml.adlayout.intro.ebox=Оберіть Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ на Ñторінках Ñвого журналу та Ñтрічки друзів. Виберіть "Горизонтальне розміщеннÑ" Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð³Ð¾Ñ€Ñ– та внизу Ñторінки, "Вертикальне розміщеннÑ" Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð°Ð²Ð¾Ñ€ÑƒÑ‡ або ліворуч або "Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ запиÑами" Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ запиÑами. Ðе забудьте натиÑнути кнопку "Зберегти" внизу Ñторінки, щоб зберегти ваші налаштуваннÑ. + +/manage/payments/adsettings.bml.adlayout.intro.ebox.note=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ запиÑами можливе лише на Ñторінках Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¾Ñтанніх запиÑів, запиÑів за день та в Ñтрічці друзів. Ðа інших Ñторінках реклама відображатиметьÑÑ Ð·Ð³Ñ–Ð´Ð½Ð¾ з вашими попередніми налаштуваннÑми — горизонтально чи вертикально. + +/manage/payments/adsettings.bml.adlayout.needs2=Параметр зміни Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ доÑтупний тільки Ñкщо Ви заÑтоÑовуєте СиÑтему Ñтилів S2. + +/manage/payments/adsettings.bml.adlayout.select.entries=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ запиÑами + +/manage/payments/adsettings.bml.adlayout.select.horizontal=Горизонтальне Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ + +/manage/payments/adsettings.bml.adlayout.select.vertical=Вертикальне Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ + +/manage/payments/adsettings.bml.emailoffers=Я згоден отримувати Ñ‡Ð°Ñ Ð²Ñ–Ð´ чаÑу рекламні матеріали у категоріÑÑ…, що Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð¸Ð². Я розумію, що LiveJournal не буде передавати чи продавати адреÑу моєї електронної пошти рекламодавцю. + +/manage/payments/adsettings.bml.error.choosecat=Будь лаÑка, оберіть категорії реклами, щоб ми могли завершити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку та надÑилати вам рекламу, Ñка може зацікавити ваÑ. Якщо ви не хочете обирати жодної категорії, оберіть опцію "ÐÑ–, дÑкую". + +/manage/payments/adsettings.bml.error.wronglevel=Ви не обрали Розширений рахунок Ð´Ð»Ñ [[user]]. ДивітьÑÑ ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/manage/payments/adsettings.bml.excuses=Поки ми важко працюємо, щоб зробити рекламу на LiveJournal відповіднішою та цікавішою, можемо Ñ‡Ð°Ñ Ð²Ñ–Ð´ чаÑу припуÑкатиÑÑ Ð¿Ð¾Ð¼Ð¸Ð»Ð¾Ðº. Чим більше вражень ви відправите нам, тим краще. ПоділітьÑÑ Ð· нами Ñвоїми враженнÑми. + +/manage/payments/adsettings.bml.geninfo.endtext=Ви можете контролювати, чи буде Ñ†Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ‚Ð¸ÑÑ Ñ–Ð½ÑˆÐ¸Ð¼ кориÑтувачам, завітавши на Ñторінку зміни профілю. + +/manage/payments/adsettings.bml.i.am.an.id.i.ot=Інколи надÑилайте мені рекламні пропозиції з категорій, Ñкі Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð¸Ð². Я розумію, що LiveJournal не буде розповÑюджувати чи продавати мою email-адреÑу іншим рекламодавцÑм. + +/manage/payments/adsettings.bml.i.am.an.idiot=Будь лаÑка, надÑилайте мені рекламні пропозиції по тих категоріÑÑ…, що Ñ Ð¿Ð¾Ð·Ð½Ð°Ñ‡Ð¸Ð². Я розумію, що LiveJournal не надає Ñ– не продає мою email-адреÑу жодному рекламодавцю. + +/manage/payments/adsettings.bml.intro=Будь лаÑка, оберіть п’ÑÑ‚ÑŒ (5) чи більше рекламних категорій, Ñкі Ð²Ð°Ñ Ð½Ð°Ð¹Ð±Ñ–Ð»ÑŒÑˆÐµ цікавлÑÑ‚ÑŒ. + +/manage/payments/adsettings.bml.intro_communities=Ð”Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ ваших налаштувань у Ñпільнотах з Розширеним рахунком перейдіть на Ñторінку реклами Ñпільноти. + +/manage/payments/adsettings.bml.intro_signup=Вже практично вÑе! Ð”Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ: + +/manage/payments/adsettings.bml.next1=Ðалаштуйте параметри реклами + +/manage/payments/adsettings.bml.next2=Завантажити юзерпики + +/manage/payments/adsettings.bml.next3=Перейти до ScrapBook + +/manage/payments/adsettings.bml.next4=ПовернутиÑÑ Ð´Ð¾ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ¾Ð¼ + +/manage/payments/adsettings.bml.nocat=ÐÑ–, дÑкую, Ñ Ð½Ðµ буду зазначати жодної категорії реклами + +/manage/payments/adsettings.bml.nocat.note=Вибір цієї позначки на змінить ваш тип рахунку та не зупинить Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸. + +/manage/payments/adsettings.bml.save=Зберегти + +/manage/payments/adsettings.bml.saved=Вашу категорію рекламних переваг було збережено. ПовернутиÑÑ Ð´Ð¾ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ°Ð¼Ð¸. + +/manage/payments/adsettings.bml.standout.para1=Ðа LiveJournal розміщуєтьÑÑ Ñ€Ñ–Ð·Ð½Ð° реклама. Ми хотіли б показувати вам рекламу, Ñка Ð²Ð°Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ цікавить. ПроÑимо Ð²Ð°Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ ÑƒÐ¿Ð¾Ð´Ð¾Ð±Ð°Ð½Ð½Ñ Ñ‚Ð° інформацію, Ñка б допомогла нам в цьому. + +/manage/payments/adsettings.bml.standout.para2=LiveJournal не передаватиме третім Ñторонам жодної інформації, Ñка може бути ідентифікована з вами. + +/manage/payments/adsettings.bml.sub.adcat=Категорії реклами + +/manage/payments/adsettings.bml.sub.adlayout=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ + +/manage/payments/adsettings.bml.sub.general=Загальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/manage/payments/adsettings.bml.title=Ðалаштувати рекламні параметри + +/manage/payments/adsettings.bml.title_1=Оберіть Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ + +/manage/payments/adsettings.bml.title_landing=Зміни збережено + +/manage/payments/adsettings.bml.whatnext=Що ви бажали б зробити далі? + +/manage/payments/cancel.bml.autopayoff.success=Ðвтоматичну оплату вашого рахунку вимкнуто. ДивітьÑÑ ÐºÑ–Ð½Ñ†ÐµÐ²Ñƒ дату у влаÑтивоÑÑ‚ÑÑ… рахунку. + +/manage/payments/cancel.bml.autopayoff.title=Ðвтоматичну оплату вимкнено + +/manage/payments/cancel.bml.btn.no=ÐÑ–, повернутиÑÑ Ð´Ð¾ мого рахунку + +/manage/payments/cancel.bml.btn.yes=Так, перейти далі та ÑкаÑувати + +/manage/payments/cancel.bml.checkbox.accept=Я розумію та приймаю Ñказане й бажаю вимкнути автоматичну оплату. + +/manage/payments/cancel.bml.error.alreadydisabled=Ðвтоматичну оплату вашого рахунку вже вимкнено. + +/manage/payments/cancel.bml.error.autopaydisabled=Ðвтоматична оплата зараз не діє. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації, будь лаÑка, завітайте до http://status.livejournal.org. + +/manage/payments/cancel.bml.error.cannotdisable=Виникла проблема з вимкненнÑм ваших платежів. ЗвернітьÑÑ Ð´Ð¾ Ñлужби підтримки. + +/manage/payments/cancel.bml.error.cannotloadbillinginfo=Проблема із завантаженнÑм банківÑької інформації. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки. + +/manage/payments/cancel.bml.error.mustcheckbox=Ви повинні поÑтавити галочку на знак Ñвоєї згоди з припиненнÑм автоматичної оплати. + +/manage/payments/cancel.bml.keepinmind=Ðижче наведені кілька речей, Ñкі ви маєте враховувати, вимикаючи автоматичну оплату. + +/manage/payments/cancel.bml.keepinmind.bonustime=Ви маєте призовий чаÑ, Ñкий буде анульовано в разі Ð²Ð¸Ð¼Ð½ÐµÐºÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати. + +/manage/payments/cancel.bml.keepinmind.confirm=Ми надішлемо на вашу електрону адреÑу Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ñ– терміну Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку. + +/manage/payments/cancel.bml.keepinmind.content=Зверніть увагу, що певна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñƒ вашому журналі (фотографії, юзерпики, Ñтилі) може Ñтати недоÑтупною піÑÐ»Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ платного рахунку. + +/manage/payments/cancel.bml.keepinmind.expiration=ПереконайтеÑÑŒ у тому, Ñкий виглÑд матиме ваш рахунок піÑÐ»Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ. + +/manage/payments/cancel.bml.keepinmind.norefunds=ВідÑутні платежі, а також передачі Ñплаченого чаÑу Ð´Ð»Ñ Ð¾ÐºÑ€ÐµÐ¼Ð¸Ñ… міÑÑців. + +/manage/payments/cancel.bml.keepinmind.remainpaid=Ваш рахунок залишитьÑÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ð¼ до [[date]]. + +/manage/payments/cancel.bml.title=Вимкнути автоматичну оплату? + +/manage/payments/cc.bml.chargeamount=Ви повинні Ñплатити [[amount]] Ñьогодні. Ð”Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— безпеки вам необхідно знову ввеÑти дані кредитної картки, адже [[sitename]] не зберігає цю інформацію на Ñвоїх Ñерверах. + +/manage/payments/cc.bml.email.ccchanged.body<< +[[username]], ви уÑпішно змінили дані Ñвоєї кредитної картки Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати вашого рахунку. Будь лаÑка, перевірте правильніÑÑ‚ÑŒ вказаних даних. + +Рахунок (ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача): [[username]] +Кредитна картка: xxxx-xxxx-xxxx-[[last4]] +ДійÑна до: [[month]]/[[year]] + +Ð”Ð»Ñ Ð²Ð½ÐµÑÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½ у Ñвій платний рахунок відвідайте [[managepaymentsurl]]. + +Свої Ð·Ð°Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸ можете поÑтавити, напиÑавши на адреÑу відправника. + +ДÑкуємо за підтримку нашого Ñайту, + +Команда [[sitename]] +. + +/manage/payments/cc.bml.email.ccchanged.subject=Кредитну картку Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати змінено + +/manage/payments/cc.bml.enterccinfo=Будь лаÑка, введіть дані кредитної картки. Ð’ÑÑ– Ð¿Ð¾Ð»Ñ Ð¾Ð±Ð¾Ð²'Ñзкові Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ. Отримувачем коштів буде вказано [[sitename]]. + +/manage/payments/cc.bml.error.autherror=Помилка при Ñпробі авторизації: [[errormsg]] + +/manage/payments/cc.bml.error.cantapplybonusitem=Ðеможливо заÑтоÑувати бонуÑи: [[item]] + +/manage/payments/cc.bml.error.cantapplypaidtime=Ðеможливо заÑтоÑувати Ñ‡Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку. + +/manage/payments/cc.bml.error.cantcreateaccount=Помилка при Ñтворенні рахунку: [[errormsg]] + +/manage/payments/cc.bml.error.cantcreatenewcard=Помилка при Ñтворенні нової картки: [[errormsg]] + +/manage/payments/cc.bml.error.cantdeleteoldcard=Помилка при видаленні Ñтарої картки: [[errormsg]] + +/manage/payments/cc.bml.error.cantloadpaymentinfo=Ðеможливо завантажити інформацію про оплату. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки. + +/manage/payments/cc.bml.error.cantprocessrequest=Вибачте, ми не можемо виконати ваш запит. + +/manage/payments/cc.bml.error.cantsavenewcard=Помилка при збереженні нової картки: [[errormsg]] + +/manage/payments/cc.bml.error.cantsetupaccount=Під Ñ‡Ð°Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ виникла помилка. Кошти з картки не були знÑÑ‚Ñ–. Спробуйте повторити операцію за кілька хвилин. Якщо проблема не зникне, будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки. [[errormsg]] + +/manage/payments/cc.bml.error.ineligible=Ваш рахунок негідний Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати. + +/manage/payments/cc.bml.error.invalidaccounttype=Вибачте, Ñ†Ñ Ñторінка доÑтупна тільки Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів звичайних журналів. + +/manage/payments/cc.bml.error.unknownautherror=ÐевиÑÑнена помилка при Ñпробі авторизації. Будь лаÑка, Ñпробуйте ще раз. + +/manage/payments/cc.bml.infosecure.header=Ваша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð² безпеці + +/manage/payments/cc.bml.infosecure.text=Це означає, що Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ вашу кредитну картку шифруєтьÑÑ Ð½Ð° шлÑху від вашого комп'ютера до [[sitename]] та банку, Ñкий отримує гроші. [[sitename]] не зберігає дані вашої картки на Ñвоїх Ñерверах. Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ñ”Ñ‚ÑŒÑÑ Ð²Ð¸ÐºÐ»ÑŽÑ‡Ð½Ð¾ на захищених Ñерверах нашого обробника даних кредитних карток. Ðе передавайте дані вашої кредитної картки чи пароль через e-mail. + +/manage/payments/cc.bml.owenothing=Ðавіть Ñкщо на даний Ñ‡Ð°Ñ Ð²Ð°Ñˆ рахунок оплачений, вам необхідно ввеÑти дані кредитної картки Ð´Ð»Ñ Ð¿Ð¾Ð´Ð°Ð»ÑŒÑˆÐ¾Ñ— автоматичної оплати. Ви зможете обновити цю інформацію в майбутньому. + +/manage/payments/cc.bml.title=Введіть дані вашої кредитної картки + +/manage/payments/giftcerts.bml.error.title=Помилка + +/manage/payments/giftcerts.bml.nogiftcerts=Подарункові Ñертифікати відÑутні + +/manage/payments/giftcerts.bml.table.amount=ВартіÑÑ‚ÑŒ + +/manage/payments/giftcerts.bml.table.code=Код + +/manage/payments/giftcerts.bml.table.item=Товар + +/manage/payments/giftcerts.bml.text=Ðижче наведені вÑÑ– подарункові Ñертифікати, пов’Ñзані з вашим рахунком. Ви можете вжити невикориÑтані подарункові Ñертифікати Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати або Ð´Ð»Ñ ÐºÑƒÐ¿Ñ–Ð²Ð»Ñ– товарів у Крамниці подарунків. ВикориÑтані Ñертифікати відзначені, але вÑе одно відображаютьÑÑ Ð² таблиці. + +/manage/payments/giftcerts.bml.title=Ваші подарункові Ñертифікати + +/manage/payments/history.bml.description.autopayment=Ðвтоматична оплата + +/manage/payments/history.bml.description.giftshop=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² крамниці подарунків + +/manage/payments/history.bml.description.notes=Додаткові нотатки: + +/manage/payments/history.bml.error.deleted=Рахунок видалено. + +/manage/payments/history.bml.nopayments=Жодних оплат. + +/manage/payments/history.bml.paymentmethod.cash=Готівка + +/manage/payments/history.bml.paymentmethod.cc=Кредитна картка + +/manage/payments/history.bml.paymentmethod.check=Чек + +/manage/payments/history.bml.paymentmethod.moneyorder=Грошовий переказ + +/manage/payments/history.bml.status.failed=Ðевдало + +/manage/payments/history.bml.status.successful=УÑпішно + +/manage/payments/history.bml.table.amount=ВартіÑÑ‚ÑŒ + +/manage/payments/history.bml.table.date=Дата + +/manage/payments/history.bml.table.description=ÐžÐ¿Ð¸Ñ + +/manage/payments/history.bml.table.paymentmethod=СпоÑіб оплати + +/manage/payments/history.bml.table.status=Стан + +/manage/payments/history.bml.text=Ðижче наведено Ñ–Ñторію ваших оплат за [[sitename]]. Також ви можете проглÑнути додаткову інформацію про Ñвій рахунок. + +/manage/payments/history.bml.title=Ваші попередні оплати + +/manage/payments/index.bml.applieson.header=ЗаÑтоÑовуєтьÑÑ Ð´Ð¾: + +/manage/payments/index.bml.autopay.header=Ðвтоматична оплата: + +/manage/payments/index.bml.autopay.interval=Сплата кожні [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] + +/manage/payments/index.bml.autopayinfo=З вашої кредитної картки [[date]] автоматично буде знÑто [[price]]. + +/manage/payments/index.bml.bonusitem=Ð‘Ð¾Ð½ÑƒÑ [[item]] — [[qty]] [[?qty|міÑÑць|міÑÑців]] + +/manage/payments/index.bml.btn.autopay.change=Змінити автоматичну оплату + +/manage/payments/index.bml.btn.autopay.renew=Відновити за допомогою автоматичної оплати + +/manage/payments/index.bml.btn.autopay.turnoff=Вимкнути автоматичну оплату + +/manage/payments/index.bml.btn.cc.change=Змінити банківÑькі дані + +/manage/payments/index.bml.btn.manualpay.pay=Сплатити влаÑноруч + +/manage/payments/index.bml.btn.switch_1=Перейти на базовий рахунок + +/manage/payments/index.bml.btn.upgrade_paid=Перейти на платний рахунок + +/manage/payments/index.bml.btn.upgrade_plus=Перейти на Розширений рахунок + +/manage/payments/index.bml.btn.upgrade_sup_sponsored=Виберіть ÑпонÑора зі ÑпиÑку! + +/manage/payments/index.bml.cc.endsin= закінчуєтьÑÑ [[lastfournum]] + +/manage/payments/index.bml.cc.expires=Минає [[month]]/[[year]] + +/manage/payments/index.bml.cc.header=Сплачено: + +/manage/payments/index.bml.cc.nocard=картка не вказана + +/manage/payments/index.bml.changeaccount=Змінити ваш рахунок + +/manage/payments/index.bml.error.ineligible=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку не дозволÑÑ” здійÑнювати автоматичну оплату. + +/manage/payments/index.bml.error.invaliddate=помилкова дата + +/manage/payments/index.bml.error.regularjournals=Вибачте, Ñ†Ñ Ñторінка доÑтупна тільки Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів звичайних журналів. + +/manage/payments/index.bml.error.title=Помилка + +/manage/payments/index.bml.expires.header=Минає: + +/manage/payments/index.bml.expires.perm=Ðіколи + +/manage/payments/index.bml.free.head=Зараз ви маєте БÐЗОВИЙ рахунок + +/manage/payments/index.bml.free.line1=Базовий рахунок + +/manage/payments/index.bml.free.line2=Базовий тип рахунку пропонує кориÑтувачам LiveJournal багато можливоÑтей. + +/manage/payments/index.bml.free.para1_1=МожливоÑÑ‚Ñ– рахунку LiveJournal доÑтупні Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ð³Ð¾ типу рахунку. + +/manage/payments/index.bml.manualpay.header=Оплата влаÑноруч/подарунки: + +/manage/payments/index.bml.or=ÐБО + +/manage/payments/index.bml.paid.line1=Платний рахунок — починаєтьÑÑ Ð· 2 $/міÑ. + +/manage/payments/index.bml.paid.line2_1=Повний набір платних можливоÑтей Ñ– більше міÑÑ†Ñ Ð¿Ñ–Ð´ ваш журнал, Ð¿Ð»ÑŽÑ Ð²Ñ–Ð´ÑутніÑÑ‚ÑŒ реклами. + +/manage/payments/index.bml.promotionitem=[[item]] — [[qty]] [[?qty|month|months]] + +/manage/payments/index.bml.promotions.header=ЗаохоченнÑ: + +/manage/payments/index.bml.renew.header=За Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð¸Ñ‚Ð¸: + +/manage/payments/index.bml.renewaddons=Якщо ви бажаєте відновити Ñвої доповненнÑ, то можете додати Ñ—Ñ… до автоматичної оплати або розрахуватиÑÑ Ð²Ð»Ð°Ñноруч в Крамниці подарунків. + +/manage/payments/index.bml.rusure.btn.free_1=Змінити на базовий рахунок + +/manage/payments/index.bml.rusure.btn.sponsor=ЗалишитиÑÑ Ð· Розширеним + +/manage/payments/index.bml.rusure.head=Ви впевнені? + +/manage/payments/index.bml.rusure.intro=Ви маєте Ð·Ð°ÑƒÐ²Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡Ð¸ проблеми з викориÑтаннÑм розширеного типу рахунку? Якщо так, будь лаÑка, звернітьÑÑ Ñ–Ð· запитом до Ñлужби підтримки, аби ми могли це владнати. + +/manage/payments/index.bml.rusure.para1_1=Перехід від Розширеного до Базового рахунку обмежить ваш доÑтуп до певних можливоÑтей, включно (проте не тільки) із: + +/manage/payments/index.bml.rusure.para3_1=Докладно про те, Ñк перехід на базовий рахунок вплине на ваші можливоÑÑ‚Ñ–, читайте в Поширених питаннÑÑ…. + +/manage/payments/index.bml.rusure.para_features=Юзерпики: Ваш ліміт зменшитьÑÑ Ð´Ð¾ 6 [[faq1]]
    Фото-хоÑтинґ: Ви не зможете завантажити нові фотографії Ñ– Ñтарі фотографії можуть бути Ñтерті [[faq2]]
    Мобільні повідомленнÑ: Ви втратите доÑтуп до мобільних Ñ– голоÑових повідомлень
    + +/manage/payments/index.bml.rusure.para_features_2=Юзерпики: Ваш ліміт зменшитьÑÑ Ð´Ð¾ 6 [[faq1]]
    Фото-хоÑтинґ: Ви не зможете завантажувати нові фотографії, Ñтарі фотографії можуть бути знищені [[faq2]]
    ЗапиÑи з мобільного: Ви втратите доÑтуп до мобільних та голоÑових запиÑів
    Polls: Ви втратите можливіÑÑ‚ÑŒ розміщувати нові опитуваннÑ
    + +/manage/payments/index.bml.rusure.para_features_advancedsearch=Пошук: Ви не зможете викориÑтовувати параметри розширеного пошуку + +/manage/payments/index.bml.rusure.para_features_mobile=ЗапиÑи з мобільного: Ви не зможете надÑилати мобільні та голоÑові запиÑи + +/manage/payments/index.bml.rusure.para_features_photos=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ‚Ð¾: Ви не зможете додавати нові фотографії, а Ñтарі можуть бути видалені [[faq]] + +/manage/payments/index.bml.rusure.para_features_polls=ОпитуваннÑ: Ви не зможете Ñтворювати Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/payments/index.bml.rusure.para_features_styles=Стилі: Ви можете втратити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð¸ та Ñхеми [[faq]] + +/manage/payments/index.bml.rusure.para_features_userpics=Юзерпики: Ваш ліміт зменшитьÑÑ Ð´Ð¾ 6 [[faq]] + +/manage/payments/index.bml.rusure.switchback=Якщо ви шкодуєте за втраченими можливоÑÑ‚Ñми, ви завжди можете повернутиÑÑ Ð½Ð°Ð·Ð°Ð´! + +/manage/payments/index.bml.sponsored.head=Зараз ви маєте Розширений рахунок + +/manage/payments/index.bml.sponsored.intro=Ви можете будь-коли змінити тип вашого рахунку. + +/manage/payments/index.bml.sponsored.line1=Розширений рахунок — безкоштовно + +/manage/payments/index.bml.sponsored.line2=Більше можливоÑтей, ніж у базовому рахунку, завдÑки рекламі, Ñка звільнÑÑ” Ð²Ð°Ñ Ð²Ñ–Ð´ оплати. + +/manage/payments/index.bml.sponsored.para1_1=Розширений тип рахунку відкриває вам доÑтуп до багатьох першоклаÑних можливоÑтей LiveJournal завдÑки рекламі, Ñка звільнÑÑ” Ð²Ð°Ñ Ð²Ñ–Ð´ оплати. + +/manage/payments/index.bml.sponsored.saved.intro=Ваші зміни збережено + +/manage/payments/index.bml.sponsored.saved.line1=Поточний тип вашого рахунку - розширений. + +/manage/payments/index.bml.sponsored.saved.opt0=Завантажити юзерпики + +/manage/payments/index.bml.sponsored.saved.opt0_1=Редагувати ваші рекламні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/payments/index.bml.sponsored.saved.opt1=Завантажити юзерпики + +/manage/payments/index.bml.sponsored.saved.opt2=ПовернутиÑÑ Ð´Ð¾ ScrapBook + +/manage/payments/index.bml.sponsored.saved.opt3=ПовернутиÑÑ Ð´Ð¾ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/manage/payments/index.bml.sponsored.saved.para1=Що б ви хотіли зробити тепер? + +/manage/payments/index.bml.startingdate=ПочинаєтьÑÑ [[date]] Докладніше + +/manage/payments/index.bml.summary=Ðижче наведені загальні дані вашої передплати. Тут ви можете змінити передплату або інформацію про вашу картку. + +/manage/payments/index.bml.sup_sponsored.cancel_sponsorship=Відмінити ÑпонÑорÑтво! + +/manage/payments/index.bml.sup_sponsored.expiring_label=Цей Ñтан закінчуєтьÑÑ + +/manage/payments/index.bml.sup_sponsored.head=Ваш рахунок зараз Ñ” ÑпонÑорованим + +/manage/payments/index.bml.sup_sponsored.intro=Ви можете змінити ваш рахунок в будь-Ñкий Ñ‡Ð°Ñ + +/manage/payments/index.bml.sup_sponsored.line1=СпонÑорований рахунок - ніби платний, але безкоштовний Ð´Ð»Ñ Ð’Ð°Ñ! + +/manage/payments/index.bml.sup_sponsored.line2_1=Ви маєте обрати ÑпонÑора, Ñкий оплатить Ваш рахунок + +/manage/payments/index.bml.sup_sponsored.sponsor_label=СпонÑор + +/manage/payments/index.bml.sup_sponsored.status.D=Ваш ÑпонÑор був видалений, Ñ– Ñкоро Ваш рухунок переÑтану бути ÑпонÑорованим + +/manage/payments/index.bml.sup_sponsored.status.F=Ви відмовилиÑÑŒ продовжити ÑпонÑорÑтво, отже Ñкоро Ваш рахунок переÑтане бути ÑпонÑорованим + +/manage/payments/index.bml.sup_sponsored.status.U=Ваш рахунок Ñ” ÑпонÑорованим + +/manage/payments/index.bml.sup_sponsored.status_label=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/manage/payments/index.bml.sup_sponsored.system_error=Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ вашого запиту виникла помилка + +/manage/payments/index.bml.sup_sponsored.warning.not_sponsored=Ваш рахунок не Ñ” ÑпонÑорованим + +/manage/payments/index.bml.sup_sponsored.warning.sponsorship_cancelled=Ваше ÑпонÑорÑтво було відмінено! + +/manage/payments/index.bml.table.popfeatures.header=Ðайбільш популÑрні можливоÑÑ‚Ñ– + +/manage/payments/index.bml.title=Стан мого платного рахунку + +/manage/payments/index.bml.title1=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/manage/payments/index.bml.upgradeaccount=Змініть ваш рахунок + +/manage/payments/index.bml.warning.switch=УÑпішно змінено на базовий рахунок. Якщо маєте хвилинку, будь лаÑка, повідомте нам, Ñк ми можемо покращити наш ÑервіÑ. + +/manage/payments/index.bml.warning.upgrade=УÑпішно змінено на Розширений. + +/manage/payments/modify.bml.about.autopay.header=Про автоматичну оплату: + +/manage/payments/modify.bml.about.autopay.needcc=Ð”Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати необхідна ÑÐ¿Ñ€Ð°Ð²Ð¶Ð½Ñ ÐºÑ€ÐµÐ´Ð¸Ñ‚Ð½Ð° картка. + +/manage/payments/modify.bml.about.autopay.othermethods=Ви також можете розрахуватиÑÑ Ð·Ð° придбаний платний рахунок готівкою чи оÑобиÑтим чеком, або ж ÑкориÑтатиÑÑ PayPal чи оплатою влаÑноруч. + +/manage/payments/modify.bml.about.autopay.weaccept=Ми приймаємо: + +/manage/payments/modify.bml.about.proratedpay.header=Чому деÑкі платежі знімаютьÑÑ Ñ‡Ð°Ñтково? + +/manage/payments/modify.bml.about.proratedpay.ifpaidtimeremains=Якщо Ñплачений чаÑ, Ñкий залишивÑÑ, перевищує період оплати, то гроші не будуть зніматиÑÑ, поки не вийде Ñплачений чаÑ. + +/manage/payments/modify.bml.about.proratedpay.maynotbecharged=Залежно від налаштувань вашого рахунку та Ñплаченого чаÑу, що залишивÑÑ, з Ð²Ð°Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ не зніматиÑÑ ÐºÐ¾ÑˆÑ‚Ð¸ протÑгом перших періолів оплати. Зараз ми не знімаємо кошти, Ñкщо ваш платіж менший за [[price]], але це правило може змінитиÑÑ Ð² майбутньому. + +/manage/payments/modify.bml.about.proratedpay.readmore=ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ + +/manage/payments/modify.bml.autopay.everyxmonths=Кожні [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] з Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ зніматиÑÑ [[price]]. + +/manage/payments/modify.bml.autopay.header=Ваша автоматична оплата: + +/manage/payments/modify.bml.autopay.none=немає + +/manage/payments/modify.bml.autopay.paidaccount=Платний рахунок + +/manage/payments/modify.bml.autopay.payment=Ваша регулÑрна автоматична оплата: + +/manage/payments/modify.bml.autopay.storage=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +/manage/payments/modify.bml.autopay.total=УÑього: + +/manage/payments/modify.bml.autopay.userpics=Додаткові юзерпики + +/manage/payments/modify.bml.btn.apply=ПрийнÑти + +/manage/payments/modify.bml.btn.back=<- Ðазад + +/manage/payments/modify.bml.btn.continue=Продовжити -> + +/manage/payments/modify.bml.btn.finish=Закінчити -> + +/manage/payments/modify.bml.btn.recalcprices=Перерахувати ціну доповнень + +/manage/payments/modify.bml.btn.remove=Видалити + +/manage/payments/modify.bml.cangoback=(ви можете повернутиÑÑ Ð½Ð°Ð·Ð°Ð´ та внеÑти зміни перед тим, Ñк гроші будуть знÑÑ‚Ñ– з картки) + +/manage/payments/modify.bml.error.cantaddcoupon=Ðеможливо додати купон до платежу: [[errormsg]] + +/manage/payments/modify.bml.error.cantadditem=Ðеможливо додати цей товар до платежу: [[errormsg]] + +/manage/payments/modify.bml.error.cantadditemstoprofile=Ðеможливо додати деÑкі товари до замовленнÑ. Будь лаÑка, зв'ÑжітьÑÑ Ð·Ñ– Ñлужбою підтримки. + +/manage/payments/modify.bml.error.cantaddstoragespace=Ðевідома помилка при додаванні диÑкового проÑтору: [[errormsg]] + +/manage/payments/modify.bml.error.cantapplybonusitem=Ðеможливо заÑтоÑувати Ð±Ð¾Ð½ÑƒÑ [[item]]: [[errormsg]] + +/manage/payments/modify.bml.error.cantapplystorage=Ðеможливо заÑтоÑувати диÑковий проÑÑ‚Ñ–Ñ€ до вашого рахунку. + +/manage/payments/modify.bml.error.cantapplyuserpics=Ðеможливо заÑтоÑувати юзерпики до вашого рахунку. + +/manage/payments/modify.bml.error.cantcalcdiskquotaprice=Ðеможливо вирахувати вартіÑÑ‚ÑŒ активації Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ð´Ð¸Ñкового проÑтору: [[errormsg]] + +/manage/payments/modify.bml.error.cantcalcuserpicprice=Ðеможливо вирахувати вартіÑÑ‚ÑŒ активації юзерпик. + +/manage/payments/modify.bml.error.cantcreatepayment=Помилка при Ñтворенні платежу. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки. + +/manage/payments/modify.bml.error.cantcreateprofile=Помилка при Ñтворенні профілю. Будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки. [[errormsg]] + +/manage/payments/modify.bml.error.cantgetprice=Ðеможливо вирахувати вартіÑÑ‚ÑŒ активацію товару. + +/manage/payments/modify.bml.error.cantgetrecitem=Ðе можу діÑтати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð»Ñ [[item]]: [[errormsg]] + +/manage/payments/modify.bml.error.cantloadcart=Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… кошика. + +/manage/payments/modify.bml.error.cantremoveitem=Помилка при видаленні товару з Ñ–Ñнуючого кошика. + +/manage/payments/modify.bml.error.cantselectsmalleramount=Зараз ви не можете вибрати меньшу кількіÑÑ‚ÑŒ диÑковогу проÑтору. + +/manage/payments/modify.bml.error.cantsetrecflag=Ðе можу виÑтавити мітку у запиÑÑ– [[onoff]] [[item]]: [[errormsg]] + +/manage/payments/modify.bml.error.cartidmismatch=Ðомер кошика не Ñпівпадає! Спробуйте ще раз, будь лаÑка. + +/manage/payments/modify.bml.error.ineligible.text=Ваш рахунок негідний Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати. + +/manage/payments/modify.bml.error.ineligible.title=Помилковий ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/manage/payments/modify.bml.error.invalidaccounttype.text=Вибачте, тільки оÑобиÑÑ‚Ñ– журнали можуть переглÑдати цю Ñторінку. + +/manage/payments/modify.bml.error.invalidaccounttype.title=Ðевірний тип рахунку + +/manage/payments/modify.bml.error.invalidbillinginterval=Ðевірний інтервал розрахунків: [[interval]] + +/manage/payments/modify.bml.error.invalidcoupon=(невірний або вже викориÑтаний купон) + +/manage/payments/modify.bml.error.invalidformsubmission=Помилка при відправці форми. + +/manage/payments/modify.bml.error.invalidmode=Обрано помилковий режим. + +/manage/payments/modify.bml.error.invalidstorageamount=Ðевірний розмір диÑкового проÑтірку. + +/manage/payments/modify.bml.error.notloggedin.title=Ðеобхідно увійти + +/manage/payments/modify.bml.error.permaccount.text=ПоÑтійні рахунки, на поточний момент, не можуть реєÑтруватиÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати. + +/manage/payments/modify.bml.error.permaccount.title=Ðе вживаєтьÑÑ + +/manage/payments/modify.bml.error.selectstorageamount=Будь лаÑка, оберіть розмір диÑкового проÑтору, Ñкий бажаєте придбати. + +/manage/payments/modify.bml.error.sponsoredaccount.text=СпонÑоровані рахунки, нажаль, наразі не доÑтупні Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— Ñплати.Завітайте до Магазина подарунків щоб надіÑлати подарунок іньшому кориÑтувачєві + +/manage/payments/modify.bml.error.sponsoredaccount.title=Ðе доÑтупно + +/manage/payments/modify.bml.error.title=Помилка + +/manage/payments/modify.bml.getpaid.title=Придбайте платний рахунок + +/manage/payments/modify.bml.giftcert.entercode=Введіть код подарункового купону: + +/manage/payments/modify.bml.giftcert.excesswasted=Якщо номінальна вартіÑÑ‚ÑŒ купону перевищує вартіÑÑ‚ÑŒ покупки, то залишок буде Ñпалено. + +/manage/payments/modify.bml.giftcert.header=ЗаÑтоÑувати подарунковий купон: + +/manage/payments/modify.bml.manage.title=Редагувати мої платежі + +/manage/payments/modify.bml.nextpage=Будь лаÑка, перейдіть до наÑтупної Ñторінки, щоб ввеÑти дані кредитної картки. + +/manage/payments/modify.bml.proratedpay.fullamount=Перший раз з Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ ÑÑ‚Ñгнуто повну вартіÑÑ‚ÑŒ ([[price]]) [[date]]. + +/manage/payments/modify.bml.proratedpay.header=Ваші чаÑтковий платіж + +/manage/payments/modify.bml.proratedpay.proamount=Ваш чаÑтковий платіж [[price]] відбудетьÑÑ [[date]]. + +/manage/payments/modify.bml.review.title=ПереглÑньте Ñвій вибір + +/manage/payments/modify.bml.selectaddons.everyxmonths=[[price]] кожні [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] + +/manage/payments/modify.bml.selectaddons.header=Оберіть доповненнÑ: (за бажаннÑм) + +/manage/payments/modify.bml.selectaddons.storage.header=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +/manage/payments/modify.bml.selectaddons.storage.selectupgrade=збільшить до [[size]] + +/manage/payments/modify.bml.selectaddons.storage.size.gigabytes=[[size]] Гб + +/manage/payments/modify.bml.selectaddons.storage.size.megabytes=[[size]] Мб + +/manage/payments/modify.bml.selectaddons.storage.text2=З платним рахунком ви отримаєте [[size]] Гб диÑкового проÑтору. + +/manage/payments/modify.bml.selectaddons.storage.upgrade=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ (голоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° міÑце Ð´Ð»Ñ Ñвітлин) + +/manage/payments/modify.bml.selectaddons.text=Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупні виключно кориÑтувачам з платними рахунками. + +/manage/payments/modify.bml.selectaddons.userpics.header=Додаткові юзерпики + +/manage/payments/modify.bml.selectaddons.userpics.text=Ви отримаєте [[numuserpics]] [[?numuserpics|юзерпику|юзерпик|юзерпик]] Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку. + +/manage/payments/modify.bml.selectaddons.userpics.upgrade=збільшить до [[numuserpics]] [[?numuserpics|юзерпики|юзерпик|юзерпик]] + +/manage/payments/modify.bml.selectbilling.bestvalue=краща пропозиціÑ! + +/manage/payments/modify.bml.selectbilling.bonustimenote=Будь лаÑка, зауважте, що бонуÑний Ñ‡Ð°Ñ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку буде знищено, Ñкщо ви оберете інший період оплати, ніж кожні [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]]. + +/manage/payments/modify.bml.selectbilling.everyxmonths=Кожні [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] - [[price]] + +/manage/payments/modify.bml.selectbilling.header=Оберіть період оплати: + +/manage/payments/modify.bml.selectbilling.onlyautopay=Ці ціни доÑтупні тільки кориÑтувачам платних рахунків з автоматичною оплатою. + +/manage/payments/modify.bml.selectbilling.or=або + +/manage/payments/modify.bml.text=Гроші з вашої кредитної картки будуть автоматично зніматиÑÑ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до обраного періоду оплати. + +/manage/payments/modify.bml.text2=Гроші з вашої крелитної картки будуь зніматиÑÑŒ автоматично в злежноÑÑ‚Ñ– від циклу оплати, Ñкий ви оберете.Ви також можете Ñплатити рахунок кориÑтуючиÑÑŒ іншими методами оплати через ручні платежі. + +/manage/payments/modify.bml.todayspay.giftcert=Подарунковий купон + +/manage/payments/modify.bml.todayspay.header=Сьогоднішній платіж: + +/manage/payments/modify.bml.todayspay.lessthan1month=- менше, ніж 1 міÑÑць + +/manage/payments/modify.bml.todayspay.payment=Ваш наÑтупний платіж: + +/manage/payments/modify.bml.todayspay.subtotal=Проміжна Ñума: + +/manage/payments/modify.bml.todayspay.today=Сьогодні з Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ знÑто [[price]]. + +/manage/payments/modify.bml.todayspay.todaynocc=Сьогодні з Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ знÑто [[price], але вам необхідно ввеÑти дані кредитної картки Ð´Ð»Ñ Ð¿Ð¾Ð´Ð°Ð»ÑŒÑˆÐ¸Ñ… автоматичних платежів. + +/manage/payments/modify.bml.todayspay.total=УÑього: + +/manage/payments/modify.bml.todayspay.xmonths=[[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] + +/manage/payments/thanks.bml.error.loadingbillingdata=Помилка при Ñпробі завантажити банківÑьку інформацію. + +/manage/payments/thanks.bml.error.loadingpaymentinfo=Помилка при Ñпробі завантажити платіжні дані. Оплату здійÑнено уÑпішно. + +/manage/payments/thanks.bml.extradiskspace.header=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +/manage/payments/thanks.bml.extradiskspace.text=Зараз ви можете завантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð² ScrapBook LiveJournal. Завантажте нові зображеннÑ. + +/manage/payments/thanks.bml.extrauserpics.header=Додаткові юзерпики + +/manage/payments/thanks.bml.extrauserpics.text=Зараз ви можете завантажити [maxpics]] юзерпик. Завантжте більше юзерпик. + +/manage/payments/thanks.bml.paidaccount.header=Платний рахунок + +/manage/payments/thanks.bml.paidaccount.text=ВикориÑтовуйте Ñвій платний рахунок на повну, дізнайтеÑÑŒ про вÑÑ– переваги платного рахунку. + +/manage/payments/thanks.bml.thankyou.header=ДÑкуємо за покупку! + +/manage/payments/thanks.bml.thankyou.text1=Сотні тренованих мавп зараз Ñтукають битами по вашому рахунку. + +/manage/payments/thanks.bml.thankyou.text2=Ðе поÑпішайте, приÑвÑÑ‚Ñ–Ñ‚ÑŒ трохи чаÑу, щоб дізнатиÑÑ Ð¿Ñ€Ð¾ нові платні можливоÑÑ‚Ñ– або проглÑньте повний перелік можливоÑтей платного рахунку. + +/manage/payments/thanks.bml.title=Оплату виконано + +/manage/phonepost.bml.intro.loggedout=УчаÑники можутьувійти та змінити Ñвої Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð¾Ð¼: + +/manage/profile/index.bml.birthday=Показувати ваш день Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ð¼ кориÑтувачам + +/manage/profile/index.bml.birthday.underage=КориÑтувачі, молодші 14 років, не можуть відображати Ñвій вік у профілÑÑ…. + +/manage/profile/index.bml.birthday.year.opt=міÑÑць/дд/рррр + +/manage/profile/index.bml.chat.gizmo=Проект "Gizmo" + +/manage/profile/index.bml.chat.msnusername=Ім'Ñ Ð² MSN + +/manage/profile/index.bml.country.choose=Оберіть країну + +/manage/profile/index.bml.email.change=Змінити email + +/manage/profile/index.bml.email.opt.both=Обидві (оÑновна адреÑа + адреÑа LiveJournal) + +/manage/profile/index.bml.email.opt.dont=Ðе відображати мою email-адреÑу + +/manage/profile/index.bml.email.opt.lj=Тільки адреÑу LiveJournal + +/manage/profile/index.bml.email.opt.no_show=Ðе показувати email-адреÑу + +/manage/profile/index.bml.email.opt.prime=Тільки оÑновну адреÑу + +/manage/profile/index.bml.email.opt.show=Показувати email-адреÑу + +/manage/profile/index.bml.error.bday.child=КориÑтувачі, молодші 14 років, не можуть відображати дату Ñвого Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñƒ профілÑÑ…. + +/manage/profile/index.bml.error.bio.toolong=Ваша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñебе занадно велика. + +/manage/profile/index.bml.error.cmax_int=Вибачте, ви вказали зацікавленнÑ, що ÑкладаєтьÑÑ Ð· [[cl]] Ñимволів. Тоді Ñк дозволений розмір - [[cmax]]. Зміни, Ñкі ви внеÑли у зацікавленнÑ, не збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть "[[int]]". + +/manage/profile/index.bml.error.contact.child=КориÑтувачі, молодші 14 років, не можуть робити Ñвою контактну інформацію загальнодоÑтупною. + +/manage/profile/index.bml.error.day.notinmonth=Ðеправильний день Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ міÑÑцÑ. + +/manage/profile/index.bml.error.day.outofrange=Ðеправильний день народженнÑ. Зазначте день від 1 до 31. + +/manage/profile/index.bml.error.email.lj_domain=Ви не можете ввеÑти адреÑу email @[[domain]]. Ðадрукуйте в цьому полі Ñвою дійÑну адреÑу. Якщо ви Ñ” платним кориÑтувачем, ваша адреÑа [[user]]@[[domain]] Ñлугуватиме пÑевдонімом вашої дійÑної адреÑи. Щоб вибрати, Ñку Ñаме адреÑу (чи обидві) показувати вÑім, проглÑньте відповідний параметр у розділі "Дозволити переглÑдати вашу контактну інформацію". + +/manage/profile/index.bml.error.email.none=Ви повинні надрукувати Ñвою email-адреÑу. + +/manage/profile/index.bml.error.email.no_space=Ðе дозволÑєтьÑÑ Ð²Ð¸ÐºÐ¾Ñ€Ð¸Ñтовувати пробіли в email-адреÑÑ–. Якщо ви клієнт AOL, пам'Ñтайте, що ваша email-адреÑа — це ваше екранне ім'Ñ Ð· прибраними пробілами та з @aol.com наприкінці. + +/manage/profile/index.bml.error.excessive_int=Ðа жаль, ви зазначили забагато зацікавлень. МакÑимально дозволена кількіÑÑ‚ÑŒ — 150, натоміÑÑ‚ÑŒ ви вказали [[intcount]]. Жодні зміни, Ñкі ви внеÑли до переліку ваших зацікавлень, збережені не були. ПовернітьÑÑ, приберіть деÑкі ваші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ– збережітьÑÑ Ð·Ð½Ð¾Ð²Ñƒ. + +/manage/profile/index.bml.error.invalidbio=Ваша Ñ–ÑÑ‚Ð¾Ñ€Ñ–Ñ Ð¿Ñ€Ð¾ Ñебе міÑтить помилкові Ñимволи. Ви маєте завітати на Ñторінку Ð¿ÐµÑ€ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° перевеÑти Ñ—Ñ… в Unicode. + +/manage/profile/index.bml.error.invalidname2=Ваше ім'Ñ Ð¼Ñ–Ñтить помилкові Ñимволи. Ви маєте завітати на Ñторінку перекодувань та перевеÑти Ñ—Ñ… в Unicode. + +/manage/profile/index.bml.error.locale.country_ne_state=Ви обрали Сполучені Штати Ñк Ñвою країну, проте вказали неамериканÑький штат у полі "інший штат". + +/manage/profile/index.bml.error.locale.invalid_country=Ви ÑкимоÑÑŒ чином обрали неправильну країну. + +/manage/profile/index.bml.error.locale.state_ne_country=Ви вказали не Ðмерику, проте обрали американÑький штат. + +/manage/profile/index.bml.error.locale.zip_ne_state=Ваш Ñ–Ð½Ð´ÐµÐºÑ Ð½Ðµ Ñпівпадає зі вказаним штатом. Виправте помилку або видаліть дані про штат та/чи індекÑ. + +/manage/profile/index.bml.error.locale.zip_requires_us=Ви вказали індекÑ, але не обрали Сполучені Штати Ñк Ñвою країну. Ми збираємо індекÑи лише Ð´Ð»Ñ Ð¼ÐµÑˆÐºÐ°Ð½Ñ†Ñ–Ð² СШÐ. Будь лаÑка, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть Ñ–Ð½Ð´ÐµÐºÑ Ð°Ð±Ð¾ ж оберіть Сполучені Штати Ñк Ñвою країну. + +/manage/profile/index.bml.error.month.outofrange=Ðеправильний міÑÑць народженнÑ. Введіть міÑÑць від 1 до 12. (Ñічень-грудень) + +/manage/profile/index.bml.error.name.toolong=Ім'Ñ Ñке ви напиÑали занадто довге + +/manage/profile/index.bml.error.noname=Ваше ім'Ñ Ñ” обов'Ñзковим полем. Принаймні вкажіть ваше неповне ім'Ñ Ñ‡Ð¸ прізвиÑько. + +/manage/profile/index.bml.error.txt.require.number=Якщо ви бажаєте викориÑтовувати текÑтові повідомленнÑ, то маєте вказати номер Ñвого телефону. + +/manage/profile/index.bml.error.txt.require_provider=Якщо ви бажаєте викориÑтовувати текÑтові повідомленнÑ, то маєте вибрати Ñвого оператора зв’Ñзку. Якщо ви не можете його знайти, будь лаÑка, напишіть нам, Ñк працюють текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñƒ вашого оператора зв’Ñзку, щоб ми могли додати його. + +/manage/profile/index.bml.error.usermessaging=Ðеправильний параметр Ð´Ð»Ñ Ñповіщень кориÑтувача. + +/manage/profile/index.bml.error.wmax_int=Вибачте, ви вказали зацікавленнÑ, що ÑкладаєтьÑÑ Ð· [[wl]] Ñлів. Тоді Ñк дозволений розмір - [[wmax]]. Зміни, Ñкі ви внеÑли у зацікавленнÑ, не збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть "[[int]]". + +/manage/profile/index.bml.error.year.notenoughdigits=Ðеправильний рік народженнÑ. Вкажіть рік чотиризначним чиÑлом. + +/manage/profile/index.bml.error.year.outofrange=Ðеправильний рік народженнÑ. + +/manage/profile/index.bml.fn.bio=Розкажіть іншим кориÑтувачам про Ñебе та Ñвій журнал. Якщо ви бажаєте викориÑтати графіку, лічильники або інші елементи HTML, то можете зробити це тут. + +/manage/profile/index.bml.fn.birthday=День Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.fn.city=МіÑто + +/manage/profile/index.bml.fn.contactinfo=Дозволити переглÑдати вашу контактну інформацію: + +/manage/profile/index.bml.fn.country=Країна + +/manage/profile/index.bml.fn.email=ОÑновна email-адреÑа + +/manage/profile/index.bml.fn.emaildisplay=Показувати + +/manage/profile/index.bml.fn.friendof=Перелік "У друзÑÑ…" + +/manage/profile/index.bml.fn.gender=Стать + +/manage/profile/index.bml.fn.imservices2=Миттєві Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.fn.interests=Перелічіть уÑÑ– Ñвої зацікавленнÑ, відокремлюючи Ñ—Ñ… комами, щоб інші кориÑтувачі могли знайти Ð²Ð°Ñ Ñ‡ÐµÑ€ÐµÐ· пошук за зацікавленнÑми. + +/manage/profile/index.bml.fn.interests3=Перелічте вÑÑ– Ñвої Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· кому, щоб Ð²Ð°Ñ Ð¼Ð¾Ð³Ð»Ð¸ знайти однодумці. Краще вказувати одиночні Ñлова. + +/manage/profile/index.bml.fn.link=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/manage/profile/index.bml.fn.mutualfriends=Взаємні друзі + +/manage/profile/index.bml.fn.name=Ðазва + +/manage/profile/index.bml.fn.province=або неамериканÑький штат/провінціÑ/Ñ‚ÐµÑ€Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ + +/manage/profile/index.bml.fn.schools=Ðавчальні заклади + +/manage/profile/index.bml.fn.servprov=Оператор + +/manage/profile/index.bml.fn.sitename=Ім'Ñ + +/manage/profile/index.bml.fn.state=Штат + +/manage/profile/index.bml.fn.timezone=ЧаÑовий поÑÑ + +/manage/profile/index.bml.fn.txtmsg=Дозволити надÑилати вам текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.fn.txtnum=Повний номер телефону + +/manage/profile/index.bml.fn.userpic=юзерпика за замовчуваннÑм + +/manage/profile/index.bml.fn.zip=Ð†Ð½Ð´ÐµÐºÑ + +/manage/profile/index.bml.friendof=Показувати кориÑтувачів, Ñкі додали Ð²Ð°Ñ Ñƒ друзі + +/manage/profile/index.bml.gender.female=Жіноча + +/manage/profile/index.bml.gender.male=Чоловіча + +/manage/profile/index.bml.gender.unspecified=(Ðе визначено) + +/manage/profile/index.bml.im=Миттєві Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ / Чат + +/manage/profile/index.bml.interest.line1=Краще викориÑтовувати короткі фрази. + +/manage/profile/index.bml.interest.line2=Практичний метод: вам Ñлід формулювати Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð°Ðº, щоб вони вкладалиÑÑ Ð² Ñ€ÐµÑ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ð´Ñƒ "Мені подобаєтьÑÑ ________". + +/manage/profile/index.bml.interest.line3=ЗацікавленнÑ, Ñкі можна передати іменниками, пишіть у формі називного відмінку однини, тобто "Мені подобаєтьÑÑ Ð¼ÑƒÐ·Ð¸ÐºÐ°" заміÑÑ‚ÑŒ "Я люблю музику". + +/manage/profile/index.bml.interest.line4=ГÐРÐИЙ приклад: музика, інтернет, дівчата, мандрувати, читати, ходити пішки + +/manage/profile/index.bml.interest.line5=ПОГÐÐИЙ приклад: Мені подобаєтьÑÑ Ñлухати музику, читати гарні книжки та веÑело проводити Ñ‡Ð°Ñ Ñ–Ð· друзÑми. Про це краще напиÑати в Ñ–Ñторії про Ñебе. + +/manage/profile/index.bml.intro1=Тут ви можете заповнити Ñвою Ñторінку профілю. Ви не зобов'Ñзані показувати вÑÑŽ інформацію про Ñебе будь-кому — проÑто змініть відповідний параметр. Можливо, ви також вирішите змінити Ñвої параметри ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ переглÑду. + +/manage/profile/index.bml.location=Показувати міÑце Ñвого Ð·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ð¼ кориÑтувачам + +/manage/profile/index.bml.mutualfriends=Показувати друзів, Ñкі також додали Ð²Ð°Ñ Ñƒ друзі + +/manage/profile/index.bml.name=Ваше ім'Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ Ñƒ вашому профілі та в результатах пошуку + +/manage/profile/index.bml.optional=не обов'Ñзково + +/manage/profile/index.bml.pop_interests.heading=Це деÑкі з найпопулÑрніших зацікавлень. Оберіть бажані позначивши Ñ—Ñ…. + +/manage/profile/index.bml.pop_interests1.v2=тварини + +/manage/profile/index.bml.pop_interests1.v3=акторÑтво + +/manage/profile/index.bml.pop_interests1.v4=аÑÑ‚Ñ€Ð¾Ð»Ð¾Ð³Ñ–Ñ + +/manage/profile/index.bml.pop_interests10.v2=мода + +/manage/profile/index.bml.pop_interests10.v3=їжа + +/manage/profile/index.bml.pop_interests10.v4=Ñадівництво + +/manage/profile/index.bml.pop_interests11.v2=друзі + +/manage/profile/index.bml.pop_interests11.v3=гітара + +/manage/profile/index.bml.pop_interests11.v4=Інтернет + +/manage/profile/index.bml.pop_interests12.v2=Ñ–ÑÑ‚Ð¾Ñ€Ñ–Ñ + +/manage/profile/index.bml.pop_interests12.v3=інтернет + +/manage/profile/index.bml.pop_interests12.v4=коÑметика + +/manage/profile/index.bml.pop_interests13.v2=інтернет + +/manage/profile/index.bml.pop_interests13.v3=література + +/manage/profile/index.bml.pop_interests13.v4=манга + +/manage/profile/index.bml.pop_interests14.v2=кіно + +/manage/profile/index.bml.pop_interests14.v3=фільми + +/manage/profile/index.bml.pop_interests14.v4=мотоцикли + +/manage/profile/index.bml.pop_interests15.v2=музика + +/manage/profile/index.bml.pop_interests15.v3=філоÑÐ¾Ñ„Ñ–Ñ + +/manage/profile/index.bml.pop_interests15.v4=Ð¶Ð¸Ð²Ð¾Ð¿Ð¸Ñ + +/manage/profile/index.bml.pop_interests16.v2=фотографії + +/manage/profile/index.bml.pop_interests16.v3=Ð¿Ð¾ÐµÐ·Ñ–Ñ + +/manage/profile/index.bml.pop_interests16.v4=Фотошоп + +/manage/profile/index.bml.pop_interests17.v2=Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/manage/profile/index.bml.pop_interests17.v3=романтика + +/manage/profile/index.bml.pop_interests17.v4=політика + +/manage/profile/index.bml.pop_interests18.v2=Ñноубордінґ + +/manage/profile/index.bml.pop_interests18.v3=літо + +/manage/profile/index.bml.pop_interests18.v4=пÑÐ¸Ñ…Ð¾Ð»Ð¾Ð³Ñ–Ñ + +/manage/profile/index.bml.pop_interests19.v2=мандрівки + +/manage/profile/index.bml.pop_interests19.v3=Ñ‚Ð°Ñ‚ÑƒÑŽÐ²Ð°Ð½Ð½Ñ + +/manage/profile/index.bml.pop_interests19.v4=покупки + +/manage/profile/index.bml.pop_interests2.v2=аніме + +/manage/profile/index.bml.pop_interests2.v3=арт + +/manage/profile/index.bml.pop_interests2.v4=музичні гурти + +/manage/profile/index.bml.pop_interests20.v2=комп’ютерні ігри + +/manage/profile/index.bml.pop_interests20.v3=відео-ігри + +/manage/profile/index.bml.pop_interests20.v4=Ñпорт + +/manage/profile/index.bml.pop_interests21.v2=пиÑÐ°Ð½Ð½Ñ + +/manage/profile/index.bml.pop_interests21.v3=Ð¿Ñ€Ð°Ñ†Ñ + +/manage/profile/index.bml.pop_interests21.v4=театр + +/manage/profile/index.bml.pop_interests3.v2=арт + +/manage/profile/index.bml.pop_interests3.v3=книги + +/manage/profile/index.bml.pop_interests3.v4=плÑжі + +/manage/profile/index.bml.pop_interests4.v2=книги + +/manage/profile/index.bml.pop_interests4.v3=мультфільми + +/manage/profile/index.bml.pop_interests4.v4=автомобілі + +/manage/profile/index.bml.pop_interests5.v2=комп’ютери + +/manage/profile/index.bml.pop_interests5.v3=кофе + +/manage/profile/index.bml.pop_interests5.v4=комп’ютери + +/manage/profile/index.bml.pop_interests6.v2=танці + +/manage/profile/index.bml.pop_interests6.v3=концерти + +/manage/profile/index.bml.pop_interests6.v4=куховарÑтво + +/manage/profile/index.bml.pop_interests7.v2=мрії + +/manage/profile/index.bml.pop_interests7.v3=Ñобаки + +/manage/profile/index.bml.pop_interests7.v4=цифрове миÑтецтво + +/manage/profile/index.bml.pop_interests8.v2=емоції + +/manage/profile/index.bml.pop_interests8.v3=Ð¼Ð°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ + +/manage/profile/index.bml.pop_interests9.v2=фантазії + +/manage/profile/index.bml.pop_interests9.v3=родина + +/manage/profile/index.bml.pop_interests9.v4=ігри + +/manage/profile/index.bml.save_button=Зберегти зміни + +/manage/profile/index.bml.schools=Показувати ваші навчальні заклади + +/manage/profile/index.bml.schools.manage=Керувати навчальними закладами + +/manage/profile/index.bml.section.bio=Про Ñебе + +/manage/profile/index.bml.section.contact=Контактна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/manage/profile/index.bml.section.friends=Друзі + +/manage/profile/index.bml.section.id=Ð†Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ + +/manage/profile/index.bml.section.interests=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.section.location=МіÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.section.textmsg=ТекÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/manage/profile/index.bml.section.theme=Тема Ñпільноти + +/manage/profile/index.bml.section.web=Веб-Ñторінка + +/manage/profile/index.bml.security.visibility.everybody=Будь-кому + +/manage/profile/index.bml.security.visibility.friends=Тільки друзÑм + +/manage/profile/index.bml.security.visibility.nobody=Ðікому + +/manage/profile/index.bml.security.visibility.regusers=ЗареєÑтрованим кориÑтувачам + +/manage/profile/index.bml.share.birthday=Показувати Ñвою дату народженнÑ: + +/manage/profile/index.bml.show.birthday=Параметри Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð½Ñ Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ: + +/manage/profile/index.bml.show.birthday.day=Відображати лише міÑÑць Ñ– день + +/manage/profile/index.bml.show.birthday.full=Відображати міÑÑць, день та рік + +/manage/profile/index.bml.show.birthday.nothing=Ðе відображати + +/manage/profile/index.bml.show.birthday.year=Відображати лише рік + +/manage/profile/index.bml.showljtalk=Ðе показувати це? + +/manage/profile/index.bml.state.us=Штати СШР+ +/manage/profile/index.bml.success.editpics=Редагувати юзерпики + +/manage/profile/index.bml.success.editprofile=Змінити Ñвій профіль + +/manage/profile/index.bml.success.gonext=Що ви бажаєте зробити далі? + +/manage/profile/index.bml.success.header=УÑпішно! + +/manage/profile/index.bml.success.text=Ваш профіль було оновлено. + +/manage/profile/index.bml.success.viewprofile=ПереглÑнути профіль + +/manage/profile/index.bml.theme=Коротко опишіть ÑпрÑÐ¼ÑƒÐ²Ð°Ð½Ð½Ñ Ñвоєї Ñпільноти. Воно буде відображене у результатах пошуку за інтереÑами. + +/manage/profile/index.bml.timezone.select=Оберіть Ñвій чаÑовий поÑÑ + +/manage/profile/index.bml.title=Змінити профіль + +/manage/profile/index.bml.txt.details=(докладніше) + +/manage/profile/index.bml.userpic=Це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ Ñƒ вашому профілі. Воно також предÑтавлÑтиме Ð²Ð°Ñ Ñƒ ваших запиÑах та коментарÑÑ…, поки ви не оберете інше. + +/manage/profile/index.bml.userpic.change=Змінити юзерпику за замовчуваннÑм + +/manage/profile/index.bml.userpic.none=Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñутнє + +/manage/profile/index.bml.zip.usonly=5-значний індекÑ; лише Ð´Ð»Ñ Ð¼ÐµÑˆÐºÐ°Ð½Ñ†Ñ–Ð² СШР+ +/manage/pubkey.bml.error.invalidkey=Це не виглÑдає Ñк дійÑний PGP/GPG ключ. + +/manage/pubkey.bml.error.notconfigured=Підтримка PGP не налаштована на цьому Ñайті. + +/manage/pubkey.bml.header=Ключ PGP/GPG + +/manage/pubkey.bml.info=ÐžÐ¿Ñ€Ð¸Ð»ÑŽÐ´Ð½ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ публічного ключа дозволÑÑ” іншим бачити його у вашому профілі, Ñ– ви можете надÑилати через email-шлюз підпиÑані лиÑти. ДивітьÑÑ Ð½Ð°Ñтанови за поÑиланнÑм. + +/manage/pubkey.bml.pastekey=Скопіюйте Ñвій ключ повніÑÑ‚ÑŽ (у захищеному ASCII форматі) до полÑ, розташованого нижче: + +/manage/pubkey.bml.save=Зберегти + +/manage/pubkey.bml.successhead=УÑпішно + +/manage/pubkey.bml.successtext=Ваш публічний ключ був збереженний. Ви можете переглÑнути його тут. + +/manage/pubkey.bml.title=Ð’Ñтановити публічний ключ + +/manage/pubkey.bml.whatis=Ðе знаєте, що таке публічний ключ? Потрібна допомога щодо екÑпорту вашого ключа? Прочитайте більше про PGP та GPG. + +/manage/settings/index.bml.adultcontentflag=Цей журнал міÑтить: + +/manage/settings/index.bml.adultcontentflag.select.concepts=Матеріали Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/manage/settings/index.bml.adultcontentflag.select.explicit=Відвертий контент Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/manage/settings/index.bml.adultcontentflag.select.none=Ðе міÑтить матеріалів Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/manage/settings/index.bml.adultcontentflag.text=Це глобальні Ð½Ð°Ð»Ð°Ñ‰Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ. Матеріали відверто дороÑлого зміÑту будуть недоÑтупні кориÑтувачам,Ñким ще не виповнилоÑÑŒ [[explicitage]].ПроÑто Ñ–Ð½Ð¾Ñ„Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñилих буде недоÑтупна кориÑтувачам до [[conceptsage]] + +/manage/settings/index.bml.bdayreminder=Отримувати поштою Ð½Ð°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… друзів + +/manage/settings/index.bml.bdayreminder.note=ЗауваженнÑ: зараз Ñ†Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ заборонена, але, можливо, в майбутньому вона запрацює знову. + +/manage/settings/index.bml.commentpage=ПереглÑдати Ñторінки коментарів у Ñтилі Ñвого влаÑного журналу + +/manage/settings/index.bml.commentpage.text=Коли ви перейдете за поÑиланнÑм до коментарів зі Ñвоєї Ñтрічки друзів, ви зможете переглÑдати ту Ñторінку коментарів у Ñтилі Ñвого влаÑного журналу. + +/manage/settings/index.bml.contextualhover=Показувати контекÑтне меню при наведенні + +/manage/settings/index.bml.contextualhover.text=КонтекÑтне мені з’ÑвлÑєтьÑÑ Ð¿Ñ€Ð¸ наведенні вказівника мишки на значок кориÑтувача чи юзерпику. + +/manage/settings/index.bml.finished.save_button=Зберегти зміни + +/manage/settings/index.bml.fn.adultcontentflag=Матеріали Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/manage/settings/index.bml.fn.bdayreminder=ÐÐ°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/manage/settings/index.bml.fn.commentpage=Сторінки коментарів + +/manage/settings/index.bml.fn.contextualhover=КонтекÑтне меню при наведенні + +/manage/settings/index.bml.fn.gettingstarted=Модуль "Перші кроки" + +/manage/settings/index.bml.fn.graphicpreviews=Попередній переглÑд графіки + +/manage/settings/index.bml.fn.imageplace=Замінники зображень + +/manage/settings/index.bml.fn.jabber=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð² мережі + +/manage/settings/index.bml.fn.language=Мова + +/manage/settings/index.bml.fn.ljnews=Ðовини LiveJournal + +/manage/settings/index.bml.fn.minsecurity=ДоÑтупніÑÑ‚ÑŒ запиÑу + +/manage/settings/index.bml.fn.navstrip=Ðавігаційний Ñ€Ñдок + +/manage/settings/index.bml.fn.safesearch=Фільтр безпечного пошуку + +/manage/settings/index.bml.fn.scheme=Дизайн + +/manage/settings/index.bml.fn.searchincl=Ð’ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ñƒ пошук + +/manage/settings/index.bml.fn.viewingadult=Ви дивитеÑÑŒ матеріали Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих + +/manage/settings/index.bml.gettingstarted=Показувати модуль "Перші кроки" + +/manage/settings/index.bml.gettingstarted.text=Модуль "Перші кроки" відображаєтÑÑŒÑ Ð½Ð° початковій Ñторінці та Ñторінці підтвердженнÑ, поки уÑÑ– необхідні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ будуть завершені. + +/manage/settings/index.bml.gettingstarted.text.completed=ОÑкільки ви завершили уÑÑ– необхідні налаштуваннÑ, модуль "Перші кроки" не відображатиметьÑÑ. + +/manage/settings/index.bml.graphicpreviews.desc=Дозволити переглÑд графіки за зовнішніми поÑиланнÑми у Ñвоєму журналі + +/manage/settings/index.bml.graphicpreviews.note=Дозволити в межах Ñвого журналу попередній переглÑд зовншніх поÑилань та зображень у виринаючому вікні, коли наводите на них вказівником мишки. + +/manage/settings/index.bml.imagelinks.size.custom=Додатково: викориÑтовувати замінники Ð´Ð»Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ більших за [[width]]x[[height]] + +/manage/settings/index.bml.imageplace=ВикориÑтовувати замінники зображень Ð´Ð»Ñ + +/manage/settings/index.bml.imageplace.all=вÑÑ–Ñ… зображень + +/manage/settings/index.bml.imageplace.large=великих зображень (більших за 640x480) + +/manage/settings/index.bml.imageplace.medium=Ñередніх зображень (більших за 320x240) + +/manage/settings/index.bml.imageplace.none=нічого (показати вÑÑ– зображеннÑ) + +/manage/settings/index.bml.imageplace.text=Замінники заміÑÑ‚ÑŒ зображень вÑтавлÑÑŽÑ‚ÑŒ поÑиланнÑ; це кориÑно Ñкщо ви переглÑдаєте Ñайт на роботі або Ñкщо у Ð²Ð°Ñ Ð¿Ð¾Ð²Ñ–Ð»ÑŒÐ½Ðµ з'єднаннÑ. + +/manage/settings/index.bml.intro=Ðалаштуйте Ñвої параметри переглÑду, повідомлень та додаткові параметри безпеки. + +/manage/settings/index.bml.jabber=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð² мережі можуть бачити: [[jabbertitle]] + +/manage/settings/index.bml.jabber.text=Ваш ÑÑ‚Ð°Ñ‚ÑƒÑ Ð² мережі може бути показаний іншим людÑм, коли ви увійшли в мережу з будь-Ñкої Jabber-програми, викориÑтовуючи Ñвоє Ñ–Ð¼â€™Ñ Ñƒ [[jabbertitle]]. + +/manage/settings/index.bml.language=Оберіть Ñвою мову: + +/manage/settings/index.bml.ljnews=Отримувати по email копії новинних запиÑів LiveJournal + +/manage/settings/index.bml.minsecurity=КонфіденційніÑÑ‚ÑŒ нових запиÑів за замовчуваннÑм: + +/manage/settings/index.bml.minsecurity.friends=Лише Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/manage/settings/index.bml.minsecurity.members=Лише Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників + +/manage/settings/index.bml.minsecurity.private=Лише Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ (оÑобиÑте) + +/manage/settings/index.bml.minsecurity.public=Ð”Ð»Ñ ÑƒÑÑ–Ñ… (загальнодоÑтупно) + +/manage/settings/index.bml.minsecurity.text=Це Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ” Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ уÑÑ–Ñ… наÑтупних запиÑів, Ñкщо тільки ви не вибрали більш жорÑткі налаштуваннÑ. Ð’ такому випадку, будуть заÑтоÑовані більш жорÑткі правила. + +/manage/settings/index.bml.navstrip=Ðавігаційний Ñ€Ñдок - це маленька панель, що відображаєтьÑÑ Ð²Ð³Ð¾Ñ€Ñ– вашого журналу/Ñпільноти, а також під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду інших журналів чи Ñпільнот. Вона дозволÑÑ”: + +/manage/settings/index.bml.navstrip.choose=Оберіть колір навігаційного Ñ€Ñдка + +/manage/settings/index.bml.navstrip.choose.dark=Темно-Ñірий + +/manage/settings/index.bml.navstrip.choose.light=Світло-Ñірий + +/manage/settings/index.bml.navstrip.customcolors=Щоб викориÑтовувати оÑобливі кольори у Ñтилі Ñвого журналу, увімкніть параметр "Кольори навігаційного Ñ€Ñдка" на вкладці ОÑобливі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð´Ñ–Ð»Ñƒ "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ". + +/manage/settings/index.bml.navstrip.list1=Швидкі поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ вашого журналу, напиÑÐ°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів та Ñтрічку друзів + +/manage/settings/index.bml.navstrip.list2=Параметри, що залежать від Ñторінки, на Ñкій ви знаходитеÑÑ, наприклад, фільтри Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñтрічки друзів + +/manage/settings/index.bml.navstrip.list3=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотою, тощо + +/manage/settings/index.bml.navstrip.options=Параметри Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ð¹Ð½Ð¾Ð³Ð¾ Ñ€Ñдка: + +/manage/settings/index.bml.navstrip.options.see=Завжди показувати навігаційний Ñ€Ñдок при переглÑді будь-Ñкого журналу чи Ñпільноти + +/manage/settings/index.bml.navstrip.options.show=Завжди показувати навігаційний Ñ€Ñдок будь-кому, хто переглÑдає мій журнал або Ñпільноту + +/manage/settings/index.bml.safesearch=Цей фільтр заблокує будь Ñкі матеріали, призначені Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих з пошуку + +/manage/settings/index.bml.safesearch.select.none=Ðе фільтрувати результати пошуку + +/manage/settings/index.bml.safesearch2.select.concepts=ВкориÑтовувати жорÑтке Ñ„Ñ–Ð»ÑŒÑ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ (фільтрувати вÑÑ– матеріали Ð´Ð»Ñ Ð´Ð¾Ñ€Ð¾Ñлих та образливі запиÑи) + +/manage/settings/index.bml.searchincl=Мінімізувати Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу до пошукових ÑиÑтем + +/manage/settings/index.bml.searchincl.text=Ми можемо "попроÑити" пошукові машини не включати ваші запиÑи в їхні результати пошуку. Ðе вÑÑ– машини це роблÑÑ‚ÑŒ; Ñкщо ви не хочете, щоб ваші запиÑи у журналі відображалиÑÑ Ñƒ результатах пошуку, переÑвідчитьÑÑ, що зробили Ñ—Ñ… приватними чи "тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²". + +/manage/settings/index.bml.section.notify=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ LJ + +/manage/settings/index.bml.section.privacy=Додаткові параметри безпеки + +/manage/settings/index.bml.section.viewing=Параметри переглÑду + +/manage/settings/index.bml.security.visibility.everybody=Ð’ÑÑ– + +/manage/settings/index.bml.security.visibility.friends=Тільки друзі + +/manage/settings/index.bml.security.visibility.nobody=Ðіхто + +/manage/settings/index.bml.success.header=УÑпішно! + +/manage/settings/index.bml.success.next=Що робитимемо далі? + +/manage/settings/index.bml.success.next.customize=Ðалаштувати Ñвій журнал + +/manage/settings/index.bml.success.next.friends=Читати Ñвою Ñтрічку друзів + +/manage/settings/index.bml.success.next.home=ПовернутиÑÑŒ на початкову Ñторінку + +/manage/settings/index.bml.success.next.viewing=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду + +/manage/settings/index.bml.success.text=Ваші параметри переглÑду було збережено + +/manage/settings/index.bml.title=Параметри переглÑду + +/manage/settings/index.bml.weblogscom=ПовідомлÑти Weblogs.com, коли Ñ Ñтворюю нові загальнодоÑтупні запиÑи + +/manage/settings/index.bml.weblogscom.text=Weblogs.com, Ñлужба VeriSign, Ñ” ping-Ñервером, Ñкий автоматично Ñповіщає учаÑників, коли новий Ð·Ð°Ð¿Ð¸Ñ Ð¿ÑƒÐ±Ð»Ñ–ÐºÑƒÑ”Ñ‚ÑŒÑÑ Ð½Ð° Ñайті або у блозі, що дозволÑÑ” Ñтежити за поновленнÑми журналу значно більшій кількоÑÑ‚Ñ– людей. + +/manage/siteopts.bml.btn.lang=Переключити мову + +/manage/siteopts.bml.btn.scheme=Переключити Ñхему + +/manage/siteopts.bml.head.lang=Оберіть Ñвою мову + +/manage/siteopts.bml.head.scheme=Оберіть Ñхему, Ñка вам до вподоби + +/manage/siteopts.bml.scheme.preview=[Попередній переглÑд Ñхеми [[title]] ] + +/manage/siteopts.bml.title=Параметри переглÑду + +/manage/subscriptions/comments.bml.error.threads=Ваш тип рахунку не дозволÑÑ” переглÑдати гілки. Покращіть рахунок до платного , щоб підпиÑатиÑÑ Ð½Ð° гілки чи переглÑдати веÑÑŒ запиÑ, натиÑнувши нижче + +/manage/subscriptions/index.bml.title=Керувати налаштуваннÑми повідомлень + +/manage/tags.bml.addnew=Додавайте нові теґи тут! + +/manage/tags.bml.button.delete=Видалити обрані теґи + +/manage/tags.bml.button.rename=Перейменувати + +/manage/tags.bml.button.save=Зберегти зміни + +/manage/tags.bml.button.show=Показати запиÑи журналу + +/manage/tags.bml.confirm.delete=Чи ви впевнені у бажанні видалити обрані теґи? Ð¦Ñ Ð´Ñ–Ñ Ñ” незворотньою. + +/manage/tags.bml.error.invalidsettings=Обрано недопуÑтимі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ теґів + +/manage/tags.bml.hint.create=Ви можете Ñтворити кілька теґів відокремлюючи Ñ—Ñ… комами. + +/manage/tags.bml.hint.delete=Видалити вÑÑ– поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ обраних теґів. + +/manage/tags.bml.hint.entries=Показати запиÑи журналу з обраними теґами. + +/manage/tags.bml.hint.rename=Змінити назву теґу. + +/manage/tags.bml.intro=КориÑтуйтеÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою, щоб переглÑдати та змінювати Ñвої теґи. + +/manage/tags.bml.label.settings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÒ‘Ñ–Ð² + +/manage/tags.bml.label.tags=ВлаÑтивоÑти теґа + +/manage/tags.bml.label.yours=Ваші теґи + +/manage/tags.bml.none=Ви ще не Ñтворили жодних теґів. + +/manage/tags.bml.setting.desc.add=Хто може додавати Ñ–Ñнуючі теґи до запиÑів? + +/manage/tags.bml.setting.desc.control=Хто може Ñтворювати нові теґи Ñ– додавати/вилучати теґи запиÑів? + +/manage/tags.bml.setting.friends=Тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/manage/tags.bml.setting.maintainers=Тільки Ð´Ð»Ñ Ð´Ð¾Ð³Ð»Ñдачів + +/manage/tags.bml.setting.members=Тільки Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників + +/manage/tags.bml.setting.private=Тільки Ð´Ð»Ñ Ð²Ð°Ñ + +/manage/tags.bml.setting.public=Ð”Ð»Ñ Ð±ÑƒÐ´ÑŒ-кого + +/manage/tags.bml.sort.a=Ñортувати: за абеткою або за викориÑтаннÑм + +/manage/tags.bml.sort.b=Ñортувати: за абеткою або за викориÑтаннÑм + +/manage/tags.bml.title=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÒ‘Ð°Ð¼Ð¸ + +/manage/tags.bml.title2=Керувати тегами + +/manage/voicepost.bml.delete=Видалити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/voicepost.bml.deleted=Ви повинні ввеÑти та зберегти Ñвої Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ тим, Ñк отримати змогу кориÑтуватиÑÑ Ð³Ð¾Ð»Ð¾Ñовими повідомленнÑми. Ви можете змінювати ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð² будь-Ñкий момент. + +/manage/voicepost.bml.deleted.header=Ваші голоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ видалені. + +/manage/voicepost.bml.error.inuse=Ðеправильний ПІÐ-код, Ñпробуйте інший. + +/manage/voicepost.bml.error.phone.length=Ваш телефонний номер повинен міÑтити щонайменше 10 цифр. + +/manage/voicepost.bml.error.pin=Ваш ПІÐ-код повинен бути цифровим. + +/manage/voicepost.bml.error.pin.1234=Ваш ПІÐ-код не може бути 1234. + +/manage/voicepost.bml.error.transcription=Помилка під Ñ‡Ð°Ñ Ñ€Ð¾Ð·Ð¿Ñ–Ð·Ð½Ð°Ð²Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ друзів. + +/manage/voicepost.bml.format=Формат голоÑового повідомленнÑ: + +/manage/voicepost.bml.intro.loggedin2<< +Перед викориÑтаннÑм голоÑових запиÑів +ви маєте вказати нижче Ñвої Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° уподобаннÑ. +ГолоÑові запиÑи доÑтупні Ð´Ð»Ñ Ð²Ð»Ð°Ñників Розширених та Платних рахунків. +. + +/manage/voicepost.bml.intro.loggedin3<< +Перед ÑтвореннÑм голоÑового запиÑу вам необхідно вказати влаÑні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° уподобаннÑ. +ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви можете Ñтворити голоÑовий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½ÑƒÐ²Ð°Ð²ÑˆÐ¸ на один з номерів доÑтупу або Ñкачавши Gizmo Project Ð´Ð»Ñ LJ Talk. МожливіÑÑ‚ÑŒ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових запиÑів доÑтупна лише влаÑникам розширених та платних рахунків. +. + +/manage/voicepost.bml.intro.loggedout2=КориÑтувачі [[sitename]] можуть увійти та змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñвоїх голоÑових повідомлень тут: + +/manage/voicepost.bml.phone=Дозволений номер телефону*: + +/manage/voicepost.bml.phone.help=Ваш авторизований номер телефону повинен мати щонайменше 10 цифр, незалежно від формату, в Ñкому він набраний. Якщо ви не бажаєте телефонувати зі Ñвого номеру, вам необхідно ввеÑти ці дані, щоб мати можливіÑÑ‚ÑŒ додавати голоÑові повідомленнÑ. + +/manage/voicepost.bml.pin=ПерÑональний Ідентифікаційний Ðомер: + +/manage/voicepost.bml.pin.help=ПІÐ-код повинен ÑкладатиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ з цифр. Рекомендовано викориÑтовувати 4-6 цифр. + +/manage/voicepost.bml.privacy2<< +* Ваш номер телефону ніколи не буде викориÑтано з іншою метою, окрім авторизації вашого дзвінка. +(ДивітьÑÑ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÑƒ конфенденційноÑÑ‚Ñ– Ð´Ð»Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ð¾Ñ— інформації.) +З Ð²Ð°Ñ ÑÑ‚ÑгуватиметьÑÑ Ð»Ð¸ÑˆÐµ Ñтандартна оплата за дзвінок на довгі відÑтані (Ñкщо така Ñ”). +. + +/manage/voicepost.bml.quickpost=Рівень безпеки при припиненні Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ + +/manage/voicepost.bml.quickpost.help=Це Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ”, що траплÑєтьÑÑ ÐºÐ¾Ð»Ð¸ ви кладете Ñлухавку або припинÑєте Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð·Ð°Ð¿Ð¸Ñу телефонного повідомленнÑ. Ви завжди маєте можливіÑÑ‚ÑŒ проÑлухати іншу чаÑтину меню та обрати різні рівні безпеки повідомленнÑ. + +/manage/voicepost.bml.save=Зберегти Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/manage/voicepost.bml.saved=Збережено + +/manage/voicepost.bml.success.moreinfo2=Ð”Ð»Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ð¾Ñ— інформації про Ð·Ð°Ð¿Ð¸Ñ Ð³Ð¾Ð»Ð¾Ñового повідомленнÑ, дивітьÑÑ Ð¯Ðº запиÑати голоÑове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ Ñвого журналу?. + +/manage/voicepost.bml.success.text2=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень збережені. Знайдіть наближчий до Ð²Ð°Ñ Ð½Ð¾Ð¼ÐµÑ€ голоÑових повідомлень. + +/manage/voicepost.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень + +/manage/voicepost.bml.transcribers=Зможуть проÑлухати: + +/manage/voicepost.bml.transcribers.help=Змінити групи друзів + +/manage/voicepost.bml.vfriendsgroup=Групи друзів Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень + +/manage/voicepost.bml.vfriendsgroup.help=Коли здійÑнюєтьÑÑ Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ð¸ можете вибрати окрему групу. Змінити групи друзів + +/meme.bml.meme.disabled=ÐдмініÑтратор Ñайту вимкнув цю можливіÑÑ‚ÑŒ + +/misc/suggest_spotlight.bml.btn.submit=ÐадіÑлати пропозицію до родзинок + +/misc/suggest_spotlight.bml.error.emptyformfields=Ви заповнили не уÑÑ– Ð¿Ð¾Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ð¸. + +/misc/suggest_spotlight.bml.error.username_invalid=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, Ñке ви ввели, не Ñ–Ñнує. + +/misc/suggest_spotlight.bml.form.desc.label=Короткий Ð¾Ð¿Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ чи Ñпільноти Ñ– чому ви вважаєте це цікавим. + +/misc/suggest_spotlight.bml.form.error.header=Помилка: + +/misc/suggest_spotlight.bml.form.error.sendfailed=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вдалоÑÑŒ надіÑлати. + +/misc/suggest_spotlight.bml.form.intro=Будь лаÑка, надішліть вашу пропозицію до родзинок [[siteabbrev]]: + +/misc/suggest_spotlight.bml.form.journal.label=КориÑтувач або Ñпільнота + +/misc/suggest_spotlight.bml.form.name.label=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача/Ðазва Ñпільноти + +/misc/suggest_spotlight.bml.form.owner.label=Чи ви Ñ” влаÑником журналу/Ñпільноти? + +/misc/suggest_spotlight.bml.form.owner.select.no=ÐÑ– + +/misc/suggest_spotlight.bml.form.owner.select.yes=Так + +/misc/suggest_spotlight.bml.form.permission.label=Якщо ми оберемо цей журнал, Ñпільноту чи Ð·Ð°Ð¿Ð¸Ñ Ñƒ ÑкоÑÑ‚Ñ– Ñтартової Ñторінки [[sitenameabbrev]] , чи дозволить влаÑник відображати знімок екрану чи адреÑу? + +/misc/suggest_spotlight.bml.form.permission.select.no=ÐÑ– + +/misc/suggest_spotlight.bml.form.permission.select.yes=Так + +/misc/suggest_spotlight.bml.intro=Родзинки [[sitenameabbrev]] знайомлÑÑ‚ÑŒ Ð²Ð°Ñ Ñ–Ð· цікавими та крутими варіантами викориÑÑ‚Ð°Ð½Ð½Ñ [[sitename]]. Знайдіть нових друзів та Ñпільноти, отримайте Ð½Ð°Ñ‚Ñ…Ð½ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸Ñтовувати [[sitenameabbrev]] по-різному, дізнайтеÑÑŒ більше про можливоÑÑ‚Ñ– [[sitenameabbrev]], Ñких ви не знали раніше, та заохочуйте ваших приÑтелів за хороші новини. + +/misc/suggest_spotlight.bml.intro.community=ПереглÑньте попередні родзинки у Ñпільноті [[commname]]. + +/misc/suggest_spotlight.bml.intro.ideal=Ідеальний кандидат до родзинок [[sitenameabbrev]]: + +/misc/suggest_spotlight.bml.intro.ideal.interesting=Будь-Ñкі журнал, Ñпільнота чи запиÑ, Ñкий цікавий вам Ñ– Ñкий, на вашу думку, зацікавить інших. + +/misc/suggest_spotlight.bml.intro.ideal.lj=ЩоÑÑŒ унікальне в [[sitenameabbrev]] + +/misc/suggest_spotlight.bml.intro.ideal.news=КориÑтувачі [[sitenameabbrev]] у новинах (хороших) + +/misc/suggest_spotlight.bml.intro.ideal.unique=КориÑтувачі [[sitenameabbrev]], Ñкі викориÑтовують Ñвій журнал чи Ñпільноту в унікальний чи неперевершений ÑпоÑіб + +/misc/suggest_spotlight.bml.success.header=УÑпішно + +/misc/suggest_spotlight.bml.success.text=Ваша Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ñ€Ð¾Ð´Ð·Ð¸Ð½ÐºÐ¸ надіÑлана. ДÑкуємо! + +/misc/suggest_spotlight.bml.title=Запропонуйте родзинку + +/modify.bml.title=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/modify_do.bml.availablestyles.disabledstyles=Вимкнуті шари: + +/modify_do.bml.availablestyles.head=ДоÑтупні Ñтилі + +/modify_do.bml.availablestyles.userstyles=Стилі кориÑтувача: + +/modify_do.bml.colortheme.about=Тут ви можете обрати кольорову тему, Ñка буде заÑтоÑована до параметрів виглÑду, що ви обрали вище. Ðбо, Ñкщо вам не подобаютьÑÑ Ð½Ð°Ð´Ð°Ð½Ñ– кольори, то визначте Ñвої! + +/modify_do.bml.colortheme.area.head=Елемент + +/modify_do.bml.colortheme.color.head1=Колір + +/modify_do.bml.colortheme.color.head2=(#rrggbb або назва) + +/modify_do.bml.colortheme.customcolors=ОÑобливі кольори + +/modify_do.bml.colortheme.defaulttheme=Тема за замовчуваннÑм + +/modify_do.bml.colortheme.head=Кольорова тема + +/modify_do.bml.domainalias.about=Якщо у Ð²Ð°Ñ Ñ” зареєÑтроване доменне ім'Ñ (або ви плануєте його зареєÑтрувати) та ви бажаєте щоб воно вказувало на ваш журнал, надрукуйте його тут: + +/modify_do.bml.domainalias.domainname=Доменне ім'Ñ: + +/modify_do.bml.domainalias.example=Ðаприклад: my-journal.com + +/modify_do.bml.domainalias.head=ПÑевдоніми доменів + +/modify_do.bml.domainalias.helptext=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾ щоб це Ñпрацювало, вам потрібно щоб DNS Ð·Ð°Ð¿Ð¸Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ домену вказував на ту ж IP-адреÑу, що Ñ– [[sitename]]. Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— інформації передивітьÑÑ Ñ†ÑŽ Ñторінку. + +/modify_do.bml.done.btn.savechanges=Зберегти зміни + +/modify_do.bml.done.head=Готово? + +/modify_do.bml.done.text=Коли закінчите, натиÑніть кнопку "Зберегти зміни", наведену нижче... + +/modify_do.bml.error.dupdomainalias=Інший кориÑтувач вже зареєÑтрувавÑÑ, викориÑтовуючи ваш домений пÑевдонім. + +/modify_do.bml.error.stylenotavailable=Один з вибраних вами Ñтилів не доÑтупний. Це, можливо, через те, що хтоÑÑŒ вилучає цей Ñтиль, або ви обрали Ñтиль, до Ñкого у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу. + +/modify_do.bml.friends.about=Це параметри щодо виглÑду вашої Ñтрічки друзів. + +/modify_do.bml.friends.head=ВиглÑд Ñторінки друзів + +/modify_do.bml.friends.opt.usesharedpic.about=Цей параметр контролює, Ñку юзерпику ви бачите у влаÑній Ñтрічці друзів, коли кориÑтувач пише до Ñпільноти. Якщо ви не поÑтавите тут позначку, то ви бачитемете юзерпику кориÑтувача, Ñкий пише. Якщо поÑтавите, то бачитемете юзерпику Ñпільноти. + +/modify_do.bml.friends.opt.usesharedpic.head=ВикориÑтовувати юзерпики Ñпільнот заміÑÑ‚ÑŒ юзерпик кориÑтувачів + +/modify_do.bml.journaloptions.about=Тут ви можете Ñтворювати індивідуальний виглÑд Ñторінок Ñвого LiveJournal. Якщо вам цікаво розібратиÑÑ Ñк воно працює, прочитайте інформацію Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Ð’ іншому випадку кориÑтуйтеÑÑ Ð±Ð°Ð·Ð¾Ð²Ð¸Ð¼Ð¸ варіантами нижче. + +/modify_do.bml.journaloptions.about2=Тут ви можете налаштувати виглÑд ваших Ñторінок [[sitename]]. Якщо ви дійÑно цікавитеÑÑ Ñк воно працює, прочитайте інформацію Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Якщо ні, ми припуÑкаємо, що Ð²Ð°Ñ Ð²Ð»Ð°ÑˆÑ‚ÑƒÑŽÑ‚ÑŒ наведені нижче базові параметри: + +/modify_do.bml.journaloptions.head=Параметри журналу + +/modify_do.bml.journalstatus.about=Якщо ви бажаєте видалити або відновити Ñвій журнал, це робитьÑÑ Ñаме тут. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви видалÑєте Ñвій журнал, у Ð²Ð°Ñ Ñ” 30 днів, щоб відновити його, Ñкщо раптом передумаєте. За 30 днів журнал буде видалено назавжди Ñ– відновити його буде вже неможливо. + +/modify_do.bml.journalstatus.head=Стан активації журналу + +/modify_do.bml.journalstatus.select.activated=Ðктивований + +/modify_do.bml.journalstatus.select.deleted=Видалений + +/modify_do.bml.journalstatus.select.head=Стан: + +/modify_do.bml.journalstatus.select.suspended=Призупинено + +/modify_do.bml.moodicons.about=Коли ви пишете до журналу, ви можете вказати Ñвій наÑтрій. Різні кориÑтувачі додали різні набори зображень наÑтроїв, Ñкими ви можете кориÑтуватиÑÑ. Ðбо ви можете обрати "(None)", Ñкщо не бажаєте бачити ÑкеÑÑŒ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñвого наÑтрою (або ви можете взагалі не кориÑтуватиÑÑ Ñ‚ÐµÐ¼Ð°Ð¼Ð¸ наÑтроїв).

    Може ви бажаєте Ñтворити влаÑну тему наÑтроїв?

    + +/modify_do.bml.moodicons.head=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ñтроїв + +/modify_do.bml.moodicons.opt.forcefriends.about=ВикориÑтовувати цю тему наÑтроїв Ð´Ð»Ñ Ð²ÑÑ–Ñ… друзів у вашій Ñтрічці друзів + +/modify_do.bml.moodicons.personal=ПерÑональні Ñхеми: + +/modify_do.bml.moodicons.preview=переглÑнути + +/modify_do.bml.moodicons.select=Оберіть набір зображень наÑтроїв: + +/modify_do.bml.overrides.about=Якщо ви задоволені варіантами Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð»Ð¾ÐºÑ–Ð², що наведені вище, у вашому журналі, ви можете пропуÑтити цю чаÑтину. Це Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб наÑтроїти дуже Ñпецифічні моменти у розташуванні блоків на Ñторінці. ДивітьÑÑ Ð©Ð¾ таке коди перекриттÑ? Як вони працюють? Ð´Ð»Ñ Ð·Ð°Ð³Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації та завітайте у розділ Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² за детальною інформацією. Зауважте також, що коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð²Ð¿Ð»Ð¸Ð²Ð°ÑŽÑ‚ÑŒ лише на кілька речей у дизайні Ñторінок. Якщо ви хочете змінити вÑе, ви маєте Ñтворити оÑобиÑтий Ñтиль. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ð³Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ уÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð¹Ñ‚Ðµ Як Ñтворити оÑобливий Ñтиль Ñторінок? + +/modify_do.bml.overrides.about2=Якщо ви цілком задоволені параметрами вашої Ñхеми, ви можете проігнорувати цей розділ. Його призначено Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпецифічних Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— Ñхеми речей. ДивітьÑÑ FAQ Що таке коди перекриттÑ? Як вони працюють? (Ð´Ð»Ñ Ð·Ð°Ð³Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ уÑвленнÑ) та завітайте до розділу Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð², Ñкщо хочете дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ. Також зауважте, що коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ змінити тільки один чи два параметри Ñтилю. Якщо ви бажаєте змінити уÑе, вам треба Ñтворити Ñвій влаÑний Ñтиль. Ð”Ð»Ñ Ð¾Ð³Ð»Ñду, Ñк Ñаме це зробити, дивітьÑÑ FAQ Як мені зробити оÑобливий Ñтиль S1? + +/modify_do.bml.overrides.box.head=Коди перекриттÑ: + +/modify_do.bml.overrides.head=Коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñтилів + +/modify_do.bml.overrides.note=Зауважте, що не вÑÑ– змінні можуть бути змінені за допомогою кодів перекриттÑ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації дивітьÑÑ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–ÑŽ.
    Також зверніть увагу, що Ñкщо ви намагатиметеÑÑŒ редагувати влаÑні коди Ð¿ÐµÑ€ÐµÐºÑ€Ñ‚Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° викориÑтаєте теґ, Ñкий не дозволений у заголовку документа, Ñк то – such as <DIV>, <SPAN>, <IMG>, тощо, то ці теґи буде пропущено. Єдині HTML елементи, що можуть викориÑтовуватиÑÑ Ñƒ таких кодах перекриттÑ, Ñ” елементи, що допуÑкаютьÑÑ Ñтандартами HTML Ð´Ð»Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ° документа. Тобто <title>, <base>, <style>, <link>, та <meta>. + +/modify_do.bml.overrides.note2<< +Зверніть увагу, що коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ бути заÑтоÑовані не до вÑÑ–Ñ… змінних Ñтилю. ДивітьÑÑ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–ÑŽ Ð´Ð»Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації.
    +Крім того, коли ви редагуєте коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ– викориÑтовуєте теґи, не дозволені Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ñƒ заголовку документа – такі Ñк <div>, <span>, <img> та багато інших – ці теґи будуть проігноровані. Ð’ коді Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ *_HEAD дозволÑÑŽÑ‚ÑŒÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ñ‚Ñ– теґи, Ñкі дозволÑÑŽÑ‚ÑŒÑÑ Ð² заголовку звичайного HTML-документа. Це <title>, +<base>, <style>, <link> та <meta>. +. + +/modify_do.bml.overrides.warning=ЦЕ ÐЕ ТЕ МІСЦЕ, ДЕ ВИ ПИШЕТЕ ДО ЖУРÐÐЛУ!!! + +/modify_do.bml.pagelayoutstyle.about=Ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽÑŽÑ‚ÑŒ, Ñк виглÑдатиме ваш журнал на екрані. + +/modify_do.bml.pagelayoutstyle.head=Стиль виглÑду Ñторінок + +/modify_do.bml.pagelayoutstyle.warning=Ваш тип рахунку дозволÑÑ” вам обирати тільки з маленької кількоÑÑ‚Ñ– готових Ñтилів. + +/modify_do.bml.success.head=УÑпішно + +/modify_do.bml.success.text2=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу було оновлено. Ви можете подивитиÑÑ Ñвій журнал тут. + +/moodlist.bml.back2=Теми ÐаÑтрою + +/moodlist.bml.btn.switch=Перемкнути + +/moodlist.bml.btn.view=ПереглÑнути + +/moodlist.bml.error.cantviewtheme=У Ð²Ð°Ñ Ñ” дозвіл переглÑдати лише публічні теми наÑтрою або теми кориÑтувачів з параметром "ownerid". + +/moodlist.bml.moodname.fromparent=(материнÑький) + +/moodlist.bml.moodname.nopicfortheme=(немає Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‚ÐµÐ¼Ð¸ #[[id]]) + +/moodlist.bml.moods.header=Попередній переглÑд тем наÑтроїв + +/moodlist.bml.moods.howtochange=ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду нижченаведених параметрів, ви маєте перейти до розділу "ВиглÑд журналу" та обрати бажану тему наÑтроїв. + +/moodlist.bml.moods.intro=Це приклади тем наÑтроїв у LiveJournal. Ви можете відобразити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ñтрою обравши наÑтрій з меню при Ñтворенні запиÑу в журналі. Платні та Розширені рахунки також можуть Ñтворити оÑобливі теми наÑтроїв. + +/moodlist.bml.nav.viewall=ПереглÑнути Ð’ÑÑ– + +/moodlist.bml.specialthemes.header=Підтримувані теми наÑтрою + +/moodlist.bml.title=ÐаÑтрої [[sitename]] + +/moodlist.bml.view.table=ПереглÑнути цю тему у виглÑді таблиці. + +/moodlist.bml.view.tree=ПереглÑнути цю тему у виглÑді дерева ієрархії. + +/multisearch.bml.formaterror=Помилка формату + +/multisearch.bml.noaddress.text=Ðе введено e-mail адреÑу. + +/multisearch.bml.noaddress.title=Ðемає адреÑи + +/multisearch.bml.nofaqsearch.text=Ви не ввели термін, щоб шукати у FAQ. + +/multisearch.bml.nofaqsearch.title=Ðемає терміну Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ у FAQ + +/multisearch.bml.nointerest.text=Ðе введено зацікавленнÑ. + +/multisearch.bml.nointerest.title=Ðемає Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/multisearch.bml.nomatch.text=Ð”Ð»Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ… вами критеріїв результатів не було. + +/multisearch.bml.nomatch.title=Ðемає збігів + +/multisearch.bml.region.bodytext2<< +Ви можете шукати за регіоном кориÑтуючиÑÑŒ одним з нижченаведених форматів: +
      +
    • Країна
    • +
    • МіÑто *
    • +
    • МіÑто, Штат *
    • +
    • Штат, Країна
    • +
    • МіÑто, Штат (ОблаÑÑ‚ÑŒ), Країна
    • +
    +Примітки: +
      +
    • * при пошуку тільки за міÑтом або за міÑтом та штатом за умовчаннÑм викориÑтовуєтьÑÑ ÐºÑ€Ð°Ñ—Ð½Ð° Сполучені Штати.
    • +
    • Ð”Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ за країною можна вказувати Ñ—Ñ— повну назву або лише код, що ÑкладаєтьÑÑ Ð· двох літер
    • +
    +Якщо ви бажаєте ÑкориÑтатиÑÑ Ñ–Ð½ÑˆÐ¸Ð¼Ð¸ типами пошуку, перейдіть до пошукового каталогу. +. + +/multisearch.bml.region.head=Шукати за регіоном + +/newuser.bml.title=ЛаÑкаво проÑимо до [[sitename]] + +/paidaccounts/apply.bml.about.header=Про + +/paidaccounts/apply.bml.about.text=Ð¦Ñ Ñторінка дозволÑÑ” заÑтоÑувати код оплати до Ñ–Ñнуюючого рахунку. + +/paidaccounts/apply.bml.btn.apply=ЗаÑтоÑувати + +/paidaccounts/apply.bml.error.alreadyapplied=Ви вже заÑтоÑували цю оплату. + +/paidaccounts/apply.bml.error.alreadypermapplyingpaid=Ви вже маєте поÑтійний рахунок, тож заÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ [[nummonths]] [[?nummonths|додаткового міÑÑцÑ|додаткових міÑцÑців]] нічого не даÑÑ‚ÑŒ. + +/paidaccounts/apply.bml.error.alreadypermapplyingperm=Ви вже маєте поÑтійний рахунок, тож заÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ поÑтійного рахунку нічого не даÑÑ‚ÑŒ. + +/paidaccounts/apply.bml.error.codehasnopaidtime=Введений код не має Ñплаченого чаÑу. + +/paidaccounts/apply.bml.error.invalidcode=Ðевірний код. + +/paidaccounts/apply.bml.error.invaliduser=Ðеправильне Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/paidaccounts/apply.bml.error.notloggedin=Ви не увійшли до LiveJournal. Якщо ви вже маєте рахунок, то Ñпочатку увійдіть. Ð’ іншому випадку Ñтворіть рахунок, викориÑтавши Ñвій код оплати, піÑÐ»Ñ Ñ‡Ð¾Ð³Ð¾ цей код буде автоматично заÑтоÑовано до щойно Ñтвореного рахунку. + +/paidaccounts/apply.bml.error.somebodyelseapplied=ХтоÑÑŒ уже викориÑтав цей код. + +/paidaccounts/apply.bml.input.code=Код: + +/paidaccounts/apply.bml.input.rcpt=Отримувач: + +/paidaccounts/apply.bml.paymentcode.header=Код оплати + +/paidaccounts/apply.bml.paymentcode.text=Введіть код оплати, щоб заÑтоÑувати його до рахунку [[user]]. + +/paidaccounts/apply.bml.success.header=УÑпішно + +/paidaccounts/apply.bml.success.paid=До вашого рахунку додано [[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] Ñплаченого чаÑу. + +/paidaccounts/apply.bml.success.perm=Відтепер ви маєте поÑтійний рахунок. + +/paidaccounts/apply.bml.title=ЗаÑтоÑувати код + +/paidaccounts/friends.bml.buygift=купити подарунок + +/paidaccounts/friends.bml.error.nofriends=Ðаразі ви не маєте друзів у LiveJournal, тож ми нічого не можемо вам порадити. + +/paidaccounts/friends.bml.error.notloggedin=Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду Ñторінки вам необхідно Ñпочатку увійти. + +/paidaccounts/friends.bml.expiringsoon.header=Ðезабаром минає + +/paidaccounts/friends.bml.expiringsoon.text=Ці друзі мають платні рахунки, але їхній термін незабаром Ñпливає. + +/paidaccounts/friends.bml.freeusers.header=Базові та Розширені рахунки + +/paidaccounts/friends.bml.freeusers.text=Ці друзі, напевно, зрадіють платному рахунку. + +/paidaccounts/friends.bml.givelj.header=Зроби подарунок з LiveJournal + +/paidaccounts/friends.bml.givelj.text=Шукаєш проÑтий подарунок? Придбай платний рахунок Ð´Ð»Ñ ÐºÐ¾Ð³Ð¾ÑÑŒ із ÑпиÑку Ñвоїх друзів! + +/paidaccounts/friends.bml.otherfriends.header=Решта друзів + +/paidaccounts/friends.bml.otherfriends.text=Ці друзі мають платні рахунки, Ñкі ще тривалий Ñ‡Ð°Ñ Ð·Ð°Ð»Ð¸ÑˆÐ°Ñ‚ÑŒÑÑ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸. (Враховуючи й чаÑ, необхідний Ð´Ð»Ñ Ð´Ð¾Ñтавки замовлених подарунків.) + +/paidaccounts/friends.bml.title=Купи Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²! + +/paidaccounts/index.bml.costs.header=Ðу, то Ñкільки воно коштує? + +/paidaccounts/index.bml.costs.rates=Ціни наÑтупні: + +/paidaccounts/index.bml.costs.rates.amount.header=Сума + +/paidaccounts/index.bml.costs.rates.btn.getpaid=Отримати платний рахунок + +/paidaccounts/index.bml.costs.rates.btn.order=Замовити + +/paidaccounts/index.bml.costs.rates.onlyautomatic=Ці ціни доÑтупні лише Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків з автоматичною оплатою. Платний рахунок без автоматичної оплати коштує $25 за один рік. Платний рахунок на один міÑÑць Ñ” доÑтупним лише через автоматичні платежі. + +/paidaccounts/index.bml.costs.rates.time.header=Ð§Ð°Ñ + +/paidaccounts/index.bml.features.descs=ОÑÑŒ деÑкі найпопулÑрніші можливоÑÑ‚Ñ– платного рахунку: + +/paidaccounts/index.bml.features.descs.cust.header=Стилі журналу, Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° Ð²Ð±ÑƒÐ´Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ + +/paidaccounts/index.bml.features.descs.cust.text=Платні кориÑтувачі можуть поÑлуговуватиÑÑ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¼Ð¸ ÑтилÑми журналу або ж Ñтворювати влаÑні Ñтилі, не вдаючиÑÑŒ до Ñтандартних шаблонів LiveJournal. Також вони можуть легко додати журнал на Ñвій веб-Ñайт. + +/paidaccounts/index.bml.features.descs.directory.header=Розширений пошук + +/paidaccounts/index.bml.features.descs.directory.text=Платні кориÑтувачі мають доÑтуп до розширеного пошуку Ñ– можуть шукати інших кориÑтувачів за категоріÑми: регіон, вік, зацікавленнÑ, друзі чи недавно оновлені журнали. + +/paidaccounts/index.bml.features.descs.domainforwarding.header=ÐŸÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð· домену + +/paidaccounts/index.bml.features.descs.domainforwarding.text=Платні кориÑтувачі можуть вÑтановити доменне ім'Ñ Ð´Ð»Ñ Ð¿Ñ€Ñмого переходу до Ñвого журналу. + +/paidaccounts/index.bml.features.descs.emailalias.header=ПÑевдонім електронної адреÑи на [[sitename]] + +/paidaccounts/index.bml.features.descs.emailalias.text=Платні кориÑтувачі можуть вÑтановити пÑевдонім email на [[sitename]] ([[user]]@[[domain]]), з Ñкого вÑÑ Ð¿Ð¾ÑˆÑ‚Ð° буде перенаправлÑтиÑÑ Ð½Ð° Ñправжню адреÑу. Цей параметр можна увімкнути чи вимкнути будь-коли. + +/paidaccounts/index.bml.features.descs.expresslane.header=ДоÑтуп до Express Lane + +/paidaccounts/index.bml.features.descs.expresslane.text=Платні кориÑтувачі завжди знаходÑÑ‚ÑŒÑÑ Ð½Ð° express lane, тобто Ñторінки Ð´Ð»Ñ Ð½Ð¸Ñ… відкриваютьÑÑ ÑˆÐ²Ð¸Ð´ÑˆÐµ, ніж Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… кориÑтувачів. + +/paidaccounts/index.bml.features.descs.mobileposting.header=ЗапиÑи з мобільного + +/paidaccounts/index.bml.features.descs.mobileposting.text=Платні кориÑтувачі можуть додавати запиÑи з фотографіÑми та текÑтом зі Ñтільникового телефону чи інших мобільних приÑтроїв Ñ– публікувати Ñ—Ñ… безпоÑередньо в Ñвоєму журналі, а також у Ñпільнотах Ñ– галереÑÑ… ScrapBook. + +/paidaccounts/index.bml.features.descs.moodthemes.header=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñної оÑобливої теми наÑтроїв + +/paidaccounts/index.bml.features.descs.moodthemes.text=Платні кориÑтувачі можуть Ñтворити оÑобливу тему наÑтроїв, викориÑтовуючи влаÑні зображеннÑ. + +/paidaccounts/index.bml.features.descs.more.header=Більше… + +/paidaccounts/index.bml.features.descs.more.text=Прочитайте в Поширених питаннÑÑ… “Які вигоди платного рахунку?” + +/paidaccounts/index.bml.features.descs.noads.header=Без реклами + +/paidaccounts/index.bml.features.descs.noads.text=Платні учаÑники ніколи не будуть бачити жодне рекламне Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° [[sitename]], поки знаходÑÑ‚ÑŒÑÑ Ð¿Ñ–Ð´ Ñвоїм рахунком. + +/paidaccounts/index.bml.features.descs.polls.header=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/paidaccounts/index.bml.features.descs.polls.text=Платні кориÑтувачі можуть Ñтворювати влаÑні Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¹ публікувати Ñ—Ñ… у Ñвоєму журналі чи в Ñпільнотах. + +/paidaccounts/index.bml.features.descs.scrapbook.header=Хоcтинг фотографій у ScrapBook та 2 Гб диÑкового проÑтору + +/paidaccounts/index.bml.features.descs.scrapbook.text=У розпорÑдженні платних кориÑтувачів — ScrapBook (поÑлуга LiveJournal з Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ð¹) та 2 Гб диÑкового проÑтору. Тут можна розміщувати влаÑні фотографії в різноманітних галереÑÑ… та вÑтановлювати різні рівні безпеки Ð´Ð»Ñ Ñ—Ñ… переглÑду. Коли фотографію завантажено до ScrapBook, Ñтворити в журналі Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· вÑтавленим зображеннÑм дуже проÑто. + +/paidaccounts/index.bml.features.descs.textmessaging.header=ПоÑлуга передачі текÑтових повідомлень + +/paidaccounts/index.bml.features.descs.textmessaging.text=ПоÑлуга передачі текÑтових повідомлень дозволÑÑ” платним кориÑтувачам отримувати текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° Ñвій мобільний телефон чи пейджер за допомогою оÑобливого інтерфейÑу LiveJournal, не розголошуючи при цьому Ñвій номер. + +/paidaccounts/index.bml.features.descs.userpics.header=Більше юзерпик + +/paidaccounts/index.bml.features.descs.userpics.text=Платні кориÑтувачі можуть завантажити до 30 юзерпик, заробити юзерпики лоÑльноÑÑ‚Ñ– та придбати додаткове міÑце ще Ð´Ð»Ñ 100 юзерпик. + +/paidaccounts/index.bml.features.descs.voiceposting.header=ГолоÑовий Ð·Ð°Ð¿Ð¸Ñ + +/paidaccounts/index.bml.features.descs.voiceposting.text=Ðабравши телефонний номер з будь-Ñкого телефону, платні кориÑтувачі можуть запиÑати голоÑове повідомленнÑ, Ñке завантажуєтьÑÑ Ð¿Ñ€Ñмо до журналу. + +/paidaccounts/index.bml.features.header=То Ñкі круті можливоÑÑ‚Ñ– Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°ÑŽ? + +/paidaccounts/index.bml.intro.compare=Щоб порівнÑти, завітайте на нашу Ñторінку МожливоÑÑ‚Ñ– за типом рахунку. + +/paidaccounts/index.bml.intro.getone=Якщо ви бажаєте Ñтворити платний рахунок, перейдіть на Ñторінку Створити платний рахунок. + +/paidaccounts/index.bml.intro.header=Чи маю Ñ Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚Ð¸ за кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ LiveJournal? + +/paidaccounts/index.bml.intro.text=LiveJournal завжди надаватиме безкоштовні рахунки з безліччю чудових можливоÑтей: переглÑд Ñтрічок друзів, Ñпільноти, потужні можливоÑÑ‚Ñ– Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ– та інше. Ви також можете будь-коли Ñтати платним кориÑтувачем Ñ– тоді матимете доÑтуп до деÑких додаткових унікальних можливоÑтей, що перелічені нижче. + +/paidaccounts/index.bml.status.header=Який Ñтан мого платного рахунку? + +/paidaccounts/index.bml.status.text=ПередивитиÑÑŒ Ñтан будь-Ñкого вашого платного рахунку можна на Ñторінці Стан платного рахунку. + +/paidaccounts/index.bml.title=Про платні рахунки + +/paidaccounts/index.bml.your_username=ваше_ім'Ñ_кориÑтувача + +/paidaccounts/joincommunity.bml.btn.join=Стати платним кориÑтувачем! + +/paidaccounts/joincommunity.bml.confirm.text=Щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти [[ljuserpaidmembers]], натиÑніть кнопку нижче. + +/paidaccounts/joincommunity.bml.confirm.title=Підтвердити + +/paidaccounts/joincommunity.bml.error.needpaidaccount.text=Ви повинні мати платний рахунок, щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти [[ljuserpaidmembers]]. + +/paidaccounts/joincommunity.bml.error.needpaidaccount.title=Вибачте + +/paidaccounts/joincommunity.bml.error.nopaidmemberscomm=Ñпільноти платних кориÑтувачів не Ñ–Ñнує. + +/paidaccounts/joincommunity.bml.error.notloggedin.text=Щоб приєднатиÑÑ Ð´Ð¾ Ñпільноти платних кориÑтувачів, ви маєте ввійти в LJ. + +/paidaccounts/joincommunity.bml.error.notloggedin.title=Спочатку увійдіть + +/paidaccounts/joincommunity.bml.error.title=Помилка + +/paidaccounts/joincommunity.bml.join.title=ДолучитиÑÑ Ð´Ð¾ платних кориÑтувачів? + +/paidaccounts/joincommunity.bml.joined.title=ДолучилиÑÑ + +/paidaccounts/joincommunity.bml.success.header=УÑпішно + +/paidaccounts/joincommunity.bml.success.text=Тепер ви Ñ” учаÑником Ñпільноти [[ljuserpaidmembers]]. + +/paidaccounts/joincommunity.bml.title=ДолучітьÑÑ Ð´Ð¾ платних кориÑтувачів + +/paidaccounts/status.bml.diskquota.header=ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð¸Ñкового проÑтору + +/paidaccounts/status.bml.diskquota.text=Звіт про викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð¸Ñкового проÑтору. + +/paidaccounts/status.bml.error.accountdeleted=Рахунок видалено. + +/paidaccounts/status.bml.error.cantbeauthenticated=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +/paidaccounts/status.bml.text=Ðижче подано перелік поÑлуг [[sitename]], Ñкі ви замовили на даний чаÑ: + +/paidaccounts/status.bml.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку + +/paidaccounts/thankyou.bml.title=ДÑкуємо! + +/paidaccounts/thankyou.bml.whatnow.header=Що тепер? + +/paidaccounts/thankyou.bml.whatnow.payforexistingaccount=Якщо ви здійÑнюєте оплату Ð´Ð»Ñ Ñ–Ñнуючого рахунку, ваш платний рахунок буде Ñтворено, коли PayPal повідомить нам деталі оплати. + +/paidaccounts/thankyou.bml.whatnow.payfornewaccount=Якщо ви здійÑнюєте оплату Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ рахунку, код ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ буде надіÑлано на електронну адреÑу, Ñку ви викориÑтовуєте в PayPal. + +/paidaccounts/thankyou.bml.whatnow.processing=PayPal зараз виконує ваш платіж. Їхній Ñервер незабаром з'єднаєтьÑÑ Ð· нашим Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡Ñ– вÑÑ–Ñ… деталей оплати. Це відбудетьÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом найближчих 12 годин. + +/paidaccounts/thankyou.bml.whatnow.thanks=Ваш платіж прийнÑто. + +/paidaccounts/usepaypal.bml.delivery.badformat=Ðевірний формат дати доÑтавки. Має бути у формі рррр-мм-дд або рррр-мм-дд гг:Ñ…Ñ…. + +/paidaccounts/usepaypal.bml.delivery.past=Дата доÑтавки не може бути в минулому. Щоб надіÑлати негайно, залиште поле дати доÑтавки порожнім. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Дата доÑтавки не може бути більше, ніж міÑÑць у майбутньому. + +/pay/cc.bml.alreadypaid.header=Сплачено + +/pay/cc.bml.alreadypaid.text=Це Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð¶Ðµ Ñплачено. + +/pay/cc.bml.boughtpaidaccount=Завітайте до Ñторінки "Про платні рахунки" , щоб передивитиÑÑ Ð¿Ð¾Ð²Ð½Ð¸Ð¹ перелік можливоÑтей. + +/pay/cc.bml.boughtstoragespace=ДиÑковий проÑÑ‚Ñ–Ñ€ можна викориÑтати Ð´Ð»Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ð¹ у ScrapBook. + +/pay/cc.bml.boughtuserpics=Зараз ви можете завантажити більше юзерпик. + +/pay/cc.bml.btn.completeorder=Завершити Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/pay/cc.bml.ccinfo.authinfo=Ðа вашій заÑвці Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð·'ÑвитиÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´ [[legalname]], це Ñ” юридичне ім'Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ—, Ñка викориÑтовує [[sitename]]. ДеÑкі банки не показують запитів авторизації на документах оплати. + +/pay/cc.bml.ccinfo.charge=Витрати з'ÑвлÑÑ‚ÑŒÑÑ Ð½Ð° вашій заÑвці від [[legalname]], це Ñ” юридичне ім'Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ—, Ñка викориÑтовує [[sitename]]. + +/pay/cc.bml.ccinfo.header=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ кредитну картку + +/pay/cc.bml.ccinfo.nocharge=ОÑкільки ваш кошик міÑтить лише вікову перевірку COPPA, ми змушені перевірити, чи введена вами Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ” правдива, Ñ– тому [[amount]] Ñ” доÑтупна на вашій картці. Звичайно, Ð²Ð°Ñ Ð½Ðµ будуть оÑуджувати. + +/pay/cc.bml.ccinfo.nocharge2=ОÑкільки у вашому кошику лише товар, Ñкий потребує перевірки віку (COPPA), ми Ñпробуємо перевірити правильніÑÑ‚ÑŒ введених даних та наÑвніÑÑ‚ÑŒ щонайменше [[amount]] на вашій картці. Однак, гроші зніматиÑÑ Ð½Ðµ будуть. + +/pay/cc.bml.coppa.email=Ð¦Ñ email адреÑа повинна бути відмінною від адреÑи у вашому журнальному рахунку. Ðа введену адреÑу буде відіÑлано електронний лиÑÑ‚ із перевіркою. Це необхідно аби ви прочитали лиÑÑ‚Ñ– ÑкориÑталиÑÑ Ð¿Ð¾ÑиланнÑм вÑередині Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ рахунку. + +/pay/cc.bml.coppa.header=Вікова перевірка (Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ COPPA) + +/pay/cc.bml.coppa.input.email=Email адреÑа батьків чи опікунів: + +/pay/cc.bml.coppa.order.header=Запит авторизації ([[id]]) + +/pay/cc.bml.coppa.title=Дозвіл батьків/опікунів + +/pay/cc.bml.coppa.verify=Запит міÑтить річ, Ñка вимагає вікову перевірку Ð´Ð»Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. Ðби завершити процеÑ, ми повинні зібрати email адреÑи батьків цього кориÑтувача. + +/pay/cc.bml.coppa.verify2=Ðижчевказане Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ñ–Ñтить товар, що вимагає перевірку віку кориÑтувача. Ð”Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑу нам потрібна email-адреÑа батьків кориÑтувача. + +/pay/cc.bml.coppaaddition=Додатково, ви повинні завершити перший крок вікової перевірки COPPA. Батьки, будь-лаÑка, перевірте ваші email адреÑи: ви невдовзі повинні одержати email із перевіркою. Як тільки ви одержите лиÑта, перейдіть за поÑиланнÑм вÑередині, Ñ– рахунок вашої дитини буде активовано. + +/pay/cc.bml.coppaaddition2=Крім того, ви пройшли перший етап перевірки віку (COPPA). + +/pay/cc.bml.email.parentverification.body<< +ЛаÑкаво проÑимо, ви у процеÑÑ– ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ [[sitename]] рахунку Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— дитини. + +Ðктивувавши цей рахунок, ви підтверджуєте, що прочитали наш Ðкт "Про захиÑÑ‚ прав дитини в інтернеті" (Children's +Online Privacy Protection Act), Terms of Service Ñ– Privacy +Policy Ñ– що ви погодилиÑÑ Ñ–Ð· ними. + + COPPA Ð´ÐµÐºÐ»Ð°Ñ€Ð°Ñ†Ñ–Ñ + [[coppaurl]] + + Terms of Service + [[tosurl]] + + Privacy Policy + [[privacyurl]] + +Ðби завершити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу Ð´Ð»Ñ Ð´Ð¸Ñ‚Ð¸Ð½Ð¸ Ñ– перевірити ваші email адреÑи, ви повинні перейти за поÑиланнÑм внизу. + +[[consenturl]] + +(Якщо ви не можете натиÑнути на поÑиланнÑ, Ñкопіюйте його у ваш переглÑдач.) + +Ваша дитина може діÑтатиÑÑ Ð´Ð¾ Ñвого журналу за наÑтупними двома URL: + + [[journalurl1]] + [[journalurl2]] + +Ðижче подано [[sitename]] ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, Ñке було зареєÑтровано: + + Username: [[username]] + +Якщо вашій дитині потрібно отримати його чи Ñ—Ñ— пароль, вони можуть зробити це будь-коли, відвідавши наÑтупний URL: + + [[lostinfourl]] + +КориÑтуйтеÑÑŒ наздоров'Ñ! + +[[sitename]] команда +[[siteroot]] +. + +/pay/cc.bml.email.parentverification.body2<< +ДÑкуємо за Ð²Ñ–Ð´Ð²Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ [[sitename]]. Ви практично завершили Ð¿Ñ€Ð¾Ñ†ÐµÑ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ [[sitename]] Ð´Ð»Ñ Ñвоєї дитини. Щоб оÑтаточно Ñтворити журнал Ñвоєї дитини, будь лаÑка, перевірте вашу email-адреÑу завітавши за наÑтупною адреÑою: + + [[consenturl]] + +(Якщо ви не можете натиÑнути на поÑиланнÑ, Ñкопіюйте його у Ñ€Ñдок адреÑи Ñвого браузеру.) + +Ðктивуючи цей рахунок ви підвтерджуєте, що прочитали Ñ– погодилиÑÑ Ð· наÑтупним: + + Ð Ð¾Ð·ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð°ÐºÑ‚Ñƒ "Про захиÑÑ‚ прав дитини в інтернеті" (COPPA): [[coppaurl]] + + Умови викориÑтаннÑ: [[tosurl]] + + Політика конфіденційноÑÑ‚Ñ–: [[privacyurl]] + + +Ваша дитина отримає вітальний лиÑÑ‚ з проханнÑм підтвердити Ñ—Ñ— email-адреÑу. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð¾Ð½Ð° зможе увійти до Ñвого журналу та робити у ньому запиÑи! + +Ви можете відвідати журнал Ñвоєї дити за адреÑою: + + [[journalurl]] + +Ðижче наведено Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача [[sitename]], Ñке обрала ваша дитина: + + Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[username]] + +Якщо ваша дитина забуде Ñвій пароль, вона завжди зможе отримати новий завітавши за наÑтупною адреÑою: + + [[lostinfourl]] + + +ÐаÑолоджуйтеÑÑŒ! + +Команда [[sitename]] +[[siteroot]] +. + +/pay/cc.bml.email.parentverification.subject=[[sitename]] батьківÑька email перевірка + +/pay/cc.bml.email.parentverification.subject2=БатьківÑька перевірка [[sitename]] + +/pay/cc.bml.error.cantprocesscc=Ми не можемо обробити дану картку. + +/pay/cc.bml.error.cantprocesspayment=Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ платежа ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: [[errormsg]] + +/pay/cc.bml.error.cantprocesspayment.fundsheld=Можливо ваш банк тимчаÑово затримує кошти Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ—, але невдовзі вони повинні бути пропущені. Ваша картка не буде перевірÑтиÑÑ. + +/pay/cc.bml.error.cantprocesspayment.moreinfo=Ðби довідатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про AVS Ñ– транзакції кредитних карток, будь-лаÑка, дивітьÑÑ FAQ. + +/pay/cc.bml.error.cantprocessrequest=Вибачте, але ми не можемо обробити ваш запит. + +/pay/cc.bml.error.cantregisterauthaction=Ðеможливо зареєÑтрувати аутентифікацію. + +/pay/cc.bml.error.cantusesameemail=БатьківÑька email адреÑа не може Ñпівпадати із адреÑою вашого журнального рахунку. + +/pay/cc.bml.error.countriesdontmatch=Країна вашої інтернет адреÑи не Ñпівпадає із країною вашої кредитної картки. Звідти ви можете: + +/pay/cc.bml.error.countriesdontmatch.contactsupport=Зв'ÑжітьÑÑ Ñ–Ð· [[sitename]] підтримкою Ñ– поÑÑніть вашу ÑитуаціÑ. Ми можливо зможемо допомогти. + +/pay/cc.bml.error.countriesdontmatch.diffcc=ВикориÑтайте інший метод оплати або кредитну картку. + +/pay/cc.bml.error.countriesdontmatch.diffcountry=РозраховуйтеÑÑŒ викориÑтовуючи інтернет з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñƒ країні, із Ñкої походить ваша кредитна картка. + +/pay/cc.bml.error.invalidcart=Цей кошик міÑтить недоÑтупні речі. Це може бути Ñпричинено конфліктом із іншими кошиками, Ñтвореними в той же чаÑ. Будь лаÑка, Ñпробуйте ще раз із новим замовленнÑм. + +/pay/cc.bml.error.mustenterparentemail=Ви повинні ввеÑти email адреÑу батьків аби продовжити із віковою перевіркою COPPA. + +/pay/cc.bml.error.mustloginaschild=Ви повинні бути залоговані оÑкільки рахунок перевірÑєтьÑÑ (рахунок дитини) аби обробити замовленнÑ, що міÑтить речі, Ñкі потребують вікової перевірки. + +/pay/cc.bml.error.nocharge=У результаті цієї помилки, ваша кредитна картка не була перевірена. + +/pay/cc.bml.error.noruccs=Ðаразі ми не приймаємо оплат кредитними картками із РоÑÑ–Ñ— чи України Ð´Ð»Ñ Ð´Ð¾Ñтавки речей. + +/pay/cc.bml.error.notloggedin=Ви повинні бути залоговані Ñк влаÑник кошика, аби підтвердити його. + +/pay/cc.bml.error.notyourcart=Ви не влаÑник цього кошика. Якщо ви хочете розпочати нове, будь-лаÑка, натиÑніть Ñюди. + +/pay/cc.bml.error.notyourcart2=Ви не Ñ” влаÑником цього кошика. + +/pay/cc.bml.error.orderamountchanged=ÐеÑподівана помилка: змінилаÑÑ ÐºÑ–Ð»ÑŒÐºÑ–ÑÑ‚ÑŒ замовлених речей від того чаÑу, Ñк ви вводили інформацію про картку до тепер. + +/pay/cc.bml.error.orderiszero=КількіÑÑ‚ÑŒ замовленних речей нуль. + +/pay/cc.bml.error.ordernotfound=Ð—Ð°Ð¼Ð¾Ð»ÐµÐ½Ð½Ñ Ð½Ðµ знайдено + +/pay/cc.bml.error.paymentsdown.header=Платіжний шлюз не відповідає. + +/pay/cc.bml.error.paymentsdown.text=ПриноÑимо Ñвої вибаченнÑ, але шлюз транзакції вашой кредитної картки наразі не відповідає. Будь-лаÑка, Ñпробуйте ще раз за декілька хвилин. + +/pay/cc.bml.error.ratelimitsexceeded=Ви пробуєте оброблÑти транзакції кредитної картки занадто чаÑто. Ваша кредитна картка не оброблена. Будь-лаÑка, трохи зачекайте Ñ– Ñпробуйте ще раз пізніше. Якщо проблема не зникне, будь-лаÑка, зв'ÑжітьÑÑ Ñ–Ð· [[accountsemail]]. + +/pay/cc.bml.noshippinginfoinemail=Зауважте: Ваш отримувач із email від нашого обробника кредитних карток не міÑтитиме інформацію про доÑтавку. Ðе хвилюйтеÑÑŒ... Ñ†Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ñ”Ñ‚ÑŒÑÑ Ð² нашій базі даних. + +/pay/cc.bml.order.header=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ([[id]]) + +/pay/cc.bml.ordercompleted.header=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾. + +/pay/cc.bml.ordercompleted.text=Ðемає змін Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ замовленнÑ. + +/pay/cc.bml.paymentcomplete.header=ДÑкуємо за покупку! + +/pay/cc.bml.paymentcomplete.text=Це Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно оплачено. Бажаєте розпочати ще одне? + +/pay/cc.bml.paymentcomplete.title=Оплата завершена + +/pay/cc.bml.security.header=Ð“Ð°Ñ€Ð°Ð½Ñ‚Ñ–Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ + +/pay/cc.bml.security.text=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ–Ð· вашої кредитної картки переÑилаєтьÑÑ Ñ‡ÐµÑ€ÐµÐ· інтернет зашифрованою у обидва напрÑмки - від вашого компю'тера до [[sitename]], Ñ– від [[sitename]] до банку. Ðомер вашої кредитної картки негайно забуваєтьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ†Ñ–Ñ”Ñ— транзакції Ñ– ніколи не зберігаєтьÑÑ Ð½Ð° жодному із Ñерверів. + +/pay/cc.bml.shipping.header=ÐдреÑа доÑтавки + +/pay/cc.bml.shipping.text=Якщо наÑтупне невірне, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ до вашого Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ– підтвердіть його пізніше, виправивши адреÑу доÑтавки. + +/pay/cc.bml.success.emailsent=ЛиÑÑ‚ було надіÑлано на [[email]]. Щойно ви його отримаєте Ñ– натиÑнете на поÑиланнÑ, що в ньому міÑтитьÑÑ, рахунок вашої дитини буде повніÑÑ‚ÑŽ активовано. + +/pay/cc.bml.success.header=УÑпішна Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ + +/pay/cc.bml.success.text=Ви завершили перший крок вікової перевірки COPPA. Батьки, будь-лаÑка, перевірте ваші email адреÑи: ви невдовзі повинні одержати email із перевіркою. Як тільки ви одержите лиÑта, перейдіть за поÑиланнÑм вÑередині, Ñ– рахунок вашої дитини буде активовано. + +/pay/cc.bml.success.text2=Ви пройшли перший етап перевірки віку (COPPA). + +/pay/cc.bml.success.title=Перевірку здійÑнено + +/pay/cc.bml.title=Обробка кредитної картки + +/pay/checkout.bml.browsertitle=Оплата [[id]] + +/pay/checkout.bml.error.invalidcart=Ваш кошик включає товари, Ñкі вже відÑутні. Це могло ÑтатиÑÑ Ñ‡ÐµÑ€ÐµÐ· помилку під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ кількох одночаÑних кошиків. Спробуйте ще раз із новим кошиком. + +/pay/checkout.bml.error.notloggedin=Ви повинні увійти Ñк влаÑник кошика Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ–Ð². + +/pay/checkout.bml.error.notyourcart=Це не ваш кошик. Якщо ви хочете Ñтворити новий, будь лаÑка, натиÑніть Ñюди. + +/pay/checkout.bml.guidelines.funds=ПриймаютьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ чеки від резидентів СШРабо Канади, виготовлені фінанÑовою організацією СШР(ваш банк здійÑнить перерахунок по курÑу обміну, Ñкщо ви піÑÐ»Ñ Ñуми оплати вкажете "US Funds"). + +/pay/checkout.bml.guidelines.header=Зверніть увагу на такі пункти: + +/pay/checkout.bml.guidelines.include=Додайте до платежу роздруківку цієї Ñторінки або поÑиланнÑ: + +/pay/checkout.bml.guidelines.late=ЗамовленнÑ, отриманні пізніше [[nummonths]] [[?nummonths|міÑÑцÑ|міÑÑців]] з чаÑу Ñ—Ñ… ÑтвореннÑ, обÑлуговуватиÑÑ Ð½Ðµ будуть. + +/pay/checkout.bml.guidelines.payable=Зробіть чеки або грошові перекази можливими Ð´Ð»Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸ у [[sitename]]. + +/pay/checkout.bml.guidelines.tracking=Ми наÑтійливо радимо кориÑтуватиÑÑ ÐºÑƒÑ€â€™Ñ”Ñ€Ð¾Ð¼ або іншим методом доÑтавки, Ñкий дозволÑÑ” отримати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ, оÑкільки ми не можемо відÑтежити платежі, що не діÑталиÑÑ Ð½Ð°ÑˆÐ¾Ð³Ð¾ офіÑу. + +/pay/checkout.bml.haveaddress=Ваша адреÑа доÑтавки знаходитьÑÑ Ñƒ файлі, що пов'Ñзаний з номером вашого замовленнÑ. + +/pay/checkout.bml.ordercompleted.header=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾ + +/pay/checkout.bml.ordercompleted.text=Плата за дане Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ ÑÑ‚ÑгуєтьÑÑ. + +/pay/checkout.bml.pay.header=Оплата + +/pay/checkout.bml.pay.text=Якщо дані заповнені правильно, відішліть ваш платіж до: + +/pay/checkout.bml.thanks=ДÑкуємо за покупку! + +/pay/checkout.bml.title=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ([[id]]) + +/pay/cvv2.bml.title=Перевірка кредитної картки + +/pay/cvv2.bml.whatisit.header=Що таке CVV2/CVC2/CID? + +/pay/cvv2.bml.whatisit.oncard=Коди перевірки приÑутні тільки на картці, вони не приÑутні Ñеред даних магнітної Ñтрічки та не з'ÑвлÑÑŽÑ‚ÑŒÑÑ Ð½Ð° чеках або в платіжних документах. ВикориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ перевірки кредитної картки допомагає нам зменшити ризик викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¸Ñ… або вкрадених карток. + +/pay/cvv2.bml.whatisit.security=CVV2/CVC2/CID - це оÑобливіÑÑ‚ÑŒ безпеки Ð´Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ð¹, в Ñких ваша кредитна картка фізично не приÑутнÑ. Це три або чотири цифри, Ñкі дозволÑÑŽÑ‚ÑŒ нашій платіжній ÑиÑтемі перевірити ідентичніÑÑ‚ÑŒ вашої кредитної картки. Терміни викориÑтовуютьÑÑ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ¼Ñ–Ð½Ð½Ð¾. CVV2 (Card Verification Value 2) перекладаєтьÑÑ Ñк "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ картки 2", CVC2 (Card Validation Code 2) - "Код перевірки дійÑноÑÑ‚Ñ– картки 2", CID (Card Identification Number) - "Ідентифікаційний номер картки". Код перевірки дозволÑÑ” нам перевірити дві речі: + +/pay/cvv2.bml.whatisit.security.havecard=Ваша кредитна картка знаходитьÑÑ Ñƒ вашій влаÑноÑÑ‚Ñ–. + +/pay/cvv2.bml.whatisit.security.validaccount=Ваша кредитна картка законна. + +/pay/cvv2.bml.whereisit.amex=Ðа кредитних картках American Express код перевірки - це чотири надруковані (не вибиті) цифри, що знаходÑÑ‚ÑŒÑÑ Ð½Ð°Ð´ номером картки на Ñ—Ñ— лицьовому боці. + +/pay/cvv2.bml.whereisit.header=Де шукати ваш номер Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ + +/pay/cvv2.bml.whereisit.visa=Ðа кредитних картках Visa, Eurocard/MasterCard та Discover код перевірки - це три цифри, розташовані на зворотньому боці картки, праворуч від номеру, в зоні Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу. + +/pay/history.bml.error.title=Помилка + +/pay/history.bml.howto=ÐатиÑніть на номер замовленнÑ, щоб побачити кошик. До незавершених кошиків, Ñкщо ви Ñ—Ñ… не підтвердили, можна додавати та видалÑти товари. У незавершених кошиках, Ñкі ви підтвердили, ви зможете лише змінити тип оплати. + +/pay/history.bml.intro=Ðижче перелічено вÑÑ– ваші попередні завершені замовленнÑ, також незавершені кошики за оÑтанній міÑÑць. + +/pay/history.bml.noorders=Ðемає замовлень + +/pay/history.bml.table.amount=КількіÑÑ‚ÑŒ + +/pay/history.bml.table.date=Дата + +/pay/history.bml.table.orderid=Ðомер Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/pay/history.bml.table.status=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/pay/history.bml.table.status.completed=завершено + +/pay/history.bml.table.status.pending=очікую + +/pay/history.bml.title=ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½ÑŒ + +/pay/index.bml.back2=ПовернутиÑÑ Ð´Ð¾ крамниці + +/pay/index.bml.btn.neworder=Ðове Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/pay/index.bml.btn.use=ВикориÑтати + +/pay/index.bml.deliverydate.label=Дата доÑтавки: + +/pay/index.bml.error.header=Вибачте + +/pay/index.bml.error.nonuserscantupgrade=КориÑтувачі інших Ñайті не можуть змінювати Ñвої зовнішні рахунки. + +/pay/index.bml.error.notloggedin=Ви повинні увійти Ñк влаÑник кошика, щоб здійÑнити купівлю. + +/pay/index.bml.error.notyourcart=Ви не Ñ” влаÑником цього кошика. Якщо бажаєте Ñтворити новий, будь лаÑка, натиÑніть Ñюди. + +/pay/index.bml.giftcert.header=Маєте подарунковий купон? + +/pay/index.bml.giftcert.text=Якщо ви маєте подарунковий купон, введіть його тут: + +/pay/index.bml.intro=Ðижче наведено ваш поточний кошик. Ви можете внеÑти додаткові платні поÑлуги LiveJournal чи товари до вашого кошика або продовжити, щоб перейти до розрахунку. + +/pay/index.bml.intro2=Товари у кошику: + +/pay/index.bml.neworder.header=Ðове замовленнÑ? + +/pay/index.bml.neworder.text=Кошик вище підтверджений. Почати нове замовленнÑ? + +/pay/index.bml.note.norefund=Ð’ÑÑ– покупки, включно із невикориÑтаним Ñплаченим чаÑом та подарунковими купонами, поверненню не підлÑгають. + +/pay/index.bml.paidfor.header=Заплатити за + +/pay/index.bml.paidfor.text=Це Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð¿Ð»Ð°Ñ‡ÐµÐ½Ð¾ на [[date]]. + +/pay/index.bml.returnpolicy.header=Політика Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ + +/pay/index.bml.returnpolicy.text=Зауважте: Ðби мінімізувати затрати, ми маємо жорÑтку політику поверненнÑ. Якщо ви купуєте одÑг, обов'Ñзково попередньо переглÑньте таблицю розмірів. + +/pay/index.bml.title=Моє Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/pay/index.bml.title2=Кошик + +/pay/modify.bml.btn.acknowledged=Визнано + +/pay/modify.bml.btn.continue=Продовжити --> + +/pay/modify.bml.btn.continue_webmoney=Продовжити! + +/pay/modify.bml.cashwarning.header=Платежі готівкою + +/pay/modify.bml.cashwarning.text=Ми не рекомендуємо відÑилати готівку поштою. Якщо у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” інших варіантів, ми його приймемо, але ми не неÑемо жодної відповідальноÑÑ‚Ñ–, Ñкщо гроші загублÑÑ‚ÑŒÑÑ . + +/pay/modify.bml.cashwarning.title=Увага готівка + +/pay/modify.bml.ccprocessordown.header=Шлюз недоÑтупний + +/pay/modify.bml.ccprocessordown.paypal=Однак, ви також можете розрахуватиÑÑ ÐºÑ€ÐµÐ´Ð¸Ñ‚Ð½Ð¾ÑŽ карткою через PayPal: + +/pay/modify.bml.ccprocessordown.paypal.link=Сплатити за допомогою PayPal + +/pay/modify.bml.ccprocessordown.text=Ðаш оÑновний шлюз Ð´Ð»Ñ Ð¾Ð±Ñ€Ð¾Ð±Ð½Ð¸Ðº кредитних карток тимчаÑово недоÑтупний із незалежних від Ð½Ð°Ñ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½. + +/pay/modify.bml.ccprocessordown.title=ОÑновний обробник кредитних карток недоÑтупний + +/pay/modify.bml.customsnotice.forms=Купівельні форми Ð´Ð»Ñ Ð²ÑÑ–Ñ… інтернаціональних пакетах відображають ваші Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² залежноÑÑ‚Ñ– від типу продукту. Форму із замовленою футболкою буде зображено подібно до наÑтупного прикладу: + +/pay/modify.bml.customsnotice.header=ВлаÑні нотатки + +/pay/modify.bml.customsnotice.taxes=Із покупців поза межами Сполучених Штатів може бути ÑÑ‚Ñгнено додаткові мита та податки. зв'ÑжітьÑÑ Ñ–Ð· міÑцевим офіÑом за додатковою інформацією. Коли ви замовлÑєте із [[sitename]], ви повинні зважити можливіÑÑ‚ÑŒ доÑтавки речей Ñ– маєте погодитиÑÑ Ñ–Ð· уÑіма законами Ñ– правилами країни, у Ñкій ви отримуватимете товарю + +/pay/modify.bml.deliverydateadjusted.header=Зауважте + +/pay/modify.bml.deliverydateadjusted.text1=Ви хочете купити [[item]], але платний рахунок [[user]] (Ñкщо такий Ñ”) завершитьÑÑ Ð´Ð¾ того чаÑу, Ñк зміни до вашого першого платного рахунку у вашому кошику вÑтуплÑÑ‚ÑŒ у дію. ОÑкільки [[item]] неможливо заÑтоÑувати без платного рахунку, це Ñтановить проблему. + +/pay/modify.bml.deliverydateadjusted.text2=Щоб розв'Ñзати це, ми повинні вÑтановити Ñ‡Ð°Ñ Ð´Ð¾Ñтавки Ð´Ð»Ñ [[item]] однаковим із чаÑом доÑтавки першого платного рахунку у вашому кошику: [[date]]. + +/pay/modify.bml.deliverydatechangedtonow.header=Ðотатка + +/pay/modify.bml.deliverydatechangedtonow.text1=Ви збираєтеÑÑ Ð¿Ñ€Ð¸Ð´Ð±Ð°Ñ‚Ð¸ [[item]], але платний рахунок [[user]] закінчитьÑÑ Ð´Ð¾ вказаної дати доÑтавки. ОÑкільки у вашому кошику відÑутній платний рахунок Ð´Ð»Ñ [[user]], [[item]] не не можна придбати Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача без платного рахунку, Ñ– це Ñтановить проблему. + +/pay/modify.bml.deliverydatechangedtonow.text2=Ðби розв'Ñзати це, ми повинні виÑтавити дату доÑтавки [[item]] Ñьогоднішнім чиÑлом. + +/pay/modify.bml.error.alreadycheckedout=Ваше поточне активне Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð¶Ðµ підтверджено. Щоб додати інші речі, ви муÑите розпочати нове замовленнÑ. + +/pay/modify.bml.error.cantaddcoupon=Помилка при додаванні купону до замовленнÑ: [[errormsg]] + +/pay/modify.bml.error.cantaddcoupontoemptyorder=Ðе моду додати купон до пуÑтого замовленнÑ. Спершу додайте речі, далі заÑтоÑуйте ваш купон. + +/pay/modify.bml.error.cantadditem=Ðевдача при додаванні речей до кошика: [[errormsg]] + +/pay/modify.bml.error.cantbuycouponforself=Ðе можу купити купон Ð´Ð»Ñ Ñамого Ñебе. + +/pay/modify.bml.error.cantbuycouponwithcoupon=Ðе можу викориÑтати подарунковий купон Ð´Ð»Ñ ÐºÑƒÐ¿Ñ–Ð²Ð»Ñ– подарункового купону. + +/pay/modify.bml.error.cantbuyduetoaccountstatus=Ðе можу купити поÑлуги Ð´Ð»Ñ [[user]] через ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/pay/modify.bml.error.cantbuyextrasforfreeaccount=Ви можете купити додаткові поÑлуги Ð´Ð»Ñ Ñ–Ñнуючого платного рахунку. Якщо ви хочете купити [[item]] Ð´Ð»Ñ [[user]], додайте платний рахунок Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾ до вашого кошика Ñ– Ñпробуйте ще раз. + +/pay/modify.bml.error.cantbuyforrenamed=Ðеможливо купити платні поÑлуги Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ–Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ рахунку. + +/pay/modify.bml.error.cantbuyforsyn=Ðе можна купити додаткові можливоÑÑ‚Ñ– Ð´Ð»Ñ Ñиндикативного рахунку. + +/pay/modify.bml.error.cantbuygifts=Вам не дозволено купувати подарунки Ð´Ð»Ñ [[user]]. + +/pay/modify.bml.error.cantbuyitem=Ðе можу купити [[item]]. + +/pay/modify.bml.error.cantbuyitemasgift=Ðе можна купити [[item]] Ñк подарунок. + +/pay/modify.bml.error.cantbuyitemforperm=Вам не дозволено купувати [[item]] Ð´Ð»Ñ Ñ‚Ð¸Ð¼Ñ‡Ð°Ñових рахунків. + +/pay/modify.bml.error.cantbuymanyperms=Ðе можна замовити більш ніж один тимчаÑовий рахунок Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ð³Ð¾ одержувача. + +/pay/modify.bml.error.cantbuypaidforperm=Ðе можна оплачувати Ñ‡Ð°Ñ Ð´Ð»Ñ Ñ‚Ð¸Ð¼Ñ‡Ð°Ñових рахунків. + +/pay/modify.bml.error.cantcreatecart=Ðе можу Ñтворити новий кошик: [[errormsg]] + +/pay/modify.bml.error.cantfinduser=Ðе можу знайти кориÑтувача '[[user]]'. + +/pay/modify.bml.error.cantgivetoemail=Email адреÑа більше не прийнÑтна Ñк одержувач. + +/pay/modify.bml.error.cantmodifycart=Ðе можу змінити підтверджений кошик. + +/pay/modify.bml.error.cantspecifydateforself=Ðе можна вказати день доÑтавки Ð´Ð»Ñ Ñамого Ñебе. + +/pay/modify.bml.error.cantusepaypal=Оплата за одÑг із PayPal не підтримуєтьÑÑ. Будь-лаÑка, повернітьÑÑ Ñ– виберіть альтернативні ÑпоÑоби оплати. + +/pay/modify.bml.error.cantusewebmoney=Вибачте, нема змоги викориÑтати WebMoney Ð´Ð»Ñ Ð´Ð¾Ñтавки замовленнÑ. + +/pay/modify.bml.error.couponalreadyusedbyanother=Купон вже викориÑтано іншим кориÑтувачем. + +/pay/modify.bml.error.couponalreadyusedloggedout=Купон вже викориÑтано. + +/pay/modify.bml.error.couponalreadyused_modify=Купон, Ñкий ви ввели, вже викориÑтано іншим вашим кошиком. Якщо ви бажаєте, ви можете змінити наÑвний кошик або повернутиÑÑ Ñ– ввеÑти новий купон Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кошика. + +/pay/modify.bml.error.couponalreadyused_view=Купон, Ñкий ви ввели, вже викориÑтано іншим вашим кошиком. Якщо ви бажаєте, ви можете переглÑнути наÑвний кошик або повернутиÑÑ Ñ– ввеÑти новий купон Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кошика. + +/pay/modify.bml.error.emailnotselected=Введено email поверненнÑ, але його не обрано. Ðе впевнені, що ви маєте на увазі. + +/pay/modify.bml.error.invalidcart_new=Даний кошик міÑтить речі, Ñкі не Ñ” дійÑними. Це може призвеÑти до конфлікту із іншими кошиками, Ñтвореними в той Ñамий чаÑ. Будь лаÑка, Ñпробуйте Ñтворити новий кошик. + +/pay/modify.bml.error.invalidcart_old=Даний кошик міÑтить речі, Ñкі не Ñ” дійÑними. Це може призвеÑти до конфлікту із іншими кошиками, Ñтвореними в той Ñамий чаÑ. Будь-лаÑка, Ñпробуйте Ñтворити новий кошик або продовжити із наÑвним. + +/pay/modify.bml.error.invalidcoupon=ÐедійÑний купон. + +/pay/modify.bml.error.invalidcouponformat=ÐедійÑний фрормат купону. + +/pay/modify.bml.error.invalidpaymentmethod=невірний метод оплати + +/pay/modify.bml.error.invalidpaymentmethodforage=невірний метод оплати Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ віку + +/pay/modify.bml.error.invalidproduct=Ðевірний товар. + +/pay/modify.bml.error.needcity=Вкажіть міÑто. + +/pay/modify.bml.error.needshippingaddress=Вкажіть міÑце доÑтавки. + +/pay/modify.bml.error.needstate=Вкажіть штат. + +/pay/modify.bml.error.needzip=Вкажіть 5 цифровий код. + +/pay/modify.bml.error.noclothingitems=Ðе Ñ–Ñнує такого одÑгу, Ð´Ð»Ñ Ñкого можна викориÑтати цей купон. + +/pay/modify.bml.error.nointernationalshipping=Вибачте, наразі ми здійÑнюємо доÑтавку тільки у межах Сполучених Штатів. + +/pay/modify.bml.error.nopoboxes=Вибачте, ми не можемо доÑтавити на поштові Ñкриньки. + +/pay/modify.bml.error.norecipientgiven=Ðе вказано одержувача Ð´Ð»Ñ Ñ‚Ð¾Ð²Ð°Ñ€Ñƒ. + +/pay/modify.bml.error.notloggedin=Ви маєте бути залогованими Ñк влаÑник кошика, щоб продовжити підтвердженнÑ. + +/pay/modify.bml.error.notloggedinforaddingitems=Ви повинні залогуватиÑÑ in перед тим, Ñк додавати речі до вашого кошика. + +/pay/modify.bml.error.notloggedinforcoppa=Ðе можу виконати вікову перевірку Ð´Ð»Ñ Ð½ÐµÐ·Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ кориÑтувача. + +/pay/modify.bml.error.notloggedinforitem=Ви повинні залогуватиÑÑ, щоб придбати [[item]]. + +/pay/modify.bml.error.notloggedinpaying=Більше не залоговані, але платите за залогований рахунок. + +/pay/modify.bml.error.notunderage=Вікова перевірка Ð´Ð»Ñ [[user]] не вимагаєтьÑÑ. + +/pay/modify.bml.error.notyourcart=Ви не Ñ” влаÑником цього кошика. Якщо ви хочете розпочати новий кошик, будь лаÑка, натиÑніть Ñюди. + +/pay/modify.bml.error.notyourcoupon=Купон належить комуÑÑŒ іншому. + +/pay/modify.bml.error.nousernamegiven=Будь-лаÑка, додайте ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, що повинен отримати подарунок. + +/pay/modify.bml.error.outofstock=Вибачте, вибрані товари відÑутні. + +/pay/modify.bml.error.paidwillexpire=Ви бажаєте купити [[item]], але ваш платний рахунок завершитьÑÑ Ð´Ð¾ того чаÑу, Ñк зміни до вашого першого платного рахунку у кошику вÑтуплÑÑ‚ÑŒ у дію. ОÑкільки [[item]] неможливо заÑтоÑувати без платного рахунку, він не може бути доданий до вашого кошику. + +/pay/modify.bml.error.underage=Ваш рехунок помічено Ñк неповнолітній (дивитиÑÑ Ð²Ð¸Ð¼Ð¾Ð³Ð¸ COPPA). Ви повинні повернутиÑÑ Ñ– додати COPPA Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾ вашого рахунку перед тим, Ñк продовжити. + +/pay/modify.bml.extrasremoved.header=Зауважте + +/pay/modify.bml.extrasremoved.text=Додаткові можливоÑÑ‚Ñ– можна придбати лише Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків. ÐаÑтупні речі будуть видалені із вашого кошика, тому що їхні отримувачі не мають платних рахунків Ñ– ви наразі не купуєте платний рахунок Ð´Ð»Ñ Ð½Ð¸Ñ…. + +/pay/modify.bml.openproxy.text=Ваша IP адреÑа ([[ip]]) визначена Ñк відкритий прокÑÑ– Ñервер (зазвичай це шлÑÑ… до шахрайÑтва), Ñ– тому доÑтуп до Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð±Ð¾Ñ€Ð¾Ð½ÐµÐ½Ð¾. Якщо ви переконані, що ви доÑтупаєтеÑÑ Ð² мережу не через відкритий прокÑÑ–, будь-лаÑка, звертайтеÑÑŒ за допомогою до вашого ІСП або до технічної підтримки цього Ñайту. + +/pay/modify.bml.openproxy.title=ВиÑвлено відкритий прокÑÑ– + +/pay/modify.bml.outofstock.header=ÐайменуваннÑ, Ñких немає в наÑвноÑÑ‚Ñ–... + +/pay/modify.bml.outofstock.morethan1=Якщо ви вÑе таки хочете зробити це замовленнÑ, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– вилучіть перелічені вище найменуваннÑ. + +/pay/modify.bml.outofstock.only1=Залежно від популÑрноÑÑ‚Ñ– товару, ми можемо замовлÑти чи відмовитиÑÑ Ð²Ñ–Ð´ нього надалі. Ви можете перевірити наÑвніÑÑ‚ÑŒ у магазині подарунків — там вказано, Ñкі товари Ñ” відÑутні. + +/pay/modify.bml.outofstock.text=Між чаÑом, коли ви зробили Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ– розрахувалиÑÑ, у Ð½Ð°Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ð»Ð¸ÑÑ Ð½Ð°Ñтупні товари, тому ми не можемо зарезервувати Ñ—Ñ… Ð´Ð»Ñ Ð²Ð°Ñ. + +/pay/modify.bml.outofstock.title=Ðемає у наÑвноÑÑ‚Ñ– + +/pay/modify.bml.paidtimewillexpire.header=Зауважте + +/pay/modify.bml.paidtimewillexpire.text1=Ви бажаєте купити [[item]], але Ñ‡Ð°Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ²ÐµÑ€ÑˆÐ¸Ñ‚ÑŒ Ñ‡Ð°Ñ Ñ‚Ñ€Ð¸Ð²Ð°Ð»Ð¾ÑÑ‚Ñ– до Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку [[user]]. + +/pay/modify.bml.paidtimewillexpire.text2=Ви можете продовжити, але нові можливоÑÑ‚Ñ– будуть недоÑтупні, коли платний рахунок [[user]] завершитьÑÑ. Однак, Ñкщо [[user]] одержить платний рахунок пізніше, решта [[item]] чаÑу буде заÑтоÑовано до його рахунку. + +/pay/modify.bml.paidtimewillexpire.text2_expires=Ви можете продовжити, але нові можливоÑÑ‚Ñ– будуть недоÑтупні, коли платний рахунок [[user]] завершитьÑÑ (наразі [[date]], не включаючи додаткового чаÑу у вашому кошику). Однак, Ñкщо [[user]] одержить платний рахунок пізніше, решта [[item]] чаÑу буде заÑтоÑовано до його рахунку. + +/pay/modify.bml.paypaldown.header=Платіжний шлюз не відповідає + +/pay/modify.bml.paypaldown.text=ПроÑимо вибаченнÑ, але через проблеми із шлюзом транзакцій PayPal, ми тимчаÑово не можемо доÑтупитиÑÑ Ð´Ð¾ платіжок PayPal. Будь-лаÑка, Ñпробуйте повернутиÑÑ Ñ‡ÐµÑ€ÐµÐ· декілька хвилин. + +/pay/modify.bml.paypaldown.title=PayPal тимчаÑово недоÑтупний + +/pay/modify.bml.shippingaddress.extracost=(додатковий платіжний збір поза межами СШРта Канади) + +/pay/modify.bml.shippingaddress.header=Введіть вашу адреÑу одержувача... + +/pay/modify.bml.shippingaddress.input.address=ÐдреÑа: + +/pay/modify.bml.shippingaddress.input.city=МіÑто: + +/pay/modify.bml.shippingaddress.input.country=Країна: + +/pay/modify.bml.shippingaddress.input.name=Ім’Ñ: + +/pay/modify.bml.shippingaddress.input.state=Штат: + +/pay/modify.bml.shippingaddress.input.zip=Поштовий код: + +/pay/modify.bml.shippingaddress.nointernationalorders=Сполучені Штати
    (Вибачне, міжнародні Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– неможливі.) + +/pay/modify.bml.shippingaddress.title=ÐдреÑа одержувача + +/pay/modify.bml.success.text=Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð¾. Ð”Ð»Ñ Ð¿Ð¾ÑиланнÑ, ваш номер Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ [[id]]. + +/pay/modify.bml.success.title=УÑпішно + +/pay/modify.bml.webmoney.intro=Ваше Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ буде завершене, доки ви не відішлете вашу платіжку WebMoney. + +/pay/modify.bml.webmoney.thankyou=ДÑкуємо. + +/pay/modify.bml.webmoney.title=РозрахуватиÑÑ Ñ‡ÐµÑ€ÐµÐ· WebMoney + +/pay/modify.bml.webmoney.whattodo=Ð”Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ…Ñ–Ð´Ð½Ð¾: + +/pay/modify.bml.webmoney.whattodo.comment=У поле Ð´Ð»Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð² у вікні "Переказати WebMoney" введіть номер Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ([[orderid]]) та ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача у [[sitename]]. ВикориÑтовуйте наÑтупний формат: + +/pay/modify.bml.webmoney.whattodo.comment.format|notes=Don't translate this string; it needs to remain in English. +/pay/modify.bml.webmoney.whattodo.comment.format="Order number [[orderid]] for LJ Account [[user]]". Make WebMoney Payment + +/pay/modify.bml.webmoney.whattodo.sendmoney=Переказати [[amount]] до WebMoney-Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ [[purseid]]. + +/pay/modify.bml.webmoney.whattodo.signin=Увійти до вашого рахунку WebMoney або Ñтворити новий. + +/pay/modify.bml.webmoney.whattodo.time=ÐžÐ¿Ñ€Ð°Ñ†ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ тривати до двох банківÑьких днів. + +/pay/yandex.bml.browsertitle=Перевірка Yandex + +/pay/yandex.bml.btn.proceed=ВикориÑтовувати Yandex Money + +/pay/yandex.bml.error.invalidcart=Вказаний кошик більше не Ñ” прийнÑтним. Це може бути викликане конфліктами із іншими кошиками, Ñтвореними в той Ñамий чаÑ. Спробуйте із новим кошиком. + +/pay/yandex.bml.error.notloggedin=Ви повинні ввійти Ñк влаÑник кошика, щоб продовжити перевірку. + +/pay/yandex.bml.error.notyourcart=Ви не Ñ” влаÑником кошика, Ñкщо ви бажаєте почати із новим кошиком, натиÑніть тут. + +/pay/yandex.bml.exchange_info=ВартіÑÑ‚ÑŒ вашого Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñƒ роÑійÑький рублÑÑ… Ñтановить [[ruble_amt]] (поточний ÐºÑƒÑ€Ñ Ñтановить [[exch_rate]] роÑійÑьких рублів за 1 американÑький долар. + +/pay/yandex.bml.title=Перевірка Yandex + +/poll/create.bml.button.editpoll=Змінити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.button.insert=Ð’Ñтавити + +/poll/create.bml.button.postpoll=Опублікувати Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.button.preview=Попередньо переглÑнути Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.button.seecode=ПодивитиÑÑ ÐºÐ¾Ð´ + +/poll/create.bml.button.startover=Почати знову + +/poll/create.bml.elements.limitreached=ДоÑÑгнута межа елементів + +/poll/create.bml.error.accttype=Ви повинні покращити Ñвій рахунок Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñтворювати опитуваннÑ. + +/poll/create.bml.error.accttype2=Ви можете Ñтворювати та надÑилати Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ у випадку, коли маєте Розширений або Платний рахунок чи відправлÑєте Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ Розширену або Платну Ñпільноту, в Ñкій ви Ñ” доглÑдачем. Якщо Ð²Ð°Ñ Ñ†Ñ–ÐºÐ°Ð²Ð¸Ñ‚ÑŒ докладніша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ зміну типів рахунку, задіть до Ñвого ÑтатуÑу рахунку. + +/poll/create.bml.error.allitemsblank=Ð’ÑÑ– Ð¿Ð¾Ð»Ñ Ð½Ðµ можуть бути порожніми. + +/poll/create.bml.error.notext=Ðеобхідний текÑÑ‚, поÑÑнюючий ваше Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/poll/create.bml.error.parsing=Помилка при обробці опитуваннÑ: + +/poll/create.bml.error.pqmaxlengthinvalid=Ðтрибут maxlength у текÑтових тегах lj-pq має бути цілим чиÑлом від [[min]] до [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Ðтрибут size у текÑтових тегах lj-pq має бути цілим чиÑлом від [[min]] до [[max]]. + +/poll/create.bml.error.scalemaxlessmin=Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¼Ð°Ñштабу "from" (від) має бути менше, ніж Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ "to" (до). + +/poll/create.bml.error.scalemininvalid=ПриріÑÑ‚ маÑштабу має бути щонайменше [[min]]. + +/poll/create.bml.error.scaletoobig=Межа [[max]] вибору (до-від)/приріÑÑ‚ > 20 + +/poll/create.bml.error.texttoolong=ТекÑÑ‚ варіанту занадто довгий Ñ– був Ñкорочений. + +/poll/create.bml.haserrors=У вашому Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð´Ð½Ð° чи більше помилок. Будь лаÑка, ÑпуÑтитьÑÑ Ð½Ð¸Ð¶Ñ‡Ðµ, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ. + +/poll/create.bml.insertquestion=Ð’Ñтавте Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñюди: + +/poll/create.bml.options=Варіанти: + +/poll/create.bml.options.limitreached=ДоÑÑгнута межа варіантів + +/poll/create.bml.pollname=Ім'Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ: (opt.) + +/poll/create.bml.preview.desc=Ðижче наведений попередній переглÑд вашого опитуваннÑ. Саме так воно виглÑдатиме, коли буде поміщено до вашого журналу. КориÑтуйтеÑÑ ÐºÐ½Ð¾Ð¿ÐºÐ°Ð¼Ð¸, наведеними нижче, щоб повернутиÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– зробити зміни або опублікувати це Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ вашому журналі. + +/poll/create.bml.preview.options=Варіанти + +/poll/create.bml.properties=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.question=ПитаннÑ: + +/poll/create.bml.questionnum=ÐŸÐ¸Ñ‚Ð°Ð½Ð½Ñ #[[num]] + +/poll/create.bml.questions=ÐŸÐ¸Ñ‚Ð°Ð½Ð½Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.seecode.desc=Ðижче наведено код Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ опитуваннÑ. ВикориÑтовуйте кнопки нижче, щоб повернутиÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– внеÑти зміни чи опублікувати Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ вашому журналі. + +/poll/create.bml.title=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/create.bml.type.check=Позначки + +/poll/create.bml.type.drop=Випадаючий ÑпиÑок + +/poll/create.bml.type.radio=Кнопки-перемикачі + +/poll/create.bml.type.scale=Шкала + +/poll/create.bml.type.text=ТекÑтовий Ð·Ð°Ð¿Ð¸Ñ + +/poll/create.bml.whoview=Хто може дивитиÑÑ Ñ†Ðµ опитуваннÑ? + +/poll/create.bml.whovote=Хто може голоÑувати в цьому опитуванні? + +/poll/index.bml.discuss=Обговорити результати + +/poll/index.bml.error.cantview=Вибачте, вам не дозволено дивитиÑÑ Ñ†Ðµ опитуваннÑ. + +/poll/index.bml.error.postdeleted=ЗапиÑ, Ñкому належало опитуваннÑ, видалено, тому Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ не доÑтупне. + +/poll/index.bml.filloutpoll=Заповнити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/index.bml.gotocreate2=Це адреÑа Ð´Ð»Ñ ÑƒÑ‡Ð°ÑÑ‚Ñ– в опитуванні. Ви наштовхнулиÑÑ Ð½Ð° адреÑу, Ñка на цей Ñ‡Ð°Ñ Ð½Ñ–Ñ‡Ð¾Ð³Ð¾ не робить. Якщо бажаєте, ви можете Ñтворити нове опитуваннÑ. + +/poll/index.bml.pollnotfound=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ знайдено. + +/poll/index.bml.submitted.head=ДÑкуємо + +/poll/index.bml.submitted.text=Ваші відповіді на Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ передано. + +/poll/index.bml.submitted.title=Передано! + +/poll/index.bml.title=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/poll/index.bml.viewresults=ДивитиÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¸ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/portal/index.bml.addbox=Додати блок + +/portal/index.bml.configtitle=Змінити опції "Мій [[sitenameabbrev]]" + +/portal/index.bml.pagetitle=Мій [[sitenameabbrev]] + +/portal/index.bml.resetall=Ви впевнені у бажанні вÑтановити вÑÑ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм? + +/portal/index.bml.resetalltitle=Скинути? + +/portal/index.bml.returnlink=ПовернутиÑÑ Ð´Ð¾ Мого [[sitenameabbrev]] + +/postreg/find.bml.browse=ПереглÑд [[sitename]] + +/postreg/find.bml.browse.feeds=Потоки + +/postreg/find.bml.browse.feeds.desc=Додавайте улюблені Ñайти до Ñвоєї Ñтрічки друзів, викориÑтовуючи їхні потоки RSS/Atom. + +/postreg/find.bml.browse.popinterests=ПопулÑрні Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/postreg/find.bml.browse.popinterests.desc=ПереглÑнути найпопулÑрніші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñƒ [[sitename]]. + +/postreg/find.bml.browse.schools=Ðавчальні заклади + +/postreg/find.bml.browse.schools.desc=Знайдіть людей, Ñкі навчаютьÑÑ Ð°Ð±Ð¾ закінчили ваш навчальний заклад. + +/postreg/index.bml.setting.bio.error.invalid=Ðевірна Ð±Ñ–Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ñ + +/postreg/index.bml.setting.bio.note=Можна викориÑтовувати малюнки, лічильники Ñ– інший HTML + +/postreg/index.bml.setting.bio.question=БіографіÑ: + +/postreg/index.bml.setting.birthday.question=Дата народженнÑ: + +/postreg/index.bml.setting.birthdaydisplay.error.invalid=Виберіть найкращий вид Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð´Ð½Ñ Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/postreg/index.bml.setting.birthdaydisplay.question=ВідображеннÑ: + +/postreg/index.bml.setting.gender.error.invalid=Вибіріть Ñтать: чоловічу,жіночу або не зазначену + +/postreg/index.bml.setting.gender.question=Стать: + +/postreg/index.bml.setting.interests.desc=Перелічить ваші захопленÑ, найчаÑтіше це те, чим можна завершити фразу "Мені подобаєтьÑÑ...." + +/postreg/index.bml.setting.interests.note=Перерахуйте ваші захопленнÑ, розділені комами + +/postreg/index.bml.setting.interests.question=ЗахопленнÑ: + +/postreg/index.bml.setting.name.question=Ім'Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ: + +/postreg/index.bml.skip_step_title=ПропуÑтити цей крок + +/postreg/index.bml.title=Починаємо + +/postreg/index.bml.welcome=Вітаємо на [[sitename]]! Ваш рахунок уÑпішно Ñтворено. Email був надіÑланий на [[email]] з подальшими інÑтрукциÑми. ÐатиÑніть на поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² лиÑÑ‚Ñ–, Ñ– ви будете в ЖЖ. + +/press.staff.bml.joydtaylor.title=Реклама та ÑпонÑорÑтво + +/press/articles.bml.articles.header=Ðрхіви + +/press/articles.bml.articles.text=Тут, у LiveJournal, ми намагаємоÑÑ Ð²Ñ–Ð´Ñтежувати вÑÑ– згадки про Ð½Ð°Ñ Ñƒ ЗМІ й архівувати Ñ—Ñ… у кориÑтувача [[pressuser]]. Ðа цій Ñторінці Ð´Ð»Ñ Ð·Ñ€ÑƒÑ‡Ð½Ð¾ÑÑ‚Ñ– перелічені 5 оÑтанніх згадок про Ð½Ð°Ñ Ñƒ ЗМІ. + +/press/articles.bml.back2=ПовернутиÑÑ Ð´Ð¾ преÑ-зони + +/press/articles.bml.listing.header=Перелік: + +/press/articles.bml.snippets.header=Цитати: + +/press/articles.bml.title=LiveJournal у ЗМІ + +/press/index.bml.company.contributors=Помічники + +/press/index.bml.company.header=ÐšÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ + +/press/index.bml.company.staff=Керівний Ñклад + +/press/index.bml.contact.header=Контактна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/press/index.bml.contact.header2=Контакти Ð´Ð»Ñ Ð—ÐœÐ† + +/press/index.bml.contact.text=Ð”Ð»Ñ Ð·Ð²'Ñзку з працівником LiveJournal ÑтоÑовно зв'Ñзків з громадÑькіÑÑ‚ÑŽ або активноÑÑ‚Ñ– в ЗМІ, надішліть лиÑта на адреÑу: [[pressemail]]. + +/press/index.bml.contact.text2=Щоб зв’ÑзатиÑÑ Ð· працівником [[sitename]] зі зв’Ñзків з громадÑькіÑÑ‚ÑŽ та ЗМІ, заповніть та відправте форму. + +/press/index.bml.form.btn.edit=Змінити + +/press/index.bml.form.btn.preview=Попередній переглÑд + +/press/index.bml.form.btn.reset=Скинути + +/press/index.bml.form.btn.send=ÐадіÑлати + +/press/index.bml.form.error.header=Помилка: + +/press/index.bml.form.error.invalidemail=Схоже, ваша email-адреÑа неправильна. + +/press/index.bml.form.error.noemail=Ви повинні вказати Ñвою email-адреÑу. + +/press/index.bml.form.error.nomessage=Ви маєте ввеÑти текÑÑ‚ повідомленнÑ. + +/press/index.bml.form.error.nosubject=Ви маєте вказати тему. + +/press/index.bml.form.error.sendfailed=Ðе вдалоÑÑ Ð½Ð°Ð´Ñ–Ñлати повідомленнÑ. + +/press/index.bml.form.from.label=Від: + +/press/index.bml.form.from.note=Вкажіть email-адреÑу Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ñ–. + +/press/index.bml.form.message.label=ПовідомленнÑ: + +/press/index.bml.form.subject.label=Тема: + +/press/index.bml.form.success=Вашого лÑта надіÑлано. ДÑкуємо за Ð·Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð´Ð¾ [[sitename]]! + +/press/index.bml.form.to.label=До: + +/press/index.bml.form.to.value=ПреÑ-Ñлужба [[sitename]] + +/press/index.bml.general.articles=LiveJournal у ЗМІ + +/press/index.bml.general.header=Загальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/press/index.bml.general.stats=СтатиÑтика + +/press/index.bml.media.header=Зв'Ñзки з преÑою + +/press/index.bml.media.text=LiveJournal вітає зв'Ñзки з преÑою. Якщо ви не знайшли тут необхідної інформації, не ÑоромтеÑÑ Ð·Ð²ÐµÑ€Ñ‚Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ Ð½Ð°Ñ Ñ–Ð· будь-Ñкими запитами. + +/press/index.bml.title=ПреÑ-зона LiveJournal + +/press/index.bml.webby.alt=Переможець премії People's Choice 2001 у двох номінаціÑÑ… + +/press/index.bml.webby.caption=Переможець премій
    2004 та 2001 People's Voice + +/press/staff.bml.about=LiveJournal.com заÑновано у 1999 році Ñк проект Бреда Фіцпатріка (Brad Fitzpatrick) Ñ– протÑгом перших двох років підтримувавÑÑ Ð²ÐµÐ»Ð¸ÐºÐ¾ÑŽ прихильною групою волонтерів. Хоча LiveJournal.com Ñ– доÑÑ– підтримуєтьÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸ волонтерів, зараз ми маємо невеликий керівний Ñклад, Ñкий доглÑдає за вÑіма операціÑми. + +/press/staff.bml.arie.quip=екзиÑтенціалізм та природа об'єктивної правди, четвертий Ñ€Ñдок. + +/press/staff.bml.arie.title=ПоÑтачальник Ñпокою та Ñ€Ð¾Ð·ÑƒÐ¼Ñ–Ð½Ð½Ñ + +/press/staff.bml.avva.title=Старший розробник + +/press/staff.bml.back2=ПовернутиÑÑ Ð´Ð¾ преÑ-зони + +/press/staff.bml.bradfitz.quip=ЗоÑереджуйÑÑ Ð½Ð° Ñвоєму продукті, а не лише на заробітку грошей. + +/press/staff.bml.bradfitz.title=ІнфраÑтруктура + +/press/staff.bml.burr86.quip=Знамениті оÑтанні Ñлова: ЗвіÑно, Ñ Ð¼Ð¾Ð¶Ñƒ зробити це. + +/press/staff.bml.burr86.title=Фаворит + +/press/staff.bml.chasethestars.quip=I'm not a sockpuppet. I just play one on TV. + +/press/staff.bml.chasethestars.title=КориÑтувач LiveJournal + +/press/staff.bml.coffeechica.quip=Ми вÑе ще хоробро б'ємоÑÑ Ð· вітрÑками! + +/press/staff.bml.coffeechica.title=Кава Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ñ–Ð»Ñƒ підтримки + +/press/staff.bml.community=Маркетинг + +/press/staff.bml.contact.abuse=ÐŸÐ¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ ÑƒÐ¼Ð¾Ð² Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг + +/press/staff.bml.contact.feedback=Відгуки та пропозиції + +/press/staff.bml.contact.header=Зв'Ñзок з LiveJournal: + +/press/staff.bml.contact.press=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ð—ÐœÐ† + +/press/staff.bml.contact.sales=Рекламні Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/press/staff.bml.contact.support=Підтримка клієнтів та технічна підтримка + +/press/staff.bml.crucially.quip=Один раз живемо + +/press/staff.bml.crucially.title=Керівник розробки + +/press/staff.bml.custserv=ОбÑÐ»ÑƒÐ³Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñ–Ð² / ДоÑÐ»Ñ–Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ñ€ÑƒÑ‡Ð½Ð¾ÑÑ‚Ñ– + +/press/staff.bml.daisy.quip=Прошу не Ñ—Ñти кульбаби + +/press/staff.bml.daisy.title=PR менеджер + +/press/staff.bml.david.title=Шепотун коду + +/press/staff.bml.deflatermouse.quip=Дехто випив забагато Ñ– жарти зайшли занадто далеко + +/press/staff.bml.denisep.quip=Гроші та Ñлава, дитинко. Гроші та Ñлава. + +/press/staff.bml.denisep.title=Провидець + +/press/staff.bml.design=Ð’Ð·Ð°Ñ”Ð¼Ð¾Ð´Ñ–Ñ Ñ‚Ð° візуальний дизайн + +/press/staff.bml.deveiant.title=Кваліфікований хакер + +/press/staff.bml.developers=Розробники + +/press/staff.bml.ferrell.title=Керівник обÑÐ»ÑƒÐ³Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñ–Ð² + +/press/staff.bml.hachi.quip=кориÑтуватиÑÑ Ñ‡Ñ–Ñ‚ÐºÐ¾ + +/press/staff.bml.hachi.title=Пірат Перлу + +/press/staff.bml.henrylyne.quip=Штурхани мене ще раз + +/press/staff.bml.henrylyne.title=Хімік форми та функцій + +/press/staff.bml.jamisononfire.quip=Я - Кітті. Ти - Кітті. (поÑÑненнÑ) + +/press/staff.bml.jamisononfire.title=Дизайнер взаємодії + +/press/staff.bml.janinedog.quip=Я б знÑла це. + +/press/staff.bml.janinedog.title=Виконавець випадкових завдань + +/press/staff.bml.joydtaylor.quip=Ви не можете робити Ñьогоднішню роботу учорашніми методами та бути у Ñправі завтра. + +/press/staff.bml.joydtaylor.title=ЕкÑперт з реклами та ÑпонÑорÑтва + +/press/staff.bml.jproulx.quip=Фанатик по зв'Ñзкам із кориÑтувачами + +/press/staff.bml.jproulx.title=ÐаглÑдач Ñайту Ñпільноти / Зв'Ñзки з преÑою + +/press/staff.bml.jtrevino.quip=Проблема? Вихід Ñ”! ÐŸÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ + +/press/staff.bml.jtrevino.title=ПрограміÑÑ‚ + +/press/staff.bml.kevink.quip=Я ніколи не одÑгаю коÑтюм на роботу. Хотів би Ñ Ð½Ñ–ÐºÐ¾Ð»Ð¸ не одÑгати Ñправжні туфлі. + +/press/staff.bml.kevink.title=КоÑтюмчик + +/press/staff.bml.kimmi8.quip=Я їм лише низькокалорійні фрукти. + +/press/staff.bml.kimmi8.title=МаньÑк контролю (Менеджер продукту) + +/press/staff.bml.lisa.quip=безштанько + +/press/staff.bml.lisa.title=Головний ÑиÑтемний адмініÑтратор + +/press/staff.bml.ljkrissy.quip=Ðе дозволÑйте покидькам зіпÑувати вам наÑтрій. + +/press/staff.bml.ljkrissy.title=Джерело галаÑу (маркетинг) + +/press/staff.bml.mahlon.quip=Ик ик! + +/press/staff.bml.mahlon.title=Кодова мавпа + +/press/staff.bml.markf.title=Маркіз Шатра + +/press/staff.bml.marksmith.quip=Якщо не виходить з першого разу, то... ну Ñк у парашутному Ñпорті! + +/press/staff.bml.marksmith.title=Хакер звичайного поÑолу + +/press/staff.bml.matthew.title=СиÑтемний адмініÑтратор + +/press/staff.bml.mgmt=Керівники + +/press/staff.bml.poignantly.quip=Те, що це популÑрно, не означає, що це гарно. + +/press/staff.bml.poignantly.title=Веб-розробник + +/press/staff.bml.revmischa.quip=Ðе дозволÑйте Людині зіпÑувати вам наÑтрій. + +/press/staff.bml.revmischa.title=Багатофункціональний приÑтрій Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ програм + +/press/staff.bml.ryanfitz.title=СвійÑька мавпочка (керівник виробництва) + +/press/staff.bml.sales=Продажі + +/press/staff.bml.sandy.title=Ð‘ÑƒÑ…Ð³Ð°Ð»Ñ‚ÐµÑ€Ñ–Ñ Ñ‚Ð° адмініÑтративна робота + +/press/staff.bml.smithy.title=Хакер-учень + +/press/staff.bml.sysadmin=СиÑтемні адмініÑтратори + +/press/staff.bml.technopatra.quip=Зі ÑвÑтих корів готують найкращі гамбургери. + +/press/staff.bml.technopatra.title=МайÑÑ‚Ñ€Ð¸Ð½Ñ ÐºÐ°Ñ€ÐºÐ°Ñу + +/press/staff.bml.title=Керівний Ñклад + +/press/staff.bml.toppledwagon.title=СиÑтемний адмініÑтратор + +/press/staff.bml.veroz.quip=о боже Ñк це Ñюди потрапило Ñ Ð½Ðµ дуже Ñ‚Ñмлю у комп'ютерах + +/press/staff.bml.veroz.title=Раб Дизайну 5000 + +/press/staff.bml.whitaker.quip=Що далі? + +/press/staff.bml.whitaker.title=Perl'овий маніÑк + +/press/staff.bml.winniewong.quip=Зараз на 40% більше дівчат, що танцюють у клубах. + +/press/staff.bml.winniewong.title=Дизайн 4000 + +/press/staff.bml.zhizhu.quip=Привіт, крихітко! Хочеш вбити уÑÑ–Ñ… людей? + +/press/staff.bml.zhizhu.title=Робото-дитина + +/pubkey.bml.error.notconfigured=Ðа цьому Ñайті не налаштована підтримка PGP. + +/pubkey.bml.error.nousername=Ðе зазначене ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/pubkey.bml.info.desc=Ðе знаєте, що таке публічний ключ? Прочитайте більше про PGP та GPG. + +/pubkey.bml.info.head=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/pubkey.bml.info.upload=Бажаєте завантажити Ñвій ключ? ÐатиÑніть тут. + +/pubkey.bml.label=Публічний ключ Ð´Ð»Ñ [[user]]: + +/pubkey.bml.nokey=[[user]] ще не завантажив публічний ключ. + +/pubkey.bml.title=ДивитиÑÑ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ð¹ ключ + +/register.bml.ask.body=ÐатиÑніть кнопку, наведену нижче, щоб надіÑлав перевірочного лиÑта до [[email]]. + +/register.bml.ask.button=ВідіÑлати + +/register.bml.ask.header=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ e-mail + +/register.bml.ask.select=Виберіть рахунок + +/register.bml.ask.switch=Змінити + +/register.bml.asterisk.comment=(Будь лаÑка, зверніть увагу, що рахунки, помічені зірочкою, ще не перевірені) + +/register.bml.email.body|notes=This string is used to create an option in the "Work as user" drop down list to allow a user to view all of their journals. The * signifies that the acount, specified by [[journal]], is not validated yet. +/register.bml.email.body<< +Це перевірочний лиÑÑ‚, Ñкий Ви проÑили надіÑлати. +Щоб закінчити перевірку Вашого рахунку, завітайте, будь лаÑка, за цією адреÑою: + + [[conflink]] + +Ви можете Ñкопіювати та вÑтавити це поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð¾ вікна Вашого браузеру. + +З найкращими побажаннÑми, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ e0mail + +/register.bml.error.emailchanged=Перевірочне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ” заÑтарілим. Будь лаÑка, запитайте новий перевірочний лиÑÑ‚. + +/register.bml.error.identity_no_email=Ви не вÑтановили email. Перейдіть Ñюди, щоб це зробити. + +/register.bml.error.invalidcode=ÐеприпуÑтимий перевірочний код. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñƒ лиÑÑ‚Ñ– може бути заÑтарілим; ви можете запитати новий перевірочний лиÑÑ‚. + +/register.bml.error.useralreadyvalidated=Е-mail адреÑу кориÑтувача [[user]] вже перевірено. + +/register.bml.error.usernotfound=КориÑтувача не знайдено. + +/register.bml.new.101.community.answer=ДиÑкуÑійні групи будуютьÑÑ Ð½Ð°Ð²ÐºÐ¾Ð»Ð¾ будь-Ñкої теми. Музика, нінзі - тут можна знайти щоÑÑŒ Ð´Ð»Ñ Ñебе. + +/register.bml.new.101.community.question=Що таке Ñпільнота? + +/register.bml.new.101.friends.question=Що таке Ñтрічка друзів? + +/register.bml.new.101.journal.answer=Ð’ Ñвоєму журналі можна ділитиÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ð²Ñ–Ð´Ñми, фотографіÑми, відео та інш. + +/register.bml.new.101.journal.question=Що таке журнал? + +/register.bml.new.101.profile.answer=Ð’Ñе хороше про ваÑ. МожливіÑÑ‚ÑŒ показати Ñебе в юзерпиках, інтереÑах, біографії та інш. + +/register.bml.new.101.profile.question=Що таке профіль? + +/register.bml.new.bodyuser=ДÑкуємо! Е-mail адреÑу кориÑтувача [[user]] перевірено. Тепер ви можете зробити наÑтупне: + +/register.bml.new.customize=Ðалаштувати журнал — Ðалаштувати виглÑд вашого журналу + +/register.bml.new.customize2=Ðалаштуйте журнал — змініть виглÑд Ñвого журналу, обравши Ñтиль та тему + +/register.bml.new.editinfo2=Змінити профіль — заповніть Ñвій профіль кориÑтувача та вкажіть деÑкі налаштуваннÑ. + +/register.bml.new.editinfo3=Змініть профіль — напишіть розповідь про Ñебе, додайте Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° контактну інформацію + +/register.bml.new.header=УÑпішно + +/register.bml.new.login2=Увійти — таким чином вам не доведетьÑÑ Ð¿Ð¾Ñтійно вказувати Ñвої ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача й пароль. + +/register.bml.new.modify2=Ðалаштувати журнал — змініть виглÑд Ñвого журналу. + +/register.bml.new.search=Знайдіть інших — знайдіть друзів та Ñпільноти, Ñкі поділÑÑŽÑ‚ÑŒ ваші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/register.bml.new.title=ЛаÑкаво проÑимо до [[sitename]] + +/register.bml.new.update2=Оновити журнал - напишіть до Ñвого журналу. + +/register.bml.new.update3=Ðапишіть до журналу — Ñтворіть Ð·Ð°Ð¿Ð¸Ñ Ð°Ð±Ð¾ надішліть зображеннÑ, відео чи Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/register.bml.new.userpics=Завантажте юзерпики — завантажте аватари чи іконки, що предÑтавлÑтимуть Ð²Ð°Ñ + +/register.bml.sent.body=Перевірочний лиÑÑ‚ було виÑлано до [[email]]. Щоб завершити перевірку, вам треба натиÑнути на поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñƒ цьому лиÑÑ‚Ñ–. + +/register.bml.sent.header=УÑпішно + +/register.bml.title=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ e-mail + +/register.bml.trans.body=Вашу e-mail адреÑу було перевірено. + +/register.bml.trans.header=УÑпішно + +/rename/index.bml.does=ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ змінює лише ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Ð’ÑÑ Ñ€ÐµÑˆÑ‚Ð° - платний чи поÑтійний Ñтан рахунку, привілеї кориÑтувача, оÑобиÑÑ‚Ñ– дані, друзі та інші дані, пов'Ñзані з рахунком, - залишаєтьÑÑ Ð±ÐµÐ· змін Ñ– буде пов'Ñзана з новим іменем кориÑтувача. Ð’ÑÑ– Ñ–Ñнуючі коментарі в інших журналах та запиÑи у Ñпільнотах показуватимуть нове ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/rename/index.bml.faqurl=Щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ, дивітьÑÑ Ð¿Ð¾ÑˆÐ¸Ñ€ÐµÐ½Ðµ Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ перейменуваннÑ. + +/rename/index.bml.fee=Грошовий збір за зміну вашого імені кориÑтувача LiveJournal Ñтановить [[fee]]. + +/rename/index.bml.heading.cost=ВартіÑÑ‚ÑŒ + +/rename/index.bml.heading.details=Деталі + +/rename/index.bml.heading.how=Як купити + +/rename/index.bml.option=Ви можете обрати чи перенаправити Ñтаре ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача до нового, чи помітити його Ñк видалене. Ви також можете обрати чи люди, що додали Ð²Ð°Ñ Ñк друга, продовжують мати ваше нове ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ñк друга, чи воно буде вилучено зі ÑпиÑків друзів вÑÑ–Ñ… інших кориÑтувачів. + +/rename/index.bml.options.buy=Купити знак + +/rename/index.bml.options.buy.desc=Купити знак Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +/rename/index.bml.options.use=ВикориÑтати знак + +/rename/index.bml.options.use.desc=ВикориÑтати знак Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +/rename/index.bml.redeem=Спочатку ви купуєте знак перейменуваннÑ, Ñкий надÑилаєтьÑÑ Ð²Ð°Ð¼ електронною поштою, а потім, коли ви його отримуєте, викориÑтовуєте цей знак, щоб зробити дійÑне перейменуваннÑ. Кошти за знаки Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ повертаютьÑÑ, але Ñамі знаки передаютьÑÑ. Це значить, що ви можете купити знак Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¾Ð³Ð¾ кориÑтувача. + +/rename/index.bml.reserve=Ви не повинні Ñтворювати рахунок Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ нового імені кориÑтувача Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб ÑкориÑтатиÑÑ Ð½Ð¸Ð¼ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ. Проте, Ñкщо ви турбуєтеÑÑ, що хтоÑÑŒ може забрати ім'Ñ Ð´Ð¾ того, Ñк ви зможете купити та викориÑтати знак перейменуваннÑ, то вам Ñлід Ñтворити рахунок з новим іменем кориÑтувача. ПереконайтеÑÑ, що кориÑтуєтеÑÑ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ рахунку тими Ñамими e-mail адреÑою та паролем, Ñкими ви кориÑтуєтеÑÑ Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ рахунку. + +/rename/index.bml.title=ПоÑлуга Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/rename/index.bml.whatrename=Ви можете перейменувати ваш оÑобиÑтий рахунок, а також будь-Ñку Ñпільноту або Ñпільний журнал, Ñкий ви утримуєте. + +/rename/use.bml.changes=ÐаÑтупні зміни будуть зроблені піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк завершитьÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ: + +/rename/use.bml.changes.move="[[newuser]]" буде переміщено до "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" буде перейменований на "[[newuser]]" + +/rename/use.bml.confirm.click=ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ натіÑніть "Перейменувати": + +/rename/use.bml.confirm2=ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви натиÑнете кнопку "Перейменувати" унизу, ÑкаÑувати цю зміну буде неможливо. Як заÑіб підтвердженнÑ, надрукуйте великими літерами Ñлово "[[confirmword]]" у полі, розташованому нижче. + +/rename/use.bml.error.allocating=Помилка при визначенні імені Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð´Ð¾ рахунку призначеннÑ. + +/rename/use.bml.error.badpass=Паролі до Ñтарого та нового імен кориÑувачів не збігаютьÑÑ. + +/rename/use.bml.error.differentusername=Це не те ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, під Ñким ви увійшли, коли завантажили цю форму. + +/rename/use.bml.error.login=Спочатку ви маєте увійти. + +/rename/use.bml.error.notvalidated=Е-mail адреÑи одного чи більше рахунків з тих, що задіÑні, не перевірені. Перш ніж ви перейменуєте Ñвій журнал, ви маєте перевірити Ñвою e-mail адреÑу. Будь лаÑка, дивітьÑÑ Ð¯Ðº мені перевірити мою e-mail адреÑу?, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ, Ñк перевірити вашу e-mail адреÑу. + +/rename/use.bml.error.protected=Таке ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже викориÑтовуєтьÑÑ. + +/rename/use.bml.error.readit=Прочитайте абзац вище. + +/rename/use.bml.error.reserved=Помилка при перенеÑенні зарезервованого імені рахунку. + +/rename/use.bml.error.same=Це таке ж ім'Ñ, Ñк ваше Ñтаре ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/rename/use.bml.error.token=Ðевірний знак перейменуваннÑ. + +/rename/use.bml.error.type=Лише звичайні рахунки можуть бути перейменовані, а не рахунки Ñпільнот. + +/rename/use.bml.error.unknown=Під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ ÑталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка. + +/rename/use.bml.error.usedtoken=Цей знак вже було викориÑтано. + +/rename/use.bml.error.username=Ðевірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/rename/use.bml.error.usernametaken=Це ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже викориÑтовуєтьÑÑ. + +/rename/use.bml.heading.changes=Зміни + +/rename/use.bml.heading.success=УÑпішно + +/rename/use.bml.heading.sure=Ви впевнені? + +/rename/use.bml.intent=Ð¦Ñ Ñторінка призначена Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви прочитали наÑтанову та купили знак перейменуваннÑ. + +/rename/use.bml.label.desired=Бажане ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/rename/use.bml.label.proceed=Продовжити... + +/rename/use.bml.label.rename=Перейменувати + +/rename/use.bml.label.token=Знак перейменуваннÑ: + +/rename/use.bml.label.username=Поточне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/rename/use.bml.options=Параметри перейменуваннÑ: + +/rename/use.bml.options.delfriends=Вилучити вÑÑ–Ñ… кориÑтувачів з вашого ÑпиÑку друзів та покинути вÑÑ– Ñпільноти. + +/rename/use.bml.options.forward=Ðвтоматично перенаправлÑти кориÑтувачів з [[oldname]] до нового імені кориÑтувача. + +/rename/use.bml.options.keepfriends=Залишити вÑÑ–Ñ… кориÑтувачів та Ñпільноти у вашому ÑпиÑку друзів. + +/rename/use.bml.options.keepself=Залишити вÑÑ–Ñ… у вашому ÑпиÑку "У друзÑÑ…". + +/rename/use.bml.options.removeself=Вилучити вÑÑ–Ñ… з вашого ÑпиÑку "У друзÑÑ…". + +/rename/use.bml.options.unlink=Ðе тримати зв'Ñзок між [[oldname]] та новим журналом. + +/rename/use.bml.success.login=Зараз вам потрібно увійти знов. + +/rename/use.bml.success.moved="[[newuser]]" було переміщено до "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" було перейменовано на "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача було перейменовано. + +/rename/use.bml.title=ВикориÑтати знак Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +/resetpassword.bml.email.body<< +Ваш пароль до рахунку на Ñайті [[sitename]] було змінено. Це нові дані вашого рахунку: + + Рахунок: [[username]] + Пароль: [[password]] + +За поÑиланнÑм ви зможете змінити пароль на той, що запам'Ñтаєте: + + [[changepasswordurl]] + +ДÑкуємо, +команда [[sitename]] +. + +/resetpassword.bml.email.body.notvalidated<< +Пароль до вашого рахунку [[sitename]] було анульовано. ОÑÑŒ нові дані доÑтупу: + + Рахунок: [[username]] + Пароль: [[password]] + +Ви можете змінити пароль на більш зручний тут: + + [[changepasswordurl]] + +Завважте, що ви не зможете змінити пароль, поки ваш email не пройде перевірку, ініціювати Ñку можна тут: + + [[validationurl]] + + +ДÑкуємо, +колектив [[sitename]] +. + +/resetpassword.bml.email.subject=Зміна паролю [[sitename]] + +/resetpassword.bml.error.actionalreadyperformed=Цю дію вже було виконано. + +/resetpassword.bml.error.emailchanged=Ви змінили Ñвій email піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк замовили Ð°Ð½ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ. Щоб змінити пароль, Вам потрібно знову його анулювати. + +/resetpassword.bml.error.invalidaction=Ðевірна діÑ. + +/resetpassword.bml.error.invalidarg=Задано невірний аргумент. + +/resetpassword.bml.error.invaliduser=Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: невірний кориÑтувач + +/resetpassword.bml.success.header=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½Ð¸ паролю + +/resetpassword.bml.success.text=Ваш новий пароль відправлено до вашої email-адреÑи. + +/resetpassword.bml.title=Змінити пароль до рахунку + +/schools/index.bml.addschool.example=Приклад: + +/schools/index.bml.addschool.input.city=МіÑто: + +/schools/index.bml.addschool.input.city.examples=Київ, Ð—Ð°Ð¿Ð¾Ñ€Ñ–Ð¶Ð¶Ñ + +/schools/index.bml.addschool.input.country=Країна + +/schools/index.bml.addschool.input.name=Ðазва навчального закладу: + +/schools/index.bml.addschool.input.name.campus2=Ð”Ð»Ñ Ñ„Ñ–Ð»Ñ–Ð¹ навчальних закладів вказуйте назву міÑта піÑÐ»Ñ Ð´ÐµÑ„Ñ–Ñу (наприклад, "УніверÑитет "Україна" - Київ") + +/schools/index.bml.addschool.input.name.examples=ДніпропетровÑький національний універÑитет, Ð¡ÐµÑ€ÐµÐ´Ð½Ñ ÑˆÐºÐ¾Ð»Ð° â„–11 + +/schools/index.bml.addschool.input.name.fullname2=Вказуйте повну назву навчального закладу (наприклад, "Ð¡ÐµÑ€ÐµÐ´Ð½Ñ ÑˆÐºÐ¾Ð»Ð° â„–123", заміÑÑ‚ÑŒ "школа 123") + +/schools/index.bml.addschool.input.name.noabbrev2=Без абревіатур. (Ðе пишіть КПІ, ДÐУ та Ñ‚.ін.) + +/schools/index.bml.addschool.input.state=ОблаÑÑ‚ÑŒ/штат: + +/schools/index.bml.addschool.input.state.examples=КиївÑька облаÑÑ‚ÑŒ + +/schools/index.bml.addschool.input.url=ÐдреÑа Ñайту: + +/schools/index.bml.addschool.input.url.optional=(необов'Ñзково) + +/schools/index.bml.addschool.intro=Вкажіть інформацію про Ñвій навчальний заклад. ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸, заклад буде додано до Каталогу та ÑпиÑку навчальних закладів у вашому журналі: + +/schools/index.bml.allcountries.header=Ð’ÑÑ– країни + +/schools/index.bml.btn.add=Додати + +/schools/index.bml.btn.addschool=Додати навчальний заклад + +/schools/index.bml.btn.chooseschool=Обрати навчальний заклад + +/schools/index.bml.btn.filter=Фільтр + +/schools/index.bml.city.header=МіÑто + +/schools/index.bml.city.select=Обрати міÑто + +/schools/index.bml.dontseeschool=Ðе знайшли, що шукали? + +/schools/index.bml.dontseeschool.add=Додати навчальний заклад + +/schools/index.bml.error.cantfindschool=Ðавчальний заклад не знайдено. + +/schools/index.bml.error.cantgetcountries=Ðеможливо отримати ÑпиÑок країн. + +/schools/index.bml.error.cantgetdata=Ðеможливо отримати необхідні дані. + +/schools/index.bml.error.cantsetattendance=Ðеможливо зберегти роки Ð²Ñ–Ð´Ð²Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ [[name]]. + +/schools/index.bml.error.cantsetattendance_limit=Ðеможливо зберегти ваше Ð²Ñ–Ð´Ð²Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ [[name]], будь лаÑка, Ñпробуйте ще раз. Можливо ви доÑÑгли межи навчальних закладів, Ñкі могли відвідувати. + +/schools/index.bml.error.disabled=Каталог навчальних закладів зараз не працює через Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ñ‚ÐµÑ…Ð½Ñ–Ñ‡Ð½Ð¸Ñ… робіт. + +/schools/index.bml.error.invalidaustate=Ви повинні вказати правильне ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°Ð²ÑтралійÑького штату з двох чи трьох літер. + +/schools/index.bml.error.invalidcountry=Ви повинні вказати правильний код країни. + +/schools/index.bml.error.invalidprovince=Ви повинні вказати правильне ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ°Ð½Ð°Ð´Ñьких облаÑтей з двох літер. + +/schools/index.bml.error.invalidstate=Ви повинні вказати правильне ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°Ð¼ÐµÑ€Ð¸ÐºÐ°Ð½Ñьких штатів з двох літер. + +/schools/index.bml.error.invalidurl=Ðе вірно вказано адреÑу. + +/schools/index.bml.error.invalidyear=Ви повинні вказати правильний рік, щоб фільтрувати результати. + +/schools/index.bml.error.nocities=МіÑта не знайдено. + +/schools/index.bml.error.nocity=Ви повинні вказати міÑто, в Ñкому знаходитьÑÑ Ð½Ð°Ð²Ñ‡Ð°Ð»ÑŒÐ½Ð¸Ð¹ заклад. + +/schools/index.bml.error.nocountries=Країни не знайдено. + +/schools/index.bml.error.noname=Ви повинні вказати повну назву навчального закладу. + +/schools/index.bml.error.noschools=Ðавчальних закладів не знайдено. + +/schools/index.bml.error.nostates=Ðе знайдено облаÑтей чи штатів. + +/schools/index.bml.error.undefinedstate=облаÑÑ‚ÑŒ чи штат не зазначено + +/schools/index.bml.error.validaustates=Правильні ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð°Ð²ÑтралійÑьких штатів: ACT, NSW, NT, Qld, SA, Tas, Vic та WA. + +/schools/index.bml.error.validprovinces=Правильні ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð´Ñьких штатів: AB, BC, MB, NB, NL, NT, NS, NU, ON, PE, QC, SK та YT. + +/schools/index.bml.findschool=Знайти навчальний заклад у: + +/schools/index.bml.intro=З каталогом навчальних закладів ви можете: + +/schools/index.bml.intro.addschool=Додати навчальний заклад до вашого журналу або профілю Ñпільноти. + +/schools/index.bml.intro.dontseeschool3=Якщо ви не знайшли заклад, Ñкий шукали, додайте його ÑкориÑтувавшиÑÑŒ поÑиланнÑм "Додати навчальний заклад" знизу цієї Ñторінки. Ð”Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ будь-Ñкі помилки у каталозі, будь лаÑка, Ñтворіть запит підтримки у категорії "Schools Directory". + +/schools/index.bml.intro.findusers=Шукати інших кориÑтувачів та Ñпільноти, що пов'Ñзані з конкретним навчальним закладом. + +/schools/index.bml.intro.manageschools=Редагувати навчальні заклади, Ñкі ви відвідували. + +/schools/index.bml.matchesfound.header=Знайдено Ñхожі заклади + +/schools/index.bml.matchesfound.table.city=МіÑто + +/schools/index.bml.matchesfound.table.school=Ðавчальний заклад + +/schools/index.bml.matchesfound.table.url=ÐдреÑа Ñайту + +/schools/index.bml.matchesfound.text=Ми знайшли наÑтупні Ñхожі навчальні заклади у вашій країні та облаÑÑ‚Ñ–. Будь лаÑка, оберіть один з предÑтавлених навчальних закладів, або додайте нові дані, Ñкщо це інший навчальний заклад. Якщо дані вашого навчального закладу міÑÑ‚ÑÑ‚ÑŒ помилку, будь лаÑка, звернітьÑÑ Ð´Ð¾ Ñлужби підтримки, вказавши вÑÑŽ інформацію, що Ñ” в наÑвноÑÑ‚Ñ–. + +/schools/index.bml.school.addthisschool=Додати цей навчальний заклад Ð´Ð»Ñ [[user]] + +/schools/index.bml.school.browsejournals=ПереглÑнути журнали, Ñкі пов'Ñзані з цим навчальним закладом: + +/schools/index.bml.school.communities=Спільноти + +/schools/index.bml.school.findanother=Знайти інший навчальний заклад + +/schools/index.bml.school.header=Ðавчальний заклад + +/schools/index.bml.school.limitbyyear=Обмежити перелік роком: + +/schools/index.bml.school.manage=Редагувати ваші навчальні заклади + +/schools/index.bml.school.nousers=Жоден кориÑтувач чи Ñпільнота не зазначили цей навчальний заклад. + +/schools/index.bml.school.nousersforthisyear=Жоден кориÑтувач чи Ñпільнота не зазначили рік Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ [[year]] Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ навчального закладу. + +/schools/index.bml.school.select=Оберіть навчальний заклад + +/schools/index.bml.school.url=(офіційний Ñайт) + +/schools/index.bml.school.users=КориÑтувачі + +/schools/index.bml.schoolcount=([[numschools]] [[?numschools|навчальний заклад|навчальні заклади|навчальних закладів]]) + +/schools/index.bml.state.header=ОблаÑÑ‚ÑŒ + +/schools/index.bml.state.select=Оберіть облаÑÑ‚ÑŒ + +/schools/index.bml.stateorprovince.header=ОблаÑÑ‚ÑŒ чи штат + +/schools/index.bml.submitted.header=Ðавчальний заклад передано + +/schools/index.bml.submitted.manage=Перейти до вашого переліку навчальних закладів + +/schools/index.bml.submitted.return=ПовернутиÑÑ Ð´Ð¾ каталогу навчальних закладів + +/schools/index.bml.submitted.text=Ваш навчальний заклад передано Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸. У разі уÑпішної перевірки, навчальний заклад буде додано до каталогу навчальних закладів та автоматично додано до вашого ÑпиÑку навчальних закладів. Пізніше ви можете перевірити Ñторінку Редагувати навчальні заклади, щоб вказати роки відвідуваннÑ. + +/schools/index.bml.title=Каталог навчальних закладів + +/schools/index.bml.top5countries.header=Кращі п'ÑÑ‚ÑŒ країн + +/schools/manage.bml.btn.save=Зберегти зміни + +/schools/manage.bml.error.cantaddattendance=Помилка при додаванні років Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ Ñƒ навчальному закладі, Ñпробуйте пізніше. Ви могли доÑÑгти межі навчальних закладів, в Ñких навчалиÑÑ + +/schools/manage.bml.error.cantbeauthenticated=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +/schools/manage.bml.error.cantdeleteattendance=Помилка Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ€Ð¾ÐºÑ–Ð² Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ Ñƒ навчальному закладі, Ñпробуйте ще раз. + +/schools/manage.bml.error.cantendbeforestart=Рік Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð½Ðµ може бути менше, ніж рік вÑтупу. + +/schools/manage.bml.error.cantloadschool=Ðеможливо завантажити вказаний навчальний заклад + +/schools/manage.bml.error.cantsetattendance=Ðеможливо вÑтановити Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ Ñƒ "[[school]]", будь лаÑка, Ñпробуйте ще раз. Ви могли доÑÑгти межі навчальних закладів, що відвідували. + +/schools/manage.bml.error.currentlyattend=Якщо ви ще навчаєтеÑÑ Ð² цьому навчальному закладі, ви можете залишити поле ріку Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ–Ð¼ або вказати "[[now]]". + +/schools/manage.bml.error.disabled=Каталог навчальних закладів зараз не працює через Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ñ‚ÐµÑ…Ð½Ñ–Ñ‡Ð½Ð¸Ñ… робіт. + +/schools/manage.bml.error.locationdoesntmatch=Країна та/або міÑто не Ñпівпадають із зазначеним навчальним закладом. + +/schools/manage.bml.error.needstartingyear=Ви повинні вказати рік вÑтупу, Ñкщо зазначаєте рік закінченнÑ. + +/schools/manage.bml.error.toofuture=Рік вÑтупу повинен бути таким, що минув або йде зараз. + +/schools/manage.bml.error.toopast=Ви дійÑно навчалиÑÑ Ñ‚Ð°Ðº давно? + +/schools/manage.bml.findanother=Знайти інший навчальний заклад Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ. + +/schools/manage.bml.intro=Ðижче ви можете змінити ÑпиÑок навчальних закладів, що пов'Ñзані з вашим журналом чи Ñпільнотами. Ці дані Ñ” відкритими. + +/schools/manage.bml.noschools=Ви не вказали жодної школи. ПереглÑньте каталог навчальних закладів, щоб знайти та додати навчальні заклади. + +/schools/manage.bml.selectjournal=ДивитиÑÑ Ð½Ð°Ð²Ñ‡Ð°Ð»ÑŒÐ½Ñ– заклади: + +/schools/manage.bml.table.input.delete=Видалити + +/schools/manage.bml.table.name=Ðазва навчального закладу + +/schools/manage.bml.table.to=по + +/schools/manage.bml.table.years=Роки Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ + +/schools/manage.bml.title=Редагувати навчальні заклади + +/shop/index.bml.cart.btn.checkout=Придбати + +/shop/index.bml.cart.items=([[numitems]] [[?numitems|товар|товари|товарів]]) + +/shop/index.bml.cart.mycart=Кошик + +/shop/index.bml.cart.myorder=Моє Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/shop/index.bml.error.notloggedin=Ви повинні увійти Ñк влаÑник цього кошика, щоб додати чи придбати товари. + +/shop/index.bml.error.notyourcart=Ви не Ñ” влаÑником цього кошика. Якщо ви бажаєте Ñтворити новий кошик, будь лаÑка, натиÑніть Ñюди. + +/shop/index.bml.intro=Отримай 35% знижку на деÑкі товари та безкоштовну доÑтавку вÑÑ–Ñ… замовлень! + +/shop/index.bml.storefront.addons.header=Придбати Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ + +/shop/index.bml.storefront.addons.storage=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +/shop/index.bml.storefront.addons.text=Додайте до вашого платного рахунку ще більше юзерпик та розширте Ñвій диÑковий проÑÑ‚Ñ–Ñ€. + +/shop/index.bml.storefront.addons.userpics=[[numuserpics]] [[?numuserpics|юзерпику|юзерпик|юзерпик]] + +/shop/index.bml.storefront.gifts.extrauserpics=Подарувати додаткові юзерпики + +/shop/index.bml.storefront.gifts.giftcerts=Подарувати Ñертифікат + +/shop/index.bml.storefront.gifts.header=Подарунки від LiveJournal + +/shop/index.bml.storefront.gifts.paidaccount=Подарувати платний рахунок + +/shop/index.bml.storefront.gifts.text=Платний рахунок LiveJournal - це клаÑний подарунок! + +/shop/index.bml.storefront.gifts.vgifts=Віртуальні подарунки + +/shop/index.bml.storefront.merchandise.babydolltee=Жіноча футболка + +/shop/index.bml.storefront.merchandise.header=Товари LiveJournal + +/shop/index.bml.storefront.merchandise.hoodie=Кенгурка + +/shop/index.bml.storefront.merchandise.longsleeveshirt=Светр + +/shop/index.bml.storefront.merchandise.text=Сорочки й головні убори LiveJournal Ñких завгодно кольорів та розмірів. Придбай зараз. + +/shop/index.bml.storefront.merchandise.tshirt=Футболка + +/shop/index.bml.storefront.merchandise.twillhat=Кепі + +/shop/index.bml.storefront.new= + +/shop/index.bml.storefront.paidaccount.autopay.header=Ðвтоматична оплата + +/shop/index.bml.storefront.paidaccount.autopay.text=ВикориÑтовуй кредитну картку Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— оплати! + +/shop/index.bml.storefront.paidaccount.header=Придбати платний рахунок + +/shop/index.bml.storefront.paidaccount.manualpay.header=ОÑобиÑÑ‚Ñ– платежі + +/shop/index.bml.storefront.paidaccount.manualpay.text=РозраховуйÑÑ ÐºÑ€ÐµÐ´Ð¸Ñ‚Ð½Ð¾ÑŽ карткою, через PayPal, оÑобиÑтим чеком, грошовим переказом чи готівкою. + +/shop/index.bml.storefront.paidaccount.text=Отримай доÑтуп до вÑÑ–Ñ… прикольних можливоÑтей платного рахунку. + +/shop/index.bml.title=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ Ð¿Ð¾Ð´Ð°Ñ€ÑƒÐ½ÐºÑ–Ð² + +/shop/sizechart.bml.babydolls.bust=БюÑÑ‚ + +/shop/sizechart.bml.babydolls.header=Жіночі футболки + +/shop/sizechart.bml.babydolls.l=Великий + +/shop/sizechart.bml.babydolls.l_bust=94-96,5 Ñм + +/shop/sizechart.bml.babydolls.l_size=10/12 + +/shop/sizechart.bml.babydolls.l_waist=73,5-76 Ñм + +/shop/sizechart.bml.babydolls.m=Середній + +/shop/sizechart.bml.babydolls.m_bust=89-91,5 Ñм + +/shop/sizechart.bml.babydolls.m_size=6/8 + +/shop/sizechart.bml.babydolls.m_waist=68,5-71 Ñм + +/shop/sizechart.bml.babydolls.s=Маленький + +/shop/sizechart.bml.babydolls.subtext=Ці футболки зроблено обтÑгуючими, Ñ—Ñ… розміри відповідають розмірам, Ñким вони паÑуватимуть. Вони розтÑгуютьÑÑ, проте багато дівчат будуть відчувати Ñебе комфортніше у футболці трохи більшого розміру, ніж зазвичай вони купують. + +/shop/sizechart.bml.babydolls.s_bust=84-86 Ñм + +/shop/sizechart.bml.babydolls.s_size=2/4 + +/shop/sizechart.bml.babydolls.s_waist=63,5-66 Ñм + +/shop/sizechart.bml.babydolls.text=Розміри футболок Ð´Ð»Ñ Ð½Ð°Ð¹ÐºÑ€Ð°Ñивіших дівчат: + +/shop/sizechart.bml.babydolls.waist=Ð¢Ð°Ð»Ñ–Ñ + +/shop/sizechart.bml.babydolls.xl=Ðайбільший + +/shop/sizechart.bml.babydolls.xl_bust=99 Ñм + +/shop/sizechart.bml.babydolls.xl_waist=79-81 Ñм + +/shop/sizechart.bml.back2=ПовернутиÑÑ Ð´Ð¾ Крамниці + +/shop/sizechart.bml.caps.header=Кепки + +/shop/sizechart.bml.caps.text=Ð¦Ñ Ð½ÐµÐ³Ð»Ð¸Ð±Ð¾ÐºÐ° кепка паÑуватиме Ð´Ð»Ñ Ð¾Ð±'ємів голови 17-19 Ñм. + +/shop/sizechart.bml.polos.3xl_length=86 Ñм + +/shop/sizechart.bml.polos.3xl_sleevelength=32 Ñм + +/shop/sizechart.bml.polos.3xl_width=72,5 Ñм + +/shop/sizechart.bml.polos.header=Поло з вишитим малюнком + +/shop/sizechart.bml.polos.length=Довжина + +/shop/sizechart.bml.polos.l_length=79 Ñм + +/shop/sizechart.bml.polos.l_sleevelength=28 Ñм + +/shop/sizechart.bml.polos.l_width=60 Ñм + +/shop/sizechart.bml.polos.m_length=76 Ñм + +/shop/sizechart.bml.polos.m_sleevelength=26,5 Ñм + +/shop/sizechart.bml.polos.m_width=54.5 Ñм + +/shop/sizechart.bml.polos.sleevelength=Довжина рукавів + +/shop/sizechart.bml.polos.subtext=УÑÑ– розміри наведено в Ñантиметрах, Ñкщо не зазначено інше. Довжина відбиває відÑтань від міÑцÑ, де пришитий комірець до нижнього шву. Довжина рукава відÑтань від міÑцÑ, де пришитий комірець до нижнmього шву на рукаві. Ширина відбиває відÑтань між боковими швами та вимірюєтьÑÑ Ð¿Ñ€Ð¸Ð½Ð¹Ð¼Ð½Ñ– на 5 Ñм нижче, від міÑцÑ, де вшиті рукави. + +/shop/sizechart.bml.polos.s_length=71 Ñм + +/shop/sizechart.bml.polos.s_sleevelength=25,5 Ñм + +/shop/sizechart.bml.polos.s_width=49.5 Ñм + +/shop/sizechart.bml.polos.text=Поло виробництва компанії Outer Banks Pique Polo. + +/shop/sizechart.bml.polos.width=Ширина + +/shop/sizechart.bml.polos.xl_length=81 Ñм + +/shop/sizechart.bml.polos.xl_sleevelength=29 Ñм + +/shop/sizechart.bml.polos.xl_width=63,5 Ñм + +/shop/sizechart.bml.polos.xxl_length=84 Ñм + +/shop/sizechart.bml.polos.xxl_sleevelength=30,5 Ñм + +/shop/sizechart.bml.polos.xxl_width=67 Ñм + +/shop/sizechart.bml.sweatshirts.header=Кенгурка + +/shop/sizechart.bml.sweatshirts.text=Пропонуємо вашій увазі кенгурку. Склад 50/50 вовна та фліÑ. Капюшон затÑгуєтьÑÑ Ð¼Ð¾Ñ‚ÑƒÐ·ÐºÐ¾ÑŽ. Рще на пузі Ñ” велика кишенÑ. + +/shop/sizechart.bml.title=Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ€Ñ–Ð² + +/shop/sizechart.bml.tshirts.3xl_length=84 Ñм + +/shop/sizechart.bml.tshirts.3xl_width=71 Ñм + +/shop/sizechart.bml.tshirts.4xl_length=86 Ñм + +/shop/sizechart.bml.tshirts.4xl_width=76 Ñм + +/shop/sizechart.bml.tshirts.header=Футболки з коротким та довгим рукавом + +/shop/sizechart.bml.tshirts.length=Довжина + +/shop/sizechart.bml.tshirts.l_length=76 Ñм + +/shop/sizechart.bml.tshirts.l_width=56 Ñм + +/shop/sizechart.bml.tshirts.m_length=73,5 Ñм + +/shop/sizechart.bml.tshirts.m_width=51 Ñм + +/shop/sizechart.bml.tshirts.s_length=71 Ñм + +/shop/sizechart.bml.tshirts.s_width=46 Ñм + +/shop/sizechart.bml.tshirts.text=Розміри S-XXL фірми Gildan Ultra ÑкаладаютьÑÑ Ð·Ñ– 100% бавовни. Розмір 3XL - фірми Gildan Ultra. Розмір 4XL - фірми Bayside. + +/shop/sizechart.bml.tshirts.width=Ширина + +/shop/sizechart.bml.tshirts.xl_length=79 Ñм + +/shop/sizechart.bml.tshirts.xl_width=61 Ñм + +/shop/sizechart.bml.tshirts.xxl_length=81 Ñм + +/shop/sizechart.bml.tshirts.xxl_width=66 Ñм + +/shop/view.bml.babydolltshirt.desc=ДивітьÑÑ Ñк зроÑтає ÑпиÑок друзів у цій жіночій футболці. + +/shop/view.bml.babydolltshirt.longdesc=Ðаш найпопулÑрніший товар на цей чаÑ, придбай це зараз, бо потім буде пізно. Команда панÑнок в американÑькому одÑзі. + +/shop/view.bml.babydolltshirt.price=Від [[price]] + +/shop/view.bml.babydolltshirt.shortdesc=Футболка
    Ð´Ð»Ñ Ð»Ñлечки + +/shop/view.bml.babydolltshirt.title=Футболка Ð´Ð»Ñ Ð»Ñлечок + +/shop/view.bml.btn.add2order=Додати до Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/shop/view.bml.coffeemug.desc=Пийте більше кави, отримуйте більше коментарів. + +/shop/view.bml.coffeemug.longdesc=Пийте більше кави, отримуйте більше коментарів. Зручна міцна ручка. Кришка, щоб не розплеÑкати кави. МіÑткіÑÑ‚ÑŒ 0,473 літри. + +/shop/view.bml.coffeemug.shortdesc=Філіжанка + +/shop/view.bml.coffeemug.title=Ðеіржавіюча філіжанка + +/shop/view.bml.diskspace.desc=Зберігайте більше фотографій та голоÑових повідомлень, Ñ– ніколи не турбуйтеÑÑ Ð¿Ñ€Ð¾ трафік! + +/shop/view.bml.diskspace.longdesc1=Придбайте додатковий диÑковий проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— кількоÑÑ‚Ñ– зображень у ScrapBook та голоÑових повідомлень Ñ– більше не турбуйтеÑÑ Ð¿Ñ€Ð¾ трафік! Ваш диÑковий проÑÑ‚Ñ–Ñ€ збільшитьÑÑ Ð·Ð°Ð³Ð°Ð»Ð¾Ð¼ до 10 Гб. ПоÑлуга доÑтупна лише влаÑникам платних рахунків. + +/shop/view.bml.diskspace.longdesc2=Якщо ви кориÑтуєтеÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ÑŽ оплатою, то можете додати цю можливіÑÑ‚ÑŒ до Ñвого рахунку тут. + +/shop/view.bml.diskspace.price=Від [[price]] + +/shop/view.bml.diskspace.shortdesc=Додатковий проÑÑ‚Ñ–Ñ€ + +/shop/view.bml.diskspace.title=ДоповненнÑ: Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +/shop/view.bml.error.checkedout=Ваш поточний кошик вже Ñплачений. Бажаєте відкрити нове замовленнÑ? + +/shop/view.bml.error.invaliditem=Помилковий товар + +/shop/view.bml.error.notloggedin=Ви повинні увійти Ñк влаÑник кошику, щоб додати або придбати товари. + +/shop/view.bml.error.notloggedin2pay=Ви повинні увійти або Ñтворити новий рахунок перед тим, Ñк купувати товари в крамниці. + +/shop/view.bml.error.notyourcart=Ви не Ñ” влаÑником цього кошику. Якщо ви бажаєте Ñтворити новий кошик, будь лаÑка, натиÑніть Ñюди. + +/shop/view.bml.giftcertificate.desc=Ðе можете визначитиÑÑ, що подарувати другу? Подаруйте йому це! + +/shop/view.bml.giftcertificate.gifttitle=Подарункові Ñертифікати + +/shop/view.bml.giftcertificate.longdesc=Ðе можете визначитииÑÑ, що подарувати другу? Подаруйте це! БакÑи Френка завжди в нагоді. ДозволÑÑŽÑ‚ÑŒ Ñплачувати ÑервіÑи та товари LiveJournal. + +/shop/view.bml.giftcertificate.price=Від [[price]] + +/shop/view.bml.giftcertificate.title=Подарунковий Ñертифікат + +/shop/view.bml.giftoptions.header=Опції подарунку + +/shop/view.bml.hat.desc=Забудь бейÑбол, підтримай команду LJ! + +/shop/view.bml.hat.longdesc=Забудь про бейÑбол, підтримуй команду LiveJournal! ПаÑуватиме Ð´Ð»Ñ Ð¾Ð±'ємів голови 17,5-18,73 Ñм. + +/shop/view.bml.hat.shortdesc=Кепка + +/shop/view.bml.hat.title=Кепка + +/shop/view.bml.hoodie.desc=Капюшон запобігає вивітрюванню 80% великих ідей. + +/shop/view.bml.hoodie.longdesc=Кенгурки дуже Ñмакують Френкові, тож купуйте Ñ—Ñ…, поки вони не ÑкінчилиÑÑ. Склад: 50% вовни, 50% поліеÑтеру. Ціна включає доÑтавку. + +/shop/view.bml.hoodie.title=Кенгурка + +/shop/view.bml.input.anongift=Ðнонімний подарунок? + +/shop/view.bml.input.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/shop/view.bml.inventorynote.header=Примітка про перелік + +/shop/view.bml.inventorynote.text=Ðа цей Ñ‡Ð°Ñ Ð´ÐµÑкі товари можуть бути вичерпаними. Будь лаÑка, повернітьÑÑ Ð¿Ñ–Ð·Ð½Ñ–ÑˆÐµ, Ñкщо не знайшли необхідні товари. Через деÑкий проміжок чаÑу, неÑплачені Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ анульовані Ñ– ці товари Ñтануть доÑтупними. + +/shop/view.bml.item.forother=Цей подарунок Ð´Ð»Ñ Ð»ÑŽÐ´Ð¸Ð½Ð¸ чи Ñпільноти? + +/shop/view.bml.item.foryou.loggedin=Купуєте цей товар Ð´Ð»Ñ Ñебе? + +/shop/view.bml.item.foryou.loggedout=Якщо ви Ñ” кориÑтувачем LiveJournal Ñ– бажаєте придбати цей товар Ð´Ð»Ñ Ñебе, будь лаÑка, увійдіть в LJ зараз. + +/shop/view.bml.longsleeveshirt.desc=ВерÑÑ–Ñ "Будь у теплі" нашої клаÑики. + +/shop/view.bml.longsleeveshirt.longdesc=КлаÑичний Ñветр Ñтане в нагоді за будь-Ñкої погоди. 100% бавовна. + +/shop/view.bml.longsleeveshirt.price=Від [[price]] + +/shop/view.bml.longsleeveshirt.shortdesc=Светр + +/shop/view.bml.longsleeveshirt.title=Светр + +/shop/view.bml.mosaicposter.desc=Ювілейний плакат-мозаїка із Френком. + +/shop/view.bml.mosaicposter.longdesc=Коли зареєÑтрувавÑÑ 8-мільонний кориÑтувач LiveJournal, ми швидко розробили цю мозаїку з 2400 зображень LiveJournal, щоб відзначити цю подію. Через виÑокий попит з цієї мозаїки був Ñтворений виÑокоÑкіÑний глÑнÑовий плакат 46Ñ…61 Ñм. + +/shop/view.bml.mosaicposter.shortdesc=Плакат-мозаїка Френка + +/shop/view.bml.mosaicposter.title=Плакат-мозаїка Френка + +/shop/view.bml.note.needpaidaccount=Примітка: Ви можете купувати Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ð´Ð»Ñ Ñ–Ñнуючих платних рахунків. Якщо ви бажаєте придбати “[[item]]”, додайте платний рахунок до Ñвого кошика Ñ– Ñпробуйте знову. + +/shop/view.bml.note.notallinstock=Зараз ми доÑтавлÑємо товари тільких в межах Сполучених Штатів. + +/shop/view.bml.note.outofstock=Зараз ми доÑтавлÑємо товари лише по території Сполучених Штатів. + +/shop/view.bml.note.setupautopay=Створіть автоматичну оплату та отримайте рахунок на [[nummonths]] міÑÑців вÑього за [[price]]. + +/shop/view.bml.options.header=Опції + +/shop/view.bml.paidaccount.desc=Додаткові можливоÑÑ‚Ñ– та підтримка долі цього довбаного Ñайту! + +/shop/view.bml.paidaccount.gifttitle=Подаруй платний рахунок + +/shop/view.bml.paidaccount.longdesc=ВлаÑники платних рахунків можуть завантажувати до [[numuserpics]] юзерпик, Ñтворювати Ñ– змінювати Ñтилі журналу та теми наÑтроїв, а також мають доÑтуп до інших прикольних можливоÑтей, включно зі ScrapBook (поÑлуга LiveJournal з Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ð¹). Платні кориÑтувачі можуть отримати юзерпики лоÑльноÑÑ‚Ñ–, а також придбати доповненнÑ, наприклад збільшити диÑковий проÑÑ‚Ñ–Ñ€ чи завантажити до 100 юзерпик. Завітайте на Ñторінку Про платні рахунки, щоб ознайомитиÑÑ Ð· уÑіма можливоÑÑ‚Ñми. + +/shop/view.bml.paidaccount.price=Від [[price]] + +/shop/view.bml.paidaccount.shortdesc=Платний рахунок + +/shop/view.bml.paidaccount.title=Отримай платний рахунок (ручні платежі) + +/shop/view.bml.poloshirt.desc=ХизуйтеÑÑ Ñвоєю гордіÑÑ‚ÑŽ LiveJournal на роботі! + +/shop/view.bml.poloshirt.longdesc=РозÑунь межі "щоденного Ð±Ñ–Ð·Ð½ÐµÑ Ñтилю" за допомогою цього поло, виробництва Outer Banks Pique. Воно точно буде головним у твоєму гардеробі! + +/shop/view.bml.poloshirt.price=Від [[price]] + +/shop/view.bml.poloshirt.shortdesc=Сорочка Поло + +/shop/view.bml.poloshirt.title=Сорочка Поло + +/shop/view.bml.promo.autopay.header=Створіть автоматичну оплату! + +/shop/view.bml.promo.autopay.setup=Рви знаєте, що можете Ñтворити автоматичну оплату Ð´Ð»Ñ Ñвого платного рахунку? + +/shop/view.bml.promo.autopay.setup.1=Одноразово введіть Ñвої платіжні дані + +/shop/view.bml.promo.autopay.setup.2=Забудьте про необхідніÑÑ‚ÑŒ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/shop/view.bml.promo.autopay.setup.3=Оберіть, Ñк чаÑто треба платити + +/shop/view.bml.promo.autopay.setup.4=Вмикайте та вимикайте автоматичну оплату в будь-Ñкий Ñ‡Ð°Ñ + +/shop/view.bml.promo.autopay.signup=ПриєднуйтеÑÑ Ð´Ð¾ нашої найкращої пропозиції, вартіÑÑ‚ÑŒ за рік вÑього [[price]]. + +/shop/view.bml.promo.ljpresent.bdays=ДізнайтеÑÑ Ð¿Ñ€Ð¾ дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñвоїх друзів + +/shop/view.bml.promo.ljpresent.header=LiveJournal робить великий подарунок! + +/shop/view.bml.promo.ljpresent.paidaccount=Ваші друзі бажають платний рахунок? + +/shop/view.bml.promo.merchandise.header=Вам дуже личитимуть наші: + +/shop/view.bml.related.header=Вам також може ÑподобатиÑÑ … + +/shop/view.bml.rename.desc=Перейменуйте Ñвій рахунок LiveJournal. + +/shop/view.bml.rename.longdesc=Перейменуйте Ñвій рахунок LiveJournal за невеличку плату. Читайте про поÑлугу Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ð´Ð»Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ð¾Ñ— інформації. + +/shop/view.bml.rename.title=Код Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +/shop/view.bml.sizeinfo.header=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ розміри + +/shop/view.bml.sizeinfo.text=ДивітьÑÑ Ð½Ð°ÑˆÑƒ таблицю розмірів Ð´Ð»Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації. + +/shop/view.bml.skullcap.desc=Зробіть Ñвоїм пріоритетом LiveJournal, а не Ñвоє волоÑÑÑ. + +/shop/view.bml.skullcap.longdesc=Зробіть Ñвоїм пріоритетом LiveJournal, а не Ñвоє волоÑÑÑ. 100% акрилове в'ÑÐ·Ð°Ð½Ð½Ñ Ð· вишитим логотипом LiveJournal. + +/shop/view.bml.skullcap.shortdesc=Шапка + +/shop/view.bml.skullcap.title=Шапка + +/shop/view.bml.title=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ + +/shop/view.bml.tshirt.desc=Тільки клаÑика. Футболка LiveJournal. + +/shop/view.bml.tshirt.longdesc=Футболки завжди у моді. 100% бавовна. + +/shop/view.bml.tshirt.price=Від [[price]] + +/shop/view.bml.tshirt.shortdesc=Футболка + +/shop/view.bml.tshirt.title=Футболка + +/shop/view.bml.userpics.desc=Додайте талант до Ñвоїх запиÑів та коментарів з додатковими юзерпиками! + +/shop/view.bml.userpics.giftdesc=Подаруйте це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑŒ-кому з володарів платних рахунків, Ñ– вони зможуть завантажити до [[numuserpics]] юзерпик! + +/shop/view.bml.userpics.gifttitle=Подарункове доповненнÑ: Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ð´Ð¾ [[numuserpics]] юзерпик + +/shop/view.bml.userpics.longdesc1=Це Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” завантажити до [[numuserpics]] юзерпик! ДоÑтупний тільки Ð´Ð»Ñ Ð²Ð¾Ð»Ð¾Ð´Ð°Ñ€Ñ–Ð² платних рахунків. + +/shop/view.bml.userpics.longdesc2=Якщо ви кориÑтуєтеÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ñƒ оплату, то можете додати цю можливіÑÑ‚ÑŒ до Ñвого рахунку тут. + +/shop/view.bml.userpics.price=Від [[price]] + +/shop/view.bml.userpics.shortdesc=Додаткові юзерпики + +/shop/view.bml.userpics.title=ДоповненнÑ: Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ð´Ð¾ [[numuserpics]] юзерпик + +/shop/view.bml.vgift.desc=ДоÑтавте подарунок туди, куди не зможе жодний квіткар - до профілю вашого друга + +/shop/view.bml.vgift.giftnote.header=Ðотатка до подарунку: + +/shop/view.bml.vgift.giftnote.note=(ВідображатиметьÑÑ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¾ у профілі одержувача) + +/shop/view.bml.vgift.giftnote.text=Введіть оÑобливу нотатку тут. + +/shop/view.bml.vgift.gifttitle=Віртуальні подарунки + +/shop/view.bml.vgift.longdesc=

    ДоÑтавте подарунок туди, куди не зможе жодний квіткар - до профілю вашого друга

    Віртуальні подарунки - це значки, Ñкі можна придбати Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-кого, у кого Ñ” рахунок [[sitename]]. Значок подарунку відображатиметьÑÑ Ñƒ профілі одержувача впродовж двох (2) тижнів.

    + +/shop/view.bml.vgift.note.header=Ðотатка до подарунку: + +/shop/view.bml.vgift.price=Починаючи з [[price]] + +/shop/view.bml.vgift.title=Віртуальні подарунки + +/shop/view.bml.xmonths=[[nummonths]] [[?nummonths|міÑÑць|міÑÑці|міÑÑців]] + +/site/about.bml.faq.header=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/site/about.bml.faq.text=ДеÑкі поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ (та відповіді!), що ÑтоÑуютьÑÑ LiveJournal, можна знайти на нашій Ñторінці FAQ. + +/site/about.bml.features.customization=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/site/about.bml.features.customization.embed=Додайте Ñвій журнал до влаÑної веб-Ñторінки. + +/site/about.bml.features.customization.modify=ВиглÑд вашого журналу легко змінити за допомогою шаблонної ÑиÑтеми Ñтилів або виÑококлаÑного майÑтра налаштувань. + +/site/about.bml.features.customization.s2=Ð”Ð»Ñ ÐºÑ€Ð°Ñ‰Ð¾Ð³Ð¾ контролю Ñтворіть Ñвій влаÑний Ñтиль за допомогою мови Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ S2. + +/site/about.bml.features.friends=Друзі + +/site/about.bml.features.friends.groups=Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— безпеки й відÑÑ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¹Ð²Ð¾Ñ— інформації ви можете поділити друзів на групи. + +/site/about.bml.features.friends.syn=Ð¡Ð¸Ð½Ð´Ð¸ÐºÐ°Ñ†Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” вам читати новини з інших Ñайтів (RSS), Ñк звичайні допиÑи інших кориÑтувачів LiveJournal. + +/site/about.bml.features.friends.view=Вбудований збирач (званий "переглÑд друзів") виводить уÑÑ– запиÑи ваших друзів на одній Ñторінці. + +/site/about.bml.features.header=МожливоÑÑ‚Ñ– + +/site/about.bml.features.interoperability=СуміÑніÑÑ‚ÑŒ + +/site/about.bml.features.interoperability.languages=Ðаш Ñайт доÑтупний багатьма мовами. + +/site/about.bml.features.interoperability.rss=RSS-потік кожного журналу дає можливіÑÑ‚ÑŒ іншим Ñайтам/програмам збирати ваш зміÑÑ‚. + +/site/about.bml.features.interoperability.unicode=Повна підтримка Юнікоду дозволÑÑ” пиÑати будь-Ñкою мовою. + +/site/about.bml.features.journal=Ваш журнал + +/site/about.bml.features.journal.comments=Коментарі до кожного запиÑу підтримують Ð¿ÐµÑ€ÐµÐ³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° наÑкрізні відповіді (коментарі у відповідь на інші коментарі). + +/site/about.bml.features.journal.entries=ЗапиÑи можуть включати: + +/site/about.bml.features.journal.entries.basics=Стандартне: заголовок, текÑÑ‚ Ñ– дату + +/site/about.bml.features.journal.entries.currents=ТекÑÑ‚ або іконку поточного наÑтрію, а також музику, що зараз грає. + +/site/about.bml.features.journal.entries.pics=Маленьке зображеннÑ, що предÑтавлÑÑ” ваÑ. + +/site/about.bml.features.journal.entries.polls=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð· автоматичним підрахунком відповідей. + +/site/about.bml.features.journal.photos=ПовніÑÑ‚ÑŽ інтегрований альбом зображень з можливіÑÑ‚ÑŽ елементарного редагуваннÑ. + +/site/about.bml.features.journal.profile=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ кориÑтувача включає: + +/site/about.bml.features.journal.profile.bio=Розділ про Ñебе. + +/site/about.bml.features.journal.profile.communities=Спільноти, Ñкі ви читаєте та в Ñких берете учаÑÑ‚ÑŒ. + +/site/about.bml.features.journal.profile.friends=З ким дружите ви Ñ– хто дружить з вами. + +/site/about.bml.features.journal.profile.interests=Перелік зацікавлень — іще один шлÑÑ… Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ інших кориÑтувачів. + +/site/about.bml.features.journal.profile.textmessage=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° наш шлюз текÑтових повідомлень, що не відображає номер вашого мобільного. + +/site/about.bml.features.journal.security=Безпека кожного запиÑу дозволÑÑ” зробити його доÑтупним лише Ð´Ð»Ñ Ð²Ð°Ñ Ð°Ð±Ð¾ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ ваших друзів. + +/site/about.bml.features.networking=Соціальна мережа + +/site/about.bml.features.networking.communities=Спільноти об'єднують людей, що мають Ñпільні інтереÑи. + +/site/about.bml.features.networking.directory=СкориÑтайтеÑÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼ Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ інших людей за країною або за іншими критеріÑми. + +/site/about.bml.features.networking.users=Ви можете ÑпілкуватиÑÑ Ð· мільйонами кориÑтувачів. + +/site/about.bml.features.open=ВідкритіÑÑ‚ÑŒ + +/site/about.bml.features.open.code=Відкритий код дозволÑÑ” будь-кому Ñтворити влаÑний Ñайт на зразок LiveJournal. + +/site/about.bml.features.open.dev=Відкритий Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ дозволÑÑ” будь-кому зробити Ñвій внеÑок чи проÑто ÑпоÑтерігати й навчатиÑÑ. + +/site/about.bml.features.open.noads=Жодної реклами й Ñ‚. п. (ДивітьÑÑ ÐºÐµÑ€Ñ–Ð²Ð½Ñ– принципи.) + +/site/about.bml.features.open.support=Підтримка здійÑнюєтьÑÑ Ð²Ð¾Ð»Ð¾Ð½Ñ‚ÐµÑ€Ð°Ð¼Ð¸, Ñкі піклуютьÑÑ Ð¿Ñ€Ð¾ Ñайт. + +/site/about.bml.features.privacy=КонфіденційніÑÑ‚ÑŒ + +/site/about.bml.features.privacy.ban=Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½ÑˆÐ¸Ñ… кориÑтувачів у вашому журналі чи Ñпільноті. + +/site/about.bml.features.privacy.control=Ви контролюєте: + +/site/about.bml.features.privacy.control.comments=Хто може залишати коментарі та чиї коментарі будуть приховані до ваших подальших дій. + +/site/about.bml.features.privacy.control.contact=Хто може переглÑдати вашу контактну інформацію. + +/site/about.bml.features.privacy.control.entries=Хто може переглÑдати кожен окремий запиÑ. + +/site/about.bml.features.privacy.control.polls=Хто може брати учаÑÑ‚ÑŒ в окремих опитуваннÑÑ…. + +/site/about.bml.features.privacy.control.textmessage=Хто можете надіÑлати вам текÑтове повідомленнÑ. + +/site/about.bml.features.software=Програми + +/site/about.bml.features.software.clients=КлієнтÑькі програми (Ð´Ð»Ñ Windows, MacOS, Linux та ін.) дозволÑÑŽÑ‚ÑŒ оновлювати журнал, не відкриваючи браузер. + +/site/about.bml.features.text=Це оглÑд можливоÑтей, що роблÑÑ‚ÑŒ LiveJournal цікавішим. Також до вашої уваги порівнÑÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾Ñтей різних типів рахунків. + +/site/about.bml.title=Про LiveJournal + +/site/about.bml.tryit=ПервіÑно цей Ñайт був Ñтворений Ð´Ð»Ñ Ð½ÐµÐ²ÐµÐ»Ð¸ÐºÐ¾Ñ— групи друзів. Той факт, що він здобув популÑрніÑÑ‚ÑŒ без жодної реклами, заÑвідчує, наÑкільки це клаÑно. Спробуйте... Ñкщо у Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ½Ðµ ÑкаÑÑŒ проблема чи з'ÑвитьÑÑ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ ÑтоÑовно Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ñайту, дайте нам знати! + +/site/accounts.bml.addonphotos=ÐšÑƒÐ¿Ñ–Ð²Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ диÑкового проÑтору (Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ð´Ð¾ [[size]] Гб) + +/site/accounts.bml.addonuserpics=ÐšÑƒÐ¿Ñ–Ð²Ð»Ñ [[num]] [[?num|додаткової юзерпики|додаткових юзерпик|додаткових юзерпик]] + +/site/accounts.bml.adsupported=СпонÑоруєтьÑÑ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¾ÑŽ + +/site/accounts.bml.advancedfeatures.header=Розширені можливоÑÑ‚Ñ– + +/site/accounts.bml.archive=Ðрхів запиÑів + +/site/accounts.bml.backdating=Довільні дні + +/site/accounts.bml.banning=Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñми у Ñвоєму журналі + +/site/accounts.bml.bio=Вкажіть у Ñвоєму профілі Ñ–Ñторію про Ñебе, друзів, зацікавленнÑ, Ñпільноти, тощо + +/site/accounts.bml.btn.createacct=Створити рахунок + +/site/accounts.bml.btn.upgrade=Зробити рахунок платним + +/site/accounts.bml.btn.upgrade.free=Змінити на базовий рахунок + +/site/accounts.bml.btn.upgrade.plus=Перейти на Розширений рахунок + +/site/accounts.bml.comments=ÐšÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів чи відповідь на інші коментарі (гілки коментарів) + +/site/accounts.bml.communities=ÐŸÑ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ Ñпільнот Ð´Ð»Ñ ÑÐ¿Ñ–Ð»ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð· кориÑтувачами, Ñкі підтримують ваші Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/site/accounts.bml.connect.header=Зв'Ñзок між кориÑтувачами та Ñпільнотами LiveJournal + +/site/accounts.bml.cost=ВартіÑÑ‚ÑŒ + +/site/accounts.bml.create=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñвого влаÑного журналу + +/site/accounts.bml.createjournal.header=ПроÑте ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñвого влаÑного журналу в мережі + +/site/accounts.bml.createstyles=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° зміна влаÑних наборів Ñтилів + +/site/accounts.bml.createsynfeeds=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… Ñиндикативних рахунків + +/site/accounts.bml.current_metadata=ÐаÑтрій/музика + +/site/accounts.bml.customize.header=Великі можливоÑÑ‚Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду журналу + +/site/accounts.bml.custommood=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних наборів зображень наÑтрою + +/site/accounts.bml.custom_security=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñобливих груп друзів та Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів до конкретної групи + +/site/accounts.bml.directory=Розширені можливоÑÑ‚Ñ– пошуку кориÑтувачів за міÑтом, облаÑÑ‚ÑŽ, країною, віком, друзÑми + +/site/accounts.bml.disk_quota=Відобразити та впорÑдковати Ñвої Ñвітлини за допомогою ScrapBook + +/site/accounts.bml.domain_forward=Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñвого доменого імені з перенаправленнÑм до влаÑного журналу + +/site/accounts.bml.email=КориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ email-адреÑою [[sitename]] + +/site/accounts.bml.embed=Вбудова журналу до влаÑного Ñайту + +/site/accounts.bml.export=ÐÑ€Ñ…Ñ–Ð²Ð°Ñ†Ñ–Ñ Ñ‚Ð° Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñвого журналу за допомогою нашого заÑобу Ð´Ð»Ñ ÐµÐºÑпорту + +/site/accounts.bml.feature.limited=Обмежено + +/site/accounts.bml.feature.max=МакÑ. + +/site/accounts.bml.feature.most=Ðайбільше + +/site/accounts.bml.free=Безкоштовний + +/site/accounts.bml.friendfriends=ПереглÑд запиÑів друзів Ñвоїх друзів + +/site/accounts.bml.friends=ПереглÑд вÑÑ–Ñ… оÑтанніх запиÑів Ñвоїх друзів у влаÑній Ñтрічці друзів + +/site/accounts.bml.friendsyn=ПереглÑд зовнішніх інформаційних потоків формату XML/RSS/Atom у Ñвоїй Ñтрічці друзів + +/site/accounts.bml.interests=Перелік зацікавлень + +/site/accounts.bml.intro_1=У цій таблиці порівнюютьÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ÑÑ‚Ñ– наших рахунків. ДізнатиÑÑ Ð¿Ñ€Ð¾ ціни ви можете на Ñторінці Про платні рахунки. + +/site/accounts.bml.ljtalkchat2=ВикориÑтовуйте LJ Talk Ð´Ð»Ñ Ð¾Ð±Ð¼Ñ–Ð½Ñƒ миттєвими повідомленнÑми з LJ-друзÑми та кориÑтувачами Jabber + +/site/accounts.bml.ljtalkdownload2=Скачати Gizmo Project Ð´Ð»Ñ ÑпілкуваннÑ, дзвінків, безкоштовних конференцій та голоÑових переговорів у LJ Talk + +/site/accounts.bml.loyalpics=МожливіÑÑ‚ÑŒ отримати та викориÑтовувати більше юзерпик завдÑки програмі "Loyalty Userpics" + +/site/accounts.bml.media_quota=Квота ноÑÑ–Ñ + +/site/accounts.bml.memories=Перелік вибраних запиÑів + +/site/accounts.bml.mobileposting.header=Відправка запиÑів з мобільних приÑтроїв + +/site/accounts.bml.moderated=Модеровані Ñпільноти + +/site/accounts.bml.mood=Вибір з-поміж багатьох тем Ñ– зображень наÑтрою Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñвого наÑтрою у кожному запиÑÑ– + +/site/accounts.bml.music=Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¼ÑƒÐ·Ð¸ÐºÐ¸, Ñку ви Ñлухаєте, у кожному запиÑÑ– + +/site/accounts.bml.noads=ВідÑутніÑÑ‚ÑŒ банерної та Ñпливаючої реклами + +/site/accounts.bml.paid.cost=Від 2 доларів на міÑÑць. + +/site/accounts.bml.permonth=[[num]][[?num|/міÑ.|/міÑ.]] + +/site/accounts.bml.photosecurity=Ð’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¸Ñ…, хто зможе бачити оÑобиÑÑ‚Ñ– фотографії та галереї у вашому Ðльбомі + +/site/accounts.bml.photostorage=Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° упорÑÐ´ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñвоїх фотографій за допомогою Ðльбому та [[size]] Гб диÑкового проÑтору + +/site/accounts.bml.photostorage.paid.note=Можливо придбати додатковий проÑÑ‚Ñ–Ñ€. + +/site/accounts.bml.photostorage.perm.note=Можливо придбати додатковий проÑÑ‚Ñ–Ñ€. + +/site/accounts.bml.planned=ПлануєтьÑÑ + +/site/accounts.bml.polling=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних опитувань та доÑліджень + +/site/accounts.bml.popfeatures.header=Ðайбільш популÑрні можливоÑÑ‚Ñ– + +/site/accounts.bml.popfriends=Перелік кориÑтувачів, популÑрних Ñеред ваших друзів + +/site/accounts.bml.post_client=Ð¡ÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñької програми Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів без Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° + +/site/accounts.bml.post_email=Відправка запиÑів до Ñвого журналу через телефон або мобільний приÑтрій + +/site/accounts.bml.post_email1=ВідправлÑйте фотографії та текÑтові запиÑи до вашого журналу за допомогою мобільних приÑтроїв. + +/site/accounts.bml.post_emailpgp=КориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð»Ð°Ñним PGP/GPG ключем + +/site/accounts.bml.post_phone=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень з мобільного телефону (у форматі mp3/wav/ogg) + +/site/accounts.bml.post_web=Веб-Ñайт + +/site/accounts.bml.privacy.header=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð»Ð°Ñних рівнів конфіденційноÑÑ‚Ñ– та безпеки + +/site/accounts.bml.protectedposts=Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¸Ñ…, хто має доÑтуп до ваших оÑобиÑтих запиÑів (публічні, тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð², оÑобливих, приватних) + +/site/accounts.bml.random=Випадкові журнали + +/site/accounts.bml.rss=RSS-потік журналу + +/site/accounts.bml.screening=ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð² + +/site/accounts.bml.search=Пошук інших кориÑтувачів за іменем кориÑтувача, email-адреÑою, зацікавленнÑми, AIM, Yahoo! та MSN + +/site/accounts.bml.sendtext=Відправка текÑтових повідомлень іншим кориÑтувачам без Ð·Ð½Ð°Ð½Ð½Ñ Ñ—Ñ… номеру телефону + +/site/accounts.bml.spellchecking=Інтегрована перевірка правопиÑу + +/site/accounts.bml.startcommunity=Ð—Ð°Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти Ð´Ð»Ñ Ð²Ð¸Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñвоїх інтереÑів + +/site/accounts.bml.stylechoices=Оберіть з Ñ€Ð¾Ð·Ð¼Ð°Ñ—Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¸Ð²Ð°Ð±Ð»Ð¸Ð²Ð¸Ñ… Ñтилів + +/site/accounts.bml.styles=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду влаÑного журналу + +/site/accounts.bml.subject=Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÐ¼Ð¸ кожного запиÑу + +/site/accounts.bml.subjects=Теми запиÑів + +/site/accounts.bml.table.ea.header=Ранній кориÑтувач + +/site/accounts.bml.table.free.header=Базовий + +/site/accounts.bml.table.paid.header=Платні + +/site/accounts.bml.table.perm.header=ПоÑтійні + +/site/accounts.bml.tags=Ð’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÐ³Ñ–Ð² до кожного запиÑу + +/site/accounts.bml.textmessage=ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÑтових повідомлень без Ñ€Ð¾Ð·Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ñвого номеру телефону + +/site/accounts.bml.title=МожливоÑÑ‚Ñ– різних типів рахунків + +/site/accounts.bml.userlinks=СпиÑок вибраних Ð°Ð´Ñ€ÐµÑ + +/site/accounts.bml.userpics=Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´ÐµÐºÑ–Ð»ÑŒÐºÐ¾Ñ… юзерпик, що відображаютьÑÑ Ð² кожному влаÑному запиÑÑ– чи коментарі + +/site/accounts.bml.userpics.paid.note=Можливо придбати додаткові юзерпики. + +/site/accounts.bml.weblogs.name=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ weblogs.com про Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу + +/site/banners.bml.banner.another=Інший банер + +/site/banners.bml.banner.businessethics=Коректний банер + +/site/banners.bml.banner.captivating=Чарівний банер + +/site/banners.bml.banner.elegant=Витончений банер + +/site/banners.bml.banner.goat=Банер цапа + +/site/banners.bml.banner.impactingsociety=Стимулючий банер + +/site/banners.bml.banner.informational=Інформаційний банер + +/site/banners.bml.banner.metal=Металевий банер + +/site/banners.bml.banner.narcissicm=Банер ÑÐ°Ð¼Ð¾Ð·Ð°ÐºÐ¾Ñ…Ð°Ð½Ð½Ñ + +/site/banners.bml.banner.pastel=ПаÑтельний банер + +/site/banners.bml.banner.sexy=СекÑуальний банер + +/site/banners.bml.helplj.header=Допоможіть [[sitename]]! + +/site/banners.bml.helplj.text=Допоможіть поширити інформацію про те, наÑкільки клаÑний [[sitename]], розміÑтивши один з цих банерів [[sitename]] на Ñвоєму веб-Ñайті. Код HTML наведено нижче; вÑе що вам потрібно - це Ñкопіювати та вÑтавити один з них до Ñвого HTML. + +/site/banners.bml.title=Банери [[sitename]] + +/site/contract.bml.promise=Ми тримаємоÑÑ Ð´Ð¾ ÐºÑ–Ð½Ñ†Ñ Ñƒ виÑлові, що ми будемо: + +/site/contract.bml.promise.account=Поважати ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ рахунку + +/site/contract.bml.promise.account.about=ПоÑтійні рахунки шануватимутьÑÑ, доки Ñ–Ñнує Ñайт. Платні рахунки залишатимутьÑÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ð¼Ð¸ рахунками, доки їхні терміни не завершутьÑÑ, Ñкщо вони не відновлені наперед. Рахунки Ранніх кориÑтувачів матимуть доÑтуп до можливоÑтей платних рахунків, Ñкі були безкоштовно доÑтупні у ранній Ñ–Ñторії Ñайту. (Стан рахунку Ñ” дійÑним за винÑтком Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ на підÑтаві Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ð£Ð¼Ð¾Ð² Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг.) + +/site/contract.bml.promise.ads=Уникати реклами + +/site/contract.bml.promise.ads.about=ОÑкільки це Ñ” однією з найбільших Ñкарг наших улюбленців, ми уникатимо Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ на Ñайті. Хоча наші Умови викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑŽÑ‚ÑŒ змінити нашу політику в майбутньому, ми виÑвили протÑгом оÑтанніх кількох років, що наша бізнеÑ-модель "платних рахунків" чудово Ñпрацювала, зробивши банерну рекламу непотрібною. + +/site/contract.bml.promise.community=Працювати разом із Ñпільнотою, заради Ñпільноти + +/site/contract.bml.promise.community.about=Ми обіцÑємо тримати Ð²Ð°Ñ Ð¿Ð¾Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð¾Ð²Ð°Ð½Ð¸Ð¼Ð¸ про зімни, наÑкільки нам дозволÑÑŽÑ‚ÑŒ наші здібноÑÑ‚Ñ–, але без наÑтирливоÑÑ‚Ñ–. Ми обіцÑємо керувати нашім бізнеÑом на підÑтаві зворотнього зв'Ñзку зі Ñпільнтою LiveJournal, Ñ– пам'Ñтаючи про кращі інтереÑи Ñпільоти LiveJournal. + +/site/contract.bml.promise.opensource=Підтримувати рух вільного програмного Ð·Ð°Ð±ÐµÐ¿ÐµÑ‡ÐµÐ½Ð½Ñ + +/site/contract.bml.promise.opensource.about=ВеÑÑŒ код, що викориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ уÑтановки LiveJournal, Ñка Ñ” повною та добре налаштовуєтьÑÑ, Ñ” публічно доÑтупним. Ми обіцÑємо тримати це джерело безкоштовним Ñ– відкритим, так щоб ми могли чимоÑÑŒ віддÑчити Ñпільноті Вільного програмного забезпеченнÑ. + +/site/contract.bml.promise.spam=Ðіколи не надÑилати вам непрошену елктронну пошту + +/site/contract.bml.promise.spam.about=Ми переконано віримо, що Ñпаму немає міÑÑ†Ñ Ð² Інтернеті, Ñ– ми обіцÑємо ніколи не поÑилати будь-Ñкого лиÑта без вашої непрÑмої або Ñвної згоди. Ми обіцÑємо ніколи не продавати ÑпиÑки e-mail Ð°Ð´Ñ€ÐµÑ Ð°Ð±Ð¾ оÑобиÑтих даних кориÑтувачів, Ñ– ми обіцÑємо ніколи не надÑилати Ñпам на кориÑÑ‚ÑŒ зацікавленої третьої оÑоби. + +/site/contract.bml.promise.uptime=Підтримувати надійний Ñ‡Ð°Ñ Ð¿Ñ€Ð°Ñ†ÐµÐ·Ð´Ð°Ñ‚Ð½Ð¾ÑÑ‚Ñ– в межах технічних можливоÑтей + +/site/contract.bml.promise.uptime.about=Ми намагаємоÑÑŒ робити так, щоб вÑе працювало добре, оÑобливо Ñкщо взÑти до уваги, що ми Ñамі викориÑтовуємо ÑиÑтему так Ñамо, Ñк будь-хто інший. Ðа жаль, завіÑÐ°Ð½Ð½Ñ Ñерверів траплÑÑŽÑ‚ÑŒÑÑ, але ми працюємо заздалегідь так добре, Ñк можемо, щоб уникнути цього. + +/site/contract.bml.promisetoyou=Ми у LiveJournal намагаємоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ так, щоб наш ÑÐµÑ€Ð²Ñ–Ñ Ð±ÑƒÐ² приємним Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ кориÑтувача наÑкільки це можливо, Ñ– тому ми Ñтворили ÑпиÑок обіцÑнок, Ñкі ми триматимемо. + +/site/contract.bml.promisetoyou.header=Ðаша обіцÑнка вам + +/site/contract.bml.title=СуÑпільний контракт + +/site/contributors.bml.ack.done.header=Зроблено + +/site/contributors.bml.ack.done.text=Ви визнали цей внеÑок. + +/site/contributors.bml.ack.title=Ð’Ð¸Ð·Ð½Ð°Ð½Ð½Ñ + +/site/contributors.bml.add.input.category=КатегоріÑ: + +/site/contributors.bml.add.input.description=ОпиÑ: + +/site/contributors.bml.add.input.url=Ðеобов'Ñзкова адреÑа: + +/site/contributors.bml.add.input.user=Кого додати? + +/site/contributors.bml.add.title=Додати внеÑок(-ки) + +/site/contributors.bml.addyourself.header=Додати Ñебе! + +/site/contributors.bml.addyourself.text=Якщо ви допомогали Ñ– не бачите Ñебе у цьому ÑпиÑку, додайте Ñебе. + +/site/contributors.bml.add_do.success=Додано. Ви можете дивитиÑÑ Ñ†Ðµ тут. + +/site/contributors.bml.add_do.title=Додати внеÑок(-ки) + +/site/contributors.bml.back2=Ðазад + +/site/contributors.bml.back2contributions=ПовернутиÑÑ Ð´Ð¾ переліку внеÑків. + +/site/contributors.bml.btn.ack=Визнати цей внеÑок + +/site/contributors.bml.btn.add=Додати + +/site/contributors.bml.btn.delete=Видалити цей внеÑок + +/site/contributors.bml.btn.view=ДивитиÑÑ + +/site/contributors.bml.byuser.acked.header=Визнані внеÑки + +/site/contributors.bml.byuser.acked.text=Ці внеÑки були визнані іншими учаÑниками Ñпільноти: + +/site/contributors.bml.byuser.nocontributions=[[user]] не вказав жодних внеÑків. + +/site/contributors.bml.byuser.title=ВнеÑки [[user]] + +/site/contributors.bml.byuser.unacked.header=Ðевизнані внеÑки + +/site/contributors.bml.byuser.unacked.text=Ці внеÑки були вказані, але ще не визнані іншими: + +/site/contributors.bml.cat.biz=Ділові проблеми та керівництво + +/site/contributors.bml.cat.code=Код/ÐŸÑ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ + +/site/contributors.bml.cat.creative=ТворчіÑÑ‚ÑŒ (Стилі/Ðрт/Презентації) + +/site/contributors.bml.cat.doc=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ + +/site/contributors.bml.cat.other=Інше + +/site/contributors.bml.category.nocontributions=Жодних внеÑків у цій категорії. + +/site/contributors.bml.delete.success.header=УÑпішно + +/site/contributors.bml.delete.success.text=ВнеÑок видалено. + +/site/contributors.bml.delete.success.title=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð½ÐµÑку - УÑпішно + +/site/contributors.bml.detail.acks.header=Ð’Ð¸Ð·Ð½Ð°Ð½Ð½Ñ + +/site/contributors.bml.detail.acks.none=(відÑутні) + +/site/contributors.bml.detail.acks.text=Цей внеÑок визнали наÑтупні помічники: + +/site/contributors.bml.detail.acks.whentoack<< +ВнеÑок не відображаєтьÑÑ Ð½Ð° головній Ñторінці, оÑкільки його не визнали інші помічники. Щоб визнати цей внеÑок, натиÑніть кнопку нижче. +Визнавайте лише у випадках, коли точно знаєте, що це було зроблено Ñ– ви маєте до цього відношеннÑ. Ðаприклад, Ñкщо ви керівник групи Ñ– дали комуÑÑŒ завданнÑ, ви повинні визнати це. Інша причина Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ð½Ð½Ñ Ð²Ð½ÐµÑку - загальна відоміÑÑ‚ÑŒ внеÑку Ñ– ваше Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ð¹Ð¾Ð³Ð¾ підтримати. +Тільки не визнавайте внеÑки, Ñких ви не знаєте Ñ– в Ñких не брали учаÑÑ‚ÑŒ. +. + +/site/contributors.bml.detail.label.category=КатегоріÑ: + +/site/contributors.bml.detail.label.category.viewall=(дивитиÑÑ Ð²ÑÑ–) + +/site/contributors.bml.detail.label.date=Дата додаваннÑ: + +/site/contributors.bml.detail.label.description=ОпиÑ: + +/site/contributors.bml.detail.label.numacks=Визнали: + +/site/contributors.bml.detail.label.url=ÐдреÑа: + +/site/contributors.bml.detail.label.user=КориÑтувач: + +/site/contributors.bml.detail.title=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ внеÑок + +/site/contributors.bml.error.ack.cantack=Ви не маєте Ñхвалених внеÑків, тож не можете визнавати внеÑки інших. + +/site/contributors.bml.error.ack.cantackself=Ви не можете визнавати влаÑні внеÑки. + +/site/contributors.bml.error.ack.notloggedin.text=Ви повинні увійти перед визнаннÑм внеÑків. + +/site/contributors.bml.error.add.notloggedin.text=Ð”Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ð½ÐµÑку до цього ÑпиÑку ви повинні увійти. + +/site/contributors.bml.error.add_do.cantaddsomeoneelse=Ви повинні бути визнаним помічником до того, Ñк додавати когоÑÑŒ іншого. + +/site/contributors.bml.error.add_do.cantfinduser=КориÑтувача [[user]] не знайдено. + +/site/contributors.bml.error.add_do.notadded=Помилка... не додано. + +/site/contributors.bml.error.add_do.notloggedin.text=Ви увійшли раніше, але не зараз. ФантаÑтика. Увійдіть знову. + +/site/contributors.bml.error.cantfindcontrib=ВнеÑок не знайдено. + +/site/contributors.bml.error.delete.noid=Ðеобхідно вказати номер внеÑку. + +/site/contributors.bml.error.delete.notauthorized=Ви не маєте прав Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ внеÑку. + +/site/contributors.bml.error.delete.notloggedin.text=Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð½ÐµÑу ви повинні Ñпочатку увійти. + +/site/contributors.bml.error.delete.title=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð½ÐµÑку - Помилка + +/site/contributors.bml.error.invalidcategory=Ðевірна категоріÑ. + +/site/contributors.bml.error.invalidusername=Ðевірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/site/contributors.bml.error.notloggedin.header=Спочатку увійдіть + +/site/contributors.bml.error.requirespost=Вимагає запиÑу. + +/site/contributors.bml.recent.acked.header=Визнані внеÑки + +/site/contributors.bml.recent.acked.text=Ці внеÑки оÑтанні, що були визнані іншими учаÑниками Ñпільноти: + +/site/contributors.bml.recent.nocontributions=Жодних внеÑків не додано за [[num]] [[?num|оÑтанній день|оÑтанні дні|оÑтанніх днів]]. + +/site/contributors.bml.recent.title=ОÑтанні внеÑки + +/site/contributors.bml.recent.unacked.header=Ðевизнані внеÑки + +/site/contributors.bml.recent.unacked.text=Ці внеÑки були додані, але ще не визнані іншими: + +/site/contributors.bml.selectview.byuser=КориÑтувачі: + +/site/contributors.bml.selectview.byuser.input.username=Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/site/contributors.bml.selectview.cat=Категорії: + +/site/contributors.bml.selectview.header=Оберіть режим переглÑду: + +/site/contributors.bml.selectview.recent=ОÑтанні [[num]] [[?num|день|дні|днів]]: + +/site/contributors.bml.selectview.recent.acked=ОÑтанні внеÑки + +/site/contributors.bml.selectview.recent.all=ОÑтанні внеÑки, включно з невизнаними + +/site/contributors.bml.table.category=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ + +/site/contributors.bml.table.date=Дата + +/site/contributors.bml.table.item=ВнеÑок + +/site/contributors.bml.table.item.detail=докладніше + +/site/contributors.bml.title=Помічники + +/site/contributors.bml.unknownmode.text=Ðевідомий режим. + +/site/contributors.bml.unknownmode.title=Ðевідомий режим + +/site/contributors.bml.whoruns.header=Хто підтримує [[sitename]]? + +/site/contributors.bml.whoruns.text1=[[sitename]] почавÑÑ Ñƒ 1999 році, Ñк проект Бреда Фіцпатріка (Brad Fitzpatrick), Ñ– протÑгом перших двох років підтримувавÑÑ Ð²ÐµÐ»Ð¸ÐºÐ¾ÑŽ та прихільною групою волонтерів. Хоча [[sitename]] й доÑÑ– підтримуєтьÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸ волонтерів, зараз ми маємо невеликий керівний Ñклад, Ñкий доглÑдає за вÑіма операціÑми. + +/site/contributors.bml.whoruns.text2=Ðижченазвані люди - волонтери, Ñкі зробили Ñвій внеÑок у [[sitename]] та Ñерверний проект [[sitenameshort]]. + +/site/goat.bml.image.alt=Цап Френк - таліÑман LiveJournal. + +/site/goat.bml.image.caption="Ме-е-е", - каже Френк. + +/site/goat.bml.meet.body=Це Френк. Френк Ñ” таліÑманом LiveJournal. Він допомогає нам з випадковим програмуваннÑм, коли ми позаду, та іноді відповідає на запити до технічної підтримки. Френк дійÑно вельми багатобічний... він іноді навіть працює на дворі. Коли лужок розроÑтаєтьÑÑ, ми кажемо: "Гей, Френку! Ð§Ð°Ñ Ð¿ÐµÑ€ÐµÐºÑƒÑити... йди Ñ—Ñи лужок!". У цій Ñитуації дійÑно виграють вÑÑ–. + +/site/goat.bml.meet.header=ЗуÑтрічайте Френка + +/site/goat.bml.title=Цап Френк + +/site/index.bml.enhancedforpaidusers== краще у платних кориÑтувачів + +/site/index.bml.otherlinks.dev.changelog=ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð·Ð¼Ñ–Ð½ + +/site/index.bml.otherlinks.dev.contributors=Помічники + +/site/index.bml.otherlinks.dev.header=Розробка: + +/site/index.bml.otherlinks.dev.info=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² + +/site/index.bml.otherlinks.dev.serverdoc=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ñерверу [[sitename]] + +/site/index.bml.otherlinks.dev.test=ТеÑтовий Ñайт + +/site/index.bml.otherlinks.docs.guides=Довідник + +/site/index.bml.otherlinks.docs.header=ДокументаціÑ: + +/site/index.bml.otherlinks.docs.serverdoc=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ñерверу [[sitename]] + +/site/index.bml.otherlinks.feedback.header=Зворотній зв'Ñзок: + +/site/index.bml.otherlinks.feedback.suggestions=Пропозиції + +/site/index.bml.otherlinks.feedback.support=Технічна підтримка + +/site/index.bml.otherlinks.header=Інші поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/site/index.bml.otherlinks.offsite.header=Сторонні нÑтрументи: + +/site/index.bml.otherlinks.offsite.joule=Ðналіз, минуле та ÑÑŒÐ¾Ð³Ð¾Ð´ÐµÐ½Ð½Ñ ÑпиÑку друзів + +/site/index.bml.otherlinks.offsite.meetup=ЗуÑтрічаймоÑÑ! + +/site/index.bml.otherlinks.press.area=ПреÑ-зона + +/site/index.bml.otherlinks.press.header=ЗМІ: + +/site/index.bml.otherlinks.press.inthepress=[[sitename]] у ЗМІ + +/site/index.bml.otherlinks.press.staff=Керівний Ñклад + +/site/index.bml.otherlinks.press.stats=СтатиÑтика + +/site/index.bml.otherlinks.status.header=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ ÑервіÑу: + +/site/index.bml.otherlinks.status.news=Сторінка новин + +/site/index.bml.otherlinks.status.statuspage=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ [[sitename]] + +/site/index.bml.paidonlyfeature== тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів + +/site/index.bml.thanks=ДÑкуємо [[user]] за першу верÑÑ–ÑŽ цієї Ñторінки. + +/site/index.bml.title=Мапа Ñайту + +/site/index.bml.userlinks.clients.download=Скачати програму-клієнт + +/site/index.bml.userlinks.clients.faqcat=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ FAQ + +/site/index.bml.userlinks.clients.header=Програми-клієнти: + +/site/index.bml.userlinks.clients.voicepost=ГолоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/site/index.bml.userlinks.clients.web=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· веб + +/site/index.bml.userlinks.clients.webfull=(розширений режим) + +/site/index.bml.userlinks.communities.center=Центр Ñпільнот + +/site/index.bml.userlinks.communities.create=Створити Ñпільноту + +/site/index.bml.userlinks.communities.faqcat=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ FAQ + +/site/index.bml.userlinks.communities.faqcatmanage=FAQ з ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ñпільнотою + +/site/index.bml.userlinks.communities.header=Спільноти: + +/site/index.bml.userlinks.communities.manage=Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ñпільнотами + +/site/index.bml.userlinks.friends.birthdays=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +/site/index.bml.userlinks.friends.edit=Редагувати ваших друзів + +/site/index.bml.userlinks.friends.editgroups=Редагувати оÑобливі групи друзів + +/site/index.bml.userlinks.friends.filter=Фільтр друзів + +/site/index.bml.userlinks.friends.header=Друзі + +/site/index.bml.userlinks.friends.popusers=ПопулÑрні кориÑтувачі Ñеред ваших друзів + +/site/index.bml.userlinks.fun.banners=Банери + +/site/index.bml.userlinks.fun.frank=Цап Френк! + +/site/index.bml.userlinks.fun.header=Розваги: + +/site/index.bml.userlinks.fun.meme=Вузлик на пам'ÑÑ‚ÑŒ + +/site/index.bml.userlinks.fun.singles=Служба знайомÑтв + +/site/index.bml.userlinks.fun.song=ПіÑÐ½Ñ Ð¿Ñ€Ð¾ … [[sitename]]! + +/site/index.bml.userlinks.header=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів + +/site/index.bml.userlinks.international.convert=Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ñтарого ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + +/site/index.bml.userlinks.international.header=ЛокалізаціÑ: + +/site/index.bml.userlinks.international.setlang=Обрати мову + +/site/index.bml.userlinks.international.translate=Переклад LiveJournal + +/site/index.bml.userlinks.legal.coppa=Політика COPPA + +/site/index.bml.userlinks.legal.faqcat=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ FAQ + +/site/index.bml.userlinks.legal.header=Правова інформаціÑ: + +/site/index.bml.userlinks.legal.principles=Принципи, Ñкими ми керуємоÑÑ + +/site/index.bml.userlinks.legal.privacy=Політика конфіденційноÑÑ‚Ñ– + +/site/index.bml.userlinks.legal.report=Повідомити про Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ + +/site/index.bml.userlinks.legal.tos=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +/site/index.bml.userlinks.new.about=Про [[sitename]] + +/site/index.bml.userlinks.new.create=Створити рахунок + +/site/index.bml.userlinks.new.header=Ðещодавно на [[sitename]]? + +/site/index.bml.userlinks.new.newbies=Кімната Ð´Ð»Ñ Ð½Ð¾Ð²Ð°Ñ‡ÐºÑ–Ð² + +/site/index.bml.userlinks.new.question=Маєте питаннÑ? + +/site/index.bml.userlinks.new.tour=ЗдійÑніть екÑкурÑÑ–ÑŽ по [[sitename]] + +/site/index.bml.userlinks.paid.buyforfriends=Придбати Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²! + +/site/index.bml.userlinks.paid.faqcat=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ FAQ + +/site/index.bml.userlinks.paid.features=ПорівнÑÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾Ñтей рахунків + +/site/index.bml.userlinks.paid.giftcerts=Подарункові купони + +/site/index.bml.userlinks.paid.header=Платні рахунки: + +/site/index.bml.userlinks.paid.history=Попередні платежі + +/site/index.bml.userlinks.paid.paidaccounts=Платні рахунки + +/site/index.bml.userlinks.paid.rename=ÐŸÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/site/index.bml.userlinks.paid.status=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку + +/site/index.bml.userlinks.paid.voicepost=ГолоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/site/index.bml.userlinks.s1.create=Створити Ñтиль + +/site/index.bml.userlinks.s1.edit=Змінити Ñтилі + +/site/index.bml.userlinks.s1.header=СиÑтема Ñтилів S1: + +/site/index.bml.userlinks.s1.reference=ПоÑібник по ÑтилÑм + +/site/index.bml.userlinks.s1.settings=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S1 + +/site/index.bml.userlinks.s2.advanced=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/site/index.bml.userlinks.s2.customize=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/site/index.bml.userlinks.s2.header=СиÑтема Ñтилей S2: + +/site/index.bml.userlinks.s2.layerbrowser=ОглÑдач шарів + +/site/index.bml.userlinks.s2.manual=ПоÑібник по S2 + +/site/index.bml.userlinks.search.directory=Пошук по каталогу + +/site/index.bml.userlinks.search.header=Пошук кориÑтувачів: + +/site/index.bml.userlinks.search.interest=За зацікавленнÑми + +/site/index.bml.userlinks.search.random=Випадковий кориÑтувач + +/site/index.bml.userlinks.search.region=За регіоном + +/site/index.bml.userlinks.support.ask=Спитати + +/site/index.bml.userlinks.support.faqpop=ПопулÑрні поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/site/index.bml.userlinks.support.header=Технічна підтримка: + +/site/index.bml.userlinks.support.help=Допоможіть іншим + +/site/index.bml.userlinks.support.highscores=Ðайвищі бали + +/site/index.bml.userlinks.support.notifications=Змінити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ + +/site/index.bml.userlinks.syn.faqcat=ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ FAQ + +/site/index.bml.userlinks.syn.header=СиндикаціÑ: + +/site/index.bml.userlinks.syn.recent=Ðещодавно оновлені потоки + +/site/index.bml.userlinks.syn.synaccounts=Синдикативні рахунки + +/site/index.bml.userlinks.tools.adminconsole=ÐдмініÑтративна конÑоль + +/site/index.bml.userlinks.tools.export=Зберегти журнал + +/site/index.bml.userlinks.tools.header=Різне: + +/site/index.bml.userlinks.tools.invitefriend=ЗапроÑити друга + +/site/index.bml.userlinks.tools.memories=Вибране + +/site/index.bml.userlinks.tools.pollcreator=Створити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/site/index.bml.userlinks.tools.portal=Портал + +/site/index.bml.userlinks.tools.reference=ÐžÐ¿Ð¸Ñ + +/site/index.bml.userlinks.tools.textmessage=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° мобільний + +/site/index.bml.userlinks.tools.todo=СпиÑок Ñправ + +/site/index.bml.userlinks.tools.whereami=Де Ñ? + +/site/index.bml.userlinks.youraccount.changepassword=Змінити пароль + +/site/index.bml.userlinks.youraccount.create=Створити рахунок + +/site/index.bml.userlinks.youraccount.deletejournal=Видалити/поновити журнал + +/site/index.bml.userlinks.youraccount.edit=Змінити журнальні запиÑи + +/site/index.bml.userlinks.youraccount.emailmanagement=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ email-адреÑою + +/site/index.bml.userlinks.youraccount.filemanager=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸ + +/site/index.bml.userlinks.youraccount.header=Ваш рахунок: + +/site/index.bml.userlinks.youraccount.login=Увійти до рахунку + +/site/index.bml.userlinks.youraccount.lostpassword=Загубили пароль? + +/site/index.bml.userlinks.youraccount.update=Поновити журнал + +/site/index.bml.userlinks.yoursettings.browseprefs=Параметри переглÑду + +/site/index.bml.userlinks.yoursettings.customize=Ðалаштувати журнал + +/site/index.bml.userlinks.yoursettings.editinfo=Змінити дані + +/site/index.bml.userlinks.yoursettings.emailgateway=Ðалаштувати email-шлюз + +/site/index.bml.userlinks.yoursettings.header=Ваші налаштуваннÑ: + +/site/index.bml.userlinks.yoursettings.linklist=Створити ÑпиÑок поÑилань + +/site/index.bml.userlinks.yoursettings.manageall=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñіма налаштуваннÑми + +/site/index.bml.userlinks.yoursettings.userpics=Зміна та Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑŽÐ·ÐµÑ€Ð¿Ð¸Ðº + +/site/index.bml.userlinks.yoursettings.voicepost=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень + +/site/search.bml.advanced.header=Розширений пошук + +/site/search.bml.advanced.text=Шукати за декількома критеріÑми. + +/site/search.bml.feeds.header=ПереглÑнути Ñиндикативні потоки + +/site/search.bml.interests.header=Шукати за зацікавленнÑми + +/site/search.bml.interests.text=Знайти людей та Ñпільноти за зацікавленнÑми. + +/site/search.bml.paidonlyfeature== тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків + +/site/search.bml.random.header=ПереглÑнути випадковий журнал + +/site/search.bml.random.text=Знайти випадковий журнал, що був оновлений протÑгом оÑтаннього днÑ. + +/site/search.bml.region.header=Шукати за регіоном + +/site/search.bml.region.text=Знайти журнали за облаÑÑ‚ÑŽ чи країною. + +/site/search.bml.schools.header=ПереглÑнути каталог навчальних закладів + +/site/search.bml.searchmethods.header=Методи пошуку + +/site/search.bml.title=Пошук + +/step2.bml.comm.vip=Зірочка (*) Ð±Ñ–Ð»Ñ Ñпільнот означає, що ваш друг Ñ” доглÑдачем або модератором цієї Ñпільноти. + +/step2.bml.friends.intro=Оберіть ці пункти Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб отримувати Ñвіжу, кориÑну інформацію. Вона буде відображатиÑÑ Ñƒ вашій Ñтрічці друзів, а не у потштовій Ñкриньці. + +/step2.bml.heading_acctlevel=Оберіть тип рахунку + +/step2.bml.heading_friends=Друзі + +/step2.bml.heading_useful=КориÑна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/step2.bml.invite.addfriend=додати [[ljuser]] до друзів + +/step2.bml.invite.welcome=Ваш друг [[ljuser]] вітає Ð²Ð°Ñ Ñƒ [[sitename]]. + +/step2.bml.submit=ÐадіÑлати + +/step2.bml.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/styles/create.bml.choosebase=Оберіть початковий базовий Ñтиль Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸: + +/styles/create.bml.createstyle.head=Створити Ñтиль + +/styles/create.bml.createstyle.text=Тут ви можете Ñтворити новий перÑональний Ñтиль, Ñкий може Ñтати вам в пригоді, Ñкщо ви хочете інтегрувати журнал до Ñвоєї домашньої Ñторінки або Ñтворити публічний Ñтиль, Ñким зможе кориÑтуватиÑÑ Ð±ÑƒÐ´ÑŒ-хто. Вам Ñлід Ñпочатку попрацювати над ним тут, але не в Ñвоєму розділі кодів перекриттÑ. Зауважте, що лише кориÑтувачі з платними рахунками можуть Ñтворювати влаÑні Ñтилі. + +/styles/create.bml.createstyle.text2=Тут ви можете Ñтворити новий перÑональний Ñтиль Ñ– викориÑтати його, за потреби, Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ до Ñвоєї домашньої Ñторінки, або Ñтворити публічний Ñтиль, Ñким зможе викориÑтати будь-хто. Вам Ñлід Ñпочатку попрацювати над ним тут, але не в вашому розділі кодів перекриттÑ.

    Зауважте, що лише кориÑтувачі з платними рахунками можуть Ñтворювати влаÑні Ñтилі.

    + +/styles/create.bml.enterstyleid=Ðбо введіть неÑиÑтемний публічний ID# Ñтилю: + +/styles/create.bml.noneorother=(Жодний, або введіть нижче інший:) + +/styles/create.bml.selecttype.head=Оберіть тип Ñтилю + +/styles/create.bml.selecttype.text=Стиль впливає лише на один тип виглÑду. Якщо ви бажаєте Ñтворити Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу набір Ñтилів, Ñкі збігаютьÑÑ, то вам потрібно Ñтворити Ñтиль Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ типу виглÑду. + +/styles/create.bml.submit=Створити Ñтиль + +/styles/create.bml.title=Створити Ñтиль + +/styles/create_do.bml.editstyle=Змінити Ñтиль + +/styles/create_do.bml.error.accounttype=Ваш тип рахунку не дозволÑÑ” вам Ñтворювати Ñтилі. + +/styles/create_do.bml.error.invalidview=Ви не обрали дійÑний тип Ñтилю. + +/styles/create_do.bml.error.styleexists=Ви вже маєте Ñтиль цього типу під назвою [[des]]. Якщо ви дійÑно бажаєте Ñтворити новий Ñтиль типу [[view]], тоді модифікуйте Ñвій Ñтарий Ñтиль [[view]], змінить його ім'Ñ, а потім повертайтеÑÑ Ñюди, щоб Ñтворити новий Ñтиль цього типу. + +/styles/create_do.bml.error.stylenotfound=Стиль, з Ñкого ви намагаєтеÑÑ Ñтворити новий Ñтиль ([[baseid]]), здаєтьÑÑ, не Ñ–Ñнує. + +/styles/create_do.bml.error.stylenotpublic=Стиль, з Ñкого ви намагаєтеÑÑ Ñтворити новий Ñтиль ([[baseid]]), не Ñ” публічним, тому ви не можете копіювати його. + +/styles/create_do.bml.success.head=УÑпішно + +/styles/create_do.bml.success.text=Ваш Ñтиль було Ñтворено Ñ– тимчаÑово надано ім'Ñ [[des]]. Ви можете почати змінювати його, натиÑнувши кнопку, розташовану нижче. + +/styles/create_do.bml.title=Створити Ñтиль + +/styles/edit.bml.edit.action=ДіÑ: + +/styles/edit.bml.edit.delete=Видалити цей Ñтиль! + +/styles/edit.bml.edit.easy=Змінити у Ñпрощеному режимі + +/styles/edit.bml.edit.head=Ви маєте наÑтупні Ñтилі. Оберіть той, що хочете змінити. + +/styles/edit.bml.edit.nostyle=жодних Ñтилів + +/styles/edit.bml.edit.raw=Змінити у режимі вихідного текÑту (Ñтарий режим) + +/styles/edit.bml.edit.submit=Продовжити + +/styles/edit.bml.edit.text2=Оберіть Ñтиль: + +/styles/edit.bml.editstyle.head=Який Ñтиль змінюватимемо? + +/styles/edit.bml.editstyle.text2=ПіÑÐ»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñтилю ви зможете змінити його тут. Щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про ÑиÑтему Ñтилів, натиÑніть Ñюди. + +/styles/edit.bml.title=Змінити Ñтиль + +/styles/edit_do.bml.delete.confirmed.head=Видалено + +/styles/edit_do.bml.delete.confirmed.text=Стиль було видалено. Ви можете подивитиÑÑ Ð²Ð°Ñˆ поточний перелік Ñтилів тут. + +/styles/edit_do.bml.delete.head=Ви впевнені? + +/styles/edit_do.bml.delete.submit=Так, видалити! + +/styles/edit_do.bml.delete.text=Ви Ñправді хочете видалити [[style]]? Якщо так, натиÑніÑÑ‚ÑŒ кнопку нижче. Якщо ви поÑлуговувалиÑÑ Ñ†Ð¸Ð¼ Ñтилем, ваш журнал не працюватиме, доки ви не оберете іншого Ñтилю. + +/styles/edit_do.bml.edit.col.code=Код + +/styles/edit_do.bml.edit.col.description=ОпиÑ: + +/styles/edit_do.bml.edit.col.transform=ТранÑформувати + +/styles/edit_do.bml.edit.colorcodes.head=Коди кольорів + +/styles/edit_do.bml.edit.colorcodes.text=Створюючи Ñтиль, краще уникати прÑмого Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð². Таким чином, за потреби ви зможете з легкіÑÑ‚ÑŽ змінювати вÑÑ– кольори в одному міÑці (на Ñторінці налаштувань журналу) й це позначитьÑÑ Ð½Ð° вÑÑ–Ñ… ÑтилÑÑ…, де ви заÑтоÑовуватимете код цього кольору. Звичайно, Ñкщо вам необхідно викориÑтати Ñпеціальні Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ Ñвоєму Ñтилі, ви можете задіÑти прÑме Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð², але намагайтеÑÑ Ñ†ÑŒÐ¾Ð³Ð¾ уникати. Ви можете викориÑтовувати ці кольори в будь-Ñкій змінній, що міÑтить HTML: + +/styles/edit_do.bml.edit.customize.head=Змінні кориÑтувача + +/styles/edit_do.bml.edit.description=ÐžÐ¿Ð¸Ñ Ñтилю: + +/styles/edit_do.bml.edit.head=Змінити Ñтиль + +/styles/edit_do.bml.edit.links.head=Зручні поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/styles/edit_do.bml.edit.links.text=Ви можете викориÑтовувати ці поÑиланнÑ, щоб прокрутити Ñторінку до міÑцÑ, де опиÑана вказана змінна. + +/styles/edit_do.bml.edit.options=Параметри Ñтилю: + +/styles/edit_do.bml.edit.override.head=Лише Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів. + +/styles/edit_do.bml.edit.override.text=Тільки кінцеві кориÑтувачі можуть змінювати цей параметр. Ви не можете визначити його в Ñтилі. + +/styles/edit_do.bml.edit.preview=[ПереглÑнути поточний Ñтиль] (потрібно зберегти зміни нижче, щоб Ñ—Ñ… побачити; не закривайте вікно Ñ– перезавантажте його піÑÐ»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½) + +/styles/edit_do.bml.edit.styleid=Унікальний номер Ñтилю: + +/styles/edit_do.bml.edit.submit=Зберегти Ñтиль + +/styles/edit_do.bml.edit.success.head=УÑпішно + +/styles/edit_do.bml.edit.success.text=Стиль було оновлено. Можете переглÑнути його тут. + +/styles/edit_do.bml.edit.text=ВнеÑÑ–Ñ‚ÑŒ необхідні зміни та натиÑніть "Зберегти" піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ. + +/styles/edit_do.bml.edit.transforms.head=ТранÑформації + +/styles/edit_do.bml.edit.transforms.text=Що робити, Ñкщо ви бажаєте викориÑтовувати влаÑтивіÑÑ‚ÑŒ, але вам не подобаєтьÑÑ Ñ—Ñ— форматуваннÑ? Будь-Ñка влаÑтивіÑÑ‚ÑŒ може бути транÑформована 0 або більше разів із заÑтоÑуваннÑм правил транÑформації. Ðаприклад, ви хочете викориÑтовувати %%monlong%% (Березень, Квітень, Травень тощо), але вам не подобаєтьÑÑ, що за замовчуваннÑм перша літера Ñлова — велика. Ви можете заÑтоÑувати транÑформацію lc (нижній регіÑÑ‚Ñ€):%%lc:monlong%%. ТранÑформації заÑтоÑовуютьÑÑ Ñправа наліво, тобто Ñкщо ви заÑтоÑуєте %%a:b:c:d:property%%, першим буде виконано d. ОÑÑŒ перелік можливих транÑформацій: + +/styles/edit_do.bml.edit.type=Типи виглÑду Ñтилю: + +/styles/edit_do.bml.edit.variables.head=Змінні Ñтилю: + +/styles/edit_do.bml.edit.variables.text=(Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð·Ð° поÑиланнÑм) + +/styles/edit_do.bml.error.mode=Ðевідомий режим: + +/styles/edit_do.bml.error.nostyle=Вказаний Ñтиль не Ñ–Ñнує. + +/styles/edit_do.bml.opts.colorfree.des=Стиль вважаєтьÑÑ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ð¾Ð½ÐµÐ·Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼, Ñкщо він не міÑтить жодних прÑмих зазначень кольорів, а лише загальні коди, вказані в таблиці нижче. + +/styles/edit_do.bml.opts.colorfree.title=Кольоронезалежний? + +/styles/edit_do.bml.opts.embedded.des=Цей Ñтиль розроблений Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб бути вбудованим у чиюÑÑŒ Ñторінку? Якщо так — увімкніть. Ðе вмикайте, Ñкщо це Ñтиль цілої Ñторінки. + +/styles/edit_do.bml.opts.embedded.title=Вбудований? + +/styles/edit_do.bml.opts.public.des=Зробіть Ñтиль загальнодоÑтупним, Ñкщо згодні, щоб інші могли його викориÑтовувати чи копіювати. + +/styles/edit_do.bml.opts.public.title=ЗагальнодоÑтупний? + +/styles/edit_do.bml.transforms.color.des=ТранÑформаціÑ, що керує кодами кольорів. Див. таблицю кодів кольорів. + +/styles/edit_do.bml.transforms.cons.des=КонÑтанти доÑтупу до Ñайту. Ðаразі підтримуютьÑÑ: 'siteroot', 'sitename' та 'img' (кореневий Ð´Ð»Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ). Приклад: %%cons:img%%/icon_protected.gif + +/styles/edit_do.bml.transforms.lc.des=Ðижній регіÑÑ‚Ñ€ + +/styles/edit_do.bml.transforms.ljcomm.des=ТранÑформує змінну, наче вона обмежена <lj comm=%%variable%%>. Ðаприклад: %%ljcomm:username%%" + +/styles/edit_do.bml.transforms.ljuser.des=ТранÑформує змінну, наче вона обмежена <lj user=%%variable%%>. Ðаприклад: %%ljuser:username%% + +/styles/edit_do.bml.transforms.uc.des=Верхній регіÑÑ‚Ñ€ + +/styles/edit_do.bml.transforms.ue.des=ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑи. Змінює пробіли на +, а вÑÑ– неприпуÑтимі Ñимволи — на шіÑтнадцÑткові вирази %hh. ВикориÑтовуйте Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² даних, що заÑтоÑовуютьÑÑ Ð² роликах Flash-4. + +/styles/edit_do.bml.transforms.userurl.des=Отримує Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, транÑформуючи в поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° його журнал. + +/styles/edit_do.bml.transforms.xe.des=ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ XML. Робить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½Ð½Ð¾Ñ— доÑтупним Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ñк атрибут чи елемент XML. Замінює амперÑанди, кутові дужки й обидва типи лапок. Проте не замінює ]]>, тому не заÑтоÑовуйте елементи CDATA. + +/styles/index.bml.about.header=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Ð¾Ñобливих Ñтилів + +/styles/index.bml.about2<< +

    Ðа цій Ñторінці зібрані поÑиланнÑ, за Ñкими ви можете Ñтворити й змінювати Ñтилі S1 на влаÑний Ñмак або за потреби видалити Ñ—Ñ…. Якщо ви кориÑтуєтеÑÑ ÑиÑтемою Ñтилів S2, перейдіть на Ñторінку Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ñтилі S1 та S2 тут.

    + +

    ДоÑвідчені кориÑтувачі знайдуть додаткову інформацію про ÑиÑтему Ñтилів на Ñторінці документації зі Ñтилів та в розділі розробників.

    + +

    Зверніть увагу, що тільки влаÑники платних рахунків можуть Ñтворювати й викориÑтовувати оÑобливі Ñтилі. ВлаÑники безкоштовних рахунків можуть обрати ÑкийÑÑŒ із готових Ñтилів LiveJournal на Ñторінці налаштувань виглÑду журналу.

    + +
    + +
    +. + +/styles/index.bml.about3<< +

    Тут наведено поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñторінки, де ви можете Ñтворити й змінювати Ñтилі S1 на влаÑний Ñмак, а також за потреби видалити Ñ—Ñ…. Якщо ви кориÑтуєтеÑÑ ÑиÑтемою Ñтилів S2, перейдіть на +Ñторінку Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ñтилі S1 та S2 тут.

    + +

    ДоÑвідчені кориÑтувачі можуть знайти додаткову інформацію про ÑиÑтему Ñтилів на +Ñторінці документації зі Ñтилів або в +розділі Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð².

    + +

    Будь лаÑка, зауважте, що тільки влаÑники платних +рахунків можуть Ñтворювати й викориÑтувати оÑобливі Ñтилі. ВлаÑники базових +рахунків можуть обрати ÑкийÑÑŒ із готових Ñтилів [[sitename]] на +Ñторінці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ.

    + +
    + +
    +. + +/styles/index.bml.nav.browse=ОглÑдач Ñтилів + +/styles/index.bml.nav.browse.about=ОглÑдач Ñтилів дозволÑÑ” вам проглÑдати публічні Ñтилі, Ñтворені іншими кориÑтувачами. + +/styles/index.bml.nav.create=Створити новий Ñтиль + +/styles/index.bml.nav.create.about=Створити новий Ñтиль з Ñамого початку або базувати ваш Ñтиль на Ñ–Ñнуючому публічному Ñтилі. + +/styles/index.bml.nav.edit=Змінити або видалити Ñ–Ñнуючий Ñтиль + +/styles/index.bml.nav.edit.about=Ви можете змінювати лише Ñтилі, Ñкими “володіє” ваш рахунок. Щоб змінити ÑиÑтемний Ñтиль, вам Ñпочатку потрібно Ñтворити новий Ñтиль, Ñкий базуєтьÑÑ Ð½Ð° Ñтилі ÑиÑтемному. + +/styles/index.bml.nav.embedding=Додайте Ñвій журнал на влаÑний Ñайт + +/styles/index.bml.nav.embedding.about=Якщо у Ð²Ð°Ñ Ð±ÐµÐ·ÐºÐ¾ÑˆÑ‚Ð¾Ð²Ð½Ð¸Ð¹ рахунок, ваш доданий журнал буде відображатиÑÑ Ð² тому ж виглÑді, що й в LiveJournal. КориÑтувачі з платними рахунками можуть повніÑÑ‚ÑŽ змінювати виглÑд Ñвоїх доданих журналів. + +/styles/index.bml.nav.header=Швидкі поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/styles/index.bml.nav.modify=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/styles/index.bml.nav.modify.about=Змінити Ñтиль за замовчуваннÑм вашого рахунку — або на запропонований ÑиÑтемою, або на Ñтворений вами. + +/styles/index.bml.title=ОÑобливі Ñтилі + +/suggestions/index.bml.howto.text2<< +
    +
    Прочитайте попередні пропозиції
    +Спочатку ознайомтеÑÑ Ð· оÑтанніми пропозиціÑми, аби переконатиÑÑ, що нічого подібного доÑÑ– не було запропоновано. Якщо ж це не так, ви можете проглÑнути коментарі до відповідного запиÑу. ЧаÑом здаєтьÑÑ, наче Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ñ–Ð³Ð½Ð¾Ñ€ÑƒÑ”Ñ‚ÑŒÑÑ, проте, можливо, вона перебуває у розробці. Іноді ідеї відхилÑÑŽÑ‚ÑŒÑÑ Ñ‡Ð¸ відкладаютьÑÑ Ð· різних причин. +
    +
    Ðе знайшли аналогів Ñвоєї ідеї? ПоділітьÑÑ Ð½ÐµÑŽ з нами!
    +Цей шаблон призначено Ð´Ð»Ñ Ð²ÑÑ–Ñ… пропозицій. ПереконайтеÑÑ, що ви заповнили вÑÑ– Ð¿Ð¾Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ñƒ, а ваша Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð¾Ð¿Ð¸Ñана докладно й правильно. Генератор пропозицій не додає кінці Ñ€Ñдків, тож Ð´Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÑту Ñлід ÑкориÑтовувати тег <br>. Це зробить вашу пропозицію більш зручною Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. +
    +
    Відправити!
    +Ви можете додати Ñпільноту [[suggestionscomm]] до Ñвоєї Ñтрічки друзів тут. Щойно Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ опублікована, почнетьÑÑ Ñ—Ñ— обговореннÑ. Якщо це дійÑно гарна ідеÑ, Ñ—Ñ— додадуть до переліку проектів, Ñкі перебувають у розробці, та працюватимуть над нею, наÑкільки дозволить чаÑ. Ðе вÑÑ– пропозиції можна реалізувати негайно, так що чекайте, поки йде процеÑ. +
    +. + +/suggestions/index.bml.howto.title=Як мені зробити пропозицію? + +/suggestions/index.bml.info.text2<< +Відчуваєте, що можете зробити Ñвій внеÑок до реалізації влаÑних ідей? ПереглÑньте наÑтупні Ñпільноти: +
    +
    [[sitename]] Форум розробників — Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚ÐµÑ…Ð½Ñ–Ñ‡Ð½Ð¸Ñ… деталей.
    +
    +
    [[sitename]] БізнеÑ-форум — Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñновних можливоÑтей ділової діÑльноÑÑ‚Ñ– [[sitename]] та Ñуміжних облаÑтей.
    +
    +
    [[sitename]] Форум документації Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів — Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾ÑÑ‚Ñ– форм документації Ð´Ð»Ñ ÐºÑ–Ð½Ñ†ÐµÐ²Ð¸Ñ… кориÑтувачів.
    +
    +
    [[sitename]] Ðрт-форум — Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° обмін іконок, тем наÑтроїв, кольорових тем Ñ– юзерпик.
    +
    +
    +Будь лаÑка, пам’Ñтайте, що люди, Ñкі запроваджують зміни та Ð½Ð¾Ð²Ð¾Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð´Ð¾ [[sitename]], такі ж кориÑтувачі, Ñк Ñ– ви. Ці речі можуть зайнÑти багато чаÑу Ñ– чим більше ви допоможете у впровадженні, тим більше буде зроблено. +. + +/suggestions/index.bml.info.title=Інша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +/suggestions/index.bml.rules2<< +Є кілька речей, про Ñкі Ñлід пам’Ñтати: +
      +
    • Чимало пропозицій вже було зроблено Ñ– обговорено, але проÑто доÑÑ– не впроваджено. ПереÑвідчитьÑÑ, що ви не відправлÑєте дублікат.
    • +
    • Скандали не дозволÑÑŽÑ‚ÑŒÑÑ. Будь-хто має Ñвою думку ÑтоÑовно того, Ñк Ñаме [[sitename]] Ñлід працювати; пам’Ñтайте, що можна (Ñ– треба) відÑтоювати влаÑну точку зору, але не можна образливо ÑтавитиÑÑ Ð´Ð¾ іншої.
    • +
    • Зробіть Ñвою пропозицію макÑимально вичерпною. ПропозиціÑ, що міÑтить нотатки щодо реалізаці, має більше шанÑів бути Ñхваленою, ніж та, що Ñ—Ñ… немає. Вам не обов’Ñзково треба бути оÑвідченим у програмуванні; проÑто Ñпробуйте подумати, що ваша Ñ–Ð´ÐµÑ Ð¼Ð¾Ð¶Ðµ зачіпити Ñ– Ñкі проблеми можуть бути із цим пов’Ñзані.
    • +
    • ПереÑвідчитьÑÑ, що ви Ñпочатку перечитали FAQ, щоб подивитиÑÑ, чи не була ваша Ñ–Ð´ÐµÑ Ð²Ð¶Ðµ реалізована, або ÑкийÑÑŒ з аÑпектів Ñайту може бути викориÑтаний Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚Ð¾Ð³Ð¾, що вам треба.
    • +
    • Якщо ви хочете поÑтавити Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ ÑтоÑовно роботи [[sitename]], не впевнені у наÑвноÑÑ‚Ñ– тої чи іншої можливоÑÑ‚Ñ– або маєте інші проблеми, не надÑилайте пропозиції. ЗаміÑÑ‚ÑŒ цього звернітьÑÑ Ð´Ð¾ Служби підтримки.
    • +
    +. + +/suggestions/index.bml.title=Розділ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¹ + +/suggestions/index.bml.welcome.text=Пропозиції кориÑтувачів Ñ” важливою чаÑтиною LiveJournal. Якщо ви маєте щоÑÑŒ, що, Ñк ви гадаєте, було б файною ідеєю, то ви можете дотриматиÑÑ Ñ†Ð¸Ñ… процедур, щоб привернути увагу людей, Ñкі підтримують цей Ñайт. + +/suggestions/index.bml.welcome.title=ЛаÑкаво проÑимо! + +/support/append_request.bml.back.support2=ПовернутиÑÑ Ð´Ð¾ Ñторінки підтримки. + +/support/append_request.bml.bounce.noemail=Ðе зазначено e-mail адреÑу Ð´Ð»Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÑннÑ. + +/support/append_request.bml.bounce.notauth=Вам не дозволено відхилÑти цей запит. + +/support/append_request.bml.bounce.toomany=Ви можете надÑилати тільки до не більше ніж п'Ñти e-mail адреÑ. Ви зазначили більше ніж п'ÑÑ‚ÑŒ. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Запит про підтримку було закрито. + +/support/append_request.bml.closed.title=Закрито + +/support/append_request.bml.internal.approve=Щоб Ñхвалити відповідь, ви маєте обрати "Внутрішній коментар / ДіÑ" Ñ– поÑÑнити, необов'Ñзково, чому ви Ñхвалюєте його. + +/support/append_request.bml.internal.changecat=Щоб змінити категорію запиту, ви маєте обрати "Внутрішній коментар / ДіÑ" Ñ– поÑÑнити, необов'Ñзково, чому ви змінюєте Ñ—Ñ—. + +/support/append_request.bml.internal.changesum=Щоб змінити оглÑд запиту, ви маєте обрати "Внутрішній коментар / ДіÑ" Ñ– ввеÑти новий оглÑд. + +/support/append_request.bml.internal.touch=Щоб змінити ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ, ви маєте обрати "Внутрішній коментар / ДіÑ" Ñ– поÑÑнити, чому ви змінюєте його. + +/support/append_request.bml.invalid.blank=Ваше Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ порожнє. Ðадрукуйте, будь лаÑка, хоч щоÑÑŒ у полі Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ. + +/support/append_request.bml.invalid.noanswer=Ðевірний прихований коментар Ð´Ð»Ñ ÑхваленнÑ. + +/support/append_request.bml.invalid.nocat=Ð¦Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ, здаєтьÑÑ, не Ñ–Ñнує. + +/support/append_request.bml.invalid.noid=Ð¦Ñ Ð´Ñ–Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÑ” Ð½Ð°Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ запиту до центру підтримки. + +/support/append_request.bml.invalid.nosummary=Ви маєте ввеÑти оглÑд запиту. + +/support/append_request.bml.invalid.type=Ðевірний тип відповіді. + +/support/append_request.bml.logged.text=Вашу дію/коментар/відповідь було запиÑано. ДÑкуємо. + +/support/append_request.bml.logged.title=УÑпішно + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.successlinks2<< + +. + +/support/append_request.bml.title=Приєднати коментар/відповідь + +/support/append_request.bml.unknown.request=Ðевідомий запит підтримки + +/support/encodings.bml.edit.header=Я не можу змінити мої запиÑи у веб-інтерфейÑÑ–! + +/support/encodings.bml.edit.text<< +Коротка відповідь: (Ñкщо ви ведете Ñвій журнал англійÑькою): Завітайте до Ñторінки зміни налаштувань. Оберіть "Western European (Windows)" з меню та збережіть ваші налаштуваннÑ. Тепер ви матимете можливіÑÑ‚ÑŒ редагувати ваші запиÑи. p?> + +Довга відповідь: Щоб мати можливіÑÑ‚ÑŒ редагувати ваші запиÑи, Ñкі були не в Unicode, LiveJournal має знати, Ñке ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾, коли ви робили запиÑи. Ð”Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів англійÑькою чи іншими західноєвпройÑькими мовами, зазвичай буде "Western European (Windows)", хоча Ñкщо це не Ñпрацює Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… Ñимволів, Ñпробуйте "Western European (ISO)". КориÑутвачі, що кориÑтуютьÑÑ Ñ–Ð½ÑˆÐ¸Ð¼Ð¸ мовами мають обрати Ñвоє кодуваннÑ; Ñкщо його нема у ÑпиÑку, напишіть до Служби підтримки та поÑÑніть Ñвою проблему. p?> + + +. + +/support/encodings.bml.edit.text2<< +Коротка відповідь: (Ñкщо ви ведете Ñвій журнал англійÑькою): Завітайте до Ñторінки зміни налаштувань. Оберіть "Western European (Windows)" з меню та збережіть ваші налаштуваннÑ. Тепер ви матимете можливіÑÑ‚ÑŒ редагувати ваші запиÑи. p?> + +Довга відповідь: Щоб мати можливіÑÑ‚ÑŒ змінювати ваші запиÑи, Ñкі були не в Unicode, LiveJournal має знати, Ñке ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾, коли ви робили запиÑи. Ð”Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів англійÑькою чи іншими західноєвпройÑькими мовами, зазвичай буде "Western European (Windows)", хоча Ñкщо це не Ñпрацює Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… Ñимволів, Ñпробуйте "Western European (ISO)". КориÑутвачі, що кориÑтуютьÑÑ Ñ–Ð½ÑˆÐ¸Ð¼Ð¸ мовами мають обрати Ñвоє кодуваннÑ; Ñкщо його нема у ÑпиÑку, напишіть до Служби підтримки та поÑÑніть Ñвою проблему. p?> + + +. + +/support/encodings.bml.editcl.header=Я не можу змінити мої запиÑи у клієнтÑькій програмі! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Я не можу редагувати мій ÑпиÑок друзів у клієнтÑькій програмі! + +/support/encodings.bml.groups.text2<< +Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿ друзів, а потім ÑкориÑтуватиÑÑ Ð²Ð°ÑˆÐ¾ÑŽ клієнтÑькою програмою. p?> +. + +/support/encodings.bml.overview.header=Про що взагалі йдетьÑÑ? + +/support/encodings.bml.overview.text<< + + +. + +/support/encodings.bml.still.header=Ð’Ñе ще маєте проблему? + +/support/encodings.bml.still.text2=Служби Підтримки. p?> + +/support/encodings.bml.title=ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + +/support/faqbrowse.bml.backfaq2=ПовернутиÑÑ Ð´Ð¾ переліку питань. + +/support/faqbrowse.bml.backfaqcat2=ПовернутиÑÑ Ð´Ð¾ вищої категорії. + +/support/faqbrowse.bml.backfaqcat3=ПовернутиÑÑ Ð´Ð¾ категорії [[categoryname]]. + +/support/faqbrowse.bml.backsearch=ПовернутиÑÑ Ð´Ð¾ Ñторінки пошуку. + +/support/faqbrowse.bml.backsupport2=ПовернутиÑÑ Ð´Ð¾ Ñторінки підтримки. + +/support/faqbrowse.bml.edit.faq=Змінити це поширене Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/support/faqbrowse.bml.error.nofaq=Вказане поширене Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує. + +/support/faqbrowse.bml.lastupdated=ОÑтаннє оновленнÑ: + +/support/faqbrowse.bml.more=Прочитати більше + +/support/faqbrowse.bml.title_cat=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ — [[catname]] + +/support/faqbrowse.bml.title_num=Поширене Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ â„– [[num]] + +/support/faqsearch.bml.button.search=Пошук + +/support/faqsearch.bml.error.noresults=нічого не знайдено + +/support/faqsearch.bml.error.noterm=не введені параметри пошуку + +/support/faqsearch.bml.error.tooshort=параметри пошуку занадтно короткі + +/support/faqsearch.bml.example=Приклади: css, Ñтиль, наÑтрій, музика, код, mac + +/support/faqsearch.bml.info=ПитаннÑ, що міÑÑ‚ÑÑ‚ÑŒ ці умови в заголовку або у текÑÑ‚Ñ– наведені нижче. Ð’ÑÑ– Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ бути перекладені тільки чаÑтково. + +/support/faqsearch.bml.label.lang=Мова + +/support/faqsearch.bml.label.term=Умови пошуку + +/support/help.bml.interim<< + + + + + + +
    • Будьте профеÑійними та ввічливими.
    • +
    • Ðе копіюйте відповіді інших людей.
    • +
    • Контакуйте з людьми лише на дошці оголошень Служби підтримки, щоб дати відповідь чи отримати більше інформації щодо запиту.
    • +
    • Тримайте інформацію щодо запитів до Служби підтримки у Ñекреті.
    + + + + + +. p?> + +дошки оголошень Служби підтримки. p?> + + +. + +/support/see_overrides.bml.error.noprivs=Лише кориÑтувачі з привілеÑми supportviewscreened або supporthelp можуть проглÑдати коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ–Ð½ÑˆÐ¸Ñ… кориÑтувачів. + +/support/see_overrides.bml.error.nos1=Цей кориÑтувач не кориÑтуєтьÑÑ S1. + +/support/see_overrides.bml.header2=Коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ [[user]]: + +/support/see_overrides.bml.nooverrides=Ðе знайдено жодних перекриваючіх кодів Ð´Ð»Ñ . + +/support/see_overrides.bml.title=Коди Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/support/submit_do.bml.back2=ПовернутиÑÑ Ð´Ð¾ Ñторінки підтримки. + +/support/submit_do.bml.error.invalidpassword=Ðевірний пароль. + +/support/submit_do.bml.error.invalidusername=Ðевірне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. + +/support/submit_do.bml.text1=Ваш запит підтримки [[sitename]] збережено, Ñ– ви отримаєте відповідь так швидко, Ñк це можливо. Ðомер вашого запиту [[requestid]]. Ви можете відÑтежувати його за поÑиланнÑм: [[link]] + +/support/submit_do.bml.text2=Маєте вільний чаÑ? Бажаєте допомогти іншим кориÑтувачам [[sitename]]? ПереглÑньте ÑпиÑок відкритих запитів у публічних категоріÑÑ… та поділітьÑÑ Ñвоїми знаннÑми про [[sitename]] з іншими. + +/support/submit_do.bml.title=Запит підтримки + +/syn/index.bml.account=Рахунок: + +/syn/index.bml.add=Додати Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/index.bml.add.byurl.text=Додайте Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ вашого ÑпиÑку друзів, зазначивши нижче його адреÑу. + +/syn/index.bml.add.byurl.title=Додати Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð° адреÑою + +/syn/index.bml.add.pop.text=Ðижче наведені деÑкі популÑрні живленнÑ, Ñкі ви наразі не дивитеÑÑ: + +/syn/index.bml.add.pop.title=Додати популÑрне Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/index.bml.add.selected=Додати обране + +/syn/index.bml.back=Ðазад + +/syn/index.bml.create=Створити Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/index.bml.create.name=ÐдреÑа, Ñку ви зазначили, наразі не транÑлюєтьÑÑ Ð½Ð° цьому Ñайті. Введіть, будь лаÑка, ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ потоку. Якщо ви бажаєте змінити адреÑу Ñ–Ñнуюючого потоку, то не Ñтворюйте новий рахунок; адже ви можете змінити адреÑу потоку. + +/syn/index.bml.error.nocreate=ÐдреÑа, Ñку ви зазначили, наразі не транÑлюєтьÑÑ Ð½Ð° цьому Ñайті, але ви можете придбати платний рахунок Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… Ñиндикативних потоків. + +/syn/index.bml.error.unknown=Ðевідома помилка + +/syn/index.bml.feed.url=ÐдреÑа живленнÑ: + +/syn/index.bml.invalid.accountname=Ðевірне ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/syn/index.bml.invalid.cantadd=Ви не можете додати RSS Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð· цього Ñайту. + +/syn/index.bml.invalid.http.text=При отриманні цієї адреÑи трапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Можливо, зараз не працює Ñервер, або недоÑтупний зміÑÑ‚. Перевірте, будь лаÑка, адреÑу, Ñку ви надали, Ñ– Ñпробуйте ще раз. + +/syn/index.bml.invalid.http.title=Помилка при отриманні зміÑту + +/syn/index.bml.invalid.inuse.text=Таке ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ вже викориÑтовуєтьÑÑ. + +/syn/index.bml.invalid.inuse.title=Ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ викориÑтовуєтьÑÑ + +/syn/index.bml.invalid.needname.text=Щоб додати транÑльований рахунок, Ñкий ще не Ñ–Ñнує, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– дайте йому ім'Ñ. + +/syn/index.bml.invalid.needname.title=Ðеобхідно ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/syn/index.bml.invalid.needurl=Ви маєте ввеÑти або ім'Ñ Ñ‚Ñ€Ð°Ð½Ñльованого рахунку, або його адреÑу, щоб додати нове живленнÑ. + +/syn/index.bml.invalid.notexist=Ðе Ñ–Ñнує транÑльованого рахунку з таким ім'Ñм. + +/syn/index.bml.invalid.notrss.text=Зазначена адреÑа не міÑтить даних у форматі XML. + +/syn/index.bml.invalid.notrss.title=Дані не у форматі XML + +/syn/index.bml.invalid.port=ÐеÑтандартні номери портів не дозволені + +/syn/index.bml.invalid.reserved=Це ім'Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ зарезервоване. Оберіть інше ім'Ñ, будь лаÑка. + +/syn/index.bml.invalid.submission=Ðевірно надіÑлано форму. + +/syn/index.bml.invalid.url=ÐдреÑа, Ñку ви надрукували, Ñ” невірною. ПереконайтеÑÑ, будь лаÑка, що ви надрукували адреÑу вірно, Ñ– Ñпробуйте ще раз. + +/syn/index.bml.loginrequired.text=Щоб керувати Ñвоїми Ñиндикативними рахунками, Ñпочатку увійдіть. + +/syn/index.bml.promo.text=Якщо ви бажаєте побачити ÑпиÑок транÑльованих живлень, Ñкі кориÑтувачі рекламували у минулому, то ви можете завітати до , де кориÑтувачі публікують Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ живленнÑ, Ñкі вони Ñтворили Ñ– дивлÑÑ‚ÑŒÑÑ. + +/syn/index.bml.remove=Видалити обране + +/syn/index.bml.table.account=Рахунок + +/syn/index.bml.table.feed=Потік + +/syn/index.bml.table.watchers=ДивлÑÑ‚ÑŒÑÑ + +/syn/index.bml.title=Ð¡Ð¸Ð½Ð´Ð¸ÐºÐ°Ñ†Ñ–Ñ + +/syn/index.bml.top1000.text=ПереглÑнути ÑпиÑок нашу 1000 найпопулÑрніших Ñиндикативних потоків. + +/syn/index.bml.user.nomatch=КориÑтувач, Ñкий публікує, не збігаєтьÑÑ Ð· кориÑтувачем, Ñкий заповнив форму. + +/syn/index.bml.using.text=Тут ви можете додати транÑльовані Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ (RSS) з інших Ñайтів до вашого ÑпиÑку друзів, тим Ñамим позбавлÑючиÑÑŒ необхідноÑÑ‚Ñ– проглÑдати Ñ‰Ð¾Ð´Ð½Ñ Ð´ÐµÑÑтки Ñайтів. + +/syn/index.bml.using.title=ВикориÑÑ‚Ð°Ð½Ð½Ñ [[sitename]] Ð´Ð»Ñ Ñиндикації + +/syn/list.bml.error.nofeeds=Помилка: жодне транÑльоване Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ було оновлено протÑгом оÑтанніх 24 годин. + +/syn/list.bml.feeddesc=ÐžÐ¿Ð¸Ñ Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/list.bml.feedurl=ÐдреÑа Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/list.bml.numreaders=КількіÑÑ‚ÑŒ читачів + +/syn/list.bml.title=ТранÑльовані Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/syn/list.bml.username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +/syn/list.bml.xml_icon.alt=[ДивитиÑÑ Ñире живленнÑ] + +/talkmulti.bml.deleted.body2=Коментарі були видалені. Ви можете подивитиÑÑ Ð³Ñ–Ð»ÐºÑƒ, що залишилаÑÑ, тут. + +/talkmulti.bml.deleted.title=Коментарі видалено + +/talkmulti.bml.error.comms_deleted=Один з коментарів було видалено з того чаÑу, Ñк ви обрали його. По причині безпеки, будь лаÑка, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– Ñпробуйте ще раз. + +/talkmulti.bml.error.inconsistent_data=Ðадані дані Ñ” неÑуміÑними. + +/talkmulti.bml.error.invalid=Зазначено невірні параметри. + +/talkmulti.bml.error.invalid_mode=Ви не обрали жодної дії. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´, будь лаÑка, Ñ– оберіть, чи ви бажаєте приховати, відкрити або видалити коментарі. + +/talkmulti.bml.error.login=Ви не увійшли до журналу. + +/talkmulti.bml.error.none_selected=Ви не обрали жодних коментарів. + +/talkmulti.bml.error.privs.delete=Ви не маєте дозволу видалÑти ці коментарі. + +/talkmulti.bml.error.privs.screen=Ви не маєте дозволу приховувати ці коментарі. + +/talkmulti.bml.error.privs.unscreen=Ви не маєте дозволу відкривати ці коментарі. + +/talkmulti.bml.screened.body2=Коментарі було приховано. Ви можете подивитиÑÑ Ñ—Ñ… тут. + +/talkmulti.bml.screened.title=Коментарі приховано + +/talkmulti.bml.title.delete=Видалити кілька коментарів + +/talkmulti.bml.title.screen=Приховати кілька коментарів + +/talkmulti.bml.title.unscreen=Відкрити кілька коментарів + +/talkmulti.bml.unscreened.body2=Коментарі знову відображаютьÑÑ. Ви можете подивитиÑÑ Ñ—Ñ… тут. + +/talkmulti.bml.unscreened.title=Коментарі відкрито + +/talkpost.bml.allowedhtml=HTML дозволено + +/talkpost.bml.error.cannotreplynopost=Ви не можете відповіÑти на неіÑнуючий запиÑ. + +/talkpost.bml.error.nocommentsjournal=КориÑтувач вимкнув можливіÑÑ‚ÑŒ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñів у його журналі. + +/talkpost.bml.error.nocommentspost=КориÑтувач вимкнув можливіÑÑ‚ÑŒ ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost.bml.error.noreplypost=ПовідомленнÑ, на Ñке Ви відповідаєте, не знайдено (видалено?). + +/talkpost.bml.error.noreply_deleted=Цей коментар було видалено. Ви не можете відповіÑти на нього. + +/talkpost.bml.error.noreply_frozen=Цей коментар заморожений Ñ– на нього не можна відповідати. + +/talkpost.bml.error.noreply_screened=Це прихований коментар Ñ– ви не можете його побачити чи відповіÑти на нього. + +/talkpost.bml.label.picturetouse2=ВикориÑтати юзерпику: + +/talkpost.bml.loganonip=Увага! Цей кориÑтувач увімкнув Ð·Ð°Ð¿Ð¸Ñ IP-Ð°Ð´Ñ€ÐµÑ Ð°Ð½Ð¾Ð½Ñ–Ð¼Ð½Ð¸Ñ… кориÑтувачів. + +/talkpost.bml.loginq=Увійти? + +/talkpost.bml.logyourip=Увага! Цей кориÑтувач увімкнув Ð·Ð°Ð¿Ð¸Ñ IP-адреÑи при надÑиланні повідомленнÑ. + +/talkpost.bml.noaccount=Ðе маєте рахунку? Створіть його зараз. + +/talkpost.bml.nosubjecthtml=HTML не дозволено у темі. + +/talkpost.bml.opt.anonymous=Ðнонімно + +/talkpost.bml.opt.bannedfrom=- Вам заборонено коментувати в цьому журналі. + +/talkpost.bml.opt.defpic=(за замовчуваннÑм) + +/talkpost.bml.opt.friendsonly=- цей кориÑтувач вимкнув ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð½Ð¾Ð½Ñ–Ð¼Ð°Ð¼Ð¸ та не друзÑми. Ви зможете коментувати, Ñкщо [[username]] додаÑÑ‚ÑŒ Ð²Ð°Ñ Ð´Ð¾ друзів. + +/talkpost.bml.opt.from=Від: + +/talkpost.bml.opt.ljuser=КориÑтувач LiveJournal: + +/talkpost.bml.opt.ljuser2=КориÑтувач LiveJournal + +/talkpost.bml.opt.loggedin=КориÑтувач: [[username]] + +/talkpost.bml.opt.message=ПовідомленнÑ: + +/talkpost.bml.opt.noanonpost=- цей кориÑтувач вимкнув анонімне коментуваннÑ. + +/talkpost.bml.opt.noautoformat=Ðе автоформатувати: + +/talkpost.bml.opt.noimage=Ðемає зображень + +/talkpost.bml.opt.preview=Попередньо переглÑнути + +/talkpost.bml.opt.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´ публікуваннÑм (тільки англійÑькою) + +/talkpost.bml.opt.subject=Тема: + +/talkpost.bml.opt.submit=Опублікувати коментар + +/talkpost.bml.opt.willscreen=(буде приховано) + +/talkpost.bml.opt.willscreenfriend=(буде приховано, Ñкщо не в друзÑÑ…) + +/talkpost.bml.paraformat=За замовчуваннÑм абзаци будуть автоматично відформатовані. + +/talkpost.bml.postresponse=Додати коментар: + +/talkpost.bml.title=Опублікувати коментар + +/talkpost.bml.usermismatch<< +Ви ввели Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, але не обрали варіант "КориÑтувач LiveJournal". + +Будь лаÑка, або очиÑÑ‚Ñ–Ñ‚ÑŒ текÑтове поле Ð´Ð»Ñ Ñ–Ð¼ÐµÐ½Ñ– кориÑтувача, або оберіть відповідний режим Ð¿ÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ– Ñпробуйте ще раз. +. + +/talkpost.bml.warnscreened=Увага: Це прихований коментар. Якщо ви на нього відповіÑте, він автоматично Ñтане відкритим Ñ– він Ñтане видими Ð´Ð»Ñ Ð²ÑÑ–Ñ…. + +/talkpost_do.bml.error.badpassword2=Вказано невірний пароль Ð´Ð»Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾Ð³Ð¾ кориÑтувача. Якщо ви забули Ñвій пароль, то можете Ñкинути його за поÑиланнÑм. + +/talkpost_do.bml.error.badusername2=Зазначене Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача не Ñ–Ñнує у [[sitename]]. Якщо ви забули Ñвоє Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, то можете відновити його за поÑиланнÑм або можете пиÑати анонімно. + +/talkpost_do.bml.error.banned=Вам не дозволено пиÑати в цьому журналі. + +/talkpost_do.bml.error.blankmessage=Ваш коментар порожній. Будь лаÑка, напишіть що-небудь у полі повідомленнÑ. + +/talkpost_do.bml.error.confused_identity=Ви ввели ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, але обрали пиÑати анонімно, або від імені кориÑтувача, що вже увійшов у журнал. Будь лаÑка повернітьÑÑ Ð½Ð°Ð·Ð°Ð´ та вирішите що дійÑно ви хочете зробити. + +/talkpost_do.bml.error.deleted=Ваш журнал було видалено. Ви не можете пиÑати повідомленнÑ. + +/talkpost_do.bml.error.friendsonly=Тільки друзі [[user]] можуть пиÑати в цьому журналі. + +/talkpost_do.bml.error.lostcookie=Ваш файл cookie Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ до LiveJournal, здаєтьÑÑ, зник? + +/talkpost_do.bml.error.manybytes=Вибачте, але розмір вашого ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ([[current]]) більше дозволеного розміру ([[limit]]) в байтах. Будь лаÑка повернітьÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкоротіть його та Ñпробуйте ще раз. + +/talkpost_do.bml.error.manychars=Вибачте, але розмір вашого ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ([[current]]) більше дозволеного розміру ([[limit]]) у Ñимволах. Будь лаÑка, повернітьÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкоротіть його та Ñпробуйте ще раз. + +/talkpost_do.bml.error.mustlogin=Ви маєте увійти до журналу викориÑтовуючи ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль щоб коментувати захищений запиÑ. + +/talkpost_do.bml.error.noanon=Ð’ цьому журналі ви не можете пиÑати анонімно. + +/talkpost_do.bml.error.noauth=Вам не дозволено відповідати на цей захищений запиÑ. + +/talkpost_do.bml.error.nocomments=КориÑтувач заборонив ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost_do.bml.error.noparent=Ðе можна віповідати на неіÑнуючі запиÑи. + +/talkpost_do.bml.error.notafriend=Вибачте, але ви не Ñ” другом кориÑтувача [[user]], а він обрав параметр "тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²" Ð´Ð»Ñ Ñ‚Ð¸Ñ…, хто хоче відповіÑти. + +/talkpost_do.bml.error.nousername=Ви не ввели ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. Ви можете напиÑати анонімно, Ñкщо у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” рахунку LiveJournal. + +/talkpost_do.bml.error.noverify=Перепрошуємо, але ви не можете коментувати запиÑи в інших журналах до того, Ñк підтвердите Ñвою адреÑу електронної пошти. Якщо ви загубили лиÑта з підтвердженнÑм, ви можете отримати його знову. + +/talkpost_do.bml.error.noverify2=Вибачте, ви не зможете пиÑати коментарі в журналах інших людей, поки не підтвердите Ñвою email-адреÑу. Якщо ви загубили лиÑÑ‚ підтвердженнÑ, ви можете запроÑити його ще раз. + +/talkpost_do.bml.error.postshared=Ви не можете пиÑати Ñк Ñпільнота. Такі рахунки предÑтавлÑÑŽÑ‚ÑŒ групу людей, а не оÑобиÑÑ‚Ñ–ÑÑ‚ÑŒ. + +/talkpost_do.bml.error.purged=Ваш журнал було видалено та знищено. Ви не можете публікувати запиÑи. + +/talkpost_do.bml.error.screened=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу на ÐºÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу. + +/talkpost_do.bml.error.suspended=Дію вашого журналу припинено. Ви не можете пиÑати повідомленнÑ. + +/talkpost_do.bml.error.testacct=ТеÑтові рахунки можуть викориÑтовуватиÑÑŒ тільки в теÑтових журналах. + +/talkpost_do.bml.opt.preview=Preview + +/talkpost_do.bml.preview=Такий виглÑд матиме ваш коментар, коли його буде опубліковано. ВикориÑтовуючи форму, наведену нижче, ви можете змінити Ñвій коментар далі або ви можете надіÑлати його, Ñк Ñ”. + +/talkpost_do.bml.preview.subject=Тема: + +/talkpost_do.bml.preview.submit=ÐадіÑлати + +/talkpost_do.bml.preview.title=Попередній переглÑд + +/talkpost_do.bml.success.loggedin=Тепер ви ввійшли до журналу. + +/talkpost_do.bml.success.message2=Ваш коментар додано. Ви можете переглÑнути його тут. + +/talkpost_do.bml.success.screened.comm.anon2=Ваш анонімний коментар додано. Через Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти його було приховано. Поки доглÑдачі Ñпільноти його не відкриють, бачити його будуть тільки вони. Ви можете повернутиÑÑ Ð´Ð¾ коментарів. + +/talkpost_do.bml.success.screened.comm2=Ваш коментар додано. Через Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти його було приховано. Поки доглÑдачі Ñпільноти його не відкриють, бачити його будуть тільки вони та ви. Ви можете переглÑнути Ñвій коментар тут. + +/talkpost_do.bml.success.screened.user.anon2=Ваш анонімний коментар додано. Через Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ його було приховано. Поки влаÑник журналу його не відкриє, бачити його буде тільки він. Ви можете повернутиÑÑ Ð´Ð¾ коментарів. + +/talkpost_do.bml.success.screened.user2=Ваш коментар додано. Через Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ його було приховано. Поки влаÑник журналу його не відкриє, бачити його буде тільки він та ви. Ви можете переглÑнути Ñвій коментар тут. + +/talkpost_do.bml.success.title=УÑпішно + +/talkpost_do.bml.success.unscreened=Додатково, прихований коментар, на Ñкий ви відповідаєте вже не Ñ” прихованим. + +/talkpost_do.bml.title=Коментар опублікований + +/talkpost_do.bml.title.error=Коментар не опублікований + +/talkpost_do.bml.title.preview=Попередній переглÑд ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +/talkread.bml.anonuser=(Ðнонімно) + +/talkread.bml.button.more=Більше налаштувань... + +/talkread.bml.button.post=Опублікувати коментар + +/talkread.bml.confirm.action=Ви впевнені, що хочете видалити обрані коментарі? + +/talkread.bml.deletedpost=(Видалений запиÑ) + +/talkread.bml.deleteduser=(Видалений кориÑтувач: [[username]]) + +/talkread.bml.fromip=(з [[ip]]) + +/talkread.bml.noreplies=Ðемає відповідей + +/talkread.bml.nosubject=(без теми) + +/talkread.bml.posted=Коментар уÑпішно опубліковано + +/talkread.bml.qr.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ (тільки англійÑькою) Ñ– попередньо переглÑнути + +/talkread.bml.replysuspended=(Відповідь кориÑтувача з припиненим рахунком) + +/talkread.bml.screenedpost=(Прихований запиÑ) + +/talkread.bml.select=Обрати + +/talkread.bml.subjectdeleted=[видалений] + +/talkread.bml.talkmulti.delete=Видалити + +/talkread.bml.talkmulti.deletespam=Видалити, Ñк Ñпам + +/talkread.bml.talkmulti.des=Групова Ð´Ñ–Ñ Ð½Ð°Ð´ обраними коментарÑми: + +/talkread.bml.talkmulti.screen=Приховати + +/talkread.bml.talkmulti.submit=Виконати дію + +/talkread.bml.talkmulti.unscreen=Відкрити + +/talkread.bml.title=Читати коментарі + +/talkscreen.bml.error.login=Ви маєте увійти до LiveJournal, щоб працювати з прихованими коментарÑми. + +/talkscreen.bml.error.privs.freeze=Ви не маєте дозволу заморожувати цю гілку. + +/talkscreen.bml.error.privs.screen=Ви не маєте дозволу приховати цей коментар. + +/talkscreen.bml.error.privs.unfreeze=Ви не маєте дозволу розморожувати цю гілку. + +/talkscreen.bml.error.privs.unscreen=Ви не маєте дозволу відкрити цей коментар. + +/talkscreen.bml.freeze.doit=Так, заморозити цю гілку. + +/talkscreen.bml.freeze.sure.body=Чи ви впевнені, що бажаєте заморозити цю гілку? Ð’ÑÑ– подальші відповіді до неї чи вÑÑ– коментарі під нею будуть заборонені. + +/talkscreen.bml.freeze.sure.title=Заморозити цю гілку? + +/talkscreen.bml.frozen.body=Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° була заморожена. + +/talkscreen.bml.frozen.title=УÑпішно + +/talkscreen.bml.link=ПовернутиÑÑ Ð´Ð¾ повідомленнÑ. + +/talkscreen.bml.screen.doit=Так, приховати цей коментар + +/talkscreen.bml.screen.sure.body=Чи Ви впевнені, що бажаєте приховати цей коментар? + +/talkscreen.bml.screen.sure.title=Приховати цей коментар? + +/talkscreen.bml.screened.body=Коментар було приховано. Ви можете переглÑнути його тут. + +/talkscreen.bml.screened.title=УÑпішно + +/talkscreen.bml.title2=Змінити Ñтан ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +/talkscreen.bml.unfreeze.doit=Так, розморозити цю гілку. + +/talkscreen.bml.unfreeze.sure.body=Чи Ви впевнені, що бажаєте розморозити цю гілку? + +/talkscreen.bml.unfreeze.sure.title=Розморозити цю гілку? + +/talkscreen.bml.unfrozen.body=Гілка була розморжена. + +/talkscreen.bml.unfrozen.title=УÑпішно + +/talkscreen.bml.unscreen.doit=Так, відкрити цей коментар + +/talkscreen.bml.unscreen.sure.body=Чи Ви впевнені, що бажаєте відкрити цей коментар? + +/talkscreen.bml.unscreen.sure.title=Відкрити цей коментар? + +/talkscreen.bml.unscreened.body=Коментар був відкритий. Ви можете переглÑнути його тут. + +/talkscreen.bml.unscreened.title=УÑпішно + +/tools/emailmanage.bml.address.current.title=Поточна адреÑа + +/tools/emailmanage.bml.address.old.none=Ðемає + +/tools/emailmanage.bml.address.old.text=Це ÑпиÑок e-mail адреÑ, що викориÑтовувалиÑÑ Ð· вашим рахунком, Ñ– чаÑу, коли вони були вимкнені Ñк оÑновні e-mail адреÑи. Відзначте Ñ‚Ñ–, що ви бажаєте видалити. + +/tools/emailmanage.bml.address.old.title=Попередні адреÑи + +/tools/emailmanage.bml.delete_selected=Обрано Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ + +/tools/emailmanage.bml.desc.notfirst=Ð¦Ñ Ñторінка дозволÑÑ” вам вилучити лише Ñ‚Ñ– e-mail адреÑи, Ñкі були викориÑтані піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви в перший раз ÑкориÑталиÑÑ Ñ‚Ñ–Ñ”ÑŽ адреÑою, що наразі перевірена. Зокрема, це значить, що нападник не в змозі вилучити вашу первинну e-mail адреÑу. + +/tools/emailmanage.bml.desc.text=Ð¦Ñ Ñторінка дозволÑÑ” вам вилучити минулі e-mail адреÑи, що викориÑтовувалиÑÑ Ð· вашим рахунком. Якщо ви вилучите e-mail адреÑу, то більше вже не буде можливо надіÑлати ваш пароль до цієї адреÑи. Це кориÑно, Ñкщо хтоÑÑŒ викрив ваш пароль та захопив ваш журнал. ПроÑто надішліть новий пароль до вашої Ñтарої адреÑи, зміните пароль та вилучіть e-mail адреÑу нападника. + +/tools/emailmanage.bml.desc.title=ÐžÐ¿Ð¸Ñ + +/tools/emailmanage.bml.log.deleted=Видалено: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Зміни збережено + +/tools/emailmanage.bml.notvalidated.text=Щоб кориÑтуватиÑÑ Ñ†Ð¸Ð¼ інÑтрументом, ви маєте підтвердити адреÑу Ñвоєї електронної пошти, [[email]]. Якщо лиÑта з підтвердженнÑм втрачено, ви можете отримати його знову. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ - повертайÑÑ Ð´Ð¾ цієї Ñторінки. + +/tools/emailmanage.bml.notvalidated.text2=Щоб ÑкориÑтатиÑÑ Ñ†Ð¸Ð¼ інÑтрументом, ваша поточна email-адреÑа ([[email]]) повинна бути підтверджена. Якщо ви загубили лиÑÑ‚ підтвердженнÑ, ви можете запроÑити його ще раз. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð°Ð´Ñ€ÐµÑи, повертайтеÑÑ Ñюди. + +/tools/emailmanage.bml.notvalidated.title=E-mail адреÑу не перевірено + +/tools/emailmanage.bml.title=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ e-mail адреÑами + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body2=Ваш ÑпиÑок Ñпогадів було оновлено. Ви можете повернутиÑÑ Ð´Ð¾ запиÑу, Ñкий ви щойно додали. + +/tools/memadd.bml.body.added.header=УÑпішно + +/tools/memadd.bml.description=ОпиÑ: + +/tools/memadd.bml.description.text=Дайте Ð¾Ð¿Ð¸Ñ Ñ†ÑŒÐ¾Ð¼Ñƒ запиÑу, за Ñким Ви зможете його запам'Ñтати. Ð”Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиÑу зі ÑпиÑку Ñпогадів, введіть порожній опиÑ. + +/tools/memadd.bml.edit_previous<< + + +. + +/tools/memadd.bml.error.deleted.body=ЗапиÑ, Ñкий раніше мав Ð¾Ð¿Ð¸Ñ "[[desc]]", було вилучено із вашого ÑпиÑку Ñпогадів. + +/tools/memadd.bml.error.deleted.title=Вибраний Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¾ + +/tools/memadd.bml.error.entry_deleted=Такого запиÑу більше не Ñ–Ñнує. Його видалено з вибраного. + +/tools/memadd.bml.error.fivekeywords=ДозволÑєтьÑÑ Ð²ÐºÐ°Ð·Ð°Ñ‚Ð¸ тільки 5 ключових Ñлів/категорій Ð´Ð»Ñ Ñпогаду. + +/tools/memadd.bml.error.invalid_security=Ðевірно вказаний або відÑутній рівень безпеки. + +/tools/memadd.bml.error.login=Ви повинні увійти щоб ÑкориÑтатиÑÑ Ñ†Ñ–Ñ”ÑŽ можливіÑÑ‚ÑŽ. Увійдіть, піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви повернетеÑÑ Ñюди. + +/tools/memadd.bml.error.maxsize=Це ключове Ñлово перевищує макÑимально можливий розмір: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body=Щоб додати цей Ð·Ð°Ð¿Ð¸Ñ Ñƒ вибране, вам потрібно коротко його опиÑати. Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб видалити Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· вибраного, ви можете змінити та видалити опиÑ, однак цього запиÑу у вибраному ще немає. + +/tools/memadd.bml.error.nodescription.title=Без опиÑу + +/tools/memadd.bml.form.reset=ОчиÑтити + +/tools/memadd.bml.form.submit=Додати + +/tools/memadd.bml.keywords=Ключові Ñлова: + +/tools/memadd.bml.keywords.example=Приклад: Ñмішне, комп'ютерне, романтичне + +/tools/memadd.bml.keywords.select=Ðбо виберіть із ключових Ñлів, що було викориÑтано раніше: + +/tools/memadd.bml.keywords.text=Чому Ви додаєте цей Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ Ñпогадів? Уведіть не більше п'Ñти ключових Ñлів або категорій, відокремлених комами. + +/tools/memadd.bml.login.enterinfo=Уведіть Ñ–Ð¼â€™Ñ + +/tools/memadd.bml.multiple_selections=Щоб обрати кілька Ñлів, натиÑніть та утримуйте 'Control' (Ctrl) на клавіатурі, поки натиÑкаєте мишою. + +/tools/memadd.bml.security=Рівень безпеки: + +/tools/memadd.bml.security.friendsonly=Тільки друзі + +/tools/memadd.bml.security.private=Тільки Ñ + +/tools/memadd.bml.security.public=УÑÑ– + +/tools/memadd.bml.title=Додати у вибране + +/tools/memadd.bml.title.added=Додано + +/tools/memadd.bml.title.add_memory=Додати вибраний Ð·Ð°Ð¿Ð¸Ñ + +/tools/memadd.bml.title.deleted=Видалено + +/tools/memadd.bml.title.edit_memory=Змінити вибраний Ð·Ð°Ð¿Ð¸Ñ + +/tools/memadd.bml.whocansee<< +Хто може бачити, що ви додали цей Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ Ñпогадів? +УÑÑ–, тільки ваші друзі чи тільки ви? +. + +/tools/memadd.bml.whocansee.comm<< +Хто може бачити, що Ви помітили цей Ð·Ð°Ð¿Ð¸Ñ Ñк Ñпогад? +Ð’ÑÑ–, тільки учаÑники Ñпільноти або тільки наглÑдачі Ñпільноти? +. + +/tools/memories.bml.back=Ðазад + +/tools/memories.bml.body.keyword<< + +[[user]] на тему "[[keyword]]". p?> + +. + +/tools/memories.bml.body.list_categories<< + +[[user]] додав вибрані запиÑи. p?> + +. + +/tools/memories.bml.body.memorable=Ðижче наведено ÑпиÑок Ñпогадів кориÑтувача [[user]], що не потрапили до жодної категорії. + +/tools/memories.bml.delete=Видалити обрані + +/tools/memories.bml.delete.confirm=Ви намагаєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ один чи кілька вибраних запиÑів. Ви впевнені, що хочете цього? + +/tools/memories.bml.delete.deleted.head=УÑпішно + +/tools/memories.bml.delete.deleted.text=Обрані запиÑи були видалені. Ви можете повернутиÑÑ Ð´Ð¾ a [[aopts]]>вибраного. + +/tools/memories.bml.delete.deleted.title=Вибрані запиÑи видалено + +/tools/memories.bml.delete.error.dberror=Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¸Ñ… запиÑів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° бази даних. Помилка: [[error]]. Спробуйте ще раз, будь лаÑка. + +/tools/memories.bml.delete.error.noneselected=Ви не обрали запиÑи, Ñкі хочете видалити. + +/tools/memories.bml.edit=змінити + +/tools/memories.bml.error.noentries.body<< +Це могло ÑтатиÑÑ Ñ‚Ð¾Ð¼Ñƒ, що:
      +
    1. кориÑтувач не має вибраних запиÑів;
    2. +
    3. вибрані запиÑи кориÑтувача захищені й ви не маєте доÑтупу до них, або
    4. +
    5. кориÑтувач не має вибраних запиÑів, Ñкі відповідають критеріÑм вашого пошуку.
    + +. + +/tools/memories.bml.error.noentries.title=Жодних вибраних запиÑів. + +/tools/memories.bml.filter.all=УÑÑ– вибрані запиÑи + +/tools/memories.bml.filter.other=Тільки інші запиÑи + +/tools/memories.bml.filter.own=Тільки запиÑи кориÑтувача '[[user]]' + +/tools/memories.bml.form.filter=Які запиÑи відображати: + +/tools/memories.bml.form.sort=Сортувати запиÑи за: + +/tools/memories.bml.form.switch=Змінити + +/tools/memories.bml.login=Щоб дивитиÑÑ Ñвої вибрані запиÑи, будь лаÑка, увійдіть до LiveJournal. + +/tools/memories.bml.plur_entry=[[num]] [[?num|запиÑ|запиÑи|запиÑів]] + +/tools/memories.bml.sort.description=опиÑом + +/tools/memories.bml.sort.journal=журналом + +/tools/memories.bml.sort.orderadded=порÑдком Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ + +/tools/memories.bml.title.keyword=Вибране на тему "[[keyword]]" + +/tools/memories.bml.title.memorable=Вибрані запиÑи + +/tools/memories.bml.uncategorized=Без категорії + +/tools/recent_comments.bml.managesettings=Керувати налаштуваннÑми коментарів + +/tools/recent_comments.bml.maxnotshown=Зробіть Ñвій рахунок платним, щоб бачити [[max]] оÑтанніх коментарів заміÑÑ‚ÑŒ [[current]]. + +/tools/textmessage.bml.enter.user.head=Введіть кориÑтувача + +/tools/textmessage.bml.enter.user.input=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/tools/textmessage.bml.enter.user.submit=Продовжити... + +/tools/textmessage.bml.enter.user.text=ПідтримуютьÑÑ Ð½Ð°Ñтупні поÑтачальники поÑлуги текÑтових повідомлень. + +/tools/textmessage.bml.enter.user.text2=Введіть Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача LiveJournal, Ñкому бажаєте відіÑлати текÑтове повідомленнÑ: + +/tools/textmessage.bml.error.notloggedin.head=Ðе увійшли + +/tools/textmessage.bml.error.notloggedin.notfriend=Ñ– бути у ÑпиÑку його друзів + +/tools/textmessage.bml.error.notloggedin.text=Щоб відіÑлати текÑтове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð¼Ñƒ кориÑтувачу, ви маєте увійти [[andbefriend]]. + +/tools/textmessage.bml.error.unauthorized.head=Ðедозволено + +/tools/textmessage.bml.error.unauthorized.text=КориÑтувач [[user]] дозволив надÑилати текÑтові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ñвоїм друзÑм. + +/tools/textmessage.bml.error.unavailable.head=ВідÑутній + +/tools/textmessage.bml.error.unavailable.notfound=Ðеможливо знайти [[user]]. + +/tools/textmessage.bml.error.unavailable.notpermitted=Тип рахунку кориÑтувача не підтримує текÑтові повідомленнÑ. + +/tools/textmessage.bml.error.unavailable.notsetup=Цей кориÑтувач не надав дані Ð´Ð»Ñ Ñ‚ÐµÐºÑтових повідомлень у [[sitenameshort]] або вимкнув Ñ—Ñ…. + +/tools/textmessage.bml.footer.disclaimer.text=ЗаÑтереженнÑ: Ðе Ñлід покладатиÑÑ Ð½Ð° Ñлужбу текÑтових повідомлень у випадках, пов’Ñзаних з безпекою людей. + +/tools/textmessage.bml.footer.howwork.text=Як працює Ñ†Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ? Прочитайте це. + +/tools/textmessage.bml.form.head=ВідіÑлати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/tools/textmessage.bml.form.message.from=Від: + +/tools/textmessage.bml.form.message.input=ПовідомленнÑ: + +/tools/textmessage.bml.form.message.note=(max [[maxlen]] Ñимволів ... набирайте поки Ð²Ð°Ñ Ð½Ðµ зупинÑÑ‚ÑŒ) + +/tools/textmessage.bml.form.message.submit=ВідіÑлати повідомленнÑ! + +/tools/textmessage.bml.form.text=Заповніть цю форму Ð´Ð»Ñ Ð²Ñ–Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÑтового Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ [[user]]. + +/tools/textmessage.bml.providers.from=від: + +/tools/textmessage.bml.providers.head=ПоÑтачальники поÑлуг + +/tools/textmessage.bml.providers.msg=повідомл: + +/tools/textmessage.bml.providers.text=ПідтримуютьÑÑ Ð½Ð°Ñтупні поÑтачальники поÑлуги текÑтових повідомлень. + +/tools/textmessage.bml.providers.total=уÑього: + +/tools/textmessage.bml.setup.text=Ð’Ñтановіть або змініть Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñвоїх текÑтових повідомлень. + +/tools/textmessage.bml.success.head=УÑпішно + +/tools/textmessage.bml.success.text=Ваше текÑтове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñ–Ñлано. + +/translate/index.bml.table.code=Код + +/translate/index.bml.table.done=Виконано, % + +/translate/index.bml.table.langname=Мова + +/translate/index.bml.table.lastupdate=ОÑтаннє Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/translate/index.bml.text=LiveJournal підтримує багато мов, а Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¿ÐµÑ€ÐµÐºÐ»Ð°Ð´Ñƒ Ñайту на ці мови здійÑнюєтьÑÑ Ð¿ÐµÑ€ÐµÐºÐ»Ð°Ð´Ð°Ñ‡Ð°Ð¼Ð¸-волонтерами. У цій таблиці вказано, Ñкільки перекладено кожною з команд. + +/translate/index.bml.title=Зона перекладу + +/translate/teams.bml.table.community=Спільнота + +/translate/teams.bml.table.language=Мова + +/translate/teams.bml.table.users=КориÑтувачі з привілеÑми + +/translate/teams.bml.teams.header=Команди + +/translate/teams.bml.teams.text=Переклад здійÑнюють перелічені нижче команди. Якщо ви зацікавлені в приєдананні до однієї з них, ознайомтеÑÑ Ð· даними відповідної Ñпільноти. Кожна команда працює окремо, залежно від Ñвого координатора, але вÑÑ– вони відкриті Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… волонтерів. + +/translate/teams.bml.title=Команди перекладачів + +/update.bml.altpost=Додати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ журналу: + +/update.bml.auth.poster=Відправник: + +/update.bml.btn.preview=Попередньо переглÑнути + +/update.bml.btn.update=Оновити журнал + +/update.bml.currmusic=Зараз грає: + +/update.bml.date=Дата: + +/update.bml.default=за замовчуваннÑм + +/update.bml.defaultjournal=([[user]]) - за замовчуваннÑм + +/update.bml.draft.autosave=Чернетку було автоматично збережено о [[time]] + +/update.bml.draft.confirm=Відновити збережену чернетку? + +/update.bml.draft.restored=Відновлено збережену чернетку + +/update.bml.error.cantpost=Вибачте, ви наразі не можете публікувати. + +/update.bml.error.cantpost.title=Ðеможливо надіÑлати + +/update.bml.error.disabled=Ваш тип рахунку не дозволÑÑ” публікувати. + +/update.bml.error.disabled.title=ДоÑтуп до Ð¿ÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾ + +/update.bml.error.login=Помилка входу до журналу: + +/update.bml.error.noentry=Ð—Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати зміÑÑ‚. + +/update.bml.error.nonusercantpost=КориÑтувачі з інших Ñайтів не можуть Ñтворювати запиÑи, оÑкільки не мають тут журналів. Хоча, ви можете залишати коментарі в інших журналах. + +/update.bml.error.nopass=Введіть пароль + +/update.bml.error.update=Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ: + +/update.bml.event=ТекÑÑ‚ запиÑу: + +/update.bml.full=Повна Ñторінка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +/update.bml.htmlokay.norich=(HTML дозволено; за замовчуваннÑм нові Ñ€Ñдки будуть автовідфоматовані на <br />.) + +/update.bml.htmlokay.rich=(HTML дозволено; за замовчуваннÑм нові Ñ€Ñдки будуть автовідфоматовані на <br> або ÑкориÑтуйтеÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼ редактором.) + +/update.bml.htmlokay.rte_nosupport=(Вибачте, ваш браузер наразі не підтримує Ñередовище форматованого текÑту.) + +/update.bml.localtime=МіÑцевий чаÑ: + +/update.bml.loggedinas2=Ви увійшли Ñк [[user]].
    Щоб пиÑати від імені іншого кориÑтувача, натиÑніть Ñюди. + +/update.bml.loggingin=Входжу до журналу... + +/update.bml.noneother=Ðемає, або інший: + +/update.bml.note=Увага: Ñ‡Ð°Ñ Ñ‚Ð° дата взÑÑ‚Ñ– з нашого Ñервера. Змініть Ñ—Ñ… відноÑно Ñвоєї чаÑової зони перед напиÑаннÑм. + +/update.bml.opt.backdate=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом: + +/update.bml.opt.backdate.about=не з’ÑвитьÑÑ Ð½Ð° Ñторінці друзів + +/update.bml.opt.defpic=(за замовчуваннÑм) + +/update.bml.opt.nocomments=Заборонити коментарі: + +/update.bml.opt.noemail=Ðе виÑилати коментарі на email: + +/update.bml.opt.noformat=Ðе автоформатувати: + +/update.bml.opt.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ (тільки англійÑькою) + +/update.bml.options=Додаткові параметри + +/update.bml.other=Інший: + +/update.bml.password=Пароль: + +/update.bml.preview.header=Попередній переглÑд + +/update.bml.preview.text=Так виглÑдатиме запиÑ, коли його буде опубліковано. ВикориÑтовуючи форму, наведену нижче, ви можете змінювати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð°Ð»Ñ– або ви можете надіÑлати його таким, Ñк Ñ”. + +/update.bml.rowarn=Увага: ваш рахунок наразі знаходитьÑÑ Ñƒ [[a_open]]режимі тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ[[a_close]]. Через профілактичні роботи ви зараз можете бути не в змозі пиÑати до вашого журналу. + +/update.bml.security.custom=ОÑобливий... + +/update.bml.security.friends=Тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/update.bml.security.head=Рівень безпеки: + +/update.bml.security.private=Приватний + +/update.bml.security.public=Публічний + +/update.bml.servermsg=Ðа Ñервері Ñ” Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ð°Ñ: + +/update.bml.spellchecked=Ваш Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· перевіреним правопиÑом: + +/update.bml.subject=Тема: (необов’Ñзково) + +/update.bml.success.links=Тепер, піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾ Ñк ви опублікували запиÑ, ви можете: + +/update.bml.success.links.edit=Змінити Ð·Ð°Ð¿Ð¸Ñ + +/update.bml.success.links.memories=Додати Ð·Ð°Ð¿Ð¸Ñ Ñƒ вибране + +/update.bml.success.links.tags=Змінити теґи цього запиÑу + +/update.bml.success.links.view=ПереглÑнути Ð·Ð°Ð¿Ð¸Ñ + +/update.bml.timeformat=24-годинний Ñ‡Ð°Ñ + +/update.bml.title=Оновити журнал + +/update.bml.title.readonly=Режим тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + +/update.bml.update.alternate=Ви можете кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою Ð´Ð»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñвого LiveJournal, Ñкщо не хочете завантажувати клієнтÑьку програму на Ñвій комп’ютер, або Ñкщо такої не Ñ–Ñнує Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾. Ð¦Ñ Ñторінка також Ñтане у нагоді коли ви відпочиваєте чи перебуваєте далеко від Ñвого оÑновного комп’ютера. Якщо ви маєте платний рахунок, то також можете оновлювати журнал через email, запиÑувати голоÑові Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° Ñтворювати Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ Ñвоїх запиÑах. + +/update.bml.update.head=Оновити ваш журнал... + +/update.bml.update.success=Оновлено! Ви можете переглÑнути Ñвій оновлений журнал тут. + +/update.bml.update.success2=Оновлено. Ви можете переглÑнути Ñвій оновлений журнал тут. + +/update.bml.updating=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ... + +/update.bml.username=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +/uploadpic.bml.error.unsupportedtype=Файли типу [[filetype]] не підтримуютьÑÑ. Ви можете завантажувати лише файли GIF, PNG або JPG. Майже вÑÑ– програми Ð´Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ із зображеннÑми/фотографіÑми можуть зробити Ð´Ð»Ñ Ð²Ð°Ñ Ñ‚Ð°ÐºÐµ перетвореннÑ. + +/userinfo.bml.about.comm=Про Ñпільноту: + +/userinfo.bml.about.user=Про Ñебе: + +/userinfo.bml.allpics=Ð’ÑÑ– юзерпики + +/userinfo.bml.body.leave2=Ви можете покинути цю Ñпільноту в будь-Ñкий момент. + +/userinfo.bml.comminfo.body=Ðижче наведено дані Ñпільноти "[[commname]]". + +/userinfo.bml.comminfo.name=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñпільноти + +/userinfo.bml.date.never=Ðіколи. + +/userinfo.bml.error.malfname=Погане ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: занадто довге або міÑтить неприпуÑтимі Ñимволи. + +/userinfo.bml.error.notloggedin=Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду влаÑного профілю кориÑтувача, вам потрібно увійти. + +/userinfo.bml.fbpictures.lessthan=менш ніж [[count]] публічних + +/userinfo.bml.fbpictures.over=більш ніж [[count]] публічних + +/userinfo.bml.friendof.comm=ДивлÑÑ‚ÑŒÑÑ: + +/userinfo.bml.friendof.hidden=(приховано) + +/userinfo.bml.friendof.syndreadcount=КількіÑÑ‚ÑŒ читачів + +/userinfo.bml.friendof.user=У друзÑÑ…: + +/userinfo.bml.friends.comm=УчаÑники + +/userinfo.bml.friends.user=Друзі + +/userinfo.bml.label.addbuddy=Додати друга + +/userinfo.bml.label.adduser=Додати кориÑтувача + +/userinfo.bml.label.alsofriendof=Також у друзÑÑ…: + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=День народженнÑ: + +/userinfo.bml.label.clientsused2=ВикориÑтані програми: + +/userinfo.bml.label.comments=Коментарі: + +/userinfo.bml.label.composted=Залишено: [[num]] - + +/userinfo.bml.label.comreceived=Отримано: [[num]] + +/userinfo.bml.label.datecreated=Дата ÑтвореннÑ: + +/userinfo.bml.label.dateupdated=Дата оновленнÑ: + +/userinfo.bml.label.email=Електронна пошта: + +/userinfo.bml.label.fbpictures=ЗображеннÑ: + +/userinfo.bml.label.frcommunity=Спільноти: + +/userinfo.bml.label.frpeople=Люди + +/userinfo.bml.label.frsyndication2=Ð–Ð¸Ð²Ð»ÐµÐ½Ð½Ñ + +/userinfo.bml.label.gizmo=Проект "Gizmo": + +/userinfo.bml.label.icquin=Ðомер ICQ: + +/userinfo.bml.label.interests=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +/userinfo.bml.label.interests.modifyyours=Змінити Ð²Ð°ÑˆÑ– + +/userinfo.bml.label.interests.removesome=Видалити + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] інтереÑів не показано + +/userinfo.bml.label.journalentrs=ЗапиÑів у журналі: + +/userinfo.bml.label.location=МіÑцезнаходженнÑ: + +/userinfo.bml.label.maintainers=ДоглÑдачі + +/userinfo.bml.label.manageschools=Редагувати навчальні заклади + +/userinfo.bml.label.memberof=УчаÑник + +/userinfo.bml.label.memories=Вибране: + +/userinfo.bml.label.moderators=Модератори + +/userinfo.bml.label.moredetails=(детальніше...) + +/userinfo.bml.label.msnusername=MSN ім'Ñ: + +/userinfo.bml.label.mutual=Взаємні друзі: + +/userinfo.bml.label.name=Ім'Ñ: + +/userinfo.bml.label.nofriends=Ðемає. + +/userinfo.bml.label.noschools=Ðе вказано + +/userinfo.bml.label.post=ÐапиÑати до "[[journal]]" + +/userinfo.bml.label.postalt=Поновити ваш журнал + +/userinfo.bml.label.reqfinduser=Тільки кориÑтувачі з привілеєю 'finduser' можуть шукати кориÑтувачів за Ñ—Ñ… кодом. + +/userinfo.bml.label.schools=Ðавчальні заклади + +/userinfo.bml.label.searchjournal=Шукати по цьому журналу + +/userinfo.bml.label.sendmessage=ÐадіÑлати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +/userinfo.bml.label.shared=Дозвіл пиÑати: + +/userinfo.bml.label.supportpoints=Бали підтримки + +/userinfo.bml.label.syndicatedfrom=ТранÑльовано з: + +/userinfo.bml.label.syndicatedstatus=Стан транÑлÑції: + +/userinfo.bml.label.textmessage=ТекÑтове
    повідомленнÑ
    : + +/userinfo.bml.label.todo=Ðотатник + +/userinfo.bml.label.user=КориÑтувач: + +/userinfo.bml.label.userprofile=Дані кориÑтувача + +/userinfo.bml.label.viewfriends=ДивитиÑÑ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +/userinfo.bml.label.viewmembers=ДивитиÑÑ ÑƒÑ‡Ð°Ñників + +/userinfo.bml.label.website=ВебÑайт: + +/userinfo.bml.label.yahooid=Yahoo! ID: + +/userinfo.bml.membership.body2=Щоб приєднатиÑÑ Ð´Ð¾ цієї Ñпільноти, натиÑніть Ñюди. + +/userinfo.bml.membership.paidmembers2=ПіÑÐ»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ платного рахунку, ви можете приєднатиÑÑ Ð´Ð¾ Ñпільноти paidmembers. + +/userinfo.bml.memories.entries=[[count]] запиÑів + +/userinfo.bml.memories.entry=[[count]] Ð·Ð°Ð¿Ð¸Ñ + +/userinfo.bml.monitor.comm=Додати до друзів + +/userinfo.bml.monitor.comm2=СпоÑтерігати за Ñпільнотою + +/userinfo.bml.monitor.user=Додати цього кориÑтувача до вашого ÑпиÑку друзів + +/userinfo.bml.nonexist.body=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача [[user]] наразі не зареєÑтровано. + +/userinfo.bml.nonexist.name=Ðевідомий кориÑтувач + +/userinfo.bml.sendmessage.body2=ÐадіÑлати [[user]] текÑтове повідомленнÑ
    на його (Ñ—Ñ—) мобільний. + +/userinfo.bml.syn.last.never=Ðіколи + +/userinfo.bml.syn.lastcheck=ВоÑтаннє перевірено: + +/userinfo.bml.syn.nextcheck=ÐаÑтупна перевірка: + +/userinfo.bml.syn.parseerror=Помилка: + +/userinfo.bml.syndinfo.body2=Якщо ви бажаєте читати Ñтатті з Ñиндикативного Ñайту у Ñвоїй Ñтрічці друзів, можете додати цей журнал до Ñвого ÑпиÑку друзів. + +/userinfo.bml.syndinfo.name=Журнал Ñиндикації + +/userinfo.bml.tellafriend=Скажи другові! + +/userinfo.bml.timeupdate.dayago=1 день тому + +/userinfo.bml.timeupdate.daysago=[[num]] дні(в) тому + +/userinfo.bml.timeupdate.hourago=1 годину тому + +/userinfo.bml.timeupdate.hoursago=[[num]] годин(и) тому + +/userinfo.bml.timeupdate.minuteago=1 хвилину тому + +/userinfo.bml.timeupdate.minutesago=[[num]] хвилин(и) тому + +/userinfo.bml.timeupdate.secondago=1 Ñукунду тому + +/userinfo.bml.timeupdate.secondsago=[[num]] Ñекунд(и) + +/userinfo.bml.timeupdate.weekago=1 тиждень тому + +/userinfo.bml.timeupdate.weeksago=[[num]] тижні(в) тому + +/userinfo.bml.title=Профіль + +/userinfo.bml.title.communityinfo=Дані Ñпільноти + +/userinfo.bml.title.syndicated=Синдикативний рахунок + +/userinfo.bml.title1=Профіль + +/userinfo.bml.userinfo.body2=Ðижче наведено дані кориÑтувача [[username]]. Якщо це ви, то можете змінити Ñвої дані (або визначити, Ñка Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð²Ð²Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¾ÑŽ) на Ñторінці зміни профілю. + +/userinfo.bml.userinfo.body3=Ви можете змінити інформацію про Ñебе (чи визначити, Ñка Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ” загальнодоÑтупною) на Ñторінці "Змінити перÑональну інформацію". + +/userinfo.bml.userinfo.name=Профіль + +/userinfo.bml.userpic.none=немає юзерпики за замовчуваннÑм + +/voicepost/index.bml.didyouknow.head=Чи знаєте ви? + +/voicepost/index.bml.didyouknow.replace=замініть '[[username]]' Ñвоїм іменем кориÑтувача + +/voicepost/index.bml.didyouknow.text=[[sitename]] автоматично Ñтворює RSS-потік, Ñкий підтримує подкаÑтінг ваших голоÑових запиÑів. Щоб кориÑтуватиÑÑ Ð¿Ð¾Ñ‚Ð¾ÐºÐ¾Ð¼, введіть таку адреÑу - [[aopts2]] + +/voicepost/index.bml.error.upgrade=Покращіть ваш рахунок, щоб кориÑтуватиÑÑ Ð³Ð¾Ð»Ð¾Ñовими запиÑами + +/voicepost/index.bml.info.text2=КориÑтуючиÑÑŒ голоÑовими запиÑами, ви можете зателефонувати на один з наших номерів та залишити Ñвоє повідомленнÑ, Ñке одразу з’ÑвитьÑÑ Ñƒ вашому журналі. ГолоÑові запиÑи доÑтупні лише кориÑтувачам розширених та платних рахунків. + +/voicepost/index.bml.info.text3=МожливіÑÑ‚ÑŒ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових запиÑів доÑтупна лише влаÑникам розширених та платних рахунків. Ви можете зателефонувати на один зі Ñпеціальних номерів та запиÑати голоÑовий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ñто у Ñвій журнал. Також ви можете Ñтворити Ñкачавши Gizmo Project Ð´Ð»Ñ LJ Talk. + +/voicepost/index.bml.links.encoding.text=Ми підтримуємо різні аудіоформати ваших запиÑів + +/voicepost/index.bml.links.encoding.title2=ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÑƒÐ´Ñ–Ð¾ + +/voicepost/index.bml.links.filemanager.text=Керуйте Ñвоїм диÑковим проÑтором та голоÑовими запиÑами + +/voicepost/index.bml.links.filemanager.title2=Менеджер файлів + +/voicepost/index.bml.links.head=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +/voicepost/index.bml.links.manage.text=Керуйте авторизованим номером телефону та ідентифікаційним номером ваших голоÑових запиÑів + +/voicepost/index.bml.post.head=Ð—Ð°Ð¿Ð¸Ñ + +/voicepost/index.bml.post.text5<< +
  • Зателефонуйте на один з наших номерів Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень.
  • +
  • Запишіть Ñвоє повідомленнÑ. +

    КеруйтеÑÑ Ð³Ð¾Ð»Ð¾Ñовими інÑтрукціÑми, щоб зробити Ñвій запиÑ. Ð’Ð°Ñ Ð¿Ð¾Ð¿Ñ€Ð¾ÑÑÑ‚ÑŒ: +
      +
    • ВвеÑти ваш авторизований номер телефону.
    • +
    • ВвеÑти ваш ПІÐ.
    • +
    • ЗапиÑати ваше повідомленнÑ.
    • +
    • Обрати, хтоможе Ñлухати ваше повідомленнÑ. (УÑÑ–, лише друзі, група друзів Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… голоÑових повідомлень чи лише ви).
    • +
    +Коли ви закінчете ваш дзвінок, наша ÑиÑтема зробить аудіо-файл та опублікує його до вашого журналу в новому запиÑÑ–.
  • +. + +/voicepost/index.bml.setup.head=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +/voicepost/index.bml.setup.text=Спершу введіть Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ð¾Ñових запиÑів, включаючи авторизований телефонний номер та ПІÐ, а потім оберіть Ð½Ð°Ð»Ð°ÑˆÑƒÑ‚Ð²Ð°Ð½Ð½Ñ Ð¿ÑƒÐ±Ð»Ñ–ÐºÐ°Ñ†Ñ–Ð¹. + +/voicepost/index.bml.status.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ + +/voicepost/index.bml.status.storage.head=ПроÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ: + +/voicepost/index.bml.status.storage.text=Ðаразі викориÑтано [[diskusage]] Мб з [[diskmax]] Мб + +/voicepost/index.bml.status.voiceposts.head=ГолоÑові запиÑи: + +/voicepost/index.bml.status.voiceposts.text=У цьому міÑÑці ви зробили [[phoneusage]] запиÑів з [[phonemax]] дозволених. + +/voicepost/index.bml.transcribe.head=Розшифровка + +/voicepost/index.bml.transcribe.text=ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк Ð·Ð°Ð¿Ð¸Ñ Ð·â€™ÑвитьÑÑ Ñƒ вашому журналі, його можно розшифрувати, щоб уÑÑ– могли його ще й прочитати. Ви можете дозволити розшифровку уÑім вашим друзÑм, певній групі друзів чи лише Ñобі. + +/voicepost/numbers.bml.error.upgrade=Ваш рахунок не дозволÑÑ” кориÑтуватиÑÑ Ð³Ð¾Ð»Ð¾Ñовими запиÑами, тому відображаютьÑÑ Ð»Ð¸ÑˆÐµ коди та міÑта. Якщо ви хочете робити запиÑи за допомогою телефону, переглÑньте інформацію про платні рахунки. + +/voicepost/numbers.bml.list.caution.head=ЗаÑтереженнÑ: + +/voicepost/numbers.bml.list.caution.text=ДеÑкі телефонні компанії ÑÑ‚Ñгують оплату за локальні дзвінки, Ñкі не входÑÑ‚ÑŒ до вашого тарифного плану.

    Якщо ви не певні, що номери Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñових повідомлень входÑÑ‚ÑŒ до вашого тарифного плану, зателефонуйте до Ñвоєї телефонної компанії.

    Ви відповідаєте за Ñплату уÑÑ–Ñ… рахунків, що пов’Ñзані з кориÑтуваннÑм цією поÑлугою. + +/voicepost/numbers.bml.list.info=Ðижче перераховано коди та міÑта, де ми маємо номери Ð´Ð»Ñ Ð³Ð¾Ð»Ð¾Ñових запиÑів. ВлаÑники платних рахунків повинні увійти, щоб побачити повний ÑпиÑок номерів. + +/voicepost/numbers.bml.list.jump=Перейти до: + +/voicepost/numbers.bml.list.note=ЗауваженнÑ: Ми поÑтійно додаємо нові номери. + +/voicepost/numbers.bml.list.request=Ми проÑимо Ð²Ð°Ñ Ð½Ðµ поширювати ці номери, бо ми хотіл б уникнути зайвого телефонного трафіку. + +/voicepost/numbers.bml.list.text=Ð”Ð»Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу голоÑових запиÑів зателефонуйте за цими номерами: + +/voicepost/numbers.bml.title=Ðомери доÑтупу до голоÑових запиÑів + +account_level.plus=Розширений + +account_level.plus2=Розширений + +adcat.arts.display=МиÑтецтво та людÑтво + +adcat.arts.example=Художні школи, культурні події, музеї, живі театри + +adcat.auto.display=Ðвто та колеÑа + +adcat.auto.example=Ðвтомобілі та вантажівки, запчаÑтини, мотоцикли + +adcat.books.display=Книги та Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + +adcat.books.example=ІÑторії, книжкові клуби, оглÑди + +adcat.charity.display=БлагодійніÑÑ‚ÑŒ, політика та Ñоціальний захиÑÑ‚ + +adcat.charity.example=ÐÑоціації, пожертвуваннÑ, Ñоціальне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ + +adcat.date.display=ЗнайомÑтва, Ñоціальні мережі + +adcat.date.example=Друзі, ÑтоÑунки, ÐºÐ¾Ñ…Ð°Ð½Ð½Ñ + +adcat.edujob.display=Робота та Ð½Ð°Ð²Ñ‡Ð°Ð½Ð½Ñ + +adcat.edujob.example=Школи, підготовчі курÑи, оÑвіта, кар’єри, Ñлужби зайнÑтоÑÑ‚Ñ– + +adcat.electronics.display=ОÑобиÑта електроніка + +adcat.electronics.example=Play Station, Xbox, iPod, ÑтереоÑиÑтеми, плоÑкі екрани + +adcat.fun.display=Відпочинок та Ð´Ð¾Ð·Ð²Ñ–Ð»Ð»Ñ + +adcat.fun.example=Обіди, нічне життÑ, знаменитоÑÑ‚Ñ– + +adcat.health.display=Ð—Ð´Ð¾Ñ€Ð¾Ð²â€™Ñ + +adcat.health.example=Спортивні вправи, дієти, медицина та Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +adcat.hobby.display=Дім та хоббі + +adcat.hobby.example=КулінаріÑ, їжа та вино, веÑіллÑ, озелененнÑ, вихованнÑ, крій та ÑˆÐ¸Ñ‚Ñ‚Ñ + +adcat.house.display=ОÑÐµÐ»Ñ + +adcat.house.example=Квартири, нерухоміÑÑ‚ÑŒ, домашні поÑлуги + +adcat.internet.display=Інтернет та медіа + +adcat.internet.example=Веб-дизайн, аніме та мультфільми, чаÑопиÑи, блоґи + +adcat.money.display=Гроші та Ð±Ñ–Ð·Ð½ÐµÑ + +adcat.money.example=ФінанÑові поÑлуги та інвеÑтуваннÑ, ÑтрахуваннÑ, банківÑька Ñправа, бізнеÑ-поÑлуги + +adcat.movies.display=Фільми + +adcat.movies.example=У кінотеатрах, відео-каÑети, DVD + +adcat.music.display=Музика + +adcat.music.example=Концерти, текÑти піÑень, інÑтрументи, квитки + +adcat.news.display=Ðовини + +adcat.news.example=Поточні події, погода, джерела інформації + +adcat.pets.display=СвійÑькі тварини + +adcat.pets.example=Зоомагазини, піклуваннÑ, продукти + +adcat.shop.display=Покупки + +adcat.shop.example=Роздрібна торгівлÑ, одÑг, взуттÑ, аукціони, коÑметика, подарунки, Ð¼ÐµÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ + +adcat.sport.display=Спорт та відпочинок + +adcat.sport.example=СпорÑдженнÑ, квитки, пам’Ñтні речі, команди + +adcat.tech.display=Комп’ютери та технології + +adcat.tech.example=Ðпаратне та програмне забезпеченнÑ, ÑиÑтеми, графічні ÑиÑтеми + +adcat.trav.display=Подорожі + +adcat.trav.example=Ðвіалінії, готелі, пункти призначеннÑ, круїзи, пригоди + +adcat.wireless.display=Мобільні приÑтрої + +adcat.wireless.example=Телефони, бездротові провайдери, мелодії, WiFi + +birthday.link=дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +birthday.text=Гей, [[user]], подивиÑÑŒ Ñкі [[link]] твоїх друзів будуть незабаром! LiveJournal тримає цей ÑпиÑок Ñаме Ð´Ð»Ñ Ñ‚ÐµÐ±Ðµ. + +bml.badcontent.body=Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ вашого запиту виникли одна чи більше помилок. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´, будь лаÑка, виправте необхідну інформацію Ñ– надішліть дані знов. + +bml.badinput.body=Ваш браузер надіÑлав певний текÑÑ‚, Ñкий не було розпізнано Ñк текÑÑ‚ в кодуванні UTF-8, Ñк мало би бути. Це могло ÑтатиÑÑ, Ñкщо ви налаштували переглÑд попередньої Ñторінки в ÑкомуÑÑŒ іншому кодуванні, відмінному від UTF-8. Також, це може Ñвідчити про програмну помилку в браузері. Якщо Ви не можете впоратиÑÑ Ð· цією проблемою, зв'ÑжітьÑÑ Ð· нами. + +bml.badinput.head=Погані вхідні дані Unicode + +bml.needlogin.body4=Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñторінки ви повинні увійти. Якщо ви не маєте рахунку, то можете Ñтворити його негайно. + +bml.needlogin.body5=Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñторінки ви повинні увійти. Якщо ви не маєте рахунку, то можете Ñтворити новий. + +bml.needlogin.head=Потрібно увійти + +BML.parse_multipart.parse=Помилка при обробці файла, Ñкий було завантажено. + +BML.parse_multipart.toolarge=Занадто велике Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ + +BML.parse_multipart.unknowntype=Ðевідомий тип зміÑту. + +bml.requirepost=З причин безпеки, Ñторінка, Ñку ви дивитеÑÑ, вимагає запит типу POST, а не GET. Якщо ви законно намагаєтеÑÑ Ð½Ð°Ð´Ñ–Ñлати цю форму, то зв'ÑжітьÑÑ Ð· нами, будь лаÑка. + +btn.search=Пошук + +controlstrip.link=навігаційний Ñ€Ñдок + +controlstrip.text=9 з 10 кориÑтувачів LJ обрали [[link]]. (Добре, ми вигадали це, але у будь-Ñкому разі ви маєте це перевірити.) + +cprod.adplacement.link.free.v1=Розширений тип рахунку + +cprod.adplacement.link.free.v2=_skip + +cprod.adplacement.link.free.v3=_skip + +cprod.adplacement.link.free.v4=_skip + +cprod.adplacement.link.free.v5=_skip + +cprod.adplacement.link.plus.v1=горизонтальне розміщеннÑ. + +cprod.adplacement.link.plus.v2=_skip + +cprod.adplacement.link.plus.v3=_skip + +cprod.adplacement.link.plus.v4=_skip + +cprod.adplacement.link.plus.v5=_skip + +cprod.adplacement.text.plus.v1=[[user]], вертикальна реклама пÑує ваш Ñтиль?
    Спробуйте нове [[link]] + +cprod.adplacement.text.plus.v2=_skip + +cprod.adplacement.text.plus.v3=_skip + +cprod.adplacement.text.plus.v4=_skip + +cprod.adplacement.text.plus.v5=_skip + +cprod.adplacement.text2.free.v1=[[user]], [[link]] тепер виглÑдає значно краще.
    • Спробуйте нове горизонтальне Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ Ð´Ð»Ñ ÐºÑ€Ð°Ñ‰Ð¾Ð³Ð¾ виглÑду журналу.
    • ПодивітьÑÑ Ð½Ð¾Ð²Ñ– Ñтилі, в Ñких реклама виглÑдає краще.
    + +cprod.adplacement.text2.free.v2=_skip + +cprod.adplacement.text2.free.v3=_skip + +cprod.adplacement.text2.free.v4=_skip + +cprod.adplacement.text2.free.v5=_skip + +cprod.birthday.link.v1=дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +cprod.birthday.link.v2=_skip + +cprod.birthday.link.v3=_skip + +cprod.birthday.link.v4=_skip + +cprod.birthday.link.v5=_skip + +cprod.birthday.text.v1=Гей, [[user]], дізнайÑÑ Ð¿Ñ€Ð¾ [[link]] Ñвоїх друзів, Ñкі незабаром ÑвÑткуватимутьÑÑ! LiveJournal тримає ÑпиÑок цих днів народжень Ð´Ð»Ñ Ñ‚ÐµÐ±Ðµ. + +cprod.birthday.text.v2=_skip + +cprod.birthday.text.v3=_skip + +cprod.birthday.text.v4=_skip + +cprod.birthday.text.v5=_skip + +cprod.box.alllink=УÑÑ– + +cprod.box.nextlink=Інша + +cprod.box.title=Порада + +cprod.controlstrip.link.v1=навігаційний Ñ€Ñдок + +cprod.controlstrip.link.v2=_skip + +cprod.controlstrip.link.v3=_skip + +cprod.controlstrip.link.v4=_skip + +cprod.controlstrip.link.v5=_skip + +cprod.controlstrip.text.v1=9 з 10 кориÑтувачів LJ обрали [[link]]. (Добре, ми трохи перебільшили, але у будь-Ñкому разі ви повинні це Ñпробувати.) + +cprod.controlstrip.text.v2=_skip + +cprod.controlstrip.text.v3=_skip + +cprod.controlstrip.text.v4=_skip + +cprod.controlstrip.text.v5=_skip + +cprod.controlstrip_activated.linkconfig.v1=Ðалаштувати/Видалити + +cprod.controlstrip_activated.linkhide.v1=Сховати це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +cprod.controlstrip_activated.text.v1=
    Спробуйте новий навігаційний Ñ€Ñдок!
    [[linkconfig]] [[linkhide]]
    + +cprod.controlstrip_adplacement.linkhide.free.v1=Ðе показувати знов + +cprod.controlstrip_adplacement.linkhide.plus.v1=Ðе показувати знов + +cprod.controlstrip_adplacement.linkupgrade.free.v1=Розширений рахунок + +cprod.controlstrip_adplacement.linkupgrade.plus.v1=Спробувати + +cprod.controlstrip_adplacement.text.free.v1=
    Перейдіть безкоштовно.
    Більше Ñтилів та контролю над розміщеннÑм
    [[linkupgrade]] [[linkhide]]
    + +cprod.controlstrip_adplacement.text.plus.v1=
    Ðове! ПеренеÑÑ–Ñ‚ÑŒ рекламу до гори та до низу.
    [[linkupgrade]] [[linkhide]]
    + +cprod.controlstrip_adplacement.text3.free.v1=
    Більше Ñтилів та контролю над рекламою.
    [[linkupgrade]] [[linkhide]]
    + +cprod.controlstrip_expressivethemes.linkhide.paid.v1=Ðе показувати знов + +cprod.controlstrip_expressivethemes.linkupgrade.paid.v1=Спробувати + +cprod.controlstrip_expressivethemes.text.paid.v1=
    Ðові Ñтилі вже тут Ñ– платники мають повний доÑтуп до них.
    [[linkupgrade]] [[linkhide]]
    + +cprod.controlstrip_expressivethemes.text2.paid.v1=
    Ðові Ñтилі Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів!
    [[linkupgrade]] [[linkhide]]
    + +cprod.controlstrip_polls.linkhide.v1=Сховати + +cprod.controlstrip_polls.linkupgrade.v1=обравши Розширений рахунок + +cprod.controlstrip_polls.text.v1=
    Отримайте Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·ÐºÐ¾ÑˆÑ‚Ð¾Ð²Ð½Ð¾
    [[linkupgrade]] | [[linkhide]]
    + +cprod.controlstrip_splus.linkhide.v1=Сховати це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +cprod.controlstrip_splus.linkmore.v1=ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ + +cprod.controlstrip_splus.text.v1=
    Отримайте більше можливоÑтей! Спробуйте Розширений рахунок
    [[linkmore]] [[linkhide]]
    + +cprod.createstyles.link.v1=отримайте платний рахунок. + +cprod.createstyles.link.v2=_skip + +cprod.createstyles.link.v3=_skip + +cprod.createstyles.link.v4=_skip + +cprod.createstyles.link.v5=_skip + +cprod.createstyles.text.v1=Це функціональна можливіÑÑ‚ÑŒ платного рахунку. Щоб Ñтворити Ñтиль, [[link]] + +cprod.createstyles.text.v2=_skip + +cprod.createstyles.text.v3=_skip + +cprod.createstyles.text.v4=_skip + +cprod.createstyles.text.v5=_skip + +cprod.directory.link.v1=перейдіть на платний рахунок + +cprod.directory.link.v2=_skip + +cprod.directory.link.v3=_skip + +cprod.directory.link.v4=_skip + +cprod.directory.link.v5=_skip + +cprod.directory.text.v1=Тип вашого рахунку не дозволÑÑ” кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼. Щоб отримати доÑтуп до каталогу, ÑкориÑтайтеÑÑ [[link]] + +cprod.directory.text.v2=_skip + +cprod.directory.text.v3=_skip + +cprod.directory.text.v4=_skip + +cprod.directory.text.v5=_skip + +cprod.directory.text2.v1=Тип вашого рахунку не дозволÑÑ” кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼. Щоб отримати доÑтуп до каталогу, ви повинні [[link]] + +cprod.directory.text2.v2=_skip + +cprod.directory.text2.v3=_skip + +cprod.directory.text2.v4=_skip + +cprod.directory.text2.v5=_skip + +cprod.dystopia.nav.link.v1=Поновіть ваш рахунок + +cprod.dystopia.nav.link.v2=_skip + +cprod.dystopia.nav.link.v3=_skip + +cprod.dystopia.nav.link.v4=_skip + +cprod.dystopia.nav.link.v5=_skip + +cprod.dystopia.nav.link3.v1=Отримайте більше можливоÑтей + +cprod.dystopia.nav.link3.v2=Поновіть ваш рахунок + +cprod.dystopia.nav.text.v2=_skip + +cprod.dystopia.nav.text.v3=_skip + +cprod.dystopia.nav.text.v4=_skip + +cprod.dystopia.nav.text.v5=_skip + +cprod.editpics.link.free.v1=придбати Платний рахунок + +cprod.editpics.link.free.v2=_skip + +cprod.editpics.link.free.v3=_skip + +cprod.editpics.link.free.v4=_skip + +cprod.editpics.link.free.v5=_skip + +cprod.editpics.link.plus.v1=Отримайте платний рахунок + +cprod.editpics.link.plus.v2=_skip + +cprod.editpics.link.plus.v3=_skip + +cprod.editpics.link.plus.v4=_skip + +cprod.editpics.link.plus.v5=_skip + +cprod.editpics.link.v1=отримайте платний рахунок + +cprod.editpics.link.v2=Отримайте платний рахунок + +cprod.editpics.link.v3=_skip + +cprod.editpics.link.v4=_skip + +cprod.editpics.link.v5=_skip + +cprod.editpics.link2-2.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpics.link2-2.v2=_skip + +cprod.editpics.link2-2.v3=_skip + +cprod.editpics.link2-2.v4=_skip + +cprod.editpics.link2-2.v5=_skip + +cprod.editpics.link2.free.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpics.link2.free.v2=_skip + +cprod.editpics.link2.free.v3=_skip + +cprod.editpics.link2.free.v4=_skip + +cprod.editpics.link2.free.v5=_skip + +cprod.editpics.link2.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpics.link2.v2=_skip + +cprod.editpics.link2.v3=_skip + +cprod.editpics.link2.v4=_skip + +cprod.editpics.link3-2.v1=_skip + +cprod.editpics.link3-2.v4=_skip + +cprod.editpics.link3-2.v5=_skip + +cprod.editpics.link3-3.v3=Отримайте більше юзерпик. + +cprod.editpics.link3.paid2.v1=Отримайте більше юзерпик. + +cprod.editpics.link3.paid2.v2=_skip + +cprod.editpics.link3.paid2.v3=_skip + +cprod.editpics.link3.paid2.v4=_skip + +cprod.editpics.link3.paid2.v5=_skip + +cprod.editpics.text.free.v1=Бажаєте більше юзерпик?
    Збільшить до [[plusnum]] при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text.free.v2=_skip + +cprod.editpics.text.free.v3=_skip + +cprod.editpics.text.free.v4=_skip + +cprod.editpics.text.free.v5=_skip + +cprod.editpics.text.paid.v2=_skip + +cprod.editpics.text.paid.v3=_skip + +cprod.editpics.text.paid.v4=_skip + +cprod.editpics.text.paid.v5=_skip + +cprod.editpics.text.paid2.v1=Бажаєте більше юзерпик?
    [[link3]] + +cprod.editpics.text.plus.v1=Бажаєте більше юзерпик?
    [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text.plus.v2=_skip + +cprod.editpics.text.plus.v3=_skip + +cprod.editpics.text.plus.v4=_skip + +cprod.editpics.text.plus.v5=_skip + +cprod.editpics.text.v3=_skip + +cprod.editpics.text.v4=_skip + +cprod.editpics.text.v5=_skip + +cprod.editpics.text3.v1=Бажаєте більше юзерпик?
    Збільшить до 15 при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text3.v2=Бажаєте більше юзерпик?
    [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text5.v4=_skip + +cprod.editpics.text5.v5=_skip + +cprod.editpics.text6.v1=Бажаєте більше юзерпик?
    Збільшить до [[plusnum]] при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text6.v2=Бажаєте більше юзерпик?
    [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpics.text6.v3=Бажаєте більше юзерпик?
    [[link3]] + +cprod.editpics.text7.v1=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. + +cprod.editpicsmax.link.free.v1=отримайте платний рахунок + +cprod.editpicsmax.link.free.v2=_skip + +cprod.editpicsmax.link.free.v3=_skip + +cprod.editpicsmax.link.free.v4=_skip + +cprod.editpicsmax.link.free.v5=_skip + +cprod.editpicsmax.link.plus.v1=Отримайте платний рахунок + +cprod.editpicsmax.link.plus.v2=_skip + +cprod.editpicsmax.link.plus.v3=_skip + +cprod.editpicsmax.link.plus.v4=_skip + +cprod.editpicsmax.link.plus.v5=_skip + +cprod.editpicsmax.link.v1=отримайте платний рахунок + +cprod.editpicsmax.link.v2=Отримайте платний рахунок + +cprod.editpicsmax.link.v3=_skip + +cprod.editpicsmax.link.v4=_skip + +cprod.editpicsmax.link.v5=_skip + +cprod.editpicsmax.link2-2.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpicsmax.link2-3.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpicsmax.link2.free.v1=переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.editpicsmax.link2.free.v2=_skip + +cprod.editpicsmax.link2.free.v3=_skip + +cprod.editpicsmax.link2.free.v4=_skip + +cprod.editpicsmax.link2.free.v5=_skip + +cprod.editpicsmax.link2.v2=_skip + +cprod.editpicsmax.link2.v3=_skip + +cprod.editpicsmax.link2.v4=_skip + +cprod.editpicsmax.link2.v5=_skip + +cprod.editpicsmax.link3.paid.v1=Отримайте більше юзерпик. + +cprod.editpicsmax.link3.paid.v2=_skip + +cprod.editpicsmax.link3.paid.v3=_skip + +cprod.editpicsmax.link3.paid.v4=_skip + +cprod.editpicsmax.link3.paid.v5=_skip + +cprod.editpicsmax.link3.v1=_skip + +cprod.editpicsmax.link3.v3=Отримайте більше юзерпик. + +cprod.editpicsmax.link3.v4=_skip + +cprod.editpicsmax.link3.v5=_skip + +cprod.editpicsmax.text.free.v1=You've reached your limit of [[num]] userpics. Want more?
    Increase to [[plusnum]] when you [[link2]] for free, or [[link]] for [[paidnum]] userpics and the option to earn or buy even more. + +cprod.editpicsmax.text.free.v2=_skip + +cprod.editpicsmax.text.free.v3=_skip + +cprod.editpicsmax.text.free.v4=_skip + +cprod.editpicsmax.text.free.v5=_skip + +cprod.editpicsmax.text.paid.v1=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. Бажаєте більше?
    [[link3]] + +cprod.editpicsmax.text.paid.v2=- + +cprod.editpicsmax.text.paid.v3=_skip + +cprod.editpicsmax.text.paid.v4=_skip + +cprod.editpicsmax.text.paid.v5=_skip + +cprod.editpicsmax.text.plus.v1=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. Бажаєте більше?
    [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text.plus.v2=_skip + +cprod.editpicsmax.text.plus.v3=_skip + +cprod.editpicsmax.text.plus.v4=_skip + +cprod.editpicsmax.text.plus.v5=_skip + +cprod.editpicsmax.text.v1=Бажаєте більше?
    Збільшить до 15 при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text.v2=Бажаєте більше?
    [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text.v3=_skip + +cprod.editpicsmax.text.v4=_skip + +cprod.editpicsmax.text.v5=_skip + +cprod.editpicsmax.text2.v1=Ви доÑÑгли Ñвого ліміту в 6 юзерпик. Бажаєте більше?
    Збільшить до 15 при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text2.v2=Ви доÑÑгли Ñвого ліміту в 15 юзерпик. Бажаєте більше?
    [[link]] Ð´Ð»Ñ 30 юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text5.v1=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. Бажаєте більше?
    Збільшить до [[plusnum]]при безкоштовному переході на [[link2]] або [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text5.v2=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. Бажаєте більше?
    [[link]] Ð´Ð»Ñ [[paidnum]] юзерпик та можливоÑÑ‚Ñ– заробити або придбати ще більше. + +cprod.editpicsmax.text5.v3=Ви доÑÑгли Ñвого ліміту в [[num]] юзерпик. Бажаєте більше?
    [[link3]] + +cprod.editpicsmax.text5.v4=_skip + +cprod.editpicsmax.text5.v5=_skip + +cprod.editstyles.link.v1=отримайте платний рахунок. + +cprod.editstyles.link.v2=_skip + +cprod.editstyles.link.v3=_skip + +cprod.editstyles.link.v4=_skip + +cprod.editstyles.link.v5=_skip + +cprod.editstyles.text.v1=Це функціональна можливіÑÑ‚ÑŒ платного рахунку. Щоб Ñтворити Ñтиль, [[link]] + +cprod.editstyles.text.v2=_skip + +cprod.editstyles.text.v3=_skip + +cprod.editstyles.text.v4=_skip + +cprod.editstyles.text.v5=_skip + +cprod.esn.link.v1=Ðалаштуйте ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ð°Ð·! + +cprod.esn.link.v2=_skip + +cprod.esn.link.v3=_skip + +cprod.esn.link.v4=_skip + +cprod.esn.link.v5=_skip + +cprod.esn.text2.v1=[[user]], бажаєте знати, коли Ð²Ð°Ñ Ð´Ð¾Ð´Ð°ÑŽÑ‚ÑŒ додають до друзів або коли друзі оновлюють Ñвої журнали? [[link]] + +cprod.esn.text2.v2=_skip + +cprod.esn.text2.v3=_skip + +cprod.esn.text2.v4=_skip + +cprod.esn.text2.v5=_skip + +cprod.expressivethemes.link.paid.v1=Спробувати + +cprod.expressivethemes.link.paid.v2=_skip + +cprod.expressivethemes.link.paid.v3=_skip + +cprod.expressivethemes.link.paid.v4=_skip + +cprod.expressivethemes.link.paid.v5=_skip + +cprod.expressivethemes.text.paid.v1=Бажаєте новий дизайн журналу? Ми додали більше 75 нових Ñтилів Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів. [[link]] + +cprod.expressivethemes.text.paid.v2=_skip + +cprod.expressivethemes.text.paid.v3=_skip + +cprod.expressivethemes.text.paid.v4=_skip + +cprod.expressivethemes.text.paid.v5=_skip + +cprod.feeds.link.v1=Ñиндикативні потоки + +cprod.feeds.link.v2=_skip + +cprod.feeds.link.v3=_skip + +cprod.feeds.link.v4=_skip + +cprod.feeds.link.v5=_skip + +cprod.feeds.text.v1=Ðапевно, Ñ” непогані речі й поза LJ? Що ж, ми надаємо змогу додати Ñиндикатні потоки до вашої Ñтрічки друзів - Ñ– вам не доведетьÑÑ Ñ—Ñ— залишати. + +cprod.feeds.text.v2=_skip + +cprod.feeds.text.v3=_skip + +cprod.feeds.text.v4=_skip + +cprod.feeds.text.v5=_skip + +cprod.friendsfriends.link.v1=друзі друзів + +cprod.friendsfriends.link.v2=_skip + +cprod.friendsfriends.link.v3=_skip + +cprod.friendsfriends.link.v4=_skip + +cprod.friendsfriends.link.v5=_skip + +cprod.friendsfriends.link2.v1=друзі друзів + +cprod.friendsfriends.link2.v2=_skip + +cprod.friendsfriends.link2.v3=_skip + +cprod.friendsfriends.link2.v4=_skip + +cprod.friendsfriends.link2.v5=_skip + +cprod.friendsfriends.text.v1=Гей, друже, Ñтрічка [[link]] відображає вÑÑ– Ñтрічки друзів твоїх друзів у одній Ñтрічці друзів. Скажи це тричі без зупинки. + +cprod.friendsfriends.text.v2=_skip + +cprod.friendsfriends.text.v3=_skip + +cprod.friendsfriends.text.v4=_skip + +cprod.friendsfriends.text.v5=_skip + +cprod.friendsfriends.text2.v1=Гей, друже, Ñтрічка [[link]] показує вÑÑ– Ñтрічки друзів твоїх друзів у одній Ñтрічці друзів. Скажи це тричі без зупинки. + +cprod.friendsfriends.text2.v2=_skip + +cprod.friendsfriends.text2.v3=_skip + +cprod.friendsfriends.text2.v4=_skip + +cprod.friendsfriends.text2.v5=_skip + +cprod.friendsfriendsinline.link2.v1=Платні рахунки + +cprod.friendsfriendsinline.link2.v2=_skip + +cprod.friendsfriendsinline.link2.v3=_skip + +cprod.friendsfriendsinline.link2.v4=_skip + +cprod.friendsfriendsinline.link2.v5=_skip + +cprod.friendsfriendsinline.link3.v1=Платні рахунки + +cprod.friendsfriendsinline.link3.v2=_skip + +cprod.friendsfriendsinline.link3.v3=_skip + +cprod.friendsfriendsinline.link3.v4=_skip + +cprod.friendsfriendsinline.link3.v5=_skip + +cprod.friendsfriendsinline.text2.v1=Вибачте, лише [[link]] підтримують Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² друзів. + +cprod.friendsfriendsinline.text2.v2=_skip + +cprod.friendsfriendsinline.text2.v3=_skip + +cprod.friendsfriendsinline.text2.v4=_skip + +cprod.friendsfriendsinline.text2.v5=_skip + +cprod.friendsfriendsinline.text3.v1=Вибачте, лише [[link]] підтримують Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² друзів. + +cprod.friendsfriendsinline.text3.v2=_skip + +cprod.friendsfriendsinline.text3.v3=_skip + +cprod.friendsfriendsinline.text3.v4=_skip + +cprod.friendsfriendsinline.text3.v5=_skip + +cprod.gizmo.link2.v1=Gizmo Project Ð´Ð»Ñ LJ Talk + +cprod.gizmo.link2.v2=_skip + +cprod.gizmo.link2.v3=_skip + +cprod.gizmo.link2.v4=_skip + +cprod.gizmo.link2.v5=_skip + +cprod.gizmo.text2.v1=Хочете поговорити зі Ñвоїми друзÑми? Скачайте [[link]] Ñ– вÑÑ– ваші друзі з’ÑвлÑÑ‚ÑŒÑÑ Ñƒ ÑпиÑку контактів. Також ви зможете робити голоÑові запиÑи проÑто зі Ñвого комп’ютера. + +cprod.gizmo.text2.v2=_skip + +cprod.gizmo.text2.v3=_skip + +cprod.gizmo.text2.v4=_skip + +cprod.gizmo.text2.v5=_skip + +cprod.horizon.link.v1=Зазирнути. + +cprod.horizon.link.v2=_skip + +cprod.horizon.link.v3=_skip + +cprod.horizon.link.v4=_skip + +cprod.horizon.link.v5=_skip + +cprod.horizon.text.v1=У вереÑні LiveJournal отримає новий дизайн. [[link]] + +cprod.horizon.text.v2=_skip + +cprod.horizon.text.v3=_skip + +cprod.horizon.text.v4=_skip + +cprod.horizon.text.v5=_skip + +cprod.interests.text2.v1=Люди, Ñкі мають зацікавленнÑ, Ñ” цікавими.

    Ви цікаві, чи не так? + +cprod.interests.text2.v2=_skip + +cprod.interests.text2.v3=_skip + +cprod.interests.text2.v4=_skip + +cprod.interests.text2.v5=_skip + +cprod.links.link.v1=Перейти на платний рахунок + +cprod.links.link.v2=Перейти на платний рахунок + +cprod.links.link.v3=_skip + +cprod.links.link.v4=_skip + +cprod.links.link.v5=_skip + +cprod.links.link2-2.v1=Безкоштовно переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.links.link2.v2=_skip + +cprod.links.link2.v3=_skip + +cprod.links.link2.v4=_skip + +cprod.links.link2.v5=_skip + +cprod.links.text.v1=Бажаєте більше поÑилань? [[link2]], щоб збільшити до 30, [[link]], щоб збільшити до 50. + +cprod.links.text.v2=Бажаєте більше поÑилань? [[link]], щоб збільшити до 50. + +cprod.links.text.v3=_skip + +cprod.links.text.v4=_skip + +cprod.links.text.v5=_skip + +cprod.links.text3.v1=Тип вашого рахунку не підтримує більшої кількоÑÑ‚Ñ– поÑилань. + +cprod.links.text3.v2=_skip + +cprod.links.text3.v3=_skip + +cprod.links.text3.v4=_skip + +cprod.links.text3.v5=_skip + +cprod.ljfeedback.text.v1=Любите голоÑувати? ПриєднуйтеÑÑ Ð´Ð¾ [[journal]], де ми проводимо Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° доÑлідженнÑ, Ñкі допомогають впливати та покращувати LJ. + +cprod.ljfeedback.text.v2=_skip + +cprod.ljfeedback.text.v3=_skip + +cprod.ljfeedback.text.v4=_skip + +cprod.ljfeedback.text.v5=_skip + +cprod.ljspotlight.text.v1=Ми не відводимо поглÑду від цікавих Ñпільнот. ДивітьÑÑ [[journal]], щоб дізнатиÑÑ Ð¿Ñ€Ð¾ найцікавіше у LJ. + +cprod.ljspotlight.text.v2=_skip + +cprod.ljspotlight.text.v3=_skip + +cprod.ljspotlight.text.v4=_skip + +cprod.ljspotlight.text.v5=_skip + +cprod.ljtalk.link4.v1=ÑÐµÑ€Ð²Ñ–Ñ Ð¼Ð¸Ñ‚Ñ‚Ñ”Ð²Ð¸Ñ… повідомлень + +cprod.ljtalk.link4.v2=_skip + +cprod.ljtalk.link4.v3=_skip + +cprod.ljtalk.link4.v4=_skip + +cprod.ljtalk.link4.v5=_skip + +cprod.ljtalk.link5.v1=ÑÐµÑ€Ð²Ñ–Ñ Ð¼Ð¸Ñ‚Ñ‚Ñ”Ð²Ð¸Ñ… повідомлень + +cprod.ljtalk.link5.v2=_skip + +cprod.ljtalk.link5.v4=_skip + +cprod.ljtalk.link5.v5=_skip + +cprod.ljtalk.text7.v1=Френк: Ме-е-е. LJ має новий [[link]]!
    КориÑтувач LJ: Ðавіщо мені ще один?
    Френк: Бо твої LJ-друзі автоматично з’ÑвлÑÑ‚ÑŒÑÑ Ñƒ ÑпиÑку контактів, а ще ти зможеш напиÑати з нього до LJ!
    КориÑтувач LJ: Це здаєтьÑÑ Ð´Ð¸Ð²Ð¾Ð²Ð¸Ð¶Ð½Ð¸Ð¼ Ñ– легким! + +cprod.ljtalk.text7.v2=_skip + +cprod.ljtalk.text7.v3=_skip + +cprod.ljtalk.text7.v4=_skip + +cprod.ljtalk.text7.v5=_skip + +cprod.ljtalk.text8.v1=Френк: Ме-е-е. Ð’ LJ з’ÑвивÑÑ Ð½Ð¾Ð²Ð¸Ð¹ [[link]]!
    КориÑтувач LJ: Ðавіщо мені ще один?
    Френк: ОÑкільки у ньому автоматично з’ÑвлÑÑ‚ÑŒÑÑ Ñ‚Ð²Ð¾Ñ— друзі, крім того у ньому ти зможеш робити запиÑи до LJ!
    КориÑтувач LJ: Звучить заманливо! + +cprod.ljtalk.text8.v2=_skip + +cprod.ljtalk.text8.v3=_skip + +cprod.ljtalk.text8.v4=_skip + +cprod.ljtalk.text8.v5=_skip + +cprod.ljtips.text.v1=Бажаєте дізнатиÑÑ Ð¿Ñ€Ð¾ інші чудові поради на зразок цієї, [[user]]? ДивітьÑÑ [[journal]]! + +cprod.ljtips.text.v2=_skip + +cprod.ljtips.text.v3=_skip + +cprod.ljtips.text.v4=_skip + +cprod.ljtips.text.v5=_skip + +cprod.news.text.v1=

    Що нового на [[sitename]]?

    Додайте новини до Ñвоєї Ñтрічки друзів, щоб отримувати найÑвіжіші анонÑи й завжди бути в курÑÑ– Ñправ.

    + +cprod.polls.link.v1=майÑтру ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½ÑŒ + +cprod.polls.link.v2=_skip + +cprod.polls.link.v3=_skip + +cprod.polls.link.v4=_skip + +cprod.polls.link.v5=_skip + +cprod.polls.text.v1=[[user]], чи знаєте ви, що можете Ñтворити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ Ñвоєму журналі завдÑки нашому [[link]]? ДізнайтеÑÑ Ñправжню думку Ñвоїх друзів про вашу нову Ñорочку. + +cprod.polls.text.v2=_skip + +cprod.polls.text.v3=_skip + +cprod.polls.text.v4=_skip + +cprod.polls.text.v5=_skip + +cprod.sms.branded1.text.v1=Ви можете надÑилати та отримувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñƒ виглÑді текÑтових повідомлень завдÑки нашій новій можливоÑÑ‚Ñ– - TxtLJ (підтримуєтьÑÑ amp'd mobile)! + +cprod.sms.branded2.text.v1=Ðемає комп’ютера поруч? amp'd mobile надав підтримку LJ Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… можливоÑтей Ð´Ð»Ñ Ð²Ð°ÑˆÑ–Ñ… мобільних телефонів! + +cprod.sms.nonbranded1.text.v1=Ви можете надÑилати та отримувати ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñƒ виглÑді текÑтових повідомлень завдÑки нашій новій можливоÑÑ‚Ñ– - TxtLJ! + +cprod.sms.nonbranded2.text.v1=Ðемає комп’ютера поруч? LJ надає багато можливоÑтей Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ мобільного телефона! + +cprod.splus.link=Розширений + +cprod.splus.link.v1=Розширений + +cprod.splus.link.v10=_skip + +cprod.splus.link.v11=_skip + +cprod.splus.link.v12=_skip + +cprod.splus.link.v13=_skip + +cprod.splus.link.v14=_skip + +cprod.splus.link.v15=_skip + +cprod.splus.link.v2=_skip + +cprod.splus.link.v3=_skip + +cprod.splus.link.v4=_skip + +cprod.splus.link.v5=_skip + +cprod.splus.link.v6=_skip + +cprod.splus.link.v7=_skip + +cprod.splus.link.v8=_skip + +cprod.splus.link.v9=_skip + +cprod.splus.text.v1=

    [[user]], отримайте більше можливоÑтей безкоштовно:

    • 15 юзерпик
    • Більше параметрів Ð´Ð»Ñ Ñтилів
    • Фото-хоÑтинґ ScrapBook
    • ЗапиÑи з мобільного
    • ГолоÑові запиÑи
    • Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних опитувань

    Перейдіть на Розширений рахунок. + +cprod.splus.text.v10=_skip + +cprod.splus.text.v11=_skip + +cprod.splus.text.v12=_skip + +cprod.splus.text.v13=_skip + +cprod.splus.text.v14=_skip + +cprod.splus.text.v15=_skip + +cprod.splus.text.v2=

    [[user]], отримайте більше можливоÑтей безкоштовно:

    • 15 юзерпик
    • Більше параметрів Ð´Ð»Ñ Ñтилів
    • Фото-хоÑтинґ ScrapBook
    • ЗапиÑи з мобільного
    • ГолоÑові запиÑи
    • Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних опитувань

    Перейдіть на Розширений рахунок. + +cprod.splus.text.v3=_skip + +cprod.splus.text.v4=_skip + +cprod.splus.text.v5=_skip + +cprod.splus.text.v6=_skip + +cprod.splus.text.v7=_skip + +cprod.splus.text.v8=_skip + +cprod.splus.text.v9=_skip + +cprod.syn.link.v1=Змініть зараз. + +cprod.syn.link.v2=_skip + +cprod.syn.link.v3=_skip + +cprod.syn.link.v4=_skip + +cprod.syn.link.v5=_skip + +cprod.syn.text.v1=Примітка: Ñ†Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ доÑтупна лише Ð´Ð»Ñ ÐŸÐ»Ð°Ñ‚Ð½Ð¸Ñ… рахунків. [[link]] + +cprod.syn.text.v2=_skip + +cprod.syn.text.v3=_skip + +cprod.syn.text.v4=_skip + +cprod.syn.text.v5=_skip + +cprod.textmessaging.link.v1=перейдіть на платний рахунок + +cprod.textmessaging.link.v2=_skip + +cprod.textmessaging.link.v3=_skip + +cprod.textmessaging.link.v4=_skip + +cprod.textmessaging.link.v5=_skip + +cprod.textmessaging.link2-2.v1=безкоштовно переключітьÑÑ Ð½Ð° Розширений рахунок + +cprod.textmessaging.link2.v2=_skip + +cprod.textmessaging.link2.v3=_skip + +cprod.textmessaging.link2.v4=_skip + +cprod.textmessaging.link2.v5=_skip + +cprod.textmessaging.text.v1=Це функціональна можливіÑÑ‚ÑŒ платного рахунку. Щоб включити голоÑові запиÑи [[link]] + +cprod.textmessaging.text.v2=_skip + +cprod.textmessaging.text.v3=_skip + +cprod.textmessaging.text.v4=_skip + +cprod.textmessaging.text.v5=_skip + +cprod.textmessaging.text2.v1=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— можливоÑÑ‚Ñ–. Щоб кориÑтуватиÑÑ Ñ‚ÐµÐºÑтовими повідомленнÑми, [[link2]] або [[link]]. + +cprod.textmessaging.text3.v1=Тип вашого рахунку не дозволÑÑ” викориÑÑ‚Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— можливоÑÑ‚Ñ–. Щоб кориÑтуватиÑÑ Ñ‚ÐµÐºÑтовими повідомленнÑми, [[link2]] або [[link]]. + +cprod.todomaxitems.link.v1=обравши Платний рахунок. + +cprod.todomaxitems.link.v2=_skip + +cprod.todomaxitems.link.v3=_skip + +cprod.todomaxitems.link.v4=_skip + +cprod.todomaxitems.link.v5=_skip + +cprod.todomaxitems.text.v1=Ви можете збільшити ліміт до 150 [[link]] + +cprod.todomaxitems.text.v2=_skip + +cprod.todomaxitems.text.v3=_skip + +cprod.todomaxitems.text.v4=_skip + +cprod.todomaxitems.text.v5=_skip + +cprod.todomaxitems.text2.v1=Ви доÑÑгли ліміту нотаток, дозволених Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ типу рахунку. + +cprod.todomaxitems.text2.v2=_skip + +cprod.todomaxitems.text2.v3=_skip + +cprod.todomaxitems.text2.v4=_skip + +cprod.todomaxitems.text2.v5=_skip + +cprod.todononpublic.link.v1=Перейти на Платний рахунок + +cprod.todononpublic.link.v2=_skip + +cprod.todononpublic.link.v3=_skip + +cprod.todononpublic.link.v4=_skip + +cprod.todononpublic.link.v5=_skip + +cprod.todononpublic.text.v1=Лише влаÑники Платних рахунків можуть робити непублічні нотатки. [[link]] + +cprod.todononpublic.text.v2=_skip + +cprod.todononpublic.text.v3=_skip + +cprod.todononpublic.text.v4=_skip + +cprod.todononpublic.text.v5=_skip + +cprod.userpic.link.v1=юзерпику за замовчуваннÑм + +cprod.userpic.link.v2=_skip + +cprod.userpic.link.v3=_skip + +cprod.userpic.link.v4=_skip + +cprod.userpic.link.v5=_skip + +cprod.userpic.text.v1=[[user]], чи знаєте ви, що можете обрати [[link]] Ð´Ð»Ñ Ñвоїх запиÑів та коментарів? + +cprod.userpic.text.v2=_skip + +cprod.userpic.text.v3=_skip + +cprod.userpic.text.v4=_skip + +cprod.userpic.text.v5=_skip + +cprod.voicepost.link.v1=голоÑове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +cprod.voicepost.link.v2=_skip + +cprod.voicepost.link.v3=_skip + +cprod.voicepost.link.v4=_skip + +cprod.voicepost.link.v5=_skip + +cprod.voicepost.link4.v1=голоÑовий Ð·Ð°Ð¿Ð¸Ñ + +cprod.voicepost.link4.v2=_skip + +cprod.voicepost.link4.v3=_skip + +cprod.voicepost.link4.v4=_skip + +cprod.voicepost.link4.v5=_skip + +cprod.voicepost.text.v1=[[user]], бажаєте поділитиÑÑ Ñвоїм мелодичним голоÑом з читачами LiveJournal Ñтворивши [[link]]? + +cprod.voicepost.text.v2=_skip + +cprod.voicepost.text.v3=_skip + +cprod.voicepost.text.v4=_skip + +cprod.voicepost.text.v5=_skip + +cprod.voicepost.text4.v1=[[user]], ви вже поділилиÑÑŒ Ñвоїм чарівним голоÑом з читачами LiveJournal Ñтворивши [[link]]? + +cprod.voicepost.text4.v2=_skip + +cprod.voicepost.text4.v3=_skip + +cprod.voicepost.text4.v4=_skip + +cprod.voicepost.text4.v5=_skip + +crumb.about=Про LiveJournal + +crumb.abusereport=Повідомити про Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ + +crumb.acctfeatures=МожливоÑÑ‚Ñ– різних типів рахунків + +crumb.acctstatus=Стан рахунку + +crumb.addfriend=Додати друга + +crumb.addtodo=Додати Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ Ðотатника + +crumb.advcustomize=Змінити розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S2 + +crumb.advsearch=Розширений + +crumb.banners=Рекламні банери + +crumb.birthdays=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +crumb.cart=Кошик + +crumb.changeemail=Змінити email-адреÑу + +crumb.changepass=Змінити пароль + +crumb.code=Код LiveJournal + +crumb.commaccount=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ Ñпільноти + +crumb.comminvites=Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ Ñпільнот + +crumb.commmembers=УчаÑÑ‚ÑŒ у Ñпільноті + +crumb.commpending=Очікуючі учаÑники + +crumb.commsearch=Пошук Ñпільнот + +crumb.commsentinvites=ÐадіÑлати Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +crumb.commsettings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільноти + +crumb.community=Центр Ñпільнот + +crumb.contract=Ðаш ÑуÑпільний контракт + +crumb.contributors=Помічники + +crumb.createcommunity=Створити Ñпільноту + +crumb.createjournal=Створити журнал + +crumb.createjournal_1=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ рахунку + +crumb.createstyle=Створити Ñтиль + +crumb.customize=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ S2 + +crumb.customizelayer=Індивідуальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +crumb.delcomment=Видалити коментар + +crumb.dmca=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ DMCA + +crumb.domain=ПÑевдонім домену + +crumb.download=Скачати клієнта + +crumb.editcomments=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð² + +crumb.editentries=Змінити запиÑи + +crumb.editentries_do=Змінити Ð·Ð°Ð¿Ð¸Ñ + +crumb.editfriendgrps=Редагувати групи друзів + +crumb.editfriends=Змінити друзів + +crumb.editinfo=ОÑобиÑÑ‚Ñ– дані + +crumb.editpics=Юзерпики + +crumb.editprofile=Змінити профіль + +crumb.editsettings=Параметри переглÑду + +crumb.editstyle=Змінити Ñтиль + +crumb.edituserpics=Змінити юзерпики + +crumb.emailgateway=E-mail шлюз + +crumb.emailmanage=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ e-mail адреÑами + +crumb.encodings=Про ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + +crumb.export=ЕкÑпортувати журнал + +crumb.faq=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +crumb.feedstersearch=Шукати журнал + +crumb.filemanager=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸ + +crumb.friends=ЗаÑоби ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñми + +crumb.friendsfilter=Фільтр друзів + +crumb.goat=Про Френка + +crumb.guidingprinciples=Ðаші провідні принципи + +crumb.home=Початок + +crumb.invitefriend=ЗапроÑити друга + +crumb.itsfree=Це безкоштовно? + +crumb.joincomm=ПриєднатиÑÑ Ð´Ð¾ Ñпільноти + +crumb.latestposts=ОÑтанні запиÑи + +crumb.layerbrowse=ОглÑдач публічних шарів + +crumb.leavecomm=Покинути Ñпільноту + +crumb.legal=Правова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +crumb.linkslist=Ваші поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +crumb.ljhome=Початок + +crumb.ljtalkdownload=Gizmo Project Ð´Ð»Ñ LJ Talk + +crumb.login=Вхід + +crumb.logout=Вихід + +crumb.lostinfo=Загублені дані + +crumb.manage=Керувати рахунками + +crumb.managecommunity=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотами + +crumb.managelogins=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÑеÑÑ–Ñми входу + +crumb.meme=ВідÑтежувач ідей + +crumb.memories=Вибрані запиÑи + +crumb.mobilepost=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¸Ñ… повідомленнь + +crumb.moderate=ÐœÐ¾Ð´ÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñпільнотою + +crumb.modify=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +crumb.moodeditor=Редактор Поточної Теми ÐаÑтрою + +crumb.moodlist=ПереглÑд наÑтроїв + +crumb.news=Ðовини + +crumb.nudgefriend=Штурхнути друга + +crumb.paidaccounts=Платні рахунки + +crumb.paidacctstatus=Стан платного рахунку + +crumb.paidacctstatus2=Стан мого платного рахунку + +crumb.paidacctstatus3=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +crumb.paidhistory=ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð²Ð°ÑˆÐ¸Ñ… платежів + +crumb.pay=Моє Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +crumb.payments=Керувати моїми платежами + +crumb.phonepostsettings=ÐŸÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð¾Ð¼ + +crumb.popfaq=Ðайпоширеніші Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +crumb.popwithfriends=ПопулÑрні кориÑтувачі Ñеред ваших друзів + +crumb.press=ПреÑ-зона LiveJournal + +crumb.pressarticles=LiveJournal у преÑÑ– + +crumb.preview=Попередній переглÑд Ñхем + +crumb.privacy=Політика конфіденційноÑÑ‚Ñ– + +crumb.register=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ email + +crumb.schools=Каталог навчальних закладів + +crumb.schoolsfind=Знайти навчальний заклад + +crumb.schoolsmy=Мої навчальні заклади + +crumb.search=Пошук + +crumb.searchinterests=За зацікавленнÑм + +crumb.searchregion=За регіоном + +crumb.securechangeemail=Змінити email-адреÑу + +crumb.securechangepass=Змінити пароль + +crumb.securecreatejournal=Створити журнал + +crumb.securecreatejournal_1=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ LJ-рахунку + +crumb.secureeditinfo=ОÑобиÑÑ‚Ñ– дані + +crumb.securelogin=Вхід + +crumb.securemanage=Керувати рахунками + +crumb.seeoverrides=ДивитиÑÑ ÐºÐ¾Ð´Ð¸ Ð¿ÐµÑ€ÐµÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +crumb.setpgpkey=Публічний ключ + +crumb.shop=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ Ð¿Ð¾Ð´Ð°Ñ€ÑƒÐ½ÐºÑ–Ð² + +crumb.shopitem=Окремий товар + +crumb.singles=ЗнайомÑтва на LiveJournal + +crumb.singlesopts=Змінити доÑтупніÑÑ‚ÑŒ + +crumb.singlessearch=Шукати знайомÑтва + +crumb.sitemap=Мапа Ñайту + +crumb.siteopts=Параметри переглÑду + +crumb.sizechart=Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ€Ñ–Ð² + +crumb.staff=Старші керівні Ñпівробітники + +crumb.stats=СтатиÑтика + +crumb.store=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ LiveJournal + +crumb.storeitem=ПодивитиÑÑ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ñ– дані + +crumb.styles=Стилі + +crumb.suggestions=Генератор пропозицій + +crumb.suggview=Пропозиції + +crumb.support=Підтримка + +crumb.supportact=ÐадіÑлати запит + +crumb.supportappend=Приєднати до запиту + +crumb.supporthelp=Дошка запитів + +crumb.supportnotify=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ + +crumb.supportscores=Ðайвищі бали + +crumb.supportsubmit=Запит підтримки + +crumb.textmessage=ВідіÑлати текÑтове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +crumb.themes=Попередній переглÑд тем + +crumb.todo=Ðотатник + +crumb.tos=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +crumb.transfercomm=ПеренеÑти Ñпільноту + +crumb.translate=Зона перекладу + +crumb.translateteams=Команди перекладачів + +crumb.unsubscribe=ВідпиÑатиÑÑ + +crumb.update=Оновити журнал + +crumb.utf8convert=Конвертер UTF-8 + +crumb.voicepostsettings=ГолоÑове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +crumb.yourlayers=Ваші шари + +crumb.yourstyles=Ваші Ñтилі + +date.day.friday.long=П’ÑÑ‚Ð½Ð¸Ñ†Ñ + +date.day.friday.short=П’ÑÑ‚ + +date.day.monday.long=Понеділок + +date.day.monday.short=Пон + +date.day.saturday.long=Субота + +date.day.saturday.short=Суб + +date.day.sunday.long=ÐÐµÐ´Ñ–Ð»Ñ + +date.day.sunday.short=Ðед + +date.day.thursday.long=Четвер + +date.day.thursday.short=Чет + +date.day.tuesday.long=Вівторок + +date.day.tuesday.short=Вів + +date.day.wednesday.long=Середа + +date.day.wednesday.short=Сер + +date.month.april.long=Квітень + +date.month.april.short=Кві + +date.month.august.long=Серпень + +date.month.august.short=Сер + +date.month.december.long=Грудень + +date.month.december.short=Гру + +date.month.february.long=Лютий + +date.month.february.short=Лют + +date.month.january.long=Січень + +date.month.january.short=Січ + +date.month.july.long=Липень + +date.month.july.short=Лип + +date.month.june.long=Червень + +date.month.june.short=Чер + +date.month.march.long=Березень + +date.month.march.short=Бер + +date.month.may.long=Травень + +date.month.may.short=Тра + +date.month.november.long=ЛиÑтопад + +date.month.november.short=Ð›Ð¸Ñ + +date.month.october.long=Жовтень + +date.month.october.short=Жов + +date.month.september.long=ВереÑень + +date.month.september.short=Вер + +dystopia.btn.login=Увійти + +dystopia.hello_anonymous=ЛаÑкаво проÑимо до LiveJournal! + +dystopia.hello_loggedin=Привіт, [[username]]! + +dystopia.nav.contact=Контактні дані + +dystopia.nav.createjournal=Створити журнал + +dystopia.nav.customize=Ðалаштувати + +dystopia.nav.developer=Ð”Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð² + +dystopia.nav.download=Скачати + +dystopia.nav.editentries=Змінити запиÑи + +dystopia.nav.editfriends=Ваші друзі + +dystopia.nav.editpassword=Ваш пароль + +dystopia.nav.editstyle=Змінити Ñтиль + +dystopia.nav.edituserpics=Ваші юзерпики + +dystopia.nav.faq=Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +dystopia.nav.findcomm=За Ñпільнотою + +dystopia.nav.finddir=Пошук у каталозі + +dystopia.nav.findfeed=ДивитиÑÑ Ð¿Ð¾Ñ‚Ð¾ÐºÐ¸ + +dystopia.nav.findint=За зацікавленнÑм + +dystopia.nav.findrandom=Випадково + +dystopia.nav.findregion=За регіоном + +dystopia.nav.home=Початок + +dystopia.nav.journalcalendar=Календар + +dystopia.nav.journalcomments=Коментарі + +dystopia.nav.journalfriends=Друзі + +dystopia.nav.journalinfo=Профіль + +dystopia.nav.journalrecent=ОÑтанні запиÑи + +dystopia.nav.legalprivacy=ПриватніÑÑ‚ÑŒ + +dystopia.nav.legaltos=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +dystopia.nav.login=Увійти + +dystopia.nav.logout=Вийти + +dystopia.nav.lostinfo=Загублений пароль + +dystopia.nav.manage=Керувати рахунками + +dystopia.nav.memories=Вибране + +dystopia.nav.mobile=Мобільний + +dystopia.nav.modifyjournal=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +dystopia.nav.mylj=Мій LJ + +dystopia.nav.news=Ðовини + +dystopia.nav.paidaccts=Платні рахунки + +dystopia.nav.paymentarea=Оплата + +dystopia.nav.personalinfo=ОÑобиÑÑ‚Ñ– дані + +dystopia.nav.schools=По школах + +dystopia.nav.scrapbook=Твій ScrapBook + +dystopia.nav.scrapbook.galleries=Галереї + +dystopia.nav.scrapbook.groups=Групи + +dystopia.nav.scrapbook.main=Головна + +dystopia.nav.scrapbook.styles=Стилі + +dystopia.nav.scrapbook.taggingtool=ІнÑтрумент Ñ‚ÐµÐ³ÑƒÐ²Ð°Ð½Ð½Ñ + +dystopia.nav.scrapbook.tags=Теги + +dystopia.nav.scrapbook.upload=Завантажити + +dystopia.nav.scrapbook.view=ДивитиÑÑ + +dystopia.nav.sitemap=Мапа Ñайту + +dystopia.nav.siteopts=Параметри переглÑду + +dystopia.nav.support=Маєте запитаннÑ? + +dystopia.nav.updatejournal=Оновити журнал + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=150 + +dystopia.navhead.findusers=Знайти кориÑтувачів + +dystopia.navhead.help=Допомога та підтримка + +dystopia.navhead.journal=Ваш журнал + +dystopia.navhead.legal=Правова Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ + +dystopia.navhead.settings=Ваші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +dystopia.navhead.welcome=ЛаÑкаво проÑимо! + +dystopia.search.icq=ICQ номер + +dystopia.search.int=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +dystopia.search.msn=MSN ім'Ñ + +dystopia.search.region=Регіон + +dystopia.search.site=Сайт + +dystopia.search.siteandusername=Сайт та кориÑтувачі + +dystopia.searchlj=Шукати у LiveJournal: + +Email=E-mail + +email.newacct.body|notes=This string is no longer in use, please translate email.newacct2.body instead. +email.newacct.body<< +Вітаємо, ви Ñтворили новий рахунок у LiveJournal! + +Щоб завершити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ та перевірити вашу e-mail адреÑу, зайдіть Ñюди: + + [[regurl]] + +ÐдреÑа, де розміщений ваш новий журнал, така: + + [[siteroot]]/users/[[username]]/ + +а також така: + + [[siteroot]]/~[[username]]/ + +Ðижче наведено ваші Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль Ð´Ð»Ñ LiveJournal: + + Ім’Ñ: [[username]] + Пароль: [[password]] + +Ви можете піти до [[siteroot]]/ щоб мати доÑтуп до Ñвого рахунка, Ñтворювати нові запиÑи в журналі та змінювати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу, але ми рекомендуємо Ñкачати клієнтÑьку програму Ð´Ð»Ñ LiveJournal. Це найпроÑтіший ÑпоÑіб поновлювати Ñвій журнал, оÑобливо враховуючи, що Ñ–Ñнують клієнтÑькі програми Ð´Ð»Ñ Ð±Ð°Ð³Ð°Ñ‚ÑŒÐ¾Ñ… платформ! Візьміть одну з них тут: + + [[siteroot]]/download/ + +Спочатку, допоки ви нікого не знаєте у LiveJournal, вам може бути важкувато. Завітайте до http://newbies.livejournal.com, щоб отримати розумні поради та допомогу... маючи трохи вдачі, ви дуже швидко Ñтанете фахівцем у LiveJournal! Ми ÑподіваємоÑÑŒ, ви опануєте LiveJournal у вÑій повноті, що ми Ð´Ð»Ñ Ð²Ð°Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð¸Ð»Ð¸. Якщо ви маєте будь-Ñкі Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ ÑтоÑовно кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ LiveJournal, завітайте, будь лаÑка, до розділу підтримки: + + [[siteroot]]/support/ + +Там ви знайдете відповіді на майже будь-Ñке питаннÑ, Ñке ви могли б задати про LiveJournal. + +Ðаша мета - зробити LiveJournal Ñправді доÑконалим... Ñкщо ми можемо зробити щоÑÑŒ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, аби його вдоÑконалити, зробити потужнішим, зручнішим у налаштуваннÑÑ…... повідомте нам. Ми не тримаємо цей Ñайт, Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð±ÑƒÑ‚ÐºÑƒ. Ми - не велика ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð· чужим капіталом, що ÑподіваєтьÑÑ Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ продавати Ñвої акції на біржі, - цей Ñайт утримують вÑÑ– Ñ‚Ñ– люди, Ñкі ним кориÑтуютьÑÑ. Розкажіть нам, чого ви від нього бажаєте. + +Якщо ви маєте питаннÑ, то команда підтримки надаÑÑ‚ÑŒ вам швидку відповідь - зазвичай менш ніж протÑгом 24 годин. + +ÐаÑолоджуйтеÑÑŒ! + +Команда [[sitename]] +[[siteroot]]/ +. + +email.newacct.subject=ЛаÑкаво проÑимо до LiveJournal + +email.newacct2.body|notes=This string replaces email.newacct.body. You may refer to the old string while translating if you wish. +email.newacct2.body<< +Вітаємо, ви Ñтали влаÑником нового рахунку на [[sitename]]! + +Щоб завершити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñвого журналу та підтвердити e-mail, завітайте, будь лаÑка, за наÑтупною адреÑою. Перевірка e-mail допоможе захиÑтити ваш рахунок, а також дозволить вам викориÑтувати більше можливоÑтей журналу. + + [[regurl]] + +Як тільки Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ буде завершено, ви отримаєте доÑтуп до вÑÑ–Ñ… оÑновних функцій. Щоб переглÑнути Ñ—Ñ… перелік, завітайте до + + [[siteroot]]/site/accounts.bml + +Ви можете діÑтатиÑÑ Ñвого журналу за наÑтупними адреÑами: + + [[siteroot]]/users/[[username]]/ + [[siteroot]]/~[[username]]/ + +Ðижче наведено ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача на [[sitename]], Ñке Ви зареєÑтрували: + + Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[username]] + +Ці поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ Ñтати вам у нагоді: + +Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑŽÐ·ÐµÑ€Ð¿Ð¸Ðº — [[siteroot]]/editpics.bml +Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиÑу в журналі — [[siteroot]]/update.bml +Інші кориÑні поÑÐ¸Ð»Ð°Ð½Ð½Ñ — [[siteroot]]/manage/ + +Бережіть Ñвій пароль. Ми ніколи не проÑимо надіÑлати ваш пароль на електронну адреÑу й ніколи не проÑимо увійти до Ñвого рахунку, щоб подовжити його активацію. Ви не муÑите повідомлÑти Ñвій пароль будь-кому. Якщо ви захочете отримати пароль, то зможете зробити це будь-коли, завітавши за цією адреÑою: + + [[siteroot]]/lostinfo.bml + +Цей лиÑÑ‚ було Ñтворено автоматично. Якщо ви маєте ще ÑкіÑÑŒ запитаннÑ, можете прочитати Поширені Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ ж звертайтеÑÑ Ð·Ð° адреÑою: + + [[siteroot]]/support/ + +Якщо ви чи хтоÑÑŒ інший помилково Ñтворили цей рахунок, його можна видалити за адреÑою: + + [[siteroot]]/accountstatus.bml + +ЛаÑкаво проÑимо до Ñпільноти [[sitename]], наÑолоджуйтеÑÑ! + +Команда [[sitename]] +[[siteroot]]/ +. + +email.newacct3.body|notes=Updated for correct journal URL +email.newacct3.body<< +Вітаємо, тепер ви маєте новий рахунок у [[sitename]]! + +Щоб закінчити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу та перевірити вашу email-адреÑу, будь лаÑка, відвідайте наÑтупну Ñторінку. Перевірка вашої email-адреÑи допоможе нам захиÑтити ваш рахунок + + [[regurl]] + +Ваш журнал буде доÑтупний за адреÑою: + + [[journal_base]]/ + +Це зареєÑтроване вами ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + + Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[username]] + +Якщо у Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ½Ðµ потреба згадати Ñвій пароль, ви зможете зробити це в будь-Ñкий момент за адреÑою: + + [[siteroot]]/lostinfo.bml + +ÐаÑолоджуйтеÑÑŒ! + +Команда [[sitename]] +[[siteroot]]/ +. + +email.newacct4.body<< +ПоздоровленнÑ! +[[sitenameshort]] — ваш новий друг. +Чи ви любите хайку? + +ÐатиÑніть це поÑиланнÑ, щоб підтвердити Ñвою реєÑтрацію Ñ– довеÑти, +що ви — не робот (ми продовжуємо вважати роботів клаÑними): + + [[regurl]] + +(Якщо ви не можете натиÑнути на поÑиланнÑ, Ñкопіюйте його до вікна вашого +браузера.) + + +Це дані вашого рахунку: + + Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: [[username]] + Пароль: приховано — забули пароль? ([[lostinfourl]]) + + Журнал: [[journal_base]]/ + + +Допомога початківцÑм: + +* Заповніть Ñвій профіль +[[editprofileurl]] +У ньому ви можете вказати Ñвої зацікавленнÑ, напиÑати Ñка ви чудова людина +та/або додати жарти Чака ÐорріÑа. + +* Знайдіть інших за зацікавленнÑми +[[searchinterestsurl]] +Ви любите пухнаÑтих кроликів? Добре, в [[sitenameshort]] Ñ” ще 272 таких людини. + +* Завантажте юзерпики +[[editpicsurl]] +Юзерпики передають розкривають вашу думку. + +* Змінить виглÑд журналу +[[customizeurl]] +Бажаєте, щоб Ð²Ð°Ñ Ð¶ÑƒÑ€Ð½Ð°Ð» блищав Ñ– набридливо миготів? Дуже погано. Ми пропонуємо лише неепілептичні макети. + +* Створіть Ð·Ð°Ð¿Ð¸Ñ +[[postentryurl]] +Про що ви думаєте проÑто зараз? Вперед. + + + +Поетично ваша, +команда [[sitenameshort]] +[[siteroot]]/ +. + +entryform.backdated=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом: + +entryform.backdated2=Ð—Ð°Ð¿Ð¸Ñ Ð·Ð°Ð´Ð½Ñ–Ð¼ чиÑлом Ñ– не відображати на уÑÑ–Ñ… Ñтрічках друзів + +entryform.backdated3=Ðеправильна дата + +entryform.comment.screening=Приховати коментарі: + +entryform.comment.screening2=ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð²: + +entryform.comment.settings=Параметри коментарів: + +entryform.comment.settings.default=За замовчуваннÑм + +entryform.comment.settings.default2=За замовчуваннÑм (у межах журналу) + +entryform.comment.settings.default3=Дозволено (за замовчуваннÑм) + +entryform.comment.settings.default4=За налаштуваннÑми журналу ([[aopts]]) + +entryform.comment.settings.default5=За налаштуваннÑми журналу + +entryform.comment.settings.nocomments=Вимкнено + +entryform.comment.settings.noemail=Ðе надÑилати до e-mail адреÑи + +entryform.comment.settings2=Дозволити коментарі? + +entryform.date=Дата: + +entryform.date.24hournote=(24 години) + +entryform.date.edit=Змінити + +entryform.delete=Видалити Ð·Ð°Ð¿Ð¸Ñ + +entryform.delete.confirm=Чи ви впевнені, що бажаєте видалити цей запиÑ? + +entryform.deletespam=Видалити Ñ– позначити Ñк Ñпам + +entryform.deletespam.confirm=Чи ви впевнені, що бажаєте видалити цей Ð·Ð°Ð¿Ð¸Ñ Ñ– помітити його Ñк Ñпам? + +entryform.entry=ЗапиÑ: + +entryform.entry.hint=Почати Ñвій Ð·Ð°Ð¿Ð¸Ñ + +entryform.format=Ðвтоформатувати HTML: + +entryform.format.auto=Так, поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñ‚Ð° нові Ñ€Ñдки + +entryform.format.preformatted=ÐÑ– + +entryform.format2=Конвертувати переноÑи Ñ€Ñдків + +entryform.format3=Заборонити Ð°Ð²Ñ‚Ð¾Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +entryform.htmlokay.norich=(HTML дозволено; за замовчуваннÑм нові Ñ€Ñдки будуть автовідформатовані на <br>.) + +entryform.htmlokay.norich2=(HTML дозволено; за замовчуваннÑм нові Ñ€Ñдки будуть автовідформатовані на <br>.) + +entryform.htmlokay.rich=(HTML дозволено; нові Ñ€Ñдки будуть автовідформатовані на <br>; або кориÑтуйтеÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼ редактором.) + +entryform.htmlokay.rich2=(HTML дозволено; нові Ñ€Ñдки будуть автовідформатовані на <br>; або кориÑтуйтеÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ð¼ редактором.) + +entryform.htmlokay.rich4=Відформатований текÑÑ‚ + +entryform.htmlokay.rte_nosupport=Вибачте, ваш браузер наразі не підтримує Ñередовище форматованого текÑту.) + +entryform.insert.header=Ð’Ñтавити... + +entryform.insert.image=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +entryform.insert.image2=Ð’Ñтавити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +entryform.insert.poll=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +entryform.location=МіÑцезнаходженнÑ: + +entryform.mood=ÐаÑтрій: + +entryform.mood.noneother=Жодного або інший: + +entryform.music=Музика: + +entryform.nojstime.note=Примітка: чаÑ/дата вище - з нашого Ñервера.
    Виправте Ñ—Ñ… згідно з вашим чаÑовим поÑÑом перед тим, Ñк публікувати запиÑ. + +entryform.opt.defpic=(за замовчуваннÑм) + +entryform.options=Параметри: + +entryform.plainswitch=(ÐатиÑніть кнопку 'Source' Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ HTML. Ви також можете повернутиÑÑ Ð´Ð¾ звичайного режиму.) + +entryform.postas=Зробити Ð·Ð°Ð¿Ð¸Ñ Ñк: + +entryform.postto=ÐапиÑати до: + +entryform.preview=Попередньо переглÑнути + +entryform.save=Зберегти Ð·Ð°Ð¿Ð¸Ñ + +entryform.security=Рівень безпеки: + +entryform.security2=Показувати цей запиÑ: + +entryform.spellcheck=Перевірити Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ (тільки англійÑькою) + +entryform.spellcheck.noerrors=Помилок у правопиÑÑ– не знайдено + +entryform.spellchecked=Ð—Ð°Ð¿Ð¸Ñ Ñ–Ð· перевіреним правопиÑом: + +entryform.subject=Тема: + +entryform.subject.hint=Заголовок запиÑу + +entryform.subject.hint2=Введіть тему + +entryform.switchuser=Змінити + +entryform.tags=Теги: + +entryform.update=Оновити журнал + +entryform.update2=Зберегти в + +entryform.update3=Опублікувати в + +entryform.update4=Опублікувати Ð·Ð°Ð¿Ð¸Ñ + +entryform.userpic=Юзерпика: + +entryform.userpic.choose=Виберіть юзерпику + +entryform.userpics=Картинка кориÑтувача: + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Помилка + +error.badpassword=Ðевірний пароль. + +error.code.comm_not_comm=Рахунок не Ñ” Ñпільнотою + +error.code.comm_not_found=Спільноту не знайдено + +error.code.comm_not_member=КориÑтувач не Ñ” учаÑником цієї Ñпільноти + +error.dberror=Помилка бази даних: + +error.deleted.name=Видалено + +error.deleted.text=Цей журнал було видалено. Якщо ви Ñ” [[user]], то ви маєте 30 днів зо Ð´Ð½Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ, щоб відновити журнал. ПіÑÐ»Ñ 30 днів ми видалимо з наших Ñерверів веÑÑŒ зміÑÑ‚ журналу. + +error.deleted.title=Видалений рахунок + +error.expiredchal=Термін входу до журналу завершивÑÑ. Спробуйте ще, будь лаÑка. + +error.interest.bytes=Вибачте, вказаний вами Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” розмір [[bytes]] байтів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² [[chars_max]] Ñимволів. УÑÑ– зміни, Ñкі ви зробили в ÑпиÑку інтереÑів, не були збережені. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.bytes.chars=Вибачте, вказаний вами Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” розмір [[bytes]] байтів та [[chars]] Ñимволів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² [[bytes_max]] байтів та [[chars_max]] Ñимволів. УÑÑ– зміни, Ñкі ви зробили в ÑпиÑку інтереÑів, не були збережені. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.bytes.chars.words=Вибачте, вказаний вами Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” розмір [[bytes]] байтів, [[chars]] Ñимволів та [[words]] Ñлів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² [[bytes_max]] байтів,[[chars_max]] Ñимволів та [[words_max]] Ñлів. УÑÑ– зміни, Ñкі ви зробили в ÑпиÑку інтереÑів, не були збережені. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.chars=Вибачте, вказаний вами Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” розмір [[chars]] Ñимволів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² [[chars_max]] Ñимволів. УÑÑ– зміни, Ñкі ви зробили в ÑпиÑку інтереÑів, не були збережені. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.chars.words=Вибачте, вказаний вами Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” розмір [[chars]] Ñимволів та [[words]] Ñлів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² [[chars_max]] Ñимволів та [[words_max]] Ñлів. УÑÑ– зміни, Ñкі ви зробили в ÑпиÑку інтереÑів, не були збережені. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.excessive=Вибачте, ви вказали забагато інтереÑів. МакÑимальна кількіÑÑ‚ÑŒ - 150, але ви перечиÑлили [[intcount]]. УÑÑ– зміни, зроблені вами у ÑпиÑку інтереÑів, не було збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть кілька інтереÑів. + +error.interest.invalid=Вибачте, ви вказали Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ñ–Ð· недопуÑтимими Ñимволами. УÑÑ– зміни, зроблені вами у ÑпиÑку інтереÑів, не було збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.interest.words=Вибачте, ви вказали Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ñ–Ð· [[words]] Ñлів. Кожен Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð¼Ð°Ñ” Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñƒ [[words_max]] Ñлів. УÑÑ– зміни, зроблені вами у ÑпиÑку інтереÑів, не було збережено. ПовернітьÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– видаліть або змініть Ñ–Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° "[[int]]". + +error.invalidauth=Ð’Ð°Ñ Ð½Ðµ вдалоÑÑ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñк зазначеного кориÑтувача. + +error.invalidform=Ðевірно надіÑлано форму. Перезавантажте та Ñпробуйте ще, будь лаÑка. + +error.ipbanned=Вашу IP-адреÑу тимчаÑово заблоковано через Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ ÐºÑ–Ð»ÑŒÐºÐ¾ÑÑ‚Ñ– помилок при вході до журналу. + +error.malformeduser=Погане ім'Ñ. + +error.mediauploadsdisabled=Зміни зображень тимчаÑово не працюють. ДеÑкі або вÑÑ– можливоÑÑ‚Ñ– на цій Ñторінці наразі відключені. + +error.nobutton=Ðе натиÑнули на кнопку? + +error.nocommlogin=Вхід в ÑкоÑÑ‚Ñ– Ñпільноти було вимкнено. + +error.nodb=База даних тимчаÑово недоÑтупна. Будь лаÑка, дивітьÑÑ http://status.livejournal.org щоб дізнатиÑÑ Ð¿Ñ€Ð¾ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‰Ð¾Ð´Ð¾ Ñтану LiveJournal. + +error.nodbmaintenance=Ð¦Ñ Ñ‡Ð°Ñтина бази даних тимчаÑово зачинена на обÑлуговуваннÑ. Спробуйте ще раз за декілька хвилин. + +error.noentry=Такого запиÑу не Ñ–Ñнує. + +error.nojournal=Ðевідомий Журнал + +error.noremote=Вам потрібно увійти щоб ÑкориÑтатиÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою. + +error.notloggedin=Ви повинні увійти, щоб ÑкориÑтатиÑÑ Ñ†Ñ–Ñ”ÑŽ Ñторінкою. + +error.procrequest=Під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ запиту виникла помилка: + +error.purged.name=Видалений + +error.purged.text=Цей журнал було видалено та знищено. + +error.purged.title=Очищений рахунок + +error.suspended.name=Припинений + +error.suspended.text=Цей рахунок було або тимчаÑово, або поÑтійно припинено. Якщо ви Ñ” [[user]], то звернітьÑÑ, будь лаÑка, до ÐайчаÑтішого Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ назвою Мій рахунок було припинено! Як Ñ Ð¼Ð¾Ð¶Ñƒ його повернути?, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ. Візьміть до уваги, будь лаÑка, що з метою Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾ÑÑ‚Ñ– наших кориÑтувачів [[sitename]] не може обговорювати причини Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð· будь-ким, крім влаÑника рахунку. + +error.suspended.title=Припинений рахунок + +error.tempdisabled=ТимчаÑово відключений. + +error.unknownmode=Ðевідомий режим + +error.usernameinvalid=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача міÑтить невірні Ñимволи. + +error.usernamelong=Ім'Ñ Ð·Ð°Ð´Ð¾Ð²Ð³Ðµ, 15 Ñимволів макÑимум. + +error.username_notfound=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача не знайдено. + +fckland.ljimage=Додати/змінити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +fcklang.cutcontents=Введіть зміÑÑ‚ ÑкраданнÑ. + +fcklang.cutprompt=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° повний запиÑ? + +fcklang.invalidchars=Помилкові Ñимволи в імені кориÑтувача + +fcklang.ljcut=Ð¡ÐºÑ€Ð°Ð´Ð°Ð½Ð½Ñ LiveJournal + +fcklang.ljuser=КориÑтувач LiveJournal + +fcklang.ljvideo=Відео LiveJournal + +fcklang.ljvideo2=Вбудоване медіа + +fcklang.readmore=Читати більше + +fcklang.userprompt=Введіть Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +fcklang.videoprompt=Будь лаÑка, введіть адреÑу відео: + +feeds.link=Ñиндикативні потоки + +feeds.text=Ðапевно, Ñ” непогані речі й поза LJ? Що ж, ми надаємо змогу додати Ñиндикатні потоки до вашої Ñтрічки друзів - Ñ– вам не доведетьÑÑ Ñ—Ñ— залишати. + +friendsfriends.link=друзі друзів + +friendsfriends.text=Гей, друже, Ñтрічка [[link]] відображає вÑÑ– Ñтрічки друзів твоїх друзів у одній Ñтрічці друзів. Вимови це втричі швидше. + +Help=Допомога + +horizon.barenav.create=Створити рахунок + +horizon.barenav.explore=ОглÑд + +horizon.barenav.giftshop=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ + +horizon.barenav.post=Поновити журнал + +horizon.esn.messages=Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ + +horizon.footer.about=Про LJ + +horizon.footer.advertise=РекламодавцÑм + +horizon.footer.create=Створити безкоштовний блоґ (журнал) + +horizon.footer.options=Параметри переглÑду + +horizon.footer.privacy=Політика конфіденційноÑÑ‚Ñ– + +horizon.footer.tos=Умови викориÑÑ‚Ð°Ð½Ð½Ñ + +horizon.footer.tour=ОглÑдовий тур + +horizon.login.create=Створити рахунок + +horizon.login.forgot=Забули Ñ–Ð¼â€™Ñ Ñ‡Ð¸ пароль? + +horizon.login.openid=Увійти з OpenID + +horizon.login.password=Пароль: + +horizon.login.remember=Пам’Ñтати мене + +horizon.login.submit=Увійти + +horizon.login.username=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: + +horizon.nav.admin=Admin + +horizon.nav.admin.acctedit=Edit Account + +horizon.nav.admin.editprivs=Edit Privs + +horizon.nav.admin.editprops=Edit Props + +horizon.nav.comm=Спільноти + +horizon.nav.comm.create=Створити нову + +horizon.nav.comm.invites=Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ + +horizon.nav.comm.manage=Керувати Ñпільнотами + +horizon.nav.comm.manageinvites=Керувати запрошеннÑми + +horizon.nav.comm.post=ПиÑати до Ñпільноти + +horizon.nav.comm.postentry=Створити Ð·Ð°Ð¿Ð¸Ñ + +horizon.nav.comm.search=Шукати Ñпільноти + +horizon.nav.find=Пошук + +horizon.nav.find.browsefeeds=ПереглÑд потоків + +horizon.nav.find.bycommunity=За Ñпільнотою + +horizon.nav.find.byinterest=За інтереÑами + +horizon.nav.find.byregion=За регіоном + +horizon.nav.find.byschool=За навчальними закладами + +horizon.nav.find.explore=ОглÑд LJ + +horizon.nav.find.feeds=Знайти потоки + +horizon.nav.find.interest=Пошук за зацікавленнÑми + +horizon.nav.find.moreoptions=Більше параметрів + +horizon.nav.find.options=Більше параметрів пошуку + +horizon.nav.find.random=Випадковий журнал + +horizon.nav.find.region=Пошук за регіоном + +horizon.nav.find.school=Пошук за навч.закладом + +horizon.nav.friends=Друзі + +horizon.nav.friends.edit=Редагувати друзів + +horizon.nav.friends.editgroups=Редагувати групи друзів + +horizon.nav.friends.filter=Фільтр друзів + +horizon.nav.friends.filters=Фільтри друзів + +horizon.nav.friends.gift=Подарунок Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð° + +horizon.nav.friends.invite=ЗапроÑити нових друзів + +horizon.nav.friends.ljtalk=Базікати з друзÑми + +horizon.nav.friends.manage=Керувати ÑпиÑком друзів + +horizon.nav.friends.managegroups=Керувати групами друзів + +horizon.nav.friends.search=Шукати друзів + +horizon.nav.friends.viewfriends=Читати Ñтрічку друзів + +horizon.nav.home=Початок + +horizon.nav.journal=Журнал + +horizon.nav.journal.comments=Керувати коментарÑми + +horizon.nav.journal.customize=ВиглÑд журналу + +horizon.nav.journal.editentry=Змінити запиÑи + +horizon.nav.journal.editstyle=Змінити виглÑд журналу + +horizon.nav.journal.edittags=Змінити теґи + +horizon.nav.journal.managetags=Керувати теґами + +horizon.nav.journal.postentry=Створити Ð·Ð°Ð¿Ð¸Ñ + +horizon.nav.journal.postpoll=Створити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +horizon.nav.journal.settings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +horizon.nav.journal.viewjournal=ДивитиÑÑ Ð¶ÑƒÑ€Ð½Ð°Ð» + +horizon.nav.livejournal.contact=Зв’Ñзок з нами + +horizon.nav.livejournal.downloads=Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ + +horizon.nav.livejournal.giftshop=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ Ð¿Ð¾Ð´Ð°Ñ€ÑƒÐ½ÐºÑ–Ð² + +horizon.nav.livejournal.upgrade=Покращити рахунок + +horizon.nav.mylj=Мій LJ + +horizon.nav.photos=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +horizon.nav.photos.editgalleries=Змінити галереї + +horizon.nav.photos.editstyle=Змінити виглÑд + +horizon.nav.photos.edittaggalleries=Змінити теґи галерей + +horizon.nav.photos.edittags=Змінити теґи + +horizon.nav.photos.getmore=(Отримати більше) + +horizon.nav.photos.piccount=([[piccount]] з [[picmax]]) + +horizon.nav.photos.tagtool=Редактор теґів + +horizon.nav.photos.upload=Завантажити + +horizon.nav.photos.viewphotos=ДивитиÑÑ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +horizon.nav.photos.whatis=Що таке ScrapBook? + +horizon.nav.profile=Профіль + +horizon.nav.profile.edit=Змінити профіль + +horizon.nav.profile.manageschools=Керувати навчальними закладами + +horizon.nav.profile.manageuserpic=Керувати юзерпиками + +horizon.nav.profile.memories=Керувати вибраним + +horizon.nav.profile.memories2=Вибране + +horizon.nav.profile.schools=Змінити навч.заклади + +horizon.nav.profile.userpic=Змінити юзерпики + +horizon.nav.profile.view=ДивитиÑÑ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŒ + +horizon.nav.scrapbook.customize=Ðалаштувати ScrapBook + +horizon.nav.scrapbook.managegalleries=Керувати галереÑми + +horizon.nav.scrapbook.managetaggalleries=Керувати галереÑми з теґами + +horizon.nav.scrapbook.upload=Завантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +horizon.nav.scrapbook.view=ОглÑд зображень + +horizon.search.icq=Ðомер ICQ + +horizon.search.interest=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +horizon.search.moreopts=Більше параметрів + +horizon.search.region=Регіон + +horizon.search.site=Сайт + +horizon.search.siteuser=Сайт та кориÑтувачі + +horizon.search.submit=Шукати + +horizon.search.username=КориÑтувач + +horizon.sitemap=Міні-мапа Ñайту: + +horizon.sitemap.account_settings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +horizon.sitemap.contact=Контакти + +horizon.sitemap.downloads=Скачати + +horizon.sitemap.faqs=FAQ + +horizon.sitemap.feedback=Відгуки + +horizon.sitemap.feedbackcontact=Відгуки та Контакти + +horizon.sitemap.giftshop=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ LJ + +horizon.sitemap.manage_account=Керувати рахунком + +horizon.sitemap.more=Більше... (Мапа Ñайту) + +horizon.sitemap.news=Ðовини та Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +horizon.sitemap.opensource=Відкритий код LJ + +horizon.sitemap.policies=Ðаша політика + +horizon.sitemap.support=Підтримка + +horizon.sitemap.supportfaqs=Підтримка та FAQs + +horizon.sitemap.upgrade=Покращити + +horizon.sitemap.volunteer=Стати волонтером + +horizon.userpic.upload=Додати юзерпику + +horizon.welcome.account=Рахунок + +horizon.welcome.friends=Стрічка друзів + +horizon.welcome.help=Допомога + +horizon.welcome.invite=ЗапроÑити + +horizon.welcome.logout=Вихід + +horizon.welcome.mobile=Мобільний + +horizon.welcome.post=ÐапиÑати + +img.btn_del=Видалити + +img.btn_down=Вниз + +img.btn_freeze=Заморозити + +img.btn_scr=Сховати + +img.btn_unfreeze=Розморозити + +img.btn_unscr=Показати + +img.btn_up=Вгору + +img.editentry=Змінити Ð·Ð°Ð¿Ð¸Ñ + +img.edittags=Змінити теґи + +img.ins_obj=Ð’Ñтавити зображеннÑ/об’єкт + +img.memadd=У вибране! + +img.next_entry=ÐаÑтупний Ð·Ð°Ð¿Ð¸Ñ + +img.placeholder=Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +img.prev_entry=Попередній Ð·Ð°Ð¿Ð¸Ñ + +img.tellfriend=Розкажи другові! + +img.track=ВідÑлідковувати + +img.track_active=ВідÑлідковувати + +img.track_thread_active=ВідÑлідковувати + +img.xml=Джерело XML + +label.screening.all=Ð’ÑÑ– коментарі + +label.screening.all2=Ð’ÑÑ– коментарі + +label.screening.anonymous=Тільки анонімні + +label.screening.anonymous2=Тільки Ð´Ð»Ñ Ð°Ð½Ð¾Ð½Ñ–Ð¼Ñ–Ð² + +label.screening.default=За замовчуваннÑм + +label.screening.default2=За замовчуваннÑм (налаштуваннÑми журналу) + +label.screening.default3=За налаштуваннÑми журналу ([[aopts]]) + +label.screening.default4=За налаштуваннÑми журналу + +label.screening.header=Приховані коментарі: + +label.screening.none=Жодні + +label.screening.none2=Вимкнено + +label.screening.nonfriends=Від не друзів + +label.screening.nonfriends2=Ð’ÑÑ–, крім друзів + +label.security.custom=ОÑобливий... + +label.security.friends=Тільки Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð² + +label.security.head=Рівень безпеки: + +label.security.maintainers=ÐаглÑдачі + +label.security.members=УчаÑники + +label.security.private=Приватний + +label.security.private2=Тільки Ð´Ð»Ñ Ð¼ÐµÐ½Ðµ (приватно) + +label.security.public=Публічний + +label.security.public2=Ð”Ð»Ñ Ð²ÑÑ–Ñ… (загальнодоÑтупно) + +label.switch.button=Переключити + +label.switch.header=Переключити журнал + +label.switch.workwith=Працювати з журналом: + +label.warning=Увага: + +langname.be=БілоруÑька + +langname.da=ДанÑька + +langname.de=Ðімецька + +langname.en=ÐнглійÑька + +langname.en_GB=ÐнглійÑька, Ð’ÐµÐ»Ð¸ÐºÐ¾Ð±Ñ€Ð¸Ñ‚Ð°Ð½Ñ–Ñ + +langname.en_LJ=ÐнглійÑька + +langname.eo=ЕÑперанто + +langname.es=ІÑпанÑька + +langname.et=ЕÑтонÑька + +langname.fi=ФінÑька + +langname.fr=Французька + +langname.ga=ІрландÑька + +langname.gd=ГельÑька + +langname.gr=Грецька + +langname.he=Іврит + +langname.hi=Хінді + +langname.hu=УгорÑька + +langname.is=ІÑландÑька + +langname.it=ІталійÑька + +langname.ja=ЯпонÑька + +langname.la=ЛатинÑька + +langname.lt=ЛитовÑька + +langname.lv=ЛатиÑька + +langname.ms=МалайÑька + +langname.nb=Ðорвезька BokmÃ¥l + +langname.nl=ГолландÑька + +langname.nn=Ðорвезька Nynorsk + +langname.pl=ПольÑька + +langname.pt=ПортугальÑька + +langname.pt_BR=БразильÑка португальÑка + +langname.ru=РоÑійÑька + +langname.sb=СибирÑка + +langname.sv=ШведÑька + +langname.tr=Турецька + +langname.uk=УкраїнÑька + +langname.zh=КитайÑька Ñпрощена + +langname.zh_TR=КитайÑька традиційна + +lanzelot.item.all_stats=Повна ÑтатиÑтика LJ + +lanzelot.item.friends=Друзі + +lanzelot.item.ljplus.counter=Лічильник + +lanzelot.item.ljplus.photo=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ‚Ð¾ + +lanzelot.item.mylj=Мій LJ + +lanzelot.item.postlj=Створити Ð·Ð°Ð¿Ð¸Ñ + +lanzelot.item.tshorts=Футболки + +lanzelot.mobile.LJ=LJ Ð´Ð»Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¸Ñ… приÑтроїв + +lanzelot.mobile.settings=Мобільні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +lanzelot.search.example=журнали + +lanzelot.search.example_title=Ðаприклад + +lanzelot.search.internet=інтернеті + +lanzelot.search.submit=Знайти! + +lanzelot.search.where=Шукати в + +ljcom.account.basic=Базовий рахунок + +ljcom.account.choose=Виберіть тип рахунку + +ljcom.account.feature=МожливіÑÑ‚ÑŒ + +ljcom.account.feature.customize=Створіть та налаштуйте виглÑд та Ð²Ñ–Ð´Ñ‡ÑƒÑ‚Ñ‚Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ журналу + +ljcom.account.feature.email=E-mail адреÑа на LiveJournal + +ljcom.account.feature.full2=Повну таблицю можна побачити тут. + +ljcom.account.feature.limit=обмежено + +ljcom.account.feature.mobile=Пишіть до Ñвого журналу за допомогою телефону або мобільного приÑтрою, навіть коли ви не поруч зі Ñвоїм комп'ютером. + +ljcom.account.feature.nobanners=Жодних банерів або виринаючих вікон + +ljcom.account.feature.ownblog=Ваш влаÑний журнал/веблоґ + +ljcom.account.feature.photo=Інтегрований хоÑтинґ фотографій 100MiB + +ljcom.account.feature.pp=ÐŸÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð¾Ð¼ + +ljcom.account.feature.scrapbook=Показуйте та ÑиÑтематизуйте Ñвої Ñвітлини викориÑтовуючи Ðльбом та [[space]] МБ диÑкового проÑтору + +ljcom.account.feature.search=Пошук у каталозі + +ljcom.account.feature.search2=ВикориÑтовуйте розширені можливоÑÑ‚Ñ– пошуку Ð´Ð»Ñ Ð·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів по міÑту, регіону, країні, віку, друзÑм + +ljcom.account.feature.styles=СтвореннÑ/Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñтилів + +ljcom.account.feature.syn=Збирач друзів Ñ– транÑльованих живлень + +ljcom.account.feature.userpic=Завантажте кілька юзерпик, Ñкі з'ÑвлÑтимутьÑÑ Ð¿Ð¾Ñ€Ñд із вашими запиÑами та коментарÑми + +ljcom.account.free=Базовий рахунок (безкоштовно) + +ljcom.account.onlyautomatic=Ці ціни діють тільки Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків з автоматичною оплатою. + +ljcom.account.paid=Платний рахунок + +ljcom.account.paid.desc=Менш ніж за $2/міÑÑць*, влаÑники платного рахунку отримають повний набір першоклаÑних можливоÑтей!
    Отримайте більше юзерпик, більше диÑкового проÑтору, доÑтуп до вÑÑ–Ñ… Ñтилів,
    розширеного пошуку та іншого - Ñ– вÑе це за ціною ранкової філіжанки кави! + +ljcom.account.paid.price=Платний рахунок (від 2 доларів СШРна міÑÑць) + +ljcom.account.paid12=Оплачений на 12 міÑÑців ($25 USD) + +ljcom.account.paid2=Оплачений на 2 міÑÑці ($5 USD) + +ljcom.account.paid6=Оплачений на 6 міÑÑців ($15 USD) + +ljcom.account.plus=Розширений рахунок (безкоштовно) + +ljcom.account.plus3=Розширений рахунок (безкоштовно) + +ljcom.accounttype=Тип рахунку + +ljcom.acct.free=Базовий + +ljcom.acct.free.cost=ВартіÑÑ‚ÑŒ: безкоштовно + +ljcom.acct.free.intro=МожливоÑÑ‚Ñ– базового журналу та: + +ljcom.acct.free.line1=[[pics]] юзерпик (уоÑоблені іконки) + +ljcom.acct.paid=Платний + +ljcom.acct.paid.cost=ВартіÑÑ‚ÑŒ: мінімальна - $19,95* за рік
    (це менше, ніж $2/міÑÑць) + +ljcom.acct.paid.line1=[[pics]] юзерпик (уоÑоблені іконки) + +ljcom.acct.paid.line2=[[space]] ÒБ диÑкового проÑтору + +ljcom.acct.paid.line3=Мобільні запиÑи з фотографіÑми, текÑтом та звуком + +ljcom.acct.paid.line4=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñƒ журналу + +ljcom.acct.paid.note=* ці ціни доÑтупні лише Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків з автоматичною оплатою. + +ljcom.acct.plus=Розширений + +ljcom.acct.plus.cost=ВартіÑÑ‚ÑŒ: безкоштовно, з рекламою + +ljcom.acct.plus.intro=ПершоклаÑні можливоÑÑ‚Ñ– та: + +ljcom.acct.plus.line1=[[pics]] юзерпик (уоÑоблені іконки) + +ljcom.acct.plus.line2=[[space]] Òб диÑкового проÑтору + +ljcom.acct.plus.line3=Мобільні запиÑи з фотографіÑми, текÑтом та звуком + +ljcom.adlayoutblurb.header=Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ + +ljcom.adlayoutblurb.text=ВлаÑники розширеного рахунку можуть обрати Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€ÐµÐºÐ»Ð°Ð¼Ð¸ у Ñвоєму журналі та у Ñтрічці друзів. Завітайте на Ñторінку рекламних налаштувань Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð½Ð½Ñ Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð½Ð°Ð³Ð¾Ñ€Ñ– чи внизу, або вертикального - ліворуч чи праворуч. + +ljcom.allpicsupsell=Ви можете бути зацікавлені у зміні ключових Ñлів до ваших юзерпик або завантаженні нових юзерпик. Також ви можете збільшити кількіÑÑ‚ÑŒ можливих юзерпик. + +ljcom.badpass.ascii=Ваш пароль повинен міÑтити тільки Ñимволи ASCII + +ljcom.badpass.common=Пароль, Ñхожий до вашого, дуже чаÑто вживаєтьÑÑ. + +ljcom.badpass.displayname=Ваш пароль не може бути заÑновано на вашому призвіÑьку. + +ljcom.badpass.distinct=Ваш пароль повинен міÑтити щонайменше 4 різних Ñимвола. + +ljcom.badpass.email=Ваш пароль не може базуватиÑÑ Ð½Ð° вашій адреÑÑ– елктронної пошти. + +ljcom.badpass.length=Ваш пароль повинен міÑтити щонайменше 6 Ñимволів. + +ljcom.badpass.onlyalpha=Ваш пароль повинен міÑтити принаймні одну цифру чи Ñимвол. + +ljcom.badpass.username=Ваш пароль не може базуватиÑÑ Ð½Ð° вашому імені кориÑтувача. + +ljcom.badpass.username.reverse=Ваш пароль не може бути заÑновано на вашому імені кориÑтувача, напиÑаному ззаду наперед. + +ljcom.control_panel.free=Щоб отримати доÑтуп до першоклаÑних можливоÑтей, безкоштовно переключітьÑÑ Ð½Ð° Розширений рахунок або придбайте Платний рахунок. + +ljcom.control_panel.paid=Докладну інформацію про ÑервіÑи [[sitename]], на Ñкі ви зараз підпиÑані, ви знайдете на Ñторінці Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ рахунку. + +ljcom.control_panel.plus=Отримайте першоклаÑні можливоÑÑ‚Ñ– змінивши тип Ñвого рахунку. + +ljcom.customizeupgradenotice.basiclayout=Отримайте більше Ñхем безкоштовно обравши Розширений рахунок. + +ljcom.customizeupgradenotice.basictheme=Отримайте більше тем безкоштовно обравши Розширений рахунок. + +ljcom.customizeupgradenotice.pluslayout=Отримайте доÑтуп до вÑÑ–Ñ… Ñхем з Платним рахунком. + +ljcom.customizeupgradenotice.plustheme=Отримайте доÑтуп до вÑÑ–Ñ… тем з Платним рахунком. + +ljcom.editpicsupsell.free=Якщо ви бажаєте більше юзерпик, переключитьÑÑ Ð½Ð° Розширений рахунок або придбайте Платний рахунок. + +ljcom.editpicsupsell.paid=Придбати додаткові юзерпики + +ljcom.editpicsupsell.plus=Придбайте платний рахунок Ð´Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñ— кількоÑÑ‚Ñ– юзерпик + +ljcom.entryform.box.download=Скачати клієнтÑьку програму + +ljcom.entryform.box.download.header=Скачати клієнтÑьку програму + +ljcom.entryform.box.download.others=Інші… + +ljcom.entryform.box.ljtalk=Скачати Gizmo/LJ Talk + +ljcom.entryform.box.paidoptions.createpoll=Створити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +ljcom.entryform.box.paidoptions.emailpost=ЗапиÑи з мобільного + +ljcom.entryform.box.paidoptions.header=Інші можливоÑÑ‚Ñ–: + +ljcom.entryform.box.paidoptions.header2=Інші ÑпоÑоби публікації: + +ljcom.entryform.box.paidoptions.ljtalk=Скачати Gizmo/LJ Talk + +ljcom.entryform.box.paidoptions.ljtalk.download=Скачати Gizmo/LJ Talk + +ljcom.entryform.box.paidoptions.ljtalk.post2=Миттєві Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +ljcom.entryform.box.paidoptions.mobilepost=ЗапиÑи з мобільного + +ljcom.entryform.box.paidoptions.voicepost=ГолоÑові запиÑи + +ljcom.entryform.box.paidoptions.voicepost2=ГолоÑові запиÑи + +ljcom.extra_privacy_options.vgifts=Віртуальні подарунки + +ljcom.extra_privacy_options.vgifts.disable=ВідхилÑти віртуальні подарунки + +ljcom.extra_privacy_options.vgifts.disable.all=ВідхилÑти уÑÑ– + +ljcom.extra_privacy_options.vgifts.disable.none=Ðе відхилÑти + +ljcom.extra_privacy_options.vgifts.disable.note=КориÑтувачі з розширеним рахунком не можуть відхилÑти лише ÑпонÑоровані віртуальні подарунки. + +ljcom.extra_privacy_options.vgifts.disable.sponsored=ВідхилÑти лише ÑпонÑоровані + +ljcom.interests.sponsored.head=Підтримувані Ñпільноти + +ljcom.lj-replace.first_post<< +

    У вашому журналі ще немає запиÑів. Почніть із Ð¾Ð¿ÑƒÐ±Ð»Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу чи зміни Ñтилю Ñвого журналу.

    + +

    Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð´Ð¾Ñтупом:

    + +

    - Публікуйте приватно: Така позначка Ð±Ñ–Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу означає, що бачите його лише ви.

    + +

    - Публікуйте лише Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·Ñ–Ð²: Позначка у виглÑді замка означає, що запиÑу можуть побачити лише кориÑтувачі, Ñких ви додали у ÑпиÑок друзів. Ви також можете Ñтворити оÑобливі групи друзів Ñ– обрати, Ñка з цих груп може бачити ваш запиÑ.

    + +

    Люди, Ñкі додали Ð²Ð°Ñ Ñƒ ÑпиÑок друзів, бачитимуть ваші запиÑи у Ñвоїй Ñтрічці друзів, Ñкщо ви ваші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†Ðµ не заборонÑÑŽÑ‚ÑŒ.

    + +

    +Створюючи запиÑ, ви можете викориÑтовувати LJ-Cut щоб Ñховати вÑе під поÑиланнÑм. Це зручно викориÑтовувати у доÑить великих запиÑах, приховуванні Ñпойлерів Ñ– чаÑто викориÑтовуєтьÑÑ Ñк знак поваги та хорошого тону, щоб ваші запиÑи не займали уÑÑŽ Ñтрічку друзів вашого друга. + +

    ІÑнує кілька ÑпоÑобів Ñтворити запиÑ:
    +ГолоÑовий Ð·Ð°Ð¿Ð¸Ñ - Розкажіть Ñвій Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾ телефону Ñ– ми магічним ÑпоÑобом розміÑтимо Ð°ÑƒÐ´Ñ–Ð¾Ð·Ð°Ð¿Ð¸Ñ Ñƒ вашому журналі.
    +Ð—Ð°Ð¿Ð¸Ñ Ð· мобільного - Публікуйте фотографії та текÑти зі Ñвого мобільного телефону.
    +TxtLJ - Керуйте та публікуйте за допомогою текÑтових повідомлень.
    +LJ Talk - Робіть запиÑи до Ñвого журналу через Ñлужбу миттєвих повідомлень LiveJournal. +

    +

    +. + +ljcom.lj-replace.first_post.friends<< +

    Це ваша Ñторінка друзів. Щоразу, коли з’ÑвлÑÑŽÑ‚ÑŒÑÑ Ð½Ð¾Ð²Ñ– запиÑи у журналах ваши друзів або у Ñпільнотах, до Ñких ви приєдналиÑÑŒ, вони будуть відображатиÑÑŒ на цій Ñторінці. Вважайте цю функцію збирачем уÑÑ–Ñ… цікавих Ð´Ð»Ñ Ð²Ð°Ñ Ñ€ÐµÑ‡ÐµÐ¹, а також ÑпоÑобом бути в курÑÑ– Ñправ ваших друзів.

    + +

    ОÑÑŒ короткий оглÑд типів кориÑтувачів, Ñких ви можете додати до друзів. ÐатиÑнувши на значок порÑд із іменем кориÑтувача, ви перейдете прÑмо до його профілю. Щоб додати друга, проÑто перейдіть до його профілю Ñ– натиÑніÑÑ‚ÑŒ на такий значок.

    + +

    - кориÑтувачі з таким значком із зображеннÑм голови порÑд із іменем кориÑтувача Ñ” індивідуальними кориÑтувачами, Ñк Ñ– ви. Дехто з них цікавий, дехто нудний, а решта Ñ” проÑто шаленими (ми попереджаємо). Продовжуємо. Знайдіть друзів за інтереÑами або навчальними закладами.

    + +

    - Це значок означає, що відповідний журнал Ñ” Ñпільнотою. Люди можуть приєднатиÑÑŒ Ñ– робити запиÑи в Ñпільноті, що чудово ÑприÑÑ” обговореннÑм, обміну інформацією тощо. Знайдіть Ñпільноти за інтереÑами або переглÑдайте Родзинки LJ.

    + +

    - Ð¦Ñ Ñ–ÐºÐ¾Ð½ÐºÐ° означає потік. Потоки формуютьÑÑ Ñ–Ð· запиÑів на інших Ñайтах. Ми підтримуємо потоки RSS та Atom, тому доÑить багато Ñайтів, Ñкі надають потоки можуть бути додані Ñ– ви зможете бучити Ñ—Ñ… на Ñвоїй Ñторінці друзів. ПереглÑньте найбільш популÑрні потоки у LiveJournal.

    + +

    ДоÑÑ– не знаєте з чого почати?

    + +. + +ljcom.login.post_login_news<< +

    Ðалаштуйте ÑповіщеннÑ!

    +

    СпілкуйтеÑÑ Ð· друзÑми через LJ Talk

    +

    Робіть запиÑи через TxtLJ

    +. + +ljcom.login.post_login_news.header=Читайте оÑтанні новини LJ + +ljcom.meetup.head=ЗуÑтрічаймоÑÑ! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Міжнародний день зуÑтрічей [[name]] + +ljcom.meetup.moreinfo=(детальніше) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Бажаєте зуÑтріти в реальному житті людей з вашого регіону, щоб обговорити це зацікавленнÑ? Прочитайте про [[link]]! + +ljcom.menu.upgrade=Зробити рахунок платним + +ljcom.mini_matrix.comparisonchart=ДивітьÑÑ Ð¿Ð¾Ð²Ð½Ðµ порівнÑÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾Ñтей різних рахунків + +ljcom.mini_matrix.extrauserpics=КориÑтувачі платних рахунків починають із [[num]] [[?num|юзерпики|юзерпик]] Ñ– можуть заробити більше у програмі "Юзерпики лоÑльноÑÑ‚Ñ–" чи придбати додаткові 100 юзерпик. + +ljcom.mini_matrix.table.adfree=Без реклами + +ljcom.mini_matrix.table.adsupported=За підтримки реклами + +ljcom.mini_matrix.table.cost=ВартіÑÑ‚ÑŒ + +ljcom.mini_matrix.table.custom_styles=Створити оÑобиÑÑ‚Ñ– Ñтилі журналу + +ljcom.mini_matrix.table.directory=КориÑтуйтеÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŽ розширеного пошуку, щоб знайти кориÑтувачів за міÑтом, облаÑÑ‚ÑŽ, країною, віком, друзÑми + +ljcom.mini_matrix.table.feature.limited=Обмежено + +ljcom.mini_matrix.table.free=Безкоштовно + +ljcom.mini_matrix.table.free.header=Базовий + +ljcom.mini_matrix.table.ljtalk2=КориÑтуйтеÑÑ LJ Talk Ð´Ð»Ñ Ð¼Ð¸Ñ‚Ñ‚Ñ”Ð²Ð¸Ñ… повідомлень з LJ-друзÑми та іншими кориÑтувачами Jabber + +ljcom.mini_matrix.table.paid.cost=Від 2 доларів на міÑÑць + +ljcom.mini_matrix.table.paid.header=Платний + +ljcom.mini_matrix.table.planned=ПлануєтьÑÑ + +ljcom.mini_matrix.table.polls=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñобливих опитувань у Ñвоєму журналі + +ljcom.mini_matrix.table.popfeatures.header=ÐайпопулÑрніші можливоÑÑ‚Ñ– + +ljcom.mini_matrix.table.post_email1=ВідправлÑйте фотографії та текÑтові запиÑи до вашого журналу за допомогою мобільних приÑтроїв + +ljcom.mini_matrix.table.scrapbook=Показуйте та упорÑдковуйте Ñвої фотографії за допомогою ScrapBook + +ljcom.mini_matrix.table.styles=Створіть та налаштуйте дизайн вашого журналу + +ljcom.mini_matrix.table.userpics=Завантажуйте різні юзерпики, Ñкі з’ÑвлÑÑŽÑ‚ÑŒÑÑ Ð±Ñ–Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ вашого запиÑу Ñ– ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ + +ljcom.moodtheme_upsell.bored=СтомилиÑÑŒ [[img]] від необхідноÑÑ‚Ñ– вибору? + +ljcom.moodtheme_upsell.creative=Відчуваєте натхненнÑ? [[img]] + +ljcom.moodtheme_upsell.original=Хочете оригінальну [[img]] тему наÑтроїв Ð´Ð»Ñ Ñвого журналу? + +ljcom.moodtheme_upsell.text1=[[sitename]] дає вам можливіÑÑ‚ÑŒ Ñтворювати та змінювати влаÑні теми наÑтроїв Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 150 різних наÑтроїв. Це так Ñамо проÑто, Ñк Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ до [[fb_sitename]] чи файлового хоÑтинга, Ñкий дозволÑÑ” віддалене Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð¾ [[sitenameabbrev]]. + +ljcom.moodtheme_upsell.text2=Ð¦Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ñ–ÑÑ‚ÑŒ доÑтупна лише Ð´Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¾Ð³Ð¾ та платного/поÑтійного рахунків. Ðби покращити рахунок, натиÑніть тут. + +ljcom.small_matrix.basic=Базовий рахунок + +ljcom.small_matrix.feature.basic=МожливоÑÑ‚Ñ– базового журналу + +ljcom.small_matrix.feature.custom=Розширені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñтилю + +ljcom.small_matrix.feature.disk_quota=Фото + +ljcom.small_matrix.feature.mobile=ЗапиÑи з мобільного + +ljcom.small_matrix.feature.userpic=Юзерпики + +ljcom.small_matrix.free=БЕЗКОШТОВÐО + +ljcom.small_matrix.none=Ðема + +ljcom.small_matrix.paid=Платний рахунок + +ljcom.small_matrix.plus=Розширений рахунок + +ljcom.small_matrix.plus.note=(з рекламою) + +ljcom.small_matrix.viewfull=ПодивитиÑÑ Ð¿Ð¾Ð²Ð½Ñƒ порівнÑльну таблицю + +ljcom.userinfo.accounttype=Тип рахунку + +ljcom.userinfo.paiduser=Платний кориÑтувач + +ljcom.userinfo.types.early=Ранній кориÑтувач + +ljcom.userinfo.types.free=Базовий рахунок + +ljcom.userinfo.types.paid=Платний рахунок + +ljcom.userinfo.types.paid_early=Платний рахунок раннього кориÑтувача + +ljcom.userinfo.types.paid_early_expiring=Платний рахунок раннього кориÑтувача, закінчуєтьÑÑ [[paiduntil]] + +ljcom.userinfo.types.paid_expiring=Платний рахунок, закінчуєтьÑÑ [[paiduntil]] + +ljcom.userinfo.types.permanent=ПоÑтійний рахунок + +ljcom.userinfo.types.permanent_early=ПоÑтійний рахунок раннього кориÑтувача + +ljcom.userinfo.types.plus=Розширений рахунок + +ljcom.userinfo.types.plus_early=Розширений рахунок раннього кориÑтувача + +ljfeedback.text=Любиш голоÑувати? ПриєднуйÑÑ Ð´Ð¾ [[journal]], де ми проводимо Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° доÑлідженнÑ, Ñкі допомогають впливати та покращувати LJ. + +ljlib.pageofpages=Сторінка [[page]] з [[total]] + +ljru.nav.celebrities=ЗнаменитоÑти + +ljru.nav.communities=СообщеÑтва + +ljru.nav.ljru=.RU + +ljru.nav.photo=Фото + +ljru.nav.ratings=Рейтинги + +ljru.nav.themes=Темы + +ljspotlight.text=Ми відÑтежуємо цікаві Ñпільноти. ДивітьÑÑ [[journal]], щоб дізнатиÑÑ Ð¿Ñ€Ð¾ найцікавіше у LJ. + +ljtips.text=Ви зацікавлені в інших чудових порадах на зразок цієї, [[user]]? Тоді рушайте до [[journal]]! + +lostinfo.head=ЩоÑÑŒ забули? + +lostinfo.text2=Якщо ви забули Ñвої ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або пароль, відновіть Ñ—Ñ… тут. + +lynx.nav.friends=Друзі + +lynx.nav.help=Технічна підтримка + +lynx.nav.home=Початок + +lynx.nav.login=Увійти + +lynx.nav.logout=Вийти + +lynx.nav.recent=ОÑтанні запиÑи + +lynx.nav.search=Пошук + +lynx.nav.sitemap=Мапа Ñайту + +lynx.nav.siteopts=Параметри переглÑду + +lynx.nav.update=Оновити журнал + +number.punctuation=  + +Password=пароль + +password.max30=Паролі не можуть міÑтити більш ніж 30 Ñимволів + +pay.blurb.bonus.text=Бажаєте мати більше юзерпик, робити запиÑи з телефону чи завантажити більше картинок? Додайте більше можливоÑтей до Ñвого рахунку! + +pay.blurb.dyk.autopay.feature1=Лише раз введіть платіжні дані Ñ– вÑе інше ми зробимо за Ð²Ð°Ñ + +pay.blurb.dyk.autopay.feature2=Уникніть Ñкладнощів ручного Ð¿Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ + +pay.blurb.dyk.autopay.feature3=Оберіть чаÑтоту оплати (щоміÑÑцÑ, щороку, тощо) + +pay.blurb.dyk.autopay.feature4=Вмикайте та вимикайте автоматичну оплату коли завгодно + +pay.blurb.dyk.autopay.intro=Ви можете налаштувати автоматичну оплату Ð´Ð»Ñ Ñвого платного рахунку. + +pay.blurb.dyk.autopay.signup=Оберіть нашу найкращу пропозицію - щорічний план лише за [[price]] на рік + +pay.blurb.dyk.header=Чи знаєте ви...? + +pay.blurb.giftshop.text=Завітайте до крамниці [[sitename]], щоб придбати подарунки, Ñувеніри, знаки перейменуваннÑ, платні рахунки та інше. + +pay.blurb.tryit.text=Купуєте подарунок? Можливо, ви ще не готові це зробити. Перевірте це на Ñобі. + +pay.blurb.whyautopay.feature1=Лише раз введіть платіжні дані Ñ– вÑе інше ми зробимо за Ð²Ð°Ñ + +pay.blurb.whyautopay.feature2=Уникніть Ñкладнощів ручного поновленнÑ. + +pay.blurb.whyautopay.feature3=Вмикайте та вимикайте автоматичну оплату коли завгодно. + +pay.blurb.whyautopay.header=Ðавіщо обирати автоматичну оплату? + +pay.cart.amount=КількіÑÑ‚ÑŒ + +pay.cart.btn.checkout=Перевірити + +pay.cart.btn.continueshopping=Продовжити покупки + +pay.cart.btn.remove=Видалити обране + +pay.cart.giftcert.gen=Загальний подарунковий Ñертифікат: + +pay.cart.giftcert.int=Віртуальний подарунковий Ñертифікат: + +pay.cart.giftcert.tan=Матеріальний подарунковий Ñертифікат: + +pay.cart.item=Товар + +pay.cart.item.anon=, анонімно + +pay.cart.item.coppa=Перевірка віку (Ð´Ð»Ñ COPPA) + +pay.cart.item.coupon=Подарунковий Ñертифікат + +pay.cart.item.diskquota=ДиÑковий проÑÑ‚Ñ–Ñ€ + +pay.cart.item.none=(немає позицій) + +pay.cart.item.paidacct=Платний рахунок + +pay.cart.item.perm=ПоÑтійний рахунок + +pay.cart.item.rename=Код Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +pay.cart.item.shipping=ВартіÑÑ‚ÑŒ доÑтавки + +pay.cart.item.tobedelivered=, доÑтавити до [[date]] + +pay.cart.item.userpic=Додаткові юзерпики + +pay.cart.item.vgift=Віртуальний подарунок + +pay.cart.method_group.fast=Займає кілька хвилин... + +pay.cart.method_group.slow=Займає кілька днів... + +pay.cart.note.adjustemail=КориÑтувачі AOL: Щоб уникнути труднощів при отриманні Ñвоїх кодів Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½Ð²Ð°Ð½Ð½Ñ Ñ–/або подарункових Ñертифікатів, проÑимо вÑтановити ваші поштові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ від [[accountsemail]]. + +pay.cart.note.coppa=ЗауваженнÑ: ОÑкільки ваш кошик міÑтить товар, що підлÑгає COPPA, ви повинні розрахуватиÑÑ ÐºÑ€ÐµÐ´Ð¸Ñ‚Ð½Ð¾ÑŽ карткою. + +pay.cart.note.minpayment=Увага: Готівка, чеки та грошові перекази недоÑтупні Ð´Ð»Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½ÑŒ менше [[amount]]. + +pay.cart.note.unusedgencoupon=Увага: Ви викориÑтали [[amtused]] з вартоÑÑ‚Ñ– універÑальних подарункових Ñертифікатів. Проте [[amtunused]] залишаютьÑÑ Ð½ÐµÐ²Ð¸ÐºÐ¾Ñ€Ð¸Ñтаними. Якщо ви бажаєте оформити Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ð°Ð·, [[amtunused]] буде втрачено! + +pay.cart.note.unusedintcoupon=Увага: Ви викориÑтали [[amtused]] з вартоÑÑ‚Ñ– подарункових Ñертифікатів, Ñкі придатні лише Ð´Ð»Ñ Ð²Ñ–Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð¸Ñ… замовлень, таких Ñк, наприклад, платний рахунок чи додаткові можливоÑÑ‚Ñ–. Проте [[amtunused]] залишаютьÑÑ Ð½ÐµÐ²Ð¸ÐºÐ¾Ñ€Ð¸Ñтаними. Якщо ви бажаєте оформити Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ð°Ð·, [[amtunused]] буде втрачено! + +pay.cart.note.unusedtancoupon=Увага: Ви викориÑтали [[amtused]] з вартоÑÑ‚Ñ– подарункових Ñертифікатів, Ñкі придатні лише Ð´Ð»Ñ Ñ€ÐµÐ°Ð»ÑŒÐ½Ð¸Ñ… замовлень, таких Ñк, наприклад, футболки. Проте [[amtunused]] залишаютьÑÑ Ð½ÐµÐ²Ð¸ÐºÐ¾Ñ€Ð¸Ñтаними. Якщо ви бажаєте оформити Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ñ€Ð°Ð·, [[amtunused]] буде втрачено! + +pay.cart.paymentmethod=Вид розрахунку: + +pay.cart.paymentmethod.cash=Готівка + +pay.cart.paymentmethod.cc=Кредитна картка + +pay.cart.paymentmethod.check=Чек + +pay.cart.paymentmethod.moneyorder=Поштовий переказ + +pay.cart.paymentmethod.sup_sms=SMS (РоÑÑ–Ñ) + +pay.cart.paymentmethod.sup_yandex=Yandex Money (РоÑÑ–Ñ) + +pay.cart.recipient=Отримувач + +pay.cart.subtotal=ПідÑума: + +pay.cart.total=Ð’Ñього ($ СШÐ) + +pay.cart.type=Тип + +pay.cc.form.address.label=ÐдреÑа платника: + +pay.cc.form.btn.coppaconfirm=Ви погоджуєтеÑÑŒ із COPPA? + +pay.cc.form.btn.finish=Закінчити + +pay.cc.form.cardexpires.label=ДійÑна до: + +pay.cc.form.cardnumber.label=Ðомер картки: + +pay.cc.form.cardtype.label=Тип картки: + +pay.cc.form.city.label=МіÑто: + +pay.cc.form.country.label=Країна платника: + +pay.cc.form.cvv2.info=що це? + +pay.cc.form.cvv2.label=Ðомер перевірки картки: + +pay.cc.form.email.label=Email-адреÑа: + +pay.cc.form.name.label=Ð†Ð¼â€™Ñ Ð½Ð° картці + +pay.cc.form.note=Зауважте, що уÑÑ– платежі здійÑнюютьÑÑ Ð½ÐµÐ³Ð°Ð¹Ð½Ð¾ Ñ– не повертаютьÑÑ. + +pay.cc.form.postalcode.label=Поштовий індекÑ: + +pay.cc.form.state.label=Штат / ПровінціÑ: + +pay.cc.form.state.other=(Інший) + +pay.cc.form.state.uscanadaonly=(Вкажіть лише Ð´Ð»Ñ Ð¡Ð¨Ð Ñ‡Ð¸ Канади) + +pay.cc.validate.address=Будь лаÑка, введіть правильну адреÑу утримувача картки. + +pay.cc.validate.cardexpires=Будь лаÑка, вкажіть картку із незавершеним терміном дії. + +pay.cc.validate.cardnumber=Введено неправильний номер кредитної картки, Ðомер картки [[cardtype]] повинен мати довжину [[num]] [[?num|digit|digits]] цифр. + +pay.cc.validate.cardtype=Вибрано неправильний тип кредитної картки, [[cardtype]]. + +pay.cc.validate.country=Будь лаÑка, виберіть країну + +pay.cc.validate.cvv2=Введено некоректний номер CVV2. [[cardtype]] має [[num]]-цифровий номер CVV2. + +pay.cc.validate.name=Будь лаÑка, введіть повне Ñ–Ð¼â€™Ñ Ð²Ð»Ð°Ñника картки + +pay.cc.validate.postalcode.other=Будь лаÑка, введіть правильний поштовий індекÑ. + +pay.cc.validate.postalcode.us.invalid=Вказаний поштовий Ñ–Ð½Ð´ÐµÐºÑ Ñ” некоректним у СШÐ. Якщо він довший за п’ÑÑ‚ÑŒ цифр, ви повинні викориÑтовувати Ñимвол "-". + +pay.cc.validate.postalcode.us.zero=Поштовий Ñ–Ð½Ð´ÐµÐºÑ Ð¡Ð¨Ð Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ бути більшим за 0. + +pay.cc.validate.state.ca=Будь-лаÑка, введіть провінцію Канади + +pay.cc.validate.state.us=Будь лаÑка, введіть штат СШР+ +pay.color.black=Чорний + +pay.color.grey=Сірий + +pay.color.khaki=Хакі + +pay.color.navyblue=Темно-Ñиній + +pay.color.orange=Помаранчевий + +pay.color.pink=Рожевий + +pay.color.royalblue=ЯÑкраво-Ñиній + +pay.color.silver=СріблÑÑтий + +pay.color.white=Білий + +pay.product.coppa=Перевірка віку (Ð´Ð»Ñ COPPA) + +pay.product.extrastorage=Додатковий диÑковий проÑÑ‚Ñ–Ñ€ + +pay.product.extrauserpics=Додаткові юзерпики + +pay.product.giftcert=Подарунковий Ñертифікат + +pay.product.giftcert.freeclothing=Безкоштовний одÑг + +pay.product.giftcert.int=Подарунковий Ñертифікат, віртуальний + +pay.product.giftcert.tan=Подарунковий Ñертифікат + +pay.product.paidacct=Платний рахунок + +pay.product.perm=ПоÑтійний рахунок + +pay.product.rename=Код Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ð½Ð½Ñ + +pay.product.vgift=Віртуальний подарунок + +pay.size.3xlarge=3XL + +pay.size.4xlarge=4XL + +pay.size.all=один розмір Ð´Ð»Ñ Ð²ÑÑ–Ñ… + +pay.size.large=L + +pay.size.medium=M + +pay.size.small=S + +pay.size.xlarge=XL + +pay.size.xxlarge=XXL + +pay.vgift.bdayballoons=СвÑткові кульки + +pay.vgift.biodiesel=Біодизель + +pay.vgift.blackrose=Чорна троÑнда + +pay.vgift.boxchoc=Коробка цукерок + +pay.vgift.candyhearts=Солодкі Ñердечка + +pay.vgift.candytarts=ЗіпÑована цукерка + +pay.vgift.clover=Конюшина щаÑÑ‚Ñ + +pay.vgift.coal=Шматок Ð²ÑƒÐ³Ñ–Ð»Ð»Ñ + +pay.vgift.darkliquid=Бокал портеру + +pay.vgift.diamond=Діамант + +pay.vgift.dozenred=Букет червоних троÑнд + +pay.vgift.eggs=ПиÑанки + +pay.vgift.electriccar=Електрична машинка (кількіÑÑ‚ÑŒ обмежена) + +pay.vgift.emoheart=Палке Ñерце (кількіÑÑ‚ÑŒ обмежена) + +pay.vgift.finger=Палець-вказівник + +pay.vgift.frankbunny=Кролик Френк (кількіÑÑ‚ÑŒ обмежена) + +pay.vgift.frankrecycles=Френк, Ñкого знудило + +pay.vgift.gifts=Пакунок подарунків + +pay.vgift.grannypanties=БабуÑині кальÑони + +pay.vgift.jellybeansbitten=Солодке драже + +pay.vgift.kwanzaa=Свічки Кванза + +pay.vgift.leprechaun=Лепрекон + +pay.vgift.mistletoe=Омела + +pay.vgift.potgold=Глечик із золотом + +pay.vgift.pubsign=ВеÑелий Цап (кількіÑÑ‚ÑŒ обмежена) + +pay.vgift.realheart=Вирване Ñерце + +pay.vgift.redrose=Червона троÑнда + +pay.vgift.rotteneggs=Протухлі ÑÐ¹Ñ†Ñ + +pay.vgift.sapling=ПоÑади дерево + +pay.vgift.shotglass=Чарчина + +pay.vgift.solarpanels=СонÑчні батареї + +pay.vgift.supafrank=Супер Френк + +pay.vgift.sup_martiniglass=Келих мартіні + +pay.vgift.sup_medved=Медвед + +pay.vgift.sup_pig=ПороÑÑ + +pay.vgift.sup_pinkelephant=Рожевий Слон + +pay.vgift.sup_poison=Йад + +pay.vgift.sup_v_bobruisk=ВивіÑка "Ð’ БобруйÑьк!" + +pay.vgift.yellowrose=Жовта троÑнда + +pay.widget.details=ДивітьÑÑ Ð²ÑÑ– дані рахунку + +pay.widget.giftcerts=ДивитиÑÑ Ð¿Ð¾Ð´Ð°Ñ€ÑƒÐ½ÐºÐ¾Ð²Ñ– купони + +pay.widget.header=Ви викориÑтали: + +pay.widget.history=ДивитиÑÑ Ñ–Ñторію платежів + +pay.widget.storage=[[amountused]] з [[max]] диÑкового проÑтору. + +pay.widget.upgrade=Розвинути Ñвій рахунок + +pay.widget.userpics=[[numused]] з [[max]] юзерпик + +pay.widget.voiceposts=[[numused]] з [[max]] голоÑових запиÑів цього міÑÑÑ†Ñ + +phonepost.links=ГолоÑовий Ð·Ð°Ð¿Ð¸Ñ Ð· телефону або через Gizmo/LJ Talk + +phonepost.links2=ГолоÑові запиÑи телефоном або через Gizmo/LJ Talk. + +poll.dberror=Помилка в базі даних: [[errmsg]] + +poll.dberror.items=Помилка в базі даних під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ‚Ñ–Ð²: [[errmsg]] + +poll.dberror.questions=Помилка в базі даних під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ð°Ð½ÑŒ: [[errmsg]] + +poll.error.badmaxlength=ЗначеннÑм макÑимальної довжини Ð´Ð»Ñ Ñ‚ÐµÐºÑтових теґів "lj-pq" має бути ціле чиÑло від 1 до 255. + +poll.error.badsize=ЗначеннÑм розміру Ð´Ð»Ñ Ñ‚ÐµÐºÑтових теґів "lj-pq" має бути ціле чиÑло від 1 до100. + +poll.error.cantview=Помилка: ви не маєте дозволу дивитиÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¸ цього опитуваннÑ. + +poll.error.cantvote=Вибачте, ви не маєте дозволу брати учаÑÑ‚ÑŒ в цьому окремому голоÑуванні. + +poll.error.missingljpoll=Ð’ÑÑ– теги lj-pq мають бути вÑередині закритого тегу lj-poll. + +poll.error.missingljpq=Ð’ÑÑ– теги lj-pi мають бути вÑередині закритого тегу lj-pq. + +poll.error.nested=Ви не можете вÑтавити теги [[tag]]. Чи ви забули закрити такий? + +poll.error.noentry=Помилка: це голоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ долучене до цього запиÑу журналу + +poll.error.noitems=Ви муÑите мати принаймні один елемент у нетекÑтовому питанні опитуваннÑ. + +poll.error.noitemstext=Теги lj-pq типу 'текÑÑ‚' не можуть міÑтити елементи опитуваннÑ. + +poll.error.nopollid=ВідÑутній параметр pollid. + +poll.error.noquestions=Ви муÑите мати принаймні одне Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñƒ голоÑуванні. + +poll.error.notext=Ð’Ñередині теґу lj-pq має бути текÑÑ‚, щоб поÑÑнити, про що питаннÑ. + +poll.error.pitoolong=ТекÑÑ‚ вÑередині теґу lj-pi має бути між 1 та 255 Ñимволами. Довжина вашого Ñтановить [[len]]. + +poll.error.pollnotfound=Помилка: Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ #[[num]] не знайдено. + +poll.error.questionnotfound=Помилка: цього Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує. + +poll.error.scalefromlessto=Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÑˆÐºÐ°Ð»Ð¸ "від" має бути менше Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ "до". + +poll.error.scaleincrement=Шаг шкали має рівнÑтиÑÑ Ð¿Ñ€Ð¸Ð½Ð°Ð¹Ð¼Ð½Ñ– 1. + +poll.error.scaletoobig=Ваша шкала перевищує межу в 20 елементів (до-від)/на > 20. + +poll.error.tagnotopen=Ви не можете закрити теґ[[tag]], Ñкий не Ñ” відкритим. + +poll.error.truncated=... Ñкорочено + +poll.error.unknownpqtype=Ðевідомий тип теґу lj-pq. + +poll.error.unlockedtag=Тег [[tag]] розблоковано. + +poll.error.whoview=whoview має бути "вÑÑ–", "друзі" або "ніхто". + +poll.error.whovote=whovote має бути "вÑÑ–" або "друзі". + +poll.pollnum=ÐžÐ¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ #[[num]] + +poll.scaleanswers=Середнє: [[mean]] Медіана: [[median]] Стандартне відхиленнÑ: [[stddev]] + +poll.security=ГолоÑувати можуть [[whovote]], дивитиÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¸ - [[whoview]] + +poll.security.all=вÑÑ– + +poll.security.friends=друзі + +poll.security.none=ніхто + +poll.submit=ВідповіÑти на Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +poll.viewanswers=ДивитиÑÑ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ñ– + +polls.link=майÑтру ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +polls.text=[[user]], чи знаєте ви, що можете Ñтворити Ð¾Ð¿Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ Ñвоєму журналі завдÑки нашому [[link]]? ДізнайтеÑÑ Ñправжню думку Ñвоїх друзів про вашу нову Ñорочку. [[poll]] + +popfriends.link=друзі друзів + +popfriends.text=Гей, друже, Ñторінка [[link]] відображає вÑÑ– Ñтрічки друзів твоїх друзів у одній Ñтрічці друзів. Скажи це тричі без зупинки. + +portal.bdays.count.des=За замовчуваннÑм показуютьÑÑ 5 друзів із найближчими днÑми народженнÑ. + +portal.bdays.count.name=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +portal.bdays.portalname=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +portal.bdays.portaltitle=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +portal.goat.name=ТаліÑман Ñайту + +portal.goattext.des=Що ви хочете, щоб казав ваш цап? Єдина ÑÐ¿Ñ€Ð°Ð²Ð¶Ð½Ñ Ñ€Ñ–Ñ‡, Ñку може казати цап - це "Ме-е-е", але Ñкщо ви дуже хочете, ви можете зробити виглÑд, що ваш цап може казати щоÑÑŒ інше. + +portal.goattext.name=ТекÑÑ‚ Ð´Ð»Ñ Ñ†Ð°Ð¿Ð° + +portal.login.portalname=Вхід до журналу + +portal.memories.entriesnoun=запиÑи + +portal.memories.entrynoun=Ð·Ð°Ð¿Ð¸Ñ + +portal.memories.portalname=Вибрані запиÑи + +portal.memories.portaltitle=Вибрані запиÑи + +portal.ministats.active=Ðктивні: + +portal.ministats.title=КориÑтувачі + +portal.ministats.total=Ð’Ñього: + +portal.misbehaved.des=Вам краще залишити це без позначки. ÐедреÑировані цапи Ñ” Ñуцільним лихом. + +portal.misbehaved.name=Цап-бешкетник + +portal.newtolj.name=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ñайту + +portal.popfaq.portalname=10 ÐайчаÑтіших питань, Ñкі переглÑдали найбільше + +portal.popfaq.portaltitle=10 ÐайчаÑтіших питань, Ñкі переглÑдали найбільше + +portal.popwithfriends.accttype=Покращіть рахунок до платного, щоб побачити, Ñкі кориÑтувачі кориÑтуютьÑÑ Ð¿Ð¾Ð¿ÑƒÐ»ÑрніÑÑ‚ÑŽ Ñеред ваших друзів. + +portal.randuser.count.des=За замовчуваннÑм показуєтьÑÑ Ð»Ð¸ÑˆÐµ 1 випадковий кориÑтувач, але ви можете мати до 10, розміщених вертикально у вузьких колонках, або до 5, розміщених горизонтально у широких колонках. + +portal.randuser.count.name=КількіÑÑ‚ÑŒ випадкових кориÑтувачів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + +portal.randuser.error.tableempty=Ðемає випадкових кориÑтувачів. Зв'ÑжітьÑÑ Ð· адміном. + +portal.randuser.hidename.des=За замовчуваннÑм показуєтьÑÑ Ñ–Ð¼'Ñ Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾Ð³Ð¾ кориÑтувача. ÐатиÑніть тут, щоб видалити це. + +portal.randuser.hidename.name=Приховати ім'Ñ + +portal.randuser.hidepic.des=За замовчуваннÑм показуєтьÑÑ ÑŽÐ·ÐµÑ€Ð¿Ð¸ÐºÐ° випадкового кориÑтувача. ÐатиÑніть тут, щоб видалити це. + +portal.randuser.hidepic.name=Приховати юзерпику + +portal.randuser.portalname=Випадковий кориÑтувач + +portal.randuser.portaltitle=Випадковий кориÑтувач + +portal.randuser.portaltitleplural=Випадкові кориÑтувачі + +portal.recent.error.noentries=Вибачте. Ðемає запиÑів. + +portal.recent.error.notsetup=Ви маєте це налаштувати. ÐатиÑните на Ñимвол плюÑа, щоб задати журнал, Ñкий ви хотіли б тут бачити. + +portal.recent.error.userstatus=КориÑтувач видалив або припинив дію Ñвого рахунку. + +portal.recent.items.description=За замовчуваннÑм показуєтьÑÑ Ð»Ð¸ÑˆÐµ найÑвіжиший запиÑ. + +portal.recent.items.name=Що відображувати + +portal.recent.journal.description=ОÑтанні запиÑи Ñкого журналу ви бажаєте бачити? + +portal.recent.journal.name=Журнал + +portal.recent.nosubject=(Без теми) + +portal.recent.permlink=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +portal.recent.portalname=ВиглÑд нещодавніх запиÑів + +portal.recent.portaltitle=ОÑтанні запиÑи + +portal.recent.showtext.description=За замовчуваннÑм будуть показані лише теми. + +portal.recent.showtext.name=Включити текÑÑ‚ + +portal.stats.journalentyest=Вчорашні запиÑи журналу + +portal.stats.portalname=СтатиÑтика Ñайту + +portal.stats.portaltitle=СтатиÑтика + +portal.stats.totalusers=КориÑтувачів уÑього + +portal.update.entry=ЗапиÑ: + +portal.update.mode.des=Повний режим дає вам безліч додаткових параметрів публікуваннÑ... включаючи публікацію до Ñпільнот Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… поточних наÑтрою, музики та юзерпики. ПроÑтий режим більше личить, Ñкщо ви майже не кориÑтуєтеÑÑ Ñ†Ð¸Ð¼Ð¸ можливоÑÑ‚Ñми та вважали б за краще не бачити Ñ—Ñ… взагалі. + +portal.update.mode.full=Повний + +portal.update.mode.name=Режим + +portal.update.mode.simple=ПроÑтий + +portal.update.moreopts=Більше можливоÑтей + +portal.update.portalname=ÐŸÐ¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +portal.update.portaltitle=Поновити ваш журнал + +portal.update.subject=Тема: + +protocol.bad_password=Ваш пароль занадто легко вгадати. Рекомедовано змінити його, інакше ви ризикуєте, що Ваш журнал вкрадуть. Завітайте до [[siteroot]]/changepassword.bml, щоб змінити пароль. + +protocol.hello_test=Привіт, теÑтовий рахунок! + +protocol.mail_bouncing=Ви наразі кориÑтуєтеÑÑ Ð¿Ð¾Ð³Ð°Ð½Ð¾ÑŽ e-mail адреÑою. Ð’ÑÑ Ð¿Ð¾ÑˆÑ‚Ð°, Ñку ми вам надÑилаємо, повертаєтьÑÑ Ð½Ð°Ð·Ð°Ð´. [[sitename]] вимагає дійÑну e-mail адреÑу, щоб продовижити кориÑтуваннÑ. Завітайте до [[siteroot]]/support/faqbrowse.bml?faqid=19 щоб дізнатиÑÑ, Ñк змінити e-mail адреÑу. + +protocol.modpost=Ваш Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² поміщений до черги на модеруваннÑ. Він буде прийнÑтий або відхилений одним з модераторів Ñпільноти. + +protocol.must_revalidate=Вам треба перевірити вашу e-mail адреÑу. Ваша Ñтара адреÑа була правильна, але оÑкільки ви змінили Ñ—Ñ—, ви маєте перевірити нову. Якщо ви не зробите цього, ви не отримаєте доÑтупу до вÑÑ–Ñ… функцій [[sitename]]. Додаткову інформацію можна знайти за адреÑою [[siteroot]]/support/faqbrowse.bml?faqid=11. + +protocol.not_validated=Ваша нова e-mail адреÑа не була перевірена. Ви може продовжувати кориÑтуватиÑÑ [[sitename]], але Ñкщо ви не підтвердите адреÑу, ви не отримаєте доÑтупу до вÑÑ–Ñ… функцій Ñайту. ІнÑтрукції ви можете знайти в лиÑÑ‚Ñ–, що було надіÑлано вам, коли ви Ñтворили Ñвій журнал, або завітайте за адреÑою [[siteroot]]/support/faqbrowse.bml?faqid=11. + +protocol.old_win32_client=ДоÑтупні значно новіші клієнтÑькі програми LiveJournal Ð´Ð»Ñ Windows, Ñ– ми рекомендуємо, щоб ви оновили Ñвоє програмне забезпеченнÑ. Завітайте до [[siteroot]]/download/ щоб Ñкачати новішу клієнтÑьку програму. + +protocol.readonly=Ваш рахунок тимчаÑово у режимі, коли можна тільки читати. ДеÑкі операції будуть неможливі протÑгом кількох хвилин. + +setting.bio.error.invalid=Ðеправильна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñебе + +setting.bio.question=Про Ñебе: + +setting.birthday.question=Коли ви народилиÑÑŒ? + +setting.birthdaydisplay.error.invalid=Ðеправильний параметр + +setting.birthdaydisplay.question=Параметри показу Ð´Ð½Ñ Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ: + +setting.gender.error.invalid=Ðеправильний параметр + +setting.gender.question=Якої ви Ñтаті? + +setting.interests.question=ІнтереÑи: + +setting.name.question=Як Ð²Ð°Ñ Ð·Ð²Ð°Ñ‚Ð¸? + +settings.city=МіÑто + +settings.country=Країна + +settings.country.choose=Оберіть країну + +settings.embedplaceholder.info=Оберіть цей параметр, щоб вÑÑ– вбудовані відео-файли, Ñкщо ви увійшли до LJ, замінювалиÑÑ Ð¿Ð¾ÑиланнÑми. Цей параметр запобігає завантаженню відео, поки ви не натиÑнете поÑиланнÑ, Ñ– кориÑний при переглÑді на роботі, платному трафіку чи повільному з’єднанні. + +settings.embedplaceholder.option=ВикориÑтовувати замінники відео-файлів + +settings.embedplaceholder.title=Замінники відео + +settings.error.locale.country_ne_state=Ви вказали Сполучені Штати, але ввели назву штату поза СШРу поле "неамериканÑький штат". + +settings.error.locale.invalid_country=ЯкоÑÑŒ ви обрали помилкову країну. + +settings.error.locale.state_ne_country=Ви вказали відмінну від СШРкраїну, але обрали штат СШÐ. + +settings.error.locale.zip_ne_state<< +Ваш Ñ–Ð½Ð´ÐµÐºÑ Ð½Ðµ відповідає вказаному штату. +Введіть правильні дані або очиÑÑ‚Ñ–Ñ‚ÑŒ одне чи обидва Ð¿Ð¾Ð»Ñ ÑˆÑ‚Ð°Ñ‚ та індекÑ. +. + +settings.error.locale.zip_requires_us<< +Ви заповнили поштовий індекÑ, але вказана вами країна - не Сполучені Штати. +Ми ведемо облік поштових індекÑів тільки Ð´Ð»Ñ Ð»ÑŽÐ´ÐµÐ¹ зі СШÐ. +Будь лаÑка, повернітьÑÑ Ñ– видаліть поштовий Ñ–Ð½Ð´ÐµÐºÑ Ð°Ð±Ð¾ вкажіть Сполучені Штати, Ñк країну вашого проживаннÑ. +. + +settings.error.year.notenoughdigits=Ðеправильний рік народженнÑ. Введіть 4-значний рік. + +settings.error.year.outofrange=Ðеправильний рік народженнÑ. + +settings.gender=Стать + +settings.gender.female=Жіноча + +settings.gender.male=Чоловіча + +settings.gender.uns=(Ðевизначена) + +settings.province=або неамериканÑький штат/облаÑÑ‚ÑŒ/Ñ‚ÐµÑ€Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ + +settings.security.visibility.everybody=Будь-хто + +settings.security.visibility.friends=Тільки друзі + +settings.security.visibility.nobody=Ðіхто + +settings.state=Штат + +settings.state.us=Штати СШР+ +settings.yearofbirth=Рік Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +settings.zipcode=Поштовий Ñ–Ð½Ð´ÐµÐºÑ + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Вибачте + +splus.link=ÑпонÑорований рахунок + +splus.text=Перейдіть на Розширений рахунок та отримайте більше можливоÑтей безкоштовно!

    ТиÑÑчі кориÑтувачів LJ вже зробили це, то ж на що чекаєте ви?

    + +splus.text2=Перейдіть на Розширений рахунок та отримайте більше можливоÑтей безкоштовно!

    ТиÑÑчі кориÑтувачів LJ вже зробили це, то ж на що чекаєте ви?

    + +taglib.error.toomany=Це Ñпричинить вихід за межі макÑимуму, що Ñкаладає [[max]] [[?max|теґ|теґи|теґів]]. Будь лаÑка, видаліть деÑкі з них Ñ– Ñпробуйте знову. + +talk.anonwrote=ХтоÑÑŒ пише, + +talk.anonwrote_comm=ХтоÑÑŒ пише до [[commlink]], + +talk.btn.preview=Попередньо переглÑнути + +talk.commentpermlink=поÑÐ¸Ð»Ð°Ð½Ð½Ñ + +talk.commentpost=ÐапиÑати новий коментар + +talk.commentsread=Читати коментарі + +talk.curname_Location=МіÑцезнаходженнÑ: + +talk.curname_Mood=ÐаÑтрій: + +talk.curname_Music=Зараз грає: + +talk.curname_Tags=Теги запиÑу: + +talk.error.bogusargs=Підроблені аргументи + +talk.error.comm_deleted=Цей коментар було видалено. + +talk.error.deleted=Цей журнал видалено. + +talk.error.deleted.title=Видалено + +talk.error.mustlogin=Ви маєте увійти до журналу щоб побачити цей захищений запиÑ. + +talk.error.nocomment=Коментарю не Ñ–Ñнує. + +talk.error.noentry=Такого запиÑу не Ñ–Ñнує. + +talk.error.nojournal=Помилка: неможливо визначити журнал з аргументів. + +talk.error.nosuchjournal=Такого журналу не Ñ–Ñнує. + +talk.error.notauthorised=Вам не дозволено дивитиÑÑ Ñ†ÐµÐ¹ захищений запиÑ. + +talk.error.suspended=Ð”Ñ–Ñ Ñ†ÑŒÐ¾Ð³Ð¾ журналу припинена. + +talk.error.suspended.title=Припинено + +talk.frozen=Відповіді заморожені + +talk.parentlink=Рівнем вище + +talk.readsimilar=Читати Ñхожі запиÑи журналу: + +talk.replytothis=ВідповіÑти + +talk.somebodywrote=[[realname]] ([[userlink]]) пише, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) пише до [[commlink]], + +talk.spellcheck=ПеревірÑти Ð¿Ñ€Ð°Ð²Ð¾Ð¿Ð¸Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду + +talk.threadlink=Гілка + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_ukrainian + +time.ago.day=[[num]] [[?num|день|дні|днів]] тому + +time.ago.hour=[[num]] [[?num|годину|години|годин]] тому + +time.ago.minute=[[num]] [[?num|хвилину|хвилини|хвилин]] тому + +time.ago.never=Ðіколи. + +time.ago.second=[[num]] [[?num|Ñекунду|Ñекунди|Ñекунд]] тому + +time.ago.week=[[num]] [[?num|тиждень|тижні|тижнів]] тому + +tos.error=Ви маєте прочитати та погодитиÑÑ Ð· умовами Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг. + +tos.haveread=Я прочитав Умови викориÑÑ‚Ð°Ð½Ð½Ñ Ñ– погодивÑÑ Ð· ними. + +tos.mustread=Перш ніж продовжити, ви муÑите прочитати та погодитиÑÑ Ð· Умовами Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг. + +Username=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +userpic.inactive=Ðеактивна + +userpic.link=юзерпику за замовчуваннÑм + +userpic.text=[[user]], чи знаєте ви, що можете обрати [[link]] Ð´Ð»Ñ Ñвоїх запиÑів та коментарів? + +vgift.bdayballoons.anon=Звідки ж узÑлиÑÑ Ñ†Ñ– повітрÑні кульки? + +vgift.bdayballoons.fromuser=Кілька файних повітрÑних кульок від [[user]]. + +vgift.biodiesel.anon=Дехто вважає, вам Ñлід Ñпробувати біодизель. + +vgift.biodiesel.fromuser=[[user]] вважає, вам Ñлід Ñпробувати біодизель. + +vgift.blackrose.anon=Чорна троÑнда від таємничого друга. + +vgift.blackrose.fromuser=Чорна троÑнда від [[user]]! + +vgift.boxchoc.anon=Загадкова коробка шоколадних цукерок від загадкового кориÑтувача. + +vgift.boxchoc.fromuser=Коробка Ñмачних лаÑощів від [[user]]! + +vgift.candycorn.anon=Ðадгризені Ñолодощі + +vgift.candycorn.fromuser=Ðадгризені Ñолодощі від [[user]] + +vgift.candyhearts.anon=Солодкі карамельні Ñердечка. + +vgift.candyhearts.fromuser=Солодкі карамельні Ñердечка від [[user]]. + +vgift.candytarts.anon=ЗіпÑована цукерка! Хто б це міг бути? + +vgift.candytarts.fromuser=ЗіпÑована цукерка від [[user]] + +vgift.coal.anon=Шматок Ð²ÑƒÐ³Ñ–Ð»Ð»Ñ + +vgift.coal.fromuser=Шматок Ð²ÑƒÐ³Ñ–Ð»Ð»Ñ Ð²Ñ–Ð´ [[user]] + +vgift.diamond.anon=Вражаючий діамант! + +vgift.diamond.fromuser=Вражаючий діамант від [[user]]! + +vgift.dozenred.anon=Загадковий букет троÑнд! + +vgift.dozenred.fromuser=Дюжина довгих квітів від [[user]]! + +vgift.eggs.anon=ПиÑанки від загадкового друга. + +vgift.eggs.fromuser=ПиÑанки від [[user]]. + +vgift.electriccar.anon=Декому до душі низькі витрати. + +vgift.electriccar.fromuser=[[user]] до душі низькі витрати. + +vgift.emoheart.anon=Палке Ñерце від загадкового друга. + +vgift.emoheart.fromuser=Палке Ñерце від [[user]] + +vgift.finger.anon=Дехто вказує вам правильний шлÑÑ…. + +vgift.finger.fromuser=[[user]] вказує вам правильний шлÑÑ…. + +vgift.flamingbag.anon=Підпалений пакетик з какашками. + +vgift.flamingbag.fromuser=Підпалений пакетик з какашками від [[user]] + +vgift.frankbunny.anon=Френк - великодній кролик? + +vgift.frankbunny.fromuser=[[user]] надіÑлав вам Френка - великоднього кролика? + +vgift.frankolantern.anon=Сюрприз - Френк-о-Ліхтарик! + +vgift.frankolantern.fromuser=Френк-о-Ліхтарик від [[user]] + +vgift.frankrecycles.anon=Декого нудить, Ñк Ñ– Френка. + +vgift.frankrecycles.fromuser=[[user]] нудить, Ñк Ñ– Френка. + +vgift.gifts.anon=Пакунок подарунків від Ð½ÐµÐ·Ð½Ð°Ð¹Ð¾Ð¼Ñ†Ñ + +vgift.gifts.fromuser=Пакунок подарунків від [[user]] + +vgift.grannypanties.anon=Дехто вважає, що вам ÑподобаютьÑÑ Ð±Ð°Ð±ÑƒÑині кальÑони. + +vgift.grannypanties.fromuser=[[user]] вважає, що вам ÑподобаютьÑÑ Ð±Ð°Ð±ÑƒÑині кальÑони. + +vgift.jellybeansbitten.anon=Дехто надіÑлав вам Ñолодке драже. + +vgift.jellybeansbitten.fromuser=[[user]] надіÑлав вам Ñолодке драже. + +vgift.kwanzaa.anon=Свічки Кванза від Ð½ÐµÐ·Ð½Ð°Ð¹Ð¾Ð¼Ñ†Ñ + +vgift.kwanzaa.fromuser=Свічки Кванза від [[user]] + +vgift.leprechaun.anon=Танцюй, Ñк лепрекон! + +vgift.leprechaun.fromuser=Танцюй, Ñк лепрекон! + +vgift.mistletoe.anon=ХтоÑÑŒ бажає зуÑтрітиÑÑŒ з вами під омелою + +vgift.mistletoe.fromuser=[[user]] бажає зуÑтрітиÑÑŒ з вами під омелою + +vgift.potgold.anon=Дехто надіÑлав вам глечик із золотом. + +vgift.potgold.fromuser=[[user]] надіÑлав вам глечик із золотом. + +vgift.pubsign.anon=ЗуÑтрінемоÑÑŒ у ВеÑелого Цапа. + +vgift.pubsign.fromuser=[[user]] бажає зуÑтрітиÑÑŒ у ВеÑелого Цапа. + +vgift.realheart.anon=Дехто надіÑлав вам вирване Ñерце. + +vgift.realheart.fromuser=[[user]] надіÑлав вам вирване Ñерце. + +vgift.redrose.anon=Загадкова червона троÑнда + +vgift.redrose.fromuser=Чудова троÑнда від [[user]] + +vgift.rotteneggs.anon=Протухлі ÑÐ¹Ñ†Ñ Ð²Ñ–Ð´ незнайомого боÑгуза. + +vgift.rotteneggs.fromuser=Протухлі ÑÐ¹Ñ†Ñ Ð²Ñ–Ð´ [[user]]. + +vgift.sapling.anon=ПоÑадіть дерево! + +vgift.sapling.fromuser=[[user]] поÑадив Ð´Ð»Ñ Ð²Ð°Ñ Ð´ÐµÑ€ÐµÐ²Ð¾! + +vgift.shamrock.anon=Дехто хоче, щоб ви перехилили чарочку, + +vgift.shamrock.fromuser=[[user]] хоче, щоб ви перехилили чарочку. + +vgift.shotglass.anon=ДеÑкий друг придбав вам чарчину. + +vgift.shotglass.fromuser=[[user]] придбав вам чарчину. + +vgift.solarpanels.anon=Декому подобаєтьÑÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÑŽÐ²Ð°Ð½Ð° енергіÑ. + +vgift.solarpanels.fromuser=КориÑтувачу [[user]] подобаєтьÑÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÑŽÐ²Ð°Ð½Ð° енергіÑ. + +vgift.supafrank.anon=Дехто вважає, що ви варті Супер Френка! + +vgift.supafrank.fromuser=[[user]] вважає, що ви варті Супер Френка! + +vgift.sup_martiniglass.anon=Келих мартіні від загадкового друга + +vgift.sup_martiniglass.fromuser=Келих мартіні від [[user]] + +vgift.sup_medved.anon=Медвед від загадкового друга + +vgift.sup_medved.fromuser=Медвед від [[user]] + +vgift.sup_pig.anon=ПороÑÑ Ð²Ñ–Ð´ загадкового друга + +vgift.sup_pig.fromuser=ПороÑÑ Ð²Ñ–Ð´ [[user]] + +vgift.sup_pinkelephant.anon=Рожевий Слон від загадкового друга + +vgift.sup_pinkelephant.fromuser=Рожевий Слон від [[user]] + +vgift.sup_poison.anon=Йад від загадкового друга + +vgift.sup_poison.fromuser=Йад від [[user]] + +vgift.sup_v_bobruisk.anon=ВивіÑка "Ð’ БобруйÑьк!" від загадкового друга + +vgift.sup_v_bobruisk.fromuser=ВивіÑка "Ð’ БобруйÑьк!" від [[user]] + +vgift.womens_history.anon=Ð’ підтримку "National Women's History Month" + +vgift.womens_history.fromuser=[[user]] підтримує "National Women's History Month" + +vgift.yellowrose.anon=Приємна загадкова троÑнда + +vgift.yellowrose.fromuser=Приємна жовта троÑнда від [[user]] + +voicepost.link=голоÑове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ + +voicepost.text=[[user]], чи бажали ви поділитиÑÑ Ñвоїм мелодичним голоÑом з читачами LiveJournal Ñтворивши [[link]]? + +web.ads.advertisement=Реклама + +web.ads.customize=Ðалаштувати + +web.ads.feedback=Зворотній зв’Ñзок + +web.ads.search=Підтримувані поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ + +web.authas.btn=Змінити + +web.authas.label=Від імені: + +web.authas.label.comm=Від Ñпільноти: + +web.controlstrip.btn.login=Увійти + +web.controlstrip.btn.logout=Вийти + +web.controlstrip.btn.view=ДивитиÑÑ + +web.controlstrip.links.addfeed=Додати до вашої Ñтрічки друзів + +web.controlstrip.links.addfriend=Додати до друзів + +web.controlstrip.links.changecommsettings=Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +web.controlstrip.links.create=Створити рахунок у [[sitename]] + +web.controlstrip.links.editcommmembers=Змінити учаÑників + +web.controlstrip.links.editcommprofile=Змінити профіль + +web.controlstrip.links.home=Початок + +web.controlstrip.links.invitefriends=ЗапроÑити друзів + +web.controlstrip.links.joincomm=ДолучитиÑÑ Ð´Ð¾ цієї Ñпільноти + +web.controlstrip.links.learnmore=ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ + +web.controlstrip.links.leavecomm=Залишити цю Ñпільноту + +web.controlstrip.links.managecomminvites=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñми + +web.controlstrip.links.manageentries=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñами + +web.controlstrip.links.managefriends=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐ·Ñми + +web.controlstrip.links.mylj=Мій [[siteabbrev]] + +web.controlstrip.links.popfeeds=ДивитиÑÑ Ð½Ð°Ð¹Ð¿Ð¾Ð¿ÑƒÐ»Ñрніші потоки + +web.controlstrip.links.post=Поновити журнал + +web.controlstrip.links.postcomm=ÐапиÑати до цієї Ñпільноти + +web.controlstrip.links.recentcomments=ДивитиÑÑ Ð¾Ñтанні коментарі + +web.controlstrip.links.removecomm=Припинити ÑпоглÑÐ´Ð°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— Ñпільноти + +web.controlstrip.links.removefeed=Видалити з вашої Ñтрічки друзів + +web.controlstrip.links.viewfriendspage=Читати запиÑи друзів + +web.controlstrip.links.watchcomm=СпоглÑдати за цією Ñпільнотою + +web.controlstrip.login.forgot=Забули ваш пароль? + +web.controlstrip.login.remember=Запам’Ñтати мене + +web.controlstrip.nouserpic.alt=Завантажити юзерпику + +web.controlstrip.nouserpic.title=Змінити юзерпики + +web.controlstrip.poweredby.alt=Під управліннÑм [[sitename]] + +web.controlstrip.poweredby.title=Дім + +web.controlstrip.select.friends.all=Ð’ÑÑ– друзі + +web.controlstrip.select.friends.communities=Тільки Ñпільноти + +web.controlstrip.select.friends.feeds=Синдикативні потоки + +web.controlstrip.select.friends.journals=Тільки журнали + +web.controlstrip.select.friends.label=Фільтр: + +web.controlstrip.status.community=Ви дивитеÑÑ Ñпільноту [[user]] + +web.controlstrip.status.friend=[[user]] у вашому ÑпиÑку друзів + +web.controlstrip.status.friendof=Ви у ÑпиÑку друзів [[user]] + +web.controlstrip.status.maintainer=Ви доглÑдач [[user]] + +web.controlstrip.status.member=Ви учаÑник [[user]] + +web.controlstrip.status.memberwatcher=Ви Ñ” учаÑником та ÑпоглÑдаєте за [[user]] + +web.controlstrip.status.mutualfriend=[[user]] - ваш взаємний друг + +web.controlstrip.status.news=Ви дивитеÑÑ [[user]] на [[sitename]] + +web.controlstrip.status.other=Ви дивитеÑÑ [[user]] + +web.controlstrip.status.personal=Ви дивитеÑÑ Ð¶ÑƒÑ€Ð½Ð°Ð» [[user]] + +web.controlstrip.status.personalfriendsfriendspage=Ви дивитеÑÑ Ñтрічку "Друзі друзів" [[user]] + +web.controlstrip.status.personalfriendspage=Ви дивитеÑÑ Ñтрічку друзів [[user]] + +web.controlstrip.status.syn=Ви дивитеÑÑ Ð¿Ð¾Ñ‚Ñ–Ðº [[user]] + +web.controlstrip.status.watcher=Ви ÑпоглÑдаєте за [[user]] + +web.controlstrip.status.yourfriendsfriendspage=Ви дивитеÑÑ Ñвою Ñтрічку "Друзі друзів" + +web.controlstrip.status.yourfriendspage=Ви дивитеÑÑ Ñвою Ñтрічку друзів + +web.controlstrip.status.yourjournal=Ви дивитеÑÑ Ñвій журнал + +web.controlstrip.userpic.alt=Юзерпика + +web.controlstrip.userpic.title=Змінити юзерпики + +web.lj-replace.first_post=Ваш журнал поки що не міÑтить запиÑів. Почніть із ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу. + +web.lj-replace.first_post.subject=ЛаÑкаво проÑимо до [[sitename]] + +web.postto.btn=Змінити + +web.postto.label=ПиÑати до: + +widget.commsofuser.title=Додано Ñпільноти [[user]] + +widget.commsofuser.viewprofile=ПереглÑнути профіль [[user]] + +widget.extrasearch.community=Пошук Ñпільнот + +widget.extrasearch.community.info=Пошук Ñпільнот за кількома критеріÑми + +widget.extrasearch.directory=Пошук у каталозі + +widget.extrasearch.directory.info=Шукати журнали за кількома критеріÑми. + +widget.extrasearch.moreoptions=Більше параметрів пошуку + +widget.extrasearch.moreoptions.info=Пошук за кількома критеріÑми. + +widget.extrasearch.paidonly=Ці параметри доÑтупні лише Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… рахунків. + +widget.extrasearch.region=Пошук за регіоном + +widget.extrasearch.region.info=Знайдіть журнали у Ñвоїй країні. + +widget.extrasearch.region2=Знайти людей за регіоном + +widget.extrasearch.title=Додаткові параметри пошуку + +widget.featurematrix.free=БЕЗКОШТОВÐО + +widget.featurematrix.pricing.paid=Починаючи з
    менш ніж
    2 доларів СШРв міÑÑць** + +widget.frank.about=Френк - наш Ñимвол. Він цап Ñ– любить жувати панталони. + +widget.frank.image.alt=Цап Френк, Ñимвол LiveJournal. + +widget.frank.saysfrank=каже Френк. + +widget.frank.text="Ме-е-е", - + +widget.friendbirthdays.gift=Подарунок + +widget.friendbirthdays.title=Дні Ð½Ð°Ñ€Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ + +widget.friendbirthdays.userbirthday=[[user]] ÑвÑткує [[month]] [[day]] + +widget.friendbirthdays.viewall=Ще + +widget.friendinterests.intro=Можливо, деÑкі речі, Ñкі цікавлÑÑ‚ÑŒ вашого друга [[user]], ÑподобаютьÑÑ Ð¹ вам: + +widget.friendupdates.noupdates=Ðемає оновлень. + +widget.friendupdates.noupdates.setup=Ðалаштуйте Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° Ñторінці "Керувати налаштуваннÑми повідомлень". + +widget.friendupdates.title=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑпиÑку друзів + +widget.friendupdates.viewall=Ще + +widget.gettingstarted.entry.link=Зробити Ð·Ð°Ð¿Ð¸Ñ + +widget.gettingstarted.entry.note=Ви ще не робили запиÑів у Ñвоєму журналі. + +widget.gettingstarted.expires=ЗакінчуєтьÑÑ [[date]] + +widget.gettingstarted.friends.link=Знайдіть друзів та Ñпільноти + +widget.gettingstarted.friends.note=Ви обрали лише [[num]] [[?num|день|дні|днів]]. + +widget.gettingstarted.manage=Керувати рахунком + +widget.gettingstarted.profile.link=Редагувати профіль + +widget.gettingstarted.profile.note=Ви не заповнили Ñвій профіль. + +widget.gettingstarted.title=Починаємо + +widget.gettingstarted.userpics.link=Завантажити юзерпику + +widget.gettingstarted.userpics.note=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” юзерпик. + +widget.journalspotlight.intro=Ð©Ð¾Ñ‚Ð¸Ð¶Ð½Ñ Ð¼Ð¸ відзначаємо кориÑтувачів та Ñпільноти, Ñкі Ñ” цікавими та унікальними. + +widget.journalspotlight.suggest=Запропонувати родзинку + +widget.journalspotlight.title=Родзинка + +widget.journalspotlight.viewmore=ПереглÑнути більше родзинок + +widget.officialjournals.nosubject=(без теми) + +widget.officialjournals.readmore=Докладніше... + +widget.officialjournals.title=Ðовини [[sitename]] + +widget.officialjournals.viewall=Ще + +widget.promotext.minititle=СпонÑоровано + +widget.publicstats.day=ЗапиÑи за оÑтанню добу + +widget.publicstats.latestposts=ПереглÑнути оÑтанні загальнодоÑтупні запиÑи + +widget.publicstats.rssalt=ВерÑÑ–Ñ RSS + +widget.publicstats.sincestart=журнали та Ñпільноти + +widget.qotd.answer=Відповідь + +widget.qotd.entry.subject=Блок допиÑувача + +widget.qotd.title=ÐŸÐ¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð½Ñ + +widget.recentcomments.anon=ХтоÑÑŒ + +widget.recentcomments.commentheading=[[poster]] у запиÑÑ– [[entry]] + +widget.recentcomments.link=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ + +widget.recentcomments.nocomments=Жодного ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ Ñ‰Ðµ не опубліковано. Зробіть запиÑ, щоб розпочати. + +widget.recentcomments.nosubject=(без теми) + +widget.recentcomments.title=Коментарі + +widget.recentcomments.viewall=Ще + +widget.recentposts.rssalt=ВерÑÑ–Ñ RSS + +widget.recentposts.title=ОÑтанні загальнодоÑтупні запиÑи + +widget.recentposts.viewall=ПереглÑнути оÑтанні загальнодоÑтупні запиÑи + +widget.search.icq=Ðомер ICQ + +widget.search.interest=Ð†Ð½Ñ‚ÐµÑ€ÐµÑ + +widget.search.submit=Вперед + +widget.search.title=Шукати за + +widget.search.username=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача + +widget.sitemessages.title=ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ + +xcolibur.greeting.anon=ЛаÑкаво проÑимо до LiveJournal! + +xcolibur.greeting.logged_in=ЛаÑкаво проÑимо, [[name]]! [[logout]] + +xcolibur.login=Увійти? + +xcolibur.login.createaccount=(Створити рахунок або викориÑтовувати OpenID) + +xcolibur.login.forget=забули ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача? + +xcolibur.login.loginnow=Увійти негайно. + +xcolibur.login.remember=запам'Ñтати мене + +xcolibur.logout=Вийти? + +xcolibur.morefeatures=Отримайте більше можливоÑтей + +xcolibur.nav.about=Про Ð½Ð°Ñ + +xcolibur.nav.about.download=Скачати + +xcolibur.nav.about.general=Загальні дані + +xcolibur.nav.about.paidaccounts=Платні рахунки + +xcolibur.nav.about.press=ПреÑа + +xcolibur.nav.about.sitenews=Ðовини Ñайту + +xcolibur.nav.about.stats=СтатиÑтика + +xcolibur.nav.footer.sitemap=Мапа Ñайту + +xcolibur.nav.giftshop=ÐšÑ€Ð°Ð¼Ð½Ð¸Ñ†Ñ + +xcolibur.nav.giftshop.addons=Ð”Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ + +xcolibur.nav.giftshop.gifts=Подарунки + +xcolibur.nav.giftshop.merchandise=Товари + +xcolibur.nav.giftshop.paidaccts=Платні рахунки + +xcolibur.nav.help=Допомога + +xcolibur.nav.help.ask=ПоÑтавити Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ + +xcolibur.nav.help.contact=Контактні Ð´Ð°Ð½Ñ– + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Загубили пароль? + +xcolibur.nav.home=Початок + +xcolibur.nav.journal=Журнал + +xcolibur.nav.journal.archive=Ðрхів + +xcolibur.nav.journal.comments=Коментарі + +xcolibur.nav.journal.edit.entries=Змінити запиÑи + +xcolibur.nav.journal.friends=Друзі + +xcolibur.nav.journal.info=Дані + +xcolibur.nav.journal.memories=Вибране + +xcolibur.nav.journal.recent=ОÑтанні запиÑи + +xcolibur.nav.journal.update=Поновити + +xcolibur.nav.manage=Редагувати + +xcolibur.nav.manage.accountstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ° + +xcolibur.nav.manage.community=Спільноти + +xcolibur.nav.manage.customize=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + +xcolibur.nav.manage.entries=ЗапиÑи + +xcolibur.nav.manage.friends=Друзів + +xcolibur.nav.manage.info=ОÑобиÑÑ‚Ñ– дані + +xcolibur.nav.manage.mobile=Мобільний + +xcolibur.nav.manage.password=Пароль + +xcolibur.nav.manage.styles=Стилі + +xcolibur.nav.manage.tags=Теги + +xcolibur.nav.manage.userpics=Юзерпики + +xcolibur.nav.mylj=Мій LJ + +xcolibur.nav.scrapbook=ScrapBook + +xcolibur.nav.scrapbook.galleries=Галереї + +xcolibur.nav.scrapbook.groups=Групи + +xcolibur.nav.scrapbook.main=Головна + +xcolibur.nav.scrapbook.styles=Стилі + +xcolibur.nav.scrapbook.taggingtool=Редактор теґів + +xcolibur.nav.scrapbook.tags=Теги + +xcolibur.nav.scrapbook.upload=Завантажити + +xcolibur.nav.scrapbook.view=ДивитиÑÑ + +xcolibur.nav.search=Пошук + +xcolibur.nav.search.directory=За регіоном + +xcolibur.nav.search.directory.search=Розширений + +xcolibur.nav.search.feeds=Потоки + +xcolibur.nav.search.interests=За зацікавленнÑм + +xcolibur.nav.search.random=Випадково + +xcolibur.nav.search.schools=Ðавчальні заклади + +xcolibur.nav.siteopts=Параметри переглÑду + +xcolibur.nav.title=ÐавігаціÑ: + +xcolibur.nav.welcome=ЛаÑкаво проÑимо + +xcolibur.nav.welcome.create=Створити рахунок + +xcolibur.nav.welcome.login=Увійти + +xcolibur.nav.welcome.update=Поновити журнал + +xcolibur.search=Пошук: + +xcolibur.search.aolim=AOL IM + +xcolibur.search.category=КатегоріÑ: + +xcolibur.search.icq=Ðомер ICQ + +xcolibur.search.int=Ð—Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»ÐµÐ½Ð½Ñ + +xcolibur.search.jabber=Jabber + +xcolibur.search.msn=MSN-ім'Ñ + +xcolibur.search.region=Регіон + +xcolibur.search.site=Сайт + +xcolibur.search.siteandusername=Сайт та кориÑтувачі + +xcolibur.search.yahoo=Yahoo! ID + +xcolibur.upgrade=Зробити рахунок платним + diff --git a/local/bin/upgrading/update-db-general.pl b/local/bin/upgrading/update-db-general.pl new file mode 100755 index 0000000..d48eee2 --- /dev/null +++ b/local/bin/upgrading/update-db-general.pl @@ -0,0 +1,2587 @@ +# +# database schema & data info +# + +mark_clustered(@LJ::USER_TABLES); + +register_tablecreate("adopt", <<'EOC'); +CREATE TABLE adopt ( + adoptid int(10) unsigned NOT NULL auto_increment, + helperid int(10) unsigned NOT NULL default '0', + newbieid int(10) unsigned NOT NULL default '0', + changetime datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (adoptid), + KEY (helperid), + KEY (newbieid) +) +EOC + +register_tablecreate("adoptlast", <<'EOC'); +CREATE TABLE adoptlast ( + userid int(10) unsigned NOT NULL default '0', + lastassigned datetime NOT NULL default '0000-00-00 00:00:00', + lastadopted datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("authactions", <<'EOC'); +CREATE TABLE authactions ( + aaid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + datecreate datetime NOT NULL default '0000-00-00 00:00:00', + authcode varchar(20) default NULL, + action varchar(50) default NULL, + arg1 varchar(255) default NULL, + PRIMARY KEY (aaid) +) +EOC + +register_tablecreate("clients", <<'EOC'); +CREATE TABLE clients ( + clientid smallint(5) unsigned NOT NULL auto_increment, + client varchar(40) default NULL, + PRIMARY KEY (clientid), + KEY (client) +) +EOC + +post_create("clients", + "sqltry" => "INSERT INTO clients (client) SELECT DISTINCT client FROM logins", + ); + +register_tablecreate("clientusage", <<'EOC'); +CREATE TABLE clientusage ( + userid int(10) unsigned NOT NULL default '0', + clientid smallint(5) unsigned NOT NULL default '0', + lastlogin datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (clientid,userid), + UNIQUE KEY userid (userid,clientid) +) +EOC + +post_create("clientusage", + "sqltry" => "INSERT INTO clientusage SELECT u.userid, c.clientid, l.lastlogin FROM user u, clients c, logins l WHERE u.user=l.user AND l.client=c.client", + ); + +register_tablecreate("codes", <<'EOC'); +CREATE TABLE codes ( + type varchar(10) NOT NULL default '', + code varchar(7) NOT NULL default '', + item varchar(80) default NULL, + sortorder smallint(6) NOT NULL default '0', + PRIMARY KEY (type,code) +) PACK_KEYS=1 +EOC + +register_tablecreate("community", <<'EOC'); +CREATE TABLE community ( + userid int(10) unsigned NOT NULL default '0', + ownerid int(10) unsigned NOT NULL default '0', + membership enum('open','closed') NOT NULL default 'open', + postlevel enum('members','select','screened') default NULL, + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("dirsearchres2", <<'EOC'); +CREATE TABLE dirsearchres2 ( + qdigest varchar(32) NOT NULL default '', + dateins datetime NOT NULL default '0000-00-00 00:00:00', + userids blob, + PRIMARY KEY (qdigest), + KEY (dateins) +) +EOC + +register_tablecreate("duplock", <<'EOC'); +CREATE TABLE duplock ( + realm enum('support','log','comment') NOT NULL default 'support', + reid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + digest char(32) NOT NULL default '', + dupid int(10) unsigned NOT NULL default '0', + instime datetime NOT NULL default '0000-00-00 00:00:00', + KEY (realm,reid,userid) +) +EOC + +register_tablecreate("faq", <<'EOC'); +CREATE TABLE faq ( + faqid mediumint(8) unsigned NOT NULL auto_increment, + question text, + answer text, + sortorder int(11) default NULL, + faqcat varchar(20) default NULL, + lastmodtime datetime default NULL, + lastmoduserid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (faqid) +) +EOC + +register_tablecreate("faqcat", <<'EOC'); +CREATE TABLE faqcat ( + faqcat varchar(20) NOT NULL default '', + faqcatname varchar(100) default NULL, + catorder int(11) default '50', + PRIMARY KEY (faqcat) +) +EOC + +register_tablecreate("faquses", <<'EOC'); +CREATE TABLE faquses ( + faqid MEDIUMINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + dateview DATETIME NOT NULL, + PRIMARY KEY (userid, faqid), + KEY (faqid), + KEY (dateview) +) +EOC + +register_tablecreate("friendgroup", <<'EOC'); +CREATE TABLE friendgroup ( + userid int(10) unsigned NOT NULL default '0', + groupnum tinyint(3) unsigned NOT NULL default '0', + groupname varchar(30) NOT NULL default '', + sortorder tinyint(3) unsigned NOT NULL default '50', + is_public enum('0','1') NOT NULL default '0', + PRIMARY KEY (userid,groupnum) +) +EOC + +register_tablecreate("friends", <<'EOC'); +CREATE TABLE friends ( + userid int(10) unsigned NOT NULL default '0', + friendid int(10) unsigned NOT NULL default '0', + fgcolor char(7) default NULL, + bgcolor char(7) default NULL, + groupmask int(10) unsigned NOT NULL default '1', + showbydefault enum('1','0') NOT NULL default '1', + PRIMARY KEY (userid,friendid), + KEY (friendid) +) +EOC + +register_tablecreate("twits", <<'EOC'); +CREATE TABLE twits ( + userid int(10) unsigned NOT NULL default '0', + twitid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,twitid), + KEY (friendid) +) +EOC + +register_tablecreate("interests", <<'EOC'); +CREATE TABLE interests ( + intid int(10) unsigned NOT NULL auto_increment, + interest varchar(255) NOT NULL default '', + intcount mediumint(8) unsigned default NULL, + PRIMARY KEY (intid), + UNIQUE interest (interest) +) +EOC + +register_tablecreate("keywords", <<'EOC'); +CREATE TABLE keywords ( + kwid int(10) unsigned NOT NULL auto_increment, + keyword varchar(80) binary NOT NULL default '', + PRIMARY KEY (kwid), + UNIQUE KEY kwidx (keyword) +) +EOC + +register_tablecreate("logproplist", <<'EOC'); +CREATE TABLE logproplist ( + propid tinyint(3) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + prettyname varchar(60) default NULL, + sortorder mediumint(8) unsigned default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (propid), + UNIQUE KEY name (name) +) +EOC + +register_tablecreate("memkeyword", <<'EOC'); +CREATE TABLE memkeyword ( + memid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (memid,kwid) +) +EOC + +register_tablecreate("memorable", <<'EOC'); +CREATE TABLE memorable ( + memid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + itemid int(10) unsigned NOT NULL default '0', + des varchar(60) default NULL, + security enum('public','friends','private') NOT NULL default 'public', + PRIMARY KEY (memid), + UNIQUE KEY userid (userid,itemid), + KEY (itemid) +) +EOC + +register_tablecreate("moods", <<'EOC'); +CREATE TABLE moods ( + moodid int(10) unsigned NOT NULL auto_increment, + mood varchar(40) default NULL, + parentmood int(10) unsigned NOT NULL default '0', + PRIMARY KEY (moodid), + UNIQUE KEY mood (mood) +) +EOC + +register_tablecreate("moodthemedata", <<'EOC'); +CREATE TABLE moodthemedata ( + moodthemeid int(10) unsigned NOT NULL default '0', + moodid int(10) unsigned NOT NULL default '0', + picurl varchar(100) default NULL, + width tinyint(3) unsigned NOT NULL default '0', + height tinyint(3) unsigned NOT NULL default '0', + KEY (moodthemeid), + PRIMARY KEY (moodthemeid,moodid) +) +EOC + +register_tablecreate("moodthemes", <<'EOC'); +CREATE TABLE moodthemes ( + moodthemeid int(10) unsigned NOT NULL auto_increment, + ownerid int(10) unsigned NOT NULL default '0', + name varchar(50) default NULL, + des varchar(100) default NULL, + is_public enum('Y','N') NOT NULL default 'N', + PRIMARY KEY (moodthemeid), + KEY (is_public), + KEY (ownerid) +) +EOC + +register_tablecreate("news_sent", <<'EOC'); +CREATE TABLE news_sent ( + newsid int(10) unsigned NOT NULL auto_increment, + newsnum mediumint(8) unsigned NOT NULL default '0', + user varchar(15) NOT NULL default '', + datesent datetime default NULL, + email varchar(100) NOT NULL default '', + PRIMARY KEY (newsid), + KEY (newsnum), + KEY (user), + KEY (email) +) +EOC + +register_tablecreate("noderefs", <<'EOC'); +CREATE TABLE noderefs ( + nodetype char(1) NOT NULL default '', + nodeid int(10) unsigned NOT NULL default '0', + urlmd5 varchar(32) NOT NULL default '', + url varchar(120) NOT NULL default '', + PRIMARY KEY (nodetype,nodeid,urlmd5) +) +EOC + +register_tablecreate("overrides", <<'EOC'); # global, old +CREATE TABLE overrides ( + user varchar(15) NOT NULL default '', + override text, + PRIMARY KEY (user) +) +EOC + +register_tablecreate("pendcomments", <<'EOC'); +CREATE TABLE pendcomments ( + jid int(10) unsigned NOT NULL, + pendcid int(10) unsigned NOT NULL, + data blob NOT NULL, + datesubmit int(10) unsigned NOT NULL, + PRIMARY KEY (pendcid, jid), + KEY (datesubmit) +) +EOC + +register_tablecreate("poll", <<'EOC'); +CREATE TABLE poll ( + pollid int(10) unsigned NOT NULL auto_increment, + itemid int(10) unsigned NOT NULL default '0', + journalid int(10) unsigned NOT NULL default '0', + posterid int(10) unsigned NOT NULL default '0', + whovote enum('all','friends') NOT NULL default 'all', + whoview enum('all','friends','none') NOT NULL default 'all', + name varchar(255) default NULL, + PRIMARY KEY (pollid), + KEY (itemid), + KEY (journalid), + KEY (posterid) +) +EOC + +register_tablecreate("pollitem", <<'EOC'); +CREATE TABLE pollitem ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + pollitid tinyint(3) unsigned NOT NULL default '0', + sortorder tinyint(3) unsigned NOT NULL default '0', + item varchar(255) default NULL, + PRIMARY KEY (pollid,pollqid,pollitid) +) +EOC + +register_tablecreate("pollquestion", <<'EOC'); +CREATE TABLE pollquestion ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + sortorder tinyint(3) unsigned NOT NULL default '0', + type enum('check','radio','drop','text','scale') default NULL, + opts varchar(20) default NULL, + qtext text, + PRIMARY KEY (pollid,pollqid) +) +EOC + +register_tablecreate("pollresult", <<'EOC'); +CREATE TABLE pollresult ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (pollid,pollqid,userid), + KEY (pollid,userid) +) +EOC + +register_tablecreate("pollsubmission", <<'EOC'); +CREATE TABLE pollsubmission ( + pollid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + datesubmit datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (pollid,userid), + KEY (userid) +) +EOC + +register_tablecreate("priv_list", <<'EOC'); +CREATE TABLE priv_list ( + prlid smallint(5) unsigned NOT NULL auto_increment, + privcode varchar(20) NOT NULL default '', + privname varchar(40) default NULL, + des varchar(255) default NULL, + is_public ENUM('1', '0') DEFAULT '1' NOT NULL, + PRIMARY KEY (prlid), + UNIQUE KEY privcode (privcode) +) +EOC + +register_tablecreate("priv_map", <<'EOC'); +CREATE TABLE priv_map ( + prmid mediumint(8) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + prlid smallint(5) unsigned NOT NULL default '0', + arg varchar(40) default NULL, + PRIMARY KEY (prmid), + KEY (userid), + KEY (prlid) +) +EOC + +register_tablecreate("cmdbuffer", <<'EOC'); +CREATE TABLE cmdbuffer ( + cbid INT UNSIGNED NOT NULL AUTO_INCREMENT, + journalid INT UNSIGNED NOT NULL, + cmd VARCHAR(30) NOT NULL default '', + instime datetime NOT NULL default '0000-00-00 00:00:00', + args TEXT NOT NULL, + PRIMARY KEY (cbid), + KEY (cmd), + KEY (journalid) +) +EOC + +register_tablecreate("randomuserset", <<'EOC'); +CREATE TABLE randomuserset ( + rid INT UNSIGNED NOT NULL AUTO_INCREMENT, + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (rid) +) +EOC + +register_tablecreate("schemacols", <<'EOC'); +CREATE TABLE schemacols ( + tablename varchar(40) NOT NULL default '', + colname varchar(40) NOT NULL default '', + des varchar(255) default NULL, + PRIMARY KEY (tablename,colname) +) +EOC + +register_tablecreate("schematables", <<'EOC'); +CREATE TABLE schematables ( + tablename varchar(40) NOT NULL default '', + public_browsable enum('0','1') NOT NULL default '0', + redist_mode enum('off','insert','replace') NOT NULL default 'off', + des text, + PRIMARY KEY (tablename) +) +EOC + +register_tablecreate("stats", <<'EOC'); +CREATE TABLE stats ( + statcat varchar(30) NOT NULL, + statkey varchar(150) NOT NULL, + statval int(10) unsigned NOT NULL, + UNIQUE KEY statcat_2 (statcat,statkey) +) +EOC + +register_tablecreate("blobcache", <<'EOC'); +CREATE TABLE blobcache ( + bckey VARCHAR(40) NOT NULL, + PRIMARY KEY (bckey), + dateupdate DATETIME, + value MEDIUMBLOB +) +EOC + +register_tablecreate("style", <<'EOC'); +CREATE TABLE style ( + styleid int(11) NOT NULL auto_increment, + user varchar(15) NOT NULL default '', + styledes varchar(50) default NULL, + type varchar(10) NOT NULL default '', + formatdata text, + is_public enum('Y','N') NOT NULL default 'N', + is_embedded enum('Y','N') NOT NULL default 'N', + is_colorfree enum('Y','N') NOT NULL default 'N', + opt_cache enum('Y','N') NOT NULL default 'N', + has_ads enum('Y','N') NOT NULL default 'N', + lastupdate datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (styleid), + KEY (user), + KEY (type) +) PACK_KEYS=1 +EOC + +# cache Storable-frozen pre-cleaned style variables +register_tablecreate("s1stylecache", <<'EOC'); # clustered +CREATE TABLE s1stylecache ( + styleid INT UNSIGNED NOT NULL PRIMARY KEY, + cleandate DATETIME, + type VARCHAR(10) NOT NULL DEFAULT '', + opt_cache ENUM('Y','N') NOT NULL DEFAULT 'N', + vars_stor BLOB, + vars_cleanver SMALLINT UNSIGNED NOT NULL +) +EOC + +# caches Storable-frozen pre-cleaned overrides & colors +register_tablecreate("s1usercache", <<'EOC'); # clustered +CREATE TABLE s1usercache ( + userid INT UNSIGNED NOT NULL PRIMARY KEY, + override_stor BLOB, + override_cleanver SMALLINT UNSIGNED NOT NULL, + color_stor BLOB +) +EOC + +register_tablecreate("support", <<'EOC'); +CREATE TABLE support ( + spid int(10) unsigned NOT NULL auto_increment, + reqtype enum('user','email') default NULL, + requserid int(10) unsigned NOT NULL default '0', + reqname varchar(50) default NULL, + reqemail varchar(70) default NULL, + state enum('open','closed') default NULL, + authcode varchar(15) NOT NULL default '', + spcatid int(10) unsigned NOT NULL default '0', + subject varchar(80) default NULL, + timecreate int(10) unsigned default NULL, + timetouched int(10) unsigned default NULL, + timeclosed int(10) unsigned default NULL, + PRIMARY KEY (spid), + INDEX (state), + INDEX (requserid), + INDEX (reqemail) +) +EOC + +register_tablecreate("supportcat", <<'EOC'); +CREATE TABLE supportcat ( + spcatid int(10) unsigned NOT NULL auto_increment, + catname varchar(80) default NULL, + sortorder mediumint(8) unsigned NOT NULL default '0', + basepoints tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (spcatid) +) +EOC + +register_tablecreate("supportlog", <<'EOC'); +CREATE TABLE supportlog ( + splid int(10) unsigned NOT NULL auto_increment, + spid int(10) unsigned NOT NULL default '0', + timelogged int(10) unsigned NOT NULL default '0', + type enum('req','custom','faqref') default NULL, + faqid mediumint(8) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + message text, + PRIMARY KEY (splid), + KEY (spid) +) +EOC + +register_tablecreate("supportnotify", <<'EOC'); +CREATE TABLE supportnotify ( + spcatid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + level enum('all','new') default NULL, + KEY (spcatid), + KEY (userid), + PRIMARY KEY (spcatid,userid) +) +EOC + +register_tablecreate("supportpoints", <<'EOC'); +CREATE TABLE supportpoints ( + spid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + points tinyint(3) unsigned default NULL, + KEY (spid), + KEY (userid) +) +EOC + +register_tablecreate("supportpointsum", <<'EOC'); +CREATE TABLE supportpointsum ( + userid INT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid), + totpoints MEDIUMINT UNSIGNED DEFAULT 0, + lastupdate INT UNSIGNED NOT NULL, + INDEX (totpoints, lastupdate), + INDEX (lastupdate) +) +EOC + +post_create("supportpointsum", + "sqltry" => "INSERT IGNORE INTO supportpointsum (userid, totpoints, lastupdate) " . + "SELECT userid, SUM(points), 0 FROM supportpoints GROUP BY userid", + ); + + +register_tablecreate("talkproplist", <<'EOC'); +CREATE TABLE talkproplist ( + tpropid smallint(5) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + prettyname varchar(60) default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (tpropid), + UNIQUE KEY name (name) +) +EOC + +register_tablecreate("themedata", <<'EOC'); +CREATE TABLE themedata ( + themeid mediumint(8) unsigned NOT NULL default '0', + coltype varchar(30) default NULL, + color varchar(30) default NULL, + KEY (themeid) +) PACK_KEYS=1 +EOC + +register_tablecreate("themelist", <<'EOC'); +CREATE TABLE themelist ( + themeid mediumint(8) unsigned NOT NULL auto_increment, + name varchar(50) NOT NULL default '', + PRIMARY KEY (themeid) +) +EOC + +register_tablecreate("todo", <<'EOC'); +CREATE TABLE todo ( + todoid int(10) unsigned NOT NULL auto_increment, + journalid int(10) unsigned NOT NULL default '0', + posterid int(10) unsigned NOT NULL default '0', + ownerid int(10) unsigned NOT NULL default '0', + statusline varchar(40) default NULL, + security enum('public','private','friends') NOT NULL default 'public', + subject varchar(100) default NULL, + des varchar(255) default NULL, + priority enum('1','2','3','4','5') NOT NULL default '3', + datecreate datetime NOT NULL default '0000-00-00 00:00:00', + dateupdate datetime default NULL, + datedue datetime default NULL, + dateclosed datetime default NULL, + progress tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (todoid), + KEY (journalid), + KEY (posterid), + KEY (ownerid) +) +EOC + +register_tablecreate("tododep", <<'EOC'); +CREATE TABLE tododep ( + todoid int(10) unsigned NOT NULL default '0', + depid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (todoid,depid), + KEY (depid) +) +EOC + +register_tablecreate("todokeyword", <<'EOC'); +CREATE TABLE todokeyword ( + todoid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (todoid,kwid) +) +EOC + +register_tablecreate("txtmsg", <<'EOC'); +CREATE TABLE txtmsg ( + userid int(10) unsigned NOT NULL default '0', + provider varchar(25) default NULL, + number varchar(60) default NULL, + security enum('all','reg','friends') NOT NULL default 'all', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("user", <<'EOC'); +CREATE TABLE user ( + userid int(10) unsigned NOT NULL auto_increment, + user char(15) default NULL, + caps SMALLINT UNSIGNED NOT NULL DEFAULT 0, + email char(50) default NULL, + password char(30) default NULL, + status char(1) NOT NULL default 'N', + statusvis char(1) NOT NULL default 'V', + statusvisdate datetime default NULL, + name char(50) default NULL, + bdate date default NULL, + themeid int(11) NOT NULL default '1', + moodthemeid int(10) unsigned NOT NULL default '1', + opt_forcemoodtheme enum('Y','N') NOT NULL default 'N', + allow_infoshow char(1) NOT NULL default 'Y', + allow_contactshow char(1) NOT NULL default 'Y', + allow_getljnews char(1) NOT NULL default 'N', + opt_showtalklinks char(1) NOT NULL default 'Y', + opt_whocanreply enum('all','reg','friends') NOT NULL default 'all', + opt_gettalkemail char(1) NOT NULL default 'Y', + opt_htmlemail enum('Y','N') NOT NULL default 'Y', + opt_mangleemail char(1) NOT NULL default 'N', + useoverrides char(1) NOT NULL default 'N', + defaultpicid int(10) unsigned default NULL, + has_bio enum('Y','N') NOT NULL default 'N', + txtmsg_status enum('none','on','off') NOT NULL default 'none', + is_system enum('Y','N') NOT NULL default 'N', + journaltype char(1) NOT NULL default 'P', + lang char(2) NOT NULL default 'EN', + PRIMARY KEY (userid), + UNIQUE KEY user (user), + KEY (email), + KEY (status), + KEY (statusvis) +) PACK_KEYS=1 +EOC + +register_tablecreate("userbio", <<'EOC'); +CREATE TABLE userbio ( + userid int(10) unsigned NOT NULL default '0', + bio text, + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("userinterests", <<'EOC'); +CREATE TABLE userinterests ( + userid int(10) unsigned NOT NULL default '0', + intid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,intid), + KEY (intid) +) +EOC + +register_tablecreate("userpic", <<'EOC'); +CREATE TABLE userpic ( + picid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + contenttype char(25) default NULL, + width smallint(6) NOT NULL default '0', + height smallint(6) NOT NULL default '0', + state char(1) NOT NULL default 'N', + picdate datetime default NULL, + md5base64 char(22) NOT NULL default '', + PRIMARY KEY (picid), + KEY (userid), + KEY (state) +) +EOC + +register_tablecreate("userpicblob2", <<'EOC'); +CREATE TABLE userpicblob2 ( + userid int unsigned not null, + picid int unsigned not null, + imagedata blob, + PRIMARY KEY (userid, picid) +) max_rows=10000000 +EOC + +register_tablecreate("userpicmap", <<'EOC'); +CREATE TABLE userpicmap ( + userid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + picid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,kwid) +) +EOC + +register_tablecreate("userpicmap2", <<'EOC'); +CREATE TABLE userpicmap2 ( + userid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + picid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid, kwid) +) +EOC + +register_tablecreate("userpic2", <<'EOC'); +CREATE TABLE userpic2 ( + picid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + fmt char(1) default NULL, + width smallint(6) NOT NULL default '0', + height smallint(6) NOT NULL default '0', + state char(1) NOT NULL default 'N', + picdate datetime default NULL, + md5base64 char(22) NOT NULL default '', + comment varchar(255) BINARY NOT NULL default '', + flags tinyint(1) unsigned NOT NULL default 0, + location enum('blob','disk','mogile') default NULL, + PRIMARY KEY (picid) +) +EOC + +# - blobids aren't necessarily unique between domains; +# global userpicids may collide with the counter used for the rest. +# so type must be in the key. +# - domain ids are set up in ljconfig.pl. +# - NULL length indicates the data is external-- we need another +# table for more data for that. +register_tablecreate("userblob", <<'EOC'); # clustered +CREATE TABLE userblob ( + journalid INT UNSIGNED NOT NULL, + domain TINYINT UNSIGNED NOT NULL, + blobid MEDIUMINT UNSIGNED NOT NULL, + length MEDIUMINT UNSIGNED, + PRIMARY KEY (journalid, domain, blobid), + KEY (domain) +) +EOC + +register_tablecreate("userproplist", <<'EOC'); +CREATE TABLE userproplist ( + upropid smallint(5) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + indexed enum('1','0') NOT NULL default '1', + prettyname varchar(60) default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (upropid), + UNIQUE KEY name (name) +) +EOC + +# global, indexed +register_tablecreate("userprop", <<'EOC'); +CREATE TABLE userprop ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(60) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid,value) +) +EOC + +# global, not indexed +register_tablecreate("userproplite", <<'EOC'); +CREATE TABLE userproplite ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid) +) +EOC + +# clustered, not indexed +register_tablecreate("userproplite2", <<'EOC'); +CREATE TABLE userproplite2 ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid) +) +EOC + +# clustered +register_tablecreate("userpropblob", <<'EOC'); +CREATE TABLE userpropblob ( + userid INT(10) unsigned NOT NULL default '0', + upropid SMALLINT(5) unsigned NOT NULL default '0', + value blob, + PRIMARY KEY (userid,upropid) +) +EOC + +register_tablecreate("backupdirty", <<'EOC'); +CREATE TABLE backupdirty ( + userid INT(10) unsigned NOT NULL default '0', + marktime INT(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("zip", <<'EOC'); +CREATE TABLE zip ( + zip varchar(5) NOT NULL default '', + state char(2) NOT NULL default '', + city varchar(100) NOT NULL default '', + PRIMARY KEY (zip), + KEY (state) +) PACK_KEYS=1 +EOC + +register_tablecreate("zips", <<'EOC'); +CREATE TABLE zips ( + FIPS char(2) default NULL, + zip varchar(5) NOT NULL default '', + State char(2) NOT NULL default '', + Name varchar(30) NOT NULL default '', + alloc float(9,7) NOT NULL default '0.0000000', + pop1990 int(11) NOT NULL default '0', + lon float(10,7) NOT NULL default '0.0000000', + lat float(10,7) NOT NULL default '0.0000000', + PRIMARY KEY (zip) +) +EOC + +################# above was a snapshot. now, changes: + +register_tablecreate("log2", <<'EOC'); +CREATE TABLE log2 ( + journalid INT UNSIGNED NOT NULL default '0', + jitemid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jitemid), + posterid int(10) unsigned NOT NULL default '0', + eventtime datetime default NULL, + logtime datetime default NULL, + compressed char(1) NOT NULL default 'N', + anum TINYINT UNSIGNED NOT NULL, + security enum('public','private','usemask') NOT NULL default 'public', + allowmask int(10) unsigned NOT NULL default '0', + replycount smallint(5) unsigned default NULL, + year smallint(6) NOT NULL default '0', + month tinyint(4) NOT NULL default '0', + day tinyint(4) NOT NULL default '0', + rlogtime int(10) unsigned NOT NULL default '0', + revttime int(10) unsigned NOT NULL default '0', + KEY (journalid,year,month,day), + KEY `rlogtime` (`journalid`,`rlogtime`), + KEY `revttime` (`journalid`,`revttime`), + KEY `posterid` (`posterid`,`journalid`) +) +EOC + +register_tablecreate("logtext2", <<'EOC'); +CREATE TABLE logtext2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + subject VARCHAR(255) DEFAULT NULL, + event TEXT, + PRIMARY KEY (journalid, jitemid) +) max_rows=100000000 +EOC + +register_tablecreate("logprop2", <<'EOC'); +CREATE TABLE logprop2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + propid TINYINT unsigned NOT NULL, + value VARCHAR(255) default NULL, + PRIMARY KEY (journalid,jitemid,propid) +) +EOC + +register_tablecreate("logsec2", <<'EOC'); +CREATE TABLE logsec2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + allowmask INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid,jitemid) +) +EOC + +register_tablecreate("talk2", <<'EOC'); +CREATE TABLE talk2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL DEFAULT '', + nodeid INT UNSIGNED NOT NULL default '0', + parenttalkid MEDIUMINT UNSIGNED NOT NULL, + posterid INT UNSIGNED NOT NULL default '0', + datepost DATETIME NOT NULL default '0000-00-00 00:00:00', + state CHAR(1) default 'A', + PRIMARY KEY (journalid,jtalkid), + KEY (nodetype,journalid,nodeid), + KEY (journalid,state,nodetype), + KEY (posterid) +) +EOC + +register_tablecreate("talkprop2", <<'EOC'); +CREATE TABLE talkprop2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + tpropid TINYINT UNSIGNED NOT NULL, + value VARCHAR(255) DEFAULT NULL, + PRIMARY KEY (journalid,jtalkid,tpropid) +) +EOC + +register_tablecreate("talktext2", <<'EOC'); +CREATE TABLE talktext2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + subject VARCHAR(100) DEFAULT NULL, + body TEXT, + PRIMARY KEY (journalid, jtalkid) +) max_rows=100000000 +EOC + +register_tablecreate("talkleft", <<'EOC'); +CREATE TABLE talkleft ( + userid INT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + INDEX (userid, posttime), + journalid INT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL, + nodeid INT UNSIGNED NOT NULL, + INDEX (journalid, nodetype, nodeid), + jtalkid MEDIUMINT UNSIGNED NOT NULL, + publicitem ENUM('1','0') NOT NULL DEFAULT '1' +) +EOC + +register_tablecreate("talkleft_xfp", <<'EOC'); +CREATE TABLE talkleft_xfp ( + userid INT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + INDEX (userid, posttime), + journalid INT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL, + nodeid INT UNSIGNED NOT NULL, + INDEX (journalid, nodetype, nodeid), + jtalkid MEDIUMINT UNSIGNED NOT NULL, + publicitem ENUM('1','0') NOT NULL DEFAULT '1' +) +EOC + +register_tabledrop("ibill_codes"); +register_tabledrop("paycredit"); +register_tabledrop("payments"); +register_tabledrop("tmp_contributed"); +register_tabledrop("transferinfo"); +register_tabledrop("contest1"); +register_tabledrop("contest1data"); +register_tabledrop("logins"); +register_tabledrop("hintfriendsview"); +register_tabledrop("hintlastnview"); +register_tabledrop("batchdelete"); +register_tabledrop("ftpusers"); +register_tabledrop("ipban"); +register_tabledrop("ban"); +register_tabledrop("logaccess"); +register_tabledrop("fvcache"); +register_tabledrop("userpic_comment"); + +register_tablecreate("portal", <<'EOC'); +CREATE TABLE portal ( + userid int(10) unsigned NOT NULL default '0', + loc enum('left','main','right','moz') NOT NULL default 'left', + pos tinyint(3) unsigned NOT NULL default '0', + boxname varchar(30) default NULL, + boxargs varchar(255) default NULL, + PRIMARY KEY (userid,loc,pos), + KEY boxname (boxname) +) +EOC + +register_tablecreate("infohistory", <<'EOC'); +CREATE TABLE infohistory ( + userid int(10) unsigned NOT NULL default '0', + what varchar(15) NOT NULL default '', + timechange datetime NOT NULL default '0000-00-00 00:00:00', + oldvalue varchar(255) default NULL, + other varchar(30) default NULL, + KEY userid (userid) +) +EOC + +register_tablecreate("useridmap", <<'EOC'); +CREATE TABLE useridmap ( + userid int(10) unsigned NOT NULL, + user char(15) NOT NULL, + PRIMARY KEY (userid), + UNIQUE KEY user (user) +) +EOC + +post_create("useridmap", + "sqltry" => "REPLACE INTO useridmap (userid, user) SELECT userid, user FROM user", + ); + +register_tablecreate("userusage", <<'EOC'); +CREATE TABLE userusage +( + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid), + timecreate DATETIME NOT NULL, + timeupdate DATETIME, + timecheck DATETIME, + lastitemid INT UNSIGNED NOT NULL DEFAULT '0', + INDEX (timeupdate) +) +EOC + +# wknum - number of weeks past unix epoch time +# ubefore - units before next week (unit = 10 seconds) +# uafter - units after this week (unit = 10 seconds) +register_tablecreate("weekuserusage", <<'EOC'); +CREATE TABLE weekuserusage +( + wknum SMALLINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (wknum, userid), + ubefore SMALLINT UNSIGNED NOT NULL, + uafter SMALLINT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("userupdate", <<'EOC'); +CREATE TABLE userupdate +( + userid INT UNSIGNED NOT NULL, + groupbit TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, groupbit), + timeupdate DATETIME NOT NULL +) +EOC + + +post_create("userusage", + "sqltry" => "INSERT IGNORE INTO userusage (userid, timecreate, timeupdate, timecheck, lastitemid) SELECT userid, timecreate, timeupdate, timecheck, lastitemid FROM user", + "sqltry" => "ALTER TABLE user DROP timecreate, DROP timeupdate, DROP timecheck, DROP lastitemid", + ); + +register_tablecreate("acctcode", <<'EOC'); +CREATE TABLE acctcode +( + acid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + userid INT UNSIGNED NOT NULL, + rcptid INT UNSIGNED NOT NULL DEFAULT 0, + auth CHAR(5) NOT NULL, + INDEX (userid), + INDEX (rcptid) +) +EOC + +register_tablecreate("meme", <<'EOC'); +CREATE TABLE meme ( + url VARCHAR(150) NOT NULL, + posterid INT UNSIGNED NOT NULL, + UNIQUE (url, posterid), + ts TIMESTAMP, + itemid INT UNSIGNED NOT NULL, + INDEX (ts) +) +EOC + +register_tablecreate("statushistory", <<'EOC'); +CREATE TABLE statushistory ( + userid INT UNSIGNED NOT NULL, + adminid INT UNSIGNED NOT NULL, + shtype VARCHAR(20) NOT NULL, + shdate TIMESTAMP NOT NULL, + notes TEXT, + INDEX (userid, shdate), + INDEX (adminid, shdate), + INDEX (adminid, shtype, shdate), + INDEX (shtype, shdate) +) +EOC + +register_tablecreate("includetext", <<'EOC'); +CREATE TABLE includetext ( + incname VARCHAR(80) NOT NULL PRIMARY KEY, + inctext TEXT, + updatetime INT UNSIGNED NOT NULL, + INDEX (updatetime) +) +EOC + +register_tablecreate("oldids", <<'EOC'); +CREATE TABLE oldids ( + area CHAR(1) NOT NULL, + oldid INT UNSIGNED NOT NULL, + UNIQUE (area, oldid), + userid INT UNSIGNED NOT NULL, + newid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (area,userid, newid), + INDEX (userid) +) TYPE=MYISAM +EOC + +register_tablecreate("dudata", <<'EOC'); +CREATE TABLE dudata ( + userid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + areaid INT UNSIGNED NOT NULL, + bytes MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, area, areaid) +) +EOC + +register_tablecreate("dbinfo", <<'EOC'); +CREATE TABLE dbinfo ( + dbid TINYINT UNSIGNED NOT NULL, + name VARCHAR(25), + fdsn VARCHAR(255), + rootfdsn VARCHAR(255), + masterid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (dbid), + UNIQUE (name) +) +EOC + +register_tablecreate("dbweights", <<'EOC'); +CREATE TABLE dbweights ( + dbid TINYINT UNSIGNED NOT NULL, + role VARCHAR(25) NOT NULL, + PRIMARY KEY (dbid, role), + norm TINYINT UNSIGNED NOT NULL, + curr TINYINT UNSIGNED NOT NULL +) +EOC + +# notification/subscription stuff: + +register_tablecreate("subs", <<'EOC'); # global +CREATE TABLE subs ( + userid INT UNSIGNED NOT NULL, + etype CHAR(1) NOT NULL, + ejournalid INT UNSIGNED NOT NULL, + eiarg INT UNSIGNED NOT NULL, + UNIQUE (userid, etype, ejournalid, eiarg), + INDEX (etype, ejournalid, eiarg), + subtime DATETIME NOT NULL, + exptime DATETIME NOT NULL, + INDEX (exptime), + ntype CHAR(1) NOT NULL +) +EOC + +register_tablecreate("events", <<'EOC'); # clustered +CREATE TABLE events ( + evtime DATETIME NOT NULL, + INDEX (evtime), + etype CHAR(1) NOT NULL, + ejournalid INT UNSIGNED NOT NULL, + eiarg INT UNSIGNED NOT NULL, + duserid INT UNSIGNED NOT NULL, + diarg INT UNSIGNED NOT NULL +) +EOC + +# Begin S2 Stuff +register_tablecreate("s2layers", <<'EOC'); # global +CREATE TABLE s2layers +( + s2lid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (s2lid), + b2lid INT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + INDEX (userid), + INDEX (b2lid, type) +) +EOC + +register_tablecreate("s2info", <<'EOC'); # global +CREATE TABLE s2info +( + s2lid INT UNSIGNED NOT NULL, + infokey VARCHAR(80) NOT NULL, + value VARCHAR(255) NOT NULL, + PRIMARY KEY (s2lid, infokey) +) +EOC + +register_tablecreate("s2source", <<'EOC'); # global +CREATE TABLE s2source +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + s2code MEDIUMBLOB +) +EOC + +register_tablecreate("s2checker", <<'EOC'); # global +CREATE TABLE s2checker +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + checker MEDIUMBLOB +) +EOC + +# the original global s2compiled table. see comment below for new version. +register_tablecreate("s2compiled", <<'EOC'); # global (compdata is not gzipped) +CREATE TABLE s2compiled +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + comptime INT UNSIGNED NOT NULL, + compdata MEDIUMBLOB +) +EOC + +# s2compiled2 is only for user S2 layers (not system) and is lazily +# migrated. new saves go here. loads try this table first (unless +# system) and if miss, then try the s2compiled table on the global. +register_tablecreate("s2compiled2", <<'EOC'); # clustered (compdata is gzipped) +CREATE TABLE s2compiled2 +( + userid INT UNSIGNED NOT NULL, + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid, s2lid), + + comptime INT UNSIGNED NOT NULL, + compdata MEDIUMBLOB +) +EOC + +register_tablecreate("s2styles", <<'EOC'); # global +CREATE TABLE s2styles +( + styleid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (styleid), + userid INT UNSIGNED NOT NULL, + name VARCHAR(255), + modtime INT UNSIGNED NOT NULL, + INDEX (userid) +) +EOC + +register_tablecreate("s2stylelayers", <<'EOC'); # global +CREATE TABLE s2stylelayers +( + styleid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + UNIQUE (styleid, type), + s2lid INT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("s2stylelayers2", <<'EOC'); # clustered +CREATE TABLE s2stylelayers2 +( + userid INT UNSIGNED NOT NULL, + styleid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + PRIMARY KEY (userid, styleid, type), + s2lid INT UNSIGNED NOT NULL +) +EOC + + +register_tablecreate("ml_domains", <<'EOC'); +CREATE TABLE ml_domains +( + dmid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (dmid), + type VARCHAR(30) NOT NULL, + args VARCHAR(255) NOT NULL DEFAULT '', + UNIQUE (type,args) +) +EOC + +register_tablecreate("ml_items", <<'EOC'); +CREATE TABLE ml_items +( + dmid TINYINT UNSIGNED NOT NULL, + itid MEDIUMINT UNSIGNED AUTO_INCREMENT NOT NULL, + PRIMARY KEY (dmid, itid), + itcode VARCHAR(80) NOT NULL, + UNIQUE (dmid, itcode), + notes MEDIUMTEXT +) TYPE=MYISAM +EOC + +register_tablecreate("ml_langs", <<'EOC'); +CREATE TABLE ml_langs +( + lnid SMALLINT UNSIGNED NOT NULL, + UNIQUE (lnid), + lncode VARCHAR(16) NOT NULL, # en_US en_LJ en ch_HK ch_B5 etc... de_DE + UNIQUE (lncode), + lnname VARCHAR(60) NOT NULL, # "Deutsch" + parenttype ENUM('diff','sim') NOT NULL, + parentlnid SMALLINT UNSIGNED NOT NULL, + lastupdate DATETIME NOT NULL +) +EOC + +register_tablecreate("ml_langdomains", <<'EOC'); +CREATE TABLE ml_langdomains +( + lnid SMALLINT UNSIGNED NOT NULL, + dmid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (lnid, dmid), + dmmaster ENUM('0','1') NOT NULL, + lastgetnew DATETIME, + lastpublish DATETIME, + countokay SMALLINT UNSIGNED NOT NULL, + counttotal SMALLINT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("ml_latest", <<'EOC'); +CREATE TABLE ml_latest +( + lnid SMALLINT UNSIGNED NOT NULL, + dmid TINYINT UNSIGNED NOT NULL, + itid SMALLINT UNSIGNED NOT NULL, + PRIMARY KEY (lnid, dmid, itid), + txtid INT UNSIGNED NOT NULL, + chgtime DATETIME NOT NULL, + staleness TINYINT UNSIGNED DEFAULT 0 NOT NULL, # better than ENUM('0','1','2'); + INDEX (lnid, staleness), + INDEX (dmid, itid), + INDEX (lnid, dmid, chgtime), + INDEX (chgtime) +) +EOC + +register_tablecreate("ml_text", <<'EOC'); +CREATE TABLE ml_text +( + dmid TINYINT UNSIGNED NOT NULL, + txtid INT UNSIGNED AUTO_INCREMENT NOT NULL, + PRIMARY KEY (dmid, txtid), + lnid SMALLINT UNSIGNED NOT NULL, + itid SMALLINT UNSIGNED NOT NULL, + INDEX (lnid, dmid, itid), + text TEXT NOT NULL, + userid INT UNSIGNED NOT NULL +) TYPE=MYISAM +EOC + +register_tablecreate("domains", <<'EOC'); +CREATE TABLE domains +( + domain VARCHAR(80) NOT NULL, + PRIMARY KEY (domain), + userid INT UNSIGNED NOT NULL, + INDEX (userid) +) +EOC + +register_tablecreate("procnotify", <<'EOC'); +CREATE TABLE procnotify +( + nid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (nid), + cmd VARCHAR(50), + args VARCHAR(255) +) +EOC + +register_tablecreate("syndicated", <<'EOC'); +CREATE TABLE syndicated +( + userid INT UNSIGNED NOT NULL, + synurl VARCHAR(255), + checknext DATETIME NOT NULL, + lastcheck DATETIME, + lastmod INT UNSIGNED, # unix time + etag VARCHAR(80), + PRIMARY KEY (userid), + UNIQUE (synurl), + INDEX (checknext) +) +EOC + +register_tablecreate("synitem", <<'EOC'); +CREATE TABLE synitem +( + userid INT UNSIGNED NOT NULL, + item CHAR(22), # base64digest of rss $item + dateadd DATETIME NOT NULL, + INDEX (userid, item(3)), + INDEX (userid, dateadd) +) +EOC + +register_tablecreate("ratelist", <<'EOC'); +CREATE TABLE ratelist +( + rlid TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + name varchar(50) not null, + des varchar(255) not null, + PRIMARY KEY (rlid), + UNIQUE KEY (name) + ) +EOC + +register_tablecreate("ratelog", <<'EOC'); +CREATE TABLE ratelog +( + userid INT UNSIGNED NOT NULL, + rlid TINYINT UNSIGNED NOT NULL, + evttime INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + index (userid, rlid, evttime), + quantity SMALLINT UNSIGNED NOT NULL + ) +EOC + +register_tablecreate("rateabuse", <<'EOC'); +CREATE TABLE rateabuse +( + rlid TINYINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + evttime INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + enum ENUM('soft','hard') NOT NULL, + index (rlid, evttime), + index (userid), + index (ip) + ) +EOC + +register_tablecreate("loginstall", <<'EOC'); +CREATE TABLE loginstall +( + userid INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + time INT UNSIGNED NOT NULL, + UNIQUE (userid, ip) + ) +EOC + +# web sessions. optionally tied to ips and with expiration times. +# whenever a session is okayed, expired ones are deleted, or ones +# created over 30 days ago. a live session can't change email address +# or password. digest authentication will be required for that, +# or javascript md5 challenge/response. +register_tablecreate("sessions", <<'EOC'); # user cluster +CREATE TABLE sessions ( + userid MEDIUMINT UNSIGNED NOT NULL, + sessid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, sessid), + auth CHAR(10) NOT NULL, + exptype ENUM('short','long') NOT NULL, # browser closed or "infinite" + timecreate INT UNSIGNED NOT NULL, + timeexpire INT UNSIGNED NOT NULL, + ipfixed CHAR(15) # if null, not fixed at IP. +) +EOC + +register_tablecreate("sessions_data", <<'EOC'); # user cluster +CREATE TABLE sessions_data ( + userid MEDIUMINT UNSIGNED NOT NULL, + sessid MEDIUMINT UNSIGNED NOT NULL, + skey VARCHAR(30) NOT NULL, + PRIMARY KEY (userid, sessid, skey), + sval VARCHAR(255) +) +EOC + +# what: ip, email, ljuser, ua, emailnopay +# emailnopay means don't allow payments from that email +register_tablecreate("sysban", <<'EOC'); +CREATE TABLE sysban ( + banid MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (banid), + status ENUM('active','expired') NOT NULL DEFAULT 'active', + INDEX (status), + bandate DATETIME, + banuntil DATETIME, + what VARCHAR(20) NOT NULL, + value VARCHAR(80), + note VARCHAR(255) +) +EOC + +# clustered relationship types are defined in ljlib.pl and ljlib-local.pl in +# the LJ::get_reluser_id function +register_tablecreate("reluser2", <<'EOC'); +CREATE TABLE reluser2 ( + userid INT UNSIGNED NOT NULL, + type SMALLINT UNSIGNED NOT NULL, + targetid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid,type,targetid), + INDEX (userid,targetid) +) +EOC + +# relationship types: +# 'A' means targetid can administrate userid as a community maintainer +# 'B' means targetid is banned in userid +# 'P' means targetid can post to userid +# 'M' means targetid can moderate the community userid +# 'N' means targetid is preapproved to post to community userid w/o moderation +# new types to be added here + +register_tablecreate("reluser", <<'EOC'); +CREATE TABLE reluser ( + userid INT UNSIGNED NOT NULL, + targetid INT UNSIGNED NOT NULL, + type char(1) NOT NULL, + PRIMARY KEY (userid,type,targetid), + KEY (targetid,type) +) +EOC + +post_create("reluser", + "sqltry" => "INSERT IGNORE INTO reluser (userid, targetid, type) SELECT userid, banneduserid, 'B' FROM ban", + "sqltry" => "INSERT IGNORE INTO reluser (userid, targetid, type) SELECT u.userid, p.userid, 'A' FROM priv_map p, priv_list l, user u WHERE l.privcode='sharedjournal' AND l.prlid=p.prlid AND p.arg=u.user AND p.arg<>'all'", + "code" => sub { + my $dbh = shift; + print "# Converting logaccess rows to reluser...\n"; + my $sth = $dbh->prepare("SELECT MAX(userid) FROM user"); + $sth->execute; + my ($maxid) = $sth->fetchrow_array; + return unless $maxid; + + my $from = 1; my $to = $from + 10000 - 1; + while ($from <= $maxid) { + printf "# logaccess status: (%0.1f%%)\n", ($from * 100 / $maxid); + do_sql("INSERT IGNORE INTO reluser (userid, targetid, type) ". + "SELECT ownerid, posterid, 'P' ". + "FROM logaccess ". + "WHERE ownerid BETWEEN $from AND $to"); + $from += 10000; + $to += 10000; + } + print "# Finished converting logaccess.\n"; + }, + ); + +register_tablecreate("clustermove", <<'EOC'); +CREATE TABLE clustermove ( + cmid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (cmid), + userid INT UNSIGNED NOT NULL, + KEY (userid), + sclust TINYINT UNSIGNED NOT NULL, + dclust TINYINT UNSIGNED NOT NULL, + timestart INT UNSIGNED, + timedone INT UNSIGNED, + sdeleted ENUM('1','0') +) +EOC + +# moderated community post summary info +register_tablecreate("modlog", <<'EOC'); +CREATE TABLE modlog ( + journalid INT UNSIGNED NOT NULL, + modid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, modid), + posterid INT UNSIGNED NOT NULL, + subject CHAR(30), + logtime DATETIME, + KEY (journalid, logtime) +) +EOC + +# moderated community post Storable object (all props/options) +register_tablecreate("modblob", <<'EOC'); +CREATE TABLE modblob ( + journalid INT UNSIGNED NOT NULL, + modid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, modid), + request_stor MEDIUMBLOB +) +EOC + +# user counters +register_tablecreate("counter", <<'EOC'); +CREATE TABLE counter ( + journalid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + PRIMARY KEY (journalid, area), + max MEDIUMINT UNSIGNED NOT NULL +) +EOC + +# user counters on the global (contrary to the name) +register_tablecreate("usercounter", <<'EOC'); +CREATE TABLE usercounter ( + journalid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + PRIMARY KEY (journalid, area), + max INT UNSIGNED NOT NULL +) +EOC + +# community interests +register_tablecreate("comminterests", <<'EOC'); +CREATE TABLE comminterests ( + userid int(10) unsigned NOT NULL default '0', + intid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,intid), + KEY (intid) +) +EOC + +# links +register_tablecreate("links", <<'EOC'); # clustered +CREATE TABLE links ( + journalid int(10) unsigned NOT NULL default '0', + ordernum tinyint(4) unsigned NOT NULL default '0', + parentnum tinyint(4) unsigned NOT NULL default '0', + url varchar(255) default NULL, + title varchar(255) NOT NULL default '', + KEY (journalid) +) +EOC + +# supportprop +register_tablecreate("supportprop", <<'EOC'); +CREATE TABLE supportprop ( + spid int(10) unsigned NOT NULL default '0', + prop varchar(30) NOT NULL, + value varchar(255) NOT NULL, + PRIMARY KEY (spid, prop) +) +EOC + +# s1overrides +register_tablecreate("s1overrides", <<'EOC'); # clustered +CREATE TABLE s1overrides ( + userid int unsigned NOT NULL default '', + override text NOT NULL, + PRIMARY KEY (userid) +) +EOC + +# s1style +register_tablecreate("s1style", <<'EOC'); # clustered +CREATE TABLE s1style ( + styleid int(11) NOT NULL auto_increment, + userid int(11) unsigned NOT NULL, + styledes varchar(50) default NULL, + type varchar(10) NOT NULL default '', + formatdata text, + is_public enum('Y','N') NOT NULL default 'N', + is_embedded enum('Y','N') NOT NULL default 'N', + is_colorfree enum('Y','N') NOT NULL default 'N', + opt_cache enum('Y','N') NOT NULL default 'N', + has_ads enum('Y','N') NOT NULL default 'N', + lastupdate datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (styleid), + KEY (userid) + +) +EOC + +# s1stylemap +register_tablecreate("s1stylemap", <<'EOC'); # global +CREATE TABLE s1stylemap ( + styleid int unsigned NOT NULL, + userid int unsigned NOT NULL, + PRIMARY KEY (styleid) +) +EOC + +# comment urls +register_tablecreate("commenturls", <<'EOC'); # global +CREATE TABLE commenturls ( + posterid int unsigned NOT NULL, + journalid int unsigned NOT NULL, + jtalkid mediumint unsigned NOT NULL, + timecreate int unsigned NOT NULL, + url varchar(255) NOT NULL, + INDEX (timecreate) +) +EOC + +post_create("comminterests", + "code" => sub { + my $dbh = shift; + print "# Populating community interests...\n"; + + my $BLOCK = 1_000; + + my @ids = @{ $dbh->selectcol_arrayref("SELECT userid FROM community") || [] }; + my $total = @ids; + + while (@ids) { + my @set = grep { $_ } splice(@ids, 0, $BLOCK); + + printf ("# community interests status: (%0.1f%%)\n", + ((($total - @ids) / $total) * 100)) if $total > $BLOCK; + + local $" = ","; + do_sql("INSERT IGNORE INTO comminterests (userid, intid) ". + "SELECT userid, intid FROM userinterests " . + "WHERE userid IN (@set)"); + } + + print "# Finished converting community interests.\n"; + }, + ); + +# tracking where users are active +register_tablecreate("clustertrack2", <<'EOC'); # clustered +CREATE TABLE clustertrack2 ( + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid), + timeactive INT UNSIGNED NOT NULL, + clusterid SMALLINT UNSIGNED, + INDEX (timeactive, clusterid) +) +EOC + +# rotating site secret values +register_tablecreate("secrets", <<'EOC'); # global +CREATE TABLE secrets ( + stime INT UNSIGNED NOT NULL, + secret CHAR(32) NOT NULL, + PRIMARY KEY (stime) +) +EOC + +# Captcha table +register_tablecreate("captchas", <<'EOC'); +CREATE TABLE captchas ( + capid INT UNSIGNED NOT NULL auto_increment, + type enum('image','audio'), + issuetime INT UNSIGNED NOT NULL DEFAULT 0, + answer CHAR(10), + userid INT UNSIGNED NOT NULL DEFAULT 0, + anum SMALLINT UNSIGNED NOT NULL, + INDEX(type,issuetime), + INDEX(userid), + PRIMARY KEY(capid) +) +EOC + +# Challenges table (for non-memcache support) +register_tablecreate("challenges", <<'EOC'); +CREATE TABLE challenges ( + ctime int(10) unsigned NOT NULL DEFAULT 0, + challenge char(80) NOT NULL DEFAULT '', + PRIMARY KEY (challenge) +) +EOC + +register_tablecreate("clustermove_inprogress", <<'EOC'); +CREATE TABLE clustermove_inprogress ( + userid INT UNSIGNED NOT NULL, + locktime INT UNSIGNED NOT NULL, + dstclust SMALLINT UNSIGNED NOT NULL, + moverhost INT UNSIGNED NOT NULL, + moverport SMALLINT UNSIGNED NOT NULL, + moverinstance CHAR(22) NOT NULL, # base64ed MD5 hash + PRIMARY KEY (userid) +) +EOC + +# track open HTTP proxies +register_tablecreate("openproxy", <<'EOC'); +CREATE TABLE openproxy ( + addr VARCHAR(15) NOT NULL, + status ENUM('proxy', 'clear'), + asof INT UNSIGNED NOT NULL, + src VARCHAR(80), + PRIMARY KEY (addr) +) +EOC + +register_tablecreate("captcha_session", <<'EOC'); # clustered +CREATE TABLE captcha_session ( + sess char(20) NOT NULL default '', + sesstime int(10) unsigned NOT NULL default '0', + lastcapid int(11) default NULL, + trynum smallint(6) default '0', + PRIMARY KEY (`sess`), + KEY sesstime (`sesstime`) +) +EOC + +register_tablecreate("spamreports", <<'EOC'); # global +CREATE TABLE spamreports ( + reporttime INT(10) UNSIGNED NOT NULL, + ip VARCHAR(15), + journalid INT(10) UNSIGNED NOT NULL, + posterid INT(10) UNSIGNED NOT NULL DEFAULT 0, + subject VARCHAR(255) BINARY, + body BLOB NOT NULL, + PRIMARY KEY (reporttime, journalid), + INDEX (ip), + INDEX (posterid) +) +EOC + +register_tablecreate("tempanonips", <<'EOC'); # clustered +CREATE TABLE tempanonips ( + reporttime INT(10) UNSIGNED NOT NULL, + ip VARCHAR(15) NOT NULL, + journalid INT(10) UNSIGNED NOT NULL, + jtalkid MEDIUMINT(8) UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jtalkid), + INDEX (reporttime) +) +EOC + +# partialstats - stores calculation times: +# jobname = 'calc_country' +# clusterid = '1' +# calctime = time() +register_tablecreate("partialstats", <<'EOC'); +CREATE TABLE partialstats ( + jobname VARCHAR(50) NOT NULL, + clusterid MEDIUMINT NOT NULL DEFAULT 0, + calctime INT(10) UNSIGNED, + PRIMARY KEY (jobname, clusterid) +) +EOC + +# partialstatsdata - stores data per cluster: +# statname = 'country' +# arg = 'US' +# clusterid = '1' +# value = '500' +register_tablecreate("partialstatsdata", <<'EOC'); +CREATE TABLE partialstatsdata ( + statname VARCHAR(50) NOT NULL, + arg VARCHAR(50) NOT NULL, + clusterid INT(10) UNSIGNED NOT NULL DEFAULT 0, + value INT(11), + PRIMARY KEY (statname, arg, clusterid) +) +EOC + +# inviterecv -- stores community invitations received +register_tablecreate("inviterecv", <<'EOC'); +CREATE TABLE inviterecv ( + userid INT(10) UNSIGNED NOT NULL, + commid INT(10) UNSIGNED NOT NULL, + maintid INT(10) UNSIGNED NOT NULL, + recvtime INT(10) UNSIGNED NOT NULL, + args VARCHAR(255), + PRIMARY KEY (userid, commid) +) +EOC + +# invitesent -- stores community invitations sent +register_tablecreate("invitesent", <<'EOC'); +CREATE TABLE invitesent ( + commid INT(10) UNSIGNED NOT NULL, + userid INT(10) UNSIGNED NOT NULL, + maintid INT(10) UNSIGNED NOT NULL, + recvtime INT(10) UNSIGNED NOT NULL, + status ENUM('accepted', 'rejected', 'outstanding') NOT NULL, + args VARCHAR(255), + PRIMARY KEY (commid, userid) +) +EOC + +# memorable2 -- clustered memories +register_tablecreate("memorable2", <<'EOC'); +CREATE TABLE memorable2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + memid INT(10) UNSIGNED NOT NULL DEFAULT '0', + journalid INT(10) UNSIGNED NOT NULL DEFAULT '0', + ditemid INT(10) UNSIGNED NOT NULL DEFAULT '0', + des VARCHAR(150) DEFAULT NULL, + security ENUM('public','friends','private') NOT NULL DEFAULT 'public', + PRIMARY KEY (userid, journalid, ditemid), + UNIQUE KEY (userid, memid) +) +EOC + +# memkeyword2 -- clustered memory keyword map +register_tablecreate("memkeyword2", <<'EOC'); +CREATE TABLE memkeyword2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + memid INT(10) UNSIGNED NOT NULL DEFAULT '0', + kwid INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid, memid, kwid), + KEY (userid, kwid) +) +EOC + +# userkeywords -- clustered keywords +register_tablecreate("userkeywords", <<'EOC'); +CREATE TABLE userkeywords ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + kwid INT(10) UNSIGNED NOT NULL DEFAULT '0', + keyword VARCHAR(80) BINARY NOT NULL, + PRIMARY KEY (userid, kwid), + UNIQUE KEY (userid, keyword) +) +EOC + +# friendgroup2 -- clustered friend groups +register_tablecreate("friendgroup2", <<'EOC'); +CREATE TABLE friendgroup2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + groupnum TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + groupname VARCHAR(90) NOT NULL DEFAULT '', + sortorder TINYINT(3) UNSIGNED NOT NULL DEFAULT '50', + is_public ENUM('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (userid, groupnum) +) +EOC + +register_tablecreate("readonly_user", <<'EOC'); +CREATE TABLE readonly_user ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("underage", <<'EOC'); +CREATE TABLE underage ( + uniq CHAR(15) NOT NULL, + timeof INT(10) NOT NULL, + PRIMARY KEY (uniq), + KEY (timeof) +) +EOC + +register_tablecreate("support_youreplied", <<'EOC'); +CREATE TABLE support_youreplied ( + userid INT UNSIGNED NOT NULL, + spid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid, spid) +) +EOC + +register_tablecreate("support_answers", <<'EOC'); +CREATE TABLE support_answers ( + ansid INT UNSIGNED NOT NULL, + spcatid INT UNSIGNED NOT NULL, + lastmodtime INT UNSIGNED NOT NULL, + lastmoduserid INT UNSIGNED NOT NULL, + subject VARCHAR(255), + body TEXT, + + PRIMARY KEY (ansid), + KEY (spcatid) +) +EOC + +register_tablecreate("userlog", <<'EOC'); +CREATE TABLE userlog ( + userid INT UNSIGNED NOT NULL, + logtime INT UNSIGNED NOT NULL, + action VARCHAR(30) NOT NULL, + actiontarget INT UNSIGNED, + remoteid INT UNSIGNED, + ip VARCHAR(15), + uniq VARCHAR(15), + extra VARCHAR(255), + + INDEX (userid) +) +EOC + +# external user mappings +# note: extuser/extuserid are expected to sometimes be NULL, even +# though they are keyed. (Null values are not taken into account when +# using indexes) +register_tablecreate("extuser", <<'EOC'); +CREATE TABLE extuser ( + userid INT UNSIGNED NOT NULL PRIMARY KEY, + siteid INT UNSIGNED NOT NULL, + extuser VARCHAR(50), + extuserid INT UNSIGNED, + UNIQUE KEY `extuser` (siteid, extuser), + UNIQUE KEY `extuserid` (siteid, extuserid) +) +EOC + +# table showing what tags a user has; parentkwid can be null +register_tablecreate("usertags", <<'EOC'); +CREATE TABLE usertags ( + journalid INT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + parentkwid INT UNSIGNED, + display ENUM('0','1') DEFAULT '1' NOT NULL, + PRIMARY KEY (journalid, kwid) +) +EOC + +# mapping of tags applied to an entry +register_tablecreate("logtags", <<'EOC'); +CREATE TABLE logtags ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jitemid, kwid), + KEY (journalid, kwid) +) +EOC + +# logtags but only for the most recent 100 tags-to-entry +register_tablecreate("logtagsrecent", <<'EOC'); +CREATE TABLE logtagsrecent ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, kwid, jitemid) +) +EOC + +# summary counts for security on entry keywords +register_tablecreate("logkwsum", <<'EOC'); +CREATE TABLE logkwsum ( + journalid INT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + security INT UNSIGNED NOT NULL, + entryct INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (journalid, kwid, security), + KEY (journalid, security) +) +EOC + +# action history tables +register_tablecreate("actionhistory", <<'EOC'); +CREATE TABLE actionhistory ( + time INT UNSIGNED NOT NULL, + clusterid TINYINT UNSIGNED NOT NULL, + what CHAR(2) NOT NULL, + count INT UNSIGNED NOT NULL DEFAULT 0, + INDEX(time) + +) +EOC + +register_tablecreate("recentactions", <<'EOC'); +CREATE TABLE recentactions ( + what CHAR(2) NOT NULL +) TYPE=MYISAM +EOC + +# external identities +# +# idtype ::= +# "O" - OpenID +# "L" - LID (netmesh) +# "T" - TypeKey +# ? - etc +register_tablecreate("identitymap", <<'EOC'); +CREATE TABLE identitymap ( + idtype CHAR(1) NOT NULL, + identity VARCHAR(255) BINARY NOT NULL, + userid INT unsigned NOT NULL, + PRIMARY KEY (idtype, identity), + KEY userid (userid) +) +EOC + +register_tablecreate("openid_trust", <<'EOC'); +CREATE TABLE openid_trust ( + userid int(10) unsigned NOT NULL default '0', + endpoint_id int(10) unsigned NOT NULL default '0', + trust_time int(10) unsigned NOT NULL default '0', + duration enum('always','once') NOT NULL default 'always', + last_assert_time int(10) unsigned default NULL, + flags tinyint(3) unsigned default NULL, + PRIMARY KEY (userid,endpoint_id), + KEY endpoint_id (endpoint_id) +) +EOC + +register_tablecreate("openid_endpoint", <<'EOC'); +CREATE TABLE openid_endpoint ( + endpoint_id int(10) unsigned NOT NULL auto_increment, + url varchar(255) BINARY NOT NULL default '', + last_assert_time int(10) unsigned default NULL, + PRIMARY KEY (endpoint_id), + UNIQUE KEY url (url), + KEY last_assert_time (last_assert_time) +) +EOC + +register_tablecreate("openid_external", <<'EOC'); +CREATE TABLE openid_external ( + userid int(10) unsigned NOT NULL default '0', + url varchar(255) binary default NULL, + KEY userid (userid) +) +EOC + +# NOTE: new table declarations go here + + +### changes + +register_alter(sub { + + my $dbh = shift; + my $runsql = shift; + + if (column_type("supportcat", "is_selectable") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD is_selectable ENUM('1','0') ". + "NOT NULL DEFAULT '1', ADD public_read ENUM('1','0') NOT ". + "NULL DEFAULT '1', ADD public_help ENUM('1','0') NOT NULL ". + "DEFAULT '1', ADD allow_screened ENUM('1','0') NOT NULL ". + "DEFAULT '0', ADD replyaddress VARCHAR(50), ADD hide_helpers ". + "ENUM('1','0') NOT NULL DEFAULT '0' AFTER allow_screened"); + + } + if (column_type("supportlog", "type") =~ /faqref/) + { + do_alter("supportlog", + "ALTER TABLE supportlog MODIFY type ENUM('req', 'answer', ". + "'custom', 'faqref', 'comment', 'internal', 'screened') ". + "NOT NULL"); + do_sql("UPDATE supportlog SET type='answer' WHERE type='custom'"); + do_sql("UPDATE supportlog SET type='answer' WHERE type='faqref'"); + do_alter("supportlog", + "ALTER TABLE supportlog MODIFY type ENUM('req', 'answer', ". + "'comment', 'internal', 'screened') NOT NULL"); + + } + if (table_relevant("supportcat") && column_type("supportcat", "catkey") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD catkey VARCHAR(25) AFTER spcatid"); + do_sql("UPDATE supportcat SET catkey=spcatid WHERE catkey IS NULL"); + do_alter("supportcat", + "ALTER TABLE supportcat MODIFY catkey VARCHAR(25) NOT NULL"); + } + if (column_type("supportcat", "no_autoreply") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD no_autoreply ENUM('1', '0') ". + "NOT NULL DEFAULT '0'"); + } + + if (column_type("support", "timelasthelp") eq "") + { + do_alter("supportlog", + "ALTER TABLE supportlog ADD INDEX (userid)"); + do_alter("support", + "ALTER TABLE support ADD timelasthelp INT UNSIGNED"); + } + + if (column_type("duplock", "realm") !~ /payments/) + { + do_alter("duplock", + "ALTER TABLE duplock MODIFY realm ENUM('support','log',". + "'comment','payments') NOT NULL default 'support'"); + } + + if (column_type("schematables", "redist_where") eq "") + { + do_alter("schematables", + "ALTER TABLE schematables ADD ". + "redist_where varchar(255) AFTER redist_mode"); + } + + # upgrade people to the new capabilities system. if they're + # using the the paidfeatures column already, we'll assign them + # the same capability bits that ljcom will be using. + if (table_relevant("user") && column_type("user", "caps") eq "") + { + do_alter("user", + "ALTER TABLE user ADD ". + "caps SMALLINT UNSIGNED NOT NULL DEFAULT 0 AFTER user"); + try_sql("UPDATE user SET caps=16|8|2 WHERE paidfeatures='on'"); + try_sql("UPDATE user SET caps=8|2 WHERE paidfeatures='paid'"); + try_sql("UPDATE user SET caps=4|2 WHERE paidfeatures='early'"); + try_sql("UPDATE user SET caps=2 WHERE paidfeatures='off'"); + } + + # axe this column (and its two related ones) if it exists. + if (column_type("user", "paidfeatures")) + { + try_sql("REPLACE INTO paiduser (userid, paiduntil, paidreminder) ". + "SELECT userid, paiduntil, paidreminder FROM user WHERE paidfeatures='paid'"); + try_sql("REPLACE INTO paiduser (userid, paiduntil, paidreminder) ". + "SELECT userid, COALESCE(paiduntil,'0000-00-00'), NULL FROM user WHERE paidfeatures='on'"); + do_alter("user", + "ALTER TABLE user DROP paidfeatures, DROP paiduntil, DROP paidreminder"); + } + + # move S1 _style ids to userprop table! + if (column_type("user", "lastn_style")) { + + # be paranoid and insert these in case they don't exist: + try_sql("INSERT INTO userproplist VALUES (null, 's1_lastn_style', 0, 'Recent View StyleID', 'num', 'The style ID# of the S1 style for the recent entries view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_calendar_style', 0, 'Calendar View StyleID', 'num', 'The style ID# of the S1 style for the calendar view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_day_style', 0, 'Day View StyleID', 'num', 'The style ID# of the S1 style for the day view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_friends_style', 0, 'Friends View StyleID', 'num', 'The style ID# of the S1 style for the friends view.')"); + + foreach my $v (qw(lastn day calendar friends)) { + do_sql("INSERT INTO userproplite SELECT u.userid, upl.upropid, u.${v}_style FROM user u, userproplist upl WHERE upl.name='s1_${v}_style'"); + } + + do_alter("user", + "ALTER TABLE user DROP lastn_style, DROP calendar_style, DROP search_style, DROP searchres_style, DROP day_style, DROP friends_style"); + } + + # add scope columns to proplist tables + if (column_type("userproplist", "scope") eq "") { + do_alter("userproplist", + "ALTER TABLE userproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("logproplist", "scope") eq "") { + do_alter("logproplist", + "ALTER TABLE logproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("talkproplist", "scope") eq "") { + do_alter("talkproplist", + "ALTER TABLE talkproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("priv_list", "scope") eq "") { + do_alter("priv_list", + "ALTER TABLE priv_list ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + # change size of stats table to accomodate meme data, and shrink statcat, + # since it's way too big + if (column_type("stats", "statcat") eq "varchar(100)") { + do_alter("stats", + "ALTER TABLE stats ". + "MODIFY statcat VARCHAR(30) NOT NULL, ". + "MODIFY statkey VARCHAR(150) NOT NULL, ". + "MODIFY statval INT UNSIGNED NOT NULL, ". + "DROP INDEX statcat"); + } + + if (column_type("priv_list", "is_public") eq "") { + do_alter("priv_list", + "ALTER TABLE priv_list ". + "ADD is_public ENUM('1', '0') DEFAULT '1' NOT NULL"); + } + + if (column_type("randomuserset", "rid") eq "") { + do_alter("randomuserset", + "ALTER TABLE randomuserset DROP PRIMARY KEY, DROP timeupdate, ". + "ADD rid INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (rid)"); + } + + # cluster stuff! + if (column_type("meme", "journalid") eq "") { + do_alter("meme", + "ALTER TABLE meme ADD journalid INT UNSIGNED NOT NULL AFTER ts"); + } + + if (column_type("memorable", "jitemid") eq "") { + do_alter("memorable", "ALTER TABLE memorable ". + "DROP INDEX userid, DROP INDEX itemid, ". + "CHANGE itemid jitemid INT UNSIGNED NOT NULL, ". + "ADD journalid INT UNSIGNED NOT NULL AFTER userid, ". + "ADD UNIQUE uniq (userid, journalid, jitemid), ". + "ADD KEY item (journalid, jitemid)"); + } + + if (column_type("user", "clusterid") eq "") { + do_alter("user", "ALTER TABLE user ". + "ADD clusterid TINYINT UNSIGNED NOT NULL AFTER caps, ". + "ADD dversion TINYINT UNSIGNED NOT NULL AFTER clusterid, ". + "ADD INDEX idxcluster (clusterid), ". + "ADD INDEX idxversion (dversion)"); + } + + if (column_type("friends", "bgcolor") eq "char(7)") { + do_alter("friends", "ALTER TABLE friends ". + "MODIFY bgcolor CHAR(8) NOT NULL DEFAULT '16777215', ". + "MODIFY fgcolor CHAR(8) NOT NULL DEFAULT '0'"); + do_sql("UPDATE friends SET ". + "bgcolor=CONV(RIGHT(bgcolor,6),16,10), ". + "fgcolor=CONV(RIGHT(fgcolor,6),16,10)") + unless skip_opt() eq "colorconv"; + } + + return if skip_opt() eq "colorconv"; + + if (column_type("friends", "bgcolor") eq "char(8)") { + do_alter("friends", "ALTER TABLE friends ". + "MODIFY bgcolor MEDIUMINT UNSIGNED NOT NULL DEFAULT 16777215, ". + "MODIFY fgcolor MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + # add the default encoding field, for recoding older pre-Unicode stuff + + if (column_type("user", "oldenc") eq "") { + do_alter("user", "ALTER TABLE user ". + "ADD oldenc TINYINT DEFAULT 0 NOT NULL, ". + "MODIFY name CHAR(80) NOT NULL"); + } + + if (column_type("user", "allow_getpromos") ne "") { + do_alter("user", "ALTER TABLE user DROP allow_getpromos"); + } + + # widen columns to accomodate larger Unicode names + if (column_type("friendgroup", "groupname") eq "varchar(30)") { + do_alter("friendgroup", + "ALTER TABLE friendgroup ". + "MODIFY groupname VARCHAR(60) NOT NULL"); + } + if (column_type("todo", "statusline") eq "varchar(15)") { + do_alter("todo", + "ALTER TABLE todo ". + "MODIFY statusline VARCHAR(40) NOT NULL, " . + "MODIFY subject VARCHAR(100) NOT NULL, " . + "MODIFY des VARCHAR(255) NOT NULL"); + } + if (column_type("memorable", "des") eq "varchar(60)") { + do_alter("memorable", + "ALTER TABLE memorable ". + "MODIFY des VARCHAR(150) NOT NULL"); + } + if (column_type("keywords", "keyword") eq "varchar(40) binary") { + do_alter("keywords", + "ALTER TABLE keywords ". + "MODIFY keyword VARCHAR(80) BINARY NOT NULL"); + } + + # change interest.interest key to being unique, if it's not already + { + my $sth = $dbh->prepare("SHOW INDEX FROM interests"); + $sth->execute; + while (my $i = $sth->fetchrow_hashref) { + if ($i->{'Key_name'} eq "interest" && $i->{'Non_unique'}) { + do_alter("interests", "ALTER IGNORE TABLE interests ". + "DROP INDEX interest, ADD UNIQUE interest (interest)"); + last; + } + } + } + + if (column_type("supportcat", "scope") eq "") + { + do_alter("supportcat", + "ALTER IGNORE TABLE supportcat ADD scope ENUM('general', 'local') ". + "NOT NULL DEFAULT 'general', ADD UNIQUE (catkey)"); + } + + # convert 'all' arguments to '*' + if (table_relevant("priv_map") && !check_dbnote("privcode_all_to_*")) { + + # arg isn't keyed, but this table is only a couple thousand rows + do_sql("UPDATE priv_map SET arg='*' WHERE arg='all'"); + + set_dbnote("privcode_all_to_*", 1); + } + + # convert 'wizard' s2 styles to 'wizard-uniq' + if (table_relevant("s2styles") && !check_dbnote("s2style-wizard-update")) { + + # set_dbnote will return true if $opt_sql is set and it sets + # the note successfully. only then do we run the wizard updater + set_dbnote("s2style-wizard-update", 1) && + system("$ENV{'LJHOME'}/bin/upgrading/s2style-wizard-update.pl"); + } + + # this never ended up being useful, and just freaked people out unnecessarily. + if (column_type("user", "track")) { + do_alter("user", "ALTER TABLE user DROP track"); + } + + # need more choices (like "Y" for sYndicated journals) + if (column_type("user", "journaltype") =~ /enum/i) { + do_alter("user", "ALTER TABLE user MODIFY journaltype CHAR(1) NOT NULL DEFAULT 'P'"); + } + + unless (column_type("syndicated", "laststatus")) { + do_alter("syndicated", + "ALTER TABLE syndicated ADD laststatus VARCHAR(80), ADD lastnew DATETIME"); + } + + # change themedata. key to being unique, if it's not already + unless (index_name("themedata", "UNIQUE:themeid-coltype")) { + do_alter("themedata", "ALTER IGNORE TABLE themedata ". + "DROP KEY themeid, MODIFY coltype VARCHAR(30) NOT NULL, ". + "ADD UNIQUE `thuniq` (themeid, coltype)"); + } + + unless (column_type("syndicated", "numreaders")) { + do_alter("syndicated", + "ALTER TABLE syndicated ". + "ADD numreaders MEDIUMINT, ADD INDEX (numreaders)"); + } + + if (column_type("community", "ownerid")) + { + do_alter("community", + "ALTER TABLE community DROP ownerid"); + } + + # if it exists, but it's the old way, just kill it. + if (column_type("weekuserusage", "ubefore") && ! column_type("weekuserusage", "uafter")) { + do_sql("DROP TABLE weekuserusage"); + create_table("weekuserusage"); + } + + unless (column_type("userproplist", "cldversion")) { + do_alter("userproplist", + "ALTER TABLE userproplist ADD cldversion TINYINT UNSIGNED NOT NULL AFTER indexed"); + } + + unless (column_type("authactions", "used") && + index_name("authactions", "INDEX:userid") && + index_name("authactions", "INDEX:datecreate")) { + + do_alter("authactions", + "ALTER TABLE authactions " . + "ADD used enum('Y', 'N') DEFAULT 'N' AFTER arg1, " . + "ADD INDEX(userid), ADD INDEX(datecreate)"); + } + + unless (column_type("s2styles", "modtime")) { + do_alter("s2styles", + "ALTER TABLE s2styles ADD modtime INT UNSIGNED NOT NULL AFTER name"); + } + + if (column_type("acctinvite", "reason") eq "varchar(20)") { + do_alter("acctinvite", + "ALTER TABLE acctinvite MODIFY reason VARCHAR(40)"); + } + + # Add BLOB flag to proplist + unless (column_type("userproplist", "datatype") =~ /blobchar/) { + if (column_type("userproplist", "is_blob")) { + do_alter("userproplist", + "ALTER TABLE userproplist DROP is_blob"); + } + do_alter("userproplist", + "ALTER TABLE userproplist MODIFY datatype ENUM('char','num','bool','blobchar') NOT NULL DEFAULT 'char'"); + } + + if (column_type("challenges", "count") eq "") + { + do_alter("challenges", + "ALTER TABLE challenges ADD ". + "count int(5) UNSIGNED NOT NULL DEFAULT 0 AFTER challenge"); + } + + if (column_type("userblob", "length") =~ /mediumint/) + { + do_alter("userblob", "ALTER TABLE userblob MODIFY length INT UNSIGNED"); + } + + unless (index_name("support", "INDEX:requserid")) { + do_alter("support", "ALTER IGNORE TABLE support ADD INDEX (requserid), ADD INDEX (reqemail)"); + } + + unless (column_type("community", "membership") =~ /moderated/i) { + do_alter("community", "ALTER TABLE community MODIFY COLUMN " . + "membership ENUM('open','closed','moderated') DEFAULT 'open' NOT NULL"); + } + + if (column_type("userproplist", "multihomed") eq '') { + do_alter("userproplist", "ALTER TABLE userproplist " . + "ADD multihomed ENUM('1', '0') NOT NULL DEFAULT '0' AFTER cldversion"); + } + + if (index_name("moodthemedata", "INDEX:moodthemeid")) { + do_alter("moodthemedata", "ALTER IGNORE TABLE moodthemedata DROP KEY moodthemeid"); + } + + if (column_type("userpic2", "flags") eq '') { + do_alter("userpic2", "ALTER TABLE userpic2 " . + "ADD flags tinyint(1) unsigned NOT NULL default 0 AFTER comment, " . + "ADD location enum('blob','disk','mogile') default NULL AFTER flags"); + } + + if (column_type("userblob", "blobid") =~ /mediumint/) { + do_alter("userblob", "ALTER TABLE userblob MODIFY blobid INT UNSIGNED NOT NULL"); + } + + if (column_type("counter", "max") =~ /mediumint/) { + do_alter("counter", "ALTER TABLE counter MODIFY max INT UNSIGNED NOT NULL DEFAULT 0"); + } + + if (column_type("userpic2", "url") eq '') { + do_alter("userpic2", "ALTER TABLE userpic2 " . + "ADD url VARCHAR(255) default NULL AFTER location"); + } + + unless (column_type("spamreports", "posttime") ne '') { + do_alter("spamreports", "ALTER TABLE spamreports ADD COLUMN posttime INT(10) UNSIGNED " . + "NOT NULL AFTER reporttime, ADD COLUMN state ENUM('open', 'closed') DEFAULT 'open' " . + "NOT NULL AFTER posttime"); + } + + if (column_type("captchas", "location") eq '') { + do_alter("captchas", "ALTER TABLE captchas " . + "ADD location ENUM('blob','mogile') DEFAULT NULL AFTER type"); + } + + if (column_type("spamreports", "report_type") eq '') { + do_alter("spamreports", "ALTER TABLE spamreports " . + "ADD report_type ENUM('entry','comment') NOT NULL DEFAULT 'comment' " . + "AFTER posterid"); + } + + if (column_type("commenturls", "ip") eq '') { + do_alter("commenturls", + "ALTER TABLE commenturls " . + "ADD ip VARCHAR(15) DEFAULT NULL " . + "AFTER journalid"); + } + + if (column_type("sessions", "exptype") !~ /once/) { + do_alter("sessions", + "ALTER TABLE sessions CHANGE COLUMN exptype ". + "exptype ENUM('short', 'long', 'once') NOT NULL"); + } + + if (column_type("ml_items", "itid") =~ /auto_increment/) { + do_alter("ml_items", + "ALTER TABLE ml_items MODIFY COLUMN " . + "itid MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + if (column_type("ml_text", "txtid") =~ /auto_increment/) { + do_alter("ml_text", + "ALTER TABLE ml_text MODIFY COLUMN " . + "txtid MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + unless (column_type("syndicated", "oldest_ourdate")) { + do_alter("syndicated", + "ALTER TABLE syndicated ADD oldest_ourdate DATETIME AFTER lastnew"); + } + + if (column_type("sessions", "userid") =~ /mediumint/) { + do_alter("sessions", + "ALTER TABLE sessions MODIFY COLUMN userid INT UNSIGNED NOT NULL"); + } + + +}); + +1; # return true diff --git a/local/cgi-bin/Apache/BML.pm b/local/cgi-bin/Apache/BML.pm new file mode 100755 index 0000000..94693b0 --- /dev/null +++ b/local/cgi-bin/Apache/BML.pm @@ -0,0 +1,2068 @@ +#!/usr/bin/perl +# + + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljr_readconf.pl"; + +package BML::Request; + +use fields qw( + env blockref lang r blockflags BlockStack + file scratch IncludeOpen content_type clean_package package + filechanged scheme scheme_file IncludeStack etag location + most_recent_mod stop_flag want_last_modified cookies + ); + + +package Apache::BML; + +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED); +use Apache::File (); +use Apache::URI; +use Digest::MD5; +use File::Spec; +BEGIN { + $Apache::BML::HAVE_ZLIB = eval "use Compress::Zlib (); 1;"; +} + +# set per request: +use vars qw($cur_req); +use vars qw(%CodeBlockOpts); +# scalar hashrefs of versions below, minus the domain part: +my ($SchemeData, $SchemeFlags); + +# keyed by domain: +my $ML_SCOPE; # generally the $r->uri, auto set on each request (unless overridden) +my (%SchemeData, %SchemeFlags); # domain -> scheme -> key -> scalars (data has {s} blocks expanded) + +# safely global: +use vars qw(%FileModTime %LookItems); # LookItems: file -> template -> [ data, flags ] +use vars qw(%LookParent); # file -> parent file +use vars qw(%LookChild); # file -> child -> 1 + +my (%CodeBlockMade); + +use vars qw($conf_pl $conf_pl_look); # hashref, made empty before loading a .pl conf file +my %DenyConfig; # filename -> 1 +my %FileConfig; # filename -> hashref +my %FileLastStat; # filename -> time we last looked at its modtime + +use vars qw($base_recent_mod); + +# the request we're handling (Apache->request). using this way +# instead of just using Apache->request because when using +# Apache::FakeRequest and non-mod_perl env, I can't seem to get/set +# the value of Apache->request +use vars qw($r); + +# regexps to match open and close tokens. (but old syntax (=..=) is deprecated) +my ($TokenOpen, $TokenClose) = ('<\?', '\?>'); + +tie %BML::ML, 'BML::ML'; +tie %BML::COOKIE, 'BML::Cookie'; + +sub handler +{ + my $r = shift; + my $file; + + $Apache::BML::r = $r; + + # determine what file we're supposed to work with: + if (ref $r eq "Apache::FakeRequest") { + # for testing. FakeRequest's 'notes' method is busted, always returning + # true. + $file = $r->filename; + stat($file); + } elsif ($file = $r->notes("bml_filename")) { + # when another handler needs to invoke BML directly + stat($file); + } else { + # normal case + $file = $r->filename; + $r->finfo; + } + + unless (-e _) { + $r->log_error("File does not exist: $file"); + return NOT_FOUND; + } + + unless (-r _) { + $r->log_error("File permissions deny access: $file"); + return FORBIDDEN; + } + + my $modtime = (stat _)[9]; + + return FORBIDDEN if $file =~ /\b_config/; + + # create new request + my $req = $cur_req = fields::new('BML::Request'); + $req->{file} = $file; + $req->{r} = $r; + $req->{BlockStack} = [""]; + $req->{scratch} = {}; # _CODE blocks can play + $req->{cookies} = {}; + + # setup env + my $env = $req->{env} = {}; + + # walk up directories, looking for _config.bml files, populating env + my $dir = $file; + my $docroot = $r->document_root(); $docroot =~ s!/$!!; + my @dirconfs; + my %confwant; # file -> 1, if applicable config + + while ($dir) { + $dir =~ s!/[^/]*$!!; + my $conffile = "$dir/_config.bml"; + $confwant{$conffile} = 1; + push @dirconfs, load_conffile($conffile); + last if $dir eq $docroot; + } + + # we now have dirconfs in order from first to apply to last. + # but a later one may have a subconfig to override, so + # go through those first, keeping track of which configs + # are effective + my %eff_config; + + foreach my $cfile (@dirconfs) { + my $conf = $FileConfig{$cfile}; + next unless $conf; + $eff_config{$cfile} = $conf; + if ($conf->{'SubConfig'}) { + foreach my $sconf (keys %confwant) { + my $sc = $conf->{'SubConfig'}{$sconf}; + $eff_config{$cfile} = $sc if $sc; + } + } + } + + foreach my $cfile (@dirconfs) { + my $conf = $eff_config{$cfile}; + next unless $conf; + while (my ($k,$v) = each %$conf) { + next if exists $env->{$k} || $k eq "SubConfig"; + $env->{$k} = $v; + } + } + + # check if there are overrides in pnotes + # wrapped in eval because Apache::FakeRequest doesn't have + # pnotes support (as of 2004-04-26 at least) + eval { + if (my $or = $r->pnotes('BMLEnvOverride')) { + while (my ($k, $v) = each %$or) { + $env->{$k} = $v; + } + } + }; + + # environment loaded at this point + + if ($env->{'AllowOldSyntax'}) { + ($TokenOpen, $TokenClose) = ('(?:<\?|\(=)', '(?:\?>|=\))'); + } else { + ($TokenOpen, $TokenClose) = ('<\?', '\?>'); + } + + # Look for an alternate file, and if it exists, load it instead of the real + # one. + if ( exists $env->{TryAltExtension} ) { + my $ext = $env->{TryAltExtension}; + + # Trim a leading dot on the extension to allow '.lj' or 'lj' + $ext =~ s{^\.}{}; + + # If the file already has an extension, put the alt extension between it + # and the rest of the filename like Apache's content-negotiation. + if ( $file =~ m{(\.\S+)$} ) { + my $newfile = $file; + substr( $newfile, -(length $1), 0 ) = ".$ext"; + if ( -e $newfile ) { + $modtime = (stat _)[9]; + $file = $newfile; + } + } + + elsif ( -e "$file.$ext" ) { + $modtime = (stat _)[9]; + $file = "$file.$ext"; + } + } + + # Read the source of the file + unless (open F, $file) { + $r->log_error("Couldn't open $file for reading: $!"); + $Apache::BML::r = undef; # no longer valid + return SERVER_ERROR; + } + + my $bmlsource; + { local $/ = undef; $bmlsource = ; } + close F; + + # consider the file's mod time + note_mod_time($req, $modtime); + + # and all the config files: + note_mod_time($req, $Apache::BML::base_recent_mod); + + # if the file changed since we last looked at it, note that + if (!defined $FileModTime{$file} || $modtime > $FileModTime{$file}) { + $FileModTime{$file} = $modtime; + $req->{'filechanged'} = 1; + } + + # setup cookies + *BMLCodeBlock::COOKIE = *BML::COOKIE; + BML::reset_cookies(); + + # tied interface to BML::ml(); + *BMLCodeBlock::ML = *BML::ML; + + # let BML code blocks see input + %BMLCodeBlock::GET = (); + %BMLCodeBlock::POST = (); + %BMLCodeBlock::FORM = (); # whatever request method is + my %input_target = ( GET => [ \%BMLCodeBlock::GET ], + POST => [ \%BMLCodeBlock::POST ], ); + push @{$input_target{$r->method}}, \%BMLCodeBlock::FORM; + foreach my $id ([ [ $r->args ] => $input_target{'GET'} ], + [ [ $r->content ] => $input_target{'POST'} ]) + { + while (my ($k, $v) = splice @{$id->[0]}, 0, 2) { + foreach my $dest (@{$id->[1]}) { + $dest->{$k} .= "\0" if exists $dest->{$k}; + $dest->{$k} .= $v; + } + } + } + + if ($env->{'HOOK-startup'}) { + eval { + $env->{'HOOK-startup'}->(); + }; + return report_error($r, "Error running startup hook:
    \n$@") + if $@; + } + + my $scheme = $r->notes('bml_use_scheme') || + $env->{'ForceScheme'} || + $BMLCodeBlock::GET{'usescheme'} || + $BML::COOKIE{'BMLschemepref'} || + $env->{'DefaultScheme'}; + unless (BML::set_scheme($scheme)) { + $scheme = $env->{'ForceScheme'} || + $env->{'DefaultScheme'}; + BML::set_scheme($scheme); + } + + my $uri = $r->uri; + BML::set_language_scope($uri); + my $lang = BML::decide_language(); + BML::set_language($lang); + + # print on the HTTP header + my $html = $env->{'_error'}; + + bml_decode($req, \$bmlsource, \$html, { DO_CODE => $env->{'AllowCode'} }) + unless $html; + + # force out any cookies we have set + BML::send_cookies($req); + + $r->register_cleanup(\&reset_codeblock) if $req->{'clean_package'}; + + # redirect, if set previously + if ($req->{'location'}) { + $r->header_out(Location => $req->{'location'}); + $Apache::BML::r = undef; # no longer valid + return REDIRECT; + } + + # exit, if we set 304 manually + if ($Apache::BML::r->status == 304) { + $Apache::BML::r = undef; # no longer valid + return HTTP_NOT_MODIFIED; + } + + # see if we can save some bandwidth (though we already killed a bunch of CPU) + my $etag; + if ($Apache::BML::r->status == 200) { + ### $etag = Digest::MD5::md5_hex($html); + ### see http://cvs-ljr.lenin.ru/cgi-bin/viewvc.cgi/LJR/local/cgi-bin/Apache/LiveJournal.pm?r1=1.29&r2=1.30 + $etag = Digest::MD5::md5_hex(pack('C*', unpack('C*', $html))); + $etag = '"' . $etag . '"'; + } + + my $ifnonematch = $r->header_in("If-None-Match"); + if (defined $ifnonematch && defined $etag && $etag eq $ifnonematch) { + $Apache::BML::r = undef; # no longer valid + return HTTP_NOT_MODIFIED; + } + + + my $rootlang = substr($req->{'lang'}, 0, 2); + unless ($env->{'NoHeaders'}) { + eval { + # this will fail while using Apache::FakeRequest, but that's okay. + $r->content_languages([ $rootlang ]); + }; + } + + my $modtime_http = modified_time($req); + + my $content_type = $req->{'content_type'} || + $env->{'DefaultContentType'} || + "text/html"; + + unless ($env->{'NoHeaders'}) + { + my $ims = $r->header_in("If-Modified-Since"); + if ($ims && ! $env->{'NoCache'} && + $ims eq $modtime_http) + { + $Apache::BML::r = undef; # no longer valid + return HTTP_NOT_MODIFIED; + } + + $r->content_type($content_type); + + if ($env->{'NoCache'}) { + $r->header_out("Cache-Control", "no-cache"); + $r->no_cache(1); + } + + $r->header_out("Last-Modified", $modtime_http) + if $env->{'Static'} || $req->{'want_last_modified'}; + + $r->header_out("Cache-Control", "private, proxy-revalidate"); + $r->header_out("ETag", $etag) if defined $etag; + + my $length = length($html); + $r->header_out('Content-length', $length); + + $r->send_http_header(); + } + + $r->print($html) unless $env->{'NoContent'} || $r->header_only; + + $Apache::BML::r = undef; # no longer valid + return OK; +} + +sub report_error +{ + my $r = shift; + my $err = shift; + + $r->content_type("text/html"); + $r->send_http_header(); + $r->print($err); + + return OK; # TODO: something else? +} + +sub file_dontcheck +{ + my $file = shift; + my $now = time; + return 1 if $FileLastStat{$file} > $now - 10; + my $realmod = (stat($file))[9]; + $FileLastStat{$file} = $now; + return 1 if $FileModTime{$file} && $realmod == $FileModTime{$file}; + $FileModTime{$file} = $realmod; + return 1 if ! $realmod; + return 0; +} + +sub load_conffile +{ + my ($ffile) = @_; # abs file to load + die "can't have dollar signs in filenames" if index($ffile, '$') != -1; + die "not absolute path" unless File::Spec->file_name_is_absolute($ffile); + my ($volume,$dirs,$file) = File::Spec->splitpath($ffile); + + # see which configs are denied + my $r = $Apache::BML::r; + if ($r->dir_config("BML_denyconfig") && ! %DenyConfig) { + my $docroot = $r->document_root(); + my $deny = $r->dir_config("BML_denyconfig"); + $deny =~ s/^\s+//; $deny =~ s/\s+$//; + my @denydir = split(/\s*\,\s*/, $deny); + foreach $deny (@denydir) { + $deny = dir_rel2abs($docroot, $deny); + $deny =~ s!/$!!; + $DenyConfig{"$deny/_config.bml"} = 1; + } + } + + return () if $DenyConfig{$ffile}; + + my $conf; + if (file_dontcheck($ffile) && ($FileConfig{$ffile} || ! $FileModTime{$ffile})) { + return () unless $FileModTime{$ffile}; # file doesn't exist + $conf = $FileConfig{$ffile}; + } + + if (!$conf && $file =~ /\.pl$/) { + return () unless -e $ffile; + my $conf = $conf_pl = {}; + do $ffile; + undef $conf_pl; + $FileConfig{$ffile} = $conf; + return ($ffile); + } + + unless ($conf) { + unless (open (C, $ffile)) { + Apache->log_error("Can't read config file: $file") + if -e $file; + return (); + } + + my $curr_sub; + $conf = {}; + my $sconf = $conf; + + my $save_config = sub { + return unless %$sconf; + + # expand $env vars and make paths absolute + foreach my $k (qw(LookRoot IncludePath)) { + next unless exists $sconf->{$k}; + $sconf->{$k} =~ s/\$(\w+)/$ENV{$1}/g; + $sconf->{$k} = dir_rel2abs($dirs, $sconf->{$k}); + } + + # same as above, but these can be multi-valued, and go into an arrayref + foreach my $k (qw(ExtraConfig)) { + next unless exists $sconf->{$k}; + $sconf->{$k} =~ s/\$(\w+)/$1 eq "HTTP_HOST" ? clean_http_host() : $ENV{$1}/eg; + $sconf->{$k} = [ map { dir_rel2abs($dirs, $_) } grep { $_ } + split(/\s*,\s*/, $sconf->{$k}) ]; + } + + # if child config, copy it to parent config + return unless $curr_sub; + foreach my $subdir (split(/\s*,\s*/, $curr_sub)) { + my $subfile = dir_rel2abs($dirs, "$subdir/_config.bml"); + $conf->{'SubConfig'}->{$subfile} = $sconf; + } + }; + + + while () { + chomp; + s/\#.*//; + next unless /(\S+)\s+(.+?)\s*$/; + my ($k, $v) = ($1, $2); + if ($k eq "SubConfig:") { + $save_config->(); + $curr_sub = $v; + $sconf = {%$sconf}; # clone config seen so far. SubConfig inherits those. + next; + } + + # automatically arrayref-ify certain options + $v = [ split(/\s*,\s*/, $v) ] + if $k eq "CookieDomain" && index($v,',') != -1; + + $sconf->{$k} = $v; + } + close C; + $save_config->(); + $FileConfig{$ffile} = $conf; + } + + my @files = ($ffile); + foreach my $cfile (@{$conf->{'ExtraConfig'} || []}) { + unshift @files, load_conffile($cfile); + } + + return @files; +} + +sub compile +{ + eval $_[0]; +} + +sub reset_codeblock +{ + my BML::Request $req = $Apache::BML::cur_req; + my $to_clean = $req->{clean_package}; + + no strict; + local $^W = 0; + my $package = "main::${to_clean}::"; + *stab = *{"main::"}; + while ($package =~ /(\w+?::)/g) + { + *stab = ${stab}{$1}; + } + while (my ($key,$val) = each(%stab)) + { + return if $DB::signal; + deleteglob ($key, $val); + } +} + +sub deleteglob +{ + no strict; + return if $DB::signal; + my ($key, $val, $all) = @_; + local(*entry) = $val; + my $fileno; + if ($key !~ /^_ +# $data - "Whatever" in the case of +# $option_ref - hash ref to %BMLEnv +sub bml_block +{ + my BML::Request $req = shift; + my ($type, $data, $option_ref, $elhash) = @_; + my $realtype = $type; + my $previous_block = $req->{'BlockStack'}->[-1]; + my $env = $req->{'env'}; + + # Bail out if we're over 200 frames deep + # :TODO: Make the max depth configurable? + if ( @{$req->{BlockStack}} > 200 ) { + my $stackSlice = join " -> ", @{$req->{BlockStack}}[0..10]; + return "[Error: Too deep recursion: $stackSlice]"; + } + + if (exists $req->{'blockref'}->{"$type/FOLLOW_${previous_block}"}) { + $realtype = "$type/FOLLOW_${previous_block}"; + } + + my $blockflags = $req->{'blockflags'}->{$realtype}; + + # executable perl code blocks + if ($type eq "_CODE") + { + return inline_error("_CODE block failed to execute by permission settings") + unless $option_ref->{'DO_CODE'}; + + %CodeBlockOpts = (); + + # this will be their package + my $md5_package = "BMLCodeBlock::" . Digest::MD5::md5_hex($req->{'file'}); + + # this will be their handler name + my $md5_handler = "handler_" . Digest::MD5::md5_hex($data); + + # we cache code blocks (of templates) also in each *.bml file's + # package, since we're too lazy (at the moment) to trace back + # each code block to its declaration file. + my $unique_key = $md5_package . $md5_handler; + + my $need_compile = ! $CodeBlockMade{$unique_key}; + + if ($need_compile) { + # compile (which just calls eval) then check for errors. + # we put it off to that sub, historically, to make it + # show up separate in profiling, but now we cache + # everything, so it pretty much never shows up. + compile(join('', + 'package ', + $md5_package, + ';', + "no strict;", + 'use vars qw(%ML %COOKIE %POST %GET %FORM);', + "*ML = *BML::ML;", + "*COOKIE = *BML::COOKIE;", + "*GET = *BMLCodeBlock::GET;", + "*POST = *BMLCodeBlock::POST;", + "*FORM = *BMLCodeBlock::FORM;", + 'sub ', $md5_handler, ' {', + $data, + "\n}")); + return "[Error: $@]" if $@; + + $CodeBlockMade{$unique_key} = 1; + } + + my $cv = \&{"${md5_package}::${md5_handler}"}; + $req->{clean_package} = $md5_package; + my $ret = eval { $cv->($req, $req->{'scratch'}, $elhash || {}) }; + if ($@) { + my $msg = $@; + if ($env->{'HOOK-codeerror'}) { + $ret = eval { + $env->{'HOOK-codeerror'}->($msg); + }; + return "[Error running codeerror hook]" if $@; + } else { + return "[Error: $msg]"; + } + } + + # don't call bml_decode if BML::noparse() told us not to, there's + # no data, or it looks like there are no BML tags + return $ret if $CodeBlockOpts{'raw'} or $ret eq "" or + (index($ret, " \@elements }); + } + elsif (index($blockflags, 'P') != -1) + { + my @itm = split(/\s*\|\s*/, $data); + my $ct = 0; + foreach (@itm) { + $ct++; + $element{"DATA$ct"} = $_; + push @elements, "DATA$ct"; + } + } + else + { + # single argument block (goes into DATA element) + $element{'DATA'} = $data; + push @elements, 'DATA'; + } + + # check built-in block types (those beginning with an underscore) + if (rindex($type, '_', 0) == 0) { + + # multi-linguality stuff + if ($type eq "_ML") + { + my $code = $data; + return $code + if $req->{'lang'} eq 'debug'; + my $getter = $req->{'env'}->{'HOOK-ml_getter'}; + return "[ml_getter not defined]" unless $getter; + $code = $req->{'r'}->uri . $code + if rindex($code, '.', 0) == 0; + return $getter->($req->{'lang'}, $code); + } + + # an _INFO block contains special internal information, like which + # look files to include + if ($type eq "_INFO") + { + if ($element{'PACKAGE'}) { $req->{'package'} = $element{'PACKAGE'}; } + if ($element{'NOCACHE'}) { $req->{'env'}->{'NoCache'} = 1; } + if ($element{'STATIC'}) { $req->{'env'}->{'Static'} = 1; } + if ($element{'NOHEADERS'}) { $req->{'env'}->{'NoHeaders'} = 1; } + if ($element{'NOCONTENT'}) { $req->{'env'}->{'NoContent'} = 1; } + if ($element{'LOCALBLOCKS'} && $req->{'env'}->{'AllowCode'}) { + my (%localblock, %localflags); + load_elements(\%localblock, $element{'LOCALBLOCKS'}); + # look for template types + foreach my $k (keys %localblock) { + if ($localblock{$k} =~ s/^\{([A-Za-z]+)\}//) { + $localflags{$k} = $1; + } + } + my @expandconstants; + foreach my $k (keys %localblock) { + $req->{'blockref'}->{$k} = \$localblock{$k}; + $req->{'blockflags'}->{$k} = $localflags{$k}; + if (index($localflags{$k}, 's') != -1) { push @expandconstants, $k; } + } + foreach my $k (@expandconstants) { + $localblock{$k} =~ s/$TokenOpen([a-zA-Z0-9\_]+?)$TokenClose/${$req->{'blockref'}->{uc($1)} || \""}/og; + } + } + return ""; + } + + if ($type eq "_INCLUDE") + { + my $code = 0; + $code = 1 if ($element{'CODE'}); + foreach my $sec (qw(CODE BML)) { + next unless $element{$sec}; + if ($req->{'IncludeStack'} && ! $req->{'IncludeStack'}->[-1]->{$sec}) { + return inline_error("Sub-include can't turn on $sec if parent include's $sec was off"); + } + } + unless ($element{'FILE'} =~ /^[a-zA-Z0-9-_\.]{1,255}$/) { + return inline_error("Invalid characters in include file name: $element{'FILE'} (code=$code)"); + } + + if ($req->{'IncludeOpen'}->{$element{'FILE'}}++) { + return inline_error("Recursion detected in includes"); + } + push @{$req->{'IncludeStack'}}, \%element; + my $isource = ""; + my $file = $element{'FILE'}; + + # first check if we have a DB-edit hook + my $hook = $req->{'env'}->{'HOOK-include_getter'}; + unless ($hook && $hook->($file, \$isource)) { + $file = $req->{'env'}->{'IncludePath'} . "/" . $file; + open (INCFILE, $file) || return inline_error("Could not open include file."); + { local $/ = undef; $isource = ; } + close INCFILE; + } + + if ($element{'BML'}) { + my $newhtml; + bml_decode($req, \$isource, \$newhtml, { DO_CODE => $code }); + $isource = $newhtml; + } + $req->{'IncludeOpen'}->{$element{'FILE'}}--; + pop @{$req->{'IncludeStack'}}; + return $isource; + } + + if ($type eq "_COMMENT" || $type eq "_C") { + return ""; + } + + if ($type eq "_EH") { + return BML::ehtml($element{'DATA'}); + } + + if ($type eq "_EB") { + return BML::ebml($element{'DATA'}); + } + + if ($type eq "_EU") { + return BML::eurl($element{'DATA'}); + } + + if ($type eq "_EA") { + return BML::eall($element{'DATA'}); + } + + return inline_error("Unknown core element '$type'"); + } + + $req->{'BlockStack'}->[-1] = $type; + + # traditional BML Block decoding ... properties of data get inserted + # into the look definition; then get BMLitized again + return inline_error("Undefined custom element '$type'") + unless defined $req->{'blockref'}->{$realtype}; + + my $preparsed = (index($blockflags, 'p') != -1); + + if ($preparsed) { + ## does block request pre-parsing of elements? + ## this is required for blocks with _CODE and AllowCode set to 0 + foreach my $k (@elements) { + my $decoded; + bml_decode($req, \$element{$k}, \$decoded, $option_ref, \%element); + $element{$k} = $decoded; + } + } + + # template has no variables or BML tags: + return ${$req->{'blockref'}->{$realtype}} if index($blockflags, 'S') != -1; + + my $expanded; + if ($preparsed) { + $expanded = ${$req->{'blockref'}->{$realtype}}; + } else { + $expanded = parsein(${$req->{'blockref'}->{$realtype}}, \%element); + } + + # {R} flag wants variable interpolation, but no expansion: + unless (index($blockflags, 'R') != -1) + { + my $out; + push @{$req->{'BlockStack'}}, ""; + my $opts = { %{$option_ref} }; + if ($preparsed) { + $opts->{'DO_CODE'} = $req->{'env'}->{'AllowTemplateCode'}; + } + + unless (index($expanded, "{'BlockStack'}}; + } + + $expanded = parsein($expanded, \%element) if $preparsed; + return $expanded; +} + +######## bml_decode +# +# turns BML source into expanded HTML source +# +# $inref scalar reference to BML source. $$inref gets destroyed. +# $outref scalar reference to where output is appended. +# $opts security flags +# $elhash optional elements hashref + +use vars qw(%re_decode); +sub bml_decode +{ + my BML::Request $req = shift; + my ($inref, $outref, $opts, $elhash) = @_; + + my $block = undef; # what are we in? + my $data = undef; # what is inside the current block? + my $depth = 0; # how many blocks we are deep of the *SAME* type. + my $re; # active regular expression for finding closing tag + + pos($$inref) = 0; + + EAT: + for (;;) + { + # currently not in a BML tag... looking for one! + if (! defined $block) { + if ($$inref =~ m/ + \G # start where last match left off + (?> # independent regexp: won't backtrack the .*? below. + (.*?) # $1 -> optional non-BML stuff before opening tag + $TokenOpen + (\w+) # $2 -> tag name + ) + (?: # CASE A: could be 1) immediate tag close, 2) tag close + # with data, or 3) slow path, below + ($TokenClose) | # A.1: $3 -> immediate tag close (depth 0) + (?: # A.2: simple close with data (data has no BML start tag of same tag) + ((?:.(?!$TokenOpen\2\b))+?) # $4 -> one or more chars without following opening BML tags + \b\2$TokenClose # matching closing tag + ) | + # A.3: final case: nothing, it's not the fast path. handle below. + ) # end case A + /gcosx) + { + $$outref .= $1; + $block = uc($2); + $data = $4 || ""; + + # fast path: immediate close or simple data (no opening BML). + if (defined $4 || $3) { + $$outref .= bml_block($req, $block, $data, $opts, $elhash); + return if $req->{'stop_flag'}; + $data = undef; + $block = undef; + next EAT; + } + + # slower (nesting) path. + # fast path (above) + # fast: ... foo?> + # slow (this path): ... foo?> + + $depth = 1; + + # prepare/find a cached regexp to continue using below + # continues below, finding an opening/close of existing tag + $re = $re_decode{$block} ||= + qr/($TokenClose) | # $1 -> immediate token closing + (?: + (.+?) # $2 -> non-BML part to push onto $data + (?: + ($TokenOpen$block\b) | # $3 -> increasing depth + (\b$block$TokenClose) # $4 -> decreasing depth + ) + )/isx; + + # falls through below. + + } else { + # no BML left? append it all and be done. + $$outref .= substr($$inref, pos($$inref)); + return; + } + } + + # continue with slow path. + + # the regexp prepared above looks out for these cases: (but not in + # this order) + # + # * Increasing depth: + # - some text, then another opening + # - closing the tag (if depth == 0, then we're done) + # + + if ($$inref =~ m/\G$re/gc) { + if ($1) { + # immediate close + $depth--; + $data .= $1 if $depth; # add closing token if we're still in another tag + } elsif ($3) { + # increasing depth of same block + $data .= $2; # data before opening bml tag + $data .= $3; # the opening tag itself + $depth++; + } elsif ($4) { + # decreasing depth of same block + $data .= $2; # data before closing tag + $depth--; + $data .= $4 if $depth; # add closing tag itself, if we're still in another tag + } + } else { + $$outref .= inline_error("BML block '$block' has no close"); + return; + } + + # handle finished blocks + if ($depth == 0) { + $$outref .= bml_block($req, $block, $data, $opts, $elhash); + return if $req->{'stop_flag'}; + $data = undef; + $block = undef; + } + } +} + +# takes a scalar with %%FIELDS%% mixed in and replaces +# them with their correct values from an anonymous hash, given +# by the second argument to this call +sub parsein +{ + my ($data, $hashref) = @_; + $data =~ s/%%(\w+)%%/$hashref->{uc($1)}/eg; + return $data; +} + +sub inline_error +{ + return "[Error: @_]"; +} + +# returns lower-cased, trimmed string +sub trim +{ + my $a = $_[0]; + $a =~ s/^\s*(.*?)\s*$/$1/s; + return $a; +} + +sub load_look_perl +{ + my ($file) = @_; + + $conf_pl_look = {}; + eval { do $file; }; + if ($@) { + print STDERR "Error evaluating BML block conf file $file: $@\n"; + return 0; + } + $LookItems{$file} = $conf_pl_look; + undef $conf_pl_look; + + return 1; +} + +sub load_look +{ + my $file = shift; + my BML::Request $req = shift; # optional + + my $dontcheck = file_dontcheck($file); + if ($dontcheck) { + return 0 unless $FileModTime{$file}; + note_mod_time($req, $FileModTime{$file}) if $req; + return 1; + } + note_mod_time($req, $FileModTime{$file}) if $req; + + if ($file =~ /\.pl$/) { + return load_look_perl($file); + } + + my $target = $LookItems{$file} = {}; + + foreach my $look ($file, keys %{$LookChild{$file}||{}}) { + delete $SchemeData->{$look}; + delete $SchemeFlags->{$look}; + } + + open (LOOK, $file); + my $look_file; + { local $/ = undef; $look_file = ; } + close LOOK; + load_elements($target, $look_file); + + # look for template types + while (my ($k, $v) = each %$target) { + if ($v =~ s/^\{([A-Za-z]+)\}//) { + $v = [ $v, $1 ]; + } else { + $v = [ $v ]; + } + $target->{$k} = $v; + } + + $LookParent{$file} = undef; + if ($target->{'_PARENT'}) { + my $parfile = file_rel2abs($file, $target->{'_PARENT'}->[0]); + if ($parfile && load_look($parfile)) { + $LookParent{$file} = $parfile; + $LookChild{$parfile}->{$file} = 1; + } + } + + return 1; +} + +# given a block of data, loads elements found into +sub load_elements +{ + my ($hashref, $data, $opts) = @_; + my $ol = $opts->{'declorder'}; + + my @lines = split(/\r?\n/, $data); + + while (@lines) { + my $line = shift @lines; + + # single line declaration: + # key=>value + if ($line =~ /^\s*(\w[\w\/]*)=>(.*)/) { + $hashref->{uc($1)} = $2; + push @$ol, uc($1); + next; + } + + # multi-line declaration: + # key<= + # line1 + # line2 + # <=key + if ($line =~ /^\s*(\w[\w\/]*)<=\s*$/) { + my $block = uc($1); + my $endblock = qr/^\s*<=$1\s*$/; + my $newblock = qr/^\s*$1<=\s*$/; + my $depth = 1; + my @out; + while (@lines) { + $line = shift @lines; + if ($line =~ /$newblock/) { + $depth++; + next; + } elsif ($line =~ /$endblock/) { + $depth--; + last unless $depth; + } + push @out, $line; + } + if ($depth == 0) { + $hashref->{$block} = join("\n", @out) . "\n"; + push @$ol, $block; + } + } + + } # end while (@lines) +} + +# given a file, checks it's modification time and sees if it's +# newer than anything else that compiles into what is the document +sub note_file_mod_time +{ + my ($req, $file) = @_; + note_mod_time($req, (stat($file))[9]); +} + +sub note_mod_time +{ + my BML::Request $req = shift; + my $mod_time = shift; + + if ($req) { + if ($mod_time > $req->{'most_recent_mod'}) { + $req->{'most_recent_mod'} = $mod_time; + } + } else { + if ($mod_time > $Apache::BML::base_recent_mod) { + $Apache::BML::base_recent_mod = $mod_time; + } + } +} + +# formatting +sub modified_time +{ + my BML::Request $req = shift; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($req->{'most_recent_mod'}); + my @day = qw{Sun Mon Tue Wed Thu Fri Sat}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + if ($year < 1900) { $year += 1900; } + + return sprintf("$day[$wday], %02d $month[$mon] $year %02d:%02d:%02d GMT", + $mday, $hour, $min, $sec); +} + +# both Cwd and File::Spec suck. they're portable, but they suck. +# these suck too (slow), but they do what i want. + +sub dir_rel2abs { + my ($dir, $rel) = @_; + return $rel if $rel =~ m!^/!; + my @dir = grep { $_ ne "" } split(m!/!, $dir); + my @rel = grep { $_ ne "" } split(m!/!, $rel); + while (@rel) { + $_ = shift @rel; + next if $_ eq "."; + if ($_ eq "..") { pop @dir; next; } + push @dir, $_; + } + return join('/', '', @dir); +} + +sub file_rel2abs { + my ($file, $rel) = @_; + return $rel if $rel =~ m!^/!; + $file =~ s!(.+/).*!$1!; + return dir_rel2abs($file, $rel); +} + +package BML; + +# returns false if remote browser can't handle the HttpOnly cookie atttribute +# (Microsoft extension to make cookies unavailable to scripts) +# it renders cookies useless on some browsers. by default, returns true. +sub http_only +{ + my $ua = BML::get_client_header("User-Agent"); + return 0 if $ua =~ /MSIE.+Mac_/; + return 1; +} + +sub fill_template +{ + my ($name, $vars) = @_; + return Apache::BML::parsein(${$Apache::BML::cur_req->{'blockref'}->{uc($name)}}, + $vars); +} + +sub get_scheme +{ + return $Apache::BML::cur_req->{'scheme'}; +} + +sub set_scheme +{ + my BML::Request $req = $Apache::BML::cur_req; + my $scheme = shift; + return 0 if $scheme =~ /\W/; + unless ($scheme) { + $scheme = $req->{'env'}->{'ForceScheme'} || + $req->{'env'}->{'DefaultScheme'}; + } + + my $file = "$req->{env}{LookRoot}/$scheme.look"; + + return 0 unless Apache::BML::load_look($file); + + $req->{'scheme'} = $scheme; + $req->{'scheme_file'} = $file; + + # now we have to combine both of these (along with the VARINIT) + # and then expand all the static stuff + unless (exists $SchemeData->{$file}) { + my $iter = $file; + my @files; + while ($iter) { + unshift @files, $iter; + $iter = $Apache::BML::LookParent{$iter}; + } + + my $sd = $SchemeData->{$file} = {}; + my $sf = $SchemeFlags->{$file} = {}; + + foreach my $file (@files) { + while (my ($k, $v) = each %{$Apache::BML::LookItems{$file}}) { + $sd->{$k} = $v->[0]; + $sf->{$k} = $v->[1]; + } + } + foreach my $k (keys %$sd) { + next unless index($sf->{$k}, 's') != -1; + $sd->{$k} =~ s/$TokenOpen([a-zA-Z0-9\_]+?)$TokenClose/$sd->{uc($1)}/og; + } + } + + # now, this request needs a copy of (well, references to) the + # data above. can't use that directly, since it might + # change using _INFO LOCALBLOCKS to declare new file-local blocks + $req->{'blockflags'} = { + '_INFO' => 'F', '_INCLUDE' => 'F', + }; + $req->{'blockref'} = {}; + foreach my $k (keys %{$SchemeData->{$file}}) { + $req->{'blockflags'}->{$k} = $SchemeFlags->{$file}->{$k}; + $req->{'blockref'}->{$k} = \$SchemeData->{$file}->{$k}; + } + + return 1; +} + +sub set_etag +{ + my $etag = shift; + $Apache::BML::cur_req->{'etag'} = $etag; +} + +# when CODE blocks need to look-up static values and such +sub get_template_def +{ + my $blockname = shift; + my $schemefile = $Apache::BML::cur_req->{'scheme_file'}; + return $SchemeData->{$schemefile}->{uc($blockname)}; +} + +sub parse_multipart +{ + my ($dest, $error, $max_size) = @_; + my $r = $Apache::BML::r; + my $err = sub { $$error = $_[0]; return 0; }; + + my $size = $r->header_in("Content-length"); + unless ($size) { + return $err->("No content-length header: can't parse"); + } + if ($max_size && $size > $max_size) { + return $err->("[toolarge] Upload too large"); + } + + my $sep; + unless ($r->header_in("Content-Type") =~ m!^multipart/form-data;\s*boundary=(\S+)!) { + return $err->("[unknowntype] Unknown content type"); + } + $sep = $1; + + my $content; + $r->read($content, $size); + my @lines = split(/\r\n/, $content); + my $line = shift @lines; + return $err->("[parse] Error parsing upload") unless $line eq "--$sep"; + + while (@lines) { + $line = shift @lines; + my %h; + while (defined $line && $line ne "") { + $line =~ /^(\S+?):\s*(.+)/; + $h{lc($1)} = $2; + $line = shift @lines; + } + while (defined $line && $line ne "--$sep") { + last if $line eq "--$sep--"; + $h{'body'} .= "\r\n" if $h{'body'}; + $h{'body'} .= $line; + $line = shift @lines; + } + if ($h{'content-disposition'} =~ /name="(\S+?)"/) { + my $name = $1 || $2; + $dest->{$name} = $h{'body'}; + } + } + + return 1; +} + +# FIXME: document the hooks +sub parse_multipart_interactive { + my ($r, $errref, $hooks) = @_; + + # subref to set $@ and $$errref, then return false + my $err = sub { $$errref = $@ = $_[0], return 0 }; + + my $run_hook = sub { + my $name = shift; + my $ret = eval { $hooks->{$name}->(@_) }; + if ($@) { + return $err->($@); + } + unless ($ret) { + return $err->("Hook: '$name' returned false"); + } + return 1; + }; + + # size hook is optional + my $size = $r->header_in("Content-length"); + if ($hooks->{size}) { + $run_hook->('size', $size) + or return 0; + } + + unless ($r->header_in("Content-Type") =~ m!^multipart/form-data;\s*boundary=(\S+)!) { + return $err->("No MIME boundary. Bogus Content-type? " . $r->header_in("Content-Type")); + } + my $sep = "--$1"; + my $seplen = length($sep) + 2; # plus \r\n + + my $window = ''; + my $to_read = $size; + my $max_read = 8192; + + my $seen_chunk = 0; # have we seen any chunk yet? + + my $state = 0; # what we last parsed + # 0 = nothing (looking for a separator) + # 1 = separator (looking for headers) + # 0 = headers (looking for data) + # 0 = data (looking for a separator) + + while (1) { + my $read = -1; + if ($to_read) { + $read = $r->read($window, + $to_read < $max_read ? $to_read : $max_read, + length($window)); + $to_read -= $read; + + # prevent loops. Opera, in particular, alerted us to + # this bug, since it doesn't upload proper MIME on + # reload and its Content-Length header is correct, + # but its body tiny + if ($read == 0) { + return $err->("No data from client. Possibly a refresh?"); + } + } + + # starting case, or data-reading case (looking for separator) + if ($state == 0) { + my $idx = index($window, $sep); + + # didn't find a separator. emit the previous data + # which we know for sure is data and not a possible + # new separator + if ($idx == -1) { + # bogus if we're done reading and didn't find what we're + # looking for: + if ($read == -1) { + return $err->("Couldn't find separator, no more data to read"); + } + + if ($seen_chunk) { + + # data hook is required + my $len = length($window) - $seplen; + $run_hook->('data', $len, substr($window, 0, $len, '')) + or return 0; + } + next; + } + + # we found a separator. emit the previous read's + # data and enddata. + if ($seen_chunk) { + my $len = $idx - 2; + if ($len > 0) { + + # data hook is required + $run_hook->('data', $len, substr($window, 0, $len)) + or return 0; + } + + # enddata hook is required + substr($window, 0, $idx, ''); + $run_hook->('enddata') + or return 0; + } + + # we're now looking for a header + $seen_chunk = 1; + $state = 1; + + # have we hit the end? + return 1 if $to_read <= 2 && length($window) <= $seplen + 4; + } + + # read a separator, looking for headers + if ($state == 1) { + my $idx = index($window, "\r\n\r\n"); + if ($idx == -1) { + if (length($window) > 8192) { + return $err->("Window too large: " . length($window) . " bytes > 8192"); + } + + # bogus if we're done reading and didn't find what we're + # looking for: + if ($read == -1) { + return $err->("Couldn't find headers, no more data to read"); + } + + next; + } + + # +4 is \r\n\r\n + my $header = substr($window, 0, $idx+4, ''); + my @lines = split(/\r\n/, $header); + + my %hdval; + my $lasthd; + foreach (@lines) { + if (/^(\S+?):\s*(.+)/) { + $lasthd = lc($1); + $hdval{$lasthd} = $2; + } elsif (/^\s+.+/) { + $hdval{$lasthd} .= $&; + } + } + + my ($name, $filename); + if ($hdval{'content-disposition'} =~ /\bNAME=\"(.+?)\"/i) { + $name = $1; + } + if ($hdval{'content-disposition'} =~ /\bFILENAME=\"(.+?)\"/i) { + $filename = $1; + } + + # newheaders hook is required + $run_hook->('newheaders', $name, $filename) + or return 0; + + $state = 0; + } + + } + return 1; +} + + +sub reset_cookies +{ + %BML::COOKIE_R = (); + %BML::COOKIE_M = (); + $BML::COOKIES_PARSED = 0; +} + +sub set_config +{ + my ($key, $val) = @_; + die "BML::set_config called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{$key} ||= $val; + #$Apache::BML::config->{$path}->{$key} = $val; +} + +sub noparse +{ + $Apache::BML::CodeBlockOpts{'raw'} = 1; + return $_[0]; +} + +sub decide_language +{ + my BML::Request $req = $Apache::BML::cur_req; + my $env = $req->{'env'}; + + # GET param 'uselang' takes priority + my $uselang = $BMLCodeBlock::GET{'uselang'}; +# if (exists $env->{"Langs-$uselang"} || $uselang eq "debug") { +# return $uselang; +# } + if ($uselang eq "debug") { + return $uselang; + } + + # next is their cookie preference + if ($BML::COOKIE{'langpref'} =~ m!^(\w{2,10})/(\d+)$!) { + if (exists $env->{"Langs-$1"}) { + # make sure the document says it was changed at least as new as when + # the user last set their current language, else their browser might + # show a cached (wrong language) version. + note_mod_time($req, $2); + return $1; + } + } + + # next is their browser's preference +# my %lang_weight = (); +# my @langs = split(/\s*,\s*/, lc($req->{'r'}->header_in("Accept-Language"))); +# my $winner_weight = 0.0; +# my $winner; +# foreach (@langs) +# { +# # do something smarter in future. for now, ditch country code: +# s/-\w+//; +# +# if (/(.+);q=(.+)/) { +# $lang_weight{$1} = $2; +# } else { +# $lang_weight{$_} = 1.0; +# } +# if ($lang_weight{$_} > $winner_weight && defined $env->{"ISOCode-$_"}) { +# $winner_weight = $lang_weight{$_}; +# $winner = $env->{"ISOCode-$_"}; +# } +# } +# return $winner if $winner; + + # next is the default language + return $req->{'env'}->{'DefaultLanguage'} if $req->{'env'}->{'DefaultLanguage'}; + + # lastly, english. + return "ru"; +} + +sub register_language +{ + my ($langcode) = @_; + die "BML::register_language called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"Langs-$langcode"} ||= 1; +} + +sub register_isocode +{ + my ($isocode, $langcode) = @_; + next unless $isocode =~ /^\w{2,2}$/; + die "BML::register_isocode called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"ISOCode-$isocode"} ||= $langcode; +} + +# get/set the flag to send the Last-Modified header +sub want_last_modified +{ + $Apache::BML::cur_req->{'want_last_modified'} = $_[0] + if defined $_[0]; + return $Apache::BML::cur_req->{'want_last_modified'}; +} + +sub note_mod_time +{ + my $mod_time = shift; + Apache::BML::note_mod_time($Apache::BML::cur_req, $mod_time); +} + +sub redirect +{ + my $url = shift; + $Apache::BML::cur_req->{'location'} = $url; + finish_suppress_all(); + return; +} + +sub do_later +{ + my $subref = shift; + return 0 unless ref $subref eq "CODE"; + $Apache::BML::cur_req->{'r'}->register_cleanup($subref); + return 1; +} + +sub register_block +{ + my ($type, $flags, $def) = @_; + my $target = $Apache::BML::conf_pl_look; + die "BML::register_block called from non-lookfile context.\n" unless $target; + $type = uc($type); + + $target->{$type} = [ $def, $flags ]; + return 1; +} + +sub register_hook +{ + my ($name, $code) = @_; + die "BML::register_hook called from non-conffile context.\n" unless $Apache::BML::conf_pl; + $Apache::BML::conf_pl->{"HOOK-$name"} = $code; +} + +sub get_request +{ + # we do this, and not use $Apache::BML::r directly because some non-BML + # callers sometimes use %BML::COOKIE, so $Apache::BML::r isn't set. + # the cookie FETCH below calls this function to try and use Apache->request, + # else fall back to the global one (for use in profiling/debugging) + my $r; + eval { + $r = Apache->request; + }; + $r ||= $Apache::BML::r; + return $r; +} + +sub get_query_string +{ + return scalar($Apache::BML::r->args); +} + +sub get_uri +{ + return $Apache::BML::r->uri; +} + +sub get_method +{ + return $Apache::BML::r->method; +} + +sub get_path_info +{ + return $Apache::BML::r->path_info; +} + +sub get_remote_ip +{ + my $ip1 = $Apache::BML::r->connection()->remote_ip; + my $ip2 = $Apache::BML::r->header_in("X-Forwarded-For"); + + return LJ::get_real_remote_ip($ip1, $ip2); +} + +sub get_remote_host +{ + return $Apache::BML::r->connection()->remote_host; +} + +sub get_remote_user +{ + return $Apache::BML::r->connection()->user; +} + +sub get_client_header +{ + my $hdr = shift; + return $Apache::BML::r->header_in($hdr); +} + +# +# class: web +# name: BML::self_link +# des: Takes the URI of the current page, and adds the current form data +# to the url, then adds any additional data to the url. +# returns: scalar; the full url +# args: newvars +# des-newvars: A hashref of information to add/override to the link. +# +sub self_link +{ + my $newvars = shift; + my $link = $Apache::BML::r->uri; + my $form = \%BMLCodeBlock::FORM; + + $link .= "?"; + foreach (keys %$newvars) { + if (! exists $form->{$_}) { $form->{$_} = ""; } + } + foreach (sort keys %$form) { + if (defined $newvars->{$_} && ! $newvars->{$_}) { next; } + my $val = $newvars->{$_} || $form->{$_}; + next unless $val; + $link .= BML::eurl($_) . "=" . BML::eurl($val) . "&"; + } + chop $link; + return $link; +} + +sub http_response +{ + my ($code, $msg) = @_; + + my $r = $Apache::BML::r; + $r->status($code); + $r->content_type('text/html'); + $r->print($msg); + finish_suppress_all(); + return; +} + +sub finish_suppress_all +{ + finish(); + suppress_headers(); + suppress_content(); +} + +sub suppress_headers +{ + # set any cookies that we have outstanding + send_cookies(); + $Apache::BML::cur_req->{'env'}->{'NoHeaders'} = 1; +} + +sub suppress_content +{ + $Apache::BML::cur_req->{'env'}->{'NoContent'} = 1; +} + +sub finish +{ + $Apache::BML::cur_req->{'stop_flag'} = 1; +} + +sub set_content_type +{ + $Apache::BML::cur_req->{'content_type'} = $_[0] if $_[0]; +} + +# +# class: web +# name: BML::set_status +# des: Takes a number to indicate a status (e.g. 404, 403, 410, 500, etc) and sets +# that to be returned to the client when the request finishes. +# returns: nothing +# args: status +# des-newvars: A number representing the status to return to the client. +# +sub set_status +{ + $Apache::BML::r->status($_[0]+0) if $_[0]; +} + +sub eall +{ + return ebml(ehtml($_[0])); +} + + +# escape html +sub ehtml +{ + my $a = $_[0]; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +sub ebml +{ + my $a = $_[0]; + my $ra = ref $a ? $a : \$a; + $$ra =~ s/\(=(\w)/\(= $1/g; # remove this eventually (old syntax) + $$ra =~ s/(\w)=\)/$1 =\)/g; # remove this eventually (old syntax) + $$ra =~ s/<\?/<?/g; + $$ra =~ s/\?>/?>/g; + return if ref $a; + return $a; +} + +sub get_language +{ + return $Apache::BML::cur_req->{'lang'}; +} + +sub get_language_default +{ + return $Apache::BML::cur_req->{'env'}->{'DefaultLanguage'} || "en"; +} + +sub set_language_scope { + $BML::ML_SCOPE = shift; +} + +sub set_language +{ + my ($lang, $getter) = @_; # getter is optional + my BML::Request $req = $Apache::BML::cur_req; + my $r = BML::get_request(); + $r->notes('langpref' => $lang); + + # don't rely on $req (the current BML request) being defined, as + # we allow callers to use this interface directly from non-BML + # requests. + if ($req) { + $req->{'lang'} = $lang; + $getter ||= $req->{'env'}->{'HOOK-ml_getter'}; + } + + no strict 'refs'; + if ($lang eq "debug") { + *{"BML::ml"} = sub { + return $_[0]; + }; + *{"BML::ML::FETCH"} = sub { + return $_[1]; + }; + } elsif ($getter) { + *{"BML::ml"} = sub { + my ($code, $vars) = @_; + $code = $BML::ML_SCOPE . $code + if rindex($code, '.', 0) == 0; + return $getter->($lang, $code, undef, $vars); + }; + *{"BML::ML::FETCH"} = sub { + my $code = $_[1]; + $code = $BML::ML_SCOPE . $code + if rindex($code, '.', 0) == 0; + return $getter->($lang, $code); + }; + }; + +} + +# multi-lang string +# note: sub is changed when BML::set_language is called +sub ml +{ + return "[ml_getter not defined]"; +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +sub randlist +{ + my @rlist = @_; + my $size = scalar(@rlist); + + my $i; + for ($i=0; $i<$size; $i++) + { + unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1); + } + return @rlist; +} + +sub page_newurl +{ + my $page = $_[0]; + my @pair = (); + foreach (sort grep { $_ ne "page" } keys %BMLCodeBlock::FORM) + { + push @pair, (eurl($_) . "=" . eurl($BMLCodeBlock::FORM{$_})); + } + push @pair, "page=$page"; + return $Apache::BML::r->uri . "?" . join("&", @pair); +} + +sub paging +{ + my ($listref, $page, $pagesize) = @_; + $page = 1 unless ($page && $page==int($page)); + my %self; + + $self{'itemcount'} = scalar(@{$listref}); + + $self{'pages'} = $self{'itemcount'} / $pagesize; + $self{'pages'} = $self{'pages'}==int($self{'pages'}) ? $self{'pages'} : (int($self{'pages'})+1); + + $page = 1 if $page < 1; + $page = $self{'pages'} if $page > $self{'pages'}; + $self{'page'} = $page; + + $self{'itemfirst'} = $pagesize * ($page-1) + 1; + $self{'itemlast'} = $self{'pages'}==$page ? $self{'itemcount'} : ($pagesize * $page); + + $self{'items'} = [ @{$listref}[($self{'itemfirst'}-1)..($self{'itemlast'}-1)] ]; + + unless ($page==1) { $self{'backlink'} = "<<<"; } + unless ($page==$self{'pages'}) { $self{'nextlink'} = ">>>"; } + + return %self; +} + +sub send_cookies { + my $req = shift() || $Apache::BML::cur_req; + foreach (values %{$req->{'cookies'}}) { + $req->{'r'}->err_headers_out->add("Set-Cookie" => $_); + } + $req->{'cookies'} = {}; + $req->{'env'}->{'SentCookies'} = 1; +} + +# $expires = 0 to expire when browser closes +# $expires = undef to delete cookie +sub set_cookie +{ + my ($name, $value, $expires, $path, $domain, $http_only) = @_; + + my BML::Request $req = $Apache::BML::cur_req; + my $e = $req->{'env'}; + $path = $e->{'CookiePath'} unless defined $path; + $domain = $e->{'CookieDomain'} unless defined $domain; + + # let the domain argument be an array ref, so callers can set + # cookies in both .foo.com and foo.com, for some broken old browsers. + if ($domain && ref $domain eq "ARRAY") { + foreach (@$domain) { + set_cookie($name, $value, $expires, $path, $_, $http_only); + } + return; + } + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($expires); + $year+=1900; + + my @day = qw{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + my $cookie = eurl($name) . "=" . eurl($value); + + # this logic is confusing potentially + unless (defined $expires && $expires==0) { + $cookie .= sprintf("; expires=$day[$wday], %02d-$month[$mon]-%04d %02d:%02d:%02d GMT", + $mday, $year, $hour, $min, $sec); + } + $cookie .= "; path=$path" if $path; + $cookie .= "; domain=$domain" if $domain; + $cookie .= "; HttpOnly" if $http_only && BML::http_only(); + + # send a cookie directly or cache it for sending later? + if ($e->{'SentCookies'}) { + $req->{'r'}->err_headers_out->add("Set-Cookie" => $cookie); + } else { + $req->{'cookies'}->{"$name:$domain"} = $cookie; + } + + if (defined $expires) { + $BML::COOKIE_R{$name} = $value; + } else { + delete $BML::COOKIE_R{$name}; + } +} + +# cookie support +package BML::Cookie; + +sub TIEHASH { + my $class = shift; + my $self = {}; + bless $self; + return $self; +} + +sub FETCH { + my ($t, $key) = @_; + # we do this, and not use $Apache::BML::r directly because some non-BML + # callers sometimes use %BML::COOKIE. + my $r = BML::get_request(); + unless ($BML::COOKIES_PARSED) { + foreach (split(/;\s+/, $r->header_in("Cookie"))) { + next unless ($_ =~ /(.*)=(.*)/); + my ($name, $value) = ($1, $2); + + # if the cookie already exists, we'll take the existing value as + # well as all new ones, and push them onto an arrayref in COOKIE_M + if (exists $BML::COOKIE_R{$name}) { + push @{$BML::COOKIE_M{$name}}, $BML::COOKIE_R{$name} + unless ref $BML::COOKIE_M{$name}; + + push @{$BML::COOKIE_M{$name}}, $value; + } + + $BML::COOKIE_R{BML::durl($name)} = BML::durl($value); + } + $BML::COOKIES_PARSED = 1; + } + + # return scalar value, or arrayref if key has [] appended + return $key =~ s/\[\]$// ? + $BML::COOKIE_M{$key} || [$BML::COOKIE_R{$key}] : $BML::COOKIE_R{$key}; +} + +sub STORE { + my ($t, $key, $val) = @_; + my $etime = 0; + my $http_only = 0; + ($val, $etime, $http_only) = @$val if ref $val eq "ARRAY"; + $etime = undef unless $val ne ""; + BML::set_cookie($key, $val, $etime, undef, undef, $http_only); +} + +sub DELETE { + my ($t, $key) = @_; + STORE($t, $key, undef); +} + +sub CLEAR { + my ($t) = @_; + foreach (keys %BML::COOKIE_R) { + STORE($t, $_, undef); + } +} + +sub EXISTS { + my ($t, $key) = @_; + return defined $BML::COOKIE_R{$key}; +} + +sub FIRSTKEY { + my ($t) = @_; + keys %BML::COOKIE_R; + return each %BML::COOKIE_R; +} + +sub NEXTKEY { + my ($t, $key) = @_; + return each %BML::COOKIE_R; +} + +# provide %BML::ML & %BMLCodeBlock::ML support: +package BML::ML; + +sub TIEHASH { + my $class = shift; + my $self = {}; + bless $self; + return $self; +} + +# note: sub is changed when BML::set_language is called. +sub FETCH { + return "[ml_getter not defined]"; +} + +# do nothing +sub CLEAR { } + +1; + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/local/cgi-bin/Apache/LiveJournal.pm b/local/cgi-bin/Apache/LiveJournal.pm new file mode 100755 index 0000000..dcfe214 --- /dev/null +++ b/local/cgi-bin/Apache/LiveJournal.pm @@ -0,0 +1,1618 @@ +#!/usr/bin/perl +# + +package Apache::LiveJournal; + +use strict; +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED HTTP_MOVED_PERMANENTLY + M_TRACE M_OPTIONS); +use Apache::File (); +use lib "$ENV{'LJHOME'}/cgi-bin"; +use Apache::LiveJournal::PalImg; +use LJ::S2; +use LJ::Blob; +use Apache::LiveJournal::Interface::Blogger; +use Apache::LiveJournal::Interface::AtomAPI; +use Apache::LiveJournal::Interface::S2; +use LJR::GD; + +BEGIN { + $LJ::OPTMOD_ZLIB = eval "use Compress::Zlib (); 1;"; + $LJ::OPTMOD_XMLRPC = eval "use XMLRPC::Transport::HTTP (); 1;"; + + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl"; + require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl"; + if (%LJ::FOTOBILDER_IP) { + use Apache::LiveJournal::Interface::FotoBilder; + } +} + +my %RQ; # per-request data +my %USERPIC; # conf related to userpics +my %REDIR; +my $GTop; # GTop object (created if $LJ::LOG_GTOP is true) + +# Mapping of MIME types to image types understood by the blob functions. +my %MimeTypeMap = ( + 'image/gif' => 'gif', + 'image/jpeg' => 'jpg', + 'image/png' => 'png', +); +my %MimeTypeMapd6 = ( + 'G' => 'gif', + 'J' => 'jpg', + 'P' => 'png', +); + +$USERPIC{'cache_dir'} = "$ENV{'LJHOME'}/htdocs/userpics"; +$USERPIC{'use_disk_cache'} = -d $USERPIC{'cache_dir'}; +$USERPIC{'symlink'} = eval { symlink('',''); 1; }; + +# redirect data. +foreach my $file ('redirect.dat', 'redirect-local.dat') { + open (REDIR, "$ENV{'LJHOME'}/cgi-bin/$file") or next; + while () { + next unless (/^(\S+)\s+(\S+)/); + my ($src, $dest) = ($1, $2); + $REDIR{$src} = $dest; + } + close REDIR; +} + +my @req_hosts; # client IP, and/or all proxies, real or claimed + +# init handler (PostReadRequest) +sub handler +{ + my $r = shift; + + if ($LJ::SERVER_TOTALLY_DOWN) { + $r->handler("perl-script"); + $r->set_handlers(PerlHandler => [ \&totally_down_content ]); + return OK; + } + + # only perform this once in case of internal redirects + if ($r->is_initial_req) { + $r->push_handlers(PerlCleanupHandler => sub { %RQ = () }); + $r->push_handlers(PerlCleanupHandler => "Apache::LiveJournal::db_logger"); + $r->push_handlers(PerlCleanupHandler => "LJ::end_request"); + + if ($LJ::TRUST_X_HEADERS) { + # if we're behind a lite mod_proxy front-end, we need to trick future handlers + # into thinking they know the real remote IP address. problem is, it's complicated + # by the fact that mod_proxy did nothing, requiring mod_proxy_add_forward, then + # decided to do X-Forwarded-For, then did X-Forwarded-Host, so we have to deal + # with all permutations of versions, hence all the ugliness: + @req_hosts = ($r->connection->remote_ip); + if (my $forward = $r->header_in('X-Forwarded-For')) + { + my (@hosts, %seen); + foreach (split(/\s*,\s*/, $forward)) { + next if $seen{$_}++; + push @hosts, $_; + push @req_hosts, $_; + } + if (@hosts) { + my $real = pop @hosts; + $r->connection->remote_ip($real); + } + $r->header_in('X-Forwarded-For', join(", ", @hosts)); + } + + # and now, deal with getting the right Host header + if ($_ = $r->header_in('X-Host')) { + $r->header_in('Host', $_); + } elsif ($_ = $r->header_in('X-Forwarded-Host')) { + $r->header_in('Host', $_); + } + } + + # reload libraries that might've changed + if ($LJ::IS_DEV_SERVER) { + my %to_reload; + while (my ($file, $mod) = each %LJ::LIB_MOD_TIME) { + my $cur_mod = (stat($file))[9]; + next if $cur_mod == $mod; + $to_reload{$file} = 1; + } + my @key_del; + foreach (my ($key, $file) = each %INC) { + push @key_del, $key if $to_reload{$file}; + } + delete $INC{$_} foreach @key_del; + + foreach my $file (keys %to_reload) { + print STDERR "Reloading $file...\n"; + my $good = do $file; + if ($good) { + $LJ::LIB_MOD_TIME{$file} = (stat($file))[9]; + } else { + die "Failed to reload module [$file] due to error: $@\n"; + } + } + } + } + + $r->set_handlers(PerlTransHandler => [ \&trans ]); + + return OK; +} + +sub redir +{ + my ($r, $url, $code) = @_; + $r->content_type("text/html"); + $r->header_out(Location => $url); + return $code || REDIRECT; +} + +sub totally_down_content +{ + my $r = shift; + my $uri = $r->uri; + + if ($uri =~ m!^/interface/flat! || $uri =~ m!^/cgi-bin/log\.cg!) { + $r->content_type("text/plain"); + $r->send_http_header(); + $r->print("success\nFAIL\nerrmsg\n$LJ::SERVER_DOWN_MESSAGE"); + return OK; + } + + if ($uri =~ m!^/customview.cgi!) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print(""); + return OK; + } + + # FIXME: ljcom-specific, move to a hook; too lazy now. + if ($uri =~ m!^/paidaccounts/pp_notify\.bml!) { + $r->status(SERVER_ERROR); + } + + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("

    $LJ::SERVER_DOWN_SUBJECT

    $LJ::SERVER_DOWN_MESSAGE"); + return OK; +} + +sub blocked_bot +{ + my $r = shift; + + $r->status_line("403 Denied"); + $r->content_type("text/html"); + $r->send_http_header(); + my $subject = $LJ::BLOCKED_BOT_SUBJECT || "403 Denied"; + my $message = $LJ::BLOCKED_BOT_MESSAGE || "You don't have permission to view this page."; + $r->print("

    $subject

    $message"); + return OK; +} + +sub trans +{ + my $r = shift; + return DECLINED if ! $r->is_main || $r->method_number == M_OPTIONS; # don't deal with subrequests or OPTIONS + + my $uri = $r->uri; + my $args = $r->args; + my $args_wq = $args ? "?$args" : ""; + my $host = $r->header_in("Host"); + my $hostport = ($host =~ s/:\d+$//) ? $& : ""; + + # disable TRACE (so scripts on non-LJ domains can't invoke + # a trace to get the LJ cookies in the echo) + return FORBIDDEN if $r->method_number == M_TRACE; + + # If the configuration says to log statistics and GTop is available, mark + # values before the request runs so it can be turned into a delta later + if ( $LJ::LOG_GTOP && $LJ::HAVE_GTOP ) { + $GTop ||= new GTop; + $r->pnotes( 'gtop_cpu' => $GTop->cpu ); + $r->pnotes( 'gtop_mem' => $GTop->proc_mem($$) ); + } + + LJ::start_request(); + LJ::procnotify_check(); + S2::set_domain('LJ'); + + my $is_ssl = $LJ::IS_SSL = LJ::run_hook("ssl_check", { + r => $r, + }); + + # handle uniq cookies + if ($LJ::UNIQ_COOKIES && $r->is_initial_req) { + + # if cookie exists, check for sysban + my ($uniq, $uniq_time); + if (Apache->header_in("Cookie") =~ /\bljuniq\s*=\s*([a-zA-Z0-9]{15}):(\d+)/) { + ($uniq, $uniq_time) = ($1, $2); + $r->notes("uniq" => $uniq); + if (LJ::sysban_check('uniq', $uniq) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + }; + } + + # if no cookie, create one. if older than a day, revalidate + my $now = time(); + my $DAY = 3600*24; + if (! $uniq || $now - $uniq_time > $DAY) { + $uniq ||= LJ::rand_chars(15); + + # set uniq cookies for all cookie_domains + my @domains = ref $LJ::COOKIE_DOMAIN ? @$LJ::COOKIE_DOMAIN : ($LJ::COOKIE_DOMAIN); + foreach my $dom (@domains) { + $r->err_headers_out->add("Set-Cookie" => + "ljuniq=$uniq:$now; " . + "expires=" . LJ::time_to_cookie($now + $DAY*60) . "; " . + ($dom ? "domain=$dom; " : "") . "path=/"); + } + } + } + + # only allow certain pages over SSL + if ($is_ssl) { + if ($uri =~ m!^/interface/!) { + # handled later + } elsif ($LJ::SSLDOCS && $uri !~ m!(\.\.|\%|\.\/)!) { + my $file = "$LJ::SSLDOCS/$uri"; + unless (-e $file) { + # no such file. send them to the main server if it's a GET. + return $r->method eq 'GET' ? redir($r, "$LJ::SITEROOT$uri$args_wq") : 404; + } + if (-d _) { $file .= "/index.bml"; } + $file =~ s!/{2,}!/!g; + $r->filename($file); + $LJ::IMGPREFIX = "/img"; + $LJ::STATPREFIX = "/stc"; + return OK; + } + return FORBIDDEN; + } else { + $LJ::IMGPREFIX = $LJ::IMGPREFIX_BAK; + $LJ::STATPREFIX = $LJ::STATPREFIX_BAK; + } + + # let foo.com still work, but redirect to www.foo.com + if ($LJ::DOMAIN_WEB && $r->method eq "GET" && + $host eq $LJ::DOMAIN && $LJ::DOMAIN_WEB ne $LJ::DOMAIN) + { + my $url = "$LJ::SITEROOT$uri"; + $url .= "?" . $args if $args; + return redir($r, $url); + } + + # check for sysbans on ip address + foreach my $ip (@req_hosts) { + if (LJ::sysban_check('ip', $ip) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + } + } + if (LJ::run_hook("forbid_request", $r) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + } + + # see if we should setup a minimal scheme based on the initial part of the + # user-agent string; FIXME: maybe this should do more than just look at the + # initial letters? + if (my $ua = $r->header_in('User-Agent')) { + if (($ua =~ /^([a-z]+)/i) && $LJ::MINIMAL_USERAGENT{$1}) { + $r->notes('use_minimal_scheme' => 1); + $r->notes('bml_use_scheme' => $LJ::MINIMAL_BML_SCHEME); + } + } + + # now we know that the request is going to succeed, so do some checking if they have a defined + # referer. clients and such don't, so ignore them. + my $referer = $r->header_in("Referer"); + if ($referer && $r->method eq 'POST' && !LJ::check_referer('', $referer)) { + $r->log_error("REFERER WARNING: POST to $uri from $referer"); + } + + my %GET = $r->args; + + # anti-squatter checking + if ($LJ::ANTI_SQUATTER && $r->method eq "GET") { + my $ref = $r->header_in("Referer"); + if ($ref && index($ref, $LJ::SITEROOT) != 0) { + # FIXME: this doesn't anti-squat user domains yet + if ($uri !~ m!^/404!) { + # So hacky! (see note below) + $LJ::SQUAT_URL = "http://$host$hostport$uri$args_wq"; + } else { + # then Apache's 404 handler takes over and we get here + # FIXME: why?? why doesn't it just work to return OK + # the first time with the handlers pushed? nothing + # else requires this chicanery! + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&anti_squatter); + } + return OK; + } + } + + my $bml_handler = sub { + my $filename = shift; + $r->handler("perl-script"); + $r->notes("bml_filename" => $filename); +# $r->push_handlers(PerlHandler => \&Apache::BML::handler); + return OK; + }; + + # is this the embed module host + my $embed_host = $host; + $embed_host = $r->header_in("X-Forwarded-Host") + if $r->header_in("X-Forwarded-Host"); + if ($LJ::EMBED_MODULE_DOMAIN && $embed_host =~ /$LJ::EMBED_MODULE_DOMAIN/) { + return $bml_handler->("$LJ::HOME/htdocs/tools/embedcontent.bml"); + } + + my $journal_view = sub { + my $opts = shift; + $opts ||= {}; + + my $orig_user = $opts->{'user'}; + $opts->{'user'} = LJ::canonical_username($opts->{'user'}); + + if ($opts->{'mode'} eq "info") { + return redir($r, "$LJ::SITEROOT/userinfo.bml?user=$opts->{'user'}"); + } + + %RQ = %$opts; + + # redirect communities to /community/ + my $u = LJ::load_user($opts->{'user'}); + if ($u && $u->{'journaltype'} eq "C" && + ($opts->{'vhost'} eq "" || $opts->{'vhost'} eq "tilde")) { + my $newurl = $uri; + $newurl =~ s!^/(users/|~)\Q$orig_user\E!!; + $newurl = "$LJ::SITEROOT/community/$opts->{'user'}$newurl$args_wq"; + return redir($r, $newurl); + } + + # redirect case errors in username + if ($orig_user ne lc($orig_user)) { + my $url = LJ::journal_base($opts->{'user'}, $opts->{'vhost'}) . + "/$opts->{'mode'}$opts->{'pathextra'}$args_wq"; + return redir($r, $url); + } + + if ($opts->{mode} eq "data" && $opts->{pathextra} =~ m!^/(\w+)(/.*)?!) { + if (my $handler = LJ::run_hook("data_handler:$1", $RQ{'user'}, $2)) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => $handler); + return OK; + } + } + + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&journal_content); + return OK; + }; + + my $determine_view = sub { + my ($user, $vhost, $uuri) = @_; + my $mode = undef; + my $pe; + + if ($uuri =~ m#^/(\d+)\.html$#) { + if ($GET{'mode'} eq "reply" || $GET{'replyto'}) { + $mode = "reply"; + } else { + $mode = "entry"; + } + } elsif ($uuri =~ m#^/(\d+)\.htm$#) { + return redir($r, "http://$host$hostport$uri" . "l"); + + } elsif ($uuri =~ m#^/(\d\d\d\d)(?:/(\d\d)(?:/(\d\d))?)?(/?)$#) { + my ($year, $mon, $day, $slash) = ($1, $2, $3, $4); + # Year 2038 fix: + if ($year < 1970 || $year > 2037) { #crash in some rare cases + return 404; + } + unless ($slash) { + return redir($r, "http://$host$hostport$uri/"); + } + + # the S1 ljviews code looks at $opts->{'pathextra'}, because + # that's how it used to do it, when the pathextra was /day[/yyyy/mm/dd] + $pe = $uuri; + + if (defined $day) { + $mode = "day"; + } elsif (defined $mon) { + $mode = "month"; + } else { + $mode = "calendar"; + } + + } elsif ($uuri =~ m! + /([a-z\_]+)? # optional / + (.*) # path extra: /FriendGroup, for example + !x && ($1 eq "" || defined $LJ::viewinfo{$1})) { + + ($mode, $pe) = ($1, $2); + $mode ||= "" unless length $pe; # if no pathextra, then imply 'lastn' + + # redirect old-style URLs to new versions: + if ($mode =~ /day|calendar/ && $pe =~ m!^/\d\d\d\d!) { + my $newuri = $uri; + $newuri =~ s!$mode/(\d\d\d\d)!$1!; + return redir($r, "http://$host$hostport$newuri"); + } elsif ($mode eq 'rss') { + # code 301: moved permanently, update your links. + return redir($r, LJ::journal_base($user) . "/data/rss$args_wq", 301); + } elsif ($mode eq 'pics' && $LJ::REDIRECT_ALLOWED{$LJ::FB_DOMAIN}) { + # redirect to a user's gallery + my $url = "$LJ::FB_SITEROOT/$user"; + return redir($r, $url); + } + } elsif (($vhost eq "users" || $vhost =~ /^other:/) && + $uuri eq "/robots.txt") { + $mode = "robots_txt"; + } + + return undef unless defined $mode; + return $journal_view->({'vhost' => $vhost, + 'mode' => $mode, + 'args' => $args, + 'pathextra' => $pe, + 'user' => $user }); + }; + + # flag if we hit a domain that was configured as a "normal" domain + # which shouldn't be inspected for its domain name. (for use with + # Akamai and other CDN networks...) + my $skip_domain_checks = 0; + + # user domains + if ($LJ::USER_VHOSTS && + $host =~ /^([\w\-]{1,15})\.\Q$LJ::USER_DOMAIN\E$/ && + $1 ne "www" && + + # 1xx: info, 2xx: success, 3xx: redirect, 4xx: client err, 5xx: server err + # let the main server handle any errors + $r->status < 400) + { + my $user = $1; + + # see if the "user" is really functional code + my $func = $LJ::SUBDOMAIN_FUNCTION{$user}; + + if ($func eq "normal") { + # site admin wants this domain to be ignored and treated as if it + # were "www", so set this flag so the custom "OTHER_VHOSTS" check + # below fails. + $skip_domain_checks = 1; + + } elsif ($uri =~ m!^/(?:talkscreen|delcomment)\.bml!) { + # these URLs need to always work for the javascript comment management code + # (JavaScript can't do cross-domain XMLHttpRequest calls) + $skip_domain_checks = 1; + + } elsif ($func) { + my $code = { + 'userpics' => \&userpic_trans, + 'files' => \&files_trans, + }; + return $code->{$func}->($r) if $code->{$func}; + return 404; # bogus ljconfig + } else { + my $view = $determine_view->($user, "users", $uri); + return $view if defined $view; + return 404; + } + } + + # custom used-specified domains + if ($LJ::OTHER_VHOSTS && !$skip_domain_checks && + $host ne $LJ::DOMAIN_WEB && + $host ne $LJ::DOMAIN && $host =~ /\./ && + $host =~ /[^\d\.]/) + { + my $dbr = LJ::get_db_reader(); + my $checkhost = lc($host); + $checkhost =~ s/^www\.//i; + $checkhost = $dbr->quote($checkhost); + # FIXME: memcache this? + my $user = $dbr->selectrow_array(qq{ + SELECT u.user FROM useridmap u, domains d WHERE + u.userid=d.userid AND d.domain=$checkhost + }); + return 404 unless $user; + + my $view = $determine_view->($user, "other:$host$hostport", $uri); + return $view if defined $view; + return 404; + } + + # userpic + return userpic_trans($r) if $uri =~ m!^/userpic/!; + + # comments + return comments_trans($r) if $uri =~ m!^/comments/!; + + # readable comments + return numreplies_trans($r) if $uri =~ m!^/numreplies/!; + + # front page journal + if ($LJ::FRONTPAGE_JOURNAL) { + my $view = $determine_view->($LJ::FRONTPAGE_JOURNAL, "front", $uri); + return $view if defined $view; + } + + # normal (non-domain) journal view + if (! $LJ::ONLY_USER_VHOSTS && + $uri =~ m! + ^/(users\/|community\/|\~) # users/community/tilde + ([^/]*) # potential username + (.*)? # rest + !x) + { + my ($part1, $user, $rest) = ($1, $2, $3); + + # get what the username should be + my $cuser = LJ::canonical_username($user); + return DECLINED unless length($cuser); + + my $srest = $rest || '/'; + + # redirect to canonical username and/or add slash if needed + return redir($r, "http://$host$hostport/$part1$cuser$srest$args_wq") + if $cuser ne $user or not $rest; + + my $vhost = { 'users/' => '', 'community/' => 'community', + '~' => 'tilde' }->{$part1}; + + my $view = $determine_view->($user, $vhost, $rest); + return $view if defined $view; + } + + # protocol support + if ($uri =~ m!^/(?:interface/(\w+))|cgi-bin/log\.cgi!) { + my $int = $1 || "flat"; + $r->handler("perl-script"); + if ($int eq "fotobilder") { + return 403 unless $LJ::FOTOBILDER_IP{$r->connection->remote_ip}; + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::Interface::FotoBilder::handler); + return OK; + } + if ($int =~ /^flat|xmlrpc|blogger|atom(?:api)?$/) { + $RQ{'interface'} = $int; + $RQ{'is_ssl'} = $is_ssl; + $r->push_handlers(PerlHandler => \&interface_content); + return OK; + } + if ($int eq "s2") { + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::Interface::S2::handler); + return OK; + } + return 404; + } + + # customview + if ($uri =~ m!^/customview\.cgi!) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&customview_content); + return OK; + } + + if ($uri =~ m!^/palimg/!) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::PalImg::handler); + return OK; + } + + # redirected resources + if ($REDIR{$uri}) { + my $new = $REDIR{$uri}; + if ($r->args) { + $new .= ($new =~ /\?/ ? "&" : "?"); + $new .= $r->args; + } + return redir($r, $new, HTTP_MOVED_PERMANENTLY); + } + + # confirm + if ($uri =~ m!^/confirm/(\w+\.\w+)!) { + return redir($r, "$LJ::SITEROOT/register.bml?$1"); + } + + # approve + if ($uri =~ m!^/approve/(\w+\.\w+)!) { + return redir($r, "$LJ::SITEROOT/approve.bml?$1"); + } + + return FORBIDDEN if $uri =~ m!^/userpics! || $uri =~ m!^/comments! || $uri =~ m!^/numreplies!; + return DECLINED; +} + +sub numreplies_trans { + my $r = shift; + + #readable comments url: /numreplies/ljr_todo/35616 + return NOT_FOUND unless $r->uri =~ m!^/(?:numreplies/)?(.*)/(\d+)$!; + my ($user, $ditemid) = ($1, $2); + + # Load the user object and make sure talk is viewable + my $u = LJ::load_user($user); + return NOT_FOUND unless $u && $u->{'statusvis'} !~ /[XS]/; + + my $itemid = $ditemid>>8; + my $row = LJ::get_log2_row($u, $itemid); + return NOT_FOUND unless $row; + + my $new = "$LJ::SITEROOT/comments/$itemid/$u->{userid}"; + return redir($r, $new, HTTP_MOVED_PERMANENTLY); +} + +sub comments_trans { + my $r = shift; + + return NOT_FOUND unless $r->uri =~ m!^/(?:comments/)?(\d+)/(\d+)$!; + my ($itemid, $userid) = ($1, $2); + + $RQ{'itemid'} = $itemid; + $RQ{'itemid-userid'} = $userid; + + $r->notes("codepath" => "img.comments"); + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&comments_content); + + return OK; +} + +sub comments_content { + my $r = shift; + + my $itemid = $RQ{'itemid'}; + my $userid = $RQ{'itemid-userid'}+0; + + my $lastmod; + my $mime = "image/png"; + my $size; + my $now = time(); + # nginx use memcache directly, so avoid calculation - 60s is OK. + my $expires = 60; + + my $send_headers = sub { + + $r->content_type($mime); + $r->header_out("Cache-Control", "max-age=$expires, must-revalidate, no-transform"); + $r->header_out("Last-Modified", LJ::time_to_http($lastmod)); + $r->header_out("Expires", LJ::time_to_http($now + $expires)); + $r->header_out("Content-length", $size+0); + $r->send_http_header(); + }; + + # Load the user object and pic and make sure the picture is viewable + my $u = LJ::load_userid($userid); + return NOT_FOUND unless $u && $u->{'statusvis'} !~ /[XS]/; + + my $row = LJ::get_log2_row($u, $itemid); + $lastmod = LJ::mysqldate_to_time($row->{'logtime'}, 0) if $row && $row->{'logtime'}; + + my $count = LJ::Talk::get_replycount($u, $itemid); + + my $dbr = LJ::get_db_reader(); + my ($font, $color, $ljr_es_lastmod) = $dbr->selectrow_array( + "SELECT font_name, font_color, UNIX_TIMESTAMP(update_time) FROM ljr_export_settings WHERE user=?", + undef, $u->{'user'}); + + $font = "gdLargeFont" unless $font; + $color = "blue" unless $color; + + if ($ljr_es_lastmod) { + $lastmod = $ljr_es_lastmod unless $lastmod; + } + $lastmod = $now - 3600 * 24 * 31 unless $lastmod; # month + + my $img = LJR::GD::generate_number($count, $font, $color, " "); + my $data = $img->png; + $size = length($data); + $send_headers->(); + LJ::MemCache::set($r->uri, $data); #used by nginx! (NB!) $size < $MEMCACHE_COMPRESS_THRESHOLD. cleared in replycount_do() + $r->print($data) unless $r->header_only; + return OK; +} + +sub userpic_trans +{ + my $r = shift; + return 404 unless $r->uri =~ m!^/(?:userpic/)?(\d+)/(\d+)$!; + my ($picid, $userid) = ($1, $2); + + $r->notes("codepath" => "img.userpic"); + + # we can safely do this without checking since we never re-use + # picture IDs and don't let the contents get modified + return HTTP_NOT_MODIFIED if $r->header_in('If-Modified-Since'); + + $RQ{'picid'} = $picid; + $RQ{'pic-userid'} = $userid; + + if ($USERPIC{'use_disk_cache'}) { + my @dirs_make; + my $file; + + if ($picid =~ /^\d*(\d\d)(\d\d\d)$/) { + push @dirs_make, ("$USERPIC{'cache_dir'}/$2", + "$USERPIC{'cache_dir'}/$2/$1"); + $file = "$USERPIC{'cache_dir'}/$2/$1/$picid-$userid"; + } else { + my $mod = sprintf("%03d", $picid % 1000); + push @dirs_make, "$USERPIC{'cache_dir'}/$mod"; + $file = "$USERPIC{'cache_dir'}/$mod/p$picid-$userid"; + } + + foreach (@dirs_make) { + next if -d $_; + mkdir $_, 0777; + } + + # set both, so we can compared later if they're the same, + # and thus know if directories were created (if not, + # apache will give us a pathinfo) + $RQ{'userpicfile'} = $file; + $r->filename($file); + } + + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&userpic_content); + return OK; +} + +sub userpic_content +{ + my $r = shift; + my $file = $r->filename; + + my $picid = $RQ{'picid'}; + my $userid = $RQ{'pic-userid'}+0; + + # will we try to use disk cache? + my $disk_cache = $USERPIC{'use_disk_cache'} && + $file eq $RQ{'userpicfile'}; + + my ($data, $lastmod); + my $need_cache; + + my $mime = "image/jpeg"; + my $set_mime = sub { + my $data = shift; + if ($data =~ /^GIF/) { $mime = "image/gif"; } + elsif ($data =~ /^\x89PNG/) { $mime = "image/png"; } + }; + my $size; + + my $send_headers = sub { + $r->content_type($mime); + $r->header_out("Content-length", $size+0); + $r->header_out("Cache-Control", "no-transform"); + $r->header_out("Last-Modified", LJ::time_to_http($lastmod)); + $r->send_http_header(); + }; + + # Load the user object and pic and make sure the picture is viewable + my $u = LJ::load_userid($userid); + return NOT_FOUND unless $u && $u->{'statusvis'} !~ /[XS]/; + + my %upics; + LJ::load_userpics(\%upics, [ $u, $picid ]); + my $pic = $upics{$picid} or return NOT_FOUND; + return NOT_FOUND if $pic->{'userid'} != $userid || $pic->{state} eq 'X'; + + # Read the mimetype from the pichash if dversion 7 + $mime = { 'G' => 'image/gif', + 'J' => 'image/jpeg', + 'P' => 'image/png', }->{$pic->{fmt}}; + + ### Handle reproxyable requests + + # For dversion 7+ and mogilefs userpics, follow this path + if ($pic->{location} eq 'M' ) { # 'M' for mogilefs + my $key = $u->mogfs_userpic_key( $picid ); + + if ( !$LJ::REPROXY_DISABLE{userpics} && + $r->header_in('X-Proxy-Capabilities') && + $r->header_in('X-Proxy-Capabilities') =~ m{\breproxy-file\b}i ) + { + my $memkey = [$picid, "mogp.up.$picid"]; + + my $zone = $r->header_in('X-MogileFS-Explicit-Zone') || undef; + $memkey->[1] .= ".$zone" if $zone; + + my $paths = LJ::MemCache::get($memkey); + unless ($paths) { + my @paths = LJ::mogclient()->get_paths( $key, { noverify => 1, zone => $zone }); + $paths = \@paths; + LJ::MemCache::add($memkey, $paths, 3600) if @paths; + } + + # reproxy url + if ($paths->[0] =~ m/^http:/) { + $r->header_out('X-REPROXY-URL', join(' ', @$paths)); + } + + # reproxy file + else { + $r->header_out('X-REPROXY-FILE', $paths->[0]); + } + + $send_headers->(); + } + + else { + my $data = LJ::mogclient()->get_file_data( $key ); + return NOT_FOUND unless $data; + $size = length $$data; + $send_headers->(); + $r->print( $$data ) unless $r->header_only; + } + + return OK; + } + + # dversion < 7 reproxy file path + if ( !$LJ::REPROXY_DISABLE{userpics} && + exists $LJ::PERLBAL_ROOT{userpics} && + $r->header_in('X-Proxy-Capabilities') && + $r->header_in('X-Proxy-Capabilities') =~ m{\breproxy-file\b}i ) + { + my ( + $root, + $fmt, + $path, + ); + + # Get the blobroot and load the pic hash + $root = $LJ::PERLBAL_ROOT{userpics}; + + # sometimes we don't want to reproxy userpics + unless ($LJ::USERPIC_REPROXY_DISABLE{$u->{clusterid}}) { + # Now ask the blob lib for the path to send to the reproxy + $fmt = ($u->{'dversion'} > 6) ? $MimeTypeMapd6{ $pic->{fmt} } : $MimeTypeMap{ $pic->{contenttype} }; + $path = LJ::Blob::get_rel_path( $root, $u, "userpic", $fmt, $picid ); + + $r->header_out( 'X-REPROXY-FILE', $path ); + $send_headers->(); + + return OK; + } + } + + # try to get it from disk if in disk-cache mode + if ($disk_cache) { + if (-s $r->finfo) { + $lastmod = (stat _)[9]; + $size = -s _; + my $fh = Apache::File->new($file); + my $magic; + read($fh, $magic, 4); + $set_mime->($magic); + $send_headers->(); + $r->print($magic); + $r->send_fd($fh); + $fh->close(); + return OK; + } else { + $need_cache = 1; + } + } + + # else, get it from db. + unless ($data) { + $lastmod = $pic->{'picdate'}; + + if ($LJ::USERPIC_BLOBSERVER) { + my $fmt = ($u->{'dversion'} > 6) ? $MimeTypeMapd6{ $pic->{fmt} } : $MimeTypeMap{ $pic->{contenttype} }; + $data = LJ::Blob::get($u, "userpic", $fmt, $picid); + } + + unless ($data) { + my $dbb = LJ::get_cluster_reader($u); + return SERVER_ERROR unless $dbb; + $data = $dbb->selectrow_array("SELECT imagedata FROM userpicblob2 WHERE ". + "userid=$pic->{'userid'} AND picid=$picid"); + } + } + + return NOT_FOUND unless $data; + + if ($need_cache) { + # make $realfile /userpic-userid, and $file /userpic + my $realfile = $file; + unless ($file =~ s/-\d+$//) { + $realfile .= "-$pic->{'userid'}"; + } + + # delete short file on Unix if it exists + unlink $file if $USERPIC{'symlink'} && -f $file; + + # write real file. + open (F, ">$realfile"); print F $data; close F; + + # make symlink, or duplicate file (if on Windows) + my $symtarget = $realfile; $symtarget =~ s!.+/!!; + unless (eval { symlink($symtarget, $file) }) { + open (F, ">$file"); print F $data; close F; + } + } + + $set_mime->($data); + $size = length($data); + $send_headers->(); + $r->print($data) unless $r->header_only; + return OK; +} + +sub files_trans +{ + my $r = shift; + return 404 unless $r->uri =~ m!^/(\w{1,15})/(\w+)(/\S+)!; + my ($user, $domain, $rest) = ($1, $2, $3); + + if (my $handler = LJ::run_hook("files_handler:$domain", $user, $rest)) { + $r->notes("codepath" => "files.$domain"); + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => $handler); + return OK; + } + return 404; +} + +sub journal_content +{ + my $r = shift; + my $uri = $r->uri; + + my %GET = $r->args; + + if ($RQ{'mode'} eq "robots_txt") + { + my $u = LJ::load_user($RQ{'user'}); + LJ::load_user_props($u, "opt_blockrobots"); + $r->content_type("text/plain"); + $r->send_http_header(); + $r->print("User-Agent: *\n"); + if ($u->{'opt_blockrobots'}) { + $r->print("Disallow: /\n"); + } + return OK; + } + + # handle HTTP digest authentication + if ($GET{'auth'} eq 'digest' || + $r->header_in("Authorization") =~ /^Digest/) { + my $res = LJ::auth_digest($r); + unless ($res) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Digest authentication failed."); + return OK; + } + } + + my $criterr = 0; + my $remote = LJ::get_remote({ criterr => \$criterr }); + + # check for faked cookies here, since this is pretty central. + if ($criterr) { + $r->status_line("500 Invalid Cookies"); # client error, in fact + $r->content_type("text/html"); + # reset all cookies + foreach my $dom (@LJ::COOKIE_DOMAIN_RESET) { + my $cookiestr = 'ljsession='; + $cookiestr .= '; expires=' . LJ::time_to_cookie(1); + $cookiestr .= $dom ? "; domain=$dom" : ''; + $cookiestr .= '; path=/; HttpOnly'; + Apache->request->err_headers_out->add('Set-Cookie' => $cookiestr); + } + + $r->send_http_header(); + $r->print("Invalid cookies. Try logging out and then logging back in.\n"); + $r->print("\n") for (0..100); + return OK; + } + + # LJ::make_journal() will set this flag if the user's + # style system is unable to handle the requested + # view (S1 can't do EntryPage or MonthPage), in which + # case it's our job to invoke the legacy BML page. + my $handle_with_bml = 0; + + my %headers = (); + my $opts = { + 'r' => $r, + 'headers' => \%headers, + 'args' => $RQ{'args'}, + 'getargs' => \%GET, + 'vhost' => $RQ{'vhost'}, + 'pathextra' => $RQ{'pathextra'}, + 'handle_with_bml_ref' => \$handle_with_bml, + }; + + my $user = $RQ{'user'}; + my $html = LJ::make_journal($user, $RQ{'mode'}, $remote, $opts); + + return HTTP_NOT_MODIFIED if $opts->{'notmodified'}; + return redir($r, $opts->{'redir'}) if $opts->{'redir'}; + return $opts->{'handler_return'} if defined $opts->{'handler_return'}; + + # if LJ::make_journal() indicated it can't handle the request: + if ($handle_with_bml) { + my $args = $r->args; + my $args_wq = $args ? "?$args" : ""; + + # can't show BML on user domains... redirect them + if ($RQ{'vhost'} eq "users" && ($RQ{'mode'} eq "entry" || + $RQ{'mode'} eq "reply" || + $RQ{'mode'} eq "month")) + { + my $u = LJ::load_user($RQ{'user'}); + my $base = "$LJ::SITEROOT/users/$RQ{'user'}"; + $base = "$LJ::SITEROOT/community/$RQ{'user'}" if $u && $u->{'journaltype'} eq "C"; + return redir($r, "$base$uri$args_wq"); + } + + if ($RQ{'mode'} eq "entry" || $RQ{'mode'} eq "reply") { + my $filename = $RQ{'mode'} eq "entry" ? + "$LJ::HOME/htdocs/talkread.bml" : + "$LJ::HOME/htdocs/talkpost.bml"; + $r->notes("_journal" => $RQ{'user'}); + $r->notes("bml_filename" => $filename); + return Apache::BML::handler($r); + } + + if ($RQ{'mode'} eq "month") { + my $filename = "$LJ::HOME/htdocs/view/index.bml"; + $r->notes("_journal" => $RQ{'user'}); + $r->notes("bml_filename" => $filename); + return Apache::BML::handler($r); + } + } + + my $status = $opts->{'status'} || "200 OK"; + $opts->{'contenttype'} ||= $opts->{'contenttype'} = "text/html"; + if ($opts->{'contenttype'} =~ m!^text/! && + $LJ::UNICODE && $opts->{'contenttype'} !~ /charset=/) { + $opts->{'contenttype'} .= "; charset=utf-8"; + } + + # Set to 1 if the code should generate junk to help IE + # display a more meaningful error message. + my $generate_iejunk = 0; + + if ($opts->{'badargs'}) + { + # No special information to give to the user, so just let + # Apache handle the 404 + return 404; + } + elsif ($opts->{'baduser'}) + { + $status = "404 Unknown User"; + $html = "

    Unknown User

    There is no user $user at $LJ::SITENAME.

    "; + $generate_iejunk = 1; + } + elsif ($opts->{'badfriendgroup'}) + { + # give a real 404 to the journal owner + if ($remote && $remote->{'user'} eq $user) { + $status = "404 Friend group does not exist"; + $html = "

    Not Found

    " . + "

    The friend group you are trying to access does not exist.

    "; + + # otherwise be vague with a 403 + } else { + # send back a 403 and don't reveal if the group existed or not + $status = "403 Friend group does not exist, or is not public"; + $html = "

    Denied

    " . + "

    Sorry, the friend group you are trying to access does not exist " . + "or is not public.

    \n"; + + $html .= "

    You're not logged in. If you're the owner of this journal, " . + "log in and try again.

    \n" + unless $remote; + } + + $generate_iejunk = 1; + + } elsif ($opts->{'suspendeduser'}) { + $status = "403 User suspended"; + $html = "

    Suspended User

    " . + "

    The content at this URL is from a suspended user.

    "; + + $generate_iejunk = 1; + } + + unless ($html) { + $status = "400 Bad Template"; + $html = "

    Error

    User $user has messed up their journal template definition.

    "; + $generate_iejunk = 1; + } + + $r->status_line($status); + foreach my $hname (keys %headers) { + if (ref($headers{$hname}) && ref($headers{$hname}) eq "ARRAY") { + foreach (@{$headers{$hname}}) { + $r->header_out($hname, $_); + } + } else { + $r->header_out($hname, $headers{$hname}); + } + } + + $r->content_type($opts->{'contenttype'}); + $r->header_out("Cache-Control", "private, proxy-revalidate") unless $opts->{'cachecontrol'}; + $r->header_out("Cache-Control", $opts->{'cachecontrol'}) if $opts->{'cachecontrol'}; + + $html .= ("\n" x 100) if $generate_iejunk; + + unless ($generate_iejunk) { + my $etag; + $etag = Digest::MD5::md5_hex(pack('C*', unpack('C*', $html))); + $etag = '"' . $etag . '"'; + $r->header_out("ETag", $etag); + } + + my $length = length($html); + $r->header_out("Content-length", $length); + $r->send_http_header(); + $r->print($html) unless $r->header_only; + + return OK; +} + +sub customview_content +{ + my $r = shift; + + my %FORM = $r->args; + + my $charset = "utf-8"; + + if ($LJ::UNICODE && $FORM{'charset'}) { + $charset = $FORM{'charset'}; + if ($charset ne "utf-8" && ! Unicode::MapUTF8::utf8_supported_charset($charset)) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error: requested charset not supported."); + return OK; + } + } + + my $ctype = "text/html"; + if ($FORM{'type'} eq "xml") { + $ctype = "text/xml"; + } + + if ($LJ::UNICODE) { + $ctype .= "; charset=$charset"; + } + + $r->content_type($ctype); + + my $user = $FORM{'username'} || $FORM{'user'}; + my $styleid = $FORM{'styleid'} + 0; + my $nooverride = $FORM{'nooverride'} ? 1 : 0; + + my $remote; + if ($FORM{'checkcookies'}) { + $remote = LJ::get_remote(); + } + + my $opts = { "nocache" => $FORM{'nocache'}, + "vhost" => "customview", + "nooverride" => $nooverride, + "styleid" => $styleid, + "saycharset" => $charset, + "args" => scalar $r->args, + "getargs" => \%FORM, + "r" => $r, + }; + + my $data = (LJ::make_journal($user, "", $remote, $opts) + || "[$LJ::SITENAME: Bad username, styleid, or style definition]"); + + return HTTP_NOT_MODIFIED if $opts->{'notmodified'}; + + if ($FORM{'enc'} eq "js") { + $data =~ s/\\/\\\\/g; + $data =~ s/\"/\\\"/g; + $data =~ s/\n/\\n/g; + $data =~ s/\r//g; + $data = "document.write(\"$data\")"; + } + + if ($LJ::UNICODE && $charset ne 'utf-8') { + $data = Unicode::MapUTF8::from_utf8({-string=>$data, -charset=>$charset}); + } + + $r->header_out("Cache-Control", "must-revalidate"); + $r->header_out("Content-Length", length($data)); + $r->send_http_header(); + $r->print($data) unless $r->header_only; + return OK; +} + +sub interface_content +{ + my $r = shift; + my $args = $r->args; + + if ($RQ{'interface'} eq "xmlrpc") { + return 404 unless $LJ::OPTMOD_XMLRPC; + my $server = XMLRPC::Transport::HTTP::Apache + -> on_action(sub { die "Access denied\n" if $_[2] =~ /:|\'/ }) + -> dispatch_to('LJ::XMLRPC') + -> handle($r); + return OK; + } + + if ($RQ{'interface'} eq "blogger") { + return 404 unless $LJ::OPTMOD_XMLRPC; + my $pkg = "Apache::LiveJournal::Interface::Blogger"; + my $server = XMLRPC::Transport::HTTP::Apache + -> on_action(sub { die "Access denied\n" if $_[2] =~ /:|\'/ }) + -> dispatch_with({ 'blogger' => $pkg }) + -> dispatch_to($pkg) + -> handle($r); + return OK; + } + + if ($RQ{'interface'} =~ /atom(?:api)?/) { + # the interface package will set up all headers and + # print everything + Apache::LiveJournal::Interface::AtomAPI::handle($r); + return OK; + } + + if ($RQ{'interface'} ne "flat") { + $r->content_type("text/plain"); + $r->send_http_header; + $r->print("Unknown interface."); + return OK; + } + + $r->content_type("text/plain"); + + my %out = (); + my %FORM = (); + my $content; + $r->read($content, $r->header_in("Content-Length")); + LJ::decode_url_string($content, \%FORM); + + # the protocol needs the remote IP in just one place, where tracking is done. + $ENV{'_REMOTE_IP'} = $r->connection()->remote_ip(); + LJ::do_request(\%FORM, \%out); + + if ($FORM{'responseenc'} eq "urlenc") { + $r->send_http_header; + foreach (sort keys %out) { + $r->print(LJ::eurl($_) . "=" . LJ::eurl($out{$_}) . "&"); + } + return OK; + } + + my $length = 0; + foreach (sort keys %out) { + $length += length($_)+1; + $length += length($out{$_})+1; + } + + $r->header_out("Content-length", $length); + $r->send_http_header; + foreach (sort keys %out) { + my $key = $_; + my $val = $out{$_}; + $key =~ y/\r\n//d; + $val =~ y/\r\n//d; + $r->print($key, "\n", $val, "\n"); + if ($key ne $_ || $val ne $out{$_}) { + print STDERR "Stripped spurious newline in $FORM{mode} protocol request for $FORM{user}: $_ => $out{$_}\n"; + } + } + + return OK; +} + +sub db_logger +{ + my $r = shift; + my $rl = $r->last; + + $r->pnotes('did_lj_logging' => 1); + + my $uri = $r->uri; + my $ctype = $rl->content_type; + + return if $ctype =~ m!^image/! and $LJ::DONT_LOG_IMAGES; + return if $uri =~ m!^/(img|userpic)/! and $LJ::DONT_LOG_IMAGES; + return if $uri =~ m!^/(comments)/! and $LJ::DONT_LOG_IMAGES; + + my $dbl = LJ::get_dbh("logs"); + my @dinsertd_socks; + + my $now = time; + my @now = localtime($now); + + foreach my $hostport (@LJ::DINSERTD_HOSTS) { + next if $LJ::CACHE_DINSERTD_DEAD{$hostport} > $now - 15; + + my $sock = + $LJ::CACHE_DINSERTD_SOCK{$hostport} ||= + IO::Socket::INET->new(PeerAddr => $hostport, + Proto => 'tcp', + Timeout => 1, + ); + + if ($sock) { + delete $LJ::CACHE_DINSERTD_DEAD{$hostport}; + push @dinsertd_socks, [ $hostport, $sock ]; + } else { + delete $LJ::CACHE_DINSERTD_SOCK{$hostport}; + $LJ::CACHE_DINSERTD_DEAD{$hostport} = $now; + } + } + + # why go on if we have nowhere to log to? + return unless $dbl || @dinsertd_socks; + + $ctype =~ s/;.*//; # strip charset + + # Send out DBI profiling information + if ( $LJ::DB_LOG_HOST && $LJ::HAVE_DBI_PROFILE ) { + my ( $host, $dbh ); + + while ( ($host,$dbh) = each %LJ::DB_REPORT_HANDLES ) { + $host =~ s{^(.*?);.*}{$1}; + + # For testing: append a random character to simulate different + # connections. + if ( $LJ::IS_DEV_SERVER ) { + $host .= "_" . substr( "abcdefghijklmnopqrstuvwxyz", int rand(26), 1 ); + } + + # From DBI::Profile: + # Profile data is stored at the `leaves' of the tree as references + # to an array of numeric values. For example: + # [ + # 106, # count + # 0.0312958955764771, # total duration + # 0.000490069389343262, # first duration + # 0.000176072120666504, # shortest duration + # 0.00140702724456787, # longest duration + # 1023115819.83019, # time of first event + # 1023115819.86576, # time of last event + # ] + + # The leaves are stored as values in the hash keyed by statement + # because LJ::get_dbirole_dbh() sets the profile to + # "2/DBI::Profile". The 2 part is the DBI::Profile magic number + # which means split the times by statement. + my $data = $dbh->{Profile}{Data}; + + # Make little arrayrefs out of the statement and longest + # running-time for this handle so they can be sorted. Then sort them + # by running-time so the longest-running one can be send to the + # stats collector. + my @times = + sort { $a->[0] <=> $b->[0] } + map {[ $data->{$_}[4], $_ ]} keys %$data; + + # ( host, class, time, notes ) + LJ::blocking_report( $host, 'db', @{$times[0]} ); + } + } + + my $table = sprintf("access%04d%02d%02d%02d", $now[5]+1900, + $now[4]+1, $now[3], $now[2]); + + unless ($LJ::CACHED_LOG_CREATE{"$table"}++) { + my $sql = "(". + "whn TIMESTAMP(14) NOT NULL,". + "INDEX(whn),". + "server VARCHAR(30),". + "addr VARCHAR(15) NOT NULL,". + "ljuser VARCHAR(15),". + "journalid INT UNSIGNED,". # userid of what's being looked at + "codepath VARCHAR(80),". # protocol.getevents / s[12].friends / bml.update / bml.friends.index + "anonsess INT UNSIGNED,". + "langpref VARCHAR(5),". + "uniq VARCHAR(15),". + "method VARCHAR(10) NOT NULL,". + "uri VARCHAR(255) NOT NULL,". + "args VARCHAR(255),". + "status SMALLINT UNSIGNED NOT NULL,". + "ctype VARCHAR(30),". + "bytes MEDIUMINT UNSIGNED NOT NULL,". + "browser VARCHAR(100),". + "clientver VARCHAR(100),". + "secs TINYINT UNSIGNED,". + "ref VARCHAR(200),". + "pid SMALLINT UNSIGNED,". + "cpu_user FLOAT UNSIGNED,". + "cpu_sys FLOAT UNSIGNED,". + "cpu_total FLOAT UNSIGNED,". + "mem_vsize INT,". + "mem_share INT,". + "mem_rss INT,". + "mem_unshared INT) DELAY_KEY_WRITE = 1"; + + if ($dbl) { + $dbl->do("CREATE TABLE IF NOT EXISTS $table $sql"); + $r->log_error("error creating log table ($table), perhaps due to old MySQL not supporting delayed key writes? Error is: " . + $dbl->errstr) if $dbl->err; + } + + foreach my $rec (@dinsertd_socks) { + my $sock = $rec->[1]; + my $url = LJ::eurl("CREATE TABLE IF NOT EXISTS [tablename] $sql"); + print $sock "SET_NOTE lj_create_table $url\r\n"; + my $res = <$sock>; + } + } + + my $var = { + 'whn' => sprintf("%04d%02d%02d%02d%02d%02d", $now[5]+1900, $now[4]+1, @now[3, 2, 1, 0]), + 'server' => $LJ::SERVER_NAME, + 'addr' => $r->connection->remote_ip, + 'ljuser' => $rl->notes('ljuser'), + 'journalid' => $rl->notes('journalid'), + 'codepath' => $rl->notes('codepath'), + 'anonsess' => $rl->notes('anonsess'), + 'langpref' => $rl->notes('langpref'), + 'clientver' => $rl->notes('clientver'), + 'uniq' => $r->notes('uniq'), + 'method' => $r->method, + 'uri' => $uri, + 'args' => scalar $r->args, + 'status' => $rl->status, + 'ctype' => $ctype, + 'bytes' => $rl->bytes_sent, + 'browser' => $r->header_in("User-Agent"), + 'secs' => $now - $r->request_time(), + 'ref' => $r->header_in("Referer"), + }; + + # If the configuration says to log statistics and GTop is available, then + # add those data to the log + # The GTop object is only created once per child: + # Benchmark: timing 10000 iterations of Cached GTop, New Every Time... + # Cached GTop: 2.06161 wallclock secs ( 1.06 usr + 0.97 sys = 2.03 CPU) @ 4926.11/s (n=10000) + # New Every Time: 2.17439 wallclock secs ( 1.18 usr + 0.94 sys = 2.12 CPU) @ 4716.98/s (n=10000) + STATS: { + if ( $LJ::LOG_GTOP && $LJ::HAVE_GTOP ) { + $GTop ||= new GTop or last STATS; + + my $startcpu = $r->pnotes( 'gtop_cpu' ) or last STATS; + my $endcpu = $GTop->cpu or last STATS; + my $startmem = $r->pnotes( 'gtop_mem' ) or last STATS; + my $endmem = $GTop->proc_mem( $$ ) or last STATS; + my $cpufreq = $endcpu->frequency or last STATS; + + # Map the GTop values into the corresponding fields in a slice + @$var{qw{pid cpu_user cpu_sys cpu_total mem_vsize mem_share mem_rss mem_unshared}} = ( + $$, + ($endcpu->user - $startcpu->user) / $cpufreq, + ($endcpu->sys - $startcpu->sys) / $cpufreq, + ($endcpu->total - $startcpu->total) / $cpufreq, + $endmem->vsize - $startmem->vsize, + $endmem->share - $startmem->share, + $endmem->rss - $startmem->rss, + $endmem->size - $endmem->share, + ); + } + } + + if ($dbl) { + my $delayed = $LJ::IMMEDIATE_LOGGING ? "" : "DELAYED"; + $dbl->do("INSERT $delayed INTO $table (" . join(',', keys %$var) . ") ". + "VALUES (" . join(',', map { $dbl->quote($var->{$_}) } keys %$var) . ")"); + + $dbl->disconnect if $LJ::DISCONNECT_DB_LOG; + } + + if (@dinsertd_socks) { + $var->{_table} = $table; + my $string = "INSERT " . Storable::nfreeze($var) . "\r\n"; + my $len = "\x01" . substr(pack("N", length($string) - 2), 1, 3); + $string = $len . $string; + + foreach my $rec (@dinsertd_socks) { + my $sock = $rec->[1]; + print $sock $string; + my $rin; + my $res; + vec($rin, fileno($sock), 1) = 1; + $res = <$sock> if select($rin, undef, undef, 0.3); + delete $LJ::CACHE_DINSERTD_SOCK{$rec->[0]} unless $res =~ /^OK\b/; + } + } + + + # Now clear the profiling data for each handle we're profiling at the last + # possible second to avoid the next request's data being skewed by + # requests that happen above. + if ( $LJ::DB_LOG_HOST && $LJ::HAVE_DBI_PROFILE ) { + for my $dbh ( values %LJ::DB_REPORT_HANDLES ) { + # DBI::Profile-recommended way of resetting profile data + $dbh->{Profile}{Data} = undef; + } + %LJ::DB_REPORT_HANDLES = (); + } +} + + +sub anti_squatter +{ + my $r = shift; + $r->push_handlers(PerlHandler => sub { + my $r = shift; + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Dev Server Warning", + "", + "

    Warning

    This server is for development and testing only. ", + "Accounts are subject to frequent deletion. Don't use this machine for anything important.

    ", + "
    ", + LJ::html_hidden("dest", "$LJ::SQUAT_URL"), + LJ::html_submit(undef, "Acknowledged"), + "
    "); + return OK; + }); + +} + +package LJ::Protocol; + +sub xmlrpc_method { + my $method = shift; + shift; # get rid of package name that dispatcher includes. + my $req = shift; + + if (@_) { + # don't allow extra arguments + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message(202)) + ->faultcode(202); + } + my $error = 0; + if (ref $req eq "HASH") { + foreach my $key ('subject', 'event') { + # get rid of the UTF8 flag in scalars + $req->{$key} = pack('C*', unpack('C*', $req->{$key})) + if $req->{$key}; + } + } + my $res = LJ::Protocol::do_request($method, $req, \$error); + if ($error) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($error)) + ->faultcode(substr($error, 0, 3)); + } + return $res; +} + +package LJ::XMLRPC; + +use vars qw($AUTOLOAD); + +sub AUTOLOAD { + my $method = $AUTOLOAD; + $method =~ s/^.*:://; + LJ::Protocol::xmlrpc_method($method, @_); +} + +1; diff --git a/local/cgi-bin/CSS/Cleaner.pm b/local/cgi-bin/CSS/Cleaner.pm new file mode 100644 index 0000000..9e2cd58 --- /dev/null +++ b/local/cgi-bin/CSS/Cleaner.pm @@ -0,0 +1,152 @@ +# +# Note: this is a very early version of a CSS cleaner. The plan is to eventually +# make it a white-listing CSS cleaner (deny by default) with a nice +# interface where you can build policy about what's allowed, like +# HTML::Sanitize/::Scrub/etc, but for now this is almost a null cleaner, +# just parsing and reserializing the CSS, removing two trivial ways to +# inject javascript. +# +# The plan now is to integrate this interface into LiveJournal, then improve +# this module over time. +# +# Note2: we tried 4 different CSS parsers for this module to use, and all 4 sucked. +# so for now this module sucks, until we can find a suitable parser. for the +# record, CSS::Tiny, CSS, and CSS::SAC all didn't work. and csstidy wasn't +# incredibly hot either. CSS.pm's grammar was buggy, and CSS::SAC had the +# best interface (SAC) but terrible parsing of selectors. we'll probably +# have to write our own, based on the Mozilla CSS parsing code. + + +package CSS::Cleaner; +use strict; +use vars qw($VERSION); +$VERSION = '0.01'; + +sub new { + my $class = shift; + my %opts = @_; + + my $self = bless {}, $class; + + if (defined( $opts{rule_handler} )) { + my $rule_handler = $opts{rule_handler}; + die "rule_handler needs to be a coderef if supplied" unless ref( $rule_handler ) eq 'CODE'; + $self->{rule_handler} = $rule_handler; + } + + if (defined( $opts{pre_hook} )) { + my $pre_hook = $opts{pre_hook}; + die "pre_hook needs to be a coderef if supplied" unless ref( $pre_hook ) eq 'CODE'; + $self->{pre_hook} = $pre_hook; + } + + return $self; +} + +# cleans CSS +sub clean { + my ($self, $target) = @_; + $self->_stupid_clean(\$target); + return $target; +} + +# cleans CSS properties, as if it were in a style="" attribute +sub clean_property { + my ($self, $target) = @_; + $self->_stupid_clean(\$target); + return $target; +} + +# this is so stupid. see notes at top. +# returns 1 if it was okay, 0 if possibly malicious +sub _stupid_clean { + my ($self, $ref) = @_; + + my $reduced = $$ref; + if (defined( $self->{pre_hook} )) { + $self->{pre_hook}->( \$reduced ); + } + + $reduced =~ s/&\#(\d+);?/chr($1)/eg; + $reduced =~ s/&\#x(\w+);?/chr(hex($1))/eg; + + if ($reduced =~ /[\x00-\x08\x0B\x0C\x0E-\x1F]/) { + $$ref = "/* suspect CSS: low bytes */"; + return; + } + + if ($reduced =~ /[\x7f-\xff]/) { + $$ref = "/* suspect CSS: high bytes */"; + return; + } + + # returns 1 if something bad was found + my $check_for_bad = sub { + if ($reduced =~ m!<\w!) { + $$ref = "/* suspect CSS: start HTML tag? */"; + return 1; + } + + my $with_white = $reduced; + $reduced =~ s/[\s\x0b]+//g; + + if ($reduced =~ m!\\[a-f0-9]!i) { + $$ref = "/* suspect CSS: backslash hex */"; + return; + } + + $reduced =~ s/\\//g; + + if ($reduced =~ /\@(import|charset)([\s\x0A\x0D]*[^\x0A\x0D]*)/i) { + my $what = $1; + my $value = $2; + if (defined( $self->{rule_handler} )) { + return $self->{rule_handler}->( $ref, $what, $value ); + } else { + $$ref = "/* suspect CSS: $what rule */"; + return; + } + } + + if ($reduced =~ /&\#/) { + $$ref = "/* suspect CSS: found irregular &# */"; + return; + } + + if ($reduced =~ m!(\$reduced); + + # restore whitespace + $reduced = $with_white; + $reduced =~ s!/\*.*?\*/!!sg; + $reduced =~ s!\<\!--.*?--\>!!sg; + $reduced =~ s/[\s\x0b]+//g; + $reduced =~ s/\\//g; + return 1 if $check_phrases->(\$reduced); + + return 0; + }; + + # check for bad stuff before/after removing comment lines + return 0 if $check_for_bad->(); + $reduced =~ s!//.*!!g; + return 0 if $check_for_bad->(); + return 1; +} + +1; diff --git a/local/cgi-bin/Cache/Memcached.pm b/local/cgi-bin/Cache/Memcached.pm new file mode 100755 index 0000000..018c2d9 --- /dev/null +++ b/local/cgi-bin/Cache/Memcached.pm @@ -0,0 +1,1164 @@ +# $Id: Memcached.pm,v 1.1.1.1 2005/07/29 01:03:35 nit Exp $ +# +# Copyright (c) 2003, 2004 Brad Fitzpatrick +# +# See COPYRIGHT section in pod text below for usage and distribution rights. +# + +package Cache::Memcached; + +use strict; +no strict 'refs'; +use Storable (); +use Socket qw( MSG_NOSIGNAL PF_INET IPPROTO_TCP SOCK_STREAM ); +use IO::Handle (); +use Time::HiRes (); +use String::CRC32; +use Errno qw( EINPROGRESS EWOULDBLOCK EISCONN ); + +use fields qw{ + debug no_rehash stats compress_threshold compress_enable stat_callback + readonly select_timeout namespace namespace_len servers active buckets + pref_ip + bucketcount _single_sock _stime +}; + +# flag definitions +use constant F_STORABLE => 1; +use constant F_COMPRESS => 2; + +# size savings required before saving compressed value +use constant COMPRESS_SAVINGS => 0.20; # percent + +use vars qw($VERSION $HAVE_ZLIB $FLAG_NOSIGNAL); +$VERSION = "1.14"; + +BEGIN { + $HAVE_ZLIB = eval "use Compress::Zlib (); 1;"; +} + +$FLAG_NOSIGNAL = 0; +eval { $FLAG_NOSIGNAL = MSG_NOSIGNAL; }; + +my %host_dead; # host -> unixtime marked dead until +my %cache_sock; # host -> socket + +my $PROTO_TCP; + +our $SOCK_TIMEOUT = 2.6; # default timeout in seconds + +sub new { + my Cache::Memcached $self = shift; + $self = fields::new( $self ) unless ref $self; + + my ($args) = @_; + + $self->set_servers($args->{'servers'}); + $self->{'debug'} = $args->{'debug'} || 0; + $self->{'no_rehash'} = $args->{'no_rehash'}; + $self->{'stats'} = {}; + $self->{'pref_ip'} = $args->{'pref_ip'} || {}; + $self->{'compress_threshold'} = $args->{'compress_threshold'}; + $self->{'compress_enable'} = 1; + $self->{'stat_callback'} = $args->{'stat_callback'} || undef; + $self->{'readonly'} = $args->{'readonly'}; + + # TODO: undocumented + $self->{'select_timeout'} = $args->{'select_timeout'} || 1.0; + $self->{namespace} = $args->{namespace} || ''; + $self->{namespace_len} = length $self->{namespace}; + + return $self; +} + +sub set_pref_ip { + my Cache::Memcached $self = shift; + $self->{'pref_ip'} = shift; +} + +sub set_servers { + my Cache::Memcached $self = shift; + my ($list) = @_; + $self->{'servers'} = $list || []; + $self->{'active'} = scalar @{$self->{'servers'}}; + $self->{'buckets'} = undef; + $self->{'bucketcount'} = 0; + + $self->{'_single_sock'} = undef; + if (@{$self->{'servers'}} == 1) { + $self->{'_single_sock'} = $self->{'servers'}[0]; + } + + return $self; +} + +sub set_debug { + my Cache::Memcached $self = shift; + my ($dbg) = @_; + $self->{'debug'} = $dbg; +} + +sub set_readonly { + my Cache::Memcached $self = shift; + my ($ro) = @_; + $self->{'readonly'} = $ro; +} + +sub set_norehash { + my Cache::Memcached $self = shift; + my ($val) = @_; + $self->{'no_rehash'} = $val; +} + +sub set_compress_threshold { + my Cache::Memcached $self = shift; + my ($thresh) = @_; + $self->{'compress_threshold'} = $thresh; +} + +sub enable_compress { + my Cache::Memcached $self = shift; + my ($enable) = @_; + $self->{'compress_enable'} = $enable; +} + +sub forget_dead_hosts { + %host_dead = (); +} + +sub set_stat_callback { + my Cache::Memcached $self = shift; + my ($stat_callback) = @_; + $self->{'stat_callback'} = $stat_callback; +} + +sub _dead_sock { + my ($sock, $ret, $dead_for) = @_; + if ($sock =~ /^Sock_(.+?):(\d+)$/) { + my $now = time(); + my ($ip, $port) = ($1, $2); + my $host = "$ip:$port"; + $host_dead{$host} = $now + $dead_for + if $dead_for; + delete $cache_sock{$host}; + } + return $ret; # 0 or undef, probably, depending on what caller wants +} + +sub _close_sock { + my ($sock) = @_; + if ($sock =~ /^Sock_(.+?):(\d+)$/) { + my ($ip, $port) = ($1, $2); + my $host = "$ip:$port"; + close $sock; + delete $cache_sock{$host}; + } +} + +sub _connect_sock { # sock, sin, timeout + my ($sock, $sin, $timeout) = @_; + $timeout ||= 0.25; + + # make the socket non-blocking from now on, + # except if someone wants 0 timeout, meaning + # a blocking connect, but even then turn it + # non-blocking at the end of this function + + if ($timeout) { + IO::Handle::blocking($sock, 0); + } else { + IO::Handle::blocking($sock, 1); + } + + my $ret = connect($sock, $sin); + + if (!$ret && $timeout && $!==EINPROGRESS) { + + my $win=''; + vec($win, fileno($sock), 1) = 1; + + if (select(undef, $win, undef, $timeout) > 0) { + $ret = connect($sock, $sin); + # EISCONN means connected & won't re-connect, so success + $ret = 1 if !$ret && $!==EISCONN; + } + } + + unless ($timeout) { # socket was temporarily blocking, now revert + IO::Handle::blocking($sock, 0); + } + + # from here on, we use non-blocking (async) IO for the duration + # of the socket's life + + return $ret; +} + +sub sock_to_host { # (host) + my Cache::Memcached $self = ref $_[0] ? shift : undef; + my $host = $_[0]; + return $cache_sock{$host} if $cache_sock{$host}; + + my $now = time(); + my ($ip, $port) = $host =~ /(.*):(\d+)/; + return undef if + $host_dead{$host} && $host_dead{$host} > $now; + my $sock = "Sock_$host"; + + my $connected = 0; + my $sin; + my $proto = $PROTO_TCP ||= getprotobyname('tcp'); + + # if a preferred IP is known, try that first. + if ($self && $self->{pref_ip}{$ip}) { + socket($sock, PF_INET, SOCK_STREAM, $proto); + my $prefip = $self->{pref_ip}{$ip}; + $sin = Socket::sockaddr_in($port,Socket::inet_aton($prefip)); + if (_connect_sock($sock,$sin,0.1)) { + $connected = 1; + } else { + close $sock; + } + } + + # normal path, or fallback path if preferred IP failed + unless ($connected) { + socket($sock, PF_INET, SOCK_STREAM, $proto); + $sin = Socket::sockaddr_in($port,Socket::inet_aton($ip)); + unless (_connect_sock($sock,$sin)) { + return _dead_sock($sock, undef, 20 + int(rand(10))); + } + } + + # make the new socket not buffer writes. + my $old = select($sock); + $| = 1; + select($old); + + return $cache_sock{$host} = $sock; +} + +sub get_sock { # (key) + my Cache::Memcached $self = shift; + my ($key) = @_; + return $self->sock_to_host($self->{'_single_sock'}) if $self->{'_single_sock'}; + return undef unless $self->{'active'}; + my $hv = ref $key ? int($key->[0]) : _hashfunc($key); + + $self->init_buckets() unless $self->{'buckets'}; + + my $real_key = ref $key ? $key->[1] : $key; + my $tries = 0; + while ($tries++ < 20) { + my $host = $self->{'buckets'}->[$hv % $self->{'bucketcount'}]; + my $sock = $self->sock_to_host($host); + return $sock if $sock; + return undef if $sock->{'no_rehash'}; + $hv += _hashfunc($tries . $real_key); # stupid, but works + } + return undef; +} + +sub init_buckets { + my Cache::Memcached $self = shift; + return if $self->{'buckets'}; + my $bu = $self->{'buckets'} = []; + foreach my $v (@{$self->{'servers'}}) { + if (ref $v eq "ARRAY") { + for (1..$v->[1]) { push @$bu, $v->[0]; } + } else { + push @$bu, $v; + } + } + $self->{'bucketcount'} = scalar @{$self->{'buckets'}}; +} + +sub disconnect_all { + my $sock; + foreach $sock (values %cache_sock) { + close $sock; + } + %cache_sock = (); +} + +sub _oneline { + my Cache::Memcached $self = shift; + my ($sock, $line) = @_; + my $res; + my ($ret, $offset) = (undef, 0); + + # state: 0 - writing, 1 - reading, 2 - done + my $state = defined $line ? 0 : 1; + + # the bitsets for select + my ($rin, $rout, $win, $wout); + my $nfound; + + my $copy_state = -1; + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + + # the select loop + while(1) { + if ($copy_state!=$state) { + last if $state==2; + ($rin, $win) = ('', ''); + vec($rin, fileno($sock), 1) = 1 if $state==1; + vec($win, fileno($sock), 1) = 1 if $state==0; + $copy_state = $state; + } + $nfound = select($rout=$rin, $wout=$win, undef, + $self->{'select_timeout'}); + last unless $nfound; + + if (vec($wout, fileno($sock), 1)) { + $res = send($sock, $line, $FLAG_NOSIGNAL); + next + if not defined $res and $!==EWOULDBLOCK; + unless ($res > 0) { + _close_sock($sock); + return undef; + } + if ($res == length($line)) { # all sent + $state = 1; + } else { # we only succeeded in sending some of it + substr($line, 0, $res, ''); # delete the part we sent + } + } + + if (vec($rout, fileno($sock), 1)) { + $res = sysread($sock, $ret, 255, $offset); + next + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { # catches 0=conn closed or undef=error + _close_sock($sock); + return undef; + } + $offset += $res; + if (rindex($ret, "\r\n") + 2 == length($ret)) { + $state = 2; + } + } + } + + unless ($state == 2) { + _dead_sock($sock); # improperly finished + return undef; + } + + return $ret; +} + + +sub delete { + my Cache::Memcached $self = shift; + my ($key, $time) = @_; + return 0 if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return 0 unless $sock; + + $self->{'stats'}->{"delete"}++; + $key = ref $key ? $key->[1] : $key; + $time = $time ? " $time" : ""; + my $cmd = "delete $self->{namespace}$key$time\r\n"; + my $res = _oneline($self, $sock, $cmd); + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, 'delete'); + } + + return $res eq "DELETED\r\n"; +} + +sub add { + _set("add", @_); +} + +sub replace { + _set("replace", @_); +} + +sub set { + _set("set", @_); +} + +sub _set { + my $cmdname = shift; + my Cache::Memcached $self = shift; + my ($key, $val, $exptime) = @_; + return 0 if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return 0 unless $sock; + + use bytes; # return bytes from length() + + $self->{'stats'}->{$cmdname}++; + my $flags = 0; + $key = ref $key ? $key->[1] : $key; + + if (ref $val) { + $val = Storable::nfreeze($val); + $flags |= F_STORABLE; + } + + my $len = length($val); + + if ($self->{'compress_threshold'} && $HAVE_ZLIB && $self->{'compress_enable'} && + $len >= $self->{'compress_threshold'}) { + + my $c_val = Compress::Zlib::memGzip($val); + my $c_len = length($c_val); + + # do we want to keep it? + if ($c_len < $len*(1 - COMPRESS_SAVINGS)) { + $val = $c_val; + $len = $c_len; + $flags |= F_COMPRESS; + } + } + + $exptime = int($exptime || 0); + + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + my $line = "$cmdname $self->{namespace}$key $flags $exptime $len\r\n$val\r\n"; + + my $res = _oneline($self, $sock, $line); + + if ($self->{'debug'} && $line) { + chop $line; chop $line; + print STDERR "Cache::Memcache: $cmdname $self->{namespace}$key = $val ($line)\n"; + } + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, $cmdname); + } + + return $res eq "STORED\r\n"; +} + +sub incr { + _incrdecr("incr", @_); +} + +sub decr { + _incrdecr("decr", @_); +} + +sub _incrdecr { + my $cmdname = shift; + my Cache::Memcached $self = shift; + my ($key, $value) = @_; + return undef if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return undef unless $sock; + $key = $key->[1] if ref $key; + $self->{'stats'}->{$cmdname}++; + $value = 1 unless defined $value; + + my $line = "$cmdname $self->{namespace}$key $value\r\n"; + my $res = _oneline($self, $sock, $line); + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, $cmdname); + } + + return undef unless $res =~ /^(\d+)/; + return $1; +} + +sub get { + my Cache::Memcached $self = shift; + my ($key) = @_; + + # TODO: make a fast path for this? or just keep using get_multi? + my $r = $self->get_multi($key); + my $kval = ref $key ? $key->[1] : $key; + return $r->{$kval}; +} + +sub get_multi { + my Cache::Memcached $self = shift; + return undef unless $self->{'active'}; + $self->{'_stime'} = Time::HiRes::time() if $self->{'stat_callback'}; + $self->{'stats'}->{"get_multi"}++; + my %val; # what we'll be returning a reference to (realkey -> value) + my %sock_keys; # sockref_as_scalar -> [ realkeys ] + my $sock; + + foreach my $key (@_) { + $sock = $self->get_sock($key); + next unless $sock; + my $kval = ref $key ? $key->[1] : $key; + push @{$sock_keys{$sock}}, $kval; + } + $self->{'stats'}->{"get_keys"} += @_; + $self->{'stats'}->{"get_socks"} += keys %sock_keys; + + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + + _load_multi($self, \%sock_keys, \%val); + + if ($self->{'debug'}) { + while (my ($k, $v) = each %val) { + print STDERR "MemCache: got $k = $v\n"; + } + } + return \%val; +} + +sub _load_multi { + use bytes; # return bytes from length() + my Cache::Memcached $self = shift; + my ($sock_keys, $ret) = @_; + + # all keyed by a $sock: + my %reading; # bool, whether we're reading from this socket + my %writing; # bool, whether we're writing into this socket + my %state; # reading state: + # 0 = waiting for a line, N = reading N bytes + my %buf; # buffers + my %offset; # offsets to read into buffers + my %key; # current key per socket + my %flags; # flags per socket + + foreach (keys %$sock_keys) { + print STDERR "processing socket $_\n" if $self->{'debug'} && $self->{'debug'} >= 2; + $writing{$_} = 1; + $buf{$_} = "get ". join(" ", map { "$self->{namespace}$_" } @{$sock_keys->{$_}}) . "\r\n"; + } + + my $active_changed = 1; # force rebuilding of select sets + + my $dead = sub { + my $sock = shift; + print STDERR "killing socket $sock\n" if $self->{'debug'} >= 2; + delete $reading{$sock}; + delete $writing{$sock}; + delete $ret->{$key{$sock}} + if $key{$sock}; + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($self->{'_stime'}, $etime, $sock, 'get_multi'); + } + + close $sock; + _dead_sock($sock); + $active_changed = 1; + }; + + my $finalize = sub { + my $sock = shift; + my $k = $key{$sock}; + + # remove trailing \r\n + chop $ret->{$k}; chop $ret->{$k}; + + unless (length($ret->{$k}) == $state{$sock}-2) { + $dead->($sock); + return; + } + + $ret->{$k} = Compress::Zlib::memGunzip($ret->{$k}) + if $HAVE_ZLIB && $flags{$sock} & F_COMPRESS; + if ($flags{$sock} & F_STORABLE) { + # wrapped in eval in case a perl 5.6 Storable tries to + # unthaw data from a perl 5.8 Storable. (5.6 is stupid + # and dies if the version number changes at all. in 5.8 + # they made it only die if it unencounters a new feature) + eval { + $ret->{$k} = Storable::thaw($ret->{$k}); + }; + # so if there was a problem, just treat it as a cache miss. + if ($@) { + delete $ret->{$k}; + } + } + }; + + my $read = sub { + my $sock = shift; + my $res; + + # where are we reading into? + if ($state{$sock}) { # reading value into $ret + $res = sysread($sock, $ret->{$key{$sock}}, + $state{$sock} - $offset{$sock}, + $offset{$sock}); + return + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { # catches 0=conn closed or undef=error + $dead->($sock); + return; + } + $offset{$sock} += $res; + if ($offset{$sock} == $state{$sock}) { # finished reading + $finalize->($sock); + $state{$sock} = 0; # wait for another VALUE line or END + $offset{$sock} = 0; + } + return; + } + + # we're reading a single line. + # first, read whatever's there, but be satisfied with 2048 bytes + $res = sysread($sock, $buf{$sock}, + 2048, $offset{$sock}); + return + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { + $dead->($sock); + return; + } + $offset{$sock} += $res; + + SEARCH: + while(1) { # may have to search many times + # do we have a complete END line? + if ($buf{$sock} =~ /^END\r\n/) { + # okay, finished with this socket + delete $reading{$sock}; + $active_changed = 1; + return; + } + + # do we have a complete VALUE line? + if ($buf{$sock} =~ /^VALUE (\S+) (\d+) (\d+)\r\n/) { + ($key{$sock}, $flags{$sock}, $state{$sock}) = + (substr($1, $self->{namespace_len}), int($2), $3+2); + # Note: we use $+[0] and not pos($buf{$sock}) because pos() + # seems to have problems under perl's taint mode. nobody + # on the list discovered why, but this seems a reasonable + # work-around: + my $p = $+[0]; + my $len = length($buf{$sock}); + my $copy = $len-$p > $state{$sock} ? $state{$sock} : $len-$p; + $ret->{$key{$sock}} = substr($buf{$sock}, $p, $copy) + if $copy; + $offset{$sock} = $copy; + substr($buf{$sock}, 0, $p+$copy, ''); # delete the stuff we used + if ($offset{$sock} == $state{$sock}) { # have it all? + $finalize->($sock); + $state{$sock} = 0; # wait for another VALUE line or END + $offset{$sock} = 0; + next SEARCH; # look again + } + last SEARCH; # buffer is empty now + } + + # if we're here probably means we only have a partial VALUE + # or END line in the buffer. Could happen with multi-get, + # though probably very rarely. Exit the loop and let it read + # more. + + # but first, make sure subsequent reads don't destroy our + # partial VALUE/END line. + $offset{$sock} = length($buf{$sock}); + last SEARCH; + } + + # we don't have a complete line, wait and read more when ready + return; + }; + + my $write = sub { + my $sock = shift; + my $res; + + $res = send($sock, $buf{$sock}, $FLAG_NOSIGNAL); + return + if not defined $res and $!==EWOULDBLOCK; + unless ($res > 0) { + $dead->($sock); + return; + } + if ($res == length($buf{$sock})) { # all sent + $buf{$sock} = ""; + $offset{$sock} = $state{$sock} = 0; + # switch the socket from writing state to reading state + delete $writing{$sock}; + $reading{$sock} = 1; + $active_changed = 1; + } else { # we only succeeded in sending some of it + substr($buf{$sock}, 0, $res, ''); # delete the part we sent + } + return; + }; + + # the bitsets for select + my ($rin, $rout, $win, $wout); + my $nfound; + + # the big select loop + while(1) { + if ($active_changed) { + last unless %reading or %writing; # no sockets left? + ($rin, $win) = ('', ''); + foreach (keys %reading) { + vec($rin, fileno($_), 1) = 1; + } + foreach (keys %writing) { + vec($win, fileno($_), 1) = 1; + } + $active_changed = 0; + } + # TODO: more intelligent cumulative timeout? + $nfound = select($rout=$rin, $wout=$win, undef, + $self->{'select_timeout'}); + last unless $nfound; + + # TODO: possible robustness improvement: we could select + # writing sockets for reading also, and raise hell if they're + # ready (input unread from last time, etc.) + # maybe do that on the first loop only? + foreach (keys %writing) { + if (vec($wout, fileno($_), 1)) { + $write->($_); + } + } + foreach (keys %reading) { + if (vec($rout, fileno($_), 1)) { + $read->($_); + } + } + } + + # if there're active sockets left, they need to die + foreach (keys %writing) { + $dead->($_); + } + foreach (keys %reading) { + $dead->($_); + } + + return; +} + +sub _hashfunc { + return (crc32(shift) >> 16) & 0x7fff; +} + +# returns array of lines, or () on failure. +sub run_command { + my Cache::Memcached $self = shift; + my ($sock, $cmd) = @_; + return () unless $sock; + my $ret; + my $line = $cmd; + while (my $res = _oneline($self, $sock, $line)) { + undef $line; + $ret .= $res; + last if $ret =~ /(?:END|ERROR)\r\n$/; + } + chop $ret; chop $ret; + return map { "$_\r\n" } split(/\r\n/, $ret); +} + +sub stats { + my Cache::Memcached $self = shift; + my ($types) = @_; + return 0 unless $self->{'active'}; + return 0 unless !ref($types) || ref($types) eq 'ARRAY'; + if (!ref($types)) { + if (!$types) { + # I don't much care what the default is, it should just + # be something reasonable. Obviously "reset" should not + # be on the list :) but other types that might go in here + # include maps, cachedump, slabs, or items. + $types = [ qw( misc malloc sizes self ) ]; + } else { + $types = [ $types ]; + } + } + + $self->init_buckets() unless $self->{'buckets'}; + + my $stats_hr = { }; + + # The "self" stat type is special, it only applies to this very + # object. + if (grep /^self$/, @$types) { + $stats_hr->{'self'} = \%{ $self->{'stats'} }; + } + + # Now handle the other types, passing each type to each host server. + my @hosts = @{$self->{'buckets'}}; + my %malloc_keys = ( ); + HOST: foreach my $host (@hosts) { + my $sock = $self->sock_to_host($host); + TYPE: foreach my $typename (grep !/^self$/, @$types) { + my $type = $typename eq 'misc' ? "" : " $typename"; + my $line = _oneline($self, $sock, "stats$type\r\n"); + if (!$line) { + _dead_sock($sock); + next HOST; + } + + # Some stats are key-value, some are not. malloc, + # sizes, and the empty string are key-value. + # ("self" was handled separately above.) + if ($typename =~ /^(malloc|sizes|misc)$/) { + # This stat is key-value. + LINE: while ($line) { + # We have to munge this data a little. First, I'm not + # sure why, but 'stats sizes' output begins with NUL. + $line =~ s/^\0//; + + # And, most lines end in \r\n but 'stats maps' (as of + # July 2003 at least) ends in \n. An alternative + # would be { local $/="\r\n"; chomp } but this works + # just as well: + $line =~ s/[\r\n]+$//; + + # OK, process the data until the end, converting it + # into its key-value pairs. + last LINE if $line eq 'END'; + my($key, $value) = $line =~ /^(?:STAT )?(\w+)\s(.*)/; + if ($key) { + $stats_hr->{'hosts'}{$host}{$typename}{$key} = $value; + } + $malloc_keys{$key} = 1 if $typename eq 'malloc'; + + # read the next line + $line = _oneline($self, $sock); + } + } else { + # This stat is not key-value so just pull it + # all out in one blob. + LINE: while ($line) { + $line =~ s/[\r\n]+$//; + last LINE if $line eq 'END'; + $stats_hr->{'hosts'}{$host}{$typename} ||= ""; + $stats_hr->{'hosts'}{$host}{$typename} .= "$line\n"; + + # read the next one + $line = _oneline($self, $sock); + } + } + } + } + + # Now get the sum total of applicable values. First the misc values. + foreach my $stat (qw( + bytes bytes_read bytes_written + cmd_get cmd_set connection_structures curr_items + get_hits get_misses + total_connections total_items + )) { + $stats_hr->{'total'}{$stat} = 0; + foreach my $host (@hosts) { + $stats_hr->{'total'}{$stat} += + $stats_hr->{'hosts'}{$host}{'misc'}{$stat}; + } + } + + # Then all the malloc values, if any. + foreach my $malloc_stat (keys %malloc_keys) { + $stats_hr->{'total'}{"malloc_$malloc_stat"} = 0; + foreach my $host (@hosts) { + $stats_hr->{'total'}{"malloc_$malloc_stat"} += + $stats_hr->{'hosts'}{$host}{'malloc'}{$malloc_stat}; + } + } + + return $stats_hr; +} + +sub stats_reset { + my Cache::Memcached $self = shift; + my ($types) = @_; + return 0 unless $self->{'active'}; + + $self->init_buckets() unless $self->{'buckets'}; + + HOST: foreach my $host (@{$self->{'buckets'}}) { + my $sock = $self->sock_to_host($host); + my $ok = _oneline($self, $sock, "stats reset"); + unless ($ok eq "RESET\r\n") { + _dead_sock($sock); + } + } + return 1; +} + + + +1; +__END__ + +=head1 NAME + +Cache::Memcached - client library for memcached (memory cache daemon) + +=head1 SYNOPSIS + + use Cache::Memcached; + + $memd = new Cache::Memcached { + 'servers' => [ "10.0.0.15:11211", "10.0.0.15:11212", + "10.0.0.17:11211", [ "10.0.0.17:11211", 3 ] ], + 'debug' => 0, + 'compress_threshold' => 10_000, + }; + $memd->set_servers($array_ref); + $memd->set_compress_threshold(10_000); + $memd->enable_compress(0); + + $memd->set("my_key", "Some value"); + $memd->set("object_key", { 'complex' => [ "object", 2, 4 ]}); + + $val = $memd->get("my_key"); + $val = $memd->get("object_key"); + if ($val) { print $val->{'complex'}->[2]; } + + $memd->incr("key"); + $memd->decr("key"); + $memd->incr("key", 2); + +=head1 DESCRIPTION + +This is the Perl API for memcached, a distributed memory cache daemon. +More information is available at: + + http://www.danga.com/memcached/ + +=head1 CONSTRUCTOR + +=over 4 + +=item C + +Takes one parameter, a hashref of options. The most important key is +C, but that can also be set later with the C +method. The servers must be an arrayref of hosts, each of which is +either a scalar of the form C<10.0.0.10:11211> or an arrayref of the +former and an integer weight value. (The default weight if +unspecified is 1.) It's recommended that weight values be kept as low +as possible, as this module currently allocates memory for bucket +distribution proportional to the total host weights. + +Use C to set a compression threshold, in bytes. +Values larger than this threshold will be compressed by C and +decompressed by C. + +Use C to disable finding a new memcached server when one +goes down. Your application may or may not need this, depending on +your expirations and key usage. + +Use C to disable writes to backend memcached servers. Only +get and get_multi will work. This is useful in bizarre debug and +profiling cases only. + +The other useful key is C, which when set to true will produce +diagnostics on STDERR. + +=back + +=head1 METHODS + +=over 4 + +=item C + +Sets the server list this module distributes key gets and sets between. +The format is an arrayref of identical form as described in the C +constructor. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the compression threshold. See C constructor for more information. + +=item C + +Temporarily enable or disable compression. Has no effect if C +isn't set, but has an overriding effect if it is. + +=item C + +my $val = $memd->get($key); + +Retrieves a key from the memcache. Returns the value (automatically +thawed with Storable, if necessary) or undef. + +The $key can optionally be an arrayref, with the first element being the +hash value, if you want to avoid making this module calculate a hash +value. You may prefer, for example, to keep all of a given user's +objects on the same memcache server, so you could use the user's +unique id as the hash value. + +=item C + +my $hashref = $memd->get_multi(@keys); + +Retrieves multiple keys from the memcache doing just one query. +Returns a hashref of key/value pairs that were available. + +This method is recommended over regular 'get' as it lowers the number +of total packets flying around your network, reducing total latency, +since your app doesn't have to wait for each round-trip of 'get' +before sending the next one. + +=item C + +$memd->set($key, $value[, $exptime]); + +Unconditionally sets a key to a given value in the memcache. Returns true +if it was stored successfully. + +The $key can optionally be an arrayref, with the first element being the +hash value, as described above. + +The $exptime (expiration time) defaults to "never" if unspecified. If +you want the key to expire in memcached, pass an integer $exptime. If +value is less than 60*60*24*30 (30 days), time is assumed to be relative +from the present. If larger, it's considered an absolute Unix time. + +=item C + +$memd->add($key, $value[, $exptime]); + +Like C, but only stores in memcache if the key doesn't already exist. + +=item C + +$memd->replace($key, $value[, $exptime]); + +Like C, but only stores in memcache if the key already exists. The +opposite of C. + +=item C + +$memd->delete($key[, $time]); + +Deletes a key. You may optionally provide an integer time value (in seconds) to +tell the memcached server to block new writes to this key for that many seconds. +(Sometimes useful as a hacky means to prevent races.) Returns true if key +was found and deleted, and false otherwise. + +=item C + +$memd->incr($key[, $value]); + +Sends a command to the server to atomically increment the value for +$key by $value, or by 1 if $value is undefined. Returns undef if $key +doesn't exist on server, otherwise it returns the new value after +incrementing. Value should be zero or greater. Overflow on server +is not checked. Be aware of values approaching 2**32. See decr. + +=item C + +$memd->decr($key[, $value]); + +Like incr, but decrements. Unlike incr, underflow is checked and new +values are capped at 0. If server value is 1, a decrement of 2 +returns 0, not -1. + +=item C + +$memd->stats([$keys]); + +Returns a hashref of statistical data regarding the memcache server(s), +the $memd object, or both. $keys can be an arrayref of keys wanted, a +single key wanted, or absent (in which case the default value is malloc, +sizes, self, and the empty string). These keys are the values passed +to the 'stats' command issued to the memcached server(s), except for +'self' which is internal to the $memd object. Allowed values are: + +=over 4 + +=item C + +The stats returned by a 'stats' command: pid, uptime, version, +bytes, get_hits, etc. + +=item C + +The stats returned by a 'stats malloc': total_alloc, arena_size, etc. + +=item C + +The stats returned by a 'stats sizes'. + +=item C + +The stats for the $memd object itself (a copy of $memd->{'stats'}). + +=item C + +The stats returned by a 'stats maps'. + +=item C + +The stats returned by a 'stats cachedump'. + +=item C + +The stats returned by a 'stats slabs'. + +=item C + +The stats returned by a 'stats items'. + +=back + +=item C + +$memd->disconnect_all(); + +Closes all cached sockets to all memcached servers. You must do this +if your program forks and the parent has used this module at all. +Otherwise the children will try to use cached sockets and they'll fight +(as children do) and garble the client/server protocol. + +=back + +=head1 BUGS + +When a server goes down, this module does detect it, and re-hashes the +request to the remaining servers, but the way it does it isn't very +clean. The result may be that it gives up during its rehashing and +refuses to get/set something it could've, had it been done right. + +=head1 COPYRIGHT + +This module is Copyright (c) 2003 Brad Fitzpatrick. +All rights reserved. + +You may distribute under the terms of either the GNU General Public +License or the Artistic License, as specified in the Perl README file. + +=head1 WARRANTY + +This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + +=head1 FAQ + +See the memcached website: + http://www.danga.com/memcached/ + +=head1 AUTHORS + +Brad Fitzpatrick + +Anatoly Vorobey + +Brad Whitaker + +Jamie McCarthy diff --git a/local/cgi-bin/Golem.pm b/local/cgi-bin/Golem.pm new file mode 100644 index 0000000..d3498d6 --- /dev/null +++ b/local/cgi-bin/Golem.pm @@ -0,0 +1,94 @@ +#!/usr/bin/perl -w + +package Golem; + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/Golem/dblib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/Golem/loglib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/Golem/netlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/Golem/proplib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/Golem/textlib.pl"; + +# *** LJR apis conversion layer +# +# check out + +our $on = 1; +our $counter_prefix = "golem_"; + +sub get_db { + return LJ::get_db_writer(); +} + +# Golem tags are not ported to LJR +sub unset_row_tag { + return 1; +} +# *** LJR apis conversion layer + +sub get_callstack { + my $cstack; + my $i = 0; + while ( 1 ) { + my $tfunc = (caller($i))[3]; + if ($tfunc && $tfunc ne "") { + if ($tfunc !~ /\_\_ANON\_\_/ && + $tfunc !~ /.*::get_callstack/) { + $cstack .= "\t" . $tfunc . "\n"; + } + $i = $i + 1; + } + else { + last; + } + } + return "\nCallstack:\n" . $cstack . "\n"; +} + +sub err { + if (ref($_[0])) { + my $dbh = shift; + $dbh->rollback; + } + + my $errstr = shift || ""; + my $previous_object; + + if (ref($_[0]) eq 'HASH') { + $previous_object = shift; + } + + if ($previous_object) { + $previous_object->{'err'} = 1; + $previous_object->{'errstr'} = $errstr . Golem::get_callstack(); + + return $previous_object; + } + else { + my %res = ( + "err" => 1, + "errstr" => $errstr . Golem::get_callstack(), + ); + + return \%res; + } +} + +sub die { + my ($message, $suppress_callstack) = @_; + + print STDERR "$message"; + + unless ($suppress_callstack) { + print STDERR Golem::get_callstack(); + } + else { + print "\n"; + } + + exit 1; +} + + +1; diff --git a/local/cgi-bin/Golem/dblib.pl b/local/cgi-bin/Golem/dblib.pl new file mode 100644 index 0000000..c0c2cc5 --- /dev/null +++ b/local/cgi-bin/Golem/dblib.pl @@ -0,0 +1,746 @@ +#!/usr/bin/perl -w +# +# Generic database routines +# + + +package Golem; +use strict; + +use Golem; + +# courtesy of LiveJournal.org +sub disconnect_dbs { + foreach my $h (($Golem::DB, $Golem::PlanerDB, $Golem::CalendarDB, $Golem::OtrsDB, $Golem::SwerrsDB)) { + if ($h) { + $h->disconnect(); + $h = undef; + } + } + + print STDERR localtime() . " [$$]: closed db connections\n" if $ENV{'GOLEM_DEBUG'}; +} + +# build DSN connection string based on database info hashref, +# courtesy of livejournal.org +# +# $DBINFO = { +# 'master' => { +# 'dbname' => "golem_kohts", +# 'host' => "localhost", +# 'port' => 3306, +# 'user' => "root", +# 'pass' => "", +# 'sock' => "", +# 'encoding' => "utf8", +# }, +# }; +# +sub make_dbh_fdsn { + my ($db) = @_; + + my $fdsn = "DBI:mysql"; + $fdsn .= ":$db->{'dbname'}"; + $fdsn .= ";host=$db->{'host'}" if $db->{'host'}; + $fdsn .= ";port=$db->{'port'}" if $db->{'port'}; + $fdsn .= ";mysql_socket=$db->{'sock'}" if $db->{'sock'}; + $fdsn .= "|$db->{'user'}|$db->{'pass'}"; + + return $fdsn; +} + +# test if connection is still available +# (should check for replication, etc. here) +# +sub connection_bad { + my ($dbh, $try) = @_; + + return 1 unless $dbh; + + my $ss = eval { +# +# $dbh->selectrow_hashref("SHOW SLAVE STATUS"); +# +# on a real slave +# +# $ss = { +# 'Skip_counter' => '0', +# 'Master_Log_File' => 'ararita-bin.882', +# 'Connect_retry' => '60', +# 'Master_Host' => 'ararita.lenin.ru', +# 'Relay_Master_Log_File' => 'ararita-bin.882', +# 'Relay_Log_File' => 'laylah-relay-bin.323', +# 'Slave_IO_Running' => 'Yes', +# 'Slave_SQL_Running' => 'Yes', +# 'Master_Port' => '3306', +# 'Exec_master_log_pos' => '17720151', +# 'Relay_log_space' => '19098333', +# 'Relay_Log_Pos' => '19098333', +# 'Last_errno' => '0', +# 'Last_error' => '', +# 'Replicate_do_db' => 'prod_livejournal,prod_livejournal', +# 'Read_Master_Log_Pos' => '17720151', +# 'Master_User' => 'replication', +# 'Replicate_ignore_db' => '' +# }; + + $dbh->selectrow_hashref("select name from _dbi"); + }; + + if ($dbh->err && $dbh->err != 1227) { + print STDERR localtime() . " [$$]: " . $dbh->errstr . "\n" if $ENV{'GOLEM_DEBUG'}; + return 1; + } + + if ($ss && $ss->{'name'} ne '??') { + return 0; + } + elsif ($ss && $ss->{'name'} eq '??') { + print STDERR localtime() . " [$$]: DBI returned garbage: $ss->{'name'}\n" if $ENV{'GOLEM_DEBUG'}; + return 1; + } + elsif (!$ss) { + print STDERR localtime() . " [$$]: DBI returned nothing\n" if $ENV{'GOLEM_DEBUG'}; + return 1; + } +} + +# LJR modification; redefined in cgi-bin/Golem.pmGolem.pm +# so it works correctly with original LJ code +# +sub golem_get_db { + my ($params, $opts) = @_; + + $opts = {} unless $opts; + $params = {} unless $params; + + if ($Golem::DB) { + if (! connection_bad($Golem::DB)) { + return $Golem::DB; + } + else { + print STDERR localtime() . " [$$]: new connection: was bad\n" if $ENV{'GOLEM_DEBUG'}; + $Golem::DB->disconnect; + } + } + else { + print STDERR localtime() . " [$$]: new connection: had none\n" if $ENV{'GOLEM_DEBUG'}; + } + undef $Golem::DB; + + # DB connection defaults (unless programmer specified them) + # + $params->{'RaiseError'} = 0 unless defined($params->{'RaiseError'}); + $params->{'PrintError'} = 1 unless defined($params->{'PrintError'}); + $params->{'AutoCommit'} = 1 unless defined($params->{'AutoCommit'}); + + Golem::die("No Golem::DBINFO master defined") + unless $Golem::DBINFO->{'master'}; + + my $dbinfo = $Golem::DBINFO->{'master'}; + my $fdsn = make_dbh_fdsn($dbinfo); + + $Golem::DB = DBI->connect($fdsn, $dbinfo->{'user'}, $dbinfo->{'pass'}, $params); + while (!$Golem::DB && $opts->{'retry_forever'}) { + Golem::do_log("database not available, retrying", {"stderr" => 1}); + sleep 1; + $Golem::DB = DBI->connect($fdsn, $dbinfo->{'user'}, $dbinfo->{'pass'}, $params); + } + Golem::die("Unable to connect to database: " . DBI->errstr) + unless $Golem::DB; + + $Golem::DB->do("SET NAMES " . $dbinfo->{'encoding'}) + if $dbinfo->{'encoding'}; + + if (connection_bad($Golem::DB)) { + print STDERR "got fresh new bad handle, retrying\n" if $ENV{'GOLEM_DEBUG'}; + $Golem::DB = undef; + $Golem::DB = Golem::get_db(); + } + + $Golem::default_dc_obj = Golem::get_dc($Golem::default_dc); + return $Golem::DB; +} + +sub get_planer_db { + my ($params) = @_; + + return $Golem::PlanerDB if $Golem::PlanerDB; + + $params = {RaiseError => 0, PrintError => 1, AutoCommit => 1} + unless $params; + + $Golem::PlanerDB = DBI->connect("DBI:Sybase:server=argo3.yandex.ru;database=planer;", + "helpdesk", "gkfyshfcnfvfys123", $params); + + return $Golem::PlanerDB; +} + +sub get_calendar_db { + my ($params) = @_; + + return $Golem::CalendarDB if $Golem::CalendarDB; + + $params = {RaiseError => 0, PrintError =>1, AutoCommit => 1} + unless $params; + + $Golem::CalendarDB = DBI->connect("DBI:Sybase:server=argo3.yandex.ru;database=momdb;", + "staffreader", "cegthgfhjkm678", $params); + + return $Golem::CalendarDB; +} + +sub get_otrs_db { + my ($params) = @_; + + return $Golem::OtrsDB if $Golem::OtrsDB; + + $params = {RaiseError => 0, PrintError =>1, AutoCommit => 1} + unless $params; + + $Golem::OtrsDB = DBI->connect("DBI:mysql:database=otrs_utf8:host=casa.yandex.ru:port=3306", + "userorder", "xuo9Bahf", $params); + + return $Golem::OtrsDB; +} + +sub get_swerrs_db { + my ($params) = @_; + + return $Golem::SwerrsDB if $Golem::SwerrsDB; + + $params = { RaiseError => 0, PrintError => 1, AutoCommit => 1 } + unless $params; + + $Golem::SwerrsDB = DBI->connect("DBI:mysql:racktables:localhost:3306", "swerrs", "V7Hl}O]Usr", $params); + + return $Golem::SwerrsDB; +} + + +sub sth_bind_array { + my ($sth, $bound_values) = @_; + + my $i = 0; + foreach my $b (@{$bound_values}) { + $i++; + + Golem::die("error binding params") + unless $sth->bind_param($i, $b) ; + } +} + +# courtesy of LiveJournal.org +# see also: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id +# +sub alloc_global_counter { + my ($tag, $recurse) = @_; + + my $dbh = Golem::get_db(); + my $newmax; + + # in case name `counter` is already occupied + # by some user table + my $counter_prefix = ""; + $counter_prefix = $Golem::counter_prefix + if defined($Golem::counter_prefix); + + my $rs = $dbh->do("UPDATE ${counter_prefix}counter SET max=LAST_INSERT_ID(max+1) WHERE tag=?", undef, $tag); + if ($rs > 0) { + $newmax = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + return $newmax; + } + + return undef if $recurse; + + # no prior counter rows - initialize one. + + # if this is a table then trying default id column + if ($Golem::SCHEMA_CACHE->{'tables'}->{$tag}) { + $newmax = $dbh->selectrow_array("SELECT MAX(id) FROM `$tag`"); + } + else { + Golem::die("alloc_global_counter: unknown tag [$tag], unable to get max value."); + } + + $newmax += 0; + + $dbh->do("INSERT IGNORE INTO ${counter_prefix}counter (tag, max) VALUES (?,?)", + undef, $tag, $newmax) || return undef; + + return Golem::alloc_global_counter($tag, 1); +} + +# get schema table definition, +# prepare in-memory table structure +# +sub get_schema_table { + my ($table_name, $opts) = @_; + + return $Golem::SCHEMA_CACHE->{'tables'}->{$table_name} + if $Golem::SCHEMA_CACHE->{'tables'}->{$table_name} && + !$opts->{'force'}; + + delete($Golem::SCHEMA_CACHE->{'tables'}->{$table_name}) + if $Golem::SCHEMA_CACHE->{'tables'}->{$table_name}; + + $Golem::SCHEMA_CACHE->{'tables'}->{$table_name}->{'fields'} = {}; + my $t = $Golem::SCHEMA_CACHE->{'tables'}->{$table_name}; + + my $dbh = Golem::get_db(); + Golem::debug_sql("describe `$table_name`"); + my $sth = $dbh->prepare("describe `$table_name`"); + $sth->execute(); + Golem::die("Error describing table [$table_name]: " . $dbh->errstr) + if $dbh->err; + + my $select_all_sql = ""; + while (my $r = $sth->fetchrow_hashref) { + my $field_name = $r->{'Field'}; + + $t->{'fields'}->{$field_name} = $r; + + if ($r->{'Type'} =~ /^enum\((.+)\)/o) { + my $enums = $1; + foreach my $etype (split(/,/o, $enums)) { + $etype =~ s/'//go; + $t->{'fields'}->{$field_name}->{'enum'}->{$etype} = 1; + } + } + + if ($r->{'Type'} eq 'timestamp') { + $select_all_sql .= "UNIX_TIMESTAMP(`$field_name`) as `$field_name`, "; + } + else { + $select_all_sql .= "`$field_name`, "; + } + + if ($r->{'Key'} eq 'PRI') { + $t->{'primary_key'}->{$field_name} = 1; + } + } + chop($select_all_sql); + chop($select_all_sql); + + $Golem::SCHEMA_CACHE->{'tables'}->{$table_name}->{'select_all_sql'} = $select_all_sql; + + return $Golem::SCHEMA_CACHE->{'tables'}->{$table_name}; +} + +# function tells whether field is data field or some special field +# like host.id (incremented with alloc_global_counter) or +# like host.last_updated (automatically updated when record is updated) +# maybe we should filter them by name instead of using db structure hints? +sub is_data_field { + my ($table_name, $field_name, $opts) = @_; + + $opts = {} unless $opts; + + my $table = Golem::get_schema_table($table_name); + my $table_fields = $table->{'fields'}; + + if ($table_fields->{$field_name}) { + if ($table_fields->{$field_name}->{'Default'} && + $table_fields->{$field_name}->{'Default'} eq 'CURRENT_TIMESTAMP' && + !$opts->{'ignore_default_current_timestamp'} ) { + + return 0; + } + +# if ($table_fields->{$field_name}->{'Key'} && +# $table_fields->{$field_name}->{'Key'} eq 'PRI') { +# +# return 0; +# } + + # we have to distinguish between host.id and host_rackmap.host; + # both are PRIMARY keys, but + # 1) we shouldn't ever update host.id + # 2) we have to update host_rackmap.host with host.id + # when creating record corresponding to host record + if ($field_name eq "id" && !$opts->{'manual_id_management'}) { + return 0; + } + + return 1; + } + else { + return 0; + } +} + +sub __insert { + my ($table_name, $record_hashref, $opts) = @_; + + Golem::die("Severe programmer error: __insert expects table name as first parameter!") + unless $table_name; + Golem::die("Severe programmer error: __insert expects record hashref as second parameter!") + unless ref($record_hashref) eq 'HASH'; + + $opts = {} unless ref($opts) eq 'HASH'; + + my $dbh; + if ($opts->{'dbh'}) { + $dbh = $opts->{'dbh'}; + } + else { + $dbh = Golem::get_db(); + } + + $dbh->{'PrintError'} = $opts->{'PrintError'} + if defined($opts->{'PrintError'}); + + my $sth; + + my $table = Golem::get_schema_table($table_name); + my $table_fields = $table->{'fields'}; + + # continue only if there's data for the table + # or if there's a flag saying we should create + # empty record with defaults + my $have_data_for_the_table = 0; + while (my ($o, $v) = each(%{$record_hashref})) { + if (Golem::is_data_field($table_name, $o, $opts)) { + $have_data_for_the_table = 1; + } + } + unless ($have_data_for_the_table || $opts->{'create_empty_record'}) { + return $dbh; + } + + my @record_fields; + my @record_values; + + foreach my $o (keys %{$record_hashref}) { + # $record_hashref might contain more fields than present in database. + # we only choose those which are in db + + if ($table_fields->{$o} && Golem::is_data_field($table_name, $o, $opts)) { + + # enum validation + if ($table_fields->{$o}->{'enum'}) { + Golem::die("Enum [$table_name.$o] value is not specified and doesn't have default value") + if !defined($record_hashref->{$o}) && $table_fields->{$o}->{'Default'} eq ''; + + Golem::die("Enum [$table_name.$o] can't be [$record_hashref->{$o}]") + if $record_hashref->{$o} && !$table_fields->{$o}->{'enum'}->{$record_hashref->{$o}}; + + # if they passed empty value for enum + # and there's some default -- silently + # decide to use it + unless ($record_hashref->{$o}) { + delete($record_hashref->{$o}); + next; + } + } + + push @record_fields, $o; + push @record_values, $record_hashref->{$o}; + } + } + + if ($table_fields->{"id"} && !$opts->{'manual_id_management'}) { + if ($record_hashref->{"id"}) { + Golem::die("Severe database structure or programmer error: __insert got id [$record_hashref->{'id'}] +when creating record for table [$table_name]; won't overwrite.\n"); + } + + $record_hashref->{"id"} = Golem::alloc_global_counter($table_name); + + # check that id is not taken and + # die with severe error otherwise + # + + my $t_id = $dbh->selectrow_array("select id from `$table_name` where id = ?", + undef, $record_hashref->{"id"}); + if ($t_id && $t_id eq $record_hashref->{"id"}) { + Golem::die("Severe database error: __insert got [$t_id] for table [$table_name] " . + "from alloc_global_counter which already exists!\n" . + "Probable somebody is populating [$table_name] without Golem::__insert()\n"); + } + + push @record_fields, "id"; + push @record_values, $record_hashref->{"id"}; + } + + my $sql; + my @bound_values; + + $sql = "INSERT INTO `$table_name` ( "; + foreach my $o (@record_fields) { + $sql = $sql . " `$o`,"; + } + chop($sql); + + $sql .= " ) VALUES ( "; + + my $i = 0; + foreach my $o (@record_values) { + + # we represent timestamp datatype as unixtime (http://en.wikipedia.org/wiki/Unix_time) + # doing all the conversions almost invisible to the end user + # + # if the value being written is 0 then we're not using FROM_UNIXTIME(value) + # (which generates warnings) just value + # + if ($table_fields->{$record_fields[$i]}->{'Type'} eq 'timestamp' && $o && $o != 0) { + Golem::die("Programmer error: __insert got hashref with invalid data for $table_name.$record_fields[$i] (should be unixtime)") + unless $o =~ /^[0-9]+$/o; + + $sql = $sql . "FROM_UNIXTIME(?),"; + } + else { + $sql = $sql . "?,"; + } + + push @bound_values, $o; + $i++; + } + chop($sql); + $sql .= " )"; + + Golem::debug_sql($sql, \@bound_values); + + $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + if ($dbh->err && $dbh->{'PrintError'}) { + Golem::do_log("got error [" . $dbh->err . "] [" . $dbh->errstr . "]" . + " while executing [$sql] with values (" . join(",", @bound_values) . ")", + {'stderr' => 1}); + } + + return $dbh; +} + +sub __update { + my ($table_name, $record_hashref, $opts) = @_; + + Golem::die("Severe programmer error: __update expects table name as first parameter!") + unless $table_name; + Golem::die("Severe programmer error: __update expects record hashref as second parameter!") + unless ref($record_hashref) eq 'HASH'; + + $opts = {} unless ref($opts) eq 'HASH'; + + my $dbh; + if ($opts->{'dbh'}) { + $dbh = $opts->{'dbh'}; + } + else { + $dbh = Golem::get_db(); + } + + my $sth; + + my $table = Golem::get_schema_table($table_name); + my $table_fields = $table->{'fields'}; + my $unique_fields_arrayref = [keys %{$table->{'primary_key'}}]; + + if ($opts->{'unique_fields'}) { + $unique_fields_arrayref = $opts->{'unique_fields'}; + } + + # continue only if there's data for the table + # in the in-memory hash or if there's a flag + # saying we should create empty record with defaults + # + my $have_data_for_the_table = 0; + while (my ($o, $v) = each(%{$record_hashref})) { + if (Golem::is_data_field($table_name, $o)) { + my $is_unique = 0; + + foreach my $u (@{$unique_fields_arrayref}) { + if ($u eq $o) { + $is_unique = 1; + } + } + next if $is_unique; + + $have_data_for_the_table = 1; + } + } + unless ($have_data_for_the_table || $opts->{'create_empty_record'}) { + return $dbh; + } + + my $sql; + my @bound_values; + + $sql = "SELECT " . $table->{'select_all_sql'} . " from `$table_name` WHERE "; + foreach my $f (@{$unique_fields_arrayref}) { + if ($table_fields->{$f}->{'Type'} eq 'timestamp' && $record_hashref->{$f} != 0) { + Golem::die("Programmer error: __update got hashref with invalid data for $table_name.$f (should be unixtime)") + unless $record_hashref->{$f} =~ /^[0-9]+$/o; + + $sql .= " `$f` = FROM_UNIXTIME(?) and "; + } + else { + $sql .= " `$f` = ? and "; + } + push @bound_values, $record_hashref->{$f}; + } + # remove last "and " + chop($sql); + chop($sql); + chop($sql); + chop($sql); + + $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + # create record if it doesn't exist: useful when updating + # records in dependent tables (hosts_resps, hosts_netmap, host_rackmap) + # when master table exists. + unless ($sth->rows) { + if ($opts->{"create_nonexistent"}) { + $dbh = Golem::__insert($table_name, $record_hashref, $opts); + return $dbh; + } + else { + Golem::die("Programmer error: requested to update non-existent record with no create_nonexistent option"); + } + } + + my $existing_row; + while(my $r = $sth->fetchrow_hashref()) { + Golem::debug_sql($sql, \@bound_values); + Golem::die("more than 1 record fetched with should-be-unique lookup") + if $existing_row; + + $existing_row = $r; + } + + # check that existing record differs somehow from record to be written + my $records_differ = 0; + while (my ($k, $v) = each %{$existing_row}) { + if (Golem::is_data_field($table_name, $k)) { + + # what a mess! + utf8::decode($record_hashref->{$k}); + utf8::decode($v); + + if ( + ($record_hashref->{$k} && $v && $v ne $record_hashref->{$k}) || + (! $record_hashref->{$k} && $v) || + ($record_hashref->{$k} && ! $v) + ) { + + Golem::debug_sql("in-memory [$table_name] object field [$k] differs: [" . + ($record_hashref->{$k} ? $record_hashref->{$k} : "") . " + ] -- [" . + ($v ? $v : "") . + "]"); + + $records_differ = 1; + last; + } + } + } + + # don't update database if that wouldn't actually + # change any data; we should save A LOT of time here + # + return $dbh unless $records_differ; + + @bound_values = (); + $sql = ""; + while (my ($o, $v) = each(%{$record_hashref})) { + # $record_hashref might contain more fields than present in database. + # we only choose those which are in db + if ($table_fields->{$o} && Golem::is_data_field($table_name, $o)) { + if ($table_fields->{$o}->{'Type'} eq 'timestamp' && $record_hashref->{$o} && $record_hashref->{$o} != 0) { + Golem::die("Programmer error: __update got hashref with invalid data for $table_name.$o (should be unixtime)") + unless $record_hashref->{$o} =~ /^[0-9]+$/o; + + $sql = $sql . " `$o` = FROM_UNIXTIME(?),"; + } + else { + $sql = $sql . " `$o` = ?,"; + } + push @bound_values, $record_hashref->{$o}; + } + } + chop($sql); + + $sql = "UPDATE `$table_name` SET " . $sql . " WHERE "; + foreach my $f (@{$unique_fields_arrayref}) { + $sql .= " `$f` = ? and "; + push @bound_values, $record_hashref->{$f}; + } + # remove last "and " + chop($sql); + chop($sql); + chop($sql); + chop($sql); + + Golem::debug_sql($sql, \@bound_values); + + $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + if ($dbh->err) { + Golem::do_log("error executing: $sql; bound values: " . join(",", @bound_values), {"stderr" => 1}); + } + + return $dbh; +} + + +sub __delete { + my ($table_name, $record_hashref, $opts) = @_; + + Golem::die("Severe programmer error: __delete expects table name as first parameter!") + unless $table_name; + Golem::die("Severe programmer error: __delete expects record hashref as second parameter!") + unless ref($record_hashref) eq 'HASH'; + + $opts = {} unless ref($opts) eq 'HASH'; + + my $dbh; + if ($opts->{'dbh'}) { + $dbh = $opts->{'dbh'}; + } + else { + $dbh = Golem::get_db(); + } + + my $sth; + + my $table = Golem::get_schema_table($table_name); + my $table_fields = $table->{'fields'}; + my $unique_fields_arrayref = [keys %{$table->{'primary_key'}}]; + + if ($opts->{'unique_fields'}) { + $unique_fields_arrayref = $opts->{'unique_fields'}; + } + + my @bound_values = (); + my $sql = "DELETE FROM `$table_name` WHERE "; + + foreach my $f (@{$unique_fields_arrayref}) { + $sql .= " `$f` = ? and "; + push @bound_values, $record_hashref->{$f}; + } + # remove last "and " + chop($sql); + chop($sql); + chop($sql); + chop($sql); + + $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + if ($dbh->err) { + Golem::do_log("error executing: $sql; bound values: " . join(",", @bound_values), {"stderr" => 1}); + } + + return $dbh; +} + + +1; diff --git a/local/cgi-bin/Golem/loglib.pl b/local/cgi-bin/Golem/loglib.pl new file mode 100644 index 0000000..813e889 --- /dev/null +++ b/local/cgi-bin/Golem/loglib.pl @@ -0,0 +1,197 @@ +#!/usr/bin/perl -w +# +# Logging related routines +# + + +package Golem; +use strict; + +use Golem; +use Data::Dumper; + + +sub dumper { + my ($v) = @_; + + return Dumper($v); +} + +sub debug_sql { + my ($text, $bound_values, $opts) = @_; + + if ($Golem::debug_sql) { + $opts = {} unless $opts; + + $text = "SQL: [" . ($text ? $text : "") . "]"; + + if ($bound_values && ref($bound_values) eq 'ARRAY') { + $text .= " bound_values [" . Golem::safe_join(",", @{$bound_values}) . "]"; + } + + if ($opts->{'stderr'}) { + print STDERR localtime() . " " . $text . "\n"; + } + else { + print localtime() . " " . $text . "\n"; + } + } +} + +sub debug2 { + my ($text, $opts) = @_; + + if ($Golem::debug2) { + debug($text, $opts); + } +} + +sub debug { + my ($text, $opts) = @_; + + $opts = {} unless $opts; + + if ($Golem::debug) { + my $stamp = localtime() . ": "; + + utf8::encode($text) if utf8::is_utf8($text); + + if ($opts->{'stderr'}) { + if (ref($text)) { + print STDERR join("", map { "$stamp$_\n" } Dumper($text)); + } + else { + print STDERR $stamp . ($text ? $text : "") . "\n"; + } + } + else { + if (ref($text)) { + print join("", map { "$stamp$_\n" } Dumper($text)); + } + else { + print $stamp . ($text ? $text : "") . "\n"; + } + } + } +} + +# safe_open and safe_close are copied +# from ps_farm.pm (should be one library actually) +sub safe_open { + my ($filename, $mode, $timeout) = @_; + + $timeout = 30 unless $timeout; + $mode = "open" unless $mode; + + if ($mode eq "overwrite" || $mode eq ">") { + $mode = ">"; + } + elsif ($mode eq "append" || $mode eq ">>") { + $mode = ">>"; + } + else { + $mode = ""; + } + + my $fh; + my $i=0; + while (! open($fh, "${mode}${filename}")) { + if ($i > $timeout) { + print STDERR "Unable to open $filename\n"; + return 0; + } + + print STDERR "still trying to open $filename\n"; + $i = $i + 1; + sleep 1; + } + + while (! flock($fh, 2)) { + if ($i > $timeout) { + print STDERR "Unable to lock $filename\n"; + return 0; + } + + print STDERR "still trying to lock $filename\n"; + $i = $i + 1; + sleep 1; + } + + my $fh1; + if (!open($fh1, "${mode}${filename}")) { + $i = $i + 1; + + if ($i > $timeout) { + print STDERR "Unable to open and lock $filename\n"; + return 0; + } + + print STDERR "Locked $filename, but it's gone. Retrying...\n"; + return safe_open($filename, $mode, $timeout - 1); + } + else { + close($fh1); + return $fh; + } +} + +sub safe_close { + my ($fh) = @_; + return flock($fh, 8) && close($fh); +} + +sub do_log { + my ($message, $opts) = @_; + + my $module; + my $stderr = 0; + + if (ref($opts) eq 'HASH') { + if ($opts->{'module'}) { + $module = "[$opts->{'module'}] "; + } + if ($opts->{'stderr'}) { + $stderr = $opts->{'stderr'}; + } + } + else { + $module = $opts; + $module = "[$module] " if $module; + } + + $message = "" unless $message; + + utf8::encode($message) if utf8::is_utf8($message); + + $module = "[" . $0 . "] " unless $module; + + my $message_eol = chop($message); + + my $message_formatted = + localtime() . " " . $module . + $message . + $message_eol . + ($message_eol eq "\n" ? "" : "\n"); + + if ($stderr) { + print STDERR $message_formatted; + } + elsif ($Golem::debug) { + print $message_formatted; + } + + if (defined($Golem::LOG)) { + my $fh = safe_open($Golem::LOG, ">>"); + Golem::die ("Unable to open $Golem::LOG\n") unless $fh; +# binmode($fh, ":utf8"); + print $fh $message_formatted; + safe_close($fh); + } + else { + print STDERR "No Golem::LOG is configured. Logging to STDERR\n"; + print STDERR $message_formatted; + } +} + + +1; diff --git a/local/cgi-bin/Golem/netlib.pl b/local/cgi-bin/Golem/netlib.pl new file mode 100644 index 0000000..3e74969 --- /dev/null +++ b/local/cgi-bin/Golem/netlib.pl @@ -0,0 +1,330 @@ +#!/usr/bin/perl -w +# +# networking related routines +# + + +package Golem; +use strict; + +use Golem; + +sub get_external_ipinfo { + my ($ip) = @_; + + return undef unless $ip && $Golem::noc_nets_cgi; + + my $ipinfo; + my @net_info; + + my $wget_options = ""; + $wget_options = "--timeout=${Golem::noc_nets_cgi_timeout}" + if $Golem::noc_nets_cgi_timeout; + + open(NOCNET,"wget $wget_options -q -O - ${Golem::noc_nets_cgi}?name=$ip |"); + + Golem::debug("wget $wget_options -q -O - ${Golem::noc_nets_cgi}?name=$ip |"); + + my $line; + while($line=) { + if ($line=~/^/) { + chomp($line); + $line =~ s/<\/td>/\|/g; + $line =~ s/(||<\/tr>|<\/td>)//g; + @net_info= split(/\|/,$line,5); + } + } + close(NOCNET); + + if (@net_info) { + $ipinfo->{'ip'} = $net_info[0]; + $ipinfo->{'subnet'} = $net_info[1]; + $ipinfo->{'router'} = $net_info[2]; + $ipinfo->{'iface'} = $net_info[3]; + + $ipinfo->{'vlan'} = $ipinfo->{'iface'}; + $ipinfo->{'vlan'} =~ /(\d+)/; + $ipinfo->{'vlan'} = $1; + + $ipinfo->{'router_if_addr'} = $net_info[4]; + } + + return $ipinfo; +} + +# --- ghetto code +sub int2maskpart { + my ($i) = @_; + return "0" unless defined($i); + + my $j = 0; + my $bits = ""; + while ($j < 8) { + if ($i <= $j) { + $bits .= "0"; + } + else { + $bits .= "1"; + } + $j++; + } + return oct("0b" . $bits); +} + + +sub mask2netmask { + my ($j) = @_; + + my @ip; + my $i; + for ($i = 1; $i <= int($j / 8); $i++) { + push @ip, int2maskpart(8); + } + while ($i < 5) { + push @ip, int2maskpart($j % 8); + $j = 0; + $i++; + } + + return join(".", @ip); +} + + +# convert string representation of ipv4 address into integer +sub ipv4_str2int { + my ($ip_string) = @_; + + if ($ip_string =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) { + return (16777216 * $1) + (65536 * $2) + (256 * $3) + $4; + } + else { + return 0; + } +} + +# convert integer representation of ipv4 address into string +sub ipv4_int2str { + my ($ip_int) = @_; + + if ($ip_int >= 0 && $ip_int <= 4294967295) { + my $w = ($ip_int / 16777216) % 256; + my $x = ($ip_int / 65536) % 256; + my $y = ($ip_int / 256) % 256; + my $z = $ip_int % 256; + + return $w . "." . $x . "." . $y . "." . $z; + } + else { + return 0; + } +} + +# /24 -> +255 +# /27 -> +31 +# /28 -> +15 +# /29 -> +7 +sub ipv4_mask2offset { + my ($mask) = @_; + $mask ||= 0; + my $offset = 2 ** (32 - $mask); + return $offset - 1; +} + +sub get_net { + my ($ip, $mask, $opts) = @_; + + Golem::trim(\$ip); + + Golem::die("Programmer error: get_net expects net and mask") + unless + ($ip && $mask && Golem::is_digital($mask)) || + ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/); + + if ($ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})$/o) { + $ip = ipv4_str2int($1); + $mask = $2; + } + elsif ($ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/o) { + $ip = ipv4_str2int($1); + } + + my $dbh = Golem::get_db(); + my $sth = $dbh->prepare("SELECT * FROM net_v4 WHERE ip = ? and mask = ?"); + $sth->execute($ip, $mask); + my $net = $sth->fetchrow_hashref(); + $sth->finish(); + + if ($net->{'id'}) { + return Golem::get_net_by_id($net->{'id'}, $opts); + } + else { + return 0; + } +} + +sub get_net_by_id { + my ($id, $opts) = @_; + + Golem::die("Programmer error: get_net_by_id expects network id") + unless $id; + + $opts = {} unless $opts; + + my $dbh = Golem::get_db(); + my $sth = $dbh->prepare("SELECT * FROM net_v4 WHERE id = ?"); + + $sth->execute($id); + + my $r = $sth->fetchrow_hashref(); + if ($r->{'id'}) { + $r->{'ip_str'} = Golem::ipv4_int2str($r->{'ip'}); + $r->{'net_with_mask'} = $r->{'ip_str'} . "/" . $r->{'mask'}; + if ($r->{'name'} =~ /VLAN([\d]+)/o) { + $r->{'vlan'} = $1; + } + else { + $r->{'vlan'} = ""; + } + + if ($opts->{'with_props'} || $opts->{'with_all'}) { + $r = Golem::load_props("net_v4", $r); + } + + return $r; + } + else { + return 0; + } +} + +sub insert_net { + my ($net) = @_; + + Golem::die("Programmer error: insert_net expects net object") + unless $net && ($net->{'ip_str'} || $net->{'ip'}) && + $net->{'mask'} && $net->{'name'}; + + if ($net->{'ip_str'}) { + $net->{'ip'} = Golem::ipv4_str2int($net->{'ip_str'}); + } + + my $enet = Golem::get_net($net->{'ip'}, $net->{'mask'}); + return Golem::err("net already exists [$enet->{'ip_str'}/$enet->{'$mask'} ($enet->{'id'})]") + if $enet; + + my $dbh = Golem::__insert("net_v4", $net); + return Golem::err($dbh->errstr, $net) + if $dbh->err; + + $net->{'id'} = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + + return Golem::get_net_by_id($net->{'id'}); +} + +sub save_net { + my ($net) = @_; + + Golem::die("Programmer error: save_net expects net object") + unless $net && $net->{'id'} && + ($net->{'ip_str'} || $net->{'ip'}) && + $net->{'mask'} && $net->{'name'}; + + if ($net->{'ip_str'}) { + $net->{'ip'} = Golem::ipv4_str2int($net->{'ip_str'}); + } + + my $enet = Golem::get_net($net->{'ip'}, $net->{'mask'}, {"with_all" => 1}); + + if ($enet) { + my $dbh = Golem::__update("net_v4", $net); + return Golem::err($dbh->errstr, $net) + if $dbh->err; + + $net = Golem::save_props("net_v4", $net); + } + else { + return Golem::insert_net($net); + } + + return $net; +} + +sub delete_net { + my ($net) = @_; + + Golem::die("Programmer error: delete_net expects net object") + unless $net && $net->{'id'}; + + my $dbh = Golem::get_db(); + + Golem::unset_row_tag("net_v4", $net->{'id'}); + $dbh->do("DELETE from net_v4prop where net_v4id = ?", undef, $net->{'id'}); + $dbh->do("DELETE from net_v4propblob where net_v4id = ?", undef, $net->{'id'}); + + $dbh->do("DELETE FROM net_v4 WHERE net_v4.id = ?", undef, $net->{'id'}); + return Golem::err($dbh->errstr, $net) + if $dbh->err; + + return {}; +} + +sub get_containing_net { + my ($ip, $opts) = @_; + + Golem::die("Programmer error: get_containing_net expects ip address") + unless $ip; + + Golem::trim(\$ip); + if ($ip =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/o) { + $ip = Golem::ipv4_str2int($1); + } + + my $dbh = Golem::get_db(); + + # choose nearest (by ip desc) and smallest (by mask desc) known network + my $sth = $dbh->prepare("SELECT * FROM net_v4 WHERE ip < ? and mask <> 32 + order by ip desc, mask desc"); + + $sth->execute($ip); + + my $net; + + while(my $r = $sth->fetchrow_hashref()) { + # choose first network that includes tested ip address if any + if ($r->{'ip'} + ipv4_mask2offset($r->{'mask'}) ge $ip) { + return Golem::get_net_by_id($r->{'id'}, $opts); + } + } + + return 0; +} + +sub get_net_by_vlan { + my ($vlan, $opts) = @_; + + Golem::die("Programmer error: get_net_by_vlan expects vlan name") + unless $vlan; + + $vlan =~ s/vlan//go; + $vlan =~ s/\s//go; + + my $dbh = Golem::get_db(); + my $sth = $dbh->prepare("SELECT * FROM net_v4 WHERE mask <> 32 and name like ? order by name"); + $sth->execute("VLAN${vlan}%"); + + while (my $r = $sth->fetchrow_hashref()) { + if ($r->{'name'} =~ /VLAN${vlan}\s/o) { + return Golem::get_net($r->{'ip'}, $r->{'mask'}, $opts); + } + } + + return 0; +} + +sub is_ipv4 { + my ($str) = @_; + return $str =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/o; +} + + +1; diff --git a/local/cgi-bin/Golem/proplib.pl b/local/cgi-bin/Golem/proplib.pl new file mode 100644 index 0000000..98a4eb3 --- /dev/null +++ b/local/cgi-bin/Golem/proplib.pl @@ -0,0 +1,393 @@ +#!/usr/bin/perl -w +# +# Properties manipulation routines +# +# +# This is an object property library which +# implements DB -> MEMORY (load_props) +# and MEMORY -> DB (save_props) transition +# of object properties +# +# Object is defined as a record in some TABLE +# (called owner). To be able to use properties +# for the given TABLE you should create +# another two tables: TABLEprop and TABLEpropblob +# +# Example for host object: +# +# CREATE TABLE `hostprop` ( +# `hostid` int(11) NOT NULL, +# `propid` smallint(6) NOT NULL default '0', +# `propseq` int(11) NOT NULL default '0', +# `value` varchar(1024) default NULL, +# PRIMARY KEY (`hostid`,`propid`,`propseq`), +# KEY `prop` (`propid`) +# ) ENGINE=InnoDB DEFAULT CHARSET=utf8 +# +# CREATE TABLE `hostpropblob` ( +# `hostid` int(11) NOT NULL, +# `propid` smallint(6) NOT NULL default '0', +# `propseq` int(11) NOT NULL default '0', +# `value` blob, +# PRIMARY KEY (`hostid`,`propid`,`propseq`), +# KEY `prop` (`propid`) +# ) ENGINE=InnoDB DEFAULT CHARSET=utf8 +# +# After that you should create "allowed" properties +# for the owner using `gconsole.pl --create-proplist` +# +# You could see all the defined properties for the owner +# using gconsole.pl --list-proplist OWNER +# +# +# For the owner (tables) which primary key is not simple +# id auto_increment (as in the example above) the following +# TABLEprop and TABLEpropblob structure should be used: +# + +package Golem; +use strict; + +use Golem; + +use Storable; + + +# check that given property owner is valid +# currently there are two valid property owners: host, user +# +sub check_prop_owner { + my ($owner) = @_; + + Golem::die("Programmer error: check_prop_owner got empty prop owner") + unless $owner; + + my $props = { + "eventhistory" => 1, + "host" => 1, + "user" => 1, + "net_v4" => 1, + }; + + Golem::die("Programmer error: not valid property owner [$owner]") + unless defined($props->{$owner}); +} + +# get property definition record(s) from database +# for the specified owner +# +sub get_proplist { + my ($owner, $hpname) = @_; + + Golem::die("Programmer error: get_proplist expects at least owner") + unless $owner; + + Golem::check_prop_owner($owner); + + my $dbh = Golem::get_db(); + my $sth; + my $ret; + + if ($hpname) { + $sth = $dbh->prepare("SELECT * FROM proplist WHERE owner = ? and name = ?"); + $sth->execute($owner, $hpname); + $ret = $sth->fetchrow_hashref(); + $ret = 0 unless $ret->{'id'}; + } + else { + $sth = $dbh->prepare("SELECT * FROM proplist where owner = ?"); + $sth->execute($owner); + while (my $r = $sth->fetchrow_hashref()) { + $ret->{$r->{'name'}} = $r; + } + } + + return $ret; +} + +sub create_proplist { + my ($owner, $op) = @_; + + Golem::die("Programmer error: create_proplist expects at least owner and property name") + unless $owner && $op && $op->{'name'}; + + Golem::check_prop_owner($owner); + + my $eop = Golem::get_proplist($owner, $op->{'name'}); + Golem::die("proplist record already exists [$eop->{'name'} ($eop->{'id'})]") + if $eop; + + $op->{'owner'} = $owner; + + my $dbh = Golem::__insert("proplist", $op); + Golem::die("Error creating proplist: " . $dbh->errstr, $op) + if $dbh->err; + + $op->{'id'} = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + + Golem::do_log("new proplist record: [$op->{'owner'}/$op->{'name'}] ($op->{'id'})"); + + return $op; +} + +sub delete_proplist { + my ($owner, $op) = @_; + + Golem::die("Programmer error: delete_proplist expects proplist record") + unless $op && $op->{'id'} && $op->{'name'}; + + Golem::check_prop_owner($owner); + + my $eop = Golem::get_proplist($owner, $op->{'name'}); + + return Golem::err("delete_proplist: invalid proplist record") + unless $eop; + + my $dbh = Golem::get_db(); + my $objs_with_prop = + $dbh->selectrow_array("select count(*) from ${owner}prop where propid = ?", undef, $op->{'id'}) + + $dbh->selectrow_array("select count(*) from ${owner}propblob where propid = ?", undef, $op->{'id'}) + ; + + return Golem::err("delete_proplist: unable to delete proplist record; $objs_with_prop records are using it") + if $objs_with_prop; + + $dbh->do("delete from proplist where id = ?", undef, $op->{'id'}); + + return Golem::err("error while deleting from proplist: " . $dbh->errstr) + if $dbh->err; + + return {}; +} + +# read object properties for the given owner +# (exactly matches table name) +# +sub load_props { + my ($owner, $o) = @_; + + Golem::die("Programmer error: load_props expects owner name and object") + unless $owner && ref($o); + + Golem::check_prop_owner($owner); + + my $table = Golem::get_schema_table($owner); + my $pk = $table->{'primary_key'}; + + my $dbh = Golem::get_db(); + my $sth; + + $o->{'props'}->{'data'} = {}; + + foreach my $t ("${owner}prop", "${owner}propblob") { + my $sql = "select * from $t inner join proplist on proplist.id = $t.propid WHERE 1 "; + my @bound_values = (); + while (my ($pk_field, $dummy) = each %{$table->{'primary_key'}}) { + if ($pk_field eq 'id') { + $sql .= " and `${owner}id` = ? "; + } + else { + $sql .= " and `$pk_field` = ? "; + } + + Golem::die("Programmer error: load_props got empty value for primary key field [$pk_field] of table [$owner]") + unless defined($o->{$pk_field}); + + push (@bound_values, $o->{$pk_field}); + } + $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + while (my $r = $sth->fetchrow_hashref()) { + my $v; + + if ($t eq "${owner}prop") { + $v = $r->{'value'}; + } + if ($t eq "${owner}propblob") { +# print STDERR Storable::thaw($r->{'value'}); + $v = Storable::thaw($r->{'value'}); + } + + if ($r->{'datatype'} eq 'array' || $r->{'datatype'} eq 'arrayblob') { + $o->{'props'}->{'data'}->{$r->{'name'}} = [] + unless defined($o->{'props'}->{'data'}->{$r->{'name'}}); + + push (@{$o->{'props'}->{'data'}->{$r->{'name'}}}, $v); + } + else { + $o->{'props'}->{'data'}->{$r->{'name'}} = $v; + } + } + } + + $o->{'props'}->{'loaded'} = 1; + + return $o; +} + +# save properties from memory into database +# checks that properties were loaded using load_props +# (for advanced users: "loaded" is the key of check, +# it is set by load_props which could be emulated) +# +sub save_props { + my ($owner, $o) = @_; + + Golem::die("Programmer error: save_props expects owner name and object") + unless $owner && ref($o); + + Golem::check_prop_owner($owner); + + return Golem::err("Programmer error: save_props should be called only after calling load_props") + unless $o->{'props'}->{'loaded'}; + + my $table = Golem::get_schema_table($owner); + my $pk = $table->{'primary_key'}; + + my $dbh = Golem::get_db(); + + while (my ($k, $v) = each %{$o->{'props'}->{'data'}}) { + my $op = Golem::get_proplist($owner, $k); + + unless ($op) { + Golem::do_log("Non-existent $owner property name [$k], skipping.", {"stderr" => 1}); + next; + } + + my $do_save = sub { + my ($value, $seq) = @_; + + $seq = 0 unless defined($seq); + + my $tpref = ""; + my $db_value; + + if ($op->{'datatype'} eq 'blob' || $op->{'datatype'} eq 'arrayblob') { + $db_value = Storable::nfreeze($value); + $tpref = "blob"; + } + else { + $db_value = $value; + + if ($op->{'datatype'} eq 'bool') { + $db_value = $value ? 1 : 0; + } + } + + my $prop_ref = { + "propid" => $op->{'id'}, + "propseq" => $seq, + "value" => $db_value, + }; + + while (my ($pk_field, $dummy) = each %{$table->{'primary_key'}}) { + if ($pk_field eq 'id') { + $prop_ref->{"${owner}id"} = $o->{$pk_field}; + } + else { + $prop_ref->{$pk_field} = $o->{$pk_field}; + } + } + + $dbh = Golem::__update("${owner}prop${tpref}", $prop_ref, {"create_nonexistent" => 1}); + Golem::die("save_props: error while replacing ${owner} props: " . $dbh->errstr) + if $dbh->err; + }; + + if ($op->{'datatype'} eq 'array' || $op->{'datatype'} eq 'arrayblob') { + my $i = 0; + foreach my $array_value (@{$v}) { + $do_save->($array_value, $i); + $i = $i + 1; + } + + my $tpref = ""; + if ($op->{'datatype'} eq 'arrayblob') { + $tpref = "blob"; + } + + my $sql = "delete from ${owner}prop${tpref} where 1 "; + my @bound_values = (); + while (my ($pk_field, $dummy) = each %{$table->{'primary_key'}}) { + if ($pk_field eq 'id') { + $sql .= " and ${owner}id = ? "; + } + else { + $sql .= " and $pk_field = ? "; + } + push (@bound_values, $o->{$pk_field}); + } + $sql .= " and propid = ? and propseq >= ?"; + push (@bound_values, $op->{'id'}); + push (@bound_values, $i); + + my $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + } + else { + $do_save->($v, 0); + } + } + + return $o; +} + +# deletes object property if no objects +# are associated with the property +# +# input +# owner type (for the listing see check_prop_owner) +# object (with $obj->{'id'} defined) +# property name to delete +# +sub delete_prop { + my ($owner, $obj, $propname) = @_; + + Golem::die("Programmer error: delete_prop expects owner and object") + unless $owner && ref($obj); + + Golem::check_prop_owner($owner); + + my $op = Golem::get_proplist($owner, $propname); + return Golem::err("delete_prop: invalid propname [$propname]") + unless $op; + + my $table = Golem::get_schema_table($owner); + my $pk = $table->{'primary_key'}; + + my $dbh = Golem::get_db(); + + my $tpref = ""; + if ($op->{'datatype'} eq 'blob' || $op->{'datatype'} eq 'blobarray') { + $tpref = "blob"; + } + + my $sql = "delete from ${owner}prop${tpref} where 1 "; + my @bound_values = (); + while (my ($pk_field, $dummy) = each %{$table->{'primary_key'}}) { + if ($pk_field eq 'id') { + $sql .= " and ${owner}id = ? "; + } + else { + $sql .= " and $pk_field = ? "; + } + push (@bound_values, $obj->{$pk_field}); + } + $sql .= " and propid = ? "; + push (@bound_values, $op->{'id'}); + + my $sth = $dbh->prepare($sql); + Golem::sth_bind_array($sth, \@bound_values); + $sth->execute(); + + Golem::die("delete_prop: error deleting $owner [$obj->{'id'}] property [$propname]: " . $dbh->errstr) + if $dbh->err; + + return {}; +} + + +1; diff --git a/local/cgi-bin/Golem/textlib.pl b/local/cgi-bin/Golem/textlib.pl new file mode 100644 index 0000000..0d82c8a --- /dev/null +++ b/local/cgi-bin/Golem/textlib.pl @@ -0,0 +1,222 @@ +#!/usr/bin/perl -w +# +# Text manipulation routines +# +# parts courtesy of LiveJournal.org +# + +package Golem; +use strict; + +use Golem; + +# +# name: LJ::decode_url_string +# class: web +# des: Parse URL-style arg/value pairs into a hash. +# args: buffer, hashref +# des-buffer: Scalar or scalarref of buffer to parse. +# des-hashref: Hashref to populate. +# returns: boolean; true. +# +sub decode_url_string +{ + my $a = shift; + my $buffer = ref $a ? $a : \$a; + my $hashref = shift; # output hash + my $keyref = shift; # array of keys as they were found + + my $pair; + my @pairs = split(/&/, $$buffer); + @$keyref = @pairs; + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $hashref->{$name} .= $hashref->{$name} ? ",$value" : $value; + } + return 1; +} + + +# +# name: LJ::ehtml +# class: text +# des: Escapes a value before it can be put in HTML. +# args: string +# des-string: string to be escaped +# returns: string escaped. +# +sub ehtml +{ + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[&\"\'<>]/o; + + # this is faster than doing one substitution with a map: + my $a = $_[0]; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +sub esql { + return $_[0] unless $_[0] =~ /[\'\"\\]/o; + + my $a = $_[0]; + $a =~ s/\'//go; + $a =~ s/\"//go; + $a =~ s/\\//go; + return $a; +} + +# +# name: LJ::is_ascii +# des: checks if text is pure ASCII. +# args: text +# des-text: text to check for being pure 7-bit ASCII text. +# returns: 1 if text is indeed pure 7-bit, 0 otherwise. +# +sub is_ascii { + my $text = shift; + return ($text !~ m/[^\x01-\x7f]/o); +} + +sub is_digital { + my $text = shift; + return ( $text =~ /\d+/o ); +} + +# tests if there's data in configuration file string: +# i.e. if it's not empty and is not commented +# +sub have_data { + my ($line) = @_; + + if ($line =~ /^\s*#/o || $line =~ /^[\s]*$/o) { + return 0; + } + + return 1; +} + +# fixes user input strings (passed as array of references), +# currently only trims +# +# used when importing: +# - 1C data +# +sub fix_input { + my (@i) = @_; + + foreach my $v (@i) { + Golem::die("Programmer error: check_input expects only scalar references") + unless ref($v) eq 'SCALAR'; + + Golem::do_log("Inaccurate spacing trimmed [$$v]", {"stderr" => 1}) + if Golem::trim($v); + } +} + +# given scalar string trims white space +# at the beginning and in the end and +# returns trimmed string +# +# given scalar reference trims white space +# at the beginning and in the end and +# returns true if trimming occured and false otherwise +# NOTE: modifies the original string +# reference to which was given as input parameter +sub trim { + my ($string) = @_; + + if (ref($string) eq 'SCALAR') { + my $tstr = $$string; + + return 0 if $tstr eq ''; # nothing to trim, do not waste cpu cycles + + $tstr =~ s/^\s+//so; + $tstr =~ s/\s+$//so; + + if ($tstr ne $$string) { + $$string = $tstr; + return 1; + } + else { + return 0; + } + } + else { + return "" if $string eq ''; # nothing to trim, do not waste cpu cycles + + $string =~ s/^\s+//so; + $string =~ s/\s+$//so; + return $string; + } +} + +# same as standard perl join except for it doesn't +# output "uninitialized value in join" when joining +# list with undef values; and we use those lists +# when binding params to DBI query +# +sub safe_join { + my ($delimiter, @arr) = @_; + + my $joined_text = ""; + $delimiter = "" unless $delimiter; + + foreach my $bv (@arr) { + $joined_text .= ($bv ? $bv : "") . $delimiter; + } + + my $i; + for ($i = 0; $i < length($delimiter); $i++) { + chop($joined_text); + } + + return $joined_text; +} + +# should be used when you need to concatenate string +# which might be undefined and you want empty string ("") +# instead of perl warnings about uninitialized values +# +sub safe_string { + my ($str) = @_; + + if ($str) { + return $str; + } + else { + return ""; + } +} + +# inserts $symbol every $range characters in a $line +sub div_line { + my ($line, $range, $symbol) = @_; + + Golem::die("Programmer error: div_line expects at least string") + unless $line; + + $range = 70 unless $range; + $symbol = ' ' unless $symbol; + + my $result = ''; + for (my $i = 0 ; $i <= int(length($line)/$range) ; $i++) { + $result .= substr($line,$i*$range,$range) . $symbol; + } + chop($result); + + return $result; +} + + +1; diff --git a/local/cgi-bin/HTMLCleaner.pm b/local/cgi-bin/HTMLCleaner.pm new file mode 100644 index 0000000..2db7836 --- /dev/null +++ b/local/cgi-bin/HTMLCleaner.pm @@ -0,0 +1,207 @@ +#!/usr/bin/perl +# + +package HTMLCleaner; + +use strict; +use base 'HTML::Parser'; +use CSS::Cleaner; + +sub new { + my ($class, %opts) = @_; + + my $p = new HTML::Parser('api_version' => 3); + $p->handler('start' => \&start, 'self, tagname, attr, attrseq, text' ); + $p->handler('end' => \&end, 'self, tagname' ); + $p->handler('text' => \&text, 'self, text' ); + $p->handler('declaration' => \&decl, 'self, tokens' ); + + $p->{'output'} = $opts{'output'} || sub {}; + $p->{'cleaner'} = CSS::Cleaner->new; + $p->{'valid_stylesheet'} = $opts{'valid_stylesheet'} || sub { 1 }; + $p->{'allow_password_input'} = $opts{'allow_password_input'} || 0; + + bless $p, $class; +} + +my %bad_attr = (map { $_ => 1 } + qw(datasrc datafld)); + +my %eat_tag = (map { $_ => 1 } + qw(script iframe object applet embed param)); + +my @eating; # push tagname whenever we start eating a tag + +sub start { + my ($self, $tagname, $attr, $seq, $text) = @_; + $tagname =~ s/can($meth) + or return 1; # don't clean, if no element-specific cleaner method + return $code->($self, $seq, $attr); + }; + return if !$@ && !$clean_res; + + my $ret = "<$tagname"; + foreach (@$seq) { + if ($_ eq "/") { $slashclose = 1; next; } + next if $bad_attr{lc($_)}; + next if /^on/i; + next if /(?:^=)|[\x0b\x0d]/; + + if ($_ eq "style") { + $attr->{$_} = $self->{cleaner}->clean_property($attr->{$_}); + } + + if ($tagname eq 'input' && $_ eq 'type' && $attr->{'type'} =~ /^password$/i && !$self->{'allow_password_input'}) { + delete $attr->{'type'}; + } + + my $nospace = $attr->{$_}; + $nospace =~ s/[\s\0]//g; + + # IE is brain-dead and lets javascript:, vbscript:, and about: have spaces mixed in + if ($nospace =~ /(?:(?:(?:vb|java)script)|about):/i) { + delete $attr->{$_}; + } + $ret .= " $_=\"" . ehtml($attr->{$_}) . "\""; + } + $ret .= " /" if $slashclose; + $ret .= ">"; + + if ($tagname eq "style") { + $self->{'_eating_style'} = 1; + $self->{'_style_contents'} = ""; + } + + $self->{'output'}->($ret); +} + +sub CLEAN_meta { + my ($self, $seq, $attr) = @_; + + # don't allow refresh because it can refresh to javascript URLs + # don't allow content-type because they can set charset to utf-7 + # why do we even allow meta tags? + my $equiv = lc $attr->{"http-equiv"}; + if ($equiv) { + $equiv =~ s/[\s\x0b]//; + return 0 if $equiv =~ /refresh|content-type|link|set-cookie/; + } + return 1; +} + +sub CLEAN_link { + my ($self, $seq, $attr) = @_; + + if ($attr->{rel} =~ /\bstylesheet\b/i) { + my $href = $attr->{href}; + return 0 unless $href =~ m!^https?://([^/]+?)(/.*)$!; + my ($host, $path) = ($1, $2); + + my $rv = $self->{'valid_stylesheet'}->($href, $host, $path); + if ($rv == 1) { + return 1; + } + if ($rv) { + $attr->{href} = $rv; + return 1; + } + return 0; + } + + # Allow blank tags through so RSS S2 styles can work again without the 'rel="alternate"' hack + return 1 if (keys( %$attr ) == 0); + + return 1 if $attr->{rel} =~ /^(?:service|openid)\.\w+$/; + my %okay = map { $_ => 1 } (qw(icon shortcut alternate next prev index made start search top help up author edituri file-list previous home contents bookmark chapter section subsection appendix glossary copyright child)); + return 1 if $okay{lc($attr->{rel})}; + + # Allow link tags with only an href tag. This is an implied rel="alternate" + return 1 if (exists( $attr->{href} ) and (keys( %$attr ) == 1)); + + # Allow combinations of rel attributes through as long as all of them are valid, most notably "shortcut icon" + return 1 unless grep { !$okay{$_} } split( /\s+/, $attr->{rel} ); + + # unknown link tag + return 0; +} + +sub end { + my ($self, $tagname) = @_; + if (@eating) { + pop @eating if $eating[-1] eq $tagname; + return; + } + + if ($self->{'_eating_style'}) { + $self->{'_eating_style'} = 0; + $self->{'output'}->($self->{cleaner}->clean($self->{'_style_contents'})); + } + + $self->{'output'}->(""); +} + +sub text { + my ($self, $text) = @_; + return if @eating; + + if ($self->{'_eating_style'}) { + $self->{'_style_contents'} .= $text; + return; + } + + # this string is magic [hack]. (See $out_straight in + # cgi-bin/LJ/S2.pm) callers can print "" to HTML::Parser + # just to make it flush, since HTML::Parser has no + # ->flush_outstanding text tag. + return if $text eq ""; + + # the parser gives us back text whenever it's confused + # on really broken input. sadly, IE parses really broken + # input, so let's escape anything going out this way. + $self->{'output'}->(eangles($text)); +} + +sub decl { + my ($self, $tokens) = @_; + $self->{'output'}->(""); +} + +sub eangles { + my $a = shift; + $a =~ s//>/g; + return $a; +} + +sub ehtml { + my $a = shift; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +1; diff --git a/local/cgi-bin/LJ/Auth.pm b/local/cgi-bin/LJ/Auth.pm new file mode 100644 index 0000000..3f63aa4 --- /dev/null +++ b/local/cgi-bin/LJ/Auth.pm @@ -0,0 +1,124 @@ +# This is the LiveJournal Authentication module. +# It contains useful authentication methods. + +package LJ::Auth; +use strict; +use Digest::HMAC_SHA1 qw(hmac_sha1_hex); +use Digest::SHA1 qw(sha1_hex); +use Carp qw (croak); + +# Generate an auth token for AJAX requests to use. +# Arguments: ($remote, $action, %postvars) +# $remote: remote user object +# $uri: what uri this is for +# %postvars: the expected post variables +# Returns: Auth token good for the current hour +sub ajax_auth_token { + my ($class, $remote, $uri, %postvars) = @_; + + $remote = LJ::want_user($remote) || LJ::get_remote(); + + croak "No URI specified" unless $uri; + + my ($stime, $secret) = LJ::get_secret(); + my $postvars = join('&', map { $postvars{$_} } sort keys %postvars); + my $remote_session_id = $remote && $remote->session ? $remote->session->id : LJ::UniqCookie->current_uniq; + my $remote_userid = $remote ? $remote->id : 0; + + my $chalbare = qq {ajax:$stime:$remote_userid:$remote_session_id:$uri:$postvars}; + my $chalsig = sha1_hex($chalbare, $secret); + return qq{$chalbare:$chalsig}; +} + +# Checks an auth token sent by an ajax request +# Arguments: $remote, $uri, %POST variables +# Returns: bool whether or not key is good +sub check_ajax_auth_token { + my ($class, $remote, $uri, %postvars) = @_; + + $remote = LJ::want_user($remote) || LJ::get_remote(); + + # get auth token out of post vars + my $auth_token = delete $postvars{auth_token} or return 0; + + # recompute post vars + my $postvars = join('&', map { $postvars{$_} } sort keys %postvars); + + # get vars out of token string + my ($c_ver, $stime, $remoteid, $sessid, $chal_uri, $chal_postvars, $chalsig) = split(':', $auth_token); + + # get secret based on $stime + my $secret = LJ::get_secret($stime); + + # no time? + return 0 unless $stime && $secret; + + # right version? + return 0 unless $c_ver eq 'ajax'; + + # in logged-out case $remoteid is 0 and $sessid is uniq_cookie + my $req_remoteid = $remoteid > 0 ? $remote->id : 0; + my $req_sessid = $remoteid > 0 ? $remote->session->id : LJ::UniqCookie->current_uniq; + + + # do signitures match? + my $chalbare = qq {$c_ver:$stime:$remoteid:$sessid:$chal_uri:$chal_postvars}; + my $realsig = sha1_hex($chalbare, $secret); + return 0 unless $realsig eq $chalsig; + + return 0 unless + $remoteid == $req_remoteid && # remote id matches or logged-out 0=0 + $sessid == $req_sessid && # remote sessid or logged-out uniq cookie match + $uri eq $chal_uri && # uri matches + $postvars eq $chal_postvars; # post vars to uri + + return 1; +} + +# this is similar to the above methods but doesn't require a session or remote +sub sessionless_auth_token { + my ($class, $uri, %reqvars) = @_; + + croak "No URI specified" unless $uri; + + my ($stime, $secret) = LJ::get_secret(); + my $reqvars = join('&', map { $reqvars{$_} } sort keys %reqvars); + + my $chalbare = qq {sessionless:$stime:$uri:$reqvars}; + my $chalsig = sha1_hex($chalbare, $secret); + return qq{$chalbare:$chalsig}; +} + +sub check_sessionless_auth_token { + my ($class, $uri, %reqvars) = @_; + + # get auth token out of post vars + my $auth_token = delete $reqvars{auth_token} or return 0; + + # recompute post vars + my $reqvars = join('&', map { $reqvars{$_} } sort keys %reqvars); + + # get vars out of token string + my ($c_ver, $stime, $chal_uri, $chal_reqvars, $chalsig) = split(':', $auth_token); + + # get secret based on $stime + my $secret = LJ::get_secret($stime); + + # no time? + return 0 unless $stime && $secret; + + # right version? + return 0 unless $c_ver eq 'sessionless'; + + # do signitures match? + my $chalbare = qq {$c_ver:$stime:$chal_uri:$chal_reqvars}; + my $realsig = sha1_hex($chalbare, $secret); + return 0 unless $realsig eq $chalsig; + + # do other vars match? + return 0 unless $uri eq $chal_uri && $reqvars eq $chal_reqvars; + + return 1; +} + +1; diff --git a/local/cgi-bin/LJ/CSS/Cleaner.pm b/local/cgi-bin/LJ/CSS/Cleaner.pm new file mode 100644 index 0000000..e4156f9 --- /dev/null +++ b/local/cgi-bin/LJ/CSS/Cleaner.pm @@ -0,0 +1,21 @@ +package LJ::CSS::Cleaner; + +use strict; +use warnings; +no warnings 'redefine'; + +use base 'CSS::Cleaner'; + +sub new { + my $class = shift; + return $class->SUPER::new( @_, + pre_hook => sub { + my $rref = shift; + + $$rref =~ s/comment-bake-cookie/CLEANED/g; + return; + }, + ); +} + +1; diff --git a/local/cgi-bin/LJ/ConvUTF8.pm b/local/cgi-bin/LJ/ConvUTF8.pm new file mode 100644 index 0000000..31e278e --- /dev/null +++ b/local/cgi-bin/LJ/ConvUTF8.pm @@ -0,0 +1,47 @@ +# this is a small wrapper around Unicode::MapUTF8, just so we can lazily-load it easier +# with Class::Autouse, and so we have a central place to init its charset aliases. +# and in the future if we switch transcoding packages, we can just do it here. +package LJ::ConvUTF8; + +use strict; +use warnings; +use Unicode::MapUTF8 (); + +BEGIN { + # declare some charset aliases + # we need this at least for cases when the only name supported + # by MapUTF8.pm isn't recognized by browsers + # note: newer versions of MapUTF8 know these + { + my %alias = ( 'windows-1251' => 'cp1251', + 'windows-1252' => 'cp1252', + 'windows-1253' => 'cp1253', ); + foreach (keys %alias) { + next if Unicode::MapUTF8::utf8_supported_charset($_); + Unicode::MapUTF8::utf8_charset_alias($_, $alias{$_}); + } + } +} + +sub load { + 1; +} + +sub supported_charset { + my ($class, $charset) = @_; + return Unicode::MapUTF8::utf8_supported_charset($charset); +} + +sub from_utf8 { + my ($class, $from_enc, $str) = @_; + return Unicode::MapUTF8::from_utf8({ -string=> $str, -charset => $from_enc }); +} + +sub to_utf8 { + my ($class, $to_enc, $str) = @_; + return Unicode::MapUTF8::to_utf8({ -string=> $str, -charset => $to_enc }); +} + +1; + + diff --git a/local/cgi-bin/LJ/EmbedModule.pm b/local/cgi-bin/LJ/EmbedModule.pm new file mode 100644 index 0000000..fc74a93 --- /dev/null +++ b/local/cgi-bin/LJ/EmbedModule.pm @@ -0,0 +1,466 @@ +#!/usr/bin/perl +package LJ::EmbedModule; +use strict; +use Carp qw (croak); +use Class::Autouse qw ( + LJ::Auth + HTML::TokeParser + ); + +# states for a finite-state machine we use in parse() +use constant { + # reading plain html without , or + REGULAR => 1, + # inside or tag + IMPLICIT => 2, + # inside explicit tag + EXPLICIT => 3, + # maximum embed width and height + MAX_WIDTH => 800, + MAX_HEIGHT => 800, +}; + +# can optionally pass in an id of a module to change its contents +# returns module id +sub save_module { + my ($class, %opts) = @_; + + my $contents = $opts{contents} || ''; + my $id = $opts{id}; + my $journal = $opts{journal} + or croak "No journal passed to LJ::EmbedModule::save_module"; + my $preview = $opts{preview}; + + # are we creating a new entry? + unless (defined $id) { + $id = LJ::alloc_user_counter($journal, 'D') + or die "Could not allocate embed module ID"; + } + + my $cmptext = 'C-' . LJ::text_compress($contents); + + ## embeds for preview are stored in a special table, + ## where new items overwrites old ones + my $table_name = ($preview) ? 'embedcontent_preview' : 'embedcontent'; + $journal->do("REPLACE INTO $table_name (userid, moduleid, content) VALUES ". + "(?, ?, ?)", undef, $journal->{'userid'}, $id, $cmptext); + die $journal->errstr if $journal->err; + + # save in memcache + my $memkey = $class->memkey($journal->{'userid'}, $id, $preview); + LJ::MemCache::set($memkey, $contents); + + return $id; +} + +# changes
    (((?!<\/div>).)*)<\/div>/$3<\/lj-embed>/ig; + $txt =~ s/(((?!<\/div>).)*)<\/div>/$3<\/lj-embed>/ig; + return $txt; +} + +# takes a scalarref to entry text and expands lj-embed tags +# REPLACE +sub expand_entry { + my ($class, $journal, $entryref, %opts) = @_; + + $$entryref =~ s/(]+\/>)/$class->_expand_tag($journal, $1, $opts{edit}, %opts)/ge; +} + +sub _expand_tag { + my $class = shift; + my $journal = shift; + my $tag = shift; + my $edit = shift; + my %opts = @_; + + my %attrs = $tag =~ /(\w+)="?(\-?\d+)"?/g; + + return '[invalid lj-embed, id is missing]' unless $attrs{id}; + + if ($edit) { + return '\n" . + $class->module_content(moduleid => $attrs{id}, journalid => $journal->id) . + "\n<\/lj-embed>"; + } + elsif ($opts{'content_only'}) { + return $class->module_content(moduleid => $attrs{id}, journalid => $journal->{'userid'}); + } + else { + @opts{qw /width height/} = @attrs{qw/width height/}; + return $class->module_iframe_tag($journal, $attrs{id}, %opts) + } +}; + + +# take a scalarref to a post, parses any lj-embed tags, saves the contents +# of the tags and replaces them with a module tag with the id. +# REPLACE +sub parse_module_embed { + my ($class, $journal, $postref, %opts) = @_; + + return unless $postref && $$postref; + + return if LJ::conf_test($LJ::DISABLED{embed_module}); + + # fast track out if we don't have to expand anything + return unless $$postref =~ /lj\-embed|embed|object/i; + + # do we want to replace with the lj-embed tags or iframes? + my $expand = $opts{expand}; + + # if this is editing mode, then we want to expand embed tags for editing + my $edit = $opts{edit}; + + # previews are a special case (don't want to permanantly save to db) + my $preview = $opts{preview}; + + # deal with old-fashion calls + if (($edit || $expand) && ! $preview) { + return $class->expand_entry($journal, $postref, %opts); + } + + # ok, we can safely parse post text + # machine state + my $state = REGULAR; + my $p = HTML::TokeParser->new($postref); + my $newtxt = ''; + my %embed_attrs = (); # ($eid, $ewidth, $eheight); + my $embed = ''; + my @stack = (); + my $next_preview_id = 1; + + while (my $token = $p->get_token) { + my ($type, $tag, $attr) = @$token; + $tag = lc $tag; + my $newstate = undef; + my $reconstructed = $class->reconstruct($token); + + if ($state == REGULAR) { + if ($tag eq 'lj-embed' && $type eq 'S' && ! $attr->{'/'}) { + # , not self-closed + # switch to EXPLICIT state + $newstate = EXPLICIT; + # save embed id, width and height if they do exist in attributes + $embed_attrs{id} = $attr->{id} if $attr->{id}; + $embed_attrs{width} = ($attr->{width} > MAX_WIDTH ? MAX_WIDTH : $attr->{width}) if $attr->{width}; + $embed_attrs{height} = ($attr->{height} > MAX_HEIGHT ? MAX_HEIGHT : $attr->{height}) if $attr->{height}; + } elsif (($tag eq 'object' || $tag eq 'embed') && $type eq 'S') { + # or + # switch to IMPLICIT state unless it is a self-closed tag + unless ($attr->{'/'}) { + $newstate = IMPLICIT; + # tag balance + push @stack, $tag; + } + # append the tag contents to new embed buffer, so we can convert in to lj-embed later + $embed .= $reconstructed; + } else { + # otherwise stay in REGULAR + $newtxt .= $reconstructed; + } + } elsif ($state == IMPLICIT) { + if ($tag eq 'object' || $tag eq 'embed') { + if ($type eq 'E') { + # or + # update tag balance, but only if we have a valid balance up to this moment + pop @stack if $stack[-1] eq $tag; + # switch to REGULAR if tags are balanced (stack is empty), stay in IMPLICIT otherwise + $newstate = REGULAR unless @stack; + } elsif ($type eq 'S') { + # or + # mind the tag balance, do not update it in case of a self-closed tag + push @stack, $tag unless $attr->{'/'}; + } + } + # append to embed buffer + $embed .= $reconstructed; + + } elsif ($state == EXPLICIT) { + + if ($tag eq 'lj-embed' && $type eq 'E') { + # - that's the end of explicit embed block, switch to REGULAR + $newstate = REGULAR; + } else { + # continue appending contents to embed buffer + $embed .= $reconstructed; + } + } else { + # let's be paranoid + die "Invalid state: '$state'"; + } + + # we decided to switch back to REGULAR and have something in embed buffer + # so let's save buffer as an embed module and start all over again + if (defined($newstate) && $newstate == REGULAR && $embed) { + $embed_attrs{id} = $class->save_module( + id => ($preview ? $next_preview_id++ : $embed_attrs{id}), + contents => $embed, + journal => $journal, + preview => $preview, + ); + + $newtxt .= ""; + + $embed = ''; + %embed_attrs = (); + } + + # switch the state if we have a new one + $state = $newstate if defined $newstate; + + } + + # update passed text + $$postref = $newtxt; +} + +sub module_iframe_tag { + my ($class, $u, $moduleid, %opts) = @_; + + return '' if $LJ::DISABLED{embed_module}; + + my $journalid = $u->{'userid'}; + $moduleid += 0; + + # parse the contents of the module and try to come up with a guess at the width and height of the content + my $content = $class->module_content(moduleid => $moduleid, journalid => $journalid); + my $preview = $opts{preview}; + my $width = 0; + my $height = 0; + my $p = HTML::TokeParser->new(\$content); + my $embedcodes; + + # if the content only contains a whitelisted embedded video + # then we can skip the placeholders (in some cases) + my $no_whitelist = 0; + my $found_embed = 0; + + # we don't need to estimate the dimensions if they are provided in tag attributes + unless ($opts{width} && $opts{height}) { + while (my $token = $p->get_token) { + my $type = $token->[0]; + my $tag = $token->[1] ? lc $token->[1] : ''; + my $attr = $token->[2]; # hashref + + if ($type eq "S") { + my ($elewidth, $eleheight); + + if ($attr->{width}) { + $elewidth = $attr->{width}+0; + $width = $elewidth if $elewidth > $width; + } + if ($attr->{height}) { + $eleheight = $attr->{height}+0; + $height = $eleheight if $eleheight > $height; + } + + my $flashvars = $attr->{flashvars}; + + if ($tag eq 'object' || $tag eq 'embed') { + my $src; + next unless $src = $attr->{src}; + + # we have an object/embed tag with src, make a fake lj-template object + my @tags = ( + ['S', 'lj-template', { + name => 'video', + (defined $elewidth ? ( width => $width ) : ()), + (defined $eleheight ? ( height => $height ) : ()), + (defined $flashvars ? ( flashvars => $flashvars ) : ()), + }], + [ 'T', $src, {}], + ['E', 'lj-template', {}], + ); + + $embedcodes = LJ::run_hook('expand_template_video', \@tags); + + $found_embed = 1 if $embedcodes; + $found_embed &&= $embedcodes !~ /Invalid video/i; + + $no_whitelist = !$found_embed; + } elsif ($tag ne 'param') { + $no_whitelist = 1; + } + } + } + + # add padding + $width += 50 if $width; + $height += 50 if $height; + } + + # use explicit values if we have them + $width = $opts{width} if $opts{width}; + $height = $opts{height} if $opts{height}; + + $width ||= 240; + $height ||= 200; + + # some dimension min/maxing + $width = 50 if $width < 50; + $width = MAX_WIDTH if $width > MAX_WIDTH; + $height = 50 if $height < 50; + $height = MAX_HEIGHT if $height > MAX_HEIGHT; + + # safari caches state of sub-resources aggressively, so give + # each iframe a unique 'name' attribute + my $id = qq(name="embed_${journalid}_$moduleid"); + + my $auth_token = LJ::eurl(LJ::Auth->sessionless_auth_token('embedcontent', moduleid => $moduleid, journalid => $journalid, preview => $preview,)); + my $iframe_url = qq {http://$LJ::EMBED_MODULE_DOMAIN/tools/embedcontent.bml?journalid=$journalid&moduleid=$moduleid&preview=$preview&auth_token=$auth_token}; + my $iframe_tag = qq {}; + + my $remote = LJ::get_remote(); + my $do_placeholder; + + if ($remote) { + return $iframe_tag if $opts{edit}; + + # show placeholder instead of iframe? + LJ::load_user_props($remote, "opt_embedplaceholders"); + my $placeholder_prop = $remote->prop('opt_embedplaceholders'); + $do_placeholder = $placeholder_prop && $placeholder_prop ne 'N'; + + # if placeholder_prop is not set, then show placeholder on a friends + # page view UNLESS the embedded content is only one embed/object + # tag and it's whitelisted video. + my $r = eval { Apache->request }; + my $view = $r ? $r->notes("view") : ''; + if (! $placeholder_prop && $view eq 'friends') { + # show placeholder if this is not whitelisted video + $do_placeholder = 1 if $no_whitelist; + } + } + else { + $do_placeholder = $BML::COOKIE{'flashpref'}; + $do_placeholder = 0 unless $do_placeholder eq "0" || $do_placeholder eq "1"; + } + + return $iframe_tag unless $do_placeholder; + + my $tmpcontent = $class->module_content( + journalid => $journalid, + moduleid => $moduleid, + 0 + ); + $tmpcontent =~ s/.+param\s+name\s*?=\s*?"?movie"?\s*value\s*?=\s*?"?//sg; #" + $tmpcontent =~ s/("|\s).+//sg; #" + $tmpcontent = LJ::ehtml($tmpcontent); + + # placeholder + return LJ::placeholder_link( + placeholder_html => $iframe_tag, + placeholder_link => $iframe_url, + width => $width, + height => $height, + img => "$LJ::IMGPREFIX/videoplaceholder.png", + img_title => $tmpcontent, + ); +} + +sub module_content { + my ($class, %opts) = @_; + + my $moduleid = $opts{moduleid}; + croak "No moduleid" unless defined $moduleid; + $moduleid += 0; + + my $journalid = $opts{journalid}+0 or croak "No journalid"; + my $journal = LJ::load_userid($journalid) or die "Invalid userid $journalid"; + my $preview = $opts{preview}; + + # try memcache + my $memkey = $class->memkey($journalid, $moduleid, $preview); + my $content = LJ::MemCache::get($memkey); + my ($dbload, $dbid); # module id from the database + unless (defined $content) { + my $table_name = ($preview) ? 'embedcontent_preview' : 'embedcontent'; + ($content, $dbid) = $journal->selectrow_array("SELECT content, moduleid FROM $table_name WHERE " . + "moduleid=? AND userid=?", + undef, $moduleid, $journalid); + die $journal->errstr if $journal->err; + $dbload = 1; + } + + $content ||= ''; + + LJ::text_uncompress(\$content) if $content =~ s/^C-//; + + # clean js out of content + unless ($LJ::DISABLED{'embedmodule-cleancontent'}) { + LJ::CleanHTML::clean(\$content, { + addbreaks => 0, + tablecheck => 0, + mode => 'allow', + allow => [qw(object embed)], + deny => [qw(script iframe)], + remove => [qw(script iframe)], + ljcut_disable => 1, + cleancss => 0, + extractlinks => 0, + noautolinks => 1, + extractimages => 0, + noexpandembedded => 1, + transform_embed_nocheck => 1, + }); + } + + # if we got stuff out of database + if ($dbload) { + # save in memcache + LJ::MemCache::set($memkey, $content); + + # if we didn't get a moduleid out of the database then this entry is not valid + return defined $dbid ? $content : "[Invalid lj-embed id $moduleid]"; + } + + # get rid of whitespace around the content + return LJ::trim($content) || ''; +} + +sub memkey { + my ($class, $journalid, $moduleid, $preview) = @_; + my $pfx = $preview ? 'embedcontpreview' : 'embedcont'; + return [$journalid, "$pfx:$journalid:$moduleid"]; +} + +# create a tag string from HTML::TokeParser token +sub reconstruct { + my $class = shift; + my $token = shift; + my ($type, $tag, $attr, $attord) = @$token; + if ($type eq 'S') { + my $txt = "<$tag"; + my $selfclose; + + # preserve order of attributes. the original order is + # in element 4 of $token + foreach my $name (@$attord) { + if ($name eq '/') { + $selfclose = 1; + next; + } + + # FIXME: ultra ghetto. + $attr->{$name} = LJ::no_utf8_flag($attr->{$name}); + + $txt .= " $name=\"" . LJ::ehtml($attr->{$name}) . "\""; + } + $txt .= $selfclose ? " />" : ">"; + + } elsif ($type eq 'E') { + return ""; + } else { # C, T, D or PI + return $tag; + } +} + + +1; + diff --git a/local/cgi-bin/LJ/Entry.pm b/local/cgi-bin/LJ/Entry.pm new file mode 100644 index 0000000..c93dfe6 --- /dev/null +++ b/local/cgi-bin/LJ/Entry.pm @@ -0,0 +1,1138 @@ +package LJ; + +use Class::Autouse qw ( + LJ::EmbedModule +); + + +# +# name: LJ::get_posts_raw +# des: Gets raw post data (text and props) efficiently from clusters. +# info: Fetches posts from clusters, trying memcache and slaves first if available. +# returns: hashref with keys 'text', 'prop', and values being hashrefs +# with keys "jid:jitemid". values of that are as follows: +# text: [ $subject, $body ], props: { ... }; +# replycount scalar returned within props. +# +# args: opts?, id+ +# des-opts: An optional hashref of options: +# - memcache_only: Don't fall back on the database. +# - prop_only: Retrieve only props, for efficiensy. +# des-id: An arrayref of [ clusterid, ownerid, itemid ]. +# +sub get_posts_raw +{ + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $ret = {}; + my $sth; + + LJ::load_props('log'); + + # throughout this function, the concept of an "id" + # is the key to identify a single post. + # it is of the form "$jid:$jitemid". + + # build up a list for each cluster of what we want to get, + # as well as a list of all the keys we want from memcache. + my %cids; # cid => 1 + my $needtext; # text needed: $cid => $id => 1 + my $needprop; # props needed: $cid => $id => 1 + my $needrc; # replycounts needed: $cid => $id => 1 + my @mem_keys; + + # if we're loading entries for a friends page, + # silently failing to load a cluster is acceptable. + # but for a single user, we want to die loudly so they don't think + # we just lost their journal. + my $single_user; + + # because the memcache keys for logprop don't contain + # which cluster they're in, we also need a map to get the + # cid back from the jid so we can insert into the needfoo hashes. + # the alternative is to not key the needfoo hashes on cluster, + # but that means we need to grep out each cluster's jids when + # we do per-cluster queries on the databases. + my %cidsbyjid; + foreach my $post (@_) { + my ($cid, $jid, $jitemid) = @{$post}; + my $id = "$jid:$jitemid"; #!!! + if (not defined $single_user) { + $single_user = $jid; + } elsif ($single_user and $jid != $single_user) { + # multiple users + $single_user = 0; + } + $cids{$cid} = 1; + $cidsbyjid{$jid} = $cid; + + unless ($opts->{prop_only}) { + $needtext->{$cid}{$id} = 1; + push @mem_keys, [$jid, "logtext:$cid:$id"]; + $needrc->{$cid}{$id} = 1; + push @mem_keys, [$jid, "rp:$id"]; + } + $needprop->{$cid}{$id} = 1; + push @mem_keys, [$jid, "logprop:$id"]; + } + + # first, check memcache. + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + next unless defined $v; + next unless $k =~ /(\w+):(?:\d+:)?(\d+):(\d+)/; + my ($type, $jid, $jitemid) = ($1, $2, $3); + my $cid = $cidsbyjid{$jid}; + my $id = "$jid:$jitemid"; + if ($type eq "logtext") { + delete $needtext->{$cid}{$id}; + $ret->{text}{$id} = $v; + } elsif ($type eq "logprop" && ref $v eq "HASH") { + delete $needprop->{$cid}{$id}; + $ret->{prop}{$id} = $v; + } elsif ($type eq "rp") { + delete $needrc->{$cid}{$id}; + $ret->{replycount}{$id} = $v; + } + } + + # we may be done already. + return $ret if $opts->{memcache_only}; + return $ret unless values %$needtext or values %$needprop + or values %$needrc; + + # otherwise, hit the database. + foreach my $cid (keys %cids) { + # for each cluster, get the text/props we need from it. + my $cneedtext = $needtext->{$cid} || {}; + my $cneedprop = $needprop->{$cid} || {}; + my $cneedrc = $needrc->{$cid} || {}; + + next unless %$cneedtext or %$cneedprop or %$cneedrc; + + my $make_in = sub { + my @in; + foreach my $id (@_) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + push @in, "(journalid=$jid AND jitemid=$jitemid)"; + } + return join(" OR ", @in); + }; + + # now load from each cluster. + my $fetchtext = sub { + my $db = shift; + return unless %$cneedtext; + my $in = $make_in->(keys %$cneedtext); + $sth = $db->prepare("SELECT journalid, jitemid, subject, event ". + "FROM logtext2 WHERE $in"); + $sth->execute; + while (my ($jid, $jitemid, $subject, $event) = $sth->fetchrow_array) { + LJ::text_uncompress(\$event); + my $id = "$jid:$jitemid"; + my $val = [ $subject, $event ]; + $ret->{text}{$id} = $val; + LJ::MemCache::add([$jid, "logtext:$cid:$id"], $val, 7200); + delete $cneedtext->{$id}; + } + }; + + my $fetchprop = sub { + my $db = shift; + return unless %$cneedprop; + my $in = $make_in->(keys %$cneedprop); + $sth = $db->prepare("SELECT journalid, jitemid, propid, value ". + "FROM logprop2 WHERE $in"); + $sth->execute; + my %gotid; + while (my ($jid, $jitemid, $propid, $value) = $sth->fetchrow_array) { + my $id = "$jid:$jitemid"; + my $propname = $LJ::CACHE_PROPID{'log'}->{$propid}{name}; + $ret->{prop}{$id}{$propname} = $value; + $gotid{$id} = 1; + } + foreach my $id (keys %gotid) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + LJ::MemCache::add([$jid, "logprop:$id"], $ret->{prop}{$id}); #7200 + delete $cneedprop->{$id}; + } + }; + + my $fetchrc = sub { + my $db = shift; + return unless %$cneedrc; + my $in = $make_in->(keys %$cneedrc); + $sth = $db->prepare("SELECT journalid, jitemid, replycount FROM log2 WHERE $in"); + $sth->execute; + while (my ($jid, $jitemid, $rc) = $sth->fetchrow_array) { + my $id = "$jid:$jitemid"; + $ret->{replycount}{$id} = $rc; + LJ::MemCache::add([$jid, "rp:$id"], $rc); + delete $cneedrc->{$id}; + } + }; + + my $dberr = sub { + die "Couldn't connect to database" if $single_user; + next; + }; + + # run the fetch functions on the proper databases, with fallbacks if necessary. + my ($dbcm, $dbcr); + if (@LJ::MEMCACHE_SERVERS or $opts->{use_master}) { + $dbcm ||= LJ::get_cluster_master($cid) or $dberr->(); + $fetchtext->($dbcm) if %$cneedtext; + $fetchprop->($dbcm) if %$cneedprop; + $fetchrc->($dbcm) if %$cneedrc; + } else { + $dbcr ||= LJ::get_cluster_reader($cid); + if ($dbcr) { + $fetchtext->($dbcr) if %$cneedtext; + $fetchprop->($dbcr) if %$cneedprop; + $fetchrc->($dbcr) if %$cneedrc; + } + # if we still need some data, switch to the master. + if (%$cneedtext or %$cneedprop) { + $dbcm ||= LJ::get_cluster_master($cid) or $dberr->(); + $fetchtext->($dbcm); + $fetchprop->($dbcm); + $fetchrc->($dbcm); + } + } + + # and finally, if there were no errors, + # insert into memcache the absence of props + # for all posts that didn't have any props. + foreach my $id (keys %$cneedprop) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + LJ::MemCache::add([$jid, "logprop:$id"], {} ); + } + } + + # move replycount into prop : we could not do this before prop are set because prop hash will rewrite replycount... + while (my ($k, $v) = each %{$ret->{"replycount"}||{}}) { + $ret->{prop}{$k}{replycount} = $ret->{replycount}{$k}; + } + + return $ret; +} + + +# +# returns a row from log2, trying memcache +# accepts $u + $jitemid +# returns hash with: posterid, eventtime, logtime, +# security, allowmask, journalid, jitemid, anum. + +sub get_log2_row +{ + my ($u, $jitemid, $db) = @_; + my $jid = $u->{'userid'}; + + my $memkey = [$jid, "log2:$jid:$jitemid"]; + my ($row, $item); + + $row = LJ::MemCache::get($memkey); + + if ($row) { + @$item{'posterid', 'eventtime', 'logtime', 'allowmask', 'ditemid'} = unpack("NNNNN", $row); + $item->{'security'} = ($item->{'allowmask'} == 0 ? 'private' : + ($item->{'allowmask'} == 2**31 ? 'public' : 'usemask')); + $item->{'journalid'} = $jid; + @$item{'jitemid', 'anum'} = ($item->{'ditemid'} >> 8, $item->{'ditemid'} % 256); + $item->{'eventtime'} = LJ::mysql_time($item->{'eventtime'}, 1); + $item->{'logtime'} = LJ::mysql_time($item->{'logtime'}, 1); + + return $item; + } + + $db = LJ::get_cluster_def_reader($u) unless $db; + return undef unless $db; + + my $sql = "SELECT posterid, eventtime, logtime, security, allowmask, " . + "anum FROM log2 WHERE journalid=? AND jitemid=?"; + + $item = $db->selectrow_hashref($sql, undef, $jid, $jitemid); + return undef unless $item; + $item->{'journalid'} = $jid; + $item->{'jitemid'} = $jitemid; + $item->{'ditemid'} = $jitemid*256 + $item->{'anum'}; + + my ($sec, $eventtime, $logtime); + $sec = $item->{'allowmask'}; + $sec = 0 if $item->{'security'} eq 'private'; + $sec = 2**31 if $item->{'security'} eq 'public'; + $eventtime = LJ::mysqldate_to_time($item->{'eventtime'}, 1); + $logtime = LJ::mysqldate_to_time($item->{'logtime'}, 1); + + $row = pack("NNNNN", $item->{'posterid'}, $eventtime, $logtime, $sec, + $item->{'ditemid'}); + LJ::MemCache::set($memkey, $row); + + return $item; +} + +# local function. +# Get 8 weeks worth of recent items, in rlogtime order, using memcache. +# accepts ($jid, $clusterid, $timeupdate, $notafter, $notbefore). +# - $notafter - max value for rlogtime +# - $notbefore - min value for rlogtime, optional +# - $timeupdate is the timeupdate for this user, as far as the caller knows, +# in UNIX time. +# returns arrayref of the following: +# [$rlogtime, $posterid, $eventtime, $allowmask, $ditemid] + +sub get_log2_recent_log +{ + my ($jid, $cid, $timeupdate, $notafter, $notbefore) = @_; + + my $DATAVER = "3"; # 1 char + + my $memkey = [$jid, "log2lt:$jid"]; + my $lockkey = $memkey->[1]; + my ($rows, $ret); + + $rows = LJ::MemCache::get($memkey); + $ret = []; + + my $rows_decode = sub { + return 0 + unless $rows && substr($rows, 0, 1) eq $DATAVER; + my $tu = unpack("N", substr($rows, 1, 4)); + + # if update time we got from upstream is newer than recorded + # here, this data from memcache is unreliable + return 0 if $timeupdate > $tu; + + my $n = (length($rows) - 5 )/20; + for (my $i=0; $i<$n; $i++) { + #was: pack("NNNNN", $rlogtime, $posterid, $eventtime, $allowmask, $ditemid); + my @item = unpack("NNNNN", substr($rows, $i*20+5, 20)); + next if $notbefore and $item[0] < $notbefore; # rlogtime + last if $notafter and $item[0] > $notafter; # rlogtime + push @$ret, \@item; + } + return 1; + }; + + return $ret + if $rows_decode->(); + + #clear otherwise: + LJ::MemCache::delete($memkey) if $rows; + $rows = ""; + + my $db = LJ::get_cluster_def_reader($cid); + # if we use slave or didn't get some data, don't store in memcache + my $dont_store = 0; + unless ($db) { + $db = LJ::get_cluster_reader($cid); + $dont_store = 1; + return undef unless $db; + } + + + # get reliable log2lt data from the db + + my $max_age = $LJ::MAX_FRIENDS_VIEW_AGE || 3600*24*56; # 8 weeks default + + my $sql = "SELECT rlogtime, posterid, eventtime, jitemid, " . + "security, allowmask, anum, replycount FROM log2 " . + "USE INDEX (rlogtime) WHERE journalid=? AND " . + "rlogtime <= ($LJ::EndOfTime - UNIX_TIMESTAMP()) + $max_age"; + + my $sth = $db->prepare($sql); + $sth->execute($jid); + my @row; + while (my @arr = $sth->fetchrow_array) { push @row, \@arr; } + @row = sort { $a->[0] <=> $b->[0] } @row; #rlogtime + my $i = 0; + + foreach (@row) { + my ($rlogtime, $posterid, $eventtime, $jitemid, $security, $allowmask, $anum, $replycount) = @$_; #in $sql order! + $eventtime = LJ::mysqldate_to_time($eventtime, 1); + + $allowmask = 0 if $security eq 'private'; + $allowmask = 2**31 if $security eq 'public'; + + my $ditemid = $jitemid*256 + $anum; + + $rows .= pack("NNNNN", $rlogtime, $posterid, $eventtime, $allowmask, $ditemid); + + unless (($notafter and $rlogtime > $notafter) || ($notbefore and $rlogtime < $notbefore)) { + push @$ret, [$rlogtime, $posterid, $eventtime, $allowmask, $ditemid]; + } + + if ($i++ < 50) { + LJ::MemCache::add([$jid, "rp:$jid:$jitemid"], $replycount); + } + if ($i > $LJ::MAX_SCROLLBACK_FRIENDS_SINGLE_USER_ACTIVITY) { + last; #limit log2lt: to a reasonable size + } + } + + $rows = $DATAVER . pack("N", $timeupdate) . $rows; + LJ::MemCache::add($memkey, $rows, $timeupdate + $max_age) unless $dont_store; + + return $ret; +} + +# public function, called from get_friend_items() +sub get_log2_recent_user +{ + my $opts = shift; + my $ret = []; + + my $journalid = $opts->{'userid'}; + my $clusterid = $opts->{'clusterid'}; + + my $log = LJ::get_log2_recent_log($journalid, $clusterid, $opts->{'timeupdate'}, $opts->{'notafter'}, $opts->{'notbefore'}); + + my $left = $opts->{'itemshow'}; + my $remote = $opts->{'remote'}; + my $remoteid = $remote->{'userid'}; + my $valid_remote_journaltype = $remote->{'journaltype'} eq "P" || $remote->{'journaltype'} eq "I"; + my $mask; + + foreach my $i (@$log) { + last unless $left; + + ## filter security and provide proper format for the caller: + + my ($rlogtime, $posterid, $eventtime, $allowmask, $ditemid) = @$i; + + my $security = $allowmask == 0 ? 'private' : + ($allowmask == 2**31 ? 'public' : 'usemask'); + + next unless $remote || $security eq 'public'; + next if $security eq 'private' + and $journalid != $remoteid; + + if ($security eq 'usemask') { + next unless $valid_remote_journaltype; + my $permit = ($journalid == $remoteid); + unless ($permit) { + $mask = LJ::get_groupmask($journalid, $remoteid) unless defined $mask; + $permit = $allowmask+0 & $mask+0; + } + next unless $permit; + } + + my ($jitemid, $anum) = ($ditemid >> 8, $ditemid % 256); + + push @$ret, [$rlogtime, $jitemid, $posterid, $eventtime, $anum, $ditemid, $security, $journalid]; + $left--; + } + + return $ret; +} + + +# called from go.bml +sub get_itemid_near2 +{ + my ($u, $ditemid, $direction) = @_; + + $ditemid += 0; + my $jitemid = $ditemid >> 8; + + my ($inc, $order); + if ($direction eq "next") { + ($inc, $order) = (1, "DESC"); + } elsif ($direction eq "prev") { + ($inc, $order) = (-1, "ASC"); + } else { + return 0; + } + + my $dbr = LJ::get_cluster_reader($u); + my $jid = $u->{'userid'}+0; + + # $remote nujen dlia svjaznosti ssylok. + my $remote = LJ::get_remote(); + my $mask; + + my $item; + + while (1) { + $jitemid += $inc; + # TODO: try get_log2_row() + #($anum, $security, $allowmask) = $dbr->selectrow_array( + # "SELECT anum, security, allowmask ". + # " FROM log2 WHERE journalid=$jid AND jitemid=$jitemid"); + $item = get_log2_row($u, $jitemid, $dbr); + last unless $item; + + my $security = $item->{'security'}; + # usually exits from the first try, unless security: + last if $security eq 'public'; + last if $security eq 'private' && $remote && $jid == $remote->{'userid'}; + + if ($security eq 'usemask' && $remote) { + next unless $remote->{'journaltype'} eq "P" || $remote->{'journaltype'} eq "I"; + my $permit = ($jid == $remote->{'userid'}); + unless ($permit) { + $mask = LJ::get_groupmask($jid, $remote->{'userid'}) unless defined $mask; + $permit = $item->{'allowmask'} & $mask+0; + } + last if $permit; + } + next; + } + return $item->{'jitemid'}*256 + $item->{'anum'} if ($item); + #return 0; # deleted posts can be a problem + + + # old, unused code, use as fallback + $jitemid = $ditemid >> 8; + my $field = $u->{'journaltype'} eq "P" ? "revttime" : "rlogtime"; + + my $stime = $dbr->selectrow_array("SELECT $field FROM log2 WHERE ". + "journalid=$jid AND jitemid=$jitemid"); + return 0 unless $stime; + + my $day = 86400; + foreach my $distance ($day, $day*7, $day*30, $day*90) { + my ($one_away, $further) = ($stime - $inc, $stime - $inc*$distance); + if ($further < $one_away) { + # swap them, BETWEEN needs lower number first + ($one_away, $further) = ($further, $one_away); + } + my ($id, $anum) = + $dbr->selectrow_array("SELECT jitemid, anum FROM log2 WHERE journalid=$jid ". + "AND $field BETWEEN $one_away AND $further ". + "ORDER BY $field $order LIMIT 1"); + if ($id) { + return wantarray() ? ($id, $anum) : ($id*256 + $anum); + } + } + return 0; +} + + +sub set_logprop +{ + my ($u, $jitemid, $hashref, $logprops) = @_; # hashref to set, hashref of what was done + + $jitemid += 0; + my $uid = $u->{'userid'} + 0; + my $kill_mem = 0; + my $del_ids; + my $ins_values; + while (my ($k, $v) = each %{$hashref||{}}) { + my $prop = LJ::get_prop("log", $k); + next unless $prop; + $kill_mem = 1; + if ($v) { + $ins_values .= "," if $ins_values; + $ins_values .= "($uid, $jitemid, $prop->{'id'}, " . $u->quote($v) . ")"; + $logprops->{$k} = $v; + } else { + $del_ids .= "," if $del_ids; + $del_ids .= $prop->{'id'}; + } + } + + $u->do("REPLACE INTO logprop2 (journalid, jitemid, propid, value) ". + "VALUES $ins_values") if $ins_values; + $u->do("DELETE FROM logprop2 WHERE journalid=? AND jitemid=? ". + "AND propid IN ($del_ids)", undef, $u->{'userid'}, $jitemid) if $del_ids; + + LJ::MemCache::delete([$uid,"logprop:$uid:$jitemid"]) if $kill_mem; +} + +# +# name: LJ::load_log_props2 +# class: +# des: +# info: +# args: db?, uuserid, listref, hashref +# des-: +# returns: +# +sub load_log_props2 +{ + my $db = isdb($_[0]) ? shift @_ : undef; + + my ($uuserid, $listref, $hashref) = @_; + my $userid = want_userid($uuserid); + return unless ref $hashref eq "HASH"; + + my %needprops; + my %needrc; + my %rc; + my @memkeys; + foreach (@$listref) { + my $id = $_+0; + $needprops{$id} = 1; + $needrc{$id} = 1; + push @memkeys, [$userid, "logprop:$userid:$id"]; + push @memkeys, [$userid, "rp:$userid:$id"]; + } + return unless %needprops || %needrc; + + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $k =~ /(\w+):(\d+):(\d+)/; + if ($1 eq 'logprop') { + next unless ref $v eq "HASH"; + delete $needprops{$3}; + $hashref->{$3} = $v; + } + if ($1 eq 'rp') { + delete $needrc{$3}; + $rc{$3} = $v; + } + } + + foreach (keys %rc) { + $hashref->{$_}{'replycount'} = $rc{$_}; + } + + return unless %needprops || %needrc; + + unless ($db) { + my $u = LJ::load_userid($userid); + $db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + return unless $db; + } + + if (%needprops) { + LJ::load_props("log"); + my $in = join(",", keys %needprops); + my $sth = $db->prepare("SELECT jitemid, propid, value FROM logprop2 ". + "WHERE journalid=? AND jitemid IN ($in)"); + $sth->execute($userid); + while (my ($jitemid, $propid, $value) = $sth->fetchrow_array) { + $hashref->{$jitemid}->{$LJ::CACHE_PROPID{'log'}->{$propid}->{'name'}} = $value; + } + foreach my $id (keys %needprops) { + LJ::MemCache::add([$userid,"logprop:$userid:$id"], $hashref->{$id} || {}); #7200 + } + } + + if (%needrc) { + my $in = join(",", keys %needrc); + my $sth = $db->prepare("SELECT jitemid, replycount FROM log2 WHERE journalid=? AND jitemid IN ($in)"); + $sth->execute($userid); + while (my ($jitemid, $rc) = $sth->fetchrow_array) { + $hashref->{$jitemid}->{'replycount'} = $rc; + LJ::MemCache::add([$userid, "rp:$userid:$jitemid"], $rc); + } + } + + +} + +# +# name: LJ::delete_entry +# des: Deletes a user's journal entry +# args: uuserid, jitemid, quick?, anum? +# des-uuserid: Journal itemid or $u object of journal to delete entry from +# des-jitemid: Journal itemid of item to delete. +# des-quick: Optional boolean. If set, only [dbtable[log2]] table +# is deleted from and the rest of the content is deleted +# later using [func[LJ::cmd_buffer_add]]. +# des-anum: The log item's anum, which'll be needed to delete lazily +# some data in tables which includes the anum, but the +# log row will already be gone so we'll need to store it for later. +# returns: boolean; 1 on success, 0 on failure. +# +sub delete_entry +{ + my ($uuserid, $jitemid, $quick, $anum) = @_; + my $jid = LJ::want_userid($uuserid); + my $u = ref $uuserid ? $uuserid : LJ::load_userid($jid); + $jitemid += 0; + + my $and = ""; + if (defined $anum) { $and = "AND anum=" . ($anum+0); } + + my $dc = $u->log2_do(undef, "DELETE FROM log2 WHERE journalid=$jid AND jitemid=$jitemid $and"); + return 0 unless $dc; + LJ::MemCache::delete([$jid, "log2:$jid:$jitemid"]); + LJ::MemCache::decr([$jid, "log2ct:$jid"]); + LJ::memcache_kill($jid, "dayct"); + + # delete tags + LJ::Tags::delete_logtags($u, $jitemid); + + # if this is running the second time (started by the cmd buffer), + # the log2 row will already be gone and we shouldn't check for it. + if ($quick) { + return 1 if $dc < 1; # already deleted? + return LJ::cmd_buffer_add($u->{clusterid}, $jid, "delitem", { + 'itemid' => $jitemid, + 'anum' => $anum, + }); + } + + # delete from clusters + foreach my $t (qw(logtext2 logprop2 logsec2)) { + $u->do("DELETE FROM $t WHERE journalid=$jid AND jitemid=$jitemid"); + } + $u->dudata_set('L', $jitemid, 0); + + # delete all comments + LJ::Talk::delete_all_comments($u, 'L', $jitemid); + + # clean unused cache - + LJ::MemCache::delete([$jid, "logtext:$u->{clusterid}:$jid:$jitemid"]); + LJ::MemCache::delete([$jid, "logprop:$jid:$jitemid"]); + LJ::MemCache::delete([$jid, "rss:$jid"]); + + return 1; +} + +# +# name: LJ::mark_entry_as_spam +# class: web +# des: Copies an entry in a community into the global spamreports table +# args: journalu, jitemid +# des-journalu: User object of journal (community) entry was posted in. +# des-jitemid: ID of this entry. +# returns: 1 for success, 0 for failure +# +sub mark_entry_as_spam { + my ($journalu, $jitemid) = @_; + $journalu = LJ::want_user($journalu); + $jitemid += 0; + return 0 unless $journalu && $jitemid; + + my $dbcr = LJ::get_cluster_def_reader($journalu); + my $dbh = LJ::get_db_writer(); + return 0 unless $dbcr && $dbh; + + my $item = LJ::get_log2_row($journalu, $jitemid); + return 0 unless $item; + + # step 1: get info we need + my $logtext = LJ::get_logtext2($journalu, $jitemid); + my ($subject, $body, $posterid) = ($logtext->{$jitemid}[0], $logtext->{$jitemid}[1], $item->{posterid}); + return 0 unless $body; + + # step 2: insert into spamreports + $dbh->do('INSERT INTO spamreports (reporttime, posttime, journalid, posterid, subject, body, report_type) ' . + 'VALUES (UNIX_TIMESTAMP(), UNIX_TIMESTAMP(?), ?, ?, ?, ?, \'entry\')', + undef, $item->{logtime}, $journalu->{userid}, $posterid, $subject, $body); + + return 0 if $dbh->err; + return 1; +} + +# replycount_do +# input: $u, $jitemid, $action, $value +# action is one of: "init", "incr", "decr" +# $value is amount to incr/decr, 1 by default + +sub replycount_do { + my ($u, $jitemid, $action, $value) = @_; + $value = 1 unless defined $value; + my $uid = $u->{'userid'}; + my $memkey = [$uid, "rp:$uid:$jitemid"]; + + # "init" is easiest and needs no lock (called before the entry is live) + if ($action eq 'init') { + LJ::MemCache::set($memkey, 0); + return 1; + } + + return 0 unless $action eq 'decr' || $action eq 'incr'; + return 0 unless $u->writer; + + + if ($action eq 'decr') { $value = - $value; } + + $u->do("UPDATE log2 SET replycount=replycount+$value WHERE journalid=$uid AND jitemid=$jitemid"); + + my $rc = $u->selectrow_array("SELECT replycount FROM log2 WHERE journalid=$uid AND jitemid=$jitemid"); + LJ::MemCache::set($memkey, $rc) if defined $rc; + LJ::MemCache::delete("/comments/$jitemid/$uid"); + LJ::Talk::update_commentalter($u, $jitemid); # timestamp + + return 1; +} + +# +# name: LJ::get_logtext2 +# des: Efficiently retrieves a large number of journal entry text, trying first +# slave database servers for recent items, then the master in +# cases of old items the slaves have already disposed of. See also: +# [func[LJ::get_talktext2]]. +# args: u, opts?, jitemid* +# returns: hashref with keys being jitemids, values being [ $subject, $body ] +# des-opts: Optional hashref of special options. Currently only 'usemaster' +# key is supported, which always returns a definitive copy, +# and not from a cache or slave database. +# des-jitemid: List of jitemids to retrieve the subject & text for. +# +sub get_logtext2 +{ + my $u = shift; + my $clusterid = $u->{'clusterid'}; + my $journalid = $u->{'userid'}+0; + + my $opts = ref $_[0] ? shift : {}; + + # return structure. + my $lt = {}; + return $lt unless $clusterid; + + # keep track of itemids we still need to load. + my %need; + my @mem_keys; + foreach (@_) { + my $id = $_+0; + $need{$id} = 1; + push @mem_keys, [$journalid,"logtext:$clusterid:$journalid:$id"]; + } + + # pass 0: memory, avoiding databases + unless ($opts->{'usemaster'}) { + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $v; + $k =~ /:(\d+):(\d+):(\d+)/; + delete $need{$3}; + $lt->{$3} = $v; + } + } + + return $lt unless %need; + + # pass 1 (slave) and pass 2 (master) + foreach my $pass (1, 2) { + next unless %need; + next if $pass == 1 && $opts->{'usemaster'}; + my $db = $pass == 1 ? LJ::get_cluster_reader($clusterid) : + LJ::get_cluster_def_reader($clusterid); + next unless $db; + + my $jitemid_in = join(", ", keys %need); + my $sth = $db->prepare("SELECT jitemid, subject, event FROM logtext2 ". + "WHERE journalid=$journalid AND jitemid IN ($jitemid_in)"); + $sth->execute; + while (my ($id, $subject, $event) = $sth->fetchrow_array) { + LJ::text_uncompress(\$event); + + unless ($opts->{'text-only'}) { + LJR::Distributed::sign_imported_entry ($journalid, $id, \$event); + } + + my $val = [ $subject, $event ]; + $lt->{$id} = $val; + LJ::MemCache::add([$journalid,"logtext:$clusterid:$journalid:$id"], $val, 7200); + delete $need{$id}; + } + } + return $lt; +} + + +# +# name: LJ::load_talk_props2 +# des: Retrieves comments properties. +# info: +# args: +# des-: +# returns: +# +sub load_talk_props2 +{ + my ($u, $listref, $hashref) = @_; + my $userid = $u->{'userid'}+0; + + $hashref = {} unless ref $hashref eq "HASH"; + + my %need; + my @memkeys; + foreach (@$listref) { + my $id = $_+0; + $need{$id} = 1; + push @memkeys, [$userid,"talkprop:$userid:$id"]; + } + return $hashref unless %need; + + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $k =~ /(\d+):(\d+)/ && ref $v eq "HASH"; + delete $need{$2}; + $hashref->{$2}->{$_[0]} = $_[1] while @_ = each %$v; + } + return $hashref unless %need; + + my $db; + if (@LJ::MEMCACHE_SERVERS) { + $db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + return $hashref unless $db; + } + + LJ::load_props("talk"); + my $in = join(',', keys %need); + my $sth = $db->prepare("SELECT jtalkid, tpropid, value FROM talkprop2 ". + "WHERE journalid=? AND jtalkid IN ($in)"); + $sth->execute($userid); + while (my ($jtalkid, $propid, $value) = $sth->fetchrow_array) { + my $p = $LJ::CACHE_PROPID{'talk'}->{$propid}; + next unless $p; + $hashref->{$jtalkid}->{$p->{'name'}} = $value; + } + foreach my $id (keys %need) { + LJ::MemCache::add([$userid,"talkprop:$userid:$id"], $hashref->{$id} || {}, 3600); + } + return $hashref; +} + + +# +# name: LJ::get_talktext2 +# des: Retrieves comments text. Tries slave servers first, then master. +# info: Efficiently retreives batches of comment text. Will try alternate +# servers first. See also [func[LJ::get_logtext2]]. +# returns: Hashref with the talkids as keys, values being [ $subject, $event ]. +# args: u, opts?, jtalkids +# des-opts: A hashref of options. 'onlysubjects' will only retrieve subjects. +# des-jtalkids: A list of talkids to get text for. +# +sub get_talktext2 +{ + my $u = shift; + my $clusterid = $u->{'clusterid'}; + my $journalid = $u->{'userid'}+0; + + my $opts = ref $_[0] ? shift : {}; + + # return structure. + my $lt = {}; + return $lt unless $clusterid; + + # keep track of itemids we still need to load. + my %need; + my @mem_keys; + foreach (@_) { + my $id = $_+0; + push @mem_keys, [$journalid,"talktext:$clusterid:$journalid:$id"]; + } + + # try the memory cache + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + foreach (@_) { + my $id = $_+0; + my $v = $mem->{"talktext:$clusterid:$journalid:$id"}; + if (defined $v) { + $lt->{$id} = $v; + } else { + $need{$id} = 1; + } + } + return $lt unless %need; + + # pass 1 (slave) and pass 2 (master) + foreach my $pass (1, 2) { + next unless %need; + my $db = $pass == 1 ? LJ::get_cluster_reader($clusterid) : + LJ::get_cluster_def_reader($clusterid); + next unless $db; + my $in = join(",", keys %need); + my $sth = $db->prepare("SELECT jtalkid, subject, body FROM talktext2 ". + "WHERE journalid=$journalid AND jtalkid IN ($in)"); + $sth->execute; + while (my ($id, $subject, $body) = $sth->fetchrow_array) { + LJ::text_uncompress(\$body); + $lt->{$id} = [ $subject, $body ]; + LJ::MemCache::add([$journalid,"talktext:$clusterid:$journalid:$id"], [$subject, $body], 3600); + delete $need{$id}; + } + } + return $lt; +} + + +# +# name: LJ::item_link +# class: component +# des: Returns URL to view an individual journal item. +# info: The returned URL may have an ampersand in it. In an HTML/XML attribute, +# these must first be escaped by, say, [func[LJ::ehtml]]. This +# function doesn't return it pre-escaped because the caller may +# use it in, say, a plain-text email message. +# args: u, itemid, anum? +# des-itemid: Itemid of entry to link to. +# des-anum: If present, $u is assumed to be on a cluster and itemid is assumed +# to not be a $ditemid already, and the $itemid will be turned into one +# by multiplying by 256 and adding $anum. +# returns: scalar; unescaped URL string +# +sub item_link +{ + my ($u, $itemid, $anum, @args) = @_; + my $ditemid = $itemid*256 + $anum; + + # XXX: should have an option of returning a url with escaped (&) + # or non-escaped (&) arguments. a new link object would be best. + my $args = @args ? "?" . join("&", @args) : ""; + return LJ::journal_base($u) . "/$ditemid.html$args"; +} + +# +# name: LJ::expand_embedded +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub expand_embedded +{ + &nodb; + my ($u, $ditemid, $remote, $eventref, %opts) = @_; + + LJ::Poll::show_polls($ditemid, $remote, $eventref); + LJ::EmbedModule->expand_entry($u, $eventref, %opts); + LJ::run_hooks("expand_embedded", $u, $ditemid, $remote, $eventref, %opts); +} + +# +# name: LJ::item_toutf8 +# des: convert one item's subject, text and props to UTF8. +# item can be an entry or a comment (in which cases props can be +# left empty, since there are no 8bit talkprops). +# args: u, subject, text, props +# des-u: user hashref of the journal's owner +# des-subject: ref to the item's subject +# des-text: ref to the item's text +# des-props: hashref of the item's props +# returns: nothing. +# +sub item_toutf8 +{ + my ($u, $subject, $text, $props) = @_; + return unless $LJ::UNICODE; + + my $convert = sub { + my $rtext = shift; + my $error = 0; + my $res = LJ::text_convert($$rtext, $u, \$error); + if ($error) { + LJ::text_out($rtext); + } else { + $$rtext = $res; + }; + return; + }; + + $convert->($subject); + $convert->($text); + foreach(keys %$props) { + $convert->(\$props->{$_}); + } + return; +} + + +# Called from get_friend_items, get_recent_items, get_journal_item, few others. +# +# A single place to pickup text, props, tags, convert utf-8, and fill items' properies. +# $items: arrayref; +# $u: user object, or hashref of user objects by uid (= multiowner); +# $opts fields: multiowner, only_subject, props_only. +# +# TODO: should be optimized / rewtitten from scratch. +# +# Usage: fill_items_with_text_props(\@items, $u); +# fill_items_with_text_props(\@friend_items, $opts->{'friends_u'}, {'multiowner' => 1}); +# +sub fill_items_with_text_props { + my ($items, $u, $opts) = @_; + + if ($opts->{'multiowner'}) { # $u - hashref of user objects by ownerid + # required fields: ownerid, itemid + + my @ids; + foreach (@$items) { + push @ids, [ $u->{$_->{'ownerid'}}->{'clusterid'}, $_->{'ownerid'}, $_->{'itemid'} ]; + } + + # load the text and props of the entries + my $res = LJ::get_posts_raw({}, @ids); #key {text or prop}{"$ownerid:$itemid"} + + # load tags + my $tags; + $tags = LJ::Tags::get_logtagsmulti(\@ids); #key "$ownerid:$itemid" + + foreach (@$items) { + $_->{'text'} = $res->{text}{"$_->{'ownerid'}:$_->{'itemid'}"}; + $_->{'props'} = $res->{prop}{"$_->{'ownerid'}:$_->{'itemid'}"}; + + if ($LJ::UNICODE && $_->{'props'}->{'unknown8bit'}) { + # artefact, very very small fraction of old items affected + LJ::item_toutf8($u->{$_->{'ownerid'}}, + \$_->{'text'}->[0], \$_->{'text'}->[1], $_->{'props'}); + ###$_->{'props'}->{'unknown8bit'} = 0; #no change: memcache logtext,logprop always in sync with db + print STDERR "Fixing item_toutf8 in friend_items $_->{'ownerid'} $_->{'itemid'} \n"; + } + + if ($tags) { + # $taglist = [ split(/\s*,\s*/, $_->{'props'}->{taglist}) ]; #unknown8bit ? edittags? + my @taglist = values %{$tags->{"$_->{'ownerid'}:$_->{'itemid'}"}}; #$kwid => $kw + @taglist = sort { $a cmp $b } @taglist; + $_->{'props'}->{'tags'} = \@taglist; + } + } + + } else { #single owner: $u - user object + # required fields: itemid + + my @ids; + foreach (@$items) { + push @ids, [ $u->{'clusterid'}, $u->{'userid'}, $_->{'itemid'} ]; + } + + # load the text and props of the entries + my $res; + if ($opts->{'props_only'}) { + $res = LJ::get_posts_raw({'prop_only' => 1}, @ids); + } else { + $res = LJ::get_posts_raw({}, @ids); + } + + # load tags + my $tags; + $tags = LJ::Tags::get_logtagsmulti(\@ids) unless $opts->{'only_subject'} || $opts->{'props_only'}; + + foreach (@$items) { + $_->{'text'} = $res->{text}{"$u->{'userid'}:$_->{'itemid'}"}; + $_->{'props'} = $res->{prop}{"$u->{'userid'}:$_->{'itemid'}"}; + + if ($LJ::UNICODE && $_->{'props'}->{'unknown8bit'} && $logtext) { + # artefact, very very small fraction of old items affected + LJ::item_toutf8($u, + \$_->{'text'}->[0], \$_->{'text'}->[1], $_->{'props'}); + ###$_->{'props'}->{'unknown8bit'} = 0; #no change: memcache logtext,logprop always in sync with db + print STDERR "Fixing item_toutf8 in recent_items $u->{'userid'} $_->{'itemid'} \n"; + } + + if ($tags) { + # $taglist = [ split(/\s*,\s*/, $_->{'props'}->{taglist}) ]; + my @taglist = values %{$tags->{"$u->{'userid'}:$_->{'itemid'}"}}; #$kwid => $kw + @taglist = sort { $a cmp $b } @taglist; + $_->{'props'}->{'tags'} = \@taglist; + } + } + } + + #foreach (@$items) { + #TODO + #my $subject = $_->{'text'}->[0]; + + # see if we have a subject and clean it + #if ($subject) { + # $subject =~ s/[\r\n]/ /g; + # LJ::CleanHTML::clean_subject_all(\$subject); + # $_->{'text'}->[0] = $subject; + #} + #} +} + + +1; diff --git a/local/cgi-bin/LJ/OpenID.pm b/local/cgi-bin/LJ/OpenID.pm new file mode 100755 index 0000000..63b164c --- /dev/null +++ b/local/cgi-bin/LJ/OpenID.pm @@ -0,0 +1,184 @@ +package LJ::OpenID; + +use strict; +use Digest::SHA1 qw(sha1 sha1_hex); +use LWPx::ParanoidAgent; + +BEGIN { + $LJ::OPTMOD_OPENID_CONSUMER = $LJ::OPENID_CONSUMER ? eval "use Net::OpenID::Consumer; 1;" : 0; + $LJ::OPTMOD_OPENID_SERVER = $LJ::OPENID_SERVER ? eval "use Net::OpenID::Server; 1;" : 0; +} + +# returns boolean whether consumer support is enabled and available +sub consumer_enabled { + return 0 unless $LJ::OPENID_CONSUMER; + return $LJ::OPTMOD_OPENID_CONSUMER || eval "use Net::OpenID::Consumer; 1;"; +} + +# returns boolean whether consumer support is enabled and available +sub server_enabled { + return 0 unless $LJ::OPENID_SERVER; + return $LJ::OPTMOD_OPENID_CONSUMER || eval "use Net::OpenID::Server; 1;"; +} + +sub server { + my ($get, $post) = @_; + + return Net::OpenID::Server->new( + compat => $LJ::OPENID_COMPAT, + get_args => $get || {}, + post_args => $post || {}, + + get_user => \&LJ::get_remote, + is_identity => sub { + my ($u, $ident) = @_; + return LJ::OpenID::is_identity($u, $ident, $get); + }, + is_trusted => \&LJ::OpenID::is_trusted, + + setup_url => "$LJ::SITEROOT/openid/approve.bml", + + server_secret => \&LJ::OpenID::server_secret, + secret_gen_interval => 3600, + secret_expire_age => 86400 * 14, + ); +} + +# Returns a Consumer object +# When planning to verify identity, needs GET +# arguments passed in +sub consumer { + my $get_args = shift || {}; + + my $ua; + unless ($LJ::IS_DEV_SERVER) { + $ua = LWPx::ParanoidAgent->new( + timeout => 10, + max_size => 1024*300, + ); + } + + my $csr = Net::OpenID::Consumer->new( + ua => $ua, + args => $get_args, + cache => eval { LJ::MemCache::get_memcache() }, + consumer_secret => \&LJ::OpenID::consumer_secret, + debug => $LJ::IS_DEV_SERVER || 0, + required_root => $LJ::SITEROOT, + ); + + return $csr; +} + +sub consumer_secret { + my $time = shift; + return server_secret($time - $time % 3600); +} + +sub server_secret { + my $time = shift; + my ($t2, $secret) = LJ::get_secret($time); + die "ASSERT: didn't get t2 (t1=$time)" unless $t2; + die "ASSERT: didn't get secret (t2=$t2)" unless $secret; + die "ASSERT: time($time) != t2($t2)\n" unless $t2 == $time; + return $secret; +} + +sub is_trusted { + my ($u, $trust_root, $is_identity) = @_; + return 0 unless $u; + # we always look up $is_trusted, even if $is_identity is false, to avoid timing attacks + + my $dbh = LJ::get_db_writer(); + my ($endpointid, $duration) = $dbh->selectrow_array("SELECT t.endpoint_id, t.duration ". + "FROM openid_trust t, openid_endpoint e ". + "WHERE t.userid=? AND t.endpoint_id=e.endpoint_id AND e.url=?", + undef, $u->{userid}, $trust_root); + return 0 unless $endpointid; + return 1; +} + +sub is_identity { + my ($u, $ident, $get) = @_; + return 0 unless $u && $u->{journaltype} eq "P"; + + my $user = $u->{user}; + return 1 if + $ident eq "$LJ::SITEROOT/users/$user/" || + $ident eq "$LJ::SITEROOT/~$user/" || + $ident eq "http://$user.$LJ::USER_DOMAIN/"; + + return 0; +} + +sub getmake_endpointid { + my $site = shift; + + my $dbh = LJ::get_db_writer() + or return undef; + + my $rv = $dbh->do("INSERT IGNORE INTO openid_endpoint (url) VALUES (?)", undef, $site); + my $end_id; + if ($rv > 0) { + $end_id = $dbh->{'mysql_insertid'}; + } else { + $end_id = $dbh->selectrow_array("SELECT endpoint_id FROM openid_endpoint WHERE url=?", + undef, $site); + } + return $end_id; +} + +sub add_trust { + my ($u, $site) = @_; + + my $end_id = LJ::OpenID::getmake_endpointid($site) + or return 0; + + my $dbh = LJ::get_db_writer() + or return undef; + + my $rv = $dbh->do("REPLACE INTO openid_trust (userid, endpoint_id, duration, trust_time) ". + "VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $u->{userid}, $end_id, "always"); + return $rv; +} + +# From Digest::HMAC +sub hmac_sha1_hex { + unpack("H*", &hmac_sha1); +} +sub hmac_sha1 { + hmac($_[0], $_[1], \&sha1, 64); +} +sub hmac { + my($data, $key, $hash_func, $block_size) = @_; + $block_size ||= 64; + $key = &$hash_func($key) if length($key) > $block_size; + + my $k_ipad = $key ^ (chr(0x36) x $block_size); + my $k_opad = $key ^ (chr(0x5c) x $block_size); + + &$hash_func($k_opad, &$hash_func($k_ipad, $data)); +} + +# Returns 1 if destination identity server +# is blocked +sub blocked_hosts { + my $csr = shift; + + return do { my $dummy = 0; \$dummy; } if $LJ::IS_DEV_SERVER; + + my $tried_local_id = 0; + $csr->ua->blocked_hosts( + sub { + my $dest = shift; + + if ($dest =~ /((^|\.)\Q$LJ::DOMAIN\E$|demotivation\.me|anonymity\.com)/i) { + $tried_local_id = 1; + return 1; + } + return 0; + }); + return \$tried_local_id; +} + +1; diff --git a/local/cgi-bin/LJ/S2.pm b/local/cgi-bin/LJ/S2.pm new file mode 100755 index 0000000..2e96ad5 --- /dev/null +++ b/local/cgi-bin/LJ/S2.pm @@ -0,0 +1,2739 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'LJHOME'}/src/s2"; +use S2; +use S2::Checker; +use S2::Color; +use S2::Compiler; +use Storable; +use Apache::Constants (); +use HTMLCleaner; +use POSIX (); + +use LJ::S2::RecentPage; +use LJ::S2::YearPage; +use LJ::S2::DayPage; +use LJ::S2::FriendsPage; +use LJ::S2::MonthPage; +use LJ::S2::EntryPage; +use LJ::S2::ReplyPage; + +package LJ::S2; + +# TEMP HACK +sub get_s2_reader { + return LJ::get_dbh("s2slave", "slave", "master"); +} + +sub make_journal +{ + my ($u, $styleid, $view, $remote, $opts) = @_; + + my $r = $opts->{'r'}; + my $ret; + $LJ::S2::ret_ref = \$ret; + + my ($entry, $page); + my $con_opts = {}; + + if ($view eq "res") { + if ($opts->{'pathextra'} =~ m!/(\d+)/stylesheet$!) { + $styleid = $1; + $entry = "print_stylesheet()"; + $opts->{'contenttype'} = 'text/css'; + $con_opts->{'use_modtime'} = 1; + } else { + $opts->{'handler_return'} = 404; + return; + } + } + + $u->{'_s2styleid'} = $styleid + 0; + $con_opts->{'u'} = $u; + $con_opts->{'style_u'} = $opts->{'style_u'}; + my $ctx = s2_context($r, $styleid, $con_opts); + unless ($ctx) { + $opts->{'handler_return'} = Apache::Constants::OK(); + return; + } + + my $lang = 'en'; + LJ::run_hook('set_s2bml_lang', $ctx, \$lang); + + # note that's it's very important to pass LJ::Lang::get_text here explicitly + # rather than relying on BML::set_language's fallback mechanism, which won't + # work in this context since BML::cur_req won't be loaded if no BML requests + # have been served from this Apache process yet + BML::set_language($lang, \&LJ::Lang::get_text); + + # let layouts disable EntryPage / ReplyPage, using the BML version + # instead. + if ($ctx->[S2::PROPS]->{'view_entry_disabled'} && ($view eq "entry" || $view eq "reply")) { + ${$opts->{'handle_with_bml_ref'}} = 1; + return; + } + + # make sure capability supports it + if (($view eq "entry" || $view eq "reply") && + ! LJ::get_cap(($opts->{'checkremote'} ? $remote : $u), "s2view$view")) { + ${$opts->{'handle_with_bml_ref'}} = 1; + return; + } + + # setup tags backwards compatibility + unless ($ctx->[S2::PROPS]->{'tags_aware'}) { + $opts->{enable_tags_compatibility} = 1; + } + + escape_context_props($ctx->[S2::PROPS]); + + $opts->{'ctx'} = $ctx; + $LJ::S2::CURR_CTX = $ctx; + + foreach ("name", "url", "urlname") { LJ::text_out(\$u->{$_}); } + + $u->{'_journalbase'} = LJ::journal_base($u->{'user'}, $opts->{'vhost'}); + + if ($view eq "lastn") { + $entry = "RecentPage::print()"; + $page = RecentPage($u, $remote, $opts); + } elsif ($view eq "calendar") { + $entry = "YearPage::print()"; + $page = YearPage($u, $remote, $opts); + } elsif ($view eq "day") { + $entry = "DayPage::print()"; + $page = DayPage($u, $remote, $opts); + } elsif ($view eq "friends" || $view eq "friendsfriends") { + $entry = "FriendsPage::print()"; + $page = FriendsPage($u, $remote, $opts); + } elsif ($view eq "month") { + $entry = "MonthPage::print()"; + $page = MonthPage($u, $remote, $opts); + } elsif ($view eq "entry") { + $entry = "EntryPage::print()"; + $page = EntryPage($u, $remote, $opts); + } elsif ($view eq "reply") { + $entry = "ReplyPage::print()"; + $page = ReplyPage($u, $remote, $opts); + } + + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + + # the friends mode=live returns raw HTML in $page, in which case there's + # nothing to "run" with s2_run. so $page isn't runnable, return it now. + # but we have to make sure it's defined at all first, otherwise things + # like print_stylesheet() won't run, which don't have an method invocant + return $page if $page && ref $page ne 'HASH'; + + s2_run($r, $ctx, $opts, $entry, $page); + + if (ref $opts->{'errors'} eq "ARRAY" && @{$opts->{'errors'}}) { + return join('', + "Errors occurred processing this page:
      ", + map { "
    • $_
    • " } @{$opts->{'errors'}}, + "
    "); + } + + # unload layers that aren't public + LJ::S2::cleanup_layers($ctx); + + + # see if we can save some bandwidth (though we already killed a bunch of CPU) + my $etag = Digest::MD5::md5_hex(pack('C*', unpack('C*', $ret))); + $etag = '"' . $etag . '"'; + + my $ifnonematch = $r->header_in("If-None-Match"); + if (defined $ifnonematch && $etag eq $ifnonematch) { + $opts->{'notmodified'} = 1; + return undef; + } else { + $r->header_out("ETag", $etag); + } + + return $ret; +} + +sub s2_run +{ + my ($r, $ctx, $opts, $entry, $page) = @_; + + my $ctype = $opts->{'contenttype'} || "text/html"; + my $cleaner; + + my $cleaner_output = sub { + my $text = shift; + + # expand lj-embed tags + if ($text =~ /lj\-embed/i) { + # find out what journal we're looking at + my $r = eval { Apache->request }; + if ($r && $r->notes("journalid")) { + my $journal = LJ::load_userid($r->notes("journalid")); + # expand tags + LJ::EmbedModule->expand_entry($journal, \$text) + if $journal; + } + } + + $$LJ::S2::ret_ref .= $text; + }; + + if ($ctype =~ m!^text/html!) { + $cleaner = HTMLCleaner->new( + 'output' => $cleaner_output, + 'valid_stylesheet' => \&LJ::valid_stylesheet_url, + ); + } + + my $send_header = sub { + my $status = $ctx->[S2::SCRATCH]->{'status'} || 200; + $r->status($status); + $r->content_type($ctx->[S2::SCRATCH]->{'ctype'} || $ctype); + $r->send_http_header(); + }; + + my $need_flush; + my $out_straight = sub { + # Hacky: forces text flush. see: + # http://zilla.livejournal.org/906 + if ($need_flush) { + $cleaner->parse(""); + $need_flush = 0; + } + $$LJ::S2::ret_ref .= $_[0]; + }; + my $out_clean = sub { + $cleaner->parse($_[0]); + $need_flush = 1; + }; + S2::set_output($out_straight); + S2::set_output_safe($cleaner ? $out_clean : $out_straight); + + $LJ::S2::CURR_PAGE = $page; + $LJ::S2::RES_MADE = 0; # standard resources (Image objects) made yet + + eval { + S2::run_code($ctx, $entry, $page); + }; + $LJ::S2::CURR_PAGE = undef; + $LJ::S2::CURR_CTX = undef; + + if ($@) { + my $error = $@; + $error =~ s/\n/
    \n/g; + S2::pout("Error running style: $error"); + return 0; + } + $cleaner->eof if $cleaner; # flush any remaining text/tag not yet spit out + return 1; +} + +# returns hashref { lid => $u }; undef on error +sub get_layer_owners { + my @lids = map { $_ + 0 } @_; + return {} unless @lids; + + my $ret = {}; # lid => uid/$u + my @need; + + # see what we can get out of memcache first + my @keys; + push @keys, [ $_, "s2lo:$_" ] foreach @lids; + my $memc = LJ::MemCache::get_multi(@keys); + foreach my $lid (@lids) { + if (my $uid = $memc->{"s2lo:$lid"}) { + $ret->{$lid} = $uid; + } else { + push @need, $lid; + } + } + + # if we still need any from the database, get them now + if (@need) { + my $dbh = LJ::get_db_writer(); + my $in = join(',', @need); + my $res = $dbh->selectall_arrayref("SELECT s2lid, userid FROM s2layers WHERE s2lid IN ($in)"); + die "Database error in LJ::S2::get_layer_owners: " . $dbh->errstr . "\n" if $dbh->err; + + foreach my $row (@$res) { + # save info and add to memcache + $ret->{$row->[0]} = $row->[1]; + LJ::MemCache::add([ $row->[0], "s2lo:$row->[0]" ], $row->[1]); + } + } + + # now load these users; they're likely process cached anyway, so it should + # be pretty fast + my $us = LJ::load_userids(values %$ret); + foreach my $lid (keys %$ret) { + $ret->{$lid} = $us->{$ret->{$lid}} + } + return $ret; +} + +# returns max comptime of all lids requested to be loaded +sub load_layers { + my @lids = map { $_ + 0 } @_; + return 0 unless @lids; + + my $maxtime = 0; # to be returned + + # figure out what is process cached...that goes to DB always + # if it's not in process cache, hit memcache first + my @from_db; # lid, lid, lid, ... + my @need_memc; # lid, lid, lid, ... + + # initial sweep, anything loaded for less than 60 seconds is golden + foreach my $lid (@lids) { + if (my $loaded = S2::layer_loaded($lid, 60)) { + # it's loaded and not more than 60 seconds load, so we just go + # with it and assume it's good... if it's been recompiled, we'll + # figure it out within the next 60 seconds + $maxtime = $loaded if $loaded > $maxtime; + } else { + push @need_memc, $lid; + } + } + + # attempt to get things in @need_memc from memcache + my $memc = LJ::MemCache::get_multi(map { [ $_, "s2c:$_"] } @need_memc); + foreach my $lid (@need_memc) { + if (my $row = $memc->{"s2c:$lid"}) { + # load the layer from memcache; memcache data should always be correct + my ($updtime, $data) = @$row; + if ($data) { + $maxtime = $updtime if $updtime > $maxtime; + S2::load_layer($lid, $data, $updtime); + } + } else { + # make it exist, but mark it 0 + push @from_db, $lid; + } + } + + # it's possible we don't need to hit the database for anything + return $maxtime unless @from_db; + + # figure out who owns what we need + my $us = LJ::S2::get_layer_owners(@from_db); + my $sysid = LJ::get_userid('system'); + + # break it down by cluster + my %bycluster; # cluster => [ lid, lid, ... ] + foreach my $lid (@from_db) { + next unless $us->{$lid}; + if ($us->{$lid}->{userid} == $sysid) { + push @{$bycluster{0} ||= []}, $lid; + } else { + push @{$bycluster{$us->{$lid}->{clusterid}} ||= []}, $lid; + } + } + + # big loop by cluster + foreach my $cid (keys %bycluster) { + # if we're talking about cluster 0, the global, pass it off to the old + # function which already knows how to handle that + unless ($cid) { + my $dbr = LJ::S2::get_s2_reader(); + S2::load_layers_from_db($dbr, @{$bycluster{$cid}}); + next; + } + + my $db = LJ::get_cluster_master($cid); + die "Unable to obtain handle to cluster $cid for LJ::S2::load_layers\n" + unless $db; + + # create SQL to load the layers we want + my $where = join(' OR ', map { "(userid=$us->{$_}->{userid} AND s2lid=$_)" } @{$bycluster{$cid}}); + my $sth = $db->prepare("SELECT s2lid, compdata, comptime FROM s2compiled2 WHERE $where"); + $sth->execute; + + # iterate over data, memcaching as we go + while (my ($id, $comp, $comptime) = $sth->fetchrow_array) { + LJ::text_uncompress(\$comp); + LJ::MemCache::set([ $id, "s2c:$id" ], [ $comptime, $comp ]) + if length $comp <= $LJ::MAX_S2COMPILED_CACHE_SIZE; + S2::load_layer($id, $comp, $comptime); + $maxtime = $comptime if $comptime > $maxtime; + } + } + + # now we have to go through everything again and verify they're all loaded and + # otherwise do a fallback to the global + my @to_load; + foreach my $lid (@from_db) { + next if S2::layer_loaded($lid); + + unless ($us->{$lid}) { + print STDERR "Style $lid has no available owner.\n"; + next; + } + + if ($us->{$lid}->{userid} == $sysid) { + print STDERR "Style $lid is owned by system but failed load from global.\n"; + next; + } + + if ($LJ::S2COMPILED_MIGRATION_DONE) { + LJ::MemCache::set([ $lid, "s2c:$lid" ], [ time(), 0 ]); + next; + } + + push @to_load, $lid; + } + return $maxtime unless @to_load; + + # get the dbh and start loading these + my $dbr = LJ::S2::get_s2_reader(); + die "Failure getting S2 database handle in LJ::S2::load_layers\n" + unless $dbr; + + my $where = join(' OR ', map { "s2lid=$_" } @to_load); + my $sth = $dbr->prepare("SELECT s2lid, compdata, comptime FROM s2compiled WHERE $where"); + $sth->execute; + while (my ($id, $comp, $comptime) = $sth->fetchrow_array) { + S2::load_layer($id, $comp, $comptime); + $maxtime = $comptime if $comptime > $maxtime; + } + return $maxtime; +} + +# find existing re-distributed layers that are in the database +# and their styleids. +sub get_public_layers +{ + my $sysid = shift; # optional system userid (usually not used) + $LJ::CACHED_PUBLIC_LAYERS ||= LJ::MemCache::get("s2publayers") + unless $LJ::LESS_CACHING; + return $LJ::CACHED_PUBLIC_LAYERS if $LJ::CACHED_PUBLIC_LAYERS; + + $sysid ||= LJ::get_userid("system"); + my $layers = get_layers_of_user($sysid, "is_system"); + + return $layers if $LJ::LESS_CACHING; + $LJ::CACHED_PUBLIC_LAYERS = $layers if $layers; + LJ::MemCache::set("s2publayers", $layers, 60*10) if $layers; + return $LJ::CACHED_PUBLIC_LAYERS; +} + +# update layers whose b2lids have been remapped to new s2lids +sub b2lid_remap +{ + my ($uuserid, $s2lid, $b2lid) = @_; + my $b2lid_new = $LJ::S2LID_REMAP{$b2lid}; + return undef unless $uuserid && $s2lid && $b2lid && $b2lid_new; + + my $sysid = LJ::get_userid("system"); + return undef unless $sysid; + + LJ::statushistory_add($uuserid, $sysid, 'b2lid_remap', "$s2lid: $b2lid=>$b2lid_new"); + + my $dbh = LJ::get_db_writer(); + return $dbh->do("UPDATE s2layers SET b2lid=? WHERE s2lid=?", + undef, $b2lid_new, $s2lid); +} + +sub get_layers_of_user +{ + my ($u, $is_system) = @_; + my $userid = LJ::want_userid($u); + return undef unless $userid; + undef $u unless LJ::isu($u); + + return $u->{'_s2layers'} if $u && $u->{'_s2layers'}; + + my %layers; # id -> {hashref}, uniq -> {same hashref} + my $dbr = LJ::S2::get_s2_reader(); + + my $extrainfo = $is_system ? "'redist_uniq', " : ""; + my $sth = $dbr->prepare("SELECT i.infokey, i.value, l.s2lid, l.b2lid, l.type ". + "FROM s2layers l, s2info i ". + "WHERE l.userid=? AND l.s2lid=i.s2lid AND ". + "i.infokey IN ($extrainfo 'type', 'name', 'langcode', ". + "'majorversion', '_previews')"); + $sth->execute($userid); + die $dbr->errstr if $dbr->err; + while (my ($key, $val, $id, $bid, $type) = $sth->fetchrow_array) { + $layers{$id}->{'b2lid'} = $bid; + $layers{$id}->{'s2lid'} = $id; + $layers{$id}->{'type'} = $type; + $key = "uniq" if $key eq "redist_uniq"; + $layers{$id}->{$key} = $val; + } + + foreach (keys %layers) { + # setup uniq alias. + if ($layers{$_}->{'uniq'} ne "") { + $layers{$layers{$_}->{'uniq'}} = $layers{$_}; + } + + # setup children keys + my $bid = $layers{$_}->{b2lid}; + next unless $layers{$_}->{'b2lid'}; + + # has the b2lid for this layer been remapped? + # if so update this layer's specified b2lid + if ($bid && $LJ::S2LID_REMAP{$bid}) { + my $s2lid = $layers{$_}->{s2lid}; + b2lid_remap($userid, $s2lid, $bid); + $layers{$_}->{b2lid} = $LJ::S2LID_REMAP{$bid}; + } + + if ($is_system) { + my $bid = $layers{$_}->{'b2lid'}; + unless ($layers{$bid}) { + delete $layers{$layers{$_}->{'uniq'}}; + delete $layers{$_}; + next; + } + push @{$layers{$bid}->{'children'}}, $_; + } + } + + if ($u) { + $u->{'_s2layers'} = \%layers; + } + return \%layers; +} + + +# get_style: +# +# many calling conventions: +# get_style($styleid, $verify) +# get_style($u, $verify) +# get_style($styleid, $opts) +# get_style($u, $opts) +# +# opts may contain keys: +# - 'u' -- $u object +# - 'verify' -- if verify, the $u->{'s2_style'} key is deleted if style isn't found +sub get_style +{ + my ($arg, $opts) = @_; + + my $verify = 0; + my ($styleid, $u); + + if (ref $opts eq "HASH") { + $verify = $opts->{'verify'}; + $u = $opts->{'u'}; + } elsif ($opts) { + $verify = 1; + die "Bogus second arg to LJ::S2::get_style" if ref $opts; + } + + if (ref $arg) { + $u = $arg; + $styleid = $u->{'s2_style'} + 0; + } else { + $styleid = $arg + 0; + } + + my %style; + my $have_style = 0; + + if ($verify && $styleid) { + my $dbr = LJ::S2::get_s2_reader(); + my $style = $dbr->selectrow_hashref("SELECT * FROM s2styles WHERE styleid=$styleid"); + if (! $style && $u) { + delete $u->{'s2_style'}; + $styleid = 0; + } + } + + if ($styleid) { + my $stylay = $u ? + LJ::S2::get_style_layers($u, $styleid) : + LJ::S2::get_style_layers($styleid); + while (my ($t, $id) = each %$stylay) { $style{$t} = $id; } + $have_style = scalar %style; + } + + # this is a hack to add remapping support for s2lids + # - if a layerid is loaded above but it has a remapping + # defined in ljconfig, use the remap id instead and + # also save to database using set_style_layers + if (%LJ::S2LID_REMAP) { + my @remaps = (); + + # all system layer types (no user layers) + foreach (qw(core i18nc i18n layout theme)) { + my $lid = $style{$_}; + if (exists $LJ::S2LID_REMAP{$lid}) { + $style{$_} = $LJ::S2LID_REMAP{$lid}; + push @remaps, "$lid=>$style{$_}"; + } + } + if (@remaps) { + my $sysid = LJ::get_userid("system"); + LJ::statushistory_add($u, $sysid, 's2lid_remap', join(", ", @remaps)); + LJ::S2::set_style_layers($u, $styleid, %style); + } + } + + unless ($have_style) { + my $public = get_public_layers(); + while (my ($layer, $name) = each %$LJ::DEFAULT_STYLE) { + next unless $name ne ""; + next unless $public->{$name}; + my $id = $public->{$name}->{'s2lid'}; + $style{$layer} = $id if $id; + } + } + + return %style; +} + +sub s2_context +{ + my $r = shift; + my $styleid = shift; + my $opts = shift || {}; + + my $u = $opts->{u}; + my $style_u = $opts->{style_u} || $u; + + # but it doesn't matter if we're using the minimal style ... + my %style; + eval { + my $r = Apache->request; + if ($r->notes('use_minimal_scheme')) { + my $public = get_public_layers(); + while (my ($layer, $name) = each %LJ::MINIMAL_STYLE) { + next unless $name ne ""; + next unless $public->{$name}; + my $id = $public->{$name}->{'s2lid'}; + $style{$layer} = $id if $id; + } + } + }; + + # fall back to the standard call to get a user's styles + unless (%style) { + %style = $u ? get_style($styleid, { 'u' => $style_u }) : get_style($styleid); + } + + my @layers; + foreach (qw(core i18nc layout i18n theme user)) { + push @layers, $style{$_} if $style{$_}; + } + + # TODO: memcache this. only make core S2 (which uses the DB) load + # when we can't get all the s2compiled stuff from memcache. + # compare s2styles.modtime with s2compiled.comptime to see if memcache + # version is accurate or not. + my $dbr = LJ::S2::get_s2_reader(); + my $modtime = LJ::S2::load_layers(@layers); + + # check that all critical layers loaded okay from the database, otherwise + # fall back to default style. if i18n/theme/user were deleted, just proceed. + my $okay = 1; + foreach (qw(core layout)) { + next unless $style{$_}; + $okay = 0 unless S2::layer_loaded($style{$_}); + } + unless ($okay) { + # load the default style instead, if we just tried to load a real one and failed + if ($styleid) { return s2_context($r, 0, $opts); } + + # were we trying to load the default style? + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error preparing to run: One or more layers required to load the stock style have been deleted."); + return undef; + } + + if ($opts->{'use_modtime'}) + { + my $ims = $r->header_in("If-Modified-Since"); + my $ourtime = LJ::time_to_http($modtime); + if ($ims eq $ourtime) { + # 304 return; unload non-public layers + LJ::S2::cleanup_layers(@layers); + $r->status_line("304 Not Modified"); + $r->send_http_header(); + return undef; + } else { + $r->header_out("Last-Modified", $ourtime); + } + } + + my $ctx; + eval { + $ctx = S2::make_context(@layers); + }; + + if ($ctx) { + LJ::S2::populate_system_props($ctx); + S2::set_output(sub {}); # printing suppressed + S2::set_output_safe(sub {}); + eval { S2::run_code($ctx, "prop_init()"); }; + return $ctx unless $@; + } + + # failure to generate context; unload our non-public layers + LJ::S2::cleanup_layers(@layers); + + my $err = $@; + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error preparing to run: $err"); + return undef; + +} + +# parameter is either a single context, or just a bunch of layerids +# will then unregister the non-public layers +sub cleanup_layers { + my $pub = get_public_layers(); + my @unload = ref $_[0] ? S2::get_layers($_[0]) : @_; + S2::unregister_layer($_) foreach grep { ! $pub->{$_} } @unload; +} + +sub clone_layer +{ + die "LJ::S2::clone_layer() has not been ported to use s2compiled2, but this function is not currently in use anywhere; if you use this function, please update it to use s2compiled2.\n"; + + my $id = shift; + return 0 unless $id; + + my $dbh = LJ::get_db_writer(); + my $r; + + $r = $dbh->selectrow_hashref("SELECT * FROM s2layers WHERE s2lid=?", undef, $id); + return 0 unless $r; + $dbh->do("INSERT INTO s2layers (b2lid, userid, type) VALUES (?,?,?)", + undef, $r->{'b2lid'}, $r->{'userid'}, $r->{'type'}); + my $newid = $dbh->{'mysql_insertid'}; + return 0 unless $newid; + + foreach my $t (qw(s2compiled s2info s2source)) { + $r = $dbh->selectrow_hashref("SELECT * FROM $t WHERE s2lid=?", undef, $id); + next unless $r; + $r->{'s2lid'} = $newid; + + # kinda hacky: we have to update the layer id + if ($t eq "s2compiled") { + $r->{'compdata'} =~ s/\$_LID = (\d+)/\$_LID = $newid/; + } + + $dbh->do("INSERT INTO $t (" . join(',', keys %$r) . ") VALUES (". + join(',', map { $dbh->quote($_) } values %$r) . ")"); + } + + return $newid; +} + +sub create_style +{ + my ($u, $name, $cloneid) = @_; + + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my $uid = $u->{userid} + 0 + or return 0; + + my $clone; + $clone = load_style($cloneid) if $cloneid; + + # can't clone somebody else's style + return 0 if $clone && $clone->{'userid'} != $uid; + + # can't create name-less style + return 0 unless $name =~ /\S/; + + $dbh->do("INSERT INTO s2styles (userid, name, modtime) VALUES (?,?, UNIX_TIMESTAMP())", + undef, $u->{'userid'}, $name); + my $styleid = $dbh->{'mysql_insertid'}; + return 0 unless $styleid; + + if ($clone) { + $clone->{'layer'}->{'user'} = + LJ::clone_layer($clone->{'layer'}->{'user'}); + + my $values; + foreach my $ly ('core','i18nc','layout','theme','i18n','user') { + next unless $clone->{'layer'}->{$ly}; + $values .= "," if $values; + $values .= "($uid, $styleid, '$ly', $clone->{'layer'}->{$ly})"; + } + $u->do("REPLACE INTO s2stylelayers2 (userid, styleid, type, s2lid) ". + "VALUES $values") if $values; + } + + return $styleid; +} + +sub load_user_styles +{ + my $u = shift; + my $opts = shift; + return undef unless $u; + + my $dbr = LJ::S2::get_s2_reader(); + + my %styles; + my $load_using = sub { + my $db = shift; + my $sth = $db->prepare("SELECT styleid, name FROM s2styles WHERE userid=?"); + $sth->execute($u->{'userid'}); + while (my ($id, $name) = $sth->fetchrow_array) { + $styles{$id} = $name; + } + }; + $load_using->($dbr); + return \%styles if scalar(%styles) || ! $opts->{'create_default'}; + + # create a new default one for them, but first check to see if they + # have one on the master. + my $dbh = LJ::get_db_writer(); + $load_using->($dbh); + return \%styles if %styles; + + $dbh->do("INSERT INTO s2styles (userid, name, modtime) VALUES (?,?, UNIX_TIMESTAMP())", undef, + $u->{'userid'}, $u->{'user'}); + my $styleid = $dbh->{'mysql_insertid'}; + return { $styleid => $u->{'user'} }; +} + +sub delete_user_style +{ + my ($u, $styleid) = @_; + return 1 unless $styleid; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my $style = load_style($dbh, $styleid); + delete_layer($style->{'layer'}->{'user'}); + + foreach my $t (qw(s2styles s2stylelayers)) { + $dbh->do("DELETE FROM $t WHERE styleid=?", undef, $styleid) + } + $u->do("DELETE FROM s2stylelayers2 WHERE userid=? AND styleid=?", undef, + $u->{userid}, $styleid); + + return 1; +} + +sub load_style +{ + my $db = ref $_[0] ? shift : undef; + my $id = shift; + return undef unless $id; + + my $memkey = [$id, "s2s:$id"]; + my $style = LJ::MemCache::get($memkey); + unless ($style) { + $db ||= LJ::S2::get_s2_reader(); + $style = $db->selectrow_hashref("SELECT styleid, userid, name, modtime ". + "FROM s2styles WHERE styleid=?", + undef, $id); + LJ::MemCache::add($memkey, $style, 3600); + } + return undef unless $style; + + my $u = LJ::load_userid($style->{userid}) + or return undef; + + $style->{'layer'} = LJ::S2::get_style_layers($u, $id) || {}; + + return $style; +} + +sub create_layer +{ + my ($userid, $b2lid, $type) = @_; + $userid = LJ::want_userid($userid); + + return 0 unless $b2lid; # caller should ensure b2lid exists and is of right type + return 0 unless + $type eq "user" || $type eq "i18n" || $type eq "theme" || + $type eq "layout" || $type eq "i18nc" || $type eq "core"; + + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + + $dbh->do("INSERT INTO s2layers (b2lid, userid, type) ". + "VALUES (?,?,?)", undef, $b2lid, $userid, $type); + return $dbh->{'mysql_insertid'}; +} + +# takes optional $u as first argument... if user argument is specified, will +# look through s2stylelayers and delete all mappings that this user has to +# this particular layer. +sub delete_layer +{ + my $u = LJ::isu($_[0]) ? shift : undef; + my $lid = shift; + return 1 unless $lid; + my $dbh = LJ::get_db_writer(); + foreach my $t (qw(s2layers s2compiled s2info s2source s2checker)) { + $dbh->do("DELETE FROM $t WHERE s2lid=?", undef, $lid); + } + + # make sure we have a user object if possible + unless ($u) { + my $us = LJ::S2::get_layer_owners($lid); + $u = $us->{$lid} if $us->{$lid}; + } + + # delete s2compiled2 if this is a layer owned by someone other than system + if ($u && $u->{user} ne 'system') { + $u->do("DELETE FROM s2compiled2 WHERE userid = ? AND s2lid = ?", + undef, $u->{userid}, $lid); + } + + # now clear memcache of the compiled data + LJ::MemCache::delete([ $lid, "s2c:$lid" ]); + + # now delete the mappings for this particular layer + if ($u) { + my $styles = LJ::S2::load_user_styles($u); + my @ids = keys %{$styles || {}}; + if (@ids) { + # map in the ids we got from the user's styles and clear layers referencing + # this particular layer id + my $in = join(',', map { $_ + 0 } @ids); + $dbh->do("DELETE FROM s2stylelayers WHERE styleid IN ($in) AND s2lid = ?", + undef, $lid); + + $u->do("DELETE FROM s2stylelayers2 WHERE userid=? AND styleid IN ($in) AND s2lid = ?", + undef, $u->{userid}, $lid); + + # now clean memcache so this change is immediately visible + LJ::MemCache::delete([ $_, "s2sl:$_" ]) foreach @ids; + } + } + + return 1; +} + +sub get_style_layers +{ + my $u = LJ::isu($_[0]) ? shift : undef; + my ($styleid, $force) = @_; + return undef unless $styleid; + + # check memcache unless $force + my $stylay = undef; + my $memkey = [$styleid, "s2sl:$styleid"]; + $stylay = LJ::MemCache::get($memkey) unless $force; + return $stylay if $stylay; + + unless ($u) { + my $sty = LJ::S2::load_style($styleid) or + die "couldn't load styleid $styleid"; + $u = LJ::load_userid($sty->{userid}) or + die "couldn't load userid $sty->{userid} for styleid $styleid"; + } + + my %stylay; + + my $fetch = sub { + my ($db, $qry, @args) = @_; + + my $sth = $db->prepare($qry); + $sth->execute(@args); + die "ERROR: " . $sth->errstr if $sth->err; + while (my ($type, $s2lid) = $sth->fetchrow_array) { + $stylay{$type} = $s2lid; + } + return 0 unless %stylay; + return 1; + }; + + unless ($fetch->($u, "SELECT type, s2lid FROM s2stylelayers2 " . + "WHERE userid=? AND styleid=?", $u->{userid}, $styleid)) { + my $dbh = LJ::get_db_writer(); + if ($fetch->($dbh, "SELECT type, s2lid FROM s2stylelayers WHERE styleid=?", + $styleid)) { + LJ::S2::set_style_layers_raw($u, $styleid, %stylay); + } + } + + # set in memcache + LJ::MemCache::set($memkey, \%stylay); + return \%stylay; +} + +# the old interfaces. handles merging with global database data if necessary. +sub set_style_layers +{ + my ($u, $styleid, %newlay) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my @lay = ('core','i18nc','layout','theme','i18n','user'); + my %need = map { $_, 1 } @lay; + delete $need{$_} foreach keys %newlay; + if (%need) { + # see if the needed layers are already on the user cluster + my ($sth, $t, $lid); + + $sth = $u->prepare("SELECT type FROM s2stylelayers2 WHERE userid=? AND styleid=?"); + $sth->execute($u->{'userid'}, $styleid); + while (($t) = $sth->fetchrow_array) { + delete $need{$t}; + } + + # if we still don't have everything, see if they exist on the + # global cluster, and we'll merge them into the %newlay being + # posted, so they end up on the user cluster + if (%need) { + $sth = $dbh->prepare("SELECT type, s2lid FROM s2stylelayers WHERE styleid=?"); + $sth->execute($styleid); + while (($t, $lid) = $sth->fetchrow_array) { + $newlay{$t} = $lid; + } + } + } + + set_style_layers_raw($u, $styleid, %newlay); +} + +# just set in user cluster, not merging with global +sub set_style_layers_raw { + my ($u, $styleid, %newlay) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + $u->do("REPLACE INTO s2stylelayers2 (userid,styleid,type,s2lid) VALUES ". + join(",", map { sprintf("(%d,%d,%s,%d)", $u->{userid}, $styleid, + $dbh->quote($_), $newlay{$_}) } + keys %newlay)); + return 0 if $u->err; + + $dbh->do("UPDATE s2styles SET modtime=UNIX_TIMESTAMP() WHERE styleid=?", + undef, $styleid); + + # delete memcache key + LJ::MemCache::delete([$styleid, "s2sl:$styleid"]); + LJ::MemCache::delete([$styleid, "s2s:$styleid"]); + + return 1; +} + +sub load_layer +{ + my $db = ref $_[0] ? shift : LJ::S2::get_s2_reader(); + my $lid = shift; + + return $db->selectrow_hashref("SELECT s2lid, b2lid, userid, type ". + "FROM s2layers WHERE s2lid=?", undef, + $lid); +} + +sub escape_context_props +{ + my $obj = shift; + if (ref $obj eq "HASH") { + while (my ($k, $v) = each %{$obj}) { + if (ref $v) { + escape_context_props($v); + } else { + $obj->{$k} =~ s/{$k} =~ s/>/>/g; + $obj->{$k} =~ s!\n!
    !g; + } + } + } elsif (ref $obj eq "ARRAY") { + foreach (@$obj) { + if (ref) { + escape_context_props($_); + } else { + s//>/g; + s!\n!
    !g; + } + } + } +} + +sub populate_system_props +{ + my $ctx = shift; + $ctx->[S2::PROPS]->{'SITEROOT'} = $LJ::SITEROOT; + $ctx->[S2::PROPS]->{'PALIMGROOT'} = $LJ::PALIMGROOT; + $ctx->[S2::PROPS]->{'SITENAME'} = $LJ::SITENAME; + $ctx->[S2::PROPS]->{'SITENAMESHORT'} = $LJ::SITENAMESHORT; + $ctx->[S2::PROPS]->{'SITENAMEABBREV'} = $LJ::SITENAMEABBREV; + $ctx->[S2::PROPS]->{'IMGDIR'} = $LJ::IMGPREFIX; +} + +sub layer_compile_user +{ + my ($layer, $overrides) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless ref $layer; + return 0 unless $layer->{'s2lid'}; + return 1 unless ref $overrides; + my $id = $layer->{'s2lid'}; + my $s2 = "layerinfo \"type\" = \"user\";\n"; + + foreach my $name (keys %$overrides) { + next if $name =~ /\W/; + my $prop = $overrides->{$name}->[0]; + my $val = $overrides->{$name}->[1]; + if ($prop->{'type'} eq "int") { + $val = int($val); + } elsif ($prop->{'type'} eq "bool") { + $val = $val ? "true" : "false"; + } else { + $val =~ s/[\\\$\"]/\\$&/g; + $val = "\"$val\""; + } + $s2 .= "set $name = $val;\n"; + } + + my $error; + return 1 if LJ::S2::layer_compile($layer, \$error, { 's2ref' => \$s2 }); + return LJ::error($error); +} + +sub layer_compile +{ + my ($layer, $err_ref, $opts) = @_; + my $dbh = LJ::get_db_writer(); + + my $lid; + if (ref $layer eq "HASH") { + $lid = $layer->{'s2lid'}+0; + } else { + $lid = $layer+0; + $layer = LJ::S2::load_layer($dbh, $lid) or return 0; + } + return 0 unless $lid; + + # get checker (cached, or via compiling) for parent layer + my $checker = get_layer_checker($layer); + unless ($checker) { + $$err_ref = "Error compiling parent layer."; + return undef; + } + + # do our compile (quickly, since we probably have the cached checker) + my $s2ref = $opts->{'s2ref'}; + unless ($s2ref) { + my $s2 = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $lid); + unless ($s2) { $$err_ref = "No source code to compile."; return undef; } + $s2ref = \$s2; + } + + my $is_system = $layer->{'userid'} == LJ::get_userid("system"); + my $untrusted = ! $LJ::S2_TRUSTED{$layer->{'userid'}} && ! $is_system; + + # system writes go to global. otherwise to user clusters. + my $dbcm; + if ($is_system) { + $dbcm = $dbh; + } else { + my $u = LJ::load_userid($layer->{'userid'}); + $dbcm = $u; + } + return 0 unless $dbcm; + + my $compiled; + my $cplr = S2::Compiler->new({ 'checker' => $checker }); + eval { + $cplr->compile_source({ + 'type' => $layer->{'type'}, + 'source' => $s2ref, + 'output' => \$compiled, + 'layerid' => $lid, + 'untrusted' => $untrusted, + 'builtinPackage' => "S2::Builtin::LJ", + }); + }; + if ($@) { $$err_ref = "Compile error: $@"; return undef; } + + # save the source, since it at least compiles + if ($opts->{'s2ref'}) { + $dbh->do("REPLACE INTO s2source (s2lid, s2code) VALUES (?,?)", + undef, $lid, ${$opts->{'s2ref'}}) or return 0; + } + + # save the checker object for later + if ($layer->{'type'} eq "core" || $layer->{'type'} eq "layout") { + $checker->cleanForFreeze(); + my $chk_frz = Storable::nfreeze($checker); + LJ::text_compress(\$chk_frz); + $dbh->do("REPLACE INTO s2checker (s2lid, checker) VALUES (?,?)", undef, + $lid, $chk_frz) or die; + } + + # load the compiled layer to test it loads and then get layerinfo/etc from it + S2::unregister_layer($lid); + eval $compiled; + if ($@) { $$err_ref = "Post-compilation error: $@"; return undef; } + if ($opts->{'redist_uniq'}) { + # used by update-db loader: + my $redist_uniq = S2::get_layer_info($lid, "redist_uniq"); + die "redist_uniq value of '$redist_uniq' doesn't match $opts->{'redist_uniq'}\n" + unless $redist_uniq eq $opts->{'redist_uniq'}; + } + + # put layerinfo into s2info + my %info = S2::get_layer_info($lid); + my $values; + my $notin; + foreach (keys %info) { + $values .= "," if $values; + $values .= sprintf("(%d, %s, %s)", $lid, + $dbh->quote($_), $dbh->quote($info{$_})); + $notin .= "," if $notin; + $notin .= $dbh->quote($_); + } + if ($values) { + $dbh->do("REPLACE INTO s2info (s2lid, infokey, value) VALUES $values") or die; + $dbh->do("DELETE FROM s2info WHERE s2lid=? AND infokey NOT IN ($notin)", undef, $lid); + } + if ($opts->{'layerinfo'}) { + ${$opts->{'layerinfo'}} = \%info; + } + + # put compiled into database, with its ID number + if ($is_system) { + $dbh->do("REPLACE INTO s2compiled (s2lid, comptime, compdata) ". + "VALUES (?, UNIX_TIMESTAMP(), ?)", undef, $lid, $compiled) or die; + } else { + my $gzipped = LJ::text_compress($compiled); + $dbcm->do("REPLACE INTO s2compiled2 (userid, s2lid, comptime, compdata) ". + "VALUES (?, ?, UNIX_TIMESTAMP(), ?)", undef, + $layer->{'userid'}, $lid, $gzipped) or die; + + # delete from memcache; we can't store since we don't know the exact comptime + LJ::MemCache::delete([ $lid, "s2c:$lid" ]); + } + + # caller might want the compiled source + if (ref $opts->{'compiledref'} eq "SCALAR") { + ${$opts->{'compiledref'}} = $compiled; + } + + S2::unregister_layer($lid); + return 1; +} + +sub get_layer_checker +{ + my $lay = shift; + my $err_ref = shift; + return undef unless ref $lay eq "HASH"; + return S2::Checker->new() if $lay->{'type'} eq "core"; + my $parid = $lay->{'b2lid'}+0 or return undef; + my $dbh = LJ::get_db_writer(); + + my $get_cached = sub { + my $frz = $dbh->selectrow_array("SELECT checker FROM s2checker WHERE s2lid=?", + undef, $parid) or return undef; + LJ::text_uncompress(\$frz); + return Storable::thaw($frz); # can be undef, on failure + }; + + # the good path + my $checker = $get_cached->(); + return $checker if $checker; + + # no cached checker (or bogus), so we have to [re]compile to get it + my $parlay = LJ::S2::load_layer($dbh, $parid); + return undef unless LJ::S2::layer_compile($parlay); + return $get_cached->(); +} + +sub load_layer_info +{ + my ($outhash, $listref) = @_; + return 0 unless ref $listref eq "ARRAY"; + return 1 unless @$listref; + my $in = join(',', map { $_+0 } @$listref); + my $dbr = LJ::S2::get_s2_reader(); + my $sth = $dbr->prepare("SELECT s2lid, infokey, value FROM s2info WHERE ". + "s2lid IN ($in)"); + $sth->execute; + while (my ($id, $k, $v) = $sth->fetchrow_array) { + $outhash->{$id}->{$k} = $v; + } + return 1; +} + +sub get_layout_langs +{ + my $src = shift; + my $layid = shift; + my %lang; + foreach (keys %$src) { + next unless /^\d+$/; + my $v = $src->{$_}; + next unless $v->{'langcode'}; + $lang{$v->{'langcode'}} = $src->{$_} + if ($v->{'type'} eq "i18nc" || + ($v->{'type'} eq "i18n" && $layid && $v->{'b2lid'} == $layid)); + } + return map { $_, $lang{$_}->{'name'} } sort keys %lang; +} + +# returns array of hashrefs +sub get_layout_themes +{ + my $src = shift; $src = [ $src ] unless ref $src eq "ARRAY"; + my $layid = shift; + my @themes; + foreach my $src (@$src) { + foreach (sort { $src->{$a}->{'name'} cmp $src->{$b}->{'name'} } keys %$src) { + next unless /^\d+$/; + my $v = $src->{$_}; + push @themes, $v if + ($v->{'type'} eq "theme" && $layid && $v->{'b2lid'} == $layid); + } + } + return @themes; +} + +sub get_layout_themes_select +{ + my @sel; + my $last_uid; + foreach my $t (get_layout_themes(@_)) { + if ($last_uid && $t->{'userid'} != $last_uid) { + push @sel, 0, '---'; # divider between system & user + } + $last_uid = $t->{'userid'}; + push @sel, $t->{'s2lid'}, $t->{'name'}; + } + return @sel; +} + +sub get_policy +{ + return $LJ::S2::CACHE_POLICY if $LJ::S2::CACHE_POLICY; + my $policy = {}; + + # localize $_ so that the while (

    ) below doesn't clobber it and cause problems + # in anybody that happens to be calling us + local $_; + + foreach my $infix ("", "-local") { + my $file = "$LJ::HOME/bin/upgrading/s2layers/policy${infix}.dat"; + my $layer = undef; + open (P, $file) or next; + while (

    ) { + s/\#.*//; + next unless /\S/; + if (/^\s*layer\s*:\s*(\S+)\s*$/) { + $layer = $1; + next; + } + next unless $layer; + s/^\s+//; s/\s+$//; + my @words = split(/\s+/, $_); + next unless $words[-1] eq "allow" || $words[-1] eq "deny"; + my $allow = $words[-1] eq "allow" ? 1 : 0; + if ($words[0] eq "use" && @words == 2) { + $policy->{$layer}->{'use'} = $allow; + } + if ($words[0] eq "props" && @words == 2) { + $policy->{$layer}->{'props'} = $allow; + } + if ($words[0] eq "prop" && @words == 3) { + $policy->{$layer}->{'prop'}->{$words[1]} = $allow; + } + } + } + + return $LJ::S2::CACHE_POLICY = $policy; +} + +sub can_use_layer +{ + my ($u, $uniq) = @_; # $uniq = redist_uniq value + return 1 if LJ::get_cap($u, "s2styles"); + my $pol = get_policy(); + my $can = 0; + foreach ('*', $uniq) { + next unless defined $pol->{$_}; + next unless defined $pol->{$_}->{'use'}; + $can = $pol->{$_}->{'use'}; + } + return $can; +} + +sub can_use_prop +{ + my ($u, $uniq, $prop) = @_; # $uniq = redist_uniq value + return 1 if LJ::get_cap($u, "s2styles"); + my $pol = get_policy(); + my $can = 0; + my @layers = ('*'); + my $pub = get_public_layers(); + if ($pub->{$uniq} && $pub->{$uniq}->{'type'} eq "layout") { + my $cid = $pub->{$uniq}->{'b2lid'}; + push @layers, $pub->{$cid}->{'uniq'} if $pub->{$cid}; + } + push @layers, $uniq; + foreach my $lay (@layers) { + foreach my $it ('props', 'prop') { + if ($it eq "props" && defined $pol->{$lay}->{'props'}) { + $can = $pol->{$lay}->{'props'}; + } + if ($it eq "prop" && defined $pol->{$lay}->{'prop'}->{$prop}) { + $can = $pol->{$lay}->{'prop'}->{$prop}; + } + } + } + return $can; +} + +sub get_journal_day_counts +{ + my ($s2page) = @_; + return $s2page->{'_day_counts'} if defined $s2page->{'_day_counts'}; + + my $u = $s2page->{'_u'}; + my $counts = {}; + + my $remote = LJ::get_remote(); + my $days = LJ::get_daycounts($u, $remote) or return {}; + foreach my $day (@$days) { + $counts->{$day->[0]}->{$day->[1]}->{$day->[2]} = $day->[3]; + } + + return $s2page->{'_day_counts'} = $counts; +} + + +## S2 object constructors + +sub CommentInfo +{ + my $opts = shift; + $opts->{'_type'} = "CommentInfo"; + $opts->{'count'} += 0; + return $opts; +} + +sub Date +{ + my @parts = @_; + my $dt = { '_type' => 'Date' }; + $dt->{'year'} = $parts[0]+0; + $dt->{'month'} = $parts[1]+0; + $dt->{'day'} = $parts[2]+0; + $dt->{'_dayofweek'} = $parts[3]; + die "S2 Builtin Date() takes day of week 1-7, not 0-6" + if defined $parts[3] && $parts[3] == 0; + return $dt; +} + +sub DateTime_unix +{ + my $time = shift; + my @gmtime = gmtime($time); + my $dt = { '_type' => 'DateTime' }; + $dt->{'year'} = $gmtime[5]+1900; + $dt->{'month'} = $gmtime[4]+1; + $dt->{'day'} = $gmtime[3]; + $dt->{'hour'} = $gmtime[2]; + $dt->{'min'} = $gmtime[1]; + $dt->{'sec'} = $gmtime[0]; + $dt->{'_dayofweek'} = $gmtime[6] + 1; + return $dt; +} + +sub DateTime_parts +{ + my @parts = split(/\s+/, shift); + my $dt = { '_type' => 'DateTime' }; + $dt->{'year'} = $parts[0]+0; + $dt->{'month'} = $parts[1]+0; + $dt->{'day'} = $parts[2]+0; + $dt->{'hour'} = $parts[3]+0; + $dt->{'min'} = $parts[4]+0; + $dt->{'sec'} = $parts[5]+0; + # the parts string comes from MySQL which has range 0-6, + # but internally and to S2 we use 1-7. + $dt->{'_dayofweek'} = $parts[6] + 1 if defined $parts[6]; + return $dt; +} + +sub Tag +{ + my ($prefix, $kw) = @_; + + my $e = { + _type => 'Tag', + #_id => $kwid, #seems unused? + name => LJ::ehtml($kw), + url => $prefix . LJ::eurl($kw), + }; + + return $e; +} + +# +# name: LJ::S2::get_tags_text +# class: s2 +# des: Gets text for display in entry for tags compatibility. +# args: ctx, taglistref +# des-ctx: Current S2 context +# des-taglistref: Arrayref containing "Tag" S2 objects +# returns: String; can be appended to entry... undef on error (no context, no taglistref) +# +sub get_tags_text { + my ($ctx, $taglist) = @_; + return undef unless $ctx && $taglist; + return "" unless @$taglist; + + # now get the customized tag text and insert the tag list and append to body + my $tags = join(', ', map { "" } @$taglist); + my $tagtext = S2::get_property_value($ctx, 'text_tags'); + $tagtext =~ s/#/$tags/; + return "

    $tagtext
    "; +} + +sub Entry +{ + my ($u, $arg) = @_; + my $e = { + '_type' => 'Entry', + 'link_keyseq' => [ 'edit_entry', 'edit_tags' ], + 'metadata' => {}, + }; + foreach (qw(subject _rawsubject text journal poster new_day end_day + comments userpic permalink_url itemid)) { + $e->{$_} = $arg->{$_}; + } + + $e->{'time'} = DateTime_parts($arg->{'dateparts'}); + $e->{'depth'} = 0; # Entries are always depth 0. Comments are 1+. + + my $link_keyseq = $e->{'link_keyseq'}; + push @$link_keyseq, 'mem_add' unless $LJ::DISABLED{'memories'}; + push @$link_keyseq, 'tell_friend' unless $LJ::DISABLED{'tellafriend'}; + # Note: nav_prev and nav_next are not included in the keyseq anticipating + # that their placement relative to the others will vary depending on + # layout. + + if ($arg->{'security'} eq "public") { + # do nothing. + } elsif ($arg->{'security'} eq "usemask") { + $e->{'security'} = "protected"; + $e->{'security_icon'} = Image_std("security-protected"); + } elsif ($arg->{'security'} eq "private") { + $e->{'security'} = "private"; + $e->{'security_icon'} = Image_std("security-private"); + } + + my $p = $arg->{'props'}; + + if ($p->{'current_music'}) { + $e->{'metadata'}->{'music'} = $p->{'current_music'}; + LJ::CleanHTML::clean_subject(\$e->{'metadata'}->{'music'}); + } + if (my $mid = $p->{'current_moodid'}) { + my $theme = defined $arg->{'moodthemeid'} ? $arg->{'moodthemeid'} : $u->{'moodthemeid'}; + my %pic; + $e->{'mood_icon'} = Image($pic{'pic'}, $pic{'w'}, $pic{'h'}) + if LJ::get_mood_picture($theme, $mid, \%pic); + if (my $mood = LJ::mood_name($mid)) { + $e->{'metadata'}->{'mood'} = $mood; + } + } + if ($p->{'current_mood'}) { + $e->{'metadata'}->{'mood'} = $p->{'current_mood'}; + LJ::CleanHTML::clean_subject(\$e->{'metadata'}->{'mood'}); + } + + $e->{'tags'} = []; + if ($p->{'tags'}) { + my $prefix = $arg->{'base_url'} ? $arg->{'base_url'} . '/tag/' : LJ::journal_base($u) . '/tag/'; + my @taglist; + + foreach (@{$p->{'tags'}}) { + push @taglist, Tag($prefix, $_); + } + + my $t = $arg->{enable_tags_compatibility}; #[bool, ctx] + if ($t && $t->[0]) { + $e->{'text'} .= LJ::S2::get_tags_text($t->[1], \@taglist); + } + + $e->{'tags'} = \@taglist; + } + + return $e; +} + +sub Friend +{ + my ($u) = @_; + my $o = UserLite($u); + $o->{'_type'} = "Friend"; + $o->{'bgcolor'} = S2::Builtin::LJ::Color__Color($u->{'bgcolor'}); + $o->{'fgcolor'} = S2::Builtin::LJ::Color__Color($u->{'fgcolor'}); + return $o; +} + +sub Null +{ + my $type = shift; + return { + '_type' => $type, + '_isnull' => 1, + }; +} + +sub Page +{ + my ($u, $opts) = @_; + my $styleid = $u->{'_s2styleid'} + 0; + my $base_url = $u->{'_journalbase'}; + + my $get = $opts->{'getargs'}; + my %args; + foreach my $k (keys %$get) { + my $v = $get->{$k}; + next unless $k =~ s/^\.//; + $args{$k} = $v; + } + + # get MAX(modtime of style layers) + my $stylemodtime = S2::get_style_modtime($opts->{'ctx'}); + my $style = load_style($u->{'s2_style'}); + $stylemodtime = $style->{'modtime'} if $style->{'modtime'} > $stylemodtime; + + my $linkobj = LJ::Links::load_linkobj($u); + my $linklist = [ map { UserLink($_) } @$linkobj ]; + + my $p = { + '_type' => 'Page', + '_u' => $u, + 'view' => '', + 'args' => \%args, + 'journal' => User($u), + 'journal_type' => $u->{'journaltype'}, + 'time' => DateTime_unix(time), + 'base_url' => $base_url, + 'stylesheet_url' => "$base_url/res/$styleid/stylesheet?$stylemodtime", + 'view_url' => { + 'recent' => "$base_url/", + 'userinfo' => "$LJ::SITEROOT/userinfo.bml?user=$u->{'user'}", + 'archive' => "$base_url/calendar", + 'friends' => "$base_url/friends", + }, + 'linklist' => $linklist, + 'views_order' => [ 'recent', 'archive', 'friends', 'userinfo' ], + 'global_title' => LJ::ehtml($u->{'journaltitle'} || $u->{'name'}), + 'global_subtitle' => LJ::ehtml($u->{'journalsubtitle'}), + 'head_content' => '', + }; + + if (LJ::are_hooks('s2_head_content_extra')) { + my $remote = LJ::get_remote(); + $p->{head_content} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + if ($LJ::UNICODE && $opts && $opts->{'saycharset'}) { + $p->{'head_content'} .= '\n"; + } + + # Automatic Discovery of RSS/Atom + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + + # FOAF autodiscovery + my $real_user = 1; + foreach (@LJ::PROTECTED_USERNAMES) { + $real_user = 0 if ($u->{'user'} =~ $_); + } + if ($real_user) { + my $foafurl = $u->{external_foaf_url} ? LJ::eurl($u->{external_foaf_url}) : "$p->{base_url}/data/foaf"; + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{email}); + $p->{head_content} .= qq{\n}; + $p->{head_content} .= qq{\n}; + } + + return $p; +} + +sub Image +{ + my ($url, $w, $h, $alttext) = @_; + return { + '_type' => 'Image', + 'url' => $url, + 'width' => $w, + 'height' => $h, + 'alttext' => $alttext, + }; +} + +sub Image_std +{ + my $name = shift; + my $ctx = $LJ::S2::CURR_CTX or die "No S2 context available "; + + unless ($LJ::S2::RES_MADE++) { + $LJ::S2::RES_CACHE = { + 'security-protected' => Image("$LJ::IMGPREFIX/icon_protected.gif", 14, 15, $ctx->[S2::PROPS]->{'text_icon_alt_protected'}), + 'security-private' => Image("$LJ::IMGPREFIX/icon_private.gif", 16, 16, $ctx->[S2::PROPS]->{'text_icon_alt_private'}), + }; + } + return $LJ::S2::RES_CACHE->{$name}; +} + +sub Image_userpic +{ + my ($u, $picid, $kw) = @_; + + $picid ||= LJ::get_picid_from_keyword($u, $kw); + + my $pi = LJ::get_userpic_info($u); + my $p = $pi->{'pic'}->{$picid}; + + return Null("Image") unless $p; + return { + '_type' => "Image", + 'url' => "$LJ::USERPIC_ROOT/$picid/$u->{'userid'}", + 'width' => $p->{'width'}, + 'height' => $p->{'height'}, + 'alttext' => "", + }; +} + +sub ItemRange_fromopts +{ + my $opts = shift; + my $ir = {}; + + my $items = $opts->{'items'}; + my $page_size = ($opts->{'pagesize'}+0) || 25; + my $page = $opts->{'page'}+0 || 1; + my $num_items = scalar @$items; + + my $pages = POSIX::ceil($num_items / $page_size) || 1; + if ($page > $pages) { $page = $pages; } + + splice(@$items, 0, ($page-1)*$page_size) if $page > 1; + splice(@$items, $page_size) if @$items > $page_size; + + $ir->{'current'} = $page; + $ir->{'total'} = $pages; + $ir->{'total_subitems'} = $num_items; + $ir->{'from_subitem'} = ($page-1) * $page_size + 1; + $ir->{'num_subitems_displayed'} = @$items; + $ir->{'to_subitem'} = $ir->{'from_subitem'} + $ir->{'num_subitems_displayed'} - 1; + $ir->{'all_subitems_displayed'} = ($pages == 1); + $ir->{'_url_of'} = $opts->{'url_of'}; + return ItemRange($ir); +} + +sub ItemRange +{ + my $h = shift; # _url_of = sub($n) + $h->{'_type'} = "ItemRange"; + + my $url_of = ref $h->{'_url_of'} eq "CODE" ? $h->{'_url_of'} : sub {"";}; + + $h->{'url_next'} = $url_of->($h->{'current'} + 1) + unless $h->{'current'} >= $h->{'total'}; + $h->{'url_prev'} = $url_of->($h->{'current'} - 1) + unless $h->{'current'} <= 1; + $h->{'url_first'} = $url_of->(1) + unless $h->{'current'} == 1; + $h->{'url_last'} = $url_of->($h->{'total'}) + unless $h->{'current'} == $h->{'total'}; + + return $h; +} + +sub User +{ + my ($u) = @_; + my $o = UserLite($u); + $o->{'_type'} = "User"; + $o->{'default_pic'} = Image_userpic($u, $u->{'defaultpicid'}); + $o->{'userpic_listing_url'} = "$LJ::SITEROOT/allpics.bml?user=".$u->{'user'}; + $o->{'website_url'} = LJ::ehtml($u->{'url'}); + $o->{'website_name'} = LJ::ehtml($u->{'urlname'}); + return $o; +} + +sub UserLink +{ + my $link = shift; # hashref + + # a dash means pass to s2 as blank so it will just insert a blank line + $link->{'title'} = '' if $link->{'title'} eq "-"; + + return { + '_type' => 'UserLink', + 'is_heading' => $link->{'url'} ? 0 : 1, + 'url' => LJ::ehtml($link->{'url'}), + 'title' => LJ::ehtml($link->{'title'}), + 'children' => $link->{'children'} || [], # TODO: implement parent-child relationships + }; +} + +sub UserLite +{ + my ($u) = @_; + + my $display_name; + if (eval { $u->display_name } ) { + $display_name = $u->display_name; + } + else { + $display_name = LJ::ehtml($u->{'name'}); +# print STDERR "User " . $u->{'name'} . " does not have a display name.\n"; + } + + my $o = { + '_type' => 'UserLite', + '_u' => $u, + 'username' => $display_name, + 'name' => LJ::ehtml($u->{'name'}), + 'journal_type' => $u->{'journaltype'}, + }; + return $o; +} + + +############### + +package S2::Builtin::LJ; +use strict; + +sub AUTOLOAD { + no strict; + if ($AUTOLOAD =~ /::(\w+)$/) { + my $real = \&{"S2::Builtin::$1"}; + *{$AUTOLOAD} = $real; + return $real->(@_); + } + die "No such builtin: $AUTOLOAD"; +} + +sub ehtml +{ + my ($ctx, $text) = @_; + return LJ::ehtml($text); +} + +sub eurl +{ + my ($ctx, $text) = @_; + return LJ::eurl($text); +} + +# escape tags only +sub etags { + my ($ctx, $text) = @_; + $text =~ s//>/g; + return $text; +} + +# sanitize URLs +sub clean_url { + my ($ctx, $text) = @_; + unless ($text =~ m!^https?://[^\'\"\\]*$!) { + $text = ""; + } + return $text; +} + +sub get_page +{ + return $LJ::S2::CURR_PAGE; +} + +sub get_plural_phrase +{ + my ($ctx, $n, $prop) = @_; + my $form = S2::run_function($ctx, "lang_map_plural(int)", $n); + my $a = $ctx->[S2::PROPS]->{"_plurals_$prop"}; + unless (ref $a eq "ARRAY") { + $a = $ctx->[S2::PROPS]->{"_plurals_$prop"} = [ split(m!\s*//\s*!, $ctx->[S2::PROPS]->{$prop}) ]; + } + my $text = $a->[$form]; + + # this fixes missing plural forms for russians (who have 2 plural forms) + # using languages like english with 1 plural form + $text = $a->[-1] unless defined $text; + + $text =~ s/\#/$n/; + return LJ::ehtml($text); +} + +sub get_url +{ + my ($ctx, $obj, $view) = @_; + my $dir = "users"; + my $journal_type; + my $user; + + # now get data from one of two paths, depending on if we were given a UserLite + # object or a string for the username + if (ref $obj eq 'HASH') { + $journal_type = $obj->{journal_type}; + $user = $obj->{username}; + } else { + my $u = LJ::load_user($obj); + $journal_type = $u ? $u->{journaltype} : 'P'; + $user = $u ? $u->{user} : $obj; + } + + # construct URL to return + $dir = 'community' if $journal_type eq 'C'; + $view = "info" if $view eq "userinfo"; + $view = "calendar" if $view eq "archive"; + $view = "" if $view eq "recent"; + return "$LJ::SITEROOT/$dir/$user/$view"; +} + +sub htmlattr +{ + my ($ctx, $name, $value) = @_; + return "" if $value eq ""; + $name = lc($name); + return "" if $name =~ /[^a-z]/; + return " $name=\"" . LJ::ehtml($value) . "\""; +} + +sub rand +{ + my ($ctx, $aa, $bb) = @_; + my ($low, $high); + if (ref $aa eq "ARRAY") { + ($low, $high) = (0, @$aa - 1); + } elsif (! defined $bb) { + ($low, $high) = (1, $aa); + } else { + ($low, $high) = ($aa, $bb); + } + return int(rand($high - $low + 1)) + $low; +} + +sub viewer_logged_in +{ + my ($ctx) = @_; + my $remote = LJ::get_remote(); + return defined $remote; +} + +sub viewer_is_owner +{ + my ($ctx) = @_; + my $remote = LJ::get_remote(); + return 0 unless $remote; + return $remote->{'userid'} == $LJ::S2::CURR_PAGE->{'_u'}->{'userid'}; +} + +sub weekdays +{ + my ($ctx) = @_; + return [ 1..7 ]; # FIXME: make this conditionally monday first: [ 2..7, 1 ] +} + +sub set_handler +{ + my ($ctx, $hook, $stmts) = @_; + my $p = $LJ::S2::CURR_PAGE; + return unless $hook =~ /^\w+\#?$/; + $hook =~ s/\#$/ARG/; + + $S2::pout->("\n"); +} + +sub zeropad +{ + my ($ctx, $num, $digits) = @_; + $num += 0; + $digits += 0; + return sprintf("%0${digits}d", $num); +} +*int__zeropad = \&zeropad; + + +sub Color__update_hsl +{ + my ($this, $force) = @_; + return if $this->{'_hslset'}++; + ($this->{'_h'}, $this->{'_s'}, $this->{'_l'}) = + S2::Color::rgb_to_hsl($this->{'r'}, $this->{'g'}, $this->{'b'}); + $this->{$_} = int($this->{$_} * 255 + 0.5) foreach qw(_h _s _l); +} + +sub Color__update_rgb +{ + my ($this) = @_; + + ($this->{'r'}, $this->{'g'}, $this->{'b'}) = + S2::Color::hsl_to_rgb( map { $this->{$_} / 255 } qw(_h _s _l) ); + Color__make_string($this); +} + +sub Color__make_string +{ + my ($this) = @_; + $this->{'as_string'} = sprintf("\#%02x%02x%02x", + $this->{'r'}, + $this->{'g'}, + $this->{'b'}); +} + +# public functions +sub Color__Color +{ + my ($s) = @_; + $s =~ s/^\#//; + $s =~ s/^(\w)(\w)(\w)$/$1$1$2$2$3$3/s; # 'c30' => 'cc3300' + return if $s =~ /[^a-fA-F0-9]/ || length($s) != 6; + + my $this = { '_type' => 'Color' }; + $this->{'r'} = hex(substr($s, 0, 2)); + $this->{'g'} = hex(substr($s, 2, 2)); + $this->{'b'} = hex(substr($s, 4, 2)); + $this->{$_} = $this->{$_} % 256 foreach qw(r g b); + + Color__make_string($this); + return $this; +} + +sub Color__clone +{ + my ($ctx, $this) = @_; + return { %$this }; +} + +sub Color__set_hsl +{ + my ($this, $h, $s, $l) = @_; + $this->{'_h'} = $h % 256; + $this->{'_s'} = $s % 256; + $this->{'_l'} = $l % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); +} + +sub Color__red { + my ($ctx, $this, $r) = @_; + if (defined $r) { + $this->{'r'} = $r % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'r'}; +} + +sub Color__green { + my ($ctx, $this, $g) = @_; + if (defined $g) { + $this->{'g'} = $g % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'g'}; +} + +sub Color__blue { + my ($ctx, $this, $b) = @_; + if (defined $b) { + $this->{'b'} = $b % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'b'}; +} + +sub Color__hue { + my ($ctx, $this, $h) = @_; + + if (defined $h) { + $this->{'_h'} = $h % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + $this->{'_h'}; +} + +sub Color__saturation { + my ($ctx, $this, $s) = @_; + if (defined $s) { + $this->{'_s'} = $s % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + $this->{'_s'}; +} + +sub Color__lightness { + my ($ctx, $this, $l) = @_; + + if (defined $l) { + $this->{'_l'} = $l % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + + $this->{'_l'}; +} + +sub Color__inverse { + my ($ctx, $this) = @_; + my $new = { + '_type' => 'Color', + 'r' => 255 - $this->{'r'}, + 'g' => 255 - $this->{'g'}, + 'b' => 255 - $this->{'b'}, + }; + Color__make_string($new); + return $new; +} + +sub Color__average { + my ($ctx, $this, $other) = @_; + my $new = { + '_type' => 'Color', + 'r' => int(($this->{'r'} + $other->{'r'}) / 2 + .5), + 'g' => int(($this->{'g'} + $other->{'g'}) / 2 + .5), + 'b' => int(($this->{'b'} + $other->{'b'}) / 2 + .5), + }; + Color__make_string($new); + return $new; +} + +sub Color__lighter { + my ($ctx, $this, $amt) = @_; + $amt = defined $amt ? $amt : 30; + + Color__update_hsl($this); + + my $new = { + '_type' => 'Color', + '_hslset' => 1, + '_h' => $this->{'_h'}, + '_s' => $this->{'_s'}, + '_l' => ($this->{'_l'} + $amt > 255 ? 255 : $this->{'_l'} + $amt), + }; + + Color__update_rgb($new); + return $new; +} + +sub Color__darker { + my ($ctx, $this, $amt) = @_; + $amt = defined $amt ? $amt : 30; + + Color__update_hsl($this); + + my $new = { + '_type' => 'Color', + '_hslset' => 1, + '_h' => $this->{'_h'}, + '_s' => $this->{'_s'}, + '_l' => ($this->{'_l'} - $amt < 0 ? 0 : $this->{'_l'} - $amt), + }; + + Color__update_rgb($new); + return $new; +} + +sub Comment__get_link +{ + my ($ctx, $this, $key) = @_; + if ($key eq "delete_comment" || $key eq "unscreen_comment" || $key eq "screen_comment" || + $key eq "freeze_thread" || $key eq "unfreeze_thread") { + my $page = get_page(); + my $u = $page->{'_u'}; + my $post_user = $page->{'entry'} ? $page->{'entry'}->{'poster'}->{'username'} : undef; + my $com_user = $this->{'poster'} ? $this->{'poster'}->{'username'} : undef; + my $remote = LJ::get_remote(); + if ($key eq "delete_comment") { + return undef unless LJ::Talk::can_delete($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/delcomment.bml?journal=$u->{'user'}&id=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_delete"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_del.gif", 22, 20), + }; + } + if ($key eq "freeze_thread") { + return undef if $this->{'frozen'}; + return undef unless LJ::Talk::can_freeze($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=freeze&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_freeze"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_freeze.gif", 22, 20), + }; + } + if ($key eq "unfreeze_thread") { + return undef unless $this->{'frozen'}; + return undef unless LJ::Talk::can_unfreeze($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=unfreeze&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_unfreeze"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_unfreeze.gif", 22, 20), + }; + } + if ($key eq "screen_comment") { + return undef if $this->{'screened'}; + return undef unless LJ::Talk::can_screen($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=screen&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_screen"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_scr.gif", 22, 20), + }; + } + if ($key eq "unscreen_comment") { + return undef unless $this->{'screened'}; + return undef unless LJ::Talk::can_unscreen($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=unscreen&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_unscreen"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_unscr.gif", 22, 20), + }; + } + } +} + +sub Comment__print_multiform_check +{ + my ($ctx, $this) = @_; + my $tid = $this->{'talkid'} >> 8; + $S2::pout->(""); +} + +# class 'date' +sub Date__day_of_week +{ + my ($ctx, $dt) = @_; + return $dt->{'_dayofweek'} if defined $dt->{'_dayofweek'}; + return $dt->{'_dayofweek'} = LJ::day_of_week($dt->{'year'}, $dt->{'month'}, $dt->{'day'}) + 1; +} +*DateTime__day_of_week = \&Date__day_of_week; + +my %dt_vars = ( + 'm' => "\$time->{month}", + 'mm' => "sprintf('%02d', \$time->{month})", + 'd' => "\$time->{day}", + 'dd' => "sprintf('%02d', \$time->{day})", + 'yy' => "sprintf('%02d', \$time->{year} % 100)", + 'yyyy' => "\$time->{year}", + 'mon' => "\$ctx->[S2::PROPS]->{lang_monthname_short}->[\$time->{month}]", + 'month' => "\$ctx->[S2::PROPS]->{lang_monthname_long}->[\$time->{month}]", + 'da' => "\$ctx->[S2::PROPS]->{lang_dayname_short}->[Date__day_of_week(\$ctx, \$time)]", + 'day' => "\$ctx->[S2::PROPS]->{lang_dayname_long}->[Date__day_of_week(\$ctx, \$time)]", + 'dayord' => "S2::run_function(\$ctx, \"lang_ordinal(int)\", \$time->{day})", + 'H' => "\$time->{hour}", + 'HH' => "sprintf('%02d', \$time->{hour})", + 'h' => "(\$time->{hour} % 12 || 12)", + 'hh' => "sprintf('%02d', (\$time->{hour} % 12 || 12))", + 'min' => "sprintf('%02d', \$time->{min})", + 'sec' => "sprintf('%02d', \$time->{sec})", + 'a' => "(\$time->{hour} < 12 ? 'a' : 'p')", + 'A' => "(\$time->{hour} < 12 ? 'A' : 'P')", + ); + +sub Date__date_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "short"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_datefmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_datefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_date_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_date_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} +*DateTime__date_format = \&Date__date_format; + +sub DateTime__time_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "short"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_timefmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_timefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_time_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_time_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} + +sub EntryLite__get_link +{ + my ($ctx, $this, $key) = @_; + return undef; +} + +sub EntryLite__get_tags_text +{ + my ($ctx, $this) = @_; + return LJ::S2::get_tags_text($ctx, $this->{tags}) || ""; +} +*Entry__get_tags_text = \&EntryLite__get_tags_text; + +sub EntryLite__get_plain_subject +{ + my ($ctx, $this) = @_; + return $this->{'_plainsubject'} if $this->{'_plainsubject'}; + return $this->{'subject'} unless $this->{'_rawsubject'}; + my $subj = $this->{'subject'}; + LJ::CleanHTML::clean_subject_all(\$subj); + return $this->{'_plainsubject'} = $subj; +} +*Entry__get_plain_subject = \&EntryLite__get_plain_subject; + +sub Entry__get_link +{ + my ($ctx, $this, $key) = @_; + if ($key eq "nav_prev" || $key eq "edit_entry" || $key eq "mem_add" || + $key eq "tell_friend" || $key eq "nav_next" || $key eq "edit_tags") + { + my $journal = $this->{'journal'}->{'username'}; + my $poster = $this->{'poster'}->{'username'}; + my $remote = LJ::get_remote(); + + if ($key eq "edit_entry") { + return undef unless $remote && ($remote->{'user'} eq $journal || + $remote->{'user'} eq $poster || + LJ::can_manage($remote, LJ::load_user($journal))); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/editjournal.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Edit Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_edit.gif", 22, 20), + } + } + if ($key eq "edit_tags") { + return undef unless $remote && LJ::Tags::can_add_tags(LJ::load_user($journal), $remote); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/edittags.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => 'Edit Tags', + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_edittags.gif", 22, 20), + }; + } + if ($key eq "tell_friend") { + return undef if $LJ::DISABLED{'tellafriend'}; + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/tools/tellafriend.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Tell A Friend", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_tellfriend.gif", 22, 20), + }; + } + if ($key eq "mem_add") { + return undef if $LJ::DISABLED{'memories'}; + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/tools/memadd.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Add to Memories", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_memories.gif", 22, 20), + }; + } + if ($key eq "nav_prev") { + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/go.bml?journal=$journal&itemid=$this->{'itemid'}&dir=prev", + 'caption' => "Previous Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_prev.gif", 22, 20), + }; + } + if ($key eq "nav_next") { + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/go.bml?journal=$journal&itemid=$this->{'itemid'}&dir=next", + 'caption' => "Next Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_next.gif", 22, 20), + }; + } + } +} + +sub Entry__plain_subject +{ + my ($ctx, $this) = @_; + return $this->{'_subject_plain'} if defined $this->{'_subject_plain'}; + $this->{'_subject_plain'} = $this->{'subject'}; + LJ::CleanHTML::clean_subject_all(\$this->{'_subject_plain'}); + return $this->{'_subject_plain'}; +} + +sub EntryPage__print_multiform_actionline +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + my $pr = $ctx->[S2::PROPS]; + $S2::pout->($pr->{'text_multiform_des'} . "\n" . + LJ::html_select({'name' => 'mode' }, + "" => "", + map { $_ => $pr->{"text_multiform_opt_$_"} } + qw(unscreen screen delete)) . "\n" . + LJ::html_submit('', $pr->{'text_multiform_btn'}, + { "onclick" => "return (document.multiform.mode.value != \"delete\") " . + "|| confirm(\"" . LJ::ejs($pr->{'text_multiform_conf_delete'}) . "\");" })); +} + +sub EntryPage__print_multiform_end +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + $S2::pout->(""); +} + +sub EntryPage__print_multiform_start +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + $S2::pout->("
    \n" . + LJ::html_hidden("ditemid", $this->{'entry'}->{'itemid'}, + "journal", $this->{'entry'}->{'journal'}->{'username'}) . "\n"); +} + +sub Page__visible_tag_list +{ + my $ctx = shift; + my $remote = LJ::get_remote(); + my $u = $LJ::S2::CURR_PAGE->{'_u'}; + return [] unless $u; + + my $tags = LJ::Tags::get_usertags($u, { remote => $remote }); + return [] unless $tags; + + my $prefix = LJ::journal_base($u) . '/tag/'; + my @taglist; + foreach my $kwid (keys %{$tags}) { + # only show tags for display + next unless $tags->{$kwid}->{display}; + + # create tag object + push @taglist, LJ::S2::Tag($prefix, $tags->{$kwid}->{name}); + } + + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + return \@taglist; +} +*RecentPage__visible_tag_list = \&Page__visible_tag_list; +*DayPage__visible_tag_list = \&Page__visible_tag_list; +*MonthPage__visible_tag_list = \&Page__visible_tag_list; +*YearPage__visible_tag_list = \&Page__visible_tag_list; +*FriendsPage__visible_tag_list = \&Page__visible_tag_list; +*EntryPage__visible_tag_list = \&Page__visible_tag_list; +*ReplyPage__visible_tag_list = \&Page__visible_tag_list; + +sub Page__get_latest_month +{ + my ($ctx, $this) = @_; + return $this->{'_latest_month'} if defined $this->{'_latest_month'}; + my $counts = LJ::S2::get_journal_day_counts($this); + my ($year, $month); + my @years = sort { $a <=> $b } keys %$counts; + if (@years) { + # year/month of last post + $year = $years[-1]; + $month = (sort { $a <=> $b } keys %{$counts->{$year}})[-1]; + } else { + # year/month of current date, if no posts + my @now = gmtime(time); + ($year, $month) = ($now[5]+1900, $now[4]+1); + } + return $this->{'_latest_month'} = LJ::S2::YearMonth($this, { + 'year' => $year, + 'month' => $month, + }); +} +*RecentPage__get_latest_month = \&Page__get_latest_month; +*DayPage__get_latest_month = \&Page__get_latest_month; +*MonthPage__get_latest_month = \&Page__get_latest_month; +*YearPage__get_latest_month = \&Page__get_latest_month; +*FriendsPage__get_latest_month = \&Page__get_latest_month; +*EntryPage__get_latest_month = \&Page__get_latest_month; +*ReplyPage__get_latest_month = \&Page__get_latest_month; + +sub palimg_modify +{ + my ($ctx, $filename, $items) = @_; + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + return $url unless $items && @$items; + return undef if @$items > 7; + $url .= "/p"; + foreach my $pi (@$items) { + die "Can't modify a palette index greater than 15 with palimg_modify\n" if + $pi->{'index'} > 15; + $url .= sprintf("%1x%02x%02x%02x", + $pi->{'index'}, + $pi->{'color'}->{'r'}, + $pi->{'color'}->{'g'}, + $pi->{'color'}->{'b'}); + } + return $url; +} + +sub palimg_tint +{ + my ($ctx, $filename, $bcol, $dcol) = @_; # bright color, dark color [opt] + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + $url .= "/pt"; + foreach my $col ($bcol, $dcol) { + next unless $col; + $url .= sprintf("%02x%02x%02x", + $col->{'r'}, $col->{'g'}, $col->{'b'}); + } + return $url; +} + +sub palimg_gradient +{ + my ($ctx, $filename, $start, $end) = @_; + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + $url .= "/pg"; + foreach my $pi ($start, $end) { + next unless $pi; + $url .= sprintf("%02x%02x%02x%02x", + $pi->{'index'}, + $pi->{'color'}->{'r'}, + $pi->{'color'}->{'g'}, + $pi->{'color'}->{'b'}); + } + return $url; +} + +sub userlite_base_url +{ + my ($ctx, $UserLite) = @_; + my $u = $UserLite->{_u}; + if ($u->{journaltype} eq "P") { + return "$LJ::SITEROOT/users/$u->{user}"; + } elsif ($u->{journaltype} eq "C") { + return "$LJ::SITEROOT/community/$u->{user}"; + } elsif ($u->{journaltype} eq "I") { + return $u->url; + } +} + +sub userlite_as_string +{ + my ($ctx, $UserLite) = @_; + return LJ::ljuser($UserLite->{'_u'}); +} + +sub PalItem +{ + my ($ctx, $idx, $color) = @_; + return undef unless $color && $color->{'_type'} eq "Color"; + return undef unless $idx >= 0 && $idx <= 255; + return { + '_type' => 'PalItem', + 'color' => $color, + 'index' => $idx+0, + }; +} + +sub YearMonth__month_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "long"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_monthfmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_timefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_month_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_month_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} + +sub Image__set_url { + my ($ctx, $img, $newurl) = @_; + $img->{'url'} = LJ::eurl($newurl); +} + +sub ItemRange__url_of +{ + my ($ctx, $this, $n) = @_; + return "" unless ref $this->{'_url_of'} eq "CODE"; + return $this->{'_url_of'}->($n+0); +} + +sub UserLite__equals +{ + return $_[1]->{'_u'}{'userid'} == $_[2]->{'_u'}{'userid'}; +} +*User__equals = \&UserLite__equals; +*Friend__equals = \&UserLite__equals; + +sub string__substr +{ + my ($ctx, $this, $start, $length) = @_; + use utf8; + return substr($this, $start, $length); +} + +sub string__length +{ + use utf8; + my ($ctx, $this) = @_; + return length($this); +} + +sub string__lower +{ + use utf8; + my ($ctx, $this) = @_; + return lc($this); +} + +sub string__upper +{ + use utf8; + my ($ctx, $this) = @_; + return uc($this); +} + +sub string__upperfirst +{ + use utf8; + my ($ctx, $this) = @_; + return ucfirst($this); +} + +sub string__starts_with +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /^\Q$str\E/; +} + +sub string__ends_with +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /\Q$str\E$/; +} + +sub string__contains +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /\Q$str\E/; +} + +sub string__repeat +{ + use utf8; + my ($ctx, $this, $num) = @_; + $num += 0; + my $size = length($this) * $num; + return "[too large]" if $size > 5000; + return $this x $num; +} + +1; diff --git a/local/cgi-bin/LJ/S2/DayPage.pm b/local/cgi-bin/LJ/S2/DayPage.pm new file mode 100755 index 0000000..37f9394 --- /dev/null +++ b/local/cgi-bin/LJ/S2/DayPage.pm @@ -0,0 +1,232 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub DayPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "DayPage"; + $p->{'view'} = "day"; + $p->{'entries'} = []; + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/calendar" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + my $get = $opts->{'getargs'}; + + my $month = $get->{'month'}; + my $day = $get->{'day'}; + my $year = $get->{'year'}; + my @errors = (); + + if ($opts->{'pathextra'} =~ m!^/(\d\d\d\d)/(\d\d)/(\d\d)\b!) { + ($month, $day, $year) = ($2, $3, $1); + } + + $opts->{'errors'} = []; + if ($year !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant year."; } + if ($month !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant month."; } + if ($day !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant day."; } + if ($month < 1 || $month > 12 || int($month) != $month) { push @{$opts->{'errors'}}, "Invalid month."; } + if ($year < 1970 || $year > 2038 || int($year) != $year) { push @{$opts->{'errors'}}, "Invalid year: $year"; } + if ($day < 1 || $day > 31 || int($day) != $day) { push @{$opts->{'errors'}}, "Invalid day."; } + if (scalar(@{$opts->{'errors'}})==0 && $day > LJ::days_in_month($month, $year)) { push @{$opts->{'errors'}}, "That month doesn't have that many days."; } + return if @{$opts->{'errors'}}; + + $p->{'date'} = Date($year, $month, $day); + # mysqldate_to_time(): ^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/ -> unixtime, with check. + # why not using get_recent_items() ? + +#use Time::HiRes qw(gettimeofday tv_interval); +#my $t0 = [gettimeofday]; +#my @elapsed; +#push @elapsed, (tv_interval ($t0)); +#print STDERR "@elapsed \n"; + + my $secwhere = "AND security='public'"; + my $viewall = 0; + my $viewsome = 0; # see public posts from suspended users + if ($remote) { + + # do they have the viewall priv? + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "day: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P' || $remote->{'journaltype'} eq 'I') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (security='public' OR (security='usemask' AND allowmask & $gmask))" + if $gmask; + } + } + + my $dbcr = LJ::get_cluster_reader($u); + unless ($dbcr) { + push @{$opts->{'errors'}}, "Database temporarily unavailable"; + return; + } + + # load the log items + my $dateformat = "%Y %m %d %H %i %s %w"; # yyyy mm dd hh mm ss day_of_week + my $sth = $dbcr->prepare("SELECT jitemid AS itemid, posterid, security, DATE_FORMAT(eventtime, \"$dateformat\") AS 'alldatepart', anum ". + "FROM log2 " . + "WHERE journalid=$u->{'userid'} AND year=$year AND month=$month AND day=$day $secwhere " . + "ORDER BY eventtime, logtime LIMIT 200"); + $sth->execute; + + my @items; + push @items, $_ while $_ = $sth->fetchrow_hashref; +#push @elapsed, (tv_interval ($t0)); + + LJ::fill_items_with_text_props(\@items, $u); + + # load 'opt_ljcut_disable_lastn' prop for $remote. + LJ::load_user_props($remote, "opt_ljcut_disable_lastn"); + + my (%apu, %apu_lite); # alt poster users; UserLite objects + foreach (@items) { + next unless $_->{'posterid'} != $u->{'userid'}; + $apu{$_->{'posterid'}} = undef; + } + if (%apu) { + LJ::load_userids_multiple([map { $_, \$apu{$_} } keys %apu], [$u]); + $apu_lite{$_} = UserLite($apu{$_}) foreach keys %apu; + } + + my $userlite_journal = UserLite($u); +#push @elapsed, (tv_interval ($t0)); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart, $anum) = + map { $item->{$_} } qw(posterid itemid security alldatepart anum); + + my $props = $item->{'props'}; + + my $replycount = $props->{'replycount'}; + my $subject = $item->{'text'}->[0]; + my $text = $item->{'text'}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + # don't show posts from suspended users + next ENTRY if $apu{$posterid} && $apu{$posterid}->{'statusvis'} eq 'S' && ! $viewsome; + + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid*256 + $anum; + + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $props->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $anum), + 'ljcut_disable' => $remote->{'opt_ljcut_disable_lastn'}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$text); + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount; # && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $props->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($props->{'hasscreened'} && $remote && + ($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $apu_lite{$posterid} or die "No apu_lite for posterid=$posterid"; + $pu = $apu{$posterid}; + } + my $userpic = Image_userpic($pu, 0, $props->{'picture_keyword'}); + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $props, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + 'enable_tags_compatibility' => [$opts->{enable_tags_compatibility}, $opts->{ctx}], + }); + + push @{$p->{'entries'}}, $entry; + } +#push @elapsed, (tv_interval ($t0)); +#print STDERR "@elapsed \n"; + + + if (@{$p->{'entries'}}) { + $p->{'has_entries'} = 1; + $p->{'entries'}->[0]->{'new_day'} = 1; + $p->{'entries'}->[-1]->{'end_day'} = 1; + } + + # calculate previous day + my $pdyear = $year; + my $pdmonth = $month; + my $pdday = $day-1; + if ($pdday < 1) + { + if (--$pdmonth < 1) + { + $pdmonth = 12; + $pdyear--; + } + $pdday = LJ::days_in_month($pdmonth, $pdyear); + } + + # calculate next day + my $nxyear = $year; + my $nxmonth = $month; + my $nxday = $day+1; + if ($nxday > LJ::days_in_month($nxmonth, $nxyear)) + { + $nxday = 1; + if (++$nxmonth > 12) { ++$nxyear; $nxmonth=1; } + } + + $p->{'prev_url'} = "$u->{'_journalbase'}/" . sprintf("%04d/%02d/%02d/", $pdyear, $pdmonth, $pdday); + $p->{'prev_date'} = Date($pdyear, $pdmonth, $pdday); + $p->{'next_url'} = "$u->{'_journalbase'}/" . sprintf("%04d/%02d/%02d/", $nxyear, $nxmonth, $nxday); + $p->{'next_date'} = Date($nxyear, $nxmonth, $nxday); + + return $p; +} + +1; diff --git a/local/cgi-bin/LJ/S2/EntryPage.pm b/local/cgi-bin/LJ/S2/EntryPage.pm new file mode 100755 index 0000000..0ce52df --- /dev/null +++ b/local/cgi-bin/LJ/S2/EntryPage.pm @@ -0,0 +1,432 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub EntryPage +{ + my ($u, $remote, $opts) = @_; + + my $get = $opts->{'getargs'}; + + my $p = Page($u, $opts); + $p->{'_type'} = "EntryPage"; + $p->{'view'} = "entry"; + $p->{'comments'} = []; + $p->{'comment_pages'} = undef; + + # setup viewall options + my ($viewall, $viewsome) = (0, 0); + if ($get->{viewall} && LJ::check_priv($remote, 'canview')) { + # we don't log here, as we don't know what entry we're viewing yet. the logging + # is done when we call EntryPage_entry below. + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + my ($entry, $s2entry) = EntryPage_entry($u, $remote, $opts); + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + + $p->{'multiform_on'} = $remote && + ($remote->{'userid'} == $u->{'userid'} || + $remote->{'userid'} == $entry->{'posterid'} || + LJ::can_manage($remote, $u)); + + my $itemid = $entry->{'itemid'}; + my $ditemid = $entry->{'itemid'} * 256 + $entry->{'anum'}; + my $permalink = LJ::journal_base($u) . "/$ditemid.html"; + my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : ""; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/$ditemid.html" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $p->{'head_content'} .= '\n"; + } + + $p->{'entry'} = $s2entry; + + # add the comments + my %userpic; + my %user; + my $copts = { + 'thread' => ($get->{'thread'} >> 8), + 'page' => $get->{'page'}, + 'view' => $get->{'view'}, + 'userpicref' => \%userpic, + 'userref' => \%user, + # user object is cached from call just made in EntryPage_entry + 'up' => LJ::load_user($s2entry->{'poster'}->{'username'}), + 'viewall' => $viewall, + + # Okuklivanie tredov - daem upravlenie pol'zovatelyu - + 'page_size' => $get->{'page_size'}, + 'max_subjects' => $get->{'max_subjects'}, + 'threading_point' => $get->{'threading_point'}, + 'uncollapse' => $get->{'uncollapse'}, + }; + + my $userlite_journal = UserLite($u); + + my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $copts); + + my $pics = LJ::Talk::get_subjecticons()->{'pic'}; # hashref of imgname => { w, h, img } + my $convert_comments = sub { + my ($self, $destlist, $srclist, $depth) = @_; + + foreach my $com (@$srclist) { + my $dtalkid = $com->{'talkid'} * 256 + $entry->{'anum'}; + my $text = $com->{'body'}; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + LJ::CleanHTML::clean_comment(\$text, { 'preformatted' => $com->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$com->{posterid}}); + + # local time in mysql format to gmtime + my $datetime = DateTime_unix(LJ::mysqldate_to_time($com->{'datepost'})); + if ($datetime == 0) { + $datetime = "Invalid date"; + } + + my $subject_icon = undef; + if (my $si = $com->{'props'}->{'subjecticon'}) { + my $pic = $pics->{$si}; + $subject_icon = Image("$LJ::IMGPREFIX/talk/$pic->{'img'}", + $pic->{'w'}, $pic->{'h'}) if $pic; + } + + my $comment_userpic; + if (my $pic = $userpic{$com->{'picid'}}) { + $comment_userpic = Image("$LJ::USERPIC_ROOT/$com->{'picid'}/$pic->{'userid'}", + $pic->{'width'}, $pic->{'height'}); + } + + my $reply_url = LJ::Talk::talkargs($permalink, "replyto=$dtalkid", $stylemine); + + my $par_url; + if ($com->{'parenttalkid'}) { + my $dparent = ($com->{'parenttalkid'} << 8) + $entry->{'anum'}; + $par_url = LJ::Talk::talkargs($permalink, "thread=$dparent", $stylemine) . "#t$dparent"; + } + + my $poster; + if ($com->{'posterid'}) { + if ($user{$com->{'posterid'}}) { + $poster = UserLite($user{$com->{'posterid'}}); + } else { + $poster = { + '_type' => 'UserLite', + 'username' => $com->{'userpost'}, + 'name' => $com->{'userpost'}, # we don't have this, so fake it + 'journal_type' => 'P', # fake too, but only people can post, so correct + }; + } + } + + my $s2com = { + '_type' => 'Comment', + 'journal' => $userlite_journal, + 'metadata' => { + 'picture_keyword' => $com->{'props'}->{'picture_keyword'}, + }, + 'permalink_url' => "$permalink?thread=$dtalkid#t$dtalkid", + 'reply_url' => $reply_url, + 'poster' => $poster, + 'replies' => [], + 'subject' => LJ::ehtml($com->{'subject'}), + 'subject_icon' => $subject_icon, + 'talkid' => $dtalkid, + 'text' => $text, + 'userpic' => $comment_userpic, + 'time' => $datetime, + 'tags' => [], + 'full' => $com->{'_loaded'} ? 1 : 0, + 'depth' => $depth, + 'parent_url' => $par_url, + 'screened' => $com->{'state'} eq "S" ? 1 : 0, + 'frozen' => $com->{'state'} eq "F" ? 1 : 0, + 'link_keyseq' => [ 'delete_comment' ], + 'anchor' => "t$dtalkid", + 'dom_id' => "ljcmt$dtalkid", + }; + + # don't show info from suspended users + # FIXME: ideally the load_comments should only return these + # items if there are children, otherwise they should be hidden entirely + my $pu = $com->{'posterid'} ? $user{$com->{'posterid'}} : undef; + if ($pu && $pu->{'statusvis'} eq "S" && !$viewsome) { + $s2com->{'text'} = ""; + $s2com->{'subject'} = ""; + $s2com->{'full'} = 0; + $s2com->{'subject_icon'} = undef; + $s2com->{'userpic'} = undef; + } + + # Conditionally add more links to the keyseq + my $link_keyseq = $s2com->{'link_keyseq'}; + push @$link_keyseq, $s2com->{'screened'} ? 'unscreen_comment' : 'screen_comment'; + push @$link_keyseq, $s2com->{'frozen'} ? 'unfreeze_thread' : 'freeze_thread'; + + if (@{$com->{'children'}}) { + $s2com->{'thread_url'} = LJ::Talk::talkargs($permalink, "thread=$dtalkid", $stylemine) . "#t$dtalkid"; + } + + # add the poster_ip metadata if remote user has + # access to see it. + $s2com->{'metadata'}->{'poster_ip'} = $com->{'props'}->{'poster_ip'} if + ($com->{'props'}->{'poster_ip'} && $remote && + ($remote->{'userid'} == $entry->{'posterid'} || + LJ::can_manage($remote, $u) || $viewall)); + + push @$destlist, $s2com; + + $self->($self, $s2com->{'replies'}, $com->{'children'}, $depth+1); + } + }; + $p->{'comments'} = []; + $convert_comments->($convert_comments, $p->{'comments'}, \@comments, 1); + + # prepare the javascript data structure to put in the top of the page + # if the remote user is a manager of the comments + my $do_commentmanage_js = $p->{'multiform_on'}; + if ($LJ::DISABLED{'commentmanage'}) { + if (ref $LJ::DISABLED{'commentmanage'} eq "CODE") { + $do_commentmanage_js = $LJ::DISABLED{'commentmanage'}->($remote); + } else { + $do_commentmanage_js = 0; + } + } + + if ($do_commentmanage_js) { + my $js = "\n"; + $p->{'head_content'} .= $js; + $p->{'head_content'} .= "\n"; + + } + + + $p->{'viewing_thread'} = $get->{'thread'} ? 1 : 0; + + # default values if there were no comments, because + # LJ::Talk::load_comments() doesn't provide them. + if ($copts->{'out_error'} eq 'noposts') { + $copts->{'out_pages'} = $copts->{'out_page'} = 1; + $copts->{'out_items'} = 0; + $copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef; + } + + $p->{'comment_pages'} = ItemRange({ + 'all_subitems_displayed' => ($copts->{'out_pages'} == 1), + 'current' => $copts->{'out_page'}, + 'from_subitem' => $copts->{'out_itemfirst'}, + 'num_subitems_displayed' => scalar @comments, + 'to_subitem' => $copts->{'out_itemlast'}, + 'total' => $copts->{'out_pages'}, + 'total_subitems' => $copts->{'out_items'}, + '_url_of' => sub { return "$permalink?page=" . int($_[0]) . + ($stylemine ? "&$stylemine" : ''); }, + }); + + return $p; +} + +sub EntryPage_fast_check +{ + my ($u, $view, $remote, $opts) = @_; + + return unless ($view eq "entry" || $view eq "reply"); + + my $get = $opts->{'getargs'}; + + my $r = $opts->{'r'}; + my $uri = $r->uri; + + my ($ditemid, $itemid, $anum); + unless ($uri =~ /(\d+)\.html/) { + $opts->{'handler_return'} = 404; + return; + } + + $ditemid = $1; + $anum = $ditemid % 256; + $itemid = $ditemid >> 8; + + my $entry = LJ::Talk::get_journal_item($u, $itemid, "props_only"); + unless ($entry && $entry->{'anum'} == $anum) { + $opts->{'handler_return'} = 404; + return; + } + my $props = $entry->{'props'}; + + # do they have the viewall priv? + my $viewall = 0; + my $viewsome = 0; + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "entry: $u->{'user'}, itemid: $itemid, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + # check using normal rules + unless (LJ::can_view($remote, $entry) || $viewall) { + $opts->{'handler_return'} = 403; + return; + } + + my $pu = $u; + if ($entry->{'posterid'} != $entry->{'ownerid'}) { + $pu = LJ::load_userid($entry->{'posterid'}); + } + if (($pu && $pu->{'statusvis'} eq 'S') && !$viewsome) { + $opts->{'suspendeduser'} = 1; + return; + } + + # check If-Modified-Since + my $lastmod = $props->{'commentalter'}; + my $revisiontime = $props->{' revtime'}; + $lastmod = $revisiontime if $revisiontime && $revisiontime > $lastmod; + + my $ims = $r->header_in('If-Modified-Since'); + if ($ims) { + my $theirtime = LJ::http_to_time($ims); + if ($theirtime >= $lastmod && !$remote) { + # only for anonymous: logged users will be checked by Etag for exact match + # reply special: uniq challange string for regular users + if ($view eq "entry" || ($view eq "reply" && $r->header_in('User-Agent') =~ /$LJ::ROBOTS_REGEXP/)) { + + $opts->{'notmodified'} = 1; + return; + } + } + } + $r->header_out("Last-Modified", LJ::time_to_http($lastmod)); +} + +sub EntryPage_entry +{ + my ($u, $remote, $opts) = @_; + + ### NB! EntryPage_fast_check was previously called, so all checks passed. + + my $get = $opts->{'getargs'}; + + my $r = $opts->{'r'}; + my $uri = $r->uri; + + my ($ditemid, $itemid, $anum); + unless ($uri =~ /(\d+)\.html/) { + $opts->{'handler_return'} = 404; + return; + } + + $ditemid = $1; + $anum = $ditemid % 256; + $itemid = $ditemid >> 8; + + my $entry = LJ::Talk::get_journal_item($u, $itemid); + unless ($entry && $entry->{'anum'} == $anum) { + $opts->{'handler_return'} = 404; + return; + } + ### more checks skipped ### + + my $props = $entry->{'props'}; + + my $userlite_journal = UserLite($u); + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($entry->{'posterid'} != $entry->{'ownerid'}) { + $pu = LJ::load_userid($entry->{'posterid'}); + $userlite_poster = UserLite($pu); + } + + my $replycount = $props->{'replycount'}; + my $nc = ""; + $nc .= "nc=$replycount" if $replycount; # && $remote && $remote->{'opt_nctalklinks'}; + + my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : ""; + + my $userpic = Image_userpic($pu, 0, $props->{'picture_keyword'}); + + my $permalink = LJ::journal_base($u) . "/$ditemid.html"; + my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine); + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine); + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! + $props->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($props->{'hasscreened'} && $remote && + LJ::can_manage($remote, $u)) ? 1 : 0, + }); + + # format it + if ($opts->{'getargs'}->{'nohtml'}) { + # quote all non-LJ tags + $entry->{'subject'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $entry->{'event'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + my $raw_subj = $entry->{'subject'}; + LJ::CleanHTML::clean_subject(\$entry->{'subject'}); + LJ::CleanHTML::clean_event(\$entry->{'event'}, $props->{'opt_preformatted'}); + LJ::expand_embedded($u, $ditemid, $remote, \$entry->{'event'}); + + my $s2entry = Entry($u, { + '_rawsubject' => $raw_subj, + 'subject' => $entry->{'subject'}, + 'text' => $entry->{'event'}, + 'dateparts' => $entry->{'alldatepart'}, + 'security' => $entry->{'security'}, + 'props' => $props, + 'itemid' => $ditemid, + 'comments' => $comments, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'new_day' => 0, + 'end_day' => 0, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + 'enable_tags_compatibility' => [$opts->{enable_tags_compatibility}, $opts->{ctx}], + }); + + return ($entry, $s2entry); +} + +1; diff --git a/local/cgi-bin/LJ/S2/FriendsPage.pm b/local/cgi-bin/LJ/S2/FriendsPage.pm new file mode 100755 index 0000000..3be9a9f --- /dev/null +++ b/local/cgi-bin/LJ/S2/FriendsPage.pm @@ -0,0 +1,444 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +eval "use LJR::Distributed;"; +my $ljr = $@ ? 0 : 1; + +if ($ljr) { + use LJR::Distributed; +} + +sub FriendsPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "FriendsPage"; + $p->{'view'} = "friends"; + $p->{'entries'} = []; + $p->{'friends'} = {}; + $p->{'friends_title'} = LJ::ehtml($u->{'friendspagetitle'}); + $p->{'filter_active'} = 0; + $p->{'filter_name'} = ""; + + my $sth; + my $user = $u->{'user'}; + + # see how often the remote user can reload this page. + # "friendsviewupdate" time determines what granularity time + # increments by for checking for new updates + my $nowtime = time(); + + # update delay specified by "friendsviewupdate" + my $newinterval = LJ::get_cap_min($remote, "friendsviewupdate") || 1; + + # when are we going to say page was last modified? back up to the + # most recent time in the past where $time % $interval == 0 + my $lastmod = $nowtime; + $lastmod -= $lastmod % $newinterval; + + # see if they have a previously cached copy of this page they + # might be able to still use. + my $ims = $opts->{'r'}->header_in('If-Modified-Since'); + if ($ims) { + my $theirtime = LJ::http_to_time($ims); + + # send back a 304 Not Modified if they say they've reloaded this + # document in the last $newinterval seconds: + unless ($theirtime < $lastmod) { + $opts->{'handler_return'} = 304; + return 1; + } + } + $opts->{'r'}->header_out('Last-Modified', LJ::time_to_http($lastmod)); + + my $get = $opts->{'getargs'}; + + my $ret; + + if ($get->{'mode'} eq "live") { + $ret .= "${user}'s friends: live!\n"; + $ret .= "\n"; + $ret .= " \n"; + $ret .= " \n"; + $ret .= "\n"; + return $ret; + } + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . "/friends"; + return 1; + } + + LJ::load_user_props($remote, "opt_nctalklinks", "opt_stylemine", "opt_imagelinks", "opt_ljcut_disable_friends"); + + # load options for image links + my ($maximgwidth, $maximgheight) = (undef, undef); + ($maximgwidth, $maximgheight) = ($1, $2) + if ($remote && $remote->{'userid'} == $u->{'userid'} && + $remote->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/); + + ## never have spiders index friends pages (change too much, and some + ## people might not want to be indexed) + $p->{'head_content'} .= LJ::robot_meta_tags(); + + my $itemshow = S2::get_property_value($opts->{'ctx'}, "page_friends_items")+0; + if ($itemshow < 1) { $itemshow = 20; } + elsif ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = ($LJ::MAX_SCROLLBACK_FRIENDS || 1000) - $itemshow; + if ($skip > $maxskip) { $skip = $maxskip; } + if ($skip < 0) { $skip = 0; } + my $itemload = $itemshow+$skip; + + my $dayskip = $get->{'dayskip'}+0; + + my $filter; + my $group; + my $common_filter = 1; + + if (defined $get->{'filter'} && $remote && $remote->{'user'} eq $user) { + $filter = $get->{'filter'}; + $common_filter = 0; + $p->{'filter_active'} = 1; + $p->{'filter_name'} = ""; + } else { + if ($opts->{'pathextra'}) { + $group = $opts->{'pathextra'}; + $group =~ s!^/!!; + $group =~ s!/$!!; + if ($group) { $group = LJ::durl($group); $common_filter = 0; } + } + if ($group) { + $p->{'filter_active'} = 1; + $p->{'filter_name'} = LJ::ehtml($group); + } + my $grp = LJ::get_friend_group($u, { 'name' => $group || "Default View" }); + my $bit = $grp->{'groupnum'}; + my $public = $grp->{'is_public'}; + if ($bit && ($public || ($remote && $remote->{'user'} eq $user))) { + $filter = (1 << $bit); + } elsif ($group) { + $opts->{'badfriendgroup'} = 1; + return 1; + } + } + + if ($opts->{'view'} eq "friendsfriends") { + $p->{'friends_mode'} = "friendsfriends"; + } + + if ($get->{'mode'} eq "livecond") + { + ## load the itemids + my @items = LJ::get_friend_items({ + 'u' => $u, + 'remote' => $remote, + 'itemshow' => 1, + 'skip' => 0, + 'filter' => $filter, + 'common_filter' => $common_filter, + }); + my $first = @items ? $items[0]->{'itemid'} : 0; + + $ret .= "time = " . scalar(time()) . "
    "; + $opts->{'headers'}->{'Refresh'} = "30;URL=$LJ::SITEROOT/users/$user/friends?mode=livecond&lastitemid=$first"; + if ($get->{'lastitemid'} == $first) { + $ret .= "nothing new!"; + } else { + if ($get->{'lastitemid'}) { + $ret .= "New stuff!\n"; + $ret .= "\n"; + $opts->{'trusted_html'} = 1; + } else { + $ret .= "Friends Live! started."; + } + } + return $ret; + } + + ## load the itemids + my %friends; + my %friends_row; + my @items = LJ::get_friend_items({ + 'u' => $u, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'dayskip' => $dayskip, + 'filter' => $filter, + 'common_filter' => $common_filter, + 'friends_u' => \%friends, + 'friends' => \%friends_row, + 'showtypes' => $get->{'show'}, + 'friendsoffriends' => $opts->{'view'} eq "friendsfriends", + 'dateformat' => 'S2', + }); + + while ($_ = each %friends) { + # we expect fgcolor/bgcolor to be in here later + $friends{$_}->{'fgcolor'} = $friends_row{$_}->{'fgcolor'} || '#ffffff'; + $friends{$_}->{'bgcolor'} = $friends_row{$_}->{'bgcolor'} || '#000000'; + } + + return $p unless %friends; + + my %posters; + { + my @posterids; + foreach my $item (@items) { + next if $friends{$item->{'posterid'}}; + push @posterids, $item->{'posterid'}; + } + LJ::load_userids_multiple([ map { $_ => \$posters{$_} } @posterids ]) + if @posterids; + } + + my %objs_of_picid; + my @userpic_load; + + my %lite; # posterid -> s2_UserLite + my $get_lite = sub { + my $id = shift; + return $lite{$id} if $lite{$id}; + return $lite{$id} = UserLite($posters{$id} || $friends{$id}); + }; + + my $eventnum = 0; + my $hiddenentries = 0; + ENTRY: + foreach my $item (@items) + { + my ($friendid, $posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(ownerid posterid itemid security alldatepart); + + my $fru = $friends{$friendid}; + my ($friend, $poster); + $friend = $poster = $fru->{'user'}; + $p->{'friends'}->{$fru->{'user'}} ||= Friend($fru); + + my $clusterid = $item->{'clusterid'}+0; + + my $props = $item->{'props'}; + + my $replycount = $props->{'replycount'}; + my $subject = $item->{'text'}->[0]; + my $text = $item->{'text'}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid * 256 + $item->{'anum'}; + + my $stylemine = ""; + $stylemine .= "style=mine" if $remote && $remote->{'opt_stylemine'} && + $remote->{'userid'} != $friendid; + + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $props->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($fru, $itemid, $item->{'anum'}, $stylemine), + 'maximgwidth' => $maximgwidth, + 'maximgheight' => $maximgheight, + 'ljcut_disable' => $remote->{'opt_ljcut_disable_friends'}, }); + LJ::expand_embedded($fru, $ditemid, $remote, \$text); + + my $userlite_poster = $get_lite->($posterid); + my $userlite_journal = $get_lite->($friendid); + + # get the poster user + my $po = $posters{$posterid} || $friends{$posterid}; + + # don't allow posts from suspended users + if ($po->{'statusvis'} eq 'S') { + $hiddenentries++; # Remember how many we've skipped for later + next ENTRY; + } + + # do the picture + my $picid = 0; + my $picu = undef; + if ($friendid != $posterid && S2::get_property_value($opts->{ctx}, 'use_shared_pic')) { + # using the community, the user wants to see shared pictures + $picu = $fru; + + # use shared pic for community + $picid = $fru->{defaultpicid}; + } else { + # we're using the poster for this picture + $picu = $po; + + # check if they specified one + $picid = LJ::get_picid_from_keyword($po, $props->{picture_keyword}) + if $props->{picture_keyword}; + + # fall back on the poster's default + $picid ||= $po->{defaultpicid}; + } + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount; # && $remote && $remote->{'opt_nctalklinks'}; + + my $journalbase = LJ::journal_base($fru); + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine); + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine); + my $synurl = ""; + + if ($ljr && $props->{'syn_link'}) { + my $rs = LJR::Distributed::match_remote_server($props->{'syn_link'}); + if ($rs->{"servertype"} eq "lj") { + $readurl = $props->{'syn_link'}; + $posturl = $props->{'syn_link'} . "?mode=reply"; + $replycount = 'Read'; + } + else { + $posturl = $props->{'syn_link'}; + $replycount = undef; + } + $synurl = $props->{'syn_link'}; + } + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'syn_url' => $synurl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($fru->{'opt_showtalklinks'} eq "Y" && + ! $props->{'opt_nocomments'} || + $props->{'syn_link'} + ) ? 1 : 0, + 'screened' => ($remote && LJ::can_manage($remote, $fru) && $props->{'hasscreened'}) ? 1 : 0, + }); + + my $moodthemeid = $u->{'opt_forcemoodtheme'} eq 'Y' ? + $u->{'moodthemeid'} : $fru->{'moodthemeid'}; + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $props, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'new_day' => 0, # setup below + 'end_day' => 0, # setup below + 'userpic' => undef, + 'permalink_url' => $permalink, + 'base_url' => $journalbase, + 'moodthemeid' => $moodthemeid, + 'enable_tags_compatibility' => [$opts->{enable_tags_compatibility}, $opts->{ctx}], + }); + $entry->{'_ymd'} = join('-', map { $entry->{'time'}->{$_} } qw(year month day)); + + if ($picid && $picu) { + push @userpic_load, [ $picu, $picid ]; + push @{$objs_of_picid{$picid}}, \$entry->{'userpic'}; + } + + push @{$p->{'entries'}}, $entry; + $eventnum++; + + } # end while + + # set the new_day and end_day members. + if ($eventnum) { + for (my $i = 0; $i < $eventnum; $i++) { + my $entry = $p->{'entries'}->[$i]; + $entry->{'new_day'} = 1; + my $last = $i; + for (my $j = $i+1; $j < $eventnum; $j++) { + my $ej = $p->{'entries'}->[$j]; + if ($ej->{'_ymd'} eq $entry->{'_ymd'}) { + $last = $j; + } + } + $p->{'entries'}->[$last]->{'end_day'} = 1; + $i = $last; + } + } + + # load the pictures that were referenced, then retroactively populate + # the userpic fields of the Entries above + my %userpics; + LJ::load_userpics(\%userpics, \@userpic_load); + + foreach my $picid (keys %userpics) { + my $up = Image("$LJ::USERPIC_ROOT/$picid/$userpics{$picid}->{'userid'}", + $userpics{$picid}->{'width'}, + $userpics{$picid}->{'height'}); + foreach (@{$objs_of_picid{$picid}}) { $$_ = $up; } + } + + # make the skip links + my $nav = { + '_type' => 'RecentNav', + 'version' => 1, + 'skip' => $skip, + 'count' => $eventnum, + }; + + my $base = "$u->{'_journalbase'}/$opts->{'view'}"; + if ($group) { + $base .= "/" . LJ::eurl($group); + } + + # $linkfilter is distinct from $filter: if user has a default view, + # $filter is now set according to it but we don't want it to show in the links. + # $incfilter may be true even if $filter is 0: user may use filter=0 to turn + # off the default group + my $linkfilter = $get->{'filter'} + 0; + my $incfilter = defined $get->{'filter'}; + + # if we've skipped down, then we can skip back up + if ($skip) { + my %linkvars; + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + my $newskip = $skip - $itemshow; + if ($newskip > 0) { $linkvars{'skip'} = $newskip; } + else { $newskip = 0; } + $linkvars{'dayskip'} = $dayskip if $dayskip; + $nav->{'forward_url'} = LJ::make_link($base, \%linkvars); + $nav->{'forward_skip'} = $newskip; + $nav->{'forward_count'} = $itemshow; + } + + ## unless we didn't even load as many as we were expecting on this + ## page, then there are more (unless there are exactly the number shown + ## on the page, but who cares about that) + # Must remember to count $hiddenentries or we'll have no skiplinks when > 1 + unless (($eventnum + $hiddenentries) != $itemshow || $skip == $maxskip) { + my %linkvars; + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + my $newskip = $skip + $itemshow; + $linkvars{'skip'} = $newskip; + $linkvars{'dayskip'} = $dayskip if $dayskip; + $nav->{'backward_url'} = LJ::make_link($base, \%linkvars); + $nav->{'backward_skip'} = $newskip; + $nav->{'backward_count'} = $itemshow; + } + + $p->{'nav'} = $nav; + + if ($get->{'mode'} eq "framed") { + $p->{'head_content'} .= ""; + } + + return $p; +} + +1; diff --git a/local/cgi-bin/LJ/S2/MonthPage.pm b/local/cgi-bin/LJ/S2/MonthPage.pm new file mode 100755 index 0000000..52f1bba --- /dev/null +++ b/local/cgi-bin/LJ/S2/MonthPage.pm @@ -0,0 +1,224 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub MonthPage +{ + my ($u, $remote, $opts) = @_; + + my $get = $opts->{'getargs'}; + + my $p = Page($u, $opts); + $p->{'_type'} = "MonthPage"; + $p->{'view'} = "month"; + $p->{'days'} = []; + + my $ctx = $opts->{'ctx'}; + + my $dbcr = LJ::get_cluster_reader($u); + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + my ($year, $month); + if ($opts->{'pathextra'} =~ m!^/(\d\d\d\d)/(\d\d)\b!) { + ($year, $month) = ($1, $2); + } + + $opts->{'errors'} = []; + if ($month < 1 || $month > 12) { push @{$opts->{'errors'}}, "Invalid month: $month"; } + if ($year < 1970 || $year > 2038) { push @{$opts->{'errors'}}, "Invalid year: $year"; } + unless ($dbcr) { push @{$opts->{'errors'}}, "Database temporarily unavailable"; } + return if @{$opts->{'errors'}}; + + $p->{'date'} = Date($year, $month, 0); + + # load the log items + my $dateformat = "%Y %m %d %H %i %s %w"; # yyyy mm dd hh mm ss day_of_week + my $sth; + + my $secwhere = "AND l.security='public'"; + my $viewall = 0; + my $viewsome = 0; + if ($remote) { + + # do they have the viewall priv? + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "month: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P' || $remote->{'journaltype'} eq 'I') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (l.security='public' OR (l.security='usemask' AND l.allowmask & $gmask))" + if $gmask; + } + } + + $sth = $dbcr->prepare("SELECT l.jitemid AS 'itemid', l.posterid, l.anum, l.day, ". + " DATE_FORMAT(l.eventtime, '$dateformat') AS 'alldatepart', ". + " l.replycount, l.security ". + "FROM log2 l ". + "WHERE l.journalid=? AND l.year=? AND l.month=? ". + "$secwhere LIMIT 2000"); + $sth->execute($u->{'userid'}, $year, $month); + + my @items; + push @items, $_ while $_ = $sth->fetchrow_hashref; + @items = sort { $a->{'alldatepart'} cmp $b->{'alldatepart'} } @items; + + LJ::fill_items_with_text_props(\@items, $u, {'only_subject' => 1}); + + my (%pu, %pu_lite); # poster users; UserLite objects + foreach (@items) { + $pu{$_->{'posterid'}} = undef; + } + LJ::load_userids_multiple([map { $_, \$pu{$_} } keys %pu], [$u]); + $pu_lite{$_} = UserLite($pu{$_}) foreach keys %pu; + + my %day_entries; # -> [ Entry+ ] + + my $opt_text_subjects = S2::get_property_value($ctx, "page_month_textsubjects"); + my $userlite_journal = UserLite($u); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart, $replycount, $anum) = + map { $item->{$_} } qw(posterid itemid security alldatepart replycount anum); + my $day = $item->{'day'}; + + # don't show posts from suspended users + next unless $pu{$posterid}; + next ENTRY if $pu{$posterid}->{'statusvis'} eq 'S' && !$viewsome; + + my $subject = $item->{'text'}->[0]; + my $props = $item->{'props'}; + + if ($opt_text_subjects) { + LJ::CleanHTML::clean_subject_all(\$subject); + } else { + LJ::CleanHTML::clean_subject(\$subject); + } + + my $ditemid = $itemid*256 + $anum; + my $nc = ""; + $nc .= "nc=$replycount" if $replycount; # && $remote && $remote->{'opt_nctalklinks'}; + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $props->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($props->{'hasscreened'} && $remote && + ($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $userpic = $p->{'journal'}->{'default_pic'}; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $pu_lite{$posterid}; + $userpic = Image_userpic($pu{$posterid}, 0, $props->{'picture_keyword'}); + } + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => "", + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $props, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + }); + + push @{$day_entries{$day}}, $entry; + } + + my $days_month = LJ::days_in_month($month, $year); + for my $day (1..$days_month) { + my $entries = $day_entries{$day} || []; + my $month_day = { + '_type' => 'MonthDay', + 'date' => Date($year, $month, $day), + 'day' => $day, + 'has_entries' => scalar @$entries > 0, + 'num_entries' => scalar @$entries, + 'url' => $journalbase . sprintf("/%04d/%02d/%02d/", $year, $month, $day), + 'entries' => $entries, + }; + push @{$p->{'days'}}, $month_day; + } + + # populate redirector + my $vhost = $opts->{'vhost'}; + $vhost =~ s/:.*//; + $p->{'redir'} = { + '_type' => "Redirector", + 'user' => $u->{'user'}, + 'vhost' => $vhost, + 'type' => 'monthview', + 'url' => "$LJ::SITEROOT/go.bml", + }; + + # figure out what months have been posted into + my $nowval = $year*12 + $month; + + $p->{'months'} = []; + + my $days = LJ::get_daycounts($u, $remote) || []; + my $lastmo; + foreach my $day (@$days) { + my ($oy, $om) = ($day->[0], $day->[1]); + my $mo = "$oy-$om"; + next if $mo eq $lastmo; + $lastmo = $mo; + + my $date = Date($oy, $om, 0); + my $url = $journalbase . sprintf("/%04d/%02d/", $oy, $om); + push @{$p->{'months'}}, { + '_type' => "MonthEntryInfo", + 'date' => $date, + 'url' => $url, + 'redir_key' => sprintf("%04d%02d", $oy, $om), + }; + + my $val = $oy*12+$om; + if ($val < $nowval) { + $p->{'prev_url'} = $url; + $p->{'prev_date'} = $date; + } + if ($val > $nowval && ! $p->{'next_date'}) { + $p->{'next_url'} = $url; + $p->{'next_date'} = $date; + } + } + + return $p; +} + +1; diff --git a/local/cgi-bin/LJ/S2/RecentPage.pm b/local/cgi-bin/LJ/S2/RecentPage.pm new file mode 100755 index 0000000..733e869 --- /dev/null +++ b/local/cgi-bin/LJ/S2/RecentPage.pm @@ -0,0 +1,216 @@ +use strict; +package LJ::S2; + +sub RecentPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "RecentPage"; + $p->{'view'} = "recent"; + $p->{'entries'} = []; + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}); + return; + } + + LJ::load_user_props($remote, "opt_nctalklinks", "opt_ljcut_disable_lastn"); + + my $get = $opts->{'getargs'}; + + if ($opts->{'pathextra'}) { + $opts->{'badargs'} = 1; + return 1; + } + + if ($u->{'opt_blockrobots'} || $get->{'skip'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + $p->{'head_content'} .= qq{\n} + if LJ::OpenID::server_enabled(); + + my $itemshow = S2::get_property_value($opts->{'ctx'}, "page_recent_items")+0; + if ($itemshow < 1) { $itemshow = 20; } + elsif ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = $LJ::MAX_HINTS_LASTN-$itemshow; + if ($skip < 0) { $skip = 0; } + if ($skip > $maxskip) { $skip = $maxskip; } + + my $dayskip = $get->{'dayskip'}+0; + + # do they want to view all entries, regardless of security? + my $viewall = 0; + my $viewsome = 0; + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "lastn: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + ## load the items + my $err; + my @items = LJ::get_recent_items({ + 'u' => $u, + 'clustersource' => 'slave', + 'viewall' => $viewall, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'dayskip' => $dayskip, + 'tags' => $opts->{tags}, + 'dateformat' => 'S2', + 'order' => ($u->{'journaltype'} eq "C" || $u->{'journaltype'} eq "Y") # community or syndicated + ? "logtime" : "", + 'err' => \$err, + }); + + die $err if $err; + + my $lastdate = ""; + my $itemnum = 0; + my $lastentry = undef; + + my (%apu, %apu_lite); # alt poster users; UserLite objects + foreach (@items) { + next unless $_->{'posterid'} != $u->{'userid'}; + $apu{$_->{'posterid'}} = undef; + } + if (%apu) { + LJ::load_userids_multiple([map { $_, \$apu{$_} } keys %apu], [$u]); + $apu_lite{$_} = UserLite($apu{$_}) foreach keys %apu; + } + + my $userlite_journal = UserLite($u); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(posterid itemid security alldatepart); + + my $props = $item->{'props'}; + + my $replycount = $props->{'replycount'}; + my $subject = $item->{'text'}->[0]; + my $text = $item->{'text'}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + # don't show posts from suspended users unless the user doing the viewing says to (and is allowed) + next ENTRY if $apu{$posterid} && $apu{$posterid}->{'statusvis'} eq 'S' && !$viewsome; + + my $date = substr($alldatepart, 0, 10); + my $new_day = 0; + if ($date ne $lastdate) { + $new_day = 1; + $lastdate = $date; + $lastentry->{'end_day'} = 1 if $lastentry; + } + + $itemnum++; + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid * 256 + $item->{'anum'}; + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $props->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $item->{'anum'}), + 'ljcut_disable' => $remote->{"opt_ljcut_disable_lastn"}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$text); + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount; # && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $props->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($props->{'hasscreened'} && ($remote->{'user'} eq $u->{'user'}|| LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $apu_lite{$posterid} or die "No apu_lite for posterid=$posterid"; + $pu = $apu{$posterid}; + } + my $userpic = Image_userpic($pu, 0, $props->{'picture_keyword'}); + + my $entry = $lastentry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $props, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'new_day' => $new_day, + 'end_day' => 0, # if true, set later + 'userpic' => $userpic, + 'permalink_url' => $permalink, + 'enable_tags_compatibility' => [$opts->{enable_tags_compatibility}, $opts->{ctx}], + }); + + push @{$p->{'entries'}}, $entry; + + } # end huge while loop + + # mark last entry as closing. + $p->{'entries'}->[-1]->{'end_day'} = 1 if $itemnum; + + #### make the skip links + my $nav = { + '_type' => 'RecentNav', + 'version' => 1, + 'skip' => $skip, + 'count' => $itemnum, + }; + + # if we've skipped down, then we can skip back up + if ($skip) { + my $newskip = $skip - $itemshow; + $newskip = 0 if $newskip <= 0; + $nav->{'forward_skip'} = $newskip; + $nav->{'forward_url'} = LJ::make_link("$p->{base_url}/", { skip => ($newskip || ""), tag => (LJ::eurl($get->{tag}) || ""), dayskip => ($dayskip || "") }); + $nav->{'forward_count'} = $itemshow; + } + + # unless we didn't even load as many as we were expecting on this + # page, then there are more (unless there are exactly the number shown + # on the page, but who cares about that) + unless ($itemnum != $itemshow) { + $nav->{'backward_count'} = $itemshow; + if ($skip == $maxskip) { + my $date_slashes = $lastdate; # "yyyy mm dd"; + $date_slashes =~ s! !/!g; + $nav->{'backward_url'} = "$p->{'base_url'}/day/$date_slashes"; + } else { + my $newskip = $skip + $itemshow; + $nav->{'backward_url'} = LJ::make_link("$p->{'base_url'}/", { skip => ($newskip || ""), tag => (LJ::eurl($get->{tag}) || ""), dayskip => ($dayskip || "") }); + $nav->{'backward_skip'} = $newskip; + } + } + + $p->{'nav'} = $nav; + return $p; +} + +1; diff --git a/local/cgi-bin/LJ/S2/ReplyPage.pm b/local/cgi-bin/LJ/S2/ReplyPage.pm new file mode 100755 index 0000000..72a2c83 --- /dev/null +++ b/local/cgi-bin/LJ/S2/ReplyPage.pm @@ -0,0 +1,139 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub ReplyPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "ReplyPage"; + $p->{'view'} = "reply"; + + my $get = $opts->{'getargs'}; + + my ($entry, $s2entry) = EntryPage_entry($u, $remote, $opts); + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + my $ditemid = $entry->{'itemid'}*256 + $entry->{'anum'}; + $p->{'head_content'} .= $LJ::COMMON_CODE{'chalresp_js'}; + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + $p->{'entry'} = $s2entry; + + # setup the replying item + my $replyto = $s2entry; + my $parpost; + if ($get->{'replyto'}) { + my $re_talkid = int($get->{'replyto'} >> 8); + my $re_anum = $get->{'replyto'} % 256; + unless ($re_anum == $entry->{'anum'}) { + $opts->{'handler_return'} = 404; + return; + } + + my $sql = "SELECT jtalkid, posterid, state, datepost FROM talk2 ". + "WHERE journalid=$u->{'userid'} AND jtalkid=$re_talkid ". + "AND nodetype='L' AND nodeid=$entry->{'jitemid'}"; + foreach my $pass (1, 2) { + my $db = $pass == 1 ? LJ::get_cluster_reader($u) : LJ::get_cluster_def_reader($u); + $parpost = $db->selectrow_hashref($sql); + last if $parpost; + } + unless ($parpost and $parpost->{'state'} ne 'D') { + $opts->{'handler_return'} = 404; + return; + } + if ($parpost->{'state'} eq 'S' && !LJ::Talk::can_unscreen($remote, $u, $s2entry->{'poster'}->{'username'}, undef)) { + $opts->{'handler_return'} = 403; + return; + } + if ($parpost->{'state'} eq 'F') { + # frozen comment, no replies allowed + + # FIXME: eventually have S2 ErrorPage to handle this and similar + # For now, this hack will work; this error is pretty uncommon anyway. + $opts->{status} = "403 Forbidden"; + return "

    This thread has been frozen; no more replies are allowed.

    "; + } + + my $tt = LJ::get_talktext2($u, $re_talkid); + $parpost->{'subject'} = $tt->{$re_talkid}->[0]; + $parpost->{'body'} = $tt->{$re_talkid}->[1]; + $parpost->{'props'} = + LJ::load_talk_props2($u, [ $re_talkid ])->{$re_talkid} || {}; + + if($LJ::UNICODE && $parpost->{'props'}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$parpost->{'subject'}, \$parpost->{'body'}, {}); + } + + LJ::CleanHTML::clean_comment(\$parpost->{'body'}, + { 'preformatted' => $parpost->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$parpost->{posterid} }); + + my $datetime = DateTime_unix(LJ::mysqldate_to_time($parpost->{'datepost'})); + + my ($s2poster, $pu); + my $comment_userpic; + if ($parpost->{'posterid'}) { + $pu = LJ::load_userid($parpost->{'posterid'}); + return $opts->{handler_return} = 403 if $pu->{statusvis} eq 'S'; # do not show comments by suspended users + $s2poster = UserLite($pu); + + # FIXME: this is a little heavy: + $comment_userpic = Image_userpic($pu, 0, $parpost->{'props'}->{'picture_keyword'}); + } + + my $dtalkid = $re_talkid * 256 + $entry->{'anum'}; + $replyto = { + '_type' => 'EntryLite', + 'subject' => LJ::ehtml($parpost->{'subject'}), + 'text' => $parpost->{'body'}, + 'userpic' => $comment_userpic, + 'poster' => $s2poster, + 'journal' => $s2entry->{'journal'}, + 'metadata' => {}, + 'permalink_url' => $u->{'_journalbase'} . "/$ditemid.html?view=$dtalkid#t$dtalkid", + 'depth' => 1, + 'time' => $datetime, + }; + } + + $p->{'replyto'} = $replyto; + + $p->{'form'} = { + '_type' => "ReplyForm", + '_remote' => $remote, + '_u' => $u, + '_ditemid' => $ditemid, + '_parpost' => $parpost, + }; + + return $p; +} + +package S2::Builtin::LJ; + +sub ReplyForm__print +{ + my ($ctx, $form) = @_; + my $remote = $form->{'_remote'}; + my $u = $form->{'_u'}; + my $parpost = $form->{'_parpost'}; + my $parent = $parpost ? $parpost->{'jtalkid'} : 0; + + $S2::pout->(LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $u, + 'parpost' => $parpost, + 'replyto' => $parent, + 'ditemid' => $form->{'_ditemid'}, + 'form' => $form })); + +} + +1; diff --git a/local/cgi-bin/LJ/S2/YearPage.pm b/local/cgi-bin/LJ/S2/YearPage.pm new file mode 100755 index 0000000..f5ab597 --- /dev/null +++ b/local/cgi-bin/LJ/S2/YearPage.pm @@ -0,0 +1,181 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub YearPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "YearPage"; + $p->{'view'} = "archive"; + + my $user = $u->{'user'}; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/calendar" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $p->{'head_content'} .= '\n"; + } + + my $get = $opts->{'getargs'}; + + my $count = LJ::S2::get_journal_day_counts($p); + my @years = sort { $a <=> $b } keys %$count; + my $maxyear = @years ? $years[-1] : undef; + my $year = $get->{'year'}; # old form was /users//calendar?year=1999 + + # but the new form is purtier: */calendar/2001 + if (! $year && $opts->{'pathextra'} =~ m!^/(\d\d\d\d)/?\b!) { + $year = $1; + } + + # else... default to the year they last posted. + $year ||= $maxyear; + + $p->{'year'} = $year; + $p->{'years'} = []; + foreach (@years) { + push @{$p->{'years'}}, YearYear($_, "$p->{'base_url'}/$_/", $_ == $p->{'year'}); + } + + $p->{'months'} = []; + + for my $month (1..12) { + push @{$p->{'months'}}, YearMonth($p, { + 'month' => $month, + 'year' => $year, + }); + } + + return $p; +} + +sub YearMonth { + my ($p, $calmon) = @_; + + my ($month, $year) = ($calmon->{'month'}, $calmon->{'year'}); + $calmon->{'_type'} = 'YearMonth'; + $calmon->{'weeks'} = []; + $calmon->{'url'} = sprintf("$p->{'_u'}->{'_journalbase'}/$year/%02d/", $month); + + my $count = LJ::S2::get_journal_day_counts($p); + my $has_entries = $count->{$year} && $count->{$year}->{$month} ? 1 : 0; + $calmon->{'has_entries'} = $has_entries; + + my $start_monday = 0; # FIXME: check some property to see if weeks start on monday + my $week = undef; + + my $flush_week = sub { + my $end_month = shift; + return unless $week; + push @{$calmon->{'weeks'}}, $week; + if ($end_month) { + $week->{'post_empty'} = + 7 - $week->{'pre_empty'} - @{$week->{'days'}}; + } + $week = undef; + }; + + my $push_day = sub { + my $d = shift; + unless ($week) { + my $leading = $d->{'date'}->{'_dayofweek'}-1; + if ($start_monday) { + $leading = 6 if --$leading < 0; + } + $week = { + '_type' => 'YearWeek', + 'days' => [], + 'pre_empty' => $leading, + 'post_empty' => 0, + }; + } + push @{$week->{'days'}}, $d; + if ($week->{'pre_empty'} + @{$week->{'days'}} == 7) { + $flush_week->(); + my $size = scalar @{$calmon->{'weeks'}}; + } + }; + + my $day_of_week = LJ::day_of_week($year, $month, 1); + + my $daysinmonth = LJ::days_in_month($month, $year); + + for my $day (1..$daysinmonth) { + # so we don't auto-vivify years/months + my $daycount = $has_entries ? $count->{$year}->{$month}->{$day} : 0; + my $d = YearDay($p->{'_u'}, $year, $month, $day, + $daycount, $day_of_week+1); + $push_day->($d); + $day_of_week = ($day_of_week + 1) % 7; + } + $flush_week->(1); # end of month flag + + my $nowval = $year * 12 + $month; + + # determine the most recent month with posts that is older than + # the current time $month/$year. gives calendars the ability to + # provide smart next/previous links. + my $maxbefore; + while (my ($iy, $h) = each %$count) { + next if $iy > $year; + while (my $im = each %$h) { + next if $im >= $month; + my $val = $iy * 12 + $im; + if ($val < $nowval && $val > $maxbefore) { + $maxbefore = $val; + $calmon->{'prev_url'} = $p->{'_u'}->{'_journalbase'} . sprintf("/%04d/%02d/", $iy, $im); + $calmon->{'prev_date'} = Date($iy, $im, 0); + } + } + } + + # same, except inverse: next month after current time with posts + my $minafter; + while (my ($iy, $h) = each %$count) { + next if $iy < $year; + while (my $im = each %$h) { + next if $im <= $month; + my $val = $iy * 12 + $im; + if ($val > $nowval && (!$minafter || $val < $minafter)) { + $minafter = $val; + $calmon->{'next_url'} = $p->{'_u'}->{'_journalbase'} . sprintf("/%04d/%02d/", $iy, $im); + $calmon->{'next_date'} = Date($iy, $im, 0); + } + } + } + return $calmon; +} + +sub YearYear { + my ($year, $url, $displayed) = @_; + return { '_type' => "YearYear", + 'year' => $year, 'url' => $url, 'displayed' => $displayed }; +} + +sub YearDay { + my ($u, $year, $month, $day, $count, $dow) = @_; + my $d = { + '_type' => 'YearDay', + 'day' => $day, + 'date' => Date($year, $month, $day, $dow), + 'num_entries' => $count + }; + if ($count) { + $d->{'url'} = sprintf("$u->{'_journalbase'}/$year/%02d/%02d/", + $month, $day); + } + return $d; +} + +1; diff --git a/local/cgi-bin/LJ/TextMessage.pm b/local/cgi-bin/LJ/TextMessage.pm new file mode 100755 index 0000000..580f47b --- /dev/null +++ b/local/cgi-bin/LJ/TextMessage.pm @@ -0,0 +1,2164 @@ +#!/usr/bin/perl +# +# LJ::TextMessage class +# See perldoc documentation at the end of this file. +# +# ------------------------------------------------------------------------- +# +# This package is released under the LGPL (GNU Library General Public License) +# +# A copy of the license has been included with the software as LGPL.txt. +# If not, the license is available at: +# http://www.gnu.org/copyleft/library.txt +# +# ------------------------------------------------------------------------- +# + +package LJ::TextMessage; + +use URI::Escape; +use LWP::UserAgent; +use MIME::Lite; + +use strict; +use vars qw($VERSION $SENDMAIL %providers); + +$VERSION = '1.5.3'; + +# default path to sendmail, if none other specified. we should probably +# use something more perl-ish and less unix-specific, but whateva' + +$SENDMAIL = "/usr/sbin/sendmail -t"; + +%providers = ( + + 'email' => { + 'name' => 'Other', + 'notes' => 'If your provider isn\'t supported directly, enter the email address that sends you a text message in phone number field. To be safe, the entire message is sent in the body of the message, and the length limit is really short. We\'d prefer you give us information about your provider so we can support it directly.', + 'fromlimit' => 15, + 'msglimit' => 100, + 'totlimit' => 100, + }, + + 'a1telekom' => { + 'name' => 'A1/Telekom Austria', + 'notes' => 'Enter your phone number. Messages are sent via web gateway. Number must start 43664, 43676, 43699, 43650, 43660, 38640, 38591 or 42379', + 'fromlimit' => 20, + 'msglimit' => 420, + 'totlimit' => 420, + }, + + 'airtouch' => { + 'name' => 'Verizon Wireless (formerly Airtouch)', + 'notes' => 'Enter your phone number. Messages are sent to number@airtouchpaging.com. This is ONLY for former AirTouch customers. Verizon Wireless customers should use Verizon Wireless instead.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + 'aliant' => { + 'name' => 'Alianet (NBTel, MTT, NewTel, and Island Tel)', + 'notes' => 'Enter your phone number. Message is sent to number@wirefree.informe.ca', + 'fromlimit' => 11, + 'msglimit' => 140, + 'totlimit' => 140, + }, + 'alltel' => { + 'name' => 'Alltel', + 'notes' => 'Enter your phone number. Goes to number@message.alltel.com.', + 'fromlimit' => 50, + 'msglimit' => 116, + 'totlimit' => 116, + }, + + 'ameritech' => { + 'name' => 'Ameritech (ACSWireless)', + 'notes' => 'Enter your phone number. Goes to number@paging.acswireless.com', + 'fromlimit' => 120, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'arch' => { + 'name' => 'Arch Wireless', + 'notes' => 'Enter your phone number. Sent via http://www.arch.com/message/ (assumes blank PIN)', + 'fromlimit' => 15, + 'msglimit' => 240, + 'totlimit' => 240, + }, + + 'aubykddi' => { + 'name' => 'AU by KDDI', + 'notes' => 'Enter your phone number. Goes to username@ezweb.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 10000, + 'totlimit' => 10000, + }, + + 'bellmobilityca' => { + 'name' => 'Bell Mobility Canada', + 'notes' => 'Enter your phone number, including the 1 prefix. Goes to number@txt.bellmobility.ca', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'beemail' => { + 'name' => 'BeeLine GSM', + 'notes' => 'Enter your phone number. Goes to number@sms.beemail.ru', + 'fromlimit' => 50, + 'msglimit' => 255, + 'totlimit' => 255, + }, + + 'bellsouth' => { + 'name' => 'Bellsouth', + 'notes' => 'Enter your phone number. Goes to number@bellsouth.cl', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'bellsouthmobility' => { + 'name' => 'BellSouth Mobility', + 'notes' => 'Enter your phone number. Goes to number@blsdcs.net', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'blueskyfrog' => { + 'name' => 'Blue Sky Frog', + 'notes' => 'Enter your phone number. Goes to number@blueskyfrog.com', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'boost' => { + 'name' => 'Boost', + 'notes' => 'Enter your phone number. Goes to number@myboostmobile.com', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'cellularonedobson' => { + 'name' => 'CellularOne (Dobson)', + 'notes' => 'Enter your phone number. Goes to number@mobile.celloneusa.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'cellularonewest' => { + 'name' => 'CellularOne West', + 'notes' => 'Enter your phone number. Goes to number@mycellone.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'centennial' => { + 'name' => 'Centennial Wireless', + 'notes' => 'Enter your phone number. Sent via http://www.centennialwireless.com', + 'fromlimit' => 10, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'cingular' => + { + 'name' => 'Cingular', + 'notes' => 'Enter your phone number. Goes to number@mobile.mycingular.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'cingularblue' => { + 'name' => 'Cingular Blue (formerly AT&T Wireless)', + 'notes' => 'Enter your phone number. Goes to number@mmode.com', + 'fromlimit' => 50, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'claro' => + { + 'name' => 'Claro', + 'notes' => 'Enter your phone number. Goes to number@clarotorpedo.com.br', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'comviq' => + { + 'name' => 'Comviq', + 'notes' => 'Enter your phone number. Goes to number@sms.comviq.se', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'csouth1' => { + 'name' => 'Cellular South', + 'notes' => 'Enter your phone number. Messages are sent to number@csouth1.com', + 'fromlimit' => 50, + 'msglimit' => 155, + 'totlimit' => 155, + }, + + 'dutchtone' => { + 'name' => 'Dutchtone/Orange-NL', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.orange.nl', + 'fromlimit' => 15, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'edgewireless' => { + 'name' => 'Edge Wireless', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.edgewireless.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'emt' => { + 'name' => 'Estonia Mobile Telefon', + 'notes' => 'Enter your phone number. Sent via webform.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'eplus' => { + 'name' => 'EPlus', + 'notes' => 'Enter your phone number. Goes to number@smsmail.eplus.de.', + 'fromlimit' => 20, + 'msglimit' => 480, + 'totlimit' => 480, + }, + + 'fidoca' => { + 'name' => 'Fido Canada', + 'notes' => 'Enter your phone number. Goes to number@fido.ca.', + 'fromlimit' => 15, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'goldentelecom' => { + 'name' => 'Golden Telecom', + 'notes' => 'Enter your phone number or nickname. Messages are sent to number@sms.goldentele.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ideacellular' => { + 'name' => 'Idea Cellular', + 'notes' => 'Enter your phone number. Messages are sent to number@ideacellular.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'imcingular' => + { + 'name' => 'Cingular IM Plus/Bellsouth IPS', + 'notes' => 'Enter 8 digit PIN or user name. Goes to @imcingular.com', + 'fromlimit' => 100, + 'msglimit' => 16000, + 'totlimit' => 16000, + }, + + 'imcingular-cell' => + { + 'name' => 'Cingular IM Plus/Bellsouth IPS Cellphones', + 'notes' => 'Enter phone number. Goes to @mobile.mycingular.com', + 'fromlimit' => 100, + 'msglimit' => 16000, + 'totlimit' => 16000, + }, + + 'kyivstar' => { + 'name' => 'Kyivstar', + 'notes' => 'Sent by addressing the message to number@sms.kyivstar.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'lmt' => { + 'name' => 'LMT', + 'notes' => 'Sent by addressing the message to number@smsmail.lmt.lv', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'meteor' => { + 'name' => 'Meteor', + 'notes' => 'Enter your phone number. Goes to number@sms.mymeteor.ie', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'megafonmoscow' => { + 'name' => 'Megafon Moscow', + 'notes' => 'Enter your phone number. Sent via web form', + 'fromlimit' => 20, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'metrocall' => { + 'name' => 'Metrocall Pager', + 'notes' => '10-digit phone number. Goes to number@page.metrocall.com', + 'fromlimit' => 120, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'metropcs' => { + 'name' => 'Metro PCS', + 'notes' => '10-digit phone number. Goes to number@mymetropcs.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'movistar' => { + 'name' => 'Telefonica Movistar', + 'notes' => '10-digit phone number. Goes to number@movistar.net', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'mtsmobility' => { + 'name' => 'Manitoba Telecom Systems', + 'notes' => '10-digit phone number. Goes to @text.mtsmobility.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'mtsprimtel' => { + 'name' => 'MTS Primtel', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobileone' => { + 'name' => 'MobileOne', + 'notes' => 'Enter your phone number. Goes to number@m1.com.sg', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobilfone' => { + 'name' => 'Mobilfone', + 'notes' => 'Enter your phone number. Goes to number@page.mobilfone.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobility' => { + 'name' => 'Mobility Bermuda', + 'notes' => 'Enter your phone number. Goes to number@ml.bm', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + 'netcom' => { + 'name' => 'Netcom', + 'notes' => 'Enter your phone number. Goes to number@sms.netcom.no', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'nextel' => { + 'name' => 'Nextel', + 'notes' => '10-digit phone number. Goes to 10digits@messaging.nextel.com. Note: do not use dashes in your phone number.', + 'fromlimit' => 50, + 'msglimit' => 126, + 'totlimit' => 126, + }, + + 'nwgsm-megafon' => { + 'name' => 'North-WestGSM Megafon', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'npiwireless' => { + 'name' => 'NPI Wireless', + 'notes' => 'Enter your phone number. Goes to number@npiwireless.com.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ntc' => { + 'name' => 'NTC', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ntelos' => { + 'name' => 'NTELOS', + 'notes' => '10-digit phone number. Goes to 10digits@pcs.ntelos.com.', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'o2' => { + 'name' => 'O2 (formerly BTCellnet)', + 'notes' => 'Enter O2 username - must be enabled first at http://www.o2.co.uk. Goes to username@o2.co.uk.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'o2mmail' => { + 'name' => 'O2 M-mail (formerly BTCellnet)', + 'notes' => 'Enter phone number, omitting intial zero - must be enabled first by sending an SMS saying "ON" to phone number "212". Goes to +44[number]@mmail.co.uk.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'optus' => { + 'name' => 'Optus', + 'notes' => 'Enter your phone number. Goes to @optusmobile.com.au', + 'fromlimit' => 20, + 'msglimit' => 114, + 'totlimit' => 114, + }, + + 'orange' => { + 'name' => 'Orange', + 'notes' => 'Enter your phone number. Goes to @orange.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'oskar' => { + 'name' => 'Oskar', + 'notes' => 'Enter your phone number. Goes to @mujoskar.cz', + 'fromlimit' => 20, + 'msglimit' => 320, + 'totlimit' => 320, + }, + + 'pacbell' => { + 'name' => 'Pacific Bell Cingular', + 'notes' => '10-digit phone number. Goes to @mobile.mycingular.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'pagenet' => { + 'name' => 'Pagenet', + 'notes' => '10-digit phone number (or gateway and pager number separated by a period). Goes to number@pagenet.net.', + 'fromlimit' => 20, + 'msglimit' => 220, + 'totlimit' => 240, + }, + + 'pcom' => { + 'name' => 'Personal Communication (Sonet)', + 'notes' => 'Enter your phone number. Goes to sms@pcom.ru with your number in the subject line.', + 'fromlimit' => 20, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'pcsrogers' => { + 'name' => 'PCS Rogers', + 'notes' => '10-digit phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 125, + 'totlimit' => 125, + }, + + 'phonehouse' => { + 'name' => 'The Phone House', + 'notes' => '10-digit phone number. Goes to number@sms.phonehouse.de.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'plusgsm' => { + 'name' => 'Plus GSM Poland', + 'notes' => '10-digit phone number. Goes to number@text.plusgsm.pl.', + 'fromlimit' => 20, + 'msglimit' => 620, + 'totlimit' => 620, + }, + + 'pscwireless' => { + 'name' => 'PSC Wireless', + 'notes' => 'Enter your phone number. Goes to number@sms.pscel.com', + 'fromlimit' => 20, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'primtel' => { + 'name' => 'Primtel', + 'notes' => 'Enter your phone number. Goes to number@sms.primtel.ru', + 'fromlimit' => 20, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'ptel' => { + 'name' => 'Powertel', + 'notes' => '10-digit phone number. Goes to number@ptel.net', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'qualcomm' => { + 'name' => 'Qualcomm', + 'notes' => 'Enter your username. Goes to username@pager.qualcomm.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'qwest' => { + 'name' => 'Qwest', + 'notes' => '10-digit phone number. Goes to @qwestmp.com', + 'fromlimit' => 14, + 'msglimit' => 100, + 'totlimit' => 100, + }, + + 'safaricom' => { + 'name' => 'Safaricom', + 'notes' => 'Goes to @safaricomsms.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'satelindogsm' => { + 'name' => 'Satelindo GSM', + 'notes' => 'Goes to @satelindogsm.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'scs900' => { + 'name' => 'SCS-900', + 'notes' => 'Goes to @scs-900.ru', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'simplefreedom' => { + 'name' => 'Simple Freedom', + 'notes' => 'Goes to @text.simplefreedom.net', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'skytelalpha' => { + 'name' => 'Skytel - Alphanumeric', + 'notes' => 'Enter your 7-digit pin number as your number and your message will be mailed to pin@skytel.com', + 'fromlimit' => 15, + 'msglimit' => 240, + 'totlimit' => 240, + }, + + 'smarttelecom' => { + 'name' => 'Smart Telecom', + 'notes' => 'Enter your phone number. Goes to @mysmart.mymobile.ph', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'smartsgsm' => { + 'name' => 'Smarts GSM', + 'notes' => 'Enter your phone number. Sent via http://www.samara-gsm.ru/scripts/smsgate.exe', + 'fromlimit' => 11, + 'msglimit' => 70, + 'totlimit' => 70, + }, + + 'southernlinc' => { + 'name' => 'Southern Linc', + 'notes' => 'Enter your 10-digit phone number. Goes to @page.southernlinc.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'sprintpcs' => { + 'name' => 'Sprint PCS', + 'notes' => 'Enter your 10-digit phone number. Goes to @messaging.sprintpcs.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'sprintpcs-shortmail' => { + 'name' => 'Sprint PCS - Short Mail', + 'notes' => 'Enter your phone number. Goes to @sprintpcs.com', + 'fromlimit' => 15, + 'msglimit' => 1000, + 'totlimit' => 1000, + }, + + 'suncom' => { + 'name' => 'SunCom', + 'notes' => 'Enter your number. Email will be sent to number@tms.suncom.com.', + 'fromlimit' => 18, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'surewest' => { + 'name' => 'SureWest Communications', + 'notes' => 'Enter your phone number. Message will be sent to number@mobile.surewest.com', + 'fromlimit' => 20, + 'msglimit' => 200, + 'totlimit' => 200, + }, + + 'swisscom' => { + 'name' => 'SwissCom Mobile', + 'notes' => 'Enter your phone number. Message will be sent to number@bluewin.ch', + 'fromlimit' => 20, + 'msglimit' => 10000, + 'totlimit' => 10000, + }, + + 'tele2' => { + 'name' => 'Tele2 Latvia', + 'notes' => '10-digit phone number. Goes to number@sms.tele2.lv.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telenor' => { + 'name' => 'Telenor', + 'notes' => '10-digit phone number. Goes to number@mobilpost.no.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telia' => { + 'name' => 'Telia Denmark', + 'notes' => '8-digit phone number. Goes to number@gsm1800.telia.dk.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telus' => { + 'name' => 'Telus Mobility', + 'notes' => '10-digit phone number. Goes to 10digits@msg.telus.com.', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'timnet' => { + 'name' => 'TIM', + 'notes' => '10-digit phone number. Goes to number@timnet.com.', + 'fromlimit' => 30, + 'msglimit' => 350, + 'totlimit' => 350, + }, + + 'tmobilegermany' => { + 'name' => 'T-Mobile Germany', + 'notes' => 'Enter your number. Email will be sent to number@T-D1-SMS.de', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileholland' => { + 'name' => 'T-Mobile Netherlands', + 'notes' => 'Send "EMAIL ON" to 555 from your phone, then enter your number starting with 316. Email will be sent to number@gin.nl', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileuk' => { + 'name' => 'T-Mobile UK', + 'notes' => 'Messages are sent to number@t-mobile.uk.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileusa' => { + 'name' => 'T-Mobile USA', + 'notes' => 'Messages are sent to number@tmomail.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'umc' => { + 'name' => 'UMC', + 'notes' => 'Sent by addressing the message to number@sms.umc.com.ua', + 'fromlimit' => 10, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'uscc' => { + 'name' => 'US Cellular', + 'notes' => 'Enter a 10 digit USCC Phone Number. Messages are sent via http://usc.ztango.com/uscwmss', + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'unicel' => { + 'name' => 'Unicel', + 'notes' => 'Sent by addressing the message to number@utext.com', + 'fromlimit' => 10, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'vzw' => { + 'name' => 'Verizon Wireless', + 'notes' => 'Enter your 10-digit phone number. Messages are sent via email to number@vtext.com.', + 'fromlimit' => 34, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'vzw-myairmail' => { + 'name' => 'Verizon Wireless (myairmail.com)', + 'notes' => 'Enter your phone number. Messages are sent via to number@myairmail.com.', + 'fromlimit' => 34, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'vessotel' => { + 'name' => 'Vessotel', + 'notes' => 'Enter your phone number. Messages are sent to roumer@pager.irkutsk.ru.', + 'fromlimit' => 20, + 'msglimit' => 800, + 'totlimit' => 800, + }, + + 'virginmobileusa' => { + 'name' => 'Virgin Mobile USA', + 'notes' => 'Enter your phone number. Messages are sent to number@vmobl.com.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonees' => { + 'name' => 'Vodafone Spain', + 'notes' => 'Enter your username. Messages are sent to username@vodafone.es', + 'fromlimit' => 20, + 'msglimit' => 90, + 'totlimit' => 90, + }, + + 'vodafoneit' => { + 'name' => 'Vodafone Italy', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.vodafone.it', + 'fromlimit' => 20, + 'msglimit' => 132, + 'totlimit' => 132, + }, + + 'vodafonejp-c' => { + 'name' => 'Vodafone Japan (Toukai/Central)', + 'notes' => 'Enter your phone number. Messages are sent to number@c.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-d' => { + 'name' => 'Vodafone Japan (Hokkaido)', + 'notes' => 'Enter your phone number. Messages are sent to number@d.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-h' => { + 'name' => 'Vodafone Japan (Touhoku/Niigata/North)', + 'notes' => 'Enter your phone number. Messages are sent to number@h.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-k' => { + 'name' => 'Vodafone Japan (Kansai/West -- including Osaka)', + 'notes' => 'Enter your phone number. Messages are sent to number@k.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-n' => { + 'name' => 'Vodafone Japan (Chuugoku/Western)', + 'notes' => 'Enter your phone number. Messages are sent to number@n.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-q' => { + 'name' => 'Vodafone Japan (Kyuushu/Okinawa)', + 'notes' => 'Enter your phone number. Messages are sent to number@q.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-r' => { + 'name' => 'Vodafone Japan (Hokuriko/Central North)', + 'notes' => 'Enter your phone number. Messages are sent to number@r.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-s' => { + 'name' => 'Vodafone Japan (Shikoku)', + 'notes' => 'Enter your phone number. Messages are sent to number@s.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-t' => { + 'name' => 'Vodafone Japan (Kanto/Koushin/East -- including Tokyo)', + 'notes' => 'Enter your phone number. Messages are sent to number@t.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafoneuk' => { + 'name' => 'Vodafone UK', + 'notes' => 'Enter your username. Messages are sent to username@vodafone.net', + 'fromlimit' => 20, + 'msglimit' => 70, + 'totlimit' => 90, + }, + + 'voicestream' => { + 'name' => 'Voicestream', + 'notes' => 'Enter your 10-digit phone number. Message is sent via the email gateway, since they changed their web gateway and we have not gotten it working with the new one yet.', + 'fromlimit' => 15, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'weblinkwireless' => { + 'name' => 'Weblink Wireless', + 'notes' => 'Enter your phone number. Goes to @airmessage.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'wellcom' => { + 'name' => 'WellCom', + 'notes' => 'Enter your phone number. Goes to @sms.welcome2well.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'wyndtell' => { + 'name' => 'WyndTell', + 'notes' => 'Enter username/phone number. Goes to @wyndtell.com', + 'fromlimit' => 20, + 'msglimit' => 480, + 'totlimit' => 500, + }, + +); + +sub providers +{ + return sort { lc($providers{$a}->{'name'}) cmp lc($providers{$b}->{'name'}) } keys %providers; +} + +sub provider_info +{ + my $provider = remap(shift); + return { %{$providers{$provider}} }; +} + +sub remap { + my $provider = shift; + return "o2mmail" if $provider eq "btcellnet"; + return "voicestream" if $provider eq "voicestream2"; + return "tmobileusa" if $provider eq "tmomail"; + return "suncom" if $provider eq "tms-suncom"; + return "cingular" if $provider eq "cingular-acs"; + return "cingular" if $provider eq "cingular-texas"; + return "cingularblue" if $provider eq "att"; + return "aliant" if $provider eq "nbtel"; + return $provider; +} + +sub new { + my ($class, $args) = @_; + my $self = {}; + bless $self, ref $class || $class; + + $self->init($args); + return $self; +} + +sub init { + my $self = shift; + my $args = shift; + $self->{'sendmail'} = $args->{'mailcommand'} || $SENDMAIL; + $self->{'provider'} = remap($args->{'provider'}); + $self->{'number'} = $args->{'number'}; + $self->{'smtp'} = $args->{'smtp'}; +} + +sub send +{ + my $self = shift; + my $msg = shift; # hashref: 'from', 'message' + my $errors = shift; # arrayref + my $provider = $self->{'provider'}; + + unless ($provider) { + push @$errors, "No provider specified in object constructor."; + return; + } + + unless ($msg) { + push @$errors, "No message specified in object constructor."; + return; + } + unless ($self) { + push @$errors, "No self specified in object constructor."; + return; + } + unless ($self->{'sendmail'}) { + push @$errors, "No sendmail specified in object constructor."; + return; + } + unless ($self->{'provider'}) { + push @$errors, "No provider specified in object constructor."; + return; + } + unless ($self->{'number'}) { + push @$errors, "No number specified in object constructor."; + return; + } + + my $prov = $providers{$provider}; + + ## + ## truncate 'from' if it's too long for the given provider + ## + + if (length($msg->{'from'}) > $prov->{'fromlimit'}) { + $msg->{'from'} = substr($msg->{'from'}, 0, $prov->{'fromlimit'}); + } + + ## + ## now send the message, based on the provider + ## + + if ($provider eq "email") + { + send_mail($self, { + 'to' => $self->{'number'}, + 'from' => "LJ.Rossia.org", + 'body' => "(f:$msg->{'from'})$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "a1telekom") + { + $self->{'number'} =~ /(\d\d\d\d\d)(\d+)/; + post_webform("http://www.a1.net/sms_check_tr/1,2855,14-813-html-de,00.html", { + 'an1' => $1, + 'an2' => $2, + 'msg' => $msg->{'message'}, + 'userEmail' => $msg->{'from'}, + },$errors); + } + + elsif ($provider eq "airtouch") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sender.airtouchpaging.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "aliant") + { + send_mail($self, { + 'to' => "$self->{'number'}\@wirefree.informe.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "alltel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@message.alltel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ameritech") + { + send_mail($self, { + 'to' => "$self->{'number'}\@paging.acswireless.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "arch") + { + send_mail($self, { + 'to' => "$self->{'number'}\@archwireless.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "aubykddi") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ezweb.ne.jp", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "beemail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.beemail.ru", + 'body' => "$msg->{'from'} - $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellmobilityca") + { + send_mail($self, { + 'to' => "$self->{'number'}\@txt.bellmobility.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellsouth") + { + send_mail($self, { + 'to' => "$self->{'number'}\@bellsouth.cl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellsouthmobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@blsdcs.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + + elsif ($provider eq "blueskyfrog") + { + send_mail($self, { + 'to' => "$self->{'number'}\@blueskyfrog.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "boost") + { + send_mail($self, { + 'to' => "$self->{'number'}\@myboostmobile.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "cellularonedobson") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.celloneusa.com", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "cellularonewest") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mycellone.net", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "centennial") + { + post_webform("http://www.centennialwireless.com/home/sms.php", { + 'deviceid' => $self->{'number'}, + 'mess' => $msg->{'message'}, + 'yournumber' => $msg->{'from'}, + },$errors); + } + + elsif ($provider eq "cingular") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "cingularblue") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mmode.com", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "claro") + { + send_mail($self, { + 'to' => "$self->{'number'}\@clarotorpedo.com.br", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "comviq") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.comviq.se", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "csouth1") { + send_mail($self, { + 'to' => "$self->{'number'}\@csouth1.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "dutchtone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.orange.nl", + 'body' => "$msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "edgewireless") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.edgewireless.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "emt") + { + post_webform("http://www.emt.ee/wwwmain", { + 'actionId' => "send", + 'phoneNo' => $self->{'number'}, + 'userEmail' => $msg->{'from'}, + 'message' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "eplus") + { + send_mail($self, { + 'to' => "$self->{'number'}\@smsmail.eplus.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "fidoca" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@fido.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "goldentelecom") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.goldentele.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "ideacellular") { + send_mail($self, { + 'to' => "$self->{'number'}\@ideacellular.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "imcingular") + { + send_mail($self, { + 'to' => "$self->{'number'}\@imcingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "imcingular-cell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "kyivstar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.kyivstar.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "lmt") + { + send_mail($self, { + 'to' => "$self->{'number'}\@smsmail.lmt.lv", + + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "megafonmoscow") + { + my $prefix = substr($self->{'number'},0,4); + post_webform("http://www.megafonmoscow.ru/misc/sms2", { + 'prefix' => "$prefix", + 'message' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "meteor") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.mymeteor.ie", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "metrocall") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.metrocall.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "metropcs") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mymetropcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mobileone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@m1.com.sg", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mobilfone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.mobilfone.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "movistar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@movistar.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mtsmobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.mtsmobility.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mtsprimtel") + { + post_webform("http://80.83.224.19/sms/sent_sakh.shtml", { + 'ref' => 8, + 'txtAddr' => $self->{'number'}, + 'textSM' => "(f:".$msg->{'from'}.")".$msg->{'message'}, + },$errors); + } + + elsif ($provider eq "mobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ml.bm", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "netcom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.netcom.no", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "nextel") # Nextel + { + send_mail($self, { + 'to' => "$self->{'number'}\@messaging.nextel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "nwgsm-megafon") + { + post_webform("http://www-old.nwgsm.ru:8101/sendsms.htm", { + "tll" => $self->{'number'}, + "txt" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "npiwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@npiwireless.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ntc") + { + my $prefix; + my $number; + if ($self->{'number'} =~ /^74232(\d\d\d\d\d\d)/) { + $prefix = "74232"; + $number = $1; + } + if ($self->{'number'} =~ /^(7902\d\d\d)(\d\d\d\d)/) { + $prefix = $1; + $number = $2; + } + post_webform("http://www.ntconline.ru/data/pages/sms/send.php", { + 'sent' => 1, + 'prefix' => $prefix, + 'number' => $number, + 'lang' => "eng", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "ntelos") # NTELOS PCS + { + send_mail($self, { + 'to' => "$self->{'number'}\@pcs.ntelos.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "o2") + { + send_mail($self, { + 'to' => $self->{'number'}."\@o2.co.uk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "o2mmail") + { + send_mail($self, { + 'to' => "+44".$self->{'number'}."\@mmail.co.uk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "optus") + { + send_mail($self, { + 'to' => "$self->{'number'}\@optusmobile.com.au", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "orange") + { + send_mail($self, { + 'to' => "$self->{'number'}\@orange.net", + 'from' => "$msg->{'from'}", + 'subject' => "$msg->{'message'}", + 'body' => "Textmessage in subject line.", + },$errors); + } + + elsif ($provider eq "oskar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@musoskar.cz", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pacbell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pagenet") + { + send_mail($self, { + 'to' => "$self->{'number'}\@pagenet.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pcom") + { + send_mail($self, { + 'to' => "sms\@pcom.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "$self->{'number'}", + },$errors); + } + + elsif ($provider eq "pcsrogers") + { + $self->{'number'} =~ /(\d\d\d)(\d\d\d)(\d\d\d\d)/; + post_webform("http://216.129.53.44:8080/cgi-bin/send_sm_rogers.new", { + "area" => $1, + "num1" => $2, + "num2" => $3, + "text" => "From $msg->{'from'}: $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "phonehouse") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.phonehouse.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "plusgsm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.plusgsm.pl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pscwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.pscel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "primtel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.primtel.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ptel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ptel.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "qualcomm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@pager.qualcomm.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "qwest") + { + send_mail($self, { + 'to' => "(f:$msg->{'from'})$self->{'number'}\@qwestmp.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "safaricom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@safaricomsms.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "satelindogsm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@satelindogsm.com", + 'from' => $LJ::BOGUS_EMAIL, + 'body' => "From: $msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "scs900") + { + send_mail($self, { + 'to' => "$self->{'number'}\@scs-900.ru", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "simplefreedom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.simplefreedom.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "skytelalpha") + { + send_mail($self, { + 'to' => "$self->{'number'}\@skytel.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "smarttelecom") { + send_mail($self, { + 'to' => "$self->{'number'}\@mysmart.mymobile.ph", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "smartsgsm") + { + post_webform("http://www.samara-gsm.ru/scripts/smsgate.exe/send", { + "phone" => $self->{'number'}, + "sendtext" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "southernlinc") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.southernlinc.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "sprintpcs") # SprintPCS + { + send_mail($self, { + 'to' => "(f:$msg->{'from'}) $self->{'number'}\@messaging.sprintpcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "sprintpcs-shortmail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sprintpcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "suncom") { + send_mail($self, { + 'to' => "$self->{'number'}\@tms.suncom.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "surewest") { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.surewest.com", + 'body' => "(f:$msg->{'from'}) $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "swisscom") { + send_mail($self, { + 'to' => "$self->{'number'}\@bluewin.ch", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tele2") { + post_webform("http://sms.tele2.lv/cgi-bin/send_sm_t2.cgi", { + "msisdn" => $self->{'number'}, + "text" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "telenor") { + send_mail($self, { + 'to' => "$self->{'number'}\@mobilpost.no", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "telia") { + send_mail($self, { + 'to' => "$self->{'number'}\@gsm1800.telia.dk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "telus") # Telus Mobility + { + send_mail($self, { + 'to' => "$self->{'number'}\@msg.telus.com", + 'from' => "$msg->{'from'}", + 'body' => "(f:$msg->{'from'})$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "timnet") + { + send_mail($self, { + 'to' => "$self->{'number'}\@timnet.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileaustria") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.t-mobile.at", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobilegermany") + { + send_mail($self, { + 'to' => "$self->{'number'}\@T-D1-SMS.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileholland") + { + send_mail($self, { + 'to' => "$self->{'number'}\@gin.nl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileuk") + { + send_mail($self, { + 'to' => "$self->{'number'}\@t-mobile.uk.net", + 'subject' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'from' => "LJ", + },$errors); + } + + elsif ($provider eq "tmobileusa") + { + send_mail($self, { + 'to' => "$self->{'number'}\@tmomail.net", + 'subject' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'from' => "LJ", + },$errors); + } + + elsif ($provider eq "umc") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.umc.com.ua", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "uscc") # U.S Cellular + { + post_webform("http://usc.ztango.com/uscwmss", { + "addresses" => $self->{'number'}, + "MSG" => "$msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "unicel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@utext.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vzw") # Verizon Wireless + { + send_mail($self, { + 'to' => "$self->{'number'}\@vtext.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "vzw-myairmail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@myairmail.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vessotel" ) + { + send_mail($self, { + 'to' => "roumer\@pager.irkutsk.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "$self->{'number'}", + },$errors); + } + + elsif ($provider eq "virginmobileusa" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@vmobl.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vodafonees") { + send_mail($self, { + 'to' => "$self->{'number'}\@vodafone.es", + 'from' => $msg->{'from'}, + 'subject' => $msg->{'message'}, + 'body' => "Your LJ.Rossia.org Text Message has been placed into the subject line." + },$errors); + } + + elsif ($provider eq "vodafoneit") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.vodafone.it", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-c") { + send_mail($self, { + 'to' => "$self->{'number'}\@c.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-d") { + send_mail($self, { + 'to' => "$self->{'number'}\@d.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-h") { + send_mail($self, { + 'to' => "$self->{'number'}\@h.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-k") { + send_mail($self, { + 'to' => "$self->{'number'}\@k.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-n") { + send_mail($self, { + 'to' => "$self->{'number'}\@n.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-q") { + send_mail($self, { + 'to' => "$self->{'number'}\@q.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-r") { + send_mail($self, { + 'to' => "$self->{'number'}\@r.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-s") { + send_mail($self, { + 'to' => "$self->{'number'}\@s.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-t") { + send_mail($self, { + 'to' => "$self->{'number'}\@t.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafoneuk") { + send_mail($self, { + 'to' => "$self->{'number'}\@vodafone.net", + 'from' => $msg->{'from'}, + 'subject' => $msg->{'message'}, + 'body' => "Your LJ.Rossia.org Text Message has been placed into the subject line." + },$errors); + } + + elsif ($provider eq "voicestream" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@voicestream.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "weblinkwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@airmessage.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "wellcom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.welcome2well.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "wyndtell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@wyndtell.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + else { + push @$errors, "Tried to send a message to an unknown or unsupported provider."; + } +} + +sub post_webform +{ + my ($url, $postvars, $errors) = @_; + + ### we're going to POST to provider's page + my $ua = new LWP::UserAgent; + $ua->agent("Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"); + $ua->timeout(5); + + my $req = new HTTP::Request POST => $url; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(request_string($postvars)); + + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + if ($res->is_success || $res->is_redirect) { + return; + } else { + push @$errors, "There was some error contacting the user's text messaging service via its web gateway. The message was most likely not sent."; + return; + } +} + +sub send_mail +{ + my $self = shift; + my $opt = shift; + my $errors = shift; + my $status; + unless ($opt->{'to'}) { + push @$errors, "To not defined in provider description."; + return; + } + unless ($opt->{'body'}) { + push @$errors, "Data not defined in provider description."; + return; + } + $opt->{'from'} =~ s,[!\\/\@#],_,g; # I haven't escaped too much/too little, have I? + my $msg = new MIME::Lite ('From' => $opt->{'from'} . "\@$LJ::DOMAIN", + 'To' => $opt->{'to'}, + 'Subject' => $opt->{'subject'}, + 'Data' => $opt->{'body'}); + if ($self->{'smtp'}) { + $status = eval { $msg->send_by_smtp($self->{'smtp'}, Timeout => 10) && 1; }; + } else { + $status = eval { $msg->send_by_sendmail($self->{'sendmail'}) && 1; }; + } + unless ($status) { + if ($@ =~ /(bad address syntax|syntax illegal)/i) { + push @$errors, "Recipient has an invalid email address on file."; + } else { + push @$errors, "There may have been a problem sending your message through the email gateway. The error reported was: $@"; + } + } + return $status; +} + +sub request_string +{ + my ($vars) = shift; + my $req = ""; + foreach (sort keys %{$vars}) + { + my $val = uri_escape($vars->{$_},"\+\=\&"); + $val =~ s/ /+/g; + $req .= "&" if $req; + $req .= "$_=$val"; + } + return $req; +} + +1; +__END__ +# Below is the stub of documentation for your module. You better edit it! + +=head1 NAME + +LJ::TextMessage - text message phones/pages using a variety of methods/services + +=head1 SYNOPSIS + + use LJ::TextMessage; + + @providers = LJ::TextMessage::providers(); + foreach my $p (@providers) { + my $info = LJ::TextMessage::provider_info($p); + print "Name: $info->{'name'}\n"; + print "Notes: $info->{'notes'}\n"; + print "Limits: \n"; + foreach my $limit (qw(from msg tot)) { + print " $limit: ", $info->{"${limit}limit"}, "\n"; + } + } + + my $phone = new LJ::TextMessage { + 'provider' => 'voicestream', + 'number' => '2045551212', + 'mailcommand' => '/usr/local/sbin/sendmail -t', + }; + + my @errors; + $phone->send({ 'from' => 'Bob', + 'message' => "Hello! This is my message!" }, + \@errors); + if (@errors) { + ... + } else { + print "Message sent!\n"; + } + +=head1 DESCRIPTION + +The synopsis pretty much shows all the functionality that's available, +but details would be nice here. + +=head1 BUGS + +This library is highly volatile, as cellphone and pager providers can +change the details of their web or email gateways at any time. In +practice I haven't had to update this library much, but providers have +no responsibility to tell me when they change their form field names +on their website, or change URLs*. + +This documentation sucks rancid goats**. + + +* - This will, of course, change once LJ has conquered the world. +** - No, not Frank. + +=head1 AUTHOR + +Current maintainers: + - Aaron B. Russell (idigital) - + - Eric Carr (iicarrii) - + +Based on (mostly still, actually) code by: + - Brad Fitzpatrick (bradfitz) - + - Nicholas Tang (ntang) - + +Additional code provided by: + - Larry Gilbert (l2g) - + - (delphy) + - (rory) + - Tony Sutton (tsutton) - + - Chris Bartow (christowang) - + - Gavin Mogan (halkeye) - + - Steven Kreuzer (22dip) - +(if you've been forgotten, please give a holler!) + +Information about text messaging gateways from many. + +=cut diff --git a/local/cgi-bin/LJ/User.pm b/local/cgi-bin/LJ/User.pm new file mode 100755 index 0000000..01855e6 --- /dev/null +++ b/local/cgi-bin/LJ/User.pm @@ -0,0 +1,3712 @@ +# +# LiveJournal user object +# +# 2004-07-21: we're transition from $u hashrefs to $u objects, currently +# backed by hashrefs, to ease migration. in the future, +# more methods from ljlib.pl and other places will move here, +# and the representation of a $u object will change to 'fields'. +# at present, the motivation to moving to $u objects is to do +# all database access for a given user through his/her $u object +# so the queries can be tagged for use by the star replication +# daemon. + +use strict; + +package LJ::User; +use Carp; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJ::MemCache; + + +# instance method: returns userprop for a user. currently from cache with no +# way yet to force master. +sub prop { + my ($u, $prop) = @_; + + # some props have accessors which do crazy things, if so they need + # to be redirected from this method, which only loads raw values + if ({ map { $_ => 1 } + qw(opt_sharebday opt_showbday opt_showlocation opt_showmutualfriends + view_control_strip show_control_strip opt_ctxpopup + esn_inbox_default_expand opt_getting_started) + }->{$prop}) + { + return $u->$prop; + } + + return $u->raw_prop($prop); +} + +sub raw_prop { + my ($u, $prop) = @_; + $u->preload_props($prop) unless exists $u->{$_}; + return $u->{$prop}; +} + +sub preload_props { + my $u = shift; + LJ::load_user_props($u, @_); +} + +sub readonly { + my $u = shift; + return LJ::get_cap($u, "readonly"); +} + +# returns self (the $u object which can be used for $u->do) if +# user is writable, else 0 +sub writer { + my $u = shift; + return $u if $u->{'_dbcm'} ||= LJ::get_cluster_master($u); + return 0; +} + +# returns a true value if the user is underage; or if you give it an argument, +# will turn on/off that user's underage status. can also take a second argument +# when you're setting the flag to also update the underage_status userprop +# which is used to record if a user was ever marked as underage. +sub underage { + # has no bearing if this isn't on + return undef unless $LJ::UNDERAGE_BIT; + + # now get the args and continue + my $u = shift; + return LJ::get_cap($u, 'underage') unless @_; + + # now set it on or off + my $on = shift() ? 1 : 0; + if ($on) { + LJ::modify_caps($u, [ $LJ::UNDERAGE_BIT ], []); + $u->{caps} |= 1 << $LJ::UNDERAGE_BIT; + } else { + LJ::modify_caps($u, [], [ $LJ::UNDERAGE_BIT ]); + $u->{caps} &= !(1 << $LJ::UNDERAGE_BIT); + } + + # now set their status flag if one was sent + my $status = shift(); + if ($status || $on) { + # by default, just records if user was ever underage ("Y") + $u->underage_status($status || 'Y'); + } + + # add to statushistory + if (my $shwhen = shift()) { + my $text = $on ? "marked" : "unmarked"; + my $status = $u->underage_status; + LJ::statushistory_add($u, undef, "coppa", "$text; status=$status; when=$shwhen"); + } + + # now fire off any hooks that are available + LJ::run_hooks('set_underage', { + u => $u, + on => $on, + status => $u->underage_status, + }); + + # return what we set it to + return $on; +} + +# log a line to our userlog +sub log_event { + my $u = shift; + + my ($type, $info) = @_; + return undef unless $type; + $info ||= {}; + + # now get variables we need; we use delete to remove them from the hash so when we're + # done we can just encode what's left + my $ip = delete($info->{ip}) || LJ::get_remote_ip() || undef; + my $uniq = delete $info->{uniq}; + unless ($uniq) { + eval { + $uniq = Apache->request->notes('uniq'); + }; + } + my $remote = delete($info->{remote}) || LJ::get_remote() || undef; + my $targetid = (delete($info->{actiontarget})+0) || undef; + my $extra = %$info ? join('&', map { LJ::eurl($_) . '=' . LJ::eurl($info->{$_}) } keys %$info) : undef; + + # now insert the data we have + $u->do("INSERT INTO userlog (userid, logtime, action, actiontarget, remoteid, ip, uniq, extra) " . + "VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?, ?, ?, ?)", undef, $u->{userid}, $type, + $targetid, $remote ? $remote->{userid} : undef, $ip, $uniq, $extra); + return undef if $u->err; + return 1; +} + +# return or set the underage status userprop +sub underage_status { + return undef unless $LJ::UNDERAGE_BIT; + + my $u = shift; + + # return if they aren't setting it + unless (@_) { + LJ::load_user_props($u, 'underage_status'); + return $u->{underage_status}; + } + + # set and return what it got set to + LJ::set_userprop($u, 'underage_status', shift()); + return $u->{underage_status}; +} + +# returns a true value if user has a reserved 'ext' name. +sub external { + my $u = shift; + return $u->{user} =~ /^ext_/; +} + +# this is for debugging/special uses where you need to instruct +# a user object on what database handle to use. returns the +# handle that you gave it. +sub set_dbcm { + my $u = shift; + return $u->{'_dbcm'} = shift; +} + +sub begin_work { + my $u = shift; + return 1 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->begin_work; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +sub commit { + my $u = shift; + return 1 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->commit; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +sub rollback { + my $u = shift; + return 0 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->rollback; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +# get an $sth from the writer +sub prepare { + my $u = shift; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->prepare(@_); + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +# $u->do("UPDATE foo SET key=?", undef, $val); +sub do { + my $u = shift; + my $query = shift; + + my $uid = $u->{userid}+0 + or croak "Database update called on null user object"; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + $query =~ s!^(\s*\w+\s+)!$1/* uid=$uid */ !; + + my $rv = $dbcm->do($query, @_); + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + + $u->{_mysql_insertid} = $dbcm->{'mysql_insertid'} if $dbcm->{'mysql_insertid'}; + + return $rv; +} + +sub selectrow_array { + my $u = shift; + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + return $dbcm->selectrow_array(@_); +} + +sub selectrow_hashref { + my $u = shift; + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + return $dbcm->selectrow_hashref(@_); +} + +sub err { + my $u = shift; + return $u->{_dberr}; +} + +sub errstr { + my $u = shift; + return $u->{_dberrstr}; +} + +sub quote { + my $u = shift; + my $text = shift; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + return $dbcm->quote($text); +} + +sub mysql_insertid { + my $u = shift; + if ($u->isa("LJ::User")) { + return $u->{_mysql_insertid}; + } elsif (LJ::isdb($u)) { + my $db = $u; + return $db->{'mysql_insertid'}; + } else { + die "Unknown object '$u' being passed to LJ::User::mysql_insertid."; + } +} + +# +# name: LJ::User::dudata_set +# class: logging +# des: Record or delete disk usage data for a journal +# args: u, area, areaid, bytes +# area: One character: "L" for log, "T" for talk, "B" for bio, "P" for pic. +# areaid: Unique ID within $area, or '0' if area has no ids (like bio) +# bytes: Number of bytes item takes up. Or 0 to delete record. +# returns: 1. +# +sub dudata_set { + my ($u, $area, $areaid, $bytes) = @_; + $bytes += 0; $areaid += 0; + if ($bytes) { + $u->do("REPLACE INTO dudata (userid, area, areaid, bytes) ". + "VALUES (?, ?, $areaid, $bytes)", undef, + $u->{userid}, $area); + } else { + $u->do("DELETE FROM dudata WHERE userid=? AND ". + "area=? AND areaid=$areaid", undef, + $u->{userid}, $area); + } + return 1; +} + +sub generate_session +{ + my ($u, $opts) = @_; + my $udbh = LJ::get_cluster_master($u); + return undef unless $udbh; + + # clean up any old, expired sessions they might have (lazy clean) + $u->do("DELETE FROM sessions WHERE userid=? AND timeexpire < UNIX_TIMESTAMP()", + undef, $u->{userid}); + + my $sess = {}; + $opts->{'exptype'} = "short" unless $opts->{'exptype'} eq "long" || + $opts->{'exptype'} eq "once"; + $sess->{'auth'} = LJ::rand_chars(10); + my $expsec = $opts->{'expsec'}+0 || { + 'short' => 60*60*24*1.5, # 36 hours + 'long' => 60*60*24*60, # 60 days + 'once' => 60*60*24*1.5, # same as short; just doesn't renew + }->{$opts->{'exptype'}}; + my $id = LJ::alloc_user_counter($u, 'S'); + return undef unless $id; + $u->do("REPLACE INTO sessions (userid, sessid, auth, exptype, ". + "timecreate, timeexpire, ipfixed) VALUES (?,?,?,?,UNIX_TIMESTAMP(),". + "UNIX_TIMESTAMP()+$expsec,?)", undef, + $u->{'userid'}, $id, $sess->{'auth'}, $opts->{'exptype'}, $opts->{'ipfixed'}); + return undef if $u->err; + $sess->{'sessid'} = $id; + $sess->{'userid'} = $u->{'userid'}; + $sess->{'ipfixed'} = $opts->{'ipfixed'}; + $sess->{'exptype'} = $opts->{'exptype'}; + + # clean up old sessions + my $old = $udbh->selectcol_arrayref("SELECT sessid FROM sessions WHERE ". + "userid=$u->{'userid'} AND ". + "timeexpire < UNIX_TIMESTAMP()"); + $u->kill_sessions(@$old) if $old; + + # mark account as being used + LJ::mark_user_active($u, 'login'); + + return $sess; +} + +sub make_login_session { + my ($u, $exptype, $ipfixed) = @_; + $exptype ||= 'short'; + return 0 unless $u; + + my $etime = 0; + eval { Apache->request->notes('ljuser' => $u->{'user'}); }; + + my $sess = $u->generate_session({ + 'exptype' => $exptype, + 'ipfixed' => $ipfixed, + }); + $BML::COOKIE{'ljsession'} = [ "ws:$u->{'user'}:$sess->{'sessid'}:$sess->{'auth'}", $etime, 1 ]; + LJ::set_remote($u); + + LJ::load_user_props($u, "browselang", "schemepref" ); + my $bl = LJ::Lang::get_lang($u->{'browselang'}); + if ($bl) { + BML::set_cookie("langpref", $bl->{'lncode'} . "/" . time(), 0, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + BML::set_language($bl->{'lncode'}); + } + + # restore default scheme + if ($u->{'schemepref'} ne "") { + BML::set_cookie("BMLschemepref", $u->{'schemepref'}, 0, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + BML::set_scheme($u->{'schemepref'}); + } + + LJ::run_hooks("post_login", { + "u" => $u, + "form" => {}, + "expiretime" => $etime, + }); + + LJ::mark_user_active($u, 'login'); + + return 1; +} + +sub tosagree_set +{ + my ($u, $err) = @_; + return undef unless $u; + + unless (-f "$LJ::HOME/htdocs/inc/legal-tos") { + $$err = "TOS include file could not be found"; + return undef; + } + + my $rev; + open (TOS, "$LJ::HOME/htdocs/inc/legal-tos"); + while ((!$rev) && (my $line = )) { + my $rcstag = "Revision"; + if ($line =~ /\$$rcstag:\s*(\S+)\s*\$/) { + $rev = $1; + } + } + close TOS; + + # if the required version of the tos is not available, error! + my $rev_req = $LJ::REQUIRED_TOS{rev}; + if ($rev_req > 0 && $rev ne $rev_req) { + $$err = "Required Terms of Service revision is $rev_req, but system version is $rev."; + return undef; + } + + my $newval = join(', ', time(), $rev); + my $rv = LJ::set_userprop($u, "legal_tosagree", $newval); + + # set in $u object for callers later + $u->{legal_tosagree} = $newval if $rv; + + return $rv; +} + +sub tosagree_verify { + my $u = shift; + + return 1 unless $LJ::TOS_CHECK; + + my $rev_req = $LJ::REQUIRED_TOS{rev}; + return 1 unless $rev_req > 0; + + LJ::load_user_props($u, 'legal_tosagree') + unless $u->{legal_tosagree}; + + my $rev_cur = (split(/\s*,\s*/, $u->{legal_tosagree}))[1]; + + return $rev_cur eq $rev_req; +} + +sub kill_sessions { + my $u = shift; + my (@sessids) = @_; + my $in = join(',', map { $_+0 } @sessids); + return 1 unless $in; + my $userid = $u->{'userid'}; + foreach (qw(sessions sessions_data)) { + $u->do("DELETE FROM $_ WHERE userid=? AND ". + "sessid IN ($in)", undef, $userid); + } + foreach my $id (@sessids) { + $id += 0; + my $memkey = [$userid,"sess:$userid:$id"]; + LJ::MemCache::delete($memkey); + } + return 1; +} + +sub kill_all_sessions { + my $u = shift; + return 0 unless $u; + my $udbh = LJ::get_cluster_master($u); + my $sessions = $udbh->selectcol_arrayref("SELECT sessid FROM sessions WHERE ". + "userid=$u->{'userid'}"); + $u->kill_sessions(@$sessions) if @$sessions; + + # forget this user, if we knew they were logged in + delete $BML::COOKIE{'ljsession'}; + LJ::set_remote(undef) if + $LJ::CACHE_REMOTE && + $LJ::CACHE_REMOTE->{userid} == $u->{userid}; + + return 1; +} + +sub kill_session { + my $u = shift; + return 0 unless $u; + return 0 unless exists $u->{'_session'}; + $u->kill_sessions($u->{'_session'}->{'sessid'}); + + # forget this user, if we knew they were logged in + delete $BML::COOKIE{'ljsession'}; + LJ::set_remote(undef) if + $LJ::CACHE_REMOTE && + $LJ::CACHE_REMOTE->{userid} == $u->{userid}; + + return 1; +} + +# +# name: LJ::User::mogfs_userpic_key +# class: mogilefs +# des: Make a mogilefs key for the given pic for the user +# args: pic +# pic: Either the userpic hash or the picid of the userpic. +# returns: 1. +# +sub mogfs_userpic_key { + my $self = shift or return undef; + my $pic = shift or croak "missing required arg: userpic"; + + my $picid = ref $pic ? $pic->{picid} : $pic+0; + return "up:$self->{userid}:$picid"; +} + +# all reads/writes to talk2 must be done inside a lock, so there's +# no race conditions between reading from db and putting in memcache. +# can't do a db write in between those 2 steps. the talk2 -> memcache +# is elsewhere (talklib.pl), but this $dbh->do wrapper is provided +# here because non-talklib things modify the talk2 table, and it's +# nice to centralize the locking rules. +# +# return value is return of $dbh->do. $errref scalar ref is optional, and +# if set, gets value of $dbh->errstr +# +# write: (LJ::talk2_do) +# GET_LOCK +# update/insert into talk2 +# RELEASE_LOCK +# delete memcache +# +# read: (LJ::Talk::get_talk_data) +# try memcache +# GET_LOCk +# read db +# update memcache +# RELEASE_LOCK + +sub talk2_do { + my ($u, $nodetype, $nodeid, $errref, $sql, @args) = @_; + return undef unless $nodetype =~ /^\w$/; + return undef unless $nodeid =~ /^\d+$/; + return undef unless $u->writer; + + my $dbcm = $u->{_dbcm}; + + my $memkey = [$u->{'userid'}, "talk2:$u->{'userid'}:$nodetype:$nodeid"]; + my $lockkey = $memkey->[1]; + + $dbcm->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + my $ret = $u->do($sql, undef, @args); + $$errref = $u->errstr if ref $errref && $u->err; + $dbcm->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + LJ::MemCache::delete($memkey, 0) if int($ret); + return $ret; +} + +# log2_do +# see comments for talk2_do + +sub log2_do { + my ($u, $errref, $sql, @args) = @_; + return undef unless $u->writer; + + my $dbcm = $u->{_dbcm}; + + my $memkey = [$u->{'userid'}, "log2lt:$u->{'userid'}"]; + my $lockkey = $memkey->[1]; + + $dbcm->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + my $ret = $u->do($sql, undef, @args); + $$errref = $u->errstr if ref $errref && $u->err; + $dbcm->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + LJ::MemCache::delete($memkey, 0) if int($ret); + return $ret; +} + +sub url { + my $u = shift; + LJ::load_user_props($u, "url"); + if ($u->{'journaltype'} eq "I" && ! $u->{url}) { + my $id = $u->identity; + if ($id && $id->[0] eq "O") { + LJ::set_userprop($u, "url", $id->[1]) if $id->[1]; + return $id->[1]; + } + } + return $u->{url}; +} + +# returns arrayref of [idtype, identity] +sub identity { + my $u = shift; + return $u->{_identity} if $u->{_identity}; + return undef unless $u->{'journaltype'} eq "I"; + my $memkey = [$u->{userid}, "ident:$u->{userid}"]; + my $ident = LJ::MemCache::get($memkey); + if ($ident) { + return $u->{_identity} = $ident; + } + + my $dbh = LJ::get_db_writer(); + $ident = $dbh->selectrow_arrayref("SELECT idtype, identity FROM identitymap ". + "WHERE userid=? LIMIT 1", undef, $u->{userid}); + if ($ident) { + LJ::MemCache::set($memkey, $ident); + return $ident; + } + return undef; +} + +# returns a URL iff account is an OpenID identity. undef otherwise. +sub openid_identity { + my $u = shift; + my $ident = $u->identity; + return undef unless $ident && $ident->[0] == 0; + return $ident->[1]; +} + +# returns username or identity display name, not escaped +sub display_name { + my $u = shift; + return $u->{'user'} unless $u->{'journaltype'} eq "I"; + + my $id = $u->identity; + return "[ERR:unknown_identity]" unless $id; + + my ($url, $name); + if ($id->[0] eq "O") { + require Net::OpenID::Consumer; + $url = $id->[1]; + $name = Net::OpenID::VerifiedIdentity::DisplayOfURL($url, $LJ::IS_DEV_SERVER); + # FIXME: make a good out of this + $name =~ s/\[(live|dead)journal\.com/\[${1}journal/; + } + elsif ($id->[0] eq "G") { + if ($id->[1] =~ /^http\:\/\/.*\.(.*)journal.*\/(.*)$/) { + $name = $2 . "\@" . substr($1, 0, 1) . "j"; + } + else { + $name = $id->[1]; + } + } + return $name; +} + +sub ljuser_display { + my $u = shift; + my $opts = shift; + + return LJ::ljuser($u, $opts) unless $u->{'journaltype'} eq "I"; + + my $id = $u->identity; + return "????" unless $id; + + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::IMGPREFIX; + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + + my ($url, $name); + + if ($id->[0] eq "O") { + $url = $id->[1]; + $name = $u->display_name; + + my $openid_icon; + if ($url =~ /http:\/\/.+\.livejournal.com\/$/ || + $url =~ /http:\/\/users.livejournal.com\/.+\/$/) { + $openid_icon = "userinfo-lj.gif"; + } + else { + $openid_icon = "openid-profile.gif"; + } + + + $url ||= "about:blank"; + $name ||= "[no_name]"; + + $url = LJ::ehtml($url); + $name = LJ::ehtml($name); + + return "[info]$name"; + + } + elsif ($id->[0] eq "G") { + $url = $id->[1]; + $name = $u->display_name; + + $url ||= "about:blank"; + $name ||= "[no_name]"; + + $url = LJ::ehtml($url); + $name = LJ::ehtml($name); + + return "[info]$name"; + } + else { + return "????"; + } +} + +sub load_identity_user { + my ($type, $ident, $vident) = @_; + + my $dbh = LJ::get_db_writer(); + my $uid = $dbh->selectrow_array("SELECT userid FROM identitymap WHERE idtype=? AND identity=?", + undef, $type, $ident); + return LJ::load_userid($uid) if $uid; + + # increment ext_ counter until we successfully create an LJ + # account. hard cap it at 10 tries. (arbitrary, but we really + # shouldn't have *any* failures here, let alone 10 in a row) + + for (1..10) { + my $extuser = 'ext_' . LJ::alloc_global_counter('E'); + + my $name = $extuser; + if ($type eq "O" && ref $vident) { + $name = $vident->display; + } + + $uid = LJ::create_account({ + caps => undef, + user => $extuser, + name => $name, + journaltype => 'I', + }); + last if $uid; + select undef, undef, undef, .10; # lets not thrash over this + } + return undef unless $uid && + $dbh->do("INSERT INTO identitymap (idtype, identity, userid) VALUES (?,?,?)", + undef, $type, $ident, $uid); + return LJ::load_userid($uid); +} + +package LJ; + +# +# name: LJ::get_authas_list +# des: Get a list of usernames a given user can authenticate as +# returns: an array of usernames +# args: u, opts? +# des-opts: Optional hashref. keys are: +# - type: 'P' to only return users of journaltype 'P' +# - cap: cap to filter users on +# +sub get_authas_list { + my ($u, $opts) = @_; + + # used to accept a user type, now accept an opts hash + $opts = { 'type' => $opts } unless ref $opts; + + # only one valid type right now + $opts->{'type'} = 'P' if $opts->{'type'}; + + my $ids = LJ::load_rel_target($u, 'A'); + return undef unless $ids; + + # load_userids_multiple + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } @$ids ], [$u]); + + return $u->{'user'}, sort map { $_->{'user'} } + grep { ! $opts->{'cap'} || LJ::get_cap($_, $opts->{'cap'}) } + grep { ! $opts->{'type'} || $opts->{'type'} eq $_->{'journaltype'} } + grep { $_->{clusterid} > 0 } + grep { $_->{statusvis} !~ /[XS]/ } + values %users; +} + +# +# name: LJ::can_view +# des: Checks to see if the remote user can view a given journal entry. +# Note: This is meant for use on single entries at a time, +# not for calling many times on every entry in a journal. +# returns: boolean; 1 if remote user can see item +# args: remote, item +# des-item: Hashref from the 'log' table. +# +sub can_view +{ + &nodb; + my $remote = shift; + my $item = shift; + + # public is okay + return 1 if $item->{'security'} eq "public"; + + # must be logged in otherwise + return 0 unless $remote; + + my $userid = int($item->{'ownerid'} || $item->{'journalid'}); + my $remoteid = int($remote->{'userid'}); + + # owners can always see their own. + return 1 if ($userid == $remoteid); + + # other people can't read private + return 0 if ($item->{'security'} eq "private"); + + # should be 'usemask' security from here out, otherwise + # assume it's something new and return 0 + return 0 unless ($item->{'security'} eq "usemask"); + + # if it's usemask, we have to refuse non-personal journals, + # so we have to load the user + return 0 unless + $remote->{'journaltype'} eq 'P' || + $remote->{'journaltype'} eq 'I'; + + # TAG:FR:ljlib:can_view (turn off bit 0 for just watching? hmm.) + my $gmask = LJ::get_groupmask($userid, $remoteid); + my $allowed = (int($gmask) & int($item->{'allowmask'})); + return $allowed ? 1 : 0; # no need to return matching mask +} + +# +# name: LJ::wipe_major_memcache +# des: invalidate all major memcache items associated with a given user +# args: u +# returns: nothing +# +sub wipe_major_memcache +{ + my $u = shift; + my $userid = LJ::want_userid($u); + foreach my $key ("userid","bio","talk2ct","talkleftct","log2ct", + "log2lt","memkwid","dayct","s1overr","s1uc","fgrp", + "friends","friendofs","tu","upicinf","upiccom", + "upicurl", "intids", "memct", "lastcomm") + { + LJ::memcache_kill($userid, $key); + } +} + +# +# name: LJ::load_user_props +# des: Given a user hashref, loads the values of the given named properties +# into that user hashref. +# args: dbarg?, u, opts?, propname* +# des-opts: hashref of opts. set key 'cache' to use memcache. +# des-propname: the name of a property from the userproplist table. +# +sub load_user_props +{ + &nodb; + + my $u = shift; + return unless isu($u); + return if $u->{'statusvis'} eq "X"; + + my $opts = ref $_[0] ? shift : {}; + my (@props) = @_; + + my ($sql, $sth); + LJ::load_props("user"); + + ## user reference + my $uid = $u->{'userid'}+0; + $uid = LJ::get_userid($u->{'user'}) unless $uid; + + my $mem = {}; + my $use_master = 0; + my $used_slave = 0; # set later if we ended up using a slave + + if (@LJ::MEMCACHE_SERVERS) { + my @keys; + foreach (@props) { + next if exists $u->{$_}; + my $p = LJ::get_prop("user", $_); + die "Invalid userprop $_ passed to LJ::load_user_props." unless $p; + push @keys, [$uid,"uprop:$uid:$p->{'id'}"]; + } + $mem = LJ::MemCache::get_multi(@keys) || {}; + $use_master = 1; + } + + $use_master = 1 if $opts->{'use_master'}; + + my @needwrite; # [propid, propname] entries we need to save to memcache later + + my %loadfrom; + my %multihomed; # ( $propid => 0/1 ) # 0 if we haven't loaded it, 1 if we have + unless (@props) { + # case 1: load all props for a given user. + # multihomed props are stored on userprop and userproplite2, but since they + # should always be in sync, it doesn't matter which gets loaded first, the + # net results should be the same. see doc/designnotes/multihomed_props.txt + # for more information. + $loadfrom{'userprop'} = 1; + $loadfrom{'userproplite'} = 1; + $loadfrom{'userproplite2'} = 1; + $loadfrom{'userpropblob'} = 1; + } else { + # case 2: load only certain things + foreach (@props) { + next if exists $u->{$_}; + my $p = LJ::get_prop("user", $_); + die "Invalid userprop $_ passed to LJ::load_user_props." unless $p; + if (defined $mem->{"uprop:$uid:$p->{'id'}"}) { + $u->{$_} = $mem->{"uprop:$uid:$p->{'id'}"}; + next; + } + push @needwrite, [ $p->{'id'}, $_ ]; + my $source = $p->{'indexed'} ? "userprop" : "userproplite"; + if ($p->{datatype} eq 'blobchar') { + $source = "userpropblob"; # clustered blob + } + elsif ($p->{'cldversion'} && $u->{'dversion'} >= $p->{'cldversion'}) { + $source = "userproplite2"; # clustered + } + elsif ($p->{multihomed}) { + $multihomed{$p->{id}} = 0; + $source = "userproplite2"; + } + push @{$loadfrom{$source}}, $p->{'id'}; + } + } + + foreach my $table (qw{userproplite userproplite2 userpropblob userprop}) { + next unless exists $loadfrom{$table}; + my $db; + if ($use_master) { + $db = ($table =~ m{userprop(lite2|blob)}) ? + LJ::get_cluster_master($u) : + LJ::get_db_writer(); + } + unless ($db) { + $db = ($table =~ m{userprop(lite2|blob)}) ? + LJ::get_cluster_reader($u) : + LJ::get_db_reader(); + $used_slave = 1; + } + $sql = "SELECT upropid, value FROM $table WHERE userid=$uid"; + if (ref $loadfrom{$table}) { + $sql .= " AND upropid IN (" . join(",", @{$loadfrom{$table}}) . ")"; + } + $sth = $db->prepare($sql); + $sth->execute; + while (my ($id, $v) = $sth->fetchrow_array) { + delete $multihomed{$id} if $table eq 'userproplite2'; + $u->{$LJ::CACHE_PROPID{'user'}->{$id}->{'name'}} = $v; + } + + # push back multihomed if necessary + if ($table eq 'userproplite2') { + push @{$loadfrom{userprop}}, $_ foreach keys %multihomed; + } + } + + # see if we failed to get anything above and need to hit the master. + # this usually happens the first time a multihomed prop is hit. this + # code will propogate that prop down to the cluster. + if (%multihomed) { + + # verify that we got the database handle before we try propogating data + if ($u->writer) { + my @values; + foreach my $id (keys %multihomed) { + my $pname = $LJ::CACHE_PROPID{user}{$id}{name}; + if (defined $u->{$pname} && $u->{$pname}) { + push @values, "($uid, $id, " . $u->quote($u->{$pname}) . ")"; + } else { + push @values, "($uid, $id, '')"; + } + } + $u->do("REPLACE INTO userproplite2 VALUES " . join ',', @values); + } + } + + # Add defaults to user object. + + # defaults for S1 style IDs in config file are magic: really + # uniq strings representing style IDs, so on first use, we need + # to map them + unless ($LJ::CACHED_S1IDMAP) { + + my $pubsty = LJ::S1::get_public_styles(); + foreach (values %$pubsty) { + my $k = "s1_$_->{'type'}_style"; + next unless $LJ::USERPROP_DEF{$k} eq "$_->{'type'}/$_->{'styledes'}"; + + $LJ::USERPROP_DEF{$k} = $_->{'styleid'}; + } + + $LJ::CACHED_S1IDMAP = 1; + } + + # If this was called with no @props, then the function tried + # to load all metadata. but we don't know what's missing, so + # try to apply all defaults. + unless (@props) { @props = keys %LJ::USERPROP_DEF; } + + foreach my $prop (@props) { + next if (defined $u->{$prop}); + $u->{$prop} = $LJ::USERPROP_DEF{$prop}; + } + + unless ($used_slave) { + foreach my $wr (@needwrite) { + my ($id, $name) = ($wr->[0], $wr->[1]); + LJ::MemCache::set([$uid,"uprop:$uid:$id"], $u->{$name} || ""); + } + } +} + +# simple interface to LJ::load_userids_multiple. takes userids, +# returns hashref with keys ids, values $u refs. +sub load_userids +{ + my %u; + LJ::load_userids_multiple([ map { $_ => \$u{$_} } @_ ]); + return \%u; +} + +# +# name: LJ::load_userids_multiple +# des: Loads a number of users at once, efficiently. +# info: loads a few users at once, their userids given in the keys of $map +# listref (not hashref: can't have dups). values of $map listref are +# scalar refs to put result in. $have is an optional listref of user +# object caller already has, but is too lazy to sort by themselves. +# args: dbarg?, map, have, memcache_only? +# des-map: Arrayref of pairs (userid, destination scalarref) +# des-have: Arrayref of user objects caller already has +# des-memcache_only: Flag to only retrieve data from memcache +# returns: Nothing. +# +sub load_userids_multiple +{ + &nodb; + my ($map, $have, $memcache_only) = @_; + + my $sth; + + my %need; + while (@$map) { + my $id = shift @$map; + my $ref = shift @$map; + next unless int($id); + push @{$need{$id}}, $ref; + + if ($LJ::REQ_CACHE_USER_ID{$id}) { + push @{$have}, $LJ::REQ_CACHE_USER_ID{$id}; + } + } + + my $satisfy = sub { + my $u = shift; + next unless ref $u eq "LJ::User"; + foreach (@{$need{$u->{'userid'}}}) { + $$_ = $u; + } + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + delete $need{$u->{'userid'}}; + }; + + if ($have) { + foreach my $u (@$have) { + $satisfy->($u); + } + } + + if (keys %need) { + foreach (LJ::memcache_get_u(map { [$_,"userid:$_"] } keys %need)) { + $satisfy->($_); + } + } + + if (keys %need && ! $memcache_only) { + my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + _load_user_raw($db, "userid", [ keys %need ], sub { + my $u = shift; + LJ::memcache_set_u($u); + $satisfy->($u); + }); + } +} + +# des-db: $dbh/$dbr +# des-key: either "userid" or "user" (the WHERE part) +# des-vals: value or arrayref of values for key to match on +# des-hoook: optional code ref to run for each $u +# returns: last $u found +sub _load_user_raw +{ + my ($db, $key, $vals, $hook) = @_; + $hook ||= sub {}; + $vals = [ $vals ] unless ref $vals eq "ARRAY"; + + if (!$db) { + warn("_load_user_raw: database is not available"); + return 0; + } + + my $use_isam; + unless ($LJ::CACHE_NO_ISAM{user} || scalar(@$vals) > 10) { + eval { $db->do("HANDLER user OPEN"); }; + if ($@ || $db->err) { + $LJ::CACHE_NO_ISAM{user} = 1; + } else { + $use_isam = 1; + } + } + + my $last; + + if ($use_isam) { + $key = "PRIMARY" if $key eq "userid"; + foreach my $v (@$vals) { + my $sth = $db->prepare("HANDLER user READ `$key` = (?) LIMIT 1"); + $sth->execute($v); + my $u = $sth->fetchrow_hashref; + if ($u) { + bless $u, 'LJ::User'; + $hook->($u); + $last = $u; + } + } + $db->do("HANDLER user close"); + } else { + my $in = join(", ", map { $db->quote($_) } @$vals); + my $sth = $db->prepare("SELECT * FROM user WHERE $key IN ($in)"); + $sth->execute; + while (my $u = $sth->fetchrow_hashref) { + bless $u, 'LJ::User'; + $hook->($u); + $last = $u; + } + } + + return $last; +} + +# +# name: LJ::load_user +# des: Loads a user record given a username. +# info: From the [dbarg[user]] table. +# args: dbarg?, user, force? +# des-user: Username of user to load. +# des-force: if set to true, won't return cached user object and will +# query a dbh +# returns: Hashref with keys being columns of [dbtable[user]] table. +# +sub load_user +{ + &nodb; + my ($user, $force) = @_; + + $user = LJ::canonical_username($user); + return undef unless length $user; + + my $set_req_cache = sub { + my $u = shift; + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + return $u; + }; + + my $get_user = sub { + my $use_dbh = shift; + my $db = $use_dbh ? LJ::get_db_writer() : LJ::get_db_reader(); + my $u = _load_user_raw($db, "user", $user); + return $u unless $u && $use_dbh; + + # set caches since we got a u from the master + LJ::memcache_set_u($u); + return $set_req_cache->($u); + }; + + # caller is forcing a master, return now + return $get_user->("master") if $force; + + my $u; + + # return process cache if we have one + $u = $LJ::REQ_CACHE_USER_NAME{$user}; + return $u if $u; + + # check memcache + { + my $uid = LJ::MemCache::get("uidof:$user"); + $u = LJ::memcache_get_u([$uid, "userid:$uid"]) if $uid; + return $set_req_cache->($u) if $u; + } + + # try to load from master if using memcache, otherwise from slave + $u = $get_user->(scalar @LJ::MEMCACHE_SERVERS); + return $u if $u; + + # setup LDAP handler if this is the first time + if ($LJ::LDAP_HOST && ! $LJ::AUTH_EXISTS) { + require LJ::LDAP; + $LJ::AUTH_EXISTS = sub { + my $user = shift; + my $rec = LJ::LDAP::load_ldap_user($user); + return $rec ? $rec : undef; + }; + } + + # if user doesn't exist in the LJ database, it's possible we're using + # an external authentication source and we should create the account + # implicitly. + my $lu; + if (ref $LJ::AUTH_EXISTS eq "CODE" && ($lu = $LJ::AUTH_EXISTS->($user))) + { + my $name = ref $lu eq "HASH" ? ($lu->{'nick'} || $lu->{name} || $user) : $user; + if (LJ::create_account({ + 'user' => $user, + 'name' => $name, + 'email' => ref $lu eq "HASH" ? $lu->{email} : "", + 'password' => "", + })) + { + # this should pull from the master, since it was _just_ created + return $get_user->("master"); + } + } + + return undef; +} + +# +# name: LJ::u_equals +# des: Compares two user objects to see if they're the same user. +# args: userobj1, userobj2 +# des-userobj1: First user to compare. +# des-userobj2: Second user to compare. +# returns: Boolean, true if userobj1 and userobj2 are defined and have equal userids. +# +sub u_equals { + my ($u1, $u2) = @_; + return $u1 && $u2 && $u1->{'userid'} == $u2->{'userid'}; +} + +# +# name: LJ::load_userid +# des: Loads a user record given a userid. +# info: From the [dbarg[user]] table. +# args: dbarg?, userid, force? +# des-userid: Userid of user to load. +# des-force: if set to true, won't return cached user object and will +# query a dbh +# returns: Hashref with keys being columns of [dbtable[user]] table. +# +sub load_userid +{ + &nodb; + my ($userid, $force) = @_; + return undef unless $userid; + + my $set_req_cache = sub { + my $u = shift; + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + return $u; + }; + + my $get_user = sub { + my $use_dbh = shift; + my $db = $use_dbh ? LJ::get_db_writer() : LJ::get_db_reader(); + my $u = _load_user_raw($db, "userid", $userid); + return $u unless $u && $use_dbh; + + # set caches since we got a u from the master + LJ::memcache_set_u($u); + return $set_req_cache->($u); + }; + + # user is forcing master, return now + return $get_user->("master") if $force; + + my $u; + + # check process cache + $u = $LJ::REQ_CACHE_USER_ID{$userid}; + return $u if $u; + + # check memcache + $u = LJ::memcache_get_u([$userid,"userid:$userid"]); + return $set_req_cache->($u) if $u; + + # get from master if using memcache + return $get_user->("master") if @LJ::MEMCACHE_SERVERS; + + # check slave + $u = $get_user->(); + return $u if $u; + + # if we didn't get a u from the reader, fall back to master + return $get_user->("master"); +} + +sub memcache_get_u +{ + my @keys = @_; + my @ret; + foreach my $ar (values %{LJ::MemCache::get_multi(@keys) || {}}) { + my $u = LJ::MemCache::array_to_hash("user", $ar); + if ($u) { + bless $u, 'LJ::User'; + push @ret, $u; + } + } + return wantarray ? @ret : $ret[0]; +} + +sub memcache_set_u +{ + my $u = shift; + return unless $u; + my $ar = LJ::MemCache::hash_to_array("user", $u); + return unless $ar; + LJ::MemCache::set([$u->{'userid'}, "userid:$u->{'userid'}"], $ar); + LJ::MemCache::set("uidof:$u->{user}", $u->{userid}); +} + +# +# name: LJ::get_bio +# des: gets a user bio, from db or memcache +# args: u, force +# des-force: true to get data from cluster master +# returns: string +# +sub get_bio { + my ($u, $force) = @_; + return unless $u && $u->{'has_bio'} eq "Y"; + + my $bio; + + my $memkey = [$u->{'userid'}, "bio:$u->{'userid'}"]; + unless ($force) { + my $bio = LJ::MemCache::get($memkey); + return $bio if defined $bio; + } + + # not in memcache, fall back to disk + my $db = @LJ::MEMCACHE_SERVERS || $force ? + LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + $bio = $db->selectrow_array("SELECT bio FROM userbio WHERE userid=?", + undef, $u->{'userid'}); + + # set in memcache + LJ::MemCache::add($memkey, $bio); + + return $bio; +} + +# +# name: LJ::journal_base +# des: Returns URL of a user's journal. +# info: The tricky thing is that users with underscores in their usernames +# can't have some_user.site.com as a hostname, so that's changed into +# some-user.site.com. +# args: uuser, vhost? +# des-uuser: User hashref or username of user whose URL to make. +# des-vhost: What type of URL. Acceptable options are "users", to make a +# http://user.site.com/ URL; "tilde" to make http://site.com/~user/; +# "community" for http://site.com/community/user; or the default +# will be http://site.com/users/user. If unspecifed and uuser +# is a user hashref, then the best/preferred vhost will be chosen. +# returns: scalar; a URL. +# +sub journal_base +{ + my ($user, $vhost) = @_; + if (isu($user)) { + my $u = $user; + $user = $u->{'user'}; + unless (defined $vhost) { + if (($LJ::FRONTPAGE_JOURNAL) && $LJ::FRONTPAGE_JOURNAL eq $user) { + $vhost = "front"; + } elsif ($u->{'journaltype'} eq "P") { + $vhost = ""; + } elsif ($u->{'journaltype'} eq "C") { + $vhost = "community"; + } + + } + } + if ($vhost eq "users") { + my $he_user = $user; + $he_user =~ s/_/-/g; + return "http://$he_user.$LJ::USER_DOMAIN"; + } elsif ($vhost eq "tilde") { + return "$LJ::SITEROOT/~$user"; + } elsif ($vhost eq "community") { + return "$LJ::SITEROOT/community/$user"; + } elsif ($vhost eq "front") { + return $LJ::SITEROOT; + } elsif ($vhost =~ /^other:(.+)/) { + return "http://$1"; + } else { + return "$LJ::SITEROOT/users/$user"; + } +} + + +# loads all of the given privs for a given user into a hashref +# inside the user record ($u->{_privs}->{$priv}->{$arg} = 1) +# +# name: LJ::load_user_privs +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub load_user_privs +{ + &nodb; + my $remote = shift; + my @privs = @_; + return unless $remote and @privs; + + # return if we've already loaded these privs for this user. + @privs = grep { ! $remote->{'_privloaded'}->{$_} } @privs; + return unless @privs; + + my $dbr = LJ::get_db_reader(); + return unless $dbr; + foreach (@privs) { $remote->{'_privloaded'}->{$_}++; } + @privs = map { $dbr->quote($_) } @privs; + my $sth = $dbr->prepare("SELECT pl.privcode, pm.arg ". + "FROM priv_map pm, priv_list pl ". + "WHERE pm.prlid=pl.prlid AND ". + "pl.privcode IN (" . join(',',@privs) . ") ". + "AND pm.userid=$remote->{'userid'}"); + $sth->execute; + while (my ($priv, $arg) = $sth->fetchrow_array) { + unless (defined $arg) { $arg = ""; } # NULL -> "" + $remote->{'_priv'}->{$priv}->{$arg} = 1; + } +} + +# +# name: LJ::check_priv +# des: Check to see if a user has a certain privilege. +# info: Usually this is used to check the privs of a $remote user. +# See [func[LJ::get_remote]]. As such, a $u argument of undef +# is okay to pass: 0 will be returned, as an unknown user can't +# have any rights. +# args: dbarg?, u, priv, arg? +# des-priv: Priv name to check for (see [dbtable[priv_list]]) +# des-arg: Optional argument. If defined, function only returns true +# when $remote has a priv of type $priv also with arg $arg, not +# just any priv of type $priv, which is the behavior without +# an $arg +# returns: boolean; true if user has privilege +# +sub check_priv +{ + &nodb; + my ($u, $priv, $arg) = @_; + return 0 unless $u; + + if (! $u->{'_privloaded'}->{$priv}) { + LJ::load_user_privs($u, $priv); + } + + if (defined $arg) { + return (defined $u->{'_priv'}->{$priv} && + defined $u->{'_priv'}->{$priv}->{$arg}); + } else { + return (defined $u->{'_priv'}->{$priv}); + } +} + +# +# +# +# name: LJ::remote_has_priv +# class: +# des: Check to see if the given remote user has a certain priviledge +# info: DEPRECATED. should use load_user_privs + check_priv +# args: +# des-: +# returns: +# +sub remote_has_priv +{ + &nodb; + my $remote = shift; + my $privcode = shift; # required. priv code to check for. + my $ref = shift; # optional, arrayref or hashref to populate + return 0 unless ($remote); + + ### authentication done. time to authorize... + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT pm.arg FROM priv_map pm, priv_list pl WHERE pm.prlid=pl.prlid AND pl.privcode=? AND pm.userid=?"); + $sth->execute($privcode, $remote->{'userid'}); + + my $match = 0; + if (ref $ref eq "ARRAY") { @$ref = (); } + if (ref $ref eq "HASH") { %$ref = (); } + while (my ($arg) = $sth->fetchrow_array) { + $match++; + if (ref $ref eq "ARRAY") { push @$ref, $arg; } + if (ref $ref eq "HASH") { $ref->{$arg} = 1; } + } + return $match; +} + +# $dom: 'L' == log, 'T' == talk, 'M' == modlog, 'S' == session, +# 'R' == memory (remembrance), 'K' == keyword id, +# 'P' == phone post, 'C' == pending comment +sub alloc_user_counter +{ + my ($u, $dom, $recurse) = @_; + + ################################################################## + # IF YOU UPDATE THIS MAKE SURE YOU ADD INITIALIZATION CODE BELOW # + return undef unless $dom =~ /^[LTMPSRKCD]$/; # + ################################################################## + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + my $newmax; + my $uid = $u->{'userid'}+0; + return undef unless $uid; + my $memkey = [$uid, "auc:$uid:$dom"]; + + # in a master-master DB cluster we need to be careful that in + # an automatic failover case where one cluster is slightly behind + # that the same counter ID isn't handed out twice. use memcache + # as a sanity check to record/check latest number handed out. + my $memmax = int(LJ::MemCache::get($memkey) || 0); + + my $rs = $dbh->do("UPDATE usercounter SET max=LAST_INSERT_ID(GREATEST(max,$memmax)+1) ". + "WHERE journalid=? AND area=?", undef, $uid, $dom); + if ($rs > 0) { + $newmax = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + LJ::MemCache::set($memkey, $newmax); + return $newmax; + } + + if ($recurse) { + # We shouldn't ever get here if all is right with the world. + return undef; + } + + my $qry_map = { + # for entries: + 'log' => "SELECT MAX(jitemid) FROM log2 WHERE journalid=?", + 'logtext' => "SELECT MAX(jitemid) FROM logtext2 WHERE journalid=?", + 'talk_nodeid' => "SELECT MAX(nodeid) FROM talk2 WHERE nodetype='L' AND journalid=?", + # for comments: + 'talk' => "SELECT MAX(jtalkid) FROM talk2 WHERE journalid=?", + 'talktext' => "SELECT MAX(jtalkid) FROM talktext2 WHERE journalid=?", + }; + + my $consider = sub { + my @tables = @_; + foreach my $t (@tables) { + my $res = $u->selectrow_array($qry_map->{$t}, undef, $uid); + $newmax = $res if ($res) && $res > $newmax; + } + }; + + # Make sure the counter table is populated for this uid/dom. + if ($dom eq "L") { + # back in the ol' days IDs were reused (because of MyISAM) + # so now we're extra careful not to reuse a number that has + # foreign junk "attached". turns out people like to delete + # each entry by hand, but we do lazy deletes that are often + # too lazy and a user can see old stuff come back alive + $consider->("log", "logtext", "talk_nodeid"); + } elsif ($dom eq "T") { + # just paranoia, not as bad as above. don't think we've ever + # run into cases of talktext without a talk, but who knows. + # can't hurt. + $consider->("talk", "talktext"); + } elsif ($dom eq "M") { + $newmax = $u->selectrow_array("SELECT MAX(modid) FROM modlog WHERE journalid=?", + undef, $uid); + } elsif ($dom eq "S") { + $newmax = $u->selectrow_array("SELECT MAX(sessid) FROM sessions WHERE userid=?", + undef, $uid); + } elsif ($dom eq "R") { + $newmax = $u->selectrow_array("SELECT MAX(memid) FROM memorable2 WHERE userid=?", + undef, $uid); + } elsif ($dom eq "K") { + $newmax = $u->selectrow_array("SELECT MAX(kwid) FROM userkeywords WHERE userid=?", + undef, $uid); + } elsif ($dom eq "P") { + my $userblobmax = $u->selectrow_array("SELECT MAX(blobid) FROM userblob WHERE journalid=? AND domain=?", + undef, $uid, LJ::get_blob_domainid("phonepost")); + my $ppemax = $u->selectrow_array("SELECT MAX(blobid) FROM phonepostentry WHERE userid=?", + undef, $uid); + $newmax = ($ppemax > $userblobmax) ? $ppemax : $userblobmax; + } elsif ($dom eq "C") { + my $commentmax = $u->selectrow_array("SELECT MAX(pendid) FROM pendcomments WHERE jid=?", + undef, $uid); + } elsif ($dom eq "D") { + $newmax = $u->selectrow_array("SELECT MAX(moduleid) FROM embedcontent WHERE userid=?", + undef, $uid); + } else { + die "No user counter initializer defined for area '$dom'.\n"; + } + $newmax += 0; + $dbh->do("INSERT IGNORE INTO usercounter (journalid, area, max) VALUES (?,?,?)", + undef, $uid, $dom, $newmax) or return undef; + + # The 2nd invocation of the alloc_user_counter sub should do the + # intended incrementing. + return LJ::alloc_user_counter($u, $dom, 1); +} + +# +# name: LJ::make_user_active +# des: Record user activity per cluster to +# make per-activity cluster stats easier. +# args: userobj, type +# arg-userid: source userobj ref +# arg-type: currently unused +# +sub mark_user_active { + my ($u, $type) = @_; # not currently using type + return 0 unless $u; # do not auto-vivify $u + my $uid = $u->{userid}; + return 0 unless $uid && $u->{clusterid}; + + # Update the clustertrack table, but not if we've done it for this + # user in the last hour. if no memcache servers are configured + # we don't do the optimization and just always log the activity info + if (@LJ::MEMCACHE_SERVERS == 0 || + LJ::MemCache::add("rate:tracked:$uid", 1, 3600)) { + + return 0 unless $u->writer; + $u->do("REPLACE INTO clustertrack2 SET ". + "userid=?, timeactive=?, clusterid=?", undef, + $uid, time(), $u->{clusterid}) or return 0; + } + return 1; +} + +# +# name: LJ::infohistory_add +# des: Add a line of text to the infohistory table for an account. +# args: uuid, what, value, other? +# des-uuid: User id or user object to insert infohistory for. +# des-what: What type of history being inserted (15 chars max). +# des-value: Value for the item (255 chars max). +# des-other: Extra information (30 chars max). +# returns: 1 on success, 0 on error. +# +sub infohistory_add { + my ($uuid, $what, $value, $other) = @_; + $uuid = LJ::want_userid($uuid); + return unless $uuid && $what && $value; + + # get writer and insert + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO infohistory (userid, what, timechange, oldvalue, other) VALUES (?, ?, NOW(), ?, ?)", + undef, $uuid, $what, $value, $other); + return $dbh->err ? 0 : 1; +} + +# +# name: LJ::set_userprop +# des: Sets/deletes a userprop by name for a user. +# info: This adds or deletes from the +# [dbtable[userprop]]/[dbtable[userproplite]] tables. One +# crappy thing about this interface is that it doesn't allow +# a batch of userprops to be updated at once, which is the +# common thing to do. +# args: dbarg?, uuserid, propname, value, memonly? +# des-uuserid: The userid of the user or a user hashref. +# des-propname: The name of the property. Or a hashref of propname keys and corresponding values. +# des-value: The value to set to the property. If undefined or the +# empty string, then property is deleted. +# des-memonly: if true, only writes to memcache, and not to database. +# +sub set_userprop +{ + &nodb; + + my ($u, $propname, $value, $memonly) = @_; + $u = ref $u ? $u : LJ::load_userid($u); + my $userid = $u->{'userid'}+0; + + my $hash = ref $propname eq "HASH" ? $propname : { $propname => $value }; + + my %action; # $table -> {"replace"|"delete"} -> [ "($userid, $propid, $qvalue)" | propid ] + my %multihomed; # { $propid => $value } + + foreach $propname (keys %$hash) { + my $p = LJ::get_prop("user", $propname) or + die "Invalid userprop $propname passed to LJ::set_userprop."; + if ($p->{multihomed}) { + # collect into array for later handling + $multihomed{$p->{id}} = $hash->{$propname}; + next; + } + my $table = $p->{'indexed'} ? "userprop" : "userproplite"; + if ($p->{datatype} eq 'blobchar') { + $table = 'userpropblob'; + } + elsif ($p->{'cldversion'} && $u->{'dversion'} >= $p->{'cldversion'}) { + $table = "userproplite2"; + } + unless ($memonly) { + my $db = $action{$table}->{'db'} ||= ( + $table !~ m{userprop(lite2|blob)} + ? LJ::get_db_writer() + : $u->writer ); + return 0 unless $db; + } + $value = $hash->{$propname}; + if (defined $value && $value) { + push @{$action{$table}->{"replace"}}, [ $p->{'id'}, $value ]; + } else { + push @{$action{$table}->{"delete"}}, $p->{'id'}; + } + } + + foreach my $table (keys %action) { + my $db = $action{$table}->{'db'}; + if (my $list = $action{$table}->{"replace"}) { + if ($db) { + my $vals = join(',', map { "($userid,$_->[0]," . $db->quote($_->[1]) . ")" } @$list); + $db->do("REPLACE INTO $table (userid, upropid, value) VALUES $vals"); + } + LJ::MemCache::set([$userid,"uprop:$userid:$_->[0]"], $_->[1]) foreach (@$list); + } + if (my $list = $action{$table}->{"delete"}) { + if ($db) { + my $in = join(',', @$list); + $db->do("DELETE FROM $table WHERE userid=$userid AND upropid IN ($in)"); + } + LJ::MemCache::set([$userid,"uprop:$userid:$_"], "") foreach (@$list); + } + } + + # if we had any multihomed props, set them here + if (%multihomed) { + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + while (my ($propid, $pvalue) = each %multihomed) { + if (defined $pvalue && $pvalue) { + # replace data into master + $dbh->do("REPLACE INTO userprop VALUES (?, ?, ?)", + undef, $userid, $propid, $pvalue); + } else { + # delete data from master, but keep in cluster + $dbh->do("DELETE FROM userprop WHERE userid = ? AND upropid = ?", + undef, $userid, $propid); + } + + # fail out? + return 0 if $dbh->err; + + # put data in cluster + $pvalue ||= ''; + $u->do("REPLACE INTO userproplite2 VALUES (?, ?, ?)", + undef, $userid, $propid, $pvalue); + return 0 if $u->err; + + # set memcache + LJ::MemCache::set([$userid,"uprop:$userid:$propid"], $pvalue); + } + } + + return 1; +} + +# +# name: LJ::get_shared_journals +# des: Gets an array of shared journals a user has access to. +# returns: An array of shared journals. +# args: u +# +sub get_shared_journals +{ + my $u = shift; + my $ids = LJ::load_rel_target($u, 'A') || []; + + # have to get usernames; + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } @$ids ], [$u]); + return sort map { $_->{'user'} } values %users; +} + +# +# class: component +# name: LJ::ljuser +# des: Make link to userinfo/journal of user. +# info: Returns the HTML for a userinfo/journal link pair for a given user +# name, just like LJUSER does in BML. This is for files like cleanhtml.pl +# and ljpoll.pl which need this functionality too, but they aren't run as BML. +# args: user, opts? +# des-user: Username to link to, or user hashref. +# des-opts: Optional hashref to control output. Key 'full' when true causes +# a link to the mode=full userinfo. Key 'type' when 'C' makes +# a community link, when 'Y' makes a syndicated account link, +# when 'N' makes a news account link, otherwise makes a user account +# link. If user parameter is a hashref, its 'journaltype' overrides +# this 'type'. Key 'del', when true, makes a tag for a deleted user. +# If user parameter is a hashref, its 'statusvis' overrides 'del'. +# Key 'no_follow', when true, disables traversal of renamed users. +# Key 'side' for LJ-based server control +# returns: HTML with a little head image & bold text link. +# +sub ljuser +{ + my $user = shift; + my $opts = shift; + my $u; + my $native=1; + + if ($opts->{'side'}){ + if ($opts->{'side'} eq 'LJR') {$native=1; $opts->{'side'}="lj.rossia.org"} + elsif ($opts->{'side'} eq 'lj.rossia.org') {$native=1;} + elsif ($opts->{'side'} eq 'LJCOM') { $opts->{'side'}="www.livejournal.com"; $native=0;} + elsif ($opts->{'side'} eq 'LJ') { $opts->{'side'}="www.livejournal.com"; $native=0;} + else {$native=0;} + } + if ($native){ + my $do_dynamic = $LJ::DYNAMIC_LJUSER || ($user =~ /^ext_/); + if ($do_dynamic && ! isu($user) && ! $opts->{'type'}) { + # Try to automatically pick the user type, but still + # make something if we can't (user doesn't exist?) + $user = LJ::load_user($user) || $user; + + my $hops = 0; + + # Traverse the renames to the final journal + while (ref $user and $user->{'journaltype'} eq 'R' + and ! $opts->{'no_follow'} && $hops++ < 5) { + + LJ::load_user_props($user, 'renamedto'); + last unless length $user->{'renamedto'}; + $user = LJ::load_user($user->{'renamedto'}); + + } + } + + if (isu($user)) { + $u = $user; + $opts->{'type'} = $user->{'journaltype'}; + # Mark accounts as deleted that aren't visible, memorial, or locked + $opts->{'del'} = $user->{'statusvis'} ne 'V' && + $user->{'statusvis'} ne 'M' && + $user->{'statusvis'} ne 'L'; + $user = $user->{'user'}; + } + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::IMGPREFIX; + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + my $make_tag = sub { + my ($fil, $dir, $x, $y) = @_; + $y ||= $x; # make square if only one dimension given + + return "[info]$user"; + }; + $u = LJ::load_user($user); + $opts->{'type'} = $u->{'journaltype'}; + + if ($opts->{'type'} eq 'C') { + return $make_tag->('community.gif', 'community', 16); + } elsif ($opts->{'type'} eq 'Y') { + return $make_tag->('syndicated.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'N') { + return $make_tag->('newsinfo.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'I') { + return $u->ljuser_display($opts); + } else { + return $make_tag->('userinfo.gif', 'users', 17); + } + } else { + #we have non-native side + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::SITEROOT."/".$LJ::IMGPREFIX; + if ($opts->{'side'} eq "www.livejournal.com") {$img="http://stat.livejournal.com/img/"} + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + my $make_tag = sub { + my ($s, $fil, $dir, $x, $y) = @_; + $y ||= $x; # make square if only one dimension given + + return "[info]$user"; + }; + + if ($opts->{'type'} eq 'C') { + return $make_tag->( $opts->{'side'}, 'community.gif', 'community', 16); + } elsif ($opts->{'type'} eq 'Y') { + return $make_tag->( $opts->{'side'}, 'syndicated.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'N') { + return $make_tag->( $opts->{'side'}, 'newsinfo.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'I') { + return $u->ljuser_display($opts); + } else { + return $make_tag->( $opts->{'side'}, 'userinfo.gif', 'users', 17); + } + + } +} + +sub update_user +{ + my ($arg, $ref) = @_; + my @uid; + + if (ref $arg eq "ARRAY") { + @uid = @$arg; + } else { + @uid = want_userid($arg); + } + @uid = grep { $_ } map { $_ + 0 } @uid; + return 0 unless @uid; + + my @sets; + my @bindparams; + while (my ($k, $v) = each %$ref) { + if ($k eq "raw") { + push @sets, $v; + } else { + push @sets, "$k=?"; + push @bindparams, $v; + } + } + return 1 unless @sets; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + { + local $" = ","; + my $where = @uid == 1 ? "userid=$uid[0]" : "userid IN (@uid)"; + $dbh->do("UPDATE user SET @sets WHERE $where", undef, + @bindparams); + return 0 if $dbh->err; + } + if (@LJ::MEMCACHE_SERVERS) { + LJ::memcache_kill($_, "userid") foreach @uid; + } + return 1; +} + +# +# name: LJ::get_timezone +# des: Gets the timezone offset for the user. +# args: u, offsetref, fakedref +# des-u: user object. +# des-offsetref: reference to scalar to hold timezone offset; +# des-fakedref: reference to scalar to hold whether this timezone was +# faked. 0 if it is the timezone specified by the user (not supported yet). +# returns: nonzero if successful. +# +sub get_timezone { + my ($u, $offsetref, $fakedref) = @_; + + # we currently don't support timezones, + # but when we do this will be the function to modify. + + my $offset; + + my $dbcr = LJ::get_cluster_def_reader($u); + return 0 unless $dbcr; + + # we guess their current timezone's offset + # by comparing the gmtime of their last post + # with the time they specified on that post. + + # grab the times on the last post. + if (my $last_row = $dbcr->selectrow_hashref( + "SELECT rlogtime, eventtime ". + "FROM log2 WHERE journalid=? ". + "ORDER BY rlogtime LIMIT 1", + undef, $u->{userid})) { + my $logtime = $LJ::EndOfTime - $last_row->{'rlogtime'}; + my $eventtime = LJ::mysqldate_to_time($last_row->{'eventtime'}, 1); + my $hourdiff = ($eventtime - $logtime) / 3600; + + # if they're up to a quarter hour behind, round up. + $$offsetref = $hourdiff > 0 ? int($hourdiff + 0.25) : int($hourdiff - 0.25); + } + + # until we store real timezones, the timezone is always faked. + $$fakedref = 1 if $fakedref; + + return 1; +} + +# returns undef on error, or otherwise arrayref of arrayrefs, +# each of format [ year, month, day, count ] for all days with +# non-zero count. examples: +# [ [ 2003, 6, 5, 3 ], [ 2003, 6, 8, 4 ], ... ] +# +sub get_daycounts +{ + my ($u, $remote, $not_memcache) = @_; + # NOTE: $remote not yet used. one of the oldest LJ shortcomings is that + # it's public how many entries users have per-day, even if the entries + # are protected. we'll be fixing that with a new table, but first + # we're moving everything to this API. + + my $uid = LJ::want_userid($u) or return undef; + + my @days; + my $memkey = [$uid,"dayct:$uid"]; + unless ($not_memcache) { + my $list = LJ::MemCache::get($memkey); + return $list if $list; + } + + my $dbcr = LJ::get_cluster_def_reader($u) or return undef; + my $sth = $dbcr->prepare("SELECT year, month, day, COUNT(*) ". + "FROM log2 WHERE journalid=? GROUP BY 1, 2, 3"); + $sth->execute($uid); + while (my ($y, $m, $d, $c) = $sth->fetchrow_array) { + # we force each number from string scalars (from DBI) to int scalars, + # so they store smaller in memcache + push @days, [ int($y), int($m), int($d), int($c) ]; + } + LJ::MemCache::add($memkey, \@days); + return \@days; +} + +# +# name: LJ::modify_caps +# des: Given a list of caps to add and caps to remove, updates a user's caps +# args: uuid, cap_add, cap_del, res +# arg-cap_add: arrayref of bit numbers to turn on +# arg-cap_del: arrayref of bit numbers to turn off +# arg-res: hashref returned from 'modify_caps' hook +# returns: updated u object, retrieved from $dbh, then 'caps' key modified +# otherwise, returns 0 unless all hooks run properly +# +sub modify_caps { + my ($argu, $cap_add, $cap_del, $res) = @_; + my $userid = LJ::want_userid($argu); + return undef unless $userid; + + $cap_add ||= []; + $cap_del ||= []; + my %cap_add_mod = (); + my %cap_del_mod = (); + + # convert capnames to bit numbers + if (LJ::are_hooks("get_cap_bit")) { + foreach my $bit (@$cap_add, @$cap_del) { + next if $bit =~ /^\d+$/; + + # bit is a magical reference into the array + $bit = LJ::run_hook("get_cap_bit", $bit); + } + } + + # get a u object directly from the db + my $u = LJ::load_userid($userid, "force"); + + # add new caps + my $newcaps = int($u->{'caps'}); + foreach (@$cap_add) { + my $cap = 1 << $_; + + # about to turn bit on, is currently off? + $cap_add_mod{$_} = 1 unless $newcaps & $cap; + $newcaps |= $cap; + } + + # remove deleted caps + foreach (@$cap_del) { + my $cap = 1 << $_; + + # about to turn bit off, is it currently on? + $cap_del_mod{$_} = 1 if $newcaps & $cap; + $newcaps &= ~$cap; + } + + # run hooks for modified bits + if (LJ::are_hooks("modify_caps")) { + $res = LJ::run_hook("modify_caps", + { 'u' => $u, + 'newcaps' => $newcaps, + 'oldcaps' => $u->{'caps'}, + 'cap_on_req' => { map { $_ => 1 } @$cap_add }, + 'cap_off_req' => { map { $_ => 1 } @$cap_del }, + 'cap_on_mod' => \%cap_add_mod, + 'cap_off_mod' => \%cap_del_mod, + }); + + # hook should return a status code + return undef unless defined $res; + } + + # update user row + LJ::update_user($u, { 'caps' => $newcaps }); + + return $u; +} + +# returns 1 if action is permitted. 0 if above rate or fail. +# action isn't logged on fail. +# +# opts keys: +# -- "limit_by_ip" => "1.2.3.4" (when used for checking rate) +# -- +sub rate_log +{ + my ($u, $ratename, $count, $opts) = @_; + my $rateperiod = LJ::get_cap($u, "rateperiod-$ratename"); + return 1 unless $rateperiod; + + return 0 unless $u->writer; + + my $rp = LJ::get_prop("rate", $ratename); + return 0 unless $rp; + + my $now = time(); + my $beforeperiod = $now - $rateperiod; + + # delete inapplicable stuff (or some of it) + $u->do("DELETE FROM ratelog WHERE userid=$u->{'userid'} AND rlid=$rp->{'id'} ". + "AND evttime < $beforeperiod LIMIT 1000"); + + # check rate. (okay per period) + my $opp = LJ::get_cap($u, "rateallowed-$ratename"); + return 1 unless $opp; + my $udbr = LJ::get_cluster_reader($u); + my $ip = $udbr->quote($opts->{'limit_by_ip'} || "0.0.0.0"); + my $sum = $udbr->selectrow_array("SELECT COUNT(quantity) FROM ratelog WHERE ". + "userid=$u->{'userid'} AND rlid=$rp->{'id'} ". + "AND ip=INET_ATON($ip) ". + "AND evttime > $beforeperiod"); + + # would this transaction go over the limit? + if ($sum + $count > $opp) { + # TODO: optionally log to rateabuse, unless caller is doing it themselves + # somehow, like with the "loginstall" table. + return 0; + } + + # log current + $count = $count + 0; + $u->do("INSERT INTO ratelog (userid, rlid, evttime, ip, quantity) VALUES ". + "($u->{'userid'}, $rp->{'id'}, $now, INET_ATON($ip), $count)"); + return 1; +} + +sub login_ip_banned +{ + my $u = shift; + return 0 unless $u; + + my $ip; + return 0 unless ($ip = LJ::get_remote_ip()); + + my $udbr; + my $rateperiod = LJ::get_cap($u, "rateperiod-failed_login"); + if ($rateperiod && ($udbr = LJ::get_cluster_reader($u))) { + my $bantime = $udbr->selectrow_array("SELECT time FROM loginstall WHERE ". + "userid=$u->{'userid'} AND ip=INET_ATON(?)", + undef, $ip); + if ($bantime && $bantime > time() - $rateperiod) { + return 1; + } + } + return 0; +} + +sub handle_bad_login +{ + my $u = shift; + return 1 unless $u; + + my $ip; + return 1 unless ($ip = LJ::get_remote_ip()); + # an IP address is permitted such a rate of failures + # until it's banned for a period of time. + my $udbh; + if (! LJ::rate_log($u, "failed_login", 1, { 'limit_by_ip' => $ip }) && + ($udbh = LJ::get_cluster_master($u))) + { + $udbh->do("REPLACE INTO loginstall (userid, ip, time) VALUES ". + "(?,INET_ATON(?),UNIX_TIMESTAMP())", undef, $u->{'userid'}, $ip); + } + return 1; +} + +# +# name: LJ::_friends_do +# des: Runs given sql, then deletes the given userid's friends from memcache +# args: uuserid, sql, args +# des-uuserid: a userid or u object +# des-sql: sql to run via $dbh->do() +# des-args: a list of arguments to pass use via: $dbh->do($sql, undef, @args) +# returns: return false on error +# +sub _friends_do { + my ($uuid, $sql, @args) = @_; + my $uid = want_userid($uuid); + return undef unless $uid && $sql; + + my $dbh = LJ::get_db_writer() or return 0; + + my $ret = $dbh->do($sql, undef, @args); + return 0 if $dbh->err; + + LJ::memcache_kill($uid, "friends"); + + # pass $uuid in case it's a $u object which mark_dirty wants + LJ::mark_dirty($uuid, "friends"); + + return 1; +} + +# +# name: LJ::add_friend +# des: Simple interface to add a friend edge. +# args: uuid, to_add, opts? +# des-to_add: a single uuid or an arrayref of uuids to add (befriendees) +# des-opts: hashref; 'defaultview' key means add target uuids to $uuid's Default View friends group +# returns: boolean; 1 on success (or already friend), 0 on failure (bogus args) +# +sub add_friend +{ + &nodb; + my ($userid, $to_add, $opts) = @_; + + $userid = LJ::want_userid($userid); + return 0 unless $userid; + + my @add_ids = ref $to_add eq 'ARRAY' ? map { LJ::want_userid($_) } @$to_add : ( LJ::want_userid($to_add) ); + return 0 unless @add_ids; + + my $dbh = LJ::get_db_writer(); + + my $black = LJ::color_todb("#000000"); + my $white = LJ::color_todb("#ffffff"); + + my $groupmask = 1; + if ($opts->{'defaultview'}) { + # TAG:FR:ljlib:add_friend_getdefviewmask + my $group = LJ::get_friend_group($userid, { name => 'Default View' }); + my $grp = $group ? $group->{groupnum}+0 : 0; + $groupmask |= (1 << $grp) if $grp; + } + + # TAG:FR:ljlib:add_friend + my $bind = join(",", map { "(?,?,?,?,?)" } @add_ids); + my @vals = map { $userid, $_, $black, $white, $groupmask } @add_ids; + + my $res = LJ::_friends_do + ($userid, "INSERT IGNORE INTO friends (userid, friendid, fgcolor, bgcolor, groupmask) VALUES $bind", @vals); + + # delete friend-of memcache keys for anyone who was added + foreach (@add_ids) { + LJ::MemCache::delete([ $userid, "frgmask:$userid:$_" ]); + LJ::memcache_kill($_, 'friendofs'); + } + + return $res; +} + +# +# name: LJ::remove_friend +# args: uuid, to_del +# des-to_del: a single uuid or an arrayref of uuids to remove +# +sub remove_friend +{ + my ($userid, $to_del) = @_; + + $userid = LJ::want_userid($userid); + return undef unless $userid; + + my @del_ids = ref $to_del eq 'ARRAY' ? map { LJ::want_userid($_) } @$to_del : ( LJ::want_userid($to_del) ); + return 0 unless @del_ids; + + my $bind = join(",", map { "?" } @del_ids); + my $res = LJ::_friends_do($userid, "DELETE FROM friends WHERE userid=? AND friendid IN ($bind)", + $userid, @del_ids); + + # delete friend-of memcache keys for anyone who was removed + foreach my $fid (@del_ids) { + LJ::MemCache::delete([ $userid, "frgmask:$userid:$fid" ]); + LJ::memcache_kill($fid, 'friendofs'); + } + + return $res; +} +*delete_friend_edge = \&LJ::remove_friend; + +# +# name: LJ::get_friends +# des: Returns friends rows for a given user. +# args: uuserid, mask?, memcache_only?, force?, hint_superset? +# des-uuserid: a userid or u object +# des-mask: a security mask to filter on +# des-memcache_only: flag, set to only return data from memcache +# des-force: flag, set to ignore memcache and always hit db +# des-hint_superset: if defined, friends should be within this hash of ids +# returns: hashref; keys = friend userids +# values = hashrefs of 'friends' columns and their values +# +sub get_friends { + # TAG:FR:ljlib:get_friends + my ($uuid, $mask, $memcache_only, $force, $hint) = @_; + my $userid = LJ::want_userid($uuid); + return undef unless $userid; + return undef if $LJ::FORCE_EMPTY_FRIENDS{$userid}; + + # memcache data version + my $ver = 1; + + my $packfmt = "NH6H6NC"; + my $packlen = 15; # bytes + + my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault); + + # first, check memcache + my $memkey = [$userid, "friends:$userid"]; + + unless ($force) { + my $memfriends = LJ::MemCache::get($memkey); + if ($memfriends) { + my %friends; # rows to be returned + + # first byte of object is data version + # only version 1 is meaningful right now + my $memver = substr($memfriends, 0, 1, ''); + return undef unless $memver == $ver; + + # get each $packlen-byte row + while (length($memfriends) >= $packlen) { + my @row = unpack($packfmt, substr($memfriends, 0, $packlen, '')); + + # don't add into %friends hash if groupmask doesn't match + next if $mask && ! ($row[3]+0 & $mask+0); + next if $hint && not exists $hint->{$row[0]}; + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + # turn unpacked row into hashref + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + + # got from memcache, return + return \%friends; + } + } + return {} if $memcache_only; # no friends + + my %colors; + my $color_fmt = sub { + my ($c) = @_; + my $res = $colors{$c}; + if (!defined $res) { $res = sprintf("%06x", $c); $colors{$c} = $res; }; + return $res; + }; + + # nothing from memcache, select all rows from the + # database and insert those into memcache + # then return rows that matched the given groupmask + + my $mempack = $ver; # full packed string to insert into memcache, byte 1 is dversion + my %friends; # friends object to be returned, all groupmasks match + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT friendid, fgcolor, bgcolor, groupmask, showbydefault " . + "FROM friends WHERE userid=?"); + $sth->execute($userid); + die $dbh->errstr if $dbh->err; + while (my @row = $sth->fetchrow_array) { + + # convert color columns to hex + $row[$_] = $color_fmt->($row[$_]) foreach 1..2; + #$row[$_] = sprintf("%06x", $row[$_]) foreach 1..2; + + $mempack .= pack($packfmt, @row); + + # unless groupmask matches, skip adding to %friends + next if $mask && ! ($row[3]+0 & $mask+0); + next if $hint && not exists $hint->{$row[0]}; + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + + LJ::MemCache::set($memkey, $mempack); + + return \%friends; +} + + +# Get friendsfriends list using MemCache::get_multi() +# Skip self references, apply mask, but ignore colors. +# (code from get_friends(), slightly improved) +# +sub get_friends_multi { + # TAG:FR:ljlib:get_friends_multi + my ($uids, $mask) = @_; + + # memcache data version + my $ver = 1; + + my $packfmt = "NH6H6NC"; + my $packlen = 15; # bytes + + my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault); + my %friends; # rows to be returned + + my @memkeys = map { [$_, "friends:$_"] } keys %$uids; + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + foreach (values %$mem) { + my $memfriends = $_; + if ($memfriends) { + + # first byte of object is data version + # only version 1 is meaningful right now + my $memver = substr($memfriends, 0, 1, ''); + return undef unless $memver == $ver; + + # get each $packlen-byte row + while (length($memfriends) >= $packlen) { + my @row = unpack($packfmt, substr($memfriends, 0, $packlen, '')); + + my $fid = $row[0]; + next if exists $uids->{$fid}; + next if exists $friends{$fid}; + next if $mask && ! ($row[3]+0 & $mask+0); + + # turn unpacked row into hashref + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + } + } + return \%friends; +} + + +# +# name: LJ::get_friendofs +# des: Returns userids of friendofs for a given user. +# args: uuserid, opts? +# des-opts: options hash, keys: 'force' => don't check memcache +# returns: userid for friendofs +# +sub get_friendofs { + # TAG:FR:ljlib:get_friends + my ($uuid, $opts) = @_; + my $userid = LJ::want_userid($uuid); + return undef unless $userid; + + # first, check memcache + my $memkey = [$userid, "friendofs:$userid"]; + + unless ($opts->{force}) { + my $memfriendofs = LJ::MemCache::get($memkey); + return @$memfriendofs if $memfriendofs; + } + + # nothing from memcache, select all rows from the + # database and insert those into memcache + + my $dbh = LJ::get_db_writer(); + my $limit = $opts->{force} ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD+1); + my $friendofs = $dbh->selectcol_arrayref + ("SELECT userid FROM friends WHERE friendid=? $limit", + undef, $userid) || []; + die $dbh->errstr if $dbh->err; + + LJ::MemCache::add($memkey, $friendofs); + + return @$friendofs; +} + +# +# name: LJ::get_friend_group +# des: Returns friendgroup row(s) for a given user. +# args: uuserid, opt? +# des-uuserid: a userid or u object +# des-opt: a hashref with keys: 'bit' => bit number of group to return +# 'name' => name of group to return +# returns: hashref; if bit/name are specified, returns hashref with keys being +# friendgroup rows, or undef if the group wasn't found. +# +# otherwise, returns hashref of all group rows with keys being +# group bit numbers and values being row col => val hashrefs +# +sub get_friend_group { + my ($uuid, $opt) = @_; + my $u = LJ::want_user($uuid); + return undef unless $u; + my $uid = $u->{userid}; + + # data version number + my $ver = 1; + + # sanity check bitnum + delete $opt->{'bit'} if + (exists $opt->{'bit'}) && + ($opt->{'bit'} > 31 || $opt->{'bit'} < 0); + + my $fg; + my $find_grp = sub { + + # $fg format: + # [ version, [userid, bitnum, name, sortorder, public], [...], ... ] + + my $memver = shift @$fg; + return undef unless $memver == $ver; + + # bit number was specified + if ($opt->{'bit'}) { + foreach (@$fg) { + return LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) + if $_->[1] == $opt->{'bit'}; + } + return undef; + } + + # group name was specified + if ($opt->{'name'}) { + foreach (@$fg) { + return LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) + if lc($_->[2]) eq lc($opt->{'name'}); + } + return undef; + } + + # no arg, return entire object + return { map { $_->[1] => LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) } @$fg }; + }; + + # check memcache + my $memkey = [$uid, "fgrp:$uid"]; + $fg = LJ::MemCache::get($memkey); + return $find_grp->() if $fg; + + # check database + $fg = [$ver]; + my ($db, $fgtable) = $u->{dversion} > 5 ? + (LJ::get_cluster_def_reader($u), 'friendgroup2') : # if dversion is 6+, use definitive reader + (LJ::get_db_writer(), 'friendgroup'); # else, use regular db writer + return undef unless $db; + + my $sth = $db->prepare("SELECT userid, groupnum, groupname, sortorder, is_public " . + "FROM $fgtable WHERE userid=?"); + $sth->execute($uid); + return LJ::error($db) if $db->err; + + my @row; + push @$fg, [ @row ] while @row = $sth->fetchrow_array; + + # set in memcache + LJ::MemCache::set($memkey, $fg); + + return $find_grp->(); +} + +# +# name: LJ::fill_groups_xmlrpc +# des: Fills a hashref (presumably to be sent to an XMLRPC client, EG fotobilder) +# with user friend group information +# args: u, ret +# des-ret: a response hashref to fill with friend group data +# returns: undef if called incorrectly, 1 otherwise +# +sub fill_groups_xmlrpc { + my ($u, $ret) = @_; + return undef unless ref $u && ref $ret; + + # layer on friend group information in the following format: + # + # grp:1 => 'mygroup', + # ... + # grp:30 => 'anothergroup', + # + # grpu:whitaker => '0,1,2,3,4', + # grpu:test => '0', + + my $grp = LJ::get_friend_group($u) || {}; + + $ret->{"grp:0"} = "_all_"; + foreach my $bit (1..30) { + next unless my $g = $grp->{$bit}; + $ret->{"grp:$bit"} = $g->{groupname}; + } + + my $fr = LJ::get_friends($u) || {}; + my $users = LJ::load_userids(keys %$fr); + while (my ($fid, $f) = each %$fr) { + my $u = $users->{$fid}; + next unless $u->{journaltype} =~ /[PS]/; + + my $fname = $u->{user}; + $ret->{"grpu:$fid:$fname"} = + join(",", 0, grep { $grp->{$_} && $f->{groupmask} & 1 << $_ } 1..30); + } + + return 1; +} + +# +# name: LJ::mark_dirty +# des: Marks a given user as being $what type of dirty +# args: u, what +# des-what: type of dirty being marked (EG 'friends') +# returns: 1 +# +sub mark_dirty { + my ($uuserid, $what) = @_; + + my $userid = LJ::want_userid($uuserid); + return 1 if $LJ::REQ_CACHE_DIRTY{$what}->{$userid}; + + my $u = LJ::want_user($userid); + + # friends dirtiness is only necessary to track + # if we're exchange XMLRPC with fotobilder + if ($what eq 'friends' && $LJ::FB_SITEROOT) { + push @LJ::CLEANUP_HANDLERS, sub { + my $res = LJ::cmd_buffer_add($u->{clusterid}, $u->{userid}, 'dirty', { what => 'friends' }); + }; + } else { + return 1; + } + + $LJ::REQ_CACHE_DIRTY{$what}->{$userid}++; + + return 1; +} + +# +# name: LJ::memcache_kill +# des: Kills a memcache entry, given a userid and type +# args: uuserid, type +# des-uuserid: a userid or u object +# des-args: memcache key type, will be used as "$type:$userid" +# returns: results of LJ::MemCache::delete +# +sub memcache_kill { + my ($uuid, $type) = @_; + my $userid = want_userid($uuid); + return undef unless $userid && $type; + + return LJ::MemCache::delete([$userid, "$type:$userid"]); +} + +# is a user object (at least a hashref) +sub isu { return ref $_[0] && (ref $_[0] eq "LJ::User" || + ref $_[0] eq "HASH" && $_[0]->{userid}); } + +# create externally mapped user. +# return uid of LJ user on success, undef on error. +# opts = { +# extuser or extuserid (or both, but one is required.), +# caps +# } +# opts also can contain any additional options that create_account takes. (caps?) +sub create_extuser +{ + my ($type, $opts) = @_; + return undef unless $type && $LJ::EXTERNAL_NAMESPACE{$type}->{id}; + return undef unless ref $opts && + ($opts->{extuser} || defined $opts->{extuserid}); + + my $uid; + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + # make sure a mapping for this user doesn't already exist. + $uid = LJ::get_extuser_uid( $type, $opts, 'force' ); + return $uid if $uid; + + # increment ext_ counter until we successfully create an LJ account. + # hard cap it at 10 tries. (arbitrary, but we really shouldn't have *any* + # failures here, let alone 10 in a row.) + for (1..10) { + my $extuser = 'ext_' . LJ::alloc_global_counter( 'E' ); + $uid = + LJ::create_account( + { caps => $opts->{caps}, user => $extuser, name => $extuser } ); + last if $uid; + select undef, undef, undef, .10; # lets not thrash over this. + } + return undef unless $uid; + + # add extuser mapping. + my $sql = "INSERT INTO extuser SET userid=?, siteid=?"; + my @bind = ($uid, $LJ::EXTERNAL_NAMESPACE{$type}->{id}); + + if ($opts->{extuser}) { + $sql .= ", extuser=?"; + push @bind, $opts->{extuser}; + } + + if ($opts->{extuserid}) { + $sql .= ", extuserid=? "; + push @bind, $opts->{extuserid}+0; + } + + $dbh->do($sql, undef, @bind) or return undef; + return $uid; +} + +# given an extuserid or extuser, return the LJ uid. +# return undef if there is no mapping. +sub get_extuser_uid +{ + my ($type, $opts, $force) = @_; + return undef unless $type && $LJ::EXTERNAL_NAMESPACE{$type}->{id}; + return undef unless ref $opts && + ($opts->{extuser} || defined $opts->{extuserid}); + + my $dbh = $force ? LJ::get_db_writer() : LJ::get_db_reader(); + return undef unless $dbh; + + my $sql = "SELECT userid FROM extuser WHERE siteid=?"; + my @bind = ($LJ::EXTERNAL_NAMESPACE{$type}->{id}); + + if ($opts->{extuser}) { + $sql .= " AND extuser=?"; + push @bind, $opts->{extuser}; + } + + if ($opts->{extuserid}) { + $sql .= $opts->{extuser} ? ' OR ' : ' AND '; + $sql .= "extuserid=?"; + push @bind, $opts->{extuserid}+0; + } + + return $dbh->selectrow_array($sql, undef, @bind); +} + +# given a LJ userid/u, return a hashref of: +# type, extuser, extuserid +# returns undef if user isn't an externally mapped account. +sub get_extuser_map +{ + my $uid = LJ::want_userid(shift); + return undef unless $uid; + + my $dbr = LJ::get_db_reader(); + return undef unless $dbr; + + my $sql = "SELECT * FROM extuser WHERE userid=?"; + my $ret = $dbr->selectrow_hashref($sql, undef, $uid); + return undef unless $ret; + + my $type = 'unknown'; + foreach ( keys %LJ::EXTERNAL_NAMESPACE ) { + $type = $_ if $LJ::EXTERNAL_NAMESPACE{$_}->{id} == $ret->{siteid}; + } + + $ret->{type} = $type; + return $ret; +} + +# +# name: LJ::create_account +# des: Creates a new basic account. Note: This function is +# not really too useful but should be extended to be useful so +# htdocs/create.bml can use it, rather than doing the work itself. +# returns: integer of userid created, or 0 on failure. +# args: dbarg?, opts +# des-opts: hashref containing keys 'user', 'name', 'password', 'email', 'caps', 'journaltype' +# +sub create_account +{ + &nodb; + my $o = shift; + + my $user = LJ::canonical_username($o->{'user'}); + unless ($user) { + return 0; + } + + my $dbh = LJ::get_db_writer(); + my $quser = $dbh->quote($user); + my $cluster = defined $o->{'cluster'} ? $o->{'cluster'} : LJ::new_account_cluster(); + my $caps = $o->{'caps'} || $LJ::NEWUSER_CAPS; + my $journaltype = $o->{'journaltype'} || "P"; + + # new non-clustered accounts aren't supported anymore + return 0 unless $cluster; + + my $userid = 0; # scope it higher + my $errorcounter = 0; + my $old_print_error = $dbh->{PrintError}; # save PrintError mode + $dbh->{PrintError} = 0; # will check for errors manually + + while (1) { + my $ruserid; + if ($o->{imported}) { + $ruserid = LJ::get_new_importedid(); + } + else { + $ruserid = LJ::get_new_userid(); + } + + return 0 unless $ruserid; + $dbh->do("set insert_id = $ruserid"); + + # try to create new account + $dbh->do("INSERT INTO user (user, name, password, clusterid, dversion, caps, email, journaltype) ". + "VALUES ($quser, ?, ?, ?, $LJ::MAX_DVERSION, ?, ?, ?)", undef, + $o->{'name'}, $o->{'password'}, $cluster, $caps, $o->{'email'}, $journaltype); + + if ($dbh->err) { + # who wants to try forever + if ($errorcounter > 10) { + print $dbh->{err} . ": " . $dbh->{errstr} . "\n"; + return 0; + } + + $errorcounter++; + + sleep 1; # let it breathe + next; # try again + } + else { + $userid = $dbh->{'mysql_insertid'}; # smells like success + $dbh->{PrintError} = $old_print_error; # restore error reporting + + return 0 unless $userid; # but? + + last; # finally + } + } + + $dbh->do("INSERT INTO useridmap (userid, user) VALUES ($userid, $quser)"); + $dbh->do("INSERT INTO userusage (userid, timecreate) VALUES ($userid, NOW())"); + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + 'code' => undef, + }); + return $userid; +} + +# +# name: LJ::new_account_cluster +# des: Which cluster to put a new account on. $DEFAULT_CLUSTER if it's +# a scalar, random element from @$DEFAULT_CLUSTER if it's arrayref. +# also verifies that the database seems to be available. +# returns: clusterid where the new account should be created; 0 on error +# (such as no clusters available) +# +sub new_account_cluster +{ + # if it's not an arrayref, put it in an array ref so we can use it below + my $clusters = ref $LJ::DEFAULT_CLUSTER ? $LJ::DEFAULT_CLUSTER : [ $LJ::DEFAULT_CLUSTER+0 ]; + + # iterate through the new clusters from a random point + my $size = @$clusters; + my $start = int(rand() * $size); + foreach (1..$size) { + my $cid = $clusters->[$start++ % $size]; + + # verify that this cluster is in @LJ::CLUSTERS + my @check = grep { $_ == $cid } @LJ::CLUSTERS; + next unless scalar(@check) >= 1 && $check[0] == $cid; + + # try this cluster to see if we can use it, return if so + my $dbcm = LJ::get_cluster_master($cid); + return $cid if $dbcm; + } + + # if we get here, we found no clusters that were up... + return 0; +} + +# +# name: LJ::make_journal +# class: +# des: +# info: +# args: dbarg, user, view, remote, opts +# des-: +# returns: +# +sub make_journal +{ + &nodb; + my ($user, $view, $remote, $opts) = @_; + + my $r = $opts->{'r'}; # mod_perl $r, or undef + my $geta = $opts->{'getargs'}; + + if ($LJ::SERVER_DOWN) { + if ($opts->{'vhost'} eq "customview") { + return ""; + } + return LJ::server_down_html(); + } + + my $u = LJ::load_user($user); + unless ($u) { + $opts->{'baduser'} = 1; + return "

    Error

    No such user $user"; + } + + if (($view eq 'entry' || $view eq 'reply') && $u->{'statusvis'} !~ /[DXS]/) { + # both for s1 and s2: fast check for 304, 403, 404 statuses without a body + LJ::S2::EntryPage_fast_check($u, $view, $remote, $opts); + return if $opts->{'notmodified'} || $opts->{'suspendeduser'} || $opts->{'handler_return'}; + } + + # what charset we put in the HTML + $opts->{'saycharset'} ||= "utf-8"; + + if ($view eq 'data' && $u->{'statusvis'} !~ /[DXS]/) { + # rss, atom, foaf + return LJ::Feed::make_feed($r, $u, $remote, $opts); + } + + + # if we're using the 'tag' view, then convert to lastn and set option, this + # is done early so it can propogate to S1 and S2 as appropriate + if ($view eq 'tag') { + # FIXME: would be nice to have boolean logic "foo AND bar" or "+foo -bar" etc + # "foo,bar" is interpreted as "foo or bar" for now, common case + my $tags = LJ::durl($opts->{pathextra}); + $tags =~ s/^\///; # clear leading / + $opts->{getargs}->{tag} = $tags; + + # use a lastn view to render + delete $opts->{pathextra}; + $view = 'lastn'; + } + + # S1 style hashref. won't be loaded now necessarily, + # only if via customview. + my $style; + + my $styleid; + if ($opts->{'styleid'}) { # s1 styleid + $styleid = $opts->{'styleid'}+0; + + # if we have an explicit styleid, we have to load + # it early so we can learn its type, so we can + # know which uprops to load for its owner + $style = LJ::S1::load_style($styleid, \$view); + } else { + $view ||= "lastn"; # default view when none specified explicitly in URLs + if ($LJ::viewinfo{$view} || $view eq "month" || + $view eq "entry" || $view eq "reply") { + $styleid = -1; # to get past the return, then checked later for -1 and fixed, once user is loaded. + } else { + $opts->{'badargs'} = 1; + } + } + return unless $styleid; + + my $eff_view = $LJ::viewinfo{$view}->{'styleof'} || $view; + my $s1prop = "s1_${eff_view}_style"; + + my @needed_props = ("stylesys", "s2_style", "url", "urlname", "opt_nctalklinks", + "renamedto", "opt_blockrobots", "opt_usesharedpic", + "journaltitle", "journalsubtitle", "external_foaf_url"); + + # S2 is more fully featured than S1, so sometimes we get here and $eff_view + # is reply/month/entry/res and that means it *has* to be S2--S1 defaults to a + # BML page to handle those, but we don't want to attempt to load a userprop + # because now load_user_props dies if you try to load something invalid + push @needed_props, $s1prop if $eff_view =~ /^(?:calendar|day|friends|lastn)$/; + + # preload props the view creation code will need later (combine two selects) + if (ref $LJ::viewinfo{$eff_view}->{'owner_props'} eq "ARRAY") { + push @needed_props, @{$LJ::viewinfo{$eff_view}->{'owner_props'}}; + } + + if ($eff_view eq "reply") { + push @needed_props, "opt_logcommentips"; + } + + LJ::load_user_props($u, @needed_props); + + # if the remote is the user to be viewed, make sure the $remote + # hashref has the value of $u's opt_nctalklinks (though with + # LJ::load_user caching, this may be assigning between the same + # underlying hashref) + $remote->{'opt_nctalklinks'} = $u->{'opt_nctalklinks'} if + ($remote && $remote->{'userid'} == $u->{'userid'}); + + my $stylesys = 1; + if ($styleid == -1) { + + my $get_styleinfo = sub { + + my $get_s1_styleid = sub { + my $id = $u->{$s1prop}; + LJ::run_hooks("s1_style_select", { + 'styleid' => \$id, + 'u' => $u, + 'view' => $view, + }); + return $id; + }; + + # forced s2 style id + if ($geta->{'s2id'} && LJ::get_cap($u, "s2styles")) { + + # see if they own the requested style + my $dbr = LJ::get_db_reader(); + my $style_userid = $dbr->selectrow_array("SELECT userid FROM s2styles WHERE styleid=?", + undef, $geta->{'s2id'}); + + # if remote owns the style or the journal owns the style, it's okay + if ($u->{'userid'} == $style_userid || + $remote->{'userid'} == $style_userid ) { + return (2, $geta->{'s2id'}); + } + } + + # style=mine passed in GET? + if ($remote && $geta->{'style'} eq 'mine') { + + # get remote props and decide what style remote uses + LJ::load_user_props($remote, "stylesys", "s2_style"); + + # remote using s2; make sure we pass down the $remote object as the style_u to + # indicate that they should use $remote to load the style instead of the regular $u + if ($remote->{'stylesys'} == 2 && $remote->{'s2_style'}) { + $opts->{'checkremote'} = 1; + $opts->{'style_u'} = $remote; + return (2, $remote->{'s2_style'}); + } + + # remote using s1 + return (1, $get_s1_styleid->()); + } + + # resource URLs have the styleid in it + if ($view eq "res" && $opts->{'pathextra'} =~ m!^/(\d+)/!) { + return (2, $1); + } + + my $forceflag = 0; + LJ::run_hooks("force_s1", $u, \$forceflag); + + # if none of the above match, they fall through to here + if ( !$forceflag && $u->{'stylesys'} == 2 ) { + return (2, $u->{'s2_style'}); + } + + # no special case and not s2, fall through to s1 + return (1, $get_s1_styleid->()); + }; + + ($stylesys, $styleid) = $get_styleinfo->(); + } + + if ($r) { + $r->notes('journalid' => $u->{'userid'}); + } + + my $notice = sub { + my $msg = shift; + my $status = shift; + + my $url = "$LJ::SITEROOT/users/$user/"; + $opts->{'status'} = $status if $status; + + my $head; + $head .= qq{\n} + if LJ::OpenID::server_enabled(); + + return qq{ + + + $head + + +

    Notice

    +

    $msg

    +

    Instead, please use $url

    + + + }.("\n" x 50); + }; + my $error = sub { + my $msg = shift; + my $status = shift; + $opts->{'status'} = $status if $status; + + return qq{ +

    Error

    +

    $msg

    + }.("\n" x 50); + }; + if ($LJ::USER_VHOSTS && $opts->{'vhost'} eq "users" && $u->{'journaltype'} ne 'R' && + ! LJ::get_cap($u, "userdomain")) { + return $notice->("URLs like http://username.$LJ::USER_DOMAIN/" . + " are not available for this user's account type."); + } + if ($opts->{'vhost'} =~ /^other:/ && ! LJ::get_cap($u, "userdomain")) { + return $notice->("This user's account type doesn't permit domain aliasing."); + } + if ($opts->{'vhost'} eq "customview" && ! LJ::get_cap($u, "styles")) { + return $notice->("This user's account type is not permitted to create and embed styles."); + } + if ($opts->{'vhost'} eq "community" && $u->{'journaltype'} !~ /[CR]/) { + $opts->{'badargs'} = 1; # Output a generic 'bad URL' message if available + return "

    Notice

    This account isn't a community journal.

    "; + } + if ($view eq "friendsfriends" && ! LJ::get_cap($u, "friendsfriendsview")) { + return "Sorry
    This user's account type doesn't permit showing friends of friends."; + } + + # if there's a GET argument for tags, split those out + if (exists $opts->{getargs}->{tag}) { + my $tagfilter = $opts->{getargs}->{tag}; + + my $print_tag_list = sub { + # show all tags and exit + my $tags = LJ::Tags::get_usertags($u, { remote => $remote }); + my @list = (); + foreach (values %{$tags}) { + push @list, [$_->{'name'}, $_->{'uses'}]; + } + @list = sort {$a->[0] cmp $b->[0]} @list; #sort by alphabet + #@list = sort {$b->[1] <=> $a->[1]} @list; #sort by popularity + my $text = "Visible Tags
      \n"; + foreach (@list) { + my $num = "$_->[1] uses"; + $num = "1 use" if ($_->[1] == 1); + $text .= "
    • [0]\">$_->[0] - $num
    • \n"; + } + $text .= "
    "; + return $text; + }; + + # if empty tags argument - show all tags and exit. + return $print_tag_list->() unless $tagfilter; + + $opts->{tags} = []; + + return $print_tag_list->() + #return $error->("Sorry, the tag list specified is invalid.", "404 Not Found") + unless LJ::Tags::is_valid_tagstring($tagfilter, $opts->{tags}); + } + + + unless ($geta->{'viewall'} && LJ::check_priv($remote, "canview") || + $opts->{'pathextra'} =~ m#/(\d+)/stylesheet$# + ) { # don't check style sheets + return $error->("Journal has been deleted. If you are $user, you have a period of 30 days to decide to undelete your journal.", "404 Not Found") if ($u->{'statusvis'} eq "D"); + return $error->("This journal has been suspended.", "403 Forbidden") if ($u->{'statusvis'} eq "S"); + } + + return $error->("This journal has been deleted and purged.", "410 Gone") if ($u->{'statusvis'} eq "X"); + + return $error->("This user has no journal here.", "404 Not here") if $u->{'journaltype'} eq "I" && $view ne "friends"; + + $opts->{'view'} = $view; + + if ($stylesys == 2) { + $r->notes('codepath' => "s2.$view") if $r; + return LJ::S2::make_journal($u, $styleid, $view, $remote, $opts); + } + + # Everything from here on down is S1. FIXME: this should be moved to LJ::S1::make_journal + # to be more like LJ::S2::make_journal. + + return LJ::S1_make_journal($r, $u, $style, $styleid, $view, $remote, $opts); +} + +# S1 +sub S1_make_journal { + my ($r, $u, $style, $styleid, $view, $remote, $opts) = @_; + + $r->notes('codepath' => "s1.$view") if $r; + + # signal to LiveJournal.pm that we can't handle this - is it ever needed? + if ($view eq "entry" || $view eq "reply" || $view eq "month") { + ${$opts->{'handle_with_bml_ref'}} = 1; + } + + # For embedded polls + BML::set_language($LJ::LANGS[0] || 'en', \&LJ::Lang::get_text); + + # load the user-related S1 data (overrides and colors) + my $s1uc = {}; + my $s1uc_memkey = [$u->{'userid'}, "s1uc:$u->{'userid'}"]; + if ($u->{'useoverrides'} eq "Y" || $u->{'themeid'} == 0) { + $s1uc = LJ::MemCache::get($s1uc_memkey); + unless ($s1uc) { + my $db; + my $setmem = 1; + if (@LJ::MEMCACHE_SERVERS) { + $db = LJ::get_cluster_def_reader($u); + } else { + $db = LJ::get_cluster_reader($u); + $setmem = 0; + } + $s1uc = $db->selectrow_hashref("SELECT * FROM s1usercache WHERE userid=?", + undef, $u->{'userid'}); + LJ::MemCache::set($s1uc_memkey, $s1uc) if $s1uc && $setmem; + } + } + + # we should have our cache row! we'll update it in a second. + my $dbcm; + if (! $s1uc) { + $u->do("INSERT IGNORE INTO s1usercache (userid) VALUES (?)", undef, $u->{'userid'}); + $s1uc = {}; + } + + # conditionally rebuild parts of our cache that are missing + my %update; + + # is the overrides cache old or missing? + my $dbh; + if ($u->{'useoverrides'} eq "Y" && (! $s1uc->{'override_stor'} || + $s1uc->{'override_cleanver'} < $LJ::S1::CLEANER_VERSION)) { + + my $overrides = LJ::S1::get_overrides($u); + $update{'override_stor'} = LJ::CleanHTML::clean_s1_style($overrides); + $update{'override_cleanver'} = $LJ::S1::CLEANER_VERSION; + } + + # is the color cache here if it's a custom user theme? + if ($u->{'themeid'} == 0 && ! $s1uc->{'color_stor'}) { + my $col = {}; + $dbh ||= LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT coltype, color FROM themecustom WHERE user=?"); + $sth->execute($u->{'user'}); + $col->{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref; + $update{'color_stor'} = Storable::nfreeze($col); + } + + # save the updates + if (%update) { + my $set; + foreach my $k (keys %update) { + $s1uc->{$k} = $update{$k}; + $set .= ", " if $set; + $set .= "$k=" . $u->quote($update{$k}); + } + my $rv = $u->do("UPDATE s1usercache SET $set WHERE userid=?", undef, $u->{'userid'}); + if ($rv && $update{'color_stor'}) { + $dbh ||= LJ::get_db_writer(); + $dbh->do("DELETE FROM themecustom WHERE user=?", undef, $u->{'user'}); + } + LJ::MemCache::set($s1uc_memkey, $s1uc); + } + + + + # load the style + my $viewref = $view eq "" ? \$view : undef; + $style ||= $LJ::viewinfo{$view}->{'nostyle'} ? {} : + LJ::S1::load_style($styleid, $viewref); + + my %vars = (); + + # apply the style + foreach (keys %$style) { + $vars{$_} = $style->{$_}; + } + + # apply the overrides + if ($opts->{'nooverride'}==0 && $u->{'useoverrides'} eq "Y") { + my $tw = Storable::thaw($s1uc->{'override_stor'}); + foreach (keys %$tw) { + $vars{$_} = $tw->{$_}; + } + } + + # apply the color theme + my $cols = $u->{'themeid'} ? LJ::S1::get_themeid($u->{'themeid'}) : + Storable::thaw($s1uc->{'color_stor'}); + foreach (keys %$cols) { + $vars{"color-$_"} = $cols->{$_}; + } + + # instruct some function to make this specific view type + return unless defined $LJ::viewinfo{$view}->{'creator'}; + my $ret = ""; + + # call the view creator w/ the buffer to fill and the construction variables + my $res = $LJ::viewinfo{$view}->{'creator'}->(\$ret, $u, \%vars, $remote, $opts); + unless ($res) { + my $errcode = $opts->{'errcode'}; + my $errmsg = { + 'nodb' => 'Database temporarily unavailable during maintenance.', + 'nosyn' => 'No syndication URL available.', + }->{$errcode}; + return "" if ($opts->{'vhost'} eq "customview"); + + print STDERR "error running LJ::viewinfo [$errcode]; user [$u->{'name'}] \n"; + + # If not customview, set the error response code. + $opts->{'status'} = { + 'nodb' => '503 Maintenance', + 'nosyn' => '404 Not Found', + }->{$errcode} || '500 Server Error'; + return "3".$errmsg; + } + + if ($opts->{'redir'}) { + return undef; + } + + # clean up attributes which we weren't able to quickly verify + # as safe in the Storable-stored clean copy of the style. + $ret =~ s/\%\%\[attr\[(.+?)\]\]\%\%/LJ::CleanHTML::s1_attribute_clean($1)/eg; + + # return it... + return $ret; +} + +# +# name: LJ::canonical_username +# des: +# info: +# args: user +# returns: the canonical username given, or blank if the username is not well-formed +# +sub canonical_username +{ + my $user = shift; + if ($user =~ /^\s*([\w\-]{1,15})\s*$/) { + # perl 5.8 bug: $user = lc($1) sometimes causes corruption when $1 points into $user. + $user = $1; + $user = lc($user); + $user =~ s/-/_/g; + return $user; + } + return ""; # not a good username. +} + +# +# name: LJ::get_userid +# des: Returns a userid given a username. +# info: Results cached in memory. On miss, does DB call. Not advised +# to use this many times in a row... only once or twice perhaps +# per request. Tons of serialized db requests, even when small, +# are slow. Opposite of [func[LJ::get_username]]. +# args: dbarg?, user +# des-user: Username whose userid to look up. +# returns: Userid, or 0 if invalid user. +# +sub get_userid +{ + &nodb; + my $user = shift; + + $user = LJ::canonical_username($user); + + if ($LJ::CACHE_USERID{$user}) { return $LJ::CACHE_USERID{$user}; } + + my $userid = LJ::MemCache::get("uidof:$user"); + return $LJ::CACHE_USERID{$user} = $userid if $userid; + + my $dbr = LJ::get_db_reader(); + $userid = $dbr->selectrow_array("SELECT userid FROM useridmap WHERE user=?", undef, $user); + + # implictly create an account if we're using an external + # auth mechanism + if (! $userid && ref $LJ::AUTH_EXISTS eq "CODE") + { + $userid = LJ::create_account({ 'user' => $user, + 'name' => $user, + 'password' => '', }); + } + + if ($userid) { + $LJ::CACHE_USERID{$user} = $userid; + LJ::MemCache::set("uidof:$user", $userid); + } + + return ($userid+0); +} + +# +# name: LJ::want_userid +# des: Returns userid when passed either userid or the user hash. Useful to functions that +# want to accept either. Forces its return value to be a number (for safety). +# args: userid +# des-userid: Either a userid, or a user hash with the userid in its 'userid' key. +# returns: The userid, guaranteed to be a numeric value. +# +sub want_userid +{ + my $uuserid = shift; + return ($uuserid->{'userid'} + 0) if ref $uuserid; + return ($uuserid + 0); +} + +# +# name: LJ::want_user +# des: Returns user object when passed either userid or the user hash. Useful to functions that +# want to accept either. +# args: user +# des-user: Either a userid, or a user hash with the userid in its 'userid' key. +# returns: The user hash represented by said userid. +# +sub want_user +{ + my $uuser = shift; + return $uuser if ref $uuser; + return $uuser unless $uuser; + return LJ::load_userid($uuser+0); +} + +# +# name: LJ::get_username +# des: Returns a username given a userid. +# info: Results cached in memory. On miss, does DB call. Not advised +# to use this many times in a row... only once or twice perhaps +# per request. Tons of serialized db requests, even when small, +# are slow. Opposite of [func[LJ::get_userid]]. +# args: dbarg?, user +# des-user: Username whose userid to look up. +# returns: Userid, or 0 if invalid user. +# +sub get_username +{ + &nodb; + my $userid = shift; + $userid += 0; + + # Checked the cache first. + if ($LJ::CACHE_USERNAME{$userid}) { return $LJ::CACHE_USERNAME{$userid}; } + + # if we're using memcache, it's faster to just query memcache for + # an entire $u object and just return the username. otherwise, we'll + # go ahead and query useridmap + if (@LJ::MEMCACHE_SERVERS) { + my $u = LJ::load_userid($userid); + return undef unless $u; + + $LJ::CACHE_USERNAME{$userid} = $u->{'user'}; + return $u->{'user'}; + } + + my $dbr = LJ::get_db_reader(); + my $user = $dbr->selectrow_array("SELECT user FROM useridmap WHERE userid=?", undef, $userid); + + # Fall back to master if it doesn't exist. + unless (defined $user) { + my $dbh = LJ::get_db_writer(); + $user = $dbh->selectrow_array("SELECT user FROM useridmap WHERE userid=?", undef, $userid); + } + + return undef unless defined $user; + + $LJ::CACHE_USERNAME{$userid} = $user; + return $user; +} + +# +# name: LJ::can_manage +# des: Given a user and a target user, will determine if the first user is an +# admin for the target user. +# returns: bool: true if authorized, otherwise fail +# args: remote, u +# des-remote: user object or userid of user to try and authenticate +# des-u: user object or userid of target user +# +sub can_manage { + my $remote = LJ::want_user(shift); + my $u = LJ::want_user(shift); + return undef unless $remote && $u; + + # is same user? + return 1 if LJ::u_equals($u, $remote); + + # people/syn/rename accounts can only be managed by the one account + return undef if $u->{journaltype} =~ /^[PYR]$/; + + # check for admin access + return undef unless LJ::check_rel($u, $remote, 'A'); + + # passed checks, return true + return 1; +} + +# +# name: LJ::can_manage_other +# des: Given a user and a target user, will determine if the first user is an +# admin for the target user, but not if the two are the same. +# returns: bool: true if authorized, otherwise fail +# args: remote, u +# des-remote: user object or userid of user to try and authenticate +# des-u: user object or userid of target user +# +sub can_manage_other { + my ($remote, $u) = @_; + return 0 if LJ::want_userid($remote) == LJ::want_userid($u); + return LJ::can_manage($remote, $u); +} + +sub can_delete_journal_item { + return LJ::can_manage(@_); +} + +# +# name: LJ::get_remote +# des: authenticates the user at the remote end based on their cookies +# and returns a hashref representing them +# returns: hashref containing 'user' and 'userid' if valid user, else +# undef. +# args: opts? +# des-opts: 'criterr': scalar ref to set critical error flag. if set, caller +# should stop processing whatever it's doing and complain +# about an invalid login with a link to the logout page.. +# 'ignore_ip': ignore IP address of remote for IP-bound sessions +# +sub get_remote +{ + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $dummy; + + return $LJ::CACHE_REMOTE if $LJ::CACHED_REMOTE && ! $opts->{'ignore_ip'}; + + my $criterr = $opts->{criterr} || \$dummy; + $$criterr = 0; + + my $cookie = sub { return $BML::COOKIE{$_[0]}; }; + + my $no_remote = sub { + LJ::set_remote(undef); + return undef; + }; + + # set this flag if any of their ljsession cookies contained the ".FS" + # opt to use the fast server. if we later find they're not logged + # in and set it, or set it with a free account, then we give them + # the invalid cookies error. + my $tried_fast = 0; + my @errs = (); + my $now = time(); + + my ($u, $sess); # what we eventually care about + my $memkey; + + foreach my $sessdata (@{ $cookie->('ljsession[]'); }) { + my ($authtype, $user, $sessid, $auth, $sopts) = split(/:/, $sessdata); + $tried_fast = 1 if $sopts =~ /\.FS\b/; + my $err = sub { + $sess = undef; + push @errs, "$sessdata: $_[0]"; + }; + + # fail unless authtype is 'ws' (more might be added in future) + unless ($authtype eq "ws") { + $err->("no ws auth"); + next; + } + + $u = LJ::load_user($user); + unless ($u) { + $err->("user doesn't exist"); + next; + } + + # locked accounts can't be logged in + if ($u->{statusvis} eq 'L') { + $err->("User account is locked."); + next; + } + + my $sess_db; + my $get_sess = sub { + return undef unless $sess_db; + $sess = $sess_db->selectrow_hashref("SELECT * FROM sessions ". + "WHERE userid=? AND sessid=? AND auth=?", + undef, $u->{'userid'}, $sessid, $auth); + }; + $memkey = [$u->{'userid'},"sess:$u->{'userid'}:$sessid"]; + # try memory + $sess = LJ::MemCache::get($memkey); + # try master + unless ($sess) { + $sess_db = LJ::get_cluster_def_reader($u); + $get_sess->(); + LJ::MemCache::set($memkey, $sess) if $sess; + } + # try slave + unless ($sess) { + $sess_db = LJ::get_cluster_reader($u); + $get_sess->(); + } + + unless ($sess) { + $err->("Couldn't find session"); + next; + } + + unless ($sess->{auth} eq $auth) { + $err->("Invald auth"); + next; + } + + if ($sess->{'timeexpire'} < $now) { + $err->("Invalid auth"); + next; + } + + if ($sess->{'ipfixed'} && ! $opts->{'ignore_ip'}) { + my $remote_ip = $LJ::_XFER_REMOTE_IP || LJ::get_remote_ip(); + if ($sess->{'ipfixed'} ne $remote_ip) { + $err->("Session wrong IP"); + next; + } + } + + last; + } + + # inform the caller that this user is faking their fast-server cookie + # attribute. + if ($tried_fast && ! LJ::get_cap($u, "fastserver")) { + $$criterr = 1; + } + + if (! $sess) { + LJ::set_remote(undef); + return undef; + } + + # renew short session + my $sess_length = { + 'short' => 60*60*24*1.5, + 'long' => 60*60*24*60, + 'once' => 0, # do not renew these + }->{$sess->{exptype}}; + + # only long cookies should be given an expiration time + # other should get 0 (when browser closes) + my $cookie_length = $sess->{exptype} eq 'long' ? $sess_length : 0; + + # if there is a new session length to be set and the user's db writer is available, + # go ahead and set the new session expiration in the database. then only update the + # cookies if the database operation is successful + if ($sess_length && $sess->{'timeexpire'} - $now < $sess_length/2 && + $u->writer && $u->do("UPDATE sessions SET timeexpire=? WHERE userid=? AND sessid=?", + undef, $now + $sess_length, $u->{userid}, $sess->{sessid})) + { + + # delete old, now-bogus memcache data + LJ::MemCache::delete($memkey); + + # update their ljsession cookie unless it's a session-length cookie + if ($cookie_length) { + + eval { + my @domains = ref $LJ::COOKIE_DOMAIN ? @$LJ::COOKIE_DOMAIN : ($LJ::COOKIE_DOMAIN); + foreach my $dom (@domains) { + my $cookiestr = 'ljsession=' . $cookie->('ljsession'); + $cookiestr .= '; expires=' . LJ::time_to_cookie($now + $cookie_length); + $cookiestr .= $dom ? "; domain=$dom" : ''; + $cookiestr .= '; path=/; HttpOnly'; + + Apache->request->err_headers_out->add('Set-Cookie' => $cookiestr); + } + }; + } + } + + # augment hash with session data; + $u->{'_session'} = $sess; + + LJ::set_remote($u); + + eval { + Apache->request->notes("ljuser" => $u->{'user'}); + }; + + return $u; +} + +sub set_remote +{ + my $remote = shift; + $LJ::CACHED_REMOTE = 1; + $LJ::CACHE_REMOTE = $remote; + 1; +} + +sub unset_remote +{ + $LJ::CACHED_REMOTE = 0; + $LJ::CACHE_REMOTE = undef; + 1; +} + + +1; diff --git a/local/cgi-bin/LJR/Distributed.pm b/local/cgi-bin/LJR/Distributed.pm new file mode 100755 index 0000000..6aa2e16 --- /dev/null +++ b/local/cgi-bin/LJR/Distributed.pm @@ -0,0 +1,1458 @@ +use strict; + +package LJR::Distributed; + +my $warn = sub { + print join ("\n", @_); + print "\n"; +}; + +my $err = sub { + if (ref($_[0])) { + my $dbh = shift; + $dbh->rollback; + } + my %res = (); + + my $cstack = "\ncallstack:"; + my $i = 0; + while ( 1 ) { + my $tfunc = (caller($i))[3]; + if ($tfunc && $tfunc ne "") { + if ($tfunc !~ /\_\_ANON\_\_/) { + $cstack .= " " . $tfunc; + } + $i = $i + 1; + } + else { + last; + } + } + + $res{"err"} = 1; + $res{"errtext"} = join ("\n", @_); + $res{"errtext"} .= $cstack; + return \%res; +}; + +# +# created from LJ::Talk::Post::enter_comment +# +sub create_imported_comment { + my ($journalu, $parent, $item, $comment) = @_; + + return $err->("Invalid user object passed.") unless LJ::isu($journalu); + + my $partid = $parent->{talkid}; + my $itemid = $item->{jitemid}; + my $posterid = $comment->{u} ? $comment->{u}{userid} : 0; + + # TODO: change this to be remote server specific + my $time_float = "-3"; + my $comment_time; + if ($comment->{datetime}) { + $comment_time = "'" . $comment->{datetime} . "' + INTERVAL " . $time_float . " HOUR"; + } + else { + # deleted comments + $comment_time = "'1970-01-01T00:00:00Z'"; + } + + my $jtalkid = LJ::alloc_user_counter($journalu, "T"); + return $err->("Could not generate a talkid necessary to import comment.") unless $jtalkid; + + my $errstr; + $journalu->talk2_do( + "L", $itemid, \$errstr, + "INSERT INTO talk2 ". + "(journalid, jtalkid, nodetype, nodeid, parenttalkid, posterid, datepost, state) ". + "VALUES (?,?,'L',?,?,?," . $comment_time . ",?)", + $journalu->{userid}, $jtalkid, $itemid, $partid, $posterid, $comment->{state} + ); + return $err->("error creating imported comment: " . $errstr) if ($errstr); + + $comment->{talkid} = $jtalkid; + + # add to poster's talkleft table, or the xfer place + if ($posterid) { + my $table; + my $db = LJ::get_cluster_master($comment->{u}); + + if ($db) { + # remote's cluster is writable + $table = "talkleft"; + } else { + # log to global cluster, another job will move it later. + $db = LJ::get_db_writer(); + $table = "talkleft_xfp"; + } + my $pub = $item->{'security'} eq "public" ? 1 : 0; + if ($db) { + $db->do( + "INSERT INTO $table (userid, posttime, journalid, nodetype, ". + "nodeid, jtalkid, publicitem) VALUES (?, UNIX_TIMESTAMP(" . $comment_time . "), " . + "?, 'L', ?, ?, ?)", + undef, $posterid, $journalu->{userid}, $itemid, $jtalkid, $pub); + return $err->($db->errstr) if $db->err; + } else { + # both primary and backup talkleft hosts down. can't do much now. + } + } + + $journalu->do( + "INSERT INTO talktext2 (journalid, jtalkid, subject, body) ". + "VALUES (?, ?, ?, ?)", undef, + $journalu->{userid}, $jtalkid, $comment->{subject}, + LJ::text_compress($comment->{body}) + ); + return $err->($journalu->errstr) if $journalu->err; + + my %talkprop = %{$comment->{props}}; # propname -> value + + if (%talkprop) { + my $values; + my $hash = {}; + foreach (keys %talkprop) { + my $p = LJ::get_prop("talk", $_); + next unless $p; + $hash->{$_} = $talkprop{$_}; + my $tpropid = $p->{'tpropid'}; + my $qv = $journalu->quote($talkprop{$_}); + $values .= "($journalu->{'userid'}, $jtalkid, $tpropid, $qv),"; + } + + if ($values) { + chop $values; + $journalu->do("INSERT INTO talkprop2 (journalid, jtalkid, tpropid, value) VALUES $values"); + return $err->($journalu->errstr) if $journalu->err; + } + } + + # update the "replycount" summary field of the log table + if ($comment->{state} eq 'A' || $comment->{state} eq 'F') { + LJ::replycount_do($journalu, $itemid, "incr"); + } + + # update the "hasscreened" property of the log item if needed + if ($comment->{state} eq 'S') { + LJ::Talk::screenedcount_do($journalu, $itemid, "incr"); + } + + return $comment; +} + +sub create_imported_comments { + my ($ru, $local_user, $throttle_num, $throttle_sec) = @_; + + if (!$throttle_num) { + $throttle_num = 1000; + } + if (!$throttle_sec) { + $throttle_sec = 20; + } + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + # local journal where comment is to be created + my $journalu = LJ::load_user($local_user, 1); + + $ru = LJR::Distributed::get_cu_field($ru, "cached_comments_maxid"); + $ru->{cached_comments_maxid} = 0 if not defined $ru->{cached_comments_maxid}; + + $ru = LJR::Distributed::remote_local_assoc($ru, $journalu); + return $err->("error while getting remote-local association: " . $ru->{errtext}) + if $ru->{err}; + + # check if someone deleted imported comments, + # delete inconsistent ljr_remote_comments entries and + # update corresponding ljr_remote_users.created_comments_maxid + my $sth_cc = $dbr->prepare("SELECT count(*) from ljr_remote_comments l + LEFT JOIN talk2 t on l.local_journalid = t.journalid and l.local_jtalkid = t.jtalkid + WHERE l.local_journalid = ? and t.journalid is NULL;"); + $sth_cc->execute($journalu->{"userid"}); + + my $deleted_num; + if (($deleted_num = $sth_cc->fetchrow_array) && $deleted_num && $deleted_num gt 0) { + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "DELETE ljr_remote_comments FROM + ljr_remote_comments LEFT JOIN talk2 ON + ljr_remote_comments.local_journalid = talk2.journalid AND + ljr_remote_comments.local_jtalkid = talk2.jtalkid + WHERE + ljr_remote_comments.local_journalid = ? and + talk2.journalid is NULL;", + undef, $journalu->{"userid"}); + return $err->($dbh->errstr) if $dbh->err; + + $dbh->do ("UPDATE ljr_remote_users + SET created_comments_maxid = created_comments_maxid - ? + WHERE ru_id=? and local_journalid=?", + undef, $deleted_num, $ru->{"ru_id"}, $journalu->{"userid"} + ); + return $err->($dbh->errstr) if $dbh->err; + + $ru->{"created_comments_maxid"} = $ru->{"created_comments_maxid"} - $deleted_num; + } + $sth_cc->finish; + + # if we haven't posted all the cached comments, do it now + if ($ru->{"created_comments_maxid"} < $ru->{"cached_comments_maxid"}) { + LJ::load_props("talk"); + return $err->("Can't load talkprops.") unless $LJ::CACHE_PROP{talk}; + + my $sth = $dbr->prepare(" + SELECT ljr_cached_comments.* FROM ljr_cached_comments LEFT JOIN ljr_remote_comments + ON ljr_cached_comments.cc_id = ljr_remote_comments.cc_id and + ljr_remote_comments.local_journalid = ? + WHERE ljr_cached_comments.ru_id = ? and ljr_remote_comments.cc_id is NULL + "); + $sth->execute($journalu->{"userid"}, $ru->{"ru_id"}); + + my $up; # local user which owns imported comment + my $item; # local journal entry where the comment is to be imported + my $parent; # parent comment (0 for comments to the entry) + my $comment; # comment being created + my $i = 0; # counter + + while (my $r = $sth->fetchrow_hashref) { + if ($r->{posterid}) { + $up = LJR::Distributed::get_cached_user({ru_id => $r->{ru_id}}); + + $up->{ru_id} = 0; + $up->{userid} = $r->{posterid}; + $up->{username} = ""; + $up = LJR::Distributed::get_cached_user($up); + + $up = LJR::Distributed::get_cu_field($up, "local_commenterid"); + $up = LJ::load_userid ($up->{local_commenterid}); + } + else { + $up = undef; + } + + $item = LJR::Distributed::get_local_itemid ($journalu, $r->{ru_id}, $r->{jitemid}); + + if (!$item->{itemid}) { + $warn->("Can't find corresponding local entry while importing " . + $journalu->{name} . + " (remote entry " . $r->{ru_id} . ":" . $r->{jitemid} . ")."); + next; + } + + $item = $item->{item}; + + if ($r->{"parentid"}) { + $parent = LJR::Distributed::get_local_commentid( + $journalu->{"userid"}, $r->{"ru_id"}, $r->{"parentid"}); + + if (!$parent->{"talkid"}) { + $warn->( + "Can't find corresponding parent comment while importing " . + $journalu->{"name"} . + " (remote parent id: " . $r->{"parentid"} . "), " . + "attaching to the local entry (" . $item->{"jitemid"} . ")" + ); + $parent->{"talkid"} = 0; + } + } + else { + $parent->{"talkid"} = 0; + } + + my $sth1 = $dbr->prepare("SELECT tpropid, value FROM ljr_cached_comprops WHERE cc_id=?"); + $sth1->execute($r->{cc_id}); + + my %props = (); + while (my $p = $sth1->fetchrow_hashref) { + $props{$LJ::CACHE_PROPID{talk}->{$p->{tpropid}}->{name}} = $p->{value}; + } + + $sth1->finish(); + + $comment = { + u => $up, + subject => $r->{subject}, + body => $r->{body}, + state => $r->{state}, + datetime => $r->{date}, + props => \%props, + }; + + $comment = LJR::Distributed::create_imported_comment($journalu, $parent, $item, $comment); + return $err->("error while creating imported comment: " . $comment->{errtext}) + if $comment->{err}; + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "INSERT INTO ljr_remote_comments VALUES (?,?,?)", + undef, $r->{cc_id}, $journalu->{userid}, $comment->{talkid}); + return $err->($dbh->errstr) if $dbh->err; + + $dbh->do("UPDATE ljr_remote_users + SET created_comments_maxid = ? + WHERE ru_id=? and local_journalid=?", + undef, $r->{commentid}, $ru->{ru_id}, $journalu->{userid} + ); + return $err->($dbh->errstr) if $dbh->err; + + $i = $i + 1; + if ($i % $throttle_num == 0) { + sleep $throttle_sec; + } + } + $sth->finish(); + } + + return $ru; +} + +sub cache_comment { + my ($c) = @_; + + if ($c->{id}) { + $c->{commentid} = $c->{id}; + } + if (!$c->{state}) { + $c->{state} = "A"; + } + + return $err->("cache_comment: no ru_id specified.") unless $c->{ru_id}; + return $err->("cache_comment: no comment id specified.") unless $c->{commentid}; + return $err->("cache_comment: no jitemid specified.") unless $c->{jitemid}; + + if ($c->{state} ne "D") { + return $err->("cache_comment: no body specified.") unless $c->{body}; + return $err->("cache_comment: no date specified.") unless $c->{date}; + } + else { + $c->{body} = "" unless $c->{body}; + $c->{date} = "" unless $c->{date}; + } + + if (!$c->{posterid}) { + $c->{posterid} = 0; + } + if (!$c->{parentid}) { + $c->{parentid} = 0; + } + if (!$c->{subject}) { + $c->{subject} = ""; + } + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $cc_id1 = $dbr->selectrow_array( + "SELECT cc_id FROM ljr_cached_comments " . + "WHERE ru_id=? and commentid=?", + undef, $c->{ru_id}, $c->{commentid}); + + if ($cc_id1) { + my $existing_comment = $dbr->selectrow_hashref( + "SELECT * FROM ljr_cached_comments " . + "WHERE ru_id=? and commentid=?", + undef, $c->{ru_id}, $c->{commentid}); + + # it just works (somehow clears some UTF8 flag) + $c->{body} = pack('C*', unpack('C*', $c->{body})) + if $c->{body}; + $c->{subject} = pack('C*', unpack('C*', $c->{subject})) + if $c->{subject}; + + if ( + $c->{jitemid} != $existing_comment->{jitemid} || + $c->{parentid} != $existing_comment->{parentid} || + $c->{subject} ne $existing_comment->{subject} || + $c->{body} ne $existing_comment->{body} || + $c->{date} ne $existing_comment->{date} || + ($c->{posterid} != 0 && $c->{posterid} != $existing_comment->{posterid}) + ) { + + my $ru = LJR::Distributed::get_cached_user({ru_id => $c->{ru_id}}); + return $err->("There already exists different comment id=$c->{commentid} for user $ru->{username} (ru_id = $ru->{ru_id}).!") ; + } + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "UPDATE ljr_cached_comments " . + "SET posterid=?, state=? " . + "WHERE ru_id=? and commentid=?", + undef, $c->{posterid}, $c->{state}, $c->{ru_id}, $c->{commentid}); + return $err->($dbh->errstr) if $dbh->err; + } + else { + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + # start transaction + $dbh->begin_work; + return $err->($dbh->errstr) if $dbh->err; + + $dbh->do( + "INSERT INTO ljr_cached_comments " . + "(ru_id, commentid, posterid, state, jitemid, parentid, " . + "subject, body, date) VALUES " . + "(?,?,?,?,?,?,?,?,?)", + undef, $c->{ru_id}, $c->{commentid}, $c->{posterid}, $c->{state}, + $c->{jitemid}, $c->{parentid}, $c->{subject}, $c->{body}, $c->{date}); + return $err->($dbh, $dbh->errstr) if $dbh->err; + + # get newly cached comment id + $c->{cc_id} = $dbh->{mysql_insertid}; + + # save props + LJ::load_props("talk"); + return $err->($dbh, "Can't load talkprops.") unless $LJ::CACHE_PROP{talk}; + + if ($c->{props}) { + foreach my $k (keys %{$c->{props}}) { + if (${$LJ::CACHE_PROP{talk}}{$k}->{tpropid}) { + $dbh->do( + "INSERT INTO ljr_cached_comprops VALUES (?, ?, ?) ", + undef, + $c->{cc_id}, + ${$LJ::CACHE_PROP{talk}}{$k}->{tpropid}, + $c->{props}->{$k} + ); + return $err->($dbh, + "Error caching property \"" . $k . "\": " . $dbh->errstr) + if $dbh->err; + } + } + } + + $dbh->commit; + return $err->($dbh->errstr) if $dbh->err; + } + + return $c; +} + +# +# copied from LJ::alloc_global_counter +# +sub alloc_global_counter { + my ($dom, $recurse) = @_; + + return $err->("alloc_global_counter: invalid domain!") unless $dom =~ /^[I]$/; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $newmax; + my $uid = 0; # userid is not needed, we just use '0' + + my $rs = $dbh->do( + "UPDATE ljr_counter + SET max=LAST_INSERT_ID(max+1) WHERE journalid=? AND area=?", + undef, $uid, $dom); + + if ($rs > 0) { + $newmax = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + return $newmax; + } + + return undef if $recurse; + + # no prior counter rows - initialize one. + if ($dom eq "I") { + $newmax = 0; + } + $newmax += 0; + + $dbh->do("INSERT IGNORE INTO ljr_counter (journalid, area, max) VALUES (?,?,?)", + undef, $uid, $dom, $newmax) or return undef; + return LJR::Distributed::alloc_global_counter($dom, 1); +} + +# +# copied from LJ::User::load_identity_user +# +sub get_imported_user { + my ($ru) = @_; + + return $err->("remote_serverid is not specified.") + unless $ru->{serverid}; + return $err->("remote_username is not specified.") + unless $ru->{username}; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + $ru = LJR::Distributed::get_remote_server_byid($ru); + return $err->("Server " . $ru->{serverid} . "doesn't exist!") unless $ru->{"servername"}; + + my $serverurl = $ru->{servername}; + my $identity = $serverurl . "/users/" . $ru->{username}; + + my $uid = $dbr->selectrow_array( + "SELECT userid FROM identitymap WHERE idtype=? AND identity=?", + undef, "G", $identity); + + if (!$uid) { + my $impuser = 'imp_' . LJR::Distributed::alloc_global_counter('I'); + + $uid = LJ::create_account({ + caps => undef, + user => $impuser, + name => $impuser, + journaltype => 'I', + imported => 1, + }); + return $err->("can't create account!") unless $uid; + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "INSERT INTO identitymap (idtype, identity, userid) VALUES (?,?,?)", + undef, "G", $identity, $uid); + return $err->($dbh->errstr) if $dbh->err; + + $uid = $dbr->selectrow_array( + "SELECT userid FROM identitymap WHERE idtype=? AND identity=?", + undef, "G", $identity); + return $err->("can't get identity userid for " . $identity) unless $uid; + } + + $ru->{commenterid} = $uid; + return $ru; +} + +# +# gets ljr_cached_users field (identified with ru_id) +# +sub get_cu_field { + my ($ru, $field) = @_; + + my $truid; + if (ref($ru)) { + $truid = $ru->{ru_id} + } + else { + $truid = $ru; + } + + return $err->("get_cu_field: ru_id is not specified.") + unless $truid; + return $err->("get_cu_field: field is not specified.") + unless $field; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $tvalue = $dbr->selectrow_array( + "SELECT $field FROM ljr_cached_users " . + "WHERE ru_id=?", undef, $truid); + + if (ref($ru)) { + $ru->{$field} = $tvalue; + return $ru; + } + else { + return $tvalue; + } +} + +# +# currently overwrites everything. maybe it shouldn't. +# +sub set_cu_field { + my ($ru, $field, $value) = @_; + + return $err->("set_cu_field: no ru_id in ru hashref.") + unless $ru->{ru_id}; + return $err->("set_cu_field: field is not specified (ru_id = $ru->{ru_id}).") + unless $field; + return $err->("set_cu_field: field value is not specified (field = $field).") + unless defined($value); + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $existing_field_value = $dbr->selectrow_array( + "SELECT $field FROM ljr_cached_users WHERE ru_id = ?", undef, $ru->{ru_id}); + + if ( + defined($existing_field_value) && defined($value) && $existing_field_value != $value || + $existing_field_value && !defined($value) || + !defined($existing_field_value) && $value + ) { + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + if ($existing_field_value) { + $warn->( + "ljr_cached_users: overwriting " . $field . " [" . $existing_field_value . "] " . + "with [ " . $value . " ] " . + "for ru_id = " . $ru->{ru_id}); + } + + $dbh->do( + "UPDATE ljr_cached_users SET $field = ? WHERE ru_id = ?", + undef, $value, $ru->{ru_id}); + return $err->("error updating ljr_cached_users.${field}: " . $dbh->errstr) if $dbh->err; + } + + $ru->{$field} = $value; + return $ru; +} + +sub match_remote_server { + my ($remote_server) = @_; + my %res = (); + + return $err->("no server name specified!") unless $remote_server; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + if ($remote_server =~ /.*\.(\w+\.\w+)\/?/) { + $remote_server = $1; + } + + my ($serverid, $servername, $servertype) = $dbr->selectrow_array( + "SELECT remote_serverid, canonical_url, blog_type FROM ljr_remote_servers " . + "WHERE canonical_url like '%" . $remote_server . "'"); + + $res{"serverid"} = $serverid; + $res{"servertype"} = $servertype; + $res{"servername"} = $servername; + return \%res; +} + +# +# name: LJR::Distributed::get_remote_server +# des: get remote server identification at the local site +# returns: $hashref->{serverid} or $hashref->{err} and $hashref->{errtext} +# args: remote_server +# des-remote_server: canonical name of the remote server +# +sub get_remote_server { + my ($remote_server) = @_; + my %res = (); + + return $err->("no server name specified!") unless $remote_server; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + # TODO: maybe we'll have to change this to support https or smth else? + # TODO: note that we'll have to change LJ::Simple also, which currently + # TODO: work only with http:// + if ($remote_server !~ /^http\:\/\//) { + $remote_server = "http://" . $remote_server; + } + + my ($serverid, $servertype) = $dbr->selectrow_array( + "SELECT remote_serverid, blog_type FROM ljr_remote_servers " . + "WHERE canonical_url=?", undef, $remote_server); + + if (!$serverid) { + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "INSERT INTO ljr_remote_servers (canonical_url) VALUES (?)", + undef, $remote_server); + return $err->($dbh->errstr) if $dbh->err; + + $serverid = $dbh->{mysql_insertid}; + return $err->("Can't get serverid!") unless $serverid; + } + + $res{"serverid"} = $serverid; + $res{"servertype"} = $servertype; + $res{"servername"} = $remote_server; + return \%res; +} + +sub get_remote_server_byid { + my ($ru) = @_; + + if ($ru->{"serverid"}) { + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + + ($ru->{"servername"}, $ru->{"servertype"}) = + $dbr->selectrow_array( + "SELECT canonical_url, blog_type " . + "FROM ljr_remote_servers WHERE remote_serverid=?", + undef, $ru->{serverid}); + } + return $ru; +} + +sub remote_local_assoc { + my ($ru, $u) = @_; + + return $err->("remote_local_assoc: no ru_id in ru hashref.") + unless $ru->{ru_id}; + return $err->("remote_local_assoc: no userid in user hashref.") + unless $u->{userid}; + + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + + my ($r) = $dbr->selectrow_array( + "SELECT count(*) FROM ljr_remote_users " . + "WHERE ru_id=? and local_journalid=?", + undef, $ru->{ru_id}, $u->{userid}); + if ($r) { + $ru->{created_comments_maxid} = $dbr->selectrow_array( + "SELECT created_comments_maxid FROM ljr_remote_users " . + "WHERE ru_id=? and local_journalid=?", + undef, $ru->{ru_id}, $u->{userid}); + + $ru->{assoc_existed} = 1; + } + else { + $ru->{assoc_existed} = 0; + $ru->{created_comments_maxid} = 0; + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "INSERT ljr_remote_users SET ru_id = ?, local_journalid = ?", + undef, $ru->{ru_id}, $u->{userid}, + ); + return $err->($dbh->errstr) if $dbh->err; + } + + return $ru; +} + +sub change_identity { + my ($dbh, $remote_serverid, $old_username, $new_username) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + + my ($serverurl, $servertype) = $dbr->selectrow_array( + "SELECT canonical_url, blog_type FROM ljr_remote_servers " . + "WHERE remote_serverid=?", undef, $remote_serverid); + return $err->("Server " . $remote_serverid . "doesn't exist!") unless $serverurl; + + my $old_identity = $serverurl . "/users/" . $old_username; + my $new_identity = $serverurl . "/users/" . $new_username; + + my $uid = $dbr->selectrow_array( + "SELECT userid FROM identitymap WHERE idtype=? AND identity=?", + undef, "G", $old_identity); + return $err->("can't get identity userid for " . $old_identity) unless ($uid); + + $dbh->do( + "UPDATE identitymap SET identity = ? WHERE userid = ?", + undef, $new_identity, $uid); + return $err->("Error changing identity: " . $dbh->errstr) if $dbh->err; + + return {'err' => 0}; +} + +# +# name: LJR::Distributed::get_cached_user +# des: get cached user hashref +# des: $ru->{ru_id} +# des: $ru->{serverid} +# des: $ru->{userid} +# des: $ru->{username} +# des: $ru->{type} +# returns: $ru or $ru->{err} and $ru->{errtext} +# args: $ru->{serverid} && ($ru->{userid} and/or $ru->{username}) +# +sub get_cached_user { + my ($ru) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + if ($ru->{'ru_id'}) { + ($ru->{'serverid'}, $ru->{'userid'}, $ru->{'username'}) = + $dbr->selectrow_array( + "SELECT remote_serverid, remote_userid, remote_username " . + "FROM ljr_cached_users WHERE ru_id=?", + undef, $ru->{'ru_id'}); + } + else { + return $err->("remote_serverid is not specified.") unless $ru->{'serverid'}; + + my $remote_type; + if ($ru->{'type'}) { + $remote_type = $ru->{'type'} + } + else { + $remote_type = "P"; + } + + if ($ru->{'username'} && $ru->{'userid'}) { + my $update_ljr_cached_users = sub { + $dbh->do( + "UPDATE ljr_cached_users + SET remote_userid = ?, remote_username = ? + WHERE ljr_cached_users.ru_id = ?", + undef, $ru->{'userid'}, $ru->{'username'}, $ru->{'ru_id'}); + return $err->($dbh, $dbh->errstr) if $dbh->err; + + $ru->{'type'} = $dbr->selectrow_array( + "SELECT remote_type FROM ljr_cached_users WHERE ru_id = ?", + undef, $ru->{'ru_id'}); + + return; + }; + + my $rename_remote_user = sub { + my ($ru_id, $old_username, $new_username) = @_; + + my $rename_seq = $dbr->selectrow_array( + "SELECT max(rename_seq) FROM ljr_remote_renamed WHERE ru_id=?", + undef, $ru_id); + + $rename_seq++; + + # save old username + $dbh->do( + "INSERT ljr_remote_renamed (ru_id, rename_seq, old_username, new_username) + VALUES (?, ?, ?, ?)", + undef, $ru_id, $rename_seq, $old_username, $new_username); + return $err->($dbh, $dbh->errstr) if $dbh->err; + + # update identitymap + my $r = change_identity($dbh, $ru->{'serverid'}, $old_username, $new_username); + return $err->($dbh, $r->{"errtext"}) if $r->{"err"}; + + return; + }; + + my $reid_remote_user = sub { + my ($remote_username, $old_ru_id, $new_ru_id) = @_; + + my $reid_seq = $dbr->selectrow_array( + "SELECT max(reid_seq) FROM ljr_remote_reided " . + "WHERE remote_serverid=? and remote_username=?", + undef, $ru->{'serverid'}, $remote_username); + + $reid_seq++; + + $dbh->do( + "INSERT INTO ljr_remote_reided (remote_serverid, remote_username, + reid_seq, old_ru_id, new_ru_id) VALUES (?, ?, ?, ?, ?)", + undef, $ru->{'serverid'}, $remote_username, $reid_seq, $old_ru_id, $new_ru_id); + return $err->($dbh, $dbh->errstr) if $dbh->err; + + return; + }; + + my ($username_ru_id, $username_userid, $username_local_commenterid) = $dbr->selectrow_array( + "SELECT ru_id, remote_userid, local_commenterid FROM ljr_cached_users " . + "WHERE remote_serverid=? and remote_username=?", + undef, $ru->{'serverid'}, $ru->{'username'}); + + my ($userid_ru_id, $userid_username, $userid_local_commenterid) = $dbr->selectrow_array( + "SELECT ru_id, remote_username, local_commenterid FROM ljr_cached_users " . + "WHERE remote_serverid=? and remote_userid=?", + undef, $ru->{'serverid'}, $ru->{'userid'}); + + my $r; + + if ($username_ru_id && $userid_ru_id) { + if ($username_userid && $userid_username) { + if ($username_ru_id ne $userid_ru_id) { + + $warn->("get_cached_user: " . + $ru->{'username'} . " points to ${username_userid}, " . + $ru->{'userid'} . " points to ${userid_username}; " . + "trying to solve."); + + $dbh->begin_work; + + $r = $reid_remote_user->($ru->{'username'}, $username_ru_id, $userid_ru_id); + return $err->("gcu1.1: " . $r->{'errtext'}) if $r->{'err'}; + + my $has_ex = 1; + my $ex_suff; + my $ex_name; + + while ($has_ex) { + $ex_name = "ex_" . $ru->{'username'} . ($ex_suff ? ("_" . $ex_suff) : ""); + + $has_ex = $dbh->selectrow_array( + "SELECT count(remote_username) FROM ljr_cached_users + WHERE remote_serverid=? and remote_username=?", + undef, $ru->{'serverid'}, $ex_name); + + $ex_suff = $ex_suff + 1; + } + + $r = $rename_remote_user->($username_ru_id, $ru->{'username'}, $ex_name); + return $err->("gcu1.2: " . $ru->{'username'} . ": " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->do( + "UPDATE ljr_cached_users SET remote_username = ? + WHERE ljr_cached_users.ru_id = ?", + undef, $ex_name, $username_ru_id); + return $err->($dbh, "gcu1.3: ${ex_name}:" . $dbh->errstr) if $dbh->err; + + $r = $rename_remote_user->($userid_ru_id, $userid_username, $ru->{'username'}); + return $err->("gcu1.4: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->do( + "UPDATE ljr_cached_users SET remote_username = ? + WHERE ljr_cached_users.ru_id = ?", + undef, $ru->{'username'}, $userid_ru_id); + return $err->($dbh, "gcu1.5: " . $dbh->errstr) if $dbh->err; + + $ru->{'ru_id'} = $userid_ru_id; + + $r = $update_ljr_cached_users->(); + return $err->("gcu1.6: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->commit; + } + else { + $ru->{'ru_id'} = $username_ru_id; + $r = $update_ljr_cached_users->(); + return $err->("gcu1.7: " . $r->{'errtext'}) if $r->{'err'}; + } + } + elsif (! $username_userid && ! $username_local_commenterid && $userid_username) { + $dbh->begin_work; + $ru->{'ru_id'} = $userid_ru_id; + + # ljr_cached_users for $ru->{'username'} doesn't have remote_userid + # it's bogus. deleting it. + $dbh->do ("DELETE FROM ljr_cached_users WHERE ru_id=?", undef, $username_ru_id); + return $err->($dbh, "gcu1.2: " . $dbh->errstr) if $dbh->err; + + if ($userid_username ne $ru->{'username'}) { + $r = $rename_remote_user->($ru->{'ru_id'}, $userid_username, $ru->{'username'}); + return $err->("gcu1.2: " . $r->{'errtext'}) if $r->{'err'}; + } + + $r = $update_ljr_cached_users->(); + return $err->("gcu1.2: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->commit; + } + else { + return $err->("ljr_cached_users inconsistency type 1 for $ru->{username} and $ru->{userid}.") + } + } + elsif ($username_ru_id) { + $dbh->begin_work; + + if ($username_userid && $username_userid ne $ru->{'userid'}) { + my $has_ex = 1; + my $ex_suff; + my $ex_name; + + while ($has_ex) { + $ex_name = "ex_" . $ru->{'username'} . ($ex_suff ? ("_" . $ex_suff) : ""); + + $has_ex = $dbr->selectrow_array( + "SELECT count(remote_username) FROM ljr_cached_users + WHERE remote_serverid=? and remote_username=?", + undef, $ru->{'serverid'}, $ex_name); + + $ex_suff = $ex_suff + 1; + } + + $r = $rename_remote_user->($username_ru_id, $ru->{'username'}, $ex_name); + return $err->("gcu2.1: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->do( + "UPDATE ljr_cached_users SET remote_username = ? + WHERE ljr_cached_users.ru_id = ?", + undef, $ex_name, $username_ru_id); + return $err->($dbh, "gcu2.2: " . $dbh->errstr) if $dbh->err; + + $dbh->do( + "INSERT INTO ljr_cached_users + (remote_serverid, remote_username, remote_userid, remote_type) + VALUES (?, ?, ?, ?)", + undef, $ru->{'serverid'}, $ru->{'username'}, $ru->{'userid'}, $remote_type); + return $err->($dbh, "gcu2.3: " . $dbh->errstr) if $dbh->err; + + $ru->{'ru_id'} = $dbh->{mysql_insertid}; + + $r = $reid_remote_user->($ru->{'username'}, $username_ru_id, $ru->{'ru_id'}); + return $err->("gcu2.4: " . $r->{'errtext'}) if $r->{'err'}; + } + else { + $ru->{'ru_id'} = $username_ru_id; + } + + $r = $update_ljr_cached_users->(); + return $err->("gcu2.5: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->commit; + } + elsif ($userid_ru_id) { + $dbh->begin_work; + $ru->{'ru_id'} = $userid_ru_id; + + if ($userid_username && $userid_username ne $ru->{'username'}) { + $r = $rename_remote_user->($ru->{'ru_id'}, $userid_username, $ru->{'username'}); + return $err->("gcu3: " . $r->{'errtext'}) if $r->{'err'}; + } + + $r = $update_ljr_cached_users->(); + return $err->("gcu3: " . $r->{'errtext'}) if $r->{'err'}; + + $dbh->commit; + } + else { + $dbh->do( + "INSERT ljr_cached_users + (remote_serverid, remote_userid, remote_username, remote_type) + VALUES (?, ?, ?, ?)", + undef, $ru->{'serverid'}, $ru->{'userid'}, $ru->{'username'}, $remote_type); + return $err->("gcu4: " . $dbh->errstr) if $dbh->err; + + $ru->{'ru_id'} = $dbh->{mysql_insertid}; + $ru->{'type'} = $remote_type; + } + } + elsif ($ru->{'username'} && !$ru->{'userid'}) { + my ($ru_id_1, $ljr_userid, $ljr_type); + + ($ru_id_1, $ljr_userid, $ljr_type) = $dbr->selectrow_array( + "SELECT ru_id, remote_userid, remote_type FROM ljr_cached_users " . + "WHERE remote_serverid=? and remote_username=?", + undef, $ru->{'serverid'}, $ru->{'username'}); + + # maybe the user was renamed at the remote site + if (!$ru_id_1) { + ($ru_id_1, $ljr_userid, $ljr_type) = $dbr->selectrow_array( + "SELECT ljr_remote_renamed.ru_id, ljr_cached_users.remote_userid, ljr_cached_users.remote_type " . + "FROM ljr_remote_renamed, ljr_cached_users " . + "WHERE ljr_remote_renamed.old_username = ? and ljr_cached_users.remote_serverid = ? " . + "and ljr_remote_renamed.ru_id = ljr_cached_users.ru_id", + undef, $ru->{'username'}, $ru->{'serverid'}); + } + + if ($ru_id_1) { + $ru->{'ru_id'} = $ru_id_1; + $ru->{'userid'} = $ljr_userid; + $ru->{'type'} = $ljr_type; + } + else { + # TODO: try to get userid from userinfo.bml + # and maybe from lj_gate + $dbh->do( + "INSERT INTO ljr_cached_users + (remote_serverid, remote_username, remote_type) + VALUES (?, ?, ?)", + undef, $ru->{'serverid'}, $ru->{'username'}, $remote_type); + return $err->($dbh->errstr) if $dbh->err; + + $ru->{'ru_id'} = $dbh->{mysql_insertid}; + $ru->{'type'} = $remote_type; + } + } + elsif ($ru->{'userid'} && !$ru->{'username'}) { + my ($ru_id_2, $ljr_username, $ljr_type) = $dbr->selectrow_array( + "SELECT ru_id, remote_username, remote_type FROM ljr_cached_users " . + "WHERE remote_serverid=? and remote_userid=?", + undef, $ru->{'serverid'}, $ru->{'userid'}); + if ($ru_id_2) { + $ru->{'ru_id'} = $ru_id_2; + $ru->{'username'} = $ljr_username; + $ru->{'type'} = $ljr_type; + } + else { + $dbh->do( + "INSERT INTO ljr_cached_users + (remote_serverid, remote_userid, remote_type) + VALUES (?, ?, ?)", + undef, $ru->{'serverid'}, $ru->{'userid'}, $remote_type); + return $err->($dbh->errstr) if $dbh->err; + + $ru->{'ru_id'} = $dbh->{mysql_insertid}; + $ru->{'type'} = $remote_type; + } + } + elsif (!$ru->{'userid'} && !$ru->{'username'}) { + return $err->("no userid and username supplied."); + } + } + + return $ru; +} + +sub get_local_commentid { + my ($local_userid, $ru_id, $remote_talkid) = @_; + my %res = (); + + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + + my $jtalkid; + my $local_user; + + if ($local_userid) { + $jtalkid = $dbr->selectrow_array( + "SELECT local_jtalkid FROM ljr_cached_comments, ljr_remote_comments " . + "WHERE ru_id = ? and commentid = ? and ljr_cached_comments.cc_id = ljr_remote_comments.cc_id " . + "and local_journalid = ?", + undef, $ru_id, $remote_talkid, $local_userid); + return $err->("Can't find remote comment (" . $ru_id . ":" . $remote_talkid . + ") for local user $local_userid.") unless $jtalkid; + } + else { + ($local_userid, $jtalkid) = $dbr->selectrow_array( + "SELECT local_journalid, local_jtalkid FROM ljr_cached_comments, ljr_remote_comments " . + "WHERE ru_id = ? and commentid = ? and ljr_cached_comments.cc_id = ljr_remote_comments.cc_id " . + "limit 1", + undef, $ru_id, $remote_talkid); + return $err->("Can't find remote comment (" . $ru_id . ":" . $remote_talkid . ")") + unless $local_userid && $jtalkid; + + $local_user = LJ::load_userid ($local_userid); + } + + $res{"journalid"} = $local_user->{"userid"}; + $res{"journalname"} = $local_user->{"user"}; + $res{"talkid"} = $jtalkid; + return \%res; +} + +# +# name: LJR::Distributed::get_local_itemid +# des: returns local itemid corresponding to remote entry +# returns: $hashref->{itemid} or $hashref->{err} and $hashref->{errtext} +# args: local_user, remote_server, remote_journal, remote_itemid +# des-local_user: user object of journal into which we're importing +# des-remote_server: remote serverid +# des-remote_journal: remote journalid +# des-remote_itemid: remote jitemid +# +sub get_local_itemid { + my ($local_user, $ru_id, $remote_itemid, $type) = @_; + my %res = (); + + my $dbr = LJ::get_db_reader(); + return $err->("No database reader available!") unless $dbr; + + $type = "I" unless $type; + + my $jitemid; + my $item; + + if ($local_user) { + # find first jitemid + $jitemid = $dbr->selectrow_array( + "SELECT local_jitemid FROM ljr_remote_entries " . + "WHERE local_journalid=? and sync_type=? and ru_id=? and remote_jitemid=?", + undef, $local_user->{"userid"}, $type, $ru_id, $remote_itemid); + } + else { + my $tid; + ($tid, $jitemid) = $dbr->selectrow_array( + "SELECT local_journalid, local_jitemid FROM ljr_remote_entries " . + "WHERE ru_id=? and sync_type=? and remote_jitemid=? limit 1", + undef, $ru_id, $type, $remote_itemid); + $local_user = LJ::load_userid ($tid); + + return $err->("Error loading user $tid") unless $local_user; + } + + # check that local entry is still there + if ($jitemid) { + $item = LJ::get_log2_row($local_user, $jitemid); + + # if it's not there then break association + if (!$item) { + $jitemid = 0; + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do( + "DELETE FROM ljr_remote_entries WHERE + local_journalid=? and sync_type=? and + ru_id=? and remote_jitemid=?", + undef, $local_user->{"userid"}, $type, $ru_id, $remote_itemid); + return $err->($dbh->errstr) if $dbh->err; + } + } + else { + $jitemid = 0; + } + + $res{"journalid"} = $local_user->{"userid"}; + $res{"journalname"} = $local_user->{"user"}; + $res{"itemid"} = $jitemid; + $res{"item"} = $item; + return \%res; +} + + +# +# name: LJR::Distributed::store_remote_itemid +# des: associates remote entry with local entry +# returns: 1 or $hashref->{err} and $hashref->{errtext} +# args: local_user, remote_server, remote_journal, remote_itemid +# des-local_user: user object of journal into which we're importing +# des-local_jitemd: local journal entry id +# des-remote_server: remote serverid +# des-remote_journal: remote journalid +# des-remote_itemid: remote jitemid +# +sub store_remote_itemid { + my ($local_user, $local_jitemid, $ru_id, $remote_itemid, $remote_htmlid, $type) = @_; + my %res = (); + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $type = "I" unless $type; + + $dbh->do("INSERT INTO ljr_remote_entries VALUES (?,?,?,?,?,?)", + undef, $local_user->{"userid"}, $local_jitemid, $ru_id, $remote_itemid, $remote_htmlid, $type); + return $err->($dbh->errstr) if $dbh->err; + + return \%res; +} + +sub remove_remote_itemid { + my ($local_user, $local_jitemid, $ru_id, $remote_itemid, $type) = @_; + my %res = (); + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + $dbh->do("delete from ljr_remote_entries where local_journalid=? and local_jitemid=? + and ru_id=? and remote_jitemid=? and sync_type=?", + undef, $local_user->{"userid"}, $local_jitemid, $ru_id, $remote_itemid, $type); + return $err->($dbh->errstr) if $dbh->err; + + return \%res; +} + +# +# get remote item id +# type: I for imported items, E for exported (gated) items +# +sub get_remote_itemid { + my ($local_journalid, $local_jitemid, $type) = @_; + my $res = {}; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + $type = "I" unless $type; + + my ($ru_id, $ritemid, $rhtmlid) = $dbr->selectrow_array( + "select ru_id, remote_jitemid, remote_htmlid from ljr_remote_entries " . + "WHERE local_journalid=? and local_jitemid=? and sync_type=?", + undef, $local_journalid, $local_jitemid, $type); + + if ($ru_id) { + $res->{"ru_id"} = $ru_id; + $res->{"ritemid"} = $ritemid; + $res->{"rhtmlid"} = $rhtmlid; + + $res = LJR::Distributed::get_cached_user($res); + return undef unless $res->{"username"}; + + $res = LJR::Distributed::get_remote_server_byid($res); + return undef unless $res->{"servername"}; + + $res->{"original_entry"} = + $res->{"servername"} . "/users/" . + $res->{"username"} . "/" . + $res->{"rhtmlid"} . ".html"; + + return $res; + } + else { + return undef; + } +} + +sub sign_imported_entry { + my ($journalid, $entryid, $event) = @_; + + my $ru = LJR::Distributed::get_remote_itemid ($journalid, $entryid); + + if ($ru && $ru->{"original_entry"}) { + $$event .= + "\n\n" . + "Imported event " . + "Original" . + ""; + } +} + +sub sign_exported_rss_entry { + my ($u, $jitemid, $anum, $event) = @_; + my $item_url = LJ::item_link($u, $jitemid, $anum); + + my $dbr = LJ::get_db_reader(); + my ($font, $color, $ljr_es_lastmod) = $dbr->selectrow_array( + "SELECT font_name, font_color FROM ljr_export_settings WHERE user=?", + undef, $u->{'user'}); + + $font = "gdLargeFont" unless $font; + $color = "blue" unless $color; + + my $img = LJR::GD::generate_number(0, $font, $color, " "); + my $padded_width = $img->width; + my $padded_height = $img->height; + #my $replycounturl = $LJ::SITEROOT . "/comments/" . $jitemid . "/" . $u->{'userid'} ; + my $ditemid = $jitemid * 256 + $anum; + my $replycounturl = $LJ::SITEROOT . "/numreplies/" . $u->{'user'} . "/" . $ditemid ; + + my $talklink = + "

    "; + $$event .= $talklink; +} + +sub sign_exported_gate_entry { + my ($u, $jitemid, $anum, $event) = @_; + my $item_url = LJ::item_link($u, $jitemid, $anum); + + my $dbr = LJ::get_db_reader(); + my ($font, $color, $ljr_es_lastmod) = $dbr->selectrow_array( + "SELECT font_name, font_color FROM ljr_export_settings WHERE user=?", + undef, $u->{'user'}); + + $font = "gdLargeFont" unless $font; + $color = "blue" unless $color; + + my $img = LJR::GD::generate_number(0, $font, $color, " "); + my $padded_width = $img->width; + my $padded_height = $img->height; + #my $replycounturl = $LJ::SITEROOT . "/comments/" . $jitemid . "/" . $u->{'userid'} ; + my $ditemid = $jitemid * 256 + $anum; + my $replycounturl = $LJ::SITEROOT . "/numreplies/" . $u->{'user'} . "/" . $ditemid ; + + my $talklink = + ""; + $$event .= $talklink; +} + +sub update_export_status { + my ($local_user, $mode, $status_text) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $u = LJ::load_user($local_user, 1); + return $err->("Invalid local user: " . $local_user) unless $u; + + my ($record_exists) = $dbr->selectrow_array( + "select count(*) from ljr_export_settings where user=? ", + undef, $local_user); + + return err->("Export is not configured for $local_user") unless $record_exists; + + if ($mode) { + $mode = 1; + } + else { + $mode = 0; + } + + $dbh->do ( + "UPDATE ljr_export_settings set enabled=?, update_time=NOW(), last_status=? WHERE user=?", + undef, $mode, $status_text, $local_user + ); + return $err->($dbh->errstr) if $dbh->err; +} + +sub update_export_settings { + my ($local_user, $ru_id, $remote_password) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $u = LJ::load_user($local_user, 1); + return $err->("Invalid local user: " . $local_user) unless $u; + + return $err->("ru_id or remote_password not specified") unless $ru_id && $remote_password; + + my ($record_exists) = $dbr->selectrow_array( + "select count(*) from ljr_export_settings where user=? ", + undef, $local_user); + + if ($record_exists) { + $dbh->do( + "UPDATE ljr_export_settings SET ru_id=?, remote_password=?, update_time=NOW() WHERE user=?", + undef, $ru_id, $remote_password, $local_user + ); + return $err->($dbh->errstr) if $dbh->err; + } + else { + $dbh->do( + "INSERT INTO ljr_export_settings " . + "(user, ru_id, remote_password, update_time) " . + "VALUES (?,?,?,NOW())", + undef, $local_user, $ru_id, $remote_password + ); + return $err->($dbh->errstr) if $dbh->err; + } + return LJR::Distributed::update_export_status($local_user, 1, "OK: Updated settings."); +} + +sub is_gated_local { + my ($username) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my ($exported) = $dbr->selectrow_array( + "select enabled from ljr_export_settings where user=?", + undef, $username); + + return $exported; +} + +sub is_gated_remote { + my ($server, $username) = @_; + + return $err->("Server and username must be specified.") unless $server && $username; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $ru = LJR::Distributed::get_remote_server($server); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{'username'} = $username; + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + my ($exported) = $dbr->selectrow_array( + "select count(*) from ljr_export_settings where ru_id=?", + undef, $ru->{'ru_id'}); + + return $exported; +} diff --git a/local/cgi-bin/LJR/GD.pm b/local/cgi-bin/LJR/GD.pm new file mode 100644 index 0000000..88e74d9 --- /dev/null +++ b/local/cgi-bin/LJR/GD.pm @@ -0,0 +1,51 @@ +use strict; +use GD::Simple; + +package LJR::GD; + +sub generate_number { + my ($num, $fontname, $fontcolor, $stuff) = @_; + + $num =~ s/^(\ +)//g; + $num =~ s/(\ +)$//g; + + my $font; + if ($fontname eq "gdTinyFont") { + $font = GD::Font->Tiny(); + } + elsif ($fontname eq "gdSmallFont") { + $font = GD::Font->Small(); + } + elsif ($fontname eq "gdLargeFont") { + $font = GD::Font->Large(); + } + elsif ($fontname eq "gdMediumBoldFont") { + $font = GD::Font->MediumBold(); + } + elsif ($fontname eq "gdGiantFont") { + $font = GD::Font->Giant(); + } + else { + $font = GD::Font->Small(); + } + + my $cell_width = $font->width; + my $cell_height = $font->height; + my $cols = length($stuff) > length($num) ? length($stuff) : length($num); + my $width = int($cols * $cell_width + $cell_width / 3); + my $height = $cell_height + 1; + my $img = GD::Simple->new($width,$height); + $img->font($font); + $img->moveTo(1,$font->height + 1); + $img->transparent("white"); + $img->bgcolor("white"); + $img->fgcolor($fontcolor); + + my $str = (length($num) < length($stuff) ? + substr($stuff, 0, length($stuff) - length($num)) : + "") . $num; + $img->string($str); + return $img; +} + +return 1; diff --git a/local/cgi-bin/LJR/Gate.pm b/local/cgi-bin/LJR/Gate.pm new file mode 100644 index 0000000..0ee75ac --- /dev/null +++ b/local/cgi-bin/LJR/Gate.pm @@ -0,0 +1,234 @@ +use strict; + +use XMLRPC::Lite; +use Digest::MD5; +use Time::Local; + +use LJR::Distributed; +use LJR::xmlrpc; +use LJR::Viewuserstandalone; + +require "$ENV{'LJHOME'}/cgi-bin/ljpoll.pl"; + +package LJR::Gate; + +$LJR::Gate::clientver = 'LJR::Gate/0.02'; + +sub Authenticate { + my ($server, $user, $pass) = @_; + + my $xmlrpc = new XMLRPC::Lite; + $xmlrpc->proxy("http://" . $server . "/interface/xmlrpc", timeout => 60); + + my $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.getchallenge"); + return $xmlrpc_ret if $xmlrpc_ret->{"err_text"}; + + my $challenge = $xmlrpc_ret->{'result'}->{'challenge'}; + my $response = Digest::MD5::md5_hex($challenge . Digest::MD5::md5_hex($pass)); + + my $xmlrpc_req = { + 'username' => $user, + 'auth_method' => 'challenge', + 'auth_challenge' => $challenge, + 'auth_response' => $response, + 'ver' => 1, + 'clientver' => $LJR::Gate::clientver, + }; + + $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.login", $xmlrpc_req); + return $xmlrpc_ret if $xmlrpc_ret->{"err_text"}; + + return $xmlrpc; +} + +sub ExportEntry { + my ($u, $req, $security, $jitemid, $anum) = @_; + + return "User [" . $u->{'user'} . "] is not gated." unless LJR::Distributed::is_gated_local($u->{'user'}); + + my $dbr = LJ::get_db_reader(); + return "Can't get database reader!" unless $dbr; + + my $r; + $r = $dbr->selectrow_hashref ( + "SELECT * FROM ljr_export_settings WHERE user=?", + undef, $u->{'user'}); + + my $ru; + $ru = LJR::Distributed::get_cached_user({ 'ru_id' => $r->{'ru_id'}}); + $ru = LJR::Distributed::get_remote_server_byid($ru); + + my $xmlrpc = new XMLRPC::Lite; + $xmlrpc->proxy($ru->{'servername'} . "/interface/xmlrpc", timeout => 60); + + my $xmlrpc_ret; + my $xmlrpc_req; + my $challenge; + my $response; + + my $real_event; + my $real_subject; + + my $last_status; + + if ($req->{'event'} !~ /\S/) { + $last_status = "removed entry."; + + $real_event = $req->{'event'}; + $real_subject = $req->{'subject'}; + } + else { + my $item_url = LJ::item_link($u, $jitemid, $anum); + $last_status = "exported entry"; + + $real_event = LJR::Viewuserstandalone::expand_ljuser_tags($req->{'event'}); + $real_subject = LJR::Viewuserstandalone::expand_ljuser_tags($req->{'subject'}); + + my $i=0; + while ($real_event =~ /lj-cut/ig) { $i++ }; + while ($real_event =~ /\/lj-cut/ig) { $i-- }; + if ($i gt 0) { + $real_event .= ""; + } + LJ::Poll::replace_polls_with_links(\$real_event); + LJ::EmbedModule->expand_entry($u, \$real_event, ('content_only' => 1)); + + unless ($req->{'props'}->{'opt_nocomments'}) { + LJR::Distributed::sign_exported_gate_entry($u, $jitemid, $anum, \$real_event); + } + } + + $security = $req->{'sequrity'} if !$security && $req->{'security'}; + $security = "public" unless $security; + + $xmlrpc_req = { + 'username' => $ru->{'username'}, + 'auth_method' => 'challenge', + 'ver' => 1, + 'clientver' => $LJR::Gate::clientver, + 'subject' => $real_subject, + 'event' => $real_event, + 'year' => $req->{'year'}, + 'mon' => $req->{'mon'}, + 'day' => $req->{'day'}, + 'hour' => $req->{'hour'}, + 'min' => $req->{'min'}, + 'security' => $security, + 'allowmask' => $req->{'allowmask'}, + 'props' => { + 'current_moodid' => $req->{'props'}->{'current_moodid'}, + 'current_mood' => $req->{'props'}->{'current_mood'}, + 'current_music' => $req->{'props'}->{'current_music'}, + 'picture_keyword' => $req->{'props'}->{'picture_keyword'}, + 'taglist' => $req->{'props'}->{'taglist'}, + 'opt_backdated' => $req->{'props'}->{'opt_backdated'}, + 'opt_preformatted' => $req->{'props'}->{'opt_preformatted'}, + 'opt_nocomments' => 1, + }, + }; + + my $is_invalid_remote_journal = sub { + my ($error_message) = @_; + if ( + $error_message =~ /Invalid password/ || + $error_message =~ /Selected journal no longer exists/ || + $error_message =~ /account is suspended/ || + $error_message =~ /Invalid username/ + ) { + return 1; + } + return 0; + }; + + my $is_invalid_remote_entry = sub { + my ($error_message) = @_; + if ($error_message =~ /Can\'t edit post from requested journal/) { + return 1; + } + return 0; + }; + + my $post_new_event = sub { + $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.getchallenge"); + return $xmlrpc_ret->{"err_text"} if $xmlrpc_ret->{"err_text"}; + $challenge = $xmlrpc_ret->{'result'}->{'challenge'}; + $response = Digest::MD5::md5_hex($challenge . Digest::MD5::md5_hex($r->{'remote_password'})); + $xmlrpc_req->{'auth_challenge'} = $challenge; + $xmlrpc_req->{'auth_response'} = $response; + + my $item_time = Time::Local::timelocal(0, $req->{'min'}, $req->{'hour'}, + $req->{'day'}, $req->{'mon'} - 1, $req->{'year'}); + + if ((time - $item_time) > 60*60*24) { + $xmlrpc_req->{'props'}->{'opt_backdated'} = 1; + } + + $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.postevent", $xmlrpc_req); + if ($xmlrpc_ret->{'err_text'}) { + if ($is_invalid_remote_journal->($xmlrpc_ret->{'err_text'})) { + $r = LJR::Distributed::update_export_status($u->{'user'}, 0, "ERROR: " . $xmlrpc_ret->{'err_text'}); + } + else { + $r = LJR::Distributed::update_export_status($u->{'user'}, 1, "ERROR: " . $xmlrpc_ret->{'err_text'}); + } + return $xmlrpc_ret->{"err_text"} . " " . ($r->{'err'} ? $r->{'errtext'} : ""); + } + + my $rhtml_id = $xmlrpc_ret->{'result'}->{'itemid'} * 256 + + $xmlrpc_ret->{'result'}->{'anum'}; + + $r = LJR::Distributed::store_remote_itemid( + $u, + $jitemid, + $ru->{'ru_id'}, + $xmlrpc_ret->{'result'}->{'itemid'}, + $rhtml_id, + "E" + ); + return + "store_remote_itemid: " . $u->{'user'} . "," . + $jitemid . "," . $ru->{'ru_id'} . "," . + $xmlrpc_ret->{'result'}->{'itemid'} . "," . $rhtml_id . ": " . + $r->{"errtext"} if $r->{"err"}; + }; + + my $ritem = LJR::Distributed::get_remote_itemid($u->{'userid'}, $jitemid, "E"); + if ($ritem && ($req->{'props'}->{'revnum'} || $req->{'event'} !~ /\S/)) { + $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.getchallenge"); + return $xmlrpc_ret->{"err_text"} if $xmlrpc_ret->{"err_text"}; + $challenge = $xmlrpc_ret->{'result'}->{'challenge'}; + $response = Digest::MD5::md5_hex($challenge . Digest::MD5::md5_hex($r->{'remote_password'})); + $xmlrpc_req->{'auth_challenge'} = $challenge; + $xmlrpc_req->{'auth_response'} = $response; + + $xmlrpc_req->{'itemid'} = $ritem->{'ritemid'}; + + $xmlrpc_ret = LJR::xmlrpc::xmlrpc_call($xmlrpc, "LJ.XMLRPC.editevent", $xmlrpc_req); + if ($xmlrpc_ret->{'err_text'}) { + if ($is_invalid_remote_entry->($xmlrpc_ret->{'err_text'})) { + LJR::Distributed::remove_remote_itemid($u, $jitemid, $ru->{'ru_id'}, $ritem->{'ritemid'}, "E"); + my $errmsg = $post_new_event->(); + return $errmsg if $errmsg; + } + elsif ($is_invalid_remote_journal->($xmlrpc_ret->{'err_text'})) { + $r = LJR::Distributed::update_export_status($u->{'user'}, 0, "ERROR: " . $xmlrpc_ret->{'err_text'}); + return $xmlrpc_ret->{"err_text"} . " " . ($r->{'err'} ? $r->{'errtext'} : ""); + } + $r = LJR::Distributed::update_export_status($u->{'user'}, 1, "ERROR: " . $xmlrpc_ret->{'err_text'}); + return $xmlrpc_ret->{"err_text"} . " " . ($r->{'err'} ? $r->{'errtext'} : ""); + } + if ($req->{'event'} !~ /\S/) { + LJR::Distributed::remove_remote_itemid($u, $jitemid, $ru->{'ru_id'}, $ritem->{'ritemid'}, "E"); + } + + } + else { + my $errmsg = $post_new_event->(); + return $errmsg if $errmsg; + } + + $r = LJR::Distributed::update_export_status($u->{'user'}, 1, "OK: $last_status"); + return $r->{'errtext'} if $r->{'err'}; + + return; +} diff --git a/local/cgi-bin/LJR/Viewuser.pm b/local/cgi-bin/LJR/Viewuser.pm new file mode 100755 index 0000000..9b369ae --- /dev/null +++ b/local/cgi-bin/LJR/Viewuser.pm @@ -0,0 +1,241 @@ +package LJR::Viewuser; + +use strict; +use Carp; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use DBI; +use DBI::Role; +use DBIx::StateKeeper; + +# A function to canonicalize sitename: take one of the possible +# abbreviations for a given known site, and returns the siteid +# from the list. Otherwise, assume that abbreivation is actually the +# full URL, and return it "as is", without the possible leading http://. +# +# We check the known servers database for "site=servername" or "site +# contains serverurl without the leading www"; make additional +# explicit matchings if necessary (presently none are necessary), et +# voila. +# + +sub canonical_sitenum { + my ($site)=@_; + +# Cut away leading http:// + $site =~ s|http://(.*)|$1|; + + my $dbh = LJ::get_db_reader(); + my $sth = $dbh->prepare( + "SELECT serverid FROM alienservers WHERE servername=?" + ); + + $sth->execute($site); + return LJ::error($dbh) if $dbh->err; +# +# Match $site=servername (e.g. "LJ") +# + if ($sth->rows) { + my ($guu) = $sth->fetchrow_array; + return $guu; + } + $sth->finish; + + $sth = $dbh->prepare( + "SELECT serverid, REPLACE(serverurl, 'www.', '') FROM alienservers" + ); + $sth->execute; + return LJ::error($dbh) if $dbh->err; +# +# Scan all known servers and match "serverurl without www is +# contained in $site" +# + while (my ($hale, $guu) = $sth->fetchrow_array) { + if (index ($site, $guu) !=-1) { + return $hale; + } + } + + if ( (lc($site) eq "ljr") || ($site =~ m/.*${LJ::DOMAIN}.*/) ) +# +# 0 means ourselves +# + {return 0;} +# elsif ( ($site eq "LJ") || ($site =~ m/.*livejournal\.com.*/) ) +# {return 1;} +# elsif ( ($site eq "GJ") || ($site =~ m/.*greatestjournal\.com.*/) ) +# {return 2;} +# elsif ( ($site eq "NPJ") || ($site =~ m/.*npj\.ru.*/) ) +# {return 3;} + else {return $site}; + +} + +# +# Provides a representation of a user. +# +# Format: we receive a username and a site, where site is either a +# number or a string. If a non-zero number, this is a known site; we take +# information about it from the alianservers table in the db. If +# zero, site is ourselves. If a string, we do not know anything about +# the site and treat it as an OpenID guest; we assume site is the URL. +# +# We return the HTML code. +# +# should be expand to +# ljuser( $username, {'site'=> canonical_sitenum($sitename), +# 'type'=>'P'} ) +# +# For lj comm, replace 'P' with 'C' +# + +sub ljuser { + # we assume $opts->{'site'} to be a siteid of a known site or a full + # URL of a site we do not have in db + my $user = shift; + my $opts = shift; + my $u; + my $native=0; + my $known=0; + + my $name=""; + my $url; + my $uicon; + my $cicon; + my $commdir; + my $udir; + my $lj_type; + +# If site is not given, assume native (siteid=0) + unless ($opts->{'site'}) {$opts->{'site'}=0;} + +# Check if site is a number + if($opts->{'site'} =~ m/(\d+)/) + { $known=1; } + + if($known) { + +# Site a number (known site) + + $opts->{'site'} = $opts->{'site'}+0; + + # now we've got default - $LJ::DOMAIN + + if ($opts->{'site'}==0){ + + # local + $url=$LJ::DOMAIN; + $cicon='community.gif'; # default local commicon + $uicon='userinfo.gif'; # default local usericon + $commdir='community/'; + $udir='users/'; + $lj_type='Y'; + + $native=1; + } else { + + # alien but known -- + # go to db to get $name + + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT serverurl, servername, udir, uicon, cdir, cicon, ljtype FROM alienservers WHERE serverid=?"); + $sth->execute($opts->{'site'}); + ($url, $name, $udir, $uicon, $commdir, $cicon, $lj_type) = $sth->fetchrow_array; + $native=0; + } + } else { + +# site is not a number -- unknown alien site + + $name=$opts->{'site'}; + $url=$opts->{'site'}; + $uicon='openid-profile.gif'; # default unknown alien usericon + $cicon='openid-profile.gif'; # default unknown alien commicon + $commdir=''; + $udir=''; + $lj_type='N'; + $native=0; + + } + + if ($native){ + +# If the user is local, we do some processing: check validity, check +# whether user or community, etc. + +# my $do_dynamic = $LJ::DYNAMIC_LJUSER || ($user =~ /^ext_/); +# if ($do_dynamic && ! isu($user) && ! $opts->{'type'}) { + # Try to automatically pick the user type, but still + # make something if we can't (user doesn't exist?) + $user = LJ::load_user($user) || $user; + + my $hops = 0; + + # Traverse the renames to the final journal + while (ref $user and $user->{'journaltype'} eq 'R' + and ! $opts->{'no_follow'} && $hops++ < 5) { + + LJ::load_user_props($user, 'renamedto'); + last unless length $user->{'renamedto'}; + $user = LJ::load_user($user->{'renamedto'}); + + } +# } + + if (LJ::isu($user)) { + $u = $user; + $opts->{'type'} = $user->{'journaltype'}; + # Mark accounts as deleted that aren't visible, memorial, or locked + $opts->{'del'} = $user->{'statusvis'} ne 'V' && + $user->{'statusvis'} ne 'M' && + $user->{'statusvis'} ne 'L'; + $user = $user->{'user'}; + } + } + + +# End of local-specific part + + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::IMGPREFIX; + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + my $make_tag = sub { + my ($s, $n, $fil, $dir) = @_; + $n = lc ($n); + + if ($n eq ""){ + return "[info]$user"; + } else { + if ($lj_type eq 'Y') { + +# If the site is known and has an lj-type engine, then we now how to +# refer to userinfo; make the info icon link to this + + return "[info]$user\@$n"; + } elsif ($known) { + +# If not lj-type, but known, let the info icon link to the user journal + + return "[info]$user\@$n"; + } else { + +# Unknown site. Treat as openid + + return "[info]$user [$n]"; + } + } + }; + + if ($opts->{'type'} eq 'C') { + return $make_tag->( $url, $name, $cicon, $commdir); + } elsif ($opts->{'type'} eq 'Y') { + return $make_tag->( $url, $name, 'syndicated.gif', 'users/'); + } elsif ($opts->{'type'} eq 'N') { + return $make_tag->( $url, $name, 'newsinfo.gif', 'users/'); + } elsif ($opts->{'type'} eq 'I') { + return $u->ljuser_display($opts); + } else { + return $make_tag->( $url, $name, $uicon, $udir); + } +}; + +1; diff --git a/local/cgi-bin/LJR/Viewuserstandalone.pm b/local/cgi-bin/LJR/Viewuserstandalone.pm new file mode 100755 index 0000000..117fdb0 --- /dev/null +++ b/local/cgi-bin/LJR/Viewuserstandalone.pm @@ -0,0 +1,210 @@ +package LJR::Viewuserstandalone; + +use strict; + +# A function to canonicalize sitename: take one of the possible +# abbreviations for a given known site, and returns the siteid +# from the list. Otherwise, assume that abbreivation is actually the +# full URL, and return it "as is", without the possible leading http://. +# Right now we work case-by-case, since the number of known +# abbreviations is small. +# +# +# Known sites: +# +# 0 -- local +# 1 -- www.livejournal.com +# 2 -- greatestjournal.com +# 3 -- npj.ru +# 4 -- dreamwidth.org +# TODO: add third level domains + +sub canonical_sitenum { + my ($site)=@_; + + if ( ($site eq "LJR") || ($site =~ m/.*lj\.rossia\.org.*/) ) + {return 0;} + elsif ( ($site eq "LJ") || ($site =~ m/.*livejournal\.com.*/) ) + {return 1;} + elsif ( ($site eq "GJ") || ($site =~ m/.*greatestjournal\.com.*/) ) + {return 2;} + elsif ( ($site eq "NPJ") || ($site =~ m/.*npj\.ru.*/) ) + {return 3;} + elsif ( ($site eq "DW") || ($site eq "dw") || ($site =~ m/.*dreamwidth\.org.*/) ) + {return 4;} + else {return $site;} +} + +# +# Provides a representation of a user. +# +# Format: we receive a username and a site, where site is either a +# number or a string. If a non-zero number, this is a known site; we take +# information about it from the alianservers table in the db. If +# zero, site is ourselves. If a string, we do not know anything about +# the site and treat it as an OpenID guest; we assume site is the URL. +# +# We return the HTML code. +# +# should be expand to +# ljuser( $username, {'site'=> canonical_sitenum($sitename), +# 'type'=>'P','imgroot'=>''} ) +# +# For lj comm, replace 'P' with 'C'; 'imgroot' should be equal to the +# current value of $LJ::IMGPREFIX -- right now it is differs +# between test and production!! +# + +sub ljuser { + # we assume $opts->{'site'} to be a siteid of a known site or a full + # URL of a site we do not have in db + my $user = shift; + my $opts = shift; + my $u; + + my $name=""; + my $url; + my $uicon; + my $cicon; + my $commdir; + my $udir; + my $lj_type; + +# If site is not given, assume native (siteid=0) + unless ($opts->{'site'}) {$opts->{'site'}=0;} + +# Check if site is a number + if($opts->{'site'} =~ m/(\d+)/) { + +# Site a number (known site) + + $opts->{'site'} = $opts->{'site'}+0; + + # now we've got default - $LJ::DOMAIN + + if ($opts->{'site'}==0){ + + # local + $url='lj.rossia.org'; + $cicon='community.gif'; # default local commicon + $uicon='userinfo.gif'; # default local usericon + $commdir='community/'; + $udir='users/'; + $lj_type='Y'; + } elsif ($opts->{'site'}==1) { + # LJ + $name="LJ"; + $url='www.livejournal.com'; + $cicon='community-lj.gif'; + $uicon='userinfo-lj.gif'; + $commdir='community/'; + $udir='users/'; + $lj_type='Y'; + } elsif ($opts->{'site'}==2) { + # GJ + $name="GJ"; + $url='www.greatestjournal.com'; + $cicon='community-lj.gif'; + $uicon='userinfo-lj.gif'; + $commdir='community/'; + $udir='users/'; + $lj_type='Y'; + } elsif ($opts->{'site'}==3) { + # LJ + $name="NPJ"; + $url='www.npj.ru'; + $cicon='community-npj.gif'; + $uicon='userinfo-npj.gif'; + $commdir=''; + $udir=''; + $lj_type='N'; + } elsif ($opts->{'site'}==4) { + # DW + $name="DW"; + $url='www.dreamwidth.org'; + $cicon='community-dw.gif'; + $uicon='userinfo-dw.gif'; + $commdir='community/'; + $udir='users/'; + $lj_type='Y'; + } else { return "[Unknown LJ user tag]"; } + + } else { + +# site is not a number -- unknown alien site + + $name=$opts->{'site'}; + $url=$opts->{'site'}; + $uicon=''; # default unknown alien usericon + $cicon=''; # default unknown alien commicon + $commdir='community'; + $udir='users'; + $lj_type='N'; + } + + + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + + my $img = $opts->{'imgroot'}; + my $make_tag = sub { + my ($s, $n, $fil, $dir) = @_; + if ($n eq ""){ + return "[info]$user"; + } else { + if ($lj_type eq 'Y') { + +# If the site is known and has an lj-type engine, then we now how to +# refer to userinfo; make the info icon link to this + + return "[info]$user [$n]"; + } else { + +# If not lj-type, let the info icon link to the user journal + + return "[info]$user [$n]"; + } + } + }; + if ($opts->{'type'} eq 'C') { + return $make_tag->( $url, $name, $cicon, $commdir); + } else { + return $make_tag->( $url, $name, $uicon, $udir); + } +} + +sub expand_ljuser_tags { + + my ($string)=@_; + + return "" unless $string; + + my $imgroot='http://lj.rossia.org/img'; + + $string=~ s// + ljuser($1,{ + 'site'=>canonical_sitenum($2), + 'type'=>'P','imgroot'=>$imgroot, + }) + /egxi; + $string=~ s// + ljuser($1,{ + 'site'=>canonical_sitenum($2), + 'type'=>'C','imgroot'=>$imgroot, + }) + /egxi; + $string=~ s// + ljuser($1,{ + 'site'=>0, + 'type'=>'P','imgroot'=>$imgroot, + }) + /egxi; + $string=~ s// + ljuser($1,{ + 'site'=>0, + 'type'=>'C','imgroot'=>$imgroot, + }) + /egxi; + return $string; +} + +1; diff --git a/local/cgi-bin/LJR/ljpoll-local.pl b/local/cgi-bin/LJR/ljpoll-local.pl new file mode 100644 index 0000000..485f18a --- /dev/null +++ b/local/cgi-bin/LJR/ljpoll-local.pl @@ -0,0 +1,25 @@ +package LJ::Poll; + +use strict; + +sub replace_polls_with_links { + my ($event) = @_; + + my $dbr = LJ::get_db_reader(); + + while ($$event =~ //g) { + my $pollid = $1; + my $name = $dbr->selectrow_array("SELECT name FROM poll WHERE pollid=?", + undef, $pollid); + + if ($name) { + LJ::Poll::clean_poll(\$name); + } else { + $name = "#$pollid"; + } + + $$event =~ s!!!g; + } +} + +return 1; diff --git a/local/cgi-bin/LJR/unicode.pm b/local/cgi-bin/LJR/unicode.pm new file mode 100644 index 0000000..1ab2a57 --- /dev/null +++ b/local/cgi-bin/LJR/unicode.pm @@ -0,0 +1,53 @@ +use strict; + +package LJR::unicode; + +use XML::Parser; +use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset); + + +sub utf8ize { + my $text_in = shift; + $$text_in = pack("C*", unpack("C*", $$text_in)) if $$text_in; +} + + +sub force_utf8 { + my $xdata = shift; + my %error_lines; + my $finished = 0; + my @xlines; + my $orig_xdata = $$xdata; + + my $p1 = new XML::Parser (); + + while (!$finished) { + eval { $p1->parse($$xdata); }; + + if ($@ && $@ =~ /not\ well\-formed\ \(invalid\ token\)\ at\ line\ (\d+)\,/) { + my $error_line = $1; + $error_lines{$error_line} ++; + + if ($error_lines{$error_line} > 1) { + $$xdata = $orig_xdata; + $finished = 1; + } + else { + @xlines = split(/\n/, $$xdata); + my $output = to_utf8({ -string => $xlines[$error_line - 1], -charset => 'latin1' }); + $xlines[$error_line - 1] = $output; + $$xdata = join("\n", @xlines); + } + } + # unknown error or no error, doesn't matter + elsif ($@) { + $$xdata = $orig_xdata; + $finished = 1; + } + else { + $finished = 1; + } + } +} + +return 1; diff --git a/local/cgi-bin/LJR/xmlrpc.pm b/local/cgi-bin/LJR/xmlrpc.pm new file mode 100644 index 0000000..e8f90a7 --- /dev/null +++ b/local/cgi-bin/LJR/xmlrpc.pm @@ -0,0 +1,28 @@ +use strict; + +package LJR::xmlrpc; + +sub xmlrpc_call { + my ($xmlrpc, $method, $request) = @_; + my $res; + + if ($xmlrpc) { + $res = $xmlrpc->call ($method, $request); + + if ($res && $res->fault) { + $res->{"err_text"} = $method . ": " . "XML-RPC Error [" . $res->faultcode . "]: " . $res->faultstring; + } + elsif (!$res) { + $res->{"err_text"} = $method . ": " . "Unknown XML-RPC Error."; + } + + $res->{"result"} = $res->result; + } + else { + $res->{"err_text"} = "Invalid xmlrpc object"; + } + + return $res; +} + +return 1; diff --git a/local/cgi-bin/LWPx/ParanoidAgent.pm b/local/cgi-bin/LWPx/ParanoidAgent.pm new file mode 100755 index 0000000..ffabdeb --- /dev/null +++ b/local/cgi-bin/LWPx/ParanoidAgent.pm @@ -0,0 +1,585 @@ +package LWPx::ParanoidAgent; +require LWP::UserAgent; + +use vars qw(@ISA $VERSION); +@ISA = qw(LWP::UserAgent); +$VERSION = '1.02'; + +require HTTP::Request; +require HTTP::Response; + +use HTTP::Status (); +use strict; +use Net::DNS; +use LWP::Debug; + +sub new { + my $class = shift; + my %opts = @_; + + my $blocked_hosts = delete $opts{blocked_hosts} || []; + my $whitelisted_hosts = delete $opts{whitelisted_hosts} || []; + my $resolver = delete $opts{resolver}; + $opts{timeout} ||= 15; + + my $self = LWP::UserAgent->new( %opts ); + + $self->{'blocked_hosts'} = $blocked_hosts; + $self->{'whitelisted_hosts'} = $whitelisted_hosts; + $self->{'resolver'} = $resolver; + + $self = bless $self, $class; + return $self; +} + +# returns seconds remaining given a request +sub _time_remain { + my $self = shift; + my $req = shift; + + my $now = time(); + my $start_time = $req->{_time_begin} || $now; + return $start_time + $self->{timeout} - $now; +} + +sub _resolve { + my ($self, $host, $request, $timeout, $depth) = @_; + my $res = $self->resolver; + $depth ||= 0; + + die "CNAME recursion depth limit exceeded.\n" if $depth > 10; + die "Suspicious results from DNS lookup" if $self->_bad_host($host); + + # return the IP address if it looks like one and wasn't marked bad + return ($host) if $host =~ /^\d+\.\d+\.\d+\.\d+$/; + + my $sock = $res->bgsend($host) + or die "No sock from bgsend"; + + my $rin = ''; + vec($rin, fileno($sock), 1) = 1; + my $nf = select($rin, undef, undef, $self->_time_remain($request)); + die "DNS lookup timeout" unless $nf; + + my $packet = $res->bgread($sock) + or die "DNS bgread failure"; + $sock = undef; + + my @addr; + my $cname; + foreach my $rr ($packet->answer) { + if ($rr->type eq "A") { + die "Suspicious DNS results from A record\n" if $self->_bad_host($rr->address); + push @addr, $rr->address; + } elsif ($rr->type eq "CNAME") { + # will be checked for validity in the recursion path + $cname = $rr->cname; + } + } + + return @addr if @addr; + return () unless $cname; + return $self->_resolve($cname, $request, $timeout, $depth + 1); +} + +sub _host_list_match { + my $self = shift; + my $list_name = shift; + my $host = shift; + + foreach my $rule (@{ $self->{$list_name} }) { + if (ref $rule eq "CODE") { + return 1 if $rule->($host); + } elsif (ref $rule) { + # assume regexp + return 1 if $host =~ /$rule/; + } else { + return 1 if $host eq $rule; + } + } +} + +sub _bad_host { + my $self = shift; + my $host = lc(shift); + + return 0 if $self->_host_list_match("whitelisted_hosts", $host); + return 1 if $self->_host_list_match("blocked_hosts", $host); + return 1 if + $host =~ /^localhost$/i || # localhost is bad. even though it'd be stopped in + # a later call to _bad_host with the IP address + $host =~ /\s/i; # any whitespace is questionable + + # Let's assume it's an IP address now, and get it into 32 bits. + # Uf at any time something doesn't look like a number, then it's + # probably a hostname and we've already either whitelisted or + # blacklisted those, so we'll just say it's okay and it'll come + # back here later when the resolver finds an IP address. + my @parts = split(/\./, $host); + return 0 if @parts > 4; + + # un-octal/un-hex the parts, or return if there's a non-numeric part + my $overflow_flag = 0; + foreach (@parts) { + return 0 unless /^\d+$/ || /^0x[a-f\d]+$/; + local $SIG{__WARN__} = sub { $overflow_flag = 1; }; + $_ = oct($_) if /^0/; + } + + # a purely numeric address shouldn't overflow. + return 1 if $overflow_flag; + + my $addr; # network order packed IP address + + if (@parts == 1) { + # a - 32 bits + return 1 if + $parts[0] > 0xffffffff; + $addr = pack("N", $parts[0]); + } elsif (@parts == 2) { + # a.b - 8.24 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xffffff; + $addr = pack("N", $parts[0] << 24 | $parts[1]); + } elsif (@parts == 3) { + # a.b.c - 8.8.16 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xff || + $parts[2] > 0xffff; + $addr = pack("N", $parts[0] << 24 | $parts[1] << 16 | $parts[2]); + } else { + # a.b.c.d - 8.8.8.8 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xff || + $parts[2] > 0xff || + $parts[3] > 0xff; + $addr = pack("N", $parts[0] << 24 | $parts[1] << 16 | $parts[2] << 8 | $parts[3]); + } + + my $haddr = unpack("N", $addr); # host order IP address + return 1 if + ($haddr & 0xFF000000) == 0x00000000 || # 0.0.0.0/8 + ($haddr & 0xFF000000) == 0x0A000000 || # 10.0.0.0/8 + ($haddr & 0xFF000000) == 0x7F000000 || # 127.0.0.0/8 + ($haddr & 0xFFF00000) == 0xAC100000 || # 172.16.0.0/12 + ($haddr & 0xFFFF0000) == 0xA9FE0000 || # 169.254.0.0/16 + ($haddr & 0xFFFF0000) == 0xC0A80000 || # 192.168.0.0/16 + $haddr == 0xFFFFFFFF || # 255.255.255.255 + ($haddr & 0xF0000000) == 0xE0000000; # multicast addresses + + # as final IP address check, pass in the canonical a.b.c.d decimal form + # to the blacklisted host check to see if matches as bad there. + my $can_ip = join(".", map { ord } split //, $addr); + return 1 if $self->_host_list_match("blocked_hosts", $can_ip); + + # looks like an okay IP address + return 0; +} + +sub request { + my ($self, $req, $arg, $size, $previous) = @_; + + # walk back to the first request, and set our _time_begin to its _time_begin, or if + # we're the first, then use current time. used by LWPx::Protocol::http_paranoid + my $first_res = $previous; # previous is the previous response that invoked this request + $first_res = $first_res->previous while $first_res && $first_res->previous; + $req->{_time_begin} = $first_res ? $first_res->request->{_time_begin} : time(); + + my $host = $req->uri->host; + if ($self->_bad_host($host)) { + my $err_res = HTTP::Response->new(403, "Unauthorized access to blocked host"); + $err_res->request($req); + $err_res->header("Client-Date" => HTTP::Date::time2str(time)); + $err_res->header("Client-Warning" => "Internal response"); + $err_res->header("Content-Type" => "text/plain"); + $err_res->content("403 Unauthorized access to blocked host\n"); + return $err_res; + } + + return $self->SUPER::request($req, $arg, $size, $previous); +} + +sub redirect_ok +{ + # RFC 2616, section 10.3.2 and 10.3.3 say: + # If the 30[12] status code is received in response to a request other + # than GET or HEAD, the user agent MUST NOT automatically redirect the + # request unless it can be confirmed by the user, since this might + # change the conditions under which the request was issued. + + # Note that this routine used to be just: + # return 0 if $_[1]->method eq "POST"; return 1; + + my($self, $new_request, $response) = @_; + my $method = $response->request->method; + return 0 unless grep $_ eq $method, + @{ $self->requests_redirectable || [] }; + + if ($new_request->url->scheme eq 'file') { + $response->header("Client-Warning" => + "Can't redirect to a file:// URL!"); + return 0; + } + + $self->{'final_url'} = $new_request->uri; + + # Otherwise it's apparently okay... + return 1; +} + +# taken from LWP::UserAgent and modified slightly. (proxy support removed, +# and map http and https schemes to separate protocol handlers) +sub send_request +{ + my ($self, $request, $arg, $size) = @_; + $self->_request_sanity_check($request); + + my ($method, $url) = ($request->method, $request->uri); + + local($SIG{__DIE__}); # protect against user defined die handlers + + # Check that we have a METHOD and a URL first + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "Method missing") + unless $method; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "URL missing") + unless $url; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "URL must be absolute") + unless $url->scheme; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, + "ParanoidAgent doesn't support going through proxies. ". + "In that case, do your paranoia at your proxy instead.") + if $self->_need_proxy($url); + + my $scheme = $url->scheme; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "Only http and https are supported by ParanoidAgent") + unless $scheme eq "http" || $scheme eq "https"; + + LWP::Debug::trace("$method $url"); + + my $protocol; + + { + # Honor object-specific restrictions by forcing protocol objects + # into class LWP::Protocol::nogo. + my $x; + if($x = $self->protocols_allowed) { + if(grep lc($_) eq $scheme, @$x) { + LWP::Debug::trace("$scheme URLs are among $self\'s allowed protocols (@$x)"); + } + else { + LWP::Debug::trace("$scheme URLs aren't among $self\'s allowed protocols (@$x)"); + require LWP::Protocol::nogo; + $protocol = LWP::Protocol::nogo->new; + } + } + elsif ($x = $self->protocols_forbidden) { + if(grep lc($_) eq $scheme, @$x) { + LWP::Debug::trace("$scheme URLs are among $self\'s forbidden protocols (@$x)"); + require LWP::Protocol::nogo; + $protocol = LWP::Protocol::nogo->new; + } + else { + LWP::Debug::trace("$scheme URLs aren't among $self\'s forbidden protocols (@$x)"); + } + } + # else fall thru and create the protocol object normally + } + + unless ($protocol) { + LWP::Protocol::implementor("${scheme}_paranoid", "LWPx::Protocol::${scheme}_paranoid"); + eval "require LWPx::Protocol::${scheme}_paranoid;"; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + my $response = _new_response($request, &HTTP::Status::RC_NOT_IMPLEMENTED, $@); + return $response; + } + + $protocol = eval { LWP::Protocol::create($scheme eq "http" ? "http_paranoid" : "https_paranoid", $self) }; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + my $response = _new_response($request, &HTTP::Status::RC_NOT_IMPLEMENTED, $@); + if ($scheme eq "https") { + $response->message($response->message . " (Crypt::SSLeay not installed)"); + $response->content_type("text/plain"); + $response->content(<. +EOT +} + return $response; + } + } + + # Extract fields that will be used below + my ($timeout, $cookie_jar, $use_eval, $parse_head, $max_size) = + @{$self}{qw(timeout cookie_jar use_eval parse_head max_size)}; + + my $response; + my $proxy = undef; + if ($use_eval) { + # we eval, and turn dies into responses below + eval { + $response = $protocol->request($request, $proxy, + $arg, $size, $timeout); + }; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + $response = _new_response($request, + &HTTP::Status::RC_INTERNAL_SERVER_ERROR, + $@); + } + } + else { + $response = $protocol->request($request, $proxy, + $arg, $size, $timeout); + # XXX: Should we die unless $response->is_success ??? + } + + $response->request($request); # record request for reference + $cookie_jar->extract_cookies($response) if $cookie_jar; + $response->header("Client-Date" => HTTP::Date::time2str(time)); + return $response; +} + +# blocked hostnames, compiled patterns, or subrefs +sub blocked_hosts +{ + my $self = shift; + if (@_) { + my @hosts = @_; + $self->{'blocked_hosts'} = \@hosts; + return; + } + return @{ $self->{'blocked_hosts'} }; +} + +# whitelisted hostnames, compiled patterns, or subrefs +sub whitelisted_hosts +{ + my $self = shift; + if (@_) { + my @hosts = @_; + $self->{'whitelisted_hosts'} = \@hosts; + return; + } + return @{ $self->{'whitelisted_hosts'} }; +} + +# get/set Net::DNS resolver object +sub resolver +{ + my $self = shift; + if (@_) { + $self->{'resolver'} = shift; + require UNIVERSAL ; + die "Not a Net::DNS::Resolver object" unless + UNIVERSAL::isa($self->{'resolver'}, "Net::DNS::Resolver"); + } + return $self->{'resolver'} ||= Net::DNS::Resolver->new; +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _need_proxy +{ + my($self, $url) = @_; + $url = $HTTP::URI_CLASS->new($url) unless ref $url; + + my $scheme = $url->scheme || return; + if (my $proxy = $self->{'proxy'}{$scheme}) { + if (@{ $self->{'no_proxy'} }) { + if (my $host = eval { $url->host }) { + for my $domain (@{ $self->{'no_proxy'} }) { + if ($host =~ /\Q$domain\E$/) { + LWP::Debug::trace("no_proxy configured"); + return; + } + } + } + } + LWP::Debug::debug("Proxied to $proxy"); + return $HTTP::URI_CLASS->new($proxy); + } + LWP::Debug::debug('Not proxied'); + undef; +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _request_sanity_check { + my($self, $request) = @_; + # some sanity checking + if (defined $request) { + if (ref $request) { + Carp::croak("You need a request object, not a " . ref($request) . " object") + if ref($request) eq 'ARRAY' or ref($request) eq 'HASH' or + !$request->can('method') or !$request->can('uri'); + } + else { + Carp::croak("You need a request object, not '$request'"); + } + } + else { + Carp::croak("No request object passed in"); + } +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _new_response { + my($request, $code, $message) = @_; + my $response = HTTP::Response->new($code, $message); + $response->request($request); + $response->header("Client-Date" => HTTP::Date::time2str(time)); + $response->header("Client-Warning" => "Internal response"); + $response->header("Content-Type" => "text/plain"); + $response->content("$code $message\n"); + return $response; +} + +1; + +__END__ + +=head1 NAME + +LWPx::ParanoidAgent - subclass of LWP::UserAgent that protects you from harm + +=head1 SYNOPSIS + + require LWPx::ParanoidAgent; + + my $ua = LWPx::ParanoidAgent->new; + + # this is 10 seconds overall, from start to finish. not just between + # socket reads. and it includes all redirects. so attackers telling + # you to download from a malicious tarpit webserver can only stall + # you for $n seconds + + $ua->timeout(10); + + # setup extra block lists, in addition to the always-enforced blocking + # of private IP addresses, loopbacks, and multicast addresses + + $ua->blocked_hosts( + "foo.com", + qr/\.internal\.company\.com$/i, + sub { my $host = shift; return 1 if is_bad($host); }, + ); + + $ua->whitelisted_hosts( + "brad.lj", + qr/^192\.168\.64\.3?/, + sub { ... }, + ); + + # get/set the DNS resolver object that's used + my $resolver = $ua->resolver; + $ua->resolver(Net::DNS::Resolver->new(...)); + + # and then just like a normal LWP::UserAgent, because it is one. + my $response = $ua->get('http://search.cpan.org/'); + ... + if ($response->is_success) { + print $response->content; # or whatever + } + else { + die $response->status_line; + } + +=head1 DESCRIPTION + +The C is a class subclassing C, +but paranoid against attackers. It's to be used when you're fetching +a remote resource on behalf of a possibly malicious user. + +This class can do whatever C can (callbacks, uploads from +files, etc), except proxy support is explicitly removed, because in +that case you should do your paranoia at your proxy. + +Also, the schemes are limited to http and https, which are mapped to +C and +C, respectively, which are forked +versions of the same ones without the "_paranoid". Subclassing them +didn't look possible, as they were essentially just one huge function. + +This class protects you from connecting to internal IP ranges (unless you +whitelist them), hostnames/IPs that you blacklist, remote webserver +tarpitting your process (the timeout parameter is changed to be a global +timeout over the entire process), and all combinations of redirects and +DNS tricks to otherwise tarpit and/or connect to internal resources. + +=head1 CONSTRUCTOR + +=over 4 + +=item C + +my $ua = LWPx::ParanoidAgent->new([ %opts ]); + +In addition to any constructor options from L, you may +also set C (to an arrayref), C (also +an arrayref), and C, a Net::DNS::Resolver object. + +=back + +=head1 METHODS + +=over 4 + +=item $csr->B($net_dns_resolver) + +=item $csr->B + +Get/set the L object used to lookup hostnames. + +=item $csr->B(@host_list) + +=item $csr->B + +Get/set the the list of blocked hosts. The items in @host_list may be +compiled regular expressions (with qr//), code blocks, or scalar +literals. In any case, the thing that is match, passed in, or +compared (respectively), is all of the given hostname, given IP +address, and IP address in canonical a.b.c.d decimal notation. So if +you want to block "1.2.3.4" and the user entered it in a mix of +network/host form in a mix of decimal/octal/hex, you need only block +"1.2.3.4" and not worry about the details. + +=item $csr->B(@host_list) + +=item $csr->B + +Like blocked hosts, but matching the hosts/IPs that bypass blocking +checks. The only difference is the IP address isn't canonicalized +before being whitelisted-matched, mostly because it doesn't make sense +for somebody to enter in a good address in a subversive way. + +=back + +=head1 SEE ALSO + +See L to see how to use this class. + +=head1 WARRANTY + +This module is supplied "as-is" and comes with no warranty, expressed +or implied. It tries to protect you from harm, but maybe it will. +Maybe it will destroy your data and your servers. You'd better audit +it and send me bug reports. + +=head1 BUGS + +Maybe. See the warranty above. + +=head1 COPYRIGHT + +Copyright 2005 Brad Fitzpatrick + +Lot of code from the the base class, copyright 1995-2004 Gisle Aas. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. diff --git a/local/cgi-bin/Net/OpenID/Association.pm b/local/cgi-bin/Net/OpenID/Association.pm new file mode 100755 index 0000000..7572b2a --- /dev/null +++ b/local/cgi-bin/Net/OpenID/Association.pm @@ -0,0 +1,231 @@ +use strict; +use Carp (); + +############################################################################ +package Net::OpenID::Association; +use fields ( + 'server', # author-identity identity server endpoint + 'secret', # the secret for this association + 'handle', # the 255-character-max ASCII printable handle (33-126) + 'expiry', # unixtime, adjusted, of when this association expires + 'type', # association type + ); + +use Storable (); +use Digest::SHA1 qw(sha1); + +sub new { + my Net::OpenID::Association $self = shift; + $self = fields::new( $self ) unless ref $self; + my %opts = @_; + for my $f (qw( server secret handle expiry type )) { + $self->{$f} = delete $opts{$f}; + } + Carp::croak("unknown options: " . join(", ", keys %opts)) if %opts; + return $self; +} + +sub handle { + my $self = shift; + die if @_; + $self->{'handle'}; +} + +sub secret { + my $self = shift; + die if @_; + $self->{'secret'}; +} + +sub server { + my Net::OpenID::Association $self = shift; + Carp::croak("Too many parameters") if @_; + return $self->{server}; +} + +sub expired { + my Net::OpenID::Association $self = shift; + return time() > $self->{'expiry'}; +} + +sub usable { + my Net::OpenID::Association $self = shift; + return 0 unless $self->{'handle'} =~ /^[\x21-\x7e]{1,255}$/; + return 0 unless $self->{'expiry'} =~ /^\d+$/; + return 0 unless $self->{'secret'}; + return 0 if $self->expired; + return 1; +} + + +# return a handle for an identity server, or undef if +# no local storage/cache is available, in which case the caller +# goes into dumb consumer mode. will do a POST and allocate +# a new assoc_handle if none is found, or has expired +sub server_assoc { + my ($csr, $server) = @_; + + # closure to return undef (dumb consumer mode) and log why + my $dumb = sub { + $csr->_debug("server_assoc: dumb mode: $_[0]"); + return undef; + }; + + my $cache = $csr->cache; + return $dumb->("no_cache") unless $cache; + + # try first from cached association handle + if (my $handle = $cache->get("shandle:$server")) { + my $assoc = handle_assoc($csr, $server, $handle); + + if ($assoc && $assoc->usable) { + $csr->_debug("Found association from cache (handle=$handle)"); + return $assoc; + } + } + + # make a new association + my $dh = _default_dh(); + + my %post = ( + "openid.mode" => "associate", + "openid.assoc_type" => "HMAC-SHA1", + "openid.session_type" => "DH-SHA1", + "openid.dh_consumer_public" => OpenID::util::bi2arg($dh->pub_key), + ); + + my $req = HTTP::Request->new(POST => $server); + $req->header("Content-Type" => "application/x-www-form-urlencoded"); + $req->content(join("&", map { "$_=" . OpenID::util::eurl($post{$_}) } keys %post)); + + $csr->_debug("Associate mode request: " . $req->content); + + my $ua = $csr->ua; + my $res = $ua->request($req); + + # uh, some failure, let's go into dumb mode? + return $dumb->("http_failure_no_associate") unless $res && $res->is_success; + + my $recv_time = time(); + my $content = $res->content; + my %args = OpenID::util::parse_keyvalue($content); + $csr->_debug("Response to associate mode: [$content] parsed = " . join(",", %args)); + + return $dumb->("unknown_assoc_type") unless $args{'assoc_type'} eq "HMAC-SHA1"; + + my $stype = $args{'session_type'}; + return $dumb->("unknown_session_type") if $stype && $stype ne "DH-SHA1"; + + # protocol version 1.1 + my $expires_in = $args{'expires_in'}; + + # protocol version 1.0 (DEPRECATED) + if (! $expires_in) { + if (my $issued = OpenID::util::w3c_to_time($args{'issued'})) { + my $expiry = OpenID::util::w3c_to_time($args{'expiry'}); + my $replace_after = OpenID::util::w3c_to_time($args{'replace_after'}); + + # seconds ahead (positive) or behind (negative) the server is + $expires_in = ($replace_after || $expiry) - $issued; + } + } + + # between 1 second and 2 years + return $dumb->("bogus_expires_in") unless $expires_in > 0 && $expires_in < 63072000; + + my $ahandle = $args{'assoc_handle'}; + + my $secret; + if ($stype ne "DH-SHA1") { + $secret = OpenID::util::d64($args{'mac_key'}); + } else { + my $server_pub = OpenID::util::arg2bi($args{'dh_server_public'}); + my $dh_sec = $dh->compute_secret($server_pub); + $secret = OpenID::util::d64($args{'enc_mac_key'}) ^ sha1(OpenID::util::bi2bytes($dh_sec)); + } + return $dumb->("secret_not_20_bytes") unless length($secret) == 20; + + my %assoc = ( + handle => $ahandle, + server => $server, + secret => $secret, + type => $args{'assoc_type'}, + expiry => $recv_time + $expires_in, + ); + + my $assoc = Net::OpenID::Association->new( %assoc ); + return $dumb->("assoc_undef") unless $assoc; + + $cache->set("hassoc:$server:$ahandle", Storable::nfreeze(\%assoc)); + $cache->set("shandle:$server", $ahandle); + + return $assoc; +} + +# returns association, or undef if it can't be found +sub handle_assoc { + my ($csr, $server, $handle) = @_; + + # closure to return undef (dumb consumer mode) and log why + my $dumb = sub { + $csr->_debug("handle_assoc: dumb mode: $_[0]"); + return undef; + }; + + return $dumb->("no_handle") unless $handle; + + my $cache = $csr->cache; + return $dumb->("no_cache") unless $cache; + + my $frozen = $cache->get("hassoc:$server:$handle"); + return $dumb->("not_in_cache") unless $frozen; + + my $param = eval { Storable::thaw($frozen) }; + return $dumb->("not_a_hashref") unless ref $param eq "HASH"; + + return Net::OpenID::Association->new( %$param ); +} + +sub invalidate_handle { + my ($csr, $server, $handle) = @_; + my $cache = $csr->cache + or return; + $cache->set("hassoc:$server:$handle", ""); +} + +sub _default_dh { + my $dh = Crypt::DH->new; + $dh->p("155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443"); + $dh->g("2"); + $dh->generate_keys; + return $dh; +} + + + +1; + +__END__ + +=head1 NAME + +Net::OpenID::Association - a relationship with an identity server + +=head1 DESCRIPTION + +Internal class. + +=head1 COPYRIGHT, WARRANTY, AUTHOR + +See L for author, copyrignt and licensing information. + +=head1 SEE ALSO + +L + +L + +L + +Website: L + diff --git a/local/cgi-bin/Net/OpenID/Consumer.pm b/local/cgi-bin/Net/OpenID/Consumer.pm new file mode 100755 index 0000000..c05fa32 --- /dev/null +++ b/local/cgi-bin/Net/OpenID/Consumer.pm @@ -0,0 +1,952 @@ +# LICENSE: You're free to distribute this under the same terms as Perl itself. + +use strict; +use Carp (); +use LWP::UserAgent; +use URI::Fetch 0.02; + +############################################################################ +package Net::OpenID::Consumer; + +use vars qw($VERSION); +$VERSION = "0.12"; + +use fields ( + 'cache', # the Cache object sent to URI::Fetch + 'ua', # LWP::UserAgent instance to use + 'args', # how to get at your args + 'consumer_secret', # scalar/subref + 'required_root', # the default required_root value, or undef + 'last_errcode', # last error code we got + 'last_errtext', # last error code we got + 'debug', # debug flag or codeblock + ); + +use Net::OpenID::ClaimedIdentity; +use Net::OpenID::VerifiedIdentity; +use Net::OpenID::Association; + +use MIME::Base64 (); +use Digest::SHA1 (); +use Crypt::DH 0.05; +use Time::Local; +use HTTP::Request; + +sub new { + my Net::OpenID::Consumer $self = shift; + $self = fields::new( $self ) unless ref $self; + my %opts = @_; + + $self->{ua} = delete $opts{ua}; + $self->args ( delete $opts{args} ); + $self->cache ( delete $opts{cache} ); + $self->consumer_secret ( delete $opts{consumer_secret} ); + $self->required_root ( delete $opts{required_root} ); + + $self->{debug} = delete $opts{debug}; + + Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts; + return $self; +} + +sub cache { &_getset; } +sub consumer_secret { &_getset; } +sub required_root { &_getset; } + +sub _getset { + my Net::OpenID::Consumer $self = shift; + my $param = (caller(1))[3]; + $param =~ s/.+:://; + + if (@_) { + my $val = shift; + Carp::croak("Too many parameters") if @_; + $self->{$param} = $val; + } + return $self->{$param}; +} + +sub _debug { + my Net::OpenID::Consumer $self = shift; + return unless $self->{debug}; + + if (ref $self->{debug} eq "CODE") { + $self->{debug}->($_[0]); + } else { + print STDERR "[DEBUG Net::OpenID::Consumer] $_[0]\n"; + } +} + +# given something that can have GET arguments, returns a subref to get them: +# Apache +# Apache::Request +# CGI +# HASH of get args +# CODE returning get arg, given key + +# ... + +sub args { + my Net::OpenID::Consumer $self = shift; + + if (my $what = shift) { + Carp::croak("Too many parameters") if @_; + my $getter; + if (! ref $what){ + Carp::croak("No args defined") unless $self->{args}; + return $self->{args}->($what); + } elsif (ref $what eq "HASH") { + $getter = sub { $what->{$_[0]}; }; + } elsif (ref $what eq "CGI") { + $getter = sub { scalar $what->param($_[0]); }; + } elsif (ref $what eq "Apache") { + my %get = $what->args; + $getter = sub { $get{$_[0]}; }; + } elsif (ref $what eq "Apache::Request") { + $getter = sub { scalar $what->param($_[0]); }; + } elsif (ref $what eq "CODE") { + $getter = $what; + } else { + Carp::croak("Unknown parameter type ($what)"); + } + if ($getter) { + $self->{args} = $getter; + } + } + $self->{args}; +} + +sub ua { + my Net::OpenID::Consumer $self = shift; + $self->{ua} = shift if @_; + Carp::croak("Too many parameters") if @_; + + # make default one on first access + unless ($self->{ua}) { + my $ua = $self->{ua} = LWP::UserAgent->new; + $ua->timeout(10); + } + + $self->{ua}; +} + +sub _fail { + my Net::OpenID::Consumer $self = shift; + my ($code, $text) = @_; + + $text ||= { + 'no_identity_server' => "The provided URL doesn't declare its OpenID identity server.", + 'empty_url' => "No URL entered.", + 'bogus_url' => "Invalid URL.", + 'no_head_tag' => "URL provided doesn't seem to have a head tag.", + 'url_fetch_err' => "Error fetching the provided URL.", + }->{$code}; + + $self->{last_errcode} = $code; + $self->{last_errtext} = $text; + + $self->_debug("fail($code) $text"); + wantarray ? () : undef; +} + +sub json_err { + my Net::OpenID::Consumer $self = shift; + return OpenID::util::js_dumper({ + err_code => $self->{last_errcode}, + err_text => $self->{last_errtext}, + }); +} + +sub err { + my Net::OpenID::Consumer $self = shift; + $self->{last_errcode} . ": " . $self->{last_errtext}; +} + +sub errcode { + my Net::OpenID::Consumer $self = shift; + $self->{last_errcode}; +} + +sub errtext { + my Net::OpenID::Consumer $self = shift; + $self->{last_errtext}; +} + + +sub _get_url_contents { + my Net::OpenID::Consumer $self = shift; + my ($url, $final_url_ref, $hook) = @_; + $final_url_ref ||= do { my $dummy; \$dummy; }; + + my $ures = URI::Fetch->fetch($url, + UserAgent => $self->ua, + Cache => $self->cache, + ContentAlterHook => $hook, + ) + or return $self->_fail("url_fetch_error", "Error fetching URL: " . URI::Fetch->errstr); + + # who actually uses HTTP gone response status? uh, nobody. + if ($ures->status == URI::Fetch::URI_GONE()) { + return $self->_fail("url_gone", "URL is no longer available"); + } + + my $res = $ures->http_response; + $$final_url_ref = $res->request->uri->as_string; + + return $ures->content; +} + +sub _find_semantic_info { + my Net::OpenID::Consumer $self = shift; + my $url = shift; + my $final_url_ref = shift; + + my $trim_hook = sub { + my $htmlref = shift; + # trim everything past the body. this is in case the user doesn't + # have a head document and somebody was able to inject their own + # head. -- brad choate + $$htmlref =~ s/_get_url_contents($url, $final_url_ref, $trim_hook) or + return; + + # find content of document (notably: the first head, if an attacker + # has added others somehow) + return $self->_fail("no_head_tag", "Couldn't find OpenID servers due to no head tag") + unless $doc =~ m!]*>(.*?)!is; + my $head = $1; + + my $ret = { + 'openid.server' => undef, + 'openid.delegate' => undef, + 'foaf' => undef, + 'foaf.maker' => undef, + 'rss' => undef, + 'atom' => undef, + }; + + # analyze link/meta tags + while ($head =~ m!<(link|meta)\b([^>]+)>!g) { + my ($type, $val) = ($1, $2); + my $temp; + + # OpenID servers / delegated identities + # + if ($type eq "link" && + $val =~ /\brel=.openid\.(server|delegate)./i && ($temp = $1) && + $val =~ m!\bhref=[\"\']([^\"\']+)[\"\']!i) { + $ret->{"openid.$temp"} = $1; + next; + } + + # FOAF documents + # + if ($type eq "link" && + $val =~ m!title=.foaf.!i && + $val =~ m!rel=.meta.!i && + $val =~ m!type=.application/rdf\+xml.!i && + $val =~ m!href=[\"\']([^\"\']+)[\"\']!i) { + $ret->{"foaf"} = $1; + next; + } + + # FOAF maker info + # + if ($type eq "meta" && + $val =~ m!name=.foaf:maker.!i && + $val =~ m!content=([\'\"])(.*?)\1!i) { + $ret->{"foaf.maker"} = $2; + next; + } + + if ($type eq "meta" && + $val =~ m!name=.foaf:maker.!i && + $val =~ m!content=([\'\"])(.*?)\1!i) { + $ret->{"foaf.maker"} = $2; + next; + } + + # RSS + # + if ($type eq "link" && + $val =~ m!rel=.alternate.!i && + $val =~ m!type=.application/rss\+xml.!i && + $val =~ m!href=[\"\']([^\"\']+)[\"\']!i) { + $ret->{"rss"} = $1; + next; + } + + # Atom + # + if ($type eq "link" && + $val =~ m!rel=.alternate.!i && + $val =~ m!type=.application/atom\+xml.!i && + $val =~ m!href=[\"\']([^\"\']+)[\"\']!i) { + $ret->{"atom"} = $1; + next; + } + } + + # map the 4 entities that the spec asks for + my $emap = { + 'lt' => '<', + 'gt' => '>', + 'quot' => '"', + 'amp' => '&', + }; + foreach my $k (keys %$ret) { + next unless $ret->{$k}; + $ret->{$k} =~ s/&(\w+);/$emap->{$1} || ""/eg; + } + + $self->_debug("semantic info ($url) = " . join(", ", %$ret)); + + return $ret; +} + +sub _find_openid_server { + my Net::OpenID::Consumer $self = shift; + my $url = shift; + my $final_url_ref = shift; + + my $sem_info = $self->_find_semantic_info($url, $final_url_ref) or + return; + + return $self->_fail("no_identity_server") unless $sem_info->{"openid.server"}; + $sem_info->{"openid.server"}; +} + +# returns Net::OpenID::ClaimedIdentity +sub claimed_identity { + my Net::OpenID::Consumer $self = shift; + my $url = shift; + Carp::croak("Too many parameters") if @_; + + # trim whitespace + $url =~ s/^\s+//; + $url =~ s/\s+$//; + return $self->_fail("empty_url", "Empty URL") unless $url; + + # do basic canonicalization + $url = "http://$url" if $url && $url !~ m!^\w+://!; + return $self->_fail("bogus_url", "Invalid URL") unless $url =~ m!^https?://!i; + # add a slash, if none exists + $url .= "/" unless $url =~ m!^http://.+/!i; + + my $final_url; + + my $sem_info = $self->_find_semantic_info($url, \$final_url) or + return; + + my $id_server = $sem_info->{"openid.server"} or + return $self->_fail("no_identity_server"); + + return Net::OpenID::ClaimedIdentity->new( + identity => $final_url, + server => $id_server, + consumer => $self, + delegate => $sem_info->{'openid.delegate'}, + ); +} + +sub user_cancel { + my Net::OpenID::Consumer $self = shift; + return $self->args("openid.mode") eq "cancel"; +} + +sub user_setup_url { + my Net::OpenID::Consumer $self = shift; + my %opts = @_; + my $post_grant = delete $opts{'post_grant'}; + Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts; + return $self->_fail("bad_mode") unless $self->args("openid.mode") eq "id_res"; + + my $setup_url = $self->args("openid.user_setup_url"); + + OpenID::util::push_url_arg(\$setup_url, "openid.post_grant", $post_grant) + if $setup_url && $post_grant; + + return $setup_url; +} + +sub verified_identity { + my Net::OpenID::Consumer $self = shift; + my %opts = @_; + + my $rr = delete $opts{'required_root'} || $self->{required_root}; + Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts; + + return $self->_fail("bad_mode") unless $self->args("openid.mode") eq "id_res"; + + # the asserted identity (the delegated one, if there is one, since the protocol + # knows nothing of the original URL) + my $a_ident = $self->args("openid.identity") or return $self->_fail("no_identity"); + + my $sig64 = $self->args("openid.sig") or return $self->_fail("no_sig"); + my $returnto = $self->args("openid.return_to") or return $self->_fail("no_return_to"); + my $signed = $self->args("openid.signed"); + + my $real_ident = $self->args("oic.identity") || $a_ident; + + # check that returnto is for the right host + return $self->_fail("bogus_return_to") if $rr && $returnto !~ /^\Q$rr\E/; + + # check age/signature of return_to + my $now = time(); + { + my ($sig_time, $sig) = split(/\-/, $self->args("oic.time") || ""); + # complain if more than an hour since we sent them off + return $self->_fail("time_expired") if $sig_time < $now - 3600; + # also complain if the signature is from the future by more than 30 seconds, + # which compensates for potential clock drift between nodes in a web farm. + return $self->_fail("time_in_future") if $sig_time - 30 > $now; + # and check that the time isn't faked + my $c_secret = $self->_get_consumer_secret($sig_time); + my $good_sig = substr(OpenID::util::hmac_sha1_hex($sig_time, $c_secret), 0, 20); + return $self->_fail("time_bad_sig") unless $sig eq $good_sig; + } + + my $final_url; + my $sem_info = $self->_find_semantic_info($real_ident, \$final_url); + return $self->_fail("unexpected_url_redirect") unless $final_url eq $real_ident; + + my $server = $sem_info->{"openid.server"} or + return $self->_fail("no_identity_server"); + + # if openid.delegate was used, check that it was done correctly + if ($a_ident ne $real_ident) { + return $self->_fail("bogus_delegation") unless $sem_info->{"openid.delegate"} eq $a_ident; + } + + my $assoc_handle = $self->args("openid.assoc_handle"); + + $self->_debug("verified_identity: assoc_handle: $assoc_handle"); + my $assoc = Net::OpenID::Association::handle_assoc($self, $server, $assoc_handle); + + if ($assoc) { + $self->_debug("verified_identity: verifying with found association"); + + return $self->_fail("expired_association") + if $assoc->expired; + + # verify the token + my $token = ""; + foreach my $p (split(/,/, $signed)) { + $token .= "$p:" . $self->args("openid.$p") . "\n"; + } + + my $good_sig = OpenID::util::b64(OpenID::util::hmac_sha1($token, $assoc->secret)); + return $self->_fail("signature_mismatch") unless $sig64 eq $good_sig; + + } else { + $self->_debug("verified_identity: verifying using HTTP (dumb mode)"); + # didn't find an association. have to do dumb consumer mode + # and check it with a POST + my %post = ( + "openid.mode" => "check_authentication", + "openid.assoc_handle" => $assoc_handle, + "openid.signed" => $signed, + "openid.sig" => $sig64, + ); + + # and copy in all signed parameters that we don't already have into %post + foreach my $param (split(/,/, $signed)) { + next unless $param =~ /^\w+$/; + next if $post{"openid.$param"}; + $post{"openid.$param"} = $self->args("openid.$param"); + } + + # if the server told us our handle as bogus, let's ask in our + # check_authentication mode whether that's true + if (my $ih = $self->args("openid.invalidate_handle")) { + $post{"openid.invalidate_handle"} = $ih; + } + + my $req = HTTP::Request->new(POST => $server); + $req->header("Content-Type" => "application/x-www-form-urlencoded"); + $req->content(join("&", map { "$_=" . OpenID::util::eurl($post{$_}) } keys %post)); + + my $ua = $self->ua; + my $res = $ua->request($req); + + # uh, some failure, let's go into dumb mode? + return $self->_fail("naive_verify_failed_network") unless $res && $res->is_success; + + my $content = $res->content; + my %args = OpenID::util::parse_keyvalue($content); + + # delete the handle from our cache + if (my $ih = $args{'invalidate_handle'}) { + Net::OpenID::Association::invalidate_handle($self, $server, $ih); + } + +# bad but works. check out +# http://www.livejournal.com/community/lj_everywhere/194480.html?thread=724400#t724400 +# + if ($content !~ /error:bad_handle/) { + return $self->_fail("naive_verify_failed_return: $content") unless + $args{'is_valid'} eq "true" || # protocol 1.1 + $args{'lifetime'} > 0; # DEPRECATED protocol 1.0 + } + } + + $self->_debug("verified identity! = $real_ident"); + + # verified! + return Net::OpenID::VerifiedIdentity->new( + identity => $real_ident, + foaf => $sem_info->{"foaf"}, + foafmaker => $sem_info->{"foaf.maker"}, + rss => $sem_info->{"rss"}, + atom => $sem_info->{"atom"}, + consumer => $self, + ); +} + +sub supports_consumer_secret { 1; } + +sub _get_consumer_secret { + my Net::OpenID::Consumer $self = shift; + my $time = shift; + + my $ss; + if (ref $self->{consumer_secret} eq "CODE") { + $ss = $self->{consumer_secret}; + } elsif ($self->{consumer_secret}) { + $ss = sub { return $self->{consumer_secret}; }; + } else { + Carp::croak("You haven't defined a consumer_secret value or subref.\n"); + } + + my $sec = $ss->($time); + Carp::croak("Consumer secret too long") if length($sec) > 255; + return $sec; +} + +package OpenID::util; + +# From Digest::HMAC +sub hmac_sha1_hex { + unpack("H*", &hmac_sha1); +} +sub hmac_sha1 { + hmac($_[0], $_[1], \&Digest::SHA1::sha1, 64); +} +sub hmac { + my($data, $key, $hash_func, $block_size) = @_; + $block_size ||= 64; + $key = &$hash_func($key) if length($key) > $block_size; + + my $k_ipad = $key ^ (chr(0x36) x $block_size); + my $k_opad = $key ^ (chr(0x5c) x $block_size); + + &$hash_func($k_opad, &$hash_func($k_ipad, $data)); +} + +sub parse_keyvalue { + my $reply = shift; + my %ret; + $reply =~ s/\r//g; + foreach (split /\n/, $reply) { + next unless /^(\S+?):(.*)/; + $ret{$1} = $2; + } + return %ret; +} + +sub ejs +{ + my $a = $_[0]; + $a =~ s/[\"\'\\]/\\$&/g; + $a =~ s/\r?\n/\\n/gs; + $a =~ s/\r//; + return $a; +} + +# Data::Dumper for JavaScript +sub js_dumper { + my $obj = shift; + if (ref $obj eq "HASH") { + my $ret = "{"; + foreach my $k (keys %$obj) { + $ret .= "$k: " . js_dumper($obj->{$k}) . ","; + } + chop $ret; + $ret .= "}"; + return $ret; + } elsif (ref $obj eq "ARRAY") { + my $ret = "[" . join(", ", map { js_dumper($_) } @$obj) . "]"; + return $ret; + } else { + return $obj if $obj =~ /^\d+$/; + return "\"" . ejs($obj) . "\""; + } +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\,\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub push_url_arg { + my $uref = shift; + $$uref =~ s/[&?]$//; + my $got_qmark = ($$uref =~ /\?/); + + while (@_) { + my $key = shift; + my $value = shift; + $$uref .= $got_qmark ? "&" : ($got_qmark = 1, "?"); + $$uref .= eurl($key) . "=" . eurl($value); + } +} + +sub time_to_w3c { + my $time = shift || time(); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time); + $mon++; + $year += 1900; + + return sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", + $year, $mon, $mday, + $hour, $min, $sec); +} + +sub w3c_to_time { + my $hms = shift; + return 0 unless + $hms =~ /^(\d{4,4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/; + + my $time; + eval { + $time = Time::Local::timegm($6, $5, $4, $3, $2 - 1, $1); + }; + return 0 if $@; + return $time; +} + +sub bi2bytes { + my $bigint = shift; + die "Can't deal with negative numbers" if $bigint->is_negative; + + my $bits = $bigint->as_bin; + die unless $bits =~ s/^0b//; + + # prepend zeros to round to byte boundary, or to unset high bit + my $prepend = (8 - length($bits) % 8) || ($bits =~ /^1/ ? 8 : 0); + $bits = ("0" x $prepend) . $bits if $prepend; + + return pack("B*", $bits); +} + +sub bi2arg { + return b64(bi2bytes($_[0])); +} + +sub b64 { + my $val = MIME::Base64::encode_base64($_[0]); + $val =~ s/\s+//g; + return $val; +} + +sub d64 { + return MIME::Base64::decode_base64($_[0]); +} + +sub bytes2bi { + return Math::BigInt->new("0b" . unpack("B*", $_[0])); +} + +sub arg2bi { + return undef unless defined $_[0] and $_[0] ne ""; + # don't acccept base-64 encoded numbers over 700 bytes. which means + # those over 4200 bits. + return Math::BigInt->new("0") if length($_[0]) > 700; + return bytes2bi(MIME::Base64::decode_base64($_[0])); +} + + +__END__ + +=head1 NAME + +Net::OpenID::Consumer - library for consumers of OpenID identities + +=head1 SYNOPSIS + + use Net::OpenID::Consumer; + + my $csr = Net::OpenID::Consumer->new( + ua => LWPx::ParanoidAgent->new, + cache => Some::Cache->new, + args => $cgi, + consumer_secret => ..., + required_root => "http://site.example.com/", + ); + + # a user entered, say, "bradfitz.com" as their identity. The first + # step is to fetch that page, parse it, and get a + # Net::OpenID::ClaimedIdentity object: + + my $claimed_identity = $csr->claimed_identity("bradfitz.com"); + + # now your app has to send them at their identity server's endpoint + # to get redirected to either a positive assertion that they own + # that identity, or where they need to go to login/setup trust/etc. + + my $check_url = $claimed_identity->check_url( + return_to => "http://example.com/openid-check.app?yourarg=val", + trust_root => "http://example.com/", + ); + + # so you send the user off there, and then they come back to + # openid-check.app, then you see what the identity server said; + + if (my $setup_url = $csr->user_setup_url) { + # redirect/link/popup user to $setup_url + } elsif ($csr->user_cancel) { + # restore web app state to prior to check_url + } elsif (my $vident = $csr->verified_identity) { + my $verified_url = $vident->url; + print "You are $verified_url !"; + } else { + die "Error validating identity: " . $csr->err; + } + + +=head1 DESCRIPTION + +This is the Perl API for (the consumer half of) OpenID, a distributed +identity system based on proving you own a URL, which is then your +identity. More information is available at: + + http://www.danga.com/openid/ + +=head1 CONSTRUCTOR + +=over 4 + +=item C + +my $csr = Net::OpenID::Consumer->new([ %opts ]); + +You can set the C, C, C, C, +and C in the constructor. See the corresponding method +descriptions below. + +=back + +=head1 METHODS + +=over 4 + +=item $csr->B($user_agent) + +=item $csr->B + +Getter/setter for the LWP::UserAgent (or subclass) instance which will +be used when web donwloads are needed. It's highly recommended that +you use LWPx::ParanoidAgent, or at least read its documentation so +you're aware of why you should care. + +=item $csr->B($cache) + +=item $csr->B + +Getter/setter for the optional (but recommended!) cache instance you +want to use for storing fetched parts of pages. (identity server +public keys, and the EheadE section of user's HTML pages) + +The $cache object can be anything that has a -Eget($key) and +-Eset($key,$value) methods. See L for more +information. This cache object is just passed to L +directly. + +=item $nos->B($scalar) + +=item $nos->B($code) + +=item $code = $nos->B; ($secret) = $code->($time); + +The consumer secret is used to generate self-signed nonces for the +return_to URL, to prevent spoofing. + +In the simplest (and least secure) form, you configure a static secret +value with a scalar. If you use this method and change the scalar +value, any outstanding requests from the last 30 seconds or so will fail. + +The more robust (but more complicated) form is to supply a subref that +returns a secret based on the provided I<$time>, a unix timestamp. +And if one doesn't exist for that time, create, store and return it +(with appropriate locking so you never return different secrets for +the same time.) + +Your secret may not exceed 255 characters. + +=item $csr->B($ref) + +=item $csr->B($param) + +=item $csr->B + +Can be used in 1 of 3 ways: + +1. Setting the way which the Consumer instances obtains GET parameters: + +$csr->args( $reference ) + +Where $reference is either a HASH ref, CODE ref, Apache $r, +Apache::Request $apreq, or CGI.pm $cgi. If a CODE ref, the subref +must return the value given one argument (the parameter to retrieve) + +2. Get a paramater: + +my $foo = $csr->args("foo"); + +When given an unblessed scalar, it retrieves the value. It croaks if +you haven't defined a way to get at the parameters. + +3. Get the getter: + +my $code = $csr->args; + +Without arguments, returns a subref that returns the value given a +parameter name. + +=item $nos->B($url_prefix) + +=item $url_prefix = $nos->B + +If provided, this is the required string that all return_to URLs must +start with. If it doesn't match, it'll be considered invalid (spoofed +from another site) + +=item $csr->B($url) + +Given a user-entered $url (which could be missing http://, or have +extra whitespace, etc), returns either a Net::OpenID::ClaimedIdentity +object, or undef on failure. + +Note that this identity is NOT verified yet. It's only who the user +claims they are, but they could be lying. + +If this method returns undef, you can rely on the following errors +codes (from $csr->B) to decide what to present to the user: + +=over 8 + +=item no_identity_server + +=item empty_url + +=item bogus_url + +=item no_head_tag + +=item url_fetch_err + +=back + + +=item $csr->B( [ %opts ] ) + +Returns the URL the user must return to in order to login, setup trust, +or do whatever the identity server needs them to do in order to make +the identity assertion which they previously initiated by entering +their claimed identity URL. Returns undef if this setup URL isn't +required, in which case you should ask for the verified_identity. + +The base URL this this function returns can be modified by using the +following options in %opts: + +=over + +=item C + +What you're asking the identity server to do with the user after they +setup trust. Can be either C or C to return the user +back to the return_to URL, or close the browser window with +JavaScript. If you don't specify, the behavior is undefined (probably +the user gets a dead-end page with a link back to the return_to URL). +In any case, the identity server can do whatever it wants, so don't +depend on this. + +=back + +=item $csr->B + +Returns true if the user declined to share their identity, false +otherwise. (This function is literally one line: returns true if +"openid.mode" eq "cancel") + +It's then your job to restore your app to where it was prior to +redirecting them off to the user_setup_url, using the other query +parameters that you'd sent along in your return_to URL. + +=item $csr->B( [ %opts ] ) + +Returns a Net::OpenID::VerifiedIdentity object, or undef. +Verification includes double-checking the reported identity URL +declares the identity server, verifying the signature, etc. + +The options in %opts may contain: + +=over + +=item C + +Sets the required_root just for this request. Values returns to its +previous value afterwards. + +=back + +=item $csr->B + +Returns the last error, in form "errcode: errtext" + +=item $csr->B + +Returns the last error code. + +=item $csr->B + +Returns the last error text. + +=item $csr->B + +Returns the last error code/text in JSON format. + +=back + +=head1 COPYRIGHT + +This module is Copyright (c) 2005 Brad Fitzpatrick. +All rights reserved. + +You may distribute under the terms of either the GNU General Public +License or the Artistic License, as specified in the Perl README file. +If you need more liberal licensing terms, please contact the +maintainer. + +=head1 WARRANTY + +This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + +=head1 SEE ALSO + +OpenID website: http://www.danga.com/openid/ + +L -- part of this module + +L -- part of this module + +L -- another module, for acting like an OpenID server + +=head1 AUTHORS + +Brad Fitzpatrick diff --git a/local/cgi-bin/bml/scheme/added.variables b/local/cgi-bin/bml/scheme/added.variables new file mode 100755 index 0000000..d306874 --- /dev/null +++ b/local/cgi-bin/bml/scheme/added.variables @@ -0,0 +1,32 @@ +ljrlook.nav.create +ljrlook.nav.update +ljrlook.nav.fullupdate +ljrlook.nav.site +ljrlook.nav.news +ljrlook.nav.paidaccounts +ljrlook.nav.edit +ljrlook.nav.modify +ljrlook.nav.editinfo +ljrlook.nav.editfriends +ljrlook.nav.editjournal +ljrlook.nav.editpics +ljrlook.nav.changepassword +ljrlook.nav.communities.manage +ljrlook.nav.frills +ljrlook.nav.customize +ljrlook.nav.createstyle +ljrlook.nav.editstyle +ljrlook.nav.needhelp +ljrlook.nav.lostinfo +ljrlook.nav.support.faq +ljrlook.nav.support + +ljrlook.nav.hello +ljrlook.nav.yourjournal +ljrlook.nav.recent +ljrlook.nav.calendar +ljrlook.nav.friends +ljrlook.nav.userinfo +ljrlook.nav.memories +ljrlook.nav.logout +ljrlook.nav.login diff --git a/local/cgi-bin/bml/scheme/bluewhite.look b/local/cgi-bin/bml/scheme/bluewhite.look new file mode 100755 index 0000000..c452800 --- /dev/null +++ b/local/cgi-bin/bml/scheme/bluewhite.look @@ -0,0 +1,267 @@ +# +# Welcome to GENERIC.LOOK for the WhiteBlue scheme +# +# by.... +# Brad Fitzpatrick +# brad@danga.com +# + +######################### little stuff + +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT +SOERROR=>
    %%data%%
    +EMAILEX=>
    %%data%%
    + +######################### choices stuff + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F}

    + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + + +<?_code { + my $elhash = $_[2]; + return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'}; +} _code?> +%%head%% +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> + + + + + + + + +
    + + + + + + + +
      +'; +} +return ""; +_code?> + + + "; + } + return ""; +_code?> +
    + +
    + + + + + + + + + + + + + + + + +
    + + +
    + + +"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name
    "; + } else { + $$ret .= "$name
    "; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name
    "; + } else { + $$ret .= "{'uri'}\">$name
    "; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
    + +
    +
    +
    + +
    + +
    +%%BODY%% + +
     
    +  + 
    + + + + + + +<=PAGE + diff --git a/local/cgi-bin/bml/scheme/dystopia.look b/local/cgi-bin/bml/scheme/dystopia.look new file mode 100755 index 0000000..9b8b0bf --- /dev/null +++ b/local/cgi-bin/bml/scheme/dystopia.look @@ -0,0 +1,622 @@ +# LiveJournal.com-specific library +# +# This file is NOT licensed under the GPL. As with everything in the +# "ljcom" CVS repository, this file is the property of Danga +# Interactive and is made available to the public only as a reference +# as to the best way to modify/extend the base LiveJournal server code +# (which is licensed under the GPL). +# +# Feel free to read and learn from things in "ljcom", but don't use +# our schemes because we don't want your site looking like +# LiveJournal.com (our logo and site scheme are our identity and we +# don't want to confuse users) +# +# Instead, use/modify one of the schemes in the "livejournal" repository. +# (Ideally you'd make your own entirely) +# + +_parent=>global.look + +help=>{Ds}(<?_ml Help _ml?>) + +h1=>{D}

    %%data%% +h1/follow_choices=>{D}%%data%% + +h2=>{D}

    %%data%% + +# Banner Header: search results banner, content desriptor, etc... +bh=>{D}

    %%data%% + +grin=>{S}<grin> +hr=>{S}

    *

    + +newline=>{S}
         +p=>{DRp}
    %%data%% +p/follow_p=>{DRps}

    %%data%% + +emcolor=>{S}#a7c7e8 +emcolorlite=>{S}#d9e9f9 +altcolor1=>{S}#d9e9f9 +altcolor2=>{S}#a7c7e8 + +de=>{DRp}%%data%% + +standout<= +{DRps}

    + + + + + + + + + + + + + + +
    + / + + \
    + +%%data%% + + +
    + \ + + /
    + +
    +<=standout + +warningbar<= +{DRps}
    +%%data%% +
    +<=warningbar + +errorbar<= +{DRps}
    +%%data%% +
    +<=errorbar + +soerror=>
    %%data%%
    +emailex=>
    %%data%%
    + +######################### choices stuff + +choice=>{PRps}
    %%data1%%
    %%data3%% + +choices<= +{FRp}

    + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=choices + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + +{r}); +} +_code?> + + + + + +<?_code { + my $elhash = $_[2]; + return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'}; +} _code?> + + + + + +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> +%%head%% + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
      
    +
    /dys/logo3-lang.gif" width="122" height="52" border="0" ismap="ismap" usemap="#setlang">'; + } else { + return ''; + } +_code?> + + + + + + + + + + + + + + + + + + + + + + + +
      + +   + "; + $ret .= ' + + + +
    + LJ::get_remote()->{'user'} })); + } else { + return BML::noparse(BML::ml("dystopia.hello_anonymous")) + } +_code?> + | + | + | + | + +| {'user'}&sessid=$r->{'_session'}->{'sessid'}" . '">' . BML::ml("dystopia.nav.logout") . ''); + } + return; +_code?> +
    +
    + + BML::ml('dystopia.navhead.journal'), + 'links' => [ { 'url' => '/update.bml', + 'text' => BML::ml('dystopia.nav.updatejournal'), }, + { 'url' => "/users/$remote->{'user'}/", + 'text' => BML::ml('dystopia.nav.journalrecent'), }, + { 'url' => "/users/$remote->{'user'}/calendar", + 'text' => BML::ml('dystopia.nav.journalcalendar'), }, + { 'url' => "/users/$remote->{'user'}/friends", + 'text' => BML::ml('dystopia.nav.journalfriends'), + 'extra' => '/friends/filter.bml', }, + { 'url' => "/userinfo.bml?user=$remote->{'user'}", + 'text' => BML::ml('dystopia.nav.journalinfo'), + 'extra' => "/userinfo.bml?user=$remote->{'user'}&mode=full", + }, + { 'url' => "/tools/memories.bml?user=$remote->{'user'}", + 'text' => BML::ml('dystopia.nav.memories'), }, + { 'url' => "/editjournal.bml", + 'text' => BML::ml('dystopia.nav.editentries'), }, + ], + }; + push @nav, { 'name' => BML::ml('dystopia.navhead.settings'), + 'links' => [ { 'url' => '/manage/', + 'text' => BML::ml('dystopia.nav.manage') }, + { 'url' => '/editinfo.bml', + 'text' => BML::ml('dystopia.nav.personalinfo') }, + { 'url' => "/friends/edit.bml", + 'text' => BML::ml('dystopia.nav.editfriends'), }, + { 'url' => "/editpics.bml", + 'text' => BML::ml('dystopia.nav.editpics'), }, + { 'url' => "/changepassword.bml", + 'text' => BML::ml('dystopia.nav.editpassword'), }, + { 'url' => "/modify.bml", + 'text' => BML::ml('dystopia.nav.modifyjournal'), }, + { 'url' => "/styles/edit.bml", + 'text' => BML::ml('dystopia.nav.editstyle'), }, + ], + }; + } + else + { + push @nav, { 'name' => BML::ml('dystopia.navhead.welcome'), + 'links' => [ + { 'url' => '/login.bml', + 'text' => BML::ml('dystopia.nav.login'), }, + { 'url' => '/create.bml', + 'text' => BML::ml('dystopia.nav.createjournal'), }, + { 'url' => "/update.bml", + 'text' => BML::ml('dystopia.nav.updatejournal'), }, + ], + }; + + } + + push @nav, { 'name' => BML::ml('dystopia.navhead.findusers'), + 'links' => [ + { 'url' => '/random.bml', + 'text' => BML::ml('dystopia.nav.findrandom'), }, + $LJ::DISABLED{'directory'} ? () : + ( + { 'url' => '/directory.bml', + 'text' => BML::ml('dystopia.nav.findregion'), } + ), + { 'url' => '/community/', + 'text' => BML::ml('dystopia.nav.findcomm'), }, + { 'url' => '/interests.bml', + 'text' => BML::ml('dystopia.nav.findint'), }, + $LJ::DISABLED{'directory'} ? () : + ( + { 'url' => '/directorysearch.bml', + 'text' => BML::ml('dystopia.nav.finddir'), } + ), + ], + }; + + push @nav, { 'name' => 'LiveJournal', + 'links' => [ + { 'url' => '/download/', + 'text' => BML::ml('dystopia.nav.download'), }, + { 'url' => '/paidaccounts/', + 'text' => BML::ml('dystopia.nav.paidaccts'), }, + { 'url' => '/pay/', + 'text' => BML::ml('dystopia.nav.paymentarea'), }, + ], + }; + + push @nav, { 'name' => BML::ml('dystopia.navhead.help'), + 'links' => [ { 'url' => '/support/faq.bml', + 'text' => BML::ml('dystopia.nav.faq'), }, + { 'url' => '/support/', + 'text' => BML::ml('dystopia.nav.support'), }, + { 'url' => '/lostinfo.bml', + 'text' => BML::ml('dystopia.nav.lostinfo'), }, + { 'url' => '/developer/', + 'text' => BML::ml('dystopia.nav.developer'), }, + { 'url' => '/press/staff.bml', + 'text' => BML::ml('dystopia.nav.contact'), }, + ], + }; + + push @nav, { 'name' => BML::ml('dystopia.navhead.legal'), + 'links' => [ { 'url' => '/tos.html', + 'text' => BML::ml('dystopia.nav.legaltos'), }, + { 'url' => '/privacy.bml', + 'text' => BML::ml('dystopia.nav.legalprivacy'), }, + # { 'url' => '/legal/dmca.bml', + # 'text' => BML::ml('dystopia.nav.legaldmca'), }, + ], + }; + + + my $ret = $LJ::DYS_LEFT_TOP; + foreach my $sec (@nav) { + $ret .= ""; + } + return BML::noparse($ret); + +_code?> + + + + + + + + + +

    $sec->{'name'}
    "; + foreach my $l (@{$sec->{'links'}}) { + $ret .= "{'url'}\">$l->{'text'}"; + if ($l->{'extra'}) { + $ret .= " {'extra'}\">..."; + } + $ret .= "
    "; + } + $ret .= "

     
     
     
    +

     

    +

     

    +
    + + + +"; + } else { + $button = ""; + } + } else { + if (! $LJ::IS_SSL) { + $button = ""; + } else { + $button = ""; + } + } + + my $chal = LJ::challenge_generate(300); + return <<"END_LOGIN_BAR"; + + + + + + + +END_LOGIN_BAR + } + return; + +_code?> + + + +
    + + + + + + + + +
     $ML{'Username'}:  $ML{'Password'}:  $button
    +
    + + +
    + + + +%%pretitle%% + +%%title%%

    + +%%body%% + +

    + +
    +
    + +<=PAGE + diff --git a/local/cgi-bin/bml/scheme/global.look b/local/cgi-bin/bml/scheme/global.look new file mode 100755 index 0000000..22ea3f6 --- /dev/null +++ b/local/cgi-bin/bml/scheme/global.look @@ -0,0 +1,379 @@ +_parent=>../../lj-bml-blocks.pl + +loginboxstyle=>{Ss}background: url(/userinfo.gif) no-repeat; background-color: #fff; background-position: 0px 1px; padding-left: 18px; color: #00C; font-weight: bold; +commloginboxstyle=>{Ss}background: url(/community.gif) no-repeat; background-color: #fff; background-position: 0px 2px; padding-left: 19px; color: #00C; font-weight: bold; + +SECURITYPRIVATE=>{Ss} +SECURITYPROTECTED=>{Ss} +LJUSER=>{DRs}userinfo%%data%% +LJCOMM=>{DRs}userinfo%%data%% +LJUSERF=>{DRs}userinfo%%data%% +HELP=>{DR}(help) +INERR=>{DR}%%data%% +SOERROR=>{DR}
    %%data%%
    +EMAILEX=>
    %%data%%
    + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +NEEDLOGIN<= + h1?> + p?> +<=NEEDLOGIN + +BADINPUT<= + h1?> + p?> +<=BADINPUT + +REQUIREPOST=> + +LOAD_PAGE_INFO<= + 'Home', + 'uri' => '/', + 'match' => "^/(index\\.bml)?(\\?.*)?\$", + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.create'), + 'uri' => '/create.bml', }, + { 'name' => BML::ml('ljrlook.nav.update'), + 'uri' => '/update.bml', + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.fullupdate'), + 'uri' => '/update.bml?mode=full', } + ], + }, +# { 'name' => 'Download', +# 'uri' => '/download/', }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.site'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.news'), + 'match' => '^/news\\.bml\$', + 'uri' => '/community/ljr_news/', }, + { 'name' => BML::ml('ljrlook.nav.siteopts'), + 'uri' => '/manage/siteopts.bml', }, + { 'name' => 'Sitemap', + 'uri' => '/site/', }, + { 'name' => BML::ml('ljrlook.nav.paidaccounts'), + 'uri' => '/paidaccounts/', +# 'recursematch' => '^/paidaccounts/', +# 'children' => [ +# { 'name' => 'Is this safe?', +# 'uri' => '/paidaccounts/whysafe.bml', }, +# { 'name' => 'Progress', +# 'uri' => '/paidaccounts/progress.bml', }, +# ], + }, + { 'name' => BML::ml('ljrlook.nav.ljfif'), + 'uri' => '/users/ljr_fif/friends', }, +# { 'name' => 'To-Do list', +# 'uri' => '/todo.bml', }, +# { 'name' => 'Contributors', +# 'uri' => '/contributors.bml', }, + ], + }, +# { 'name' => 'Find Users', +# 'children' => [ +# { 'name' => 'Random!', +# 'uri' => '/random.bml', }, +# { 'name' => 'By Region', +# 'uri' => '/directory.bml', }, +# { 'name' => 'By Interest', +# 'uri' => '/interests.bml', }, +# { 'name' => 'Search', +# 'uri' => '/directorysearch.bml', } +# ], }, + { 'name' => BML::ml('ljrlook.nav.edit'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.editinfo'), + 'uri' => '/editinfo.bml', }, +# { 'name' => 'Settings', cont => 1, +# 'uri' => '/editinfo.bml', }, + { 'name' => BML::ml('ljrlook.nav.editfriends'), + 'uri' => '/friends/edit.bml', }, + { 'name' => BML::ml('ljrlook.nav.editjournal'), + 'uri' => '/editjournal.bml', }, + { 'name' => BML::ml('ljrlook.nav.editpics'), + 'uri' => '/editpics.bml', }, + { 'name' => BML::ml('ljrlook.nav.changepassword'), + 'uri' => '/changepassword.bml', }, + { 'name' => BML::ml('ljrlook.nav.modify'), + 'uri' => '/modify.bml', }, +# { 'name' => 'Import', +# 'uri' => '/import.bml' }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.communities.manage'), + 'uri' => '/community/manage.bml' + }, +# { 'name' => 'Developer Area', +# 'uri' => '/developer/', +# 'match' => "^/developer/\$", +# 'recursematch' => "^/developer/", +# 'children' => [ +# { 'name' => 'Style System', +# 'uri' => '/developer/styles.bml', +# 'children' => [ +# { 'name' => 'View Types', +# 'uri' => '/developer/views.bml', }, +# { 'name' => 'Variable List', +# 'uri' => '/developer/varlist.bml', }, +# ], +# }, +# { 'name' => 'Embedding', +# 'uri' => '/developer/embedding.bml', }, +# { 'name' => 'Protocol', +# 'uri' => '/developer/protocol.bml', +# 'children' => [ +# { 'name' => 'Mode List', +# 'uri' => '/developer/modelist.bml', } +# ], +# }, +# ], +# }, +# { 'name' => BML::ml('ljrlook.nav.frills'),#Styles,customization +# 'children' => [ + { 'name' => BML::ml('ljrlook.nav.customize'), + 'uri' => '/customize/', }, +# { 'name' => BML::ml('ljrlook.nav.createstyle'), +# 'uri' => '/createstyle.bml', }, +# { 'name' => BML::ml('ljrlook.nav.editstyle'), +# 'uri' => '/editstyle.bml', }, +# ], +# }, + { 'name' => BML::ml('ljrlook.nav.needhelp'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.lostinfo'), + 'uri' => '/lostinfo.bml', }, + { 'name' => BML::ml('ljrlook.nav.support.faq'), + 'uri' => '/support/faq.bml', }, +# { 'name' => 'Questions', +# 'uri' => '/support/faq.bml', cont => 1, }, + { 'name' => BML::ml('ljrlook.nav.support'), + 'uri' => '/support/', }, + ], + }, + ); + + my $remote = LJ::get_remote(); + my $remuser = $remote ? $remote->{'user'} : ""; + my $hello_name = $remote ? LJ::User::display_name($remote) : ""; + my $uri = BML::get_uri(); + if ($remuser ne "" && $uri ne "/logout.bml") + { + my $subdomain = $remuser; + $subdomain =~ s/_/-/g; + unshift @sidebar, { 'name' => BML::ml('ljrlook.nav.hello').", ".$hello_name."!", + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.yourjournal'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.recent'), + 'uri' => "/users/$remuser/", }, + { 'name' => BML::ml('ljrlook.nav.calendar'), + 'uri' => "/users/$remuser/calendar", }, + { 'name' => BML::ml('ljrlook.nav.friends'), + 'uri' => "/users/$remuser/friends", + 'extra' => "/friendsfilter.bml", + }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.userinfo'), + 'uri' => "/userinfo.bml?user=$remuser", }, + { 'name' => BML::ml('ljrlook.nav.memories'), + 'uri' => "/memories.bml?user=$remuser", }, + { 'name' => BML::ml('ljrlook.nav.logout'), + 'uri' => '/logout.bml', }, + ] + }; + } elsif ($uri ne "/login.bml") { + unshift @sidebar, { 'name' => BML::ml('ljrlook.nav.login'),, + 'uri' => '/login.bml', } + } + +return ""; +_code?> +<=LOAD_PAGE_INFO + +AL=>{P}%%data2%% +AWAYLINK=>{P}%%data2%% + +H1=>{D}

    %%data%%

    +H2=>{D}

    %%data%%

    + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%data%% + +GRIN=>{S}<grin> +HR=>{S}


    + +NEWLINE=>{S}
         +P=>{D}

    %%data%%

    + +STANDOUT<= +{D}
    +
    +%%data%% +
    +
    +<=STANDOUT + +ERRORBAR<= +{D}
    +
    +%%data%% +
    +
    +<=ERRORBAR + +WARNINGBAR<= +{D}
    +
    +%%data%% +
    +
    +<=WARNINGBAR + +BADCONTENT<= + h1?> + p?> +<=BADCONTENT + +DE<= +%%data%% +<=DE + +EMCOLOR=>{S}#c0c0c0 +HOTCOLOR=>{S}#ff0000 +EMCOLORLITE=>{S}#e2e2e2 +ALTCOLOR1=>{S}#eeeeee +ALTCOLOR2=>{S}#dddddd +screenedbarcolor=>{S}#d0d0d0 + +CHOICE=>{P}
    %%data1%%
    %%data3%% + +CHOICES<= +{F} + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=CHOICES + +PAGE<= +{Fp} +%%title%%%%head%% + +%%body%% + + +<=PAGE + +BREADCRUMBS<= +{Fp}[3]; # no blank crumbs + if ($crumb->[3] eq 'dynamic') { + # dynamic + unshift @ret, "$crumb->[0]"; + $count++; + } else { + # non-dynamic + unshift @ret, $count++ == 0 ? + "$ML{'crumb.'.$crumb->[3]}" : + $crumb->[1] ne '' ? + "[1]\">$ML{'crumb.'.$crumb->[3]}" : + "$ML{'crumb.'.$crumb->[3]}"; + } + } + return "
    " . join(" : ", @ret) . "
    "; +_code?> +<=BREADCRUMBS diff --git a/local/cgi-bin/bml/scheme/global.look.original b/local/cgi-bin/bml/scheme/global.look.original new file mode 100755 index 0000000..11dfe6e --- /dev/null +++ b/local/cgi-bin/bml/scheme/global.look.original @@ -0,0 +1,370 @@ +_parent=>../../lj-bml-blocks.pl + +loginboxstyle=>{Ss}background: url(/userinfo.gif) no-repeat; background-color: #fff; background-position: 0px 1px; padding-left: 18px; color: #00C; font-weight: bold; +commloginboxstyle=>{Ss}background: url(/community.gif) no-repeat; background-color: #fff; background-position: 0px 2px; padding-left: 19px; color: #00C; font-weight: bold; + +SECURITYPRIVATE=>{Ss} +SECURITYPROTECTED=>{Ss} +LJUSER=>{DRs}userinfo%%data%% +LJCOMM=>{DRs}userinfo%%data%% +LJUSERF=>{DRs}userinfo%%data%% +HELP=>{DR}(help) +INERR=>{DR}%%data%% +SOERROR=>{DR}
    %%data%%
    +EMAILEX=>
    %%data%%
    + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +NEEDLOGIN<= + h1?> + p?> +<=NEEDLOGIN + +BADINPUT<= + h1?> + p?> +<=BADINPUT + +REQUIREPOST=> + +LOAD_PAGE_INFO<= + 'Home', + 'uri' => '/', + 'match' => "^/(index\\.bml)?(\\?.*)?\$", + 'children' => [ + { 'name' => 'Create Journal', + 'uri' => '/create.bml', }, + { 'name' => 'Update', + 'uri' => '/update.bml', + 'children' => [ + { 'name' => 'Full Update', + 'uri' => '/update.bml?mode=full', } + ], + }, +# { 'name' => 'Download', +# 'uri' => '/download/', }, + ], + }, + { 'name' => 'LiveJournal', + 'children' => [ + { 'name' => 'News', + 'match' => '^/news\\.bml\$', + 'uri' => '/news.bml', }, +# { 'name' => 'Paid Accounts', +# 'uri' => '/paidaccounts/', +# 'recursematch' => '^/paidaccounts/', +# 'children' => [ +# { 'name' => 'Is this safe?', +# 'uri' => '/paidaccounts/whysafe.bml', }, +# { 'name' => 'Progress', +# 'uri' => '/paidaccounts/progress.bml', }, +# ], +# }, + { 'name' => 'To-Do list', + 'uri' => '/todo.bml', }, +# { 'name' => 'Contributors', +# 'uri' => '/contributors.bml', }, + ], + }, + { 'name' => 'Customize', + 'children' => [ + { 'name' => 'Modify Journal', + 'uri' => '/modify.bml', + 'children' => [ + { 'name' => 'Customize S2', + 'uri' => '/customize/', }, + ], + }, + { 'name' => 'Create Style', + 'uri' => '/createstyle.bml', }, + { 'name' => 'Edit Style', + 'uri' => '/editstyle.bml', }, + ], + }, + { 'name' => 'Find Users', + 'children' => [ + { 'name' => 'Random!', + 'uri' => '/random.bml', }, + { 'name' => 'By Region', + 'uri' => '/directory.bml', }, + { 'name' => 'By Interest', + 'uri' => '/interests.bml', }, + { 'name' => 'Search', + 'uri' => '/directorysearch.bml', } + ], }, + { 'name' => 'Edit ...', + 'children' => [ + { 'name' => 'Personal Info &', + 'uri' => '/editinfo.bml', }, + { 'name' => 'Settings', cont => 1, + 'uri' => '/editinfo.bml', }, + { 'name' => 'Your Friends', + 'uri' => '/editfriends.bml', }, + { 'name' => 'Old Entries', + 'uri' => '/editjournal.bml', }, + { 'name' => 'Your Pictures', + 'uri' => '/editpics.bml', }, + { 'name' => 'Your Password', + 'uri' => '/changepassword.bml', }, + ], + }, +# { 'name' => 'Developer Area', +# 'uri' => '/developer/', +# 'match' => "^/developer/\$", +# 'recursematch' => "^/developer/", +# 'children' => [ +# { 'name' => 'Style System', +# 'uri' => '/developer/styles.bml', +# 'children' => [ +# { 'name' => 'View Types', +# 'uri' => '/developer/views.bml', }, +# { 'name' => 'Variable List', +# 'uri' => '/developer/varlist.bml', }, +# ], +# }, +# { 'name' => 'Embedding', +# 'uri' => '/developer/embedding.bml', }, +# { 'name' => 'Protocol', +# 'uri' => '/developer/protocol.bml', +# 'children' => [ +# { 'name' => 'Mode List', +# 'uri' => '/developer/modelist.bml', } +# ], +# }, +# ], +# }, + { 'name' => 'Need Help?', + 'children' => [ + { 'name' => 'Lost Password?', + 'uri' => '/lostinfo.bml', }, + { 'name' => 'Freq. Asked', + 'uri' => '/support/faq.bml', }, + { 'name' => 'Questions', + 'uri' => '/support/faq.bml', cont => 1, }, + { 'name' => 'Support Area', + 'uri' => '/support/', }, + ], + }, + ); + + my $remote = LJ::get_remote(); + my $remuser = $remote ? $remote->{'user'} : ""; + my $uri = BML::get_uri(); + if ($remuser ne "" && $uri ne "/logout.bml") + { + my $subdomain = $remuser; + $subdomain =~ s/_/-/g; + unshift @sidebar, { 'name' => "Hello, $remuser!", + 'children' => [ + { 'name' => 'Your Journal', + 'children' => [ + { 'name' => 'Recent', + 'uri' => "/users/$remuser/", }, + { 'name' => 'Calendar', + 'uri' => "/users/$remuser/calendar", }, + { 'name' => 'Friends', + 'uri' => "/users/$remuser/friends", + 'extra' => "/friendsfilter.bml", + }, + ], + }, + { 'name' => 'User Info', + 'uri' => "/userinfo.bml?user=$remuser", }, + { 'name' => 'Memories', + 'uri' => "/memories.bml?user=$remuser", }, + { 'name' => 'Logout', + 'uri' => '/logout.bml', }, + ] + }; + } elsif ($uri ne "/login.bml") { + unshift @sidebar, { 'name' => "Log In", + 'uri' => '/login.bml', } + } + +return ""; +_code?> +<=LOAD_PAGE_INFO + +AL=>{P}%%data2%% +AWAYLINK=>{P}%%data2%% + +H1=>{D}

    %%data%%

    +H2=>{D}

    %%data%%

    + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%data%% + +GRIN=>{S}<grin> +HR=>{S}


    + +NEWLINE=>{S}
         +P=>{D}

    %%data%%

    + +STANDOUT<= +{D}
    +
    +%%data%% +
    +
    +<=STANDOUT + +ERRORBAR<= +{D}
    +
    +%%data%% +
    +
    +<=ERRORBAR + +WARNINGBAR<= +{D}
    +
    +%%data%% +
    +
    +<=WARNINGBAR + +BADCONTENT<= + h1?> + p?> +<=BADCONTENT + +DE<= +%%data%% +<=DE + +EMCOLOR=>{S}#c0c0c0 +HOTCOLOR=>{S}#ff0000 +EMCOLORLITE=>{S}#e2e2e2 +ALTCOLOR1=>{S}#eeeeee +ALTCOLOR2=>{S}#dddddd +screenedbarcolor=>{S}#d0d0d0 + +CHOICE=>{P}
    %%data1%%
    %%data3%% + +CHOICES<= +{F} + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=CHOICES + +PAGE<= +{Fp} +%%title%%%%head%% + +%%body%% + + +<=PAGE + +BREADCRUMBS<= +{Fp}[3]; # no blank crumbs + if ($crumb->[3] eq 'dynamic') { + # dynamic + unshift @ret, "$crumb->[0]"; + $count++; + } else { + # non-dynamic + unshift @ret, $count++ == 0 ? + "$ML{'crumb.'.$crumb->[3]}" : + $crumb->[1] ne '' ? + "[1]\">$ML{'crumb.'.$crumb->[3]}" : + "$ML{'crumb.'.$crumb->[3]}"; + } + } + return "
    " . join(" : ", @ret) . "
    "; +_code?> +<=BREADCRUMBS diff --git a/local/cgi-bin/bml/scheme/ljr.look b/local/cgi-bin/bml/scheme/ljr.look new file mode 100755 index 0000000..0ca0287 --- /dev/null +++ b/local/cgi-bin/bml/scheme/ljr.look @@ -0,0 +1,374 @@ +_parent=>../../lj-bml-blocks.pl + +loginboxstyle=>{Ss}background: url(/userinfo.gif) no-repeat; background-color: #fff; background-position: 0px 1px; padding-left: 18px; color: #00C; font-weight: bold; +commloginboxstyle=>{Ss}background: url(/community.gif) no-repeat; background-color: #fff; background-position: 0px 2px; padding-left: 19px; color: #00C; font-weight: bold; + +SECURITYPRIVATE=>{Ss} +SECURITYPROTECTED=>{Ss} +LJUSER=>{DRs}userinfo%%data%% +LJCOMM=>{DRs}userinfo%%data%% +LJUSERF=>{DRs}userinfo%%data%% +HELP=>{DR}(help) +INERR=>{DR}%%data%% +SOERROR=>{DR}
    %%data%%
    +EMAILEX=>
    %%data%%
    + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +NEEDLOGIN<= + h1?> + p?> +<=NEEDLOGIN + +BADINPUT<= + h1?> + p?> +<=BADINPUT + +REQUIREPOST=> + +LOAD_PAGE_INFO<= + 'Home', + 'uri' => '/', + 'match' => "^/(index\\.bml)?(\\?.*)?\$", + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.create'), + 'uri' => '/create.bml', }, + { 'name' => BML::ml('ljrlook.nav.update'), + 'uri' => '/update.bml', + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.fullupdate'), + 'uri' => '/update.bml?mode=full', } + ], + }, +# { 'name' => 'Download', +# 'uri' => '/download/', }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.site'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.news'), + 'match' => '^/news\\.bml\$', + 'uri' => '/community/ljr_news/', }, + { 'name' => BML::ml('ljrlook.nav.siteopts'), + 'uri' => '/manage/siteopts.bml', }, + { 'name' => BML::ml('ljrlook.nav.paidaccounts'), + 'uri' => '/paidaccounts/', +# 'recursematch' => '^/paidaccounts/', +# 'children' => [ +# { 'name' => 'Is this safe?', +# 'uri' => '/paidaccounts/whysafe.bml', }, +# { 'name' => 'Progress', +# 'uri' => '/paidaccounts/progress.bml', }, +# ], + }, + { 'name' => BML::ml('ljrlook.nav.ljfif'), + 'uri' => '/users/ljr_fif/friends', }, +# { 'name' => 'To-Do list', +# 'uri' => '/todo.bml', }, +# { 'name' => 'Contributors', +# 'uri' => '/contributors.bml', }, + ], + }, +# { 'name' => 'Find Users', +# 'children' => [ +# { 'name' => 'Random!', +# 'uri' => '/random.bml', }, +# { 'name' => 'By Region', +# 'uri' => '/directory.bml', }, +# { 'name' => 'By Interest', +# 'uri' => '/interests.bml', }, +# { 'name' => 'Search', +# 'uri' => '/directorysearch.bml', } +# ], }, + { 'name' => BML::ml('ljrlook.nav.edit'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.editinfo'), + 'uri' => '/editinfo.bml', }, +# { 'name' => 'Settings', cont => 1, +# 'uri' => '/editinfo.bml', }, + { 'name' => BML::ml('ljrlook.nav.editfriends'), + 'uri' => '/editfriends.bml', }, + { 'name' => BML::ml('ljrlook.nav.editjournal'), + 'uri' => '/editjournal.bml', }, + { 'name' => BML::ml('ljrlook.nav.editpics'), + 'uri' => '/editpics.bml', }, + { 'name' => BML::ml('ljrlook.nav.changepassword'), + 'uri' => '/changepassword.bml', }, + { 'name' => BML::ml('ljrlook.nav.modify'), + 'uri' => '/modify.bml', }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.communities.manage'), + 'uri' => '/community/manage.bml' + }, +# { 'name' => 'Developer Area', +# 'uri' => '/developer/', +# 'match' => "^/developer/\$", +# 'recursematch' => "^/developer/", +# 'children' => [ +# { 'name' => 'Style System', +# 'uri' => '/developer/styles.bml', +# 'children' => [ +# { 'name' => 'View Types', +# 'uri' => '/developer/views.bml', }, +# { 'name' => 'Variable List', +# 'uri' => '/developer/varlist.bml', }, +# ], +# }, +# { 'name' => 'Embedding', +# 'uri' => '/developer/embedding.bml', }, +# { 'name' => 'Protocol', +# 'uri' => '/developer/protocol.bml', +# 'children' => [ +# { 'name' => 'Mode List', +# 'uri' => '/developer/modelist.bml', } +# ], +# }, +# ], +# }, + { 'name' => BML::ml('ljrlook.nav.frills'),#Styles,customization + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.customize'), + 'uri' => '/customize/', }, + { 'name' => BML::ml('ljrlook.nav.createstyle'), + 'uri' => '/createstyle.bml', }, + { 'name' => BML::ml('ljrlook.nav.editstyle'), + 'uri' => '/editstyle.bml', }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.needhelp'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.lostinfo'), + 'uri' => '/lostinfo.bml', }, + { 'name' => BML::ml('ljrlook.nav.support.faq'), + 'uri' => '/support/faq.bml', }, +# { 'name' => 'Questions', +# 'uri' => '/support/faq.bml', cont => 1, }, + { 'name' => BML::ml('ljrlook.nav.support'), + 'uri' => '/support/', }, + ], + }, + ); + + my $remote = LJ::get_remote(); + my $remuser = $remote ? $remote->{'user'} : ""; + my $uri = BML::get_uri(); + if ($remuser ne "" && $uri ne "/logout.bml") + { + my $subdomain = $remuser; + $subdomain =~ s/_/-/g; + unshift @sidebar, { 'name' => BML::ml('ljrlook.nav.hello').", ".$remuser."!", + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.yourjournal'), + 'children' => [ + { 'name' => BML::ml('ljrlook.nav.recent'), + 'uri' => "/users/$remuser/", }, + { 'name' => BML::ml('ljrlook.nav.calendar'), + 'uri' => "/users/$remuser/calendar", }, + { 'name' => BML::ml('ljrlook.nav.friends'), + 'uri' => "/users/$remuser/friends", + 'extra' => "/friendsfilter.bml", + }, + ], + }, + { 'name' => BML::ml('ljrlook.nav.userinfo'), + 'uri' => "/userinfo.bml?user=$remuser", }, + { 'name' => BML::ml('ljrlook.nav.memories'), + 'uri' => "/memories.bml?user=$remuser", }, + { 'name' => BML::ml('ljrlook.nav.logout'), + 'uri' => '/logout.bml', }, + ] + }; + } elsif ($uri ne "/login.bml") { + unshift @sidebar, { 'name' => BML::ml('ljrlook.nav.login'),, + 'uri' => '/login.bml', } + } + +return ""; +_code?> +<=LOAD_PAGE_INFO + +AL=>{P}%%data2%% +AWAYLINK=>{P}%%data2%% + +H1=>{D}

    %%data%%

    +H2=>{D}

    %%data%%

    + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%data%% + +GRIN=>{S}<grin> +HR=>{S}


    + +NEWLINE=>{S}
         +P=>{D}

    %%data%%

    + +STANDOUT<= +{D}
    +
    +%%data%% +
    +
    +<=STANDOUT + +ERRORBAR<= +{D}
    +
    +%%data%% +
    +
    +<=ERRORBAR + +WARNINGBAR<= +{D}
    +
    +%%data%% +
    +
    +<=WARNINGBAR + +BADCONTENT<= + h1?> + p?> +<=BADCONTENT + +DE<= +%%data%% +<=DE + +EMCOLOR=>{S}#c0c0c0 +HOTCOLOR=>{S}#ff0000 +EMCOLORLITE=>{S}#e2e2e2 +ALTCOLOR1=>{S}#eeeeee +ALTCOLOR2=>{S}#dddddd +screenedbarcolor=>{S}#d0d0d0 + +CHOICE=>{P}
    %%data1%%
    %%data3%% + +CHOICES<= +{F} + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=CHOICES + +PAGE<= +{Fp} +%%title%%%%head%% + +%%body%% + + +<=PAGE + +BREADCRUMBS<= +{Fp}[3]; # no blank crumbs + if ($crumb->[3] eq 'dynamic') { + # dynamic + unshift @ret, "$crumb->[0]"; + $count++; + } else { + # non-dynamic + unshift @ret, $count++ == 0 ? + "$ML{'crumb.'.$crumb->[3]}" : + $crumb->[1] ne '' ? + "[1]\">$ML{'crumb.'.$crumb->[3]}" : + "$ML{'crumb.'.$crumb->[3]}"; + } + } + return "
    " . join(" : ", @ret) . "
    "; +_code?> +<=BREADCRUMBS diff --git a/local/cgi-bin/bml/scheme/opalcat.look b/local/cgi-bin/bml/scheme/opalcat.look new file mode 100755 index 0000000..df3c74a --- /dev/null +++ b/local/cgi-bin/bml/scheme/opalcat.look @@ -0,0 +1,225 @@ +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +DE<= +%%DATA%% +<=DE + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT + +######################### choices stuff + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F}

    + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{F} + + + +%%TITLE%% +%%HEAD%% + + + + + + + + + + + + + + + + + +
    + +
    + + +/opal/bullet.gif\" WIDTH=10 HEIGHT=10 HSPACE=2 ALIGN=ABSMIDDLE>"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $extra = ""; + if ($mi->{'extra'}) { + $extra = " {'extra'}\">..."; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name$extra
    "; + } else { + $$ret .= "$name$extra
    "; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name$extra
    "; + } else { + $$ret .= "{'uri'}\">$name$extra
    "; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
    + +

    + + + + + +
    +

    '; +} else { + return "

     

    "; +} +return ""; +_code?> + +

    %%TITLE%% +

    + +
    + + +
    + + + + + +
    +%%BODY%% + 
    + +
       +

     

    + + Terms of Service
    + Privacy Policy - + COPPA +
    +

    + + + +<=PAGE + diff --git a/local/cgi-bin/bml/scheme/redwhite.look b/local/cgi-bin/bml/scheme/redwhite.look new file mode 100755 index 0000000..c452800 --- /dev/null +++ b/local/cgi-bin/bml/scheme/redwhite.look @@ -0,0 +1,267 @@ +# +# Welcome to GENERIC.LOOK for the WhiteBlue scheme +# +# by.... +# Brad Fitzpatrick +# brad@danga.com +# + +######################### little stuff + +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT +SOERROR=>
    %%data%%
    +EMAILEX=>
    %%data%%
    + +######################### choices stuff + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F}

    + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + + +<?_code { + my $elhash = $_[2]; + return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'}; +} _code?> +%%head%% +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> + + + + + + + + +
    + + + + + + + +
      +'; +} +return ""; +_code?> + + + "; + } + return ""; +_code?> +
    + +
    + + + + + + + + + + + + + + + + +
    + + +
    + + +"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name
    "; + } else { + $$ret .= "$name
    "; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name
    "; + } else { + $$ret .= "{'uri'}\">$name
    "; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
    + +
    +
    +
    + +
    + +
    +%%BODY%% + +
     
    +  + 
    + + + + + + +<=PAGE + diff --git a/local/cgi-bin/bml/scheme/vari b/local/cgi-bin/bml/scheme/vari new file mode 100755 index 0000000..d306874 --- /dev/null +++ b/local/cgi-bin/bml/scheme/vari @@ -0,0 +1,32 @@ +ljrlook.nav.create +ljrlook.nav.update +ljrlook.nav.fullupdate +ljrlook.nav.site +ljrlook.nav.news +ljrlook.nav.paidaccounts +ljrlook.nav.edit +ljrlook.nav.modify +ljrlook.nav.editinfo +ljrlook.nav.editfriends +ljrlook.nav.editjournal +ljrlook.nav.editpics +ljrlook.nav.changepassword +ljrlook.nav.communities.manage +ljrlook.nav.frills +ljrlook.nav.customize +ljrlook.nav.createstyle +ljrlook.nav.editstyle +ljrlook.nav.needhelp +ljrlook.nav.lostinfo +ljrlook.nav.support.faq +ljrlook.nav.support + +ljrlook.nav.hello +ljrlook.nav.yourjournal +ljrlook.nav.recent +ljrlook.nav.calendar +ljrlook.nav.friends +ljrlook.nav.userinfo +ljrlook.nav.memories +ljrlook.nav.logout +ljrlook.nav.login diff --git a/local/cgi-bin/cleanhtml.pl b/local/cgi-bin/cleanhtml.pl new file mode 100755 index 0000000..52e0d1f --- /dev/null +++ b/local/cgi-bin/cleanhtml.pl @@ -0,0 +1,1618 @@ +#!/usr/bin/perl +# +# +# lib: HTML::TokeParser, cgi-bin/ljconfig.pl, cgi-bin/ljlib.pl +# link: htdocs/userinfo.bml, htdocs/users +# + +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + +use strict; + +use Class::Autouse qw( + URI + HTML::TokeParser + HTMLCleaner + LJ::CSS::Cleaner + LJ::EmbedModule + ); + +use LJR::Viewuser; +use LJR::Distributed; + +package LJ; + +# +# name: LJ::strip_bad_code +# class: security +# des: Removes malicious/annoying HTML. +# info: This is just a wrapper function around [func[LJ::CleanHTML::clean]]. +# args: textref +# des-textref: Scalar reference to text to be cleaned. +# returns: Nothing. +# +sub strip_bad_code +{ + my $data = shift; + LJ::CleanHTML::clean($data, { + 'eat' => [qw[layer iframe script object embed]], + 'mode' => 'allow', + 'keepcomments' => 1, # Allows CSS to work + }); +} + +# LJ::CleanHTML::clean(\$u->{'bio'}, { +# 'wordlength' => 100, # maximum length of an unbroken "word" +# 'addbreaks' => 1, # insert
    after newlines where appropriate +# 'tablecheck' => 1, # make sure they aren't closing that weren't opened. +# 'eat' => [qw(head title style layer iframe)], +# 'mode' => 'allow', +# 'deny' => [qw(marquee)], +# 'remove' => [qw()], +# 'maximgwidth' => 100, +# 'maximgheight' => 100, +# 'keepcomments' => 1, +# 'cuturl' => 'http://www.domain.com/full_item_view.ext', +# 'ljcut_disable' => 1, # stops the cleaner from using the lj-cut tag +# 'cleancss' => 1, +# 'extractlinks' => 1, # remove a hrefs; implies noautolinks +# 'noautolinks' => 1, # do not auto linkify +# 'extractimages' => 1, # placeholder images +# 'transform_embed_nocheck' => 1, # do not do checks on object/embed tag transforming +# 'transform_embed_wmode' => , # define a wmode value for videos (usually 'transparent' is the value you want) +# 'blocked_links' => [ qr/evil\.com/, qw/spammer\.com/ ], # list of sites which URL's will be blocked +# 'blocked_link_substitute' => 'http://domain.com/error.html' # blocked links will be replaced by this URL +# }); + +package LJ::CleanHTML; + +sub helper_preload +{ + my $p = HTML::TokeParser->new(""); + eval {$p->DESTROY(); }; +} + + +# this treats normal characters and &entities; as single characters +# also treats UTF-8 chars as single characters if $LJ::UNICODE +my $onechar; +{ + my $utf_longchar = '[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]'; + my $match; + if (not $LJ::UNICODE) { + $match = '[^&\s]|(&\#?\w{1,7};)'; + } else { + $match = $utf_longchar . '|[^&\s\x80-\xff]|(?:&\#?\w{1,7};)'; + } + $onechar = qr/$match/o; +} + +# Some browsers, such as Internet Explorer, have decided to alllow +# certain HTML tags to be an alias of another. This has manifested +# itself into a problem, as these aliases act in the browser in the +# same manner as the original tag, but are not treated the same by +# the HTML cleaner. +# 'alias' => 'real' +my %tag_substitute = ( + 'image' => 'img', + ); + +# In XHTML you can close a tag in the same opening tag like
    , +# but some browsers still will interpret it as an opening only tag. +# This is a list of tags which you can actually close with a trailing +# slash and get the proper behavior from a browser. +my $slashclose_tags = qr/^(?:area|base|basefont|br|col|embed|frame|hr|img|input|isindex|link|meta|param|lj-embed)$/i; + +# +# name: LJ::CleanHTML::clean +# class: text +# des: Multi-faceted HTML parse function +# info: +# args: data, opts +# des-data: A reference to HTML to parse to output, or HTML if modified in-place. +# des-opts: An hash of options to pass to the parser. +# returns: Nothing. +# +# (NB!) very slow on a large text, called for every item within view stage. +# example: http://lj.rossia.org/users/lll22021918_01/2009/10/07/ +# +sub clean +{ + my $data = shift; + my $opts = shift; + my $newdata; + + # remove the auth portion of any see_request.bml links + $$data =~ s/(see_request\.bml\S+?)auth=\w+/$1/ig; + + my $p = HTML::TokeParser->new($data); + + my $wordlength = $opts->{'wordlength'}; + my $addbreaks = $opts->{'addbreaks'}; + my $keepcomments = $opts->{'keepcomments'}; + my $mode = $opts->{'mode'}; + my $cut = $opts->{'cuturl'} || $opts->{'cutpreview'}; + my $ljcut_disable = $opts->{'ljcut_disable'}; + my $s1var = $opts->{'s1var'}; + my $extractlinks = 0 || $opts->{'extractlinks'}; + my $noautolinks = $extractlinks || $opts->{'noautolinks'}; + my $noexpand_embedded = $opts->{'noexpandembedded'} || $opts->{'textonly'} || 0; + my $transform_embed_nocheck = $opts->{'transform_embed_nocheck'} || 0; + my $transform_embed_wmode = $opts->{'transform_embed_wmode'}; + my $remove_colors = $opts->{'remove_colors'} || 0; + my $remove_sizes = $opts->{'remove_sizes'} || 0; + my $remove_fonts = $opts->{'remove_fonts'} || 0; + my $blocked_links = (exists $opts->{'blocked_links'}) ? $opts->{'blocked_links'} : \@LJ::BLOCKED_LINKS; + my $blocked_link_substitute = + (exists $opts->{'blocked_link_substitute'}) ? $opts->{'blocked_link_substitute'} : + ($LJ::BLOCKED_LINK_SUBSTITUTE) ? $LJ::BLOCKED_LINK_SUBSTITUTE : '#'; + + my @canonical_urls; # extracted links + my %action = (); + my %remove = (); + if (ref $opts->{'eat'} eq "ARRAY") { + foreach (@{$opts->{'eat'}}) { $action{$_} = "eat"; } + } + if (ref $opts->{'allow'} eq "ARRAY") { + foreach (@{$opts->{'allow'}}) { $action{$_} = "allow"; } + } + if (ref $opts->{'deny'} eq "ARRAY") { + foreach (@{$opts->{'deny'}}) { $action{$_} = "deny"; } + } + if (ref $opts->{'remove'} eq "ARRAY") { + foreach (@{$opts->{'remove'}}) { $action{$_} = "deny"; $remove{$_} = 1; } + } + + $action{'script'} = "eat"; + + # if removing sizes, remove heading tags + if ($remove_sizes) { + foreach my $tag (qw( h1 h2 h3 h4 h5 h6 )) { + $action{$tag} = "deny"; + $remove{$tag} = 1; + } + } +# foreach my $tag (qw( marquee )) { +# $action{$tag} = "deny"; +# $remove{$tag} = 1; +# } +# Marquee is abused by makaka, I disabled it here, no idea what is a proper place +# to disable tags - please change - MV, 2014 +# A few days later: the proper place is probably when we strip tags from +# several HTML tags, such as hr, pre, textarea etc + +# antimakaka measure. Remove certain tags for anon - Nov 2014, MV + + if ($opts->{'anonhtml'}) { + foreach my $tag (qw( h1 h2 big font pre )) { + $action{$tag} = "deny"; + $remove{$tag} = 1; + } + } + + + my @attrstrip = qw(); + # cleancss means clean annoying css + # clean_js_css means clean javascript from css + if ($opts->{'cleancss'}) { + push @attrstrip, 'id'; + $opts->{'clean_js_css'} = 1; + } + + if ($opts->{'nocss'}) { + push @attrstrip, 'style'; + } + + if (ref $opts->{'attrstrip'} eq "ARRAY") { + foreach (@{$opts->{'attrstrip'}}) { push @attrstrip, $_; } + } + + my %opencount = (); + my @tablescope = (); + + my $cutcount = 0; + my $imagecount = 0; + + # bytes known good. set this BEFORE we start parsing any new + # start tag, where most evil is (because where attributes can be) + # then, if we have to totally fail, we can cut stuff off after this. + my $good_until = 0; + + # then, if we decide that part of an entry has invalid content, we'll + # escape that part and stuff it in here. this lets us finish cleaning + # the "good" part of the entry (since some tags might not get closed + # till after $good_until bytes into the text). + my $extra_text; + my $total_fail = sub { + my $tag = LJ::ehtml(@_); + + my $edata = LJ::ehtml($$data); + $edata =~ s/\r?\n/
    /g if $addbreaks; + + $extra_text = "
    [Error: Irreparable invalid markup ('<$tag>') in entry. ". + "Owner must fix manually. Raw contents below.]

    " . + '
    ' . $edata . '
    '; + }; + + my $htmlcleaner = HTMLCleaner->new(valid_stylesheet => \&LJ::valid_stylesheet_url); + + my $eating_ljuser_span = 0; # bool, if we're eating an ljuser span + my $ljuser_text_node = ""; # the last text node we saw while eating ljuser tags + my @eatuntil = (); # if non-empty, we're eating everything. thing at end is thing + # we're looking to open again or close again. + + my $capturing_during_eat; # if we save all tokens that happen inside the eating. + my @capture = (); # if so, they go here + + my $form_tag = { + input => 1, + select => 1, + option => 1, + }; + + my $start_capture = sub { + next if $capturing_during_eat; + + my ($tag, $first_token, $cb) = @_; + push @eatuntil, $tag; + @capture = ($first_token); + $capturing_during_eat = $cb || sub {}; + }; + + my $finish_capture = sub { + @capture = (); + $capturing_during_eat = undef; + }; + + TOKEN: + while (my $token = $p->get_token) + { + my $type = $token->[0]; + + # See if this tag should be treated as an alias + + $token->[1] = $tag_substitute{$token->[1]} if defined $tag_substitute{$token->[1]} && + ($type eq 'S' || $type eq 'E'); + + if ($type eq "S") # start tag + { + my $tag = $token->[1]; + my $attr = $token->[2]; # hashref + + $good_until = length $newdata; + + if (@eatuntil) { + push @capture, $token if $capturing_during_eat; + if ($tag eq $eatuntil[-1]) { + push @eatuntil, $tag; + } + next TOKEN; + } + + if ($tag eq "lj-template" && ! $noexpand_embedded) { + my $name = $attr->{name} || ""; + $name =~ s/-/_/g; + + my $run_template_hook = sub { + # can pass in tokens to override passing the hook the @capture array + my ($token, $override_capture) = @_; + my $capture = $override_capture ? [$token] : \@capture; + my $expanded = ($name =~ /^\w+$/) ? LJ::run_hook("expand_template_$name", $capture) : ""; + $newdata .= $expanded || "[Error: unknown template '" . LJ::ehtml($name) . "']"; + }; + + if ($attr->{'/'}) { + # template is self-closing, no need to do capture + $run_template_hook->($token, 1); + } else { + # capture and send content to hook + $start_capture->("lj-template", $token, $run_template_hook); + } + next TOKEN; + } + + if ($tag eq "lj-replace") { + my $name = $attr->{name} || ""; + my $replace = ($name =~ /^\w+$/) ? LJ::lj_replace($name, $attr) : undef; + $newdata .= defined $replace ? $replace : "[Error: unknown lj-replace key '" . LJ::ehtml($name) . "']"; + + next TOKEN; + } + + # Capture object and embed tags to possibly transform them into something else. + if ($tag eq "object" || $tag eq "embed") { + if (LJ::are_hooks("transform_embed") && !$noexpand_embedded) { + # XHTML style open/close tags done as a singleton shouldn't actually + # start a capture loop, because there won't be a close tag. + if ($attr->{'/'}) { + $newdata .= LJ::run_hook("transform_embed", [$token], + nocheck => $transform_embed_nocheck, wmode => $transform_embed_wmode) || ""; + next TOKEN; + } + + $start_capture->($tag, $token, sub { + my $expanded = LJ::run_hook("transform_embed", \@capture, + nocheck => $transform_embed_nocheck, wmode => $transform_embed_wmode); + $newdata .= $expanded || ""; + }); + next TOKEN; + } + } + + if ($tag eq "span" && lc $attr->{class} eq "ljruser" && ! $noexpand_embedded) { + $eating_ljuser_span = 1; + $ljuser_text_node = ""; + } + + if ($eating_ljuser_span) { + next TOKEN; + } + + if (($tag eq "div" || $tag eq "span") && lc $attr->{class} eq "ljvideo") { + $start_capture->($tag, $token, sub { + my $expanded = LJ::run_hook("expand_template_video", \@capture); + $newdata .= $expanded || "[Error: unknown template 'video']"; + }); + next TOKEN; + } + + # do some quick checking to see if this is an email address/URL, and if so, just + # escape it and ignore it + if ($tag =~ m!(?:\@|://)!) { + $newdata .= LJ::ehtml("<$tag>"); + next; + } + + if ($form_tag->{$tag}) { + if (! $opencount{form}) { + $newdata .= "<$tag ... >"; + next; + } + + if ($tag eq "input") { + if ($attr->{type} !~ /^\w+$/ || lc $attr->{type} eq "password") { + delete $attr->{type}; + } + } + } + + my $slashclose = 0; # If set to 1, use XML-style empty tag marker + # for tags like , pretend it's and reinsert the slash later + $slashclose = 1 if ($tag =~ s!/$!!); + + unless ($tag =~ /^\w([\w\-:_]*\w)?$/) { + $total_fail->($tag); + last TOKEN; + } + + # for incorrect tags like (note the lack of a space) + # delete everything after 'name' to prevent a security loophole which happens + # because IE understands them. + $tag =~ s!/.+$!!; + + if ($action{$tag} eq "eat") { + $p->unget_token($token); + $p->get_tag("/$tag"); + next; + } + + # try to call HTMLCleaner's element-specific cleaner on this open tag + my $clean_res = eval { + my $cleantag = $tag; + $cleantag =~ s/^.*://s; + $cleantag =~ s/[^\w]//g; + no strict 'subs'; + my $meth = "CLEAN_$cleantag"; + my $seq = $token->[3]; # attribute names, listref + my $code = $htmlcleaner->can($meth) + or return 1; + return $code->($htmlcleaner, $seq, $attr); + }; + next if !$@ && !$clean_res; + + # this is so the rte converts its source to the standard ljuser html + my $ljuser_div = $tag eq "div" && $attr->{class} eq "ljruser"; + if ($ljuser_div) { + my $ljuser_text = $p->get_text("/b"); + $p->get_tag("/div"); + $ljuser_text =~ s/\[info\]//; + $tag = "lj"; + $attr->{'user'} = $ljuser_text; + } + # stupid hack to remove the class='ljcut' from divs when we're + # disabling them, so we account for the open div normally later. + my $ljcut_div = $tag eq "div" && lc $attr->{class} eq "ljcut"; + if ($ljcut_div && $ljcut_disable) { + $ljcut_div = 0; + } + + # no cut URL, record the anchor, but then fall through + if (0 && $ljcut_div && !$cut) { + $cutcount++; + $newdata .= ""; + $ljcut_div = 0; + } + + if (($tag eq "lj-cut" || $ljcut_div) && !$ljcut_disable) { + next TOKEN if $ljcut_disable; + $cutcount++; + my $link_text = sub { + my $text = "Read more..."; + if ($attr->{'text'}) { + $text = $attr->{'text'}; + if ($text =~ /[^\x01-\x7f]/) { + $text = pack('C*', unpack('C*', $text)); + } + $text =~ s//>/g; + } + return $text; + }; + if ($cut) { + my $etext = $link_text->(); + my $url = LJ::ehtml($cut); + $newdata .= "
    " if $tag eq "div"; + $newdata .= "$etext )"; + $newdata .= "
    " if $tag eq "div"; + unless ($opts->{'cutpreview'}) { + push @eatuntil, $tag; + next TOKEN; + } + } else { + $newdata .= "" unless $opts->{'textonly'}; + if ($tag eq "div" && !$opts->{'textonly'}) { + $opencount{"div"}++; + my $etext = $link_text->(); + $newdata .= "
    "; + } + next; + } + } + elsif ($tag eq "style") { + my $style = $p->get_text("/style"); + $p->get_tag("/style"); + unless ($LJ::DISABLED{'css_cleaner'}) { + my $cleaner = LJ::CSS::Cleaner->new; + $style = $cleaner->clean($style); + LJ::run_hook('css_cleaner_transform', \$style); + if ($LJ::IS_DEV_SERVER) { + $style = "/* cleaned */\n" . $style; + } + } + $newdata .= "\n\n"; + next; + } + elsif ($tag eq "lj") + { + # keep working for backwards compatibility, but pretend + # it was so we don't have to account for it below. + my $user = $attr->{'user'} = exists $attr->{'user'} ? $attr->{'user'} : + exists $attr->{'comm'} ? $attr->{'comm'} : undef; + + if (length $user) { + my $orig_user = $user; # save for later, in case +# $user = LJ::canonical_username($user); + if ($s1var) { + $newdata .= "%%ljuser:$1%%" if $attr->{'user'} =~ /^\%\%([\w\-\']+)\%\%$/; + } elsif (length $user) { + if ($opts->{'textonly'}) { + $newdata .= $user; + } else { + $opts->{'site'} = LJR::Viewuser::canonical_sitenum( + exists $attr->{'site'} ? $attr->{'site'} : "LJ" + ); + if (exists $attr->{'comm'}) { + $opts->{'type'} = "C"; + } + else { + delete $opts->{'type'}; + } + $newdata .= LJR::Viewuser::ljuser($user, $opts); +# $newdata .= LJ::ljuser($user); + } + } else { + $orig_user = LJ::no_utf8_flag($orig_user); + $newdata .= "[Bad username: " . LJ::ehtml($orig_user) . "]"; + } + } else { + $newdata .= "[Unknown LJ tag]"; + } + } + + + elsif ($tag eq "ljr") { + my $optss=(); + my $user = $attr->{'user'} = + exists $attr->{'user'} ? $attr->{'user'} : + exists $attr->{'comm'} ? $attr->{'comm'} : undef; + + if (length $user) { + if (exists $attr->{'comm'}) {$optss->{'type'}='C';} + + $optss->{'site'}=0; + $newdata .= LJR::Viewuser::ljuser($user, $optss); + } + else { + $newdata .= "[Bad username in LJ tag]"; + } + } + elsif ($tag eq "ljr-href") { + my $attr = $token->[2]; + my $ljr_rhref = exists $attr->{'url'} ? $attr->{'url'} : undef; + my $ljr_rsite = exists $attr->{'site'} ? $attr->{'site'} : undef; + + if ($ljr_rhref && $ljr_rsite) { + my $furl = $ljr_rsite . $ljr_rhref; + my $ftxt = $ljr_rsite . $ljr_rhref; + + my $have_local_copy = 1; + my $ru; + my $ljr_rusername; + my $ljr_ritemid; + my $ljr_rthread; + my $ljr_rreplyto; + my $r; + my $c; + + $ru = LJR::Distributed::get_remote_server($ljr_rsite); + $have_local_copy = 0 if $ru->{"err"}; + + # we know remote server, proceed identifying link + if ($have_local_copy) { + #TODO: extract username according to remote server type + # (currently we support only LJ-based servers) + if ($ljr_rhref =~ /users\/(.+?)\/(\d+?)\.html(\?((thread\=(\d*))|(replyto\=(\d*))).*)*/) { + $ljr_rusername = $1; + $ljr_rusername =~ s/\-/\_/; + + $ljr_ritemid = int($2 / 256); + $ljr_rthread = int($6 / 256) if $6; + $ljr_rreplyto = int($8 / 256) if $8; + } + else { + $have_local_copy = 0; + } + } + + # we've got remote username and event htmlid, proceed identifying link + if ($have_local_copy) { + $ru->{username} = $ljr_rusername; + $ru = LJR::Distributed::get_cached_user($ru); # populates $ru->{ru_id} + $have_local_copy = 0 if $ru->{"err"}; + } + + # we know remote user, proceed identifying link + if ($have_local_copy) { + $r = LJR::Distributed::get_local_itemid (0, $ru->{ru_id}, $ljr_ritemid); + $have_local_copy = 0 if $r->{"err"} || $r->{"itemid"} == 0; + } + + if ($have_local_copy && ($ljr_rthread || $ljr_rreplyto)) { + my $tempid; + $tempid = $ljr_rthread if $ljr_rthread; + $tempid = $ljr_rreplyto if $ljr_rreplyto; + $c = LJR::Distributed::get_local_commentid (0, $ru->{ru_id}, $tempid); + $have_local_copy = 0 if $c->{"err"} || $c->{"talkid"} == 0; + } + + if ($have_local_copy) { + $furl = $LJ::SITEROOT . "/users/" . $r->{"journalname"} . "/" . + ($r->{"item"}->{"jitemid"} * 256 + $r->{"item"}->{"anum"}) . ".html"; + + if ($c->{"talkid"}) { + my $thread_id = $c->{"talkid"} * 256 + $r->{"item"}->{"anum"}; + if ($ljr_rthread) { + $furl .= "?thread=" . $thread_id . "#t" . $thread_id; + } + else { + $furl .= "?replyto=" . $thread_id; + } + } + + $ftxt = $furl; + } + + $newdata .= ""; + $opencount{'a'}++; + } + else { + $newdata .= "[Malformed ljr-user tag]"; + } + } + elsif ($tag eq "lj-raw") { + # Strip it out, but still register it as being open + $opencount{$tag}++; + } + + # Don't allow any tag with the "set" attribute + elsif ($tag =~ m/:set$/) { + next; + } + + else + { + my $alt_output = 0; + + my $hash = $token->[2]; + my $attrs = $token->[3]; # attribute names, in original order + + $slashclose = 1 if delete $hash->{'/'}; + + foreach (@attrstrip) { + # maybe there's a better place for this? + next if (lc $tag eq 'lj-embed' && lc $_ eq 'id'); + delete $hash->{$_}; + } + + if ($tag eq "form") { + my $action = lc($hash->{'action'}); + my $deny = 0; + if ($action =~ m!^https?://?([^/]+)!) { + my $host = $1; + $deny = 1 if + $host =~ /[%\@\s]/ || + $LJ::FORM_DOMAIN_BANNED{$host}; + } else { + $deny = 1; + } + delete $hash->{'action'} if $deny; + } + + + ATTR: + foreach my $attr (keys %$hash) + { + if ($attr =~ /^(?:on|dynsrc)/) { + delete $hash->{$attr}; + next; + } + # added in Apr 2014 to prevent an exploit by 1px guy - MV + if ($tag eq "table") { + delete $hash->{$attr}; + next; + } + #more anti-makaka measures - Oct 2014, MV + if ($tag eq "pre" || $tag eq "hr" + || $tag eq "marquee" || $tag eq "textarea") { + delete $hash->{$attr}; + next; + } + + if ($attr eq "data") { + delete $hash->{$attr} unless $tag eq "object"; + next; + } + + if ($attr eq "href" && $hash->{$attr} =~ /^data/) { + delete $hash->{$attr}; + next; + } + + if ($attr =~ /(?:^=)|[\x0b\x0d]/) { + # Cleaner attack:

    ' onmouseover="javascript:alert(document/**/.cookie)" > + # is returned by HTML::Parser as P_tag("='" => "='") Text( onmouseover...) + # which leads to reconstruction of valid HTML. Clever! + # detect this, and fail. + $total_fail->("$tag $attr"); + last TOKEN; + } + + # ignore attributes that do not fit this strict scheme + unless ($attr =~ /^[\w_:-]+$/) { + $total_fail->("$tag " . (%$hash > 1 ? "[...] " : "") . "$attr"); + last TOKEN; + } + + $hash->{$attr} =~ s/[\t\n]//g; + + # IE ignores the null character, so strip it out + $hash->{$attr} =~ s/\x0//g; + + # IE sucks: + my $nowhite = $hash->{$attr}; + $nowhite =~ s/[\s\x0b]+//g; + if ($nowhite =~ /(?:jscript|livescript|javascript|vbscript|about):/ix) { + delete $hash->{$attr}; + next; + } + + if ($attr eq 'style') { + if ($opts->{'cleancss'}) { + # css2 spec, section 4.1.3 + # position === p\osition :( + # strip all slashes no matter what. + $hash->{style} =~ s/\\//g; + + # and catch the obvious ones ("[" is for things like document["coo"+"kie"] + foreach my $css ("/*", "[", qw(margin absolute fixed expression eval behavior cookie document window javascript -moz-binding)) { + if ($hash->{style} =~ /\Q$css\E/i) { + delete $hash->{style}; + next ATTR; + } + } + + # remove specific CSS definitions + if ($remove_colors) { + $hash->{style} =~ s/(?:background-)?color:.*?(?:;|$)//gi; + } + if ($remove_sizes) { + $hash->{style} =~ s/font-size:.*?(?:;|$)//gi; + } + if ($remove_fonts) { + $hash->{style} =~ s/font-family:.*?(?:;|$)//gi; + } + + # Added to prevent the new div exploit (August 2008) - M. V. + $hash->{style} =~s/(content|background-image|background|position|top|left|width|height):.*?(?:;|$)//gi; + #modified March 2014 to remove backgrounds and content + # and in July 2014 to remove background-image + } + + if ($opts->{'clean_js_css'} && ! $LJ::DISABLED{'css_cleaner'}) { + # and then run it through a harder CSS cleaner that does a full parse + my $css = LJ::CSS::Cleaner->new; + $hash->{style} = $css->clean_property($hash->{style}); + } + } + + # reserve ljs_* ids for divs, etc so users can't override them to replace content + if ($attr eq 'id' && $hash->{$attr} =~ /^ljs_/i) { + delete $hash->{$attr}; + next; + } + + if ($s1var) { + if ($attr =~ /%%/) { + delete $hash->{$attr}; + next ATTR; + } + + my $props = $LJ::S1::PROPS->{$s1var}; + + if ($hash->{$attr} =~ /^%%([\w:]+:)?(\S+?)%%$/ && $props->{$2} =~ /[aud]/) { + # don't change it. + } elsif ($hash->{$attr} =~ /^%%cons:\w+%%[^\%]*$/) { + # a site constant with something appended is also fine. + } elsif ($hash->{$attr} =~ /%%/) { + my $clean_var = sub { + my ($mods, $prop) = @_; + # HTML escape and kill line breaks + $mods = "attr:$mods" unless + $mods =~ /^(color|cons|siteroot|sitename|img):/ || + $props->{$prop} =~ /[ud]/; + return '%%' . $mods . $prop . '%%'; + }; + + $hash->{$attr} =~ s/[\n\r]//g; + $hash->{$attr} =~ s/%%([\w:]+:)?(\S+?)%%/$clean_var->(lc($1), $2)/eg; + + if ($attr =~ /^(href|src|lowsrc|style)$/) { + $hash->{$attr} = "\%\%[attr[$hash->{$attr}]]\%\%"; + } + } + } + + # remove specific attributes + if (($remove_colors && ($attr eq "color" || $attr eq "bgcolor" || $attr eq "fgcolor" || $attr eq "text")) || + ($remove_sizes && $attr eq "size") || + ($remove_fonts && $attr eq "face")) { + delete $hash->{$attr}; + next ATTR; + } + } + if (exists $hash->{href}) { + ## links to some resources will be completely blocked + ## and replaced by value of 'blocked_link_substitute' param + if ($blocked_links) { + foreach my $re (@$blocked_links) { + if ($hash->{href} =~ $re) { + $hash->{href} = sprintf($blocked_link_substitute, LJ::eurl($hash->{href})); + last; + } + } + } + + unless ($hash->{href} =~ s/^lj:(?:\/\/)?(.*)$/ExpandLJURL($1)/ei) { + $hash->{href} = canonical_url($hash->{href}, 1); + } + } + + if ($tag eq "img") + { + $imagecount++; + my $img_bad = 0; + if ((defined $opts->{'maximgwidth'} && + (! defined $hash->{'width'} || + $hash->{'width'} > $opts->{'maximgwidth'})) +# I replaced 1 to 33 temporarily +# as an anti-macaque measure. Really stupid, in fact. - MV, Sept 2014 + || (defined $hash->{'width'} && $hash->{'width'} <= 33)) + # to avoid bombing with billion 1px images + { $img_bad = 1; } + if ((defined $opts->{'maximgheight'} && + (! defined $hash->{'height'} || + $hash->{'height'} > $opts->{'maximgheight'})) + || (defined $hash->{'height'} && $hash->{'height'} <= 33)) + { $img_bad = 1; } + if ($opts->{'extractimages'}) { $img_bad = 1; } +# anti-makaka: prohibit putting more than $MAXIMAGES images to comments + my $MAXIMAGES = 5; # maximal number of images in comments +# we should put this to ljconfig.pl! + if (($imagecount > $MAXIMAGES) && $opts->{'maximages'}) + { $img_bad = 1; } +# remove img src="data:image/..." images + $hash->{src} = canonical_url($hash->{src}, 1); + if ("$hash->{src}" =~ "^data:") { + $img_bad=1; + $hash->{src} = "data:image is not allowed"; + } + # Anon and OpenID commenters are not allowed to post images + if ($img_bad) { + $newdata .= "{'src'}) . "\">" . + LJ::img('placeholder') . ''; + $alt_output = 1; + $opencount{"img"}++; + } + } + + if ($tag eq "a" && $extractlinks) + { + push @canonical_urls, canonical_url($token->[2]->{href}, 1); + $newdata .= ""; + next; + } + + + # Through the xsl namespace in XML, it is possible to embed scripting lanaguages + # as elements which will then be executed by the browser. Combining this with + # customview.cgi makes it very easy for someone to replace their entire journal + # in S1 with a page that embeds scripting as well. An example being an AJAX + # six degrees tool, while cool it should not be allowed. + # + # Example syntax: + # + # text/javascript + if ($tag eq 'xsl:attribute') + { + $alt_output = 1; # We'll always deal with output for this token + + my $orig_value = $p->get_text; # Get the value of this element + my $value = $orig_value; # Make a copy if this turns out to be alright + $value =~ s/\s+//g; # Remove any whitespace + + # See if they are trying to output scripting, if so eat the xsl:attribute + # container and its value + if ($value =~ /(javascript|vbscript)/i) { + + # Remove the closing tag from the tree + $p->get_token; + + # Remove the value itself from the tree + $p->get_text; + + # No harm, no foul...Write back out the original + } else { + $newdata .= "$token->[4]$orig_value"; + } + } + + unless ($alt_output) + { + my $allow; + if ($mode eq "allow") { + $allow = 1; + if ($action{$tag} eq "deny") { $allow = 0; } + } else { + $allow = 0; + if ($action{$tag} eq "allow") { $allow = 1; } + } + + if ($allow && ! $remove{$tag}) + { + if ($opts->{'tablecheck'}) { + + $allow = 0 if + + # can't open table elements from outside a table + ($tag =~ /^(?:tbody|thead|tfoot|tr|td|th|caption|colgroup|col)$/ && ! @tablescope) || + + # can't open td or th if not inside tr + ($tag =~ /^(?:td|th)$/ && ! $tablescope[-1]->{'tr'}) || + + # can't open a table unless inside a td or th + ($tag eq 'table' && @tablescope && ! grep { $tablescope[-1]->{$_} } qw(td th)); + } + + if ($allow) { $newdata .= "<$tag"; } + else { $newdata .= "<$tag"; } + + # output attributes in original order, but only those + # that are allowed (by still being in %$hash after cleaning) + foreach (@$attrs) { + unless (LJ::is_ascii($hash->{$_})) { + # FIXME: this is so ghetto. make faster. make generic. + # HTML::Parser decodes entities for us (which is good) + # but in Perl 5.8 also includes the "poison" SvUTF8 + # flag on the scalar it returns, thus poisoning the + # rest of the content this scalar is appended with. + # we need to remove that poison at this point. *sigh* + $hash->{$_} = LJ::no_utf8_flag($hash->{$_}); + } + $newdata .= " $_=\"" . LJ::ehtml($hash->{$_}) . "\"" + if exists $hash->{$_}; + } + + # ignore the effects of slashclose unless we're dealing with a tag that can + # actually close itself. Otherwise, a tag like can pass through as valid + # even though some browsers just render it as an opening tag + if ($slashclose && $tag =~ $slashclose_tags) { + $newdata .= " /"; + $opencount{$tag}--; + $tablescope[-1]->{$tag}-- if $opts->{'tablecheck'} && @tablescope; + } + if ($allow) { + $newdata .= ">"; + $opencount{$tag}++; + + # maintain current table scope + if ($opts->{'tablecheck'}) { + + # open table + if ($tag eq 'table') { + push @tablescope, {}; + + # new tag within current table + } elsif (@tablescope) { + $tablescope[-1]->{$tag}++; + } + } + + } + else { $newdata .= ">"; } + } + } + } + } + # end tag + elsif ($type eq "E") + { + my $tag = $token->[1]; + next TOKEN if $tag =~ /[^\w\-:]/; + + if (@eatuntil) { + push @capture, $token if $capturing_during_eat; + + if ($eatuntil[-1] eq $tag) { + pop @eatuntil; + if (my $cb = $capturing_during_eat) { + $cb->(); + $finish_capture->(); + } + next TOKEN; + } + + next TOKEN if @eatuntil; + } + + if ($eating_ljuser_span && $tag eq "span") { + $eating_ljuser_span = 0; + $newdata .= $opts->{'textonly'} ? $ljuser_text_node : LJ::ljuser($ljuser_text_node); + next TOKEN; + } + + my $allow; + if ($tag eq "lj-raw") { + $opencount{$tag}--; + $tablescope[-1]->{$tag}-- if $opts->{'tablecheck'} && @tablescope; + } + elsif ($tag eq "lj-cut") { + if ($opts->{'cutpreview'}) { + $newdata .= "</lj-cut>"; + } + } + elsif ($tag eq "ljr-href") { + $newdata .= ""; + $opencount{'a'}--; + } + else { + if ($mode eq "allow") { + $allow = 1; + if ($action{$tag} eq "deny") { $allow = 0; } + } else { + $allow = 0; + if ($action{$tag} eq "allow") { $allow = 1; } + } + + if ($extractlinks && $tag eq "a") { + if (@canonical_urls) { + my $url = LJ::ehtml(pop @canonical_urls); + $newdata .= " ($url)"; + next; + } + } + + if ($allow && ! $remove{$tag}) + { + + if ($opts->{'tablecheck'}) { + + $allow = 0 if + + # can't close table elements from outside a table + ($tag =~ /^(?:table|tbody|thead|tfoot|tr|td|th|caption|colgroup|col)$/ && ! @tablescope) || + + # can't close td or th unless open tr + ($tag =~ /^(?:td|th)$/ && ! $tablescope[-1]->{'tr'}); + } + + if ($allow && ! ($opts->{'noearlyclose'} && ! $opencount{$tag})) { + + # maintain current table scope + if ($opts->{'tablecheck'}) { + + # open table + if ($tag eq 'table') { + pop @tablescope; + + # closing tag within current table + } elsif (@tablescope) { + $tablescope[-1]->{$tag}--; + } + } + + $newdata .= ""; + $opencount{$tag}--; + + } else { + $newdata .= "</$tag>"; + } + } + } + } + elsif ($type eq "D") { + # remove everything past first closing tag + $token->[1] =~ s/>.+/>/s; + # kill any opening tag except the starting one + $token->[1] =~ s/.[1]; + } + elsif ($type eq "T") { + my %url = (); + my $urlcount = 0; + + if (@eatuntil) { + push @capture, $token if $capturing_during_eat; + next TOKEN; + } + + if ($eating_ljuser_span) { + $ljuser_text_node = $token->[1]; + next TOKEN; + } + + if ($opencount{'style'} && $LJ::DEBUG{'s1_style_textnode'}) { + my $r = Apache->request; + my $uri = $r->uri; + my $host = $r->header_in("Host"); + warn "Got text node while style elements open. Shouldn't happen anymore. ($host$uri)\n"; + } + + my $auto_format = $addbreaks && + ($opencount{'table'} <= ($opencount{'td'} + $opencount{'th'})) && + ! $opencount{'pre'} && + ! $opencount{'lj-raw'}; + + if ($auto_format && ! $noautolinks && ! $opencount{'a'} && ! $opencount{'textarea'}) { + my $match = sub { + my $str = shift; + if ($str =~ /^(.*?)(&(#39|quot|lt|gt)(;.*)?)$/) { + $url{++$urlcount} = $1; + return "&url$urlcount;$1&urlend;$2"; + } else { + $url{++$urlcount} = $str; + return "&url$urlcount;$str&urlend;"; + } + }; + $token->[1] =~ s!https?://[^\s\'\"\<\>]+[a-zA-Z0-9_/&=\-]! $match->($&); !ge; + } + + # escape tags in text tokens. shouldn't belong here! + # especially because the parser returns things it's + # confused about (broken, ill-formed HTML) as text. + $token->[1] =~ s/[1] =~ s/>/>/g; + + # put tags into long words, except inside

     and 
    "; + + # Display captcha challenge if over rate limits. + if ($opts->{do_captcha}) { + my ($wants_audio, $captcha_sess, $captcha_chal); + $wants_audio = 1 if lc($form->{answer}) eq 'audio'; + + # Captcha sessions + my $cid = $journalu->{clusterid}; + $captcha_chal = $form->{captcha_chal} || LJ::challenge_generate(900); + $captcha_sess = LJ::get_challenge_attributes($captcha_chal); + my $dbcr = LJ::get_cluster_reader($journalu); + + my $try = 0; + if ($form->{captcha_chal}) { + $try = $dbcr->selectrow_array('SELECT trynum FROM captcha_session ' . + 'WHERE sess=?', undef, $captcha_sess); + } + $ret .= '

    '; + + # Visual challenge + if (! $wants_audio && ! $form->{audio_chal}) { + $ret .= "
    $BML::ML{'/create.bml.captcha.desc'}
    "; + $ret .= ""; + $ret .= "

    $BML::ML{'/create.bml.captcha.answer'}"; + } + # Audio challenge + else { + $ret .= "
    $BML::ML{'/create.bml.captcha.audiodesc'}
    "; + $ret .= "$BML::ML{'/create.bml.captcha.play'}   "; + $ret .= LJ::html_hidden(audio_chal => 1); + } + $ret .= LJ::html_text({ name =>'answer', size =>15 }); + $ret .= LJ::html_hidden(captcha_chal => $captcha_chal); + $ret .= '
    '; + } + + if ($LJ::SPELLER) { + $ret .= " "; + } + + $ret .= ""; + $ret .= LJ::html_check( + { + name => 'prop_opt_preformatted', + id => 'prop_opt_preformatted', + value => 1, + selected => $form->{'prop_opt_preformatted'} + } + ); + + if (defined $LJ::HELPURL{'noautoformat'}) { + $ret .= " $BML::ML{"; + } + + # post and preview buttons + my $limit = LJ::CMAX_COMMENT; # javascript String.length uses characters + $ret .= < + + +LOGIN + + if ($journalu->{'opt_logcommentips'} eq "A") { + $ret .= "
    $BML::ML{'.logyourip'}"; + $ret .= LJ::help_icon("iplogging", " "); + } + if ($journalu->{'opt_logcommentips'} eq "S") { + $ret .= "
    $BML::ML{'.loganonip'}"; + $ret .= LJ::help_icon("iplogging", " "); + } + + $ret .= "\n"; + + # Some JavaScript to help the UI out + + $ret .= ""; + $ret .= "\n"; + + return $ret; +} + +# +# name: LJ::record_anon_comment_ip +# class: web +# des: Records the IP address of an anonymous comment +# args: journalu, jtalkid, ip +# des-journalu: User object of journal comment was posted in. +# des-jtalkid: ID of this comment. +# des-ip: IP address of the poster. +# returns: 1 for success, 0 for failure +# +sub record_anon_comment_ip { + my ($journalu, $jtalkid, $ip) = @_; + $journalu = LJ::want_user($journalu); + $jtalkid += 0; + return 0 unless LJ::isu($journalu) && $jtalkid && $ip; + + $journalu->do("INSERT INTO tempanonips (reporttime, journalid, jtalkid, ip) VALUES (UNIX_TIMESTAMP(),?,?,?)", + undef, $journalu->{userid}, $jtalkid, $ip); + return 0 if $journalu->err; + return 1; +} + +# +# name: LJ::mark_comment_as_spam +# class: web +# des: Copies a comment into the global spamreports table +# args: journalu, jtalkid +# des-journalu: User object of journal comment was posted in. +# des-jtalkid: ID of this comment. +# returns: 1 for success, 0 for failure +# +sub mark_comment_as_spam { + my ($journalu, $jtalkid) = @_; + $journalu = LJ::want_user($journalu); + $jtalkid += 0; + return 0 unless $journalu && $jtalkid; + + my $dbcr = LJ::get_cluster_def_reader($journalu); + my $dbh = LJ::get_db_writer(); + + # step 1: get info we need + my $row = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $jtalkid); + my $temp = LJ::get_talktext2($journalu, $jtalkid); + my ($subject, $body, $posterid) = ($temp->{$jtalkid}[0], $temp->{$jtalkid}[1], $row->{posterid}); + return 0 unless $body; + + # step 2: get ip if anon + my $ip; + unless ($posterid) { + $ip = $dbcr->selectrow_array('SELECT ip FROM tempanonips WHERE journalid=? AND jtalkid=?', + undef, $journalu->{userid}, $jtalkid); + return 0 if $dbcr->err; + + # we want to fail out if we have no IP address and this is anonymous, because otherwise + # we have a completely useless spam report. pretend we were successful, too. + return 1 unless $ip; + + # we also want to log this attempt so that we can do some throttling + my $rates = LJ::MemCache::get("spamreports:anon:$ip") || $RATE_DATAVER; + $rates .= pack("N", time); + LJ::MemCache::set("spamreports:anon:$ip", $rates); + } + + # step 3: insert into spamreports + $dbh->do('INSERT INTO spamreports (reporttime, posttime, ip, journalid, posterid, subject, body) ' . + 'VALUES (UNIX_TIMESTAMP(), UNIX_TIMESTAMP(?), ?, ?, ?, ?, ?)', + undef, $row->{datepost}, $ip, $journalu->{userid}, $posterid, $subject, $body); + return 0 if $dbh->err; + return 1; +} + +# +# name: LJ::Talk::get_talk2_row +# class: web +# des: Gets a row of data from talk2. +# args: dbcr, journalid, jtalkid +# des-dbcr: Database handle to read from. +# des-journalid: Journal id that comment is posted in. +# des-jtalkid: Journal talkid of comment. +# returns: Hashref of row data, or undef on error. +# +sub get_talk2_row { + my ($dbcr, $journalid, $jtalkid) = @_; + return $dbcr->selectrow_hashref('SELECT journalid, jtalkid, nodetype, nodeid, parenttalkid, ' . + ' posterid, datepost, state ' . + 'FROM talk2 WHERE journalid = ? AND jtalkid = ?', + undef, $journalid+0, $jtalkid+0); +} + +# get a comment count for a journal entry. +sub get_replycount { + my ($ju, $jitemid) = @_; + $jitemid += 0; + return undef unless $ju && $jitemid; + + my $memkey = [$ju->{'userid'}, "rp:$ju->{'userid'}:$jitemid"]; + my $count = LJ::MemCache::get($memkey); + return $count if defined $count; + + my $dbcr = LJ::get_cluster_def_reader($ju); + return unless $dbcr; + + $count = $dbcr->selectrow_array("SELECT replycount FROM log2 WHERE " . + "journalid=? AND jitemid=?", undef, + $ju->{'userid'}, $jitemid); + LJ::MemCache::add($memkey, $count); + return $count; +} + +package LJ::Talk::Post; + +sub format_text_mail { + my ($targetu, $parent, $comment, $talkurl, $item) = @_; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + + $Text::Wrap::columns = 20000; # was 76; -- temp hack!!! + + my $who = "Somebody"; + if ($comment->{u}) { + $who = "$comment->{u}{name} ($comment->{u}{user})"; + } + + my $text = ""; + if (LJ::u_equals($targetu, $comment->{u})) { + if ($parent->{ispost}) { + $who = "$parent->{u}{name} ($parent->{u}{user})"; + $text .= "You left a comment in a post by $who. "; + $text .= "The entry you replied to was:"; + } else { + $text .= "You left a comment in reply to another comment. "; + $text .= "The comment you replied to was:"; + } + } elsif (LJ::u_equals($targetu, $item->{entryu})) { + if ($parent->{ispost}) { + $text .= "$who replied to your $LJ::SITENAMESHORT post in which you said:"; + } else { + $text .= "$who replied to another comment somebody left in your $LJ::SITENAMESHORT post. "; + $text .= "The comment they replied to was:"; + } + } else { + $text .= "$who replied to your $LJ::SITENAMESHORT comment in which you said:"; + } + $text .= "\n\n"; + $text .= indent($parent->{body}, ">") . "\n\n"; + $text .= (LJ::u_equals($targetu, $comment->{u}) ? 'Your' : 'Their') . " reply was:\n\n"; + if ($comment->{subject}) { + $text .= Text::Wrap::wrap(" Subject: ", + " ", + $comment->{subject}) . "\n\n"; + } + $text .= indent($comment->{body}); + $text .= "\n\n"; + + my $can_unscreen = $comment->{state} eq 'S' && + LJ::Talk::can_unscreen($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef); + + if ($comment->{state} eq 'S') { + $text .= "This comment was screened. "; + $text .= $can_unscreen ? + "You must respond to it or unscreen it before others can see it.\n\n" : + "Someone else must unscreen it before you can reply to it.\n\n"; + } + + my $opts = ""; + $opts .= "Options:\n\n"; + $opts .= " - View the discussion:\n"; + $opts .= " " . LJ::Talk::talkargs($talkurl, "thread=$dtalkid") . "\n"; + $opts .= " - View all comments on the entry:\n"; + $opts .= " $talkurl\n"; + $opts .= " - Reply to the comment:\n"; + $opts .= " " . LJ::Talk::talkargs($talkurl, "replyto=$dtalkid") . "\n"; + if ($can_unscreen) { + $opts .= " - Unscreen the comment:\n"; + $opts .= " $LJ::SITEROOT/talkscreen.bml?mode=unscreen&journal=$item->{journalu}{user}&talkid=$dtalkid\n"; + } + if (LJ::Talk::can_delete($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef)) { + $opts .= " - Delete the comment:\n"; + $opts .= " $LJ::SITEROOT/delcomment.bml?journal=$item->{journalu}{user}&id=$dtalkid\n"; + } + + my $footer = ""; + $footer .= "-- $LJ::SITENAME\n\n"; + $footer .= "(If you'd prefer to not get these updates, go to $LJ::SITEROOT/editinfo.bml and turn off the relevant options.)"; + return Text::Wrap::wrap("", "", $text) . "\n" . $opts . "\n" . Text::Wrap::wrap("", "", $footer); +} + +sub format_html_mail { + my ($targetu, $parent, $comment, $encoding, $talkurl, $item) = @_; + my $ditemid = $item->{itemid}*256 + $item->{anum}; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + my $threadurl = LJ::Talk::talkargs($talkurl, "thread=$dtalkid"); + + my $who = "Somebody"; + if ($comment->{u}) { + $who = "$comment->{u}{name} ". + "({u}{user}\">$comment->{u}{user})"; + } + + my $html = ""; + $html .= "\n\n"; + + my $intro; + my $cleanbody = $parent->{body}; +# Identity comments should be cleaned together with anons - MV, July 2014 + my $anon_comment_t = ($comment->{'u'}->identity() || !$comment->{u}); + if (LJ::u_equals($targetu, $comment->{u})) { + if ($parent->{ispost}) { + $who = "$parent->{u}{name} " . + "({u}{user}\">$parent->{u}{user})"; + $intro = "You replied to a $LJ::SITENAMESHORT post in which $who said:"; + LJ::CleanHTML::clean_event(\$cleanbody, {preformatted => $parent->{preformat}}); + } else { + $intro = "You replied to a comment somebody left in "; + $intro .= "a $LJ::SITENAMESHORT post. "; + $intro .= "The comment you replied to was:"; + LJ::CleanHTML::clean_comment(\$cleanbody, + { 'preformatted' => $parent->{preformat}, + 'anon_comment' => $anon_comment_t }); +# was: !$comment->{u} }); + } + } elsif (LJ::u_equals($targetu, $item->{entryu})) { + if ($parent->{ispost}) { + $intro = "$who replied to your $LJ::SITENAMESHORT post in which you said:"; + LJ::CleanHTML::clean_comment(\$cleanbody, + { 'preformatted' => $parent->{preformat}, + 'anon_comment' => $anon_comment_t }); + } else { + $intro = "$who replied to another comment somebody left in "; + $intro .= "your $LJ::SITENAMESHORT post. "; + $intro .= "The comment they replied to was:"; + LJ::CleanHTML::clean_comment(\$cleanbody, + { 'preformatted' => $parent->{preformat}, + 'anon_comment' => $anon_comment_t }); + } + } else { + $intro = "$who replied to your $LJ::SITENAMESHORT comment "; + $intro .= "in which you said:"; + LJ::CleanHTML::clean_comment(\$cleanbody, + { 'preformatted' => $parent->{preformat}, + 'anon_comment' => $anon_comment_t }); + } + + my $pichtml; + if ($comment->{u} && $comment->{u}{defaultpicid} || $comment->{pic}) { + my $picid = $comment->{pic} ? $comment->{pic}{'picid'} : $comment->{u}{'defaultpicid'}; + unless ($comment->{pic}) { + my %pics; + LJ::load_userpics(\%pics, [ $comment->{u}, $comment->{u}{'defaultpicid'} ]); + $comment->{pic} = $pics{$picid}; + # load_userpics doesn't return picid, but we rely on it above + $comment->{pic}{'picid'} = $picid; + } + if ($comment->{pic}) { + $pichtml = "{pic}{'userid'}\" align='absmiddle' ". + "width='$comment->{pic}{'width'}' height='$comment->{pic}{'height'}' ". + "hspace='1' vspace='2' alt='' /> "; + } + } + + if ($pichtml) { + $html .= "
    $pichtml$intro
    \n"; + } else { + $html .= "
    $intro
    \n"; + } + $html .= blockquote($cleanbody); + + $html .= "\n\n" . (LJ::u_equals($targetu, $comment->{u}) ? 'Your' : 'Their') . " reply was:\n\n"; + $cleanbody = $comment->{body}; + LJ::CleanHTML::clean_comment(\$cleanbody, $comment->{preformat}); + my $pics = LJ::Talk::get_subjecticons(); + my $icon = LJ::Talk::show_image($pics, $comment->{subjecticon}); + + my $heading; + if ($comment->{subject}) { + $heading = "Subject: " . LJ::ehtml($comment->{subject}); + } + $heading .= $icon; + $heading .= "
    " if $heading; + # this needs to be one string so blockquote handles it properly. + $html .= blockquote("$heading$cleanbody"); + + my $can_unscreen = $comment->{state} eq 'S' && + LJ::Talk::can_unscreen($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef); + + if ($comment->{state} eq 'S') { + $html .= "

    This comment was screened. "; + $html .= $can_unscreen ? + "You must respond to it or unscreen it before others can see it.

    \n" : + "Someone else must unscreen it before you can reply to it.

    \n"; + } + + $html .= "

    From here, you can:\n"; + $html .= "

    "; + + my $want_form = $comment->{state} eq 'A' || $can_unscreen; # this should probably be a preference, or maybe just always off. + if ($want_form) { + $html .= "If your mail client supports it, you can also reply here:\n"; + $html .= "
    \n"; + + $html .= LJ::html_hidden( + usertype => "user", + parenttalkid => $comment->{talkid}, + itemid => $ditemid, + journal => $item->{journalu}{user}, + userpost => $targetu->{user}, + ecphash => LJ::Talk::ecphash($item->{itemid}, $comment->{talkid}, $targetu->{password}) + ); + + $html .= "" unless $encoding eq "UTF-8"; + my $newsub = $comment->{subject}; + unless (!$newsub || $newsub =~ /^Re:/) { $newsub = "Re: $newsub"; } + $html .= "Subject: "; + $html .= "

    Message
    "; + $html .= "
    "; + $html .= "

    \n"; + } + $html .= "

    (If you'd prefer to not get these updates, go to your user profile page and turn off the relevant options.)

    \n"; + $html .= "\n"; + + return $html; +} + +sub indent { + my $a = shift; + my $leadchar = shift || " "; + $Text::Wrap::columns = 20000; # was 76; -- temp hack!!! + return Text::Wrap::fill("$leadchar ", "$leadchar ", $a); +} + +sub blockquote { + my $a = shift; + return "
    $a
    "; +} + +sub generate_messageid { + my ($type, $journalu, $did) = @_; + # $type = {"entry" | "comment"} + # $journalu = $u of journal + # $did = display id of comment/entry + + my $jid = $journalu->{userid}; + return "<$type-$jid-$did\@$LJ::DOMAIN>"; +} + +# entryu : user who posted the entry this comment is under. +# journalu : journal this entry is in. +# parent : comment/entry this post is in response to. +# comment : the comment itself. +# item : entry this comment falls under. +sub mail_comments { + my ($entryu, $journalu, $parent, $comment, $item) = @_; + my $itemid = $item->{itemid}; + my $ditemid = $itemid*256 + $item->{anum}; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + my $talkurl = LJ::journal_base($journalu) . "/$ditemid.html"; + my $threadurl = LJ::Talk::talkargs($talkurl, "thread=$dtalkid"); + + # check to see if parent post is from a registered livejournal user, and + # mail them the response + my $parentcomment = ""; + my $parentmailed = ""; # who if anybody was just mailed + + # message ID of the mythical top-level journal entry (which + # currently is never emailed) so mail clients can group things + # together with a comment ancestor if parents are missing + my $top_msgid = generate_messageid("entry", $journalu, $ditemid); + # find first parent + my $par_msgid; + if (my $ptid = $parent->{talkid}) { + $par_msgid = generate_messageid("comment", $journalu, + $ptid * 256 + $item->{anum}); + } else { + # is a reply to the top-level + $par_msgid = $top_msgid; + $top_msgid = ""; # so it's not duplicated + } + # and this message ID + my $this_msgid = generate_messageid("comment", $journalu, $dtalkid); + + # if a response to another comment, send a mail to the parent commenter. + if ($parent->{talkid}) { + my $dbcr = LJ::get_cluster_def_reader($journalu); + + # get row of data + my $row = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $parent->{talkid}); + my $paruserid = $row->{posterid}; + + # now get body of comment + my $temp = LJ::get_talktext2($journalu, $parent->{talkid}); + my $parbody = $temp->{$parent->{talkid}}[1]; + LJ::text_uncompress(\$parbody); + $parentcomment = $parbody; + + my %props = ($parent->{talkid} => {}); + LJ::load_talk_props2($journalu, [$parent->{talkid}], \%props); + $parent->{preformat} = $props{$parent->{talkid}}->{'opt_preformatted'}; + + # convert to UTF-8 if necessary + my $parentsubject = $parent->{subject}; + if ($LJ::UNICODE && $props{$parent->{talkid}}->{'unknown8bit'}) { + LJ::item_toutf8($journalu, \$parentsubject, \$parentcomment, {}); + $props{$parent->{talkid}}->{'unknown8bit'} = 0; ## ??? + print STDERR "Fixing item_toutf8 in mail_comments $journalu->{'userid'} $itemid $parent->{talkid} $comment->{talkid} \n"; + } + + if ($paruserid) { + my $paru = LJ::load_userid($paruserid); + LJ::load_user_props($paru, 'mailencoding'); + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + + # we don't want to send email to a parent if the email address on the + # parent's user is the same as the email address on this comment's user + # is_diff_email: also so we don't auto-vivify $comment->{u} + my $is_diff_email = !$comment->{u} || + $paru->{'email'} ne $comment->{u}{'email'}; + + if ($paru->{'opt_gettalkemail'} eq "Y" && + $is_diff_email && + $paru->{'status'} eq "A") + { + $parentmailed = $paru->{'email'}; + my $encoding = $paru->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$paru->{'mailencoding'}} : "KOI8-R"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $fromname = $comment->{u} ? LJ::User::display_name($comment->{u}) . " - $LJ::SITENAMEABBREV Comment" : "$LJ::SITENAMESHORT Comment"; + + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)", + 'To' => $paru->{'email'}, + 'Subject' => ($headersubject || "Reply to your comment..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + $parent->{u} = $paru; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + my $text = format_text_mail($paru, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding); +# if $LJ::UNICODE; + + if ($paru->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($paru, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + } + + LJ::send_mail($msg); + } + } + } + + # send mail to the poster of the entry + if ($entryu->{'opt_gettalkemail'} eq "Y" && + !$item->{props}->{'opt_noemail'} && + !LJ::u_equals($comment->{u}, $entryu) && + $entryu->{'email'} ne $parentmailed && + $entryu->{'status'} eq "A") + { + LJ::load_user_props($entryu, 'mailencoding'); + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + my $encoding = $entryu->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$entryu->{'mailencoding'}} : "KOI8-R"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $fromname = $comment->{u} ? LJ::User::display_name($comment->{u}) . " - $LJ::SITENAMEABBREV Comment" : "$LJ::SITENAMESHORT Comment"; + + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)", + 'To' => $entryu->{'email'}, + 'Subject' => ($headersubject || "Reply to your post..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + my $quote = $parentcomment ? $parentcomment : $item->{'event'}; + + # if this is a response to a comment inside our journal, + # we don't know who made the parent comment + # (and it's potentially anonymous). + if ($parentcomment) { + $parent->{u} = undef; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + } else { + $parent->{u} = $entryu; + $parent->{body} = $item->{'event'}, + $parent->{ispost} = 1; + $parent->{preformat} = $item->{'props'}->{'opt_preformatted'}; + } + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + + my $text = format_text_mail($entryu, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + + if ($entryu->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($entryu, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding); +# if $LJ::UNICODE; + } + + LJ::send_mail($msg); + } + + # now send email to the person who posted the comment we're using? only if userprop + # opt_getselfemail is turned on. no need to check for active/suspended accounts, as + # they couldn't have posted if they were. (and if they did somehow, we're just emailing + # them, so it shouldn't matter.) + my $u = $comment->{u}; + LJ::load_user_props($u, 'opt_getselfemail', 'mailencoding') if $u; + if ($u && $u->{'opt_getselfemail'} && LJ::get_cap($u, 'getselfemail')) { + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + my $encoding = $u->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$u->{'mailencoding'}} : "KOI8-R"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($u->{'user'} - $LJ::SITENAMEABBREV Comment)", + 'To' => $u->{'email'}, + 'Subject' => ($headersubject || "Comment you posted..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + my $quote = $parentcomment ? $parentcomment : $item->{'event'}; + + # if this is a response to a comment inside our journal, + # we don't know who made the parent comment + # (and it's potentially anonymous). + if ($parentcomment) { + $parent->{u} = undef; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + } else { + $parent->{u} = $entryu; + $parent->{body} = $item->{'event'}, + $parent->{ispost} = 1; + $parent->{preformat} = $item->{'props'}->{'opt_preformatted'}; + } + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + + my $text = format_text_mail($u, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + + if ($u->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($u, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding); +# if $LJ::UNICODE; + } + + LJ::send_mail($msg); + + } +} + +sub enter_comment { + my ($journalu, $parent, $item, $comment, $errref) = @_; + + my $partid = $parent->{talkid}; + my $itemid = $item->{itemid}; + + my $err = sub { + $$errref = join(": ", @_); + return 0; + }; + + return $err->("Invalid user object passed.") + unless LJ::isu($journalu); + + use Golem; + my $tnet = Golem::get_containing_net(LJ::get_remote_ip(), {"with_props" => 1}); + $tnet = Golem::get_net(LJ::get_remote_ip(), 32, {"with_props" => 1}) unless $tnet; + if ($tnet && $tnet->{'props'}->{'data'}->{'ban_comments'} && + $tnet->{'props'}->{'data'}->{'ban_comments'}->{$journalu->{'userid'}}) { + return $err->('Sorry, you are not allowed to leave comments.'); + } + + my $jtalkid = LJ::alloc_user_counter($journalu, "T"); + return $err->("Database Error", "Could not generate a talkid necessary to post this comment.") + unless $jtalkid; + + # insert the comment + my $posterid = $comment->{u} ? $comment->{u}{userid} : 0; + + my $errstr; + $journalu->talk2_do("L", $itemid, \$errstr, + "INSERT INTO talk2 ". + "(journalid, jtalkid, nodetype, nodeid, parenttalkid, posterid, datepost, state) ". + "VALUES (?,?,'L',?,?,?,NOW(),?)", + $journalu->{userid}, $jtalkid, $itemid, $partid, $posterid, $comment->{state}); + if ($errstr) { + return $err->("Database Error", + "There was an error posting your comment to the database. " . + "Please report this. The error is: $errstr"); + } + + LJ::MemCache::incr([$journalu->{'userid'}, "talk2ct:$journalu->{'userid'}"]); + + $comment->{talkid} = $jtalkid; + + # record IP if anonymous + LJ::Talk::record_anon_comment_ip($journalu, $comment->{talkid}, LJ::get_remote_ip()) + unless $posterid; + + # add to poster's talkleft table, or the xfer place + if ($posterid) { + my $table; + my $db = LJ::get_cluster_master($comment->{u}); + + if ($db) { + # remote's cluster is writable + $table = "talkleft"; + } else { + # log to global cluster, another job will move it later. + $db = LJ::get_db_writer(); + $table = "talkleft_xfp"; + } + my $pub = $item->{'security'} eq "public" ? 1 : 0; + if ($db) { + $db->do("INSERT INTO $table (userid, posttime, journalid, nodetype, ". + "nodeid, jtalkid, publicitem) VALUES (?, UNIX_TIMESTAMP(), ". + "?, 'L', ?, ?, ?)", undef, + $posterid, $journalu->{userid}, $itemid, $jtalkid, $pub); + + LJ::MemCache::incr([$posterid, "talkleftct:$posterid"]); + } else { + # both primary and backup talkleft hosts down. can't do much now. + } + } + + $journalu->do("INSERT INTO talktext2 (journalid, jtalkid, subject, body) ". + "VALUES (?, ?, ?, ?)", undef, + $journalu->{userid}, $jtalkid, $comment->{subject}, + LJ::text_compress($comment->{body})); + die $journalu->errstr if $journalu->err; + + my $memkey = "$journalu->{'clusterid'}:$journalu->{'userid'}:$jtalkid"; + LJ::MemCache::set([$journalu->{'userid'},"talktext:$memkey"], [$comment->{subject}, $comment->{body}]); #$comment->{unknown8bit} ? + + # dudata + my $bytes = length($comment->{subject}) + length($comment->{body}); + # we used to do a LJ::dudata_set(..) on 'T' here, but decided + # we could defer that. to find size of a journal, summing + # bytes in dudata is too slow (too many seeks) + + my %talkprop; # propname -> value + # meta-data + $talkprop{'unknown8bit'} = 1 if $comment->{unknown8bit}; + $talkprop{'subjecticon'} = $comment->{subjecticon}; + + $talkprop{'picture_keyword'} = $comment->{picture_keyword}; + + $talkprop{'opt_preformatted'} = $comment->{preformat} ? 1 : 0; + if ($journalu->{'opt_logcommentips'} eq "A" || + ($journalu->{'opt_logcommentips'} eq "S" && $comment->{usertype} ne "user")) + { + my $ip = BML::get_remote_ip(); + my $proxies = join(", ", LJ::filter_out_ip($ip, BML::get_client_header('X-Forwarded-For'))); + my $old_fs = $/; + $/ = ", "; + chomp($proxies); + $/ = $old_fs; + $ip = "$ip, via $proxies" if $proxies; + $talkprop{'poster_ip'} = $ip; + } + + # remove blank/0 values (defaults) + foreach (keys %talkprop) { delete $talkprop{$_} unless $talkprop{$_}; } + + # update the talkprops + LJ::load_props("talk"); + if (%talkprop) { + my $values; + my $hash = {}; + foreach (keys %talkprop) { + my $p = LJ::get_prop("talk", $_); + next unless $p; + $hash->{$_} = $talkprop{$_}; + my $tpropid = $p->{'tpropid'}; + my $qv = $journalu->quote($talkprop{$_}); + $values .= "($journalu->{'userid'}, $jtalkid, $tpropid, $qv),"; + } + if ($values) { + chop $values; + $journalu->do("INSERT INTO talkprop2 (journalid, jtalkid, tpropid, value) ". + "VALUES $values"); + die $journalu->errstr if $journalu->err; + } + LJ::MemCache::set([$journalu->{'userid'}, "talkprop:$journalu->{'userid'}:$jtalkid"], $hash); + } + + # record up to 25 (or $LJ::TALK_MAX_URLS) urls from a comment + my (%urls, $dbh); + if ($LJ::TALK_MAX_URLS && + ( %urls = map { $_ => 1 } LJ::get_urls($comment->{body}) ) && + ( $dbh = LJ::get_db_writer() )) # don't log if no db available + { + my (@bind, @vals); + my $ip = LJ::get_remote_ip(); + while (my ($url, undef) = each %urls) { + push @bind, '(?,?,?,?,UNIX_TIMESTAMP(),?)'; + push @vals, $posterid, $journalu->{userid}, $ip, $jtalkid, $url; + last if @bind >= $LJ::TALK_MAX_URLS; + } + my $bind = join(',', @bind); + my $sql = qq{ + INSERT DELAYED INTO commenturls + (posterid, journalid, ip, jtalkid, timecreate, url) + VALUES $bind + }; + $dbh->do($sql, undef, @vals); + } + + # update the "replycount" summary field of the log table + if ($comment->{state} eq 'A') { + LJ::replycount_do($journalu, $itemid, "incr"); + } + + # update the "hasscreened" property of the log item if needed + if ($comment->{state} eq 'S') { + LJ::Talk::screenedcount_do($journalu, $itemid, "incr"); + } + + return $jtalkid; +} + +# XXX these strings should be in talk, but moving them means we have +# to retranslate. so for now we're just gonna put it off. +my $SC = '/talkpost_do.bml'; + +sub init { + my ($form, $remote, $need_captcha, $errret) = @_; + my $sth; + + my $err = sub { + my $error = shift; + push @$errret, $error; + + my $ip = LJ::get_remote_ip(); + print STDERR "$ip talklib.pl: $error\n"; + # change return status from 200 to 403: + BML::set_status(403); # 403 Forbidden + + return undef; + }; + my $bmlerr = sub { + return $err->($BML::ML{$_[0]}); + }; + + my $init = LJ::Talk::init($form); + return $err->($init->{error}) if $init->{error}; + + my $journalu = $init->{'journalu'}; + return $bmlerr->('talk.error.nojournal') unless $journalu; + return $err->($LJ::MSG_READONLY_USER) if LJ::get_cap($journalu, "readonly"); + + return $err->("Account is locked, unable to post comment.") if $journalu->{statusvis} eq 'L'; + + my $r = Apache->request; + $r->notes("journalid" => $journalu->{'userid'}); + + my $dbcr = LJ::get_cluster_def_reader($journalu); + return $bmlerr->('error.nodb') unless $dbcr; + + my $itemid = $init->{'itemid'}+0; + + my $item = LJ::Talk::get_journal_item($journalu, $itemid); + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + return $bmlerr->('talk.error.noentry'); + } + + my $iprops = $item->{'props'}; + my $ditemid = $init->{'ditemid'}+0; + + my $talkurl = LJ::journal_base($journalu) . "/$ditemid.html"; + $init->{talkurl} = $talkurl; + + ### load users + LJ::load_userids_multiple([ + $item->{'posterid'} => \$init->{entryu}, + ], [ $journalu ]); + LJ::load_user_props($journalu, "opt_logcommentips"); + + if ($form->{'userpost'} && $form->{'usertype'} ne "user") { + unless ($form->{'usertype'} eq "cookieuser" && + $form->{'userpost'} eq $form->{'cookieuser'}) { + $bmlerr->("$SC.error.confused_identity"); + } + } + + # anonymous/cookie users cannot authenticate with ecphash + if ($form->{'ecphash'} && $form->{'usertype'} ne "user") { + $bmlerr->("$SC.error.badusername"); + return undef; + } + + my $cookie_auth; + if ($form->{'usertype'} eq "cookieuser") { + $bmlerr->("$SC.error.lostcookie") + unless ($remote && $remote->{'user'} eq $form->{'cookieuser'}); + return undef if @$errret; + + $cookie_auth = 1; + $form->{'userpost'} = $remote->{'user'}; + $form->{'usertype'} = "user"; + } + # XXXevan hack: remove me when we fix preview. + $init->{cookie_auth} = $cookie_auth; + + # test accounts may only comment on other test accounts. + if ((grep { $form->{'userpost'} eq $_ } @LJ::TESTACCTS) && + !(grep { $journalu->{'user'} eq $_ } @LJ::TESTACCTS)) + { + $bmlerr->("$SC.error.testacct"); + } + + my $userpost = lc($form->{'userpost'}); + my $up; # user posting + my $exptype; # set to long if ! after username + my $ipfixed; # set to remote ip if < after username + my $used_ecp; # ecphash was validated and used + + if ($form->{'usertype'} eq "user") { + if ($form->{'userpost'}) { + + # parse inline login opts + if ($form->{'userpost'} =~ s/[!<]{1,2}$//) { + $exptype = 'long' if index($&, "!") >= 0; + $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; + } + + $up = LJ::load_user($form->{'userpost'}); + if ($up) { + ### see if the user is banned from posting here + if (LJ::is_banned($up, $journalu)) { + $bmlerr->("$SC.error.banned"); + } + + unless ($up->{'journaltype'} eq "P" || + ($up->{'journaltype'} eq "I" && $cookie_auth)) { + $bmlerr->("$SC.error.postshared"); + } + + # if we're already authenticated via cookie, then userpost was set + # to the authenticated username, so we got into this block, but we + # don't want to re-authenticate, so just skip this + unless ($cookie_auth) { + + # if ecphash present, authenticate on that + if ($form->{'ecphash'}) { + + if ($form->{'ecphash'} eq + LJ::Talk::ecphash($itemid, $form->{'parenttalkid'}, $up->{'password'})) + { + $used_ecp = 1; + } else { + $bmlerr->("$SC.error.badpassword"); + } + + # otherwise authenticate on username/password + } else { + my $ok; + if ($form->{response}) { + $ok = LJ::challenge_check_login($up, $form->{chal}, $form->{response}); + } else { + $ok = LJ::auth_okay($up, $form->{'password'}, $form->{'hpassword'}); + } + $bmlerr->("$SC.error.badpassword") unless $ok; + } + } + + # if the user chooses to log in, do so + if ($form->{'do_login'} && ! @$errret) { + $init->{didlogin} = $up->make_login_session($exptype, $ipfixed); + } + } else { + $bmlerr->("$SC.error.badusername"); + } + } else { + $bmlerr->("$SC.error.nousername"); + } + } + + # OpenID + if (LJ::OpenID::consumer_enabled() && ( + ($form->{'usertype'} eq 'openid' || $form->{'usertype'} eq 'openid_cookie') || + ($form->{'usertype'} eq 'ljc_openid') + )) { + + if ($form->{'usertype'} eq 'ljc_openid' && $form->{'ljc_oidurl'}) { + $form->{'oidurl'} = "http://www.livejournal.com/users/" . $form->{'ljc_oidurl'}; +# $form->{'oiddo_login'} = 1; + $form->{'exptype'} = "long"; + } + + return $err->("No OpenID identity URL entered") unless $form->{'oidurl'}; + + use LJ::OpenID; # to-TOP + + if ($remote && defined $remote->openid_identity && + ( + $form->{'usertype'} eq 'openid_cookie' || + $form->{'usertype'} eq 'openid' && $remote->openid_identity eq $form->{'oidurl'} || + $form->{'usertype'} eq 'ljc_openid' && ( + $remote->openid_identity eq "http://www.livejournal.com/users/" . $form->{'ljc_oidurl'} . "/" || + $remote->openid_identity eq "http://" . $form->{'ljc_oidurl'} . ".livejournal.com/" || + $remote->openid_identity eq "http://users.livejournal.com/" . $form->{'ljc_oidurl'} . "/" + ) + ) + ) { + + $up = $remote; + + ### see if the user is banned from posting here + if (LJ::is_banned($up, $journalu)) { + $bmlerr->("$SC.error.banned"); + } + + if ($form->{'oiddo_login'}) { + $up->make_login_session($form->{'exptype'}, $form->{'ipfixed'}); + + if ($form->{'ljc_howlong'}) { + my $ljc_days = 1; + if ($form->{'ljc_howlong'} eq "a") { + $ljc_days = 1; + } + if ($form->{'ljc_howlong'} eq "b") { + $ljc_days = 7; + } + if ($form->{'ljc_howlong'} eq "c") { + $ljc_days = 31; + } + if ($form->{'ljc_howlong'} eq "d") { + $ljc_days = 365; + } + BML::set_cookie("ljsession", $BML::COOKIE{'ljsession'}, time() + 60*60*24*$ljc_days, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + } + } + } else { # First time through + my $csr = LJ::OpenID::consumer(); + my $exptype = $form->{'exptype'} ? $form->{'exptype'} : 'short'; + my $etime = $form->{'etime'} ? $form->{'etime'} : 0; + my $ipfixed = 0; + + # parse inline login opts + if ($form->{'oidurl'} =~ s/[!<]{1,2}$//) { + if (index($&, "!") >= 0) { + $exptype = 'long'; + $etime = time()+60*60*24*60; + } + $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; + } + + my $tried_local_ref = LJ::OpenID::blocked_hosts($csr); + + my $claimed_id = $csr->claimed_identity($form->{'oidurl'}); + + unless ($claimed_id) { + return $err->("Your OpenID is blocked. Please use another OpenID provider.") if $$tried_local_ref; + return $err->("No claimed id: ".$csr->err); + } + + # Store their cleaned up identity url vs what they + # actually typed in + $form->{'oidurl'} = $claimed_id->claimed_url(); + + # Store the entry + my $pendcid = LJ::alloc_user_counter($journalu, "C"); + + $err->("Unable to allocate pending id") unless $pendcid; + + # Since these were gotten from the oidurl and won't + # persist in the form data + $form->{'exptype'} = $exptype; + $form->{'etime'} = $etime; + $form->{'ipfixed'} = $ipfixed; + my $penddata = Storable::nfreeze($form); + + $err->("Unable to get database handle to store pending comment") unless $journalu->writer; + + $journalu->do("INSERT INTO pendcomments (jid, pendcid, data, datesubmit) VALUES (?, ?, ?, UNIX_TIMESTAMP())", undef, $journalu->{'userid'}, $pendcid, $penddata); + + $err->($journalu->errstr) if $journalu->err; + + my $check_url = $claimed_id->check_url( + return_to => "$LJ::SITEROOT/talkpost_do.bml?jid=$journalu->{'userid'}&pendcid=$pendcid", + trust_root => "http://*.$LJ::DOMAIN/", + delayed_return => 1, + ); + # Don't redirect them if errors + return undef if @$errret; + return BML::redirect($check_url); + } + } + + # validate the challenge/response value (anti-spammer) + unless ($used_ecp) { + my $chrp_err; + if (my $chrp = $form->{'chrp1'}) { + my ($c_ditemid, $c_uid, $c_time, $c_chars, $c_res) = + split(/\-/, $chrp); + my $chal = "$c_ditemid-$c_uid-$c_time-$c_chars"; + my $secret = LJ::get_secret($c_time); + my $res = Digest::MD5::md5_hex($secret . $chal); + if ($res ne $c_res) { + $chrp_err = "invalid"; + } elsif ($c_time < time() - 2*60*60) { + $chrp_err = "too_old" if $LJ::REQUIRE_TALKHASH_NOTOLD; + } + } else { + $chrp_err = "missing"; + } + if ($chrp_err) { + my $ip = LJ::get_remote_ip(); + if ($LJ::DEBUG_TALKSPAM) { + my $ruser = $remote ? $remote->{user} : "[nonuser]"; + print STDERR "talkhash error: from $ruser \@ $ip - $chrp_err - $talkurl\n"; + } + if ($LJ::REQUIRE_TALKHASH) { + return $err->("Sorry, form expired. Press back, copy text, reload form, paste into new form, and re-submit.") + if $chrp_err eq "too_old"; + return $err->("Missing parameters"); + } + } + } + + # check that user can even view this post, which is required + # to reply to it + #### Check security before viewing this post + unless (LJ::can_view($up, $item)) { + $bmlerr->("$SC.error.mustlogin") unless (defined $up); + $bmlerr->("$SC.error.noauth"); + return undef; + } + + # If the reply is to a comment, check that it exists. + # if it's screened, check that the user has permission to + # reply and unscreen it + + my $parpost; + my $partid = $form->{'parenttalkid'}+0; + + if ($partid) { + $parpost = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $partid); + unless ($parpost) { + $bmlerr->("$SC.error.noparent"); + } + + # can't use $remote because we may get here + # with a reply from email. so use $up instead of $remote + # in the call below. + + if ($parpost && $parpost->{'state'} eq "S" && + !LJ::Talk::can_unscreen($up, $journalu, $init->{entryu}, $init->{entryu}{'user'})) { + $bmlerr->("$SC.error.screened"); + } + } + $init->{parpost} = $parpost; + + # don't allow anonymous comments on syndicated items + if ($journalu->{'journaltype'} eq "Y" && $journalu->{'opt_whocanreply'} eq "all") { + $journalu->{'opt_whocanreply'} = "reg"; + } + + if ( + ($journalu->{'opt_whocanreply'} eq "friends" && $form->{'usertype'} ne "user") || + ($journalu->{'opt_whocanreply'} eq "reg" && + $form->{'usertype'} ne "user" && + $form->{'usertype'} ne "openid" && + $form->{'usertype'} ne "openid_cookie" && + $form->{'usertype'} ne "cookieuser" && + $form->{'usertype'} ne "ljc_openid") + ) { + $bmlerr->("$SC.error.noanon"); + } + + if ($iprops->{'opt_nocomments'}) { + $bmlerr->("$SC.error.nocomments"); + } + + if ($up) { + if ($up->{'status'} eq "N" && $up->{'journaltype'} ne "I") { + $bmlerr->("$SC.error.noverify"); + } + if ($up->{'statusvis'} eq "D") { + $bmlerr->("$SC.error.deleted"); + } elsif ($up->{'statusvis'} eq "S") { + $bmlerr->("$SC.error.suspended"); + } + } + + if ($journalu->{'opt_whocanreply'} eq "friends") { + if ($up) { + if ($up->{'userid'} != $journalu->{'userid'}) { + unless (LJ::is_friend($journalu, $up)) { + $err->(BML::ml("$SC.error.notafriend", {'user'=>$journalu->{'user'}})); + } + } + } else { + $err->(BML::ml("$SC.error.friendsonly", {'user'=>$journalu->{'user'}})); + } + } + + $bmlerr->("$SC.error.blankmessage") unless $form->{'body'} =~ /\S/; + + # in case this post comes directly from the user's mail client, it + # may have an encoding field for us. + if ($form->{'encoding'}) { + $form->{'body'} = Unicode::MapUTF8::to_utf8({-string=>$form->{'body'}, -charset=>$form->{'encoding'}}); + $form->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$form->{'subject'}, -charset=>$form->{'encoding'}}); + } + + # unixify line-endings + $form->{'body'} =~ s/\r\n/\n/g; + + # now check for UTF-8 correctness, it must hold + + return $err->("") unless LJ::text_in($form); + + $init->{unknown8bit} = 0; + unless (LJ::is_ascii($form->{'body'}) && LJ::is_ascii($form->{'subject'})) { + if ($LJ::UNICODE) { + # no need to check if they're well-formed, we did that above + } else { + # so rest of site can change chars to ? marks until + # default user's encoding is set. (legacy support) + $init->{unknown8bit} = 1; + } + } + + my ($bl, $cl) = LJ::text_length($form->{'body'}); + if ($cl > LJ::CMAX_COMMENT) { + $err->(BML::ml("$SC.error.manychars", {'current'=>$cl, 'limit'=>LJ::CMAX_COMMENT})); + } elsif ($bl > LJ::BMAX_COMMENT) { + $err->(BML::ml("$SC.error.manybytes", {'current'=>$bl, 'limit'=>LJ::BMAX_COMMENT})); + } + # the Subject can be silently shortened, no need to reject the whole comment + $form->{'subject'} = LJ::text_trim($form->{'subject'}, 100, 100); + + my $subjecticon = ""; + if ($form->{'subjecticon'} ne "none" && $form->{'subjecticon'} ne "") { + $subjecticon = LJ::trim(lc($form->{'subjecticon'})); + } + + # figure out whether to post this comment screened + my $state = 'A'; + my $screening = LJ::Talk::screening_level($journalu, $ditemid >> 8); + if ($screening eq 'A' || + ($screening eq 'R' && !$up) || +# was: $form->{'usertype'} eq "anonymous") || +# This causes problems with people filling this form as openid, +# and posting as anonymous - MV + ($screening eq 'F' && !($up && LJ::is_friend($journalu, $up)))) { + $state = 'S'; + } + $state = 'A' if LJ::Talk::can_unscreen($up, $journalu, $init->{entryu}, $init->{entryu}{user}); + + my $parent = { + state => $parpost->{state}, + talkid => $partid, + }; + my $comment = { + u => $up, + usertype => $form->{'usertype'}, + subject => $form->{'subject'}, + body => $form->{'body'}, + unknown8bit => $init->{unknown8bit}, + subjecticon => $subjecticon, + preformat => $form->{'prop_opt_preformatted'}, + picture_keyword => $form->{'prop_picture_keyword'}, + state => $state, + }; + + $init->{item} = $item; + $init->{parent} = $parent; + $init->{comment} = $comment; + + # anti-spam captcha check + if (ref $need_captcha eq 'SCALAR') { + + # see if they're in the second+ phases of a captcha check. + # are they sending us a response? + if ($form->{captcha_chal}) { + + # assume they won't pass and re-set the flag + $$need_captcha = 1; + + # if they typed "audio", we don't double-check if they still need + # a captcha (they still do), they just want an audio version. + if (lc($form->{answer}) eq 'audio') { + return; + } + + my ($capid, $anum) = LJ::Captcha::session_check_code($form->{captcha_chal}, + $form->{answer}, $journalu); + + return $err->("Incorrect response to spam robot challenge.") unless $capid && $anum; + my $expire_u = $comment->{'u'} || LJ::load_user('system'); + LJ::Captcha::expire($capid, $anum, $expire_u->{userid}); + + } else { + + my $show_captcha = sub { + return 1 if $LJ::HUMAN_CHECK{'comment_html_auth'}; + + # Anonymous commenter + return 1 if $LJ::HUMAN_CHECK{'comment_html_anon'} && ! LJ::isu($comment->{'u'}); + + # Identity commenter + return 1 if $LJ::HUMAN_CHECK{'comment_html_anon'} && + $comment->{'u'}->identity() && + ! LJ::is_friend($journalu, $comment->{'u'}); + }; + + $$need_captcha = + ($LJ::HUMAN_CHECK{anonpost} || $LJ::HUMAN_CHECK{authpost}) && + ! LJ::Talk::Post::check_rate($comment->{'u'}, $journalu, $talkurl); + + if ($show_captcha->()) { + # see if they have any tags or URLs + if ($form->{'body'} =~ /<[a-z]/i) { + # strip white-listed bare tags w/o attributes, + # then see if they still have HTML. if so, it's + # questionable. (can do evil spammy-like stuff w/ + # attributes and other elements) + my $body_copy = $form->{'body'}; + $body_copy =~ s/<(?:q|blockquote|b|strong|i|em|cite|sub|sup|var|del|tt|code|pre|p)>//ig; + $$need_captcha = 1 if $body_copy =~ /<[a-z]/i; + } + # multiple URLs is questionable too +# $$need_captcha = 1 if +# $form->{'body'} =~ /\b(?:http|ftp)\b.+\b(?:http|ftp)\b/s; + $$need_captcha = 1 if + $form->{'body'} =~ /\b(?:http|ftp):\/\//s; + } + + # if the user is anonymous and the IP is marked, ignore rates and always human test. + $$need_captcha = 1 if $LJ::HUMAN_CHECK{anonpost} && + ! $comment->{'u'} && + LJ::sysban_check('talk_ip_test', LJ::get_remote_ip()); + + if ($$need_captcha) { + return $err->("Please confirm you are a human below."); + } + } + } + + return undef if @$errret; + return $init; +} + +# returns 1 on success. 0 on fail (with $$errref set) +sub post_comment { + my ($entryu, $journalu, $comment, $parent, $item, $errref) = @_; + + # unscreen the parent comment if needed + if ($parent->{state} eq 'S') { + LJ::Talk::unscreen_comments($journalu, $item->{itemid}, [$parent->{talkid}]); + $parent->{state} = 'A'; + } + + # make sure they're not underage + if ($comment->{u} && $comment->{u}->underage) { + $$errref = $LJ::UNDERAGE_ERROR; + return 0; + } + + # check for duplicate entry (double submission) + # Note: we don't do it inside a locked section like ljprotocol.pl's postevent, + # so it's not perfect, but it works pretty well. + my $posterid = $comment->{u} ? $comment->{u}{userid} : 0; + my $jtalkid; + + # check for dup ID in memcache. + my $memkey; + if (@LJ::MEMCACHE_SERVERS) { + my $md5_b64 = Digest::MD5::md5_base64( + join(":", ($comment->{body}, $comment->{subject}, + $comment->{subjecticon}, $comment->{preformat}, + $comment->{picture_keyword}))); + $memkey = [$journalu->{userid}, "tdup:$journalu->{userid}:$item->{itemid}-$parent->{talkid}-$posterid-$md5_b64" ]; + $jtalkid = LJ::MemCache::get($memkey); + } + + # they don't have a duplicate... + unless ($jtalkid) { + # XXX do select and delete $talkprop{'picture_keyword'} if they're lying + my $pic = LJ::get_pic_from_keyword($comment->{u}, $comment->{picture_keyword}); + delete $comment->{picture_keyword} unless $pic && $pic->{'state'} eq 'N'; + $comment->{pic} = $pic; + + # put the post in the database + my $ditemid = $item->{itemid}*256 + $item->{anum}; + $jtalkid = enter_comment($journalu, $parent, $item, $comment, $errref); + return 0 unless $jtalkid; + + # save its identifying characteristics to protect against duplicates. + LJ::MemCache::set($memkey, $jtalkid+0, time()+60*10); + + # send some emails + mail_comments($entryu, $journalu, $parent, $comment, $item); + + # log the event + # this function doesn't do anything. + # LJ::event_register($dbcm, "R", $journalu->{'userid'}, $ditemid); + # FUTURE: log events type 'T' (thread) up to root + } + + # the caller wants to know the comment's talkid. + $comment->{talkid} = $jtalkid; + + # cluster tracking + LJ::mark_user_active($comment->{u}, 'comment'); + + return 1; +} + +# XXXevan: this function should have its functionality migrated to talkpost. +# because of that, it's probably not worth the effort to make it not mangle $form... +sub make_preview { + my ($talkurl, $cookie_auth, $form) = @_; + my $ret = ""; + + my $cleansubject = $form->{'subject'}; + LJ::CleanHTML::clean_subject(\$cleansubject); + + $ret .= ""; + $ret .= ""; + + my $event = $form->{'body'}; + my $spellcheck_html; + if ($LJ::SPELLER && $form->{'do_spellcheck'}) { + my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, + 'color' => '', }; + $spellcheck_html = $s->check_html(\$event); + } + LJ::CleanHTML::clean_comment(\$event, $form->{'prop_opt_preformatted'}); + + $ret .= "$BML::ML{'/talkpost_do.bml.preview.subject'} " . LJ::ehtml($cleansubject) . "
    \n"; + if ($spellcheck_html) { + $ret .= $spellcheck_html; + $ret .= "

    "; + } else { + $ret .= $event; + } + + $ret .= "


    "; + $ret .= "

    \n"; + $ret .= "
    "; + $ret .= "

    "; + + # change mode: + delete $form->{'submitpreview'}; $form->{'submitpost'} = 1; + if ($cookie_auth) { + $form->{'usertype'} = "cookieuser"; + delete $form->{'userpost'}; + } + delete $form->{'do_spellcheck'}; + foreach (keys %$form) { + $ret .= LJ::html_hidden($_, $form->{$_}) + unless $_ eq 'body' || $_ eq 'subject' || $_ eq 'prop_opt_preformatted'; + } + + $ret .= "
    \n"; + $ret .= "\n"; + if ($LJ::SPELLER) { + $ret .= " "; + } + $ret .= "

    "; + $ret .= "$BML::ML{'/talkpost.bml.opt.noautoformat'} ". + LJ::html_check({ 'name' => 'prop_opt_preformatted', + selected => $form->{'prop_opt_preformatted'} }); + $ret .= LJ::help_icon("noautoformat", " "); + $ret .= "

    "; + + $ret .= "

    "; + + $ret .= "
    "; + return $ret; +} + +# given a journalu and jitemid, return 1 if the entry +# is over the maximum comments allowed. +sub over_maxcomments { + my ($journalu, $jitemid) = @_; + $journalu = LJ::want_user($journalu); + $jitemid += 0; + return 0 unless $journalu && $jitemid; + + my $count = LJ::Talk::get_replycount($journalu, $jitemid); + return ($count >= LJ::get_cap($journalu, 'maxcomments')) ? 1 : 0; +} + +# more anti-spammer rate limiting. returns 1 if rate is okay, 0 if too fast. +sub check_rate { + my ($remote, $journalu, $talkurl) = @_; + + # we require memcache to do rate limiting efficiently + return 1 unless @LJ::MEMCACHE_SERVERS; + + # return right away if the account is suspended + return 0 if $remote && $remote->{'statusvis'} =~ /[SD]/; + + my $ip = LJ::get_remote_ip(); + my $now = time(); + my @watch; + +# Now comments from Openid users are treated the same as anonymous +# vis-a-vis spam rates - MV, Nov 2014 (antimakaka) + if ($remote && ! $remote->openid_identity) { + # registered human (or human-impersonating robot) + push @watch, + [ + "talklog:$remote->{userid}", + $LJ::RATE_COMMENT_AUTH || [ [ 200, 3600 ], [ 20, 60 ] ], + ]; + } else { + # anonymous, per IP address (robot or human) + push @watch, + [ + "talklog:$ip", + $LJ::RATE_COMMENT_ANON || + [ [ 300, 3600 ], [ 200, 1800 ], [ 150, 900 ], [ 15, 60 ] ] + ]; + + # anonymous, per journal. + # this particular limit is intended to combat flooders, instead + # of the other 'spammer-centric' limits. + push @watch, + [ + "talklog:anonin:$journalu->{userid}", + $LJ::RATE_COMMENT_ANON || + [ [ 300, 3600 ], [ 200, 1800 ], [ 150, 900 ], [ 15, 60 ] ] + ]; + + # throttle based on reports of spam + push @watch, + [ + "spamreports:anon:$ip", + $LJ::SPAM_COMMENT_RATE || + [ [ 50, 86400], [ 10, 3600 ] ] + ]; + } + + + WATCH: + foreach my $watch (@watch) { + my ($key, $rates) = ($watch->[0], $watch->[1]); + my $max_period = $rates->[0]->[1]; + + my $log = LJ::MemCache::get($key); + + # parse the old log + my @times; + if (length($log) % 4 == 1 && substr($log,0,1) eq $RATE_DATAVER) { + my $ct = (length($log)-1) / 4; + for (my $i=0; $i<$ct; $i++) { + my $time = unpack("N", substr($log,$i*4+1,4)); + push @times, $time if $time > $now - $max_period; + } + } + + # add this event + push @times, $now unless $key =~ /^spamreports/; + + # check rates + foreach my $rate (@$rates) { + my ($allowed, $period) = ($rate->[0], $rate->[1]); + my $events = scalar grep { $_ > $now-$period } @times; + if ($events > $allowed) { + + if ($LJ::DEBUG_TALK_RATE && + LJ::MemCache::add("warn:$key", 1, 600)) { + + my $ruser = (exists $remote->{'user'}) ? $remote->{'user'} : 'Not logged in'; + my $nowtime = localtime($now); + my $body = < $allowed allowed / $period secs + Remote user: $ruser + Remote IP: $ip + Time caught: $nowtime + Posting to: $journalu->{'user'} + URL: $talkurl +EOM + LJ::send_mail({ + 'to' => $LJ::DEBUG_TALK_RATE, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => "talk spam: $key", + 'body' => $body, + }); + } + + return 0 if $LJ::ANTI_TALKSPAM; + last WATCH; + } + } + + # build the new log + my $newlog = $RATE_DATAVER; + foreach (@times) { + $newlog .= pack("N", $_); + } + + LJ::MemCache::set($key, $newlog, $max_period); + } + + return 1; +} + +1; diff --git a/local/cgi-bin/weblib.pl b/local/cgi-bin/weblib.pl new file mode 100755 index 0000000..bd18c87 --- /dev/null +++ b/local/cgi-bin/weblib.pl @@ -0,0 +1,1870 @@ +#!/usr/bin/perl +# + +package LJ; +use strict; + +# load the bread crumb hash +require "$ENV{'LJHOME'}/cgi-bin/crumbs.pl"; + +# +# name: LJ::img +# des: Returns an HTML <img> or <input> tag to an named image +# code, which each site may define with a different image file with +# its own dimensions. This prevents hard-coding filenames & sizes +# into the source. The real image data is stored in LJ::Img, which +# has default values provided in cgi-bin/imageconf.pl but can be +# overridden in cgi-bin/ljconfig.pl. +# args: imagecode, type?, attrs? +# des-imagecode: The unique string key to reference the image. Not a filename, +# but the purpose or location of the image. +# des-type: By default, the tag returned is an <img> tag, but if 'type' +# is "input", then an input tag is returned. +# des-attrs: Optional hashref of other attributes. If this isn't a hashref, +# then it's assumed to be a scalar for the 'name' attribute for +# input controls. +# +sub img +{ + my $ic = shift; + my $type = shift; # either "" or "input" + my $attr = shift; + + my $attrs; + if ($attr) { + if (ref $attr eq "HASH") { + foreach (keys %$attr) { + $attrs .= " $_=\"" . LJ::ehtml($attr->{$_}) . "\""; + } + } else { + $attrs = " name=\"$attr\""; + } + } + + my $i = $LJ::Img::img{$ic}; + if ($type eq "") { + return "{'src'}\" width=\"$i->{'width'}\" ". + "height=\"$i->{'height'}\" alt=\"$i->{'alt'}\" title=\"$i->{'alt'}\" ". + "border='0'$attrs />"; + } + if ($type eq "input") { + return "{'src'}\" ". + "width=\"$i->{'width'}\" height=\"$i->{'height'}\" title=\"$i->{'alt'}\" ". + "alt=\"$i->{'alt'}\" border='0'$attrs />"; + } + return "XXX"; +} + +# +# name: LJ::date_to_view_links +# class: component +# des: Returns HTML of date with links to user's journal. +# args: u, date +# des-date: date in yyyy-mm-dd form. +# returns: HTML with yyy, mm, and dd all links to respective views. +# +sub date_to_view_links +{ + my ($u, $date) = @_; + return unless $date =~ /^(\d\d\d\d)-(\d\d)-(\d\d)/; + + my ($y, $m, $d) = ($1, $2, $3); + my ($nm, $nd) = ($m+0, $d+0); # numeric, without leading zeros + my $user = $u->{'user'}; + my $base = LJ::journal_base($u); + + my $ret; + $ret .= "$y-"; + $ret .= "$m-"; + $ret .= "$d"; + return $ret; +} + + +# +# name: LJ::auto_linkify +# des: Takes a plain-text string and changes URLs into tags (auto-linkification) +# args: str +# arg-str: The string to perform auto-linkification on. +# returns: The auto-linkified text. +# +sub auto_linkify +{ + my $str = shift; + my $match = sub { + my $str = shift; + if ($str =~ /^(.*?)(&(#39|quot|lt|gt)(;.*)?)$/) { + return "$1$2"; + } else { + return "$str"; + } + }; + $str =~ s!https?://[^\s\'\"\<\>]+[a-zA-Z0-9_/&=\-]! $match->($&); !ge; + return $str; +} + + +# +# name: LJ::make_authas_select +# des: Given a u object and some options, determines which users the given user +# can switch to. If the list exists, returns a select list and a submit +# button with labels. Otherwise returns a hidden element. +# returns: string of html elements +# args: u, opts? +# des-opts: Optional. Valid keys are: +# 'authas' - current user, gets selected in drop-down +# 'label' - label to go before form elements +# 'button' - button label for submit button +# others - arguments to pass to LJ::get_authas_list +# +sub make_authas_select { + my ($u, $opts) = @_; # type, authas, label, button + + my @list = LJ::get_authas_list($u, $opts); + + # only do most of form if there are options to select from + if (@list > 1) { + return ($opts->{'label'} || 'Work as user:') . " " . + LJ::html_select({ 'name' => 'authas', + 'selected' => $opts->{'authas'} || $u->{'user'}}, + map { $_, $_ } @list) . " " . + LJ::html_submit(undef, $opts->{'button'} || 'Switch'); + } + + # no communities to choose from, give the caller a hidden + return LJ::html_hidden('authas', $opts->{'authas'} || $u->{'user'}); +} + +# +# name: LJ::help_icon +# des: Returns BML to show a help link/icon given a help topic, or nothing +# if the site hasn't defined a URL for that topic. Optional arguments +# include HTML/BML to place before and after the link/icon, should it +# be returned. +# args: topic, pre?, post? +# des-topic: Help topic key. See doc/ljconfig.pl.txt for examples. +# des-pre: HTML/BML to place before the help icon. +# des-post: HTML/BML to place after the help icon. +# +sub help_icon +{ + my $topic = shift; + my $pre = shift; + my $post = shift; + return "" unless (defined $LJ::HELPURL{$topic}); + return "$pre$post"; +} + + +# +# name: LJ::bad_input +# des: Returns common BML for reporting form validation errors in +# a bulletted list. +# returns: BML showing errors. +# args: error* +# des-error: A list of errors +# +sub bad_input +{ + # change return status from 200 to 403: + BML::set_status(403); # 403 Forbidden + + my @errors = @_; + my $ret = ""; + $ret .= "\n
      \n"; + foreach (@errors) { + $ret .= "
    • $_
    • \n"; + } + $ret .= "
    \n"; + return $ret; +} + + +# +# name: LJ::error_list +# des: Returns an error bar with bulleted list of errors +# returns: BML showing errors +# args: error* +# des-error: A list of errors +# +sub error_list +{ + my @errors = @_; + my $ret; + $ret .= ""; + $ret .= BML::ml('error.procrequest'); + $ret .= "
      "; + + foreach (@errors) { + $ret .= "
    • $_
    • "; + } + $ret .= "
    errorbar?>"; + return $ret; +} + +# +# name: LJ::warning_list +# des: Returns a warning bar with bulleted list of warnings +# returns: BML showing warnings +# args: warnings* +# des-warnings: A list of warnings +# +sub warning_list +{ + my @warnings = @_; + my $ret; + + $ret .= ""; + $ret .= BML::ml('label.warning'); + $ret .= "
      "; + + foreach (@warnings) { + $ret .= "
    • $_
    • "; + } + $ret .= "
    warningbar?>"; + return $ret; +} + +sub tosagree_widget { + my ($checked, $errstr) = @_; + + return + "
    " . + BML::ml('tos.mustread', + { aopts => "target='_new' href='$LJ::SITEROOT".$LJ::TOSURL."'" }) . + "
    " . + "" . + "
    " . LJ::html_check({ name => 'agree_tos', id => 'agree_tos', + value => '1', selected => $checked }) . + "
    " . + ($errstr ? "" : ''); +} + +sub tosagree_html { + my $domain = shift; + + my $ret = ""; + + my $html_str = LJ::tosagree_str($domain => 'html'); + $ret .= "" if $html_str; + + $ret .= "
    "; + $ret .= LJ::tosagree_widget(@_); + $ret .= "
    "; + + return $ret; +} + +sub tosagree_str { + my ($domain, $key) = @_; + + return ref $LJ::REQUIRED_TOS{$domain} && $LJ::REQUIRED_TOS{$domain}->{$key} ? + $LJ::REQUIRED_TOS{$domain}->{$key} : $LJ::REQUIRED_TOS{$key}; +} + +# +# name: LJ::did_post +# des: When web pages using cookie authentication, you can't just trust that +# the remote user wants to do the action they're requesting. It's way too +# easy for people to force other people into making GET requests to +# a server. What if a user requested http://server/delete_all_journal.bml +# and that URL checked the remote user and immediately deleted the whole +# journal. Now anybody has to do is embed that address in an image +# tag and a lot of people's journals will be deleted without them knowing. +# Cookies should only show pages which make no action. When an action is +# being made, check that it's a POST request. +# returns: true if REQUEST_METHOD == "POST" +# +sub did_post +{ + return (BML::get_method() eq "POST"); +} + +# +# name: LJ::robot_meta_tags +# des: Returns meta tags to block a robot from indexing or following links +# returns: A string with appropriate meta tags +# +sub robot_meta_tags +{ + return "\n" . + "\n"; +} + +sub paging_bar +{ + my ($page, $pages, $opts) = @_; + + my $self_link = $opts->{'self_link'} || + sub { BML::self_link({ 'page' => $_[0] }) }; + + my $navcrap; + if ($pages > 1) { + $navcrap .= "
    "; + $navcrap .= BML::ml('ljlib.pageofpages',{'page'=>$page, 'total'=>$pages}) . "
    "; + my $left = "<<"; + if ($page > 1) { $left = "$left"; } + my $right = ">>"; + if ($page < $pages) { $right = "$right"; } + $navcrap .= $left . " "; + for (my $i=1; $i<=$pages; $i++) { + my $link = "[$i]"; + if ($i != $page) { $link = "$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + } + $navcrap .= "$right"; + $navcrap .= "
    \n"; + $navcrap = BML::fill_template("standout", { 'DATA' => $navcrap }); + } + return $navcrap; +} + +# +# class: web +# name: LJ::make_cookie +# des: Prepares cookie header lines. +# returns: An array of cookie lines. +# args: name, value, expires, path?, domain? +# des-name: The name of the cookie. +# des-value: The value to set the cookie to. +# des-expires: The time (in seconds) when the cookie is supposed to expire. +# Set this to 0 to expire when the browser closes. Set it to +# undef to delete the cookie. +# des-path: The directory path to bind the cookie to. +# des-domain: The domain (or domains) to bind the cookie to. +# +sub make_cookie +{ + my ($name, $value, $expires, $path, $domain) = @_; + my $cookie = ""; + my @cookies = (); + + # let the domain argument be an array ref, so callers can set + # cookies in both .foo.com and foo.com, for some broken old browsers. + if ($domain && ref $domain eq "ARRAY") { + foreach (@$domain) { + push(@cookies, LJ::make_cookie($name, $value, $expires, $path, $_)); + } + return; + } + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($expires); + $year+=1900; + + my @day = qw{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + $cookie = sprintf "%s=%s", LJ::eurl($name), LJ::eurl($value); + + # this logic is confusing potentially + unless (defined $expires && $expires==0) { + $cookie .= sprintf "; expires=$day[$wday], %02d-$month[$mon]-%04d %02d:%02d:%02d GMT", + $mday, $year, $hour, $min, $sec; + } + + $cookie .= "; path=$path" if $path; + $cookie .= "; domain=$domain" if $domain; + push(@cookies, $cookie); + return @cookies; +} + +sub set_active_crumb +{ + $LJ::ACTIVE_CRUMB = shift; + return undef; +} + +sub set_dynamic_crumb +{ + my ($title, $parent) = @_; + $LJ::ACTIVE_CRUMB = [ $title, $parent ]; +} + +sub get_parent_crumb +{ + my $thiscrumb = LJ::get_crumb(LJ::get_active_crumb()); + return LJ::get_crumb($thiscrumb->[2]); +} + +sub get_active_crumb +{ + return $LJ::ACTIVE_CRUMB; +} + +sub get_crumb_path +{ + my $cur = LJ::get_active_crumb(); + my @list; + while ($cur) { + # get crumb, fix it up, and then put it on the list + if (ref $cur) { + # dynamic crumb + push @list, [ $cur->[0], '', $cur->[1], 'dynamic' ]; + $cur = $cur->[1]; + } else { + # just a regular crumb + my $crumb = LJ::get_crumb($cur); + last unless $crumb; + last if $cur eq $crumb->[2]; + $crumb->[3] = $cur; + push @list, $crumb; + + # now get the next one we're going after + $cur = $crumb->[2]; # parent of this crumb + } + } + return @list; +} + +sub get_crumb +{ + my $crumbkey = shift; + if (defined $LJ::CRUMBS_LOCAL{$crumbkey}) { + return $LJ::CRUMBS_LOCAL{$crumbkey}; + } else { + return $LJ::CRUMBS{$crumbkey}; + } +} + +# +# name: LJ::check_referer +# class: web +# des: Checks if the user is coming from a given URI. +# args: uri?, referer? +# des-uri: string; the URI we want the user to come from +# des-referer: string; the location the user is posting from. if not supplied, +# will be retrieved with BML::get_client_header. in general, you don't want to +# pass this yourself unless you already have it or know we can't get it from BML. +# returns: 1 if they're coming from that URI, else undef +# +sub check_referer { + my $uri = shift(@_) || ''; + my $referer = shift(@_) || BML::get_client_header('Referer'); + + # get referer and check + return 1 unless $referer; + return 1 if $LJ::SITEROOT && $referer =~ m!^$LJ::SITEROOT$uri!; + return 1 if $LJ::DOMAIN && $referer =~ m!^http://$LJ::DOMAIN$uri!; + return 1 if $LJ::DOMAIN_WEB && $referer =~ m!^http://$LJ::DOMAIN_WEB$uri!; + return 1 if $uri =~ m!^http://! && $referer eq $uri; + return undef; +} + +# +# name: LJ::form_auth +# class: web +# des: Creates an authentication token to be used later to verify that a form +# submission came from a particular user. +# returns: HTML hidden field to be inserted into the output of a page. +# +sub form_auth { + my $remote = LJ::get_remote() or return ""; + my $sess = $remote->{'_session'} or return ""; + my $auth = join('-', + LJ::rand_chars(10), + $remote->{userid}, + $sess->{auth}); + return LJ::html_hidden("lj_form_auth", LJ::challenge_generate(86400, $auth)); +} + +# +# name: LJ::check_form_auth +# class: web +# des: Verifies form authentication created with LJ::form_auth. +# returns: Boolean; true if the current data in %POST is a valid form submitted +# by the user in $remote using the current session, false if the user has changed, +# the challenge has expired, or the user has changed session (logged out and in +# again, or something). +# +sub check_form_auth { + my $remote = LJ::get_remote() or return 0; + my $sess = $remote->{'_session'} or return 0; + my $formauth = $BMLCodeBlock::POST{'lj_form_auth'} or return 0; + + # check the attributes are as they should be + my $attr = LJ::get_challenge_attributes($formauth); + my ($randchars, $userid, $sessauth) = split(/\-/, $attr); + return 0 unless $userid == $remote->{userid} && + $sessauth eq $sess->{auth}; + + # check the signature is good and not expired + my $opts = { dont_check_count => 1 }; # in/out + LJ::challenge_check($formauth, $opts); + return $opts->{valid} && ! $opts->{expired}; +} + +# +# name: LJ::create_qr_div +# class: web +# des: Creates the hidden div that stores the Quick Reply form +# returns: undef upon failure or HTML for the div upon success +# args: user, remote, ditemid, stylemine, userpic +# des-u: user object or userid for journal reply in +# des-ditemid: ditemid for this comment +# des-stylemine: if the user has specified style=mine for this page +# des-userpic: alternate default userpic +# +sub create_qr_div { + + my ($user, $ditemid, $stylemine, $userpic, $viewing_thread) = @_; + my $u = LJ::want_user($user); + my $remote = LJ::get_remote(); + return undef unless $u && $remote && $ditemid; + return undef if $remote->underage; + + $stylemine ||= 0; + my $qrhtml; + + LJ::load_user_props($remote, "opt_no_quickreply"); + return undef if $remote->{'opt_no_quickreply'}; + + my $stylemineuri = $stylemine ? "style=mine&" : ""; + my $basepath = LJ::journal_base($u) . "/$ditemid.html?${stylemineuri}replyto="; + $qrhtml .= LJ::html_hidden({'name' => 'replyto', 'id' => 'replyto', 'value' => ''}, + {'name' => 'parenttalkid', 'id' => 'parenttalkid', 'value' => ''}, + {'name' => 'itemid', 'id' => 'itemid', 'value' => $ditemid}, + {'name' => 'usertype', 'id' => 'usertype', 'value' => 'cookieuser'}, + {'name' => 'userpost', 'id' => 'userpost', 'value' => $remote->{'user'}}, + {'name' => 'qr', 'id' => 'qr', 'value' => '1'}, + {'name' => 'cookieuser', 'id' => 'cookieuser', 'value' => $remote->{'user'}}, + {'name' => 'dtid', 'id' => 'dtid', 'value' => ''}, + {'name' => 'basepath', 'id' => 'basepath', 'value' => $basepath}, + {'name' => 'stylemine', 'id' => 'stylemine', 'value' => $stylemine}, + {'name' => 'saved_subject', 'id' => 'saved_subject'}, + {'name' => 'saved_body', 'id' => 'saved_body'}, + {'name' => 'saved_spell', 'id' => 'saved_spell'}, + {'name' => 'saved_upic', 'id' => 'saved_upic'}, + {'name' => 'saved_dtid', 'id' => 'saved_dtid'}, + {'name' => 'saved_ptid', 'id' => 'saved_ptid'}, + {'name' => 'viewing_thread', 'id' => 'viewing_thread', 'value' => $viewing_thread}, + ); + + # rate limiting challenge + { + my ($time, $secret) = LJ::get_secret(); + my $rchars = LJ::rand_chars(20); + my $chal = $ditemid . "-$u->{userid}-$time-$rchars"; + my $res = Digest::MD5::md5_hex($secret . $chal); + $qrhtml .= LJ::html_hidden("chrp1", "$chal-$res"); + } + + # Start making the div itself + $qrhtml .= ""; + + my $ret; + $ret = ""; + return $ret; +} + +# +# name: LJ::make_qr_link +# class: web +# des: Creates the link to toggle the QR reply form or if +# JavaScript is not enabled, then forwards the user through +# to replyurl. +# returns: undef upon failure or HTML for the link +# args: dtid, basesubject, linktext, replyurl +# des-dtid: dtalkid for this comment +# des-basesubject: parent comment's subject +# des-linktext: text for the user to click +# des-replyurl: URL to forward user to if their browser +# does not support QR +# +sub make_qr_link +{ + my ($dtid, $basesubject, $linktext, $replyurl) = @_; + + return undef unless defined $dtid && $linktext && $replyurl; + + my $remote = LJ::get_remote(); + LJ::load_user_props($remote, "opt_no_quickreply"); + unless ($remote->{'opt_no_quickreply'}) { + my $pid = int($dtid / 256); + + $basesubject =~ s/^(Re:\s*)*//i; + $basesubject = "Re: $basesubject" if $basesubject; + $basesubject = LJ::ejs($basesubject); + my $onclick = "return quickreply('$dtid', $pid, '$basesubject')"; + $onclick = LJ::ehtml($onclick); + return "$linktext"; + } else { # QR Disabled + return "$linktext"; + } +} + +# +# name: LJ::get_lastcomment +# class: web +# des: Looks up the last talkid and journal the remote user posted in +# returns: talkid, jid +# args: +# +sub get_lastcomment { + my $remote = LJ::get_remote; + return (undef, undef) unless $remote; + + # Figure out their last post + my $memkey = [$remote->{'userid'}, "lastcomm:$remote->{'userid'}"]; + my $memval = LJ::MemCache::get($memkey); + my ($jid, $talkid) = split(/:/, $memval) if $memval; + + return ($talkid, $jid); +} + +# +# name: LJ::make_qr_target +# class: web +# des: Returns a div usable for Quick Reply boxes +# returns: HMTML for the div +# args: +# +sub make_qr_target { + my $name = shift; + + return "
    "; +} + +# +# name: LJ::set_lastcomment +# class: web +# des: Sets the lastcomm Memcache key for this user's last comment +# returns: undef on failure +# args: u, remote, dtalkid, life? +# des-u: Journal they just posted in, either u or userid +# des-remote: Remote user +# des-dtalkid: Talkid for the comment they just posted +# des-life: How long, in seconds, the Memcache key should live +# +sub set_lastcomment +{ + my ($u, $remote, $dtalkid, $life) = @_; + + my $userid = LJ::want_userid($u); + return undef unless $userid && $remote && $dtalkid; + + # By default, this key lasts for 10 seconds. + $life ||= 10; + + # Set memcache key for highlighting the comment + my $memkey = [$remote->{'userid'}, "lastcomm:$remote->{'userid'}"]; + LJ::MemCache::set($memkey, "$userid:$dtalkid", time()+$life); + + return; +} + +# +# name: LJ::entry_form +# class: web +# des: Returns a properly formatted form for creating/editing entries +# args: opts, head +# des-head: string reference for the section (javascript previews, etc) +# des-onload: string reference for javascript functions to be called on page load +# des-opts: hashref of keys/values: +# mode: either "update" or "edit", depending on context +# datetime: date and time, formatted yyyy-mm-dd hh:mm +# remote: remote u object +# subject: entry subject +# event: entry text +# richtext: allow rich text formatting +# richtext_on: rich text formatting has been turned on +# auth_as_remote: bool option to authenticate as remote user, prefilling pic/friend groups/etc +# return: form to include in BML pages +# +sub entry_form { + my ($opts, $head, $onload, $errors) = @_; + + my $out = ""; + my $remote = $opts->{'remote'}; + my ($moodlist, $moodpics, $userpics); + + # usejournal has no point if you're trying to use the account you're logged in as, + # so disregard it so we can assume that if it exists, we're trying to post to an + # account that isn't us + if ($remote && $opts->{usejournal} && $remote->{user} eq $opts->{usejournal}) { + delete $opts->{usejournal}; + } + + my $tabnum = 1; + my $tabindex = sub { return $tabnum++; }; + $opts->{'event'} = LJ::durl($opts->{'event'}) if $opts->{'mode'} eq "edit"; + + # 15 minute auth token, should be adequate + my $chal = LJ::challenge_generate(900); + $out .= ""; + $out .= ""; + + $out .= "
    "; + $out .= "\n"; + ### Meta Information Column 1 + { + $out .= ""; + } + ### Meta Information Column 2 + + + { + $out .= ""; + } + + $out .= "
    "; + + # Authentication box + $out .= $opts->{'auth'}; + $out .= "\n" if $errors->{'auth'}; + # Date / Time + { + my ($year, $mon, $mday, $hour, $min) = split( /\D/, $opts->{'datetime'}); + # date entry boxes / formatting note + my $datetime = LJ::html_datetime({ 'name' => "date_ymd", 'notime' => 1, 'default' => "$year-$mon-$mday", 'disabled' => $opts->{'disabled_save'}}) . " " x 5; + $datetime .= LJ::html_text({ size => 2, maxlength => 2, value => $hour, name => "hour", tabindex => $tabindex->(), disabled => $opts->{'disabled_save'} }) . ":"; + $datetime .= LJ::html_text({ size => 2, maxlength => 2, value => $min, name => "min", tabindex => $tabindex->(), disabled => $opts->{'disabled_save'} }); + + $out .= ""; + $out .= "\n"; + } + + ### Subject + $out .= ""; + $out .= "
    {'auth'} inerr?>
    " . BML::ml('entryform.date') . "$datetime "; + $out .= "
    " . BML::ml('entryform.subject') . ""; + $out .= LJ::html_text({ 'name' => 'subject', 'value' => $opts->{'subject'}, + 'size' => '60', 'maxlength' => '100', 'tabindex' => $tabindex->(), 'disabled' => $opts->{'disabled_save'} }) . "\n"; + $out .= "
    "; + $out .= LJ::run_hook('entryforminfo'); + $out .= "
    \n"; + + ### Display Spell Check Results: + $out .= "

    " . BML::ml('entryform.spellchecked') . "
    $opts->{'spellcheck_html'}

    " + if $opts->{'spellcheck_html'}; + $out .= "


    $errors->{'entry'}

    " + if $errors->{'entry'}; + + ### Event Text Area: + $out .= "

    " . BML::ml('entryform.entry') . "

    " unless $opts->{'richtext_on'}; + if ($opts->{'richtext_on'}) { + my $jevent = $opts->{'event'}; + + # manually typed tags + $jevent =~ s//<lj user="$1" \/>/ig; + $jevent =~ s/<(\/)?lj-cut(.*?)(?: \/)?>/<$1lj-cut$2>/ig; + + $jevent = LJ::ejs($jevent); + my $rte_nosupport = LJ::ejs(BML::fill_template("de", { DATA => BML::ml('entryform.htmlokay.rte_nosupport') })); + + $out .= LJ::html_hidden('richtext', '1') . "\n"; + $out .= LJ::html_hidden('saved_entry', '') . "\n"; + + $out .= <
    "; + return $out; +} + +# +# name: LJ::entry_form_decode +# class: web +# des: Decodes an entry_form into a protocol compatible hash +# info: Generate form with [func[entry_form]]. +# args: req, post +# des-req: protocol request hash to build +# des-post: entry_form POST contents +# returns: req +# +sub entry_form_decode +{ + my ($req, $POST) = @_; + + # find security + my $sec = "public"; + my $amask = 0; + if ($POST->{'security'} eq "private") { + $sec = "private"; + } elsif ($POST->{'security'} eq "friends") { + $sec = "usemask"; $amask = 1; + } elsif ($POST->{'security'} eq "custom") { + $sec = "usemask"; + foreach my $bit (1..30) { + next unless $POST->{"custom_bit_$bit"}; + $amask |= (1 << $bit); + } + } + $req->{'security'} = $sec; + $req->{'allowmask'} = $amask; + + # date/time + my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, $POST); + my ($year, $mon, $day) = split( /\D/, $date); + $req->{'year'} = $year; $req->{'mon'} = $mon; $req->{'day'} = $day; + + foreach ( "year", "mon", "day" ) { + $req->{$_} = $POST->{$_} if $POST->{$_} ne ""; + } + + # copy some things from %POST + foreach (qw(subject hour min + prop_picture_keyword prop_current_moodid + prop_current_mood prop_current_music + prop_opt_screening prop_opt_noemail + prop_opt_preformatted prop_opt_nocomments + prop_taglist)) { + $req->{$_} = $POST->{$_}; + } + + $req->{"prop_opt_preformatted"} ||= $POST->{'event_format'} eq "preformatted" ? 1 : 0; + $req->{"prop_opt_nocomments"} ||= $POST->{'comment_settings'} eq "nocomments" ? 1 : 0; + $req->{"prop_opt_noemail"} ||= $POST->{'comment_settings'} eq "noemail" ? 1 : 0; + $req->{'prop_opt_backdated'} = $POST->{'prop_opt_backdated'} ? 1 : 0; + + # Convert the rich text editor output back to parsable lj tags. + my $event = $POST->{'event'}; + if ($POST->{'richtext'}) { + # check for blank entry + (my $event_tmp = $event) =~ s!(?:
    |

    (?: |\s)+

    | )\s*?!!gm; + if ($event_tmp =~ /\w/) { # ok, we still have content + $event =~ s/<(\/)?lj-cut(.*?)(?: \/)?>/<$1lj-cut$2>/ig; + $event =~ s/<lj user=['"]?(\w{1,15})['"]?\s?\/?>//ig; # manually typed tags + $event =~ s/<\/a>(?:<\/span>)?//ig; + } else { # RTE blanks (just
    , newlines,   - no real content) + $event = undef; # force protocol error + } + } + $req->{'event'} = $event; + + ## see if an "other" mood they typed in has an equivalent moodid + if ($POST->{'prop_current_mood'}) { + if (my $id = LJ::mood_id($POST->{'prop_current_mood'})) { + $req->{'prop_current_moodid'} = $id; + delete $req->{'prop_current_mood'}; + } + } + return $req; +} + +# returns exactly what was passed to it normally. but in developer mode, +# it includes a link to a page that automatically grants the needed priv. +sub no_access_error { + my ($text, $priv, $privarg) = @_; + if ($LJ::IS_DEV_SERVER) { + my $remote = LJ::get_remote(); + return "$text (DEVMODE: Grant $priv\[$privarg\])"; + } else { + return $text; + } +} + +# Data::Dumper for JavaScript +# sort for stable result, e.g. MD5() +sub js_dumper { + my $obj = shift; + if (ref $obj eq "HASH") { + my $ret = "{"; + foreach my $k (sort keys %$obj) { + $ret .= "$k: " . js_dumper($obj->{$k}) . ","; + } + chop $ret; + $ret .= "}"; + return $ret; + } elsif (ref $obj eq "ARRAY") { + my $ret = "[" . join(", ", map { js_dumper($_) } sort @$obj) . "]"; + return $ret; + } else { + return $obj if $obj =~ /^\d+$/; + return "\"" . LJ::ejs($obj) . "\""; + } +} + +# Common challenge/response javascript, needed by both login pages and comment pages alike. +# Forms that use this should onclick='return sendForm()' in the submit button. +# Returns true to let the submit continue. +$LJ::COMMON_CODE{'chalresp_js'} = qq{ + + +}; + +# Common Javascript function for auto-checking radio buttons on form +# input field data changes +$LJ::COMMON_CODE{'autoradio_check'} = q{ + +}; + +# Common Javascript functions for Quick Reply +$LJ::COMMON_CODE{'quickreply'} = q{ + + +}; + +# +# name: LJ::set_interests +# des: Change a user's interests +# args: dbarg?, u, old, new +# arg-old: hashref of old interests (hashing being interest => intid) +# arg-new: listref of new interests +# returns: 1 on success, undef on failure +# +sub set_interests +{ + my ($u, $old, $new) = @_; + + $u = LJ::want_user($u); + my $userid = $u->{'userid'}; + return undef unless $userid; + + return undef unless ref $old eq 'HASH'; + return undef unless ref $new eq 'ARRAY'; + + my $dbh = LJ::get_db_writer(); + my %int_new = (); + my %int_del = %$old; # assume deleting everything, unless in @$new + + # user interests go in a different table than user interests, + # though the schemas are the same so we can run the same queries on them + my $uitable = $u->{'journaltype'} eq 'C' ? 'comminterests' : 'userinterests'; + + # track if we made changes to refresh memcache later. + my $did_mod = 0; + + foreach my $int (@$new) + { + $int = lc($int); # FIXME: use utf8? + $int =~ s/^i like //; # *sigh* + next unless $int; + next if $int =~ / .+ .+ .+ /; # prevent sentences + next if $int =~ /[\<\>]/; + my ($bl, $cl) = LJ::text_length($int); + next if $bl > LJ::BMAX_INTEREST or $cl > LJ::CMAX_INTEREST; + $int_new{$int} = 1 unless $old->{$int}; + delete $int_del{$int}; + } + + ### were interests removed? + if (%int_del) + { + ## easy, we know their IDs, so delete them en masse + my $intid_in = join(", ", values %int_del); + $dbh->do("DELETE FROM $uitable WHERE userid=$userid AND intid IN ($intid_in)"); + $dbh->do("UPDATE interests SET intcount=intcount-1 WHERE intid IN ($intid_in)"); + $did_mod = 1; + } + + ### do we have new interests to add? + if (%int_new) + { + $did_mod = 1; + + ## difficult, have to find intids of interests, and create new ints for interests + ## that nobody has ever entered before + my $int_in = join(", ", map { $dbh->quote($_); } keys %int_new); + my %int_exist; + my @new_intids = (); ## existing IDs we'll add for this user + + ## find existing IDs + my $sth = $dbh->prepare("SELECT interest, intid FROM interests WHERE interest IN ($int_in)"); + $sth->execute; + while (my ($intr, $intid) = $sth->fetchrow_array) { + push @new_intids, $intid; # - we'll add this later. + delete $int_new{$intr}; # - so we don't have to make a new intid for + # this next pass. + } + + if (@new_intids) { + my $sql = ""; + foreach my $newid (@new_intids) { + if ($sql) { $sql .= ", "; } + else { $sql = "REPLACE INTO $uitable (userid, intid) VALUES "; } + $sql .= "($userid, $newid)"; + } + $dbh->do($sql); + + my $intid_in = join(", ", @new_intids); + $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid IN ($intid_in)"); + } + } + + ### do we STILL have interests to add? (must make new intids) + if (%int_new) + { + foreach my $int (keys %int_new) + { + my $intid; + my $qint = $dbh->quote($int); + + $dbh->do("INSERT INTO interests (intid, intcount, interest) ". + "VALUES (NULL, 1, $qint)"); + if ($dbh->err) { + # somebody beat us to creating it. find its id. + $intid = $dbh->selectrow_array("SELECT intid FROM interests WHERE interest=$qint"); + $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid=$intid"); + } else { + # newly created + $intid = $dbh->{'mysql_insertid'}; + } + if ($intid) { + ## now we can actually insert it into the userinterests table: + $dbh->do("INSERT INTO $uitable (userid, intid) ". + "VALUES ($userid, $intid)"); + } + } + } + + ### if journaltype is community, clean their old userinterests from 'userinterests' + if ($u->{'journaltype'} eq 'C') { + $dbh->do("DELETE FROM userinterests WHERE userid=?", undef, $u->{'userid'}); + } + + LJ::memcache_kill($u, "intids") if $did_mod; + return 1; +} + +# $opts is optional, with keys: +# forceids => 1 : don't use memcache for loading the intids +# forceints => 1 : don't use memcache for loading the interest rows +# justids => 1 : return arrayref of intids only, not names/counts +# returns otherwise an arrayref of interest rows, sorted by interest name +sub get_interests +{ + my ($u, $opts) = @_; + $opts ||= {}; + return undef unless $u; + my $uid = $u->{userid}; + my $uitable = $u->{'journaltype'} eq 'C' ? 'comminterests' : 'userinterests'; + + # load the ids + my $ids; + my $mk_ids = [$uid, "intids:$uid"]; + $ids = LJ::MemCache::get($mk_ids) unless $opts->{'forceids'}; + unless ($ids && ref $ids eq "ARRAY") { + $ids = []; + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT intid FROM $uitable WHERE userid=?"); + $sth->execute($uid); + push @$ids, $_ while ($_) = $sth->fetchrow_array; + LJ::MemCache::add($mk_ids, $ids, 3600*12); + } + return $ids if $opts->{'justids'}; + + # load interest rows + my %need; + $need{$_} = 1 foreach @$ids; + my @ret; + + unless ($opts->{'forceints'}) { + if (my $mc = LJ::MemCache::get_multi(map { [$_, "introw:$_"] } @$ids)) { + while (my ($k, $v) = each %$mc) { + next unless $k =~ /^introw:(\d+)/; + delete $need{$1}; + push @ret, $v; + } + } + } + + if (%need) { + my $ids = join(",", map { $_+0 } keys %need); + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT intid, interest, intcount FROM interests ". + "WHERE intid IN ($ids)"); + $sth->execute; + my $memc_store = 0; + while (my ($intid, $int, $count) = $sth->fetchrow_array) { + # minimize latency... only store 25 into memcache at a time + # (too bad we don't have set_multi.... hmmmm) + my $aref = [$intid, $int, $count]; + if ($memc_store++ < 25) { + # if the count is fairly high, keep item in memcache longer, + # since count's not so important. + my $expire = $count < 10 ? 3600*12 : 3600*48; + LJ::MemCache::add([$intid, "introw:$intid"], $aref, $expire); + } + push @ret, $aref; + } + } + + @ret = sort { $a->[1] cmp $b->[1] } @ret; + return \@ret; +} + +# returns a placeholder link +sub placeholder_link { + my (%opts) = @_; + + my $placeholder_html = LJ::ejs_all(delete $opts{placeholder_html} || ''); + my $width = delete $opts{width} || 100; + my $height = delete $opts{height} || 100; + my $link = delete $opts{link} || delete $opts{placeholder_link} || ''; + my $img = delete $opts{img} || "$LJ::IMGPREFIX/videoplaceholder.png"; + my $img_title = delete $opts{img_title} || "Click to show embedded content"; + # A really stupid hack, so that the images won't be too big + $height = ($height>150) ? $height-100 : 50 ; + $width = ($width>150) ? $width-100 : 50 ; + + return qq { +
    + +
    + +
    Click to show embedded content +
    +
    + }; +} + +# Returns replacement for lj-replace tags +sub lj_replace { + my $key = shift; + my $attr = shift; + + # Return hook if hook output not undef + if (LJ::are_hooks("lj-replace_$key")) { + my $replace = LJ::run_hook("lj-replace_$key"); + return $replace if defined $replace; + } + + # Return value of coderef if key defined + my %valid_keys = ( 'first_post' => \&lj_replace_first_post ); + + if (my $cb = $valid_keys{$key}) { + die "$cb is not a valid coderef" unless ref $cb eq 'CODE'; + return $cb->($attr); + } + + return undef; +} + +# Replace for lj-replace name="first_post" +sub lj_replace_first_post { + return unless LJ::is_web_context(); + return BML::ml('web.lj-replace.first_post', { + 'update_link' => "href='$LJ::SITEROOT/update.bml'", + }); +} + +# return 1 if URL is a safe stylesheet that S1/S2/etc can pull in. +# return 0 to reject the link tag +# return a URL to rewrite the stylesheet URL +# $href will always be present. $host and $path may not. +sub valid_stylesheet_url { + my ($href, $host, $path) = @_; + unless ($host && $path) { + return 0 unless $href =~ m!^https?://([^/]+?)(/.*)$!; + ($host, $path) = ($1, $2); + } + + my $cleanit = sub { + # allow tag, if we're doing no css cleaning + return 1 if $LJ::DISABLED{'css_cleaner'}; + + # remove tag, if we have no CSSPROXY configured + return 0 unless $LJ::CSSPROXY; + + # rewrite tag for CSS cleaning + return "$LJ::CSSPROXY?u=" . LJ::eurl($href); + }; + + return 1 if $LJ::TRUSTED_CSS_HOST{$host}; + return $cleanit->() unless $host =~ /\Q$LJ::DOMAIN\E$/i; + + # let users use system stylesheets. + return 1 if $host eq $LJ::DOMAIN || $host eq $LJ::DOMAIN_WEB || + $href =~ /^\Q$LJ::STATPREFIX\E/; + + # S2 stylesheets: + return 1 if $path =~ m!^(/\w+)?/res/(\d+)/stylesheet(\?\d+)?$!; + + # unknown, reject. + return $cleanit->(); +} + + +1; diff --git a/local/htdocs/.htaccess b/local/htdocs/.htaccess new file mode 100755 index 0000000..9b731e2 --- /dev/null +++ b/local/htdocs/.htaccess @@ -0,0 +1,2 @@ +Options FollowSymLinks Indexes +AddType "text/html; charset=koi8-r" .html diff --git a/local/htdocs/404-error.html b/local/htdocs/404-error.html new file mode 100755 index 0000000..723fd08 --- /dev/null +++ b/local/htdocs/404-error.html @@ -0,0 +1,9 @@ + 404 + +Page was not found. Sorry. +

    + +Livejournal Rossia.org + + + diff --git a/local/htdocs/_config-local.bml b/local/htdocs/_config-local.bml new file mode 100755 index 0000000..a072c5b --- /dev/null +++ b/local/htdocs/_config-local.bml @@ -0,0 +1 @@ +DefaultLanguage ru \ No newline at end of file diff --git a/local/htdocs/admin/console/index.bml b/local/htdocs/admin/console/index.bml new file mode 100755 index 0000000..2ae86ab --- /dev/null +++ b/local/htdocs/admin/console/index.bml @@ -0,0 +1,104 @@ + +Admin Console + +Error: requires post."; + } + + if ($remote && $remote->{'user'} ne $POST{'remoteuser'}) { + return "Error: invalid user."; + } + + $ret .= "[ console | reference ]

    "; + + foreach my $cmd (split(/\n/, $commands)) + { + my @args = LJ::Con::parse_line($cmd); + next unless @args; + + my $first = 1; + $ret .= "

    "; + foreach (@args) { + my $arg = BML::eall($_); + if ($first) { + $ret .= ""; + $first = 0; + } else { + $ret .= ""; + } + } + $ret .= "
    $arg$arg
    "; + + my @output; + my $rv; + + # TODO: make the entire console library not take $db args. + my $dbh = LJ::get_db_writer(); + $rv = LJ::Con::execute($dbh, $remote, \@args, \@output); + + unless ($rv) { $ret .= "

    Failed!"; } + if (@output) { + $ret .= "

    ";
    +             foreach my $line (@output) {
    +                 my $color = "#000000";
    +                 if ($line->[0] eq "error") { 
    +                     $color = "#FF0000";
    +                 } 
    +                 if ($line->[0] eq "info") { 
    +                     $color = "#008800";
    +                 } 
    +                 
    +                 $ret .= "".LJ::eall($line->[1])."\n";
    +                 
    +             }
    +             $ret .= "
    "; + } + } + + $ret .= "

    "; + $ret .= "enter commands:
    "; + $ret .= LJ::html_hidden('remoteuser', $remote->{'user'}) if $remote; + $ret .= " "; + $ret .= "

    \n"; + + return $ret; + + } + else + { + $ret .= "[ console | reference ]

    "; + + $ret .= "

    "; + $ret .= LJ::html_hidden('remoteuser', $remote->{'user'}) if $remote; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + $ret .= "
    command console."; + $ret .= "

    welcome to the console. from here administrators can do administrative type things. you will forget the commands, so there is a reference.

    "; + $ret .= "

    enter commands:
    "; + $ret .= "

    \n"; + return $ret; + } + +_code?> + + + +lib: cgi-bin/console.pl, cgi-bin/ljlib.pl +link: htdocs/admin/console/reference.bml +post: htdocs/admin/console/index.bml + _c?> diff --git a/local/htdocs/admin/console/reference.bml b/local/htdocs/admin/console/reference.bml new file mode 100755 index 0000000..9418dd0 --- /dev/null +++ b/local/htdocs/admin/console/reference.bml @@ -0,0 +1,60 @@ +Console Reference + + +[ console | reference ] + +

    Grammar +
    Think of this like a DOS or bash prompt. The first word is a command. Every word after that is an argument to that command. Every command has a different number of required and optional parameters. White space delimits arguments. If you need a space in an argument, put double quotes around the whole thing. If you need double quotes and spaces in an argument, escape the quote with a backslash (\) first. If you need to do a backslash, escape that with a backslash. +

    It's pretty straight-forward. If you're confused, ask. + +

    Command Reference +
    Arguments in <angle brackets> are required. Arguments in [brackets] are optional. If there is more than one optional argument, you can't skip one and provide one after it. Once you skip one, you have to skip the rest. + + \n"; + + foreach my $cmdname (sort keys %LJ::Con::cmd) + { + my $cmd = $LJ::Con::cmd{$cmdname}; + next if ($cmd->{'hidden'}); + + my $anchor = "$cmdname"; + $ret .= "$cmdname    \n"; + } + $ret .= "

    \n"; + + foreach my $cmdname (sort keys %LJ::Con::cmd) + { + my $cmd = $LJ::Con::cmd{$cmdname}; + next if ($cmd->{'hidden'}); + + my $args = LJ::ehtml($cmd->{'argsummary'}); + my $anchor = "$cmdname"; + $ret .= "

    "; + $ret .= "$cmdname $args
    "; + $ret .= "

    $cmd->{'des'}"; + if ($cmd->{'args'}) { + my @des = @{$cmd->{'args'}}; + $ret .= "

    "; + while (my ($arg, $des) = splice(@des, 0, 2)) { + $ret .= "
    $arg
    $des
    "; + } + $ret .= "
    "; + } + $ret .= "
    \n"; + } + $ret .= "
    "; + return $ret; + +_code?> + + +lib: cgi-bin/console.pl, cgi-bin/ljlib.pl +link: htdocs/admin/console/index.bml + _c?> diff --git a/local/htdocs/admin/ljr/.htaccess b/local/htdocs/admin/ljr/.htaccess new file mode 100644 index 0000000..8ec82a2 --- /dev/null +++ b/local/htdocs/admin/ljr/.htaccess @@ -0,0 +1,2 @@ +ExpiresActive on +ExpiresByType image/png A0000000 diff --git a/local/htdocs/admin/ljr/import-queue.bml b/local/htdocs/admin/ljr/import-queue.bml new file mode 100644 index 0000000..30d6d41 --- /dev/null +++ b/local/htdocs/admin/ljr/import-queue.bml @@ -0,0 +1,147 @@ + +body<= + + +
    "; + }; + + use strict; + use vars qw(%POST %GET); + use POSIX; + + my $records_per_page = 10; + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access import page.") + unless $remote; + + return"Error: You don't have access to view import results." + unless (LJ::check_priv($remote, "siteadmin", "importresults")); + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $ret; + my $dbr; + + $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + $ret = "\n
    "; + + my $sth1; + my $max_importid; + + $sth1 = $dbr->prepare("SELECT max(importid) as mi FROM ljr_iqueue"); + $sth1->execute(); + if (my $r = $sth1->fetchrow_hashref) { + $max_importid = $r->{"mi"}; + } + $sth1->finish; + + if (!$max_importid) { + return $err->("Import queue is empty right now. Check out import results instead.") + } + + $ret .= "
    Check out import results also.
    "; + + my $tot_pages = POSIX::floor($max_importid / $records_per_page) + 1; + my $offset = $max_importid - POSIX::floor($max_importid / $records_per_page) * $records_per_page; + my $i; + + + if (!defined($GET{"page"}) || int($GET{"page"}) == 0 ) { + $GET{"page"} = $tot_pages; + } + else { + $GET{"page"} = abs(int($GET{"page"})); + } + + + $ret .= "
    Страницы:  "; + + my $lindex; + my $rindex; + + $lindex = $GET{"page"} + 5; + if ($lindex > $tot_pages) { + $rindex = $rindex - ($lindex - $tot_pages); + $lindex = $tot_pages; + } + $rindex = $rindex + $GET{"page"} - 5; + if ($rindex < 1) { + $lindex = $lindex + abs($rindex) - 1; + $rindex = 1; + } + + for ($i = $lindex; $i >= $rindex; $i--) { + if ($i == $GET{"page"}) { + $ret .= $i . " "; + } + else { + $ret .= "$i "; + } + } + $ret .= ""; + + $ret .= "
    "; + $ret .= ""; + $ret .= "prepare( + "SELECT * FROM ljr_iqueue where importid <= " . + (($GET{"page"} - 1) * $records_per_page + $offset) . + " and importid > " . + ((($GET{"page"} - 1) * $records_per_page) + $offset - $records_per_page) . + " order by priority, importid desc " + ); + $sth1->execute(); + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + while (my $r = $sth1->fetchrow_hashref) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    ПриоритетÐомерИÑходный
    Ñервер
    Пользователь
    на иÑходном Ñервере
    ПротоколПользователь
    LJ.Rossia.org
    Дата и времÑ
    ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ñвки
    " . $r->{priority} . "" . $r->{importid} . "" . $r->{remote_site} . "{remote_site} ."/users/" . $r->{remote_user} . ">" . + $r->{remote_user} . "" . $r->{remote_protocol} . "{local_user} . ">" . + $r->{local_user} . "" . $r->{qdate} . "
    "; + $sth1->finish; + + return $ret; +} +_code?> + + +<=body +page?> diff --git a/local/htdocs/admin/ljr/import-results.bml b/local/htdocs/admin/ljr/import-results.bml new file mode 100755 index 0000000..6337cb5 --- /dev/null +++ b/local/htdocs/admin/ljr/import-results.bml @@ -0,0 +1,203 @@ + +body<= + + +
    "; + }; + + use strict; + use vars qw(%POST %GET); + use POSIX; + + my $records_per_page = 10; + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access import page.") + unless $remote; + + return"Error: You don't have access to view import results." + unless (LJ::check_priv($remote, "siteadmin", "importresults")); + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $ret; + my $dbr; + + $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + if (defined($GET{"retry"}) && int($GET{"retry"}) > 0 ) { + $ret = "\n

    "; + $ret .= "Yes please  "; + $ret .= "No thanks"; + return $ret; + } + if (defined($GET{"retrydo"}) && int($GET{"retrydo"}) > 0 ) { + my $sth1; + + $sth1 = $dbr->prepare("SELECT * FROM ljr_ihistory WHERE importid=?"); + $sth1->execute($GET{"retrydo"}); + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $r; + if ($r = $sth1->fetchrow_hashref) { + $sth1->finish; + + return $err->("Sorry we do not have remote password for import [" . $GET{"retrydo"} . "]!") + if $r->{remote_pass} eq ""; + + $sth1 = $dbr->prepare("SELECT * FROM ljr_iqueue WHERE local_user=?"); + $sth1->execute($r->{local_user}); + if ($sth1->fetchrow_hashref) { + $dbh->do( + "update ljr_iqueue set remote_site=?, remote_user=?, remote_pass=?, remote_protocol=? " . + "where local_user=?;", undef, + $r->{remote_site}, $r->{remote_user}, $r->{remote_pass}, + $r->{remote_protocol}, $r->{local_user}); + return $err->($dbh->errstr) if $dbh->err; + } + else { + $dbh->do( + "insert into ljr_iqueue " . + "(remote_site, remote_user, remote_pass, remote_protocol, local_user, " . + "opt_overwrite, opt_comments, qdate, priority) VALUES " . + "(?, ?, ?, ?, ?, '0', '1', now(), 4);", + undef, $r->{remote_site}, $r->{remote_user}, $r->{remote_pass}, + $r->{remote_protocol}, $r->{local_user}); + return $err->($dbh->errstr) if $dbh->err; + } + $sth1->finish; + + $ret = "OK. You have it."; + } + else { + return $err->("Sorry, we can't find import [" . $GET{"retrydo"} . "]!"); + } + + return $ret; + } + + $ret = "\n
    "; + + my $sth1; + my $max_importid; + + $sth1 = $dbr->prepare("SELECT max(importid) as mi FROM ljr_ihistory"); + $sth1->execute(); + if (my $r = $sth1->fetchrow_hashref) { + $max_importid = $r->{"mi"}; + } + else { + return $err->("No import ever happened.") + } + $sth1->finish; + + $ret .= "
    Check out import queue also.
    "; + + my $tot_pages = POSIX::floor($max_importid / $records_per_page) + 1; + my $offset = $max_importid - POSIX::floor($max_importid / $records_per_page) * $records_per_page; + my $i; + + + if (!defined($GET{"page"}) || int($GET{"page"}) == 0 ) { + $GET{"page"} = $tot_pages; + } + else { + $GET{"page"} = abs(int($GET{"page"})); + } + + + $ret .= "
    Страницы:  "; + + my $lindex; + my $rindex; + + $lindex = $GET{"page"} + 5; + if ($lindex > $tot_pages) { + $rindex = $rindex - ($lindex - $tot_pages); + $lindex = $tot_pages; + } + $rindex = $rindex + $GET{"page"} - 5; + if ($rindex < 1) { + $lindex = $lindex + abs($rindex) - 1; + $rindex = 1; + } + + for ($i = $lindex; $i >= $rindex; $i--) { + if ($i == $GET{"page"}) { + $ret .= $i . " "; + } + else { + $ret .= "$i "; + } + } + $ret .= ""; + + $ret .= ""; + $ret .= ""; + $ret .= "prepare( + "SELECT * FROM ljr_ihistory where importid <= " . + (($GET{"page"} - 1) * $records_per_page + $offset) . + " and importid > " . + ((($GET{"page"} - 1) * $records_per_page) + $offset - $records_per_page) . + " order by importid desc " + ); + $sth1->execute(); + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + while (my $r = $sth1->fetchrow_hashref) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    ÐомерИÑходный
    Ñервер
    Пользователь
    на иÑходном Ñервере
    ПротоколПользователь
    LJ.Rossia.org
    Дата и времÑ
    изменениÑ
    ÑтатуÑа заÑвки
    Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ñвки
    " . $r->{importid} . "" . $r->{remote_site} . "{remote_site} ."/users/" . $r->{remote_user} . ">" . + $r->{remote_user} . "" . $r->{remote_protocol} . "{local_user} . ">" . + $r->{local_user} . "" . $r->{idate} . "" . + ($r->{istatus} ne "SUCCESSFUL" && $r->{remote_pass} ne "" ? + "{importid}>retry " + : "") . + $r->{istatus} . "
    "; + $sth1->finish; + + return $ret; +} +_code?> + + +<=body +page?> diff --git a/local/htdocs/admin/memcache-keys.txt b/local/htdocs/admin/memcache-keys.txt new file mode 100755 index 0000000..31a0632 --- /dev/null +++ b/local/htdocs/admin/memcache-keys.txt @@ -0,0 +1,81 @@ + userid: == $u, (in arrayref packed form) + uidof: == userid + uprop:: == scalar + tags: == { tagid => { **tag info hashref, see LJ::Tags::get_usertags** } } + sess:: == sessions row hashref + bio: == user bio text + + talktext::: == [ subject, text ] 60 min + talkprop:: == { propname => $value, ... } 60 min + talk2::: == packed data 120 min + talk2ct: == # rows for user + talkleftct: == # rows for user + + logtext::: == [ subject, text ] 120 min + logprop:: == { propname => $value, ... } 120 min + logtag:: == [ kwid, kwid, kwid, ... ] + log2:: == packed data + log2ct: == # of rows for user + log2lt: == packed data: array of recent log2 entries in rlogtime +order, for friends page, last few weeks by default + rp:: == scalar, the replycount value + + memkwid: == hashref of 'memories' keyword ids to keywords. + + dayct: == arrayref of arrayrefs (see LJ::get_daycounts) + + auc:: == last ID from LJ::alloc_user_counter() for $uid/$domain + + moodthemedata: = { $moodid => { 'pic' => $pic, 'w' => $w, 'h' => $h } } + + s1overr: == overrides for a given user + s1uc: == s1usercache row hashref + s1pubstyc == hashref keyed on styleid with values being rows from s1style table + s1styc: == s1stylecache row hashref, 30 minutes + s1style: == hashref of s1style row, without formatdata + s1style_all: == hashref of s1style row, including formatdata + s1stylemap: == userid who owns the given styleid + + s2sl: == hashref of s2stylelayers { type => s2lid } + s2s: == hashref of s2styles row + s2publayers == memoize LJ::S2::get_public_layers for 10 mins + s2lo: == userid of the owner of this layer + s2c: == arrayref; [ compile time, compiled data (or 0 meaning no data) ] + + checkfriends:: == scalar maxupdate, expires after refresh interval + frgmask:: -- scalar numeric mask, 15 minutes + fgrp: == packed data, friendgroup rows for a given user + friends: == packed data, friends rows for a user + friendofs: == packed data, friendofs for a user + tu: == packed number: unixtime when user last updated + te: == packed number: unixtime when user last updated or edited + rss: == anonymous RSS page (text/html + last-modified) + blob:timeupdate == array of recently updated userids, few weeks. 1 min expire + popsyn == 100 most read syndicated accounts [user, userid, synurl, numreaders], 1 hour + +sysban:ip == hashref of ip => unix expiration time +sysban:uniq == hashref of uniq => unix expiration time + + userpic. == hashref-as-arrayref (ARRAYFMT: 'userpic' in LJ::MemCache) + upicinf: == packed data, userpic keywords + upiccom: == packed data, userpic comments + upicurl: == packed data, userpic urls + mogp.up. == arrayref of paths (URLs) + +rate_eperr: == rate limiting errors sent via email for email gateway +rate:tracked: == cluster tracking on login, posts, and comments + +ml... + +includefile: == text of BML include file + + introw: -- arrayref of [ $intid, $interest, $intcount ] + intids: -- arrayref of intids for this userid + + rel::: == [{0|1}, as_of_time] + relmodu:: == as_of_time, updated when rel edges of uid change + relmodt:: == as_of_time, updated when rel edges of targetid change + + memct: -- number of memories user has + + lastcomm: -- id of the last comment the user posted via quickreply diff --git a/local/htdocs/admin/memcache.bml b/local/htdocs/admin/memcache.bml new file mode 100755 index 0000000..0ed6b1a --- /dev/null +++ b/local/htdocs/admin/memcache.bml @@ -0,0 +1,171 @@ +{'userid'},"mcrate:$u->{'userid'}"]) : undef; + + my $ret; + + my $mode = $GET{'mode'}; + if ($GET{'host'}) { + $mode ||= "host"; + } + $mode ||= "overview"; + + $ret .= "
    [Overview]\n"; + + if ($mode eq "overview") { + $ret .= <<"END_TOP"; +
    +

    Memory Cache Overview

    + + +END_TOP + } + + my %now_hits; + if ($prev_hits) { %now_hits = %$prev_hits; } + + my ($tot_hits, $tot_misses) = (); + + foreach my $entry (@LJ::MEMCACHE_SERVERS) { + my $host = ref $entry ? $entry->[0] : $entry; + next if $mode eq "host" && $host ne $GET{'host'}; + + LJ::MemCache::forget_dead_hosts(); + my $sock = Cache::Memcached::sock_to_host($host); + + my $t1 = Time::HiRes::time(); + + my $log; + my %stat; + my @cmds = ("", "malloc", "items", "slabs"); + my $cmd; + if ($sock) { + while (defined($cmd = shift @cmds)) { + my $realcmd = "stats" . ($cmd ? " $cmd" : ""); + $log .= "$realcmd\n"; + foreach (LJ::MemCache::run_command($sock, "$realcmd\r\n")) { + last if $_ eq "END\r\n"; + $log .= $_; + next if $cmd eq "maps"; + if (/^STAT (\S+) (\S+)/) { + $stat{$cmd}{$1} = $2; + } + } + } + } + + my $t2 = Time::HiRes::time(); + + my $cpu = 0; + foreach my $key (qw(rusage_user rusage_system)) { + my $sec = $stat{''}{$key}; + $sec =~ s/:/\./; + $cpu += $sec; + #$ret .= "Host $host was $stat{''}{$key} = $sec, cpu = $cpu
    \n"; + } + + $now_hits{$host} = [ $stat{''}{'get_hits'}, $stat{''}{'get_misses'}, $cpu ]; + + my $hit_rate = sprintf("%0.02f%%", $stat{''}{'get_hits'}/($stat{''}{'get_hits'}+$stat{''}{'get_misses'}||1)*100); + + if ($mode eq "overview") { + $ret .= "\n"; + $ret .= ""; + my $gb_used = ($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) / (1024*1024*1024); + my $gb_max = $stat{''}{'limit_maxbytes'} / (1024*1024*1024); + if ($gb_used >= $gb_max) { + $ret .= sprintf("", $gb_max); + } else { + $ret .= sprintf("", $gb_used, $gb_max, $gb_used*100/($gb_max||1)); + } + + my $utiliz = $stat{''}{'bytes'} / + (($stat{'malloc'}{'mmapped_space'} + $stat{'malloc'}{'arena_size'}) || 1); + $ret .= sprintf("", $utiliz*100); + + my $up = $stat{''}{'uptime'}; + my $upstring; + foreach my $u ([86400,"d"],[3600,"h"],[60,"m"],[1,"s"]) { + if ($up / $u->[0] > 1) { + my $v = int($up / $u->[0]); + $upstring .= "${v}$u->[1] "; + $up -= $v * $u->[0]; + } + } + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + + if ($mode eq "host" && $host eq $GET{'host'}) { + $ret .= "[Raw Data]"; + $ret .= "

    Details for $host

    "; + + $ret .= "

    Slab classes

    "; + $ret .= "
    HostHit RateCurr/Max SizeUtlz %UptimeVersion
    $host$hit_rate"; + if ($prev_hits && $prev_hits->{$host}) { + my $nh = $now_hits{$host}; + my $ph = $prev_hits->{$host}; + + my $new_hits = $now_hits{$host}[0] - $prev_hits->{$host}[0]; + my $new_misses = $now_hits{$host}[1] - $prev_hits->{$host}[1]; + $tot_hits += $new_hits; + $tot_misses += $new_misses; + my $new_whatev = $new_hits + $new_misses; + my $new_rate = $new_hits / ($new_whatev || 1); + + my $cpu = sprintf("%0.6f", $nh->[2] - $ph->[2]); + $ret .= sprintf(" [%0.02f%% {$new_whatev} $cpu]", $new_rate * 100); + } + $ret .= sprintf(" %0.02f", $t2-$t1); + $ret .= "%0.01fG%0.02f/%0.01fG (%0.02f%%)%0.02f%%$upstring$stat{''}{'version'}
    "; + $ret .= "\n"; + foreach my $cls (0..60) { + my $size = $stat{'slabs'}{"$cls:chunk_size"}; + next unless $size; + $ret .= "" + . join('', map { "" } + qw(chunk_size used_chunks total_chunks free_chunks free_chunks_end total_pages)); + my $age = $stat{'items'}{"items:$cls:age"}; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    classsizeusedtotalfreepagesmax age
    $cls" . $stat{'slabs'}{"$cls:$_"} . "$age
    \n"; + + } + + if ($mode eq "raw" && $host eq $GET{'host'}) { + $ret .= "[Host Stats]
    "; + $ret .= "

    Raw data for $host

    "; + $ret .= "
    $log
    "; + } + + } + + LJ::MemCache::set([$u->{'userid'},"mcrate:$u->{'userid'}"], \%now_hits) + if $u; + + if ($mode eq "overview") { + $ret .= "\n"; + + my $new_whatev = $tot_hits + $tot_misses; + my $new_rate = $tot_hits / ($new_whatev || 1); + $ret .= sprintf("Global [%0.02f%% {$new_whatev}]", $new_rate * 100); + } + + return $ret; +} +_code?> + diff --git a/local/htdocs/admin/memcache_view.bml b/local/htdocs/admin/memcache_view.bml new file mode 100755 index 0000000..92015ce --- /dev/null +++ b/local/htdocs/admin/memcache_view.bml @@ -0,0 +1,282 @@ + +Memcache view + +Error: You don't have access to viewing memcache info." + unless (LJ::check_priv($remote, "finduser")); +# unless (LJ::check_priv($remote, "siteadmin", "memcacheview")); + + return "Error: No memcache servers defined." + unless @LJ::MEMCACHE_SERVERS; + + my $uid = sub { + my $u = LJ::load_user(shift); + return $u ? $u->{'userid'} : ""; + }; + my $cuid = sub { + my $u = LJ::load_user(shift); + return $u ? "$u->{'clusterid'}:$u->{'userid'}" : ""; + }; + + # key: unique prefix of a memcache key + # value: number n, means the n-th component of the key when + # split by ':' is the hash key. 0 means no hash key. + # the default, when absent from this hash, is "n=2 if the 2nd component + # is a number". + + my %MEMC_HASHKEYS = ( + 'uidof:' => 0, + 'talktext:' => 3, + 'logtext:' => 3, + 's1pubstyc:' => 0, + 'popsyn:' => 0, + 'rate_eperr:' => 0, + 'rate:' => 0, + 'ml.' => 0, + ); + + my $get_hashkey = sub { + my $key = shift; + return undef unless $key; + + my $hk; + my $component; + + foreach (keys %MEMC_HASHKEYS) { + if ($key =~ /^$_/) { + $component = $MEMC_HASHKEYS{$_}; + } + } + return undef if defined ($component) and $component == 0; + my $sep = ':'; + $sep = '.' if $key =~ /userpic\./; #special case + my @els = split (/\Q$sep\E/, $key); + $hk = $els[defined($component) ? $component-1 : 2-1]; + $hk = undef + unless defined($component) || int($hk)==$hk; + return $hk; + }; + + my $display = sub { + my ($key, $val) = @_; + + # first, transform array->hash if necessary + $val = LJ::MemCache::array_to_hash("user", $val) + if $key =~ /^user:/ + or $key =~ /^userid:/; + + # blot out passwords + if (ref $val eq 'HASH' && defined($val->{'password'})) { + $val->{'password'} = '*' x 8; + } + + # unpack packed data + if ($key =~ /^talk2:/) { + my $newval; + my $n = (length($val) - 1) / 16; + for (my $i=0; $i<$n; $i++) { + my ($f1, $par, $poster, $time) = unpack("NNNN",substr($val,$i*16+1,16)); + my $state = chr($f1 & 255); + my $talkid = $f1 >> 8; + $newval->{$talkid} = { + talkid => $talkid, + state => $state, + posterid => $poster, + datepost => LJ::mysql_time($time), + parenttalkid => $par, + }; + } + $val = [substr($val,0,1), $newval]; + } + + if ($key =~ /^log2:/) { + my $item = {}; + @$item{'posterid', 'eventtime', 'logtime', 'allowmask', 'ditemid'} = unpack("NNNNN", $val); + $item->{'security'} = ($item->{'allowmask'} == 0 ? 'private' : + ($item->{'allowmask'} == 2**31 ? 'public' : 'usemask')); + @$item{'jitemid', 'anum'} = ($item->{'ditemid'} >> 8, $item->{'ditemid'} % 256); + $item->{'eventtime'} = LJ::mysql_time($item->{'eventtime'}, 1); + $item->{'logtime'} = LJ::mysql_time($item->{'logtime'}, 1); + $val = $item; + } + + if ($key =~ /^log2lt:/) { + my $items = []; + my $ver = substr($val, 0, 1); + my $offset = {1=>1, 2=>5, 3=>5}->{$ver}; + my $newval; + + push @$newval, $ver; + push @$newval, unpack("N", substr($val, 1, 4)) + if $ver>=2; + + my $n = (length($val) - $offset )/20; + for (my $i=0; $i<$n; $i++) { + my ($rlogtime, $posterid, $eventtime, $allowmask, $ditemid) = + unpack("NNNNN", substr($val, $i*20+$offset, 20)); + $eventtime = LJ::mysql_time($eventtime, 1); + my $security = $allowmask == 0 ? 'private' : + ($allowmask == 2**31 ? 'public' : 'usemask'); + my ($jitemid, $anum) = ($ditemid >> 8, $ditemid % 256); + my $item = {}; + @$item{'posterid','eventtime','rlogtime','allowmask','ditemid', + 'security', 'jitemid', 'anum'} = + ($posterid, $eventtime, $rlogtime, $allowmask, + $ditemid, $security, $jitemid, $anum); + push @$items, $item; + } + push @$newval, $items; + $val = $newval; + } + + if ($key =~ /^fgrp:/) { + my $newval = []; + my $ver = shift @$val; + push @$newval, $ver; + foreach(@$val) { + push @$newval, LJ::MemCache::array_to_hash("fgrp", [$ver, @$_]); + } + $val = $newval; + } + + if ($key =~ /^upicinf:(\d+)$/) { + my $userid = $1; + my ($ver, $picstr, $kwstr) = @$val; + my $info = { + 'version' => $ver, + 'pic' => {}, + 'kw' => {}, + }; + + while (length $picstr >= 7) { + my $pic = { userid => $userid }; + ($pic->{picid}, + $pic->{width}, $pic->{height}, + $pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, ''); + $info->{pic}{$pic->{picid}} = $pic; + } + + my ($pos, $nulpos); + $pos = $nulpos = 0; + while (($nulpos = index($kwstr, "\0", $pos)) > 0) { + my $kw = substr($kwstr, $pos, $nulpos-$pos); + my $id = unpack("N", substr($kwstr, $nulpos+1, 4)); + $pos = $nulpos + 5; # skip NUL + 4 bytes. + $info->{kw}{$kw} = $info->{pic}{$id} if $info; + } + $val = $info; + } + + if ($key =~ /^friends:/) { + my $ver = substr($val, 0, 1, ''); + my $packfmt = "NH6H6NC"; + my $packlen = 15; + my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault); + my %friends; + + while (length($val) >= $packlen) { + my @row = unpack($packfmt, substr($val, 0, $packlen, '')); + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + # turn unpacked row into hashref + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + $val = [$ver, \%friends]; + } + + if ($key =~ /^tu:/) { + $val = unpack("N", $val); + } + if ($key =~ /^te:/) { + $val = unpack("N", $val); + } + # just in case this remains a packed scalar + if (not ref $val) { + $val =~ s/([\x00-\x1f])/sprintf("\\x%02x", $1)/eg; + } + $ret .= "Data: "; + + my $dumper = Data::Dumper->new([$val],["Value"]); + $dumper->Terse(1); + $dumper->Indent(2); + my $d = $dumper->Dump(); + + $ret.= "
    " . LJ::ehtml($d) . "
    "; + + return; + }; + + + if ($POST{'query'}) { + foreach my $key (split(/\r\n/, $POST{'query'})) { + + next unless $key =~ /\S/; + # shortcuts + $key =~ s/(##)(\w+)/$cuid->($2)/eg; + $key =~ s/(#)(\w+)/$uid->($2)/eg; + $key =~ s!\((\d+)\)!int($1/256)!eg; + + my $sock = LJ::MemCache::_get_sock($key); + $ret .= "

    Key: $key
    "; + + unless ($sock) { + $ret .= "Error: Could not connect to server

    "; + next; + } + + if ($POST{'sock'}) { + $ret .= "Socket: $sock
    "; + } + + my $hashkey = $get_hashkey->($key); + if ($hashkey) { + $ret .= "Hashkey: $hashkey
    "; + } + my $pars = defined($hashkey) ? [$hashkey, $key] : $key; + my $val = LJ::MemCache::get($pars); + unless (defined $val) { + $ret .= "Data: not found

    "; + next; + } + $display->($key, $val); + $ret .= "

    "; + } + return $ret; + } + + #my $docurl = 'http://cvs.livejournal.org/browse.cgi/livejournal/doc/raw/memcache-keys.txt?rev=.&content-type=text/x-cvsweb-markup'; + #my $docurl = 'http://cvs-ljr.lenin.ru/cgi-bin/viewvc.cgi/LJR/livejournal/doc/raw/memcache-keys.txt?view=markup'; + my $docurl = 'http://lj.rossia.org/admin/memcache-keys.txt'; + + $ret .= "

    Enter your memcache query(-ies) below.

    "; + $ret .= "

    Here\'s the reference of key names.

    "; + $ret .= "

    Shortcuts:

    #username -> userid
    ##username -> cid:userid
    (number) -> number/256

    "; + + $ret .= ""; + $ret .= " "; + $ret .= "

    " . LJ::html_check({ 'type' => 'check', 'name' => 'sock', 'id' => 'sock' }); + $ret .= "

    "; + + $ret .= ""; + return $ret; + + +_code?> + + diff --git a/local/htdocs/admin/netstat.bml b/local/htdocs/admin/netstat.bml new file mode 100755 index 0000000..c3146bf --- /dev/null +++ b/local/htdocs/admin/netstat.bml @@ -0,0 +1,56 @@ + +Netstat + +requests"; + + $ret = "
    " . $ret . "\n" . $netstat . "
    "; + + return $ret; + + + +_code?> + + + diff --git a/local/htdocs/admin/priv/index.bml b/local/htdocs/admin/priv/index.bml new file mode 100755 index 0000000..c95a91c --- /dev/null +++ b/local/htdocs/admin/priv/index.bml @@ -0,0 +1,339 @@ + + + +Privilege Management + +prepare("SELECT prlid, privcode, privname, des, is_public, scope FROM priv_list ORDER BY privcode"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + push @privs, $_; + $priv{$_->{'prlid'}} = $_; + $pcode2id{$_->{'privcode'}} = $_->{'prlid'}; + } + + if (LJ::did_post()) { + return "

    ERROR: Invalid form submission" unless LJ::check_form_auth(); + } + + unless ($mode) + { + if ($FORM{'user'}) { $mode = "viewuser"; } + elsif ($FORM{'priv'}) { $mode = "viewpriv"; } + } + + if ($FORM{'devmode'}) { + return "not in dev mode" unless $LJ::IS_DEV_SERVER; + my $userid = $remote->{userid}; + if ($dbh->do("INSERT INTO priv_map (userid, prlid, arg) SELECT ?, prlid, ? FROM priv_list WHERE privcode=?", + undef, $userid, $FORM{arg}, $FORM{priv})) { + LJ::statushistory_add($dbh, $userid, $userid, "privadd", "DEVMODE Granting: \"$FORM{priv}\" with arg \"$FORM{arg}\""); + return "done."; + } else { + return "fail."; + } + } + + unless ($mode) + { + $ret .= "

    Privilege Management

    \n"; + $ret .= ""; + $ret .= "

    View all privileges of user

    "; + + $ret .= "

    Or, show all users with privilege:

    "; + foreach my $priv (@privs) { + my ($des, $args) = split(/arg=/, $priv->{'des'}); + $ret .= "
    $priv->{'privcode'}: $priv->{'privname'}"; + $ret .= " (Site Specific)" if $priv->{'scope'} eq 'local'; + $ret .= "
    "; + $ret .= "
    $des\n"; + $ret .= "
    Argument: $args" if $args; + $ret .= "
    "; + } + $ret .= "
    "; + return $ret; + } + + + # Returns true if the remote user can grant the given priv + sub remote_can_grant + { + my ($remote, $priv, $arg) = @_; + return 0 unless defined $priv; + return LJ::check_priv($remote, 'admin', $priv) || LJ::check_priv($remote, 'admin', '*') || LJ::check_priv($remote, 'admin', "$priv/$arg"); + } + + if ($mode eq "userchange" || $mode eq "privchange") + { + unless (LJ::did_post()) { + return "

    Error: requires post

    "; + } + + unless ($FORM{'submit:refresh'}) { + foreach my $key (keys %FORM) { + if ($key =~ /^revoke:(\d+):(\d+)$/) { + my $prmid = $1; + my $del_userid1 = $2; + my $sth = $dbh->prepare("SELECT userid, prlid, arg FROM priv_map WHERE prmid=$prmid"); + $sth->execute; + my ($del_userid2, $prlid, $arg) = $sth->fetchrow_array; + + unless (remote_can_grant($remote, $priv{$prlid}->{'privcode'}, $arg)) { + $ret .= "ERROR: Invalid access to remove priv $priv{$prlid}->{'privcode'}.
    "; + } else { + if ($del_userid1 && $del_userid1 == $del_userid2) + { + $dbh->do("DELETE FROM priv_map WHERE prmid=$prmid"); + my $privcode = $priv{$prlid}->{'privcode'}; + LJ::statushistory_add($dbh, $del_userid1, $remote->{'userid'}, "privdel", + "Denying: \"$privcode\" with arg \"$arg\""); + $ret .= "Privilege removed.
    \n"; + } + } + } + } + if ($FORM{'grantpriv'}) { + my $u = LJ::load_user($FORM{'user'}); + return "ERROR: Invalid user." unless $u; + my $userid = $u->{'userid'}; + my $qpriv = $FORM{'grantpriv'}+0; + my $privcode = $priv{$qpriv}->{'privcode'}; + my $arg = $FORM{'arg'}; + + if ($privcode) { + if (remote_can_grant($remote, $privcode, $arg)) { + if (LJ::check_priv($u, $privcode, $arg)) { + $ret .= "ERROR: User already has specified priv $privcode $arg.
    "; + } else { + my $qarg = $dbh->quote($arg); + $dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $qpriv, $qarg)"); + LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$arg\""); + $ret .= "Privilege $privcode $arg granted.
    \n"; + } + } else { + $ret .= "ERROR: You don't have access to grant $privcode $arg.
    \n"; + } + } else { + $ret .= "ERROR: Unknown privilege.
    \n"; + } + } + if ($FORM{'grantuser'}) { + my $u = LJ::load_user($FORM{'grantuser'}); + return "ERROR: Invalid user." unless $u; + my $userid = $u->{'userid'}; + my $privid = $pcode2id{$FORM{'priv'}}; + my $arg = $FORM{'arg'}; + my $qarg = $dbh->quote($arg); + my $privcode = $priv{$privid}->{'privcode'}; + if ($privcode) { + if (remote_can_grant($remote, $privcode, $arg)) { + if (LJ::check_priv($u, $privcode, $arg)) { + $ret .= "ERROR: User already has specified priv $privcode $arg.
    "; + } + elsif ($userid && $privid) { + my $qarg = $dbh->quote($FORM{'arg'}); + $dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $privid, $qarg)"); + LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$FORM{'arg'}\""); + $ret .= "Privilege added.
    \n"; + } + else { + my $euser = LJ::ehtml($FORM{'grantuser'}); + unless ($userid) { + $ret .= "ERROR: cannot grant priv to non-existent user $euser
    "; + } + else { $ret .= "privid is 0!
    "; } + } + } else { + $ret .= "ERROR: You don't have access to grant $privcode with argument '$arg'.
    \n"; + } + } else { + $ret .= "ERROR: Unknown privilege.
    \n"; + } + } # end if grantuser + } + + if ($mode eq "userchange") { $mode = "viewuser"; } + if ($mode eq "privchange") { $mode = "viewpriv"; } + } + + if ($mode eq "viewuser") + { + my $user = LJ::canonical_username($FORM{'user'}); + my $userid = LJ::get_userid($user); + + $ret .= "

    << view user \"$user\"

    \n"; + unless ($userid) { + $ret .= "Error: non-existent user\n"; + return $ret; + } + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= "\n"; + $ret .= "\n"; + $sth = $dbh->prepare("SELECT pm.prmid, pm.prlid, pm.arg FROM priv_map pm, priv_list pl WHERE pm.prlid=pl.prlid AND pm.userid=$userid ORDER BY pl.privcode,pm.arg"); + $sth->execute; + $ret .= "\n"; + while (my ($prmid, $prlid, $arg) = $sth->fetchrow_array) + { + my $prec = $priv{$prlid}; + my $pcode = $priv{$prlid}->{'privcode'}; + my $can_grant = remote_can_grant($remote, $pcode, $arg); + + next unless ($prec->{'is_public'} || ($remote && $remote->{'userid'} == $userid) || $can_grant); + + $ret .= ""; + if ($arg) + { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + $ret .= "
    RevokePrivilegeArg
    "; + if ($can_grant) { + $ret .= ""; + } else { + $ret .= "--"; + } + + $ret .= "$pcode$arg
     
    "; + + if (LJ::check_priv($remote, 'admin')) { + $ret .= "

    Grant $user privilege:

    \n"; + $ret .= "\n"; + $ret .= "Arg:
    \n"; + } else { + $ret .= "

    (you do not have access to grant any privileges)

    \n"; + } + + $ret .= "

    \n"; + if (LJ::check_priv($remote, 'admin')) { + $ret .= ""; + } + $ret .= " "; + $ret .= "

    "; + return $ret; + } + + if ($mode eq "viewpriv") { + my $priv = $pcode2id{$FORM{'priv'}}; + my $prec = $priv{$priv}; + my $pcode = $prec->{'privcode'}; + my $skip = $FORM{'skip'} + 0; + my $limit = 100; + + my $viewarg; + if ($FORM{'viewarg'}) { + $viewarg = " AND pm.arg=" . $dbh->quote($FORM{'viewarg'}); + } + + my $privname = join(' ', grep { $_ } $priv{$priv}->{'privcode'}, $FORM{'viewarg'}); + $ret .= "

    << view priv \"$privname\"

    \n"; + $ret .= "

    Privilege Name: $priv{$priv}->{'privname'}"; + my ($des, $args) = split(/arg=/, $priv{$priv}->{'des'}); + $ret .= "
    Description: $des" if $des; + $ret .= "
    Argument: $args" if $args; + $ret .= "

    "; + + # $pcode is the name of the privilege list they're looking at, and $FORM{'viewarg'} is + # the argument in particular they care about + unless ($prec->{'is_public'} || remote_can_grant($remote, $pcode, $FORM{'viewarg'})) { + $ret .= "

    ERROR: This privilege's access list is not public.

    \n"; + return $ret; + } + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= "

    View only privs with arg: "; + $ret .= " "; + $ret .= "

    \n"; + + $ret .= "\n"; + $ret .= ""; + $sth = $dbh->prepare("SELECT pm.prmid, u.user, u.userid, pm.arg ". + "FROM priv_map pm, useridmap u WHERE pm.prlid=$priv AND pm.userid=u.userid$viewarg ". + "ORDER BY u.user,pm.arg LIMIT $skip,$limit"); + $sth->execute; + $ret .= "\n"; + + my $showgrant = remote_can_grant($remote, $pcode, $FORM{'viewarg'}); + my $foundcount = 0; + + while ($_ = $sth->fetchrow_hashref) + { + $foundcount++; + $ret .= ""; + if ($_->{'arg'} ne "") + { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + $ret .= "\n"; + $ret .= "
    RevokeUserArg
    "; + if (remote_can_grant($remote, $priv{$priv}->{'privcode'}, $_->{'arg'})) + { + $ret .= "{'prmid'}:$_->{'userid'}\" />"; + } else { + $ret .= "--"; + } + $ret .= "{'user'}\">$_->{'user'}{'privcode'}&viewarg=$_->{'arg'}\">$_->{'arg'}
     
    $foundcount users
    "; + + if ($foundcount >= $limit) { + $ret .= "($skip +$limit)}) . "'>See more...\n"; + } + + if ($showgrant) { + $ret .= "

    Grant $privname privilege to:

      "; + $ret .= "User: "; + $ret .= "Arg:
    \n"; + } else { + $ret .= "

    (you don't have access to grant this privilege to other users)

    \n"; + } + + if ($showgrant) { + $ret .= "\n"; + } + $ret .= "
    \n"; + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= LJ::html_hidden('mode', 'privchange', + 'priv', $pcode, + 'viewarg', $FORM{'viewarg'}) . "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + return $ret; + } + + return "Unknown mode."; + +_code?> + + + +lib: cgi-bin/ljlib.pl +link: htdocs/admin/priv/index.bml +post: htdocs/admin/priv/index.bml + diff --git a/local/htdocs/bots/index.html b/local/htdocs/bots/index.html new file mode 100755 index 0000000..e504528 --- /dev/null +++ b/local/htdocs/bots/index.html @@ -0,0 +1,12 @@ + + +

    Please advise your robots to use Last-Modified header.

    + +1, +2 +

    +Support of gzip decompression on a client side recommended. +

    +Also, RSS are cached on the server so polling interval faster than 5 minutes will not help. + + diff --git a/local/htdocs/changepassword.bml b/local/htdocs/changepassword.bml new file mode 100755 index 0000000..8c7e3b0 --- /dev/null +++ b/local/htdocs/changepassword.bml @@ -0,0 +1,178 @@ + +head=> +body<= +{'user'}; + my $memoryu = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $memoryu; + + + + if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") { + return BML::redirect("$LJ::SSLROOT/changepassword.bml"); + } + + my $crumb = $LJ::IS_SSL ? 'securechangepass' : 'changepass'; + LJ::set_active_crumb($crumb); + + my $update_form = sub { + my $ret; + + # else, show the form to change: + $ret .= "

    \n"; + $ret .= LJ::html_hidden(mode => 'submit', + ssl => $GET{'ssl'}); + + $ret .= "\n"; + $ret .= "\n"; + + my $remote = LJ::get_remote(); + + # Warn them if logged in and not validated + if (!LJ::did_post() && $remote && $remote->{'status'} ne 'A') { + $ret .= "$ML{'label.warning'} $ML{'.error.notvalidated'} warningbar?>"; + $ret .= "
    "; + } + + $ret .= "\n
    \n"; + + # we make the field for the new password *longer* than the max length + # for a password - that way we can tell if someone is trying to use an + # excessively long password, instead of silently truncating it. + + $ret .= "$ML{'.oldpassword'}
    \n"; + $ret .= "
    \n"; + $ret .= "$ML{'.newpassword'}
    \n"; + $ret .= "
    \n"; + $ret .= "$ML{'.newpasswordagain'}
    \n"; + $ret .= "
    \n"; + $ret .= "standout?>\n"; + + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "standout?>\n"; + $ret .= "
    \n"; + return $ret; + }; + + unless (LJ::did_post()) { + $body .= $update_form->(); + } elsif ($POST{'mode'} eq 'submit') { + my $user = $authas; #LJ::canonical_username($POST{'user'}); + my $password = $POST{'password'}; + my $newpass1 = LJ::trim($POST{'newpass1'}); + my $newpass2 = LJ::trim($POST{'newpass2'}); + + my $remote = LJ::get_remote(); + my $u = LJ::load_user($user); + + my @errors = (); + if ($user eq "test") { push @errors, $ML{'.error.changetestaccount'}; } + unless ($user) { + push @errors, $ML{'.error.mustenterusername'}; + } else { + unless (defined $u) { + push @errors, BML::ml('.error.invaliduser', {'user' => $user} ); + } else { + if (LJ::login_ip_banned($u)) { + push @errors, $ML{'error.ipbanned'}; + } elsif ($u->{'password'} eq "" || $u->{'password'} ne $password) { + push @errors, $ML{'.error.badoldpassword'}; + LJ::handle_bad_login($u); + } + } + } + if ($newpass1 ne $newpass2) { + push @errors, $ML{'.error.badnewpassword'}; + } else { + if ($newpass1 eq "") { + push @errors, $ML{'.error.blankpassword'}; + } elsif (length $newpass1 > 30) { + push @errors, $ML{'.error.characterlimit'}; + } else { + + my @checkpass = LJ::run_hooks("bad_password", + { 'user' => $u->{'user'}, 'password' => $newpass1, + 'name' => $u->{'name'}, 'email' => $u->{'email'} }); + if (@checkpass && $checkpass[0]->[0]) { + push @errors, BML::ml('.error.badcheck', {'error' => $checkpass[0]->[0]}); + } + } + } + + # don't allow changes if email address is not validated + unless ($u->{'status'} eq 'A') { + push @errors, $ML{'.error.notvalidated'}; + } + + unless (LJ::is_ascii($newpass1)) { + push @errors, $ML{'.error.nonascii'}; + } + + if (@errors) { + $body .= LJ::error_list(@errors); + $body .= $update_form->(); + return $body; + } + + ## make note of changed password + my $dbh = LJ::get_db_writer(); + my $oldval = Digest::MD5::md5_hex($u->{'password'} . "change"); + LJ::infohistory_add($u, 'password', $oldval); + + LJ::update_user($u, { password => $POST{'newpass1'} }); + + # Kill all sessions, forcing user to relogin + $u->kill_all_sessions; + + LJ::send_mail({ + 'to' => $u->{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => $ML{'.email.subject'}, + 'body' => BML::ml('.email.body', {'sitename'=>$LJ::SITENAME, 'siteroot'=>$LJ::SITEROOT})}); + + $body = ""; + + # if they were logged in, tell them to relogin + $body .= " "href='/login.bml'" }) . " p?>" if $remote; + + LJ::run_hooks("post_changepassword", { + "u" => $u, + "newpassword" => $POST{'newpass1'}, + "oldpassword" => $u->{'password'}, + }); + } + + return $body; +_code?> +<=body +page?> +post: htdocs/changepassword.bml +lib: Digest::MD5 +hook: post_changepassword + _c?> diff --git a/local/htdocs/community/create.bml b/local/htdocs/community/create.bml new file mode 100755 index 0000000..a1c45b7 --- /dev/null +++ b/local/htdocs/community/create.bml @@ -0,0 +1,315 @@ + +body<= +" unless LJ::text_in(\%POST); + + my $mode = $POST{mode} || 'getinfo'; + + my $remote = LJ::get_remote(); + return "" if !$remote; + return "" + if $remote->{journaltype} ne 'P'; + return "" + unless $remote->{statusvis} eq 'V'; + + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + # fix up the incoming data (is used in getinfo mode and submit mode so it's here) + $POST{membership} = 'open' + unless $POST{membership} =~ m/^(?:open|moderated|closed)$/; + $POST{postlevel} = 'members' + unless $POST{postlevel} =~ m/^(?:members|select)$/; + $POST{nonmember_posting} = '0' + unless $POST{nonmember_posting} =~ m/^[01]$/; + $POST{moderated} = '0' + unless $POST{moderated} =~ m/^[01]$/; + + # MODE: submit - try to create an account. might change mode + # if there are errors, we'll populate $error and + # return to "getinfo" mode below + my $error; +SUBMIT: + while ($mode eq 'submit') # using while instead of if so we can 'last' out of it + { + return "$ML{'Error'}: $ML{'.error.postrequired'}" unless LJ::did_post(); + + my $user = LJ::canonical_username($POST{user}); + my $title = $POST{title} || $user; + + # reject this email? + return LJ::sysban_block(0, "Create user blocked based on email", + { new_user => $user, email => $remote->{email}, name => $user }) + if LJ::sysban_check('email', $remote->{email}); + + $error = "$ML{'error.usernamelong'}" if length($user) > 15; + $error = "$ML{'error.usernameinvalid'}" if $POST{user} && !$user; + $error = "$ML{'.error.username.mustenter'}" unless $POST{user}; + + my $u = LJ::load_user($user); + + if(!LJ::check_priv($remote, 'create_protected_com')){ + foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { + next unless $user =~ /$re/; + + # you can give people sharedjournal priv ahead of time to create + # reserved communities: + next if LJ::check_priv($remote, "sharedjournal", $user); + + $error = "$ML{'.error.username.reserved'}"; + } + } + + my $second_submit = 0; + if ($u) { + my $in_use = 1; + + if ($u->{email} eq $remote->{email}) { + if (LJ::login_ip_banned($u)) { + # brute-force possible going on + } else { + if ($u->{password} eq $remote->{password}) { + # oh, they double-clicked the submit button + $second_submit = 1; + + # if we found a comm and everything matches, they double hit. if + # we found a person/etc, then they tried to recreate their community, + # which isn't allowed anymore + $in_use = $u->{journaltype} eq 'C' ? 0 : 1; + } else { + LJ::handle_bad_login($u); + } + } + } + + if ($in_use) { + $error = "$ML{'.error.username.inuse'}"; + } + } + + last SUBMIT if $error; + + my $qclusterid = LJ::new_account_cluster() + 0; + die "Cluster 0 not supported" unless $qclusterid; + + my $userid = ref $u ? $u->{userid} : 0; + unless ($second_submit) { + my $dbh = LJ::get_db_writer(); + + my $errorcounter = 0; + my $old_print_error = $dbh->{PrintError}; # save PrintError mode + $dbh->{PrintError} = 0; # will check for errors manually + + while (1) { + my $ruserid = LJ::get_new_userid("P"); + + if (!$ruserid) { + return ""; + } + $dbh->do("set insert_id = $ruserid"); + + $dbh->do( + "INSERT INTO user (user, email, status, caps, name, clusterid, dversion, journaltype) ". + "VALUES (?, ?, ?, ?, ?, ?, $LJ::MAX_DVERSION, 'C')", + undef, $user, $remote->{email}, $remote->{status}, int($LJ::NEWUSER_CAPS), $title, $qclusterid); + + if ($dbh->err) { + # who wants to try forever + if ($errorcounter > 10) { + return "" . $dbh->errstr . " p?>"; + } + + $errorcounter++; + sleep 1; # let it breathe + next; # try again + } + else { + $userid = $dbh->{'mysql_insertid'}; # smells like success + $dbh->{PrintError} = $old_print_error; # restore error reporting + + return 0 unless $userid; # but? + + last; # finally + } + } + + if ($LJ::LJR_FIF) { + use LJ::MemCache; + my $ljr_fif_id = LJ::get_userid($LJ::LJR_FIF); + if ($ljr_fif_id) { + $dbh->do("INSERT INTO friends (userid, friendid) VALUES (?, ?)", undef, $ljr_fif_id, $userid); + # refresh memcache + #my $memkey = [$ljr_fif_id, "friends:$ljr_fif_id"]; + #LJ::MemCache::delete($memkey); + LJ::get_friends($ljr_fif_id, undef, undef, 'force', {} ); + } + } + + $dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user); + $dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid); + + # set any properties that get set in new users + $u = LJ::load_userid($userid); + while (my ($name, $val) = each %LJ::USERPROP_INIT) { + LJ::set_userprop($u, $name, $val); + } + + # since they're a community, let's do more setup + $dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES (?, ?, ?)", + undef, $userid, $POST{membership}, $POST{postlevel}); + LJ::set_userprop($u, 'nonmember_posting', $POST{nonmember_posting} + 0); + LJ::set_userprop($u, 'moderated', $POST{moderated} + 0); + LJ::set_rel($userid, $remote->{userid}, 'M') if $POST{moderated}; # moderator if moderated + LJ::set_rel($userid, $remote->{userid}, 'A'); # maintainer + LJ::join_community($remote, $u, 0, 1); # make them a member of the community + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + }); + } + + my $nu = LJ::load_userid($userid, "force"); + + # log creation + $nu->log_event('account_create', { remote => $remote }); + + # local sites may want to override what happens at this point + my $ret; + my $redirect; + my $stop_output; + LJ::run_hooks("create.bml_postsession", { + post => \%POST, + u => $nu, + type => 'community', + redirect => \$redirect, + ret => \$ret, + stop_output => \$stop_output, + }); + return BML::redirect($redirect) if $redirect; + return $ret if $stop_output; + + $ret = ""; + my $uri = LJ::journal_base($nu); + $ret .= "\n"; + $ret .= "$uri/
    standout?>\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= "

    " . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "

    "; + $ret .= "
    \n"; + + return $ret; + + } + + if ($mode eq "getinfo" || $error) + { + my $ret; + + if ($error) { + $ret .= "$ML{'.errors.label'}
      "; + $ret .= "
    • $error
    • "; + $ret .= "
    errorbar?>"; + } + + $ret .= "" unless $error; + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'submit', ssl => $FORM{'ssl'}); + + $ret .= "
      "; + + # username + my $v = LJ::ehtml($FORM{'user'}); + $ret .= "
    1. $ML{'.username.head'}
      "; + $ret .= "

      $error

      "; + $ret .= "
      " . BML::ml(".username.text", { sitename => $LJ::SITENAME }) . "
      "; + $ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style=""' }); + $ret .= "
      " . BML::ml('.person', { aopts => "href='$LJ::SITEROOT/create.bml'" }); + $ret .= "
      $ML{'.username.charsallowed'}
      " unless $error; + $ret .= "
    2. "; + + # account title + $v = LJ::ehtml($FORM{'title'}); + $ret .= "
    3. $ML{'.name.head'}
      "; + $ret .= "
      $ML{'.name.text'}
      "; + $ret .= LJ::html_text({ name => 'title', style => 'width: 60%;', maxlength => 80, value => $v, }); + $ret .= "
    4. "; + + # membership levels + $ret .= "
    5. $ML{'/community/settings.bml.label.membership'}" . + "
      $ML{'/community/settings.bml.label.whocanjoin'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen', + value => 'open', selected => ($POST{membership} eq 'open' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated', + value => 'moderated', selected => ($POST{membership} eq 'moderated' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed', + value => 'closed', selected => ($POST{membership} eq 'closed' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    6. "; + + # posting access options + $ret .= "
    7. $ML{'/community/settings.bml.label.postaccess'}" . + "
      $ML{'/community/settings.bml.label.whocanpost'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postopen', + value => 'members', selected => ($POST{postlevel} eq 'members' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postclosed', + value => 'select', selected => ($POST{postlevel} eq 'select' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    8. "; + + # nonmember posting options + $ret .= "
    9. $ML{'/community/settings.bml.label.nmheader'}" . + "
      $ML{'/community/settings.bml.label.nmtext'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonopen', + value => '0', selected => ($POST{nonmember_posting} eq '0' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonclosed', + value => '1', selected => ($POST{nonmember_posting} eq '1' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    10. "; + + # moderated options + $ret .= "
    11. $ML{'/community/settings.bml.label.modheader'}" . + "
      $ML{'/community/settings.bml.label.modtext'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radunmod', + value => '0', selected => ($POST{moderated} eq '0' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radmod', + value => '1', selected => ($POST{moderated} eq '1' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    12. "; + + LJ::run_hooks("create.bml_opts", { + post => \%POST, + get => \%GET, + ret => \$ret, + }); + + $ret .= "
    "; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + $ret .= "
    "; + + return $ret; + } + + return "$ML{'error.unknownmode'}: $mode"; +} +_code?> +<=body +page?> diff --git a/local/htdocs/community/join.bml b/local/htdocs/community/join.bml new file mode 100755 index 0000000..742098a --- /dev/null +++ b/local/htdocs/community/join.bml @@ -0,0 +1,148 @@ +"; + return; + } + + # bad statusvis? + unless ($remote->{statusvis} eq 'V') { + $body = ""; + return; + } + + # get info about the community + my $cuserid = $FORM{'cuserid'}+0; + my $cu = $FORM{comm} ? + LJ::load_user($FORM{comm}) : # they gave us the comm name + LJ::load_userid($cuserid); # they gave us the comm id + + # NOTE: we wrapped this in an eval due to code going live; the library isn't going to go + # live at the same time as the BML file, and we don't want weird things happening, so we + # verify that this is all good and return an error if it's not okay. + my $ci; + eval { $ci = LJ::get_community_row($cu); }; + if ($@) { + $body = ""; + return; + } + $cuserid = $ci->{'userid'}; + + LJ::text_out(\$ci->{'name'}); + my $ecname = LJ::ehtml($ci->{'name'}); + + # does this community even exit? + unless ($cu) { + $body .= ""; + return; + } + + # make sure a community doesn't join a community (that's confusing + # or something) + unless ($remote->{'journaltype'} eq "P") { + $body .= ""; + return; + } + + # ensure this user isn't banned + if (LJ::is_banned($remote, $cuserid)) { + $body .= ""; + return; + } + +# # and make sure they're not already a member +# if (LJ::is_friend($cuserid, $remote->{userid})) { +# $body .= ""; +# return; +# } + + # get the list of maintainers and their usernames + my $dbr = LJ::get_db_reader(); + my $admins = $dbr->selectcol_arrayref("SELECT u.user FROM useridmap u, reluser r ". + "WHERE r.userid=$cuserid AND r.targetid=u.userid AND r.type='A'") || []; + my $list = "
      "; + foreach (sort @$admins) { $list .= "
    • "}; + $list .= "
    "; + + # can't join closed communities + # but if invited, go around and finally join + +my $invited=0; + + if ($ci->{membership} eq 'closed') { + + my $inv = LJ::get_sent_invites($cuserid) || []; + + foreach my $invite (@$inv) { + my $id = $invite->{userid}; + if (($invited!=1) && ($id == $remote->{'userid'})) {$invited=1;} + } + + if($invited == 0){ + $body .= " $list }) . + " p?>"; + return; + } + } + # now do the join + if ($POST{confirm}) { + # can members join this community openly? + # another case if user is already invited - then we will not make a request + if (($ci->{membership} ne 'open') && ($invited == 0)) { + # hit up the maintainers to let them know a join was requested + LJ::comm_join_request($cu, $remote); + $body .= ""; + return; + } + + # make remote user a friend of the community + LJ::join_community($remote, $cu, $FORM{addfriend}); + + # success message + $body .= " $ci->{user}, commname => $ecname}) . " p?>"; + + # if community permits it, tell the user they have access + if ($ci->{postlevel} eq "members") { + $body .= ""; + } else { + $body .= " $list }) . " p?>"; + } + } else { + if (($ci->{membership} ne 'open') && ($invited == 0)) { + $body .= " LJ::ljuser($cu) }) . "
    p?>"; + $body .= "
    "; + $body .= ""; + $body .= ""; + $body .= "
    "; + return; + } + + $body .= " $ecname }); + $body .= "
    "; + $body .= ""; + $body .= "
    "; + $body .= ""; + $body .= BML::ml('.label.addtofriends', { maintainer => $ecname }); + $body .= "
    p?>"; + } + + return; + +_code?> +body=> +page?> +link: htdocs/login.bml, htdocs/userinfo.bml +post: htdocs/community/join.bml + _c?> + diff --git a/local/htdocs/community/pending.bml b/local/htdocs/community/pending.bml new file mode 100755 index 0000000..f9620f7 --- /dev/null +++ b/local/htdocs/community/pending.bml @@ -0,0 +1,135 @@ + +body<= + '/community/manage.bml', + 'text' => $ML{'/community/members.bml.manage2'}, + }); + + # get remote + my $remote = LJ::get_remote(); + return "" + unless $remote; + + my $cname = $GET{'comm'}; + return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname; + + # get $c object + my $c = LJ::load_user($cname); + return "" + unless $c; + my $cid = $c->{'userid'}; + + # is $remote an admin? + unless (LJ::can_manage($remote, $c)) { + $ret .= " LJ::ljuser($cname, { type => 'C' }) }); + $ret .= " p?>"; + return $ret; + } + + # hit up the database to find pending members + my $pendids = LJ::get_pending_members($c) || []; + my $us = LJ::load_userids(@$pendids); + + # nothing pending? + return "" + unless @$pendids || LJ::did_post(); + + # saving a form submission + if ($POST{'action:update'}) { + my @userids = split(',', $POST{'ids'}); + + # need a db handle now + my $dbh = LJ::get_db_writer(); + + # hit up each user to find out what to do with them + my ($added, $rejected, $ignored, $previous); + foreach my $id (@userids) { + unless ($us->{$id}) { + $previous++; + next; + } + if ($POST{"pending_$id"} eq 'yes') { + LJ::approve_pending_member($cid, $id); + $added++; + } elsif ($POST{"pending_$id"} eq 'no') { + LJ::reject_pending_member($cid, $id); + $rejected++; + } else { + $ignored++; + } + } + + $ret .= ""; + $ret .= " $added }) . " p?>" if $added; + $ret .= " $rejected }) . " p?>" if $rejected; + $ret .= " $ignored }) . " p?>" if $ignored; + $ret .= " $previous }) . " p?>" if $previous; + $ret .= " BML::get_uri() . "?comm=$cname" }) . " p?>"; + + return $ret; + } + + my @users = sort { $a->{user} cmp $b->{user} } values %$us; + my $page_size = 100; # change to adjust page size + + # how to make links back to this page + my $self_link = sub { + return "pending.bml?comm=$cname&page=$_[0]"; + }; + + my %items = BML::paging(\@users, $GET{page}, $page_size); + my $navbar = LJ::paging_bar($items{page}, $items{pages}, + { self_link => $self_link }); + @users = @{$items{items}}; + + # output starts here + $ret .= " LJ::ljuser($cname, { type => 'C' }) }); + $ret .= " " . BML::ml('/community/members.bml.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>"; + + $ret .= "
    "; + + # table headers + $ret .= "
    \n" . + "\n"; + + # rows for existing users + my $rc = 0; + foreach (@users) { + my $rstyle = ($rc++ & 1) ? '' : ''; + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + } + + # some hidden values + $ret .= LJ::html_hidden('ids', join(',', map { $_->{userid}} @users)) . "\n"; + $ret .= "
    $ML{'/community/members.bml.key.user'}$ML{'.approve.title'}
    " . LJ::ljuser($_->{user}) . "" . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}", + id => "pending_$_->{userid}_yes", value => 'yes' }); + $ret .= " " . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}", + id => "pending_$_->{userid}_no", value => 'no' }); + $ret .= "

    " . LJ::html_submit('action:update', $ML{'/community/members.bml.update'}) . "

    \n"; + $ret .= "
    \n\n"; + + $ret .= $navbar; + + return $ret; + +} +_code?> + +<=body +page?> diff --git a/local/htdocs/community/settings.bml b/local/htdocs/community/settings.bml new file mode 100755 index 0000000..16dd4d5 --- /dev/null +++ b/local/htdocs/community/settings.bml @@ -0,0 +1,252 @@ + +<=title +head<= + +<=head +body<= + '/community/manage.bml', + 'text' => $ML{'/community/members.bml.manage2'}, + }); + my %errors; + + my $remote = LJ::get_remote(); + + unless ($remote) { + $ret .= ""; + return $ret; + } + + unless ($remote->{'journaltype'} eq 'P') { + $ret .= ""; + return $ret; + } + + my $mode = "modify"; + $mode = "create" if $GET{'mode'} eq 'create'; + + if (LJ::did_post()) + { + my $sth; + my $cuser = LJ::canonical_username($POST{'cuser'}); + my $cu = LJ::load_user($cuser); + + unless ($cu) { + $errors{'username'} = $ML{'.error.notfound'}; + } + + if ($cu && $cu->{'userid'} == $remote->{'userid'}) { + $errors{'username'} = $ML{'.error.samenames'}; + } + + # if we're changing rather than creating, check that we can + if ($mode eq 'modify' && !LJ::can_manage_other($remote, $cu)) { + $errors{'username'} = BML::ml('.error.noaccess', {'comm'=>$cuser}); + } + + # if we're creating, community password must match + if ($mode eq 'create' && $cu && !LJ::auth_okay($cu, $POST{'cpassword'})) { + $errors{'password'} = $ML{'.error.badpassword'}; + } + + # disallow changing the journal type if the journal has entries + if ($mode eq 'create' && !%errors && !LJ::check_priv($remote, "changejournaltype", "")) { + my $count; + my $userid=$cu->{'userid'}+0; + + my $dbcr = LJ::get_cluster_reader($cu); + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=$userid AND posterid=journalid"); + + $errors{'username'} = $ML{'.error.hasentries'} if $count; + } + + # if it's already a community, don't let them turn it into a community + if ($mode eq 'create' && !%errors && $cu->{journaltype} eq 'C') { + $errors{'username'} = $ML{'.error.alreadycomm'}; + } + + # if we found errors, we'll redisplay the form below. otherwise, + # proceed. + unless (%errors) { + my $dbh = LJ::get_db_writer(); + my $cid = $cu->{'userid'}; + my $qmembership = $POST{membership}; + $qmembership = 'closed' unless $qmembership =~ m/(?:open|moderated|closed)/; + $qmembership = $dbh->quote($qmembership); + my $qpostlevel = $dbh->quote($POST{'postlevel'} eq "members" ? "members" : "select"); + + LJ::update_user($cu, { journaltype => 'C' }); + if ($mode eq 'create') { + $dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES ($cid, $qmembership, $qpostlevel)"); + LJ::set_rel($cu, $remote, 'A'); + + # delete existing friends + my $friends = LJ::get_friends($cid, undef, undef, 'force') || {}; + LJ::remove_friend($cid, [ keys %$friends ]); + + } else { + $dbh->do("UPDATE community SET membership=$qmembership, postlevel=$qpostlevel WHERE userid=$cid"); + } + + my $nonmembers = $POST{'nonmember_posting'} + 0; + my $moderated = $POST{'moderated'} + 0; + + LJ::set_userprop($cu, 'nonmember_posting', $nonmembers); + LJ::set_userprop($cu, 'moderated', $moderated); + + if ($moderated && ! LJ::load_rel_user($cu->{'userid'}, 'M')->[0]) { + LJ::set_rel($cu->{'userid'}, $remote->{'userid'}, 'M'); + } + + $ret .= ""; + if ($mode eq 'create') { + $ret .= ""; + } else { + $ret .= ""; + } + + $ret .= "
  • $ML{'.label.commsite'}
  • "; + $ret .= "
  • $ML{'.label.comminfo'}
  • " + . BML::ml('.label.managepage', { 'aopts' => 'href="/community/manage.bml"' }) . "
  • p?>"; + + return $ret; + } + } + + # we're either creating a new community or modifying settings of an existing one + # based on whether $mode is 'create' or 'modify'. Most of the page is the same in + # either case, and additionally we must preload existing settings when modifying. + + my ($cname, $c); + + $cname = $POST{'cuser'}; # if we're falling through with errors when creating + + my %info = ( + 'membership'=>$POST{'membership'} || 'open', + 'postlevel'=>$POST{'postlevel'} || 'members', + 'nonmember_posting'=>$POST{'nonmember_posting'} || 0, + 'moderated'=>$POST{'moderated'} || 0, + ); + + if ($mode eq 'modify') { + $cname = LJ::canonical_username($GET{'comm'}); + $c = LJ::load_user($cname); + unless ($c) { + # if no community was specified, redirect to manage.bml + return BML::redirect("$LJ::SITEROOT/community/manage.bml"); + } + unless ($c->{'journaltype'} eq 'C') { + $ret = ""; + return $ret; + } + my $dbr = LJ::get_db_reader(); + ($info{'membership'},$info{'postlevel'}) = + $dbr->selectrow_array("SELECT membership, postlevel FROM community WHERE userid=$c->{'userid'}"); + LJ::load_user_props($c, "nonmember_posting", "moderated"); + $info{'nonmember_posting'} = $c->{'nonmember_posting'} ? 1 : 0; + $info{'moderated'} = $c->{'moderated'} ? 1 : 0; + } + + $ret .= "
    "; + + if ($mode eq 'modify') { + $ret .= ""; + } else { + $ret .= ""; + } + + if ($mode eq 'create') { + LJ::set_active_crumb('createcommunity'); + $ret .= "" . + ($mode eq 'modify' ? "" : ""); + $ret .= "$ML{'.label.maintainer'}"; + $ret .= "{'user'} ljuser?>
    $ML{'.label.maintainer.login'}"; + $ret .= "$ML{'.label.community'}"; + $ret .= "$ML{'.label.username'}

    "; + $ret .= "
    "; + $ret .= "$ML{'.label.password'}

    "; + $ret .= " standout?>"; + } else { + LJ::set_active_crumb('commsettings'); + $ret .= LJ::html_hidden('cuser', $cname); + $ret .= """}); + $ret .= " " . BML::ml('.members',{'link'=>"/community/members.bml?comm=$cname"}) . " p?>"; + } + + $ret .= ""; + $ret .= "
    "; + + # membership levels + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen', + value => 'open', selected => ($info{membership} eq 'open' ? 1 : 0)}); + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated', + value => 'moderated', selected => ($info{membership} eq 'moderated' ? 1 : 0)}); + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed', + value => 'closed', selected => ($info{membership} eq 'closed' ? 1 : 0)}); + $ret .= "

    "; + $ret .= "
    "; + + my ($optopen,$optclosed); + if ($info{'postlevel'} eq 'members') { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    "; + + if ($info{'nonmember_posting'}) { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    "; + + if ($info{'moderated'}) { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    \n"; + + $ret .= "
    "; + + return $ret; + +_code?> + +<=body +page?> diff --git a/local/htdocs/create.bml b/local/htdocs/create.bml new file mode 100755 index 0000000..1fd285c --- /dev/null +++ b/local/htdocs/create.bml @@ -0,0 +1,639 @@ + +head<= + +<=head +body<= +" unless LJ::text_in(\%POST); + + my $mode = $POST{'mode'}; + my $code = $POST{'code'} || $GET{'code'}; + + if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") { + return BML::redirect("$LJ::SSLROOT/create.bml"); + } + + # with no mode, decide which screen the user sees first, based + # on whether or not this LJ installation lets in free users + if ($mode eq "") { + $mode = $LJ::USE_ACCT_CODES ? + ($code ? "codesubmit" : "entercode") + : "getinfo"; + } + + my $remote = LJ::get_remote(); + + my %errors; + my $error_msg = sub { + my $key = shift; + my $pre = shift; + my $post = shift; + my $msg = $errors{$key}; + return unless $msg; + return "$pre $msg $post"; + }; + + # Flag to indicate they've submitted with 'audio' as the answer to the spambot + # challenge. + my $wants_audio = 0; + + # Captcha + my $recaptcha = Captcha::reCAPTCHA->new; + + # validate a code they've entered and throw them back to entercode + # mode if it's invalid + if ($code && $mode eq "submit" || # account codes turned off, but one specified anyway + $LJ::USE_ACCT_CODES && ($mode eq "codesubmit" || $mode eq "submit")) # account codes required + { + my $error; + my $userid = 0; # acceptable userid for double-click protection + if ($mode eq "submit") { + my $u = LJ::load_user($POST{'user'}); + $userid = $u->{'userid'}; + } + $errors{'code'} = $error + unless (LJ::acct_code_check($code, \$error, $userid)); + if (%errors) { + $mode = "entercode"; + } elsif ($mode eq "codesubmit") { + $mode = "getinfo"; + } + } + + # MODE: entercode - enter an account code to proceed making an account + if ($LJ::USE_ACCT_CODES && $mode eq "entercode") + { + my $ret; + my $v; + + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'codesubmit', + ssl => $FORM{'ssl'}); + + $ret .= ""; + + $v = LJ::ehtml($code); + $ret .= " "; + $ret .= $error_msg->('code', '
    '); + $ret .= " standout?>"; + $ret .= "
    \n"; + + open (REM, "$LJ::HOME/htdocs/inc/account-codes"); + while () { + $ret .= $_; + } + close REM; + + return $ret; + } + +# MODE: submit - if they've given 'audio' as the answer to the spambot-blocker, +# reset the mode to 'getinfo' and set the audio flag +if ( $LJ::HUMAN_CHECK{create} && $mode eq 'submit' && lc($POST{answer}) eq 'audio' ) +{ + $mode = 'getinfo'; + $wants_audio = 1; +} + + # MODE: submit - try to create an account. might change mode + # if there are errors, we'll populate %errors and + # return to "getinfo" mode below + SUBMIT: + while ($mode eq "submit") # using while instead of if so we can 'last' out of it + { + return "$ML{'Error'}: $ML{'.error.postrequired'}" unless LJ::did_post(); + + my $user = LJ::canonical_username($POST{'user'}); + my $email = LJ::trim(lc($POST{'email'})); + + # setup global things that can be used to modify the user later + my $is_underage = 0; # turn on if the user should be marked as underage + my $ofage = 0; # turn on to note that the user is over 13 in actuality + # (but is_underage might be on which just means that their + # account is being marked as underage--even if they're old + # enough [unique cookie check]) + + # reject this email? + return LJ::sysban_block(0, "Create user blocked based on email", + { 'new_user' => $user, 'email' => $email, 'name' => $user }) + if LJ::sysban_check('email', $email); + + my $dbh = LJ::get_db_writer(); + + if (length($user) > 15) { + $errors{'username'} = "$ML{'error.usernamelong'}"; + } + if ($POST{'user'} && ! $user) { + $errors{'username'} = "$ML{'error.usernameinvalid'}"; + } + unless ($POST{'user'}) { + $errors{'username'} = "$ML{'.error.username.mustenter'}"; + } + foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { + next unless ($user =~ /$re/); + + # you can give people sharedjournal priv ahead of time to create + # reserved communities: + next if LJ::check_priv($remote, "sharedjournal", $user); + + $errors{'username'} = "$ML{'.error.username.reserved'}"; + } + + # see if they're confused and entered a valid account code + # for their username (happens often) + if ($LJ::USE_ACCT_CODES && $user =~ /^.....a[ab].....$/) { + # see if the acctcode is valid and unused + my ($acid, $auth) = LJ::acct_code_decode($user); + my $is_valid = $dbh->selectrow_array("SELECT COUNT(*) FROM acctcode ". + "WHERE acid=? AND rcptid=0", + undef, $acid); + $errors{'username'} = "$ML{'.error.username.iscode'}" + if $is_valid; + } + + my $u = LJ::load_user($user); + my $second_submit = 0; + if ($u) { + my $in_use = 1; + + if ($u->{'email'} eq $POST{'email'}) { + if (LJ::login_ip_banned($u)) { + # brute-force possible going on + } else { + if ($u->{'password'} eq $POST{'password1'}) { + # oh, they double-clicked the submit button + $second_submit = 1; + $in_use = 0; + } else { + LJ::handle_bad_login($u); + } + } + } + + if ($in_use) { + $errors{'username'} = "$ML{'.error.username.inuse'}"; + } + } + + $POST{'password1'} = LJ::trim($POST{'password1'}); + $POST{'password2'} = LJ::trim($POST{'password2'}); + + if ($POST{'password1'} ne $POST{'password2'}) { + $errors{'password'} = "$ML{'.error.password.nomatch'}"; + } else { + my @checkpass = LJ::run_hooks("bad_password", + { 'user' => $user, 'name' => $user, + 'email' => $email, 'password' => $POST{'password1'} }); + if (@checkpass && $checkpass[0]->[0]) { + $errors{'password'} = "Bad password: $checkpass[0]->[0]"; + } + } + if (! $POST{'password1'}) { + $errors{'password'} = "$ML{'.error.password.blank'}"; + } elsif (length $POST{'password1'} > 30) { + $errors{'password'} = "$ML{'password.max30'}"; + } + + unless (LJ::is_ascii($POST{'password1'})) { + $errors{'password'} = "$ML{'.error.password.asciionly'}"; + } + + ### start COPPA_CHECK + # age checking to determine how old they are + if ($LJ::COPPA_CHECK) { + my $uniq; + if ($LJ::UNIQ_COOKIES) { + $uniq = Apache->request->notes('uniq'); + if ($uniq) { + my $timeof = $dbh->selectrow_array('SELECT timeof FROM underage WHERE uniq = ?', undef, $uniq); + $is_underage = 1 if $timeof && $timeof > 0; + } + } + + my ($year, $mon, $day) = ( $POST{"bday_yyyy"}+0, $POST{"bday_mm"}+0, $POST{"bday_dd"}+0 ); + if ($year < 100) { + $POST{'bday_yyyy'} += 1900; + $year += 1900; + } + + # get current time + my ($nday, $nmon, $nyear) = (gmtime())[3, 4, 5]; + $nyear += 1900; + $nmon += 1; + + # require dates in the 1900s (or beyond) + if ($year && $mon && $day && $year >= 1900 && $year <= $nyear) { + # now see how many years back they are + my $ofageyear = $year + 13; + if ($ofageyear > $nyear) { + $is_underage = 1; + } elsif ($ofageyear == $nyear) { + # years match, see if they were born after this month + if ($mon > $nmon) { + $is_underage = 1; + } elsif ($mon == $nmon) { + # now check the day + if ($day > $nday) { + $is_underage = 1; + } else { + $ofage = 1; + } + } else { + $ofage = 1; + } + } else { + $ofage = 1; + } + } else { + $errors{'bday'} = "$ML{'.error.birthday.invalid'}"; + } + + # note this unique cookie as underage (if we have a unique cookie) + if ($is_underage && $uniq) { + $dbh->do("REPLACE INTO underage (uniq, timeof) VALUES (?, UNIX_TIMESTAMP())", undef, $uniq); + } + } + ### end COPPA_CHECK + + if ($LJ::TOS_CHECK && ! $POST{'agree_tos'}) { + $errors{'agree_tos'} = $ML{'tos.error'}; + } + + # check the email address + { + my @email_errors; + LJ::check_email($email, \@email_errors); + if ($LJ::USER_EMAIL and $email =~ /\@\Q$LJ::USER_DOMAIN\E$/i) { + push @email_errors, BML::ml(".error.email.lj_domain", + {domain => $LJ::USER_DOMAIN}); + } + $errors{'email'} = join(", ", @email_errors) if @email_errors; + } + + # Check the turing test answer if it's turned on + if ($LJ::HUMAN_CHECK{create}) { + my $result = $recaptcha->check_answer($LJ::recaptcha_private_key, LJ::get_remote_ip(), + $POST{recaptcha_challenge_field}, + $POST{recaptcha_response_field}); + $errors{'captcha'} = $ML{'.captcha.invalid'} unless $result->{is_valid}; + } + + if ($LJ::LJR_NEWACC_RATE && $LJ::LJR_NEWACC_RATEPERIOD) { + my $numaccs = $dbh->selectrow_array( + "SELECT count(*) FROM userlog WHERE ip = ? and action = 'account_create' and logtime > UNIX_TIMESTAMP() - ?", + undef, LJ::get_remote_ip(), $LJ::LJR_NEWACC_RATEPERIOD); + if ($numaccs > $LJ::LJR_NEWACC_RATE) { + $errors{'banned'} = 'Sorry, we do not accept that much accounts from one person that fast.'; + } + } + + use Golem; + my $tnet = Golem::get_containing_net(LJ::get_remote_ip(), {"with_props" => 1}); + $tnet = Golem::get_net(LJ::get_remote_ip(), 32, {"with_props" => 1}) unless $tnet; + if ($tnet && $tnet->{'props'}->{'data'}->{'ban_new_accounts'}) { + $errors{'banned'} = 'Sorry, we do not accept accounts from you.'; + } + + last SUBMIT if %errors; + + my $clusterid = ($LJ::ALLOW_CLUSTER_SELECT + ? $POST{'cluster_id'} + : LJ::new_account_cluster()) + 0; + die "Cluster 0 not supported" unless $clusterid; + + my $userid = $u ? $u->{'userid'}+0 : 0; + unless ($second_submit) + { + my $caps = int($LJ::NEWUSER_CAPS); + my $status = ($LJ::EVERYONE_VALID ? 'A' : 'N'); + + my $errorcounter = 0; + my $old_print_error = $dbh->{PrintError}; # save PrintError mode + $dbh->{PrintError} = 0; # will check for errors manually + + while (1) { + my $ruserid = LJ::get_new_userid("P"); + + if (!$ruserid) { + return ""; + } + $dbh->do("set insert_id = $ruserid"); + + $dbh->do( + "INSERT INTO user (user, email, password, status, caps, name, clusterid, dversion) ". + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + undef, $user, $email, $POST{'password1'}, $status, $caps, + $user, $clusterid, $LJ::MAX_DVERSION); + + if ($dbh->err) { + # who wants to try forever + if ($errorcounter > 10) { + return "" . $dbh->errstr . " p?>"; + } + + $errorcounter++; + sleep 1; # let it breathe + next; # try again + } + else { + $userid = $dbh->{'mysql_insertid'}; # smells like success + $dbh->{PrintError} = $old_print_error; # restore error reporting + + return 0 unless $userid; # but? + + last; # finally + } + } + + if ($LJ::LJR_FIF) { + use LJ::MemCache; + my $ljr_fif_id = LJ::get_userid($LJ::LJR_FIF); + if ($ljr_fif_id) { + $dbh->do("INSERT INTO friends (userid, friendid) VALUES (?, ?)", undef, $ljr_fif_id, $userid); + # refresh memcache + #my $memkey = [$ljr_fif_id, "friends:$ljr_fif_id"]; + #LJ::MemCache::delete($memkey); + LJ::get_friends($ljr_fif_id, undef, undef, 'force', {} ); + } + } + + $dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user); + $dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid); + + # if we're using account codes on this site, mark the code as used + if ($code) { + my ($acid, $auth) = LJ::acct_code_decode($code); + $dbh->do("UPDATE acctcode SET rcptid=$userid WHERE acid=$acid"); + if ($dbh->err) { return $dbh->errstr; } + } + + # if we have initial friends for new accounts, add them. + foreach my $friend (@LJ::INITIAL_FRIENDS) { + my $friendid = LJ::get_userid($friend); + LJ::add_friend($userid, $friendid) if $friendid; + } + foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) { + my $friendid = LJ::get_userid($friend); + LJ::add_friend($userid, $friendid) if $friendid and $POST{"initial_optional_friend_$friend"}; + } + + # Set any properties that get set in new users + while (my ($name, $val) = each %LJ::USERPROP_INIT) { + LJ::set_userprop($userid, $name, $val); + } + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + 'code' => $code, + }); + } + + # send welcome mail... unless they're underage + unless ($is_underage) { + my $aa = {}; + if ($userid) { + $aa = LJ::register_authaction($userid, "validateemail", $email); + } + + my $body = BML::ml('email.newacct2.body', { + "email" => $email, + "regurl" => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}", + "username" => $user, + "sitename" => $LJ::SITENAME, + "siteroot" => $LJ::SITEROOT, + "admin_email" => $LJ::ADMIN_EMAIL, + "bogus_email" => $LJ::BOGUS_EMAIL, + }); + + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => BML::ml('email.newacct.subject', {'sitename' => $LJ::SITENAME}), + 'body' => $body, + }); + } + + my $nu = LJ::load_userid($userid, "force"); + + # now flag as underage (and set O to mean was old or Y to mean was young) + $nu->underage(1, $ofage ? 'O' : 'Y', 'account creation') if $is_underage; + + if ($LJ::TOS_CHECK) { + my $err = ""; + $nu->tosagree_set(\$err) + or return LJ::bad_input($err); + } + + # record create information + $nu->log_event('account_create', { remote => $remote }); + + $nu->make_login_session; + + # local sites may want to override what happens at this point + my $redirect = undef; + my $stop_output; + LJ::run_hooks("create.bml_postsession", { + post => \%POST, + u => $nu, + redirect => \$redirect, + ret => \$ret, + stop_output => \$stop_output, + }); + return BML::redirect($redirect) if $redirect; + return $ret if $stop_output; + + $ret = " $email, 'username' => $user}) ." p?>"; + my $uri = LJ::journal_base($nu); + $ret .= "\n"; + $ret .= "$uri/
    standout?>\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= "

    " . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "

    "; + $ret .= "
    \n"; + + return $ret; + + } + + if ($mode eq "getinfo" || %errors) + { + my $ret; + my $v; + + if (%errors) { + my @errors_order = ('code', 'username', 'email', 'password', 'agree_tos', 'captcha'); + my %errors_def; + $errors_def{$_} = 1 for @errors_order; + foreach my $key (keys %errors) { push @errors_order, $key unless $errors_def{$key}; } + $ret .= "$ML{'.errors.label'}
    • "; + $ret .= join ("
    • ", grep { $_ } map { $errors{$_} } @errors_order); + $ret .= "
    standout?>"; + } + + $ret .= "" unless %errors; + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'submit', + code => $code, + ssl => $FORM{'ssl'}); + + $ret .= "
      "; + + ### username + $v = LJ::ehtml($FORM{'user'}); + $ret .= "
    1. $ML{'.username.box.head'}
      "; + $ret .= $error_msg->('username', '

      ', '

      '); + $ret .= "
      " . BML::ml(".username.text", {'sitename' => $LJ::SITENAME}) . "
      "; + $ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style=""' }); + $ret .= "
      " . BML::ml('.community', { aopts => "href='$LJ::SITEROOT/community/create.bml'" }); + $ret .= "
      $ML{'.username.charsallowed'}
      " if (!%errors || exists $errors{'username'}); + $ret .= "
    2. "; + + ### email address + $v = LJ::ehtml($FORM{'email'}); + $ret .= "
    3. $ML{'.email.input.head'}
      "; + $ret .= $error_msg->('email', '

      ', '

      '); + $ret .= "
      " . BML::ml('.email.text3', { + aopts => "target='_new' href='$LJ::SITEROOT/privacy.bml'", + }) . "
      "; + $ret .= LJ::html_text({'name' => 'email', 'size' => 40, 'maxlength' => 50, 'value' => $v,}); + $ret .= "
    4. "; + + $ret .= "
    5. $ML{'.password.input.head1'}
      "; + $ret .= $error_msg->('password', '

      ', '

      '); + $ret .= "
      $ML{'.password.secure'}
      " if exists $errors{'password'}; + $ret .= "
      $ML{'.password.text'}
      "; + my $pass_value = $errors{'password'} ? "" : $POST{'password1'}; + $ret .= LJ::html_text({'name' => 'password1', 'size' => 30, 'maxlength' => 31, 'type' => "password", + value => $pass_value, }); + $ret .= "
      $ML{'.password.input.head2'}
      "; + $ret .= LJ::html_text({'name' => 'password2', 'size' => 30, 'maxlength' => 31, 'type' => "password", + value => $pass_value, }); + $ret .= "
    6. "; + + if (@LJ::INITIAL_OPTIONAL_FRIENDS) { + $ret .= "
    7. $ML{'.initialfriends.heading'}
      "; + $ret .= "
      $ML{'.initialfriends'}
      "; + $ret .= "
      "; + foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) { + $ret .= LJ::html_check({'name' => "initial_optional_friend_$friend", + 'value' => 1, + 'selected' => $POST{"initial_optional_friend_$friend"}, + 'id' => "optfriend_$friend", + }); + $ret .= "
      "; + } + $ret .= "
    8. "; + } + + if ($LJ::COPPA_CHECK) + { + $ret .= "
    9. $ML{'.birthday.head'}
      "; + $ret .= "
      $errors{'bday'}
      " if exists $errors{'bday'}; + $ret .= "
      $ML{'.birthday.question'}
      "; + $ret .= ""; + $ret .= "
      $ML{'.birthday.birthdate'}"; + $ret .= LJ::html_datetime({ name => 'bday', notime => 1, + default => sprintf("%04d-%02d-%02d", $POST{bday_yyyy}, $POST{bday_mm}, $POST{bday_dd}) }); + $ret .= "$ML{'.birthday.required'}
    10. "; + } + + LJ::run_hooks("create.bml_opts", { + post => \%POST, + get => \%GET, + ret => \$ret, + }); + + if ($LJ::TOS_CHECK) + { + $ret .= "
    11. $ML{'.tos.heading'}
      "; + $ret .= LJ::tosagree_widget($POST{agree_tos}, $errors->{agree_tos}); + $ret .= "
    12. "; + } + + if ($LJ::ALLOW_CLUSTER_SELECT) { + $ret .= "
    13. $ML{'.clusterselect.head'}
      "; + $ret .= "
      $ML{'.clusterselect.text'}
      "; + $ret .= LJ::html_select({ 'name' => 'cluster_id' }, + "0", "$BML{'.clusterselect.nocluster'}", + map { $_, BML::ml(".clusterselect.clusternum", {'number' => $_}) } @LJ::CLUSTERS); + + $ret .= "
      $ML{'.clusterselect.cluster'}
      "; + $ret .= "
    14. "; + } + + if ($LJ::HUMAN_CHECK{create}) { + $ret .= "
    15. $ML{'.captcha.prove'}
      "; + $ret .= $recaptcha->get_html($LJ::recaptcha_public_key); + } + + $ret .= "
    "; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + $ret .= "
    "; + + return $ret; + } + + return "$ML{'error.unknownmode'}: $mode"; + +_code?> +<=body +page?> +link: htdocs/privacy.bml +post: htdocs/create.bml, htdocs/editinfo.bml +file: htdocs/inc/account-codes +hook: post_create + _c?> diff --git a/local/htdocs/customize/advanced/layerbrowse.bml b/local/htdocs/customize/advanced/layerbrowse.bml new file mode 100755 index 0000000..42591af --- /dev/null +++ b/local/htdocs/customize/advanced/layerbrowse.bml @@ -0,0 +1,308 @@ + './', + 'text' => 'Advanced Customization', + }); + + my $err = sub { + $title = "Error"; + $body = shift; + return; + }; + + my $pub = LJ::S2::get_public_layers(); + + my $id; + if ($GET{'id'} =~ /^\d+$/) { # numeric + $id = $GET{'id'}; + } elsif ($GET{'id'}) { # redist_uniq + $id = $pub->{$GET{'id'}}->{'s2lid'}; + } + + my $dbr = LJ::get_db_reader(); + my $remote = LJ::get_remote(); + + # show the public layers + unless ($id) { + $title = "Public Layers"; + my %layerinfo; + my @to_load = grep { /^\d+$/ } keys %$pub; + LJ::S2::load_layer_info(\%layerinfo, \@to_load); + + my $recurse = sub { + my $self = shift; + my $lid = shift; # layer id + my $lay = $pub->{$lid}; + return unless $lay; + + # set to true if the layer is not core and is not a layout + my $is_child = $lay->{'type'} ne 'core' && $lay->{'type'} ne 'layout'; + + my $typedes = " ($lay->{'type'}" . (! $is_child ? ": $lid" : '') . ")"; + + # show link to detailed view + $body .= "
  • " . LJ::ehtml($layerinfo{$lid}->{'name'}); + $body .= "$typedes
  • "; + + # done unless there are children to recurse through + return unless ! $is_child && $lay->{'children'}; + + # if we're not expanding these children, stop and show a link + if ($lay->{'type'} eq 'layout' && $GET{'expand'} != $lid) { + $body .= ""; + return; + } + + # expand children + $body .= "
      "; + foreach (@{$lay->{'children'}}) { + $self->($self, $_); + } + $body .= "
    "; + + return; + }; + + # iterate through core layers + $body .= "
      "; + foreach (grep { $pub->{$_}->{'b2lid'} == 0 } grep { /^\d+$/ } keys %$pub) { + $recurse->($recurse, $_); # start from the top + } + $body .= "
    "; + + return; + } + + ### details on a specific layer ### + + my $xlink = sub { + my $r = shift; + $$r =~ s/\[class\[(\w+)\]\]/$1<\/a>/g; + $$r =~ s/\[method\[(.+?)\]\]/$1<\/a>/g; + $$r =~ s/\[function\[(.+?)\]\]/$1<\/a>/g; + $$r =~ s/\[member\[(.+?)\]\]/$1<\/a>/g; + }; + + # load layer info + my $layer = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id); + return $err->("The specified layer does not exist.") + unless $layer; + + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ? + $layerinfo->{$id}->{'source_viewable'} : undef; + + # do they have access? + my $isadmin = !defined $pub->{$id} && # public styles are pulled from the system + (LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges + LJ::check_priv($remote, 'canview', '*')); # in case they're private styles + return $err->("You are not authorized to view this layer.") + unless defined $pub->{$id} || $srcview == 1 || + LJ::can_manage($remote, $layer->{'userid'}) || + $isadmin; + + LJ::S2::load_layers($id); + my $s2info = S2::get_layer_all($id); + my $class = $s2info->{'class'} || {}; + + my $xlink_args = sub { + my $r = shift; + return unless + $$r =~ /^(.+?\()(.*)\)$/; + my ($new, @args) = ($1, split(/\s*\,\s*/, $2)); + foreach (@args) { + s/^(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + } + $new .= join(", ", @args) . ")"; + $$r = $new; + $xlink->($r); + }; + + $body .= "
    "; + # link to layer list if this is a public layer, otherwise user's layer list + if (defined $pub->{$id}) { + $body .= BML::ml('Backlink', { 'link' => 'layerbrowse.bml', 'text' => 'Public Layers' }) . "\n"; + } else { + $body .= BML::ml('Backlink', { 'link' => "layers.bml", 'text' => 'Your Layers' }) . "\n"; + $body .= BML::ml('Actionlink', { 'link' => "
    Edit Layer" }) . "\n"; + } + + if ($layer->{'b2lid'}) { + $body .= "[{'b2lid'}\">Parent Layer]\n"; + } + if (defined $pub->{$id} && (! defined $srcview || $srcview != 0) || + $srcview == 1 || + LJ::can_manage($remote, $layer->{'userid'}) || + $isadmin) { + + $body .= "[Download]\n"; + $body .= "[View as HTML]\n"; + } + + # layerinfo + if (my $info = $s2info->{'info'}) { + $body .= ""; + $body .= ""; + foreach my $k (sort keys %$info) { + my ($ek, $ev) = map { LJ::ehtml($_) } ($k, $info->{$k}); + $title = $ev if $k eq "name"; + $body .= "\n"; + } + $body .= "
    $ek$ev
    "; + } + + # sets + if (my $set = $s2info->{'set'}) { + $body .= ""; + $body .= ""; + foreach my $k (sort keys %$set) { + my $v = $set->{$k}; + if (ref $v eq "HASH") { + if ($v->{'_type'} eq "Color") { + $v = "{'as_string'}\"> $v->{'as_string'}"; + } else { + $v = "[unknown object type]"; + } + } elsif (ref $v eq "ARRAY") { + $v = "List: (" . join(", ", map { LJ::ehtml($_) } @$v) . ")"; + } else { + $v = LJ::ehtml($v); + } + $body .= "\n"; + } + $body .= "
    $k$v
    "; + } + + # global functions + my $gb = $s2info->{'global'}; + if (ref $gb eq "HASH" && %$gb) { + $body .= ""; + $body .= ""; + foreach my $fname (sort keys %$gb) { + my $rt = $gb->{$fname}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = LJ::ehtml($gb->{$fname}->{'docstring'}); + $xlink->(\$ds); + + my $args = $gb->{$fname}->{'args'}; + $xlink_args->(\$args); + + $body .= ""; + } + $body .= "
    $args : $rt$ds
    "; + } + + + if (%$class) + { + # class index + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "
    Alphabetical"; + $body .= "
      "; + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + $body .= "
    • $cname
    • \n"; + } + $body .= "
    "; + $body .= "
    Hierarchical"; + my $dumpsub = sub { + my $self = shift; + my $parent = shift; + $body .= "
  • $parent
  • \n" + if $parent; + my $didul = 0; + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + next unless $class->{$cname}->{'parent'} eq $parent; + unless ($didul++) { $body .= "
      "; } + $self->($self, $cname); + } + if ($didul) { $body .= "
    "; } + }; + $dumpsub->($dumpsub, ""); + $body .= "
    "; + + # classes + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + $body .= ""; + my $ds = LJ::ehtml($class->{$cname}->{'docstring'}); + if ($class->{$cname}->{'parent'}) { + $ds = "Child class of [class[$class->{$cname}->{'parent'}]]. $ds"; + } + if ($ds) { + $xlink->(\$ds); + $body .= ""; + } + + # build functions & methods + my (%func, %var); + my $add = sub { + my ($self, $aname) = @_; + foreach (keys %{$class->{$aname}->{'funcs'}}) { + $func{$_} = $class->{$aname}->{'funcs'}->{$_}; + $func{$_}->{'_declclass'} = $aname; + } + foreach (keys %{$class->{$aname}->{'vars'}}) { + $var{$_} = $class->{$aname}->{'vars'}->{$_}; + $var{$_}->{'_declclass'} = $aname; + } + + my $parent = $class->{$aname}->{'parent'}; + $self->($self, $parent) if $parent; + }; + $add->($add, $cname); + + $body .= "" if %var; + foreach (sort keys %var) { + my $type = $var{$_}->{'type'}; + $type =~ s/(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + $xlink->(\$type); + + my $ds = LJ::ehtml($var{$_}->{'docstring'}); + $xlink->(\$ds); + + if ($var{$_}->{'readonly'}) { + $ds = "(Read-only) $ds"; + } + + $body .= ""; + } + $body .= "
    $type $_$ds
    " if %var; + + $body .= "" if %func; + foreach (sort keys %func) { + my $rt = $func{$_}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = LJ::ehtml($func{$_}->{'docstring'}); + $xlink->(\$ds); + + my $args = $_; + $xlink_args->(\$args); + + $body .= ""; + } + $body .= "
    $args : $rt$ds
    " if %func; + } + } + + return; +} +_code?> +body=> +page?> + diff --git a/local/htdocs/customize/advanced/layeredit.bml b/local/htdocs/customize/advanced/layeredit.bml new file mode 100755 index 0000000..28139ed --- /dev/null +++ b/local/htdocs/customize/advanced/layeredit.bml @@ -0,0 +1,139 @@ + +Error\n

    Error

    " . shift; + }; + + # we need a valid id + my $id = $GET{'id'} if $GET{'id'} =~ /^\d+$/; + return $err->("You have not specified a layer to edit.") + unless $id; + + # authenticate user; + my $remote = LJ::get_remote(); + return $err->("You must be logged in to edit layers.") + unless $remote; + + # load layer + my $lay = LJ::S2::load_layer($id); + return $err->("The specified layer does not exist.") + unless $lay; + + # if the b2lid of this layer has been remapped to a new layerid + # then update the b2lid mapping for this layer + my $b2lid = $lay->{b2lid}; + if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) { + LJ::S2::b2lid_remap($remote, $id, $b2lid); + $lay->{b2lid} = $LJ::S2LID_REMAP{$b2lid}; + } + + # is authorized admin for this layer? + return $err->('You are not authorized to edit this layer.') + unless LJ::can_manage($remote, $lay->{'userid'}); + + # get u of user they are acting as + my $u = $lay->{'userid'} == $remote->{'userid'} ? $remote : LJ::load_userid($lay->{'userid'}); + + # check priv and ownership + return $err->("You are not authorized to edit styles.") + unless LJ::get_cap($u, "s2styles"); + + # at this point, they are authorized, allow viewing & editing + my $ret; + $ret .= "
    \n"; + $ret .= BML::ml('Backlink', { 'text' => 'Your Layers', 'link' => "layers.bml?authas=$u->{'user'}" }) . "\n"; + + # get s2 code from db - use writer so we know it's up-to-date + my $dbh = LJ::get_db_writer(); + my $s2code = $POST{'s2code'}; + $s2code = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", + undef, $lay->{'s2lid'}) unless $s2code; + + # we tried to compile something + if ($POST{'action'} eq "compile") { + $ret .= "
    \n"; + $ret .= "S2 Compiler Output at " . scalar(localtime) . "
    \n"; + + my $error; + $POST{'s2code'} =~ s/\r//g; # just in case + unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$POST{'s2code'} })) { + + $error =~ s/LJ::S2,.+//s; + $error =~ s!, .+?(src/s2|cgi-bin)/!, !g; + + $ret .= "Error compiling layer:\n
    $error
    "; + + # display error with helpful context + if ($error =~ /^compile error: line (\d+)/i) { + my $errline = $1; + my $kill = $errline - 5 < 0 ? 0 : $errline - 5; + my $prehilite = $errline - 1 > 4 ? 4: $errline - 1; + my $snippet = $s2code; + + # make sure there's a newlilne at the end + chomp $snippet; + $snippet .= "\n"; + + # and now, fun with regular expressions + my $ct = 0; + $snippet =~ s!(.*?)\n!sprintf("%3d", ++$ct) . ": " . + $1 . "\n"!ge; # add line breaks and numbering + $snippet = LJ::ehtml($snippet); + $snippet =~ s!^((?:.*?\n){$kill,$kill}) # kill before relevant lines + ((?:.*?\n){$prehilite,$prehilite}) # capture context before error + (.*?\n){0,1} # capture error + ((?:.*?\n){0,4}) # capture context after error + .* # kill after relevant lines + !$2$3$4!sx; + + $ret .= "Context
    $snippet
    \n"; + } + + } else { + $ret .= "No errors\n"; + } + $ret .= "
    \n\n"; + } + + $ret .= LJ::html_hidden("action", "compile") . "\n"; + $ret .= "

    " . LJ::html_submit('submit', 'Compile', { + 'style' => 'float: right; margin-bottom: 2px', + 'accesskey' => 'c', + 'title' => 'alt-C: compile', + } ) . "\n"; + $ret .= "Edit layer source\n"; + $ret .= LJ::html_textarea({ 'name' => 's2code', 'class' => 's2code', 'wrap' => 'off', + 'cols' => '50', 'rows' => '40', 'value' => $s2code }) . "\n"; + $ret .= LJ::html_submit('submit', 'Compile') . "\n"; + $ret .= "

    \n"; + + # load layer info + my $layinf = {}; + LJ::S2::load_layer_info($layinf, [ $id ]); + + # find a title to display on this page + my $type = $layinf->{$id}->{'type'}; + my $name = $layinf->{$id}->{'name'}; + + # find name of parent layer if this is a child layer + if (! $name && $type =~ /^(user|theme|i18n)$/) { + my $par = $lay->{'b2lid'} + 0; + LJ::S2::load_layer_info($layinf, [$par]); + $name = $layinf->{$par}->{'name'}; + } + + # Only use the layer name if there is one and it's more than just whitespace + my $title = "[$type] "; + $title .= $name && $name =~ /[^\s]/ ? "$name [\#$id]" : "Layer \#$id"; + + return "" . LJ::ehtml($title) . " - Edit\n" . $ret; +} +_code?> diff --git a/local/htdocs/customize/advanced/layers.bml b/local/htdocs/customize/advanced/layers.bml new file mode 100755 index 0000000..905a255 --- /dev/null +++ b/local/htdocs/customize/advanced/layers.bml @@ -0,0 +1,260 @@ +\n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "\n\n"; + }; + + # used for error messages + my $err = sub { + $title = "Error"; + $body = ''; + $authasform->() if $remote; + $body .= ""; + return; + }; + + # id is optional + my $id = $POST{'id'} if $POST{'id'} =~ /^\d+$/; + + # this catches core_hidden if it's set + $POST{'parid'} ||= $POST{'parid_hidden'}; + + # authenticate user + $remote = LJ::get_remote(); + return $err->('You must be logged in to view your layers.') + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + + # if we don't have a u, maybe they're an admin and can view stuff anyway? + my $noactions = 0; + if ($GET{user} && (LJ::check_priv($remote, 'canview', 'styles') || + LJ::check_priv($remote, 'canview', '*'))) { + return $err->('This privilege cannot be used on the system account.') + if $GET{user} eq 'system'; + $u = LJ::load_user($GET{user}); + $noactions = 1; # don't let admins change anything + } + return $err->('You could not be authenticated as the specified user.') + unless $u; + + # load user and public layers + my $pub = LJ::S2::get_public_layers(); + my $ulay = LJ::S2::get_layers_of_user($u); + + my $has_priv = LJ::get_cap($u, 's2styles'); + return $err->($remote->{user} eq $u->{user} ? + 'Your account type does not allow advanced customization.' : + 'The selected user\'s account type does not allow advanced customization.' ) + unless $has_priv; + + # start of output + $title = "Your Layers"; + $body .= BML::ml("Backlink", { + 'link' => './', + 'text' => 'Advanced Customization', + }) . "\n"; + $body .= BML::ml("Actionlink", { + 'link' => "Your Styles", + }) . "\n"; + + + ### perform actions ### + + # create + if ($POST{'action:create'} && !$noactions) { + return $err->("You have reached your maximum number of allowed layers") + if keys %$ulay >= LJ::get_cap($u, 's2layersmax'); + + my $err_badparid = "No/bogus parent layer ID given (for layouts and core languages, use core parent ID; for themes and layout languages, use layout ID)"; + my $type = $POST{'type'} or return $err->("No layer type selected."); + my $parid = $POST{'parid'}+0 or return $err->($err_badparid); + return $err->("Invalid layer type") unless $type =~ /^layout|theme|user|i18nc?$/; + my $parent_type = ($type eq "theme" || $type eq "i18n" || $type eq "user") ? "layout" : "core"; + + # parent ID is public layer + if ($pub->{$parid}) { + # of the wrong type + return $err->($err_badparid) if $pub->{$parid}->{'type'} ne $parent_type; + + # parent ID is user layer, or completely invalid + } else { + return $err->($err_badparid) if + ! $ulay->{$parid} || $ulay->{$parid}->{'type'} != $parent_type; + } + + my $id = LJ::S2::create_layer($u, $parid, $type); + return $err->("Error creating layer") unless $id; + + my $lay = { + 'userid' => $u->{'userid'}, + 'type' => $type, + 'b2lid' => $parid, + 's2lid' => $id, + }; + + # help user out a bit, creating the beginning of their layer. + my $s2 = "layerinfo \"type\" = \"$type\";\n"; + $s2 .= "layerinfo \"name\" = \"\";\n\n"; + my $error; + unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$s2 })) { + return $err->("Error setting up & compiling layer: $error"); + } + + # redirect so they can't refresh and create a new layer again + return BML::redirect("layers.bml?authas=$authas"); + } + + # delete + if ($POST{'action:del'} && !$noactions) { + my $id = $POST{'id'}+0; + my $lay = LJ::S2::load_layer($id); + return $err->("The specified layer does not exist") + unless $lay; + + return $err->("You do not own the specified layer") + unless $lay->{'userid'} == $u->{'userid'}; + + unless ($POST{'confirm'}) { + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $name = $layerinfo->{$id}->{'name'} ? "'$layerinfo->{$id}->{'name'}'" : "#$id"; + $name = LJ::ehtml($name); + + $title = "Deleting layer $name"; + $body .= "
    "; + $body .= BML::ml("Backlink", { + 'link' => "layers.bml?authas=$authas", + 'text' => 'Your Layers', + }) . "\n"; + $body .= "
    "; + $body .= LJ::html_hidden('action:del', '1', 'id', $id); + + $body .= "Are you sure you want to delete $lay->{'type'} layer $name?"; + $body .= "

    " . LJ::html_submit('confirm', 'Delete') . "

    \n";; + $body .= "
    \n"; + return; + } + + LJ::S2::delete_layer($u, $id); + return BML::redirect("layers.bml?authas=$authas"); + } + + # authas switcher form + unless ($noactions) { + $authasform->(); + } + + # show list of layers + $body .= "\n"; + if (%$ulay) { + $body .= "\n"; + $body .= "\n"; + my $lastbase = 0; + foreach my $lid (sort { $ulay->{$a}->{'b2lid'} <=> $ulay->{$b}->{'b2lid'} || $a <=> $b } + keys %$ulay) + { + my $bid = $ulay->{$lid}->{'b2lid'}; + if ($bid != $lastbase) { + $lastbase = $bid; + my $parlay = $ulay->{$bid} || $pub->{$bid}; + my $pname = LJ::ehtml($parlay->{'name'}); + $body .= "\n"; + } + my $lay = $ulay->{$lid}; + my $name = LJ::ehtml($lay->{'name'}) || "(none)"; + $body .= "\n" + } + $body .= "
    LayerIDTypeNameActions
    Child of layer $bid: $pname
    $lid$lay->{'type'}$name"; + $body .= "
    "; + $body .= LJ::html_submit('action:edit', 'Edit...', { disabled => $noactions }); + $body .= "
    "; + + $body .= "
    "; + $body .= LJ::html_hidden('id', $lid); + $body .= LJ::html_submit('action:del', 'Delete...', { disabled => $noactions }); + $body .= "
    "; + $body .= "
    \n\n"; + } else { + $body .= "None p?>\n\n"; + } + + # jump out if we're just viewing + return if $noactions; + + # create layer + $body .= "\n"; + + $body .= "
    \n"; + $body .= "\n"; + $body .= "
    \n"; + + $body .= "Type: " . LJ::html_select({ 'name' => 'type' }, + "" => "", + "layout" => "Layout", + "i18nc" => "Language", + ) . "\n"; + + my @corelayers = map { $_, $pub->{$_}->{'majorversion'} } + sort { $pub->{$b}->{'majorversion'} <=> $pub->{$a}->{'majorversion'} } + grep { $pub->{$_}->{'b2lid'} == 0 && $pub->{$_}->{'type'} eq 'core' && /^\d+$/} + keys %$pub; + $body .= " Core Version: " . LJ::html_select({ 'name' => 'parid', + 'selected' => $corelayers[0], + 'disabled' => @corelayers > 2 ? 0: 1 }, + @corelayers ) . "\n"; + + # store value in hidden to later be copied to 'parid' if necessary + # defaults to $corelayers[0] which should be the highest numbered core + $body .= LJ::html_hidden("parid_hidden", $POST{'parid'} || $corelayers[0]) . "\n"; + $body .= LJ::html_submit("action:create", "Create") . "\n"; + $body .= "
    \n"; + $body .= "
    \n\n"; + + $body .= "\n"; + $body .= "
    \n"; + + $body .= "Type: " . LJ::html_select({ 'name' => 'type' }, + "" => "", + "theme" => "Theme", + "i18n" => "Language", + "user" => "User" + ) . "\n"; + + my @layouts = ('', ''); + push @layouts, map { $_, $pub->{$_}->{'name'} } + sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} || $a <=> $b} + grep { $pub->{$_}->{'type'} eq 'layout' && /^\d+$/} + keys %$pub; + if (%$ulay) { + my @ulayouts = (); + push @ulayouts, map { $_, "$ulay->{$_}->{'name'} (#$_)" } + sort { $ulay->{$a}->{'name'} cmp $ulay->{$b}->{'name'} || $a <=> $b} + grep { $ulay->{$_}->{'type'} eq 'layout' } + keys %$ulay; + push @layouts, ('', '---', @ulayouts) if @ulayouts; + } + + $body .= "Layout: " . LJ::html_select({ 'name' => 'parid' }, @layouts) . "\n"; + + $body .= LJ::html_submit("action:create", "Create") . "\n"; + $body .= "
    \n\n"; + + return; +} +_code?> +body=> +page?> + diff --git a/local/htdocs/customize/advanced/styles.bml b/local/htdocs/customize/advanced/styles.bml new file mode 100755 index 0000000..a65e30d --- /dev/null +++ b/local/htdocs/customize/advanced/styles.bml @@ -0,0 +1,465 @@ +\n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "\n\n"; + }; + + # used for error messages + my $err = sub { + $title = "Error"; + $body = ''; + $authasform->() if $remote; + $body .= ""; + return; + }; + + # authenticate user + $remote = LJ::get_remote(); + return $err->('You must be logged in to view your styles.') + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->('You could not be authenticated as the specified user.') + unless $u; + + return $err->($remote->{user} eq $u->{user} ? + 'Your account type does not allow advanced customization.' : + 'The selected user\'s account type does not allow advanced customization.' ) + unless LJ::get_cap($u, 's2styles'); + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + my $getextra_amp = "&authas=$authas" if $getextra; + + # style id to edit, if we have one + # if we have this we're assumed to be in 'edit' mode + my $id = $GET{'id'}+0; + + my $dbh = LJ::get_db_writer(); + + # variables declared here, but only filled in if $id + my ($core, $layout); # scalars + my ($pub, $ulay, $style); # hashrefs + + # start of output + $title = "Styles"; + $body = BML::ml("Backlink", { + 'link' => './', + 'text' => 'Advanced Customization', + }) . "\n"; + $body .= BML::ml("Actionlink", { + 'link' => "Your Layers", + }) . "\n"; + + # edit mode + if ($id) { + + # load style + $style = LJ::S2::load_style($id); + return $err->('Style not found') unless $style; + + # check that they own the style + return $err->("You do not own this style.") + unless $style->{'userid'} == $u->{'userid'}; + + # use selected style + if ($POST{'action:usestyle'}) { + + # save to db and update user object + LJ::set_userprop($u, "stylesys", '2'); + LJ::set_userprop($u, "s2_style", $id); + return BML::redirect("styles.bml$getextra"); + } + + # get public layers + $pub = LJ::S2::get_public_layers(); + + # get user layers + $ulay = LJ::S2::get_layers_of_user($u); + + # find effective layerids being used + my %eff_layer = (); + my @other_layers = (); + foreach (qw(i18nc layout theme i18n user)) { + my $lid = $POST{$_} eq "_other" ? $POST{"other_$_"} : $POST{$_}; + next unless $lid; + $eff_layer{$_} = $lid; + + unless ($ulay->{$eff_layer{$_}} || $pub->{$eff_layer{$_}}) { + push @other_layers, $lid; + } + } + + # core lid (can't use user core layer) + $POST{'core'} ||= $POST{'core_hidden'}; + $core = defined $POST{'core'} ? $POST{'core'} : $style->{'layer'}->{'core'}; + unless ($core) { # default to highest numbered core + map { $core = $_ if $pub->{$_}->{'type'} eq 'core' && /^\d+$/ && + $pub->{$_}->{'majorversion'} > $pub->{$core}->{'majorversion'} } keys %$pub; + + # update in POST to keep things in sync + $POST{'core'} = $core; + } + + # layout lid + $layout = $POST{'action:change'} ? $eff_layer{'layout'} : $style->{'layer'}->{'layout'}; + + # if we're changing core, clear everything + if ($POST{'core'} && $style->{'layer'}->{'core'} && + $POST{'core'} != $style->{'layer'}->{'core'}) { + foreach (qw(i18nc layout theme i18n user)) { + delete $eff_layer{$_}; + } + undef $layout; + } + + # if we're changing layout, clear everything below + if ($eff_layer{'layout'} && $style->{'layer'}->{'layout'} && + $eff_layer{'layout'} != $style->{'layer'}->{'layout'}) { + foreach (qw(theme i18n user)) { + delete $eff_layer{$_}; + } + } + + # set up start of output + $title = "Edit Style"; + $body .= "
    " . BML::ml('Backlink', { 'text' => 'Your Styles', 'link' => "styles.bml$getextra" }) . "\n"; + + ### process edit actions + + # delete + if ($POST{'action:delete'}) { + LJ::S2::delete_user_style($u, $id); + undef $id; # don't show form below + return BML::redirect("styles.bml$getextra"); + } + + # save changes + if ($POST{'action:change'} || $POST{'action:savechanges'}) { + + # are they renaming their style? + if ($POST{'stylename'} && $style->{'name'} && + $POST{'stylename'} ne $style->{'name'}) { + + # update db + my $styleid = $style->{'styleid'}; + $dbh->do("UPDATE s2styles SET name=? WHERE styleid=? AND userid=?", + undef, $POST{'stylename'}, $styleid, $u->{'userid'}); + LJ::MemCache::delete([$styleid, "s2s:$styleid"]); + + # update style object + $style->{'name'} = $POST{'stylename'}; + } + + # load layer info of any "other" layers + my %other_info = (); + if (@other_layers) { + LJ::S2::load_layer_info(\%other_info, \@other_layers); + foreach (@other_layers) { + return $err->("Layer not found: $_") unless exists $other_info{$_}; + return $err->("Layer not public: $_") unless $other_info{$_}->{'is_public'}; + } + } + + # error check layer modifications + my $get_layername = sub { + my $lid = shift; + + my $name; + $name = $pub->{$lid}->{'name'} if $pub->{$lid}; + $name ||= $ulay->{$lid}->{'name'} if $ulay->{$lid}; + $name ||= "#$lid"; + + return $name; + }; + + # check layer hierarchy + my $error_check = sub { + my ($type, $parentid) = @_; + + my $lid = $eff_layer{$type}; + next if ! $lid; + + my $layer = $ulay->{$lid} || $pub->{$lid} || LJ::S2::load_layer($lid); + my $parentname = $get_layername->($parentid); + my $layername = $get_layername->($lid); + + # is valid layer type? + return "Invalid layer type: $layername is not a $type layer" + if $layer->{'type'} ne $type; + + # is a child? + return "Layer hierarchy mismatch: $layername is not a child $type layer of $parentname" + unless $layer->{'b2lid'} == $parentid; + + return undef; + }; + + # check child layers of core + foreach my $type (qw(i18nc layout)) { + my $errmsg = $error_check->($type, $core); + return $err->($errmsg) if $errmsg; + } + + # don't check sub-layout layers if there's no layout + if ($layout) { + + # check child layers of selected layout + foreach my $type (qw(theme i18n user)) { + my $errmsg = $error_check->($type, $layout); + return $err->($errmsg) if $errmsg; + } + } + + # save in database + my @layers = ( 'core' => $core ); + push @layers, map { $_, $eff_layer{$_} } qw(i18nc layout i18n theme user); + LJ::S2::set_style_layers($u, $style->{'styleid'}, @layers); + + # redirect if they clicked the bottom button + return BML::redirect("styles.bml$getextra") if $POST{'action:savechanges'}; + } + + # no style id, process actions for non-edit mode + # and load in data necessary for style list + } else { + + # load user styles + my $ustyle = LJ::S2::load_user_styles($u); + + # process create action + if ($POST{'action:create'} && $POST{'stylename'}) { + + return $err->('You have reached your maximum number of styles.') + if scalar(keys %$ustyle) >= LJ::get_cap($u, 's2stylesmax'); + + my $styleid = LJ::S2::create_style($u, $POST{'stylename'}); + return $err->('Style not created: Database error') unless $styleid; + + return BML::redirect("styles.bml?id=$styleid$getextra_amp"); + } + + # load style currently in use + LJ::load_user_props($u, 's2_style'); + + # set up page header + $title = "Your Styles"; + + $authasform->(); + + $body .= "
    \n"; + + # show style listing + $body .= "\n"; + if (%$ustyle) { + my $journalbase = LJ::journal_base($u); + foreach my $styleid (sort { $ustyle->{$a} cmp $ustyle->{$b} || $a <=> $b} keys %$ustyle) { + $body .= "\n"; + } + } else { + $body .= "\n"; + } + $body .= "
    "; + my @b = $styleid == $u->{'s2_style'} ? "" : ""; + $body .= $b[0] . LJ::ehtml($ustyle->{$styleid}); + $body .= " (\#$styleid)$b[1] "; + $body .= "
    "; + $body .= LJ::html_submit('action:edit', 'Edit') . " "; + $body .= LJ::html_submit('action:delete', 'Delete', + { 'onclick' => "return confirm('Are you sure you want to delete style \#$styleid?')" }) . " "; + $body .= LJ::html_submit('action:usestyle', 'Use', { 'disabled' => $styleid == $u->{'s2_style'} }), + $body .= "
    none
    \n"; + } + + + ### show create / edit form + + my $extra = $id ? "?id=$id" : ''; + $extra .= $extra ? $getextra_amp : $getextra; + $body .= "
    "; + + # create a new style, or change the name of the style currently being edited + # note: this little bit of code appears whether there is an id passed or not. + # the textbox just has a different purpose depending on the context. + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Name: "; + $body .= LJ::html_text({ 'name' => 'stylename', 'size' => '30', 'maxlength' => '255', + 'value' => defined $POST{'stylename'} ? $POST{'stylename'} : $style->{'name'} }); + $body .= " " . LJ::html_submit('action:create', 'Create') unless $id; + $body .= "
    \n"; + + # if no id to edit, we're finished + $body .= "
    \n", return unless $id; + + # from here on we have $pub, $ulay, and $style filled in + + # sub to take a layer type, core, and parent layout + # and return a list of options to feed to LJ::html_select() + my $layerselect = sub { + my ($type, $b2lid) = @_; + + my @opts = (); + + # returns html_select to caller + my $html_select = sub { + my $dis = scalar(@opts) > 2 ? 0 : 1; + + my $lid = $POST{'action:change'} ? $POST{$type} : $style->{'layer'}->{$type}; + $lid = $POST{"other_$type"} if $lid eq "_other"; + my $sel = ($lid && ! $pub->{$lid} && ! $ulay->{$lid}) ? "_other" : $lid; + return [ LJ::html_select({ 'name' => $type, 'id' => "select_$type", + 'onChange' => "showOther('$type')", + 'selected' => $sel, + 'disabled' => $dis }, @opts), { 'disabled' => $dis, } ]; + }; + + # greps, and sorts a list + my $greplist = sub { + my $ref = shift; + return sort { $ref->{$a}->{'name'} cmp $ref->{$b}->{'name'} || $a <=> $b} + grep { $ref->{$_}->{'type'} eq $type && $ref->{$_}->{'b2lid'} == $b2lid && /^\d+$/} + keys %$ref; + }; + + # public layers + my $name = $type eq 'core' ? 'majorversion' : 'name'; + push @opts, map { $_, $pub->{$_}->{$name} } $greplist->($pub); + + # no user core layers + return $html_select->() if $type eq 'core'; + + # user layers + push @opts, ('', '---'); + my $startsize = scalar(@opts); + push @opts, map { $_, "$ulay->{$_}->{'name'} (\#$_)" } $greplist->($ulay); + + # if we didn't push anything above, remove dividing line + pop @opts, pop @opts unless scalar(@opts) > $startsize; + + # add option for other layerids + push @opts, ('_other', 'Other ...'); + + # add blank option to beginning of list + unshift @opts, ('', @opts ? '' : ' '); + + return $html_select->(); + }; + + my $layerother = sub { + my $name = shift; + + my $olid = $POST{'action:change'} ? $POST{"other_$name"} : $style->{'layer'}->{$name}; + my $disp = 'none'; + my $val; + if ($olid && ! $pub->{$olid} && ! $ulay->{$olid}) { + $disp = 'inline'; + $val = $olid; + } + + return "
    Layerid: " . + LJ::html_text({ 'name' => "other_$name", 'id' => "other_$name", + 'size' => 6, 'value' => $val }) . + "
    "; + }; + + ### core version + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Core Version: "; + my $coresel = $layerselect->('core', 0); + $body .= $coresel->[0]; + $body .= LJ::html_hidden('core_hidden', $core); + my $dis = $coresel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef; + $body .= " " . LJ::html_submit('action:change', 'Change', $dis) . "
    \n"; + + ### i18nc / layout + + $body .= "\n"; + + # i18nc + $body .= "\n"; + + # layout + $body .= "\n"; + $body .= "
    Language (i18nc): "; + $body .= $layerselect->('i18nc', $core)->[0]; + $body .= $layerother->('i18nc'); + $body .= "
    Layout: "; + my $layoutsel = $layerselect->('layout', $core); + $body .= $layoutsel->[0]; + $body .= $layerother->('layout'); + my $dis = $layoutsel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef; + $body .= " " . LJ::html_submit("action:change", "Change", $dis) . "
    \n"; + + # do we need to show the rest of the form? + $body .= "\n", return unless $layout; + + ### theme / i18n / user + + # theme + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Language (i18n): "; + $body .= $layerselect->('i18n', $layout)->[0]; + $body .= $layerother->('i18n') . "
    Theme: "; + $body .= $layerselect->('theme', $layout)->[0]; + $body .= $layerother->('theme') . "
    User: "; + $body .= $layerselect->('user', $layout)->[0]; + $body .= $layerother->('user') . "
     "; + $body .= LJ::html_submit('action:savechanges', 'Save Changes') . "
    \n"; + + # end edit form + $body .= "\n"; + + return; +} +_code?> +head<= + +<=head +body=> +bodyopts=>onLoad="pageload();" +page?> + diff --git a/local/htdocs/delcomment.bml b/local/htdocs/delcomment.bml new file mode 100755 index 0000000..0016836 --- /dev/null +++ b/local/htdocs/delcomment.bml @@ -0,0 +1,165 @@ +1 +_info?>"; + return; + }; + my $bad_input = sub { + return $error->("Bad input: $_[0]") if $jsmode; + $body = LJ::bad_input($_[0]); + return; + }; + + LJ::set_active_crumb('delcomment'); + + my $remote = LJ::get_remote(); + return $bad_input->($ML{'error.noremote'}) + unless $remote; + + return $error->("Missing parameters.") unless $GET{'journal'} ne "" && $GET{'id'}; + + # $u is user object of journal that owns the talkpost + my $u = LJ::load_user($GET{'journal'}); + return $bad_input->($ML{'error.nojournal'}) + unless $u; + + # can't delete if you're suspended + return $bad_input->($ML{'.error.suspended'}) + if $remote->{statusvis} eq 'S'; + + return $error->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + return $error->($ML{'error.nodb'}) + unless $dbcr; + + # $tp is a hashref of info about this individual talkpost row + my $tpid = $GET{'id'} >> 8; + my $tp = $dbcr->selectrow_hashref("SELECT jtalkid AS 'talkid', nodetype, state, " . + "nodeid AS 'itemid', parenttalkid, journalid, posterid " . + "FROM talk2 ". + "WHERE journalid=? AND jtalkid=?", + undef, $u->{'userid'}, $tpid); + + return $bad_input->($ML{'.error.nocomment'}) + unless $tp; + + return $bad_input->($ML{'.error.invalidtype'}) + unless $tp->{'nodetype'} eq 'L'; + + return $bad_input->($ML{'.error.alreadydeleted'}) + if $tp->{'state'} eq "D"; + + # get username of poster + $tp->{'userpost'} = LJ::get_username($tp->{'posterid'}); + + # userid of user who posted journal entry + my $jposterid = $dbcr->selectrow_array("SELECT posterid FROM log2 WHERE " . + "journalid=? AND jitemid=?", + undef, $u->{'userid'}, $tp->{'itemid'}); + my $jposter = LJ::load_userid($jposterid); + + # can $remote delete this comment? + unless (LJ::Talk::can_delete($remote, $u, $jposter, $tp->{'userpost'})) { + my $err = $u->{'journaltype'} eq 'C' ? $ML{'.error.cantdelete.comm'} : $ML{'.error.cantdelete'}; + return $error->($err); + } + + my $can_manage = LJ::can_manage($remote, $u); + + # can ban if can manage and the comment is by someone else and not anon + my $can_ban = $can_manage && $tp->{'posterid'} + && $remote && $remote->{'userid'} != $tp->{'posterid'}; + my $can_delthread = $can_manage || $jposterid == $remote->{userid}; + + ### perform actions + if (LJ::did_post() && $POST{'confirm'}) { + # mark this as spam? + LJ::Talk::mark_comment_as_spam($u, $tp->{talkid}) + if $POST{spam}; + + # delete entire thread? or just the one comment? + if ($POST{delthread} && $can_delthread) { + # delete entire thread ... + LJ::Talk::delete_thread($u, $tp->{'itemid'}, $tpid); + } else { + # delete single comment... + LJ::Talk::delete_comments($u, "L", $tp->{'itemid'}, [$tpid]); + } + + # ban the user, if selected + my $msg; + if ($POST{'ban'} && $can_ban) { + LJ::set_rel($u->{'userid'}, $tp->{'posterid'}, 'B'); + $msg = BML::ml('.success.andban', { 'user' => LJ::ljuser($tp->{'userpost'}) }); + } + $msg ||= $ML{'.success.noban'}; + $msg .= "" if $POST{spam}; + + if ($jsmode) { + BML::finish(); + return "1;"; + } else { + $body = ""; + return; + } + } + + ### show confirmation form + + $body .= ""; + $body .= ""; + $body .= "
    \n"; + $body .= "" . LJ::html_submit('confirm', $ML{'.confirm.submit'}) . "\n"; + + if ($can_ban) { + $body .= "
    " . LJ::html_check({ 'type' => 'check', 'name' => 'ban', 'id' => 'ban' }); + $body .= "
    "; + } + + if ($tp->{'posterid'} != $remote->{'userid'}) { # Despite the idea of natural selection, don't let users report their own comments as spam + $body .= "
    " . LJ::html_check({name => 'spam', id => 'spam'}); + $body .= "
    "; + } + + if ($can_delthread) { + $body .= "
    " . LJ::html_check({name => 'delthread', id => 'delthread'}); + $body .= "
    "; + } + + $body .= " standout?>"; + + if ($can_manage) { + my $msg = BML::ml('.changeoptions', { 'link' => + "$ML{'/editinfo.bml.title'}" }); + $body .= ""; + } + + $body .= "
    \n"; + return; +} +_code?> +body=> +page?> +link: htdocs/editinfo.bml +post: htdocs/delcomment.bml + _c?> diff --git a/local/htdocs/developer/index.html b/local/htdocs/developer/index.html new file mode 100755 index 0000000..235f9f1 --- /dev/null +++ b/local/htdocs/developer/index.html @@ -0,0 +1,7 @@ +LJR Developer Area + + +

    Under construction.

    + +

    If you want to master a tool, you first have to master the use of +that tool. \ No newline at end of file diff --git a/local/htdocs/directory.bml b/local/htdocs/directory.bml new file mode 100755 index 0000000..0bbb1d2 --- /dev/null +++ b/local/htdocs/directory.bml @@ -0,0 +1,380 @@ +Search Results +body<= + + \%state, country => \%country }); + $ret = ""; + $ret .= "\n"; + $ret .= "

    "; + $ret .= "\n"; + + $ret .= "\n"; + + $ret .= "US Map

    \n"; + + $sth = $dbr->prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('country', 'stateus')"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $count{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'}; + } + + my @shapes = ( + "1,235,1,309,108,309,108,235,18,235,1,235", "AK", + "328,196,328,236,355,235,345,195,328,196,328,196", "AL", + "267,182,272,215,294,216,293,206,300,182,267,182,267,182", "AR", + "86,162,72,205,113,225,124,167,86,162,86,162", "AZ", + "14,86,6,110,22,166,54,198,69,189,29,123,38,90,14,86,14,86", "CA", + "137,122,133,160,191,169,191,128,137,122,137,122", "CO", + "444,91,443,99,456,92,456,88,444,91,444,91", "CT", + "445,158,460,158,460,168,445,158", "DC", + "428,122,433,134,436,132,430,121,428,122", "DE", + "450,126,464,135", "DE", + "335,240,335,244,371,242,391,259,410,293,414,279,390,238,335,240,335,240", "FL", + "352,194,366,234,388,233,389,216,364,192,352,194,352,194", "GA", + "119,269,185,312", "HI", + "248,101,254,126,289,126,286,97,248,101,248,101", "IA", + "86,24,73,90,114,99,118,76,100,72,86,24,86,24", "ID", + "302,111,293,135,313,162,321,147,316,111,302,111,302,111", "IL", + "326,119,328,154,344,143,343,114,326,119,326,119", "IN", + "199,140,196,167,257,170,254,141,199,140,199,140", "KS", + "325,172,324,161,341,160,348,148,366,149,367,164,325,172,325,172", "KY", + "274,224,277,255,307,254,307,244,290,244,291,221,274,224,274,224", "LA", + "471,79,488,88", "MA", + "442,82,442,89,458,84,464,89,466,87,457,79,442,82,442,82", "MA", + "465,142,483,153", "MD", + "397,128,426,122,432,135,437,136,431,142,419,138,420,128,411,128,409,126,397,129,397,128", "MD", + "462,27,457,52,461,64,476,38,469,25,462,27,462,27", "ME", + "309,56,361,61,359,107,331,110,309,56,309,56", "MI", + "243,36,250,92,277,92,268,65,283,46,243,36,243,36", "MN", + "260,134,267,173,308,173,283,133,260,134,260,134", "MO", + "322,196,321,240,299,237,301,204,322,196,322,196", "MS", + "96,22,111,64,176,73,180,33,96,22,96,22", "MT", + "388,171,374,181,415,186,423,166,388,171,388,171", "NC", + "189,33,186,59,240,63,236,36,189,33,189,33", "ND", + "184,104,182,119,200,121,200,134,248,135,237,108,184,104,184,104", "NE", + "453,51,459,74,449,79,450,61,452,60,452,51,453,51,453,51", "NH", + "435,27,452,36", "NH", + "432,102,431,109,436,114,431,121,437,125,441,111,437,111,438,103,432,102,432,102", "NJ", + "132,170,125,221,176,227,180,174,132,170,132,170", "NM", + "45,93,37,122,72,173,82,102,45,93,45,93", "NV", + "433,59,439,77,440,99,430,98,429,91,391,100,401,87,417,78,419,63,433,59", "NY", + "450,99,440,106,445,109,455,100,450,99", "NY", + "379,112,350,116,352,139,368,143,381,127,379,112,379,112", "OH", + "186,172,186,175,212,177,214,201,259,207,259,174,186,172,186,172", "OK", + "27,42,13,75,64,91,72,51,27,42,27,42", "OR", + "386,106,388,125,428,117,425,99,386,106,386,106", "PA", + "421,229,485,260", "PR", + "472,100,482,110", "RI", + "458,86,457,94,461,89,458,86", "RI", + "375,191,395,210,410,193,375,191,375,191", "SC", + "187,69,183,97,240,101,241,71,187,69,187,69", "SD", + "315,180,311,190,355,188,372,172,315,180,315,180", "TN", + "188,180,183,235,151,230,174,258,184,250,202,254,223,292,242,263,266,252,266,216,204,205,207,181,188,180,188,180", "TX", + "97,103,86,153,126,160,131,120,112,119,114,106,97,103,97,103", "UT", + "411,135,383,163,425,158,411,135,411,135", "VA", + "454,272,481,307", "VI", + "416,34,430,43", "VT", + "437,58,442,80,446,79,447,54,437,58,437,58", "VT", + "41,6,82,17,75,45,34,37,41,6,41,6", "WA", + "282,62,283,81,293,87,297,103,313,102,308,66,282,62,282,62", "WI", + "385,133,374,148,383,156,401,133,385,133,385,133", "WV", + "126,73,122,111,174,120,178,80,126,73,126,73", "WY", + ); + + while (my ($coords, $state) = splice(@shapes, 0, 2)) + { + next unless ($count{'stateus'}->{$state}); + my $shape = "poly"; + if ($coords =~ /^[^,]+,[^,]+,[^,]+,[^,]+$/) { $shape = "RECTANGLE"; } + $ret .= "$state{$state}+0); + $s = $count{'stateus'}->{$state} != 1 ? "s" : ""; + $ret .= " Journal$s'); return true;\" onmouseout=\"updateStatus(''); return true;\" />\n"; + } + + $ret .= "\n"; + + # by country + $ret .= ""; + $ret .= "
      "; + my $total = scalar(keys %{$count{'country'}}); + my $count = 0; + my $col = 0; + foreach (sort { $country{$a} cmp $country{$b} } keys %{$count{'country'}}) + { + $count++; + $ret .= "
    • $country{$_} ($count{'country'}->{$_})
    • \n"; + if ($col==0 && $count > ($total/2)) { $ret .= "
      "; $col = 1; } + } + $ret .= "
    \n"; + return $ret; + } + + my $remote = LJ::get_remote(); + +# unless (LJ::check_priv($remote, "betatest", "directory") || +# LJ::get_cap($remote, "directory") || +# (@filters == 1 && $filters[0] eq "int" && $GET{'opt_format'} eq "simple")) +#{ +# return $ML{'.error.accounttype'}; +#} + + unless (LJ::Dir::do_search($dbr, $dbdir, \%FORM, \@matches, \%info)) { + return ""; + } + + # opt_format and opt_sort might've been modified by do_search, + # filling in appropriate defaults based on other parameters + my $opt_format = $FORM{'opt_format'}; + my $opt_sort = $FORM{'opt_sort'}; + + $info{'allwhat'} ||= "users"; + + if ($info{'searching'}) { + my ($uri, $args) = (BML::get_uri(), BML::get_query_string()); + $uri .= '?' . $args if $args; + $head .= "\n"; + return "
    $ML{'.search.title'}...

    $ML{'.search.monkey'}

    "; + } + + if ($POST{'com_do'} || $GET{'com_do'}) { + $ret .= "<< $ML{'.search.new'}

    \n"; + } else { + $ret .= "<< $ML{'.search.new'}

    \n"; + } + unless (@{$info{'english'}}) { + push @{$info{'english'}}, "wish to be listed in the public directory"; + } + + $ret .= "Below are all $info{'allwhat'} that "; + + my $count_preds = @{$info{'english'}}; + + ### remove consecutive "are"s + my $last_are = 0; + foreach (@{$info{'english'}}) { + if (/^are /) { + if ($last_are) { + s/^are //; + } + $last_are = 1; + } else { + $last_are = 0; + } + } + my $last = pop @{$info{'english'}}; + if (@{$info{'english'}}) { + $ret .= join(", ", map { LJ::ehtml($_) } @{$info{'english'}}) . ", and "; + } + $ret .= LJ::ehtml($last) . ".\n"; + + if ($info{'overflow'}) { + $ret .= BML::ml(".search.overflow", {'count' => $info{'count'}}); + } + + if ($count_preds == 1 && $GET{'int_like'}) { + my $intid = $dbr->selectrow_array("SELECT intid FROM interests WHERE interest=?", + undef, $GET{'int_like'}); + LJ::run_hooks("interests_bml", { + 'intid' => $intid, + 'int' => $interest, + 'ret' => \$ret, + }) if $intid; + } + + ########## make the navcrap + my $navcrap; + $navcrap .= "".BML::ml(".navcrap.matches", {'count' => $info{'count'}}).""; + if ($info{'count'}) { + if ($info{'pages'} > 1) { + $navcrap .= "
    "; + $navcrap .= BML::ml(".navcrap.xofy", {'curpage' => $info{'page'}, 'totpages' => $info{'pages'}, 'reca' => $info{'first'}, 'recb' => $info{'last'}}); + $navcrap .= "
    "; + my $left = "<<"; + if ($info{'page'} > 1) { $left = " $info{'page'}-1 }) . "\">$left"; } + my $right = ">>"; + if ($info{'page'} < $info{'pages'}) { $right = " $info{'page'}+1 }) . "\">$right"; } + $navcrap .= $left . " "; + for (my $i=1; $i<=$info{'pages'}; $i++) { + my $link = "[$i]"; + if ($i != $info{'page'}) { $link = " $i }) . "\">$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + } + $navcrap .= "$right"; + } + $navcrap .= "
    standout?>\n"; + } else { + $navcrap .= " standout?>\n"; + } + ####### end navcrap + + $ret .= $navcrap . "

    "; + + unless ($info{'count'}) { return $ret; } + + if ($opt_sort eq "loc") { + LJ::load_codes({ state => \%state, country => \%country }); + } + + if ($opt_format eq "simple") + { + my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0; + my %last = (); + $ret .= "

      \n"; + foreach my $rec (@matches) + { + if ($showloc) { + if ($last{'country'} ne $rec->{'country'} || + $last{'state'} ne $rec->{'state'} || + $last{'city'} ne $rec->{'city'}) { + foreach (qw(country state city)) { $last{$_} = $rec->{$_}; } + my $country = $country{$rec->{'country'}}; + my ($state, $city); + if ($rec->{'state'}) { + $state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'}); + } + if ($rec->{'city'}) { + $city = ", $rec->{'city'}"; + } + $ret .= "
      "; + } + } + + $ret .= "{'user'}\">"; + if ($rec->{'journaltype'} eq "C") { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= " "; + $ret .= "{'user'}/\">$rec->{'user'} - " . LJ::ehtml($rec->{'name'}) . ", Updated "; + $ret .= LJ::ago_text($rec->{'secondsold'}); + $ret .= "
      \n"; + } + $ret .= "
    \n"; + } + + if ($opt_format eq "com") + { + $ret .= "\n"; + $ret .= "\n"; + foreach my $rec (@matches) + { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + my $color; + if ($rec->{'membership'} eq "open") { $color = "green"; } else { $color = "red"; } + $ret .= ""; + if ($rec->{'postlevel'} eq "members") { $color = "green"; } else { $color = "red"; } + $ret .= ""; + + $ret .= ""; + } + $ret .= "
     $ML{'.user'}$ML{'.community'}$ML{'.open'}$ML{'.post'}
    {'user'}\">"; + if ($rec->{'journaltype'} eq "C") { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= "{'user'}/\">$rec->{'user'}" . LJ::ehtml($rec->{'name'}) . "
    \n"; + } + + if ($opt_format eq "pics") + { + my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0; + my %last = (); + + my %pic; + my @picids = map { [$_, $_->{'defaultpicid'}] } @matches; + LJ::load_userpics(\%pic, \@picids); + + my $count = 0; + my $pos = 0; + my $more_to_show = 0; + $ret .= "\n"; + foreach my $rec (@matches) + { + if ($pos==5) { $ret .= "\n"; } + $pos++; $pos %= 5; + + if ($showloc) { + if ($last{'country'} ne $rec->{'country'} || + $last{'state'} ne $rec->{'state'} || + $last{'city'} ne $rec->{'city'}) { + foreach (qw(country state city)) { $last{$_} = $rec->{$_}; } + my $country = $country{$rec->{'country'}}; + my ($state, $city); + if ($rec->{'state'}) { + $state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'}); + } + if ($rec->{'city'}) { + $city = ", $rec->{'city'}"; + } + if ($pos > 1) { $ret .= ""; $pos = 1; } + $ret .= "
    "; + $ret .= "
    "; + $ret .= "\n"; + } + } + + + if ($pos==1) { $ret .= "\n"; } + my $picid = $rec->{'defaultpicid'}; + my $updateago = LJ::ago_text($rec->{'secondsold'}); + my $img; + if ($picid) { + $img = "{'userid'}\" ALT=\"$_->{'user'}\" WIDTH=$pic{$picid}->{'width'} HEIGHT=$pic{$picid}->{'height'} BORDER=0>
    "; + } + $ret .= "\n"; + } + $ret .= "
    "; + $ret .= $img; + $ret .= LJ::ljuser($rec->{'user'}); + $ret .= "
    $Ml{'.update'} $updateago
    \n"; + } + + if ($info{'pages'} > 1) { $ret .= $navcrap; } + return $ret; + + +_code?> + +<=body +head<= + + +<=head +page?> diff --git a/local/htdocs/download/index.bml b/local/htdocs/download/index.bml new file mode 100644 index 0000000..14edffe --- /dev/null +++ b/local/htdocs/download/index.bml @@ -0,0 +1,70 @@ +Клиенты Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð½ÐµÐ²Ð½Ð¸ÐºÐ° +HEAD<= +<=HEAD +BODYOPTS<= +<=BODYOPTS +BODY<= + +

    Блог на lj.rossia.org можно обновлÑÑ‚ÑŒ прÑмо из веб-браузера, но можно также иÑпользовать небольшую программу-клиент.

    + +

    Обратите внимание, что в наÑтройках требуетÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÑŒ Ñервер http://lj.rossia.org/.

    + +

    *NIX

    + +
      +
    • Drivel, LogJam — под GTK.
    • +
    • KLuJe — Ð´Ð»Ñ KDE (в качеÑтве Ñервера укажите http://lj.rossia.org/interface/flat/).
    • +
    • ljupdate — Ð´Ð»Ñ EMACS. + +

      УÑтановите файлы ljupdate, например, в ~/elisp/ljupdate. ТребуютÑÑ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ¸ http-cookies.el, http-get.el, http-post.el; еÑли их нет, то загрузите при помощи make fetch или вручную из CVS.

      + +

      В ~/.emacs напишите что-то вроде

      + +
      (add-to-list 'load-path "~/elisp")
      +(add-to-list 'load-path "~/elisp/ljupdate")
      +(require 'ljupdate)
      + +

      ÐаÑтройки можно указать при помощи M-x customize-group RET ljupdate RET.

      + +

      Далее работайте Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸ lj-... (в чаÑтноÑти, lj-login, lj-logout, lj-compose).

      +
    • +
    + +

    Windows

    + + + +

    КроÑÑплатформенные

    + +
      +
    • CHARM — на Python, конÑольный. + +

      Ð’ ~/.charmrc надо напиÑать

      + +
      login = usr pwd
      +url = http://lj.rossia.org/interface/flat
      + +

      Ð”Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚ÐµÐºÑтов будет иÑпользоватьÑÑ $EDITOR.

      +
    • + +
    • Deepest Sender — раÑширение Ð´Ð»Ñ Mozilla Firefox (в качеÑтве Ñервера укажите http://lj.rossia.org/interface/flat/).
    • + +
    • JLJ — на Perl, конÑольный. + +

      Ð’ ~/.livejournal.rc надо напиÑать

      + +
      server: lj.rossia.org
      +postcgi: /interface/flat
      +user: usr
      +password: pwd
      +
    • +
    • Petrus Blogger — на Java, Ñ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑким интерфейÑом.
    • +
    + +<=BODY +page?> diff --git a/local/htdocs/editinfo.bml b/local/htdocs/editinfo.bml new file mode 100755 index 0000000..d23ef52 --- /dev/null +++ b/local/htdocs/editinfo.bml @@ -0,0 +1,911 @@ + +body<= + + +underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + ### user is now authenticated ### + + my $dbr = LJ::get_db_reader(); + my $sth; + + # load user props + LJ::load_user_props($u, { use_master => 1 }, "opt_whatemailshow", + "country", "state", "city", + "zip", "icq", "aolim", "yahoo", "msn", "url", + "urlname", "gender", "jabber", "opt_blockrobots", + "opt_logcommentips", + "howhear", "opt_bdaymail", "opt_hidefriendofs", + "sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks", + "opt_whoscreened", "journaltitle", "journalsubtitle", + "friendspagetitle", "opt_weblogscom", "opt_stylemine", + "opt_imagelinks", "opt_getselfemail", "external_foaf_url", + "opt_showmutualfriends", "opt_embedplaceholders", + ); + + # to store values before they undergo normalisation + my %saved = (); + $saved{'name'} = $u->{'name'}; + + # clean userprops + foreach (values %$u) { LJ::text_out(\$_); } + + # load and clean bio + $u->{'bio'} = LJ::get_bio($u); + $saved{'bio'} = $u->{'bio'}; + LJ::text_out(\$u->{'bio'}, "force"); + + # load interests + my $uints = LJ::get_interests($u, { forceids => 1 }); + my %interests = (); + foreach (@$uints) { + $interests{$_->[1]} = $_->[0]; # $interests{name} = intid + } + + # load state and country codes + my %countries; + my %states; + LJ::load_codes({ "country" => \%countries, "state" => \%states }); + + + ### + ### no post, show edit form + ### + + unless (LJ::did_post()) { + + my $ret; + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + + # personal information + $ret .= "\n"; + + $ret .= "\n"; + + # name + $ret .= ""; + if (LJ::text_in($saved{'name'})) { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + + # birthday + $ret .= "\n"; + + # gender + $ret .= "\n"; + + # email + $ret .= "\n"; + + # url + $ret .= "\n"; + + # urlname + $ret .= "\n"; + + # chat thingies + foreach my $p (["aolim", $ML{'.chat.aolim.title'}, 28], ["icq", $ML{'.chat.icquin.title'}, 12], + ["yahoo", $ML{'.chat.yahooid.title'}, 33], ["msn", $ML{'.chat.msnusername.title'}, 60], + ["jabber", $ML{'.chat.jabber.title'}, 60]) + { + $ret .= "\n"; + } + + # country + $ret .= "\n"; + + # city + $ret .= "\n"; + + # state + $ret .= "\n"; + + # zip + $ret .= "\n"; + + # text messaging + if (LJ::get_cap($u, "textmessaging")) + { + $sth = $dbr->prepare("SELECT provider, number, security FROM txtmsg WHERE userid=?"); + $sth->execute($u->{'userid'}); + my $tminfo = $sth->fetchrow_hashref; + foreach (values %$tminfo) { LJ::text_out(\$_); } + + # text messaging + $ret .= "\n"; + } + + # end personal info + $ret .= "
    $ML{'.name.title'}" . LJ::html_text({ 'name' => 'name', 'value' => $u->{'name'}, + 'maxlength' => '50' }) . "
    " . LJ::html_hidden('name_absent', 'yes'); + $ret .= "
    $ML{'.bday.title'}"; + my %bdpart; + if ($u->{'bdate'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/) { + ($bdpart{'year'}, $bdpart{'month'}, $bdpart{'day'}) = ($1, $2, $3); + if ($bdpart{'year'} eq "0000") { $bdpart{'year'} = ""; } + if ($bdpart{'day'} eq "00") { $bdpart{'day'} = ""; } + } + $ret .= LJ::html_select({ 'name' => 'month', 'selected' => int($bdpart{'month'}) }, + '', '', map { $_, $ML{LJ::Lang::month_long_langcode($_)} } (1..12)) . " "; + + $ret .= LJ::html_text({ 'name' => 'day', 'value' => $bdpart{'day'}, 'size' => '3', 'maxlength' => '2' }) . " "; + $ret .= LJ::html_text({ 'name' => 'year', 'value' => $bdpart{'year'}, 'size' => '5', 'maxlength' => '4' }); + $ret .= " ($ML{'.bday.year.opt'})"; + + $ret .= "
    $ML{'.gender.title'}"; + $ret .= LJ::html_select({ 'name' => 'gender', 'selected' => $u->{'gender'} }, + 'U' => "(Unspecified)", 'M' => "Male", 'F' => "Female" ); + $ret .= "
    $ML{'.email.title'}"; + $ret .= LJ::html_text({ 'name' => 'email', 'value' => $u->{'email'}, 'size' => '40', 'maxlength' => '50' }); + $ret .= "
    $ML{'.webpageurl.title'}"; + $ret .= LJ::html_text({ 'name' => 'url', 'value' => $u->{'url'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= " ($ML{'.optional'})
    $ML{'.webpagename.title'}"; + $ret .= LJ::html_text({ 'name' => 'urlname', 'value' => $u->{'urlname'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= " ($ML{'.optional'})
    $p->[1]"; + $ret .= LJ::html_text({ 'name' => $p->[0], 'value' => $u->{$p->[0]}, 'size' => '20', 'maxlength' => $p->[2] }); + $ret .= " ($ML{'.optional'})
    $ML{'.country.title'}"; + $ret .= LJ::html_select({ 'name' => 'country', 'selected' => $u->{'country'} }, + '', $ML{'.country.choose'}, + 'US', 'United States', + map { $_, $countries{$_} } sort { $countries{$a} cmp $countries{$b} } keys %countries ); + $ret .= "
    $ML{'.city.title'}"; + $ret .= LJ::html_text({ 'name' => 'city', 'value' => $u->{'city'}, 'size' => '20', 'maxlength' => '255' }); + $ret .= "
    $ML{'.state.title'}"; + $ret .= LJ::html_select({ 'name' => 'statedrop', 'selected' => $u->{'state'} }, + '', "($ML{'.state.us'})", + map { $_, $states{$_} } sort { $states{$a} cmp $states{$b} } keys %states ); + + # other state? + $ret .= "
    $ML{'.state.other'}: "; + $ret .= LJ::html_text({ 'name' => 'stateother', 'size' => '20', 'maxlength' => '50', + 'value' => defined $states{$u->{'state'}} ? '' : $u->{'state'} }); + $ret .= "
    $ML{'.zip.title'}"; + $ret .= LJ::html_text({ 'name' => 'zip', 'value' => $u->{'zip'}, 'size' => '6', 'maxlength' => '5' }); + $ret .= " ($ML{'.zip.usonly'})
    "; + $ret .= LJ::help_icon('textmessage', "", " "); + $ret .= "$ML{'.tm.title'}\n\n\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'use_txtmsg', 'id' => 'use_txtmsg', + 'selected' => $u->{'txtmsg_status'} eq 'on' }); + + $ret .= "
     $ML{'.tm.sec.title'}"; + + $ret .= LJ::html_select({ 'name' => 'txtmsg_security', 'selected' => $tminfo->{'security'} }, + "all" => BML::ml(".security.visibility.anybody"), + "reg" => BML::ml(".security.visibility.regusers"), + "friends" => BML::ml(".security.visibility.friends") ); + $ret .= "
    $ML{'.tm.servprov'}"; + { + my @opts = ("", ""); + foreach my $p (LJ::TextMessage::providers()) { + my $info = LJ::TextMessage::provider_info($p); + push @opts, ($p, $info->{'name'}); + } + $ret .= LJ::html_select({ 'name' => 'txtmsg_provider', + 'selected' => $tminfo->{'provider'}, }, + @opts); + } + + $ret .= " ($ML{'.tm.details'})
    $ML{'.tm.phonenum'}"; + $ret .= LJ::html_text({ 'name' => 'txtmsg_number', 'value' => $tminfo->{'number'}, + 'size' => '15', 'maxlength' => '40' }); + $ret .= "
    \n
    \n\n"; + + ### User bio + $ret .= ""; + if (LJ::text_in($saved{'bio'})) { + $ret .= "
    "; + $ret .= LJ::html_textarea({ 'name' => 'bio', 'rows' => '10', 'cols' => '50', + 'wrap' => 'soft', 'value' => $u->{'bio'}, 'style' => "width: 90%", }) . "
    \n"; + } else { + $ret .= LJ::html_hidden('bio_absent', 'yes'); + $ret .= " p?>\n"; + } + + ### How heard Settings + unless ($u->{'howhear'}) { + $ret .= "\n"; + $ret .= " $LJ::SITENAME }) . " p?>\n"; + $ret .= "
    "; + $ret .= LJ::html_text({ 'name' => 'howhear', 'size' => '60', 'maxlength' => '100' }); + $ret .= "
    \n\n"; + } + + { + ### Interests + $ret .= "\n"; + my @eintsl; + foreach (sort keys %interests) { + push @eintsl, $_ if LJ::text_in($_); + } + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_textarea({ 'name' => 'interests', 'value' => join(", ", @eintsl), + 'rows' => '10', 'cols' => '50', 'wrap' => 'soft' }); + $ret .= "
    \n\n"; + } + + ### Picture Settings + $ret .= "\n\n"; + $ret .= "

    "; + if ($u->{'defaultpicid'}) + { + my $picid = $u->{'defaultpicid'}; + my %userpics = (); + LJ::load_userpics(\%userpics, [ $u, $picid ]); + $ret .= "{'userid'}\" width='$userpics{$picid}->{'width'}' height='$userpics{$picid}->{'height'} alt='$u->{'user'}' border='0'>"; + } else + { + $ret .= "($ML{'.userpic.none'})"; + } + $ret .= "

    $ML{'.userpic.edit'}

    \n\n"; + + + ### + ### Journal Options + ### + + $ret .= "\n"; + + + ### display options + $ret .= "\n"; + $ret .= "\n"; + + # journaltitle + $ret .= ""; + $ret .= "\n"; + + # journalsubtitle + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + + # friendspagetitle + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    $ML{'.settings.journal.title'} " . LJ::html_text({ 'name' => 'journaltitle', 'value' => $u->{'journaltitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.journal.subtitle'} " . LJ::html_text({ 'name' => 'journalsubtitle', 'value' => $u->{'journalsubtitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.journal.subtitle.optional'}
    $ML{'.settings.friendspage.title'} " . LJ::html_text({ 'name' => 'friendspagetitle', 'value' => $u->{'friendspagetitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.friendspage.title.optional'}
    \n\n"; + + ### privacy options + $ret .= "\n"; + $ret .= "\n"; + + # allow_contactshow + $ret .= "\n"; + $ret .= "\n"; + + # allow_infoshow + $ret .= "\n"; + $ret .= "\n"; + + # opt_blockrobots + $ret .= "\n"; + $ret .= "\n"; + + # opt_weblogscom + if (LJ::get_cap($u, "weblogscom")) { + $ret .= "\n"; + $ret .= "\n"; + } + + # opt_showmutualfriends + $ret .= "\n"; + $ret .= "\n"; + + # opt_hidefriendofs + $ret .= "\n"; + $ret .= "\n"; + + + # allow_getljnews + $ret .= "\n"; + $ret .= "\n"; + + # opt_bdaymail + $ret .= "\n"; + $ret .= "\n"; + + # opt_imagelinks + my ($maxwidth, $maxheight) = (0, 0); + ($maxwidth, $maxheight) = ($1, $2) + if ($u->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/); + my $is_stock = {'320|240' => 1, '640|480' => 1, '0|0' => 1, '' => 1}->{$u->{'opt_imagelinks'}}; + my $extra = $is_stock ? '' : BML::ml('.imagelinks.size.custom', + {'width' => $maxwidth, 'height' => $maxheight}); + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + # opt_getselfemail + $ret .= "\n"; + $ret .= "\n"; + + # opt_showtalklinks + $ret .= "\n"; + $ret .= "\n"; + + # opt_embedplaceholders + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_contactshow', 'id' => 'allow_contactshow', + 'selected' => $u->{'allow_contactshow'} ne 'N' }); + $ret .= "
     $ML{'.allowshowcontact.about'}"; + + { + # contactshow_sec + $ret .= "\n

    $ML{'.security.header'} "; + $ret .= LJ::html_select({ 'name' => 'contactshow_sec', + 'selected' => $u->{'allow_contactshow'} }, + "Y" => BML::ml(".security.visibility.everybody"), + "F" => BML::ml(".security.visibility.friends") ); + $ret .= "

    \n"; + + # opt_whatemailshow + $ret .= "

    $ML{'.allowshowcontact.email'}\n"; + $ret .= "

    "; + my $cur = $u->{'opt_whatemailshow'} || "N"; + my @vals = ( ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail")) + ? ("B" => BML::ml(".allowshowcontact.email.both", { 'domain' => $LJ::USER_DOMAIN}), + "A" => BML::ml(".allowshowcontact.email.actual_only"), + "L" => BML::ml(".allowshowcontact.email.lj_only"), + "N" => BML::ml(".allowshowcontact.email.neither")) + : ("A" => BML::ml(".allowshowcontact.email.show"), + "N" => BML::ml(".allowshowcontact.email.no_show"))); + $ret .= LJ::html_select({ 'name' => 'opt_whatemailshow', 'selected' => $cur }, @vals) . "\n"; + + $ret .= "

    " . ($LJ::USER_EMAIL + ? $ML{'.allowshowcontact.email.withdomainaddr'} + : $ML{'.allowshowcontact.email.withoutdomainaddr'}) . "

    \n
    \n"; + + # opt_mangleemail + $ret .= "\n\n"; + $ret .= "\n
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_mangleemail', 'id' => 'opt_mangleemail', + 'selected' => $u->{'opt_mangleemail'} eq 'Y' }); + $ret .= "
     $ML{'.mangleaddress.about'}
    \n"; + + } + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_infoshow', 'id' => 'allow_infoshow', + 'selected' => $u->{'allow_infoshow'} eq 'Y' }); + $ret .= "
     $ML{'.allowshowinfo.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_blockrobots', 'id' => 'opt_blockrobots', + 'selected' => $u->{'opt_blockrobots'} }); + $ret .= "
     $ML{'.blockrobots.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_weblogscom', 'id' => 'opt_weblogscom', + 'selected' => $u->{'opt_weblogscom'} }); + $ret .= "
     $ML{'.weblogscom.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showmutualfriends', 'id' => 'opt_showmutualfriends', + 'selected' => $u->{'opt_showmutualfriends'} }); + $ret .= "
     $ML{'.mutualfriends.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_hidefriendofs', 'id' => 'opt_hidefriendofs', + 'selected' => $u->{'opt_hidefriendofs'} }); + $ret .= "
     $ML{'.hidefriendof.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_getljnews', 'id' => 'allow_getljnews', + 'selected' => $u->{'allow_getljnews'} eq 'Y' }); + $ret .= "
     $ML{'.opt_in.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_bdaymail', 'id' => 'opt_bdaymail', + 'selected' => $u->{'opt_bdaymail'} }); + $ret .= "
     $ML{'.bdayreminders.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_imagelinks_on', 'id' => 'opt_imagelinks_on', + 'selected' => $u->{'opt_imagelinks'} }); + $ret .= "
     $ML{'.imagelinks.about'}
     "; + $ret .= LJ::html_select({'name' => 'opt_imagelinks', 'selected' => $u->{'opt_imagelinks'}}, + '0|0', BML::ml('.imagelinks.size.all'), + '320|240', BML::ml('.imagelinks.size.small', {'width' => 320, 'height' => 240}), + '640|480', BML::ml('.imagelinks.size.medium', {'width' => 640, 'height' => 480}), + $extra ? ("$maxwidth|$maxheight", $extra) : ()); + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_getselfemail', 'id' => 'opt_getselfemail', + 'selected' => $u->{'opt_getselfemail'}, + 'disabled' => !LJ::get_cap($u, 'getselfemail') }); + $ret .= "
     $ML{'.getselfemails.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showtalklinks', 'id' => 'opt_showtalklinks', + 'selected' => $u->{'opt_showtalklinks'} eq 'Y' }); + $ret .= "
     $ML{'.enableboards.about'}"; + + { + # opt_whocanreply + $ret .= "\n

    $ML{'.whoreply.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_whocanreply', 'selected' => $u->{'opt_whocanreply'} }, + "all" => BML::ml(".security.visibility.anybody"), + "reg" => BML::ml(".security.visibility.regusers"), + "friends" => BML::ml(".security.visibility.friends")); + $ret .= "

    \n"; + + # opt_logcommentips + $ret .= "

    $ML{'.logip.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_logcommentips', 'selected' => $u->{'opt_logcommentips'} }, + "N" => BML::ml(".donotlog"), + "S" => BML::ml(".logip.anon_only"), + "A" => BML::ml(".logip.always") ); + $ret .= "

    \n"; + + # opt_whoscreened + $ret .= "

    $ML{'.screen.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_whoscreened', 'selected' => $u->{'opt_whoscreened'} }, + "N" => $ML{'.screen.none'}, + "R" => $ML{'.screen.anon'}, + "F" => ($u->{'journaltype'} eq 'C' ? $ML{'.screen.nonmembers'} : $ML{'.screen.nonfriends'}), + "A" => $ML{'.screen.all'} ); + $ret .= "

    \n"; + + $ret .= "\n"; + + # opt_nctalklinks +# $ret .= "\n"; +# $ret .= "\n"; + + # stylemine + $ret .= "\n"; + $ret .= "\n"; + + # opt_gettalkemail + $ret .= "\n"; + $ret .= "\n"; + + # opt_htmlemail + $ret .= "\n"; + $ret .= "\n"; + + + $ret .= "
    "; +# $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_nctalklinks', 'id' => 'opt_nctalklinks', +# 'selected' => $u->{'opt_nctalklinks'} }); +# $ret .= "
     $ML{'.numcomments.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_stylemine', 'id' => 'opt_stylemine', + 'value' => 1, 'selected' => $u->{'opt_stylemine'} }); + $ret .= "
     $ML{'.stylemine.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_gettalkemail', 'id' => 'opt_gettalkemail', + 'selected' => $u->{'opt_gettalkemail'} eq 'Y' }); + $ret .= "
     $ML{'.getreplies.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_htmlemail', 'id' => 'opt_htmlemail', + 'selected' => $u->{'opt_htmlemail'} eq 'Y' }); + $ret .= "
     $ML{'.htmlemail.about'}
    \n"; + + } + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_embedplaceholders', 'id' => 'opt_embedplaceholders', + 'selected' => $u->{'opt_embedplaceholders'}}); + $ret .= "
     $ML{'.opt_embedplaceholders.about'}
    \n\n"; + + ### advanced options + $ret .= "\n"; + $ret .= "\n"; + + # external foaf link + $ret .= ""; + + # done +# $ret .= "
    $ML{'.foafurl.title'}"; + $ret .= LJ::html_text({ 'name' => 'external_foaf_url', + 'value' => $u->{'external_foaf_url'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= "
    $ML{'.foafurl.about'}
    \n"; + + ### unicode options + if ($LJ::UNICODE) { + my (%old_encnames, %mail_encnames, %encodings); + LJ::load_codes({ "encoding" => \%encodings } ); + LJ::load_codes({ "encname" => \%old_encnames } ); + %mail_encnames = %old_encnames; + +# +# OK, as of 2011 Apr 02, all LJR users with oldenc!=0 converted to utf-8 in db, thanks nit! +# +# ### oldenc - your messages stored in database in this encoding +# ### Default: 0 for utf-8. Only 32 users have oldenc!=0 +# ### Perhaps we should convert them to utf using utf8convert.bml +# ### and hide the option, but not tested - check twice! +# +# +# # which encodings to show? For now, we just delete utf-8 from the old encodings +# # list because it doesn't make sense there. +# foreach my $id (keys %encodings) { +# delete $old_encnames{$id} if lc($encodings{$id}) eq 'utf-8'; +# } +# +# $ret .= "\n"; +# $ret .= "\n"; +# $ret .= ""; +# $ret .= "\n"; +# $ret .= ""; + + + ### e-mail encoding: + if ($u->{journaltype} eq 'P') { + $ret .= ""; + my $encoding = $u->{'mailencoding'} ? $u->{'mailencoding'} : 6; +# $ret .= "\n"; + $ret .= "\n"; + + $ret .= ""; + } + + $ret .= "
    $ML{'.autotranslate.header'}" . LJ::html_select({ 'name' => 'oldenc', 'selected' => $u->{'oldenc'}}, +# map { $_, $old_encnames{$_} } sort keys %old_encnames ) . "
    " . $ML{'.autotranslate.about'} . "
    $ML{'.translatemailto.header'}" . LJ::html_select({ 'name' => 'mailencoding', 'selected' => $u->{'mailencoding'}}, +# map { $_, $mail_encnames{$_} } sort keys %mail_encnames ) . "
    " . LJ::html_select({ 'name' => 'mailencoding', 'selected' => $encoding}, + map { $_, $mail_encnames{$_} } sort keys %mail_encnames ) . "
    $ML{'.translatemailto.about'}
    \n"; + } + + ### let them un-ban users if they've banned users + my $banned = LJ::load_rel_user($u, 'B'); + if ($banned && @$banned) { + my $us = LJ::load_userids(@$banned); + + $ret .= "\n"; + $ret .= "
    \n"; + foreach (@$banned) { + my $bu = $us->{$_}; + next unless $bu; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'unban', 'id' => "unban-$bu->{'user'}", + 'value' => $bu->{'userid'} }); + $ret .= "
    \n"; + } + $ret .= "
    \n"; + } + + # ending submit block + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + + return $ret; + } + + + ### + ### we have a post, process edits + ### + + if (LJ::did_post()) { + return "" unless LJ::check_form_auth(); + + $POST{'unban'} =~ s/\0/,/g; + return "" unless LJ::text_in(\%POST); + + my @errors = (); + + # name + unless ($POST{'name'} || defined($POST{'name_absent'})) { + push @errors, $ML{'.error.noname'}; + } + + # state and zip + my ($zipcity, $zipstate); + if ($POST{'country'} eq "US") { + $sth = $dbr->prepare("SELECT city, state FROM zip WHERE zip=?"); + $sth->execute($POST{'zip'}); + ($zipcity, $zipstate) = $sth->fetchrow_array; + } + + # country + if ($POST{'country'} ne "US" && $POST{'zip'}) { + push @errors, $ML{'.error.locale.zip_requires_us'}; + } + + if ($POST{'country'} eq "US" && $POST{'stateother'}) { + push @errors, $ML{'.error.locale.country_ne_state'}; + } elsif ($POST{'country'} && $POST{'country'} ne "US" && $POST{'statedrop'}) { + push @errors, $ML{'.error.locale.state_ne_country'}; + } + + # zip-code validation stuff + if ($POST{'country'} eq "US") { + if ($POST{'statedrop'} && $zipstate && $POST{'statedrop'} ne $zipstate) { + push @errors, $ML{'.error.locale.zip_ne_state'}; + } + if ($zipcity) { + $POST{'statedrop'} = $zipstate; + $POST{'city'} = $zipcity; + } + } + + if ($POST{'country'} && !defined($countries{$POST{'country'}})) { + push @errors, $ML{'.error.locale.invalid_country'}; + } + + # birthday + my $this_year = (localtime())[5]+1900; + + if ($POST{'year'} && $POST{'year'} < 100) { + push @errors, $ML{'.error.year.notenoughdigits'}; + } + + if ($POST{'year'} && $POST{'year'} >= 100 && ($POST{'year'} < 1890 || $POST{'year'} > $this_year)) { + push @errors, $ML{'.error.year.outofrange'}; + } + + if ($POST{'month'} && ($POST{'month'} < 1 || $POST{'month'} > 12)) { + push @errors, $ML{'.error.month.outofrange'}; + } + + if ($POST{'day'} && ($POST{'day'} < 1 || $POST{'day'} > 31)) { + push @errors, $ML{'.error.day.outofrange'}; + } + + if (@errors == 0 && $POST{'day'} > LJ::days_in_month($POST{'month'}, $POST{'year'})) { + push @errors, $ML{'.error.day.notinmonth'}; + } + + # email + unless ($POST{'email'}) { + push @errors, $ML{'.error.email.none'}; + } + + if ($LJ::USER_EMAIL and $POST{'email'} =~ /\@\Q$LJ::USER_DOMAIN\E$/i) { + push @errors, BML::ml(".error.email.lj_domain", { 'user' => $u->{'user'}, 'domain' => $LJ::USER_DOMAIN, }); + } + + if ($POST{'email'} =~ /\s/) { + push @errors, $ML{'.error.email.no_space'}; + } + + unless (@errors) { + LJ::check_email($POST{'email'}, \@errors); + } + + # text messaging + if ($POST{'use_txtmsg'}) { + unless ($POST{'txtmsg_provider'}) { + push @errors, $ML{'.error.tm.require_provider'}; + } + unless ($POST{'txtmsg_number'}) { + push @errors, $ML{'.error.tm.require.number'}; + } + } + + return LJ::bad_input(@errors) if @errors; + + ### no errors + + my $dbh = LJ::get_db_writer(); + + my $email_changed = ($u->{'email'} ne $POST{'email'}); + if ($email_changed) { + # record old email address; + LJ::infohistory_add($u, 'email', $u->{email}, $u->{status}); + } + + $POST{'url'} =~ s/\s+$//; $POST{'url'} =~ s/^\s+//; + if ($POST{'url'} && $POST{'url'} !~ /^https?:\/\//) { + $POST{'url'} =~ s/^http\W*//; + $POST{'url'} = "http://$POST{'url'}"; + } + + my $newname = defined $POST{'name_absent'} ? $saved{'name'} : $POST{'name'}; + $newname =~ s/[\n\r]//g; + $newname = LJ::text_trim($newname, LJ::BMAX_NAME, LJ::CMAX_NAME); + + my $newbio = defined($POST{'bio_absent'}) ? $saved{'bio'} : $POST{'bio'}; + my $has_bio = ($newbio =~ /\S/) ? "Y" : "N"; + my $txtmsg_status = $POST{'use_txtmsg'} ? "on" : "off"; + # setup what we're gonna update in the user table: + my %update = ( + 'name' => $newname, + 'bdate' => sprintf("%04d-%02d-%02d", $POST{'year'}, $POST{'month'}, $POST{'day'}), + 'email' => $POST{'email'}, + 'status' => ($email_changed && $u->{'status'} eq "A") ? "T" : $u->{'status'}, + 'has_bio' => $has_bio, + 'allow_infoshow' => $POST{'allow_infoshow'} ? "Y" : "N", + 'allow_getljnews' => $POST{'allow_getljnews'} ? "Y" : "N", + 'opt_showtalklinks' => $POST{'opt_showtalklinks'} ? "Y" : "N", + 'opt_gettalkemail' => $POST{'opt_gettalkemail'} ? "Y" : "N", + 'opt_htmlemail' => $POST{'opt_htmlemail'} ? "Y" : "N", + 'opt_mangleemail' => $POST{'opt_mangleemail'} ? "Y" : "N", + 'opt_whocanreply' => $POST{'opt_whocanreply'}, + 'txtmsg_status' => $txtmsg_status, + ); + + if ($POST{'allow_contactshow'}) { + $update{'allow_contactshow'} = "Y"; + $update{'allow_contactshow'} = "F" if $POST{'contactshow_sec'} eq "F"; + } else { + $update{'allow_contactshow'} = "N"; + } + +# if (defined $POST{'oldenc'}) { +# $update{'oldenc'} = $POST{'oldenc'}; +# } + + LJ::update_user($u, \%update); + + ### change any of the userprops ? + { + # journal / friends titles + $POST{'journaltitle'} = LJ::text_trim($POST{'journaltitle'}, 0, 80) if $POST{'journaltitle'}; + $POST{'journalsubtitle'} = LJ::text_trim($POST{'journalsubtitle'}, 0, 80) if $POST{'journalsubtitle'}; + $POST{'friendspagetitle'} = LJ::text_trim($POST{'friendspagetitle'}, 0, 80) if $POST{'friendspagetitle'}; + + # opts + $POST{'opt_showmutualfriends'} = $POST{'opt_showmutualfriends'} ? 1 : 0; + $POST{'opt_getselfemail'} = $POST{'opt_getselfemail'} ? 1 : 0; + $POST{'opt_stylemine'} = $POST{'opt_stylemine'} ? 1 : 0; + $POST{'opt_blockrobots'} = $POST{'opt_blockrobots'} ? 1 : 0; + $POST{'opt_bdaymail'} = $POST{'opt_bdaymail'} ? 1 : 0; + $POST{'opt_hidefriendofs'} = $POST{'opt_hidefriendofs'} ? 1 : 0; + $POST{'opt_nctalklinks'} = $POST{'opt_nctalklinks'} ? 1 : 0; + $POST{'opt_weblogscom'} = $POST{'opt_weblogscom'} ? 1 : 0; + if ($POST{'opt_logcommentips'} ne "N" && + $POST{'opt_logcommentips'} ne "S" && + $POST{'opt_logcommentips'} ne "A") { $POST{'opt_logcommentips'} = "N"; } + $POST{'opt_whoscreened'} = "N" unless $POST{'opt_whoscreened'} =~ m/^(N|R|F|A)$/; + $POST{'opt_imagelinks'} = 0 unless $POST{'opt_imagelinks_on'} && + $POST{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/; + $POST{'opt_embedplaceholders'} = $POST{'opt_embedplaceholders'} ? 1 : 0; + + # for the directory. + $POST{'sidx_bdate'} = ""; + $POST{'sidx_loc'} = ""; + $POST{'state'} = $POST{'statedrop'} || $POST{'stateother'}; + if ($update{'allow_infoshow'} eq 'Y') { + if ($POST{'year'}) { + $POST{'sidx_bdate'} = sprintf("%04d-%02d-%02d", map { $POST{$_} } + qw(year month day)); + } + + if ($POST{'country'}) { + my $state; + if ($POST{'country'} eq "US") { + $state = $POST{'statedrop'}; + } else { + $state = $POST{'stateother'}; + } + $POST{'sidx_loc'} = sprintf("%2s-%s-%s", + $POST{'country'}, + $state, + $POST{'city'}); + } + } + + my @uprops = ( + "opt_whatemailshow", + "country", "state", "city", "zip", "icq", + "aolim", "yahoo", "msn", "url", "urlname", + "gender", "jabber", "opt_blockrobots", + "opt_logcommentips", + "opt_bdaymail", "opt_hidefriendofs", + "sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks", + "opt_whoscreened", "journaltitle", "journalsubtitle", "friendspagetitle", + "opt_stylemine", "opt_imagelinks", "opt_getselfemail", + "external_foaf_url", "opt_showmutualfriends", "opt_embedplaceholders", + ); + + # weblogs.com requires a special cap + push @uprops, 'opt_weblogscom' if LJ::get_cap($u, 'weblogscom'); + + # this is only done once, then never appears again. + push @uprops, 'howhear' if $POST{'howhear'}; + + # set userprops + foreach my $uprop (@uprops) { + my $eff_val = $POST{$uprop}; # effective value, since 0 isn't stored + $eff_val = "" unless $eff_val; + my $mem_only = $eff_val eq $u->{$uprop}; + LJ::set_userprop($u, $uprop, $eff_val, $mem_only); + } + } + + # update their bio text + if (($u->{'bio'} ne $POST{'bio'}) && !defined($POST{'bio_absent'})) { + if ($has_bio eq "N") { + $u->do("DELETE FROM userbio WHERE userid=?", undef, $u->{'userid'}); + $u->dudata_set('B', 0, 0); + } else { + $u->do("REPLACE INTO userbio (userid, bio) VALUES (?, ?)", + undef, $u->{'userid'}, $POST{'bio'}); + $u->dudata_set('B', 0, length($POST{'bio'})); + } + LJ::MemCache::set([$u->{'userid'}, "bio:$u->{'userid'}"], $POST{'bio'}); + } + + # update their text messaging info + if ($txtmsg_status eq "off" && $u->{'txtmsg_status'} eq "on") { + $dbh->do("DELETE FROM txtmsg WHERE userid=?", undef, $u->{'userid'}); + } elsif ($txtmsg_status eq "on") { + $dbh->do("REPLACE INTO txtmsg (userid, provider, number, security) VALUES (?, ?, ?, ?)", + undef, $u->{'userid'}, $POST{'txtmsg_provider'}, $POST{'txtmsg_number'}, $POST{'txtmsg_security'}); + } + + # update interests + unless ($POST{'interests_absent'}) { + $POST{'interests'} =~ s/^\s+//; + $POST{'interests'} =~ s/\s+$//; + $POST{'interests'} =~ s/\n/,/g; + $POST{'interests'} =~ s/\s+/ /g; #Strip duplicate spaces from the interest + my @ints = split (/\s*,\s*/, $POST{'interests'}); + my $intcount = scalar(@ints); + if ($intcount > 150) { + return LJ::bad_input(BML::ml(".error.excessive_int", {'intcount' => $intcount})); + } + LJ::set_interests($u, \%interests, \@ints); + } + + # now unban users they selected to be unbanned + if ($POST{'unban'}) { + my $bannedin = join(",", map { $dbh->quote($_); } split(/,/, $POST{'unban'})); + $dbh->do("DELETE FROM reluser WHERE userid=? AND type='B' AND targetid IN ($bannedin)", undef, $u->{'userid'}); + } + + # actions if email changed + if ($email_changed) { + my $aa = {}; + $aa = LJ::register_authaction($u->{'userid'}, + "validateemail", $POST{'email'}); + + LJ::send_mail({ + 'to' => $POST{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'charset' => 'utf-8', + 'subject' => $ML{'.newemail.subject'}, + 'body' => BML::ml('.newemail.body2', + { username => $u->{user}, + sitename => $LJ::SITENAME, + sitelink => $LJ::SITEROOT, + conflink => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}" }), + }); + } + + # tell the user all is well + return "\n" . + " $u->{'user'}, }) . " p?>"; + } + + # should never happen + return ""; + +} +_code?> + +<=body +page?> +lib: LJ::TextMessage, cgi-bin/ljlib.pl, cgi-bin/ljlang.pl +link: htdocs/privacy.bml, htdocs/support/faqbrowse.bml, htdocs/tools/textmessage.bml, htdocs/uploadpic.bml +link: htdocs/paidaccounts/index.bml, htdocs/users, htdocs/userinfo.bml +post: htdocs/editinfo.bml +img: htdocs/userpic + _c?> diff --git a/local/htdocs/edittags.bml b/local/htdocs/edittags.bml new file mode 100755 index 0000000..a009eb0 --- /dev/null +++ b/local/htdocs/edittags.bml @@ -0,0 +1,126 @@ + +body<= +" unless $remote; + + my $err = sub { return ""; }; + return $err->($ML{'.disabled'}) + if $LJ::DISABLED{tags}; + + my ($ret, $msg); + + return $err->($ML{'.invalid.link'}) + unless LJ::did_post() || ($GET{journal} && $GET{itemid}); + + my $journal = $GET{journal} || $POST{journal}; + my $u = LJ::load_user($journal); + return $err->($ML{'.invalid.journal'}) unless $u; + + my $ditemid = ($GET{itemid} || $POST{itemid})+0; + my $anum = $ditemid % 256; + my $jitemid = $ditemid >> 8; + return $err->($ML{'.invalid.entry'}) unless $jitemid; + + my $logrow = LJ::get_log2_row($u, $jitemid); + return $err->($ML{'.invalid.entry'}) unless $logrow; + return $err->($ML{'.invalid.entry'}) unless $logrow->{anum} == $anum; + return $err->($ML{'.invalid.notauthorized'}) + unless LJ::can_view($remote, $logrow); + + if (LJ::did_post()) { + return $err->($ML{'.invalid.link'}) + unless LJ::check_form_auth(); + + LJ::Tags::update_logtags($u, $jitemid, { + set_string => $POST{edittags}, + remote => $remote, + }); + + BML::redirect( LJ::journal_base($u) . "/$ditemid.html" ); + #$msg = "
    Tags successfully updated.
    "; + } + + my $item = LJ::Talk::get_journal_item($u, $jitemid); + + my $subj = $item->{'subject'}; + my $evt = $item->{'event'}; + + LJ::CleanHTML::clean_subject(\$subj); + LJ::CleanHTML::clean_event(\$evt); + + ## $item->{'props'}->{'tags'} ??? + my $logtags = LJ::Tags::get_logtags($u, $jitemid); + my $usertags = LJ::Tags::get_usertags($u, { remote => $remote }) || {}; + $logtags = $logtags->{$jitemid} || {}; + my $logtagstr = join ', ', map { LJ::ejs($_) } sort values %$logtags; + + $ret .= "
    "; + $ret .= ""; + + $ret .= ''; + $ret .= "" if $subj; + $ret .= ""; + $ret .= ""; # spacer + + $ret .= ""; + $ret .= ''; + $ret .= LJ::form_auth(); + $ret .= ""; + + $ret .= ""; + + $ret .= '
    $ML{'.subject'}$subj
    $ML{'.entry'}$evt
      
    $ML{'.current'}
    "; + if ( LJ::Tags::can_add_tags($u, $remote) ) { + $ret .= LJ::html_text( + { + name => 'edittags', + value => (join ', ', sort values %$logtags), + size => 40, + class => 'tagfield', + id => 'tagfield', + } + ); + $ret .= '  '; + $ret .= LJ::html_submit( 'save', $ML{'.button.save'}, { class => 'btn' }); + $ret .= $msg if $msg; + } else { + # no widgets + $ret .= $ML{'.permissions.none'}; + } + $ret .= "
    $ML{'.users'}"; + + if ( scalar keys %$usertags ) { + $ret .= ""; + } else { + $ret .= "none" + } + + $ret .= "

    "; + $ret .= "$ML{'.permissions.add.yes'}
    " if LJ::Tags::can_add_tags($u, $remote); + $ret .= "$ML{'.permissions.control.yes'}
    " if LJ::Tags::can_control_tags($u, $remote); + $ret .= BML::ml('.view', { aopts => 'href="' . LJ::journal_base($u) . "/$ditemid.html" . '"' }); + $ret .= "
    '; + $ret .= LJ::html_hidden('journal', $journal); + $ret .= LJ::html_hidden('itemid', $GET{itemid} || $POST{itemid}); + $ret .= ''; + + return $ret; +} +_code?> +<=body +head<= + + +<=head +page?> diff --git a/local/htdocs/export_comments.bml b/local/htdocs/export_comments.bml new file mode 100644 index 0000000..87e4874 --- /dev/null +++ b/local/htdocs/export_comments.bml @@ -0,0 +1,158 @@ +{'r'}; + + my $remote = LJ::get_remote(); + return "" unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) unless $u; + + my @errors = (); + + my $dbcr = LJ::get_cluster_reader($u); + push @errors, $ML{'error.nodb'} unless $dbcr; + + # don't let people hit us with silly GET attacks + push @errors, "This page can't be viewed except via POST." + if BML::get_client_header('Referer') && !LJ::did_post(); + + my $mode = $GET{get}; + push @errors, "Invalid mode." + unless $mode =~ m/^comment_(?:meta|body)$/; + + # error stuff + return LJ::bad_input(@errors) if @errors; + + # from now on, we manage our own output + BML::suppress_headers(); + BML::suppress_content(); + + # print top + $r->content_type("text/xml; charset=utf-8"); + $r->send_http_header(); + $r->print("\n\n"); + + # startid specified? + my $gather = $mode eq 'comment_meta' ? 10000 : 1000; + my $startid = $GET{startid}+0; + my $endid = $startid + $gather; + + # get metadata + my $rows = $dbcr->selectall_arrayref('SELECT jtalkid, nodeid, parenttalkid, posterid, state, datepost ' . + "FROM talk2 WHERE nodetype = 'L' AND journalid = ? AND " . + " jtalkid >= $startid AND jtalkid < $endid", + undef, $u->{userid}); + + # now let's gather them all together while making a list of posterids + my %posterids; + my %comments; + foreach my $r (@{$rows || []}) { + $comments{$r->[0]} = { + nodeid => $r->[1], + parenttalkid => $r->[2], + posterid => $r->[3], + state => $r->[4], + datepost => $r->[5], + }; + $posterids{$r->[3]} = 1 if $r->[3]; # don't include 0 (anonymous) + } + + # now we have two choices: comments themselves or metadata + if ($mode eq 'comment_meta') { + # meta data is easy :) + my $max = $dbcr->selectrow_array('SELECT MAX(jtalkid) FROM talk2 ' . + "WHERE journalid = ? AND nodetype = 'L'", + undef, $u->{userid}); + $max += 0; + $r->print("$max\n"); + + # load posterids + my $us = LJ::load_userids(keys %posterids); + + # now spit out the metadata + $r->print("\n"); + while (my ($id, $data) = each %comments) { + my $ret = "{posterid}; + $ret .= " state='$data->{state}'" if $data->{state} ne 'A'; + $ret .= " />\n"; + $r->print($ret); + } + $r->print("\n\n"); + + # now spit out usermap + my $ret = ''; + while (my ($id, $user) = each %$us) { + $ret .= "\n"; + } + $r->print($ret); + $r->print("\n"); + + # comment data also presented in glorious XML: + } elsif ($mode eq 'comment_body') { + # get real comments from startid to a limit of 10k data, however far that takes us + my @ids = sort { $a <=> $b } keys %comments; + + # call a load to get comment text + my $texts = LJ::get_talktext2($u, @ids); + + # get props if we need to + my $props = {}; + if ($GET{'props'}) { + LJ::load_talk_props2($u, \@ids, $props); + } + + # now start spitting out data + $r->print("\n"); + foreach my $id (@ids) { + # get text for this comment + my $data = $comments{$id}; + my $text = $texts->{$id}; + my ($subject, $body) = @{$text || []}; + + # only spit out valid UTF8, and make sure it fits in XML, and uncompress it + LJ::text_uncompress(\$body); + LJ::text_out(\$subject); + LJ::text_out(\$body); + $subject = LJ::exml($subject); + $body = LJ::exml($body); + + # setup the date to be GMT and formatted per W3C specs + my $date = LJ::mysqldate_to_time($data->{datepost}); + $date = LJ::time_to_w3c($date, 'Z'); + + # print the data + my $ret = "{posterid}; + $ret .= " state='$data->{state}'" if $data->{state} ne 'A'; + $ret .= " parentid='$data->{parenttalkid}'" if $data->{parenttalkid}; + if ($data->{state} eq 'D') { + $ret .= " />\n"; + } else { + $ret .= ">\n"; + $ret .= "$subject\n" if $subject; + $ret .= "$body\n" if $body; + $ret .= "$date\n"; + foreach my $propkey (keys %{$props->{$id} || {}}) { + $ret .= ""; + $ret .= LJ::exml($props->{$id}->{$propkey}); + $ret .= "\n"; + } + $ret .= "\n"; + } + $r->print($ret); + } + $r->print("\n"); + } + + # all done + $r->print("\n"); +} +_code?> + _c?> diff --git a/local/htdocs/export_do.bml b/local/htdocs/export_do.bml new file mode 100755 index 0000000..575f6e3 --- /dev/null +++ b/local/htdocs/export_do.bml @@ -0,0 +1,206 @@ +{'r'}; + + my $remote = LJ::get_remote(); + return "" + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my @errors = (); + + my $year = $POST{'year'}+0; + my $month = $POST{'month'}+0; + + my $dbcr = LJ::get_cluster_reader($u); + push @errors, $ML{'error.nodb'} unless $dbcr; + + my $encoding; + + if ($POST{'encid'}) { + my %encodings; + LJ::load_codes({ "encoding" => \%encodings } ); + $encoding = $encodings{$POST{'encid'}}; + } + + $encoding ||= $POST{'encoding'}; + $encoding ||= $LJ::UNICODE ? 'utf-8' : 'iso-8859-1'; + + if ($LJ::UNICODE && lc($encoding) ne "utf-8" && + ! Unicode::MapUTF8::utf8_supported_charset($encoding)) { + push @errors, $ML{'.error.encoding'}; + } + + if (@errors) { + return LJ::bad_input(@errors); + } + + # from now on, we manage our own output + BML::suppress_headers(); + BML::suppress_content(); + + my $opts = {}; # information needed by printing routines + + ##### figure out what fields we're exporting + + my @fields; + foreach my $f (qw(itemid eventtime logtime subject event security allowmask)) { + if ($POST{"field_${f}"}) { + push @fields, $f; + } + } + + if ($POST{'field_currents'}) { + push @fields, ("current_music", "current_mood"); + $opts->{'currents'} = 1; + } + + #### do file-format specific initialization + + if ($POST{'format'} eq "csv") { + $opts->{'format'} = "csv"; + $r->content_type("text/plain"); + $r->send_http_header(); + if ($POST{'header'}) { + $r->print(join(",",@fields) . "\n"); + } + } + if ($POST{'format'} eq "xml") { + $opts->{'format'} = "xml"; + my $lenc = lc($encoding); + $r->content_type("text/xml; charset=$lenc"); + $r->send_http_header(); + $r->print("\n"); + $r->print("\n"); + } + + $opts->{'fields'} = \@fields; + $opts->{'encoding'} = $encoding; + $opts->{'notranslation'} = 1 + if $POST{'notranslation'}; + + $sth = $dbcr->prepare("SELECT jitemid, anum, eventtime, logtime, security, allowmask FROM log2 ". + "WHERE journalid=$u->{'userid'} AND year=$year AND month=$month"); + $sth->execute; + if ($dbcr->err) { $r->print($dbcr->errstr); return; } + my @buffer; + while ($_ = $sth->fetchrow_hashref) { + $_->{'ritemid'} = $_->{'jitemid'} || $_->{'itemid'}; + $_->{'itemid'} = $_->{'jitemid'} * 256 + $_->{'anum'} if $_->{'jitemid'}; + push @buffer, $_; + if (@buffer == 20) { + load_and_dump_buffer($u, \@buffer, $opts); + @buffer = (); + } + + } + load_and_dump_buffer($u, \@buffer, $opts); + + if ($opts->{'format'} eq "xml") { + $r->print("\n"); + } + return; + + sub load_and_dump_buffer + { + my ($u, $buf, $opts) = @_; + my $lt; + my %props; + my @ids = map { $_->{'ritemid'} } @{$buf}; + + # TODO: use fill_items_with_text_props($buf, $u); + # this need valid $buf->{'itemid'}, but no extra fields in dump_entry($e) ... + + $lt = LJ::get_logtext2($u, @ids); + LJ::load_log_props2($dbcr, $u->{'userid'}, \@ids, \%props); + + foreach my $e (@{$buf}) { + $e->{'subject'} = $lt->{$e->{'ritemid'}}->[0]; + $e->{'event'} = $lt->{$e->{'ritemid'}}->[1]; + + my $eprops = $props{$e->{'ritemid'}}; + + # convert to UTF-8 if necessary + if ($LJ::UNICODE && $eprops->{'unknown8bit'} && !$opts->{'notranslation'}) { + my $error; + $e->{'subject'} = LJ::text_convert($e->{'subject'}, $u, \$error); + $e->{'event'} = LJ::text_convert($e->{'event'}, $u, \$error); + foreach (keys %{$eprops}) { + $eprops->{$_} = LJ::text_convert($eprops->{$_}, $u, \$error); + } + } + + if ($opts->{'currents'}) { + $e->{'current_music'} = $eprops->{'current_music'}; + $e->{'current_mood'} = $eprops->{'current_mood'}; + if ($eprops->{'current_moodid'}) { + my $mood = LJ::mood_name($eprops->{'current_moodid'}) + if $eprops->{'current_moodid'}; + $e->{'current_mood'} = $mood if $mood; + } + } + + my $entry = dump_entry($e, $opts); + + # now translate this to the chosen encoding but only if this is a + # Unicode environment. In a pre-Unicode environment the chosen encoding + # is merely a label. + + if ($LJ::UNICODE && lc($opts->{'encoding'}) ne 'utf-8' && !$opts->{'notranslation'}) { + $entry = Unicode::MapUTF8::from_utf8({-string=>$entry, + -charset=>$opts->{'encoding'}}); + } + + $r->print($entry); + } + } + + sub dump_entry + { + my $e = shift; + my $opts = shift; + my $format = $opts->{'format'}; + my $entry = ""; + + my @vals = (); + if ($format eq "xml") { + $entry .= "\n"; + } + + foreach my $f (@{$opts->{'fields'}}) + { + my $v = $e->{$f}; + if ($format eq "csv") { + if ($v =~ /[\"\n\,]/) { + $v =~ s/\"/\"\"/g; + $v = "\"$v\""; + } + } + if ($format eq "xml") { + $v = LJ::exml($v); + } + push @vals, $v; + } + if ($format eq "csv") { + $entry .= join(",", @vals) . "\n"; + } + if ($format eq "xml") { + foreach my $f (@{$opts->{'fields'}}) { + my $v = shift @vals; + $entry .= "<$f>" . $v . "\n"; + } + $entry .= "\n"; + } + return $entry; + } + + +_code?> + _c?> diff --git a/local/htdocs/favicon-misha.ico b/local/htdocs/favicon-misha.ico new file mode 100755 index 0000000000000000000000000000000000000000..30c813bcc9897e75034ec85d9d229996dde48acd GIT binary patch literal 1078 zcmZvbJ%|%g6ot>^7X>HTR*;0iO2ldztSlx%lvHAoSESi2s2f2L3pF;nqlRVED#2f{ z5Q_y1iNdObkRZsiW;-h}5?BVTk~9kmgn6Es$2#G~p%POjqVzKt`fEIyf^p`nG%?XOS* zCRUbPc+ot-?Ynn4q>PvC(fqJ($K}ZHLpNr1;Uq#8edNSkx{X|_4JyH z^$Oh^m20OnfO>Pi{*j1M#3UjViDw-|rnKh9kQdx{E^@ zMl(U_)CR@k2h=ypIj1C*p(f{K@C+9{?m4aWAj}`IpS@y98Ko=IJ+IyGP4YhKZ{Ofn ztAn4v+MM^!Jx?fq7L8k+Q@h=+-%$@V&Ck$2%(1Fz=KEQJD$bhb&i!e^>XOS-R#$D) z&z2Z2)Q3I+^ zbr6*e%AkO#4aE4DC3wyCK5uV>x3|GIgQZ?cjAaQ*r#6_A(wW={a+j!-{TMgarThn0 CbNr0} literal 0 HcmV?d00001 diff --git a/local/htdocs/favicon-petya.ico b/local/htdocs/favicon-petya.ico new file mode 100755 index 0000000000000000000000000000000000000000..62dcf2918abfde76be30360f547aa74bb2abe16e GIT binary patch literal 5222 zcmd5<&2Jk;6n{%9<$@INDfP)dA^r>Z#9zXpClrgrB0dyX0#RBO*#ZIEMtlf_+EWw` zD3vN$6jAY!fb-qoj-+OOnJ+U2U?KKkPc{}sw{pR=HzS*5w69sgR zN~IEUc|IU|0j*W(;tbJC7^_y*{^%K^y>qNHn&{@UMBmI}9{P-^LYQxKX%L}OqoED1 z=u(m-XxU(-k}=$a;KxIJkrIT`grT(I<(Ih)!YJYp!dCPO+Muj$7`GS}l;d)Y7HZro z_0+nkG#`nT!ss!qMCHm8;SO4LRxwXhGF?QGa3sbY2gV#hx{!3nm<}YFHKs8Ka|Kd^ zEDF?I!jv`0$vmAG>Oz+VBCR7>GK}9j4bPa@Uw!Sp@BUocGx1O9NPd8usPA68e0|?s z|Ha(c#u8z0Xi+c#&1-K)AMKfs@0-@`gH!MsnDM~8edV1ipMU+vTUUqS`@p~_QhDM4 zeh{1zX>Cpe41SFnY)XqO`U@wM0(F6(cxwV6brpSB`wB*yz{?cwj|5{bFde|~%%KP# zQ&2HJv?$(Aab8XXD?@LJ(2fRYQvlOCGz>c^?^%N*?|aYiuH}8ts^Gc+`S155I2l%g zu;dK~*seSsny15fes!g155ub{y61oc=2etT56dmz9$;5vyQ2@wG21U$9cHnwSRH1u zTX$@ZB^-@b%z)S}PtAa|)V(vuI{i#DGkLS;5i5qW*-_}5gZZe=4y>6%)}dP8yt!jS zW)}T17+q$<*8HOJ5*x&!F;D8w%%?)dM7=!YJP19r92?%UAR&k*o6Y&bQfQjwDsPuD zzw1+);^}NaXvQ2vjv!r{H7TS6NgxfH!`nD_3^^jIbct#y(P9UiMnVD1Gmu$^Kq`e1c8xcnNqB_|SoFLLXS zZ$Xh`@%NE;&f=e#JeBj=^5eTnbK+km{`~xYKN^nL2qB5&m%ZdzVajQ5VG{C*AID zFMqkc|KR8Kb;%EI0WPLS4i{$W)2-e6?X8_}S64C@eQ%Je?m0&cc}kPX>(7Dz?ppF| zduwxNf8~o09ZCPPy78RkHaXzOM7Y@8-d*3=*xJ4KAi$@3h@N)3S!{yK3 zFA%v)lAOrOuP$^sup-kSw^_0elH5h+MOJgH1^7X>HTR*;0iO2ldztSlx%lvHAoSESi2s2f2L3pF;nqlRVED#2f{ z5Q_y1iNdObkRZsiW;-h}5?BVTk~9kmgn6Es$2#G~p%POjqVzKt`fEIyf^p`nG%?XOS* zCRUbPc+ot-?Ynn4q>PvC(fqJ($K}ZHLpNr1;Uq#8edNSkx{X|_4JyH z^$Oh^m20OnfO>Pi{*j1M#3UjViDw-|rnKh9kQdx{E^@ zMl(U_)CR@k2h=ypIj1C*p(f{K@C+9{?m4aWAj}`IpS@y98Ko=IJ+IyGP4YhKZ{Ofn ztAn4v+MM^!Jx?fq7L8k+Q@h=+-%$@V&Ck$2%(1Fz=KEQJD$bhb&i!e^>XOS-R#$D) z&z2Z2)Q3I+^ zbr6*e%AkO#4aE4DC3wyCK5uV>x3|GIgQZ?cjAaQ*r#6_A(wW={a+j!-{TMgarThn0 CbNr0} literal 0 HcmV?d00001 diff --git a/local/htdocs/friends/pipiskomer.bml b/local/htdocs/friends/pipiskomer.bml new file mode 100755 index 0000000..aef4263 --- /dev/null +++ b/local/htdocs/friends/pipiskomer.bml @@ -0,0 +1,65 @@ + +body<= + $LIMIT; + + my $fus = LJ::load_userids(@ids); + @ids = grep { $fus->{$_}{journaltype} eq "P" } @ids; + + my %count; + + my $MAX_DELAY = 4; + + my $start = time(); + while (@ids && time() < $start + $MAX_DELAY) { + my $fid = shift @ids; + my $fr = LJ::get_friends($fid); + next unless $fr; + $count{$_}++ foreach (keys %$fr); + } + + my @pop = sort { $count{$b} <=> $count{$a} } keys %count; + + my $ret = ""; + + my $rows; + my $MAX_DISPLAY = 150; + my $shown; + foreach my $popid (@pop) { + last if ++$shown > $MAX_DISPLAY; + my $u = LJ::load_userid($popid); + my $count = $count{$popid}; + $rows .= "" . LJ::ljuser($u) . " - " + . LJ::ehtml($u->{name}) . + "$count\n"; + } + + if ($rows) { + $ret .= "\n"; + $ret .= + "\n"; + $ret .= $rows; + $ret .= "
    $ML{'.user'}$ML{'.count'}
    \n"; + + $ret .= $GET{'own'} ? "" : ""; + + } + return $ret; +} +_code?> +<=body +page?> + diff --git a/local/htdocs/friends/popwithfriends.bml b/local/htdocs/friends/popwithfriends.bml new file mode 100755 index 0000000..0d8a3bc --- /dev/null +++ b/local/htdocs/friends/popwithfriends.bml @@ -0,0 +1,96 @@ + +body<= + $LIMIT; + + my $fus = LJ::load_userids(@ids); + @ids = grep { $fus->{$_}{journaltype} eq "P" } @ids; + + my %count; + + my $MAX_DELAY = 4; + + my $start = time(); + while (@ids && time() < $start + $MAX_DELAY) { + my $fid = shift @ids; + + my $fr = LJ::get_friends($fid); + next unless $fr; + $count{$_}++ foreach (keys %$fr); + } + + my @pop = sort { $count{$b} <=> $count{$a} } keys %count; + + my $ret = $GET{'own'} ? "" : ""; + + my $rows; + my $MAX_DISPLAY = 50; + my $shown; + foreach my $popid (@pop) { + next if $fr->{$popid} && ! $GET{'own'}; + last if ++$shown > $MAX_DISPLAY; + my $u = LJ::load_userid($popid); + my $count = $count{$popid}; + $rows .= "" . LJ::ljuser($u) . " - " + . LJ::ehtml($u->{name}) . + "$count\n"; + } + + if ($rows) { + $ret .= "\n"; + $ret .= + "\n"; + $ret .= $rows; + $ret .= "
    $ML{'.user'}$ML{'.count'}
    \n"; + + $ret .= $GET{'own'} ? "" : ""; + + } else { + $ret .= "
    $ML{'.no_users'}
    \n"; + + $ret .= "" unless $GET{'own'}; + } + + return $ret; +} +_code?> +<=body +page?> + diff --git a/local/htdocs/go.bml b/local/htdocs/go.bml new file mode 100755 index 0000000..040f4d7 --- /dev/null +++ b/local/htdocs/go.bml @@ -0,0 +1,67 @@ + +body=> +page?> diff --git a/local/htdocs/guidelines.html b/local/htdocs/guidelines.html new file mode 100755 index 0000000..8f35a8b --- /dev/null +++ b/local/htdocs/guidelines.html @@ -0,0 +1,97 @@ + Guidelines + + +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    +

    òÕËÏ×ÏÄÑÝÉÅ ÐÒÉÎÃÉÐÙ LJR (lj.rossia.org).

    + +

    äÅËÌÁÒÁÃÉÑ ÎÁÍÅÒÅÎÉÊ

    + + +
      +
    • LJR - ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÐÒÏÅËÔ, ÓÏÚÄÁÎÎÙÊ ÄÌÑ ÐÏÄÄÅÒÖËÉ +Ó×ÏÂÏÄÙ ÓÌÏ×Á, ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ.

      + +

    • LJR - ÐÒÏÓÔÒÁÎÓÔ×Ï, Ó×ÏÂÏÄÎÏÅ ÏÔ ÃÅÎÚÕÒÙ. +ðÏÌÉÔÉÞÅÓËÁÑ, ÜÓÔÅÔÉÞÅÓËÁÑ É ËÁËÁÑ-ÌÉÂÏ ÄÒÕÇÁÑ +ÃÅÎÚÕÒÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ. ðÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÄÎÅ×ÎÉË - +ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÐÏÌØÚÏ×ÁÔÅÌÑ, ÏÇÒÁÎÉÞÉ×ÁÔØ +ÅÇÏ × ×ÙÓËÁÚÙ×ÁÎÉÉ Ó×ÏÉÈ ÍÙÓÌÅÊ × ÄÎÅ×ÎÉËÅ ÔÁË ÖÅ +ÇÌÕÐÏ (É ÇÁÄËÏ), ËÁË ÏÇÒÁÎÉÞÉ×ÁÔØ ËÕÈÏÎÎÙÅ +ÒÁÚÇÏ×ÏÒÙ, ÁÎÅËÄÏÔÙ É ÌÉÞÎÕÀ ÐÅÒÅÐÉÓËÕ. åÓÌÉ +×ÁÍ ÎÅ ÎÒÁ×ÉÔÓÑ, ÞÔÏ ÐÉÛÅÔ ÔÁËÏÊ-ÔÏ ÐÏÌØÚÏ×ÁÔÅÌØ, +ÎÅ ÞÉÔÁÊÔÅ ÅÇÏ.

      + + +

    • LJR - ÐÒÏÓÔÒÁÎÓÔ×Ï, Ó×ÏÂÏÄÎÏÅ ÏÔ ÍÅÒÉÔÏËÒÁÔÉÉ. +îÅ ÐÒÅÄÏÓÔÁ×ÌÑÅÔÓÑ ÎÉËÁËÉÈ ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÈ +ÐÒÅÉÍÕÝÅÓÔ× ÚÁÓÌÕÖÅÎÎÏÍÕ ÂÌÏÇÇÅÒÕ × ÓÒÁ×ÎÅÎÉÉ +Ó ÎÏ×ÉÞËÏÍ. úÁÓÌÕÖÅÎÎÏÍÕ ÂÌÏÇÇÅÒÕ ÄÏÓÔÁÔÏÞÎÏ +ÐÒÅÉÍÕÝÅÓÔ×, ÐÒÅÄÏÓÔÁ×ÌÅÎÎÙÈ ÚÁÓÌÕÖÅÎÎÏÓÔØÀ.

      + + +

    • LJR +ÔÏÔÁÌØÎÏ ÐÏÄÏÔÞÅÔÅÎ ÐÕÂÌÉËÅ. ÷ÓÅ ÖÁÌÏÂÙ ÎÁÞÁÌØÓÔ×Õ, +ÒÁ×ÎÏ ËÁË É ÒÅÛÅÎÉÑ ÐÏ ÐÒÉÏÓÔÁÎÏ×ËÅ ÔÅÈ ÉÌÉ ÉÎÙÈ ÖÕÒÎÁÌÏ× +ÄÏÌÖÎÙ ÂÙÔØ ÏÂÑÚÁÔÅÌØÎÏ ÏÐÕÂÌÉËÏ×ÁÎÙ.

      + + +

    • ïÓÎÏ×ÎÙÍ ÓÏÄÅÒÖÁÎÉÅÍ ÓÅÒ×ÅÒÁ Ñ×ÌÑÅÔÓÑ +ËÏÎÔÅÎÔ, ÓÏÚÄÁÎÎÙÊ ÐÏÌØÚÏ×ÁÔÅÌÑÍÉ. âÁÎÎÅÒÎÁÑ ÒÅËÌÁÍÁ, +ÐÒÏÄÁÖÁ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ Å-ÍÜÊÌÏ×, ÎÁ×ÑÚÙ×ÁÎÉÅ +ËÏÍÍÅÒÞÅÓËÉÈ ÕÓÌÕÇ ÁÂÓÏÌÀÔÎÏ ÎÅÄÏÐÕÓÔÉÍÙ × LJR.

      + + +

    • âÅÓÐÌÁÔÎÙÊ ÐÏÌØÚÏ×ÁÔÅÌØ ÉÍÅÅÔ ÓÔÏÌØËÏ ÖÅ ÐÒÁ×, +ÓËÏÌØËÏ ÐÌÁÔÎÙÊ; ÏÓÎÏ×ÎÙÅ ÆÕÎËÃÉÏÎÁÌØÎÙÅ ×ÏÚÍÏÖÎÏÓÔÉ +ÓÅÒ×ÉÓÁ ÄÏÓÔÕÐÎÙ ÉÍ × ÒÁ×ÎÏÊ ÓÔÅÐÅÎÉ. +

      + + +

    • úÁËÒÙÔÉÅ ÄÎÅ×ÎÉËÏ× - ËÒÁÊÎÑÑ ÍÅÒÁ, É ÂÅÚ +ËÒÁÊÎÅÊ ÎÅÏÂÈÏÄÉÍÏÓÔÉ Ë ÎÅÊ ÐÒÉÂÅÇÁÔØ ÎÅ ÂÕÄÕÔ. +ìÀÂÏÍÕ ÐÏÌØÚÏ×ÁÔÅÌÀ (× ÔÏÍ ÞÉÓÌÅ É ÚÁËÒÙÔÏÍÕ) ÂÕÄÅÔ +ÐÏ ÐÅÒ×ÏÍÕ ÔÒÅÂÏ×ÁÎÉÀ ×ÙÄÁÎ ÁÒÈÉ× ÅÇÏ ÓÏÏÂÝÅÎÉÊ, +× ÍÁËÓÉÍÁÌØÎÏ ÕÄÏÂÏÞÉÔÁÅÍÏÍ ×ÉÄÅ. ðÏÌØÚÏ×ÁÔÅÌØ +ÉÍÅÅÔ ÐÒÁ×Ï ÁÐÅÌÌÑÃÉÉ +Ë ðÏÐÅÞÉÔÅÌØÓËÏÍÕ óÏ×ÅÔÕ, +× ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ.

      + + +

    • íÙ (ÁÄÍÉÎÉÓÔÒÁÃÉÑ LJR) +ÏÂÑÚÕÅÍÓÑ ÓÏÈÒÁÎÑÔØ ÞÁÓÔÎÙÊ ÈÁÒÁËÔÅÒ +ÞÁÓÔÎÏÊ (ÚÁËÒÙÔÏÊ) ÉÎÆÏÒÍÁÃÉÉ, ×ÙÌÏÖÅÎÎÏÊ ÎÁ ÓÅÒ×ÅÒ +(ËÒÏÍÅ ÓÌÕÞÁÅ×, ÐÒÅÄÕÓÍÏÔÒÅÎÎÙÈ ÚÁËÏÎÏÍ òæ É ÓÔÒÁÎÙ +ÐÒÏÖÉ×ÁÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÑ). ôÁËÖÅ ÍÙ ÏÂÑÚÕÅÍÓÑ +ÌÀÂÏÊ ÃÅÎÏÊ (É ÎÅÓÍÏÔÒÑ ÎÁ ÕÂÙÔÏÞÎÏÓÔØ ÐÒÏÅËÔÁ) +ÐÏÄÄÅÒÖÉ×ÁÔØ ÓÅÒ×ÅÒ × ÒÁÂÏÞÅÍ ÓÏÓÔÏÑÎÉÉ.

      + +

    • LJR - ÐÒÏÅËÔ, ÐÏÓÔÒÏÅÎÎÙÊ ÎÁ ÐÒÉÎÃÉÐÁÈ +Ó×ÏÂÏÄÎÏÇÏ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ. ÷ÓÅ ÒÁÚÒÁÂÏÔËÉ, +×ÅÄÕÝÉÅÓÑ × ÒÁÍËÁÈ LJR, ÏÐÕÂÌÉËÏ×ÁÎÙ ÐÏÄ Ó×ÏÂÏÄÎÏÊ +ÌÉÃÅÎÚÉÅÊ (GPL É ÅÅ ÁÎÁÌÏÇÁÍÉ) É ÄÏÓÔÕÐÎÙ ÄÌÑ +ÉÓÐÏÌØÚÏ×ÁÎÉÑ.

      + +

    • ÷ ÓÌÕÞÁÅ ÚÌÏÓÔÎÏÇÏ ÎÁÒÕÛÅÎÉÑ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ ÉÚÌÏÖÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ×, ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ×ÐÒÁ×Å × ÌÀÂÏÊ ÍÏÍÅÎÔ +ÚÁÂÒÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ É ×ÓÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ LJR +É ÐÏÄÎÑÔØ LJR ÎÁ ÎÏ×ÏÍ ÓÅÒ×ÅÒÅ. + + +
    +
    +
    +ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    \ No newline at end of file diff --git a/local/htdocs/img/blue_check.gif b/local/htdocs/img/blue_check.gif new file mode 100755 index 0000000000000000000000000000000000000000..5ce3be02d42bc85e7af27d66b4eb038618d61782 GIT binary patch literal 160 zcmZ?wbhEHb8X6h_5)u;_7z_*y92^`LNJt#u5ct8t z5fKqlQBlzV1T75{rc78cXU2&$CoY^h@Zipg4{vV#`11p75*9)SBnGmJfpzHv)xMNW zr|V1B<=kGBXT$r2>-5_LJY~DwS`!qvzy8ZLZAq%f;2J*iNG+21b5< zMh1pSjhf61Ok7;E7AQU$c~pd&46371gWPu&-Oh&Be~3FV4)$#>B+J!N76y S)V`Gh=gwcacu7E!!5RRdpkey} literal 0 HcmV?d00001 diff --git a/local/htdocs/img/btn_edit.gif b/local/htdocs/img/btn_edit.gif new file mode 100755 index 0000000000000000000000000000000000000000..27c8e8b9658cc042084b759729b32770a8993a82 GIT binary patch literal 444 zcmZ?wbhEHb6k`x!SZdA?#lW4yAd$i$nIoWBBcNU*VUVq;-y)&ks%X)xXj*M(->Ydk zRnxZG(y_%UXs%^owRcdDS7c38@|2*YZBDUUy@4pcB_+2vIpdgD{MO*C>gwvAlJa9w zIme<3&qbBCw6yfJ*7WqWoXctM>FK$aQ+F+=;aW-ey^`+d)xGblr)^!<`*;54zw@{L zTekY&vaR>_O*wY#*z@C4znz=+_w4+?*XIAdJO4j!p!kp3$18|IhXDvcUSeRobzpXZ zhmMrv_8CPdbIcsg(-Nc#tQ@zeIy7bato6CzD>)%XZTk!bhOnl*QwNSJ_So<>n!Q-Y zqcMe9PEVJEF+suHi;>Zgi$_*RAIJ?;F!yF;;*I}c)dt&hd>5| Rxf_Cq>+Gx;%hUT{~um+W@Z|L zfWng(OV<=cHoF-x2ncX1m_`~{+9~q(wwQCsdYqYQJagtupcbq^@h1x-NJ0lhfb3*o zU8kVXmy$Uz!;8(MdS$YJ#I%F^44iHoF)_D4Xnfwx%5tLl&4%``Gy=aB;RNg+;J6F-+j(=j5BG#F56*#~?Iu;>tXZNTv`LC83pbS1;h69_gdB fVn1Kr8e=wY*FF4vtAtb;9nUNCw_Z_FWUvMRqa#?| literal 0 HcmV?d00001 diff --git a/local/htdocs/img/community.gif b/local/htdocs/img/community.gif new file mode 100755 index 0000000000000000000000000000000000000000..e236a8b30bc9928e3c3cdf45f1eef22f02ee450b GIT binary patch literal 271 zcmZ?wbhEHb6krfwXc1um0!AQaW=LaTPh(_HXXH>&luu{kNN3{AVB!oCm($eNn8F}1 zl|j(a$>A2WM14cu+_}pyo;dj9&HevG0L7myj9d)z3_2j2Kz1^)_B>GUOUaz~V*8pm zRZ^2obT4o5@!shYWUIUNXo_Q$i^@LNT*Jr-VuGFL1B`ummbkh+ioPN?nKe^z;tw&X z64R4ON|7F7s_iLCg+3~LLVRl60>T2^KqSDe!Zd+NU?LOy6nO^DS-kAL^LQCpc{$nS dIp_28@ba%=Wai-Il%F-9X9Xi8%REH}YXFd$VblNs literal 0 HcmV?d00001 diff --git a/local/htdocs/img/imported-profile.gif b/local/htdocs/img/imported-profile.gif new file mode 100755 index 0000000000000000000000000000000000000000..5037f65973f8edd789be14aa102b7e3bd8b1f450 GIT binary patch literal 955 zcmV;s14R5sNk%w1VG#fk0QUd@000010RaL60s{jB1Ox;H1qB8M1_uWR2nYxX2?+`c z3JVJh3=9kn4Gj(s4i66x5D*X%5fKs+5)%^>6ciK{6%`g178e&67#J8C85tTH8XFrM z92^`S9UUGX9v>ecARr(iAt53nA|oRsBqSsyB_$>%CMPE+C@3f?DJd!{Dl021EG#T7 zEiEoCE-x=HFfcGNF)=bSGBYzXG&D3dH8nOiHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}? zK0iM{KtMo2K|w-7LPJACL_|bIMMXwNMn^|SNJvOYNl8jdN=r*iOiWBoO-)WtPESuy zP*6}&QBhJ-Qd3h?R8&+|RaI72R##V7SXfwDSy@_IT3cINTwGjTU0q&YUSD5dU|?Wj zVPRroVq;@tWMpJzWo2e&W@l$-XlQ6@X=!R|YHMq2Y;0_8ZEbFDZf|dIaBy&OadC2T za&vQYbaZreb#-=jc6WDoczAeud3kzzdV70&e0+R;eSLm@et&;|fPjF3fq{a8f`fyD zgoK2Jg@uNOhKGlTh=_=ZiHVAeii?YjjEszpjg5|uj*pLzkdTm(k&%*;l9Q8@l$4Z} zm6ev3mY0{8n3$NEnVFiJnwy)OoSdAUot>VZo}ZteprD|kp`oIpqNAguq@<*!rKP5( zrl+T;sHmu^si~@}s;jH3tgNi9t*x%EuCK4Ju&}VPv9YqUva_?Zw6wIfwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~A^8LW00930EC2ui01*HY000P>0RIUbNU)$mfh`iYI9RZSF=y}IEoAtw z1t(+g;6WfGc6b dfC+PjDcTk#Jb3s(13--$Gy>PK>(gLB06TSj!wLWZ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/accomplished.gif b/local/htdocs/img/mood/bitospud/courier/black/accomplished.gif new file mode 100755 index 0000000000000000000000000000000000000000..3015d5b5572933161234c9ef20027495079a2eac GIT binary patch literal 108 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{1{F{VPwuDnl|$se_H+RAODv<6>B1OJAAaJdoFsTac63s^|G&BXS24) J_%bqB0|3&gD?b1L literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/amused.gif b/local/htdocs/img/mood/bitospud/courier/black/amused.gif new file mode 100755 index 0000000000000000000000000000000000000000..5f6544e4b1b6999e35ac79a1eba7a24239e0d62d GIT binary patch literal 102 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{18?{VPwu0r5dH3`|Zv{VPwu0r5dH3`{OP{VPwu0r5dH3{1v7{VPwulok?$^0Cn|^Mt_9KfvcKB$Cvocr%0ENFJzW@LL literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/artistic.gif b/local/htdocs/img/mood/bitospud/courier/black/artistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..f27793699b3d387af2a64eac7253a0ee1a25b2d9 GIT binary patch literal 129 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3``L{{VPwuDnl|$se_H+R#=h5A3k0r5dH3`|Zv{VPwu|bJaTcRfigRPL*^&{}so$bUyRBygiFPc9?Jqo}TsoW{BP7E33YCoz2?b I!Ngz<0M&OaQvd(} literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/bitchy.gif b/local/htdocs/img/mood/bitospud/courier/black/bitchy.gif new file mode 100755 index 0000000000000000000000000000000000000000..27ce66c212b0004b528c94ce1e9f286535308b41 GIT binary patch literal 115 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`|}<{VPwuja`g7legAB|8k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/blank.gif b/local/htdocs/img/mood/bitospud/courier/black/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..1507548d9655643281ee233f1b21761289942b90 GIT binary patch literal 89 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`_<+{VPwuM0{{$BA?5%8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/bouncy.gif b/local/htdocs/img/mood/bitospud/courier/black/bouncy.gif new file mode 100755 index 0000000000000000000000000000000000000000..baff3f61364f3f188f40a257c3fa09584463c642 GIT binary patch literal 113 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3``z9{VPwu+M{-jQVc>Qwu-;RF;jO|MDD{>#>}x N35MK!-Oa2F)&Q1)E8_qF literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/busy.gif b/local/htdocs/img/mood/bitospud/courier/black/busy.gif new file mode 100755 index 0000000000000000000000000000000000000000..54927d3f80442200833fb49d170c85f27dd42af4 GIT binary patch literal 109 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`{OP{VPwuja`g7legABS7A7=z|XQPVtrzk84uTF+qs`Pd(YK)uKe0{Hf#GG Jy+sTR)&QwMDGLAq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/calm.gif b/local/htdocs/img/mood/bitospud/courier/black/calm.gif new file mode 100755 index 0000000000000000000000000000000000000000..fb5d706657b8a3759f1cf9f50853d7a3b0192a9e GIT binary patch literal 104 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{3Vt{VPwuGDsKd)XbM|^Izq0D9l_mp& FH2_~?DX;(l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/cold.gif b/local/htdocs/img/mood/bitospud/courier/black/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..db1a823cc19ece18e40b2aaa16bfd58186275bff GIT binary patch literal 107 zcmV-x0F?hnNk%w1VJHA70Du4h013wb|NkNR1OWg50RSuj0000e04M+e0z!f?BaVz%nhC0|N20r5dH3{2iV{VPwu_?!(h|O#$)facV}mHy*>T?-}&sfO&g^@bogiq9+UJ{f91INV5DDGY1q~v Rt%4mq-N&DN+Qh(M4FHsSFlzt+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/confused.gif b/local/htdocs/img/mood/bitospud/courier/black/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..87975dab84d08de5d0d0a9a080b36dbb351b9f80 GIT binary patch literal 109 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`{OP{VPwu|bJaTcRfigRPL*^&{}so$bUyRBygiFPR*10G9^nhltTMAaFDue{Hf#Hx Jb*mT{tN{s(D(L_K literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/crazy.gif b/local/htdocs/img/mood/bitospud/courier/black/crazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..516c7e841ac70b093851e755ad33a1843a719604 GIT binary patch literal 104 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{3Vt{VPwu`7v)60+l~rH0G#MDI E0Sdt0r5dH3`~|i{VPwuaWAzw77pIP>qv$u(h!5RQgy(aVk literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/curious.gif b/local/htdocs/img/mood/bitospud/courier/black/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..6beab8292b84110a91d5fff673fa9f5be7025408 GIT binary patch literal 102 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{18?{VPwu|bJaTcRfigRPL*^&{}so$bUyRBygiFPcJK)K9$NC5v)60+l~tP=7_0&B C-6*vH literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/cynical.gif b/local/htdocs/img/mood/bitospud/courier/black/cynical.gif new file mode 100755 index 0000000000000000000000000000000000000000..9f860f63baa7f45f3cb1f9274f67f21a9c27207c GIT binary patch literal 114 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{0Lq{VPwu>|F+*&$;D3|7FLxXg%|;f<220zboa{_$*s{v*upXW_eTgrps4QiNP8G*nKUk literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/determined.gif b/local/htdocs/img/mood/bitospud/courier/black/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..a78000282278f56f4bc06b0c85bf63097bffbbca GIT binary patch literal 107 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`|Zv{VPwu>|F+*&$;D3|7FLxXg%|;f<22qcKAH2IiqIyxI}CDl~rH6&Sq`j Iz{Fq;0IiQJxc~qF literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/devious.gif b/local/htdocs/img/mood/bitospud/courier/black/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..554b71f0d3508722872203f2dca371049686aea3 GIT binary patch literal 98 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`~|i{VPwuSLdL^tFomf8LU_UiphL-Z=4Ogtyl8Gs`}6_S$hXSOWklog}0H literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/disappointed.gif b/local/htdocs/img/mood/bitospud/courier/black/disappointed.gif new file mode 100755 index 0000000000000000000000000000000000000000..1aebe7c8a520484f72d94f93dd15b64e4f71db65 GIT binary patch literal 97 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3``b1{VPwuSkf`4v1{8q?&F`Vu5YV+{%hYvombq`T0r5dH3`}M{{VPwuFScoWUH{g5dezHgkLEEvYdf;&V~3B{^fS*EGB8*J02tFKBLDyZ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/drunk.gif b/local/htdocs/img/mood/bitospud/courier/black/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..8554ef87ac4db91a82e7c70a5c49583ec46226b5 GIT binary patch literal 108 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{1{F{VPwu0r5dH3{3Vt{VPwuSkf`4v1{AA+fzR%o`0?Ld|lmP(>!C=c1N+d-xW2du2=oY+3U6Z%BrtinhXrq E06Whpq5uE@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/envious.gif b/local/htdocs/img/mood/bitospud/courier/black/envious.gif new file mode 100755 index 0000000000000000000000000000000000000000..acab2ea801a685ee850c397f9c1f217d73ddf6e8 GIT binary patch literal 109 zcmV-z0FwVlNk%w1VJHA70Du4h0Ga^*|NkNR1OWg50RSuj0000e04M+e0z{0DsmtvT zqnxzbi?iOmdk-YxCzhlcjAyB?NZ7hZEE{x<=Q;$8J^oAGcEqC57zFl)on><6WOAIk P=kbcoYPa0(rT_ptF{&-M literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/exanimate.gif b/local/htdocs/img/mood/bitospud/courier/black/exanimate.gif new file mode 100755 index 0000000000000000000000000000000000000000..dcb4523cf81099b54418d2b3536ed5bcab6c4b2c GIT binary patch literal 91 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`|Bn{VPwuFScoWUH{hmyfNzYFMb}b_9KfvcIb#PFjxZsT|y&F literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/flirty.gif b/local/htdocs/img/mood/bitospud/courier/black/flirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..aa5144c950cee21ef53a3f2276b6ee94721f611c GIT binary patch literal 99 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`|x%{VPwuSkf`4v1{8q?(Wo_OIvL(SMIrOcTV|hl#|%TA5Kj5XO?~D?DcYGWv~VSTB0S< literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/full.gif b/local/htdocs/img/mood/bitospud/courier/black/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..54380047f48bd03765ddab6a45a602a5862b2e3c GIT binary patch literal 112 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{37l{VPwurJS&i4tpe^Bs3S5i&PCi`E-n*-SZPjrRrnIGZ N)_vzL6J=nq1^|U(EGGZ} literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/geeky.gif b/local/htdocs/img/mood/bitospud/courier/black/geeky.gif new file mode 100755 index 0000000000000000000000000000000000000000..eda020084221ac0b8b0cdbe95ac9d7d542718dca GIT binary patch literal 104 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{3Vt{VPwu0r5dH3{0*){VPwu0r5dH3`|Zv{VPwu|bJaTcRfigRPL*^&{}so$bUyRBygiFPb{zTHvUcg@9f|uEoLu#_>ulEc IlS~ZO0Q=o8h5!Hn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/good.gif b/local/htdocs/img/mood/bitospud/courier/black/good.gif new file mode 100755 index 0000000000000000000000000000000000000000..c0d277085ab27bfedf5853154c6997a870dbe901 GIT binary patch literal 108 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{1{F{VPwu#j`#?i^NY@yoPpK^vXrez1*|8?&BofETK8!Q&S@9@zIKQj4acy(34=~Z95&Sq_o JabaYz1^@(cEZYD8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/groggy.gif b/local/htdocs/img/mood/bitospud/courier/black/groggy.gif new file mode 100755 index 0000000000000000000000000000000000000000..15a22b1079648b29ab619b5d0ae52a226c2ea86e GIT binary patch literal 113 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3``z9{VPwu>|F+*&$;D3|7FLxXg%|;f<22qMtsq1KDE@>wB}gK=4blPmndz& Ov+g@LU$-tRgEauXUoEcy literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/grumpy.gif b/local/htdocs/img/mood/bitospud/courier/black/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..fd6b00ab914621854ffb2599160f02c9fc46f91b GIT binary patch literal 112 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{37l{VPwu0r5dH3`{0H{VPwuv>bG@|Y!OByw6Z5&b+K(*y*x{o!eFhVQH2}(YCDQ-^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/horny.gif b/local/htdocs/img/mood/bitospud/courier/black/horny.gif new file mode 100755 index 0000000000000000000000000000000000000000..12d2260b5e213a78a8f72317c60eabd8380264bf GIT binary patch literal 108 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{1{F{VPwukALEr^0m7C^_lPg_}^S0r5dH3`{mX{VPwuSLdL^j~pxm!F#ayYTYLCPzj6beC(>&Mf=P+3U6ZN(3W=H2}TK BC&mB( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/indescribable.gif b/local/htdocs/img/mood/bitospud/courier/black/indescribable.gif new file mode 100755 index 0000000000000000000000000000000000000000..b822c1c18d8597fb180b967fce39b4033e46b6d1 GIT binary patch literal 100 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{2KN{VPwu0r5dH3``C^{VPwu7_lpcUE0zzx$c9ee-RO71m1rr&K*GON5qRS@pH+Y!MfO FH2^rJD4hTR literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/predatory.gif b/local/htdocs/img/mood/bitospud/courier/black/predatory.gif new file mode 100755 index 0000000000000000000000000000000000000000..cec791dbe33dc89eb538085d8bafe9b7d681078c GIT binary patch literal 109 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`{OP{VPwuZ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/restless.gif b/local/htdocs/img/mood/bitospud/courier/black/restless.gif new file mode 100755 index 0000000000000000000000000000000000000000..97b6047be2ba240a6d25f8a268dcb4414927b68d GIT binary patch literal 112 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{37l{VPwu+M{-jQVc>0r5dH3`}M{{VPwuSLdLuKRHH|5(@c^VVk0_9KfvcKB#bKeKEh1A{dH0r5dH3{0*){VPwu)(8t7u0>0@8srccWHgcQKC3;>yzb~IeN7_Q$Kc{&Dwrv Kop~?=gEautKq?{t literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/sick.gif b/local/htdocs/img/mood/bitospud/courier/black/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..4d04658c88e83a4241ca13fa12834f4651f19ec9 GIT binary patch literal 101 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`{mX{VPwu4JG1OFXRp`tE2)eO)&R-{ BD8m2% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/sleepy.gif b/local/htdocs/img/mood/bitospud/courier/black/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..44e45b1b6c187ca399c0d86c1a7115c0158def2c GIT binary patch literal 123 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3`{{i{VPwu(HT4f7J8ra1hX0r5dH3{0*){VPwu0r5dH3{18?{VPwuja`g7legAB|80r5dH3{2KN{VPwu0r5dH3`~(d{VPwuXhDskJ}t&PJio--dgld{MDnv8smj*89J#Q^OtblO!>M%B5T$4S)Z1L gxtFh=TO)jbBe!?jjPuK6&hYl1e*Wdx5(Wlq08j-u2><{9 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/black/worried.gif b/local/htdocs/img/mood/bitospud/courier/black/worried.gif new file mode 100755 index 0000000000000000000000000000000000000000..2ede9062cbca3e22564f8bbe866de49e947d439f GIT binary patch literal 96 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ycfU|?j>0r5dH3{2)d{VPwuSLdLybEUDOI+8y$LrD2s;!GYcKB#bKeOy|1OtOL00;3Vc>n+a literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/accomplished.gif b/local/htdocs/img/mood/bitospud/courier/red/accomplished.gif new file mode 100755 index 0000000000000000000000000000000000000000..cf27f9240d8c6d0071d2be6d3c3ab4a4d5085290 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mBI zJg2Z5rsqR|;o^i5E=M|qguQw&f~;pnKoU?2Ef9}%aH+asDh^p;kceqA4db9yP!yX7 zB?1%w(a=_mu)}Vb7ASxYVTN4`r?47ktW23# z)xz{n2+*faXg>W1^1Ps`8>Z?hD*_f`3l}a?tRZEHJrI?#DyBTdTLne2xH&{3FcF)Z zamMaHl2qeR?1L=@B^_$Pw3SO(4KtuaW*A@z=tC`nSdyex4>r572R#<;=#kNl>BNB& IVP&ue0GOLIXaE2J literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/apathetic.gif b/local/htdocs/img/mood/bitospud/courier/red/apathetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..9c8a814b8b1942eaa540072f24ccb986c4f53946 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@n*T xJl`rP>V_EyArgU!w2Pj96dHY~g;Q9q2R#L8`OGj#Jk&Ax(^U81aUv^&H2_h*Gt&S7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/artistic.gif b/local/htdocs/img/mood/bitospud/courier/red/artistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..467db1e1a5a298870e71346900c01dda54e9784a GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@piO zc&G!@^IWQ4A(-JJ5t!uEDTonLf}&nM5*UFf5xDS32c}{!Q8gb-lktljYT*=i!-yU& zphyyC%sBz$5=rq2gGC?@qATW7*6IOT`VUPt)E(%mp#g;59XJyXrsqNCpoCN_P)!I( zq!k$A2p`TcNIcX6R2;G*03~e-tAW%U=@3#zQjFy0g;;|_6jL!&q#HBl2TFvM!5RQF C+cX0J literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/awake.gif b/local/htdocs/img/mood/bitospud/courier/red/awake.gif new file mode 100755 index 0000000000000000000000000000000000000000..9f9cc9a2238697b26f479f8e85a6f5e26d3e1e9f GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo#ZboT z9YYMC{sVcQOB9>x6#)yeg^Qr78)is_00YqpGZ0&aRJAY_(@rErA}|q)n_C4%vA7xJ ujDJ{EV|s&1B8NJF!O??}+PEKKLv4WwUlF;lPJjtGw!5RR-!826= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/bitchy.gif b/local/htdocs/img/mood/bitospud/courier/red/bitchy.gif new file mode 100755 index 0000000000000000000000000000000000000000..71115e5560f20fe80ce0c5b217641945e1d04183 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo&jrdUWBn_>+^8ija>L|`HoXS526x?%Ak zFgX5UQH>TtcvHub4yO2hk3`@?EQ&h>MX|>U)_~>|#um^k P4DbhZ_uxtPtPIuwp&2vL literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/blank.gif b/local/htdocs/img/mood/bitospud/courier/red/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..caf4b9655eb32d3136245e6995b63fe681ba2756 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@n*T oJl`rP>V_EyArgU!w2Pj9#2dZB0BbVgQXawyr+e@udsYT(09{@)(*OVf literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/bouncy.gif b/local/htdocs/img/mood/bitospud/courier/red/bouncy.gif new file mode 100755 index 0000000000000000000000000000000000000000..742e9fc827b5b1ecc07c336e6ea03cd5f2029cb4 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!AyqH>Gq{wo zSt=2@5Q}?Sg;d>$cOlUx{{woSG^0rgsa8QzERGJ52u#G{LpsNSRu3@Z{~hW;_s@|Q yPGL1HAw9zYTeMKY(IFavN!WrzP!wD0SYbeXY9(lLH;U&;F&aw%QI?Nb8LR=>iZinS literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/busy.gif b/local/htdocs/img/mood/bitospud/courier/red/busy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ee91c8d03f4e358b3b3ea56e56dda9fe2d21a28c GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo&jrdUWBn_>+^5<+~2K@z&7L2l+0R_not zIiL?09_he{%T^&#FD!~@7$p8XgsHldQ&|m5a9~(QJvD~d!%i4$*ikdJc4Gt;TJoT# LW%%u4Wv~VS%5^h? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/calm.gif b/local/htdocs/img/mood/bitospud/courier/red/calm.gif new file mode 100755 index 0000000000000000000000000000000000000000..4f05a3f2df988a69e856b0a2c03806db7c8a230b GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oVd z&xZg5@kj?oAhvP}tMy=nZ^#UT#6wsV3yFGRQLGWTkZ6;q%rHoDA|)>W5gqeBARo36 c>BA{23=)Ypc>vR0H->*m2|TL$kd?t20Er4TQ2+n{ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/cold.gif b/local/htdocs/img/mood/bitospud/courier/red/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..d5e50ffdd04b1a069a27687b95feb973a42da9cb GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{hM(zdLaJWF zilK^i literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/complacent.gif b/local/htdocs/img/mood/bitospud/courier/red/complacent.gif new file mode 100755 index 0000000000000000000000000000000000000000..59278e8c1a0f7a3a0da4d2f21264b6d195a52dc9 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu#8#NZTm z!}LxF(5FslKK&QC=tzf$;7#UU#U648yOX|T2miemGj zL|`IGaruuV)tHJw0i=Z)(mpe=1;>#VPGL1n#XS;%3o*m)NQa;(7L%s{6=OQXrIS+_ XTl!sLfIn$>qem|`qv@lDmBAVSFab40 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/confused.gif b/local/htdocs/img/mood/bitospud/courier/red/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..ffe177e96331a9e9a3a61266c925b21107c8dd6b GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo#ZboT z9YYMC{sVcQOB9>x6#)yeg^Qr78)is_00YqpGZ0&aRJAY_(@rErA}|q)n_C4%vA7xJ zjDJ{EV|s%uks~eG(v+GHW^!9$kcchpIE67|MaxG5TWUSjfz2*V?dT%i;F> E0L;2GXaE2J literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/crazy.gif b/local/htdocs/img/mood/bitospud/courier/red/crazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..cf816dcd7d5a18783d53d659dad0c15c98c06381 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oVd z&xc3^CSnQ1RzXoWngr{S4k1-7Op|?P7$iDj#O09|PGL1n#XS;%3;$tJ-61H7#po$O a)mVJk$tjF2;jAzi5^1V?@FaUy25SJ^a5O^z literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/crushed.gif b/local/htdocs/img/mood/bitospud/courier/red/crushed.gif new file mode 100755 index 0000000000000000000000000000000000000000..16acabef0aa26fe20fa6cce11a28d231e5dcdae1 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mwz z=tzr@Fc#1IXc#V}O}O+>9^ywjD336ZGyc)Whaoczu%xL&Eu6w`7^zGRD3atfFbS}m R@=(O^50<1vj2c!3YXA}zG@1Ya literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/curious.gif b/local/htdocs/img/mood/bitospud/courier/red/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..0d54b3c0278c573a01092f9c5fb5844bc83bfcf6 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo#ZboT z9YYMC{sVcQOB9>x6#)yeg^Qr78)is_00YqpGZ0&aRJAY_(@rErA}|q)n_C4%vA7xJ gjDJ{EV|s&XB3xLbWrYDow9qL@b`PFp&&ps801i$wtN;K2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/cynical.gif b/local/htdocs/img/mood/bitospud/courier/red/cynical.gif new file mode 100755 index 0000000000000000000000000000000000000000..38b666e7bf855fabb16192e646e0b82eed2a9a11 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu!T$mr1s zOu}^hkq#kMH%#w@Xap`qSNsp;c|m1to|iDh8ZKN|Luy3;R>hPDtB-~uhNA-)9cd8~ z#^z>H_W*+fi{cJ0Y$i`xfz4!~!-TQK VA*NlFh;&mPKa^OHY&$E1H2@M8HID!Q literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/determined.gif b/local/htdocs/img/mood/bitospud/courier/red/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..9b6e94025ae116146c0dea17c7d8d1062337b4f3 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu!T$Or*C z-U-w3twO3=SiB<N8NL34qGk_8Q&k0M+3#wvq^pq6=3$ZzxOB8FuF~pvxl(8zN UX&hkjAUv^m!&w8)U}dld0EMG7R{#J2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/disappointed.gif b/local/htdocs/img/mood/bitospud/courier/red/disappointed.gif new file mode 100755 index 0000000000000000000000000000000000000000..81c09eb60ce81ee841fc977533802979ffd7c4a1 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mBK ze5;_S8>Z(&Bmxr$Nw^&8pgekdutxJg8u@UB!9q-vkF;DR7RY6XsNh2klL@Ej QZpy=z3|p~U%F1930BS}w)Bpeg literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/drained.gif b/local/htdocs/img/mood/bitospud/courier/red/drained.gif new file mode 100755 index 0000000000000000000000000000000000000000..80decb908ad3b8c29bff3d4ba92f39cc923a8380 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oWq z&ujTe1STHpKo9XlErOzIJ#>zYf7oK4Qy5EH@R?zd=!B6>K;F=zx1+JS89g+KQ`1eJ LHd^RnWv~VS9ilWQ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/drunk.gif b/local/htdocs/img/mood/bitospud/courier/red/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..5ceb8202764fa9dea51390fc712e25efefdf3b27 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mBI zJg2G}7SGQJNOGb{xP$;h{745zh_`YItMy<+M#v0<#6wsVbE&#vQM@7`35&^{K*d-* zxWXXuAJ&)`CM7K>V^_QotI1duuL!`N0I@2@2p}vTBU(*2MkLTA!ijMrD}yxv(10~X literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/embarrassed.gif b/local/htdocs/img/mood/bitospud/courier/red/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..56bc376d9e95ea31eee93b57d2bb6451993c5bbc GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mBK ze5;_S8>Z(&Bmxs@6)uL@LtGha9AH)4Dx|E1#myRqi=42l68;L#;(urgQ!0O^b}mH+?% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/envious.gif b/local/htdocs/img/mood/bitospud/courier/red/envious.gif new file mode 100755 index 0000000000000000000000000000000000000000..2dc0dffec44701e85fac9199254e59940997aa2c GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{hM(FpJ^3fB=vL0>z&!j0_A+3_2hVNS=Y|-xQ6&MJ}B}s$Rp0 z(I}+Kh3Op;pidppeEJXMc>z@?Ox05~0v2Ek7baG$Ati`C5EZd1raZ(O1z54TS%f1{ z0h^m~#_m6oRO3+0f-MCpIW%C}%EZWo8PFme0$2jtp+NvklH_W^W*7FL$D$oQGP*IH KI8Y+24Aub7YcJpc literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/exanimate.gif b/local/htdocs/img/mood/bitospud/courier/red/exanimate.gif new file mode 100755 index 0000000000000000000000000000000000000000..b96e50ee8e9e5b523c8eb27bf1f899ead80e220e GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oWq y&ujTe1STHpKo9XlErOzIJ#>zYf5gZ93InXkgiCn{C!B8dNFY8qs2x$P4AuajC^UTl literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/flirty.gif b/local/htdocs/img/mood/bitospud/courier/red/flirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..227ec86ccdfda7410219388ffff9a1e302d127b4 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mBK ze5;_S8>Z(&BmxuZ94^XOJm^iW0dKgxZG%^e{#46r(yQy5D?PnltWEudRDv6(zY S14nR>m43SiPqJraum%9GEi&Z* literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/full.gif b/local/htdocs/img/mood/bitospud/courier/red/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..edda29ba54d17547a2186d330e99a9421cc99a11 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuy-$(UiV z5YzETS~!K(FubGH1N7;k4pg81qp9ax1x4L3+~E}>5txYSXj+PJ3S)ByFgX4>VZ{8A z4k2MLP*9;dsAok$5>N^)nH=fhQgy>r9J0b75z}N;12Mye2obDt7`O;~gnLcFnmUl2 Q(T(mOBsn@uu`*Z#043r!Jpcdz literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/geeky.gif b/local/htdocs/img/mood/bitospud/courier/red/geeky.gif new file mode 100755 index 0000000000000000000000000000000000000000..5c74de8e8de760d81abc8da9afdfd8c72eff2bc2 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oVl z&(APOa>5M6R!(8H9*pn}(Fk04qyrOUNW|j9R!(8eXwmYKz!t2BF#Qa321#zltGFAR Ne=wa$4-r-dYXGsaGmZcN literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/gloomy.gif b/local/htdocs/img/mood/bitospud/courier/red/gloomy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6712798ca96aaf59cc552e4adfff26125c0645f1 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo#ZboT z9YYMC{sVcQOB9>x6#)yeg^Qr78)is_00YqpGZ0&aRJAY_(@rErA}|q)n_C4%vA7xJ ojDJ{EV|s&XBAmil0@`PWK_X_@9qIsvT@Q`ZX7}Jp_N)xn0Id--RR910 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/good.gif b/local/htdocs/img/mood/bitospud/courier/red/good.gif new file mode 100755 index 0000000000000000000000000000000000000000..fae95d4a7b624921529dd902a581c9efcf8f5f16 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo&j^`e zkcjTne}RjRv~UWmVS2s?7%om2;c}!yNL33{u@BH_OvNs(oWgFHifJbjA`yt;LtyN- o3X0-z#y|A%pk-P(1PVJ)u%cRuBkVdkg=wB7y9ZCQXJxPk03B*Gd;kCd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/groggy.gif b/local/htdocs/img/mood/bitospud/courier/red/groggy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9b5c16fbd46136a2cb37e0044c6d5a4e4d4eec7 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu!T$mr1s zOu}^hkq#kMH%#w@Xap`qSNsp;c|m1to|iDh8ZKN|Luy3;R>hPDtB-~uhNA-)9cd8~ z#^z>H# z)xz{n2+*faXg>W1^1Ps`8>Z?hD*_f`3l}a?tRZEHJrI?#DyBTdTLne2xH&{3FcF)Z zamMaHl2l_;%qfh;haoczu(<;mEtrnh^3e!PI@E#TM68OvrjY7GY;K0z)eUD2ID?hJ F8UVI1GJXI6 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/happy.gif b/local/htdocs/img/mood/bitospud/courier/red/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ac3be4f6d4a8fa16a97102dfb6c8b2e1440fdf8e GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@n(_ zo)3`-OvDo6t%9O%^p1mnnC>{#A*8C+gOMnFW*8(oVM!*O!b3RWbPt|n&&ps80M-06 Ad;kCd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/horny.gif b/local/htdocs/img/mood/bitospud/courier/red/horny.gif new file mode 100755 index 0000000000000000000000000000000000000000..8d1ad2652189280b4660c92e4df1798163fbe7b1 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu#8&d>sR z@JI)$PyYojasqk22R#(Dd}bIV9zs(cxad#|r?47^Vj6~Bh(ur_mgs2}6m_FQg#E)} zH1@O*0t_HBS|%7ijxkta0;toq%t+1 T83u_?1Cs!|2T!tRWv~VSj)OHn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/hungry.gif b/local/htdocs/img/mood/bitospud/courier/red/hungry.gif new file mode 100755 index 0000000000000000000000000000000000000000..be3220b77e1b281b07378f547c2c95b7d3e668cb GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oW8 z&$kMSx?u)uh(ur_T|>N8NK_4rGc*hn{~hYUi1}6_Wv?ELL=hrkxabI`;!aLsHB7}* VRv08Y4S_V(jp6wLb2KZ1H30a)GWY-h literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/indescribable.gif b/local/htdocs/img/mood/bitospud/courier/red/indescribable.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe2b41a4b7449cc48a14124715cb13f1155f7cee GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@mwz z=tzr@Fc#1IXc#V}Z@6$_je`{dSfhtJivLmS!&V_tEMYfA!jJ?cRAvMBt($9jHG22l70ZsuniS8zx~57iBkWiUSv7RV+%YVC7U*!{Uq?0ZC4z#N|J% xj;2vsIMTu?tmcCeEj}|05)ZYYMhi5eLNFAAW3?4sF}c3zrj|jJo5RXr4FDPkG*tiq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/restless.gif b/local/htdocs/img/mood/bitospud/courier/red/restless.gif new file mode 100755 index 0000000000000000000000000000000000000000..20f0d6f2282d16bbdfe2314663808cdc9edd7c7f GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!AyuydUj7x-&$=#^_A;oBn0K(>05^@$RgEatK)id<~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/sad.gif b/local/htdocs/img/mood/bitospud/courier/red/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..57164a79457a905b26d86bd4cab28ec6bb24789a GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oW8 y&$kMSx?u)uh(uuGUdPSFiR%ggU3It4AuY;JTzSZ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/shocked.gif b/local/htdocs/img/mood/bitospud/courier/red/shocked.gif new file mode 100755 index 0000000000000000000000000000000000000000..a92d003c24fdbbea0bd4eb978deb58735537e43d GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!AyuzI&fpTo z=E4;L3$Zz#XvP0Po+ny0ZpAbU#1M(VL@YjR6%=)&LWKRpVl?)&5HiC6i#v|Aa0;to qx}yge98MVK9O)2J)xuQl12h>^u}dqbFg1LL*Mr@IC)u+ySOWmrxHOmm literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/sick.gif b/local/htdocs/img/mood/bitospud/courier/red/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..3a28e72978660c6688584c5a1e096277618f98ed GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oW0 z&mUc~2r?M8N;*c2u TSQKO0HP9m6gD2UuGFSrulX^6J literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/sleepy.gif b/local/htdocs/img/mood/bitospud/courier/red/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..011b27ac825dc0254257cf6b5f1f9dc408ac9a86 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayu!T%y0ub zej$c0k`A?S3S;_9&1Z%IOz}U2=aXDIIkAO;51B?IOa_IoD3Uu?1OP<@G3??JR`ZcS z)df_u!XWWb3qrB5+7z(sxm2}!5HV+%=+p`EY9dJ{|3fw!*+H1@Kv;(1M1+(fC|ogv cToe@KSW+1-+Ytuhv5N{)-Ge9Dvocr%00X--F8}}l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/sore.gif b/local/htdocs/img/mood/bitospud/courier/red/sore.gif new file mode 100755 index 0000000000000000000000000000000000000000..42ac7c9ad159a128220f7fc88800c6c17bf1696e GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuy-$ygDv z5YzETS~!K(dNBOuGs7V9PzS0{|A9QuC5pxK*i;8D!eR6jtnR>c8P!Bu1x4L3BP>KB zFp(rH{*j~_hhiU$kOsOe=}-%5NP`1fSPhG#XBc3K!$U2CSdyd`W~^cwNW4flrV|HB Igq6V>0HKyOVE_OC literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/thoughtful.gif b/local/htdocs/img/mood/bitospud/courier/red/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..f5994f0949605d5cd0152032f68dd9262da01663 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuzo&jrdUWBn_>+^8ija>L|`HoXS526x?%Ak iFgX5UQH>Ttv`-x?46p_V7xu8DrhB>vPqJraum%7$?=xWl literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/red/tired.gif b/local/htdocs/img/mood/bitospud/courier/red/tired.gif new file mode 100755 index 0000000000000000000000000000000000000000..0abd727ae01969f5546ca0f733500c0d0006f477 GIT binary patch literal 951 zcmZ?wbhEHb)L_tH_{abP*98Q?G=t(#7DfgJCI%f47bMTX^lyqr;3Ah!Ayuyt$@oW0 z&mU?L6jkd%4__@GiNM4|9dr!wR!(6z%-HprVUYOG2_xo@09~eqsT$-BEQ(t=h1D<> XhX9Qp3TdjFj*);7(5L~#%3uuuE((BelBlJ3wV6XXq0K!d#j i@(;vhXoSN(4@tHwa7K6ta*$z5@+JdtT$K`wW{txuLc&u41h)gP%Nuum1+?9Si OruB-=YPVcX0RTJOpesKB literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/amused.gif b/local/htdocs/img/mood/bitospud/courier/white/amused.gif new file mode 100755 index 0000000000000000000000000000000000000000..fceaf9e6d35d2ae174c7fd0e3060492c61c0f42a GIT binary patch literal 102 zcmV-s0Ga<6WOAIk P=kbcoYPa0(rT_pt0edYS literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/apathetic.gif b/local/htdocs/img/mood/bitospud/courier/white/apathetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..21d59b4b82826b0f7dc1201d5bc14d3c053a9a92 GIT binary patch literal 92 zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7DfgJMg|=q8z`>9z`$hO)4%fcTmHp!w%qF8 wd~eTh{wcYUv+3vNYCp2*V~3BHI4grS0FJgJzW@LL literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/artistic.gif b/local/htdocs/img/mood/bitospud/courier/white/artistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..8fb2cb92e252d23d80bb5ad5c765ff21d45f3a82 GIT binary patch literal 129 zcmV-{0Dk{RNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0$7ZXsmtvT zqnxzbi?iOm`wxZ{K$0Q?B@+JdtT$K`wW*uLx4a52?yHq4=pvZPa}NP2)J jpOqnnW_SlKE-RsWzntKr1?~*foAvb#kIUzDP5}Tr1%Ea+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/awake.gif b/local/htdocs/img/mood/bitospud/courier/white/awake.gif new file mode 100755 index 0000000000000000000000000000000000000000..ff039af1ddc81556ee026b119e288cfe6547f19c GIT binary patch literal 107 zcmV-x0F?hnNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z!f?BaVz%nhC0|N2jg literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/bitchy.gif b/local/htdocs/img/mood/bitospud/courier/white/bitchy.gif new file mode 100755 index 0000000000000000000000000000000000000000..978b53d777ae2828cc77b4c5c715dcd7bfdfa725 GIT binary patch literal 115 zcmV-(0F3`fNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!oaJsmtvT zqnxzbi?iOm`wu=qGKNQanh1)j#@M<6ER(f;=lb3NrC$TiV!WaeL?n8AOs1>Ze9m4| V6>X~g{Blul_6QD($7D_c06Pr~ErS36 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/blank.gif b/local/htdocs/img/mood/bitospud/courier/white/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..056d07f97a5a24dfda99880ebc2c8a4fe411188b GIT binary patch literal 89 zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7DfgJMg|=q8z`>9z`$hC)4%fcTmHp!w%qF8 td~eTh{COs8#%$GKF$)fhg9QLPpLi?d literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/busy.gif b/local/htdocs/img/mood/bitospud/courier/white/busy.gif new file mode 100755 index 0000000000000000000000000000000000000000..7f57b37b4304971e86837bf8665c7d5750ba8b36 GIT binary patch literal 109 zcmV-z0FwVlNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z{0DsmtvT zqnxzbi?iOm`wu=qGKNQanh1)j#@M<6ER(f;=Oh5fAP)q(Sg&DfHVg`rJ)QFjjm~^Y Psr8D@YPZ}jq5uFpvNtIU literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/calm.gif b/local/htdocs/img/mood/bitospud/courier/white/calm.gif new file mode 100755 index 0000000000000000000000000000000000000000..3cc1050708fc71abf36809f7dd0f97c48b2e57b7 GIT binary patch literal 104 zcmV-u0GIzqNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0zZt8smtvT zqnxzbi?iOm`wxcVNR||!pd-MxEa|%Np{k-?!||)5ya@~n89$m0v@70P!>02IjY_A~ Ks`WZ40028^St+mp literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/cold.gif b/local/htdocs/img/mood/bitospud/courier/white/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..4d9c420c4207831b50a93ebfd04049392f2f71e4 GIT binary patch literal 107 zcmV-x0F?hnNk%w1VJHA70Du4hmH++#001HR1OWg50RSuj0000e04M+e0z!f?BaVz%nhC0|N2OrHy WSx#zoR<%+paJUSM$K>*|0029kaWHED literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/confused.gif b/local/htdocs/img/mood/bitospud/courier/white/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..d4f2296478f5570ef8c1b504e908f57b5719eb3c GIT binary patch literal 109 zcmV-z0FwVlNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z{0DsmtvT zqnxzbi?iOm`)>f?BaVz%nhC0|N2+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/crushed.gif b/local/htdocs/img/mood/bitospud/courier/white/crushed.gif new file mode 100755 index 0000000000000000000000000000000000000000..ff434e12acc4422486727bc13aadc6a1bba5027d GIT binary patch literal 98 zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7DfgJMg|=q8z`>9z`$hL)4%fcTmHp!w%qF8 zd~eTh{x(Sli6tF#8oRc=TRruIk9AS+^YU}w^-nr6w(s`85b{NH`k7^)IeVM97_0$T Cv?lZb literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/curious.gif b/local/htdocs/img/mood/bitospud/courier/white/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..49b2ffec6c73a862dd7dbad0464671f7a7791345 GIT binary patch literal 102 zcmV-s0Gaf?BaVz%nhC0|N29z`$hL)4%fcTmHp!w%qF8 zd~eTh{tUmV1M_;R`|K}|^>y^J4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/drunk.gif b/local/htdocs/img/mood/bitospud/courier/white/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..0c2c1b7cc8515b09958536902516c1d4c8033ec9 GIT binary patch literal 108 zcmV-y0F(bmNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z-_CsmtvT zqnxzbi?iOm`wxa202ri*oPmnA?wgf~ERwd}-gmy5JzA0lUqaXlXJi?dKISjUq%Eb+ Os`ZM^YPVca0RTJWtt$fn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/embarrassed.gif b/local/htdocs/img/mood/bitospud/courier/white/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..0ece15da89d2bb0967940bda8cd08ed722f79749 GIT binary patch literal 104 zcmV-u0GIzqNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0zZt8smtvT zqnxzbi?iOm`wxa102ri*oPmnA?%S2{A<6WOAIk P=kbcoYPa0(rT_ptvcN1! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/exanimate.gif b/local/htdocs/img/mood/bitospud/courier/white/exanimate.gif new file mode 100755 index 0000000000000000000000000000000000000000..886eb87bafdece63840385c3646316e964d04827 GIT binary patch literal 91 zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7DfgJMg|=q8z`>9z`$hG)4%fcTmHp!w%qF8 vd~eTh{9z`$hH)4%fcTmHp!w%qF8 zd~eTh{x&HFi6tF#8oRc=FaDjk<6K Ss>c)pW~JP&_X~Cv0029VSu7_2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/geeky.gif b/local/htdocs/img/mood/bitospud/courier/white/geeky.gif new file mode 100755 index 0000000000000000000000000000000000000000..95af67be6e2174179148a186dfed9993d856d748 GIT binary patch literal 104 zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7DfgJMg|=q8z`>9z`$hR)4%fcTmHp!w%qF8 zd~eTh{}&pv)60+l~rG* IfF@W200u56B>(^b literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/giddy.gif b/local/htdocs/img/mood/bitospud/courier/white/giddy.gif new file mode 100755 index 0000000000000000000000000000000000000000..e5435904577cda9df26d71567398cae89b03b7d7 GIT binary patch literal 110 zcmV-!0FnPkNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!56EsmtvT zqnxzbi?iOmPvA*l=!_&|o~X*Ut_uQbD;qOekGH1>HEr9Sa<8JX@_WgWswH#ige{HF QqxFi-YPa03_fP-;J4F~RwEzGB literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/gloomy.gif b/local/htdocs/img/mood/bitospud/courier/white/gloomy.gif new file mode 100755 index 0000000000000000000000000000000000000000..b016882601abdb0435ae4799b3c4701729e11b9f GIT binary patch literal 107 zcmV-x0F?hnNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z!f?BaVz%nhC0|N2BO##Sw_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/grumpy.gif b/local/htdocs/img/mood/bitospud/courier/white/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..2d95c176b8adb013f8ae27f792efe552d2b30704 GIT binary patch literal 112 zcmV-$0FVDiNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!NIGsmtvT zqnxzbi?iOmdk-YxCzhlcjAyB?NZ7hZEE{x<=Q;$8J^oAGcEq9)*c*P5N#IM?oCQ}c SCCFwyYPa03_X~a$0028$%qqkH literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/happy.gif b/local/htdocs/img/mood/bitospud/courier/white/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..830e0df0d30538ca4ccc3b4552f42a6ab447d3be GIT binary patch literal 93 zcmV-j0HXg#Nk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0yK<|smtvT zqnxzbi?iOm`wxcVNS5aL0f3>JZSbP%VQ&ixhs2`sh)gP%m;wMh({3fx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/horny.gif b/local/htdocs/img/mood/bitospud/courier/white/horny.gif new file mode 100755 index 0000000000000000000000000000000000000000..3277dc2a4904c3f1d97bbf498b11d0ef203db32d GIT binary patch literal 108 zcmV-y0F(bmNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z-_CsmtvT zqnxzbi?iOm`wun%Glr#de!$AMVbI3uOV{=du7+;&JPr&Bhl|-PmpCGKz>)Ih6h3KF OqV literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/hot.gif b/local/htdocs/img/mood/bitospud/courier/white/hot.gif new file mode 100755 index 0000000000000000000000000000000000000000..cddf493ab0bd33a8bf4673dde412681ce8314c65 GIT binary patch literal 98 zcmV-o0GH0$|XoSbP}i3 Ls`ZM^atZ)DL7XU^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/predatory.gif b/local/htdocs/img/mood/bitospud/courier/white/predatory.gif new file mode 100755 index 0000000000000000000000000000000000000000..220c9f2aa088dbe8d44554c8f1f7f1e9f023f414 GIT binary patch literal 109 zcmV-z0FwVlNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z{0DsmtvT zqnxzbi?iOm`wt}HCzhlcjAyB?NZ7hZEE{x<=Q;$8J^oAGcEqCbh$Quv%%P^)Tn(L> PY4VEAYPa03p#T6oD)ud) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/restless.gif b/local/htdocs/img/mood/bitospud/courier/white/restless.gif new file mode 100755 index 0000000000000000000000000000000000000000..c8e11b5bc5649989fe84cbcc26637b4c3b586203 GIT binary patch literal 112 zcmV-$0FVDiNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!NIGsmtvT zqnxzbiyZ)&^6+&}2#V&3Z0Kl^YYM;eOxK4Bx-yR2{tpZahn9`;s52pv#HMo>vwf1Y S-m@C5O@r2}_Y1BS00298$SiXJ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/sad.gif b/local/htdocs/img/mood/bitospud/courier/white/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..eed3d7c278b3ac99c0f49a26a89b2929d8271712 GIT binary patch literal 95 zcmZ?wbhEHb)L_tHXkY+=|Ns9h{$ybUF?B!$NQQyQtfhbD>9_og=WMyvz4_jr-~4Tl tJf!St?6f$Eo5M@1_0$BCLRC) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/shocked.gif b/local/htdocs/img/mood/bitospud/courier/white/shocked.gif new file mode 100755 index 0000000000000000000000000000000000000000..6df7a41c60a7ba4b9dbb0bc6e69f2166a2a1af31 GIT binary patch literal 110 zcmV-!0FnPkNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!56EsmtvT zqnxzbi?iMv1kXVp7&>G5oM@x2OY0_ZOxN~J1E7BMABhVJheU<$2y`KlwdAL1Y%YDd QW$}v5YPa03H&XxrJKQ%aA^-pY literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/sick.gif b/local/htdocs/img/mood/bitospud/courier/white/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..42b27110b19dad41663969a8455a96599382b132 GIT binary patch literal 101 zcmV-r0Gj_tNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0z8b5smtvT zqnxzbi?iOm`wxcVNS0;>07h!EfqTaCOf%`--Z-hQZ!ZG&fFa$mw0qT-%%<}RjY_A~ HWdQ&?()=jH literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/sleepy.gif b/local/htdocs/img/mood/bitospud/courier/white/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6025060dee6084ea483bd8ae2e07c9e0576dd697 GIT binary patch literal 123 zcmV->0EGWXNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0#b~RsmtvT zqnxzbi?iOmcc6e?0+ePslBby>Vt}^c`?f19!*`v#84v62fSzIHWI+0oM2J$UIy5=P dT(w8SYGpCkRCBfBw&b$;j83c9?DnVt06W?@HA4UZ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/sore.gif b/local/htdocs/img/mood/bitospud/courier/white/sore.gif new file mode 100755 index 0000000000000000000000000000000000000000..c63566f490f35c05ad9454e5af4e62ab6ac022f4 GIT binary patch literal 110 zcmV-!0FnPkNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0!56EsmtvT zqnxzbi?iOmOAvtG0+gmXBIlYapx7Sk8HaOO%VEy<{@=mbdO{)ah)gO~Fdi+(f<9|g QXLE_oYPa03cTxZVJ2^Hhm;e9( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/thoughtful.gif b/local/htdocs/img/mood/bitospud/courier/white/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..2a95a7ba22870091699b5423b198009729bb5030 GIT binary patch literal 102 zcmV-s0Ga G0suS4dnls- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/working.gif b/local/htdocs/img/mood/bitospud/courier/white/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..439cf902aae72fefd8a389acda8d7f4fd09d9b0f GIT binary patch literal 130 zcmV-|0Db>QNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0$GfYsmtvT zqnxzbi?iOm9{`4;hlnOXrs~Qrpz*dr9Lx5NTeWiT7wY11d^4d2Xe?!jpQH-eWc8pJ kYO2?o@}^ctcdMOz6W_55OJ<{9 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/bitospud/courier/white/worried.gif b/local/htdocs/img/mood/bitospud/courier/white/worried.gif new file mode 100755 index 0000000000000000000000000000000000000000..148ed431ac6769ac4498e78062ec7df65c026654 GIT binary patch literal 96 zcmV-m0H6OyNk%w1VJHA70Du4h|Ns90001HR1OWg50RSuj0000e04M+e0ym70smtvT zqnxzbi?iOm`wxcVNS3As07h!EfqTaCOiOT?-eInTyh`H5dbOhQh)gP%%%;;=0027> C=q7mp literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/angry.gif b/local/htdocs/img/mood/charitycam/blackbox/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..46f88be76e0c3d5005e6848f35952dcb651100d2 GIT binary patch literal 363 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fEiK269sAF~@E;5m|8x7fh6Fo12DlpO889<~ z)cs`PG-6<5&|zd?WDsJIW?*1xzHq{GwV=~88_S~!D`Mr$s>DyWzIicAGwV>vuY+NE z53An)ci>I*&=Ip_nHH4d!NkD0!bD1xLFL@?vfn%`8=5o{HmKSke(>q?oxf&lQ@`Du zyXMgOf_$llo8NwxB*rvX<;SqH#$>cbbu#qjCL}dSbw^H#YV}N=@ zk=z9|9_p^v3nw&N7ko)dettFKcx{+w-PB`ib*!p#r}d@Pu6noZ`R-Nui{=-&Ye@CG z^Bz1VqRZIeP@*-Ji(!&_$>~-$rpQJSg9p$&!DKN=;U zgV9oN29^lEFBzK}&dxGtT$96jAdPX3ec~w*kIm_R^R?RDG=6Jh_Zz_ZQ{HsRj2>-L<@sduDgV$Dli>%aa@+jx+)} zl8u3nfrEhy=tw07agH7V#{~yjS@`*Mc1&0Rc4WfF956sYg^ey^PnXqb^l&R6&V literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/cold.gif b/local/htdocs/img/mood/charitycam/blackbox/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..6029155aa16fb82fa735b646f62fc3be5004628d GIT binary patch literal 362 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+PjvaGy`v0GS;XfEC{^#~{4GDI33~)8lGhk)} zsr$*o$;QCOpaaq*%pk+Sz|t7tk+^DacvRQ!i=xj{=eRYdTjoB!J}bAaFWY$BS##=J+dCR+YFiT93mYZxUiE@>}viRGgE2I*(Pd{H7m!Dh_n%SIG*q8!zS3_HJAH(GOjOymr#Eysw0htRJ Q7cSJ9o3?yK8qjIh0JA5K2LJ#7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/crazy.gif b/local/htdocs/img/mood/charitycam/blackbox/crazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..8fbc7cc5e49a2eca6052125969f82162c2d1c6f5 GIT binary patch literal 342 zcmZ?wbhEHb6k(8KSj5Hv2LBZm6^o0Dj~zSqpMl{&7%2Yd_Hzvhc6JPKHPSO+W(2BJ z{K>*9!obF$1JVQ1&cIT9;e_Yvy%w*}?*5;k(U-E5*JahZ*A9ZtI_JMwGc-(izpL){ zjs*r90yjz;A_8Wb_$BO!F0#^PS{j&mMzfJKuknD%ohMQY8Vn+JfR|hq54?&dMMF)WQkWB70$mz>_u8!gSeZ%w*)bm)^P9 zaL%<;`wISuZgPwkMCf1x>fi+HkiO89_-YD6$mErL3fmi>gt4+^t;@+4dBl|sw80tx Dg6VRo literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/curious.gif b/local/htdocs/img/mood/charitycam/blackbox/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..8f9225244607b602e19b7e2c09c793a60200d055 GIT binary patch literal 260 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0;ai6#sMkxrPKgI|jHK=@~FHg4F$F z;WT1kW6)t@U}6wpkYZq9iM?<_bJYxs;ImKP&R}gz{x)?**|IkpJOw(Z*QegUroiBE z;lJH|zvJ3c-Hi?B%5Au&?0#nGIYnx|x5L7OJD*kr<_GrFMoqj>ys<__U|GPknQPxU z&i~<1x8M8M|9U|b8+m{>3IJ_%3Fz_6o~rcvY&(O4K;NPtl?khsIX>uot+gY5&$bn7 u&*=wP;F^6;Gyx&!K zd&dF;362{j4UGYv!V>BmRQo!$nWkTP7R>bdZqvqB*92Hw4#qz(Jh9Db|3Rn36?NRt y8TM416}z^xptd^Sua&W_O(fB^r?*#4MG(maoIn>aF>nK2z#af}fkB%agEas{r%m_( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/devilish.gif b/local/htdocs/img/mood/charitycam/blackbox/devilish.gif new file mode 100755 index 0000000000000000000000000000000000000000..259b61eaa869666748474a17bb602dae83160386 GIT binary patch literal 243 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fEiK269sAF~@E;5m|8x7fh6Fo12DlpO889<~ z)cs^(HDX|6&;e-zX=h;RxNyRA^evL^JEOz4^1pFNLp{(KRihNNZ7yJT0b c5=3$wJA(kwjm$vDacr28xn#|jI~)ww09Yql!~g&Q literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/dirty.gif b/local/htdocs/img/mood/charitycam/blackbox/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..32baee37ddc8214f07e74a7b8a84bd04be490de5 GIT binary patch literal 324 zcmZ?wbhEHb6k(8KSj5Hv1d57^$;rtrEiK269s3UhivPL&TtkAL9RpmA^bD98LF#_8 zaHcS@G3YQdFfj--NHZ|76ka%C*}A|Y-FxlzOQE?c5?yL1mcHrSHpAgeN$ld5Kywb%FahFM|k7oTJoNTnRV z`@ZmI?)}vdEnS-!o0~;ly*s1YcS=$uw5ylbI$)8YMpTgQY$%u>vU=PoeMFq+GtSjg$XRuz_WDIkY$ z-u)NbGX5woPhAi))2x4`-HQCPt=rGPDf_VYx?gJpV`HO2SX+CAnyzSa|~K*w_x+(><_bM^0H27sBdcU2xx0>2ij~6 E0KnvTYybcN literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/embarrassed.gif b/local/htdocs/img/mood/charitycam/blackbox/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..e8b12a66332726ada9156db31cc772868cd1efd6 GIT binary patch literal 254 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0_McKLjZL=k{|A33hf2a5d61U}glV z`^mz|#=yp)!^ptHAOM66EPeq!p4n5CUY~7ea1iKQ^rJFi)iTEiov*ca$XCdi@oihd z%WiexjcD{omev%RCI{*Lx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/envy.gif b/local/htdocs/img/mood/charitycam/blackbox/envy.gif new file mode 100755 index 0000000000000000000000000000000000000000..fa7b339b15157b3a7ad3bcd2c5c8fb9a15c282ff GIT binary patch literal 238 zcmZ?wbhEHb6k(8KSj5Hv1OkQv$slkH2>vrL{09TY|J;7AA;Hd$0j@@R2F#2=b&5Y( zSW_6-7<53IK-w8t@-Ce4T)o%g_1WG36EynfILyhI#U-M+r$A@B6T^)kYp|bnPx8Ru+&Jg@)6KnJ3WeXea^ilGY+JVK zu$QiR%>8{#){PC#`9k%M9i5#jJ-y0;NcJ-`ure?MAp;BR1s>0I7KF>#!Q$9txEL52 oI2kyAdZaGQFjQGPU8rdL^2-l$XIO9vE7mNvSP;bHCCFe60MjU2RsaA1 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/green.gif b/local/htdocs/img/mood/charitycam/blackbox/green.gif new file mode 100755 index 0000000000000000000000000000000000000000..896e9dc44e94f2d61e772727c887f52a47b84601 GIT binary patch literal 303 zcmZ?wbhEHb6k(8KSj5Hv0xb-Rii*j}$;XZz`_I7e9}E=#bNji51UowhxEkphFf#&` zDgI<(m1AII&;jWIX=h+bzi`5H^9a0 zzr%b7hs~_bdpb{-Tl|@|Karmy)vDIB^K?az(9~wVPpj8si;$ zJkz}~uetx!iRe4Gw6>{qbSeuX+0DWr%D}_G478imz{7dv9P`&}l@TsuVGx4Kau}TO zT)NWYItQ{OA5fA7sFn9Zi>J0}QPS>GzWJ`M$SQb%Dwu#OI4-bwF6Xt#mSM0408e3C A-T(jq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/happy.gif b/local/htdocs/img/mood/charitycam/blackbox/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..0782a8ba3310d2ac091dda1ef02b9c5e396b63dd GIT binary patch literal 227 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^)fE&q=lJN6$26#sMkxrPKgI|jHK=@~FHg4F$F zVHIIuW6%L<0%>PpDZX&RbM;<}*JpSCPtfQ~*~#g$YTarFK_{K_U$hwTB*jXYZSB^)7Hiu{^EUCsrXolR4=c{o!0Nt3DfQs9QzS{ zeB0;Zs`}E{a_8)}M1$yV#-1J#!;GxS;cCi)NbX=|5N6+96NUGzmwDdmjD0%GXOD&f&m~~ z@jthpYe=xOV}PrXo&hr>NdHe3PB{i{1|22_CI$fp2?hq1hJurpmu5)Zo_a0v@WhhI z6_N9&2R$xqTVxi}`J(J|$oaX|lPAp*5XoAbb?{<`v7p4f3ol;06p2`WV~wK#L&^So z2Ibruv(GF#Ns z8rK{%n{m#(n5>11773y_ijhHxK@#YwnFS{``S%w0Or7>rK2`RlBVXF~*rhucrh2P> zywIp}Y^B)WET!o4DN#92a>*y1y>D0@nH#*w>z)czbJ^*qTqc-*kx{mD*DfJc*TRCZwZL=cwVBV)O}+H?-gez)SH3t? z9;utMIypx#XUXYbUnSa?W_woa;3toOsb|jzd1kS+tuUE2Lux_OnzGY-*%~cve1JWwzdM(sWNVnUgnUSD5KMEh|+jU-QtW z{nC%hFD?B`g0hd!{32u?bW!{fL*&}l0}gAW)&@70oqj9D!st+;qu0E@VN2CqK9+rr zO*MY{b6AU*64%Y&y}z=$vADdjw6wmWy|lHvq_eN2yqII^)c*X0iA9rVvvwvdWL&f) zA#eGL6{t>Q07kJC&}p*^PL?j)yZw>wdC8Lws=}F_aWmE^zbu`)V@;^fsVhb@obTUm zZp>KW-Krty8;~LMu1Zz>#pTZvBj$<~rB34DdGJBeN6dq#X-m~vJ8mY{9X5XTySabt zk(1}x@vyqOj60)(g{88+vbLPHtF5D=IisPmyRL<4TGNavv#0mYXPrE&f@Ases-Brs aXD?Y)GdGhlf9sa*&6{g?@7V*2WNQG}eQ%in literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/hungry.gif b/local/htdocs/img/mood/charitycam/blackbox/hungry.gif new file mode 100755 index 0000000000000000000000000000000000000000..41e5fe9c9136afecaa8923931f2071e236c1ffa0 GIT binary patch literal 457 zcmZ?wbhEHb6k(8KSj5Hv1d57^$slkH2>vrL{09TY|J;7AA;Hd$0j@@R2F#2gbw61+ zQyAD7beI^p7zBWjfyFCef@k(rrPpUWIT$qBo;+vFShdLULF4g-$5v=AD4Dfgy@1D9 z;Q(9I+6wc>T`ROi`qrtOdKq#vEL3#UiZ!mgZ@oyDQJ8JNc1x5jBf@x)n}ivpfW|im zcqFQA4GlZ|eVP37(g&(l(T`x!(@mFckA46Dzyf~<4XOU)5{gHU6ij1u zDA8KW#WYtn;q==)<{QsN3oJ@b-_8!(;97k5L1}ftGUh9fR$P}BfB(ILEg+VawI;DC zr==~nF{-;gyQ)63qkl^LG$F?DxpU?>&Q4goWC@!flD9!&0C87Kzzj`Q(?gGJHtwH# zyfOAi>I%)c^p{y{)avzY59eAws(21`mw+?SUGBV!M{~+x?(%1ZxQkN+;;yppXWI^D ze|liUzT#;3dbz&quivvJ$FQ=-)ig#mx3tDIc*nK0C3XbX^-k`e7Srw>K96z!e5-^d LOP2`)9cB#xhnTjk literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/loved.gif b/local/htdocs/img/mood/charitycam/blackbox/loved.gif new file mode 100755 index 0000000000000000000000000000000000000000..8658049dcf36a7e49a2ed528a8546333dc7b9fe5 GIT binary patch literal 273 zcmZ?wbhEHb6k(8KSj5Hv1d57^PXGTWCnp~}cI-a`!+$VP{Lk&@8WQa67~pE8XTZz| zQumXEGlhYTL5GQfi9vutf`Nf0<-&=`u9e1@Ppv&S_j}`wADwBd)~zuSD9}0mKH+|a z9}nY&|N9j3*)^p4k2)k=cUEd|UgVH4M{24|L#UUo)9iDvjil`A7+F)SEcL>A^7C)s zwM?o^RW{MT_wgTNLz9hHYg?Njip5+&iv@rddlgLZ%$}$AK6CusD|ahQ`ai%Ue2!|}tpk7xYy0z?=eytZLj z!+Pgy*B%Mh7sl^qoqQ_%K*wRK#goGHBVI*r@(dL`TUZ{?vv@20=)&tC=l}HavlV_9 z*Nd;_)vK*6scx!kY0x+7Ht6jZ=`x%&d9up1>B@pgE@5HdVc=$90=k6rLQ6u{+@edX Hl^Lu7B6(Ed literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/okay.gif b/local/htdocs/img/mood/charitycam/blackbox/okay.gif new file mode 100755 index 0000000000000000000000000000000000000000..d210e014fb441ae803370c7f7603a88eadcbf6d1 GIT binary patch literal 202 zcmZ?wbhEHb6k(8KSj5Hv1d57^$;rtrEiK269s3UhivPL&TtkAL9RpmA^bD98LF#_8 zu%$AK6CusD|ahQ`ai%UdtPl3*MriA-DbXiK?F*Dvf zk}56H?S5b#y8+(>{{;a~Icjrvtz7tPH|xy1Iu?IquN9oUeM#n9*3O5fU+?IhFaP0S j=U>VCzoAj3xkXtJ$yzoBeg+N(pi5X-4Lp)lIvA`01xHFK literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/peaceful.gif b/local/htdocs/img/mood/charitycam/blackbox/peaceful.gif new file mode 100755 index 0000000000000000000000000000000000000000..65e30cda02a8bf713d30964e1855f108af959cc3 GIT binary patch literal 245 zcmZ?wbhEHb6k(8K*v!cQ1d57^PEP-mlar4fV>ou~*nb9w|Nou-g8@hy2>`_u|8x7f zh6Fo12DlpO889;fWfgz2u%<9@GU$L*f{bNgNj5m?xq7d~>$AK6CusED37C^Hi!a1* zPl3*MXNDU;)?PPx@ZTX`!C^CN^PbMv6*Avym>5G|d3(jUEt{}HCZq8h%eURN|9IF` zzQ0nvf9=sM>pdmbySLUjtY5yTt)a0=rKMF_5XoLP23DZ;{6KrfC!DbC-#h))k;^X@ Ti1(#r&dXTU$9BC)kii-N17BP3 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/relaxed.gif b/local/htdocs/img/mood/charitycam/blackbox/relaxed.gif new file mode 100755 index 0000000000000000000000000000000000000000..1f39d516a2c9e281813ec79206c876736ee5a1eb GIT binary patch literal 188 zcmZ?wbhEHb6k(8KSj5Hv1d57^PXGTWCnp~}cI-a`!+$VP{Lk&@8WQa67~pE8XTZz| zQumXEHHCqVK?kG>q@95!@4^Ys)q5>opWXdGL8I@E!<>v+d?JQ>3UszRGu-&G_PWV~ z{|@mA4x3q<_jI0C7x*)4e%?Cm%a@>_3PH0*e2+{aizWogD*Qjr0td8G*_a zf3mQqFt9P`fb@X0Gq7Y|IN`Z^uf^-LyZ^xbiolQD}=#Bfi6&UWU6`#WqoO5QOu z-8+(MEmPn&H^7NSCI5WFc}a&b#@#R9tI1y5wtbCxxWg^ey^PnXqb^P;F^z%J%dn8yn7$nMllM^^gKdlOSbS}c-*fI-=@5e*icH7?9x3yV)KY#NP(f|8y z7dKk{z1{q|pwX$Gt)!_`SKp}HptoD3D}K`C7L{q!vIxVIJP@PAQYE}MP7hTnz38UUm(UJ(EQ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/suprised.gif b/local/htdocs/img/mood/charitycam/blackbox/suprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..03c691acfb05ab077678aeef91817d842aa84365 GIT binary patch literal 472 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2Y!0;ai6#sMkxrPKgI|jHK=@~FHg4F$F zVdY|AW6%L<0%>Pp$+&RBbM;<}*JpSCPtfQ~*~#g=YTarFUMHRNU$hw-k!au+-lmn{4?E$HaF zSw}>bT%*!wN@>4b`SeR>Oq*{43&H|~7R3u50!ug#NGZ5HyQkuDFQZ~k+N70R=gp4X Sl*ExH){tL;RTph6vIYQ+vzovF literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/thirsty.gif b/local/htdocs/img/mood/charitycam/blackbox/thirsty.gif new file mode 100755 index 0000000000000000000000000000000000000000..09ebfb201439c0ef5076d1b9ac69353c7d5b0357 GIT binary patch literal 362 zcmZ?wbhEHb6k(8K*v!cQ2LBoU|5sF0OioU2`Tzgev19)kfC3-@k%p5%5yk)9ey$_gMa6iFeGi&pn&eP%?e`f7ZnwMFmK>b0GFFB>b& zj`+n_U=hIetm|f;>E4*v{D101^qpH;+f+I_l?9RPW?>Lz;9+0}+RYPi!e!+g)%kOG z|Bq!sIF5xu2&jMssDMA=wpaaqb($2t=b>W2P>b(}P&+h)8pwTzSVNS*@E)m5&1v=ZA67KKNWhr^b z%y{oes<;X>rlS@ zv1JwCzFO9@hWaLN;X23mjt-UX9%Vr!>zNr?8JK~Pfra$~N9D5~gu~du;@D)k7#JBi r890D?*s){(85sV9f#QE|Ki808XU70nBRvCVMv%In zEUYOEYz#UeO(5+IETtDtc&^@S;eW98+`aTxCD&<}I;H0B+PA{tOiAo~m(}k>)AIZL9URcvO)ddXfr??pLFfAz+Qartal z6pugmJ-s%?zof~xrNOm}vAbK%)o-1HC~Xx8UP@nU_k%? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/blackbox/working.gif b/local/htdocs/img/mood/charitycam/blackbox/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..4ed0f630783a4344afd9da7068edeaf4f1f4bf90 GIT binary patch literal 268 zcmZ?wbhEHb6k(8KSj5Hv1d57^#l^+Pjvf2|-|0ULDE{a6a}5c0b_{Se(lcOY1gZPU z!pgz4J_ z&Y%AxsKFtso{_n=y^XC&q`pz3yk=sQ^pvU7rq7ruh~yM*1`Y;BAY@=+n&5(PAsYiP b12b5dd4hxxLYxaI&I%T1nIPe*#9$2onRr&5 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/angry.gif b/local/htdocs/img/mood/charitycam/goth_boy/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..b61bc75912ffecb7058a77c98a2379c04daac75b GIT binary patch literal 1106 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_6Sqj0|!Nh71fW z|1O-+oF2<|e|GM>yKF(C=}kA5%$+@b(tPVlN~>!(#vTscacXTmpZiVL-s4XUrvzKg zzp&zpW(3E&;B3+CgJJsjpP1X+n|Ank(e*V~7d3~M)!1!!I{U>&y6)QZ`E}v!>`l!v zWeF)QOwBF5J^iK9CA|};PR#F|-pnv{?$pAX3G56@=PX~cY@y@4rOQ^%SvQ~Ey?4_( z&TZT0Z(YK*{{Yu~hJy#@?me>qOnaYg2`@Os@xWKJwFN`GES6}7L&19p?uO!;cr9C=k#Z*LJfC5SW@x%!bFbY zn+}+O=|CEi4hnRQm(Eqou6lh|{9&X<3gwVl~y{c*d~ z(X}-dl`XAVNtrdxZQYp(y)_Koll$VkDj8%HwAbWgoD-e&BkKrRKve_vhVSUoZM_Gv8zWCC197z|g?pc%Yt}iAyEp!-9Pc wtdeGb*b5U5cKYyzOp!3Szt=`gP(Lo&i9Kt0At@;-LMbV0N=kbODTDw3goFUSy}iZ& z0LI3~|Ns9NuND9R02i+oA^!_bMO0HmK~P09E-(WD0000X`2+bj(LI!k&lgvnR1DnhI*8iml}4XrhQDFaBgpLU#oAju(7jmDYm&kvIf1f zNe#JYz!JiK#KpqM76WGk%NGX+3IGZU($E#s)7975*%H#$-QM8g)6~}G;0faC*3zWV zPvh#x7YOf)A70gz@TtQEE1F@` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/awake.gif b/local/htdocs/img/mood/charitycam/goth_boy/awake.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9724ba811ca9b57c4384a7cd7b05c918f1c558a GIT binary patch literal 830 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_oYQA;b~DVJ(bUT}XZoU9(-zNTTd-v2?753qPF=R5W^VU_P2FvqH%NAN zlsD#YuRl^IbM(ZN!zat-jeowOCo%8Q9tHYu%^FJ+EH+c%K~m=3TyF&YVV(%Dz$OmTUaF L(y*qBgTWdA?G8U2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/bouncy.gif b/local/htdocs/img/mood/charitycam/goth_boy/bouncy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9f9e881ac95a741846c2c5336945bc563533f74c GIT binary patch literal 755 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0gj2*jdKQ5d7z1*#^A)~Ijy{Wvh zt)ZyCw^gXBadKZ>XJ7Udw&_hNap~c6Qa_q#(Q$mN2pF4l?(vhRbuU%xjeCzn(9S8ld+%CTEcwO1{ mwbA=`3Em&&KZywfqYdFtE}%a(fd0HT-2D0a(>GC|SFHgbK{aRq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/cold.gif b/local/htdocs/img/mood/charitycam/goth_boy/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..aa28b434ec236c350e0c2037990969eb442ff6f9 GIT binary patch literal 683 zcmZ?wbhEHbRAMk<*v!iS0xc~J$BqfC6;M=E)YR0h=Fn^biv9n;ckkX~3_zJ<|Ns9N zUoQq!2qYE%bNji51UowhxEkphFf#&06@RjDvNP~9=rA&HGsrNgGcd6H+i+6Td4|~i zT`SMuNlkssK5g-YRnvYM_MBjIx~ru8c%O0;yWKQ~K<6VavfX^*CPM9g5}PjXxZA@s zKcrwuskzDg3JK*$LY<4YSV=8qec@s$-7(qUK-Q)&>)xL`-!}p@U(KOGsV@Ltl+U zX&*zTf^ZE(<&=zxGYw{Q$`#I=#XV=q{ES7MD`xdpZkV!q$(Hr=*KOXgZq2ThtM_c2 zv1|7J13U{B?_Ma;Nfr*?)w;-T6pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVj1002h71fW z{|ZieuAZy*+@wGM`rLTmEh5n~?1fRvAj_ zRiAD;{BU`k_EDE|>$S_SZ#|PSDQZN%l&k(w!{LI~L4M%+}nH2!3h(^3|Jn@6BJn{rtt^`|G#A zOxS-s^$tHXTdL-t!CiyR&5C{Y^>S7lHx(#N;T9aeQ47k)QsAh43(UvUckXz#m-qi1 z_P)s;Z8s%XEk0S6ue1A;nvRp-t6fKew|g0Me7;*{`6%VY5!v}(k1x+$^Dif4^|hTT zS^EQDelIvN@$``=LbYOB&Sz{D^)tKt*x`FEe|YeDhQ^vkh6ar=sS%a``gUOS~@Wy+?_JzM*?uW4wiZYkJN zb9C>%V>O~Dk4e?ATsS3trbOY&arrCy%;n5RkQjYn_~7B=r_XdAJbCq6|J|b}AGO#& he|W(DJ>~t^2@wqw4Gr4l?e+P-d32;CwgU62H2~9AebN8` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/determined.gif b/local/htdocs/img/mood/charitycam/goth_boy/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..6b3ce3d6fe35bc397b92862a740e82315fb1306c GIT binary patch literal 1018 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8q`_oT@oATNoJj?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVObk*C1`G@= zzb35lT)j8gYtOf5Qf@s@ILc&J&Ab0}X@>Vy)!F;Lze+23f8J_-f}#dj`?1bKkHoMU zei}iqaBc%YI;WZ~KIXV|{1yMbBLnyLe8#kM%~M%#|jCJLhfh*o!c?F+Ub% zW8+}p;CS^y_|@yT??1eF_3rDpk3ZkM`*Te8!*>7Jjq(*=7@xHG`R*~Pl~Y@!Ytr7n_1Nlr1YM!;hX8bc*^ulzxCcJpH7w9?QCz>)!~zxn7YZqS8x9Ew;wFty<7Y8 z$2UtawjZDC7)ph58MxY;3fnqTglpR;FmU!y;OgvS@18m>an{tP8M7A6oj8$w;q0E7 zE9cBuJ->DK^p+`ex|Subn_FMen7ga;;LZbwN<@zyk~qkEQ0hdX-1);7Pv|h0FzZ30 z^S18oJNF(u)Vh8D=`)>|ckjPZXMgwl_Hvb!S08${V)g#%etVOs7{Go|iA~#ufx#L8 D-9Mr= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/devlish.gif b/local/htdocs/img/mood/charitycam/goth_boy/devlish.gif new file mode 100755 index 0000000000000000000000000000000000000000..ad33cf47c3dad5b2a3e5a1bec701fb6e421b19e5 GIT binary patch literal 1016 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0gj2*jdKQ5d7z1*#^A)~Ijy{Wvh zt)ZyCw^gXBadKZ>XJ7Udw&_hNap~c6Qa_q#(Q$mN2pF4l?(vhRbuU%xjeCzn(9S8ld+%CTEcwO1{ zwbA=`3Em&&KZywr-)LiG;9!tp&;mx=zkrh~ITr4?H%IsQwQqv$KSGysPFt=rL5DrR zX~C7?+@;^8ZtIB`xH0%8=-fHG%w<(TyUJ#_T1)G|%&lELtL7ZlEuG#gdwSZcgA25) z8{alJ*v4PKnO$wV{M_rml_8R*4XtfWHRTN5ZEW2PC2m4>43QHWrUp)Dlc=0IjbmQk z^tpX`v$E%>PFOmB-O6dx=7?-qK7G}urOQ@NS)9FVH~Z{GEB0@h($m&occAy&vE%2@ z$((0DFW(#4t9$ddF4v_q_a{GmEXmx;tZpFB%6cg9ow6dkd_De@NB)VZ|0csyysBn=k^25SI@ C50_p5 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/dirty.gif b/local/htdocs/img/mood/charitycam/goth_boy/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..fcb1a73917d2212b3b9860ba6d191cd4a9608d4e GIT binary patch literal 1110 zcmZ?wbhEHbRAMk<*v!cQ1OjUX6crUUH8ra_G+P)LT3T9;F);l9|6hE)7)Tlk07Vr4 zbNji51UowhxEkphFf#&W75|;~%uP&BRdCKPs4U7%&nQtaGB7YyP$(}i*GtYwEXpjY zOis+z%P&e-;N{}w3dzVUR>%bF$W5$N$jdKLNJ>>GEly2QD9TGrD$+GROJ!O^E z?F^H8Co#138;ebytUi01iOZ~c^B2uqV9da=YBk6Fm1|Z_lVe-IcJ;dL+udxpY}hz! z-&)t1Tlb3}J#<)DZR?WbyG*R+&S{;hc6w&-Ep5Bo_i}IEYklxgoaK4%>E(MKX{)?_ zt@OycxwYsECo3yE13UXKtt*)qwy(c$-ypq<_s;S2_Z=l~XuSBG{vq*@+!G$3oEQH0 z*LBG2=meC!=wt1$5O+Kmx%k}O}MT_$_#h1=nxYT?B1INZq9E&$>-Z)pCZQGVjTlei-F1CC7 zj+IBZ9I`mFdD)qRr}Ac8Xx+1H*P7X@*R7a*uT|~-Bb`V0GYtgI07SY+xI6Z-4W$J9Bq%rd8SFfdpH0J`+D(EtDd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/drunk.gif b/local/htdocs/img/mood/charitycam/goth_boy/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..450be1a288fd810f0a2a8932f4a938b46e09e284 GIT binary patch literal 1117 zcmZ?wbhEHbRAMk<*v!oU0>>Bx)(R*pDr#zKR&!{!Ffg>VwCvrx_ZS1i|NsBR*NcG_ zfe0X5@jthpYe=xOV}PrXo&hr>P*m~XY0uom^i&1s{DR7&%=C;B1tS9kLj{HM@^Zc8 zjKreMlFH=7T)q6FbOl~6UapXg%wmO1u#VisN`<`q5{0Bxh0@~G6ovB4l8pS)5`~hC zRE5M+AiJnop&+#=H?z1nGe1uuEx$-1F|SggC^fMd$c3pcD9Qv%lmqQ4NzGG8&d)1O z%`4GUPzcBYs!LT!%}vbAQ9wAv0l@^j31liv6E7Eo;!hS%BL;2;9gyGTfuY2}@~_~e z=j)Xg*;U)$N&krK_Lvo8+4$&T+=tm-2Ax;G?`*T#yLj_NP6?Sxqa%xpPM+ZrYt9H( zni@3!yl2_uyJZ{iuYFeC+H^K4T~sD__d@S&)%)byUskB@ljU&vT^A=B7SPzh+}_Zb zD^c84Ti@Ru(=lmUS5NOmMuxf5=Q2!|>{>9dfoaat2C0Un3zn=~$hc+>*S76kn;3R% zU$|xWwgWqB4;|gSc|-apvHXv$b1}?45M%%K0P9ZrnXCG5ygb>Bo#KrprBh z?7qB<^~1Z>Ua$LoyI#Bue)Ka~l;so0kHZNE9GDn5g+ydL7A|mX;Sx8B2{2GR(jlxV zWivxS*_lN_)KX2SR6 zHJ_dHqs5YxPs*;iu`)G$YGTj6D>>I+a?R4^eXkYx&dItm%3<-R%_fHP1I{NHu5eQi zTdk5kvu;n^tFl#V+bkcLOg&?le&+So%5$~bUjF!D-TQv`_c}(#(5B|Zyr_`2R_318 zwgT~z{-%~G6M}lD&+eZ%X&NKLqB)BgW=QrgUEIpFa8;{J>#C(IH!ow{xR7i29S zd-p8cd0_X^eND$t?O3tv;E8hw51+kwY~`ht0A-%o5{{R60|Nj@S78kD;A^!_bMO0Hm zK~P09E-(WD0000X`2+j=!}_!@G@c`0^Qp8ep*qY}!6Yr*xSdO0UQ&worg^ySr>}A^?BOTy(mb zaemM0w^A5?+wF4<@Xp86G6Qb_gLi`fb^{xMT!w^SjfY=}8jFyQmXQUMfRBxWo|1~6 znVqDXqJ62Ml&YliauNScehmp99w{Ntyg20cx9kIH+xx8Gyu(F6Cwyq-3vm^u7 zeAde$+1xA!f!ZhFE8O7ODAUU5+?wa)r{3T2$74q^+6p~UEN{drd6v{J8GV)7H z6iPBu6%tE$5lH!(9u0pSn_1QYBgkf|_Dyj%>5KUp}97IYkq!`p0 z7+9`sIO(}sXKhCI_k9v(ol`t!DSGuKyk4q3BP}YoJ;v?+pF8ht<8!6?CUSNX1-0!-lU%JCbWmq_mb#=jK!OCz85Ry-M)Y9$6XKe+yC>c8n|k! z+A7PdTkEUqdU!Hw`+7T?TZFQwlor*@$WDn%51*8}w0Oy~IMJ2M#Ns$MY*;0;Cem`= z*6k}&cZspZvh9`OTV7&bU##`nJi^tZ?)8mD+=CRLG>dKp| z5OXhjpXS}EF%Qn|-nV;O82<}lo`&YduQ_%L_MUk1NnmPgiPyo#Rkj-JjZ407|J1p= zx!L{A&3{!pWX;#!yLI^HmYx;a_nFzbxH6lXOMH|ZYCKyToBEnctWC>28CxeZ&uGo` zv5aV$y=ZoFxM3^9%EeqO8JZ`H$~7^Rt((0idYiWJin5(Ec5H2u+`RA5nq&KqoY;B% z;CZgo2ls8eeCYI<<43O?mN;;0@BX`@+gB}KJLAUc*R4`--b?Ym=J@jZZmF4fvgcld)yOm~jFfdpH0OU-u`Tzg` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/full.gif b/local/htdocs/img/mood/charitycam/goth_boy/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..71f3c32cd43218e8a54ddc8698a5d36a37070872 GIT binary patch literal 1150 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_{TqJHm3|nEaVCr7Nc{pV440XVzk6WoKY#f1vr`;p3;z)E_)~ z^;+ZIqbDEL*gk)Fuv|6%{nz+_gg`@sqjPN3`7R0kNM6{+F?=JGg+YQrl0ga>p&pO$I8pNq?dTkjH#P({sl+Y z!b@>YzGhpumbk}z{V<+3Wow2v%dk!S%)pS624V&lA5d7WefCP%_t}Fdtxr6fp6#rh zpS5wVckRkMrH0F%d_FUOr_=|fCnB!pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&tVRsn3_2h$gF=acEy!TSG6U>*SDO&Y%0OP1N5y|fv4xIIalw+`fr>2 zJ@IB@*;36e?uD~X{yz4;{K%KJ&nsjP8Qt}9&)Avap6EX{^K6~o)lDy4mIe89O~}$& Uv`Fq$`)SE`^A}qpgcupD0WlToq5uE@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/happy.gif b/local/htdocs/img/mood/charitycam/goth_boy/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..33d5bd047514a690bc4633d83c64bc0eb89254f9 GIT binary patch literal 1007 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelE`4|)#SQ&uHm4#)(3QwhB W>rY+=1qODoKUpWNu=HeMum%9Qa&YMY literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/high.gif b/local/htdocs/img/mood/charitycam/goth_boy/high.gif new file mode 100755 index 0000000000000000000000000000000000000000..cd4920eaa5516f380b0cd5137e385ab7be9297ba GIT binary patch literal 1106 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8pVEDZ7tdJGIK z{|Zieu3mfW&e@gI;?J1z_T!Sn1zV6{%leF8n%Ql72E%;x~ z$=UuMJ&)E!EO^dzwrX+o%g?{}@+^IFm~nZWc<;uQ2ky>W{kD9K>g{!pe}{+I)YrDQ zHgc&cQC$j$ z_+6IQ*@q9mc=;&B;={+MxAeXni88k_{}$sCabRFzWNKv4@xvl-vAc-Tc2g+ z{`wN#QF=3|YenR|l`}TxdK}aASp4Da%SjtJ4tT8-;`vsy&$H;qYt8=sDi_j~ofh9% zbg^V++VX__AXAsN^HC?gHC=a?yMKSkFz52|#WnY47Xr zs8kIuW0*F9eHue~vQGP~>3s`k7iWo1UCh9_V)4=#k>ZuJHg1}|Y{Sg0TQ;$87v9Kq z@DSG$hQo)p?c<($e93{sOXPQ)Khl5f;JF^5MGLRp-FxZwjK_Vq9zA*Nba?{H#0(Dc z87!YmjvxQ<@y)yRA3tBLGyK>1*zmzc200OEGHB&c)rh(ALD8j!OEzqagrTx?yMj!m l%!eI;4;`e+Oq#X`fAl?~ksf!bN4faoqG@ht0At@;-dk86n006zcy~Y3l#>U3~LPG!l zLjV7S|Ns9NuND9R02i+oA^!_bMO0HmK~P09E-(WD0000X`2+f^Ri6S$TL*T{{K_oL!Zcbtj(*o}XEro>y3klBcMildGR~CU~;CSp~A8 zCZ(PL!?I4j!vLwG6|w*f&&i%q1rRK3;+ny+SUfx2H@M#<<{fc>%!*d;u`JS z@8t9EhyVZ~`2+OOvU1_VHtEm>SMuw-cba}L>v#qeNt{T3otii+?5dZ)?)ol#S literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/hungry.gif b/local/htdocs/img/mood/charitycam/goth_boy/hungry.gif new file mode 100755 index 0000000000000000000000000000000000000000..4d5e3591e320c932422e62d9b804cbb8b0708160 GIT binary patch literal 322 zcmZ?wbhEHbRAMkw8ht65^D&MiCl6nsTGYjj^zuF!o zQGfewG0%r{$1fW(=QA{yH#3wmOE<=}wZ!+f$9GC~Pw1OAk#%xIe{a*gNnP`2&RsHV zQSHiwQ&z2=Ez!NUcD?vU*7k`zdba0p+1hlVf3NJuU3+%!iP^VdQ-{K~bxIdDt1w@y zxprFd<{cfj##`zSwC_B)sd4$#i#xNPKUse7{)Z>m-)TO6to7sbi{(G11(7@~$e_)@ P$iM{jF!O{791PX~NX?9+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/loved.gif b/local/htdocs/img/mood/charitycam/goth_boy/loved.gif new file mode 100755 index 0000000000000000000000000000000000000000..7346feeacc963b0165e6dd3c631690b1138a2903 GIT binary patch literal 625 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3d?t7PeD|#=zI}eYMJ4{p!{QRAZmwp{XHPVLG_!HF@|n5-;}jMMoD5710u0K) zKrj#RbP`oHdVPB9^XcD9A9YN9)VVI_^}Yg~^Ch|WE7mQZ@hej7(lTK!(MIk2d78!& PB7SNnzpADwF<1itL$daI literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/nerdy.gif b/local/htdocs/img/mood/charitycam/goth_boy/nerdy.gif new file mode 100755 index 0000000000000000000000000000000000000000..f0980c221b4ffd5fa9cdd6d09ea906dcd098a79b GIT binary patch literal 1060 zcmZ?wbhEHbRAMk<*v!cQ1OjUX6crUUH8ra_G+P)L_U_$#jDg|*|Nr9a#X!n?bLV0FMMt*6DLPP%kq;L+|im*Y&&N zxn~}Un{B=RAcOSe?kkH9Fl6*!&o7IfwQTGA^v|_@%eIskaWv&sF*I@1a8?VIm$kKb zFeK+rn5f6l(={V+%G8N-r*?PE>RGU`d|va6C2RUuO<1t3Lu%c`4eK_ome@LP)50x# z+N)Pilxp0&;)L|%JuN#Yoj!ADQtRbpnbwN5Gq+@K-@1J#P43}smZy*9U%bAq_~xm~ z`XB~iv@Ez}0DHxW4*&oF literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/okay.gif b/local/htdocs/img/mood/charitycam/goth_boy/okay.gif new file mode 100755 index 0000000000000000000000000000000000000000..73b6d9d21f0d1c0ebcdf44cc0aa3601a2f1fc91e GIT binary patch literal 1010 zcmZ?wbhEHbRAMk<*v!QM1OjUX6crUUH8ra_G+P)L_U_$#jDg|Uv19-L{}*2`22ue7 zK(69{Za>$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelExfsM5_!xl6m4!{f!&Q5# W!m#xzCxZlo0L-T=SIsqIum%7`+HraS literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/sad.gif b/local/htdocs/img/mood/charitycam/goth_boy/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..73b8c4cd2cca57aeb797e7fc5f2b8554543fb8bf GIT binary patch literal 1859 zcmZ?wbhEHbRAMk<*v!oU0>_RCtQAmHRMgbetme>cVPM$1ckeNf@Uj2@|BJ5|11ka% zK(^w4Za>$MU}whwS0g;=j|Lxryni3eNcjl|`B986^rv1_p)-3gzYHddV4y zMVTd)$%(mo`9Vna=}T@ z)iT)`+28j`m~~F^n5F2|m+*S2_KdWs-1Zo^`+x4dvz1d{VJXvf?0jB{j6}bG`W3b* zcC)X)=_^u2SFaF@W8JhV&T<_v>b9@k$-RBA z7%=J%K%?&XQPJZkPMtY>PU!gQOP8-+J8|;#t*h+U@0~ur=Yao>`^C2%Z!6orH~Rc3 z!TYQHw~-NbHwPx_FmfCtVcJ0mR@ty#F2d;fuh!oc`D3XQ)rr$o=31(uhW zh0a{Ke&Z-3qwt+`7w#W?SoP%InIi}N?><{~%kh?~?KfrlgrDC3e*XCp*}=eI4FK3? B_?Q3y literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/scared.gif b/local/htdocs/img/mood/charitycam/goth_boy/scared.gif new file mode 100755 index 0000000000000000000000000000000000000000..eb9a26357e747e9166e5dd9dd9b074121200c867 GIT binary patch literal 499 zcmZ?wbhEHbRAMkM{(W@`v^-}E_X;HcD zF>d$&+<9j!r@lf_pzGNAyb=+Ke*g3_CxmK0a}H#9ZpM7Fi(Cr_yFpP1A!C3#vwWzFo_-EIwy>5FIe zi8SSOubeY~Vfpk@%g%}GL^n^hT+Y0`e)mq9-3RyW-=DVih}f|c2M+B$e0ovb@tuc` l9lUUI(v1VRZl~@(cW-^(sYj=t-g|ymOc2R)Y{SrV)&O6U$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUPjdf-1O)=6n zT?`z3T|H6_oYQA;b~DVJ(bUT}XZoU9(-zNTTd-v2?753qPF=R5W^VU_P2FvqH%NAN zlsD#YuRl^IbM(ZN!zat-jeowOCo%8Q9tHYu%^FJ+EH+c%K~m=3TyF&YVV(%Dz$OmTUaF z(y*qBW7sBkW(E!h83svU;M4*W`|=g9yn0t&xUbfyES{HeGBxA&x_7LHRMIwCc$R<4 zE!`th5Hay-hl_HNIW$`s820YndyIkM*s){(|Nj?X zF9ue}0Awis=k{|A33hf2a5d61U}gkLDE>R`nVXoNs^FYoP+63jo>8J;WME*Zpio|3 zu9uvVSd>{(nVgubmtT~wz{|zU6_SxztdI%Tk(*elke6Sgkd&%WTAZ4qP@Y+mkzZP( zP?C|VkXQ<27ZocMq!#6778hsc=P9J+7bzs>RVoyvCKdy^Fx3S`nLvqhpgkq2c?!w- zdBv%DC3*@90XaZ*sS2sNiJ3VH2!}Wzm|!=7OoeIU zz;bQENzc_PJsH{G_eq#_PVtzf=+&3-da3q|w5Z(n7`OX>?!2>=Q(xhz&~@y5UWtlC zzkm7_wkdYAufOD)`8F+klX}7%*B(aSOQIVx7H`h^UaXXNo3U$G?Z;)azn8leHe}Q_ zw>OnHwlx&h_qGaEHBRoU>+H*(!ZE!mB`!UDZt4;@k)Sa52uG}Na8q2z0hMk?0fs^yt5z%AEPo6$=R_NHNi`lXwi_cf z%i<@FPn2zc82$O3;Qi0;&t?I}5s>?+6^CDa&TYDQtn&wNz?u7noq`)){1z{$sjtl_ zN~>#XsP5?CXzQ$RY;NhR>YkY0T+lYXE3dbbCoeZPJ$z2;N`H}6YeiSGZCoi9w{aUN zA~(faPV;9xcrbF`oP$g!7?&RvWjt|`k@bw&@$ zJ-R;i^0RBF?teJ{;`8fA-=6+>{_@Moe?N{s2E`#}k@JE|2^ZDV6YK7MzF3r2UsuD? z$iUs%#a+$MU}whwS0g3(XQ?_saR`0{Rd-HyLl5Cbr*vOG{%g%jy$xIoq z^(VBhB{UT7-kp=L#87`arexR5!n*UXwg*Yn-+o)n^MU)t{hhT82}vUP44fTJW$m5u z(ls3u88{|PzOvaVNUPN*^B0NPGVa)f9|Z6O*2sqpGxm4TcZM`w;8tUpB z^LN)DI&koCz3j1*a)(&X9#S}2u5__a`HBW}IkOfkD?0-_`(4eu_Z~cYtbX_5^A{Sg z?>~H}#`fXu-7PBdZ$4dBi_l_NHe>R07Dp)!KA}|tjKelExfvuG_!)SBktrFV$*^Rv z$=Rx<%VHssIV&i}Q{aWS+c5ULIMDNaK+nqwFt}z<6^UM*={5UnWrD{nU`oz;y{{lk zgT?xK8q2T^0S*Rn1_5vg$OoL9vSja-XWhaKcfLj@YfMdpgn&+bOVW<7XI+PJ5WsSP gtbr;d5p4g?@F7r9v+wB&P$HPNP++Z3v><~u0R415IsgCw literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/sleepy.gif b/local/htdocs/img/mood/charitycam/goth_boy/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..dc24e01d936a6e817f728e50cd9aed2135c1463d GIT binary patch literal 1045 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_8p}zexc@iGk%? z!AZ~8Mi#fvu6&vBwNR3+@8Q*jirUL2y*~IV>XhN#X;tr+H?<~k@Cd0MdEnw1Xf)SN zqqwt$Yw`6=QR_EVljpoB?^&C7@-c5!g~f*3$KPDi&Dj06bdUM(ZI}O61=lvT)Wt@Z zF?6-EcQKUs)b({YOzzJW?wrQJIcwSsq1@Shix&6K?B!a;u!?K?n$>HUFI>5H)1qzL zS8UzhxpVsNJ<})cWk1+ErDaLk@t$+X&Yo`&y>wpe9LqVGtCwZ(EKs;(%iO|j&&tZd zz`^mt?#0X3Z{JzHc=PGA?YCENewwiV{;;rl+M#oM>&}!c__^`IaYakMew#NR3zAwn zhHuP*60;&WX8&C{kvVOz#p_<}{|}zFE-{;?W;##f#YSn@eQ%l4ORCEk?Yg~iezuyk zXtwD=rvolgv(7FLs$AH%BJ52_Hf!e6)44l-Cw869__ArM@9v|i?{4?bGUji$w%c{> z18ZeNbwy=MW1386TXj=+M_h0Bq_%$Pv=)Y$li6o7v@5jDoz=Z)Ud4inr87BatXeL= za@FEZvsP?bww-<3mW`WsZP>eL;kx}Yhv!aO+OlHpvXhI~ADex-Tk*9j*A`^o(0Cs@Ap#T5? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/stressed.gif b/local/htdocs/img/mood/charitycam/goth_boy/stressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..467fc5255d37b0a7a550640171f610bc748957dc GIT binary patch literal 692 zcmV;l0!#fzNk%w1VIlxB0J94K0000Gtq>t0At@;-dk86n004x9guT7J#sC1u#>W5u z{}-Gs(FW=-hJl>YW$8y)K)uMw}c6>g!Le2C%8-CX3pMF;d2ZDoKc3@+4DE@0CjM z^G@sp_v}!c1daTcQuE?X2?#BVg#nue7;I6X00ICA5HwtPp`k;F5+_n@7!hMeiX{s; zK8*Nr;Q^5z8x|Zms3XZnApL+`^JnI&RWZ5XqXohEB~>(&<+c9lel)(N6!T8`XFsvq34uiT;fc+WK)X-F&@k1nKgNfIms zP-QeKnO>aDss%gcQaj$Nv-|vB$b12nJ4KFeEue0X_;g=%7H ze1nFIX<&_f0E?53Uy6AEnwgvjnv;(fl%JKGo}_#ilBAjmtE_pdo(iLBM|t0tzH(@Swhc1sOK{2XSD*iA)Yulo&AIy*w5X aFJ5Cp2Vt2vCPRh#r_u~bDl0og0028!m^NGh literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/thirsty.gif b/local/htdocs/img/mood/charitycam/goth_boy/thirsty.gif new file mode 100755 index 0000000000000000000000000000000000000000..5f40b734a04d2bfcb16b4c649aa3f3707a209e37 GIT binary patch literal 1241 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjPZmxi25tr&W*{NQpw7U+@~_~e=W0>!jMLBW zU2;#16{}KY%Sv%ymo=yHo%rS*5%Vg~pOcw!e*0`*es*4?n^}y`XO=qbO8MuuLn~G-ilhgGM#&9d?0%zlgNjy-(=&9rj_hqnsDItYxZ*X%KD;~s_dr9?zE1M#@y!m z{z;RoCy3Uy=1neY>TQ^_aDG}wLRRRK#MK_MYu2lJvu$ScW?3V%Wi!W~t?VoZ5_j%7 z!m(xBAu+bSyVjST+B@@{>}fVt=2+${yEexaS|LdvOBkcLuU7#8{CI4 zUlzS{_ddsqLywO=7Q3_i)oa$bPd+@qd+*4@9WU;j@wHIsm*2rOLybpUE#T0k$|HG! z5guz6vMZgGU_1E2=P|1yzp6&mo*zwZ8zNQL^{fl literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/thoughtful.gif b/local/htdocs/img/mood/charitycam/goth_boy/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..3be38a36704d6ac26178e4db1b6e1ed0f10066c1 GIT binary patch literal 1393 zcmZ?wbhEHbRAMk<*v!oU1OjUX6crUUH8ra_G+P)LT3TB6?%jKgf#KM(WB>pE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&tVRsn3_2h$gF=acN1 z&((V^UZ36lKS84}C39ZJs&xxCa2QA)zvQ!1wr~Gd@58%$^L~7iY?eyc$dPl)&V6~w zOc}5BC$zp5G!*XMos+M`P=7k6WY^5Xy7RBL2T9c5ep}4*f&0b%owW=JNh0|STpdki z?Va(`H60TfI44Zx>gs3jnKr#)PVdawi{^DsVqZ9a?yQwfGgnXRTC!}pRNLlly)o+= z>gpTwch?^}aPV-w?6H$_hgi-YQaD+zbg@tQiUxBzvlc5W2LlJkUCq1q9z1%ie)r+? z7aFhcKYXXg{^9N2Eh_PEK3!Fd&|+9NWAbwrM=1?Hp;ZEm!!|M*88{gP8Ki)bDN``h zb@g7iv!`FbgGXl0>wN_}=eJb33|s#*F|aZSFvtP@FAwtnR-pf1qWizZR-RjM_$C2X zV1AZnPzDA;4k$nG-2N(6X=%-6-Jb7zXY0wEi);U{o3z|ji>-cZ zxXu?XwM@%16TZKBsEi?MeyB#%t>upE7hf+1 zQUnG-w&H(oKi808XU70nBRvCVMxeOjztf(%iRq~d&iMtEMVaXtB??9c28Id><>lpi z$r*`7nI)CUiMe|DMd=E>T)bQ%8JWcjnP45ciIoa@`6UWTsS2gVsVNHOnI#$dr6md_ z8L0}1r9gI3u|h#=QEp~&ab|v=LRx;2LSkN}LQ!gBF^~&WT~L$>lqd(2F0H&oJI`X3_45Me9=>;W!vs<__l&)_WB!}9~3Zby6wF>^=;bvxA_%e+-GmUud6O@sB5ik zs?A~OZe#Ces1mR2@2Q(IA!kz8bOz4+IWuN0n7VkvBChExx>ihCwR{Z&*Q&lv{ae{* zZCSB>{?Cl0`sjdB$$9m81ICHK}^5QwEUX~lZa#t?N-6(A{-dGg(DfZho6*#yUCnrte z7974&%M47mQoszr!1Ao%q-F2kX|K*^|DVIyCuiBE*0JpFsl0dIM~hlxOV4q2KbX9K zzKX}g%${TSCa8Z=RX>r@?^&z2GI;s46D#xf2WNco-WGSVy;*;)pVh+LZ4T%1_HY0C z#VTL_+|P#6{Ky=Jw#GJwTA|X;_R7AlOySmv44hLZPVQl!)|ol4eahU03zjZkIB6yO z;w7_Y_RZ$*-8fA$>t|BWX5yVtj`D(AfVkfWb!`p<}s_tkY5j)R7>N(>Cv0Ns9} AzW@LL literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_boy/working.gif b/local/htdocs/img/mood/charitycam/goth_boy/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..25cc66b25285450cb7f3044be0692c3e5ab013a2 GIT binary patch literal 460 zcmZ?wbhEHbRAMk<*v!KK1OjUX6crUUH8q_yHM70EsyQ@U7#Q~M-Fu9I;n=Zb|Ns9N zUoQqy$G`w&DE{a6a}5c0b_{Se(lcOY1d1yDWMMU8;9<}KDFGSF!18axNzc`LEnaKR z_z}(4bjhQ1VR%uhdtFAyzPz^+KSdngGjrWug*V$4a<=ZjE!g27X3U?N%MeoalS!;%=g)cdc{eH=8Mqo6xvT0qYTDWhdTKkn zC-qe}aZK#*?V4HCIlHZD%CzZHWs8^9`phfH%P)*yoxf?r#?ASf+jiP-V%xjPlV@l8 z0ii>6M~)skA;z4}d|I5Hos)r+^U?*;OP8-+zj0IO(zUzy9z48!<=WE+9FJaJyR_tj z|KnH3AGkl0@la&>_n(1L>ZSOG1V>frf1(j5HYgr$u+Y;e@%WhN!23@tE2m#49Nv`f+F+F4#^PC&;odKwA7#^7 z_~=*@^E_1(57TE29imD|p~}O+%OJ$S3=CC)35E_!w~9Pi^Ztqabx$QxMh0sD-o?ET literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/angry.gif b/local/htdocs/img/mood/charitycam/goth_girl/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..440f153206669ef131ebebcfc3a1ecf8ebec5122 GIT binary patch literal 771 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WYA$?U}jKc&}U#^`Dd`yF?*^-diBQ(m)QGeN%&oJnYMD} ztogsE&5JrdrMIa3-LWmb?^ND=bdrfE+R9`!Uq!vdYi-o}84e1YkEZRul^e0xcZz3h zaYb!d^UTa`F=ty(zt7n|Q~LPt>(!<8&6PFf?2K$|QQf`eLYaBlY^+_ZQS8%ux*HlN zP3~IQxo}EXWo=Fu!|EjqS2N6+J7Fao1IP9aOSbLUm^+`5efM^bom&s@*c9J$==g>+ zhZ&L^S01{0Y{!M-`PYvhxpVf?soCd`KG~SE;Lg!i7nVINU$v37 zzvUC^9x6L*xGGb(->p??!-Yw<&RhQ3ij@1uFZ9@aY=fmjg0Fj|>%MOpM~(zCFzT|f z)Ev2?mclkwjdNK@XIq!oOry*y&jbcFza|6TipU?E7c82~+4aap%WDmJ9P6)&CEZw zum7hr&eomd~HFoMHNmSux8v zHm#Y@u!&>MqNY^#ZQFOO+P`Dn?$&*W)*Ro@kRG1KcKqUn?HBWw96Pl6^35}eN9Ub7 zu<`WT_@$2@9lW)+;{37|D=&QLF8=s!<&4L=IR!c)$AJhJ34gU7xh{=BkVb+U*?`gdOt4}@$7gp z?f=f$?o?)}RO{|nC$0$AHy=>YS{pR+WMJMYUfcW;)#<~3`WPsD!RK5m1rj)J9x+;a!F2R z#FYcbn3)V8b#Jo09LL7=TJz1bP0vJLGqHUA`dZ?iBezT^SU7>-+y zH!W;9+%BLjrf}lm!a3a%cP-w8Up%|GJB>xpZ_D+K{U`17-kg+-T>r$~QZc+J=S86K zsR@S8n^XcWDf_gtlzrP%!jOK7*(p2=j&TJ z_KGOCyrfm@a$fH%&^cd{d%t4c`8yFL-cjDTqm&)&6fQ4-_tpwAGARCw@XSq2Pqk7=&M&Ae%1qBFQE<*kEXpjYR46Ym*Gq=5lM{3G z@{7_Hj0_A6dAWGG-13VQ3W_qz5=&AQ^78Y5nsakgi;^=Fa}-L8Qx)>_aw_#0tO1xE BI(Ps8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/cold.gif b/local/htdocs/img/mood/charitycam/goth_girl/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..6d3f7fd70585fe95ccfe4c581338ce97fb425707 GIT binary patch literal 2172 zcmZ?wbhEHbRAMk<*v!cQ1cru&PEP-w{{Qb`VA#8N@3H^?&z(E>|NnoG90pMQ&+X?L z671|4;A*62z|06#p!n~CbACZ(QD%BZiGq=VfuTZqdAVM4Mq*KBNo8_ku3mmoIxiP5 zS4c)`ajHUQZen_Bu|jTQr9xhQi9%AULTPboib7_dLSkN}LP273HdsEtNFfb~lk;

    V zDhv!PpA1fVrgDf}Kl^;^{iT&RuJZNo7o@5Fyo+)F~jQFaf}^5ZgEfFoau6Lp`81f)3rsp z9^N&L*=@B9?z$m0{S8H3hB2*;T@$BwS5$h>EX$mgBO1GKLFk0?yztcYj4Yo(i;OJ^ zxvGX+cO{wb%wS<)*|tY<->!{Q^em5;Tb**qm=fKxql!iIdh?vCF6`_FZXTTNWHLwO z0n5u*4C-d0FJ3)(_nGy>$CufkWkbKeV)yx#^QBw-!d-__R#rKc2^$VOwegzU%n@e< z2Ll%<7#JCNfx(~(42FNeU|7CFEW2{!i!0kJ7pS%^535U6;$i-Abk&W$I@Ss&eqLH9 zbN0K@fhwlBH20SyW;7y);SKRCk*XBjXZs_g$BepbQ zHp9L%&w8w^YzmCx^Rf(z0*Z>#HLJ6GBMe;QBP%ua!YjiW=6Mx!%ws5;DN|x-!w|8$ zV$qsLbDc=*wQIJgGq_rZT2^n{xjuc>G_!C+wr!^lone^f+_wMlsxt?zld~cN51c)` z%iAT`|H_jci&%A3jDuIrzr2|BfoOh1z~%2-8a7R}sh;-z+q)kdH>^B9rJjXBfMK!z zZ81Jp(VNkmH98mAu$&LjVs1UhI;hN<-NyYM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WYA$?U}jKc&}U#^`Dbv_uO>R{F8lW)Izx7kg- zwJFL`{E* z=Lrv{K2q|z!N?dOkmgmU-ZQ_MiQ|ugf`j7p6dvP{o)>*dN7dBSwaVW72yAccRlb{R zQt&wLRC!^=9+{iU2ha4G=I=Vaa`N-D0)i+Z#{>*H18~SKbzHs2;`Lni{|VbewJ3?JH87`7eve!?Dx25C~&}JviP!=n@iG`1f4T>d>gg==G(N_ zy2VG6d@FOeEjsz8VtTdh>G$_FehU~#%&2e74)#lBW36NLVee|FFD^-FtD90grM)h0 zVp(h*!~E$}<}>t9m=rRPW7U%B468Vn%&LlIU$=h4qU{@&ZLZz6YsvoY4DtSPZ2M21 zSbs8Y&c0o%PhUI|xp&&39V-tn4WE1a*3L^y3y#lQu<*o-=Iod67ETDA{QljnW9O$W zWcmH!Tl$Zme*_kod=S{}^!eV#n=Bu0tEOkpv$a-O;O!cGjbmq|OCSTInk5TMj8C#| zGTTJC@2w&$Q#(ASYDGGECNQX;sny_hP^_3dfBsC)szWSVjw`$tIra)UtSZsGxJ*$A z7?}UOlJg5Hi!#$QN)(I?3=9>@%ggnWGZKq3ODdBSbM^9z(s{Xfx!m%L6bgzm%Mwdc g74q`)bd&RQb5o0wGZS+ZN{dq!^7C>k6%`q*0l?d2*Z=?k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/determined.gif b/local/htdocs/img/mood/charitycam/goth_girl/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..e5322b1277a7b93257ba65e4e9ce9ee3a21178aa GIT binary patch literal 815 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;WT34WY7UARsTvaIaz+S2Zl?z+;@j@*z^hG~7>(-_*?JH4lJ zES%lPu#jW+#KKVarOTGjT(^Ags`9lPXK!1_5au4rw(Y?FWd~v>m+U-zXyc}UEv+XO zpE_AEulLf$1&byWB+Z;YWB>iCyAPiBwfl5EdpdFNv1@%SpJt@Qz5l?*(*3LMam}k| z$2@kqcgATM9P5!4aA-|jo>qN|BTA!zL6C__rYVzcqtmf2%})ktJw-~%CnhN8OZ=z^ zy64Vp@@?y!aQEY9Cfnt;omn}V!GErOep3fZ;4uLM&j1>DtEVR4Ih+6PDb+ONphJU^Yt#~5q*&ywCsMFI>US$i^1b)=?N)mcqu`${NHzvAwOTIxV|( zcE_ClX))!!Yz#~1%wEc{Aa!O`D+9;IRdY6MTAi1|zI7wV<|TVJP48*hePGqmJq)R# zy}Qrt-*hsk_Q-*g7p|RZSle=A+xnXeVv|=~-}3BG;fiI;m%QnE_4d=8>Cv-3e=a_A z_KTazWZwfc-~)}-Q20Tm6_>SiqH3B^NusyORx$|aB?_s ztgqZ+hRDzLOFRwSeYWNNyu`)IteyTZI`hCXmKG~Uu}_wYFMJk>^lWp93ejX-CN#&c zRZG-`1sJ6Nypr<^DvL7HGfEVU3=9kv%FE03k~0#EGD|9x6LaYM|8x7fh6Fo1 z2DlpO889;f6)65>VKrjlWY7UA1{ur1^3UL;=jy!{ug~uOpPkg@0$k?MY-z#?W_Liun)9#c?pK;=6Y*sYWv(MkXWTArI z5x%@nJGkfA9{o`?&-S?AJ2r-<%8Dk2TIYJFBnFPY_R8M=j$kMDNqrm>8fW&GWTwoR z+rDTfgR_U@oc?92XD#z`u~@fw%Z8Ay&D&-#ZSUM!v~G6K+K#gBp5~UuQ|Y0rPG77n zF=@DT(Wx{e>om)~mOz*DyRK)aPrY+J;MRd_6&rmw**LN@IeweJnF|SVPUM2_V{puy@^}gOeawx(Iuagcfx_N0Vi KB%YNV4AuZdeyUjj literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/dirty.gif b/local/htdocs/img/mood/charitycam/goth_girl/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..786b6888a0ae4a1bf60a1c774bdfa3905b214826 GIT binary patch literal 1430 zcmZ?wbhEHbRAMkgmXk@NbxT)!Nq0+} zmoqavvyEP^MW6eOj#=_EWS!@yd3LZei?5Kh^H?Lwx}15{rd4Z}%4}!YvU|%850RaF z4jtIPRQu2&mL2;#Pi)duxVY;a^QB8yu3l5PaqIS#yV7?q3XYg~Iy&g$iGgXU2g8=V zTV%G29Nc&0(C%FtM~<)@VA{FP@DwnvuI{9)e%YY(m{+y+NggeRy}vjP@ZuyW8DQv6{l3c*Drs5o*1mTv_`nPrJ3 TslcKz53Q^N7EU>pdJNV8xDOo@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/drunk.gif b/local/htdocs/img/mood/charitycam/goth_girl/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe65e59a8704eb7c1ae16052858f548bb43f9d42 GIT binary patch literal 723 zcmV;^0xbPUNk%w1VIlxB0HOc@0000nF)>mA0Hs1gy}iB8&d&e;{{R30A^!_bMO0Hm zK~P09E-(WD0000X`2-0v0000i00031ApkJ|00jOJ$T_CHxMEDUpWR1!+E$9;)upN^ zRVPr!a%~dTI;1Ow_dgn-BNWz*7M2UNv^7UdWmEcGBCFV}Rul+Wyjw|EJnn)g^j#m=|my?JbXgLiX)got-veFXso1YMAld}51kkC}D1-G@Yy}6+Ty|=@}te;?)2L{c|&cn?H&(pEX z(%1*l*v_A+tK8b)*`9lCnAGCv(&D*%=&i24l<%(gql$;3_x5g}pmyvD7`W*asxMxR~*5CH%o`2-0v0000i00031ApkJ| z00jOJ$Vn?0HtQ`3{~yMQ8JT&ThgPbFnG^}j(?HmOYQwG7Td&au#sV2j$K+(CG!mQ8 zsPq^JP^{Ccq-y0>v|0@oz%6^X;c;ecZj;q&OMCA2!rAnEnf!h0|7R0<1px#ERfmal zTUTv{k5vVSh?8e{j*o_gnUH&zWrhc$oS~y`f@Yd#GgvuB(ru zX=q#o2L{E&#>2%1$IGXw%*xBj(Z+$nl+e2!m6ahqvm#)>hR`_ zbMf$Ie0=Yj0{oJlo^QUP%T&PMKY+1P)uV&&8a+cI#T@Z?@}$Qp1WLAa$&X2rMY^fyJP&M6Xn&IEcv=t-hRj{;5lghB)W F06Q0;T801s literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/envious.gif b/local/htdocs/img/mood/charitycam/goth_girl/envious.gif new file mode 100755 index 0000000000000000000000000000000000000000..79009bb42459a2f39755f34a8f768fef71830937 GIT binary patch literal 1044 zcmZ?wbhEHbRAMk<*v!cQ0!|DJEewW+hED&TdKeh??%jLt+`0e%|AXbw3B~{1ey$khD}i8_!hdimouV?%pu%K>M^5CU#~vHq}{k zVpJkMa%V1{J!`3)MdHNPrHkjRTM}nzlrfWG`-W{hs#fXhZ*yeWz;JL@ok9is5wAlB z&Qxq(&34+0<U5D7dL{eZoem8-i~SwFG8z%bXCIq|?4bc>B$}4dogfQo_HO z!W1h$#O^Us0>;I^3(olkl|`B986^rv1_p)-<>lpi$r*`7nI)CUiMe|DMd`d;yj&p} zsl}-ZnYoGSsl^JpiIoa@`6UWTsS2gVsVNGXc?yYnl?nxk$=P7}{33-kAWqKD%}p&z z&P>b!DbrI>@Jv&v%r8|aPs}S(D9Hy2DwH6bo1C9ll9&vX%Scs7Ov*1yRR|680qO%e zAQGq%WG_@xu0npELP2U#aef}q`0~`G;>;4D%l!R(B9YSLVc z=7(jgqV~qk?9XDDanQ$@VfE}d#*QDixTkNv-H@98 zhN3RRnAXOwiPO6)D!pfxWzNbGja|4PbV7Mvcxrk^mQSEX#+HO!Rl}{jl1z7Iurjc2 z+oQN|*TyM&mdDGjPB~;uiEi0Z#j1I|dCpZAcJ>1|56*TnnIrOm_2nxDbu-ZyuO7Vn z%=Y2q%k0mxq2FJz`~1rJ(k*`Bu0ts+tDMe+4TqiDc+G9*h%*ACHo_AWUsk|~fW@#g lBx12dGC1-<0qq8ixq_n1vc!^9U?k_E#Ue1+b1L;1tO1T6q;miO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/full.gif b/local/htdocs/img/mood/charitycam/goth_girl/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..c6ce1f4233f9d0a0848ad3185c9acd34a9d0ac8c GIT binary patch literal 646 zcmZ?wbhEHbRAMk$AK6CusDgWX{W2wJzuNJV%Fg=3rIm(zC}ZJud7iWx81& z=yL7)+4Kpg&jg&`U2?nf*&!Q8Rwl;}v%DiiLs{S7G`#s~Lbc={rcc(N92YnUv+zi% zI3)EtG3H53tC+#d>e`{M7qw)^N5ysyV5qG}M-I?o&J5h-81*dVeK$qY6IIR-JHDGV$YAT#!U z%9^vC-Q|1c!yTzg%Yt5B-}dCktdiXO73*FfGGW*&_kjHlNBb1UjVmmFO%qOcy=5|M zjv&H8tPC;?;y~jVSX?IvIIP|q@o28;|EcUvmpx`>tO|PiYF~2o$%3_93ja8*j{jac z&vnM_7i=yK2@alGn#?NsQn^yvfoclTg+iNey%YV)>;iP=KhNa+g36-I^o$Y(BLf2i zh4S)pz2uCGet~{Qc~$ZfnkO z=v_W}uEF=;u`MSap2<*FoA2Gt<8{?@a;t;lYF?f_9umGgbXRXP++up%Y1-NM-}_`$ z#2J445aWNa?zL5QYHfZ?d3?QXV{K+zPdYY1l&K=!p`rum9zk_eX2+F@LL6T)A#ZMHtg*q1DyLRQB?g=(W#0xnj%Xl|j1RXO;+R&XrmI z?8mCQY1eYvSFUvfhWft<&)mfHR4aw#{DR7&%=C;B1?P;!qRf&?h4S)py<`YGIWbo+ zzbIY7$iTpmmy4InEx$;ipeVB}u_RR?FFy~cIX5@8C^<7RN1?PhRUtnwr&5o>8UPNk B+Q0w+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/happy.gif b/local/htdocs/img/mood/charitycam/goth_girl/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..b16667775a9c83fa6760697cc9f05d030083fead GIT binary patch literal 656 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/nerdy.gif b/local/htdocs/img/mood/charitycam/goth_girl/nerdy.gif new file mode 100755 index 0000000000000000000000000000000000000000..3d01024aef4c26ee0f38b4b0e4b3b264d6d3a18e GIT binary patch literal 910 zcmZ?wbhEHbRAMk^rd9Z%UHE8=k+{Chm&bKM~&icmbppqSn%%J@5H)8Di<>LsLc0@-MqaeYU#8) zrP61dI2#WtnCaQ)i#Awkg}7EHEq&_`Q>v(7SCI-VCwW$)BC%G=k`xqUbbRVe~8oa`K#9~ayHJ{ zz4Gwt0~>N$Hn(-GnH+n<>1Cx;E86_1!0m^rd9Z%UHE8=k+{Chm&bKM~&icmbppqSn%%J@5H)8Di<>LsLc0@-MqaeYU#8) zrP61dI2#WtnCaQ)?_N^jE4RJ%1!u|GWtSiNd}TPWz56FaUaYZGJ!^Yo2}3(;V?m1} zOLtFi_T(Oh=FF7oQyS;aaQ1Mlo-t!-$HM;5Ia8J|=y0BpyP$K$@=Zlc+B(Xncg|X4 zF|D?)Au0V(Zrz!jMJ}yp&sG$jI>W@kR2JxRD)G{}E1P#;3UHWRe7oQGg3UxG#}BhY zt_B&hurU2H{PiigQt}t)oAM`z4>YT?$=Fyl9GTVn>&T3T75uEOjAEK;EjtPo+c|(S zt@tm(6BK(^z-WQRw=*P~u|zpIDS(3A4H%CFMVV!ZC8@wD&qIq-U?k*J>M>XY0Kz5s AssI20 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/sad.gif b/local/htdocs/img/mood/charitycam/goth_girl/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..0ad8a4bbb1a0c2416d0f38f5970658376b63c5fd GIT binary patch literal 763 zcmZ?wbhEHbRAMk-nxc@Ir;wOesZfxZoDG)GFH%SY;^h3?+|;7v%)}g!GCc(a z&oqU~{8EMT#Jm!Pl6;V$LJ6|D$@zIDiOE2@j8uihr2Mi}h0q`$pgxcTB7qt~_Cht~ zD&*%W6r>gv=jQ>9FHcP>&MX1C%-_!^l0oq&3#$>(Z#tlW00jvH%Rhk=o~!p-ygs}8 ze}YC|O6I(bRqJwI&uelxnWl5pDDGyN8}p6@@2>q$tUIJ~A!Coqe6QHe+gqZRPP};LQr5#-@!A`8b zoowB;Q@Uc~QYO!6o;!uTsLgSD*TQ8}7kar^tem%gb;y!+8>cO3ZrxI_a$4hxmTIT$ zriR-3e%G2~XAV|{Eu^I#}VMcxN5KI3jts%i|_;`9V=j( qfF(9(NE*YE-oWV)6z6WhL{w0eS(aFm3QTW#XbB3K0&*(#7_0$)J{j%+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/scared.gif b/local/htdocs/img/mood/charitycam/goth_girl/scared.gif new file mode 100755 index 0000000000000000000000000000000000000000..17ef2c3776431851683722c2c5fcbfe76b88f4b0 GIT binary patch literal 721 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;pAfAWYA$?;AfC$P-b9Y`Dk#`(|Lu->zt)~<=Nw;X4Yi9D1Cly zoo3ane98MSdHmGgJ-5A^e?n*(A7k^uO*!{$45lnxpcBCt_AKbyA-^ zi-_h0sGRerZxZqhsV7~atKhJyu(R{2wBFWjIL!*@;1I6YW*zn?*=c5~-6NGP0! zg@XA9cqkY^Lm}0@y`rOQ;>4J^?uiqcTioJi%`ECkiS=68Shm122ow%$9agW~96zma z%a&^EdD$%cvJH)Emd3Lj4Gmb5z9YZ&u;#jhj!WFxnKZAr&b6{)zsAHO&cbw4PgR!l z$%B25pU9d@KY8=!-HR7&uRia4#r93+=&w56kJlA}q40ud)9dzvW~X>oDXW?eJthXl ze|gFI1(ija=@}&oMg|6k3gzYHddV4yMVTd)$%(mo`98T1pZgPHZZfa3-W?~LViJpRj8&I&ID6=fF1guFRKQE_J HkHH!M*V!Wf literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/sick.gif b/local/htdocs/img/mood/charitycam/goth_girl/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..8be8f4874dcc91f08efdb01ff732c05df00d3348 GIT binary patch literal 2383 zcmZ?wbhEHbRAMk0BW_Qh~+es*k{hA59g!h?kK^EJGS&Yal%!jaXsR&DRgpya^C{`0$Xv?i)I ztPWh8#M`-f6(fVdA*K$lus1=IOjNZrq{R+Jtj;~UO2=bL?wyTgx0w>EE~($%AOH2$ z(^+Ndahu!k-jms7{Ne7R%Hw+PZr|7#y{W45obH-0+Sk^E-)D23xwYiVPEqGsakg8R zyjsJWq-=W2>e1`vTxpl{&fd^|eKFQ^zL@3YbzZ$(Tqz;@B;THy;Xe7eoy6>&K9kOI zhS?w3Th-XD#%+@Kylz3&kI!t!ChN=JKJc^6_4;IegWr2Se|~z~etdsilTSKC>R#j^O3&vbF&x{wpbPaWqQ8;TwIae48@879u_WU8*bXlCx)B^JQkbXsG5*{eU*|f8}F{IIw70W);?Mi@mafJd&c&CtPG+W2WN3TJ-0Nw zOh0z3xTDzz?(p^ZXYthXsqswzczXgH?<7`+g+`611YQJf>ydN_I;qH>EVs6@M7H+;U+Ivt+bzZcaEfP?mlnF^>boxlqJqIzg?I6V8M@T%qKdfze`Qa_3BUUw$5nS zv#VtNiuIdB*VI&%KDoZOhU=`xpO>YtPA>iJv-4WznH?DuZ|&hO$%*+WE7^CqE`YI# zm6xG|A;Exm>)kT0AMFR~d37uj+{!ycgB&NZz%QXpNv?jj`%iUd@wM{Np&zV@wU7Oh~zMM@TglOZ|Nd8{cArS_2}QsSj=Q$ zwIsQh?aPe|{pMUJ1t#i!S`p|l8Y{SR37N4XDALf(%GS`}ENaz~*e1R2OAxbsnuG(h zl9kJ&X0~}V7Pae~Du38*aLhuvmuKpZ`@I%X63Q)%Um_;->FyiNCD=->4%(Jle5?uw zdQ7+k92j^GteDtidZ{9r!OHANa=#th$qN%)Ze^r6dI)hYabsiz*C<>ARx>xQPFUP@ zcU94giyITSF4DdIRr}V4{DVfeFOBuWb~Eg_v?lv{?w#3bSNn9O$}=68H!*g|?wPVG zXn&-ld7q@wrqsp7fpObxwx&E?!|J4bbj_wknMeGc#V4G)ntbZ)|Ne3 zc4EhDUC;A^{aOLF6Mnp(D&o6Jui(LfPr!P3Ro=ar(l4*srUkE;yLI4eo9j%4{BpZr kyH9?6eAeB4e{AEgwl^!Q>-QVf760OSD_@Xrq`+Ve0P+v=umAu6 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/silly.gif b/local/htdocs/img/mood/charitycam/goth_girl/silly.gif new file mode 100755 index 0000000000000000000000000000000000000000..f3189b76cecd63a01dc4dd783a60ce7a6ef362e8 GIT binary patch literal 1672 zcmZ?wbhEHbRAMkF z^;|QjIZdAq41$}@)-5hBEH{pbAGz&hQX%^E^;31TS8raw|IGaHBlBn3&~Ho;KYq&o z5M=)0w}7F^j7Nz_qkygffRqC23X0p(>wrn1t0TX$8x#O-wVjQ#fB`URGAIE07A&kQ zndQ?w9i9k40bsauA20wip#iWKmi6n?V@> zuq@D7)?WwoeQA1Eeo;+##gvBWb)f|dih%*qP!>Pir+Erd0WjHV$`oJ{xV3KXp8G7& z0GK;80-zwhJ-@E4+o;mJf6Al@U7!>&v0>u8UQhx6mI82$rU|8J;WME*RP+nfHmzkwQRGW?5oMszP3Vo0yLW}?ay}iB8&d&e;{{R30A^!_bMO0Hm zK~P09E-(WD0000X`2-0v0000i00093ApkD`00jOJ$VsKR_}0z)7G5X<;AmFmsivyQ zw&DwW^32utmtlDi2LVd32b2JV$4ar-83K;bq><_5IHTBSwYtH2v&rrCONKs`+Ok?Y zAr}G!0#Hu(8im-n9$1ji{ZeCjdU0@sduD=AaR-fujE-4tQIL%XhnA6MlTZbjmU^F! zn|O1gpr@l$Q%3{`2C%QOuCNBOwvv>$wYIdpv23h=ySVC@Bf%UAP5vnghOP;Xygo!$Y>Lwq>i3csWeOcXusNQGKdA6x7efj%$`EOg#dvd zq}#vh$#>2d7U*?=Rb_j8b8?1#QC4qJa|e)#kC9<|Qj?GeiJ6p(mQe+qnS7#bd&}eE}&;thp zf6_`x;+Kg9-{9e>8fc&cQTC^~<6`FA_}vGNL9z6~U$+4WxjBj9FCoHi lKL|8*m{3y>QWOz>`;pNh5C9Dw6MhVda3o2SAxlI606Pb9C2s%# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/stressed.gif b/local/htdocs/img/mood/charitycam/goth_girl/stressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..68ab6834f092025905e187d7da69087bba0b2756 GIT binary patch literal 734 zcmZ?wbhEHbRAMk<*v!cQ1cru&K@1EnEiF?R7`E;Ofph21{r~?TB!>YM|8x7fh6Fo1 z2DlpO889;f6)65>;pAfAWYA$?U}2DF&;wHc3Qkx~-uvUyEVpg<)YBGjFIDzjm~ms$ z8nx+bMe@yV+}yG{Sxq9Ky;#(A#}thfIdwD6ttj!D%Ely-bG7Jc+4@_j&F6?VpO0NX zEhcR7!A_I%FYER{j^B9mTzmV*+Qy9Pe0D}Qw(!pG(&CB?Hr5W-aP}!(o$1A89do9hCmns+XJ$?|h$`M2+L zS^le;zIy(C?p%w!S4(y`PY_sO%+4}rq6JUCoc&ZKE`@^D28J%z99N z@w4Jn$|+qouWe_-FF8!DH~y-4Ym!2`_dKzhd0S2fXY6Bg=oQKkVnhTZ6CxN5PI^Aw zA#vT-{gX&U=QZ)P@b9V1S|`b6c743DYlYPEFVgo^X9`Gc+1qB+S9CJRYW{^4C9^nK zG{Un?v-g&1U(;3J{dU&L`>TX%?Yh-d3aa1zE4uk*k8Iqv--m@NL17ry)=^xP&c@ox z8pb}My)7-GxOHa7tiGw4wXv-Xi)YPT%rGxAcM-?h6|)%Da;(T(z{tLF)8=KnHcu;9 zxO4A{L%SH}_Z&LKc52h{RcUATuDf*ke8rTbyVo3>cVOY2+k398+}5&a$o zKWqPt4o&^ zU^FWH)4JqC;bLGgUIz!GmliM>uY_MZAktv`UG&nV%}d2NZT)XOk(}btINz01r;~xf F8USNnQdIx| literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/surprised.gif b/local/htdocs/img/mood/charitycam/goth_girl/surprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..9c77f6ba01aa94994c47ffffa2f684694203bd80 GIT binary patch literal 588 zcmZ?wbhEHbRAMk<*v!rV1cru&K@1F27#Ozh-FxiVvH$=7gG6xv#sA!Xt|7tBjsdPl zdIrplKxK+QSy+u2*co&{T0q7!u>AXQ!gKXri`Qp&|4-29OUayv@h2C)0F} z8pYi#bCch(;N7*~iFJomE@bRcneP?5d3#IL(rI@}rO!BVH!@ksC`_5ZJvQh}UuWTa zy@GEk+uxQwtO?R*_*aos&yZYH@ju0%Ec4<=TuFZzhu#Z+0G>et7ml1ZjIZqx@YFv!jRCZO%09BM~Z42&*v`Nu>V41 zmB+EXM&>&efi5?1T|E=Az2k8}^}P6d>wPcZWMy*v+;%iG=oS+bvmx{EZ3kpeZRnTZ zUjMtV=0^F4ghN6sTxL(gCNOX^v2ys>crYyP>=oh-Y7%1 z+>Zs(=MoMtSLa%^WJy5iv&#?tln?>W1~gKffe&b;#|ID2S9?V7@b<8?Jd?atRw8V< zaFSM@*6eA^6XllV9{Y9o{Z#ok*SLfV-GkgCQXW+}$-Qy@cqVMG;M!$RdsfUjqnm8$ w$CXjc!l3w1F*(1WvM4h>qeQ{Tz`#(Uyu4g5IU}(sv!pUPF;_3YD4oF?0MUl$qyPW_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/charitycam/goth_girl/thoughtful.gif b/local/htdocs/img/mood/charitycam/goth_girl/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..c4085935f3137dbf596dc83193200580f73e0187 GIT binary patch literal 967 zcmZ?wbhEHbRAMkY7}>~%#C@+f_K+`C)OQOxsb6(WxiMJ=It#}OQ+o_ zl|JLd&B&x^re~kOdr5__-1gQNoF!+MU4H0e`tZQ^?w{;=vBpmIZ0(ID?Corg1uc%O z-95e8lY7{kGgGEdX`DO5*~77V#*C#M3;RRoOj*95!+ApPg3cAoHx(^u>nNMvIctr@ zwA#9cr1V3%b!T!GxwM`=TTyiC3^O}(S)j|Q#7pO{Y~Fn-z+rar?S9`2HWQg0KgT2~WLru8 zV}l93soIq;dju!GU}7pgJa3BUp-6S>n?aE!i@LNod{mxS>g%6V7*!h^s2P_V<5?cW zw92;p_$M zU}whwS0gvWH2R*1vWP^fEiYM= ze|6i;Q~NAxSDU3hKMqU+Nu3NW_7>ICrp>OK zR$(1IwP{ILOKZy1?s;=pWX|eo%I@gyU!gS)`EbtWh#P;*&CpG!=zZkyR zY6m`u-xtfoT_SK`!$Rj;Hl}x{4;@^1v|Uh9FUMlR;^T}F;-+~Ier#0n=>F+e^yac) z^G$CqmK=gFls8 zcbdyiLG92UHk%lk(*j8m8&jlb`L0xCLWDIJgCGzx1H+onK-FRCRFNAo`q$&lTLl>u z|3!G_CZ?xaDJ16?R2F5XXOt*7XCxM7mQ*T~mzV1$L)giQxqA6U=?X>$28O&`yj*Vi nMG6H)nPrJ3sS0`dc|gs%xv53TnTa_HrNyZV`FS~&dJNV8sWsp< literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/angry.gif b/local/htdocs/img/mood/classic/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..e1fbeb5f0ce20eda0aaad987497cd071d31385c3 GIT binary patch literal 94 zcmZ?wbhEHb`FT literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/blah.gif b/local/htdocs/img/mood/classic/blah.gif new file mode 100755 index 0000000000000000000000000000000000000000..d3c8b47f0ebf9fba873c1f2786275985cb2cbdc6 GIT binary patch literal 92 zcmZ?wbhEHb+|z`)F)1LA<>8JKkE@XkCwndxDYLR96e oy$qhZHVcJ26*Ka}R@LdYYblsbk807Y{f2mk;8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/blush.gif b/local/htdocs/img/mood/classic/blush.gif new file mode 100755 index 0000000000000000000000000000000000000000..ad7efa2fbec6f55dc4d486c3f906b76a7c5b69d9 GIT binary patch literal 99 zcmZ?wbhEHb07IlA A4*&oF literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/confused.gif b/local/htdocs/img/mood/classic/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe5e522b15588682a59ae074ce128078b719518f GIT binary patch literal 112 zcmZ?wbhEHb6lM@)SjYeZ|NjFK2q^w!VPs%nV$cDJg5(*P9H;biaKDsD^3Dkq5a}!8 zT2pXC%;)At-K1ZwD&f-({XF>O_0_v8ycTkZ{7rC?U)6EurI)B8Yi9MH4lmxVuT~`R IvNBi$0CT@8GXMYp literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/devious.gif b/local/htdocs/img/mood/classic/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..b2593f38d9dd090518ab85bec1c5bcf94a5f5302 GIT binary patch literal 913 zcmds$F>94!4292yBCTRugwlcv79FIhC|O#%SkQYFS8=+FAlY=#%|+3v)y1|5*}J&- z3p#ia3rZFp93330;4jc6KEZ$CyM-ht&p998=;m;B?e3iB^h5uiNiKzyQi;k;=CY8b zth(tYcX`NDUOgM8a78FmQN5a`bY&=0StzMY<*HDniUMt<(PEkD>O1}1EX>lZ`Ye^Z zd6=hpH3iLZi?B$GYA9yYEyFS`3r1G0+$yZnimOl~1~iml(c>`MNTbDawV|$g;hyf* z{y0k&;gKHIcA=n|;hCO=d!U&03a|9S9(jPtHgVt|2pmF<7|>8M3I~VLMjEZ^_R~^Dx=7eqzM2n#t9m?L`fcCvP~Q?VHk%{BL*~^V8Ov*w2`j< zL_JNLnpb==g2W$Zsj{j+Ai4h6Z~6Dsplx30KcW8#O+V1tjX$ILryI|wmS@J(GkSkx zcH!&R?OV%xn~RHg#!H*8hc8YZ8$MflwRcr@>hb>1`F96fM=o9(fBbyr!^@-V-_E_c x{QY3(^!+anS0CNGwmW(<>Ua{)J-Va+G zUN$et+WqMsLvSUdT6k==7Mf*Mo_{ F8UTuKFO2{I literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/energetic.gif b/local/htdocs/img/mood/classic/energetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..caaf284aa0e8f88b7e9fed05344e2ef78fa7c938 GIT binary patch literal 313 zcmZ?wbhEHb6l4%&SjYeZ`}gnv{~yFq{Lk&@8WQa67~pE8XTZz|68g!)$;iOWpu@<( z#J~@P3`}}+cxN7;%=9oxA*%A#UItHHn}x!iiWzxftLk)@H)@L&OZ?PK{Z=-mCM!i` UpEDz}5sZ`@!9ckY#j39;%hyckmFd4My&OAPW@nMouROPF^ rOs=vGbAM>aOVnN4ocpG;ZN&~Nq4t|^r@u}7JgG#A-2U_3hKFef6mIvXI7>SU2cpF)&PEy9cTam literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/classic/sick.gif b/local/htdocs/img/mood/classic/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..217a67cbae60740fdc90b92e06b977cf7fc56699 GIT binary patch literal 94 zcmZ?wbhEHb|6B+|z`)3$0}=(vGcf7&@XkCwk?CQQLR96e oy$rdXnO#3Po-UvHQhe?jl|_mfopNio+`JvQ`qqgaDOLt+0L51ydjJ3c literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/angry.gif b/local/htdocs/img/mood/growf/dwaggins/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..0369268f2cb8f0f662504ec5515021c7e65df8fd GIT binary patch literal 997 zcmZ?wbhEHbRA5kG_|54q>gB6B`yDZWmDYnv)^Gz|bVFDYj+C#YcyFcof>_l)5$Dad|;Y1^NA@dg_d~ER!@I5$8(bs;|zVvRZlEGEkCkQCUcsO*QWGSb4|E6 z)Od=%a9CoxlxafO#msXPt+sRJdToAja8`hB8|&%MYXVjjbXMKDVYu$@HqQ2Cvew^{ zW2P~$v3uGn>hNH(OuZPNj>VFOSu*Sfc{P)k1Rb5?{Aj6{;DN_Gr3|?$WM=8TxU?de JpNE6N8UTQ4WPAVs literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/annoyed.gif b/local/htdocs/img/mood/growf/dwaggins/annoyed.gif new file mode 100755 index 0000000000000000000000000000000000000000..d077744c7e0494f959a4861402a47cc924362ee3 GIT binary patch literal 976 zcmZ?wbhEHbRA5kG_|5}|adFYHUPe78j-Q1OPE1g? zt+SC_@bqL4bAnaM%}vWr&k(eX+9Ek=$(fm^mb-jj8ZSH1YSJv^aWnA2#TK3NwwPa6 zGOsr4=Q1rgb#aCFq=@~Wru>@v%zw30<*KV)o05)iEjX^_BNe{fYenJBdpQ}`@-A%- k*qtPzAiBY&-^x2r#3ABi!eJ3s>v=vqH$7!!WMr@g03iuo^#A|> literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/blah.gif b/local/htdocs/img/mood/growf/dwaggins/blah.gif new file mode 100755 index 0000000000000000000000000000000000000000..d532f9ebcb418c52f79629fc0cd90fa2a5ea0016 GIT binary patch literal 977 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zIMy++bI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz)U#hwaZ`@x=cf%bcrBxrL>e!3nI;n}q`=Vd;_PfC@pEe|w`90CdI~eudQMS3 zwt^%6Q^_jfmEM!sw|;WjY5L^a2CL(%WM>PhU+K$!yeV`?h@RK#lDE@XPZumZw;=83 kx1-rX3>PNlPh91~6WWk?to80R6`q}&o}TVuW@4}g0M1Za`2YX_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/blank.gif b/local/htdocs/img/mood/growf/dwaggins/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..e4a5bcda6dd61592d4462773c2d36dd72eed209f GIT binary patch literal 975 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zIMy(*bI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz)U#hwaZ`@x=cf%bcrBxrL>e!3nI;n}q`=Vd;_PfC@pEfDrz}3u=Pt}tdo$$e zC1v=cju=6 iwmPc8ka2Rm6~D0Fnj0#Qk9pj6n&-3g(~$-S25SKBl3jlQ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/blush.gif b/local/htdocs/img/mood/growf/dwaggins/blush.gif new file mode 100755 index 0000000000000000000000000000000000000000..65874d48601862fb582dcf970abd7c1e894a1ccf GIT binary patch literal 998 zcmZ?wbhEHbRA5kG_|5qD_}|d*>({UU|NldTN6FC;81^Bc_>+Z^fq|7l z2jo*wo?zfO%)red$MU}whwS0g*B1fS=$@675>Qf9Zr7# zT_$7x-bjtzzV*V7eAi8l^Y^|PlgG@=&{AHW%77#b{E)s}{?{3CNO0EmtB!8^;+Jju23DDw>did`w!k3 z`>(y&k(0NW^Ofe*TE70-dCw~i7`{9#h>FW?sVnyFD0EA$imVL@X!6Wxt!eKqOG$4j zZH;VADW0=en?Autj`K=CIFBLf2qgAT~E zpgh6Aag~9SL&jsnf`iQ*!cr^;HY7T?3UD$=I20Z@(#4>pw8x`R$-P^O+h|S4#FS$b znDp!Za0ER$IfdD{PsMZd($kZ9RGU&x7AG^zv{ya0rqfWdfx*82naYa|D+8AV^s9+> z8L3`bZ9nnUnp+~-mllMox}~lVbzs~aUA*th%c&1FL7i$rg-MBsbs@4>(tM6{M zr))mgyK-x8{K0T`?~)f=3$LuyTWd9MO{xCVBYwK^dfaA@9xiKKyr@JY$RXiqqPTwC btg6Kfm)G_l>Z|>r`1baW;@A6R1sJRWz2R(R{QC9lz<~o0u~Bj~1V%y#DE?$&WME)n&;fZC zlqVQCb}(>q$arj6aIl#}SS#klhJ}aQ1(dz!WC$=YG>OZmxnvkFc5RavXW}R*d~&Q= zU9?Xn(0`%gYY*iIq-T;(0*bZ#+mFaCOFWh`vWaLI zEO^zh$fsBA?97l=S64Atu3ED4bN2CNDYe%^vZlTcSf|nGG}l@rEuz09)#>W0aLo(* xqqbkVySh+4VPT`;yrUWlnUC6R#DmvpEclo*Wt#r}Evt8Ketv#|FdGYlH2?!iV21zz literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/determined.gif b/local/htdocs/img/mood/growf/dwaggins/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..ddfcf5559bb3bcad3679817c5e4da8a56030bcc8 GIT binary patch literal 975 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zIMy(*bI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz^kffnf>p}RP0LQt5VVZiA~|WvnVF`RyL?_6FFVm{(k$e0Gw{L17M=387_J1( zW6L?>Z>?DsyyV(^wb)NCJGZ7^XpTL;innW1(($bY=bd^_Z`Kalm3%Pm?k&@m_twam ib9F>rS{XjIbuO30oEs{SkGcJKn&-3A=tu(tgEat_hF$*v literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/devious.gif b/local/htdocs/img/mood/growf/dwaggins/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..b2983fcb990ebf8aa40cd6add57d23e982dcea5e GIT binary patch literal 985 zcmZ?wbhEHbRA5kG_|5F=52uyJAlNMy+C@4(vXjSL# zQ^_=1>NTA?oNdO=qQ{;y4AWoT@hocao+H-$$>e45BAAJk! zuRB23?dT1Y#Iti57O|yzZGL`mz0UEb(5kO%qPF<2-?U~%pjz~XtlL$xR@d@wtqOb0 sWp?^P-u*o--0W*L7U&&`n@wdH$QJ?WMr@g0Cs9!B>(^b literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/dirty.gif b/local/htdocs/img/mood/growf/dwaggins/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..919671dd9c3e3fdd84ba870f35d130123520f318 GIT binary patch literal 977 zcmZ?wbhEHbRA5kG_|5}|adFYHUM4*zj-Q1OPE1g? zt+UZw@YJ(kQgKs`=jW#lGk7hdmP8sab(tm;E2O~C@Z#)jCGm4>EVpF1H+l*))p|}* zKDL4*{!_^+;g#N#*tdRi*=hRZ+6JrRt7K;jsbA^Ke!MAkM~I%+>XNt9SWg!$JGUV1 l=eMKTMhq7wqmo1UKTVP;~m1_15sTUr1B literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/geeky.gif b/local/htdocs/img/mood/growf/dwaggins/geeky.gif new file mode 100755 index 0000000000000000000000000000000000000000..f49c6302be96f0396fcb027b9f73072414b1c361 GIT binary patch literal 1020 zcmZ?wbhEHbRA5kG_|5en?Autj`K=CIFBLf2qgAT~E zpgh6Aag%|QL&jsnf`iQ*!cr^;HY7T?3UD$=IBZlr%E+LkG$-Ptl6#L7x6zx9LZ#z9 zimdaFoVb*7v{fUN?~KK!rAMb51R71@`1II)ngTx)hr{F*M`p_9AB&M_cyVDai>#Ng z#g@#=tE{KDt;xEob#1Zc(z3n3OrH9z=UFeN!O-yb;u?XSWx1~do<+CDToy|GU7+T> zC;a)kwX3(Uxo{x)E8Dcyp-T^M>{NE{T_s$Ua=LeMl%G!Nr(y{>zXv{iniWzv$wtT@?YOOySw~-0|SFK0Ki*wJpcdz literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/high.gif b/local/htdocs/img/mood/growf/dwaggins/high.gif new file mode 100755 index 0000000000000000000000000000000000000000..861836df5ba7805225ecedf109f0e9b52783a311 GIT binary patch literal 998 zcmZ?wbhEHbRA5kG_|5pu{z3Wtb|lA|Fo5<)=nCkrD312cmT$g`k4 z!N75tft^FfW5a@j%^bp7F()=GJlrmzEX1O)@eu=q2zy#dhoIuI9$D$UFA@z(4U=Tt z#cU!!rFcwak7S#1a?|2dGqlrRU5Wg>$Z4v);kzX-Kc)N3bMn6Al6mQg(@g8;HkOyh z3(qWJ;7GV)bushm9Ir~D3%@=l`A&&vohLi1L^EW)R5M?y_xIG8t;LI-dS{g--CL@= z^d8Ia@b@Ly{<7}M2T4?I}z8=tf#=i?%VliJqR`*H*~y|}z0cy*hE H0E0CE+tX;M literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/hot.gif b/local/htdocs/img/mood/growf/dwaggins/hot.gif new file mode 100755 index 0000000000000000000000000000000000000000..c1b40a5b5d6a284c7dcb8d9162972cf4ca670cf7 GIT binary patch literal 1003 zcmZ?wbhEHbRA5kG_|5Bl zJi)+mf`Oew#$&^RgUuYmS}_&^4vy_iie@Srf(wsyG3y1zbOb&=*2$yW)U!gs;pk+3 z_b3y|i;s`@$S_;5Ctg$QoS%$DWW@UvXH`SljP7I-pfj+mf_Ft%#Ypv>h3P#b=UVc z{FLH7v;9rNAy4iDuHL5kkB(MUnu#!6S(3D};;z-+o|}spPUTwvU&147^z1^q>*~0( NySBb=W@Kcr1^}ByYKQ;; literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/hyper.gif b/local/htdocs/img/mood/growf/dwaggins/hyper.gif new file mode 100755 index 0000000000000000000000000000000000000000..63ea5ceb65abf8a0924cbb084c0e605194d80d11 GIT binary patch literal 993 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zIQB8HbI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8ulZ6fLoywk* zL~a-+onkNuPMh;XXxZ6G>as;!GK^Ik=QA`o)ttPj&e-Sf+7%OFtQOGi?z?HqtO+kp zEO2Pu6cc5d=D)_;_Y_ZOL5}}abLTqS9h+ZXUlyLuXY=w~cF+#4*SC0YO?!EBf56XE zXMaz7es*zS>9jjh6&t)6+w$waNZd4ZWtbpdpQ5>7^V8Ea&6Ce)?%MLAfq}sq0DCrL AumAu6 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/idea.gif b/local/htdocs/img/mood/growf/dwaggins/idea.gif new file mode 100755 index 0000000000000000000000000000000000000000..46df85639840ea1d56eb476a42e87bf97cdea435 GIT binary patch literal 1026 zcmZ?wbhEHbRA5kG_|5?>5RvO zMAv=|{Yf%AHY%R#S96~>MRVfPBfTQQt71+BB%JS*i0+a(6`0(xz&-odmJ?Ib92pq< zoZebqe(1b7aIw?WRV7Q0tV!t4dOPc4R>Vrry>(Yl1*~RlH?4QNBPDj=_G;y3ttGd= zt!UhypFSyeh3J~QyY0989rZHLzJI89?yr)HZJUzU`G1Zwi-{~cdA4nB)jytFA0KU6 qcvdQobNiBpeT%QEEn8)#$iTQh`~BIq(aLY{9cbp3_p?!8um%7NDSBQ2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/sad.gif b/local/htdocs/img/mood/growf/dwaggins/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..f240e92130d46ec83d94615bdc91bad261dbea3a GIT binary patch literal 977 zcmZ?wbhEHbRA5kG_|5}|adFYHUM4*zj-Q1OPE1g? zt+UZw@YJ(kQgKs`=jW#lGk7hdmP8sab(tm;E2O~C@Z#)jCGm4>EVpF1H+l*))p|}* zKDL4*{!_^+;g#N#*tdRi*=hRZ+6JrRt7K;jsbA^Ke!MAkM~I%+>XNt9SWg!$JGUV1 l=eMKTMhq7wqmo1UKTVP;~m1^|0oTnPXG literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/shocked.gif b/local/htdocs/img/mood/growf/dwaggins/shocked.gif new file mode 100755 index 0000000000000000000000000000000000000000..8854e5ce50e8258c5041023b60517bc725f5d40a GIT binary patch literal 997 zcmZ?wbhEHbRA5kG_|5hwbWC*5vPZr9pI}^Epfnl+-v)-1<&l>){0i{V( zEI+RZT*5q6ZOyGMFD}nhYm|G^C7g3^gVFI%UrvUpoo$k~+%|W1S$6b1=h<2*UZM>R zeHD_Qax*{X`)+Re>s6aEZF%Ca1V#C72?E=bPb20=N7@EX2#kS12xae3fqaG8-&%y^MCMet1 z*+?#U>N!;?a@(ArMr!Ue^g_-r&}s%*(GP^CQpakc+JI9;*-|*OjWq**qK!)&PM}T9N<& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/smile.gif b/local/htdocs/img/mood/growf/dwaggins/smile.gif new file mode 100755 index 0000000000000000000000000000000000000000..317832d51a869e290008b4759a7659166844c864 GIT binary patch literal 978 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zIMy?;bI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz)U#hwaZ`@x=cf%bcrBxrL>e!3nI;n}q`=Vd;_PfC@pEfDrz}3u=Pt}tdo$$e z~*4$FpB6pCse{Yma1bl5e;9Bl%WJM~yP|Pm h&8f~9Pd+!DAcw?bS@O<)G8LPio}OVW%)`N84FEfJR89Z@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/surprised.gif b/local/htdocs/img/mood/growf/dwaggins/surprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..74039178578fb79a6581c4035e24a6376c061d0b GIT binary patch literal 974 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zI94;TbI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;7D%LB=7oyyLA zUm`Z89+|?Jv@E65XxZ7>Mu9~wnU|GLPPeUXQ*mH$xHwHs{L>rHD;e&MN}`8EUQJOx zwt_SL-kPkbug-TF6|TA?RrLDcT<@cgVk(OiPH)M&x{X!3T>I9}lGmqVeolBEyDeV& g-4Tt3SMJ-D*2<~%d|&+N=mcf&c|MVe4h#&|0E)U?9smFU literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/tearful.gif b/local/htdocs/img/mood/growf/dwaggins/tearful.gif new file mode 100755 index 0000000000000000000000000000000000000000..8e5af7292dc4767c34d4e64a1bcc34c386c5ef3e GIT binary patch literal 971 zcmZ?wbhEHbRA5kG_|5}|adFYHUM4*zj-Q1OPE1g? zt+UZw@YJ(kQgKs`=V#T%8N8NJOCpVzx=fRam6`wQwr&|>sDv_G> z+`G?ps$9)U;Z;{xnQnjergKZS*Bo!_Ycc`bvTw8)-<}l8d3|l{hK$$ec)PwYJlD(E eFwG}=%DV@%8JXnGR#p@y9-pA>Ehi(uU=0AbWmrZ4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/think.gif b/local/htdocs/img/mood/growf/dwaggins/think.gif new file mode 100755 index 0000000000000000000000000000000000000000..68bed92f349fe02f426a65d7c8dd80711979f6de GIT binary patch literal 1013 zcmZ?wbhEHbRA5kG_|5en?Autj`K=CIFBLf2qgAT~E zpgh6AafyMGL&jsnf`iQ*!cr^;HY7T?3UD$=IBZOEWe^nf+j63i;aCrgWZ9D+f=gVw zq}{7xB7z<{^eBZcviT99bY`li`l~%F3>kdp>#;6-b7PZ21A|?^k;$tIiH8<@OmvEk zGEu&=B5*ky>rIi>AxqWb(^56IHU!TwP>egubs*<#f9Cu?-Rx^QCwAD@Zqj`)?N!JE zlciO@r^52XX7RCWpPMyh>4l>c_)qtqxwi7q)+tMi*4~-A*7LMJ>jYLAv5jY!F4gB2 Zm>X4k^_qU*;d#Ehx4pg1!o;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zI5sk{bI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz)U#hwaZ`@x=cf%bcrBxrL>e!3nI;n}bfNO|vJ7Wax5)@FSOWmr+ggYK literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/weird.gif b/local/htdocs/img/mood/growf/dwaggins/weird.gif new file mode 100755 index 0000000000000000000000000000000000000000..a6ae210eb3df9891f9c357be67080d48029f225b GIT binary patch literal 1003 zcmZ?wbhEHbRA5kG_|5<5RR15BX$VOg%GMNw%+~;{ZJUv}TIsE6Z*Hu0-@5GX>g}tY zcGf(r?*G>u7{Hmw>~JG~aU~j>da`Y&H&_y*PMv O+}T}Qvl|&18LR=bbZs;M literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/dwaggins/working.gif b/local/htdocs/img/mood/growf/dwaggins/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..23cb1fe3719c9c8ac81badc7810c24ffb1ea107e GIT binary patch literal 996 zcmZ?wbhEHbRA5kG_|5;M1%5P?y0Gz3OS2q^w!VPs%nX3zoo7nCO$ zI1VzfbI5pXSa7hJLs%>3#D;~3+Xa-p=41#kFf@s4ifx&3anZ3}Mm;8upM?)jOi;G1 zvyoiz)U#hwaZ`@x=cf%bcrBxrL>e!3nI;n}q`=Vd;_PfC@pEfDrz}3u=Pt}tdo$$e zB$W*&g`~6 zuO(Y`{e>^1Lor{h&lH28B^57?)Oy4l7>@Ak8Xfy3QtZ;#=Ii$F&9)^kFRu`1V_~oc E0NDU#JOBUy literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/amused.gif b/local/htdocs/img/mood/growf/pengies/amused.gif new file mode 100755 index 0000000000000000000000000000000000000000..2f433627727452e03ba0102cf2784baf838f2cde GIT binary patch literal 489 zcmZ?wbhEHb6kw2GxXR7|1P%cS{}(X)|G?0&-~bT(|NkE(Iz)ite{Mh5kYH!W09PYD z17=2`vlV}`aPl*-Gw6W40P-dSTj7D`0uLRjeh)>4f&{hJwiSvyStQo@DK{M08`mG5 z*Py^!%*p6jYI}$6*!u$scI9msA06Cu?^yTSNZ;gi#>U#_jQFVZq`#eh&n-P-{@0y;}lGl`x x98~Yr*3{eDHE~ksl$2@Hr_P!k+|fU0K|^dXlTT|{&~m1=eR(+>`+zR61^`wbc%}dV literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/annoyed.gif b/local/htdocs/img/mood/growf/pengies/annoyed.gif new file mode 100755 index 0000000000000000000000000000000000000000..4f8e4924479c6c9602d3be77082ca6716967aed6 GIT binary patch literal 491 zcmZ?wbhEHb6kw2GxXR7|1P%cS{}(X)|G?0&-~bT(|NkE(Iz)ite{Mh5kYH!W09PYD z17=2`vlV}`a2heNGw6W40P-dSTfu?m0uLRj{u4`zDj6&oon8n!tdN@1mU%VnMb`G~ zuY+&h31ehBm|#00=qyXA^aZ(nXTPdl#r9Zl3 zdRJR*OIbnloVhWvU4gR~EM3IL LCi}So9bpXs{S|n4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/balloon.gif b/local/htdocs/img/mood/growf/pengies/balloon.gif new file mode 100755 index 0000000000000000000000000000000000000000..a427f106bea729164a8326884d3228123be21817 GIT binary patch literal 998 zcmZ?wbhEHb6kw2GxXQr*1P%cS{}(X)|G>}y1Pcxvc<>(xKoUa%DE{a6a}5c0b_{Se z(lcOY1iD%ACkv+{0|$c+$o(L1GO%Skv=nqOFmxSx^5KAuMtkE6MuS>6?i-n=k{S~G z?k+R>aFmVZ*cQQyrXuT@8xtIsGvB&Vb2sDtv;VB@jIQo=4Ux?O?U79}4ZfW&ZH*Jc zDyRDA^h}(Y&NOFc&Vq$GOOlsOTH&;K?yA-6Rybm{KL=>PhmKS$1A|kgirl<*H6;gI zhBfY4iP=ZRm|2@8cud)j+-^`f>F0Nt^{s<~#ErKM8xl|NSO1t$(*$&aw^w6xOq+9O zvwu%-|Ae%rfY!*GfQeIEW&{P7%n1rv5Wmc2@q$&pYu2t<8HC*dpa1|mp#Ov-LqmdE zYx@gD$rW-8*ORv%*qhef*pw(UO^P`=&tXH3zF?wrqO|}ATZN6nxwp@!S0&aq16|TU2e(q-m`){j-_ohAav3Pgt>XmD4hhb2N$ya_eQcu2Pv` zsC2kd$(BpNU_t8Xc1`_FG6z1Wo|?$wXLV=C<;O1b%=OtgJ{YU`Et0h4`r09~;sk^8 yY#|@Zkc^89d^kPkR+VUn_lPuFeUZGD;MK*(^1|ihghjWeW;xF?@ib6ium%8dctKqN literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/blushing.gif b/local/htdocs/img/mood/growf/pengies/blushing.gif new file mode 100755 index 0000000000000000000000000000000000000000..7f0d6ec10935da1225c607ba024db4b38deb8b6a GIT binary patch literal 949 zcmZ?wbhEHb6kw2G_|5>XlOWa;J}9uAO8RU4^}ct zjE2DQ3<1TTEQ|~coD4c3?}73J1IHu=VGbFO4GRu7a|o-kFeo@Wx9~7(O!#p@p@B(4 z-Or}t;(w@r2sb~MONQW&5-{y66 ZQK&(~!pOFS*T>eJ4t#p5k&%(X8URVUQD^`F literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/bouncy.gif b/local/htdocs/img/mood/growf/pengies/bouncy.gif new file mode 100755 index 0000000000000000000000000000000000000000..76f48abad942992e35336da251f86bfccbfee27c GIT binary patch literal 701 zcmZ?wbhEHb6kw2GxXQ)=1P%cS{}(X)|G?0&;K2X?|3N}S2PppM_Hzvhc6JPKHPSO+ zW(2xi@h1x_7XurE4#*cEZ!)lzI5Zb{=t%W@C^94@sI|6cDDGqtS>vbNaA0p-e{^1h z0&6j6qeH3fon^-v4<^`^w_SW;wcy^d#nZhaeHoH7;-l)?+FkO}Q@Xv9`U0DL`_hA& z$|q0hnchEl-kgPt7EG8JJF{bDAX7t+chEYfEmIq_LtPxf4&g*|h#u4-CzceQ%(0ry zq@E~{D#XLQ`opd#MU(F|gysBDI{9?@&y#t(?|-N;p!PEu`{-LMSqlk`s9pt3UxumRlcw{_D~`yJAqNR-`o5rsoH?`F5noyCmk<^|#l>PU)GJ l(ludL(2SXVLERPemn@p&x-=-OEp!b-QC32Bjx*2|)&LFNzbOC! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/confused.gif b/local/htdocs/img/mood/growf/pengies/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..b3cdb7fbd53d0482729dcf8ff6a9d6e82c82d8ff GIT binary patch literal 961 zcmZ?wbhEHb6kw2G_|5Vl)JXc?c-}WMO1r zU}Mk$`4f~U7&zuJ@N%d)Y*1iqH-m?*%>#^IpQaHOA|X-3MAAcck|8OAGnIzKNuH{FKQti&JP(j}nD*lyM6L5 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/cool.gif b/local/htdocs/img/mood/growf/pengies/cool.gif new file mode 100755 index 0000000000000000000000000000000000000000..4365d6865b6e8dfef6bc1ab3f291c9a0c9a8d1d7 GIT binary patch literal 949 zcmZ?wbhEHb6kw2G_|5mElSQrjCIJfW!ip;S1sKCI)qUJRvjdqFl4+w PwI;i8>HWowj11NQT`)*a literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/determined.gif b/local/htdocs/img/mood/growf/pengies/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..f995b33f084376b2a63eaea889a9144385d3e4ca GIT binary patch literal 939 zcmZ?wbhEHb6kw2G_|5p?N?sH_@MPlm-M6Lk(xY=t>dY(~eh6mxEOe?jTOy&L*0{{x z+>F=KRLgxy#MFCFJVIVxn&8qc^ycPOg~<77JB368CaJr1=Y(#$>M=>>U;_h#H2~BP BMKJ&X literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/devious.gif b/local/htdocs/img/mood/growf/pengies/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..3d3e00a5c72925bdbdf00c1b953c5c8da1d1083c GIT binary patch literal 958 zcmZ?wbhEHb6kw2G_|5bMM~Tr87|tP}_>+Z^ zfq{)d2jodmo?zgZ&A`hcyb6NnCq_Gx@*Cy4Y z3mC(!_P+SA;?yLbbf&$WS0DTLFzj%;+9j~+#?<(khkClEF1xiXLR6~NIy5n0a_Q=Q YN3@L}9qd<4eKnGfIqxz%UO1#h)yU z3=C`xIv{_7@&p6NBnDm%lYj*a4mNVIig|cUNIcZUCCeA%F=3HQtAM`Um5vKa$NSkB zIz%Lclo*&a_*d9G_@Ls&#LjRe=cmvz9|n_nE{T)H3%sW=v2n;+F)TkY-^P{8RO(Yo z1A}(*B%7$o4h)PDGuvDwA3VLfh9kD@YgOp$^ULGP&F)5h&b&DzYxXsk38ATX=4(uD P%AHlB63@)Y$Y2cs|2j$i literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/envious.gif b/local/htdocs/img/mood/growf/pengies/envious.gif new file mode 100755 index 0000000000000000000000000000000000000000..f37d6f69bdf2f4dd6434a7d08771c25eefd611a1 GIT binary patch literal 943 zcmZ?wbhEHb6kw2G_|5r#P5|e<%M+F8J34Rxw1i|EE z%nH_3S5^cjxiX8}Ds^ZiG@ND>4Hlabxj@y2!GN7O`W zSbV%uf|*6Zz@edm(IC<8h{dF(J`6^I*REJxUgSKBMeWy>nSo0$G&^+5sd^MYJ;5O2 zI_VDQRrP?W{)>fbvqD~9>k*!ABrAFC^|ejTvXgkV8xq|+g>Uc5>AsTU(a6ZiU=0A5 CSwv(2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/happy.gif b/local/htdocs/img/mood/growf/pengies/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..fd571ac5de899c6907a8813986d33d0601524540 GIT binary patch literal 941 zcmZ?wbhEHb6kw2G_|5Vl)JXc?c-}WMO1r zU}Mk$`4f~U7&y8ZcsXP|HY_;U%)!dUkkF9m)X1(R=dnZJ0An{FFO$N7kB^QvOIxxj zCdZ^-Ie_)_NVOnzF=YF|U80t9QsEuT|W4nI^0hdg3*WnVE^f F8UVSzMMD4p literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/hyper.gif b/local/htdocs/img/mood/growf/pengies/hyper.gif new file mode 100755 index 0000000000000000000000000000000000000000..403ecfd5b6844876c59123144253daed9bf4b896 GIT binary patch literal 990 zcmZ?wbhEHb6kw2GxXQ)=1P%cS{}(X)|G?0&;K2X?|3N}S2PppM_Hzvhc6JPKHPSO+ zW(2xi@h1ys3IiL14#*cEZ!)kIJ2V$~=t%W@C^94@sI|6cDDGqtS>vbNaA0p-e{^1h z0&6iRqhqP<9kyf4jR_9Rtq(u{b?Kg6@pP|9--^Jd+9bx-w7SlCm&D}s&bA448GT-p zCQfgv=;)m?Eoer2N>H0``r;KWL0MD0*D(}jC1mF~J3`zcg6fVEs5?%i2r(F#Ol@o0 zvLQu`AzTIMj&&uR6KW=m|SaE%R`ntK5<;DMV{rsJLG8luJT`Ds= zToaS)+dKV|>XYJICQj(->@H}ZF>_k*!bK^;lc&V4NT^?uH90#tt2iqyC&vZ5Lo#3v zSyFT|$BZ%HfRMuqp(P$#iU~)B7KY_r&1Q&R&A2Xnw?T(Mi8jTc)J!eRm7T(Ih#K6p) zz{t!JU!Td;RL00u;oHPk&=wUFz);FM!+rLGFpq))pII3`D_5=d!ESc~#BRnDDwi@C zIDo!NVl)JXc?c-}WMO1r zU}Mk$`4f~U7&ulk@N%d)1TZ)lGfLm#u|-` zOe{Pztfp#SXbzbi=36l};nEzRgZorGOwz&^rfR+_`S~gN#G6A} mA4D~xw>UE@h)ORoI6RA&{j=?f8OsxndMp19$x={Yum%7L+Eq*d literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/livid.gif b/local/htdocs/img/mood/growf/pengies/livid.gif new file mode 100755 index 0000000000000000000000000000000000000000..ab1099cf0237c85614c98a6e1f9eab1b970dd7f2 GIT binary patch literal 526 zcmZ?wbhEHb6kw2GxXQ%<1P%cS9~>P1FJSopfuUi+fddN`d}wGmaNxlI|NlYKgBvLR z=k{|A33hf2a5d61U}glmR`Dkbrz8UxgAT~$Aa63TH8`|7DX8$Zo_JE28Di9ZZbb;^ z3Z|Cp8V(11LxiL9%pLi-`PkQApB2h*q2NG*!wTU|`8y6e>}P)Gkzd{1kmniNoRZtl z+RMn866eRzJGH;RdkQP#)M>1_v*yfQv|!rw=`-g}o!FhXYT~4j)oUhi?%LYBfjKlJ zK4o|D?x>s`Pe-t$SkWBS?9duupu^Sgw#cc|MQi@q6(L+eM}@CSn7u-6OSEIspI)YI z?ate?&uTHev`8>exWO4&aVKHLW5x>if|{1be2>tUVl)JXc?c-}WMO1r zU}Mk$`4f~U7&zJ)csXP|HY_;U%pt55b7I3n=T-(KHxmX1MFu7b{tTOf4@z!K>=fHXb24F5K#Qd z!pOkD%Af=CBq&cXa7<$0=8*B&u;5@bhp<*m1Ve)}1Cyd0OTz*srgjdsC>MbR$qc>H z`gSE26CSxSGO?`)(Y(0i=oDpkkDMKX4L*~MrFU)NeBf}djfJCtC*i?D|0af(D3wiq&pV32HB4 QT(HKv@QFtgBO`+~0IyO^Z2$lO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/sob.gif b/local/htdocs/img/mood/growf/pengies/sob.gif new file mode 100755 index 0000000000000000000000000000000000000000..4f44cb3bd13da1176ccb79dbf6cfa7773cc015af GIT binary patch literal 487 zcmZ?wbhEHb6kw2GxXR7|1P%cS{}(X)|G?1D@V{Zff&c&igG7f2Q2fvB=Nc01>=@u` zq-Vg)2z0jMPZmx&26hG=kQYGSWMC^i&|Ki5Bh`OmNzut1Jx-^LAg?7tj1g}b8(2g* zS_>8wY{)zOsNvTO*M8>6wHsn3uCq4(X{Z+K{v1*5TvA_CQ=3=h8dt{1#@61Pm)t+0 zJ0oN2#EzM>qGMVTr%qsCYFpUP(7&vB#>@z&HS-G#H?uo}UBT*x>WXY+S6EGL$oRtG zz{C}iv!Gy48uJ4O^VPf_%bnJ56A<9J*R1t*b*=kj=l9ckmkV8uDspYeVQZ?-iDK(+ tFHU9c?&(OGFtNR5>ZITq6WbV=iUOzfbT7!95;2cySxEZ2wV^=!tpVk(b_W0e literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/sweat.gif b/local/htdocs/img/mood/growf/pengies/sweat.gif new file mode 100755 index 0000000000000000000000000000000000000000..d360d615d851e4c8dda04ded547d3f61d25af560 GIT binary patch literal 497 zcmZ?wbhEHb6kw2GxXQ)=1P%cS{}(X)|G?0&;K2X?|3N}S2PppM_Hzvhc6JPKHPSO+ zW(2xi@h1ysC<7aV4#*cEZ!)k|I5ZbzCO(g&Fzr|$lAG(|2zCrBKdNK$fR6Fd zk?KFOq$rcYVy>@BgTq>(zROt&(g&i}`X4ZeF6Cl-(YWKM>YS?#Uw7#C_nmAxw9Dh3 z*q694#`)Y#O*7n5>btr_=1-YWIiD%O#eX>i)4G{$ KiHRU5SOWkQ?|I<> literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/thoughtful.gif b/local/htdocs/img/mood/growf/pengies/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..a48b04fdeffafdae1ebc6bd28372a551f512793d GIT binary patch literal 959 zcmZ?wbhEHb6kw2G_|5Vl)JXc?c-}WMO1r zU}Mk$`4f~U7&zuI@N%d)Y*1iq2hOPRR>_MNVC!%0e~_4U3PrbE^BD zk(iWtkb#kdrNg2iv7wJQl8Ytaf-=KQ6Hc}bou8KgGgkAxIV&e0U|?io(+IUPNk6#M zVWv`vm%xiN3&TV6j?9|y%CFBhcva4cs|>yylTVgiU3FFQ`exU=v-ZvmeiJ_1e)A%q YpC29KHnU|jx!wv{@o=X(GZTX~0M`0a&;S4c literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/wideeyed.gif b/local/htdocs/img/mood/growf/pengies/wideeyed.gif new file mode 100755 index 0000000000000000000000000000000000000000..53bb9af10f1f6466bd2f91f2a477404e9fddbf06 GIT binary patch literal 942 zcmZ?wbhEHb6kw2G_|5d;kCd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/growf/pengies/yawn.gif b/local/htdocs/img/mood/growf/pengies/yawn.gif new file mode 100755 index 0000000000000000000000000000000000000000..a71cedc4380d4d6d8244bc8740352ad49c4496e8 GIT binary patch literal 766 zcmZ?wbhEHb6kw2GxXQ)=1P%cS{}(X)|G?0&;K2X?|3N}S2PppM_Hzvhc6JPKHPSO+ zW(2xi@h1zX5d#~84#*cEZ!)lzI5Zb{=t%W@C^94@sI|6cIA+E$afPcTJO~lm7xAX- zz}LF{-i(!&EOVHfEVgI!)m;DbtFo?SK4)re9ZN)`OEV*5U}ai0LAHSvu#0&I{`COv5iwbefelTm zEGBMX-fl(z&gL@7pqiL=DX=BDkRLB>73VKAi%*^U=dN%Yy9-(JJH++ z+%sc?5?qrQ8JnW3k~>_os@j|D!?XLNDko3ro>-FH)-$~^c;cjpMTraNF9>E$U7Qx2 znwJ`#o(^>dD~>opbH(xrmRsUDBh`QbBekcc!NEsu_Fl$A4hjXu+wZUb+p(|jtgBCa zP=iYbBV$WVWoB1fcwu~JYx;zq$^8>1_O{k$cJ#&e1W&1mSmKru9M#wyoINFJJwr)$ MP1255V4PS30Q<+b< z2M$Ett=ar`zfgl3SC{Pae{uSuB1wZpv?4)5`~g{1)tQk5`|!(DdmYpsS2KX$$DH|A^8f$r3D2=sl~+#B^jB; z3b{a5VtT4VW*(5As!)`go>^RyS_HJCEVZaOGe3{3G%qB$-kfk$S+o?LD&p* zUT$h$i9%XYVs5Gu7lYzY7ETQYSq2?Yc!A=If$jf+z5)*&ss0m7icaQ8F$OeD=CoxJ zis&opV#!$3d0ct-Q=z?gKRhn-oYHzhKlES7=G(WDYC7M2X=g~v&WXq`sQ0Q3Y)mT8 z;S=vpFRlwu?3>Y&(iRdS-aIi!Omv|*OGHXc_zZ@H5+ZBYE@N4qw~BM-&hjl==XB2N z3lNvgIkacx_8mtVH%&ZqoU<~m?m!?1A4}kt6PK?fGDNX%36R-(>25*Op4YdZzX)&I z$;}=iy)XE~g1{Uhp1m(#$~kDbeK^#V{C$=IQ!CeLCeGt;7It6o2xit;u|PG(=%Aoc zK|}`c2G({yQQwRA8jdI(aFBGVvB;^~6m)Q!?T+Yvz*m+Op!}VvosM zZx<|F89do_zE^Hm$*QZ1!&d5jm1MydY;Tc+&1(LI6(wG4qdFUO9-Lxn**8a5{H18; zfk%ZKb)7x#8xUy5no3s!D5><&+ykBI9dXdgB!n>to}Un|oX2`X@~C zitBC6TOhYMevaq7=_~UV&nyUtQ*2qVXvyrr4Ydr63_EwP>0jo(qdjs>)YkIO?louj zZ)>PNdxrO9Xqo>`87V(^%tm?by L%ZZI%0u0swJjZy0 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/angelic_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/angelic_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..d20c5df1008c8f9617b630af3f052b25a2a88188 GIT binary patch literal 1916 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 Dt}NbL literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/awake_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/awake_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..ade1b84f262a471a4fd9221bc1f6bbbf9b3b90e1 GIT binary patch literal 1477 zcmZ?wbhEHb)L_tHxXJ(m|NsA2D6o?&wu-!09sQtIq+UDnZb{^wT(*93L09p}+i8)v z(-|xoB5npP`#*crpOwn`iV@fBcm%jZuE~a8kqEmi7Jh**?4n@gIicj_WKB&?2?>b< z2M$Ett=ar`zfgl3SC{Pae{YQedU8UtV6WS5%TyoS#;rmzeT$GwvlA5AWo>`Ki;0P60 zaQAdm2vacBGcw{zs#FNdOwTA$D9KmwNlhzJ2nL!`o>-Ks;F*`K$Hf(ruTWfCP*9Xw zT&z%%ky)&e3uGmxrz<0r{y4MXBkT#U-glKs(A(i;6Sz^SDa$k~311vlW#53rc|e zVuc!n%|PenrskC>q!lIRrYdnUDE?&O)L@Wh&;f-MD6SaT-X7>H@X(R!Ke43fWRBJR z3oA;z)<$(U=sY;Z(z0)kuJ}vQ&I6AMH|j|BI%RI1aJR1gsdK~4H+9F?Mpc#8D$6N1 zhD65KwDiU+Cf3KsD>wJH$n{T{G z85wplY>Qv#y>rXHC0m!4cXqEiv;SmhlhWBUyys8J*X&uiBwqTUZ)!{9;y~)luK4};=YE-8Ec4^(vJYBU_0R9uSGeNISYR+|q7LuZ(o05$-1E96 zjI-`|xHKQ{m)CES;Vj}gIa$?r(U%h&y#%m@z<=ZrkYWsIDE{RWVHu<)I-$a5U1aX$ z*L!1x5;sozV=#Z?E7b$H&7vjFa{-?3k6cJCK8qC2;A^ z=2nIX)};Y5%L*!GYxvjRI(4-&CwJdAZuT(g^?o_qsu_fM)?KR+SS`-I<9TmM-b_wz zp&ic(mA+U`UcjiReej*;%m?W+jayjQ=18Tb&y?fqWRVEq;9jiec4>{q0}ky|Qj@O* zt%^ChY3b?d2Fa)9taNQYJ6kI0(Vfi8s^>Z8>(_rgBq+d$T9h2jgyNCWyGBM~(y2!?rE+!=z^f=d8PQ?7H8n_IYRT z_SNQ1<2=fFt)(=bleabOPD}m9lQN$cKF%)tR`p}rH&sT42^WQ%{vF|wl3<;AxLrWm kYmUdpMMt|Oj%M6A5!igRPr=-e$8(aB=S0cREQ}1+0QzK4s{jB1 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/blank_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/blank_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..41f43f62633833f2f13b8c829aeebb66fc151d29 GIT binary patch literal 1512 zcmc&z>r>QK7(OWElDo7i%^;w-uF?ufz=<6RisiPfB4MUv$RwBET9n!3#vN8LNN|FifKzbv)p3#sp(hQHaI3bIt^3 zQV|RuD09JtU{cW!TIlAI3CW~l2i$@^@B;=wF(g70M1VDDf)|KjGoXPDFifKzbv)n* z&ZS}{6k;*%LU5@#3&G%lvXERVMk5yF0OR2_tc8~_4{pI8_yGf;7!pAmSYQpB-~}Ss z3}|2j4AW>w9S=BC$qZIPAr|89{D1*a z42d8OEU*Sm@B$HR1~jk%hH12;jt3m&m-s(?=;Y$(6Slq>7qdAbEI4GL3n=LRc6E=! zchEeY`M(KK%@G%sucfQ0uSB&pAl=#3+;7wBH#S(hTM~-L!mL-E+Io$X)_krRM6wtgh~wQ>J4_tV1Fzf2FZDWY28V7hCS6B*un2J@51z2CMu^0#4qK zGg#aMa*V$l`fNjO8R1?vWMP}dzM^xBCU8Vs*B$TIz9;g+qHjaW2MR|o59=3RTvqCT zAg847(NEuw{w6uiqOLo)SHI6KuwAA7J>Ate0(W^FTN0Yq)EXK&lymrW z!qIbWsoU=B)q00*XK#9tS)D%OaWwei)Q$zyM@(ghf^z#W)g~0=r~Jb|$;&x=voi5S z`t4~;?i!QH%DR?+wB7M@XiZPrpFOd;0nQb9)sOEWKDyhz-}N*e`dX4l4C9B%_RR63 zMRT_CVpYw+c!}m2RdbPRs;5@*)a}1Kjmgz^M>NcAF4nlOS-qvre$(7)Ub5OT+|#Wy zx>x&VPwR?yZzy{*`ZZ@$pP9V>)MM79@13^tx^?-_Rn2tYN~!Z6$gSH)MF-zU~OS&?D5J6Pp=WzIG7!qlclZ}q!teMUQ7H5ng&cB)`&|Ekce zU}M=^d#5&DvrmRu9S3qI&ID%9HdOel^_6K!2aj+5<8*C^WAc@&Yxh5V>1nIiHBHdI zkQ*(XgPs-Zd|Gp^MCnEz6#ei^#gG2adY>$ObMhz0^<}^A-+jD2|EhJ!H^t-py@^U= zaK&$#s$`veZ~o4+j);dXF7~m(w$B@u){m-R4Yw}Ndm*^$a@|+9_(*NN%Y)GCrsc6? z9T~ThlVjo=T?5pXjQEfk!)U2zYSu)V7wecP_dVFr{KU%gEH~S#6Dn)DfBQ^kg}z{Y JriqZqe*yV)cMSjl literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/bored_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/bored_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..70c47eaba0d7199d46c5bcd9a897562667d53825 GIT binary patch literal 1528 zcmc&z>r>QK7(OI4P>_s5aWh>ZAS4wIY!Hrdk&T-OY78cpyU}rp%Q#~hH8djEAL1HV zfd`qmDWHwXqB+o%!)=rFcp)GcWE!y%L?#DksKA*zJ^cQGK6XCr&N=VDFG5j(TgH(ONUX)DHW7TbusRYQO>AfRH{5sW}I?P1*cM_ zg>EJ&7gPu;RhAfLl5$Cfq*5gf5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD#T*kIcI`1 zsR{-Ul(}F+FsbSXEp&6qgk(~+18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY z=Tfy23b7b>A-GhXg<$YNSx7EbqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR z1~jk%hH12;jt3m6W(F&v5Q}k_YJ|uifg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`I zhD4AC7FdHOc!3Bu0~*)>!!+7a#{-V~OZ*=`H1gTx*qu9KqEcdm*Kb^A0}7f&TZc{f z4qT$M^fw{){}3B{uegrJ-eUWe0U3iGP5tH0-U;<_=4MN!i#cmT32M@xi*)jn;E@==Y8(ou?ynOdh%OO*XARnZi~*_Bz{Jm2_-n=n)ZrF>9NH*7!@o z!uF@)+LE2(3pK}m25MjKf0W@q?CcS=woPjr;gX&HRq257kNDB2i<=@J=ehLT=kEMA zJNDiWWyk%reFgnWiH%kNX1|A1Y0$+X=kaROY_KuY-L$KF-%abD>c#Bj8wTGN9(bF~ zRBm|he$rT4fAh8T>kOaYQrds)s2K|O|Gld^Wqj~cr8`&2`*}E~DPj4qw{>|HVHM+{ zjV@t`_!#-2CMift26Y?7p3p7`|r$-ImnpI^be?DVAWBsJ?bYhN;b*?rqPGkGU zR(s#}yG4#GGA+f<(aPQu7o9b=)a|W&ec5ttdTOL2Op2aQLbL5Pz zQ`(`jk zZxF6Fm&hZ_K;dQA z^RZ*L`gePF1@(07iMF=yuS>IwDrv9{@KW|}*_i4-QtHOqC(FDJKA0?DQ}&?A)u+a2 Wr}(zU8Oj4Lg&8XSj^yj%d&IvP)r@Wc literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/cold_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/cold_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..4fea2e840da0122df216df3015ff6d0bd06cc31d GIT binary patch literal 1640 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/dirty_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/dirty_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..2b24a129cc6894e6198a38c296432942715b3402 GIT binary patch literal 1845 zcmc&zX;4#F6uuA$0h5AkCV(XYQUf{^eIZ43GN>#8F)9K@3$<*wq=YJqqMeCjATg0; z3{aOVi=cvtz#xjtj7$XrrSv&PtjM5t7*Ui?t;>jFo$>YXe)oUx514z;Ip6t~mzdb- zu+`}@Bt!4e!l4kt2oZ#6gc$ZtQ3z9rP>7}w!A@%LB@o zP=ru4p%|7HbYq$#G)2=C!?J{7%us}(Xog}~(jWp@15MxsL|`+l0&D<-X=sN!Jis9s z(-#oKm#^_!8Ei(9UkD&gfOg?pb!?rou&!HItzk<2b5`sFs#uK3*-RCgVSIwcnRi# zTVN0P0S16#kO-s!3s?h9-~~irGe842fWb7hLmeLAFl=UEB`Ac&aA(*EA%6%Q5{5`2 zLkJC0f>9j$fMs$}_#BVsCC+#2MoUG7&#SFTTv+`fBybR2KRCzR7D(`K|oFD34g-Z%&~> zBS$K`%F^8rT@uRc^estoi}oyA=U>vEF_|eUC^Vp=}RE2t| z+;-&lX{rh~dM2IAvCQ#W8ztibTO0TPP?Qs6aviBUV~IZ5dR7-2H``p**&5j5sQEK6 zx$cuUv#m{K;cXtxElv>;?AKub-(N#xUn$Qmh;Qv`>Ng=<=?(5}@dktIqOa|4jyxJN z_^!l;XD*q8HJq4+L{boN<@kiBk{=i{+N7V*KA7tEYf%x;{K=dmb9p6FI*%outQKGK zj?~RtESJwG)i|8`bh6DR#zT~p+Zid$yl^I3nU!*}yJVIw3AvcJbeiL^WO*82W8P?K zjy}Fx>eC(j<-m^M1fA8K|K>@OQLk%!?iXF^EYJt-d@C6`WC+p@C}|DpbUsnLwNO!% zbMcv(7yE&iHQD|AR@!x;Q$XKP?oYObtAvF)6;8h&oA&DNAC!$?%sb8fbEnY|ra^DizZ|I7dY literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/drunk_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/drunk_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9eff5567aca1bc08bffe335e1dfe04dd612d9ad GIT binary patch literal 1669 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 Gy!j6wlV#Me(3Z|?+2Ls&N;vHTW(_G zlwosnq)3W>MdOD-2qVNIL=d9fona7W5X&IKAj*{)j4(zlMg$|ubu%o&EMi$iSVXyD zh9FE3OAsN5a###Sm?D-ULJ{Sl83af$3cXN-+xWo@!!itE7|Jb%JH`x)8G;$g@qjXB z8J1-T%TSIMbYsG>gdv2X97`C+lwm1DC__2YAOcteP2dGYU^A=&Yyg94Xoos{fWu-; zFs7VBSPXZT#e~I_6AV0{%o0oprksAD1>G#ggks9s0d9dk;0G80ia{c10ujI(XaX-F z0-FIEumKFFp&jb*0S;kV%2^2tVKLkZVJYV<2nHTdCX}U|(GUyd0LFvUU@dqF=7C#a z5BLEFfMSpcqyY<915MxsL|`*O12%xcG_*qv$m z1}Q--kOLSGPJ^}JCD;KhVHo@X13)oI1k!*7tbr!*0wS;(paC1eU>e$?4j2yrUw+Py_(e>)dj|Uu6FIw9di(G=d?2Y2tUN$R6 z(iIaFC-=0iL|B)lPL02h%4n)n7Kp_q{!*pr9h;z=lKZWhs^%(ZHN~tPgD}IkPsxzl(%z z{4{p)ocmq*ny%tUi#lRc?Y%n2s_ga!buP&^wXAnl_-ZTD@tAYd?WKN#+S~DyaP-BM z@e%G@bVD(X)(^gGY987V*f}~>F7K5N8<^*IDF($)qw0!z=ldE|v#}@dbrgwz6NR~y zCyC#$YO9agHW;El+sCVMc2wAENA%WZl33Au2A>RGO|jBgq-ky2-4wp3LVcNN)_NcQy=ylimqB02~5WlwKr}mj5lvsWBFSLKCe8I zv_KquK(N(4W6j46)>@`&dFzbR=0kGlOV7)d3dsbYtdBax4|11?az;BlN0V19Ztb{t zKkdQGmK<$?C4I>(e)GUig;wR#FxdO3?A<+yUxXr$#&vfSET`Wp3kokhv*L)Tr`L02 zlOb#MSIsX|x7+dGc+@{d;cM`_T_n7gw%(<=|T@6;JANqzfC}B=y?<)Moo&VZ~T+wJ9$}B&Z&9xL+ylsphZN z)C${V-|E$~^F~zHa#LzD#NQL^*wMP~gdlal{JQMNv-ynNNv9m{EAjI!az3^}>vC?h zAXr|WCdts=XuUPj_&yOt39jT1{5G|o-|I^A0-Zd7UylO7&_?wQY$RkHKa;j)nHdbQEJgP-*}fr<0}f93z`E1&xpsk_A7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/happy_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/happy_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..b41aeee8e693e7ee63b28e408e9cfc36dfcf8eed GIT binary patch literal 2260 zcmeHHSx}Q#6uy*2qXB~kgn*jJ(hNnm3#qoUNJv=RC^9OHAPMk`6rwFIh`0htkYI5` zF5t+f;M5|i1r?``%3^GPFx-7Bt#R3!I)soVobTg5Hk!W3}zWjIUbN^ z2qpxx1XGR{R5L6lEM{3uIhN4OP)sOhDW)805CN=#Ch!6xFd0SxHh@7lltUga;1Gsk z8HRESVKBsmFf3sxCm47@ny?JZGL+K~w4j<$hNTSU>;SjG9`FMU0L35?G=T_U4K#rl z5P``64cGt%-B1pBxPZeFLOClzAq<9?WeMe+1;M}r(kvyEGaA+cdjR9XX|NW&1oOZx zum}7A13)oI1k!*7tbr!*0wOROpaC1epc~2|4;OGKw==L36vAMLDYrt{KP((J3@e2l z!qQ+%uol<@7!OW^wcsV#0W6^z`~U+$F-Qc`fCa39Ch!6xFd3i$8^E9&${`OIaJZNF zAACsY)MbkJ74k)~iU1!!OADYNd2Pj82;bflbS8c#X!09mG1)b$rRGY(bm}!WKUXj(fgs9rkX2Cbkuj6dhuP8 zPFp!IC&ci|cx!p3s53*a&zT!hqTDrR8aR7xNsUaRS-4&<@15PZe~kaDob4)cUa)0+ zeUSHEzGmG%|1??C3ZCfn8+Q9AS8Fcx2}cxdp^~vAk<8$v}da4$1diTN#nS!$049GIq=!@xepYQ3vRA< zf%8z7h0i|w86DdEW7`s*yDaK+O6gGeUw-yb?q$9sjCdVgb9JwLhiq*`czV;I)^*G1 zpiZon4(TO{s-fbQdi~Ho&z+{B67i+Jxy8;lR`29|hfd%YQypcjQ|#>vP+v3&s%&|( z_p%=8&8cpYa~2!i69iR-%F_Id7URJaVTbmsd)SN|v8=)`eXQns-0j$p?X1ec|fP{N8r6 zTS1$qDpS}IwIS-#j?lJmwb@>>?!u1z!ae8fhgzL&i~JjIl_j4(a_(M=*@V{ws`<4c zI8TwG3svRy8rLZy%1n7{hBUH?L7WIU^3e z7wcowTsk;?SDa_7MF)y6J9X2q%w^}o0!ugJk+3=E@}iAm=iQUUG?V{$`Kd6+{QPv` zZd;vw=Q$f8Muw zz_R}PqmztXpZA&~wUsi>kd?sx{xv0Dl_?mmmoC#g9=KgSwn9Fwd?ucflzUri(-3pU zE9n7Qw|-$KQ*bR)JBhg7*u&%ZY>&@+HA`9Ctdo$8-AWQ zPln7m>fo)i-cT|7gwM(9JIo+CB2O%Z0*~8G}Vm pnzSyhYobb}6Km$H^zLy{b$Vwz2LbnIV*R#1lmDOezkSjl{{>7bx5@wj literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/horny_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/horny_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..32fa2e0b4bbcc2f946b89d8702f16fa8c4118698 GIT binary patch literal 1642 zcmc&z>rc~H7(S)Y73!r_pcO$ukRS?E4^$l+DU`O+s+a2ZZzMyFA;vWm!U zLu=qD7*MuoVigThGg+c?8P4BG@q(yh>qM8C%`Ike#yLHE`27Lk z5@8bI5|Jb#WGpHO6NC#Q2_j@@N`Qn>^rDE{_+gZCN+n8#ycl=JC}&h+RLDF~W}I?P zB~FD*3*AhjT%wXhh0GGeOi(VUB&d){Lj+iZCU}7eHe(gA0fuR`qmBn0&X~lQkQHJv z?wm7;Ga(BG50tsYB#8-GKWL$w3nmFBWINy%?13LJ0E!_InjiwKK@+?{1e*a3Y=B`J z?Wp4cN8((_Rze{b<1R^D$j(AAc%Uo^E@Yz-3vz(*a2nRaOPB|@U=RF&0Z?j{HmfA3mamW|<{tr8#|tWkJ$Br2-V9 zpZf=<<9qHno$W~t}O6F~k zFX(n`K4WqEz22JkG+L3b@yn}N65`8PU+D>Vg=cI!N)(Eah5P#|O~*&OJ`Q$=cFv!< zG*GQmYj^lgO;(l#L}@pj9WytVKCWStk<8v8v6CiSKSxy?rpZ5zPP)obd}TZTGPXCJRfd5fA!}*)l9kL z#prsaQdPdL$9bx+=?A7-U~01}++E*0CmUV$s$+J;G~=x1SjB{ncU<*BG1I;8rAI{S z^|l~S|Mj}$;gYfXu)OxMhSa+QW1qcw*8joh=|T36hDDVjS~-+}h5sE&^yM(pY425$ zqdm1r>P)x8oDo=)G`BEk#81v5Wq*{@->6@e*^oRkv({d&3txQQXTEYxKfgG<+uCN* zv?Qdg^EzTKEf34koQq%K>ln1ACC__$r_vP0GXgHCdDMw_J!`cs@g|e$X7xz#b#2=% zTh+<824@=PnC>raF>1R^ZSAiaJ=;|bhp j^x(h>>uh&uPHt)6fm~*vbzt?@JL{VAmpm^p5t8~ZLyn$d literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/hot_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/hot_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..2e1e039f36b44dba5bfaee2762a90e6bb713a226 GIT binary patch literal 1686 zcmc&zYfO_@7(V4vTM-bIiv`rm-N}L;)`2WjD3?N}gMc_L)0WFY2-}=SL}QGARE&Ut z2pp>!$h{$)9BMP(m0XoDhi+A>Sz_j1o?XM2V2glo7@VXGCH|$la6^#tG*{;zY>9R3c0w zTq2T0gp5T6VS;c$Bte7>O$m@Nie40Pn>>tCPN_txkQd|580Cygj0%|t%8XOasl=&} zX`!1*luJ~SsE}D=m`+sX@~%8&;&0K!Dg%iHo!2AcGU5J!x@tp6S6`q#+`E} zaVBKJ;DIuim?SYF>jy1#bHOCRglq@gf<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;7FVc*-9wHV%#N(3)xu+1`m`a!G&xzVnGft9!|qrcnS017VLo^FaU}n5u||y)}RSq zAcD<+1~$Mjjds-WfFtD0U?mh{G44W+5cwl;B#cOrAwok+hy^*ocsLDf;U(+$B6|HFq?xUERa%GAfFCoO(6%2@#l+7~YB zAbc;Jq%-+9A*z3fLKR@JcG_!HGZzF5R2lVEp1x^2RK${0?iBalZPmQ_I<+pi)i&@T zA-PfgR`%C}$C_Q5M`G&N`gtAJy9LH_gI?*bTR7*3 zoA&Aqb3k>y?fWywJ>BOOR>V|4KVjRQpI5f-@$)xs9rBN?F7L_Kdw%vleLXF9M$nZ# zy6CHYy=@b#+|A3r3wZJNx(Cj_Zfml-;_EvuW{5Ov?;jC&dp6Rj8E3{1-#e$hvF)kJ z>(riMbHCAJo#yw4M@LSY3N8K?ZFIq3!w=78Rp;$)8_W+5tf(whH&~l(=FqcA-u95I zy11y1f);h#JMxsCdtc>@H!9=))`Y&A`l#Xh%K`GD&vUL#-ye2&W8^O9p}w$WZCf#G z+f-RQtHq^Yx?;7T?tIDc)UsIb7KKklS#8E9(T0pavnJLW(TXsT32XN$M&VH z&I#Fj+tp<X&PwBmYBK3-rw2KWM_FrJt2{!IKUZzPkW>}8xZv8cCezNQnXw0= z)h$H{yBFwlRkL?!ce>4q?Fp{T9BcLnvZ^n!Pj_7L3g4uAXLDkR&VMpt-F(B!Zr|2y z$HY+oP;%p;md;!8E&Nln&o+K1pOkBSFSwzj{-qGKDE(|DZyd_IY?KXD{E5CE; zo6d-$EhopGYRsCcg@(TM%FO3WK8bGa>3Es()g$k^o2RsopD0oeDhi)Yv1Oiqy)Q4{ z6dqQ!?OE#mTbueyZFPS3;u2ncF#b`EUo9!QTVh-uzA7ujRHrn1mQ`AIRV^}-wHaSt zRyp_Q==N`%UNCc6gGbNE0j2%Jqgwdmt8Yv*b@!J~Q583(FHH+6+Mthc@T&ZZU&h*v f=F}$dqP85?!H$%&_Oi3zhFU&uiD2yt1&R9?M%lew literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/hungry_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/hungry_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..0659992ad7ee902e77007d81e5476476e8691cbb GIT binary patch literal 1636 zcmc&z>rc~H7(NAL)D=Yuh!oTgr$yPuIDk4fGC-)*4M8k26_vJ}m4TWtj5t9Bu_I`w zAUY3XX00qbQ7f`38Q!=Urw60ibW*{60Gu;wG?^NAJA3&30sFf1q0Kq(`#$e;X$|RV zv*+aNiJrV5BZm^g2;qbXLZou1lrTy-C4v&Elqn;O5zdHUL@M2s6UGVWL~tUNVJZj{ zgbN}BkqQ=-gh|3B5t2v+ni3#k6ul_oHgXuHoKiulR2JjT80Cx#My0|7WyUGzRB$R4 zTIgniazTZlQelZLopUBQ zlZs&QK$#0B1e1z>&_XwtOh_gbJKz@VfgdmciXjo2AOfsG6TCnKn*j}MfMFW#sN(@g za4r=qp%9C47lKR0SqKIXl!fF{F&eQT2N(~hVJ*Cbd2kE%zz-Mz#gGWnzyfQ~1TPT5 zWUhABN@lPU3b7b>sYHnU5jYY?q{tAVAtl6u9AG@0hPCh#c7P>@;Rg(W zVn_sOV1YGgf)|KjGoXPDFifKzbv)oGzr_FHLnmL&NL`ejl9ZVm^JcWS3KVoNeblq? z9W_E{J zy6W|6^Qjw$>wMHx(~@J?w_1~SIKm2_=#uUwH%?z;v>nlH@ztuzz1%!&u(!!kZkz2n zHRZ>zH8agceYS71{LQhpJWr|9uqS&R+v#!XO^0r8j&C{aJepg)ym{eIEAKZuY73s$ z4n&4%?{t>;w6u6ihgZ5*4P-c)D(lSZ#D;6(QEMM8pPUx?M?j!GYe8*+D(cqt;5%_0 zMR}G$%S5ZX-Tzq2xrC*f##-~}in;rjxOVSwxO?VW^qSNlb8*o%+ps6D!C~8W!uKezfj*Vx}T-bec{`lbSG3VCyf2uW|UsF(${`^_{Y14f9^u;e5 zb6TPYQf3A;CsjU7E$d(L_(*(^&2PzcXGnB(PFV4jzMW2c;3d*kH74KHX-I!$IJkOh zc`2!l^zzjiET*#SmGA5cTCpRy@)hgql;Falx_Q%%45dC(7g~2^zNQ{-NYD6fsQ&RN zpOKhG{YOkQmR)u`yFL$yFgEFLjP9ukrlH-Jkk_`caaCb8y>=h1>fO+`n0npSFMa06 zmsne?ja5;)&h3%Ttcb~>#rvp-JaUu^Up&UM=^yAmtBp6S{OuiAqX%=_k;yffcU zZ1Xx(`>l0Bb6&*yye>a$=9sy zcC3r->3gduBze#i*VuR{yme7U@0Dd25=&0^d>7~nQs*=-RT(!EYi#uKnq!wIeP8;# z$aC|Pvh+!3vul=W-&iMG+c!KI4qE-;gTanJWpBDWxx{}}oN2@T*KhadX#&bVS{&c@ z>sLXY`-i413*Bu0dHv8yYrTJTb=tW28JY2on|f6j#;K<_m)7N4+9zZiCR8+-9ajcw lB61R*-yh6}*t)E(Nyf@1_SEV8e{{nUGt%m>r literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/hyper_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/hyper_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..d96cae3d387c2d9975f6fcd637c997ce32848d00 GIT binary patch literal 1540 zcmc&z|4-Cq9DfK&Za{&ZsrZcxq}xG!d+-)ze81yR2?o^6p_4pMRhqdw#gv^Ss~h*ZcM5 zE-Tyka#FFDXvyDX`A|X_A)F9Fh*a*B5=IH9L{K7?GG&A@!Wj{aNTr){!Z_ia2u`Fj zOa)BET9n!3#vN8LNN|FifKzbv)p3#sp(hQHaI3 zbIt^3QV|RuD09JtU{cW!TIlAI3CW~l2i$@^@B;=wF(g70M1VDDf)|KjGoXPDFifKz zbv)n*&ZS}{6k;*%LU5@#3&G%lvXERVMk5yF0OR2_tc8~_4{pI8_yGf;7!pAmSYQpB z-~}Ss3}|2j4AW>w9S=BC$qZIPAr|89 z{D1*a42d8OEU*Sm@B$HR1~jk%hH12;jt3m&m-s(?Xk@_ahQfl3v^+yXOq{O|C}{p! zp;F^JdYR7h--P%-AwK>aOoOiRdjIEiMV`UV343t(_70P~%TPC)V7}-HZVyuFpDMrO z@Ro#UZQkLGcq_QQ!Ps158FZgIpZZ~od0JSkVfu4%2bNq{^A~cn(zkll3lrK&=jM9d z$BP+SlS+3`|4=(_pYGYWb?qtQ+hcNU>M!$ZPk+8Ev7{+^XH;VOY`XbM&CHlLyneW{ zy-Yn}ddKwbk(A*}jTJimRKr9~L+xny?V)u+w)mdwt$Qz=8M(R7>!C%7=D^NmT5Yh{ zQ;Mr^IhnQ0cObUR5i{kk14uZ0-Lsu66yj}Z+3&wxPAd;~Cv`l^ zs|!+XiOBD9Tr+kXS4FgXN8K8|s(C}{@0!~E*|rx`$~>-dBl#%yS@Vt?9(!ZkOV(uP zBlq>(w$LjUhr{|p<_Y7mCC}Vf-|uwkHI>^+Gcsm2&9*EB{+b~sPpnI-dR)3S`bJ>o z+aJX5*Y_2uLN7cK?;qZh^NI62*Eh53yN2Nu&C;Gwy>qQG@XN~AI@bI=G}sioKE1@# z_0y@1ez#X^Tza{-tcbIksr<_OM3n iZAZjeZP#k;rxw2^-LS*#h?#oN?2Kv~Elwrm)qeqe4TU`b literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/indescribable_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/indescribable_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..0c554f3e0304c0ee47c53d315aafb7dddac5540a GIT binary patch literal 633 zcmZ?wbhEHb)L_tHxWWJe3I%p@#a5B`s-qv&iqvaI-Yto|lgrjGF6b&Ac{?rgb~=M4 zL&VLXW&dYy`m<75UoqmE9ghHa_yxYOi-M8ogp!k!H8nLQBqRyxUlPmfn4D!(F4~_ZcPdd%!w-TlbW0>lD4|) zycrAM=|_rcX^*d2daS;A`n#pg!V@ofS(sSa%Md6tk(#UP5tm86@s9Gu@vTw)ROTBkLLOr{y^YpE*Bz8~!rb`tLsj zGnb6Vh6M+kIa(tkPF!d@*d`#(*W)o!!L^ffa|_lmxQ_^f*ZT@|&X?p)cHq0CbK&m{ zS^lS=D;f?Zu6*&c#>#VP$ITkHrOFK#U(~qeTIFv2eX-`ymOK64dH<~r=D+_gX?-~M zth8SE&s*gw43$z<0S5IA&9U97t@gE=cCrn*z5O+YlczTJwY3|~PHCOq7M_{ix@6Ui z<)%q;s~FZu@vK`Ros&C5e4?J~w3fDgx=C~9RUOgZ5L+#~MRspynLSUI{i+F>DIUQR zHxA#Pzn$T}z087z&kEHnU!SV8`e+&P_1pI!KUKv3{Qdj&AJZ>sr40`pn%I86TrJ4N GU=09zasze% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/indifferent_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/indifferent_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..0195f6fad26b7152e4ee2b96d156ee770a089593 GIT binary patch literal 1516 zcmc&z>r>QK7(QHM6BG&&5icuS{RT|eJ+dRCAc(u55`s88T4cJ^nH7ndhES)$;l8YK zNw5(Pf-RRC9F1XZG|Zt9!CLEx*r=`Ahb1G4n(1QNYGbE|-#^gD&WGJO=Y8MjeJ;Bh z8_lbeb}K|7f03C(31NhALIfdFy;DjUC7cpLiB!v!5yl8-L@*-NZpsPcgmWS|k?JrN zgbBh05rRk+i%P;I;gSeRqzX+5kT8l~6mgq5j8aaipj4`hac7KjMg^l%<$*HelyfRL zl`1WCGeNnaLQtu)#4wYTODZIlDrtxSYtRHQ5W!}w0ye-fjds-WfWsLRj7e1?7URx2 z6P!s^FnFNM1rvfvRX=ErRppMg9pk&a;X}PSdasZhtseYUcx-M1$*EJ41i)t1ZiM_HE4nt zh+s3IfekQBqaAfT;7BzySP6w#jJs4LME(dI2_sTuh|rJ{VnGft9!|qrcnLee62tHV z20$?+f;6ze8Z^NRM6emqzy=tm(T+MEaMWMo|L~!ev$9Rw^3v0COorw906$RBJ_^*V z#rLuqIx~M067mo63yIAfa1K|8JR6_y9_SjW3y<5>k?HC-Re227^X~9tVH%@<(GQOC zg1C&un;UdH!jILM8_R41u9go|k2G1wgso(Wu}%NRW9Q|qceiA$PjpA#9Z@bdEUu34 zoK9CVHSv3me=5UuW4*f)qgzNoZ>D3>iNbN^{g1b=Dmavqm9VPFv)(#dcKx&QxPXEA zM}luIu{VbWC-@#d@jQ$y#4gp-|5dMmo0onbNJFoLRsv*w_YmJ^p%(Z$}rbG5w@WUq9(w(Les?H$AymBM$mf@3*fW=^T1AUAtEi z`S$xKdbiAU8B7+Bgu`(J^5yuJXiQ z=nPzW!TCXU{Pwr=@**_*o!Jq?kzF~F7TZK^H0ztN$L^b&uv==B?zsz_Y*t6i@xG;w N_!ghG*3XZu`4`=-f$#tT literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/loved_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/loved_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..a3d6b1f40409370d89075b52787d68f1e31b027d GIT binary patch literal 1726 zcmc&z`B#)x7{0^K1WF@w8W<2p78%Tr_~FPR$_`o@$&w3tVARXvXljKWQ$rD45E5LN z3nDH!fm%^0$K_}&f}j`0oHGvTvG5>*m2Jl*t-c<w9S=B+QckHTDa2yj z8Kaz0Q4$OuC^Jqur=p}Ew9w5&%0((lcEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ue zQO5%gXH1l=ghDLFopUBi&O$JFpv*-kN=73VM;#A1qLdk|ghDLFU6dk3{shK@Kn;PQzMw2|K_N z!|($JKrtkOG_b%LG{Fl*uo=+61{kK%jyfK2q+jCy@Szc3nU|238W)q2F!hZowlYxA z{AuSLgYVZz>5TqOh|@nr=H!*!bhxd^XwQr5rH*4Aw z3lBRkIl<2<8ojr_sSejKvdM2tUAyD4!RBFbhI5(cpM6;!D`RFRSKQm#XfDY(WB6pk zi~#%V?vWcen&w`xB;DEe`HM`0lY5P&-P5w`x0}y>yNYKqMLF+J8Zar&pI^bvj!U~6 zrl~5)v60j|UBpVV$k>t}dUEXT2fHUv%Qxsf*ZlU~TeNUyu zQ2b7dcj}YgcsE_H(rR?jyHEA9CHkjELvh|~2kn%BgH}2-v~!>9tGl+;xH<<9tCs6p zv!dx-`}GdC=X=fSoGac$sSCJlT)f?JNtN1GE5GcQ8?vUsmslHGtIIq8b}w|DC-d-6 zk*Bu|9>^>hc~F(LIj_^WywbxIy~4E6WXx~L3#?haXzkEJVrMs+r2T&+IS_4d`${`Q z8C>0(TkzAtbwO@5c520(9^1X_sz#?S^PIgWTJIl|67Y**>$v<|wPArv z=Hw107man+Iew>I*i%2dZkBq(?nX_KgIZQ;^Mmb^k+*Bt)GJmE#&x9EJH*LW$;~-l zk8|?FZskYvhTC=3Zn1wYxP9tVmlYqUMU^Ti6dsx+yAd&bv!tXws;PhS z$^PxCJ-!Jxx%MB9YdCwLH`sDF-1f&4dY4U!lbR+@Djq-WRK`VXL%NT(PZjY;h<46h z-`+=M!;8N##^z>iGhhAn__mG>U*_pb=Uz}HHYa@Z{zju$SbRu!U;M_I%|p+(TGR=4 z?>QZnhxjyKnjSXYqzSzt3sU>t`q}aOlydW#+H~uVkUMg7*)v7@wVnqZ9?c2eH#42} zSG<;fy~%WBf&0{_6{@JivRYR+Pp4LSnzuuxtZ0jWjYcRt+gCt~bqbxV&_D45-SCc@ z)jrDSdt|yocUzaluH&(r%iA3NlY`?u-i<%IcI19lR*81Vxcorg5X&_+(%6jCBPM0u WC2dX(y`J}w6?}Vc$S9MM$bSJHAkf?Z literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/mellow_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/mellow_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..10e9b06a0339d41b4baf3252a31da5e5671104c2 GIT binary patch literal 1499 zcmc&z>r>QK7(OHtTT3wpgsTDDf^B389N1t~lH0Nfa#19#HDQtCf-8>0 zB?mPTuw){K9n=6P69L_(6N57pt4pXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)(8_1ild?A@#APN$yb-p@4HUG0xvS#v zy>fxh!rz2=J|S+N%T2xQLsgzHgqoebr-$pjb?Z-<934rOt_aH|r}uF$mEkGdPxkQw zU2wef=qi5E&G+M@lwKT}k8df;p{>{eejO6$zr_c1TezYO5D)i(` zg5IPG-D&tkKU6o?l^5lIlq~8p*#o+Z$Mqk6ksDcXFgESANSiC(GO}-Ca9mf_Wh~VA z4x4tHE`Ly@*(zM!iRUV#>cbikO3YQim(Vi%$%O}5IhnQt zcPq_%mj0f4#kS$mN10`xPh9N1lYW2ep7Y~JoTJs@?vozBezt8#L>QUX&4iVmT5(}$ zDu&qHde(Nndi!0i!4Y(6awO+ov3lUh=BBk*`a` z?k8PL)uk7P8r3?FEnnWsTR#x-^D%RIgx|3LuKYUlvhbt=`@_-Z_{G2dZMC1z8|(_- zfBDU%9{7$vdmSOG{{?7razc7(b=8w$NtfHVfV;MQ#;Wc(G`<5H7Y91`HH|A!51gs3=4ohB0v&(phm< zE+XXxB%pwxTm{@l)Sy6y*>OP#!jNr{AZBDFXq=+cojtt&z&`GLXmifg&9Dlv0Su<09qRA^hsBs+ zOgV+H815{K35zKw7h? z_yGohVvq==0Sj0IP2dGYU^74iHh{r2v_l;p;7~3zuo4u)Vz^T-LdYKihlC+g$Phw< zlpq$!0gMNy!CLSV>;RT941RzCpco_qX}|*3KofWY5!ejSfDK?U4ed~e2RPg>@qhSG zP@8CN+^*2z7_HwHHJ=9*6t4whKlt9fLTBY~f<*ryo@kxEv+i!8$lg17xU+u1BvVGz z=({ct@q}Fm2X(S5+5WDtj*GNX08#AnM#`@arCdd;!88-g&)#?^PuIbDfWN(0>t zHb%w+S+<j26I)!(8`i7GJa%o=o3jUXe|g79PbX(LG=?8Mrax0AkWuUF@0xnX@-!Gt-%*A#5;)cClJ z?MVImY*ddt)Rd*JBx_#mGZ#y<90rCP_7}CLUCTCBbg z;6VPJ(d+JQ$ER?v)Z?M`{l*CgiLm^$(Ss)Orc#^xd5u%N7Z;aYloEaX^l^TS+&NW8V}ePy0XuiYCt{G@3v zc>L1>gH3c`kt|_%lDOYd`9t}Wpm?KKQ{{Wo8P`1d$?fx1>6(mrWOc;Lt@7}r@TL&` zgQAj4xtZayL0qh>{v+1eeqOwFTJ@Q>8DtW-Nksm#YQb8&h&YF4+w^-p8PCxDu(?zq zcGF$<&nr{jl>2O5E{X9SiL6>3dzrKZ7n;#zObYMpkps#wr~Hg%&vND1d56_9pM?RF zu-v{Q`t4-1=R~uU|BiQZzt-?#jeq(02){b1!}-rl_2A9L$KPvD%&m`{X#Z7mdT^=N zceFmN4=X;F9)3Sc;qS6GAla+nSjz1bk2j)pk+kqiRY0NS+~U;it@a_c9pBG=*Uwt7 zv$lo0TzQFW$2Gw(qCJti29IlXixYFbCVpq{;lVw=&OSU`gsX``hYI8*TXo(xaC0qMRKO%yT*o{6+2xqeO&;(nK?yx}`-58rI~6B{H`VjC{H}YKkkGo*s>Wy+cQqzn mG6nzIci|xJeE=baZC_6Y^(!+!xkE#9U8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/nerdy_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/nerdy_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..705cf7d43521f772fe0cc1b23a5b1b1b79b04c80 GIT binary patch literal 1538 zcmc&z>r>QK7(S>li$J0agCVyK%$+q6IIxM~h1Oj#NRUV*m~mP3xDYWggiSMq39_sP zdBL)S+8{{D5DYtw4sw}shfAxT7}CbH!VI;nLCFRNqlweQ?;q%6=fm!t^SO5J8Ak?vxTn38zF*B9$^_gfYSy5sXNsn{vW9;hYFgq%uqe zVS;c$gdkGEqLMI4xFkXnsX$W#B#fdLMcn2Oqm)xBD3!`$+!>>sQNgHGc%aNU<(vvm zr9uncOi(VU5L7BGG0Y_8k_t(sLK-5#8Z^NRM6emFfDJHAqaAfT;BdwSV^UFw#kh0M z1ZPqa3?3+R!GvH^(GOba=8_4?q+$o$f<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;0Vs8VkHz}G44WesW=P4;DNG`Tq;H*7UTfq;WVs;moN`*!5;Vl1E3fZK^juh3?uOt5S)ATAI&y^7w=j>mbT1?9#j*fOa zG+Y9dr8em`#R&xlLuPx@dz~Wem+_&xpx(I&=i5a&(YC7|<+{Y`*NZmo9UnRsu%ac( z8mX^&_sOa|A(o1X>C)kJkD`(_cka9VCNK2+4&~}I^h5>}^|FLujxj zxIQa2Ke}vJ!Q&IZ-S}c?&=#0t{j|(@wI#qOp%UZ{MHt<@8Qq2VK(i!J>uha&HmcYtnP<&7wr~% znry; z<8YeY%{3-E+ilB=*<&~sSN!10g_7X`OTy#>-HgN87~+_I)c$?v52Ko_#^OUg$F|2- z)K>NYzZrSjL|L)++>bL&Po6a@&e{{l}=BpWXi=yI$BIbN>P+1pcKTjlI(_MV*qwXNIp6ud@9f>+ z5b452aUvu_Z_xO{2oVU82vG>p%pPMzU_@d>VMH@wOdx_lB!MUb(M&cb5kVr7L==f= zrWjL*pb$wRib6Dlg=s|4h@=rkBbtH62#}x@av=!2@kL-vVoYI7GmT+S5SSz|MPQoY z0bzo~B#9{!(+n-hCMZl&n4&Pvu!LfQ#w3j?8q*AE5CN=#Ch!6x&>30*Hh@7jq(dAI zV37nt5d_UBgvPKZNrEB?nh^{g=hIEL-0W6xC8CVGlp)u@fW`r<* z7&uHAMhY{8p}~}3EHDQ!9-Ibi!Ar0MSVA%Q0S16#kO-s!3s?h9-~~jWGe842fI&5+ zLmUoZF<;_;@UW++u9B<^7cXBU@pAJpH316tZ_OtA!`o$?&iFM!toO)-HA{B7qInk`D_-~Mpm{+uQT5C9u()Ti6TS~9G*$ar!R_ZtTa)s zuZq%J@<;hq(p+1;a&Su6mWOOPyFs$J;YoCp^hQT$r-*$tZ`; z=kluV`nW@-R;49avYzDtA0vm#&t`Z`rBKQz-tAkA9UGnBE-{FN}Jgek@UW#u&MBx_9<8zv<^E2p{B` z+wS2XS}#n^Q63})X7?Sp_x9*cvJ;nXPU5OpTD^>5d$3Cir&x|s{j-vtM&X(4i1DY`m4Y)kD$sz}?z2{c2gkr3op0HFXhHVfvncVS{h{P^+K7=9m2I z+n%b*!}gW5e3yRY^N>G=;(K|G@$T`@yuWG7_pQ$x+2U|MsAj{~A3QR+OI~0$x_t0P zUqFb;QEOJdhpT=))AU99j98gx*3N<{>bEK5YlRH>^PG*%`UKYUb7~PH-rD_MH$aQtn#(?DV(!6 zNS5XBNnw{Zf0IM-Qg2ymnnw+M^p3S%70uU!%gxg}syA|?T!Qsq#(OAD6PM>KJLNgi zgIn4m4N6vW`l}XD$0AuPp0m!@_MEWZHTXO0l|gDqoVXqC!?zon$D|cd|u} zGS>woqpf8L{^zq4N$!Kq3U-r4OYNqNp4KY08_Y00+ z4Et85XgV+U>qc$DrLK$9&I*cOu6|^;;9gy{_Z?&LvB18!hP}br?KKr%snm0p?Bv`9YS60|l~}qA;n{T8+wm{l4!^$u D)Gp%} literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/sad_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/sad_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..06d2cf961aafb9442d93c67760b9513e3c15cf13 GIT binary patch literal 1580 zcmc&z{ZrIM7+(a9Gssh*z!&5=)RRnsg_{`BI1Y|OZ;%8{EtO7P4#cv-tSK@Dfnzv8 zkUt;5Jm_mL=YmCJEeqC!YL7yNTo~}VT^D_1S3-ErkpTNI46P=sSHy= zm>^sbA&6A4s3c4hE{TvtD$tYw38Uym5x0rMDCLw2N~N+Gcg84ZR4^(P9w;+TIj4eC zsn9|<6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l* z!I@M9g9pl7Fd>*!^n(_?j#M&(l~9PqxJxBMj`Z);k~f>-if%@<7M(2{A^mA71FrHwBYEO(4JudZsG*=4ia3&N8tOdpTA z?tIl_Y1V7rO2{=DuZMc7#{7niqPrp_e)m7Qaf{aYuRYWoxW$#9acst&@hr{ofaTM| zkP<_IbD^l%6Bk(2{#puYeAj>dnQw>hUT?d3alEU3y$HFi|GNH|}+wOlue|v+?lDauy+PTh)9hudp9&6LXOvlE7=iUpK z9}ed<+-A;VdVkKw;_j!`9~Z~mP8gWV>5`dy-`DRpKZ$B%iJwoOrK&jBt!~`@q@=Dd z(KCBzjZgIXy_=If?NQw3W5_B>c^dM`A)uvd+4x9HxoOhi(K0WuiC88l{6{R8%GBBwht1BT zDMg+b>uHy|$zP?Plz-pu-l9#NyV4P{Ufs0cR9R^2aMrdZ9;~wV3R^*#z9DMcSo7u8 z_g1AQ#km6SUD9UJ$h^Qr(jGJ?!Skj60+!{StpET3 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/sexy_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/sexy_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..1313b8f94faae4e1126ee11d2fee8c69863113f2 GIT binary patch literal 1693 zcmc&zYfzL`7(U$A1wnxzV$);=W(Y{s16yj%C@TmI8n~OHf$q|BMBExJZ{#>3iwg$J zkaF2WUUmZC{jpOOz``_=*kKH-vec$JOF1stT zGhbO`Odtv5Z!&c#A&d}Ch(w5x@01co38zG&M95{z2xEjZA~7Q5ZpsPcgmWTsBIIEz z5hf8X5lJFK#-f5SLAW52AVP+w1V|V~FN(NL9Y!gqRH9VKi*aX+az-Uah0FtG#wq7i z;#A1A(9I;uB`Qf&$Sg6;1m%KCf(n^5M1VDDf)|KjGgbi`V3UhB6j7f|MSs@nV z&N-7f6S83NK$%NSl9-V7gBH5EV3J@$wgYa#9{2$RpcoRN2_nE6G{Fl*uo=+61{kK% zjyfK2B+i9wB@|*Y?vliX>?{O>2g;J*LN*$)AO{!^r(rF;gn4ia_P`Gq0L739(!c_1 z&;&0K!Dc`M8(^45JL-7A5prg*5(=>xcOgfJ{1G@3Mx@9Pp&=#2f*fExoQAdV5_W(k zhT#VcfMQ4lX<&ghXo44rU^AeB4KPfj9d$h5$iKw@;X^H^ugcKtw9E1`7S5aR=K~7r z$Nqr{_)eapGxawi%BRFfIV-Evamk{5M)jocL2X}k&;`S`1zovS${9X}+chDdTuF(F z-cXl!?>Y(8#5GP#gsJ;gQJI-vE~R~SnYO%l%m+f*U~N=#;qR3?i{km@@@F4Lzjr?% zpy+DqjS;QoT6@m4q2X;^+UnZSt*ZvN>V1b!`)(;Ty`k=_x9dJtMYip`=WQ;F-QMYF zv(zi~?!P=sH61pxq>bzs8T#CqcW^JZ`69{p#BFE!Y&v!?W# zn8sx9DT`M3W5w~%*2Z0t#c#g$RigLej-;q?i^9q}hF2?oRrdaoX1<&fI~cOyeATF@ z-*LAzA@^ES>9p?k$I2SNpR_6REHhI!n0IMQ`|Q>a?2BJFhpQH~=8U{-Of7EjuH5@V z{MyD+|KOOlGmHK0sy(X76-V={^5Ye;M*pl4?Ql(`J;a(Fqp*y5=f~_xiYU?ND9ok; zORb^DnBKH^_bg4k;|D`O>9127+kA6s?tGqKujy7gi+Z>D-)$;j zCr6tLcTSGB7_5&wB2CSk1MKX0Hft&CnJoEu%ZKG9OXVB`Uj6SJ6AQ0)I{T|bV{;B? zg$-XtyJv)E$#Gh z!|BB3!_Gr*uMM%L+PB~C%v?8p@#2XZL(7?4&UiI)G;Yp9ju9+rKvBoj=KQliSbehc zpn2uaNXvjH_nW{aDUbG@d2q*Ly{vDpP^o*qb*>zn_u^Qc`f^y8J9ux%?IN?wHNQ2a zttb6%u%k6KV!-pzyF4kV#gnjeb82z0W8cO&p8=ookgk)qqS-4SJx~NYHYFU6yfsv` z&hmxvE!UIrpQC$PW)?@Rj`kDr?Z4>GHl_abZd3g3hWEGZNV}PAf zdT@W&OMMmk7b>q_EcZ3)`f|^?$HJ>&jd>jKZ1Gidb4_?m1VGVaX&PJQ6U l!CcMc{X==-CRd|=bzn(T!5X)zxv=bfNsBJiZ9-;C{smuH!S4V7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/sick_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/sick_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9e83b7a8f5d4aadde03956158edbe1baf41257e GIT binary patch literal 1915 zcmc&zdo+}37=I_1=;m5GuAOmPNj1C(t^Uwm+d3UKsib!IBxP5=eSClK|NH(ibDsBkp5OEP{hs%8-|yz=bkq`A zqK|0hV1x)l6hbsY3>#yN2u2h}G)4@Y#sm?9D1vB$7`7Tyh){^45KSS5ZN@YrG@@uk z(}-cQFoOt#CJ2V~WN!jTx3DG!q6>45k^(u%tl*um+mI3y8pE7zNk>2Hj8&dANW>5keEfunJ)? z#1utniZHBT-~nlhCNxbLRzJ{!YKkE=Lm1W$a0~1KKfnM`3=%;Thyd0=6L z4Pej><&cL9I5b5utd*b;2188K6vH|Tf`JF5X@+80qhT$u2QVI-25Z4fFb~`Ud%zDc z02G5nAPrc+8fXG9AOe#C8n6Kjx}hBMZ~=#5cLr91LKqA&!>$na4-1D4!%AU?ur$~b ztOfP}#)H#fEqDob083~FKfnM`3=)AfU;%5O3A}&^Oa^Gc1~BM`a>&C49QGyt4?jF+ z?SXy%egaqFKHKelB@R&FEh?+K!oT$jot4i7sVyUpnxTihsw-Pf$11c>UfrFqY3gZx zDxp*sGT!Kuddg?)vd!*c`NOt@Q}*s6d412!4Xyr*y1wVTh#*UXtTj4v)T@5yZMHLT zYCc|E>m@PA1Ig1$bvbSlyH7=(!}+E)+W3&N`e>eM-EKRD@b&Y2nOJMk{7Vb~(8X!7Xf{8e5a$1HT*U%%Vj%qyrl(>x$N&+eyd{y`shKJz=f32kPcnNv6)Ziz588 zlz)+MjYW~4lSZvApVSWrxLB#a;>C!0y2P{pVzhp~rn5A#WVZH_J-517N06I1TfZkT z$Eu;Oa)aG${f)HqvkmnP1F>}~wU6{Q*>|Dx-|u3wHLgWA=zQu{6}*e}1IekDgFN@< z4Q>-{f0fH@MDl_j2UU^ag5~No!{ZCcB@ra^*v1saX zskXk;@T6ds!%h1yV%tv($9e=JySBM{Ubd=%NqRK5SXC;^b&Rr)crA$cs+II)oERwC zGUyh)D{R-iV9q1n#USRDbFg?!nsCO^S#L;mM9NpuSdhBLYdqv9D63WE+4NlTNQl<- zKAjYFucSA!RGw91eW9wU!1&74j*+Kldb!`cy<-s{;$a_Jx^?2t@y$^^{4}SOu|JCV ztC{q)(|^A!t4LobaV)HjS5IzQKKz4KdVBISGqS8$4vBizXxf|Oiid^VIp6fE{@*^C z`juTjTKp{1M2}zQohX^o`#z>kCD`}nHj})>pZD{_zuhMvSMU-NUYrXLyIRW8Z*P4x z8nO27IM27n$Sq7m=b@dS&z6QyWBGq-)tyZ~TDLHovG?tVO+gX2NH&*md;L({Q50IA$X1nlVacW! z2XBZ;PjG-vda!nxrBR8dV8;fV=~@51TDq~f+GZNwG`26yzPa6ch&Lw>L~k^k`qsqB UzV3IpZ{0Gu>7Th~4hQY}7uqH{?EnA( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/silly_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/silly_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..86ecb62d8d9207342aa52e628e804ba54cdff631 GIT binary patch literal 893 zcmZ?wbhEHb)L_tHxXJ(m|NsC0`QgvoM_&~R?Bt5ABJWj4Kd6noTM~IEm#tqs@^)I} z?Q{l9hKQR%%l^;a^k-$nH9H;w?(hqIk>`Z|Gcer0e?K`nSyNL}LPFxefdf%@Yc{{# zFVvvM)g`<9-`x1qGGI$+MJWE~_Hzvhc6JPKHPSO+W(3-!_>+axhCzx!2V^J6n+$CK z9eN8qbfo%EqzE3!v6}C*G=!NWVtr#**=bgviJ@<%datY4?`^p4j_u-=S%$lRw;ezJ zd2O`RzUb2oDS^SYb&;_-)d_7C9ZfAg^$q=A49u;JGuqSqrX(;k&8Q6!7WOTf$~-;E zUszDcLz&tj9UryV^vQ>RnF%caA8vQlW45%Xnpp$@yJ!MR$Y(P8Vqo#sjtxZWXtsB7DWBr+Gv6JuqOfzEZaH zVM(fw+5GKUhQD9d9e(_va&zAC?zuI!nGDTUfo1v4g>CMQO-WfjksayX&E5>mHI0=a z(*v2AX2*mnCEyvtd)^46#LPmj$msCcS^ljNo0z zm!D@iDJ|Es)gzBV?&!voM^DOK%?`NvQ2z3Z%MT^5Jz2sa|MBGu-ZyVcmdMF`yzuvd zoW!~v+zLkzvqv0rSh2e7?F5m!4f{&G-B`QDDg+!`em_!-H7oy+(3%}!aA!;ZkFvc{ z$Jrd%CU5eHyyM!tbnWzqRz8`JC#fo%Yg*i#c+p^4(v-Q*v3y69{2yGhJuuHHR&DCZ lHHFT48FzPW)e7Q`Ib5_>%Vo{YjVTA`U7fW}ccKD=H2{-KU|;|M literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/singing_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/singing_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..099356a84c2dff13ebbaa1e3b6658e1a5d339a9f GIT binary patch literal 1639 zcmc&z>rc~H7(SJXg0Qfvh)mQ9YnT#JIJKdu8(OGZfhadK5d#$t$iU%bf}3uxunrKp z6i^O0yf7!|+^TcVY|hBMP|a}>VzgcoZ-j`tMKgzNi#vPx{Q>*B^P$Z-@B2RQb7>bZ zwZxcm!bv!JK}HWHgb~6C5rjzPPAOrOa7qLvQYlkL7$ck!!H874DJP5*&WYeeD#KI| zCI}Zq2qG0MDhZQ>OCltZ3N$4^!YF!C#BKC2N;##1QmHJ)oiWN86^u%S2g;07&Z*#3 zDzwne1m%JXL8ZbH!%R{xsgP7Eq#**VK@+?{1e>u6*Z{*c+EK>?4rfd-CKZKPj63H{ za3&SO;DIt1Ob8|w{h)? zj^JD>Rze{b<1Pf3in9<59w-aRrD8Nm`6F;7j7X6oLPJW31v$WYI1OvzCF}r848so? z0L739(!c_1&;&0K!Dc`M8(^45JL-7AQGSX4!-rN*NKQygH7{JA5FM%aQh|c@Pqj}p zz9UBIjQ&l?_t52 znSIe=44&(p`H9+X52GEEVw&z=u+$kw8lF0JOZUuu$M@8YC1!7by zMFVE9ln(vp{o;d^{b?;3^@RbQJ#&6;O8jhn;=1&F$DswaYm$QdzR1{XHWh{+(ysR$ zitXL>WaQ{jR&((KYw3?M71}6UtUYmi$=W+7GG3n8dRUdDH8^Lya_(Bx#yeHJKHU3J zt+%7MBVbwP`AzB5H1HhRyw&Ex8ThI=|rij+oh#w+57l7R~6JU)NB6x4+NZUbgyPyJ?*(?upIrEB#GVqeV!@;Li?nXz@fYoz zGJZ9*s%=;D-BXROvORHgw!J=Wv3I;7sNCiXySwPbrwN{TPs5p4%k=7z?6j>Lp0_29 zD-B!dr!VSi^u3gopIS97WM-#D^Q_=Ob)5Gb0}b(k>joN^=(-1-+Vk-@8j~%XTN_d` zs&iXXqfKk#l%&S~XHqd&Y9>1Zw6R;l`*PwdCQV(XZg{r;Or6g>`_+>xLVFs=9PK`r zQDTd)iS)O9tL?Fno&L)rE4%4|9hSO+oo9xkSfbq%W+)smSNQLrQa^pSPjh!_%XHIl zL{;%n|Ceue{8oGN*x^uDa9ho@6~i;FU(=RV36H&sl6=hj-di1Xz4!L z1#8n+*)5)3N3G@@zax{*x?OAP=~P2>bL_EJw@COVrsKQEDT6(I>bKUqxA{JD7gxDg zT?&f0b+x~zDZTJ?#G{9rt7gNpm3cSywH>LywDlj(YBPGC?heW?HHLira$la8pLbX3 zl#NXn4+a>0qf1D#r+N9r4Sr8nhUCtTD!CiyX((BlqtR9F@U6@$-)&W?%Y*FX_<{RY n!(i8gy7|KoJL@Noz0p>;DA1IfVbN_4b6QXT5xPUABJ=(Q{oSmO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/sleepy_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/sleepy_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..26d276813b92135f427b5ff21cdc3844bf851941 GIT binary patch literal 1609 zcmc&zTTs+h7(Xi)p9Fwj(Nzpg3VOHi){y zh6rA24r;l0LrsEAO>8CBr-6ji6B`$SmC7c(CNqDo_p;)?9Msg_x--#Wq00u zYtk%-p6JO_GJGf@j1W$UAVey6N(rNcQz9slN|`dk7~zZvMx@eBIbob|P6Q`X8K#0T zLAW475UF5MNth&D5+R9HpeX?oM$wBRZo`LB$|)6;N@X$bj8V?0U{oqRP-dKRP6ek@ zp@nWHC>K-+DixL(W|DGAg``p;4G~}sn&1T@*o;-c1{kK%jyfK2IAek_sVKx^+&O20 zGpPs$50trJLNKZ52Q74S$%JH5u>)?w9{2$RpcoRN2_nE6G{Fl*uo=+61{kK%jyfK2 z1m{w*5(=>xcOke`oP}WUKv_sG6{8Uga)9x08rH%~mi0K+ueQO5(0@=N?5J|;+YW_os(C1p{1;xvPw3KS;%1}2p0vQ3)U+}+Bp~Xw$oh_*>1D5ky2P`h zXzTV@)yJ2WpNTQKCyuUK_T?3q|9Dk4DfDf0-q<%+xAJUXy@4#*?0m zY0iTeems>qvg`v#an{-%PkPj~u0{D99uB^J`%ahP-j?77RcG>7-^|@Kcx52=SZYb` zpF{gns{Ixxwt2Nn7i^y#;LZLw6<@zTvCmo_zs|V9 zxv|~7XH?Vt{LY|>nvZPb8cKWXSEmKXAGW5K?>dfqv(`>)SAbsVR@4ttF*eNp8F>~$I_msvaw*%$7P${_Q`=EZ(URC zsP9qI%IB%5hEo}1M=GI6REmuK_7T6HsT;p=RBJu`ZQyiBb->O2v9+By zV#Xz2zcfAPcv<`VhGxG1(+8g2>*i_b#m_f?#w$*EFU~N(Suu0)#I)_M!p%qHO5fFK z0vnxsL$3979$FjGV~)=5-dDJ{MAO}PIQ18ux5eS_$TKf*PJbub&%V|By=uq9FLEl> p=Zkxb4PJd;r7?3=`>v!1xp`G{2Evib(6hYinO*ru%_2 zX$c}h^sbNf04JQvxK6q8CNn1`nf@Qz}s^4KPfj9d$h5aKck})+44f&FOik?{~zjv$rpDslEK2zIN9rKlg7^u4aAkqU)R}H+`4&;Cjuk7beyk z+xGqx_{z+_*azML#nV!6C2Z<=oZ$cYiM6Sr>0hiHc;?~92Oj;N_ZPby`$o0uxoXXm z?&v)i1B}D1X{>3-y;FU!tlKnNmmhc1q~odk%ELbiYjce|tkwNJv}|LF$=;dj?%_LR z7zw=Oqo33euyTt}QC#`^v$g#zY_s-MjNBGH;Ni3{@J)2)M+87fwLG^q#c2*26IDVpyp!fvOkCp7-HkJQHaN{Ebfylk zm=W=dE24hZB|92()Z-@9c`mQB@Bg;st?SqNwRfzp8pW;Z$hPAXuU4lGxiM;eW`?TX zJnnqIa@%L?&s$r)itTL{O~Ia^Z41P4~BsNS=19S-n&-a84Ed{Sw>r z8IEUl%aXib=Dy0OXI#}?W8>d*M(k|YU01feJ7ez7mnUP)VmQ^xB9Iv;dLYb*{!@=(t#m2&IFg)upk>bLG*<+^udgJrv-s52{ZM9oVp rJi9*XF@!#BD>@MNDQvjT literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/stressed_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/stressed_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..598cfdc803a22e52eff3b585fa7303129c16264f GIT binary patch literal 2852 zcmeHHYgo&?%KDG&k?K`9{R5*ZTYfDn+Yqc$Bu2#FL& z?s9}y?s6Yc$bfw;B65?XAmypl(Fzr&RIB4Cqqbu`vp7Fso|#YcVP=0wp1s#v?|R>N z?Xv@S1-$pZjF0%}C0bt?LO4PMLL@>Iy~i+wV~D^Ii6M#(V>rTbMBs?T5k+TX1i}eK z5QroYMHgcv!bwDsh$In3V__7+DMV0+q!2|zV+fF-6mlU5yY+=*7=d9VhEa55*yA`x z;24Qx6wL#|IDruaMiLlB(}HZA#0U~2NsOXdLNQKZ1ci|lM$x1}1h590zzc{#XJ`f3 z00z~N4skeuMc_Dz;}oqB8pEC-aFW0&S}^c{FhSxZiBq(Gpat0kg_9Ic(RP4aU=R2K z27qFa2%10yum+mI3y45xfCg*;gK9{JI2^zt34)@n1clHT_9RJAw6h=>ctDt>2#Piu z#sYHy5fs8^E9%(jg89uqb+FU?nJo z#;~X85yJdo;4onrDa;Ut22+Buz#PDMa2l)yFToCA3B}+C7yybvB9I0wU=1{Z7Z8EY z01emx2Gx)baX5fQ-^BmI50CoQ9&tpt$Tw8H-PKKp0Tg&Y>FT`=|1Rrv);|+u@CGpq zY$Uz)BLxO#PSVNVhEX-!A*fE$*C;-*uwDMeB)gVn=&?buteH)42(;T>;uy`YEetrN zOz!O~Z}F-4gZw6$oXz#9aZCKUek$z2-atR$r1^tU{#c1!fzxLXMSO{&Q>w=re?)z= zIbO&qM>@?C&D-rMv;4~LC_%zW?_g(vV!=;-O*wyQ)}cU~UYlY*Dmf(i@{s{V8*es&U*3gpZNZ|s;jS^a_R*taEkc8X5Vua8yg zg&*9{`qcaTp4Dfa`WA}tM~P1_J($um4s;k?;WMQ}W(mg!{+5{|n>nTq+x?oz>1VWY z$8_)iqkl)i(n3(P-R_^-qe}mpIzAkuJ?f`$D$PZEx5>=V?~-=5l=BEWMr;7Gh)eYNFI{qOAGy%DSvsk>ye;9gqOl%QNoW{(z+pR&U2e^c1B zWfS2Y-_>indeFZ@J*ZhZInZTdDEug5#-Dp;Eb=>jb&OfwSMTV1i|5ePB-wJ7I&KUF~M+3z_7Ptf{!&S?zQ6YJDSC zh9I;n-|Z{TPMb%kcpkY^9A>(s{?<)z$x1yl?hp2f6}Pp{jtfs2AEz>hxZQ52`&Nn; zL^F18dSXVnFG)_`Rhy8wcgC~&^4Pu=oHnDGCYe^_n;;>da9-rDYz|a&uZC|*)|B1; z@bzPTb7!5b{tC`}&Au{eqp&D|qx5wr{B3QstX1RpX0I5z3&tfJw|aeh=kQEkxJli~ zYAN&8Jyc+!$vZO1k>pp~F!g`T6>)x1G3G*k`&e)$Z2EGdiosl9k5}!?uri2E%N-d@ zEEdj6xr^OCD`nHWwAVk%H50)EXrtCwt}MNc9H23zDoQ zVe-YODZlwuwpCSEjFVvM`mF|$d@w4y{rRGh=wf&K(( zy%^vZWtK9^%Y$#Z70&ZA^-Lo|Z?{<1Wln5MDiborUlGwEj0?6_ijc+S)S|VCAZJ$J zTnzW_sfOl|?bnc~BL3`{sVIPt_4&`<`2W8?|8uX8*FOP!NwWU{ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/thirsty_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/thirsty_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..3e3e77c079a55f1b5623cae1a15335e3c472228f GIT binary patch literal 1643 zcmc&z>rc~H7(Ps_6lmmPm4b?e$_fH12O5i)2tp}t5-aL7Srj`wL04l9Z1J`X6f25i z3wSxf8L)`OLU# zFhRH=LJ+B7QAwC2ToNIPRG=vV5=POBB5q@cQOYS5luBhW?u=2+s9;noJWytwa!v)O zQlW)zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}r zf-|WI1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+ME za0KU4u@VZg7?j`Bw z0lt&R=#2eMNYFndAZV(!t?~Napva{6``Vha9AWLcvWNY8liFmccdu!WCk|6|M(vD> zz`Q+^7Eb?asLwM|6H$Bf-If*l?=8{kulkLig!1|fwY_@8=Q$EOf6HG}UnQ61IO4Yb zArgBhnE2ZZvwMs$N8V|U-r40(Kj#>(nX;v%>vh`G!PZ4RRZCUpFBm&Ef6b~+T%52z zc6;N@i>j1a-PNDmzp}3(OBg>an;qTB+t0hM9oKIzN)P7L&1dbYcdn$S%V+hOqr0Dv z6gNa^W3oReIoCwJr}Vpyjb=P`+k>0bsm$g~pJOqT@6N z7%Ww%96ru^6B>J*G2R+|{72&IQg>YG&P&sJpBrr(pM5h?zARaPw`5XW#a2z$9c{jD zc!uiZkh^VfRfJ@XR2Aroi@R3q?j5^VUSRWOSz^?c%hXXBefLWBRwe7#pub=A9ebVOOaZnO6Q{lee5+k7z5(BeHY$9u}WYx19u--`*2 z)@7!sZaFPyw=^eQ8h&x-j6HPU+)7tx**N4f3ESf8g1{2F|rVsN@sRi0Z^7C&?Q(5f!IZ-qKA z?c4HCpKL1Xvxcsj7iKbq2JH=uNUb~^9MR=0FO9cHmTL@WeD=KB`;TtdEEs+C;K-D< ddcS+g8>`=w^QO{Yo1b*E*}b@BQWzog{{?8itib>P literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/green/working_sg.gif b/local/htdocs/img/mood/moonsis/stars/green/working_sg.gif new file mode 100755 index 0000000000000000000000000000000000000000..4aa926a3ead2cc9229b2d3807e5b1a4cfffaefb1 GIT binary patch literal 2039 zcmc&zX;)KM6um@91wks2Ydj5Na4AC@6^r zcm^tnifBMoj7uDf71V_fi#Xvd3RaOi)LGZ!_4rnQLBI5VNY=UMoPGA*=f2<&@suBv zrXd0Ph`t>HA&d}-5QPxU!~}sbfk*;T1frQVff2@t#E8O(W~vDiVG@xfqDVwD%>;!o zg-8lf6rvd{f<~A|B#kH<(F`hrhH}Wm1soD% z3S*j42!kOeNlcNLW&{HdNRt$%C`>c@ffiJgG^S`wGj@PmU=R2K27qFa2%10yum+mI z3y8pEfCg*;gKj8?JY2w`NRno(1cfjdVu~VZ##s;yJRnWcB+VENYk@t0@!&LA3tobG z;1<{eet-d>7$gE|zyj7l6L4Pej><&cL9I5e{}uo4u)V2EjEg|L5EIBXbJ z3Oj_Q!Ioexum><6oCa&bORxi2LNoXQ27qFa2&4fESOZPq1w>#nKm#^_K{u2`9xmW8 zFY$l);nPFr&RGySJ1}C7ulJ-u7C?dj+0uF%{Cj<)^X)T1g9nhs;4zYh%5yn`M|j3x zYN$HD*wvmb3zNtJ$zk))BQ$^^gK;V+h)Ez z&#R$%sdz`x80Bkzx7+#R2~p2l%$wZj=^QkEoyCDUMM&(BeC#Oet|)!3(Lc{~cwC2g zhA?L0ofXS&6^B33s&|Q!q-136L5J$9eF^nlER8{0_VV{)_qRjai_M!C?Tl7Cwv;SL z>At+idRJo=fBCTVG^dYaJ=v-@)6NMm$~T-0&`_+TgEt;=g^F=b>5&dg4hZAg4QGyi z|6sx2Db|gt?uVN)53t2a9hE^Du6qs3>W(>YFOte&k0ihIBM_uT6L>zw0mHNRkZg(P{TiW9}oaFFp9pB%-T^+uFk6khn+ zQE!v%RVM%CoyCEQgvUR7|XWfX3C=NqHZ}% z@NZYN>Li@cNnz_gCvK9kKQ%jtuQ}(@8J%;r%taUPY5h>{f2E{^n;IrxDy84#?sbS4 z3x?>fK65EcT-+u!D*f`i2W8o?YMpc%%O+f!%NZ}N)MU7K*sOi5?c8AuX*RC@&2D52 z&y?8KEAsJo-D+H+3W>@&wsey|^hoPPXIsOCoBQ@JBym#!&#EQuS^1XO(7PcMW1Coq zeVSL`xe2PiouXVe3#FGFeAM0Gaprh`<7IP;t0~CLsn%0zex4g|#-3at?Q!fY4er^0 zsJ_WX-t_WRzxPOc=ABvnhj+G}H#@XNtlxV<-{q}OnRB$6wZrj9NCUqrsI9;y+LTz3 zp^=ul2H#O!mtdAD`Ps01{WE#vhE_$u^QhFw5{+P#LaKV&ZE|||As}qk z#IW410skVeOy6kIPdMhKCS&>2R(b2{`rB(C$@Ee6h6i>d;`+`Q<4%0g1x|_e(WZQy z&i%6dr_PS=1{K#Py?xM^?~{6?*~519uH!WWTeF&+zl1;JY^9xFN}z(Rywk)esr^al5mQSLe3eZtYx z1>x~E-B!Je)+=8xQu&#t+&7vm_w)YqlQEU7gwoIIk~TsJAhcGA6;PV=liJ#|`@uei*{Q>G0^!rB%6C;H7&L&7WH PV8f|*S(hUM5SscAHaToK literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/achy_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/achy_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..a6b1f4e92abcf2c399856b778156517d9b96b949 GIT binary patch literal 860 zcmZ?wbhEHb)L_tHxWWJe|NsBL7We&9=aZ8?PxD1K9X|J;!IB|4IayOvQ$j-Gz<~n~ zTc6xXdVeeD%`)vhS2`cxjQw`G^GOBIn$u_ggAKq(DE{a6a}5c0b_{Se(lcOY1gcg1 zcQB)*q`*pFzr4I$uc#!aI6tjKFF8L~KQS*eH!(dkS)Yr`xhOTUBsE2$JhLQ2!4WF1 z;O^Jh3QM!80#ekBciLU!l0Ppr9zV zxLBbiBePf`7syIXPgTgw1M*W9ic-@vi%U|AfOeFn78Pga=W&(hC1<22XDcZA7nA_` z#R@eDn}N>DP0cG&NGnRrO;zGzQ2fclslmX_pab$eC@dLR|36UbOUay8R|Gs=CrZgLKf0nAM$&;rVm$&p! zXr0qB%_53{anUMI~uNj!B#?Q%fz&yAJnc z*Pof#bh7ZYU#0y{;X@gv_UxHgPh=!7WZ=5j{D8l5&*LlIi=IrjRI_})$1q*1p^c!mH_325`l@vbUHd6gAg_s z&|$d(BZz{K1OW{*Xmwf(D)_L9CF~%r#R^h8R$(X|UJvgN=-1v4F!!Bve&@H`go#3T z`6qiI543<*4uKGf5JreXh-U5tfk*;j0#O8_nKD5ll0=w96p3i2o4|;~2xCNHL^Hz# zg-8lv3Q-iI87zWEB#khQC>qfWG=TsKMxhsqa9cSfL12QQ2!du7!<{4vOcE4H&Kk?DVn4iJHRcl2mAm7Kru)JO&|hT z15MxsL|`*O12%xcG_*qnA z63hd)z#i}e3;@L-5l90Tum+mI3y8pGfCg*;gK21oI(&dbGns*vpb!?ron|70{2_2i z7$SuXAv8z{Vu2jMcyJo51uwx4Ug%>WJ900z_04t4kd zhk1$r!yjjQZDdG{_>;h>5T9+^SFwPC^P;JR5B%ShzQ9&$Fb-NaI_vn-_ zyXCu%l)S)-0JVvtaKmU(g168*QC+}w3H16Pg;?FkcK6GQ-_~tZ^1Lst`rIWWPsqE> zS>4vDHjBWXY1uL9To2={p)LBAVCVk0ZdT6FP!JLFdakN7rKkOEQ95s=?1r`9zJor0 zO4Dk`a=a3;R+ru`$rH?0$e+n0Wu;xc^O@wmY>U(~<;gDxpXnrRGkdj7Bchl?x3``i z*0-l*O+2)|z42*gd7{mma_cHWH0Ufm^m;EM{Ko9aUehW({rU*||t!1-60tjJpuKruFJP|MDofSG?v_yy;23YloV89eQk{Reljn}23Ui@VNl681iA6xZ&( z6Pedj>ftL6b?a2mY>4)jA2_A@=WlWIgR^9rx?j6x_R#f+Rd19%N}g|U`)=c2xwSr3 z7bc%jE*kZ^xQaHtQ=7@?mWCnz(`d8I?6A8HZSRk{O8Vm-1=RJmcLY7R46KmlX>{xC z<0eDZOYWi7I|T_@mrU5wC7JZFvi^(6UPzM?kw(NA^b8$+^Zd_5)|xqgML2g#xFzGl`pO~es*g7f(ewFVo7(Q4to zYRuV&?eeZkT4EW%bvGC2c4%T%$CJB9sXH<9mg zv-W5m9!Sdlmb+Ob)3CaSLu%feJ4T-v&x=(k*N09PNA=5oja^#IcT@;NJP!mW@eCFA z9~y&`6*V>foXS!wp^H4#Zu91g94}Yf$cvp*8dYLXlbuJU&V0a9XGr)R51E#v%kosp zlj-wwg$-er<5yob)@rRKAYXZ6h!5^wEQcqDuN E1=A!t@c;k- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/angry_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/angry_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..2f93869dfa082d3591f66bc7eb4f9cd018a55e53 GIT binary patch literal 1567 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/awake_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/awake_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..8e1b2b8aa1b5fa9fe12788df44cfb206710f9848 GIT binary patch literal 1212 zcmZ?wbhEHb)L_tHI3mmd0+tLC5)zu4n#sw@*#cXuIo2-K+_{~xTAFroOL+s`#5*x50_)kx2PnGvW%@h1zXBZDx5 z4oEl184Rr79;o!CWX{W2wJs-{$>71c{6uaeUuM>(JC?EC&%F(}92a(V7^rbsJmq?j zt){STNr=c|G2w(`N*AXd%DMI-G`IOs$sVS~Cl#(AZg{=u?Y)y%8F(7qDl3!tsy*t; zv$On4xhHl;1)B*Zv{X({shs3cU{=~BRN1m*UaeE%bi+w&I|I`)7%bLp*)XLbbkd%Q zE2DjU+Y%V|u`=&8_Bj%Jl$$RyS~xDOynIhrT4-VoYsb73x2~EorkmZr=(V(T{$-}; zlhfY3jd@>lQfG_96oYRYUl~qgnc}u#!NFz@VXc@G8x}gtvM70}94J_Hw1ZPWD`bV> zK(Ix93BN?f_Z!+^(gX~#<+iKa_} z4viT`64zGvZg*`sIN?Z>e3)4|;{^H9vB`V#?nt|c_F9qYZE7sn}J&zNt2bH^3k z6`|`Hm_B~a<6$p5z3hds%lhL76#9!^XbT8T;}gx@fy)d7?$z@W3{Fe7KXFn)$%wT9pVd$IfR5+!y-)~8ET1NkdS!<)?I5uwBye>3lVT&1a)SP&p`lK}n zt#`W}?QcDyw>7bfwXeDIK-ytYy4ZAHXMx{R1}3xSHZO+K+(6~0mmdT_%R6ZB<=rbo v@88k?{xdLh$#{Sh2)9tgi3tY|wh4#}^>_p-y0&xvZ3Tw`>uAbAPZ`z#qm1Ko literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/blank_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/blank_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..09173af4d4a080622464a7d71ec025687ceb4b9e GIT binary patch literal 1489 zcmc&z{V&~D7(X{`v7qzPqHYtB-f&$d9u z#)a?A)eOCltZ3N$4^!YF!C#BJ*^N;##1QmHJ)oiWN86^u%S2g;07&Z*#3 zDzwne1m%JXL8ZbH!%R{xsgP7Eq#**VK@+?{1e>u6*Z{*c+EK>?4rfd-CKZKPj63H{ za3&SO;DIt1Ob8|w{h)? zj^JD>Rze{b<1Pf3in9<59w-aRrD8Nm`6F;7j7X6oLPJW31v$WYI1OvzCF}r848so? z0L739(!c_1&;&0K!Dc`M8(^45JL-7AQGSX4!-u!DKNy>8ijGQ(4Gw(6Mgh}}z~vfCBk-F&yg&Q+H+*8SzZGfuk`F2`H0$Cl3rAL$=+YEtWKw-r1( zJH0z3ztB*v$(YuJm?joG^ZcgG!KUG*w#IRnh4F^roQbFHziAF6>7#Z~^TnU=svr6r)Z<L)WL9mxa5zWmJ>--WUKA(Q8r zw*A-NSDYl&@R^6mm#fY6JTa%AQ7aDr{Oy=OE zgGal1JjhC1ftxX^Vj}JFfv<)Q4=$$G-O#irUn{NG)upFj+Vx}jFB7i1LwsbhYQ)z1 zIJUP~r9PgyCoki6(fy?t6EgvGcN`8~tzQqj>DN{GdjIhHhnCF#%AhnyU5z$mp!8YQ zRQ!8wqm9jhZyi_H7Ejm3&XhmcsM?lyrZw%O%CEoh$TCNm6FiRv{jvU&{ke$VaF-6X z{)Y<CISp9Saa)xxR4LHsjb)h?fc fvpG?RHEqp1Yy#JE%E^9h?kN{T$+A(UB9Z?BBD#P@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/bored_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/bored_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..e4af0f52710931e84f37288d325d6a30fa991add GIT binary patch literal 1516 zcmc&z{ZG|Z7(WQ)4a5nG@+Ryi7m1f99L5b~OkPEW8zAyBY6Zc8?2029fzAc;6691s zB+eiLQ$d&@ zTo56MRIsQdOcE}MkVGoblmH2%=tU8?wZkaolnP3vvKV*9C}&hKDit0mGfp|Df>Wu` zLN^nX3n~Pa3QG(#Nx7s#QmK%J2(SiC@B$HR#wuU~4AW>w9S=C1F~OKr6k;*%oHN0h zR0M+u%3LrZm{jzG7P`4)LNck?0k>ce{D1*a42jSL5nv6P-~}Ss3}|2j4AW>w9S=By zbE#Mfg;!!+7a#{-U3GJ};+h{d=|B|_wnz>zQ_MTQ6sDIpf*0OR2_tc91b11vENKVSe9 zLn2563#>sCyg&q-0S#<`VH)kI;{iwcCH@Z|YH6v9NH`c45*y+B$}UqAP*6WNdoc*# zUTbvL{w75A4>3_WMfEh_C{bU|1mXQxP?bzQKWoR8cy~Xg(Y=w{7Upv`6lzVku z>UfDumTA;$Xe}r(7UzChU!fFrn2L;f84n^I(y2(^W{gO z`lGX#8@uYJyFM+f9IDP6UV2lTQkH(b{K(@Bea=Wtp4YZsab`5s`qt%opRB7@Ef4QD z6fDhXJ#@RxEWD2`rWacE_0{+O9v2%|`Q%E9&q7kB!}^^Yy;8d;I!j{s%}+kgTJ8ul zUEfq|x9T`=lbiUSxh8RSe7MrczVsY0?9qFyJF(Od_hZApJpaw5E(OaCi_Ydnm5!PR z11|oagC>qe&YH5x*Zd>gjip->qpED}SbbWlL;j_-z0T#&)D4hqB}=Jr>YaqUv%yA*zv@# zy{>+y$1C7kuEm9{r0WwOebuj8Ss3e#`XPAxUr((%K1(_oIF@ha_|~oIr!^06KmIi( z*7|4W#_SAJRg=Tl`Yqqjh%F9p8T!+9!rMK4Y*&1fin6<(=Y+AKlfE5E`uxoDb~@9h z8!pJaui2W^rRxgToOz?^#1{uzb>3%3?|*;f!J?)(#&ly!;=STWX+E|eJYShN)=htt zx?w0-JwUb{NcL7O2W|iMPQ*%0QKxP8T(QdS(%h*H{`cle98=WB(nP-~W0{Rdg|XZ+ Nr(RteVs1uu{|jSngKq!; literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/cold_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/cold_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..f8955844eec3d6b6e8575f46a3b19ad719c5f4b5 GIT binary patch literal 1663 zcmc&zYfzL`7(S#hyCRORgp%OM{idjU6eJXt9cY(WTyWi3By&k84Wdqz5bEfdIVCV?M?)uZnUGPzG|LIiOIFkA;rrc>{&jxr&N=VAfR4P1BW}I?P1*cM> zg>EJ&7gPu;6_yxgl5$Cfq*5Ub5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD8ypiIcI`1 zsR#xSl(}F+FsbMVEp&6qgk(~&18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY z=Tfl}3b7b>A-GhWg<$YNSx7DwqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR z1~jk%hH12;jt3m6WCkmt5Q}k_N`%NCfg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`I zhD4AC7FdHOc!3Bu0~*)>!!+7a#{-V?OZ*=`{G@wIf_bTKu_-|tIct;)DEPe?t#-xt z^btBEe-onmo4BZa^sUoKzN*bTv%A%{IDeG?IMe;s?1b%_fV30ck8Fw6zB*0E(b-$O z?Uu2@zx3F0%d10Nn#{!xopI0f6 zol8ya^*d!~uH*iDPR@?XuDSVTSikAG)>KJD21>2oL)jez`cH)E*D0MH$w8T=Z_hp2 zz0Oh-Im3JIsWs00!C<$HCuM#0L1$7A)})7ascheF*gRZ4C9l(O(sPe~|EN6YLft@$ zShVHAq{hZo(XN$$WiLH+Q=f4qbLNSTeQo<6cb3fj{gN~GUWMHB=g_mk!_8HNyHC$n z7pS^6G$!@r1@CuJJ-l1-L1~QrakD&)q#Zz=Kd6@GgyX(>XvwU2GyBa zUsLV;)y1BBS9*DlS0ZyA^RJQJTJ&Ec`$!#Ir1!QBUaW9N7S$X}%YA*TB`dBarv0AX zJ^o`mNd{ZFP}fIg{JX21)BF%a~#Xc(_FP{D~FG~Q9mie?PjGm*w~PI!N0>> z>t{T=pd@j-Y5iyV{B`|JPcGf~G~G~O9(``!#X9ZMj?crp5?k61M1SaeXPMiB*4zvG z!XnmWRyn5_cG=?Ml7%_G<4B8t@Scqcc~=YctIk#!qaJphpX%Pb!&rOZf_jHNsjBBu z;Hcv>vP%ZtGKRap=4Tr+Jom4^Qr$k0&ieS(te<<5_m*jPI?eZbFV;s#XIf9r%L zd_M2Z!nMz;+I0<;mp2#Z3gexwz~PtgCvG$@F6?`&`*!`__cu?l8;cu!^%J5Z=Cl6N zvDYozw$%FE(p2p9nC!6lc-W2Ps~z(u$A=%{emxCa}pMg l>oe_&w>pMulTw}r>^5mv=hT^#Vsh(^uN=F($i;=k{sYn%xU#FhRH= zLJ+B7QAwC2ToNIPRG=vV5=POBB5o6hQOYS5luBhW?u=2+s9;noJWytwa!v)OQlW)z zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}rf-|WI z1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+MEa0KU4 zu@VZg7?j`B72%>dW?wu!hM-O^+$wy^q_Ue%|VR z&|Mdp>*bn0{>(jo|1?`qhXMzuj=1=P7%25ijDJ*q^X96sXZqm6p_C_uIo*qckFBrU_V?+hyxl(FxD9m= zc-Z-2f8vgNKf2`CWtH7bvI?nG&+o}PJW{NRTQyR&gR9ClH!VkxdY#>VWN__CP5!M7 z(+y*5OL=@${a$C!px<|#*jtuVkhkbXU%IBnan^iY{S7zWlk-o9^CL|?$$7Ig8o~~O4qdv5b@V-e3*PD<&XVt;4r z!ZR9&Ywu6`mJRQ+@IEzMG(~rRxY#CleNTz~>XGzP$K_q=1{ZDbaf7YO!G@4`{sr~z Bwfq18 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/dirty_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/dirty_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..4dfec36488b950d87e6405e17a92b3cf028be247 GIT binary patch literal 1816 zcmc&zX;YI|6ux0maH(u@6i`{hl2B22fvOb+F$swVK{ipbB!yd+)S?v^tV&a)&^nPkOE zr6=-4f1>HbAcPSj2vLMs?#?g>Gl(#VGKl5M3`Q6uf)T}t<+>SyFhPVMN)XEpGZbNp z2t|}4mcwFLgjqybL|Mdg&Oa!fpCsh9L|?8HVK+!yRLWV1{Cb<#<3D6NV6m z5{BhyK{uuhp$w%A%dv!E%rb;!D9f-MX%GRdfhO<*BCr`&0XBfaG_*q<9^ep+DaI_P z5EjFo5KIYXIl;gK%7kJ{G0W)(TF^~cOj*owc7R)85BLEFfMSpcnm`1w2AaSNh`?rm z25bO>X=sN!JiwuZu$+~k5EjFoQo?f1f?(hQWy%tkGa6!n9Kd*R8mt8`!8~va>;XT( z08k7Pfiz$NYoH0dfCy{`Xut+An1*(!!vh?a%M7dpg|HazEEgf<4}n9%5GiB`p+QOz z3*-RCgVSIwcnNj@OBe<}zyMGT5`i>e0c)TMynqO7257(rFqnpRsKWys?w9yKd^oeS z!^BaMA;IBdU+?9nJfPtG#>{dxe7`?UXZmk~EZ!lWg=1*5uIspkt!VrA%@x6Fs}|=u zqsyJeNdHs9?#t^`x>KgXqC_{FPN_z3Fgxb{!z{a8_t_<@_n*GsrS(!6TTDK$6rZzb zk%?;h>{g#!h@{ZQE8}JNUE~D^(L`O|++|xM^>k9B$_^X88Gd7H?zeqfU-e0avHN`c zy~V0-T|&I)=H$nfI&Dor>H+_)gO#PNNn?^?94>Z_am#6cnO4ASy;CTc+IV`M{95^< zK(W%tt2}kd%l5X3k^DU(shL9kmuh2I+xXtLFsnzswSwkdC)!PfcKozUXJ+Oq?#d^7 zf*c-)eA4m7E4C+VAn|BW$cW~8m%B{*tY^Kwq%eAK+YO zN&2mRtla$E&6u-er=L-9G<0Y8gAjd@uJp*|63=lT;IO}WKH`nS z$Wus;DvxkA@B{#c9tP`a_7X*`z zZEq$MRDnmPyjKkmIDFIJ9DmFG0NJCiTgxw5IGple(!23l{!-Z-JD=CxSMP3r_lGe` zmSJM;^^yAUfy-+&JJl11>xI=*){##R%}_u8D%P9VYMbz#IN(Xz+6w>sX$Sun7blho z&3oeJE28tZq{}2Ude1~~{@(q8S&D73PjSECj_h^sp%R&mGS>f}60NZOx*>-rxFN_* z%DmpCJo4Db!z$p2@VDUteZ$k7Fx`TYhx>xf*TpYde$(2*$<@47>!3;Zv?&oOKOWuW zo>D!uI5kDP#VO`W=}^4oP+d~qyjKq@j1Fcpp&Dzn#!gw?0R N&ho3uW|*N5{{_$a1{44Q literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/drunk_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/drunk_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..b853944bb2cbabb99b7f8100e107950b3cda57ac GIT binary patch literal 1695 zcmc&z>r>QK7(NEb#lg5$D58LXERdu8bdeDWM6R(r#4a1Dkh`#F2E$b3n%bbi2BUy3 zD0@(9DP2gL5tPVFIx3*T97+ug%d)(qWixm|XPQnAzpwoPoe#Tn&ilU4`&@RDQWBR$ z=|e~enIMx#B7_pc2;qbX`7TL>N`y&-OGLhN+O4khqY9Od2A<8Z^NRM6emFfDJHAqaAfT;4n%#r9xJS#key@ zIio@r3?3*mPC2JS)(=|fW`c4-g=`1hf<5p920$?+LK8%QHE4nth+s3IfekQBqaAfT z;Bdx-Y$X(8G47l*Av+7f;DIt1Ovpwf7UTfq;WVs;moN`*!5;Vl1E3fZK^jlbiqaEoB=FeLGxI^i9bdzUZ&XV!(ezvd;6!+F`n0|rvB-wZe8kowJ2W86p_iL zD+{8$S`a+B(Ap0&Dx==_IPEg1=rY*Wv;@7p>Z&=Mt6~ARW=nR8 zW6tBR6a!wr_G~^9tkdzKefy$}hRwH?^Lbz4gvVT3^f;rv{KSGOc;Ky62<1#_L9Z?F+r# z%#g&)PljCT*HKT?B4!@QEoyRmO&L16xHfl*vP$J#axiFkr_#YRhZH7w88d!dR(>T( zSF-0|YSxG48F9KQh0T&Pd(l0X`%&$^mi$8l)MC8wUV5yYqr-o5befgii5y>f=C}G% zr+ztc@r~$9bYB&p;o+WRS25%o92piKp!Hsu8&_bq#%-EAP;sfcBF*DlQ(b+k(H3}m zOIAj3TvMn@VOOmq`6}BYJ<-zUeO~oPE#=hvIX{Sp3!s^ZY4gEct3-l-ZJnoN-b><~?869qK2|aEx zG-OXRU#;AI`(l?`k!q`H&RW=zIH&$^#lTQr!6H?)jd^Py?Xqv59zJGKuhAsFUE$&o z8e2=+#tpYtb}kbMncwt!j5vJm{#i_GSxBT~a(DJGowfpv z)&4ElSgyRpb2O&b9gVk)X)lc3!>UU6drkS}4i7F@sFsbi1fEgs9o?$kxWXDS`^4}S zAM@%9-kGI)zHUw)?fA{)vsbV4*RN>n@l=L&-r48lqV_tQ6x31dp>&M3Tuv@5UdTHeaEclT=M58Q1|`}n%CDRHVjS^6&x?aiG4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/emberassed_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/emberassed_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..da333df59e59bdc43d545e38e53c1dd4e920d755 GIT binary patch literal 2367 zcmeHH=~Giz6u+@R0hO{Z;;3MX1W}L|4H%>ZSt1Aq2+HDyz%5z?suZoIQz~m&C9D^8 z8Zp6OsbeTo24w~@AmXzFxHO7`WgAh^v5Ff^`+9i(0rgAUFTEd6vNVjZcI~zrf8aCSe9@ZGZbMcnxPn$G>8D!KofWY5tt0402{#IHnc+>4qy?C zX^a_GAq<8+A($qZVFd#ZC=(jfG-g=+KnuDFgJ}jctR3JM*aLom0iYNpf+i3Ftbr!* z0wOROpaC1e;5M{F9S&g8gfOg?pb!Sbo~8-IItzk<2b5`sFs#uK3*-RCgVSIwcnRi# zTVN0P0S16#kO-s!3s?h9-~~irGC%`1fWd8OhdLaB)cVb8D;LjDjqBn**4 zh7cO01hGI4U_3Yt)`FK{2e5?8;0G80ia{cf1}tC=G=Ucofyn?3*Z>B%p&jaQ0E_)4 z{s$j+%={2PY4}Ew#LsQD>jxa5VE0zXz!Scm=jhBm6Qutq;^;3HpOat8(l>M3-h1w( zD9Kpuar{mHLI=T0ZkQrJ*p#1`%(dxnQ`@auzqFFbe47jXOH&J4J$w0cA>AJO?2vKC{=WO?&*YvqY%b7br1E?>moeaYL~6tn9Hi3>5fH7af@pPcH} zS#mPIvpQ$dvxl$R2TxnYhFOTTi+>Au$lzIY`q^-F%f3ynP)dDWLKBB_tg&h&cX9gU zNZzvCwlWKDRbqFZLxb2p@#Tez~oTI&6NzF*EWULJT{tgiPvs&(6Qq1U+1RvWZuM6La{CY4EHg_d(7?RRLFv{B-=vgB;<5u>z6L^7u*!dj zV1Ku1kbkLvaLg;&dd@t7=C)5@#hrBi9h>XEfrV!6wtD%igv}EpVKu%{qqX)Ef=K@t zobDF4G+xT^A@2Q|1HxO44R7SPb^4w@D8HB0PIR6xT=OdJhoI@GwMvdkrhQ$_9jmOc z5*KqauXAK=BinZ9F3B$D5yf=RH`Z(ND-WB;hIa+*^{5;$#80H5;f5#0Hwv6vCr1kn zqU^?ssAln4F<+KFR^suf_f(Nv4L^fH0=x5`$ zlJw0r`u$ch$SmEv<5KUP@jAzhkQPTyL8SV|swwBjpFC8ZrjZJ*$@7bm!0u(jK!!n1w^_uZ*n{3UBPV;APf~2pGLg|t_Wf*k-PBNjZ_%{e zw&)M5fuI#L4WsX(aP4s%E8-`|cNe=y+r^c54!_w`>fNQUC|#>(@h%VDzxzx2|7rXy HPeb?@{;32` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/envious_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/envious_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..466a484f3037414e7b9c08170243d92d4231fc63 GIT binary patch literal 2387 zcmeHHSx{3~7(N*wW21Bc4U1F}2uQ*vxd=o9NJxNKkdTG4RYA-(T9md5V%u>nN{q5d zB0+BvhbTe9Vu@n4IL>GdRNz*ER*Kcy4k%EoGsWW8#oM3TnZDMSPG5Q+k~!!9&-Z^z zPLicbF@l016oj6k*@Yp5BSauXB1F-93`01E2n>-JqUbV)BOFHrjz}C)bT>vIoInJD zNCHvxWsF2Pi3k#rB%)|6j6yht2nvxDqG)Ig0TNt=UMRwDcHtOCU>J#E6g?RBIF1oG zM&cMn^MEo=U<84Y1V+)cpc^MKg2YG?qiB|J8K*FU!bl3EXwo18SOZPq1w>#ni~?)` zgWJ#!bvS@U;5don6s-^j!=4~;lE5iiFz|pfLEFRNlN3(Tc7R)85BLEF zfMSpcnm`1w2AaSNh`?lk25bO>+t3bmIDkbG1Vvj33SltpNs^#wXF)LVfHFxD6m2xb z0y%*3;51kZUV?ex7T5!RfB~QwBm!x`0@gqicmWZZ4A6iLU~n7Sp$-SIC^|E+5){H< z*i&?bkUsKnDf$4D5&r<=d1@kw*d z-PvRw+%p;{!pw4mcSAHoOnPl=$xtU2i@MJ%%zW7z^{H-8G?rB4o|dqO#qv(KtTnpM zl_ty6Y7EV7Htm92s8xFL&bF0J$48*_$e$;7%*dMx%InH^HP)2w8$EVeE)fW) z&GR;YqMJKQ^vwreQl}|M<@q?K_>p@;)*i20S*MpYK zg0a2XWZLTJ;O@YgviTi-)?%Y;!*BSMB0B#|?Uu^AEbHe>Zq|3abCyfW(k9DSbNPO6 zDQc~6UzsR{R0OIuGdhcs>&fhLohu1BaX{WQrD@Ss*DO|Pg+mt~ddU{YavWDG8H2Sv zxq0GcfK!Um+3u0s{@`L;9amPXV)z|f+SxnOp1-mi;xZ`nxx5b*2o zyh!!Ht?iw~TBdtlgVYo|()dTlIZ@Gi?jgBmxkdKPI_`^e_5705$NG<)MgsO{v+5UI z+Pg_$9A@E?Q?D7@&&oE99SAmD9jgp6IF46E45XYm5R|jP<<$cCm!8Fd z>VE1;o9Mb;dFTYk!t;L|X|6wVyDLP{^B$|D)6$b}bPb*u@v|TH_~mqO%kjE4`RF{) z+FKrqo9%IF#&Sj>yGo>;cUh)(NaD&2Q+3Y=UAzNhD_EiO#-5U&gxmSd-lt2e{B9TI zd>Xc0EAtF(UbOy;F?or` zq*2GN{H!A}x*G})!H8Q_fZaDUFHBXIk+dqITa=>avWMRcU$OM>XVE%dBiy>7_u#4= iQ(>+6Wm%yXk8vo+cSotT}n(xj4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/exhausted_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/exhausted_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..b1a4aaaf9a1ba161ed3825239db175af2760152f GIT binary patch literal 1577 zcmc&z>r>QK7(N1S2$8S|Nz064LI^E`dsMvOjw}~JSTc7tg$B8KA_E&mG0S2Q1)?MZ zc7_9Liz0Fn1!qaiB83$lILrWwm&!D)8MLe!#}-lR^zi!w`r7%hJLkOb`@GL(cV$A{ z;w2fuB$$ko$wLWYgm6LxAyT>tCPN|?&DvNPvjB-W=qf+64GUJqUDmax2 zEp#(Mxu8N&sj$Q_laxy;B$WzjhyZKQ1TPT5W~>4>z%Y$=)bW7B854|2MIjdB&N&mD zNkuStpv(mmf=NX`XrY@+CM1)J9dHZwzz-Mz#gGV15CPVp30@$A&430rz%Y$=)bW5L zIG2i*P>9923&Ex0EChoG%0hCf7>!tv1B{2$uohmzJh%mW;0FwVVn_sOV1YGgf)|Kj zGoXPDFifKzbv)omB{NtFg;1+4lo{0!&-O=JHQgd@B;=w zF(iUCu)rEL!3#vN8PLE67^cyVIv#M8U*iAp5g^@@W6h@MsMWE$uyE%opb#+OGA$C{ zuTIjL{F@Nhf5;S9|M(8;`C?b^kT)-NG(_ckb}l*ac*r9tB6RMW#xkRNLC%)BenV$E z0~RfvW#LsZry6@IW*NOwcUg}P6kpdH=+QM*n)-+-F~Tpu>Ge&~?;31pOh>zVFm{YM+F*0hvu{kSN|p)!qH*DwDgP*wX% z^SNWiZliwV3+HbvoWEt!z0PLyq5ZU9@0YK&A8WWdbmQB~U|X;CJ*SERbysqWKG5PZ zm~wigCQ@szu;1@9KD-~+Yw*~$Zmhg=+tknx-yhzdnEU6=?7FrE=Psz%`M3;!;Arq2 zPJFJv>Gq!I7meL6_KXYudGCxZ*%$WBObN&+@lSi4UOL<0dbrd_<>RUNJoP_)j`!5` zmQME|m5aR&#}=t{PV0+|cVj_A6T%g$sF%J7F8c>oR@#Org5kt*23pF;`R-+xgXSP-SXPZtsy7B zwEM303vRcT^OQC<8K}>@wQ4j`49<=4Kd<}ioz~;2?e@mHwO7Z3($Bl*ZC)<6o&2G{ zzuYUd!26*oqV&bz4t`^)efvaJq{i-0**4_npFXt5Bb8peI4dt%*R^x%MpNLbr<)%v z)MjMbB3}OD>_pJTuM7S*B<_Ag{kk2`x@MP#B$Zt*oTHkZk=~YZ#Az$(yQDU0qmJFJh;)qI{VZfdz%P~2 bPSeQe@#-5{RY@UVWmg+sx|g+rkY)b@l~|sY literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/full_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/full_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..5220d1f18e8ef6e843688f18033c5e1a151a7644 GIT binary patch literal 1739 zcmc&zYfzL`7(N6Di#VZjNevYQPyRHgzE1i}O&3WQ7Dlo5du#)!xWmxifG z1d%Y2h$7(<7Ue|XgmEHr!X;=*fP_)>qKMnr5h!Jpij;C`G46sunLtH>a)}4Z0;7yk zkx?$uLbo7NCQ?zPTw;k~fm6n*$SIddLj+iZCU}7eHe(gA0fuR`qmBn0CJ3S+a7iH+ z4>-~<@qhU6FW4cl{_jU($N7F z{9ZZ9*5NyRjLz8Kgt-1q99-W_XtiEH=sGzx>+9CW8)Y7|5|1aeos#eG&4}^aKcP=v zGKKC7H5*f8M`yU?987E0hHU9HW$!runzqx+mdMh^z5g_2L8`Uni}EhdVC|Wr&^}pn zK*KU?dRCT0rz!QM;w{~%)6X@@6}>;1MxWHI%~W?>z9S>v(`<`Z#jaUXVBhjEl~o%m z%e#&QsJp8&T5|74v?Z~J@4EeFZd`w1d0T$vo*lE>zNwftXZVWg*EHJ+_Rd$~%JXrb zZCmQnU*19=SJuWRN9opOS0`zPa;{|9hx7Ehy?)Ul&q>fH))9Mnc5!d6-rPyCa->cVj$^{1N$3^8WXVPrRM=akzK3r!TFm!Bg zj}IGuUY(l%?0S!zp|YTNySPjfBOBQtUAJ1Li?Rgm?4CPw#khb&*3}2{U)(OeVOTgl zF0lVe=G%ey24sayUndL7RoX4713h!Il(m1k{7~lc=b(>oqLbGQUuBHn?PJxZ!s4pH z?umi2v>Y~3;j%PSE%$w9R@H^sG=pr5?QBqd#)TnUz3y7b)B2Du-Ry>)j~)zKW;i>I zW$OGNnfk@*!>k{)mv%ME_j~wBQ5q|Je8!^G{2Qevp(HHH9CgM$FxirKBIfqXb2FpW zR+G8;Y-P|#Rfdt`w4R!NHX9qktXQgcdiOK;@85I48x zbJmy#`#Mb}ISKl_0CvFJGxT9=zERuxWSp9`xZkb1YTWAo_~<;NGNN+r>H1UK4o~gU zr~j@|n!Rj$YZkSy(AT{lZ*qUH`c}7Fjb?PzyYJ%3?5&$-{gT^ytJWoQgY(5Et<13_ zebe}ug6)cOAEo`$)cN7T-|jOnQY5;JTz3pe{L*qNdAND=ABrWH8y&TW41J;)h3xCQW;mHj+@uxkoc+HlXyNbt7?PtLI&$JAL^t`2QB(&?alh_>)M3l VhHFNlp~z-zYS>ya#eFbq7@4X82Vb=a2ocnP z2nWy-qKu*yLPbOvM~8qSR|YBAIN>2$DN7}w!-gr0Fh&F;8Y70yrU=3W5rSxf z7`B+A5vCEL5lth8#iAI58AKRFGl*fKDFjGR3b_!3+w{Q{MJS4A@ z%LBrgP=ru4p%|7HWMi5lG)2=C!?J{8%us}(Xog}~(jWp@15MxsM4&UY0&D<-YDkAT zJis9s(-g&HxSA00z~N4sm#Z!>}_0D?uSNhC9QK5atg9 zhY7<-VTLd?m=cTy<^aZn(_k%l33dQWCC8a*7EIHb{+S?)zmSQAOH@<0jymQMdHM9tc*2hs zB<2r`NqEy-`=1D!c*|7^Cp@^fZwShX}pWt6tOP>;3aN7S22Sfui@`w3er3QD2i3w|W+z0GVzSX4ZJY+N9RWIaJ>kACSSJcYu54-Xl zHKBVt?>>q==&m906Wu@ce8Vp%9qHf_5>32qL>zE+Yk=wXIR~q1V z!q;W~r4F9;T7mtAl;_IpySG%C9}t=4oGa_=lq779|El6wv!mq;`dfI-T+QIAb-^bS z)QTC`PCv-C3Z8rrk+9N7lV`PBKAz{Da@M`TG1FoE;JgB#x)twD{_sw38xK?1IJ@ex zSzTw*^iI30=dJX!4@osW@P4OlqHWW=)UHozBsiutO2tW9Cde7!>Z)e&_75(#HAc(p z%E z^e?bt>h7I;7gIzdUBZ{%I@#`RzYX3h4@kRiQ_gug6fF4iXzZ+w?b#I*SdnAIPJ1}c zbK7#=3vleylH0uwBAK7bvITlnKEB>w{wiIr*BEyU-!Z1I5!W8uDO$d_^~ovyj?vGD zPki#UDDs?8;F7Ex8jWgCy_(|GVd(zFb+ebK&9=IGu|{0yW=QJTH0l>W)fM#Z;>40t z)5mJd%;F#2qD|y_^=g~PyT*2L_!9f=|Jdp5NzI{v{99>-yxikyMLrpYbwzIR4mRw+ Oh*{|WYyI!8b;#e0l*h^d literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/happy_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/happy_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..6c8936ab27bcc18ec02012c95f5f89d5839190be GIT binary patch literal 2222 zcmeHH=}**G6n(T{P;3QM)Q$ux1G2e5GD{oAY34# z)J!>HoCut7PDBZdiiC+o5D6EFC_z&KB($OyNkrp^Q7TZ%DHWx`h#8{-qnuGu;(;_1 zs31@-P*I|VYR0L+Dd$v_SfZJUR1hf_sVI?#2(SiC@B$G`#wcI|4BaS49v3(QW1KNj zQi#Eb1%YvaiIQOOKw998b0$jqK?~J_$hgQv$qu*$d*BBQfMQ65CWruQ&;&0K!DK)K z8(`>0Ir6x`;esGaRze{LBj#KXC1)WRJdoz1AWBAKE!YE$htseYUcx-M1$*EJ41i)t z1ZiM_HE4nth+s0HfekQpqa1l$;E2-BU?mh{Fk(?!A@+}jW5ZY}c8H~6OIQo`0OR2_ ztc91b11!-DKVSe9Ln2563#>sCyg&q#0S#<`p&RAM;{r!|iT}Zey=V~?qE-b3C_+5u zFMQhs6zqRDo#=;e_i;MoKNDj9CowUfy}YsFr)=}7t{>lMtPIdt>U_#ybiL!`?Iu@N z=S5n3Ca210b+zd1y?pITg_7W=>Z^rzkyf!gDzrDVd;9~bR#_q|^EL_Qvp%o+FexZ4 z@Is49>!FBBI(uOz=?m4^LLZ0J<9c^TigL)9xAK*B z*|+Lib(8ma?54jfxqY^xJ+ckQsNE`d{g}=;$?l{oFs)?->(W zg{5tJ3=429J(PLQvCfz^*=yLCZ5is^n=>sYp*J@=IInlFjqi=#eN%Sz*yjeAnZA+B zZTl=8R+KN-oes(B@kqRM!?H}~UGlD`Kd;NdGdV4=P#)7I_f&P>Z&>frrS(whAJiT1 zu)f!EOdsF*xPC+)q3{lvPPN5DZ3pcNT!VIwIq8aAPtG4(+;RJ6eRM)!P7IG+;q7+8 zY3z%s4eh$LQme98Y*^(Te|>LC{*g7h@8=kfHf(Bk;flzitQ9UE@2^%Z)Wx+8Zfjb% zZjLNGBO<~jnfYDf0_KULOv5`*SRks&;BgP--i14a5< zcGa(0iOkoLUG%mXEy&33G2Jt9V^mUgVBC_Cn&Pb%-Tjiw34zh-CLfuLzn-hx7@jEAfi?u*j=nXTqUn}br|*39zA}q(cS0bXOl`dtiIHF;7YUk z*ub^gjrMm_!W(89S{HmZfmzIy#cEQ6j?UXL>K-qoYD3%Ai=3m2(w?;zMA(c3pYD3_ z()ID3^!AFk656+D4$K=obZ%+YeIMF)>&ljhvfGc;XFTrc`&v9ZPmL2Dx&mKwI-9sig z8~2#nBpWl$o$8FC(VoK<)6M;z6SB>sk}ET9lr8ZJ6O-`=Z1#756aPQpfBJxz`~~rB B!?^$e literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/horny_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/horny_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..905dbaa5a735122cd3a8e3d1c1353d0a0aa89eef GIT binary patch literal 1657 zcmc&z=}**07#M;#A1oH4M;#A1 zf^(@@358gUyAWI|&O$JFpe!VpiqVJ#Ily>04Qt^g%!6C72Y$c+D27Ck1{PR@CU}7e zHUk>i0K+ueQO5(0R5F8=P>992OC>_&kHC>IB1MJ>4JjcOrD$1CFE5tP{5arP4r-?^s3X6v~v9(ms0TYF~e8^VJY-*QZ7@*<8~1y$eP z+vBARjGkj^vCq;cUFkT{QcQL?`G=;@IhoKw;!Nv{=2GpT(@V3!=UAw*-~QdM16zF- z*7vwI=)&4OO?S`5Yg{6%JaF!yndnklO0}WEv$Cum7JK`R;m!3&)i&;3S=8OtS?98B zYVYwq!_B)=8rz%JcIK8iE==`}X)FD4XZ?QtXWao+*NO(__@8=o;c=Gn;Eaprz?#Sd zO$%)14}*>ujcpssIdfJ`svq$>TV7di?S_ZOlJw`NQUK?4(jV&Eo96ii%!@EtSAFIF=Jc`JCcnmp>bO-ea!iGshxfO~s=}PjOEhboEoIqOXKRLf(Ak#kIcdZaX9&=?-f?ps zkI60iKVr(g)N4Jz#e0Rf#pAKnYl14z*xlLdrtuH3nVhS8<9BQ)y?tc} z8DnSaqswQ{C>U*x7azajsjgh-8+asof$eB;b4jt#gy$Cf1P^wGm6W>{_>4U{7~7e4 zJ1bpP+Unwx9aZykXpftI@0CjkH)*u~n|Cr#Z?5*cmRn>`88vrJeUNqLK#I?@l*tFP z+x;pGk@lTB%jx$rb>Y7_E_?2Ht>XLkzQex{of!!1bNSU6b!-UD40(O}h=~ubYmRQatPcI#VX952IC(hVG;wnO7nOaF-LI~+h0)FGrzfuOYUnZV zca)b0Yjf9DR9?Kg!WL3epWJsUB*@?$x%}t+s|}x;J^gNE_!kbHjA)#`-cmnZ|N5Ox z*Gf0J)eqMF(`C6|x3Op6m4Y&Dm$NlRKRSC+#*(o87K35Uh$VStmv%>XdB8|pvdWdb F{Vx~cyiNcB literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/hot_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/hot_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..0c8e31482698baba99dfcbe0459d7d507463ea02 GIT binary patch literal 1629 zcmc&zYfzL`7(NIX-sK`W;+n7;V1mdI1CbFV(8Vy8TSy?V>H)lzB4TJX-~|wu6%llg zXt4$e<^>p2B1eUU8Sv16mth@8$8@nU4I3Q|o$2)O{qJ|@$L^f-zVGusm)&KWaQ}d` zS;T|9CL@Ou!U*An2tuTCr<5>CI3h2loQ4Y=R|NKm0>Cf6NC#Q z1d$3Bm4r#cB@vQH1)35dVHCY6;x=*^rJPbhsZE17*f3=TvYi6xcd0~({1G@3Mx@9Pp&=#2f*fExoQAdV5_W(khT#VcfMQ4l zX<&ghXo44rU^AeB4KPfj9d$h5D8I!2;lovqTNxG`6B-f~=IiZaZ3POh!!~2o_?|mL zXXI}}?EWEEcGH(PR=4f8bDUubE;9uejaBUTd!b5D(Vk>yg<&6-|&Rc!Nuu&3@q9T1q%I9wK5 zW^YbdN(W-ftBfkcgPNnwC*s#t_s-dnIKM8kWX8oeYrAhdC7&~nin?XCKjfK_Y5jKN zldWe~ESl#P9;@k3?`Yk`9n_Dbo7xR~Z)Q!ol)I^^YlfHmwO3lNn3Ch#PwI{t&-J&N z&!)w=xZGWv^11IbzaL}D@0EOC;J9;l=IhUn^fp#D25}wf&JDYAyYu?_IY2{kk-akwWIRWzIE>FPd+S}d*Szo z`+Yh+9_bg{$ml5bPjp>lSbYC)-GShCyP5-jr>0I;^04*#?>w@mwv?r{7flWv|1>ou zHMDrr>`@P*w5dh=o#(qHnSWL1Pc%pC0tdC0kdo;USyvy2-*A~?_D_0H-&fmlTxF=v zww`dbswyB*?=!e{O_zFplV;8-QQ@*ty-VMF=jE(-OwJk3ezoIo&9YAL@_07wQ0Sh< zFcWtRe-#-$Gbs5)Y`}$$ak}idvoCowONolRUheltXHQ9mTjomN+5JOF%||Njcd8ry zTBBd!sE*HF^*l+}F>TVQg~_8*qNc#Sr`c(TWQzh!ts;wq1}{C&BXOYinrP9drn zRnuM8r?f8lsb;wDbcD`Socyl$AlcHp%w$Xpby>VFzsGQ8nPHqUXY%k ze!ghC?aZ7e-8Z2jx5#GSM6v? zF8n6je0sA}YG*-lZ`QWO=6joFFYLS%7n$Z5oPIy=Ncq0Oo|6t6mi*~%Df`Gd({gZW hqRCRe!mZ14=wpX50~Oi`O>Oyd)-Z6`+t!8z{tHeTzH$Hn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/hungry_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/hungry_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..29da1c5437bd58ee2b8304f5fae2fcf2dbff73db GIT binary patch literal 1672 zcmc&z=~L537+#g2U=a~P3m$_4a!9MJD3y+Ff`kT8qe2WSj6__uGU=d1M`=e4AV;AG z1n`GPIXqBQqEZ~SY87IOE*2C^I<11O)T4Bq4pK*|ZXbSsK)-fBB(wXz@AE!K60K2( zzmpO`0?2bRbSNQ=5Qz{@h>-7;5=Mzc38zHJWy%O+L}G+9BIIr=5hf8yB3vRu9;Tcy zP9#n^Cql-ef-pfOLAW47hNc8a7)39NxD6dfsYEHKRLF~QXN*dWaz=&B17#*rNupe$ zLZ*do#;L?9=TyinG0X&&1m%JXnKVRzHE4nth+s2T0UKbLMmy?wz>yf^j0ssG7UM2S zj7v<&g24l2i8IcbkoAKWx+TH5U_!P7ZowY-0Rx~I5}^qqz#25c3q-IP(7*;5rqPZ% z9&orM3E4_0#A4hzmxSyr1cL|4Tu4GT8nGY;7!RjmExd$za0~Xp4;TQ&kONCatMfi-A?7l>dppn(lAOrsrjJmAQ`#Q)*LM~q$^6~8=Esf`MKYu1Qipy2bu z!D$}8XAaRB`kRnZugS1clRmIkUCAEh9<=&;+`JU9P<(iwf>QmP+ z^Q8Q?VsFjJcfA@zOMGrrIK-;5|8_hSW1i`AwdgTB9JtPC9K(;EsfychJM ze2Q=89DcUG-K?FwvM;~wNT^n$^q{tZqYFRtzi57Su6&PXZ-}=cc&XX0H@sKxZ>vAP zXK$rZ7oMbFmY8*HvfGxIn&auMSDa7zmF=r&NVaaBe0kTtvEDy5q`JFD*uI`!SLqnO z?R9KlaMLDB!NqH=tE<(Lo@6MEADI?ys7~FI_R`<_Bv)ruUKw4e@4t5Q&wC3_e&N@* zNmmlo?CCtd$x!T4({s~nbFO!={X|yO{hDL9HU(F$Iier;Dy%Q`Qcz~WJ?Hvo?j7nP zQ`f@gsav1>MIVSvQf60pbo`Rnlk>z$JvCuX^^C7_6o&PMzAF@U-OF_P+ub|uyEa$) zcA8j>zfE&mWqzEP;=IPxnBTto_C^2uI(wbgJ$gdfK)iXjDWfC0Kjdga>EgMTRhIbV zmhQ5IF{a+~<+_&MiliM*tUT4xVJJ1lf2201vBp{*X?|n6SBn~9?RHhfw1kh{>m6s* z>E~?7t!*v|a59uSxKw&;9M!5h+fSz|(=t{DQ9sS^s>&H3oz7u}6Mq=7V3?iP{l#Ky zBK*#2&RYVT3+)Fy@5aQvsXG)Gv7^P|jwMtZvCXTjFp$`+#99`hESk7dYv;zc`XYPm zd_TkPfkz2%H(gb`_Mcew>$+RJ^A;(>>vc~P&r}uOami}!T${VywKgOsy}qm2^h%d= z;nt(Xw61CH*~K9PH%2V!2^t6poNep$_~X*Xe_o`tR-Cyz{5#KY8+;F*4@q$Gpz7`yFQ~oMV<=zFxQd^C=a3Jf1d0)qZ^0Fuy%-d-u<0Ynl!YzUWw| zD9(Hu_1pfPgNZ)lGKYKic8BfiJTk>(jI;IV4!@u75_=noml5doGIfJKE z)mx^iJhObWQl{U}=qzZw8f`o^q3c7}lQY^^%rAL%?-OP6gSB6VxfS?oV&^`7P^wi2 b9$MC){xG#nzo4METx;CeYw1upkcfW)_Q%g` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/hyper_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/hyper_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..5c7f2b40a6a2429206b229dc877f7b80cda27722 GIT binary patch literal 1515 zcmc&z>r>QK7(Prep-=%LhN~j6FkB3E53zEI;eL~ajYYiR1vE}HuFy=0WYi!lf})Tl z;Td$~s@M>@3>aO;CfNw|R6E2L6HN+(u{P2O(Nx%UdiebVee8VLopavzectD?o068i zC88jZ1d>0<(xHSfLO3CU5UJcLC5#eIiJ(L(Wy%O+gfk)-kxDn^gmJ<-5u8Y6mpXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)@Rcr^NjZjuIDL{Pbkk!Fpy2zL<1$Zt zZ&;$U^fw{S{}2b~HL2HHJ~uh92;Mz>t#z>4%`g2zs<|zxa$K|jlVP`JmA2tY<8+PH zFRZ8}zD~WI}U$ZYAwJJ2QCN=S*4R3wl&{!GB!;;__SO%8LG;gG@2u_E)~y) zT$wu=^IP`iFk&;#*4wu3e<|8y;#9rmTc3`2cKR=ug5*-6H4Oy1`M4VeP&@#-_v9&+32NmD{qgPgK?q65)RmC^8 zqaQv#aNax6^80HdWmn=x_p*s&&H-I_D_z6wOD^wtd!=V?QI*MyrA}6^E*;LVR;8C2 IVhM@*7vCm@3;+NC literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/indescribable_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/indescribable_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..785c1d131c345b00b581dc338647ab6c34e3451f GIT binary patch literal 624 zcmZ?wbhEHb)L_tHxWWJe*W$ik>U?st=V`vkro-p{GgvYtCnsxaYD!2*95`^`UdN4x ztxxVGy}y<7W|{V$E1i#T#(ulp`J{qp&FM4$!3N+X6#sMkxrPKgI|jHK=@~FH0@W)1 zWZ~3c;9}4L=>s`~f%WbJrM{HRc^RwL=Jm#GPe7M}jPAkFQC3tiE~ryX70!3(Tb+)>X{4 zZSf6_6`Fa~>2)2A0nJr?6FMBcdgB_V$InboEn!G-o78O_!`iu|vvhK#Phq_o#|mfL z!s(sikzA|#CYEjw3h^srSy#F(Io6$pEyZk4)2z4!44jv{lEW56-6}iM^DtZg=6$E6 z9>aa_-hcS`>GPMb-@gBFV*mYz{o7xL?`OF^CdfH9{@m1p)yFRoK7PHgK<9i(?qmnP zJ30n`J7xKwE)Hlol(^DkqKBI2(vFukY)h3JHb%B;l}6=-3QcUt+&RDSOr6qV-TN*| zWlgIm$_qWqo_(C5La;JUzc#lqw6nR{zCgRE&X2p^uU9y{#=cH~r*m4h(Zpn4zWLK< z8W)N1trcVtzPwT4e*ec=Ol}9p4 z?b$NzFI?P~ypVzOe#_|zLi|!6dthCZ2{{H*Vz}#oyup!}K9h_{~xTAFroOL+s`#5*x50_)kx2PnGvW%@h1zX5rZ&; z4oEl184RpnAE@-DWX{W2wJwKikAwDPheYm=cdl_1J+~6&pO_%haPabm85$2JX*l%H zXt*)KbHEt-K)k+(mJTqp< zsMsU?=H?Z(uNJxbOpA?@^b#B-JvJ;j*vuiU6?0-kq7ajSvQU7=Mx`UoV#Z2mDlR5Y z5&(w;t2t^&{6mDq>wN_^OePB38y0eZoBNF8$hzmojG~-vjS(`klR25!dopPVc(5s- znsRkb$6K*U5eEAVX7O>Wc2Bm_PquXlG7P@Ch|F#bVoA?&EgbX#4u-`o@KXyDPNl@H}5L_H5?2!+#7ec*TzL~Oq?)r z4r6c}+rg*?&q-{|ol_D6;%B!_HcY6>pS|*u*6n~AwmFk7W=0mUF=koq-uFObN%X3n z?>}bpuos?C`d;(otbl=vAa4`vpS7z5`xK|P3n+WdxzW^cv|C&;=}yN+j^q8ZwoO|+ NHZD0iNfDSntO2wX`C|Y8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/loved_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/loved_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..b66eb0db237bbc13e67ee3c64fe1f549265dd987 GIT binary patch literal 1703 zcmc&zYfzL`7(Ocsh+rv7u7ZiM2%5J&fhgq6VxS<4++xhjDB_-gA#qg_%|Sve z2em+8lM-}ANttK{1M+e(P%sdLQ4y_ls7Yin>-6x=^uK?dAG>qT`@YZnTy~cS26!)y zb|>y+h>RRc2qT0OA_$Snol?Rm;gkqUq*A7gFh)2df)S~7Q%)EsoD;!`REDV_Ob{-J z5JW0iR1zi$mqbV+6=+I;gi-XOh}+0vlyXW1rBYdpJ7bhHDj1at50n|FoKwN6RA`}_ z3CaZ(f=Y!YhMA;XQX#2SNJ9izgC=-^2sUFCumOf?w4;s(9L|_vOezYo7GEdm}`o4h>jzUUcv>rH0S& zx)gY8YN{&b0M{Pt^g6M{w#Q1JXjWg{5I^X#xg_q1Ub}wJcTXH2Lnx z@3OtsDgRG8x;JjC_KVRSJRZ=bnoMtA%^~Lk(=3}0yIRb%3U^d*?>kxKZEn3^A#%%# zM-8{R#@}{3k+Wo1(aiqmq%Fer%cky0Ka7w1yd~H(ug`KeDfKtRuPK}`?QUgqhR4@) zKI^+0iO~PGJBVRC9!ip^>}R-t8|DQ*i@ZWv18><%>z@zg7Z!8YcIH-^$t7lf8<%w zua)iQW=l;*$k+!Cc~w+OWz<`~-KT-)7C95#tq4_PLI{w`rpYbPTOg0ymRo?;Gz;ka7FpV&CI3h2loQ4Y=R|NKm0>Cf z6NC#Q1d$3Bm4r#cB@vQH1)35dVHCY6;x=;_rJPbhsZE17*f3=TvYi z6xcd0~({1G@3Mx@9Pp&=#2f*fExoQAdV5_W(khT#Vc zfMQ4lX<&ghXo44rU^AeB4KPfj9d$h5D8I!2;Uh}U+nSMWO*fb`5>~E$O$7>3f6bn2 z!1wYQIx~M0;{S@M{1;|kX}MGG9}=J6f2GynP`i`Q{pkyg(J#|k+N(^OMEhP{xbLPr zYHdnn19xt`+Wu{Aq$xP>;}+Nb@}UiB)Mar-H0xCxMfm=U@9j=6PV?Nfx)RJ=cXxZj z$f(hwH5tkS0wUh+*wGL?FKd&TmLotnxMB+%l3ISL$kW-UTB6t^8{y2*4RrMbtyWs&U>;W-g~>- z_I_Y|U99K!;g_`!GV?CoZQL=X>DB6Wzqhe<8U%Xx*?k-oM=E>(U-xLI9vCURf! z*Qa+D&tE(7OS#$@J5mvvYcDY5?z+^vAY|`EL8ba=Y+=QcvV$Wgm1@T6IsfH!?{RhX z=5v|uwv4i&gu+|>>gEW&Gsy9@$`_qzFHWn~*?hW0>%E`4cE$Nz30CiuON|4X;eoT> zo%ddJ{GofttT!y6uKMxbQ;{|C>4zp`+@HsvUpbjH@aTR=Zoz1UO_(<8mw93)4~BI0 zxr-Zun_sdCtA6L*%A)Gi+uS{i2hVhUG?jYd)avy5q|{l%`R2F`$yw32-l}^JYh{F?*YK{F7gQ_1ACCP@~_^zVU&coBJc`9N#_L;<#8>w(oF`=Z`&~erbE-!o;=99jBXmzEa8HPX^q{Io~Im z&vxskUw6lKj-8)Mb;Lh9pgrnW5K^kUklauozqupUrGMo3 VLg(z!s;HBhZIxl$L)C<=`xlm3g@gbA literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/mischivious_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/mischivious_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..1c7e90a9075bd12e5cb484ce7c379c2a0cb10d87 GIT binary patch literal 1796 zcmc&z>r+!l6yGF(f`9=DRxuPXXy6)!Tp(1?F(?oakb+nqfdayc6)7k_@G%1jmc+*( z4`me{A`n{}EFf5MT8kpo+KWZSidKtC2Nl~6Op#V>-5%~A(68MO$?TqUe&_c{Lc>D* z-%FDtIrhJ)EV9a4m zd4;eT?u1~DV9E;y9#AG6<~U4w{Xh%43B?@6l(z%i0(-y@FaQ*TM9>5xfHlwrUO)sk z12kX*7)(Pu)ZqaRM+oJu1ck5|?i@!b?<@!g9#G~ep}f%$3*-RCgVSIwcnRi#TVN0P z0S16#kO-s!3s?h9-~~irGe842fWb7hLmeLAP(CxT5){H>xKlnt$R7fSgdtMM5JH2L zAQs30j0dN|TJRF=0G2Qeet-d>7$gE|zyj7l6L zi(7tBDVS>$J&}(O=dB4o6=52GQnu@vXV-R{TfY)j8hm+DG|H;*Wz^zDz3 zyT!;K&xU(no)v#RI+tN$TYe0DQ_#9YbZ7oRN`R>n_w{6|3(mcnG^`c~ZB?%VP7KBV zUhO*KP^c)M=+$NpYrR(mw^eN~RyS&sAHKewxO-A+jKh@|T_t`MbtNAbP1-!Zx<0R? z$KH?e8aOWNw`+6IEVf4RQi-!ltdlp6hv<>n)7xmY-9@umkg@Y#h|gs^=b)m_P&dY; zT^|!#uO`tIqfOD0mG@Frcace(@MxP$dvoP6O>w_Fu}HopobgNE#&St+&zudbm_oBb z#MIuesNHk(e&5c(l(G5hy^fv>SDI39H3aRS)D2e)1XEd?|7X_zxu~mTD&i13Cp9CQ zw>+@STddB`@#;uOdq1`ApwrA#2j$`uvaG&`8fCPyzNgCE8(WtgvW>_z$`Z7?S%zN0 z5(9~`u!=?5eh21C3vG-s>FO7&suP=^qR&@!rT1!%Fi7uOE%YswFmj`tyHtK)mTW<6 z-_ONY9giw5G+qn3QJeIE{ZEa?zutDAtx>dmt6ZI9HfN&AQh%Um@+$2 zRbP01FzwZYO*PtQq`+G3TZkO~X)rh#mdZLMP32)?rYPh2V6j5`Vt9oqe_>~_ s(Bw6IQZ&}KA!J?6#%@Ddh3<)=z-=V!bk1_m7ly*9aF4op3o{h(FWk-QaR2}S literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/nerdy_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/nerdy_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..800296836cde0d77cc3b850d3d15e560c06e582a GIT binary patch literal 1527 zcmc&z>r>QK7(PtW;CLBOBxp6FT?iJ!;Ow#@W$favh%6$zFbIZ%a@=VkMj$Om%K!xw zbzCAlfRhmmGJvrKGme^?Tt?uOOW6z|l{dPZQmoDxBaRLYbQ#t3IbFd~(1$_e9yb0RpA$}km# z3Bm;tf=C66O2Q=Jk_btp0!;~!Fp6FjahpAiQckI$R4R*cXN+=21*1~ofimNib1FEM z3N3UqLAjtpP^qxQFq4!^DkPN(X@~%8&;&0K!Dg%iHo!2AcGU5J!xhK@Kn;PQzMw2|K_N!|($J zKrtkOG_b%LG{Fl*uo=+61{kK%jyfK2lwaci@DU>CrJ3!vBxAZcHu~8|yg(sjX3pH_ z@EtWvXZCMGd>#@npQXt?CqJq5S*+c3rRTl=YF~9qbF#a|TrnP7aPEq4lgi*+Sahex zqt-b}Oh+^uJsO>DWU^~pgvS+Y8~EnbJHv~v4<8@cGV)8uZ<^F}gK-IU9s9n&F8HuE zY4>!P`>6Ir^z@41Yoi@m`M0Vz3TuiXvNvq{)v}kqaF^5$@1@fns-E$QipxXx<#7dr zr&BU=oxfTy7#pU{^Y53W^;WHm%iMYR1Ix%8O|0(J*r%G&L$z-PSPk7n?fOEKx=r`d zWO_^H!n(=Q)~ju$hxGb$rF6UDg`-&~A|txZ^_lmddSy>vwE11nrN)V-G5eNFpM{!& zJEKCsUR&Cqb1`Ps*!Emo`GQ3Kyfg84`?i*iJi4!VaLuiI>$IKpNA*nOgR#(I)y%Rg zD{&@%XSZlQeKxZ-!av07pXIo@KQL_D;DM#3+4=f~{z?`t}e)xYcX z_Aqx(RQ%Z;2aBI^pB-P+EW9DJ^?!LQy=lvRjx7V7Pi$Q^HTRF=D-*``ZIgf7 zUDtcca}qQYy=D0qOKxkw+_y?5oBTD)C1D(1)iaHG=K5`MGF-{ctFAD9!9 Xe_&~zBfol?#iylui8j!ekc58$F*b&U literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/pensive_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/pensive_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..176e742feac4d3fda403ae2ce093a964c794a715 GIT binary patch literal 2359 zcmeHH=~Giz6u)sn1hp7Nk%&lG1R_+pD1vB#umlB1*5kW#wmS~VG z(k9A);)1~v_dOz}R|O;rh%(?(#OjQ@wA$Ch`v>ZmPQUbiNantC&hPw|yo82@%=Afg zM$YIX8aNms1|fnFMTq6@7$XKFf)T}t<;s{r41)-RD1%t88xzD3L#otO9HRgK21oIy`_w7=|(o%PEA# za3_SJgkd?szyr#JGL$kbrypoRH(?pdGAw5YxCQorA7B6|28o~vL;!1`3A}&^YzAn+ z1~8b0cBsPxIFt~Uvl0}-Vz^UESk74x3_PGrS;BHgLoAR37!OW^wcsU~2X28q;0G80 zia{cf1}tC=G=Ucofz1F7*Z>C8&<=HY0Egu=11muxEQUMFMF{yr;E*sx3K>FZkP^fK zIe_utG*}B>f*rsThQSXo02G5nAPrc+8fXG9AOf2K8n6KjrlB3`@Bj|?OZ*Q$>{#>p z!O>CTfCa&x?$ZYIfP!8Bkl}vtJ#~Q2z-xj`|3W;|iINlQE89)SxGrrxVW-P$vz{9y zzctdyTO^#{X^P4nRyB1>Jk`w#%R+N)Gw(3nQz?%dW23V2CW@qs>?I=-#)bxf+SmyBqAB(*wLofH=Ba8t3nbIU7pui6y_ z%X0WL7Nl8xiA!8(#T@G1F)_2ZJ8$w1 zXJM$5Y87AZRJB2v=c?;XED#l*PW1mO-!<3rEbQm*muQ8-GApgiFVgEmBwO1l@m0T8 zt5Wa#E=wOgvZK7jk+*K_2G8W+Vz&sFw5Yl&0}(B8#lgStGTSw0wweAO-+Ez%UrNpS zGLLG{1>yiptny%jcG?}28huLRC1uM5+53|W&y5;=`ka_pdTXAysKtGV&$~4Z)jz66 z3qCvbi7zHUZFpIriq~EdzIWBfTCI(%(3~A*@?QBQ&RdotJ-6f5w<$L+25l-mUAihn zs*zuCSH#s_t8eljeRuYTQ!9+RZ@e@7KD}NcHHqy?BG}zIDn8>9O&wj`sj;g4Flxfm zV@ zfuqvO;w!wL*`yHf7^V%=n=~8h3r5)n>YthHF1H+Ox%j+ILC^u+)9M1$SZtA|18qNz(uTdU~lNxka zKd0oX^@R%}Tn4M~%7ur^21#V`!ixs;3L0!9f>VU6_j6XAk$woW}Az>L`F9qzb&%swoU)8 z%7Z7%TS}75rZqQSSM?8a%pWzp=88{MPQ(bWjIPVuL$_GBkC!c1KU5ydI&SkcDoU-W z{_ZxvGIRTkbFSv)o84sI>5X@unXPeKdD$4OyStgG_!t{HbyiNtA7voh5Ed1cC+IWEa1k%6SLh{qfFXBzqs|4jeCA^*}FGV5>n CH22H^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/sad_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/sad_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..13822f64c28d9fdfaa061ce128603c91dcd69e4a GIT binary patch literal 1571 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 Rx?Na&QSr{LMMnp%`xnE8CwKq= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/silly_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/silly_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..3f1b9f54cc0ede341797321178d67eec88b59664 GIT binary patch literal 745 zcmZ?wbhEHb)L_tHxWWJe|NsBL7We&9=aZiw{^W~ndi&_>;dB2PEE)bYFx|IWJ??Ivwsk1v>k4xmYUX zRBGNcn_l*v{#jD^z=I5rBeL};6*j-D`L<}S=G9-TGq<}rNMtWIJM91ICHFtst4_v- zvT=+&xBk2d-7d*dX=%XR(qa&+RbJs@)M~&qfi=mdK!t&&+lqmCHp2v_xf3UamvJ@p zu+L_m-@?np%E~+0qs(9y`;Pg$CT`+OnyTT$u!DV0TgxJzngiKQJNoobEIRFV=zOcq zrHNO9&b4l^VcpGo>daZji!B>C^fx@Z{Os&1<_&xI@ousDtsdqG-6x>xeeXBj=l(nRLlA5sWLZ8gTk2+WllJycY zotF8|Fmb(eXJ+v8b2Dv=+aMtpfGfmuUhgZ=IlqPZPQ|+WTV?+oa7gmdVajMo*l@x} zCe>4QLuSpsMVBDpEv_l!%;?KiGXT(;uQ@stM- zAD)?^bnpKB>!K^ZoE5um7BK(D3J&wHTZ@h;sCM2EX5bBAwP9%%vCViVbm{OB0ZE4F zERQ=ADpo%dm09i3By*!V<)k*RpW>z+ra`GPq1;KQrc?@vH_Wt1|F&V~=JYdC%C(nD LJg+!%FjxZsk}Eg@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/singing_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/singing_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..687b19064e007fd5999423eb41a7e280aec9307f GIT binary patch literal 1619 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 lc%EsS2+>@8+^qAu?DC3{{^iPu1Ej? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/sore_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/sore_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..e2d6782a9304b705a9f74a2aed4cb63dd4918a1a GIT binary patch literal 1664 zcmc&zYfzL`7(T>BKnfE<6h;3Z`SR4B5%prX>zki0BIC>e@0mP3W)jCy+b{`b4{V|UJZ-}iZ+%WkknJ$GKB zC-Ef1WaLmn7$KYxL5NiDloCb>r$kU9l`>_7F~S)Uj7X)Ma>6*_oCr>&GE44KPfj9d$h5aK;29cgkVz94_fHvk_pMAVh7xUJ@5ktKrtjj6GVVDXo44rU^AeB4KPfj9d$h52+pNq zB@|*Y?m}>>I19nxfwGWXDn=s~M;#A1QppTfLLnC8E|mz8KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4Pz;G6 z4J@z*P4EH{Yz8#20fuR`qmBn0<(K$Be7MTd;Xx~+0v1OE&7Pq$H30?JS7ugfd`}yp zGx9efmT!rPrE^Hb;mbQL?Iy)tPVaU0v+X|@8FHuB+Q)Hq;N2^cwug4Pn8aO8tt+Wc z_Kf_EJMKNAE;59Bl;0do3N6$>JF#qDxm#$#szvI)uJT_4=DRo8+sxmiTT<@7t@CDA zTg7a@s)`wUO@H$BgB`80=5=D+tSDpWI`iHNty86KP0Sqs;pZ`$XwzDIqi^Da%43JU z+=@&7=xS{*YAFj0?lh_2X4|}Z?tO3Hl%hM@=B20qdfepFsM+tI^St*=R&nO4gF_z8 zZJS1Y{Kza%KNy|%z(q&mp7JudjcJFePtmYC;OI9DLa>39-%Eru2|ur zsjCPbJ7J6xlzG^H2jv}iBfX~bvoZFun;jdqi+2%KY}(ummuvPeqi$!=4dDk$CRpVj zOic;WEKm(~EZ&@M9_pk2drEgp)Q_6|=J9(s9i=gmRWyHWTEOwCA0Ab0_n!W0oVO@5 ztXfM?WF&?kj~r0xla_KXzcnpOYL8NnsML=3{U7-5o6&q;=hHkeZ>%9EqMiKU{<5v4 z)->Da%#hC8u=Xq)=v=8brr-b0rhE76^$suMqN=^@e4bk9gVGExqjRSX52k7h+!I+* zy=uKSyTAHdr*90pdWS~M7P|@EbJDJrUd-K?;~RMQ>Y&!m!P+lDd+|_k;O`a_XGJt5 z9@(+;mUH8BV(i^A)8fE_ty+tBQWy60%=C=Pdr|6ZR0rBphYn-Twi0sYp*%K!iX literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/stressed_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/stressed_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..7403e00b5e403a0a73042d191ab18a0b0ac19de7 GIT binary patch literal 2739 zcmeHHYgAKL7CsAhqf$RlAnn+1@ojXZ7#=m^nX^bl1V#`TNnjLB3$k$%BS?%SF^Xmh#W;l#6h=}QMUw^*z#3=*FCYS) zp%q{Q7*s<##NhxIf#W2OQ?x>8410pWNdl*6!N3E;1c{R*PSN^-7Gx6?PEt5U+W~HY zJ>Ulz0E$5(XaW(y8fXG9AOf8M8n6Kjsv#ZXZ~%)W2#U566hdRzlO#dW&Vpdz0b!CN zDB5Tk3(NtG2dBYW@Dj`ex4<6o0}KGgAQ4Cd7O)1Izzc{#XMhH50E22shd3O-qUf1{ zm7owB!=9o?2=j-5!-Qd^Fhdv`ObNyUa{%MPX|NW&1UrBw6oVgN04N5DKpL=sHP8fJ zKm(2x^ zy+U?Qep@c+uhuzv^56O9Lc6e#XL#ONF@sd=d-`oV5xM+*V`^^Pp4k3DnIU|8a&BM$GV~y!&^t+3 z=i=gW6=s=-u32WR*LZ0cHwkA$z4xvO)`x{frAyp8G7py= zso!*Dpl@5@_mfda{d{zR8-ftFiTEyU=<~MO@bZSguO1-vX2#>Jh_0B9(chl_v@!B* zK|5#Hsc&yY6mPjLOz}>avu@j&_uU;Gn`aJ;AU@}$eshK?*%TF~3UK82sqO_e$TwVE zXX!uvxjzx+=K6s-VLEC*mHt~=^~0J;xu$1Y_VNbu$#wJ+EqP&Pja&2yK7%jQvTBlxe^Hb!<>rmd1@d^F0U^f>Q9LYSUdHBb zs`kjSGP`)WaYFYxX@ENAP{^~qyVIpz8K!`@vO{wd3r06rSz{s?bK{(@P+LE*CNx+q zua5fc<;1`|Yx_vyqZ<2Wg>jp<^^42CPN8poQM2&lCvJ(y(p0CyKWq22Dn*yetOze~ z8R2}Z@0rxyvMgcuwnoR5Hri~h(mKZUft$}B7i=#7x$n5nd1B{y*_~M7fys+M-1FPo zTe7+`-ubNFs+fwq{-QO;sC(jQc_8`uP44i@-L+bWmk*C6svY@^^nxdZk1Twr^GDY z``+vnZq2Y#>R)j`-MH?#F7?x&l=03I=Hie4)Z!cTPm=UdzNMs#sIsv-rgXQke^^tJM|d{gbA?<&=XB}%8Rjx!?-R{g&( z!P5V9368G{k$vO>pIgcO2>F_od5y(~eV@mB{IojFHX;2UI-dP_Tp zPjc4x33BHeIVZzd*$=r-RwNQe9lPH-e(7)vDj%?1>sF5+_ES4D7EDXnT=5@cbxtRK zl*xJ$36HHk{4;OL-z(NsFlQ8>3bxj0&(F(@=d0E<>4L`6rW%a)4eX6RUR;&_QLH5E zX?t4Jp6LA^FHHE&6#d%Wm(=e~?=-hL>~|4V{*5!-oZ@TD-|+BjqhUrXFS_)rdZIed z`)E=4g_&D}w#k3QT@24L1u3WHp+9t&jO*1F9Z_1Ozg<1YJeMg>85@^gedRK%@Hq9) z`Nln}zWfDzl`W}KwQt#n^EbCuTb-g?On=>L4i^e;#D6dP%ec_fmU=x$UbMSu3rZ-v zxzEq=i+okp=-8cF!fP>GQKg(nJ-DkOeS{;=o1EgXtDGKWCtqcqR#aDr#q8z_d6QW? zBg&bIx+}RItnJo}>$S~avs4K^Jsv&>>)12z{<%>SoG!~WKh0K@tglyoEO%T`HGOn> zwsRYwp{lQXEYYONvTC1CXfm^Xf<#;FMkf^E@d8)DBDIZ`Q5ihzmBrwfaRrOK`Am^z z9pBceljo1dSwxK{gDZQ^rfG4Uv$eOcm@zbUHg%sn$1<$o?{__SX$Aj$TX&*5hJK70 QzxNpb|B3h?cp^6b3saba?EnA( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/purple/thirsty_sp.gif b/local/htdocs/img/mood/moonsis/stars/purple/thirsty_sp.gif new file mode 100755 index 0000000000000000000000000000000000000000..2f0c996fb37e2de32c008e8b4b0dda7f3a0850f6 GIT binary patch literal 1601 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 OwjGqK#ior2ZT}A)G~x6B literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/achy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/achy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..193f4c7d3df356e86768ee9165793c7efdc774c6 GIT binary patch literal 854 zcmZ?wbhEHb)L_tHxWWJe|NsBLVd!?l$m_Fj#mB(V9f z86_nJR{Hwo<>h)sB{{|UX(f8e`MLUud6~J1>6yv;TwKmYsfi`2DGKG8B^e5iP;mu! zPd9}y1w%a}Bd(-Mg`mvzj1q;Cdv=W72pef~vMX3s&dC7WQTp{@i#ia!WMXANb z3MCnt#R|DVR$_XpLS`P2pQ=!lnx0u)l3E0`qb#+kI5R(wt28e;BQ-f&LCL?M1jsK| zs6p5abY5<1UWr0lQDSbY5*LHwPZmxM20jKIkmo^R$-w%5fpT9;=Ddtm>vFQ03?6Ly z#3@q|eEwUKJezagacRby{R)i*3RV-=D!*D5BUhsO(rb4CQ&XGj=ATV@6F26E>L@Jf z4V34R5EDO=bVoF7k1R)NUPTiNQ&qK%c{4*xQ%@^XTZ(a4^R%3all-EqDh%fJ%yh1` zNMc~@&s(vm!QlNfGOm>ev{pm?s+WZk=75F!Sg{i$k3yjTOh)c~0tOHD*qj zwcRaYXB5oXqom-DW^Fe8y6kzmN3rRvSYzw_fAp!t~VWpOHTHvd9vg!kzm3WFpm%c z^Lk%_&iRtu$qsyXbPE3T%JM&*?9p&2aixZ$0H5d5j+ZrTOO+coMz(5|M&(WYpwN)H zbAI8Ox_=8UPJ8bluzhv^_lLheZ7dCKNa3%Ht1T%nZ)veF)Gkg=NNec!Fr47Wz{t=z zdunxGk^M}|ZmXUJro}?tYv#n zKm#^_K{u2`9xmX}gfOg?pb!Q_Ow)v6odv20E2EQhdf-sVc4C4m7ov?L(H%%g#E+9VZ*Re*dZ(p zwghW|J%I7xG*}B>f*rsTn!yh+02G5nAPrc+8fXG9AOe#C8n6Kjx}hBMZ~=#XiT}fo z38S;aJ2YggN3ge(ox>6}pkVS&UE2x%g^P3+KNF<&0jX&j`Y9T}%hOt66Emo2y7Psu zSwNj%$CGB`#9XO$S4yDwsq=c;{XTlNx4qVw%N@iHe#Ir0!F7?^yGMre)-99wcE{&? zRJrHf=r25QSIQG`aY2pvi!H@pNd-C zAKTd0NW&Y3XC{^NQTN0GNkEIxe0a)Q{=Tlj`e^&~PtvH4iOofAq1@28ZQ`5VPW)*n zNvUG8*4DI=&S-wJq&9U(c%-vDVXb$-_WifgK9rq4SCG7}t!jO=-9eWk?tW2>I)DGF zsPR&>`qKjzU7ZWFk39Gd8CI=mS4e}~M%{#Xw~e(~s+hdM^yPh)vD-CsA99j7Z_~#k zRl=0qWb^cwo`s^p(7v1mH{VhZ!^Z<|FY_X(!ZQdSc%l zDG51aCHGA{yWjap4ypRX6EhswY6gC8Z_{s_l^KkU{Hu&!_3eL_KBSvas-L0n|J%^G z5vSPyenfT0NM+sGJueb0(^ZMf%hUuzr#v%r#{73yRKC)hW~{dy-S3S&LfPkudfS=v1_)2^>0Hkp-n^##nzu6CZ8mG{gj+og(b16}s5 zX#B@pvB(Uy@FQl4N~!hlRt0@UOYCwqEvW%GYIyO6{-IT}|WH7x6?FWtEzNo7N523pbRc&OhQ>1<6Hm zsjsQ7y$v-%CrtMxuH83!?z1ePKU5{cG1thJ`4q=|yNH(Tj2khVbPPA&Y-6i*nw#QZ%ZJn&s}z{&|awMS$jG{LeCV<$vZwIo@*g#2OFhw z7g?d{P2YjJl5ZoO^rOe+*ELF=byttQ9No4mVj@h%%^xwE^7j#A*~k2|Y8o;HH^kl_ z^NtMm9D2YV?BPd83|BPvscE($ZX8dkPBQFbR8irLJ%R#`R>dKtz0l#bQkUYO&bxsKEviT@@DRUV)lCH%`v$oi84%@IE~qmgIhNRicYwS=(5? zadqth3z5g2Hz^Sb@_OS>QpLAi^lBoTcDwt^n{LM+J=RAix!ax(jd9ke_%(zdi*H_e zyxctOqvLydHRT-nqkg1tWgZu%u28F6Yk2cM|mX6dmkGl RU%9R1NUvP$TzoLD{{T_HJc0lK literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/angry_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/angry_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..b1fa70c8e36f8a107237c0c282254ed6cf299954 GIT binary patch literal 1602 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 Z2HD@IgzMQ`G}gj|sF~_Eh9wiN_yfml?koTR literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/awake_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/awake_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..0d4389367967d3e45b0bf56584b3ebbaeac196ec GIT binary patch literal 1323 zcmZ?wbhEHb)L_tHxWWJe|NsBLVd!?l$m_Fj#mB(6yhPsYO6L%2JDpGxPJf zO7oI4Qj@b4l>7@yfc#>G8idV2=jEp6l_;bYCFZ6oaWN?VWZ~3c;A7AM`4$wG46IKV zDEFmg&dXS}F6Z^W0-f_Exsx6E?&uW!>6PVwI@zP)P~u7rMFBp~r5!J8*p@0cY>aHx zDvipU`az)~bLafRGj;zKT%7jaL16pp{_hWeecD(W+K|Fu8CP3UUf$ATU#MN&*pz0~ z?O`~^uwG%MzMf_vs~e zwg~hbvCWRHTDRx4R#dV*SEl{^OPV|VrtvZG-aMRf?|$&3s@pCv9s4YKg+&BkyI5WR z9`WnCItrOM3o4!wB(9hTP?*Mr!8>$kt|1=L)5>mjOF?3 z=g7UQXJrbn$ZUygXlOFdt8_D{DrzsU=wV>2naVJcJ-{ii*Pz|7V|GrL85@HIbAthI zy&rgq?I?; z-_k58n-j%b#>w$eT25SIXeH$eJ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/blank_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/blank_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..e8553e478943996bad2f8b4542f57b1337a38bda GIT binary patch literal 1533 zcmc(e{ZrIc6vpo+On^>+y96o>EEuq0jB?XqCj)ueg%v~IXE5>w;cCtrg<*k0Me!0$ zSl|oSS#UuRwW(NW6oi?E5_!8g5Sq)B7MO-JsLWJ`Hq-6l+aJ)6-5+-6-gC}#p7S}o z@g`%0epfIFCV!H}LkVGoa6$wjQn^z~7$uw%L5Wntlo7@VXGAa}m2AohNu(l836xNZTm*4jJd9FKsi0IUjd5p;az+KCQt^Q>{VJ?^uOe*uk7P7fyLNck~04?AF4*poN@qnZJ690z}tz4R9NKcE6PBw&xtzDvm1?^)8 z=Z*MYvuJ1WZ$g~@CMqZIgbr)}2Ttmc?4ge4Z!6sbHd_*GErv3Ccuwz-+Yio~piJ{G zRpYyTBZHETdYL+{!;x=yT6RvQT1}B9XNIz~4)|TD*FWBJk9M^g%@Mn=T+`)^q*Skn z3LNt<-{-5-=apJaUCr^DpvugQlZJMm^L|n1XD^MnUTxFcs>X`rt8X4Ld*sBvU+8kY zp`@$&*i6hw&Cw!t>DW^zbhp3Gb52z0!dnK_Syz+XLn7#Poh~#nd)dW#b|x&cE@7^4 z*g5jx(!tt~bB0ylKl5(WSAUhwYo>z3xA#pI>890N;$mM?{kHCB%fU9k3k&tG8CUG> z3t`@U{@>kQmzGt1s&QM-ozIR$tsHWy%TMb|?h4qEe_$Z~fgvbovM9&dd@7xtyTBqPAxJX@3v_-Xi64xc|lpOsoW=u_0&6_9zF52tt4IV zn44&E4Je(X>cp*{Y5un?P7?tsx~$gU@9Fc{%QYc>ug_I=x;}gIg?6tyX@At#)Of}h zY_xUWZ~QXzP|W(!0mD$++7!EP<%ZE)7t>$8cC5fXKjsVbYnwmcwqc*IXV~_g>kltD z)c1rAKk8p&A6Tx*+EH-R>``DJ++#>(_KDjggN5y%JZDy)-PEYlx>hWkn%P&M^wFb? zxiZs!Yj;Ld*l2IZ{vWrR9yWHa8pvq9?o38`_9O( z|S5S&j literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/bored_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/bored_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..dc40340f14fd7e6d7e35246e86b9b571eeed9653 GIT binary patch literal 1529 zcmc(e`%lwX7{(8ivKq&@w5}u$!({`6>gJAujRrv|au-@8fG{H~XK0w21aTu{BQh?^ z*d<)#KtV+a+O3n~LM9|jKv0Hf1U47kNSGzggbBMi2W(_Jd-(nX`*G)oHs`$W`@GNl zdE5O7ak~shLP!W%CToWh!U*An2tuTCr<5>CI3g}loQ4Y=R|NK zm0~Ig6NC#Q1d)msm4r#cB@vQHMVb;Qp%l3Y;k17XG~ z=TvYi6*!=7%k0bIF8cQo#XQzylrtfQd08X2K9~4V&-||&mkMaC1$zK^kOo??1U%3J9`FDFOpFm>8d`7- zoA3oA=nQFSLk!hOM;s40QrQ_$VnQ^=T`DWY{;_au7%RmNu{3N6Yr!4>9;AU5EP(?q zQ4AgcfQd08OhXH7>4@V2NBJfG4u921>pd}-T@>s(;L z|4-NTd+@Dav$OU$A?kmKi~8C4-U~yOYE5YFSntIfHJ*Wq)_6zfXx&D~(UI!(i#H?R zO0#B7dHMHi{8p2vvij~N)SLUPxkHZbs3O0J{I=rGptyFwUo2js8RO&i+MOLyLp>i% zwwU^ootocAzV3+h?TB^pwvAuiUUxRv77%u$A+%=vPRr=T_wD6fV|m9){lm4UjQlrS zo3G~TOfP5IAD+09)Bf5I`5W|AdgpNP(}!ma+8N813S;vdMbpO$>fecQ>rbSY;v-wk zJ#Gst0TZ9L^pNJQD%JXloC7<$ZQ&0ZuZJYIJ%}l>Cq{0wc=XrW=hO7&$FnZ_bHT?4 zqq~R>|OfJDqUo)v)ZS0#98B8rtYlLW@&Id(PBVyBK>uGB~wy@^c4hl&@HL@o7s!mG545y+L*9_PHk=yfB+G*0ku`ZFYn-J(~OED|>KDR7#oqq3oijJmJoN zdw%+g*ZhF`@8N(mLqRd#-G*u7-GSt%E|gxT1rKLRRO>eSn1c>}+?HPAmUE~et0-)> zusQ$Ksl^`iYJB^?zi{uuFKZ5`hUPX-nLO^{{`05h=KqB literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/cold_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/cold_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..cfb038b7caf6e45547d7a7f1cbb05f614ca62a59 GIT binary patch literal 1684 zcmc&zYfO_@7(O5@ZB-(uD8{;hLa7%7&W4ww;bH+bT*M2-fu<;jY1kBp7mPYC1q23) z)YdaWP{7MF6RLBGnOl%dM)9!V5;t^gI<;gjZh^^E(CqBt%YN?1{_Xr|bI$v|&-+~3 z_?2;smzaY|FnLbK4kd&U!U++CNaao`VU%!61SL`_Q$`pgoDso@RJtiAj1$g@;6y6J zR1hWz7eojm6)Y+VlY~nmB#{a@Z3>rGiqaEXJKN${7`mN`(i?j8o33 z;8ZHK(9Hzpf(k*U!V<$wQZA{GR4Sw)0<1w3yg&q-u?pA#!!+7a#{&*$OfV)Dg;EjHkW4Cez%AGVKVSe9Ln1Um1XzP6c!3Bu0~*)>!!+7a z#{-VwTq;&VAr|8<1ec1l5DXqD3(2KoG-5#xFdk0BT6hWb;1=wGA20xlArYj31=gSm zULbqhI>i_s5<1Qe6#Pd# z)SmdBKSpQlZ$eam5jWM$gtj+GuFBz;(bZ;-&K(!vmGVnlmhrI9?9@-YhRku*+E|~j z&W9Cu)u;{m34Z2>&a%Fc{G%6Avv1nH9JlM8PdhyAi(h}%zvSt;=y@A9{W@oE-9S(C zst<8ugJVpYMvUk;K4HQ89%(0+u$#40j?XzCI{}a8yzjXJHA!VYwpwz-*??n zReZkhz3F+oi~2@e28S|6O80aJCj_VU>^m^nySJrzaFcdNqrsGs+!NCuJ}~;=ip?{^ z{iiTqu<%v+N`peS-6{F7f1|5-*o&xGC8dpBHkmZ@8(~V)7oC@=ojARb}du%F?!`9-bn+p89oj^!4%xu!bMT3?&tw$t~Zwspmv pI**1w=U7*!Zp*IA%;v7+?{9nTI+k)sf7X^(b2ZSO@tOxQ{0$ee%Pjx^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/confused_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/confused_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..ea3beb1712dda9aa7d069e7a48579fe414d747e4 GIT binary patch literal 1670 zcmc&zX-t$y7#{5|E*M3+zzTu_BJLt0I*|&+19X)mP&q}a7GxQT6)VIlT4|8O71k)o z^sb zA&6A4s3c4hE{TvtD$tYw38Uym5x4QfDCLw2N~N+Gcg84ZR4^(P9w;+TIj4eCsn9|< z6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l*!I@M9 zg9pl7Fd>*!^n(_?j#M&(l~9PqxJxBM`7qxIf!t*s$=+qCw8n$Zzev38zkOw+*^tLm1`jVix&uHD_= zK4;X#v+_(~g|5rl`7(9mjjBoQIdK7MQ$&sJ?9ZQ5ZNvw7) z_bvP+yX>u2pL@)3`gV|a-{$oCz_f%6pNqbm9tMt08-DiY;|IDe89grd z{7s?upZ0865U^>{UdPK3YwxT+v@txTCN0$*bU0F7Jg0X4)-|J!roUQM!8`4=KNdCT z8K0@ULQL0;s+WW2Mwnz5?Yj^MRC7H8( zDi_3`FAr^R4y%}DyS?fBPweU!wysuF#yU2KG^*PTeOII1ZgBfkuUoy!+|FwCQLV{O zU%Ew?PPOxJ$nLVO)6NY~?)*94Q`9@`pQyk8II2=RaIf~xvz?~Ms?78Su zQ+wGizdA$CNXu_GZvEbOVnFqJe|7 z&XNjN`Y7p%t6_b6OG(bL=hk<3x21)hxp3s=t&1l})xObtY4(?v-k)=6&+Al!@ApHg za|Zj5zZh<*I=*hf-+k}e_gFrhwByCoBA;Cy$)~=_S?)g)lWd&0r_afJB`YHAaY&x8 zsVjc}XI#?t8m6{{1(;NKUxjCgVZ%4RO(;b@#pKeoGM5d?n;an^4Kk5q{x2CVs bpV+BiS>%6V5@BX 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 GMSlUB^Wj+l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/envious_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/envious_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..afe590033c3fe9f5b3a33e0ec92e756422a20b52 GIT binary patch literal 2413 zcmeHHSx}Q#6uu}?pe_MIL=jnK4JclvpcZ8dLPXgG!4{HmMT`n4I#skL8i62)BLnG{FqZ1Hy#D z6oqLDGb}C0CN!pKOw*WQSwb;kFvVb+!3;|ph5*(;6LJXbg9XA~Z!9c3|KEVTvX+O&E55pat0!LuiIDtQ?>g$OC$S05CC(2s6PDz#3=* zFCYS)0UEFY45}d=;_v{6rYMG$5+;PkaHnaCVU>k}fd_7y4pvmbDjho^>JKP)Ok*0mn6eU&HM;1ARUW$6#YnkP-#qW%4Lx{XoIh`*!_~cS!>gaPr z2Z?4~)AkyXwV5`mp)sQ*SKdC~|HbeGf6hVogmaChw;zP$na0V*8<7+=0=n=!xDY4G5}A5sSMy&j$z6t?^tJG;PV(wJSo zAAf`7u>aGX$mM^}m8NX2T}Z_WO?9B6cY*jq8@Jz(=NKcqpVKL^8n?$hSX+6`XNR^T z@u!H&V4vN`+Y;ioTAw}QJ+^Wf>uQ8DFG=f7=j8Tq)y!oM*KL)lR?gnZdn$r;RY5$* z?3n1Xz*@^X>t%IAUw5i+l+NmS(d87QDmo-H6Z^|Ejf!j5=%#&c+oCL*;r!C!w=&Kd zprkdVeX2!rp{=7hzPnmvZSEpVqoy{YAy+p)myw+< z?T_#3E+kN!TG}6|dK1xN{hW^H?lEV!*=%lV43x$ASv*p3GIp3XpZ-iOyki?y(iZz> z>7EB)rPF ze3sHYS`}X>jo(R&C)b7@Unv<$?|3b~wcqli)*{9Ay((9Ey*hKr1F`T_)Z0Y4o?YQo z59PTNr5EEuzW+A)SeggVVP#dfcuKml=>bumY0NIMPFvIPr2EU&TQo0XJ*RZnhJHoz z`zNJj>pWb4HaQ`(9!NOVTzuQM@KJMk{fc`%9Bzp_|4fq2+xB>Vide=3I6~ QIDhrW_5X_et1GhP4{_oG-T(jq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/exhausted_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/exhausted_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..48a6c2e346b251be4f1b5ccb64df130cf139db82 GIT binary patch literal 1594 zcmc&z>r>QK7(S~YD3hYgf)_0A!U7I)9E8GzVnGDf3t-}9@`492XvTHG3j+m;fLjUy zYe!Z~Ss}@BTrCDF%a9#tIGX4vJE2aH7%(`dqkvB1>EZVW^tJP0cg}g=_j#YoZbD*w zWYpF`5=h3$pXR9Iq|Ny;S^l1ha%M1VDDf)|KjGgbi`V3UhB6j0wi1q7aL5=bQ=7 zq#_tRQ09UO!K9)ew9w5Z6Ou{A4!8w-;0FwVVn~E0hyZKQ1TPT5WUh8r zoJ++@D8ypih2Tw9S=ClFY$l)@RlxmU0UjUv8#3Ai^Ha>K*9Tk!}Mr; zhfLC${F@NxS48FPx#GfCzZ`H@Yd3XWI2D`gYK<~a{Oxd99qhN(Qt>G6%Xb#(Yj3n# zy(8R;CNjC9G&8Ym;d0hi z?O-WJt=C7R6&Gi@AAhT9?%;vEMx)Uq!4Pe|7~0aj_ca&fhccR~vQ|b_RBwEwaRz4dae?Iu5T2E76Ys-dAUj{^3I53;*7;vmdWK6le>d zG3SeU1<&kbi*KIY%jZ_)8JhBLH=OaBrVVRMKAzSvpsTKKyGV~ZA=CG@hYde$+%dMfblZ5Mu`aYAVZFOHsowVfl|6437hgX)aH>iZYp>eU zQ}Sw=rCsNgo$eavGEiQ#HcS_Hw`?x^y8n=8!BBs>*P->FYy3>vw(@|+6+Y$K7W-CX z@L}h)7{zzT@c;5X(sjYr@>vV#yS7d_tt+vwi|jD<^y`coYl?Z|$>|kjX0R!`t9pCv z5l!NGzlul5X8s2|(|*0-+pR8|Fh{OwZ%`fc(%c!n^_SkHj$i)rpLyT@R@PNI*G;)RQoDU)$o8n$O+GgE;Gli=gl%Bm=%6*#(pvR&+fdfQgMF;B-myNn zuO)p?yeeblhAq#U;eVp6? z2TG$idBpvk;PAcs^W1N4?P_jvc{cNj=~8}SgfV<5_YXhMEuA~hI^U0@$A;HXMP-u@RE$*j!) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/full_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/full_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..cab0fb3492bcf069b62093a3d3dd4413a2578674 GIT binary patch literal 1767 zcmc&z>razc7(bwFTy!h86o`r-x1xmvss#~rnXWpVOuvYu1ogO4W!lItN(ADZM%{G6vc3E9?hn|7gi#`h z!yF?#Ba{)wh#+Ed0^tQh1;PX(h|nAX5=POBB5pH>=Qzr7jN=4xG44FiQJ!NwCx|>y z<|#)h$0#R=w9w5njxvrhP7qmQm=`!Ia7^F?ku*erHE4nth+s2T0UKbLMmy?wz@a?P zcwP_{VlnQN@{IC=C>T6Yri^Ed7exJ_g>EYFOyC944!8w-;0FwVVn~E0hyZKQ1TPT5 zWUh9mlnSDiP>992Ge!l`SqKIXl$k&U(P+ei9AG@0hPCh#=D{u413zE@ z6hk6N0}HG{6TCnKn*j}MfMFW#sN(@g5Ho|7P>9923u1)GAAuubM2ZX%8d5?m$N|Q~ zX;=#{VFy@Z7=FM2D27Ck1{PR@CU}7eHUk>i0K+ueQO5(0_)GjBK0*YaY|YyI)yX-U zWihH*ZlDk{HQTEI-^v*}Gk+7}`8RR%T%fhv`geOumlO`!JCZ9UXXD!SlEsbE$o1N; zAxT^6fxPM8`}HNEY4uCj7vJBl$rwsBbgR8==83C&^mdnT)V%9fWnQ*jRb?8;GA}JG zdH7}Tcdg3mu0H+Z@x~j+iT!-*n6!LRRBZpnRmPT3b%d@c<-o&{icDE_Mu1{eGU_GE z>?x-1FTefi3uBS0s;V|508NcdsOPM?|rc-AK@_6nQ5v|I8leASVN>qLQ(t3Z{^B<+p z8q%C@F3Z-ywRwy*>mSALa(d+^xh>QzX}=)f@Yv`yXEyaaQe>~S%gCbqI*0$BnDh4b zwYtNX&1sSA$`{LZTBo~r?$+unJ8tY9%pqY<{cg=8@<7Ljc^&rpPkaKmENqVK8%ps} zpUb(T$@pmdr-d8%`nkKp0+RB{`=?D#Z+)qsZ>g^P;Y8b(!Klght+y*Ctu;$FIgZv9 z7|V{Cp2U^e>Tjl>wAGgQNyLyn{ww5f_DDiA+O=mpHD=ecl1qK6(3!L=A6Rm`v{5^! zP0HAo2aSIESH;cdb88Mo<+`67zUn()uH2s2J@8)SzE-JHw;;Hx$|Fm;)Ao|KjDIZi z&+IC^Z*WfD>QtQgL6-TO`nn~Ms!teROpKi3a(flVdzGszBXg3h=F&!2!p=V}FCLlq z?vpA*#;kYcZ9{{BJsY<@b8b$P8Ga2oIOl>w?;mp}CfR5(k|y2eC(N^U@_YY9nv}3A zbHvY4t~18t??kTnYPe(kkfkO#qx?wj^6cB5cU40tUJq(1_YL=c(VtqR>-fdrVf;M0 z;D%~jO;Y!;vaV1~-Q%x4km?FdT|vd$M-uBQGpJ$PYgyN7t-;4?BnwSh8FXE^V@_bR zBS;!-m3YXU$zAR{-hDh7B#$0mP79T4qe<=dG`6AmgIaCAkFCg2@1Eh

    ^E9{)Bg>5<0gl-W-PAkXx&75-Z9hkRGF>%_SM`ZLK6M~ZtC6U literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/grumpy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/grumpy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..129048674fc88dc67b1bf1d544d9808f125897b6 GIT binary patch literal 2285 zcmeHH{Wp|p7=9@0qqU7tHsoWE3}=+>QHw>PVJ5;%Mq24GcsNVDeJmE?D8^vqJH4Xy zS+>I|*;Q?8TVc}lMmE)0?Mgnqf;VpuH9Ai^MuK{SIH78)Z!f>x-7Bt%PxU`%05W6ZFFAtnS<1k(gFEDuN% z3R4uODa^36pqkK_qA^WlhGhxOguxVpX$CVaX%GRdfhO<*A}|?70XBd^H5xfHlwr zUO)sU12kX*7<5B9(ft8>T21CrSD}?>S!ePU( zQrICZ4YmYpfjxln;51kZUV?AG*Vrzb-wXkXe zPe!XM_1matWjO;ilyjC|<7IqH)FA#dDEPb5Xn$V%nc0I?InCxqCcA@a>R?&|(Jwz#~oduN+`JLLWue%Ou7X&2)nEPq*VsC)~}= zN$!MxYqL3$K#~A>p$tL%hu3f?e=+#-QBsI4|Y@w+Uog7)tjVO`#2-IMz$dd6Y@Jz z79O?%1X=(?m2APQRcGX{}i`3`6M_;DTnN0RHFR%x30f! zo%5-Mol8tcwXnU;*T}X8ekhU#qhbrm7vXW@SpUL3XJ)g~eDlMLS&4clns$$q zJ@&o)v7!{i4D;$q?s!Aa*~XnM&XeQu>Iv80z4HkIRjR}2hwue(~s^B_ZoFy z*jkF7e;XKjRd#BvPu=T!-)gUMQX`#f5EP^>aNS*SN$kpXhjsOqi9C0tSlQU@?^TSvT$i^qCw1U=zu%mSezw&uMpMZ_>1C}IgL-~E zt9?mppWcfI(SZ3m@V9SY-C`5Spjt|FIDdtmeVA8|?0Wy5%W+NR>2AHfk!#G1Fa0uoY4)Mr z5zRT5H(sq%xBZo>PFdk}$o&)H)e+K1uO1hsHwwPziBttPT(zcTSUYTg_Xe|fiVLOt zA1EY3)6+9Yg+ovFb;;asr8^xiQimsRF|Qh`3mJaUhV={dTjLWdkLAXye4C>y=FeW+ z_U__B>NlqMlxm+BO}3J>sLAMZKYNb+ZmzOEFOwCJ=yIt>V5ICJP;jpXFdfQ*j|8M?Zc=I3s E4Kh#KfB*mh literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/happy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/happy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..fc5db454b3077ca90697de58473481e118e045ac GIT binary patch literal 2260 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/hungry_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/hungry_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..e6b82f7554961f16798d1d84cca8d0b08368dbf5 GIT binary patch literal 1669 zcmc&z>r>QK7(N&~u^NV41QC>r;I1&MaMZMn2^54y1%}ITSp-Z@88C`DnHgRdx$6jo z=^sb zA&6A4s3c4hE{TvtD$tYw38Uym5x2?1DCLw2N~N+Gcg84ZR4^(P9w;+TIj4eCsn9|< z6O;=o1eFR)3^Pf&q(V}ukcJ4b22Jn+5p2dPU;_-(Xh$6nIGi!Tm{b&EG47l*!I@M9 zg9pl7Fd>*!^n(_?j#M&(l~9PqxJxBM1vZ}g=VRPsj0M)Zmt8mX zyr-|KiAY-7YMODZuR4(Hd7s0cpYmPS?z-lYmo--#o_BO{yPwC`#KhQz-0stZzR{=k z%ZsKQ>o4$XNj0B2;+Y!YI-xIXcJdjj_O9HZPIA~{(CReD=JjkD-Eb!PuD_*k)_z zt=ng<_WrhVcD^C4rNcJd#in+@tNMP*n!xqjB6o-6FHR{p`8~e>85_Mkw<1WtX*j_y z`O9>pW7bu#LyjuT$-q?q5!m$BQ%yB1jjwq+cZDFQ{MS|bu4Oi6wf+3K_{Hz%)pnL^ z)So=*f7n%I>*;=UMMAUNQu~}|8~Ij`2OWHV*2z>pysok|z~ZK;@AVEp5uG^h+g73N zEH=fDYm2>3muTY;`6m}PsG_t9pN|#2S@)>-;DRQLtWdu_B>^9_H;(kYniS>e7L_`! zw4!mEcGrQw)*e^QHhq_~!eh?Pmh7b3kdY^bl8G%F?GI>kgU`&$9%{7jzdI6^?Mn`7 zbnjk#(Do=ZQ#ZZkof>0aM%|nOW1Yrpd$4w)q4-5ZZ;yIrne{#0`dfLwcg$)qT#PG^ zsOmf%TNNG{Gcbn2mWq*rgpq@f$km&+8Ji{L*)_s=?ctFaO}xg#=gx^69k$V~ z^-~O6^R85ddfiwynBkyRRew4q@0@4Yxb-H7(vZHJDdqDf1B(pN4p#*Hdj5WC98;%P R8bYq7$HqK$vLWQHe*xAC$dUj6 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/hyper_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/hyper_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..a23cd780593d1b17f308b631b503a281ec5400cd GIT binary patch literal 1545 zcmc(e`%lwX7{(8gIxdT_flvsH+rn)Qoo5n?3Ii=rm^h_YKux5=8EoJtMz$C)0V$Vu zG8YPZSV84J6I@%IVG`VonUi^3U@;Mc6PcHRlWox@Kt^`<@cjq&!Wj{aNF|$c!Z_ia2u`F@ zOa)ML%=m`!WWF7Gg?6#VyH$s;&{N}j0wi1G9en{ z&N&mDNo8R8K$r_A1e41Au!U?cnUG8>I6w<{zykm;m=KL|7lKQLECz-TgoWf%0gbg_4*(C+Kns?D2U@@b9sq!eF(OPu3$9@k zzF-8MAq{Pap&IFk;{iu1I|E8gh{m`}Wrf&37LE;LrPv{shAm+&*aN_WG|+-2aKI&s z!2x9t{ijoiQReKe)ejucSNQw!_ls-8e44~yzV{j?i*z& zeONcLCnPB<+p5+%&kQGh2UY;oq791FE(oC-=3!ZU1_BWd#>GzDf(fH zIUqUmX1M9SkQhzT5u2|6Y`Sk$tzlb>wkP;pX!5zKOCy~>o(jD2Y&6{ z@J-QvbNo)ouyvESp!vk*CxrYqNh&_&uB3XvCJ7yw1O-HAQTbB{p>L(>kY@UrS<-`q8nn zZi~e~y?mX+`TE69!$kAYgH*HSL{>q&J;xfk>9YRsvEV~*e2{v+v?Q}K_sx>L!Ik#F zq(fEix7LoGA8O?RpIa{Z)5{NI6WVwAcSl%k!rqZyx^&&RNqs-AaqKPClZD(_?avci zJ$_y4o%4A7i@bFc+OWW>y-lZ@jE&DyJ?`BdJe}X=5v2OflsI4H-4)I|8x7fh6Fo12DlpO889;fl`H;a;nZN@ zWzYd>1v!I(^=5){UrOe@j8*G$vY8AXoLir0Y~;)A7I?=pw)?p>50B%*t_TCU!c(FL zuAAJN6d0HjRl>*AoGWr|wG?NZw!rB}l5A;@uSsrTEPr2egL?t{E02n*YQNg}`i30u zvgTH|j`E7i=C%oJ0Zw_D^=<7Fz4FqS7!vyDCx>(_>FA7%N-eB2M_F70?(!?skpVPj;gR%ujT=>v&|%$@TK&(!@}aBjO<&+9arP3I8#wcf0Fe()v2s2JO zr-D2;+=bv$A&Y_G17RV#R6t`b*aN_WG|+-2;DHwKfCm6zVvGpW(1L5& zgfAFDXGlXEVyH$s;&{N3%Fcii6QVKhQduGPkA-8ySSfahrD0203-$o;APux&2^?^V zV(8d`7-oA3oA=nQFSLk!hOM;s40$}jPM_z0CVlB{W|8`i&SUB2|iX;WY! z^kG2I8hkIFv@`iPA%Ty{l)wdX-ECi#2F{7d_I025vLZMv-W})t*jjRPdG2Lj@U0-t zBD-_UHN1V{xy%{E06+voPd*gXQ6-3EF#Vqcd{*;0?3m ztK`c0(cxbk%62R?TO5bnw%!x5nne}%Eyt}L`p%H(&hftC_G``04BfkKvR5|NIOpbW z_@HQd)2Z~{r&rxFP?!fC|$>z-V`x6!iORS0r*>&61Gh2InMaR6KQ~#*0 zs?x<4tnv1A4Yxl1W?${7VJxNDbXzm)*`m%Zeeb_8lIT0SBrz&Dy}s<`6;;Zor9qyY zsVgT|I=6YZwjTKQmxQyaVFlVphW6Lo`n9=3zh+GDS1)a9^G#1{yH-=(5jnENx_c*C z<|uiTrLzwHaA99=a_2{9w~lS-DsPETUtQ^&S#)pT{*_}#ek@#@eOTLSJwL@|%KK(X zvA*cW(a@S{(K&T@>ph+Wt+j~-#DZyuU*B$g&0~$&{x0?P%T{e%M e_Lr+N{r(DjPT;8PIeXmb5p8RRp&}Bzqy7OITY$g- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/loved_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/loved_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..4d5a3fcb65c7e5dc9cf83cdf4e3313ec43cfef43 GIT binary patch literal 1728 zcmc&z>r>QK7(Q|fRwqnA&?H4gmX#0pS3$h{yn5fK)I6wMZ`R zfkovG;$;y<939OBH2e)rsJSXOA!?}sUdUobJw5#T1Nzwcusi3x@B6&ZW%skCOT6br zDv6T(MMe)Lgb~6Ckq8m;ol?Rm;gm>}2)RrdVT^D_Bu0eXO*vtla84vnggi_o!X&~a zB1uHZSX2-u2p2>WM99#T012b$MG?2r!zksHN|XwDG46~}&Zxwwka?iYIOUv5oC=v1 zx|u||L?wv|nI(pqpj=Q%P$83s2(SiC@B$HR#wuU~4AW>w9S=C1F^MrDE5u^lIcE}Q zLKX}jD07KP5)-n1&_XvCOcG4UcEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ueQO5(0 z#JP~IghDLFU6QzvorPfVKv@!8$VMX;M;#A1Le30ULLnC8F60Q2KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4 zPz;G64J@z*P4EH{Yz8#20fuR`qmBn0`Iq=Vd^m}*%lyJZKlRo4&2j(GbPOmsjhI>a z;@fSM&gkESSiT`+ET{Mz4qeQ)v{9{6J`JmnGaWF-w;Q4^YSQlYdYJ!uz1%z5d*u;J z)pbYLplaipOVJAb{28-vTiNZ(E1wmpY00rEbUGLms;iFP*IZk!GwzED@DEi4SG=G2 zOY3{UKlUw`#+iwqeh?6VHE9 zM(uZ>?RaOdHr;Su^X6EFI($NRY|4eI;VoP34cF+ntR3B{_MwAi-R>8rx17!hZ0g-8 zJ!8widT}FtvS&|ltv-CkpJAE}8TFob6VEO6D9tg8?01N6TdkX#b=A4UiHPvrvQ^>5 z?eA_^F1}K+E9+E?nZjabOz{TiQl(S&cg4;#JZFcs>yuof`fpBnmg>J~ci{Bg@t&$S zmoGz9ZcRCRsLEWw-{ou9hq~yJc*d7kH`JEKDo#EuOQ^K^O|R`-T4$H|(8|Y0PSpHA z6HPEVeyizPex$F~p~-n%j7wK}e%)YO-rCMeAFYcX7M(aX7B|v7`6I)R#YQbh)aoH;J5V7k_=(&*g!2 zPczm%4V%(9r#~)4_s*TJqv?kFRF9fLpQa?g+uJvd@6Rj$qI%|FRhr`St!Qb7gz-tBdIlQ3j6^^G&T4+g5Hjy>+T6JvDMh``D2C z7LhsW&P)2@Oe!_2mj(2hbG1wTTZgueSO4CZIvlySG+BG9)o2@_-{2EqJW|k;=(_ic zX2*hxX_I`71qD5+b0_BRRn!gax?dQ)-g4U-9uxhbWL4Uu2m2%bO>|zZU0iLvIbYY3 S$8_sET$w(p^id4Loc|BIQ1^lW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/mellow_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/mellow_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..9fcbf7d749bbb0c9e04fe2196d2118de9cf8152e GIT binary patch literal 1519 zcmc(e{ZrIc6vi(m6K|s^3ri^jEXg~La%*ENK@fIXP+%8WWrPw~E@A63>XbDjOz|Sj zVnQQfm)S-jUV@p7T_&U&Yp7r-t_Bm8iDizGSdyhp>ezI9`1S|%WA}&Mx%Zs&oacPb zuED5J(v?P&XmW=vA4&)#gcBkNk;ry#U+ZFq+C)VsZ>m32)Kq#_<|91Mk{DT4An?S91l30F~OKrCPZW0 zIcI`1sSFGs2y?-NU{aYMwvf#w6Ou^<2WSBgcmMz<#)y~+L%=m`!WWF7Go+ynF;pWR zaXjD%&ZUA96QVKhLU5^&#lY}^u#j9Tps^P00pLLzXu%TjKnr-l0{}2FMucf-!8L5c z7mT1Yq@fKlR3ja6Jm5%WXF!Pw(HM8BtPuOh!m(kj6g$MyuqCVodjNQl23oKL4!A@y zcmMz<#)vQtEx3kF_<|91hBUMxhH9iEjt3m&m-s(?giGI?jDq}asd*WR8#g`R0Sn>x zR(hx6JAT>D^52Ab{Y^Z))@KfPjn{hx#1>BtcYoUCACcwEboFG^olh+LaLRw)TNP!o zU2UEz4^58BX%9BKyFO1o&u|R8dWq!p@9=kfE@Yp~Vkode6P_@bsFg5x54*PhD+OHIAx%f`qZ@jyIYGi>yG)k6AM(?8g+7~ z`Rc^UqzxYrKex-L^2=4#KYjMiSp4WGVI?~sed${D;@AuO)FHL*$E~)8lI@$1t~fM5 zn4f3gk~(kC{H5jHJf^!pyH($IxbI5i&&5lbwz%Y=9KXVAYwrXbZ58ffjW+OC*XytO zWXFeJOwUc|H|6?i7k{kxUu&IcP?@LpGzMET%}3Vn9V=}L(C;#BRTz8z7vof$zf0%5 z``b!KK-?qd-sYwBlgnsl#$4fARn1*1KTu~iHio3I_m6wNHGSeiS51M=)0*vE9Z`FO z24v@|^EE#>y=Eg!F-5(9T-Q~w9WAk8_8ZOa)j^$43>MT>dZqtSCbFCZ8atGJ#&Z_EKQGP4j@hU5{nV)W$J9_&u(?my=dh(rv zr)RnU+1TncGh<)3sdMLQOy9EK+v8l8_|#IOx$xEWGaY@7!U%0((9*Gi+Of*a$OZ4R zxKdY2O~cLiPOH*m)Bg;8dChoxnEhYI`sm9ID$BE%^%m>f-GM6mV(F1Jwb4Bdnz|Rm K^E^Drlm7q=?{(Dx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/mischivious_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/mischivious_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..3fb448978b7c826dd36df88850fe7c0434705e5a GIT binary patch literal 1799 zcmc&zYg3a)6y5}=AzTa~P*fBU3IfvLLKG=Z03%>ANC3G-1q>@pt%7Y49Iyok5Xw*) zQCvg;C0x985~_$DodO06@wJ1ZL%g(AM8#5UwQ6PB>GtscfPU?MNM`q(^PK0BM8&LK z8ItLPe9)h0_F#kvLKGnmA;#Y^Mg${@5r+}u%a|ZS5G9Bsi1FQ+B0>?Rh@*({!xD$dY!5qPi=K*CxF{PNJ znDMlrn{b$NnBy?xS;8=3m@>>U%y`lu0$2l0-~~irGpqt^0E200hdMmKp@eXRFkT@n zhC8K%qlEE-fd`Z+M>vi!UO&)+ZpsM92;=Plx4<6o0}KGgAQ3cy2w)8~ffo>g%>WJ9 z00z_04t02d!%@n3D?uSFhC9bm#ybmwfd`a1Mj3B3!~!{h@!&LA3tobG;1<{eet-d> z7$gE|zyj7l6LE>tOSLy819UZ5b}q>Az_FVGKA0|C5Q!b z0OP@Fuok=oJAfq&gCAf3Cf3u9TXTEi3gNC*@x)bW~a=+AXMFU7~FAsSA`C>n+3fSX<(2#~fV3Hurbs zJ+(ZN@?7KIbucGtyYw#&wRf0Y-{BNEF!9LYTD`xjJtL^<^>}>Omfs4eBVV76o#z{{ z%4ViJPUUYZRt`>$S~%3<;a%1t=cPTNMbny)rrp(6O9M3G+DVl@O`F@%eLd^xi$`?_ zU2lf9CL0w$WW+`8bzlDczC&!=TSI|OdfHu+y7)bpJ-VUQ?e9kvl*Wsv`clG;zwWy( z-!bHDwuX#<5E9-gUHske)~Vv0Det1GH`_ylcWdT(9o%y7;`u4l>f;S)eeK76gPn~y zE_GU{*jetZADfe0J*;_LDow=DYG zm%zO-TG!jGN{aiYzAU zkWlwUx!ahuNK)^7RwDA-=xeS;CUaGGgDB~lr_4{3Xh$vdWjB=J;f5!2ve{f)B2?cn zHks+|qpRa&rhy~HVuP1V7&PhDurcVDoJftwsnL`5G9zg`MACBF4?Eq>mhLFe0l}gEybu~HJ<9z~0S6iLWi17=#g}%zLc4SFZshP~yP#_$va`cQpH8E-DiMIQ^ zeHD^_!hBf1G|m`1+&#BBG*x*Zwn)**omkc3xvXwi`>4QF^M-bR=H1g05k_eRI$eJ@Wnx|a9o68E6$-7#;NkMXvAWdf(e(aH zX=Kyq9U0-qki3a+RO;xW{?V5Mmzr-^|7{)e>On($+#mk;-p-eG73l69_sAB<9dU^N z*(KzTMZR7=EB4R; literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/nerdy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/nerdy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..52718190454cefb26f8a40ca06092879b2d933b5 GIT binary patch literal 1559 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/sad_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/sad_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..b5509c8011b885e2cf08967d617945a297644fff GIT binary patch literal 1588 zcmc&z>r>QK7(NIjs55TtCa5sTV#109akLQ=bcGcNVp}dY7Ab|C#96ixCDMSIMAqdt zLjpQS76n8^?XtVfP-1?NKvy{w5{_#&j*v`RnvK(pnAYjx_Yd^3^I><+dEfVWpUZAa z+Q!xK??#eH@|esVN(du_6Cwza%AHceDB+X{N~BVzj4(zxBZ3jBbW=_kC!7<(iByKE zAWRT0h!8|7SX2@w3714jA{A&#fP_)>qKMnfVU%)81*KA1j5}kLGb$LB3J;VSr<_y4 zsZ?m8n+eJV6@p5IC5D-#Tv8#aR7gVvSc4{bfe1EZ6|ez@X|$t`2OQ3rU`#3su^4yG zncz$+g24l2E|?HZD*8bS-CQyunN;k6Td)UyzyK(QL}-Etum(-=0ugKmG_V1NX|$t` z2OPnS(`E<)>br=XP}H%_?WSefkfdT6NUYtS;MwA!F{T z1n1eFs44BO{dqUWnrB_zG3F}Wnx9ZV?W67~bG-BM)7;+M7n-(~v@LReQ8#wb)YvW@ z$1nBmKN+0F0u7tmXO(uZOc)x<|FLYRw@sJ*`}m5g7&iEM>-!6AIsS`T;>x-<7eD@2 z=68ELG82=}R9ffNY`8L4cfNRXyf|SvK=a%YYjB?0P&R0K)0&r9UOm*G@oec^#)xmq zZm#z<=Rd#aaoGNbIe{VVxq6lUqk&I44L(iQfzrDZdUv^J)U1u$olz6n-7{G`yDhTw zh1iSRef8G`E3m~}?g_8=zGf2*FFuG|TD#$qTWj(1nn}d>zY_WOfGYeod#bb3u+J0s z-Z{7GroSd)llhKqv>88_lZ= zE{^L8ub65Vu3I*ut=HJF89xU zhqsKZ)=>8ii*fH3OUh2mc~5AuG2}?x)YgYZ$BfU477nL)oAmvbd8-~Z-y)7vjo$|u zrmIS>S!cZ+)Z)l3mJ7R%nTrd%1_IK1zB;?qrQl+uNBOW8L0Z9~`Gq5%TK4_;IDV literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/sexy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/sexy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..a0ee4fab17c8276af043c637d6bb8be60db3cea1 GIT binary patch literal 1699 zcmc&zX-t$y7#?6(IRX(-C@6_rJXo}BWdf066sjB=MdT8UE}+Y-RUnX3JgJJTVDTt+ z3y$0>h(!%}m9`jV0a16VjiwZf*iyP^Y^_HctBH2{@TGtIyYpi=Gw=I8?{nb&ID&t z5eyzEbHRjQQqd1u=;o3M$)sWj+=4yu0|r1bBtjEJfHi1>7l>dppn(lAOrsrjJm3h< zrD7!%VlnPQaH%*8!Qg?ikX$N8BNpTU4>(fE3|2xR7UM3J2$4SmN5Y5{86q^KgjkRRjEB>(7GA;*u*5L@fB{ep zi69Luum(-=0ugKmG_V1NX|$t`2OQ;>_&QsTnM_^9BZcOC3NLGw!GG!Ngi z$LNgxO^D;)#LjU_Y+FOuZb#3+)z{h@yGtkdFR6)jzfx769vJw#xHqaV*!^vTYUk-` zq5B;!mvp`r{QiEOLtITn<1dEZ@{pkO`|=u%D&L})Vp`^BYvbxQx>U!#rsehFX>k*4 zHzygbF3z2fkEq&O>p81=$*FdKL#dl)lIn4Hh;`!0fQ==FWR2y3OGvY!!gArDSv#Zm zJ@e$o-D*F-f<=dK_a7K+p-s*ysSd@aCe5Unj*;(Ar(X^*+^*Rdf5xpOTX<8 zvrTuFpUKN{tC{!b6PI?=sKcP?!w0&X$9k?7hCS8(@oa%^SKV;I3F~n4}~+VOLkEyXx}S$_St?q!S8i@%EW`qAle*!qS&)~w-yrQ^&KeVuP!R}Dwn ze;qYs7n*s_vNWNm)KWe!^Vkm_&s|Ggoht0EuZtXL$*aqlezL8{!+*nikIjik4Ytoy z*-2ZaDs9+Sm7eP~dN@PBc$8-y+1p&TTJJMKNl+d9-wFD@wmdDjlsaF|$e+``w8YWP zE@QCF^=O~Y+eg1Ie#E-db7p+Y!-wvgZeQ={=#B_#zkhyF!l8`2x2K9D-n!I|GPSW% zJ9G1kX)o#MH6^&+wzx{qS>~Wgsq6ZB-TZ67X!2W?{{if=Jr;e{at@& z;7n%XX`j|yli2ao@Z7AB7;jztsjd3(34^2aV-7y}w$m_YOYuP7^Zdv+p>OUzvDQzm zRu2vzYi%+of9!jG)7|K^E52Nmpt@=_XQik&jW0@EUpTbz*|S~xwV%{R)Nbg%^dQ5l z@`CY7bWL*VkjW`?MpRmWYfFW5wYto{{F@<@hv!U7jD-cvE*n93pH5k)&N*+Xc=g!i l7o&>S+RRBQAN-r(#<2ub3`kJF3JI>POPf*kO06Q{{{V-x)l&cf literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/sick_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/sick_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..66395405259fcd25dc5dcd5bea3cf116c8ce33c4 GIT binary patch literal 1875 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 anSI$>%jE@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/sleepy_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/sleepy_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..b9cd27505c20f18268d52a2cdef304c9e1beba5e GIT binary patch literal 1578 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 N3obe6^~L})<6jVT+W7zg literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/red/stressed_sr.gif b/local/htdocs/img/mood/moonsis/stars/red/stressed_sr.gif new file mode 100755 index 0000000000000000000000000000000000000000..d4d4aebe321664d05cd2a01f0b45a7ac4c19e1f1 GIT binary patch literal 2853 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 YIY0e;!nsV#lk4)Cd}UIHrG<9>50I+H3IG5A literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/achy_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/achy_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..1f724e4459310605fa715f2dc18f7874aca58ae8 GIT binary patch literal 792 zcmZ?wbhEHb)L_tHxXb_o|NsAIuw?lB?e70S44*$WUD?5toSdwwsVN~Lap1s#Z$EB- zdf)ovfi_qzgW`W~Ki808XU70nBRvCVMxdzTzk?YiB?VUc`sL;2dPOBU#rbI^ddc~@ z`iXg&xrynS$@*Me&PAz-C8;S2<(VZJ3XV{51$R$3g)jv}JtHHoq)LUL%=C;Bg_3*) zpVYJxgK&i;S9EoH)flPYAoZzA80i=Y|cTigN?5bF(nr zK4~m{g(1nOv9Y2uT)4olKC9QKvfbIzxTm?*QKhXax67z#2IF*wg%iyEJ?E=VST(z5 z`4nab-PN1g*Dd!9nXr4?TzRj|_=z0*WWA=%TsmpTPKTx$v#O3N$A#sv?O{8zBREr= zDP4Q_Y5(a?bEG*RwOR<~CVXzU=Ukod{Q!oLVm9~Mo;$ny#4Uj_~VyPpTE9-sVc}|4FHfxM`8c~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/angelic_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/angelic_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..a6079e582b5d8f6e7bd89a787ac2d1256507f9ab GIT binary patch literal 1902 zcmc&z=~Giz6u+qf1jJG_jzFTagP;Nr7|`N?CJ<4SO;&MOk_!?Y6%?c@WeJKPOJwt+ zC>0P0izu49PzwqQ`hp;`*r}FcOG}g)9V=El`g(YOK)?2WfVuaa^E7}w!A@%LB@oP=ru4 zp%|7HbYq$#G)2=C!?J{7%us}(Xog}~(jWp@15MxsL|`+l0&D<-X=sN!Jis9s(-#o zKm#^_!8Ei(9UkD&gfOg?pb!?rou&!HItzk<2b5`sFs#uK3*-RCgVSIwcnRi#TVN0P z0S16#kO-s!3s?h9-~~irGe842fWb7hLmeLAFl=UEB`Ac&aA(*EA%6%Q5{5`2LkJC0 zf>Iapv>I?KRyw^B1k$(bxXn-Q$K9 zerLs(Cu&znvs>&s_WO(E#YVb4K1OG{gv+ej93vdXB?`WKc(`ti`eBZXL0hLPF4wzq zHFc9aX=J0~b%d7KUjO1Ndtr76zeihAQR^!^&@RbWPdkLJ*J%?z(Nj1Gt@PqvILemz z3HjpPJonj`u2+Jl*Lp^U_HwevadgK`ZTsUl;vZi5n4cK>Q+dbYb)qQe*ABwmhjRX# z#^kVwA;~qPqoaGn8ph5InA>&CShR!-c&m4NPd#WW2<%Aeeem}8=g!O3-}r0WU+}FO zso{5brt1D&`Ga|!uE71(q?LZN-HGxKd8f0gKdaXI3lw9CvcS}Hf>WQWrk~5=qZZ7_ z`V|42E?s*q_W$EmQCT2KQ)$hXB@P>e7)K0ig)Ma(i_ykFFknD}9ZWN_ExnY6+*??VZ{rfgMkM|NbEyXd<}Biss3dhHCaE_7GA5(k;V zRE7M@^^f^FCEoGp^7U5b6>8n>pFJ;^8YXhmL!3iMjI74ebd${8{6*}0k%Ux8`z&or ztb-OWP5w09mBncpnUX3NIvK}oc~p2c`#dec4W-wn_jT^r>ntJ#eH81N|Ot2 z;XMQS^~$B3A;dz?Mv?mT|L5I Gb^ih}oH+CV literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/angry_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/angry_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..955ea2ff4d3dc46644c0235089add494757032d2 GIT binary patch literal 1562 zcmc&zYfzL`7(R^ix?L@Auy1r4USAD0=q0A z0?Kd%1+g?yG%jm_jw6EQ386}8PBoBG zHxrZ#Dg>1ZOAIqfxuil;sgQ;Uum(-=0ugM+DqsT)(`ZK>4>+7L!I)GOVlnQVGr^fu z1cL|4TreS+RP=)uy18URGO5@Bw_p$afB{epiO>WQU=5n!1tQoCXkY^j(`ZK>4>*Ez zsaOexSd6<6Tq@2&FnFLWB$tZOhy^*ocsLDf;U&z2Td)UyzyK(QM34p+Sc4{bfe1DO z8rT5CG}=+e1CCTOgOyN-#kfl)LgbIYkuV}fh6oKQAr|BSO_)3w5tAD-KWm9O0on`8fv3$6vV98Ru-fy}s z40bLKn>Bg9KL=K|pXHj$fnaBmuuiCvOr6{`I-tYNT z=jh3zlMe069~pg^n_tDH)r)^OX8u_2zGt;X;;zW1^RLxqXXyv7EN$4jto#35 zeBQ6Vwew@=&S$+{?*yzKToq^5wd^`)p6}+gJ!ip$XXhqG%ueJSS@mFG)31Y_j|zWCn`y~t(-_8bzneLeH9!)oAGa`@ve^)nJ{ar&Up;+I`!%5A~W;#W%y$VYM3uO28+AwYss$b}%>J{}yy2n-`JjG`OE9mg>O$4DHb zXdV#835*~xlE5gM7G&cjMvxduVie61ig5}fD2${qiY5&rfHlwrUO)soLo2`rFsO!f zh{FRM0>?=lr)Y)H814jtlLSuDf`JEw2@)qsoTBvuEyyM)oTPAywgcP(d%zDc02G5n z&;%lYHP8fJKmg&HxSA00z~N4sm#ZL(ww>D?uSNhC4-% z5atg9hY7<-VTLd?m=cTy<^aZn(_k%l33dQWC*gL=m?kBwFIT+K0&i3j8Hwvmp2veWdg8GePVRh{1M}bvE^t zu&upPJ!(&xm$SRV2TiQRJclu_6@z#Cj4D>xIGA(`WG!ONB!1A<>Sc2O>I5UgxKP)x z&B<}u*>oV6Q@N&c*Xb7D8j({|z=}K9#M-8ARn~0PiFT!(>g>?Mn4{F?pekcQ zahZF;x2Y*Or)+4t+B$zEqPKj$#j0kdCiig1)hD-rg)*kLxb82@ zmmF<~Gu3m0`*i#M@%C?lUp3t}eSB*1)_s(IBu!p=w&;41>wsUy_XTQUhIne&-g^C0 zec_7<_pzeihngB>8lHhI_)IM;7ior74WeJTy%X}$p(%Tm(D_uR)³HT$$YLQXi zV4t7YzPnET%?Ep*6o2yL<-7dNBZ90dkxDr(mpw1DFk4D0l&5UHSav!klanU8pqXqVcvyFMn}?Wnq{} zxFS@_i^T`<4*5U5z zpqJ|O4t-}y(>q6-|LA?=y!7eW1wJO;oL|>OTKJ_h+2u^DT)%3j*`aEoDnP|ytbG+P zyunV|(i<`v#ypok)@hV_+bnoNsW{ECv7|o+*8lz(Ecqt&R;!vNrA1oyH^X&X?YxWD zSIr0qs$@Gnx}0y=s^cRQwA$1gzsD9z>S-H-gv zyDHLB`Z(fEwv*l2x@2oS_M$DWJJeggVN@*A8fF^fMZKBHk%Ga4xgtVpn;?s4oMc_e zIbVA4rDDIWcYjj#cig~z7D>ytw|`Y;BL7L0R1ui9D#FLj|5D|{AkOnQ-9fE zpAkVuMYoTAb4k`F*?Gj^ z{Mu(vGS?XorTbi9#makZ!X|U4j#Q}jrW!>*+{_$%WvR>vG37_Jbxn`Q8YlH}Y&f4k zvOkc$($Jb@)D~ZRZqvFpll+=zuFp>&8p^Ew^609?^N#BsqR&P}sRrCbj<)$H?$$Ig z!p=@Tv+#^)cemT;lh_ihOZTzCvl;!N=VA1KU!jwyUMD;A^LRSTWfv@dX50MN ae(pC7qI=)}-~0bu z^Z$Q_|3FMSQ2fvB=Nc01>=@u`q-Vg)2sAo(i%4uBV`YrWeZ^k@d z&z0Rjf7isx`wnE??3i?}Ff5_Y>@e%uw0I6P#`H&5?@sNR7sK?1m-U@yo5x4x?QcBO zK6CA3lFyoD0|KE*tqDZEQ?W=ibLVz<2{1*T~joKo*dOx1cnMI zP;5{Gg%_B#TMon zx^9I@QyT*JrquZFx{#e$ZO>-EpY_D`R89xRoICZs*{!$tFfcvqIoaHGYmd^~XRIIl z-?5gcS^jx-GT^hv@hQz5!dfvani>wb^9wr7;h4yAv|Cg+spP~3Hx5WZ=%NP1Q$#?3 zQ%8Oxw~;UN(ZV~HvE9#|6}TK1c2yY26`m43aNXqAq`<(OssM{#-XmsQn?v_!L^HOh ze&p&f{&hQG{cZ0b=FgreOErXBR~2(`W;8T4mxgyW3qrtD# zAu^x6b9v|DNdA~*D^_-|_VJxDZIT)D96g`fiIW!Xa<+?`wr}}HueE+X+NA>y0Oaj&brWxD( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/blank_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/blank_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..319bf68f801b8fc1806690523a6b9fb87b35e52a GIT binary patch literal 1508 zcmc(e|4-Fb7{?C@K~w575EOwc0Y=%(I0Iu6g9Ppcf*~LRl3m#KNCTTFkg{0uMZE?H zq9i9+l7P|;0tUH>(*nW(4dJLh?x_w#;U&%K)9 zptrme-HAJSN|p~Lgb~6C5rjzPPAOrOa7qLvQVCN=7$ck!!H86{DJP5*&WYeeD#cU~ zCI}Zq2qG0NDhZQ>OCltZiZmrqLMd_)#BKR7N;##1QmHh?oiWN86^u&72f~a~&Z*#3 zDz=c#1m%JXL8amn#Y|EzsgP7ErZEIu!zO&e2s)z`v>}FSq$7?89L|_vOezziG47l* z!I@MBh7W|fU_vmd%nw`0=8_4?q=EyqfCoGP02546%G_>FvHsK3K z&>7Ouh8U`mjyN80q_Q)h#Dr*!yHr+){bS+SFjk5kVrkeC)`C3%JV*mASON!Jq8K~? z02539Syo2uILEUaHk=x+L|^O(vdq*B{_E--i4Bk6LtYMuE?hmh1s z!_A5Ml=Z=du5qf0BXKQG4P#BEwSL97lS&Wk69dCOAJ$z?$DYkt6Lfu zC%4-2ITxV`v$lG#x@=l=R%4gdI_o}F?XlM}ZQn?G{;rajowH6aCSQne3m7<%u{C!^ z*d_hrFB_g&oP1Xk?>J|+)@v-b{Um0rMbLXh2pG}Ku{qS=9 zwZi!c&#O&##aGwZu+(9P=%1%bDBF4ETy}i=TI&J(AHyskEos{(27AlWw!D!YSrikX zZu#k<_m#;AuC@%-n|_dZX}hs1XaDzc9e@7y(7f5d&*`J}7oYs0sXQB7_H3YV;}2%< ze{5eCQx#^hq3&+(stx+CJk>kpx_p};ZRC+P@rM$RzT}m>-A}=5_Fs7YQ&r90l?x?# zW-q$AM%EaLI=_pv3r-##UZ#3`$Y*?WX-&rowPV>~{g_|q8T018k;UYq>Vhq4&l&0- zeNi8fQsQerXK)WU*zSECZDhvY0^1nB(cys(m#_6%y*4uk`wUjLZ$6*h({9}5sh!yL z_VpY$O{1^6EUo6i`CcRIKS6p2lKMN36PNol+S#tc1j}PP`27AI?HSIe9*i8E8*Scm z!*};gQ%bK!Z>m23OJVbV$&U*#uhwnKh>!X`?{V^S2UZ9 zsdOp+hWmZfrBUO7uD|5`i`VPk-8@y$Le*-Um}IkjTc%CSv(LPzJGL(5kPeKu{sZ6u Bj!OUl literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/bored_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/bored_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..0bc44d4f9eed7d42188276c8bff3fc30558bc096 GIT binary patch literal 1484 zcmc&z>r>QK7(OU0i-K|8(vgH&VRjf`&|@MK5!52LBDsWuRBG#KMTQBH8jA|pfwn;i zGOz=T+-!gqixn|0p$TGK&em8HFv&E?n8h+<7e~ORJU#sWfj)LV?9Msw`#$e;*^Nus zy({9Nj_AlTSv`~xMhGWF5F(X3rG!z!DG`)NrA!%NjBrK-BU0(6oG?x}CxR2H3{ydv zAY2e3h*YqsBuo-6iI7Ap(3AiPqv%Bux7EWa<&+9arLq`z#wcf0Fe()uC^Jqur-DM;#A1oH4M;#A1 zf^(@@358gUyAWI|&O$JFpe!VpiqVJ#Ily>04Qt^g%!6C72Y$c+D27Ck1{PR@CU}7e zHUk>i0K+ueQO5(0R5F8=P>992OC>_&kHC>IB1MJ>4JjcOW9QZy*a+S`Kn3n6_h>J-7@mNyEd^g-r71^;cY!KYu@I+b3+fyoZGWz z|JSCO;OvI`#>(rboSx1p(yMN^oepz4w7%aO;C#wA{O*@i7Y?_^Y4eUXcGQ^4s&{Ou z&A(Wl)A~em!hF%njbUwF>~wsHMYUk|NZv~dSFE~?pYEJo$}Z5HFY9$ntMZv#&e^9w z{%zH@$?ipM|5HC~^~`$HFm5g%Jv3Ne`I{lPFv57)o^HQB&=j{T(AB!wI}l@MmztO6 zzp1vo+7sx;M-uCbD$YEg)Ufz{T(O6(XmB8We@B18xrdqg9rG4#+hm^2`-}8;Ree?P znUtUx{dx)`KbyIHbLE+a))QXWGKM=3+*{X>6L3EN?>i@xJl5I9uUtWXo`%t4N6)cW zO4OQ}lv3BAz5}MUs(mTZil0vZYeecIcerJ?NVe#T|nIDQE%Jb&ZP!y9MBdYyZG4N zyPNd-g_p%xZFgesboWBp$;wdY-q69QRIi%6U%vXJDeJk2<*uK4TFUHtm%d&npQFz2 z8Ge2v(B5VBt=D&6u-vxPh1?GP;7?;}EwyDme!06Nz3E8Ez|>#I>+T5nOG9BBI2$iHe{`!}Q}%Okeuar_RG}X3ja^`7XQB zF}lDY<5IGeJSH=T62b`Kga|^Ua;KCqN;oBg5~-9aBa9Kwh+sr2-INo?3Fky`B9&n( z2or=0A_S2N7L|la!X*)sNClb_AYl}}DB?DA7^R$2L8(+0!L3uo4Qf7bdKB}QruQU1OwXW4*)$J5#N zw)kE#Lucl1LhPoAjh#l{@EXarYgBJCHyE|KvlcrU#v9V3Oe)WWX7dB1Zohk^>gN-y z3e6?tUgz>;^=eB<3CcI zG_hr$njZh^*1hqSj71l$FMWBzv2o+deddO-?t?z`)$)b@ksTHDDq^0Pgy-cNcZV?h z>;5e{)=k}U?p8X|VVa*8XLh}RuXfHvm(F$fst*TSg3@a)?rfSE?kt$o+4KC|o%tmj zmULzrhdkHjsEUkfP3=vOz8IX>+tbnZe9GKZe=?@Ir#z!K_)zMA)6VuW|9o}6VY8<4 z_=a7jl_O@i@Ra+D)+`Uab4dGk)Rf(4J0A2V?zT;TBWaJr#ntbBkm->WQRMvB>~vG! zwaJYUN%qaRb~sz~p3&aJCq_#`T*gLALoH86%fjyIZymFy(1{+gKT>2>-A9!UkU zRmJPZn@(FCd5P{xhUf^BUrzki}6(`xGPIumUg+P~zxA9eKZxb;+POX#zw zQ?>sjQ=2*vw)*oI$s9a>H7)hcgd)!zV$^Q^>FmveJDl4mhdixg7jI})E~alITzoS} z@_%qFGT6HnW|b$$Ub9V%uq$#-kEX@eAw$4**Np88#>_|b$+MRoEqlu=;CA`iY18em SBVE+a724os$HHxFNXXxA_PcTb literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/confused_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/confused_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9a52be01285a76d615c71bf469668df10e9f5009 GIT binary patch literal 1626 zcmc&zYfzL`7(SRFs30h=vV+KS@d9Yb5n9GVQSO+d0viwzq8xV$EeyykC*`861}L%M zfnYGf3oOQ>RN~|WB%z!%NMSWKs8PmJM{@|7nobYj@BVjw?9Msw`#$e;*^P{j&<1Z> zL>7@TGI1y&j1W$UAVey6N(rNcQz9slN|`dk7~zZvMx@eBIbob|P6Q`X8K#0TLAW47 z5UF5MNth&D5+R9HpeX?oM$wBRZWD)5$|)6;N@X$bj8V?0U{oqRP-dKRP6ek@p@nWH zC>K-+DixL(W|DGAg``p;4G~}sn&1T@*o;-c1{kK%jyfK2IAek_sVKx^+&O20GpPs$ z50trJLNKZ52Q74S$%JH5u>)?w9{2$RpcoRN2_nE6G{Fl*uo=+61{kK%jyfK21m{w* z5(=>xcOke`oP}WUKv_sG6{8Uga)9x08rH%~mi0K+ueQO5(0@=N?5J~VRLy72h8HKFUn1D5)~UxVn{+ccXt24)+L1+y2Y754NUj3`u3*>%pg-=kxn zoyMnJo9)?E@nXXH@+k9(Xyg1D+w0H&$hxa%%(Jl{Z_QYJ+}gbOQuhY;Uhdp9YFhA# zdys=lTb};gAMP8DI5>IC-kCelX7cjNn{7w+;dP`X>1g2ZeQF2GK<#zkewNVcdgg}r zv!2eWCtjV?8Xw-~8`PdVXldJ%xa^I6&YPC*{;;@ZB+}DuTgXk-@rZ`R2e(p}B<*l9 zB^&b-4m@crip&k){6U!Zh`OOJ^5buIY0U`^O_v|0olQA+=T7JTxS*^4j~@jz^=ix3 z?ks-$Lf_f%bdU8_E%{jsP;k`567FztQT2(2!OPSi?l+vt`D3=RPs(Cu6n5a$r zo15>ur+JiRR;cqdlU~=U)B_&5rLW}QQ75_7#p_fiZH=LK+sUrImh!rxgDcfjQgw5? zy)(-^{kY~$Ro0EqHu^q!t-%x&2XtKaFiTNq=1`GIpy&ea1WwUwDYC)ej) zba7OowGQ~tXzMx(Y-jnT^t2oc&2lscfBO7zfwhCT*T#B7aaUW?oM`=Ri(_?B(%`_$ zzxbEccb3ebXMBIl@T%C#Ddz8Qjq8h#A9^W!lHt^|DpS~7heOm)4U5(pR9i>m8(HI( zLn_^>+m^mg&(m9~l5-22M+{D?Wj4DncQjgB6M8FB-&HM%ElJz`=j|174KV?^k>s8} zyRphpdfjVv%2-CknWBV@3qfBlzSr)0z5U@Wnvr@fKX7H+(f)@wzup=??M85K^3b3v z-sJta+4vJbefDaezP0VjSB{nU@21YY=T{#iZ7%-h++eCL=}#+cZX18v749AM>r_P1DEB*yUmbpg& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/dirty_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/dirty_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d766e33a11d042f7de09077362c6c11e52cc56fc GIT binary patch literal 1817 zcmc&zX;YI|6ut<7ut*bDBhiLU8HiMQjRHzb1QHf?3W7u=DoburaEd7)>Y$)RgQP4f z%XLs$gi5Oz6|G9!0R;qo)l$Vqw9eRqLIrh3+G?xb9^OCDkG&s~x%Zs&oM%atQHsEz z6d&Y+{z6lSK?oy65MmLc+?`<%W)NWz%OJ{?8H_MS1S1wB%5^gYVS)%jEJ2hTW>|z- zL|DYKh;mpAMVKN&5la!}pcw>6Fbcg;gxl1?3_}=(Wf;mWhC9X#!3>KT%JG0QCJZ4A zOBl-0f^N(*gk@Nkp&UyX#*`tHVJSm7(jWp@15MxsL|`+l0&D<-X=sN!Jis9svlvrO zAuNVFA($nYa)N;elnIMj7E?|?(1LD4F-tM!>;SjG9`FMU0L35?G=T_U4K#rl5P{7A z4cGt%)6foec!0waLOClzAuNVF%M!{t3xa_MlvzqBXEekDIe_utG*}B>f_dN;*aLom z0iYNp0%^bk)<6?@0TI{?(0~nKFb(ZchX**6%M7dpg|Hazl#3AZhrl6Wh!iq}&>$s< z1#$r6!D+A-yaYRdB@BZfU;rovi9i~#fHlwrUO)sk12kX*7)(Pu)ZqaR_e=aAKHRD8 z%82+?Ve(HS0{rKjn*jy)Hx|}Q;afUIXX7H=~pOgLVXkS!}+U*m+MU0 zQ4-N&d!uH$`MZVr3o`20lwVezX>@Fj)XkB#g)W?|tnycD$GuDk$6~UA%?k?JTWlMR z<-uhdy@T66zhsr#?165=Ghp@XHGP#~Pm_;YO#C{%y{6Rlg8rUYT-cKVz9a}|OSYJP z@9ik~CvS4e_M0POmq5cjzn}b7O3mB05~*7(5!V)}YH$3Vc3oWcbDvJSSgEpiS#4mq zy9AA8n(i5UEDO5z;>5s1ofjTv$va%$kL0y~ocfmU7i6D5{yfO*b>{G%in+HNUatHz z{gwF!UWCgxYhLj(y7Ce)wO1(QzgSe|*d^tu?WGT`gu8>ryLvn|fma6BSF7bS5**!U z=+n;jD`w!-gyNghlNCbZ+1it@b`2;_7!3Ez+rnGhD(Vz!g9Uq&T>YF(2ct~kgFM5~ zM6rvNxMFTtrR7eiRjDn__tI0nB%i76y__xd{dXRKtPc2}@d+>y^MH;p!+<;|mwdYksqCWEET*zwBf=&|@OJ!T5H;CcTQ zygW;A#@%jszIy~Rx7-VUA0BGD=1(1~S@{ky$CSeKqFSX&l)PLN9; zYa1gD^O-#B_Ldk|zga1Z>@4nXkYuSRjUIP&%gaQo>l_T1awXkg6G zgZsDW4CRW`lI`KW*PCR?ZNnzhnWtAu7in^crpHF)koo+Pw>-C7?-!u0c=^n6#JMS_ zW5bSiV)yiRrg-c97&0$fr28--q3)tgEeTQ#_oZ~b7^)EapC%oa9_q`2XT48i-du>v z5^H^W^QN!Od}30Fk2G8@yw+w4^Y}Jn*Bs3h0P`91(`@~rJA3QD3wOrL%l>0#LW3m(7iu@5Pa~smE z{Zr0OvkGSS)^C2*zi@bFiLvikqFHulQQCRUHRl4ajFR+?f~wHEnz$bhRY!RjOjae) zciwlDMWaFoiMz&m{o!5reY}qCdT;G;WG)Ya*U$NSw9#-&WopvNq6NnfDTXqdYol#Y NOZBG98KDR*`4{kw{%imM literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/drunk_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/drunk_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ce7273591de2669fbddae48499900b6f1c10034f GIT binary patch literal 1671 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 C2>%cO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/exhausted_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/exhausted_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ad88d564fd093716b2d699d6eba42f657d5cbf3e GIT binary patch literal 1542 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 WSn$tZjaNJTZ+G~WvH!)#VcnlY_gYE- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/happy_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/happy_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..00fbf834e68fcbbf4b061baa57a24e2bef695ffe GIT binary patch literal 2219 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/indescribable_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/indescribable_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9ec1c5f90dfbc87e2db32eebd6c678475ec96fbe GIT binary patch literal 559 zcmZ?wbhEHb)L_tHxXb_smJFZ2-TnWE;q#}aD?50SlanA8BZ#p|=XSrs1i z#wRK%c`~&s%vpJBqn@M4#x)n4Y8UU~J#cmN%pyn6jEK*IY%Qq*DOy(RmoagjOcdn^ zyM4)ABBfFJTId^=38#-=Er0v%>gj?xHT$;R{$QXLSDWKsnbD*co?6=07#y0y5Ky1i z5$sYixnf#Or%P=m`@Bru#NLJ~PoG4;IjgMJ*hQ+%Nn1Q4OpP&QYr~RQzkUXeeQ5`r z-1@zavKE}MJ{v865E^8y|DA`!R|es;#W({xhty+^y_2m%UhCa zYTH>#U7PZHmDB8EbEi~Ii-@Y^VW^zyt`^8uxp>JuRU6yVin;84@}?bg=5Cb>j1OM3 zTh}Z&QGZF*mWUvGR>sI*vn|`CWM)T>i=~|cHc)b7c f@zZBvwr}6RzyI<3hw-2PfB!IUabNGk!e9*m){^z& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/indifferent_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/indifferent_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6ef1abdb9cdd4604b4ed2ba4823aafe40d667419 GIT binary patch literal 577 zcmZ?wbhEHbRAJCy*v!iS0+tLC5)zu4n#sw@*Y*;!@$d+15yJrmVxELhLfJF_gcI@Yy87OJ;))E z>*0;597W4k9aCxxJn+%f-4I4TaVE+V%cC4EYS5E$LBm^$OLKQ~M27 zSveRqrpzhMnBi2tWWj_wr^+HV=H*7SLOhad*2%3b_g+#PxIH3mDeKxjacYb~YP+_I zb$Pe)&N)$hO0v%U7@8ynXln!^cmCEMLE|y#M~| z>zm*I-v0Y>_Ou`)$kVK7o_+@N^zQ!&6^tqhWey9up3Pj!v1!{nR^_(93tvl~TZQ#A zbv)$T8M{8@h~$Kwt&N;YE0Zi=2(QrEP@zBd;7-XxCnaBw;#HZ;=CHa| z1H$RyR*Pa&rw_lspx-(lb~E$7@AE##uCJfk&E4os zoXI;fb|@i?5Kf37L@IYm38RElA}EncnKHr{;fx4Iq|!|}VVrPI1Se7%rh+g*xFA9h zsbEn_m?T^hA&FF=DFG5j(TgH(V~0`7DHW7TWijrIQO>AfR4P1BW}I?P1*cM>g>EJ& z7gPu;6_yxgl5$Cfq*5Ub5nv6P-~}Ssj8(t}7^cyVIv#L1V}dcMD8ypiIcI`1sR#xS zl(}F+FsbMVEp&6qgk(~&18%_{_yGf;7!sigBET9n!3#vN8PLE67^cyVIv#KY=Tfl} z3b7b>A-GhWg<$YNSx7DwqY(>ofbnn|*1}7e2e)7k{D1*a42d8OEU*Sm@B$HR1~jk% zhH12;jt3m6WCkmt5Q}k_N`%NCfg@o=iVP7NQbH`q0mj2=SPL&<2Uuble!u`IhD4AC z7FdHOc!3Bu0~*)>!!+7a#{-V?OZ*=`9OR@xpAfB=N05)p(&c6*px`h%&e8+li^u4U z{Y{9)M`B`OzoFs8^}QA|7H)ML4sq6+2K;m(@j&IR%*vNHbKA_<*Q#bY7@A@icGsvr z^{DVp*;ehNnmbhQ{e@-q#_ZIsWu2XE>ikf0O^U)L>Kl`-+d+j6~2{^I&wi$hxx zOnBpc(}x$A=0*;dZ|JOQ&sVPrw%XFKZTfQd3`0?DVo0mkMg8vTkxjfg$3oSvI{8(1 zU9Nk5T2@(qpLa`7)12#-2~WCCUr2C$6}#Iu{z}yx-R{wXs9P7Uhq5nkej6X()8PKi zv9*`FpIIF}cHZIg(KS1NEZOJT+M?>%G1PF^Jn-+UACpIae|6^GRol^=+Iy$=PuAyG zyYhs)woVTt_jZkROfCjHcdqWpCI^U*%vt+wk^ zb2=w(3MhNx+4ovq5w@)T{lh#F-qK_AD%n-F$NR6DcIg|O>Yf(*yZRlm4pQ636b0)R z#1!gSiestXb0E6V#AGb5@&75W0kZ-JkNBAv9IayJ2ikv5JRjsH&M)@K=ylujD9E$Q zLtE+kz}8YzT>2>`hMFos87zLVLU0PWA^^Z*yPx zrsGD&X;ZJzmHN-71ZMZLy0oVDE=>ao3~2TXF1nEycm6v~Q}$5RwEW@e^E57p!?R|F z{t!91d2&?Eq9yg$oExmW0!~b?X&R1Q!LQ}dHb$u;voxjaqQ1TS{o@t=U59=14cfjY zZRRl@=z zbKhoNWX#5)PeS##-Hx{oyy;(drd4+(ec+GR`GesvzwR9V)84;yuEsCC&Dzj=q@iN` zF2AxeU9Zvm=cLKctGf+HD%vyB3PW@5>l4mJ6LrD8#@(W9kJzk$wsqr<|aY9scOgCc@gQEaiv{*{9Om076qvnJSz^-#W|MfqU%mshwd1N TDGg3v@Vq!OGv!nfl2iQ)SpwD- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/mellow_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/mellow_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..22c1bc298cac362483e33239126a3986983b14c9 GIT binary patch literal 1514 zcmc(e|4-Fb7{?D9NLt1!0vZDer$kU9l`v(5F~S)Uj7TM$a>6*_oCr>&QcMM5 zf^b2EAX3qyk}yfQBtjCYNK*nOlp+^F+{}kj$|)6;N~JOGj8V?0U{oqT5N4cmP6ek@ zv4w0VC>K-+DixO~W|DGAg``q3jUnI~HsK3K&>5|u4KY+B9dSJ1aK;245sCJX`BunAuum^w#X`ls5zymGd0S^Gc#268#p#|5l312XR z&X9&S#88cN#PNV5m7M`4CPZW0rLsco9}CBZu~O_1OT(717VH7wK^kbm5;))z#oz$| zm>46%G_>FvHsK3K&>7Ouh8U`mjyN80lwaci@ZlskL}?S^-wTY<`n=`6)&drsp1ts5 zAilSo?U?^2#QHh0uyzRTZ0swse$_pBu(RoUnT>OJeP~y+w%Fv8_T!+9{kjbf;W;z< zk>A_1w}n-@B-(skns|AuajLVXE#S;}T1{a_sy6bxDdk48^JxE_FEu5HBU)!wqan^) zUE69Gokd7wc}G~QUB;bCmA|gQb}4o<*Xw;B`ZaroR@?Xwecm14B7*YAySMb6U=v-L zJ-^-FUEnp?vVI_~C}E$a??&up^PG1-wA8UMOaBY>H?SX?$C2E%C6sF0);#9UZ&aFvnVPS@B`CpI&b8Nc& z>YrAXSZ;K6iEGuLy55ucT3FVE$;@_qZ11#pO>6&Y$1UdyGo}I}zFOCH`N1JrB`P@NiZaY%7axqN9hy@1J!mzp5UO z+U}mcP^bU2+QX~-=u=J55wD@)-9=5qv+kZTn&XB;tD_64p@dI6umn!Sm6V`8Dm@IzDSAl%c3^}V5kVB`6HTi=nW%l9v_y9uo F{0n}xj9vf$ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/mischivious_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/mischivious_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe17a2d247ed1830c7891f263f1fc14fa3290fef GIT binary patch literal 1742 zcmc&zX-||_6uu)+5DSh0iP8Z^7C{!Zyntg0$|4Nl(s9YKuZ0&7LMb{?>XJ%Pk$`k? zpkA>A8H*cZz=f7B7J^o+S7i(WE@_|w+B8^-OKqF>_Tl{j{o4CsCik9mp7Sg->bMxy z$}At^Lw+YSM<7Hbgc8CC;nH0Yh$s*$5GD{Vl?9QABB3H-BH>cEK#52RrG!z!rD1^) zkrB!WV}wgs0w*FTloQ4Ym!Jg#B#fdLMcihNC_UzG47%$P*Gr_z$G3ii&UUg zU{v4|Ep&@apiE#);1Wv=i(H^wU|ir5X@~%8&;&0K!Dg%iHo!2AcGU5JLq(B^B9|0m zG47O#jEYKE!YD;U;q?DA~Zn+Sc4{bfe1DO8rT5C zG}=+e0}i8VnGft9!|qrcnS017VLo^FaU}n5u||y z)}RSqAcD<+1~$Mjjds-WfWxKCU?mh{G45Q75cwl;B#cOrAwok+hy^*ocsLDf;U(+< zOANyg7y!kP2-3g;YtRHQ5W!|Z0~=tNMmy?wz>$85|HH>3K4(Mpmd#NSn&`l#%PnM} zu;>rV*@5`>pP@7JHz79v5Sfi4w!OLMV;cwGR8pkPouRBzdt1NO7(^8&ST7=XJ1!q%l^n7j%to2uPJ8gNY zDZ1FQD*18jSiE6_l~&QbS=$nv;a0P=LZ7WAj#0OdISx1DCfP z$_Y<)?>glcxi51pBV$*6R!ZD(n?{*u?Y{k1{6G>}v)3)IPnI*^x58Dfu+$8xhYj+( z+vaAC&HB*W^+j4)g56Y$y3fV2&(`ndP`Pqw?6i?AFm>DdMc5uv>K82O>JQdx1`J26 zX`WSWKzrnPH-1!x~TV~-| zme*9)G~4HRp6^1rl&{r)=G)hPqW7TOBi^9O{OPJ}et>;@w!BeYWc7BkWoB-;vV2&T zIHH;58CSh9xY+S%>EPvh&+s?OS8h_?F${@e$-OeqJ540heq?!});+k^zfDs$@PrhF z>_5M7tL&j!?`9pe=g-sCMzx1)){A_z@rTx0g(>cm?%81dru&iW3P$z)7or|Flv(O- zRrdO&JR6rEWyV_FYWuLz@+kASd#s0Cs`3lpyHvSs_1N0i9b>_jtFn#9hsX2l_jRQ8 zI_(O{y;Wihg#(c*idK^sfW_DSp03LRcLt9`9hpY4!$WV>khnL6rZ z#io;wcD$MN!HCD!Pky+I=!*XYCd7SC3~m=}j6P n|1{&()vAh=!`2ft^Oa+tA-|KhM&J5b)!LYzz9c7{kazwCLB`!? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/nerdy_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/nerdy_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..c2cf901a65b8929d5956b7dbe3432cbc50b578d3 GIT binary patch literal 1518 zcmc(e{ZG?Z6vi)O0#0ScL79lWq_R{ToAkyC4qQ=6DMTFD87Yhj!3zeWd&9`kxloWQ zYJm;6i^fP-BQL@rZpt={0p}*&bq*oWIJba;E;GY0r_-41?&o6UGVWL~tUN zVk!s|gbN}Bk%|_Tgh|3B5t2wnni43X6uAiE<~@v3PN|?&DvfbxjB-W=qf+sKFyoYS zDmayjEo3u6xu8N&sklTjlaxy;B$bM33<1}$312XR&S(W~h@l$kh~oi=GbR|5%7kc) zJLgPrCY6EV17R+h5KJob!xpl+WI{5j-~cV)0S^Gc#267XVFe zluy}zx^=oN%6xEXuIgxQ?wN?L$)2W@2FG|&Q)O|Xas3g`mhbX4BZF5DgxLx*UAKcq zOqz(8lb_CNglYZ$ZnG<-`0Bx+Wb3Zr``L@Q-LC&7(HWQCs7iM4PJN+Wr0)Fr@PvWR zc+Plkch3#qyj*`i$`Kn}zw)g`rX2r~=E`07#(N?)Z(h_V+-kX^3B2%nf5NiD!Pb)z z`UMXs(;X=fy2lo;p1Rxjc}YxjSEJ2+)D?QOzoVi%FK|uV*Q3iSbS38_ZL8*6kF=$o z`r=7Wa{IpJPRGQyY)4;GeA|S>ucNwV`^O!*rmY_~e1EoRPu?F3ee=#9>iyPq?ppK1 z#to*emdL%9Z5C^pe&ufyHdUIvAtZRy=2n}Ul}4MxcJ@WrMdWB(jXpkJ$aDS+a!R?X zH}Tk`2HTv#n58)``=N_p=7yR}Z+N_H$H$Uxu4r-%9*$hnTvu}erHyLhth6gq6#qYa=@4kD*9;A-<+cPu} zJKVnGs&nhmaOZ~dmBGnQW;K07=Wv^TMB zI^(^21>ys_^Vikcw+hlMh_$(rEp#g}TIw?-H43om%Ir7mi1 OfU_>-nGh8rulx(~)rNuq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/pensive_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/pensive_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..521f7d1372e76d17ac1c198d2f00841400d2afc6 GIT binary patch literal 2323 zcmeHH`&Z0q7=OD^q0Tg#QB+ihQ5{EKIWE~FU1oCaP7@t7^2$z@r4r#pX(mdAYTuMY zxsB#$<~(TWu+;wWmZbn|oMxefR1653C>doc(3rA7;+`eV*s@d@l1HS%CkX zxk@RLqW5U{V1x)l6d{HX$KNqV1S5(O!-(U{m>@zBC5REk@!gmrLJ_5iQN;1Xm?6Rt zWr#7v@mQEcghP}=j6)m`jS(QhDD*-RZo`LQOfhB{bNphs6M`whj9`xE0cAolrI=C7 z@wA|uFiaU{40Ak77$zL19A+Hmc+wyOSOZPq1w>#otO9HRgK21oIy`_w31NhAyh2zE zcS;GPgyRJR4=7Vc7$Y37A80{0l$J+sJfj!^{7yybvB4`2;z#3=*FCYS&0UEFY z45pzS>hJ&#qm<*V1ck5|?u=26cNPQ#4=6K^a=g(H3*-RCgVSIwcnRi#TVN0P0S16# zkO-s!3s?h9-~~irGe842fWb7hLmeK#;rPtJN>B)k;m+|9LjDjqBn**4h7cO01hGI4 zU_3Yt)`FK{2e5=;@B<70#UK$#0~W9bn!pQ)z-E93Yyg94XoosHfW!Y1|AP-FZuD}$ z&=4Q*K);#OXP6iP1*bnuExh2{eVEShYl6%_BO`NrdDV%A6!WpJtDCBv>NMTs7yD{6 zQ$|=xoR{~QpXjTN7#9$uSM7hWC{|3?M847b__}pf=FZyD`oLYb-Z5fMvgMhj1)du$ zcI$7nHRj{J38|&Q;l-XSCT1p@29-2x#2c(L&k?s<2gTuD{j1upxl}}J`$8k*TC~<; z4@G=agIicmq^>vqQ(nrgOlhakp(kMry|6jUxb9-uvSLlv*2=vZA5{L;84;?>X@fZr zTDk?F>UVi!U&C41s^bUm8V_hnmDeQ|Hpg1k+HLPeWuYfz5sHXW`R58!y6;QF@)|5& zS=+UVR~-qn`_o$4xBK)8{qB~HK~>`TC{5?{Ess}PjjW1df8~<_eYC&YP^a3hdOc?T zc^!)O@{X0HnvL5tRcT^sW|R@u>NC_FHo~PoE+yLHbVr4);ENnTd0iuLSzIXBIs3)h>Za*cjm{|6-hGSoaKZF{WG2w z$b}N4EjEcW*ZV;REj#sTKFtNL8!E5V9bqn`-DVjNNd?Dl7pW5!AIe^ueb_eaoL6*luqC@o zVCKy(o%cICZ^!7(gVvLSO0zB>5?FjBw`B=~sxiOsc>1C`X5xZJ^&eDAJim4b)mcvK zdFOjJ`Bv(z8R60KUFQdiN2(m}je5WH@)EiNR+iun#w3@icK#a5_ zL^dMD6}iyGCw3lbX;&)!uh%Z6Sbc^?Jj$^$Sz!73Xh6-R zx`;c91zYtYvi5yed!y8&*7k+O)Wl6`pWBzS^1FoZZ^)l|wet!wm^bfPmUjPXhjGu( z`CXF~HLGd|e(F*TZMs=o{^JF870oS=e6M!McB-sTQfzBWFPbn=e<>&BP)GEFb&d@} zIeK($?$hj{OP`({O4?u8RVccbv^}r8v7}J)?3a?_7r!Mve;mBaaI9Kb=24!+Z7+Xk z_x7l#QkM`B)ZCJPKcFVrFMmy7hUv}# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/sad_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/sad_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..7048e783ec7848c92e8bd0cc2efd66ab7b4e39b9 GIT binary patch literal 1558 zcmc&z>rc~H7(TdxEG49%Ttuuig{3;LoY;Z$(hB8PMc9f0QzIRmp=dS+G7&YCiYuZN z*kl}Fn-?(Rs1s2aaf=bixa1%bopgp}Toz?)*@9+qewb$uzkgsKcRsW^=Y8MjeJ*W$ zVq8>omY(RzGct21A&d}Ch#*8NcS;GPgi|6YkxH2|!WiL<2u7sRO*vtla83j#QW>U# zFhRH=LJ+B7QAwC2ToNIPRG=vV5=POBB5pH>QOYS5luBhW?u=2+s9;noJWytwa!v)O zQlW)zCMXwF2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}r zf-|WI1`m|EU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+ME za0KU4u@VZg7?j`BP0A>J>Dhj(bg<%Dx&v`5_*-S~Hv-P1QB{LLoE$*yY|L5aB| zZgoRh#_)qR<11>KIx810I8~fIX0&`ZyKUg%^W2l?Dqhc@<+$*)zBM+lYF)^*L!ayj zeD^QwMRu{jB5;dw#68rhYss$9+;`OV*x?tr((6#)?ThJOE>5f6UJ$s{Qn}-hAuXC# zhcvsVDoOv)c)BCMq1IKhQn$4$t!?{j^S693+8%np+n+`yBOIn=n=u%z94;gcjwRP5#HC&R8_Hy<^4)VH2ar z!};X6aoC~PmM=TJKgAJZn5$L-@cgd;x;|Fxk{T1*&YDZzk+z$?>iM%(p-Fpwaon9~ z%?nFB5uP!VM7zc{cDbh6=p44y6lZ6dH`Tg#e!oq3uXFHth<%5p>5<>Pc%3Gqxo%n~ z;y0CFN^AXN=oJBT^YG1d*xlViF)4rmCOjmAs$DusyAMW>jVG4KiGB$p1R-n^VQ0r>XQ$P(uW|K+$ccJCrMSSe`2M3gmp&gb^&F{pj}!!JZZ*Z67)by5!uHGG9&Mn9;+7yzwuX C5}M`! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/sexy_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/sexy_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..b4e91b5c6777504b6661c3f61149e6590201b979 GIT binary patch literal 1653 zcmc&zYfzL`7(Ppoc!5BLm79bZ!%Y#78lo1gunU9+N-By9xqH+=5oaRCDMyn6;wE6| z!BDoq!9ZQq2rsD!;_cu7mb-Wv2bT;>2XvBhMms%x|NGtfu{-Cy@B6&ZWmgxg4V#r$kU9l`>_7F~S)Uj7X)Ma>6*_oCr>&GE44KPfj9d$h5aK;29cgkVz94_fHvk_pMAVh7xUJ@5ktKrtjj6GVVDXo44rU^AeB4KPfj9d$h52+pNq zB@|*Y?m}>>I19nxfwGWXDn=s~M;#A1QppTfLLnC8E|mz8KLSU>h!hzjG^B)BkOPc|)36p^!Va*+F#Lc4Pz;G6 z4J@z*P4EH{Yz8#20fuR`qmBn0<(K$BeE7(*i=&g4E{sfwo;iKSYbsFid0{)+AK$?v zbVmLr#QqmI(TJNwRrKd1`OZo1#h`vZ7_caH~<59yatic4)mQQ%~F-IV-5F zO6R&P*br#yC@J&`Pf1Gs^R|0!z>iz)60B1i#yDrE)Q67ku8Jy|T%6OMc;s@kbNGs` z?ns?&ZOq_-Mf_vmo9<4*<9@2Q+T`jC&yMxX;KEYI|P_IU2Jr5S3o<+G@ViJKcdo)0^Ax_HE$ySn_~rECX}L35D#qfc*S zIb@bxKXEYq{^q`cdxIXU3%!p$y&ar<*4m)HcXRHI?|Pg=%-7bedvSXIk!2}v=H!Tj zI?LTW%cjz>@!lEMw{nVu3+zX&jC(fQ)tH!X)L+mREy$_S*tqX4&#^S_NXzu~n_6ub zu^}wss~}CwEp5aWryc9;HYM4_y^Ox%T(EF>eScYu-{Jo9_&JaID-yOEF6~KL*{A<{ z#o|-?%9NQ`>nanEtDTg{?B@S>WPvGHOvbi6C*QblVwxVbhfF#@uD!!~fAr3^rWU7U zKaFiMF=d%97;|-nYvVthItMX*4*Tp`liz=Euy{l-8aYL?~E9=~L^2=TC7ep3U zolR}6Rad7wEjVs^5YS$)*|?^@+pcWMq4;SzuTHn=^BnzL{1??eOmx$gYUlsnQkmvZ z(HIzI3C-^GJ!$AV-hb_B!>Y02;RE?Y`SFHBCF4siqNlE{#`XKEpR-gpx|3cGnUh;v zAN}T4+oq|>`1@#DTfXTC>s6=O+H2l8)^~lD^Zj3f&TRj{v?Q!K-7@1{bLT0;;1_|@ zW;|)BnwQ?;a-w+cDlh%>&3|||1ymc(E!b8Vc&xg3`~L9ve(kGxN2A{tw)KahYQrQq zuTaB*^ofT*DRwWI)ZDY{$$SkB4Y9vjSliL8#Uccm3No= zHh1(Ej5b`ctn@7N@5}Wv?z8IV4-Z&NBVLc)?GojhtlzEm+o&&%n{#Sv#p3Y+`cjpO G%=;Id-^D2a literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/sick_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/sick_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..73d5040ad23bf6b03b616ea5b9628cd26bdef34c GIT binary patch literal 1826 zcmc&zX;4#F6uuO&p$-bQK?077K@B0;P9C6uWn@VZL_|PIA|fR4Kmvm(tw^OxgGg9| zV#^ETj2H-8Py|^zPG>5D6}VWC#n3ty6d_uzilAeyz8>E1{_p*f%)RHF?|e%V6fEB2 z70*LF^ad>+0wEG13L%UT&D;qBkp!X$gb745Wr9Q`i6|0b646XIK_QYt6ooK_Xl9te zh{TA(2xCMuSOkqo8c{UDG@==30s#_?LN65Iws=T_pa=pJ1kEglJ4q50Nnnzo86Hq3 zDT1O1Oc69g3%W^6P?*4&pc$4hOwt5J6PPAwhBSx()<6?@0TI{?s{k9oU>e$?4i9iB zlEfrQGYVlb+$oC06iG9Jfd`Z+OkzyZjDDa6-4sn?nxq*!z%8%``~U+$F-QbWAOcte zP2dGYU^74iHh{r2v_l;p;9!cP87n~{EQUMA6wNpbf`JE=F-_5o(GUyd0LFvUU@dqF z=7C#a5BLEFfMSpcqyY<915MxsL|`*O12%xcG_*q<9^lYSW?&^KgvD^DnFt|&2pkfI zNFhTA4N`(wAO|oWoCa&bORxi2!Z7#&27qFa2&4fESOZPq1w>#oKm#^_!8Ei(9UkB? zzr_FH!--xRCW?v-@Cz3SH+^Al1{9p$T3GqPw_uUZ;@YOk}C;`qgfh-Kx~YVD?U>?_vLQbeYoZ4>Yjeh-PlhI zSrIb^rF&Xyri-m&SAbD~wF}ACr_TvQc0X-s;_8}=TVfO;Gv$`-a7Q(M{6gy?jplG< zc}sqe&?~hviPXdoYhBt9D{7pZ)m=KVrX;IoZbp(n?of^Ur)C`jGq{^~_QcN=RutFp zN2|uVbyBtSQMZQ$^IF?_)uo=IAp_QzjoO4+?MsXtFgg*kuI#l7c# zG`)Dt>vigH%1_zi*dw*=C9Mt~Wkt^%Iy_3ppJx7&f30;$Y}j|eXX3c`lgEvhQ*J9u z-eYN(YI0Nhlu#!siHWw8@!seC@$I{X&O7U<+D?s!ubX96LcMeeJAHWudEFzoJl>J> zkKdz7@@ep`{b}Ew>x?*QvtM^!p*iL;63XJ=dJv%g(Q+T>97l7f*eTz_R%W#5SYl(R zL2OUgp&I!Pj=yA@V0|GAEO@*H{rZb=-P?09kn@CTh>FQ|<0@ z|EPuea>2?+3FUhPy>pSflcZ;pvhCHGmEypLx{-^YOQ%e_GGT~KO@)7da&4t7`=Guw zBU-+*yt~Bs@LfH3hw&K zAI9aHTcs8YV|@f^F)c{|lBGB$O4{%O(%mCCx^^Uh9VZM)jl^rayeF_ ztLYk;^xdIfV6|^)em^Mn8NMHsQrh{K)rd<_LwSbc+V|2onW@cQSvNaa^GB3zx@Q}g zPspapnKVVf)nISoS94W^M?M_C`L3^e?Lh3S!4p0@QNH`Sd(l_IYa^xCp1pSbxM*s6 z)y~bso<$ysaUCnI2HZ|XiVsKwMt7^4I~>2RI+(mB=Iumgv|RAA&OX%q{?Qdu)x`K2 zv)uOSs{AL`KS&c3lizT*yPC3A7k}yNsfe&cFCUx;WcT^0xxEGQ?b{C7AVuUJ=V&Xz z+xf|y$-Z8RC}+L%K=HcsyoagF^bNy)iQXn-j;EA6tMH7^ObXv+#pXrj*`=7O3pO;G jE*7s&>D6gu!^wW-d;d1oAW5T(o=V}n)Rio;KtBHh>zf@* literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/silly_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/silly_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..33dd4fd955ca16abd878aedf794fe8b5350d90c3 GIT binary patch literal 739 zcmZ?wbhEHb)L_tHxWWJe|NsAIuw?lA@Av0#cmMxk`24Bq@89=VcJTcA_V7Og!~OgB zlarG*H8mw9Bn})n@a@O#9}l#_`iLSF|8x7fh6Fo12DlpO889;fH7WjN;nZN@XV3u| z0CENc>;DJJeJPpqGNPDrUhi9@W$%!1zj4uf8-vBBcY57Je$;6zuDfBal4{1hBX|EqhfR|7&utg&7ZuEgHLCv ze>2PBUGw+aB~C9jXE@B#*1w8v5eM)7Q<{g)x9VMA};=rypUn6GC^i6$hrp3e^I-^#sCNRxxzQK)?lO6qpY@6Tx(cJRlJiBYV z+*U~@e1W%W9Wd|;bk3LfGFPm7zk`?MK!Ss#jufN$!V4!t6jJR|H&oW_TXactYesJ3 z=EJ(zzp|P$o{?LfV;8hrqwHHvT=UfTU$`b{Y~E>ArCGyX=V-&gYUy6h&Ru88Hp#w| zm6d}d!=(Tif~{Uw)4D9C&ET8mSIynOaIxUx#mg;{wXB>N1Oztj;aH)RF=t!*E;fcq zlb3PudK@%}IDW#4ZPQHtbK&hLZco~H?MBM2Ni&}8J#*bK(Bd%%lf~0hX9E~7Za%;_ zW0Td(FHiO>Gkj1qV0{~DA2O$a!=>~@0$=p@29C|Fu4j#Eg(w2qT0OA_$Snol?Rm;gkqUq*A7gFh)2df)S~7Q%)EsoD;!`REDV_Ob{-J z5JW0iR1zi$mqbV+6=+I;gi-XOh}*1~Le#?ojmkBjc!so%e+BB|lgy8EHY4Na-bGB1rh8<<~Q5c@~t zg*`*B8}1#s)0_X7N7d7MU2~83_>L#K{Jqyp)}{BQ3}!T*-?cPqcuZ(-%rU#uc_S`y zukPLDANV>JIp}{d8Mnpfersi&^`lW;kU97KhrdQH)s#NZoch^7WR%A)gDEZ5SQ>s< zU8m~K@on2&9OxIdI6gOEu>OlY&FDyc{;3YtR*e$KVp3H5d+JWQ-fny+_+gLc^s;$ZE7iX}yR37LnReXq&7w6kJzb3H z2``VXFZ7>r(95v*!V_JR^RZTsH@&N~?XPStFz(d1>)c%vzX_V{arBJa4(-@Y_DY{` zzbV4&@YBJ-JbTw0i{0C9x$g-wrSI_Sa*%9*QS#y~=D6OkXbLd{%mR!H+<2m>LNxl{H!mjVn zfbzpFji!*^ZAA+^n+o=(wz+2*&s{laE+gSd!zOFvWQ|!DmSsD$ZCj$5RBOqXAD_@q yb=$S1Ym0rH`K3X1t<-YHt7^bm literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/sleepy_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/sleepy_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ddf84ba01d6c28e0ea713b35246ad5e5c8e0abdd GIT binary patch literal 1598 zcmc&z>rc~H7(PzWBD0gLy0HN*GpJygMxu}z(M1iss1h;_~ya3BYK}A|H zO5Cx=SP;Yv6cA9+8Ij5eJJSqMOwbryBswqAVKV17&mMk%z`pK$Xmif{zR&wyTI13s z5s~S^B$)g`#ttQf5yA-(gh=I1DPfdwN(3cRDN{xmBb*Vzh*Y{MCyW!$iQq&k!&DF^ z2p2>MA{8tu36q3NA|#OtG$la7D0)%EZR{{gIi-S9sVv5wG0GVgj7o(E%8XOaso+#9 zw9w52<$?-9rNR=!Oj0hXkW?z9Ap)#H6TCnKo3RSm0K+ueQO5%gXG}0A6@^%gJLgPr zCKbWpfif3N2qqQ%poMNOnUG8>cEByz13zE@6hk63K?GQXCU}7eHUk>i0K+ueQO5(0 z;9M$JLLnC8E(Di~vk(j(C=1D@Vl-kw4lo{0!&-O=^WYZjfgdmciXjoCfd$r}30@$A z&430rz%Y$=)bW5LmCRrz6k;*%Qi%}xBXA^)NRc5zLrRDRIly>04Qt^g>;Ov)!w(n$ z#gGWnzyfQ~1TPT5WUh9Weu@9XN1$|%k6pFWpi7LMJ11=XI8X@u)5UEW zzC*_7jQvfB>Ma?k@-sD^=-jRHnw8qqG^|tm25ibTeKNdwmuKj^!t5~|TkJnSzc4E- zsM~gDMTXagM2qf-x_N0xvuBLcJ}ollZoOBXo}W7t8HD*d^oOla3EUmlJC@3S!UM_>dHkuF zN&3Q8@2Bq@i$0v5KTo4^`s7XREqqng7+3f8$`v1ZWV$$e7KNrgKfuopU(v28@SVLa zY<>8V!GMm2D9!TD>cOn;QogNsph9Q#vF@;DcUgDmRPj}9n{WAT@e9!TlJ*nljxVSP zKBh^m{rsn*%6ON%?_{=^PK|6mnKF5c`@Ij=C6}3_%`b1H7=AeO_QmpjH}lT>7Zp9u zyqZe%Q|~7nZak=3d_E<)IKD0PyD6W(ee9i{;NmWr4+uPv4HZ)au3D1o^CS0LU!o%*g)cWqo|M018- z?dl)pSMO01Yn%Gs&c9V@Cv}GcKF(OX->T6co}-H2-)N$PSWPi%?KeRcGxabJgRyVLXOk5zuh zXKZp-J*iooeIY8fJ}$NHZ@&^UZR<;Wr@j4n zNk?S1I!axsawkIxBR4jDU-x{peqgS{Yx_U!a>qH>`ur62H(xmlW1kq^j_{3dE*4Y` zUW_U$=)c(YSHtyWvth#3TZx;8+$K)fT%BC9+%4~y326ztpM7CBPg(O~XpdXEL7y7l x*xom(E$>d?vV{)Qy|R$@M-L8!A&c^PeJYDJ;&xAlE&8_$mI~S(JeI|Re*uq>rvm^0 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/sore_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/sore_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..862344398a627c2405609a744da42c7a57973f74 GIT binary patch literal 1664 zcmc&zYgCj)7#<8<5V@E_f(U|wkYVM-%}a&AE~1d)bpcl)7?Bl1@UC^(1kEb~D>4D5 zC<#aLAlO=F983YRAw^AAfkF=GQOr|TbS!gv`2P31`LTOu-uHdp=d!DrqYe&9^d-LJ zPcn2UA&d}Ch#*8NcS;GPgi|6YkxH2|!WiL<2u7sRO*vtla83j#QW>U#FhRH=LJ+B7 zQAwC2ToNIPRG=vV5=POBB5p&6QOYS5luBhW?u=2+s9;noJWytwa!v)OQlW)zCMXwF z2r3np7-o`kNrj|RAq^2=4VvHuBG`;ozy=tm(T+MEa5!UvF{voTV%#}rf-|WI1`m|E zU_vmd=m#xybIF8cQn3SW!5;Vl1E3fZp$Q_u8Z^NRM6emqzy=tm(T+MEa0KU4u@VZg z7?j`BHTwtW!)tgo^;>Zc&0k0 zY-`d}ZT0q&;|*=yz9wx)W4_0V!zTtz8TVq`4d(i-wjIM%?o)$Dt+MUj+;Mwl(Wn+} zj$`@8w$%L-?)PkQHfxq|%QvnqvDh%aIW+Ag?@Msmf65{}Hzl!tSdyDpRcC^Il<$FE zzBiUGdH;Mtqs7Lr?kt|Yil!OMXTNhl#TfpU{pR@vYM<)kbNm8YuNS(7_<0vPN3ZTL zQtNhk8^eZM4rOJf{_m{Z6E0@pIJ+RSy=TOfu}i~mU0UE!zI%d2!sXP;eTS2M z7d+z2u18(@*wyoV2;b||l0STT!x;09{a1|vA$2pW>XX8cgoeD`=SbqeGenI3^tqog z<{Bc>_VoN--B_i1SoYYQU3^EQ{b8mnBI-O%8lx6J%Pc;o*>!7DT#@z9I{Wy!U;Z;9 z_VLw#diR6cFfaeR&3a8HxiBoFDbT@VR&1v!o165tN5_Y{*7ol<2mjK4GH}3Eqiy%{ zirzA?dbin>F}Npvy{=uKs%qFbuC~|I5q`3%xNI=_;tbX2rkp|l^nr;xG?Rn7{cYBC z)O?nm(@_3*K>gX9hkRD(RzA``X#cA%t~9KF@QJ@DJQ&p8+4jBm-LARj#zQ6g-zr<2 zKC;qX`bi(3-elO~+_h9^P^C2)EHWahdUC2}&EE0Jwe@*zBjRmTUKy!c5}sFFUQ&@f z<<&lC$9Z;34#azt<{vkFP%}1pbJjgoY=Js9H@R?L;KRP6`D(w)qDhNGQVuRlvP>yX QP`6eVFP!G$NXU$T0j0ppSO5S3 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/moonsis/stars/yellow/stressed_sy.gif b/local/htdocs/img/mood/moonsis/stars/yellow/stressed_sy.gif new file mode 100755 index 0000000000000000000000000000000000000000..dbf3b053ce71d32f42b91456f057b2154c1b5849 GIT binary patch literal 2752 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/aggravated.gif b/local/htdocs/img/mood/neko/kaokitty/aggravated.gif new file mode 100755 index 0000000000000000000000000000000000000000..675f74f1464d6608a642108a4537f0c3653d6921 GIT binary patch literal 1767 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aD+Wdm8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByLI%?C1hS$%FFJ@<8|Ow15<2x(v>XX%+Lj))B9v2zrBuJnr|wWD{cBJYHrDECfV!- z>ltUW^S$6*b8$W6ri`!aOz(*2-kH?HKbduA#N%Ug_|=2NswF==ot1V@FI{2!G~?2W z;MIN-H}hXzn<#o{o^Ey7{boi+Y`#3lz{tSi5CDo~b}J9(9igM&%~154JVo|DEZ z=Vs}ai@n%cl;N>}IZ;eCYfH-ECDzlA<-EG`%wgakG;l)wN0 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/amused.gif b/local/htdocs/img/mood/neko/kaokitty/amused.gif new file mode 100755 index 0000000000000000000000000000000000000000..6ea3f9042a6ea2240a426c6f7bac198568c59156 GIT binary patch literal 1748 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3RobPdvdST zN2!d{!f$U(XJ);xTT{{S=wPm+(p`z`58O{`Yx;*)%=~ohET8)_7TH}}US8&qe{8z; z*TzHFHpCy^S8bqx&4(u$7#TPm0zh%gE@mR(z;KX(Q_!xY!r%Y{BcGyMNJn9VTca3z zOpV8+B@7egw1os_3NH0-QfC+VVKL#rnF)HuLR&nI51g6f5Pxn>hjGS*R)uac4Tcg; zuO-aMd>Rf7E4^2Rxra^JWwQFjIt@*uC$GL_MXpWmT_wsLwCdKJB;FII1)mNuZY|S4 zXFB1Vme=|W#y3-E3$HnSu;zG~N!P?&ry1RclUjBO7Ck;`VlJdRGjj9u^9!82<$R?~ z9vxZa|DJbkRYBHOX=WyDzB^2l_?tB){cxl3Y`&u$p$ASeMN}r~ZkY7SW3}qeqF&8y zs{=O#C0Fh3G<)ma$o5ET!zu^IOS`0=O08J+Rm*>U)#I$QQpO+dtx}kn7xTLy>Crmr o`C5N=RBTLXR}Q{)THpgaCsz0Ms0n`Tzg` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/angry.gif b/local/htdocs/img/mood/neko/kaokitty/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..1b9e2eae9994fd325da2aee06deb47b445acc02b GIT binary patch literal 1771 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!c+no z=cKX9xmmj9VlQ?UWq2%LP83tk+LCg3iS_hjIj^ofb6FG-?0 zSf3saj7hWX^IOet@9MR@))31a!!L7URrupr=9K4`M1Nk_JHNq(n^}!pXw8-00(rlj pHD!;3Tjdp<_q{1d@j5rxxm&I`;A8B?Wun?XXRA!JcY`9(8UPKLk-Y!_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/annoyed.gif b/local/htdocs/img/mood/neko/kaokitty/annoyed.gif new file mode 100755 index 0000000000000000000000000000000000000000..42b2d0fcb9a8a6f56873e1fba6a46ab81a8acb32 GIT binary patch literal 1757 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhfz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MJShL@d4%l-pPEg%;*-M#?|()vey}dWR^7}F0Jv%-=W@BbTc$}Sqok5a8 z7U=QwNFJBtIS`QO*v81gCctn}(WOg>onwK7pyJ_PW-Bfpg9R$?9UAu2cr+(AoMci7 zU&j;R;NZ!m#K@x1Fgb;Brgpv2lbOZoXC~RFs_ABiJPKS8kSX}+mguC(c^sJSJtnPjsUtY@6f&i8_M&BgVMo2nMB zGrc387d5koe==)i`Qy9o!kXQ8XM{dEwlB2S$rcymkWT77-# zFpHT>V1`!E>yR#90_YYs-8u#r zmsn3fmhw)^ACL;d~o(Pb7!OMTBRaPIb7@gwiW Tr7qD$acir#-fd=NWUvMROudFk literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/apathetic.gif b/local/htdocs/img/mood/neko/kaokitty/apathetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/artistic.gif b/local/htdocs/img/mood/neko/kaokitty/artistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..714ed16c5d205eca323176802573bc43390647ed GIT binary patch literal 6325 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/bitchy.gif b/local/htdocs/img/mood/neko/kaokitty/bitchy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6ea9832cd1793316a33f0a8ae6d78dcfe86770e5 GIT binary patch literal 1773 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0y)v8VX75w7(46o&U7rKfUADQR9^OVkltJ*${-kcq}3&he-uFp6= z>8#cC=f`(Mzizww>)V=3`|E!T9p#qT@Su%NNZO(Lfx|<_UVkk!hVS~38`bA4&C79k zmAY<@=Hc9#-#__GnYF(uCsQibtA{yqS6QxDSIUBO@XJ*csRvBpGCZ0dNT^0OWWM1SC4PF>n+8W>ozCg}(itNOQD<~~w+xmo@ERA*J8-pUe( z;3ZDet!kq-Ib3dIR{y2qu$AHZREf=8A2P3I+?+0SJj~X6Tjq_4S=Fa{e|}55v$OcH z)Q#+fH;v4>;s36lxZV)4Ic()V-96JYA1&|U?Pj$!-FULsOx}+rvr^f;-Q2wT*qob5 zr!FlBUL99!U=)9Kow9b1Z?)Omz3j|P*t~g~fsuj3ApjK5>|!Po4h#nwI0fxWDhv)V zF!Cw7g>)1)xHXEg$JBUCTEZ|sXZHuC| zW$%=lk^SIFBXa@!oxL8{9jfi%Tj#e>!&F h-?HB)GIGny%PTm|_GMRUraS-u literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/blah.gif b/local/htdocs/img/mood/neko/kaokitty/blah.gif new file mode 100755 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/blank.gif b/local/htdocs/img/mood/neko/kaokitty/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..d34f7de7f0cc8d45b6d1da151e52eaf6329f4cbc GIT binary patch literal 1256 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aX$D3P8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCL^y>#jhh6Klh~t3(;ZRz=K6Ijv^vZL&6MPLAcS z+G?TKPRtd&XLPj{);De}dF}P3`@8PL{mId7u9@O$9!Co#&Hw$7So(CG1othGnL9T> zKfl1a+^$E$By<0Ke_^xQs4cIrZ%EeX;XwG0oq?S}l0g>ezl})#ljAuMkm%UP$iXJS za8c2vONgCgfrOyq;a+AdE*^sgD()Q`_S1MYCpLJtX(z9ead1#+U|`9b)N|5U<=iaY z@^3O-m(|WJ^r-a`nKdQ-aHH^SzM~wW4OixcxJT`kGJbt_ZA`oui}bWrjhop{c!@S# zbGW)e%5|IV>C$z#S1C-)`|_(G>E6`p`C5N=m~ZfHHxK4=JF{csx~ice2Z M)1PlEA;4e_0Oe)NZvX%Q literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/bored.gif b/local/htdocs/img/mood/neko/kaokitty/bored.gif new file mode 100755 index 0000000000000000000000000000000000000000..98807d5819024455ead64a98216187f0faf163af GIT binary patch literal 1741 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqO^k%7Y@02Hn4VkQy}3F$pi8&hUUcTPJpXXobU=NABd_xI+9hZmN8Z}O9s zD1Ft-$cQcK4$&m)W=%;y+$cPo?^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPEd&GfCx}NV&Hhnz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN z6@~|nFfdu^y^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MJShL@d4%nT+R^Um%Uw>is~?}*X=!wO zT3DdiKMtWSQBx8PnG!UkO0upp=XSOD?%wwH_72UmZ#mWGPj2lq{Qhn3?j0W=pWtO< zLHL}Vft^8;K^Exq(?~v-<2ewJ=-9@{!6v|PQPHJKh@E4BgrMT#US=yU9)krc?j0KT z(|9x|Hh8vaC$Exma8PMrV9A=)bJAGl+$`PlZ!%q%)y^#RsPz)DTHw$)&oA6e#-cEl zk;y+f?(C|ID;QP>Zf$$3^)cIXdCd8~qaIgtF3rnv-&HF;d2QovwtZRw6H3;*?P0t1 z>B+2VYa9-gv-j(ES`1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/calm.gif b/local/htdocs/img/mood/neko/kaokitty/calm.gif new file mode 100755 index 0000000000000000000000000000000000000000..c7cc71f62318ee4593546041cdc7b4aa06513e53 GIT binary patch literal 1304 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhfz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wEI%dH zPfd|v-(*u;mHev7%yr*9-`(5Z-WIVeU$^$Q;oE!DE59G}-LvE4V>V_cgvZ$#*cl`l zWPu((f#h*Ho&y1ij%|z_Yyu1y6hfIdwzlf)qb5d125SK2 CSLC<= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/cheerful.gif b/local/htdocs/img/mood/neko/kaokitty/cheerful.gif new file mode 100755 index 0000000000000000000000000000000000000000..7fde6e74894e9c498cc6a50490a8e86294cee20f GIT binary patch literal 1860 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8eU&z`0@Xwz`MG6LbrV2@w3Xx^0#R>tL z>7}V942nNlIE{b`bwI%a%0~dimaWx#`+K|Y#obM{mrUOXG$ym;3#$m|R5mcN_8(O`w%c@N z!)ZZzd%s!cE0fRk-QBjO%V-HxmsxbRTc+^q6H9cWx4-L{o$>yb^y+6%ZdflYxP7d9 zeaO76YRbZY@@?i7$X&sdLKxX|U+TWL6HBxid{yHLhpVh^w`l z`Z{Dof_Go*uC1!K*RwyW3*CK1J!WTOao^f%q1*_T2Eh)W2??4H8M#DQw!PY%8$G3y zm5uMtjvVg;U5wptcWhbg%E}sE_3dTlQ}^W#wyUSTC|1h4zASe8IZNw@*|$v8U%M4p zFF$p6ceogfUrh0#N8P+^EZBVhoPm*n!yy2aDA>hJBpetHGH?pol~foUU|{4^bPMSy zY;bE7V~?rvn6!jpqMWvnz)ZoV-c9Q40zWJ!95^#UuUKe{r}2R^a~$H&t?4k%xX`N5 zEvCUxqUp7SIhjwxp<$)>Dj(hq(}2KNL8~?P^WE4bx+Hvg`1CB>17WKp7du?v_EbtV zFJ=>izzf#`BS)qkb?h1e8>TM|nV4{JlZ;Nm`+IYeVqdAQ*`DpbSVC57LdGYfQ)g67 z#lGG!FwSVQVqeA=TVUdHUD|P-pRDw@L+u+SC!IOFyFB^$)Y|`S?{1iXe0->%-Csfg zo8RxyD%OMM^DB4NSY2)iWfob^r*Yt_`gJDeb#b~YMRjh>Oj|1#kv&!C>a?tzNoQAn zT^q56jOMPOZA~Bse)t^n3 vpUZUACratcoaK)8BDNE^I$d8QecJ7T)$&s}H;0QIIXk=P(7hH=WLpCOQG>?! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/chipper.gif b/local/htdocs/img/mood/neko/kaokitty/chipper.gif new file mode 100755 index 0000000000000000000000000000000000000000..b9e940430845398dc0c21c5b6cbfcdd0751aa687 GIT binary patch literal 1301 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kk$gC;phZ}`w^Bv^~ zJ#dOCqB2Q$!=zUpt5tUv^=fWg9k?MVxoU5x*<0^MwntJMRyjCc+9mZ=YQ?J3*AbhU zzaD%0d;5|HdqW+S?(X>Z(B){Xxn1awiH46)^0_bDGIQtV=jS>3Pk+_<<6{ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/cold.gif b/local/htdocs/img/mood/neko/kaokitty/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..dc9566c556a7c97805e5e29ddaa3077e0194635a GIT binary patch literal 1393 zcmZ?wbhEHb)L_tH_|C#`;J^Xnv@>Zl|Ia-09|#zXXEFe}XZ{0uX=!N;qhK@yhII%i z{^#~{4GDI33~)8lGhk)}dRFnDtb1mfQ)y;SN@|gUfu5;CQl&y*j ziWw@^a1=G1Xp>{F*>hsjQiiE&mTU?Oj8x9dRtXidI9c%Q+!XU>JCzN=&(1CIC=^@D zVUl^NQ)9N6Mnj2~&kEc4RXPq0uYA|Vg`c`&m5_B~ZCLiFGalD+0=8!zx0<_qqSDQs z9@mvj4qQKQnwk9>)4vDH+qku~+|@zB{Nt_ttV+jaZOj>- zos6}v=d-Cg$iga=aXs(vuW#>f^X_J5@SnH)$ERmU%lSDF;lswj#302W2MnKI!0_R5 z2mpl-qX18XK|@0;r?gPbje>@Tb{=J|5{(20w`NARjw3rZJaL&QCoLr5DX{ePWM+;U z84rgvkLeb+Y%45-7oM5p;QH>(O{0tpP3+xWIsppm!BadO%VNA1tUS#W8W`kbRmu>& zT4R5f>aEZ>SC{KZmzj1IuMXMf&MP$|d%@#IX1DiIOR^iZW2WaZewf>RS?AQjT7J2R z>@P|F&8%X^Y;Piz8J10wj29`mzR6)txq0`#=&PTf&SH7DN-cJC!%HTPgvIlEZ+(4z znj`9Y-`v~V(r<5wWk3G*w#moy6ME%+0u&mHpP!m;KmVVN)z{Y-)+YNeFjQc$1^^jB B4kQ2o literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/complacent.gif b/local/htdocs/img/mood/neko/kaokitty/complacent.gif new file mode 100755 index 0000000000000000000000000000000000000000..4c1748eb5a68dd5cb4201a438f45bc0029f88f04 GIT binary patch literal 1832 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 MTibZ$fu)c&0F9Y#kN^Mx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/contemplative.gif b/local/htdocs/img/mood/neko/kaokitty/contemplative.gif new file mode 100755 index 0000000000000000000000000000000000000000..85e4d9e201235a584e9a528b068a919ef8d4bba2 GIT binary patch literal 1888 zcmZ?wbhEHb)L<}T_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~adj>`h8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tc1sv% z-8r#w@$r5I=Pnt~Pe~1v`Tf~uNH{c{YSoI}B%^TPsaK17Hs20O!vhWT%|f}({w!Aa zW^(Wsi}fmDV4NqwEKu>Pc;(f(LG$I-S}izmb$(oV*3=auZ>}#&44ky~)mDcaOY?Ro zrD`(hHf~RNFE-V4o8FBb1&o(lW?jk;KUjbN)7#7+Z>}B{gFu^6`CV3tya`bfB4A|KzUH zW&s`rh2(?H(&}Y*EF2u%d%0b?BpQMe8W;`y)8=Rjsh#d+N%Grra`Q6=CS69Bf*q5W z2TpTtd{o1^`M||x2JLLRRtH`Nukdho(oLAEetlJ>>be}S1==^)DIdM{Bx~EN@VU~* zcjcbGmKHU=XuaHCZIktJ^D_D6Vk#dr+&iSo>ip*S^%t>6+55N2GE^4EPp34M%ULv382Ox#x^HF|C9&CYWpQ~`n&jk-k7xLJF4}TZvNWsJ)O$ML&WmsT zZ*47peedkn}Sb{x9PC=Et&Bt#b>6mW8R*b7n6_9 zwW(#&I3S$Zz#!2$DaLcc%d?$k-Eu8fL9ec?QrZ|L>S6jUaA_>JoUX=$*P$C3Pl?GW zELd}?(fu~x4atOt*zNJ3k8QQyuF$yK{U_Hw>js9{u0~evdEHkw+}~Bkt<#qyt{HoR zS;c?ZnFyVyOtV;<&)tz+$FPr;qor@nto2csSGadiJ3H;&%M)7)+w1Or{PyhR9^+sC z*8bS)+`gP&=EvGOZwuFCc8cHsap&Qqt7WUReYMMrZ$DsHdR$h1w@k^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/cranky.gif b/local/htdocs/img/mood/neko/kaokitty/cranky.gif new file mode 100755 index 0000000000000000000000000000000000000000..70340cc8bc2b10e65cbf9119e756c371cd231ac8 GIT binary patch literal 1768 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhiz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnh~j><~N6ti(`W41Jxr8EM3QRJ_xG^ z_j>jg>HM0Ud3C0hnL9)EXcdOE9LPb z+1u0B-JKa_eD3S3(DxS)w#=5w%UH0naUnaON?*;Tjf^|Xh4s^NZXUS1-@-b6+HIrH zo>LkVn{;@^OJDV`4m@SoJ#m5Wt*ync@15Ok?sjo;CG++@)fMRv57%nPpWE~EPy@pI z>}3nT;;5BD-#aq$=|P;u|ju%E`G zIkDj+lS=qHo&X02PbMWs7KMh%DU36<>y4hwEKWZ&$v#z0H#6i>;DUg3vD&DF%nM6- z+5LFD4!mk$iVaV?k|mrOx*&9VpKRo}*O5!}O~rDhOQBUs@5o+D_tT{;O*f zMGwu>tuDLY%*cq%m**H588{pQK#|NYW+LIhaFBsh(5|Gy-~a<7pQ2kxM`43oqZoTk zjmM-V3=`$Fg#T#y0%Wvch{De zmsbSOPrFlLn!RUPynNZ&s$>UjUOY)oM0&PqC$Exma8PMrV9A=)bJAGl+$`O4u@^gw zGCUSACyJ?NZAm%2#CrO%oL5(#xh#r^_Yw)%!f=%_Zg!H-sjW{gtWOUIMxnFD*SOQb4q31QteOcV-LnvO0oHfElHRxoohGeMMQ4ONp8*jJAbYy fUYRn_xm!-Q>SOH1W#ZaCXRA!Jce67yF<1itEnJNW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/crappy.gif b/local/htdocs/img/mood/neko/kaokitty/crappy.gif new file mode 100755 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/crazy.gif b/local/htdocs/img/mood/neko/kaokitty/crazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9d71be310067f9a949d849622373a685d4614bd0 GIT binary patch literal 2335 zcmeH{`9IWo9LGO%G&6GK7#g!?n{hObSPZh-GD8@K7$YH+T;oXPswwsOqC)N&DNGqO za*kn*7#&lDTpgrzNTpM$-3n~JnU~Ci@AKWj|J?v-UVf8<7t5aJ;b3lJihwQflD-n0 zBEswvBBDb=V~M6Fmc$(#qHkho9MK~pJRvk5kUk^j%oi5dEXrBDBY?RNU>GgBSa3NN zqh{#eBQEPmQ`T|e(;LgLW-21sNmXXDP5`$td4v1?DS(mIYY(T#LcQrQRFCUu<7!5c ziLL6%YL&CsOAwgzhj9>e676c>$UK5*M`0M0GPp_FcuW6{e8~Bz zQE-hGm8uH?WF$B18bx=o*m&=>*0G`0{blrnF4*FN@Q!4)5~Zt{&9Yv&4`+w5nERSu ztJfBrZO~H76nh5mzmQ?|mXVBlf(Io{Apx*hMK8ry1rhWH&eOT|QgiC|4D6R_H~QVF z?P+V7HX;ls#HHjoC2GvyboW^QX?r6DH=C)Kw<;A;$p4~h2QYx4dMu`h*08`)!DS$) zvLSw-sSLoBNRD3VdmzVT4YYp}oqGo4|7fJDT%;moq>$0dv(|aC{ydX7)n;dkte;Qa zHdvQVVc$4H%*5Xwr9Af(U^Q)wsg~s1aQ%uDz742l)CD?u$IlH5N0LMOnughe`s9;( z4qfWwBam0FYeHoGeQyKWsif{X!g*%U*oh;W+yaJqV<*>wz&P#N*7U5e@N>&RUE9>e zV6j1J%MWJ6Z#-ZjCGy`X{kbG1Lw~j@WS<6KWtU~0PlD1^(Cp!tyLGzL;iiU3IP;3` z95Q7&Mw3|9aU9_n_z_0|Zbep>O$9wHnInH~+}A8RmE0@XfL6}qFtr`>SIVtXcli(w zs$Gp$g?^u&d)6bF8n~^{>d_|4%Svy2s5M^Ah!q8WtF4`Bi{GQbS(ml|wKsW2;VU;?pZU@?v*Y zg8*D_Z6UwS9CCrL*{Y!n@pK1DQJm+)a^u45rF7a8-PhcZchw&Rk(`Jj~o|wi02rwd3#KqMdp_yZ>6Hn=YtDYM68eO*K+l&u1y{X!lxc0CAo^2f0t#6 zmVaK@zQwX2R@q@^^MX1vU?}!54p6%mPI^DqgZbE=i=`d?Smhbw2-9`2QUGy!j68yE zOnjSJWoIcov9goHs&azkgKH+}EFD;p?N5cj%z3@=tVEvnv%rnNy4?^E8Y7%-ght_p z*UJ?R66-o(%bLOhn$@~J74S2n(d_USO4RDTy83-iDG{!YX3b9mfNqCOm1>b_$2PQiyznV5D|W8fYXCdEgcOH`y(bq!VVu0+2n u4s#n%O;da4+H&s0`F^#peEbFJr^%57URR(;d(6}rx+8Uk?fz&gSoas>>WxqU literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/creative.gif b/local/htdocs/img/mood/neko/kaokitty/creative.gif new file mode 100755 index 0000000000000000000000000000000000000000..714ed16c5d205eca323176802573bc43390647ed GIT binary patch literal 6325 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/curious.gif b/local/htdocs/img/mood/neko/kaokitty/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..109d542c6536225bb5c39b4e0a6acc6fa543b678 GIT binary patch literal 2183 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aO9n;`8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0eFv;pP6*nNox*I1L#Z z7uweUx>7MkPKZ>Vwbe&M7W`4hY|~Gq5vAGROjbe;CF0I}93}+n8n96eJuPjVJDQ*82hMW)KUc-;;`8&%mD{as zyFy-GT4=`pM>%2Z(`)Obl+%2pM0LW}hg_VsbcX1w^BYue@0u%lts$0KiC?B*_4LQF z%t_BLwfw&R?)*AkZf3FD7jxZrusNTq{Uh-B@#(3GuVQ9KZhqd<^*)PlZG_^>%gg+4 z+e!#v^VcZ`Mg|Ut08p&5idp)H=q2Ye>7HtpkyVt96@%c5B8>kZ?T7Z$oEezW16 z;t(>0bTvzQNoMvNkM>4fceuVo z|M<71vp;K{I#{>6ET-$?+9Pe<+mm8;2&z0eHaRmaEn?EAXXh6ALux zbk)~{tEJ7c_o|tI(_~aDHX-DSl-25CIZM7FZ zBwkqdz0OZoqV!cSBO|s*J4SY1%lWx}*$GA#4<-%=h2>{vI>>&zaxysWY`sJCvn4-_ zS6-gzGW(j3)z>G7JIsN3t)b-EwRJL`X|`Nba(udyS6>QQE%^HK_FV6@TJ9}t8+Wt0 z$XR?S(|6y)cIVPuN%0S{s}lUB_^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>OnJEC%GMsEYUc=++sQ31+S~C4$q5R+||0Obg|2XNX~-0tHjbzZe}{P zPS@f3+Uq@qC(o@t{W&>qX~XYBygonPIx~0h9gtkOaNi$^9(3Scc+hZ2IdY}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmQT|;F!_bo9J55R*vyc$poPp_0&}gl zWFBr5o+*@JRr1=aCxX>rYSffB-knLSi+Z!dk}qwseLRm>d%Io)a|LgQZNUP)_})t1 z3u{jc>ogpwIK9qQ$3n+rr!=qhpC3P7A6w0(>Ao-L^24)J=Gu14`AR81-m}=>IBdl( z)7RH3_}N&ndG7=RBLjy+04QGB#Y`j|7!ERU3fh%a7#v_=g)nPEG8T{GeNIdXp5)u0iWrtMQpAwH>>+iab{Oh%@WDDuw02- zC6>czSrC)=dbOn|F08t;CO)ueZCA*ufXzD9QD;wvt+}Kfl1aTW;vAj#9$i=x6rQw3>p^DY zn)rozvNyM?ge?u+Dy3_^^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>2?WDt=|nQ>iB>!gCT1 la&Uf*_1W_9*fBn3?|E~!uQ`0GQZ(t_no8rF&5Vo;)&L5m<6!^* literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/determined.gif b/local/htdocs/img/mood/neko/kaokitty/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..4a168428b3f97b7cea81d64cb476bd677ea5a3ed GIT binary patch literal 1741 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a3kF6G8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0eFv;pP6*nNox*I1L#Z z7aDT^nX)qEao{4E_Fo}ZSCO=C?>oMdT>FXk>1ZpP!P$@GkL4g=kRRo|1PB zXQw{g_N2?`qx*!#cNgh&3o@L(v@~+NTt@JdH@9~bzrN=ySn}e|KF!B``y?w0?wy#d z9iL~Qfbcv!13QBxgDlYVCr~`U!=S;rjaimWLBgToNE@GSkc`5CM=mXrtUNz73=T9* zmQ!7IrlLs2l}W>Q+Z@ZFCk#v~j4TQbm!H_rQm?mqGP8L3nFS{G+f2MZYFt>Z+->!D zd5PN9rLMVrKin5&U0A1U>UPEJ>g#K(4K*jZ-rkgRV@<&0F5Q);dcGUkK1m5wK5)3R zPv)zXMD}+*&x4hXvt%18KHTUlvVNu`u}RPUZIgkGGVU^V%WjaErU@Dy&x zd3QVyXofBqk@N#b-|N%sBI@&4e_z%1-sp8XZR)JB%rNEx-Z?e}3c7c@3wbkge;4J( z?XX(g^=EZ>w)=L8Os|{@3Dsjg(%MFKb0P{;Ca5lsyLV>i=I7@ZIIF9~+%SH*XRiN$ z)7q+J2W&n&M2%<*Ry#YBukzWQm!F^eFB0kgXS{36)59IE>?XOEU!Po_WY(K?Rl@M~ zrBy+Pk1cueRX$>K@Xn;Gr^42rTa%MnWa@Ce;RG}LjYm%-t~*@cQRMk;>2KjT4F~IX wm*w0xOg}iGz|yR&Mxf~UNr8pymdx3?+3`rJakJZ+f-NsEEqf`)!@*z;0H%tZEC2ui literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/devious.gif b/local/htdocs/img/mood/neko/kaokitty/devious.gif new file mode 100755 index 0000000000000000000000000000000000000000..48fb4af554af801c4c398f860cb33e2fffc5ced5 GIT binary patch literal 2005 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

    )ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%%u!om;@P@A`m>#k%=V{yd|j<`b+&wQ zyl~<5B(tA8-<^MbA@o}5EZgMojrSEZ&1&uHmi+wuLRrjw-n<9DZog&S$1fNE@At1C zpI_gN9=Gj;|R21N!1Y+>fy$jBtp^W#H;3nPm&ql29Sn<149!7k5bHu2@4z!v{RJb zZc4?(2Mzs<8b&;lA0IdLF|Y|3NER+(n5-Shr{R$Bl%bE${+dp~rpITPOnkXSy%;q7 zXR8p?&u73;`iyaz+xkySq^>@?GT&iqS}s>;^5Omn?heuHFUoFh8Jjop zYG2bmIgR7sDpP~+4DpK%dAZ_Nd~Zlx({}WjPQ|p$q$BN9-HyIAT${S4TR2E;#rL9H zXJ&CKN%S&gG_lO{XIAY!p!jf6hkmn}_Jpr5woL53mFH`{KH#)7>*G6jc3NCJ*~}@w z{^TADuXD%St?KP+6G~?~Jxr@Vw|DpV_p*ZJpV{=IY%)J>J-gX$e%zk#4LHLHIpfhL z5%r$hs&Q?V@AiMMca`J>Y%t+;()GT!CVaJgI#a}HvsJgZ3mcxh@dCLYVe#YY;Iq`5d07?NEW4Pxzh3>eb9TMaVr@kk0TW?*8@dS}96tkJkoGqvrH zC&P-f%l+9+Yif4!vU=oZEoews*DG&5_hq?Z&DvU}jKYP{aty41?fE;2gTZW7T9aA;g;*{UXcsyL%@zJxzhK~?ChD=SsGV`8H&th~NHJshg5Js%CqY zy*7L9bYzZY^*Nmn4KJBJ1Qj^e{(AP3dB*8HzS^CMFR!y}nfrA~o4s6M@mq*bMkepg z+?r}X-8`ebL$eMpUVmlP*PVxF8LqFt6L+`l_&Z%;O{N#MvvS-%?X_PNzrJqo%N9mP zoS~#)&~T7}g;B;O!eHUyMjm;u9*vEQj<$&l>#0--JaT1ZWJy>f5!B$(D$G8^Ch}qm z!&EuLHWdR0RquASY@r>U29JE0Ov1TDtr%YT^@%WYXfRw^c5%67qu7qlNe?cqWSW=7 znziY`m5H3w)9!keJrCc&<2x-j+bAt`X>y~K!G_Xx7q=-Zb7^R8XSlnZ?T=LJ%K-g& zrsDrnzBV&no!Hy`mT8(y$s&gn*(Zg{s(%(dTRyv*&&J`GLm&&swMEM!e>q%TGQ-~d zY3D}M%(Xr9Zl8oL)?7r%O49JcbM8=Tq6Hk5zy zy}+*UFLuw&4DZGj_QG;Dre&{orxw1_^@-jdyD9baw>htFr`%~VE!B=+8LC~>Zkp`$ h-{WrO;r?s!_FH(RcDTOV#%13muV44)IVdez0{}66Ckp@o literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/disappointed.gif b/local/htdocs/img/mood/neko/kaokitty/disappointed.gif new file mode 100755 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/discontent.gif b/local/htdocs/img/mood/neko/kaokitty/discontent.gif new file mode 100755 index 0000000000000000000000000000000000000000..e28f795a436ba32c3dc741e228c955925189c7e8 GIT binary patch literal 1286 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{N% zmB`DmRk87YrViH}jx)1YEjk);jp4=yiTz9&-eTETCY9U`5>5D$7qTyyzvzkfH2sU6 j8jQ?#X9|>)+b1ZypNqbx_;e4Ke)hRFGv6F+V6X-N>+#^8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/ditzy.gif b/local/htdocs/img/mood/neko/kaokitty/ditzy.gif new file mode 100755 index 0000000000000000000000000000000000000000..57c00620779c00083efab637b5afa942bc3b0fc7 GIT binary patch literal 1350 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a2L?tC8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=12d{HE(XKAO;+4>6 z_bE-WYP{JKQ@v--c^+iaYgBq|7FX`AGgeZ`PS>~bKROp%V4mN!Svbk=PxXU>^LzUF z_1D=HeSCglvG;Nb0pvhnVNd`<298&-Kwx4M*7Av1@bFMOx1iIU6&n`1bV;zso#9Yu zINr?1UB$y-*w8RhO1RG^vZ$e9vWjR`jith~Lk!GChh$C`r=6Rn%K75UkIgI2GqU8I zQkfu*wEHC41q6`i1{MGS literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/dorky.gif b/local/htdocs/img/mood/neko/kaokitty/dorky.gif new file mode 100755 index 0000000000000000000000000000000000000000..8573666daa89c0c54d17b1e757af09f8acb41862 GIT binary patch literal 1818 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a4+cgK8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>1UV%xK(D!giQbfQUQ9z%aLL_G71t*{h!seUFcx*{wWOChIcho9m5yPg$^=Y~dg%4b| zgwJ1>YaQfpWm(0?OM5fJ^R6w6H7zr7xY2NznZ0VA%bJZF7`NAcz8C9x-7s-+y?0a{ zkK~f1Ug=!BIWJ}wWnAR;%#Yc7b>ZzPYhzE(^R<5X?9k@?{IC_f&EMZ^;b&vP=HXim zj0_wO0if7t7c-G?U^vLYDQH(xVQ_$fkx$Vrq@%FGtx=3Urp9B^5{8L#+Cl;|1($j^ zsk00Gu$XY*%mlq+p)H=q2hK3EHi@0kELm}Wo>=>$5Uwjr1DE(Tn}uqLzHn-EauriB zFnJxe%2At(;dW`(RVES1zN=bWbHWy6I?hYE6|(yB#H5>HvA@jLHtuKhle3s``RRl1 z2Hq8_yG+vW9I5YoC(0SQ@m61JWYQANjf!bgB#iUcys-R|c5bobv^}$SZGC-xL-Of) zb2n^Cy|GPr|2baC@^`(AjM%(;jkfX2ur=l4Dt~D{m0OcnUtB1}YOq&o>YIojX7xVV zsBfCLmuI+hb==yLcXx;R^If&KuV_axH}IaZEm-i}>yQ+)w8!e}dUvN5iZcI;3jLIH yOo2E1PR8elN6t*JERXw9xj1tz-{oa4b3xwa)MYQzy}jwstsVJ~*=h_F7_0$7ytGmP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/drained.gif b/local/htdocs/img/mood/neko/kaokitty/drained.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&J&Nz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6Or!30i7snc8|Iz%S8H>_%_V8v4@6#zE|1!3cYj^(D*=@oD{?v~ z?R{;W@66o5TVq?0p#5-iBX7@B>+qzc0|5_z)vT$=IlV#SWg2T`Wp3J8k;p|dbA=u| z&Q|hW9d~xu*6gcOw72)ooniX+_~y+0_s;I#{=Suw5#e2S26hHX23eqYk05zhj^{u? zqGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsSPvg;?*x)%yJ9(9igM&%~154JS zo|BUk{bpN~f0B{fw9I9pOS_rO34@iFmnySb_;yWPd1VsorcY<05>l_O(B56vt9ecP z!s_74y1kudYa<)k9!X88deCrrm()|K4X?iG#_VNl%j)HJit o$Ni{SoVtR~ec6#YJ2yW+&%u5AtIn@7Klgc`#mvzo)ow6XeX>xM*oH<+npS$-T2n-Dk zlarJGZ~f0O3PwX<*oA=Ne{Mh5kYH!W09PYD17=2`2NnOxx@V?2m1gFoq!uX{=$R@c zRVqZ5r4}m$WTuy$({SLqUz>Tin#Hb94o%D5O1*r4m1z322Fwk+>t))=v`mX%m3DuA>btIJ{=KWK%Tms-vO51x_15&q_m^{v=orkdC=8p&u}W{onHisw zcTaqNPP8lX^Rq*Ok{xLRI~|$NF6-<|yKwV!*g386?!4@st8%W*nCeyLvqj^@2HVnb z-K;Io4lOy-dEKtZyK~;&=2+V;@4s))#|A{uumgie zl0gL+H19z{!WWIgMGSo$ zzVlo%1(q;Ol;J;-qWPKOATvi+*qWK2)0kK+bCsrWnluJ9vI}YOMs3y%T z)z#&kA~LK64vp7Vg&jWiW!F~i8yhluv-Vb+>E4>joEn##Eus^%gk!-q5$)-(&hGIN z*N6}ZGf3QD$fzE1U`Ijnk&3%s?`B49iay0-WPIZGg2pH3>`jeVx(0<3pcS<-BP%CBOvp>Z^dl03wNdGzDn`jQ&D(*R-jV(+k%~+pPe(7=i$H+1}p*s z3=P0A5Y}Q*Sn%*rI}^8@jD}#+AqG+LB$tQ_u;crExvquraksBcr(!HVAou3am}WkdDX}E zt}bc3zoAat;cB+{s)U1K{QP>S#q%Q$#YkJn=}c%$Wh<99nX&rk^HjEK_26}XW-{K| zALiYBFZznXqxlZo#Z+!p73ADx&t$$EYrgFAJ)LH5_m#hlK0aD1s}#SkX6MspMn(o} E0L0wj%K!iX literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/ecstatic.gif b/local/htdocs/img/mood/neko/kaokitty/ecstatic.gif new file mode 100755 index 0000000000000000000000000000000000000000..c848689c01097f022f4a6525870f1e4e0138805b GIT binary patch literal 1365 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a9|lGa8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D!v6Iqy5xgo*RQLn?fT$ziD79 zn0iRpAXwLP4TIjfCEnZB@9zp&|I4J?EH|OE;;Y!Z%;`^qnJ4hh2wBjeojPG6Z%XRz zuy=R%HJoNT!E@6%WBL-)?tK!IvQHda6ud9&*Q}hJX4UxiEw!^#&fGiD%*{T}>Qh0} S(O`c6b2XO5Cq$W<7_0%p)d%+g literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/energetic.gif b/local/htdocs/img/mood/neko/kaokitty/energetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..a1f0d0c7bad655fefedf07766f138637bd1913f6 GIT binary patch literal 1961 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPJW<59Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kk$gC;phZ}`w^Bv^~ zJ#dOCqB2Q$!=zUpt5tUv^=fWg9k?MVxoU5x*<0^MwntJMRyjCc+9mZ=YQ?IrTK?;+ z9%r4EGX8LHmBPflnBN6SkJd@g*ZQ-gVq;3Xa`3GqXLfFW-qQB8j4wAr@#W=Z{>N=4 z1hDz*Bm*M@heH4;M%l$oBpetHGH?pol~foUU|{4^bPMSyY;bE7V~?rvn6!jpqMWvn zz)ZoV-c9Q40zWJ!95^#UuUKe{r}2R^a~$H&t?4k%xX`N5EvCUxqUp7SIhjwxp<$)> zsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1eADt;pTYQM z>TKaPrw`T~FEi^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLi zH4+;a9q*QM3|jKyqSDD;8Ski^8Agv?rWz!l;&BjGJIi3i$|g{-`H}BDOGXw6g$8xM z7L#s13#;OW;Kk;P)k=4nWH2!KX9nH1DrI0?X1KmiHY!2;>LwG;nytS|vm>|1Tz_^Y z>)Ts~-67fMWUIv1UuG)%dQPNZTEl&&wv|kCy?^LG*ww!|D!0bGD1LW0`|P`WEQ=#f z&9SW3>zwqVk$EBe9JQ`VAJY!hbvA`|URoG^qau6qmdGuJ@3!wvkG{K7#O>re-mp zTh==Yo}ON6*Y3A>*VorKHb1|zSK9jfwVQnVuV0f3GXMGc#pTuQasr3|VrO7vkYrE> z2G9qj08&B(P)2~#;ch`$yPh2dNp9UTwpw>A0+o;UscI&PtlW@#h`}J1uSK#Ufq~H^ z`qGii;s%B}rh-ZdrAik)?-;!$Cp&(yD~+qO($8 zUpFu%p0|6tYHC*Kmi&Xq=45`;jM-Xro6F;L`Kq&fJ-Ip9w14QGpV@Hr9&gX}<@fg0 z@XP!DDJ!^fSna!(>+CMd{wZ|E%2lAYjqzdZyCK zX!EzXtY$M!_uRANW7}HKZ9ey^REnRSn?GMh0&5_=0tSMKfXo!pjjQzVQYc}&y@=HfXJll8)0tV$^k`06 zdXCX1oKIqx@Up=9&W-z29HyjRTJFIvz`>=!(72LuUY6{sPgdtKpcQ@5dzSq(no)fvV{kzb$+2tQ%kEO6TAE|!O zaPO3*quw;>h}Fpx*ysO}{VP&(VwDwl|GPP}RyohN_uO7~Rb%7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/enthralled.gif b/local/htdocs/img/mood/neko/kaokitty/enthralled.gif new file mode 100755 index 0000000000000000000000000000000000000000..c94069bf5c1461cb8046e9b0ffab004dd59434a3 GIT binary patch literal 2263 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aHwH!y8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&LZLax|>JU1*H>aUoniEC!{LBP9}WW zvy(Z|QLd2^X}%Y;GTTIFi>PE?3N7CBFLQHp_GEkhWAjcIY=3uKK3i=|=f;X>=Z|sM zU7I6wpyTxya(!3n^ zUA5Aa*Ea5E+ou(&7Gbb^{g^v zmFqd5NG+bbJC{5=YvgIYr}IVj2u3nqEtolle3p8diF*3Ud#evdd)kiFF#9Mo(US z$%kd(y6Jj^L)izI0n9}mM?`?*Na`YnM zyK!fJ1T6A9KBIeC%8JcToac%^XC`{y%r`KM)ui8YU+v|KIw5X4-#-SOtbrFd72G zIs_E|bNji51UowhxEkphFf#%@tN2gWJu}UzG&3h9wMfB0&r~6)QX#S|wOAn_Grcsm zghBBq3#SoKp$;fyK>3J)<2eH(hm6OD1qYisgtcN$Y*=`>T|n7uj>pDDN4t5MGip{C z9yr3lWTp2;;?rXWMnzktD;-4*r#cwfPWas1sOCLW&t7Q8O2OslXESr`X_07XxG;mY z=8?~;i!TEDoNCpk{tA9^e1_L@z6)K&i;v9n-g!!A!BuS^MsLmz-34OlC)Z~jpLEu0 z`t##EqF=XN{q=3lrTz84g^qGdYI&2g^Iur59+28K>^h z-L5ycQ|NQ}goSsfnfXpsJ#}5vP;QH6(6+a?cND+g_V#D-yL*!hnXmtm{_*bdiOJgW z5&{UnvokO;NHQn^{r(B)ca{kW2~EvxoN6*BHY_;QB*3o}a-ty7rCmTgEayeQf+L;M zrd~cbHYT5#tP#A*MsmT^Q;oXJ20RK1%TCQOP3IE`2v+l+#l-eQL?WT#;ylC2+jz1{ zG#VIK`nH*PZPoN$%reL6Y}6Kq&{c8KLMN<@vqRUXuXef`^+o#@WB$rrEjO=aH0~(7 ze@^w3h#un})_*}~IXAzLJy6b`Z93;i&f~e=`@N?5%y|FgbP%i5jU0s+jm$Ib-#^J& zV32mo*)zZF_l*^=F11!Zv#pu3{BoCfYWUNe#i@Dsw&mXs+4X(t$HynM_dUz0`T2Uv Oxy8=?`z%u&7_0%P`3qhE literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/exanimate.gif b/local/htdocs/img/mood/neko/kaokitty/exanimate.gif new file mode 100755 index 0000000000000000000000000000000000000000..8bb7d52e488b06afa2f68021b09964908da03a3c GIT binary patch literal 1293 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aeFjDj8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!djzPm}|8;TG>qI_?X5E+^VLa*XEmO^iIjX8n zTfEHm&TK82dP}v-eEs>oyu2J{4&M$i?rQVrGgH{UKK?+XxO74EgEtH(d!)B-=@Qx$ zGhz0_MRz&^6;7X<>p5L5BlyXy>l>0!&+`>5es*J<_~CQ9lI3}~4m5Mi=NTv<{LIe4 z&LGJk3-t3LBtOgX90*8sY-8kL6JWTg=+Y&`&aps3Q1NgtvlSPQ!2%Wc4h{QhJem_5 zJlnLBSIIays5CIJWKHThX{>T?mTvhsnXb!fXBK+YdWl3OI9#6LJ6}uILhx0#Zr+^77KMhjKg|4AuaKL)v%% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/exausted.gif b/local/htdocs/img/mood/neko/kaokitty/exausted.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&J&Nz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6Or!30i7snc8|Iz%S8H>_%_V8v4@6#zE|1!3cYj^(D*=@oD{?v~ z?R{;W@66o5TVq?0p#5-iBX7@B>+qzc0|5_z)vT$=IlV#SWg2T`Wp3J8k;p|dbA=u| z&Q|hW9d~xu*6gcOw72)ooniX+_~y+0_s;I#{=Suw5#e2S26hHX23eqYk05zhj^{u? zqGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsSPvg;?*x)%yJ9(9igM&%~154JS zo|BUk{bpN~f0B{fw9I9pOS_rO34@iFmnySb_;yWPd1VsorcY<05>l_O(B56vt9ecP z!s_74y1kudYa<)k9!X88deCrrm()|K4X?iG#_VNl%j)HJit o$Ni{SoVtR~ec6#YJ2yW+&%u5AtIn^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPC1}L9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D!v6Iqp>eC-+efxPr)ft`jDLA5WOsQ%^t^y>HI~Tl1&{Ztsv7Z0n;H2WoH8@2EMviD z#$D`u0erQWHZz`_!G1k<*UZhC%-)>(wY5^Er%!3L2c=X>tDl-8(cARrZ*|UxBW9)Y z@#psJ{QO)X^Ln1%U6aqR)~^h2Keu=H_xEf}%uL9E!VU})Szw^NMGcgK#D;cWRy!Vn zjR_2l!m@TpA|@s@Ffthgx$Fo$&@fS!u||fWXp#4Hwa7(pBpMjJC+ZZR+H+#kfiqpE zwd<~UeoU;rv%l#jbm#F0#r1q!bME5Q$#FcMrYg~^b7O@|c?Gu}oV3pQ+BV-$Ps8pVXy%UZ XnDy~P^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a2L?tC8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=12d{HE(XKAO;+4>6 z_bE-WYP{JKQ@v--c^+iaYgBq|7FX`AGgeZ`PS>~bKROp%V4mN!Svbk=PxXU>^LzUF z_1D=HeSCglvG;Nb0pvhnV^Cm_0|vq~XdoP5W@k_^0S1C&i-4?Gi9})2VFn3FHIoiV zAk-a!20|Q*Wu^B(e18&qiD`GS?zu^km#b1wZ+(4xnat(9ubk#@?k%b1m6FI=pz5@` zomIe0K>Xz`CNuv>syiw+B%knL4sq)?Dt>m-AaYr2)zwA87Zr_**UY@C_PS|F@hr2S j#b$5U^J?qwTd`}wyZg&sgZ}x>*_g|4l+&1pgTWdA-5dHa literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/frustrated.gif b/local/htdocs/img/mood/neko/kaokitty/frustrated.gif new file mode 100755 index 0000000000000000000000000000000000000000..3331bcbb6d7e2401e0fc6d3318c51aab7c05b2b8 GIT binary patch literal 1822 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSv`!yMfh66sm7R~o$93Cw7 zZ8U6EQVlT4ys%tq=Bg5{%gR^hFjNKUewd=|x7K4}n&|AWuNc;+&)+pi>)Wdr@{SkKH& z&ddvVKiC#D7{8pnkT+x7naU5R+gCd3v)L$Ydv#UUdU1{K#ME~OcUMM#>D{y=wud!W z&i&k;ou8jyn0R~N--pvNO~$Z?r&6P@ExfWZIrdjeXSmMsE;c6VhRO#F_YNtrO3$dAsCjFLPP!If&*zV~ zrcM?&<~u3=F7=#yI+I4Gkot=Yi&W#D)L3nGo4z9U^gQ3)$!Q0-a^5=^Q@#EDy?xB? zJRArgvof#){R{H(6`+q<1Qt9v(9FRu#xo%R=uvKIxfqVXB%ntXjJEs;IMC3`sn2&{ z$A%Qoeq~1`9*2Y_$0iyC+sSx3Jau6*bvD!~5GyD0ldh{A{)Y?cac<9u`%dEhopz!EWhp0NAKtSLl zmo6r@3KNNhhLe4Q!Dc*}MJWdvSp3XPJU6SlPG*U5Qkk$hl-Jq^IhQGb8$UmTSf1pwL7P;Ph>Vd?X~Xb4}+w>u7yQ8YYJ4;j>*W{ n$-Jm6&X~KHb(P3mphvH-)&AY8ySwPstsVJ~-_15qV6X-NR_?~E literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/full.gif b/local/htdocs/img/mood/neko/kaokitty/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..0b6aee37d62dbde6e57e0019fbf0a3055835d7dc GIT binary patch literal 2362 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aF9t>q8IKJM4mNWLYsH+{u<&rZfU?(|9|jGsU1H1@ zJPHcRM|xz<`2;R}Ogc7Mjxj>T(joaU19Q@}7Rk-ad?%R38u2(dq`A#@h+fy@>G0fX zo@*vstkx8Vi@mNhz0UspvNUKmD;LXIt}l-hK2tt?aax@q<|Z`lf?ZLja{30-6(xo5}6$0sIh z_j}wrP}F!;8=JH5^BF22f`f&Dl|hj~9vB?2P=Z6lpuxF~Lzc}#!lA*X zgIP6diG@SM(RLx{IF<(&9yfHdG4n+H419WOx`F9Fmq-H!#%V%{uWTZVR2gTn3b%b%&+N{v5$hp!-#pd4ns(O1- zrgUGf*YwmoU8SGPmPB4$61S|-^U>ekmm3})X5f>Kt9;OK@0dRG53_{Y z9t(!YhbCzRw=L-iTH?f{YC0+8=A@?#OnUrm3Jt|-XXi6lJ~P>I`T6<9iiJ@oQJWkX zXZeK+$!IcYH7?iWj+tsTH6wII;O4f_$cwN2mq!FH`Wv||p<%tp<7H=Fd|G>Fx5n*# ztexh0xBF}Rr6hbL7#b~T^`%Y!dZy^P zcM4m6Qe7=*`fBfD^WAlKKYn?0dq?r>duMlVe}8it?;kUXKOf#dn$oVkUseE{-$!`V zKO6i}-xw;VXLFO`(w3b6yPn=QUz~n6&c1k==k&!#I%V9SU#bvMjEo;=iln~wuq%-^SBrk`z8J0qweWTmok)ZNGhtIw@t?aI3nWs(yy zBkd^D+KR1f-Dl<8j+6Di^f+v%+sjEk-Qmj{_ct&y{M-HM0OQWK_*ZLhUw{8#f0MlQ z*Hd3|ukMaHueB|Erc(OusnJ2b8ke4&+wNd!_UDY{)>myx&im&1?k;^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M48z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7VPi9fdK?W8- zGZW9vs;-k+Vw_YaY)&~lUn%j~oEgOqjf+|9lzh2@pC6d%ndxR4HF;%lBkyv#rBbD< z1KZgr&eCyESQ)V?w%<==!Zn@n^{hrlDb{7Hqc^%eoy21~_0^44((9RaWQwd0*;BGpI9>&Y+&qX z=X=vL^GEW@Hsi&wS|be?CLVTU?B5e}Bgt(_w_#dH*0u-F=g!}`Zj1NV&DmEKBlS%! zuP)5#+>v{H&D`ookMA95=4L;)^Ye%1qn7gQ6ZZTldUm#$odq=rWWed+IdXc?fu;u; z&fK^l`B2r>V|)Hc7`gAM zx94X)AewSw#v=F6ygC=Yr1ym=-p-wCwC&A4e*1IhcqLUG&$U+avz)Uu|M>V=zp$Hx z05-qBL5=0Vy%lpeqBxtoX5m%#Cj`4^XhyyVK&i7V2QFe zcIq@1%>!Cj*W0hWCt_*r5VQcw+%UBW?Y-pU!&i9~X z<_+bOEqU#FM?D3B(eM1fYfsD$rDOZL^^;nxrX{;ipTF7bPWG?Q87l(6yXmf!+VrMl q2j{(Wdp{b!zki_l`LjEbKO7#-=~Y(GoAaUQ4kIIK0F3m)z#0Hmzqnce literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/giddy.gif b/local/htdocs/img/mood/neko/kaokitty/giddy.gif new file mode 100755 index 0000000000000000000000000000000000000000..dd0075dcbfbc4e00872393a325d6f3c6f5117e7b GIT binary patch literal 1299 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPJW<59Z;}<@(}~aLk30;8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0eFv;pOLNGjr@|k!WbR zFwbssmWkDr#TS+Y)N}pqFv+^oD`fghCxAgKd`?6n*MZ0ehwE$83a6d13RAnjIc5K+ zKR3z_++I@teACubKZlSYikWJKrh6~FKr?&Z6 zE?{6>ZnQS(XvO5L%WIYQAKT(_QTxi8^qqD~x^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPA;HA9Z;}<@(}~aV+KYJ8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tC!kVATcs-FDZY%Y3r%-wGsQm{#uzh+&FN9nf-^7UF3}eaR=;J`SWrTUPtd>*04^yeQE8T z$r`hRTqDcVGA@cnPEwN zMb5p6MWBJfbE0zcsuqh$2Tn~hOFVUF=7ff`?Pld%Q*VA+c5b1wXpl|Rf`$vr45zmF zST0~-TyC^B>1f5|tjlYa_aEEhaZ&rqn)ID^OS(cdZm!IoILXxEdc$#M_FIpRMqGEe zIXC|DKA9WS^`bT!a{tzyZK#&iBN;B{ax)^$tyg$@+&vxB&zB}ovh9}h-L>UqQ`hTB TersTDwqDf|IZ4%PqM^MIhh*_{ zzkYkhA0k|nG!8CsU{})p^|9e{yC1)gO@qR#Ln}g;t2qROYB?>B5w7U1P-wilF7R@b zsdm|_rpwPuCq#UCzy>!!3bOUmAgC>|`5y}xy3)CZr-tK-k_ zTkz$j?0xy?8uu$}e!l(u`u=+Z1w@#!Gw?7-GN_}6nT~`)!+|z#UNaGegruV#%*+9I zc3f0+V-T};`s3k{?ApO%CzLb8XsK6|9{aH)7QxR>Ph%*!7Sj>@;9N6%(;*!T;}?ug z>;e*|5hg2wmT(Ga*mhmeY+?yvmGd}Iy6WP3znw|0s}^JjY|J>U7BE5d03&P8c0C8} zvb=yDx%czddY7+@*z56q(bw4xAMWpI;+B54t6{^1M$gw;5qlCg-B>6;^$ z%n}X$CS#hPv1^6?Y`?R=j2YNANXFz|SYY~g#YV}Lyk4o#ukY|!>9eh~-W+nQX0cap z^o3WMPlJ`Mrtg~b(`iG0eAfMc6D!`lyT{$A&EsEZQ+b1(nF)937&tIAvToJSQ?Vv@rP0Qt>QEJvCh~lCS4yP}=F4X2n@H z2aMIvGqdn3{P6tr{K5iG0UlPbiOVms_y7aNq4eeX)qX3TcvmgZ@?V>S6euan z^%z!{>iTaLOPRHj>TW2@Czq_OA_phb98uHIKI^EWi*psmF+TsquExIw& zH(g&ai8FfM8Szb5&g3{Zf6Wowl5uf@GiC++1E&lp$WBSi`Z%>D6BXtp(-qXA+ zH-=nhTl>f^FJj@R$HDPUx&JopD(zXb`F7k1s~zS29NfFB<@eux@Z%#W-B<$v7U?TA literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/good.gif b/local/htdocs/img/mood/neko/kaokitty/good.gif new file mode 100755 index 0000000000000000000000000000000000000000..afffbf1f4b312ab5d511da3a535439eb8eaa65a0 GIT binary patch literal 2278 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 X@7Klgc`#mvzo)ow6XeX>xM*oH<+npS$-T2n-Dk zlarJGZ~f0O3PwX<*oA=Ne{Mh5kYH!W09PYD17=2`2NnOxx@V?2m1gFoq!uX{=$R@c zRVqZ5r4}m$WTuy$({SLqUz>Tin#Hb94o%D5O1*r4m1z322Fwk+>t))=v`mX%m3DuA>btIJ{=KWK%Tms-vO51x_15&q_m^{v=orkdC=8p&u}W{onHisw zcTaqNPP8lX^Rq*Ok{xLRI~|$NF6-<|yKwV!*g386?!4@st8%W*nCeyLvqj^@2HVnb z-K;Io4lOy-dEKtZyK~;&=2+V;@4s))#|A{uumgie zl0gL+H19z{!WWIgMGSo$ zzVlo%1(q;Ol;J;-qWPKOATvi+*qWK2)0kK+bCsrWnluJ9vI}YOMs3y%T z)z#&kA~LK64vp7Vg&jWiW!F~i8yhluv-Vb+>E4>joEn##Eus^%gk!-q5$)-(&hGIN z*N6}ZGf3QD$fzE1U`Ijnk&3%s?`B49iay0-WPIZGg2pH3>`jeVx(0<3pcS<-BP%CBOvp>Z^dl03wNdGzDn`jQ&D(*R-jV(+k%~+pPe(7=i$H+1}p*s z3=P0A5Y}Q*Sn%*rI}^8@jD}#+AqG+LB$tQ_u;crExvquraksBcr(!HVAou3am}WkdDX}E zt}bc3zoAat;cB+{s)U1K{QP>S#q%Q$#YkJn=}c%$Wh<99nX&rk^HjEK_26}XW-{K| zALiYBFZznXqxlZo#Z+!p73ADx&t$$EYrgFAJ)LH5_m#hlK0aD1s}#SkX6MspMn(o} E0L0wj%K!iX literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/grumpy.gif b/local/htdocs/img/mood/neko/kaokitty/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..cda97f1dd44e60ce7c8d8e9a485e77bb0e9f82b8 GIT binary patch literal 2012 zcmZ?wbhEHb)L<}Y_|C;};J|^XsHld9hC_!AIaw_|a^%S2!-tcz=gisq|J=R*KwxNS zn4Fyaf9rpSQ7{?;!!86A|8x7fh6Fo12DlpO889;fJ*fCk);%-LsWdYuCACPwK+jYm zsZt@bEVWo6ATzx*wS+TDwqDf|IZ4%PqM^MIhh*_{ zzkYkhA0k|nG!8CsU{})p^|9e{yC1)gO@qR#Ln}g;t2qROYB?>B5w7U1P-wilF7R@b zsdm|_rpwPuCq#UCzy>!!3bOUmAgC>|`5y}xy3)CZr-tK-k_ zTkz$j?0xy?8uu$}e!l(u`u=+Z1w@#!GVm}+GpJ*PnS?^afi`YIGZBS^q@x|I%mH_H zTvR;PC}!>SM`J?6u`U7531=i6mY$l*8qYVybJ8=P84NMc?qmutJ~v5)pF=fc^0Eue zZ2SrqSr=AZSn4UP5YZ*_FqnmNm5|MZ1=?2^C(JK9J1e9yd|~qCF5d+XuMaSD-71Qm zP^J^Ru<$Nd%jv6mvAdFgs=b{pR={+)@hg)mE*E>T+brYw(fZ_^^P1kx$WRPR56YuH9UkdOaN<7aZ$kl#@I2qfn8NL5^{bP2?s8@2Ljy+f+1! zpZQE@&c1hN=ZA*#v+el5xCnen4p?L>te~J(vgrI$&RL+K(Ym}KVt!cft>DJc`O$~7 zfI;&L7&NDXVg<^yqvvOy<#O@9nj5_>`sKGZ(qj2c`zxO^F}xNlxXM~rFJ{wlU@g;O zZn=EdT{}J|9w|4hmyMFxl(w`;yWn7yyKyVHUIzs literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/guilty.gif b/local/htdocs/img/mood/neko/kaokitty/guilty.gif new file mode 100755 index 0000000000000000000000000000000000000000..2be353057283d47bb79fd85c2a92c002b661e3d6 GIT binary patch literal 1728 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=N#nwa&DGx`8S!a%W7v9denM}SS@g9oaYyACSy^k+PK1S zy6L#z+B z=iS<<%Kbl;d(+GC$10MJt>+Uu{dLM)08f=^f2ZE-Z?e}47zu_3wbkgUw=!E+hKWn z*Pqql*~eF=L?$iK-1snYO}C_bOXtR-W4+Sec1Obh8d)tG2@bA};>K(e4x5%7XOOjLYVcrKbaJ{% zq?3xo0@X9K4Wlo~bP7NB>9(mp^oMiP;(!^FnNqR=4KGhG^Yv8Qx?@Yj)#c$!*#fFW zUWToTjrTKkxaM%2nZ0V!(THmdH#SJ@XUgyv%f2$H^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%8Ej+5B{ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/high.gif b/local/htdocs/img/mood/neko/kaokitty/high.gif new file mode 100755 index 0000000000000000000000000000000000000000..7b1337480b9f123704e35bc5fd5b07d112efe0be GIT binary patch literal 1611 zcmZ?wbhEHb)L_tH_|D33;J|_8>^XC`{y%r`|CA|H{{R1PXlR(6ocw?5|LZ$a1V#C72?E=bPb38UK zI@-<4oKdsF@W2rUCM&%+5}zJ3Fe=(AUFj%lIMu<(cEac8Mm6u5dh9|EA`+Il&2h-* z)A&%d{4fJ+$1#>uS5$)*S+Pomc9djZULCqvXvVA$&#$ic<1Tuebu}}1ed6LYk%rC6 z!Q1UP``(@kTh_?LHsjt|>2O`=2^PE@*Q|G}zp}XWpqcK=@|2{b4wCY56$?HwZsQPW zI9qe+Q{&0(uT4{RO7k4gPv!i4wDXtoi~Sn%#=Ub_O{H zSzzE?L=GGqi3Jaxns}L2coY;K9qJHO=MxABR65iq!(NeMu^{Dmhlb-c5zCDYC)>1> zSIGn0ZBPAT129~K8q^sm**Jr!`^REN#ReRDFl zE&+x>MIG<%ugTXL*)Da3MsIr+v{>@&K3%Ep4;pu~uTgT?Q1aew5Brm2D&FQV91fIU zm-09;<6{$R!_KxTGp}w4?n_@B6~-a7`B^(pU>a+!pz6!ZD>#+<=13iQb$xmK>3!1G zW^Y@u`|=|LBLjy+04NEti}`36G%z$VO31bR2zYdWkx9;Niig4DhF%_K9*LELi%#|_ z+e@i57&tIaVhKLwV!439W12Ac4H3=F&)uh+g>xNwIcfR%#jdSF3Rzz?f+jfg9`ms* zU3RfGa4FYE}K8wCby E02K#sdH?_b literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/hopeful.gif b/local/htdocs/img/mood/neko/kaokitty/hopeful.gif new file mode 100755 index 0000000000000000000000000000000000000000..3feac74222c4908827f3c62887aa15ac7f986eae GIT binary patch literal 1756 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0yrK*MQ3Q4=ToUfX1hS%0r-fJY2^`2UZJ$LI=m@cHSyHxkwqzu-c z)aV88qBrnd_S*V-vtIZPgQsP(HA3$_4z{dhD$7`~k#Q$GpFm&DrHzd{ymoGiJ#%AI z>&mZpm zA9rrg&f;c9MnnLxGq5vAGROi0;1o&#>@a9>Zex~ZQ;=|IIMT+a8ziG};E_vljT%bovA2Nab?nw-8ScB5d-5S1}1?WnVSxrnPw;Z?#Rl^PZ;LgH_p@Xx~Oq! ziI=;OY1O6!!3+H5-9#d%9=N(VE;{Q@*VolomnVA{*=Bux9=Xxwx>M^cv*mYo+8>v? zk?ruLk-6f3(Ua_kH)oc|UlzLedfVGGM_ad-9l5hp3WEa-jC_i2AsvMcZjEB> zF*P2OmM~0|(-sn#DY(?TNu6EbhsA^gKHaP_i_UmnP&>M63LLZ!8xaIKN1@^wE^cOD_VKsLQ*(dHF>% zWTmQWl&{PoA@pxsmO@TK2XW&(CSe?rS(T-M?`ZzVezg*I7BGXS;FcF)shrertcd JJJ`Tr4FCvLr*QxP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/horny.gif b/local/htdocs/img/mood/neko/kaokitty/horny.gif new file mode 100755 index 0000000000000000000000000000000000000000..493acd1801f24b83ea272f8c28cc66517eb23ef7 GIT binary patch literal 1882 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

    O^>%G0%XIUw11iG}lC zQ`jv@#vrCd`RJ>Ac5X>OFwt}OvYRHkmnSmtNb|0qy&>kFee?IQleb@f=sC`=wp{n~ zg5WzB7JHY!nDzNf)7A9&^KpN7IlNoOvA0{^f8U-j4Tzv&XJBEFWKaMG%^S3!NoZi; zQ#7m5aAuWe&3IMG$xRH5)0v(4d~Qy1 zXq?K-E+Wwty!7HkyLKi~ivtW7Cps_I%C)?5Ac(#Qx4ef?D{WK)X! zraM+&4m7UITfB-_>uW>f_R{xmOFhk3MenJ5Y`0cYq9FR9+1W*|r>DP6+EgRx;bvgs z$h2izyPunY$;$X+-saxVeobGUan7-~&$ep9+Mspo>ZN+_eqQE%V{@YX(z(&ELf7m_ zm$vO~D0Onqt+&$ zpUidG$&|X{s@By@F4ps=os`;o{g7Alt~iU`Z=)_P&V0V^#P03y@9(p%XXA6&k@Db} zv9N!fp#nC~zZ$UE@7i{tkvZ@xTdwt&2F4x!*>0`fS09a@%0_u;4ORzqbE6nNJ5B7_0#iCEwuy literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/hot.gif b/local/htdocs/img/mood/neko/kaokitty/hot.gif new file mode 100755 index 0000000000000000000000000000000000000000..2365e5dbaa577bcad31d16f6cd6290507d11e3e8 GIT binary patch literal 1943 zcmZ?wbhEHb)L_tH_|DF7;J|@qMa7xS%>SobefjV3zb^OxvFZQ+|99!S=_4$hoSe)s z3PwX<_=bSue{Mh5kYH!W09PYD17=2`PZj^kx@V?2m1gFoq!uX{=$R@cRVqZ5r4}m$ zWTuy;zNI1a2$Y8PP&5TbfrzXlVvq(53EcKqO&B-%Cb5mjila1vila;|5 z{tFD`r8F2!96Xt<7S5V-@`}Ux4z^8ZPft$G3R~^TEOSBY^Xka;YHm_0NRp%>a>c6)CYnbRAiPF4V^9;*dt)=p=pJ%Us zckZ-F+5Kk)v%mXgO~@*Kd7@Q*`MJHjzrTMVd$?PD#ezMRtdH5}#mCp#{Qmy({&s)= z{rmp@zQW9e2rqU9CI(3cC17~{Mh-6)fds|Ft-QQ$A{K#442(={ZgV;eA3OFi+pwLu z@$pf^1R+o`H9Ya0pu))$5NYVZI7^XrgN>%J^4Zxe%n}*}#j4&jS*lj4WGz_MxZE|< zEB4ox%nQr`p<#Eut{!Nd#lDa0uGhBAh7AeFr^QxpTXt(}ir@_1UuKR?o66=Z1xRjj zxXQx*E{|15f-#`CZvHLNKj!Nh51R^0NBB(p^!Tud>S5jPnG2ttjkdncviIADkQMWt z)u(mMD0$HteBZAu#o?lp~-|uI; z>+`D{OV!Wh-A!=779Kx=;UOZC08Bru{7NP>3Kkw}WK!buxe<_bxS5HKM}R>=$-Pt7 zyvRjD;Q#}Zyld7Uj|7L4-Hcp&dMbjFy=UpC8kqz*q&4)gM6q3s*tDE+2HT`xH7B=Z zTw2V-uc7;M%c@{z_5`^TQVUjHU!uA_>+P?tZ!WIkIXUZV*8>fot!zRnKeWs>nu{nfAi&d!$Dn0VACQ7rCvslmaMQ&vZ@2^bfrcIi(|`j&M? z_ulDw^P}>(%=J<>_2?1=O@o5mG4zYJ(ELzQC8+MBU6GioWH3Nf+*AEWWWwWWxSx|8G zSjYdMm^0<8Q`)9zr(az?^G*E90OM#r9npg4XGNAzYV|2wl>|%_alk}T7J9Q%@z#{y l-HV*B@08_|_X8%1$0sK8`=7Jf`SIC>sp>uN?f?^oH30Wb?g{_^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/hungry2.gif b/local/htdocs/img/mood/neko/kaokitty/hungry2.gif new file mode 100755 index 0000000000000000000000000000000000000000..9e60e1bd8f4a371f519fa761a3d30ccf8d33ac74 GIT binary patch literal 2285 zcmeH{`#02i7{@=~`7$$dNiv#>nsLizXk6DNR!uI0axIEl8HUkBjY}fC-%&|tl*>fM zt!cWsmP>;}YAUtFU|otrj0#~nUCy$nnjL#~kM>{K)AQr!e13Vo->>I!rMlSI9x?z1 z;14+<5{YPsi;9HOu2HFM%*@PaG@6trrAz662c&em6o8!M10SW<@1^AyfX7>Y_&(ng z_@5*|lq&9a_V=S~_jWcnCBu*mi}+Q`l|kPT&tQgyvj}8UD?;cA!oGy?Sb{erB0fA0 z5SQc>%w-=*%NZ>15x@=u2&?H<&3|wTyVfYUt@_HNv#L7oMQ$~M#~fui@?@!*s1=~> zOlR@$Cjdlr(C$xXAy3mGberc;jlKuZ^hdS)vNbom3t{Zt(|82w$#>*7k&OJe_+Izs zsJvNJkLoW|N!~AP^3iUq+Ut>oL+X&BYjnjibwzHar!Xqz;Q@}-)u3wXkXj4pQuIz3 zQOlrl@ zUrmBYvh%cxy~-k%g-|oq{L(CKeF-Qz1vN|EqrJqALSu~TVrdAwn`aLXYew}F*~O^j zuNjTp(msJ3WN@Izd#dl|YOZfp63)2&6t3BBAfH^>j*2`hFcIaD+#u3WZHr;UT)-*% zInU0(8DfO$f3y-p_2q@RD`8n5}6#^hyU6Umz zA%flD`$_}bWF7Gmik;jf_P8`Nawo+PmDltPIRr zQQ}qYx@|V2U%AAK?yOx;J?kjG^V+LlkJeGLtGRwIqsYFa>x+%`d`I(%txDK$iT`c* z-M0;U;`!q{Qk7u?B?3Y6Fder=Mb+C!`(c_UCh@ZkKkV0ZgY9|h`^ei<*$_6L*;sqy zDJ18DN?ZUBJb+m&x|Dh+jDoUNa6|ya7Ufeo?l_)5!3*nf*`?TM;L0AE!mQ$VdkBG8 zFZqnzf@5R8=}{gU`5tl6?A#+_!I|~PMI+5tQpo@#OY%Z+V)X{cU<-}B$0hOb|U-sSj z^kUC~_}*#GhUiFs4J5>0=wuPBc`eksl zh5P4ghDDj50H5uMb3YdHq>SpYAE#P}1Y9|&*xFx^Gvi(p8Y9r^=qEiZ3`=fG3G(B! zo6(J%Y!>3Sy4^+Br_LE&B#kwP+#lVhnOH%+Nu1CiEhRGB%2ye>-s|L!dvva$aQ3$0 UZ$IkIpk8&UN{XLIg&<)67ae4VZU6uP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/hyper.gif b/local/htdocs/img/mood/neko/kaokitty/hyper.gif new file mode 100755 index 0000000000000000000000000000000000000000..c33e89fd32b63cf0fcfd3305e21f3b75ad968f04 GIT binary patch literal 1312 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXPEd&GfCx}NV&Hhrz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN z6@~|nFfdu^y^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D71^MBz#|Y^QgL@bi(W_hH>+RROQ#ngfDw` zGABC9HS&kD$HlC`wxb*ks+pHoNAhpc4BGbg_KxD$%YI0jyt_9kpZWS9=^yVNpO~y| zE+K&MJ39kAgCv72(C=rF{4U3HARy7Pjgf;*fZ?K|OP3Hk#{vmK#lyYKR$M#=3sl@Y zH0-DGXijYKY|~C&CF9_r(!juyHL2&MvC6qwy5-+wx-P4oS?E#gC1SO}p>dvHxS5Pa zVJah&e{$T}RTozuI5~tm*c*xR(kT<#@%fDv;r20<(}Lt z^-(J0wD8*-)0tWC>(*2>JUW=`sB~B2`UCfq+M52M6*E5_JIm+3j74_WmY0_~^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w`3{2y=Qd_pHU$ZXh9hl!xK2K@r>W-_2G^~xm(Ux%H+|JMgH%3*H#r| zU6p2L!sfgEw2HT&`TWXVHNS!vUzx_b>DQU41xv3^3T7{PYgN1^d`aTUc}r)6=^pQA zdn6@L`QX5%T{2Ilc0`G-KEJ-|ao$xc;}3BwWv7?@$udZ}eKb(iD(;P7(vhhXb+i34 WBGx@U*CyH|r(0EWr^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aX$D3P8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCL^y>#jhh6Klh~t3(;ZRz=K6Ijv^vZL&6MPLAcS z+G?TKPRtd&XLPj{);De}dF}P3`@8PL{mId7u9@O$9!Co#&Hw$7So(CG1othGnL9T> zKfl1a+^$E$By<0Ke_^xQs4cIrZ%EeX;XwG0oq?S}l0g>ezl})#ljAuMkm%UP$iXJS za8c2vONgCgfrOyq;a+AdE*^sgD()Q`_S1MYCpLJtX(z9ead1#+U|`9b)N|5U<=iaY z@^3O-m(|WJ^r-a`nKdQ-aHH^SzM~wW4OixcxJT`kGJbt_ZA`oui}bWrjhop{c!@S# zbGW)e%5|IV>C$z#S1C-)`|_(G>E6`p`C5N=m~ZfHHxK4=JF{csx~ice2Z M)1PlEA;4e_0Oe)NZvX%Q literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/indifferent.gif b/local/htdocs/img/mood/neko/kaokitty/indifferent.gif new file mode 100755 index 0000000000000000000000000000000000000000..8ad9137c4b9e4f70953a4ff42433c79f91257bd0 GIT binary patch literal 1739 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a69z^O8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H~7?S$`zj+_I$6lS7v6e z_i7F9dX}G&x~DcsFmB+Hl`4JJXy&?ap6~8$Z*PlOmakhYZS?lu^vdtYeE015_?V5E z3E^>e26hHX23erTPa=6-j^{u?qGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsS zPvg;?*x=cwoxDoM!9k^gfhB8F&q-sIbF*~IzsYo6Ry(uMqt;8rYJo%JJil-=8H>VH zMkfE{xU;J+u3%UlxV7!A*2iqm)q_weRqt3k%7Y@02Hn4VkQy}3=Uc5Z%tet~oMx11jaFD_NvFXpR} z`g*JZTf`lrNyN>Xl76^RcsAcrj?e?Am?A2ZbT>?T<*{0IXHl=_w$*_ff|9HDcACBQ zZe)8TwV~>P!=+tPPo-A8`lcJRmu*X0FK0!5=mZb*b+s0Ph1YxiMe9P=SZq2xQBybm b-kF`ohYl54HtVe^*z)qyvd3~f91PX~Wq^y# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/infuriated.gif b/local/htdocs/img/mood/neko/kaokitty/infuriated.gif new file mode 100755 index 0000000000000000000000000000000000000000..c1c2789b2938fd62556b2422f2a13121c24e9c57 GIT binary patch literal 1447 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLi zH4+;a9q*QM3|jKyqSDD;8Ski^8Agv?rWz!l;&BjGJIi3i$|g{-`H}BDOGXw6g$8xM z7L#s13#;OW;Kk;P)k=3=Nx#y_$YHb8bL;CXj4U&}uHM|bDu5}mT}#{#q@p_l7i&<6pKj^G=gTaFxr7zEkYVBxvxUD5yi*3#4Rep@koHlw3W@=qH zWh?ql=FN^Z$%p2rC$;U_`Q_Sz#WzoVJ7bde=H{m0)h?Ys4=~=@*SY9S6D6T(Q`$_#elLc(*ll}Jh$<{coynl9e{P}%*e}8|q(7jy0 z{>SfMrysVrtlPi;|9^&A;sVGa$H<`0po|uBS}`XA7B)7rDLJux2uL{E#;$F5$HQ=u zOP7RT)*FjYkB&}|^soBUVWjLbO-6Uy9M8)M4YL*V*=9&OG@NU-s{JIRaNxOLi#agl zx{MAqEO#sQ^8Hn!>CY69A9mNPl!0-XC1*|PuB~q_F(e&Ka`7&6VBDOydehUJ-(KEc zTmE!a?uxBB_x4m(ay58ctbVYHRp@tU&W=?7BZVK`)OJmO`1nvktCd`inc;&~vkceC z)I4a2JzwrE9J{k}^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!cUStNwq#`gTp8#W$B_Ux!V>274 zn#_p}3l232@GFI!C`fc^7Z4B2c@ePSNT;-^m(Puj$tNajNU}xD-1O)agBI(aoS#9< zPBAj29J1MI^t@p%6Ely*s?SR=&U3C`rQ%SMdTF@_y8r{10z>0Ur}n|tn?Xz6Y<5y!*IDrQkx7Gkne5!5$ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/irritated.gif b/local/htdocs/img/mood/neko/kaokitty/irritated.gif new file mode 100755 index 0000000000000000000000000000000000000000..aca255cbb7f8231982a5026a6adb02824d4b4dcb GIT binary patch literal 1297 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a0|rJ88IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>X#TN1V1Q#E;FfVYLneT;V9@jP`pPuJCJ1On#rhN0hwX=)z?rv@7miN1p;DGQn zI|Dm|B!eu_(?^j!Eyr^pAkndnk%LWu;i95Tmk>M00trFI!@bN_Ts#H~RNOl>?5FW) zPHgaO(@tI`Bz2&Zx45NU(Bmn^&$E3u_>~BJ~JaXKR>@fP-)%oN|U74Wx^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3RobPdvdST zN2!d{!f$U(XJ);xTT{{S=wPm+(p`z`58O{`Yx;*)%=~ohET8)_7TH}}US8&qe{8z; z*TzHFHpCy^S8bqx&4(u$7#TPm0zh%gE@mR(z;KX(Q_!xY!r%Y{BcGyMNJn9VTca3z zOpV8+B@7egw1os_3NH0-QfC+VVKL#rnF)HuLR&nI51g6f5Pxn>hjGS*R)uac4Tcg; zuO-aMd>Rf7E4^2Rxra^JWwQFjIt@*uC$GL_MXpWmT_wsLwCdKJB;FII1)mNuZY|S4 zXFB1Vme=|W#y3-E3$HnSu;zG~N!P?&ry1RclUjBO7Ck;`VlJdRGjj9u^9!82<$R?~ z9vxZa|DJbkRYBHOX=WyDzB^2l_?tB){cxl3Y`&u$p$ASeMN}r~ZkY7SW3}qeqF&8y zs{=O#C0Fh3G<)ma$o5ET!zu^IOS`0=O08J+Rm*>U)#I$QQpO+dtx}kn7xTLy>Crmr o`C5N=RBTLXR}Q{)THpgaCsz0Ms0n`Tzg` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/lazy.gif b/local/htdocs/img/mood/neko/kaokitty/lazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/loved.gif b/local/htdocs/img/mood/neko/kaokitty/loved.gif new file mode 100755 index 0000000000000000000000000000000000000000..e9780f6e82385d4fd09b84383f6fa64d11f9df28 GIT binary patch literal 2424 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJL4b1F(Y9=Q(EOc(-P_~<6A+XS?O~_Df zi-n<*do#Cb+M6E}lMYT4ah}DpbJJ4q$&5+cdL$n#J;1<};kRVwWwizdW|k*wZW=7R zz~~asBr7mwS@3eE8A@Lz8yGGx4B9M}>ZP#q^s3nDX|mFj9l}?|9$$5}>RQ^Ftpzhr zm1vhaG%{tq_nN!fMC&pW%ZD^pogJE?`^&!ah2`APeYCsvztOvw7J4zKYIWBi-E*lS zojFkOn5gc9&5fs;m%8P>xwPf^#tFxF*}eVoB6VS0?Y|?L(W@>j+$AaX_wVfdf`|US z^6}^P?EL)vg73LyvbDQ1UtEg~-!8Xz_xJY?n48&I5TU{X3>7&B6=0}*hJ?z3gUw9* zG7Jj@79MWo74^#bapB>SRw3=MGcy7fA8VC!?(*pnd~%{$+&^lGg;9g|6!uuQ0tttP zGhIfxmt+(UJo9PMtLFP5S=ILwy<)8z7y_FaIU;x!wyqAG9<^TV z%&DuZZ!QeWoMxN-P4&W7W-gHrTGLnFp20LjOu-=h)xCW-M}^j`+`caUaAW2(Q!R0W zqD z4-dBUife^vOiVi3!eQuCBJpwI(OyC8C=-cIDNd6$0@)&F3LQAbAjr&75&7xqnHkJ1 zXIgF+EIr3)BgrP=Q1blrV!KYJUe5(Dyp{$`=2H+TNn~IOX?MEI^+hXmS=7$1y-`~q z1aHjPeT>I?fdk{Zys4YsXgXvvGUYG4cXsw>9mknvk6(%2F;9zKl=o9ft!8pw)Rx{> zxw<{3Mvlxgc(2&bn6|m$44cgBtMJaq9lsrL+Fc34d{O-jb__^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/mellow.gif b/local/htdocs/img/mood/neko/kaokitty/mellow.gif new file mode 100755 index 0000000000000000000000000000000000000000..72b8e4becef7cc1745ccc7bda9d56ec77e651481 GIT binary patch literal 1832 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M44z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wyT8;OXDhLWon2Y5{YCS>?8kp{4Su}16EZP5X5WP3^k>X- zt=sqtvP~CzT1CQ_jv;N_;kFhVY7u z)0`!L*<@W=7&Mu6k=PH-(yR-eimTn0t}M-RYm407^>tP8gR|>mw&v+*e|XlgDrD)Y zBd5N+2ybHhB*jtrfZ_5!>90}@-cw(n-(A5f-H|woJSMSMB%bn*sw@c+j6r?mRXDxH;{dG~pu|IhJ zp)*ojm4esA9G>;Zs^N9m3J?1>7t7FBm$%rbt35sWc|qfDHXAt$gYOJ6n+#V@Q;iZ* zjN6mP+HX^HJ;`l~v%Iuy^oNgrCnvuadh^5LanQ0^{j;{bGT3tD^3u*lak{^ZUtiyl zte$cw;+w;*p4`XFa-|RCF|S}|LiMjSIF@f9$FdAGmL-s5S?N%l40}b3#e$T^$*f9d zE|CkCoakg>+hFsuD9xKmSyD(LVe|4+bC{SPY>E7w!Z2O6(afY%XyutHepBU2y+pNw zmNKod(rqx#a_n-AR&xDWoD??MX!|9dnIB(At}VFjRKq=eRSW|#mQPeYaJUPK<$~Q? zmt6+Ma)9==rH>BgIUjqfaaGCVq@HEjpI4#>QqN9lWP2;~W%=Re;MlG@i(gu=`?Waj XuKkXB@a8yw{_AsVt=}JPV6X-Nv_Hjn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/mischievous.gif b/local/htdocs/img/mood/neko/kaokitty/mischievous.gif new file mode 100755 index 0000000000000000000000000000000000000000..fc0097e9a45d7938aa0205bc3ebf8b5282a9d974 GIT binary patch literal 2011 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

    )ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%JY#qGnpfRi`P=8!L|EjVuAJRfb}J&| zW%Gi?*Hv>r72lnIWAW-WuS2Tc-ZLv5yqv=|_s@yXFD|>A)Wz63e%pSRyG1|dU(Jti zpI_fUf4|lN5oqiTEDVYa3fKb8xsj1cr02(n1Q$jo6{jN}8y_8DkTk7h(cJW~VX}g8 z)RT%LhQo|3QL9WiHl?1K&dPB_Cg9U!&$+BIdNKhEUYwieQ7^{(>r%tT$=-{#bQ2s_ z9Aac!C1fj5s(F1ubCrV6wOD&5aKpEwEZ_f80ha@6t=Y zjm>dhwK_rfIrt}4u`t~G{^Qe&^NY>@8YtilAq@iuh9(9crI-^F7C168@rkvp*s$cFq-jKMa?dUO`ifNfiN7|>l9eruIHg!$6aFE!F z??t!H%;Hp%=w--gVwva9tlE1(@!_Jr<3_BxVG6G=PI!JVFV=c}z-edJ$9L}Rw77P% znNxoK$vqZc=Z?2q)!Wr3l+JW|m{xyo@9yvKWd+MWv*}0KWPaLqcC*|3xINz+aE1|b z)}u`->OHkpwRra_-grdrijyKt8Q->HavI7Yg@kG4hAJI zu@l=5+}PbFY`=BIwRiSM`tRQJvEHyDe%)ksvwc2hpFJ8moRl?YDKy@{^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/naughty.gif b/local/htdocs/img/mood/neko/kaokitty/naughty.gif new file mode 100755 index 0000000000000000000000000000000000000000..f23b53ff1f1ba4c0c77984707462233b54c944cb GIT binary patch literal 2013 zcmZ?wbhEHb)L_tH_|C>~;J|@OW!19`49VGZ=4}0c?%sbOFf=qwPEP*6^*_TX7!848 z9RiB~x&2&2f}I@$T#fV$m>GedRs1LGo|)!UnwgW5TBKm0XR44?sSsI~TC5O|nO>S& z!l3w*h0_SAPzMw;pnSx@@t1*-L&jsnf`iQ*!dfvWHY_~cE}-nCBB9`LuuE7pOhn

    )ppGIyhbUxJabJJ8G(RI!zYWUOR_JqE0I+5gD zZ1>VqG2`OG%1Ln@3rv}oatbZb6Np}!%_1T%JY#qGnpfRi`P=8!L|EjVuAJRfb}J&| zW%Gi?*Hv>r72lnIWAW-WuS2Tc-ZLv5yqv=|_s@yXFD|>A)Wz63e%pSRyG1|dU(Jti zpI_fUf4|lN5oqiTEDVYa3fKb8xsj1cr02(n1Q$jo6{jN}8y_8DkTk7h(cJW~VX}g8 z)RT%LhQo|3QL9WiHl?1K&dPB_Cg9U!&$+BIdNKhEUYwieQ7^{(>r%tT$=-{#bQ2s_ z9Aac!C1fj5s(F1ubCrV6wOD&5aKpEwEZ_f80ha@6t=Y zjm>dhwK_rfIrt}4u`t~G{^Qe&^NY>@8YtilAq@iuh9(9crI-^F7C168@rkvp*s$cFq-jKMa?dUO`ifNfiN7|>l9eruIHg!$6aFE!F z??t!H%;Hp%=w--gVwva9tlE1(@!_Jr<3_BxVG6G=PI!JVFV=c}z-edJ$9L}Rw77P% znNxoK$vqZc=Z?2q)!Wr3l+JW|m{xyo@9yvKWd+MWv*}0KWPaLqcC*|3xINz+aE1|b z)}u)(;$xpL1ulU>fQ=T7&U-#5j) YX^9*!W5sjXx;;NXJ#)9`;b5=^0Osi!G5`Po literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/nauseated.gif b/local/htdocs/img/mood/neko/kaokitty/nauseated.gif new file mode 100755 index 0000000000000000000000000000000000000000..6fdaa09904c67169f3b25f9e3cd3a8daa30761ef GIT binary patch literal 796 zcmZ?wbhEHb)L_tH_{73+;J|^jnQ1fspE>jY%>V!Yjg5`d($bQXlNJAS`?-b$J39ur z8tEA@GcqtRDE^am&rEYF&CE$jEmAPhGgU~cRER7~EmjD~OfO9>VNm?Z!f6Clr~|}6 z(=`|zm^X6ly7SLqlS0$f1D6^UWfL4l5;P|zTy>qI(31A5D7*H~kHGge_JSGo7_%WrqY1Rri-Z|;|l^oNfVtz>8ICcEV zKg-&t=9bnrDeI2({3spWRDVVm%_Ns{1;>ew#nWb{N2uj3R88|N%FW51GO=h*WVNiN zzFx`}rbe^+m5Z1g0?N0PR5iscZ99H~uc5yAwE4*k!JG(RurshTNHWL*eK8g2i+7DJ zj;r??t~lH;ai~00@rJDbD!pKdjF-`eycGCc>z=ZD8gH7Us#39*VR?%C*I%-;9hjC{ zNS@RXN|?In_E!zJYq>6L2dCW2cRiWo)X%+C#;-qcuE5Rw>hj(B)ht5MsrpUTEvXXK z=BzAPG5vN9y|JP;lasnqU3txBi_aBsiJ2a(=WpiXl32PG3w%rFUk(w@KKMcvq|~aFrWlBIi{LgCf8;>B3|t1YAAl&9-Q^mZv%iez`qpPC{ele1Ve%O^LYVEu-T{6*{=wiF9sb?gL+ zg0=L>Qi;gz?^f*ad{-i-x|!2fZ%V;-8@E!Yl>NDL&+dE5DHI*6-%#0^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a4+cgK8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>1UV%xK(D!giQbfQUQ9z%aLL_G71t*{h!seUFcx*{wWOChIcho9m5yPg$^=Y~dg%4b| zgwJ1>YaQfpWm(0?OM5fJ^R6w6H7zr7xY2NznZ0VA%bJZF7`NAcz8C9x-7s-+y?0a{ zkK~f1Ug=!BIWJ}wWnAR;%#Yc7b>ZzPYhzE(^R<5X?9k@?{IC_f&EMZ^;b&vP=HXim zj0_wO0if7t7c-G?U^vLYDQH(xVQ_$fkx$Vrq@%FGtx=3Urp9B^5{8L#+Cl;|1($j^ zsk00Gu$XY*%mlq+p)H=q2hK3EHi@0kELm}Wo>=>$5Uwjr1DE(Tn}uqLzHn-EauriB zFnJxe%2At(;dW`(RVES1zN=bWbHWy6I?hYE6|(yB#H5>HvA@jLHtuKhle3s``RRl1 z2Hq8_yG+vW9I5YoC(0SQ@m61JWYQANjf!bgB#iUcys-R|c5bobv^}$SZGC-xL-Of) zb2n^Cy|GPr|2baC@^`(AjM%(;jkfX2ur=l4Dt~D{m0OcnUtB1}YOq&o>YIojX7xVV zsBfCLmuI+hb==yLcXx;R^If&KuV_axH}IaZEm-i}>yQ+)w8!e}dUvN5iZcI;3jLIH yOo2E1PR8elN6t*JERXw9xj1tz-{oa4b3xwa)MYQzy}jwstsVJ~*=h_F7_0$7ytGmP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/nostalgic.gif b/local/htdocs/img/mood/neko/kaokitty/nostalgic.gif new file mode 100755 index 0000000000000000000000000000000000000000..85e4d9e201235a584e9a528b068a919ef8d4bba2 GIT binary patch literal 1888 zcmZ?wbhEHb)L<}T_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~adj>`h8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tc1sv% z-8r#w@$r5I=Pnt~Pe~1v`Tf~uNH{c{YSoI}B%^TPsaK17Hs20O!vhWT%|f}({w!Aa zW^(Wsi}fmDV4NqwEKu>Pc;(f(LG$I-S}izmb$(oV*3=auZ>}#&44ky~)mDcaOY?Ro zrD`(hHf~RNFE-V4o8FBb1&o(lW?jk;KUjbN)7#7+Z>}B{gFu^6`CV3tya`bfB4A|KzUH zW&s`rh2(?H(&}Y*EF2u%d%0b?BpQMe8W;`y)8=Rjsh#d+N%Grra`Q6=CS69Bf*q5W z2TpTtd{o1^`M||x2JLLRRtH`Nukdho(oLAEetlJ>>be}S1==^)DIdM{Bx~EN@VU~* zcjcbGmKHU=XuaHCZIktJ^D_D6Vk#dr+&iSo>ip*S^%t>6+55N2GE^4EPp34M%ULv382Ox#x^HF|C9&CYWpQ~`n&jk-k7xLJF4}TZvNWsJ)O$ML&WmsT zZ*47peedkn}Sb{x9PC=Et&Bt#b>6mW8R*b7n6_9 zwW(#&I3S$Zz#!2$DaLcc%d?$k-Eu8fL9ec?QrZ|L>S6jUaA_>JoUX=$*P$C3Pl?GW zELd}?(fu~x4atOt*zNJ3k8QQyuF$yK{U_Hw>js9{u0~evdEHkw+}~Bkt<#qyt{HoR zS;c?ZnFyVyOtV;<&)tz+$FPr;qor@nto2csSGadiJ3H;&%M)7)+w1Or{PyhR9^+sC z*8bS)+`gP&=EvGOZwuFCc8cHsap&Qqt7WUReYMMrZ$DsHdR$h1w@k^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*P z4X98D6h5GQ#K7^4fssSTW5a@j%^bp7F()=GJlrmz>@~+@jWD(F&3PZ! zwMJgoy0X{h_b*?r9Sa)|v)z)jcu@Y)^9b7wJ~f+i#V3b7->dDFnVEZJG;}esmc{spcHv)N` hkAa_on}G%BbrA-3h}Rieg~WVTY&hW5!pO*A4FGC+nWO*! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/okay.gif b/local/htdocs/img/mood/neko/kaokitty/okay.gif new file mode 100755 index 0000000000000000000000000000000000000000..3f57b0d5d791f4781c57d699ff916660ff93ad42 GIT binary patch literal 1746 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/optimistic.gif b/local/htdocs/img/mood/neko/kaokitty/optimistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..341b988f7b0b1d9369167ff7b0e483953d3d4307 GIT binary patch literal 1756 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVFqi>BcD|lUj+0yrK*MQ3Q4=ToUfX1hS%0r-fJY2^`2UZJ$LI=m@cHSyHxkwqzu-c z)aV88qBrnd_S*V-vtIZPgQsP(HA3$_4z{dhD$7`~k#Q$GpFm&DrHzd{ymoGiJ#%AI z>&mZpm zA9rrg&f;c9MnnLxGq5vAGROi0;1o&#>@a9>Zex~ZQ;=|IIMT+a8ziG};E_vljT%bovA2Nab?nw-8ScB5d-5S1}1?WnVSxrnPw;Z?#Rl^PZ;LgH_p@Xx~Oq! ziI=;OY1O6!!3+H5-9#d%9=N(VE;{Q@*VolomnVA{*=Bux9=Xxwx>M^cv*mYo+8>v? zk?ruLk-6f3(Ua_kH)oc|UlzLedfVGGM_ad-9l5hp3WEa-jC_i2AsvMcZjEB> zF*P2OmM~0|(-sn#DY(?TNu6EbhsA^gKHaP_i_UmnP&>M63LLZ!8xaIKN1@^wE^cOD_VKsLQ*(dHF>% zWTmQWl&{PoA@pxsmO@TK2XW&(CSe?rS(T-M?`ZzVezg*I7BGXS;FcF)shrertcd JJJ`Tr4FF_wr_=xd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/peaceful.gif b/local/htdocs/img/mood/neko/kaokitty/peaceful.gif new file mode 100755 index 0000000000000000000000000000000000000000..4c1748eb5a68dd5cb4201a438f45bc0029f88f04 GIT binary patch literal 1832 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&M44z{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnz2%F`T5z*9D7(wyT8;OXDhLWon2Y5{YCS>?8kp{4Su}16EZP5X5WP3^k>X- zt=sqtvP~CzT1CQ_jv;N_;kFhVY7u z)0`!L*<@W=7&Mu6k=PH-(yR-eimTn0t}M-RYm407^>tP8gR|>mw&v+*e|XlgDrD)Y zBd5N+2ybHhB*jtrfZ_5!>90}@-cw(n-(A5f-H|woJSMSMB%bn*sw@c+j6r?mRXDxH;{dG~pu|IhJ zp)*ojm4esA9G>;Zs^N9m3J?1>7t7FBm$%rbt35sWc|qfDHXAt$gYOJ6n+#V@Q;iZ* zjN6mP+HX^HJ;`l~v%Iuy^oNgrCnvuadh^5LanQ0^{j;{bGT3tD^3u*lak{^ZUtiyl zte$cw;+w;*p4`XFa-|RCF|S}|LiMjSIF@f9$FdAGmL-s5S?N%l40}b3#e$T^$*f9d zE|CkCoakg>+hFsuD9xKmSyD(LVe|4+bC{SPY>E7w!Z2O6(afY%XyutHepBUiUxhpi zneN4U<;lw}4Chv`YKrA{iab5v88vf~>}#Xs8(TsjPb=XTTz6+x38Tb~Y=_s4%;o>{ zo@77By*|tD^DEVy1=_w#dbs!VYEEDLXtRRm_NOl^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~adj>`h8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tc1sv% z-8r#w@$r5I=Pnt~Pe~1v`Tf~uNH{c{YSoI}B%^TPsaK17Hs20O!vhWT%|f}({w!Aa zW^(Wsi}fmDV4NqwEKu>Pc;(f(LG$I-S}izmb$(oV*3=auZ>}#&44ky~)mDcaOY?Ro zrD`(hHf~RNFE-V4o8FBb1&o(lW?jk;KUjbN)7#7+Z>}B{gFu^6`CV3tya`bfB4A|KzUH zW&s`rh2(?H(&}Y*EF2u%d%0b?BpQMe8W;`y)8=Rjsh#d+N%Grra`Q6=CS69Bf*q5W z2TpTtd{o1^`M||x2JLLRRtH`Nukdho(oLAEetlJ>>be}S1==^)DIdM{Bx~EN@VU~* zcjcbGmKHU=XuaHCZIktJ^D_D6Vk#dr+&iSo>ip*S^%t>6+55N2GE^4EPp34M%ULv382Ox#x^HF|C9&CYWpQ~`n&jk-k7xLJF4}TZvNWsJ)O$ML&WmsT zZ*47peedkn}Sb{x9PC=Et&Bt#b>6mW8R*b7n6_9 zwW(#&I3S$Zz#!2$DaLcc%d?$k-Eu8fL9ec?QrZ|L>S6jUaA_>JoUX=$*P$C3Pl?GW zELd}?(fu~x4atOt*zNJ3k8QQyuF$yK{U_Hw>js9{u0~evdEHkw+}~Bkt<#qyt{HoR zS;c?ZnFyVyOtV;<&)tz+$FPr;qor@nto2csSGadiJ3H;&%M)7)+w1Or{PyhR9^+sC z*8bS)+`gP&=EvGOZwuFCc8cHsap&Qqt7WUReYMMrZ$DsHdR$h1w@k^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a8wN%W8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0izE1vS4pj9eTOJRhhY zVPNSxrt?8qJ-FAiw@ByL+4;GZkr5F9>T=K*ha7!+si%=ER1ROe*2)cmf<8JeiajSri&3r!dact~YuzvpD_CB>Pk~-OP|j zfeQlC#cHDxGA}IUW%uLpI`FE2DKbSWEo8qsoQ`YYBtu}kRkDZwbn>WufFfwpB1c2h1UCcznf#Dznr=VR)g~0&^ zMm|NikdDFzw?;Acm>Q2sOBg1~X$uKxE^zReqQop>VcBrtcq2aI-E4kx77pd_UH7mZx|G@__TlclTX!c+no z=cKX9xmmj9VlQ?UWq2%LP83tk+LCg3iS_hjIj^ofb6FG-?0 zSf3saj7hWX^IOet@9MR@))31a!!L7URrupr=9K4`M1Nk_JHNq(n^}!pXw8-00(rlj pHD!;3Tjdp<_q{1d@j5rxxm&I`;A8B?Wun?XXRA!JcY`9(8UPKLk-Y!_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/pissed.gif b/local/htdocs/img/mood/neko/kaokitty/pissed.gif new file mode 100755 index 0000000000000000000000000000000000000000..3a9bec095271702ca0f25299bc778c42808927bb GIT binary patch literal 1918 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}F8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aHvn3l}+Hn$Hi`wSRAW(3>Kt%_cKIrDR6#%;K|6GwW(xg@pA7OcA2YKIzK;k zn6E$anTY3tr43A8@nRZY4(jLUg*OVVIJN1()oF32d0S5vtDaaKT3Hnuy)En1W=_+( zxzXFyTz2YluL<34o^oVjCFdJf?Hj6Ioec+H?Oj#={^5RCc9XO{H&({>O?+8bTVuXC zZQdMdDT!Q$=Z(y>{P_hOZZRaCpYPnAm)r2^0ppg~{qs1@)?c1EUH#q{o5^a&7Atp) zf3KGLdEwcG#oqJ%_9o@sy|jLN-@3VFWpA&tAMTd-zn9>E95U>{aFGRu%um#iDM)N+ z=Vi6y5!jf(z$h$hcO+tBLIWd{L6FOizyl2vWf^N^7>X8oPgjdvr1G*Tfq_YfRV3o% zrt}6TL(VfbD>p6o>11iC(@EH(e!1N<@Y58_uPT>T`t+tv)x45+xjkMrEZ6JXk}K;& z-J42xO z!b2(-0v#Bq>oAL~uxx1Xn(GkkrjjrvnQ@Nne5sTwlNWBi-i>ytJHIZz*dwAH*Xm`K z;ki+5YuVR`1==oK)H?Yz91`B%*(GOqsQ2_X-E-SwzrHKg5dRRr-}XFTpT>5bkb~Wl z)_UBP8yZiuWyx7QsMzdrhD}L4$0l+~(&+`fGTUZbZOJ&M@qE);%THfkuU7VaURNEx z@W`Frx!=nyCV&6%_{3ywU}#ikUq8!g$1Yo2_38z~nr=Q0Y=QBK(xl5k@SC2uC< z_*G9TgOnH-Xm@_9sSruMG|$ETo==p+%Z61(jkkJ!ZCP<@T|{}?+nuGE;VWa;cZG5V zCS6%Csd{XS*Yw3_XK~hU(m60)|O#Aj^I^v}?zrM@Ma>jZGYGHk@Q; z7fWV~yy@UIwOH}_9LbHwsrzdyXMOwgGwH^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/predatory.gif b/local/htdocs/img/mood/neko/kaokitty/predatory.gif new file mode 100755 index 0000000000000000000000000000000000000000..c3193551d72f53bb7ed1e14790e9cf46e745fed2 GIT binary patch literal 2346 zcmeIxX*d*k9KiAa90rS7S8_Ka$2ex12`!Q#-_j zs{)*%=mjaUa=Uz}pJ*IE0WgXQ0`GHgI8KwV%AR`bs5eqhzK+z!O$F}?>AY-x!**9Q zS;2zI!YhY*%z_geiD4d*>Z7u;dUXSDQwG4>-MuN$uiQ;p{NB0ENRab zzfkaMu<5uG#WNxP)f|T!5>^)^a?^SUm&onCE?pKfT)A3N&)@8GEU7^?`#_^i$?`93 z{vQx>vTPcs<;QRw>u%%fe1D0PAm85xynq)-0l6K6o=*%K@$|!~FgXND(um%kio{Z6 zQEaYhvJ{Wt1_sZj=g2En^u$Ff5}_EIdZsRA20#@da1?!L#_*y_qTWnFRC!O4R${%D zrGQ0;y*M%@`8A z?g5K(kP=N#KQgU2(yht#j!3p73E#1};u9-Y(6Y1LPY4s^&B zFupuVVyhl07nic#DY?|ma!w56c{ieNRb@Fu&AWIs=qQXP#MGyuuu~ZkLV+VeBeUao zX`AajH}lb5rAm7hQZ^$aEKg?=EMu+3{HC*W#i*<&&IHnU4GTg17>iY2)8_=1$Cl zU8R%5+hOSg8XdRP^E(xnD8a)u`zAWYi*mu}`PhiaTB!jQkJ{ryi`dQI!rdFly1`oR z>lNJA%x(jNz@lo%9bTkXpT=M{qr+(#>ABDpxzJo@7_x?mSM<&>?Mjc{lCB@kY9v|0 zr7kUpJ@rg9T)W^}M`Lt22-x){=&o{_VbD(t|0S^X&%)MecsfXeNXjQ~*mK(CyC>73Cc*@)4 zu3TnrQAa$SB4o93At1(G) z)r>XhUEw-*NbN?JS~asf8M<;6XHQJ{y@W)CClb3veOiHc$@t}hiCWUFpWO~VD6D(4 zHtn_PdjHjU*zik)I4R%2Q}%tp>+?-2ru#g%zFS}XJk#ud97wyzzSeb=f{k;iaI8N#H7=AsTEw`IxGS&YmG9qK zZ`_73>TU!_*mN;<55d~klMIa#+mmG+C8K|Z;Qy0zUIdmJtyPDEDx+Ca0axhC*^ eb!Xl=w9Fg_->`gNl=p)?QeOvf=}HJVIQR#RGMd2v literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/productive.gif b/local/htdocs/img/mood/neko/kaokitty/productive.gif new file mode 100755 index 0000000000000000000000000000000000000000..93bfaa4c14f1211e16890274a0be38ae1619a314 GIT binary patch literal 1187 zcmZ?wbhEHb)L_tH_{_|ZoIPjG*8k`3{RaX=L&N0c1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/quixotic.gif b/local/htdocs/img/mood/neko/kaokitty/quixotic.gif new file mode 100755 index 0000000000000000000000000000000000000000..ca43109be40faaca819e0f62a74a2b5940ed21da GIT binary patch literal 1849 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aKL$n)8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raQl`s$XAc<9y(h&_;50`#blhp}+dhf8OFt=FFf=!Hv+4**uS}T0^ zJk2KZ|H|%ZYZK2!*Q)Ww+){XPs_y@(8rdkFQ2`<(2mL&+Xk^-pt5|93X8oPgjdv^hTnA!F!@k@u@v0CLK7_Wm>!L zisu(a#`&76zf?|zq@SHHrEWHNm+|7mi!8ZC5>|z#U0m%KnRRzn@tW}E3B~KKWCg1? zu2bKyB~x`RCvr!Lzfp~6=_~J9hQEcL-niJ1$gIXMBM@EIkTjv4SLNwVi`9OIT9u_0 ztfuLBpPi)M&a-C0mZsT?3;p&<6g6bBE>=`iJsIWj^2)08=$e_)+uz?mFuBQ2X3v9y z3rG94{ny{oVF;&Dh=a%`eOu$_#j!&4U~Q`cj6A_bQFwwji6^`5-6?Bqg^ zRJSWLh0+?CoaURUp8E3m#PWdTq`6$170$0_jXI{Ha8>K-dgg6ey3tb~UR>hryUvBP zJl(a0?UU4piU$Wm*E0V~x{|%%q0a%o zibj}eT-=;`W{&mrc^N@pUtQmje0rYm?rm?ICu`n5=ext~{juGZ>-jja`S>1kgxg3g zc<9u`%dEhopz!EWhp0NAKtSLlmo6r@3KNNhhLe4Q!Dc*}MJWdvSp3XPJU6SlPG*U5 zQkk$hv#>0M9)xr*lWeA z_U`xO*N;zji5D+fxnOhCWEo{+7RgJSnfheqwOsF7ZppZ+CA$jj}Lc0CP6UmH+?% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/recumbent.gif b/local/htdocs/img/mood/neko/kaokitty/recumbent.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0065da3e414a914c09d5cda421d83ece4857f61 GIT binary patch literal 1290 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&J&Nz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6Or!30i7snc8|Iz%S8H>_%_V8v4@6#zE|1!3cYj^(D*=@oD{?v~ z?R{;W@66o5TVq?0p#5-iBX7@B>+qzc0|5_z)vT$=IlV#SWg2T`Wp3J8k;p|dbA=u| z&Q|hW9d~xu*6gcOw72)ooniX+_~y+0_s;I#{=Suw5#e2S26hHX23eqYk05zhj^{u? zqGKB)2b%!HMMak`A$E=h5`v0{dzr1ccnlV(xOZsSPvg;?*x)%yJ9(9igM&%~154JS zo|BUk{bpN~f0B{fw9I9pOS_rO34@iFmnySb_;yWPd1VsorcY<05>l_O(B56vt9ecP z!s_74y1kudYa<)k9!X88deCrrm()|K4X?iG#_VNl%j)HJit o$Ni{SoVtR~ec6#YJ2yW+&%u5AtIn{9Yt~@4@;1#xM=hO|?sUkSUA$Ivwq9(tw|lkI^LzU{&pF@E^Ld`Y;D8O@ z99Q59=1@SbR&(PNingWxv8Cnm@bF-#)#jbL$>nmF+Ljh)62aSgOW^-Yz;VfVyZ?^x zExs&&Pj@O3T2AWtheM#?fM2RW$m1uGsO~gUOgd@L5q>g>B{-PMPXUe#D6Hr5$8|5U zyxb#zc>y4deUPeBa|~m?HmXbYP3H-`(>6s=OVy7#?;vB3)_JHe0|di;itzX@fE+ik z(n^xx9tmXF6?&t^C8X5-Ju`W|>8XJ-B&H*i0K?bhKC%nz*6tvODOowV$$5)I+Irk4 zd)qD~Ru1MO+V@h{NC7x&;(KSEn!e^2#D;D&Dw};KqkzNz;rRXJ!?#M%{Rm7Wt0_Xs zLmRs&u1#|)vXNzcAwGkT;+Q+@PA^RGQO7JLwH=4m$GAC_ChamQU{X_N>W`NOi_QtPWa5o4x^)*SaMv4tM{5a2sLA9E+t z=N^v_HS8ZC#xVazga&9pT7CfY_zgt2H308`fC+34fGj9}mtzxQkZWlgZ$TyTegMcY zaZOhex2MnwTbDWCTH6buLQgtN&G|o7tVT|27pUZG)oYHM(Spp^T$dP?F$|1moV)9p z-T@aGmGI9M`;0rZhh~%!Ewq8W=)KdcMjD0K3!g^H8hueBQ)#Gl-1UP?#3!qCMzhM$ zQZGxRE5_{rLK+h7A~uQc2UemJa2wbqw}Z}<(N;W<#PbNS6Qa1VGi)pf8q=(~qu&0&t1_qnIFx&$Wz%W@aO+j0& zCoq8qU`>5eL{v3^aE<{xB#Cf9h7~&MXi#AdC?L9-;Y&@GA!0HbKfgh$?vuJFo1F{x zQuisC`}-RuUa{AXlX7f_Z+QI{R%v0wpfG9VVT5b7Sit}dA&vV2ccm<9l_MFv-d3%o zk|LI2%}{MNb5)V3u%@c0ZaotPWqvQro8Lzi5d3o*11(7nHX{w|1WPj)@s-Hg^I(&))66)g^P= zk0X&@ci>fc{c8@Kr@~vZkPe0<0u#QRg`yA z5n19c?!@@G1gTRJ11@8xtl|kGp-#TXV7AC)L8a@ZZVViIZrvPEYwJa(*=TPI`fQah z57LKH^*Sc{`a@CJk5|@8(TaPyWtle?&1_=tAj=v^XC`{y%r`KM)ui8YU+v|KIw55j#7>C>RZa;T{5t z|GE8KLxPzLCpIiR+%BN(HOFJ)qNCls%o#N+3=bS( zV6xJCBk}1m1EZp?(v^;)hEpAkY$tqfZdCK0sb?=VW2NBo^Rt;b_OwVeG+dZrH+h$i zR)~7g(tvKhr$0opuB_y%exwuNpcy_#TD9qp*MimOnNkar%Kk4j^FtzZ_ zc^}ucMqbytve)JJFJG=53mXr!-IB9-Q2x>L2-^)lHJft9Cx<=XtL>GUnR}YC;_M=w zKY~xvw`v?tVmVOsCFAO9_FE#7ySKf)y`wnz$(^5O`6ss3$A9}9z5V0k6O*NRI1pZE zXJBQJWRM4X{TA5k0*p)yY@Av#D=sW>ZW9o<>+vXjaIlMsIpc^$Kr%xUBTL1a7lA4# z7@1t^T2>f7ZI~*_ej?=M#x(Dl`i^j~A7BvxdY!>;@~JBsB^iNBycX{h;SySPWrehL zlx)C)hD+-#Hm8X+Y-V6wZ+CW)>&q!?&aBJ6-}IF8lJ51LsUK&($@rdiX>amhx4YR3 zHZX2t=Zo>}xwL_CUsEkpS&W6|oh4J`KbM}|`sU0OXVGm>dW@HP^(^*n=JUO@ETV5i z^69V{Hx1t0nyLBd-rDNP7oWbZNqy{icH?j5Lio0`~x-sL!u;MC5e%x9u8VbPIp zetjm61A)qpeT;To3@Zhnoakp}>EV%_xcC&K4lA34L$T_K*?O6W{&*}nw ztjxH`xKXQB@n3*{)L^d#lFGxMVtj22Ev#_ms zdw+>|hULX>RX@CKua@chGka^MJ~MT=ao`3s`wu0*$Qup!4m2g3sjd04_R`6|ulr;c zd|TtSpF1}1+E2+ht{3Nr&ib}P@OjoXpm*o_?lxmMGc)mV-kGZJDR*}(v$0_F@Odmr zTaj(XkAfsnv_`~a1S%h6WHO0!u`qnnFp-IwCqnbmqSKSK{gYG<6eXRRZNM(zz^TB{ zI9Ds5%l2jQ^D_&aC;xhqX}mIck;FtkjerD=t20E{(|RHs9Inoe-QSd=)$lrWL;CR~ zo!ygG-Po3Co0a;zWW}8+C9m&I$zHI&5g4sDygZlIH}0(ZzR2WG_=@O-J^bfQEvIUq uo?yd0ZHbKW5|6gow#nztd`!L8u_9Qz=goD+*C$rT@9)!%E;`u2U=09IGrArC literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/rejuvenated.gif b/local/htdocs/img/mood/neko/kaokitty/rejuvenated.gif new file mode 100755 index 0000000000000000000000000000000000000000..3cc6917ec766e8cb6038ed3ba9b101c357906850 GIT binary patch literal 2437 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 SdTR={yu7sRu^bNvgEas+ZiKu5 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/rushed.gif b/local/htdocs/img/mood/neko/kaokitty/rushed.gif new file mode 100755 index 0000000000000000000000000000000000000000..83106ed425885561e9cd538b3e8b3a769e6aa02e GIT binary patch literal 1684 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~a3I;|F8IKJM4mNWLYsH+{u<&rZfU?&dkBy5CFt8c1 zZTMl3e3(JOxl6`VNQI$a#$M{ij7f=Zz09m9=6G&ic6PRD^s753KPR7<$L7ld3WD8^8HThict!^m%;B zwQ6hb_1yyJUoGt{&+^yZBU{?#u{OKHkr&%_QKkY01gS8o~2ePHtLyxZxl_j&x_K8ohZn_1V=8rJeVBS5JR;xdGXcY{2l913L0O!jZy4 zJO=_29oraXlz0>v7CCo_s><;gI5-^b5Z2_9U@%fV(#B-T_o8Bx>fwpn-b@*m#Y=rB zFmkN8UJUtM*u$qyBTTo4$_itzc?Svwr;k zZMD`*PTxDw%q{P?XGg)6mA%Xk`)*o%zIbZBG#>|Y7_bAwKo%GV*O9^in92$g8`^nU z?RW$>CNMAx%i0}@n3&MO$Yc=YvLo<7!$eue8X1P7Mc&iZA{V`pXkhT3s8f7u&xuI~ z&UBg9uDjy-MUip7rs^-1Qz7YR=L^c4&D~|Z^3=kRZl~N6#@fMsp1b)p9Hwd9WU@TC zOr%?E?YV84+l@qCo4$*hURu1bC+f=q##MD2=RJusS)Z^|jC;TC>n$3I%M~N%rOJFN zxH4T_c|L2T^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*%LZt^Z2 ztq}E~r2*Z1Pk)GHU0KOj{YWRkK{I@gv})5GuLY~mGo=1Dp2YFl?~X}G#Pd?{Oi zmk?vqytu7JyxJyjLYOmnOKb`js7Lo?@&?#u6=^l>$k^zn+ZnDG%INmpjWy@Gg8Kn| oPT{#7lQukB%NL&4BC~VT(^IvVt}Lc0AjP?2LJ#7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/satisfied.gif b/local/htdocs/img/mood/neko/kaokitty/satisfied.gif new file mode 100755 index 0000000000000000000000000000000000000000..eb49f85416770c98f85d69dbdeb9e83ff572c68e GIT binary patch literal 1300 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIwbVHAvpzz7Hd#sA!X zt|7tBjsdPldIrplKrbu)lXcHbb1KcuNl7hIFwiqqNUBtbEK4m`2*^w?O)X(i{K>*; z1XQR43Lj8DV&Hhdz{nxvv0=f%W)5Mkm=hZo9&Q&<_L}3danaFkUgnIN6@~|nFfdu^ zy^;9zn1NBzR_RJdQNyVYMz#|^H#e$z&(yOQnjtB?{QPWYjy)|B4GkCO*-g$ev6`~@ z!jgb`uD=~7Syy_6On>PFFldF(iAdx+5ZT~xeQjFdv@=#=YS%ZX?Em!VM%jVeOUj>b z+Ip&dZN$E?zg8v=HxArjX8)mN7kT5ry|pQmx#aHLV2Imkp>3UZ+sNS5vXH=QbAL*f zxK3N-+J4mI!ZMF*8~O@QH|qDz+$JI4YELB+$p%vM}H1`AZ&J2dR4@n}wL@SLQbyh_Hw zL8XC#CF@Yn$;pX+vn|R$$w+Nl=CaVG-Av|$!OF`^m02x(yC$x@GKrNfrFUlOYPSX9 zTg5(fmA*N(DsZ`wYqjy3TbpHhPnarvJ;1m|d;6`c7S|g>=f$0@lf4nHm$2E8`}bC^ yNw3^y^Q)WL{g(LTbW+;bxzxhwY1+93&fRV+D)L@j>JnWPx3+5Qon}Tx25SHjRpJH! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/scared.gif b/local/htdocs/img/mood/neko/kaokitty/scared.gif new file mode 100755 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/shocked.gif b/local/htdocs/img/mood/neko/kaokitty/shocked.gif new file mode 100755 index 0000000000000000000000000000000000000000..a29f52dedc28fc67d6690818e9305dd096f3309f GIT binary patch literal 1776 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/sleepy.gif b/local/htdocs/img/mood/neko/kaokitty/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..772e1969566916d034230150365cf50b1f03e084 GIT binary patch literal 1443 zcmZ?wbhEHb)L_tH_|DF7;J|^IXBZ-~de8i4NY0)!XY2oS_x=Ncp`l@Na`OMJ{~1QX zXb2475K#Qj?dKX2?CcoeYNTht%n0H$L>7q8WZj<%iI+QxlENx4BeqR&1Pa%=kwoAYiG- zeAYHEnOP-E0_U)CN@z@&qH$<`2(Q3Wjmyg$*N3)u9sL#h`gm&qzmNsPxAdFaQ+Q=I zNQFGOwKM4ctE*Mh^X_h~{LaM|Q@$YjV8>6fZPFGS;}&#tiWKNryi8g+dB4()HRZ-l zo2DtJn|=8C`Szs+f7zz`ROY`pv?h9gt*vq6Tb9Y98Xjw^U%h2nl)63k&+TtXpYgOY6xC){S=cb+Wr}ZM-YHw_DzS-=3eJ4W{b5umAV`=eMIbx4ZlA z-}m?T4Q3`H!fV6A!_D069y|>J4X)k%fqIb>hjoPKbc=<3M_8aKt9J{9|W%NxdR9{hJyt+%fa+*=X6>*?+71vhp( zuu7SpnUR;o&@C-(H*3ebCx=3`SDQ90D87G=<4Ky_Zp)GvJD0h#i)H@&bmwBO`R=ye zw-TFfa~{wNxKOb@><*{N`DJq@e!M+2@3|EJx=QU=m!q~{%lm!hXZFj>+Tr(4&HeOv lQHI>!dSH0j{Cv9Othmem7~9|9-`&3-1`e+uvTQ62)&QtoJPQB- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/sore.gif b/local/htdocs/img/mood/neko/kaokitty/sore.gif new file mode 100755 index 0000000000000000000000000000000000000000..475a04828e8f67b6030b1ebdaa3fa97482e6494a GIT binary patch literal 1909 zcmZ?wbhEHb)L_tH_|D64;J|^sd-rOZneExTH#$1HU1`PsJ$oL{`?$<%8&Kll!Gq`S z{ZG!G^Z)<<%MbsbzyIIR&~VPy|H;Y8|F`~U7zLvtFvLSZ@jthpYe=xOV}PrXo&hr> z&^wC%WZg5<$M z7&&A-HY_;U%pt55b7I57!|ei$EFB(!4M)4h)Pqtq8XAuGGntu*1T0wMIa$h8N~dzc z($mw_y;q5x__XxwbT!v&Ih_mA&(Agxb}{+6Dcxs2N6e{~hy^cBvIg`^=^ilA^k-pR zkac&L!n1(Y5u1x-cQ-gPv&ApZD|HCdX5JEdIIEQ*Q73kLfxKNS*Fwj;Yis}ObxaUf zYUU_@&lF~}ucu1=iAoB zmVSM=iF;@Hald_getza=Wjj zhzM|K>{oCMD*5rT;pAjB=Q^JVp{3qa6nM9pbS_9cJ6%(lhoy7VGOyVje(OXc7NnnG z^{D@)<6xrU%fdRrYwj+Gr+&)=76;wk1qzh#>3*dLLbaGT_-^(B28wp{<_ty|S74yr zURnBHuR|bQp_wE5{v**n+w~jvH-5dOdS<)AqfM#O!ZkdVt5X<+jJz3uf%4>BwW;?E zo*kdAoSxz8z2H>XN2aTbJ>50det(y9h3)*kWmUg(T<>nLmM*KSK8hmDIGIs{ooZk(8??9#(z zE+^qxlybaR&~;i&c7<_#Z%pNh<=)tTltAaTM)-4kC7CR8INI+^ytyKBDCXQTI zqmF_y-Prx*pP6plzOEN@pn_Y7Puk4z;L)D-R%{9jH?iy!Rx>zPbA40G@fv0Oxjr{H zv#iMA)i?MnS<-T$?D;;m-hwwdD>ff*y0W{xEbrj%<6PqVcJKK37#I@%=XQPl_-tOU zv-w|{U56U5g~Pi6N)gj^tIO0+Y)w^OAbUcgDTJe9<)c=G(7c1Y%Edp-JyrgJX+I0& z;k#Wk*4;fCBJDjx=is{*&TM`8Wjcxvv}T(t)<<#8+aSblysnV*e?!5RQ3Zv21% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/stressed.gif b/local/htdocs/img/mood/neko/kaokitty/stressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..c632702aef5c3dfaacde3e6427061c7b47b49a60 GIT binary patch literal 1796 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aKL$n)8IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jwaA)t@fa*fJ2k_C^-77SfI7o0>&kyB3Bk!1 z=IUe%Rd9-AUY@1JED-VQi$=&wZ}u=#DU(-0s}mNc&8?iGeQ9Rs;j+}IZ|Od3{kcUp zXkE`dzulnpnvO$4UckOO|9veSMa%CTsD3T>cSZSuhl~5gy>-@z<(xd(tIfXm&xM9` zW-ES~0PSB-(wS$N=F7eLuqFLOSNSft-knR651R#U`p0qUo8J^o!$YioG0Q&ewkVg6 zKeuP+=jU_N?dQLpWm)?2+Ir{v=l1R{Z)Rjf4ia`?fXD)ajLSdLz-m;5|{N_|%>glMbBeGOb;A z#q*0I<9tokUn-|U($CHplsB8Z%XsCfh0I(c39C%ik1Vl?6jRs``uxTw-L-9JZ(Yr~ zy(J-eldJYO-Qzn#mfvH2Wt1N{J+NEO!lBgQ+GJjS`FX1>3Ii8Ky_~1>>PDu=M$6M} zIdgtIJ$l;8xvM6#G{N)Y?1j^|y@>q!>iULccN2%*Ww|$5a$j%Lt=^u0Z(}`kzJvh6 z%WMqn4ANjPp8$H9#~}ce3K#`=CKxm{v~mjS)!Zm(XlUnA)+*6Ra5&b?$kuUW#|D*y zeMo;om@Iv>09a$@S)Hq%Nj-=D#Y&MkD}mU6WU(e#+&Qyw&h zV{60JxnbM~=KK;_7Pi)Kf8N%W0$Eo!DtOOp%?x^Yj)9#|p|?8Z+3l^R)%SR-P1Ej8 zuhZ{hv1WL4bicH3oJsb_4W65{E%nOQY%F@TZJKfRy)!#EKR>^Kw?i&h!Q|!TrIw51 z-d1jXaSAy;5uQ7R9G@Z*3m!T(@iI&BC@4HS)FG>42=9I&8%p|Y9@w}3Lw$r*>tTaMkS-Puo4RP)K{sq#ikdcr`S6O@whon`Xk(h6^TpR-Y44_#Zw J%f`ZB4FHxTw8sDd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/suprised.gif b/local/htdocs/img/mood/neko/kaokitty/suprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..a29f52dedc28fc67d6690818e9305dd096f3309f GIT binary patch literal 1776 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8Om={`pUcQ_Op z+?yn1`MyXrBrq_lm`-xZENWnwqN-d~W2vz000VQ;A(fNGY3F9CalZKSWAlphj4U~2 zDicJ~FD^G_HVD^V7$hHLK{j_L_YOWfJ<-v1zjiu|+J7R#TVOv@~) z?VS10=i>DEXgSdQ^k#)fO^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/thankful.gif b/local/htdocs/img/mood/neko/kaokitty/thankful.gif new file mode 100755 index 0000000000000000000000000000000000000000..3f57b0d5d791f4781c57d699ff916660ff93ad42 GIT binary patch literal 1746 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aQwBy38IKJM4mNWLYsH+{u<&rZfU?&dkBy6tcJnf4 z)T}T(aD;)$O7D%tr^gJ8indBuI*J-jbuhA>@VU8B&3mSvz0i!6g3Hg(X6D$_BGJ%r zVTRr0T{>DJ>Oo5by7`{|5Xri-lCS!aPJn}E_#A1~raN8>R-b1|Eu1Ezo$&hl=6wI8 zvp2%j!Z+uAT-O?TUF*tTm*2m9xppjUJj`}W&f-D&N6#Z{H`I=HPhakGqFw#?)J{vI z+tb1V#r|;!ZHbzaXvmbH8C8;Xl{vSo#dr6%x3_m_mVL{qHh*$!pW*j!b9e9f`1k}b z8w}3nT;;5BD-#aq$=|P;u|j zu%E`GIkCaBO*?s&jDv$p0|QIeq@I(;D(7bDmVcA!x~z6)p+~Kkh}8mz#(93>W-=Cq zsf-Tdj}Tp37s-_Z{`PnsaGhj{B}!>B(ywceCx&3Ybu`-fa)t ztxr#8OsxbGkDZ5NopIE1%Y4qgPm#oOO$-S#Yxr0{Snv=wP!nEMi0miLm`sYk1 zeADt;pTYQM>TKaPrw`T~FEi+z7>&mzVh;x0MiJum%7gu#`vu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/thirsty.gif b/local/htdocs/img/mood/neko/kaokitty/thirsty.gif new file mode 100755 index 0000000000000000000000000000000000000000..3cc6917ec766e8cb6038ed3ba9b101c357906850 GIT binary patch literal 2437 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 Jzd71QzXI_h8lwOJ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/touched.gif b/local/htdocs/img/mood/neko/kaokitty/touched.gif new file mode 100755 index 0000000000000000000000000000000000000000..d716b78b96c78e0c0bfc3c93e24716d09ede821b GIT binary patch literal 1913 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIxG*w{ENE$#oz{|uvG zGz5lk2q^yN_Hzvhc6JPKHPSO+W(4|F@t>@FW|~uJW==|Kk%EDqsX|hvLS$KLu|hy* zdTDA2gW^vXP9vZ~9Z;}<@(}~aUj{}FmVyTij?K)%S}_$H6rCGcmF?zO7$iA%u?r^6 z(I{N()+VlR_h-k%#YZP;_)hXUDU@`&moaHskK_Z@1_q{#q$M*ir!_D#65Fn-an zP`93s!E1A7Fr#<>FO>};8CO=jP8V`GWyH|9)@yxN@6V~P&#Xkr5F%EWp5#V^9GG&NpD- z$an-iXk=#K6N@=9;o-q{UU97ujfqJ|TR04zN+domJlZR09c3c1DaC2BM)0bblbcc+ zrfbEsbx1fg_)OQ&y(FV>;MtirOIDsACk+lXEVfJ4I$K$y;mhO^Z#MT-2?OIIZf1cU zStYBkFN|7m_x9J;HDPO5mrjf2o~Cw_k(H~a_qK>yz(RL!feF^3`tkEJIIrbMeb0~E z6`1*`wR=WE^4#*9>sn((-XGpHozd9jz|97R{u%OIFLD$6fVAFSsw>vIEhA1{AK z?5{lkZMNa=K;iSqtZJO_eQPcw)y zb5wACdU|FCGs~G4$%#wPG1@4yNjQ`|KfTzlld0Epfrj_efXRFc0wIYEOd;(~ce%c3 zg)WQQ*|j&y^kMMEjNQk0tQR;iuFIRc?Tw~GCL>e+!h2_DZ`N^|S@!sq=pFO4*hP6i zmDFk`=S6MlZI#Q@m{ye7%4Q@j@L)rcGvh2?i)ClN>pnff>6|WCps?W)<0{w7e>o$U z-=AlcseN^4@Y7Rw_T=8T>zuOe{o@nBpg3oflymds{B}3J*wT`h;@E@Y{XnLQ$Zc_n zOrl)hSD)MI%l+c(s_hP!ce}pi`|!G4>*0Q2@>r8?{_((3X1Qro&s^Tvc$$r+V$Poc zhBW31RdG3)p9xRf=Igtk+g+ZOb)mR=(_2mn_1yJao*rA{X}$gN6z}|PGJbn@9JoHC UUAca3(az7$&gr}Ja4=W{0N5tw2><{9 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/uncomfortable.gif b/local/htdocs/img/mood/neko/kaokitty/uncomfortable.gif new file mode 100755 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/weird.gif b/local/htdocs/img/mood/neko/kaokitty/weird.gif new file mode 100755 index 0000000000000000000000000000000000000000..9d71be310067f9a949d849622373a685d4614bd0 GIT binary patch literal 2335 zcmeH{`9IWo9LGO%G&6GK7#g!?n{hObSPZh-GD8@K7$YH+T;oXPswwsOqC)N&DNGqO za*kn*7#&lDTpgrzNTpM$-3n~JnU~Ci@AKWj|J?v-UVf8<7t5aJ;b3lJihwQflD-n0 zBEswvBBDb=V~M6Fmc$(#qHkho9MK~pJRvk5kUk^j%oi5dEXrBDBY?RNU>GgBSa3NN zqh{#eBQEPmQ`T|e(;LgLW-21sNmXXDP5`$td4v1?DS(mIYY(T#LcQrQRFCUu<7!5c ziLL6%YL&CsOAwgzhj9>e676c>$UK5*M`0M0GPp_FcuW6{e8~Bz zQE-hGm8uH?WF$B18bx=o*m&=>*0G`0{blrnF4*FN@Q!4)5~Zt{&9Yv&4`+w5nERSu ztJfBrZO~H76nh5mzmQ?|mXVBlf(Io{Apx*hMK8ry1rhWH&eOT|QgiC|4D6R_H~QVF z?P+V7HX;ls#HHjoC2GvyboW^QX?r6DH=C)Kw<;A;$p4~h2QYx4dMu`h*08`)!DS$) zvLSw-sSLoBNRD3VdmzVT4YYp}oqGo4|7fJDT%;moq>$0dv(|aC{ydX7)n;dkte;Qa zHdvQVVc$4H%*5Xwr9Af(U^Q)wsg~s1aQ%uDz742l)CD?u$IlH5N0LMOnughe`s9;( z4qfWwBam0FYeHoGeQyKWsif{X!g*%U*oh;W+yaJqV<*>wz&P#N*7U5e@N>&RUE9>e zV6j1J%MWJ6Z#-ZjCGy`X{kbG1Lw~j@WS<6KWtU~0PlD1^(Cp!tyLGzL;iiU3IP;3` z95Q7&Mw3|9aU9_n_z_0|Zbep>O$9wHnInH~+}A8RmE0@XfL6}qFtr`>SIVtXcli(w zs$Gp$g?^u&d)6bF8n~^{>d_|4%Svy2s5M^Ah!q8WtF4`Bi{GQbS(ml|wKsW2;VU;?pZU@?v*Y zg8*D_Z6UwS9CCrL*{Y!n@pK1DQJm+)a^u45rF7a8-PhcZchw&Rk(`Jj~o|wi02rwd3#KqMdp_yZ>6Hn=YtDYM68eO*K+l&u1y{X!lxc0CAo^2f0t#6 zmVaK@zQwX2R@q@^^MX1vU?}!54p6%mPI^DqgZbE=i=`d?Smhbw2-9`2QUGy!j68yE zOnjSJWoIcov9goHs&azkgKH+}EFD;p?N5cj%z3@=tVEvnv%rnNy4?^E8Y7%-ght_p z*UJ?R66-o(%bLOhn$@~J74S2n(d_USO4RDTy83-iDG{!YX3b9mfNqCOm1>b_$2PQiyznV5D|W8fYXCdEgcOH`y(bq!VVu0+2n u4s#n%O;da4+H&s0`F^#peEbFJr^%57URR(;d(6}rx+8Uk?fz&gSoas>>WxqU literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/working.gif b/local/htdocs/img/mood/neko/kaokitty/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..93bfaa4c14f1211e16890274a0be38ae1619a314 GIT binary patch literal 1187 zcmZ?wbhEHb)L_tH_{_|ZoIPjG*8k`3{RaX=L&N0c1(Bxq7d~>$AK6CusDgWX_XaP^V?UoLmHa9ni|?1 z7`uumP3jAo&|FUSxhVV7_A{?u3qKS3sQBvm s^Y1@isJwdj?*03JHX0|~Hze5caS3U~0P~4+#8xG*KTp=UurOEy0M+*K*Z=?k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/neko/kaokitty/worried.gif b/local/htdocs/img/mood/neko/kaokitty/worried.gif new file mode 100755 index 0000000000000000000000000000000000000000..72864c820c552b7decaa1bed9aba6455ad48a63e GIT binary patch literal 1762 zcmZ?wbhEHb)L_tH_|C#`;J|_8>^XC`{y%r`KM)ui8YU+v|KIw5X4-#-Q7{?;!#xBP z|8x7fh6Fo12DlpO889;f{j2y-);%-LsWdYuCACPwK+jYmsZt@bEVWo6ATzx*wS+>}io`Xt*$gnd`@t zl_85SE|h6~6tZi|$}@`sWWQ~RDt&czjpRh5rLQ(K-0T%{^iy@1rWrj)^)lCttg@An zn+g-p$=){0jGZU{y-aq_^c4>dhH{&m9Jq1d4l}!ev)#=b4KYVL59+NsbK_n7oH@Fu zb7x+8?Kx#uXOjxAcEDb#GkYJ8^6A>w9N+m%qEPsFHd8o@$Hqhlgvm*#tpcrNsGm&s$ILN>$Xjf8UaDai4Pth%;qp-oP zQH(vN#$(bFhKX|8LIN`dmwGp;vkUyNm~i0C1lE|YGoBaJ&N3JWKD)9rSmnZeMRp$5 zs4L1r(^;o+#qJVF@mb2UBq`Qw;=`*eq7E*4lU15^V?}a(T>R zobN867dwO}``s-!d3|toWIhiEHvgTZJPLbG8mpX}rCa_@rt7lWnW?O8YOyy99$aMf zo@!*OwIJon!hm?MHCbB^gszASPbxWO`uh5kz~g;7-CLL6nw@j|m`wJ9b&ado`L>*0 zeQ_P*rlQJKU!$ilzrMcZ|0LF#S67|vHIw&C(Ge?p(mL5ZEAQ2XOs{iuf&QCourc=H TGGT3>vsI?Acd;`wF<1it?cu75 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankangry.gif b/local/htdocs/img/mood/niaha/kitty/ankangry.gif new file mode 100755 index 0000000000000000000000000000000000000000..9fe6ee21134581c4c3c456a2b8b35e7e6ee78685 GIT binary patch literal 398 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zIBghM8FY9VI2lA3Wd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcO0ZFMM$XC2PrHv*sx6gKFWIT&qj@lUQi9LSLxItf#~sBt@8|w< zdfw*#cL#56?sNRAZ>q|~Qr}wZ*v!&u)ZI{|pw^SzpI}_$X=j? zaHcS@GU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5Y3qq4AMYn&V)GgeuMh^TdEwf22F~lJWspYo}ChF^jUU~Ysaqc z%S<=dZQqq?x9MKMw?@v%%}=|JRjMtOQ7_r4)6cFYSi6Oq@dQ5+@D}v<7sN9J5eWNR)evjuFX;%pC+Y- arqJAmP9=38A7z#4(xSe*A~k@nwFUs@B9tKj literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankangryg.gif b/local/htdocs/img/mood/niaha/kitty/ankangryg.gif new file mode 100755 index 0000000000000000000000000000000000000000..7640effa67043cfa12c48d47c48cde2495aa74c3 GIT binary patch literal 398 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|!7+4u}co{euL>S~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8z~5JW(v%i5)9HnXU>E;^L~T+`&+6Uu?9_wraVu(+Mb;fYxG%m zk88)S?#oO!*KOaGX}9TKz_&)u$<0r@k5#HIl~FI*spO-1Fndyh&&)%C(UQj<#W(Ng z{&ITW=KgmFZ*A^#{HkxN%EVINTI<-%(rVP*P^6&NliZ(RT;pkKraMt5V^)K)p{~tR f9iJwphNjTmhE64QA0K6v>C&RUyCOA!uC)dLb={J7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankangryp.gif b/local/htdocs/img/mood/niaha/kitty/ankangryp.gif new file mode 100755 index 0000000000000000000000000000000000000000..3b1043207a0a5019cee967fe8681850d3dd9e1b8 GIT binary patch literal 399 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ|@7U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|ohdMPN-#(R-8mED&if7O?{BGc#2Pdyn({pDYP)kv zs?lfJJ+2+Qx-T=`T(^B!rroA{0pA)qCpSOs7E`v1l~FI*spO-1P-S|8&&)%C(UQj< z#W(Ng{&ITW=KgmFZ*4Ynyzg$Dz*65*>!`}a(qhzIrC>UttF^zTDZ$g!Om~7##;kth jI$fKkIzAJX`X?IZ_ID_$`}ioUOqYxF-L+E^=vr$4t1_5T literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankawake.gif b/local/htdocs/img/mood/niaha/kitty/ankawake.gif new file mode 100755 index 0000000000000000000000000000000000000000..b1662cd8be7959df42f85ea52e8b28cbe80b53f6 GIT binary patch literal 400 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zIF%V#8FY9VI2lA3Wd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcOt#Ad fAyXz!US+6~I7NNsN@W#WX;FC-pWPZj_gVu0wKk77 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankawakeb.gif b/local/htdocs/img/mood/niaha/kitty/ankawakeb.gif new file mode 100755 index 0000000000000000000000000000000000000000..e02e383f38d46384ffbf2623fe973d32754e4e78 GIT binary patch literal 400 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za4IvfGU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5aP@Vm@_39q=C+y4RPlE2KD#1R5@Y|niNfWo_4i8J0;fWvuxg* zSH^Om_so8_S&5;7p{bi$TdveoyyvltR^%DQ51Pt*Y?zkxDfrAh#N1F-dZ@B)+ZyZT zzjtMq-WQNS~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8z~5JW(CZd5)9HnXU>K=^L~T+`&+6Uu?9_wraVu(+Mb;fYxG$* z@69V?xzBrMKijOtP{GjD&8#g~>M7py*hMSyjN%7PusFFBEedS7J6U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ_h1U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|ofR;5N-#(R-8l>5&if7O?{BGc#2Pdyn({pDYP)kv zs?lfJyf?3m^FAGz{cN)mLj^-qH?y`}si(M(nSs(&oo50+rU=H#F$TE{Ec1E9n6TIC zp^d#PXU(&VwPp7Wa+zm46xyU&sxn2SFgM$`vb2YKb=iuvIZSAsWKyG3q}!lVW14F! j+HGmQe75%t`{KyOYnCRe8!eo_Szq47XXhSCpmVJO2zir% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankcreate.gif b/local/htdocs/img/mood/niaha/kitty/ankcreate.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0fef55a5874952e86110b46ec7c0a98cc14b685 GIT binary patch literal 972 zcmZ?wbhEHb)MGGU*v!KK2FDnjoETbK7>+S896Q$1@*e~l82&T-|Nr0V|9_w;0x16H z_Hzvhc6JPKHPSO+W(3M8{$$~FW8h)X;bq`t5M_{NU|^Xr!BcbDS~KH=#>b^hc@`Kn zEesHO+EsPKCq0%WF}k6m zbXRVTWze?m(aUd5H{I3taqqL2RS&bH{`_&&Qf20@Git4_YHqV^5G`|x)~nRAF)5zf zX{9@Pu9cp+VU~`}l0|;XD!#re%Vp)$`#psOA&v|HIg*KinL(975$MQ=6HXpjvB%|M(@)#z=QJ(JnlPO5&t?bgcOH!kv*sK=#5awm#6G&VVAGo-tA z6n7d}F(+geHY7#+g#}02&9HCwN(`8*vn0gavwaFPcl^d>G14rGF5DXfcd>4nyIpDL zrhTT%6GoR}-fujcOYYqlh26>>r8Cb4PIO(~1X~)ykyZLwmpRb6A9%n)x~*(74b9FgcR%oN-;adM#B z1l3w6KhLQ$b9{9sH_BRZhp(I$BEMp#7x(HVYb}{K)U(>p*X;9}KG!HC%6VVV!Jq{u z`_H)UpWSCOIl6b(DHCg(vqw7}3ho;hOnfZI#`Eln=nLW3FNN4XynFTG$M zU}whwS0gCi z*(W5OM7`XDDSc{nOdlk%sKU_n$YyHIx zRV{hjuSV)~-Iz9e*YZs@dK+d-9(J;ms^4$BwQ}{1i@YW3aVe2piQ)~7O^(?N>8>5c zod#Ac37LfrNzr~`!I5?|?3=w31Lo>12{HFYeNFF?SO2V`GtW%UZ2lpNE%U8k!&pvs4SCV7uHT%4#&o#=3a^4qoFld3v z{xh!oXZP7mj_%!c%Ea2{?9on#g8Rk=6Cca5azA?_`a<~iOChg!uL3`ce0V%!W7ir0 D5J-~2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankcreateg.gif b/local/htdocs/img/mood/niaha/kitty/ankcreateg.gif new file mode 100755 index 0000000000000000000000000000000000000000..1cd0a73a2b3d95d5a79816e79481c92bf69c3fff GIT binary patch literal 1220 zcmZ?wbhEHb)MGGUIKsmK2FDnVF(@i3IypJDwEPFcIdkUxXJGix@c;jRCm@C>B9B!3 z&+X?L671|4;A*62z|06VMe!#KryBzggAOkPCxa-1Gy?<2E(S>s5sQQc2b*N?dMIs zv_(_s@tI!p@<(5O8ofBiDlgvVlUd^EGr^nD<8H;rCr;BfHPv!=7G)n>$G$yDxAVf& z;~OJS%T;6*9`xRBXd0%n;lSDxyRxsI+d5k)&vCQS^eUg#6ID-cZ2i3Ijm3_QUj6LO zSx-+)*pxC~So7PPnLl$5w}=0KCL$pK_D%rEJ4_7B45|!@K=1qmdWYvg!-50N9Ku>L z9Ty%rw(}@^$w)9fI?~Ohopt1dVe-*F1?Mgi%Y?*}6V=$~*sLg0^_s@Qu|`JV@>6d% zWpy!7te42dJ+E!snUaMK9VX%}e5-yjygasCb(z@PT~D5NFePa( z>DjW$YXfKU^J~2Z&+ptbnmW(tK*P_250CV-z4fiF`rN|l$8Vk)vFzjh)@*Tk9|ybQ zGf!-n&yV-pXLD@Jht11m-`gpGgDM3SR2&Sf4D!Ihf&`U}$A$%tO&k&`HYYYLJlrlI zsuv^iQL(8T81q*mJ}9|$v9WjPXiQRe>fvJ-P)G<;J>8|qFO#8pS;dDblh3MOqEZwJ)Di)tJO^X@xyIpTsKj4-XcYF^1=8Urs-Fh)44K6AOzx z=c(L%X=OfN6rY{363h zO}dyGR@IWX{c5B>*NthjcP-ykW4B@UOeSYLsrvo4TPt_pxX4|i9+wiyohaVW*yNba zknY-1+-YFNmXKN4kQD6~7943e!@k)oF<`FFk`Qyx_9<-K@f(-LNHZzAaBmFU#lB_k zcBP%0_L(kMWI8CdBx0#mf#kuHrzAX^&pJh!bMo8~zkDS;@a&VvcO^NuUpAZObnX1q zqvD)jRyyAFef<6Qm#-R?440qGe6G&~jvBD9IT%62Y;k^WjZRe(MJiJhS3!|jfLxGilWM`gAEUEPITkaR&%Q>U0 zd-IeHzilUU%dKf~0hIs4BCJ`gHh(v#3=HRZ0 zlLOr*sMb39c}|s?^_^x(Y?D)nONJLJ=*C|aNoFK;$t}$o@Y-)UkJZ`Da7*O-K!5DKfU=n Jam2>2H2^Lqnpyw= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankfood.gif b/local/htdocs/img/mood/niaha/kitty/ankfood.gif new file mode 100755 index 0000000000000000000000000000000000000000..a52572163bd7d053f14f64497d0e0a1036c1cd63 GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSOXYX8FWDMAngn+hc}$?T)o%g_1WG36Eyl#GUsKiS{HGk&GAoJW5VutF;7Bl|5)DB zQk%?DXYcqibhqS0&xZjGJ%Nk?Pv3B~Cau1`PU6g$zQ$;+Prv^PF44Fn=}_}})}v)* zyFWYbWG?VAs}Hmib}xLdBZx)1)#et&CKsk`i6vGrG8EK$64+A?;Mr=cm b=jt^(+6;CqkCsS^PA`hATIwvw$Y2csee8mq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankfoodb.gif b/local/htdocs/img/mood/niaha/kitty/ankfoodb.gif new file mode 100755 index 0000000000000000000000000000000000000000..9b07cee1835ad2fc89f8cefc04b06a999d95569f GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zum&)&GU$L5fV4BP9NuukbM;<}*JpSCPtfQ~$()z5YF)&EHpf3@jS0Ko#XJeI{bPAg zOKmbsoxS77(A|;~Js$=%^aL^nJblB_nzZ`%I*Bu1`WmCPKK=eHxJ2WQq(jZ?S&x>L z?f&ezlexghtUl06*u^lAxmwiQxhJN;w@J0mE2E=ct8QYOf7nz5CYJPScZ)eomL@H4 z)G=M-;1OlFNO^8!WY_u$a~pQ8*bsW8vU%c)sx8}hn9Xo->GAV1a^rd9Z%UHE8;y|0@pR&e;-S1+agxLPE zyr-o$nWfI&@nh(2$%&p10~&e)83Ufa;b=`-eS4k6nJ;~f(ORE={}o)KaYxdj=Jl*c z%gT0tcHGHa;A2)FXeI1o7|2{L>h0VUQ{daATIZF~QLj}uvCThhssR&AdbPX7oFz+> zmN)8{u5s{)vRkA)w=uG7{e-y-L?y z_wGM<_~`MIr#ga2{t^Ltj){R8=r7g{Jxbmz2p@|BMVWzeAekwKDM&KXKye-hcA$*d dh91w=Yj(65>{uQxkrbU?6j`;@S&)&z8UUqsg1P_z literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankfoodp.gif b/local/htdocs/img/mood/niaha/kitty/ankfoodp.gif new file mode 100755 index 0000000000000000000000000000000000000000..9dd7dc44c6c471fc1252e34aac23effc32f1aeba GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ybdU|?m?0Vx1!XJ9$J;e_Yvy%w*}?*5;k(U+1rFJslZhy!hof65vYcE5{x5@P$u z@}8F3WR^O6$B&`AB`1153~1;HWDI!vhNCrU_3d>MXTJ0`Mr(cg{a0{_#vMtAn%A=) zEi2po*>NXxfsa{zpp~$TVIXt0sJC-ZOo4BcYMoa`N4-|v#5Vu1sRm3e>DBHQbCxVk zTHdH*y2imH%5IVJ+{VbR^%Lec>{_uQ^hjm%#1&Orw(l^T;o#Ea=VRnzd#(NEt=o6* z-n;+c;iJb-p6Uo9`AY=oIVJ{Xpubo*^eB0=Abczi6lDg=fn=r_rXa~k1I2k5*nu)) d8+trfui4RNuw!|&L{fBmQDoIpXF)~=YXG?Fg!}*i literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankgeek.gif b/local/htdocs/img/mood/niaha/kitty/ankgeek.gif new file mode 100755 index 0000000000000000000000000000000000000000..4d7f2a69019e724748f8c04420f554fe248c8e55 GIT binary patch literal 347 zcmZ?wbhEHb)MGGUSj5Hv0!~g0EiDYkjwvcC{{MdrEX1JrpWDwhB-q(8z|~04fSC~} zs`!(IHGqMQK?kG)q@97~`h^potM^*GKD+yWf<|9T=Ddtm>vAL{@=voe$)1+9y-}g} zrZM6DB58^2!(JCH9Qrr{oQ{i0h%i_SF)~azS9dHsY|GoK6=7?HL%!9`Jo9yVt(eGz zW4GtL{&%mxO0Gn~wWvC+rJ%8?rX`^vrB~kDw_Ccow0=U)q?xmlivwF&=PwY6UJ<)0 zrX#)F(Pvufnk{Q;jjfqXXD{EnZ*8z|!&I@rW5)v~_m}T>vh}V%+ol~FS`lhGP4n7@ zLdRQLu2=7S3Om}jKG1!1?&-6)?>>I|{N?Mn?>~Ni5`_3w8RS=5NFJn}f#v#z6P~O0TD(5H`+tH)UrOe@j8*G$G$is*b27`Gmh`<*VfUsf z;r$|IiR{B(7d;&Mm@YURS5pvSunuBim~gJ{Sa#T!w^b{`)(D4utDAY|>+)JTkq5_a z&w2gtUVoKbiGpiUby`b7V^d8_LPJWgyti++baQF_gq%q;XC)U0wy@4$AQHVIc2!JA zdby*|wA3|Q*3=qXGn>v{zIET)VBdzRVu8nw2TblS-|b}UU4OPsJ2bQ+)O4EWwGD-i zx3pZZ-uD!Cv~PW&`{>-$XK&wq{Pg+D*Kgl{{QM*c@vAb(uRIL=49q~tz`}MxfQezE R8X_2wr9>Q-nFumi0|59dgVz86 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankgeekg.gif b/local/htdocs/img/mood/niaha/kitty/ankgeekg.gif new file mode 100755 index 0000000000000000000000000000000000000000..2acff60b4d989698bffc0af3e16b2ab26461f03f GIT binary patch literal 343 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr7<7+4u}Kng(G8CWiFIN`Z^uf^-LyZ^rd9Z%UHE8M?xh3G%J(rX-V4~6?$(P z6W%Y9mdHNrbvu7LtW*%AhZg3CHxO`R1rad NEG1yDOh=Hx8UUVafNTH& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankgeekp.gif b/local/htdocs/img/mood/niaha/kitty/ankgeekp.gif new file mode 100755 index 0000000000000000000000000000000000000000..7dcd4330152c7ae81319abd1b33efcc9815c5dbb GIT binary patch literal 347 zcmZ?wbhEHb)MGGUSj5Hv1d57^*@i7!qmI2_`u_j_V;~`*;D2sE*N|Xm#{gF&Jp*P& zkkC&S)&K@J1|5(*NIL_|^$RCFSMRlWeRlW%1dYCw%y}8B*5znO$G|g)p z3LS50xn8~RDeP$9`at*5xu?(GzWey;^OvvRzW@07Nf6>!WsqNa82A~OfslcP?ScRk T!$dViFd$2bI4m;}WUvMR>zss^ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhappy.gif b/local/htdocs/img/mood/niaha/kitty/ankhappy.gif new file mode 100755 index 0000000000000000000000000000000000000000..82ecc6f6a69954ba13db8cd3c40ee76aec215161 GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSSuJ<8FWDMAngn+hc=w>T)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y-)wNu|LzAIW4z)qNdhIAC&{K;W~3S zWz37FDa~83 zN`Gp~q>zp*J=eA%Ti3-q+=CBpuh`%mYZ5+ZuFakU?q}90oBNtxzU+A8=B?Xz?%uoq x;NhdkPjmz!-U`fs=s==q-+dhQL)z7QB){_!&u3fG1$plEpwtYXINibs+!% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhappyb.gif b/local/htdocs/img/mood/niaha/kitty/ankhappyb.gif new file mode 100755 index 0000000000000000000000000000000000000000..7f46402be9bf5967432be7518258d8f1cdec694a GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSi}GVhE7wwg08i+{Qu9u@c+Nle-O=}_@CR)H6+;CF~HSG&w!Z` zB=nPowE{@%05JndI|IuhffJsq_gcI@yZe8FMqf(iyo^=r)=0(VXS0^L9{(i5!L;wY zrB{N%2f@OfvKu)hgc=>62UYcOO^eVeDUFufbU(TG>7O?CXIe9-<#tch)cWXSav(Nb z=kA8wzt7kcZOXGNy=_~JiaI?bJ(9cH{0+T&RK0QooNG0#*>dO4@`+($oA14hdC@eb zc?(wQPfeK=(vhX-+7@K%x_F0s@WJgB8=PZJ!spDj*>k}C%o=5LU(?H%9dF#cb^FfU zd-oqaeDwH^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvrZsa~Zudk@t&ct`2V%o@ z=5EOS`-~ycraZgS+qT81sM9mjBe|>1-_WZ^)hjo^xmLrPC3pTTpBN^V`QFQz7fn-| zw_uh2)Rajf9a(y=Z9%rKi+8vOAKYHC!8z6>e9l~(JqO&+tWh@iHNAY<@y5+tx9{A& zcmKh|M~|QA2tvFS0P>a)gCGMZ0~63&90d)5tClQyC4=xYlB57nz^WySfs)n$0|j+I literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhappyp.gif b/local/htdocs/img/mood/niaha/kitty/ankhappyp.gif new file mode 100755 index 0000000000000000000000000000000000000000..cbb6f17b37d81351a260efeb3a749967945dee23 GIT binary patch literal 330 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ydTU|?m?0Vx1!XJ9$B;e_Yvy%w*}?*5;k(U+1rFJslZHBvG8*{mh5$3Ka1Fzx$p z>6KvcL9lSA?8XQQp+?8&K~+6m(;{?AN~4)J-B0d)`lpTknbyo{x!n^rwLbc&9Ec6q znY$tP?=yx(oAT^RZ`&55qE639kL0d4e?zYxRj=Ft=UNSGmfZQXd}5eb=6f$=UNlW< z-hx&7Q&T2|bY$tdwguU`F5clDd~kck2Ip9l@HumB_8f3Ovqst6*Yxsb#~U|q-M(}8 z-u(v;A3c7eBM9+U0LWWH41x@t3`{_8aTGKJu3EC-l?=kqNRk3P0jriQ21;530KlGi AfdBvi literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhunt.gif b/local/htdocs/img/mood/niaha/kitty/ankhunt.gif new file mode 100755 index 0000000000000000000000000000000000000000..d00698f86c80ecb39f6dee451b22e5577e0678d5 GIT binary patch literal 322 zcmZ?wbhEHb)MGGUSj5Hv0!~g0EiDYkjwvcC{{MdrEX1JrpWDwhB-q(8z|~04fSC~} zs`!(I)rNtMK?kG)q@96f+l3RJtM^*GKD+yWf<|9T=Ddtm>vCT2E6_P#lFPE)mzAmi z_4auS%zt$m3T)lSv##up# sSCm0s;b9O5Qp`ZFa9!w0<$KN0If%J*Z=?k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhuntb.gif b/local/htdocs/img/mood/niaha/kitty/ankhuntb.gif new file mode 100755 index 0000000000000000000000000000000000000000..752b09b6ee5bd5c64a0ba10dba199342871dd3d9 GIT binary patch literal 314 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu-Y)NGU$L5fV4BPY};_cbM;<}*JpSCPtfQ~$()z5YF*CjeFZw_OJZ5J`?50izurD? zf%&gaCgvv!lAlDUdM{?zoU6B<`BBILmX8~}-|9N(y(wnH7=J89!s@-0-^TORAXbGUArh z6a>zl72Yeqxhrtu#EPmE)zsXLhvw|mO*_6X&EfQ!v**rVxOnOEm8;jT-#9A>@rp9Y hD?AM149q~tz{0knCy^rd9Z%UHE8=k>k2c9rWHW^3}75k=xaNEWg~EL10pV z-1Gzc(;vr#N)?r5C)C#2+Iu8Px0I)}dDkSkcr{5BP4di&Na>89F>`Ks-Sj0@%yk)Y zOKJ)N=gtc6mEYVIIB{Y{Rf=kA?#4rNcIu`b-U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$ydbVPIv@0Vx1!XJFa3;e_Yvy%w*}?*5;k(U+1rFJslZoY(sbbk3K=vTXNdW$J&u zecl4|U!6?MPZT6SiB9!i%&s|CZ$0y)kOM3qH+a9*b~0lb<>wrG1q0p zEvYF8oI5MLSAKI>;KYd)RVk{exf>77*{Pd$d|#Tw=`&}~oxgDL(&Z~xuU)@!RuJM9 iWsp~R7{nQvfslcPZ9`8W7lSdvm&j5KL0po?4Aubkzijap2|}0~Kr2x(b(k=H@87P#dpCxugi!uF^z@X%#bO&ZoON;aq~ClPcd4+{gogTx)ZIiUp+DTN7M3;SL)sWt{lUhQ1vTiGK1 z_WM-9J}F_z1KSn`8_Igld3G_lEM}HY^<$rKzdDdR8>&1D-L(Ac?S0dFI#VV(OrBz6 kR-Qbow!Bbz(QJ8zEWM?9rWs3P*S1$}?AX}J3UsD50K^%JX8-^I literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhyperb.gif b/local/htdocs/img/mood/niaha/kitty/ankhyperb.gif new file mode 100755 index 0000000000000000000000000000000000000000..bffde8b1c0cddaf29277bcf2503a11e69d5ab4da GIT binary patch literal 390 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za7r?;GU)I!a59K7$TBdnOx)lhxooZ35oywFU(CoyS>srq8M zCBZ9#X3w8KTT~Fmm26N~P9o?^9u@|E2Z=j+b3zLuQVJ8i7WTbpQf&;9yxO_Sx3We2 z?f0pIeNw`b2evH?Hk9?8^Xy`9Sc>9eesv&sHdJ{Qx@q~>+xw>Vbf!#nm^{VC ktUP&EZF!;cqS^8aS$a$JOf#0ou5GW{*s-yb73fTB03D-@2mk;8 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankhyperg.gif b/local/htdocs/img/mood/niaha/kitty/ankhyperg.gif new file mode 100755 index 0000000000000000000000000000000000000000..773cf0c6760f36f98501599f7da87d78722ced74 GIT binary patch literal 390 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp{>8CV%~co{eu#29257+5B5@Q_@#*6ebF`g zvD}j26+yG-PoFI+h~i2%s4FKCbR`c91HXgB9lbfB1raHQ30@2PUNosT21#D+T;*HY zBL4RKRKY$eVaWsA76u#2dd_)vF}N&dmQM9!pK!lAkUJZyJPX~l{Oj#~(|S5nCOS-> mVq;dGJgc_6PU;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$~lWME~`;bq`t5Mz*KU|^ZJ!9#M{TC>Xy>hGmgIbsc(5)F8scBMT#CHBgzZOWTh z#abT@+-}{h#8AP|)Xl6dSL!L=V_~2)Rp%M&k12w2TjWFB1+sjS8g8Ze9W7D$FjL+C zVqyBmHND1xn`;bItWE1GT=JQlqwGR$yc*?_B3!#l6CI{i%$PZ=Hc5G*nS4)T(h^hk z#d1r6R|L(TKYg~SAc`y5pst)m(3Lza4Ezofcl73j7DS{JCU`CEd(ouY7$kYMbCqvp zi}>5`Qw95^ge4DbTNrF8>pADy#o)4-Svu8^eZu|fK<;d)@+@@I@~^k|P3!4QndmTi mij7%$@~qnOLghuXyteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I yL5Cp3OOhZj2{8yTa569hy~Mqt$LS@D>ElMt8G;BeBg;29y_7LcZg>flw*~+wlXRZ| literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankittenb.gif b/local/htdocs/img/mood/niaha/kitty/ankittenb.gif new file mode 100755 index 0000000000000000000000000000000000000000..7153ac366544b7b1afdf775be099c719e2232d67 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu%a^isw&x#1;H-WmYjoOTBQ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankitteng.gif b/local/htdocs/img/mood/niaha/kitty/ankitteng.gif new file mode 100755 index 0000000000000000000000000000000000000000..bf337dd06d3dac0432b940f94d2759dd66256111 GIT binary patch literal 332 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr8)7+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k z@BV`hL5PU;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWMNHVU}Mk$$%C{ru8n&VII*G0~_9Q7FWx!z{8nEV5=o;iOuY!s%1XS*Cl>VVq|DuSH zg&NMSuHLrYDZyLZ^HRcX*P6I`ZCtKwzj2$p&HfZqb6*qI*wrl?4%99<)nnFv?dGl9 zckbT1|KMSVAjD6SAU_E)2rzImFa!O>eSydMC5!3fM$H+52tOmsGdRDLF->lG36!@6 E0C`e)RR910 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anksad.gif b/local/htdocs/img/mood/niaha/kitty/anksad.gif new file mode 100755 index 0000000000000000000000000000000000000000..9e2f6b534aeb0d7634852ff9e3d06bed95d8b380 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LBnHoETbK7>*tL|Nj_7Nbx_npKD04vtxj(k)8oFBT!WF zCktx;0~>=5NCikc1IxY(Cp=g0wRnAY_x}WqzLd;)8LQUiye?`gIQm|Nr`hLjW$vAp zc`O<=oE#oaZ)RMPoa~XdnXM(N*)Pd#r@=y#&E??6lmk61EVE3+zUS5{bKeY| z%A+fC&?45NGJ`qHvc*5nPAtZ&$GR<`K4emRXB9JR`0Ob~vu1m;&YhuYzOXjJuG(wz zQg!$0Aj|#)-|c|~^CLE98n$g&uV}MnXQ0KwB9r(tne#$6ADX%6(y6NxZrr?e`_A2a i_aA5oB6&%KL4<*o0q9E>7K0g*N(jG-Fo>Z@SOWlIYHd6K literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anksadb.gif b/local/htdocs/img/mood/niaha/kitty/anksadb.gif new file mode 100755 index 0000000000000000000000000000000000000000..3b360d429468f681bf60fc7234038dc2aa7f44b3 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LBD6rg#NiYiaop1P~#`|J;7AA;Hd$0j@@R2F#2=QN^Du ztN{#c3_2hcAngn+`!1aDT)o%g_1WG36Eyl#GUsKiT9@;>sHx!SdljB$pSzX0cUtDL zXw-0Wcr?A4aYb^nN7`n#mZ)aGP@k&Syl9^W3r#kcgBw#0^sunZG7gd^VaPeaNKt&MIcs@Yz#}X3h3wojXI*d|_>bUA5Qb zrRwh0L6-dqzS{!}=0|MIG;G_lUeRXD&OnQUMJDlQGUtVCJ~VUBrBhcY+_-t`_MN-; i?my5FMDmgdg9rmF1JIW&ECw?ql@NXvVGu)+um%8vzHM3n literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anksadp.gif b/local/htdocs/img/mood/niaha/kitty/anksadp.gif new file mode 100755 index 0000000000000000000000000000000000000000..1cd4f6e58813070e99a0043129236788e43fbc20 GIT binary patch literal 318 zcmZ?wbhEHb)MGGUSj5Hv2LH1STee0Wd%yJk|NqAzLW=*n{aizWogD*Qjr0td8G)jT zKUr7<7}yweKq^4m8CdpRIN`Z^uf^-LyZ^rd9Z%UHE8=XFt2!O{0BJk36LD|7F( z%wy50;pFgWdNbpSUiRjql^J`EO{Y%T{krX1*DVVPwj_C2>wnfqqw zR32TCgBGzCl^M)omM#8qc49GJJ=Sdj^&ykmJFA#k!)H$^nl;;#b?yvJ^M$n$cGX^! zm#Vv02U+$f_-+p@m>;n*)39yJdPSQpI|D5a7MaAK$($Fm`OwTgmrh-saO38!+js8X iyZ=B#5Xnm-3?dAy3_xG9uo%pcR6_Vwgh32N!WsY`h;N(# literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankscared.gif b/local/htdocs/img/mood/niaha/kitty/ankscared.gif new file mode 100755 index 0000000000000000000000000000000000000000..821f52bb15bdc951238dbdd6369604ba376a17ad GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zI9VB38FY9VI2j}uq!}1k7Hsg4T(;KieuMh^TdEwf22F~lJWspYo}ChF^jS9V%`0O$ zVF$?x20JqCw3!-a#O$)zpjNyfWnadelz{A3xk_e+{(_|(6-f&XQ?1$=UkaZSzC7_% zpzOS}hxflS3s+NUD66+MVG4F~ZAn+{>UPXF>FDhC?3L?Rs%o=r(aFj? zaI!M6GU)I!a56|RNHZ|7EZE>7xooZ3{RZ{-w^TV|4Vn~9d7gH)Jv$}V=(B9zn^(qi z!VZ!X40dGNX)`sf~F lG{bV8NSSn%IkVM`O!bsirilc|M~EKK5JYk`_YiWlH2{_Yk469h literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankscaredg.gif b/local/htdocs/img/mood/niaha/kitty/ankscaredg.gif new file mode 100755 index 0000000000000000000000000000000000000000..9cde3d2a60775540d748113e96941b7551148341 GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|g8CV%~co{euBp9R_7+4l;@Q_@#*6ew|5$q5EKGVQdP8fL`ove=+jydY&?#+;OZ>{hu-W`_QPr5qJW3k_4P+8JL8pA)`3 z@l>Gfyt9Y*zcLF~Q)noww>4o3c5-b=SMBO{%r@!h?Dp)H>sP93vux4H(`hs|)U{r@ n#DAJ$xlW`^y2_l{>PDt|$|}=D0^}n^4`>J?IhuP2IocWkI?av4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankscaredp.gif b/local/htdocs/img/mood/niaha/kitty/ankscaredp.gif new file mode 100755 index 0000000000000000000000000000000000000000..da85544a4e784eeb3ea375b5ba06dd76772fde86 GIT binary patch literal 419 zcmZ?wbhEHb)MGGUSj5Tz1lfiyTceJ>U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$}~Wng8{;bq`tkYJEzU|?CW!9#M{TC@8N>hEuN=mDVp*;?P_~=O03am*}ONe zjOBzKBqtc`$h6aDYM2qT%VL9C@q(0n8FNwsvRmaUnHl;EmU2`iEi_EEYG-^Yd`|fC z#8ZK?^UfaL|H>>}O`)Nz-qwUE*vYjeUA3#*G25i0v)i**u3xFD&9X%&Pp8q?P}h3p n68~w2DXUBq36PHvJ)j|oU%+`Rbm9+mz1v*$B=-`DLPI!9nu()z|_tyu@G7~K) zrdcjiJk@mb>$w=W>UX|Rccpwk@W68kH%E-yJTC(W$=O?$PhPp^$UJ5Zv0FPiW;7?4 z$w;J6jbm(VV4Qv5edhb!Y7_4N`0N+EJ^52*QEF*gQX~UIen*v9UO{SFXM1u^af5qb zC5wA+L*$IEDRbsdU@mJFZz!5uxNP~_!f>Uu@cF4pi%lciHi{{ST1)IZAPaT%kP2pN E01yJ>V*mgE literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anksleepyb.gif b/local/htdocs/img/mood/niaha/kitty/anksleepyb.gif new file mode 100755 index 0000000000000000000000000000000000000000..3cf516bf3ba54e17d34bb7d02f314ba6e4c4f41a GIT binary patch literal 593 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? za0W22GU#wIa52a-NHH+5%-PW5>Ach8^Hx&4-6 z9Bc3UsY&$I9h6ofc91>#^ILCzzjI-~%&wRgIZ^Hc_pZ#LDCx5CeN-a%GiezBO@2C>XD@aZ2Y){T9 zZgB6bWOeUth@8U;6(4|6?FN7%2Yd_Hzvhc6JPKHPSO+W&{c< z{$$|{U|?m?;bP!okY$i!U|^ZEp~cgAr^V~Ny8jnEZA>{Hx>T($S!-f$RG{Rmdlqv0 zEyXz2-uF|J=&3t4Z%IYUskEbxLYlI1YE2per+5oiFQ4Dwu)t-1#)Bi%RfTuGu$b{y zOdc%-yw9r^N;3*H={eGH2B; zT9IXJy&%+hMqKo~#Ha;pgp|TeO-w8WAr4M~IG7daV0oZ}7j8J=>Al0^%GuptA1upE zw49h`xlHj?)6K8vV%)0V`99s1^8LUA&n4U(F>dp`3>+k9Z&^Nh<(eb&m^H+1?c|uz zoLnX&kv=t!v9W=1_I>x6?{}+Bxc}p`U+nhePnAWfrD;i#3=H`lRbqJsscD_<$vMRh z?tPUk?!66>GrFeCnLB~GtW~_BXl~)MWd=tj)dL!*nw)k|jNBZ3|JI7Qch$F- z-BoPz_g~JzQDxM?TpQIG+mfB(Tb!obZKb7bBhsTcONgybfVw*c6uby`FD1g=^SKUy z+$}2zba(sidB=YGcsU+YEL^D+V}4w+oS~w!*Zrb!xbx(oK($?q*u;gP~Imvu#L2K~s66W4t0uXp@x+(BV`4>x|km=V}}0YA)>SvNmnj>x%4IwW4fE cwz>V9uAHR{Gl4FzwKSL27pamQ!Xa)A0QR>fRR910 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankthinkb.gif b/local/htdocs/img/mood/niaha/kitty/ankthinkb.gif new file mode 100755 index 0000000000000000000000000000000000000000..e89e20e07396495e3b47972d54a6283ee3429a99 GIT binary patch literal 778 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zaN01iGU)I!a59K6$T2XmOxoZfxooXj``XHRjS2~_7IhB{CNz3wHSL=A>F3r@v(A5b zcYA3s&j#gPHYQUGHIg}}9#s>X9=(cVebAa&$_$Q5ss}VqH975`7`Zw6{;d^p@2YPv zyQ|pb@4uXbqspj(xi+dXwk12mw>V9=+e%B>Mx;k?nzlqn*3ACd{ZXki)F#i8krrLy zsM{)QnkR0UwLvyg5XqUG3>*wHK*+$dc*6-x=Dim84{SZ(s1S86Jn`XzX-|)r1}#{{ zl+%`Mb9t@ynK|+a;l`pVyYC8QxTwuUP^?!=W`tZ zxm#8c=~bYDL+S cY;*fHT{%k^W&&MaYiTa4FH$8rghSjK0LWt|_5c6? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankthinkg.gif b/local/htdocs/img/mood/niaha/kitty/ankthinkg.gif new file mode 100755 index 0000000000000000000000000000000000000000..2f522b22b992d5992032f0fe57d21ef1eb2b8f5e GIT binary patch literal 778 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUp|!7+4u}co{euL>S~47+5B4@Q_@#)~tPP<-A6P1Xqi?2L=-wy|S8iP5bn7>!(@g zKfJrWw3lat@-7>bsf8NJoKugg2~Ce)#j!qU%`9aGMx zx0l^jZ1VSC&cRV-)WBRD)fn57o#9)YrrT|$rEDY8qc=@kA|q>N|Lp##)ER1%XURy5 zu5i?Cl{L*1H_X}~8!3q7Oil(41{ok^U|GE3geCJ{i~9$*o^Mo$x)z@JaKW^v$4i42 ztYXS(OSZYZR{P8x`Gjy|(UjeH1u|UJ<~PqfW*OnMbiw_cOj&^qvz52}`X$xBNPXQ6 zn`LEw8~k@anyam!l6&CZ2~DHwKn+W|{3hFwqWqdFT_eW?MV9283GTs6EK~faHMh+w zFm~0f&selrMq4kiq$_ZKu*2pob9>VX*(dERi9Fc&!I|UTH2zM_f!rk+^ z4uIS(D+qLV`|f$ie)@Ph9#Sk^sT5;=T(X>@qO#ZhqHwtLqKl?u?|Q~m3V+A`;A8|P{+?CY{NZPx3G>{+#< eY)Q7c{hF?vr3*8GF0ZvTm(>@kk{rSzZVdoVTqSb= literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankthinkp.gif b/local/htdocs/img/mood/niaha/kitty/ankthinkp.gif new file mode 100755 index 0000000000000000000000000000000000000000..94735e4e7240d61412d44e439365ad358e679959 GIT binary patch literal 779 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ|@7U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmatWJ2@FR7-WEufo1W96PC<-E$$!KdcIL1>RNc>!v)ix z9xn}Au!z7pj zBK37QY?hVzZSddyXs)(?O74MsCp3+!12rt=@|$c!it=l!bd4Mn6j_pUCb$PPu}txw z*4#F$z}Qu@K4Z~h8Ew75lCHq{!48|V%sPBqN7Aq@ph<%y2*iY%c`Rw_V;PxY@eYRjCfZJevQu&>M7v{|n! ivS-zbvL)H(_G`LwmM+W$y1drXTvlJCN^%H?xHSNk-z)b3 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anktired.gif b/local/htdocs/img/mood/niaha/kitty/anktired.gif new file mode 100755 index 0000000000000000000000000000000000000000..d4ce64b1482c228f4bf4b85a45990cbc352b8648 GIT binary patch literal 368 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSOXYX8FWDMAngn+`!<~LT)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y{f#`%h&2%+%vCl=S{|H2Zy5d5oU?A zpRHv~v?yteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I zL5Cp3OClgI2{8yVa569fy~H8F6R>K@;#V?Y|JtBQ7BmE|TCxBtnF5g%0P181>J$~2 a;@K@z)Ree$t^}(e4AuZZs(Pyc literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anktiredb.gif b/local/htdocs/img/mood/niaha/kitty/anktiredb.gif new file mode 100755 index 0000000000000000000000000000000000000000..cc677750cdc35f001b815f2c5614ef493cacc1ff GIT binary patch literal 374 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zum&)&GU$L5fV4BP?Avg{bM;<}*JpSCPtfQ~$()z5YTX*CnEY(k64&FOL^zoCeYf;V zF!&%?xKnmxgoIF|B*Y-Vz{$W2^b+@m9;cTqrjHvnX9$A5Y=bV};Pg_)G`Zm=R6YeE&koct cDlo;fTc)TfapznKR)I*b%7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anktiredg.gif b/local/htdocs/img/mood/niaha/kitty/anktiredg.gif new file mode 100755 index 0000000000000000000000000000000000000000..2389d6a59152b1a537fa271eca59c938abb37707 GIT binary patch literal 374 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr7<7+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k z@BV`hL5P<`Kwc7J5MbbBUK7H5;@K@z)Ree$t^}(e4Auan1${06 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/anktiredp.gif b/local/htdocs/img/mood/niaha/kitty/anktiredp.gif new file mode 100755 index 0000000000000000000000000000000000000000..4f0652d8a13e06683cd895b98e5563c6b2e87515 GIT binary patch literal 735 zcmZ?wbhEHb)MGGUSj5Hv1lfiyTceJ>U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWZ?{8U}MnXW#D8GVUS~BV3~ZuLvq<#v-Y)>^BNTr+$`!I7))sN%4*s*?bFY# zpJtu^@b31~UY-rgyKGFR7HTAOPCcq7G(CD1$NHc(vy>Sel~fOCoN98~Juz}~^!-~a z;@(x?UUpZp$=`oD2S=4r19NRuV{A)yhHr72Znu?|vW-ZO-ZX8AjI5dcv-_h`XQ)k{ zB_l1mf^|h_p?FBEZC0MShmat|og%32oJO=ew=iB@k@Km^;(p%YPlll_;hNKS3pFTA z+_K<8UduI~!0qNXd-5*Ve-k*koxPp28tBeC5vE4V+T1Loz?KZ%9;>v8;=R-L zdL^=Qw4J04m5tRF&D2v`G+QPlfHkDQIMcLDeBqjnnNd)u+Mqgh&<1G=sym4aQZ9xY zg0XV5)>xd`*utDv(wQR3d5Q61XqWCrBPIbAsU~(MJ&h|a>VaM}rCKK+*1vaa&YR-H z&MbC~$tf(2iOt0gO?Bp#R#oQOm8HPgFPf=WB$1=6E4^Ueg4oPilb6kvS?DObu(#ZC Q;>Os#{EchGfI(^v0O6w^5dZ)H literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankwink.gif b/local/htdocs/img/mood/niaha/kitty/ankwink.gif new file mode 100755 index 0000000000000000000000000000000000000000..f61c588f9c9abab910d50dc1ab649a3c82797792 GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz0!~g0EiDYkj{X0C49o`+ivPL&TtkAL9RpmA^bD98K|()S zSZx?s8FWDMAngn+`!<~LT)o%g_1WG36Eyl#GUsKiTDL|jCO@0C#P#?m5e}w(-z~io z3_b`J?v&jaAtBW0_&lhphih7dPDyDr)292$y{f#`%h&2%+%vCl=S{|H2Zy5d5oU?A zpRHv~v?yteH?asg|X1`qXlk>E3ggXX!D`jhNZLC?aH`hI6Z{ zw{3Sy@D}&HlyKX%Cazu^mn++E+~#hxKgHDC_vD_{EgKHhE;!X=)_(QI&0Dwc+`V`I nL5Cp3ODP~PNiYa9Ff%X#y~HZO6X4c~@GO!{K|`QJCxbNr7DjEO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankwinkb.gif b/local/htdocs/img/mood/niaha/kitty/ankwinkb.gif new file mode 100755 index 0000000000000000000000000000000000000000..ad7176c28e80703ec751096b422766ff4f0ab00f GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz1cpviyn?Q^wEPDG5FZQ_|8x7fh6Fo12DlpO889;f1r>j? zu-Y)NGU$L5fV4BP?Avg{bM;<}*JpSCPtfQ~$()z5YTX*CnEY(k64&FOL^zoCeYf;V zF!&%?xKnmxgoIF|t|!m~&+1r31?oeb6h{j6_9 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/niaha/kitty/ankwinkg.gif b/local/htdocs/img/mood/niaha/kitty/ankwinkg.gif new file mode 100755 index 0000000000000000000000000000000000000000..7f5322d666a441d4a2d848f738c3812b644b4107 GIT binary patch literal 320 zcmZ?wbhEHb)MGGUSj5Tz1d57^PEJm9=FIv3|38Qi28#c={aizWogD*Qjr0td8G(X| zKUr997+4u}Kng(G8CdphIN`Z^uf^-LyZ^rd9Z%UHE;jZ{p2HfxFN@lPTgO#8lD zdLp&yD>sSsL}CxP*o4tvR?yOX2jX^=P=LGW11T=vwu-U$U+V0 zR#$J^?v&sy?s+NUwrfpXy*4gaw%@qT-DZD^sk!gTJ*!(b9H?Dzs>iJT>W!PXZr{0k p@BV`hL5P=9Kwgqy5M*FxU;=uHRe&eJtrOu{B$U;6(4|6~9E{|5;%Fev`#_Hzvhc6JPKHPSO+ zW&{cSWMQ>oU}Mk$$%C{ru8n&VII*G0~_9Q7FWx!z{8nEV5=o;iOuY!s%1XS*Cl>VVq|DuSH zg&NMSuHLrYDZyLZ^HRcX*P6I`ZCtKwzj2$p&HfZqb6*qI*wrl?4%99<)nnFv?dGl9 uckbT1|KMSVAjD58Fh4Oe0KLh=bioDTRS5<`24)5(pfIZdPeNNKgEas#0C9T& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/angry.gif b/local/htdocs/img/mood/opiummmm/foxies/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..df166b2a8ed1197f6f4ad1a0b69ab9bf47e9d3d4 GIT binary patch literal 210 zcmZ?wbhEHb)M8L#SoEJ^!;TIA>lywtF#P}j|NZ;-2M!!y00YIJEQ|~ctPDCJ9!RYN z^Yn;acm5fi^2|0?YuRI3H~*lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1y|a;>kq nMuxbgPoi9sN~(H#k4Q?3U#ETXOsOWZlF}thmn{$AWUvMRv~Wka literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/determined.gif b/local/htdocs/img/mood/opiummmm/foxies/determined.gif new file mode 100755 index 0000000000000000000000000000000000000000..4a643980e4b7b0ae705eca35ddac250e19e7557f GIT binary patch literal 245 zcmZ?wbhEHb)M1cg*!-V?fgvCvJz>K13Gxc^|LYlm0_PbR{{R1f;J^WXetw`d8c_Vn z!pOkD!Jq>Y2btl(vPj^h=jy!{ua^XB#T+WV>ptfNXIEO43X8|NlHB_{j&CaZD%o~b z!(335OH*Ru)F9r@3oA;hI4jp(YI&eg@r&zV|Mz1)Uv1n)jm(zSUQ3%H$XdN|$JlAICXU#V*UdzHh&9}Vy(BUIT%>)^&0dLP(`~Uy| literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/discontent.gif b/local/htdocs/img/mood/opiummmm/foxies/discontent.gif new file mode 100755 index 0000000000000000000000000000000000000000..b70972864503d88b30b3a4abe4107e08e0b6611a GIT binary patch literal 222 zcmZ?wbhEHb)L_tISoELaz<~q*>lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1yNIp5}e&HMknvH~4~M@-iD7QA4POx)n> zzBDCj{f#wc*3wsPrawLJ>AP`o&z>I%RqE@|!s%1r`jJA$n`34`qfXStr f`YXkk2Ds;hq=%>Mo|$*tlDoM3!o^FGoD9|gw;Ei> literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/enthralled.gif b/local/htdocs/img/mood/opiummmm/foxies/enthralled.gif new file mode 100755 index 0000000000000000000000000000000000000000..8b6b71a1a6849e9b66b1be6f28ff15b50104f0a2 GIT binary patch literal 225 zcmZ?wbhEHbRAbO&SoELae?7y028RFt|G$6#{=k6)3^1VhlZBCifrUW_Bmh$Dz`V?3 z*PVX`r#xdh8CrrQ{>QTxN(Q8;S51vl*UFYY^YPifigoX6QTxMrJa}gylUdN{v?7FLnK1#k%)@T;`izKd{W3m8I#X|KV4b z^DnH}!ZFJ(V^faUHN}$Rl}uX7`${aDO$5sW*9I+r_Ey<>lKq{y6PvgF`rpvl)ZEe< zlq(%y7t!e!)s+zKV9ZrLFI2n0%7*HyFEb U)`(22ic!#7)pqy@4<~~)0P)pV)c^nh literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/indescribable.gif b/local/htdocs/img/mood/opiummmm/foxies/indescribable.gif new file mode 100755 index 0000000000000000000000000000000000000000..9adbfde94208917058d3ec2df80aa42318fbb4a5 GIT binary patch literal 201 zcmV;)05<06+tdXu90~Fv>~g8D!|KNj^sdR>~y^Ac&^sDQF=n&vad}whay^tM0B< zEJrLFkH{qC;2De-zSObh3J9#BowHCFQZA|>>f{vnYSA=K$!@#f@VI`(*f3%G1bGGd|Md+2 z;~DF4KWi%S$41#?B3JJ)@*F*nzf2AmswPR z@6?&osV9~xZ96de>b2`PZr-|m-Jy8WosQX}6XqqP+?cvLJkR=Ga@>L?PA^*CFuw{s z`d#hu)_I4S+5(f>cxOxf_%b)}fs3epCQHQx<_k-&Y>8oc#q#4LQ>d2DN)ekW&z3td z_DBW)zs9)XB0m#L~DEW;m!TJvmUfGEmK?*!MVZfhV=!pW1F>d zR&9F}sB+kN{%={1xexAdiI%85c=Lyjv9H$Ji${)eb6j|#q7nR#@4@lu3K9pi=LPEC zeB%FXkC;V-LP>bT#{E_2c~(AqW+>{waPr~~Z|m}Dn*SG=3D1d`s4gn@lywtF#P}j|NZ;-3^1VhlZ6q))&UV9wGPaSId0hSx}K9@Ymghz`*ddSu$ls%1`zdXrC|1yia%Kx85kHDbU+-CS_kI2 z61(pFGdShBy7$`JzuV)H5?!99hh@W2zRT>D98X46l54?WsHe{`dcex{&4+ zu9grpX}z)_?bt4hKI=R=tI6d$A=7wTi@FjLoQgFngxi}ZxVVcg*3b-&_U}^H)SeJ* NynK1%9sy1UYXGC3RMh|g literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/scared.gif b/local/htdocs/img/mood/opiummmm/foxies/scared.gif new file mode 100755 index 0000000000000000000000000000000000000000..0d6cc9772557d02531d041bb613cb11a35888ad4 GIT binary patch literal 216 zcmZ?wbhEHbRAEqISoEJEK|bKXfddC>0*XIb7#SEC8FWA#kXi@k zxe~kX{4+S^IaM*`#oCQ4rzrNN9FsiCzAopr-t^^qN4Yy)?VcP}u(Q9A>fo@{%6Uod z$sDUzwV52wx_bJ1=AOG{Qn0V#{FWKBTW$7CdA{0^+q2+OvETaJ?|+28WleuG-_td% z&{3x`G{h@hEhi>CLc@AulS96Qbezi+MitGr9_cW{T&8*2$(BY7mgEUJr?|V!RM#`y PCfBjHa`zrlP6lfLu9#HE literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/opiummmm/foxies/thoughtful.gif b/local/htdocs/img/mood/opiummmm/foxies/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..6d7457d094c6297bd33ea0d9f06a81199f000a5c GIT binary patch literal 204 zcmZ?wbhEHb)Mij(SoEJ^!;TIA>lywtF#P}j|NZ;-2M!!y00YIJEQ|~ctPDCJ9!RYN z^Tdc>Y2EW|+0}>>S0$GX0&Zv`_ed_qOj8KEH?2RyR_K+8@dWxl$oq;{kDYb>#1aMF&)(^tgmzE gTWz~%Z}FbT6{-^>9A8&&$`FZny0zfzd_e|l0JL#(CjbBd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/angelic.gif b/local/htdocs/img/mood/punquinheads/blue/angelic.gif new file mode 100755 index 0000000000000000000000000000000000000000..8d3ba77efd158bdb900e260a77c494b106d568ef GIT binary patch literal 2006 zcmZ?wbhEHb)L_tH*v!rF{=l!N=l}ozpJr@qeCCYt%$fgZ&YYQ+mUiaMnY6T-XU+hn z{xcu}#sA!Xt|7tBjsdPldIrplKq@^jy8y;`Q0x{}VKV zTry`pcH_voEu^_EjY%eY_3K;ab@TQvFmTjSYY|(NbTUL>B6n)>E1PdZSKeHDWmv&0 zq*FXW)p%|EhNImX$_J8;CfLoLJ(s)r_u6x>zvptYCYSh@`LJ>}k*hOPzNwjE?@chNgSFaV=-@Rvl_2Kio=U=|R z`2O|HpTGb93sT#|vkn=tM;c7NZ8(GX;(LcRY4Yb^^e{TQt8l%2IV;xVieRBwaY=Ex zZ%(^!Z9{3JaC1*tMO0Mx#0HV(;^wv~k<(_k2+e9K0r`|GCt<}Zt_4eHa2FJmS1{~c z9nZCsVMFcKbeXnw-qqg6Y7Mu~^I<)G=ECIp7gA!kU-7=|@8NR!!QB8MH`m8t4@-eO z{1WKl$6vlbhj{ok)WdRkVz@6QbDr|Tb=p~iPCBPstPjo%xXo>I-a4-TsF0L>=MtmB z7!}bAE0j)Fd#w+CrrG$`X{%iG4TXnp?6D;w)@sp5IxL!U!g$_Y-(9uK;KcL1+PeBe zPS*5_psGMt&X&R?p}OXRwyw;e-i8UqB2$W{#l_8UPlGUr(6Xo zYu0fsSviNhq@=orVek56uDuLf8h2*PbZrW#4>;ARx_eO|>-h^;rZ2vdk+}Ot!1WL_ z&+AVfx{>JNn-u2ZHDTF*n{?w^q!`7t+1_i)?2DDS_Ga_nzHoIepW>oIZ&uFQtT>_a zn#_9Nl4hT_%FY~--t7M5$SKpNi)PMhm=iLuvnnHgHqgf{g=^PywWZ0|H!$qlP_T<( zOPgl@CU53r-bW4|VqLQIOpNl5v&+sqx}3RupzT8Vr5m>cMBH2-K79sE(o*bi-m*V` l_wmicPhX#Y{ru|J?>{dEsa#?Wkqk`T^gNn@2UiBR1^{fzo7DgS literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/angry.gif b/local/htdocs/img/mood/punquinheads/blue/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe6f56225b90c0a292b259bcffee841890c5c22b GIT binary patch literal 1147 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMGbmX>C0Z2bTKe+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEC&TndamAU@%rrVneH4)@|tB4Ki8&3 zcOZk$(BP0Xd*6odT<4JS_-`Idl}1fcMpR^zTWfnSb60U~U;7069tK8+_8GJK zn`LWi85bv1EN1MVI<0n2sUGv%RjVhJ)CG)s{rzSRdh1PYU=!^lBgZF-0h8J))pbN zgL0=?Pt)VRv*lN{OaAf99}Tf3<<5nBrmfQ!xL4Isz*3`8my#75)8f|N+0WclT0fz4 zl6@c0U!Ak&Ol*~{t7lxARJD|G;`ABy^UC#@*RNSSrMw}UWy{uWS-WURnmHP7Pl-##DaZuV7p_y>KC8*ThLP zr!Fp@HOFIq<)+#dJuKThw{I<*-yXUvKG1j9k%N&@{>P4=26;*b7*%ZNu3W!#`o`@u zw{Ko}0Q3~rIc8B zJv`3DD7)$VMwUXWs;Kc`Y#YbrY!{0LSrDx}MWMr}1v|rG$<_+7v1og|&4reGX1(t$`w zb7YK}Ko%0lV1$ufguzPP;^+*p0;Ov7kGg)g0I(zXmf$zm!8kJSW!X2!n!h+UeRn%wcZKUn@l z>yumBy_1*l$2nh}g-FoHHMQg)D=4IT;h8V$Nt9nI$cl!13aY@WiZOXfV`~bpy`=T} zXVvXwRLqyq1%1lg`_czxcgp2y)uM+=Y)~m48i@j9aR7ga8;qu8BRp-h+sui;j=0<& z_l%D1^iTuAP;dcWX8J<3?VZ1NR*CJPAFd_vmsx2wW*>YyQLh(2xQgC-&L4M5>q{(y07K~HIrx=|DP>KVZ^)7jKth$at>yiUs%m# zKAq^54XF=a4v4X}0EHf>4-He}xA zcG*FK!%g)Ef&mY_#PSAdTiZL^A!H4I7Fnl;N;)X$#G$1BcbwUIk#T;D663si1MNzd zeJGGHWToAA%L+&%)xu zEbL^t7HKQ1YpY9$Z64{cM)wVua;+GWVEWilV22tN*MfH zsklcfJTDXV(@$e*GQz1+{}Bs@Gz_5Y(cyYMR}Y&lR?8FzSP_SF-Z>2tX6LD1pWo+# Z7g$Sv+Q#PAW&l~yMwS^qo(Vzxe*q*Q5heft literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/awake.gif b/local/htdocs/img/mood/punquinheads/blue/awake.gif new file mode 100755 index 0000000000000000000000000000000000000000..13891fabb3c5a1f2687d8a5496c242bef98866c3 GIT binary patch literal 1668 zcma*neNfVO9KdmY{V43_TAFhYXH8};xFE$}l4K8-k7z1RLS1RtDeA;bMR^cS6c9BO zAM#mC%|Os(!?czU2ns5wSxdL8t=wI;yVlfYYisS;&#OPyj%$7Y{@(ZQb??vT8$kB= zB*kG67=*?Kaev0LsD0ksd(UjP)Yn@WjCu%y7z~ERVnJ9tXv;gHe$)t`gA_maoo*li z-$DP0TV6zS1ZhWfdI)7OqO{{C1I|2ypP3r{_SPKU?kycWznnf1&6dR+`NLyA`ruNv zV``Kpgzvq1A<@D999TPQtR~xeDf+mN<5BBUIY|x)@BX}<=d=x-oRZbxk2(G0DZ*F# zbt#wmj02Q(iU6GkOXw+aC1=1QXDaNFrq=?MRn-S%r!rwi;c1`XY)PKq zVDUm3=?CAy6+3Z|OU51lF z-&_}dtWfY}rZ85F=EIiwT(C?AmO4j)Kw|}~p(%`)<5SIIchsHnu=5 zXyPEXhTDeSyUSJg5o*j}z#AuxSktt5YGzCi57w(74zCAMTM1%)L44c7g-#zf4L;Ox zw%)lAu8^ux)SNWbq5lMg9F10pXRP7R+^hVqh8lUpPOm;S%gQNi^xp`m- zP*5lq(fkwhiBhmG)8_bDM`o%dX}2V}Ek#1lkYij``&3z2wMvt4na~Rj4h?G|lztR7 zI5w`wO_=fK$&uL`H?40+&l?fJI;zw{`d(Ozy(9EL?;hagxSkk&gF&G+uf=St5(TA+ zmt6S?+5N|29C3zB?e*Ck zkkt*hW_Y{JsMPlUs@`*GCE}iYv)8hM&s33m*L&G)7_wWQWO<^H2x?+pKA4unWAKs3 z0I7f!A_YX^V#zTwvrrb>$WEwpP|uaiIFEM1kUeTd zr^D+FdaQABe8My`3>#i`i2wg#`nLfhM_g%^B{sfrUmHUpF@M`?mYqDcpPE7;n~3bCp)`cqH?xyqOWPnS3*PbKFt>#Dn#?(7Ew9ya!Z_ARs)jpg@0AY9&+(C~YHI8D(O%s!5o%ZE0 GdHn-SVb@sz literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/blah.gif b/local/htdocs/img/mood/punquinheads/blue/blah.gif new file mode 100755 index 0000000000000000000000000000000000000000..41b239e061827cd1ef4b974793966fa57e8cc8b9 GIT binary patch literal 960 zcmZ?wbhEHb)L_tH*v!H3^!)$#2Y#ic&73*&|CTKe&YbygY;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^p3 zwr9fyul&UOM|WSVn15QmF+YQOQj7WFfJ)=839QXq)Kj1JH9rvv-^)8k-qCF5ky`hp zMZf;Ytgd|%unTB<+t+GEKB08x2ImIG>YCcfO0(FKvg(BPynN=iqRA6&r}g{SO`kc- zea^J_`HqHG#w%8?TD_8e-Fo&F8#b@g*|J@C`_?sk_U_Xa1iLo?)xC4DxHsqZJ_EHg zTRxm~T_^sz>%GIgw<;V`#m+&2=>}${o)#mhD@&?O3;F@4o#|2aBLOcm@^+V-H}LMS(3k5_9%G z-&`ScXG!3S+zo#?)?9yBa{Ft|WS4g@dcLiknc%=+Fy%7$`wQ2lUhw~Btf;ICD>Gy3 zFl%dWNyugH>Fvv#km^%CxhZCv`-}-w=YT?Y>9XZ3ma(s1!@hLwhSfS7x9D!!v~uUJ V-B8CGp*nWZrv^0l4(`-o4FERspjH3? literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/blank.gif b/local/htdocs/img/mood/punquinheads/blue/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..1e943c9cd68b9afe842c3950fea29127400f8d90 GIT binary patch literal 347 zcmZ?wbhEHb)L_tHSj56`=FI<@GykWh%}h&6`~Uwx0}Lqs=k{|A33hf2a5d61U}gl0 zEB<8ROkrSQ&;h9dX=h-r@z{0epTQ~5)q5>opWXdGL8EVp%A6GeTIvt>9kAS1AiH{g z!h5}QFKy=eGxOYPlW;t+gIht@YuVYIonDC{k3Ri6m9{3P!Cdl2+-d(6kyihvozML~ zJG@VL>SsNxzlX1X*JjbwXl!k3?@(dx?qP21ozUGiaiZ#!Nu4ui%~s?DJ1BsVgHkf* zX{fAOQ?SlKhxs+fd5gDoPVbIe`@R3poz-?^j-WD!N^RrPr9aQOnqPVKrm7?>^^VUs zZVqGSINc~K-|(|ZTcqTs|G)4h`7&SJ=GN+pI(=PJ&2}EP>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)Rspt^Ss7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RYeOnmo8yaJ3+vECsdJBtKCQq5_Fnva8)2unR zTE=shF48qMF_U_vcb+8Cw2V)OlmqmdsG7@w4KHprS za%V~4irx)>MAlq?SaSPo&19E%FM7VMoSERj@WAB8{GwkEWPe35H zH8Xd2bSC720yu9u5d_$=Fm8+r(H~S07nz7F$wQn*d4^oki28*v_2f-!N;= qT=)4i;}?OPyn4;rb!*r+Zem}(dD}*v?Yne$?O4D6z`>!ID69dawW=-v literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/cold.gif b/local/htdocs/img/mood/punquinheads/blue/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..b5ac5fe3bf9dbd8d3f5aa33459b6b0777a368454 GIT binary patch literal 635 zcmZ?wbhEHb)L_tHIKsp5^!)$#2YzkY^5D#w|1)R)PfMG5=;Ob_TR&{qo-sBy{{J5+ zk_IFh$OVf3x&2&2f}I@$T#fV$m>GfQDE?&OWMJT7&;gkVas~tI3kBuAl+1YjKWEFStzw(DI+fe#-Z*mQ zNQAHHP>teG7S0p~4h9{NdXTXUENcZ$damAU@%rrU|8o_+7CH7Mc+3=@ zounajJU{nvcHR4$eDMPb2h$n(`c5!T=rB;5e@byZ!&C!um}8S#+nK913o{reb@)$W?CtB%=nkDT zb5?ETj7EhC3;kJEF6m#kV%6&MWh>YFh&VZJ-MMS`p1o4+2M)6DK6LcJ)?+7ko;<$q z-1!T81;IWDK=r{oLOyu^|Gw;&gHDbX1tLFlYf8W z^9ug5&HG2!rF^x}mmppcLG{8KLSDcT3HGbSelL>aWiAlX3H!(4@hP}gr2rTSyQ1WFWEZaedT;7_ z?|>T3N|5stliNDV^5sC0(CImev8<^X5(#xxEb|vE^k2LrcEYk1-YyO+Hm>s#a&p|V z0~85T?E4R}?>cy7|CXaCcAPl2_w2dzdmtV#LiGT_IKbrrU@GzjrXt6emTq;9tcNzP z5mn_(_m4VVdnmhj^;fIX6);qkku19ch>B> zDtDFz3l{|}U6wF$#ms_c`?ae!fRfQRP%7Fd#eVP*`<}zc4sJVsYS*a~`+;$=Z&)NF FYXD9o%bx%M literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/curious.gif b/local/htdocs/img/mood/punquinheads/blue/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..061be62538f6b16cb21186364a1f4af59ec490bc GIT binary patch literal 967 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEOP`-damAU@%rrU{|Op>DVg&!R;`=z za8t12c~+gB#}>T*r1jn*;e7~)RO_-wdg&>zvQ(Zjh%d2Q+_H4_uB(Cz7CMzxmhkOU z{#f{ywfV{$8R_T(x@5YWDRT*jH}cvR-HF4uc)r*6!W6-#`%T-~dzy&&A^4oY(sd z!p@X@l=`vY^^T3_b|)0HX>s&BPcBS%Fe^8^RCGZ&tTZsN@xU3@^~_FUTmD)#KMIsQ z$=7fH`kUd}r+f^I3_|P6S98WNHra$&H8CcZl$KZ8#MRUVH56Glwb{n~x|59mT%EQ0Fd*;rh>CTvf^MK3qo zJLS1+^xyr~4|(X$GOO+A69+dZKA!XPB2~#S(QdQtHQ=v#UDa z1V{-mh`jvfXybE&?Vn|AJ!4gM4ReL1Sx0GALQ!pgT-$_+p0!iLBc`R*I%?_9STtYP z(7<>FFo;*NuUpT)V#DTjI$O5uZr{3Q&)$7d_Zp$P7h96R?p_P$z|P4NCotdjuPW~1 zYFTpDT~=U?f=>C%-+f1pZV~_ExVrOMb{Ww0uCKp;f!!NuUe6d;SX5GG8C_ZJUz=}H oo1+*pA+xq!Rez@aOh>IbGv`my1UeW!N$5h71k}MpD@j-b0O0n)G`(4hUsRHjiCka0F?G$>ZMI6zPJ0d|0IKU(VRe1Y`~MEXPJtRy++B+6CrDV#Z)OP!FELwqU1=S|+p6Uz?>^sB zP+nWp@+5}BDTe-E$)G7UzW6~X&^8Fi`4tlxG>Sy`l{q~vC;|Has z_6JVCs0pphtO7bbw5_AING~g!abj@pM8?|Y7Ur(tB)8c!TB;hS_Zsvs@?%-GG;_J{ zs=_r1%QtLv=5ln{zI)H!eKza|53z4QeC*%>VA!8JvH$#qi-B7BRo5wgMtY8XbLt8s@Z&<45yxHxwEwd&VOj;VqvUWwzs(`g6 n>yuY)-s0}+>$q2i{lLM4wug=$vOIS3_=!^o_5mFZ3~_4!^%=;F literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/dirty.gif b/local/htdocs/img/mood/punquinheads/blue/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..ef4903f6b45aee8ebe98400837da4a42324b8b78 GIT binary patch literal 1206 zcmZ?wbhEHb)L_tHSj5V(`pC`BRY%g&W~Qa3853>5!!`?-b$J39ur8tEA@ zGXez_f3k3V^x3@^Z{EIp|AB`S?8^XDUtU7^^7Yx>|HT!B&U$F6 zPmj{}*!t?ki50sJq{^k~+Fj>sEYO(ogKOn9fde^AErRp&U#_w1-o2po^bsa~CiO(? zysC-oU1wOX+P2%?(@P*@-`hoL2de*EI-25F9m!fB6Vt4dRT@^_l%Cnz!#IT@bsEEz z$rA*;rp}s?Gjo1t#$3nJ1z`)8E?dr1($nrUCB4>Qz&!oLmf?3_2jiAY&O=b{d@YT)o%g_1WEKaTStFGW;H_^h((^ z@7?LGo5ZhI=!w?EzYx8b;34y&;n1Q>KURxQyO3D?RYht+_@gf&vRkIaYfep2Z9MCI zsO+-0$ceC=z_)g3yKE{%Rvo+lureaUtG1y&rIDF|ks(euyt|jVwL>a5KZS8tU;He_ z$tAgp`CUEEi4!MhE6u1bF43P+<;}8nbg7|nZr?d6h|M?a;l44A+X3`V+=I+XE2Xx*i#n$6bH5_!P0hsU-Hinn zH~yBeE(*%nqdNV9(%Y3L4r}eiOHZttv}rk0;!V{}90`K`HL?pX%f2$Ra`ARfO538d z<*<2DatP2H%sMK}Ep=+y&Wsb zT$zeTJ&?e}i$m@;kpjIidp^X9uYmmAqE^IGO^wQ|{-MIm-;9ky-Xv2&Lk``&%*JNF;j zyY29??Z=MnK7HowIjqi~0(U;~Q6Sm+E9T0oPgPn1TLPHEpIrUakrZm_wRG9;__8~; zd~4UX=*P}oKd-g2w5%|pp{cngsxi2-)2p{#&APY0abi|n?}X{Ww!ZEQ7A{)6M2>y= z3iib-*DPPKcEiFA>y~Z>Iv=Y;r@sBsWziIKN4a-5{jMb@g;Z7wpOs5~dTzk;Vu!u+I-MJSFXPjDAG4uP5 zKWEQW?60YEDrRYrO092dwM$j3EX;~%oiK6If)(z7n2*fuV1!KP5$Jz+P1$pZo@~Pn$^bf z1=cy{GhZ^ZWNO7XG?vR&mNa#AHWelHSlIMu^z_zM_D=^E8MbplsbHxT`-+w9i&w2( zF?Zd@g&Wr|1EzwdSY5gV?o#5zR@20#(@uP9X=)aybKdj`rlJQDRr@`{=B^LP`W+&$ z`r@ZeE6%a9F!-<}ROab~F?Kj-J2h2Rt2os)1QzEt#X9!}H)RCO>B~!>p3}R)(0a~F zUw0u}n>8CYZrZ#>ihcVI_DwtYY+tkYz=i|+wgL;lEm$2+Mp>tu*$_6}F1&H+6Rpk5 znGRa3@N+)6&}XotY@@H~EZL)cmt{82$WXJps8q$m$dIcO%Ft5I%+k=9)Z7-sIHj&o zEva>qQ|BzFKCKC*F1-~qdP@RUEK8iQa{kgaQR`M@Z1S_6?hY>NWI$!zK44k5`^4!z Lkh1QwAcHjkR_6{+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/embarrassed.gif b/local/htdocs/img/mood/punquinheads/blue/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..5dcc439d0c75177d0aa0d45667cf592c695f1dd9 GIT binary patch literal 960 zcmZ?wbhEHb)L_tHSj5h7=FI<@GykWh&3r!l@con}#>U2JX=(re|5yCa?dKX2?Ccoe zYNTht%*epNp!k!8GlhYjK?leNYSv(2U|vwM>&`!eQ=Y5$TD(5H`+tH)-x8HMD+09C zAM86|xvfBU_56hQdgorQKjio0Q)WX$)23xA$Lbm%2wkgT?Gbl0v1o}kkDB+R`VQZ@ zby^Q>3MLvqWK6Ux5PMQ`KzcFn1I|*%dS=Gzn!4f!)8@AJx(u_N)`)`EXzOWH+-s-j zO`c^xXIl6IOHCu~m8({-S;e+~1KY}tTh^;=-J!Z;+uFVR_N#J&9UXw`=!F=LPRX37 zp|WO8!8!*W=GPqOE#B5Sy*qC0=O6Y#G}ZB}KtRT$S?;q897@hD*yQj@X@O9$@!Ms; zwY#U@YqV-(UBSMwxXni42Kz;)zkCytcQID8RJb%TGuG8NmNi?nb#^soTjqB}7k9+j z&7AJlFspFdT&MXnqZZrfnrg1$0Xlkv>c%Y_6}Rr#wteUNwfpuTfVx@))z$MbT#YrT zZRYtivxxL;eZ28I_ns-9OSBF4aLhS>w% z42FgRJA_~O*D=?`#?=JPD*QT50w8(|mIM(#Ys!unaZlpA8`rK9pO%3hkD^{*r z$+mVK+w%3B)~amYrn+s*>fL+xLY-_xmXp^V^5giN+0dGz>-pv{lcQ=6C%1$?Q$|6= z=DbaNHhf-le}&!5%1;kRIgQhG9LX>A>IdwC&eYg<=|Mp=G!|Afv-B~vn3S*F#`WM-Ki zH@9s1#InVi%R1JTuAVcmL#tzB%Vq{fhR)@?_AFWwK6f7DvAt!-7#D5d!MuOng|j<0 zuitR_%GGTwH|89zkO%_!ujLRw@-f=o-=+~ zzJ9^MW{$!Zh>ruP>Eo!9IQQ%2C(a(oo1+)6&Y^Q&Uk= ztI^g!VN&0eI?cL?Ku>qin!K2qWnSEZ$-RB8%QIK4*|cm$_{OPAYu3+S$PD!M+R6J5 zZrQ-Hknz-^+Ea|ncJJADV9k+ZSqt`V-gWW#iOnbO-ne<|&ho8!r4L_sG^&)Bz5A5O d{`K3p&z#?Xe{cNr|L-5hHPgX9z6$iQH2~0g466VD literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/excited.gif b/local/htdocs/img/mood/punquinheads/blue/excited.gif new file mode 100755 index 0000000000000000000000000000000000000000..20848840fbadf1fff3cf4a7e61a5872c69d700dd GIT binary patch literal 970 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEb|0TdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMWLyG?K+x|L^3v2#5OV3*40N=o5hxt)h2Z1<+F4aO`BpnbCQ3< ztT}Vt=g*8^u#*E&ojeDNlXG70 zGYC6V^6{MWI{wdH?;Ym74dIX~b`Afsx^B&vpJ63aK%SE!CF3EsXUIjWM6)4tt`=oqw|>3uhRqu^w`||KZO6Jbd-v^!I#`6TgRzIP%c8&*8HqW2 zpKq>Exw9m2Mel|`B5STcEV=!)X0pq>7d_ur&P;G%cwlm4e$lT7vcIC38%oQW8yKr= zYQrkcnwh&hIumkPCQO`^Hzn1lZhCvnEcZE6W-b7Q@XA%I*Q{b+zkz+_#x3i0w(ii~ Tv288F!A7VK9!(TfP88Mv!yBwe literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/flirty.gif b/local/htdocs/img/mood/punquinheads/blue/flirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..e33eebf73282bc5e32a1e1945c6513ca7c7ab5d5 GIT binary patch literal 1117 zcmZ?wbhEHb)L_tH*v!dr=FI<@GykWh&3wJ)^7F?1_fwV}b!;;>Hcm@R`~Uwx0|rq1 z&+X?L671|4;A*62z|06#p!k!8GlhYZK?kH5WGn;APJ@%4t94ZqPw!sO7A6s&>8DsZ z?>5`I?2eTMy?teUuWH`^KcL|5pu^Q7s+4e&MPTBoWmhWya4x%%I<-7iZbSStv+Jxf z=PniBILTXa(bv@2ppElRT*2gZyVL*Iq*O4sM6@t_H=5Nkv-B}%v-kEhbeWbjPG*@9 zH;b8Z+Vq)yv(qx>EnGCSHMo62Y4?JPh)o+(W^C?Uzb$6Rrjk8jZvGxej~zd8(tzX4 zS&kFuE}l7h>FTkomrvcgedn$qHs9<4`X*KL<+ZcB&BGHbQg${jUO7v1X=ZjzW4QMH z7i;~$z59P)L4k*kRKG}Lk*0&%l!g@|3v`^8M`RgmoTyqH9UorxVcOEfyAlN%$+y#2 zSvZvWKfL5%rM6)5+2AVc+W6L{tUBhdxGv_vcJmfymMP4I?31T5OfaftoXIjRWdSqe zoVoL-EX>JUvV6t-?#SL{)f1Q1#qHRZHE(DC);&r4c2pgT@d@=iEz5E4{CW2amoGS9 zxqkK9jdN%2-n;(*;vo@gM$e|Rx$C$sW-PtGewy@$d9yRq9C(Dc?2Y(Zv~F|r=9=Vk zaP(A{XoI7t3KTt!W@RYRlbQ~To-WfF3)@};g>hI*Tb>D6eAvf29;OLPDMbB|y b^c=i&^(Z8IPC|TRG^~7smUV`9VzUMS$>{DC literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/full.gif b/local/htdocs/img/mood/punquinheads/blue/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..968495def231a1968e6a063222a3b72dc04b3d09 GIT binary patch literal 1049 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEb9bLdamAU@%rrU{|Op>DVg&!R;|+s z+f#5y%sKb|(O>s!{?6Jk@4|QPi)|j!?}8P+@HlDoZ+K!dpKYb?>aBrm{c_3=h}M~2 zUvVp@v~}_asfTa+ZnJ;!F0Nx{VQ{Kzu&u1hG-d2G4G8LF%t@%N?~XKWnjqa?-qKo? zKij-GSF(CR@$$J#RxI~eWTarIUo&U1diCl>#v9k`?v-LcaFBi9p`!8+=Aj23o=%&@F+H1(z&6rc9p}Ll^Y#480qelWP>teG7ETcc4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yg4oKC;>@wxp~!0p#M&qG?lXXHN2Om^Ejv`}~>liyRHDj90H&yKW8p#!c+2 zH*edhvwfHDt{v<5A2^8J$)iEcuxJ2+IOp{~gRnCtAI~|jxS74d(E9XYoUv&t>G#W_O8{_jUUT!dEnBy*U5zsp z&&QIAak)1z-N3BW^I}oL3Z~Wm^ClhG@@|8b)0f}}Msuw{uBgdbz4Tex2iYWk21W+a z+ecormnfvhFt%1Fv@$j{HpSFgCX`n;B=;5;vGkPAobE7ZYEbjs`3t-j%}H7ca`QS7 zU@G3EyLsDY&F#B(?A*O^{egpruqWd=G;#CSp6mQCKu&I{w)AabtZ!(Hscnzz?*X}Z z@|39#(`S@6&6;DYWjtr;B3)Ax!_}g|l48B?hRqu^w`||KZO6Jbd-v_f?%+Wm$kqTq CN|D|G literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/gloomy.gif b/local/htdocs/img/mood/punquinheads/blue/gloomy.gif new file mode 100755 index 0000000000000000000000000000000000000000..942da66c1934effb90e1a1c2ed05f4c694212027 GIT binary patch literal 971 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEOP};damAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7o6TIEFOv9Feg&}a0to?-MBaw_vm1bT|jJ0+3k=4$3Ke z89&>7?(|s;9SyCFSFK*Nb~XEkjqIy7ZQY==ZKv+e?d$gKKcFiJc5wizi|1i+an9>~ z24QDPKAv-4$N#zOy~Dh>AskZ0&Ow3c24+l1b}!rY$ZGL~6+vt|S} zPwh#X=e1zg+$AoiwuWm(fG*ysyJ_nt&22lk@7T3r-Tngyp-vV-b@FU1PR1U{E{g(N zWF+S7eZILu<<6486}=n&h^)E(u;ljFn#nHjUc52h(VnFyA;6Hau;jOb+^;C+hI0P~ z#_F2duuA8y_Kt*%wp4|>emj=wlWM2fPLG+HJ!S4ZV-7=uB`a30TCKyrZaw>w4V%}k c-Lge@`_?sk_U_Y!1hEmSdq)!mwG)Lk0Q)(po&W#< literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/groggy.gif b/local/htdocs/img/mood/punquinheads/blue/groggy.gif new file mode 100755 index 0000000000000000000000000000000000000000..b076eecf9580cdfba7a28e92bcb2fe6c53cd5e0c GIT binary patch literal 508 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEC&TndTLvlz20m1|3OJYaz>Hd)OpXU z_D(u|Xs*@mqOH+i8E)< zoxgBV-u}uZ@hdkxl5XC-c*pzN!$*&wNDG2|#TtO>s{=q^t=?;qU6OPE!PQz}$-HHn zE7gy!J1(*PruWSfo!gpk7pnHXpZ57{+j2pn&SbK#x!FDd) zj`NY9F7>#rZhzD0C^zr?dCTX{T+rFHxF>4y)@|E+cZCHlZrQnOcYpJtL$Pt9 gA;D)Z_*h-`y>#Vz-1S?R&)l}U_yFjuI6($$04v+y=l}o! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/grumpy.gif b/local/htdocs/img/mood/punquinheads/blue/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d4267e96a75f919f5f7244726e979724746811a5 GIT binary patch literal 1344 zcmbu;+fSNz7{KwDy)QxZVu@XoE?d@V+(v5CHF~j{ElYH>?YuB9_G)2E-53`n;#RR0 zImkhvFMjR8TzNit|vShPI3Ih(xPfXH^vBps*KqV5*Z?q=yJJob8};{7?9j##L|ijZ12U$4yL*lC;Y^GT+ny)bY5_os%%D0!w zw%?}ZXShl}TNLs;-F2jyhhOU`-(-FcFFunm{djfahn$ODWc%7jg=NJbJJ%l-eDBzO zGyQgTRwbRr81@-8=LLj)G)NY8)gzM&QQrC$@)0T{@Ht*0@l%(J|cwYyy9O_S`<~p2E+pNT5wmr?+XdcT44c z^*1A{hUyF8F`;lc5Q#=8Q7m-sr<11N!h>oj^bdG!CJ7E2SQYeh6Z*c?yY z)~ZaT7D!b{bj) z4*fgU)&_T&`My=LM`P2gm}n}NQ*)Pon=gdxsdeNAFq^HAR-hpv(wPd$2r8OHPt)FO zhYetFxvmd3k<5q}9<&=f@v3%|Q=oC8j04v85rLdK`_%QwGUIsuf&(ot^#8gzqg`$D zEU#?vC=BM#>)pM5UmnIEz#OC=Mg056F<;dG^qNsU&dn?M_niL&UP>Mu|JZlVz77_Q zP|gQq;2j!+#bejpLNl@aS`qtaVS~7ld6z5&vw3ZD1l@pBX_=6Mpk_7qvh*z)aX;8s z-h-So$%>%GBV(3sJQ8`TzH2Ie&6@H0RwfeJWSey^{K1Dj%LBiy&g#7#8=m!Tn98B; d6EKHP>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)Rspt^Sf7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RY1>F zZ`0kjW%ceod!f!XLUry?OA~Xj1TST2f*+U^zV=+_f1!{X!`M=7>D$6s-_RIS+aA~7 z(_2`?GI`2Whv_p)n`X_i)iR#5bdfGFJ**Z5rs4Iv8#Zsy+_HV^wjJx%?A^B?7{Jy5 Dt}m%I literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/hopeful.gif b/local/htdocs/img/mood/punquinheads/blue/hopeful.gif new file mode 100755 index 0000000000000000000000000000000000000000..281e8a93f914caf30dd9e213c2bd06595315934d GIT binary patch literal 994 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEQDVg&!R;^nT zwx{5tSF7Qj9|WB;~?D>{BN&Sg&RSZVCA+VACZhm5HC_oW?gKV<87 zyHjz~bvJwV#Gk!={5PjnZWl%MT@%T;Q>-Zqqc2`YXb5VNJ*y zAtC$sH-uJGW`>+PiztK6d6!M~)uTg}7S; z)!p;4xEp71SL8gJqPXm1`{uxf^O+WA@szQ%1Tp;V?UKZs3fCi$Gz$V$Irh x>vh;SZDwDwW&5U$J9g;q-nrqx!9&onHbQmt5KSW3oIO~Q$d*mOlnqQF)&Lr(uzmml literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/hot.gif b/local/htdocs/img/mood/punquinheads/blue/hot.gif new file mode 100755 index 0000000000000000000000000000000000000000..f4a6a9ec6163881ff52fa9a27aa9ad6221b39a69 GIT binary patch literal 1602 zcmd_n>rYb$7{~E*Jm)yd*`|TGX-1rY6Y(}FIAjYT3Oc7#qUg+IUb2ng7* z-P?UmuLsrx%_z{XvyL{*R#h3>+pS!#H7txf`P`u|3FuP-o}QjzVPRIQ75E?LY()_R|T4 z%Geg)x+%&K0l)foJ zA;Wm!nCt8BcJ4Z~GGu9H;X21&uVbl zM{0lUnEq_b@})w2&&1#PZKbDM*FF$y+)V_HA0Hph**6fS+&kp4cT0@{!8;6_VxG`z z6O98U-F8F@or>%ZL@qE%$Zu#m8OO{avyWy$I3AssN9DlTe2Rb!U-m{s*}0TbMj4AK z_mk!p(yJt8HZ-?fRS(_5OGTizfs~^KoA0!Unwa-HyZ)%`5G&xGn@=Be)P|>}CM;@T zC<=2YM89plaiKLj2fXS*za3j0ko?+VL#QS=$nHPXLv@5ry4dt9@qz(wIp6nl`Lv@m z7VvBd_nz}d2iGkj#~vsSp&u-C;EPpD+(XHwL|{tgCDB+euI_| zVt*!_u%pt_l8__Y5C)cje9cb8VV4rKy==V&X#!3X56%R5GT0>bztLdJ!-#^wc z@@y!`CGPzA)HeH>+1Y6qi`DWBbXpm_rja_opgysv`susYZ`Jq5eP0rpW9TVGwPi)} zPQ7mIEIw0Je7ZF-M9{)J!rbmuet7J#b}~*iIO<)#nSzcHK~-cuYHJO6yPfnWQ0OEA zZ7cBtle#^fgkxrrk!=``L+9jVcp@;F$IU0fd3Yg(FQF6*3Ro;zsr;IhT~1suUf6_2}v9PJvKuR1*SS3BALEFTOYzGdkgEKQ%o) ciJIrkFXn;yc{KcBK_lJHvC9s8PeXt654^zYQUCw| literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/hungry2.gif b/local/htdocs/img/mood/punquinheads/blue/hungry2.gif new file mode 100755 index 0000000000000000000000000000000000000000..70a23641e488a431e4b84161f219959dd09457a4 GIT binary patch literal 1263 zcmciB`%hDM6aetcMHIZ;a={VF#H>hNa8qDwSCIk(3~q={T}`$*67ki+mNCfK!hjKU z4+OM@J}BkYCkUk!xs*pK4_jX4wIWzrpkTEWDKKD%}64I!?U~0&U`*t8_x2yY24crLZVeHiyf($=e5)mcjc&_?%KiDnm+1 zBC4cHQC(3&g6o^44YyGlp{ZTg!fQi<6}skDNFCHOD22M%@PJxVHCi&JG8?<^n(L>z zCd37FX|mao`(kJST$Q$Wtb&fE<%jc6h95cpTDHuZ*EV((debr|MUCWu6zicscI?re z(u**f+TTu%HyzDdq?ei4+l#ghgUmT~#@s1S?R9vY}B*K-JP_ZYvU8 zr&YB;Z9zJ{1nR8qZ)=y0@L@v}I?*+0s+$rSa2)i34Vhyb`@t27TC)N^T6FZ=SBG9a zdp=`=HeRjAZkTSAwr67{-dWy$bX{(>PqkSVE9oon_er$0dHTCCiAOHF$9_JqXTKfp zCg0?V^YVM6^VU{%;scRLA|ce~R7>^&a?Z!SBogvZxLla|J$jdi^4CsA))({^A+!~>xIUhC-}a{%M-6% z?JL-Qp!km7Q`*lYhG)AcoskZ50_fZ1XFb8!ziP{C^Z&t!3Cd;>ZWCP7aT|p+L7hE9 zNR7j2TEw_Z!?>Yhc)a#r;oa9Rv-gpyYDfz%3Y%LOLEF6DGPl(Cz^1oPnigKJt=BAA zqv#9*u{#@e-5#d@)}=ZQ_CHS1iX<@wyW-+4=^ywHu=a*uQP>teG7ETcc4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRMNfX!3b1!>W^Al5^J-+QsjZ8wYKiXY?8?h$nJ{sZ?UboS_0wls zY3a{gG+)=yz<9;VRjXIAuUpT)V#DTjI$O5uZr{3Q&)$8yf?)S@p}Kbt7Wd}7-e(YY zrsU%}=XLy_yWTs@dmF+bRqPxTm~LQJ>Ups!VFlA_|9O)RYeOnmo8yaJ3+vECsdJBtKCQq5_Fnva8)2unR zTE=shF48qMF_U_w{-NCc4I2d~XyDSQ9k&&3Q_xa`u zl{-rUSM+Z9BeLfD!;;%yYbLwAd(rc4<;(;Jh6SysUN)D%$mad=+P{vmvZ^|)+>EWu ztfRFpA(y4Ee?s1*RG*ruEip6PXHA+u&(YAzcsVeDSFo>L$G&|1rnNeox9M)%vU>NP Ry-?>4we*1I-oc$7tN~fKrm+A3 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/indescribable.gif b/local/htdocs/img/mood/punquinheads/blue/indescribable.gif new file mode 100755 index 0000000000000000000000000000000000000000..db241c62e5575f09b386df55e10d8622b11a0fec GIT binary patch literal 809 zcmZ?wbhEHb)L_tHSj5V3=FI<@GykWh%``SPPD@Ms|NlP&7%2Yd_Hzvhc6JPKHPSO+ zW&{c<{$$}yVPIv@0Vx1!XJBrO*mdWh!70zxdo5m{-Tgm7qi>1IoD~6D>JRoEu-sN4 zyLx`Yd%bfnZRYti^W18aa7-}Ic*o??eaT{jqj_-JRjIWpy<4>lPd@21_A($>__?&|L8?O~ZPk)>-;%%MNyW`e=@4s_rwH=uwsLb($Eg(K2GgFOy z=gVWij-;&=%@bN~Yc+p=(XvXp<4mtgZ_7?U-&ydXwRZl&*U>d8l~s-P?WStFI-0$_ pKvzvvoiufl;+oi#`T%V;RLYA{5hH2{7XQT+e_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/indifferent.gif b/local/htdocs/img/mood/punquinheads/blue/indifferent.gif new file mode 100755 index 0000000000000000000000000000000000000000..5f1a0830ab92fe90fd3e3e62c71fe8e79471ead4 GIT binary patch literal 960 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBhpdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7ov%2<8Ko!vRwy(bx_=M7#8=M;$t7~c_E6rj{%BmCE^YU5RiY8CAo!0MPH+|+T z_c_zz=Q|o&8LwEmYV}I?b?ezzY}mX`XUlfo?OWIE*}G3y5bWLnRQJxo;@+Is`wYU) zlzcqrypI2K*L#O~Z$mhwik*W3(+$i@Juem|tYBL0KX1~3E$=p1IeiI!U^LhI#mhD@&?O3;F@4o#|2aBLOcm@^+V-H}LMS(3c5_9%G z-&~<`XG!3S-VJ|5)?9yBa{Ft|WS4g@dcLiknc%=+Fy%7)`wQ2lUhw~Btf;ICD>Gy3 zFl%dWNyugC>Fvv#km^%CxhZCv`-}-w=YT?Y>9XZ3ma(s1!@hLwhSfS7x9D!!v~uUJ S-B8CGp*nUnHBd7(SOWlGU8D>E literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/lazy.gif b/local/htdocs/img/mood/punquinheads/blue/lazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..dd0bdf05e6145c37ec349dac122c0c39ff8af49c GIT binary patch literal 1041 zcmZ?wbhEHb)L_tH*v!H3{=l!N=l^fn^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEUN`hdamAU@%rrU{|Op>DVg&!R;|l< zy>CP4nUcF=&gW8WwDJS+{G43OoCzP3)TcjvPI9MCp` zKW74lenXRES$PFRmt{J07ehw1L`6#vTg=q9Ni~(erL&Fd<~q!m4O~=GyHsxZsuc;L iW(uapr5Ww&YuD{iWoO^A1#9>lQSAQF^h0j?w*~+hlFx+z literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/loved.gif b/local/htdocs/img/mood/punquinheads/blue/loved.gif new file mode 100755 index 0000000000000000000000000000000000000000..2ed247c5e4ec15000145b93cdde6a493102b4813 GIT binary patch literal 1115 zcmZ?wbhEHb)L_tH*v!dr=FI<@GykWh&3wJ)^7F?1_fwV}b!;;>Hcm@R`~Uwx0|rq1 z&+X?L671|4;A*62z|06#p!k!8GlhYZK?kH5WGn;APJ@%4t94ZqPw!sO7A6s&>8DsZ z?>5`I?2eTMy?teUuWH`^KcL|5pu^Q7s+4e&MPTBoWmhWya4x%%I<-7iZbSStv+Jxf z=PniBILTXa(bv@2ppElRT*2gZyVL*Iq*O4sM6@t_H=5Nkv-B}%v-kEhbeWbjPG*@9 zH;b8Z+Vq)yv(qx>EnGCSHMo62Y4?JPh)o+(W^C?Uzb$6Rrjk8jZvGxej~zd8(tzX4 zS&kFuE}l7h>FTkomrvcgedn$qHs9<4`X*KL<+ZcB&BGHbQg${jUO7v1X=ZjzW4QMH z7i;~$z59P)L4k*kRKG}Lk*0&%l!g@|3v`^8M`RgmoTyqH9UorxVcOEfyAlN%$+y#2 zSvZvWKfL5%rM6)5+2AVc+W6L{tUBhdxGv_vcJmfymMP4I?31T5OfaftoXIjRWdSqe zoVoL-EX>JUvV6t-?#SL{)f1Q1#qHRZHE(DC);&r4c2pgT@d@=iEz5E4{CW2amoGS9 zxqkK9jdN%2-n;(*;vo^#=-Ey|^qfuGzEkgk!L&&yqw*Rm&8AOhH1OGwmVB|`XV<&4 z$4YA$n42S-nJXKznOS<6E7-ex8R`=m87H#z<;-B7R#iQ{XJ#^c%A6^k(_4bu=Gm1@ zi<`E>)@5_hW`Cz`n|IE4aC7xId;}OhrW~hEa~wN!{?y?MmycY&c;d#*Tel&8F+%mr LXi^(INzEDnpyTaW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/mellow.gif b/local/htdocs/img/mood/punquinheads/blue/mellow.gif new file mode 100755 index 0000000000000000000000000000000000000000..76e814287312bc31e55ca026f479e10bcb598d31 GIT binary patch literal 446 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMGbmX>C0Z2bTKe+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEDHrrdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq?YF9PZy$%id7c|SI#!-UC5-E`PPW@M*p7vJEu6o?%Gl7rc-{I98#l0R*~+$V+s-XIyY}kt-M#71;Ul_&U{?pAx_S{7 zSLeLmXApL#Z-aE{D8^R$~>>N~BkRjJ_PJMkyk6G!pbfXXjgUt`r6Mw&~ zTO9E^!NzF*(wDDiy(yIM&6y}Iz+kYExu&i-mnDv|qu$cLgE70ZDz2%!X!3-KaphKR zB?_@^P>teG7S0p~4h9{NdXTXUEOP};damAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj(AAn16bCQ+@{Xq!#nT0hPvG6PTN~sHZ;bYk49PzE^P0d?&M=M{3=Z z7XA7o6TIEFOv9Feg&}a0to?-MBaw_vm1bT|jJ0+3k=4$3Ke z89&>7?(|s;9SyCFSFK*Nb~XEkjqIy7ZQY==ZKv+e?d$gKKcFiJc5wizi|1i+an9>~ z24QDPKAv-4$N#zOy~Dh>AskZ0&Ow3c24+l1b}!rY$ZGL~6+vt|S} zPwh#X=e1zg+$AoiwuWm(fG*ysyJ_nt&22lk@7T3r-Tngyp-vV-b@FU1PR1U{E{g(N zWF+S7eZILu<<6486}=n&h^)E(u;ljFn#nHjUc52h(VnFyA;6Hau;jOb+^;C+hI0P~ z#_F2duuA8y_Kt*%wp4|>emj=wlWM2fPLG+HJ!S4ZV-7=uB`a30TCKyrZaw>w4V%}k z-Lge@`_?sk_U_Y!1Tk8oAl|)ZhXXo+iJ~n-|CEj#r>ACLm$HRDYfjP4&wYoEZ274< zujq6Cv(#bEcKC fp@A{Ty{ka(T>*5j&X(;^_d>%L&Ao#?Nmv5_YOJPb literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/naughty.gif b/local/htdocs/img/mood/punquinheads/blue/naughty.gif new file mode 100755 index 0000000000000000000000000000000000000000..274ec27470a08900a8753f52752ee85f4f239100 GIT binary patch literal 579 zcmZ?wbhEHb)L_tHIKsv7^!)$#2YzkY^5D#w|1)R)PfMG5!_cspnc3LbI4v#h|Ns9C zlmW&6+;k2}l+1Y1l^_3e7G;c{3l#ns<_FIy)LPTn{@$-cT-il=%TfSzSF3-6ajMH^= zl`j<>iORCu|FC(tROI&8e=}JfYdKmA+tQniSy?h#>nl5$S-K2+GAEQ}PU-Hgn4dAn zX!?Q$i>A$EU}UK5V_vmp@>GMKUdHWfXKiPkynMy_)pg|?HZ`-%Tbh1+^Wx(tD$bqh z-gN}Z@X_NZPoJr9zI?^`{Pnw+Pu_oe`su^-?>~P2(ozKbFaXtu zr%`=)z9jelr@}c_esXPdIW>+jHrp^?+TkOXeLP*W%G#{{)N7q8jf(xObAx7Gu4I4l z<-ls?0|4;e B_Kg4l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/nerdy.gif b/local/htdocs/img/mood/punquinheads/blue/nerdy.gif new file mode 100755 index 0000000000000000000000000000000000000000..4c2a87fa02c2d2a59c25b551867f1a4f2bb4ae2f GIT binary patch literal 1159 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 F1^`mUU|0YE literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/sore.gif b/local/htdocs/img/mood/punquinheads/blue/sore.gif new file mode 100755 index 0000000000000000000000000000000000000000..934f84dc4934b568846d1676308562971fa68f10 GIT binary patch literal 1358 zcmZ?wbhEHb)L_tHIKs{F^!)!VTOOP_^MB^d|7mG6kA#H$|NsB>lqoBel#Gpy)6&v_ zTm}k&;(u;G*N|Xm#{gF&Jp*P&pizoHSvXS|xEXXn#)6!|!20lkQeR5uyo^=ra$fJt zS2}ORqwcj%!YgTi#{z>N$*lY*RD=S36sKHJ-K;63#eE}3QBy~0o9CN=j!?hE_$3mK z8M`?Tep*;iR(n0Su}(kZ`14ZT@*I|$wyL@$GpE+}zS`LC-YU+%snrF(la1Tvbj)I| zp0~)TnwiCwW#OV}HOp77?(bV~ziQgj_AO@Hm>BjkO+T=AKhrLQRSWkq9GY_YH1o0J zCy%t9I=W)P#!W{r?!IuV?f#7r?%ewiFXTQ^eRluR1{{G8Q z{D9lTK;E(Ow~$uMi2zp)u&)D9ef#= zHQF#|b?+|2JxmNonC2cke3a>c!G`5W7*5POd6D_d+4HA*E}UMsZ2OMW*AHHM(DU@3 zS@F~7*NQ`4KYj5sguArl>rZ{hKMp_tGW`9@;SuoQKoi#&&6pD#9(D_Wy)A<3?R&`H zrcq?~_W@&?lWAtn%-OZmnXBivEv|w@cHcZEU~Erm-(bILtx?}rv+Ya_`)94$&#-L8 zHs*zg4_3`Qb>i6ZeFxglT{ymJ^Z5|&RVSvL*d3DlpzT5KZPmvQo?UyPlArhP)8{Y1 t$X2oX_2buH%dh{KZgKzMpMS8KLwFSjBiPGEs9qi+=^M@0BO!fT0{}#1V#fdg literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/stressed.gif b/local/htdocs/img/mood/punquinheads/blue/stressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..4ad750176fc9cc34de06375aa29735d690054ee1 GIT binary patch literal 2530 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 Z_F3;gwBP*ju_H&1@7)b_|9L?MYXGYxxtag~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/thirsty.gif b/local/htdocs/img/mood/punquinheads/blue/thirsty.gif new file mode 100755 index 0000000000000000000000000000000000000000..76dd7c0dc7d29211588164d84afdbbfc51977756 GIT binary patch literal 1012 zcmZ?wbhEHb)L_tHIKs>D^!)$#2YzkY^5D#w|1)R)PfMF=Y;63lYW2)B|4Y_ByZGY2 z@ys)6X=(re|7RczDE{a6a}5c0b_{Se(lcOY1RA3FlZDfWftNuCWFW{H46Nr8l>1UL z=Vh!~m-BjGfzJ7o-1`;l-tUS2bHK^}i?l?4^Zj)lIclxjn~JkqE-i6q7R{WR$lms0 zTa{|c(PXFZp$6&4-M+5jEkCvQ-LH>wi=`PD8A@vmSlL+E7`qBsT6EYau(#JY_GD{M zP|odW?o;Ppuux@oWm)g^`5a8l9Nen*y-S%ldg*en=31-1VdIt+n%vAxJJ)GAIv8zvYsOGmFeB_+4l3hD?fhz z`pv6|&5Nf<@?yxU&^B3#JvU!XE%;M+xaI9?2fg;*my*BV_7va#ve?$loPmj};$5w_cHPG1 znp=3c?NA5$Z^uE9?>NpLI(hmm$9d!Sc-N?{Tfb?A=2qVAJ3;>2dB|Di@Qzc; zXU;fZIH$zT$;rWSQHAI3J)Yy&uixgq|LiU(?w-H3ef#3dr_W!mK%y=MHFX{s5`Md^ f!E@s#&+*ghx9;BndFsJ4+h-52yngc*=qYOegSw|T literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/thoughtful.gif b/local/htdocs/img/mood/punquinheads/blue/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..9491f9238198b194cb3e1adab48f1020f9f0dec0 GIT binary patch literal 1201 zcmZ?wbhEHb)L_tH*v!fB^!)$#2YzkY^5D#w|1)R)PfMGbmX>C0Z2TV#7%+h1e{Mh5 zkYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=&KjKbd~IWqox6KEyHcM@WsOEgQc~Ko z%m}3->v;xImrZX!+con8+m|;P%Y@ctSn_3_IiEJGGiv>crn2Z4IvZ~_R@huvweO5U zW$Zhz3rCr%^~#!0wpZ5WY(I5WGP|)ffhD=QT_TyKwy>?eDy1i!wZEiza^1A)*)s#D zCNVHFbXG1}!aOgNrHyf2L&`eFm8(`WFE8G)b@lA&YkKFe**j@}gh}^Ev&VLM$tcagpRqwByy5ogqF+A~p3nZQQJSif-%?S+lGfIxoW{}+ z)7e#<-fze{sl04jR_qSdv*Y=bQrD0QjJ~GqjwF^UVDuF?GlSx36H*;;OG+uM&F&MFCIao TF9PC2BbxhgG=b76fm#Cq!~Q?u literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/tired.gif b/local/htdocs/img/mood/punquinheads/blue/tired.gif new file mode 100755 index 0000000000000000000000000000000000000000..88b6c78ce9b7548506de329c732af133573aa97c GIT binary patch literal 958 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YwkF8*kb2;LMr-GiUx!OPiUNmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEVBeodamAU@%rrU{|Op>DVg&!R;^o; zwr9gdFa5;(M|NMUn15QmIX{DWQj5!?z!nvbIeVXPuF$!&Byh#r4SyuoTz^<{`)kc) zmv=9EzO9^@;J}a|d?UBW>Y?nfDCUOJa+U_h>YCcHO6Ts5&V*dnzWxb$lTv-^rnbk- zaGy14`aDNNE92!WR<2sXzIGk^^7Wh6>TKSoyKT$r-Fx=x3WA**fa=`YSe%>ldY?hs znJpjBxvUfZ-1XjJ-rE!osbc4#j}<;$(^wouG^Q#|WsRL`byjqaymMIgma2nthM#}P zuDpKmTQLs@Ls3)Bx;pg}&PkDs%@tKF&5U*R4Usi&ece6D1*{V%O)i|8;omr;D}J`u z+^Mq`x|rG;t`Y${cb)F~P3tu`Z`-nU``Xoe_U?naR|M6)gFSeShL&@OQfjaU0Kzz> AQvd(} literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/working.gif b/local/htdocs/img/mood/punquinheads/blue/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..1e56c11c9113324a9fc5aecf40965a2b2af82c12 GIT binary patch literal 1768 zcmc(fU1(Eh7{^a%^Pcx0yD(`%>qpn6ZH|(Y9+vK;LlF0&!)!>vU1%a0nG^+g(Nl2| zwlWYJ7&4h1joob5q)D5!woR6_r#bm<(&p>5`Ebces?%24#hA_;cQM(>PP!{uE(XH- zUc9^)4=?=q|DWIc$BuTrbrwf(#El_8XDUy_&pn=Xj;jm}Rl2)}luBi#B0Rc<8~N91 zscb)fz|LWX@k@IZh zMV-CzAonc1NKfB=dg^ib)b(fEfze{=G1fQ24_-6>a^>i!cfS5zn{GENubz}qS-<(o z=!g3<+2gMmUhNER^!)bS^DAPc4mtb6nt7)Dsd_KD70`=HaM?$FKbfvA_Ao1m$-1=bf7!3mQzvgm~bCrhRCnO0YkFFEmY z(Q*I5`bP7PO{9hwkpf$S1jq&jf!!KzvW)GtjgC9i#%4I{yp8Fm_d;~R>v0Q2jF%0F zpxY!3M;0KFmL*fU)mCSr$j{=X!uU@DQf;E}RuIv^M2Z!1FtXb+w#$YQ;|`PB*aBT} z#;u=ihA4~bM1Go*d3_;G&_CQ7jU_}b7A|skxLoRoQhBY|ez!EWzVYx;Q_Yw{TL47^ zp?Y#akh_3ow^eMmVGi}M6iz$!Gc8cyVQA{WJgf0Ca=1T;E{b3(6_2$q$8-7o>TH@X zl?!ca{G`ylhqZ(9|Nl&KAgq%NC`@F-CKF+^o7BVab&8LGggv}6FipS{c}nB0%6l0PqJ;DtB;`j(gc zqX$DzbFZL>PpWn>Xuvn;`;FS(8wPN*T|oc|K{i-1^@z5!LpOQm9lL?T;rx8B$F7n= zG!!OKNCw04cx*1jtT0?4kx!(gt9)sGuDoWe>H)9WyDiZJ=r_5UX!iksMn6ZJM(7Q4kW0N6rKoAt8vymX>1?JQ@zJ ZBxLD$ekmzk;Y)0`yk@P2^!g6u;NPGr`-%Vn literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/blue/worried.gif b/local/htdocs/img/mood/punquinheads/blue/worried.gif new file mode 100755 index 0000000000000000000000000000000000000000..a018a5a24a2d7513077aac6e725d7b355373a26b GIT binary patch literal 987 zcmZ?wbhEHb)L_tH*v!H3^!)$#2YzkY^5D#w|1)R)PfMF=Y;2sCmiGVue+Fzo@jthp zYe=xOV}PrXo&hr>P>teG7S0p~4h9{NdXTXUEDHrrdamAU@%rrU{|Op>DVg&!R;^nT zwx{5t*ZYL~hj;H|dndgsIPt>gzeURuH&&=9c{@S#>BGnx~kmzM%9))JC@$U89Ajh zngUwpn9X+7)Sta#sg9w6@w)XJHf~_wvXy<^ww+sacJ0;OyL;22!$))l!LANKb@d`F zuFiSA&minf$;Wff>-axgN$*~;uw09$!BO#iii^_JQ;pflN0t_yznQQ7&(iCFj7(43&I~h|ds~T$ynp#xb3msV| zl+4brnB5xOKHqYli>C3s)hl#NO$;}R0$sgTciYZwn!EPy-m`DZro%^$LY*yw>g>5# zoQ*56FIG&M*tYGSk=GteSJp$mRWU;A7U<;dI$Gb8FNZXqiTG5ySnqU%~&Q(oa8ojT14ZF&iH!Ixw94+a~K*dTeW)4S{?Qc z8`+m_+PY!=wr#pQx3Al`|9~bWpwW`YeEcrHRx$td@}{#7b_*7(Jv>nGMz;UJ#0e)$ z!lrv@CRUi1vA1Zf*dQx5d)tO>C;YnYpBP_VE_Rf?fq^0W%=?4+aw*Y_tu^MYj0vS> z(RHr)1DKW?!>q`zD79M6YuI literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/angelic.gif b/local/htdocs/img/mood/punquinheads/pink/angelic.gif new file mode 100755 index 0000000000000000000000000000000000000000..5c97a6545e462a994a11c248de422889aa378308 GIT binary patch literal 2080 zcmZ?wbhEHb)L_tH*v!lD>D2r82Yx+0|Nrau4`)`~nUp{2)wR$6|EC!n8=pC2JagvE zw6wG{XU_cp|DOR26#sMkxrPKgI|jHK=@~FH0tFR+vTzzP@G|It6o8CnV0pITr043r z7O&6l{-2-`*=f(;HjVl85e5>J{4Oyo^1er5BG z>&lx;uL3JXg>-}`sv572-*EJFhVg+U<|Mnhv*+@*{$6|T_4iy>mgExOG9MP!hTJ%z zs`{L!wp8EFnx1@-33-#EqNdH5DVj5<{I$f zr6>s(WICNON&>8ymy?$oUN3 z(`L5_&1xxWV_;s#ki)TdJ=@Y%Gk6OM%2_ruZ;0Q=z*4&_U8ejHTlKtk`)dvNELu4K zNQ%;)$&p7cgx?IlH{zL1qAy&|Y8kcG9S zFiEJcxuC5pGpM&=Lb1q{qG@q)v*yedEm+Xb#;_)K4MV_^361&5)4-8l&9P(GhTdEc z7GR{G*pq(zrX1-_MfV z-@bo$`|(+&*x<1@-<=Ef17mU z+Ga6|NejH!l-ZZ7aqZ3KzkT8296rTGh2AWzwOMgOk~OPZCTZpCSMQq_n~c#2M@EfY1Z%Dn$J;ihT-I? z6DwCNI}xM2f63gNjxHzew%)uIe&8X7*qYwIwZVdq9Ose4k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/angry.gif b/local/htdocs/img/mood/punquinheads/pink/angry.gif new file mode 100755 index 0000000000000000000000000000000000000000..e3d35b3749327de3aab4c4cff3c068857a0baec9 GIT binary patch literal 1148 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEIr=_JC8yo-s|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7f%$mFt~>t>PI<15RC`>!b6r4rZ`?Ia^%EVc zrxI7bI`T}t{e$PO^7sD_EZ9&eDbe42eS)EZz`TGa#ho@1^Uq~mvygGwpYZBD_u0C$ zEQS3#XXo7Y-`=9E9Pp=@2X$1sd-QQ{+Lj={U?rwa(lR+ zK7ZljrOQUF*RHc(x^es3`8)S7+`oI}$~`q}wZV%C1m8_A48H{9^Xso@ml|$2iAH@361 za#NpHKGSr@DW>xnn3`MWPMSY;(b8pe+l!*6wJ(`fv7|m``_`5@ zJ4(0gPT#w|>|lg@c;KniXU?9pXT5ld_1xua7f)Zmb>`NM^YU!c_3 z*}SBvAV!7rf`(#djo13%Wd#hT35)M#PT>C6wlGS5X2Py*7xyvE|(i6;)cmNSg-q+tlf8lN5@WW;4z(UBtlD-m!4n;+e}2`K*O_Hzvhc6JPKHPSO+W&}zp{$$}4Vc=%a0Vx9+%fNEA;H2m3y%w*}?*5;k z(U+1rPi4_Mj;fWOI_j&m4;K4vS6}qsFpkSZq^rj0sK2IhlR*2DCe5XCbL28i&9^35 z-+EG1CfmyWLVlNkw*2DPUv$ouwJ&HtlyH9Ddv;d#vhvFM951h`n&uYvdc#;wuKK2U z`HDa*ucn@~88K6*&6_ia%T(KpTW7^8-<9U;5*KOC)U7aCzp81+D$|{NIoS3~upM20 z^u)D9Kg zcRyVCY@va~h18l_R`!a@>e{-PfX2Gkww^q$Nt_e<`s+h;r@2@8#e}t(nrXGLb1l_2 z6VcH&N>}qR;Z9nwx@B|Ard2!qY*y|z*J3*$$#(1r_pwu_PphA1xNz~(#WRX*ml$u} zx_#^NVY%zKnI1oR`s5D7ed&i!S>C<>@ctR&%M(DK{``gAuUClnD`m0T#oQ6h+1D5^ zACMhll--k7F_W_?eCk}Tg*uBhm;0It13j9!A}w%z#ricHnzn22SgXahSCZ}UL6O79 zPn=Lc!EpB6`Ew@~+0HXwyME*Pg#&U|ZZJJ~_~_wHhC9;t9|wns&6hiIz2*X7`ZW{Y zVWYiEM4N5D6x-3m5=T#-I;DP!;rxY*7fvg(U1Yp*^VZEvhvcr^VtVxW$>ZA$_oN>@ zVR`%R{kx}(FOGwf?@wv0>GuYmyoxuavFO2Z@71L#Y;Cf$vTRkh6* z%-Jf$w)dbI+wr5vj-NhrM*R%K#Y>kjomFJJ%y{eeo!eK~<#hv$s1PJ+_!Z|t5WK3=JkSy{Q7fY~)TYX&g88nbhSr)&CZw=7y}YouceOvDKu zCL7GdHs`Na)!yE+TaRt;HZfpkJ%%k_+2j%NDuamEBj9*d#2T-}mrE4p)do-s<^pHd zELJXHW(6i;u4(g{!nKxjnTcronwzdR&(-xX*~o3zv}N=59UFGe-Oi@HSCsAe>f_kT SB{q3Pxg>)qmyW{9C2Ig`g#)hu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/awake.gif b/local/htdocs/img/mood/punquinheads/pink/awake.gif new file mode 100755 index 0000000000000000000000000000000000000000..05e5cd4e464413c7b2bbeb910b6924cbe93d8858 GIT binary patch literal 1651 zcma)+eNfVO9LK->5X@|5X`NhGlM@p9X(?Lb!_22L6O9TV^C2^xrTK`=e8$93Bu%CS zVp$rIF!6a#5flx4e#l+6u9mfKJ(^Z)v$~sO*Y38JxAouWpU)q!d%fRpZ=c;{$0!0I zfJ^$|MD006LW^bANq zA6V&b-7^6IWNSv(?cZ&NeWX3)r(@kqhY4ru?M08MTP*J>2OK++H%jjwp5HqDSg!V8 ze0eOtu%JbZ(^yHaxfzG4h1;0hZn@nT&tNGdTNqa-kms}((kYF@YYzHmcyPhS+0=ax zjlz;L5iH=h7qAf7iN{H%c_l?`6t5IIgE`304z3Ya3$mQE1SyvU34)6oEM?neMHEwVOKQh!iIdvUxupCFrha91vZz@mO8z(%eU1;r?GM}Uj zJ^!ZrCRs51^Yn`|dOY=R8gaE+y0QsV7- zLKrKNH(5B^1ax$D>o|vS-PSUREYg zS4@!Say_4Go&EO(F06}jA1kNE-4}WbS?y*k*y9-5<`oAvjMN0gi_+IcEd*qmE#*G^ z)rqJonaR&i@Et@RNeN^aMW*KHF!rMW8#LKh>o&lR3jIElA}X;(|aqaO^iGbzjn8X3YFjYMvNW&sDcI7 zq9=0h#bXY5PyjznLh$_Nn)^ zQLGY8+(`{>4?E>@9M!(K7Q_Wb&3Pa@V?yfK?;t3nH#2X-WI&&u7Mu=2If%?G6dM$= zD64|}U4yv06S(=zB3q-QF-3{aiDeb3(M7?|4dGrq>A|wbolOn2Hb2W$PAxof71?OszSi3sFd1OHgNwwiS-WdX zB=J6zxuT8OEXl@bYE9wljE)XR6eEgG zmjS4h3-R>6$BAR=68O6Vh9$sn0SXpxdxYnIrRU20v;VL~8T_dw? zly8Kko!d8CUnMH_mkHHhE{^^?RLvi`_$LRfB`wINpQm~wL$-Co*G&iN_8O<*4OmBL z8D=(>tKn%PoRR+HD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B@rM-Kbm3bPYZu7P*#CopsiLyFu-4PNp}D0x!z`;QBCjdhddejCs;M~> zXV}l05X|pgjPf*w@;59j_p)Y4`w0lMHdQM8 zyTtq~F1*6AqDxkNs_9fCr5RIaH!5gqXfIv1e8qCM)oa+6 iuHCR&W#bmrEt^*E+_f9(U?Wrq4~2Ar=Hx-2F027sgrye% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/blank.gif b/local/htdocs/img/mood/punquinheads/pink/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..2587a813948bfaffcc70eb38d187cfad2a76eefd GIT binary patch literal 782 zcmZ?wbhEHb)L_tHSj56`X2qRJ`IBB<`<#}R_W%EX1{hHM&+X?L671|4;A*62z|05~ zSNzGsnZm%rpaW6^($2tKY~ zc6gug)X#cWe-B^(uFayU(b(G7-l4+W-NW42JE6O4;zZRclR9V4nyttQc2EEz2c=}r z(-2vcQ?SlShx;|hd5gDoj_;0J`@R3poz-?^j-W7uN^Qf^r9aQOnqPVKrm7?>^^VUs zZ4P6`INc~K-|(|ZTcqTs|G)4h`7&SJ=GN+pI(=PJ&2}ED2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^IRMqo3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_w9!|T7;0Ju?DowJbz{t zk)ExOH+~o1GsSa>x4|BsIp^;dMQx2~wt4l;n_)(I8bkRT7M6PrO)>AwYHDZ$1A5JBw)Gp> kR&Ly~US;bJ)g9Z`A{=dm>S!9Ijs+`QV5#Hf2u&T<0E4Wk?EnA( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/cold.gif b/local/htdocs/img/mood/punquinheads/pink/cold.gif new file mode 100755 index 0000000000000000000000000000000000000000..f0e79583d52cab56355aa1d5284b26932238f271 GIT binary patch literal 591 zcmZ?wbhEHb)L_tH*v!rF>D2o}AOC&b{-N;Jk4gEH&aAj&yY|ehYoCpcjsO4upO%&e zBpHx^;(u;G*N|Xm#{gF&Jp*P&pp@cI7ET5RZU!BYGLW$hEUyYqdamAU@%rrU{|Op> zDVg&!c1h-}j>=Iw|1O({dEtAOycOnm6FqERu-Q-9aKc1rlB!d&mCB4IE=NMVw@li= z-ZDe;nbiK)H#;KK#P%pUS?$){=U%kxpWZ2Xh6d-{`bPGe!b}FHZiY0DuAa66g(B7o zOudoQ8CcsD*`{^R@R^+-FrRr^>yn1K9x7~%D~p5YvNAI+SJ=q8d5iNl3(lPz7>z8p zojhc8BwnjqCe& qp-);r{{GeH{=<2Oy+FaSfkRj;rbCGdD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq6s4t~>t>PI<20yES7e_x*@t72J|e4<;^4 zf4wOA&$*Jfd=+*#`27AjF!hyxVC_F7o7<4{Z_4(Bg_f*N{%7K!@2I`Uav(2)StLfE zxnPEr$@WXWNMGJ&}9AVx773d;Z?F>=1?Tn2Tig`?J9bGJw zdztztOzLTLo6az6_M{r0hMCP06Y~RSE-G2=z0SkjcHQLA)V?>Wz)~y@5S0%$JK)CH>=K$q`sBdXL57UEm+#0AO6~xT!iL zI&3?eApj?&<5Ob)3X7by{DAN6nOa ziQX*VDRT>!xvzA#u~@ljy$hF>=gofgKhVrqX)JgJGt}Z@qNI!*bDK65jA`P zOi{c}{yt96cd*78G9O&8eU*hZ-aEp}c2RWp^3T1Z!VEt?it+!r=$sAmMQAe67xf8D vKwq?#cQEv3X7x>W@9*qx=&kXsnQENaThu$ZU}>4d3ZO4m5a)|wkff{u3LnvW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/curious.gif b/local/htdocs/img/mood/punquinheads/pink/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..42878a0dcc300ab4b9d9896f87999b8fed37a09b GIT binary patch literal 951 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeLjhkPA^!; zylMuk;`vuA&RN9OJHLB9@1D*x!jc2=NwHs z!qV_-Iop)Ofes1pj-7lN|JhZ02m2kLItHeMf+p|arq+VmY`ff+s>qgT`ze#8w5C{2 zpW#_EW#T*=9c#ViD^{*r&bD?P+nV*8HYji2rm=19>fL+x>T!ad96-p)DVg&$OxC<9 z5HnCbU0}Gbc;5O43;tX8=Z7(frR$xW5OCQv)$^=_L(kKBERG_^d!>qR`HFj-%hOM8 zkXpfZ;!u#5f`yGCUaf{Xt{dt$&c<) z&$+E`amVJ}+r0{oM;V2ZpMebN@`VMji+8i zZbemwO;(eAWnkjuX8(Xn^J&xFXHIUKE3c`cy$tB&6~IttTefcF8kJ33RkvD2qL+drIHac5Hgq*vEI&zw0kEiLWLnKQ=5#{d8SXTSi8 z|GE8KLxPQ%!hNhxgnK-6a#_9;m9tNi3l8M<98hfXd zbXRy)P3}maT$;6Hk-Xs&&*du=S1nnqD`af6dHar?yLPhe-N&|l|DnA)hmYwVJF@%q znX|frVCM&*I)615=jXiMx1m+VIhX(B89t7O|5;f4LO*|PI4+gNkYm-Z^6dSMB|;07 zG6fRv25nr>m~d+Cv|6SO?mZ=JjV}dn`>G$=oXnK){vPv%EZH0e#@2d=mbS7+nIxu8 z#`+lB2@Fi-6;t!4v`(B+(O=_NH@zo&dS%{WQK_v!9G zv|sb^u_H&1@7;ao>^Z3WMNr+p5{vus1i#jN>t!cyt`=I$qM4y^<7r#m8i&^pyZQFNnkItc^xXkwC<+_VA`{GQ770Rz0V&=SNW%*ZWUDr^MDi_Pt%vhP!#lTcu(-%6WZ(>bn znPbI-HieE{j|tO*7dR}o)iPeZW~HvFiQy(uptHB>Zr`0hNh z(UTtkJn<>ywtU?k=lA@(ZaQ64mgsMZd$O%rWa0&t4~M#=dM{s3Z7_-0dpyVZglXA= z^qg)Ti)DA`ELJ!zqsNx}UEFf{z0cucwPMN@ZVVl1g)AKmZp|%RZ48W484_67rc7g* zAmqZtG@EgH-eQJ@CEk1$%LA6rD^0Fn)EU^jGJ7>|#lpsg8$}db_crveOp-ow;EY$4 z0gt_%v-&2j&1Khb?3OTB5V+>8cT0lx*>lz>{4d@-d&T|sp-epny%gTzQzKJ89(?|PMdHbN2o<` ze*VifcHO%dl%77qq|dxO(K@ec;(FH^maDeyw)f0Z$k_LG(Xs>8e=Z$O@vDwxuaAjo z*2yYmVd%@L?Codi>}oA#V4TH}%EC5t_LTHM-V&w-jC0CXFfdJZHz-*Xx@Ky|5}sv! z4AHySrPpp;*AspCK<4(=Wk-CDEw(8>eYm~RJAzl_i_3|x*m&u9Zg12e29oJoSP*6VkEJa(#V$s5U zXcTWZ^_>y?zA`qj4jjjw$ub>Xwecc~?Vu>m1jcZ`C@_L&0V8-J!+cN#FAZ4Q66M5G zv7m2l=kn~8yqg=Fca&MR?FpD)JVEWy(NkUyGE$q9rh_2&A-DvMOy;^bQ?Bt literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/dizzy.gif b/local/htdocs/img/mood/punquinheads/pink/dizzy.gif new file mode 100755 index 0000000000000000000000000000000000000000..8bd09e8251c3ce25b80870f59ebf1880f980eb2f GIT binary patch literal 1761 zcmbW1Sx{4F7>3UY;fz+H&}y+%n85+76tF@UwnQXCG%N*Cu`WP@Vu&oV#RQ1vB%C2E zF^gcxXpk+0lMo1Dmo0=vAf%vx%hVQZosPIrOLbb*)`ni>Di`X1{mnnm^M3Dq#C@T@ ze&lVyHlTG4usremi_T}04fn+9;zzgs^zrdYN=kb3{{t*NmpAJoLk`3cc1MMHdwppI znr2*9uxmd6)&L%>^Q+$i*j~HweX2g+$HpG7IL5|0YUBb+I&rOX$oc~#=H}ljn@iK=tQW4IRK@=C{D50qS^V~c32v~FFi4*vtRFj+68#jPbS;pv zK{+~qpGg3?1Tq&$hC|PvfB{elc)AKiSQduwn3|3$2gMh!0@7WnF6p&#NwwLDl?7pi za&K8~n6#OWMlg`l8G-S9jJ2f_UXZ+4B<4-@&FW6fWYB39W z#&wy5;uey{sAI>{kIAe8t;%ZrW9)x zaKc?TEjGbkkndJCwCrwy@qk!^o^S{79GmW4sXASPm!0$W|hmij%(VYz}N?K%RI_K zKa#w@C!T%}XRB6ob{v;AS0c2=E@6i%6v~{UjW*b$4OKthhlfTg7gs_)Za-o3 z>PgduzEJ;{+q?1xa>+FJ)HLk50#+I;!-Wlpuy{L?ibbXT0)aSD>W$|HnLy?B&Je1E zw82dJ_StUt*i(de zD9<@bvnHg)3ct3|k=+D)56PMj&|ZCIXSEdG*6X2c1wa@G!6f9Rd04YK;k$#8e3mP= z1ms3#r6Iv*C1JuCgj!J*dFpbCP!yx6Q4%-c0yS-`eRYI-dZCU!U5{pPxNTV9Z90XP zJKXy2@SfkZ4@vO1+42YOtqNEd;QFEU!gOR%7riASN8~hOJ9DLO6JVFS!U_+jZpp=f zpy})ZrkpVa2&J&NgwKORGPY6#$0`I|1|o`LpAsJtWk)sEk;~Lv(UnMTBUR&z3nZG( eo_=TxGCZ}{$#^KqyTet0jfd2r4+YoaA literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/embarrassed.gif b/local/htdocs/img/mood/punquinheads/pink/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..ea6a79a47c859a5e3046a369c4816ebb7db56d22 GIT binary patch literal 960 zcmZ?wbhEHb)L_tHSj5ioeD>k{DND|*xHBn#(yMEqjg5`d($fC_|F8I;+s`#5*x50_ z)kx2PnUR5kLGdRGX9@#5gAR}l)U3h4z`USh*PVX`r#x5hwRnAY_x}Wqz9lAeUIb{V zKiqf3a$AAy>iY@r_0GLqf5`90r_6?yrcKLKj@30i5V}^w*)!eI#G)nEJZj#L>N`y5 z)@eQDDVS)S=#aoyAoir>ko02F2h638^$bkaHFd=erp;~bbs1(ktq}#S(bm(ZxYth4 zn>@>Y&b06amYPP|D_5;vvx;r~2DX(Ox2#v$x(F-vgosv0E z!(`2yf^{xB!ml~bTfD7ves|p3&p+&gXsYAc2>}_8X1UJ_a40#qz{v5F(E_1fc%Y_6}Rr#wteUNwfpuTfVx@))z$MbT#YrT zZRYtitBCY$eZ29z@SZ82OS}#C@XR@Xw% zEQWy!JJ?_N*D=(@#?=JPD*QT50w8(|mIM(#Ys!unaZlpA8`rK9pO%3hkD^{*r z$+mVK+w%3B)~amYrn+s*>fL+xLY-_xmXp^V^5giN+0dGz>-pv{i=%1}r?7-Rb4EeL z=DbaNHhf>fI%Bby@d49w4UCNz3p^W6bLRSlCGej~tYu)Ttg0!jGi_{Xtw}e_Y7Wn9 hjD2qL+drIHac5HgB-gK%udaPgOG`60Hva$rKLa+P_@CR) zH6+;CF~HSG&w!Z`s7CQ83ug)g2ZIhsJ;+!FmU{vxJ+*BuUgzvy&#u__q@qS6BS}rL zD}C0!#J5=+bZ$$&d1fWDb_*k$_4?>bX*N-lR2K#BSb1#OjWy{9-ttYj#kt)|A3kK99jE`{W=2Y` zL|J`9Q(a4*WL_iC*VSFklUbSi{3bNl)|F0=oHb|Bv>EOT8CFbcS;3GqzkebF<7S37 z_RWlI*9T8v+O(x@|4yded-m;En|Fxe=&^k(Yu6lEdT!#PBWD-vy_S2UqA>Nwqx*$L l=}(@%bZ2|>_U$W-RSw{s6rkrNqEs4FEoN1^)m5 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/excited.gif b/local/htdocs/img/mood/punquinheads/pink/excited.gif new file mode 100755 index 0000000000000000000000000000000000000000..caaf6e4ce52c799595ec5436ed516a4ee8fff79d GIT binary patch literal 993 zcmZ?wbhEHb)L_tH_{7fe>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^9~_sle>(#)Kc)FK4~JyV6GN`=U>)MABz%=FUK5(dSeESxC}>b(}P&+h)8pwYL)WX_8KE%k@{j#zFhkX?O0;l19um+KGt z{rHsG(9*PNnaZ)crUydTYB+nQJDOOu#F|IV`%!&|>D+GP1Fq*<7#l4XtZX^WncEYV zz<=gtEdx_!RZU@?r*~sZYfXk(R&zvNbF}r;$?nzDawg5RpFK5vzNMy-_KKCORz57%-!EO#fb@KuYH>YII(=b`{reK|mj__-a^A>OGoZlU{ z_VW+>Ae!oUc0xeLqgn2=0vt-tEiiKYWVAr2*ZA$S-`d?%;~H))XFGCE(n!I9-G%$J z6=UB^u1}0*E)5J!HMR96jXr)Y?H%>mmbq=wg>7+mGp2df&CH)V$7$Y-s6{rqrkbmH zfNox|x?%GM#Vy;nZribL&E9?cp^g?I*I~zh4)PHT;gr8hiA_D zyG2o3W14MVJ@aOmQJ%(7{)UC+UPDvNyEfq?E{zN1I?i*~FjU3HRp-~b6{WT}wX{~J zn`Ji3g;zONRZN{0p+D0|Nqy$x1*)1F+Q5Kbvzl%F2DX(Ox2#v$x=%U1vCIS;rExS_rM|9bZ)T!mEavS2GnO!%P zId`e}#!1zRi@v6l4cbKS#1%|lw>$lRO-cnrOGFEUccWPy17jaUHhXVBTbF4$%Vfq0 zakCg$rcIyOH#;q3-oiyQTZ7vdly)zuh}g6tWya>t_1j{0Y%19k=H~Bl^w{weCk;5x zoaH!i?&6uFm#!YWdim6?+js5?V)M-&pl_B6yu5aHxBPU2ijw5*0u4iO<8peU2$Cuf$iok42)A43fU)5Wt(7B%QBO3TFL?j zmN|3hPg$6gw`BQ>`Q4Gd%c>_XtBc#QEocUqR?-1+nF7cO6L zzH2V4F3|=@PZcP78qLa3q9-*S7Cl|2Gs+_ttgPJ>wAJ6qW$V7(9zt%e2f@)J4~m}S c!00)6>FQBP^qhqF#%Ngi1}*Ch?Zjpc01j05asU7T literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/full.gif b/local/htdocs/img/mood/punquinheads/pink/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..125b689151a0343b35232ffa366daffa262beac7 GIT binary patch literal 1048 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8Sqt~>t>PI<20Yw`N*?*9oIeJUn%GNSlg zUhg|xv9F}MDr4>K@?-BD!rvGPT;Z}(@ikZ?($Bh7TdUM?u3N@bhpVxw=a<~LZIasj zV%mf3b&U6RnK$sn&1Y=<^QZOt^&4u5EVYcq9v&^#`VG0doiTyUm96!uy?q6FGrN2E zn=<3(&dXj9R+c@jbomnN6TA3g$-1sCTPeSBqv}2pwu6V*_8&fWQ04e3)l(<- zpTBVNk`O1@9|5TTSdZb4l+1Z6jMwBu^SS7pKfL2y#h$91cdvKzym6m$Rgc+m-Gk&u zEbd-Kkp-t#g-M32T9U>YaX-u`ch=EBkDVv_IFG%0$K&w*B4fsJpY5s!zMN!rHGpbfDvtOkrp{u>le~GN; z+UnJ^Y;2o1vnlR7a`e~{rQ^pm&zwDX9^wZPR6lIO@B{9+VCipCTpFP*Fh^hg%hVXD z+5WRa!lxRPUVgDo`lsA^rca08FzqPKV+h~r7th(?@Zj&M*H2BdveW9SBmG(%LQ2%i zJN;QZs@fWRN^5IO3QaSo@#Un?Y3eOsSXMS~$?~O*o}jqMj9F~4dihFOU{vfCVLNb; hZQr4z2UL!oR6Tio-#K7hK%>G4)f=NpYJifIH2{xH)CK?m literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/giggly.gif b/local/htdocs/img/mood/punquinheads/pink/giggly.gif new file mode 100755 index 0000000000000000000000000000000000000000..9dadf3cde9a409827e4fded3de95f64e117d78e0 GIT binary patch literal 1499 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vXP7wxn1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{|+Sn-{EXfw}qRP;v8U zIAclA^DxqLO6EKblQnM&*16~izveh^@wU$S-EnKb_usj*+FG21mWMF4GDS|_*#kR)9mvxdld!pNtj=^%}oj_FKDqYFxvu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/gloomy.gif b/local/htdocs/img/mood/punquinheads/pink/gloomy.gif new file mode 100755 index 0000000000000000000000000000000000000000..4cee556c1f5f6603a509815f8ac78e63434f2df6 GIT binary patch literal 962 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq6m2t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA ztlv7;YwC&{Oq<)<>oUx8S|bWtqphb+aj%`8 zH+h!*oN3_;EH#a^SFT#UW)<7|4QwknZdtFgb%*MXZEN@L+po$Ac60!$qZeX0IwfY1?yaNgkN)!V5+NcENixC>+EXGw#@H{F7Al4 zn>pR9VOHU^xlZ$EMlH6{HPu|h19bET)s0&=DsJ7eZTrskYxnIx0Clwps;lQ=xEgCv z+syN4RuSph`gr4a;XPA4mv|fO;hA&(Zc)_Mm}Z+-&%7CC#I|lZ&GVpdZbO622Hhji zSquXecCf$juVbi*jjJuHH*KoQuT3}0X^{)BajfZ)RiAD;-AHNH^tr7Hni|^6SFBvM ll5Ooew&m+LtyS5)O?BIr)w}oXg*w>?)ybo&gEpzd8UP+Mr}zK> literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/groggy.gif b/local/htdocs/img/mood/punquinheads/pink/groggy.gif new file mode 100755 index 0000000000000000000000000000000000000000..918f9b72ed2edfde700cdcd3f15898f8af101388 GIT binary patch literal 489 zcmV&pS>ell!Gc#spX8-^HA^!_bMO0Hm zK~P09E-(WD0000X`2-1M00#gp00000C;%t`00YB#y4+_j$~hsucp12}rxp`_-uRq~ zNurgwx@t>~akF)I`D$yO`8HgqF(?`bwqB%2XgUeSU5Yq(TAR_=sCw-}r3$XMiC)+x23d$?^y4xn)-*IDIe=m9j0Ek_P0CspJdH?~Ej0Kg4k^zi_c>)5F zlWCTpnVpW0o|ueJqX3(Qor{WyrC>agMY_eo!c<45$jr^o&(P2} z)6oyp*Faj>*wWkC)!^ac;|TyE`2+<}00#gp00000C;%t`00YB#y4?OS%41xe_|?03 zo}QP zzftbc3kHjKWI{omU9ZDqfz;h*M+N87KtBJz?|C14Wng$fg9HGIQ3Z`riU5FzasUCA zk&SDWmjs4r0s@->n2w?Vpn-y+mZNH=tf#4}p^I9Os7HICWuTt9x_nZ-RaOT|y~xDH fS4_&w&p|TMMMTrq)X~@4#o98^-{9fmLkR#oB23{l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/grumpy.gif b/local/htdocs/img/mood/punquinheads/pink/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..fb67a4b020fe78a11cb1a201440acd710bb6fd60 GIT binary patch literal 1290 zcmb``TTGf~7{KxO`}{`Y=CZmjiwTLDy)e2gOQYM;b-QuIEltSMtR!p5#HrMcGEk^T z>ZfuLJg^mXNacIco_Do#I#~ z-P{-VdWhkwX}iN)uM=k|3(u+!zMi?=xcJu#nlo>vT=j7#WcDwKiGs;15YNgydL;jy za}J8dmp8od)8^DfOetExtjgjRCsg1WLQ)LO5SP|}1Aj-5@X(T$%O@55PDDmg0Ucil zlv*i(`V7q8esz1A1pWash(`geFkXqtk9OIH}lY@0pGj%NkOv_H{#ySytk#T8)J@&gjAF|6 zVYyw)n{yKL<|=+$ATQ0`jVRy8j6EA}oPQJN-3t2GclJDcA@BadlW^*>r(2!&zZN%f z%RU6x?1BNs8}EHSyK%zeO;pFT-&HaOH-Z;wMU+Ye&l2&nV_*)(OoRC(F`X-;HwnHi zS0b%h7_X*W0~)_4wg9L{PdD~d`3DS#30Icd9?y(4OjZfN!wQQYru-SU0+&N3m zb+YDNf+6S6D=3x0jBd3j73cHgHexq}zNf|8&naFxoN;8acjNB3Gltp8L%$1xBQN(% z&Hu^8=Trsn=Wr^~DrOmlhv17FgjjWDg1CtZi%62fn$|*DtrYD<+Orf0(4%?`nTR2q zx(oXU)I9_VY=*iU#<5G*j+rLvXKXibja@G>*hl1c73!KJf8{D(T&f*){kqDfvFYn1 a?2did9s8+)P;h70>%s2$Np?H{AN&h7?1BdX literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/happy.gif b/local/htdocs/img/mood/punquinheads/pink/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..3db0b17031d0993e2809af10745aa40b2b49f3a3 GIT binary patch literal 957 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^IRMqo3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_w9!|S_IY6b1@u^HK1+g z`7^7C^lW{+@w@PzDV|Hb4fgQNIe)h(YHLih&8uhL3^U5p7|P$Uu-t3NJ;D2qL+dsUz_W8_;JCpJ!Jw5;b{efRwwmdj<=Ksu@|I^ZD z8XFs@rKSD<|DOR26#sMkxrPKgI|jHK=@~FH0tFR+vT&v_@G|It6o8CnU|G50r043r z7O&6l{-2=Hmy$UzW7WDfZhH(adL2=^vtz@FSJ}^Z%AR+*z}Ua-;fjvmjB}Y%J61+J ztoD1^Zjcc*|Nd=<+Yj0L-R@M}bluIGJu#AD#p2fthBK4dSpG5iao05zR7=M&w=g#P zb~7*+7IoG4M3hXO&|WjKqP%qC>^T$jCr(n;U*@n(Uwh@UHH%aX4UD&K-?4KC&z`+J z+x8vYqjTt}?$N`$PMtoZD+qRd0IKU(VR3!V>wN}pXG}f{buV~-C~5U(nf~X$XL9Ua zXp}CaSbiumVvQ;MccRW)AeywX^E&C2yl zRZL9`cZvdCzgKtP!F`&CjvhX8Y|pOKXU;;MFM{g)#aNt=Gw>^N9!*hP_OX3);6nLB z3$l31SebL&U%Ng#bb9UOPO*us4Hd?GJGL&4c1Yk~p!cOFAxS2Rxq-1Zw4H&uyrSER z+pN2r9$&9}pczd@%(Q5`YhD#Z7mSJ!%09iLqhn}j=<@P1;=jjY+33h&zwg}+ z`5bn@?Lq>>t;GU_F-Kq#+gDz$e2aj7_qp#?C)qdg$Yqaz4P}FUdOEjeg3bAI>GluU z_PDD(*TIt1Ox?MEfv}g-ZUTMgd!O@jtV97{?s~%4(@LF$Cw@&1gD;)GM2Sd+@R_uXFoY5<%)r@o+si<&bPOg3%T*!yCjyd^eO3LPZ3_o?07ct@>QQ{ zfd9zYxLl!}*oaYUFepI^$AG(bcFxmmcDVD{_x{9UTcwVRY(G_xMcV1gBtLOP?Y*7D5 z(BP)CXWkf!Rg>y1m?<4bgVoPXP0qhnzg?I?AhBjO7Hd{>9{Etc*Z-u!IiiZWSrN`7 zY!YeeO%ZkDyoWl`*1®&D17hraN9PqYkUc!l7uIFIh|*pVPbZTmOrm8*!#Hhf=l5s%E=+YL7a)e zqn>pUFZ%ek{Xlr2RHJn@&eF7ytWeP~IW-DplX4Euj?Yeyu|`2rx%8ZKP=+OgnigG5 zVJ0S)U9AAztRgO8U$MBhf}Ll;MprdLE7*nYpp7q)#mmIi(%J-G=Qc)LWm|W_i;AfJ z;5{3H`$zs5{4_M=jlv3}nw(T()jIW{es+3hPNiL$xAp4t9{30P?_%bNGZ!Dq$C|ZF z{Mg~JuqOJ+An)_QdyX5)f&yRsCvdi#{AgF~SJwu{9c%0N8x6$(kt)&10F4lg9oVTQ zmaLT?S}Sa$yVe;KlOs?ziD)<@HY0^#s7<0pW<@}$mbnZ{}oRk_3ou3-83<;Z=z1x~e+JqDta389i4N`=XcJ|E%Ms6ZTBd h@EaS9T%j0SuT(3CH9GB-Uap#7SbRHd{6FM%`4dYf+4KMa literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/hungry2.gif b/local/htdocs/img/mood/punquinheads/pink/hungry2.gif new file mode 100755 index 0000000000000000000000000000000000000000..55a91e4ee347be8802fcbbe261a5f1a9239c60d5 GIT binary patch literal 1300 zcmciB|1;Zn7y$5h)ExbMJ_|YSa+__@#+}==GKq{bMXQ=&XXCD0>#l5?qIbUB+SB27 zs_c9jkuOBlmwZ(b67mJ{Z4*XBGL%dZop7j$Qrffbm+Yhc2mG|>`QiELdG5K_Jx>hn zN^nT3AMgWX9^k;R_o{c_K?gj#gA8~M031BD0=ffDx{(fyZB|w`>+e4g>2x}oOm@5p zaN_WBKwm~DC0>e5hz>kYI)y~)P4e*X5g;<@I(VX5c@A!8x$A3CI zG(17RSJ-lq>g|*pY=>PQ6n%z=tK10?*YBHqG)YAF9bDs;ZFRosR&8?GQ7FNC?2~p) zkvZ#!-5}e7F0wuB+l)}>f(tq4!z(Jvaw!Z7mBr?;t7^}{4Ub^oU@p4>5s8roBA+Uh zbhI|r6X8ykNYSMfV^#g)p4vWy)S=V#LfU}QNf9*6f+w^C5>x$*+G7577ObdNfboy^ z34qzMNj9G$OPm>K2V?8+KLF74y%$@DBa=rjcPqC#z4{8*qc$q3cT#nE`}n|1|IAz; zD>Z$rGmLG|k246d!FU=g?JCnZ(X#=TDsN4)J(A@mG*zqVQE+t0Td0H+Lye`lyWW3@ zamuxv!^RV!Yn0QT1H{NhqwndIvb)!VzVlhyEt)AU99j1==bJj`N>&C4S#Gl1q0T>k ze)D2vczJnlBBh!_WwO|;UpQxBUIXe>$L1kI5yB(3Fa=_nq>)R6JCs7XqFaPjYDF4O zFG7-ysC%Hk0G(b44N1rQ`o%^rJgrjB4Nn8B(h8nqZvuF7pn-5#3mRG+c4q zHMieR@=ku1y^Q274S)>TUyBF3mQZnAT_-3rD53a&^Id!=t%FBIqKK}!E z<#N=5%w3g34~%@gvDs|jzZ+A3s1CcIl3x)1b9h!FrIJFeX4EjsnMAmbiyE<+bw~>z zsUtQrngwk_9;a3+Z;^Gt3UzlAAB$)O+5w>w>g#VC;zK>v@Q6-2j7)G0YQ;>`6tKuG zpv7GC1Yp*z0^9nuo@#(LG1lLA0rd1Q``YvV0OZBXSN26|k16(c=F`AyE^a^F$m?2; zD4oT>7v{pOb&cctXIj&B4<;BNh13BWPONA7#Usse+h2*NxTNn5NghsbKJLVa^#2J7 zuyPF_MIyBgb}6BOfT7VANQ(*$^axNO#gl0iXhFUJ#`V-$fUzwLR@adE8UwU}S=MOm z0D88)W7|arQJ@`*bZPS*IVhVaD?T+RC8x)wM5RN}hXwjCoLghP$e9!yUlhZ5Keo{O X^{2#1wr@NvwBwbMW1)6e3<&)XvsFpe literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/hyper.gif b/local/htdocs/img/mood/punquinheads/pink/hyper.gif new file mode 100755 index 0000000000000000000000000000000000000000..a5da87b6ff2484399e208399c02b458288260cfa GIT binary patch literal 957 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vXP7wxn1|1+9s9A%7fq8z#t~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B(c(a4!)eakp0EV|GtIROOqEqNg>|0ZjV-M;8D?3{5qZtg)>9|DS5M2C zG}C_e)bRP1nnv0yR<2sTl5O33wiO#TuT$BwU3L4`HGB5%Q{@D^nG4m;3ozWAk~vSq zWX+p`buK!>uQ|?JysdM7cih^~KkS2Os^i%S0U3{Gxz7r4C^@&l$nlfW0-;{xx66KO zcTbILxV4<^$T>+P1qXH)?$1_?eJ{B_F_yVBFfi5B)|WK;__efm)Ms1fwnZ1V#o5i6 z=2bT{f9f2kc{8FG+31>TuI2%{dA;g}%^MWAY~Q+V$GSCp_wC2-=(!k<#v0Hz^Zc1r zM0&P9-uPX3&lJxk-UfSk=A6G<6ty*`+2++VZ-yD=X$<9WSXk~gQo>P@>mf0v5Ug=obEvr7wbefUU%xQC)6f`xomn~nhas}I(wQS4Q eZCsoR*gM|NnmmFi`x@?dKX2?CcoeYNTht z%m@@z{K>+Z!obR)15yCe&cNIlvFpx1gHxWX_gcI@yZe8FM&A;ZIV%FRoSEbgb^lsHIJo%*4*vsgKsKw%| z+25t*a?15Ht=8xse|EU6ysoCjNLy1wyQ{mWw})lIM3$~eQzxiQo2fc;df&YH3sgD5 zt_nbPRTGA*QZnahsH|C2u+CYB|24;Xi??-7?~Yshz5mXg)plf#pfbk~hJg5l%uF@L zoiC65I+C_hG*4)`t=0VfMawGXjx)U~y)8Tad}qOj*4p_8Uq{!ZR8}?Cx0|Zz>S*@z p0$nvxb<)&HiqmFJpD}Af-~0s&q0SOPb=DvWETf^|s=*M2)&TF!QD2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7oVt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6<+cLZ)%O$L>z#YK{*d2~PniuZO`Ddf9II=3Aat#UvuC=aiA77SdDOfg)pwZA z?KVE(dai}B@rM-Kbm3bPYZu7P*#CopsiLyFu-4PNp}D0x!z`;QBCjdhddejCs;M~> zXV}l05X|pgjPf*w@;59j_p)Y4`w0lMHdQM8 zyTtq~F1*6AqDxkNs_9fCr5RIaH!5gqXfIv1e8qCM)oa+6 fuHCR&W#bmrEt^*E+_f9(U?WrqkERRirweNUZ$hOt literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/lazy.gif b/local/htdocs/img/mood/punquinheads/pink/lazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..50fa8a38fe75bd636c3d5b120791544a6c25658e GIT binary patch literal 1039 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq8w!t~>t>PI<20Yw`N*?*9oIeJPpqRv53z ziRN?BIe&P^xr#kiIqzQY=6T~j<*FXDh4*|o#4=%U1vCIS;rExS_rM|9bZ)T!mEavS2GnO!%P zId`e}#!1zRi@v6l4cbKS#1%|lw>$lRO-cnrOGFEUccWPy17jaUHhXVBTbF4$%Vfq0 zakCg$rcIyOH#;q3-oiyQTZ7vdly)zuh}g6tWya>t_1j{0Y%19k=H~Bl^w{weCk;5x zoaH!i?&6uFm#!YWdim6?+js5?V)M-&pl_B6yu5aHxBPU2ijw5*0u4iO<8peU2$Cuf$iok42)A43fU)5Wt(7B%QBO3TFL?j zmN|3hPg$6gw`BQ>`Q4Gd%c>_XtBc#QEocUqR?-1+nF7cO6L zzH73pY+&0gy zWLn&`6}B#$gEsp+ZQHzazJr^q$KfNu=rQFub(-VYne(R(U$}ha^2HN3Zr-{L@rx0v MUq+MK;7MxM0J@s@LI3~& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/mellow.gif b/local/htdocs/img/mood/punquinheads/pink/mellow.gif new file mode 100755 index 0000000000000000000000000000000000000000..6ee4a4951b44b23c287a6ed2ef964c58a4c837d4 GIT binary patch literal 425 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/sad.gif b/local/htdocs/img/mood/punquinheads/pink/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..84e1c00206508615196e42714a8bc98e2d28af08 GIT binary patch literal 1087 zcmZ?wbhEHb)L_tH*v!fB>D2qL+dnXz`Oh@>$e9&)Cgo3hb?vjUv2j{j+W-Im88Cq2 ze{Mh5kYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=wiulBT)o%g_1WG36Eyl#GUsKi zTDK-_Pr*g6^@;b7?Y>qq|Mc>v{0!zvE!z(VR2p|pXlvf0p8Bk><%vl6Ucou@oy>L~ zsdZ0E@_)cueTl8%&b40d8*QJBxjB9?hOyT&Gc#1?$tJPX);IPrGO$!t_qSP0om|~r zY*#dK=B#ArNeeQ%7MU%v($ZhDZndtVf$^5D+qUbrv~cX%%dx9Peb>Gtdk!$G96ow< zm+JA;#|~;9Kd|H4bz?!WM*>hivKfmCav79p=3a;gBkJ4hk$c zFe~-Ec&T6o(`x^DlMZZox53KkOYj4uxz-<7)a0yQn$}>$ZgzrkXL$!N&?AxTwM>i^ zRSKyfe>5{Ou(Wq{)wMbReK#R_a#yiq`NTPM)7&Ob%I;iRxoEN1s^v-RTuf~Zw{y;9 z26|-gE@t(a`;P28ptAeusr{-4PVYacdEoMntJm}({t!X+$5t%J9IZ};Mlv5WA_I2-TRO3J-AW%$gyL)RZpBben|7g!JXG{ zKx4#c*!To3ZDGqK)Jt3SY@npo%-G=5#lX_m-dWe}&^K{XCoo-2NUolc=C*KtP{*Rm zc}u;PFHB-GH??KjU?{@OthIv~7$^I7?^N5d|LFdMDtnHdKA?K=%z;B12d`|qcHK~r G!5RR;8QZ1+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/sick.gif b/local/htdocs/img/mood/punquinheads/pink/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..10adbf5a93e65a4c77e9c123f14353ca4b0ae6d8 GIT binary patch literal 1372 zcmZ?wbhEHb)L_tH*v!fB>D2qL+dugFN}pMAXHx#8SJytLr5UFIv9a<0|Nj{Qsf%Pr9oL+el>A9-qg={ku1pO zY*4HtGbJ!R$-=i}_QlJ8F3jr^XJ|+YYGBCCS1x2=>}H7M=;~puDPU%vz}TBPondNw z$F%Ml-m@pyPHm}dnHx5>qH^uLwDhUo8#WqQuifS6E^KSF_u!$!M~*79pE${Wf_Q}s)hmYvz$NIxuPeY9s5d$HCq@b?*FyiUJZbGPrEzjx>I<0ns_ zVfEID!Q!oDv+5hb-da8h=qqNX?Q9@V?b{CY)Y0`P#F$R8F`YSk?%bto*Dcv^-Dbaj z=l-oT4<287{P4z$m#^xm-pr^L?8J|}vC?UKlqYo~Wyy~%mw8vBL|Ozh{_pFe!G;l-sF@1EcN z`04W(F|3*FIGMf-UiF?;RBPkC7X`DGc-rE%${gfob|#oiJX@9ip0(;{48xDT3Qlzl zPE{KD42)e25geV}mAOi3%>9f#8Pgb;+uEmgP4}KPcizZR;vv zw5{I>PK$dE=rFMzVLK?wbol78<3cA-pE-N}^jY?kmya;9A7HD2qL+drIHac5Hgq*vEI|NsBr*w{ENEe*(Ezy=imbNji5 z1UowhxEkphFf#(xDE?&OG-BXj&;h9j8Oy+OLg1w5>b(}P&+h)8pwX9-IWJ??x;18d zK3wq9PrQF*_qB@orbkO<2 zAcnb&Q`VwS;tVU}F^inQvig8D`sdzR?x%y^RqWe*mHX#rEGcTBctV4TlT%{Fhr>^$!! zj0>F?&tK);*|n0PCu-_ChDqfsX8BLsxofxgjENgGbiKQsPbTY!oZPVSxW!p*pyzJh zl4ieqkNxKTM|ZD1es=xYliRP~ynRQk_txdS-e+KT=F5k3F6)FpcfEI*_tr!~q>pt$ zV&;RHU98I#XUks=_a-^l90NvRMefBvrO#(JGI(@8?6bV<;_-#E%}cq+Yl3G>z--Y% z;|ku(O*;Z&^Q`X{GWJB*pY#g6wcBppQ8tU58Ot|wmY1_I70UZmCfDbcG`Gt6u*BEr zCR?;9Phgl8!ZM3tT3?1U1LIPLdbTCYdT02rVqEUNa_I*Dg^SkDkDt4RVR|*wygBo> isYN)?X+COvJlMZw`;6n~FX-Et=--sY;yqyOSpxu%jjeM4 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/sleepy.gif b/local/htdocs/img/mood/punquinheads/pink/sleepy.gif new file mode 100755 index 0000000000000000000000000000000000000000..4f4f316d9d57d6685945d00a15ce97d4b9793183 GIT binary patch literal 1270 zcmZ?wbhEHb)L_tH*v!fB>D2qL+drIHac5Hgq*vEI8yg#+`Oh%(3`1I4+W-Im88Cq2 ze{Mh5kYH!W09PYD17=2`0>z&!oGA>P3_2jiAY&O=t{I&4)ZVq@(&3%|9<;QyCzd5@ zO>Z&@Gb-@h}?i*ad7R_t$%dLH#f z=v+qAbZMjI_g@*zHfp$i{!``Oy7R@~Sy&tMo0=-Bm@-;hn$wx;QaiiK+WICqFi)x} z=+Bv%&akj-A;YwJoeYetma?v8S-F~JZaovz2F5k(wli#`NtA&h6cIlQSXy{^KW4pFMwJ>EZX}wa2q}ub+Q>^YYvGA3sF} z!CnnO_3B-qS6A=-l+kPLs&GlxZD(bMQqmGj**J-?)mNnovaSlnZ?(MJZnk-6i?fP= z<;SIYj&p+h=VVVTx9p{aIW(o7bH<@v0u@|QDAo$fP}fpH7N zs_mP%&fVbA&$N?q+jiCi3`~oc?B8;*WA)J!C-<+YSbKcWjN=OyT`S4BS$?ysg!A6b zhu0rxWj=nB8e#O-_Wk?EpT8-*`TpbMpTGb9mncCZR|M6^!#Q$|MvhlURywu@0O5pO Ao&W#< literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/sore.gif b/local/htdocs/img/mood/punquinheads/pink/sore.gif new file mode 100755 index 0000000000000000000000000000000000000000..26896dd8a003a7564c73f2915e5fa0d1295e1482 GIT binary patch literal 1299 zcmZ?wbhEHb)L_tH*v!pvBqZe1srO&EfB66Z|LZAJ&aAjIDSy%mC8bx_J{ubwr=_I< z#Tk%*;(u;G*N|Xm#{gF&Jp*P&pp@cI7S0p~ZU!BYGLW$hEcXgddamAU@%rrU|M5zF zN*rolt9ZPU>fCjX>x&Cl^vRc&y*MDdUVY+Ah7&3Z>Z@g^Sw8V;yTa?}Kj%xri>j3Y z2d;j;QzrPrWRY}qmv8DiM_>2NOF!J$b1vTeVRZ&)O>-t&vO=SBNq3no8*66oB&AGN zHq!}Ntvy-OXHKlGov%NOgKL;zI^ri&D(b(S|8tk{G$2h z>yNiTzP~d73&hI-s9wI0@N$AiUrMHz=c;At(=;|1X?S+aR`lH#_4{++extf2 zOaGyTn&K=L^BEHIN;;V4?wVt~f+e*6MsuRiwJ63|e^VQ`9rrs7^}6`h9%b8cPxtt( z!piEV!r-#TJkF-he6~!5cCD(3H7abZ`IBd8=CiUXPb=u2R4{k`^ycQJN((p`*LBQZ zyPji};sQpdos5e(ckJ3SZ#66HKBnC>jxruTc<5x+$*qTuY(Bs4wA!@8D-K_rdUN@l z(`R&(?>tL(5lMOd@~yn#2ZOgCzkJgD`s3U8pIq;NUS_WAfcRMir=O`F&9yb4IOgQ& z$m;0I21RpE$>a=BGbsRk0w8Oj+e7^lrxI+2lS3u7dnnx%o!%>D7J=G$*S-~Igl Y8RX|IsGp5c{X7zqHky}*ebTlD0AvbQL;wH) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/stressed.gif b/local/htdocs/img/mood/punquinheads/pink/stressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..d72afdd84fc29770b69f97e241051e1d19e1e259 GIT binary patch literal 2520 zcmcK5X*8Sp9tZG$9uZZon%2y4+_rKgLmJdtDXJ=3Rnew)ZfO-QwZ%Gig2WnHK}2F{ zEu)e_YpJn>pb4=Av6QOna;H10xA&UqIoHjd&N=sLoqKxj^6q)_y!f2&_xJtV*q*>0 z_SOPg;D#Jn6Ro_zvpQ0@P!L-1a^{_(q2Z-Vmo_#wkQ)l8k2^Wyj}ea>=<3P90078e z;PM7Q4roiir9W!{Ak!SvvG6xNku9ei_iD6rnlA-J~(grxONsv7(NhvQ!G;=)Zk1AOy1`p?s>YU z?p+E$^GxwvXdH|J>`ws-EFt8IfpT&-HB*+J3+1UgG7{X%N?FW!vv_9M4Q3GYx|$}} zn0po3$h}?Hf@#Kfb@O_#h`xSA*MP7OH8_kO9_k&Rm_*C}=Gea3A^6ncf&Zl_%}6Qe zW#wvf+l2Z!VQBfs&U-lK($A8&d2o8)2`9`h!|IlGuC=^uK=d<-wZf7{3=4IH%)Nyh z*-h-UTV89^c=viahLnf5+lVDbk_djO+8`?+C<_GZQb@$hCIH3&J{O8h;ADD%6~u-y zORE9?x=R(K#?8B~!V6Dxpw;gqL^|M`|A6M%@SHU}c_AEuo=9U%EOqQcOwS-DX6L8J z?k|cL7bH)f{^{qBv`-?s{lB3-1@1m!CFti~WBxjg-DJC($Q2rRUNxHtfKv!Ck@V~@rkI}W*_4DJyFrRZSD+v0mba;D!~&Os zhJD0Xf=%0A4Bw9Lj^*(q8r6*gH7Ar1Q`6JvnYkI{{Db=oi&K;TY}yw@^dHiu6r&F@ zyi->x>v)+rZ+AWriF0NFIVhA2Na5c|DY;Tg4h^29O1uWki(&wq%q)my$0|&&OeIjt z_7MYJY^t@mc8%^>Zev)vx{mP$DcY zUN#d@DTE!ar!8D*CxU1xWU9WRuOBtUEF`}m+=uFBR_|#|=Q!p!9Brz1YB`Ll!%9c3 z7mMg0Ky=?7>_-iaphrafiAl-UtH%E~kfG}Yg@?B~#wS)^TCnv5zrKg-I*&Um9iqvg zzS@2Kz=lK_?t z&bephz@zO<%^WNtC?A$fD+MJC+nwhN&z8e4m#0=M#$+%PaLJX%>ED+)M78YKY&U6d z>vC?dEJR@%u%h9SQ8Z$F0wJ259!Jg0iRUC^iw~E6SA8;QjsF)_;CzaCGh43xwW<$* zrAs|&6nKh?a~6!6kq@9;8bpU*rWZ3x;&6#YriMihQB~@iwI;QJNKS1-H40;nZU3pG zvmL?fL3H=_^EC#9Xd$m_WONMsWuq)zfiGAyqGjY*rNOZ^gUa1B!#A}busIm6EED(( zn}SRpC7d)VHZxG~m9tiePmG8?`Mp;x1d(A$);S<6(~|0R%rhUCAL&`77`>ex3@mP3 z+fm`4C*!nxh-|5t0y5$hPd_KDGZXZ%GBpej=@}#5udlbH#FJ<7f zDE^g!6&kE^CClM9GVTZ4v6IRJRi~69(DIavPBAKaMZ2&P3^pce@x|Gk(HZW86>aT3 zxWI2BT}>lGp9*f2t#Q0yDf&V16rdmPOu{)OrNi>UMOly!qsH4Fv2evhP~p{r%Hr}e z`<=d}E>%=RZstwJ#H0$c8Knl7olx!?_tSoCw`q4L-=n*x6s6OQ5z8SaB@*=1>=g3e z{ki#t$?->zpKJ~L?9tqm&wm5+)R0^E34$j{S*rg3xSWf!(#xT$cu0@Nvj{*1bckun mWS5mEo29Xi9Ade~)v04SrW_KoiPL-&rE?V1t*~`IW`75o@>@j! literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/surprised.gif b/local/htdocs/img/mood/punquinheads/pink/surprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..fa49b1a7f3ad3a969ccbbe3bbab8758ff8768d30 GIT binary patch literal 980 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 DBk!Dq literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/working.gif b/local/htdocs/img/mood/punquinheads/pink/working.gif new file mode 100755 index 0000000000000000000000000000000000000000..4860a8ca0778f9490fde79ee69a14b27c0b722d8 GIT binary patch literal 1841 zcmd^=TS!xJ9LLYxIp=>W0!^ihgh{)c#g2_8XGS1eRy3gr>!s~whS(LNi>C|Sh+r_V zQVV*DWu?-N&eXEbE;#2lcXw^aavN>4t5z6Y9(r15)RQ&SUnL-U=o?2?^Zcd573)NkET zF5~mKnX+&2qDBaVq`CRrvk>gb_wF#+D&GYySsi}4asSPI%+f=fx{K=q6^@akJ&D)_f?!;(Lx0 zsfTLQiIb-*E<(o-QanSofp<=%YLO%GHMm8uxpBQQujPELin^^vWJTo!*4ed+?pa~J z*EgUvmV(F3Lrgog8lWRiyNx1+4(F(c4{Qp7&p!ePRve8bo;_hw=}dTXis^gvc6z3? zV2-Wm|6%hktT#j9YU#%RZ@hItwiXO-eo2;HlXZU3x*io zqcXseIVf`7@Myi$AqA2#G{6V3SR^DGk0g@GXOCHqE+za)_wVJBk5G5iMln*ZkQL9- zaqdjYuG$Jd&{}94s;cLsppqg{ht%hi0KWx9W8)#wL@=K4xdm)Glg6jm!QcNm*Wc!{ zhAz3X_xaW0HKM11L!0B0{JsQ3T6XrtXQ5LUjvZ*`>8tg;Ga{9NTPCfr;gaTh8`7F* zI9sb~zLkgEtm0BxNXUvznDTCI#d__1jc%}+#DUFbw3roQfVw>d3S=%%DCD=g?J;|F zG&~uOtYx34Y}Ry!e)amzTYTP3F6^evL(Uni2t>i5(OAycdTqZ(_kbd00CbRcvxFlf z>@Hw)2SY(W?n1q+*Buc?!^!dZL^?B>ntIWbvnHIE?XRuOp?Xl*p2@0T1-vJ}K B3^xD( literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/punquinheads/pink/worried.gif b/local/htdocs/img/mood/punquinheads/pink/worried.gif new file mode 100755 index 0000000000000000000000000000000000000000..c843b7efa3966b80fc91a0dcb756894d92604141 GIT binary patch literal 972 zcmZ?wbhEHb)L_tHSj5io>D2qL+drIHac5Hgq*vEI8yg#^rKSD<|6lPxx1VcBu(M-; ztC5}oGa~~7gW^vX&J+fA1|1+9s9A%7fq7BIt~>t>PI<20Yw`N*?*9oIeM?N{ya>=z zf4J|6m;N_+p2 zS$d2I_Ido6Ws%+n-x@*V!{Ra-Ja)O;5fa>hU7|u?~ zoTp*3=1svm7aif(JH(3PuH1KcU@3d{F*8%^e#PVB+7_kfXJi`-oS1VwZHmH-v{jqm zlwMmJ)tnI-$*jh3FY1A`Ky>}uh6cF;ohRR8;v_KSXo+ZdS2%DXJPddpi29E*FJ za(dD;X3q?1nNvDrzO44_6*j86I-2WvfzIBfx_R4X#qGOx?A*O^{egprpzanyb@xIH zcjE}|^WTFD%hug8I9V-e%6!oKr!?2R85%j3t+D1&i)MUi_2O(O*>u61Ip%4Pn7|6= zHr8Epd-l4pRxy?bH!?647B!SMnYDIwHe}i5wbxEacWLiWsGm_Vb(*aDtR>*kUIh&9 zHEbI;vaQ;*b%V;bovJ&xuiLl(0MylJi3G2!w-v~)zW+e%+v($SvI{?~{#&=Bx6i}G ztleR0!uKzsoJ}fe26w-9ty{CjoiAHIMm)hccOBz1Lj?!+2JSBmF>4-jJu6LUsA8(A vt*uU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91>)eKr7Ascm+OH4Q6NJe30N4KPL(vb;@yTf^IZ%#d2X1GLLP{K5a zV|(F-9|h8;2?8H&AG7hv?ycBhb0hhRsH{canTWcl$9rU~tA6}oWbqJCe9=7R|HH+{ z`(%u_#6<=zcH?{bxPFfR|K{4SGGBEW1%#bN5|0Ras4QF{#G^HXMaW$u@Q8qqNczK8 Ki8w(H25SJ%ZELCk literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/amused.gif b/local/htdocs/img/mood/roshi/palefaces/amused.gif new file mode 100755 index 0000000000000000000000000000000000000000..ccce6019dfcb4c9779a5517817ae4219a3d75ff3 GIT binary patch literal 863 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 I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/artistic.gif b/local/htdocs/img/mood/roshi/palefaces/artistic.gif new file mode 100755 index 0000000000000000000000000000000000000000..18ee0bd4d8659f3bfc77add55a1478241854df40 GIT binary patch literal 1054 zcmd6l>rY#C7{`C56eOKwEOC~EYP&7jqPT1`Y8gpGv6oZYa{^H##tSmT0*i);)h!y$ z;q>&n^?X#VkXR=w8YYCk*l_7=*+1d);(7JtlkYd5 zMDmkH!O${ffM~Ex7h}V77JAPw+Iue*k&(9Lq zuO`DGA~Kf=`y!D@JQj_`V$r2!A|4~+(L^F~gCH`?i?_bNnaN~+xP5D7WhI-1HaIjqLc{nY4ksUL7Kt^O(}syf%@|t<#PA>(o`f$6+1N=)AQT0@L12+k z0G-5Ge15dW4S%;hFKS6;SXw^sD~(&cHa+Y zarXEG#5!%%q8}apO(7bfo~~GY68X7iq*0ZB(Dp87ryhUnr+ZAp7;*W5xp2?$YxFRn zed=rHy!UL%+Z`xu_BSuRPVIeuUtQ~BRPpv3o-eX1q*FMBv;WKyC|ss^>9xr{caG&c z;~ijs-}3p{acP%Y!)m{K7Hg`a>l*$Hru)hA+wL~2tH~j)R#!_d-ff+eoY~`l;o6Tm zdmEWrbD#;`vGUeC#v;|(hQK1(q-A)rUam7{QS=fOKbl)T7 r!AB9vfLertN+t>e02d?T3OSA-YMEANG?~A&SOrAwbaeY$n) z*1LD_u3fwK=+PsfV#WX5ey$>XzuqP#RUQ5fIoNkZK zMIkw=>XQl?yf|mrUwV^pLR6+bZuJri3oh3K42=#(DLRseJy|^kyRW;rO$$80@jl_= z1QxZPiaWNMI(u5&e)9@2JSncJtI}ksv}j^rFS73B*r4Nm*Gpu;as+KSy^Hz-o*9out7rJ~VR9+dJvmf{#x`G!mvquuco8d|_O7m(^d=_gW|mHEgv8 E0QgkSUjP6A literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/bitchy.gif b/local/htdocs/img/mood/roshi/palefaces/bitchy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9fb65aa360cf6ca3283e32fe160e41494b03a25b GIT binary patch literal 870 zcmZ?wbhEHblw^=(c*ekx!@&2Sf#LuE|9}7f{qyI~@87?F{rdIe$B*ydzkmDo?aP-h zpFe;8^y$;bk00N^fB){?ySH!OzIpTJ_3PKKUcGwx^5u&cFP=Yt{_NSar%#_gdGh4( zTLUxOVN@)vH&pT)A@j^5sjHE?vBM z@xp}*=g*%%ckbNTvuDqoIdl5-=~JgpojiH+#EBEfj~_pJ^yrZzM-Cr8eDL7G0|yT5 z-@kv~zI}W5?%lIz&+gs3ckbM|W5IMm>+9p@=H}w!;^gGy;NW0qXJ=()Wnp1qW@ct$Vq#=uWEeQ01F{+v z7YywG8$v^Zg8~Br{QZ2pdwl);+XI7wLqbEtZ6s#R7N0v$eD-Xc@M(_BOe)!o)S-HZ6^>>&^N{R5Yvz%VFmxY~I zL`u?Rhq;`BvB2OBHP2Ua!?9)1yN1v&E_mf=bYd#iK<940(yY6y4e*m3FoslL|J zOja{243iuLt*gE&1U~X=h?7@#kdQp6d_r5*wM*E(iqZ3;lWV7-qFup>2F4IJK6$4e zjfIO`xfG&K2k(eze3Z>0Aa7Oh;sayLEg_At9Tm5=J06H>2hC7$Ols*kt}HRzW8de7`3HKR43{{$3>>k0^-JLM>-Uf%@`OA^Ukl6Ro>RExVPiL zip0e`dT*bYEWJIDnQh_&;KG{nC#9kZ{NVc*<{o4 zOWv;P%?U&0*HcwZvz~0|`{yp8$iViIx#rf>3HOB<4Gmoc-DDbFgaot{6um%9rm2N5k literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/blank.gif b/local/htdocs/img/mood/roshi/palefaces/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..77fd817e13b3753882430c7e77d2d11a2e254d3d GIT binary patch literal 900 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/complacent.gif b/local/htdocs/img/mood/roshi/palefaces/complacent.gif new file mode 100755 index 0000000000000000000000000000000000000000..5fbd616cffb4d4a5cbc289f1d1ea63119754fb7f GIT binary patch literal 867 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z^03WeYgTPu!6X|Ns>Qu^<$*N^!Z^6K_UH=*M`ieEuC^k zzDsUov>s~V5Y`az{a8G$Usx+Z;z+vAtw(Hj>y8PE%5FT`+tTkI%e`%uEAEuW+vvEs z?V}Xiw|74U=9gK#Sk9vB&Ee=G=qA&6q}kKuhk}s1L?DZxlg`3B LZ8BQo91PX~8B1jI literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/confused.gif b/local/htdocs/img/mood/roshi/palefaces/confused.gif new file mode 100755 index 0000000000000000000000000000000000000000..c8ba7dfa98f61d6c5c7850222b72049d7e02b8d1 GIT binary patch literal 404 zcmV;F0c-w8Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`Td>gv+c(&pyoEEpX2_V&8E zx}~M1wzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E*5XecZwdCl{J0}wpjAUt^ zj5M5VJ4i;7RBR<1l28CL37Ef;3{VhA9GXI}B}^1F4hdl}I24q!1S#u$QbB+zmBP(Z zr~~k{Aqh;b@b;vUmM9u*HvmC|@AQ0l3U&=RfPHa?1`UG%cQ`+9esVC3b_SRfNmm*a zmkM4g}cP7und(!`IvdjS~vt1P-hU;0o*v?(gsH<>!qH&Din^@C^Cg4hs_&Fjzpa ypuvL#2VPjna6$wCA^8LWHvkU+ECm1q01W^H000CH5XeWX4cOkGH3ywFMF2a}-<~W0 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/cranky.gif b/local/htdocs/img/mood/roshi/palefaces/cranky.gif new file mode 100755 index 0000000000000000000000000000000000000000..0bbde811e2fabebe102702088817b6b2975ba46d GIT binary patch literal 556 zcmZ?wbhEHblw^=(*vtR||Ns9#ckbM_ZQEYGdbMxgzGu&#-MV$_-o1O*u3a>eMNqV#WX5ey${9vKu=2MyyliUIo%$I zl(w$f!ZFEN;1kb`{U?*2pOBQ=bMgHa88aSN2gXK+PhxA1PPnk3X-S9k)q<rdFYj>LmZttd_nuW~SLS{zaM7 zIA=4>TwE|&wmEe$SK zte3<^F0mfGa4m?nP4V(IzMFTLpFDl`?9xLao{Nv4zkkWcBh16h^Zm!qU*Er7`S)KC z7$QGe7`Ykv8FW|}I2Z&Oc!3_){LsibZ||gM3qC#(S&=Y3f^}L@uU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;#jY^ z;l~FllQ^D_x`&VT${Z>Gka2S2aSd6^yc-iX-s$3(v?$r~<>O=a2?{S7r(8ef%+4nn zwN_)HBXj!~IlG!U{`2>@m&$z6+;~RFNg%LA&|P6+f)I~Z#}Pp{5yut*Z;|wetrAg! H91PX~9CK># literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/curious.gif b/local/htdocs/img/mood/roshi/palefaces/curious.gif new file mode 100755 index 0000000000000000000000000000000000000000..8647a76ba72605692ce0d1479921bcaeb0f0fe4d GIT binary patch literal 510 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11>ZQJhMyZ7wbvwi#aS+MXNJ9g~SrAx0~y;`_% z;ipfZ&Ye5=?%g|}V#WX5ey$moJ^~IL>w_N&GI`@o5|n?zAgDefanp^V_$I@7~_wXy?Ao_VMS(&m7#s+{|Je zG9DWi9B2?1(wZZ{2=YCnG6O$@4l4sEkYWM)UPz$f!>X;qGM@Q&g>O_UJ&%oK!LE$O zVgBBHuc{AM*N>P literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/cynical.gif b/local/htdocs/img/mood/roshi/palefaces/cynical.gif new file mode 100755 index 0000000000000000000000000000000000000000..25a53ad00ecd092a798d970c830b3002098ca45a GIT binary patch literal 865 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91}8f0v1bq%aQ~^Zr$v znb~-RB_&LDnaj#c3G;EYv$8OMW?^OL<`b5Zmo?vIso+wxpw!i|shM3=;Ew{6OJAh5 z%Y+rKs~cUrMbak*E$K5f;M`1+RrnY)u*=bAA|ddvu9udG&BSOk{53USN>( zK_JP6Q&jg@5W~w^hmLZIBstf7IFQK9&M$v!n#0CJt#=|Fxwc0voWjy6sHD_iz*FMN zy?gySmP|orH*PWQkR=|Ci@s!tYDa8o5M1o~Oi?fGOoyN|+uKOPg6GS0Zy%iy>5_0| zgX0~xgO88qUTJV-`Ozb7QBv~c+Bxl5%Fb{H=HIaS`c=*^3VkJ$wj99vfK7yWDR zm$NQ9^Pno#vscP;#q|FZ>;Ce8zy7q~zR(r}Ll;3enMM~O9<7H8&7KN{ErPB*2agm= Nq^)=;+Q`6Q4FIpCYHI)h literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/depressed.gif b/local/htdocs/img/mood/roshi/palefaces/depressed.gif new file mode 100755 index 0000000000000000000000000000000000000000..fa10c4f75ee38a4b6845ce24519eae424e1aa5f7 GIT binary patch literal 884 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@lR|G)-=2*v;0ey$M47M9|>=oR^B`B~#xKY%&=CsfWL3@Vd0w-rQ7Kqj~^q)9+ zh3oqD4RcPvm~-)oz#{>E{wGI1?|t&&trDjIAK!<6K|z0PAFwMr?rY=~`sLW-k=R_v z#;8&-VM3!k8+XdtsD$RmqwRv?79T3I8k;6-Xa!FD^1>mEu};N!mXGFSW#&58C;^WK zhJ%gFY)xFEzc!~cG4V{+ise#Z0finTKZ6W|4hsVZgCGMNF!YQRLL(!l6=uvz40H9J zQW_hPo4on!p~X}GO}obJpmMHmx>BIh!;@*2*IOhryXrJost7TGjp1UDX3${<8Y9fW z3pB>^!8S$}g?UMt%NW8JCI9ZzGdPfByGC05-G*!LT~>XJaC@Y)glZuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91{W;V@xAQ$x622gAh0*ZBlh zrm^NYOk8v%PQ~TTi>u8pobh`ZVj4dzP+^%6?lMi`;^OK2!s-ECQy3OL+sL4}evZMz z!%I6w#McMR5J+TdU7%U5JosHICx^Ke6f@53b4t__NI6%RHvHn;QVcrS=}sFb%}p(T2ahgZ`P4#5fTCjWLW za=jZK-n6BIaWQMRs8-Mt2gj%_U7|Ws2Rbe?eHIWmPCL?}m|V7AVteNKzPCvp`bq{_ zH#RhGusHP4G(q5}?PE4RS?iJy8J!#0`CnKS+?lcQV%%d#&YJ~DGmP;k1$ZutMO zd%vt@TF%~0OWb;8E}#7Gu>PNW^=r!;+g%)dcmi7l-4!MtY4S4Jks#zDljtJoY>;@T LRYFRfgTWdAmxOMd literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/dirty.gif b/local/htdocs/img/mood/roshi/palefaces/dirty.gif new file mode 100755 index 0000000000000000000000000000000000000000..fe7b8c277c1b5425649243dbe4a4d02d44ecd2c6 GIT binary patch literal 665 zcmV;K0%rY3Nk%w1VHp4!0M!5h_4xJ$6$$6_>iGQm00{yC9S3c`euBr4n98BU-N>fT zt*_R$zTCsm=hFZK01FKZ2M7oK{{8v-`C5`za+z=A=HlAk*p#D*^YrqvxT%bnc!`gD z*xA&_$inaM?yRe#dUH#JeOjEGm(Hq)#{r&v}1Ox&C z0ssI2EC2ui02u%o000L6Kwqz?fu~r03JGN9hf+*ohNC= z$fn8_z$a@yS1!%2Iv(N}7#^-aUlwaAEiW^hJFXTU7CJict|OkCA0)Z)KT7;Sz{o;{ z9{>gB$Z=y6ihT)RAxMA?;U=1S5j2l>4fCv$y#Zm$yE@-&$0VU6|8EwX35duVs7BPMhxIm!<2n}_eZd&t0FJBNK z0RIR;VS;54G8&#cx3@2d7lA2HC^3P;g&#LuY_|D>@8!S+DqA*P<3nl}E^d5q9Ad&} z*c4=gFku@v?i;#gnCJ|e#^eH}DQplyy}ES~CbGwf;aqTl0tEsPaIm?&`5*v0OnDo_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/drunk.gif b/local/htdocs/img/mood/roshi/palefaces/drunk.gif new file mode 100755 index 0000000000000000000000000000000000000000..519de5431642006b5bb7613b749b8beeb537f13a GIT binary patch literal 821 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$d)O3GgraBpxO~~cU@|+&@5oIZeg27ugLbBDI)6v4cx8mlBDU6`V;bf!)|oeF zo|o1W5iSuc^OEWatVwASF=OBn7HSp~7nhhZvsPTJX>vce(Bu{|hFKB}2BPzXxRn+L z>oQE6Ic*bz;M(;8eCwU3MLyn8Lc&;Rbk??3N;2;38LD0sji&(O@i^1)$u0VgIw zPC1JV2f+(##YCk=YB&@Q9%18gGHSS%)Yv;g#6-3r=7GYKrs-Tsr>6Y8q{7U8flHty zvUpk3EHh5A3`Ye;r^}}rcTH%5zN|(BJFD^QnV>SO2dx_Uw13yKu5xO8F zm>HNDgc-PjM(8})#<(P7-is4!Q@xm!4$Rb!x^{c&JcD`fS4b9k=tz}sTAZmMBsWv~ zxuGT(BiH~ogaN`p10o)5D+C$9u_o24Xc5~CkO6aM0S(ZQE#O!aVK6h6EqUb(HIdU# zn;a9DiJfv`F^wvlwrrXjQ%r#P+yJGQb^ebyZ(mtv5iGj4<;45n{~N5G8e3|bF z%oUGoIa-c(C=0Jiwf>YKCX$vS;_GuUWLnWutJx>@i+uEEpMP?EL)X2Hfjz+-4AubK CV@DzY literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/ecstatic.gif b/local/htdocs/img/mood/roshi/palefaces/ecstatic.gif new file mode 100755 index 0000000000000000000000000000000000000000..74b0209f0d7779bfae26f3f404ea0e81ccd3aff9 GIT binary patch literal 577 zcmZ?wbhEHblw^=(*vtR||NsAg_3G8Wefyq0d$w)cwo|80-MV$_-o1O*u3fuy>5>7D zz^6~27A{=)=+PsfV#WX5ey$G~xYb_rv*preuueGJ;a^^Nh zB~2cOTX_wydz2)Z7#}~oW!Tgve^Bwv%sxIRAp-}68HXNr7K&J`QP6s%FuUM<%qa;$ zIT<0Lxhfw0{zB~qij33s8A=?@gz9TF8LI8-8XB7!>bW@EJIjiD`xqup=9(iSRU#!a zhif+5MD~*&Z|B|j>ixGj&)Il|d0Bb?Gca@g zdEP(!V6z}FXnwLVaxw5T=&&$wFbFd60DW%x!BXkQ?jMGZcdR*7Ic^#konZ8HsT7R; z#USpG#$;>nxoO+X8w-y|?^IcNr0`^p)%3RK%37r_XYAqto2HB~jSFa+#)n4Ed3z_N y38>w>yT#{VdT-3uh`a1-{5@OsUItF>oL%$&zk@elL??z*K$=a-aEcTogEassd*TED literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/embarrassed.gif b/local/htdocs/img/mood/roshi/palefaces/embarrassed.gif new file mode 100755 index 0000000000000000000000000000000000000000..b23c27f97ffebd0cdb5115182fa582d70609da1c GIT binary patch literal 685 zcmZ?wbhEHblw^=(IKlt||NsAg_UzfKSFi5fyLao>t#|LC>lk$BtcFwQAkEb;ph!`=+2UbLPy6GCHSDo%;6e+pk~04jnqg!ou>( z!{gY#eaE(KTexr`&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kx9DxdTfEegXNd^Yie+mp4DarFPys{RZ;3&{JZ**DDaozix z{T(eatB*^waV%|&c(8?ubJ>U&SI+cTWxzsY_! zpX*-!S@xU!SCzQ=1%!nKHcdNwb{4yUw6uWOwdc~Wq@Nu7_vn|}hr{iDvMiip`xpXd z1RUB^#s4Al#D#^-?RITEsS9o>9=0tOGBc7m*$~#vqGBwWGbKT{v1KA>lHLr@$!R`Q zcvLPdQh1npa<-}Xog+6VJ8^Sy+i1j|+OqNztDCXcTrX1=P%tubF~~FMurP2i2r{q% zgV9J~AxGQenv7QxO->>$20U)L(wjdVT0G%j(=~1fm2-8?N`j3KPNrFgH&$kJ)oE%z z5@5n+jN$|Ko&)LglxDJNS#45@S-3ogEiH7{5A*$Ng$t%AUFupYfK3-UmRkb=0N)4) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/energetic.gif b/local/htdocs/img/mood/roshi/palefaces/energetic.gif new file mode 100755 index 0000000000000000000000000000000000000000..dc62158ff8d0343463245bfa51a6f09a6a6058fe GIT binary patch literal 422 zcmV;X0a^Y>Nk%w1VHp4!0J8u900030|NqL$%G%o6zP`RN3=rz->eABE=H}+1p`rHn z_PV;dwzjs`*4D4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV6aWAKEC2ui02u%o000E*5XecZwFK$SJ0}wpjAUt^ zj5M5VJ4lD3RBR<5l3)Nb37Ef;3}6sQ92!HfB~%zR4hdl}Kp2!V1u5%%QbB+zmBP(Z zr~~k{Aqh;b@b;vUmMj`kM4g}cQ71`O&!`IvdjS~yu1P-hV;0x>w?(gsH<>!qF&Din_@C^Cb%?T3{Fi1eK zpuvL#2VPjna6$wCA^8LWEdUPyECm1w01p5Q000CZ@PY8EweyuqZ{1G-cHStF-kGj! Q>%MSY0WEz2HkL;KJFdN`oB#j- literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/enraged.gif b/local/htdocs/img/mood/roshi/palefaces/enraged.gif new file mode 100755 index 0000000000000000000000000000000000000000..f73741861299e91a5da769a97940d3c657379738 GIT binary patch literal 833 zcmZ?wbhEHblw^=(*v!cAp8*8^|NnpM)~#d5j=g&I>e8i4&z?QY%*@=kZ{Md+pU#~- zckSA>UAuN|+qMm;Qt>~xpKD04vtxj(k)8oFBS`3??yug`?z;LB-m z6(qYZ?Mn}k77Dx~d}m3R!WWbM6OU{W(cqFwRxp&1;j(A#zM|x`dO>EW*_xTTlM82@ zieOT?u_OABM2mEfS;GImWagUuN?xG~n?}Yu)`l8JHl7y7HlgZ*x+(d66I$8kig-jw ziOgl2$j8RrpDf3o%(H?`lW{rs%F@+R$;|7wZWQ9%y0>!sy2=#?HyvPMIk@E9+=HjN zPja8WcG}kV`lXYnIqxTmKj1ul_kj@SL}A|S`z)JyS?=?G;rsUe`xayX z+u?akO${8vRt^OV7arym1cnhX2v|Wuz{nuVAkM%H3<53zU=ZxJXkJj=fh^4rlx71; zi$J7bpLJ%CbFWOfS-W6nm>@_YBP#;sPh!SMRxcZ{~frx!+rpzZYKN z%*uMrgrb%es#Ze4iz8YzP%&a3yDv8wO-pYVdmNnqZ5ONp+eMTr-ru-b1pL1gJX zQH%878Hz^=eQqqB>7^)i(x7LulFjS~EAuYxigEud+LygR+MsG$Q&4A(K?jN{Fdyq| zF#NVkS0dVawn_BV%!LOlcqIBm{W-CFhX70F857?_Z#mu<2ng8S(_{CR5Z<@s(~O2r4)^#) Q3wcZ?G%6nyWMr@g0F3Glj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz+%@&#%7KOpGg5u3Ei{$zh4i z^02TqTQ@T@$%KV!a)oW$zGm|lrZ6te-Fkuo94srhth&I+!XY52x7%1;LWrA)5g_JAKyb3(za(c3$+>4%q%Uzv9 zwrSHG4qiOP!YQEQqtV6mLPuULXpTii156A!iYN7@H$@Njfu>EM&ni(n{q zbY>S&I_kMl|!Er|Z8$lT5+XIt~<$HASStK@Af zUK~(-yjoP%B;&z>dH2{SC@?TRWUjgWaKe0{!#avAg02#UEJ6Zmii#~BGKnsNE*u+M Pie$=OEEH{IV6X-Ny5MA~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/envious.gif b/local/htdocs/img/mood/roshi/palefaces/envious.gif new file mode 100755 index 0000000000000000000000000000000000000000..a1fa93b52e44e59ba0c7d71881f726c8201a51e6 GIT binary patch literal 852 zcmZ?wbhEHblw^=(*v!bl(8~Y>|Ns9#b?VfkM~`;x+I8#Jt#|LNF)wXThe*O9dRH^u%+s`#5*x50_)kx2P8E625;y+oZ(#)I^h4Rdj3E4Hm)vvb$(`Nt3LI?T+)b<~yd z!uhkzr_Y`h7rB1!@O9Sv_eCGvzrKc*>oF_u>o;#+zSwd0<*T=!&#qzQeEa*)Th5yd z%x=Ii0eYDYo3JeScs1ch<)#8v{Sc8cwJZ5rGr#tM^>JH}gK*-0!W)-y5H~ zd4Uze+`|f2=pmpr*C?R-_t#nKeNRFP?@FR7WP~c@H)sGl{L`zmyZL6CHwLpHI}D~q z!a&4n_1l7jlsX~ElD1RM14S{+X3YYFvL;c-jJdfMmlp`IJWYt6WvQ@I zqb*QwOL3Oj-D6&Y()0TL#Q%sYVe_E;h8bU1*-Aw3_R-|tYCF@c?S4}a|71g*O-o*% zxKnQ9j_f>GxM^-!Aep7ml9_YZ#kHB|MADpyuDQpIlzJ^DsLkH=*5lac7(G+53s)^&0fP!CApigX literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/exhausted.gif b/local/htdocs/img/mood/roshi/palefaces/exhausted.gif new file mode 100755 index 0000000000000000000000000000000000000000..4acf90a545857159d61c2fdc6c420202a5761b29 GIT binary patch literal 667 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkC_ph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^^~g++@eb|^@kXv^M1+%dCHwn(m4rn)xP^OUm6#bOOq|6qX9l;@biW02^7|#i zW-|y0FJV|Vi6LksniAKoM>D2~yy~8D`q}lT0s_zWe*O0Bli+nuL4N*E4D)RmIS$6RuqX+MlpHAV zpDD&G`^T9>;UIGxkCD-Yt4WP+Y&`M-F&`8jH%;c!4q6pbc}cmMeG}IYHWu+Ob zQm2OoUTsZ`%uWCN_0Z#~|E6E#c2F^^o9lM*Muu5>!19tVA1`OH3H%H)$R;Q%u=g;e p&r_ONre(EB#b&|sn6hU9yDZH2uN5wsqI9WisQ_4)4Mp}^0|0f~17ZLG literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/frustrated.gif b/local/htdocs/img/mood/roshi/palefaces/frustrated.gif new file mode 100755 index 0000000000000000000000000000000000000000..56dc7d1c9c5279d8c3c250e708fb41e5b086e65e GIT binary patch literal 860 zcmc(cTQ6Gy0Dw==>1j_-v9^?UsubH;Obn5l%LK!cy4Q&y%kZ*g9_B@Cu?uqzIuo&E zGIR(-meQf3XhU;K-EXP5)xGX17NW%FSM1C8{ylu5Peb_L$!vfPYyrUaKd-N^uC6XG zFO5dy#l^+>`T5z|+3D%&$;rv_@v*^RI668yJUl!&IN0Cc-`m^U-QC^U+0pCu+uPe) zTU(o(n;RP&>+9=lYip~kt2&)-Wo2b~d3kARX>oCJVPRo@eqO89&dtru&d$!v%uG*D zPfbltPEJltOpK3@kByCuj*gCujA%5P;o;$-p&_+ejpMjVr5YR@92gi-DwPU_qQAet zudlDSw^uHg_w@91cX!KVvaYVK&d$z`jt;3*+TPyY*x1<6&`?)bCl-rqYHF&ht1Buh zL?RKDN<~qWLZKiCLMD@87$y>l5CnlBNFWe^|BA~^{pJNgzWykTjfswmjEo2u6qg9X zBMPFTV`7Cu%*XOu74v&Fv#QDms|)}MO+TAkn!$j2PGhUI1>|6H&M4OYy8}a=Wv+A@ zhT~E-PNTcZJgis@DhUFy7CA(sGFVm~GA|C7%`ipDFcCT=!erEx!RB(jWPDp5S3^NS zl0Y&NRCtRo+Cd)Lv)xHF-XmWx`&?0~Z%CO0)Wzduvp|2HeiALB`-=WJCFi8#B05)H zqARa2V)zLw1EP<$L<-GOpnnO&W2ydvdVbqJm{()&loX#~pGUF9-`76>l9P+jY&?@B zz-~^ynO$&Mm=aWdZgo;7H1SuNxdmp{o@sg=??I9I{REjG$ znQ<7US-L%w#Eb1=)Z$*?hX`>BTx{hQFSMKr%r{}Vr6~MKpEA<4zY-B|uMN2Lw&InG zHCIk5wF=7ANYWi}m5uXP1FOLSH??*zPc-nL0yC~(*5x_DvG9%E`nyw|7%DJn#VRIh yv!S<{wwvR|sK+*V)*ZDAk4S&QN+&XqyJEYXFivtXJs4>ld~Jcf5Hqs@z~?XIrCquJ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/full.gif b/local/htdocs/img/mood/roshi/palefaces/full.gif new file mode 100755 index 0000000000000000000000000000000000000000..d99aec8742652a015371636e7c0672d17d2fb0c1 GIT binary patch literal 564 zcmV-40?YkJNk%w1VHp4!0K@~3^?d|RH@$vNZ^!obx z{{H>|0000000000A^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0?AWd&} zX=NZsWnpq4GA=d%A^8LVJOBUyEC2ui02u%o000I4AOHlUV4i472BOGVa4gR<(<)r9 z?|iR_l%8-%5k)eZmPn`sXfhGeQ9Us-f&SSMJ-4ggilI;6gB`16B0`;7?F{WA`%md3lfeTA_D-DlbisanhPSCQKFs~ zl2oby5fY{VsFVN~xVW~lvkMWwN-()FO1}}a3K0;o6M$s=2@nnr1HQV2E^zR1flCE2W5yh?z$60)vkLrc>2iTg z1wBdLbWorLfdmK;95`U0sZ*y*lO`ZAv8vUHApig&`2+z702}};1ONyC5da1N00lB2 zRasb;acG)hRz*#ebzN9(W3%gCIqFJ8QO{`~o~XV0EKefs3dlgE!AKYH}&;lqay z9z3{z|Ngyu_wL@kd*{xb+qZAuym|A+jT_glUAubq>Xj>3E?>TU>C&Z(7cXA8aN+#< z^XJZ;JA3x*nKNfjpFVx+)TxsvPo6k&;`s67M~@yoa^%S2!-o$ZJb2*1f&KgU@7uR; z@7}$8_Uzfcd-u+rJ9q5Zv3>jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{kS+hmv&J&qE+bVRLJrm=Km8({-VzOT%y?o8) z)lAZ%AsSrlo3?Ca=hE1rE5OgevNCk_sTC|7`~tc=jKsu4uV3GMtZiGlUdgSg@G6C)A`*VB=#cej!zdtd<80R9U8mdQEtcIO#}dd#H*_g@7Z|Ibq}V zUo{#J9Wmn;F7cX?kT{!DM71jBb72x|m!P6u!HI;0Od8yh7Bw7(Oh>zf?Uv0;n0Scg z8o%sLi;NQs8lBrWD*G%+X#94of3J2BgQ%hsOUGeFj@v#Po8GS0vJcx+u+hntOGMpo z#*I0Wu3VzpF?%9DT5xnr7{={sSorG}_x07Gi_-+3%n}ec&UmqGuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36j$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4? z@->@RGs%X9YH@Rf?cKY1-(C)GtsVM8VVo>0!&aYN!NM6Pq`$*hLQ<(j}@Bb)e%S(`Es2qm&~ZiK%7!x3*@U?|bXyv0l+2 Kg`$lN4AuaYE^EO6 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/groggy.gif b/local/htdocs/img/mood/roshi/palefaces/groggy.gif new file mode 100755 index 0000000000000000000000000000000000000000..a36b42716b7350ea0c8d4e6611154d2ff84af001 GIT binary patch literal 1005 zcmZ?wbhEHblw^=(IKlt|tgNh@oSgbW|EDoX^!4>knKEVGym^ZjEn2p0*``gKwr$(C zbLY;zd-qPAdhF1lLr0GuJ$drv*|TRaUc7kq>eU-JZrr_l_u<2bPoF-0`SRu4w{Jgw z{P^X|mtVhr{rmS1Xt?5kZa>$MU}whwS0ggL# z%v1&U)WjkMBRw+)#h)w;{0#C8Iw049+{wWDPl17DNy5AgFSbQD5^gY@E{M4waaphV zd3E!H_t&NQ#FS272#@*aV%MEv^uVF_@HGAnk{wEt49geCGS$s>R1+3FsW;O%{q>in z%@Q3i5;q<&l};`$la-N{k`%Ay*Ao*B(ruKP+@{OWCuYUKD=HG8E46Upd?gXlSv(^1 z57(wNsKL1 zd5ZLIoSdBQH-lF}z?ebs`T2R=bxf@p3tSmlIfWD)3KpyiT^+nwOG9AO>g($noPeSJ zlZ6o+sEiDZ4B`wTz(7rVpx!61#`kpPq~`_|@;-|+thPn+ zoeWb0ZnG|adDBd)=W^K0Fw-^bw;kG=U?gea*?cVG#G0cONvhBSk1riLMYRw6|3VjfR4YfkOXx6qUW>JUe+3GcN<1;4n8-_ z`r5H{?MH4d%9#iLI83?li7v0<$1lPAUhuta_m6oYY`W6uFEx85WYuf*Cf*IF&x-* IlVZ6w0P#4A<^TWy literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/grumpy.gif b/local/htdocs/img/mood/roshi/palefaces/grumpy.gif new file mode 100755 index 0000000000000000000000000000000000000000..335119ad0d9c7e8720fb9c4a97bcb171d058aaa7 GIT binary patch literal 418 zcmV;T0bTw_Nk%w1VHp4!0J8u900030|Nl%tMB3Wgva+)3>gv+c(&pyoy1Kf;!otqZ z&hql|%F4>t*4Dnhz5oCKA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV82|tPEC2ui02u%o000E)5XecZweIN6J9iTijAUt^ zgfyINJ4nVNwXC!l5>piN44A*kV#kmqG`!L8v>a*@#=+pQTP#@C-9ZWkIHWJ3b=*@) zLEb^bC)v5#fW`ogXsiPg0l>Wr0`ztW5_LFue|vm>dIk-G0EBRS1#pax2nLuGNLmLJ zm^u(=8h47;Dnn7hUb#0d$; z(m6TO4A9OJ1lQ1A7e?I-x!oWL4vrJ%f)3rS2ni172nYoA_V)AU?4i){`Skbx#e>$$ z)xCoV4}M$7FaiJ}`2+z$01p5x1^@*B4FC}U00bQH$sjAO65yw||6nMNWNDsgiZUU? MINb-pBM<=qJC8c7*#H0l literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/happy.gif b/local/htdocs/img/mood/roshi/palefaces/happy.gif new file mode 100755 index 0000000000000000000000000000000000000000..53b37a9b4e80209993939177f498db93741a9500 GIT binary patch literal 871 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#jYZQHhO-MV%2=FOWnZCbv3`O>9J7cXACaN)xF^XJc- zH*d<6DSdr?+}zw;TwI)-oE#h+?Ck8UtgI|7EX>TzOiWCSjEoEe4Rk;b0L29Z`~QaE zpuhlsKR;g|@9rLNAK!NWfWV;O;7}{^S+m9F&J&wG+bVRLJrm=Km8({-VzOT%yPPp} z%bJy2LRT=!hK6WybL?DkX!Vg$4sNZzdP1R`EZdK+WZ?`I(%Wk!At}tm#=L1Y6Eho+ zu%v|1UQ=0lDPcZtc2*YVZ!E0r+*e%weB_Ow=C1BI3lR_$G7ak=(aydO&Na00}+3D1&!fF*~ zOeQuZi*gAo`7B5tVi6b(AJkJ%@Dx4-fI z!A9ldy%GtlRc0DKb}Rd8yMsNR|8rqEbG_$-MJ@u)0)Z`p?k*iiS_I`1T?Act1Y3ko Om%ez|9?HVRU=0BLC~C3* literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/high.gif b/local/htdocs/img/mood/roshi/palefaces/high.gif new file mode 100755 index 0000000000000000000000000000000000000000..bff3498f0067a2b5f502a6e935133bbbe3b011b2 GIT binary patch literal 483 zcmZ?wbhEHblw^=(*vtR||NsBrwQJX{Teln-c-F03ckI})SFc`Ox^(H;vuEGFeLHvV z+_h`hX3m^>=+GgcV#WX5ey$1fcAl?KjE z3La|;wn-n5SR(nF>rU3e`-O}`jn&qT_6!_6^-XOpJqBF~9Fs*n!lXndb7XRGcP7bk zCh^RjJ&Ai>=>n-F<|QkZF)*!QSXr@lUB%q3+?m{LZX0GDp3BW}V6PDC{sYI)9=AMu zfQ_5=)B(Pm;vzTs4qRhkWxL7r^r`5xr#IOiFtNRSsrcdPdm-KfpMSnQz$?tl${@`l z<58e+fa&ix%@7Gjknb6}8Tc7=SQ$8h6bsPzf*)8vtlAnJR`hXOOnK{+j6gx`s`e_Z po;&RxPs;sxcY$bAJFKdNJ~Xy1Gg)BIT&tO4V}u=xN0 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/horny.gif b/local/htdocs/img/mood/roshi/palefaces/horny.gif new file mode 100755 index 0000000000000000000000000000000000000000..902797009c2b8330a84167fbc342ae8a92e7dacb GIT binary patch literal 493 zcmZ?wbhEHblw^=(*vtR||NsBLcJ11}efwU$dUfpBv1iYoEu1*@(xprH?%n(J>C>)V zyUv|Ew{6=t78VwuV#WX5ey$b<0<5;@!G+<+?-pySMJ;VP)OF_{^OBCwY#a zJjrn7s;$T6Q+rP`-%HGry3c&_&f|NNq`03y*~HEIf}5N7%h#`;UO$<{ewX>j=WqWi zy~`X9H?pw{X~mo{P&`y1pzOsWzz7ZoK~OO8GjK4l0U-m6aDZk~kkSsWge)Nzg|2xC h)0l)H>iALB@dq?=Ug8l+c<}Dcy_6IW7NX6v1^`@_uwwuK literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/hot.gif b/local/htdocs/img/mood/roshi/palefaces/hot.gif new file mode 100755 index 0000000000000000000000000000000000000000..7579818afed78a1c7d5e60fce9962012c1cd326a GIT binary patch literal 1001 zcmZ?wbhEHblw^=(c*Xz%tgNh@oSdhb7|t*;oMU0Q$i{e?oAC-4<1K#1>w-)-1exxN zGu@VCx+B4KPl@@y3iD-El`E<$7tBmA*;rk%wR)hy{79Gip+3tKZI&lGERPIWo?5ZI zFlTw~%<{^W<&_8PJ3rR9fh-@RSU$wCd`@NllFafYh51V=%hzn?Z&@tga+ts6u>2@w z`dP;GyOQxwCF8$ZhQq!-N4>l*x;kC-cD)$raVgyEa-8>-SntcJK37wGuV?#S&GEfn z?03Dy??#p1t$N>m9YIIBgU&|!-IWSvSgb4nD-GfOfQ+&$eCeDljP zQx)7(6N?m#^voC(f3h&>0u}0jd;y9_2KIjq3=E7dOl|EQoh^(_O~%3#CQh0dIN7+@ zNQfnnW$wH=EX;Ek%oQ|h5@icyWno>ne#6E&B26Z2+jp$mxqGKclPL#BZ__~zcJ_mZ z84j8@nQ=03U*hIs;JSYO+KsE+W=-Zie2@5epFVs3g4evsQtaJf{*MBm`9FNLXtI`+ zY6|R?U@%X3as9<1R@tVCk_QY2ZSap(C?5Qsu3MyI=D>`;H zwO$pC2u`@WOSE%=iteEaatp3pR< ztCh8@oo&|idEN6H5!x7m+Qb+*f!Ykg+JKr`g#rRQdRqjWSSNP3^z=?^Ve6aKJfkmw zeSXutjwMs)FI(QXa_-_qi?Etv1TiJBwY8n4qo<`kpue59WpYn VbIs@S&R^ckKYw+Aeb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nY@e}}Pzq%aQ~^8scy9$`rd z;~i$Q@>0Tl-0Z9@%%50T*}3_IrQ~JJc33DV*>MCgqaK0%c^KeHSr zE;21uAya2PIX z=@QdCQdi*nFp0HmgQ8u@Q5M6dDiYC6IpIKkcI-_Av@cf-RP zwsbHqX6+U|R%QEkX%cI3z^${)`m^F zu%I#7y+Yohf#v4>c-wwii!;kx^u0M8T?E}^8jm!2n(R;za+e5X5p>c~Jku(XR*|T{ GU=0AwkZD!` literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/hyper.gif b/local/htdocs/img/mood/roshi/palefaces/hyper.gif new file mode 100755 index 0000000000000000000000000000000000000000..ea5a47026bc65acc724382e47ca83b4b34fc9199 GIT binary patch literal 1121 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$WK(@>6S}%NcrkEi3TzW@$ukmdo^(#op5d&(`PnTc zqF1j8ojZSv>+aoc^Dn-e|MZo>3ju!qSEqg+e)a9M5~qNS1xKOEcC)u^Chb%VoH!+5O@ z&ESMaF%}^Ohk^$Ujf*`dipkDuIB;ZnfO;D+kdebsfu+2zJ=wNoJGcg3mwj4Jkmd$XCx#tvq?y?0KoC*!UuS?0SRIeh0e-qj;t+PuBmzTA`_2jZInkfdzY@+${IDf)kb-;005_3(hpiJpKbFbe>M0DFIb ze{XMZcXxMZXJ>nRduwZJb8~ZJV`F`NeQj;c>2$8HuCA=CEH5uFEiE}5j>W~rg@uLr z`T4oIx!KuSyWMWH*=A;DtX8YVVlkV|)6>&aQ&W?ZlM@pYCd8ySuBatFyDSqoc!UG#U(swzf9CUf*AqWCN5cq$cJD?9<0OT_ps&U<|g$1>zEi>&bAVq9g?VjgU~P z8^e>!xkRL8kS(APLdf)!T02jl!@<+VY=MN8CGj}hdxV~3sN#A@x)zbloiKX(cpee+ zL7&UTGYa@Ws_%=@0Pi6psYLw#lTUOC;U5ekl*8F2zb-p+-npN8ERsh*f!<=8s8YT& znMHFy7n4r|OR};tR*=YK0>xy8Z`W-(U}c73%v0@eewh-pvfYjaYJ5^d!X)+h8}>s* z(n2oXDug+UP^MM`fC{nCzk=^jjI70Ee=xct=LW`PKm9`%>s`@{1#NV!*E0bt4V z_3h(VUo07UO2~92(2e>%ljB$JZG^2)pK9nBL$qZ%C&hU8R>nBph^e|Ul PXc{Md-onfTfGht16r^jP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/indescribable.gif b/local/htdocs/img/mood/roshi/palefaces/indescribable.gif new file mode 100755 index 0000000000000000000000000000000000000000..e88f817e97ecb79ca0d2fcceb0f6d8bfe5315104 GIT binary patch literal 943 zcmV;g15o@&Nk%w1VHp4!0OkMy|NsB}{r&v>{QLX+`1ttt_V)Dj^z-xc^78WW@$vBR z@bB;M?(XjG?d|OB?Cb06>gww0>FMa`=;!C>=H}+*<>ln$W+}qpR+S=OL+1c3G*w@$B*4Eb5)z#G0)YH?`($dn=(b3S*(9h4$&d$!w z&CSfr%*)Hm%F4>g$;rsb$j8UW#l^+M#KgnH!@|PC!NI}6z`(!1zrMb{y}iA>yu7=+ zyScf!xVX5tx3{*owzajjv$M0Zva+$Uv9PePudlDJuCAx2r>3T+rKP2#qobjrp`V|h zo}QkXnwpuJnUs{2j*gCqh=_!Qgn)p6e}8{_dwX|xcXoDmb#--aZfNUaBpsljBammhjMdtb#``mJr$ap6rG+Fo0~m&mO=plsHv)}ssTcz8>g!W zNmf`)7_0yR8+dmr2nDhLQEYg}cywI@sR0EDD!wle4+hLp$6-M_T5)(`r~?KM5HG$o z78el-3dUEeHgtGA1PKur7Bs#%8yy%CO7N^fFhGF80b=lgVGsdBhYdJ<>F^Mu!v!N_ zwj40Pks}v8Vga-{4$dqXYPZbLrK#&N*x1`i@iknnNrhlvv_Ib^5+0fK`HWbn8_l7WNH6DEFCHIc%^hz}e8Fi?({7R!mam@y+p3>oH!M1f-7Jo*^qT@X1|1V#-T`0?M!f(Olw z|M}rp0}MsbHvVGj!KkOK}g6o>~9Gw8sB4?h4AL=Zv@VWJQt z0`Y?nJm@fkWOz(bLk&7K7$OiQo(P1BKJ=i&j8h;(1rbUx(S#FEBnib7l1V<{L=#LX RK?D`ZRB7dvSRNAy06U>DwXXmG literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/lazy.gif b/local/htdocs/img/mood/roshi/palefaces/lazy.gif new file mode 100755 index 0000000000000000000000000000000000000000..e4fc624c6d5cd74e0d1e88d0ba13a63a527200dd GIT binary patch literal 603 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$pa0d7?>}CB5xB)Ez{mH3bBdDd1Lg(+p$?CN4ULEG ze4}h~1OgNrSoma&Zk%X{>}Hjbv?xg^Y;5l3)(g^#I5{cRYXXmqfi{D{)6>(q;tsJy zEMRS9;Si9qNLa8UaItf( z!{gYtZ3`DJJa_IK&~U~7+m2<(VZJ3hth63cmSe znW+lysfk4jMtWupia%Kxbb$(WfEegXNd^Yie+mp4OOoehcx5d*!BL=d-srNPn4|d; zcJw;^np-Hy^szem3`J{)fMlVxEL->0zT zQ)=8^t{-|f4-PzZly`13@>x^CIR7XQkCV}Yt4@s`Y?6j1QNbS+mNZT0PC7N^=OvY9 z_AN>_8J3%#onbZ2eb;kA=};4&$7HS8t`f$;o`A((yo{hgWaMIyXV76`;9wABU;_rC zkwPPf>*bn^TOv$O5-kQiuDRlyKO9;-;a}4=ZU>cfbIGo!0c^QEF7 z6E^ C88Pqx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/mischievous.gif b/local/htdocs/img/mood/roshi/palefaces/mischievous.gif new file mode 100755 index 0000000000000000000000000000000000000000..7860c4c11b715609f62a2c1b71eb7fa6a3f92b4f GIT binary patch literal 433 zcmV;i0Z#r$Nk%w1VHp4!0J8u900030|Nqw3*1o>J>gwvo#>OxV5Yp1p=H}-1_V%Hn zp}M-d-rnBM&d#>Bwg3PCA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV9smFUEC2ui02u%o000E(5XecZwFBwRJ0Fu1jAUt^ zj>Md7%ScC(w6uIk1wmA7r588^fFK(IOviw1hX4WwjHpgl98nXxC z1_FU3Fwwc!lQegcK1vKj_l^y~rxy}*H+*<{dv^c_0)PO5a1w@(iHm^;mJ}Lp8WffX zj1C74ifK_DQE3992Ppuc4Wg)8vZ$e=tPZcQqo}-TwXe4g1qHdC#+JFm4Z*|10M5@i zK+VLr!vok{7uf^D*4)^P6AR$otP2I<3kweI?(Xa4-HZy?1M%$d_}Ie=6ABI#2pmYT zpum6^5-OY!0RSQS1OX@j4*)C!00RIM015yA1S~LsIfK2D0*N`^ACV+oX^jN)tgC6U bDl5-)ZP(kK%SKiAyA?3-^T~p=U<3d=nryC* literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/moody.gif b/local/htdocs/img/mood/roshi/palefaces/moody.gif new file mode 100755 index 0000000000000000000000000000000000000000..87a9ade7e997708d6d4dd9211fb2ffc666183faf GIT binary patch literal 485 zcmZ?wbhEHblw^=(*vtR||Ns9#b?VfuTesG&TW7(-^Xk>BOP4MkI&|pSvuEGFecQEb z*S>xGu3ft}bLLE-V#WX5ey$6e9iQZnato6O0v_Gn)e zlA|g=DS^R=bH@IOJP86G0#eTFRYN39IvyuXFwjWl61w(tjvHgo%j``@gN`VCSfI%1 zv*yFMC59gQQaR=e99rIgsj1LpD7R>+Eo^7!ZEh_Rsy^P|-JfL@m~V_Fpw@c8$Z zBI~QN(XTSz|39#x;K%PZI)Y&Bk`V38KMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGId-onbeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$H8O*vFgj{qb7$!~f(CzP0>d#=FJa5vRK4)%*(1qfVOSD6 zO=-pE3Eu0J)^AWUU|6w7S8$CISE!(na6_sggJ`F)&{2DaBLZn6qBk0y1q3f~2|TzX z^!UWn#}^(7+!NsEe|Yf2$A@oUDRBz$@x5jE{U;0bknR#>U3p-rnZs=F-yAosE(5^77W! z*4o4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LVHvj+tEC2ui02u%o000E;5CBK3y;#a&y8qxeXiZ?A zXsR|+p}ue-9Z8}AaB$a$LHy zG_`c?RxXSHgM~suk!4-|7Z0C!u00Dyi9JvumpgpG{{3W+^9jD$dzGm{$! zo;MwL9XFl_Zw&_wk_%>3A6cx5sw@Dg461ysVX$(kvl0!rw~~OY#(=WIw7~=f!llrj z!p#iJ49(3~R@+M0&dc7}hCboo%>(G@g6Zhkv;zd}0}b@`_44r&25dZ)o`2+z901p5x1ONyC5da1N00b$p6eCi4I45D`nnEa!T(NwU dk*!8&0x%q|LJTVkN{#MuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91kV{eAvKvm^DDc ztb)UEQA?MY=COtX--k)8T^khbDjsZTY;Nbz@m>(|P$_S{LQC`-53i;p9D)1%N5iAPptdP|NZ*Yg8M@I3=CZa-DDbFgm|eb7aFJHWP@%;JoXV0EJefsptlP8ZKKYsM+ z(Zh!iA3S()|Ni}Z_wL=jd-u+rJGXD&zIpTJjT<+vUAuPm>eVY(u3Wx+`O>9J7cXAC zaN)xF^XJcC(lE7cX46aQ^)H z^XAQ)GG$6%UmrI&Hy0NdCnqNd2M0SlJ1Z+I3kwS~Gcywt6C)!d!+-)EknNzjU||2> z5E2{|7~t>k=j+qm{Ek0|u*xY$yvu9g}O>Qzh*OJtX? z*}R%bHY`+&nPdURa4*v;N4bhe6d1JlDsPY%VkJvxp}?(5~${FcaQGB)|9oC%4tOk8x_TUgT| zYN3JRAr>yD;4g2UK5pR>VKxj=@LI^!)~FFO=flOz3GXMevq=*-S18M9Vn zp(FEgzK?bd44jAJ|5wRbKX8~YbWlf;MbK5EkVS|`?V&=mhfJc2pbN*wBMuU2D-_!r H85pbqgpp(o literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/refreshed.gif b/local/htdocs/img/mood/roshi/palefaces/refreshed.gif new file mode 100755 index 0000000000000000000000000000000000000000..d224ceed80a723780d4ddde211de783f67614b6a GIT binary patch literal 681 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBNa}rhIapXV1a;&9>meg2ef1 zx-w=zrVBVQwed=1q!_F|+SJPLmZc8%LXJC(|siw@7Ao)oHF&5n=)xBf=n!Y>dhS vww?oN^OR;X-RW5O)}rT5_PHF(8E?7Y%$Cx8ws@z9s&tVsM583-_FDr0wAKoz literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/relaxed.gif b/local/htdocs/img/mood/roshi/palefaces/relaxed.gif new file mode 100755 index 0000000000000000000000000000000000000000..5d20441e97d3ff9e3a285ef604cfbb31b08ea81a GIT binary patch literal 624 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$VxbS&DowU=)a`u^}NrfF!BBvyp@65P(hbK)o ze}{&!tFDJstG`!+h#3Qqu#l3klEmc66Lf`yySat>Co(fknL3YQ4!6?mz{TQILKX`O zEn`?QO-X#)wk-_nH*yQ^^D@|O;I&V1BbT7Sdf~<#BhiMwlY;gPCj?H-Xe<)Fa8c;w zsjFN!Zmgek=H;9RPX!(e@bf=C`eonKkMEQ?1^D zywX3MITQ{aV&gF~>bRQJ=*Gq)8xZqA;c?SsE}fuNA(fYunb|jTeKEdSw6tlO-fz(i zM+HVE7Ir=f39l&`7v^(v*uLmZc8%LXJC(|siw@7Ao)oHF&5n=*IgBvIsSQ(fZ y_<@*#l}|yTC?&G%K<26^+xF#hfNhdvkVaO*ub|$S!Z}B^k|~;diOlUb25SIRv+myj literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/relieved.gif b/local/htdocs/img/mood/roshi/palefaces/relieved.gif new file mode 100755 index 0000000000000000000000000000000000000000..6f70c4ae787e7b7ae892cc4e96fdce13fdc8fca5 GIT binary patch literal 775 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$PekFwzIj&Y}VaXUp%wA=a0f`AJ%o~Hd} zO*beg~tATWLY) z%BA8n#eJ7B2nwxbSU;N~>A=37ySW9A^%@*7=shO5n@dn&r*K=Lk!b6bi-PtH7X&WN zZ7UbOaZ~8xrMp}Y9_(Cr<>SH^Zv|cp@bkYt`{&r(pWj?m8Xg>Q+}9koMy4h}z=^4m zN7`e`jTJ{-I@#ozJRUeGHTUzBZH-`<#OT(`Z6s3@b0Dbk^mP5mNhuE!!W)~kQxAnG z6sH|z(&bQb0Gh@iu*)XRjiu`6J)7pnjhC=?m_8KfC>m>HNEgc$^Zq3Hi$Tj7$7 zc`D^hZ(eR{kl6ht`hJC9xY)F-l08e4W(DX>=RVfz8KogSabo()$hLsXJOzcZ+tfN! zqHGh@AAQ&o*63C8VMmSM{WDqRQE{)i7_r&m^k5q!$c};{pdE8o>@=ypTCwi(%2UhL zgxEWnc)S-sUa;&-Zqn?=;1m(vm2OD}-7=Zocjs34=uMWlG+7szJl_dytPPEwZVdne C$2y7t literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/rushed.gif b/local/htdocs/img/mood/roshi/palefaces/rushed.gif new file mode 100755 index 0000000000000000000000000000000000000000..07302380ac064b1776832e327e2dda4e03dfafd0 GIT binary patch literal 714 zcmZ?wbhEHblw^=(*vtR||NsBb^a*(O?Af+$+xG3-ck0xsTeoiAyLa!}wQH|ly?XTM z(WOh5K7IQ1?%g|}V#WX5ey$0YppLV*preuucc*9PPd1T z^42w13??nq_{1|~zh`p#30|>17vFD@(PMLUU~F`-lHwJ+wlE^VG3dxc)g!a2R~hao z@c5z9SMi6}L*_tBi?xCv!;|6~hPo**zvrtr)Wk(w?g zGKXh2+a&g6f0?)yoIJ~xE-On8<&I0rUB5wyg>B!asuhQ-*6nATa%|t?({oN9-*axC zrRBvFY^*oLMQ*U}J8`F-wN3F+(2eu$*B`OGdHe3&^J_QWe|hu#Mf=xZ?{EG6CkXN` zBP-CuIxGwv41x^2K<`?8So`qS?jNS+*Q`%0(D3_a@wh?efys>P7uNC@Fm|oH@pZDw z+VHfpA3viEPHIiev6_EjMTwWM*qrO$EMVg#QH|65(8xJ&@1$o7K0XoANSGeMIxV2` ng>l_oR)0y~Yp>V7uX+FfK*EFr%27&S-CU@;2i7rE3>j+xRI)9H literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/sad.gif b/local/htdocs/img/mood/roshi/palefaces/sad.gif new file mode 100755 index 0000000000000000000000000000000000000000..70b6ddaa456ce38e0402f97b5c9ce147695ae6d7 GIT binary patch literal 860 zcmc)HX-|>?0KoBwOHMTe>A?dKwWYQdX{nR)CT(eWV$I50HDBbWZ(3_Dk6LLuhDEOB zQqi1v)KXF(=LG{o1;sm^C!lyAc;YphpQ8U4_`Uewh~)VBKcoUwzz6_E0BEsTPEJma zkB^Uzjt&nG&1Uod{{G(H-p_V)JH)|Sa++Su4wUteEaTU%XSU0GRKUS3{WT3TFO zTv%8z8jbVw^K)}^27^Jb*Xwk;+1c5dnVIS7>8Yuy$;ruyiHY&?@v*V7(b3V7k&)ry z;h~|S!NI|Sfr0-1eyvv9*VotE+pE!N)M|B4PfvGucUM=JN~KaNl?sJIE|<$>GO1MB z+1c6A(b3-C-qzOE+S=OE(gHzHb8~Z3Q&VGOqeLQUXlSUas;aE4tf;6EiA1HPr6naL zLZOh)=i~8s91e%YVlfyD8jVJwP)H;afk43Fa2N~*{J$=o(x)!~v?VJcJ}x$f%e@^P zm0u7Qefxb(Y+QUo0*`(6Ycb_p38lE0%_|Cq!^G7!wKeeI@6J_ql3KVkFVPc^X%O>j zJFDRsyeD+gj>uE1B^ou+?jqy^Qb`0WMEehf6@f$reIQ?Fx&z4uk47O8n@AKIZ$omR zJNrWZ3?^Mmb_4ymGKnoSXfCNK6q)x_;}9XlWKglhfTCSSjQ;OsfX85iSee0I;2yD) zWRxqgpBU~zUp!#O&!ls&e)$xZ>+NwQ=B=_>@9@4Sfzje16Co5;M)pj3@h(J}M^|Tk zPZgCba?jANra%BrZe{Dj5poBZC_$ZvEV(X7cSV7=b-J3qx#^OIC3_`9_b6`Z`SzSh z0q9b0!YJ9i--4s%n*s_e<#$SbNcacx`H;-S`kZh)$hsR((?9xC0J0uS?^E79e>V2> z9^noL$+32nrm-DqlN@U>?1dJ}4!yyld6n*hjiG41qxZ)L2P{_=pLYE<0J96rJzy9z z&5QM}DncEvXjoi`cxk53Yc1TsYpP>+%_UYCk>ivdW{2?)dq8E=W<1eqe8oS3S! I&jx^if6+%~jsO4v literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/scared.gif b/local/htdocs/img/mood/roshi/palefaces/scared.gif new file mode 100755 index 0000000000000000000000000000000000000000..e75a2d1bce06cc8352dd448d65cb8e22869a6c34 GIT binary patch literal 407 zcmV;I0cie5Nk%w1VHp4!0J8u900030|Nl%dG}_wQuCA`?>gv+c(!#>R=H}+Qy1MrE z_Rh}E*4Ea(zP`%J$^ZZWA^!_bMO0HmK~P09E-(WD0000X{vASfX>4>LcWHEJAV*0? zAWd&}X=NZsWnpq4GA=d%A^8LV761SMEC2ui02u%o000E(5XecZwGHXbJ8x4GjAUt^ zi8PGW8MMJ5846(9B~Aj0AvuMDLg6|MgAU0-BP13_N6kSw7$AbfAt|c}BC1nBqbi$l zvlKE&JYYy(lA!!OVGPy@h8r#b$b&W#eR?SXc|Lr8e}Mpf1`LIVba9J}0FRLdniNc4 z2o#zInG26(9$!@q2Bf2;cBUF+ZL6#j2@ANcda`YLw78KA4i34Y#+tdq3xxy=2M5E^ zKR?k9&kF<+1lG^b7fRjG*#HFH4ImALA?OX=;|T}n3G?*z_U8x8&+_*D3HS%bkt0B` zpuvL&zbRZ80RSQS1OXNR4*)C$00{sO00aO41QHN{@T#>F2uW|<6WDno=UrI@06Qt8 BoKgS) literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/sick.gif b/local/htdocs/img/mood/roshi/palefaces/sick.gif new file mode 100755 index 0000000000000000000000000000000000000000..1d313ef7f9b187aca928947f11b506a342821eea GIT binary patch literal 1856 zcmchWSya8LI-}9XJcb+#W zIMBy8${yH*pTHX-(EyDBCPtY7Q%e9@0y8r+b3DM>0L$&biU@Fyz}gAez`)i8*tvqw zYLKzDsJL2891|1Igc9m35}1~kS=JPmbyB@ua)W(pmNdCY{{%*1>qrGS}I+>yXw-Y8=ym9vv8*eNCa$TD6`1wXD_7+obwtP)?U zl_Xa3QY$&vYxp;+I5%qqRAz5dorF>^zQzT$DD9mUcptTIpTYC$dyBICqMJ-*$ zt-OkR{F;uQnl@os=RhG_RLdE-%N;0dz(8wxF?-+sYQ!arkW1A=nb%OpTL0_vtY@BerySuxDyl$aDDC!YPI3kg#zrVjln${}KY*VJSE7Ch2WOd34 zI#pS0RW?Ufzh^wlmqaO$ z$VCHkv1GJPrs$O`CGtV8Vo)R-ZIX|)JRIXcoaCv-y46#B)u>1{A|9R^P*3xRv|W$1 zJ;O77!`gnCOr}&ShlYk8jXW5hkPnY5hBfMu(Z`yp!O_XbBij2T(~8kK#rV8(a&~y~ znR@c+BaLQcYpI0}&-*{!z=KALApEfr)e|i1O>wj-;LI-{*T28@|n{CexYPE+rNY3J!#i|Kn<03>*{_l?;1(9t6(+LK}|<0FO5bZ|(>{TL1xw zq;;As9kQ|B0f)ja6x^<3Rc`oG0e&0am*!O5dYGbP@Fi8p zm1aB$siny5LgT-L+W=vyBr%3^JLWNSg8l;FamiLr?cy%_#j>)0TDr}-~}Kp zUM;%PcG8iq*wD7C$14vaOHtW?g0;T@GLoxZB0)9M#3IYG=xjR?iC%#qNV+<`@|Px; zVEVjHcJD0r!edrgydM&UK2p6%hG^jZI~Qp__*gPbbvj3)V?3n`Q6O327hpXRkgim12eXHUhX&H8rf+SP8 zE<2hW5H`&v+no!SrCa&VQBYRC%hLPXoz7k0nmC0)CWLs%O-e&;Bk5LAmR?MN9C6ii%Tv1l0VdYkAKWtVTi>&MlP*;IBo_aj$tCy$6es?q}b zH3|#9`(xBG@C-qObk(wSq}lEa0@GQZu>oOX_mDu&SD0B7;KhOur@La0ytTejoqY|B zWu9h6$^y{PC?1E?MGRrKc}dO}N&)>E0`a^3|80{)zd1Rz!_4;EdeYxfx0FTRg(Z87tWijC_`lOw BL7M;o literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/silly.gif b/local/htdocs/img/mood/roshi/palefaces/silly.gif new file mode 100755 index 0000000000000000000000000000000000000000..38febb68674aad005e58b5d1273e81d5197a185f GIT binary patch literal 1030 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9z1yT=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l)2B~gzI^%h z>({@3|G)-=2*v;0ey$Y84jDbg3NQs$QNn-Nk{)r4i!d=`#eZEts`p)H6niDAF%^*G{WJLsn zpwJSAW!~$=ckI~awrQ#0elLTa244FGH**OJY!q(DHWIDxJtb(*a8ls(%!WeIi zoxa9(^XA66XJ5^I_)Or506+h;V_)|_`}AIkQ-F^z{?k4N0f~YI_8gqwYzrYc&7i}|z{$YRzyb_D;RnYUqcdkMj^I<@ zH7lq3*pi${irCd{D@@AlQ>$FoaARG*HBYu>K2~)i57=^2GW%{Ptjk=PCv*EylFs#L zu*Hyg1I4m9g9JF<4n(A6&QoL7hOjB%=&NI*u<_cK8lDn~htJ!ek2R3FKiRR||MqoVg za0}HrFtoJx_j30LdfPFGx46m76cm~&G~L%meED*_c?=7t3a)ohS)t;vUXU9YPYZ+# zW7R|pYIg~8?G)JES(qex@X+EDN4ZX1>^-%&ws+T+W57tdvhC6OEB6JsK#|1HaR2Q) zoA>Wt3vhA<@&4-n^NaV*_kBBVZhmo*sfp){rN@Q?2j_Y1==o}}jNy?SJ2%&wYL1DE z3_I8**Jv{|I54qr2=d7o9N3iVJykMXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1OLPCa($(4nJ8kDfev^6c5O7cXACdiCm!8#nIWz5DRt!>3Q5zI^%e?c2AXK7IP~ z<;$;MzyAIE2R55Q@jthpYe=xOV}PrXo&hr>P*m}stW#-bPKiQ!W=V#EyQiCiZ+=;3 zs)BoJVv&N8o*9GUPZkCaph6vx5g>Omu>MnEU|EtdFT;y%(TSJ>o%2SQwPM%3uUX$Q zbzVV)pr^@fzw8wvrDjr{98CuqEG(bO6)y+)A^978gwp zTP!5JjA6yJxXdsHUxxJ?xrKyyJ9x!2#SiH6?%T*EB*?&f{($kh3k-rn_6(;5&+6uj z-Oum1eO-y`_TxD-L|*sLIrIF+GXa6;`@VgD{#oz_ryxK7X9gA#3)VAx>IH>5JQyA} zHn-OaC^o%dSm4CKDPxszV4~w1F>WiPiXRUiHL=SWh_47auqoAhs-mP#N9coiuNiux z2YP<4ci?8?6i~1zIM8r$v3n<%uY<#)%gX~8TY!Q5lZBCkL6$)W6qJGtY``$oO-PNM zxvVr}RqFK6z^ko^k-6!gzaDx#_22Ys+zu*cb#vV=-pDXZ4_IE(<>TcHH9-d11Vsh* r9)|RJN;Au}tTw6GELa{>_AFqRh57!q!Ua>5E_E#x0PFIm$X;szv^xkW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/surprised.gif b/local/htdocs/img/mood/roshi/palefaces/surprised.gif new file mode 100755 index 0000000000000000000000000000000000000000..be69df1fa2c3d4f87ed532a0a232fd273938c290 GIT binary patch literal 675 zcmZ?wbhEHblw^=(IKlt|tgNh@oSf4bB>MXLrc9YKZ{EB`ixw?gwrta;P209@+qrY+ z-o1Md9XfRM=+ToWPo6z{_Tt5hSFc{ZdGqGoyLTTxeE9U~)0Zz_zJ2@l({@3|G)-=2*v;0ey$Y84jDbg3$Xi!p;>3O>A>l4=p*|TUW`;?V=P=Bh#jP|maM3*RNg=Bk z1cjC{teCjhndz_j?)aH1OIlxS2~(V54wDwvlLk?hv|Pn>RPkI{RwY!)F3d1o-)%9s9cf*{AnPoC17&pBR>UF#b3o-@@{n%Piu?a!>9y z-hYZL6Am17Vv~?OleJMnxw(~3O|PJ#u+fuMLo0Zh$<2w4&5^8srlzb6Vmv+VAJ-Oz z2@H%)%!HO{|4qBb?Vxh5Zn{#S(!-N!me*S(GrQ_ESE>jxfsNs3kVZB}@c~=U zfwXx_GmEsWHmTSwSRPaKEMV6Uv;Av@3#KSt>RKuQ)};&5#mvCWAPj^ItcE~ckAb>4 yJ7R9H(|E8?d{?1a-?g&${|_uE@X(R!Ke41JQ)g=1h7}twZU~&|bV;9u!5RQ5Bnt=t literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/thirsty.gif b/local/htdocs/img/mood/roshi/palefaces/thirsty.gif new file mode 100755 index 0000000000000000000000000000000000000000..d0fe339de6f899c8607ec23a100870af667eeff4 GIT binary patch literal 597 zcmZ?wbhEHblw^=(IKlt|tgNh@oSb%x|4(C(==thiz&5@E?)3=x2{yy-3 zpI^at0p5C#CmWO|Wtbg$vhn)O3>75~w#!0+m9YoP6sls5NS)(rNGZ3FdiPYZC`3!l z=h?}?_rJmJ5_HYXc?h@$~Gi|vld`ZZa z;iBN>`JEMFEgjP?UB1Wt@Zqk-S3fPj{Z8D62%Ck}hpdANDb1by#%4wp43ip9vl=8HD~a56kU5Tx zXWJ6ZV#c$x*m$>SEKqP{V&UM^h}|W!GLV&3$7^nuAqyxN8ATXm7<3pJ7#YMFSb@PP zub|#{=O}N=s(DGCC#Nqkemv&#%2#y)BwrfN_JYM~s0Ts7D#7=dmka%BfQ2 gRqN(hZ_0@}{N(SkVyhF@f&msaqRp$6)ma#<0e$7}*8l(j literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/roshi/palefaces/thoughtful.gif b/local/htdocs/img/mood/roshi/palefaces/thoughtful.gif new file mode 100755 index 0000000000000000000000000000000000000000..3550c5d490e45910edf40fdbfe2c2c031d6d386b GIT binary patch literal 863 zcmZ?wbhEHblw^=(c*ejmjX~o7|Nnpg{{8dk&+p&AfBpLPuU@@+`SRt97cZVafBx**v!_p=K6&!w@#Dvj z9zA;a@Zp085ANT;fA8MCyLa#2xpU|C?b|nR-n?<+#g36jCr+F=e*E~+qeqV%Idb^$;e!Vc9yoAd z|Ni~^_U+rdckiA(dv@>My>sWz9Xobx-@bj@wryLtZr!|j^QKLkmM>qvbm`K?ix)3k zxN!db`Sa$@n=)leUtb?LH#Zj-7bhnt2L}f`J3A{YD+>z?Gcz+26B8pNBg4P}9gx+a zxL{!a-w+xS926K3;P2<#-Q(-$-yRqg91?Bg zv+)Q^N|@|2mz9?i=Hq5(Wnuor!phFgCoCl|Yre};LCLOU_acQx$7U|JIsrx{_qDQ0 z9wpLcOB-Fgg|jCLY+M}1FQmGT;YTU!q2|c~E|YW|7rE=otNE?iV#?d(o2r~S&*0(X zrJW*@>jP#8Br>%w(5$%jtI&zHt5HIWXK4WAVFwW{zdtKjRb076Roz-XY+yXh8X#d- z!C|mM5xAW(CFNk=kl($x)C3=mASJM#=!3pjr|8_2N zy&E3hw55Y_F>AM|R?rd$$EYn`qB>CrIxaGO77#a1JJO+;T((wXd*=DRw@DtlN(Nas zBWEx$Bc(fiWGuU@@+`SRt97cZVafBx**v!_p=K6&!w(W6HX zA3l8W;KBX-_wU`iclYkyJ9qBfzJ2@V&6_uF+_-k_+SRL9uUxru`SRsUmo8nrc=5u8 z3+Klj*|TTQoH=v)^yyQlPMth?^2CV~$B!RBdi3a#BS#J&K78=t!2<^l?BBnC z-@bi&_wL=ZXV324yLax~xnswU?c29++qP}%)~%a2Z{DFev`=H}+&;^O4wx_f+l{n`TpgMvds!mPz-%@&(GPi*#V>#%7KOpGg5u3Ei{$zh4i z@->@RGs%R7YI1XI3Jcr3Zv_(vx8@E#A;Eq78PBXdb6QYHZ-=o&m@p3;^QNuLY&^nY z62?2sWaK1;`MB9xS(rbvu(EUW2}{b!nC-BTSCpF;88~4^a&LBusMY-V)!5|9C8Xp~a-rcNlLn8JRfB+| z5-Yce{o!qkG8R5!i4c&p%DJ#%VRQRd6~7f3jMv2{9MlO>kTrC2={T+=@jK*T(>rZ# zhlm3e2a{U6L^J~CNXS~Xc8Ti59Y`pQ^x&2>N;uG=cw3z3_U6>Xd5TA_PY^fB;t=<^ zGyQ{X2bW3+4*HH zQZlwKYGLD*xqR}s!}@#f)vqmXEI(r8&Ee=G=qA&6q{-7{hk}s1L?DZxlTP5BRtYh2 H4hCxgy%}m2 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/accomplished_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/accomplished_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..3ff1d4fdcdf98a748db973a1d231473f5f860d08 GIT binary patch literal 1159 zcmZ?wbhEHbG-5Df_|5*|3S|NH+@Fd72GJp^<> zIRKOw7&!hh2y)1HY*=uxnL}7B=ER1DhuZ~|z2B2}7ku21bsOFC0Nn zPPEHA&vS_^dg?quFP^Q#bF=c9S={-L?(E#q;6I|k5VkIAN5Jh}e}7$g z9>>`5kx6VpxX%53RjdzmwGZgs-IdSiaZFp1A$Uvs!Fjq0kqe%#nk&d~V@~9vTNmap zToiZv`tJSOY+aAAojgRZc`HP{!NL<)l^DY(0C29%gbwHyW?1HU)2g+7u#DTD{$b=IfjI#e!AQTa__D!GQP$Va5e4rigMd` zrIF$<;`cE#<;!p_$ZObNciXIQ)^sJGHF@i$1a41S5Wcxc+g{}N%~c_cb7aqn9FQta zo41yg!{_XTtb;fFlf}323KqYZzowCmf7k3EFP851&i>Z(=f~MOhg%n)yBYKK^X*OM z+@dFDRfRn-+HGkrVn1Q~*XK{mEFVoq#Wc(`3a*=vr+#zjZFC5*G~oY=Vdc)x;k zmyGA8B_}6q1h0yzSde}B7!RE26?T@|x<*PUBeUtgb}xZbMv#-^NWn>|k_nM!@ry|W|s z`lhE@-}Ub86u+Iu%J4w%;oJ!R92p)5$A{}%WV7F%_+gN8s8v+|TjtL-Pd7@$`+Yqf z(ipdmg@Z%2H!LCRtZ?eSw7Di*18(>iYJ2$JHamEkbMq^^39}B|e6)+3BSLRMgERAm z#qQrvMyG$Bc0p7l{oLK1PRxvlO1kCkrE-2SGVfR&|L$)B12gBb)9QJ1UcCPJ^7`uh zc!52CKCWzCeueQNs{}*UuhQ>xOD--w_Mn+pD50T@^HY0p(C(FD6Z3Cxe10KtU*Hqz u0`^8Rsm_Bh#b$R29#xsx-MI4Wl%9p1t&6;qGFcusFyCui#Kg$RU=09t?yBYh literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/awake_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/awake_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..0d18feeff08fab936612da2ffd4a7a0a5f8bc0a1 GIT binary patch literal 1122 zcmZ?wbhEHbG-5Df_|5mwFd|Hm@f@MA}df7rdA}208H`j*s*&og;N@r(SB`a<1G|@ORgPHAzidU#Z$V#TN zZ(FKDwXUv;S-k7ct*fuE&re)$ReNJo&b7^+r;|*jzUkiC5qo{p)2#1$_jZckPGe+QeqAmhMt(Jnk`c$k@tL~M7-bE(_0$iwlOkssP={>WE~Yr z-Iq4kWNW|;!RBSla%Vqy*%DdE?JN60r|{u2Q|m99cb@0XJ>Sgce$FWK;KhXX(doPI ze*ZjwJ+H^DrRzTEe!b_F`2Ab%=gi-Yuf>n~`^oM2`jhwZe=&I(dzUX?8Moh$W84(- lporZ_WU>o4+p=rH{B3I28uU81N@l!VT7J8Mm4$`D8URODnf(9& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/backflip_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/backflip_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9889cf4671e97dc73434edfa56f8e16913791ff5 GIT binary patch literal 6440 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/blank_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/blank_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d924df801a0b7afcec8f8954a60536fede84ea26 GIT binary patch literal 1097 zcmZ?wbhEHbG-5Df_|Cv^?AWpIJzn2?&VAon{r~^>|D#|u1V&N_=r8~QC@(N@{A1wc zknz~C;9xU{uvW~84GRyq3n+Wd@z}WNXt#uM)}0d@7a#9eaPE@v+_dE6WR2ieF_wl6 z-qX3_5518{XgE8aE&i5_KttNuxi+bX7$$w!5*PSbMv? z;99RUr@d-VahCs@v`#xVosYWFtEXvq?d7>@^t8=@{q)m0CJh-3EJv)CL*s}?OGSg7L_HqV KaZn~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/boggle_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/boggle_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..3723b56463dbc0db07195916e5e3276d911ef23a GIT binary patch literal 426 zcmZ?wbhEHbG-5DfSj5Hv1jmjY``+XAz31Hbt=0ekfBz2#ivPL&TtkAL9RpmA^bD98 zf$9{0varfAurug@G=a1;F#n3!b?2YKDbLk=Enc79{XapYFC}wc#;SEWulE(`oS&U= z`%>?8rib_YX7?*R_}b<&S74{G?8FN%HoU0uT5qqlV*3%l+#{fQUBe1u#F`>4)ZHi}?jK$=s{nfK)N|u+z zEtbt%5)s9iC2q~QVNG7}Mnw@>Mj67w3@a+B* z$JaPs5p$opVY?UCy^9M4@9;bld9nTQ?X$1MUhS~lwN3Ub>!;68q#R6tulry0mD}ut z$ef1#d~F*h_aE%FOj@BaQ)6R73ky^O$ zxH)7zHY_;U%pt55b7I57!|ejfUUNJ)E;`yRVVrg6#Ky(P`xTtKWIQ)5IXPJ)cvXyL zV1xH`uJ}W5G!h!lPG^h1C8N-gc6P2!>MItj;K%+8JSM+;lNsXBz@Rr(sr2WT7e{CL zFZ5EKHFf#LHBsB|v78oJe0f#U&al5+Uo)cSW$(Yn!r-72yCb!iZ$b2ebwT?|KfhX9 z{artCz4XO*U$wV>xY^^+?NYmYOL|H-Bgd}V+2+PaPcxY>fBVK#>BWUbOQUoPZY4G_ zF69=OVH>UW_9jdG@w^{b($els&VDb#Cv2X5W4HLeZ@vyjSsRV3g(CQ*l}cBfbLM8Z z+O2c>^|jg<{*lpr*r)KTmFXV;71_8w4oppgUgkHVEdTz#d5}FJ@AXFZ zsN$cRU*f{%{}q#R`M5FcfpY@ujSG>&K|6xm{`@_%FnizE literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/cranky_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/cranky_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..ed74e0dbcc21c9b9dd1b82a3e3a30c8a1fc53b71 GIT binary patch literal 1112 zcmZ?wbhEHbG-5Df_|5wC|+?^~6<`7kEs5_a^hpic8DQXC|$& z6nPai-Db9sM!3X6 zR6RVyxPg5|n3sat8|I|I>0%kbSH5iuvHhQtD{L0<*s)Q)zM{k+Y{kym&Qthgeiq)e zobIVjmHCP% fxTgGd4``I!sT%L6w|1#$u#+pt!v;=P76xkonf#34 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/crazy_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/crazy_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..aacc452f730251a8d33869fe4c4aef2cd4704510 GIT binary patch literal 1124 zcmZ?wbhEHbG-5Df_|5($?x7|epzv8x%tebHI^c;f~MQd z=8`Zt@bdE7*zP!%+gG&$*Twc0t>t8BxVp{edfpwa1-daynQmWNnt44hh@tXp)tcL8 z@9*zpSdw-na>s$o`y55XTROkKOWr<3)jQK|{{X%^cUawR&G@ zh~3S4)JUU3e7*N>4yNC(73Ky_2SpjB?Rp{-9v_+h)GGv$ix|UhBO+uE%QYv-YxF?i;q%+Z%4p&40X3H^D4}abx`9Fx~|} z-#laB>lfP>xux+L(_-gi`xqKZUkQ2dD89b0Vo&DEN4u@>ue00rX;$mP_4@krKUSYy z&*)tLPDcMn8=HVbL-Mh;%jPtEcYPw>#M-8|AeqzZ%8UkHsc#9ff<_@xO^iW1W;L)B zRNO0QN|czv)3YeB-LCNJIXe-DfH>@vUubm9#!_BLFeC!#7+mH zlNVZfL+RcCoO{$OBbc)^F6 PnoA}K6iEs&FjxZshM2fJ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/crying_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/crying_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b355c335fef6a4ef22087e9e44378ef894a29f6 GIT binary patch literal 1102 zcmZ?wbhEHbG-5Df_|Cx466MtL|NqwNsAI>Deed!5-gEBz*6RQNzyBWvqaiQ?LO_QB z2tav(f#V+oKZlIRh6M+kIfS)hPHb3sxLrWmYmUdpMMt|OjI-{X*tqz3zk+j@jOV5$ zCnswJuZppp*x)^#EB??Mj{^;7r?bW1GI3}~J3H4V^%aX%@MHf49+Tg_$^5e7(sJ{e zNoy=cUIk6JnJuIdaNy7e!DxneVCW|j<-uKE8m;V75;g6eoy%3X_^7M z-mf{IFSKRfgx@J|4oozu&Oc#W;*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdG2}uC9t%yz9=btFN!mPh4+Rdt=k<28M$3hj=H5t-iQ{@mvsZK$&jzx=2P2 zJ8g*rep{Ihw#f$EXh>Yt%NQZM+OXi^aeIAfzdIL;5?9UInkVz?XLjZ(@p!+h-DVr( zw=uDBq{fCOuy|>J_#35(lj`?in0<+7{-e-wdKVx;L{NwtKtR~`rucv)l!#Yo1 z{J<84&kuDbhgBV~Gt;R2z;#}_#P933s*gEq#a-4-G5+-AlWY=yU43Fb^BG&!d-c3u zm*1&6Bgi3G`(kPNgLqz}FAG`(U$slMh`w5WEm&Gh?OL;5XQ*WA*Q@MzS{NA_tN|Q3 BmsJ1& literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/cynical_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/cynical_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..89395f50491496af56e8675fe71d1818deeddcc1 GIT binary patch literal 1106 zcmZ?wbhEHbG-5Df_|5wC|+?^~6<`7kEs5_a^hpic8DQXC|$A zdC8$+HRA%drMIRyG_Hxt7t?4kUVMF{-`07m*&?|SOVXG6ss5gp5xAI%fx&{op@CsR z-Pcc|3fEUK?yZ`y#CBlv;|oUu6sPay*qn8D1^c^gDl^R1+&LuhzAWstWXa)~%t8DT zYo|24x-!#O|B2U!ua~d0X4-H0^D{kb!T#oFV*9Ey^RCUXl-92^PA_<{x>&FLhp@?; z8%C^g;rC|jyz`d(phfySzq>nrv^_9A|IF$@Qg!32>!+t#SSHo{{=D+~^?Lg+5!-hE bogUwi^40u;cSh;aDFHlsJLH`h85yhrHhYp@ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/determined_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/determined_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6452736070be681d7b9adaa18bee0f335a8fdfbb GIT binary patch literal 1111 zcmZ?wbhEHbG-5Df_|529%gbwHyW?1HU)2g+7u#DTD{$b=IfjI#e!AQTa__D!GQP%gz&ta0cFp^$ zJKP5xVi(l^lsdPoFylT$eXf(<1@nx!E`yD`_GUTccsIqJJ+=2wKu*T$Al8a9i{OUr ztFtTji76DAI`9zxx>@1S9{+ bx-5vxei%O6J3I5}lmG!cjRYq~Mh0sDyqb{e literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/devious_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/devious_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..e2d26c94968fb503e65cb6f43f09e064fa0c5e16 GIT binary patch literal 1117 zcmZ?wbhEHbG-5Df_|5RZa5fB18pd0|o z3k)3p82CA4JT@#i*vuiU6?0<4!o%$X%3gCkHZD5aEn%E>=fuXv$NLqWyJS2!Ejc+^ zBY0Jf#RAns)0kZj=?Hv&z%WbCcAL%tWA%e`ZL{-OP6?}@ndw?sv}fj)m6w+|84A^U znXWiC+heuZT*<3SK1|F^EEl{cGepc6XP?1(x_C|4*0kMWEvLV%j9yXL-Xxm6eQosC zqRUJYIS&rp-PX(~!Y5#n+i-;8jnlH7A}Uz*;v%jKW=`|9`I&r9#!-#cH?rz?Z; m#(nSqt|e1KvUxegBP1`1F7VZTdNrZ(RcOTJMjloc25SKKqmXw1 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/dirty_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/dirty_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..cf06bf7c92fdf27b97f9d9682fa48d6cebd4fd74 GIT binary patch literal 1171 zcmZ?wbhEHbG-5Df_|5i~>WZ^` zUKXgHZq(RWd;5&)A=vmH+;`C#4Set&i%rI`a$mFao#w#F_8PsUiD_5GeG2{F) z+iEYadidtzl*Ee1`T(5sEm51TLwS#jft~&e2*dd*H-f}Zr-iBQF zb8~~a<797dJ+@+5>iK25CYz4T^|p^*_UiXT21cd@T=MUvEMMNAIoJE{?mrbp%tuA- zTFpX<@i*$@!;NkA{dK>B|Gm~_S>Sk$ z_nA!NFG=+&jt>&2Pj%oG`V!Z0OV=Wxg*)+tTq`H4iX-?7gWodO~H@X7)<#bWQHDx~G;L=8$$R*qM=$!5RSaFr~== literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/drunk_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/drunk_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..11bf75c2d34ffd0277fe0ff18c7e8901d1bc5a0e GIT binary patch literal 1155 zcmZ?wbhEHbG-5Df_|5mEFVoq#Wc(`3a*=vr+#zjZFnHdwNtPo5*-pgmtCBhk` zcyf}k|Du?aMGH?&Qxn|N@^a#`v$HL-pY>Q4FZY?x)WjC5QS!ozk!2E>sfLLrBcuC7 ztJZ<0IHBq~}LVt-W2dz%t%T~)3cA$YV@#wDB?yrwxc4V&K*E;)a z?wviwr)M4YW^jmNXuHdGuR~;`+eRb7&9+fDHbxxp42+s;GwpNG=78%~x(*FnUS7%) zyfRlK;`Phx;hcJH5#d@nH@s5M=k16pja%%t4B^IYyLM77FZW^T-Md+&Gq_4hYdmP^IUH0=3&hizkcYhA#rZ@)ft3)>_dIKcSV z$Mm>#0Rz{O`Sq-G%>(jX1j8RVu>YB!Q2RYlV@4DA-0w489=WQ-xAKS{eb^>?mvvE2 c^<0TX@jPNGQ{r=LP4Cy-oH!%Efq}sq0Bl^Jsd|LFf#dbtaTy}1*4ePT%oL7|2&ag^W+S+NNabyMy#}5^+ zQiqV0%w^xURE1`pWe7RQ^!8Ozb~qE`rJ%pFzUhQ*4rfk@{ax(Pu-R{Z(O0kOFYc|V zl;6e@!_bhptBvu^9;t}+A%~eng29%gbwHyW?1HU)2g+7u#F(HA`&Gm6fTCCu+6C8P0E!$v!2TA^tLsx$M4_ zZh&~fr9+LMlh#^a*MGdAN%K(5ogW|WoSdk{N1lB$_sT`!*AvH5Au}^ z0Llvt9RC;uIb=LGEI8QAA*>a1V#C72?E=bPb38UKI@&E^oOS2K#>L0`6`Z?dJU1;l zIawokRZYYK)kD)*T@Kj@d`@7TrDwa%=76#K!MV2Cc`T=d)z8dyEiBqIbIZ!hOPmaa zYQ0QX9GmU2T5PW5RV5#0RyLjsUY8jn=8JRBU_D*DCTwfk?y#2AUsgu1C~R*M&ECE? zdTY^TCIJNo$A;ax?BaGZ7H=62wY+r_b0~g!?l_Zx`cWG(H8&@x zyth4fxKNxdb}u{e^D$owmmlw4eb4UR&+G^82ldlu?N#`@@SXIg{Zaqb!%hoU uPMg>uw9s{8BdgGfNlonQuEv-1@kxj`-P$_kdIQt3<%z!TrXm6i4AuaCrig|B literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/exanimate_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/exanimate_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..a3dfbcbd18d4b9c92c076b978c33b237994dfffd GIT binary patch literal 1141 zcmZ?wbhEHbG-5Df_|Cv!XlQus*sT|n7uj>pDDN4q7Av+kVOxcGR# zf^(OQ=cXkmCu;<+im|-d;60ry{?MC@2MuSZv&G-CNoYtrJJ%-l6^m8yWB&ynli$6` z{IcTGa`Tx;rC4*#_98&IKH$8FfcPpENEJ2_+xhM3P+FINkVEaiLDQowkqaJ`CSuj<>vaZ U&`q4H@~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/full_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/full_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..a1a5c3aed148fcc0da7fe761c81b3c3e48a33420 GIT binary patch literal 1048 zcmZ?wbhEHbG-5Df_|5rib^&FtIUXAq9qpDd&bo7A-pO?LyUT3LCbsyWJf3QBOu7 zAwPb988_EbO@*w(495J*ebEUo7#MqH^?4Y|-^VO3T>h`+M5V%$^PbMleG#|5gscm^ znw9qVS7ydd$?V;_tE$WH-CJB;ZyP11>3e&h^0_lUcivxo!mpp~_Ir=jvtttdPFLhM LTOV#RZa5fB18pd0|o z3k)3p82CA4JT@#i*vuiUD7U#mBNHnNf1Qlw`hZgtMIX1yMCzw7F`De>b-4NA;TZ;(<#jo; zGNTxz*+1~EEqk1`etquwFz)IDZ&#HwF5z>C)-7Z{#Jzo;=d_J4j-oa>Ff`s%R?^F;+wgNkud~&1J9C@Z-=zm>8*hu|hK4ps!f&+O#9Ufq}sq0NstAn*aa+ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/giggly_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/giggly_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..9204c690ef92b92d4078308803b2a2801aa02e0f GIT binary patch literal 1146 zcmZ?wbhEHbG-5Df_|5RZa5fB18pd0|o z3k)3p82CA4JT@#i*vuiU6?0<4!o%$X%3gCkHZD5aEn%E>=fuXv$NLqWyJS2!Ejc+^ zBY0Je#e&q+ZF=!(IgtyN`LyU|i|vSQBYz z^;=m(#P{Aw`?7|0UBdM}a#MB{P4ncQv~Jhk-S@w|I% literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/gloomy_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/gloomy_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d22e0d47186ec5346b8c537f992b586688cb4f57 GIT binary patch literal 1215 zcmZ?wbhEHbG-5Df_|5cx+g3u$e)W?Q;(?0SbiL?lA_bQoAL&)kJap%zaf91DhvZW#3BgK!Gn^ac zR9{VgdSZ&ld@j%tpWO?y>yLaI}Uy z-KK`&bJDpLf8~DoROvTeUmm<%kN5W0Bvyu^)5q4%-uB{RS21%0gTmH=M@#G9Kh?dn zpdzJetlWRxvk$KKB3~r z#KqUkcSKY+{{R1$?LqygSoXk*RzZolhS`Q5l8xM7!sj_{lnrR8dA~3$o>5e8M`Wd# z*o0g43Ux0QHnKQ+%qkZU>qv55?pmJcY%FGx=p@S(qTI{&cKd{s{cm4Pm|*wMV*Ui1 wTj44_oIxcIC-JY%m{%@#aoLT=^|3!?a{_ji&zyF@a{HqhNkJ*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdJlyG^`KFuH(HR`nq9lEOQF)?_!3V>-^-mwd|gzdwEmg)1s+a(_h?MQ7L=w zDfa?{+lLs+;&|7DXC*dvcG{US99VU_H&WgG-^$4B<7cMudh^Zwp_4YN!?oCt_sW-} z(^rIgoAKN>J<7<$!tpjbG$HS{VCuhTZ_T#{JZNfst`>LM!tt1eE&q|dHaU5W2R19E z@4U9{{HwF9(FVFJYO4?Jy7{_|x9eYKQ1g|Q|Jwe?t@CX@H+5Fozd!qGU$TAJKB0jv z7Bdxvk|&wd63KrdO+-s%vWxV-Z8w7DlQ<-r^%$20w*PurF4M}$ H$Y2cs&?%hW literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/guilty_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/guilty_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..6be861fbef55e3b0d55651a0ee7fef4377ab326a GIT binary patch literal 1127 zcmZ?wbhEHbG-5Df_|5M>d4QHpb#oy8~Xh=Id*CzE9i&gMr{{4agrNv)nv_M zv-CJwZmimJ;2MMfMl;z3Uo*nzB^0Kqct3a*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdG2{&N74?WP1CmC_9{q@lw#=S>JTRHit8(#QrXJXxQvGzv!#i^cVM5RLXB- ziD76++||bTW{*_F`YT7+M1)&;4rE34MheT%TN9am{LEZS^=~~lpTF3;TtB|Xa%=uw zMm8yH83l)ifa{^G*V=popXJ@D%jSM6YnYMyz_e9(O7G+?7j7}Va8j?EZFOenm0G#$ zJ8d(w;@A_};PCwXJm+$`9EH!RZI-^DSOj`T9oC2cY2H?Q*~nycyH0D5_O%X&#Y|`COxby9{(0FpQ@L-NZ(j;* z6z8$qQ^~OX)>60cCOdv-WSzZzd~=9?fw}Yd+4bf}`0gv#+~O`T+8(j*d)Xh6gCYy+ ne+pX6ZaAU%A~gD@p@wKAmmJ6RM%HI3_gYP5uLd|UFjxZsJRXzR literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/hot_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/hot_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..bb144cf53945b7ae03ab91473a95e6514ebddb3b GIT binary patch literal 1171 zcmZ?wbhEHbG-5Df_|5wC|+?^~e2kHaCR1J{-ZmQ1r7f5x$2o%Eg2dw&S$Ha zay4kkxVY4(Rjbu1wd$}dt^sM}V$;;1oq1pmkC@<*GO zdf8{}x2tG=t2x1eiA&(hJ%=+tzt3-E;q*vwWX~&)cRFt>zL1I4>BRjOk!NBHo!;gi zTUfrmmSa(ic&CMulU7#Pfo^Rvmjm6bM_$PE?9a7G?v>j5Vs@9qvS*K-7#SI?0j;E- A5dZ)H literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/hungry_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/hungry_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..29cdefaac83b02e7d0c36af82cfc70a607cc2526 GIT binary patch literal 1111 zcmZ?wbhEHbG-5Df_|5($?x7|epzv8x%tebHI^c;f~MQd z=8`Zt@bdE7*zP!%+gG&$*Twc0ea#YEb7f^J;|bOYC3<()<{Mv|qCG(`Xdmmlsyo~Z z^6wsM+?;nMvLf&9fuiPTOF4vBCok>O_V4>KZSB=_qDQORZdDpPZ)Dvtt2auZ)Oi&P z^NDGHOSa`SZBShGt}@#6?cDu|_xxl-zF%V4;l5c;;=zi{mUG4b*tDvPzO>t`^NXJ< zv3NK8n5eCBdB>iuKdyTpx7V2;Q~r+W&Gqede0wu$J~0<=d*Um&GyB}Ho!{ltGcHaK ZZme2snoyLNc~qqQ4yQ`6Gb1B|H2_@5l@#xD zbAKl{=YMKys|&O*s5v#au$?1ulxV4(P_l!PR%#@)1!5XUs5XrfLU$0_YNVtE;vq^V zAT>nj1X+Y&kx)w0;C2f#2caWyL>!ci2);mA@~vLq9|N`{-C| z$_4l3ao44*pAKHR`sG)bC;01A(-&{{yTAD6hI9Pu6oo>V{&{w?Z+_Nu?e;8xdv0O= zyP4l~I?sdgdqZwrRMf+%Cx8C9bKub}mF%;&pI-moI!10?c>af*QtKmUw0yT`?ipLM zBuVpX#ZIO{?Xqm-g?=)N9TGm!6 z7tawc1n$JQnM+E{&{nG@BEq)cUUIN`)XO2!M(KWM(4ZH~^UpK&eC^5&=*$fb47pVljYh2B20WShWg(ngLW* zA&|)cR51X(9>InU0Q3yNU_g+N0KmWij79{Bi2#g&!SVs!yqRG@YiqISrcF?^HgM4u z6J1k-AU+;I4FjmIMzC=sfNBO%UXCCp20%FjC@Vt{9Sxw20aR2Vh>ZnM!2l{N5yZs- zsAK^3^$3!Z0Ms*ph6V)5$p9J{KvNTfZQB4eF@WY~1nKDjngfI7H!o>go{4|egJ8`X02&66 zlY<~M6hICG$jwEtdNqJt29TGBVC`A}c?_Va2timFfFcG^T#SGa0L2WTv=o6<3ZRq$ P=yV9yuLq!80gCT|n7uj>pDDN4q7Av$j+`U})--R+dw6 zNJu$3fzNl6PNmROr>WY}yL>o`mmZ(Vm3{BX%*$%$+my@y)mUy>5jdT3l3MPHlFVaE zm={^Ot}uDkuu^nk)ZVVpgsW>~be(duwrWPMOxf*}lXajWY(oL_mQv{lSz$Yi?;h&y z-oEzI?#i$4?%pb2cdOl#`MPY3nL+HvT5;pNIo}PE_AqjZNGy=dOFui2Il(8UAtjS( z_S$)IzTsProiPi{w>`V5;q`i0L!u9%c z?;^DvUt}-!@3R(Yc-rd6Sl{t|-`+PB3~?Kc*Kq&+^WZb;7SOWkg CRkp_f literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/moody_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/moody_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..52de77ba0571f71c2e325f2213f3058f7cd356b2 GIT binary patch literal 1104 zcmZ?wbhEHbG-5Df_|529%gbwHyW?1HU)2g+7u#F(HA`&Gm6fSyg+yl;Isl!+!@wcHpb@{Pig}M| z6odY~PPALz#yKYrZS{#n_tWM%d1?Xwxs->ekbZ{ V==N!0KAcMvn*OMY2rw{M0|1hYkHi1~ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/nerdy_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/nerdy_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..544c072479e8383a3d2de628953b26a865897df8 GIT binary patch literal 1152 zcmZ?wbhEHbG-5Df_|5*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdG2}uC9t%yz9=btFN!mPh4+Rdt+11wauQVlT4+|8tyWrzh^73ZpaJSW5xJi zBqm|~jeX+LY$v!F9DMhbabM5bQ~WWit3q13KxSt_8pCYv>OVd+4KmNki29f5SblhQ ze7f>JnS@!ZUhdl{%O{}Vu;SjHa>37THi6FycEp!|H=AIc7;x`I{U^N}e-gqTIaP97 ztd_MdUh989E$KUFZ2Hdy*Y|Gr@%sBV^2?i>$JAHMc~#K-?y9y(et}i-Ql_8o^L_mV zEhaQ@EB=^UcW&eI1ZR#g_xq*%PEY2y2pef!j5wNkVp_XFp@dx9@0DMtbV?MeE-KFT STpH-(q^X+RBgDqSU=09JR-hsP literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/nostalgic_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/nostalgic_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..156dee32bb3bfa1b853600dabff1d237b5ad6551 GIT binary patch literal 1140 zcmZ?wbhEHbG-5Df_|5*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdG2}uC9t%yz9=bsSXXBt1mB4e0t6|>f5`+(~`Iu z1ZI?NXq+4V_t8|Y0|pGMdRdt^ScN5DJ2pcxxz6UmyQd8+=tIlIg= z(~t78a|kGGF}-+kv%CM4nYX|B-`v7`z)zxN+k2+X+uBT1@dNC^M>d4QHpb#oy8~Xh=Id*CzE9i&gMr{{4agrNv)nv_M zv-CJwZmimJ;2MMfMl;z3Uo*nzB^0Kqct3a>>Sds|uZ zqJ6#f?7q3X7T#!NDti8Im9_c7+Z*b?eYsot-S4qM?PNZ#k1rS)_eToL>K>^4ywtLn z`E2ZMt2eXRrh0RyuKHvCMd*wG2L=Xf0M-GXfdBvi literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/plain_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/plain_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..f71935b23ef989cdb2c71664152ac5d5af7ffcba GIT binary patch literal 1124 zcmZ?wbhEHbG-5Df_|5mwFd|Hm@f@MA}df7rdA}208H`j*s*&og;N@r(SB`a<1G|@ORgPHAzidU#Z$V#TN zZ(FKDwXUv;S-k7ct*fuE&re)$ReNJo&b7^+r;|*jzUkiC5qo{p)2#1$_jZckPGes>sw^A-=6qkkaDP1RR3G%&oxgsO2qqpJ-wwNZW|*LhiY$FLe^Q~ z)O~4lO|}Ny@Glhi@V#wz@G|G-S7H;a4%~cnSpEIhpTBkU=bmrox_;Iu^WepV_0j3O z|9<~Ge?70)t)=Te=$791GX4GU?3~@7?yizv7w>DgU oWPvlY)QktE3nZ6b3+8WAyVjuBxirvc`_lG>nY>ye0t^h+0E@n!YXATM literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/predatory_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/predatory_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..7539153d46cf2a3261b43e0480cdc9907fbdea16 GIT binary patch literal 396 zcmZ?wbhEHbG-5Df*v!EI1Y4`4jvYJpy~pc&&$;hgtN%+d{Qv*`|Ns9WIaB}?RQ%8F z=Nc01>=@u`q-Vg)2vnf>lZ91|fuBJKq!?r@1Ixb;Cp=g0wRnAY_x}WqzLd;)8LQUi zyxv!!bG{_^e#N@?k01P=CBMN`L!y4#{EY?*V$*#V3R#8NF1+z(Q|8{R{qB0JELihv z&%A4J_)vHK?JLfEX2CaewW|d-=rb22C6_YPwPrVIx-#@c*1Gky>vc1*wFdO}Ov}^` z?q%$ETfo{I*s0=>QJ2nMWGj+a*0fx{Xk%Iu(>gh4rhU6s`|M{D+AWhJdN}^D=m~{Y zoBj6%Tn;>YZEN(|?Q1sNy6NtD^~x^K`+FXqJhC=OXy3CrFFvxrm;EYy?o;M>`9H@b zGiI$(HvAy((5yJ&%YvyB5_Mb8D@wC|+?^~6<`7kEs5_a^hpic8DQXC|$& z6nPai-Db9sM!`+TrW{4;H=6`m*Ng`gHTWuUZP44ZD+;N^RwQaNzDP zhxgxDCrn+&c(7uklG>Vbt!qci1lezrIqO!47mWnr)e02+Rc;Q#;t literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/quixotic_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/quixotic_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..edcd541b44291140a91d52319a28156766931ae5 GIT binary patch literal 1229 zcmZ?wbhEHbG-5Df_|Cwfsi_$h6qKEvJ!Q(2rAwEtUAuPc)~$Q@?mc$w*z@PlzxQ~3 z?>YBLCpIiR+%BN(HOFJ) zqNCjs##whxY+QW2U%|Oc#&gq>lan=qSH);7NIl)A7oV1s$>7L5lOy)p9!&;iUuNrA zt|=>pGcL>%%{=B((2#y+KHI!oE>?!m8W?r?ISfvj91LKNTAw7kz;q?U#_&wJ2UQI# zgSR+oZgc6r`XXwZ&-qJ7H4F7(m>HS4@KhbH}Yyc>Ia&w4_1CJBgx%x7XKijt*%!pjP(w1#|P?zIl#c*`D6_ z7m?pz`-|b*!Rg`}c1iV(PoJtQF#i_(GT)hNN4P*GBUgkR)2ENi6wLeg)V{v_S-}VF3BM<#}%9NmwFd|Hm@f@MA}df7rdA}208H`j*s*&og;N@r(SB`a<1G|@ORgPHAzidU#Z$V#TN zZ(FKDwXUv;-N?Qu z+J=2h%)+iQ3=N^vrGGMc_)IN)uv6xz*|*&lpP!zwWBmV=NAmIMmF1KBRL__>Ff3fz zd9JiKa*@xijTd)`Ma|C5zrK_6joJyT#B2AMV%RNK%j~?iJT3b-%eu)`7as48RMYL) zwW@fw|Mr05<^LvcJGlL(sGGS(%*!{|?;PAbRlmT(`S*s)()auBEB<@*T=sgr%iEXf uG7bAAPfTj!Q{1tj`Oeg|D+&IA8BwtuyF#YB8Gd{g*Us9oBfx=y!5RP?wVxya literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/rejuvenated_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/rejuvenated_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..23877a27eca841fe18931412b2b2bf2376db6121 GIT binary patch literal 1136 zcmZ?wbhEHbG-5Df_|5mwFd|Hm@f@MA}df7rdA}208H`j*s*&og;N@r(SB`a<1G|@ORgPHAzidU#Z$V#TN zZ(FKDwXUv;-N?Qu z+J=2h%)+iQ3=N^vrGGMc_)IN)uv6xz*|*&lpP!yFVJ!Zq`OE0xp=9U&xHsRQX0|gi zu?SRcU*&LfhU%#!v9mMY++>YY=h50-?t7E9RsPH@>m6?x(&w9}_uW!+oPV@5jsMgh z%hO9vz6}eT%Qr9g=j)sGkIa5t+wHXZ-bD8BD(N4kub*w@n{s}FeeU*XEXJ=R?D{bvG(Ks@Lh2w{cSE)nD zO6Ia}TdG2}uC9t%yz9=btFN!mPh4+Rdt=k<28M$3hj=H5t-iQ{@mvsZK$&jzy2!6# zq1Ft^w+}R3OwwIrsNHb9f2C93nHkEDj%4WiADwe0|H$;&hRy4I3L6+0oh;QwD`tI3 zKejgXwvFzUt%nyZ5527R!ZI=J`m*ABTU~}7*OoVW{uYS~uDEc2o2U|7on+3zm;T}L z>FYLcb$pYP>m+q&t%%vH*N+a%r`OJV_^xsP=I;9c6YAc--~ZBEMLzb|-~E3Lzszr7 iyk~YTn|afcYr))7YS-%ZI29%gbwHyW?1HU)2g+7u#D@Dy5Kldug_L-d|3J1DAK1UoKjbePCS>Lv4Q5 znn>~Y_YXxrP0~&Hu`Yg2aJ8OU_0@(O(^&S-nwqt9QN-CW%lNX2%1>$MrUjZW@d{|j zzV08t``nx#4wC|+?^~6<`7kEs5_a^hpin9z}ybh|T zM3T==XI$oXcGc!rN2jwgS@e1-I55tUYs;c;*XVytVH)9|{O?aR1g@uF`z zyB3{hWWK%YsbvAf%XVY-7u#%SzsS3>Skin?)Q9pb_gOog@Az1M^S|q`uv@JnwBpRt zld1ZtHCL(*y|Y{z=)Qffu=TsyY^B^Hr$TCrzC54JU2=ZHzp9^yH{LGK`2X$DSzAW; zi4Fh$h9`Kl8%9!JcT1E8Q#j4+|ZJ+7H$jD#~0M6Hy ArT_o{ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/scrabble_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/scrabble_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..3e413b00e35700cbe229e54a75f5ce1b13503726 GIT binary patch literal 1480 zcmZ?wbhEHbG-5DfSj5Hv1jmjYdq3y<_a3kBTdV*7|Nb8g6#sMkxrPKgI|jHK=@~FH z0@W%0WMSoEU}w+)X##0yU_KJD>&`!eQ=Y5$TD(5H`+tH)UrOe@j8*G$UhgZ=IbV`{ ze~0y(-+P1|9ypi@d}`ZpU%w+qw%gIkzqBW6>Df!4PCd;6zA1lp`usyH4jwyncyAN)`~_!u{Z9*> zKgE6J)`hDZR*L&uJ`(3d@)$D%AA<^m63}DoB6eB5(>b-$DWN%oY32N|&AG83dE_Nh z9{<>pS$Hxud%o1HwrQ#V`TTSa-C|&{?aq^+k`91C)G|Zn&y(L zHY0OF?JSW6dFpdoCs!@+c1&8dFx9+s{bZ}+zW&u~^`v_4pZgyPG8$4c&L^PDSxLLZ9H( zb#D#|YPWpk?Yw;}oUtgylTSm7&q=!@@AihbGy0az#G!9++Xsu<73gWU$T_ml%X7`^ z2EMf~yH=e#H=k$o5zkqB68OtEa`rEK)W^=C5bJqr(p4Rc<|9q|MzN-|Z>$MB^P+0K zO;OhE23C&u$@xNS+3yvq)J6zBU{bAg%F5PdsxxNPY$$4RGveyvZg4Y!BVWL- zA<}QLB*{a=F57E@$YB#F-?oA}kB^>v=kpyOY&rCwAmVR7)hWPM7b^i?VO&TTn53f#k}v?3^_{=2Oa7Y!Ike zZ?MZ@T~6R86$5@`cXPw@(<-35*MZ#Ktupzb(}tcSj?K$@NG;CrnYTi5N!qVi ziM4S`+r8?iUtw)vs=tQuQSzSHlGWcjea3|Rsr>UMO`b42$xD36 zB(s_YtqnQxDswy5n`|tp+#wnT&b3K>#bOow*nfe?tSczJnkYX?WtcJ0zGjK7xw0~qnPr34^z^7c z)2B)^R)@U5v)zsR#M;~C1=o757*DW%2q|PZX0iO+5v~TqE2kWVJ90fIti8IuL9y#A zk7&t@w%Mk$V`qK-;nBVi%1yC(0-n%n$7`}ZaMc=RNC zzkk7hhU(u>pI*Ne{aw=}HbqD@bV1{f-qr~yyHTRH{}X=mr!q`qRY3V!Urz+>{eH<@2nTv~2EGii;b z$g7~~HnaH@91gs^yf(Hwj^*}Mt-y7$y+vQM#MWF{nR-@8boRyUh9%{lRckmG=r=5{ z`@e5)SEydloEBaYGntT&37z>jqk3Zk*QBhNC~rPTbHV0@)1K@V@7_ohg*7dn->2tc zn)L9DnKkp&yE7C*&vN$j#jTmLF0W&MJ~r5=)OR zm;JZz-Uh3?tr68)TpKLn9+ZE09=$AmN1RpO_qT#(^4;J5I&S*5bbasnnzdoeoLD&& KlDJt}7_0%4uZrCO literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/smiling_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/smiling_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..bdc847629ece30c9bcc3de9b3b9ddf4fb6a2ebaa GIT binary patch literal 1117 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/surprised_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/surprised_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..058972f7e14a026a11ed2f978a1eb24ea7b91e5e GIT binary patch literal 1114 zcmZ?wbhEHbG-5Df_|5M>d4QHpb#oy8~Xh=Id*CzE9i&gMr{{kA-gSt`%<6R?u5LKIOW^_eoAG0T(EDVz0EF*iYw>OH0qzNyz}GLoXgWE zUyHrn5U_0hMhEWvAD?r7v^{74muGAH*ZKQ);i|Vc=O+FA@#&-c9-YAY*GK<;+&-s4 gWGCyKh~(51u}1d2Q>Hgful;_v;2)=m00V literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/thirsty_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/thirsty_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..d2a42c51af49bb593f5601d0bf1439c1bece4255 GIT binary patch literal 1119 zcmZ?wbhEHbG-5Df_|5u?l|dzrbViyEmC%R$N+cJ~L^J zrO2zG={B>uBn%F`yu3EHJC5b{Rjt5vvAsoKv&7b1S((bou)%72dQ_h&BZEbN`O3I` zk(sBi-WJzW> zfmvTKUt7Z&)VpIwX2U77*!Nd>KbyT=AkhEqOYiT^S8g9_)>rk5G7q@c$*fZU!+1;n z!fpIv;p?gtikVrtTqP7v)I7*}<;`8kZ$EF(w+oyb-OMuRZa5fB18pd0|o z3k)3p82CA4JT^RVVB`?iiaD`ip;NN}x78ev!o(xpOxjr`9UmVZ>*u$2W8n;1;yy{l zw`@zqM+fJr2K+@mp2aCAW?2-!x^vPv?a(}%dZw$IB`Yp2_L!`7x3gfSBU8XaFOd%> zT8#?>cr&I}8LkRrjww(3%VqY)VSUQ!F4cgtoaog#+oM8fU(RY|%DcQwwLo0|_Uh7~ z-;S;h*S~TwuvAV?W`Gx6x%VD3XA(<|RhO`qx@DrBNq7cDp?(Oupv{Z1u!TgIjKcbq?_ zcN&JySk%RN?Z}*RL$8R()yDItE0@lHcs<#_>1{;lgovkX*C#f_Y6LkjFjxZsiXyD_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/tired_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/tired_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..b50a79cae3573ddc6977c6de71207793e817f796 GIT binary patch literal 1111 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/mood/twotone/hamsters/worried_hammy.gif b/local/htdocs/img/mood/twotone/hamsters/worried_hammy.gif new file mode 100755 index 0000000000000000000000000000000000000000..011125c4f1277bf6039f1e0ded32131b9ca73e77 GIT binary patch literal 1111 zcmZ?wbhEHbG-5Df_|529%gbwHyW?1HU)2g+7u#F(Rf-|w_U6p1*H|3H9WL!E+wNr=)v%6nSNY#( zUoFJ*AMA=We|02VT=VgQYVAWux*{|mot&up?rT=r<|k*H6R?JH&BA6elUS>b z4vZTT?R$A=D_reZQGLx#w>mw4##aB;brmHI47cZWz7q|QN&0+sZ{wkJf9^ayf97DT z5pUk_WySAV`fbfc?$0eb^y8S!hQauZs^NcGhO&y%rq1TQE8BMN-tqY0 ztbb>x|G7K+-~T@hj12!t1d9KdeY}Dg6o0ZXash4BVE_V<)eNjH3M{ryl;^GRU}KuO zDCGl3*M~iigl(EWvox~zsRY=tv^qWbSj8a1-?$(_gGFwAJA(rU2S*!7kcFeAVL^fd zP|%%0RzQS@<>2G591ED4Seb(u^!XVx7@0UYIT$SX8Ce)PczL-QECl!+ICyz@7-k9Z WGqH2?@~AB4XIQ7YSVL8j!5RQAHE-zv literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/boxer/boxer.jpg b/local/htdocs/img/s2preview/boxer/boxer.jpg new file mode 100755 index 0000000000000000000000000000000000000000..9299e77bf752a8accddab1d1438ef424f96d513b GIT binary patch literal 12699 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/classic/classic.jpg b/local/htdocs/img/s2preview/classic/classic.jpg new file mode 100755 index 0000000000000000000000000000000000000000..51d9618bb6a975ca5ffc869b68fdd03e0fec6431 GIT binary patch literal 21054 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/cleansimple/cleansimple.jpg b/local/htdocs/img/s2preview/cleansimple/cleansimple.jpg new file mode 100755 index 0000000000000000000000000000000000000000..d4c25c2472643a7a3e22c481ecb55deb9851d5db GIT binary patch literal 20049 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 HlZpQYSxnGu literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/digitalmultiplex/digitalmultiplex.jpg b/local/htdocs/img/s2preview/digitalmultiplex/digitalmultiplex.jpg new file mode 100755 index 0000000000000000000000000000000000000000..9ad403a9bbcca0062664ce61168df905cf280451 GIT binary patch literal 26558 zcmd421yo$iwl3VbOVHpD+=IIZYrJs}9;6|-Yaj%7cXtWaI0^0~I5e)oHMsojbN0Uf zJMWzP?znf{JKn1v-Ce6z&FWdTR?nLAo8Nk#e_jJ%17+l805GrsfceV{@O%h(_0HAI z))N2&fCm5osxM8)089yU2U81x`L~xAm}e*;7y$ck1@5H=2mkU32af>%M?pYD_*+3l zL_$JFLPA7AK}AJDLI1}B0|y6(0FQuzh=_uLhJuEHh51sju>RKR&oA`9AN`};za2e) z1H3|pL5E?1gLwsjeFX#e3g)>NF!rK000{=><@2us^M_)HNXRItFRid}|9B1#_HXB~ z0WbQ%!oeb;pdys6!2@0);2=`rB5~kJyqV-u$0ty8{K_erkVuGZ68IBTN9{bN z;i9P(=S0IjU4-)8w1+k+FJ7vi$L&*tYa_o|K?oi1i(;?cFH<#R9=7#{OT08Fwb~d(dWQDhxED8XBlzny0w47dHNGD(a{*QKVzw)wF(CqZm%kSg zSxWI#VP!PwZEDCNSVC=cSZkD(%nVL3LueSWb)E%%m#V5Qjwloub3x#Z)|IKK#1@CV z`ePO}Mub**p9?b^;ztHury1Fj{J;rTTH+Fvl&5MU*~BlimIu+TLbwuNafsr)-A_EV``!W)Yf-`I~?ca-S7I&fj&AA6f)ODBp+4WgdXReQ`kguB`RZ^#>Fc>+4_0s;DsHAeS=QP@KiAZPBT4N!ALW7E0qFDbjKU zuU&=90^P)?iM~$>ifONCi}J{3hd)`1awaa2!anwca>12%GG=(~GCsQ@b<`SN(O^b;wXae}k8qHJhs^tJe zuR7I@C^f4}0?A2kgfU-~Wgu*-jfP@)4HY4uZ?s=CGBMjY{qFjf0juEy5)wW7V+zBY z_08x8LpX2fymS-Dg;2i~OTe{JCoiDR_(yyTcikJ6$hg|Y`bFn6cwRPF!ufxDl~A-h z-)^IlhP6wOzg#yFFK28gw?GVTJnm8|DtS>j`{CX8AtntNaiw$7M;N$8-#b`5*Z@^h zXhqF-fy=e%G0L8z1<3SEbT?@7hEBmm56zDcZ{_M#vkgV43@Kd1VPZ|I+Bfou|*V-4MD;8!Aqxjdvo!KIan^f6}kfr zVXqIj_NwxH29~lIb>5hOItKf{Pw z!lD6-1q~&zGgaD*9?dyO;Ru4RTYaE%Ce#C{82t1UABn(V|6-W0~HF>mwBxsBuMJ?I>*e_&>P zve?!}($3y)JAAWF`ur^d`~i~YSAOiBGC^+K|Lh(*_Ed%4ZU62vzrU~1th?r=n`yKZ&INR!9&Sif`P zoAu!{K<>&SXIvYK{BKztEd=;b2A4Y-H-!g(mR(L+BC(m zU%+g~X+zf9?-oqx4F!(oHma1k?~5+owG-UzV?5c=RMsy1l{IL;zAm4rtl-FQc4vg8 zS1_xOSI5!Bb3ZKnOyUV4+bXhQf2&0hOkGPKey?5_9zHcR&btyRmU8OVD0M$i$UCV;bmy7r%FB(ywirM(BCo6mKVq<5*0bQ2htR9$*ZQlGzl-L&niyB#DH= z94IIrIGj)zxS;2~dLUngcTN;leH-^AG}HSE{90_*LPx|j(y_gfX$9t^Vj=L#1;81K|SBm z#9dv+*kCH4f_&7-Mq(kH{rK=YbVr5AfWlG5daCBr2{?JmZ=(IzE^auwdqPLkY0O?k zUAH&;df2g6W9P@ynWmIw@I=*P-{q~66oG6 zAL*Dsv92-Q|E)~xEReC>v@vQ4=3@L%79 zMVi%C6-(cGB&WFX5)b^HG>x^>A|@O9L>^1&YvBraTdneQ{TUEih)nT6Dpfn|YU^j} zn1)`^mh6&z_H!w=`A{av@FQ=06-LP0Sd9uDgJ@A=@lQ%ISDAiNc7oXj!hv*40j4s7 zL75oT;ij>uiG@)#A+X|V1~jmI+V3jZ;O<@}&LR|6P13Ts)BQh$l7<7lU=|Oq8N#_Q0c`>=O~tQL&2Q z$cA&0r_36;<*XVB{7pP)m-;F`E8G_6;VE~-r2UXX2;KV=6Q?d{qbYt~QOcE3T^B~A zu;Q3$5L+$jD&uXA7fW<0o?Hw$X~}}3&H;#Mkh6>+2JUQ7dwlAjaBiK3rQMVtT9yMkT!ySittK?m_=*e>3d2sHmFJL1W7Rk$KAgdh0|NiexXGluL-(T6?fsJm7i9fPu5 zttB(<%49FXK|s`yu^XeJhOd@3Rn5|adsja{(0-lPN(YJ~+r6`RU*7$20zwev=EfV!wNXDeTWJ8&CaD>sf8v}AUEzJr>WwlQgI-Do_YB@VC z6p{|V8)?Mv60L5lWq)Kmg5j~sWc<^&d{Me)fBe^*acc58G9@#dU4%DniM1Bj8VXCv ze@Hm>s!G^+A%rr4#x3d^A6)OMd1h|M9dN66FS5mcx7)992O=b%)PJ5I%G)xhmrYrD z!vr_Zj!%(VTHaYK5NKjj@9gr)o;wiU=$`*5^wwwZYqG8$sfAxzI9^E8nky`?s?&MylD+A(0I<`D~8jPsFJP-0?XKrDZNw=|_hti$1buyyL!pJ@oG@_HtD9y=dsq%bwi~r5_u~XL5WSdv4sH5_wm@VvR2_D-{r8$ z?nU1l>n-`y^&AW0kU5SjYL-dB0VTr|2JRj=nnfF!s0T zCCdc`iEdcz1?n)}QcGTLH=hx)0+nyfadz|nyyxQ0?NU8m4s3_FK^}X7qVE0`?9YJk z(`UeSKlL*pCC!i-(a-OY#b&-W-!tF=IgZzwWPlh2MiMi>SVIBytw7(bu&1YSi?IGg!3uFR__ zC3C&fn$-~-fLj*O#V$4xunrmV6O3&@!ogFn_vKZ=BhmH~r0u2gTdnml*3(Ow&JzX>8Td zu&3A3^v-K%-Jyl&jkBYUJ|_3ZY!QDlR6lH1H3X1YCV!I*3UmhfN{lg#?~7@fN`H#e zR-i@1r)+#fjZrRDVLdy*IvH(>7Z4JQ$72wYxIc-L%h|c;%CmIVLv1NS_IcK_CDDLS z0QC!M!t!L@(QTmogUV|kbteQEE}@e0{mB**2_>q}d9<_8@FLdVt*0lVx@pJ z7{js4AFu6l)b83a;nCv-b@s^&lKPT9BYSSgLf{nJ4OQTC^;2{CgR^H?1ql$1c%K3L z8f60fX2lZ&&g2J5?kU7B+#5y?x}F82t&^+6@+g}9flj&NWZu}9L$4z>A`|F%c-ht!QTL+__3l9`TIuU|3TZa-CGl&#h+!P6K5 zS9Lxjb@qNYBpX0gOfpQDyQ%uANO#e_^H#T`hRukCAtn5kNPq{G=?L&U0+VFIM^LT= z{zm)GwL=@k#(~!6++Xog_Q#Xq(F{SwHquJx=Wl)Hd<66!Lr{+;KW}`P60W+uyrzr{ zkqSJ~VEqdqMg&uT|Hfm|+5^|GlMmC&>h|^N1|?y#X&nu%HelhBApUD;P9?P71Dr-C z7Sj|>Pe^CL$ZEBajJJWtHXjrKL;0!q(|V03)E?^ZuDL;oReEu+FT$eUySKX67n2qF ztMfP__G9~ zYA$WuGY7S6R{t4rAwvEPSiVnq20%<1&FIrbRb7O$2rwktzh2r|<98pZQ zLY4_l-qG41eVN+yPTCSRIcp85QNZyYclPzuxvca7wWjiy$Z#ZKxBIAcGk_ z8m~H9r(g}TCpZn#ai)S7b`iz%(Ov{LQox`R(vYmoob#1jWC@ry~bnGkKMg( zfsocmA}=hZ--L{ft+t<`H@D6GpdHt_MOSGP6jK(R7+?xxp9l5`INtZnXt)#C7P6qJ zZ@tJN?8{fvVP$0(`3zX7aN6VxRn%F2Eoc9|$MU>|kw1CGT9I{dM?Vj8YkL+?F1JJX zV3%wAON{;S(wnT+BzUdadjhNU$GQ5Pb0+&*^rK;c_&>yEaM~-ctv#2h=WiqhS3rrm zz4^H#DHi>cge6h2jYZ$DLHwUg*^k@_W`DC=hcECEbvp+VfYJrlp^xw51Rz_-I%;_= z^zGjQHlt|aW%ad86wnw+yHi*?wBPiet^ew(I^!wOT&#y6nde;4pS=5+zD|_5x0E?@ zGcQ`)EB?W%cbb}&K+iCZhIK~5LM%JHh$<07h2c!I5%s~X1Z^AFy29k4eYxl09yu?;BZ3#Y)phb{h4(6?&^(? z*l-hClCN<6dJdK{&4;BOJ0TTY2L>X1#ia!obNS>jC6N_lU&Xvvn)qtz3ayo)KC%Q3 zPPGLCeN!XnkE^zwO>+)Pg6f$#Y0hi{3JOV}%VhBEutiojQhLIPf9>3>G@W&p+hl*4 zoB-`N3$+@h|9hm*STip5xEC{m@9uE_CDBo=kzRb|Ue;v=@w?T>uT7C6-_dwm&R-h@ zvvOdc3+Q1N#%hiobp=7Zqe|LjHP%z?j+u0M3(pA@4imUc#F{uTU2!pBsiH3`d^2sU zS!HwA0b@6?o7!+m1yUu9CmB?g|PX8tylGV+q00$fDItoCg$1e#3BJwy z)!R3vQ75f;=9o|GK#2{h{OT`TP+??QF?wVCRENR1-1c*t5~rY@j}qX2d8lO4_5q{| zY}1vvs5$&~r45&EMRqvL<@Vm4%Z@J_x?qX3slwZn{-Z(Q{iZTyLXo^EIpti?ZFu5p zag|%quaykV9;G`@>oeKOcEtXuVrZo3)bYf^rnOyETC-DIz5V8H&$k{k{f|bVOve%$ zNZHLdSWp9ZeinV;^^uX)cXz&ysnzQ$BLhz{-Qf%G`?f}ndcDrnY~_2e-$UcMqfn@^ zmBgT_<%apzn=Oj;?^2wmijj#`g;n(78n_l%$Til`)w>L#1xZ~}a8#RJ>BfZrV^Hx{ zotR}-5!c(smIQz5^pkMIlQIDTMie=|IuHPb96o?~`ifg)zDi5gSqN&gQh#UeP1iIg z@h{ODI9j+d`RlHETLLq);QAfiM`Ax1g9yv-pj=c~hq#w41^LuVNcYE1_RU_m&T&44 zu1CjS(S5V5sEq18&c1A)FczG)+cSWe=BG&OvN5Fo(()OA;4(z%-v3La-mD^|x$nbi z$K!;HQ9uGzY3N?jIIn(fLl_T!)8{zQRw=T`SXH;ZR~ zg@T*|%J;!Z-!~YA%2^joIug{0xEnR`YQ2hr@H{kjzNuE7kePj#?qr2C9 zRmaOtJvZcED#HIYHiw>w#Y4aH3^1wGjf%$k3!G!kKmZ0XpmfTv=2CjAbcsv8V0v(B ztL%IfU`5YuYcRwNzq}WE@rx{|`sj%plj>l}>Ii9PZfg$sF7L1UjD=xl|L=X7dnz?R z+Z*6*>B{scXSo9qVv*=MsBkscTuK76PaA|8pSS7hNMDwdwrFp|X!khO9E z>wi7Voxoww7x4=urXeL?8~jps{L6E1{!;Ybg0-eykYGQH?Sf1dq?!*4ip?@CynNqJ z(3e?lbCHhtPWfCo+yXaW^8Y0d=x#RAo%S3kn{~B&~OGw zU!I9zs(d$!Qc6&^wr%cK`;FL**>E8T`fqwgjs;;pS-wnzNZGT5SSNcYgELY&4Gp|f zozt$MAS`Uf{o-E(mVD#_E1C8NnJkLeo10D^7nBW`ANFL*n3+k{%M3hCWcq{~T3vq) zjvl1$)s>j#DtngA4;1%XUw^I3*6|a}6bGfb1E;e-&;u*wnsb9L^t&45Zg+jkk%^Zd z^JOQ5wpGPvPmXXzJy)565F!2_;x5K-HL!Ww?%%~^yAS6ER;@15_*`^q!eiJ!{iNQ_ zIxnTPb-xOu5I#wgfcrlUhOX>Q9oui>`+@&ElH&?QudPo--6`-Ds5nLuN>-d{V3&;F3 z)zQPODYuU#7g}cUxJg4pW07zp>#QVNF!LvQwU0i9G^zwQY=t{@Bpu!kT#e^9{OmIF zpHj5_^i6d#-f%=;6csk0Lct{<$x7I-mCMmagnA-Dm!3*o8mfX1wurD;WFFK2x&MmBr0cFC!zD4u~#@&?ELlof1Pji2F# zhSQ}sFyg0#+=%kyMLX;3yt68_4bCj`sQu z39WSH!XI!5F62`6)H29a${JWPSQr&!NenyHzD|jIlN>H5I}3!4ZR7P0O8V%qXZlS3 z@(f|l#tX^&kpznjdEX($VX2nGIq_@i6m<*AEC0{iQgN36)^)KMi{^6I@f)=SUr#lG zhPS;IX6V`)mr1M=XEYRJR2YGUxe@X59j+R{%rF71sb!%n83nBHv9)v5$aNs6fTxG< zNB>hits?e*YZ}4Cy;Cxv3I-$SQ6=H5BZT*)rM^XXUGG@y;bYH+-{Ay4%4S*lPlXkb z?V%8lC+JL^0iy;6Q&bkE`MrXK6U$6$OZRD9 zHC``&29$SsCU`sf=4{rbVL@7nt^HpCy*UP=+IWl_R-Xalr@%#Hr;?|a_-Vrq{E)MC zElSq#4CqpM2tU0rM9djEwzChtEm80?9*M~LXlR<>^@#LsaZ%eTW4rhT$xU?d`MP@e z;G%H<`+htxU~g5~os?E31dVru(NzggZfFARl>l`itY-1h3I8pU;#t1}W<5&bcE%(g z>iOO?y6Ir2Z+VDm6x#}wus$P-xX_jDkZzin8UXUz}aPJ)Z&9g~)tWY4x>2N|lf@ zz4%XJDJzdh5MP3dEQ-Oj=DI*ezVXW*)8<*Wp6mvKb^lfMScb}XpuB(S5$21 zLz=Hn^ed;7d}Y)8#vkQIT~U-xR}^&=O|t@az$k2C;LmtT!Bo|Pst^(s=9@Ca?oP4` zvCq)63BBZ_3S~Wm3!h16qGr*FO`i~KrLw0 zc?6%_4#U|74DYG$;;sDz_{q$HUB2$RqG6k>((bXE+N3}wVZwSRUSqR{#~Y2D!a3BU zqJI9SFDm|S?L1p{@SqJyJ?ldSHl(hsi0Lk#1XxeZ>i4LYrQdXLDWmHPCelsg44#bLbE!7K%5JK~B z%7?g*fTS=a%}9rTC5BeL#4E)TMn>qkTN;eS_^?o>qwmEK6Qem8gZfAE5KIbE> z3c$uz+p;_n5`@s-pu?=^5{t}77Fw78`VC$@3@SYCdwU_@VR2fvhMdTKTr)FQn1Pt( z`_Cl`J}}sumRF8QD*bh#SpHGmo#GA33gj)4sC0E(bwKY{0=(SZfa3()`CnAxCY$<8lG*s*~ zL59t$WQA0;Oh~EPFA=GAi@pqWCL%c*`)uTV>ye%Om7%(Ua{lxUd$#}`-PR5fTfu zWt;rS7=0Mo$;%v*7j!<1P3~GymRm(*GnschmvoWQCaATtS<}Hp5*97LdqsY-oqo&= z%=CRNCOfI}gK&Y}U##m)ej)98)52L**LunF{o9}x^xTDB!F(8IyO=gdGh?1-z`H7l z%M4BBscP*5^+H_R1*$jiZ0%0Tk!)e-4>E<2Nm8xZ$cN8w-X&X&jt=UJXRk*D9fm^f z+z1VgSsUn^_G?U9Hdkh6+{$oCplX58v?ZZfnNteh?QQsmC=OSoQT`pF8!56OGK z?%9wFPf~DCA+s<3*1QM{S|f`!W0DSkQsFXYsUwB^cP+bPmlOTo9%YKWK^qOy z?WgGV?J)tAmcz`2XybM{&t_@+`0h0@Usp!*rX zaeOS$$OJ7YggAU&cn0wLpG~~_sqn?Qu(`xgeSD{czlc4};wyqYQhjZ|C;*9E%ooVS zo_Y-m0p2^jWNW6T69t)bPFY2ZYX^)fk0mSy1S&uUn^8+=c6I0qINYc7^YY{%7-G&G~5>M*k0!chu{BeCO9)0q;iWiGz)&E4Yhs@{yGbon@Sw9yw<*axI zrJN0O98Nd6s)?M-Qkh~5z5={Qxk%EqGHLurxn+?sK^X!mU%7$N*JY8Bw#YV|Jc9}j zd7lsC@hUFJ^sxDvcIISJubOVdK#-ctBU@#o3Sp88ho{Bj8_6d-CHu&JI@;(YGY&-) zVr})@RQ?vQ_(0u;E(VjM4<6OGsZy}AM^P?8Hie@+etpY@{<6FOl!&$xgw16DMXBgv zUf5T$&+Ux-Y`&@f2K+TZ0r%QX(2P0x;z-H0-}EeTgMgTUmZn1e7wo3mY{pWl@rWlY z^aZ~@XgWA9dJSDy$=Q#y|+3J#m^EEC1z4-%uoe-*|D7>VEJ0n4#`g zJ`%c;ZM!d;wC-lzSofRd=e5;Kj<8>8%%M4z#h%TIf#F+>Wtx);OTNP1nSHcP3^xDA zuH_o8^Q+B;y6P%DE!>fmVobu6nGaBKS6kp(PSdKY`-GeYiaN5;R(mKRYD@tMX<{gf$y7p7@0WS!-4vO5$7zb_GpLnrz+`g zr+CfEif&EsgyXsL!%2M}xvlG{4k+K{w<}*TasIy|7~vrT{|>Rvvh)w2SdG@-aX-Me z5R3)=2RwxQW2x6XI|U+Cj{P1IzNIGi!ClLEdE*Qcs;!b$Wm@aUb80w_K7La@gGrc* z_9f;CqC#KwtO zDXN_!mc#h?Zru{jVTP#96f?^@b`jQn<80?#(GQ0zYQojHq=4%P|h@pe3Ec%Zo>HF}P;XnYtO)9?xUviz`D_d5j9$}sCww`oWA3M(pN$UG?O+O8b6@geZnh&_5|{`F_8ht`zG{O!A~t#e{@8I850IVu!u=>xi7 zSdN%Ri}CrGxi(qHbM58!$E_MI_U*V1C=)8@yBNyoNj9f~M)Ps7MoZu2``#WJnElYz zK%Q7lhw8~BR&QklUfU+D+O1mo-Md>a=oZha|6-|7qKg{j-_&RJ;h&tIit0}+UXox0 z$$ieimc_P}-;u5t&ZOUBeFl_{+(~t6D&oR*ZHayPTb)w;j3WMj{z?%@Fu9zV&ezCOLzgCDhDoShxj&1BjxaJOPYN zY+Cwc!8M{c9M`)i%T1?psc;WE5qr3(FW{k2x?|!G$Tngt6@`_>!oBfN*rQxx0-f zE><%Ul@@d9c<#O&B8%xVQ}Zu2pu^*2=nUCAMjHferG!mXWLa5g#@ENOz&?9qr#eT| z?RlKnF^mIxz9=+NY?Kv&>o@!$lwixY|Bhw(cNWoo<@3->wBBg#r#^`j{Ek7Pn(;mE zL<@0P;~^7K1S8jgJoxc930Nsws z1gPP=qIjoLU9vA_{G}jXAO5-*p#60b?~*H|=n|h-->704xmguJ5mks6WIN+v=e`f= za6g<>(c)D>!qjl|^i_|LMwvp#u#`F9`(%k@dPrBO;HC<0&Zki}%`civY9H=N7e1N{ z-fvCuBP%CE^{8R^ZF8(Aueje}6Ul6Wd%9_bT`>^&X{m&o5lL+7R=PQCLA7^A@H1W8 z@@74L5$h~5vwCzHO(AQq0YLLRO#ohqR_C?F79;NgR1w%eK7sZ^TX>sOz!RY*1Dy83 zY=h9gaa-*kbs%-b7!Dq(+8BguE0Txj1=QA(`8QqNM-2GLlg^ zNW>)c?4C`2*U&v?6Ams+j1Q%5O45lQM{GzV7(H)t;Hv$YcH?nTd+nxxLI3))(VS9n zDGWJrX~48tFkK-JPLFt}V1QO$&x5`Px_CO_42G6zns1P!QVEPqVWCs)fUZrlQmkE0 z-aDY9D?Z2(ReIyh?&A{J-jS20;QiE$*WxZM0V&-Se(G-V9q*ZME3h7T(`PL+@|(HN zpTK`I>4qtcPIkI_=t1`x0MuS945I+G(Vtm8G8zZP)A#}pbNX^Fi(aV8asMX3_~zg3 zpXy>}83Ayjq~D0XswTYV2fd3EAzCP2t9T=EM0RB0e^?j>S0KcXL8VJ6GJaL@@$eM% zE~YFi<7R=PsA37yB98;~Vy&B&R~=-?p0r@dc~K$sze~4&XD&(=V7pB635Pcy_k5Ts z6Wv2Z_nbdT=!th!okd9?QUB%mXpN=)$8eA~t-P{ys(gRzmMk^@MT_AF1=i*uSY43( zoNF{6AaK1pk3N%gS+85NXV8fG6~sxGr-z+;u>cWgI!f{^@tZ=(Hvkng8qB*Om;C*j zJhxSrlVb%u1iH|w;kXrF6NrG4 z@Yi95kXrKvnA+OJh(u<{=W4=f=&g6#zERY1_Y`4rGKc6f*Xx(3H!l0>RJ^|Odqr0F ztTZ1TH9Nhov3&cAYq9(|4`E8_1KUTsPJLRrj^J7>w*COcYnQ^f1QbB+ze!v-|G@vr zOHzoqUANBk1J*$Ptof!L%K@%CfQOU%fVG}6B@=eLft5+K0}6Nj0WJMs@%ZB=c)Rv< zf&wlo{*T$Ne`F{P3+^ZhAjXbBqvZhm zr}~DcZwBL>@IO6~K$Ont@42v4GJS9!bQr~9D_#!H`=WGC20 z^Qd@dwpFIpT?mUbqmf;=pP;bf?Ix*FTF6A?=J9aHO+hYrdz3WtZuU=OcTXHpk5IRE2?=3kWTM1(##3okp+JCPzBj|X|4Pm=Vo5#ZLyJnu zDlacL=bZrcZ(Hve`<6yxg}h`%^@XzE)q#K0!j@0{7i)`i`2z?nE>B@=Vmj_mxuoBD zW)~&1j?ng?4jl;jPG74xi-(}-xA@&O+xo$cr?k2@MRoXx=0?#r0zbkKIR_vePUs(~ z1*j@zy>HJKWI49-qzfq$bNR74KVY(4tMl2(s-e4F(8f8o)JUfZ$Z5QTF9zyMjWxwl zR^?9qPO?E2)HKJ0?U0%KbmY!lb&X#+!`(@LI-;^3VWWmUnRH?ay0&X3Jo-)jF>k(V zWL_QF%}ta$G{5+>)&y80b`tnWX- zJ2#M3JLhons%j%jfNAnFPE5i-|H>i(3)>c zJCV&5dKG&OzE!ZiYwRF6*VmRmkK&kMWddcX333;YBlc)dmB#gcGAUm{ty^WgvR3)+ zVoygs7d*i(n;YHO#W;7Gu(MTrq&O&Z9B*Vz+t1BPpa!OWkHk`eun&l3LpT_@Cb4yJ zo2f|52p#)4^1~>zAoMRLhLGjxa1uZj*C(b+T>L7>FCgUQfg1##+d=;hj$6~}qi294 zPGot%`fOa{V*XvKtaB%owXqi`52mi&rvjOb{pOA%o4t5PQns-J%-NJ?bBoqAA)kRU z6}Gi}cRKywwp5LHggBdDT7gw=P%8RmSjdCv{G3(ilvh1V2anDetto zVA}rW#Tk_VzMPeMsYSL5C2yx?tYOD=6+y?7Ha0R`>6NgRI@*2gO-q_uPvT>C@xWtH?BH zXJvff%)cY$o%yQ4bjyM8y!jcR+nYRUfmaSXB5EEBZo1~7WzfsiYAmabNO+%dO0$}^ zq+VY=)9O~?BT8=-Wk!%Esg+r5hM%nImZ^MJKbF5W(ZWFS46tZjYacyI+hIMwHa@S* zQ-R)^A1(Pjd@$J-5PCgKuFgf4x|Ev7l^k1Grw_L2NRF+N|4MMj7jZ0VcyzV68qoo& zZTtRHb9PFa$yL`+Yg#~O&(MJ{^y;;pZO(`JTLSH*B}dxvES9mp&4ocTJ%wob?bc)| zV0yJJEqXCM!!aB2(LvVlj01_p#A~ z6?U@S_n9fD&_r9S`0%}R{E#nT()GtO%#_2rkANh6jFn(+yw(f1KZ0dC{9JJ{D zs{CfhNSmRgG6q)3qf!X1 zx}#7$8=smZ=bLx&=LLd|Ls-HkIJ<9?mhkrJRX0mBYP8)RPi!rUFCADWGixJjH%C&C z%Roy+bz_TdL+#Ks1JJq&`d*PTD;FtN^K{Tbb%P2ERbSb5ZvNgRP6l4-{A`C%Rtlte z>VrY88mccU*YBM$S0~%AP5wF=i0^!Nky@@LQ#s~6&&Wy$HfscLjT#x3EhPBVc;#q3 zX5ZXj8)oi#+glLPyxcyZ(htB#cRPuJ|Hl$EwMtK(bV9eZ6^Fj>$Fm%uur6Y*hWZsX~3F zVGjd|Frf~d1@ytlB`ZGjxwDICBbpRLNfkkTCQ$npdqj!akGKtT0(oR580qXtmuu!1 zv^aKUPjSIsGBlxYAEf?4xmwXRsCjX6F?l>!GM+`!!=o%$$PLlXuqM3sJ$28JyhUAd zdK?3#@J1m+vxcO;1%1CU88QJ`o=761eAME4=*rf55udv`6^aF>*hcLfH$yOArOiex z_sRppF#}5Ka=Dkns}8AndDmn8>T}Y`MWBJIUYMi=lK4&G)!8*NVXEO^W^d59zVV>= zZe!~OMgB<*Vb#K{4@!yg6*`ama2EgS@jw*P3)`o%8wM=Fzsy{PM?4o~4nwYt++xPFAVcmO(OK646MjHNQKx&MaJ;`pKvPg4mg(`#Gof zn&OH>sI=Jx|1e0k*H3Xpua2$e!b*=GA za_GFH^LH)mG&H&&W{XM@+yXR|JY(oPz{dw}R}~d*;F9zKdKC8B&Tyu<*(Qf;yOa~N zX8>*ME{EM{wyeuhrqr34g*&1U*&A?M0gidY&H!To;sW8xfl4;THK1FG^s%Ypn zZya~jONMbU6i3;gw6`+QLn3-BIUds10&@f?-%Zwlt(uoZYKnj?)qyp;Cony|-{p@G zbzFV67+C1HS9BRDP)I_!QoVzndV?F)NYz0Tq+sh=3%=QVF!6y1DIGQPR_M^DAhG%* z9h&HJQTA^@&v)sG2nAx2;;C#D5epk2mGknt+eOkw40`hG^RjI^B2mM0>J`x+X^GNH zs1_n2*|?$^cuym}PMJE|Km1ZmcjirkihIo3j7`JD#m;*e zM{Dg#8>(Gq#EJST1x1)edZJ|h{4tA>a6zkHo_D%o#^t{AT($mly-s3Bo3ceOIHuE7 zh^XH^at^!q(53O~8&6j@K7=CPEmOs}lC=1?ZcDB{`t%{v4>cApQw!BRt=(TSk2O1m z_mX^xMtYg_(||I)tI@+Dj8$uw66pMdL@kpFD$Y2GK^q#MoPx6CPhpk5lQJ`T+7CB2 z8Vx(Y-m5I#jv>vN7IfRur7jVAeg>%MzQhKVyO~~Z)k!_#rW$r!E9pd)xp0=`?TdDycC>3O*5Gi_nI$zR0 z-&>w%$2+2GY(%exca`N44R$M!RNzmt&4xa&<$pw0HWEX^JhtH;7%}5bWtR;{>tl1* zEG2Y-l*01p?L)BKTElwcmBCTp!R}j9DOjF@bX1NcK#e83OiwvUb-d<<_YC`zIBMTW z^kxwUrrpVQUG)~5=JkAEQmG1F>-&);&gp3z;rO-_H^fVi8BAgedChoQo;Z z8fuIyXzEb}lCa&lMGB3R5m&GUh8Q`_TZhZm(ECMKiGBtXD{%H-Co69_B zcfA&h@s$28qA+PFH(5Ykad>jvBKEfcAoqe`^n$PaPO06Q%@muD*%L|U)p@f_?i)0K zwC8PA)iyj8gw#~AL~9Z1_)f4xzGYHY+hNrHs1oOQivvv#X}Ubm5MD>asG?!ZPw*KM zA%3%Wxhb_*x3@=0UO96dSq4T)Ap+yKMU6tLrbUOu#v&#ZWM1M5LC>)}-UFO<|EZKS z=TVWuQ9r4IRjcLFX4E0+CAArm?d}M?+V)RQUG)<2p4GgelZmt_l1LoZs7x+^+r=u&k1Me)N*VQA6zRk^n9K`Xd*47I+q$n7Kszd07 zq4IoF7C0Ez?xNc6%@tMg12M1DVl+0)OXH^AJm&JUG&}C_5%RAzp@)54>2IBi1AW%_ z{I=#Sr>nxl@c&hE)^Aa^d%Fh#B?JWlDUpUDm5w15fuTb>l#=e0ROybPON60^j-izp zQse;!7-j~9A!G;z92$8!_WP{;?zP@^9P8LW+<(D!U)MLz^ZZ#T@*KARR*J zV(l|w;5r?+@g=)ZRdnB4TGi6rG@Gj)F)P`cTmBDs_cK@CmmqF(``RZ*pa&n zN@o+y&~{{ledZLU?74|qQOj3_B%jA^v5vXnKFxXb6>xuzCl=3MlRHu1$k`}Ot_hkW zzy9C2%O?#*TRGXWrfY?PF&)b+d&x}bqM)+Gd_PVB621VOX#9uvMV#s>3 zY$2TFdI&yEW?UD9H4c4XsN!yHaS&OvNr-*(y16JDzoqTSxo3DyKwZtjuwS;DRFzOA zmmv1Z^?+lTpTg7PsKBtPfMuu>?$5`~cJ*aRbzwKKTFm6VC(i8RR{OM^rw?nHc zpT96fL&dTs8B8LzCdlV{YrB($#w}b9X8OY$AI31BJop$Kn+NYmk8G>ws?ggZ_ik(c z6lJbMiNmRd;HA8F`GO{rK!z*ebY5$+fmwoXV{0+yH5ZwM@`EY*b`MMY%6FpQTR$zOauFIr~4(_pW?) zLPF{@#2eT3-XpEdx-7)A59%?G^N+11u3!Z~f#w5VL0XdODt?1RmRSYcp>~w|$C`)S z6(#`c0+r4^xH|&i!vqLQyhAxnNTLapK7d~J&5qj`*RS#qO`KZg4>VvdJ7LZ*?P6{V zqg>ymkF1|Z0CWFpFBouHcJCw^?qre??wJVv0>$;aXI%27o_VR!{P$$sd_PnAq)dP6PUOk;juIc_@+$(kk(OJQV z4{DFp)Vn(4CE6l#>T3l83V9hcItwGZV-=r^(*OLp9pYMh5Gc70|89mdW3dai@2m3R zt*%(76{E`oZm5E?%Ugq^A%Z1z)Av;oYd<_sM_StVcMD$_GPXVVmgF-uW^J}uo9p=h zLQwAB_H}&~$YG}A%92+a9m~{(c8lf$uwmM`3P`FbE-IkNmA=`0=?tb!8#T>#PWLAR zUI0o}ho@N19(8s~c5Z-*$4>&nM!Jwg=Dn$grm!I=)f!plS;slrHA)j{z6SFfUDZ$TZE@*XR4;rM*n1xKu`7S0i4_S8K@F-%J^8|#kNX2 zHH#>dzUaAY^CRz$!Y}L|%}1hUUVUeLZ=cLe!~>_u-I%#jIKSw1U#*v!EW)-1<7N`y z$m-8-87*N@TCjG{ar2_kYT4*4yGa;~USZF^C)KOJ;FOXyOP+gs$=FI~@s%v(i1vr~ zm1+Rl+{?*MN%|95fYCKUbs(ebA0ibg)1cEJ7zZtVFm=8%=?jS9u|-0*29N}nKigJR z*fW`OgE9MWwv5ofW6S)D66i6NHm{KjfNQ+vOt(zi)F%Ogh1v)h*ostLSyZEYmvG#I znVHy*0Mc%HL1;(xGf}i%_gK;lk#bH3eK|N=FiWCVH%ZAj>oNVR#E#UZ>5uLoqnR z^yo-*w0sYI8n`b+9VJz56Wd*5W$a$>ED|)lU$1&8|1&;~A?kQxXvAzf-b@V(p-x+x zkD1#72*Nbf_4PeXh__|?B=ZA9U+nShy!|O%GJ`T9hEng z9{D7HL_LQr$2xMjQyZW`TuKNeVBPxA-19AMseZw?6NE$xNQg*nJIwhSO+i{IOE<{a z2>I8GznsPFs3tmkNyBuY6Va&-4~}1t1MUe`7Qj`=!Nuen1{AeT%|Sl!4CyLFQP{W1 ztGWT|qz{jw(qryP<6Xf*m21NZRfnbt%GU#(nj*8vhPOvEwGvmVwvj zsKm+jO1ZqHpOQ=|Nk+QHSZvn}GO1Np7#jQjx36*ZB40`7TKNGS)zKV-Iv@Mc;+BVk zP}6VznzZAEQ@`dA)`%*NmgB3K86U7TAP}zNCZlhIVy*F!QW55MGVdBphd0yOZl8@J z9A{`-T$jg)AMBIg>ZVy6U%-^Nab~-10i3Nfk#^+;0eTPrPuKY`+6f_Nv3mqUk%Vx| z_-_P5mK!qtKcyDH{=4};THS;awV4vS&iPvuV%MdepLCtHhHw{mRF8W#C?g zE#A~5nm%w2kBgNz*>R@y)9vekBW`!C4WSr>ePb(e_2&*bPzEVT^)o-aL`&Oh_g$+K zR{aMW+BY(s57^{=aL=l(?TN@}UvjUM?FVEwi}q7G}{hMT&1CtMbH)hd~5a#}-f?)fN#(AR<%t+h-?6IHc~4~G#1Izk>V`@TreeAL9Lla)wG9oiA+ z-Ja(oTj-)t`lwC1nVB5)0KzIoaEl~z_hK{hQAZqXmO*my8T8Qbi>&pF=zD&YKtakX zGNz@|09$xmHoaMbAO>yqZHs0rNtvm~K4m4OIkI;5m}iQ&3qu8&gJnRNkMx*Ll5`pp z1f_p&Nfg_ za?9ePsJgUBWoqh(UL4W63TKvh0$EtCkNB1!EG+$9HZ}d#HG!d&p--vgg06#l!io4~ zMh+`U5kSL@nE%O~vBslz`u^9o&fmM=SV*C{=2W6nf&Q-_JK<32%8&Fgxb!g-ZJtta zclp$2U8(v;v5pQ(?H#N&qTrW&Mc$u^7Dkn+U|dqu1t|`7SY${c>!?N(@0&|q zE*oh)tujq0R1Rg6z7+==Q|F>sI&P3cyF+^?jOz_N9!m@gQe=X?Hvhh1@ovbx|9!*K zEv;fb6qo+T?rr8Y@pkO}Od0Qe&W0X{lUe%mjY^_S%&GKnjt}@$`S_j<=g0l zW&@z7BFG+NOS|&^=r&gahjIRPM6g94JNq0Z0z3nmVcL=j`x1Qo)| zaxT{ddDSunih;{n_oyV`JP&0Go$JGPQz{)U60Ql_dyv7D{FjDTv~0_gUL2AjY-$LL z;;GQQh#0e@4-g&RxxOyh^L%lygD#TEKi0PSOZH?n$)h&ys1U~vUjsl+q z?B{EE8-o0jgn2Dc=-h?CdgVM*e=>@39+?=lAJ>SxkT^=a zW6B^Ys`|CV1UIWt{L9&)!-8VQ<6|qRc^}go!;Ybi_T}7Ja`Cl;EC!Tnr@{edXY66Z zzr55pI@gpr=k+U`$)4vW?wWwo@AFTCe%FXC zlT)WVZ?i6LQXsPZgGzF94NEI$h(An(%aHK-Yl5kUU(>9gel%wve;e~P#zM>m6TE((5h*f|k@(STf!6kSU8&dmKX z_G~7DP707-bF73pe1iTXxACTfr1FTShYB)m(-sCU9gd-{i%eFv^z^v3u&QK`+{vYw z=;%D8P%R?acH68AHTR(s3yyZ?9WadOR5Cg)0*kSq9L(BDFhaU^>N`paB#~aH<7`y7 z78F=%N&YAbi_);#A&xkF(&!(hEl2S^aOE}uhDx6B-5vh>2>$6{)VB(3@VZ}=f)RgD zavT44k`wRyIPsjaGCg8a_+3bguVn6GK|(Bp!?` zr$L%0{g84Mlmt9n7vmnn5j56-rSB6!TRyFK_6k{8<4A*D%=H#o@e&H{1q4_RM zsrF$doADR?_K|+PD2+NigZcNlbm`V1@DIQXkFP-h^|YHFHdK* z`OLK4swK`GL__OW8u#VEdu<)A{F^f#(ssA0#vI3Id>8qA4}y@vLHdWm^(FGCQ?4ylhPd3J#&-4pZ zP}RbBN`)xLUKA|v0p>_T@-z1nik3$rT)G-Gxn_JBR5Se}mNiDI582HWxTnW$bL1J; z*Ewo=%7xs&P<`yvOD3`BIIolVbP43d&{^!A(8=ao7kgnDlfo-^?Z-z)5nO3(eD{^u zez6@h-4g$2Ws$bTt!HpDI(wqZfapUTx5@%5p78VLZeJrAu6Ast0!UMBN+$$iPaq;RtO%9%WBQ`Nf>K`- z&LUCE(`c)y2;J8XoNxU9LVDS^b$h3$-7pZhi1@8SCH*v@uqPuhn0FcQ?`5hJT__~2D0tjZ2X-jI-uh{E z;k|J)R5qT?GSm85cOT}Y!M$?^^)8!7WCH=kLBuBQ0{_pi>ohOTU@?d0E zbOMesf^9bdl6l40q)M_@WuN4Xs{-b7tA1 zM7v9+yonk^Ey~t11j@>jc?2FF^T1z2#==B1*(uEFC?50p4GbBvaj{dj(-bMu;z+)N z`eWPoI5l$NVQJn$flV1tzbdC3KXUI(u?fxZGjmrr2$$FwUJ41@pQ4=+FQT-fLI2o5FHuL%gV7p;Wy5>mvN zw9ndNsH4GraOxIrX>y=2YzrT1~t0Y?9uBvd2ewXk)A-F7CIf_Gj=z#@yaL zB=s7*hM)M66UcbY2=p0XkY#DZeWY`ezSNFruPG{Z(b=Dd)`AdkOan$ljOYzt>rWOT zt!=cDC=rD$UuF5=m0O9{p=h2pp74vAvgV^Hk~j8MKi@D1IzsbW==3}5fORT^9;oZVwRN0>Nh=9)k(1$=IuDnxBG z3#GTPF3-|(W>J!jr~j^PticfWX8Vtd(XJm$OQvXUdk9>UWhfAg)h20N%GOZQP#4wn zxJT_HM@eWXG*6ivl`?d8#>+G;Lw(k;{yY$zZSJuC)SsPC;2^u3;@+KJB~^KAq$P4Y zf~{&#*}3B^!5JZ>EkvSfS^lxkG+B~k{WxHnUZ%dyZTH2>#6B@kxN@C%IG#s9{}Ct= zv_(Ic1qCQm+|4Ms>G-@P^cc;;jFEM=8ymT!c~3t{V_nP~ZYERF7>so^Y!MWbV`wW( zCV8j*v#HFyeCd7PLtVMl_f;ucw&p1B(4qF<+2aN=(`B_RE)OPf)_5 zvIOh+Oasg}zbK`NHFp)X-_*G>;pcgbck_mxCBc3+z68*87ewYT)06t~(U~s;+6WVd z@HtKn7LJ&Mcn=tp4}oisG}2t9V9qW_9~;f_nXjN)VUJKn%`$+CSSu$xU5+v?=E7Uv zQ9IJL7n%KgbliXb*+e4yJ7_ZS%h~2% z$U4(wR>|IE!d5*RnazbO!(V!={{PMs8~>Lt3U$Iq8dMSx`H!!nmt{1p|9=vpswvo5pP@(cvn7){DUJ>Hnd%9O0#{wj~Ic?z|{~*5Y7cKM# z7U}w)e9H63BOS|qiFj-N5#;Kl3ZwI?FxdPjPE+P2ff0|O6&i?DfNEWr5&O2WQX`L5%RN8`t-NE_4e zklx@vlc(kv@ct>>?!qKC%;b#r4zxYHej|G$H2i4Irp1K4+gNY_S*ZIEf3(7cFKM~# za|u~4#x8eP^8J{t9G;!rbn1U()hC1_6|n7t^}2Tl1M78zhR-|tePm2Fq*j6hSIcyV zXR)q*{Un6R+q|uq!K#~BVei5`GS$SlyCVdj`Zi)}=K${$%p`*rKmIkVqyavMZp1Cz5h0(zFzh4(QNNE!Rks+p!N+-Z>V1c-mC3sUP`fnog87Gfl z`d*aC%l>vCo!F%!+ z)I1DDl#MKScoc+tns`!K*CQ=f1p`CCWXkf12f;i;l$*eS_y;f7*9f z2H*oyjVm)Tmn=|of16l2>;6n@lb#(sbfLKXVyO@CJ7=ErZhZ0iHr`|DxTO1hXK8f# z<5r-&l;8TLPw;60zr_`0=n{T!g1wRKE!d5wH*3aM?ePP@Fgd zezlaaj>I%SHt$lD!Y%LMjyo06XFV92&MR!*S%2#2QMk~b%^D(OREc@-)IBf!o#rrP z>YHADw2aj^3wcyl#Dg46+lp??InYX+$S*A5LPTsbFx8;4=WRpxN&U&F?Pa$&;_DVl zjnc9^sH=*yG{U0y8{s(KGibiV3b&tgw9{7*)Ukf}M`Uc_uyvYV^iS)>yz3lhC4G5$ zf4Ox(-|y%SXZQAMS!T`2*;|p30wpV~Li?5J2sF%UN9XuNEDODd!Ap$yzduGGZ)&*D z+-=Hl4dHI}TR3;~Pv;FK=vEuOpM`&HQp>c@%z>UGzw~I2Z(s{jK_fVPU{!FVT&myA zA$6a`gj}6P?Azp&CF5<@^&Y$mZx7kQVAWc#4j+eZo(NxsJ-yhvCV-418rCBE%hvVi zZz!&K{hzE2=iT_wZ&q(dU_NIGwST^i_HPC=L2E8WLQcD?C?-V~JOg8KKVQBr>9z~$ z@ZUEV8q*D$EgSj^IkEBUFVC#EMAf_ZJT79Mq4ro?ekv}W$**LN&IpxdVnbb5Y*;7s nm{I>&>IL}unC+d$|4lQ$c}G6pd$2$KASgfF#1s8d@f!JG@#WBm literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/generator/generator.jpg b/local/htdocs/img/s2preview/generator/generator.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f4d0b121d0e7c4eadf246f38fd1ad903b8d68fa8 GIT binary patch literal 10141 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/haven/haven.png b/local/htdocs/img/s2preview/haven/haven.png new file mode 100755 index 0000000000000000000000000000000000000000..6f0cee63dc5e9d35d5a8ce0d85a91e4402793d1f GIT binary patch literal 16042 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 T<$Dwe_`84ip?bM0D&+qFL7KmR literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/magazine/magazine.jpg b/local/htdocs/img/s2preview/magazine/magazine.jpg new file mode 100755 index 0000000000000000000000000000000000000000..d73945bc58aefcde0d9e5dd021b0bf79a3a35a25 GIT binary patch literal 17795 zcmd_SbzB_H(kQ&RySptRxWnQWV1eN79xS+P0tC&nI0SbK?w+8FJHdUC;2H=J$jx(} z_ni0IcfR-jcYnV-(>v8YwNu^I)7{h6Rn@1As}@9W@YPp@NdORuP;s_}ajAO}E0K}AJHLHlz-M@PfJBE-hR#Ka=QC%_@3BBQ3J zB%`FDVPFH&(7mLmpk(G_e#ybf&BIN@BmffN5@zG#=K6~W0y;W67A6)cHa002EhR12 z|MBs=2S9+1K!(79gunobY-m!-%q&pQs(?RC zuGjj4`BlRoB9wn<|CPl*>HmQU$f$@&D1UIQ1b^K}K|)4AM*0u@pBxAXd5MTMkr`wx z3mEydEREmU4``tUb`wX~}Dr`?+{sow{xM;E_^dt%s?V z@_!oW(mxxkuN3@px}VqOEIZYB7W{Q=>!%-*UBYVcEi9!3@qZ3APA!XWa%J*}qY{O4 zgUnS}42H~%^2jf#b1|mO@C35dPfYcqKk6eMa+ikNXMibXzcpnFId1MX*lcgLV6`jkBmFMKR zO3!9Cm#V}Mzf;j14uQUVtkLv9QMle_e+m}j(6WCnQtmy07I>E*&W(9{J9}BT+0WY3 znDA|@GfQj90Nsa>rUbjql8y!atoz;8S(UX)MwGQe|Hlx1^+UzsQAaB7ooH-H)6-`< z*w>u5wV3B~DJATbby_L;e}x9vXUY@lx}SK#Q7pASqh;~k(Z2zUn}&8Rq|#y57Ex~8 z-9nL6;v(zNz`^SwldVN<92$A{yr`y@J2L!!SLBAf1~$|l4Fm<}B_Oq*dYZas;)LJF zCJ){=J_8VVpQp5EceqbA{D7^NWd_RH0)?iIwK`Sn+9X!*fvuNd`ml8flUN(@H{c4F zckh>@&8cb;WQae%%K#_l5FAe zu?hFi>WM5mFC5LT z_c633&T-PCNL$6a&!1Vomue0+bzvn%4V&H95h|~?68VjtTl?Eiz0z$ja8>~wvkf87z854naqDt;>>SOzEZbI!}^ zj=+c;@ZyirdS=H^bJ)4yMorCax$Fs-Rj;?za3L<+C@*Kil@Q8OdfDtFoS;MG32P z39C%@gG5SFjHyXOXUETBthTUzq;jAgn)tlZ@)IipmMbL5v+V$+xmYW2zDJu{t(;>& z8Lu!`l-vbfW3u64ht2ZO%~c#OvMeNizvb=hD6-A-M;S3)ZM8w_5jlvRDG}Dp6j0?y z2~my!>#|AHN5D{}ewe>6cM&k>5)v71V6^{81n zQ53_&m_>QnfVbU($Zg}K9gWJV}xaph`l_z@I ztvv;DyDcX#k&^s}N(4)fCe8(BJUv~n?oVag^*Pr`tT$|MWted2kw8bhnU8A@?(C+e z4V#B49^F&nNJzA}ZSb=}lVGlkyF#%_c_kL2>$igq)I7*{;o_lthVHlEK}toMZ-s1C zv4}<_+X)PlblES-S#rgX+gnFEs)ouO9GMM%n3jS@+cnW&#;(ST@d4gUwPn^*>!GQ& zpRuH!+OTC6tQZ;qh`9hr)I3wv`xPV0okQz!TEKCI&3;F}55EDIS5Fd8!9N)7g)a}U z42C}U)r*HtJ-mjOeL#Hlxf~u60bVJUtcGYhe@-%T5Kc4$dt>c4+Xf~H6~w_Xg7eGL zuF!u2(s2E2RUAr9WMe!lRPp>?J0>;PbD?RbYA0rh9Ne`Z>r2E0>1~^9wz>L7p@62aTKm6*b5tC%92 zFC8ejijmxp7r{$6JuqIq;@K@fix^t)0M94UkLwkP(Cb@P9Gh{SqOb+_^W%CM$%Ef_)wMKJzUwtLMx#hnjGM7?*8#sfD7NGB@c3~555};2|v3x}4!%D2b;J#iw zek^8uhF<1&5w|9^06TfO;D=fH`0UxVXnL1%R(Dxy5w}>#`I;`AuJ0?YZc|LrK0CUW zj{VF_HhNAKcH}G!Q~IKIR$l>R=TZ}IhYRj3Hv9Mr@oWMKIS2%QXZR*xX#CmD76piMZ>b}M+CMzce3WKYQA~zJH+?e%IGJHMw z5MYXVn@WduK~p2uzIdxRY#?}=k`;Itq~MT(DhWR@`>Nu#@pO8}67;@tXrpG2nmTdb zn~w7NZBAClneArzN>-s9*jh^X2j=4UTD1UB7 zzU_Oe6jy5~|Mtz^s>QR^ALi2W9I9C$O4x6}Qwoa6bUW;uhuBhf@1kqyWE-;7o72QP zKe6N*X6mO2u(oB}Bp6)ZS$OR<-Eq&-Q62@DR7-4kbePYQhfMwk5UBqLG+Eetkb|p^ z-9*94nny3~)w2OJMq`;|17gc4+6GPO=`6cn+fMntyn6p%#^Z_Mvdk%U zYu%LlZ+6Q5gDa=MFr|N$Pi>LC_urO1r$#^A+v{sF&r{AbW8UAOz4|Y%veFOn;>1j9 zQI8Jafh`}!e#uMy4Lpti!U+Gxo=>|O&VP|{k~c&8(5o%!x`rf-5y9cJKNTZbvAnNc z!G$hKdR@aGEM!JaI-KEDUBYV4yZUeElh@QS98N$N3UV7B5!Awa(~2H4UXMLAh{vYl z`PQXwlho};^Ij82gW(40Js0VZj`%H}Kf_YRroz+2{ONqf^$l!_I+M;8==Y7I6X>xA zvvKloSmp{U#DuGu;t#5EN^;2-iF>TK^MDx2K`0QD-;-OwS?s5(RY4tr5wQgC zC>5OuF(Qh;BOyN4ldE4+dFZ3QF+(rC4SrsEa{9erEFV+OknI5d+CXOHD-zYh4 zIucA8oP07;+mj&&?um#ep&^0pk}uQt9`mn`kaq>DI9EAgyYHZ4p= zK~a<>aYtB3sGwPAvbFVIUIFU9{mHMR=}=h*#Hy_E{}n>a{*8!8@j&+|U%ORFn!cc4 z5SOz{hTz`TPakAg>J|*E{QmBg^lMm!YJLm@0t>hd>XRly%0;4bj;`R}J5;7FD}%Fg z!5j^Jt3Mi7$QMVPG<`e+=B+p6)%L8#$$)R5qv zI`}kK(g7=@r!j9}-H!-$%{`VsWcLb^rGl@fDQ5iiybJ@|ewMrFoIj;}GaOqNi9DPIuWakjF)_!as!JRUbFRKincUaK8L!1%cHvELgj zB@^Du>fNWfg9b_RfGD`3GoUee8d1Ip<%A@*&)XzBw|Xd0r44amSot4^=LUTj{uH4# zF0H|*bX6NMtzg4d$Rq4BMgC*L{lZ7#iIJ77g;^{s8R`8@LJ%?r?|ZPgb$%sTfKZ9V zRo{zMmo!G?yuzw1LlqRf>??5zo)8~}m!hAqY9I#esBCUaBE2_Kl)Go0V&%Z3DV*Pc z5atxp50%yqZTi4u7W$Vfil4}DNPJaKZf*lU2)kBvjgcdDzEn7QRll1v1cU>#58_`> zdtn}pwHuHeB>2IrgA^4fhxB@TdnfTqJQuoiGDT`=gB80C2R@H#e)%IGUG2Il1b8Ov zE;b~W3}_8iL~9y*CCXvwCL_o`{{~RGxkDq$MLVv$g+JZlY}wTKBP~8xVriUQbab?} z#aJs3_{`Z4JV<3H_W2_%pIvM>(qL=x@OEygql{G3vSlf#56uJR9) z9!AbGXSg|6_5%8VC_~Tf6NXil6AWB$+7p^AZJ@m5XN?W7?3|zcM?w^7gRTwIgA+TF zKt(MJ5NQjgFE~#-P{4Ln!s~m&{6v{W_99YU3*|pUXaUUs8CmDe(GnrffHY*6jM`e{ zH{e%m&x0Q4xn1Vbvr3{Lp$Mgr7kW>dR#r+vKm7-!vW(-|g0_>r`Sr`&BzBM+RlD<8 zn;M$f^-zdZ@@9|Me2v5njvCFIS-&&Y!AfP@9Dfa}?hTBwrj&X{;3lP~h;bX-XXE5CC*k*kWPI9z8b&9uX2)XW#ygfzwIz4TjzL(s33I4fEy z|8|NR84{Iey#lZGHK3zE6-fIHsA*3z6*o50Nd)Mvx}l=-@R)H)Pa(~A;9xx!&RytB z;dZZJaGBD9?cquU7(xxnk^0P0iL1>rNFpp@d@m&wU02Xunckb57JH0Ogw+p!E>*(v zYuUAY?T5BV4*xi7JZY6w;eGn^P;M!ql-|s0CQyiB_Xl z*N!kYETbtQ8*n2>zbAUJgNlW8jmCm>;3equsPWC>+c>^a<4RaWcF!s7doKXWAL)5; z9rA#w{iWH`))GND4%nL1)Sy6Whi=1>pVO&`Mh>S{gwQ3(ti)I***6=9mB@VT4xSU6zSKE|7- zx&7O4CqI%P z5FaH??<2M%GHWjq2p5EulX0wh_>k8A&brdK#o1Y0lc$9dRdy=TsU#`AaRbVTF&!N$Dkf01|82Mb~CAs^hZ8We(nbF=q&M-3I#Z6^03J6hkNyN#?`3gKcx$a%mTL zi;beOhzdJng&sl_Lq;^UJLC!>e|Glf)Z{RE`B)n(bnR6=EDFE}4f026kloF;LmQsu z*$L04wjv?zQLuIuXhC|$qyE5q)> zx6@#SlqD;!4gQROPaP)V;U&=dWOSgJwy?*!0Qxq@H!!L|{&|;lc)h6(UMeDC|5CPD|xBG?Z7seJOHX`ccaM>_m{jV{R~*!eFi|h6Dk-HDqAQNal%Fe1iCo`-L*4vm(BI!O)TB0^+0HeF@jd$}38^=p0X%ZAkz&@LP* z{u=QI`S7F%@4h|%X?37EhtJN#cFZ|rlCFN7G`r*ug6`z(dqff7mR*gDW17)#K$Bg^ z+}R#rx36Tr@Sq*V5d7UoWa}UoeWaE}Yhhu>WL2eUoS1uLsY<0aIYHb{M4XOb%e&Uo ziEN>zgIX)XxUx;R2AIqAfvFSQP(kSGDF7+-Ac5AEGf;^u9i?NPG@~fT&a#1TARYh* zJ#TU3P$D+Bl&Y%13Y^}^NG~dlr`2%%4eu}K_lCfm_drqKbfxWY` zu+p85<4(oj;C!#=i8JBH%j#uf9j1>!8()m64%E7U9%zC~E|I!5-n*e&ZttnEl5d>` z{UEuTGMImsD?bvxO_Hu#DIP%@&|vqwYNvMrVFoV`QO~m&EkGFUodaieY~`yyA^R?y z;L6z&r~?s07#v4wXF2r0vUhNSKemD54DdF$uu++yN)$t>di8UUG87F^|4&2M3F%L6 zVqpWZ_n`os^o8Vr#$wm7WPc z*mR_*xpAo7Gy|L!W=+$-vR(C{Jb@ehN%{T<(QU zU%>(J!$IPdESo9gZ-7DDylrcDBUH?_|WpX6CSpL?*NFA8ogO5$g+v(BW z|7zITWh>TfdjW;Mf|q@3H+#2b&B7+}c(6k77*y@`nAY6>8(>WMI=U{+7JH@^bWO8! zc@PenPg~EQsi{75aX#xGM662YiR)tMu(1}|x}3Mp#BO^uw`yI;bRB_snDB8hxdDot z`wS@8b7EvQBF`1$BxLs=%;GL+b%W z769EAkD`h76p3J3XUWC{F)u~Lz^6WmrdS!a0h`pGZR6)|1v$RWW}0)KlRETul1OS7 zso>K|3e$ryb4#M%y?`2h5t;wFoq7q`R%1 zu#!B7(;Dk}^W7_!VS*Lsao%?RHq`G5ifC(|@gSmRlyx6D4BW9M3ZHHDk$d2S@9xd_ zFS=en$+Fm^E=E!dz9NDC#AG8EVftu)8dXQqqv_1eV_Hl5r>Y}iVld4xf-ljwHVg%Y zhNY>&JPW+ik0;b)$c)_yabkc;?JOTq^uip~XC-Pm)Ze_W@2YGDB5zZ`+#$b~MkF&d zCmjdB6qF1vipEyOww!PdL{Q;k79qxphPPpdPKx)CTs|rmD~OHQq!L3agL35(o2gi^ zhMwh*p-mLG!R7VB4z47j5jA$2oe>-6>6Bp9Sw!n8Z{WHYNC!VTKbk7en8ES4rWxLn1IwJN$mq)kmsomTihjgbW zb7u|Jn42TzBQgkfnKL3qdO4HUaszfV(FI-Rj1F7%^ctl1ohDCSm3;Gtu|Lj-TDQh7h?QQlCN_4_^w9D!kxN>W*x$y#@{uQM9Nr>NZVR4uL&r+p zz1};&5xl}tS6#SSjXo*5*IWv-CukvA-|K`Bgir4}OL~zopPKM|7F%fn>ey;B+F>)l z-Ob}AqkDHrOV>iWhn=|E^35PS=V&1EtN}4Rd&e?ft86`sGNiFY-ocf+1ZmYH@zP?G?!DFQqh(w3!0oJi(3Nxlpdn}QW`!nWxpK`Zuy3d zvpzbDla)e;2wo#pG&_Gj!cjDm!^z&5YE9?_=hY+z;Wkvg{v1H)EBt9I_=gWo;OjQb zM2^8r3f|_%nu+sz59Rl`>gv2xYL1{lIg8687352H6brE;2C)yX+%gXM%O88M_QNOB zS6((#Ikh&{e`>DsKWiJ~nfmaK;JqU1XZ2NfF>fW7R(C8ZA0Re5XW~$LGQ-qsVKZK% z+W=U)C-I!IG7MBmB<9OiWI4sel$W`NtH73>Q!yi{4y;$=c*O7cZ2UDIlRN?l03#Dk z(fZ|I79aN;k_ox5mW9-RQSmDTQX}MTP(u}qa6#j|$H@jpOs2-Y%&qow~F{)|gOzP)q2D>iT5E0W8>EGyRHSmbz{Sk5PXxQhC_7gcjbw++ydi&-~ zuJ~aLA-bJ zXI(obf|gk*wIn6v_UV?M2^%=@X5~dXE+O+!**9zhY+FLMl!TL#dLT~p-n+-Vg_CWE(>~d z#-B10#hTkD$q99E{X~#2_i^;*y*_@N&{-c8=cZhZreFsC?D7X9ED|E3(?b={ZB+2y zH2o}&HR&9ou6${SuEe0>nR52A zCx>nq%lxh#?OE!cqTS%QXVI#Q#$-+HmI=vJ?#vj&Pz748AaPDcW0Lo$b(1JVu^H%j z%{_U@K~?#Oab>@3z{Mybw<^pZx)fcATBG%S21rqVyvNl9pE&uclgEh1xYj}q z=H1gXmThoCf7{4d#bHP*uF#X*DT$9Z*?TyTIhEdEq;1le^)bazw#H892W)m9DEPu9RzZ6pf7vN)iIFCSh@3?u?dG@g;6ICsOf}6Gjqi zr`}=6ej+-ryf{p&H&85-XJ?aVoY+FIPJD5hKt>J>2)Mu2FtZo+npJmanxF_Vh~cRi ze*4~!`b_Gv#ZQ1FZA!YaCC&eg5WKMWaeOw3DKVoC0}Ts$1DD{>EfaLv{XVPY!ki)| z-3NMXr)bH!e2+V~=2es5c75WzYCX+}Cb4l`!S&QG{d20ZS%ceNCviUTigGC?$|8r^u@9A~c(*-|O!2Xs|0l zT#sg)&-fQqdmUlpOb<>a!}1*UrID+X#fbwu#@~(k>=k&jz7Cm~KCv~|%H%hIZu|Vk z*+oFbS?G^u-~P?{w{5qHPT-ZH+pi=K{aRRP)kpNaWMT3zf~ZBgVO=K5a)u!2{Dg|eyu>g zoGJ|R8?df1SA0@ZJo$F7DPm7yy?vNUw!(5}%fcBLU{xa-;W&q(=TOuWCrdBgrl5r? z^c&FgZi6@T^V6qhW1Co!(u9FfO=i~SI%`P|F1Obz*#X)97A#QOsh-5>y;hynRE?NP z@&T35?B{df)7oNc%gMw4j|15OmvgbTQg6IE>pSF_>ejFbtFQ=t>$QZE0%&=7cu-$5*451j1mY;j1a3H7 zr5S4OZp19IhaQB-n;@7K%{~guek2K{R0=#e%gElf0Y)WHpCWDWp;1)qPQP7MyR~f3 zMl|e4%!26@^sGWGqYn>qyJk5tSEyo2!uHkf2gWt~`1ZAvz%ch7fDNvMhrQ&6u${{; zr>FOu*|$sTqlh`heDLt^QJ?ei3P5M!(@yCFV3{H)0E+o)GfyNM?wBEHDHL*A0CU>`d}Qr}eMx6Gc{T4FJbsS+*!_m3 zHtcY#*~8S;`6LbC_w}b&w(Y&JKCsShqYJS~2Wx*eJMz_!PV*4ZDp(Vz5^MYxNlZis zq?Mr&+KtHX&Le2dcnb+kjB$|B=t*iDfhVYU?f#fhD(fxA%DtViCPOgd;qyh&XOl*| zlS4#H_ztQ9Kk}BX^&=TLa!RyWB=Ptyy~Y331$@B|dAF&??%4mTso_i7!wa8G*}abu zQX;L?)HZk=cGLmaGL_0&|K3impy1tKLR~?z{i2UBY~L8pmvE%hm>7nSi$%~Y8xV4N zw|^V;Jmc__op5xjDRGrUd)=fi7SvbsGsXima?F~g2;VcCAlKt1gW2%fAmyObXDV+1 zJ9#+H5tBRsl9-3;xtO^;?`7@pPcmvcf{$6rh8X0Cr`Badiu~ig3qrj&;!stN4xh-+&qITc2b7be-;&`MAlkphDL;#J1s;fpS_#36MCPd=Ta3BkN~` zhjqVBRx#k&z zh%RrM!kONyvp!!jLv-gS1rKpC_4UMg-O5TDhfWDwXOh9b4Miki=L^%x^*I#g=-tSb zpmN5%MzY}fN~bCnqThgvB=QsTA@S?Jf~j(#wYY&Z;@*vl3WjUHi442a=BecfZkJyJ zI$P%e=LvmE9CGsOr>B(B{lV6V`MeicKP9ha+N#ZHxL-;Y&(Ntr( z5b^8W*=>_0F{N-1U9JgNhGI2g0G_K)z8_ZnAXMg^zic!ZupsO zf0>Om7%&$oNsfi+v zlShsMvhd|=hV06#7G<3vbA7+_9aA*t#_58nuLovy~}Sng?->XXtmWr zGokp5A8Rd;W+~jXOdx64lA5{)g|+MN2=`O`0N%x zeGV!n)dFa9Pu!3xf51LJWXzqY_7$y&vA_BlnNal}aU8VEIxOy}*u)0RCr-umg}EBus{LG zjsf*fsCv@23F-&>W*hmAKFUN_av#aia^r8k_8Z!hxl^4!X!sJjdqmh}UxUq@k&-kn zGe#J|2eG3?7}UsWG%8L{_r!7UQ({*_r|OOJtYC`ly{JHn-w+h4a9Cj|pK>oVRe>a9 zHWomT*5ay)?Pw|RsDJcQ>|e`NOGcKrR%IrP@R7r{*0K@Bm2uGz_a*pc^2!}VAx09p zd3F!8T&AT2!d^nWJ}?yC72aV!$_%bj52MVVPp7g295qOgRQF}sgRoHBGV%>RRLib3NPDx3K%&@ zJ{=aqg1poNo)24p>2ca^n&z^Z3hs9e6JSjPad4+$sKv4fLw&ZN)UKycYCM%}( z!8OwSGiB&=V$j@rDSD|1MUW^)eoWY{8s0+1%yv{N(+H$>6@JF}AOOY)I;lk_J;V4s z2ZJ&f&Gk~NLv$d9u|#}AB5kYvgi-A>U zkkhFgNBe+RD_+`)-T|&ir>os=WHdYyYY6jOxQ@A@-c?Ff8!L{Sp6kYE24k>L8w#x| z<^ET}DBCeR5e(Td zbRrbfjN{&wi7E4}8~NZFFA3RxowTz9U15zBw!~EW8uv+$V7&A^;Nn;ojpd_+vorN| z^$yy(JI^Nl%PqvE<1}rUsGFlRqlCXVMR0+~luf}0$IGGic4Sgpi2w)!#CodSWi}=M zSGU$m$TvK=`DEcg4JeG+`#Nv-Se0Q_{5O&Uf!e5e`^@^Y)q@?_CLv!bgvQ~l3P@UO_Jx|Z+4M|&m|_kWS9SZT(~7Y zU4-_j%9*pVh=&hc6s92i85K0r|ECuS1HUY!?Hr+>YA%8M5U1PpXbs=O`{$G6mV0(7 zQw2Z1X_@6_ZnpLerX-)0sL~Eu?{|ku4^N8pO!D9|n9Z%+fv=2AYOItnG)ffq`REDX^WRSFoBxNvAO9>;!_W9D8l**VVHr&$^MLC7xqoeg@IWx$qiS8kUZ zu3wXPmXkB3*pIohomP|ls1AZAOV4-=dVtSX@J?7ub>&e@@{+u3sX!RK(~!n8Nj|#K zB1y-MI3P3|s(_>4v?!>av|+Zftb#jcZzSf4R0DkD)qU>!rOlQz)t4O*OKhWOW%b6#Kwqaas%T5R4zV69Lk+Ieem0LXh`S8f zDWDfj!O_{z4y)0_ps+?!II##hCd5@wJe+laK@A_qwf3}C<=~3y7)7w8o&#bk z*n}5Y1;itrS+Eej5B!N|37Jiu3=3FJ)E{pNS2YFs;Mqh4Vzlt_s-_^mnn zxi;LVvE!EL3BWbYkKT>ZFqeVhsy9j4d`bNb@7YkN)e|Hna16hBZ+v zwptCsP0yHqt67$#| zeOL5al)gTT6#G3+l4>BVZr&#ztkJ&zb?z(7;XPc-O*!+nrYKb|c>{Uq!>I)M^Q}UF z4JGy`K~pav{p#y0Fg_7yQG~4CCh&bxfxo)uHTY`Bl)Z^EvY>3!6bp&EE&{{F+GFd? z)=ClO{pz&Eo`L_HGPU{Ttd}*r&F!!J`tv^dTwqYF?;7fF7+8zL7m}+F?}TNsOhxzC zYsl;U=?N-x+SjvxHXy+Gryn%l7&|@um^E%Z)HbS0dNuGXO>4OOc~KVg$4g-s7~rwD zGPAU(#>kOBD^Rb!_4TK1W1lCBC-rkk+_D4jv<3Aa%?rHA-FG~XIbmp{%ALnDL--|| z`(Bb8pJK(JTF0(A)9k*JgORhWpjRYgm4fU+l7jS_sJ{&yFs;$`&AXta=hBd;JxyfH z*XN2?wy5{LBJxF$se6wg$wpZ%=XjheawM_OQk?ziS48VD=`Ct`sAz6kqMm+p8UzAY zn~&Djqhi$OPz$1GCj_tD-z)_$w^leUw2&Q^HIWgSbU85=%lKnI0!En7B)|Ly$jO*t zJ(&fHRirZDP+u03L}amdxr)iz{6xQ@kA%m@I_sO^$I#D)*RMY`QgM+3R+U)h0?uGq z2++1lN|#P+iSGGnX{-8{P&@rC7cFy1Iu2q9C-`j=`ZV}fUj{Rh98*oo$k!XT_6kg& zy{n;U`}ycvK45N%*#4C)ALlMYYtVkbMGKmk;(C%}GqkLF_-#?{%C@f(dg{t@m-Ily z&;*s+V1s%os26d*ySz!)&e)-kUcomAK>Vo@La2mj3mO86f2(L7E}SLPby6vgZbXF| z+=BCo@-Tjh2kdIR8L2taT3eTQAZa6*T4NlBsAPAz&@v>DbAb=j9z=u%oE7yu+9J5C zNYOXel);L~yuGW#Juoo+)@8O;QRjTMGsja2ZsNmTrVd*#L4TnL^C!DnUkD_dHmbyU zu6daI9M}k5xDv5i1M7~`Vqc|qgttP z26lhh80LjFF2EZGGF}NuPwc!ATH=nN&aO=w$-YOGG_0oihmDR7nMBUanU+`PIDyD` zmW?g&dLNGtbaNMgiJ5hSqjfe*>`iC{)N)7_-PFlXlNa< zluaf)2v6KQQhFSz^;lX~Va+ra^G$(s&4dk=y+%LL&%|4I{( zS+9&)S+>N6Y)oZQd9m1!ZtK`}I4mF0aF(U;6ioCB`MFJ{d(z z4j)C0WJz8C8!ViWfTu%ce_YRSMFD8dvjQbrA4?4*tdtN@dRZtW#BXbR0(6fwWF&G* zhJ;D$#(K>c6sW?`ha~rze&!k7U$IN>72E@9=7g?tmR5`xX`8K5NQ~9ymPDK5>hW@V z2EK44srenGx$a9g-)@XcLAU2f&aRJvLT0>y+ky52VeyB62zR#+?z8mI}G#{FD z$Psf+u_pz*IpPH{nGuFW7;vpU8`fxG(8w?NM{NwO=jAd;3{$7Is@(W~D;#e>86l~R z{z1X#1DdP)YZ4QJL+FR_B4x~&GD8jpCMTjujVe?6KpB(tK_LgZ5uBE=udm-5=T;&c3I!qAOT7~mTUwTAYYqfcu6Z!> zh86wvx)!ub!KV_F!;*Hkbf+&%`NTwEv=*k{BvlrQ+j>Nwbx4N|po9|48@2Aa6H2#&C zTh{w(9Q@?9c_0&#D)+C1x~?kywNH@KKp zCPHElYQ%)!u{Fq7XZei{Z(F`E6&7;uzqgKE`rlNAHm_mNfz&HOuA7kuZT~RdI#x_H zaXh-N`3oN{ucow>U@Mid?>gd%E=+9tEWm>>Ns{)HO7rS3&mFGUWewFKEsqa}Une`- zKUGL{FKPK0JsZ+0iOGA6|H@{6NnH=>hj{egOCKh@HL<5m*->5jRnfitiy(Ei?Eq=0 zhgP@pe?zM%*!L?D+Ks-(dFRxuN>wmUF_(m-@8)GS4xVh*>%1>nT1h7#*sw}5CO4Eu zrZ7Qwy669TX-ck^C|zOTjomu(fpk95PksWG*i9P~p9!`ct}`rGnR2yKti@~LgK!3EJzOc;=@##GU%{7kb^5Aw1WlP?8tO2w;1 zpc3;x)TTF<3_lidG;;eTCe)w`^ZZ%DM|8?bZ#C*t*pb_4IV^#$NQ@F!d2*;JO?svc zUkyFo68ebPvzt-bOg%0ZA_tc@PgK~GN}#fA#H z-^9Az@g)9b)e$Bv1DuH{8>HDi@rgoIkP&rqq@Co03FP@NI>ppyv|VrlISvp-1h1MJf_+9CV)kffl%p zyIU##`EAO=JlOW@HQlNDKO<_TiZdnJf1~IA&RJg~H2B9K*0 z-c#Y?gF^AnL~MEL2hgG?c$R9m9r#={+Z8UPSrQUv3x?HS4>zB=BHm`*p58 zUwfVl65aY7sU-7n7^a>jF_4W=(_m(iuk zx);q6;0;6!1``uIdmlSxiMUupW!8s?A>;%(aESkJ03k}SbI8bB%Wj*tvy#Lj4W=<{ z#DN4+x8jF;YjNE+uWmkaGjy+G@OA>=vY3seevTg3U9RLXazjkJ%qS?A@wK}zdouM?Mrc=hnDrcu92jWxh(OFk8&)8ZaevVXT@}Q$1Twd2|s3Fh44&+m&@4;Th zz!raSmU^y&)3Q1B^}ftVFGOHAiNi`{^ca8HhM@HLD)yl=<7%+Ag2F4 z9#7rdH_COmvD}I0@D7h=Kz+Rsjq80qY}w!fEg||>2s_Rj_H|hmV3>~0$1djjp}2&K zyGZRhdU&;>`|>JQlIlp3m9&-(`Wm1ISHF}d>Un5>u~QXIt+|uT0pB4~ZC`#;X+#7` ze8r55e<=k*c(#})~HZ43-uqXChMJ-%>RQ_ z!up@9dN1wG|B^;(Xa8&aW|UMMP9JIb@{5HkEjP>Dc@@O0-nXG5$uFtmF#! zb*y5)i+H7+;>lB5!uDxN&P9pra8GEq%>|k`!Y@{36TK@FzuM;NSgq8t^xw<>4X21d Ae*gdg literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/notepad/notepad.jpg b/local/htdocs/img/s2preview/notepad/notepad.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f0ac46e55fe87e63feff7827a7108b96e1c3cb04 GIT binary patch literal 20276 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

    UEaTZO@=N74 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 by=R<%bh9|5NQy%w^5I`gD3S9_f93ug=e3k_ literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/opal/opal.jpg b/local/htdocs/img/s2preview/opal/opal.jpg new file mode 100755 index 0000000000000000000000000000000000000000..4c11fb314e1dedc9c0a9e16e7bd01dbba1e82387 GIT binary patch literal 13075 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/sturdygesture/sturdygesture.jpg b/local/htdocs/img/s2preview/sturdygesture/sturdygesture.jpg new file mode 100755 index 0000000000000000000000000000000000000000..5cc7ffa80150f1518a336878f74d28d4d4bd7660 GIT binary patch literal 19735 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/tabularindent/tabularindent.jpg b/local/htdocs/img/s2preview/tabularindent/tabularindent.jpg new file mode 100755 index 0000000000000000000000000000000000000000..2a85173b4bafd9e112bea76d51c215fbd1abab93 GIT binary patch literal 19223 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 Jg?qAq|JlIYIV}JH literal 0 HcmV?d00001 diff --git a/local/htdocs/img/s2preview/variableflow/preview.jpg b/local/htdocs/img/s2preview/variableflow/preview.jpg new file mode 100755 index 0000000000000000000000000000000000000000..b82168d76ec38108b26e2b31405a3ea3620ee8c5 GIT binary patch literal 23817 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 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/userinfo-lj.gif b/local/htdocs/img/userinfo-lj.gif new file mode 100755 index 0000000000000000000000000000000000000000..87c10f652192c0dd104df8425bfedd3d45768fe4 GIT binary patch literal 258 zcmZ?wbhEHb6l4%&I3mpe2H6Z8Qy4hzad0GaaJ=W>_|GA5OaKTZzDr01DJm*zYHAvS zz*r2V(@;Nm}H90nN+a~GY$U>X>X7k=J zi}Q06{@1l#al_P}*lDU9I>n6_0)%#BtNU$^<%}^{5x%0X) n&EDdKc?o|Wrx1gnP=}CUY6A}!BO?nh1Mk#nJ>hDK3=Gx)?5#@N literal 0 HcmV?d00001 diff --git a/local/htdocs/img/userinfo-npj.gif b/local/htdocs/img/userinfo-npj.gif new file mode 100755 index 0000000000000000000000000000000000000000..7364fa94b0fc6f3ceae5bb65da58d976ac647ade GIT binary patch literal 140 zcmZ?wbhEHb!&VUvZ8^5!5RPznJIVx literal 0 HcmV?d00001 diff --git a/local/htdocs/img/userinfo.gif b/local/htdocs/img/userinfo.gif new file mode 100755 index 0000000000000000000000000000000000000000..5fd935e7bc1ec8b596d685399afba015b7b7ab42 GIT binary patch literal 191 zcmZ?wbhEHb6l4%&c+Ahhz|5eaD4)T|nZd*vBrd0^tud8Ba0i2kqm#p52C;vP;`I%6 zbLTFA8BU>hx&m?7rZFpo1of5ffN1 zFY$8}^I>LBIcQSgDAvQa#zD(KYNcD_7Y7q3UY5^+5iMe@LJ8avIy-KAB{-Pnu(p3u rFyQ35#NMnpH$a82xq-!D+Ts7~ObkMdtSl*#43ZovtPH{8f(+IG?Yue7 literal 0 HcmV?d00001 diff --git a/local/htdocs/img/videoplaceholder.png b/local/htdocs/img/videoplaceholder.png new file mode 100644 index 0000000000000000000000000000000000000000..e49a238e2448fc68454fb4098bfd22c699629f84 GIT binary patch literal 656 zcmeAS@N?(olHy`uVBq!ia0vp^${@_a3?wz#owI=yOS+@4BLl;=8&~`zjDUQ}64!{5 z;QX|b^2DN42FH~Aq*MjZ+{EZg_Bnw z9l!MO$b|<>cbq?d>A|tf50~w{aOA@M z=kC3K|9;EiYwHhOUc2woohNT@K6gwGW%XXe$w&UEh*Pre`d$;ZA z^@Hc`?LT{WCi!%dJX+{DL7OWRMKz2mS*?lTpdj#WAGfR?n2< zWrr06T-jYGK8m}vI{3~d?&QXQ|BpLOJQLxrASW&M{f?woN8glGPA9ft!^@ffW;|z{ znk2Tku3qKHIq|bHD>*dF=4G|byn8kzIPux-FkYkZZK9G%dTSSDoSYXaKczA3JnPp6 zDcyPEj~H1P)*PDq+~4p})q@zt-$i#S_n9R3>l%6l8J{c8wmD=nA)>|HR(o%A&^5K( zhkG7YUf%pPGSMf4tB_gH|J%m1o4y}BFylhl!#5X-YZe_VxbZqO_~-^V`}LVtKYi6T zKW=!o>sXc9zb)F%MO;UWm%nxrdUSKbUrhl?BWaa+?Ay=Bo!@J%|Ma2Cx#Gurmz^t? zE##lCY_nW&-h7Vp!7c7()lB|d(ysh}^xtSzy|c0GPw@nXX|i8$MP|140>hla)78&q Iol`;+04s`eRsaA1 literal 0 HcmV?d00001 diff --git a/local/htdocs/import-enqueue.bml b/local/htdocs/import-enqueue.bml new file mode 100755 index 0000000..e09d746 --- /dev/null +++ b/local/htdocs/import-enqueue.bml @@ -0,0 +1,209 @@ + +body<= + + +
    "; + }; + + use strict; + use LJR::Distributed; + use vars qw(%POST %GET); + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access import page.") + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $iremote = $remote->{'user'}; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + my $ret; + my $e = 0; + my $dbr; + + $ret = "{'user'} . " h1?>\n
    "; + + my $iremote_is_protected = 0; + foreach (@LJ::PROTECTED_USERNAMES) { + if ($iremote =~ $_) { + $iremote_is_protected = 1; + } + } + if ($iremote_is_protected) { + $ret .= $err->("Invalid local user: import not allowed!"); + return $ret; + } + + if (LJ::did_post()) { + my $dbh = LJ::get_db_writer(); + if (!$dbh) { + $ret .= $err->("Can't get database writer!"); + $e = 1; + } + $dbr = LJ::get_db_reader(); + if (!$dbr) { + $ret .= $err->("Can't get database reader!"); + $e = 1; + } + + my $iserver; + if ($POST{'server'} eq "lj") { + $iserver = "www.livejournal.com"; + } +# elsif ($POST{'server'} eq "gj") { +# $iserver = "www.greatestjournal.com"; +# } + else { + $ret .= $err->("Invalid server specified!"); + $e = 1; + } + + my $iuser = LJ::canonical_username($POST{'username'}); + + if (!$iuser) { + $ret .= $err->("Invalid user name!"); + $e = 1; + } + $iuser =~ s/\-/\_/; + + my $ipassword = $POST{'password'}; + unless (LJ::is_ascii($ipassword) && $ipassword ne "") { + $ret .= $err->("Invalid password!"); + $e = 1; + } + + my $iprotocol = $POST{'protocol'}; + if ($iprotocol ne "flat" && $iprotocol ne "xml") { + $ret .= $err->("Invalid protocol specified!"); + $e = 1; + } + +# my $is_gated = LJR::Distributed::is_gated_remote ($iserver, $iuser); +# if ($is_gated) { +# $ret .= $err->("LJR::Gated users are currently not allowed to be imported. Sorry."); +# $e = 1; +# } + +# $sth1 = $dbr->prepare("SELECT * FROM ljgate.alien WHERE alien=?"); +# $sth1->execute($iuser); +# if ($sth1->fetchrow_hashref) { +# $ret .= $err->("Gated users are currently not allowed to be imported. Sorry."); +# $e = 1; +# } +# $sth1->finish; + + my $sth1; + if (!$e) { + $sth1 = $dbr->prepare("SELECT * FROM ljr_iqueue WHERE local_user=?"); + $sth1->execute($iremote); + + if ($sth1->fetchrow_hashref) { + $dbh->do( + "update ljr_iqueue set remote_site=?, remote_user=?, remote_pass=?, remote_protocol=? " . + "where local_user=?;", undef, $iserver, $iuser, $ipassword, $iprotocol, $iremote); + return $err->($dbh->errstr) if $dbh->err; + } + else { + $sth1 = $dbr->prepare( + "SELECT * FROM ljr_ihistory WHERE local_user=?" . + " and idate > DATE_SUB(CURDATE(), INTERVAL 1 DAY);"); + $sth1->execute($iremote); + + my $num_actions = 0; + my $num_incorrect_logins = 0; + + while (my $r = $sth1->fetchrow_hashref) { + if ($r->{istatus} =~ /Invalid password/) { + $num_incorrect_logins = $num_incorrect_logins + 1; + } + else { + $num_actions = $num_actions + 1; + } + } + + if ($num_actions > 10 or $num_incorrect_logins > 5) { + $ret .= "
    Извините, вы ввели Ñлишком много
    заÑвок.
    "; + $ret .= "ВозможноÑÑ‚ÑŒ вводить новые заÑвки у Ð²Ð°Ñ Ð¿Ð¾ÑвитÑÑ Ð·Ð°Ð²Ñ‚Ñ€Ð°."; + return $ret; + } + else { + $dbh->do( + "insert into ljr_iqueue " . + "(remote_site, remote_user, remote_pass, remote_protocol, local_user, " . + "opt_overwrite, opt_comments, qdate) VALUES " . + "(?, ?, ?, ?, ?, '0', '1', now());", + undef, $iserver, $iuser, $ipassword, $iprotocol, $iremote); + return $err->($dbh->errstr) if $dbh->err; + } + } + + $ret .= "

    Ваша заÑвка уÑпешно добавлена."; + $ret .= "
    Ð’Ñ‹ можете проÑмотреть ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¸Ñ… заÑвок здеÑÑŒ."; + return $ret; + } + } + + $ret .= "

    "; + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + + $ret .= "
    Импортировать журнал Ñ Ñервера:"; + $ret .= ""; + $ret .= "
    ЕÑли вы хотите импортировать Ñвой журнал Ñ ÐºÐ°ÐºÐ¾Ð³Ð¾-то не указанного здеÑÑŒ Ñервера, работающего на движке LiveJournal.org, — напишите в ljr_todo"; $ret .= "

    Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"; + $ret .= LJ::html_text({ + 'name' => 'username', + 'value' => $POST{'username'}, + 'size' => '15', + 'maxlength' => '15', + }); + $ret .= "

    Пароль:"; + $ret .= LJ::html_text({ + 'name' => 'password', + 'value' => $POST{'password'}, + 'size' => '31', + 'maxlength' => '31', + 'type' => 'password', + }); + $ret .= "

    ИнтерфейÑ:"; + $ret .= ""; + $ret .= "
    ЕÑли ваш журнал удален или заморожен на выбранном Ñервере, либо вы когда-нибудь делали более 50 запиÑей в день, то вы должны иÑпользовать /export.bml. Ð’ оÑтальных ÑлучаÑÑ… вы можете иÑпользовать /interface/flat, но мы рекомендуем иÑпользовать /export.bml. Другие отличиÑ"; + $ret .= "
    "; + + $ret .= "

    "; + $ret .= ""; + + return $ret; +} +_code?> + + +<=body +page?> diff --git a/local/htdocs/import-faq.bml b/local/htdocs/import-faq.bml new file mode 100755 index 0000000..e06eac1 --- /dev/null +++ b/local/htdocs/import-faq.bml @@ -0,0 +1,81 @@ + +body<= + + h2?> +

    +Импорт — процеÑÑ Ð¿ÐµÑ€ÐµÐ½Ð¾Ñа запиÑей из LiveJournal.com (и других блог-Ñерверов, +работающих на движке livejournal.org) в LJ.Rossia.org +


    + + +

    +Изначально импорт был задуман как ÑредÑтво, позволÑщее значительной чаÑти +руÑÑкоÑзычного ÑообщеÑтва LiveJournal.com перейти на LJ.Rossia.org. +Это ÑвÑзано Ñ Ñ‚ÐµÐ¼, что на Ñервере LiveJournal.com введены жеÑткие правила +цензуры, которые не ÑоответÑтвуют роÑÑийÑкому законодательÑтву. +

    +Рможно иÑпользовать импорт, к примеру, Ð´Ð»Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ð³Ð¾ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +Ñвоих запиÑей на LJ.Rossia.org. +


    + + +

    +Ðужно пойти на Ñтраницу Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ñвки, +ввеÑти ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° Ñайте LiveJournal.com, пароль, нажать на кнопку +"Добавить заÑвку". ПоÑле Ñтого на Ñтранице ÑтатуÑов заÑвок +в разделе "Результаты обработки ваших заÑвок" вы можете наблюдать +за процеÑÑом импорта вашего журнала. +


    + + +

    +Мы не воÑпользуемÑÑ Ð’Ð°ÑˆÐ¸Ð¼ паролем. +

    +Мы (админиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ LJR) обÑзуемÑÑ ÑохранÑÑ‚ÑŒ в Ñекрете +вÑÑŽ чаÑтную информацию, хранÑщуюÑÑ Ð½Ð° нашем Ñервере, кроме +Ñлучаев, предуÑмотренных законом РФ. За выполнением +админиÑтрацией ее обÑзательÑтв наблюдает ПопечительÑкий +Совет, ÑоÑтоÑщий из извеÑтных деÑтелей +руÑÑкой Сети. С жалобами и подозрениÑми в отношении +админиÑтрации Ð’Ñ‹ можете обращатьÑÑ Ð² ÑоответÑтвующее ÑообщеÑтво, +либо лично к учаÑтникам ПопечительÑкого Совета. +


    + + +

    +Сколько угодно раз, но не чаще, чем 5 раз в день. +При Ñтом новые запиÑи и новые комментарии будут добавлÑÑ‚ÑŒÑÑ, +а ранее импортированные запиÑи и комментарии будут оÑтаватьÑÑ +в неизменном виде. +


    + + +

    +СоздателÑми LiveJournal предуÑмотрено два разных вида взаимодейÑÑ‚Ð²Ð¸Ñ Ñ Ñервером, +каждый из которых позволÑет получать информацию о запиÑÑÑ… пользователÑ: +/export.bml и /interface/flat.

    +Оба вида имеют Ñвои преимущеÑтва и Ñвои недоÑтатки, но их наиболее важное различие +заключаетÑÑ Ð² том, что /export.bml позволÑет получать информацию о запиÑÑÑ… даже +в удаленных журналах, тогда как /interface/flat работает только Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ‹Ð¼Ð¸ журналами. +

    +Также /export.bml работает значительно быÑтрее (поÑкольку выдает информацию большими +чаÑÑ‚Ñми). +

    + + +$LJR$FAQ + + return $ret; + +_code?> +<=body +page?> diff --git a/local/htdocs/import-queue.bml b/local/htdocs/import-queue.bml new file mode 100755 index 0000000..10dfd72 --- /dev/null +++ b/local/htdocs/import-queue.bml @@ -0,0 +1,112 @@ + +body<= + + +
    "; + }; + + use strict; + use vars qw(%POST %GET); + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access import page.") + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $iremote = $remote->{'user'}; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + my $ret; + my $dbr; + + $ret = "{'user'} . " h1?>\n
    "; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + + $ret .= "
    \n
    "; + $dbr = LJ::get_db_reader(); + if (!$dbr) { + $ret .= $err->("Can't get database reader!"); + } + + my $sth1 = $dbr->prepare("SELECT * FROM ljr_iqueue WHERE local_user='$iremote'"); + $sth1->execute(); + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + while (my $r = $sth1->fetchrow_hashref) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    Ðомер
    заÑвки
    ИÑходный
    Ñервер
    Пользователь
    на иÑходном Ñервере
    ПротоколПользователь
    LJ.Rossia.org
    " . $r->{importid} . "" . $r->{remote_site} . "" . $r->{remote_user} . "" . $r->{remote_protocol} . "" . $r->{local_user} . "
    "; + + $ret .= "
    Ð’Ñ‹ можете добавить новую заÑвку на импорт здеÑÑŒ.

    "; + + + $ret .= "
    \n
    "; + my $sth1 = $dbr->prepare("SELECT * FROM ljr_ihistory WHERE local_user='$iremote' order by local_user, importid desc"); + $sth1->execute(); + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + while (my $r = $sth1->fetchrow_hashref) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    ÐомерИÑходный
    Ñервер
    Пользователь
    на иÑходном Ñервере
    ПротоколПользователь
    LJ.Rossia.org
    Дата и времÑ
    изменениÑ
    ÑтатуÑа заÑвки
    Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ñвки
    " . $r->{importid} . "" . $r->{remote_site} . "" . $r->{remote_user} . "" . $r->{remote_protocol} . "" . $r->{local_user} . "" . $r->{idate} . "" . $r->{istatus} . "
    "; + + return $ret; +} +_code?> + + +<=body +page?> diff --git a/local/htdocs/import.bml b/local/htdocs/import.bml new file mode 100755 index 0000000..0fc0816 --- /dev/null +++ b/local/htdocs/import.bml @@ -0,0 +1,72 @@ + +body<= + + +
    "; + }; + + use strict; + use vars qw(%POST %GET); + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access import page.") + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $iremote = $remote->{'user'}; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + my $ret; + my $e = 0; + my $dbr; + + + $ret = "{'user'} . " h1?>\n
    "; + $ret .= "
    Ð’Ñ‹ можете добавить заÑвку на импорт или "; + $ret .= "проÑмотреть ÑÑ‚Ð°Ñ‚ÑƒÑ Ñвоих заÑвок."; + $ret .= "

    "; + + $ret .= <<'$LJR$DESC'; +
      +
    • Ðе импортируютÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð½Ñ‹Ðµ/замороженные дневники +
    • Импорт проиÑходит медленно +
    • Ðе больше 50 запиÑей в день (дни Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом запиÑей больше 50 не импортируютÑÑ) +
    +
      +
    • ИмпортируютÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð½Ñ‹Ðµ/замороженные дневники +
    • Импорт проиÑходит быÑтро +
    • Из-за ограничений, накладываемых движком LiveJournal.org, не импортируютÑÑ Ñледущие атрибуты запиÑей: +
      • Форматированиe текÑта +
      • Метки (Ñ‚Ñги) +
      • Отключение отправки комментариев на e-mail, отключение комментариев +
      • Скрытие комментариев (Ñкрин) +
      • Картинка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +
      +


    +См. также: ЧаÑтые вопроÑÑ‹ про импорт +$LJR$DESC + + return $ret; +} +_code?> + + +<=body +page?> diff --git a/local/htdocs/inc/legal-tos b/local/htdocs/inc/legal-tos new file mode 100755 index 0000000..ac861ed --- /dev/null +++ b/local/htdocs/inc/legal-tos @@ -0,0 +1,137 @@ + + ToS + + +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +

    +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org). +

    + +

    þÔÏ ÍÏÖÎÏ

    +
      +
    • ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
    • áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
    • óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
    • +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
    + +

    þÔÏ ÎÅÌØÚÑ

    + +
      + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
    • éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
    • ÷ Livejournal.com (LJ) ÅÓÔØ ÎÅÓËÏÌØËÏ ÓÏÔÅÎ ÔÙÓÑÞ +ÒÕÓÓËÏÑÚÙÞÎÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ. ÷Ï ÉÚÂÅÖÁÎÉÅ ÐÕÔÁÎÉÃÙ, +ÎÁÍÅÒÅÎÎÏÇÏ ÓÁÍÏÚ×ÁÎÓÔ×Á É ÚÁÈ×ÁÔÁ ÉÍÅÎ, ÍÙ ÚÁËÒÅÐÌÑÅÍ ÚÁ +ËÁÖÄÙÍ ÒÕÓÓËÏÑÚÙÞÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÅÍ LJ, ÓÏÚÄÁÎÎÙÍ +ÄÏ ÉÀÌÑ 2005 ÇÏÄÁ, ÐÒÁ×Ï ÐÉÓÁÔØ ÐÏÄ ÔÅÍ ÖÅ ÉÍÅÎÅÍ × × LJR. + +
    • ðÒÉ ÓÏÚÄÁÎÉÉ ÎÏ×ÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ × LJR ÐÒÏ×ÅÒØÔÅ, +ÐÏÖÁÌÕÊÓÔÁ, ÎÅÔ ÌÉ ÐÏÄ ÔÁËÉÍ ÖÅ ÎÉËÏÍ ÒÕÓÓËÏÑÚÙÞÎÏÇÏ +ÐÏÌØÚÏ×ÁÔÅÌÑ × LJ. åÓÌÉ ÅÓÔØ ÔÁËÏÊ ÐÏÌØÚÏ×ÁÔÅÌØ, ÓÏÚÄÁÎÎÙÊ ÄÏ +ÉÀÌÑ 2005 ÇÏÄÁ, É ÏÎ ÚÁÔÒÅÂÕÅÔ ÔÏ ÖÅ ÓÁÍÏÅ ÉÍÑ × LJR, ðÏÐÅÞÉÔÅÌØÓËÉÊ +óÏ×ÅÔ É ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÂÕÄÕÔ ×ÙÎÕÖÄÅÎÙ ÐÏÍÅÎÑÔØ ×ÁÛÅ ÉÍÑ ÎÁ ÄÒÕÇÏÅ, +ÐÏ ×ÁÛÅÍÕ ×ÙÂÏÒÕ. + +
    + +

    ðÒÏÃÅÄÕÒÁ

    + +
      +
    • ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
    • áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
    • ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
    • ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
    • ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
    • ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
    +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    + + \ No newline at end of file diff --git a/local/htdocs/index.bml b/local/htdocs/index.bml new file mode 100755 index 0000000..c947468 --- /dev/null +++ b/local/htdocs/index.bml @@ -0,0 +1,62 @@ + +HEAD<= + + + + + +<=HEAD +BODYOPTS<= +<=BODYOPTS +BODY<= + +? h1?> + (LJR) - некоммерчеÑкий проект, Ñозданный Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ +Ñвободы Ñлова, Ñ€Ð°Ð·Ð²Ð¸Ñ‚Ð¸Ñ Ð³Ñ€Ð°Ð¶Ð´Ð°Ð½Ñкого общеÑтва и Ð¿Ð¾Ð¾Ñ‰Ñ€ÐµÐ½Ð¸Ñ Ñвободного +обмена мнениÑми. Проект дейÑтвует на оÑнове Правил, УÑтава и РуководÑщих Принципoв. С техничеÑкой +точки зрениÑ, lj.rossia.org Ñто Ñервер, на котором Ñтоит программное +обеÑпечение LiveJournal +(Ñлегка улучшенное), и предоÑтавлÑющий те же уÑлуги (в обÑтановке, +чуть более Ñвободной от цензуры). Ð’Ñ‹ можете Ñоздать Ñвой дневник, +читать чужие дневники, прокомментировать то, что вам понравилоÑÑŒ или +то, что Ð²Ð°Ñ Ð²Ð·Ð±ÐµÑило...и так далее, и так по порÑдку. Ðнонимные +жалобы начальÑтву ÑервиÑом не предуÑмотрены. +p?> + + + +! choice?> +<=ITEMS +ITEMSB<= + +<=ITEMSB +choices?> + + + + +<=ITEMS +ITEMSB<= +. choice?> +<=ITEMSB +choices?> + +<=BODY +page?> diff --git a/local/htdocs/indexkoi.bml b/local/htdocs/indexkoi.bml new file mode 100755 index 0000000..091ef80 --- /dev/null +++ b/local/htdocs/indexkoi.bml @@ -0,0 +1,62 @@ + +HEAD<= + + + + + +<=HEAD +BODYOPTS<= +<=BODYOPTS +BODY<= + +? h1?> + (LJR) - ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÐÒÏÅËÔ, ÓÏÚÄÁÎÎÙÊ ÄÌÑ ÐÏÄÄÅÒÖËÉ +Ó×ÏÂÏÄÙ ÓÌÏ×Á, ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ Ó×ÏÂÏÄÎÏÇÏ +ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ. ðÒÏÅËÔ ÄÅÊÓÔ×ÕÅÔ ÎÁ ÏÓÎÏ×Å ðÒÁ×ÉÌ, õÓÔÁ×Á É òÕËÏ×ÏÄÑÝÉÈ ðÒÉÎÃÉÐo×. ó ÔÅÈÎÉÞÅÓËÏÊ +ÔÏÞËÉ ÚÒÅÎÉÑ, lj.rossia.org ÜÔÏ ÓÅÒ×ÅÒ, ÎÁ ËÏÔÏÒÏÍ ÓÔÏÉÔ ÐÒÏÇÒÁÍÍÎÏÅ +ÏÂÅÓÐÅÞÅÎÉÅ LiveJournal +(ÓÌÅÇËÁ ÕÌÕÞÛÅÎÎÏÅ), É ÐÒÅÄÏÓÔÁ×ÌÑÀÝÉÊ ÔÅ ÖÅ ÕÓÌÕÇÉ (× ÏÂÓÔÁÎÏ×ËÅ, +ÞÕÔØ ÂÏÌÅÅ Ó×ÏÂÏÄÎÏÊ ÏÔ ÃÅÎÚÕÒÙ). ÷Ù ÍÏÖÅÔÅ ÓÏÚÄÁÔØ Ó×ÏÊ ÄÎÅ×ÎÉË, +ÞÉÔÁÔØ ÞÕÖÉÅ ÄÎÅ×ÎÉËÉ, ÐÒÏËÏÍÍÅÎÔÉÒÏ×ÁÔØ ÔÏ, ÞÔÏ ×ÁÍ ÐÏÎÒÁ×ÉÌÏÓØ ÉÌÉ +ÔÏ, ÞÔÏ ×ÁÓ ×ÚÂÅÓÉÌÏ...É ÔÁË ÄÁÌÅÅ, É ÔÁË ÐÏ ÐÏÒÑÄËÕ. áÎÏÎÉÍÎÙÅ +ÖÁÌÏÂÙ ÎÁÞÁÌØÓÔ×Õ ÓÅÒ×ÉÓÏÍ ÎÅ ÐÒÅÄÕÓÍÏÔÒÅÎÙ. +p?> + + + +! choice?> +<=ITEMS +ITEMSB<= + +<=ITEMSB +choices?> + + + + +<=ITEMS +ITEMSB<= +. choice?> +<=ITEMSB +choices?> + +<=BODY +page?> diff --git a/local/htdocs/js/talkpost.js b/local/htdocs/js/talkpost.js new file mode 100755 index 0000000..d604678 --- /dev/null +++ b/local/htdocs/js/talkpost.js @@ -0,0 +1,322 @@ + +var usernameWasFocused = 0; + +if (document.getElementById) { + // If there's no getElementById, this whole script won't do anything + + var radio_remote = document.getElementById("talkpostfromremote"); + var radio_user = document.getElementById("talkpostfromlj"); + var radio_anon = document.getElementById("talkpostfromanon"); + var radio_oidlo = document.getElementById("talkpostfromoidlo"); + var radio_ljcoidlo = document.getElementById("talkpostfromljcoidlo"); + var radio_oidli = document.getElementById("talkpostfromoidli"); + var radio_ljcoidli = document.getElementById("talkpostfromljcoidli"); + + var check_login = document.getElementById("logincheck"); + var sel_pickw = document.getElementById("prop_picture_keyword"); + var commenttext = document.getElementById("commenttext"); + + var form = document.getElementById("postform"); + + var username = form.userpost; + username.onfocus = function () { usernameWasFocused = 1; } + var password = form.password; + + var oidurl = document.getElementById("oidurl"); + var ljc_oidurl = document.getElementById("ljc_oidurl"); + var oid_more = document.getElementById("oid_more"); + var ljc_oid_more = document.getElementById("ljc_oid_more"); + var lj_more = document.getElementById("lj_more"); + var ljuser_row = document.getElementById("ljuser_row"); + var otherljuser_row = document.getElementById("otherljuser_row"); + var oidlo_row = document.getElementById("oidlo"); + var ljc_oidlo_row = document.getElementById("ljc_oidlo"); + var oidli_row = document.getElementById("oidli"); + var ljc_oidli_row = document.getElementById("ljc_oidli"); + + var remotef = document.getElementById("cookieuser"); + var remote; + if (remotef) { + remote = remotef.value; + } + + var subjectIconField = document.getElementById("subjectIconField"); + var subjectIconImage = document.getElementById("subjectIconImage"); + + var subject_field = document.getElementById("subject"); + var subject_nohtml = document.getElementById("ljnohtmlsubj"); + subject_nohtml.style.display = 'none'; +} + +var apicurl = ""; +var picprevt; + +if (! sel_pickw) { + // make a fake sel_pickw to play with later + sel_pickw = new Object(); +} + +function handleRadios(sel) { + password.disabled = check_login.disabled = (sel != 2); + if (password.disabled) password.value=''; + + // Anonymous + if (sel == 0) { + if (radio_anon.checked != 1) { + radio_anon.checked = 1; + } + } + + // Remote LJ User + if (sel == 1) { + if (radio_remote.checked != 1) { + radio_remote.checked = 1; + } + } + + // LJ User + if (sel == 2) { + if (ljuser_row) { + ljuser_row.style.display = 'none'; + } + if (lj_more) { + lj_more.style.display = ''; + } + username.focus(); + + if (radio_user.checked != 1) { + radio_user.checked = 1; + } + + } else { + if (lj_more) { + lj_more.style.display = 'none'; + } + } + + // OpenID + if (oid_more) { + if (sel == 3) { + oid_more.style.display = ''; + oidurl.focus(); + if (oidli_row) { + oidli_row.style.display = 'none'; + } + oidlo_row.style.display = ''; + + if (radio_oidlo.checked != 1) { + radio_oidlo.checked = 1; + } + + } else if (sel == 4) { + if (oidlo_row) { + oidlo_row.style.display = 'none'; + } + oidli_row.style.display = ''; + oid_more.style.display = 'none'; + + if (radio_oidli.checked != 1) { + radio_oidli.checked = 1; + } + } else { + oid_more.style.display = 'none'; + } + } + + // LiveJournal user + if (ljc_oid_more) { + if (sel == 103) { + ljc_oidlo_row.style.display = ''; + ljc_oid_more.style.display = ''; + + if (ljc_oidli_row) { + ljc_oidli_row.style.display = 'none'; + } + + if (ljc_oidurl.value == "") { + ljc_oidurl.focus(); + } + + if (radio_ljcoidlo.checked != 1) { + radio_ljcoidlo.checked = 1; + } + } + else if (sel == 104) { + if (ljc_oidlo_row) { + ljc_oidlo_row.style.display = 'none'; + } + ljc_oidli_row.style.display = ''; + ljc_oid_more.style.display = 'none'; + + if (radio_ljcoidli.checked != 1) { + radio_ljcoidli.checked = 1; + } + } + else { + ljc_oid_more.style.display = 'none'; + } + } + + if (sel_pickw.disabled = (sel != 1)) sel_pickw.value=''; +} + +function submitHandler() { + if ( + remote && username.value == remote && + ( + (! radio_anon || ! radio_anon.checked) && + (! radio_oidlo || ! radio_oidlo.checked) && + (! radio_ljcoidlo || ! radio_ljcoidlo.checked) && + (! radio_ljcoidli || ! radio_ljcoidli.checked) + ) + ) { + // Quietly arrange for cookieuser auth instead, to avoid + // sending cleartext password. + password.value = ""; + username.value = ""; + radio_remote.checked = true; + return true; + } + if (usernameWasFocused && username.value && ! radio_user.checked) { + alert(usermismatchtext); + return false; + } + if (! radio_user.checked) { + username.value = ""; + } + + return true; +} + +if (document.getElementById) { + + if (radio_anon && radio_anon.checked) handleRadios(0); + if (radio_remote && radio_remote.checked) handleRadios(1); + if (radio_user && radio_user.checked) handleRadios(2); + if (radio_oidlo && radio_oidlo.checked) handleRadios(3); + if (radio_oidli && radio_oidli.checked) handleRadios(4); + if (radio_ljcoidlo && radio_ljcoidlo.checked) handleRadios(103); + if (radio_ljcoidli && radio_ljcoidli.checked) handleRadios(104); + + if (radio_remote) { + radio_remote.onclick = function () { + handleRadios(1); + }; + if (radio_remote.checked) handleRadios(1); + } + if (radio_user) + radio_user.onclick = function () { + handleRadios(2); + }; + if (radio_anon) + radio_anon.onclick = function () { + handleRadios(0); + }; + if (radio_oidlo) + radio_oidlo.onclick = function () { + handleRadios(3); + }; + if (radio_oidli) + radio_oidli.onclick = function () { + handleRadios(4); + }; + if (radio_ljcoidlo) + radio_ljcoidlo.onclick = function () { + handleRadios(103); + }; + if (radio_ljcoidli) + radio_ljcoidli.onclick = function () { + handleRadios(104); + }; + username.onkeydown = username.onchange = function () { + if (radio_remote) { + password.disabled = check_login.disabled = 0; + if (password.disabled) password.value=''; + } else { + if (radio_user && username.value != "") + radio_user.checked = true; + handleRadios(2); // update the form + } + } + form.onsubmit = submitHandler; + + document.onload = function () { + if (radio_anon && radio_anon.checked) handleRadios(0); + if (radio_user && radio_user.checked) otherLJUser(); + if (radio_remote && radio_remote.checked) handleRadios(1); + if (radio_oidlo && radio_oidlo.checked) handleRadios(3); + if (radio_oidli && radio_oidli.checked) handleRadios(4); + if (radio_ljcoidlo && radio_ljcoidlo.checked) handleRadios(103); + if (radio_ljcoidli && radio_ljcoidli.checked) handleRadios(104); + } + +} + +// toggle subject icon list + +function subjectIconListToggle() { + if (! document.getElementById) { return; } + var subjectIconList = document.getElementById("subjectIconList"); + if(subjectIconList) { + if (subjectIconList.style.display != 'block') { + subjectIconList.style.display = 'block'; + } else { + subjectIconList.style.display = 'none'; + } + } +} + +// change the subject icon and hide the list + +function subjectIconChange(icon) { + if (! document.getElementById) { return; } + if (icon) { + if(subjectIconField) subjectIconField.value=icon.id; + if(subjectIconImage) { + subjectIconImage.src=icon.src; + subjectIconImage.width=icon.width; + subjectIconImage.height=icon.height; + } + subjectIconListToggle(); + } +} + +function subjectNoHTML(e) { + + var key; + + key = getKey(e); + + if (key == 60) { + subject_nohtml.style.display = 'block'; + } +} + +function getKey(e) { + if (window.event) { + return window.event.keyCode; + } else if(e) { + return e.which; + } else { + return undefined; + } +} + +function otherLJUser() { + handleRadios(2); + + otherljuser_row.style.display = ''; + radio_user.checked = 1; +} + +function otherOIDUser() { + handleRadios(3); + + radio_oidlo.checked = 1; +} + +function otherLJCOIDUser() { + handleRadios(103); + + radio_ljcoidlo.checked = 1; +} diff --git a/local/htdocs/legal/guidelines.html b/local/htdocs/legal/guidelines.html new file mode 100755 index 0000000..8f35a8b --- /dev/null +++ b/local/htdocs/legal/guidelines.html @@ -0,0 +1,97 @@ + Guidelines + + +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    +

    òÕËÏ×ÏÄÑÝÉÅ ÐÒÉÎÃÉÐÙ LJR (lj.rossia.org).

    + +

    äÅËÌÁÒÁÃÉÑ ÎÁÍÅÒÅÎÉÊ

    + + +
      +
    • LJR - ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÐÒÏÅËÔ, ÓÏÚÄÁÎÎÙÊ ÄÌÑ ÐÏÄÄÅÒÖËÉ +Ó×ÏÂÏÄÙ ÓÌÏ×Á, ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ.

      + +

    • LJR - ÐÒÏÓÔÒÁÎÓÔ×Ï, Ó×ÏÂÏÄÎÏÅ ÏÔ ÃÅÎÚÕÒÙ. +ðÏÌÉÔÉÞÅÓËÁÑ, ÜÓÔÅÔÉÞÅÓËÁÑ É ËÁËÁÑ-ÌÉÂÏ ÄÒÕÇÁÑ +ÃÅÎÚÕÒÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ. ðÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÄÎÅ×ÎÉË - +ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÐÏÌØÚÏ×ÁÔÅÌÑ, ÏÇÒÁÎÉÞÉ×ÁÔØ +ÅÇÏ × ×ÙÓËÁÚÙ×ÁÎÉÉ Ó×ÏÉÈ ÍÙÓÌÅÊ × ÄÎÅ×ÎÉËÅ ÔÁË ÖÅ +ÇÌÕÐÏ (É ÇÁÄËÏ), ËÁË ÏÇÒÁÎÉÞÉ×ÁÔØ ËÕÈÏÎÎÙÅ +ÒÁÚÇÏ×ÏÒÙ, ÁÎÅËÄÏÔÙ É ÌÉÞÎÕÀ ÐÅÒÅÐÉÓËÕ. åÓÌÉ +×ÁÍ ÎÅ ÎÒÁ×ÉÔÓÑ, ÞÔÏ ÐÉÛÅÔ ÔÁËÏÊ-ÔÏ ÐÏÌØÚÏ×ÁÔÅÌØ, +ÎÅ ÞÉÔÁÊÔÅ ÅÇÏ.

      + + +

    • LJR - ÐÒÏÓÔÒÁÎÓÔ×Ï, Ó×ÏÂÏÄÎÏÅ ÏÔ ÍÅÒÉÔÏËÒÁÔÉÉ. +îÅ ÐÒÅÄÏÓÔÁ×ÌÑÅÔÓÑ ÎÉËÁËÉÈ ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÙÈ +ÐÒÅÉÍÕÝÅÓÔ× ÚÁÓÌÕÖÅÎÎÏÍÕ ÂÌÏÇÇÅÒÕ × ÓÒÁ×ÎÅÎÉÉ +Ó ÎÏ×ÉÞËÏÍ. úÁÓÌÕÖÅÎÎÏÍÕ ÂÌÏÇÇÅÒÕ ÄÏÓÔÁÔÏÞÎÏ +ÐÒÅÉÍÕÝÅÓÔ×, ÐÒÅÄÏÓÔÁ×ÌÅÎÎÙÈ ÚÁÓÌÕÖÅÎÎÏÓÔØÀ.

      + + +

    • LJR +ÔÏÔÁÌØÎÏ ÐÏÄÏÔÞÅÔÅÎ ÐÕÂÌÉËÅ. ÷ÓÅ ÖÁÌÏÂÙ ÎÁÞÁÌØÓÔ×Õ, +ÒÁ×ÎÏ ËÁË É ÒÅÛÅÎÉÑ ÐÏ ÐÒÉÏÓÔÁÎÏ×ËÅ ÔÅÈ ÉÌÉ ÉÎÙÈ ÖÕÒÎÁÌÏ× +ÄÏÌÖÎÙ ÂÙÔØ ÏÂÑÚÁÔÅÌØÎÏ ÏÐÕÂÌÉËÏ×ÁÎÙ.

      + + +

    • ïÓÎÏ×ÎÙÍ ÓÏÄÅÒÖÁÎÉÅÍ ÓÅÒ×ÅÒÁ Ñ×ÌÑÅÔÓÑ +ËÏÎÔÅÎÔ, ÓÏÚÄÁÎÎÙÊ ÐÏÌØÚÏ×ÁÔÅÌÑÍÉ. âÁÎÎÅÒÎÁÑ ÒÅËÌÁÍÁ, +ÐÒÏÄÁÖÁ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ Å-ÍÜÊÌÏ×, ÎÁ×ÑÚÙ×ÁÎÉÅ +ËÏÍÍÅÒÞÅÓËÉÈ ÕÓÌÕÇ ÁÂÓÏÌÀÔÎÏ ÎÅÄÏÐÕÓÔÉÍÙ × LJR.

      + + +

    • âÅÓÐÌÁÔÎÙÊ ÐÏÌØÚÏ×ÁÔÅÌØ ÉÍÅÅÔ ÓÔÏÌØËÏ ÖÅ ÐÒÁ×, +ÓËÏÌØËÏ ÐÌÁÔÎÙÊ; ÏÓÎÏ×ÎÙÅ ÆÕÎËÃÉÏÎÁÌØÎÙÅ ×ÏÚÍÏÖÎÏÓÔÉ +ÓÅÒ×ÉÓÁ ÄÏÓÔÕÐÎÙ ÉÍ × ÒÁ×ÎÏÊ ÓÔÅÐÅÎÉ. +

      + + +

    • úÁËÒÙÔÉÅ ÄÎÅ×ÎÉËÏ× - ËÒÁÊÎÑÑ ÍÅÒÁ, É ÂÅÚ +ËÒÁÊÎÅÊ ÎÅÏÂÈÏÄÉÍÏÓÔÉ Ë ÎÅÊ ÐÒÉÂÅÇÁÔØ ÎÅ ÂÕÄÕÔ. +ìÀÂÏÍÕ ÐÏÌØÚÏ×ÁÔÅÌÀ (× ÔÏÍ ÞÉÓÌÅ É ÚÁËÒÙÔÏÍÕ) ÂÕÄÅÔ +ÐÏ ÐÅÒ×ÏÍÕ ÔÒÅÂÏ×ÁÎÉÀ ×ÙÄÁÎ ÁÒÈÉ× ÅÇÏ ÓÏÏÂÝÅÎÉÊ, +× ÍÁËÓÉÍÁÌØÎÏ ÕÄÏÂÏÞÉÔÁÅÍÏÍ ×ÉÄÅ. ðÏÌØÚÏ×ÁÔÅÌØ +ÉÍÅÅÔ ÐÒÁ×Ï ÁÐÅÌÌÑÃÉÉ +Ë ðÏÐÅÞÉÔÅÌØÓËÏÍÕ óÏ×ÅÔÕ, +× ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ.

      + + +

    • íÙ (ÁÄÍÉÎÉÓÔÒÁÃÉÑ LJR) +ÏÂÑÚÕÅÍÓÑ ÓÏÈÒÁÎÑÔØ ÞÁÓÔÎÙÊ ÈÁÒÁËÔÅÒ +ÞÁÓÔÎÏÊ (ÚÁËÒÙÔÏÊ) ÉÎÆÏÒÍÁÃÉÉ, ×ÙÌÏÖÅÎÎÏÊ ÎÁ ÓÅÒ×ÅÒ +(ËÒÏÍÅ ÓÌÕÞÁÅ×, ÐÒÅÄÕÓÍÏÔÒÅÎÎÙÈ ÚÁËÏÎÏÍ òæ É ÓÔÒÁÎÙ +ÐÒÏÖÉ×ÁÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÑ). ôÁËÖÅ ÍÙ ÏÂÑÚÕÅÍÓÑ +ÌÀÂÏÊ ÃÅÎÏÊ (É ÎÅÓÍÏÔÒÑ ÎÁ ÕÂÙÔÏÞÎÏÓÔØ ÐÒÏÅËÔÁ) +ÐÏÄÄÅÒÖÉ×ÁÔØ ÓÅÒ×ÅÒ × ÒÁÂÏÞÅÍ ÓÏÓÔÏÑÎÉÉ.

      + +

    • LJR - ÐÒÏÅËÔ, ÐÏÓÔÒÏÅÎÎÙÊ ÎÁ ÐÒÉÎÃÉÐÁÈ +Ó×ÏÂÏÄÎÏÇÏ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ. ÷ÓÅ ÒÁÚÒÁÂÏÔËÉ, +×ÅÄÕÝÉÅÓÑ × ÒÁÍËÁÈ LJR, ÏÐÕÂÌÉËÏ×ÁÎÙ ÐÏÄ Ó×ÏÂÏÄÎÏÊ +ÌÉÃÅÎÚÉÅÊ (GPL É ÅÅ ÁÎÁÌÏÇÁÍÉ) É ÄÏÓÔÕÐÎÙ ÄÌÑ +ÉÓÐÏÌØÚÏ×ÁÎÉÑ.

      + +

    • ÷ ÓÌÕÞÁÅ ÚÌÏÓÔÎÏÇÏ ÎÁÒÕÛÅÎÉÑ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ ÉÚÌÏÖÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ×, ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ×ÐÒÁ×Å × ÌÀÂÏÊ ÍÏÍÅÎÔ +ÚÁÂÒÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ É ×ÓÅ ÐÒÏÇÒÁÍÍÎÏÅ ÏÂÅÓÐÅÞÅÎÉÅ LJR +É ÐÏÄÎÑÔØ LJR ÎÁ ÎÏ×ÏÍ ÓÅÒ×ÅÒÅ. + + +
    +
    +
    +ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    \ No newline at end of file diff --git a/local/htdocs/legal/privacy.bml b/local/htdocs/legal/privacy.bml new file mode 100755 index 0000000..d32e531 --- /dev/null +++ b/local/htdocs/legal/privacy.bml @@ -0,0 +1,9 @@ + Privacy + +

    Your privacy

    + +We +pledge to protect your privacy, except the +cases when the law of Russian Federation or your own country +requires us otherwise. Please read our policy documents: +[ 1 | 2 | 3 ] \ No newline at end of file diff --git a/local/htdocs/legal/tos-mini.html b/local/htdocs/legal/tos-mini.html new file mode 100755 index 0000000..ca4748d --- /dev/null +++ b/local/htdocs/legal/tos-mini.html @@ -0,0 +1,122 @@ + + ToS + + +

    +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org). +

    + +

    þÔÏ ÍÏÖÎÏ

    +
      +
    • ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
    • áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
    • óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
    • +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
    + +

    þÔÏ ÎÅÌØÚÑ

    + +
      + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
    • éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
    • ÷ Livejournal.com (LJ) ÅÓÔØ ÎÅÓËÏÌØËÏ ÓÏÔÅÎ ÔÙÓÑÞ +ÒÕÓÓËÏÑÚÙÞÎÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ. ÷Ï ÉÚÂÅÖÁÎÉÅ ÐÕÔÁÎÉÃÙ, +ÎÁÍÅÒÅÎÎÏÇÏ ÓÁÍÏÚ×ÁÎÓÔ×Á É ÚÁÈ×ÁÔÁ ÉÍÅÎ, ÍÙ ÚÁËÒÅÐÌÑÅÍ ÚÁ +ËÁÖÄÙÍ ÒÕÓÓËÏÑÚÙÞÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÅÍ LJ, ÓÏÚÄÁÎÎÙÍ +ÄÏ ÉÀÌÑ 2005 ÇÏÄÁ, ÐÒÁ×Ï ÐÉÓÁÔØ ÐÏÄ ÔÅÍ ÖÅ ÉÍÅÎÅÍ × × LJR. + +
    • ðÒÉ ÓÏÚÄÁÎÉÉ ÎÏ×ÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ × LJR ÐÒÏ×ÅÒØÔÅ, +ÐÏÖÁÌÕÊÓÔÁ, ÎÅÔ ÌÉ ÐÏÄ ÔÁËÉÍ ÖÅ ÎÉËÏÍ ÒÕÓÓËÏÑÚÙÞÎÏÇÏ +ÐÏÌØÚÏ×ÁÔÅÌÑ × LJ. åÓÌÉ ÅÓÔØ ÔÁËÏÊ ÐÏÌØÚÏ×ÁÔÅÌØ, ÓÏÚÄÁÎÎÙÊ ÄÏ +ÉÀÌÑ 2005 ÇÏÄÁ, É ÏÎ ÚÁÔÒÅÂÕÅÔ ÔÏ ÖÅ ÓÁÍÏÅ ÉÍÑ × LJR, ðÏÐÅÞÉÔÅÌØÓËÉÊ +óÏ×ÅÔ É ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÂÕÄÕÔ ×ÙÎÕÖÄÅÎÙ ÐÏÍÅÎÑÔØ ×ÁÛÅ ÉÍÑ ÎÁ ÄÒÕÇÏÅ, +ÐÏ ×ÁÛÅÍÕ ×ÙÂÏÒÕ. + +
    + +

    ðÒÏÃÅÄÕÒÁ

    + +
      +
    • ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
    • áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
    • ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
    • ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
    • ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
    • ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
    + + \ No newline at end of file diff --git a/local/htdocs/legal/tos.html b/local/htdocs/legal/tos.html new file mode 100755 index 0000000..ac861ed --- /dev/null +++ b/local/htdocs/legal/tos.html @@ -0,0 +1,137 @@ + + ToS + + +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +

    +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org). +

    + +

    þÔÏ ÍÏÖÎÏ

    +
      +
    • ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
    • áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
    • óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
    • +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
    + +

    þÔÏ ÎÅÌØÚÑ

    + +
      + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
    • ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
    • éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
    • úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
    • ÷ Livejournal.com (LJ) ÅÓÔØ ÎÅÓËÏÌØËÏ ÓÏÔÅÎ ÔÙÓÑÞ +ÒÕÓÓËÏÑÚÙÞÎÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ. ÷Ï ÉÚÂÅÖÁÎÉÅ ÐÕÔÁÎÉÃÙ, +ÎÁÍÅÒÅÎÎÏÇÏ ÓÁÍÏÚ×ÁÎÓÔ×Á É ÚÁÈ×ÁÔÁ ÉÍÅÎ, ÍÙ ÚÁËÒÅÐÌÑÅÍ ÚÁ +ËÁÖÄÙÍ ÒÕÓÓËÏÑÚÙÞÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÅÍ LJ, ÓÏÚÄÁÎÎÙÍ +ÄÏ ÉÀÌÑ 2005 ÇÏÄÁ, ÐÒÁ×Ï ÐÉÓÁÔØ ÐÏÄ ÔÅÍ ÖÅ ÉÍÅÎÅÍ × × LJR. + +
    • ðÒÉ ÓÏÚÄÁÎÉÉ ÎÏ×ÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ × LJR ÐÒÏ×ÅÒØÔÅ, +ÐÏÖÁÌÕÊÓÔÁ, ÎÅÔ ÌÉ ÐÏÄ ÔÁËÉÍ ÖÅ ÎÉËÏÍ ÒÕÓÓËÏÑÚÙÞÎÏÇÏ +ÐÏÌØÚÏ×ÁÔÅÌÑ × LJ. åÓÌÉ ÅÓÔØ ÔÁËÏÊ ÐÏÌØÚÏ×ÁÔÅÌØ, ÓÏÚÄÁÎÎÙÊ ÄÏ +ÉÀÌÑ 2005 ÇÏÄÁ, É ÏÎ ÚÁÔÒÅÂÕÅÔ ÔÏ ÖÅ ÓÁÍÏÅ ÉÍÑ × LJR, ðÏÐÅÞÉÔÅÌØÓËÉÊ +óÏ×ÅÔ É ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÂÕÄÕÔ ×ÙÎÕÖÄÅÎÙ ÐÏÍÅÎÑÔØ ×ÁÛÅ ÉÍÑ ÎÁ ÄÒÕÇÏÅ, +ÐÏ ×ÁÛÅÍÕ ×ÙÂÏÒÕ. + +
    + +

    ðÒÏÃÅÄÕÒÁ

    + +
      +
    • ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
    • áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
    • ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
    • ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
    • ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
    • ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
    • ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
    +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +
    + + \ No newline at end of file diff --git a/local/htdocs/legal/ustav.html b/local/htdocs/legal/ustav.html new file mode 100755 index 0000000..0d4875b --- /dev/null +++ b/local/htdocs/legal/ustav.html @@ -0,0 +1,90 @@ + Ustav + + +
    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    +

    +õÓÔÁ× ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ LJR (lj.rossia.org). +

    + + LJR - ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÐÒÏÅËÔ, ÓÏÚÄÁÎÎÙÊ × ÓÏÏÔ×ÅÔÓÔ×ÉÉ +Ó òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ LJR ÄÌÑ ÐÏÄÄÅÒÖËÉ +Ó×ÏÂÏÄÙ ÓÌÏ×Á, ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ. úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÜÔÉÈ ÐÒÉÎÃÉÐÏ× +ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ: + +
      +
    • ÷ÁÄÉÍ çÕÝÉÎ +
    • é×ÁÎ äÁ×ÙÄÏ× +
    • ëÏÎÓÔÁÎÔÉÎ ëÒÙÌÏ× +
    • òÏÍÁÎ ìÅÊÂÏ× +
    • íÁËÓÉÍ íÏÛËÏ× +
    • áÎÔÏÎ îÏÓÉË +
    • íÉÛÁ ÷ÅÒÂÉÃËÉÊ +
    + +÷ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ËÏÏÐÔÉÒÕÅÔÓÑ (Ó ÐÒÁ×ÏÍ ÓÏ×ÅÝÁÔÅÌØÎÏÇÏ +ÇÏÌÏÓÁ) ÓÉÓÔÅÍÎÁÑ ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÅÒ×ÅÒÁ LJR; × ÓÌÕÞÁÅ ÒÁÚÄÅÌÁ +ÇÏÌÏÓÏ×, ÓÏ×ÅÝÁÔÅÌØÎÙÊ ÇÏÌÏÓ ÓÔÁÎÏ×ÉÔÓÑ ÒÅÛÁÀÝÉÍ. +

    + +îÅÐÏÓÒÅÄÓÔ×ÅÎÎÏÊ ÐÏÄÄÅÒÖËÏÊ LJR ÚÁÎÉÍÁÅÔÓÑ ÁÄÍÉÎÉÓÔÒÁÃÉÑ +ÓÅÒ×ÅÒÁ, ÔÏ ÅÓÔØ ÌÀÄÉ, ÎÁÄÅÌÅÎÎÙÅ ÓÉÓÔÅÍÎÙÍÉ ÐÏÌÎÏÍÏÞÉÑÍÉ. + + +

    + +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÚÁËÒÙ×ÁÅÔ ÄÎÅ×ÎÉËÉ ÓÐÁÍÍÅÒÏ×, +ÄÎÅ×ÎÉËÉ, ÓÏÚÄÁÎÎÙÅ ÄÌÑ ÈÁËÅÒÓËÉÈ ÁÔÁË, ÄÎÅ×ÎÉËÉ, +ÓÏÚÄÁÀÝÉÅ ÔÅÈÎÉÞÅÓËÉÅ ÐÒÏÂÌÅÍÙ ÄÌÑ ÒÁÂÏÔÙ +LJR, É ÄÎÅ×ÎÉËÉ, ÇÄÅ ÒÁÚÍÅÝÁÀÔÓÑ ÐÒÏÔÉ×ÏÚÁËÏÎÎÙÅ É +ÐÒÅÄÓÔÁ×ÌÑÀÝÉÅ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÕÀ ÏÐÁÓÎÏÓÔØ ÄÌÑ ÖÉÚÎÉ É +ÚÄÏÒÏ×ØÑ ËÏÎËÒÅÔÎÙÈ ÌÀÄÅÊ ÚÁÐÉÓÉ. ÷Ï ×ÓÅÈ ÄÒÕÇÉÈ +ÓÌÕÞÁÑÈ, ÄÌÑ ÚÁËÒÙÔÉÑ ÔÒÅÂÕÅÔÓÑ ÖÁÌÏÂÁ ÐÏÌØÚÏ×ÁÔÅÌÑ +ÉÌÉ ÔÒÅÔØÉÈ ÌÉÃ, Á ÔÁËÖÅ ÒÅÛÅÎÉÅ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ +óÏ×ÅÔÁ. +

    + +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ÒÁÚÂÉÒÁÅÔ ÖÁÌÏÂÙ ÐÏÌØÚÏ×ÁÔÅÌÅÊ +(ÄÒÕÇ ÎÁ ÄÒÕÇÁ É ÎÁ ÁÄÍÉÎÉÓÔÒÁÃÉÀ LJR). +òÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔÓÑ ÐÒÏÓÔÙÍ ÂÏÌØÛÉÎÓÔ×ÏÍ ÇÏÌÏÓÏ×, ÐÏ ÉÓÔÅÞÅÎÉÉ +ÐÑÔÉ ÓÕÔÏË Ó ÍÏÍÅÎÔÁ ÐÏÄÁÞÉ ÖÁÌÏÂÙ. +

    + +òÅÛÅÎÉÅ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ, ÐÒÉ ÐÒÉÎÑÔÉÉ +ËÏÔÏÒÏÇÏ ÎÅ ÇÏÌÏÓÏ×ÁÌ ÏÄÉÎ ÉÚ ÕÞÁÓÔÎÉËÏ×, +ÍÏÖÅÔ ÂÙÔØ ÐÅÒÅÓÍÏÔÒÅÎÏ ÐÏ ÐÒÏÓØÂÅ ÜÔÏÇÏ +ÕÞÁÓÔÎÉËÁ. +

    + +ôÁËÖÅ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ÍÏÖÅÔ ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ +Ï ÏÔËÁÚÅ Ë ÐÒÉÅÍÕ ÄÁÌØÎÅÊÛÉÈ ÖÁÌÏ ÏÓÏÂÏ ÓËÌÏÞÎÏÇÏ ËÌÑÕÚÎÉËÁ +(ÔÏÖÅ ÂÏÌØÛÉÎÓÔ×ÏÍ ÇÏÌÏÓÏ×). +

    + +þÌÅÎ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ ÍÏÖÅÔ ÐÏÄÁÔØ × ÏÔÓÔÁ×ËÕ. + + +

    +ðÅÒÅÓÍÏÔÒ õÓÔÁ×Á, ðÒÁ×ÉÌ É òÕËÏ×ÏÄÑÝÉÈ ðÒÉÎÃÉÐÏ×, +ÐÅÒÅÅÚÄ ÓÅÒ×ÅÒÁ, Á ÔÁËÖÅ ÐÒÉ×ÌÅÞÅÎÉÅ ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÕÞÁÓÔÎÉËÏ× +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ ÏÓÕÝÅÓÔ×ÌÑÅÔÓÑ, ÅÓÌÉ +ÚÁ ÜÔÉ ÍÅÒÙ ×ÙÓÔÕÐÁÀÔ ËÁË ÍÉÎÉÍÕÍ 2/3 ÓÐÉÓÏÞÎÏÇÏ +ÓÏÓÔÁ×Á ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. +

    + +÷ÓÅ ÇÏÌÏÓÏ×ÁÎÉÑ ×ÅÄÕÔÓÑ ÏÔËÒÙÔÏ, ËÒÏÍÅ ÇÏÌÏÓÏ×ÁÎÉÑ +ÐÏ ËÁÎÄÉÄÁÔÕÒÁÍ ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÕÞÁÓÔÎÉËÏ× +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. + + +

    +
    + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
    diff --git a/local/htdocs/lj-gate/index.bml b/local/htdocs/lj-gate/index.bml new file mode 100755 index 0000000..c8a7a28 --- /dev/null +++ b/local/htdocs/lj-gate/index.bml @@ -0,0 +1,305 @@ +LJR::Gate +body<= + + +color_names; + + my $err = sub { + my $txt = shift; + + return "
    "; + }; + + my $update_export_settings = sub { + my ($iremote) = @_; + + my $ret; + my $e; + + my $dbh = LJ::get_db_writer(); + if (!$dbh) { + return $err->("Can't get database writer!"); + } + my $dbr = LJ::get_db_reader(); + if (!$dbr) { + return $err->("Can't get database reader!"); + } + + my $iserver; + if ($POST{'server'} eq "lj") { + $iserver = "www.livejournal.com"; + } +# elsif ($POST{'server'} eq "gj") { +# $iserver = "www.greatestjournal.com"; +# } + else { + $ret .= $err->("Invalid server specified!"); + $e = 1; + } + + my $iuser = LJ::canonical_username($POST{'username'}); + if (!$iuser) { + $ret .= $err->("Invalid user name!"); + $e = 1; + } + + my $ipassword = $POST{'password'}; + unless (LJ::is_ascii($ipassword) && $ipassword ne "") { + $ret .= $err->("Invalid password!"); + $e = 1; + } + return $ret if $e; + + my $xmlrpc = LJR::Gate::Authenticate ($iserver, $iuser, $ipassword); + print STDERR + "Error in LJR::Gate::Authenticate for user " . $iuser . "\n" . $xmlrpc->{'err_text'} . "\n" + if $xmlrpc->{'err_text'}; + + return $err->($xmlrpc->{'err_text'}) if $xmlrpc->{'err_text'}; + + my $ru = LJR::Distributed::get_remote_server($iserver); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + $ru->{'username'} = $iuser; + + $ru = LJR::Distributed::get_cached_user($ru); + return $err->($ru->{"errtext"}) if $ru->{"err"}; + + my $r = LJR::Distributed::update_export_settings($iremote, $ru->{'ru_id'}, $ipassword); + return $r->{'errtext'} if $r->{'err'}; + + my $cu = LJ::load_user($iremote, 1); + return $err->("Error logging export modification for [$iremote]!") unless $cu; + + $cu->log_event('ljr_export_configured', { + remote => $cu, + actiontarget => $ru->{'ru_id'}, + method => 'web', + }); + + return; + }; + + my $cancel_export = sub { + my ($iremote) = @_; + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $sth1; + $sth1 = $dbr->prepare("SELECT * FROM ljr_export_settings WHERE user=?"); + $sth1->execute($iremote); + my $r = $sth1->fetchrow_hashref; + + $sth1 = $dbr->prepare("DELETE FROM ljr_export_settings WHERE user=?"); + $sth1->execute($iremote); + $sth1->finish; + + my $cu = LJ::load_user($iremote, 1); + return $err->("Error logging export modification for [$iremote]!") unless $cu; + + $cu->log_event('ljr_export_unconfigured', { + remote => $cu, + actiontarget => $r->{'ru_id'}, + method => 'web', + }); + + return; + }; + + my $export_options = sub { + my ($iremote) = @_; + + my %h_font_names; + @h_font_names{map {"gd" . $_ . "Font"} @font_names} = (); + if (! exists $h_font_names{$POST{'font_name'}}) { + return $err->("Invalid font name: " . $POST{'font_name'}); + } + + my %h_color_names; + @h_color_names{@color_names} = (); + if (! exists $h_color_names{$POST{'font_color'}}) { + return $err->("Invalid color name: " . $POST{'font_color'}); + } + + my $dbh = LJ::get_db_writer(); + return $err->("Can't get database writer!") unless $dbh; + + my $sth1; + $sth1 = $dbh->prepare("UPDATE ljr_export_settings SET update_time=NOW(), last_status='OK: updated options', font_name=?, font_color=? WHERE user=?"); + $sth1->execute($POST{'font_name'}, $POST{'font_color'}, $iremote); + $sth1->finish; + + return; + }; + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $remote = LJ::get_remote(); + return LJ::bad_input("You must be logged in to access this page.") + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + my $iremote = $remote->{'user'}; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + my $ret; + $ret = "{'user'} . " h1?>\n
    "; + + my $iremote_is_protected = 0; + foreach (@LJ::PROTECTED_USERNAMES) { + if ($iremote =~ $_) { + $iremote_is_protected = 1; + } + } + if ($iremote_is_protected) { + $ret .= $err->("Invalid local user: export not allowed!"); + return $ret; + } + + if (LJ::did_post()) { + if ($POST{'cancel_export'}) { + $ret .= $cancel_export->($iremote); + return BML::redirect("index.bml"); + } + elsif ($POST{'export_options'}) { + $ret .= $export_options->($iremote); + return BML::redirect("index.bml") unless $ret; + } + else { + $ret .= $update_export_settings->($iremote); + } + } + + my $dbh = LJ::get_db_writer(); + if (!$dbh) { + return $err->("Can't get database writer!"); + } + my $dbr = LJ::get_db_reader(); + if (!$dbr) { + return $err->("Can't get database reader!"); + } + + my $sth1; + $sth1 = $dbr->prepare("SELECT * FROM ljr_export_settings WHERE user=?"); + $sth1->execute($iremote); + my $r = $sth1->fetchrow_hashref; + $sth1->finish; + + if (! $r->{'enabled'}) { + $ret .= "
    "; + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    ГÑйтовать журнал на Ñервер:"; + $ret .= ""; + $ret .= "

    Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ:"; + $ret .= LJ::html_text({ + 'name' => 'username', + 'value' => $POST{'username'}, + 'size' => '15', + 'maxlength' => '15', + }); + $ret .= "

    Пароль:"; + $ret .= LJ::html_text({ + 'name' => 'password', + 'value' => $POST{'password'}, + 'size' => '31', + 'maxlength' => '31', + 'type' => 'password', + }); + $ret .= "

    Ð¡Ñ‚Ð°Ñ‚ÑƒÑ (" . $r->{'update_time'} .")" . $r->{'last_status'} . "

    "; + + $ret .= ""; + } + else { + my $ru; + $ru = LJR::Distributed::get_cached_user({ 'ru_id' => $r->{'ru_id'}}); + $ru = LJR::Distributed::get_remote_server_byid($ru); + + $ret .= + "
    Ваш журнал в данный момент гÑйтуетÑÑ Ð² {'username'} . + ">" . $ru->{'username'} . "" + ; + + $ret .= "

    "; + + $ret .= ""; + $ret .= ""; + + $ret .= ""; + + $ret .= "
    Ð¡Ñ‚Ð°Ñ‚ÑƒÑ (" . $r->{'update_time'} .")" . $r->{'last_status'} . "

    "; + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + } + $ret .= ""; + + + my $dbr = LJ::get_db_reader(); + return $err->("Can't get database reader!") unless $dbr; + + my $sth1; + $sth1 = $dbr->prepare("SELECT font_name, font_color FROM ljr_export_settings WHERE user=?"); + $sth1->execute($iremote); + my ($cname, $ccolor) = $sth1->fetchrow_array; + $sth1->finish; + + $ret .= "
    "; + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + + $ret .= ""; + $ret .= "
    КоличеÑтво комментариев
    Размер шрифта:
    Цвет шрифта:

    "; + + $ret .= "См также: ЧаÑтые вопроÑÑ‹ про гейт"; + + return $ret; +} +_code?> + +<=body +page?> diff --git a/local/htdocs/lj-gate/lj-gate-faq.bml b/local/htdocs/lj-gate/lj-gate-faq.bml new file mode 100644 index 0000000..3f6811e --- /dev/null +++ b/local/htdocs/lj-gate/lj-gate-faq.bml @@ -0,0 +1,102 @@ + +body<= + + h2?> +

    +Гейт — Ñто программа, шлюз между lj.rossia.org и Живым Журналом, +автоматичеÑки ÐºÐ¾Ð¿Ð¸Ñ€ÑƒÑŽÑ‰Ð°Ñ Ð²Ð°ÑˆÐ¸ запиÑи из дневника на LJR +в дневник на www.livejournal.com. КопироватьÑÑ Ð±ÑƒÐ´ÑƒÑ‚ только те запиÑи, +которые вы Ñделали поÑле того, как наÑтроили гейтование Ñвоего дневника. +Старые запиÑи будут копироватьÑÑ, только еÑли вы их отредактируете +(Ñ ÑƒÑтановленным атрибутом backdated). + +


    + + +

    +Гейт можно иÑпользовать, еÑли вы не хотите пользоватьÑÑ +дневником на www.livejournal.com, но также не хотите, +чтобы ваши Ð´Ñ€ÑƒÐ·ÑŒÑ Ñ‚ÐµÑ€Ñли Ñ Ð²Ð°Ð¼Ð¸ ÑвÑзь. Гейт позволÑет +удовлетворить обе Ñти потребноÑти одновременно. +


    + + +

    +Ðужно перейти на Ñтраницу наÑтройки гейта, +ввеÑти ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ livejournal.com и пароль +и нажать на кнопку "Ðачать гейтование". + +Ðа Ñтой же Ñтраничке вы можете наÑтроить размер и цвет +Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом комментариев (из техничеÑких Ñоображений +количеÑтво комментариев в запиÑи на livejournal.com реализовано +в виде изображениÑ). +


    + + +

    +Мы не воÑпользуемÑÑ Ð’Ð°ÑˆÐ¸Ð¼ паролем. +

    +Мы (админиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ LJR) обÑзуемÑÑ ÑохранÑÑ‚ÑŒ в Ñекрете +вÑÑŽ чаÑтную информацию, хранÑщуюÑÑ Ð½Ð° нашем Ñервере, кроме +Ñлучаев, предуÑмотренных законом РФ. За выполнением +админиÑтрацией ее обÑзательÑтв наблюдает ПопечительÑкий +Совет, ÑоÑтоÑщий из извеÑтных деÑтелей +руÑÑкой Сети. С жалобами и подозрениÑми в отношении +админиÑтрации Ð’Ñ‹ можете обращатьÑÑ Ð² ÑоответÑтвующее ÑообщеÑтво, +либо лично к учаÑтникам ПопечительÑкого Совета. +


    + + +

    +При передаче запиÑи на Ñервер livejournal.com ÑохранÑÑŽÑ‚ÑÑ +практичеÑки вÑе атрибуты запиÑи: уровень безопаÑноÑти, +времÑ, current music, current mood, теги, иконка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +(на livejournal у Ð²Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° ÑущеÑтвовать иконка Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же именем, как и на LJR). +


    + + + +

    +ЕÑли никакой ошибки в процеÑÑе Ð³ÐµÐ¹Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ðµ произошло, +запиÑÑŒ в ЖЖ должна поÑвитьÑÑ Ñразу же. ЕÑли же произошла +какаÑ-то ошибка и запиÑÑŒ поÑвилаÑÑŒ в LJR, но не поÑвилаÑÑŒ в ЖЖ, +то узнать об ошибке можно на Ñтранице наÑтроек гейта +в поле "СтатуÑ". Ð’ Ñтом же поле выводитÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +и об уÑпешно проведенном гейтовании. +

    + + +

    +Во-первых, вы можете предложить вашим друзьÑм зарегиÑтрироватьÑÑ Ð½Ð° LJR +и оÑтавлÑÑ‚ÑŒ вам комментарии под логином LJR (никто не заÑтавлÑет их +веÑти дневник на LJR!).
    +
    +Во-вторых, они могут воÑпользоватьÑÑ Ñ‚ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸ÐµÐ¹ OpenID: +при оÑтавлении ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð² LJR ваш друг может подпиÑатьÑÑ +Ñвоим именем Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ livejournal.com (Ð´Ð»Ñ Ñтого +он должен быть залогиненным на livejournal.com). +

    + + +

    +Можно отредактировать запиÑÑŒ в ЖЖ, изменив поле "ÐаÑтройки комментариев" +Ñ "Отключены" на "Как во вÑём журнале". +

    + +$LJR$FAQ + + return $ret; + +_code?> +<=body +page?> diff --git a/local/htdocs/lj-gate/lj-gate-faq.html b/local/htdocs/lj-gate/lj-gate-faq.html new file mode 100755 index 0000000..90c5509 --- /dev/null +++ b/local/htdocs/lj-gate/lj-gate-faq.html @@ -0,0 +1,217 @@ + + + +þÁ×Ï ÐÏ ÛÌÀÚÕ ÉÚ LJR × LJ (lj.rossia.org/lj-gate) + + +

    þÁ÷Ï ÐÏ ÛÌÀÚÕ ÉÚ LJR × LJ

    + + +

    ÷.þÔÏ ÔÁËÏÅ lj-gate? + +

    ÷. ï, ÚÎÁÞÉÔ, Ñ ÓÍÏÇÕ ÓËÏÐÉÒÏ×ÁÔØ × öö ×Ó£, ÞÔÏ ÕÓÐÅÌ ÎÁ×ÁÑÔØ × LJR? + +

    ÷. á ÍÏÇÕ ÌÉ Ñ ËÏÐÉÒÏ×ÁÔØ × öö ÞÅÊ-ÌÉÂÏ ÖÕÒÎÁÌ, ËÒÏÍÅ Ó×ÏÅÇÏ? + +

    ÷. á ÍÏÇÕ ÌÉ Ñ ÇÅÊÔÏ×ÁÔØ Ä×Á ÄÎÅ×ÎÉËÁ ÎÁ LJR × ÏÄÉÎ ÄÎÅ×ÎÉË ÎÁ +LiveJournal.com (ÏÄÉÎ ÄÎÅ×ÎÉË ÎÁ LJR × Ä×Á ÄÎÅ×ÎÉËÁ ÎÁ LiveJournal, +etc. etc.)? + +

    ÷. þÔÏ ÍÎÅ ÎÁÄÏ ÓÄÅÌÁÔØ, ÞÔÏÂÙ ÍÏÉ ÚÁÐÉÓÉ Á×ÔÏÍÁÔÉÞÅÓËÉ ËÏÐÉÒÏ×ÁÌÉÓØ × +ÍÏÊ ÓÔÁÒÙÊ ÄÎÅ×ÎÉË ÎÁ LiveJournal? + +

    ÷. á ÐÏÞÅÍÕ ÜÔÏ Ñ ÄÏÌÖÅÎ ÏÔÄÁ×ÁÔØ ×ÁÍ ÐÁÒÏÌØ ÏÔ Ó×ÏÅÇÏ öö? + +

    ÷. á ËÁË Õ lj-gate Ó ÐÏÄÄÅÒÖËÏÊ ÏÇÒÁÎÉÞÅÎÉÑ ÄÏÓÔÕÐÁ? îÅ ÓÔÁÎÕÔ ÌÉ ÍÏÉ +ÐÏÄÚÁÍÏÞÎÙÅ É ÐÒÉ×ÁÔÎÙÅ ÚÁÐÉÓÉ ÎÁ LJR ÄÏÓÔÕÐÎÙ × öö ×ÓÅÍ ÖÅÌÁÀÝÉÍ? + +

    ÷. ñ ××ÅÌÁ ÐÁÒÏÌÉ ÏÔ ÏÂÏÉÈ ÄÎÅ×ÎÉËÏ×, ÎÁÖÁÌÁ ÎÁ ËÎÏÐËÕ, Á ÔÅÐÅÒØ ×ÏÌÎÕÀÓØ: +ÎÅ ÐÒÏÉÚÏÊÄ£Ô ÌÉ Ó ÍÏÉÍ öö ÞÔÏ-ÎÉÂÕÄØ ÓÔÒÁÛÎÏÅ? + +

    ÷. ñ ÎÁÐÉÓÁÌ ÚÁÐÉÓØ, Á ÏÎÁ ÎÅ ÐÏÑ×ÉÌÁÓØ × öö! ûÌÀÚ ÎÅ ÒÁÂÏÔÁÅÔ! + +

    ÷. ðÒÏÛÌÏ ÕÖÅ ÐÏÌÞÁÓÁ, Á ÚÁÐÉÓØ ÐÏ-ÐÒÅÖÎÅÍÕ ÎÅ ÓËÏÐÉÒÏ×ÁÎÁ. + +

    ÷. ïÊ! á × ÚÁÐÉÓÑÈ-ËÏÐÉÑÈ ÎÁ öö ÚÁÐÒÅÝÅÎÙ ËÏÍÍÅÎÔÙ! îÅÌØÚÑ ÌÉ ÉÈ ÒÁÚÒÅÛÉÔØ? + +

    ÷. á ËÁË ÖÅ ÍÏÉ ÄÒÕÚØÑ ÉÚ öö ÓÍÏÇÕÔ ÏÓÔÁ×ÌÑÔØ ËÏÍÍÅÎÔÁÒÉÉ ÐÏÄ +ÓÏÂÓÔ×ÅÎÎÙÍ ÉÍÅÎÅÍ? + +

    ÷. çÅÊÔ ÒÁÂÏÔÁÌ, Á ÔÅÐÅÒØ ×ÄÒÕÇ ÐÅÒÅÓÔÁÌ! + +

    ÷. á ÅÓÌÉ Ñ ÐÏÍÅÎÑÌ ÐÁÒÏÌØ, ÞÔÏ ÍÎÅ ÄÅÌÁÔØ? + +

    ÷. ñ ÈÏÞÕ ×ÒÅÍÅÎÎÏ ÐÒÅËÒÁÔÉÔØ ÔÒÁÎÓÌÑÃÉÀ. ëÁË ÜÔÏ ÓÄÅÌÁÔØ? + +

    ÷. þÔÏ ÄÅÌÁÔØ, ÅÓÌÉ ÓÏÏÂÝÅÎÉÅ ÎÅ ÓËÏÐÉÒÏ×ÁÌÏÓØ? õ ÍÅÎÑ ÎÅÔ ×ÏÚÍÏÖÎÏÓÔÉ (ÉÌÉ ÖÅÌÁÎÉÑ) +ËÏÐÉÒÏ×ÁÔØ ÅÇÏ ×ÒÕÞÎÕÀ. + +

    ÷. íÏÖÎÏ ÌÉ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ × ËÏÍØÀÎÉÔÉ? + +

    ÷. ëÁË ÚÄÏÒÏ×Ï! úÎÁÞÉÔ, Ñ ÍÏÇÕ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ ÉÚ ÄÎÅ×ÎÉËÁ ÎÁ LJR × +LJ, É ÍÎÅ ÚÁ ÜÔÏ ÎÉÞÅÇÏ ÎÅ ÂÕÄÅÔ? + +

    ÷. á ÍÏÖÎÏ ÌÉ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ ÎÁ ÄÒÕÇÏÊ ÂÌÏÇ-ÓÁÊÔ (îðö, +GreatestJournal, liveinternet.ru)? + +


    + +

    +

    ÷.þÔÏ ÔÁËÏÅ lj-gate? + +

    ï. üÔÏ ÐÒÏÇÒÁÍÍÁ — ÛÌÀÚ ÍÅÖÄÕ lj.rossia.org É öÉ×ÙÍ +öÕÒÎÁÌÏÍ, Á×ÔÏÍÁÔÉÞÅÓËÉ ËÏÐÉÒÕÀÝÁÑ ×ÁÛÉ ÚÁÐÉÓÉ ÎÁ LJR × ÄÎÅ×ÎÉË ÎÁ +ÓÁÊÔÅ www.livejournal.com. + +

    +

    ÷. ï, ÚÎÁÞÉÔ, Ñ ÓÍÏÇÕ ÓËÏÐÉÒÏ×ÁÔØ × öö ×Ó£, ÞÔÏ ÕÓÐÅÌ ÎÁ×ÁÑÔØ × LJR? + +

    ï. ë ÓÏÖÁÌÅÎÉÀ, ÎÅÔ: ËÏÐÉÒÏ×ÁÔØÓÑ ÂÕÄÕÔ ÔÏÌØËÏ ÔÅ ÚÁÐÉÓÉ, ËÏÔÏÒÙÅ ×Ù +ÓÄÅÌÁÌÉ ÐÏÓÌÅ ÔÏÇÏ, ËÁË ×Ù ÎÁÓÔÒÏÉÌÉ ÛÌÀÚÏ×ÁÎÉÅ Ó×ÏÅÇÏ ÄÎÅ×ÎÉËÁ. á +ÓÔÁÒÙÅ ÐÏÓÔÉÎÇÉ — ÔÏÌØËÏ ÅÓÌÉ ×Ù ÉÈ ÏÔÒÅÄÁËÔÉÒÕÅÔÅ (É Ó +ÁÔÒÉÂÕÔÏÍ backdated, ÅÓÔÅÓÔ×ÅÎÎÏ). + +

    íÙ ÐÌÁÎÉÒÕÅÍ ÒÅÁÌÉÚÏ×ÁÔØ ÏÂÒÁÔÎÕÀ ×ÏÚÍÏÖÎÏÓÔØ — ÉÍÐÏÒÔ × +LJR ×ÁÛÉÈ ÚÁÐÉÓÅÊ Ó LiveJournal.com. + +

    +

    ÷. á ÍÏÇÕ ÌÉ Ñ ËÏÐÉÒÏ×ÁÔØ × öö ÞÅÊ-ÌÉÂÏ ÖÕÒÎÁÌ, ËÒÏÍÅ Ó×ÏÅÇÏ? + +

    ï. îÅÔ. ôÏ ÅÓÔØ, ËÏÎÅÞÎÏ, ÍÏÖÅÔÅ. åÓÌÉ ÚÎÁÅÔÅ ÐÁÒÏÌØ ÏÔ ÜÔÏÇÏ +ÖÕÒÎÁÌÁ. é ÅÓÌÉ ÈÏÚÑÉÎ ÖÕÒÎÁÌÁ ÎÅ ÐÒÏÔÉ×. + +

    +

    ÷. á ÍÏÇÕ ÌÉ Ñ ÇÅÊÔÏ×ÁÔØ Ä×Á ÄÎÅ×ÎÉËÁ ÎÁ LJR × ÏÄÉÎ ÄÎÅ×ÎÉË ÎÁ +LiveJournal.com (ÏÄÉÎ ÄÎÅ×ÎÉË ÎÁ LJR × Ä×Á ÄÎÅ×ÎÉËÁ ÎÁ LiveJournal, +etc. etc.)? + +

    ï. îÅÔ. åÓÌÉ ÜÔÏ ÏËÁÖÅÔÓÑ ÁËÔÕÁÌØÎÙÍ ÄÌÑ ÍÎÏÇÉÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, ÍÙ +ÐÏÐÒÏÂÕÅÍ ÄÏÂÁ×ÉÔØ ÔÁËÕÀ ×ÏÚÍÏÖÎÏÓÔØ. + +

    +

    ÷. þÔÏ ÍÎÅ ÎÁÄÏ ÓÄÅÌÁÔØ, ÞÔÏÂÙ ÍÏÉ ÚÁÐÉÓÉ Á×ÔÏÍÁÔÉÞÅÓËÉ ËÏÐÉÒÏ×ÁÌÉÓØ × +ÍÏÊ ÓÔÁÒÙÊ ÄÎÅ×ÎÉË ÎÁ LiveJournal? + +

    ï. úÁÊÔÉ ÎÁ ÜÔÕ +ÓÔÒÁÎÉÃÕ, × Ä×ÕÈ ×ÅÒÈÎÉÈ ÐÏÌÑÈ ××ÅÓÔÉ Ó×ÏÊ ÌÏÇÉÎ É ÐÁÒÏÌØ ÎÁ LJR, × +Ä×ÕÈ ÎÉÖÎÉÈ — ÌÏÇÉÎ É ÐÁÒÏÌØ ÏÔ Ó×ÏÅÇÏ öö. îÁÖÁÔØ ÎÁ ËÎÏÐËÕ +"Submit" (ÉÌÉ "ïÔÐÒÁ×ÉÔØ ÚÁÐÒÏÓ", ÉÌÉ ÅÝ£ ËÁË-ÎÉÂÕÄØ — ÜÔÏ +ÚÁ×ÉÓÉÔ ÏÔ ×ÁÛÅÇÏ ÂÒÁÕÚÅÒÁ; × ÏÂÝÅÍ, ËÎÏÐËÁ ÔÁÍ ÏÄÎÁ, ÒÁÚÂÅÒ£ÔÅÓØ). + +

    +

    ÷. á ÐÏÞÅÍÕ ÜÔÏ Ñ ÄÏÌÖÅÎ ÏÔÄÁ×ÁÔØ ×ÁÍ ÐÁÒÏÌØ ÏÔ Ó×ÏÅÇÏ öö? + +

    ï. îÉËÔÏ ÎÉËÏÍÕ ÎÉÞÅÇÏ ÎÅ ÄÏÌÖÅÎ. îÅ ÄÏ×ÅÒÑÅÔÅ ÎÁÍ — ÎÅ +ÐÏÌØÚÕÊÔÅÓØ lj-gate. + +

    +

    ÷. á ËÁË Õ lj-gate Ó ÐÏÄÄÅÒÖËÏÊ ÏÇÒÁÎÉÞÅÎÉÑ ÄÏÓÔÕÐÁ? îÅ ÓÔÁÎÕÔ ÌÉ ÍÏÉ +ÐÏÄÚÁÍÏÞÎÙÅ É ÐÒÉ×ÁÔÎÙÅ ÚÁÐÉÓÉ ÎÁ LJR ÄÏÓÔÕÐÎÙ × öö ×ÓÅÍ ÖÅÌÁÀÝÉÍ? + +

    ï. õÒÏ×ÎÉ ÄÏÓÔÕÐÁ "ÄÌÑ ÄÒÕÚÅÊ" É "ÄÌÑ ÓÅÂÑ" +ÐÏÄÄÅÒÖÉ×ÁÀÔÓÑ. ïÔÎÏÓÉÔÅÌØÎÏ ÚÁÐÉÓÅÊ, ËÏÔÏÒÙÅ ÄÅÌÁÀÔÓÑ ÄÌÑ +ÏÐÒÅÄÅÌ£ÎÎÙÈ ÇÒÕÐÐ ÄÒÕÚÅÊ, ÍÙ ÎÉÞÅÇÏ ÏÂÅÝÁÔØ ÎÅ ÍÏÖÅÍ. + +

    +

    ÷. ñ ××ÅÌÁ ÐÁÒÏÌÉ ÏÔ ÏÂÏÉÈ ÄÎÅ×ÎÉËÏ×, ÎÁÖÁÌÁ ÎÁ ËÎÏÐËÕ, Á ÔÅÐÅÒØ ×ÏÌÎÕÀÓØ: +ÎÅ ÐÒÏÉÚÏÊÄ£Ô ÌÉ Ó ÍÏÉÍ öö ÞÔÏ-ÎÉÂÕÄØ ÓÔÒÁÛÎÏÅ? +

    ï. îÅ ÄÏÌÖÎÏ. úÁÐÉÓÉ, ËÏÔÏÒÙÅ ×Ù ÐÉÛeÔÅ ÎÁ LJR, ÂÕÄÕÔ ÔÅÐÅÒØ ÐÏÑ×ÌÑÔØÓÑ +É × ×ÁÛÅÍ öö, ×ÏÔ É ×Ó£. + +

    +

    ÷. ñ ÎÁÐÉÓÁÌ ÚÁÐÉÓØ, Á ÏÎÁ ÎÅ ÐÏÑ×ÉÌÁÓØ × öö! ûÌÀÚ ÎÅ ÒÁÂÏÔÁÅÔ! + +

    ï. úÁÐÉÓÉ ËÏÐÉÒÕÀÔÓÑ Ó ÎÅÂÏÌØÛÏÊ ÚÁÄÅÒÖËÏÊ, ÄÏ ÄÅÓÑÔÉ ÍÉÎÕÔ. åÓÌÉ ×Ù ÎÅ +×ÉÄÉÔÅ ËÏÐÉÀ ×ÁÛÅÊ ÚÁÐÉÓÉ × öö ÞÅÒÅÚ ÍÉÎÕÔÕ ÉÌÉ Ä×Å, ÎÁÞÉÎÁÔØ +ÐÁÎÉËÏ×ÁÔØ ÅÝ£ ÒÁÎÏ. + +

    +

    ÷. ðÒÏÛÌÏ ÕÖÅ ÐÏÌÞÁÓÁ, Á ÚÁÐÉÓØ ÐÏ-ÐÒÅÖÎÅÍÕ ÎÅ ÓËÏÐÉÒÏ×ÁÎÁ. +

    ï. åÓÌÉ ÚÁÐÉÓØ ÂÙÌÁ ÐÏÄÚÁÍÏÞÎÏÊ, ÐÒÏ×ÅÒØÔÅ, ÚÁÌÏÇÉÎÅÎÙ ÌÉ ×Ù × öö. åÓÌÉ +ÚÁÌÏÇÉÎÅÎÙ, Á ÚÁÐÉÓÉ ×Ó£-ÔÁËÉ ÎÅ ×ÉÄÎÏ, ÚÎÁÞÉÔ, ÏÎÁ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÎÅ +ÂÙÌÁ ÓËÏÐÉÒÏ×ÁÎÁ. ë ÓÏÖÁÌÅÎÉÀ, ÔÁËÏÅ ÓÌÕÞÁÅÔÓÑ, É ÎÅ ×ÓÅÇÄÁ ÐÏ ÎÁÛÅÊ +×ÉÎÅ. ðÏÐÒÏÂÕÊÔÅ ÎÁÐÉÓÁÔØ ÅÝ£ ÏÄÎÕ ÚÁÐÉÓØ. åÓÌÉ ÎÅ ÓËÏÐÉÒÕÅÔÓÑ É ÏÎÁ, +ÚÎÁÞÉÔ, ÛÌÀÚÏ×ÁÎÉÅ ×ÁÛÅÇÏ ÄÎÅ×ÎÉËÁ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÎÅ ÒÁÂÏÔÁÅÔ. ÷ ÜÔÏÍ +ÓÌÕÞÁÅ ÎÁÐÉÛÉÔÅ ÐÏÓÔÉÎÇ × +É ÍÙ ÐÏÓÔÁÒÁÅÍÓÑ ×ÁÍ ÐÏÍÏÞØ. + +

    +

    ÷. ïÊ! á × ÚÁÐÉÓÑÈ-ËÏÐÉÑÈ ÎÁ öö ÚÁÐÒÅÝÅÎÙ ËÏÍÍÅÎÔÙ! îÅÌØÚÑ ÌÉ ÉÈ ÒÁÚÒÅÛÉÔØ? +

    ï. íÏÖÎÏ. ïÔÒÅÄÁËÔÉÒÏ×Á× ÚÁÐÉÓØ × öö ×ÒÕÞÎÕÀ. îÏ ÓÎÁÞÁÌÁ ÐÏÄÕÍÁÊÔÅ: +ÎÕÖÎÏ ÌÉ ×ÁÍ, ÞÔÏÂÙ ÏÂÓÕÖÄÅÎÉÅ ×ÁÛÅÇÏ ÐÏÓÔÉÎÇÁ ×ÅÌÏÓØ × Ä×ÕÈ ÎÉËÁË ÎÅ +Ó×ÑÚÁÎÎÙÈ ÍÅÖÄÕ ÓÏÂÏÊ ÍÅÓÔÁÈ? + +

    ÷ÐÒÏÞÅÍ, ÍÙ ÐÌÁÎÉÒÕÅÍ ÄÏÂÁ×ÉÔØ ×ÏÚÍÏÖÎÏÓÔØ ×ËÌÀÞÅÎÉÑ ËÏÍÍÅÎÔÁÒÉÅ× × +ÚÁÐÉÓÉ-ËÏÐÉÉ × ËÁÞÅÓÔ×Å ÏÐÃÉÉ. + +

    +

    ÷. á ËÁË ÖÅ ÍÏÉ ÄÒÕÚØÑ ÉÚ öö ÓÍÏÇÕÔ ÏÓÔÁ×ÌÑÔØ ËÏÍÍÅÎÔÁÒÉÉ ÐÏÄ +ÓÏÂÓÔ×ÅÎÎÙÍ ÉÍÅÎÅÍ? +

    ï. ÷ÏÏÂÝÅ-ÔÏ ÄÌÑ ÜÔÏÇÏ ÓÕÝÅÓÔ×ÕÅÔ ÛÔÕËÁ ÐÏÄ ÎÁÚ×ÁÎÉÅÍ OpenID. ðÒÏÂÌÅÍÁ × ÔÏÍ, ÞÔÏ ÏÎÁ ÅÝ£ +ÒÁÚÒÁÂÁÔÙ×ÁÅÔÓÑ, É ÒÁÂÏÔÁÅÔ ÎÅ ×ÓÅÇÄÁ. ÷ ÄÁÎÎÙÊ ÍÏÍÅÎÔ (02.08.2005) +ÐÏÌØÚÏ×ÁÔÅÌÉ ×ÓÅÈ ÂÌÏÇ-ÓÁÊÔÏ×, ÐÏÄÄÅÒÖÉ×ÁÀÝÉÊ OpenID (îðö, +GreatestJournal É ÄÒÕÇÉÅ ÓÁÊÔÙ ÎÁ ÜÔÉÈ Ä×ÉÖËÁÈ ÄÏÓÔÁÔÏÞÎÏ Ó×ÅÖÉÈ +×ÅÒÓÉÊ) ÍÏÇÕÔ ÏÓÔÁ×ÌÑÔØ ËÏÍÍÅÎÔÁÒÉÉ ÏÔ Ó×ÏÅÇÏ ÉÍÅÎÉ. ëÒÏÍÅ, Õ×Ù, +ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÓÁÍÏÇÏ LiveJournal.com. ë ÓÏÖÁÌÅÎÉÀ, ÒÅÛÅÎÉÅ ÜÔÏÊ +ÐÒÏÂÌÅÍÙ ÚÁ×ÉÓÉÔ ÎÅ ÏÔ ÎÁÓ: Õ Á×ÔÏÒÏ× LJ ÄÏ×ÏÌØÎÏ ÜËÚÏÔÉÞÅÓËÉÅ +ÐÒÅÄÓÔÁ×ÌÅÎÉÑ Ï ÏÂÒÁÔÎÏÊ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ. + +

    +

    ÷. çÅÊÔ ÒÁÂÏÔÁÌ, Á ÔÅÐÅÒØ ×ÄÒÕÇ ÐÅÒÅÓÔÁÌ! +

    ï. á ×Ù, ÓÌÕÞÁÅÍ, ÎÅ ÍÅÎÑÌÉ ÐÁÒÏÌØ ÎÉ Ë ÏÄÎÏÍÕ ÉÚ ÖÕÒÎÁÌÏ×? åÓÌÉ +ÎÅÔ — ÐÏÐÒÏÂÕÊÔÅ ÎÁÐÉÓÁÔØ ÅÝ£ ÏÄÎÕ ÚÁÐÉÓØ, ×ÄÒÕÇ ÐÒÏÂÌÅÍÙ +ÂÙÌÉ ×ÒÅÍÅÎÎÙÍÉ É ÕÖÅ ÒÅÛÅÎÙ? åÓÌÉ ÏÐÑÔØ ÎÉÞÅÇÏ ÎÅ +ÐÏÌÕÞÉÔÓÑ — ÎÁÐÉÛÉÔÅ × +ÐÏÓÔÉÎÇ Ó ÏÐÉÓÁÎÉÅÍ ÐÒÏÂÌÅÍÙ. + +

    +

    ÷. á ÅÓÌÉ Ñ ÐÏÍÅÎÑÌ ÐÁÒÏÌØ, ÞÔÏ ÍÎÅ ÄÅÌÁÔØ? +

    ï. ðÏËÁ ÍÙ ÎÅ ÐÅÒÅÛÌÉ ÎÁ ÂÏÌÅÅ ÒÁÚÕÍÎÕÀ ×ÅÒÓÉÀ ÇÅÊÔÁ — +ÔÏÌØËÏ ÕÄÁÌÉÔØ ÔÒÁÎÓÌÑÃÉÀ ÚÄÅÓØ, ××ÅÄÑ +(×ÎÉÍÁÎÉÅ!) ÓÔÁÒÙÊ ÐÁÒÏÌØ ÏÔ ×ÁÛÅÇÏ ÖÕÒÎÁÌÁ, Á ÐÏÔÏÍ ÄÏÂÁ×É× Å£ +ÚÁÎÏ×Ï. õÞÔÉÔÅ, ÞÔÏ ÐÏÓÌÅ ÜÔÏÇÏ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ ÓÔÁÒÙÈ (ÔÏ ÅÓÔØ +ÓËÏÐÉÒÏ×ÁÎÎÙÈ ÄÏ ÓÍÅÎÙ ÐÁÒÏÌÑ) ÚÁÐÉÓÅÊ +ÐÏÄÄÅÒÖÉ×ÁÔØÓÑ ÎÅ ÂÕÄÅÔ. + +

    +

    ÷. ñ ÈÏÞÕ ×ÒÅÍÅÎÎÏ ÐÒÅËÒÁÔÉÔØ ÔÒÁÎÓÌÑÃÉÀ. ëÁË ÜÔÏ ÓÄÅÌÁÔØ? +

    ï. ôÏÌØËÏ ÕÄÁÌÉÔØ Å£, Á ÐÏÔÏÍ ÎÁÓÔÒÏÉÔØ ÚÁÎÏ×Ï. éÚ×ÉÎÉÔÅ. + +

    óËÏÒÅÅ ×ÓÅÇÏ, × ÂÕÄÕÝÅÍ ÍÙ ÄÏÂÁ×ÉÍ ×ÏÚÍÏÖÎÏÓÔØ ÐÒÅËÒÁÝÅÎÉÑ ÔÒÁÎÓÌÑÃÉÉ ÂÅÚ ÕÄÁÌÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÑ. + +

    +

    ÷. þÔÏ ÄÅÌÁÔØ, ÅÓÌÉ ÓÏÏÂÝÅÎÉÅ ÎÅ ÓËÏÐÉÒÏ×ÁÌÏÓØ? õ ÍÅÎÑ ÎÅÔ ×ÏÚÍÏÖÎÏÓÔÉ (ÉÌÉ ÖÅÌÁÎÉÑ) ËÏÐÉÒÏ×ÁÔØ ÅÇÏ ×ÒÕÞÎÕÀ. +

    ï. ïÔÒÅÄÁËÔÉÒÕÊÔÅ ÏÒÉÇÉÎÁÌ ÚÁÐÉÓÉ × LJR (ÎÉÞÅÇÏ ÒÅÁÌØÎÏ ÍÅÎÑÔØ ÎÅ ÎÁÄÏ, +ÄÏÓÔÁÔÏÞÎÏ ÚÁÊÔÉ ÎÁ ÓÔÒÁÎÉÃÕ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ ÚÁÐÉÓÉ, Á ÐÏÔÏÍ ÓÏÈÒÁÎÉÔØ +ÜÔÕ ÚÁÐÉÓØ). ðÏ ÉÄÅÅ, ÐÏÓÌÅ ÜÔÏÇÏ ÚÁÐÉÓØ ÄÏÌÖÎÁ ÓËÏÐÉÒÏ×ÁÔØÓÑ × öö. + +

    +

    ÷. íÏÖÎÏ ÌÉ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ × ËÏÍØÀÎÉÔÉ? +

    ï. ðÏËÁ ÎÅÔ. íÙ ÒÁÂÏÔÁÅÍ ÎÁÄ ÜÔÉÍ. + +

    +

    ÷. ëÁË ÚÄÏÒÏ×Ï! úÎÁÞÉÔ, Ñ ÍÏÇÕ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ ÉÚ ÄÎÅ×ÎÉËÁ ÎÁ LJR × +LJ, É ÍÎÅ ÚÁ ÜÔÏ ÎÉÞÅÇÏ ÎÅ ÂÕÄÅÔ? +

    ï. îÅ ×Ó£ ÔÁË ÒÁÄÕÖÎÏ. ToS (ÐÏÌØÚÏ×ÁÔÅÌØÓËÏÅ ÓÏÇÌÁÛÅÎÉÅ) öö, × ÒÁÚÄÅÌÅ +XVI, "Member conduct", ÓÏÄÅÒÖÉÔ ÔÁËÏÊ ÐÕÎËÔ: +

    +You agree to NOT use the Service to:
    +…
    +14.Use LiveJournal.com as a forwarding service to another website; +
    +

    ëÔÏ ÉÈ ÚÎÁÅÔ, ÍÁÌÏ ÌÉ ÞÔÏ ÏÎÉ ÉÍÅÌÉ × ×ÉÄÕ. íÙ ÎÁÄÅÅÍÓÑ ÎÁ ×ÍÅÎÑÅÍÏÓÔØ +ÁÄÍÉÎÉÓÔÒÁÃÉÉ É Abuse Team öö (ÐÏ ÆÁËÔÕ ÎÁ LiveJournal.com ÓÕÝÅÓÔ×ÕÅÔ +ÍÁÓÓÁ ÇÅÊÔÕÅÍÙÈ ÄÎÅ×ÎÉËÏ×), ÎÏ ÏÂÅÝÁÔØ ×ÁÍ ÎÉÞÅÇÏ ÎÅ ÍÏÖÅÍ. + +

    +

    ÷. á ÍÏÖÎÏ ÌÉ ËÏÐÉÒÏ×ÁÔØ ÚÁÐÉÓÉ ÎÁ ÄÒÕÇÏÊ ÂÌÏÇ-ÓÁÊÔ (îðö, +GreatestJournal, liveinternet.ru)? +

    ï. îÅÔ. åÓÌÉ ÜÔÏ ÏËÁÖÅÔÓÑ ÁËÔÕÁÌØÎÏ ÂÏÌØÛÏÍÕ ËÏÌÉÞÅÓÔ×Õ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÍÙ ÄÏÂÁ×ÉÍ ÔÁËÕÀ ×ÏÚÍÏÖÎÏÓÔØ. + +

    ÷ÐÒÏÞÅÍ, ×ÏÚÍÏÖÎÏ, ×Ù ÓÍÏÖÅÔÅ ÔÒÁÎÓÌÉÒÏ×ÁÔØ ×ÁÛ ÄÎÅ×ÎÉË ÎÁ ÄÒÕÇÏÊ ÓÁÊÔ ÞÅÒÅÚ RSS-ÐÏÔÏË, ÄÏÓÔÕÐÎÙÊ ÐÏ ÁÄÒÅÓÕ http://lj.rossia.org/users/username/data/rss, ÇÄÅ username — ×ÁÛ ÎÉË ÎÁ LJR. + + diff --git a/local/htdocs/manage/siteopts.bml b/local/htdocs/manage/siteopts.bml new file mode 100755 index 0000000..6d6d543 --- /dev/null +++ b/local/htdocs/manage/siteopts.bml @@ -0,0 +1,243 @@ +{'thumb'} eq 'ARRAY') { + push @thumb_schemes, $_; + } else { + push @text_schemes, $_; + } + } + + # saving changes + if (LJ::did_post()) { + + my $remote = LJ::get_remote(); + + # was a scheme change posted? + my $scheme; + if (exists $POST{'action:setscheme'}) { + foreach (@text_schemes) { + $scheme = $_->{'scheme'} if $POST{'scheme'} eq $_->{'scheme'}; + } + } else { + foreach (@thumb_schemes) { + $scheme = $_->{'scheme'} if exists $POST{"action:setscheme:$_->{'scheme'}.x"}; + } + } + + # set scheme + if ($scheme) { + my $cval = $scheme; + + # don't set cookie for default scheme + if ($scheme eq $LJ::SCHEMES[0]->{'scheme'}) { + $cval = ''; + delete $COOKIE{'BMLschemepref'}; + } + + # logged in? + if ($remote) { + # set a userprop to remember their schemepref + LJ::set_userprop($remote, 'schemepref', $cval); + + # cookie expires when session expires + if ($remote->{'_session'}->{'exptype'} eq 'long') { + $cval = [ $scheme, $remote->{'_session'}->{'timeexpire'} ]; + } + } + + # set cookie + $COOKIE{'BMLschemepref'} = $cval if $cval; + + # redirect to refresh cookie settings + return $redir->(); + } + + # set language + if (exists $POST{'action:setlang'} && $POST{'lang'}) { + my $l = LJ::Lang::get_lang($POST{'lang'}); + return $redir->() unless $l; + + # default cookie value to set + my $cval = $l->{'lncode'} . "/" . time(); + + # if logged in, change userprop and make cookie expiration + # the same as their login expiration + my $remote = LJ::get_remote(); + if ($remote) { + LJ::set_userprop($remote, "browselang", $l->{'lncode'}); + + if ($remote->{'_session'}->{'exptype'} eq 'long') { + $cval = [ $cval, $remote->{'_session'}->{'timeexpire'} ]; + } + } + + # set cookie + $COOKIE{'langpref'} = $cval; + + # set language through BML so it will apply immediately + BML::set_language($l->{'lncode'}); + } + } + + # set title now that we have the correct language + $title = $ML{'.title'}; + + # preferences page output + + # wrapper box to to keep tables from scrolling horizontally + $body .= "
    "; + + # scheme selector + if (@LJ::SCHEMES) { + $body .= ""; + $body .= "
    "; + + my $scheme = $BML::COOKIE{'BMLschemepref'}; + $scheme = $LJ::SCHEMES[0]->{'scheme'} unless $scheme; + + if (@thumb_schemes) { + my $ct = 0; + my $cols = 3; + my $width = int(100 / $cols +.5) . "%"; + my $switch = @thumb_schemes / $cols; + + $body .= ""; + $body .= ""; + foreach my $sh (@thumb_schemes) { + if ($ct == 0) { + $body .= ""; + $ct = 0; + } + } + $body .= "
    "; + } + my $th = $sh->{'thumb'}; + $body .= "
    {'title'} h2?> [1]; + $body .= " height='$th->[2]'" if $th->[2]; + + if ($sh->{'scheme'} eq $scheme) { + $body .= "style='border: solid 2px blue;' "; + } else { + $body .= "style='border: solid 1px black;' "; + } + my $alt = BML::ml('.scheme.preview', {'title' => $sh->{'title'},}); + $body .= " alt='$alt' title='$sh->{'title'}'/>
    "; + if (++$ct >= $switch) { + $body .= "
    "; + } + + if (@text_schemes) { + + my $ct = 0; + my $cols = 3; + my $width = int(100 / $cols +.5) . "%"; + my $switch = @text_schemes / $cols; + + $body .= ""; + $body .= ""; + + foreach my $sh (@text_schemes) { + + if ($ct == 0) { + $body .= ""; + $ct = 0; + } + } + + $body .= "
    "; + } + + $body .= "

    " . + LJ::html_check({ 'type' => 'radio', 'name' => 'scheme', + 'value' => $sh->{'scheme'}, + 'id' => "scheme-$sh->{'scheme'}", + 'selected' => $scheme eq $sh->{'scheme'} }); + + $body .= "

    "; + + if (++$ct >= $switch) { + $body .= "
    "; + $body .= LJ::html_submit('action:setscheme', $ML{'.btn.scheme'}); + + $body .= "
    "; + } + + $body .= "
    "; + } + + # language selector + $body .= ""; + $body .= "
    "; + + my $ct = 0; + my $cols = 3; + my $width = int(100 / $cols +.5) . "%"; + my $switch = @LJ::LANGS / $cols; + my $curr = BML::get_language(); + + $body .= ""; + $body .= ""; + + my @inc; + push @inc, $GET{'addlang'} if $GET{'addlang'}; + + foreach my $code (@LJ::LANGS, @inc) { + my $l = LJ::Lang::get_lang($code); + next unless $l; + + my $item = "langname.$code"; + my $namethislang = BML::ml($item); + my $namenative = LJ::Lang::get_text($l->{'lncode'}, $item); + + if ($ct == 0) { + $body .= ""; + $ct = 0; + } + } + + $body .= ""; + $body .= "
    "; + } + + $body .= "

    " . LJ::html_check({ 'type' => 'radio', 'name' => 'lang', + 'value' => $code, 'id' => "sel_$code", + 'selected' => $code eq $curr }); + + $body .= "

    \n"; + + if (++$ct >= $switch) { + $body .= "
    "; + $body .= LJ::html_submit('action:setlang', $ML{'.btn.lang'}); + + $body .= "
    "; + + $body .= "
    "; + + return; +} +_code?> +body=> +page?> diff --git a/local/htdocs/manage/tags.bml b/local/htdocs/manage/tags.bml new file mode 100755 index 0000000..294220e --- /dev/null +++ b/local/htdocs/manage/tags.bml @@ -0,0 +1,269 @@ + +body<= +" + if $LJ::DISABLED{tags}; + + my $remote = LJ::get_remote(); + return "" unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + # do user requested changes + my $add_text = $ML{'.addnew'}; + if (LJ::did_post()) { + + # Adding new tags + $POST{add} = 1 if $POST{'add.x'} or $POST{'add.y'}; # image submit + if ($POST{add} or ($POST{'add_field'} && $POST{'add_field'} ne $add_text)) { + LJ::Tags::create_usertag($u, $POST{'add_field'}, { display => 1 }); + } + + # Deleting tags + if ($POST{delete}) { + foreach my $id (split /\0/, $POST{tags}) { + $id =~ s/_.*//; + LJ::Tags::delete_usertag( $u, 'id', $id ); + } + } + + if ($POST{rename}) { + my @tagnames = map { s/\d+_//; $_; } split /\0/, $POST{tags}; + my $new_tag = LJ::trim($POST{rename_field}); + $new_tag =~ s/,.*//; + + # FIXME: merge support later + my $rr = LJ::Tags::rename_usertag( $u, 'name', $tagnames[0], $new_tag ); + + return "" unless $rr; + } + + if ($POST{'show posts'}) { + # this should do some cute ajax display later. + my $tags = LJ::Tags::get_usertags( $u ); # we redirect, so we don't double load anyway + my $taglist = LJ::eurl(join ',', map { $tags->{$_}->{name} } map { /^(\d+)_/; $1; } split /\0/, $POST{tags}); + BML::redirect( LJ::journal_base($u) . "/tag/$taglist" ); + } + + } + + # get tags list! + my $tags = LJ::Tags::get_usertags( $u ); + my $tagcount = scalar keys %$tags; + + # create histogram usage levels from 'uses' counts + # for 'cell bars' icon display + if ($tagcount) { + my ( + @data, + $groups, + $max, $min, + $width, + %range, + ); + + $groups = 5; + + # order by use + @data = map { [ $_, $tags->{$_}->{uses} ] } + sort { $tags->{$a}->{uses} <=> $tags->{$b}->{uses} } keys %$tags; + + # get min use, max use, and group 'width' + $max = $data[-1]->[1]; + $min = $data[0]->[1]; + $width = ($max - $min) / $groups || 1; + + # pre calculate ranges for groups + for (1..$groups) { + $range{$_} = []; + @{$range{$_}}[0] = $min + ($_ - 1) * $width; # low + @{$range{$_}}[1] = $min + ($_ * $width); # high + } + + # iterate through sorted data, adding + # histogram group to the tags data structure. + foreach (@data) { + my ($id, $use) = (@$_); + GROUP: + for (1..$groups) { + if ($use >= @{$range{$_}}[0] && $use <= @{$range{$_}}[1]) { + $tags->{$id}->{histogram_group} = $_; + last GROUP; + } + } + } + } + + # button titles (mouseovers) + my $mo = { + create => $ML{'.hint.create'}, + rename => $ML{'.hint.rename'}, + delete => $ML{'.hint.delete'}, + entries => $ML{'.hint.entries'}, + }; + + my $sp = '  '; + my $ret; + + # user switcher + $ret .= "

    \n"; + $ret .= LJ::make_authas_select($remote, { authas => $u->{user} }); + $ret .= "
    \n"; + + $ret .= ""; + + # convert tags data structure to javascript array for quick prop display. + # this is temporary, we'll eventually do a smarter + # xml-rpc call instead of requiring this. + $ret .= "\n\n"; + + # the extra 'padding' div is a workaround for how + # IE incorrectly renders fieldsets. + $ret .= qq{ +
    + + +
    +
    + $ML{'.label.yours'} +
    + }; + + my $tagsort = sub { + $GET{sort} eq 'use' ? + $tags->{$b}->{uses} <=> $tags->{$a}->{uses} : + $tags->{$a}->{name} cmp $tags->{$b}->{name}; + }; + + if ($tagcount) { + $ret .= ""; + + $ret .= ' +
    + +
    +
    '; + + unless ($tagcount) { + $ret .= ' 
    '; + return $ret; + } + + $ret .= "
    $ML{'.label.tags'}"; + $ret .= '
    '; + $ret .= "
     
    "; + + $ret .= "
    "; + $ret .= LJ::html_text( + { + name => 'rename_field', + size => 30, + class => 'tagfield', + onClick => 'reset_field(this)', + } + ); + $ret .= $sp; + $ret .= LJ::html_submit( + 'rename', $ML{'.button.rename'}, + { + class => 'btn', + title => $mo->{rename}, + onClick => 'return validate_input(this, "rename_field")', + } + ); + $ret .= '

    '; + + my $del_conf = $ML{'.confirm.delete'}; + $ret .= LJ::html_submit( + 'delete', $ML{'.button.delete'}, + { + class => 'btn', + title => $mo->{delete}, + onClick => "return confirm('$del_conf')", + } + ) . $sp; + $ret .= LJ::html_submit( + 'show posts', $ML{'.button.show'}, + { + class => 'btn', + title => $mo->{entries}, + } + ); + + $ret .= '

     
    '; + + $ret .= ' +
    +
    + + + '; + + return $ret; + +} _code?> +<=body +head<= + + +<=head +bodyopts=>onLoad="initTagPage()" +page?> diff --git a/local/htdocs/mobile/friends.bml b/local/htdocs/mobile/friends.bml new file mode 100644 index 0000000..343b722 --- /dev/null +++ b/local/htdocs/mobile/friends.bml @@ -0,0 +1,96 @@ + + +Friends Page + + + +

    " + unless $u; + + my $itemsperpage = 50; + + my $ret; + + my $skip = $GET{skip}+0 || 0; + + my $prevcount = $skip + $itemsperpage; + my $nextcount = $skip ? $skip - $itemsperpage : -1; + my $nextlink = $nextcount != -1 ? " | Next $itemsperpage >>" : ''; + my $prevlink = "<< Previous $itemsperpage"; + + # Filter first to a "Mobile View" friends group if they have one, + # then fall back to "Default View", and then just show them everything + my $filter; + my $groupname = "All friends"; + + foreach ("Mobile View", "Default View") { + if (my $grp = LJ::get_friend_group($u, { 'name' => $_ })) { + $groupname = $_; + $filter = 1 << $grp->{'groupnum'}; + last; + } + } + + $ret = qq { + << Back to LiveJournal Mobile. +

    Friends Page
    +
    +
    Viewing: $groupname
    +
    $prevlink$nextlink

    +
    + }; + +sub New; + + + my %friends; + my @items = LJ::get_friend_items({ + 'remote' => $u, + 'itemshow' => $itemsperpage, + 'skip' => $skip, + 'showtypes' => 'PYC', + 'u' => $u, + 'filter' => $filter, + 'friends_u' => \%friends, + }); + + # how many characters to truncate entry at + my $max_entry_length = 400; + + foreach my $ei (@items) { + next unless $ei; +# my $entry; +# if ($ei->{'ditemid'}) { +# $entry = LJ::Entry->new($ei->{'journalid'}, +# ditemid => $ei->{'ditemid'}); +# } elsif ($ei->{'jitemid'} && $ei->{'anum'}) { +# $entry = LJ::Entry->new($ei->{'journalid'}, +# jitemid => $ei->{'jitemid'}, +# anum => $ei->{'anum'}); +# } +# next unless $entry; + +# my $pu = $entry->poster; +# my $ju = $entry->journal; +# my $url = $entry->url; +# $url .= "?format=light"; + +# my $who = "$pu->{user}"; +# if ($pu->{userid} != $ju->{userid}) { +# $who .= " in " . "$ju->{user}"; +# } + +# $ret .= "$who: " . "" . ($entry->subject_text || "(no subject)") . "
    "; + } + + return $ret; +} +_code?> + + + diff --git a/local/htdocs/mobile/index.bml b/local/htdocs/mobile/index.bml new file mode 100644 index 0000000..88ca998 --- /dev/null +++ b/local/htdocs/mobile/index.bml @@ -0,0 +1,42 @@ + + +<?_code return $LJ::SITENAMESHORT; _code?> Mobile + + + +

    Mobile

    +

    " . $u->display_name . "!\n" : ""; + + $ret .= "

    Welcome to the mobile version of $LJ::SITENAMESHORT.

    " + unless $u; + + $ret .= "

    Options:

      "; + + unless ($u) { + $ret .= <Log in -- required +OPTS + + } + + + if ($u) { + $ret .= "
    • Log in -- you're currently logged in as "; + $ret .= $u->display_name . "
    • "; + $ret .= '
    • Post to LiveJournal
    • ' + unless $u->{'journaltype'} eq 'I'; + $ret .= '
    • Read friends page
    • '; + } + +return $ret; + +} +_code?> +
    + + + diff --git a/local/htdocs/mobile/login.bml b/local/htdocs/mobile/login.bml new file mode 100644 index 0000000..2bfeaf1 --- /dev/null +++ b/local/htdocs/mobile/login.bml @@ -0,0 +1,70 @@ +("Invalid username"); + + my ($banned, $ok); + $ok = LJ::auth_okay($u, $POST{password}, undef, undef, \$banned); + + if ($banned) { + return $err->("Your IP address is temporarily banned for exceeding the login failure rate."); + } + + unless ($ok) { + return $err->("Bad password"); + } + + my $etime = time() + 60*60*24*60; + my $sess_opts = { + 'exptype' => 'long', + 'ipfixed' => 0, + }; + + $u->make_login_session('long'); + + return BML::redirect("$LJ::SITEROOT/mobile/?t=" . time()); +} +_code?> + + + + + + + +<< Back to LiveJournal Mobile. +

    Login

    + +

    SSL secure login

    +

    Secure using SSL, but may not work on all mobile devices:

    +
    +Username:
    +Password: + +
    + +

    Insecure basic login

    +

    This sends your password unprotected, probably over the air. Not a good idea on Wifi. Probably okay over a mobile carrier's data network.

    + +
    +Username:
    +Password: + +
    + + + diff --git a/local/htdocs/mobile/post.bml b/local/htdocs/mobile/post.bml new file mode 100644 index 0000000..a7ac6c5 --- /dev/null +++ b/local/htdocs/mobile/post.bml @@ -0,0 +1,105 @@ +1 +_info?>("You must log in before posting."); + + $res = LJ::Protocol::do_request("login", { + "ver" => $LJ::PROTOCOL_VER, + "username" => $u->{'user'}, + "getpickws" => 1, + }, undef, { + "noauth" => 1, + "u" => $u, + }); + + return "" unless LJ::did_post(); + return "$ML{'Error'} $ML{'error.invalidform'}" unless LJ::check_form_auth(); + + my $event = LJ::Util::blogger_deserialize($POST{'event'}); + my $journal = $POST{'usejournal'}; + + my $sec = $POST{'security'}; + my $allowmask = undef; + if ($sec eq "friends") { + $sec = "usemask"; + $allowmask = 1; + } + + my $req = { + 'usejournal' => $journal ne $u->{user} ? $journal : undef, + 'ver' => 1, + 'username' => $u->{'user'}, + 'password' => $u->{'password'}, + 'event' => $event->{'event'}, + 'subject' => $POST{'subject'}, + 'props' => $event->{'props'}, + 'tz' => 'guess', + 'security' => $sec, + 'allowmask' => $allowmask, + }; + + my $errcode; + my $res = LJ::Protocol::do_request("postevent", $req, \$errcode); + if ($errcode) { + return $err->("Error posting: " . LJ::Protocol::error_message($errcode)); + } + + my $url = $res->{url}; + + BML::finish(); + my $ret = ""; + $ret .= "<< Back to LiveJournal Mobile.

    Success!

    "; + $ret .= "Posted. Available here."; + return $ret; +} +_code?> + + + + + + + +<< Back to LiveJournal Mobile. +

    Post

    + +
    + +Subject:
    +
    +Post:
    +
    + + Security: 'security', + 'selected' => "public" }, @secs); +} _code?>
    + +
    +
    + to 'usejournal', }, + "", $u->{'user'}, + map { $_, $_ } @{$res->{'usejournals'} || []}); + +}_code?> +
    + +
    + + + diff --git a/local/htdocs/modify.bml b/local/htdocs/modify.bml new file mode 100755 index 0000000..12a7265 --- /dev/null +++ b/local/htdocs/modify.bml @@ -0,0 +1,493 @@ + +head<= + + +<=head +body<= + +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + return $LJ::MSG_READONLY_USER if LJ::get_cap($remote, "readonly"); + + ### user is now authenticated ### + + my $dbr = LJ::get_db_reader(); + my $sth; + + my $capstyles = LJ::get_cap($u, "styles"); + + LJ::load_user_props($u, "opt_usesharedpic", + "s1_lastn_style", "s1_calendar_style", + "s1_day_style", "s1_friends_style", + "stylesys", "journaldomain"); + + # if a POST, update their info + if (LJ::did_post()) { + + return "" unless LJ::text_in(\%POST); + + # database error reporting + my $dberr = sub { + return "@_[0] p?>"; + }; + + my $dbh = LJ::get_db_writer(); + + # setup what we're gonna update in the user table: + my %update = (); + + # what userprops we'll be setting. + my %uprop; + + # journal domains + my $dom_cap = LJ::get_cap($u, 'userdomain'); + if ((exists $POST{'journaldomain'} && $u->{'journaldomain'} ne $POST{'journaldomain'}) || + (! $dom_cap && $POST{'journaldomain_del'})) + { + $POST{'journaldomain'} =~ s!^(http://)?(www\.)?!!; + my $dom = lc($POST{'journaldomain'}); + if (($dom_cap && ! $dom) || (! $dom_cap && $POST{'journaldomain_del'})) { + $dbh->do("DELETE FROM domains WHERE userid=?", undef, $u->{'userid'}); + } else { + $dbh->do("INSERT INTO domains VALUES (?, ?)", undef, $dom, $u->{'userid'}); + if ($dbh->err) { + my $otherid = $dbh->selectrow_array("SELECT userid FROM domains WHERE domain=?", + undef, $dom); + return LJ::bad_input($ML{'.error.dupdomainalias'}) if $otherid != $u->{'userid'}; + } + if ($u->{'journaldomain'}) { + $dbh->do("DELETE FROM domains WHERE userid=? AND domain <> ?", + undef, $u->{'userid'}, $dom); + } + } + + # set journaldomain prop if it's been changed + $uprop{'journaldomain'} = $dom + unless $POST{'journaldomain'} eq $u->{'journaldomain'}; + } + + # validate moodthemeid + # mood theme, make sure they're allowed to use it + my $moodthemeid = $POST{'moodthemeid'}+0; + if ($moodthemeid) { + my ($mownerid, $mpublic) = $dbr->selectrow_array("SELECT ownerid, is_public FROM moodthemes ". + "WHERE moodthemeid=?", undef, $moodthemeid); + $moodthemeid = 0 unless $mpublic eq 'Y' || $mownerid == $u->{'userid'}; + } + $update{'moodthemeid'} = $moodthemeid; + $update{'opt_forcemoodtheme'} = $POST{'opt_forcemoodtheme'} ? "Y" : "N"; + + + # all of these options should only be processed for S1 users + if ($u->{'stylesys'} != 2) { + + # color themes + $update{'themeid'} = $POST{'themetype'} eq "custom" ? 0 : $POST{'themeid'}; + + if ($POST{'themetype'} eq "custom") { + my $dig = Digest::MD5::md5_hex(join(",", map { $POST{"theme_cust:$_"} } + map { $_->[0] } @LJ::S1::themecoltypes)); + if ($dig ne $POST{'themecolors_dig'}) { + my %cols; + foreach my $col (@LJ::S1::themecoltypes) { + my $val = $POST{"theme_cust:$col->[0]"}; + next if length($val) > 20; + next unless ($val =~ /^\#[a-f0-9]{6,6}$/i || + $val !~ /[^\s\w]/); + $cols{$col->[0]} = $val; + } + + return $ML{"error.nodb"} unless $u->writer; + $u->do("INSERT IGNORE INTO s1usercache (userid) VALUES (?)", undef, $u->{'userid'}); + $u->do("UPDATE s1usercache SET color_stor=? WHERE userid=?", undef, + Storable::nfreeze(\%cols), $u->{'userid'}); + LJ::MemCache::delete([$u->{'userid'}, "s1uc:$u->{'userid'}"]); + + $dbh->do("DELETE FROM themecustom WHERE user=?", undef, $u->{'user'}) + if $dbh->selectrow_array("SELECT user FROM themecustom ". + "WHERE user=? LIMIT 1", undef, $u->{'user'}); + } + } + + # update 'overrides' table + if ($POST{'overrides'} !~ /\S/) { + LJ::S1::clear_overrides($u); + $update{'useoverrides'} = "N"; + + } else { + + my $oldoverrides = ""; + if ($u->{'useoverrides'} eq "Y") { + $oldoverrides = LJ::S1::get_overrides($u); + } + + # This allows users to keep their current illegal overrides, + # but they may not create new ones nor edit the ones they already have. + # They may only delete or keep illegal overrides. + my %overrides = (); + my %newoverrides = (); + LJ::parse_vars(\$oldoverrides,\%overrides); + LJ::parse_vars(\$POST{'overrides'},\%newoverrides); + + # head overrides should only have valid head elements in them + foreach my $a (qw(GLOBAL LASTN FRIENDS CALENDAR DAY)) { + my $sec = "${a}_HEAD"; + next unless $newoverrides{$sec} ne $overrides{$sec}; + + my $testtag = sub { + my $tag = lc(shift); + return "<$tag" if ($tag eq "title" || $tag eq "base" || + $tag eq "style" || $tag eq "link" || + $tag eq "meta" || $tag eq "xx"); + return "($1)/eig; + $newoverrides{$sec} =~ s/\<\/head/\<\/xx-head/ig; + } + + # load all the properties to see which ones are overridable + my @vars; + LJ::load_objects_from_file("vars.dat", \@vars); + foreach my $v (@vars) { + my $ov = $v->{'props'}->{'override'}; + if ($ov eq "yes" || $ov eq "only" || $capstyles) { + my $name = $v->{'name'}; + if (defined $newoverrides{$name}) { + $overrides{$name} = $newoverrides{$name}; + } + } + } + + # make the new override code we'll put in the database + my $overr=''; + foreach (keys %overrides) { + if ($newoverrides{$_}) { + if ($overrides{$_} =~ /\n/) { + $overr .= "$_<=\n".$overrides{$_}."\n<=$_\n\n"; + } else { + $overr .= "$_=>".$overrides{$_}."\n\n"; + } + } + } + + # no value, delete overrides + if ($overr !~ /\S/) { + LJ::S1::clear_overrides($u); + $update{'useoverrides'} = "N"; + + # have a value, update overrides + } else { + LJ::S1::save_overrides($u, $overr); + $update{'useoverrides'} = "Y"; + } + } + + # friends view shared pic option for s1 + $uprop{'opt_usesharedpic'} = $POST{'opt_usesharedpic'} ? "1" : "0"; + + # set all the styles + { + my @picked = (); + foreach my $view (@LJ::views) { + my $sid = $POST{"s1_${view}_style"}+0; + if ($sid) { + $uprop{"s1_${view}_style"} = $sid; + push @picked, $sid; + } + } + + # verify they haven't forged the style numbers + unless ($capstyles) { + + # just load whole structure since it should be cached + my $pubstyles = LJ::S1::get_public_styles(); + my $userstyles = LJ::S1::get_user_styles($u); + + foreach (@picked) { + my $type = $userstyles->{$_}->{'type'}; + return LJ::bad_input($ML{'.error.stylenotavailable'}) + unless exists $pubstyles->{$_} || + exists $userstyles->{$_} && + ($capstyles || $_ == $u->{"s1_${type}_style"}); + } + } + } + } + + + # update 'user' table + foreach (keys %update) { + delete $update{$_} if $u->{$_} eq $update{$_}; + } + LJ::update_user($u, \%update) if %update; + + # change any of the userprops ? + foreach my $uprop (keys %uprop) { + next if $POST{$uprop} eq $u->{$uprop}; + LJ::set_userprop($u, $uprop, $uprop{$uprop}); + } + + # tell the user all is well + return " LJ::journal_base($u) . "/" })." p?>"; + } + + # not submitting a post, show edit form + my $ret; + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + ### journal style + $ret .= "\n\n\n"; + + ### + ### LAYOUT OPTIONS + ### + + $ret .= "
    \n"; + + # using S1, need to take style input + if ($u->{'stylesys'} != 2) + { + my $and = $capstyles ? "" : $ML{'.pagelayoutstyle.warning'}; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + my $pubstyles = LJ::S1::get_public_styles(); + my %pubstyles = (); + foreach (sort { $a->{'styledes'} cmp $b->{'styledes'} } values %$pubstyles) { + push @{$pubstyles{$_->{'type'}}}, $_; + } + + my $userstyles = LJ::S1::get_user_styles($u); + my %userstyles = (); + foreach (sort { $a->{'styledes'} cmp $b->{'styledes'} } values %$userstyles) { + push @{$userstyles{$_->{'type'}}}, $_; + } + + foreach my $view (@LJ::views) { + + $ret .= "\n"; + } + $ret .= "
    $ML{'.availablestyles.head'}
    $LJ::viewinfo{$view}->{'des'}"; + + my @list = map { $_->{'styleid'}, $_->{'styledes'} } + @{$pubstyles{$view} || []}; + + if (@{$userstyles{$view} || []}) { + + my @user_list = map { $_->{'styleid'}, $_->{'styledes'} } + grep { $capstyles || $u->{"s1_${view}_style"} == $_->{'styleid'} } + @{$userstyles{$view} || []}; + push @list, { value => "", + text => "--- $ML{'.availablestyles.userstyles'} ---", + disabled => 1 }, @user_list + if @user_list; + + my @disabled_list = + map { { value => $_->{'styleid'}, + text => $_->{'styledes'}, + disabled => 1 } } + grep { ! $capstyles && $u->{"s1_${view}_style"} != $_->{'styleid'} } + @{$userstyles{$view} || []}; + push @list, { value => '', + text => "--- $ML{'.availablestyles.disabledstyles'} ---", + disabled => 1 }, @disabled_list + if @disabled_list; + } + + $ret .= LJ::html_select({ 'name' => "s1_${view}_style", + 'selected' => $u->{"s1_${view}_style"} }, @list); + + $ret .= "
    \n\n"; + + ### + ### COLOR THEME OPTIONS + ### + + $ret .= "\n"; + $ret .= "
    \n"; + + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'themetype', + 'value' => 'default', 'selected' => $u->{'themeid'} > 0 }); + $ret .= "$ML{'.colortheme.defaulttheme'}: "; + + my @list; + $sth = $dbr->prepare("SELECT themeid, name FROM themelist ORDER BY name"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + push @list, ($_->{'themeid'}, $_->{'name'}); + } + $ret .= LJ::html_select({ 'name' => 'themeid', 'selected' => $u->{'themeid'} }, @list) . "
    \n"; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'themetype', 'id' => 'themetype:custom', + 'value' => 'custom', 'selected' => $u->{'themeid'} == 0 }) . "\n"; + $ret .= "$ML{'.colortheme.customcolors'}:"; + + $ret .= "\n"; + $ret .= "\n"; + + # get the user's custom colors + my %custcolors = (); + + if ($u->{'themeid'} == 0) { + my $dbcr = LJ::get_cluster_reader($u); + my $stor = $dbcr->selectrow_array("SELECT color_stor FROM s1usercache WHERE userid=?", + undef, $u->{'userid'}); + if ($stor) { + %custcolors = %{ Storable::thaw($stor) }; + } else { + # ancient table. + $sth = $dbr->prepare("SELECT coltype, color FROM themecustom WHERE user=?"); + $sth->execute($u->{'user'}); + $custcolors{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref; + } + } else { + $sth = $dbr->prepare("SELECT coltype, color FROM themedata WHERE themeid=?"); + $sth->execute($u->{'themeid'}); + $custcolors{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref; + } + + my $dig; + foreach my $col (@LJ::S1::themecoltypes) { + $ret .= "\n"; + $dig .= $col->[0]; + } + $dig = Digest::MD5::md5_hex($dig); + $ret .= LJ::html_hidden("themecolors_dig", $dig) unless $u->{'themeid'}; + + $ret .= "
    $ML{'.colortheme.area.head'}$ML{'.colortheme.color.head1'}
    $ML{'.colortheme.color.head2'}
    $col->[1]"; + $ret .= LJ::html_text({ 'name' => "theme_cust:$col->[0]", 'size' => '20', + 'maxlength' => '30', 'value' => $custcolors{$col->[0]}, + 'onchange' => "checkRadioButton('themetype:custom');" }); + $ret .= "
    \n\n"; + + ### + ### FRIENDS VIEW OPTIONS + ### + + $ret .= ""; + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_usesharedpic', 'selected' => $u->{'opt_usesharedpic'} }); + $ret .= "$ML{'.friends.opt.usesharedpic.head'}
     $ML{'.friends.opt.usesharedpic.about'}
    \n\n"; + + ### + ### STYLE OVERRIDES + ### + + # first, load the overrides if they use 'em: + my $overrides = ""; + if ($u->{'useoverrides'} eq "Y") { + $overrides = LJ::S1::get_overrides($u); + LJ::text_out(\$overrides); + } + + $ret .= "
    \n"; + $ret .= "\n"; + $ret .= "$ML{'.overrides.warning'} p?>\n"; + $ret .= "\n"; + $ret .= "$ML{'.overrides.box.head'}
    "; + $ret .= LJ::html_textarea({ 'name' => 'overrides', 'cols' => '60', 'rows' => '15', + 'wrap' => 'off', 'value' => $overrides }) . " standout?>"; + $ret .= "
    \n\n"; + } + + ### + ### MOOD THEME OPTIONS + ### + + $ret .= "\n"; + + $sth = $dbr->prepare("SELECT moodthemeid, name FROM moodthemes WHERE is_public='Y'"); + $sth->execute; + my @themes = ({ 'moodthemeid' => 0, 'name' => '(None)' }); + push @themes, $_ while ($_ = $sth->fetchrow_hashref); + + ### user's private themes + { + my @theme_user; + $sth = $dbr->prepare("SELECT moodthemeid, name FROM moodthemes WHERE ownerid=? AND is_public='N'"); + $sth->execute($u->{'userid'}); + push @theme_user, $_ while ($_ = $sth->fetchrow_hashref); + if (@theme_user) { + push @themes, { 'moodthemeid' => 0, 'name' => "--- $ML{'.moodicons.personal'} ---" }; + push @themes, @theme_user; + } + } + + $ret .= "
    $ML{'.moodicons.select'} \n"; + $ret .= LJ::html_select({ 'name' => 'moodthemeid', 'selected' => $u->{'moodthemeid'} }, + map { $_->{'moodthemeid'}, $_->{'name'} } @themes) . "\n"; + + $ret .= "($ML{'.moodicons.preview'})\n"; + $ret .= "
    " . LJ::html_check({ 'type' => 'check', 'name' => 'opt_forcemoodtheme', + 'id' => 'opt_forcemoodtheme', + 'selected' => $u->{'opt_forcemoodtheme'} eq 'Y' }) . "\n"; + $ret .= "
    \n\n"; + + ### + ### JOURNAL DOMAIN OPTIONS + ### + + my $has_cap = LJ::get_cap($u, 'userdomain'); + my $has_dom = $u->{journaldomain} ? 1 : 0; + if ($LJ::OTHER_VHOSTS && ($has_cap || $has_dom)) { + $ret .= "\n"; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    $ML{'.domainalias.domainname'}"; + $ret .= LJ::html_text({ 'name' => 'journaldomain', 'size' => '30', + 'maxlength' => '80', 'value' => $u->{'journaldomain'}, + 'disabled' => ! $has_cap }); + $ret .= LJ::html_submit('journaldomain_del' => "Remove") unless $has_cap; + $ret .= "
     $ML{'.domainalias.example'}
    "; + $ret .= " $LJ::SITENAME})." p?>
    \n\n"; + } + + ### ending submit block + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + + return $ret; + +} +_code?> + +<=body +page?> +link: htdocs/moodlist.bml, htdocs/developer/index.bml, htdocs/developer/varlist.bml, htdocs/styles/create.bml +post: htdocs/modify_do.bml + _c?> diff --git a/local/htdocs/moodlist.bml b/local/htdocs/moodlist.bml new file mode 100755 index 0000000..65baa44 --- /dev/null +++ b/local/htdocs/moodlist.bml @@ -0,0 +1,269 @@ +LJ.Rossia.org Moods +head<= + +<=head +body<= +. You can always enter your own, but these are the ones that can have pictures associated with them and can be searched on, etc. You're encouraged to use these if possible. p?>modify journal page and select your preferred icon set. p?>"; + }; + + # Get a list of all possible moods + my $moods = LJ::get_moods(); + my @mlist = (); + my %lists = {}; + foreach (sort { $moods->{$a}->{'name'} cmp $moods->{$b}->{'name'} } keys %$moods) { + my $m = $moods->{$_}; + push @mlist, $m; + } + + # FIXME: cache this. it's small. + $sth = $dbr->prepare("SELECT moodthemeid, name, is_public FROM moodthemes WHERE is_public='Y'"); + $sth->execute; + my @themes = (); + push @themes, $_ while $_ = $sth->fetchrow_hashref; + @themes = sort { lc($a->{name}) cmp lc($b->{name}) } @themes; + + my @user_themes; + # Determine the action depending on the GET arguments, or lack thereof + if (defined $GET{'moodtheme'}) { + $ret .= BML::ml('Backlink', { + 'link'=>'/moodlist.bml', + 'text'=>'Mood Themes', + }). "
    "; + + $add_header->(); + + my $remote = LJ::get_remote(); + + # Check if the user is logged in and didn't specify an owner. If so append their private mood themes + my $sth; + if ($remote && ! $GET{'ownerid'}) { + # FIXME: cache this. it's small. + $sth = $dbr->prepare("SELECT moodthemeid, name, is_public FROM moodthemes WHERE ownerid=?"); + $sth->execute($remote->{userid}); + @user_themes = (); + push @user_themes, $_ while $_ = $sth->fetchrow_hashref; + } elsif ($GET{'ownerid'}) { + # FIXME: cache this. it's small. + $sth = $dbr->prepare("SELECT moodthemeid, name, is_public FROM moodthemes WHERE ownerid=? AND moodthemeid=?"); + $sth->execute($GET{'ownerid'}, $GET{'moodtheme'}); + @user_themes = (); + push @user_themes, $_ while $_ = $sth->fetchrow_hashref; + } + + # Sort the user themes + @user_themes = sort { lc($a->{name}) cmp lc($b->{name}) } @user_themes; + + # See if the user can even view this theme + my $theme = (grep { $_->{moodthemeid} == $GET{moodtheme} } (@themes, @user_themes))[0]; + if (! $theme) { + # It isn't theirs, or they aren't logged in, and it isn't public and it actually exists + return LJ::bad_input("You only have permission to view public mood themes or user themes with an ownerid parameter."); + } elsif ( defined $GET{mode} && $GET{mode} == 'tree') { + + if ($GET{'ownerid'}) { + $ret .= "
    "; + $ret .= LJ::ehtml(@user_themes[0]->{name}) . ' - '; + $ret .= LJ::ljuser(LJ::get_username($GET{'ownerid'})); + $ret .= "
    "; + } else { + my @opts = ((map {$_->{moodthemeid}, $_->{name}} @themes), + (@user_themes ? (0, "---") : ()), + (map {$_->{moodthemeid}, $_->{name}} @user_themes)); + $ret .= "
    "; + $ret .= LJ::html_select({'name' => "moodtheme", 'selected' => "$GET{moodtheme}"}, + @opts); + $ret .= " "; + $ret .= LJ::html_hidden('mode' => 'tree'); + $ret .= "
    "; + $ret .= "View this theme in a table layout.
    "; + } + $ret .= "
      \n"; + + foreach (sort { $moods->{$a}->{'name'} cmp $moods->{$b}->{'name'} } keys %$moods) { + my $m = $moods->{$_}; + push @{$lists{$m->{'parent'}}}, $m; + } + + do_mood_tree(0); + } else { + do_theme_detail($GET{'moodtheme'}); + } + + } else { + $add_header->(); + do_mood_list(); + } + return $ret; + + sub do_mood_list + { + # Setup the paging bar + my $perpage = 15; + my $start; + my $self_link; + my %items = BML::paging(\@themes, $GET{'page'} || 1, $perpage); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}, { 'self_link' => $self_link }); + + if ($items{'page'} == 1) { + $start = 0; + } else { + $start = ($items{'page'} - 1) * $perpage; + } + my @show_themes = splice (@themes, $start, $perpage); + + # See if the user changed the shown moods + my @show_moods; + if($GET{'theme1'} && $GET{'theme2'} &&$ GET{'theme3'} && $GET{'theme4'}) { + @show_moods = ($GET{'theme1'}, $GET{'theme2'}, $GET{'theme3'}, $GET{'theme4'}); + } else { + @show_moods = ('happy', 'sad', 'angry', 'tired'); + } + + $ret .= "
      \n"; + $ret .= LJ::html_hidden("page", $items{page}); + $ret .= ""; + + # Create the table columns for each mood + my $mname; + my $n = 1; + foreach $mname (@show_moods) { + $ret .= "\n"; + $n++; + } + + $ret .= "\n"; + + # Output a table row for each mood theme + foreach my $theme (@show_themes) { + $ret .= "\n"; + + LJ::load_mood_theme($theme->{'moodthemeid'}); + + # Output each of the displayed moods + foreach my $mood (@show_moods) { + if (LJ::get_mood_picture($theme->{'moodthemeid'}, LJ::mood_id($mood), \ my %pic)) { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + + $ret .= ""; + } + $ret .= "
      " . + LJ::html_select({'name' => "theme$n", 'selected' => "$mname", + 'style' => "text-align: center"}, + map {$_->{name}, $_->{name}} @mlist) . "
      $theme->{'name'}$theme->{name}" . + ""; + $ret .= BML::ml('Actionlink', { + 'link' => "View All" + }); + $ret .= "

      $navbar
      "; + } + + sub do_theme_detail + { + my ($themeid) = @_; + + $ret .= "
      "; + } else { + my @opts = ((map {$_->{moodthemeid}, $_->{name}} @themes), + (@user_themes ? (0, "---") : ()), + (map {$_->{moodthemeid}, $_->{name}} @user_themes)); + + $ret .= "
      "; + $ret .= LJ::html_select({'name' => "moodtheme", 'selected' => "$themeid"}, + @opts); + $ret .= " "; + $ret .= "View this theme in a hierarchal tree layout.
      "; + } + + # Output all the moods + while (@mlist) { + $ret .= ""; + + # Show five moods in a row + for (my $i = 0; $i < 5; $i++) { + my $m = shift @mlist; + my $mood = $m->{name}; + my %pic; + if (LJ::get_mood_picture($themeid, $m->{id}, \%pic)) { + $ret .= ""; + } else { + $ret .= ""; + } + } + $ret .= ""; + } + $ret .= "
      "; + + if ($GET{'ownerid'}) { + $ret .= "
      "; + $ret .= LJ::ehtml(@user_themes[0]->{name}) . ' - '; + $ret .= LJ::ljuser(LJ::get_username($GET{'ownerid'})); + $ret .= "
      " . + "$m->{name}" . + "
      $mood
      " . + "$mood" . + "
      "; + } + + sub do_mood_tree + { + my $num = shift; + return unless $lists{$num}; + $ret .= "
        \n"; + foreach my $mood (@{$lists{$num}}) { + $ret .= "
      • {'name'}\" target='dict'>$mood->{'name'} (#$mood->{'id'})
      • \n"; + my %pic; + if (LJ::get_mood_picture($GET{moodtheme}, $mood->{'id'}, \%pic)) { + unless ($GET{'hidederived'} && $pic{'moodid'} != $mood->{'id'}) { + $ret .= "\n"; + } + if ($GET{'details'} && ($pic{'moodid'} != $mood->{'id'})) { + $ret .= " (from parent)"; + } + } else { + if ($GET{'details'}) { + $ret .= "(no pic for theme \#$GET{moodtheme})"; + } + } + do_mood_tree($mood->{'id'}); + } + $ret .= "
      \n"; + } + +} +_code?> + +<=body +page?> +form: htdocs/moodlist.bml +link: htdocs/modify.bml + _c?> diff --git a/local/htdocs/news.bml b/local/htdocs/news.bml new file mode 100755 index 0000000..205741d --- /dev/null +++ b/local/htdocs/news.bml @@ -0,0 +1,23 @@ +News +BODY<= + +We're open. That's enough news for now. Stay tuned. + + + +_c?> + +<=BODY +page?> diff --git a/local/htdocs/openid/approve.bml b/local/htdocs/openid/approve.bml new file mode 100755 index 0000000..8f6b0e6 --- /dev/null +++ b/local/htdocs/openid/approve.bml @@ -0,0 +1,83 @@ +("Currently you need to be logged in to grant another site permission to know your identity, but this page will eventually let you log in during the same step."); + + my $identity = LJ::OpenID::is_identity($u, $GET{'identity'}, \%GET); + unless ($identity) { + return $err->("The site you just came from seems to want to verify an identity that you, as " . + LJ::ljuser($u) . + ", cannot provide."); + } + + my $site = $GET{'trust_root'}; + $site =~ s/\?.*//; + return $err->("Invalid site address") unless $site =~ m!^https?://!; + + # TODO: check URL and see if it contains images or external scripts/css/images, where + # an attacker could sniff the validation tokens in the Referer header? + + if (LJ::did_post()) { + return $err->("Possible form tampering detected.") unless LJ::check_form_auth(); + my $dur; + $body = ""; + + $dur = "always" if $POST{'yes:always'}; + $dur = "once" if $POST{'yes:once'}; + + LJ::OpenID::add_trust($u, $site, $dur) + or return $err->("Failed to save"); + + $title = "Saved"; + $body .= "Permission has been granted. You can now close this window and login to the site you were previously visiting."; + if ($GET{"openid.post_grant"} eq "close") { + $body .= ""; + } elsif ($GET{"openid.post_grant"} eq "return") { + my $nos = LJ::OpenID::server(); + my $sig_return = $nos->signed_return_url( + identity => $GET{'identity'}, + return_to => $GET{'return_to'}, + trust_root => $GET{'trust_root'}, + assoc_handle => $GET{'assoc_handle'}, + ); + return BML::redirect($sig_return) if $sig_return; + return $err->("Failed to make signed return URL."); + } + return; + } + + + $title = "Grant identity validation?"; + $body = ""; + $body .= ""; + $body .= "
      "; + $body .= LJ::form_auth(); + my $dis_site = LJ::ehtml($site); + $dis_site =~ s!\*\.!<anything>.!; + + $body .= "
      $dis_site
      "; + $body .= ""; + $body .= "
      "; + $body .= ""; + $body .= "
      "; + return; + +} +_code?> +body=> +page?> diff --git a/local/htdocs/openid/login.bml b/local/htdocs/openid/login.bml new file mode 100755 index 0000000..434912c --- /dev/null +++ b/local/htdocs/openid/login.bml @@ -0,0 +1,89 @@ +OpenID, you must first log out. p?>"; + return; + } + + if ($GET{'openid.mode'}) { + my $csr = LJ::OpenID::consumer(\%GET); + if (my $setup = $csr->user_setup_url) { + return BML::redirect($setup); + } + + my $vident = eval { $csr->verified_identity; }; + return $err->($csr->err) unless $vident; + + my $url = $vident->url; + return $err->("Invalid characters in identity URL.") if $url =~ /[\<\>\s]/; + + my $u = LJ::User::load_identity_user("O", $url, $vident); + return $err->("Couldn't vivify your account (but we verified that you're " . LJ::ehtml($url) . ")") unless $u; + + my $sess_opts = { + 'exptype' => 'short', + 'ipfixed' => 0, + }; + my $etime = 0; + if ($POST{'expire'} eq "never") { + $etime = time()+60*60*24*60; + $sess_opts->{'exptype'} = "long"; + } + + $u->make_login_session($sess_opts->{'exptype'}, $sess_opts->{'ipfixed'}); + LJ::set_remote($u); + + return BML::redirect("$LJ::SITEROOT/login.bml"); + } + + + if (LJ::did_post()) { + my $csr = LJ::OpenID::consumer(); + my $url = $POST{'openid_url'}; + return $err->("Invalid characters in identity URL.") if $url =~ /[\<\>\s]/; + + my $tried_local_ref = LJ::OpenID::blocked_hosts($csr); + + my $claimed_id = $csr->claimed_identity($url); + + unless ($claimed_id) { + return $err->("You can't use a LiveJournal OpenID account on LiveJournal — ". + "just go login with your actual LJ.Rossia.org account.") if $tried_local_ref; + return $err->($csr->err); + } + + my $check_url = $claimed_id->check_url( + return_to => "$LJ::SITEROOT/openid/login.bml", + trust_root => "$LJ::SITEROOT/", + delayed_return => 1, + ); + return BML::redirect($check_url); + } + +return undef; + +} + _code?>1 +_info?> +body=> +page?> diff --git a/local/htdocs/openid/options.bml b/local/htdocs/openid/options.bml new file mode 100755 index 0000000..f6edf8b --- /dev/null +++ b/local/htdocs/openid/options.bml @@ -0,0 +1,96 @@ +("OpenID server support is disabled") + unless LJ::OpenID::server_enabled(); + + my $u = LJ::get_remote() or + return $err->("You need to be logged in to manage your OpenID options."); + + my $dbh = LJ::get_db_writer(); + my $trusted = {}; + my @external; + + my $load_trusted = sub { + $trusted = $dbh->selectall_hashref("SELECT ye.endpoint_id as 'endid', ye.url FROM openid_endpoint ye, openid_trust yt WHERE yt.endpoint_id=ye.endpoint_id AND yt.userid=$u->{userid}", 'endid'); + }; + + my $load_external = sub { + @external = @{ $dbh->selectcol_arrayref("SELECT url FROM openid_external WHERE userid=?", undef, $u->{userid}) }; + }; + + if (LJ::did_post()) { + return $err->("Possible form tampering detected.") unless LJ::check_form_auth(); + my $dur; + $body = ""; + + $load_trusted->(); + foreach my $endid (sort { $trusted->{$a} cmp $trusted->{$b} } keys %$trusted) { + next unless $POST{"delete:$endid"}; + $dbh->do("DELETE FROM openid_trust WHERE userid=? AND endpoint_id=?", undef, $u->{userid}, $endid); + } + + $load_external->(); + foreach my $url (@external) { + next unless $POST{"extdelete:$url"}; + $dbh->do("DELETE FROM openid_external WHERE userid=? AND url=?", undef, $u->{userid}, $url); + } + + if ($POST{'ext_url'} =~ m!^http://!) { + $dbh->do("REPLACE INTO openid_external (userid, url) VALUES (?,?)", undef, $u->{userid}, $POST{'ext_url'}); + } + + } + + $load_trusted->(); + $load_external->(); + + $title = "OpenID Options"; + $body = ""; + $body .= "
      "; + $body .= LJ::form_auth(); + $body .= ""; + $body .= "
      "; + if (%$trusted) { + foreach my $endid (sort { $trusted->{$a} cmp $trusted->{$b} } keys %$trusted) { + my $url = $trusted->{$endid}->{url}; + my $dis_site = LJ::ehtml($url); + $dis_site =~ s!\*\.!<anything>.!; + $body .= LJ::html_submit("delete:$endid", "Delete") . " -- $dis_site
      "; + } + } else { + $body .= "(None)"; + } + $body .= "
      "; + + + $body .= ""; + + $body .= "<link rel=\"openid.server\" href=\"$LJ::OPENID_SERVER?ljuser=$u->{user}\" />"; + + $body .= "
      "; + if (@external) { + foreach my $url (@external) { + $body .= LJ::html_submit("extdelete:$url", "Delete") . " -- " . LJ::ehtml($url) . "
      "; + } + } else { + $body .= "(None)"; + } + $body .= "
      "; + $body .= "Add: " . LJ::html_text({ name => 'ext_url', size => 60 }) . " "; + $body .= "
      "; + return; + +} +_code?> +body=> +page?> diff --git a/local/htdocs/paidaccounts/index.bml b/local/htdocs/paidaccounts/index.bml new file mode 100644 index 0000000..7545a64 --- /dev/null +++ b/local/htdocs/paidaccounts/index.bml @@ -0,0 +1,78 @@ + +Donations +HEAD<= +<=HEAD +BODYOPTS<= +<=BODYOPTS +BODY<= + + +Платных аккаунтов у Ð½Ð°Ñ Ð¿Ð¾ÐºÐ° нет. Извините. +

      + +ЕÑли хотите, вы можете Ñделать пожертвование на развитие и поддержку +Ñервера. Ð”Ð»Ñ Ñтого можно воÑпользоватьÑÑ Ð¿Ð»Ð°Ñ‚Ñ‘Ð¶Ð½Ñ‹Ð¼Ð¸ ÑиÑтемами PayPal +или ЯндекÑ.деньги. +

      +

      Пожертвование Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемы ЯндекÑ.деньги

      +

      +Ðомер Ñчёта, на который можно переводить пожертвованиÑ: 4100197259538 +

      +

      +ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ аккаунт в ÑиÑтеме ЯндекÑ.деньги, вы можете проÑто +перевеÑти деньги Ñо Ñчёта на Ñчёт. Ð’ Ñлучае, еÑли вы пользуетеÑÑŒ +веб-интерфейÑом ("ЯндекÑ.кошелёк"), вам необходимо Ñделать Ñледующее. +

      +
        +
      • ÐвторизуйтеÑÑŒ на Ñайте + yandex.ru.
      • +
      • Перейдите на Ñтраницу https://money.yandex.ru. +
      • Кликните по ÑÑылке "ПеревеÑти" (в верхней чаÑти Ñтраницы, Ñ€Ñдом Ñ + изображением конверта).
      • +
      • Выберите вариант "перевод на Ñчёт", отметив ÑоответÑтвующую галочку +(радиокнопку).
      • +
      • Ð’ поле "Ðомер Ñчёта получателÑ" введите 4100197259538
      • +
      • Ð’ поле "Сумма" введите Ñумму перевода.
      • +
      • Ðажмите кнопку "ПеревеÑти".
      • +
      • Ðа поÑвившейÑÑ Ñтранице введите Ñвой платёжный пароль в поле "Введите +ваш платёжный пароль:".
      • +
      • Ðажмите кнопку "Платить".
      • +
      +

      +Пользователи программы "Интернет.кошелёк" могут переводить деньги Ñ +помощью Ñтой программы (как Ñто Ñделать, опиÑано здеÑÑŒ). +

      +

      ЕÑли у Ð²Ð°Ñ Ð½ÐµÑ‚ аккаунта в ÑиÑтеме ЯндекÑ.деньги, вы можете + воÑпользоватьÑÑ Ð±Ð°Ð½ÐºÐ¾Ð²Ñким + переводом, почтовым + переводом, пополнить Ñчёт Ð´Ð»Ñ Ð¿Ð¾Ð¶ÐµÑ€Ñ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ð¹ + через платёжные + терминалы + или банкоматы, Ñ + помощью ÑиÑтемы интернет-банкинга, а также из других платёжных + ÑиÑтем Ñ + помощью Центра + Интернет-платежей (принимаютÑÑ WebMoney, E-gold, Internet.Money + и MoneyMail). + +

      Пожертвование через PayPal

      + +Пожертвовать на LJR можно тут: + +
      + + + + +
      +

      +СпаÑибо! +

      +Привет + +<=BODY +page?> diff --git a/local/htdocs/palimg/boxer/back.gif b/local/htdocs/palimg/boxer/back.gif new file mode 100755 index 0000000000000000000000000000000000000000..5ee70c855bbd9c5334298c7e8003476add6112e6 GIT binary patch literal 87 zcmZ?wbhEHblwpuzn8?HsSy2A}|9=KBQ2fcl$iTqFpabH84wq|M1_SmCfPvwc;@>ucY7pZ_}d-JOxa8UQr79)AD; literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/boxer/clear.gif b/local/htdocs/palimg/boxer/clear.gif new file mode 100755 index 0000000000000000000000000000000000000000..5bfd67a2d6f72ac3a55cbfcea5866e841d22f5d9 GIT binary patch literal 43 mcmZ?wbhEHbWMp7uXkdT>#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/boxer/forward.gif b/local/htdocs/palimg/boxer/forward.gif new file mode 100755 index 0000000000000000000000000000000000000000..776c4bfbc730d1e89e2c09e9ef33813a8c116d8b GIT binary patch literal 85 zcmZ?wbhEHblwpuzn8?HsSy2A}|9=KBQ2fcl$iTqFpabH8Vwl;fK7G}ijy1Y9=eF=Z|8>romBAVSW`iAL literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/bg.gif b/local/htdocs/palimg/component/bg.gif new file mode 100755 index 0000000000000000000000000000000000000000..c170c8e59cf9bd23b72f77ddb8e832dcd5f70916 GIT binary patch literal 86 zcmZ?wbhEHblw^=#XkcWxfB*jf|Nj+#vM@3*Ff!;c00Bsbfl0Tef2G7*{>RZ8{72P>2}}&u0MTe3hyVZp literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/btn_edit.gif b/local/htdocs/palimg/component/btn_edit.gif new file mode 100755 index 0000000000000000000000000000000000000000..88d96ba92e842fcacb15e955ca9d01c2646fd2f3 GIT binary patch literal 219 zcmV<103`oMNk%w1VHN-s0J9GOsL=99X^i;Mno57QDpZKIrHmIxe1cziSCPnas@-dx z)CewPgoK0uF=PM#{{R30A^8LW000jFEC2ui02Tlg000Dt@Ucm&wesoBJ9iV;jE&cU z%+?$SF`65ytw-PhO9{)*YCC~|LFeH$2m%}e0C1U%jV58qbe=*p10gXOFq=dTFRS2s ztKl)({Ix#R>uw@}$ceF?hM_zNFbWJha4LHU3<8LPcpiF&hysc!Fg*>2i6w)1BqVQ( VlQS|Og8vp>!NJvFRMan8FeSLkhEiHtE zgl1-DW&i-000960{{R30A^8LW000jFEC2ui02Tlg000D!@Tp0wwesoBJ9m>OdZ5Aq zz=A%g3Vfjk7>*+tbA7*BDbtR?p+Kkw5)H$~#|i`lgF(S5Xbc(*9&;gpMh6LG14~%+ zVvEBeI&O~{<+F*^zPiZ-ZEVJ1-0?Va8+?9ka0G#Zg9d$X1c*F}i+zWQOED(~kB}so cnVg+-9w?C=Oe3fzHLI+xt|k|;u@4adJ2NU&ZvX%Q literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/btn_tags.gif b/local/htdocs/palimg/component/btn_tags.gif new file mode 100755 index 0000000000000000000000000000000000000000..b0ae78d5ebc5b3597d2506e918a79a3b6048c813 GIT binary patch literal 223 zcmZ?wbhEHb6k`x!c+AJJ;=(8Q%$^??XL;3c)e7m@y0k~!y{0L?B7EYBqE&aZ=Um~? zOKxdtVK7Yo4+e_=M4gLL6H8K46v{J8G895GQWe}ieFGR2f3h$#Fz_?zFaQC_a0Zs* z4;wvKZ~gT0tabTh^(qD9D&Ngh)vwF6|Jv~OGK1fmi_dK}Hbt&r|H0b2EYMkjp)8|$ zMahK(4ylXh3m&|9#IVxMeE035^L?L70{q-A$6A={x@O(WFrAxQ|KO=ba!qY^Yf7%E XvQ1|cPhtOriLq+pQ>XF^GFSruU#?!C literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/btn_tellfriend.gif b/local/htdocs/palimg/component/btn_tellfriend.gif new file mode 100755 index 0000000000000000000000000000000000000000..c584764fa7d637110bbb4047a3816bf2bbb720a5 GIT binary patch literal 181 zcmZ?wbhEHb6k`x!*v!W8pMhcO)TzmnF1EC^FfcIu{|^+v2NZv@FfuT(G3bC4fy`iF zNxIPExq9oR7iX=-C#zRIFqjwBIq#KLlYh>Ul3aT?X&cw~|Lx{ciq2m<O}wRr IO_0GF0ClB8Q2+n{ literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/clear.gif b/local/htdocs/palimg/component/clear.gif new file mode 100755 index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66 GIT binary patch literal 43 scmZ?wbhEHbWMp7uXkcLY|NlP&1B2pE7Dgb&paUX6G7L;iE{qJ;0LZEa`2YX_ literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/curve-bottom-left.gif b/local/htdocs/palimg/component/curve-bottom-left.gif new file mode 100755 index 0000000000000000000000000000000000000000..55875126dc358388a97e01d61afb5e20e2b5a0a7 GIT binary patch literal 56 zcmZ?wbhEHbWMyDwn8?iV|Nnmm28Nk4X95|DKUo+V7?>G!fFeLyRt5$pPM((JO!KUJ I+^h`N0Mbtml>h($ literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/curve-bottom-right.gif b/local/htdocs/palimg/component/curve-bottom-right.gif new file mode 100755 index 0000000000000000000000000000000000000000..5a2d30837c6764e1485899c392669980343b8f0c GIT binary patch literal 57 zcmZ?wbhEHbWMyDwn8?iV|Nnmm28Nk4X95|DKUo+V7?>G!fFeLyRt5$pt|@}z$_>re KCM1h6SOWm#%MWS* literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/curve-top-left.gif b/local/htdocs/palimg/component/curve-top-left.gif new file mode 100755 index 0000000000000000000000000000000000000000..5ab117d62a56295733a529feaf8b8534184c8236 GIT binary patch literal 58 zcmZ?wbhEHbWMyDwn8?iV|Nnmm28Nk4X95|DKUo+V7?>G!fFeLyRt5$p?m6OOj2sGc K1ai8V7_0&4ehxwa literal 0 HcmV?d00001 diff --git a/local/htdocs/palimg/component/curve-top-right.gif b/local/htdocs/palimg/component/curve-top-right.gif new file mode 100755 index 0000000000000000000000000000000000000000..c5163ddfea19064e3962b1092420c81b29a3873f GIT binary patch literal 57 zcmZ?wbhEHbWMyDwn8?iV|Nnmm28Nk4X95|DKUo+V7?>G!fFeLyRt5$pt}}K5W=yx{ K2!@C>+ARU_w@7g`~3U<{{HCb z==JsW`T6 z0HUrdgD|ig&#+ Privacy + +

      Your privacy

      + +We +pledge to protect your privacy, except the +cases when the law of Russian Federation or your own country +requires us otherwise. Please read our policy documents: +[ 1 | 2 | 3 ] \ No newline at end of file diff --git a/local/htdocs/robots.txt b/local/htdocs/robots.txt new file mode 100755 index 0000000..d44c619 --- /dev/null +++ b/local/htdocs/robots.txt @@ -0,0 +1,28 @@ +User-agent: * +Disallow: /directory +Disallow: /interests +Disallow: /tools/tell +Disallow: /tools/memadd +Disallow: /tools/search.bml +Disallow: /friends/ +Disallow: /interface/ +Disallow: /translate/ +Disallow: /comments/ +Disallow: /numreplies/ +Disallow: /users/imp_ +Disallow: /userinfo.bml?user=imp_ +Disallow: /talk +Disallow: /stats/stats.txt +Disallow: /create +# +Crawl-delay: 1 + +Host: lj.rossia.org + +# +# Blocked journals aren't listed here because robots.txt files +# can't be above 50k or so, depending on the spider. +# +# Instead, blocked journals have HTML inserted in them which +# should prevent behaved spiders from indexing it. +# diff --git a/local/htdocs/robotsdisable.txt b/local/htdocs/robotsdisable.txt new file mode 100755 index 0000000..6ffbc30 --- /dev/null +++ b/local/htdocs/robotsdisable.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: / + diff --git a/local/htdocs/site/index.html b/local/htdocs/site/index.html new file mode 100755 index 0000000..cb8edc3 --- /dev/null +++ b/local/htdocs/site/index.html @@ -0,0 +1,174 @@ + Sitemap + +

      LJ.Rossia.Org sitemap

      + +
      Created 07.09.2005
      + +
      This sitemap might be obsolete
      + + + + + + + + + + + + + + + + + + + + + + + + +
      Local features
      +
      guidelines.html
      +
      tos.html
      +
      ustav.html
      +
      lj-gate/index.bml
      +
      lj-gate/lj-gate-faq.html
      +
      lj-gate/rlj_delete.bml
      +
      Stats and directory
      +
      stats.bml
      +
      stats/index.bml
      +
      directory.bml
      +
      directorysearch.bml
      +
      community/search.bml
      + +
      tools/sixdegrees.bml
      +
      interests.bml
      +
      interests.bml?view=popular
      +
      friends/popwithfriends.bml +
      moodlist.bml
      + + +
      Basic functions
      +
      create.bml
      +
      login.bml
      +
      logout.bml
      +
      changepassword.bml
      +
      lostinfo.bml
      +
      update.bml
      +
      User info
      +
      userinfo.bml
      +
      tools/recent_comments.bml
      +
      tools/memories.bml
      +
      allpics.bml
      +
      export.bml
      +
      export_comments.bml
      +
      manage/tags.bml
      Edit +user options
      +
      editinfo.bml
      +
      editjournal.bml
      +
      editpics.bml
      +
      manage/siteopts.bml
      +
      tools/emailmanage.bml
      + +
      utf8convert.bml
      +
      manage/tags.bml
      +
      manage/index.bml
      +
      manage/invites.bml
      +
      manage/moodthemes.bml
      +
      community/create.bml
      +
      community/manage.bml
      + +
      Friends
      +
      friends/index.bml
      +
      friends/add.bml
      +
      friends/edit.bml
      +
      friends/editgroups.bml
      +
      friends/filter.bml
      +
      birthdays.bml
      + + +
      +Style management
      +
      modify.bml
      + +
      manage/links.bml
      +
      styles/create.bml
      +
      styles/edit.bml
      +
      styles/index.bml
      + +
      customize/index.bml
      +
      customize/preview.bml
      +
      customize/themes.bml
      +
      customize/viewuser.bml
      +
      customize/advanced/index.bml
      +
      customize/advanced/layerbrowse.bml
      +
      customize/advanced/layers.bml
      +
      customize/advanced/layersource.bml
      +
      customize/advanced/styles.bml
      +
      +Support
      +
      support/
      +
      support/faq.bml
      +
      lj-gate/lj-gate-faq.html
      +
      community/ljr_bugs
      +
      community/ljr_features
      +
      community/ljr_todo
      +
      community/ljr_help
      +
      community/ljr_zhaloby
      +
      community/ljr_sankcii
      +
      community/ljr_popechiteli
      +
      +Miscellaneous
      +
      openid/index.bml
      +
      openid/login.bml
      +
      openid/options.bml
      +
      poll/create.bml
      +
      portal/index.bml
      +
      portal/moz.bml
      +
      syn/index.bml
      +
      syn/list.bml
      +
      Admin features
      +
      admin/console/index.bml
      +
      admin/console/reference.bml
      +
      admin/faq/faqedit.bml
      +
      admin/faq/index.bml
      +
      admin/faq/readcat.bml
      +
      admin/fileedit/index.bml
      +
      admin/priv/index.bml
      + +
      admin/topics/index.bml
      +
      admin/topics/start.bml
      +
      translate/edit.bml
      +
      translate/help-severity.bml
      +
      translate/index.bml
      +
      translate/teams.bml
      admin/schema/index.bml
      +
      +Broken features (should be fixed)
      +
      tools/search.bml
      +
      edittags.bml
      +
      meme.bml
      +
      multisearch.bml
      +
      stats/latest-rss.bml
      styles/browse/index.html
      +
      news.bml
      +
      random.bml
      +
      friends/graph.bml
      +
      paidaccounts/index.html
      + +
      tools/tellafriend.bml
      + +
      tools/textmessage.bml
      + +
      + + + + + + + LJ.Rossia.Org \ No newline at end of file diff --git a/local/htdocs/site/sitemap.html b/local/htdocs/site/sitemap.html new file mode 100755 index 0000000..447ee1b --- /dev/null +++ b/local/htdocs/site/sitemap.html @@ -0,0 +1,177 @@ + Sitemap + +

      LJ.Rossia.Org sitemap

      + +
      Created 07.09.2005
      + +
      This sitemap might be obsolete
      + + + + + + + + + + + + + + + + + + + + + + + + + +
      Local features
      +
      guidelines.html
      +
      tos.html
      +
      ustav.html
      +
      lj-gate/index.bml
      +
      lj-gate/lj-gate-faq.html
      +
      import.bml
      +
      import-enqueue.bml
      +
      import-faq.bml
      +
      import-queue.bml
      Stats and directory
      +
      stats.bml
      +
      stats/index.bml
      +
      directory.bml
      +
      directorysearch.bml
      +
      community/search.bml
      + +
      tools/sixdegrees.bml
      +
      interests.bml
      +
      interests.bml?view=popular
      +
      friends/popwithfriends.bml +
      moodlist.bml
      + + +
      Basic functions
      +
      create.bml
      +
      login.bml
      +
      logout.bml
      +
      changepassword.bml
      +
      lostinfo.bml
      +
      update.bml
      +
      User info
      +
      userinfo.bml
      +
      tools/recent_comments.bml
      +
      tools/memories.bml
      +
      allpics.bml
      +
      export.bml
      +
      export_comments.bml
      +
      manage/tags.bml
      Edit +user options
      +
      editinfo.bml
      +
      editjournal.bml
      +
      editpics.bml
      +
      manage/siteopts.bml
      +
      tools/emailmanage.bml
      + +
      utf8convert.bml
      +
      manage/tags.bml
      +
      manage/index.bml
      +
      manage/invites.bml
      +
      manage/moodthemes.bml
      +
      community/create.bml
      +
      community/manage.bml
      + +
      Friends
      +
      friends/index.bml
      +
      friends/add.bml
      +
      friends/edit.bml
      +
      friends/editgroups.bml
      +
      friends/filter.bml
      +
      birthdays.bml
      + + +
      +Style management
      +
      modify.bml
      + +
      manage/links.bml
      +
      styles/create.bml
      +
      styles/edit.bml
      +
      styles/index.bml
      + +
      customize/index.bml
      +
      customize/preview.bml
      +
      customize/themes.bml
      +
      customize/viewuser.bml
      +
      customize/advanced/index.bml
      +
      customize/advanced/layerbrowse.bml
      +
      customize/advanced/layers.bml
      +
      customize/advanced/layersource.bml
      +
      customize/advanced/styles.bml
      +
      +Support
      +
      support/
      +
      support/faq.bml
      +
      lj-gate/lj-gate-faq.html
      +
      community/ljr_bugs
      +
      community/ljr_features
      +
      community/ljr_todo
      +
      community/ljr_help
      +
      community/ljr_zhaloby
      +
      community/ljr_sankcii
      +
      community/ljr_popechiteli
      +
      +Miscellaneous
      +
      openid/index.bml
      +
      openid/login.bml
      +
      openid/options.bml
      +
      poll/create.bml
      +
      portal/index.bml
      +
      portal/moz.bml
      +
      syn/index.bml
      +
      syn/list.bml
      +
      Admin features
      +
      admin/console/index.bml
      +
      admin/console/reference.bml
      +
      admin/faq/faqedit.bml
      +
      admin/faq/index.bml
      +
      admin/faq/readcat.bml
      +
      admin/fileedit/index.bml
      +
      admin/priv/index.bml
      + +
      admin/topics/index.bml
      +
      admin/topics/start.bml
      +
      translate/edit.bml
      +
      translate/help-severity.bml
      +
      translate/index.bml
      +
      translate/teams.bml
      admin/schema/index.bml
      +
      +Broken features (should be fixed)
      +
      tools/search.bml
      +
      edittags.bml
      +
      meme.bml
      +
      multisearch.bml
      +
      stats/latest-rss.bml
      styles/browse/index.html
      +
      news.bml
      +
      random.bml
      +
      friends/graph.bml
      +
      paidaccounts/
      + +
      tools/tellafriend.bml
      + +
      tools/textmessage.bml
      + +
      + + + + + + + LJ.Rossia.Org diff --git a/local/htdocs/stats.bml b/local/htdocs/stats.bml new file mode 100755 index 0000000..71938e5 --- /dev/null +++ b/local/htdocs/stats.bml @@ -0,0 +1,296 @@ +Statistics +body<= + + Statistics h1?> +here. +p?> + + +prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('userinfo', 'client', 'age', 'gender', 'account', 'size')"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'}; + } + + unless (%stat) { + return "ljmaint.pl genstats, or ideally, put it in cron to run nightly. p?>"; + } + + $sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='country' AND s.statcat='country' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{'country'}->{$_->{'item'}} = $_->{'statval'}; + } + + $sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='state' AND s.statcat='stateus' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{'state'}->{$_->{'item'}} = $_->{'statval'}; + } + + my $total = $stat{'userinfo'}->{'total'}+0; + my $usedever = $stat{'userinfo'}->{'updated'}+0; + my $used30 = $stat{'userinfo'}->{'updated_last30'}+0; + my $used7 = $stat{'userinfo'}->{'updated_last7'}+0; + my $usedlastday = $stat{'userinfo'}->{'updated_last1'}+0; + my $allow_getljnews = $stat{'userinfo'}->{'allow_getljnews'}+0; + my $active = $stat{'size'}->{'accounts_active'}+0; + + my $ret = ""; + $ret .= "\n"; + $ret .= "
        "; + $ret .= "
      • Total accounts: $total
      • \n"; + $ret .= "
      • ... active in some way: $active
      • \n" if $active; + $ret .= "
      • ... that have ever updated: $usedever
      • \n"; + $ret .= "
      • ... updating in last 30 days: $used30
      • \n"; + $ret .= "
      • ... updating in last 7 days: $used7
      • \n"; + $ret .= "
      • ... updating in past 24 hours: $usedlastday
      • \n"; + $ret .= "
      \n"; + + $ret .= "\n"; + $ret .= "
        "; + { + my $male = $stat{'gender'}->{'M'}+0; + my $female = $stat{'gender'}->{'F'}+0; + my $tot = $male+$female; + $tot ||= 1; + $ret .= "
      • Male: $male (" . sprintf("%0.1f", $male*100/($tot||1)) . "%)
      • "; + $ret .= "
      • Female: $female (" . sprintf("%0.1f", $female*100/($tot||1)) . "%)
      • "; + } + $ret .= "
      • Unspecified: " . ($stat{'gender'}->{'U'}+0) . "
      • "; + $ret .= "
      \n"; + + LJ::run_hook('statspage', { + stat => \%stat, + ret => \$ret, + }); + + unless ($LJ::DISABLED{'stats-recentupdates'}) + { + $ret .= "\n"; + $ret .= "\n
        \n"; + $sth = $dbr->prepare("SELECT u.user, u.name, uu.timeupdate, u.statusvis FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 2 DAY) AND uu.timecreate < DATE_SUB(NOW(), INTERVAL 5 DAY) ORDER BY uu.timeupdate DESC LIMIT 50"); + $sth->execute; + my $ct; + while (my ($iuser, $iname, $itime, $status) = $sth->fetchrow_array) { + my $tmp = ", $itime"; + $tmp = "$tmp" if $status =~ /[DXS]/; + $tmp = "
      • $tmp
      • \n"; + $ret .= $tmp; + $ct++; + } + $ret .= "
      • stat not available
      • " unless $ct; + $ret .= "
      \n"; + } + + unless ($LJ::DISABLED{'stats-newjournals'}) + { + $ret .= "\n"; + $ret .= "\n
        \n"; + $ret .= "\n"; # L.P. + $sth = $dbr->prepare("SELECT u.userid, u.user, u.name, uu.timecreate, u.statusvis FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 5 DAY) AND uu.timecreate > DATE_SUB(NOW(), INTERVAL 5 DAY) ORDER BY uu.timecreate DESC"); + $sth->execute; + my $ct; + while (my ($iuserid, $iuser, $iname, $itime, $status) = $sth->fetchrow_array) { + my $tmp = ", $itime"; + $tmp = "$tmp" if $status =~ /[DXS]/; +# determine the number of posted comments + my $com_post; + my $mysth = $dbr->prepare("SELECT COUNT(*) FROM talkleft " . + "WHERE userid=?"); + $mysth->execute($iuserid); + ($com_post)=$mysth->fetchrow_array; +# number of posted comments is found + if ($com_post >0) { $tmp= "$tmp; $com_post comments posted.";} + $tmp = "
      • $tmp
      • \n"; + $ret .= $tmp; + $ct++; + } + $ret .= "
      • stat not available
      • " unless $ct; + $ret .= "
        \n
      \n"; + } + + unless ($LJ::DISABLED{'stats-newjournals'}) + { + $ret .= "\n"; + $ret .= "\n
        \n"; + $ret .= "\n"; # L.P. + $sth = $dbr->prepare("SELECT u.userid, u.user, u.name, uu.timecreate, u.statusvis FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate IS NULL AND uu.timecreate > DATE_SUB(NOW(), INTERVAL 20 DAY) ORDER BY uu.timecreate DESC"); + $sth->execute; + my $ct; + while (my ($iuserid, $iuser, $iname, $itime, $status) = $sth->fetchrow_array) { + if ($iuser !~ /^(imp|ext)_.*/) { +# determine the number of posted comments + my $com_post; + my $mysth = $dbr->prepare("SELECT COUNT(*) FROM talkleft " . + "WHERE userid=?"); + $mysth->execute($iuserid); + ($com_post)=$mysth->fetchrow_array; +# number of posted comments is found + my $tmp = ", $itime"; + $tmp = "$tmp" if $status =~ /[DXS]/; + if ($com_post >0) { $tmp= "$tmp; $com_post comments posted.";} + $tmp = "
      • $tmp
      • \n"; + $ret .= $tmp; + $ct++; + } + } + $ret .= "
      • stat not available
      • " unless $ct; + $ret .= "
        \n
      \n"; + } + + unless ($LJ::DISABLED{'stats-newjournals'}) + { + $ret .= "\n"; + $ret .= "\n
        \n"; + $ret .= "\n"; # L.P. + $sth = $dbr->prepare("SELECT u.userid, u.user, u.name, uu.timecreate, u.statusvis FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate IS NULL AND uu.timecreate > DATE_SUB(NOW(), INTERVAL 20 DAY) ORDER BY uu.timecreate DESC"); + $sth->execute; + my $ct; + while (my ($iuserid, $iuser, $iname, $itime, $status) = $sth->fetchrow_array) { + if ($iuser =~ /^(ext)_.*/) { +## determine the number of posted comments + my $com_post; + my $mysth = $dbr->prepare("SELECT COUNT(*) FROM talkleft " . + "WHERE userid=?"); + $mysth->execute($iuserid); + ($com_post)=$mysth->fetchrow_array; +## number of posted comments is found + my $tmp = ", $itime"; + $tmp = "$tmp" if $status =~ /[DXS]/; + if ($com_post >0) { $tmp= "$tmp; $com_post comments posted.";} + $tmp = "
      • $tmp
      • \n"; + $ret .= $tmp; + $ct++; + } + } + $ret .= "
      • stat not available
      • " unless $ct; + $ret .= "
        \n
      \n"; + } + + $ret .= "\n"; + { + $ret .= "
        \n"; + my $ct; + foreach my $key (sort { $stat{'country'}->{$b} <=> $stat{'country'}->{$a} } + keys %{$stat{'country'}}) + { + $ret .= "
      • $key - $stat{'country'}->{$key}
      • \n"; + $ct++; + } + $ret .= "
      • stat not available
      • " unless $ct; + $ret .= "
      \n"; + } + +# Removed by popular request - M.V. +# { +# $ret .= "The following are the 15 most popular U.S. states $LJ::SITENAMESHORT is used in:
        "; +# my $ct; +# foreach my $key (sort { $stat{'state'}->{$b} <=> $stat{'state'}->{$a} } keys %{$stat{'state'}}) +# { +# $ret .= "
      • $key - $stat{'state'}->{$key}
      • \n"; +# $ct++; +# } +# $ret .= "
      • stat not available
      • " unless $ct; +# $ret .= "
      \n"; +# } + + # ages + my %age = (); + my $maxage = 1; + foreach my $key (keys %{$stat{'age'}}) { + $age{$key} = $stat{'age'}->{$key}; + if ($stat{'age'}->{$key} > $maxage) { $maxage = $stat{'age'}->{$key}; } + } + my @ages = grep { $_ >= 13 && $_ <= 55 } sort { $a <=> $b } sort keys %age; + if (@ages) { + $ret .= "\n"; + $ret .= "\n"; + my $lastage = 0; + foreach my $age (@ages) { + my $width = int(400 * $age{$age}/$maxage); + $ret .= "\n"; + $lastage = $_; + } + $ret .= "
      $age$age{$age}
      \n"; + } + +# Clients listing is broken - sorry (MV, 07, 09, 2005) + # clients (if enabled) +# unless ($LJ::DISABLED{'clientversionlog'}) { + ### sum up clients over different versions +# foreach my $c (keys %{$stat{'client'}}) { +# next unless ($c =~ /^(.+?)\//); +# $stat{'clientname'}->{$1} += $stat{'client'}->{$c}; +# } +# +# my $out; +# foreach my $cn (sort { $stat{'clientname'}->{$b} <=> $stat{'clientname'}->{$a} } +# keys %{$stat{'clientname'}}) +# { +# last unless $stat{'clientname'}->{$cn} >= 50; +# $out .= "$stat{'clientname'}->{$cn}". +# "" . LJ::ehtml($cn) . "
      \n"; +# $out .= "\n"; +# foreach my $c (sort grep { /^\Q$cn\E\// } keys %{$stat{'client'}}) { +# my $count = $stat{'client'}->{$c}; +# $c =~ s/^\Q$cn\E\///; +# $out .= LJ::ehtml($c) . " ($count), "; +# } +# chop $ret; chop $ret; # remove trailing ", " +# $out .= "\n"; +# $out .= "\n"; +# } +# +# if ($out) { +# $ret .= "\n"; +# $ret .= "\n"; +# $ret .= $out; +# $ret .= "
      \n"; +# } +# } + + + # return early, since the graphs below are pretty much broken now + # with index changes. FIXME: make alternate means to generate stats + + $ret .= ""; + $ret .= "

      "; + + return $ret; + + ### graphs! + $ret .= ""; + + $ret .= ""; + $ret .= "

      "; + + $ret .= ""; + $ret .= "

      "; + + + + return $ret; + +_code?> + +<=body +page?> +link: htdocs/stats/, htdocs/support/faqbrowse.bml +img: htdocs/img/bluedot.gif, htdocs/stats/postsbyday.png, htdocs/stats/postsbyweek.png, htdocs/stats/newbyday.png + _c?> diff --git a/local/htdocs/stats/.htaccess b/local/htdocs/stats/.htaccess new file mode 100644 index 0000000..a736b42 --- /dev/null +++ b/local/htdocs/stats/.htaccess @@ -0,0 +1,3 @@ +ExpiresActive on +ExpiresByType image/png "modification plus 24 hours" +ExpiresByType text/plain "modification plus 24 hours" diff --git a/local/htdocs/stats/latest-img.bml b/local/htdocs/stats/latest-img.bml new file mode 100755 index 0000000..3262839 --- /dev/null +++ b/local/htdocs/stats/latest-img.bml @@ -0,0 +1,39 @@ +\n"; + $ret .= <<"EOT"; + +EOT + +$ret .= "\n"; + + my $rimg = LJ::MemCache::get("blob:ljcom_latestimg"); +unless (ref $rimg eq "ARRAY" && @$rimg) { + $ret .= "\n"; + $ret .= "\n"; + return $ret; +} + +$ret .= "\n"; + +foreach my $ri (reverse @$rimg) { + my ($img, $ju, $jitemid, $anum) = @$ri; + $img = LJ::exml($img); + my $url = LJ::item_link($ju, $jitemid, $anum); + $ret .= "\n"; +} + + +$ret .= "\n"; +$ret .= "\n"; + + return $ret; +} +_code?> \ No newline at end of file diff --git a/local/htdocs/stats/latest-rss.bml b/local/htdocs/stats/latest-rss.bml new file mode 100755 index 0000000..1b67957 --- /dev/null +++ b/local/htdocs/stats/latest-rss.bml @@ -0,0 +1,111 @@ +\n"; + $ret .= <<"EOT"; + +EOT + $ret .= "\n"; + + $ret .= "Latest $LJ::SITENAME Posts$LJ::SITEROOT/stats/latest.bmlLatest public posts at $LJ::SITENAME.\n"; + + # setup for security logging + my %securities = ( + public => 0, + private => 0, + friends => 0, + custom => 0, + ); + + # retrieve posts. + my @postids; + foreach my $p (@$recent) { + $securities{$p->{security}}++; + next unless $p->{security} eq 'public'; + $p->{ditemid} = $p->{itemid}*256 + $p->{anum}; + $p->{urn} = "urn:$LJ::DOMAIN:entry:$p->{journalu}{user}:$p->{ditemid}"; + + push @postids, [ $p->{clusterid}, $p->{journalu}{userid}, $p->{itemid} ]; + } + my $rawposts = LJ::get_posts_raw({memcache_only=>1}, @postids); + + my $rdftoc = "\n"; + my $rdfitems = ""; + + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $uj = $p->{'journalu'}; + my $up = $p->{'journalp'}; + my $id = "$uj->{userid}:$p->{itemid}"; + my $props = $rawposts->{prop}{$id}; + + # we shouldn't expect every post to be in the memcache. + next unless $rawposts->{text}{$id}; + + # skipping unknown8bit users sucks, but we can't load users here. + next if $props->{unknown8bit}; + + $rdftoc .= " \n"; + + my $url = LJ::journal_base($uj) . "/$p->{ditemid}.html"; + my ($subject, $body) = @{$rawposts->{text}{$id}}; + + $rdfitems .= "\n"; + + # first, the required RDF elements. + # we use title to represent all the metadata in one string, + # then dublin core for the data in pieces. + $rdfitems .= "$up->{'user'}"; + $rdfitems .= " (in $uj->{'user'})" if $uj->{userid} != $up->{userid}; + $rdfitems .= ": " . LJ::exml($subject) if $subject; + $rdfitems .= "\n"; + $rdfitems .= "" . LJ::exml($body) . "\n"; + $rdfitems .= "$_\n" foreach map { LJ::exml($_) } @{$p->{tags} || []}; + $rdfitems .= "$url\n"; + + # use dc for the rest. + $rdfitems .= "" . LJ::exml($subject) . "\n" if $subject; + $rdfitems .= "" . LJ::exml($up->{name}) . " ($up->{user})\n"; + $rdfitems .= "" . LJ::exml($uj->{user}) . "\n" + if $uj->{userid} != $up->{userid}; + $rdfitems .= "" . LJ::time_to_w3c($p->{timepost}) . "Z\n"; + + # and lj for the lj-specific data. + my $mood = $props->{current_mood}; + $mood ||= LJ::mood_name($props->{current_moodid}) if $props->{current_moodid}; + + my $moodid = " id='$props->{current_moodid}'" if $props->{current_moodid}; + $rdfitems .= "" . LJ::exml($mood) . "\n" + if $mood or $moodid; + $rdfitems .= "" . LJ::exml($props->{current_music}) . "\n" + if $props->{current_music}; + $rdfitems .= "" . LJ::exml($props->{picture_keyword}) . "\n" + if $props->{picture_keyword}; + + $rdfitems .= "\n"; + } + $rdftoc .= "\n"; + + $ret .= $rdftoc . $rdfitems; + $ret .= "\n"; + + $ret .= <<"EOT"; + +EOT + return BML::noparse($ret); +} +_code?> \ No newline at end of file diff --git a/local/htdocs/stats/latest.bml b/local/htdocs/stats/latest.bml new file mode 100755 index 0000000..60db193 --- /dev/null +++ b/local/htdocs/stats/latest.bml @@ -0,0 +1,90 @@ +Latest Posts +head<= + +<=head +body<= +[1] - $stat->[2]) { + + my $rate_sec = $stat->[0] / $delta; + + my $rate_min = $rate_sec * 60; + my $fmt_min = $rate_min > 10 ? "%.0f" : "%.2f"; + + my $rate_hour = $rate_min * 60; + my $fmt_hour = $rate_hour > 10 ? "%.0f" : "%.2f"; + + my $post_min = sprintf($fmt_min, $rate_min); + my $post_hour = sprintf($fmt_hour, $rate_hour); + + $ret .= "Current posting stats: $post_hour per hour, $post_min per minute\n"; + } + + my @postids; + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + $p->{ditemid} = $p->{itemid}*256 + $p->{anum}; + push @postids, [ $p->{clusterid}, $p->{journalu}{userid}, $p->{itemid} ]; + } + my $rawposts = LJ::get_posts_raw({memcache_only=>1}, @postids); + + $ret .= "RSS version"; + $ret .= "\n"; + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $uj = $p->{'journalu'}; + my $up = $p->{'journalp'}; + my $id = "$uj->{userid}:$p->{itemid}"; + + # we shouldn't expect every post to be in the memcache. + next unless $rawposts->{text}{$id}; + + # this sucks, but we can't load users here. + next if $rawposts->{prop}{$id}{unknown8bit}; + + my $url = LJ::journal_base($uj) . "/$p->{'ditemid'}.html"; + my ($subject, $body) = @{$rawposts->{text}{$id}}; + + $ret .= ""; + $ret .= "\n"; + + } + $ret .= "
      " . substr(scalar(gmtime($p->{timepost})), 4, 12) . "\n"; + + $ret .= LJ::ljuser($up->{user}); + if ($up->{userid} != $uj->{userid}) { + $ret .= " (in " . LJ::ljuser($uj->{user}, {type => $uj->{journaltype}}) . ")"; + } + $ret .= ":
      \n"; + + $ret .= "
      "; + LJ::CleanHTML::clean_subject(\$subject); + LJ::CleanHTML::clean_event(\$body, {'cuturl' => LJ::item_link($uj, $p->{'itemid'}, $p->{'anum'})}); + $ret .= "$subject
      \n" if $subject; + $ret .= $body; + $ret .= "
      \n"; + + BML::noparse(); + return $ret; +} +_code?> + +<=body +page?> \ No newline at end of file diff --git a/local/htdocs/stats/weblog-updates-xml.bml b/local/htdocs/stats/weblog-updates-xml.bml new file mode 100755 index 0000000..9bd4a51 --- /dev/null +++ b/local/htdocs/stats/weblog-updates-xml.bml @@ -0,0 +1,34 @@ +\n"; + $ret .= <<"EOT"; + +EOT + + $ret .= "\n"; + + # retrieve posts. + my @postids; + my %done; # journalid -> 1 + foreach my $p (@$recent) { + next unless $p->{security} eq 'public'; + my $u = $p->{journalu} or next; + next if $done{$u->{userid}}++; + my $base = LJ::journal_base($u); + $ret .= "\n"; + } + + $ret .= "\n"; + + return BML::noparse($ret); +} +_code?> \ No newline at end of file diff --git a/local/htdocs/styles/create.bml b/local/htdocs/styles/create.bml new file mode 100755 index 0000000..fe979ab --- /dev/null +++ b/local/htdocs/styles/create.bml @@ -0,0 +1,21 @@ + Ne rabotaet + +

      Ðе работает

      + +ДрузьÑ, ÑиÑтема Ñтилей S1 уÑтарела и не поддерживает +многих возможноÑтей LJ (например, Ñ‚Ñгов). Поддержка ее +приоÑтанавливаетÑÑ (как нами, так и, ÑÑƒÐ´Ñ Ð¿Ð¾ вÑему, +командой livejournal.com). +

      + +Ðа наÑтоÑщий момент, Ñоздание новых Ñтилей в S1 на LJR +отключено, и мы работаем над их полным уничтожением. +ПользуйтеÑÑŒ, +пожалуйÑта, ÑтилÑми S2. +

      +ПриноÑим Ð¸Ð·Ð²Ð¸Ð½ÐµÐ½Ð¸Ñ Ð·Ð° неудобÑтва. ÐдминиÑтрациÑ. + +

      + +lj.rossia.org + diff --git a/local/htdocs/styles/create_do.bml b/local/htdocs/styles/create_do.bml new file mode 100755 index 0000000..df03b4e --- /dev/null +++ b/local/htdocs/styles/create_do.bml @@ -0,0 +1,101 @@ + +body<= + +" + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.authinvalid'}) + unless $u; + + unless (LJ::get_cap($u, "styles")) { + return LJ::bad_input($ML{'.error.accounttype'}); + } + + # error check submission + return LJ::bad_input($ML{'.error.invalidview'}) + unless $POST{'type'} && defined $LJ::viewinfo{$POST{'type'}}; + + my $view = $POST{'type'}; + my $base = ""; + my $baseid = $POST{"base_$view"} || $POST{"basenum_$view"}; + + if ($baseid) { + my $rec = LJ::S1::get_style($baseid); + + return LJ::bad_input(BML::ml('.error.stylenotfound',{ 'baseid' => $baseid, })) + unless $rec && $rec->{'type'} eq $view; + + return LJ::bad_input(BML::ml('.error.stylenotpublic',{ 'baseid' => $baseid, })) + unless $rec->{'is_public'} eq "Y" || $rec->{'user'} eq $u->{'user'}; + + # they're allowed to base on this style + $base = $rec->{'formatdata'}; + } + + ### start of output + + my $ret = ""; + my $des = "$u->{'user'}-$view-new"; + + # let's see if they accidentally double-clicked: + my $double_clicked = 0; + my $new_id = 0; + my $oldstyle = LJ::S1::check_dup_style($u, $view, $des); + + # closure to show edit form + my $editform = sub { + my $getextra = "?authas=$authas" if $u->{'user'} ne $remote->{'user'}; + return "

      \n" . + LJ::html_hidden('mode', 'editstyle', 'styleid', $_[0]) . "\n" . + LJ::html_submit(undef, $ML{'.editstyle'}) . "
      \n"; + }; + + if ($oldstyle) { + if ($oldstyle->{'formatdata'} eq $base) { + # the user double-clicked + $double_clicked = 1; + $new_id = $oldstyle->{'styleid'}; + + } else { + $ret .= "" . + " $des, 'view' => $view, }) . " p?>"; + + $ret .= $editform->($oldstyle->{'styleid'}); + return $ret; + } + } + + unless ($double_clicked) { + $new_id = LJ::S1::create_style($u, + { 'styledes' => $des, + 'type' => $view, + 'formatdata' => $base }); + return "" + unless defined $new_id; + } + + $ret .= " $des, }) . " p?>\n"; + + $ret .= $editform->($new_id); + + return $ret; +} +_code?> +<=body +page?> +post: htdocs/styles/edit_do.bml + _c?> diff --git a/local/htdocs/support/faq.bml b/local/htdocs/support/faq.bml new file mode 100755 index 0000000..4a73f4a --- /dev/null +++ b/local/htdocs/support/faq.bml @@ -0,0 +1,64 @@ +FAQ +body<= + + +FAQ +LiveJournal (но имейте в виду, что многое там -- в чаÑтноÑти, +вÑе каÑающееÑÑ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтрации -- отноÑитÑÑ Ð¸Ñключительно к +www.livejournal.com, а у Ð½Ð°Ñ ÑƒÑтроено по-другому). +p?> + + +
    • ТакаÑ-то Ð²Ð°Ð¶Ð½Ð°Ñ Ð²ÐµÑ‰ÑŒ еÑÑ‚ÑŒ в livejournal, а здеÑÑŒ она не +работает -- что делать? +

      Ðапишите про Ñто в +отведенное меÑто; еÑли вы проÑто напишете в Ñвоем дневнике, +админиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñтого Ñкорее вÑего не заметит. +

    • + +
    • Работает ли Semagic? +

      Мы не проверÑли, но пользователи Ñообщают нам, что +да. БольшинÑтво других клиентов тоже. Ðо не забудьте найти в Ñвоем +клиенте, где запиÑано Ð¸Ð¼Ñ Ñервера, и впиÑать туда lj.rossia.org.

    • +
    • Что такое гейт в LJ? +

      Идеал, к которому мы ÑтремимÑÑ -- Ñто раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ð°Ñ +ÑиÑтема. Пока что, в качеÑтве временной меры, был напиÑан гейт на +livejournal.com. Работает он так: вводите имÑ/логин здеÑÑŒ и на +LJ, говорите включить. ПоÑле Ñтого вÑе ваши запиÑи здеÑÑŒ +автоматичеÑки дублируютÑÑ Ð² ваш дневник на livevournal.com (Ñ +небольшой задержкой, до 10 минут). Редактировать запиÑи тоже +можно. Линк на комментарии в запиÑи на livejournal.com будет веÑти +Ñюда. +

    • +
    • Что такое OpenID? +

      Это ÑиÑтема, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет надежно раÑпознавать пользователей +на чужих Ñайтах; ее Ñделал БрÑд Фитцпатрик веÑной Ñтого +года. Livejournal.com Ñту ÑиÑтему поддерживает, LJR тоже +поддерживает. Ðужно Ñто прежде вÑего Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы подпиÑывать +комментарии. Когда пишете комментарий на чужом Ñайте -- например, вы +пользователь LJR, а хотите напиÑать комментарий на livejournal.com -- +выбирайте OpenID, вводите в окошке Ð°Ð´Ñ€ÐµÑ Ñвоего дневника, и (еÑли +вы до того уже вошли в Ñвою родную ÑиÑтему), вÑе должно произойти +автоматичеÑки. К Ñожалению, ÑиÑтема новаÑ, и ее +продолжают допиÑывать; поÑтому Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ времени она не работает (как +правило, Ñто значит, что Фитцпатрик что-то изменил, а мы еще не +разобралиÑÑŒ, что нам нужно теперь изменить у ÑебÑ).

    • +p?> + + +

      Обратно на Ñтраницу тех. поддержки.

      + +<=body +page?> +link: htdocs/support/faqbrowse.bml, htdocs/support/index.bml + _c?> diff --git a/local/htdocs/support/index.html b/local/htdocs/support/index.html new file mode 100755 index 0000000..e86e801 --- /dev/null +++ b/local/htdocs/support/index.html @@ -0,0 +1,62 @@ +LJR Support Page + + +

      ôÅÈÎÉÞÅÓËÁÑ ÐÏÄÄÅÒÖËa

      + +

      äÌÑ ÔÅÈÎÉÞÅÓËÏÊ É ÁÄÍÉÎÉÓÔÒÁÔÉ×ÎÏÊ ÐÏÄÄÅÒÖËÉ ÓÅÒ×ÅÒÁ ÓÏÚÄÁÎÙ +ÓÌÅÄÕÀÝÉÅ ÓÏÏÂÝÅÓÔ×Á: +

        +
      • óÏÏÂÝÅÎÉÑ ÏÂ ÏÛÉÂËÁÈ +
        • +ðÏÖÁÌÕÊÓÔÁ, ÓÏÏÂÝÁÊÔÅ ÓÀÄÁ ÞÔÏ ÒÁÂÏÔÁÅÔ ÎÅ ÔÁË, ÞÔÏ ÎÅ ÒÁÂÏÔÁÅÔ ÓÏ×ÓÅÍ, É Ô.Ä. +
        + +
      • Features +
        • +åÓÌÉ ×Ù ÏÂÎÁÒÕÖÉÌÉ, ÞÔÏ ÞÔÏ-ÔÏ ÒÁÂÏÔÁÅÔ -- Á ÜÔÏ ÂÙÌÏ +ÎÅÏÞÅ×ÉÄÎÏ! -- ÔÏ ÎÁÐÉÛÉÔÅ ÓÀÄÁ, ÞÔÏÂÙ ÄÒÕÇÉÅ ÍÏÇÌÉ +ÐÏÌØÚÏ×ÁÔØÓÑ. ìÕÞÛÅ ÐÒÉÌÁÇÁÔØ ÉÎÓÔÒÕËÃÉÉ (ÎÁÐÒÉÍÅÒ: "Semagic +ÒÁÂÏÔÁÅÔ, ÔÕÄÁ-ÔÏ É ÔÕÄÁ-ÔÏ ÎÁÄÏ ×ÐÉÓÁÔØ lj.rossia.org"). +
        + +
      • ôÅÈÎÉÞÅÓËÉÅ ÎÅÄÏÒÁÂÏÔËÉ +
        • +óÀÄÁ ÍÏÖÎÏ ÐÉÓÁÔØ ÐÏÖÅÌÁÎÉÑ: ÞÔÏ ÎÁÄÏ ÄÏÂÁ×ÉÔØ, ÞÔÏ ÌÕÞÛÅ +ÉÚØÑÔØ/ÏÔËÌÀÞÉÔØ, É Ô.Ä. +
        + +
      • ÷ÚÁÉÍÏÐÏÍÏÝØ +
        • +÷ÚÁÉÍÏÐÏÍÏÝØ. úÄÅÓØ ÍÏÖÎÏ ÚÁÄÁÔØ ÔÅÈÎÉÞÅÓËÉÊ ×ÏÐÒÏÓ, +É ËÔÏ-ÎÉÂÕÄØ ÉÚ ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÎÁ ÎÅÇÏ ÏÔ×ÅÔÉÔ. é ÎÁÏÂÏÒÏÔ, ÓÀÄÁ +ÍÏÖÎÏ ÐÒÉÄÔÉ ÐÏÍÏÞØ ÎÏ×ÙÍ ÐÏÌØÚÏ×ÁÔÅÌÑÍ, ÏÔ×ÅÔÉ× ÎÁ ÉÈ ×ÏÐÒÏÓÙ. +
        + +
      • ëÎÉÇÁ ÖÁÌÏ +
        • +úÄÅÓØ ÖÁÌÕÀÔÓÑ ÎÁ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ (× ÞÁÓÔÎÏÓÔÉ, ÖÁÌÕÀÔÓÑ +ðÏÐÅÞÉÔÅÌØÓËÏÍÕ óÏ×ÅÔÕ ÎÁ ÄÅÊÓÔ×ÉÑ ÁÄÍÉÎÉÓÔÒÁÃÉÉ ÓÅÒ×ÅÒÁ). ðÒÅÖÄÅ +ÞÅÍ ÖÁÌÏ×ÁÔØÓÑ, ÐÏÖÁÌÕÊÓÔÁ, ÐÒÏÞÉÔÁÊÔÅ ðÒÁ×ÉÌÁ, É ÉÍÅÊÔÅ × ×ÉÄÕ, ÞÔÏ ×ÓÅ ÏÔËÒÙÔÙÍ +ÔÅËÓÔÏÍ ÎÅ ÚÁÐÒÅÝÅÎÎÏÅ òáúòåûåîï. åÓÌÉ ×ÁÍ ÎÅËÏÍÆÏÒÔÎÏ ÏÔ +ÓÕÝÅÓÔ×Ï×ÁÎÉÑ É/ÉÌÉ ÄÅÑÔÅÌØÎÏÓÔÉ ÐÏÌØÚÏ×ÁÔÅÌÑ XXX, ÐÒÏÓÔÏ ÎÅ ÞÉÔÁÊÔÅ +ÅÇÏ/ÅÅ ÄÎÅ×ÎÉË. +
        + +
      • ðÏÚÏÒÎÙÊ ÓÔÏÌ +
        • +úÄÅÓØ ÐÕÂÌÉËÕÀÔÓÑ ÓÏÏÂÝÅÎÉÑ Ï ÒÅÐÒÅÓÓÉÑÈ. +
        + +
      • ðÏÐÅÞÉÔÅÌØÓËÉÊ ÓÏ×ÅÔ +
        • +úÄÅÓØ ÒÁÂÏÔÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. ðÉÓÁÔØ É ×ÓÔÕÐÁÔØ ÓÀÄÁ ÍÏÇÕÔ ÔÏÌØËÏ +ÞÌÅÎÙ ÜÔÏÇÏ ÓÏ×ÅÔÁ É ÁÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org, ÎÏ ÞÉÔÁÔØ É +ËÏÍÍÅÎÔÉÒÏ×ÁÔØ ÍÏÇÕÔ ×ÓÅ. +
        +
      + +

      ëÒÏÍÅ ÔÏÇÏ, ÅÓÌÉ ×ÁÓ ÚÁÉÎÔÅÒÅÓÏ×ÁÌÉ ×ÏÐÒÏÓÙ ÒÁÚ×ÉÔÉÑ ÓÅÒ×ÉÓÁ É +ÐÒÏÇÒÁÍÍÎÏÇÏ ÏÂÅÓÐÅÞÅÎÉÑ, ÓÈÏÄÉÔÅ ÓÀÄÁ. + diff --git a/local/htdocs/syn/index.bml b/local/htdocs/syn/index.bml new file mode 100755 index 0000000..28b75a3 --- /dev/null +++ b/local/htdocs/syn/index.bml @@ -0,0 +1,355 @@ + +body<= + +"; + } + return "" if $u->{'statusvis'} eq "S"; + + if (LJ::did_post() && $POST{'userid'} != $u->{'userid'}) { + return ""; + } + + my $error = sub { + return " '/syn/', 'text' => $ML{'.back'}}) . " p?>"; + }; + + # add custom feed + if ($POST{'action:addcustom'} || $GET{'url'}) { + + unless (LJ::check_priv($u, 'syn_edit')) { + if ($LJ::LJR_SYNS_PERDAY) { + my $today_syns = $dbh->selectrow_array( + "select count(*) from user,userusage where timecreate > date_sub(now(), interval 24 hour) and " . + "user.userid=userusage.userid and journaltype = 'Y'", + undef); + + if ($today_syns >= $LJ::LJR_SYNS_PERDAY) { + return "

      Too much syndications for today. Sorry."; + } + } + + if ($LJ::LJR_SYNS_PERUSER) { + my $today_syns = $dbh->selectrow_array( + "select count(*) from syndicated,userusage where creatorid = ? and " . + "userusage.userid=syndicated.userid and timecreate > date_sub(now(), interval 24 hour)", + undef, $u->{'userid'}); + + if ($today_syns >= $LJ::LJR_SYNS_PERUSER) { + return "

      Too much syndications for today. Sorry."; + } + } + + if ($LJ::LJR_SYNS_PERWEEK_PERUSER) { + my $thisweek_syns = $dbh->selectrow_array( + "select count(*) from syndicated,userusage where creatorid = ? and " . + "userusage.userid=syndicated.userid and timecreate > date_sub(now(), interval 24*7 hour)", + undef, $u->{'userid'}); + + if ($thisweek_syns >= $LJ::LJR_SYNS_PERWEEK_PERUSER) { + return "

      Too much syndications for this week. Sorry."; + } + } + } + + my $acct = LJ::trim($POST{'acct'}); + my $url = LJ::trim($POST{'synurl'} || $GET{'url'}); + my $pfx = "syn_"; + + if ($acct ne "") { + return $error->($ML{'.invalid.accountname'}) + if $acct && $acct !~ /^\w{3,15}$/; +# foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { +# next unless ($acct =~ /$re/); +# return $error->($ML{'.invalid.reserved'}); +# } + } + if ($url ne "") { + return $error->($ML{'.invalid.url'}) + unless $url =~ m!^http://(.+?)(?::(\d+))?!; + my $hostname = $1; + my $port = $2; + return $error->($ML{'.invalid.cantadd'}) + if $hostname =~ /\Q$LJ::DOMAIN\E/i; + + return $error->($ML{'.invalid.port'}) + if defined $port && $port != 80 && $port < 1024; + $url =~ s/:80// if $port == 80; + } + + my $su; # account to add + if ($url) { + while (1) { + $su = $dbh->selectrow_hashref( + "SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE s.synurl=? AND s.userid=u.userid", + undef, $url); + + unless ($su) { + my $orig_url = $url; + + if ($url =~ /(.*)\/$/) { + $url = $1; + } + else { + $url .= "/"; + } + + $su = $dbh->selectrow_hashref( + "SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE s.synurl=? AND s.userid=u.userid", + undef, $url); + + $url = $orig_url unless $su; + } + + unless ($su) { + # check cap to create new feeds + return $error->($ML{'.error.nocreate'}) + unless LJ::get_cap($u, 'synd_create'); + + # create a safeagent to fetch the feed for validation purposes + require LWPx::ParanoidAgent; + my $ua = LWPx::ParanoidAgent->new(timeout => 30, max_size => (1024 * 500)); + $ua->agent("$LJ::SITENAME ($LJ::ADMIN_EMAIL; Initial check)"); + + my $res = $ua->get($url); + my $content = $res && $res->is_success ? $res->content : undef; + + return "" + unless $content; + + # if we've been redirected -- start from scratch + if ($ua->{'final_url'}) { + $url = $ua->{'final_url'}; + next; + } + + # Start out with the syn_url being equal to the url + # they entered of the resource. If we end up parsing + # the resource and finding it has a link to the real + # feed, we then want to save the real feed address + # to suck from. + my $syn_url = $url; + my $syn_chosen; + # analyze link/meta tags + while ($content =~ m!<(link|meta)\b([^>]+)>!g) { + my ($type, $val) = ($1, $2); + # RSS/Atom + # + if ($syn_chosen ne "rss" && + $type eq "link" && + $val =~ m!rel=.alternate.!i && + $val =~ m!type=.application/(?:rss|atom)\+xml.!i && + $val =~ m!href=[\"\']([^\"\']+)[\"\']!i) { + + $syn_url = $1; + + $val =~ m!type=.application/(rss|atom)\+xml.!i; + $syn_chosen = $1; + } + } + + # Did we find a link to the real feed? If so, start again + if ($syn_url ne $url) { + $url = $syn_url; + next; + } + + # check whatever we did get for validity (or pseudo-validity) + return "" + unless $content =~ m/<(\w+:)?(?:rss|feed|RDF)/; # Must have a <[?:]rss <[?:]feed (for Atom support) <[?:]RDF + + + my $ljuname; + if ( + $url =~ m!^http://users.livejournal.com/(.+?)(/|$)! || + $url =~ m!^http://community.livejournal.com/(.+?)(/|$)! || + $url =~ m!^http://(.+?).livejournal.com! + ) { + $ljuname = $1; + + if (length($ljuname) < 13) { + $acct = $ljuname; + $pfx = "lj_"; + } + } + + # if no account name, give them a proper entry form to pick one, but don't reprompt + # for the url, just pass that through (we'll recheck it anyway, though) + unless ($acct) { + my $ret .= ""; + $ret .= "

      $url

      "; + $ret .= "

      "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}, 'synurl', $url); + $ret .= "
      "; + $ret .= "

      $ML{'.account'} $pfx"; + $ret .= "

      "; + $ret .= "

      "; + return $ret; + } + + return "" + unless $acct; + + my $id; + + my $tu = LJ::load_user($pfx . $acct); + if ($tu) { + if ($tu->{'statusvis'} == "X") { + $id = $tu->{'userid'}; + } + else { + return $error->($ML{'.invalid.inuse.text'}); + } + } + else { + # create the feed account + $id = LJ::create_account({ + 'user' => $pfx . $acct, + 'name' => $pfx . $acct, + 'password' => '', + 'caps' => $LJ::SYND_CAPS, + 'cluster' => $LJ::SYND_CLUSTER, + }); + } + + return "" + unless $id; + + if ($LJ::LJR_SYN) { + my $ljr_syn_id = LJ::get_userid($LJ::LJR_SYN); + if ($ljr_syn_id) { + $dbh->do("INSERT INTO friends (userid, friendid) VALUES (?, ?)", undef, $ljr_syn_id, $id); + } + } + + LJ::update_user($id, { journaltype => 'Y', statusvis => 'V' }); + $dbh->do("INSERT INTO syndicated (userid, synurl, checknext, creatorid) VALUES (?,?,NOW(),?)", + undef, $id, $syn_url, $u->{'userid'}); + + LJ::statushistory_add($u->{'userid'}, $id, "synd_create", "acct: $acct"); + + $su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE s.userid=? AND s.userid=u.userid", + undef, $id); +# my $suu = LJ::load_userid($id); +# LJ::set_userprop($suu, "urlname", ); + } + + last; + } # while + } elsif ($acct) { + # account but no URL, we can add this in any case + $su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE u.userid=s.userid AND u.user=?", + undef, $acct); + unless ($su) { + return $error->($ML{'.invalid.notexist'}); + } + } else { + # need at least a URL + return $error->($ML{'.invalid.needurl'}); + } + + return $error->($ML{'.error.unknown'}) unless $su; + + # at this point, we have a new account, or an old account, but we have an account, so + # let's redirect them to the add page + return BML::redirect("$LJ::SITEROOT/friends/add.bml?user=$su->{user}"); + } + + # get most popular feeds from memcache + my $popsyn = LJ::Syn::get_popular_feeds(); + + # load user's friends so we can strip feeds they already watch + my $friends = LJ::get_friends($u) || {}; + + # populate @pop and add users they've chosen to add + my @pop; + my %urls; + my %names; + for (0 .. 99) { + next if not defined $popsyn->[$_]; + my ($user, $name, $suserid, $url, $count) = @{ $popsyn->[$_] }; + $names{$user} = $name; + + my $suser = LJ::load_userid($suserid); + LJ::load_user_props($suser, 'url'); + $urls{$user} = $suser->{url}; + + # skip suspended/deleted accounts, already watched feeds + next if $friends->{$suserid} || $suser->{'statusvis'} ne "V"; + + if ($POST{'action:add'} && $POST{"add_$user"}) { + LJ::add_friend($u->{'userid'}, $suserid, { 'defaultview' => 1 }); + } else { + push @pop, [ $user, $url, $count ]; + last if @pop >= 20; + } + } + + # intro paragraph + my $title = BML::ml('.using.title', {'sitename' => $LJ::SITENAME}); + my $ret = ""; + + $ret .= "
      "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}); + + if (@pop) { + $ret .= ""; + $ret .= "

      "; + $ret .= ""; + $ret .= ""; + foreach (@pop) { + my ($user, $url, $count) = @$_; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } else { + $ret .= "$names{$user}"; + } + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= ""; + $ret .= "
      $ML{'.table.account'}$ML{'.table.feed'}$ML{'.table.watchers'}
      "; + $ret .= LJ::ljuser($user, { 'type' => 'Y' }) . ""; + if ($urls{$user}) { + my $displayurl = $urls{$user}; + $displayurl = substr($urls{$user}, 0, 50) . "..." if length $displayurl > 60; + $ret .= "$names{$user}
      $displayurl
      " . LJ::img('xml', '', { border => 0 }) . "$count
      "; + $ret .= ""; + $ret .= "
      "; + } + + $ret .= "

      "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}); + + $ret .= ""; + $ret .= "
      "; + $ret .= "

      $ML{'.feed.url'} "; + $ret .= "

      "; + $ret .= "

      "; + + $ret .= "
      "; + + return $ret; +} +_code?> + +<=body +page?> diff --git a/local/htdocs/talkmulti.bml b/local/htdocs/talkmulti.bml new file mode 100755 index 0000000..3d448d5 --- /dev/null +++ b/local/htdocs/talkmulti.bml @@ -0,0 +1,95 @@ +"; + BML::set_status(403); # 403 Forbidden + return; + }; + + my $mode = $POST{'mode'}; + if ($mode eq 'screen') { + $title = $ML{'.title.screen'}; + } elsif ($mode eq 'unscreen') { + $title = $ML{'.title.unscreen'}; + } elsif ($mode eq 'delete') { + $title = $ML{'.title.delete'}; + } else { + $title = $ML{'Error'}; + return $err->($ML{'.error.invalid_mode'}); + } + + my $sth; + + my $remote = LJ::get_remote(); + return $err->($ML{'.error.login'}) unless $remote; + return $err->("") unless LJ::did_post(); + + my @talkids; + foreach (keys %POST) { + push @talkids, $1 if /^selected_(\d+)$/; + } + return $err->($ML{'.error.none_selected'}) unless @talkids; + + my $u = LJ::load_user($POST{'journal'}); + return $err->($ML{'talk.error.bogusargs'}) unless $u && $u->{'clusterid'}; + return $err->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + + my $jid = $u->{'userid'}; + my $ditemid = $POST{'ditemid'}+0; + my $commentlink = LJ::journal_base($u) . "/$ditemid.html"; + my $itemid = $ditemid >> 8; + my $log = $dbcr->selectrow_hashref("SELECT * FROM log2 WHERE journalid=? AND jitemid=?", + undef, $jid, $itemid); + return $err->($ML{'.error.inconsistent_data'}) unless $log && $log->{'anum'} == ($ditemid & 255); + my $up = LJ::load_userid($log->{'posterid'}); + + # check permissions + return $err->($ML{'.error.privs.screen'}) + if $mode eq "screen" && ! LJ::Talk::can_screen($remote, $u, $up); + return $err->($ML{'.error.privs.unscreen'}) + if $mode eq "unscreen" && ! LJ::Talk::can_unscreen($remote, $u, $up); + return $err->($ML{'.error.privs.delete'}) + if $mode eq "delete" && ! LJ::Talk::can_delete($remote, $u, $up); + + # filter our talkids down to those that are actually attached to the log2 + # specified. also, learn the state of all the items. + my $in = join (',', @talkids); + $sth = $dbcr->prepare("SELECT jtalkid, state FROM talk2 ". + "WHERE journalid=? AND jtalkid IN ($in) ". + "AND nodetype='L' AND nodeid=?"); + $sth->execute($jid, $itemid); + my %state; + while (my ($id, $state) = $sth->fetchrow_array) { + $state{$id} = $state; + } + @talkids = keys %state; + + # do the work: + if ($mode eq "delete") { + LJ::Talk::delete_comments($u, "L", $itemid, \@talkids); + $body = "$commentlink}) . " p?>"; + return; + + } elsif ($mode eq "unscreen") { + LJ::Talk::unscreen_comments($u, $itemid, \@talkids); + $body = "$commentlink}) . " p?>"; + return; + + } elsif ($mode eq "screen") { + LJ::Talk::screen_comments($u, $itemid, \@talkids); + $body = "$commentlink}) . " p?>"; + return; + } +} +_code?> + +body=> +page?> + _c?> diff --git a/local/htdocs/talkpost.bml b/local/htdocs/talkpost.bml new file mode 100755 index 0000000..556f376 --- /dev/null +++ b/local/htdocs/talkpost.bml @@ -0,0 +1,352 @@ + tags + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $errtxt; + + my $pics = LJ::Talk::get_subjecticons(); + + my $r = Apache->request; + $r->notes("codepath" => "bml.talkpost"); + + my $uri = BML::get_uri(); + + if ($uri =~ m!/(\d+)\.html$!) { + $FORM{'itemid'} = $1 unless $FORM{'replyto'} > 0; + $FORM{'journal'} = $r->notes("_journal"); + BML::set_language_scope("/talkpost.bml"); + } + + my $init = LJ::Talk::init(\%FORM); + return "{'error'} p?>" if $init->{'error'}; + + my $u = $init->{'journalu'}; + return $ML{'talk.error.nojournal'} unless $u; + + $r->notes("journalid" => $u->{'userid'}); + return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + + return $LJ::MSG_READONLY_USER if $LJ::CLUSTER_DOWN{0} || ! $dbcr; + + # redirect if account was renamed + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + if ($u->{'renamedto'} ne "") { + my $id = $FORM{'itemid'}+0; + return BML::redirect(LJ::journal_base($u->{'renamedto'}) . "/$id.html?mode=reply"); + } + } + + my $ret = ""; + + my $parpost; + my $reply; + + if ($init->{'replyto'}) + { + my $qparentid = $init->{'replyto'}; + + my $sql = "SELECT t.posterid, t.nodetype, t.nodeid AS 'itemid', ". + "UNIX_TIMESTAMP()-UNIX_TIMESTAMP(t.datepost) AS 'secondsold', ". + "t.state, l.anum FROM talk2 t, log2 l WHERE l.journalid=$u->{'userid'} AND ". + "l.jitemid=t.nodeid AND t.journalid=$u->{'userid'} AND t.jtalkid=$qparentid"; + foreach my $pass (1, 2) { + my $db = $pass == 1 ? LJ::get_cluster_reader($u) : $dbcr; + $parpost = $db->selectrow_hashref($sql); + last if $parpost; + } + return $ML{'.error.noreplypost'} unless $parpost; + + unless ($parpost->{'nodetype'} eq "L" && $parpost->{'itemid'}) { + return ""; + } + + ## load its text + { + my $tt = LJ::get_talktext2($u, $init->{'replyto'}); + $parpost->{'subject'} = $tt->{$init->{'replyto'}}->[0]; + $parpost->{'body'} = $tt->{$init->{'replyto'}}->[1]; + } + + ### load the talk properties + + LJ::load_talk_props2($u, [ $init->{'replyto'} ], {$init->{'replyto'} => $parpost}); + + if($LJ::UNICODE && $parpost->{'unknown8bit'}) { + LJ::item_toutf8($u, \$parpost->{'subject'}, \$parpost->{'body'}, {}); + } + + $init->{'itemid'} = $parpost->{'itemid'}; + $init->{'ditemid'} = $parpost->{'itemid'}*256 + $parpost->{'anum'}; + } + + my $itemid = $init->{'itemid'}; + + my $stylemine = $init->{'style'} eq "mine" ? "style=mine" : ""; + + ## load the journal item + my $item = LJ::Talk::get_journal_item($u, $itemid); + ################################################## + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + BML::set_status(404); # 404 Not found + return ""; + } + + my $props = $item->{'props'}; + + my $ditemid = $init->{'ditemid'}; + my $talkurl = LJ::journal_base($u) . "/$ditemid.html"; + + $parpost ||= $item; # if there's no parent post, remote is reply to top-level item + + my ($up, $ur); # $up = user posted journal item; $ur = user remote is replying to + LJ::load_userids_multiple([ $item->{'posterid'} => \$up, + $parpost->{'posterid'} => \$ur, ], + [ $u ]); + + my $remote = LJ::get_remote(); + + my @user_props = ("opt_logcommentips", "opt_whoscreened"); + push @user_props, "opt_blockrobots" if $u->{'statusvis'} eq 'V'; + LJ::load_user_props($u, @user_props); + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head = LJ::robot_meta_tags(); + } + + # check suspended + if ($u->{'statusvis'} eq "S" || $up->{'statusvis'} eq "S" + || $ur && $ur->{'statusvis'} eq "S") { + BML::set_status(403); # 403 Forbidden + return ""; + } + + # check deleted + if ($u->{'statusvis'} eq "D") { + BML::set_status(404); # 404 Not found + return ""; + } + + # checked screened post + if ($parpost->{'state'} eq "S" + && ! LJ::Talk::can_unscreen($remote, $u, $up, ($ur ? $ur->{'user'} : undef))) { + BML::set_status(403); # 403 Forbidden + return ""; + } + + if ($parpost->{'state'} eq "D") { + BML::set_status(404); # 404 Not found + return ""; + } + + # check if frozen + return "" + if $parpost->{'state'} eq "F"; + + # don't allow anonymous comments on syndicated items + if ($u->{'journaltype'} eq "Y" && $u->{'opt_whocanreply'} eq "all") { + $u->{'opt_whocanreply'} = "reg"; + } + + #### Check security before viewing this post + unless (LJ::Talk::check_viewable($remote, $item, \%FORM, \$errtxt)) { + BML::set_status(403); # 403 Forbidden + return $errtxt; + } + + + ### check If-Modified-Since + my $lastmod = $props->{'commentalter'}; + my $revisiontime = $props->{' revtime'}; + $lastmod = $revisiontime if $revisiontime && $revisiontime > $lastmod; + + my $ims = $r->header_in("If-Modified-Since"); + if ($ims) { + my $theirtime = LJ::http_to_time($ims); + if ($theirtime >= $lastmod && !$remote && $r->header_in("User-Agent") =~ /$LJ::ROBOTS_REGEXP/) { + # only for anonymous robots: + # valid browsers should refresh unique chal string!!! + BML::set_status(304); # 304 Not Modified + return ""; + } + } + $r->set_last_modified($lastmod); + + + my $event = $FORM{'replyto'} eq "" ? $item->{'event'} : $parpost->{'body'}; + my $preformatted = $FORM{'replyto'} eq "" ? $props->{'opt_preformatted'} : $parpost->{'opt_preformatted'}; + + LJ::CleanHTML::clean_event(\$event, $preformatted); + LJ::expand_embedded($u, $ditemid, $remote, \$event); + BML::ebml(\$event); + + $ret .= ""; + my $pickw = $init->{'replyto'} ? $parpost->{'picture_keyword'} : $props->{'picture_keyword'}; + my $picid = LJ::get_picid_from_keyword($ur, $pickw); + + my %userpics; + if ($picid) { + LJ::load_userpics(\%userpics, [ $u, $picid ]); + + # not auto-vivifying $ur here because $picid is based + # on $ur existing in the first place + my $alt = $ur->{'name'}; + $alt .= ": $pickw" if $pickw; + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
      "; + + # who-wrote-where + { + my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; + my $suffix = $is_shared ? "_comm" : ""; + + # user logged in + if ($ur) { + $ret .= BML::ml("talk.somebodywrote$suffix", + { 'realname' => LJ::ehtml($ur->{'name'}), + 'userlink' => LJ::ljuser($ur), + 'commlink' => LJ::ljuser($u) }); + + # user anonymous + } else { + $ret .= BML::ml("talk.anonwrote$suffix", + { 'commlink' => LJ::ljuser($u) }); + } + } + + unless ($init->{'replyto'}) { + my $etime = $item->{'eventtime'}; + $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($u, $&)!e; + $ret .= "
      @ $etime"; + } + + $ret .= "
      "; + + unless ($init->{'replyto'}) { + $ret .= LJ::Talk::link_bar({ 'u' => $u, 'up' => $up, 'headref' => \$head, + 'remote' => $remote, 'itemid' => $ditemid, }); + } + + my %current; + if ($props->{'current_mood'} || $props->{'current_moodid'}) { + $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, + $props->{'current_moodid'}, + $props->{'current_mood'}); + } + if ($props->{'current_music'}) { + $current{'Music'} = LJ::current_music_str($props->{'current_music'}); + } + + $ret .= "
      "; + + ### currents + if (! $init->{'replyto'} && %current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
      $curname$current{$_}

      \n"; + } + + ### security indicator + my $sec = ""; + if ($parpost->{'security'} eq "private") { + $sec = BML::fill_template("securityprivate"); + } elsif ($parpost->{'security'} eq "usemask") { + $sec = BML::fill_template("securityprotected"); + } + + $sec .= "
      \n" unless $sec eq "" or $parpost->{'subject'}; + $ret .= $sec; + + ### + if ($parpost->{'subject'}) { + my $cleansubject = $parpost->{'subject'}; + if ($init->{'replyto'}) { + # comments can't have HTML in subjects at all + $cleansubject = LJ::ehtml($cleansubject); + } else { + # but journal entries can have some + LJ::CleanHTML::clean_subject(\$cleansubject); + BML::ebml(\$cleansubject); + } + $ret .= "$cleansubject
      \n"; + } + + $ret .= $event; + $ret .= "

      "; + + $ret .= "

      "; + + my $jarg = "journal=$u->{'user'}&"; + my $readurl = LJ::Talk::talkargs($talkurl, $stylemine); + + $ret .= "

      ($ML{'talk.commentsread'})

      "; + + # can a comment even be made? + if ($props->{'opt_nocomments'}) { + $ret .= ""; + return $ret; + } + if ($u->{'opt_showtalklinks'} eq "N") { + $ret .= ""; + return $ret; + } + unless (LJ::get_cap($u, "get_comments") || + ($remote && LJ::get_cap($remote, "leave_comments"))) { + $ret .= ""; + return $ret; + } + + $ret .= BML::fill_template("H1", { DATA => $ML{'.postresponse'} }); + + $FORM{'body'} = LJ::ehtml($FORM{'body'}) if $FORM{'qr'}; + + $ret .= LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $u, + 'parpost' => $parpost, + 'replyto' => $init->{replyto}, + 'ditemid' => $ditemid, + 'form' => \%FORM }); + BML::noparse(); + return $ret; +} +_code?> + +<=body +head<= + + + +<=head +windowtitle=> +page?> +post: htdocs/talkpost_do.bml +link: htdocs/talkread.bml, htdocs/allpics.bml, htdocs/create.bml + _c?> + diff --git a/local/htdocs/talkpost_do.bml b/local/htdocs/talkpost_do.bml new file mode 100755 index 0000000..ef2d969 --- /dev/null +++ b/local/htdocs/talkpost_do.bml @@ -0,0 +1,286 @@ + POST escalation) + # since talklib.pl's LJ::Talk::Post::init checks for $POST{'ecphash'} + # and requires it to be correct. if it's not, the page fails. + %POST = %GET if $GET{'ecphash'}; + + return "" if $LJ::TALK_ABORT_REGEXP && $POST{'body'} =~ /$LJ::TALK_ABORT_REGEXP/; + + my $req = shift; + my $r = $req->{'r'}; + + foreach my $re (@LJ::TALKSPAM) { + return if ($POST{'body'} =~ /$re/); + } + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + # Set the title to be for an error, it will be changed later + # upon sucess + $title = $ML{'Error'}; + + # OpenID support + # openid is a bit of hackery but we'll check to make sure they're + # coming back from the identity server and then recreate their + # POST hash as if they never left. Watch and see + if (($GET{'openid.mode'} eq 'id_res' || $GET{'openid.mode'} eq 'cancel') && $GET{'jid'} && $GET{'pendcid'}) { + + return LJ::bad_input("OpenID support not enabled") + unless LJ::OpenID::consumer_enabled(); + + my $csr = LJ::OpenID::consumer(\%GET); + + if ($GET{'openid.mode'} eq 'id_res') { # Verify their identity + + unless ($GET{'openid.return_to'} =~ m!^\Q$LJ::SITEROOT\E/talkpost_do\.bml!) { + return LJ::bad_input("Invalid return_to"); + } + + my $vident = $csr->verified_identity; + return LJ::bad_input("Can't verify identity: ".$csr->err) unless $vident; + + my $url = $vident->url; + return LJ::bad_input("Invalid characters in identity URL.") if $url =~ /[\<\>\s]/; + + my $uo = LJ::User::load_identity_user("O", $url, $vident); + return LJ::bad_input("Couldn't vivify your account (but we verified that you're " . LJ::ehtml($url) . ")") + unless $uo; + + LJ::set_remote($uo); + + my $lj_name; + if ( + $url =~ /^http:\/\/users\.livejournal\.com\/(.+)\/?/ || + $url =~ /^http:\/\/(.+?)\./ + ) { + + $lj_name = $1 + } + + BML::set_cookie("LJR_lastljuser", $lj_name, time() + 3600*24*365, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + } + + # Restore their data to reset state where they were + my $pendcid = $GET{'pendcid'} + 0; + + my $journalu = LJ::load_userid($GET{'jid'}); + return LJ::bad_input("Unable to load user or get database handle") unless $journalu && $journalu->writer; + + my $pending = $journalu->selectrow_array("SELECT data FROM pendcomments WHERE jid=? AND pendcid=?", + undef, $journalu->{'userid'}, $pendcid); + + return LJ::bad_input("Unable to load pending comment, maybe you took too long") unless $pending; + + my $penddata = eval { Storable::thaw($pending) }; + + %POST = %$penddata; + push @errors, "You chose to cancel your identity verification" + if $csr->user_cancel; + } + # normally require POST. if an ecphash is specified, we'll let + # them through since they're coming from a comment page and + # validate the hash later. + elsif (! LJ::did_post() && !$POST{'ecphash'}) { + return LJ::bad_input("Comment not posted: POST required, or missing parameter."); + } + + + # as an exception, we do NOT call LJ::text_in() to check for bad + # input, since it may be not in UTF-8 in replies coming from mail + # clients. We call it later. + + my $remote_ip = LJ::get_remote_ip(); + if (($POST{'usertype'} eq "anonymous" || $POST{'usertype'} eq "openid") && LJ::is_open_proxy($remote_ip)) { + return LJ::bad_input("Your IP address ($remote_ip) is detected as an open proxy (a common source of spam) so comment access is denied. If you do not believe you're accessing the net through an open proxy, please contact your ISP or this site's tech support to help resolve the problem."); + } + + my $remote = LJ::get_remote(); + + # store openid-user e-mail + if ($remote && $remote->openid_identity && !$remote->{'email'} && $POST{'email'}) { + my @err; + LJ::check_email($POST{'email'}, \@err); + if (!@err) { + my $aa = {}; + $aa = LJ::register_authaction($remote->{'userid'}, "validateemail", $POST{'email'}); + + my %update = ('email' => $POST{'email'}, 'status' => "T",); + LJ::update_user($remote, \%update); + + LJ::send_mail({ + 'to' => $POST{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'charset' => 'utf-8', + 'subject' => $ML{'/editinfo.bml.newemail.subject'}, + 'body' => BML::ml( + '/editinfo.bml.newemail.body2', + { + username => LJ::User::display_name($remote), + sitename => $LJ::SITENAME, + sitelink => $LJ::SITEROOT, + conflink => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}" + } + ), + }); + } + } + + my $journalu = LJ::load_user($POST{journal}); + return LJ::bad_input('Unknown journal. Please go back and try again.') unless $journalu; + + ## preview + # ignore errors for previewing + if ($POST{'submitpreview'} || ($POST{'qr'} && $POST{'do_spellcheck'})) { + my $cookie_auth; + $cookie_auth = 1 if $POST{usertype} eq "cookieuser"; + my $talkurl = LJ::journal_base($journalu) . "/$POST{itemid}.html"; + $title = $ML{'.title.preview'}; + return LJ::Talk::Post::make_preview($talkurl, $cookie_auth, \%POST); + } + + ## init. this handles all the error-checking, as well. + my $need_captcha = 0; + my $init = LJ::Talk::Post::init(\%POST, $remote, \$need_captcha, \@errors); + + # Report errors in a friendly manner by regenerating the field. + # Required for challenge/response login, since we also need to regenerate an auth token. + # We repopulate what we can via hidden fields - however the objects (journalu & parpost) must be recreated here. + + # if the user leaving the comment hasn't agreed to the current TOS, and they + # didn't click the agreement checkbox, return the form back to them + my $require_tos = 0; + my $commentu = $init ? $init->{comment}->{u} : undef; + if ($init && ! $POST{agree_tos} && $commentu && ! $commentu->tosagree_verify) { + $require_tos = 1; + } + + if (! $init || $require_tos) { + my ($sth, $parpost); + my $dbcr = LJ::get_cluster_def_reader($journalu); + return LJ::bad_input('No database connection present. Please go back and try again.') unless $dbcr; + + $sth = $dbcr->prepare("SELECT posterid, state FROM talk2 ". + "WHERE journalid=? AND jtalkid=?"); + $sth->execute($journalu->{userid}, $POST{itemid}+0); + $parpost = $sth->fetchrow_hashref; + + $title = $ML{'.title.error'} unless $need_captcha; + + return LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $journalu, + 'parpost' => $parpost, + 'replyto' => $POST{replyto}, + 'ditemid' => $POST{itemid}, + 'require_tos' => $require_tos, + 'do_captcha' => $need_captcha, + 'errors' => \@errors, + 'form' => \%POST }); + } + + # checked $POST{agree_tos} was checked above if it was necessary, + # now we just need to save the userprop + if ($commentu && ! $commentu->tosagree_verify && $POST{agree_tos}) { + my $err = ""; + return LJ::bad_input($err) + unless $commentu->tosagree_set(\$err); + } + + + my $talkurl = $init->{talkurl}; + + my $entryu = $init->{entryu}; + my $journalu = $init->{journalu}; + my $parent = $init->{parent}; + my $comment = $init->{comment}; + my $item = $init->{item}; + + # check max comments + return LJ::bad_input("Sorry, this entry already has the maximum number of comments allowed.") + if LJ::Talk::Post::over_maxcomments($journalu, $item->{'jitemid'}); + + # no replying to frozen comments + return LJ::bad_input($ML{'/talkpost.bml.error.noreply_frozen'}) + if $parent->{state} eq 'F'; + + ## insertion + my $wasscreened = ($parent->{state} eq 'S'); + my $err; + unless (LJ::Talk::Post::post_comment($entryu, $journalu, + $comment, $parent, $item, \$err)) { + return LJ::bad_input($err); + } + + # Yeah, we're done. + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + + # Allow style=mine for QR redirects + my $stylemine = $POST{'stylemine'} ? 'style=mine' : ''; + + my $commentlink; + if ($POST{'viewing_thread'} eq '') { + $commentlink = LJ::Talk::talkargs($talkurl, "view=$dtalkid", $stylemine) . "#t$dtalkid"; + } else { + $commentlink = LJ::Talk::talkargs($talkurl, "thread=$POST{viewing_thread}", $stylemine) . "#t$dtalkid"; + } + + my $ret = ""; + $ret .= ""; + + my $mlcode; + if ($comment->{state} eq 'A') { + # Redirect the user back to their post as long as it didn't unscreen its parent, + # is screened itself, or they logged in + if (!($wasscreened and $parent->{state} ne 'S') && !$init->{didlogin}) { + LJ::set_lastcomment($journalu->{'userid'}, $remote, $dtalkid); + return BML::redirect($commentlink); + } + + $mlcode = '.success.message'; + } else { + # otherwise, it's a screened comment. + if ($journalu->{'journaltype'} eq 'C') { + $mlcode = $POST{'usertype'} eq 'anonymous' ? '.success.screened.comm.anon' + : '.success.screened.comm'; + } else { + $mlcode = $POST{'usertype'} eq 'anonymous' ? '.success.screened.user.anon' + : '.success.screened.user'; + } + } + + $ret .= " $commentlink }) . " p?>"; + + # did this comment unscreen its parent? + if ($wasscreened and $parent->{state} ne 'S') { + $ret .= ""; + } + + if ($init->{didlogin}) { + $ret .= ""; + } + + # Sucessful! + $title = $ML{'.title'}; + return $ret; +} +_code?> + +<=body +title=> +head<= + + +<=head +page?> +lib: LJ::SpellCheck +link: htdocs/lostinfo.bml, htdocs/userinfo.bml, htdocs/talkread.bml, htdocs/editinfo.bml +post: htdocs/talkpost_do.bml + _c?> diff --git a/local/htdocs/talkread.bml b/local/htdocs/talkread.bml new file mode 100755 index 0000000..f3372da --- /dev/null +++ b/local/htdocs/talkread.bml @@ -0,0 +1,668 @@ +{'head'} : \$r_head; + my $title = $_[1] ? \$_[1]->{'title'} : \$r_title; + my $bodyopts = $_[1] ? \$_[1]->{'bodyopts'} : \$r_bodyopts; + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + + + my $pics = LJ::Talk::get_subjecticons(); + + ## workaround mail client bug when don't understand quoted-printable. + ## Only correct 'journal' if 'itemid' was also broken, to avoid the + ## unlikely clash with a journal name. + if ($GET{'itemid'} =~ s/^3D//) { + $GET{'journal'} =~ s/^3D//; + $GET{'thread'} =~ s/^3D//; + } + + my $r = Apache->request; + $r->notes("codepath" => "bml.talkread"); + + my $uri = BML::get_uri(); + my $itemid; + + if ($uri =~ m!/(\d+)\.html$!) { + $itemid = $1; + $GET{'itemid'} = $itemid; + $GET{'journal'} = $r->notes("_journal"); + BML::set_language_scope("/talkread.bml"); + } + + # pre-load common strings for little speed and less typing later + # (we're doing this *after* set_language_scope is called, because + # two below are relative strings) + my %T = qw(postcomments talk.commentpost + readcomments talk.commentsread + parent talk.parentlink + thread talk.threadlink + replythis talk.replytothis + frozen talk.frozen + link talk.commentpermlink + deleted .subjectdeleted + nosubject .nosubject + ); + foreach (keys %T) { $T{$_} = $ML{$T{$_}}; } + + my $init = LJ::Talk::init(\%GET); + + my $u = $init->{'journalu'}; + return $ML{'talk.error.nojournal'} unless $u; + + my $ditemid = $init->{'ditemid'}+0; + + # redirect if account was renamed + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + if ($u->{'renamedto'} ne "") { + return BML::redirect(LJ::journal_base($u->{'renamedto'}) . "/$ditemid.html"); + } + } + + # now check for init->error, since we know the account wasn't renamed + return "{'error'} p?>" if $init->{'error'}; + + LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $$head .= LJ::robot_meta_tags(); + } + + $r->notes("journalid" => $u->{'userid'}); + + my $thread = $init->{'thread'}; + my $dthread = $init->{'dthread'}; + $itemid = $init->{'itemid'}+0; + + my $stylemine = $init->{'style'} eq "mine" ? "style=mine" : ""; + + ## load the journal item + my $item = LJ::Talk::get_journal_item($u, $itemid); + ################################################## + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + $ditemid = $init->{'ditemid'} + 0; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + BML::set_status(404); # 404 Not found + return ""; + } + + my $jarg = "journal=$u->{'user'}&"; + my $jargent ="journal=$u->{'user'}&"; + my $talkurl = LJ::journal_base($u) . "/$ditemid.html"; + + my $ret = ""; + + my $props = $item->{'props'}; + my $nocomments = $u->{'opt_showtalklinks'} eq "N" ? 1 : $props->{'opt_nocomments'}; + my $remote = LJ::get_remote(); + + ### load users + my ($up); # $up = user posted journal item + LJ::load_userids_multiple([ $item->{'posterid'} => \$up, ], [ $u ]); + + LJ::text_out(\$u->{'name'}); + + # set viewall/viewsome + my $viewall = 0; + my $viewsome = 0; + if ($GET{viewall} && LJ::check_priv($remote, 'canview')) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "entry: $u->{'user'}, itemid: $item->{'itemid'}, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + # check for deleted/suspended/security + unless ($viewsome) { + # check suspended + if ($u->{'statusvis'} eq "S" || $up->{'statusvis'} eq "S") { + BML::set_status(403); # 403 Forbidden + return ""; + } + + # check deleted + if ($u->{'statusvis'} eq "D") { + BML::set_status(404); # 404 Not found + return ""; + } + } + + unless ($viewall) { + #### Check security before viewing this post + my $errtxt; + unless (LJ::Talk::check_viewable($remote, $item, \%GET, \$errtxt)) { + BML::set_status(403); # 403 Forbidden + return $errtxt; + } + } + + + ### check If-Modified-Since + my $lastmod = $props->{'commentalter'}; + my $revisiontime = $props->{' revtime'}; + $lastmod = $revisiontime if $revisiontime && $revisiontime > $lastmod; + + my $ims = $r->header_in("If-Modified-Since"); + if ($ims) { + my $theirtime = LJ::http_to_time($ims); + if ($theirtime >= $lastmod && !$remote) { + # only for anonymous: logged users will be checked by Etag for exact match + BML::set_status(304); # 304 Not Modified + return ""; + } + } + $r->set_last_modified($lastmod); + + + # See if we should inject QuickReply javascript + LJ::load_user_props($remote, "opt_no_quickreply"); + + if (($remote && !$remote->{'opt_no_quickreply'}) && !$nocomments) { + $$head .= $LJ::COMMON_CODE{'quickreply'}; + $$bodyopts .= 'onload="restore_entry();" onunload="save_entry();"'; + } + + my $showmultiform = $remote && + ($remote->{'user'} eq $u->{'user'} || + $remote->{'user'} eq $up->{'user'} || + LJ::can_manage($remote, $u)); + my $multiform_selects = 0; # are there select boxes? don't show form if not. + + my $event = $item->{'event'}; + + LJ::CleanHTML::clean_event(\$event, $props->{'opt_preformatted'}); + LJ::expand_embedded($u, $ditemid, $remote, \$event); + BML::ebml(\$event); + + # make the title +{ + my $subject = $item->{'subject'} || $event; + LJ::CleanHTML::clean_subject_all(\$subject); + $subject =~ s/\n.*//s; + # yes, the 3 param to text_trim is chars, and length returns bytes, but + # it works, as bytes >= chars: + $subject = LJ::text_trim($subject, 0, length($item->{'subject'}) || 40); + $$title = "$u->{'user'}: $subject"; +} + + $ret .= "

      "; + $ret .= ""; + + my $picid = LJ::get_picid_from_keyword($up, $props->{'picture_keyword'}); + + my %userpics; + if ($picid) { + LJ::load_userpics(\%userpics, [ $u, $picid ]); + my $alt = $up->{'name'}; + if ($props->{'picture_keyword'}) { + $alt .= ": $props->{'picture_keyword'}"; + } + LJ::text_out(\$alt); + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
      "; + my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; + if ($is_shared) { + $ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up), + 'commlink' => LJ::ljuser($u) }); + } else { + $ret .= BML::ml("talk.somebodywrote", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up) }); + } + + my $etime = $item->{'eventtime'}; + $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($u, $&)!e; + $ret .= "
      @ $etime"; + $ret .= "
      "; + + ## standout bar + $ret .= LJ::Talk::link_bar({ 'u' => $u, 'up' => $up, 'headref' => $head, + 'remote' => $remote, 'itemid' => $ditemid, }); + + ## dump the log entry, unless we're browsing a thread. + my %current; + if ($props->{'current_mood'} || $props->{'current_moodid'}) { + $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, + $props->{'current_moodid'}, + $props->{'current_mood'}); + } + if ($props->{'current_music'}) { + $current{'Music'} = LJ::current_music_str($props->{'current_music'}); + } + +# my $tags = $props->{'tags'}; +# if ($tags && values %$tags) { +# my $base = LJ::journal_base($u); +# $current{'Tags'} = join(', ', +# map { "" . LJ::ehtml($_) . "" } +# sort values %$tags} +# ); +# } +my $logtags = LJ::Tags::get_logtags($u, $itemid); +if ($logtags->{$itemid} && %{$logtags->{$itemid}}) { + my $base = LJ::journal_base($u); + $current{'Tags'} = join(', ', + map { "" . LJ::ehtml($_) . "" } + sort values %{$logtags->{$itemid}} + ); +} + + $ret .= "

      "; + + if (%current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
      $curname$current{$_}

      \n"; + } + + ### security indicator + my $sec = ""; + if ($item->{'security'} eq "private") { + $sec = BML::fill_template("securityprivate"); + } elsif ($item->{'security'} eq "usemask") { + $sec = BML::fill_template("securityprotected"); + } + + $sec .= "
      \n" unless $sec eq "" or $item->{'subject'}; + $ret .= $sec; + + ### + if ($item->{'subject'}) { + my $subject = $item->{'subject'}; + LJ::CleanHTML::clean_subject(\$subject); + BML::ebml(\$subject); + $ret .= "$subject
      \n"; + } + + $ret .= $event; + $ret .= "

      "; + + $ret .= "

      "; + + my %user; + my $opts = { + 'thread' => $thread, + 'page' => $GET{'page'}, + 'view' => $GET{'view'}, + 'userpicref' => \%userpics, + 'userref' => \%user, + 'up' => $up, + 'viewall' => $viewall, + + # Okuklivanie tredov - daem upravlenie pol'zovatelyu - + 'page_size' => $GET{'page_size'}, + 'max_subjects' => $GET{'max_subjects'}, + 'threading_point' => $GET{'threading_point'}, + 'uncollapse' => $GET{'uncollapse'}, + }; + + my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $opts); + return $ML{'error.nodbmaintenance'} if $opts->{'out_error'} eq "nodb"; + + my $page = $opts->{'out_page'}; + my $pages = $opts->{'out_pages'}; + + ########## make the navcrap + my $navcrap; + $navcrap .= ""; + if ($pages > 1) { + $navcrap .= ""; + $navcrap .= ""; + my $left = "<<"; + if ($page > 1) { $left = " $page-1 }) . "#comments'>$left"; } + + my $right = ">>"; + if ($page < $pages) { $right = " $page+1 }) . "#comments'>$right"; } + + $navcrap .= ""; + $navcrap .= "
      "; + $navcrap .= BML::ml('ljlib.pageofpages',{'page'=>$page, 'total'=>$pages}); + $navcrap .= "
      $left"; + + for (my $i=1; $i<=$pages; $i++) { + my $link = "[$i]"; + if ($i != $page) { $link = " $i }) . "#comments'>$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + if ($i == 11) { $navcrap .= "
      "; } + elsif ($i > 10 && $i % 10 == 0) { $navcrap .= "
      "; } + } + + $navcrap .= "
      $right
      \n"; + $navcrap = BML::fill_template("standout", { 'DATA' => $navcrap }); + } + ####### end navcrap + + # Quick reply variables. Not always set. + my ($last_talkid, $last_jid) = LJ::get_lastcomment(); + my %LJ_cmtinfo; # data structure to give to javascript for commentmanage + $LJ_cmtinfo{'journal'} = $u->{user}; + $LJ_cmtinfo{'canAdmin'} = LJ::can_manage($remote, $u) ? 1 : 0; + $LJ_cmtinfo{'remote'} = $remote ? $remote->{user} : ""; + + my $recurse_post = sub + { + my ($self_sub, $post, $opts) = @_; + + $opts ||= { 'depth' => 0 }; + + my $tid = $post->{'talkid'}; + my $dtid = $tid * 256 + $init->{'anum'}; + my $LJci = $LJ_cmtinfo{$dtid} = { rc => [], u => '' }; + + my $datepost = "" . substr($post->{'datepost'}, 0, 16) . ""; + + my $bgcolor = ($opts->{'depth'} % 2) ? "emcolorlite" : "emcolor"; + $bgcolor = BML::get_template_def($bgcolor); + if ($post->{'state'} eq "S") { + $bgcolor = BML::get_template_def("screenedbarcolor") || $bgcolor; + } elsif ($last_talkid == $dtid && $last_jid == $u->{'userid'}) { + $bgcolor = BML::get_template_def("altcolor1"); + } + + my $pu = $post->{'posterid'} ? $user{$post->{'posterid'}} : undef; + $LJci->{u} = $pu->{user} if $pu; + + my $userpost = $post->{'userpost'}; + my $upost = $post->{'upost'}; + + my $user; + if ($post->{'props'}->{'deleted_poster'}) { + $user = BML::ml('.deleteduser', {'username'=>$post->{'deleted_poster'}}); + } + else { + $user = $ML{'.anonuser'}; + } + + if ($post->{'state'} eq "D") { + $ret .= "

      "; + $ret .= ""; + $ret .= "
      $ML{'.deletedpost'}
      \n"; + } elsif ($post->{'state'} eq "S" && !$post->{'_loaded'} && !$post->{'_show'}) { + $ret .= "

      "; + $ret .= ""; + my $screenedtext = $ML{'.screenedpost'}; + $ret .= "
      $screenedtext
      \n"; +# Here is a place to show commens from suspended journals +# HACK: I added "&& 0" here so that suspended poster's comments are seen + } elsif ($pu && 0 && $pu->{'statusvis'} eq "S" && !$viewsome) { + $ret .= "

      "; + $ret .= ""; + $ret .= "
      $ML{'.replysuspended'}"; + if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { + $ret .= " " . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + if ($post->{state} ne 'F' && LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + if ($post->{state} eq 'F' && LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + $ret .= "
      \n"; + } else { + if ($upost) { + $user = LJ::ljuser($upost); + } + my $icon = LJ::Talk::show_image($pics, $post->{'props'}->{'subjecticon'}); + + if ($post->{'_loaded'}) { + $ret .= ""; + $ret .= ""; + $ret .= "
      "; + if (my $picid = $post->{'picid'}) { + my $alt = $pu->{'name'}; + if ($post->{'props'}->{'picture_keyword'}) { + $alt .= ": $post->{'props'}->{'picture_keyword'}"; + } + $alt = LJ::ehtml($alt); + my ($w, $h) = ($userpics{$picid}->{'width'}, $userpics{$picid}->{'height'}); + $ret .= "{'subject'}); + $ret .= "$cleansubject $icon"; + $ret .= "
      $user\n"; + $ret .= "
      $datepost\n"; + if ($post->{'props'}->{'poster_ip'} && $remote && + ($remote->{'user'} eq $up->{'user'} || + LJ::can_manage($remote, $u) || $viewall)) + { + $ret .= BML::ml('.fromip', {'ip'=>$post->{'props'}->{'poster_ip'}}); + } + + $ret .= " ($T{'link'}) "; + + if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($post->{'state'} ne 'F' && + LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($post->{'state'} eq 'F' && + LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($post->{'state'} ne 'S' && + LJ::Talk::can_screen($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_scr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($post->{'state'} eq 'S' && + LJ::Talk::can_unscreen($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unscr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($showmultiform) { + $ret .= " "; + $ret .= " "; + $multiform_selects = 1; + } + + # Comment Posted Notice + $ret .= "
      $ML{'.posted'}" + if $last_talkid == $dtid && $last_jid == $u->{'userid'}; + + $ret .= "
      "; + + LJ::CleanHTML::clean_comment(\$post->{'body'}, + { 'preformatted' => $post->{'props'}->{'opt_preformatted'}, + 'anon_comment' => (!$pu || $pu->{_identity}) } ); + BML::ebml(\$post->{'body'}); + $ret .= $post->{'body'}; + + $ret .= "

      "; + + my $replyurl = LJ::Talk::talkargs($talkurl, "replyto=$dtid", $stylemine); + if ($post->{'state'} eq 'F') { + $ret .= "($T{'frozen'}) "; + } elsif ($remote) { + $ret .= "(" . LJ::make_qr_link($dtid, $post->{'subject'}, $T{'replythis'}, $replyurl) . ")"; + } else { + $ret .= "($T{'replythis'}) "; + } + + if ($post->{'parenttalkid'} != 0) { + my $dpid = $post->{'parenttalkid'} * 256 + $init->{'anum'}; + $ret .= "($T{'parent'}) "; + } + if ($post->{'children'} && @{$post->{'children'}}) { + my $url = LJ::Talk::talkargs($talkurl, "thread=$dtid", $stylemine) . "#t$dtid"; + $ret .= "($T{'thread'})"; + } + $ret .= "

      "; + + $ret .= LJ::make_qr_target($dtid) if $remote; + + $ret .= "
      \n"; # close colored table + } else { + # link to message + + $ret .= ""; + $ret .= ""; + $ret .= "
      " . LJ::ehtml($post->{'subject'} || $T{'nosubject'}) . " - $user, $post->{'datepost'}"; + + # Comment Posted Notice + $ret .= " - $ML{'.posted'}" + if $last_talkid == $dtid && $last_jid == $u->{'userid'}; + $ret .= "
      \n"; + } + } + + if ($post->{'children'}) { + foreach my $childpost (@{$post->{'children'}}) { + push @{$LJci->{rc}}, $childpost->{talkid} * 256 + $init->{'anum'}; + $self_sub->($self_sub, $childpost, { "depth" => $opts->{'depth'} + 1}); + } + } + }; + + + if ($props->{'syn_link'}) { + my $posturl; + my $rs = LJR::Distributed::match_remote_server($props->{'syn_link'}); + if ($rs->{"servertype"} eq "lj") { + $posturl = $props->{'syn_link'} . "?mode=reply"; + } + else { + $posturl = $props->{'syn_link'} . "?mode=reply"; + } + $ret .= "

      "; + $ret .= "($T{'readcomments'})"; + $ret .= " ($T{'postcomments'})"; + $ret .= "

      "; + } + + unless ($nocomments) + { + $ret .= "
      "; + $ret .= "$navcrap" if $navcrap; + my $readlink; + if ($dthread && $pages == 1) { + my $readurl = LJ::Talk::talkargs($talkurl, $stylemine); + $readlink = "($T{'readcomments'}) - "; + } + + my $posturl = LJ::Talk::talkargs($talkurl, "mode=reply", $stylemine); + + $ret .= "
      "; + + # Quick Reply when posting a new top level comment + # requires setup when logged in. + $ret .= "

      $readlink"; + if ($remote) { + $ret .= "(" . LJ::make_qr_link('top', '', $T{'postcomments'}, $posturl) . ")"; + } else { + $ret .= "($T{'postcomments'})"; + } + + $ret .= "

      "; + + $ret .= "
      " . LJ::make_qr_target('top') . "
      " if $remote; + + my $stylemine = $GET{'style'} eq 'mine' ? 1 : 0; + + my $viewing_thread; + if (defined $GET{'thread'}) { + $viewing_thread = $GET{'thread'}; + } + $ret .= LJ::create_qr_div($u, $ditemid, $stylemine, $GET{'prop_picture_keyword'}, $viewing_thread); + + $ret .= LJ::html_hidden("ditemid", $ditemid); + $ret .= LJ::html_hidden("journal", $u->{'user'}); + + # Print out each comment + if (@comments > 0) + { + $recurse_post->($recurse_post, $_, { "depth" => 0 }) foreach (@comments); + + my $do_commentmanage_js = $showmultiform; + if ($LJ::DISABLED{'commentmanage'}) { + if (ref $LJ::DISABLED{'commentmanage'} eq "CODE") { + $do_commentmanage_js = $LJ::DISABLED{'commentmanage'}->($remote); + } else { + $do_commentmanage_js = 0; + } + } + + if ($do_commentmanage_js) { + $$head .= "\n"; + my $js_screen_color = "\"" . LJ::ejs(BML::get_template_def("screenedbarcolor") || BML::get_template_def("emcolor")) . "\""; + my $js_normal_color = "\"" . LJ::ejs(BML::get_template_def("emcolor")) . "\""; + $$head .= "\n"; + } + + $ret .= "

      $readlink"; + $ret .= "(" . LJ::make_qr_link('bottom', '', $T{'postcomments'}, $posturl) . ")" if $remote; + $ret .= "

      "; + $ret .= "
      " . LJ::make_qr_target('bottom') . "
      " if $remote; + + if ($showmultiform && $multiform_selects) { + $ret .= "

      $ML{'.talkmulti.des'} "; + $ret .= LJ::html_select({'name' => 'mode' }, + "" => "", + "unscreen" => $ML{'.talkmulti.unscreen'}, + "screen" => $ML{'.talkmulti.screen'}, + "delete" => $ML{'.talkmulti.delete'}); + $ret .= " " . LJ::html_submit('', $ML{'.talkmulti.submit'}, + { "onclick" => "return (document.multiform.mode.value != \"delete\") " . + "|| confirm(\"" . LJ::ejs($ML{'.confirm.action'}) . "\");" }); + $ret .= "

      "; + } + } + + $ret .= "
      "; + + if ($navcrap) { + $ret .= "

      $navcrap

      "; + } + + $ret .= "
      "; + } + + BML::noparse(); + return $ret; + +_code?> +<=body +windowtitle=>{'title'} : $r_title _code?> +head=>{'head'} : $r_head _code?> +bodyopts=>{'bodyopts'}; _code?> +page?> +link: htdocs/talkpost.bml, htdocs/talkread.bml, htdocs/delcomment.bml +img: htdocs/img/dot.gif, htdocs/img/delcomment.gif + _c?> diff --git a/local/htdocs/talkscreen.bml b/local/htdocs/talkscreen.bml new file mode 100755 index 0000000..647cfcd --- /dev/null +++ b/local/htdocs/talkscreen.bml @@ -0,0 +1,199 @@ +1 +_info?>"; + return; + }; + my $bad_input = sub { + return $error->("Bad input: $_[0]") if $jsmode; + $body = LJ::bad_input($_[0]); + return; + }; + + my $mode = $POST{'mode'} || $GET{'mode'}; + my $talkid = $POST{'talkid'} || $GET{'talkid'}; + my $journal = $POST{'journal'} || $GET{'journal'}; + my $qtalkid = $talkid+0; + my $dtalkid = $qtalkid; # display talkid, for use in URL later + + my $jsres = sub { + my $mode = shift; + + # flip case of 'un' + my $newmode = "un$mode"; + $newmode =~ s/^unun//; + my $stockimg = { + 'screen' => "btn_scr.gif", + 'unscreen' => "btn_unscr.gif", + 'freeze' => "btn_freeze.gif", + 'unfreeze' => "btn_unfreeze.gif", + }; + + my $res = "rpcRes = {\n mode: \"$mode\", id: $dtalkid, \n" . + " oldimage: \"$LJ::IMGPREFIX/$stockimg->{$mode}\",\n " . + " newimage: '$LJ::IMGPREFIX/$stockimg->{$newmode}',\n " . + " newurl: '$LJ::SITEROOT/talkscreen.bml?mode=$newmode&journal=$journal&talkid=$dtalkid' \n" . + "};\n"; + BML::finish(); + return $res; + }; + + my $remote = LJ::get_remote(); + + return $error->($ML{'.error.login'}) unless $remote; + + # we need to find out: $u, $up (poster of the entry this is a comment to), + # userpost (username of this comment's author). Then we can check permissions. + + my $u = LJ::load_user($journal); + return $error->($ML{'talk.error.bogusargs'}) unless $u; + my $dbcr = LJ::get_cluster_def_reader($u); + return $error->($ML{'error.nodb'}) unless $dbcr; + + my $post; + $qtalkid = int($qtalkid / 256); # get rid of anum + $post = $dbcr->selectrow_hashref("SELECT jtalkid AS 'talkid', nodetype, state, nodeid AS 'itemid', ". + "parenttalkid, journalid, posterid FROM talk2 ". + "WHERE journalid=$u->{'userid'} AND jtalkid=$qtalkid"); + + return $error->($ML{'talk.error.nocomment'}) unless $post; + return $error->($ML{'talk.error.comm_deleted'}) if $post->{'state'} eq "D"; + + my $state = $post->{'state'}; + + $u ||= LJ::load_userid($post->{'journalid'}); + return $error->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + if ($post->{'posterid'}) { + $post->{'userpost'} = LJ::get_username($post->{'posterid'}); + } + + my $qitemid = $post->{'itemid'}+0; + + # $posterid is the userid of the author of the entry, not the comment + my ($posterid, $anum) = + $dbcr->selectrow_array("SELECT posterid, anum FROM log2 WHERE ". + "journalid=$u->{'userid'} AND jitemid=$qitemid"); + my $up = LJ::load_userid($posterid); + + my $ditemid = $qitemid*256 + $anum; + + my $itemlink = LJ::journal_base($u) . "/$ditemid.html"; + my $commentlink = "$itemlink?view=$dtalkid#t$dtalkid"; + + if ($mode eq 'screen') { + my $can_screen = LJ::Talk::can_screen($remote, $u, $up, $post->{'userpost'}); + return $error->($ML{'.error.privs.screen'}) unless $can_screen; + unless ($POST{'confirm'} eq 'Y') { + $body .= ""; + $body .= "

      \n"; + $body .= LJ::html_hidden(mode => 'screen', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.screen.doit'}); + $body .= "
      "; + $body .= "
      \n"; + return; + } + if ($state ne 'S') { + LJ::Talk::screen_comments($u, $qitemid, [$qtalkid]); + } + # FIXME: no error checking? + return $jsres->($mode) if $jsmode; + $body = "$commentlink}) . " p?>"; + return; + } + + if ($mode eq 'unscreen') { + my $can_unscreen = LJ::Talk::can_unscreen($remote, $u, $up, $post->{'userpost'}); + return $error->($ML{'.error.privs.unscreen'}) unless $can_unscreen; + unless ($POST{'confirm'} eq 'Y') { + $body .= ""; + $body .= "

      \n"; + $body .= LJ::html_hidden(mode => 'unscreen', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.unscreen.doit'}); + $body .= "
      "; + $body .= "
      \n"; + return; + } + if ($state ne 'A') { + LJ::Talk::unscreen_comments($u, $qitemid, [$qtalkid]); + } + # FIXME: no error checking? + return $jsres->($mode) if $jsmode; + $body = "$commentlink}) . " p?>"; + return; + } + + if ($mode eq 'freeze') { + my $can_freeze = LJ::Talk::can_freeze($remote, $u, $up, $post->{userpost}); + unless ($can_freeze) { + $body = ""; + return; + } + + unless ($POST{confirm} eq 'Y') { + $body .= ""; + $body .= "

      \n"; + $body .= LJ::html_hidden(mode => 'freeze', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.freeze.doit'}); + $body .= "
      "; + $body .= "
      \n"; + return; + } + if ($state ne 'F') { + LJ::Talk::freeze_thread($u, $qitemid, $qtalkid); + } + return $jsres->($mode) if $jsmode; + my $linktext = BML::ml('.link', { aopts => "href='$itemlink'" }); + $body = ""; + return; + } + + if ($mode eq 'unfreeze') { + my $can_unfreeze = LJ::Talk::can_unfreeze($remote, $u, $up, $post->{userpost}); + unless ($can_unfreeze) { + $body = ""; + return; + } + unless ($POST{confirm} eq 'Y') { + $body .= ""; + $body .= "

      \n"; + $body .= LJ::html_hidden(mode => 'unfreeze', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.unfreeze.doit'}); + $body .= "
      "; + $body .= "
      \n"; + return; + } + if ($state eq 'F') { + LJ::Talk::unfreeze_thread($u, $qitemid, $qtalkid); + } + return $jsres->($mode) if $jsmode; + my $linktext = BML::ml('.link', { aopts => "href='$itemlink'" }); + $body = ""; + return; + } + + $body = ""; + return; + +} +_code?> +body=> +page?> diff --git a/local/htdocs/tools/embedcontent.bml b/local/htdocs/tools/embedcontent.bml new file mode 100644 index 0000000..77ef649 --- /dev/null +++ b/local/htdocs/tools/embedcontent.bml @@ -0,0 +1,40 @@ +request; + + my $host = $r->header_in("Host"); + my $fwd_host = $r->header_in("X-Forwarded-Host"); + $host = $fwd_host if $fwd_host; + $host =~ s/,.+//; + + return "This page cannot be viewed from $host" + unless $host =~ /.*$LJ::EMBED_MODULE_DOMAIN$/i; + + # we should have three GET params: journalid, moduleid, auth_token + my $journalid = $GET{journalid}+0 or return "No journalid specified"; + my $moduleid = $GET{moduleid}; + return "No module id specified" unless defined $moduleid; + $moduleid += 0; + my $preview = $GET{preview}; + # check auth_token + return "Invalid auth string" unless + LJ::Auth->check_sessionless_auth_token('embedcontent', %GET); + + # ok we're cool, return content + my $content = LJ::EmbedModule->module_content( + journalid => $journalid, + moduleid => $moduleid, + preview => $preview, + ); + + return qq { + $content + }; +} +_code?> diff --git a/local/htdocs/tools/memadd.bml b/local/htdocs/tools/memadd.bml new file mode 100755 index 0000000..b17d561 --- /dev/null +++ b/local/htdocs/tools/memadd.bml @@ -0,0 +1,321 @@ +("Invalid UTF-8 Input"); + } + + my $remote = LJ::get_remote(); + return $err->($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $memoryu = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $memoryu; + + my %secopts = ( 'public' => $ML{'label.security.public'}, + 'friends' => $ML{'label.security.friends'}, + 'private' => $ML{'label.security.private'}, ); + + if ($memoryu->{'journaltype'} eq "C") { + $secopts{'private'} = $ML{'label.security.maintainers'}; + $secopts{'friends'} = $ML{'label.security.members'}; + } + + my $sth; + my $journal = $GET{'journal'}; + my $ditemid = $GET{'itemid'}+0; + + # OK. the memories schema is weird and stores *display* itemids in the database. + # additionally, we distinguish precluster itemids because they're stored without a userid. + # it's too late to fix it in the db, so we just work around it-- + # all new memories still get userid+ditemid because we can't change the ditemid/itemid problem, + # but old-style itemids get fixed up to userid+ditemid. + + # *however*, when editing old itemids we need to keep around + # the old-style ditemid so we can still edit it. + + # to keep this all sorted out, we fixup variables like this: + # - itemid -- real, new-style itemid + # - ditemid -- display itemid (with anum) + # - dbitemid -- itemid that is in the database; + # usually same as ditemid, but different for old-style itemids. + + my $dbitemid = $ditemid; + my $itemid; + my $oldstyle = 0; + my $ju; + my $jid; + + my $anum; + + if ($journal) { + $ju = LJ::load_user($journal); + $jid = $ju->{'userid'}; + $anum = $ditemid % 256; + $itemid = int($ditemid / 256); + } else { + # old-style item url? + my $newids = LJ::get_newids('L', $ditemid); + if ($newids) { + ($jid, $itemid) = @$newids; + $ju = LJ::load_userid($jid); + $oldstyle = 1; + } + } + + unless ($ju && $itemid) { + $title = $ML{'Error'}; + $body = $ML{'error.nojournal'}; + return; + } + + my $log = LJ::get_log2_row($ju, $itemid); + unless ($log) { + $title = $ML{'Error'}; + $body = "Error retrieving data to add a memory."; + return; + } + + # check to see if it already is memorable (thus we're editing, not adding); + my $memory = LJ::Memories::get_by_ditemid($memoryu, $oldstyle ? 0 : $jid, $ditemid); + + if ($oldstyle) { + # ditemid was an old-style itemid, so we update it to the new style. + $anum = $log->{anum}; + $ditemid = $itemid<<8 + $anum; + } + + # get keywords user has used + my $exist_kw = LJ::Memories::get_keywords($memoryu); + unless ($exist_kw) { + $title = $ML{'Error'}; + $body = "Error fetching existing keywords."; + return; + } + + if ($POST{'mode'} eq "") + { + my ($des, $keywords); + + my @all_keywords; + my %selected_keyword; + @all_keywords = sort values %$exist_kw; + + if (defined $memory) { + $title = $ML{'.title.edit_memory'}; + $des = $memory->{'des'}; + my $kwids = LJ::Memories::get_keywordids($memoryu, $memory->{memid}) || []; + foreach my $kwid (@$kwids) { + my $kw = $exist_kw->{$kwid}; + next if ($kw eq "*"); + if ($keywords) { $keywords .= ", "; } + $keywords .= $kw; + $selected_keyword{$kw} = 1; + } + if (!$log || ($jid && $log->{'anum'} != $anum)) + { + LJ::Memories::delete_by_id($memoryu, $memory->{memid}); + LJ::Memories::updated_keywords($memoryu); + $title = $ML{'Error'}; + $body = $ML{'.error.entry_deleted'}; + return; + } + + } + elsif (!$log || ($jid && $log->{'anum'} != $anum)) + { + $title = $ML{'Error'}; + $body = $ML{'error.noentry'}; + return; + } + else + { + $title = $ML{'.title.add_memory'}; + + # this is a new memory. + my $user = LJ::get_username($log->{'journalid'}); + my $dt = substr($log->{'eventtime'}, 0, 10); + my $item = LJ::Talk::get_journal_item($ju, $itemid); + my $subject = $item->{'subject'}; + + $des = "$dt: $user: $subject"; + } + + # it'd be nice to only show the authas form when adding an entry and not + # when editing one, but if user u is logged in and has post p as a memory + # already then wants to add it to community c, when u clicks the "add memory" + # link on p, u gets the "edit entry" page and they need to be able to switch + # to c. + $body .= "
      \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= LJ::html_hidden(journal => $GET{journal}) if $GET{journal}; + $body .= LJ::html_hidden(itemid => $GET{itemid}); + $body .= "
      \n\n"; + + LJ::text_out(\$des); + LJ::text_out(\$keywords); + + $body .= $ML{'.add_previous'}; + + my $getextra = "?itemid=$dbitemid"; + $getextra .= "&authas=$authas" if $authas ne $remote->{'user'}; + # we still need to pass the dbitemid and not the itemid to ourself. + $getextra .= "&journal=$journal" unless $oldstyle; + + $body .= "
      "; + $body .= LJ::html_hidden(mode => "save"); + + $body .= ""; + $body .= ""; + + $body .= "\n"; + $body .= "
      $ML{'.description'}"; + $body .= LJ::html_text({name => 'des', value => $des, maxlength => LJ::CMAX_MEMORY, size => 40}); + $body .= "
      $ML{'.description.text'}
      $ML{'.keywords'}"; + $body .= LJ::html_text({name => 'keywords', maxlength => LJ::CMAX_KEYWORD, size => 40, value => $keywords}); + $body .= "
      $ML{'.keywords.text'}
      "; + + if (@all_keywords) { + my $size = scalar(@all_keywords); + $size = 15 if $size > 15; + $body .= "$ML{'.keywords.select'}
      "; + $body .= LJ::html_select( { name => 'oldkeywords', size => $size, multiple => 1, + selected => [ keys %selected_keyword ], noescape => 1 }, + map { (LJ::ehtml($_), LJ::ehtml($_)) } @all_keywords); + $body .= "
      $ML{'.multiple_selections'}"; + } else { + $body .= "$ML{'.keywords.example'}"; + } + + $body .= "
      $ML{'.security'}"; + $body .= LJ::html_select({name => 'security', selected => defined $memory ? $memory->{'security'} : undef}, + map { ($_, $secopts{$_}) } qw(public friends private)); + if ($memoryu->{'journaltype'} eq "C") { + $body .= "
      $ML{'.whocansee.comm'}
      \n"; + } else { + $body .= "
      $ML{'.whocansee'}
      \n"; + } + $body .= LJ::html_submit(undef, $ML{'.form.submit'}); + $body .= LJ::html_submit(undef, $ML{'.form.reset'}, {type => 'reset'}) if defined $memory; + $body .= "
      "; + + return; + } + + if ($POST{'mode'} eq "save") + { + my $dbh = LJ::get_db_writer(); + + if (! $POST{'des'}) { + # then we're deleting. + if (defined $memory) { + LJ::Memories::delete_by_id($memoryu, $memory->{memid}); + LJ::Memories::updated_keywords($memoryu); + $title = $ML{'.title.deleted'}; + $body = " $memory->{'des'} }) . + "p?>"; + return; + } else { + $title = $ML{'Error'}; + $body = ""; + return; + } + } + + #### we're inserting/replacing now into memories + my @keywords; + { + my %kws; + foreach (split(/\s*,\s*/, $POST{'keywords'})) { $kws{$_} = 1; } + # oldkeywords were split at the beginning + foreach (@{$POST{'oldkeywords'}}) { $kws{$_} = 1; } + @keywords = keys %kws; + } + if (scalar(@keywords) > 5) { + $title = $ML{'Error'}; + $body = ""; + return; + } + @keywords = grep { $_ } map { s/\s\s+/ /g; LJ::trim($_); } @keywords; + push @keywords, "*" unless (@keywords); + my @kwid; + + my $needflush = 0; + foreach my $kw (@keywords) { + if (length($kw) > 40) { + $title = $ML{'Error'}; + $body = " LJ::ehtml($kw) }) . "p?>"; + return; + } + + my $kwid = LJ::get_keyword_id($memoryu, $kw); + $needflush = 1 unless defined $exist_kw->{$kwid}; + push @kwid, $kwid; + } + + unless (exists $secopts{$POST{'security'}}) { + $title = $ML{'Error'}; + $body = $ML{'.error.invalid_security'}; + return; + } + + my $des = LJ::text_trim($POST{'des'}, LJ::BMAX_MEMORY, LJ::CMAX_MEMORY); + my $sec = $POST{'security'}; + + # handle edits by deleting the old memory and recreating + LJ::Memories::delete_by_id($memoryu, $memory->{memid}) + if defined $memory; + LJ::Memories::create($memoryu, { + journalid => $jid, + ditemid => $ditemid, + des => $des, + security => $sec, + }, \@kwid); + LJ::Memories::updated_keywords($memoryu) if $needflush; + + $title = $ML{'.title.added'}; + $body = "{user}, $itemid, $anum); + $body .= BML::ml('.body.added.body2', {'aopts' => "href='$backlink'"}); + $body .= " p?>"; + + return; + } + + $title = $ML{'Error'}; + $body = $ML{'error.unknownmode'}; + + return; +_code?> + + +body=> +page?> + + +link: htdocs/login.bml +post: htdocs/tools/memadd.bml + _c?> diff --git a/local/htdocs/tools/recent_comments.bml b/local/htdocs/tools/recent_comments.bml new file mode 100755 index 0000000..88d0334 --- /dev/null +++ b/local/htdocs/tools/recent_comments.bml @@ -0,0 +1,261 @@ +Recent Comments +head<= + +<=head +body<= +{user}; + $LJ_cmtinfo{'journal'} = $remote->{user}; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my $user = $u->{'user'}; + + my $dbcr = LJ::get_cluster_reader($u); + return "Error: can't get DB for user" unless $dbcr; + + my $count = LJ::get_cap($u, "tools_recent_comments_display"); + + # authas switcher form + $ret .= "
      \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "
      \n\n"; + + my (@recv, @posted, %talkids); + my %need_userid; + my %logrow; # "jid nodeid" -> $logrow + + my $now = time(); + my $sth; + + my $jargent ="journal=$u->{'user'}&"; + + # Retrieve recv + { + my $max = $dbcr->selectrow_array("SELECT MAX(jtalkid) FROM talk2 WHERE journalid=?", + undef, $u->{userid}); + $sth = $dbcr->prepare("SELECT jtalkid, nodetype, nodeid, parenttalkid, ". + " posterid, UNIX_TIMESTAMP(datepost) as 'datepostunix', state ". + "FROM talk2 ". + "WHERE journalid=? AND jtalkid > ?"); + $sth->execute($u->{userid}, $max - $count); + die $dbcr->errstr if $dbcr->err; + while (my $r = $sth->fetchrow_hashref) { + $r->{itemid} = $r->{nodeid}; # fill_items_with required field + push @recv, $r; + $need_userid{$r->{posterid}} = 1 if $r->{posterid}; + $talkids{$r->{jtalkid}} = 1; + } + } + + # Retrieve posted + if ($u->{journaltype} eq "P") { + $sth = $dbcr->prepare("SELECT posttime, journalid, nodetype, nodeid, jtalkid, publicitem ". + "FROM talkleft ". + "WHERE userid=? ORDER BY posttime DESC LIMIT $count"); + $sth->execute($u->{'userid'}); + my %jcount; # jid -> ct + $ret .= ""; + while (my $r = $sth->fetchrow_hashref) { + $r->{ownerid} = $r->{journalid}; $r->{itemid} = $r->{nodeid}; # fill_items_with...multiowner required fields: ownerid, userid ! + push @posted, $r; + $need_userid{$r->{journalid}} = 1; + } + } + + $ret .= "
      " . + BML::ml('Actionlink', { 'link' => "Latest Received"}) . " " . + BML::ml('Actionlink', { 'link'=>"Latest Posted"}) . "
      " if $u->{journaltype} eq "P"; + + + + $ret .= ""; + $ret .= ""; + + @recv = sort { $b->{datepostunix} <=> $a->{datepostunix} } @recv; + my @recv_talkids = map { $_->{'jtalkid'} } @recv; + + my %props; + LJ::load_talk_props2($u, \@recv_talkids, \%props); + my $comment_text = LJ::get_talktext2($u, keys %talkids); + + my $root = LJ::journal_base($u); + + my $us = LJ::load_userids(keys %need_userid); + + LJ::fill_items_with_text_props(\@recv, $u, {'only_subject' => 1}); + LJ::fill_items_with_text_props(\@posted, $us, {'multiowner' => 1, 'only_subject' => 1}); + + + $ret .= "
      "; + foreach my $r ( @recv) { + next unless $r->{nodetype} eq "L"; + next if $r->{state} eq "D"; + + my $pu = $us->{$r->{posterid}}; + next if $pu->{statusvis} =~ /[XS]/; + + $r->{'props'} = $props{$r->{'jtalkid'}}; + + my $lrow = $logrow{"$u->{userid} $r->{nodeid}"} ||= LJ::get_log2_row($u, $r->{'nodeid'}); + my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'}; + + my $ditemid = "$root/$lrow->{ditemid}.html"; + my $talkurl = "$root/$lrow->{ditemid}.html?thread=$talkid\#t$talkid"; + + my $bgcolor = "transparent"; + my $state = ""; + if ($r->{state} eq "S") { + $bgcolor = BML::fill_template("screenedbarcolor"); + $state = "Screened"; + } elsif ($r->{state} eq "D") { + $state = "Deleted"; + } elsif ($r->{state} eq "F") { + $state = "Frozen"; + } + + my $ljcmt = $LJ_cmtinfo{$talkid} = {}; + $ljcmt->{u} = $pu->{userid} ? $pu->{user} : ""; + + $ret .= ""; + + } + $ret .= "
      "; + $ret .= ($pu->{userid} ? LJ::ljuser($pu) : "Anonymous") . "
      "; + + $ret .= LJ::ago_text($now - $r->{datepostunix}) . "
      "; + $ret .= "
      $state
      " if $r->{state} ne "D"; + + unless ($r->{state} eq "D") + { + $ret .= "" . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + if ($r->{'state'} ne 'F') { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($r->{'state'} eq 'F') { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($r->{'state'} ne 'S') { + $ret .= "" . LJ::img("btn_scr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($r->{'state'} eq 'S') { + $ret .= "" . LJ::img("btn_unscr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + } + + # FIXME: (David?) We'll have to make talk_multi.bml understand jtalkids in multiple posts + #$ret .= " "; + #$ret .= " "; + + $ret .= "
      "; + + my $subject = $r->{'text'}->[0]; + LJ::CleanHTML::clean_subject(\$subject) if $subject ne ""; + + $ret .= "$subject " if $subject ne ""; + $ret .= "(Entry Link)" unless $lrow->{ditemid} == undef; + $ret .= "

      "; + my $subject = $comment_text->{$r->{jtalkid}}[0]; + LJ::CleanHTML::clean_subject(\$subject); + + if ($subject && $subject !~ /^Re:\s*$/) { + $ret .= "$subject
      "; + } + + my $comment = $comment_text->{$r->{jtalkid}}[1]; + LJ::CleanHTML::clean_comment(\$comment, { 'preformatted' => $r->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$pu }); + $ret .= "$comment

      "; + + $ret .= "(Comment Link) " unless $r->{state} eq "D" || $lrow->{ditemid} == undef; + + my $stylemine = 0; + my $replyurl = LJ::Talk::talkargs($ditemid, "replyto=$talkid", $stylemine); + if ($lrow->{ditemid} == undef) { + $ret .= "(Post Deleted)"; + } elsif ($r->{'state'} eq 'F') { + $ret .= "($ML{'talk.frozen'}) "; + } elsif ($r->{'state'} eq "D") { + $ret .= "(Comment Deleted)"; + } else { + $ret .= "($ML{'talk.replytothis'}) "; + } + + $ret .= "
      "; + + $ret .= " $count, 'max' => $LJ::TOOLS_RECENT_COMMENTS_MAX }). + " p?>" unless $count == $LJ::TOOLS_RECENT_COMMENTS_MAX; + + + if ($u->{journaltype} eq "P") { + $ret .= "
      " . + BML::ml('Actionlink', { 'link'=>"Latest Received"}) . + BML::ml('Actionlink', { 'link' => "Latest Posted"}) . " " . + "
      "; + $ret .= ""; + my %jcount; # jid -> ct + $ret .= ""; + $ret .= ""; + + foreach my $r (@posted) { + $jcount{$r->{'journalid'}}++; + next unless $r->{'nodetype'} eq "L"; # log2 comment + + my $ju = $us->{$r->{journalid}}; + my $lrow = $logrow{"$ju->{userid} $r->{nodeid}"} ||= LJ::get_log2_row($ju, $r->{'nodeid'}); + my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'}; + + my $logurl = "$LJ::SITEROOT/users/$ju->{user}/$lrow->{ditemid}.html"; + my $talkurl = "$logurl?thread=$talkid\#t$talkid"; + + my $hr_ago = LJ::ago_text($now - $r->{'posttime'}); + my $subject; + if (defined $lrow->{ditemid}) { + $hr_ago = "$hr_ago"; + + $subject = $r->{'text'}->[0] || "$lrow->{ditemid}.html"; + LJ::CleanHTML::clean_subject(\$subject); + $subject = "$subject"; + } else { + $subject = "Post Deleted"; + } + + my $links = "[Comment] [Entry]\n"; + $ret .= ""; + } + $ret .= "
      TimeLocation
      $hr_ago" . LJ::ljuser($ju->{user}) . ": $subject
      "; + } + + my $js_screen_color = "\"" . LJ::ejs(BML::get_template_def("screenedbarcolor")) . "\""; + $ret .= ""; + + return $@ || $ret; + +} +_code?> +<=body +page?> diff --git a/local/htdocs/tools/search.bml b/local/htdocs/tools/search.bml new file mode 100644 index 0000000..888de09 --- /dev/null +++ b/local/htdocs/tools/search.bml @@ -0,0 +1,46 @@ +ПоиÑк по журналу +body<= +{user}; + + my $ret = qq{ + + + + + + + + + + + + + + + + + +
      Searching in:$ljuser
      Search for:
       
      + +standout?> + +

      Ð”Ð»Ñ Ð¿Ð¾Ð¸Ñка иÑпользуетÑÑ blogs.yandex.ru.

      +}; + + return $ret; +} +_code?> +<=body +page?> diff --git a/local/htdocs/tos-2006-06-06.html b/local/htdocs/tos-2006-06-06.html new file mode 100755 index 0000000..ce6fd51 --- /dev/null +++ b/local/htdocs/tos-2006-06-06.html @@ -0,0 +1,141 @@ + + ToS + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +

      +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org), ×ÅÒÓÉÑ 1.0 +

      + ÷ ÍÁÅ 2006 ÇÏÄÁ, ÐÒÁ×ÉÌÁ ÂÙÌÉ ÉÚÍÅÎÅÎÙ + ÐÏ ÒÅÛÅÎÉÀ +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. âÙÌÉ ÏÔÍÅÎÅÎÙ ÐÒÁ×ÉÌÁ II.6-II.7 + + +

      I. þÔÏ ÍÏÖÎÏ

      +
        +
      1. ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
      2. áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
      3. óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
      4. +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
      + +

      II. þÔÏ ÎÅÌØÚÑ

      + +
        + +
      1. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
      2. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
      3. éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
      4. úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
      5. úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
      6. ÷ Livejournal.com (LJ) ÅÓÔØ ÎÅÓËÏÌØËÏ ÓÏÔÅÎ ÔÙÓÑÞ +ÒÕÓÓËÏÑÚÙÞÎÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ. ÷Ï ÉÚÂÅÖÁÎÉÅ ÐÕÔÁÎÉÃÙ, +ÎÁÍÅÒÅÎÎÏÇÏ ÓÁÍÏÚ×ÁÎÓÔ×Á É ÚÁÈ×ÁÔÁ ÉÍÅÎ, ÍÙ ÚÁËÒÅÐÌÑÅÍ ÚÁ +ËÁÖÄÙÍ ÒÕÓÓËÏÑÚÙÞÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÅÍ LJ, ÓÏÚÄÁÎÎÙÍ +ÄÏ ÉÀÌÑ 2005 ÇÏÄÁ, ÐÒÁ×Ï ÐÉÓÁÔØ ÐÏÄ ÔÅÍ ÖÅ ÉÍÅÎÅÍ × × LJR. + +
      7. ðÒÉ ÓÏÚÄÁÎÉÉ ÎÏ×ÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ × LJR ÐÒÏ×ÅÒØÔÅ, +ÐÏÖÁÌÕÊÓÔÁ, ÎÅÔ ÌÉ ÐÏÄ ÔÁËÉÍ ÖÅ ÎÉËÏÍ ÒÕÓÓËÏÑÚÙÞÎÏÇÏ +ÐÏÌØÚÏ×ÁÔÅÌÑ × LJ. åÓÌÉ ÅÓÔØ ÔÁËÏÊ ÐÏÌØÚÏ×ÁÔÅÌØ, ÓÏÚÄÁÎÎÙÊ ÄÏ +ÉÀÌÑ 2005 ÇÏÄÁ, É ÏÎ ÚÁÔÒÅÂÕÅÔ ÔÏ ÖÅ ÓÁÍÏÅ ÉÍÑ × LJR, ðÏÐÅÞÉÔÅÌØÓËÉÊ +óÏ×ÅÔ É ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÂÕÄÕÔ ×ÙÎÕÖÄÅÎÙ ÐÏÍÅÎÑÔØ ×ÁÛÅ ÉÍÑ ÎÁ ÄÒÕÇÏÅ, +ÐÏ ×ÁÛÅÍÕ ×ÙÂÏÒÕ. + +
      + +

      III. ðÒÏÃÅÄÕÒÁ

      + +
        +
      1. ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
      2. áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
      3. ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
      4. ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
      5. ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
      6. ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
      7. ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
      8. ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
      +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +
      + + diff --git a/local/htdocs/tos-2009-07-12.html b/local/htdocs/tos-2009-07-12.html new file mode 100755 index 0000000..214ee07 --- /dev/null +++ b/local/htdocs/tos-2009-07-12.html @@ -0,0 +1,130 @@ + + ToS + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +

      +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org)

      +

      ×ÅÒÓÉÑ 1.1 (obsolete since 12.07.2009)

      + + +

      I. þÔÏ ÍÏÖÎÏ

      +
        +
      1. ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
      2. áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
      3. óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
      4. +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
      + +

      II. þÔÏ ÎÅÌØÚÑ

      + +
        + +
      1. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
      2. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
      3. éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
      4. úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
      5. úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
      + +

      III. ðÒÏÃÅÄÕÒÁ

      + +
        +
      1. ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
      2. áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
      3. ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
      4. ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
      5. ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
      6. ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
      7. ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
      8. ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
      +

      + ÷ ÍÁÅ 2006 ÇÏÄÁ, ÐÒÁ×ÉÌÁ ÂÙÌÉ ÉÚÍÅÎÅÎÙ + ÐÏ ÒÅÛÅÎÉÀ +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. + +

      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +
      + + \ No newline at end of file diff --git a/local/htdocs/tos-2013-02-11.html b/local/htdocs/tos-2013-02-11.html new file mode 100755 index 0000000..564cff6 --- /dev/null +++ b/local/htdocs/tos-2013-02-11.html @@ -0,0 +1,139 @@ + + ToS + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +

      +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org)

      +

      ×ÅÒÓÉÑ 1.2 (obsolete since 11.02.2013)

      + + +

      I. þÔÏ ÍÏÖÎÏ

      +
        +
      1. ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
      2. áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
      3. óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
      4. +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
      + +

      II. þÔÏ ÎÅÌØÚÑ

      + +
        + +
      1. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
      2. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
      3. éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
      4. á×ÔÏÍÁÔÉÚÉÒÏ×ÁÎÎÙÊ ÍÁÓÓÏ×ÙÊ ÐÏÓÔÉÎÇ ÐÏ +ÞÅÔÙÒÅÍ ÉÌÉ ÂÏÌØÛÅ ÂÌÏÇ-ÒÅÓÕÒÓÁÍ, ×ËÌÀÞÁÑ LJR, +ÐÒÉÒÁ×ÎÉ×ÁÅÔÓÑ Ë ËÏÍÍÅÒÞÅÓËÏÍÕ ÕÐÏÔÒÅÂÌÅÎÉÀ +ÓÅÒ×ÅÒÁ, É ÐÒÅÓÌÅÄÕÅÔÓÑ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ ÎÁÒÁ×ÎÅ +ÓÏ ÓÐÁÍÏÍ, ËÒÏÍÅ ÓÌÕÞÁÅ×, ËÏÇÄÁ ÎÁ ÜÔÏ ÐÏÌÕÞÅÎÏ +ÒÁÚÒÅÛÅÎÉÅ ÏÔ ÁÄÍÉÎÉÓÔÒÁÃÉÉ + +
      5. úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
      6. úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
      + +

      III. ðÒÏÃÅÄÕÒÁ

      + +
        +
      1. ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
      2. áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
      3. ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
      4. ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
      5. ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
      6. ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
      7. ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
      8. ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. +
      +

      + ðÒÅÄÙÄÕÝÉÅ ×ÅÒÓÉÉ ÐÒÁ×ÉÌ: +

      + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +
      + + diff --git a/local/htdocs/tos.html b/local/htdocs/tos.html new file mode 100755 index 0000000..e45af6d --- /dev/null +++ b/local/htdocs/tos.html @@ -0,0 +1,151 @@ + + ToS + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +

      +ðÒÁ×ÉÌÁ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ LJR (lj.rossia.org)

      +

      ×ÅÒÓÉÑ 1.3 (ÄÅÊÓÔ×ÕÀÝÁÑ)

      + + +

      I. þÔÏ ÍÏÖÎÏ

      +
        +
      1. ÷ ÃÅÌÑÈ ÐÏÄÄÅÒÖËÉ Ó×ÏÂÏÄÙ ÓÌÏ×Á, +ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ, ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÓÅÒ×ÅÒ +LJR ÐÒÅÄÏÓÔÁ×ÌÑÅÔ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÌÉÞÎÏÅ ×ÅÂ-ÐÒÏÓÔÒÁÎÓÔ×Ï ÄÌÑ +×ÅÄÅÎÉÑ ÄÎÅ×ÎÉËÁ (×ÅÂÌÏÇÁ). + +
      2. áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÄÅÊÓÔ×Ï×ÁÔØ × +ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó õÓÔÁ×ÏÍ É +òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ. +úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR ÚÁÑ×ÌÅÎÎÙÈ +ÐÒÉÎÃÉÐÏ× ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ + +
      3. óÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÄÎÅ×ÎÉËÏ× +Ñ×ÌÑÅÔÓÑ ÌÉÞÎÙÍ ÄÅÌÏÍ ËÁÖÄÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ. +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÏÂÑÚÕÅÔÓÑ ÂÅÚ ËÒÁÊÎÅÊ ÎÕÖÄÙ ÎÅ ÏÇÒÁÎÉÞÉ×ÁÔØ +ÄÏÓÔÕÐ Ë ÄÎÅ×ÎÉËÁÍ É ÎÅ ÍÅÎÑÔØ ÞÕÖÉÈ ÚÁÐÉÓÅÊ. + +
      4. +áÄÍÉÎÉÓÔÒÁÃÉÑ lj.rossia.org ÎÅ ÎÅÓÅÔ ÎÉËÁËÏÊ +ÏÔ×ÅÔÓÔ×ÅÎÎÏÓÔÉ ÚÁ ÓÏÄÅÒÖÁÎÉÅ ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÍÁÔÅÒÉÁÌÏ×. +
      + +

      II. þÔÏ ÎÅÌØÚÑ

      + +
        + +
      1. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR +Ó ÃÅÌØÀ ÎÁÒÕÛÅÎÉÑ ÚÁËÏÎÏ× òæ É ÉÈ ÍÅÓÔÁ ÐÒÏÖÉ×ÁÎÉÑ. + +
      2. ðÏÌØÚÏ×ÁÔÅÌÉ ÏÂÑÚÕÀÔÓÑ ÎÅ ÉÓÐÏÌØÚÏ×ÁÔØ LJR × +ËÏÍÍÅÒÞÅÓËÉÈ ÃÅÌÑÈ (ËÒÏÍÅ ÓÌÕÞÁÅ×, ÓÏÇÌÁÓÏ×ÁÎÎÙÈ Ó +ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR). + +
      3. éÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÑ ÎÁ×ÑÚÞÉ×ÙÈ +ÒÅËÌÁÍÎÙÈ ÓÏÏÂÝÅÎÉÊ (ÓÐÁÍÁ) ÎÁËÁÚÙ×ÁÅÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ +ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ. óÐÁÍ ÔÁËÖÅ ÕÄÁÌÑÅÔÓÑ, ÂÅÚ +ÐÒÅÄÕÐÒÅÖÄÅÎÉÊ. + +
      4. á×ÔÏÍÁÔÉÚÉÒÏ×ÁÎÎÙÊ ÍÁÓÓÏ×ÙÊ ÐÏÓÔÉÎÇ ÐÏ +ÞÅÔÙÒÅÍ ÉÌÉ ÂÏÌØÛÅ ÂÌÏÇ-ÒÅÓÕÒÓÁÍ, ×ËÌÀÞÁÑ LJR, +ÐÒÉÒÁ×ÎÉ×ÁÅÔÓÑ Ë ËÏÍÍÅÒÞÅÓËÏÍÕ ÕÐÏÔÒÅÂÌÅÎÉÀ +ÓÅÒ×ÅÒÁ, É ÐÒÅÓÌÅÄÕÅÔÓÑ ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ ÎÁÒÁ×ÎÅ +ÓÏ ÓÐÁÍÏÍ, ËÒÏÍÅ ÓÌÕÞÁÅ×, ËÏÇÄÁ ÎÁ ÜÔÏ ÐÏÌÕÞÅÎÏ +ÒÁÚÒÅÛÅÎÉÅ ÏÔ ÁÄÍÉÎÉÓÔÒÁÃÉÉ + +
      5. úÁÐÒÅÝÁÅÔÓÑ ÉÓÐÏÌØÚÏ×ÁÎÉÅ LJR ÄÌÑ ×ÚÌÏÍÁ ÓÁÊÔÏ×, +ÒÁÓÐÒÏÓÔÒÁÎÅÎÉÅ ÞÁÓÔÎÏÊ ÉÎÆÏÒÍÁÃÉÉ, ËÏÔÏÒÁÑ ÍÏÖÅÔ ÂÙÔØ +ÉÓÐÏÌØÚÏ×ÁÎÁ ÄÌÑ +×ÚÌÏÍÁ ÓÁÊÔÏ×, Á ÔÁËÖÅ ÐÕÂÌÉËÁÃÉÑ ÓÏÏÂÝÅÎÉÊ, +ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ ÌÀÄÑÍ ÐÏÌØÚÏ×ÁÎÉÅ LJR (ÒÁÚÌÉÞÎÙÈ +ÚÌÏ×ÒÅÄÎÙÈ ÓËÒÉÐÔÏ× É ÐÒÏÞÅÇÏ). ðÏÄÏÂÎÙÅ ÎÁÒÕÛÅÎÉÑ +ÎÁËÁÚÙ×ÁÀÔÓÑ ÎÅÍÅÄÌÅÎÎÙÍ ÚÁËÒÙÔÉÅÍ ÄÏÓÔÕÐÁ É ÕÄÁÌÅÎÉÅÍ +ÚÌÏ×ÒÅÄÎÏÇÏ ÓÏÏÂÝÅÎÉÑ. + +
      6. úÁÐÒÅÝÁÅÔÓÑ ÐÕÂÌÉËÏ×ÁÔØ ÔÅÌÅÆÏÎÙ, ÁÄÒÅÓÁ ÞÁÓÔÎÙÈ ÌÉÃ, +ÅÓÌÉ ÐÏÓÌÅÄÎÉÅ ÎÅ ÄÁ×ÁÌÉ ÒÁÚÒÅÛÅÎÉÑ ÎÁ ÐÕÂÌÉËÁÃÉÀ. +åÓÌÉ ÜÔÁ ÉÎÆÏÒÍÁÃÉÑ - ÓËÁÖÅÍ, ÎÏÍÅÒ ÄÏÍÁÛÎÅÇÏ ÔÅÌÅÆÏÎÁ +ÇÒÁÖÄÁÎÉÎÁ - ×ÚÑÔÁ ÉÚ ÏÔËÒÙÔÙÈ ÉÓÔÏÞÎÉËÏ×, ÇÄÅ ÏÐÕÂÌÉËÏ×ÁÎÁ +Ó ÒÁÚÒÅÛÅÎÉÑ ÐÏÓÌÅÄÎÅÇÏ, ÐÒÉ ÒÅÐÕÂÌÉËÁÃÉÉ ÎÅÏÂÈÏÄÉÍÏ +ÕËÁÚÁÔØ ÓÓÙÌËÕ ÎÁ ÉÓÔÏÞÎÉË. + +
      + +

      III. ðÒÏÃÅÄÕÒÁ

      + +
        +
      1. ÷ÓÅ ÄÉÓÃÉÐÌÉÎÁÒÎÙÅ ×ÏÐÒÏÓÙ ÒÅÛÁÀÔÓÑ ÇÌÁÓÎÏ +É ÐÕÂÌÉÞÎÏ. + +
      2. áÎÏÎÉÍÎÙÅ ÖÁÌÏÂÙ ÎÅ ÐÒÉÎÉÍÁÀÔÓÑ. +ëÁÖÄÁÑ ÖÁÌÏÂÁ ÐÕÂÌÉËÕÅÔÓÑ × + ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ +ÍÅÓÔÅ. + +
      3. ðÏ ËÁÖÄÏÍÕ ÆÁËÔÕ ÚÁËÒÙÔÉÑ +ÄÎÅ×ÎÉËÏ× É ÏÔËÌÀÞÅÎÉÑ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, +ÓÏÔÒÕÄÎÉËÉ ÁÄÍÉÎÉÓÔÒÁÃÉÉ, ÏÓÕÝÅÓÔ×É×ÛÉÅ +ÄÉÓÃÉÐÌÉÎÁÒÎÕÀ ÁËÃÉÀ, ÐÕÂÌÉËÕÀÔ ËÒÁÔËÉÊ +ÏÔÞÅÔ × ÏÔ×ÅÄÅÎÎÏÍ ÄÌÑ ÜÔÏÇÏ ÍÅÓÔÅ. + +
      4. ÷ ÓÌÕÞÁÑÈ ÒÁÚÍÅÝÅÎÉÑ ÓÐÁÍÁ, ÈÁËÅÒÓËÉÈ ÁÔÁË +É ÐÕÂÌÉËÁÃÉÉ ÓÏÏÂÝÅÎÉÊ, ËÏÔÏÒÙÅ ÍÏÇÕÔ ÂÙÔØ ÐÒÉÞÉÎÏÊ +ÓÍÅÒÔÉ ÉÌÉ ÕÝÅÒÂÁ ÚÄÏÒÏ×ØÀ ËÏÎËÒÅÔÎÙÈ ÌÉÃ, +ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÔÉÒÁÅÔ ÎÁÒÕÛÉÔÅÌÅÊ ÎÅÍÅÄÌÅÎÎÏ. + +
      5. ÷ ÓÌÕÞÁÅ ÎÅÎÁÍÅÒÅÎÎÏÇÏ ÒÁÚÍÅÝÅÎÉÑ +ËÕÓËÏ× HTML-ËÏÄÁ, ÚÁÔÒÕÄÎÑÀÝÉÈ ÄÒÕÇÉÍ +ÐÏÌØÚÏ×ÁÎÉÅ LJR, ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÍÏÖÅÔ +ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ Ï ×ÒÅÍÅÎÎÏÍ ÚÁÍÏÒÁÖÉ×ÁÎÉÉ +ÐÏÌØÚÏ×ÁÔÅÌÑ, ÒÁÚÍÅÓÔÉ×ÛÅÇÏ ÚÌÏ×ÒÅÄÎÙÊ ËÏÄ. + +
      6. ÷ ÄÒÕÇÉÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ +É ÐÏÌØÚÏ×ÁÔÅÌØÓËÉÈ ÖÁÌÏÂ, ÒÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔ +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
      7. ÷ ÌÀÂÙÈ ÓÌÕÞÁÑÈ ÎÁÒÕÛÅÎÉÑ ÐÒÁ×ÉÌ, ÏÂÝÅÐÒÉÎÑÔÙÈ +ÜÔÉÞÅÓËÉÈ ÎÏÒÍ ÉÌÉ ÚÁËÏÎÁ òæ, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ, +ÒÁÓÓÍÁÔÒÉ×ÁÀÝÉÊ ÖÁÌÏÂÙ × ÕÓÔÁÎÏ×ÌÅÎÎÏÍ ÐÏÒÑÄËÅ. + +
      8. ÷ ÓÌÕÞÁÑÈ ËÏÎÆÌÉËÔÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ +Ó ÁÄÍÉÎÉÓÔÒÁÃÉÅÊ LJR, ÏËÏÎÞÁÔÅÌØÎÙÍ ÁÒÂÉÔÒÏÍ +Ñ×ÌÑÅÔÓÑ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ. + +
      9. +ó ÎÏÑÂÒÑ 2012 ÇÏÄÁ ÎÁ ÔÅÒÒÉÔÏÒÉÉ òæ ÄÅÊÓÔ×ÕÅÔ ÚÁËÏÎ +Ï ÃÅÎÚÕÒÅ, ÐÒÏÔÉ×ÏÒÅÞÁÝÉÊ ËÏÎÓÔÉÔÕÃÉÉ É ÚÄÒÁ×ÏÍÕ +ÓÍÙÓÌÕ ("ÒÅÅÓÔÒ ÚÁÐÒÅÝÅÎÎÙÈ ÓÁÊÔÏ×"). äÏ ÏÔÍÅÎÙ +ÐÕÔÉÎÓËÏÇÏ ÁÎÔÉËÏÎÓÔÉÔÕÃÉÏÎÎÏÇÏ ÚÁËÏÎÏÄÁÔÅÌØÓÔ×Á +Ï ÃÅÎÚÕÒÅ ÉÎÔÅÒÎÅÔÁ, ÁÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÎÁÄÅÌÑÅÔÓÑ ÐÒÁ×ÏÍ +ÄÏÂÁ×ÌÑÔØ × ÓÔÏÐ-ÌÉÓÔ ÓÅÒ×ÅÒÁ ÓÔÒÁÎÉÃÙ, ÐÏÐÁ×ÛÉÅ × +"ÒÅÅÓÔÒ ÚÁÐÒÅÝÅÎÎÙÈ ÓÁÊÔÏ×". óÔÒÁÎÉÃÙ, ÐÏÐÁ×ÛÉÅ × +ÓÔÏÐ-ÌÉÓÔ, ÚÁËÒÙÔÙ ÄÌÑ IP-ÁÄÒÅÓÏ× òæ. + +
      +

      + ðÒÅÄÙÄÕÝÉÅ ×ÅÒÓÉÉ ÐÒÁ×ÉÌ: +

      + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +
      + + diff --git a/local/htdocs/translatetoljruser.bml b/local/htdocs/translatetoljruser.bml new file mode 100755 index 0000000..88845c9 --- /dev/null +++ b/local/htdocs/translatetoljruser.bml @@ -0,0 +1,82 @@ + +body<= +do("update logtext2 set subject = replace(subject, \'" . $ftext . "\', \'" . $rtext . "\') where journalid = ? and subject like \'%\' + \'" . $ftext . "\' + \'%\'", undef, $id); + +# Process entry bodies in own journal + + $dbh->do("update logtext2 set event = replace(event, \'" . $ftext . "\', \'" . $rtext . "\') where journalid = ? and event like \'%\' + \'" . $ftext . "\' + \'%\'", undef, $id); + +# Process entry subject lines in communities + + $dbh->do("update logtext2 left join log2 on logtext2.journalid=log2.journalid and logtext2.jitemid=log2.jitemid left join community on logtext2.journalid=community.userid set subject = replace(subject, \'" . $ftext . "\', \'" . $rtext . "\') where journalid = ? and subject like \'%\' + \'" . $ftext . "\' + \'%\'", undef, $id); + +# Process entry bodies in own journal + + $dbh->do("update logtext2 set event = replace(event, \'" . $ftext . "\', \'" . $rtext . "\') where journalid = ? and event like \'%\' + \'" . $ftext . "\' + \'%\'", undef, $id); + + + $dbh->do("update talktext2 left join talk2 on talktext2.journalid=talk2.journalid and talktext2.jtalkid=talk2.jtalkid set talktext2.body = replace(talktext2.body, \'" . $ftext . "\', \'" . $rtext . "\') where talk2.posterid = ? and talktext2.body like \'%\' + \'" . $ftext . "\' + \'%\'", undef, $id); + + +return 1; +} + + use strict; + use vars qw(%GET %POST); + + my $remote = LJ::get_remote(); + return LJ::bad_input($ML{'error.noremote'}) + unless $remote; + + my $authas = $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + my $id = $remote->{'userid'}; + + # process form submission + if (LJ::did_post()) { + + my $res = process($id); + + # error updating? + return "\n" + unless $res; + + # success + return "\n"; +} + + # update form + + my $ret; + + $ret .= "

      Мы ввели новую ÑиÑтему Ñ‚Ñгов lj user и lj comm, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет легко различать пользователей разных Ñайтов и уÑтранÑет путаницу. Ðо еÑÑ‚ÑŒ одно "но": Ñ‚Ñг lj user без дополнительного аргумента site теперь означает Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ www.livejournal.com - а пользователи lj.rossia.org обозначаютÑÑ Ñ‚Ñгом ljr user. ЕÑли вы уже неоднократно иÑпользовали в Ñвоих запиÑÑÑ… lj user, Ð¸Ð¼ÐµÑ Ð² виду пользователей lj.rossia.org, здеÑÑŒ вы можете автоматичеÑки поправить вÑе Ñвои запиÑи по новым правилам.

      Имейте в виду, что Ñто опаÑÐ½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ: вы доверÑете программе делать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² Ñвоих запиÑÑÑ… в базе данных. Конечно, мы теÑтировали Ñту программу, но Ð»ÑŽÐ±Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° вÑе равно глупаÑ. ДейÑтвительно ли вы Ñтого хотите? ЕÑли вы не абÑолютно уверены, лучше не надо.

      ТехничеÑки, программа делает Ñледующее: находит вÑе ваши запиÑи (Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð·Ð°Ð¿Ð¸Ñи в ÑообщеÑтва), менÑет \"<lj \" на \"<ljr \", потом делает то же в заголовках запиÑей и в оÑтавленных вами где бы то ни было комментариÑÑ….

      Ð’Ñ‹ ÑÐµÐ¹Ñ‡Ð°Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ð°ÐµÑ‚Ðµ как пользователь "; + + $ret .= $remote->{'user'}; + + $ret .= "\n"; + + $ret .= "

      \n"; + $ret .= ""; + $ret .= "
      \n\n"; + + return $ret; +} +_code?> +<=body +page?> + diff --git a/local/htdocs/update.bml b/local/htdocs/update.bml new file mode 100755 index 0000000..ea392cd --- /dev/null +++ b/local/htdocs/update.bml @@ -0,0 +1,411 @@ +{'title'}; + my $head = \$_[1]->{'head'}; + my $body = \$_[1]->{'body'}; + my $bodyopts = \$_[1]->{'bodyopts'}; + + $$title = $ML{'.title'}; + + # server down? + if ($LJ::SERVER_DOWN) { + $$body = LJ::server_down_html(); + return; + } + + LJ::set_active_crumb("update"); + + # invalid text input? + unless (LJ::text_in(\%POST)) { + BML::set_status(403); # 403 Forbidden + $$body = ""; + return; + } + + # get remote and see if they can post right now + my $remote = LJ::get_remote(); + + # Errors that are unlikely to change between starting + # to compose an entry and submitting it. + if ($remote) { + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + if ($remote->identity) { + BML::set_status(403); # 403 Forbidden + $$title = "Sorry"; + $$body = "Non-$LJ::SITENAME users can't post, as they don't actually have journals here. You can leave comments in other journals, though."; + return; + } + + if (! LJ::get_cap($remote, "can_post")) { + BML::set_status(403); # 403 Forbidden + $$title = "Can't Post"; + $$body = $LJ::MSG_NO_POST || $ML{'.error.cantpost'}; + return; + } + + if (LJ::get_cap($remote, "disable_can_post")) { + unless (LJ::run_hook("update.bml_disable_can_post", { + title => $title, body => $body, + })) { + #BML::set_status(403); # 403 Forbidden + $$title = $ML{'.error.disabled.title'}; + $$body = $ML{'.error.disabled'}; + } + return; + } + } + + my %res = (); + + # see if we need to do any transformations + LJ::run_hooks("transform_update_$POST{transform}", \%GET, \%POST) if $POST{transform}; + + # Set up form default values: + my @time = localtime(time); + my ($year, $mon, $mday, $hour, $min) = ($time[5] + 1900, + sprintf("%02d", $time[4] + 1), + sprintf("%02d", $time[3]), + $time[2], + sprintf("%02d", $time[1])); + my $subject = $POST{'subject'} || $GET{'subject'}; + my $event = $POST{'event'} || $GET{'event'}; + + ### define some bools with common logic ### + my $did_post = LJ::did_post() && !$POST{transform}; # transforms aren't posts + my $user_is_remote = $remote && $remote->{'user'} eq $POST{'user'}; # user is remote + my $auth_as_remote = $remote && (! $GET{'altlogin'} || $user_is_remote); # auth as remote + my $auth_missing = $POST{'user'} && + ! $POST{'password'} && + ! $user_is_remote && + ! $POST{'response'}; # user w/o password + + # which authentication option do we display by default? + my $altlogin_display = 'none'; + my $remotelogin_display = 'none'; + if ($auth_as_remote) { + $remotelogin_display = 'table-row'; + } else { + $altlogin_display = 'table-row'; + } + + # Check for errors, store in hash to render later + my $errors; my $onload = "shift_contents(); "; + my $showform = $POST{'showform'} || $auth_missing; # show entry form + my $preview = $POST{'action:preview'}; + + # are we spellchecking before we post? + my $did_spellcheck; my $spellcheck_html; + if ($LJ::SPELLER && $POST{'action:spellcheck'}) { + $did_spellcheck++; + my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, + 'color' => '', }; + my $event = LJ::ehtml($event); + $spellcheck_html = $s->check_html(\$event); + $spellcheck_html = "" unless $spellcheck_html ne ""; + $onload .= "pageload(0); "; # js fill-in off + + my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, \%POST); + ($year, $mon, $mday) = split( /\D/, $date); + $hour = $POST{'hour'}; + $min = $POST{'min'}; + } else { + $onload .= "pageload(1); "; # js fill-in on + + my @time = localtime(time); + $year = $time[5] + 1900; + $mon = sprintf("%02d", $time[4] + 1); + $mday = sprintf("%02d", $time[3]); + $hour = $time[2]; + $min = sprintf("%02d", $time[1]); + } + + # richtext + # 'switched_rte_on' is only set when the user first enables rte. We do this in a POST + # so any pre-existing text in the event and subject fields aren't lost when going to RTE. + # 'rich' is used to keep RTE mode enabled between pages, such as spellchecks. + # The $GET{'rich'} is simply for user bookmarking / faq linking convenience. + my $enabled_rte = $POST{'switched_rte_on'}; + my $richtext = 1 if $GET{rich} || $POST{rich} || + ($enabled_rte && ! $spellcheck_html && ! $preview); + $$bodyopts .= "onunload=\"save_entry();\" " if $richtext; + + my $print_entry_form = sub { + my $opts = shift; + + # authentication box + my $auth = ''; + + if ($remote) { # so lynx won't show this + $auth .= "$ML{'.auth.poster'}"; + $auth .= BML::ml(".loggedinas", {'user' => $remote->{'user'}, 'altget' => "?altlogin=1" }); + $auth .= "\n"; + } + + # table with username/password fields + $auth .= "\n"; + $auth .= "" . BML::ml('Username') . ":"; + $auth .= "" . LJ::html_text({ 'name' => 'user', 'size' => '15', 'maxlength' => '15', + 'value' => $POST{'user'} || $GET{'user'} }); + $auth .= "\n"; + $auth .= ""; + $auth .= "" . BML::ml('Password') . ":"; + $auth .= "" . LJ::html_text({ 'type' => 'password', 'name' => 'password', + 'size' => '15', 'maxlength' => '30' }); + # posted with a user, but no password + if ($did_post && $auth_missing) { + $auth .= "
      "; + } + $auth .= ""; + + # if they submit the form and are spellchecking, remember + # their settings from the GET requests + my $getextra; + $getextra .= "altlogin=1&" if $GET{'altlogin'}; + $getextra .= "rich=1&" if $richtext; + chop $getextra; + $getextra = "?$getextra" if $getextra; + + my $entry = { + 'mode' => "update", + 'auth_as_remote' => $auth_as_remote, + 'subject' => $subject, + 'event' => $event, + 'datetime' => "$year-$mon-$mday $hour:$min", + 'usejournal' => $POST{'usejournal'} || $GET{'usejournal'}, + 'auth' => $auth, + 'remote' => $remote, + 'spellcheck_html' => $spellcheck_html, + 'clientversion' => "WebUpdate/2.0.0", + 'richtext' => 1, + 'richtext_on' => $richtext, + }; + + if ($did_post) { + $entry->{$_} = $POST{$_} foreach keys %POST; + } + + if (LJ::isu($remote) && (!$did_post || $did_spellcheck) && $remote->readonly) { + $$body .= "
      "", + 'a_close' => ""} + ); + } else { + $$body .= BML::ml('.rowarn', { + 'a_open' => '', + 'a_close' => ''} + ); + } + + $$body .= " warningbar?>
      "; + } + + $$body .= "
      "; + + if ($opts->{require_tos}){ + $$body .= LJ::tosagree_html('update', $POST{agree_tos}, $errors->{require_tos}); + } + + $$body .= LJ::entry_form($entry, \$$head, \$onload, $errors); + $$body .= "
      "; + + $$bodyopts .= "onload=\"$onload\" onresize=\"shift_contents();\" "; + + return; + }; + + if ($did_post && !$did_spellcheck && !$showform && !$enabled_rte && !$preview ) { + + # what's our authentication scheme for subsequent protocol actions? + my $flags = {}; + my ($u, $user); + + if ($POST{'user'} && # user argument given + ! $user_is_remote && # user != remote + (!$remote || $GET{'altlogin'})) { # user has clicked alt auth + + $user = $POST{'user'}; + $u = LJ::load_user($user); + + # Verify entered password, if it is present. + my $ok; + if ($POST{response}) { + $ok = LJ::challenge_check_login($u, $POST{chal}, $POST{response}); + } else { # js disabled, fallback to plaintext + $ok = LJ::auth_okay($u, $POST{password}); + } + $flags = { 'noauth' => 1, 'u' => $u } if $ok; + + } elsif ($remote && LJ::check_referer()) { # assume remote if we have it + $flags = { 'noauth' => 1, 'u' => $remote }; + $user = $remote->{'user'}; + $u = $remote; + } + + if ($u && ! $u->tosagree_verify) { + if ($POST{agree_tos}) { + my $err = ""; + unless ($u->tosagree_set(\$err)) { + # error + BML::set_status(403); # 403 Forbidden + $errors->{require_tos} = $err; + $print_entry_form->({ require_tos => 1 }); + return; + } + # successfully set + } else { + BML::set_status(403); # 403 Forbidden + $errors->{require_tos} = $ML{'tos.error'}; + $print_entry_form->({ require_tos => 1 }); + return; + } + } + + # Check if the account they're posting to is read-only + my $uj = $POST{'usejournal'} ? LJ::load_user($POST{'usejournal'}) : $u; + if ($uj && $uj->readonly) { + # Tell the user they can't post since read only + BML::set_status(403); # 403 Forbidden + $$body .= "$ML{'.error.update'} "; + $$body .= $LJ::MSG_READONLY_USER; + $$body .= " errorbar?>
      "; + + $print_entry_form->(); + return + } + + # do a login action + my $login_message; + { + # build a clientversion string + my $clientversion = "Web/2.0.0"; + $clientversion .= 's' if $did_spellcheck; + + # build a request object + my %req = ( 'mode' => 'login', + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $clientversion, + 'user' => $user, + ); + + my %res; + LJ::do_request(\%req, \%res, $flags); + + # error logging in ? + unless ($res{'success'} eq 'OK') { + $errors->{'auth'} = $ML{'.error.login'} . " " . LJ::ehtml($res{'errmsg'}); + } + + # server login message for user? + $login_message = LJ::auto_linkify(LJ::ehtml($res{'message'})) + if $res{'message'}; + } + # any messages from the server? + if ($login_message) { + $$body .= "$ML{'.loggingin'} $ML{'.servermsg'} p?>
      $login_message
      "; + } + + my %req = ( 'mode' => 'postevent', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $user, + 'password' => $POST{'password'}, + 'usejournal' => $POST{'usejournal'}, + ); + + LJ::entry_form_decode(\%req, \%POST); + if ($req{'event'} eq "") { + $errors->{'entry'} = "Must provide entry text"; + } + + my %res; + LJ::do_request(\%req, \%res, $flags); + + if (!$errors) { + # examine response + my $update_message; + if ($res{'success'} eq "OK" && $res{'message'}) { + $update_message = LJ::auto_linkify(LJ::ehtml($res{'message'})); + } + + # report results + $$body .= "$ML{'.updating'} "; + + if ($res{'success'} ne 'OK') { + # update failed? + BML::set_status(403); # 403 Forbidden + $$body .= "
      $ML{'.error.update'} "; + $$body .= LJ::ehtml($res{'errmsg'}) . " errorbar?>"; + $$body .= "
      p?>"; + } else { + # short bail if this was posted moderated or some other special case (no itemid but a message) + if (!defined $res{itemid} && $res{message}) { + BML::set_status(403); # 403 Forbidden + $$body .= "
      $res{message} p?>"; + return; + } + + # update success + my $ju; + if ($POST{'usejournal'}) { + $ju = LJ::load_user($POST{'usejournal'}); # posting as community + } elsif ($user) { + $ju = LJ::load_user($user); # posting not as user from form + } else { + $ju = $remote; # posting as remote + }; + $$body .= BML::ml(".update.success", { 'uri' => LJ::journal_base($ju) . "/" }); + my $juser = $ju->{'user'}; + my ($itemid, $anum) = ($res{'itemid'}, $res{'anum'}); + my $itemlink = LJ::item_link($ju, $itemid, $anum); + $itemid = $itemid * 256 + $anum; + $$body .= " p?>"; + return; + } + } + } + + $print_entry_form->(); + return; +} + +_code?> {'title'}; _code?> +body=> {'body'}; _code?> +bodyopts=>{'bodyopts'}; _code?> +head<= + + +{'head'}; + $ret .= ""; + $ret .= (! $LJ::REQ_HEAD_HAS{'chalresp_js'}++) ? $LJ::COMMON_CODE{'chalresp_js'} : ""; + return $ret; +} +_code?> + +<=head +page?> +lib: LJ::SpellCheck +link: htdocs/users, htdocs/download/index.bml, htdocs/moodlist.bml +link: htdocs/update.bml, htdocs/lostinfo.bml, htdocs/support/faqbrowse.bml +link: htdocs/allpics.bml +post: htdocs/update.bml + _c?> diff --git a/local/htdocs/userinfo.bml b/local/htdocs/userinfo.bml new file mode 100755 index 0000000..85b7789 --- /dev/null +++ b/local/htdocs/userinfo.bml @@ -0,0 +1,1083 @@ +"; + # $body .= LJ::run_hook("bot_director", $pre, $post); + + if ($LJ::SERVER_DOWN) { + $title = $ML{'Sorry'}; + $body = LJ::server_down_html(); + return; + } + + my $MAX_FRIENDS_SHOW = 500; + my $MAX_FRIENDOF_SHOW = 150; + + my $remote = LJ::get_remote(); + if ($GET{'user'} eq "" && !$remote) { + $body = ""; + return; + } + + my $sth; + my %countries = (); + my %states = (); + LJ::load_codes({ "country" => \%countries, "state" => \%states }); + + my $error = sub { + my $e = shift; + $body = ""; + return; + }; + + my $user = LJ::canonical_username($GET{'user'}); + if ($GET{'user'} && ! $user) { + $body = $ML{'.error.malfname'}; + return; + } + if ($user eq "" && $remote) { + $user = $remote->{'user'}; + } + + my $dbr = LJ::get_db_reader(); + return $error->($ML{'error.nodb'}) unless $dbr; + + my $userid = $GET{'userid'}; + my $u; + $userid += 0; + + { + if ($userid) { + $u = LJ::load_userid($userid); + } else { + $u = LJ::load_user($user); + } + + return $error->($ML{'.label.reqfinduser'}) + if $userid && ! LJ::check_priv($remote, "finduser") && ! ($GET{t} eq "I" && $u && $u->{journaltype} eq "I"); + + # fix accidentally broken ext_nnnn URLs for identity users + if ($u->{journaltype} eq "I" && ! $userid && $u->{user} !~ /^imp.*/ ) { + return BML::redirect("$LJ::SITEROOT/userinfo.bml?userid=$u->{'userid'}&t=I"); + } + + $user = $u->{'user'} if $u; + $userid = $u->{'userid'}+0 if $u; + + LJ::text_out(\$u->{'name'}) if $u; + if ($u && ($GET{'mode'} eq "full" || $u->{'journaltype'} eq "Y")) { + $sth = $dbr->prepare("SELECT timeupdate, timecreate, ". + "UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ". + "AS 'secondsold' FROM userusage ". + "WHERE userid=$userid"); + $sth->execute; + ($u->{'timeupdate'}, + $u->{'timecreate'}, + $u->{'secondsold'}) = $sth->fetchrow_array; + } + } + + unless ($u->{'userid'}) { + $title = $ML{'Error'}; + $body = "$user}) . " p?>"; + return; + } + + if ($LJ::LJR_FIF && $u->{'user'} eq $LJ::LJR_FIF) {$fif=1;} + + # account purged? + if ($u->{'statusvis'} eq "X") { + $title = $ML{'error.purged.title'}; + $body = ""; + BML::set_status(410); # 410 Gone + return; + } + + my $dbcr = LJ::get_cluster_reader($u); + return $error->($ML{'error.nodb'}) unless $dbcr; + + # option + my %hide_fo; # userid -> 1 + if ($LJ::HIDE_FRIENDOF_VIA_BAN) { + if (my $list = LJ::load_rel_user($u, 'B')) { + $hide_fo{$_} = 1 foreach @$list; + } + } + if ($LJ::LJR_FIF) { + $hide_fo{LJ::get_userid($LJ::LJR_FIF)} = 1; + } + + + my $remote_isowner = $remote && $remote->{'user'} eq $u->{'user'}; + my $remote_isfriend = LJ::is_friend($u, $remote); + my $com = $u->{'journaltype'} eq "C" ? 1 : 0; + my $extid = $u->{'journaltype'} eq "I" ? $u->identity : undef; + + my $synd; + if ($u->{'journaltype'} eq "Y") { + $synd = $dbr->selectrow_hashref("SELECT * FROM syndicated WHERE userid=$u->{'userid'}"); + } + my $dir = "users"; + + ### load user props. some don't apply to communities + { + my @props = qw(opt_whatemailshow country state city zip renamedto + journaltitle journalsubtitle public_key + url urlname opt_hidefriendofs dont_load_members + opt_showmutualfriends fb_num_pubpics); + unless ($com || $synd) { push @props, qw(aolim icq yahoo msn gender jabber); } + if ($synd) { push @props, qw(rssparseerror); } + if ($u->{'statusvis'} eq 'V') { push @props, qw(opt_blockrobots); } + LJ::run_hooks('userinfo_local_props', { + 'props' => \@props + }); + LJ::load_user_props($u, @props); + } + + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head .= LJ::robot_meta_tags(); + } + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'}) { + my $extra = $GET{'mode'} eq 'full' ? "&mode=full" : ''; + return BML::redirect("$LJ::SITEROOT/userinfo.bml?user=$u->{'renamedto'}$extra"); + } + + my %friends = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); + my %friendsof = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); + + if ($com) { + $title = $ML{'.title.communityinfo'}; + $dir = "community"; + } elsif ($synd) { + $title = $ML{'.title.syndicated'}; + $u->{'opt_whatemailshow'} = "N"; # don't show email + $friends{'load'} = $friends{'display'} = 0; + $friendsof{'load'} = 1; + } + + if ($extid) { + $windowtitle = "External identity profile"; + } else { + $windowtitle = "$u->{'user'} - $title"; + } + + $friends{'load'} = $friendsof{'load'} = 0 if $com && $u->{'dont_load_members'}; + + # do they have the viewall priv? + # there are no entries on this page, so we just check if they have any viewall, so viewsome + # applies here too. we can't see info they've hidden anyway, but we can see the page. + my $viewall = 0; + if ($GET{'viewall'} && LJ::check_priv($remote, "canview")) { + $viewall = LJ::check_priv($remote, 'canview', '*'); + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "userinfo: $u->{'user'}, statusvis: $u->{'statusvis'}"); + } else { + + if ($u->{'statusvis'} eq "S") { + $title = $ML{'error.suspended.title'}; + $body = " LJ::ljuser($user), + 'sitename' => $LJ::SITENAME }) . " p?>"; + BML::set_status(403); # 403 Forbidden + return; + } + if ($u->{'statusvis'} eq "D") { + $title = $ML{'error.deleted.title'}; + $body = "$user}) . " p?>"; + BML::set_status(404); # 404 Not Found + return; + } + } + + $user = $u->{'user'}; + $userid = $u->{'userid'}; + + $u->{'bio'} = LJ::get_bio($u); + LJ::text_out(\$u->{'bio'}); + + # arrayref of interests rows: [ intid, intname, intcount ] + my $intu = LJ::get_interests($u); + + my %remote_interest; + if ($remote && $remote->{'userid'} != $userid) { + if (my $rint = LJ::get_interests($remote, { justids => 1 })) { + $remote_interest{$_} = 1 foreach @$rint; + } + } + + if ($u->{'opt_hidefriendofs'} && ! $remote_isowner) { + # at this point, load should be on if viewall is on or if the user + # wants to show their mutual friends + $friendsof{'load'} = $u->{'opt_showmutualfriends'} || $viewall; + $friendsof{'display'} = $viewall; + } + + # Add metadata links to + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{'email'}); + $head .= "\n"; + $head .= "\n"; + $head .= "\n"; + $head .= "\n"; + + my @friends; + my $fr_res; + my %fr; + # TAG:FR:userinfo:loadfriends + if ($friends{'load'}) { + $fr_res = LJ::get_friends($u); + my @ids = keys %$fr_res; + $friends{'count'} = @ids; + unless ($fif) { + if (@ids > $MAX_FRIENDS_SHOW) { + @ids = splice(@ids, 0, $MAX_FRIENDS_SHOW); + } + } + LJ::load_userids_multiple([ map { $_ => \$fr{$_} } @ids ]); + push @friends, sort { $a->{user} cmp $b->{user} } values %fr; + $friends{'loaded'} = 1; + } + + my (@friend_of, @member_of, @mutual); + + # TAG:FR:userinfo:loadfriendofs + if ($friendsof{'load'}) { + # figure at most 50 people are not statusvis='V' *shrug* (this is lame pending the friend changes) + my @ids = grep { ! $hide_fo{$_} } LJ::get_friendofs($u); + unless ($fif) {$friendsof{'load_clipped'} = @ids > $LJ::MAX_FRIENDOF_LOAD;} + + my %fro; + LJ::load_userids_multiple([ map { $_ => \$fro{$_} } @ids ]); + + foreach my $ulocal (sort { $a->{'user'} cmp $b->{'user'} } values %fro) { + next unless $ulocal->{'statusvis'} eq 'V'; + if ($ulocal->{'journaltype'} eq 'P' || $ulocal->{'journaltype'} eq "I") { + if (!$com && $u->{'opt_showmutualfriends'} && $fr{$ulocal->{userid}}) { + push @mutual, $ulocal; + } else { + push @friend_of, $ulocal; + } + } else { + push @member_of, $ulocal; # 'S' or 'C' (shared or community) + } + } + + $friendsof{'count'} = scalar @friend_of; + $friendsof{'count_m'} = scalar @member_of; + $friendsof{'count_b'} = scalar @mutual; + $friendsof{'loaded'} = 1; + } + + $u->{'name'} = LJ::ehtml($u->{'name'}); + + # TAG:FR:userinfo:remotefriends + # who does the remote user list as a friend? + my %remote_friendid; + if ($remote && $friends{'loaded'}) { + if ($remote->{'userid'} == $u->{'userid'}) { + foreach (@friends) { $remote_friendid{$_->{'userid'}} = 1; } + } else { + my $frs = LJ::get_friends($remote) || {}; + $remote_friendid{$_} = 1 while $_ = each %$frs; + } + } + + # BML helpers. we do BML by hand in this page, so we don't force BML + # to evaluate this huge page looking for non-existent BML. this + # makes it quicker, and prevents us from having to clean out BML in + # the HTML cleaner too. + my $h1 = sub { + return BML::fill_template("h1", { DATA => $_[0] }); + }; + my $p = sub { + return BML::fill_template("p", { DATA => $_[0] }); + }; + + if ($com) { + $body .= $h1->($ML{'.comminfo.name'}); + my $pt = BML::ml('.comminfo.body',{'commname'=>$u->{'name'}}) . " "; + my $userinfo_join_community; + LJ::run_hooks("userinfo_join_community", { + 'u' => $u, + 'ret' => \$userinfo_join_community, + }); + $pt .= $userinfo_join_community ? $userinfo_join_community : BML::ml('.membership.body',{'commname'=>$u->{'user'}}); + $pt .= BML::ml('.body.leave',{'commname'=>$u->{'user'}}); + $body .= $p->($pt); + } elsif ($synd) { + $body .= $h1->($ML{'.syndinfo.name'}) . $p->(BML::ml('.syndinfo.body', { + 'addtofriends' => "$LJ::SITEROOT/friends/add.bml?user=$u->{'user'}", + })); + } elsif ($extid) { + if ($extid->[0] eq "O") { + $body .= $h1->("OpenID user"); + $body .= $p->("This is a non-$LJ::SITENAME user that's using their external identity to log in to $LJ::SITENAME using OpenID in order to leave authenticated comments and read friends-only entries."); + } + + + } else { + $body .= $h1->($ML{'.userinfo.name'}) . $p->(BML::ml('.userinfo.body', { + 'username' => $u->{'name'}, 'siteroot'=>$LJ::SITEROOT, + })); + } + + ## standout bar + { + my @linkele; + + my $label = $com ? $ML{'.monitor.comm'} : $ML{'.monitor.user'}; + + if ($u->{user} !~ /^imp\_/o) { + push @linkele, "$label"; + } + else { + push @linkele, "No available actions"; + } + + if (LJ::can_use_journal($remote->{'userid'}, $user) && !$extid) { + if($remote_isowner) { + $label = $ML{'.label.postalt'}; + } else { + $label = BML::ml('.label.post', {'journal' => $user}); + } + + $label = LJ::ehtml("$label"); + + push @linkele, "$label"; + } + + $label = $ML{'.label.todo'}; + push @linkele, "$label" unless $extid; + + $label = $ML{'.label.memories'}; + push @linkele, "$label" unless $extid; + + unless ($LJ::DISABLED{'tellafriend'} || $extid) { + push @linkele, "$ML{"; + } + + unless ($LJ::DISABLED{'feedster_search'} || $extid || $u->{'opt_blockrobots'}) { + push @linkele, "$ML{"; + } + + if (@linkele) { + $body .= BML::fill_template("standout", { + DATA => join("  ", @linkele), + }); + } + } + + $body .= ""; + { + my $hook_extra; + LJ::run_hooks("userinfo_html_by_user", { + 'u' => $u, + 'ret' => \$hook_extra, + }); + if ($u->{journaltype} eq "I") { + if ($u->{user} =~ /^imp\_/o) { + $body .= ""; + } + else { + $body .= ""; + } + } else { + $body .= "\n"; + } + } + +### picture + + my $narrow_left = 2; ## rows with smaller colspan to 2 + $body .= ""; +### /picture + + $body .= "\n"; + + ## journal title +if ($u->{'journaltitle'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "\n"; +} + + + ### name or 'syndicated from' + unless ($synd) { + unless ($u->underage || $u->{'name'} eq $u->{'journaltitle'}) { + $narrow_left--; + $body .= "\n"; + } + } else { + $narrow_left--; + my $link; + if (my $url = $u->{'url'}) { + $link="$u->{'name'}"; + } else { + $link=$u->{'name'}; + } + my $icon="". + ""; + $body .= "\n". + "\n"; + + # syndication status + $body .= "\n"; + + } + + ## text message + if ($u->{'txtmsg_status'} eq "on" && LJ::get_cap($u, "textmessaging")) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= ""; + } + + if ( ! $synd && $u->{'url'}) { + my $url = LJ::ehtml($u->{'url'}); + my $span = ($narrow_left-- >= 0) ? 1 : 2; + unless ($url =~ /^https?:\/\//) { + $url =~ s/^http\W*//; + $url = "http://$url"; + } + my $urlname = LJ::ehtml($u->{'urlname'} || $url); + $url = "$urlname"; + $body .= "\n" if ($u->{'url'}); + } + + + if ( ! $synd && ($u->{'allow_infoshow'} eq "Y" || $viewall)) { + if ($u->{'city'} || $u->{'state'} || $u->{'country'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= ""; + } + + if ($u->{'bdate'} && !$com && $u->{'bdate'} ne "0000-00-00" && !$u->underage) { + my $bdate = $u->{'bdate'}; + $bdate =~ s/^0000-//; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "\n"; + } + } + + if ( ! $synd && ! $u->underage && ($u->{'allow_contactshow'} eq "Y" || + ($u->{'allow_contactshow'} eq "F" && $remote_isfriend) || $viewall)) + { + my $mangleaddress = sub { + my $email = shift; + my $mret = "
      Imported:" . LJ::ljuser($u) . "
      OpenID:" . LJ::ljuser($u) . "
      $ML{'.label.user'}$user ($u->{'userid'}) $hook_extra "; + if ($u->{public_key}) { + $body .= ""; + $body .= "View public key"; + } + $body .= ""; + if ($u->{'defaultpicid'}) { + my $picid = $u->{'defaultpicid'}; + my %pic; + LJ::load_userpics(\%pic, [ $u, $picid ]); + $body .= "$user"; + } else { + $body .= " "; + } + $body .= "
      "; + $body .= "" . LJ::ehtml($u->{'journaltitle'}) . ""; + if ($u->{'journalsubtitle'}) { + $body .= "
      " . LJ::ehtml($u->{'journalsubtitle'}) . ""; + } + $body .= "
      $ML{'.label.name'}$u->{'name'}
      $ML{'.label.syndicatedfrom'}$link $icon
      $ML{'.label.syndicatedstatus'}\n"; + $body .= "$ML{'.syn.lastcheck'} "; + $body .= $synd->{'lastcheck'} || $ML{'.syn.last.never'}; + my $status = { + 'parseerror' => "Parse error", + 'notmodified' => "Not Modified", + 'toobig' => "Too big", + 'posterror' => "Posting error", + 'ok' => "", # no status line necessary + 'nonew' => "", # no status line necessary + 'httperror' => "HTTP error", + }->{$synd->{'laststatus'}}; + $body .= " ($status)" if $status; + + if ($synd->{'laststatus'} eq "parseerror" || $synd->{'laststatus'} eq "httperror") { + $body .= "
      $ML{'.syn.parseerror'} " . LJ::ehtml($u->{'rssparseerror'}); + } + + $body .= "
      $ML{'.syn.nextcheck'} $synd->{'checknext'}"; + $body .= "
      $ML{'.label.textmessage'}" . BML::ml('.sendmessage.body',{'user'=>$u->{'user'}, 'link'=>"/tools/textmessage.bml?user=$u->{'user'}"}) . "
      $ML{'.label.website'}$url
      $ML{'.label.location'}"; + my $estate = LJ::eurl($u->{'state'}); + my $ecity = LJ::eurl($u->{'city'}); + my $ecountry = LJ::eurl($u->{'country'}); + + my ($state, $city, $country); + + if ($u->{'country'}) { + $country = $LJ::DISABLED{'directory'} ? $countries{$u->{'country'}} : + "". + $countries{$u->{'country'}} . ""; + } + + my $estate; + if ($u->{'state'}) { + $state = $u->{'state'}; + if ($u->{'country'} eq "US") { $state = $states{$state}; } + $estate = LJ::eurl($state); + $state = $LJ::DISABLED{'directory'} || ! $u->{'country'} ? $state : + "$state"; + } + + if ($u->{'city'}) { + my $ecity = LJ::eurl($u->{'city'}); + $city = LJ::ehtml($u->{'city'}); + if (! $LJ::DISABLED{'directory'} && $u->{'country'}) { + $city = "$city"; + } + } + + $body .= join(", ", grep { $_ } ($city, $state, $country)); + $body .= "
      $ML{'.label.birthdate'}$bdate
      "; + for (my $i = 0; $i < length($email); $i++) { + my $letter = substr($email, $i, 1); + if ($letter eq "\@") { $letter = "\@"; } + $mret .= $letter; + } + $mret .= "
      "; + return $mret; + }; + + # some classes of users we want to have their contact info hidden + # after so much time of activity, to prevent people from bugging + # them for their account or trying to brute force it. + my $hide_contactinfo = sub { + my $hide_after = LJ::get_cap($u, "hide_email_after"); + return 0 unless $hide_after; + my $memkey = [$u->{userid}, "timeactive:$u->{userid}"]; + my $active; + unless (defined($active = LJ::MemCache::get($memkey))) { + $active = $dbcr->selectrow_array("SELECT timeactive FROM clustertrack2 ". + "WHERE userid=?", undef, $u->{userid}); + LJ::MemCache::set($memkey, $active, 86400); + } + return $active && (time() - $active) > $hide_after * 86400; + }; + + my $useremail_cap = LJ::get_cap($u, 'useremail'); + unless ($u->{'opt_whatemailshow'} eq "N" || + $u->{'journaltype'} eq "I" || + $u->{'opt_whatemailshow'} eq "L" && ($u->{'no_mail_alias'} || ! $useremail_cap || ! $LJ::USER_EMAIL) || + $hide_contactinfo->()) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.email'}"; + my @emails = ($u->{'email'}); + if ($u->{'opt_whatemailshow'} eq "L") { + @emails = (); + } + if ($LJ::USER_EMAIL && $useremail_cap) { + + unless ($u->{'opt_whatemailshow'} eq "A" || $u->{'no_mail_alias'}) { + push @emails, "$u->{'user'}\@$LJ::USER_DOMAIN"; + } + } + foreach my $email (@emails) { + $body .= ($u->{'opt_mangleemail'} eq "Y" || $email =~ /\@lj\.rossial\.org$/) + ? $mangleaddress->($email) + : "$email
      "; + } + $body .= ""; + } + + foreach my $k (qw(aolim icq yahoo msn jabber)) { + $u->{$k} = LJ::ehtml($u->{$k}); + } + + if ($u->{'aolim'}) { + my $qim = $u->{'aolim'}; + $qim =~ s/ //g; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.aolim'}AIM status $u->{'aolim'} ($ML{'.label.addbuddy'}, $ML{'.label.sendmessage'})\n"; + } + if ($u->{'icq'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.icquin'}"; + $body .= "ICQ status "; + $body .= "$u->{'icq'} ("; + $body .= "$ML{'.label.userprofile'})"; + $body .= "\n"; + } + if ($u->{'yahoo'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.yahooid'}Yahoo status $u->{'yahoo'} ($ML{'.label.adduser'}, $ML{'.label.sendmessage'}) \n"; + } + if ($u->{'msn'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + my $msnname = ($u->{'opt_mangleemail'} eq "Y") ? $mangleaddress->($u->{'msn'}) : $u->{'msn'}; + $body .= "$ML{'.label.msnusername'}$msnname\n"; + } + if ($u->{'jabber'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + my $jabber = $mangleaddress->($u->{'jabber'}); + $body .= "$ML{'.label.jabber'}$jabber\n"; + } + } + + + if ($u->{'has_bio'} eq "Y") { + my $span = ($narrow_left-- > 0) ? 1 : 2; + my $label = $com ? $ML{'.about.comm'} : $ML{'.about.user'}; + + LJ::CleanHTML::clean_userbio(\$u->{'bio'}); + + $body .= "$label$u->{'bio'}\n"; + } + + ### memories + { + my $memcount = LJ::Memories::count($userid); + if ($memcount) { + my $span = ($narrow_left-- > 0) ? 1 : 2; + my $noun_name = $memcount == 1 ? '.memories.entry' : '.memories.entries'; + my $count = BML::ml($noun_name, {'count'=>$memcount}); + $body .= "$ML{'.label.memories'}$count\n"; + } + } + + ### Fotobilder gallery count + { + if (LJ::get_cap($u, 'fb_account') && LJ::get_cap($u, 'fb_can_upload') && $u->{'fb_num_pubpics'}+0 > 0) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + + # what we display is an estimate. to eliminate confusion on the user end, we'll display the + # estimate in a way that makes it clear it's not an exact number. rules are: + # + # * < 10 == "under 10" + # * 10..999 == "at least 150" (rounded down to nearest 10) + # * 1000+ == "at least 1500" (rounded down to nearest 100) + # + my $ct = $u->{fb_num_pubpics}; + my $ct_str; + if ($ct < 10) { + $ct_str = BML::ml('.fbpictures.lessthan', { count => 10 }); + } else { + my $order = $ct < 100 ? 10 : 100; + my $base = POSIX::floor($ct / $order); + $ct_str = BML::ml('.fbpictures.over', { count => $base * $order }); + } + + $body .= "$ML{'.label.fbpictures'}$ct_str\n"; + } + } + + if (@$intu) { + my $span = ($narrow_left-- > 0) ? 1 : 2; + $body .= "$ML{'.label.interests'}:"; + my $intcount = 0; + my $intlist = ""; + foreach my $int (@$intu) { + next if $intcount++ > 150; + LJ::text_out(\$int->[1]); # 1==interest + my $eint = LJ::eurl($int->[1]); + if ($int->[2] > 1) { # 2==intcount + if ($remote_interest{$int->[0]}) { # 0==intid + $intlist .= "$int->[1], "; + } else { + $intlist .= "$int->[1], "; + } + } else { + $intlist .= "$int->[1], "; + } + } + chop $intlist; chop $intlist; # remove trailing ", " + if ($intcount > 150) { + my $notshown = $intcount - 150; + $intlist .= BML::ml('.label.intsnotshown',{'intnotshown'=>$notshown}); + } + + $body .= "$intcount: " . $intlist; + if ($remote) { + my $link = "/interests.bml?mode=enmasse"; + $link .= "&fromuser=$user" unless ($remote->{'userid'} == $userid); + $body .= ". "; + my $mlcode = ($remote->{'userid'} == $userid) ? '.label.interests.removesome' + : '.label.interests.modifyyours'; + $body .= BML::ml('Actionlink', { 'link' => "$ML{$mlcode}" }); + $body .= ""; + } + $body .= ""; + } + + ## + ## friends + ## + unless ($synd || $LJ::FORCE_EMPTY_FRIENDS{$userid}) { + my $label = $com ? $ML{'.friends.comm'} : $ML{'.friends.user'}; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$label:"; + + unless ($fif) {$friends{'display'} = 0 if $friends{'count'} > $MAX_FRIENDS_SHOW;} + if ($friends{'count'}) { + if (!$friends{'loaded'} || !$friends{'display'}) { + $body .= "" . $friends{'count'} . ": "; + $body .= " " . ($com ? $ML{'.label.viewmembers'} : $ML{'.label.viewfriends'}) . " ."; + } elsif ($u->{'journaltype'} eq 'P' or $u->{'journaltype'} eq 'S') { + # personal/shared journals have a special way of showing their friends list, it breaks it down into + # three sublists: personal/shared, community/news, syndication + my (@pfriends, @cfriends, @yfriends); + my $friend_link = sub { + my $f = shift; + my $status = $f->{'statusvis'}; + my $frlink = "$f->{'user'}"; + $frlink = "$frlink" if $status =~ /[DXS]/; + $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; + return $frlink; + }; + foreach my $f (@friends) { + push @pfriends, $friend_link->($f) if $f->{'journaltype'} eq 'P' or $f->{'journaltype'} eq 'S'; + push @cfriends, $friend_link->($f) if $f->{'journaltype'} eq 'C' or $f->{'journaltype'} eq 'N'; + push @yfriends, $friend_link->($f) if $f->{'journaltype'} eq 'Y'; + } + my ($pcount, $ccount, $ycount) = (scalar @pfriends, scalar @cfriends, scalar @yfriends); + my $pfriends = join ', ', @pfriends; + my $yfriends = join ', ', @yfriends; + my $cfriends = join ', ', @cfriends; + + # now spit out the HTML + $body .= ""; + if ($pfriends) { + my $text = LJ::ehtml($ML{'.label.frpeople'}); + $body .= "" . + "". + ""; + } + if ($cfriends) { + my $text = LJ::ehtml($ML{'.label.frcommunity'}); + $body .= "" . + "" . + ""; + } + if ($yfriends) { + my $text = LJ::ehtml($ML{'.label.frsyndication2'}); + $body .= "" . + "" . + ""; + } + $body .= "
      " . + "$text$pcount:$pfriends
      " . + "$text$ccount:$cfriends
      " . + "$text$ycount:$yfriends
      "; + } else { + $body .= "" . $friends{'count'} . ": "; + foreach my $f (@friends) { + my $status = $f->{'statusvis'}; + my $frlink = "$f->{'user'}"; + $frlink = "$frlink" if $status =~ /[DXS]/; + $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; + $body .= $frlink; + $body .= ", "; + } + chop $body; chop $body; + } + } else { + $body .= $ML{'.label.nofriends'}; + } + $body .= "\n"; + } + + # friend of and mutual friends display + # there are two options that will affect what gets shown below: opt_hidefriendofs, opt_showmutualfriends + # if the option to show mutual friends is on, then what was known as the friend of list is broken down + # into two lists: mutual friends (people you list and who also list you back) and 'also friend of', which + # lists the people you don't also list as friends. you can hide your friend of list, and leave just + # your mutual friends list showing, or you can not split them and have both be hidden. +# unless ($synd) { + if ($friendsof{'loaded'}) { + my $label; + if ($u->{'opt_showmutualfriends'} && @mutual) { + $label = $ML{'.label.mutual'}; + $body .= "$label"; + $body .= ""; + + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count_b'} . "$plus: "; + my $count = 0; + my $bold_mutual = ! LJ::u_equals($remote, $u); + foreach (@mutual) { + my $frlink = "{'user'}\">$_->{'user'}"; + $frlink = "$frlink" if $bold_mutual && $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { + $friendsof{'clipped'} = 1; + last; + } + } + chop $body; chop $body; + $body .= ", ..." + if $friendsof{'clipped'} || $friendsof{'load_clipped'}; + $friendsof{'clipped'} = 0; # reset for @friend_of display + $body .= "\n"; + } + if ($friendsof{'display'} && @friend_of) { + $label = $com ? $ML{'.friendof.comm'} : + ($u->{'opt_showmutualfriends'} ? $ML{'.label.alsofriendof'} : $ML{'.friendof.user'}); + $body .= "$label"; + if ($u->{'opt_hidefriendofs'}) { + $body .= "
      $ML{'.friendof.hidden'}"; + } + $body .= ""; + + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count'} . "$plus: "; + my $count = 0; + foreach (@friend_of) { + my $frlink; + if ($_->{'journaltype'} eq "P") { + $frlink = "{'user'}\">$_->{'user'}"; + } elsif ($_->{'journaltype'} eq "I") { + $frlink = "{'userid'}&t=I\">" . LJ::ehtml($_->{'name'}) . ""; + } + $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { + $friendsof{'clipped'} = 1; + last; + } + } + chop $body; chop $body; + $body .= ", ..." + if $friendsof{'clipped'} || $friendsof{'load_clipped'}; + $body .= "\n"; + }; + if ($friendsof{'display'} && @member_of) { + $label = $ML{'.label.memberof'}; + $body .= "$label:"; + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count_m'} . "$plus: "; + foreach (@member_of) { + my $frlink = "$_->{'user'}"; + $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + } + chop $body; chop $body; + $body .= "\n"; + }; + } +# } else { # Syndication journals are special +# $body .= "$ML{'.friendof.syndreadcount'}:"; +# $body .= "$friendsof{'count'}\n"; +# } + + ## extra rows generated by hooks + foreach my $row (LJ::run_hooks("userinfo_rows", { + 'dbr' => $dbr, + 'u' => $u, + 'remote' => $remote, + })) { + next unless $row->[0]; + $body .= ""; + $body .= $row->[0]; + $body .=":"; + $body .= $row->[1]; + $body .= "\n"; + } + + unless ($synd || $GET{'mode'} eq "full") { # Synd accts are always full, but their full ends early (see below) + $body .= "\n"; + $body .= "

      $ML{'.label.moredetails'}

      "; + $bml_okay = 0; + return; + } + + + ## + ## interesting times + ## + $body .= "$ML{'.label.datecreated'}$u->{'timecreate'}"; + $body .= "$ML{'.label.dateupdated'}"; + if ($u->{'timeupdate'}) { + $body .= "$u->{'timeupdate'}, "; + my $secondsold = $u->{'secondsold'}; + my $num; + if ($secondsold > 60*60*24*7) { + $num = int($secondsold / (60*60*24*7)); + $body .= $num == 1 ? $ML{'.timeupdate.weekago'} + : BML::ml('.timeupdate.weeksago',{'num'=>$num}); + } elsif ($secondsold > 60*60*24) { + $num = int($secondsold / (60*60*24)); + $body .= $num == 1 ? $ML{'.timeupdate.dayago'} + : BML::ml('.timeupdate.daysago',{'num'=>$num}); + } elsif ($secondsold > 60*60) { + $num = int($secondsold / (60*60)); + $body .= $num == 1 ? $ML{'.timeupdate.hourago'} + : BML::ml('.timeupdate.hoursago',{'num'=>$num}); + } elsif ($secondsold > 60) { + $num = int($secondsold / (60)); + $body .= $num == 1 ? $ML{'.timeupdate.minuteago'} + : BML::ml('.timeupdate.minutesago',{'num'=>$num}); + } else { + $num = $secondsold; + $body .= $num == 1 ? $ML{'.timeupdate.secondago'} + : BML::ml('.timeupdate.secondsago',{'num'=>$num}); + } + $body .= ""; + } else { + $body .= $ML{'.date.never'}; + } + $body .= ""; + + if ($synd) { # The rest of the rows are not useful to synd accts + $body .= "\n"; + $bml_okay = 0; + return ""; + } + + unless ($LJ::DISABLED{'userinfo_clientusage'}) { + $body .= "" . BML::ml('.label.clientsused',{'siteroot'=>$LJ::SITEROOT}) . ""; + $sth = $dbr->prepare("SELECT DISTINCT c.client FROM clients c, clientusage cu ". + "WHERE cu.userid=$userid AND cu.clientid=c.clientid ORDER BY c.client"); + $sth->execute; + my $lastclient = ""; + while ($_ = $sth->fetchrow_hashref) { + next unless ($_->{'client'} =~ m!(.+)/(.+)!); + my ($client, $ver) = ($1, $2); + if ($lastclient ne $client) + { + if ($lastclient) { chop $body; chop $body; $body .= "
      "; } + else { 1; } + $body .= "" . LJ::ehtml($client) .": "; + $lastclient = $client; + } + $body .= LJ::ehtml($ver) . ", "; + } + if ($lastclient) { chop $body; chop $body; } + $body .= ""; + } + + # count journal entries + { + my $memkey = [$userid, "log2ct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 3600*24*2; # 2 days + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=?", + undef, $userid); + LJ::MemCache::set($memkey, $count, $expire); + } + + $body .= "$ML{'.label.journalentrs'}" . + "" . &comma($count) . ""; + } + + my $points = $dbr->selectrow_array("SELECT SUM(points) AS 'points' FROM supportpoints WHERE userid=$userid"); + if ($points) { + $body .= "$ML{'.label.supportpoints'}:" . &comma($points) . ""; + } + + sub comma { + my $num = shift; + if ($num =~ s/(\d)(\d\d\d)$/$1,$2/) { + $num =~ s/(\d)(\d\d\d),/$1,$2/g; + } + return $num; + } + +## +## journal comments + { + my ($com_post, $com_got); + unless ($LJ::DISABLED{'show-talkleft'}) { + my $memkey = [$userid, "talkleftct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 3600*24*2; # 2 days + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talkleft " . + "WHERE userid=?", undef, $userid); + LJ::MemCache::set($memkey, $count, $expire) if defined $count; + } + $com_post = comma($count); + $com_post = BML::ml('.label.composted', {'num'=>$com_post}); + } + + my $memkey = [$userid, "talk2ct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 900; # 15 minutes; + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talk2 ". + "WHERE journalid=?", undef, $userid); + LJ::MemCache::set($memkey, $count, $expire) if defined $count; + } + + $com_got = comma($count); + $com_got = BML::ml('.label.comreceived', {'num'=>$com_got}); + $body .= "$ML{'.label.comments'}$com_post" . + $com_got . ""; + } + +### +### shared journal access +### +{ + my $list; + if ($com || $u->{'journaltype'} eq 'S') { + # load user who can post to this community + $list = LJ::load_rel_user($u, 'P'); + } else { + # load communities/accounts this user can post to + $list = LJ::load_rel_target($u, 'P'); + } + my %u; + my @ids = @$list; + my $count = @ids; + my $chopped = 0; + my $CHOP_POINT = 500; + unless ($fif) { + if (@ids > $CHOP_POINT) { + @ids = splice(@ids, 0, $CHOP_POINT); + $chopped = 1; + } + } + LJ::load_userids_multiple([ map { $_ => \$u{$_} } @ids ]); + my @accesslist = sort { $a->{user} cmp $b->{user} } grep { $_->{statusvis} eq 'V' } values %u; + + if (my $vcount = @accesslist) { + unless ($fif) { $count = $vcount if $count < $CHOP_POINT; } + $body .= "$ML{'.label.shared'}$count: "; + $body .= join(", ", map { "$_->{user}" } @accesslist); + $body .= ", ..." if $chopped; + $body .= ""; + } +} + +$body .= "\n"; + +# removed until we run graphviz locally +# $body .= "

      Graph of friends

      "; + +$bml_okay = 0; +return; + +_code?> +title=> +body=> +head=> +page?> +lib: cgi-bin/ljlib.pl, cgi-bin/cleanhtml.pl +link: htdocs/editinfo.bml, htdocs/userinfo.bml, htdocs/users +link: htdocs/community/join.bml, htdocs/community/leave.bml, htdocs/friends/add.bml, htdocs/todo/index.bml +link: htdocs/tools/memories.bml, htdocs/tools/tellafriend.bml, htdocs/allpics.bml +link: htdocs/tools/textmessage.bml, htdocs/interests.bml, htdocs/support/faqbrowse.bml, htdocs/download/index.bml +link: htdocs/support/index.bml +img: img/btn_addfriend.gif, img/btn_todo.gif, img/btn_memories.gif, img/btn_tellfriend.gif, img/talk/md10_thumbup.gif, img/xml.gif +hook: userinfo_html_by_user, userinfo_rows + _c?> diff --git a/local/htdocs/ustav.html b/local/htdocs/ustav.html new file mode 100755 index 0000000..0d4875b --- /dev/null +++ b/local/htdocs/ustav.html @@ -0,0 +1,90 @@ + Ustav + + +
      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      +

      +õÓÔÁ× ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ LJR (lj.rossia.org). +

      + + LJR - ÎÅËÏÍÍÅÒÞÅÓËÉÊ ÐÒÏÅËÔ, ÓÏÚÄÁÎÎÙÊ × ÓÏÏÔ×ÅÔÓÔ×ÉÉ +Ó òÕËÏ×ÏÄÑÝÉÍÉ ðÒÉÎÃÉÐÁÍÉ LJR ÄÌÑ ÐÏÄÄÅÒÖËÉ +Ó×ÏÂÏÄÙ ÓÌÏ×Á, ÒÁÚ×ÉÔÉÑ ÇÒÁÖÄÁÎÓËÏÇÏ ÏÂÝÅÓÔ×Á É ÐÏÏÝÒÅÎÉÑ +Ó×ÏÂÏÄÎÏÇÏ ÏÂÍÅÎÁ ÍÎÅÎÉÑÍÉ. úÁ ÓÏÂÌÀÄÅÎÉÅÍ ÜÔÉÈ ÐÒÉÎÃÉÐÏ× +ÎÁÂÌÀÄÁÅÔ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ: + +
        +
      • ÷ÁÄÉÍ çÕÝÉÎ +
      • é×ÁÎ äÁ×ÙÄÏ× +
      • ëÏÎÓÔÁÎÔÉÎ ëÒÙÌÏ× +
      • òÏÍÁÎ ìÅÊÂÏ× +
      • íÁËÓÉÍ íÏÛËÏ× +
      • áÎÔÏÎ îÏÓÉË +
      • íÉÛÁ ÷ÅÒÂÉÃËÉÊ +
      + +÷ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ËÏÏÐÔÉÒÕÅÔÓÑ (Ó ÐÒÁ×ÏÍ ÓÏ×ÅÝÁÔÅÌØÎÏÇÏ +ÇÏÌÏÓÁ) ÓÉÓÔÅÍÎÁÑ ÁÄÍÉÎÉÓÔÒÁÃÉÑ ÓÅÒ×ÅÒÁ LJR; × ÓÌÕÞÁÅ ÒÁÚÄÅÌÁ +ÇÏÌÏÓÏ×, ÓÏ×ÅÝÁÔÅÌØÎÙÊ ÇÏÌÏÓ ÓÔÁÎÏ×ÉÔÓÑ ÒÅÛÁÀÝÉÍ. +

      + +îÅÐÏÓÒÅÄÓÔ×ÅÎÎÏÊ ÐÏÄÄÅÒÖËÏÊ LJR ÚÁÎÉÍÁÅÔÓÑ ÁÄÍÉÎÉÓÔÒÁÃÉÑ +ÓÅÒ×ÅÒÁ, ÔÏ ÅÓÔØ ÌÀÄÉ, ÎÁÄÅÌÅÎÎÙÅ ÓÉÓÔÅÍÎÙÍÉ ÐÏÌÎÏÍÏÞÉÑÍÉ. + + +

      + +áÄÍÉÎÉÓÔÒÁÃÉÑ LJR ÚÁËÒÙ×ÁÅÔ ÄÎÅ×ÎÉËÉ ÓÐÁÍÍÅÒÏ×, +ÄÎÅ×ÎÉËÉ, ÓÏÚÄÁÎÎÙÅ ÄÌÑ ÈÁËÅÒÓËÉÈ ÁÔÁË, ÄÎÅ×ÎÉËÉ, +ÓÏÚÄÁÀÝÉÅ ÔÅÈÎÉÞÅÓËÉÅ ÐÒÏÂÌÅÍÙ ÄÌÑ ÒÁÂÏÔÙ +LJR, É ÄÎÅ×ÎÉËÉ, ÇÄÅ ÒÁÚÍÅÝÁÀÔÓÑ ÐÒÏÔÉ×ÏÚÁËÏÎÎÙÅ É +ÐÒÅÄÓÔÁ×ÌÑÀÝÉÅ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÕÀ ÏÐÁÓÎÏÓÔØ ÄÌÑ ÖÉÚÎÉ É +ÚÄÏÒÏ×ØÑ ËÏÎËÒÅÔÎÙÈ ÌÀÄÅÊ ÚÁÐÉÓÉ. ÷Ï ×ÓÅÈ ÄÒÕÇÉÈ +ÓÌÕÞÁÑÈ, ÄÌÑ ÚÁËÒÙÔÉÑ ÔÒÅÂÕÅÔÓÑ ÖÁÌÏÂÁ ÐÏÌØÚÏ×ÁÔÅÌÑ +ÉÌÉ ÔÒÅÔØÉÈ ÌÉÃ, Á ÔÁËÖÅ ÒÅÛÅÎÉÅ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ +óÏ×ÅÔÁ. +

      + +ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ÒÁÚÂÉÒÁÅÔ ÖÁÌÏÂÙ ÐÏÌØÚÏ×ÁÔÅÌÅÊ +(ÄÒÕÇ ÎÁ ÄÒÕÇÁ É ÎÁ ÁÄÍÉÎÉÓÔÒÁÃÉÀ LJR). +òÅÛÅÎÉÅ ÐÒÉÎÉÍÁÅÔÓÑ ÐÒÏÓÔÙÍ ÂÏÌØÛÉÎÓÔ×ÏÍ ÇÏÌÏÓÏ×, ÐÏ ÉÓÔÅÞÅÎÉÉ +ÐÑÔÉ ÓÕÔÏË Ó ÍÏÍÅÎÔÁ ÐÏÄÁÞÉ ÖÁÌÏÂÙ. +

      + +òÅÛÅÎÉÅ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ, ÐÒÉ ÐÒÉÎÑÔÉÉ +ËÏÔÏÒÏÇÏ ÎÅ ÇÏÌÏÓÏ×ÁÌ ÏÄÉÎ ÉÚ ÕÞÁÓÔÎÉËÏ×, +ÍÏÖÅÔ ÂÙÔØ ÐÅÒÅÓÍÏÔÒÅÎÏ ÐÏ ÐÒÏÓØÂÅ ÜÔÏÇÏ +ÕÞÁÓÔÎÉËÁ. +

      + +ôÁËÖÅ ðÏÐÅÞÉÔÅÌØÓËÉÊ óÏ×ÅÔ ÍÏÖÅÔ ÐÒÉÎÑÔØ ÒÅÛÅÎÉÅ +Ï ÏÔËÁÚÅ Ë ÐÒÉÅÍÕ ÄÁÌØÎÅÊÛÉÈ ÖÁÌÏ ÏÓÏÂÏ ÓËÌÏÞÎÏÇÏ ËÌÑÕÚÎÉËÁ +(ÔÏÖÅ ÂÏÌØÛÉÎÓÔ×ÏÍ ÇÏÌÏÓÏ×). +

      + +þÌÅÎ ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ ÍÏÖÅÔ ÐÏÄÁÔØ × ÏÔÓÔÁ×ËÕ. + + +

      +ðÅÒÅÓÍÏÔÒ õÓÔÁ×Á, ðÒÁ×ÉÌ É òÕËÏ×ÏÄÑÝÉÈ ðÒÉÎÃÉÐÏ×, +ÐÅÒÅÅÚÄ ÓÅÒ×ÅÒÁ, Á ÔÁËÖÅ ÐÒÉ×ÌÅÞÅÎÉÅ ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÕÞÁÓÔÎÉËÏ× +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ ÏÓÕÝÅÓÔ×ÌÑÅÔÓÑ, ÅÓÌÉ +ÚÁ ÜÔÉ ÍÅÒÙ ×ÙÓÔÕÐÁÀÔ ËÁË ÍÉÎÉÍÕÍ 2/3 ÓÐÉÓÏÞÎÏÇÏ +ÓÏÓÔÁ×Á ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. +

      + +÷ÓÅ ÇÏÌÏÓÏ×ÁÎÉÑ ×ÅÄÕÔÓÑ ÏÔËÒÙÔÏ, ËÒÏÍÅ ÇÏÌÏÓÏ×ÁÎÉÑ +ÐÏ ËÁÎÄÉÄÁÔÕÒÁÍ ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÕÞÁÓÔÎÉËÏ× +ðÏÐÅÞÉÔÅÌØÓËÏÇÏ óÏ×ÅÔÁ. + + +

      +
      + ðÒÁ×ÉÌÁ | õÓÔÁ× | òÕËÏ×ÏÄÑÝÉÅ ðÒÉÎÃÉÐÙ + + +
      diff --git a/local/htdocs/zatychka.html b/local/htdocs/zatychka.html new file mode 100755 index 0000000..538106a --- /dev/null +++ b/local/htdocs/zatychka.html @@ -0,0 +1 @@ +temporarySorry -- temporarily disabled diff --git a/multicvs.conf b/multicvs.conf new file mode 100755 index 0000000..f16a50e --- /dev/null +++ b/multicvs.conf @@ -0,0 +1,55 @@ +# +# This file determine how files from multiple CVS repositories (or just snapshots +# of them) map onto the live file space +# +# You should've already read the installation documentation[1], but for reference, the +# repositories you'll need are: +# +# livejournal: +# CVSROOT=':pserver:anonymous@cvs.livejournal.org:/home/cvslj' +# bml, wcmtools: +# CVSROOT=':pserver:anonymous@danga.com:/home/cvspub' +# +# [1] http://www.livejournal.com/doc/server/ + +LIVEDIR=$LJHOME +CVSDIR=$LJHOME/cvs + +livejournal . +bml/lib/Apache/BML.pm cgi-bin/Apache/BML.pm +bml/doc/docbook doc/raw/bml.book +wcmtools/spud/bin/cmdshell bin/cmdshell +wcmtools/spud/bin/gatherer bin/spud/gatherer +wcmtools/spud/bin/replicator bin/spud/replicator +wcmtools/spud/bin/server bin/spud/server +wcmtools/spud/bin/wrapper bin/spud/wrapper +wcmtools/spud/bin/plugins bin/spud/plugins +wcmtools/bin/multicvs.pl bin/multicvs.pl +wcmtools/bin/apidoc.pl bin/apidoc.pl +wcmtools/lib/DBI cgi-bin/DBI +wcmtools/lib/DBIx cgi-bin/DBIx +wcmtools/lib/Apache/CompressClientFixup.pm cgi-bin/Apache/CompressClientFixup.pm +wcmtools/lib/HTMLCleaner.pm cgi-bin/HTMLCleaner.pm +wcmtools/lib/S2/Color.pm cgi-bin/S2/Color.pm +wcmtools/lib/MultiCVS.pm cgi-bin/MultiCVS.pm +wcmtools/s2 src/s2 +wcmtools/perlbal src/perlbal +wcmtools/memcached src/memcached +wcmtools/memcached/api/perl/Memcached.pm cgi-bin/Cache/Memcached.pm +wcmtools/s2/doc/docbook doc/raw/s2 +wcmtools/ddlockd/api/perl/DDLockClient.pm cgi-bin/DDLockClient.pm +wcmtools/ddlockd/server/ddlockd bin/ddlockd +wcmtools/dmtpd/server/dmtpd bin/dmtpd +wcmtools/mogilefs/api/perl/MogileFS.pm cgi-bin/MogileFS.pm +wcmtools/lib/Danga-Daemon/Daemon.pm cgi-bin/Danga/Daemon.pm +wcmtools/lib/Danga-Socket/Socket.pm cgi-bin/Danga/Socket.pm +wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx cgi-bin/LWPx +wcmtools/openid/perl/Net-OpenID-Consumer/lib cgi-bin +wcmtools/openid/perl/Net-OpenID-Server/lib cgi-bin +livejournal/htdocs/login.bml ssldocs/login.bml +livejournal/htdocs/create.bml ssldocs/create.bml +livejournal/htdocs/changepassword.bml ssldocs/changepassword.bml +livejournal/htdocs/captcha ssldocs/captcha +livejournal/htdocs/img/icon_protected.gif ssldocs/img/icon_protected.gif +livejournal/htdocs/img/userinfo.gif ssldocs/img/userinfo.gif +local? . diff --git a/obsolete/bin/rlj2lj.pl b/obsolete/bin/rlj2lj.pl new file mode 100755 index 0000000..69abcb3 --- /dev/null +++ b/obsolete/bin/rlj2lj.pl @@ -0,0 +1,405 @@ +#!/usr/bin/perl -w +use strict; +use XMLRPC::Lite; +use Digest::MD5 qw(md5_hex); +use DBI; +use Time::Local; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJR::Viewuserstandalone; + +do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl"; +# +#îÁÓÔÒÏÊËÉ +# + +#ó×ÏÊÓÔ×Á ÓÏÅÄÉÎÅÎÉÑ Ó ÂÁÚÏÊ +my $qhost = $LJ::DBINFO{'master'}->{'host'}; +my $quser = $LJ::DBINFO{'master'}->{'user'}; +my $qpass = $LJ::DBINFO{'master'}->{'pass'}; +my $qsock = $LJ::DBINFO{'master'}->{'sock'}; +my $qport = $LJ::DBINFO{'master'}->{'port'}; +#my $qdb = $LJ::DBINFO{'master'}->{'dbname'}; +my $qdb = "prod_ljgate"; + +#óÁÊÔ, Ó ËÏÔÏÒÏÇÏ ËÏÐÉÒÕÅÍ +my $source_site = "127.0.0.2"; + +#óÁÊÔ, ÎÁ ËÏÔÏÒÏÊ ËÏÐÉÒÕÅÍ +my $dest_site = "www.livejournal.com"; + +#þÁÓÔÏÔÁ ÓÉÎÈÒÏÎÉÚÁÃÉÉ × ÆÏÒÍÁÔÅ þþ:íí:óó +#(ÔÏ ÅÓÔØ ÓÉÎÈÒÏÎÉÚÁÃÉÑ ËÁÖÄÙÅ 15 ÍÉÎÕÔ ÂÕÄÅÔ ×ÙÇÌÑÄÅÔØ ËÁË +#00:15:00 +my $sync_freq = "00:10:00"; + +#òÁÚÎÉÃÁ ×Ï ×ÒÅÍÅÎÉ ÍÅÖÄÕ ÍÁÛÉÎÏÊ, ÎÁ ËÏÔÏÒÏÊ ÕÓÔÁÎÏ×ÌÅÎ ÇÅÊÔ, +#É ÍÁÛÉÎÏÊ, ÎÁ ËÏÔÏÒÏÊ ÕÓÔÁÎÏ×ÌÅÎ ÉÓÈÏÄÎÙÊ LJ-ÓÅÒ×ÅÒ (ÚÁÐÉÓÉ +#ÄÁÔÉÒÕÀÔÓÑ ÌÏËÁÌØÎÙÍ ×ÒÅÍÅÎÅÍ ÐÏÌØÚÏ×ÁÔÅÌÑ, Á ×ÒÅÍÑ ÓÉÎÈÒÏÎÉÚÁÃÉÉ +#ÏÔÓÞÉÔÙ×ÁÅÔÓÑ ÐÏ ÞÁÓÁÍ ÍÁÛÉÎÙ, ÇÄÅ ËÒÕÔÉÔÓÑ LJ, ÂÌÉÎ). +#òÁÚÎÉÃÁ ÕËÁÚÙ×ÁÅÔÓÑ × ËÏÌÉÞÅÓÔ×Å ÓÅËÕÎÄ. åÓÌÉ ×ÒÅÍÑ ÇÅÊÔÁ ÍÅÎØÛÅ +#×ÒÅÍÅÎÉ ÓÅÒ×ÅÒÁ, ÒÁÚÎÉÃÁ ÄÏÌÖÎÁ ÂÙÔØ ÐÏÌÏÖÉÔÅÌØÎÙÍ ÞÉÓÌÏÍ, ÂÏÌØÛÅ --- +#ÐÏÎÑÔÎÏÅ ÄÅÌÏ, ÏÔÒÉÃÁÔÅÌØÎÙÍ. +my $time_diff = 0; + +#îÁÓÔÒÏÊËÉ ÚÁËÏÎÞÉÌÓØ + +#áËËÁÕÎÔ, ËÏÔÏÒÙÊ ËÏÐÉÒÕÅÍ +my $source_user; +my $source_pass; + +#áËËÁÕÎÔ, × ËÏÔÏÒÙÊ ËÏÐÉÒÕÅÍ +my $dest_user; +my $dest_pass; + +#úÄÅÓØ ÂÕÄÕÔ ÈÒÁÎÉÔØÓÑ ÌÏÇÉÎÙ É ÐÁÒÏÌÉ ÓÉÎÈÒÏÎÉÚÉÒÕÅÍÙÈ +#ÄÎÅ×ÎÉËÏ× (ÎÁ ÎÁÛÅÍ É ÞÕÖÏÍ ÓÅÒ×ÅÒÁÈ) +my %journals; + +open (STDERR, "+>>$ENV{LJHOME}/logs/ljgate.log") || die "Can't open logfile:$!"; + +#÷ÙÞÉÓÌÑÅÍ ×ÒÅÍÑ ÐÒÅÄÙÄÕÝÅÇÏ ÏÂÎÏ×ÌÅÎÉÑ +my ($fr_hour,$fr_min,$fr_sec); +my ($ls_year,$ls_month,$ls_day,$ls_hour,$ls_min,$ls_sec); +($fr_hour,$fr_min,$fr_sec) = split(/:/,$sync_freq); +my $lastsync = (time() - ($fr_hour * 60 * 60) + - ($fr_min * 60) + - $fr_sec); +$lastsync = $lastsync + $time_diff; +($ls_sec,$ls_min,$ls_hour,$ls_day,$ls_month,$ls_year) = localtime($lastsync); +$ls_year += 1900; +$ls_month += 1; +$ls_month=sprintf("%.02d",$ls_month); +$ls_day=sprintf("%.02d",$ls_day); +$ls_sec=sprintf("%.02d",$ls_sec); +$ls_min=sprintf("%.02d",$ls_min); +$ls_hour=sprintf("%.02d",$ls_hour); +$lastsync = $ls_year."-". + $ls_month."-". + $ls_day." ". + $ls_hour.":". + $ls_min.":". + $ls_sec; +#print "$lastsync\n"; + +#ó×ÑÚÙ×ÁÅÍÓÑ Ó ÂÁÚÏÊ +my $dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb", + $quser, $qpass, + ) || die localtime(time) . ": Can't connect to database\n"; + +#úÁÂÉÒÁÅÍ ÉÚ ÂÁÚÙ ID ÖÕÒÎÁÌÏ×, ËÏÔÏÒÙÅ ÎÕÖÎÏ ÓÉÎÈÒÏÎÉÚÉÒÏ×ÁÔØ +my $sqh = $dbh->prepare("SELECT userid,alienid + FROM rlj2lj"); +$sqh->execute; + +my $result; + +#ðÏÍÅÝÁÅÍ ÒÅÚÕÌØÔÁÔÙ ÚÁÐÒÏÓÁ × ÈÜÛ %journals +while ($result = $sqh->fetchrow_hashref) { + $journals{$result->{'userid'}} = $result->{'alienid'}; +} + +#éÎÉÃÉÁÌÉÚÉÒÕÅÍ ÉÎÔÅÒÆÅÊÓ ÐÒÏÔÏËÏÌÁ XMLRPC +my $xmlrpc = new XMLRPC::Lite; + +#óÉÎÈÒÏÎÉÚÉÒÕÅÍ ÖÕÒÎÁÌÙ +foreach (keys(%journals)) { + #úÁÂÉÒÁÅÍ ÉÚ ÂÁÚÙ ÏÞÅÒÅÄÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ ÉÓÈÏÄÎÏÇÏ ÖÕÒÎÁÌÁ + $sqh = $dbh->prepare("SELECT our_user,our_pass + FROM our_user + WHERE userid=$_"); + $sqh->execute; + ($source_user,$source_pass) = $sqh->fetchrow_array; + + #úÁÂÉÒÁÅÍ ÉÚ ÂÁÚÙ ÏÞÅÒÅÄÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ ÞÕÖÏÇÏ ÓÅÒ×ÉÓÁ + $sqh = $dbh->prepare("SELECT alien,alienpass + FROM alien + WHERE alienid=$journals{$_}"); + $sqh->execute; + ($dest_user,$dest_pass) = $sqh->fetchrow_array; + + #ëÏÐÉÒÕÅÍ ×ÓÅ ÚÁÐÉÓÉ, ÄÏÂÁ×ÌÅÎÎÙÅ ÉÌÉ ÉÚÍÅΣÎÎÙÅ + #ÐÏÓÌÅ ÐÒÅÄÙÄÕÝÅÇÏ ÏÂÎÏ×ÌÅÎÉÑ + eval { + sync_journals($source_site,$source_user,$source_pass, + $dest_site,$dest_user,$dest_pass, + $lastsync,$_); + }; + if ($@) { + print STDERR localtime(time) . ": Syncronizing $source_user failed\n"; + } +} + + +###SUBROUTINES### + + +#óÉÎÈÒÏÎÉÚÁÃÉÑ ÄÎÅ×ÎÉËÏ× +sub sync_journals{ + my ($source_site,$souce_user,$source_pass, + $dest_site,$dest_user,$dest_pass, + $lastsync, $user_id); + + #ðÏÌÕÞÁÅÍ ÁÄÒÅÓÁ ÉÓÐÏÌØÚÕÅÍÙÈ ÓÁÊÔÏ× É ÐÁÒÏÌÉ/ÌÏÇÉÎÙ + #ÓÉÎÈÒÏÎÉÚÉÒÕÅÍÙÈ ÁËËÁÕÎÔÏ× ÉÚ ÓÔÒÏËÉ Ó ÁÒÇÕÍÅÎÔÁÍÉ + ($source_site,$souce_user,$source_pass, + $dest_site,$dest_user,$dest_pass,$lastsync,$user_id) = @_; + + my $proxy = "http://" . $source_site . "/interface/xmlrpc"; + $xmlrpc->proxy($proxy); + + #XMLRPC object, for login call + my $get_challenge; + + #Challenge (random string from server for secure login) + my $challenge; + + #String for md5 hash of server challenge and password + my $response; + + #ðÏÌÕÞÁÅÍ ÐÁÒÕ ÐÁÒÏÌØ-ÏÔÚÙ× Õ ÉÓÈÏÄÎÏÇÏ ÓÅÒ×ÅÒÁ + eval { + $get_challenge = xmlrpc_call("LJ.XMLRPC.getchallenge"); + $challenge = $get_challenge->{'challenge'}; + $response = md5_hex($challenge . md5_hex($source_pass)); + }; + #Error handling (russian over ssh doesn't work, sorry) + if ($@) { + print STDERR localtime(time) . ": Login on $source_site failed\n"; + die; + }; + + #XMLRPC object, for "getevents" call + my $getevents; + + #úÁÂÉÒÁÅÍ ×ÓÅ ÓÏÏÂÝÅÎÉÑ, ÐÏÑ×É×ÛÉÅÓÑ ÓÏ ×ÒÅÍÅÎÉ ÐÏÓÌÅÄÎÅÊ ÓÉÎÈÒÏÎÉÚÁÃÉÉ + eval { + $getevents = xmlrpc_call('LJ.XMLRPC.getevents', { + 'username' => $source_user, + 'auth_method' => 'challenge', + 'auth_challenge' => $challenge, + 'auth_response' => $response, + 'ver' => 1, + 'selecttype' => 'syncitems', + 'lastsync' => $lastsync, + 'lineendings' => 'unix', + }); + }; + #Error handling + if ($@) { + print STDERR localtime(time) . ": Getevents on $source_site failed\n"; + die; + } + + $proxy = "http://" . $dest_site . "/interface/xmlrpc"; + $xmlrpc->proxy($proxy); + + #ðÏÌÕÞÁÅÍ ÐÁÒÕ ÐÁÒÏÌØ-ÏÔÚÙ× Õ ÓÅÒ×ÅÒÁ, ÎÁ ËÏÔÏÒÙÊ ËÏÐÉÒÕÅÍ ÚÁÐÉÓÉ + eval { + $get_challenge = xmlrpc_call("LJ.XMLRPC.getchallenge"); + $challenge = $get_challenge->{'challenge'}; + $response = md5_hex($challenge . md5_hex($dest_pass)); + }; + #Error handling + if ($@) { + print STDERR localtime(time) . ": Login on $dest_site failed\n"; + print STDERR "debug1: " . $@; + print STDERR "\n\n"; + die; + } + + my $entry; + + my( $entry_date, $entry_time, $sec, $min, $hour, $day, $month, $year ); + + my $fields; + + my $postevent; + + foreach $entry (@{$getevents->{'events'}}) { + #ðÏÌÕÞÁÅÍ ÐÁÒÕ ÐÁÒÏÌØ-ÏÔÚÙ× Õ ÓÅÒ×ÅÒÁ, ÎÁ ËÏÔÏÒÙÊ ÐÅÒÅÎÏÓÉÍ ÚÁÐÉÓÉ + eval { + $get_challenge = xmlrpc_call("LJ.XMLRPC.getchallenge"); + $challenge = $get_challenge->{'challenge'}; + $response = md5_hex($challenge . md5_hex($dest_pass)); + }; + #Error handling + if ($@) { + print STDERR localtime(time) . ": Login on $dest_site failed\n"; + print STDERR "debug2: " . $@; + print STDERR "\n\n"; + die; + } + + ($entry_date, $entry_time) = split(/ /,$entry->{'eventtime'}); + ($year, $month, $day) = split(/-/,$entry_date); + ($hour, $min, $sec) = split(/:/,$entry_time); + #ëÏÐÉÒÕÅÍ × ÎÏ×ÕÀ ÚÁÐÉÓØ ÔÅ ÐÏÌÑ, ËÏÔÏÒÙÅ ÍÏÖÎÏ ÔÕÐÏ ÓËÏÐÉÒÏ×ÁÔØ + $fields = { + 'username' => $dest_user, + 'auth_method' => 'challenge', + 'auth_challenge' => $challenge, + 'auth_response' => $response, + 'ver' => 1, + 'subject' => ($entry->{'subject'})? + LJR::Viewuserstandalone::expand_ljuser_tags($entry->{'subject'}) + : "", + 'year' => $year, + 'mon' => $month, + 'day' => $day, + 'hour' => $hour, + 'min' => $min, + }; + #÷ÙÑÓÎÑÅÍ ÕÒÏ×ÅÎØ ÄÏÓÔÕÐÁ ËÏÐÉÒÕÅÍÏÊ ÚÁÐÉÓÉ + if (!$entry->{'security'}) { + $fields->{'security'} = 'public'; + } else { + $fields->{'security'} = $entry->{'security'}; + if ($entry->{'allowmask'}) { + $fields->{'allowmask'} = $entry->{'allowmask'}; + } + }; + #úÁÄÁ£Í ÓÔÒÏËÕ Ó ÍÅÔÁÄÁÎÎÙÍÉ + if ($entry->{'props'}->{'current_mood'}) + { + $fields->{'props'}->{'current_mood'} = + $entry->{'props'}->{'current_mood'}; + } + if ($entry->{'props'}->{'mood_id'}) + { + $fields->{'props'}->{'mood_id'} = + $entry->{'props'}->{'mood_id'}; + } + if ($entry->{'props'}->{'current_music'}) + { + $fields->{'props'}->{'current_music'} = + $entry->{'props'}->{'current_music'}; + } + if ($entry->{'props'}->{'opt_backdated'}) + { + $fields->{'props'}->{'opt_backdated'} = + $entry->{'props'}->{'opt_backdated'}; + } + + #úÁÐÒÅÝÁÅÍ ËÏÍÍÅÎÔÁÒÉÉ × ËÏÐÉÒÕÅÍÏÊ ÚÁÐÉÓÉ + $fields->{'props'}->{'opt_nocomments'} = 1; + + #äÏÂÁ×ÌÑÅÍ Ë ÔÅËÓÔÕ ÚÁÐÉÓÉ ÓÓÙÌËÕ ÎÁ ËÏÍÍÅÎÔÁÒÉÉ × ÉÓÈÏÄÎÏÍ ÖÕÒÎÁÌÅ + my $talklink_line = ""; + $fields->{'event'} = LJR::Viewuserstandalone::expand_ljuser_tags($entry->{'event'}).$talklink_line; + +# print STDERR "\n" . $fields->{'event'} . "\n"; + + #ïÔÐÒÁ×ÌÑÅÍ ÏÞÅÒÅÄÎÕÀ ÚÁÐÉÓØ... + unless ($entry->{'props'}->{'revnum'}) { + eval { + $postevent = xmlrpc_call('LJ.XMLRPC.postevent', $fields); + #úÁÐÉÓÙ×ÁÅÍ ÓÏÏÔ×ÅÔÓÔ×ÉÅ ID ÉÓÈÏÄÎÏÇÏ ÐÏÓÔÉÎÇÁ É + #ID ÏÔÇÅÊÔÏ×ÁÎÎÏÇÏ ÐÏÓÔÉÎÇÁ × ÔÁÂÌÉÃÕ rlj_lj_id + $sqh = $dbh->prepare ("INSERT INTO rlj_lj_id(userid,ljr_id,lj_id) + VALUES ($user_id, + $entry->{'itemid'}, + $postevent->{'itemid'})"); + $sqh->execute; + }; + #ïÂÒÁÂÏÔËÁ ÉÓËÌÀÞÅÎÉÑ: ÅÓÌÉ ÎÅ ÕÄÁÌÓÑ ×ÙÚÏ× XMLRPC + if ($@) { + print STDERR localtime(time) . ": Posting event on $dest_site failed\n"; + print STDERR "debug3: " . $@; + print STDERR "\n\n"; + }; + + #...ÉÌÉ ÒÅÄÁËÔÉÒÕÅÍ Å£, ÅÓÌÉ ÏÎÁ ÉÍÅÅÔ ÎÅÎÕÌÅ×ÏÊ ÎÏÍÅÒ ÒÅ×ÉÚÉÉ + } else { + #éÝÅÍ × ÂÁÚÅ ID ÁÎÁÌÏÇÉÞÎÏÊ ÚÁÐÉÓÉ ÄÎÅ×ÎÉËÁ-ËÏÐÉÉ + $sqh = $dbh->prepare ("SELECT lj_id + FROM rlj_lj_id + WHERE userid=$user_id + AND ljr_id=$entry->{'itemid'}"); + $sqh->execute; + + #ID ÚÁÐÉÓÉ × ÄÎÅ×ÎÉËÅ-ËÏÐÉÉ + my $lj_id; + + #åÓÌÉ ÎÁÛÌÉ, ÒÅÄÁËÔÉÒÕÅÍ ÚÁÐÉÓØ Ó ÎÁÊÄÅÎÎÙÍ ID... + if (($lj_id) = $sqh->fetchrow_array) { + $fields->{'itemid'} = $lj_id; + eval { + $postevent = xmlrpc_call('LJ.XMLRPC.editevent', $fields); + }; + #ïÂÒÁÂÏÔËÁ ÉÓËÌÀÞÉÔÅÌØÎÏÊ ÓÉÔÕÁÃÉÉ + if ($@) { + print STDERR localtime(time) . ": Editing event on $dest_site failed\n"; + print STDERR "debug4: " . $@; + print STDERR "\n\n"; + }; + #...Á ÅÓÌÉ ÎÅÔ, ÓÒÁ×ÎÉ×ÁÅÍ Å£ ÄÁÔÕ + #Ó ÄÁÔÏÊ ÐÒÅÄÙÄÕÝÅÊ ÓÉÎÈÒÏÎÉÚÁÃÉÉ + } else { + #åÓÌÉ ÚÁÐÉÓØ ÎÏ×ÁÑ, ÔÏ ÐÒÏÓÔÏ ÐÏÓÔÉÍ Å£... + if (timelocal($ls_sec,$ls_min,$ls_hour,$ls_day,$ls_month,$ls_year)< + timelocal($sec, $min, $hour, $day, $month, $year)) + { + eval { + $postevent = xmlrpc_call('LJ.XMLRPC.postevent', $fields); + #úÁÐÉÓÙ×ÁÅÍ ÓÏÏÔ×ÅÔÓÔ×ÉÅ ID ÉÓÈÏÄÎÏÇÏ ÐÏÓÔÉÎÇÁ É + #ID ÏÔÇÅÊÔÏ×ÁÎÎÏÇÏ ÐÏÓÔÉÎÇÁ × ÔÁÂÌÉÃÕ rlj_lj_id + $sqh = $dbh->prepare ( + "INSERT INTO rlj_lj_id(userid,ljr_id,lj_id) + VALUES ($user_id, + $entry->{'itemid'}, + $postevent->{'itemid'})"); + $sqh->execute; + }; + #ïÂÒÁÂÏÔËÁ ÉÓËÌÀÞÅÎÉÑ: ÅÓÌÉ ÎÅ ÕÄÁÌÓÑ ×ÙÚÏ× XMLRPC + if ($@) { + print STDERR localtime(time) . ": Posting event on $dest_site failed\n"; + print STDERR "debug5: " . $@; + print STDERR "\n\n"; + }; + #...ÉÎÁÞÅ ÐÏÓÔÉÍ Å£ Ó ÁÔÒÉÂÕÔÏÍ backdate + } else { + $fields->{'props'}->{'opt_backdated'} = 1; + eval { + $postevent = xmlrpc_call('LJ.XMLRPC.postevent', $fields); + #úÁÐÉÓÙ×ÁÅÍ ÓÏÏÔ×ÅÔÓÔ×ÉÅ ID ÉÓÈÏÄÎÏÇÏ ÐÏÓÔÉÎÇÁ É + #ID ÏÔÇÅÊÔÏ×ÁÎÎÏÇÏ ÐÏÓÔÉÎÇÁ × ÔÁÂÌÉÃÕ rlj_lj_id + $sqh = $dbh->prepare ( + "INSERT INTO rlj_lj_id(userid,ljr_id,lj_id) + VALUES ($user_id, + $entry->{'itemid'}, + $postevent->{'itemid'})"); + $sqh->execute; + }; + #ïÂÒÁÂÏÔËÁ ÉÓËÌÀÞÅÎÉÑ: ÅÓÌÉ ÎÅ ÕÄÁÌÓÑ ×ÙÚÏ× XMLRPC + if ($@) { + print STDERR localtime(time) . ": Posting event on $dest_site failed\n"; + print STDERR "debug4: " . $@; + print STDERR "\n\n"; + }; + }; + }; + }; + }; +}; + +sub xmlrpc_call { + my ($method, $req) = @_; + my $res = $xmlrpc->call($method, $req); + if ($res && $res->fault) { + print STDERR "XML-RPC Error:\n". + " String: " . $res->faultstring . "\n" . + " Code: " . $res->faultcode . "\n"; + die; + } + elsif (!$res) { + print STDERR "Unknown XML-RPC Error.\n"; + die; + } + return $res->result; +} diff --git a/obsolete/cgi-bin/DBI/Role.pm.debug b/obsolete/cgi-bin/DBI/Role.pm.debug new file mode 100755 index 0000000..9951881 --- /dev/null +++ b/obsolete/cgi-bin/DBI/Role.pm.debug @@ -0,0 +1,392 @@ +package DBI::Role; + +use 5.006; +use strict; +use warnings; +BEGIN { + $DBI::Role::HAVE_HIRES = eval "use Time::HiRes (); 1;"; +} + +our $VERSION = '1.00'; + +# $self contains: +# +# DBINFO --- hashref. keys = scalar roles, one of which must be 'master'. +# values contain DSN info, and 'role' => { 'role' => weight, 'role2' => weight } +# +# DEFAULT_DB -- scalar string. default db name if none in DSN hashref in DBINFO +# +# DBREQCACHE -- cleared by clear_req_cache() on each request. +# fdsn -> dbh +# +# DBCACHE -- role -> fdsn, or +# fdsn -> dbh +# +# DBCACHE_UNTIL -- role -> unixtime +# +# DB_USED_AT -- fdsn -> unixtime +# +# DB_DEAD_UNTIL -- fdsn -> unixtime +# +# TIME_CHECK -- if true, time between localhost and db are checked every TIME_CHECK +# seconds +# +# TIME_REPORT -- coderef to pass dsn and dbtime to after a TIME_CHECK occurence + +sub new +{ + my ($class, $args) = @_; + my $self = {}; + $self->{'DBINFO'} = $args->{'sources'}; + $self->{'TIMEOUT'} = $args->{'timeout'}; + $self->{'DEFAULT_DB'} = $args->{'default_db'}; + $self->{'TIME_CHECK'} = $args->{'time_check'}; + $self->{'TIME_LASTCHECK'} = {}; # dsn -> last check time + $self->{'TIME_REPORT'} = $args->{'time_report'}; + bless $self, ref $class || $class; + return $self; +} + +sub set_sources +{ + my ($self, $newval) = @_; + $self->{'DBINFO'} = $newval; + $self; +} + +sub clear_req_cache +{ + my $self = shift; + $self->{'DBREQCACHE'} = {}; +} + +sub disconnect_all +{ + my ($self, $opts) = @_; + my %except; + + if ($opts && $opts->{except} && + ref $opts->{except} eq 'ARRAY') { + $except{$_} = 1 foreach @{$opts->{except}}; + } + + foreach my $cache (qw(DBREQCACHE DBCACHE)) { + next unless ref $self->{$cache} eq "HASH"; + foreach my $key (keys %{$self->{$cache}}) { + next if $except{$key}; + my $v = $self->{$cache}->{$key}; + next unless ref $v eq "DBI::db"; + $v->disconnect; + delete $self->{$cache}->{$key}; + } + } + $self->{'DBCACHE'} = {}; + $self->{'DBREQCACHE'} = {}; +} + +sub same_cached_handle +{ + my $self = shift; + my ($role_a, $role_b) = @_; + return + defined $self->{'DBCACHE'}->{$role_a} && + defined $self->{'DBCACHE'}->{$role_b} && + $self->{'DBCACHE'}->{$role_a} eq $self->{'DBCACHE'}->{$role_b}; +} + +sub flush_cache +{ + my $self = shift; + foreach (keys %{$self->{'DBCACHE'}}) { + my $v = $self->{'DBCACHE'}->{$_}; + next unless ref $v; + $v->disconnect; + } + $self->{'DBCACHE'} = {}; + $self->{'DBREQCACHE'} = {}; +} + +# old interface. does nothing now. +sub trigger_weight_reload +{ + my $self = shift; + return $self; +} + +sub use_diff_db +{ + my $self = shift; + my ($role1, $role2) = @_; + + return 0 if $role1 eq $role2; + + # this is implied: (makes logic below more readable by forcing it) + $self->{'DBINFO'}->{'master'}->{'role'}->{'master'} = 1; + + foreach (keys %{$self->{'DBINFO'}}) { + next if /^_/; + next unless ref $self->{'DBINFO'}->{$_} eq "HASH"; + if ($self->{'DBINFO'}->{$_}->{'role'}->{$role1} && + $self->{'DBINFO'}->{$_}->{'role'}->{$role2}) { + return 0; + } + } + return 1; +} + +sub get_dbh +{ + my $self = shift; + my $opts = ref $_[0] eq "HASH" ? shift : {}; + + my @roles = @_; + my $role = shift @roles; + return undef unless $role; + + my $now = time(); + + # if 'nocache' flag is passed, clear caches now so we won't return + # a cached database handle later + $self->clear_req_cache if $opts->{'nocache'}; + + # otherwise, see if we have a role -> full DSN mapping already + my ($fdsn, $dbh); + if ($role eq "master") { + $fdsn = make_dbh_fdsn($self, $self->{'DBINFO'}->{'master'}); + } else { + if ($self->{'DBCACHE'}->{$role} && ! $opts->{'unshared'}) { + $fdsn = $self->{'DBCACHE'}->{$role}; + if ($now > $self->{'DBCACHE_UNTIL'}->{$role}) { + # this role -> DSN mapping is too old. invalidate, + # and while we're at it, clean up any connections we have + # that are too idle. + undef $fdsn; + + foreach (keys %{$self->{'DB_USED_AT'}}) { + next if $self->{'DB_USED_AT'}->{$_} > $now - 60; + delete $self->{'DB_USED_AT'}->{$_}; + delete $self->{'DBCACHE'}->{$_}; + } + } + } + } + + if ($fdsn) { + $dbh = get_dbh_conn($self, $fdsn, $role); + return $dbh if $dbh; + delete $self->{'DBCACHE'}->{$role}; # guess it was bogus + } + return undef if $role eq "master"; # no hope now + + # time to randomly weightedly select one. + my @applicable; + my $total_weight; + foreach (keys %{$self->{'DBINFO'}}) { + next if /^_/; + next unless ref $self->{'DBINFO'}->{$_} eq "HASH"; + my $weight = $self->{'DBINFO'}->{$_}->{'role'}->{$role}; + next unless $weight; + push @applicable, [ $self->{'DBINFO'}->{$_}, $weight ]; + $total_weight += $weight; + } + + while (@applicable) { + my $rand = rand($total_weight); + my ($i, $t) = (0, 0); + for (; $i<@applicable; $i++) { + $t += $applicable[$i]->[1]; + last if $t > $rand; + } + my $fdsn = make_dbh_fdsn($self, $applicable[$i]->[0]); + $dbh = get_dbh_conn($self, $opts, $fdsn); + if ($dbh) { + $self->{'DBCACHE'}->{$role} = $fdsn; + $self->{'DBCACHE_UNTIL'}->{$role} = $now + 5 + int(rand(10)); + return $dbh; + } + + # otherwise, discard that one. + $total_weight -= $applicable[$i]->[1]; + splice(@applicable, $i, 1); + } + + # try others + return get_dbh($self, $opts, @roles); +} + +sub make_dbh_fdsn +{ + my $self = shift; + my $db = shift; # hashref with DSN info + return $db->{'_fdsn'} if $db->{'_fdsn'}; # already made? + + my $fdsn = "DBI:mysql"; # join("|",$dsn,$user,$pass) (because no refs as hash keys) + $db->{'dbname'} ||= $self->{'DEFAULT_DB'} if $self->{'DEFAULT_DB'}; + $fdsn .= ":$db->{'dbname'}"; + $fdsn .= ";host=$db->{'host'}" if $db->{'host'}; + $fdsn .= ";port=$db->{'port'}" if $db->{'port'}; + $fdsn .= ";mysql_socket=$db->{'sock'}" if $db->{'sock'}; + $fdsn .= "|$db->{'user'}|$db->{'pass'}"; + + $db->{'_fdsn'} = $fdsn; + return $fdsn; +} + +sub get_dbh_conn +{ + my $self = shift; + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $fdsn = shift; + my $role = shift; # optional. + my $now = time(); + + my $retdb = sub { + my $db = shift; + $self->{'DBREQCACHE'}->{$fdsn} = $db; + $self->{'DB_USED_AT'}->{$fdsn} = $now; + return $db; + }; + + # have we already created or verified a handle this request for this DSN? + return $retdb->($self->{'DBREQCACHE'}->{$fdsn}) + if $self->{'DBREQCACHE'}->{$fdsn} && ! $opts->{'unshared'}; + + # check to see if we recently tried to connect to that dead server + return undef if $self->{'DB_DEAD_UNTIL'}->{$fdsn} && $now < $self->{'DB_DEAD_UNTIL'}->{$fdsn}; + + # if not, we'll try to find one we used sometime in this process lifetime + my $dbh = $self->{'DBCACHE'}->{$fdsn}; + + # if it exists, verify it's still alive and return it. (but not + # if we're wanting an unshared connection) + if ($dbh && ! $opts->{'unshared'}) { +# return $retdb->($dbh) unless connection_bad($dbh, $opts); + undef $dbh; + undef $self->{'DBCACHE'}->{$fdsn}; + } + + # time to make one! + my ($dsn, $user, $pass) = split(/\|/, $fdsn); + my $timeout = $self->{'TIMEOUT'} || 2; + $dsn .= ";mysql_connect_timeout=$timeout"; + + my $loop = 1; + my $tries = $DBI::Role::HAVE_HIRES ? 8 : 2; + while ($loop) { + $loop = 0; + $dbh = DBI->connect($dsn, $user, $pass, { + PrintError => 1, + AutoCommit => 1, + }); + + # if max connections, try again shortly. + if (! $dbh && $DBI::err == 1040 && $tries) { + $tries--; + $loop = 1; + if ($DBI::Role::HAVE_HIRES) { + Time::HiRes::usleep(250_000); + } else { + sleep 1; + } + } + } + + my $DBI_err = $DBI::err || 0; + + # check replication/busy processes... see if we should not use + # this one +# undef $dbh if connection_bad($dbh, $opts); + + # if this is an unshared connection, we don't want to put it + # in the cache for somebody else to use later. (which happens below) + return $dbh if $opts->{'unshared'}; + + # mark server as dead if dead. won't try to reconnect again for 5 seconds. + if ($dbh) { + $self->{'DB_USED_AT'}->{$fdsn} = $now; + + if ($self->{'TIME_CHECK'} && ref $self->{'TIME_REPORT'} eq "CODE") { + my $now = time(); + $self->{'TIME_LASTCHECK'}->{$dsn} ||= 0; # avoid warnings + if ($self->{'TIME_LASTCHECK'}->{$dsn} < $now - $self->{'TIME_CHECK'}) { + $self->{'TIME_LASTCHECK'}->{$dsn} = $now; + my $db_time = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()"); + $self->{'TIME_REPORT'}->($dsn, $db_time, $now); + } + } + } else { + # mark the database as dead for a bit, unless it was just because of max connections + $self->{'DB_DEAD_UNTIL'}->{$fdsn} = $now + 5 + unless $DBI_err == 1040; + } + + return $self->{'DBREQCACHE'}->{$fdsn} = $self->{'DBCACHE'}->{$fdsn} = $dbh; +} + +sub connection_bad { + my ($dbh, $opts) = @_; + + return 1 unless $dbh; + + my $ss = eval { + $dbh->selectrow_hashref("SHOW SLAVE STATUS"); + }; + + # if there was an error, and it wasn't a permission problem (1227) + # then treat this connection as bogus + if ($dbh->err && $dbh->err != 1227) { + return 1; + } + + # connection is good if $ss is undef (not a slave) + return 0 unless $ss; + + # otherwise, it's okay if not MySQL 4 + return 0 if ! $ss->{'Master_Log_File'} || ! $ss->{'Relay_Master_Log_File'}; + + # all good if within 100 k + if ($opts->{'max_repl_lag'}) { + return 0 if + $ss->{'Master_Log_File'} eq $ss->{'Relay_Master_Log_File'} && + ($ss->{'Read_Master_Log_Pos'} - $ss->{'Exec_master_log_pos'}) < $opts->{'max_repl_lag'}; + + # guess we're behind + return 1; + } else { + # default to assuming it's good + return 0; + } +} + +1; +__END__ + +=head1 NAME + +DBI::Role - Get DBI cached handles by role, with weighting & failover. + +=head1 SYNOPSIS + + use DBI::Role; + my $DBIRole = new DBI::Role { + 'sources' => \%DBINFO, + 'default_db' => "somedbname", # opt. + }; + my $dbh = $DBIRole->get_dbh("master"); + +=head1 DESCRIPTION + +To be written. + +=head2 EXPORT + +None by default. + +=head1 AUTHOR + +Brad Fitzparick, Ebrad@danga.comE + +=head1 SEE ALSO + +L. + diff --git a/obsolete/cgi-bin/LJ/Rewriteuser.pm b/obsolete/cgi-bin/LJ/Rewriteuser.pm new file mode 100755 index 0000000..04e6ff2 --- /dev/null +++ b/obsolete/cgi-bin/LJ/Rewriteuser.pm @@ -0,0 +1,133 @@ +# Package that handles redirects of the form: +# http://[sitename]/users/name1/[digits].html[anything else] => +# http://[sitename]/users/name2/[digits].html[anything else] +# if digits < maxid +# Maxid is a prescribed number, name 1 and name 2 are prescribd usernames. +# The same works for http://[sitename]/~name1/... +# name 2 must be an existing users +# +# How it works: +# all processing of *.html passes through Apache::Livejournal::trans +# A hook has been added to that function that calls +# LJ:Rewriteuser::uri_check, then uri_rew +# The list of known redirects is kept in a table "rewriteusers" in +# the livejournal database; this package also provides functions +# to work with this table in a safe way. +# +# Additionally, the part in LJ::alloc_user_counter which gives id to +# new entries has been modified in the following way: instead of +# taking max of all the existing entries, it now checks whether we +# have a redirect in the table, and if "yes", takes max of all +# existing entries and maxid from redirect table +# +# Table structure: +#+----------+------------------+------+-----+---------+-------+ +#| Field | Type | Null | Key | Default | Extra | +#+----------+------------------+------+-----+---------+-------+ +#| fromuser | char(15) | | PRI | | | +#| touser | char(15) | | | | | +#| maxid | int(10) unsigned | | | 0 | | +#+----------+------------------+------+-----+---------+-------+ + + +package LJ::Rewriteuser; + +use strict; + +use Carp; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use DBI; +use DBI::Role; +use DBIx::StateKeeper; +#use LJ; + +my %REWRITE=(); + +# Check whether uri needs to be rewritten + +sub uri_check { + my ($uri)=@_; + +# Scan the redirect table to see whether username matches + + foreach my $rwuser (keys %REWRITE){ + if ($uri =~ m|users/$rwuser/(\d+)|i) {if($1 < $REWRITE{$rwuser}{'maxnum'}){ return 1;}} + if ($uri =~ m|~$rwuser/(\d+).html|i) {if($1 < $REWRITE{$rwuser}{'maxnum'}){ return 1;}} + if ($uri =~ m|community/$rwuser/(\d+).html|i) {if($1 < $REWRITE{$rwuser}{'maxnum'}){ return 1;}} + } + return 0; +} + +# Rewrite uri (if it's needed -- if not, return the intact original) + +sub uri_rew { + my ($uri)=@_; + if(uri_check($uri)){ + foreach my $rwuser (keys %REWRITE){ + foreach my $type ("~","users/","community/"){ + my $to=$type.$rwuser; + my $from=$type.$REWRITE{$rwuser}{'newname'}; + $uri =~ s|$to|$from|i; + } + } + } + return $uri; +} + +# Check the database for redirects, and if yes, return maxid (to +# give it to LJ:alloc_user_counter). If not, return 0. + +sub get_min_jid { + my ($journalid)= @_; + my $user=LJ::get_username($journalid); + foreach my $rwuser (keys %REWRITE){ + if ($rwuser eq $user){ + return ($REWRITE{$rwuser}{'maxnum'} / 256)+1; + } + } + return 0; +} + +# Check whether there is a redirect from name1, if yes, return +# name2, if not, return 0 + +sub get_rewrite { + my ($fromuser)= @_; + if($REWRITE{$fromuser}) {return $REWRITE{$fromuser}{'newname'};} + else {return 0;} +} + +# The function to init the redirect table in the database during +# httpd restart + +sub init { + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT fromuser, touser, maxid FROM rewriteusers"); + $sth->execute; + while (my ($from, $to, $maxid) = $sth->fetchrow_array) { + $REWRITE{$from}{'newname'}=$to; + $REWRITE{$from}{'maxnum'}=$maxid; + } +} + +# Remove a redirect from the table + +sub delete_rewrite_hash{ + my ($fromuser) = @_; + delete($REWRITE{$fromuser}); + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM rewriteusers WHERE fromuser = ?", undef, $fromuser); +} + +# Add a redirect to the table + +sub insert_rewrite_hash{ + my ($from, $to, $maxid) =@_; + $REWRITE{$from}{'newname'}=$to; + $REWRITE{$from}{'maxnum'}=$maxid; + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO rewriteusers VALUES (?, ?, ?)", undef, $from, $to, $maxid); +} +init(); + +1; diff --git a/obsolete/htdocs/admin/redirectusers.bml b/obsolete/htdocs/admin/redirectusers.bml new file mode 100755 index 0000000..c0fc5ea --- /dev/null +++ b/obsolete/htdocs/admin/redirectusers.bml @@ -0,0 +1,113 @@ + +Redirect users + +\n"; + $ret .= LJ::html_hidden(mode => 'submit', + ssl => $GET{'ssl'}); + + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "
      \n"; + $ret .= "Redirect to:
      \n"; + $ret .= "
      \n"; + $ret .= "Affect entries with numbers strictly less than:
      \n"; + $ret .= "
      \n"; + $ret .= "standout?>\n"; + + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "standout?>\n"; + $ret .= "\n"; + return $ret; +}; + +# If POST didn't accur, give out the HTML form. If it did occur, +# process data + + unless (LJ::did_post()) { + $body .= $update_form->(); + +# Redirect from 'from' to 'to' with maxid 'maxid' + + } elsif ($POST{'mode'} eq 'submit') { + +# Get $from, $to, $maxid, canonicalize $from and $to. + + my $from = LJ::canonical_username($POST{'from'}); + my $to = LJ::canonical_username($POST{'to'}); + my $maxid = $POST{'maxid'}; + +# If $to not emptry, we're adding a redirect + + if ($to ne "") { + +# Check whether maxidx is an integer + + if($maxid =~ /\d+/){ + $maxid=$maxid+0; + +# Check whether we already have a redirect from $from + + if (!(LJ::Rewriteuser::get_rewrite($from))){ + +# We don't have a redirect -- okay, we add it + + LJ::Rewriteuser::insert_rewrite_hash($from,$to,$maxid); + $body = "Success: $from is now redirected to $to with maxid $maxid.
      Please restart httpd before setting any oy other redirects."; + +# We do have redirect already -- do nothing, return error + + } else {$body = "Error: there already is a redirect for this user. Namely, to: ".(LJ::Rewriteuser::get_rewrite($from));} + +# maxid is not an integer -- return error + + } else {$body="Error: maxid must be a number.";} + +# Okay, $to is empty -- this means we're removing a redirect + + } else { + if (LJ::Rewriteuser::get_rewrite($from)){ + LJ::Rewriteuser::delete_rewrite_hash($from); + $body="Success: $from is not redirected anywhere from now on.
      Please restart httpd before setting any oy other redirects."; + } + } + } + return $body; +} +_code?> + + + +lib: cgi-bin/console.pl, cgi-bin/ljlib.pl + _c?> + diff --git a/obsolete/htdocs/img/GJcommunity.gif b/obsolete/htdocs/img/GJcommunity.gif new file mode 100755 index 0000000000000000000000000000000000000000..e69850ec658b1932b4942235db358d1f037a07d7 GIT binary patch literal 163 zcmV;U09^k^Nk%w1VGsZi0J8u9Cmk45KR171QjCUz?kOSvJSXdYGt!4?|I!ry@dp3O zQ~%Ab|K{KS_w)b%@Bjb*A^8LW000jFEC2ui01yBW000C~@X7g%rFe=l1jyLdec4e+ z95MvbDG`M+Aqg@W1@XY-L))m_Lr~~(1d~C5wV@m-0M=uGp+Ym3>;*I}c)dt&hd>5| Rxf_Cq>+G_|GA5OaKTZzDr01DJm*zYHAvS zz*r2V(@;Nm}H90nN+a~GY$U>X>X7k=J zi}Q06{@1l#al_P}*lDU9I>n6_0)%#BtNU$^<%}^{5x%0X) n&EDdKc?o|Wrx1gnP=}CUY6A}!BO?nh1Mk#nJ>hDK3=Gx)?5#@N literal 0 HcmV?d00001 diff --git a/obsolete/htdocs/img/NPJcommunity.gif b/obsolete/htdocs/img/NPJcommunity.gif new file mode 100755 index 0000000000000000000000000000000000000000..4adf015b1c1643a2e66b87234ce4990d95ae951f GIT binary patch literal 305 zcmZ?wbhEHb6k!lyIKsg2{{7uFV}}1{W*Qh6WV`ckU*k6u$Y)>x;%hUT{~um+W@Z|L zfWng(OV<=cHoF-x2ncX1m_`~{+9~q(wwQCsdYqYQJagtupcbq^@h1x-NJ0lhfb3*o zU8kVXmy$Uz!;8(MdS$YJ#I%F^44iHoF)_D4Xnfwx%5tLl&4%``Gy=aB;RNg+;J6F-+j(=j5BG#F56*#~?Iu;>tXZNTv`LC83pbS1;h69_gdB fVn1Kr8e=wY*FF4vtAtb;9nUNCw_Z_FWUvMRqa#?| literal 0 HcmV?d00001 diff --git a/obsolete/htdocs/img/NPJuserinfo.gif b/obsolete/htdocs/img/NPJuserinfo.gif new file mode 100755 index 0000000000000000000000000000000000000000..7364fa94b0fc6f3ceae5bb65da58d976ac647ade GIT binary patch literal 140 zcmZ?wbhEHb!&VUvZ8^5!5RPznJIVx literal 0 HcmV?d00001 diff --git a/obsolete/htdocs/lj-gate/index.bml b/obsolete/htdocs/lj-gate/index.bml new file mode 100755 index 0000000..7f78ddb --- /dev/null +++ b/obsolete/htdocs/lj-gate/index.bml @@ -0,0 +1,14 @@ +Live LJR to LJ export. +body<= + +create or change lj-gate or delete the gate. +p?> + +LJ-gate FAQ +p?> + +<=body +page?> diff --git a/obsolete/htdocs/lj-gate/rlj2lj.bml b/obsolete/htdocs/lj-gate/rlj2lj.bml new file mode 100755 index 0000000..4704d65 --- /dev/null +++ b/obsolete/htdocs/lj-gate/rlj2lj.bml @@ -0,0 +1,144 @@ +1 +_info?> + +body<= + LJ live export parameters. h1?> +
      +underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + if ($remote->identity) { + return "Non-$LJ::SITENAME users can't post, as they don't actually have journals here.\n"; + } + if (! LJ::get_cap($remote, "can_post")) { + return $LJ::MSG_NO_POST || $ML{'.error.cantpost'}; + } + } + else { + return "Please login.\n"; + } + + my $qhost = $LJ::DBINFO{'master'}->{'host'}; + my $quser = $LJ::DBINFO{'master'}->{'user'}; + my $qpass = $LJ::DBINFO{'master'}->{'pass'}; + my $qsock = $LJ::DBINFO{'master'}->{'sock'}; + my $qport = $LJ::DBINFO{'master'}->{'port'}; + #my $qdb = $LJ::DBINFO{'master'}->{'dbname'}; + my $qdb = "prod_ljgate"; + + my $alien=$POST{'alien'}; + my $alienpass=$POST{'alienpass'}; + + my $mode=$POST{'mode'}; + + my $xmlrpc; + my $get_chal; + my $chal; + my $response; + my $login; + + #åÓÌÉ ÎÁÍ ÕÖÅ ÐÅÒÅÄÁÌÉ ÐÁÒÁÍÅÔÒÙ, ÄÏÂÁ×ÌÑÅÍ ÐÏÌØÚÏ×ÁÔÅÌÅÊ... + if ($mode eq "add") { + $xmlrpc = new XMLRPC::Lite; + $xmlrpc->proxy("http://www.livejournal.com/interface/xmlrpc"); + $get_chal = $xmlrpc->call("LJ.XMLRPC.getchallenge"); + $chal = $get_chal->result->{'challenge'}; + $response = md5_hex($chal . md5_hex($alienpass)); + $login = $xmlrpc->call('LJ.XMLRPC.login', { + 'username' => $alien, + 'auth_method' => 'challenge', + 'auth_challenge' => $chal, + 'auth_response' => $response, + }); + + if($login->fault){ + $ret .= "Got error: " . $login->faultstring . "
      "; + $ret .= "Retry."; + return $ret; + } + + #ó×ÑÚÙ×ÁÅÍÓÑ Ó ÂÁÚÏÊ + my $dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb", + $quser, $qpass, + ) || die localtime(time) . ": Can't connect to database\n"; + my $sqh; + + $sqh = $dbh->prepare("delete from our_user where our_user = ?"); + $sqh->execute($remote->{'user'}); + + $sqh = $dbh->prepare("insert INTO our_user (our_user,our_pass) VALUES(?, ?)"); + $sqh->execute($remote->{'user'}, $remote->{'password'}); + + $sqh = $dbh->prepare("INSERT INTO alien (alien,alienpass) VALUES(?, ?)"); + $sqh->execute($alien, $alienpass); + + #õÚÎÁ£Í ID Ó×ÅÖÅÄÏÂÁ×ÌÅÎÎÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ + #...ÎÁ Ó×Ï£Í ÓÅÒ×ÅÒÅ + $sqh = $dbh->prepare("SELECT userid FROM our_user WHERE our_user=?"); + $sqh->execute($remote->{'user'}); + + my $userid=$sqh->fetchrow_array; + + #...É ÎÁ ÞÕÖÏÍ + $sqh = $dbh->prepare("SELECT alienid FROM alien WHERE alien=?"); + $sqh->execute($alien); + + my $alienid=$sqh->fetchrow_array; + + #äÏÂÁ×ÌÑÅÍ ÎÏ×ÕÀ ÚÁÐÉÓØ × ÔÁÂÌÉÃÕ ÖÕÒÎÁÌÏ×, + #ËÏÔÏÒÙÅ ËÏÐÉÒÕÀÔÓÑ Ó ÎÁÛÅÇÏ ÓÅÒ×ÅÒÁ ×Ï×ÎÅ + $sqh = $dbh->prepare("INSERT INTO rlj2lj(userid,alienid) VALUES (?,?)"); + $sqh->execute($userid, $alienid); + + $ret .= "
      Export parameters updated: "; + $ret .= "{'user'}>$remote->{'user'} is exported to $alien."; + $ret .= "

      LJ-gate root"; + + $dbh->disconnect; + + } else { + $ret .= "
      \n"; + $ret .= LJ::html_hidden(mode => 'add'); + $ret .= "
      "; + $ret .= "Livejournal.com
      "; + $ret .= "
      " . BML::ml('Username') . "
      "; + $ret .= LJ::html_text({'name' => 'alien', + 'size' => 15, + 'maxlength' => 15, + }); + $ret .= "
      " . BML::ml('Password') . "
      "; + $ret .= LJ::html_text({'name' => 'alienpass', + 'size' => 30, + 'maxlength' => 31, + 'type' => "password",}); + $ret .= "
      "; + $ret .= LJ::html_submit('confirm', $ML{'.confirm.submit'}); + $ret .= "
      \n"; + }; + + return $ret; + +_code?> + +<=body +page?> diff --git a/obsolete/htdocs/lj-gate/rlj_delete.bml b/obsolete/htdocs/lj-gate/rlj_delete.bml new file mode 100755 index 0000000..4150ce7 --- /dev/null +++ b/obsolete/htdocs/lj-gate/rlj_delete.bml @@ -0,0 +1,104 @@ +1 +_info?> + +body<= + LJ live export. h1?> +
      +underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + if ($remote->identity) { + return "Non-$LJ::SITENAME users can't post, as they don't actually have journals here.\n"; + } + if (! LJ::get_cap($remote, "can_post")) { + return $LJ::MSG_NO_POST || $ML{'.error.cantpost'}; + } + } + else { + return "Please login.\n"; + } + + my $qhost = $LJ::DBINFO{'master'}->{'host'}; + my $quser = $LJ::DBINFO{'master'}->{'user'}; + my $qpass = $LJ::DBINFO{'master'}->{'pass'}; + my $qsock = $LJ::DBINFO{'master'}->{'sock'}; + my $qport = $LJ::DBINFO{'master'}->{'port'}; + #my $qdb = $LJ::DBINFO{'master'}->{'dbname'}; + my $qdb = "prod_ljgate"; + + my $dbh = DBI->connect( + "DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb", + $quser, $qpass, + ) || die localtime(time) . ": Can't connect to database\n"; + my $sqh; + + #ID ÕÄÁÌÑÅÍÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ LJR + my $user_id; + #ID ÕÄÁÌÑÅÍÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ LiveJournal + my $alien_id; + + #÷Ù×ÏÄÉÍ ÆÏÒÍÕ ÉÌÉ ÄÏÂÁ×ÌÑÅÍ ÐÏÌØÚÏ×ÁÔÅÌÑ × ÂÁÚÕ? + my $mode=$POST{'mode'}; + + #÷Ù×ÏÄ + my $ret; + + #åÓÌÉ ÎÁÍ ÕÖÅ ÐÅÒÅÄÁÌÉ ÐÁÒÁÍÅÔÒÙ, ÕÄÁÌÑÅÍ ÐÏÌØÚÏ×ÁÔÅÌÑ... + if ($mode eq "del") { + #úÁÂÉÒÁÅÍ ÉÚ ÔÁÂÌÉÃÙ our_user ID, ÌÏÇÉÎ É ÐÁÒÏÌØ ÕÄÁÌÑÅÍÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ + my $sqh=$dbh->prepare("SELECT userid FROM our_user WHERE our_user=?"); + $sqh->execute($remote->{'user'}); + $user_id = $sqh->fetchrow_array; + + #úÁÂÉÒÁÅÍ ÉÚ ÔÁÂÌÉÃÙ rlj2lj ID ÐÏÌØÚÏ×ÁÔÅÌÑ ÞÕÖÏÇÏ ÒÅÓÕÒÓÁ + $sqh = $dbh->prepare("SELECT alienid FROM rlj2lj WHERE userid=?"); + $sqh->execute ($user_id); + $alien_id = $sqh->fetchrow_array; + + #õÄÁÌÑÅÍ ÚÁÐÉÓØ ÉÚ ÔÁÂÌÉÃÙ rlj2lj + $sqh = $dbh->prepare("DELETE FROM rlj2lj WHERE userid=?"); + $sqh->execute($user_id); + + #õÄÁÌÑÅÍ ÄÁÎÎÙÅ Ï ÞÕÖÏÍ ÐÏÌØÚÏ×ÁÔÅÌÅ + $sqh = $dbh->prepare("DELETE FROM alien WHERE alienid=?"); + $sqh->execute($alien_id); + + #õÄÁÌÑÅÍ ÄÁÎÎÙÅ Ï ÎÁÛÅÍ ÐÏÌØÚÏ×ÁÔÅÌÅ + $sqh = $dbh->prepare("DELETE FROM our_user WHERE userid=?"); + $sqh->execute($user_id); + + #õÄÁÌÑÅÍ ÄÁÎÎÙÅ Ï ÐÏÓÔÉÎÇÁÈ + $sqh = $dbh->prepare("DELETE FROM rlj_lj_id WHERE userid=?"); + $sqh->execute($user_id); + + $ret .= "
      Live LJR -> LJ export removed."; + $ret .= "

      LJ-gate root"; + } + #...× ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ×Ù×ÏÄÉÍ ÆÏÒÍÕ + else { + $ret .= "
      \n"; + $ret .= LJ::html_hidden(mode => 'del'); + $ret .= LJ::html_submit('confirm', 'Remove export!'); + }; + + $dbh->disconnect; + return $ret; + +_code?> +<=body +page?> diff --git a/obsolete/htdocs/paidaccounts/index.html b/obsolete/htdocs/paidaccounts/index.html new file mode 100755 index 0000000..a390f26 --- /dev/null +++ b/obsolete/htdocs/paidaccounts/index.html @@ -0,0 +1,10 @@ +Paid Accounts + + +

      íÙ ÒÁÂÏÔÁÅÍ ÎÁÄ ÜÔÉÍ!!

      + +

      ðÏËÁ ÞÔÏ ÓÉÓÔÅÍÁ ÏÐÌÁÔÙ ÎÅ ÎÁÌÁÖÅÎÁ -- ÍÙ ÎÅ ÍÏÖÅÍ ÎÉ ÐÒÉÎÉÍÁÔØ +ÄÅÎØÇÉ ÚÁ ÐÌÁÔÎÙÅ ÁËËÁÕÎÔÙ, ÎÉ ÐÒÉÎÉÍÁÔØ ×ÁÛÉ ÐÏÖÅÒÔ×Ï×ÁÎÉÑ ÎÁ +ÒÁÚ×ÉÔÉÅ É ÐÏÄÄÅÒÖËÕ ÓÅÒ×ÅÁ. îÏ ÍÙ ÒÁÂÏÔÁÅÍ ÎÁÄ ÜÔÉÍ; ÓÌÅÄÉÔÅ ÚÁ +ÎÏ×ÏÓÔÑÍÉ. + diff --git a/wcmtools/bin/apidoc.pl b/wcmtools/bin/apidoc.pl new file mode 100755 index 0000000..e7ed8c3 --- /dev/null +++ b/wcmtools/bin/apidoc.pl @@ -0,0 +1,243 @@ +#!/usr/bin/perl + +# This script parses LJ function info from all the library files +# that make up the site. See cgi-bin/ljlib.pl for an example +# of the necessary syntax. + +use strict; +use Getopt::Long; +use Data::Dumper; + +my $opt_warn = 0; +my $opt_file; +my $opt_stubs = 0; # generate stubs of undoced funcs +my $opt_class = 0; # group by class +my ($opt_include, $opt_exclude); # which packages to inc/excl +my @do_dirs; +my $basedir; +my $opt_conf; +die unless GetOptions( + 'warn' => \$opt_warn, + 'file=s' => \$opt_file, + 'stubs' => \$opt_stubs, + 'class' => \$opt_class, + 'include=s' => \$opt_include, + 'exclude=s' => \$opt_exclude, + 'conf=s' => \$opt_conf, + ); + +die "Unknown arguments.\n" if @ARGV; +die "Can't exclude and include at same time!\n" if $opt_include && $opt_exclude; + +my (@classes, %classname, %common_args); +if ($opt_conf) { + open (C, $opt_conf) or die "Can't open conf file: $opt_conf\n"; + while () + { + chomp; + if (/^basedir\s+(\S+)$/) { + $basedir = $1; + $basedir =~ s/\$(\w+)/$ENV{$1} or die "Undefined ENV: $1"/eg; + } elsif (/^dodir\s+(\S+)$/) { + push @do_dirs, $1; + } elsif (/^class\s+(\w+)\s+(.+)/) { + push @classes, $1; + $classname{$1} = $2; + } elsif (/^arg\s+(\S+)\s+(.+)/) { + $common_args{$1} = $2; + } elsif (/\S/) { + die "Unknown line in conf file:\n$_\n"; + } + } + close C; +} + +my %funcs; +if ($opt_file) { + check_file($opt_file); +} else { + unless ($basedir) { + die "No base directory specified.\n"; + } + chdir $basedir or die "Can't cd to base: $basedir\n"; + foreach (@do_dirs) { + find($_); + } +} + +exit if $opt_warn; + +if ($opt_class) +{ + my %by_class; + foreach my $n (sort keys %funcs) { + my $f = $funcs{$n}; + push @{$by_class{$f->{'class'}}}, $f; + } + my $ret = []; + foreach my $cn (@classes) { + push @$ret, [ $classname{$cn}, $by_class{$cn} ]; + } + print Dumper($ret); + exit; +} + +print Dumper(\%funcs); +exit; + +sub find +{ + my @dirs = @_; + while (@dirs) + { + my $dir = shift @dirs; + + opendir (D, $dir) or die "Can't open dir: $dir\n"; + my @files = sort { $a cmp $b } readdir(D); + close D; + + foreach my $f (@files) { + next if ($f eq "." || $f eq ".."); + my $full = "$dir/$f"; + if (-d $full) { find($full); } + elsif (-f $full) { check_file($full); } + } + } + +} + +sub check_file +{ + $_ = shift; + return unless (-f); + return if (/\.(gif|jpg|png|class|jar|zip|exe|orig|rej)$/); + return if (/~$/); + + my $curpackage = ""; + + my $file = $_; + my $infunc = 0; + my $f; # the current function info we're loading + + my $prefix; + my $curkey; + my $contlen; + + open (F, $file) or die "Can't open file: $file\n"; + while (my $l = ) + { + if ($l =~ /^package\s*(.+);/) { + $curpackage = $1; + } + if ($opt_warn && $curpackage && $l =~ /^sub\s+([a-zA-Z0-9]\S+)/) { + my $s = $1; + my $total = $curpackage . "::" . $s; + unless ($funcs{$total}) { + print STDERR "Undocumented: $total\n"; + + if ($opt_stubs) { + print "# \n"; + print "# name: $total\n"; + print "# class: \n"; + print "# des: \n"; + print "# info: \n"; + print "# args: \n"; + print "# des-: \n"; + print "# returns: \n"; + print "# \n"; + } + } + } + + print $l if $opt_stubs; + + if (! $infunc) { + if ($l =~ //) { + $infunc = 1; + $f = {}; + } + next; + } + + if ($l =~ /<\/LJFUNC>/) { + $infunc = 0; + $prefix = ""; + $curkey = ""; + $contlen = 0; + my $include = 0; + if ($opt_exclude) { + $include = 1; + $include = 0 if $f->{'name'} =~ /^$opt_exclude/; + } elsif ($opt_include) { + $include = 1 if $f->{'name'} =~ /^$opt_include/; + } elsif (! $opt_include && ! $opt_exclude) { + $include = 1; + } + if ($f->{'name'} && $include) { + $f->{'source'} = $file; + $f->{'class'} ||= "general"; + unless ($classname{$f->{'class'}}) { + print STDERR "Unknown class: $f->{'class'} ($f->{'name'})\n"; + } + $funcs{$f->{'name'}} = $f; + treeify($f); + } + next; + } + + # continuing a line from line before... must have + # same indenting. + if ($prefix && $contlen) { + my $cont = $prefix . " "x$contlen; + if ($l =~ /^\Q$cont\E(.+)/) { + my $v = $1; + $v =~ s/^\s+//; + $v =~ s/\s+$//; + $f->{$curkey} .= " " . $v; + next; + } + } + + if ($l =~ /^(\W*)([\w\-]+)(:\s*)(.+)/) { + $prefix = $1; + my $k = $2; + my $v = $4; + $v =~ s/^\s+//; + $v =~ s/\s+$//; + $f->{$k} = $v; + $curkey = $k; + $contlen = length($2) + length($3); + } + } + close (F); + +} + +sub treeify +{ + my $f = shift; + my $args = $f->{'args'}; + $f->{'args'} = []; + + $args =~ s/\s+//g; + foreach my $arg (split(/\,/, $args)) + { + my $opt = 0; + if ($arg =~ s/\?$//) { $opt = 1; } + my $list = 0; + if ($arg =~ s/\*$//) { $list = 1; } + my $a = { 'name' => $arg }; + if ($opt) { $a->{'optional'} = 1; } + if ($list) { $a->{'list'} = 1; } + $a->{'des'} = $f->{"des-$arg"} || $common_args{$arg}; + delete $f->{"des-$arg"}; + unless ($a->{'des'}) { + if ($opt_warn) { + print "Warning: undescribed argument '$arg' in $a->{'name'}\n"; + } + } + push @{$f->{'args'}}, $a; + } + + +} diff --git a/wcmtools/bin/multicvs.pl b/wcmtools/bin/multicvs.pl new file mode 100755 index 0000000..1cd328f --- /dev/null +++ b/wcmtools/bin/multicvs.pl @@ -0,0 +1,268 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; + +$| = 1; + +my $help = 0; +my $sync = 0; +my $diff = 0; +my $cvsonly = 0; +my $liveonly = 0; +my $init = 0; +my $conf; +my $opt_update; +my $opt_justfiles; +my $opt_ignore_space; +my $these_flag; + +exit 1 unless GetOptions('conf=s' => \$conf, + 'help' => \$help, + 'sync' => \$sync, + 'diff' => \$diff, + 'cvsonly|c' => \$cvsonly, + 'liveonly' => \$liveonly, + 'init' => \$init, + 'update' => \$opt_update, + 'justfiles|1' => \$opt_justfiles, + 'no-space-changes|b|w' => \$opt_ignore_space, + 'these|t' => \$these_flag, + ); + +if ($help or not defined $conf) { + die "Usage: multicvs.pl --conf=/path/to/multicvs.conf [opts] [files]\n" . + " --help Get this help\n" . + " --sync Put files where they need to go.\n" . + " All files, unless you specify which ones.\n". + " --diff Show diffs of changed files.\n". + " --cvsonly Don't consider files changed in live dirs.\n". + " --liveonly Don't consider files changed in the CVS dirs.\n". + " --init Copy all files from cvs to main, unconditionally.\n" . + " --update Updates files in the CVS dirs from the cvs repositories.\n". + " --justfiles -1 Only output files, not the old -> new arrow. (good for xargs)\n". + " --no-space-changes -b Do not display whitespace differences.\n". + " --these -t Refuse to --sync if no files are specified.\n"; +} + +if ($init) { + $sync = 1; + die "Can't set --liveonly or --cvsonly with --init\n" + if $cvsonly or $liveonly; + $diff = 0; +} + +unless (-e $conf) { + die "Specified conf file doesn't exist: $conf\n"; +} + +my ($DIR_LIVE, $DIR_CVS); +my @paths; + +my $read_conf = sub +{ + my $file = shift; + my $main = shift; + + open (C, $file) or die "Error opening conf file.\n"; + while () + { + s/\#.*//; + next unless /\S/; + s/^\s+//; + s/\s+$//; + s/\$(\w+)/$ENV{$1} or die "Environment variable \$$1 not set.\n"/ge; + + if (/(\w+)\s*=\s*(.+)/) { + my ($k, $v) = ($1, $2); + unless ($main) { + die "Included config files can't set variables such as $k.\n"; + } + if ($k eq "LIVEDIR") { $DIR_LIVE = $v; } + elsif ($k eq "CVSDIR") { $DIR_CVS = $v; } + else { die "Unknown option $k = $v\n"; } + next; + } + + if (/(\S+)\s+(.+)/) { + my ($from, $to) = ($1, $2); + my $maybe = 0; + if ($from =~ s/\?$//) { $maybe = 1; } + push @paths, { + 'from' => $from, + 'to' => $to, + 'maybe' => $maybe, + }; + } else { + die "Bogus line: $_\n"; + } + } + close C; +}; +$read_conf->($conf, 1); + +if ($conf =~ /^(.+)(multicvs\.conf)$/) { + my $localconf = "$1multicvs-local.conf"; + $read_conf->($localconf) if -e $localconf; +} + +my %cvspath; # live path -> cvs path +my %have_updated;; + +foreach my $p (@paths) +{ + unless (-e "$DIR_CVS/$p->{'from'}") { + warn "WARNING: $p->{'from'} doesn't exist under $DIR_CVS\n" + unless $p->{'maybe'}; + next; + } + + if ($opt_update) { + my $root = $p->{'from'}; + $root =~ s!/.*!!; + my $dir = "$DIR_CVS/$root"; + if (-d $dir && ! $have_updated{$dir}) { + chdir $dir or die "Can't cd to $dir\n"; + print "Updating CVS dir '$root' ...\n"; + system("cvs", "update", "-dP"); + $have_updated{$dir} = 1; + } + } + + if (-f "$DIR_CVS/$p->{'from'}") { + $cvspath{$p->{'to'}} = $p->{'from'}; + next; + } + + $p->{'to'} =~ s!/$!!; + my $to_prefix = "$p->{'to'}/"; + $to_prefix =~ s!^\./!!; + + my @dirs = ($p->{'from'}); + while (@dirs) + { + my $dir = shift @dirs; + my $fulldir = "$DIR_CVS/$dir"; + + opendir (MD, $fulldir) or die "Can't open $fulldir."; + while (my $file = readdir(MD)) { + next if ($file =~ /~$/); # ignore emacs files + next if ($file =~ /^\.\#/); # ignore CVS archived versions + next if ($file =~ /\bCVS\b/); + next if $file eq "." or $file eq ".."; + if (-d "$fulldir/$file") { + unshift @dirs, "$dir/$file"; + } elsif (-f "$fulldir/$file") { + my $to = "$dir/$file"; + $to =~ s!^$p->{'from'}/!!; + $cvspath{"$to_prefix$to"} = "$dir/$file"; + } + } + close MD; + } +} + +# If the user has specified that there must be arguments, require @ARGV to +# contain soemthing. +die "These what?\n\nWith --these specified, you must provide at least one file to sync.\n" + if $these_flag && $sync && !@ARGV; + +my @files = scalar(@ARGV) ? @ARGV : sort keys %cvspath; +foreach my $relfile (@files) +{ + my $status; + next unless exists $cvspath{$relfile}; + my $root = $cvspath{$relfile}; + $root =~ s!/.*!!; + + my ($from, $to); # if set, do action (diff and/or sync) + + my $lfile = "$DIR_LIVE/$relfile"; + my $cfile = "$DIR_CVS/$cvspath{$relfile}"; + + if ($init) { + $status = "main <- $root"; + ($from, $to) = ($cfile, $lfile); + } else { + my $ltime = mtime($lfile); + my $ctime = mtime($cfile); + next if $ltime == $ctime; + if ($ltime > $ctime && ! $cvsonly) { + $status = "main -> $root"; + ($from, $to) = ($lfile, $cfile); + } + if ($ctime > $ltime && ! $liveonly) { + $status = "main <- $root"; + ($from, $to) = ($cfile, $lfile); + } + } + + next unless $status; + + my $the_diff; + if ($diff && -e $from && -e $to) { + my $opt; + $opt = '-b' if $opt_ignore_space; + $the_diff = `diff -u $opt $to $from`; # getting from destination to source + if ($the_diff) { + # fix the -p level to be -p0 + my $slashes = ($DIR_LIVE =~ tr!/!/!); + $the_diff =~ s/((^|\n)[\-\+]{3,3} )\/([^\/]+?\/){$slashes,$slashes}/$1/g; + } else { + # don't touch the files that don't have a diff if we're ignoring spaces + # as there might really be one and we just don't see it + next if $opt_ignore_space; + + # no real change (just touched/copied?), so copy + # cvs one on top to fix times up. + copy($from, $to); + next; + } + } + if ($sync) { + make_dirs($relfile); + copy($from, $to); + } + + if ($opt_justfiles) { + print "$relfile\n"; + } else { + printf "%-25s %s\n", $status, $relfile; + print $the_diff; + } +} + +sub mtime +{ + my $file = shift; + return (stat($file))[9]; +} + +my %MADE_DIR; +sub make_dirs +{ + my $file = shift; + return 1 unless $file =~ s!/[^/]*$!!; + return 1 if $MADE_DIR{$file}; + my @dirs = split(m!/!, $file); + for (my $i=0; $iset_handlers(PerlTransHandler => [ \&trans ]); + return OK; +} + +sub trans +{ + my $r = shift; + my $uri = $r->uri; + + my $path = $ROOT . $uri; + + if ($r->method_number == M_GET) { + # get requests just go through to the file system. + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => sub { + my $r = shift; + # let apache handle it. + $r->filename($path); + return DECLINED; + }); + return OK; + } elsif ($r->method_number == M_PUT || + $r->method_number == M_DELETE) { + # /cluster/u1/u2/u3/type/m1/m2 + # 1 2 3 4 5 6 7 + return HTTP_BAD_REQUEST unless $uri =~ m#^/\d+/\d+/\d+/\d+/\w+/\d+/\d+\.\w+$#; + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => sub { + my $r = shift; + return delete_blob($r) if $r->method_number == M_DELETE; + return HTTP_NO_CONTENT if $r->method_number == M_PUT && save_blob($r, $path); + return SERVER_ERROR; + }); + return OK; + } + return HTTP_BAD_REQUEST; +} + +# directory listing +# sub dir_trans +# { +# my ($r, $uri) = @_; +# if ($uri =~ m#^/(\d+)/(\d+)/(\w+)/?$#) { +# my ($cid, $uid) = ($1, $2, $3); +# $r->handler("perl-script"); +# $r->notes(dir => make_path($cid, $uid)); +# $r->push_handlers(PerlHandler => \&dirlisting); +# return OK; +# } +# if ($uri =~ m#^/(\d+)/(\d+)/?$#) { +# my ($cid, $uid) = ($1, $2); +# $r->handler("perl-script"); +# $r->notes(dir => make_path($cid, $uid)); +# $r->push_handlers(PerlHandler => \&dirlisting); +# return OK; +# } +# return 400; +# } + +# sub dirlisting +# { +# my $r = shift; +# return 404 unless (opendir(DIR, $r->notes('dir'))); +# $r->content_type("text/plain"); +# $r->send_http_header(); +# foreach my $f (readdir(DIR)) { +# next if $f eq '.' or $f eq '..'; +# $r->print("$f\n"); +# } +# closedir(DIR); +# return OK; +# } + +# blob access +# sub blob_trans +# { +# my ($r, $uri, $cid, $uid, $mid) = @_; +# my $path = make_path($cid, $uid, $mid); +# +# if ($r->method_number == M_PUT) { +# } else { +# return 404 unless -r $path; +# $r->handler("perl-script"); +# $r->push_handlers(PerlHandler => sub { +# my $r = shift; +# +# # these content-types aren't exactly correct. +# if ($blobtype eq 'audio') { +# $r->content_type("audio/mp3"); +# } else { +# $r->content_type("application/octet-stream"); +# } +# $r->send_http_header(); +# +# # let apache handle sending the file. +# $r->filename($path); +# return DECLINED; +# }); +# } +# } + +sub make_dirs +{ + my $filename = shift; + my $dir = File::Basename::dirname($filename); + eval { File::Path::mkpath($dir, 0, 0775); }; + return $@ ? 0 : 1; +} + +sub save_blob +{ + my ($r, $path) = @_; + + my $length = $r->header_in("Content-Length"); + + make_dirs($path); + open(FILE, ">$path.tmp") or die "couldn't make $path"; + binmode(FILE); + flock(FILE, LOCK_EX) or die "couldn't lock"; + + my ($buff, $lastsize); + my $got = 0; + my $nextread = 4096; + $r->soft_timeout("save_blob"); # ? + while ($got <= $length && ($lastsize = $r->read_client_block($buff, $nextread))) { + $r->reset_timeout; + $got += $lastsize; + print FILE $buff; + if ($length - $got < 4096) { $nextread = $length - $got; } + } + $r->kill_timeout; + + flock(FILE, LOCK_UN) or die "couldn't unlock"; + close(FILE) or die "couldn't close"; + + if ($got != $length) { + unlink("$path.tmp"); + return 0; + } + + if (-s "$path.tmp" == $length) { + return 1 if rename("$path.tmp", $path); + } + + unlink("$path.tmp"); + return 0; +} + +sub delete_blob +{ + my $r = shift; + my $uri = $r->uri; + my $path = $ROOT . $uri; + return NOT_FOUND unless -e $path; + + unlink($path) or return SERVER_ERROR; + + for (1..2) { + next unless $uri =~ s!/[^/]+$!!; + $path = $ROOT . $uri; + last unless rmdir $path; + } + + return HTTP_NO_CONTENT; +} + diff --git a/wcmtools/blobserver/lib/modperl.pl b/wcmtools/blobserver/lib/modperl.pl new file mode 100755 index 0000000..ff1322a --- /dev/null +++ b/wcmtools/blobserver/lib/modperl.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'BLOBHOME'}/lib"; +use Apache; + +Apache->httpd_conf(qq{ +PerlInitHandler +Apache::Blob +}); + +# delete this file from %INC to ensure it's reloaded +# after restarts +delete $INC{"$ENV{'BLOBHOME'}/lib/modperl.pl"}; + +1; diff --git a/wcmtools/ddlockd/api/perl/DDLockClient.pm b/wcmtools/ddlockd/api/perl/DDLockClient.pm new file mode 100755 index 0000000..a1e4b7f --- /dev/null +++ b/wcmtools/ddlockd/api/perl/DDLockClient.pm @@ -0,0 +1,363 @@ +#!/usr/bin/perl +########################################################################### + +=head1 NAME + +DDLockClient - Client library for distributed lock daemon + +=head1 SYNOPSIS + + use DDLockClient (); + + my $cl = new DDLockClient ( + servers => ['locks.localnet:7004', 'locks2.localnet:7002', 'localhost'] + ); + + # Do something that requires locking + if ( my $lock = $cl->trylock("foo") ) { + ...do some 'foo'-synchronized stuff... + } else { + die "Failed to lock 'foo': $!"; + } + + # You can either just let $lock go out of scope or explicitly release it: + $lock->release; + +=head1 DESCRIPTION + +This is a client library for ddlockd, a distributed lock daemon not entirely +unlike a very simplified version of the CPAN module IPC::Locker. + +=head1 REQUIRES + +L + +=head1 EXPORTS + +Nothing. + +=head1 AUTHOR + +Brad Fitzpatrick + +Copyright (c) 2004 Danga Interactive, Inc. + +=cut + +########################################################################### + +##################################################################### +### D D L O C K C L A S S +##################################################################### +package DDLock; + +BEGIN { + use Socket qw{:DEFAULT :crlf}; + use IO::Socket::INET (); + + use constant DEFAULT_PORT => 7002; + + use fields qw( name sockets pid ); +} + + + +### (CONSTRUCTOR) METHOD: new( $name, @sockets ) +### Create a new lock object that corresponds to the specified I and is +### held by the given I. +sub new { + my DDLock $self = shift; + $self = fields::new( $self ) unless ref $self; + + $self->{pid} = $$; + $self->{name} = shift; + $self->{sockets} = $self->getlocks( $self->{name}, @_ ); + + return $self; +} + + +### (PROTECTED) METHOD: getlocks( $lockname, @servers ) +### Try to obtain locks with the specified I from one or more of the +### given I. +sub getlocks { + my DDLock $self = shift; + my $lockname = shift; + my @servers = @_; + + my ( + @sockets, + $sock, + $res, + ); + + # First create connected sockets to all the lock hosts + @sockets = (); + SERVER: foreach my $server ( @servers ) { + my ( $host, $port ) = split /:/, $server; + $port ||= DEFAULT_PORT; + + my $sock = new IO::Socket::INET ( + PeerAddr => $host, + PeerPort => $port, + Proto => "tcp", + Type => SOCK_STREAM, + ReuseAddr => 1, + Blocking => 1, + ) or next SERVER; + + $sock->printf( "trylock lock=%s%s", eurl($lockname), CRLF ); + chomp( $res = <$sock> ); + die "$server: '$lockname' $res\n" unless $res =~ m{^ok\b}i; + + push @sockets, $sock; + } + + die "No available lock hosts" unless @sockets; + return \@sockets; +} + + +### METHOD: release() +### Release the lock held by the lock object. Returns the number of sockets that +### were released on success, and dies with an error on failure. +sub release { + my DDLock $self = shift; + + my ( + $count, + $res, + $sock, + ); + + # lock server might have gone away, but we don't really care. + local $SIG{'PIPE'} = "IGNORE"; + + $count = 0; + while (( $sock = shift @{$self->{sockets}} )) { + $sock->printf( "releaselock lock=%s%s", eurl($self->{name}), CRLF ); + chomp( $res = <$sock> ); + + if ( $res && $res !~ m{^ok\b}i ) { + my $port = $sock->peerport; + my $addr = $sock->peerhost; + die "releaselock ($addr): $res\n"; + } + + $count++; + } + + return $count; +} + + +### FUNCTION: eurl( $arg ) +### URL-encode the given I and return it. +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_,.\\: -])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + + + +##################################################################### +### D D F I L E L O C K C L A S S +##################################################################### +package DDFileLock; + +BEGIN { + use Fcntl qw{:DEFAULT :flock}; + use File::Spec qw{}; + use File::Path qw{mkpath}; + use IO::File qw{}; + + use fields qw{name path tmpfile pid}; +} + + +our $TmpDir = File::Spec->tmpdir; + +### (CONSTRUCTOR) METHOD: new( $lockname ) +### Createa a new file-based lock with the specified I. +sub new { + my DDFileLock $self = shift; + $self = fields::new( $self ) unless ref $self; + my ( $name, $lockdir ) = @_; + + $self->{pid} = $$; + + $lockdir ||= $TmpDir; + if ( ! -d $lockdir ) { + # Croaks if it fails, so no need for error-checking + mkpath $lockdir; + } + + my $lockfile = File::Spec->catfile( $lockdir, eurl($name) ); + + # First open a temp file + my $tmpfile = "$lockfile.$$.tmp"; + if ( -e $tmpfile ) { + unlink $tmpfile or die "unlink: $tmpfile: $!"; + } + + my $fh = new IO::File $tmpfile, O_WRONLY|O_CREAT|O_EXCL + or die "open: $tmpfile: $!"; + $fh->close; + undef $fh; + + # Now try to make a hard link to it + link( $tmpfile, $lockfile ) + or die "link: $tmpfile -> $lockfile: $!"; + unlink $tmpfile or die "unlink: $tempfile: $!"; + + $self->{path} = $lockfile; + $self->{tmpfile} = $tmpfile; + + return $self; +} + + +### METHOD: release() +### Release the lock held by the object. +sub release { + my DDFileLock $self = shift; + return unless $self->{path}; + unlink $self->{path} or die "unlink: $self->{path}: $!"; + unlink $self->{tmpfile}; +} + + +### FUNCTION: eurl( $arg ) +### URL-encode the given I and return it. +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_,.\\: -])/sprintf("%%%02X",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + + +DESTROY { + my $self = shift; + $self->release if $$ == $self->{pid}; +} + + +##################################################################### +### D D L O C K C L I E N T C L A S S +##################################################################### +package DDLockClient; +use strict; + +BEGIN { + use fields qw( servers lockdir ); + use vars qw{$Error}; +} + +$Error = undef; + +our $Debug = 0; + + +### (CLASS) METHOD: DebugLevel( $level ) +sub DebugLevel { + my $class = shift; + + if ( @_ ) { + $Debug = shift; + if ( $Debug ) { + *DebugMsg = *RealDebugMsg; + } else { + *DebugMsg = sub {}; + } + } + + return $Debug; +} + + +sub DebugMsg {} + + +### (CLASS) METHOD: DebugMsg( $level, $format, @args ) +### Output a debugging messages formed sprintf-style with I and I +### if I is greater than or equal to the current debugging level. +sub RealDebugMsg { + my ( $class, $level, $fmt, @args ) = @_; + return unless $Debug >= $level; + + chomp $fmt; + printf STDERR ">>> $fmt\n", @args; +} + + +### (CONSTRUCTOR) METHOD: new( %args ) +### Create a new DDLockClient +sub new { + my DDLockClient $self = shift; + my %args = @_; + + $self = fields::new( $self ) unless ref $self; + die "Servers argument must be an arrayref if specified" + unless !exists $args{servers} || ref $args{servers} eq 'ARRAY'; + $self->{servers} = $args{servers} || []; + $self->{lockdir} = $args{lockdir} || ''; + + return $self; +} + + +### METHOD: trylock( $name ) +### Try to get a lock from the lock daemons with the specified I. Returns +### a DDLock object on success, and undef on failure. +sub trylock { + my DDLockClient $self = shift; + my $lockname = shift; + + my $lock; + + # If there are servers to connect to, use a network lock + if ( @{$self->{servers}} ) { + $self->DebugMsg( 2, "Creating a new DDLock object." ); + $lock = eval { DDLock->new($lockname, @{$self->{servers}}) }; + } + + # Otherwise use a file lock + else { + $self->DebugMsg( 2, "No servers configured: Creating a new DDFileLock object." ); + $lock = eval { DDFileLock->new($lockname, $self->{lockdir}) }; + } + + # If no lock was acquired, fail and put the reason in $Error. + unless ( $lock ) { + return $self->lock_fail( $@ ) if $@; + return $self->lock_fail( "Unknown failure." ); + } + + return $lock; +} + + +### (PROTECTED) METHOD: lock_fail( $msg ) +### Set C<$!> to the specified message and return undef. +sub lock_fail { + my DDLockClient $self = shift; + my $msg = shift; + + $Error = $msg; + return undef; +} + + +1; + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/ddlockd/api/perl/MANIFEST b/wcmtools/ddlockd/api/perl/MANIFEST new file mode 100755 index 0000000..790c3ff --- /dev/null +++ b/wcmtools/ddlockd/api/perl/MANIFEST @@ -0,0 +1,5 @@ +DDLockClient.pm +Makefile.PL +MANIFEST +t/00_require.t +testlock.pl diff --git a/wcmtools/ddlockd/api/perl/MANIFEST.SKIP b/wcmtools/ddlockd/api/perl/MANIFEST.SKIP new file mode 100755 index 0000000..ede9cda --- /dev/null +++ b/wcmtools/ddlockd/api/perl/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists diff --git a/wcmtools/ddlockd/api/perl/Makefile.PL b/wcmtools/ddlockd/api/perl/Makefile.PL new file mode 100755 index 0000000..b5674cf --- /dev/null +++ b/wcmtools/ddlockd/api/perl/Makefile.PL @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# +# Perl Makefile for DDLockClient/DDLock +# $Id: Makefile.PL,v 1.2 2004/05/27 22:08:51 deveiant Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; +my $version = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + +my %config = ( + NAME => 'DDLockClient', + VERSION => "0." . $version, + AUTHOR => 'Brad Fitzpatrick ', + ABSTRACT => 'A lock client for the distributed lock daemon ddlockd', + PREREQ_PM => { + Socket => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag r$(VERSION_SYM)', + SUFFIX => ".bz2", + DIST_DEFAULT => 'all tardist', + COMPRESS => "bzip2", + }, + ); + + +WriteMakefile( %config ); diff --git a/wcmtools/ddlockd/api/perl/stresslock.pl b/wcmtools/ddlockd/api/perl/stresslock.pl new file mode 100755 index 0000000..a3c086a --- /dev/null +++ b/wcmtools/ddlockd/api/perl/stresslock.pl @@ -0,0 +1,57 @@ +#!/usr/bin/perl -w + +use Fcntl; +use lib "blib/lib"; +use DDLockClient (); +use Data::Dumper (); + +$Data::Dumper::Terse = 1; +$Data::Dumper::Indent = 1; + +$| = 1; + +my $DDServers = [ +# 'localhost:7003', +# 'localhost:7004', + 'localhost:7002', + ]; + +foreach my $servers ( $DDServers, [] ) { + print "Creating client (@$servers)..."; + my $cl = new DDLockClient ( servers => $servers ) + or die $DDLockClient::Error; + print "done:\n"; + + for ( my $i = 0; $i < 10; $i++ ) { + if ( my $pid = fork ) { + print "Created child: $pid\n"; + } else { + for ( my $ct = 0; $ct < 150; $ct++ ) { + my $rand = int(rand(10)); + #print "Trying to create lock 'lock$rand' lock in process $$...\n"; + if ( my $lock = $cl->trylock("lock$rand") ) { + my $file = ".stressfile-$rand"; + my $fh = new IO::File $file, O_WRONLY|O_EXCL|O_CREAT; + die "Couldn't create file $file: $!" unless $fh; + $fh->close; + unlink $file; + } + } + exit 0; + } + } + + while ((my $pid = wait) != -1) { + if ($? == 0) { + print "$pid is done, okay.\n"; + } else { + die "$pid FAILED\n"; + } + } + + print "done.\n\n"; +} + + + + diff --git a/wcmtools/ddlockd/api/perl/t/00_require.t b/wcmtools/ddlockd/api/perl/t/00_require.t new file mode 100755 index 0000000..ec06f3e --- /dev/null +++ b/wcmtools/ddlockd/api/perl/t/00_require.t @@ -0,0 +1,12 @@ +#!/usr/bin/perl -w + +use strict; +use Test; + +BEGIN { plan tests => 3 } + +ok( eval { require DDLockClient; 1 } ); +ok( exists $::{"DDLockClient::"} ); +ok( exists $::{"DDLock::"} ); + + diff --git a/wcmtools/ddlockd/api/perl/testlock.pl b/wcmtools/ddlockd/api/perl/testlock.pl new file mode 100755 index 0000000..05afddf --- /dev/null +++ b/wcmtools/ddlockd/api/perl/testlock.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +use lib "blib/lib"; +use DDLockClient (); +use Data::Dumper (); + +$Data::Dumper::Terse = 1; +$Data::Dumper::Indent = 1; + +$| = 1; + +my $DDServers = [ + 'localhost:7003', + 'localhost:7004', + 'localhost', + ]; + +foreach my $servers ( $DDServers, [] ) { + print "Creating client..."; + my $cl = new DDLockClient ( servers => $servers ) + or die $DDLockClient::Error; + print "done:\n"; + + print "Creating a 'foo' lock..."; + my $lock = $cl->trylock( "foo" ) + or print "Error: $DDLockClient::Error\n"; + print "done.\n"; + + if ( my $pid = fork ) { + waitpid( $pid, 0 ); + } else { + print "Trying to create a 'foo' lock in process $$..."; + my $lock2 = $cl->trylock( "foo" ) + or print "Error: $DDLockClient::Error\n"; + print "done:\n"; + exit; + } + + print "Releasing the 'foo' lock..."; + $lock->release or die; + print "done.\n\n"; +} + + + + diff --git a/wcmtools/ddlockd/server/ddlockd b/wcmtools/ddlockd/server/ddlockd new file mode 100755 index 0000000..1b3bac4 --- /dev/null +++ b/wcmtools/ddlockd/server/ddlockd @@ -0,0 +1,316 @@ +#!/usr/bin/perl +# +# Danga's Distributed Lock Daemon +# +# Status: 2004-05-18: quick hack. not for production yet. +# +# Copyright 2004, Danga Interactive +# +# Authors: +# Brad Fitzpatrick +# +# License: +# undecided. +# + +use strict; +use Getopt::Long; +use Carp; +use Danga::Socket; +use IO::Socket::INET; +use POSIX (); + +use vars qw($DEBUG); +$DEBUG = 0; + +my ( + $daemonize, + $nokeepalive, + ); +my $conf_port = 7002; + +Getopt::Long::GetOptions( + 'd|daemon' => \$daemonize, + 'p|port=i' => \$conf_port, + 'debug=i' => \$DEBUG, + 'n|no-keepalive' => \$nokeepalive, + ); + +daemonize() if $daemonize; + +use Socket qw(IPPROTO_TCP SO_KEEPALIVE TCP_NODELAY SOL_SOCKET); + +# Linux-specific: +use constant TCP_KEEPIDLE => 4; # Start keeplives after this period +use constant TCP_KEEPINTVL => 5; # Interval between keepalives +use constant TCP_KEEPCNT => 6; # Number of keepalives before death + +$SIG{'PIPE'} = "IGNORE"; # handled manually + +# establish SERVER socket, bind and listen. +my $server = IO::Socket::INET->new(LocalPort => $conf_port, + Type => SOCK_STREAM, + Proto => IPPROTO_TCP, + Blocking => 0, + Reuse => 1, + Listen => 10 ) + or die "Error creating socket: $@\n"; + +# Not sure if I'm crazy or not, but I can't see in strace where/how +# Perl 5.6 sets blocking to 0 without this. In Perl 5.8, IO::Socket::INET +# obviously sets it from watching strace. +IO::Handle::blocking($server, 0); + +my $accept_handler = sub { + my $csock = $server->accept(); + return unless $csock; + + printf("Listen child making a Client for %d.\n", fileno($csock)) + if $DEBUG; + + IO::Handle::blocking($csock, 0); + setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + # Enable keep alive + unless ( $nokeepalive ) { + (setsockopt($csock, SOL_SOCKET, SO_KEEPALIVE, pack("l", 1)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPIDLE, pack("l", 30)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPCNT, pack("l", 10)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPINTVL, pack("l", 30)) && + 1 + ) || die "Couldn't set keep-alive settings on socket (Not on Linux?)"; + } + + my $client = Client->new($csock); + $client->watch_read(1); +}; + +Client->OtherFds(fileno($server) => $accept_handler); +Client->EventLoop(); + +sub daemonize { + my($pid, $sess_id, $i); + + ## Fork and exit parent + if ($pid = fork) { exit 0; } + + ## Detach ourselves from the terminal + croak "Cannot detach from controlling terminal" + unless $sess_id = POSIX::setsid(); + + ## Prevent possibility of acquiring a controling terminal + $SIG{'HUP'} = 'IGNORE'; + if ($pid = fork) { exit 0; } + + ## Change working directory + chdir "/"; + + ## Clear file creation mask + umask 0; + + ## Close open file descriptors + close(STDIN); + close(STDOUT); + close(STDERR); + + ## Reopen stderr, stdout, stdin to /dev/null + open(STDIN, "+>/dev/null"); + open(STDOUT, "+>&STDIN"); + open(STDERR, "+>&STDIN"); +} + +##################################################################### +### C L I E N T C L A S S +##################################################################### +package Client; + +use Danga::Socket; +use base 'Danga::Socket'; +use fields ( + 'locks', # hashref of locks held by this connection. values are 1 + 'read_buf', + ); + +our (%holder); # hash of lock -> Client object holding it +# TODO: out %waiters, lock -> arrayref of client waiters (waker should check not closed) + +sub new { + my Client $self = shift; + $self = fields::new($self) unless ref $self; + $self->SUPER::new( @_ ); + + $self->{locks} = {}; + $self->{read_buf} = ''; + return $self; +} + +# Client +sub event_read { + my Client $self = shift; + + my $bref = $self->read(1024); + return $self->close() unless defined $bref; + $self->{read_buf} .= $$bref; + + if ($self->{read_buf} =~ s/^(.+?)\r?\n//) { + my $line = $1; + $self->process_line( $line ); + } +} + +sub process_line { + my Client $self = shift; + my $line = shift; + + if ($line =~ /^(\w+)\s*(.*)/) { + my ($cmd, $args) = ($1, $2); + $cmd = lc($cmd); + + no strict 'refs'; + my $cmd_handler = *{"cmd_$cmd"}{CODE}; + if ($cmd_handler) { + my $args = decode_url_args(\$args); + $cmd_handler->($self, $args); + next; + } + } + + return $self->err_line('unknown_command'); +} + +sub close { + my Client $self = shift; + + foreach my $lock (keys %{$self->{locks}}) { + _release_lock($self, $lock); + } + + $self->SUPER::close; +} + +sub _release_lock { + my Client $self = shift; + my $lock = shift; + + # TODO: notify waiters + delete $self->{locks}{$lock}; + delete $holder{$lock}; + return 1; +} + + +# Client +sub event_err { my $self = shift; $self->close; } +sub event_hup { my $self = shift; $self->close; } + + +# gets a lock or fails with 'taken' +sub cmd_trylock { + my Client $self = shift; + my $args = shift; + + my $lock = $args->{lock}; + return $self->err_line("empty_lock") unless length($lock); + return $self->err_line("taken") if defined $holder{$lock}; + + $holder{$lock} = $self; + $self->{locks}{$lock} = 1; + + return $self->ok_line(); +} + +# releases a lock or fails with 'didnthave' +sub cmd_releaselock { + my Client $self = shift; + my $args = shift; + + my $lock = $args->{lock}; + return $self->err_line("empty_lock") unless length($lock); + return $self->err_line("didnthave") unless $self->{locks}{$lock}; + + _release_lock($self, $lock); + return $self->ok_line; +} + +# shows current locks +sub cmd_locks { + my Client $self = shift; + my $args = shift; + + $self->write("LOCKS:\n"); + foreach my $k (sort keys %holder) { + $self->write(" $k = " . $holder{$k}->as_string . "\n"); + } + + return 1; +} + +sub cmd_noop { + my Client $self = shift; + # TODO: set self's last activity time so it isn't cleaned in a purge + # of stale connections? + return $self->ok_line; +} + +sub ok_line { + my Client $self = shift; + my $args = shift || {}; + my $argline = join('&', map { eurl($_) . "=" . eurl($args->{$_}) } keys %$args); + $self->write("OK $argline\r\n"); + return 1; +} + +sub err_line { + my Client $self = shift; + my $err_code = shift; + my $err_text = { + 'unknown_command' => "Unknown server command", + }->{$err_code}; + + $self->write("ERR $err_code " . eurl($err_text) . "\r\n"); + return 0; +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\,\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +sub decode_url_args +{ + my $a = shift; + my $buffer = ref $a ? $a : \$a; + my $ret = {}; + + my $pair; + my @pairs = split(/&/, $$buffer); + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $ret->{$name} .= $ret->{$name} ? "\0$value" : $value; + } + return $ret; +} + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/dinsertd/server/dinsertd b/wcmtools/dinsertd/server/dinsertd new file mode 100755 index 0000000..f8655c5 --- /dev/null +++ b/wcmtools/dinsertd/server/dinsertd @@ -0,0 +1,385 @@ +#!/usr/bin/perl +# +# Danga's Delayed Insert Daemon +# +# ... because MySQL forces connections to be threads, limiting +# total connections +# +# ... and because TCP makes it so easy to run out of local ports +# +# Status: 2004-12-22: experimental hack. +# +# Copyright 2004, Danga Interactive +# +# Authors: +# Brad Fitzpatrick +# +# License: +# undecided. +# + +use strict; +use Getopt::Long; +use Carp; +use Danga::Socket; +use IO::Socket::INET; +use POSIX (); + +use vars qw($DEBUG); +$DEBUG = 0; + +my ( + $daemonize, + $nokeepalive, + ); +my $conf_port = 7400; + +Getopt::Long::GetOptions( + 'd|daemon' => \$daemonize, + 'p|port=i' => \$conf_port, + 'debug=i' => \$DEBUG, + 'n|no-keepalive' => \$nokeepalive, + ); + +daemonize() if $daemonize; + +use Socket qw(IPPROTO_TCP SO_KEEPALIVE TCP_NODELAY SOL_SOCKET); + +# Linux-specific: +use constant TCP_KEEPIDLE => 4; # Start keeplives after this period +use constant TCP_KEEPINTVL => 5; # Interval between keepalives +use constant TCP_KEEPCNT => 6; # Number of keepalives before death + +$SIG{'PIPE'} = "IGNORE"; # handled manually + +# establish SERVER socket, bind and listen. +my $server = IO::Socket::INET->new(LocalPort => $conf_port, + Type => SOCK_STREAM, + Proto => IPPROTO_TCP, + Blocking => 0, + Reuse => 1, + Listen => 10 ) + or die "Error creating socket: $@\n"; + +# Not sure if I'm crazy or not, but I can't see in strace where/how +# Perl 5.6 sets blocking to 0 without this. In Perl 5.8, IO::Socket::INET +# obviously sets it from watching strace. +IO::Handle::blocking($server, 0); + +my $accept_handler = sub { + my $csock = $server->accept(); + return unless $csock; + + printf("Listen child making a Client for %d.\n", fileno($csock)) + if $DEBUG; + + IO::Handle::blocking($csock, 0); + setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + # Enable keep alive + unless ( $nokeepalive ) { + (setsockopt($csock, SOL_SOCKET, SO_KEEPALIVE, pack("l", 1)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPIDLE, pack("l", 30)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPCNT, pack("l", 10)) && + setsockopt($csock, IPPROTO_TCP, TCP_KEEPINTVL, pack("l", 30)) && + 1 + ) || die "Couldn't set keep-alive settings on socket (Not on Linux?)"; + } + + my $client = Client->new($csock); + $client->watch_read(1); +}; + +Client->Init; +Danga::Socket->OtherFds(fileno($server) => $accept_handler); +Danga::Socket->EventLoop(); + +sub daemonize { + my($pid, $sess_id, $i); + + ## Fork and exit parent + if ($pid = fork) { exit 0; } + + ## Detach ourselves from the terminal + croak "Cannot detach from controlling terminal" + unless $sess_id = POSIX::setsid(); + + ## Prevent possibility of acquiring a controling terminal + $SIG{'HUP'} = 'IGNORE'; + if ($pid = fork) { exit 0; } + + ## Change working directory + chdir "/"; + + ## Clear file creation mask + umask 0; + + ## Close open file descriptors + close(STDIN); + close(STDOUT); + close(STDERR); + + ## Reopen stderr, stdout, stdin to /dev/null + open(STDIN, "+>/dev/null"); + open(STDOUT, "+>&STDIN"); + open(STDERR, "+>&STDIN"); +} + +##################################################################### +### C L I E N T C L A S S +##################################################################### +package Client; + +use strict; +use Danga::Socket; +use base 'Danga::Socket'; +use fields ( + 'read_buf', + 'listen_queue_num', # undef, its own fd, or -1 if listening to system queue + ); + +our %queue; # fd -> [ [ $table, $values ] ... ] +our %note; # arbitrary client-generated key/value data + +our @listeners; # client objects that are listening + +our $MAX_QUEUE_DEPTH; + +our $is_system_attached; # bool: if somebody is watching the system queue + +sub Init { + $MAX_QUEUE_DEPTH = 5000; + + #fd=-1 is magic and is the system default queue, which always exists + $queue{-1} = []; + $is_system_attached = 0; +} + +sub new { + my Client $self = shift; + $self = fields::new($self) unless ref $self; + $self->SUPER::new( @_ ); + + $self->{read_buf} = ''; + $self->{listen_queue_num} = undef; + return $self; +} + +# Client +sub event_read { + my Client $self = shift; + + my $bref = $self->read(1024); + return $self->close() unless defined $bref; + $self->{read_buf} .= $$bref; + + if ($self->{read_buf} =~ s/^(.+?)\r?\n//) { + my $line = $1; + $self->process_line( $line ); + } +} + +sub event_write { + my Client $self = shift; + + # stop watching for writability if we're not subscribed to anything + unless (defined $self->{listen_queue_num}) { + $self->watch_write(0); + return; + } + + my $q = $queue{$self->{listen_queue_num}}; + + while (@$q) { + my $rec = shift @$q; + next if $self->write("ROW $rec->[0] $rec->[1]\r\n"); + print " Buffer was full!\n"; + return; + } + $self->watch_write(0); +} + +sub process_line { + my Client $self = shift; + my $line = shift; + + if ($line =~ /^(\w+)\s*(.*)/) { + my ($cmd, $args) = ($1, $2); + $cmd = lc($cmd); + + no strict 'refs'; + my $cmd_handler = *{"cmd_$cmd"}{CODE}; + if ($cmd_handler) { + $cmd_handler->($self, $args); + next; + } + } + + return $self->err_line('unknown_command'); +} + +# Client +sub event_err { my $self = shift; $self->close; } +sub event_hup { my $self = shift; $self->close; } + + +# gets a lock or fails with 'taken' +sub cmd_set_note { + my Client $self = shift; + my $args = shift; + return $self->err_line("bogus_format") + unless $args =~ /(\S+)\s+(.+)/; + $note{$1} = $2; + return $self->ok_line; +} + +# gets a lock or fails with 'taken' +sub cmd_get_note { + my Client $self = shift; + my $args = shift; + return $self->err_line("bogus_format") + unless $args =~ /(\S+)/; + + $self->write("NOTE $note{$1}\r\n"); + return 1; +} + +# gets a lock or fails with 'taken' +sub cmd_insert { + my Client $self = shift; + my $args = shift; + + return $self->err_line("bogus_format") + unless $args =~ /(\w+)\s+(.+)/; + + my $rec = [ $1, $2 ]; + foreach my $fd (keys %queue) { + my $q = $queue{$fd}; + shift @$q if scalar @$q >= $MAX_QUEUE_DEPTH; + push @$q, $rec; + } + + foreach (@listeners) { + $_->watch_write(1); + } + + return $self->ok_line; +} + +sub close { + my Client $self = shift; + + # remove ourselves from the listeners array + @listeners = grep { $_ != $self } @listeners; + + # delete our queue, unless it's the system queue + if ($self->{listen_queue_num} != -1) { + delete $queue{$self->{listen_queue_num}}; + } else { + $is_system_attached = 0; + } + + $self->SUPER::close; +} + +sub cmd_subscribe { + my Client $self = shift; + my $args = shift; + + my $which_fd = undef; + if ($args =~ /system/) { + return $self->err_line("dup_sys") if $is_system_attached++; + $which_fd = -1; + } else { + $which_fd = $self->{fd}; + } + + $self->{listen_queue_num} = $which_fd; + push @listeners, $self; + + $queue{$which_fd} ||= []; + $self->watch_write(1); + return 1; +} + + +# shows current locks +sub cmd_locks { + my Client $self = shift; + my $args = shift; + + $self->write("LOCKS:\n"); + + return 1; +} + +sub cmd_noop { + my Client $self = shift; + # TODO: set self's last activity time so it isn't cleaned in a purge + # of stale connections? + return $self->ok_line; +} + +sub ok_line { + my Client $self = shift; + my $args = shift || {}; + my $argline = join('&', map { eurl($_) . "=" . eurl($args->{$_}) } keys %$args); + $self->write("OK $argline\r\n"); + return 1; +} + +sub err_line { + my Client $self = shift; + my $err_code = shift; + my $err_text = { + 'unknown_command' => "Unknown server command", + 'dup_sys' => "Can't have two listeners on the system log", + }->{$err_code}; + + $self->write("ERR $err_code " . eurl($err_text) . "\r\n"); + return 0; +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\,\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +sub decode_url_args +{ + my $a = shift; + my $buffer = ref $a ? $a : \$a; + my $ret = {}; + + my $pair; + my @pairs = split(/&/, $$buffer); + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $ret->{$name} .= $ret->{$name} ? "\0$value" : $value; + } + return $ret; +} + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/diskchecker/diskchecker.pl b/wcmtools/diskchecker/diskchecker.pl new file mode 100755 index 0000000..c2bda00 --- /dev/null +++ b/wcmtools/diskchecker/diskchecker.pl @@ -0,0 +1,269 @@ +#!/usr/bin/perl +# +# Brad's el-ghetto do-our-storage-stacks-lie?-script +# + +sub usage { + die <<'END'; +Usage: diskchecker.pl -s verify + diskchecker.pl -s create + diskchecker.pl -l [port] +END +} + +use strict; +use IO::Socket::INET; +use IO::Handle; +use Getopt::Long; +use Socket qw(IPPROTO_TCP TCP_NODELAY); + +my $server; +my $listen; +usage() unless GetOptions('server=s' => \$server, + 'listen:5400' => \$listen); +usage() unless $server || $listen; +usage() if $server && $listen; + +# LISTEN MODE: +listen_mode($listen) if $listen; + +# CLIENT MODE: +my $LEN = 16 * 1024; # 16kB (same as InnoDB page) +my $mode = shift; +usage() unless $mode =~ /^verify|create$/; + +my $file = shift or usage(); +my $size; +if ($mode eq "create") { + $size = shift or usage(); +} + +$server .= ":5400" unless $server =~ /:/; + +my $sock = IO::Socket::INET->new(PeerAddr => $server) + or die "Couldn't connect to host:port of '$server'\n"; + +setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + +create() if $mode eq "create"; +verify() if $mode eq "verify"; +exit 0; + +sub verify { + sendmsg($sock, "read"); + + my $error_ct = 0; + my %error_ct; + + my $size = -s $file; + my $max_pages = int($size / $LEN); + + my $percent; + my $last_dump = 0; + my $show_percent = sub { + printf " verifying: %.02f%%\n", $percent; + }; + + open (F, $file) or die "Couldn't open file $file for read\n"; + + while (<$sock>) { + chomp; + my ($page, $good, $val, $ago) = split(/\t/, $_); + $percent = 100 * $page / ($max_pages || 1); + + my $now = time; + if ($last_dump != $now) { + $last_dump = $now; + $show_percent->(); + } + + next unless $good; + + my $offset = $page * $LEN; + sysseek F, $offset, 0; + my $buf; + my $rv = sysread(F, $buf, $LEN); + my $tobe = sprintf("%08x", $val) x ($LEN / 8); + substr($tobe, $LEN-1, 1) = "\n"; + + unless ($buf eq $tobe) { + $error_ct{$ago}++; + $error_ct++; + print " Error at page $page, $ago seconds before end.\n"; + } + } + $show_percent->(); + + print "Total errors: $error_ct\n"; + if ($error_ct) { + print "Histogram of seconds before end:\n"; + foreach (sort { $a <=> $b } keys %error_ct) { + printf " %4d %4d\n", $_, $error_ct{$_}; + } + } +} + +sub create { + open (F, ">$file") or die "Couldn't open file $file\n"; + + my $ioh = IO::Handle->new_from_fd(fileno(F), "w") + or die; + + my $pages = int( ($size * 1024 * 1024) / $LEN ); # 50 MiB of 16k pages (3200 pages) + + my %page_hit; + my $pages_hit = 0; + my $uniq_pages_hit = 0; + my $start = time(); + my $last_dump = $start; + + while (1) { + my $rand = int rand 2000000; + my $buf = sprintf("%08x", $rand) x ($LEN / 8); + substr($buf, $LEN-1, 1) = "\n"; + + my $pagenum = int rand $pages; + my $offset = $pagenum * $LEN; + + sendmsg($sock, "pre\t$pagenum\t$rand"); + + # now wait for acknowledgement + my $ok = readmsg($sock); + die "didn't get 'ok' from server ($pagenum $rand), msg=[$ok] = $!" unless $ok eq "ok"; + + sysseek F,$offset,0; + my $wv = syswrite(F, $buf, $LEN); + die "return value wasn't $LEN\n" unless $wv == $LEN; + $ioh->sync or die "couldn't do IO::Handle::sync"; # does fsync + + sendmsg($sock, "post\t$pagenum\t$rand"); + + $pages_hit++; + unless ($page_hit{$pagenum}++) { + $uniq_pages_hit++; + } + + my $now = time; + if ($now != $last_dump) { + $last_dump = $now; + my $runtime = $now - $start; + printf(" diskchecker: running %d sec, %.02f%% coverage of %d MB (%d writes; %d/s)\n", + $runtime, + (100 * $uniq_pages_hit / $pages), + $size, + $pages_hit, + $pages_hit / $runtime, + ); + } + + } +} + +sub readmsg { + my $sock = shift; + my $len; + my $rv = sysread($sock, $len, 1); + return undef unless $rv == 1; + my $msg; + $rv = sysread($sock, $msg, ord($len)); + return $msg; +} + +sub sendmsg { + my ($sock, $msg) = @_; + my $rv = syswrite($sock, chr(length($msg)) . $msg); + my $expect = length($msg) + 1; + die "sendmsg failed rv=$rv, expect=$expect" unless $rv == $expect; + return 1; +} + +sub listen_mode { + my $port = shift; + my $server = IO::Socket::INET->new(ReuseAddr => 1, + Listen => 1, + LocalPort => $port) + or die "couldn't make server socket\n"; + + while (1) { + print "[server] diskchecker.pl: waiting for connection...\n"; + my $sock = $server->accept() + or die " die: no connection?"; + setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + fork and next; + process_incoming_conn($sock); + exit 0; + } +} + +sub process_incoming_conn { + my $sock = shift; + my $peername = getpeername($sock) or + die "connection not there?\n"; + my ($port, $iaddr) = sockaddr_in($peername); + my $ip = inet_ntoa($iaddr); + + my $file = "/tmp/$ip.diskchecker"; + die "[$ip] $file is a symlink" if -l $file; + + print "[$ip] New connection\n"; + + my $lines = 0; + my %state; + my $end; + + while (1) { + if ($lines) { + last unless wait_for_readability(fileno($sock), 3); + } + my $line = readmsg($sock); + last unless $line; + + if ($line eq "read") { + print "[$ip] Sending state info from ${ip}'s last create.\n"; + open (S, "$file") or die "Couldn't open $file for reading."; + while () { + print $sock $_; + } + close S; + print "[$ip] Done.\n"; + exit 0; + } + + $lines++; + my $now = time; + $end = $now; + my ($state, $pagenum, $rand) = split(/\t/, $line); + if ($state eq "pre") { + $state{$pagenum} = [ 0, $rand+0, $now ]; + sendmsg($sock, "ok"); + } elsif ($state eq "post") { + $state{$pagenum} = [ 1, $rand+0, $now ]; + } + print "[$ip] $lines writes\n" if $lines % 1000 == 0; + } + + print "[$ip] Writing state file...\n"; + open (S, ">$file") or die "Couldn't open $file for writing."; + foreach (sort { $a <=> $b } keys %state) { + my $v = $state{$_}; + my $before_end = $end - $v->[2]; + print S "$_\t$v->[0]\t$v->[1]\t$before_end\n"; + } + print "[$ip] Done.\n"; +} + +sub wait_for_readability { + my ($fileno, $timeout) = @_; + return 0 unless $fileno && $timeout; + + my $rin; + vec($rin, $fileno, 1) = 1; + my $nfound = select($rin, undef, undef, $timeout); + + return 0 unless defined $nfound; + return $nfound ? 1 : 0; +} + + + diff --git a/wcmtools/dmtpd/README.txt b/wcmtools/dmtpd/README.txt new file mode 100755 index 0000000..92c889f --- /dev/null +++ b/wcmtools/dmtpd/README.txt @@ -0,0 +1,11 @@ +This is a server to inject mail into Sendmail/Postfix/etc's outgoing +mail queue, without blocking the client (in our case, web nodes which +can't block on outgoing email). + +Works with any MTA that has 'sendmail -i -f ....' + +This might all be temporary until we figure out mail better. (like +how to get postfix to trust our outgoing email and queue it +immediately, rather than blocking the web clients while it sends) + + diff --git a/wcmtools/dmtpd/api/perl/test.pl b/wcmtools/dmtpd/api/perl/test.pl new file mode 100755 index 0000000..f05fd04 --- /dev/null +++ b/wcmtools/dmtpd/api/perl/test.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl +# + +use strict; +use MIME::Lite (); +use IO::File; +use IO::Socket::INET; + +my $msg = new MIME::Lite ('From' => 'brad@danga.com (Brad Fitzpatrick)', + 'To' => 'brad@danga.com (Fitz)', + 'Cc' => 'brad@livejournal.com', + 'Subject' => "Subjecto el Email testo", + 'Data' => "word\n.\n\nthe end.\n"); + +my $as = $msg->as_string; +my $len = length($as); + +my $sock = IO::Socket::INET->new(PeerAddr => 'localhost', + PeerPort => '7005', + Proto => 'tcp'); + +my $message = "Content-Length: $len\r\nEnvelope-Sender: brad\@danga.com\r\n\r\n$as"; + +$sock->print("$message$message"); + +sleep 1; + +$sock->print("Content-Len"); +sleep 1; +$sock->print("gth: $len\r\nEnvelope-Sender: brad\@danga.com\r\n"); +sleep 1; +$sock->print("\r\n${as}Content-Length: $len\r\nEnvelope-Sender: "); +sleep 1; +$sock->print("brad\@danga.com\r\n\r\n$as"); + +while ($_ = $sock->getline) { + $_ =~ s/[\r\n]+$//; + print "RES: $_\n"; +} +$sock->close; + + diff --git a/wcmtools/dmtpd/server/dmtpd b/wcmtools/dmtpd/server/dmtpd new file mode 100755 index 0000000..393d24b --- /dev/null +++ b/wcmtools/dmtpd/server/dmtpd @@ -0,0 +1,231 @@ +#!/usr/bin/perl +# +# Danga's Mail Transfer Daemon +# +# Status: 2004-06-07: quick hack. +# +# Copyright 2004, Danga Interactive +# +# Authors: +# Brad Fitzpatrick +# +# License: +# Artistic/GPL. Your choice. +# + +use strict; +use Getopt::Long; +use Carp; +use Danga::Socket; +use IO::Socket::INET; +use POSIX (); + +use vars qw($DEBUG); +$DEBUG = 0; + +my ( + $daemonize, + ); +my $conf_port = 7005; + +Getopt::Long::GetOptions( + 'd|daemon' => \$daemonize, + 'p|port=i' => \$conf_port, + 'debug=i' => \$DEBUG, + ); + +daemonize() if $daemonize; + +use Socket qw(IPPROTO_TCP SO_KEEPALIVE TCP_NODELAY SOL_SOCKET); + +$SIG{'PIPE'} = "IGNORE"; # handled manually + +# establish SERVER socket, bind and listen. +my $server = IO::Socket::INET->new(LocalPort => $conf_port, + Type => SOCK_STREAM, + Proto => IPPROTO_TCP, + Blocking => 0, + Reuse => 1, + Listen => 10 ) + or die "Error creating socket: $@\n"; + +# Not sure if I'm crazy or not, but I can't see in strace where/how +# Perl 5.6 sets blocking to 0 without this. In Perl 5.8, IO::Socket::INET +# obviously sets it from watching strace. +IO::Handle::blocking($server, 0); + +my $accept_handler = sub { + my $csock = $server->accept(); + return unless $csock; + + printf("Listen child making a Client for %d.\n", fileno($csock)) + if $DEBUG; + + IO::Handle::blocking($csock, 0); + setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + my $client = Client->new($csock); + $client->watch_read(1); +}; + +Client->OtherFds(fileno($server) => $accept_handler); +Client->EventLoop(); + +sub daemonize { + my($pid, $sess_id, $i); + + ## Fork and exit parent + if ($pid = fork) { exit 0; } + + ## Detach ourselves from the terminal + croak "Cannot detach from controlling terminal" + unless $sess_id = POSIX::setsid(); + + ## Prevent possibility of acquiring a controling terminal + $SIG{'HUP'} = 'IGNORE'; + if ($pid = fork) { exit 0; } + + ## Change working directory + chdir "/"; + + ## Clear file creation mask + umask 0; + + ## Close open file descriptors + close(STDIN); + close(STDOUT); + close(STDERR); + + ## Reopen stderr, stdout, stdin to /dev/null + open(STDIN, "+>/dev/null"); + open(STDOUT, "+>&STDIN"); + open(STDERR, "+>&STDIN"); +} + +##################################################################### +### C L I E N T C L A S S +##################################################################### +package Client; + +use Danga::Socket; +use base 'Danga::Socket'; +use fields ( + 'headers', # hashref of header fields read + 'line', # partial line read so far + 'readcount', # how much into the message body we've read + 'sendmail', # IO::File pipe to sendmail + 'gotheaders', # bool: if we've finished reading headers + 'err', # bool: error has occurred so far + ); +use Errno qw(EPIPE); +use IO::File; + +sub new { + my Client $self = shift; + $self = fields::new($self) unless ref $self; + $self->SUPER::new( @_ ); + + $self->reset_for_next_message; + return $self; +} + +sub reset_for_next_message { + my Client $self = shift; + $self->{line} = ''; + $self->{headers} = {}; + $self->{readcount} = 0; + $self->{gotheaders} = 0; + $self->{sendmail} = undef; + $self->{err} = 0; + return $self; +} + +# Client +sub event_read { + my Client $self = shift; + my $bref = $self->read(8192); + return $self->close() unless defined $bref; + $self->process_read_buf($bref); +} + +sub process_read_buf { + my Client $self = shift; + my $bref = shift; + + if (! $self->{gotheaders}) { + $self->{line} .= $$bref; + while ($self->{line} =~ s/^(.*?)\r?\n//) { + my $line = $1; + if ($line =~ /^(\S+)\s*:\s*(.+)/) { + $self->{headers}{lc($1)} = $2; + } elsif ($line eq "") { + $self->{gotheaders} = 1; + $self->{readcount} = 0; + my $opts = ""; + my $h = $self->{headers}; + # pass the '-f' option to sendmail, if the given + # Envelope-Sender header is clean + if (my $es = $h->{'envelope-sender'}) { + if ($es =~ /^[\w\-\+\.]+\@[\w\-\.]+$/) { + $opts = "-f $es"; + } + } + unless ($self->{sendmail} = + IO::File->new("| /usr/sbin/sendmail -t -i $opts")) { + $self->{err} = 1; + } + $self->close unless $h->{'content-length'} > 0 && + $h->{'content-length'} =~ /^\d+$/; + + $bref = \$self->{line}; + last; + } + } + } + return unless $self->{gotheaders}; + + my $need = $self->{headers}{'content-length'} - $self->{readcount}; + my $len = length($$bref); + + # if we read into the next message (pipelined messages) + # then we need to push the overflow piece back into $overflow + my $overflow; + if ($len > $need) { + my $needed = substr($$bref, 0, $need); + $overflow = substr($$bref, $need); + $bref = \$needed; + $len = $need; + } + + $self->{readcount} += $len; + if ($self->{sendmail} && ! $self->{err}) { + $self->{sendmail}->print($$bref); + $self->{err} = 1 if $! == EPIPE; + } + + # if we're done, close sendmail + if ($len == $need) { + if (! $self->{err} && + $self->{sendmail} && + $self->{sendmail}->close()) { + $self->write("OK\r\n"); + } else { + $self->write("FAIL\r\n"); + } + $self->reset_for_next_message; + $self->process_read_buf(\$overflow) if defined $overflow; + } + + $self->watch_read(1); +} + + +# Client +sub event_err { my $self = shift; $self->close; } +sub event_hup { my $self = shift; $self->close; } + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/gearman/dev/DMap.pm b/wcmtools/gearman/dev/DMap.pm new file mode 100755 index 0000000..6149657 --- /dev/null +++ b/wcmtools/gearman/dev/DMap.pm @@ -0,0 +1,77 @@ +#!/usr/bin/perl + +package DMap; +use strict; +use Exporter; +use Storable; +use IO::Socket::INET; +use Gearman::Util; +use vars qw(@ISA @EXPORT); +@ISA = qw(Exporter); +@EXPORT = qw(dmap); + +$Storable::Deparse = 1; +$Storable::Eval = 1; + +our @js; + +sub set_job_servers { + @js = @_; +} + +sub dmap (&@) { + my $code = shift; + my $fz = Storable::freeze($code); + + my $sock; + foreach (@js) { + $_ .= ":7003" unless /:/; + $sock = IO::Socket::INET->new(PeerAddr => $js[0]); + last if $sock; + } + die "No jobserver available" unless $sock; + + my $send = sub { + print $sock Gearman::Util::pack_req_command(@_); + }; + + my $err; + my $get = sub { + return Gearman::Util::read_res_packet($sock, \$err);; + }; + + my $argc = scalar @_; + ARG: + foreach (@_) { + $send->("submit_job", join("\0", "dmap", "", Storable::freeze([ $code, $_ ]))); + } + + my $waiting = $argc; + my %handle; # n -> handle + my $hct = 0; + my %partial_res; + + while ($waiting) { + my $res = $get->() + or die "Failure: $err"; + + if ($res->{type} eq "job_created") { + $handle{$hct} = ${$res->{blobref}}; + $hct++; + next; + } + + if ($res->{type} eq "work_complete") { + my $br = $res->{blobref}; + $$br =~ s/^(.+?)\0//; + my $handle = $1; + $partial_res{$handle} = Storable::thaw($$br); + $waiting--; + } + } + + return map { @{ $partial_res{$handle{$_}} } } (0..$argc-1); +} + + +1; diff --git a/wcmtools/gearman/dev/client.pl b/wcmtools/gearman/dev/client.pl new file mode 100755 index 0000000..318b16d --- /dev/null +++ b/wcmtools/gearman/dev/client.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl +use strict; +use Gearman::Util; +use IO::Socket::INET; +use Data::Dumper; +my $sock = IO::Socket::INET->new(PeerAddr => "localhost:7003") + or die "no socket."; + +my $send = sub { + print $sock Gearman::Util::pack_req_command(@_); +}; + +my $err; +my $get = sub { + return Gearman::Util::read_res_packet($sock, \$err);; +}; + +#$send->("submit_job_bg", join("\0", "add", "", "5,3")); +$send->("get_status", "FOO"); +my $res = $get->() or die "no handle"; +die "not a status_res packet" unless $res->{type} eq "status_res"; + +while (1) { + $send->("submit_job", join("\0", "add", "-", "5,3")); + $res = $get->() or die "no handle"; + print Dumper($res); + die "not a job_created res" unless $res->{type} eq "job_created"; + + while ($res = $get->()) { + print "New packet: " . Dumper($res); + } + print "Error: $err\n"; + + exit 0; + +} + + + + diff --git a/wcmtools/gearman/dev/dmap-worker.pl b/wcmtools/gearman/dev/dmap-worker.pl new file mode 100755 index 0000000..0ba6953 --- /dev/null +++ b/wcmtools/gearman/dev/dmap-worker.pl @@ -0,0 +1,76 @@ +#!/usr/bin/perl +use strict; +use Gearman::Util; +use IO::Socket::INET; +use Data::Dumper; +use Storable; +$Storable::Eval = 1; + +my $server = shift; +$server ||= "localhost"; + +my $sock = IO::Socket::INET->new(PeerAddr => "$server:7003") + or die "no socket."; + +my $send = sub { + print $sock Gearman::Util::pack_req_command(@_); +}; + +my $err; +my $get = sub { + my $res; + while (1) { + $res = Gearman::Util::read_res_packet($sock, \$err); + return undef unless $res; + return $res unless $res->{type} eq "noop"; + } +}; + +$send->("can_do", "dmap"); + +while (1) { + $send->("grab_job"); + + my $res = $get->(); + die "ERROR: $err\n" unless $res; + print " res.type = $res->{type}\n"; + + if ($res->{type} eq "error") { + print "ERROR: " . Dumper($res); + exit 0; + } + + if ($res->{type} eq "no_job") { + $send->("pre_sleep"); + + print "Sleeping.\n"; + my $rin; + vec($rin, fileno($sock), 1) = 1; + my $nfound = select($rin, undef, undef, 2.0); + print " select returned = $nfound\n"; + next; + } + + if ($res->{type} eq "job_assign") { + my $ar = $res->{blobref}; + die "uh, bogus res" unless + $$ar =~ s/^(.+?)\0(.+?)\0//; + my ($handle, $func) = ($1, $2); + print "GOT JOB: $handle -- $func\n"; + + if ($func eq "dmap") { + my $rq = Storable::thaw($$ar); + my $code = $rq->[0]; + my @val = map { &$code; } $rq->[1]; + print "VALS: [@val]\n"; + $send->("work_complete", join("\0", $handle, Storable::freeze(\@val))); + } + next; + } + + print "RES: ", Dumper($res); + +} + + + diff --git a/wcmtools/gearman/dev/dmap.pl b/wcmtools/gearman/dev/dmap.pl new file mode 100755 index 0000000..3dea4b0 --- /dev/null +++ b/wcmtools/gearman/dev/dmap.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +use strict; +use DMap; +DMap::set_job_servers("localhost", "sammy", "kenny"); + +my @foo = dmap { "$_ = " . `hostname` } (1..10); + +print "dmap says:\n @foo"; + + + + diff --git a/wcmtools/gearman/dev/test-gear.pl b/wcmtools/gearman/dev/test-gear.pl new file mode 100755 index 0000000..0195033 --- /dev/null +++ b/wcmtools/gearman/dev/test-gear.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +use strict; +use Gearman::Util; +use IO::Socket::INET; +my $sock = IO::Socket::INET->new(PeerAddr => "localhost:7003") + or die "no socket."; + +print $sock "gibberish_cmd\r\n"; +my $res = <$sock>; +die "bogus response" unless $res =~ /^ERR unknown_command /; + +my $cmd; + +my $echo_val = "The time is " . time() . " \r\n and a null\0 is fun."; +print $sock Gearman::Util::pack_req_command("echo_req", $echo_val); + +my $err; +my $res = Gearman::Util::read_res_packet($sock, \$err); +use Data::Dumper; +print "ERROR: $err\n"; +print Dumper($res); + + diff --git a/wcmtools/gearman/dev/worker.pl b/wcmtools/gearman/dev/worker.pl new file mode 100755 index 0000000..0fd0328 --- /dev/null +++ b/wcmtools/gearman/dev/worker.pl @@ -0,0 +1,76 @@ +#!/usr/bin/perl +use strict; +use Gearman::Util; +use IO::Socket::INET; +use Data::Dumper; +my $sock = IO::Socket::INET->new(PeerAddr => "localhost:7003") + or die "no socket."; + +my $send = sub { + print $sock Gearman::Util::pack_req_command(@_); +}; + +my $err; +my $get = sub { + my $res; + while (1) { + $res = Gearman::Util::read_res_packet($sock, \$err); + return undef unless $res; + return $res unless $res->{type} eq "noop"; + } +}; + +$send->("can_do", "frob"); +$send->("cant_do", "frob"); +$send->("can_do", "bar"); +$send->("reset_abilities"); + +$send->("can_do", "add"); + +while (1) { + $send->("grab_job"); + + my $res = $get->(); + die "ERROR: $err\n" unless $res; + print " res.type = $res->{type}\n"; + + if ($res->{type} eq "error") { + print "ERROR: " . Dumper($res); + exit 0; + } + + if ($res->{type} eq "no_job") { + $send->("pre_sleep"); + + print "Sleeping.\n"; + my $rin; + vec($rin, fileno($sock), 1) = 1; + my $nfound = select($rin, undef, undef, 2.0); + print " select returned = $nfound\n"; + next; + } + + if ($res->{type} eq "job_assign") { + my $ar = $res->{blobref}; + die "uh, bogus res" unless + $$ar =~ s/^(.+)\0(.+)\0//; + my ($handle, $func) = ($1, $2); + + print " GOT: handle=$handle, func=$func, args=($$ar)\n"; + if ($func eq "add") { + for (1..10) { + $send->("work_status", join("\0", $handle, $_, 10)); + select undef, undef, undef, 0.5; + } + my ($n1, $n2) = split(/,/, $$ar); + $send->("work_complete", join("\0", $handle, $n1+$n2)); + } + next; + } + + print "RES: ", Dumper($res); + +} + + + diff --git a/wcmtools/gearman/doc/overview.txt b/wcmtools/gearman/doc/overview.txt new file mode 100755 index 0000000..de508db --- /dev/null +++ b/wcmtools/gearman/doc/overview.txt @@ -0,0 +1,225 @@ +[ WARNING: EXTREMELY PRELIMINARY! ] + +GearMan: A distributed job system +Brad Whitaker + +================================== + +TODO: error responses to malformed/unexpected packets? + priorities, expirations of old/irrelevant jobs + upper-layer handling of async system going down + reopulation of jobs + +Architecture: + + [ job_server_1 ] \ + [ job_server_2 ] | <====> application + [ job_server_n ] / + + \ | / + -*- persistent tcp connections between job servers/workers + / | \ + + [ worker_1 ] + [ worker_2 ] + [ worker_n ] + + +Guarantees: + +1) Each job server will kill dups within that job server (not global) +2) Jobs will be retried as specified, as long as the job server is running +3) Each worker will have exactly one task at a time + ... ? + +Non-Guarantees: + +1) Global duplicate checking is not provided +2) No job is guaranteed to complete +3) Loss of any job server will lose any jobs registered with it + ... ? + + +Work flow: + +1) Job server starts up, all workers connect and announce their + +2) Application sends job to random job server, noting the job record so it can + be recreated in the future if necessary. + + a) Synchronous: Application stays connected and waits for response + b) Asynchronous: + +3) Job server handles job: + + Possible messages: + + [worker => job server] + "here's what i can do." + "goodbye." + "i'm about to sleep." + "got a job for me?" + "i'm 1/100 complete now." + "i've completed my job." + + [job server => worker] + "noop." / "wake up." + "here's a job to do." + + [application => job server] + "create this new job." + "how far along is this job?" + "is this job finished?" + + [job server => application] + "okay (here is its handle)." + "job is 1/100 complete." + "job completed as follows: ..." + + + Request/Response cycles: + + [ worker <=> job server ] + "here's what i can do" => (announcement) + "goodbye" => (announcement) + "i'm about to sleep" => (announcement) + "i'm 1/100 complete now" => (announcement) + "i've completed my job" => (announcement) + "got a job for me?" => "here's a job to do." + + [ application <=> job server ] + "create this new job." => "okay (here is its handle)." + "how far along is this job?" => "job is 1/100 complete." + "is this job finished?" => "job completed as follows: ..." + + [ job server <=> worker ] + "wake up." => (worker wakes up from sleep) + "here is a job to do" => "i'm 1/100 complete now." + => "i've completed my job" + + [ job server <=> application ] + (only speaks in response to application requests) + + + Best case conversation example: + + worker_n => job_server_n: "got a job for me?" + job_server_n => worker_n: "yes, here is a job i've locked for you" + worker_n => job_server_n: "here is the result" + + Worse case: + + while ($time < $sleep_threshold) { + for $js (1..n) { + worker => job_server_$js: "got a job for me?" + job_server_$js => worker: "no, sorry" + } + } + + worker => all_job_servers: "going to sleep" + + [ worker receives wakeup packet ] or [ t seconds elapse ] + + worker wakes up and resumes loop + + +Packet types: + + Generic header: + + [ 4 byte magic + 4 byte packet type + 4 byte length ] + + Magic: + 4 opaque bytes to verify state machine "\0REQ" or "\0RES" + + Packet type: + (see Gearman::Util) + + Length: + Post-header data length + + +Properties of a job: + + func -- what function name + opaque scalar arg (passed through end-to-end, no interpretation by libraries/server) + uniq key -- for merging (default: don't merge, "-" means merge on opaque scalar) + + retry count + fail after time -- treat a timeout as a failure + do job if dequeued and no listeners ("submit_job_bg") + priority ("submit_job_high") + on_* handlers + + behavior when there's no worker registered for that job type? + + +Notes: + + -- document whether on_fail gets called on all failures, or just last one, when retry_count is in use + -- document that uniq merging isn't guaranteed, just that it's permitted. if two tasks must not run + at the same time, the task itself needs to do appropriate locking with itself / other tasks. + -- the uniq merging will generally work in practice with multiple Job servers because the client + hashes the (func + opaque_arg) onto the set of servers + + + +Task summary: + +1) mail + name => mail + dupkey => '' (don't check dups) + type => async+handle + args => storable MIME::Lite/etc + +2) gal resize + name => resize + dupkey => uid-gallid-w-h + type => async+handle + args => storable of images to resize/how + +3) thumb pregen + name => thumbgen + dupkey => uid-upicid-w-h + type => async+handle + args => storable of images to resize + +4) LJ crons + name => pay_updateaccounts/etc + dupkey => '' (no dup checking) + type => async + args => @ARGV to pass to job? + +6) Dirty Flushing + name => dirty + dupkey => friends-uid, backup-uid, etc + type => async+handle + args => none + +7) CmdBuffer jobs + name => weblogscom + dupkey => uid + type => async+throw-away + args => none + +8) RSS fetching + name => rss + dupkey => uid + type => async+handle + args => none + +9) captcha generation + name => captcha + dupkey => dd-hh ? maybe '1' or something + type => async+throw-away + args => none + +10) birthday emails + name => bday + dupkey => yyyy-mm-dd + type => async+handle + args => none + +11) restart web nodes + -- ask brad about this? \ No newline at end of file diff --git a/wcmtools/gearman/lib/Gearman/Client.pm b/wcmtools/gearman/lib/Gearman/Client.pm new file mode 100755 index 0000000..8f37fe2 --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Client.pm @@ -0,0 +1,303 @@ +#!/usr/bin/perl + +#TODO: fail_after_idle + +package Gearman::Client; + +use strict; +use IO::Socket::INET; +use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET); + +use Gearman::Objects; +use Gearman::Task; +use Gearman::Taskset; +use Gearman::JobStatus; + +sub new { + my ($class, %opts) = @_; + my $self = $class; + $self = fields::new($class) unless ref $self; + + $self->{job_servers} = []; + $self->{js_count} = 0; + $self->{sock_cache} = {}; + + $self->job_servers(@{ $opts{job_servers} }) + if $opts{job_servers}; + + return $self; +} + +sub new_task_set { + my Gearman::Client $self = shift; + return Gearman::Taskset->new($self); +} + +# getter/setter +sub job_servers { + my Gearman::Client $self = shift; + return $self->{job_servers} unless @_; + my $list = [ @_ ]; + $self->{js_count} = scalar @$list; + foreach (@$list) { + $_ .= ":7003" unless /:/; + } + return $self->{job_servers} = $list; +} + +sub _get_task_from_args { + my Gearman::Task $task; + if (ref $_[0]) { + $task = $_[0]; + Carp::croak("Argument isn't a Gearman::Task") unless ref $_[0] eq "Gearman::Task"; + } else { + my ($func, $arg_p, $opts) = @_; + my $argref = ref $arg_p ? $arg_p : \$arg_p; + Carp::croak("Function argument must be scalar or scalarref") + unless ref $argref eq "SCALAR"; + $task = Gearman::Task->new($func, $argref, $opts); + } + return $task; + +} + +# given a (func, arg_p, opts?), returns either undef (on fail) or scalarref of result +sub do_task { + my Gearman::Client $self = shift; + my Gearman::Task $task = &_get_task_from_args; + + my $ret = undef; + my $did_err = 0; + + $task->{on_complete} = sub { + $ret = shift; + }; + + $task->{on_fail} = sub { + $did_err = 1; + }; + + my $ts = $self->new_task_set; + $ts->add_task($task); + $ts->wait; + + return $did_err ? undef : $ret; + +} + +# given a (func, arg_p, opts?) or +# Gearman::Task, dispatches job in background. returns the handle from the jobserver, or false if any failure +sub dispatch_background { + my Gearman::Client $self = shift; + my Gearman::Task $task = &_get_task_from_args; + + my ($jst, $jss) = $self->_get_random_js_sock; + return 0 unless $jss; + + my $req = $task->pack_submit_packet("background"); + my $len = length($req); + my $rv = $jss->write($req, $len); + + my $err; + my $res = Gearman::Util::read_res_packet($jss, \$err); + return 0 unless $res && $res->{type} eq "job_created"; + return "$jst//${$res->{blobref}}"; +} + +sub get_status { + my Gearman::Client $self = shift; + my $handle = shift; + my ($hostport, $shandle) = split(m!//!, $handle); + return undef unless grep { $hostport eq $_ } @{ $self->{job_servers} }; + + my $sock = $self->_get_js_sock($hostport) + or return undef; + + my $req = Gearman::Util::pack_req_command("get_status", + $shandle); + my $len = length($req); + my $rv = $sock->write($req, $len); + + my $err; + my $res = Gearman::Util::read_res_packet($sock, \$err); + return undef unless $res && $res->{type} eq "status_res"; + my @args = split(/\0/, ${ $res->{blobref} }); + return undef unless $args[0]; + shift @args; + $self->_put_js_sock($hostport, $sock); + return Gearman::JobStatus->new(@args); +} + +# returns a socket from the cache. it should be returned to the +# cache with _put_js_sock. the hostport isn't verified. the caller +# should verify that $hostport is in the set of jobservers. +sub _get_js_sock { + my Gearman::Client $self = shift; + my $hostport = shift; + + if (my $sock = delete $self->{sock_cache}{$hostport}) { + return $sock if $sock->connected; + } + + my $sock = IO::Socket::INET->new(PeerAddr => $hostport, + Timeout => 1) + or return undef; + + setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + $sock->autoflush(1); + return $sock; +} + +# way for a caller to give back a socket it previously requested. +# the $hostport isn't verified, so the caller should verify the +# $hostport is still in the set of jobservers. +sub _put_js_sock { + my Gearman::Client $self = shift; + my ($hostport, $sock) = @_; + + $self->{sock_cache}{$hostport} ||= $sock; +} + +sub _get_random_js_sock { + my Gearman::Client $self = shift; + my $getter = shift; + return undef unless $self->{js_count}; + + $getter ||= sub { my $hostport = shift; return $self->_get_js_sock($hostport); }; + + my $ridx = int(rand($self->{js_count})); + for (my $try = 0; $try < $self->{js_count}; $try++) { + my $aidx = ($ridx + $try) % $self->{js_count}; + my $hostport = $self->{job_servers}[$aidx]; + my $sock = $getter->($hostport) or next; + return ($hostport, $sock); + } + return (); +} + +1; +__END__ + +=head1 NAME + +Gearman::Client - Client for gearman distributed job system + +=head1 SYNOPSIS + + use Gearman::Client; + my $client = Gearman::Client->new; + $client->job_servers('127.0.0.1', '10.0.0.1'); + + # running a single task + my $result_ref = $client->do_task("add", "1+2"); + print "1 + 2 = $$result_ref\n"; + + # waiting on a set of tasks in parallel + my $taskset = $client->new_task_set; + $taskset->add_task( "add" => "1+2", { + on_complete => sub { ... } + }); + $taskset->add_task( "divide" => "5/0", { + on_fail => sub { print "divide by zero error!\n"; }, + }); + $taskset->wait; + + +=head1 DESCRIPTION + +I is a client class for the Gearman distributed job +system, providing a framework for sending jobs to one or more Gearman +servers. These jobs are then distributed out to a farm of workers. + +Callers instantiate a I object and from it dispatch +single tasks, sets of tasks, or check on the status of tasks. + +=head1 USAGE + +=head2 Gearman::Client->new(\%options) + +Creates a new I object, and returns the object. + +If I<%options> is provided, initializes the new client object with the +settings in I<%options>, which can contain: + +=over 4 + +=item * job_servers + +Calls I (see below) to initialize the list of job +servers. Value in this case should be an arrayref. + +=back + +=head2 $client->job_servers(@servers) + +Initializes the client I<$client> with the list of job servers in I<@servers>. +I<@servers> should contain a list of IP addresses, with optional port +numbers. For example: + + $client->job_servers('127.0.0.1', '192.168.1.100:7003'); + +If the port number is not provided, C<7003> is used as the default. + +=head2 $client-Edo_task($task) + +=head2 $client-Edo_task($funcname, $arg, \%options) + +Dispatches a task and waits on the results. May either provide a +L object, or the 3 arguments that the Gearman::Task +constructor takes. + +Returns a scalar reference to the result, or undef on failure. + +If you provide on_complete and on_fail handlers, they're ignored, as +this function currently overrides them. + +=head2 $client-Edispatch_background($task) + +=head2 $client-Edispatch_background($funcname, $arg, \%options) + +Dispatches a task and doesn't wait for the result. Return value +is + +=head2 $taskset = $client-Enew_task_set + +Creates and returns a new I object. + +=head2 $taskset-Eadd_task($task) + +=head2 $taskset-Eadd_task($funcname, $arg, $uniq) + +=head2 $taskset-Eadd_task($funcname, $arg, \%options) + +Adds a task to a taskset. Three different calling conventions are +available. + +=head2 $taskset-Ewait + +Waits for a response from the job server for any of the tasks listed +in the taskset. Will call the I handlers for each of the tasks +that have been completed, updated, etc. Doesn't return until +everything has finished running or failing. + +=head1 EXAMPLES + +=head2 Summation + +This is an example client that sends off a request to sum up a list of +integers. + + use Gearman::Client; + use Storable qw( freeze ); + my $client = Gearman::Client->new; + $client->job_servers('127.0.0.1'); + my $tasks = $client->new_task_set; + my $handle = $tasks->add_task(sum => freeze([ 3, 5 ]), { + on_complete => sub { print ${ $_[0] }, "\n" } + }); + $tasks->wait; + +See the I documentation for the worker for the I +function. + +=cut diff --git a/wcmtools/gearman/lib/Gearman/JobStatus.pm b/wcmtools/gearman/lib/Gearman/JobStatus.pm new file mode 100755 index 0000000..c972a1f --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/JobStatus.pm @@ -0,0 +1,20 @@ + +package Gearman::JobStatus; + +use strict; + +sub new { + my ($class, $known, $running, $nu, $de) = @_; + undef $nu unless length($nu); + undef $de unless length($de); + my $self = [ $known, $running, $nu, $de ]; + bless $self; + return $self; +} + +sub known { my $self = shift; return $self->[0]; } +sub running { my $self = shift; return $self->[1]; } +sub progress { my $self = shift; return defined $self->[2] ? [ $self->[2], $self->[3] ] : undef; } +sub percent { my $self = shift; return (defined $self->[2] && $self->[3]) ? ($self->[2] / $self->[3]) : undef; } + +1; diff --git a/wcmtools/gearman/lib/Gearman/Objects.pm b/wcmtools/gearman/lib/Gearman/Objects.pm new file mode 100755 index 0000000..fe2b745 --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Objects.pm @@ -0,0 +1,52 @@ +use strict; + +package Gearman::Client; +use fields ( + 'job_servers', + 'js_count', + 'sock_cache', # hostport -> socket + ); + +package Gearman::Taskset; + +use fields ( + 'waiting', # { handle => [Task, ...] } + 'client', # Gearman::Client + 'need_handle', # arrayref + + 'default_sock', # default socket (non-merged requests) + 'default_sockaddr', # default socket's ip/port + + 'loaned_sock', # { hostport => socket } + + ); + + +package Gearman::Task; + +use fields ( + # from client: + 'func', + 'argref', + # opts from client: + 'uniq', + 'on_complete', + 'on_fail', + 'on_retry', + 'on_status', + 'retry_count', + 'fail_after_idle', + 'high_priority', + + # from server: + 'handle', + + # maintained by this module: + 'retries_done', + 'taskset', + 'jssock', # jobserver socket. shared by other tasks in the same taskset, + # but not w/ tasks in other tasksets using the same Gearman::Client + ); + + +1; diff --git a/wcmtools/gearman/lib/Gearman/Task.pm b/wcmtools/gearman/lib/Gearman/Task.pm new file mode 100755 index 0000000..f1536eb --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Task.pm @@ -0,0 +1,210 @@ +package Gearman::Task; + +use strict; +use Carp (); +use String::CRC32 (); + +# constructor, given: ($func, $argref, $opts); +sub new { + my $class = shift; + + my $self = $class; + $self = fields::new($class) unless ref $self; + + $self->{func} = shift + or Carp::croak("No function given"); + + $self->{argref} = shift || do { my $empty = ""; \$empty; }; + Carp::croak("Argref not a scalar reference") unless ref $self->{argref} eq "SCALAR"; + + my $opts = shift || {}; + for my $k (qw( uniq + on_complete on_fail on_retry on_status + retry_count fail_after_idle high_priority + )) { + $self->{$k} = delete $opts->{$k}; + } + + if (%{$opts}) { + Carp::croak("Unknown option(s): " . join(", ", sort keys %$opts)); + } + + $self->{retries_done} = 0; + + return $self; +} + +sub taskset { + my Gearman::Task $task = shift; + + # getter + return $task->{taskset} unless @_; + + # setter + my Gearman::Taskset $ts = shift; + $task->{taskset} = $ts; + + my $merge_on = $task->{uniq} && $task->{uniq} eq "-" ? + $task->{argref} : \ $task->{uniq}; + if ($$merge_on) { + my $hash_num = _hashfunc($merge_on); + $task->{jssock} = $ts->_get_hashed_sock($hash_num); + } else { + $task->{jssock} = $ts->_get_default_sock; + } + + return $task->{taskset}; +} + +# returns number in range [0,32767] given a scalarref +sub _hashfunc { + return (String::CRC32::crc32(${ shift() }) >> 16) & 0x7fff; +} + +sub pack_submit_packet { + my Gearman::Task $task = shift; + my $is_background = shift; + + my $mode = $is_background ? + "submit_job_bg" : + ($task->{high_priority} ? + "submit_job_high" : + "submit_job"); + + return Gearman::Util::pack_req_command($mode, + join("\0", $task->{func}, $task->{uniq}, ${ $task->{argref} })); +} + +sub fail { + my Gearman::Task $task = shift; + + # try to retry, if we can + if ($task->{retries_done} < $task->{retry_count}) { + $task->{retries_done}++; + $task->{on_retry}->($task->{retries_done}) if $task->{on_retry}; + $task->handle(undef); + return $task->{taskset}->add_task($task); + } + + return undef unless $task->{on_fail}; + $task->{on_fail}->(); + return undef; +} + +sub complete { + my Gearman::Task $task = shift; + return unless $task->{on_complete}; + my $result_ref = shift; + $task->{on_complete}->($result_ref); +} + +sub status { + my Gearman::Task $task = shift; + return unless $task->{on_status}; + my ($nu, $de) = @_; + $task->{on_status}->($nu, $de); +} + +# getter/setter for the fully-qualified handle of form "IP:port//shandle" where +# shandle is an opaque handle specific to the job server running on IP:port +sub handle { + my Gearman::Task $task = shift; + return $task->{handle} unless @_; + return $task->{handle} = shift; +} + + +1; +__END__ + +=head1 NAME + +Gearman::Task - a task in Gearman, from the point of view of a client + +=head1 SYNOPSIS + + my $task = Gearman::Task->new("add", "1+2", { + ..... + + }; + + $taskset->add_task($task); + $client->do_task($task); + $client->dispatch_background($task); + + +=head1 DESCRIPTION + +I is a Gearman::Client's representation of a task to be +done. + +=head1 USAGE + +=head2 Gearman::Task->new($func, $arg, \%options) + +Creates a new I object, and returns the object. + +I<$func> is the function name to be run. (that you have a worker registered to process) + +I<$arg> is an opaque scalar or scalarref representing the argument(s) +to pass to the distributed function. If you want to pass multiple +arguments, you must encode them somehow into this one. That's up to +you and your worker. + +I<%options> can contain: + +=over 4 + +=item * uniq + +A key which indicates to the server that other tasks with the same +function name and key will be merged into one. That is, the task +will be run just once, but all the listeners waiting on that job +will get the response multiplexed back to them. + +Uniq may also contain the magic value "-" (a single hyphen) which +means the uniq key is the contents of the args. + +=item * on_complete + +A subroutine reference to be invoked when the task is completed. The +subroutine will be passed a reference to the return value from the worker +process. + +=item * on_fail + +A subroutine reference to be invoked when the task fails (or fails for +the last time, if retries were specified). No arguments are +passed to this callback. This callback won't be called after a failure +if more retries are still possible. + +=item * on_retry + +A subroutine reference to be invoked when the task fails, but is about +to be retried. + +Is passed one argument, what retry attempt number this is. (starts with 1) + +=item * on_status + +A subroutine reference to be invoked if the task emits status updates. +Arguments passed to the subref are ($numerator, $denominator), where those +are left up to the client and job to determine. + +=item * retry_count + +Number of times job will be retried if there are failures. Defaults to 0. + +=item * high_priority + +Boolean, whether this job should take priority over other jobs already +enqueued. + +=item * fail_after_idle + +Automatically fail after this many seconds have elapsed. Defaults to 0, +which means never. + +=back + +=cut diff --git a/wcmtools/gearman/lib/Gearman/Taskset.pm b/wcmtools/gearman/lib/Gearman/Taskset.pm new file mode 100755 index 0000000..f3e3892 --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Taskset.pm @@ -0,0 +1,269 @@ +package Gearman::Taskset; + +use strict; +use Carp (); +use Gearman::Util; + +sub new { + my $class = shift; + my Gearman::Client $client = shift; + + my $self = $class; + $self = fields::new($class) unless ref $self; + + $self->{waiting} = {}; + $self->{need_handle} = []; + $self->{client} = $client; + $self->{loaned_sock} = {}; + + return $self; +} + +sub DESTROY { + my Gearman::Taskset $ts = shift; + + if ($ts->{default_sock}) { + $ts->{client}->_put_js_sock($ts->{default_sockaddr}, $ts->{default_sock}); + } + + while (my ($hp, $sock) = each %{ $ts->{loaned_sock} }) { + $ts->{client}->_put_js_sock($hp, $sock); + } +} + +sub _get_loaned_sock { + my Gearman::Taskset $ts = shift; + my $hostport = shift; + if (my $sock = $ts->{loaned_sock}{$hostport}) { + return $sock if $sock->connected; + delete $ts->{loaned_sock}{$hostport}; + } + + my $sock = $ts->{client}->_get_js_sock($hostport); + return $ts->{loaned_sock}{$hostport} = $sock; +} + +sub wait { + my Gearman::Taskset $ts = shift; + + while (keys %{$ts->{waiting}}) { + $ts->_wait_for_packet(); + # TODO: timeout jobs that have been running too long. the _wait_for_packet + # loop only waits 0.5 seconds. + } +} + +# ->add_task($func, <$scalar | $scalarref>, <$uniq | $opts_hashref> +# opts: +# -- uniq +# -- on_complete +# -- on_fail +# -- on_status +# -- retry_count +# -- fail_after_idle +# -- high_priority +# ->add_task(Gearman::Task) +# + +sub add_task { + my Gearman::Taskset $ts = shift; + my $task; + + if (ref $_[0]) { + $task = shift; + } else { + my $func = shift; + my $arg_p = shift; # scalar or scalarref + my $opts = shift; # $uniq or hashref of opts + + my $argref = ref $arg_p ? $arg_p : \$arg_p; + unless (ref $opts eq "HASH") { + $opts = { uniq => $opts }; + } + + $task = Gearman::Task->new($func, $argref, $opts); + } + $task->taskset($ts); + + my $req = $task->pack_submit_packet; + my $len = length($req); + my $rv = $task->{jssock}->syswrite($req, $len); + die "Wrote $rv but expected to write $len" unless $rv == $len; + + push @{ $ts->{need_handle} }, $task; + while (@{ $ts->{need_handle} }) { + my $rv = $ts->_wait_for_packet($task->{jssock}); + if (! $rv) { + shift @{ $ts->{need_handle} }; # ditch it, it failed. + # this will resubmit it if it failed. + print " INITIAL SUBMIT FAILED\n"; + return $task->fail; + } + } + + return $task->handle; +} + +sub _get_default_sock { + my Gearman::Taskset $ts = shift; + return $ts->{default_sock} if $ts->{default_sock}; + + my $getter = sub { + my $hostport = shift; + return + $ts->{loaned_sock}{$hostport} || + $ts->{client}->_get_js_sock($hostport); + }; + + my ($jst, $jss) = $ts->{client}->_get_random_js_sock($getter); + $ts->{loaned_sock}{$jst} ||= $jss; + + $ts->{default_sock} = $jss; + $ts->{default_sockaddr} = $jst; + return $jss; +} + +sub _get_hashed_sock { + my Gearman::Taskset $ts = shift; + my $hv = shift; + + my Gearman::Client $cl = $ts->{client}; + + for (my $off = 0; $off < $cl->{js_count}; $off++) { + my $idx = ($hv + $off) % ($cl->{js_count}); + my $sock = $ts->_get_loaned_sock($cl->{job_servers}[$idx]); + return $sock if $sock; + } + + return undef; +} + +# returns boolean when given a sock to wait on. +# otherwise, return value is undefined. +sub _wait_for_packet { + my Gearman::Taskset $ts = shift; + my $sock = shift; # optional socket to singularly read from + + my ($res, $err); + if ($sock) { + $res = Gearman::Util::read_res_packet($sock, \$err); + return 0 unless $res; + return $ts->_process_packet($res, $sock); + } else { + # TODO: cache this vector? + my ($rin, $rout, $eout); + my %watching; + + for my $sock ($ts->{default_sock}, values %{ $ts->{loaned_sock} }) { + next unless $sock; + my $fd = $sock->fileno; + + vec($rin, $fd, 1) = 1; + $watching{$fd} = $sock; + } + + my $nfound = select($rout=$rin, undef, $eout=$rin, 0.5); + return 0 if ! $nfound; + + foreach my $fd (keys %watching) { + next unless vec($rout, $fd, 1); + # TODO: deal with error vector + my $sock = $watching{$fd}; + $res = Gearman::Util::read_res_packet($sock, \$err); + $ts->_process_packet($res, $sock) if $res; + } + return 1; + + } +} + +sub _ip_port { + my $sock = shift; + return undef unless $sock; + my $pn = getpeername($sock) or return undef; + my ($port, $iaddr) = Socket::sockaddr_in($pn); + return Socket::inet_ntoa($iaddr) . ":$port"; +} + +# note the failure of a task given by its jobserver-specific handle +sub _fail_jshandle { + my Gearman::Taskset $ts = shift; + my $shandle = shift; + + my $task_list = $ts->{waiting}{$shandle} or + die "Uhhhh: got work_fail for unknown handle: $shandle\n"; + + my Gearman::Task $task = shift @$task_list or + die "Uhhhh: task_list is empty on work_fail for handle $shandle\n"; + + $task->fail; + delete $ts->{waiting}{$shandle} unless @$task_list; +} + +sub _process_packet { + my Gearman::Taskset $ts = shift; + my ($res, $sock) = @_; + + if ($res->{type} eq "job_created") { + my Gearman::Task $task = shift @{ $ts->{need_handle} } or + die "Um, got an unexpected job_created notification"; + + my $shandle = ${ $res->{'blobref'} }; + my $ipport = _ip_port($sock); + + # did sock become disconnected in the meantime? + if (! $ipport) { + $ts->_fail_jshandle($shandle); + return 1; + } + + $task->handle("$ipport//$shandle"); + push @{ $ts->{waiting}{$shandle} ||= [] }, $task; + return 1; + } + + if ($res->{type} eq "work_fail") { + my $shandle = ${ $res->{'blobref'} }; + $ts->_fail_jshandle($shandle); + return 1; + } + + if ($res->{type} eq "work_complete") { + ${ $res->{'blobref'} } =~ s/^(.+?)\0// + or die "Bogus work_complete from server"; + my $shandle = $1; + + my $task_list = $ts->{waiting}{$shandle} or + die "Uhhhh: got work_complete for unknown handle: $shandle\n"; + + my Gearman::Task $task = shift @$task_list or + die "Uhhhh: task_list is empty on work_complete for handle $shandle\n"; + + $task->complete($res->{'blobref'}); + delete $ts->{waiting}{$shandle} unless @$task_list; + + return 1; + } + + if ($res->{type} eq "work_status") { + my ($shandle, $nu, $de) = split(/\0/, ${ $res->{'blobref'} }); + + my $task_list = $ts->{waiting}{$shandle} or + die "Uhhhh: got work_status for unknown handle: $shandle\n"; + + # FIXME: the server is (probably) sending a work_status packet for each + # interested client, even if the clients are the same, so probably need + # to fix the server not to do that. just put this FIXME here for now, + # though really it's a server issue. + foreach my Gearman::Task $task (@$task_list) { + $task->status($nu, $de); + } + + return 1; + } + + die "Unknown/unimplemented packet type: $res->{type}"; + +} + +1; diff --git a/wcmtools/gearman/lib/Gearman/Util.pm b/wcmtools/gearman/lib/Gearman/Util.pm new file mode 100755 index 0000000..23ba878 --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Util.pm @@ -0,0 +1,128 @@ + +package Gearman::Util; +use strict; + +# I: to jobserver +# O: out of job server +# W: worker +# C: client of job server +# J : jobserver +our %cmd = ( + 1 => [ 'I', "can_do" ], # from W: [FUNC] + 2 => [ 'I', "cant_do" ], # from W: [FUNC] + 3 => [ 'I', "reset_abilities" ], # from W: --- + 22 => [ 'I', "set_client_id" ], # W->J: [RANDOM_STRING_NO_WHITESPACE] + 4 => [ 'I', "pre_sleep" ], # from W: --- + + 6 => [ 'O', "noop" ], # J->W --- + 7 => [ 'I', "submit_job" ], # C->J FUNC[0]UNIQ[0]ARGS + 21 => [ 'I', "submit_job_high" ], # C->J FUNC[0]UNIQ[0]ARGS + 18 => [ 'I', "submit_job_bg" ], # C->J " " " " " + + 8 => [ 'O', "job_created" ], # J->C HANDLE + 9 => [ 'I', "grab_job" ], # W->J -- + 10 => [ 'O', "no_job" ], # J->W -- + 11 => [ 'O', "job_assign" ], # J->W HANDLE[0]FUNC[0]ARG + + 12 => [ 'IO', "work_status" ], # W->J/C: HANDLE[0]NUMERATOR[0]DENOMINATOR + 13 => [ 'IO', "work_complete" ], # W->J/C: HANDLE[0]RES + 14 => [ 'IO', "work_fail" ], # W->J/C: HANDLE + + 15 => [ 'I', "get_status" ], # C->J: HANDLE + 20 => [ 'O', "status_res" ], # C->J: HANDLE[0]KNOWN[0]RUNNING[0]NUM[0]DENOM + + 16 => [ 'I', "echo_req" ], # ?->J TEXT + 17 => [ 'O', "echo_res" ], # J->? TEXT + + 19 => [ 'O', "error" ], # J->? ERRCODE[0]ERR_TEXT + ); + +our %num; # name -> num +while (my ($num, $ary) = each %cmd) { + die if $num{$ary->[1]}; + $num{$ary->[1]} = $num; +} + +sub cmd_name { + my $num = shift; + my $c = $cmd{$num}; + return $c ? $c->[1] : undef; +} + +sub pack_req_command { + my $type_arg = shift; + my $type = $num{$type_arg} || $type_arg; + die "Bogus type arg of '$type_arg'" unless $type; + my $arg = $_[0] || ''; + my $len = length($arg); + return "\0REQ" . pack("NN", $type, $len) . $arg; +} + +sub pack_res_command { + my $type_arg = shift; + my $type = int($type_arg) || $num{$type_arg}; + die "Bogus type arg of '$type_arg'" unless $type; + my $len = length($_[0]); + return "\0RES" . pack("NN", $type, $len) . $_[0]; +} + +# returns undef on closed socket or malformed packet +sub read_res_packet { + my $sock = shift; + my $err_ref = shift; + + my $buf; + my $rv; + + my $err = sub { + my $code = shift; + $$err_ref = $code if ref $err_ref; + return undef; + }; + + return $err->("malformed_header") unless sysread($sock, $buf, 12) == 12; + my ($magic, $type, $len) = unpack("a4NN", $buf); + return $err->("malformed_magic") unless $magic eq "\0RES"; + + if ($len) { + $rv = sysread($sock, $buf, $len); + return $err->("short_body") unless $rv == $len; + } + + $type = $cmd{$type}; + return $err->("bogus_command") unless $type; + return $err->("bogus_command_type") unless index($type->[0], "O") != -1; + + return { + 'type' => $type->[1], + 'len' => $len, + 'blobref' => \$buf, + }; +} + +sub send_req { + my ($sock, $reqref) = @_; + return 0 unless $sock; + + my $len = length($$reqref); + #TODO: catch SIGPIPE + my $rv = $sock->syswrite($$reqref, $len); + return 0 unless $rv == $len; + return 1; +} + +# given a file descriptor number and a timeout, wait for that descriptor to +# become readable; returns 0 or 1 on if it did or not +sub wait_for_readability { + my ($fileno, $timeout) = @_; + return 0 unless $fileno && $timeout; + + my $rin = 0; + vec($rin, $fileno, 1) = 1; + my $nfound = select($rin, undef, undef, $timeout); + + # nfound can be undef or 0, both failures, or 1, a success + return $nfound ? 1 : 0; +} + +1; diff --git a/wcmtools/gearman/lib/Gearman/Worker.pm b/wcmtools/gearman/lib/Gearman/Worker.pm new file mode 100755 index 0000000..8dbbdfb --- /dev/null +++ b/wcmtools/gearman/lib/Gearman/Worker.pm @@ -0,0 +1,366 @@ +#!/usr/bin/perl + +#TODO: retries? + +use strict; +use Gearman::Util; +use Carp (); +use IO::Socket::INET; + +# this is the object that's handed to the worker subrefs +package Gearman::Job; + +use fields ( + 'func', + 'argref', + 'handle', + + 'jss', # job server's socket + ); + +sub new { + my ($class, $func, $argref, $handle, $jss) = @_; + my $self = $class; + $self = fields::new($class) unless ref $self; + + $self->{func} = $func; + $self->{handle} = $handle; + $self->{argref} = $argref; + $self->{jss} = $jss; + return $self; +} + +# ->set_status($numerator, $denominator) : $bool_sent_to_jobserver +sub set_status { + my Gearman::Job $self = shift; + my ($nu, $de) = @_; + + my $req = Gearman::Util::pack_req_command("work_status", + join("\0", $self->{handle}, $nu, $de)); + return Gearman::Util::send_req($self->{jss}, \$req); +} + +sub argref { + my Gearman::Job $self = shift; + return $self->{argref}; +} + +sub arg { + my Gearman::Job $self = shift; + return ${ $self->{argref} }; +} + + +package Gearman::Worker; +use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET PF_INET SOCK_STREAM); + +use fields ( + 'job_servers', + 'js_count', + 'sock_cache', # host:port -> IO::Socket::INET + 'last_connect_fail', # host:port -> unixtime + 'down_since', # host:port -> unixtime + 'connecting', # host:port -> unixtime connect started at + 'can', # func -> subref + 'client_id', # random identifer string, no whitespace + ); + +sub new { + my ($class, %opts) = @_; + my $self = $class; + $self = fields::new($class) unless ref $self; + + $self->{job_servers} = []; + $self->{js_count} = 0; + $self->{sock_cache} = {}; + $self->{last_connect_fail} = {}; + $self->{down_since} = {}; + $self->{can} = {}; + $self->{client_id} = join("", map { chr(int(rand(26)) + 97) } (1..30)); + + $self->job_servers(@{ $opts{job_servers} }) + if $opts{job_servers}; + + return $self; +} + +sub _get_js_sock { + my Gearman::Worker $self = shift; + my $ipport = shift; + + if (my $sock = $self->{sock_cache}{$ipport}) { + return $sock if getpeername($sock); + delete $self->{sock_cache}{$ipport}; + } + + my $now = time; + my $down_since = $self->{down_since}{$ipport}; + if ($down_since) { + my $down_for = $now - $down_since; + my $retry_period = $down_for > 60 ? 30 : (int($down_for / 2) + 1); + if ($self->{last_connect_fail}{$ipport} > $now - $retry_period) { + return undef; + } + } + + return undef unless $ipport =~ /(^\d+\..+):(\d+)/; + my ($ip, $port) = ($1, $2); + + my $sock; + socket $sock, PF_INET, SOCK_STREAM, IPPROTO_TCP; + #IO::Handle::blocking($sock, 0); + connect $sock, Socket::sockaddr_in($port, Socket::inet_aton($ip)); + + #my $sock = IO::Socket::INET->new(PeerAddr => $ip, + # Timeout => 1); + unless ($sock) { + $self->{down_since}{$ipport} ||= $now; + $self->{last_connect_fail}{$ipport} = $now; + return undef; + } + delete $self->{last_connect_fail}{$ipport}; + delete $self->{down_since}{$ipport}; + $sock->autoflush(1); + setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + $self->{sock_cache}{$ipport} = $sock; + + my $cid_req = Gearman::Util::pack_req_command("set_client_id", $self->{client_id}); + Gearman::Util::send_req($sock, \$cid_req); + + # get this socket's state caught-up + foreach my $func (keys %{$self->{can}}) { + unless (_set_capability($sock, $func, 1)) { + delete $self->{sock_cache}{$ipport}; + return undef; + } + } + + return $sock; +} + +sub _set_capability { + my ($sock, $func, $can) = @_; + + my $req = Gearman::Util::pack_req_command($can ? "can_do" : "cant_do", + $func); + return Gearman::Util::send_req($sock, \$req); +} + +# tell all the jobservers that this worker can't do anything +sub reset_abilities { + my Gearman::Worker $self = shift; + my $req = Gearman::Util::pack_req_command("reset_abilities"); + foreach my $js (@{ $self->{job_servers} }) { + my $jss = $self->_get_js_sock($js); + unless (Gearman::Util::send_req($jss, \$req)) { + delete $self->{sock_cache}{$js}; + } + } + + $self->{can} = {}; +} + +# does one job and returns. no return value. +sub work { + my Gearman::Worker $self = shift; + my $grab_req = Gearman::Util::pack_req_command("grab_job"); + my $presleep_req = Gearman::Util::pack_req_command("pre_sleep"); + my %fd_map; + + while (1) { + + my @jss; + my $need_sleep = 1; + + foreach my $js (@{ $self->{job_servers} }) { + my $jss = $self->_get_js_sock($js) + or next; + + unless (Gearman::Util::send_req($jss, \$grab_req) && + Gearman::Util::wait_for_readability($jss->fileno, 0.50)) { + delete $self->{sock_cache}{$js}; + next; + } + push @jss, [$js, $jss]; + + my ($res, $err); + do { + $res = Gearman::Util::read_res_packet($jss, \$err); + } while ($res && $res->{type} eq "noop"); + + next unless $res; + + if ($res->{type} eq "no_job") { + next; + } + + die "Uh, wasn't expecting a $res->{type} packet" unless $res->{type} eq "job_assign"; + + ${ $res->{'blobref'} } =~ s/^(.+?)\0(.+?)\0// + or die "Uh, regexp on job_assign failed"; + my ($handle, $func) = ($1, $2); + my $job = Gearman::Job->new($func, $res->{'blobref'}, $handle, $jss); + my $handler = $self->{can}{$func}; + my $ret = eval { $handler->($job); }; + + my $work_req; + if (defined $ret) { + $work_req = Gearman::Util::pack_req_command("work_complete", "$handle\0" . (ref $ret ? $$ret : $ret)); + } else { + $work_req = Gearman::Util::pack_req_command("work_fail", $handle); + } + + unless (Gearman::Util::send_req($jss, \$work_req)) { + delete $self->{sock_cache}{$js}; + } + return; + } + + if ($need_sleep) { + my $wake_vec = 0; + foreach my $j (@jss) { + my ($js, $jss) = @$j; + unless (Gearman::Util::send_req($jss, \$presleep_req)) { + delete $self->{sock_cache}{$js}; + next; + } + my $fd = $jss->fileno; + vec($wake_vec, $fd, 1) = 1; + } + + # chill for some arbitrary time until we're woken up again + select($wake_vec, undef, undef, 10); + } + } + +} + +sub register_function { + my Gearman::Worker $self = shift; + my $func = shift; + my $subref = shift; + + my $req = Gearman::Util::pack_req_command("can_do", $func); + + foreach my $js (@{ $self->{job_servers} }) { + my $jss = $self->_get_js_sock($js); + unless (Gearman::Util::send_req($jss, \$req)) { + delete $self->{sock_cache}{$js}; + } + } + + $self->{can}{$func} = $subref; +} + +# getter/setter +sub job_servers { + my Gearman::Worker $self = shift; + return $self->{job_servers} unless @_; + my $list = [ @_ ]; + $self->{js_count} = scalar @$list; + foreach (@$list) { + $_ .= ":7003" unless /:/; + } + return $self->{job_servers} = $list; +} + + +1; +__END__ + +=head1 NAME + +Gearman::Worker - Worker for gearman distributed job system + +=head1 SYNOPSIS + + use Gearman::Worker; + my $worker = Gearman::Worker->new; + $worker->job_servers('127.0.0.1'); + $worker->register_function($funcname => $subref); + $worker->work while 1; + +=head1 DESCRIPTION + +I is a worker class for the Gearman distributed job system, +providing a framework for receiving and serving jobs from a Gearman server. + +Callers instantiate a I object, register a list of functions +and capabilities that they can handle, then enter an event loop, waiting +for the server to send jobs. + +The worker can send a return value back to the server, which then gets +sent back to the client that requested the job; or it can simply execute +silently. + +=head1 USAGE + +=head2 Gearman::Worker->new(\%options) + +Creates a new I object, and returns the object. + +If I<%options> is provided, initializes the new worker object with the +settings in I<%options>, which can contain: + +=over 4 + +=item * job_servers + +Calls I (see below) to initialize the list of job servers. + +=back + +=head2 $worker->job_servers(@servers) + +Initializes the worker I<$worker> with the list of job servers in I<@servers>. +I<@servers> should contain a list of IP addresses, with optional port numbers. +For example: + + $worker->job_servers('127.0.0.1', '192.168.1.100:7003'); + +If the port number is not provided, 7003 is used as the default. + +=head2 $worker->register_function($funcname, $subref) + +Registers the function I<$funcname> as being provided by the worker +I<$worker>, and advertises these capabilities to all of the job servers +defined in this worker. + +I<$subref> must be a subroutine reference that will be invoked when the +worker receives a request for this function. It will be passed a +I object representing the job that has been received by the +worker. + +The subroutine reference can return a return value, which will be sent back +to the job server. + +=head2 Gearman::Job->arg + +Returns the scalar argument that the client sent to the job server. + +=head2 Gearman::Job->set_status($numerator, $denominator) + +Updates the status of the job (most likely, a long-running job) and sends +it back to the job server. I<$numerator> and I<$denominator> should +represent the percentage completion of the job. + +=head1 EXAMPLES + +=head2 Summation + +This is an example worker that receives a request to sum up a list of +integers. + + use Gearman::Worker; + use Storable qw( thaw ); + use List::Util qw( sum ); + my $worker = Gearman::Worker->new; + $worker->job_servers('127.0.0.1'); + $worker->register_function(sum => sub { sum @{ thaw($_[0]->arg) } }); + $worker->work while 1; + +See the I documentation for a sample client sending the +I job. + +=cut diff --git a/wcmtools/gearman/server/gearmand b/wcmtools/gearman/server/gearmand new file mode 100755 index 0000000..af3eb39 --- /dev/null +++ b/wcmtools/gearman/server/gearmand @@ -0,0 +1,694 @@ +#!/usr/bin/perl +# +# Gearman +# +# Status: 2005-04-13 +# +# Copyright 2005, Danga Interactive +# +# Authors: +# Brad Fitzpatrick +# Brad Whitaker +# +# License: +# terms of Perl itself. +# + +use strict; +use Getopt::Long; +use Carp; +use Danga::Socket; +use IO::Socket::INET; +use POSIX (); +use lib '../lib'; +use Gearman::Util; + +use vars qw($DEBUG); +$DEBUG = 0; + +my ( + $daemonize, + $nokeepalive, + ); +my $conf_port = 7003; + +Getopt::Long::GetOptions( + 'd|daemon' => \$daemonize, + 'p|port=i' => \$conf_port, + 'debug=i' => \$DEBUG, + ); + +daemonize() if $daemonize; + +use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET); + +$SIG{'PIPE'} = "IGNORE"; # handled manually + +# establish SERVER socket, bind and listen. +my $server = IO::Socket::INET->new(LocalPort => $conf_port, + Type => SOCK_STREAM, + Proto => IPPROTO_TCP, + Blocking => 0, + Reuse => 1, + Listen => 10 ) + or die "Error creating socket: $@\n"; + +# Not sure if I'm crazy or not, but I can't see in strace where/how +# Perl 5.6 sets blocking to 0 without this. In Perl 5.8, IO::Socket::INET +# obviously sets it from watching strace. +IO::Handle::blocking($server, 0); + +my $accept_handler = sub { + my $csock = $server->accept(); + return unless $csock; + + printf("Listen child making a Client for %d.\n", fileno($csock)) + if $DEBUG; + + IO::Handle::blocking($csock, 0); + setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack("l", 1)) or die; + + my $client = Client->new($csock); + $client->watch_read(1); +}; + +Client->OtherFds(fileno($server) => $accept_handler); + +sub daemonize { + my($pid, $sess_id, $i); + + ## Fork and exit parent + if ($pid = fork) { exit 0; } + + ## Detach ourselves from the terminal + croak "Cannot detach from controlling terminal" + unless $sess_id = POSIX::setsid(); + + ## Prevent possibility of acquiring a controling terminal + $SIG{'HUP'} = 'IGNORE'; + if ($pid = fork) { exit 0; } + + ## Change working directory + chdir "/"; + + ## Clear file creation mask + umask 0; + + ## Close open file descriptors + close(STDIN); + close(STDOUT); + close(STDERR); + + ## Reopen stderr, stdout, stdin to /dev/null + open(STDIN, "+>/dev/null"); + open(STDOUT, "+>&STDIN"); + open(STDERR, "+>&STDIN"); +} + +##################################################################### +### Job definition +package Job; +use Sys::Hostname; + +use fields ( + 'func', + 'uniq', + 'argref', + 'listeners', # arrayref of interested Clients + 'worker', + 'handle', + 'status', # [1, 100] + 'require_listener', + ); + +our $handle_ct = 0; +our $handle_base = "H:" . hostname() . ":"; + +our %job_queue; # job_name -> [Job, Job*] (key only exists if non-empty) +our %jobOfHandle; # handle -> Job +our %jobOfUniq; # func -> uniq -> Job + +##################################################################### +### Client definition +package Client; + +use Danga::Socket; +use base 'Danga::Socket'; +use fields ( + 'can_do', # { $job_name => 1 } + 'can_do_list', + 'can_do_iter', + 'read_buf', + 'sleeping', # 0/1: they've said they're sleeping and we haven't woken them up + 'doing', # { $job_handle => Job } + 'client_id', # opaque string, no whitespace. workers give this so checker scripts + # can tell apart the same worker connected to multiple jobservers. + ); + + +##################################################################### +### J O B C L A S S +##################################################################### +package Job; + +sub new { + my Job $self = shift; + my ($func, $uniq, $argref, $highpri) = @_; + + $self = fields::new($self) unless ref $self; + + # if they specified a uniq, see if we have a dup job running already + # to merge with + if (length($uniq)) { + # a unique value of "-" means "use my args as my unique key" + $uniq = $$argref if $uniq eq "-"; + if ($jobOfUniq{$func} && $jobOfUniq{$func}{$uniq}) { + # found a match + return $jobOfUniq{$func}{$uniq}; + } else { + # create a new key + $jobOfUniq{$func} ||= {}; + $jobOfUniq{$func}{$uniq} = $self; + } + } + + $self->{'func'} = $func; + $self->{'uniq'} = $uniq; + $self->{'require_listener'} = 1; + $self->{'argref'} = $argref; + $self->{'listeners'} = []; + + $handle_ct++; + $self->{'handle'} = $handle_base . $handle_ct; + + my $jq = ($job_queue{$func} ||= []); + if ($highpri) { + unshift @$jq, $self; + } else { + push @$jq, $self; + } + + $jobOfHandle{$self->{'handle'}} = $self; + + return $self; +} + +sub Grab { + my ($class, $func) = @_; + return undef unless $job_queue{$func}; + + my $empty = sub { + delete $job_queue{$func}; + return undef; + }; + + my Job $job; + while (1) { + $job = shift @{$job_queue{$func}}; + return $empty->() unless $job; + return $job unless $job->{require_listener}; + + foreach my Client $c (@{$job->{listeners}}) { + return $job unless $c->{closed}; + } + $job->note_finished(0); + } +} + +sub GetByHandle { + my ($class, $handle) = @_; + return $jobOfHandle{$handle}; +} + +sub add_listener { + my Job $self = shift; + my Client $li = shift; + push @{$self->{listeners}}, $li; +} + +sub relay_to_listeners { + my Job $self = shift; + foreach my Client $c (@{$self->{listeners}}) { + next if $c->{closed}; + $c->write($_[0]); + } +} + +sub note_finished { + my Job $self = shift; + my $success = shift; + + if (length($self->{uniq})) { + delete $jobOfUniq{$self->{func}}{$self->{uniq}}; + } + delete $jobOfHandle{$self->{handle}}; +} + +# accessors: +sub worker { + my Job $self = shift; + return $self->{'worker'} unless @_; + return $self->{'worker'} = shift; +} +sub require_listener { + my Job $self = shift; + return $self->{'require_listener'} unless @_; + return $self->{'require_listener'} = shift; +} + +# takes arrayref of [numerator,denominator] +sub status { + my Job $self = shift; + return $self->{'status'} unless @_; + return $self->{'status'} = shift; +} + +sub handle { + my Job $self = shift; + return $self->{'handle'}; +} + +sub func { + my Job $self = shift; + return $self->{'func'}; +} + +sub argref { + my Job $self = shift; + return $self->{'argref'}; +} + + +##################################################################### +### C L I E N T C L A S S +##################################################################### +package Client; + +our %sleepers; # func -> [ sleepers ] (wiped on wakeup) + +our %client_map; # fd -> Client object + +# Class Method: +sub new { + my Client $self = shift; + $self = fields::new($self) unless ref $self; + $self->SUPER::new( @_ ); + + $self->{read_buf} = ''; + $self->{sleeping} = 0; + $self->{can_do} = {}; + $self->{doing} = {}; # handle -> Job + $self->{can_do_list} = []; + $self->{can_do_iter} = 0; # numeric iterator for where we start looking for jobs + $self->{client_id} = "-"; + + $client_map{$self->{fd}} = $self; + + return $self; +} + +# Class Method: +sub WakeUpSleepers { + my ($class, $func) = @_; + return unless $sleepers{$func}; + my Client $c; + foreach $c (@{$sleepers{$func}}) { + next if $c->{closed} || ! $c->{sleeping}; + $c->res_packet("noop"); + $c->{sleeping} = 0; + } + delete $sleepers{$func}; + return; +} + + +sub close { + my Client $self = shift; + + while (my ($handle, $job) = each %{$self->{doing}}) { + my $msg = Gearman::Util::pack_res_command("work_fail", $handle); + $job->relay_to_listeners($msg); + $job->note_finished(0); + } + + delete $client_map{$self->{fd}}; + $self->CMD_reset_abilities; + + $self->SUPER::close; +} + +# Client +sub event_read { + my Client $self = shift; + + my $bref = $self->read(1024); + return $self->close unless defined $bref; + $self->{read_buf} .= $$bref; + + my $found_cmd; + do { + $found_cmd = 1; + my $blen = length($self->{read_buf}); + + if ($self->{read_buf} =~ /^\0REQ(.{8,8})/s) { + my ($cmd, $len) = unpack("NN", $1); + if ($blen < $len + 12) { + # not here yet. + $found_cmd = 0; + return; + } + + $self->process_cmd($cmd, substr($self->{read_buf}, 12, $len)); + + # and slide down buf: + $self->{read_buf} = substr($self->{read_buf}, 12+$len); + + } elsif ($self->{read_buf} =~ s/^(\w.+?)?\r?\n//) { + # ASCII command case (useful for telnetting in) + my $line = $1; + $self->process_line($line); + } else { + $found_cmd = 0; + } + } while ($found_cmd); +} + +# line-based commands +sub process_line { + my Client $self = shift; + my $line = shift; + + if ($line =~ /^(\w+)\s*(.*)/) { + my ($cmd, $args) = ($1, $2); + $cmd = lc($cmd); + + no strict 'refs'; + my $cmd_handler = *{"TXTCMD_$cmd"}{CODE}; + if ($cmd_handler) { + my $args = decode_url_args(\$args); + $cmd_handler->($self, $args); + next; + } + } + + return $self->err_line('unknown_command'); +} + +sub TXTCMD_workers { + my Client $self = shift; + my $args = shift; + + foreach my $fd (sort { $a <=> $b } keys %client_map) { + my Client $cl = $client_map{$fd}; + $self->write("$fd " . $cl->peer_ip_string . " $cl->{client_id} : @{$cl->{can_do_list}}\n"); + + } + $self->write(".\n"); +} + +sub CMD_echo_req { + my Client $self = shift; + my $blobref = shift; + + return $self->res_packet("echo_res", $$blobref); +} + +sub CMD_work_status { + my Client $self = shift; + my $ar = shift; + my ($handle, $nu, $de) = split(/\0/, $$ar); + + my $job = $self->{doing}{$handle}; + return $self->error_packet("not_worker") unless $job && $job->worker == $self; + + my $msg = Gearman::Util::pack_res_command("work_status", $$ar); + $job->relay_to_listeners($msg); + $job->status([$nu, $de]); + return 1; +} + +sub CMD_work_complete { + my Client $self = shift; + my $ar = shift; + + $$ar =~ s/^(.+?)\0//; + my $handle = $1; + + my $job = delete $self->{doing}{$handle}; + return $self->error_packet("not_worker") unless $job && $job->worker == $self; + + my $msg = Gearman::Util::pack_res_command("work_complete", join("\0", $handle, $$ar)); + $job->relay_to_listeners($msg); + $job->note_finished(1); + + return 1; +} + +sub CMD_work_fail { + my Client $self = shift; + my $ar = shift; + my $handle = $$ar; + my $job = delete $self->{doing}{$handle}; + return $self->error_packet("not_worker") unless $job && $job->worker == $self; + + my $msg = Gearman::Util::pack_res_command("work_fail", $handle); + $job->relay_to_listeners($msg); + $job->note_finished(1); + return 1; +} + +sub CMD_pre_sleep { + my Client $self = shift; + $self->{'sleeping'} = 1; + + foreach my $cd (@{$self->{can_do_list}}) { + + # immediately wake the sleeper up if there are things to be done + if ($job_queue{$cd}) { + $self->res_packet("noop"); + $self->{sleeping} = 0; + return; + } + + push @{$sleepers{$cd} ||= []}, $self; + } + return 1; +} + +sub CMD_grab_job { + my Client $self = shift; + + my $job; + my $can_do_size = scalar @{$self->{can_do_list}}; + + unless ($can_do_size) { + $self->res_packet("no_job"); + return; + } + + # the offset where we start asking for jobs, to prevent starvation + # of some job types. + $self->{can_do_iter} = ($self->{can_do_iter} + 1) % $can_do_size; + + my $tried = 0; + while ($tried < $can_do_size) { + my $idx = ($tried + $self->{can_do_iter}) % $can_do_size; + $tried++; + my $job_to_grab = $self->{can_do_list}->[$idx]; + $job = Job->Grab($job_to_grab); + if ($job) { + $job->worker($self); + $self->{doing}{$job->handle} = $job; + return $self->res_packet("job_assign", + join("\0", + $job->handle, + $job->func, + ${$job->argref}, + )); + } + } + + $self->res_packet("no_job"); +} + +sub CMD_can_do { + my Client $self = shift; + my $ar = shift; + + $self->{can_do}->{$$ar} = 1; + $self->_setup_can_do_list; +} + +sub CMD_set_client_id { + my Client $self = shift; + my $ar = shift; + + $self->{client_id} = $$ar; + $self->{client_id} =~ s/\s+//g; + $self->{client_id} = "-" unless length $self->{client_id}; +} + +sub CMD_cant_do { + my Client $self = shift; + my $ar = shift; + + delete $self->{can_do}->{$$ar}; + $self->_setup_can_do_list; +} + +sub CMD_get_status { + my Client $self = shift; + my $ar = shift; + my $job = Job->GetByHandle($$ar); + + # handles can't contain nulls + return if $$ar =~ /\0/; + + my ($known, $running, $num, $den); + $known = 0; + $running = 0; + if ($job) { + $known = 1; + $running = $job->worker ? 1 : 0; + if (my $stat = $job->status) { + ($num, $den) = @$stat; + } + } + + $self->res_packet("status_res", join("\0", + $$ar, + $known, + $running, + $num, + $den)); +} + +sub CMD_reset_abilities { + my Client $self = shift; + + $self->{can_do} = {}; + $self->_setup_can_do_list; +} + +sub _setup_can_do_list { + my Client $self = shift; + $self->{can_do_list} = [ keys %{$self->{can_do}} ]; + $self->{can_do_iter} = 0; +} + +sub CMD_submit_job { push @_, 1; &_cmd_submit_job; } +sub CMD_submit_job_bg { push @_, 0; &_cmd_submit_job; } +sub CMD_submit_job_high { push @_, 1, 1; &_cmd_submit_job; } + +sub _cmd_submit_job { + my Client $self = shift; + my $ar = shift; + my $subscribe = shift; + my $high_pri = shift; + + return $self->error_packet("invalid_args", "No func/uniq header [$$ar].") + unless $$ar =~ s/^(.+?)\0(.*?)\0//; + + my ($func, $uniq) = ($1, $2); + + my $job = Job->new($func, $uniq, $ar, $high_pri); + + if ($subscribe) { + $job->add_listener($self); + } else { + # background mode + $job->require_listener(0); + } + + $self->res_packet("job_created", $job->handle); + Client->WakeUpSleepers($func); +} + +sub res_packet { + my Client $self = shift; + my ($code, $arg) = @_; + $self->write(Gearman::Util::pack_res_command($code, $arg)); + return 1; +} + +sub error_packet { + my Client $self = shift; + my ($code, $msg) = @_; + $self->write(Gearman::Util::pack_res_command("error", "$code\0$msg")); + return 0; +} + +sub process_cmd { + my Client $self = shift; + my $cmd = shift; + my $blob = shift; + + my $cmd_name = "CMD_" . Gearman::Util::cmd_name($cmd); + my $ret = eval { + $self->$cmd_name(\$blob); + }; + return $ret unless $@; + print "Error: $@\n"; + return $self->error_packet("server_error", $@); +} + +# Client +sub event_err { my $self = shift; $self->close; } +sub event_hup { my $self = shift; $self->close; } + +sub err_line { + my Client $self = shift; + my $err_code = shift; + my $err_text = { + 'unknown_command' => "Unknown server command", + }->{$err_code}; + + $self->write("ERR $err_code " . eurl($err_text) . "\r\n"); + return 0; +} + +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\,\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +sub decode_url_args +{ + my $a = shift; + my $buffer = ref $a ? $a : \$a; + my $ret = {}; + + my $pair; + my @pairs = split(/&/, $$buffer); + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $ret->{$name} .= $ret->{$name} ? "\0$value" : $value; + } + return $ret; +} + +package main; +Client->EventLoop(); + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/gearman/t/00-use.t b/wcmtools/gearman/t/00-use.t new file mode 100755 index 0000000..0fc9640 --- /dev/null +++ b/wcmtools/gearman/t/00-use.t @@ -0,0 +1,6 @@ +use strict; +use Test::More tests => 3; + +use_ok('Gearman::Util'); +use_ok('Gearman::Worker'); +use_ok('Gearman::Client'); diff --git a/wcmtools/gearman/t/10-all.t b/wcmtools/gearman/t/10-all.t new file mode 100755 index 0000000..c1ca2ac --- /dev/null +++ b/wcmtools/gearman/t/10-all.t @@ -0,0 +1,198 @@ +use strict; +our $Bin; +use FindBin qw( $Bin ); +use File::Spec; +use Gearman::Client; +use Storable qw( freeze ); +use Test::More tests => 20; +use IO::Socket::INET; +use POSIX qw( :sys_wait_h ); + +use constant PORT => 9000; +our %Children; + +END { kill_children() } + +start_server(PORT); +start_server(PORT + 1); + +## Sleep, wait for servers to start up before connecting workers. +wait_for_port(PORT); +wait_for_port(PORT + 1); + +## Look for 2 job servers, starting at port number PORT. +start_worker(PORT, 2); +start_worker(PORT, 2); + +my $client = Gearman::Client->new; +isa_ok($client, 'Gearman::Client'); +$client->job_servers('127.0.0.1:' . PORT, '127.0.0.1:' . (PORT + 1)); + +eval { $client->do_task(sum => []) }; +like($@, qr/scalar or scalarref/, 'do_task does not accept arrayref argument'); + +my $out = $client->do_task(sum => freeze([ 3, 5 ])); +is($$out, 8, 'do_task returned 8 for sum'); + +my $tasks = $client->new_task_set; +isa_ok($tasks, 'Gearman::Taskset'); +my $sum; +my $failed = 0; +my $completed = 0; +my $handle = $tasks->add_task(sum => freeze([ 3, 5 ]), { + on_complete => sub { $sum = ${ $_[0] } }, + on_fail => sub { $failed = 1 } +}); +$tasks->wait; +is($sum, 8, 'add_task/wait returned 8 for sum'); +is($failed, 0, 'on_fail not called on a successful result'); + +## Now try a task set with 2 tasks, and make sure they are both completed. +$tasks = $client->new_task_set; +my @sums; +$tasks->add_task(sum => freeze([ 1, 1 ]), { + on_complete => sub { $sums[0] = ${ $_[0] } }, +}); +$tasks->add_task(sum => freeze([ 2, 2 ]), { + on_complete => sub { $sums[1] = ${ $_[0] } }, +}); +$tasks->wait; +is($sums[0], 2, 'First task completed (sum is 2)'); +is($sums[1], 4, 'Second task completed (sum is 4)'); + +## Test some failure conditions: +## Normal failure (worker returns undef or dies within eval). +is($client->do_task('fail'), undef, 'Job that failed naturally returned undef'); +## Worker process exits. +is($client->do_task('fail_exit'), undef, + 'Job that failed via exit returned undef'); +pid_is_dead(wait()); + +## Worker process times out (takes longer than fail_after_idle seconds). +TODO: { + todo_skip 'fail_after_idle is not yet implemented', 1; + is($client->do_task('sleep', 5, { fail_after_idle => 3 }), undef, + 'Job that timed out after 3 seconds returns failure (fail_after_idle)'); +} + +## Test retry_count. +my $retried = 0; +is($client->do_task('fail' => '', { + on_retry => sub { $retried++ }, + retry_count => 3, +}), undef, 'Failure response is still failure, even after retrying'); +is($retried, 3, 'Retried 3 times'); + +my $tasks = $client->new_task_set; +$completed = 0; +$failed = 0; +$tasks->add_task(fail => '', { + on_complete => sub { $completed = 1 }, + on_fail => sub { $failed = 1 }, +}); +$tasks->wait; +is($completed, 0, 'on_complete not called on failed result'); +is($failed, 1, 'on_fail called on failed result'); + +## Test high_priority. +## Create a taskset with 4 tasks, and have the 3rd fail. +## In on_fail, add a new task with high priority set, and make sure it +## gets executed before task 4. To make this reliable, we need to first +## kill off all but one of the worker processes. +my @worker_pids = grep $Children{$_} eq 'W', keys %Children; +kill INT => @worker_pids[1..$#worker_pids]; +$tasks = $client->new_task_set; +$out = ''; +$tasks->add_task(echo_ws => 1, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->add_task(echo_ws => 2, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->add_task(echo_ws => 'x', { + on_fail => sub { + $tasks->add_task(echo_ws => 'p', { + on_complete => sub { $out .= ${ $_[0] } }, + high_priority => 1 + }); + }, +}); +$tasks->add_task(echo_ws => 3, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->add_task(echo_ws => 4, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->add_task(echo_ws => 5, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->add_task(echo_ws => 6, { on_complete => sub { $out .= ${ $_[0] } } }); +$tasks->wait; +like($out, qr/p.+6/, 'High priority tasks executed in priority order.'); +## We just killed off all but one worker--make sure they get respawned. +respawn_children(); + +## Test dispatch_background and get_status. +my $out; +my $handle = $client->dispatch_background(long => undef, { + on_complete => sub { $out = ${ $_[0] } }, +}); +ok($handle, 'Got a handle back from dispatching background job'); +my $status = $client->get_status($handle); +isa_ok($status, 'Gearman::JobStatus'); +ok($status->running, 'Job is still running'); +is($status->percent, .5, 'Job is 50 percent complete'); +do { + sleep 1; + $status = $client->get_status($handle); +} until $status->percent == 1; + +sub pid_is_dead { + my($pid) = @_; + return if $pid == -1; + my $type = delete $Children{$pid}; + if ($type eq 'W') { + ## Right now we can only restart workers. + start_worker(PORT, 2); + } +} + +sub respawn_children { + for my $pid (keys %Children) { + if (waitpid($pid, WNOHANG) > 0) { + pid_is_dead($pid); + } + } +} + +sub start_server { + my($port) = @_; + my $server = File::Spec->catfile($Bin, '..', 'server', 'gearmand'); + my $pid = start_child([ $server, '-p', $port ]); + $Children{$pid} = 'S'; +} + +sub start_worker { + my($port, $num) = @_; + my $worker = File::Spec->catfile($Bin, 'worker.pl'); + my $servers = join ',', + map '127.0.0.1:' . (PORT + $_), + 0..$num-1; + my $pid = start_child([ $worker, '-s', $servers ]); + $Children{$pid} = 'W'; +} + +sub start_child { + my($cmd) = @_; + my $pid = fork(); + die $! unless defined $pid; + unless ($pid) { + exec 'perl', '-Iblib/lib', '-Ilib', @$cmd or die $!; + } + $pid; +} + +sub kill_children { + kill INT => keys %Children; +} + +sub wait_for_port { + my($port) = @_; + my $start = time; + while (1) { + my $sock = IO::Socket::INET->new(PeerAddr => "127.0.0.1:$port"); + return 1 if $sock; + select undef, undef, undef, 0.25; + die "Timeout waiting for port $port to startup" if time > $start + 5; + } +} diff --git a/wcmtools/gearman/t/worker.pl b/wcmtools/gearman/t/worker.pl new file mode 100755 index 0000000..82071ac --- /dev/null +++ b/wcmtools/gearman/t/worker.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl -w +use strict; + +use Gearman::Worker; +use Storable qw( thaw ); +use Getopt::Long qw( GetOptions ); + +GetOptions( + 's|servers=s', \my($servers), +); +die "usage: $0 -s " unless $servers; +my @servers = split /,/, $servers; + +my $worker = Gearman::Worker->new; +$worker->job_servers(@servers); + +$worker->register_function(sum => sub { + my $sum = 0; + $sum += $_ for @{ thaw($_[0]->arg) }; + $sum; +}); + +$worker->register_function(fail => sub { undef }); +$worker->register_function(fail_exit => sub { exit 255 }); + +$worker->register_function(sleep => sub { sleep $_[0]->arg }); + +$worker->register_function(echo_ws => sub { + select undef, undef, undef, 0.25; + $_[0]->arg eq 'x' ? undef : $_[0]->arg; +}); + +$worker->register_function(long => sub { + my($job) = @_; + $job->set_status(50, 100); + sleep 2; + $job->set_status(100, 100); + sleep 2; +}); + +$worker->work while 1; diff --git a/wcmtools/lib/Apache/CompressClientFixup.pm b/wcmtools/lib/Apache/CompressClientFixup.pm new file mode 100755 index 0000000..9eb2428 --- /dev/null +++ b/wcmtools/lib/Apache/CompressClientFixup.pm @@ -0,0 +1,55 @@ +# modified from: +# http://devl4.outlook.net/devdoc/Dynagzip/ContentCompressionClients.html + +package Apache::CompressClientFixup; + +use 5.004; +use strict; +use Apache::Constants qw(OK DECLINED); +use Apache::Log(); +use Apache::URI(); + +use vars qw($VERSION); +$VERSION = "0.01"; + +sub handler { + my $r = shift; + return DECLINED unless $r->header_in('Accept-Encoding') =~ /gzip/io; + + my $no_gzip = sub { + $r->headers_in->unset('Accept-Encoding'); + return OK; + }; + + my $ua = $r->header_in('User-Agent'); + + if ($r->protocol =~ /http\/1\.0/io) { + # it is not supposed to be compressed: + # (but if request comes via mod_proxy, it'll be 1.1 regardless of what it actually was) + return $no_gzip->(); + } + if ($ua =~ /MSIE 4\./o) { + return $no_gzip->() if + $r->method =~ /POST/io || + $r->header_in('Range') || + length($r->uri) > 245; + } + if ($ua =~ /MSIE 6\.0/o) { + return $no_gzip->() if $r->parsed_uri->scheme =~ /https/io; + } + + if ($r->header_in('Via') =~ /^1\.1\s/o || # MS Proxy 2.0 + $r->header_in('Via') =~ /^Squid\//o || + $ua =~ /Galeon\)/o || + $ua =~ /Mozilla\/4\.7[89]/o || + $ua =~ /Opera 3\.5/o || + $ua =~ /SkipStone\)/o) { + return $no_gzip->(); + } + + if (($ua =~ /Mozilla\/4\.0/o) and (!($ua =~ /compatible/io))) { + return $no_gzip->(); + } +} + +1; diff --git a/wcmtools/lib/DBI/Role.pm b/wcmtools/lib/DBI/Role.pm new file mode 100755 index 0000000..c7f76fd --- /dev/null +++ b/wcmtools/lib/DBI/Role.pm @@ -0,0 +1,392 @@ +package DBI::Role; + +use 5.006; +use strict; +use warnings; +BEGIN { + $DBI::Role::HAVE_HIRES = eval "use Time::HiRes (); 1;"; +} + +our $VERSION = '1.00'; + +# $self contains: +# +# DBINFO --- hashref. keys = scalar roles, one of which must be 'master'. +# values contain DSN info, and 'role' => { 'role' => weight, 'role2' => weight } +# +# DEFAULT_DB -- scalar string. default db name if none in DSN hashref in DBINFO +# +# DBREQCACHE -- cleared by clear_req_cache() on each request. +# fdsn -> dbh +# +# DBCACHE -- role -> fdsn, or +# fdsn -> dbh +# +# DBCACHE_UNTIL -- role -> unixtime +# +# DB_USED_AT -- fdsn -> unixtime +# +# DB_DEAD_UNTIL -- fdsn -> unixtime +# +# TIME_CHECK -- if true, time between localhost and db are checked every TIME_CHECK +# seconds +# +# TIME_REPORT -- coderef to pass dsn and dbtime to after a TIME_CHECK occurence + +sub new +{ + my ($class, $args) = @_; + my $self = {}; + $self->{'DBINFO'} = $args->{'sources'}; + $self->{'TIMEOUT'} = $args->{'timeout'}; + $self->{'DEFAULT_DB'} = $args->{'default_db'}; + $self->{'TIME_CHECK'} = $args->{'time_check'}; + $self->{'TIME_LASTCHECK'} = {}; # dsn -> last check time + $self->{'TIME_REPORT'} = $args->{'time_report'}; + bless $self, ref $class || $class; + return $self; +} + +sub set_sources +{ + my ($self, $newval) = @_; + $self->{'DBINFO'} = $newval; + $self; +} + +sub clear_req_cache +{ + my $self = shift; + $self->{'DBREQCACHE'} = {}; +} + +sub disconnect_all +{ + my ($self, $opts) = @_; + my %except; + + if ($opts && $opts->{except} && + ref $opts->{except} eq 'ARRAY') { + $except{$_} = 1 foreach @{$opts->{except}}; + } + + foreach my $cache (qw(DBREQCACHE DBCACHE)) { + next unless ref $self->{$cache} eq "HASH"; + foreach my $key (keys %{$self->{$cache}}) { + next if $except{$key}; + my $v = $self->{$cache}->{$key}; + next unless ref $v eq "DBI::db"; + $v->disconnect; + delete $self->{$cache}->{$key}; + } + } + $self->{'DBCACHE'} = {}; + $self->{'DBREQCACHE'} = {}; +} + +sub same_cached_handle +{ + my $self = shift; + my ($role_a, $role_b) = @_; + return + defined $self->{'DBCACHE'}->{$role_a} && + defined $self->{'DBCACHE'}->{$role_b} && + $self->{'DBCACHE'}->{$role_a} eq $self->{'DBCACHE'}->{$role_b}; +} + +sub flush_cache +{ + my $self = shift; + foreach (keys %{$self->{'DBCACHE'}}) { + my $v = $self->{'DBCACHE'}->{$_}; + next unless ref $v; + $v->disconnect; + } + $self->{'DBCACHE'} = {}; + $self->{'DBREQCACHE'} = {}; +} + +# old interface. does nothing now. +sub trigger_weight_reload +{ + my $self = shift; + return $self; +} + +sub use_diff_db +{ + my $self = shift; + my ($role1, $role2) = @_; + + return 0 if $role1 eq $role2; + + # this is implied: (makes logic below more readable by forcing it) + $self->{'DBINFO'}->{'master'}->{'role'}->{'master'} = 1; + + foreach (keys %{$self->{'DBINFO'}}) { + next if /^_/; + next unless ref $self->{'DBINFO'}->{$_} eq "HASH"; + if ($self->{'DBINFO'}->{$_}->{'role'}->{$role1} && + $self->{'DBINFO'}->{$_}->{'role'}->{$role2}) { + return 0; + } + } + return 1; +} + +sub get_dbh +{ + my $self = shift; + my $opts = ref $_[0] eq "HASH" ? shift : {}; + + my @roles = @_; + my $role = shift @roles; + return undef unless $role; + + my $now = time(); + + # if 'nocache' flag is passed, clear caches now so we won't return + # a cached database handle later + $self->clear_req_cache if $opts->{'nocache'}; + + # otherwise, see if we have a role -> full DSN mapping already + my ($fdsn, $dbh); + if ($role eq "master") { + $fdsn = make_dbh_fdsn($self, $self->{'DBINFO'}->{'master'}); + } else { + if ($self->{'DBCACHE'}->{$role} && ! $opts->{'unshared'}) { + $fdsn = $self->{'DBCACHE'}->{$role}; + if ($now > $self->{'DBCACHE_UNTIL'}->{$role}) { + # this role -> DSN mapping is too old. invalidate, + # and while we're at it, clean up any connections we have + # that are too idle. + undef $fdsn; + + foreach (keys %{$self->{'DB_USED_AT'}}) { + next if $self->{'DB_USED_AT'}->{$_} > $now - 60; + delete $self->{'DB_USED_AT'}->{$_}; + delete $self->{'DBCACHE'}->{$_}; + } + } + } + } + + if ($fdsn) { + $dbh = get_dbh_conn($self, $fdsn, $role); + return $dbh if $dbh; + delete $self->{'DBCACHE'}->{$role}; # guess it was bogus + } + return undef if $role eq "master"; # no hope now + + # time to randomly weightedly select one. + my @applicable; + my $total_weight; + foreach (keys %{$self->{'DBINFO'}}) { + next if /^_/; + next unless ref $self->{'DBINFO'}->{$_} eq "HASH"; + my $weight = $self->{'DBINFO'}->{$_}->{'role'}->{$role}; + next unless $weight; + push @applicable, [ $self->{'DBINFO'}->{$_}, $weight ]; + $total_weight += $weight; + } + + while (@applicable) { + my $rand = rand($total_weight); + my ($i, $t) = (0, 0); + for (; $i<@applicable; $i++) { + $t += $applicable[$i]->[1]; + last if $t > $rand; + } + my $fdsn = make_dbh_fdsn($self, $applicable[$i]->[0]); + $dbh = get_dbh_conn($self, $opts, $fdsn); + if ($dbh) { + $self->{'DBCACHE'}->{$role} = $fdsn; + $self->{'DBCACHE_UNTIL'}->{$role} = $now + 5 + int(rand(10)); + return $dbh; + } + + # otherwise, discard that one. + $total_weight -= $applicable[$i]->[1]; + splice(@applicable, $i, 1); + } + + # try others + return get_dbh($self, $opts, @roles); +} + +sub make_dbh_fdsn +{ + my $self = shift; + my $db = shift; # hashref with DSN info + return $db->{'_fdsn'} if $db->{'_fdsn'}; # already made? + + my $fdsn = "DBI:mysql"; # join("|",$dsn,$user,$pass) (because no refs as hash keys) + $db->{'dbname'} ||= $self->{'DEFAULT_DB'} if $self->{'DEFAULT_DB'}; + $fdsn .= ":$db->{'dbname'}"; + $fdsn .= ";host=$db->{'host'}" if $db->{'host'}; + $fdsn .= ";port=$db->{'port'}" if $db->{'port'}; + $fdsn .= ";mysql_socket=$db->{'sock'}" if $db->{'sock'}; + $fdsn .= "|$db->{'user'}|$db->{'pass'}"; + + $db->{'_fdsn'} = $fdsn; + return $fdsn; +} + +sub get_dbh_conn +{ + my $self = shift; + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $fdsn = shift; + my $role = shift; # optional. + my $now = time(); + + my $retdb = sub { + my $db = shift; + $self->{'DBREQCACHE'}->{$fdsn} = $db; + $self->{'DB_USED_AT'}->{$fdsn} = $now; + return $db; + }; + + # have we already created or verified a handle this request for this DSN? + return $retdb->($self->{'DBREQCACHE'}->{$fdsn}) + if $self->{'DBREQCACHE'}->{$fdsn} && ! $opts->{'unshared'}; + + # check to see if we recently tried to connect to that dead server + return undef if $self->{'DB_DEAD_UNTIL'}->{$fdsn} && $now < $self->{'DB_DEAD_UNTIL'}->{$fdsn}; + + # if not, we'll try to find one we used sometime in this process lifetime + my $dbh = $self->{'DBCACHE'}->{$fdsn}; + + # if it exists, verify it's still alive and return it. (but not + # if we're wanting an unshared connection) + if ($dbh && ! $opts->{'unshared'}) { + return $retdb->($dbh) unless connection_bad($dbh, $opts); + undef $dbh; + undef $self->{'DBCACHE'}->{$fdsn}; + } + + # time to make one! + my ($dsn, $user, $pass) = split(/\|/, $fdsn); + my $timeout = $self->{'TIMEOUT'} || 2; + $dsn .= ";mysql_connect_timeout=$timeout"; + + my $loop = 1; + my $tries = $DBI::Role::HAVE_HIRES ? 8 : 2; + while ($loop) { + $loop = 0; + $dbh = DBI->connect($dsn, $user, $pass, { + PrintError => 0, + AutoCommit => 1, + }); + + # if max connections, try again shortly. + if (! $dbh && $DBI::err == 1040 && $tries) { + $tries--; + $loop = 1; + if ($DBI::Role::HAVE_HIRES) { + Time::HiRes::usleep(250_000); + } else { + sleep 1; + } + } + } + + my $DBI_err = $DBI::err || 0; + + # check replication/busy processes... see if we should not use + # this one + undef $dbh if connection_bad($dbh, $opts); + + # if this is an unshared connection, we don't want to put it + # in the cache for somebody else to use later. (which happens below) + return $dbh if $opts->{'unshared'}; + + # mark server as dead if dead. won't try to reconnect again for 5 seconds. + if ($dbh) { + $self->{'DB_USED_AT'}->{$fdsn} = $now; + + if ($self->{'TIME_CHECK'} && ref $self->{'TIME_REPORT'} eq "CODE") { + my $now = time(); + $self->{'TIME_LASTCHECK'}->{$dsn} ||= 0; # avoid warnings + if ($self->{'TIME_LASTCHECK'}->{$dsn} < $now - $self->{'TIME_CHECK'}) { + $self->{'TIME_LASTCHECK'}->{$dsn} = $now; + my $db_time = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()"); + $self->{'TIME_REPORT'}->($dsn, $db_time, $now); + } + } + } else { + # mark the database as dead for a bit, unless it was just because of max connections + $self->{'DB_DEAD_UNTIL'}->{$fdsn} = $now + 5 + unless $DBI_err == 1040; + } + + return $self->{'DBREQCACHE'}->{$fdsn} = $self->{'DBCACHE'}->{$fdsn} = $dbh; +} + +sub connection_bad { + my ($dbh, $opts) = @_; + + return 1 unless $dbh; + + my $ss = eval { + $dbh->selectrow_hashref("SHOW SLAVE STATUS"); + }; + + # if there was an error, and it wasn't a permission problem (1227) + # then treat this connection as bogus + if ($dbh->err && $dbh->err != 1227) { + return 1; + } + + # connection is good if $ss is undef (not a slave) + return 0 unless $ss; + + # otherwise, it's okay if not MySQL 4 + return 0 if ! $ss->{'Master_Log_File'} || ! $ss->{'Relay_Master_Log_File'}; + + # all good if within 100 k + if ($opts->{'max_repl_lag'}) { + return 0 if + $ss->{'Master_Log_File'} eq $ss->{'Relay_Master_Log_File'} && + ($ss->{'Read_Master_Log_Pos'} - $ss->{'Exec_master_log_pos'}) < $opts->{'max_repl_lag'}; + + # guess we're behind + return 1; + } else { + # default to assuming it's good + return 0; + } +} + +1; +__END__ + +=head1 NAME + +DBI::Role - Get DBI cached handles by role, with weighting & failover. + +=head1 SYNOPSIS + + use DBI::Role; + my $DBIRole = new DBI::Role { + 'sources' => \%DBINFO, + 'default_db' => "somedbname", # opt. + }; + my $dbh = $DBIRole->get_dbh("master"); + +=head1 DESCRIPTION + +To be written. + +=head2 EXPORT + +None by default. + +=head1 AUTHOR + +Brad Fitzparick, Ebrad@danga.comE + +=head1 SEE ALSO + +L. + diff --git a/wcmtools/lib/DBIx/StateKeeper.pm b/wcmtools/lib/DBIx/StateKeeper.pm new file mode 100755 index 0000000..b87b3bd --- /dev/null +++ b/wcmtools/lib/DBIx/StateKeeper.pm @@ -0,0 +1,252 @@ +# A StateTracker has a real DBI $dbh handle, and knows +# what the active database is (for use with MySQL) +# +# A StateKeeper (below) mimics the $dbh interface (so it +# can be used transparently instead of a real $dbh) and +# has a StateTracker and knows what database it wants to +# use. If the StateKeeper is ever invoked (->do(), ->prepare(), +# or whatever $dbh can do), then it checks its Tracker and +# changes the Tracker's database if it doesn't match. +# +# The point is to connect to a host that has multiple +# databases, but only use one connection, and make the +# client code oblivious to the fact one connection is +# being shared and there are multiple databases. +# +# Backing up, the point is to get more concurrency out +# out the ultra-fast MyISAM table handler by separating +# users onto separate databases on the same machine +# and across different replication clusters. We could use +# InnoDB, which is highly concurrent, but it's pretty slow. +# Besides, we hardly ever hit the database with memcache. +# The common case for us at the moment is doing 1 or 2 +# simple queries on 10+ different databases, most of which +# are on the same couple hosts. It's a waste to use 10 +# db connections. The MySQL support people will say +# to just jack up max_connections, but we want to limit +# the max running threads (and their associated memory). +# We keep asking MySQL people for a distinction between +# threads and connections, but it's lower on their priority +# list. This is our temporary hack. +# +# UPDATE: Oct-16-2003, it was announced by a MySQL +# developer that MySQL 5.0 will have thread vs. connection +# context separation. See: +# http://krow.livejournal.com/247835.html +# +# Please, do not use this in other code unless you know +# what you're doing. +# +# -- Brad Fitzpatrick +# + +package DBIx::StateTracker; + +use strict; + +# if set externally, EXTRA_PARANOID will validate the +# current database before any query. slow, but useful +# to make sure nobody is messing with the StateTracker's +# beside itself. +use vars qw($EXTRA_PARANOID); + +our %dbs_tracked; # $dbh -> 1 (if being tracked) + +sub new { + my ($class, $dbh, $init_db) = @_; + return undef unless $dbh; + my $bless = ref $class || $class; + + my $maker; + if (ref $dbh eq "CODE") { + $maker = $dbh; + $dbh = undef; + } + + my $self = { + 'dbh' => $dbh, + 'database' => $init_db, + 'maker' => $maker, + }; + bless $self, $bless; + + $self->reconnect() unless $self->{dbh}; + + return $self; +} + +sub reconnect { + my $self = shift; + die "DBIx::StateTracker: no db connector code available\n" + unless ref $self->{maker} eq "CODE"; + + # in case there was an old handle + delete $dbs_tracked{$self->{dbh}}; + + my $dbh = $self->{maker}->(); + my $db; + die "DBIx::StateTracker: could not reconnect to database\n" + unless $dbh; + + $db = $dbh->selectrow_array("SELECT DATABASE()"); + die "DBIx::StateTracker: error checking current database: " . $dbh->errstr . "\n" + if $dbh->err; + + if ($dbs_tracked{$dbh}++) { + die "DBIx::StateTracker: database $dbh already being tracked. ". + "Can't have two active trackers."; + } + + $self->{dbh} = $dbh; + $self->{database} = $db; + return $self; +} + +sub disconnect { + my $self = shift; + delete $dbs_tracked{$self->{dbh}}; + $self->{dbh}->disconnect if $self->{dbh}; + undef $self->{dbh}; + undef $self->{database}; +} + +sub DESTROY { + my $self = shift; + delete $dbs_tracked{$self->{'dbh'}}; +} + +sub get_database { + my $self = shift; + return $self->{'database'}; +} + +sub set_database { + my ($self, $db, $second_try) = @_; # db = desired database + + if ($self->{database} ne $db) { + die "Invalid db name" if $db =~ /\W/; + my $rc = $self->{'dbh'}->do("USE $db"); + if (! $rc) { + return 0 if $second_try; + $self->reconnect(); + return $self->set_database($db, 1); + } + $self->{'database'} = $db; + } + + elsif ($EXTRA_PARANOID) { + my $actual = $self->{'dbh'}->selectrow_array("SELECT DATABASE()"); + if (! defined $actual) { + my $err = $self->{dbh}->err; + if (! $second_try && ($err == 2006 || $err == 2013)) { + # server gone away, or lost connection (timeout?) + $self->reconnect(); + return $self->set_database($db, 1); + } else { + $@ = "DBIx::StateTracker: error discovering current database: " . + $self->{dbh}->errstr; + return 0; + } + } elsif ($actual ne $db) { + $@ = "Aborting without db access. Somebody is messing with the DBIx::StateTracker ". + "dbh that's not us. Expecting database $db, but was actually $actual."; + return 0; + } + } + + return 1; +} + +sub do_method { + my ($self, $desired_db, $method, @args) = @_; + unless ($method eq "quote") { + die "DBIx::StateKeeper: unable to switch to database: $desired_db ($@)" unless + $self->set_database($desired_db); + } + + my $dbh = $self->{dbh}; + #print "wantarray: ", (wantarray() ? 1 : 0), "\n"; + return $dbh->$method(@args); +} + +sub get_attribute { + my ($self, $desired_db, $key) = @_; + die "DBIx::StateKeeper: unable to switch to database: $desired_db" unless + $self->set_database($desired_db); + + my $dbh = $self->{dbh}; + return $dbh->{$key}; +} + +sub set_attribute { + my ($self, $desired_db, $key, $val) = @_; + die "DBIx::StateKeeper: unable to switch to database: $desired_db" unless + $self->set_database($desired_db); + + my $dbh = $self->{dbh}; + $dbh->{$key} = $val; +} + +package DBIx::StateKeeper; + +use strict; +use vars qw($AUTOLOAD); + +sub new { + my ($class, $tracker, $db) = @_; + my $bless = ref $class || $class; + my $self = {}; # always empty. real state is stored in tied node. + tie %$self, $bless, $tracker, $db; + bless $self, $bless; + return $self; +} + +sub STORE { + my ($self, $key, $value) = @_; + die "Setting attributes on DBIx::StateKeeper handles not yet supported. Use a real connection."; + return $self->{_tracker}->set_attribute($self->{_db}, $key, $value); +} + +sub DELETE { die "DELETE not implemented" } +sub CLEAR { die "CLEAR not implemented" } +sub EXISTS { die "EXISTS not implemented" } +sub FIRSTKEY { return undef; } +sub NEXTKEY { return undef; } +sub DESTROY { die "DELETE not implemented" } +sub UNTIE { } + +sub set_database { + my $self = shift; + return $self->{_tracker}->set_database($self->{_db}); +} + +sub FETCH { + my ($self, $key) = @_; + + # keys starting with underscore are our own. otherwise + # we forward them on to the real $dbh. + if ($key =~ m!^\_!) { + my $ret = $self->{$key}; + return $ret; + } + + return $self->{_tracker}->get_attribute($self->{_db}, $key); +} + +sub TIEHASH { + my ($class, $tracker, $db) = @_; + my $node = { + '_tracker' => $tracker, + '_db' => $db, + }; + return bless $node, $class; +} + +sub AUTOLOAD { + my $self = shift; + my $method = $AUTOLOAD; + $method =~ s/.+:://; + return $self->{_tracker}->do_method($self->{_db}, $method, @_); +} + +1; diff --git a/wcmtools/lib/Danga-Daemon/Daemon.pm b/wcmtools/lib/Danga-Daemon/Daemon.pm new file mode 100755 index 0000000..bbb72f3 --- /dev/null +++ b/wcmtools/lib/Danga-Daemon/Daemon.pm @@ -0,0 +1,463 @@ +#!/usr/bin/perl -w +# +#-------------------------------------------------- + +=head1 Description + +This class will make a proper daemon out of an arbitrary subroutine. +Your script will automatically inherit daemon command line flags, that +can intermix with your existing flags. (As long as you use Getopt!) + +=head1 Examples + +=head2 Basic usage + + use Danga::Daemon; + + Danga::Daemon::daemonize( \&worker ); + + sub worker + { + # do something + } + +=head2 Advanced usage + + # This spawns a listener on localhost:2000, adds a command to the CLUI, + # and does the daemon work as user 'nobody' 4 times a second: + + Danga::Daemon::daemonize( + \&worker, + { + interval => .25, + shedprivs => 'nobody', + + listenport => 2000, + bindaddr => '127.0.0.1', + listencode => \&cmd, + } + ); + + sub cmd + { + my ( $line, $s, $c, $codeloop, $codeopts ) = @_; + + if ($line =~ /newcommand/i) { + # do something + print $c ".\nOK\n"; + return 1; + } + + return; + } + +=head1 Command line switches + +=over 4 + +=item --foreground + +Run the script without daemon code, and print output to screen. + +=item --stop + +Stop an existing daemon. + +=item --pidfile + +Store the pidfile in a location other than /var/run. Useful if you are +running the script as a non-root user. Use the string 'none' to disable +pidfiles entirely. + +=back + +=head1 Options list + +Options are passed as the second argument to daemonize(), in the form of +a hashref. + +=over 4 + +=item args [ array of args ] + +A normal list of arguments that will be passed to the worker subroutine. + +=item bindaddr [ ip address ] + +If using a listener, bind to a specific IP. Not defining this will let +the listener bind to all IPs. + +=item chdir [ directory ] + +Tell the worker where to 'live'. Listener also, if one exists. +Defaults to '/'. + +=item interval [ number in fractional seconds ] + +Default eventloop time is 1 minute. Set this to override, in seconds, +or fractions thereof. + +=item listenport [ port ] + +The port the listener will bind to. Setting this option is also the +switch to enable a listener. + +=item listencode [ coderef ] + +An optional coderef that can add to the existing default command line +options. See the above example. + +=item override_loop [ boolean ] + +Your daemon may need to base its looping on something other than a time +value. Setting this puts the looping burden on the caller. Note in +this instance, the 'interval' option has no meaning. + +=item shedprivs [ system username ] + +If starting up as root, automatically change process ownership after +daemonizing. + +=item shutdowncode [ coderef ] + +If your child is doing special processing and needs to know when it's +being killed off, provide a coderef here. It will be called right before +the worker process exits. + +=back + +=head1 Default telnet commands + +These commands only apply if you use the 'listenport' option. + +=over 4 + +=item pids + +Report the pids in use. First pid is the listener. Any remaining are +workers. + +=item ping + +Returns the string 'pong' along with the daemon name. + +=item reload + +Kill off any workers, and reload them. An easy way to restart a worker +if library code changes. + +=item stop + +Shutdown the entire daemon. + +=back + +=cut + +#-------------------------------------------------- +package Danga::Daemon; + +use strict; +use Carp qw/ confess /; +use Getopt::Long qw/ :config pass_through /; +use POSIX 'setsid'; +use FindBin qw/ $RealBin $RealScript /; + +use vars qw/ $busy $stop $opt $pidfile $pid $shutdowncode /; + +# Make daemonize() and debug() available to the caller +*main::debug = \&Danga::Daemon::debug; +*main::daemonize = \&Danga::Daemon::daemonize; + +# Insert global daemon command line opts before script specific ones, +# With the addition of Getopt::Long's 'config pass_through', this +# essentially merges the command line options. +BEGIN { + $opt = {}; + GetOptions $opt, qw/ stop foreground pidfile=s /; +} + +# put arbitrary code into a loop after forking into the background. +sub daemonize +{ + my $codeloop = shift || confess "No coderef loop supplied.\n"; + confess "Invalid coderef\n" unless ref $codeloop eq 'CODE'; + my $codeopts = shift || {}; + + $SIG{$_} = \&stop_parent foreach qw/ INT TERM /; + $SIG{CHLD} = 'IGNORE'; + $pidfile = $opt->{'pidfile'} || "/var/run/$RealScript.pid"; + $| = 1; + + # setup shutdown ref if necessary + if ( $codeopts->{'shutdowncode'} && ref $codeopts->{'shutdowncode'} eq 'CODE' ) { + $shutdowncode = $codeopts->{'shutdowncode'}; + } + + # shutdown existing daemon? + if ( $opt->{'stop'} ) { + if ( -e $pidfile ) { + open( PID, $pidfile ); + chomp( $pid = ); + close PID; + } + else { + confess "No pidfile, unable to stop daemon.\n"; + } + + if ( kill 15, $pid ) { + print "Shutting down daemon."; + unlink $pidfile; + } + else { + print "Daemon not running?\n"; + exit 0; + } + + # display something while we're waiting for a + # busy daemon to shutdown + while ( kill 0, $pid ) { sleep 1 && print '.'; } + print "\n"; + exit 0; + } + + # daemonize. + if ( !$opt->{'foreground'} ) { + + if ( -e $pidfile ) { + print "Pidfile already exists! ($pidfile)\nUnable to start daemon.\n"; + exit 0; + } + + fork && exit 0; + POSIX::setsid() || confess "Unable to become session leader: $!\n"; + + $pid = fork; + confess "Couldn't fork.\n" unless defined $pid; + + if ( $pid != 0 ) { # we are the parent + unless ($pidfile eq 'none') { + unless ( open( PID, ">$pidfile" ) ) { + kill 15, $pid; + confess "Couldn't write PID file. Exiting.\n"; + } + print PID ($codeopts->{listenport} ? $$ : $pid) . "\n"; + close PID; + } + print "daemon started with pid: $pid\n"; + + # listener port supplied? spawn a listener! + spawn_listener( $codeloop, $codeopts ) + if $codeopts->{listenport}; + exit 0; # exit from parent if no listener + } + + # we're the child from here on out. + child_actions( $codeopts ); + } + + # the event loop + if ( $codeopts->{override_loop} ) { + + # the caller subref has its own idea of what + # a loop is defined as. + chdir ( $codeopts->{chdir} || '/') or die "Can't chdir!"; + $codeloop->( $codeopts->{args} ); + + } + else { + + # a loop is just a time interval inbetween + # code executions + return eventloop( $codeloop, $codeopts ); + } + + return 1; +} + +sub eventloop +{ + my $codeloop = shift || confess "No coderef loop supplied.\n"; + confess "Invalid coderef\n" unless ref $codeloop eq 'CODE'; + my $codeopts = shift || {}; + + chdir ( $codeopts->{chdir} || '/') or die "Can't chdir!"; + + { + no warnings; + $SIG{CHLD} = undef; + } + + while (1) { + + $busy = 1; + $codeloop->( $codeopts->{args} ); + $busy = 0; + + last if $stop; + select undef, undef, undef, ( $codeopts->{interval} || 60 ); + } + + return 0; +} + +sub child_actions +{ + my $codeopts = shift || {}; + + $SIG{$_} = \&stop_child foreach qw/ INT TERM /; + $0 = $RealScript . " - worker"; + umask 0; + chdir ( $codeopts->{chdir} || '/') or die "Can't chdir!"; + + # shed root privs + if ( $codeopts->{shedprivs} ) { + my $uid = getpwnam( $codeopts->{shedprivs} ); + $< = $> = $uid if $uid && ! $<; + } + + { + no warnings; + close STDIN && open STDIN, "&STDIN"; + close STDERR && open STDERR, "+>&STDIN"; + } + + return; +} + +sub spawn_listener +{ + my $codeloop = shift || confess "No coderef loop supplied.\n"; + confess "Invalid coderef\n" unless ref $codeloop eq 'CODE'; + my $codeopts = shift || {}; + + use IO::Socket; + $0 = $RealScript . " - listener"; + + my ( $s, $c ); + $s = IO::Socket::INET->new( + Type => SOCK_STREAM, + LocalAddr => $codeopts->{bindaddr}, # undef binds to all + ReuseAddr => 1, + Listen => 2, + LocalPort => $codeopts->{listenport}, + ); + unless ($s) { + kill 15, $pid; + unlink $pidfile; + confess "Unable to start listener.\n"; + } + + # pass incoming connections to listencode() + while ($c = $s->accept()) { + default_cmdline( $s, $c, $codeloop, $codeopts ); + } + + # shouldn't reach this. + close $s; + exit 0; +} + +sub stop_parent +{ + debug("Shutting down...\n"); + + if ($pid) { # not used in foreground + kill 15, $pid; + waitpid $pid, 0; + unlink $pidfile; + } + + exit 0 unless $busy; + $stop = 1; +} + +sub stop_child +{ + # call our children to have them shut down + $shutdowncode->() if $shutdowncode; + + exit 0 unless $busy; + $stop = 1; +} + +sub debug +{ + return unless $opt->{'foreground'}; + print STDERR (shift) . "\n"; +} + +# shutdown daemon remotely +sub default_cmdline +{ + my ( $s, $c, $codeloop, $codeopts ) = @_; + + while ( <$c> ) { + # remote commands + next unless /\w/; + + if (/pids/i) { + print $c "OK $$ $pid\n"; + next; + } + + elsif (/ping/i) { + print $c "OK pong $0\n"; + next; + } + + elsif (/(?:stop|shutdown)/) { + kill 15, $pid; + unlink $pidfile; + print $c "OK SHUTDOWN\n"; + exit 0; + } + + elsif (/(?:restart|reload)/i) { + # shutdown existing worker + # wait for it to completely exit + kill 15, $pid; + wait; + + # re-fork a new worker (no listener) + my $newpid = fork; + unless ($newpid) { + close $s; + $0 =~ s/listener/worker/; + child_actions( $codeopts ); + eventloop( $codeloop, $codeopts ); + exit 0; + } + + # remember the new child pid for + # future restarts + $pid = $newpid; + print $c "OK $pid\n"; + next; + } + + else { + + next if + $codeopts->{listencode} && + ref $codeopts->{listencode} eq 'CODE' && + $codeopts->{listencode}->( $_, $s, $c, $codeloop, $codeopts ); + + if (/help/i) { + foreach (sort qw/ ping stop pids reload /) { + print $c "\t$_\n"; + } + print $c ".\nOK\n"; + next; + } + + print $c "ERR unknown command\n"; + next; + } + } + return; +} + +1; + diff --git a/wcmtools/lib/Danga-EXIF/EXIF.pm b/wcmtools/lib/Danga-EXIF/EXIF.pm new file mode 100755 index 0000000..23a213d --- /dev/null +++ b/wcmtools/lib/Danga-EXIF/EXIF.pm @@ -0,0 +1,1100 @@ +#!/usr/bin/perl +# +# Danga::EXIF - An all-perl EXIF extraction library +# Brad Whitaker (whitaker@danga.com) - Danga Interactive +# +# TODO: +# - MakerNotes/UserNotes +# - GPS Tags +# - Handle more SubIFD/SubSubIFDs +# - fix bugs? + +package Danga::EXIF; + +use strict; +use Carp; +use IO::File; + +# print debugging information? +use constant DEBUG => 0; + +use constant MARK_SOI => "\xFF\xD8"; # start of image +use constant MARK_EOI => "\xFF\xD9"; # end of image +use constant MARK_SOS => "\xFF\xDA"; # start of stream +use constant MARK_APP0_JFIF => "\xFF\xE0"; # App0 (JFIF) marker +use constant MARK_APP1_EXIF => "\xFF\xE1"; # App1 (EXIF) marker +use constant EXIF_HEADER => "Exif\x00\x00"; # EXIF header +use constant EXIF_SUBIFD => 0x8769; # EXIF SubIFD Tag (numeric) +use constant TIFF_HEADER => 0x002A; # TIFF header marker +use constant ORDER_INTEL => "II"; # Intel (little-endian) byte-order +use constant ORDER_MOTOROLA => "MM"; # Motorola (big-endian) byte-order + +use fields qw(byte_order src filename buff offset tags); + +sub debug { print STDERR "$_[0]\n" if DEBUG; } + +sub new { + my Danga::EXIF $self = shift; + $self = fields::new($self) unless ref $self; + + my %args = @_; + + $self->{byte_order} = undef; + $self->{src} = $args{src}; + $self->{filename} = undef; + $self->{buff} = undef; + $self->{offset} = 0; + $self->{tags} = []; + + # this is most of the work + $self->process_file; + + return $self; +} + +sub open_src +{ + my Danga::EXIF $self = shift; + my $filename = shift; + + return length(${$self->{src}}) if ref $self->{src} eq 'SCALAR'; + return -s $self->{src} if ref $self->{src}; + + # it's probably a scalar, open the file + if ($self->{filename} = $self->{src}) { + debug("open_src: file: $self->{filename}"); + $self->{src} = new IO::File $self->{filename} + or croak "open_src: couldn't open file $self->{filename}: $!"; + return -s $self->{src}; + } + + return undef; +} + +sub close_src +{ + my Danga::EXIF $self = shift; + + # close filehandle if we were the ones who opened it + return close $self->{src} + if $self->{filename} && ref $self->{src} eq 'IO::Handle'; + + return 1; +} + +# read a specified number of bytes from $self->{src} +sub read_src +{ + my Danga::EXIF $self = shift; + my $len = shift; + + # src is scalarref + if (ref $self->{src} eq 'SCALAR') { + return substr(${$self->{src}}, 0, $len, ''); + } + + # src is probably filehandle + my $n = read($self->{src}, $self->{buff}, $len); + die "read failed: $!" unless defined $n; + die "short read ($len/$n)" unless $n == $len; + return $self->{buff}; +} + +# read the next n bytes from $self->{buff} and increment offset +sub read_buff +{ + my Danga::EXIF $self = shift; + my $len = shift; + + my $rval = substr($self->{buff}, $self->{offset}, $len); + $self->seek_buff($len); + return $rval; +} + +# move the offset pointer n bytes forward +sub seek_buff +{ + my Danga::EXIF $self = shift; + + return $self->{offset} += $_[0]; +} + +# return n bytes from $self->{buff} starting at a given offset +sub peek_buff +{ + my Danga::EXIF $self = shift; + my ($offset, $len) = @_; + + return substr($self->{buff}, $offset, $len); +} + +# unpacking mechanism which respects byte ordering +sub unpack +{ + my Danga::EXIF $self = shift; + my ($tmpl, $data) = @_; + + croak "undefined byte order" + unless defined $self->{byte_order}; + + # flip order to little endian if necessary + $tmpl =~ tr/vV/nN/ + unless $self->{byte_order} eq ORDER_INTEL; + + return CORE::unpack($tmpl, $data); +} + +sub process_file +{ + my Danga::EXIF $self = shift; + + my $filesize = $self->open_src + or croak "Couldn't open source file"; + debug("filesize: $filesize"); + debug("src: $self->{src}"); + + my $pos = 0; + + my $do_read = sub { + my $len = shift; + debug("received len: $len"); + if ($pos + $len > $filesize) { + $len = $filesize - $pos; + debug("adjusing len: $len"); + } + $pos += $len; + debug("do_read, $pos > $filesize?"); + debug("yes, done") if $pos > $filesize; + #last if $pos > $filesize; + + my $buf = $self->read_src($len); + debug("nope, buf=" . length($buf)); + return $buf; + }; + + # need an SOI to make sure this file is valid + my $soi = $self->read_src(2); + $pos += 2; + croak "Error reading EXIF header: SOI missing" + unless $soi eq MARK_SOI; + + # read until end of header + while ($pos + 4 <= $filesize) { + + debug("in loop"); + my ($mark, $len) = CORE::unpack("a2v", $do_read->(4)); + debug("mark=" . CORE::unpack("H4", $mark) . ", len=" . length($self->{buff})); + last if $mark eq MARK_EOI || $mark eq MARK_SOS; + last if $len < 2; + + # length contains the 2-byte data length descriptor, + # so strip that to know how much to actually read + + $self->{buff} = $do_read->($len - 2); + + if ($mark eq MARK_APP0_JFIF) { + debug("JFIF marker"); + + # TODO: get info from here? + next; + } + + if ($mark eq MARK_APP1_EXIF) { + debug("EXIF marker"); + $self->process_app1_exif; + last; + } + + # don't care about other markers + } + + $self->close_src; + + return 1; +} + +sub process_app1_exif +{ + my Danga::EXIF $self = shift; + + my $hdr = substr($self->{buff}, 0, 6, ''); + croak "invalid exif header" + unless $hdr eq EXIF_HEADER; + + # Offset 0 is now beginning of TIFF header + + # determine byte order + $self->{byte_order} = $self->read_buff(2); + debug("byte order: $self->{byte_order}"); + croak "process_app1_exif: unknown byte order" + unless ($self->{byte_order} eq ORDER_INTEL || + $self->{byte_order} eq ORDER_MOTOROLA); + + croak "process_app1_exif: invalid TIFF header" + unless $self->unpack("v", $self->read_buff(2)) == TIFF_HEADER; + + my $ifd_offset = $self->unpack("V", $self->read_buff(4)); + + # subtract 8 to account for the 8 bytes of tiff header + # already read, but included in the offset + $ifd_offset -= 8; + + # if the first ifd starts at an offset, skip to there + # and throw away anything in between. + debug("ifd offset: $ifd_offset"); + if ($ifd_offset > 0) { + debug("seeking"); + $self->seek_buff($ifd_offset); + } + + $self->process_ifds; +} + +sub process_ifds +{ + my Danga::EXIF $self = shift; + + debug("processing ifd at offset: $self->{offset}"); + + my $ifd_size = $self->unpack("v", $self->read_buff(2)) + or croak "process_ifds: empty ifd"; + + debug("ifd_size: $ifd_size"); + + foreach (1..$ifd_size) { + + my ($tagid, $type, $count) = + $self->unpack("vvV", $self->read_buff(8)); + + # next 4 bytes are either a value or an offset, + # read them raw at first until we know how they + # should be interpretted + my $val = $self->read_buff(4); + + # if the tagid is the EXIF_SUBIFD tag, then the value + # is a pointer to that IFD, which needs processing + if ($tagid == EXIF_SUBIFD) { + + # FIXME: ghetto, do something smarter + my $save_offset = $self->{offset}; + $self->{offset} = $self->unpack("V", $val); + $self->process_ifds; + $self->{offset} = $save_offset; + next; + } + + my $typeinf = Danga::EXIF::get_type_info($type); + my $len = $count * $typeinf->{bytes}; + + # if length is supposed to be less than 4 bytes, it'll be + # left-aligned inside the value field + if ($len < 4) { + $val = substr($val, 0, $len); + + # if length is more than 4 bytes, then val is an offset + # to the real value + } elsif ($len > 4) { + $val = $self->peek_buff($self->unpack("V", $val), $len); + } + + # apply template if defined + my $template = $typeinf->{template} || "a*"; + $template x= $count unless index($template, '*') >= 0; + my @val = $self->unpack($template, $val); + + # register this tag + if (Danga::EXIF::is_known_tag($tagid)) { + push @{$self->{tags}}, Danga::EXIF::Tag->new + ( tagid => $tagid, type => $type, value => \@val ); + } + } +} + +sub tags +{ + my Danga::EXIF $self = shift; + + # array context returns array of tags + return @{$self->{tags}} if wantarray; + + # scalar context returns hashref of tag => value + return { map { $_->tag => $_->value } grep { $_->value } @{$self->{tags}} }; +} + +sub is_known_tag +{ + my $tagid = shift; + + return exists $Danga::EXIF::TAG_INFO{$tagid} ? 1 : 0; +} + +sub get_tag_info +{ + my $tagid = shift; + + return $Danga::EXIF::TAG_INFO{$tagid} || { + tag => $tagid, + name => "Tag-" . sprintf("%4x", $tagid), + disp => "none", + }; +} + +sub get_type_info +{ + return $Danga::EXIF::TYPE_INFO{$_[0]} || {}; +} + +############################################################################### + +package Danga::EXIF::Tag; + +use strict; +use Carp; + +use fields qw(tagid type value); + +*debug = *Danga::EXIF::debug; + +sub new +{ + my Danga::EXIF::Tag $self = shift; + $self = fields::new($self) unless ref $self; + + my %args = @_; + + $self->{tagid} = $args{tagid} or croak "no tagid"; + $self->{type} = $args{type} or croak "no data type";; + $self->{value} = $args{value} or croak "no value"; + + return $self; +} + +sub tag +{ + my Danga::EXIF::Tag $self = shift; + + return Danga::EXIF::get_tag_info($self->{tagid})->{tag}; +} + +sub name +{ + my Danga::EXIF::Tag $self = shift; + + return Danga::EXIF::get_tag_info($self->{tagid})->{name}; +} + +sub value +{ + my Danga::EXIF::Tag $self = shift; + + my $taginf = Danga::EXIF::get_tag_info($self->{tagid}); + my $disp = $taginf->{disp} || 'literal'; + + if ($disp eq 'none') { + return ''; # MakerNote, UserComment (for now) + } + + if (ref $disp eq 'HASH') { + my $key = join('', @{$self->{value}}); + return $disp->{$key}; + } + + if (ref $disp eq 'CODE') { + return $disp->(@{$self->{value}}); + } + + my $typeinf = Danga::EXIF::get_type_info($self->{type}); + if (my $literal = $typeinf->{literal}) { + return $literal->(@{$self->{value}}); + } + + # default literal behavior + return join('', @{$self->{value}}); +} + + +############################################################################### + +package Danga::EXIF; + +use strict; +use vars qw(%TYPE_INFO %TAG_INFO); + +%TYPE_INFO = + ( + # An 8-bit unsigned integer. + 0x0001 => { + type => "byte", + bytes => 1, + template => "a", + }, + + # An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL. + 0x0002 => { + type => "ascii", + bytes => 1, + template => "A*", + }, + + # A 16-bit (2-byte) unsigned integer. + 0x0003 => { + type => "short", + bytes => 2, + template => "v", + }, + + # A 32-bit (4-byte) unsigned integer. + 0x0004 => { + type => "long", + bytes => 4, + template => "V", + }, + + # Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator. + 0x0005 => { + type => "rational", + bytes => 8, + template => "VV", + literal => sub { join("/", map { $_+0 } @_[0,1]) }, + }, + + # An 8-bit byte that can take any value depending on the field definition. + 0x0007 => { + type => "undefined", + bytes => 1, + template => "a*", + }, + + # A 32-bit (4-byte) signed integer (2's complement notation). + 0x0009 => { + type => "slong", + bytes => 4, + template => "l", + }, + + # Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator. + 0x000a => { + type => "srational", + bytes => 8, + template => "ll", + literal => sub { join("/", map { $_+0 } @_[0,1]) }, + + }, + + ); + +# +# TagID => { tag => "TagName", +# name => "Display name", +# disp => literal|none|hashref|subref, +# } + +%TAG_INFO = + ( + 0x927c => { + tag => "MakerNote", + name => "Manufacturer Notes", + disp => "none", + }, + 0x9286 => { + tag => "UserComment", + name => "User comments", + disp => "none", + }, + + # FILE INFO + 0x0100 => { + tag => "ImageWidth", + name => "Image width", + disp => "literal", + }, + 0x0101 => { + tag => "ImageLength", + name => "Image height", + disp => "literal", + }, + 0x0102 => { + tag => "BitsPerSample", + name => "Number of bits per component", + disp => "literal", + }, + 0x0103 => { + tag => "Compression", + name => "Compression scheme", + disp => { + 1 => "Uncompressed", + 6 => "JPEG compression (thumbnails only)", + }, + }, + 0x0106 => { + tag => "PhotometricInterpretation", + name => "Pixel composition", + disp => { + 2 => "RGB", + 6 => "YCbCr", + }, + }, + 0x0112 => { + tag => "Orientation", + name => "Orientation of image", + disp => { + 1 => "The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side", + 2 => "The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side", + 3 => "The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side", + 4 => "The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side", + 5 => "The 0th row is the visual left-hand side of the image, and the 0th column is the visual top", + 6 => "The 0th row is the visual right-hand side of the image, and the 0th column is the visual top", + 7 => "The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom", + 8 => "The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom", + }, + }, + 0x0115 => { + tag => "SamplesPerPixel", + name => "Number of components", + disp => "literal", + }, + 0x011c => { + tag => "PlanarConfiguration", + name => "Image data arrangement", + disp => { + 1 => "Chunky format", + 2 => "Planar format", + }, + }, + 0x0212 => { + tag => "YCbCrSubSampling", + name => "Subsampling ratio of Y to C", + disp => { + 21 => "YCbCr4:2:2", + 22 => "YCbCr4:2:0", + }, + }, + 0x0213 => { + tag => "YCbCrPositioning", + name => "Y and C positioning", + disp => { + 1 => "Centered", + 2 => "Co-sited", + }, + }, + 0x011a => { + tag => "XResolution", + name => "Image resolution in width direction", + disp => "literal", + }, + 0x011b => { + tag => "YResolution", + name => "Image resolution in height direction", + disp => "literal", + }, + 0x0128 => { + tag => "ResolutionUnit", + name => "Unit of X and Y resolution", + disp => { + 1 => "Unspecified", + 2 => "Pixels/Inch", + 3 => "Pixels/Centimeter", + }, + }, + 0x0111 => { + tag => "StripOffsets", + name => "Image data location", + disp => "literal", + }, + 0x0116 => { + tag => "RowsPerStrip", + name => "Number of rows per strip", + disp => "literal", + }, + 0x0117 => { + tag => "StripByteCounts", + name => "Bytes per compressed strip", + disp => "literal", + }, + 0x0201 => { + tag => "JPEGInterchangeFormat", + name => "Offset to JPEG SOI", + disp => "literal", + }, + 0x0202 => { + tag => "JPEGInterchangeFormatLength", + name => "Bytes of JPEG data", + disp => "literal", + }, + 0x012d => { + tag => "TransferFunction", + name => "Transfer function", + disp => "literal", + }, + 0x013e => { + tag => "WhitePoint", + name => "White point chromaticity", + disp => "literal", + }, + 0x013f => { + tag => "PrimaryChromaticities", + name => "Chromaticities of primaries", + disp => "literal", + }, + 0x0211 => { + tag => "YCbCrCoefficients", + name => "Color space transformation matrix coefficients", + disp => "literal", + }, + 0x0214 => { + tag => "ReferenceBlackWhite", + name => "Pair of black and white reference values", + disp => "literal", + }, + 0xa001 => { + tag => "ColorSpace", + name => "Color space information", + disp => { + 1 => "sRGB", + 65535 => "Uncalibrated", + }, + }, + 0x9000 => { + tag => "ExifVersion", + name => "Exif version", + disp => "literal", + }, + 0xa000 => { + tag => "FlashpixVersion", + name => "Supported Flashpix version", + disp => { + 0100 => "Flashpix Format Version 1.0", + }, + }, + 0x0132 => { + tag => "DateTime", + name => "File change date and time", + disp => "literal", + }, + 0x010e => { + tag => "ImageDescription", + name => "Image title", + disp => "literal", + }, + 0x010f => { + tag => "Make", + name => "Image input equipment manufacturer", + disp => "literal", + }, + 0x0110 => { + tag => "Model", + name => "Image input equipment model", + disp => "literal", + }, + 0x0131 => { + tag => "Software", + name => "Software used", + disp => "literal", + }, + 0x013b => { + tag => "Artist", + name => "Person who created the image", + disp => "literal", + }, + 0x8298 => { + tag => "Copyright", + name => "Copyright holder", + disp => "literal", + }, + 0xa420 => { + tag => "ImageUniqueID", + name => "Unique image ID", + disp => "literal", + }, + 0x9101 => { + tag => "ComponentsConfiguration", + name => "Meaning of each component", + disp => sub { + my $val = shift; + + my $map = { + 1 => "Y", + 2 => "Cb", + 3 => "Cr", + 4 => "R", + 5 => "G", + 6 => "B", + }; + return join('', map { $map->{$_} } split('', $val)); + }, + }, + 0x9102 => { + tag => "CompressedBitsPerPixel", + name => "Image compression mode", + disp => "literal", + }, + 0xa002 => { + tag => "PixelXDimension", + name => "Valid image width", + disp => "literal", + }, + 0xa003 => { + tag => "PixelYDimension", + name => "Valid image height", + disp => "literal", + }, + 0xa004 => { + tag => "RelatedSoundFile", + name => "Related audio file", + disp => "literal", + }, + 0xa005 => { + tag => "ExifInteroperabilityOffset", + name => "Exif interoperability offset", + disp => "literal", + }, + 0x9003 => { + tag => "DateTimeOriginal", + name => "Date and time of original data generation", + disp => "literal", + }, + 0x9004 => { + tag => "DateTimeDigitized", + name => "Date and time of digital data generation", + disp => "literal", + }, + 0x9290 => { + tag => "SubSecTime", + name => "DateTime subseconds", + disp => "literal", + }, + 0x9291 => { + tag => "SubSecTimeOriginal", + name => "DateTimeOriginal subseconds", + disp => "literal", + }, + 0x9292 => { + tag => "SubSecTimeDigitized", + name => "DateTimeDigitized subseconds", + disp => "literal", + }, + 0x829a => { + tag => "ExposureTime", + name => "Exposure time", + disp => "literal", + }, + 0x829d => { + tag => "FNumber", + name => "FNumber", + disp => "literal", + }, + 0x8822 => { + tag => "ExposureProgram", + name => "Exposure program", + disp => { + 1 => "Manual", + 2 => "Normal program", + 3 => "Aperture priority", + 4 => "Shutter priority", + 5 => "Creative program (biased toward depth of field)", + 6 => "Action program (biased toward fast shutter speed)", + 7 => "Portrait mode (for closeup photos with the background out of focus)", + 8 => "Landscape mode (for landscape photos with the background in focus)", + }, + }, + 0x8824 => { + tag => "SpectralSensitivity", + name => "Spectral sensitivity", + disp => "literal", + }, + 0x8827 => { + tag => "ISOSpeedRatings", + name => "ISO speed rating", + disp => "literal", + }, + 0x8828 => { + tag => "OECF", + name => "Optoelectric conversion factor", + disp => "literal", + }, + 0x9201 => { + tag => "ShutterSpeedValue", + name => "Shutter speed", + disp => "literal", + }, + 0x9202 => { + tag => "ApertureValue", + name => "Aperture", + disp => "literal", + }, + 0x9203 => { + tag => "BrightnessValue", + name => "Brightness", + disp => "literal", + }, + 0x9204 => { + tag => "ExposureBiasValue", + name => "Exposure bias", + disp => "literal", + }, + 0x9205 => { + tag => "MaxApertureValue", + name => "Maximum lens aperture", + disp => "literal", + }, + 0x9206 => { + tag => "SubjectDistance", + name => "Subject distance", + disp => "literal", + }, + 0x9207 => { + tag => "MeteringMode", + name => "Metering mode", + disp => { + 1 => "Average", + 2 => "CenterWeightedAverage", + 3 => "Spot", + 4 => "MultiSpot", + 5 => "Pattern", + 6 => "Partial", + 255 => "Other", + }, + }, + 0x9208 => { + tag => "LightSource", + name => "Light source", + disp => { + 1 => "Daylight", + 2 => "Fluorescent", + 3 => "Tungsten (incandescent light)", + 4 => "Flash", + 9 => "Fine weather", + 10 => "Cloudy weather", + 11 => "Shade", + 12 => "Daylight fluorescent (D 5700 - 7100K)", + 13 => "Day white fluorescent (N 4600 - 5400K)", + 14 => "Cool white fluorescent (W 3900 - 4500K)", + 15 => "White fluorescent (WW 3200 - 3700K)", + 17 => "Standard light A", + 18 => "Standard light B", + 19 => "Standard light C", + 20 => "D55", + 21 => "D65", + 22 => "D75", + 23 => "D50", + 24 => "ISO studio tungsten", + 255 => "Other light source", + }, + }, + 0x9209 => { + tag => "Flash", + name => "Flash", + disp => sub { + my $val = shift; + + my $bit = sub { + return $val & (1 << $_[0]); + }; + + # bit 0 + my @ret = $bit->(0) ? ("Flash fired") : ("Flash did not fire"); + + # bits 1-2 + if (! $bit->(1) && ! $bit->(2)) { + push @ret, "No strobe return detection function"; + } elsif ($bit->(1)) { + push @ret, "Strobe return light " . ($bit->(2) ? "" : "not") . " detected"; + } + + # bits 3-4 + if (! $bit->(3) && $bit->(4)) { + push @ret, "Compulsory flash firing"; + } elsif ($bit->(3) && ! $bit->(4)) { + push @ret, "Compulsory flash suppression"; + } elsif ($bit->(3) && $bit->(4)) { + push @ret, "Auto mode"; + } + + # bit 5 + push @ret, ($bit->(5) ? "No flash function" : "Flash function present"); + + # bit 6 + push @ret, ($bit->(6) ? "Red-eye reduction supported" : "No red-eye reduction mode or unknown"); + + return join("; ", @ret); + }, + }, + 0x920a => { + tag => "FocalLength", + name => "Lens focal length", + disp => "literal", + }, + 0x9214 => { + tag => "SubjectArea", + name => "Subject area", + disp => "literal", + }, + 0xa20b => { + tag => "FlashEnergy", + name => "Flash energy", + disp => "literal", + }, + 0xa20c => { + tag => "SpatialFrequencyResponse", + name => "Spatial frequency response", + disp => "literal", + }, + 0xa20e => { + tag => "FocalPlaneXResolution", + name => "Focal plane X resolution", + disp => "literal", + }, + 0xa20f => { + tag => "FocalPlaneYResolution", + name => "Focal plane Y resolution", + disp => "literal", + }, + 0xa210 => { + tag => "FocalPlaneResolutionUnit", + name => "Focal plane resolution unit", + disp => sub { + return "$_[0] inch"; + }, + }, + 0xa214 => { + tag => "SubjectLocation", + name => "Subject location", + disp => "literal", + }, + 0xa215 => { + tag => "ExposureIndex", + name => "Exposure index", + disp => "literal", + }, + 0xa217 => { + tag => "SensingMethod", + name => "Sensing method", + disp => { + 2 => "One-chip color area sensor", + 3 => "Two-chip color area sensor", + 4 => "Three-chip color area sensor", + 5 => "Color sequential area sensor", + 7 => "Trilinear sensor", + 8 => "Color sequential linear sensor", + }, + }, + 0xa300 => { + tag => "FileSource", + name => "File source", + disp => { + 3 => "DSC", + }, + }, + 0xa301 => { + tag => "SceneType", + name => "Scene type", + disp => { + 1 => "A directly photographed image", + }, + }, + 0xa302 => { + tag => "CFAPattern", + name => "CFA pattern", + disp => "literal", + }, + 0xa401 => { + tag => "CustomRendered", + name => "Custom rendered", + disp => { + 0 => "Normal process", + 1 => "Custom process", + }, + }, + 0xa402 => { + tag => "ExposureMode", + name => "Exposure mode", + disp => { + 0 => "Auto exposure", + 1 => "Manual exposure", + 2 => "Auto bracket", + }, + }, + 0xa403 => { + tag => "WhiteBalance", + name => "White balance", + disp => { + 0 => "Auto white balance", + 1 => "Manual white balance", + }, + }, + 0xa404 => { + tag => "DigitalZoomRatio", + name => "Digital zoom ratio", + disp => "literal", + }, + 0xa405 => { + tag => "FocalLengthIn35mmFilm", + name => "Focal length in 35 mm film", + disp => "literal", + }, + 0xa406 => { + tag => "SceneCaptureType", + name => "Scene capture type", + disp => { + 0 => "Standard", + 1 => "Landscape", + 2 => "Portrait", + 3 => "Night scene", + }, + }, + 0xa407 => { + tag => "GainControl", + name => "Gain control", + disp => { + 0 => "None", + 1 => "Low gain up", + 2 => "High gain up", + 3 => "Low gain down", + 4 => "High gain down", + }, + }, + 0xa408 => { + tag => "Contrast", + name => "Contrast", + disp => { + 0 => "Normal", + 1 => "Soft", + 2 => "Hard", + }, + }, + 0xa409 => { + tag => "Saturation", + name => "Saturation", + disp => { + 0 => "Normal", + 1 => "Low saturation", + 2 => "High saturation", + }, + }, + 0xa40a => { + tag => "Sharpness", + name => "Sharpness", + disp => { + 0 => "Normal", + 1 => "Soft", + 2 => "Hard", + }, + }, + 0xa40b => { + tag => "DeviceSettingDescription", + name => "Device settings description", + disp => "literal", + }, + 0xa40c => { + tag => "SubjectDistanceRange", + name => "Subject distance range", + disp => { + 0 => "Unknown", + 1 => "Macro", + 2 => "Close view", + 3 => "Distant view", + }, + }, + + # TODO: GPS INFO +); diff --git a/wcmtools/lib/Danga-Exceptions/MANIFEST b/wcmtools/lib/Danga-Exceptions/MANIFEST new file mode 100755 index 0000000..1ce1d3c --- /dev/null +++ b/wcmtools/lib/Danga-Exceptions/MANIFEST @@ -0,0 +1,4 @@ +lib/Danga/Exceptions.pm +Makefile.PL +MANIFEST +t/basic.t diff --git a/wcmtools/lib/Danga-Exceptions/MANIFEST.SKIP b/wcmtools/lib/Danga-Exceptions/MANIFEST.SKIP new file mode 100755 index 0000000..ede9cda --- /dev/null +++ b/wcmtools/lib/Danga-Exceptions/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists diff --git a/wcmtools/lib/Danga-Exceptions/Makefile.PL b/wcmtools/lib/Danga-Exceptions/Makefile.PL new file mode 100755 index 0000000..9d4637f --- /dev/null +++ b/wcmtools/lib/Danga-Exceptions/Makefile.PL @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# +# Perl Makefile for Danga-Exceptions +# $Id: Makefile.PL,v 1.1 2004/06/04 22:06:28 deveiant Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Danga::Exceptions', + VERSION_FROM => 'lib/Danga/Exceptions.pm', # finds $VERSION + AUTHOR => 'Michael Granger ', + ABSTRACT => 'Exception library', + PREREQ_PM => { + Scalar::Util => 0, + Carp => 0, + overload => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag RELEASE_$(VERSION_SYM)', + SUFFIX => ".bz2", + DIST_DEFAULT => 'all tardist', + COMPRESS => "bzip2", + }, + +); + diff --git a/wcmtools/lib/Danga-Exceptions/lib/Danga/Exceptions.pm b/wcmtools/lib/Danga-Exceptions/lib/Danga/Exceptions.pm new file mode 100755 index 0000000..2f1c529 --- /dev/null +++ b/wcmtools/lib/Danga-Exceptions/lib/Danga/Exceptions.pm @@ -0,0 +1,1131 @@ +#!/usr/bin/perl +################################################################################ + +=head1 NAME + +Danga::Exceptions - runtime exception classes for Danga systems + +=head1 SYNOPSIS + + use Danga::Exceptions qw{:syntax}; + + my $result = try { + do_some_stuff(); + } catch Danga::Exception with { + my $e = shift; + print STDERR "Failed to do_some_stuff: $e"; + }; + +=head1 EXPORTS + +Nothing by default. + +If used with the :syntax tag, the functions C, C, C, +C, and C will be imported into your package. See +B for more about what they do and how to use them. + +=head1 REQUIRES + +C, C, C, C + +=head1 DESCRIPTION + +This module provides runtime exception classes for Danga, and methods and +syntax for handling them which can be imported. + +This code is mostly a hacked-up version of Text::Templar::Exceptions, which is +mostly a hacked-up version of the Error.pm module by Graham Barr +Egbarr@ti.comE. Sections which have been copied from or are modified +versions of synonymous sections of that module are annotated accordingly. + +=head2 Procedural Interface + +C can export subroutines to use for exception +handling. The following functions can be imported into your package with the +C<:syntax> tag. + +=over 3 + +=item C I> + +C is the main subroutine called by the user. All other subroutines exported +are clauses to the C subroutine. + +The I will be evaluated and if no error is thrown, it will return the result +of the block. + +I are the subroutines below, which describe what to do in the event of +an error being thrown within I. + +C works a bit like CBLOCKE> in regards to return value -- it +evaluates to the value of the last statement executed by any of its clauses +(including C, C, or C clauses), or may be influenced +by a return within any clause. This allows statements like the following: + + # Try to get the result of executing the code, ignoring any errors that + # happen within. + my $result = try { }; + +or + + # Get the result of the unsafe code if it executed successfully, or 0 if it + # errors for any reason. + my $result = try { } catch Exception with { return 0 }; + + +=item C with I> + +This clause will cause all errors that satisfy C<$err-Eisa(I)> to be +caught and handled by evaluating I. + +I will be passed two arguments. The first will be the exception object +being thrown, and the second is a reference to a scalar variable. If this +variable is set by the C block, then on return from the C block, +C will continue processing as if the C block was never found. This +can be used to propagate an exception to a later C, for example. + +Another way of propagating the error is to call C<$err-Ethrow> from within +the C block. + +If the scalar referenced by the second argument is not set, and the error is not +re-thrown, then the current C block will return with the result from the C +block. + +=item C> + +When C is looking for a handler, if an C clause is found, C is +evaluated. The return value from this block should be a C reference or a list of +key-value pairs, where the keys are class names and the values are C +references for the handler of errors of that type. + +This is useful for defining handlers on the fly. + +For example: + + try { + somethingDangerous(); + } + + # Handle IO errors + catch Exception::IOError with { + + } + + # Build a handler for other errors + except { + my $handler = sub { print STDERR shift()->message }; + + return { + Exception::Custom1 => $handler, + Exception::Custom2 => $handler, + }; + }; + +=item C> + +Catch any error by executing the code in I + +When evaluated, I will be passed one argument, which will be the error +being processed. + +Only one C block may be specified per C block. Additional C +blocks will be ignored. + +=item C> + +The code in I will be executed after all other clauses have executed. If +the C block throws an exception then C will be executed after any +handlers have been executed. If a handler throws an exception, then the exception will +be caught, the C block will be executed and the exception will be re-thrown. + +Only one C block may be specified per C block. Additional ones will +result in a syntax error. + +=back + +=head2 The Base Exception Class + +The following methods are methods on the base exception class, from which all +exceptions classes defined herein inherit. + +=head3 Constructor Methods + +=over 4 + +=item I + +Returns a new Danga::Exception object with the error message +specified, or 'Unspecified error' if none is specified. + +=back + +=head3 Methods + +=over 4 + +=item I + +A wrapper for stringify() + +=item I + +Adds a catch clause with the specified handler code for the specified +package onto the array of 'catch' clauses in the clauses given. If the +clauses hashref is omitted, one is created. Returns the new or given clauses +hashref with the new catch clause added. + +=item I + +Returns the stack frame from frameNumber levels deep in the call stack. The +frame is a hash (or hashref if called in scalar context) of the form: + + { + 'package' => The caller's package + 'filename' => The filename of the code being executed + 'line' => The line number being executed + 'subroutine' => The name of the function or method being executed + 'hasargs' => True if the sub was passed arguments from its caller + 'wantarray' => True if the sub was called in a list context + 'evaltext' => If 'subroutine' is '(eval)', this is the EXPR of the eval block + 'is_require' => True if the frame was created from a 'require' or 'use' + } + +=item I + +Returns an array of stack frames of the format returned by C that +describe the stack trace at the moment the exception was thrown. + +=item I + +Returns the stacktrace and error message of the exception as a human-readable +string. + +=item I + +Create a new C object with I and C with it. This will be +caught by any enclosing C blocks. If not enclosed by aC, calling +this method will cause a fatal exception. This method is a modified version of +the synonymous one in Error.pm. + +=back + +=head1 RCSID + +$Id: Exceptions.pm,v 1.3 2004/10/30 00:57:57 deveiant Exp $ + +=head1 AUTHOR + +Michael Granger Eged@FaerieMUD.orgE + +Large portions of this code were copied from the Text::Templar module's +exceptions module, which is licensed under Perl's Artistic License, and is +licensed under the following terms: + + Copyright (c) 1999-2004 The FaerieMUD Consortium. All rights reserved. + + This module is free software. You may use, modify, and/or + redistribute this software under the terms of the Perl Artistic + License. (See http://language.perl.com/misc/Artistic.html) + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +Portions of this file are also borrowed from Error.pm, which has the following +licensing information: + + Copyright (c) 1997-8 Graham Barr . All rights reserved. This + program is free software; you can redistribute it and/or modify it under the + same terms as Perl itself. + +All remaining changes and additional code fall under the following strictures: + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +=head1 SEE ALSO + +Error.pm by Graham Barr + +=cut + +################################################################################ +package Danga::Exceptions; +use strict; + +BEGIN { + require 5.006; + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Exceptions.pm,v 1.3 2004/10/30 00:57:57 deveiant Exp $; + + use base qw{Exporter}; +} + +### Delegate all exported stuff to the real base exception class +sub import { + my @args = @_; + return Danga::Exception->export_to_level( 1, @args ); +} + + +############################################################################### +### B A S E E X C E P T I O N C L A S S +############################################################################### +package Danga::Exception; +use strict; + +BEGIN { + require 5.006; + + # Package constants + use vars qw{$VERSION $RCSID @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD}; + $VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Exceptions.pm,v 1.3 2004/10/30 00:57:57 deveiant Exp $; + + # Superclass + use base qw{Exporter}; + + # Exporter stuff + @EXPORT = qw{}; + @EXPORT_OK = qw{try with finally except otherwise}; + %EXPORT_TAGS = ( 'syntax' => \@EXPORT_OK ); + + # Required modules + use Carp qw{carp croak confess}; + use Scalar::Util qw{blessed}; + + # Overload some operations + use overload ( + '""' => 'stringify', + '@{}' => sub { return shift()->{stacktrace} }, + 'fallback' => 1, + ); + +} + +############################################################################### +### C L A S S V A R I A B L E S +############################################################################### +our ( $Depth, $ErrorType, $Debug ); + +$ErrorType = "System"; +$Depth = 1; +$Debug = 0; + + +############################################################################### +### P U B L I C M E T H O D S +############################################################################### + +### (CONSTRUCTOR) METHOD: new( [@errorMessage] ) +### Returns a new Danga::Exception object with the error message +### specified, or 'Unspecified error' if none is specified. +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + my $message = ( @_ ? join('', @_) : "Unspecified error" ); + + my ( + @stacktrace, + @calleritems, + $frame, + $package, + $filename, + $line, + $context, + $errtype, + ); + + print STDERR "Creating an exception of type '$class' with message '$message'.\n" if $Debug; + + # Get the name of the error being thrown from the calling class + NO_STRICT_REFS: { + no strict 'refs'; + $errtype = ${"${class}::ErrorType"} || $ErrorType; + } + + # Build a stacktrace back to the first driver call for this error + $frame = $Depth; + FRAME: while ( @calleritems = caller($frame++) ) { + + # Define the exception's variables if the sub is our constructor or + # one of the syntax methods + if ( not defined $package ) { + ( $package, $filename, $line, undef, undef, $context ) = @calleritems; + next FRAME; + } + + # :FIXME: Should we trim frames off the stacktrace if they are frames + # inside the Exception class or one of its children? + #last FRAME if $calleritems[3] =~ m{^Danga::Exception::}; + + push @stacktrace, { + 'package' => $calleritems[0], + 'filename' => $calleritems[1], + 'line' => $calleritems[2], + 'subroutine' => $calleritems[3], + 'hasargs' => $calleritems[4], + 'wantarray' => $calleritems[5], + 'evaltext' => $calleritems[6], + 'is_require' => $calleritems[7], + }; + } + + return bless { + 'message' => $message, + 'type' => $errtype, + 'stacktrace' => \@stacktrace, + 'timestamp' => time(), + 'package' => $package, + 'filename' => $filename, + 'line' => $line, + 'context' => $context, + }, $class; +} + + +### METHOD: throw( $errmsg ) +### Create a new C object with I and C with it. This +### will be caught by any enclosing C blocks. If not enclosed by a +### C, calling this method will cause a fatal exception. +### This method is a modified version of the synonymous one in Error.pm. +sub throw { + my $self = shift; + + print STDERR "Throwing a '", ref $self || $self, "' thingie.\n" if $Debug; + + # if we are not rethrow-ing then create the object to throw + #local $Depth = $Depth + 1; + $self = $self->new(@_) unless ref $self; + + # Throw ourself as the exception + print STDERR "Dying with exception '$self'.\n" if $Debug; + CORE::die $self; +} + + +### (AUTOLOADED) METHOD: message() +### Get/set the error message. + +### (AUTOLOADED) METHOD: type() +### Get/set the error type. +sub AUTOLOAD { + my $self = shift; + my $type = ref( $self ) || croak "AUTOLOAD: Cannot call proxy method in non-object '$self'."; + + ( my $name = $AUTOLOAD ) =~ s{^.*::}{}; + + # If we have an attribute with the same name as the method called, act as + # an accessor + if ( exists $self->{$name} ) { + $self->{ $name } = shift if @_; + return $self->{ $name }; + } + + # If there's not like-named attribute, try to call the method in our + # superclass + else { + my $method = "SUPER::${name}"; + return $self->$method( @_ ); + } +} + + +### METHOD: stackframe( $frameNumber ) +### Returns the stack frame from frameNumber levels deep in the call stack. The +### frame is a hash (or hashref if called in scalar context) of the form: +### +### 'package' => The caller's package +### 'filename' => The filename of the code being executed +### 'line' => The line number being executed +### 'subroutine' => The name of the function or method being executed +### 'hasargs' => True if the sub was passed arguments from its caller +### 'wantarray' => True if the sub was called in a list context +### 'evaltext' => If 'subroutine' is '(eval)', this is the EXPR +### of the eval block +### 'is_require' => True if the frame was created from a 'require' or 'use' +sub stackframe { + my $self = shift; + my $frame = shift || 0; + + return undef unless $#{$self->{'stacktrace'}} >= $frame; + return wantarray + ? %{ $self->{'stacktrace'}[$frame] } + : $self->{'stacktrace'}[$frame]; +} + + +### METHOD: stacktrace() +### Returns an array of stack frames of the format returned by C +### that describe the stack trace at the moment the exception was thrown. +sub stacktrace { + my $self = shift; + return @{$self->{'stacktrace'}}; +} + + +### METHOD: as_string( undef ) +### A wrapper for stringify() +sub as_string { stringify(@_) } + + +### METHOD: error() +### Generate an error message out of the exception's attributes and return it. +sub error { + my $self = shift; + + return sprintf( "A %s error '%s' occurred\n\tin %s (%s) line %d\n\t(%s).\n", + $self->type, + $self->message, + $self->package, + $self->filename, + $self->line, + scalar localtime($self->timestamp) ); +} + + +### METHOD: stringify() +### Returns the stacktrace and error message or the exception as a human-readable string. +sub stringify { + my $self = shift; + my $rval; + + $rval = $self->error . "-" x 80 . "\n"; + + for my $traceref ( @{$self->{'stacktrace'}} ) { + $rval .= sprintf( "%s (%s)\n\tline %s called %s.\n", + $$traceref{'package'}, + $$traceref{'filename'}, + $$traceref{'line'}, + $$traceref{'subroutine'} ); + } + + return $rval; +} + + +############################################################################### +### S Y N T A X F U N C T I O N S +############################################################################### + +### Note: Most of this code is from Error.pm by Graham Barr , with +### a few aesthetic and functional modifications by Michael Granger +### . All comments are also mine, so blame me for any +### mistakes =:) + +### FUNCTION: try( \&codeblock, \%handlerClauses ) +### The I will be evaluated and if no error condition arises, this +### function returns the result. I is a hash of code +### references that describe what actions to take if a error occurs. It is +### typically built by appending one or more C, C, or +### C clauses. +sub try (&;$) { + my $try = shift; # The try block as a CODE ref + my $clauses = @_ ? shift : {}; # The handler clauses + + my ( + $ok, + $error, + @results, + $wantarray, + $handlerCode, + ); + + $wantarray = wantarray; + + # Execute the try block + do { + no warnings; + + # Localize the depth counter and temporarily unset the die handler + local $Depth = 1; + local $SIG{__DIE__} = undef; + + # Wrap a call to the try block in an eval + $ok = eval { + if ( $wantarray ) { + @results = $try->(); + } else { + $results[0] = $try->(); + } + 1; # Indicate success + }; + + # Set the error message and set ok to false if there's an eval error + $error = $@, $ok = undef if $@; + }; + + # If the try block didn't return an ok status, handle the error + if ( $error ) { + + # If the error was just a $@, wrap it in a Exception + $error = __PACKAGE__->new( "Untrapped exception in try block: $error" ) unless ref $error; + + CATCH: { + my ( + $catchClauses, # Catch clauses (coderefs) + $owise, # Otherwise clause (coderef) + $i, # Iterator + $pkg, # The package to match for catch clauses + $keepTrying, # The 'keep trying' flag passed (by reference) to each catch block + $ok, # Eval result + ); + + # Do the catch clauses (if any are defined) + if (defined( $catchClauses = $clauses->{'catch'} )) { + + # Iterate over each catch clause package + coderef + CATCHLOOP: for( $i = 0; $i < @$catchClauses; $i += 2) { + + # Get the name of the package we're looking for + $pkg = $catchClauses->[$i]; + + # If there wasn't a package name, then it must be an except block, + # so splice the hash returned by it into the catch handlers and + # decrement the counter to point to the first new handler + unless (defined $pkg) { + + splice( @$catchClauses, $i, 2, $catchClauses->[$i+1]->() ); + $i -= 2; + redo CATCH; + } + + # Otherwise, check to see if the error's one of the ones we should catch + elsif ( $error->isa($pkg) ) { + + # Get the coderef to the handler + $handlerCode = $catchClauses->[$i+1]; + $keepTrying = 0; + + # Wrap the catch handler in an eval + $ok = eval { + if ( $wantarray ) { + @results = $handlerCode->( $error, \$keepTrying ); + } elsif ( defined($wantarray) ) { + $results[0] = $handlerCode->( $error, \$keepTrying ); + } else { + $handlerCode->( $error, \$keepTrying ); + } + 1; # Indicate success + }; + + # If the handler executed successfully, either keep + # trying (if the handler said to do so), or consider + # it handled and quit doing catches + if ( $ok ) { + next CATCHLOOP if $keepTrying; + undef $error; + } elsif ( $@ ) { + $error = $@; + $error = __PACKAGE__->new( "Exception in catch block: $error" ) unless ref $error; + } else { + $error = __PACKAGE__->new( "Mysterious error in catch block." ); + } + last CATCH; + } + } + } + + # Otherwise clause + if (defined( $owise = $clauses->{'otherwise'} )) { + + # Wrap the otherwise handler in an eval + my $ok = eval { + if ( $wantarray ) { + @results = $owise->( $error ); + } elsif (defined( $wantarray )) { + $results[0] = $owise->( $error ); + } else { + $owise->( $error ); + } + 1; # Indicate success + }; + + if ( $ok ) { + undef $error; + } elsif ( $@ ) { + $error = $@; + $error = __PACKAGE__->new( "Exception in otherwise block: $error" ) unless ref $error; + } else { + $error = __PACKAGE__->new( "Mysterious error in otherwise block." ); + } + } + } + } + + # Finally clause + $clauses->{finally}->() if exists $clauses->{finally} && defined $clauses->{finally}; + + # Propagate the error if it's still defined + $error->throw if defined $error; + + # Return the results + return $wantarray ? @results : $results[0]; +} + + +### METHOD: catch( $packageName, \&handlerCode[, \%clauses] ) +### Adds a catch clause with the specified handler code for the specified +### package onto the array of 'catch' clauses in the clauses given. If the +### clauses hashref is omitted, one is created. Returns the new or given clauses +### hashref with the new catch clause added. +sub catch { + my $pkg = shift; + my $code = shift; + my $clauses = shift || {}; + + $clauses->{catch} ||= []; + + unshift @{$clauses->{catch}}, $pkg, $code; + return $clauses; +} + + +sub with (&;$) { + return @_; # Does nothing except pass the clauses hash on +} + +sub finally (&) { + my $code = shift; + my $clauses = { 'finally' => $code }; + return $clauses; +} + +### The except clause is a block which returns a hashref or a list of +### key-value pairs, where the keys are the classes and the values are subs. +sub except (&;$) { + my $code = shift; + my $clauses = shift || {}; + + $clauses->{catch} ||= []; + + # Build the coderef that'll return the hash of handlers + my $handler = sub { + my $arg = shift; + + my $handlers; + my ( @array ) = $code->( $arg ); + + if ( @array == 1 && ref $array[0] ) { + $handlers = $array[0]; + $handlers = [ %$handlers ] if ref $handlers eq 'HASH'; + } else { + $handlers = \@array; + } + + return @$handlers; + }; + + # Stick the handler onto the front of the listref with an undef as the package + # to alert the try function that this is an except block + unshift @{$clauses->{catch}}, undef, $code; + + # Pass the clauses on + return $clauses; +} + +sub otherwise (&;$) { + my $code = shift; + my $clauses = shift || {}; + + croak "Multiple otherwise clauses" if exists $clauses->{'otherwise'}; + $clauses->{otherwise} = $code; + + return $clauses; +} + +END {} +DESTROY {} + + +############################################################################### +### D E R I V E D E X C E P T I O N C L A S S E S +############################################################################### + +### +### General exceptions +### + +### (EXCEPTION) CLASS: Danga::MethodError +### Method invocation error +package Danga::MethodError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'method invocation'; + +### (EXCEPTION) CLASS: Danga::FileIOError +### File I/O error +package Danga::FileIOError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'file I/O'; + +### (EXCEPTION) CLASS: Danga::EvalError +### Evaluation error +package Danga::EvalError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'evaluation'; + +### (EXCEPTION) CLASS: Danga::RecursionError +### Too deep recursion error +package Danga::RecursionError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'recursion'; + +### (EXCEPTION) CLASS: Danga::ConfigError +### Configuration file format/value error +package Danga::ConfigError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'configuration'; + +### (EXCEPTION) CLASS: Danga::ParseError +### Configuration/component parse error +package Danga::ParseError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'parse'; + +### (EXCEPTION) CLASS: Danga::UnimplementedMethodError +### Exception thrown when a virtual method is used. +package Danga::UnimplementedMethodError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'unimplemented method'; + +### (EXCEPTION) CLASS: Danga::UnimplementedMethodError +### Exception thrown when instantiation is attempted of an abstract class. +package Danga::InstantiationError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'instantiation'; + +sub new { + my $proto = shift; + my $errmsg = @_ ? join '', @_ : "Instantiation attempted of abstract class."; + local $Danga::Exception::Depth = $Danga::Exception::Depth + 1; + return $proto->SUPER::new( $errmsg ); +} + +### (EXCEPTION) CLASS: Danga::CommandError +### Exception thrown when a command run in the shell fails. +package Danga::CommandError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'command'; + + +### (EXCEPTION) CLASS: Danga::IncompleteObjectError +### Exception thrown when an operation is attempted on an object which does not +### have all the requisite information set. +package Danga::IncompleteObjectError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'incomplete object'; + +sub new { + my $proto = shift; + local $Danga::Exception::Depth = $Danga::Exception::Depth + 1; + + my $errmsg; + if ( @_ == 2 ) { $errmsg = sprintf("Cannot %s: Missing '%s'", @_) } + else { $errmsg = join('', @_) } + + return $proto->SUPER::new( $errmsg ); +} + +### (EXCEPTION) CLASS: Danga::ParamError +### Parameter missing or invalid error. This exception type accepts arguments in +### three different patterns which form three kinds of error message: +### +### =over 4 +### +### =item C +### +### Forms an error message like: +### +### Missing or undefined argument B<1>: B. +### +### =item C' parameter: Expected one of B, B, got a simple scalar +### +### =back +package Danga::ParamError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'parameter'; + +sub new { + my $proto = shift; + + my $errmsg; + + # Two-arg syntax when the first arg's a number indicates a missing or + # undefined parameter. + if ( @_ == 2 && $_[0] =~ m{^[0-9]+$} ) { + my ( $position, $paramName ) = @_; + + $errmsg = sprintf( 'Missing or undefined argument %s: %s', + $position, + ucfirst $paramName ); + } + + # Three-arg syntax indicates an illegal param + elsif ( @_ == 3 && ref $_[1] eq 'ARRAY' ) { + my ( $paramName, $legalValues, $actualValue ) = @_; + + if ( @$legalValues > 1 ) { + $errmsg = sprintf( q{Illegal '%s' parameter: Expected one of %s, got a %s}, + $paramName, + join(', ', @$legalValues), + (ref $actualValue ? ref $actualValue : "simple scalar") ); + } else { + $errmsg = sprintf( q{Illegal '%s' parameter: Expected a %s, got a %s}, + $paramName, + $legalValues->[0], + (ref $actualValue ? ref $actualValue : "simple scalar") ); + } + } + + else { + $errmsg = @_ ? join( '', @_ ) : 'Illegal parameter'; + $errmsg = ucfirst $errmsg; + } + + local $Danga::Exception::Depth = $Danga::Exception::Depth + 1; + return $proto->SUPER::new( $errmsg ); +} + + +### Event errors + +### (EXCEPTION) CLASS: Danga::UnhandledEventError +### Exception thrown when an unhandled event is received by a job. +package Danga::UnhandledEventError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'unhandled event'; + +sub new { + my $proto = shift; + my $event = shift or return $proto->SUPER::new( "Unhandled event: Unknown event" ); + + return $proto->SUPER::new( sprintf "Unhandled %s event", ref $event ); +} + + +### Database errors + +### (EXCEPTION) CLASS: Danga::DatabaseError +### Exception thrown when a database error occurs. If no argument is given, the +### default is built out of the current value of $DBI::errstr. +package Danga::DatabaseError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'database'; + +sub new { + my $proto = shift; + my $errmsg = @_ ? join( '', @_ ) : $DBI::errstr; + + return $proto->SUPER::new( $errmsg ); +} + +### (EXCEPTION) CLASS: Danga::SqlError +### Exception thrown when a database error occurs while preparing or executing a +### database operation. A DBI::Dbh or DBI::Sth object may be passed as the +### argument, in which case the result of calling C on the object will +### be used to build an error message. +package Danga::SqlError; +use strict; +use Scalar::Util qw{blessed}; +use base 'Danga::DatabaseError'; +our $ErrorType = 'SQL'; + +sub new { + my $proto = shift; + my @args = @_; + + if ( blessed $args[0] && ($args[0]->isa('DBI::db') || $args[0]->isa('DBI::st')) ) { + my $h = shift @args; + my $errmsg = sprintf( 'While %s (%s): %s', + $h->isa('DBI::db') ? 'preparing' : 'executing', + $h->{Statement}, + $h->errstr, + ); + unshift @args, $errmsg; + } + + return $proto->SUPER::new( join('', @args) ); +} + + +### (EXCEPTION) CLASS: Danga::ValidationError +### Exception thrown (or more likely, simply returned) when a parameter given to +### a CGI fails to untaint+validate. +package Danga::ValidationError; +use strict; +use base 'Danga::Exception'; +our $ErrorType = 'validation'; + + + +### Module require return value +1; + + + + +### AUTOGENERATED DOCUMENTATION FOLLOWS + +=head1 CLASSES + +=head2 Exception Classes + +=over 4 + +=item I + +Exception thrown when a command run in the shell fails. + +=item I + +Configuration file format/value error + +=item I + +Exception thrown when a database error occurs. If no argument is given, the +default is built out of the current value of $DBI::errstr. + +=item I + +Evaluation error + +=item I + +File I/O error + +=item I + +Exception thrown when an operation is attempted on an object which does not +have all the requisite information set. + +=item I + +Method invocation error + +=item I + +Parameter missing or invalid error. This exception type accepts arguments in +three different patterns which form three kinds of error message: + +=item I + +Configuration/component parse error + +=item I + +Too deep recursion error + +=item I + +Exception thrown when a database error occurs while preparing or executing a +database operation. A DBI::Dbh or DBI::Sth object may be passed as the +argument, in which case the result of calling C on the object will +be used to build an error message. + +=item I + +Exception thrown when an unhandled event is received by a job. + +=item I + +Exception thrown when instantiation is attempted of an abstract class. + +=back + +=head1 FUNCTIONS + +=over 4 + +=item I + +The I will be evaluated and if no error condition arises, this +function returns the result. I is a hash of code +references that describe what actions to take if a error occurs. It is +typically built by appending one or more C, C, or +C clauses. + +=back + +=head1 METHODS + +=over 4 + +=item I + +A wrapper for stringify() + +=item I + +Adds a catch clause with the specified handler code for the specified +package onto the array of 'catch' clauses in the clauses given. If the +clauses hashref is omitted, one is created. Returns the new or given clauses +hashref with the new catch clause added. + +=item I + +Returns the stack frame from frameNumber levels deep in the call stack. The +frame is a hash (or hashref if called in scalar context) of the form: + +=item I + +Returns an array of stack frames of the format returned by C +that describe the stack trace at the moment the exception was thrown. + +=item I + +Returns the stacktrace and error message or the exception as a human-readable string. + +=item I + +Create a new C object with I and C with it. This +will be caught by any enclosing C blocks. If not enclosed by a +C, calling this method will cause a fatal exception. + +This method is a modified version of the synonymous one in Error.pm. + +=back + +=head2 Autoloaded Methods + +=over 4 + +=item I + +Get/set the error message. + +=item I + +Get/set the error type. + +=back + +=head2 Constructor Methods + +=over 4 + +=item I + +Returns a new Danga::Exception object with the error message +specified, or 'Unspecified error' if none is specified. + +=back + +=cut + diff --git a/wcmtools/lib/Danga-Exceptions/t/basic.t b/wcmtools/lib/Danga-Exceptions/t/basic.t new file mode 100755 index 0000000..6cdf195 --- /dev/null +++ b/wcmtools/lib/Danga-Exceptions/t/basic.t @@ -0,0 +1,166 @@ +#!/usr/bin/perl -w +# +# Test script for Danga::Exceptions +# $Id: basic.t,v 1.1 2004/06/04 22:06:28 deveiant Exp $ +# +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl 02_exceptions.t' +# +# Please do not commit any changes you make to the module without a +# successful 'make test'! +# +package main; +use strict; + +BEGIN { $| = 1; } + +### Load up the test framework +use Test::SimpleUnit qw{:functions}; +Test::SimpleUnit::AutoskipFailedSetup( 1 ); + +use Danga::Exceptions qw{:syntax}; + +### Imported-symbol test-generation function +sub genTest { + my $functionName = shift; + return { + name => "Import $functionName", + test => sub { + no strict 'refs'; + assertDefined *{"main::${functionName}"}{CODE}, + "$functionName() was not imported"; + }, + }; +} + +### Test functions for throwing +sub simple_throw { + throw Danga::Exception "Simple throw exception."; +} +sub methoderror_throw { + throw Danga::MethodError "Method error."; +} + +### Build tests for imported syntax functions +my @synFuncTests = map { s{^&}{}; genTest $_ } @{$Danga::Exception::EXPORT_TAGS{syntax}}; + + +### Main test suite (in the order they're run) +my @testSuite = ( + + # Test for imported symbols first + @synFuncTests, + + # try + throw + catch + { + name => 'Simple throw', + test => sub { + try { + simple_throw(); + } catch Danga::Exception with { + my $except = shift; + assertInstanceOf 'Danga::Exception', $except; + }; + }, + }, + + # try + throw subclass + catch general class + { + name => 'Subclass throw - general handler', + test => sub { + try { + methoderror_throw(); + } catch Danga::Exception with { + my $except = shift; + assertInstanceOf 'Danga::MethodError', $except; + }; + }, + }, + + # try + throw subclass + catch subclass + catch general class(skipped) + { + name => 'Subclass throw - specific and general handlers', + test => sub { + my ( $sawSpecificHandler, $sawGeneralHandler ); + + try { + methoderror_throw(); + } catch Danga::MethodError with { + $sawSpecificHandler = 1; + } catch Danga::Exception with { + $sawGeneralHandler = 1; + }; + + assertNot $sawGeneralHandler, "Saw general handler with preceeding specific handler"; + assert $sawSpecificHandler, "Didn't see specific handler"; + }, + }, + + # try + throw subclass + catch subclass + rethrow + catch general class + { + name => 'Subclass throw - specific handler with keeptrying', + test => sub { + my ( $sawSpecificHandler, $sawGeneralHandler ); + + try { + methoderror_throw(); + } catch Danga::MethodError with { + my ( $e, $keepTrying ) = @_; + assertRef 'SCALAR', $keepTrying; + $sawSpecificHandler = 1; + $$keepTrying = 1; + } catch Danga::Exception with { + $sawGeneralHandler = 1; + }; + + assert $sawGeneralHandler, + "Didn't see general handler after setting \$keeptrying from ". + "preceeding specific handler"; + assert $sawSpecificHandler, + "Didn't see specific handler"; + }, + }, + + # try + catch + with + otherwise + { + name => "Throw with otherwise", + test => sub { + my ( $seenCatch, $seenOtherwise ); + try { + simple_throw(); + } catch Danga::MethodError with { + $seenCatch = 1; + } otherwise { + $seenOtherwise = 1; + }; + + assert $seenOtherwise; + assertNot $seenCatch; + }, + }, + + + ### finally + { + name => "Throw with finally", + test => sub { + my ( $sawHandler, $sawFinally ); + + try { + simple_throw(); + } catch Danga::Exception with { + $sawHandler = 1; + } finally { + $sawFinally = 1; + }; + + assert $sawHandler, "Didn't see handler"; + assert $sawFinally, "Didn't see finally clause."; + }, + }, + + +); + +runTests( @testSuite ); + diff --git a/wcmtools/lib/Danga-Socket/CHANGES b/wcmtools/lib/Danga-Socket/CHANGES new file mode 100755 index 0000000..012fe13 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/CHANGES @@ -0,0 +1,56 @@ +1.43: + -- don't even try epoll if not on a known/tested arch + -- updated POD docs + +1.42: + -- use the right epoll system call numbers on non-x86 + machines + -- start of a good test suite + -- 64-bit struct support (test suite passes on ia64, ppc) + (and presumably ppc64, but yet untested) + + +1.41: + -- make the Poll mode behave like Epoll/Kqueue in that + fds returned w/ no corresponding Danga::Socket object + or OtherFds coderef just get ignored. make it robust + against apps with races, perhaps? patch from Justin Azoff + + +1.40: + + -- Kqueue support from Matt Sergeant + +1.39: + + -- make BSD::Resource optional + +1.38: + + -- added support for profiling (epoll only at the moment while this + feature is further fleshed out); user application is required to + enable profiling and actually process the resultant data + + -- if epoll_wait returns an event we can't handle, delete it. + this means the application fucked up and lost its state somehow. + or maybe Danga::Socket did? still debugging this in Perlbal. + +1.25: (2004-10-22) + + -- move the syscall.ph require into "package main" rather than stealing + all its definitions into our namespace. now other modules can + use syscall.ph and Danga::Socket at the same time (as long as they're + also polite and load it into main) (NOTE: if you know a better way + to do this, let us know...) + +1.24: (2004-10-21) + + -- ability to steal the underlying socket from the Danga::Socket + object. this is useful if a caller wants to hold onto the socket + but destroy the Danga::Socket object (previously the Danga::Socket + close would close the underlying socket) + +1.22: (2004-10-21) + + -- minimal POD docs + -- first public release diff --git a/wcmtools/lib/Danga-Socket/MANIFEST b/wcmtools/lib/Danga-Socket/MANIFEST new file mode 100755 index 0000000..4029500 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/MANIFEST @@ -0,0 +1,9 @@ +Makefile.PL +CHANGES +MANIFEST +Socket.pm +META.yml Module meta-data (added by MakeMaker) +t/00-use.t +t/05-postloop.t +t/10-events.t + diff --git a/wcmtools/lib/Danga-Socket/MANIFEST.SKIP b/wcmtools/lib/Danga-Socket/MANIFEST.SKIP new file mode 100755 index 0000000..0a7cdf4 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/MANIFEST.SKIP @@ -0,0 +1,12 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists +\bdebian\b diff --git a/wcmtools/lib/Danga-Socket/META.yml b/wcmtools/lib/Danga-Socket/META.yml new file mode 100755 index 0000000..caddd4f --- /dev/null +++ b/wcmtools/lib/Danga-Socket/META.yml @@ -0,0 +1,15 @@ +# http://module-build.sourceforge.net/META-spec.html +#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# +name: Danga-Socket +version: 1.42 +version_from: Socket.pm +installdirs: site +requires: + fields: 0 + IO::Poll: 0 + POSIX: 0 + Socket: 0 + Test::More: 0 + +distribution_type: module +generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/wcmtools/lib/Danga-Socket/Makefile.PL b/wcmtools/lib/Danga-Socket/Makefile.PL new file mode 100755 index 0000000..961f8c4 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/Makefile.PL @@ -0,0 +1,35 @@ +#!/usr/bin/perl +# +# Perl Makefile for Danga-Socket +# $Id: Makefile.PL,v 1.6 2005/03/08 01:02:35 bradfitz Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Danga::Socket', + VERSION_FROM => 'Socket.pm', # finds $VERSION + AUTHOR => 'Brad Fitzpatrick ', + ABSTRACT => 'Async socket class', + PREREQ_PM => { + 'Socket' => 0, + 'IO::Poll' => 0, + fields => 0, + 'POSIX' => 0, + 'Test::More' => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag RELEASE_$(VERSION_SYM)', + SUFFIX => ".gz", + DIST_DEFAULT => 'all tardist', + COMPRESS => "gzip", + }, + +); + diff --git a/wcmtools/lib/Danga-Socket/Socket.pm b/wcmtools/lib/Danga-Socket/Socket.pm new file mode 100755 index 0000000..b048caa --- /dev/null +++ b/wcmtools/lib/Danga-Socket/Socket.pm @@ -0,0 +1,1170 @@ +########################################################################### + +=head1 NAME + +Danga::Socket - Event loop and event-driven async socket base class + +=head1 SYNOPSIS + + package My::Socket + use Danga::Socket; + use base ('Danga::Socket'); + use fields ('my_attribute'); + + sub new { + my My::Socket $self = shift; + $self = fields::new($self) unless ref $self; + $self->SUPER::new( @_ ); + + $self->{my_attribute} = 1234; + return $self; + } + + sub event_err { ... } + sub event_hup { ... } + sub event_write { ... } + sub event_read { ... } + sub close { ... } + + $my_sock->tcp_cork($bool); + + # write returns 1 if all writes have gone through, or 0 if there + # are writes in queue + $my_sock->write($scalar); + $my_sock->write($scalarref); + $my_sock->write(sub { ... }); # run when previous data written + $my_sock->write(undef); # kick-starts + + # read max $bytecount bytes, or undef on connection closed + $scalar_ref = $my_sock->read($bytecount); + + # watch for writability. not needed with ->write(). write() + # will automatically turn on watch_write when you wrote too much + # and turn it off when done + $my_sock->watch_write($bool); + + # watch for readability + $my_sock->watch_read($bool); + + # if you read too much and want to push some back on + # readable queue. (not incredibly well-tested) + $my_sock->push_back_read($buf); # scalar or scalar ref + + Danga::Socket->AddOtherFds(..); + Danga::Socket->SetLoopTimeout($millisecs); + Danga::Socket->DescriptorMap(); + Danga::Socket->WatchedSockets(); # count of DescriptorMap keys + Danga::Socket->SetPostLoopCallback($code); + Danga::Socket->EventLoop(); + +=head1 DESCRIPTION + +This is an abstract base class for objects backed by a socket which +provides the basic framework for event-driven asynchronous IO, +designed to be fast. Danga::Socket is both a base class for objects, +and an event loop. + +Callers subclass Danga::Socket. Danga::Socket's constructor registers +itself with the Danga::Socket event loop, and invokes callbacks on the +object for readability, writability, errors, and other conditions. + +Because Danga::Socket uses the "fields" module, your subclasses must +too. + +=head1 MORE INFO + +For now, see servers using Danga::Socket for guidance. For example: +perlbal, mogilefsd, or ddlockd. + +=head1 AUTHORS + +Brad Fitzpatrick - author + +Michael Granger - docs, testing + +Mark Smith - contributor, heavy user, testing + +Matt Sergeant - kqueue support + +=head1 BUGS + +Not documented enough. + +epoll is only used on Linux when the arch is one of x86, x86_64, ia64, +ppc, and ppc64. Mail me if you want to use this module with epoll +mode on something else. (ideally with a patch) + +=head1 LICENSE + +License is granted to use and distribute this module under the same +terms as Perl itself. + +=cut + +########################################################################### + +package Danga::Socket; +use strict; +use POSIX (); + +my $opt_bsd_resource = eval "use BSD::Resource; 1;"; + +use vars qw{$VERSION}; +$VERSION = "1.43"; + +use fields ('sock', # underlying socket + 'fd', # numeric file descriptor + 'write_buf', # arrayref of scalars, scalarrefs, or coderefs to write + 'write_buf_offset', # offset into first array of write_buf to start writing at + 'write_buf_size', # total length of data in all write_buf items + 'read_push_back', # arrayref of "pushed-back" read data the application didn't want + 'closed', # bool: socket is closed + 'corked', # bool: socket is corked + 'event_watch', # bitmask of events the client is interested in (POLLIN,OUT,etc.) + ); + +use Errno qw(EINPROGRESS EWOULDBLOCK EISCONN ENOTSOCK + EPIPE EAGAIN EBADF ECONNRESET ENOPROTOOPT); + +use Socket qw(IPPROTO_TCP); +use Carp qw{croak confess}; + +use constant TCP_CORK => 3; # FIXME: not hard-coded (Linux-specific too) + +use constant DebugLevel => 0; + +# Explicitly define the poll constants, as either one set or the other won't be +# loaded. They're also badly implemented in IO::Epoll: +# The IO::Epoll module is buggy in that it doesn't export constants efficiently +# (at least as of 0.01), so doing constants ourselves saves 13% of the user CPU +# time +use constant EPOLLIN => 1; +use constant EPOLLOUT => 4; +use constant EPOLLERR => 8; +use constant EPOLLHUP => 16; +use constant EPOLL_CTL_ADD => 1; +use constant EPOLL_CTL_DEL => 2; +use constant EPOLL_CTL_MOD => 3; + +use constant POLLIN => 1; +use constant POLLOUT => 4; +use constant POLLERR => 8; +use constant POLLHUP => 16; +use constant POLLNVAL => 32; + +our $HAVE_KQUEUE = eval { require IO::KQueue; 1 }; + +our ( + $HaveEpoll, # Flag -- is epoll available? initially undefined. + $HaveKQueue, + %DescriptorMap, # fd (num) -> Danga::Socket object + %PushBackSet, # fd (num) -> Danga::Socket (fds with pushed back read data) + $Epoll, # Global epoll fd (for epoll mode only) + $KQueue, # Global kqueue fd (for kqueue mode only) + @ToClose, # sockets to close when event loop is done + %OtherFds, # A hash of "other" (non-Danga::Socket) file + # descriptors for the event loop to track. + $PostLoopCallback, # subref to call at the end of each loop, if defined + $LoopTimeout, # timeout of event loop in milliseconds + $DoProfile, # if on, enable profiling + %Profiling, # what => [ utime, stime, calls ] + $TryEpoll, # whether epoll should be attempted to be used. + $DoneInit, # if we've done the one-time module init yet + ); + +Reset(); + +##################################################################### +### C L A S S M E T H O D S +##################################################################### + +# (CLASS) method: reset all state +sub Reset { + %DescriptorMap = (); + %PushBackSet = (); + @ToClose = (); + %OtherFds = (); + $PostLoopCallback = undef; + $LoopTimeout = -1; # no timeout by default + $DoProfile = 0; + %Profiling = (); +} + +### (CLASS) METHOD: HaveEpoll() +### Returns a true value if this class will use IO::Epoll for async IO. +sub HaveEpoll { $HaveEpoll }; + +### (CLASS) METHOD: WatchedSockets() +### Returns the number of file descriptors which are registered with the global +### poll object. +sub WatchedSockets { + return scalar keys %DescriptorMap; +} +*watched_sockets = *WatchedSockets; + +### (CLASS) METHOD: EnableProfiling() +### Turns profiling on, clearing current profiling data. +sub EnableProfiling { + if ($opt_bsd_resource) { + %Profiling = (); + $DoProfile = 1; + return 1; + } + return 0; +} + +### (CLASS) METHOD: DisableProfiling() +### Turns off profiling, but retains data up to this point +sub DisableProfiling { + $DoProfile = 0; +} + +### (CLASS) METHOD: ProfilingData() +### Returns reference to a hash of data in format above (see %Profiling) +sub ProfilingData { + return \%Profiling; +} + +### (CLASS) METHOD: ToClose() +### Return the list of sockets that are awaiting close() at the end of the +### current event loop. +sub ToClose { return @ToClose; } + +### (CLASS) METHOD: OtherFds( [%fdmap] ) +### Get/set the hash of file descriptors that need processing in parallel with +### the registered Danga::Socket objects. +sub OtherFds { + my $class = shift; + if ( @_ ) { %OtherFds = @_ } + return wantarray ? %OtherFds : \%OtherFds; +} + +### (CLASS) METHOD: AddOtherFds( [%fdmap] ) +### Add fds to the OtherFds hash for processing. +sub AddOtherFds { + my $class = shift; + %OtherFds = ( %OtherFds, @_ ); # FIXME investigate what happens on dupe fds + return wantarray ? %OtherFds : \%OtherFds; +} + +### (CLASS) METHOD: SetLoopTimeout( $timeout ) +### Set the loop timeout for the event loop to some value in milliseconds. +sub SetLoopTimeout { + return $LoopTimeout = $_[1] + 0; +} + +### (CLASS) METHOD: DescriptorMap() +### Get the hash of Danga::Socket objects keyed by the file descriptor they are +### wrapping. +sub DescriptorMap { + return wantarray ? %DescriptorMap : \%DescriptorMap; +} +*descriptor_map = *DescriptorMap; +*get_sock_ref = *DescriptorMap; + +sub init_poller +{ + return if $DoneInit; + $DoneInit = 1; + + if ($HAVE_KQUEUE) { + $KQueue = IO::KQueue->new(); + $HaveKQueue = $KQueue >= 0; + if ($HaveKQueue) { + *EventLoop = *KQueueEventLoop; + } + } + elsif ($TryEpoll) { + $Epoll = eval { epoll_create(1024); }; + $HaveEpoll = defined $Epoll && $Epoll >= 0; + if ($HaveEpoll) { + *EventLoop = *EpollEventLoop; + } + } + + if (!$HaveEpoll && !$HaveKQueue) { + require IO::Poll; + *EventLoop = *PollEventLoop; + } +} + +### FUNCTION: EventLoop() +### Start processing IO events. +sub EventLoop { + my $class = shift; + + init_poller(); + + if ($HaveEpoll) { + EpollEventLoop($class); + } elsif ($HaveKQueue) { + KQueueEventLoop($class); + } else { + PollEventLoop($class); + } +} + +## profiling-related data/functions +our ($Prof_utime0, $Prof_stime0); +sub _pre_profile { + ($Prof_utime0, $Prof_stime0) = getrusage(); +} + +sub _post_profile { + # get post information + my ($autime, $astime) = getrusage(); + + # calculate differences + my $utime = $autime - $Prof_utime0; + my $stime = $astime - $Prof_stime0; + + foreach my $k (@_) { + $Profiling{$k} ||= [ 0.0, 0.0, 0 ]; + $Profiling{$k}->[0] += $utime; + $Profiling{$k}->[1] += $stime; + $Profiling{$k}->[2]++; + } +} + +### The epoll-based event loop. Gets installed as EventLoop if IO::Epoll loads +### okay. +sub EpollEventLoop { + my $class = shift; + + foreach my $fd ( keys %OtherFds ) { + if (epoll_ctl($Epoll, EPOLL_CTL_ADD, $fd, EPOLLIN) == -1) { + print STDERR "epoll_ctl(): failure adding fd=$fd; $! (", $!+0, ")\n"; + } + } + + while (1) { + my @events; + my $i; + my $evcount; + # get up to 1000 events, class default timeout value + while (($evcount = epoll_wait($Epoll, 1000, $LoopTimeout, \@events)) >= 0) { + EVENT: + for ($i=0; $i<$evcount; $i++) { + my $ev = $events[$i]; + + # it's possible epoll_wait returned many events, including some at the end + # that ones in the front triggered unregister-interest actions. if we + # can't find the %sock entry, it's because we're no longer interested + # in that event. + my Danga::Socket $pob = $DescriptorMap{$ev->[0]}; + my $code; + my $state = $ev->[1]; + + # if we didn't find a Perlbal::Socket subclass for that fd, try other + # pseudo-registered (above) fds. + if (! $pob) { + if (my $code = $OtherFds{$ev->[0]}) { + $code->($state); + } else { + my $fd = $ev->[0]; + print STDERR "epoll() returned fd $fd w/ state $state for which we have no mapping. removing.\n"; + POSIX::close($fd); + epoll_ctl($Epoll, EPOLL_CTL_DEL, $fd, 0); + } + next; + } + + DebugLevel >= 1 && $class->DebugMsg("Event: fd=%d (%s), state=%d \@ %s\n", + $ev->[0], ref($pob), $ev->[1], time); + + if ($DoProfile) { + my $class = ref $pob; + + # call profiling action on things that need to be done + if ($state & EPOLLIN && ! $pob->{closed}) { + _pre_profile(); + $pob->event_read; + _post_profile("$class-read"); + } + + if ($state & EPOLLOUT && ! $pob->{closed}) { + _pre_profile(); + $pob->event_write; + _post_profile("$class-write"); + } + + if ($state & (EPOLLERR|EPOLLHUP)) { + if ($state & EPOLLERR && ! $pob->{closed}) { + _pre_profile(); + $pob->event_err; + _post_profile("$class-err"); + } + if ($state & EPOLLHUP && ! $pob->{closed}) { + _pre_profile(); + $pob->event_hup; + _post_profile("$class-hup"); + } + } + + next; + } + + # standard non-profiling codepat + $pob->event_read if $state & EPOLLIN && ! $pob->{closed}; + $pob->event_write if $state & EPOLLOUT && ! $pob->{closed}; + if ($state & (EPOLLERR|EPOLLHUP)) { + $pob->event_err if $state & EPOLLERR && ! $pob->{closed}; + $pob->event_hup if $state & EPOLLHUP && ! $pob->{closed}; + } + } + return unless PostEventLoop(); + + } + print STDERR "Event loop ending; restarting.\n"; + } + exit 0; +} + +sub PostEventLoop { + # fire read events for objects with pushed-back read data + my $loop = 1; + while ($loop) { + $loop = 0; + foreach my $fd (keys %PushBackSet) { + my Danga::Socket $pob = $PushBackSet{$fd}; + next unless (! $pob->{closed} && + $pob->{event_watch} & POLLIN); + $loop = 1; + $pob->event_read; + } + } + + # now we can close sockets that wanted to close during our event processing. + # (we didn't want to close them during the loop, as we didn't want fd numbers + # being reused and confused during the event loop) + $_->close while ($_ = shift @ToClose); + + # now we're at the very end, call callback if defined + if (defined $PostLoopCallback) { + return $PostLoopCallback->(\%DescriptorMap, \%OtherFds); + } + return 1; +} + +### The fallback IO::Poll-based event loop. Gets installed as EventLoop if +### IO::Epoll fails to load. +sub PollEventLoop { + my $class = shift; + + my Danga::Socket $pob; + + while (1) { + # the following sets up @poll as a series of ($poll,$event_mask) + # items, then uses IO::Poll::_poll, implemented in XS, which + # modifies the array in place with the even elements being + # replaced with the event masks that occured. + my @poll; + foreach my $fd ( keys %OtherFds ) { + push @poll, $fd, POLLIN; + } + while ( my ($fd, $sock) = each %DescriptorMap ) { + push @poll, $fd, $sock->{event_watch}; + } + + # if nothing to poll, either end immediately (if no timeout) + # or just keep calling the callback + unless (@poll) { + my $timeout = $LoopTimeout > 0 ? $LoopTimeout : 1000; + select undef, undef, undef, ($timeout / 1000); + return unless PostEventLoop(); + next; + } + + my $count = IO::Poll::_poll($LoopTimeout, @poll); + unless ($count) { + return unless PostEventLoop(); + next; + } + + # Fetch handles with read events + while (@poll) { + my ($fd, $state) = splice(@poll, 0, 2); + next unless $state; + + $pob = $DescriptorMap{$fd}; + + if (!$pob) { + if (my $code = $OtherFds{$fd}) { + $code->($state); + } + next; + } + + $pob->event_read if $state & POLLIN && ! $pob->{closed}; + $pob->event_write if $state & POLLOUT && ! $pob->{closed}; + $pob->event_err if $state & POLLERR && ! $pob->{closed}; + $pob->event_hup if $state & POLLHUP && ! $pob->{closed}; + } + + return unless PostEventLoop(); + } + + exit 0; +} + +### The kqueue-based event loop. Gets installed as EventLoop if IO::KQueue works +### okay. +sub KQueueEventLoop { + my $class = shift; + + foreach my $fd (keys %OtherFds) { + $KQueue->EV_SET($fd, IO::KQueue::EVFILT_READ(), IO::KQueue::EV_ADD()); + } + + while (1) { + my @ret = $KQueue->kevent($LoopTimeout); + if (!@ret) { + foreach my $fd ( keys %DescriptorMap ) { + my Danga::Socket $sock = $DescriptorMap{$fd}; + if ($sock->can('ticker')) { + $sock->ticker; + } + } + } + + foreach my $kev (@ret) { + my ($fd, $filter, $flags, $fflags) = @$kev; + my Danga::Socket $pob = $DescriptorMap{$fd}; + if (!$pob) { + if (my $code = $OtherFds{$fd}) { + $code->($filter); + } + next; + } + + DebugLevel >= 1 && $class->DebugMsg("Event: fd=%d (%s), flags=%d \@ %s\n", + $fd, ref($pob), $flags, time); + + $pob->event_read if $filter == IO::KQueue::EVFILT_READ() && !$pob->{closed}; + $pob->event_write if $filter == IO::KQueue::EVFILT_WRITE() && !$pob->{closed}; + if ($flags == IO::KQueue::EV_EOF() && !$pob->{closed}) { + if ($fflags) { + $pob->event_err; + } else { + $pob->event_hup; + } + } + } + return unless PostEventLoop(); + } + + exit(0); +} + +### (CLASS) METHOD: DebugMsg( $format, @args ) +### Print the debugging message specified by the C-style I and +### I +sub DebugMsg { + my ( $class, $fmt, @args ) = @_; + chomp $fmt; + printf STDERR ">>> $fmt\n", @args; +} + + +### METHOD: new( $socket ) +### Create a new Danga::Socket object for the given I which will react +### to events on it during the C. +sub new { + my Danga::Socket $self = shift; + $self = fields::new($self) unless ref $self; + + my $sock = shift; + + $self->{sock} = $sock; + my $fd = fileno($sock); + $self->{fd} = $fd; + $self->{write_buf} = []; + $self->{write_buf_offset} = 0; + $self->{write_buf_size} = 0; + $self->{closed} = 0; + $self->{corked} = 0; + $self->{read_push_back} = []; + + $self->{event_watch} = POLLERR|POLLHUP|POLLNVAL; + + init_poller(); + + if ($HaveEpoll) { + epoll_ctl($Epoll, EPOLL_CTL_ADD, $fd, $self->{event_watch}) + and die "couldn't add epoll watch for $fd\n"; + } + elsif ($HaveKQueue) { + # Add them to the queue but disabled for now + $KQueue->EV_SET($fd, IO::KQueue::EVFILT_READ(), + IO::KQueue::EV_ADD() | IO::KQueue::EV_DISABLE()); + $KQueue->EV_SET($fd, IO::KQueue::EVFILT_WRITE(), + IO::KQueue::EV_ADD() | IO::KQueue::EV_DISABLE()); + } + + $DescriptorMap{$fd} = $self; + return $self; +} + + + +##################################################################### +### I N S T A N C E M E T H O D S +##################################################################### + +### METHOD: tcp_cork( $boolean ) +### Turn TCP_CORK on or off depending on the value of I. +sub tcp_cork { + my Danga::Socket $self = $_[0]; + my $val = $_[1]; + + # make sure we have a socket + return unless $self->{sock}; + return if $val == $self->{corked}; + + # FIXME: Linux-specific. + my $rv = setsockopt($self->{sock}, IPPROTO_TCP, TCP_CORK, + pack("l", $val ? 1 : 0)); + + # if we failed, close (if we're not already) and warn about the error + if ($rv) { + $self->{corked} = $val; + } else { + if ($! == EBADF || $! == ENOTSOCK) { + # internal state is probably corrupted; warn and then close if + # we're not closed already + warn "setsockopt: $!"; + $self->close('tcp_cork_failed'); + } elsif ($! == ENOPROTOOPT) { + # TCP implementation doesn't support corking, so just ignore it + } else { + # some other error; we should never hit here, but if we do, die + die "setsockopt: $!"; + } + } +} + +### METHOD: steal_socket +### Basically returns our socket and makes it so that we don't try to close it, +### but we do remove it from epoll handlers. THIS CLOSES $self. It is the same +### thing as calling close, except it gives you the socket to use. +sub steal_socket { + my Danga::Socket $self = $_[0]; + return if $self->{closed}; + + # cleanup does most of the work of closing this socket + $self->_cleanup(); + + # now undef our internal sock and fd structures so we don't use them + my $sock = $self->{sock}; + $self->{sock} = undef; + return $sock; +} + +### METHOD: close( [$reason] ) +### Close the socket. The I argument will be used in debugging messages. +sub close { + my Danga::Socket $self = $_[0]; + return if $self->{closed}; + + # print out debugging info for this close + if (DebugLevel) { + my ($pkg, $filename, $line) = caller; + my $reason = $_[1] || ""; + print STDERR "Closing \#$self->{fd} due to $pkg/$filename/$line ($reason)\n"; + } + + # this does most of the work of closing us + $self->_cleanup(); + + # defer closing the actual socket until the event loop is done + # processing this round of events. (otherwise we might reuse fds) + if ($self->{sock}) { + push @ToClose, $self->{sock}; + $self->{sock} = undef; + } + + return 0; +} + +### METHOD: _cleanup() +### Called by our closers so we can clean internal data structures. +sub _cleanup { + my Danga::Socket $self = $_[0]; + + # we're effectively closed; we have no fd and sock when we leave here + $self->{closed} = 1; + + # we need to flush our write buffer, as there may + # be self-referential closures (sub { $client->close }) + # preventing the object from being destroyed + $self->{write_buf} = []; + + # uncork so any final data gets sent. only matters if the person closing + # us forgot to do it, but we do it to be safe. + $self->tcp_cork(0); + + # if we're using epoll, we have to remove this from our epoll fd so we stop getting + # notifications about it + if ($HaveEpoll && $self->{fd}) { + if (epoll_ctl($Epoll, EPOLL_CTL_DEL, $self->{fd}, $self->{event_watch}) != 0) { + # dump_error prints a backtrace so we can try to figure out why this happened + $self->dump_error("epoll_ctl(): failure deleting fd=$self->{fd} during _cleanup(); $! (" . ($!+0) . ")"); + } + } + + # now delete from mappings. this fd no longer belongs to us, so we don't want + # to get alerts for it if it becomes writable/readable/etc. + delete $DescriptorMap{$self->{fd}}; + delete $PushBackSet{$self->{fd}}; + + # and finally get rid of our fd so we can't use it anywhere else + $self->{fd} = undef; +} + +### METHOD: sock() +### Returns the underlying IO::Handle for the object. +sub sock { + my Danga::Socket $self = shift; + return $self->{sock}; +} + + +### METHOD: write( $data ) +### Write the specified data to the underlying handle. I may be scalar, +### scalar ref, code ref (to run when there), or undef just to kick-start. +### Returns 1 if writes all went through, or 0 if there are writes in queue. If +### it returns 1, caller should stop waiting for 'writable' events) +sub write { + my Danga::Socket $self; + my $data; + ($self, $data) = @_; + + # nobody should be writing to closed sockets, but caller code can + # do two writes within an event, have the first fail and + # disconnect the other side (whose destructor then closes the + # calling object, but it's still in a method), and then the + # now-dead object does its second write. that is this case. we + # just lie and say it worked. it'll be dead soon and won't be + # hurt by this lie. + return 1 if $self->{closed}; + + my $bref; + + # just queue data if there's already a wait + my $need_queue; + + if (defined $data) { + $bref = ref $data ? $data : \$data; + if ($self->{write_buf_size}) { + push @{$self->{write_buf}}, $bref; + $self->{write_buf_size} += ref $bref eq "SCALAR" ? length($$bref) : 1; + return 0; + } + + # this flag says we're bypassing the queue system, knowing we're the + # only outstanding write, and hoping we don't ever need to use it. + # if so later, though, we'll need to queue + $need_queue = 1; + } + + WRITE: + while (1) { + return 1 unless $bref ||= $self->{write_buf}[0]; + + my $len; + eval { + $len = length($$bref); # this will die if $bref is a code ref, caught below + }; + if ($@) { + if (ref $bref eq "CODE") { + unless ($need_queue) { + $self->{write_buf_size}--; # code refs are worth 1 + shift @{$self->{write_buf}}; + } + $bref->(); + + # code refs are just run and never get reenqueued + # (they're one-shot), so turn off the flag indicating the + # outstanding data needs queueing. + $need_queue = 0; + + undef $bref; + next WRITE; + } + die "Write error: $@ <$bref>"; + } + + my $to_write = $len - $self->{write_buf_offset}; + my $written = syswrite($self->{sock}, $$bref, $to_write, $self->{write_buf_offset}); + + if (! defined $written) { + if ($! == EPIPE) { + return $self->close("EPIPE"); + } elsif ($! == EAGAIN) { + # since connection has stuff to write, it should now be + # interested in pending writes: + if ($need_queue) { + push @{$self->{write_buf}}, $bref; + $self->{write_buf_size} += $len; + } + $self->watch_write(1); + return 0; + } elsif ($! == ECONNRESET) { + return $self->close("ECONNRESET"); + } + + DebugLevel >= 1 && $self->debugmsg("Closing connection ($self) due to write error: $!\n"); + + return $self->close("write_error"); + } elsif ($written != $to_write) { + DebugLevel >= 2 && $self->debugmsg("Wrote PARTIAL %d bytes to %d", + $written, $self->{fd}); + if ($need_queue) { + push @{$self->{write_buf}}, $bref; + $self->{write_buf_size} += $len; + } + # since connection has stuff to write, it should now be + # interested in pending writes: + $self->{write_buf_offset} += $written; + $self->{write_buf_size} -= $written; + $self->watch_write(1); + return 0; + } elsif ($written == $to_write) { + DebugLevel >= 2 && $self->debugmsg("Wrote ALL %d bytes to %d (nq=%d)", + $written, $self->{fd}, $need_queue); + $self->{write_buf_offset} = 0; + + # this was our only write, so we can return immediately + # since we avoided incrementing the buffer size or + # putting it in the buffer. we also know there + # can't be anything else to write. + return 1 if $need_queue; + + $self->{write_buf_size} -= $written; + shift @{$self->{write_buf}}; + undef $bref; + next WRITE; + } + } +} + +### METHOD: push_back_read( $buf ) +### Push back I (a scalar or scalarref) into the read stream +sub push_back_read { + my Danga::Socket $self = shift; + my $buf = shift; + push @{$self->{read_push_back}}, ref $buf ? $buf : \$buf; + $PushBackSet{$self->{fd}} = $self; +} + +### METHOD: read( $bytecount ) +### Read at most I bytes from the underlying handle; returns scalar +### ref on read, or undef on connection closed. +sub read { + my Danga::Socket $self = shift; + my $bytes = shift; + my $buf; + my $sock = $self->{sock}; + + if (@{$self->{read_push_back}}) { + $buf = shift @{$self->{read_push_back}}; + my $len = length($$buf); + if ($len <= $buf) { + unless (@{$self->{read_push_back}}) { + delete $PushBackSet{$self->{fd}}; + } + return $buf; + } else { + # if the pushed back read is too big, we have to split it + my $overflow = substr($$buf, $bytes); + $buf = substr($$buf, 0, $bytes); + unshift @{$self->{read_push_back}}, \$overflow, + return \$buf; + } + } + + my $res = sysread($sock, $buf, $bytes, 0); + DebugLevel >= 2 && $self->debugmsg("sysread = %d; \$! = %d", $res, $!); + + if (! $res && $! != EWOULDBLOCK) { + # catches 0=conn closed or undef=error + DebugLevel >= 2 && $self->debugmsg("Fd \#%d read hit the end of the road.", $self->{fd}); + return undef; + } + + return \$buf; +} + + +### (VIRTUAL) METHOD: event_read() +### Readable event handler. Concrete deriviatives of Danga::Socket should +### provide an implementation of this. The default implementation will die if +### called. +sub event_read { die "Base class event_read called for $_[0]\n"; } + + +### (VIRTUAL) METHOD: event_err() +### Error event handler. Concrete deriviatives of Danga::Socket should +### provide an implementation of this. The default implementation will die if +### called. +sub event_err { die "Base class event_err called for $_[0]\n"; } + + +### (VIRTUAL) METHOD: event_hup() +### 'Hangup' event handler. Concrete deriviatives of Danga::Socket should +### provide an implementation of this. The default implementation will die if +### called. +sub event_hup { die "Base class event_hup called for $_[0]\n"; } + + +### METHOD: event_write() +### Writable event handler. Concrete deriviatives of Danga::Socket may wish to +### provide an implementation of this. The default implementation calls +### C with an C. +sub event_write { + my $self = shift; + $self->write(undef); +} + + +### METHOD: watch_read( $boolean ) +### Turn 'readable' event notification on or off. +sub watch_read { + my Danga::Socket $self = shift; + return if $self->{closed} || !$self->{sock}; + + my $val = shift; + my $event = $self->{event_watch}; + + $event &= ~POLLIN if ! $val; + $event |= POLLIN if $val; + + # If it changed, set it + if ($event != $self->{event_watch}) { + if ($HaveKQueue) { + $KQueue->EV_SET($self->{fd}, IO::KQueue::EVFILT_READ(), + $val ? IO::KQueue::EV_ENABLE() : IO::KQueue::EV_DISABLE()); + } + elsif ($HaveEpoll) { + epoll_ctl($Epoll, EPOLL_CTL_MOD, $self->{fd}, $event) + and $self->dump_error("couldn't modify epoll settings for $self->{fd} " . + "from $self->{event_watch} -> $event: $! (" . ($!+0) . ")"); + } + $self->{event_watch} = $event; + } +} + +### METHOD: watch_write( $boolean ) +### Turn 'writable' event notification on or off. +sub watch_write { + my Danga::Socket $self = shift; + return if $self->{closed} || !$self->{sock}; + + my $val = shift; + my $event = $self->{event_watch}; + + $event &= ~POLLOUT if ! $val; + $event |= POLLOUT if $val; + + # If it changed, set it + if ($event != $self->{event_watch}) { + if ($HaveKQueue) { + $KQueue->EV_SET($self->{fd}, IO::KQueue::EVFILT_WRITE(), + $val ? IO::KQueue::EV_ENABLE() : IO::KQueue::EV_DISABLE()); + } + elsif ($HaveEpoll) { + epoll_ctl($Epoll, EPOLL_CTL_MOD, $self->{fd}, $event) + and $self->dump_error("couldn't modify epoll settings for $self->{fd} " . + "from $self->{event_watch} -> $event: $! (" . ($!+0) . ")"); + } + $self->{event_watch} = $event; + } +} + +# METHOD: dump_error( $message ) +# Prints to STDERR a backtrace with information about this socket and what lead +# up to the dump_error call. +sub dump_error { + my $i = 0; + my @list; + while (my ($file, $line, $sub) = (caller($i++))[1..3]) { + push @list, "\t$file:$line called $sub\n"; + } + + print STDERR "ERROR: $_[1]\n" . + "\t$_[0] = " . $_[0]->as_string . "\n" . + join('', @list); +} + + +### METHOD: debugmsg( $format, @args ) +### Print the debugging message specified by the C-style I and +### I if the object's C is greater than or equal to the given +### I. +sub debugmsg { + my ( $self, $fmt, @args ) = @_; + confess "Not an object" unless ref $self; + + chomp $fmt; + printf STDERR ">>> $fmt\n", @args; +} + + +### METHOD: peer_ip_string() +### Returns the string describing the peer's IP +sub peer_ip_string { + my Danga::Socket $self = shift; + return undef unless $self->{sock}; + my $pn = getpeername($self->{sock}) or return undef; + my ($port, $iaddr) = Socket::sockaddr_in($pn); + return Socket::inet_ntoa($iaddr); +} + +### METHOD: peer_addr_string() +### Returns the string describing the peer for the socket which underlies this +### object in form "ip:port" +sub peer_addr_string { + my Danga::Socket $self = shift; + return undef unless $self->{sock}; + my $pn = getpeername($self->{sock}) or return undef; + my ($port, $iaddr) = Socket::sockaddr_in($pn); + return Socket::inet_ntoa($iaddr) . ":$port"; +} + +### METHOD: as_string() +### Returns a string describing this socket. +sub as_string { + my Danga::Socket $self = shift; + my $rw = "(" . ($self->{event_watch} & POLLIN ? 'R' : '') . + ($self->{event_watch} & POLLOUT ? 'W' : '') . ")"; + my $ret = ref($self) . "$rw: " . ($self->{closed} ? "closed" : "open"); + my $peer = $self->peer_addr_string; + if ($peer) { + $ret .= " to " . $self->peer_addr_string; + } + return $ret; +} + +### CLASS METHOD: SetPostLoopCallback +### Sets post loop callback function. Pass a subref and it will be +### called every time the event loop finishes. Return 1 from the sub +### to make the loop continue, else it will exit. The function will +### be passed two parameters: \%DescriptorMap, \%OtherFds. +sub SetPostLoopCallback { + my ($class, $ref) = @_; + $PostLoopCallback = (defined $ref && ref $ref eq 'CODE') ? $ref : undef; +} + +##################################################################### +### U T I L I T Y F U N C T I O N S +##################################################################### + +our ($SYS_epoll_create, $SYS_epoll_ctl, $SYS_epoll_wait); + +if ($^O eq "linux") { + my ($sysname, $nodename, $release, $version, $machine) = POSIX::uname(); + + # whether the machine requires 64-bit numbers to be on 8-byte + # boundaries. + my $u64_mod_8 = 0; + + if ($machine =~ m/^i[3456]86$/) { + $SYS_epoll_create = 254; + $SYS_epoll_ctl = 255; + $SYS_epoll_wait = 256; + } elsif ($machine eq "x86_64") { + $SYS_epoll_create = 213; + $SYS_epoll_ctl = 233; + $SYS_epoll_wait = 232; + } elsif ($machine eq "ppc64") { + $SYS_epoll_create = 236; + $SYS_epoll_ctl = 237; + $SYS_epoll_wait = 238; + $u64_mod_8 = 1; + } elsif ($machine eq "ppc") { + $SYS_epoll_create = 236; + $SYS_epoll_ctl = 237; + $SYS_epoll_wait = 238; + $u64_mod_8 = 1; + } elsif ($machine eq "ia64") { + $SYS_epoll_create = 1243; + $SYS_epoll_ctl = 1244; + $SYS_epoll_wait = 1245; + $u64_mod_8 = 1; + } + + if ($u64_mod_8) { + *epoll_wait = \&epoll_wait_mod8; + *epoll_ctl = \&epoll_ctl_mod8; + } else { + *epoll_wait = \&epoll_wait_mod4; + *epoll_ctl = \&epoll_ctl_mod4; + } + + # if syscall numbers have been defined (and this module has been + # tested on) the arch above, then try to use it. try means see if + # the syscall is implemented. it may well be that this is Linux + # 2.4 and we don't even have it available. + $TryEpoll = 1 if $SYS_epoll_create; +} + +# epoll_create wrapper +# ARGS: (size) +sub epoll_create { + my $epfd = eval { syscall($SYS_epoll_create, $_[0]) }; + return -1 if $@; + return $epfd; +} + +# epoll_ctl wrapper +# ARGS: (epfd, op, fd, events_mask) +sub epoll_ctl_mod4 { + syscall($SYS_epoll_ctl, $_[0]+0, $_[1]+0, $_[2]+0, pack("LLL", $_[3], $_[2], 0)); +} +sub epoll_ctl_mod8 { + syscall($SYS_epoll_ctl, $_[0]+0, $_[1]+0, $_[2]+0, pack("LLLL", $_[3], 0, $_[2], 0)); +} + +# epoll_wait wrapper +# ARGS: (epfd, maxevents, timeout (milliseconds), arrayref) +# arrayref: values modified to be [$fd, $event] +our $epoll_wait_events; +our $epoll_wait_size = 0; +sub epoll_wait_mod4 { + # resize our static buffer if requested size is bigger than we've ever done + if ($_[1] > $epoll_wait_size) { + $epoll_wait_size = $_[1]; + $epoll_wait_events = "\0" x 12 x $epoll_wait_size; + } + my $ct = syscall($SYS_epoll_wait, $_[0]+0, $epoll_wait_events, $_[1]+0, $_[2]+0); + for ($_ = 0; $_ < $ct; $_++) { + @{$_[3]->[$_]}[1,0] = unpack("LL", substr($epoll_wait_events, 12*$_, 8)); + } + return $ct; +} + +sub epoll_wait_mod8 { + # resize our static buffer if requested size is bigger than we've ever done + if ($_[1] > $epoll_wait_size) { + $epoll_wait_size = $_[1]; + $epoll_wait_events = "\0" x 16 x $epoll_wait_size; + } + my $ct = syscall($SYS_epoll_wait, $_[0]+0, $epoll_wait_events, $_[1]+0, $_[2]+0); + for ($_ = 0; $_ < $ct; $_++) { + # 16 byte epoll_event structs, with format: + # 4 byte mask [idx 1] + # 4 byte padding (we put it into idx 2, useless) + # 8 byte data (first 4 bytes are fd, into idx 0) + @{$_[3]->[$_]}[1,2,0] = unpack("LLL", substr($epoll_wait_events, 16*$_, 12)); + } + return $ct; +} + +1; + + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/lib/Danga-Socket/debian/changelog b/wcmtools/lib/Danga-Socket/debian/changelog new file mode 100755 index 0000000..889ef67 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/changelog @@ -0,0 +1,17 @@ +libdanga-socket-perl (1.40-1) unstable; urgency=low + + * New upstream version + + -- Jay Bonci Tue, 5 Apr 2005 15:33:34 -0400 + +libdanga-socket-perl (1.38-1) unstable; urgency=low + + * New upstream version + + -- Jay Bonci Wed, 9 Feb 2005 02:32:07 -0500 + +libdanga-socket-perl (1.25-1) unstable; urgency=low + + * Initial release + + -- Jay Bonci Thu, 13 Jan 2005 23:13:18 -0500 diff --git a/wcmtools/lib/Danga-Socket/debian/compat b/wcmtools/lib/Danga-Socket/debian/compat new file mode 100755 index 0000000..b8626c4 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/compat @@ -0,0 +1 @@ +4 diff --git a/wcmtools/lib/Danga-Socket/debian/control b/wcmtools/lib/Danga-Socket/debian/control new file mode 100755 index 0000000..16ab362 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/control @@ -0,0 +1,13 @@ +Source: libdanga-socket-perl +Section: perl +Priority: optional +Maintainer: Jay Bonci +Build-Depends-Indep: debhelper (>= 4.1.40), perl (>= 5.8.4) +Standards-Version: 3.6.1.0 + +Package: libdanga-socket-perl +Architecture: all +Depends: ${perl:Depends} +Description: fast pure-perl asyncronous socket base class + Danga::Socket is an abstract base class which provides the basic framework for + event-driven asynchronous IO, designed to be fast. diff --git a/wcmtools/lib/Danga-Socket/debian/copyright b/wcmtools/lib/Danga-Socket/debian/copyright new file mode 100755 index 0000000..467e23c --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/copyright @@ -0,0 +1,26 @@ +This package was debianized by Jay Bonci on +Thu Jan 13 23:18:32 EST 2005 + +It was downloaded from: http://www.danga.com/dist/Danga-Socket/ + +Upstream Authors: + Brad Fitzpatrick + Michael Granger + Mark Smith + +Copyright: + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or + + b) the "Artistic License" + + See: + + /usr/share/common-licenses/Artistic + /usr/share/common-licenses/GPL + + For more information regarding these licensing options diff --git a/wcmtools/lib/Danga-Socket/debian/rules b/wcmtools/lib/Danga-Socket/debian/rules new file mode 100755 index 0000000..9164ffb --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/rules @@ -0,0 +1,53 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatibility version to use. +# export DH_COMPAT=4 + +#PACKAGE=`pwd | sed -e "s/.*\/\\(.*\\)-.*/\\1/"` +PACKAGE=`cat debian/control | perl -ne 'print if s/Package: (.*)/$$1/'` + +build: + dh_testdir + # Add here commands to compile the package. + perl Makefile.PL verbose INSTALLDIRS=vendor +clean: + dh_testdir + dh_testroot + + -$(MAKE) clean + rm -f Makefile.old + dh_clean + +install: + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + $(MAKE) PREFIX=$(CURDIR)/debian/$(PACKAGE)/usr OPTIMIZE="-O2 -g -Wall" test install + -find $(CURDIR)/debian -type d | xargs rmdir -p --ignore-fail-on-non-empty + +binary-arch:; +binary-indep: build install + dh_testdir + dh_testroot + dh_installdocs + dh_installman + dh_installchangelogs CHANGES + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_perl + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/wcmtools/lib/Danga-Socket/debian/watch b/wcmtools/lib/Danga-Socket/debian/watch new file mode 100755 index 0000000..35b41e0 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/debian/watch @@ -0,0 +1,3 @@ +version=2 +http://www.danga.com/dist/Danga-Socket/Danga-Socket-([0-9].*)\.tar.gz \ + debian uupdate diff --git a/wcmtools/lib/Danga-Socket/t/00-use.t b/wcmtools/lib/Danga-Socket/t/00-use.t new file mode 100755 index 0000000..8515eff --- /dev/null +++ b/wcmtools/lib/Danga-Socket/t/00-use.t @@ -0,0 +1,8 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More tests => 1; + +my $mod = "Danga::Socket"; + +use_ok($mod); diff --git a/wcmtools/lib/Danga-Socket/t/05-postloop.t b/wcmtools/lib/Danga-Socket/t/05-postloop.t new file mode 100755 index 0000000..e472e0b --- /dev/null +++ b/wcmtools/lib/Danga-Socket/t/05-postloop.t @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More 'no_plan'; +use Danga::Socket; + +my ($t1, $t2, $iters); + +$t1 = time(); +$iters = 0; + +Danga::Socket->SetLoopTimeout(250); +Danga::Socket->SetPostLoopCallback(sub { + $iters++; + return $iters < 4 ? 1 : 0; +}); + +Danga::Socket->EventLoop; + +$t2 = time(); + +ok($iters == 4, "four iters"); +ok($t2 == $t1 + 1, "took a second"); + diff --git a/wcmtools/lib/Danga-Socket/t/10-events.t b/wcmtools/lib/Danga-Socket/t/10-events.t new file mode 100755 index 0000000..b662cb5 --- /dev/null +++ b/wcmtools/lib/Danga-Socket/t/10-events.t @@ -0,0 +1,147 @@ +#!/usr/bin/perl -w + +use strict; +use Test::More tests => 24; +use Danga::Socket; +use IO::Socket::INET; +use POSIX; + +use vars qw($done); + +Danga::Socket::init_poller(); + +SKIP: { + my ($sysname, $nodename, $release, $version, $machine) = POSIX::uname(); + skip "not on linux 2.6", 1 if $^O ne "linux" || $version =~ /^2\.[01234]/; + ok(Danga::Socket->HaveEpoll(), "using epoll"); +} + + +for my $mode ("auto", "poll") { + $done = 0; + my $iters = 0; + is(Danga::Socket->WatchedSockets, 0, "no watched sockets"); + Danga::Socket->SetLoopTimeout(150); + Danga::Socket->SetPostLoopCallback(sub { + return 0 if $done; + $iters++; + ok(Server->new, "created server") if $iters == 1; + if ($iters == 3) { + ok(ClientOut->new, "created client outgoing"); + is(Danga::Socket->WatchedSockets, 2, "two watched sockets"); + } + return 1; + }); + + if ($mode eq "poll") { + require IO::Poll; + Danga::Socket->PollEventLoop; + } else { + Danga::Socket->EventLoop; + } + + ok($done, "$mode mode is done"); + + # check descriptor map status + my $map = Danga::Socket->DescriptorMap; + ok(ref $map eq "HASH", "map is hash"); + is(scalar keys %$map, 3, "watching 3 connections"); + Danga::Socket->Reset; + is(scalar keys %$map, 0, "watching 0 connections"); + +} + +ok(1, "finish"); + + +package Server; +use base 'Danga::Socket'; + +sub new { + my $class = shift; + my $ssock = IO::Socket::INET->new(Listen => 5, + LocalAddr => 'localhost', + LocalPort => 60000, + Proto => 'tcp', + ReuseAddr => 1, + Blocking => 0, + ); + die "couldn't create socket" unless $ssock; + IO::Handle::blocking($ssock, 0); + my $self = $class->SUPER::new($ssock); + $self->watch_read(1); + return $self; +} + +sub event_read { + my $self = shift; + while (my ($psock, $peeraddr) = $self->{sock}->accept) { + IO::Handle::blocking($psock, 0); + Test::More::ok($psock, "Server got incoming conn"); + ClientIn->new($psock); + } +} + +package ClientIn; +use base 'Danga::Socket'; +use fields ( + 'lines', #[] + ); + +sub new { + my ($class, $sock) = @_; + + my $self = fields::new($class); + $self->SUPER::new($sock); # init base fields + bless $self, ref $class || $class; + $self->watch_read(1); + $self->{lines} = []; + return $self; +} + +sub event_read { + my $self = shift; + my $bref = $self->read(5000); + Test::More::ok($$bref eq "Hello!\n", "ClientIn got hello"); + $self->watch_read(0); + $main::done = 1; +} + + +package ClientOut; +use base 'Danga::Socket'; +use fields ( + 'connected', # 0 or 1 + ); +use Socket qw(PF_INET IPPROTO_TCP SOCK_STREAM); + +sub new { + my $class = shift; + + my $sock; + socket $sock, PF_INET, SOCK_STREAM, IPPROTO_TCP; + + die "can't create outgoing sock" unless $sock && defined fileno($sock); + IO::Handle::blocking($sock, 0); + connect $sock, Socket::sockaddr_in(60000, Socket::inet_aton('127.0.0.1')); + + my $self = fields::new($class); + $self->SUPER::new($sock); + bless $self, ref $class || $class; + + $self->{'connected'} = 0; + + $self->watch_write(1); + return $self; +} + +sub event_write { + my $self = shift; + if (! $self->{'connected'}) { + Test::More::ok(1, "ClientOut connected"); + $self->{'connected'} = 1; + } + + $self->write("Hello!\n"); + $self->watch_write(0); +} diff --git a/wcmtools/lib/HTMLCleaner.pm b/wcmtools/lib/HTMLCleaner.pm new file mode 100755 index 0000000..67f75f3 --- /dev/null +++ b/wcmtools/lib/HTMLCleaner.pm @@ -0,0 +1,119 @@ +#!/usr/bin/perl +# + +package HTMLCleaner; + +use strict; +use base 'HTML::Parser'; + +sub new { + my ($class, %opts) = @_; + + my $p = new HTML::Parser('api_version' => 3); + $p->handler('start' => \&start, 'self, tagname, attr, attrseq, text' ); + $p->handler('end' => \&end, 'self, tagname' ); + $p->handler('text' => \&text, 'self, text' ); + $p->handler('declaration' => \&decl, 'self, tokens' ); + + $p->{'output'} = $opts{'output'} || sub {}; + bless $p, $class; +} + +my %bad_attr = (map { $_ => 1 } + qw(onabort onactivate onafterprint onafterupdate + onbeforeactivate onbeforecopy onbeforecut + onbeforedeactivate onbeforeeditfocus + onbeforepaste onbeforeprint onbeforeunload + onbeforeupdate onblur onbounce oncellchange + onchange onclick oncontextmenu oncontrolselect + oncopy oncut ondataavailable ondatasetchanged + ondatasetcomplete ondblclick ondeactivate + ondrag ondragend ondragenter ondragleave + ondragover ondragstart ondrop onerror + onerrorupdate onfilterchange onfinish onfocus + onfocusin onfocusout onhelp onkeydown + onkeypress onkeyup onlayoutcomplete onload + onlosecapture onmousedown onmouseenter + onmouseleave onmousemove onmouseout + onmouseover onmouseup onmousewheel onmove + onmoveend onmovestart onpaste onpropertychange + onreadystatechange onreset onresize + onresizeend onresizestart onrowenter onrowexit + onrowsdelete onrowsinserted onscroll onselect + onselectionchange onselectstart onstart onstop + onsubmit onunload datasrc datafld)); + +my %eat_tag = (map { $_ => 1 } + qw(script iframe object applet embed)); + +my @eating; # push tagname whenever we start eating a tag + +sub start { + my ($self, $tagname, $attr, $seq, $text) = @_; + my $slashclose = 0; # xml-style + if ($tagname =~ s!/(.*)!!) { + if (length($1)) { push @eating, "$tagname/$1"; } # basically halt parsing + else { $slashclose = 1; } + } + push @eating, $tagname if + $eat_tag{$tagname}; + return if @eating; + my $ret = "<$tagname"; + foreach (@$seq) { + if ($_ eq "/") { $slashclose = 1; next; } + next if $bad_attr{lc($_)}; + next if /(?:^=)|[\x0b\x0d]/; + + # IE is brain-dead and lets javascript:, vbscript:, and about: have spaces mixed in + if ($attr->{$_} =~ /((?:(?:v\s*b)|(?:j\s*a\s*v\s*a))\s*s\s*c\s*r\s*i\s*p\s*t| + a\s*b\s*o\s*u\s*t)\s*:/ix) { + delete $attr->{$_}; + } + $ret .= " $_=\"" . ehtml($attr->{$_}) . "\""; + } + $ret .= " /" if $slashclose; + $ret .= ">"; + $self->{'output'}->($ret); +} + +sub end { + my ($self, $tagname) = @_; + if (@eating) { + pop @eating if $eating[-1] eq $tagname; + return; + } + $self->{'output'}->(""); +} + +sub text { + my ($self, $text) = @_; + return if @eating; + # the parser gives us back text whenever it's confused + # on really broken input. sadly, IE parses really broken + # input, so let's escape anything going out this way. + $self->{'output'}->(eangles($text)); +} + +sub decl { + my ($self, $tokens) = @_; + $self->{'output'}->(""); +} + +sub eangles { + my $a = shift; + $a =~ s//>/g; + return $a; +} + +sub ehtml { + my $a = shift; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +1; diff --git a/wcmtools/lib/LWPx-ParanoidAgent/ChangeLog b/wcmtools/lib/LWPx-ParanoidAgent/ChangeLog new file mode 100755 index 0000000..55afb5d --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/ChangeLog @@ -0,0 +1,21 @@ +1.02: 2005-05-24 + - block 0.0.0.0/8 as well (Andy Thomas ) + +1.01: 2005-05-23 + - more POD docs (constructor and method calls) + + - be aware of all forms of IP address (a, a.b, a.b.c, a.b.c.d) + where all of a, b, c, and d can be in decimal, octal, or hex. + (thanks to Martin Atkins and Timwi for pointing this out) pass + in the canonicalized version of the IP address to the bad hosts + checker. + +1.00: 2005-05-20 + - fix holes pointed out by Martin Atkins (led to me doing all the + Net::DNS and manual resolving work) + + - bundle the test script by adding a local webserver mode to it, + rather than using an xinetd script + +0.99: 2005-05-19 + - initial release diff --git a/wcmtools/lib/LWPx-ParanoidAgent/MANIFEST b/wcmtools/lib/LWPx-ParanoidAgent/MANIFEST new file mode 100755 index 0000000..8d0b037 --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/MANIFEST @@ -0,0 +1,7 @@ +Makefile.PL +ChangeLog +lib/LWPx/Protocol/http_paranoid.pm +lib/LWPx/Protocol/https_paranoid.pm +lib/LWPx/ParanoidAgent.pm +t/00-all.t +META.yml Module meta-data (added by MakeMaker) diff --git a/wcmtools/lib/LWPx-ParanoidAgent/Makefile.PL b/wcmtools/lib/LWPx-ParanoidAgent/Makefile.PL new file mode 100755 index 0000000..90f8d9e --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/Makefile.PL @@ -0,0 +1,13 @@ +use ExtUtils::MakeMaker; +WriteMakefile( 'NAME' => 'LWPx::ParanoidAgent', + 'VERSION_FROM' => 'lib/LWPx/ParanoidAgent.pm', + 'PREREQ_PM' => { + 'LWP::UserAgent' => 0, + 'Net::DNS' => 0, + 'Time::HiRes' => 0, + }, + ($] >= 5.005 ? + (ABSTRACT_FROM => 'lib/LWPx/ParanoidAgent.pm', + AUTHOR => 'Brad Fitzpatrick ') : ()), + ); + diff --git a/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/ParanoidAgent.pm b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/ParanoidAgent.pm new file mode 100755 index 0000000..d6ef606 --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/ParanoidAgent.pm @@ -0,0 +1,556 @@ +package LWPx::ParanoidAgent; +require LWP::UserAgent; + +use vars qw(@ISA $VERSION); +@ISA = qw(LWP::UserAgent); +$VERSION = '1.02'; + +require HTTP::Request; +require HTTP::Response; + +use HTTP::Status (); +use strict; +use Net::DNS; + +sub new { + my $class = shift; + my %opts = @_; + + my $blocked_hosts = delete $opts{blocked_hosts} || []; + my $whitelisted_hosts = delete $opts{whitelisted_hosts} || []; + my $resolver = delete $opts{resolver}; + $opts{timeout} ||= 15; + + my $self = LWP::UserAgent->new( %opts ); + + $self->{'blocked_hosts'} = $blocked_hosts; + $self->{'whitelisted_hosts'} = $whitelisted_hosts; + $self->{'resolver'} = $resolver; + + $self = bless $self, $class; + return $self; +} + +# returns seconds remaining given a request +sub _time_remain { + my $self = shift; + my $req = shift; + + my $now = time(); + my $start_time = $req->{_time_begin} || $now; + return $start_time + $self->{timeout} - $now; +} + +sub _resolve { + my ($self, $host, $request, $timeout, $depth) = @_; + my $res = $self->resolver; + $depth ||= 0; + + die "CNAME recursion depth limit exceeded.\n" if $depth > 10; + die "Suspicious results from DNS lookup" if $self->_bad_host($host); + + # return the IP address if it looks like one and wasn't marked bad + return ($host) if $host =~ /^\d+\.\d+\.\d+\.\d+$/; + + my $sock = $res->bgsend($host) + or die "No sock from bgsend"; + + my $rin = ''; + vec($rin, fileno($sock), 1) = 1; + my $nf = select($rin, undef, undef, $self->_time_remain($request)); + die "DNS lookup timeout" unless $nf; + + my $packet = $res->bgread($sock) + or die "DNS bgread failure"; + $sock = undef; + + my @addr; + my $cname; + foreach my $rr ($packet->answer) { + if ($rr->type eq "A") { + die "Suspicious DNS results from A record\n" if $self->_bad_host($rr->address); + push @addr, $rr->address; + } elsif ($rr->type eq "CNAME") { + # will be checked for validity in the recursion path + $cname = $rr->cname; + } + } + + return @addr if @addr; + return () unless $cname; + return $self->_resolve($cname, $request, $timeout, $depth + 1); +} + +sub _host_list_match { + my $self = shift; + my $list_name = shift; + my $host = shift; + + foreach my $rule (@{ $self->{$list_name} }) { + if (ref $rule eq "CODE") { + return 1 if $rule->($host); + } elsif (ref $rule) { + # assume regexp + return 1 if $host =~ /$rule/; + } else { + return 1 if $host eq $rule; + } + } +} + +sub _bad_host { + my $self = shift; + my $host = lc(shift); + + return 0 if $self->_host_list_match("whitelisted_hosts", $host); + return 1 if $self->_host_list_match("blocked_hosts", $host); + return 1 if + $host =~ /^localhost$/i || # localhost is bad. even though it'd be stopped in + # a later call to _bad_host with the IP address + $host =~ /\s/i; # any whitespace is questionable + + # Let's assume it's an IP address now, and get it into 32 bits. + # Uf at any time something doesn't look like a number, then it's + # probably a hostname and we've already either whitelisted or + # blacklisted those, so we'll just say it's okay and it'll come + # back here later when the resolver finds an IP address. + my @parts = split(/\./, $host); + return 0 if @parts > 4; + + # un-octal/un-hex the parts, or return if there's a non-numeric part + my $overflow_flag = 0; + foreach (@parts) { + return 0 unless /^\d+$/ || /^0x[a-f\d]+$/; + local $SIG{__WARN__} = sub { $overflow_flag = 1; }; + $_ = oct($_) if /^0/; + } + + # a purely numeric address shouldn't overflow. + return 1 if $overflow_flag; + + my $addr; # network order packed IP address + + if (@parts == 1) { + # a - 32 bits + return 1 if + $parts[0] > 0xffffffff; + $addr = pack("N", $parts[0]); + } elsif (@parts == 2) { + # a.b - 8.24 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xffffff; + $addr = pack("N", $parts[0] << 24 | $parts[1]); + } elsif (@parts == 3) { + # a.b.c - 8.8.16 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xff || + $parts[2] > 0xffff; + $addr = pack("N", $parts[0] << 24 | $parts[1] << 16 | $parts[2]); + } else { + # a.b.c.d - 8.8.8.8 bits + return 1 if + $parts[0] > 0xff || + $parts[1] > 0xff || + $parts[2] > 0xff || + $parts[3] > 0xff; + $addr = pack("N", $parts[0] << 24 | $parts[1] << 16 | $parts[2] << 8 | $parts[3]); + } + + my $haddr = unpack("N", $addr); # host order IP address + return 1 if + ($haddr & 0xFF000000) == 0x00000000 || # 0.0.0.0/8 + ($haddr & 0xFF000000) == 0x0A000000 || # 10.0.0.0/8 + ($haddr & 0xFF000000) == 0x7F000000 || # 127.0.0.0/8 + ($haddr & 0xFFF00000) == 0xAC100000 || # 172.16.0.0/12 + ($haddr & 0xFFFF0000) == 0xA9FE0000 || # 169.254.0.0/16 + ($haddr & 0xFFFF0000) == 0xC0A80000 || # 192.168.0.0/16 + $haddr == 0xFFFFFFFF || # 255.255.255.255 + ($haddr & 0xF0000000) == 0xE0000000; # multicast addresses + + # as final IP address check, pass in the canonical a.b.c.d decimal form + # to the blacklisted host check to see if matches as bad there. + my $can_ip = join(".", map { ord } split //, $addr); + return 1 if $self->_host_list_match("blocked_hosts", $can_ip); + + # looks like an okay IP address + return 0; +} + +sub request { + my ($self, $req, $arg, $size, $previous) = @_; + + # walk back to the first request, and set our _time_begin to its _time_begin, or if + # we're the first, then use current time. used by LWPx::Protocol::http_paranoid + my $first_res = $previous; # previous is the previous response that invoked this request + $first_res = $first_res->previous while $first_res && $first_res->previous; + $req->{_time_begin} = $first_res ? $first_res->request->{_time_begin} : time(); + + my $host = $req->uri->host; + if ($self->_bad_host($host)) { + my $err_res = HTTP::Response->new(403, "Unauthorized access to blocked host"); + $err_res->request($req); + $err_res->header("Client-Date" => HTTP::Date::time2str(time)); + $err_res->header("Client-Warning" => "Internal response"); + $err_res->header("Content-Type" => "text/plain"); + $err_res->content("403 Unauthorized access to blocked host\n"); + return $err_res; + } + + return $self->SUPER::request($req, $arg, $size, $previous); +} + +# taken from LWP::UserAgent and modified slightly. (proxy support removed, +# and map http and https schemes to separate protocol handlers) +sub send_request +{ + my ($self, $request, $arg, $size) = @_; + $self->_request_sanity_check($request); + + my ($method, $url) = ($request->method, $request->uri); + + local($SIG{__DIE__}); # protect against user defined die handlers + + # Check that we have a METHOD and a URL first + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "Method missing") + unless $method; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "URL missing") + unless $url; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "URL must be absolute") + unless $url->scheme; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, + "ParanoidAgent doesn't support going through proxies. ". + "In that case, do your paranoia at your proxy instead.") + if $self->_need_proxy($url); + + my $scheme = $url->scheme; + return _new_response($request, &HTTP::Status::RC_BAD_REQUEST, "Only http and https are supported by ParanoidAgent") + unless $scheme eq "http" || $scheme eq "https"; + + LWP::Debug::trace("$method $url"); + + my $protocol; + + { + # Honor object-specific restrictions by forcing protocol objects + # into class LWP::Protocol::nogo. + my $x; + if($x = $self->protocols_allowed) { + if(grep lc($_) eq $scheme, @$x) { + LWP::Debug::trace("$scheme URLs are among $self\'s allowed protocols (@$x)"); + } + else { + LWP::Debug::trace("$scheme URLs aren't among $self\'s allowed protocols (@$x)"); + require LWP::Protocol::nogo; + $protocol = LWP::Protocol::nogo->new; + } + } + elsif ($x = $self->protocols_forbidden) { + if(grep lc($_) eq $scheme, @$x) { + LWP::Debug::trace("$scheme URLs are among $self\'s forbidden protocols (@$x)"); + require LWP::Protocol::nogo; + $protocol = LWP::Protocol::nogo->new; + } + else { + LWP::Debug::trace("$scheme URLs aren't among $self\'s forbidden protocols (@$x)"); + } + } + # else fall thru and create the protocol object normally + } + + unless ($protocol) { + LWP::Protocol::implementor("${scheme}_paranoid", "LWPx::Protocol::${scheme}_paranoid"); + eval "require LWPx::Protocol::${scheme}_paranoid;"; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + my $response = _new_response($request, &HTTP::Status::RC_NOT_IMPLEMENTED, $@); + return $response; + } + + $protocol = eval { LWP::Protocol::create($scheme eq "http" ? "http_paranoid" : "https_paranoid", $self) }; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + my $response = _new_response($request, &HTTP::Status::RC_NOT_IMPLEMENTED, $@); + if ($scheme eq "https") { + $response->message($response->message . " (Crypt::SSLeay not installed)"); + $response->content_type("text/plain"); + $response->content(<. +EOT +} + return $response; + } + } + + # Extract fields that will be used below + my ($timeout, $cookie_jar, $use_eval, $parse_head, $max_size) = + @{$self}{qw(timeout cookie_jar use_eval parse_head max_size)}; + + my $response; + my $proxy = undef; + if ($use_eval) { + # we eval, and turn dies into responses below + eval { + $response = $protocol->request($request, $proxy, + $arg, $size, $timeout); + }; + if ($@) { + $@ =~ s/ at .* line \d+.*//s; # remove file/line number + $response = _new_response($request, + &HTTP::Status::RC_INTERNAL_SERVER_ERROR, + $@); + } + } + else { + $response = $protocol->request($request, $proxy, + $arg, $size, $timeout); + # XXX: Should we die unless $response->is_success ??? + } + + $response->request($request); # record request for reference + $cookie_jar->extract_cookies($response) if $cookie_jar; + $response->header("Client-Date" => HTTP::Date::time2str(time)); + return $response; +} + +# blocked hostnames, compiled patterns, or subrefs +sub blocked_hosts +{ + my $self = shift; + if (@_) { + my @hosts = @_; + $self->{'blocked_hosts'} = \@hosts; + return; + } + return @{ $self->{'blocked_hosts'} }; +} + +# whitelisted hostnames, compiled patterns, or subrefs +sub whitelisted_hosts +{ + my $self = shift; + if (@_) { + my @hosts = @_; + $self->{'whitelisted_hosts'} = \@hosts; + return; + } + return @{ $self->{'whitelisted_hosts'} }; +} + +# get/set Net::DNS resolver object +sub resolver +{ + my $self = shift; + if (@_) { + $self->{'resolver'} = shift; + require UNIVERSAL ; + die "Not a Net::DNS::Resolver object" unless + UNIVERSAL::isa($self->{'resolver'}, "Net::DNS::Resolver"); + } + return $self->{'resolver'} ||= Net::DNS::Resolver->new; +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _need_proxy +{ + my($self, $url) = @_; + $url = $HTTP::URI_CLASS->new($url) unless ref $url; + + my $scheme = $url->scheme || return; + if (my $proxy = $self->{'proxy'}{$scheme}) { + if (@{ $self->{'no_proxy'} }) { + if (my $host = eval { $url->host }) { + for my $domain (@{ $self->{'no_proxy'} }) { + if ($host =~ /\Q$domain\E$/) { + LWP::Debug::trace("no_proxy configured"); + return; + } + } + } + } + LWP::Debug::debug("Proxied to $proxy"); + return $HTTP::URI_CLASS->new($proxy); + } + LWP::Debug::debug('Not proxied'); + undef; +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _request_sanity_check { + my($self, $request) = @_; + # some sanity checking + if (defined $request) { + if (ref $request) { + Carp::croak("You need a request object, not a " . ref($request) . " object") + if ref($request) eq 'ARRAY' or ref($request) eq 'HASH' or + !$request->can('method') or !$request->can('uri'); + } + else { + Carp::croak("You need a request object, not '$request'"); + } + } + else { + Carp::croak("No request object passed in"); + } +} + +# Taken directly from LWP::UserAgent because it was private there, and we can't depend on it +# staying there in future versions: needed by our modified version of send_request +sub _new_response { + my($request, $code, $message) = @_; + my $response = HTTP::Response->new($code, $message); + $response->request($request); + $response->header("Client-Date" => HTTP::Date::time2str(time)); + $response->header("Client-Warning" => "Internal response"); + $response->header("Content-Type" => "text/plain"); + $response->content("$code $message\n"); + return $response; +} + +1; + +__END__ + +=head1 NAME + +LWPx::ParanoidAgent - subclass of LWP::UserAgent that protects you from harm + +=head1 SYNOPSIS + + require LWPx::ParanoidAgent; + + my $ua = LWPx::ParanoidAgent->new; + + # this is 10 seconds overall, from start to finish. not just between + # socket reads. and it includes all redirects. so attackers telling + # you to download from a malicious tarpit webserver can only stall + # you for $n seconds + + $ua->timeout(10); + + # setup extra block lists, in addition to the always-enforced blocking + # of private IP addresses, loopbacks, and multicast addresses + + $ua->blocked_hosts( + "foo.com", + qr/\.internal\.company\.com$/i, + sub { my $host = shift; return 1 if is_bad($host); }, + ); + + $ua->whitelisted_hosts( + "brad.lj", + qr/^192\.168\.64\.3?/, + sub { ... }, + ); + + # get/set the DNS resolver object that's used + my $resolver = $ua->resolver; + $ua->resolver(Net::DNS::Resolver->new(...)); + + # and then just like a normal LWP::UserAgent, because it is one. + my $response = $ua->get('http://search.cpan.org/'); + ... + if ($response->is_success) { + print $response->content; # or whatever + } + else { + die $response->status_line; + } + +=head1 DESCRIPTION + +The C is a class subclassing C, +but paranoid against attackers. It's to be used when you're fetching +a remote resource on behalf of a possibly malicious user. + +This class can do whatever C can (callbacks, uploads from +files, etc), except proxy support is explicitly removed, because in +that case you should do your paranoia at your proxy. + +Also, the schemes are limited to http and https, which are mapped to +C and +C, respectively, which are forked +versions of the same ones without the "_paranoid". Subclassing them +didn't look possible, as they were essentially just one huge function. + +This class protects you from connecting to internal IP ranges (unless you +whitelist them), hostnames/IPs that you blacklist, remote webserver +tarpitting your process (the timeout parameter is changed to be a global +timeout over the entire process), and all combinations of redirects and +DNS tricks to otherwise tarpit and/or connect to internal resources. + +=head1 CONSTRUCTOR + +=over 4 + +=item C + +my $ua = LWPx::ParanoidAgent->new([ %opts ]); + +In addition to any constructor options from L, you may +also set C (to an arrayref), C (also +an arrayref), and C, a Net::DNS::Resolver object. + +=back + +=head1 METHODS + +=over 4 + +=item $csr->B($net_dns_resolver) + +=item $csr->B + +Get/set the L object used to lookup hostnames. + +=item $csr->B(@host_list) + +=item $csr->B + +Get/set the the list of blocked hosts. The items in @host_list may be +compiled regular expressions (with qr//), code blocks, or scalar +literals. In any case, the thing that is match, passed in, or +compared (respectively), is all of the given hostname, given IP +address, and IP address in canonical a.b.c.d decimal notation. So if +you want to block "1.2.3.4" and the user entered it in a mix of +network/host form in a mix of decimal/octal/hex, you need only block +"1.2.3.4" and not worry about the details. + +=item $csr->B(@host_list) + +=item $csr->B + +Like blocked hosts, but matching the hosts/IPs that bypass blocking +checks. The only difference is the IP address isn't canonicalized +before being whitelisted-matched, mostly because it doesn't make sense +for somebody to enter in a good address in a subversive way. + +=back + +=head1 SEE ALSO + +See L to see how to use this class. + +=head1 WARRANTY + +This module is supplied "as-is" and comes with no warranty, expressed +or implied. It tries to protect you from harm, but maybe it will. +Maybe it will destroy your data and your servers. You'd better audit +it and send me bug reports. + +=head1 BUGS + +Maybe. See the warranty above. + +=head1 COPYRIGHT + +Copyright 2005 Brad Fitzpatrick + +Lot of code from the the base class, copyright 1995-2004 Gisle Aas. + +This library is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. diff --git a/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/http_paranoid.pm b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/http_paranoid.pm new file mode 100755 index 0000000..afa405a --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/http_paranoid.pm @@ -0,0 +1,428 @@ +# $Id: http_paranoid.pm,v 1.1 2005/06/01 23:12:25 bradfitz Exp $ +# + +package LWPx::Protocol::http_paranoid; + +use strict; + +require LWP::Debug; +require HTTP::Response; +require HTTP::Status; +require Net::HTTP; + +use vars qw(@ISA $TOO_LATE $TIME_REMAIN); + +require LWP::Protocol; +@ISA = qw(LWP::Protocol); + +my $CRLF = "\015\012"; + +# lame hack using globals in this package to communicate to sysread in the +# package at bottom, but whatchya gonna do? Don't want to go modify +# Net::HTTP::* to pass explicit timeouts to all the sysreads. +sub _set_time_remain { + my $now = time; + return unless defined $TOO_LATE; + $TIME_REMAIN = $TOO_LATE - $now; + $TIME_REMAIN = 0 if $TIME_REMAIN < 0; +} + +sub _new_socket +{ + my($self, $host, $port, $timeout, $request) = @_; + + my $conn_cache = $self->{ua}{conn_cache}; + if ($conn_cache) { + if (my $sock = $conn_cache->withdraw("http", "$host:$port")) { + return $sock if $sock && !$sock->can_read(0); + # if the socket is readable, then either the peer has closed the + # connection or there are some garbage bytes on it. In either + # case we abandon it. + $sock->close; + } + } + + my @addrs = $self->{ua}->_resolve($host, $request, $timeout); + unless (@addrs) { + die "Can't connect to $host:$port (No suitable addresses found)"; + } + + my $sock; + local($^W) = 0; # IO::Socket::INET can be noisy + + while (! $sock && @addrs) { + my $addr = shift @addrs; + + my $conn_timeout = $request->{_timebegin} ? + (time() - $request->{_timebegin}) : + $timeout; + + $sock = $self->socket_class->new(PeerAddr => $addr, + PeerPort => $port, + Proto => 'tcp', + Timeout => $conn_timeout, + KeepAlive => !!$conn_cache, + SendTE => 1, + ); + } + + unless ($sock) { + # IO::Socket::INET leaves additional error messages in $@ + $@ =~ s/^.*?: //; + die "Can't connect to $host:$port ($@)"; + } + + # perl 5.005's IO::Socket does not have the blocking method. + eval { $sock->blocking(0); }; + + $sock; +} + +sub socket_class +{ + my $self = shift; + (ref($self) || $self) . "::Socket"; +} + +sub _get_sock_info +{ + my($self, $res, $sock) = @_; + if (defined(my $peerhost = $sock->peerhost)) { + $res->header("Client-Peer" => "$peerhost:" . $sock->peerport); + } +} + +sub _fixup_header +{ + my($self, $h, $url, $proxy) = @_; + + # Extract 'Host' header + my $hhost = $url->authority; + if ($hhost =~ s/^([^\@]*)\@//) { # get rid of potential "user:pass@" + # add authorization header if we need them. HTTP URLs do + # not really support specification of user and password, but + # we allow it. + if (defined($1) && not $h->header('Authorization')) { + require URI::Escape; + $h->authorization_basic(map URI::Escape::uri_unescape($_), + split(":", $1, 2)); + } + } + $h->init_header('Host' => $hhost); + +} + +sub hlist_remove { + my($hlist, $k) = @_; + $k = lc $k; + for (my $i = @$hlist - 2; $i >= 0; $i -= 2) { + next unless lc($hlist->[$i]) eq $k; + splice(@$hlist, $i, 2); + } +} + +sub request +{ + my($self, $request, $proxy, $arg, $size, $timeout) = @_; + LWP::Debug::trace('()'); + + # paranoid: now $timeout means total time, not just between bytes coming in. + # avoids attacker servers from tarpitting a service that fetches URLs. + $TOO_LATE = undef; + $TIME_REMAIN = undef; + if ($timeout) { + my $start_time = $request->{_time_begin} || time(); + $TOO_LATE = $start_time + $timeout; + } + + $size ||= 4096; + + # check method + my $method = $request->method; + unless ($method =~ /^[A-Za-z0-9_!\#\$%&\'*+\-.^\`|~]+$/) { # HTTP token + return new HTTP::Response &HTTP::Status::RC_BAD_REQUEST, + 'Library does not allow method ' . + "$method for 'http:' URLs"; + } + + my $url = $request->url; + my($host, $port, $fullpath); + + $host = $url->host; + $port = $url->port; + $fullpath = $url->path_query; + $fullpath = "/$fullpath" unless $fullpath =~ m,^/,; + + # connect to remote sites + my $socket = $self->_new_socket($host, $port, $timeout, $request); + + my @h; + my $request_headers = $request->headers->clone; + $self->_fixup_header($request_headers, $url, $proxy); + + $request_headers->scan(sub { + my($k, $v) = @_; + $k =~ s/^://; + $v =~ s/\n/ /g; + push(@h, $k, $v); + }); + + my $content_ref = $request->content_ref; + $content_ref = $$content_ref if ref($$content_ref); + my $chunked; + my $has_content; + + if (ref($content_ref) eq 'CODE') { + my $clen = $request_headers->header('Content-Length'); + $has_content++ if $clen; + unless (defined $clen) { + push(@h, "Transfer-Encoding" => "chunked"); + $has_content++; + $chunked++; + } + } + else { + # Set (or override) Content-Length header + my $clen = $request_headers->header('Content-Length'); + if (defined($$content_ref) && length($$content_ref)) { + $has_content++; + if (!defined($clen) || $clen ne length($$content_ref)) { + if (defined $clen) { + warn "Content-Length header value was wrong, fixed"; + hlist_remove(\@h, 'Content-Length'); + } + push(@h, 'Content-Length' => length($$content_ref)); + } + } + elsif ($clen) { + warn "Content-Length set when there is not content, fixed"; + hlist_remove(\@h, 'Content-Length'); + } + } + + my $req_buf = $socket->format_request($method, $fullpath, @h); + #print "------\n$req_buf\n------\n"; + + # XXX need to watch out for write timeouts + # FIXME_BRAD: make it non-blocking and select during the write + { + my $n = $socket->syswrite($req_buf, length($req_buf)); + die $! unless defined($n); + die "short write" unless $n == length($req_buf); + #LWP::Debug::conns($req_buf); + } + + my($code, $mess, @junk); + my $drop_connection; + + if ($has_content) { + my $write_wait = 0; + $write_wait = 2 + if ($request_headers->header("Expect") || "") =~ /100-continue/; + + my $eof; + my $wbuf; + my $woffset = 0; + if (ref($content_ref) eq 'CODE') { + my $buf = &$content_ref(); + $buf = "" unless defined($buf); + $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF + if $chunked; + $wbuf = \$buf; + } + else { + $wbuf = $content_ref; + $eof = 1; + } + + my $fbits = ''; + vec($fbits, fileno($socket), 1) = 1; + + while ($woffset < length($$wbuf)) { + + my $time_before; + + my $now = time(); + if ($now > $TOO_LATE) { + die "Request took too long."; + } + + my $sel_timeout = $TOO_LATE - $now; + if ($write_wait) { + $time_before = time; + $sel_timeout = $write_wait if $write_wait < $sel_timeout; + } + + my $rbits = $fbits; + my $wbits = $write_wait ? undef : $fbits; + my $nfound = select($rbits, $wbits, undef, $sel_timeout); + unless (defined $nfound) { + die "select failed: $!"; + } + + if ($write_wait) { + $write_wait -= time - $time_before; + $write_wait = 0 if $write_wait < 0; + } + + if (defined($rbits) && $rbits =~ /[^\0]/) { + # readable + my $buf = $socket->_rbuf; + + _set_time_remain(); + + my $n = $socket->sysread($buf, 1024, length($buf)); + unless ($n) { + die "EOF"; + } + $socket->_rbuf($buf); + if ($buf =~ /\015?\012\015?\012/) { + # a whole response present + ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, + junk_out => \@junk, + ); + if ($code eq "100") { + $write_wait = 0; + undef($code); + } + else { + $drop_connection++; + last; + # XXX should perhaps try to abort write in a nice way too + } + } + } + if (defined($wbits) && $wbits =~ /[^\0]/) { + my $n = $socket->syswrite($$wbuf, length($$wbuf), $woffset); + unless ($n) { + die "syswrite: $!" unless defined $n; + die "syswrite: no bytes written"; + } + $woffset += $n; + + if (!$eof && $woffset >= length($$wbuf)) { + # need to refill buffer from $content_ref code + my $buf = &$content_ref(); + $buf = "" unless defined($buf); + $eof++ unless length($buf); + $buf = sprintf "%x%s%s%s", length($buf), $CRLF, $buf, $CRLF + if $chunked; + $wbuf = \$buf; + $woffset = 0; + } + } + } + } + + _set_time_remain(); + ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, junk_out => \@junk) + unless $code; + ($code, $mess, @h) = $socket->read_response_headers(laxed => 1, junk_out => \@junk) + if $code eq "100"; + + my $response = HTTP::Response->new($code, $mess); + my $peer_http_version = $socket->peer_http_version; + $response->protocol("HTTP/$peer_http_version"); + while (@h) { + my($k, $v) = splice(@h, 0, 2); + $response->push_header($k, $v); + } + $response->push_header("Client-Junk" => \@junk) if @junk; + + $response->request($request); + $self->_get_sock_info($response, $socket); + + if ($method eq "CONNECT") { + $response->{client_socket} = $socket; # so it can be picked up + return $response; + } + + if (my @te = $response->remove_header('Transfer-Encoding')) { + $response->push_header('Client-Transfer-Encoding', \@te); + } + $response->push_header('Client-Response-Num', $socket->increment_response_count); + + my $complete; + $response = $self->collect($arg, $response, sub { + my $buf = ""; #prevent use of uninitialized value in SSLeay.xs + my $n; + READ: + { + _set_time_remain(); + $n = $socket->read_entity_body($buf, $size); + die "Can't read entity body: $!" unless defined $n; + redo READ if $n == -1; + } + $complete++ if !$n; + return \$buf; + } ); + $drop_connection++ unless $complete; + + _set_time_remain(); + @h = $socket->get_trailers; + while (@h) { + my($k, $v) = splice(@h, 0, 2); + $response->push_header($k, $v); + } + + # keep-alive support + unless ($drop_connection) { + if (my $conn_cache = $self->{ua}{conn_cache}) { + my %connection = map { (lc($_) => 1) } + split(/\s*,\s*/, ($response->header("Connection") || "")); + if (($peer_http_version eq "1.1" && !$connection{close}) || + $connection{"keep-alive"}) + { + LWP::Debug::debug("Keep the http connection to $host:$port"); + $conn_cache->deposit("http", "$host:$port", $socket); + } + } + } + + $response; +} + + +#----------------------------------------------------------- +package LWPx::Protocol::http_paranoid::SocketMethods; + +sub sysread { + my $self = shift; + my $timeout = $LWPx::Protocol::http_paranoid::TIME_REMAIN; + + if (defined $timeout) { + die "read timeout" unless $self->can_read($timeout); + } + else { + # since we have made the socket non-blocking we + # use select to wait for some data to arrive + $self->can_read(undef) || die "Assert"; + } + sysread($self, $_[0], $_[1], $_[2] || 0); +} + +sub can_read { + my($self, $timeout) = @_; + my $fbits = ''; + vec($fbits, fileno($self), 1) = 1; + my $nfound = select($fbits, undef, undef, $timeout); + die "select failed: $!" unless defined $nfound; + return $nfound > 0; +} + +sub ping { + my $self = shift; + !$self->can_read(0); +} + +sub increment_response_count { + my $self = shift; + return ++${*$self}{'myhttp_response_count'}; +} + +#----------------------------------------------------------- +package LWPx::Protocol::http_paranoid::Socket; +use vars qw(@ISA); +@ISA = qw(LWPx::Protocol::http_paranoid::SocketMethods Net::HTTP); + +1; diff --git a/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/https_paranoid.pm b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/https_paranoid.pm new file mode 100755 index 0000000..f7beed5 --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx/Protocol/https_paranoid.pm @@ -0,0 +1,49 @@ +# +package LWPx::Protocol::https_paranoid; + +# $Id: https_paranoid.pm,v 1.1 2005/06/01 23:12:25 bradfitz Exp $ + +use strict; + +use vars qw(@ISA); +require LWPx::Protocol::http_paranoid; +@ISA = qw(LWPx::Protocol::http_paranoid); + +sub _check_sock +{ + my($self, $req, $sock) = @_; + my $check = $req->header("If-SSL-Cert-Subject"); + if (defined $check) { + my $cert = $sock->get_peer_certificate || + die "Missing SSL certificate"; + my $subject = $cert->subject_name; + die "Bad SSL certificate subject: '$subject' !~ /$check/" + unless $subject =~ /$check/; + $req->remove_header("If-SSL-Cert-Subject"); # don't pass it on + } +} + +sub _get_sock_info +{ + my $self = shift; + $self->SUPER::_get_sock_info(@_); + my($res, $sock) = @_; + $res->header("Client-SSL-Cipher" => $sock->get_cipher); + my $cert = $sock->get_peer_certificate; + if ($cert) { + $res->header("Client-SSL-Cert-Subject" => $cert->subject_name); + $res->header("Client-SSL-Cert-Issuer" => $cert->issuer_name); + } + if(! eval { $sock->get_peer_verify }) { + $res->header("Client-SSL-Warning" => "Peer certificate not verified"); + } +} + +#----------------------------------------------------------- +package LWPx::Protocol::https_paranoid::Socket; + +use vars qw(@ISA); +require Net::HTTPS; +@ISA = qw(Net::HTTPS LWPx::Protocol::http_paranoid::SocketMethods); + +1; diff --git a/wcmtools/lib/LWPx-ParanoidAgent/t/00-all.t b/wcmtools/lib/LWPx-ParanoidAgent/t/00-all.t new file mode 100755 index 0000000..d46ab11 --- /dev/null +++ b/wcmtools/lib/LWPx-ParanoidAgent/t/00-all.t @@ -0,0 +1,207 @@ +#!/usr/bin/perl +# + +use strict; +use LWPx::ParanoidAgent; +use Time::HiRes qw(time); +use Test::More tests => 25; +use Net::DNS; +use IO::Socket::INET; + +my ($t1, $td); +my $delta = sub { printf " %.03f secs\n", $td; }; + +my $ua = LWPx::ParanoidAgent->new; +ok((ref $ua) =~ /LWPx::ParanoidAgent/); + +my ($HELPER_IP, $HELPER_PORT) = ("127.66.74.70", 9001); + +my $child_pid = fork; +web_server_mode() if ! $child_pid; +select undef, undef, undef, 0.5; + +my $HELPER_SERVER = "http://$HELPER_IP:$HELPER_PORT"; + + +$ua->whitelisted_hosts( + $HELPER_IP, + ); + +$ua->blocked_hosts( + qr/\.lj$/, + "1.2.3.6", + ); + +my $res; + +# hostnames pointing to internal IPs +$res = $ua->get("http://localhost-fortest.danga.com/"); +ok(! $res->is_success && $res->status_line =~ /Suspicious DNS results/); + +# random IP address forms +$res = $ua->get("http://0x7f.1/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); +$res = $ua->get("http://0x7f.0xffffff/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); +$res = $ua->get("http://037777777777/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); +$res = $ua->get("http://192.052000001/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); +$res = $ua->get("http://0x00.00/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); + +# test the the blocked host above in decimal form is blocked by this non-decimal form: +$res = $ua->get("http://0x01.02.0x306/"); +ok(! $res->is_success && $res->status_line =~ /blocked/); + +# hostnames doing CNAMEs (this one resolves to "brad.lj", which is verboten) +my $old_resolver = $ua->resolver; +$ua->resolver(Net::DNS::Resolver->new(nameservers => [ qw(66.150.15.140) ] )); +$res = $ua->get("http://bradlj-fortest.danga.com/"); +print $res->status_line, "\n"; +ok(! $res->is_success); +$ua->resolver($old_resolver); + +# black-listed via blocked_hosts +$res = $ua->get("http://brad.lj/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# can't do octal in IPs +$res = $ua->get("http://012.1.2.1/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# can't do decimal/octal IPs +$res = $ua->get("http://167838209/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# checking that port isn't affected +$res = $ua->get("http://brad.lj:80/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# this domain is okay. bradfitz.com isn't blocked +$res = $ua->get("http://bradfitz.com/"); +print $res->status_line, "\n"; +ok( $res->is_success); + +# SSL should still work +$res = $ua->get("https://pause.perl.org/pause/query"); +ok( $res->is_success && $res->content =~ /Login|PAUSE|Edit/); + +# internal. bad. blocked by default by module. +$res = $ua->get("http://10.2.3.4/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# okay +$res = $ua->get("http://danga.com/temp/"); +print $res->status_line, "\n"; +ok( $res->is_success); + +# localhost is blocked, case insensitive +$res = $ua->get("http://LOCALhost/temp/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# redirecting to invalid host +$res = $ua->get("$HELPER_SERVER/redir/http://10.2.3.4/"); +print $res->status_line, "\n"; +ok(! $res->is_success); + +# redirect with tarpitting +print "4 second redirect tarpit (tolerance 2)...\n"; +$ua->timeout(2); +$res = $ua->get("$HELPER_SERVER/redir-4/http://www.danga.com/"); +ok(! $res->is_success); + +# lots of slow redirects adding up to a lot of time +print "Three 1-second redirect tarpits (tolerance 2)...\n"; +$ua->timeout(2); +$t1 = time(); +$res = $ua->get("$HELPER_SERVER/redir-1/$HELPER_SERVER/redir-1/$HELPER_SERVER/redir-1/http://www.danga.com/"); +$td = time() - $t1; +$delta->(); +ok($td < 2.5); +ok(! $res->is_success); + +# redirecting a bunch and getting the final good host +$res = $ua->get("$HELPER_SERVER/redir/$HELPER_SERVER/redir/$HELPER_SERVER/redir/http://www.danga.com/"); +ok( $res->is_success && $res->request->uri->host eq "www.danga.com"); + +# dying in a tarpit +print "5 second tarpit (tolerance 2)...\n"; +$ua->timeout(2); +$res = $ua->get("$HELPER_SERVER/1.5"); +ok(! $res->is_success); + +# making it out of a tarpit. +print "3 second tarpit (tolerance 4)...\n"; +$ua->timeout(4); +$res = $ua->get("$HELPER_SERVER/1.3"); +ok( $res->is_success); + +kill 9, $child_pid; + + +sub web_server_mode { + my $ssock = IO::Socket::INET->new(Listen => 5, + LocalAddr => $HELPER_IP, + LocalPort => $HELPER_PORT, + ReuseAddr => 1, + Proto => 'tcp') + or die "Couldn't start webserver.\n"; + + while (my $csock = $ssock->accept) { + exit 0 unless $csock; + fork and next; + + my $eat = sub { + while (<$csock>) { + last if ! $_ || /^\r?\n/; + } + }; + + my $req = <$csock>; + print STDERR " ####### GOT REQ: $req" if $ENV{VERBOSE}; + + if ($req =~ m!^GET /(\d+)\.(\d+) HTTP/1\.\d+\r?\n?$!) { + my ($delay, $count) = ($1, $2); + $eat->(); + print $csock + "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"; + for (1..$count) { + print $csock "[$_/$count]\n"; + sleep $delay; + } + exit 0; + } + + if ($req =~ m!^GET /redir/(\S+) HTTP/1\.\d+\r?\n?$!) { + my $dest = $1; + $eat->(); + print $csock + "HTTP/1.0 302 Found\r\nLocation: $dest\r\nContent-Length: 0\r\n\r\n"; + exit 0; + } + + if ($req =~ m!^GET /redir-(\d+)/(\S+) HTTP/1\.\d+\r?\n?$!) { + my $sleep = $1; + sleep $sleep; + my $dest = $2; + $eat->(); + print $csock + "HTTP/1.0 302 Found\r\nLocation: $dest\r\nContent-Length: 0\r\n\r\n"; + exit 0; + } + + print $csock + "HTTP/1.0 500 Server Error\r\n" . + "Content-Length: 10\r\n\r\n" . + "bogus_req\n"; + exit 0; + } + exit 0; +} diff --git a/wcmtools/lib/MultiCVS.pm b/wcmtools/lib/MultiCVS.pm new file mode 100755 index 0000000..ee92e2a --- /dev/null +++ b/wcmtools/lib/MultiCVS.pm @@ -0,0 +1,480 @@ +#!/usr/bin/perl +# + +package MultiCVS; +use strict; + +BEGIN { + use Carp qw{confess croak}; + use IO::File qw{}; + use File::Find qw{find}; + use Fcntl qw{O_RDONLY}; + + use constant TRUE => 1; + use constant FALSE => (); +} + + +### (CONSTRUCTOR) METHOD: new( $mainconfig ) +### Create a new MultiCVS object. +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + my $mainconfig = shift; + + my $self = bless { + dir_live => '', + dir_cvs => '', + + directories => undef, + filemap => undef, + + _debug => undef, + }, $class; + + # Read the first argument as the main config file, and try to find and read + # any local variant after that. + if ( $mainconfig ) { + $self->read_config( $mainconfig, 1 ); + + if ( $mainconfig =~ m{^(.+)multicvs.conf$} ) { + my $localconf = "$1multicvs-local.conf"; + $self->read_config( $localconf ); + } + } + + return $self; +} + + +sub debugmsg { + my $self = shift or confess "Cannot be used as a function"; + return unless $self->{_debug}; + my ( $fmt, @args ) = @_; + + printf STDERR $fmt, @args; +} + + +### METHOD: read_config( $file[, $ismain] ) +### Read the object's configuration from the given I. +sub read_config { + my ( $self, $file, $ismain ) = @_; + + my ( + $ifh, + $line, + ); + + open $ifh, "<$file" or die "open: $file: $!"; + + while ( <$ifh> ) { + $line = $_; + chomp $line; + + # Strip leading, trailing space and comments + $line =~ s{(^\s+|#.*|\s+$)}{}g; + next unless $line =~ /\S/; + + # Expand environment variables + $line =~ s/\$(\w+)/$ENV{$1} or die "Environment variable \$$1 not set.\n"/ge; + + # Set key/value pair variables if this is the main config + if ( $line =~ /(\w+)\s*=\s*(.+)/ ) { + my ($k, $v) = ($1, $2); + die "Included config files can't set variables such as $k.\n" unless $ismain; + + if ( $k eq "LIVEDIR" ) { $self->{dir_live} = $v } + elsif ( $k eq "CVSDIR" ) { $self->{dir_cvs} = $v } + else { die "Unknown option $k = $v\n"; } + } + + # Set namevalue pairs + elsif (/(\S+)\s+(.+)/) { + my ($from, $to) = ($1, $2); + my $optional = 0; + + if ($from =~ s/\?$//) { $optional = 1; } + + push @{$self->{paths}}, { + 'from' => $from, + 'to' => $to, + 'optional' => $optional, + }; + } else { + die "Bogus config line in '$file': $line\n"; + } + } + close $ifh; + + # Clear any old entries + $self->{directories} = $self->{files} = undef; + + return TRUE; +} + + +### METHOD: cvs_update( [$quiet] ) +### Update the modules under multicvs's control, optionally with the quiet flag +### turned on. +sub cvs_update { + my $self = shift or confess "can't be called as a function"; + my $quiet = shift || 0; + + my ( + $dir, + $count, + ); + + $count = 0; + + # Do a 'cvs update' in directories that haven't been updated yet. + foreach my $dir ( $self->directories ) { + chdir $dir or die "chdir: $dir: $!\n"; + $self->debugmsg( "Updating CVS dir '$dir' ...\n" ); + system( "cvs", "update", "-dP" ); + + $count++; + } + + return $count; +} + + + +### METHOD: directories() +### Returns a list of the top-level directories which should be checked for +### updates. +sub directories { + my $self = shift or confess "cannot be used as a function"; + + my ( + $root, + $dir, + ); + + unless ( $self->{directories} ) { + my %map = (); + + foreach my $path ( @{$self->{paths}} ) { + + # Get the root module which contains the file, fully-qualify it, + # then add it to the map + ( $root = $path->{from} ) =~ s!/.*!!; + $dir = "$self->{dir_cvs}/$root"; + $map{ $dir } = 1 if -d $dir; + } + + $self->{directories} = [ keys %map ]; + } + + return wantarray ? @{$self->{directories}} : $self->{directories}; +} + + +### METHOD: filemap() +### Make a map of file paths to equivalent cvs path out of the multicvs +### configuration. Returns either a hash in list context or a hashref in scalar +### context. +sub filemap { + my $self = shift or confess "can't be used as a function"; + + unless ( $self->{filemap} ) { + my ( + $from, + $to, + $cvsfile, + $livefile, + $selector, + %files, + ); + + # Process each path from the config + foreach my $path ( @{$self->{paths}} ) { + + $self->debugmsg( ">>> Mapping files under $path->{from}...\n" ); + + # Calculate the fully-qualified source and destination paths + $from = "$self->{dir_cvs}/$path->{from}"; + $to = "$self->{dir_live}/$path->{to}"; + + # Trim leading dot from destination + $to =~ s{/\.?/?$}{}; + $from =~ s{/\.?/?$}{}; + + # Search the current directories for files. + if ( -d $from ) { + $self->debugmsg( "Adding files to the map from directory ${from} under ${to}\n" ); + + # Selector proc -- discards backups, saves good files. + $selector = sub { + my $name = $_; + $self->debugmsg( " Examining '$name' in '${File::Find::dir}'...\n" ); + + # Skip all but the first dot-dir + if ( $name ne '.' || $File::Find::dir ne $from ) { + + # Prune garbage + if ( $name eq '..'|| $name =~ m{^\.\#|\bCVS\b|~$} ) { + $File::Find::prune = 1; + } + + # Add the file to the map after fully-qualifying the + # paths. + else { + $cvsfile = "${File::Find::dir}/${name}"; + ( $livefile = $cvsfile ) =~ s{^$from}{$to}e; + $self->debugmsg( " Adding file from %s to map as %s\n", + $cvsfile, $livefile ); + + $files{ $livefile } = $cvsfile if -f $cvsfile; + } + } + }; + + # Now actually do the find + File::Find::find( {wanted => $selector, follow => 1}, $from ); + } + + # Plain file -- just look to see if it exists in the cvs dir, adding + # it if so, warning about it if not + else { + if ( -e $from ) { + $self->debugmsg( "Adding file ${from} to map as ${to}\n" ); + $files{ $to } = $from; + } else { + warn "WARNING: $from doesn't exist under $self->{dir_cvs}\n" + unless $path->{optional}; + } + } + } + + # Cache the results + $self->{filemap} = \%files; + } + + return wantarray ? %{$self->{filemap}} : $self->{filemap}; +} + + + +### METHOD: find_changed_files( [@files] ) +### Returns a hash (or hashref in scalar context) of tuples describing changes +### which must be made to bring the cvs and live dirs into sync for the given +### I, or for all files if no I are given. Each entry in the hash +### is keyed by relative filename, and each value is a tuple (an arrayref) of +### the following form: +### +### { from => $from_path, type => $direction, to => $to_path } +### +### where I is the path to the newer file, I is either +### C for a file which is newer in CVS or C for a file which is newer in +### the live tree, and I is the path to the older file that should be +### replaced. +sub find_changed_files { + my $self = shift or confess "Cannot be called as a function"; + + my $filemap = $self->filemap; + my %tuples = (); + + my ( + $module, + $relfile, + $lfile, + $cfile, + $live_time, + $cvs_time, + ); + + # Iterate over the list of relative files, fully-qualifying them and then + # checking for up-to-dateness. + while ( ($lfile, $cfile) = each %$filemap ) { + + # Get the name of the cvs module for this entry, as well as the relative + # path in the live site. + ( $module = $cfile ) =~ s{(^$self->{dir_cvs}/|/.*)}{}g; + ( $relfile = $lfile ) =~ s{^$self->{dir_live}/}{}; + + # Fetch timestamps + $live_time = -e $lfile ? (stat _)[9] : 0; + $cvs_time = -e $cfile ? (stat _)[9] : 0; + + $self->debugmsg( "Comparing: %s -> %s (%s): %d -> %d\n", + $lfile, $cfile, $relfile, $live_time, $cvs_time ); + + # If either of them is newer, add an entry for it + if ( $live_time > $cvs_time ) { + $self->debugmsg( " Live was newer: adding " ); + $tuples{ $relfile } = { + from => $lfile, + type => 'l', + module => $module, + to => $cfile, + live_time => $live_time, + cvs_time => $cvs_time, + diff => undef, + }; + } elsif ( $cvs_time > $live_time ) { + $tuples{ $relfile } = { + from => $cfile, + type => 'c', + module => $module, + to => $lfile, + live_time => $live_time, + cvs_time => $cvs_time, + diff => undef, + }; + } + } + + return wantarray ? %tuples : \%tuples; +} + + +### METHOD: find_init_files( [@files] ) +### Like find_changed_files(), but assumes that none of the given I are +### extant on the live side (for --init). +sub find_init_files { + my $self = shift or confess "Cannot be called as a function"; + + my $filemap = $self->filemap; + my %tuples = (); + + my ( + $module, + $relfile, + $lfile, + $cfile, + $cvs_time, + ); + + while ( ($lfile, $cfile) = each %$filemap ) { + ( $relfile = $cfile ) =~ s{^$self->{dir_cvs}/}{}; + ( $module = $relfile ) =~ s{/.*}{}; + + # Fetch the mtime of the cvs file + $cvs_time = -e $cfile ? (stat _)[9] : 0; + + # Add an entry for every file + $tuples{ $lfile } = { + from => $cfile, + type => 'c', + module => $module, + to => $lfile, + live_time => 0, + cvs_time => $cvs_time, + }; + } + + return wantarray ? %tuples : \%tuples; +} + + +# :TODO: This should really use Text::Diff or something instead of doing a bunch +# of forked reads... + +### METHOD: get_diffs( \@options, @files ) +### Given one or more tuples like those returned from find_changed_files(), +### return a list of diffs the diffs for each one. +sub get_diffs { + my $self = shift or confess "Cannot be called as a function"; + my $options = ref $_[0] eq 'ARRAY' ? shift : []; + + my @files = @_; + my @diffs = (); + my $diff = undef; + + $self->debugmsg( "In get_diffs" ); + + foreach my $tuple ( @files ) { + + # Reuse cached diffs + if ( $tuple->{diff} ) { + push @diffs, $tuple->{diff}; + } + + # Regular diff + elsif ( -e $tuple->{from} && -e $tuple->{to} ) { + $self->debugmsg( "Forking for real diff on $tuple->{from} -> $tuple->{to}" ); + $diff = $self->forkread( 'diff', @$options, + $tuple->{to}, $tuple->{from} ); + $self->debugmsg( "Read diff: '", $diff, "'" ); + $tuple->{diff} = $diff; + push @diffs, $diff; + } + + # Simulate a diff for a new file + else { + $self->debugmsg( "Diff for new file $tuple->{from}" ); + $diff = sprintf " >>> New File <<<\n%s\n\n", $self->readfile( $tuple->{from} ); + $self->debugmsg( "Read diff: '", $diff, "'" ); + $tuple->{diff} = $diff; + push @diffs, $diff; + } + } + + return @diffs; +} + + +### METHOD: readfile( $file ) +### Return the specified file in and return it as a scalar. +sub readfile { + my $self = shift or confess "cannot be used as a function"; + my $filename = shift; + + local $/ = undef; + open( my $ifh, $filename, O_RDONLY ) or + croak "open: $filename: $!"; + my $content = <$ifh>; + + return $content; +} + + +### METHOD: forkread( $cmd, @args ) +### Fork and exec the specified I, giving it the specified I, and +### return the output of the command as a list of lines. +sub forkread { + my $self = shift or confess "Cannot be used as a function"; + my ( $cmd, @args ) = @_; + + my ( + $fh, + @lines, + $pid, + ); + + # Fork-open and read the child's output as the parent + if (( $pid = open($fh, "-|") )) { + @lines = <$fh>; + $fh->close; + } + + # Child - capture output for diagnostics and progress display stuff. + else { + die "Couldn't fork: $!" unless defined $pid; + + open STDERR, ">&STDOUT" or die "Can't dup stdout: $!"; + { exec $cmd, @args }; + + # Only reached if the exec() fails. + close STDERR; + close STDOUT; + exit 1; + } + + return wantarray ? @lines : join( '', @lines ); +} + + + +1; + +__END__ + +# Local Variables: +# mode: perl +# c-basic-indent: 4 +# indent-tabs-mode: nil +# End: diff --git a/wcmtools/lib/MySQL-BinLog/MANIFEST b/wcmtools/lib/MySQL-BinLog/MANIFEST new file mode 100755 index 0000000..95d9d27 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/MANIFEST @@ -0,0 +1,12 @@ +docs/log_event.h +docs/log_event.ph +experiments/cpptokenizer.pl +experiments/try.pl +lib/Mysql/BinLog.pm +lib/Mysql/BinLog/Constants.pm +lib/Mysql/BinLog/Events.pm +lib/Mysql/BinLog/Header.pm +lib/Mysql/BinLog/Net.pm +lib/Mysql/tmp +Makefile.PL +MANIFEST diff --git a/wcmtools/lib/MySQL-BinLog/MANIFEST.SKIP b/wcmtools/lib/MySQL-BinLog/MANIFEST.SKIP new file mode 100755 index 0000000..ede9cda --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists diff --git a/wcmtools/lib/MySQL-BinLog/Makefile.PL b/wcmtools/lib/MySQL-BinLog/Makefile.PL new file mode 100755 index 0000000..b6c2372 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/Makefile.PL @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# +# Perl Makefile for MySQL-BinLog +# $Id: Makefile.PL,v 1.2 2004/11/17 01:45:16 marksmith Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'MySQL::BinLog', + VERSION_FROM => 'lib/Mysql/BinLog.pm', # finds $VERSION + AUTHOR => 'Michael Granger ', + ABSTRACT => 'MySQL Replication Binlog Reader Library', + PREREQ_PM => { + 'Net::MySQL' => 0, + 'Scalar::Util' => 0, + fields => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag RELEASE_$(VERSION_SYM)', + SUFFIX => ".bz2", + DIST_DEFAULT => 'all tardist', + COMPRESS => "bzip2", + }, + +); + diff --git a/wcmtools/lib/MySQL-BinLog/docs/log_event.h b/wcmtools/lib/MySQL-BinLog/docs/log_event.h new file mode 100755 index 0000000..2eaaab2 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/docs/log_event.h @@ -0,0 +1,795 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef _log_event_h +#define _log_event_h + +#ifdef __EMX__ +#undef write // remove pthread.h macro definition, conflict with write() class member +#endif + +#if defined(__GNUC__) && !defined(MYSQL_CLIENT) +#pragma interface /* gcc class implementation */ +#endif + +#define LOG_READ_EOF -1 +#define LOG_READ_BOGUS -2 +#define LOG_READ_IO -3 +#define LOG_READ_MEM -5 +#define LOG_READ_TRUNC -6 +#define LOG_READ_TOO_LARGE -7 + +#define LOG_EVENT_OFFSET 4 +#define BINLOG_VERSION 3 + +/* + We could have used SERVER_VERSION_LENGTH, but this introduces an + obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH + this would have broke the replication protocol +*/ +#define ST_SERVER_VER_LEN 50 + +#define DUMPFILE_FLAG 0x1 +#define OPT_ENCLOSED_FLAG 0x2 +#define REPLACE_FLAG 0x4 +#define IGNORE_FLAG 0x8 + +#define FIELD_TERM_EMPTY 0x1 +#define ENCLOSED_EMPTY 0x2 +#define LINE_TERM_EMPTY 0x4 +#define LINE_START_EMPTY 0x8 +#define ESCAPED_EMPTY 0x10 + +struct old_sql_ex +{ + char field_term; + char enclosed; + char line_term; + char line_start; + char escaped; + char opt_flags; + char empty_flags; +}; + +#define NUM_LOAD_DELIM_STRS 5 + +struct sql_ex_info +{ + char* field_term; + char* enclosed; + char* line_term; + char* line_start; + char* escaped; + int cached_new_format; + uint8 field_term_len,enclosed_len,line_term_len,line_start_len, escaped_len; + char opt_flags; + char empty_flags; + + // store in new format even if old is possible + void force_new_format() { cached_new_format = 1;} + int data_size() + { + return (new_format() ? + field_term_len + enclosed_len + line_term_len + + line_start_len + escaped_len + 6 : 7); + } + int write_data(IO_CACHE* file); + char* init(char* buf,char* buf_end,bool use_new_format); + bool new_format() + { + return ((cached_new_format != -1) ? cached_new_format : + (cached_new_format=(field_term_len > 1 || + enclosed_len > 1 || + line_term_len > 1 || line_start_len > 1 || + escaped_len > 1))); + } +}; + +/* + Binary log consists of events. Each event has a fixed length header, + followed by possibly variable ( depending on the type of event) length + data body. The data body consists of an optional fixed length segment + (post-header), and an optional variable length segment. See #defines and + comments below for the format specifics +*/ + +/* event-specific post-header sizes */ +#define LOG_EVENT_HEADER_LEN 19 +#define OLD_HEADER_LEN 13 +#define QUERY_HEADER_LEN (4 + 4 + 1 + 2) +#define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4) +#define START_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4) +#define ROTATE_HEADER_LEN 8 +#define CREATE_FILE_HEADER_LEN 4 +#define APPEND_BLOCK_HEADER_LEN 4 +#define EXEC_LOAD_HEADER_LEN 4 +#define DELETE_FILE_HEADER_LEN 4 + +/* event header offsets */ + +#define EVENT_TYPE_OFFSET 4 +#define SERVER_ID_OFFSET 5 +#define EVENT_LEN_OFFSET 9 +#define LOG_POS_OFFSET 13 +#define FLAGS_OFFSET 17 + +/* start event post-header */ + +#define ST_BINLOG_VER_OFFSET 0 +#define ST_SERVER_VER_OFFSET 2 +#define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN) + +/* slave event post-header */ + +#define SL_MASTER_PORT_OFFSET 8 +#define SL_MASTER_POS_OFFSET 0 +#define SL_MASTER_HOST_OFFSET 10 + +/* query event post-header */ + +#define Q_THREAD_ID_OFFSET 0 +#define Q_EXEC_TIME_OFFSET 4 +#define Q_DB_LEN_OFFSET 8 +#define Q_ERR_CODE_OFFSET 9 +#define Q_DATA_OFFSET QUERY_HEADER_LEN + +/* Intvar event post-header */ + +#define I_TYPE_OFFSET 0 +#define I_VAL_OFFSET 1 + +/* Rand event post-header */ + +#define RAND_SEED1_OFFSET 0 +#define RAND_SEED2_OFFSET 8 + +/* Load event post-header */ + +#define L_THREAD_ID_OFFSET 0 +#define L_EXEC_TIME_OFFSET 4 +#define L_SKIP_LINES_OFFSET 8 +#define L_TBL_LEN_OFFSET 12 +#define L_DB_LEN_OFFSET 13 +#define L_NUM_FIELDS_OFFSET 14 +#define L_SQL_EX_OFFSET 18 +#define L_DATA_OFFSET LOAD_HEADER_LEN + +/* Rotate event post-header */ + +#define R_POS_OFFSET 0 +#define R_IDENT_OFFSET 8 + +#define CF_FILE_ID_OFFSET 0 +#define CF_DATA_OFFSET CREATE_FILE_HEADER_LEN + +#define AB_FILE_ID_OFFSET 0 +#define AB_DATA_OFFSET APPEND_BLOCK_HEADER_LEN + +#define EL_FILE_ID_OFFSET 0 + +#define DF_FILE_ID_OFFSET 0 + +#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN) +#define QUERY_DATA_OFFSET (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN) +#define ROTATE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+ROTATE_HEADER_LEN) +#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN) +#define CREATE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+\ + +LOAD_HEADER_LEN+CREATE_FILE_HEADER_LEN) +#define DELETE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+DELETE_FILE_HEADER_LEN) +#define EXEC_LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+EXEC_LOAD_HEADER_LEN) +#define APPEND_BLOCK_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+APPEND_BLOCK_HEADER_LEN) + + +#define BINLOG_MAGIC "\xfe\x62\x69\x6e" + +#define LOG_EVENT_TIME_F 0x1 +#define LOG_EVENT_FORCED_ROTATE_F 0x2 + +enum Log_event_type +{ + UNKNOWN_EVENT = 0, START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, + ROTATE_EVENT = 4, INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, + CREATE_FILE_EVENT=8, APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, + DELETE_FILE_EVENT=11, NEW_LOAD_EVENT=12, RAND_EVENT=13 +}; + +enum Int_event_type +{ + INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2 +}; + + +#ifndef MYSQL_CLIENT +class String; +class MYSQL_LOG; +class THD; +#endif + +struct st_relay_log_info; + +class Log_event +{ +public: + my_off_t log_pos; + char *temp_buf; + time_t when; + ulong exec_time; + uint32 server_id; + uint cached_event_len; + uint16 flags; + bool cache_stmt; +#ifndef MYSQL_CLIENT + THD* thd; + + Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt); + Log_event(); + // if mutex is 0, the read will proceed without mutex + static Log_event* read_log_event(IO_CACHE* file, + pthread_mutex_t* log_lock, + bool old_format); + static int read_log_event(IO_CACHE* file, String* packet, + pthread_mutex_t* log_lock); + void set_log_pos(MYSQL_LOG* log); + virtual void pack_info(String* packet); + int net_send(THD* thd, const char* log_name, my_off_t pos); + static void init_show_field_list(List* field_list); + virtual int exec_event(struct st_relay_log_info* rli); + virtual const char* get_db() + { + return thd ? thd->db : 0; + } +#else + // avoid having to link mysqlbinlog against libpthread + static Log_event* read_log_event(IO_CACHE* file, bool old_format); + virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0; + void print_timestamp(FILE* file, time_t *ts = 0); + void print_header(FILE* file); +#endif + + static void *operator new(size_t size) + { + return (void*) my_malloc((uint)size, MYF(MY_WME|MY_FAE)); + } + static void operator delete(void *ptr, size_t size) + { + my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR)); + } + + int write(IO_CACHE* file); + int write_header(IO_CACHE* file); + virtual int write_data(IO_CACHE* file) + { return write_data_header(file) || write_data_body(file); } + virtual int write_data_header(IO_CACHE* file __attribute__((unused))) + { return 0; } + virtual int write_data_body(IO_CACHE* file __attribute__((unused))) + { return 0; } + virtual Log_event_type get_type_code() = 0; + virtual bool is_valid() = 0; + inline bool get_cache_stmt() { return cache_stmt; } + Log_event(const char* buf, bool old_format); + virtual ~Log_event() { free_temp_buf();} + void register_temp_buf(char* buf) { temp_buf = buf; } + void free_temp_buf() + { + if (temp_buf) + { + my_free(temp_buf, MYF(0)); + temp_buf = 0; + } + } + virtual int get_data_size() { return 0;} + virtual int get_data_body_offset() { return 0; } + int get_event_len() + { + return (cached_event_len ? cached_event_len : + (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size())); + } + static Log_event* read_log_event(const char* buf, int event_len, + const char **error, bool old_format); + const char* get_type_str(); +}; + + +class Query_log_event: public Log_event +{ +protected: + char* data_buf; +public: + const char* query; + const char* db; + /* + If we already know the length of the query string + we pass it with q_len, so we would not have to call strlen() + otherwise, set it to 0, in which case, we compute it with strlen() + */ + uint32 q_len; + uint32 db_len; + uint16 error_code; + ulong thread_id; + /* + For events created by Query_log_event::exec_event (and + Load_log_event::exec_event()) we need the *original* thread id, to be able + to log the event with the original (=master's) thread id (fix for + BUG#1686). + */ + ulong slave_proxy_id; +#ifndef MYSQL_CLIENT + + Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, + bool using_trans); + const char* get_db() { return db; } + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Query_log_event(const char* buf, int event_len, bool old_format); + ~Query_log_event() + { + if (data_buf) + { + my_free((gptr) data_buf, MYF(0)); + } + } + Log_event_type get_type_code() { return QUERY_EVENT; } + int write(IO_CACHE* file); + int write_data(IO_CACHE* file); // returns 0 on success, -1 on error + bool is_valid() { return query != 0; } + int get_data_size() + { + return (q_len + db_len + 2 + + 4 // thread_id + + 4 // exec_time + + 2 // error_code + ); + } +}; + + +class Slave_log_event: public Log_event +{ +protected: + char* mem_pool; + void init_from_mem_pool(int data_size); +public: + my_off_t master_pos; + char* master_host; + char* master_log; + int master_host_len; + int master_log_len; + uint16 master_port; + +#ifndef MYSQL_CLIENT + Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli); + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Slave_log_event(const char* buf, int event_len); + ~Slave_log_event(); + int get_data_size(); + bool is_valid() { return master_host != 0; } + Log_event_type get_type_code() { return SLAVE_EVENT; } + int write_data(IO_CACHE* file ); +}; + +class Load_log_event: public Log_event +{ +protected: + int copy_log_event(const char *buf, ulong event_len, bool old_format); + +public: + ulong thread_id; + ulong slave_proxy_id; + uint32 table_name_len; + uint32 db_len; + uint32 fname_len; + uint32 num_fields; + const char* fields; + const uchar* field_lens; + uint32 field_block_len; + + const char* table_name; + const char* db; + const char* fname; + uint32 skip_lines; + sql_ex_info sql_ex; + bool local_fname; + + /* fname doesn't point to memory inside Log_event::temp_buf */ + void set_fname_outside_temp_buf(const char *afname, uint alen) + { + fname= afname; + fname_len= alen; + local_fname= true; + } + /* fname doesn't point to memory inside Log_event::temp_buf */ + int check_fname_outside_temp_buf() + { + return local_fname; + } + +#ifndef MYSQL_CLIENT + String field_lens_buf; + String fields_buf; + + Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg, + const char* table_name_arg, + List& fields_arg, enum enum_duplicates handle_dup, + bool using_trans); + void set_fields(List &fields_arg); + void pack_info(String* packet); + const char* get_db() { return db; } + int exec_event(struct st_relay_log_info* rli) + { + return exec_event(thd->slave_net,rli,0); + } + int exec_event(NET* net, struct st_relay_log_info* rli, + bool use_rli_only_for_errors); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); + void print(FILE* file, bool short_form, char* last_db, bool commented); +#endif + + Load_log_event(const char* buf, int event_len, bool old_format); + ~Load_log_event() + {} + Log_event_type get_type_code() + { + return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT; + } + int write_data_header(IO_CACHE* file); + int write_data_body(IO_CACHE* file); + bool is_valid() { return table_name != 0; } + int get_data_size() + { + return (table_name_len + 2 + db_len + 2 + fname_len + + 4 // thread_id + + 4 // exec_time + + 4 // skip_lines + + 4 // field block len + + sql_ex.data_size() + field_block_len + num_fields); + } + int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; } +}; + +extern char server_version[SERVER_VERSION_LENGTH]; + +class Start_log_event: public Log_event +{ +public: + /* + If this event is at the start of the first binary log since server startup + 'created' should be the timestamp when the event (and the binary log) was + created. + In the other case (i.e. this event is at the start of a binary log created + by FLUSH LOGS or automatic rotation), 'created' should be 0. + This "trick" is used by MySQL >=4.0.14 slaves to know if they must drop the + stale temporary tables or not. + Note that when 'created'!=0, it is always equal to the event's timestamp; + indeed Start_log_event is written only in log.cc where the first + constructor below is called, in which 'created' is set to 'when'. + So in fact 'created' is a useless variable. When it is 0 + we can read the actual value from timestamp ('when') and when it is + non-zero we can read the same value from timestamp ('when'). Conclusion: + - we use timestamp to print when the binlog was created. + - we use 'created' only to know if this is a first binlog or not. + In 3.23.57 we did not pay attention to this identity, so mysqlbinlog in + 3.23.57 does not print 'created the_date' if created was zero. This is now + fixed. + */ + time_t created; + uint16 binlog_version; + char server_version[ST_SERVER_VER_LEN]; + +#ifndef MYSQL_CLIENT + Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION) + { + created = (time_t) when; + memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); + } + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Start_log_event(const char* buf, bool old_format); + ~Start_log_event() {} + Log_event_type get_type_code() { return START_EVENT;} + int write_data(IO_CACHE* file); + bool is_valid() { return 1; } + int get_data_size() + { + return START_HEADER_LEN; + } +}; + + +class Intvar_log_event: public Log_event +{ +public: + ulonglong val; + uchar type; + +#ifndef MYSQL_CLIENT + Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) + :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) + {} + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Intvar_log_event(const char* buf, bool old_format); + ~Intvar_log_event() {} + Log_event_type get_type_code() { return INTVAR_EVENT;} + const char* get_var_type_name(); + int get_data_size() { return sizeof(type) + sizeof(val);} + int write_data(IO_CACHE* file); + bool is_valid() { return 1; } +}; + +/***************************************************************************** + * + * Rand log event class + * + ****************************************************************************/ +class Rand_log_event: public Log_event +{ + public: + ulonglong seed1; + ulonglong seed2; + +#ifndef MYSQL_CLIENT + Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg) + :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg) + {} + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Rand_log_event(const char* buf, bool old_format); + ~Rand_log_event() {} + Log_event_type get_type_code() { return RAND_EVENT;} + int get_data_size() { return sizeof(ulonglong) * 2; } + int write_data(IO_CACHE* file); + bool is_valid() { return 1; } +}; + + +class Stop_log_event: public Log_event +{ +public: +#ifndef MYSQL_CLIENT + Stop_log_event() :Log_event() + {} + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Stop_log_event(const char* buf, bool old_format): + Log_event(buf, old_format) + {} + ~Stop_log_event() {} + Log_event_type get_type_code() { return STOP_EVENT;} + bool is_valid() { return 1; } +}; + + +class Rotate_log_event: public Log_event +{ +public: + const char* new_log_ident; + ulonglong pos; + uint ident_len; + bool alloced; +#ifndef MYSQL_CLIENT + Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg, + uint ident_len_arg = 0, + ulonglong pos_arg = LOG_EVENT_OFFSET) + :Log_event(), new_log_ident(new_log_ident_arg), + pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : + (uint) strlen(new_log_ident_arg)), alloced(0) + {} + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Rotate_log_event(const char* buf, int event_len, bool old_format); + ~Rotate_log_event() + { + if (alloced) + my_free((gptr) new_log_ident, MYF(0)); + } + Log_event_type get_type_code() { return ROTATE_EVENT;} + int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} + bool is_valid() { return new_log_ident != 0; } + int write_data(IO_CACHE* file); +}; + +/* the classes below are for the new LOAD DATA INFILE logging */ + +class Create_file_log_event: public Load_log_event +{ +protected: + /* + Pretend we are Load event, so we can write out just + our Load part - used on the slave when writing event out to + SQL_LOAD-*.info file + */ + bool fake_base; +public: + char* block; + const char *event_buf; + uint block_len; + uint file_id; + bool inited_from_old; + +#ifndef MYSQL_CLIENT + Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg, + const char* table_name_arg, + List& fields_arg, + enum enum_duplicates handle_dup, + char* block_arg, uint block_len_arg, + bool using_trans); + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); + void print(FILE* file, bool short_form, char* last_db, bool enable_local); +#endif + + Create_file_log_event(const char* buf, int event_len, bool old_format); + ~Create_file_log_event() + { + my_free((char*) event_buf, MYF(MY_ALLOW_ZERO_PTR)); + } + + Log_event_type get_type_code() + { + return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT; + } + int get_data_size() + { + return (fake_base ? Load_log_event::get_data_size() : + Load_log_event::get_data_size() + + 4 + 1 + block_len); + } + int get_data_body_offset() + { + return (fake_base ? LOAD_EVENT_OVERHEAD: + LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN); + } + bool is_valid() { return inited_from_old || block != 0; } + int write_data_header(IO_CACHE* file); + int write_data_body(IO_CACHE* file); + /* + Cut out Create_file extentions and + write it as Load event - used on the slave + */ + int write_base(IO_CACHE* file); +}; + + +class Append_block_log_event: public Log_event +{ +public: + char* block; + uint block_len; + uint file_id; + /* + 'db' is filled when the event is created in mysql_load() (the event needs to + have a 'db' member to be well filtered by binlog-*-db rules). 'db' is not + written to the binlog (it's not used by Append_block_log_event::write()), so + it can't be read in the Append_block_log_event(const char* buf, int + event_len) constructor. + In other words, 'db' is used only for filtering by binlog-*-db rules. + Create_file_log_event is different: its 'db' (which is inherited from + Load_log_event) is written to the binlog and can be re-read. + */ + const char* db; + +#ifndef MYSQL_CLIENT + Append_block_log_event(THD* thd, const char* db_arg, char* block_arg, + uint block_len_arg, bool using_trans); + int exec_event(struct st_relay_log_info* rli); + void pack_info(String* packet); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Append_block_log_event(const char* buf, int event_len); + ~Append_block_log_event() {} + Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;} + int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;} + bool is_valid() { return block != 0; } + int write_data(IO_CACHE* file); + const char* get_db() { return db; } +}; + + +class Delete_file_log_event: public Log_event +{ +public: + uint file_id; + const char* db; /* see comment in Append_block_log_event */ + +#ifndef MYSQL_CLIENT + Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans); + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Delete_file_log_event(const char* buf, int event_len); + ~Delete_file_log_event() {} + Log_event_type get_type_code() { return DELETE_FILE_EVENT;} + int get_data_size() { return DELETE_FILE_HEADER_LEN ;} + bool is_valid() { return file_id != 0; } + int write_data(IO_CACHE* file); + const char* get_db() { return db; } +}; + +class Execute_load_log_event: public Log_event +{ +public: + uint file_id; + const char* db; /* see comment in Append_block_log_event */ + +#ifndef MYSQL_CLIENT + Execute_load_log_event(THD* thd, const char* db_arg, bool using_trans); + void pack_info(String* packet); + int exec_event(struct st_relay_log_info* rli); +#else + void print(FILE* file, bool short_form = 0, char* last_db = 0); +#endif + + Execute_load_log_event(const char* buf, int event_len); + ~Execute_load_log_event() {} + Log_event_type get_type_code() { return EXEC_LOAD_EVENT;} + int get_data_size() { return EXEC_LOAD_HEADER_LEN ;} + bool is_valid() { return file_id != 0; } + int write_data(IO_CACHE* file); + const char* get_db() { return db; } +}; + +#ifdef MYSQL_CLIENT +class Unknown_log_event: public Log_event +{ +public: + Unknown_log_event(const char* buf, bool old_format): + Log_event(buf, old_format) + {} + ~Unknown_log_event() {} + void print(FILE* file, bool short_form= 0, char* last_db= 0); + Log_event_type get_type_code() { return UNKNOWN_EVENT;} + bool is_valid() { return 1; } +}; +#endif + +#endif /* _log_event_h */ diff --git a/wcmtools/lib/MySQL-BinLog/docs/log_event.ph b/wcmtools/lib/MySQL-BinLog/docs/log_event.ph new file mode 100755 index 0000000..dc7b40f --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/docs/log_event.ph @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w + +#require '_h2ph_pre.ph'; + +unless(defined(&_log_event_h)) { + eval 'sub _log_event_h () {1;}' unless defined(&_log_event_h); + eval 'sub LOG_READ_EOF () {-1;}' unless defined(&LOG_READ_EOF); + eval 'sub LOG_READ_BOGUS () {-2;}' unless defined(&LOG_READ_BOGUS); + eval 'sub LOG_READ_IO () {-3;}' unless defined(&LOG_READ_IO); + eval 'sub LOG_READ_MEM () {-5;}' unless defined(&LOG_READ_MEM); + eval 'sub LOG_READ_TRUNC () {-6;}' unless defined(&LOG_READ_TRUNC); + eval 'sub LOG_READ_TOO_LARGE () {-7;}' unless defined(&LOG_READ_TOO_LARGE); + eval 'sub LOG_EVENT_OFFSET () {4;}' unless defined(&LOG_EVENT_OFFSET); + eval 'sub BINLOG_VERSION () {3;}' unless defined(&BINLOG_VERSION); + eval 'sub ST_SERVER_VER_LEN () {50;}' unless defined(&ST_SERVER_VER_LEN); + eval 'sub DUMPFILE_FLAG () {0x1;}' unless defined(&DUMPFILE_FLAG); + eval 'sub OPT_ENCLOSED_FLAG () {0x2;}' unless defined(&OPT_ENCLOSED_FLAG); + eval 'sub REPLACE_FLAG () {0x4;}' unless defined(&REPLACE_FLAG); + eval 'sub IGNORE_FLAG () {0x8;}' unless defined(&IGNORE_FLAG); + eval 'sub FIELD_TERM_EMPTY () {0x1;}' unless defined(&FIELD_TERM_EMPTY); + eval 'sub ENCLOSED_EMPTY () {0x2;}' unless defined(&ENCLOSED_EMPTY); + eval 'sub LINE_TERM_EMPTY () {0x4;}' unless defined(&LINE_TERM_EMPTY); + eval 'sub LINE_START_EMPTY () {0x8;}' unless defined(&LINE_START_EMPTY); + eval 'sub ESCAPED_EMPTY () {0x10;}' unless defined(&ESCAPED_EMPTY); + eval 'sub NUM_LOAD_DELIM_STRS () {5;}' unless defined(&NUM_LOAD_DELIM_STRS); + eval 'sub LOG_EVENT_HEADER_LEN () {19;}' unless defined(&LOG_EVENT_HEADER_LEN); + eval 'sub OLD_HEADER_LEN () {13;}' unless defined(&OLD_HEADER_LEN); + eval 'sub QUERY_HEADER_LEN () {(4+ 4+ 1+ 2);}' unless defined(&QUERY_HEADER_LEN); + eval 'sub LOAD_HEADER_LEN () {(4+ 4+ 4+ 1+1+ 4);}' unless defined(&LOAD_HEADER_LEN); + eval 'sub START_HEADER_LEN () {(2+ &ST_SERVER_VER_LEN + 4);}' unless defined(&START_HEADER_LEN); + eval 'sub ROTATE_HEADER_LEN () {8;}' unless defined(&ROTATE_HEADER_LEN); + eval 'sub CREATE_FILE_HEADER_LEN () {4;}' unless defined(&CREATE_FILE_HEADER_LEN); + eval 'sub APPEND_BLOCK_HEADER_LEN () {4;}' unless defined(&APPEND_BLOCK_HEADER_LEN); + eval 'sub EXEC_LOAD_HEADER_LEN () {4;}' unless defined(&EXEC_LOAD_HEADER_LEN); + eval 'sub DELETE_FILE_HEADER_LEN () {4;}' unless defined(&DELETE_FILE_HEADER_LEN); + eval 'sub EVENT_TYPE_OFFSET () {4;}' unless defined(&EVENT_TYPE_OFFSET); + eval 'sub SERVER_ID_OFFSET () {5;}' unless defined(&SERVER_ID_OFFSET); + eval 'sub EVENT_LEN_OFFSET () {9;}' unless defined(&EVENT_LEN_OFFSET); + eval 'sub LOG_POS_OFFSET () {13;}' unless defined(&LOG_POS_OFFSET); + eval 'sub FLAGS_OFFSET () {17;}' unless defined(&FLAGS_OFFSET); + eval 'sub ST_BINLOG_VER_OFFSET () {0;}' unless defined(&ST_BINLOG_VER_OFFSET); + eval 'sub ST_SERVER_VER_OFFSET () {2;}' unless defined(&ST_SERVER_VER_OFFSET); + eval 'sub ST_CREATED_OFFSET () {( &ST_SERVER_VER_OFFSET + &ST_SERVER_VER_LEN);}' unless defined(&ST_CREATED_OFFSET); + eval 'sub SL_MASTER_PORT_OFFSET () {8;}' unless defined(&SL_MASTER_PORT_OFFSET); + eval 'sub SL_MASTER_POS_OFFSET () {0;}' unless defined(&SL_MASTER_POS_OFFSET); + eval 'sub SL_MASTER_HOST_OFFSET () {10;}' unless defined(&SL_MASTER_HOST_OFFSET); + eval 'sub Q_THREAD_ID_OFFSET () {0;}' unless defined(&Q_THREAD_ID_OFFSET); + eval 'sub Q_EXEC_TIME_OFFSET () {4;}' unless defined(&Q_EXEC_TIME_OFFSET); + eval 'sub Q_DB_LEN_OFFSET () {8;}' unless defined(&Q_DB_LEN_OFFSET); + eval 'sub Q_ERR_CODE_OFFSET () {9;}' unless defined(&Q_ERR_CODE_OFFSET); + eval 'sub Q_DATA_OFFSET () { &QUERY_HEADER_LEN;}' unless defined(&Q_DATA_OFFSET); + eval 'sub I_TYPE_OFFSET () {0;}' unless defined(&I_TYPE_OFFSET); + eval 'sub I_VAL_OFFSET () {1;}' unless defined(&I_VAL_OFFSET); + eval 'sub RAND_SEED1_OFFSET () {0;}' unless defined(&RAND_SEED1_OFFSET); + eval 'sub RAND_SEED2_OFFSET () {8;}' unless defined(&RAND_SEED2_OFFSET); + eval 'sub L_THREAD_ID_OFFSET () {0;}' unless defined(&L_THREAD_ID_OFFSET); + eval 'sub L_EXEC_TIME_OFFSET () {4;}' unless defined(&L_EXEC_TIME_OFFSET); + eval 'sub L_SKIP_LINES_OFFSET () {8;}' unless defined(&L_SKIP_LINES_OFFSET); + eval 'sub L_TBL_LEN_OFFSET () {12;}' unless defined(&L_TBL_LEN_OFFSET); + eval 'sub L_DB_LEN_OFFSET () {13;}' unless defined(&L_DB_LEN_OFFSET); + eval 'sub L_NUM_FIELDS_OFFSET () {14;}' unless defined(&L_NUM_FIELDS_OFFSET); + eval 'sub L_SQL_EX_OFFSET () {18;}' unless defined(&L_SQL_EX_OFFSET); + eval 'sub L_DATA_OFFSET () { &LOAD_HEADER_LEN;}' unless defined(&L_DATA_OFFSET); + eval 'sub R_POS_OFFSET () {0;}' unless defined(&R_POS_OFFSET); + eval 'sub R_IDENT_OFFSET () {8;}' unless defined(&R_IDENT_OFFSET); + eval 'sub CF_FILE_ID_OFFSET () {0;}' unless defined(&CF_FILE_ID_OFFSET); + eval 'sub CF_DATA_OFFSET () { &CREATE_FILE_HEADER_LEN;}' unless defined(&CF_DATA_OFFSET); + eval 'sub AB_FILE_ID_OFFSET () {0;}' unless defined(&AB_FILE_ID_OFFSET); + eval 'sub AB_DATA_OFFSET () { &APPEND_BLOCK_HEADER_LEN;}' unless defined(&AB_DATA_OFFSET); + eval 'sub EL_FILE_ID_OFFSET () {0;}' unless defined(&EL_FILE_ID_OFFSET); + eval 'sub DF_FILE_ID_OFFSET () {0;}' unless defined(&DF_FILE_ID_OFFSET); + eval 'sub QUERY_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &QUERY_HEADER_LEN);}' unless defined(&QUERY_EVENT_OVERHEAD); + eval 'sub QUERY_DATA_OFFSET () {( &LOG_EVENT_HEADER_LEN+ &QUERY_HEADER_LEN);}' unless defined(&QUERY_DATA_OFFSET); + eval 'sub ROTATE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &ROTATE_HEADER_LEN);}' unless defined(&ROTATE_EVENT_OVERHEAD); + eval 'sub LOAD_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &LOAD_HEADER_LEN);}' unless defined(&LOAD_EVENT_OVERHEAD); + eval 'sub CREATE_FILE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ + &LOAD_HEADER_LEN+ &CREATE_FILE_HEADER_LEN);}' unless defined(&CREATE_FILE_EVENT_OVERHEAD); + eval 'sub DELETE_FILE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &DELETE_FILE_HEADER_LEN);}' unless defined(&DELETE_FILE_EVENT_OVERHEAD); + eval 'sub EXEC_LOAD_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &EXEC_LOAD_HEADER_LEN);}' unless defined(&EXEC_LOAD_EVENT_OVERHEAD); + eval 'sub APPEND_BLOCK_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &APPEND_BLOCK_HEADER_LEN);}' unless defined(&APPEND_BLOCK_EVENT_OVERHEAD); + eval 'sub BINLOG_MAGIC () {"\\xfe\\x62\\x69\\x6e";}' unless defined(&BINLOG_MAGIC); + eval 'sub LOG_EVENT_TIME_F () {0x1;}' unless defined(&LOG_EVENT_TIME_F); + eval 'sub LOG_EVENT_FORCED_ROTATE_F () {0x2;}' unless defined(&LOG_EVENT_FORCED_ROTATE_F); + eval("sub UNKNOWN_EVENT () { 0; }") unless defined(&UNKNOWN_EVENT); + eval("sub START_EVENT () { 1; }") unless defined(&START_EVENT); + eval("sub QUERY_EVENT () { 2; }") unless defined(&QUERY_EVENT); + eval("sub STOP_EVENT () { 3; }") unless defined(&STOP_EVENT); + eval("sub ROTATE_EVENT () { 4; }") unless defined(&ROTATE_EVENT); + eval("sub INTVAR_EVENT () { 5; }") unless defined(&INTVAR_EVENT); + eval("sub LOAD_EVENT () { 6; }") unless defined(&LOAD_EVENT); + eval("sub SLAVE_EVENT () { 7; }") unless defined(&SLAVE_EVENT); + eval("sub CREATE_FILE_EVENT () { 8; }") unless defined(&CREATE_FILE_EVENT); + eval("sub APPEND_BLOCK_EVENT () { 9; }") unless defined(&APPEND_BLOCK_EVENT); + eval("sub EXEC_LOAD_EVENT () { 10; }") unless defined(&EXEC_LOAD_EVENT); + eval("sub DELETE_FILE_EVENT () { 11; }") unless defined(&DELETE_FILE_EVENT); + eval("sub NEW_LOAD_EVENT () { 12; }") unless defined(&NEW_LOAD_EVENT); + eval("sub RAND_EVENT () { 13; }") unless defined(&RAND_EVENT); + eval("sub INVALID_INT_EVENT () { 0; }") unless defined(&INVALID_INT_EVENT); + eval("sub LAST_INSERT_ID_EVENT () { 1; }") unless defined(&LAST_INSERT_ID_EVENT); + eval("sub INSERT_ID_EVENT () { 2; }") unless defined(&INSERT_ID_EVENT); +} +1; diff --git a/wcmtools/lib/MySQL-BinLog/experiments/cpptokenizer.pl b/wcmtools/lib/MySQL-BinLog/experiments/cpptokenizer.pl new file mode 100755 index 0000000..83c9fea --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/experiments/cpptokenizer.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl -w +# +# Learning Text::CPP... conclusion: not what I need. +# +# + +package cpptokenizer; + +use Text::CPP; +use Data::Dumper; + +$Data::Dumper::TERSE = 1; +$Data::Dumper::INDENT = 1; + +my $reader = new Text::CPP ( Language => "GNUC99" ); + +my ( $text, $type, $prettytype, $flags ); + +foreach my $file ( @ARGV ) { + print "File: $file\n", '-' x 70, "\n"; + + $reader->read( $file ); + + #print join("\n", $reader->tokens); + + while ( ($text, $type, $flags) = $reader->token ) { + $prettytype = $reader->type( $type ); + chomp( $text ); + #print "$prettytype: $text ($type) +$flags\n"; + print Data::Dumper->Dumpxs( [$text,$type,$flags,$prettytype], + [qw{text type flags prettytype}] ), "\n"; + print "---\n"; + } + + print "\n\n"; +} + + diff --git a/wcmtools/lib/MySQL-BinLog/experiments/try.pl b/wcmtools/lib/MySQL-BinLog/experiments/try.pl new file mode 100755 index 0000000..847fc99 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/experiments/try.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w +package try; +use strict; + +BEGIN { + use lib qw{lib}; + use MySQL::BinLog; +} + +my %connect_params = ( + hostname => 'whitaker.lj', + database => 'livejournal', + user => 'slave', + password => 'm&s', + port => 3337, + debug => 1, + + log_slave_id => 512, +); + +sub handler { + my $ev = shift; + print( ('-' x 70), "\n", + ">>> QUERY: ", $ev->query_data, "\n", + ('-' x 70), "\n" ); +} + +my $filename = shift @ARGV; + +my $log = MySQL::BinLog->open( $filename ); +#my $log = MySQL::BinLog->connect( %connect_params ); + +my @res = $log->handle_events( \&handler, MySQL::QUERY_EVENT ); + diff --git a/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog.pm b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog.pm new file mode 100755 index 0000000..4ff3fbe --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog.pm @@ -0,0 +1,244 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +MySQL::BinLog - Binary log parser classes + +=head1 SYNOPSIS + + use MySQL::BinLog (); + + my $log = MySQL::BinLog->open( "Foo-relay.bin.001" ); + + # -or- + + die unless $MySQL::BinLog::HaveNet; + my $log = MySQL::BinLog->connect( + hostname => 'db.example.com', + database => 'sales', + user => 'salesapp', + password => '', + port => 3337, + + log_name => '', + log_pos => 4, + log_slave_id => 10, + ); + + $log->handle_events( \&print_queries, MySQL::BinLog::QUERY_EVENT ); + + sub print_queries { + my $ev = shift; + print "Query: ", $ev->query_data, "\n"; + } + + +=head1 REQUIRES + +I + +=head1 DESCRIPTION + +This is a collection of Perl classes for parsing a MySQL binlog. + +=head1 AUTHOR + +Michael Granger + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package MySQL::BinLog; +use strict; +use warnings qw{all}; + +BEGIN { + # Versioning stuff + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: BinLog.pm,v 1.2 2004/11/17 21:58:39 marksmith Exp $; + + use constant TRUE => 1; + use constant FALSE => 0; + + # Subordinate classes + use MySQL::BinLog::Constants qw{}; + use MySQL::BinLog::Events qw{}; + use MySQL::BinLog::Header qw{}; + + # Try to load Net::MySQL, but no worries if we can't until they try to use + # ->connect. + use vars qw{$HaveNet $NetError}; + $HaveNet = eval { require MySQL::BinLog::Net; 1 }; + $NetError = $@; + + use Carp qw{croak confess carp}; + use IO::File qw{}; + use Fcntl qw{O_RDONLY}; +} + + +### (CONSTRUCTOR) METHOD: new +### Return a new generic MySQL::BinLog object. +sub new { + my $class = shift or confess "Cannot be used as a function"; + return bless { + fh => undef, + type => undef, + }, $class; +} + + +### (CONSTRUCTOR) METHOD: open( $filename ) +### Return a MySQL::BinLog object that will read events from the file specified +### by I. +sub open { + my $class = shift or confess "Cannot be used as a function"; + my $filename = shift or croak "Missing argument: filename"; + + my $ifh = new IO::File $filename, O_RDONLY + or croak "open: $filename: $!"; + $ifh->seek( 4, 0 ); + + my $self = $class->new; + $self->{fh} = $ifh; + + return $self; +} + + +### (CONSTRUCTOR) METHOD: connect( %connect_params ) +### Open a connection to a MySQL server over the network and read events from +### it. The connection parameters are the same as those passed to Net::MySQL. If +### Net::MySQL is not installed, this method will raise an exception. +sub connect { + my $class = shift or confess "Cannot be used as a function"; + my %connect_params = @_; + + croak "Net::MySQL not available: $NetError" unless $HaveNet; + my $self = $class->new; + + my ( + $logname, + $pos, + $slave_id, + ); + + $logname = delete $connect_params{log_name} || ''; + $pos = delete $connect_params{log_pos} || 0; + $slave_id = delete $connect_params{log_slave_id} || 128; + + $self->{net} = new MySQL::BinLog::Net ( %connect_params ); + $self->{net}->start_binlog( $slave_id, $logname, $pos ); + + return $self; +} + + +##################################################################### +### I N S T A N C E M E T H O D S +##################################################################### + + +### METHOD: read_next_event() +### Read the next event from the registered source and return it. +sub read_next_event { + my $self = shift; + + # :FIXME: This is some ugly inexcusably ugly shit, but I'm hacking all the + # IO into here to get something working, but it really should be made + # cleaner by separating out the socket IO routine into the ::Net class and + # the file IO into a new File class that reads from a file in an optimized + # fashion. + + my $event_data; + + # Reading from a file -- have to read the header, figure out the length of + # the rest of the event data, then read the rest. + if ( $self->{fh} ) { + $event_data = $self->readbytes( $self->{fh}, MySQL::LOG_EVENT_HEADER_LEN ); + my $len = unpack( 'V', substr($event_data, 9, 4) ); + $event_data .= $self->readbytes( $self->{fh}, + $len - MySQL::LOG_EVENT_HEADER_LEN ); + } + + # Reading from a real master + elsif ( $self->{net} ) { + $event_data = $self->{net}->read_packet; + } + + # An object without a reader + else { + croak "Cannot read without an event source."; + } + + # Let the event class parse the event + return MySQL::BinLog::Event->read_event( $event_data ); +} + + + + +### METHOD: handle_events( \&handler[, @types] ) +### Start reading events from whatever source is registered, handling those of +### the types specified in I with the given I. If no I +### are given, all events will be sent to the I. Events are sent as +### instances of the MySQL::BinLog::Event classes. +sub handle_events { + my $self = shift or croak "Cannot be used as a function."; + my ( $handler, @types ) = @_; + + my @rv = (); + + while (( my $event = $self->read_next_event )) { + my $etype = $event->header->event_type; + next if @types && !grep { $etype == $_ } @types; + + push @rv, $handler->( $event ); + } + + return @rv; +} + + +### FUNCTION: readbytes( $fh, $len ) +### Read and return I bytes from the specified I. +sub readbytes { + my ( $self, $fh, $len ) = @_; + my ( $buf, $rval, $bytes ) = ('', '', 0); + + until ( length $rval == $len ) { + $bytes = $fh->read( $buf, $len - length $rval ); + if ( !defined $bytes ) { + if ( $!{EAGAIN} ) { next } + die "Read error: $!"; + } elsif ( !$bytes && $fh->eof ) { + die "EOF before reading $len bytes.\n"; + } + $rval .= $buf; + } + + return $rval; +} + + + +### Destructors +DESTROY {} +END {} + + +1; + + diff --git a/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Constants.pm b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Constants.pm new file mode 100755 index 0000000..6d785be --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Constants.pm @@ -0,0 +1,105 @@ +package MySQL; + +BEGIN { + no warnings 'redefine'; + + sub LOG_READ_EOF () {-1;} + sub LOG_READ_BOGUS () {-2;} + sub LOG_READ_IO () {-3;} + sub LOG_READ_MEM () {-5;} + sub LOG_READ_TRUNC () {-6;} + sub LOG_READ_TOO_LARGE () {-7;} + sub LOG_EVENT_OFFSET () {4;} + sub BINLOG_VERSION () {3;} + sub ST_SERVER_VER_LEN () {50;} + sub DUMPFILE_FLAG () {0x1;} + sub OPT_ENCLOSED_FLAG () {0x2;} + sub REPLACE_FLAG () {0x4;} + sub IGNORE_FLAG () {0x8;} + sub FIELD_TERM_EMPTY () {0x1;} + sub ENCLOSED_EMPTY () {0x2;} + sub LINE_TERM_EMPTY () {0x4;} + sub LINE_START_EMPTY () {0x8;} + sub ESCAPED_EMPTY () {0x10;} + sub NUM_LOAD_DELIM_STRS () {5;} + sub LOG_EVENT_HEADER_LEN () {19;} + sub OLD_HEADER_LEN () {13;} + sub QUERY_HEADER_LEN () {(4+ 4+ 1+ 2);} + sub LOAD_HEADER_LEN () {(4+ 4+ 4+ 1+1+ 4);} + sub START_HEADER_LEN () {(2+ &ST_SERVER_VER_LEN + 4);} + sub ROTATE_HEADER_LEN () {8;} + sub CREATE_FILE_HEADER_LEN () {4;} + sub APPEND_BLOCK_HEADER_LEN () {4;} + sub EXEC_LOAD_HEADER_LEN () {4;} + sub DELETE_FILE_HEADER_LEN () {4;} + sub EVENT_TYPE_OFFSET () {4;} + sub SERVER_ID_OFFSET () {5;} + sub EVENT_LEN_OFFSET () {9;} + sub LOG_POS_OFFSET () {13;} + sub FLAGS_OFFSET () {17;} + sub ST_BINLOG_VER_OFFSET () {0;} + sub ST_SERVER_VER_OFFSET () {2;} + sub ST_CREATED_OFFSET () {( &ST_SERVER_VER_OFFSET + &ST_SERVER_VER_LEN);} + sub SL_MASTER_PORT_OFFSET () {8;} + sub SL_MASTER_POS_OFFSET () {0;} + sub SL_MASTER_HOST_OFFSET () {10;} + sub Q_THREAD_ID_OFFSET () {0;} + sub Q_EXEC_TIME_OFFSET () {4;} + sub Q_DB_LEN_OFFSET () {8;} + sub Q_ERR_CODE_OFFSET () {9;} + sub Q_DATA_OFFSET () { &QUERY_HEADER_LEN;} + sub I_TYPE_OFFSET () {0;} + sub I_VAL_OFFSET () {1;} + sub RAND_SEED1_OFFSET () {0;} + sub RAND_SEED2_OFFSET () {8;} + sub L_THREAD_ID_OFFSET () {0;} + sub L_EXEC_TIME_OFFSET () {4;} + sub L_SKIP_LINES_OFFSET () {8;} + sub L_TBL_LEN_OFFSET () {12;} + sub L_DB_LEN_OFFSET () {13;} + sub L_NUM_FIELDS_OFFSET () {14;} + sub L_SQL_EX_OFFSET () {18;} + sub L_DATA_OFFSET () { &LOAD_HEADER_LEN;} + sub R_POS_OFFSET () {0;} + sub R_IDENT_OFFSET () {8;} + sub CF_FILE_ID_OFFSET () {0;} + sub CF_DATA_OFFSET () { &CREATE_FILE_HEADER_LEN;} + sub AB_FILE_ID_OFFSET () {0;} + sub AB_DATA_OFFSET () { &APPEND_BLOCK_HEADER_LEN;} + sub EL_FILE_ID_OFFSET () {0;} + sub DF_FILE_ID_OFFSET () {0;} + sub QUERY_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &QUERY_HEADER_LEN);} + sub QUERY_DATA_OFFSET () {( &LOG_EVENT_HEADER_LEN+ &QUERY_HEADER_LEN);} + sub ROTATE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &ROTATE_HEADER_LEN);} + sub LOAD_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &LOAD_HEADER_LEN);} + sub CREATE_FILE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ + &LOAD_HEADER_LEN+ &CREATE_FILE_HEADER_LEN);} + sub DELETE_FILE_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &DELETE_FILE_HEADER_LEN);} + sub EXEC_LOAD_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &EXEC_LOAD_HEADER_LEN);} + sub APPEND_BLOCK_EVENT_OVERHEAD () {( &LOG_EVENT_HEADER_LEN+ &APPEND_BLOCK_HEADER_LEN);} + sub BINLOG_MAGIC () {"\\xfe\\x62\\x69\\x6e";} + sub LOG_EVENT_TIME_F () {0x1;} + sub LOG_EVENT_FORCED_ROTATE_F () {0x2;} + sub UNKNOWN_EVENT () { 0; } + sub START_EVENT () { 1; } + sub QUERY_EVENT () { 2; } + sub STOP_EVENT () { 3; } + sub ROTATE_EVENT () { 4; } + sub INTVAR_EVENT () { 5; } + sub LOAD_EVENT () { 6; } + sub SLAVE_EVENT () { 7; } + sub CREATE_FILE_EVENT () { 8; } + sub APPEND_BLOCK_EVENT () { 9; } + sub EXEC_LOAD_EVENT () { 10; } + sub DELETE_FILE_EVENT () { 11; } + sub NEW_LOAD_EVENT () { 12; } + sub RAND_EVENT () { 13; } + sub INVALID_INT_EVENT () { 0; } + sub LAST_INSERT_ID_EVENT () { 1; } + sub INSERT_ID_EVENT () { 2; } +} + + + + +1; + diff --git a/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Events.pm b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Events.pm new file mode 100755 index 0000000..538f482 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Events.pm @@ -0,0 +1,793 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +MySQL::BinLog::Event - Event class for MySQL binlog parsing + +=head1 SYNOPSIS + + use MySQL::BinLog::Event qw(); + + my $event = MySQL::BinLog::Event->read_event( $header, $data ); + +=head1 REQUIRES + +I + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package MySQL::BinLog::Event; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + ### Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Events.pm,v 1.2 2004/11/17 21:58:40 marksmith Exp $; + + # MySQL classes + use MySQL::BinLog::Header qw{}; + use Carp qw{croak confess carp}; + use Scalar::Util qw{blessed}; + + use fields qw{header rawdata}; + use base qw{fields}; +} + +our $AUTOLOAD; + +# Maps an event type to a subclass +our @ClassMap = qw( + UnknownEvent + StartEvent + QueryEvent + StopEvent + RotateEvent + IntvarEvent + LoadEvent + SlaveEvent + CreateFileEvent + AppendBlockEvent + ExecLoadEvent + DeleteFileEvent + NewLoadEvent + RandEvent + UserVarEvent +); + + +### (FACTORY) METHOD: read_event( $fh ) +### Read the next event from the given string I and return it as a +### C object. +sub read_event { + my $class = shift; + my $rawdata = shift; + my @desired_types = @_; + + my ( + $hdata, + $header, + $datalen, + $event_data, + $reallen, + $event_class, + ); + + debugMsg( "Reading event from ", length $rawdata, " byes of raw data.\n" ); + + # Read the header data and create the header object + # :TODO: only handles "new" headers; old headers are shorter. Need to + # document which version this changed and mention this in the docs. + $hdata = substr( $rawdata, 0, MySQL::LOG_EVENT_HEADER_LEN, '' ); + $header = new MySQL::BinLog::Header $hdata; + + # Read the event data + $datalen = $header->{event_len} - MySQL::LOG_EVENT_HEADER_LEN; + debugMsg( "Event data is $header->{event_len} bytes long.\n" ); + $event_data = substr( $rawdata, 0, $datalen, '' ); + debugMsg( "Read ", length $event_data, " bytes of event data.\n" ); + + $reallen = length $event_data; + croak "Short read for event data ($reallen of $datalen bytes)" + unless $reallen == $datalen; + + # Figure out which class implements the event type and create one with the + # header and data + $event_class = sprintf "MySQL::BinLog::%s", $ClassMap[ $header->{event_type} ]; + return $event_class->new( $header, $event_data ); +} + + + +### (CONSTRUCTOR) METHOD: new( $header, $raw_data ) +### Construct a new Event with the specified I

      and I. This is +### only meant to the called from a subclass. +sub new { + my MySQL::BinLog::Event $self = shift; + my ( $header, $data ) = @_; + + die "Instantiation of abstract class" unless ref $self; + + $self->{header} = $header; + $self->{rawdata} = $data; + + return $self; +} + + +# Accessor-generator + +### (PROXY) METHOD: AUTOLOAD( @args ) +### Proxy method to build (non-translucent) object accessors. +sub AUTOLOAD { + my MySQL::BinLog::Event $self = shift; + ( my $name = $AUTOLOAD ) =~ s{.*::}{}; + + ### Build an accessor for extant attributes + if ( blessed $self && exists $self->{$name} ) { + + ### Define an accessor for this attribute + my $method = sub { + my MySQL::BinLog::Event $closureSelf = shift; + + $closureSelf->{$name} = shift if @_; + return $closureSelf->{$name}; + }; + + ### Install the new method in the symbol table + NO_STRICT_REFS: { + no strict 'refs'; + *{$AUTOLOAD} = $method; + } + + ### Now jump to the new method after sticking the self-ref back onto the + ### stack + unshift @_, $self; + goto &$AUTOLOAD; + } + + ### Try to delegate to our parent's version of the method + my $parentMethod = "SUPER::$name"; + return $self->$parentMethod( @_ ); +} + + + + + +### Destructors +DESTROY {} +END {} + + +### Utility functions + +### Debugging function -- switch the commented one for debugging or no. +sub debugMsg {} +#sub debugMsg { print STDERR @_ } + + + +##################################################################### +### S T A R T E V E N T C L A S S +##################################################################### +package MySQL::BinLog::StartEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{binlog_ver server_ver created}; + + use constant PACK_TEMPLATE => 'va8a*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new StartEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::StartEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{binlog_ver server_ver created}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::StartEvent $self = shift; + return join( ':', @{$self}{qw{binlog_ver server_ver created}} ); +} + + + +##################################################################### +### Q U E R Y E V E N T C L A S S +##################################################################### +package MySQL::BinLog::QueryEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{thread_id exec_time db_len err_code dbname query_data}; + + # 4 + 4 + 1 + 2 + variable length data field. + use constant PACK_TEMPLATE => 'VVCva*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new QueryEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::QueryEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + + # The last bit needs further unpacking with a length that is in the data + # extracted via the first template. If db_len immediately preceded the + # query data it could all be done in one unpack with 'c/a' or something, + # but alas... + my $template = sprintf( 'a%da*', $fields[2] ); # $fields[2] = length of dbname + push @fields, unpack( $template, pop @fields ); + + @{$self}{qw{thread_id exec_time db_len err_code dbname query_data}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::QueryEvent $self = shift; + return join( ':', @{$self}{qw{thread_id exec_time db_len err_code dbname query_data}} ); +} + + +##################################################################### +### S T O P E V E N T C L A S S +##################################################################### +package MySQL::BinLog::StopEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{}; # Stop event has no fields +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new StopEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::StopEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::StopEvent $self = shift; + return join( ':', @{$self}{qw{}} ); +} + + +##################################################################### +### R O T A T E E V E N T C L A S S +##################################################################### +package MySQL::BinLog::RotateEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{pos ident}; + + use constant PACK_TEMPLATE => 'a8'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new RotateEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::RotateEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{pos ident}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::RotateEvent $self = shift; + return join( ':', @{$self}{qw{pos ident}} ); +} + + +##################################################################### +### I N T V A R E V E N T C L A S S +##################################################################### +package MySQL::BinLog::IntvarEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{type val}; + + use constant PACK_TEMPLATE => 'Ca8'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new IntvarEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::IntvarEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{type val}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::IntvarEvent $self = shift; + return join( ':', @{$self}{qw{type val}} ); +} + + +##################################################################### +### L O A D E V E N T C L A S S +##################################################################### +package MySQL::BinLog::LoadEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}; + + use constant PACK_TEMPLATE => 'VVVCCVa*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new LoadEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::LoadEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::LoadEvent $self = shift; + return join( ':', @{$self}{qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}} ); +} + + + +##################################################################### +### S L A V E E V E N T C L A S S +##################################################################### +package MySQL::BinLog::SlaveEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{master_pos master_port master_host}; + + use constant PACK_TEMPLATE => 'a8va*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new SlaveEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::SlaveEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{master_pos master_port master_host}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::SlaveEvent $self = shift; + return join( ':', @{$self}{qw{master_pos master_port master_host}} ); +} + + + +##################################################################### +### C R E A T E F I L E E V E N T C L A S S +##################################################################### +package MySQL::BinLog::CreateFileEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}; + + use constant PACK_TEMPLATE => 'VVVCCVa*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new CreateFileEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::CreateFileEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::CreateFileEvent $self = shift; + return join( ':', @{$self}{qw{thread_id exec_time skip_lines tbl_len db_len num_fields sql_ex ldata}} ); +} + + +##################################################################### +### A P P E N D B L O C K E V E N T C L A S S +##################################################################### +package MySQL::BinLog::AppendBlockEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{file_id data}; + + use constant PACK_TEMPLATE => 'Va*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new AppendBlockEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::AppendBlockEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{file_id data}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::AppendBlockEvent $self = shift; + return join( ':', @{$self}{qw{file_id data}} ); +} + + +##################################################################### +### E X E C L O A D E V E N T C L A S S +##################################################################### +package MySQL::BinLog::ExecLoadEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{file_id}; + + use constant PACK_TEMPLATE => 'V'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new ExecLoadEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::ExecLoadEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{file_id}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::ExecLoadEvent $self = shift; + return join( ':', @{$self}{qw{file_id}} ); +} + + +##################################################################### +### D E L E T E F I L E E V E N T C L A S S +##################################################################### +package MySQL::BinLog::DeleteFileEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{file_id}; + + use constant PACK_TEMPLATE => 'V'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new DeleteFileEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::DeleteFileEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{file_id}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::DeleteFileEvent $self = shift; + return join( ':', @{$self}{qw{file_id}} ); +} + + +##################################################################### +### N E W L O A D E V E N T C L A S S +##################################################################### +package MySQL::BinLog::NewLoadEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new NewLoadEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::NewLoadEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + # I don't think these have any data (?) -MG + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::NewLoadEvent $self = shift; + return '(New_load)'; +} + + + +##################################################################### +### R A N D E V E N T C L A S S +##################################################################### +package MySQL::BinLog::RandEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{seed1 seed2}; + + use constant PACK_TEMPLATE => 'a8a8'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new RandEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::RandEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + @{$self}{qw{seed1 seed2}} = @fields; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::RandEvent $self = shift; + return join( ':', @{$self}{qw{seed1 seed2}} ); +} + + + + +##################################################################### +### U S E R V A R E V E N T C L A S S +##################################################################### + +# USER_VAR_EVENT +# o 4 bytes: the size of the name of the user variable. +# o variable-sized part: A concatenation. First is the name of the +# user variable. Second is one byte, non-zero if the content of the +# variable is the SQL value NULL, ASCII 0 otherwise. If this bytes was +# ASCII 0, then the following parts exist in the event. Third is one +# byte, the type of the user variable, which corresponds to elements of +# enum Item_result defined in `include/mysql_com.h'. Fourth is 4 bytes, +# the number of the character set of the user variable (needed for a +# string variable). Fifth is 4 bytes, the size of the user variable's +# value (corresponds to member val_len of class Item_string). Sixth is +# variable-sized: for a string variable it is the string, for a float or +# integer variable it is its value in 8 bytes. + +package MySQL::BinLog::UserVarEvent; +use strict; + +BEGIN { + use base 'MySQL::BinLog::Event'; + use fields qw{varname value}; + + use constant PACK_TEMPLATE => 'V/aca*'; +} + + +### (CONSTRUCTOR) METHOD: new( $header_obj, $raw_data ) +### Create a new UserVarEvent object from the given I and I +### (a MySQL::BinLog::Header object). +sub new { + my MySQL::BinLog::UserVarEvent $self = shift; + + $self = fields::new( $self ); + $self->SUPER::new( @_ ); + + if ( $self->{rawdata} ) { + my @fields = unpack PACK_TEMPLATE, $self->{rawdata}; + + # If the the second field is null, the value is undef. Otherwise, + # unpack the value + if ( $fields[1] eq "\0" ) { + $fields[2] = undef; + } else { + my ( $type, $charset, $len, $data ) = unpack 'cVVa*', $fields[2]; + $fields[2] = { + type => $type, + charset => $charset, + len => $len, + data => $data, + }; + } + + @{$self}{qw{varname value}} = @fields[0, 2]; + } + + return $self; +} + + +### METHOD: stringify() +### Return a representation of the event as a human-readable string. +sub stringify { + my MySQL::BinLog::UserVarEvent $self = shift; + # :FIXME: This will obviously have to take into account the fact that the + # value field is a complex datatype or undef. + return join( ':', @{$self}{qw{varname value}} ); +} + + + +1; + + diff --git a/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Header.pm b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Header.pm new file mode 100755 index 0000000..c0039d8 --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Header.pm @@ -0,0 +1,158 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +MySQL::BinLog::Header - Per-event MySQL binlog header class + +=head1 SYNOPSIS + + use MySQL::BinLog::Header qw(); + use MySQL::Constants qw(LOG_EVENT_HEADER_LEN); + + my $hdata = substr( $data, 0, LOG_EVENT_HEADER_LEN ); + my $header = new MySQL::BinLog::Header $hdata; + + $header->event_type; + $header->server_id; + $header->event_len; + $header->log_pos; + $header->flags; + +=head1 REQUIRES + +I + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package MySQL::BinLog::Header; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + # Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Header.pm,v 1.2 2004/11/17 21:58:40 marksmith Exp $; + + # Data format template and fields definition + use constant PACK_TEMPLATE => 'VcVVVv'; + use fields qw{timestamp event_type server_id event_len log_pos flags}; + use base qw{fields}; + + # MySQL modules + use MySQL::BinLog::Constants qw{:all}; + + # Other modules + use Data::Dumper; + use Scalar::Util qw{blessed}; +} + + +our $AUTOLOAD; + + +### (CONSTRUCTOR) new( $data ) +### Construct a new MySQL::BinLog::::Header object from the given header data. +sub new { + my MySQL::BinLog::Header $self = shift; + my $data = shift || ''; + + debugMsg( "Creating a new ", __PACKAGE__, " object for header: ", + hexdump($data), ".\n" ); + die "Invalid header" unless length $data == MySQL::LOG_EVENT_HEADER_LEN; + $self = fields::new( $self ) unless ref $self; + + # Extract the fields or provide defaults + my @fields = (); + if ( $data ) { + @fields = unpack PACK_TEMPLATE, $data; + debugMsg( "Unpacked fields are: ", Data::Dumper->Dumpxs([\@fields], [qw{fields}]), "\n" ); + } else { + @fields = ( time, MySQL::UNKNOWN_EVENT, 0, 0, 0, 0 ); + } + + @{$self}{qw{timestamp event_type server_id event_len log_pos flags}} = @fields; + + debugMsg( "Returning header: ", Data::Dumper->Dumpxs([$self]), ".\n" ); + return $self; +} + + +# Accessor-generator + +### (PROXY) METHOD: AUTOLOAD( @args ) +### Proxy method to build (non-translucent) object accessors. +sub AUTOLOAD { + my MySQL::BinLog::Header $self = shift; + ( my $name = $AUTOLOAD ) =~ s{.*::}{}; + + ### Build an accessor for extant attributes + if ( blessed $self && exists $self->{$name} ) { + + ### Define an accessor for this attribute + my $method = sub { + my MySQL::BinLog::Header $closureSelf = shift; + + $closureSelf->{$name} = shift if @_; + return $closureSelf->{$name}; + }; + + ### Install the new method in the symbol table + NO_STRICT_REFS: { + no strict 'refs'; + *{$AUTOLOAD} = $method; + } + + ### Now jump to the new method after sticking the self-ref back onto the + ### stack + unshift @_, $self; + goto &$AUTOLOAD; + } + + ### Try to delegate to our parent's version of the method + my $parentMethod = "SUPER::$name"; + return $self->$parentMethod( @_ ); +} + + + +### Utility functions + +#sub debugMsg { print STDERR @_ } +sub debugMsg {} +sub hexdump { return join( ' ', map {sprintf '%02x', ord($_)} split('', $_[0])) } + + + +### Destructors +DESTROY {} +END {} + + +1; + + diff --git a/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Net.pm b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Net.pm new file mode 100755 index 0000000..0c02fda --- /dev/null +++ b/wcmtools/lib/MySQL-BinLog/lib/Mysql/BinLog/Net.pm @@ -0,0 +1,207 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +MySQL::BinLog::Net - Read binlog events from a master server over the network. + +=head1 SYNOPSIS + + use MySQL::BinLog qw{}; + + my %connect_params = ( + hostname => 'db.example.com', + database => 'sales', + user => 'salesapp', + password => 'bloo$shewz', + port => 3306, + ); + my $log = MySQL::BinLog->connect( %connect_params ) + or die "Couldn't connect."; + + +=head1 REQUIRES + +I, I + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package MySQL::BinLog::Net; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + # Versioning stuff + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Net.pm,v 1.2 2004/11/17 21:58:40 marksmith Exp $; + + use Net::MySQL qw{}; + use Carp qw{carp croak confess}; + use base qw{Net::MySQL}; + + use constant CHUNKSIZE => 16; + use constant PKTHEADER_LEN => (3 + 1 + 1); +} + + +### METHOD: start_binlog( $slave_id[, $logname, $position, $flags] ) +### Contact the remote server and send the command to start reading binlog +### events from the given I, I, I, and optional +### I. +sub start_binlog { + my $self = shift; + my ( $slave_server_id, $logname, $pos, $flags ) = @_; + + # New log: no logname and position = 4 + $logname ||= ''; + $pos = 4 unless defined $pos && $pos > 4; + + my ( + $len, + $cmd, + $packet, + $mysql, + ); + + # Build the BINLOG_DUMP packet + $cmd = Net::MySQL::COMMAND_BINLOG_DUMP; + $flags ||= 0; + $len = 1 + 4 + 2 + 4 + length( $logname ); + $packet = pack( 'VaVvVa*', $len, $cmd, $pos, $flags, $slave_server_id, $logname ); + $mysql = $self->{socket}; + + # Send it + $mysql->send( $packet, 0 ); + $self->_dump_packet( $packet ) if $self->debug; + + # Receive the response + my $result = $self->read_packet; + + # FIXME I broke error checking by switching to read_packet instead of using + # recv... but recv reads a full buffer's worth, which just gets tossed and + # causes subsequent read_packe calls to start at arbitrary positions and fail. + # real solution is to make read_packet set error flags and then have callers + # check them. eventually. oh, FYI, you have to reconstitute the packet before + # passing it on to _is_error and _set_error_by_packet, as those are in Net::MySQL + # and expect the whole packet, not just the payload that read_packet returns. + #return $self->_set_error_by_packet( $result ) if $self->_is_error( $result ); + + return 1; +} + + +### METHOD: read_packet( ) +### Read a single packet from the connection and return its payload as a scalar. +sub read_packet { + my $self = shift; + + my $pkt_header = $self->readbytes( PKTHEADER_LEN ); + my $length = unpack( 'V', substr($pkt_header, 0, 3, '') . "\0" ) - 1; + my ( $pktno, $cmd ) = unpack( 'CC', $pkt_header ); + + my $pkt = $self->readbytes( $length ); + $self->_dump_packet( $pkt ) if $self->debug; + + return $pkt; +} + + +### FUNCTION: readbytes( $len ) +### Read and return I bytes from the connection. +sub readbytes { + my ( $self, $len ) = @_; + my ( $buf, $rval, $bytes ) = ('', '', 0); + + my $sock = $self->{socket}; + + until ( length $rval == $len ) { + $bytes = $sock->read( $buf, $len - length $rval ); + if ( !defined $bytes ) { + if ( $!{EAGAIN} ) { next } + die "Read error: $!"; + } elsif ( !$bytes && $sock->eof ) { + die "EOF before reading $len bytes.\n"; + } + $rval .= $buf; + } + + return $rval; +} + + + +### Utility/debugging methods (overridden). + +sub hexdump { join ' ', map {sprintf "%02x", ord $_} grep {defined} @_ } +sub ascdump { join '', map {m/[\d \w\._]/ ? $_ : '.'} grep {defined} @_ } + +sub _dump_packet { + my $self = shift; + my $packet = shift; + + my ( + $method_name, + @bytes, + @chunk, + $half, + $width, + $count, + ); + + $method_name = (caller(1))[3]; + print "$method_name:\n"; + + @bytes = split //, $packet; + $count = 0; + while ( @bytes ) { + @chunk = grep { defined } splice( @bytes, 0, CHUNKSIZE ); + $half = CHUNKSIZE / 2; + $width = $half * 3; + + printf( " 0x%04x: %-${width}s %-${width}s |%-${half}s %-${half}s|\n", + $count, + hexdump( @chunk[0..($half-1)] ), + hexdump( @chunk[$half..$#chunk] ), + ascdump( @chunk[0..($half-1)] ), + ascdump( @chunk[$half..$#chunk] ) ); + + $count += CHUNKSIZE; + } + + print "--\n"; +} + + + +### Destructors +DESTROY {} +END {} + + +1; + + diff --git a/wcmtools/lib/S2/Color.pm b/wcmtools/lib/S2/Color.pm new file mode 100755 index 0000000..38d596d --- /dev/null +++ b/wcmtools/lib/S2/Color.pm @@ -0,0 +1,162 @@ +#!/usr/bin/perl +# +# This is a helper package, useful for creating color lightening/darkening +# functions in core layers. +# + +package S2::Color; + +# rgb to hsv +# r, g, b = [0, 255] +# h, s, v = [0, 1), [0, 1], [0, 1] +sub rgb_to_hsv +{ + my ($r, $g, $b) = map { $_ / 255 } @_; + my ($h, $s, $v); + + my ($max, $min) = ($r, $r); + foreach ($g, $b) { + $max = $_ if $_ > $max; + $min = $_ if $_ < $min; + } + return (0, 0, 0) if $max == 0; + + $v = $max; + + my $delta = $max - $min; + + $s = $delta / $max; + return (0, $s, $v) unless $delta; + + if ($r == $max) { + $h = ($g - $b) / $delta; + } elsif ($g == $max) { + $h = 2 + ($b - $r) / $delta; + } else { + $h = 4 + ($r - $g) / $delta; + } + + $h = ($h * 60) % 360 / 360; + + return ($h, $s, $v); +} + +# hsv to rgb +# h, s, v = [0, 1), [0, 1], [0, 1] +# r, g, b = [0, 255], [0, 255], [0, 255] +sub hsv_to_rgb +{ + my ($H, $S, $V) = @_; + + if ($S == 0) { + $V *= 255; + return ($V, $V, $V); + } + + $H *= 6; + my $I = POSIX::floor($H); + + my $F = $H - $I; + my $P = $V * (1 - $S); + my $Q = $V * (1 - $S * $F); + my $T = $V * (1 - $S * (1 - $F)); + + foreach ($V, $T, $P, $Q) { + $_ = int($_ * 255 + 0.5); + } + + return ($V, $T, $P) if $I == 0; + return ($Q, $V, $P) if $I == 1; + return ($P, $V, $T) if $I == 2; + return ($P, $Q, $V) if $I == 3; + return ($T, $P, $V) if $I == 4; + + return ($V, $P, $Q); +} + +# rgb to hsv +# r, g, b = [0, 255], [0, 255], [0, 255] +# returns: (h, s, l) = [0, 1), [0, 1], [0, 1] +sub rgb_to_hsl +{ + # convert rgb to 0-1 + my ($R, $G, $B) = map { $_ / 255 } @_; + + # get min/max of {r, g, b} + my ($max, $min) = ($R, $R); + foreach ($G, $B) { + $max = $_ if $_ > $max; + $min = $_ if $_ < $min; + } + + # is gray? + my $delta = $max - $min; + if ($delta == 0) { + return (0, 0, $max); + } + + my ($H, $S); + my $L = ($max + $min) / 2; + + if ($L < 0.5) { + $S = $delta / ($max + $min); + } else { + $S = $delta / (2.0 - $max - $min); + } + + if ($R == $max) { + $H = ($G - $B) / $delta; + } elsif ($G == $max) { + $H = 2 + ($B - $R) / $delta; + } elsif ($B == $max) { + $H = 4 + ($R - $G) / $delta; + } + + $H *= 60; + $H += 360.0 if $H < 0.0; + $H -= 360.0 if $H >= 360.0; + $H /= 360.0; + + return ($H, $S, $L); + +} + +# h, s, l = [0,1), [0,1], [0,1] +# returns: rgb: [0,255], [0,255], [0,255] +sub hsl_to_rgb { + my ($H, $S, $L) = @_; + + # gray. + if ($S < 0.0000000000001) { + my $gv = int(255 * $L + 0.5); + return ($gv, $gv, $gv); + } + + my ($t1, $t2); + if ($L < 0.5) { + $t2 = $L * (1.0 + $S); + } else { + $t2 = $L + $S - $L * $S; + } + $t1 = 2.0 * $L - $t2; + + my $fromhue = sub { + my $hue = shift; + if ($hue < 0) { $hue += 1.0; } + if ($hue > 1) { $hue -= 1.0; } + + if (6.0 * $hue < 1) { + return $t1 + ($t2 - $t1) * $hue * 6.0; + } elsif (2.0 * $hue < 1) { + return $t2; + } elsif (3.0 * $hue < 2.0) { + return ($t1 + ($t2 - $t1)*((2.0/3.0)-$hue)*6.0); + } else { + return $t1; + } + }; + + return map { int(255 * $fromhue->($_) + 0.5) } ($H + 1.0/3.0, $H, $H - 1.0/3.0); +} + +1; diff --git a/wcmtools/lib/S2/EXIF.pm b/wcmtools/lib/S2/EXIF.pm new file mode 100755 index 0000000..85c3a10 --- /dev/null +++ b/wcmtools/lib/S2/EXIF.pm @@ -0,0 +1,135 @@ +#!/usr/bin/perl +# +# This is a helper package, contains info about EXIF tag categories and how to print them +# + +package S2::EXIF; +use strict; +use vars qw(@TAG_CAT %TAG_CAT); + +# rough categories which can optionally be used to display tags +# with coherent ordering + +@TAG_CAT = + ( + [ media => { + name => 'Media Information', + tags => [ qw ( + PixelXDimension + PixelYDimension + ImageWidth + ImageLength + Compression + CompressedBitsPerPixel + ) + ], + }, + ], + + [ image => { + name => 'Image Information', + tags => [ qw ( + DateTime + DateTimeOriginal + ImageDescription + UserComment + Make + Software + Artist + Copyright + ExifVersion + FlashpixVersion + ) + ], + }, + ], + + [ exposure => { + name => 'Exposure Settings', + tags => [ qw( + Orientation + Flash + FlashEnergy + LightSource + ExposureTime + ExposureProgram + ExposureMode + DigitalZoomRatio + ShutterSpeedValue + ApertureValue + MeteringMode + WhiteBalance + Contrast + Saturation + Sharpness + SensingMethod + FocalLength + ISOSpeedRatings + FNumber + ) + ], + }, + ], + + [ gps => { + name => 'GPS Information', + tags => [ qw( + GPSLatitudeRef + GPSLatitude + GPSLongitudeRef + GPSLongitude + GPSAltitudeRef + GPSAltitude + GPSTimeStamp + GPSDateStamp + GPSDOP + GPSImgDirectionRef + GPSImgDirection + ) + ], + }, + ], + ); + +# make mapping into array +%TAG_CAT = map { $_->[0] => $_->[1] } @TAG_CAT; + +# return all tags in all categories +sub get_tag_info { + + my @ret = (); + foreach my $currcat (@S2::EXIF::TAG_CAT) { + push @ret, @{$currcat->[1]->{tags}}; + } + + return @ret; +} + +# return hashref of category keys => names +sub get_cat_info { + return { map { $_->[0] => $_->[1]->{name} } @S2::EXIF::TAG_CAT }; +} + +# return ordered array of category keys +sub get_cat_order { + return map { $_->[0] } @S2::EXIF::TAG_CAT; +} + +# return the name of a single category +sub get_cat_name { + return () unless $TAG_CAT{$_[0]}; + return $TAG_CAT{$_[0]}->{name}; +} + +# return the tags in a given cateogry +sub get_cat_tags { + return () unless $TAG_CAT{$_[0]}; + return @{$TAG_CAT{$_[0]}->{tags}}; +} + +# return all tags for all categories +sub get_all_tags { + return map { @{$TAG_CAT{$_}->{tags}} } keys %TAG_CAT; +} + +1; diff --git a/wcmtools/lib/SafeAgent.pm b/wcmtools/lib/SafeAgent.pm new file mode 100755 index 0000000..532bc8b --- /dev/null +++ b/wcmtools/lib/SafeAgent.pm @@ -0,0 +1,170 @@ +#!/usr/bin/perl +# +# SafeAgent: fetch HTTP resources with paranoia +# +# =head1 SYNOPSIS +# +# my $sua = new SafeAgent; +# +# $sua->fetch( $url, $max_amount[, $timeout[, $callback]]) +# +# + +package SafeAgent; +use strict; +use constant MB => 1024*1024; +use Socket; + +use LWP::UserAgent; +use Carp qw{croak confess}; +use URI (); + +sub new { + my $proto = shift or croak "Not a function"; + my $class = ref $proto || $proto; + + my $self = bless { + realagent => new LWP::UserAgent (), + timeout => 10, + maxamount => 1*MB, + last_response => undef, + last_url => undef, + }, $class; + + return $self; +} + +sub err { + my $self = shift; + $self->{lasterr} = shift if @_; + return $self->{lasterr}; +} + +sub last_response { + my $self = shift; + return $self->{last_response}; +} + + +sub last_url { + my $self = shift; + return $self->{last_url}; +} + + +sub ret_err { + my $self = shift; + $self->{lasterr} = shift; + return undef; +} + + +sub check_url { + my $self = shift; + my $url = shift; + + return $self->ret_err("BAD_SCHEME") unless $url =~ m!^https?://!; + my $urio = URI->new($url); + my $host = $urio->host; + + my $ip; + if ($host =~ /^\d+\.\d+\.\d+\.\d+$/) { + $ip = $host; + } else { + my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($host); + return $self->ret_err("BAD_HOSTNAME") unless @addrs; + $ip = inet_ntoa($addrs[0]); + } + + # don't connect to private or reserved addresses + return $self->ret_err("BAD_IP") if + ! $ip || + $ip =~ /^(?:10\.|127\.|192\.168\.)/ || + ($ip =~ /^172\.(\d+)/ && ($1 >= 16 && $1 <= 31)) || + ($ip =~ /^2(\d+)/ && ($1 >= 24 && $1 <= 54)); + + return $urio; +} + + +sub fetch { + my ($self, $url, $max_amount, $timeout, $callback) = @_; + $timeout ||= $self->{timeout} || 10, + $max_amount ||= $self->{maxamount} || 1*MB; + + my $urio = $self->check_url($url) or + return undef; + $self->{last_url} = $url; + my $req = HTTP::Request->new('GET' => $url); + + my $hops = 0; + my $ret; + my $no_callback = ! $callback; + $callback ||= sub { + my($data, $response, $protocol) = @_; + $ret .= $data; + }; + + HOP: + while (1) { + # print "Hop $hops.\n"; + $ret = ""; + + my $size = 0; + my $toobig = 0; + my $ua = $self->{realagent}; + my $res; + my $hard_timeout = 0; + + ALARM: eval { + local $SIG{ALRM} = sub { $hard_timeout = 1; die "Hard timeout." }; + alarm( $self->{timeout} ) if $self->{timeout}; + $res = $ua->simple_request($req, sub { + my($data, $response, $protocol) = @_; + $size += length($data); + $callback->($data, $response, $protocol); + $toobig = 1 && die "TOOBIG" if $size > $max_amount; + }, 10_000); + alarm( 0 ); + }; + return $self->ret_err( "Hard timeout." ) if $hard_timeout; + $self->{last_response} = $res; + + # If it's an error response, return failure unless it aborted due + # to an overlarge document, in which case just return the chunk we + # have so far. Also set the error value if it did overflow. + if ( my $err = $res->headers->header('X-Died') ) { + $self->err($err); + return undef unless $err =~ m{TOOBIG}; + last HOP; + } elsif ( $res->is_error ) { + return $self->ret_err("HTTP_Error"); + } elsif ( $res->is_redirect ) { + # follow redirect + my $newurl = $res->headers->header('Location'); + return $self->ret_err("HOPCOUNT") if ++$hops > 1; + # print "Redirect to '$newurl'\n"; + $urio = $self->check_url($newurl) or return undef; + $self->{last_url} = $newurl; + $req = HTTP::Request->new('GET' => $urio); + } else { + # print "Success.\n"; + $self->err( undef ); + last HOP; + } + } # end while + + return $no_callback ? $ret : 1; +} + +sub agent { + my $self = shift; + my $old = $self->{realagent}->agent; + if (@_) { + my $agent = shift; + $self->{realagent}->agent($agent); + } + return $old; +} + +1; diff --git a/wcmtools/memcached/AUTHORS b/wcmtools/memcached/AUTHORS new file mode 100755 index 0000000..fc95232 --- /dev/null +++ b/wcmtools/memcached/AUTHORS @@ -0,0 +1,2 @@ +Anatoly Vorobey +Brad Fitzpatrick diff --git a/wcmtools/memcached/BUILD b/wcmtools/memcached/BUILD new file mode 100755 index 0000000..d6ca4c4 --- /dev/null +++ b/wcmtools/memcached/BUILD @@ -0,0 +1,37 @@ +Ideally, you want to make a static binary, otherwise the dynamic +linker pollutes your address space with shared libs right in the +middle. (NOTE: actually, this shouldn't matter so much anymore, now +that we only allocate huge, fixed-size slabs) + +Make sure your libevent has epoll (Linux) or kqueue (BSD) support. +Using poll or select only is slow, and works for testing, but +shouldn't be used for high-traffic memcache installations. + +To build libevent with epoll on Linux, you need two things. First, +you need /usr/include/sys/epoll.h . To get it, you can install the +userspace epoll library, epoll-lib. The link to the latest version +is buried inside +http://www.xmailserver.org/linux-patches/nio-improve.html ; currently +it's http://www.xmailserver.org/linux-patches/epoll-lib-0.9.tar.gz . +If you're having any trouble building/installing it, you can just copy +epoll.h from that tarball to /usr/include/sys as that's the only thing +from there that libevent really needs. + +Secondly, you need to declare syscall numbers of epoll syscalls, so +libevent can use them. Put these declarations somewhere +inside : + +#define __NR_epoll_create 254 +#define __NR_epoll_ctl 255 +#define __NR_epoll_wait 256 + +After this you should be able to build libevent with epoll support. +Once you build/install libevent, you don't need to +compile memcache or link it against libevent. Don't forget that for epoll +support to actually work at runtime you need to use a kernel with epoll +support patch applied, as explained in the README file. + +BSD users are luckier, and will get kqueue support by default. + + + diff --git a/wcmtools/memcached/CONTRIBUTORS b/wcmtools/memcached/CONTRIBUTORS new file mode 100755 index 0000000..049fe5c --- /dev/null +++ b/wcmtools/memcached/CONTRIBUTORS @@ -0,0 +1,48 @@ +Brad Fitzpatrick + -- design/protocol + -- Perl client + -- prototype Perl server + -- memory allocator design + -- small enhancements/changes to C server + -- website + +Anatoly Vorobey + -- C server + -- memory allocator design + -- revised setuid code + +Evan Martin + -- automake/autoconf support + -- Python client + -- portability work to build on OS X + +Ryan + -- PHP client + +Jamie McCarthy + -- Perl client fixes: Makefile.PL, stats, doc updates + +Lisa Marie Seelye + -- packaging for Gentoo Linux + -- initial setuid code + +Sean Chittenden + -- packaging for FreeBSD + +Stuart Herbert + -- fix for: memcached's php client can run in an infinite loop + http://bugs.gentoo.org/show_bug.cgi?id=25385 + +Brion Vibber + -- debugging abstraction in PHP client + -- debugging the failure of daemon mode on FreeBSD + +Brad Whitaker + -- compression support for the Perl API + +Richard Russo + -- Java API + +Ryan T. Dean + -- Second PHP client with correct parsing (based on Perl client) + -- autoconf fixes for mallinfo.arena on BSD (don't just check malloc.h) diff --git a/wcmtools/memcached/COPYING b/wcmtools/memcached/COPYING new file mode 100755 index 0000000..4746b00 --- /dev/null +++ b/wcmtools/memcached/COPYING @@ -0,0 +1,30 @@ +Copyright (c) 2003, Danga Interactive, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of the Danga Interactive nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/wcmtools/memcached/ChangeLog b/wcmtools/memcached/ChangeLog new file mode 100755 index 0000000..768cc83 --- /dev/null +++ b/wcmtools/memcached/ChangeLog @@ -0,0 +1,178 @@ +2005-05-25 + * patch from Peter van Dijk to make + stderr unbuffered, for running under daemontools + +2005-04-04 + * patch from Don MacAskill 'flush_all' doesn't + seem to work properly. Basically, if you try to add a key which + is present, but expired, the store fails but the old key is no + longer expired. + + * release 1.1.12 + +2005-01-14 + * Date: Thu, 18 Nov 2004 15:25:59 -0600 + From: David Phillips + Here is a patch to configure.ac and Makefile.am to put the man page in + the correct location. Trying to install the man page from a + subdirectory results in the subdirectory being used in the install + path (it tries to install to doc/memcached.1). This is the correct + thing to do: + + - create a Makefile.am in the doc directory that installs the man page + with man_MANS + - modify Makefile.am in the base directory to reference the doc + directory using SUBDIRS + - modify the AC_CONFIG_FILES macro in configure.ac to output the + Makefile in doc + + +2005-01-14 + * pidfile saving support from Lisa Seelye , sent + Jan 13, 2005 + +2005-01-14 + * don't delete libevent events that haven't been added (the deltimer) + patch from Ted Schundler + +2004-12-10 + * document -M and -r in manpage (Doug Porter ) + +2004-07-22 + * fix buffer overflow in items.c with 250 byte keys along with + other info on the same line going into a 256 byte char[]. + thanks to Andrei Nigmatulin + +2004-06-15 + * immediate deletes weren't being unlinked a few seconds, + preventing "add" commands to the same key in that time period. + thanks to Michael Alan Dorman for the + bug report and demo script. + +2004-04-30 + * released 1.1.11 + +2004-04-24 + * Avva: Add a new command line option: -r , to maximize core file + limit. + +2004-03-31 + * Avva: Use getrlimit and setrlimit to set limits for number of + simultaneously open file descriptors. Get the current limits and + try to raise them if they're not enough for the specified (or the + default) setting of max connections. + +2004-02-24 + * Adds a '-M' flag to turn off tossing items from the cache. + (Jason Titus ) + +2004-02-19 (Evan) + * Install manpage on "make install", etc. + +2003-12-30 (Brad) + * remove static build stuff. interferes with PAM setuid stuff + and was only included as a possible fix with the old memory + allocator. really shouldn't make a difference. + * add Jay Bonci's Debian scripts and manpage + * release version 1.1.10 + +2003-12-01 (Avva) + * New command: flush_all, causes all existing items to + be invalidated immediately (without deleting them from + memory, merely causing memcached to no longer return them). +2003-10-23 + * Shift init code around to fix daemon mode on FreeBSD, + * and drop root only after creating the server socket (to + * allow the use of privileged ports) + * version 1.1.10pre + +2003-10-09 + * BSD compile fixes from Ryan T. Dean + * version 1.1.9 + +2003-09-29 + * ignore SIGPIPE at start instead of crashing in rare cases it + comes up. no other code had to be modified, since everything + else is already dead-connection-aware. (avva) + +2003-09-09 (Avva, Lisa Marie Seelye ) + * setuid support + +2003-09-05 (Avva) + * accept all new connections in the same event (so we work with ET epoll) + * mark all items as clsid=0 after slab page reassignment to please future + asserts (on the road to making slab page reassignment work fully) + +2003-08-12 (Brad Fitzpatrick) + * use TCP_CORK on Linux or TCP_PUSH on BSD + * only use TCP_NODELAY when we don't have alternatives + +2003-08-10 + * disable Nagel's Algorithm (TCP_NODELAY) for better performance (avva) + +2003-08-10 + * support multiple levels of verbosity (-vv) + +2003-08-10 (Evan Martin) + * Makefile.am: debug, optimization, and static flags are controlled + by the configure script. + * configure.ac: + - allow specifying libevent directory with --with-libevent=DIR + - check for malloc.h (unavailable on BSDs) + - check for socklen_t (unavailable on OSX) + * assoc.c, items.c, slabs.c: Remove some unused headers. + * memcached.c: allow for nonexistence of malloc.h; #define a POSIX + macro to import mlockall flags. + +2003-07-29 + * version 1.1.7 + * big bug fix: item exptime 0 meant expire immediately, not never + * version 1.1.8 + +2003-07-22 + * make 'delete' take second arg, of time to refuse new add/replace + * set/add/replace/delete can all take abs or delta time (delta can't + be larger than a month) + +2003-07-21 + * added doc/protocol.txt + +2003-07-01 + * report CPU usage in stats + +2003-06-30 + * version 1.1.6 + * fix a number of obscure bugs + * more stats reporting + +2003-06-10 + * removing use of Judy; use a hash. (judy caused memory fragmentation) + * shrink some structures + * security improvements + * version 1.1.0 + +2003-06-18 + * changing maxsize back to an unsigned int + +2003-06-16 + * adding PHP support + * added CONTRIBUTORS file + * version 1.0.4 + +2003-06-15 + * forgot to distribute website/api (still learning auto*) + * version 1.0.3 + +2003-06-15 + * update to version 1.0.2 + * autoconf/automake fixes for older versions + * make stats report version number + * change license from GPL to BSD + +Fri, 13 Jun 2003 10:05:51 -0700 Evan Martin + + * configure.ac, autogen.sh, Makefile.am: Use autotools. + * items.c, memcached.c: #include for time(), + printf time_t as %lu (is this correct?), + minor warnings fixes. + diff --git a/wcmtools/memcached/LICENSE b/wcmtools/memcached/LICENSE new file mode 100755 index 0000000..4746b00 --- /dev/null +++ b/wcmtools/memcached/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2003, Danga Interactive, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of the Danga Interactive nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/wcmtools/memcached/Makefile.am b/wcmtools/memcached/Makefile.am new file mode 100755 index 0000000..4ef0c25 --- /dev/null +++ b/wcmtools/memcached/Makefile.am @@ -0,0 +1,10 @@ +bin_PROGRAMS = memcached + +memcached_SOURCES = memcached.c slabs.c items.c memcached.h assoc.c + +SUBDIRS = doc +DIST_DIRS = scripts +EXTRA_DIST = doc scripts TODO + +AM_CFLAGS=-DNDEBUG + diff --git a/wcmtools/memcached/NEWS b/wcmtools/memcached/NEWS new file mode 100755 index 0000000..78b1eca --- /dev/null +++ b/wcmtools/memcached/NEWS @@ -0,0 +1 @@ +http://www.danga.com/memcached/news.bml diff --git a/wcmtools/memcached/README b/wcmtools/memcached/README new file mode 100755 index 0000000..b513eae --- /dev/null +++ b/wcmtools/memcached/README @@ -0,0 +1,22 @@ +Dependencies: + + -- libevent, http://www.monkey.org/~provos/libevent/ (libevent-dev) + +If using Linux, you need a kernel with epoll. Sure, libevent will +work with normal select, but it sucks. + +epoll isn't in Linux 2.4 yet, but there's a backport at: + + http://www.xmailserver.org/linux-patches/nio-improve.html + +You want the epoll-lt patch (level-triggered). + +Also, be warned that the -k (mlockall) option to memcached might be +dangerous when using a large cache. Just make sure the memcached machines +don't swap. memcached does non-blocking network I/O, but not disk. (it +should never go to disk, or you've lost the whole point of it) + +The memcached website is at: + + http://www.danga.com/memcached/ + diff --git a/wcmtools/memcached/TODO b/wcmtools/memcached/TODO new file mode 100755 index 0000000..c9ae709 --- /dev/null +++ b/wcmtools/memcached/TODO @@ -0,0 +1,8 @@ +* slab class reassignment still buggy and can crash. once that's + stable, server should re-assign pages every 60 seconds or so + to keep all classes roughly equal. [Update: fixed now?, but + not heavily tested. Future: make slab classes, with per-class + cleaners functions.] + +* calendar queue for early expirations of items, so they don't push + out other objects with infinite expirations. diff --git a/wcmtools/memcached/api/java/CHANGELOG.txt b/wcmtools/memcached/api/java/CHANGELOG.txt new file mode 100755 index 0000000..831771a --- /dev/null +++ b/wcmtools/memcached/api/java/CHANGELOG.txt @@ -0,0 +1,56 @@ +Version 0.9.1 - 12 Oct 2003 + -- Altered the SockIO helper class, so it no longer allows accessing + the streams it contains directly, instead it has methods + with identical signatures to the methods that were called + on the streams... This makes the client code prettier. + -- Changed looped non blocking read to blocking read, for getting + items from the server. This probably reduces CPU usage in + cases where the retrieval would block, and cleans up the + code a bit. We're blocking on retrieval anyhow. + -- Made get() not call get_multi(), and added single socket + optimization. This parallels recent changes to the perl + client + -- Changed a few for loops to use iterators instead, since it's + probably marginally more efficient, and it's probably + better coding practice. + -- Actually spell checked. :) + +Version 0.9.0 - 29 Sep 2003 + -- Renumbered to reflect that it's not been realworld tested + -- changed package to danga.com.MemCached (thanks) + -- added dates to changelog + -- added .txt to text files + -- added to official memcached site :) + +Version 1.0.0 - 28 Sep 2003 + -- Adjusted namespacing for SockIO, it shouldn't have been public; is now package level. + As a bonus, this means I don't have to Javadoc it. :) + -- Finished adding complete Javadoc to MemCachedClient. + -- spellchecked + -- added a couple versions of function variations that I missed. for example, some that + didn't take an int directly as a hash value, and i missed a get_multi w/out hashes. + -- removed java.net.Socket reference from MemCachedClient, SockIO has a new constructor which + takes hostname and port number + -- switched to three part version number + + + +Version 0.3 - 27 Sep 2003 + -- Compression, for strings/stringified numbers, this is compatible w/ perl + Serialized objects are incompatible w/ perl for obvious reasons. :) + -- Added PORTABILITY file, to include information about using the client + with various JVM's + -- Updated string parsing to StreamTokenizer rather than regexp's in an + effort to get sablevm to like the client + +Version 0.2 - 24 Sep 2003 + -- Serialization works + -- Possible BUG: Only the lower byte of the characters of keys are sent + This is only a problem if the memcache server can handle + unicode keys. (I haven't checked) + -- Server Failures handled gracefully + -- Partial Javadoc + +Version 0.1 - 23 Sep 2003 + -- Initial Release + -- Storing and Retrieving numbers and strings works diff --git a/wcmtools/memcached/api/java/PORTABILITY.txt b/wcmtools/memcached/api/java/PORTABILITY.txt new file mode 100755 index 0000000..59e8a94 --- /dev/null +++ b/wcmtools/memcached/api/java/PORTABILITY.txt @@ -0,0 +1,18 @@ +This file lists the portability status of this client. Please send me any +additional information. + +Richard 'toast' Russo + + +I have personally tested this on the following platforms, and it works to the +best of my knowledge: + +Sun's JRE 1.4.2 on Linux/i86 +kaffe 1.1.1 on Linux/i86 + +I have personally tested this on the following platforms, and it does not work: + +sablevm 1.0.9: complains of todo in native_interface.c +gjc(jdk) 3.3.2 20030908 (Debian prerelease): strange compiler errors +gij(jre) 3.3.2 20030908 (Debian prerelease): does not get items from server properly + \ No newline at end of file diff --git a/wcmtools/memcached/api/java/TODO.txt b/wcmtools/memcached/api/java/TODO.txt new file mode 100755 index 0000000..5608f3e --- /dev/null +++ b/wcmtools/memcached/api/java/TODO.txt @@ -0,0 +1,9 @@ +This are the things left to do + +Investigate threading issues (what needs to be synchronized) + +Investigate 3rd party jvm incompatibility + +Non deprecated stream input + +Extensive testing diff --git a/wcmtools/memcached/api/java/com/danga/MemCached/MemCachedClient.java b/wcmtools/memcached/api/java/com/danga/MemCached/MemCachedClient.java new file mode 100755 index 0000000..9287f96 --- /dev/null +++ b/wcmtools/memcached/api/java/com/danga/MemCached/MemCachedClient.java @@ -0,0 +1,1219 @@ +/** + * MemCached Java client + * Copyright (c) 2003 + * Richard 'toast' Russo + * http://people.msoe.edu/~russor/memcached + * + * Originally translated from Brad Fitzpatrick's MemCached Perl client + * See the memcached website: + * http://www.danga.com/memcached/ + * + * This module is Copyright (c) 2003 Richard Russo. + * All rights reserved. + * You may distribute under the terms of the GNU General Public License + * This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + * + * @author Richard 'toast' Russo + * @version 0.9.1 + */ + + +package com.danga.MemCached; + + +import java.util.zip.*; +import java.util.*; +import java.util.Map.*; +import java.io.*; + + + +/** This is a Java client for the memcached server available from + * http://www.danga.com/memcached/.*/ +public class MemCachedClient { + + final int F_COMPRESSED = 2; + final int F_SERIALIZED = 8; + //using 8 (1 << 3) so other clients don't try to unpickle/unstore/whatever + //things that are serialized... I don't think they'd like it. :) + + ArrayList buckets; + HashMap host_dead; + HashMap stats; + HashMap sockets; + boolean debug = false; + boolean forceserial = false; + + String singlesock = null; + double compress_savings = 0.20; + boolean compress_enable = true; + int compress_threshold = 1024; // FIXME: is this a reasonable default?? + + /** Creates a new instance of MemCachedClient. + * + * By default, compression is enabled, with a threshold of 1024, and required + * savings of 0.2; debug is disabled; forced serialization is disabled; and the + * server list is empty. + */ + public MemCachedClient() { + } + + + /** Sets the required change in size for value storage to use compression. + * This rate is expressed as a decimal, for example 0.20 means that unless the data + * becomes 20% smaller (it will then be at 80% of its original size), it will be + * stored in uncompressed form. + * + * The value defaults to 0.20. + * @param d required compression to store compressed data + */ + public void set_compress_savings(double d) { + compress_savings = d; + } + + /** Enable storing compressed data, provided it meets the threshold and savings + * requirements. If enabled, data will be stored in compressed form if it is + * longer than the threshold length set with {@link #set_compress_threshold(int) set_compress_threshold()} + * and compression results in a space savings of at least the rate set with + * {@link #set_compress_savings(double) set_compress_savings()}. + * + * The default is that compression is enabled. + * + * Even if compression is disabled, compressed data will be automatically + * decompressed. + * @param b true to enable compression, false to disable compression + */ + public void set_compress_enable(boolean b) { + compress_enable = b; + } + + /** Sets the required length for data to be considered for compression. If the + * length of the data to be stored is not equal or larger than this value, it will + * not be compressed. + * + * This defaults to 1024. + * @param i required length of data to consider compression + */ + public void set_compress_threshold(int i) { + compress_threshold = i; + } + + /** This function lets you tell the client to always serialize data. This is mostly + * useful for debugging; or if you don't want to store stringified numbers. + * @param b True if you want to always serialize data, false if you want to let the client + * decide. + * + */ + public void set_serial(boolean b) { + forceserial = b; + } + + /** Turns on or off debugging information. If enabled, the client will print + * status messages that may be helpful in tracking the progress of data through the + * system. If you're not having problems, this is probably not useful for you. + * @param b true, if debugging messages are desired, false if debugging messages are not + * desired + */ + public void set_debug(boolean b) { + debug = b; + } + + /** This lets you determine if the client will serialize everything, or only data + * types that it doesn't know to stringify + * @return true, if the client is serializing everything + */ + public boolean get_serial() { + return forceserial; + } + + /** Set the list of servers to use. All servers have an equal weight (1) + * @param serverlist An array of servers to use; servers should be in the form ip:port. Hostnames + * are acceptable. + */ + public void set_servers(String[] serverlist) { + set_servers(serverlist, null); + } + + /** Sets the list of servers, and their weights; For best results keep the weights + * as low as possible. If the weightlist is shorter than the serverlist, remaining + * servers are defaulted to a weight of 1. + * @param serverlist A list of servers, in the form ip:port. Hostnames are also acceptable + * @param weightlist A list of weights for the servers. Negative or zero values will be ignored, and + * the default weight of 1 will be used instead + * + */ + public void set_servers(String[] serverlist, int[] weightlist) { +/* I'm just going to construct the bucket list here, since this is the only place + * that the server list is going to change. The perl client constructs it elsewhere. */ + buckets = new ArrayList(); + host_dead = new HashMap(); + sockets = new HashMap(); + if (serverlist.length == 1) { + singlesock = serverlist[0]; + } else { + singlesock = null; + } + + + for (int i = 0; i < serverlist.length; ++i) { + if (weightlist != null && weightlist.length >i) { + for (int j = 0; j < weightlist[i]; ++j) { + buckets.add(serverlist[i]); + } + } else { + buckets.add(serverlist[i]); + } + } + } + + private SockIO get_sock(Object key) { + if (singlesock != null) { + return sock_to_host(singlesock); + } + if (key.getClass() == Integer.class) { + return get_sock(((Integer)key).intValue()); + } else { + return get_sock(key.toString()); + } + } + + + private SockIO get_sock(String key) { + if (singlesock != null) { + return sock_to_host(singlesock); + } + return get_sock(hashfunc(key)); + } + + private SockIO get_sock(int key) { + if (singlesock != null) { + return sock_to_host(singlesock); + } + if ( buckets.size() == 0) { + return null; + } + + int tries = 0; + int hv = key; + while (tries++ < 20) { + String host = (String) buckets.get(hv % buckets.size()); + SockIO sock = sock_to_host(host); + if (sock != null) { + return sock; + } + hv += hashfunc("" + tries + key); // stupid, but works + } + return null; + } + + private SockIO sock_to_host(String host) { + Date now = new Date(); + int tmp = host.indexOf(":"); + String[] ip ={ host.substring(0,tmp), host.substring(tmp+1)}; + + if ((host_dead.containsKey(host) && now.before((Date)host_dead.get(host))) || + (host_dead.containsKey(ip[0]) && now.before((Date)host_dead.get(ip[0])))) { + return null; + } + + if (sockets.containsKey(host) && ((SockIO)sockets.get(host)).isConnected()) { + return (SockIO) sockets.get(host); + } + + SockIO sock; + try { + sock = new SockIO(ip[0], Integer.decode(ip[1]).intValue()); + + } catch (Exception e) { + sock = null; + } + if (sock != null) { + sockets.put(host, sock); + host_dead.remove(host); + host_dead.remove(ip); + return sock; + } + now = new Date(); + host_dead.put(host, new Date(now.getTime() + 60000 + (int)(java.lang.Math.random() * 10000))); + host_dead.put(ip[0], new Date(now.getTime() + 60000 + (int)(java.lang.Math.random() * 10000))); + if (debug) { + System.out.println("MemCachedClient: marking " + host + " (" + ip[0] + ") dead\n"); + } + return null; + } + + private int hashfunc(String key) { + int hash = 0; + for (int i = 0; i < key.length(); ++i) { + hash = hash*33 + key.charAt(i); + } + return hash; + } + + /** Forget that servers were unreachable. This is useful if a network connection has + * been restored, and servers that were recently unreachable have become reachable + * again. + */ + public void forget_dead_hosts() { + host_dead.clear(); + } + + /** Disconnect from all memcached servers. */ + public void disconnect_all() { + Iterator i = sockets.values().iterator(); + while (i.hasNext()) { + ((SockIO)i.next()).close(); + i.remove(); + } + } + + /* wouldn't it be nice if java had default parameters like c? */ + + /** Deletes a key from the server; only the key is specified. + * @param key the key to be removed + * @return true, if the data was deleted successfully + */ + public boolean delete(String key) { + return delete(key,null, null); + } + /** Deletes a key from the server; the key, and a hash value are specified. + * @return true, if the data was deleted successfully + * @param hash used to determine which server is responsible for the specified key + * @param key the key to be removed + */ + public boolean delete(String key, int hash) { + return delete(key,null,new Integer(hash)); + } + /** Deletes a key from the server; the key, and a hash value are specified. + * @return true, if the data was deleted successfully + * @param hash used to determine which server is responsible for the specified key + * @param key the key to be removed + */ + public boolean delete(String key, Integer hash) { + return delete(key, null, hash); + } + /** Deletes a key from the server; the key, and a delete time are specified. The item + * is immediately made non retrievable, however {@link #add(String, Object) add} and + * {@link #replace(String, Object) replace} will fail when used with the same key will + * fail, until the server reaches the specified time. However, + * {@link #set(String, Object) set} will succeed, and the new value will not + * be deleted. + * + * @return true, if the data was deleted successfully + * @param expiry when to expire the record + * @param key the key to be removed + */ + + public boolean delete(String key, Date expiry) { + return delete(key,expiry,null); + } + /** Deletes a key from the server; the key, a delete time are specified, and a hash value + * are specified. The item is immediately made non retrievable, however + * {@link #add(String, Object) add} and {@link #replace(String, Object) replace} + * will fail when used with the same key will fail, until the server reaches the + * specified time. However, {@link #set(String, Object) set} will succeed, + * and the new value will not be deleted. + * + * @return true, if the data was deleted successfully + * @param expiry when to expire the record. + * @param hash used to determine which server is responsible for the specified key + * @param key the key to be removed + */ + public boolean delete(String key, Date expiry, int hash) { + return delete(key, expiry, new Integer(hash)); + } + + /** Deletes a key from the server; the key, a delete time are specified, and a hash value + * are specified. The item is immediately made non retrievable, however + * {@link #add(String, Object) add} and {@link #replace(String, Object) replace} + * will fail when used with the same key will fail, until the server reaches the + * specified time. However, {@link #set(String, Object) set} will succeed, + * and the new value will not be deleted. + * + * @return true, if the data was deleted successfully + * @param expiry when to expire the record. + * @param hash used to determine which server is responsible for the specified key + * @param key the key to be removed + */ + public boolean delete(String key, Date expiry, Object hash) { + SockIO sock; + if (hash != null) { + sock = get_sock(hash); + } else { + sock = get_sock(key); + } + + if (sock == null) { + return false; + } + String command = "delete " + key; + if (expiry != null) { + command = command + " " + expiry.getTime() / 1000; + } + command = command + "\r\n"; + + try { + sock.writeBytes(command); + sock.flush(); + + command = sock.readLine(); + if (command.equals("DELETED")) { + return true; + } + } catch (IOException e) { + sock.close(); + } + return false; + } + + /* Blah.... Default parameters would be _REALLY_ nice here */ + + /** Stores data on the server; only the key and the value are specified. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value) { + return set("set", key, value, null, null); + } + /** Stores data on the server; the key, value, and a hash value are specified. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value, int hash) { + return set("set",key,value,null,new Integer(hash)); + } + /** Stores data on the server; the key, value, and a hash value are specified. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value, Integer hash) { + return set("set",key,value, null, hash); + } + + /** Stores data on the server; the key, value, and an expiration time are specified. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value, Date expiry) { + return set("set",key,value,expiry,null); + } + /** Stores data on the server; the key, value, an expiration time, and a hash value are specified. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value, Date expiry, int hash) { + return set("set",key,value, expiry, new Integer(hash)); + } + /** Stores data on the server; the key, value, an expiration time, and a hash value are specified. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean set(String key, Object value, Date expiry, Object hash) { + return set("set",key,value, expiry, hash); + } + + + /** Adds data to the server; only the key and the value are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value) { + return set("add", key, value, null, null); + } + /** Adds data to the server; the key, value, and a hash value are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value, int hash) { + return set("add",key,value,null,new Integer(hash)); + } + /** Adds data to the server; the key, value, and a hash value are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value, Integer hash) { + return set("add",key,value, null, hash); + } + + /** Adds data to the server; the key, value, and an expiration time are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value, Date expiry) { + return set("add",key,value,expiry,null); + } + /** Adds data to the server; the key, value, an expiration time, and a hash value are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value, Date expiry, int hash) { + return set("add",key,value, expiry, new Integer(hash)); + } + /** Adds data to the server; the key, value, an expiration time, and a hash value are specified. + * If data already exists for this key on the server or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean add(String key, Object value, Date expiry, Object hash) { + return set("add",key,value, expiry, hash); + } + + /** Updates data on the server; only the key and the value are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value) { + return set("replace", key, value, null, null); + } + /** Updates data on the server; the key, value, and a hash value are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value, int hash) { + return set("replace",key,value,null,new Integer(hash)); + } + /** Updates data on the server; the key, value, and a hash value are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value, Integer hash) { + return set("replace",key,value, null, hash); + } + + /** Updates data on the server; the key, value, and an expiration time are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value, Date expiry) { + return set("replace",key,value,expiry,null); + } + /** Updates data on the server; the key, value, an expiration time, and a hash value are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value, Date expiry, int hash) { + return set("replace",key,value, expiry, new Integer(hash)); + } + /** Updates data on the server; the key, value, an expiration time, and a hash value are specified. + * If data does not already exist for this key on the server, or if the key is being + * deleted, the specified value will not be stored. + * The server will automatically delete the value when the expiration time has been reached. + * If the value is not a String or numeric type, or if {@link #set_serial(boolean) set_serial(true)} + * has been called; the data will be Serialized prior to storage. + * + * If compression is enabled, and the data is longer than the compression threshold, + * and compresses by at least the compression savings, the data will be stored in + * compressed form. + * + * @param key key to store data under + * @param value value to store + * @param hash used to determine which server is responsible for the specified key + * @param expiry when to expire the record + * @return true, if the data was successfully stored + */ + public boolean replace(String key, Object value, Date expiry, Object hash) { + return set("replace",key,value, expiry, hash); + } + + + private boolean set(String cmdname, String key, Object value, Date expiry, Object hash) { + SockIO sock; + if (hash != null) { + sock = get_sock(hash); + } else { + sock = get_sock(key); + } + + if (sock == null) { + return false; + } + + if (expiry == null) { + expiry = new Date(0); + } + int flags = 0; + + byte[] val; + + if (!forceserial && (value.getClass() == String.class || + value.getClass() == Double.class || + value.getClass() == Float.class || + value.getClass() == Integer.class || + value.getClass() == Long.class || + value.getClass() == Byte.class || + value.getClass() == Short.class)) { + val = value.toString().getBytes(); + } else { + if (debug) { + System.out.println("MemCache: Serializing " + value.getClass().getName()); + } + flags|= F_SERIALIZED; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + (new ObjectOutputStream(bos)).writeObject(value); + val = bos.toByteArray(); + } catch (IOException e) { + val = value.toString().getBytes(); + } + + } + + if (compress_enable && val.length > compress_threshold) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(val.length); + GZIPOutputStream gos = new GZIPOutputStream(bos); + gos.write(val); + gos.finish(); + + + if (bos.size() <= ( int)((1 - compress_savings) *(double) val.length)) { + val = bos.toByteArray(); + flags|= F_COMPRESSED; + } + + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + try { + String cmd = cmdname + " " + key + " " + flags + " " + + expiry.getTime() / 1000 + " " + val.length + "\r\n"; + sock.writeBytes(cmd); + sock.write(val); + sock.writeBytes("\r\n"); + sock.flush(); + + String line = sock.readLine(); + if (debug) { + System.out.println("MemCache: " + cmdname + " " + key + + " = " + val + "(" + line + ")"); + } + if (line.equals("STORED")) { + return true; + } + + } catch (IOException e) { + sock.close(); + } + return false; + + + + } + + + /** Increment the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key) { + return incrdecr("incr", key, 1, null); + } + /** Increment the value at the specified key by the specified increment, + * and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key, long inc) { + return incrdecr("incr", key, inc, null); + } + /** Increment the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key, Object hash) { + return incrdecr("incr", key, 1, hash); + } + /** Increment the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key, int hash) { + return incrdecr("incr", key, 1, new Integer(hash)); + } + /** Increment the value at the specified key by the specified increment, + * and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key, long inc, int hash) { + return incrdecr("incr", key, inc, new Integer(hash)); + } + /** Increment the value at the specified key by the specified increment, + * and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and does not check + * for overflow. Because Java lacks unsigned types, the value is returned as + * a 64-bit integer. The server will only increment a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long incr(String key, long inc, Object hash) { + return incrdecr("incr", key, inc, hash); + } + + /** Decrement the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key) { + return incrdecr("decr", key, 1, null); + } + /** Decrement the value at the specified key by the specified increment, + * and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key, long inc) { + return incrdecr("decr", key, inc, null); + } + /** Decrement the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key, Object hash) { + return incrdecr("decr", key, 1, hash); + } + /** Decrement the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key, int hash) { + return incrdecr("decr", key, 1, new Integer(hash)); + } + + /** Decrement the value at the specified key by the specified increment, + * and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key, long inc, int hash) { + return incrdecr("decr", key, inc, new Integer(hash)); + } + /** Decrement the value at the specified key by 1, and then return it. + * + * Note that the server uses a 32-bit unsigned integer, and checks for + * underflow. In the event of underflow, the result will be zero. Because + * Java lacks unsigned types, the value is returned as a 64-bit integer. + * The server will only decrement a value if it already exists; + * if a value is not found, -1 will be returned. + * + * @param key key where the data is stored + * @param inc how much to increment by + * @param hash used to determine which server is responsible for the specified key + * @return -1, if the key is not found, the value after incrementing otherwise + */ + public long decr(String key, long inc, Object hash) { + return incrdecr("decr", key, inc, hash); + } + + private long incrdecr(String cmdname, String key, long inc, Object hash) { + SockIO sock; + if (hash != null) { + sock = get_sock(hash); + } else { + sock = get_sock(key); + } + + if (sock == null) { + return -1; + } + + try { + sock.writeBytes(cmdname + " " + key + " " + inc + "\r\n"); + sock.flush(); + String tmp = sock.readLine(); + return Long.decode(tmp).longValue(); + } catch (IOException e) { + sock.close(); + } catch (NumberFormatException e) { + } + + return -1; + } + + /** Retrieve a key from the server. + * + * If the data was compressed or serialized when compressed, it will automatically + * be decompressed or serialized, as appropriate. (Inclusive or) + * + * Non-serialized data will be returned as a string, so explicit conversion to + * numeric types will be necessary, if desired + * + * @param key key where data is stored + * @return the object that was previously stored, or null if it was not previously stored + */ + public Object get(String key) { + return get(key, null); + } + + /** Retrieve a key from the server, using a specific hash. + * + * If the data was compressed or serialized when compressed, it will automatically + * be decompressed or serialized, as appropriate. (Inclusive or) + * + * Non-serialized data will be returned as a string, so explicit conversion to + * numeric types will be necessary, if desired + * + * @param key key where data is stored + * @param hash used to determine which server is responsible for the specified key + * @return the object that was previously stored, or null if it was not previously stored + */ + public Object get(String key, int hash) { + return get(key, new Integer(hash)); + } + + /** Retrieve a key from the server, using a specific hash. + * + * If the data was compressed or serialized when compressed, it will automatically + * be decompressed or serialized, as appropriate. (Inclusive or) + * + * Non-serialized data will be returned as a string, so explicit conversion to + * numeric types will be necessary, if desired + * + * @param key key where data is stored + * @param hash used to determine which server is responsible for the specified key + * @return the object that was previously stored, or null if it was not previously stored + */ + public Object get(String key, Object hash) { + SockIO sock; + if (hash != null) { + sock = get_sock(hash); + } else { + sock = get_sock(key); + } + + if (sock == null) { + return null; + } + try { + sock.writeBytes("get " + key + "\r\n"); + } catch (IOException e) { + sock.close(); + } + HashMap hm = new HashMap(); + load_items(sock, hm); + if (debug) { + Iterator i = hm.entrySet().iterator(); + while (i.hasNext()) { + Entry e = (Entry)i.next(); + System.out.println("MemCache: got " + e.getKey() + " = " + e.getValue()); + } + } + return hm.get(key); + } + + + /** Retrieve multiple keys from the memcache. + * + * This is recommended over repeated calls to {@link #get(String) get()}, since it + * is more efficient. + * @return a hashmap with entries for each key is found by the server, + * keys that are not found are not entered into the hashmap, but attempting to + * retrieve them from the hashmap gives you null. + * @param keys keys to retrieve + */ + public HashMap get_multi(String[] keys) { + return get_multi(keys, null); + } + + /** Retrieve multiple keys from the memcache. + * + * This is recommended over repeated calls to {@link #get(String) get()}, since it + * is more efficient. + * @param keys keys to retrieve + * @param hashes hash values used to determine which server to use for each key; + * if a hash is not provided for a key (either because there are more keys + * than hashes, or a hash value is specifically null) a hash will be computed. + * @return a hashmap with entries for each key is found by the server, + * keys that are not found are not entered into the hashmap, but attempting to + * retrieve them from the hashmap gives you null. + */ + public HashMap get_multi(String[] keys, Object[] hashes) { + ArrayList socks = new ArrayList(); + HashMap sock_keys = new HashMap(); + for (int i = 0; i < keys.length; ++i) { + SockIO sock; + if (hashes!= null && hashes.length > i && hashes[i] != null) { + sock = get_sock(hashes[i]); + } else { + sock = get_sock(keys[i]); + } + if (sock == null) { + continue; + } + if (!sock_keys.containsKey(sock)) { + sock_keys.put(sock, new StringBuffer()); + socks.add(sock); + } + ((StringBuffer)sock_keys.get(sock)).append(" " + keys[i]); + } + + // Pass 1: send out requests + + ArrayList gather = new ArrayList(); + Iterator i = socks.iterator(); + while (i.hasNext()) { + SockIO sock =null; + try { + sock = (SockIO) i.next(); + sock.writeBytes("get" + (StringBuffer)sock_keys.get(sock) + "\r\n"); + sock.flush(); + gather.add(sock); + } catch (IOException e) { + sock.close(); + } + } + + HashMap ret = new HashMap(); + // Pass 2: get results + i = gather.iterator(); + while (i.hasNext()) { + load_items((SockIO) i.next(), ret); + } + + if (debug) { + i = ret.entrySet().iterator(); + while (i.hasNext()) { + Entry e = (Entry)i.next(); + System.out.println("MemCache: got " + e.getKey() + " = " + e.getValue()); + } + } + return ret; + } + + private void load_items(SockIO sock, HashMap hm) { + try { + while (true) { + String line = sock.readLine(); + if (line == null) { + return; + } else if (line.startsWith("VALUE")) { + StreamTokenizer st = new StreamTokenizer(new StringReader(line)); + st.ordinaryChars(48, 57); + st.wordChars(48, 57); // add numbers to words + st.nextToken(); // skip VALUE token + st.nextToken(); + String key = st.sval; + st.nextToken(); + int flag = new Integer(st.sval).intValue(); + st.nextToken(); + int length = new Integer(st.sval).intValue(); + byte[] buf = new byte[length]; + sock.readFully(buf); // blocking read + + sock.readLine(); // clear out \r\n that should be left + // check for compression + Object o; + + if ((flag & F_COMPRESSED) != 0) { + try { + GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + // read the input stream, and write to a byte array output stream since + // we have to read into a byte array, but we don't know how large it + // will need to be, and we don't want to resize it a bunch + + byte[] tmp = new byte[1024]; + int count; + while ((count = gzi.read(tmp)) != -1) { + bos.write(tmp,0,count); + } + + buf = bos.toByteArray(); + } catch (IOException e) { + } + } + if ((flag & F_SERIALIZED) != 0) { + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buf)); + try { + o = ois.readObject(); + if (debug) { + System.out.println("MemCache: Deserializing " + o.getClass().getName()); + } + } catch (ClassNotFoundException e) { + o = new String(buf); + } + } else { + o = new String(buf); + } + hm.put(key, o); + } else if (line.equals("END")) { + return; + } + } + } catch (NumberFormatException e) { + //this shouldn't happen... + System.out.println("MemCache: The sever passed us bad numbers in get"); + } catch (IOException e) { + sock.close(); + } + + + + } + +} diff --git a/wcmtools/memcached/api/java/com/danga/MemCached/SockIO.java b/wcmtools/memcached/api/java/com/danga/MemCached/SockIO.java new file mode 100755 index 0000000..e333b56 --- /dev/null +++ b/wcmtools/memcached/api/java/com/danga/MemCached/SockIO.java @@ -0,0 +1,72 @@ +/** + * MemCached Java client, utility class for Socket IO + * Copyright (c) 2003 + * Richard 'toast' Russo + * http://people.msoe.edu/~russor/memcached + * + * + * This module is Copyright (c) 2003 Richard Russo. + * All rights reserved. + * You may distribute under the terms of the GNU General Public License + * This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + * + * @author Richard 'toast' Russo + * @version 0.9.1 + */ + + +package com.danga.MemCached; + + +import java.util.*; +import java.net.*; +import java.io.*; + + + +class SockIO { + Socket sock; + DataInputStream in; + DataOutputStream out; + boolean closed = false; + + public SockIO(String host, int port) throws IOException { + sock = new Socket(host,port); + in = new DataInputStream(sock.getInputStream()); + out = new DataOutputStream(sock.getOutputStream()); + + } + + public void close() { + closed = true; + try { + in.close(); + out.close(); + sock.close(); + } catch (IOException e) { + } + + } + public boolean isConnected() { + return (closed && sock.isConnected()); + } + + public void readFully(byte[] b) throws IOException { + in.readFully(b); + } + + public String readLine() throws IOException { + return in.readLine(); + } + + public void writeBytes(String s) throws IOException { + out.writeBytes(s); + } + public void flush() throws IOException { + out.flush(); + } + public void write(byte[] b) throws IOException { + out.write(b); + } + +} diff --git a/wcmtools/memcached/api/java/dist.pl b/wcmtools/memcached/api/java/dist.pl new file mode 100755 index 0000000..3035c82 --- /dev/null +++ b/wcmtools/memcached/api/java/dist.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# +# Simplify Brad's life. I'm sure there's a Java-specific way +# to do this (or there should be), but I don't have Java +# installed. +# + +use strict; +use Getopt::Long; + +my $opt_tar = 0; +my $opt_upload = 0; +exit 1 unless GetOptions("tar" => \$opt_tar, + "upload" => \$opt_upload); + +# chdir to the directory the script's at, so future +# paths need only be relative +use FindBin qw($Bin); +chdir $Bin or die "Couldn't cd to $Bin\n"; + +die "Must use --tar or --upload\n" unless $opt_tar || $opt_upload; + +# files to distribute +my @manifest = qw( + TODO.txt + PORTABILITY.txt + CHANGELOG.txt + memcachetest.java + com + com/danga + com/danga/MemCached + com/danga/MemCached/MemCachedClient.java + com/danga/MemCached/SockIO.java + ); + +# figure out the version number + +open (F, "com/danga/MemCached/MemCachedClient.java") or die; +{ local $/ = undef; $_ = ; } # suck in the whole file +close F; +die "Can't find version number\n" unless + /\@version\s+(\d[^\'\"\s]+)/s; +my $ver = $1; +my $dir = "java-memcached-$ver"; +my $dist = "$dir.tar.gz"; + +if ($opt_tar) { + # make a fresh directory + mkdir $dir or die "Couldn't make directory: $dir\n"; + + # copy files to fresh directory + foreach my $file (@manifest) { + if (-f $file) { + system("cp", $file, "$dir/$file") + and die "Error copying file $file\n"; + } elsif (-d $file) { + mkdir "$dir/$file" + or die "Error creating directory $file\n"; + } + } + + # tar it up + system("tar", "zcf", $dist, $dir) + and die "Error running tar.\n"; + + # remove temp directory + system("rm", "-rf", $dir) + and die "Error cleaning up temp directory\n"; + + print "$dist created.\n"; +} + +if ($opt_upload) { + print "Uploading $dist...\n"; + system("scp", $dist, 'bradfitz@danga.com:memd/dist/') + and die "Error uploading to memcached/dist\n"; +} + +print "Done.\n"; diff --git a/wcmtools/memcached/api/java/memcachetest.java b/wcmtools/memcached/api/java/memcachetest.java new file mode 100755 index 0000000..f394af6 --- /dev/null +++ b/wcmtools/memcached/api/java/memcachetest.java @@ -0,0 +1,61 @@ +/* + * memcachetest.java + * + * Created on September 23, 2003, 12:23 AM + */ + +/** + * + * @author toast + */ +import com.danga.MemCached.*; +import java.util.ArrayList; + +/** This is an example program using a MemCacheClient. */ +public class memcachetest { + + /** Creates a new instance of memcachetest */ + public memcachetest() { + } + + /** This runs through some simple tests of the MemCacheClient. + * @param args the command line arguments + */ + public static void main(String[] args) { + MemCachedClient mcc = new MemCachedClient(); + String[] serverlist = { "localhost:12345"}; //, "localhost:12346"}; + mcc.set_compress_enable(true); + mcc.set_compress_savings(0.0); // compress everthing + mcc.set_compress_threshold(0); // compress everthing + mcc.set_servers(serverlist); + //mcc.set_serial(true); +// Integer foo = new Integer(-2); + mcc.set("foo", "Your mother eats army boots, in the day time, with her friends. " + + "English text should be nice and compressible."); + + Object tmp = mcc.get("foo"); + System.out.println(tmp); + System.out.println("Sleeping ..."); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + + while (mcc.get("foo") == null) { + System.out.print("."); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + } + + System.out.println(mcc.get("foo")); + + + + + + + } + +} diff --git a/wcmtools/memcached/api/perl/ChangeLog b/wcmtools/memcached/api/perl/ChangeLog new file mode 100755 index 0000000..6eff984 --- /dev/null +++ b/wcmtools/memcached/api/perl/ChangeLog @@ -0,0 +1,164 @@ +2004-07-27 + * release 1.14 + +2004-07-27 + * kill buggy, slow ord() _hashfunc, replace with crc32. + this adds String::CRC32 as a dependency. thanks to + everybody's feedback on the mailing list. + +2004-07-19 + * don't use pos() because it doesn't seem to work in + taint mode. use $+[0] instead. (Dave Evans <..@djce.org.uk>) + +2004-06-19 + * support multiple paths to memcache nodes (Brad) + see 'set_pref_ip' + +2004-05-30 + * release version 1.13 + +2004-05-26 (Whitaker ) + * quiet warning + +2004-05-25 (Whitaker ) + * get_multi shouldn't modify caller's @_ + +2004-05-18 (Michael ) + * namespace support + * use fields + +2004-05-16 (Alexei Kozlov ) + * remove warnings with vec + +2004-04-09 (brad) + * in perl 5.6, trap errors dethawing 5.8 storable objects + and instead treat it like a cache miss + +2004-04-01 + * use $! and not %! for perl 5.6 compat (Dave Evans <..@djce.org.uk>) + * don't mark whole IP dead anymore when a node is down (Jason Titus ) + * start version numbering (Jamie McCarthy ) + +2004-03-09 (Brad/Avva) + * _oneline can return more than one line (but always on a line break), + so caller must decide when it's really time to quit. had to modify + run_command to know that. (which is used by stats) + +2004-03-05 (Dave Evans <..@djce.org.uk>) + * Here's a really trivial patch for the Perl binding, + Cache::Memcached. The bug is that the module assumes that the + currently select()ed filehandle is STDOUT, but this might not be + the case. So this patch ensures that the select()ed filehandle is + preserved, not forced to STDOUT. + +2004-02-29 (Brad) + * add readonly option + +2004-02-27 (Avva) + * Cleaner handling of the case when _oneline is called without a + line parameter (i.e. not to send anything, just read a line from + the socket). Make it depend on $line being defined only, + regardless of its content (thanks Brad!). + +2004-02-25 (Avva) + * Asyncify all I/O, finally get rid of alarm() yuckiness, unify all + one-liner command/responses into a single internal API. + +2004-02-17 + * document in POD the delete method + +2004-02-03 + * fix bug with 2k read boundaries falling in the middle + of "VALUE ..." or "END" lines, thus halting future + parsing and responses. (eek!) + * version 1.0.12 + +2003-12-01 + * merge stats/stats_reset patch from Jamie McCarthy + * trailing whitespace cleanup + +2003-11-08 + * work on Solaris/BSD where there's no MSG_NOSIGNAL. + the expense is extra syscalls to change the local + SIGPIPE handler all the time. in the future, it'd + be nice to have an option so Solaris/BSD callers + can say, "Hey, I've turned off SIGPIPE globally, + don't worry about it." + +2003-10-26 + * add a test file, so automated CPAN test hosts are happy + * check MSG_NOSIGNAL immediately on module load, not on use, + so Solaris dies early. (still on TODO to fix, but better + to fail loudly) + * version 1.0.11 + +2003-10-25 + * version 1.0.10, rename to Cache::Memcached, upload to CPAN + +2003-10-18 + * implement read/write timeouts everywhere. Now the client shouldn't + hang if the server machine goes down unexpectedly. (avva) + +2003-10-16 + * use Storable::nfreeze instead of freeze, so hosts from different + architectures can all use the same data. (all must use Perl, though. + the different memcache APIs all store/pickle/serialize data differently) + Suggestion by Jason Titus + +2003-10-06 + * fix _incrdecr to return complete number, not just first + digit (thanks to Ryan T. Dean) + * release version 1.0.9 + +2003-10-04 + * document expiration times in POD (thanks to Tim Bunce + for noting the omission) + * release version 1.0.8 + +2003-10-03 + * add connect timeout of 0.25s, for dead host detection. + We had 1 second a couple revs ago, but lost it when + ditching IO::Socket module. (avva) + +2003-10-02 + * fix _incrdecr with explicit-hashvalue keys (whitaker) + +2003-10-01 + * add run_command API call. TODO: document, and document + the $exptime on the setters + +2003-09-30 + * use send instead of print, so we can set MSG_NOSIGNAL + and not get SIGPIPES, which avoids 3 syscalls of localizing + $SIG{PIPE} and sends everything at once, instead of 4k + stdio chunks. in review: stdio buffered in, send unbuffered + out. TODO: setvbuf so reads are buffered at more than 4k. + +2003-09-29 + * yet faster parsing + * switch to stdio/perlio instead of raw io: more correct, + simpler parsing code. + +2003-09-28 + * prevent some warnings + * faster get() call that doesn't use get_multi() + * optimizations for single-server case + * use socket APIs directly, instead of uber-slow IO::* modules + * new faster _load_items parsing + +2003-09-04 + * emit debug when set/add/replace fails, in addition to succeed + +Version 1.0.7 + -- compression support (Brad Whitaker) + +Version 1.0.6 + -- incr/decr client support + -- make delete optionally take second argument (server now supports + a delay time on delete) + -- doc updates from Jamie McCarthy + -- better hashing after dead host detection: new requests go to different + remaining hosts, instead of all to the same one. + +Version 1.0.2 + -- initial release, about. diff --git a/wcmtools/memcached/api/perl/MANIFEST b/wcmtools/memcached/api/perl/MANIFEST new file mode 100755 index 0000000..4c7f74b --- /dev/null +++ b/wcmtools/memcached/api/perl/MANIFEST @@ -0,0 +1,8 @@ +ChangeLog +Memcached.pm +Makefile.PL +README +MANIFEST +TODO +t/use.t + diff --git a/wcmtools/memcached/api/perl/Makefile.PL b/wcmtools/memcached/api/perl/Makefile.PL new file mode 100755 index 0000000..bea54a5 --- /dev/null +++ b/wcmtools/memcached/api/perl/Makefile.PL @@ -0,0 +1,13 @@ +use ExtUtils::MakeMaker; +WriteMakefile( 'NAME' => 'Cache::Memcached', + 'VERSION_FROM' => 'Memcached.pm', + 'PREREQ_PM' => { + 'Storable' => 0, + 'Time::HiRes' => 0, + 'String::CRC32' => 0, + }, + ($] >= 5.005 ? + (ABSTRACT_FROM => 'Memcached.pm', + AUTHOR => 'Brad Fitzpatrick ') : ()), + ); + diff --git a/wcmtools/memcached/api/perl/Memcached.pm b/wcmtools/memcached/api/perl/Memcached.pm new file mode 100755 index 0000000..33cb604 --- /dev/null +++ b/wcmtools/memcached/api/perl/Memcached.pm @@ -0,0 +1,1164 @@ +# $Id: Memcached.pm,v 1.32 2004/07/27 17:07:04 bradfitz Exp $ +# +# Copyright (c) 2003, 2004 Brad Fitzpatrick +# +# See COPYRIGHT section in pod text below for usage and distribution rights. +# + +package Cache::Memcached; + +use strict; +no strict 'refs'; +use Storable (); +use Socket qw( MSG_NOSIGNAL PF_INET IPPROTO_TCP SOCK_STREAM ); +use IO::Handle (); +use Time::HiRes (); +use String::CRC32; +use Errno qw( EINPROGRESS EWOULDBLOCK EISCONN ); + +use fields qw{ + debug no_rehash stats compress_threshold compress_enable stat_callback + readonly select_timeout namespace namespace_len servers active buckets + pref_ip + bucketcount _single_sock _stime +}; + +# flag definitions +use constant F_STORABLE => 1; +use constant F_COMPRESS => 2; + +# size savings required before saving compressed value +use constant COMPRESS_SAVINGS => 0.20; # percent + +use vars qw($VERSION $HAVE_ZLIB $FLAG_NOSIGNAL); +$VERSION = "1.14"; + +BEGIN { + $HAVE_ZLIB = eval "use Compress::Zlib (); 1;"; +} + +$FLAG_NOSIGNAL = 0; +eval { $FLAG_NOSIGNAL = MSG_NOSIGNAL; }; + +my %host_dead; # host -> unixtime marked dead until +my %cache_sock; # host -> socket + +my $PROTO_TCP; + +our $SOCK_TIMEOUT = 2.6; # default timeout in seconds + +sub new { + my Cache::Memcached $self = shift; + $self = fields::new( $self ) unless ref $self; + + my ($args) = @_; + + $self->set_servers($args->{'servers'}); + $self->{'debug'} = $args->{'debug'} || 0; + $self->{'no_rehash'} = $args->{'no_rehash'}; + $self->{'stats'} = {}; + $self->{'pref_ip'} = $args->{'pref_ip'} || {}; + $self->{'compress_threshold'} = $args->{'compress_threshold'}; + $self->{'compress_enable'} = 1; + $self->{'stat_callback'} = $args->{'stat_callback'} || undef; + $self->{'readonly'} = $args->{'readonly'}; + + # TODO: undocumented + $self->{'select_timeout'} = $args->{'select_timeout'} || 1.0; + $self->{namespace} = $args->{namespace} || ''; + $self->{namespace_len} = length $self->{namespace}; + + return $self; +} + +sub set_pref_ip { + my Cache::Memcached $self = shift; + $self->{'pref_ip'} = shift; +} + +sub set_servers { + my Cache::Memcached $self = shift; + my ($list) = @_; + $self->{'servers'} = $list || []; + $self->{'active'} = scalar @{$self->{'servers'}}; + $self->{'buckets'} = undef; + $self->{'bucketcount'} = 0; + + $self->{'_single_sock'} = undef; + if (@{$self->{'servers'}} == 1) { + $self->{'_single_sock'} = $self->{'servers'}[0]; + } + + return $self; +} + +sub set_debug { + my Cache::Memcached $self = shift; + my ($dbg) = @_; + $self->{'debug'} = $dbg; +} + +sub set_readonly { + my Cache::Memcached $self = shift; + my ($ro) = @_; + $self->{'readonly'} = $ro; +} + +sub set_norehash { + my Cache::Memcached $self = shift; + my ($val) = @_; + $self->{'no_rehash'} = $val; +} + +sub set_compress_threshold { + my Cache::Memcached $self = shift; + my ($thresh) = @_; + $self->{'compress_threshold'} = $thresh; +} + +sub enable_compress { + my Cache::Memcached $self = shift; + my ($enable) = @_; + $self->{'compress_enable'} = $enable; +} + +sub forget_dead_hosts { + %host_dead = (); +} + +sub set_stat_callback { + my Cache::Memcached $self = shift; + my ($stat_callback) = @_; + $self->{'stat_callback'} = $stat_callback; +} + +sub _dead_sock { + my ($sock, $ret, $dead_for) = @_; + if ($sock =~ /^Sock_(.+?):(\d+)$/) { + my $now = time(); + my ($ip, $port) = ($1, $2); + my $host = "$ip:$port"; + $host_dead{$host} = $now + $dead_for + if $dead_for; + delete $cache_sock{$host}; + } + return $ret; # 0 or undef, probably, depending on what caller wants +} + +sub _close_sock { + my ($sock) = @_; + if ($sock =~ /^Sock_(.+?):(\d+)$/) { + my ($ip, $port) = ($1, $2); + my $host = "$ip:$port"; + close $sock; + delete $cache_sock{$host}; + } +} + +sub _connect_sock { # sock, sin, timeout + my ($sock, $sin, $timeout) = @_; + $timeout ||= 0.25; + + # make the socket non-blocking from now on, + # except if someone wants 0 timeout, meaning + # a blocking connect, but even then turn it + # non-blocking at the end of this function + + if ($timeout) { + IO::Handle::blocking($sock, 0); + } else { + IO::Handle::blocking($sock, 1); + } + + my $ret = connect($sock, $sin); + + if (!$ret && $timeout && $!==EINPROGRESS) { + + my $win=''; + vec($win, fileno($sock), 1) = 1; + + if (select(undef, $win, undef, $timeout) > 0) { + $ret = connect($sock, $sin); + # EISCONN means connected & won't re-connect, so success + $ret = 1 if !$ret && $!==EISCONN; + } + } + + unless ($timeout) { # socket was temporarily blocking, now revert + IO::Handle::blocking($sock, 0); + } + + # from here on, we use non-blocking (async) IO for the duration + # of the socket's life + + return $ret; +} + +sub sock_to_host { # (host) + my Cache::Memcached $self = ref $_[0] ? shift : undef; + my $host = $_[0]; + return $cache_sock{$host} if $cache_sock{$host}; + + my $now = time(); + my ($ip, $port) = $host =~ /(.*):(\d+)/; + return undef if + $host_dead{$host} && $host_dead{$host} > $now; + my $sock = "Sock_$host"; + + my $connected = 0; + my $sin; + my $proto = $PROTO_TCP ||= getprotobyname('tcp'); + + # if a preferred IP is known, try that first. + if ($self && $self->{pref_ip}{$ip}) { + socket($sock, PF_INET, SOCK_STREAM, $proto); + my $prefip = $self->{pref_ip}{$ip}; + $sin = Socket::sockaddr_in($port,Socket::inet_aton($prefip)); + if (_connect_sock($sock,$sin,0.1)) { + $connected = 1; + } else { + close $sock; + } + } + + # normal path, or fallback path if preferred IP failed + unless ($connected) { + socket($sock, PF_INET, SOCK_STREAM, $proto); + $sin = Socket::sockaddr_in($port,Socket::inet_aton($ip)); + unless (_connect_sock($sock,$sin)) { + return _dead_sock($sock, undef, 20 + int(rand(10))); + } + } + + # make the new socket not buffer writes. + my $old = select($sock); + $| = 1; + select($old); + + return $cache_sock{$host} = $sock; +} + +sub get_sock { # (key) + my Cache::Memcached $self = shift; + my ($key) = @_; + return $self->sock_to_host($self->{'_single_sock'}) if $self->{'_single_sock'}; + return undef unless $self->{'active'}; + my $hv = ref $key ? int($key->[0]) : _hashfunc($key); + + $self->init_buckets() unless $self->{'buckets'}; + + my $real_key = ref $key ? $key->[1] : $key; + my $tries = 0; + while ($tries++ < 20) { + my $host = $self->{'buckets'}->[$hv % $self->{'bucketcount'}]; + my $sock = $self->sock_to_host($host); + return $sock if $sock; + return undef if $sock->{'no_rehash'}; + $hv += _hashfunc($tries . $real_key); # stupid, but works + } + return undef; +} + +sub init_buckets { + my Cache::Memcached $self = shift; + return if $self->{'buckets'}; + my $bu = $self->{'buckets'} = []; + foreach my $v (@{$self->{'servers'}}) { + if (ref $v eq "ARRAY") { + for (1..$v->[1]) { push @$bu, $v->[0]; } + } else { + push @$bu, $v; + } + } + $self->{'bucketcount'} = scalar @{$self->{'buckets'}}; +} + +sub disconnect_all { + my $sock; + foreach $sock (values %cache_sock) { + close $sock; + } + %cache_sock = (); +} + +sub _oneline { + my Cache::Memcached $self = shift; + my ($sock, $line) = @_; + my $res; + my ($ret, $offset) = (undef, 0); + + # state: 0 - writing, 1 - reading, 2 - done + my $state = defined $line ? 0 : 1; + + # the bitsets for select + my ($rin, $rout, $win, $wout); + my $nfound; + + my $copy_state = -1; + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + + # the select loop + while(1) { + if ($copy_state!=$state) { + last if $state==2; + ($rin, $win) = ('', ''); + vec($rin, fileno($sock), 1) = 1 if $state==1; + vec($win, fileno($sock), 1) = 1 if $state==0; + $copy_state = $state; + } + $nfound = select($rout=$rin, $wout=$win, undef, + $self->{'select_timeout'}); + last unless $nfound; + + if (vec($wout, fileno($sock), 1)) { + $res = send($sock, $line, $FLAG_NOSIGNAL); + next + if not defined $res and $!==EWOULDBLOCK; + unless ($res > 0) { + _close_sock($sock); + return undef; + } + if ($res == length($line)) { # all sent + $state = 1; + } else { # we only succeeded in sending some of it + substr($line, 0, $res, ''); # delete the part we sent + } + } + + if (vec($rout, fileno($sock), 1)) { + $res = sysread($sock, $ret, 255, $offset); + next + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { # catches 0=conn closed or undef=error + _close_sock($sock); + return undef; + } + $offset += $res; + if (rindex($ret, "\r\n") + 2 == length($ret)) { + $state = 2; + } + } + } + + unless ($state == 2) { + _dead_sock($sock); # improperly finished + return undef; + } + + return $ret; +} + + +sub delete { + my Cache::Memcached $self = shift; + my ($key, $time) = @_; + return 0 if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return 0 unless $sock; + + $self->{'stats'}->{"delete"}++; + $key = ref $key ? $key->[1] : $key; + $time = $time ? " $time" : ""; + my $cmd = "delete $self->{namespace}$key$time\r\n"; + my $res = _oneline($self, $sock, $cmd); + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, 'delete'); + } + + return $res eq "DELETED\r\n"; +} + +sub add { + _set("add", @_); +} + +sub replace { + _set("replace", @_); +} + +sub set { + _set("set", @_); +} + +sub _set { + my $cmdname = shift; + my Cache::Memcached $self = shift; + my ($key, $val, $exptime) = @_; + return 0 if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return 0 unless $sock; + + use bytes; # return bytes from length() + + $self->{'stats'}->{$cmdname}++; + my $flags = 0; + $key = ref $key ? $key->[1] : $key; + + if (ref $val) { + $val = Storable::nfreeze($val); + $flags |= F_STORABLE; + } + + my $len = length($val); + + if ($self->{'compress_threshold'} && $HAVE_ZLIB && $self->{'compress_enable'} && + $len >= $self->{'compress_threshold'}) { + + my $c_val = Compress::Zlib::memGzip($val); + my $c_len = length($c_val); + + # do we want to keep it? + if ($c_len < $len*(1 - COMPRESS_SAVINGS)) { + $val = $c_val; + $len = $c_len; + $flags |= F_COMPRESS; + } + } + + $exptime = int($exptime || 0); + + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + my $line = "$cmdname $self->{namespace}$key $flags $exptime $len\r\n$val\r\n"; + + my $res = _oneline($self, $sock, $line); + + if ($self->{'debug'} && $line) { + chop $line; chop $line; + print STDERR "Cache::Memcache: $cmdname $self->{namespace}$key = $val ($line)\n"; + } + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, $cmdname); + } + + return $res eq "STORED\r\n"; +} + +sub incr { + _incrdecr("incr", @_); +} + +sub decr { + _incrdecr("decr", @_); +} + +sub _incrdecr { + my $cmdname = shift; + my Cache::Memcached $self = shift; + my ($key, $value) = @_; + return undef if ! $self->{'active'} || $self->{'readonly'}; + my $stime = Time::HiRes::time() if $self->{'stat_callback'}; + my $sock = $self->get_sock($key); + return undef unless $sock; + $key = $key->[1] if ref $key; + $self->{'stats'}->{$cmdname}++; + $value = 1 unless defined $value; + + my $line = "$cmdname $self->{namespace}$key $value\r\n"; + my $res = _oneline($self, $sock, $line); + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($stime, $etime, $sock, $cmdname); + } + + return undef unless $res =~ /^(\d+)/; + return $1; +} + +sub get { + my Cache::Memcached $self = shift; + my ($key) = @_; + + # TODO: make a fast path for this? or just keep using get_multi? + my $r = $self->get_multi($key); + my $kval = ref $key ? $key->[1] : $key; + return $r->{$kval}; +} + +sub get_multi { + my Cache::Memcached $self = shift; + return undef unless $self->{'active'}; + $self->{'_stime'} = Time::HiRes::time() if $self->{'stat_callback'}; + $self->{'stats'}->{"get_multi"}++; + my %val; # what we'll be returning a reference to (realkey -> value) + my %sock_keys; # sockref_as_scalar -> [ realkeys ] + my $sock; + + foreach my $key (@_) { + $sock = $self->get_sock($key); + next unless $sock; + my $kval = ref $key ? $key->[1] : $key; + push @{$sock_keys{$sock}}, $kval; + } + $self->{'stats'}->{"get_keys"} += @_; + $self->{'stats'}->{"get_socks"} += keys %sock_keys; + + local $SIG{'PIPE'} = "IGNORE" unless $FLAG_NOSIGNAL; + + _load_multi($self, \%sock_keys, \%val); + + if ($self->{'debug'}) { + while (my ($k, $v) = each %val) { + print STDERR "MemCache: got $k = $v\n"; + } + } + return \%val; +} + +sub _load_multi { + use bytes; # return bytes from length() + my Cache::Memcached $self = shift; + my ($sock_keys, $ret) = @_; + + # all keyed by a $sock: + my %reading; # bool, whether we're reading from this socket + my %writing; # bool, whether we're writing into this socket + my %state; # reading state: + # 0 = waiting for a line, N = reading N bytes + my %buf; # buffers + my %offset; # offsets to read into buffers + my %key; # current key per socket + my %flags; # flags per socket + + foreach (keys %$sock_keys) { + print STDERR "processing socket $_\n" if $self->{'debug'} >= 2; + $writing{$_} = 1; + $buf{$_} = "get ". join(" ", map { "$self->{namespace}$_" } @{$sock_keys->{$_}}) . "\r\n"; + } + + my $active_changed = 1; # force rebuilding of select sets + + my $dead = sub { + my $sock = shift; + print STDERR "killing socket $sock\n" if $self->{'debug'} >= 2; + delete $reading{$sock}; + delete $writing{$sock}; + delete $ret->{$key{$sock}} + if $key{$sock}; + + if ($self->{'stat_callback'}) { + my $etime = Time::HiRes::time(); + $self->{'stat_callback'}->($self->{'_stime'}, $etime, $sock, 'get_multi'); + } + + close $sock; + _dead_sock($sock); + $active_changed = 1; + }; + + my $finalize = sub { + my $sock = shift; + my $k = $key{$sock}; + + # remove trailing \r\n + chop $ret->{$k}; chop $ret->{$k}; + + unless (length($ret->{$k}) == $state{$sock}-2) { + $dead->($sock); + return; + } + + $ret->{$k} = Compress::Zlib::memGunzip($ret->{$k}) + if $HAVE_ZLIB && $flags{$sock} & F_COMPRESS; + if ($flags{$sock} & F_STORABLE) { + # wrapped in eval in case a perl 5.6 Storable tries to + # unthaw data from a perl 5.8 Storable. (5.6 is stupid + # and dies if the version number changes at all. in 5.8 + # they made it only die if it unencounters a new feature) + eval { + $ret->{$k} = Storable::thaw($ret->{$k}); + }; + # so if there was a problem, just treat it as a cache miss. + if ($@) { + delete $ret->{$k}; + } + } + }; + + my $read = sub { + my $sock = shift; + my $res; + + # where are we reading into? + if ($state{$sock}) { # reading value into $ret + $res = sysread($sock, $ret->{$key{$sock}}, + $state{$sock} - $offset{$sock}, + $offset{$sock}); + return + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { # catches 0=conn closed or undef=error + $dead->($sock); + return; + } + $offset{$sock} += $res; + if ($offset{$sock} == $state{$sock}) { # finished reading + $finalize->($sock); + $state{$sock} = 0; # wait for another VALUE line or END + $offset{$sock} = 0; + } + return; + } + + # we're reading a single line. + # first, read whatever's there, but be satisfied with 2048 bytes + $res = sysread($sock, $buf{$sock}, + 2048, $offset{$sock}); + return + if !defined($res) and $!==EWOULDBLOCK; + if ($res == 0) { + $dead->($sock); + return; + } + $offset{$sock} += $res; + + SEARCH: + while(1) { # may have to search many times + # do we have a complete END line? + if ($buf{$sock} =~ /^END\r\n/) { + # okay, finished with this socket + delete $reading{$sock}; + $active_changed = 1; + return; + } + + # do we have a complete VALUE line? + if ($buf{$sock} =~ /^VALUE (\S+) (\d+) (\d+)\r\n/) { + ($key{$sock}, $flags{$sock}, $state{$sock}) = + (substr($1, $self->{namespace_len}), int($2), $3+2); + # Note: we use $+[0] and not pos($buf{$sock}) because pos() + # seems to have problems under perl's taint mode. nobody + # on the list discovered why, but this seems a reasonable + # work-around: + my $p = $+[0]; + my $len = length($buf{$sock}); + my $copy = $len-$p > $state{$sock} ? $state{$sock} : $len-$p; + $ret->{$key{$sock}} = substr($buf{$sock}, $p, $copy) + if $copy; + $offset{$sock} = $copy; + substr($buf{$sock}, 0, $p+$copy, ''); # delete the stuff we used + if ($offset{$sock} == $state{$sock}) { # have it all? + $finalize->($sock); + $state{$sock} = 0; # wait for another VALUE line or END + $offset{$sock} = 0; + next SEARCH; # look again + } + last SEARCH; # buffer is empty now + } + + # if we're here probably means we only have a partial VALUE + # or END line in the buffer. Could happen with multi-get, + # though probably very rarely. Exit the loop and let it read + # more. + + # but first, make sure subsequent reads don't destroy our + # partial VALUE/END line. + $offset{$sock} = length($buf{$sock}); + last SEARCH; + } + + # we don't have a complete line, wait and read more when ready + return; + }; + + my $write = sub { + my $sock = shift; + my $res; + + $res = send($sock, $buf{$sock}, $FLAG_NOSIGNAL); + return + if not defined $res and $!==EWOULDBLOCK; + unless ($res > 0) { + $dead->($sock); + return; + } + if ($res == length($buf{$sock})) { # all sent + $buf{$sock} = ""; + $offset{$sock} = $state{$sock} = 0; + # switch the socket from writing state to reading state + delete $writing{$sock}; + $reading{$sock} = 1; + $active_changed = 1; + } else { # we only succeeded in sending some of it + substr($buf{$sock}, 0, $res, ''); # delete the part we sent + } + return; + }; + + # the bitsets for select + my ($rin, $rout, $win, $wout); + my $nfound; + + # the big select loop + while(1) { + if ($active_changed) { + last unless %reading or %writing; # no sockets left? + ($rin, $win) = ('', ''); + foreach (keys %reading) { + vec($rin, fileno($_), 1) = 1; + } + foreach (keys %writing) { + vec($win, fileno($_), 1) = 1; + } + $active_changed = 0; + } + # TODO: more intelligent cumulative timeout? + $nfound = select($rout=$rin, $wout=$win, undef, + $self->{'select_timeout'}); + last unless $nfound; + + # TODO: possible robustness improvement: we could select + # writing sockets for reading also, and raise hell if they're + # ready (input unread from last time, etc.) + # maybe do that on the first loop only? + foreach (keys %writing) { + if (vec($wout, fileno($_), 1)) { + $write->($_); + } + } + foreach (keys %reading) { + if (vec($rout, fileno($_), 1)) { + $read->($_); + } + } + } + + # if there're active sockets left, they need to die + foreach (keys %writing) { + $dead->($_); + } + foreach (keys %reading) { + $dead->($_); + } + + return; +} + +sub _hashfunc { + return (crc32(shift) >> 16) & 0x7fff; +} + +# returns array of lines, or () on failure. +sub run_command { + my Cache::Memcached $self = shift; + my ($sock, $cmd) = @_; + return () unless $sock; + my $ret; + my $line = $cmd; + while (my $res = _oneline($self, $sock, $line)) { + undef $line; + $ret .= $res; + last if $ret =~ /(?:END|ERROR)\r\n$/; + } + chop $ret; chop $ret; + return map { "$_\r\n" } split(/\r\n/, $ret); +} + +sub stats { + my Cache::Memcached $self = shift; + my ($types) = @_; + return 0 unless $self->{'active'}; + return 0 unless !ref($types) || ref($types) eq 'ARRAY'; + if (!ref($types)) { + if (!$types) { + # I don't much care what the default is, it should just + # be something reasonable. Obviously "reset" should not + # be on the list :) but other types that might go in here + # include maps, cachedump, slabs, or items. + $types = [ qw( misc malloc sizes self ) ]; + } else { + $types = [ $types ]; + } + } + + $self->init_buckets() unless $self->{'buckets'}; + + my $stats_hr = { }; + + # The "self" stat type is special, it only applies to this very + # object. + if (grep /^self$/, @$types) { + $stats_hr->{'self'} = \%{ $self->{'stats'} }; + } + + # Now handle the other types, passing each type to each host server. + my @hosts = @{$self->{'buckets'}}; + my %malloc_keys = ( ); + HOST: foreach my $host (@hosts) { + my $sock = $self->sock_to_host($host); + TYPE: foreach my $typename (grep !/^self$/, @$types) { + my $type = $typename eq 'misc' ? "" : " $typename"; + my $line = _oneline($self, $sock, "stats$type\r\n"); + if (!$line) { + _dead_sock($sock); + next HOST; + } + + # Some stats are key-value, some are not. malloc, + # sizes, and the empty string are key-value. + # ("self" was handled separately above.) + if ($typename =~ /^(malloc|sizes|misc)$/) { + # This stat is key-value. + LINE: while ($line) { + # We have to munge this data a little. First, I'm not + # sure why, but 'stats sizes' output begins with NUL. + $line =~ s/^\0//; + + # And, most lines end in \r\n but 'stats maps' (as of + # July 2003 at least) ends in \n. An alternative + # would be { local $/="\r\n"; chomp } but this works + # just as well: + $line =~ s/[\r\n]+$//; + + # OK, process the data until the end, converting it + # into its key-value pairs. + last LINE if $line eq 'END'; + my($key, $value) = $line =~ /^(?:STAT )?(\w+)\s(.*)/; + if ($key) { + $stats_hr->{'hosts'}{$host}{$typename}{$key} = $value; + } + $malloc_keys{$key} = 1 if $typename eq 'malloc'; + + # read the next line + $line = _oneline($self, $sock); + } + } else { + # This stat is not key-value so just pull it + # all out in one blob. + LINE: while ($line) { + $line =~ s/[\r\n]+$//; + last LINE if $line eq 'END'; + $stats_hr->{'hosts'}{$host}{$typename} ||= ""; + $stats_hr->{'hosts'}{$host}{$typename} .= "$line\n"; + + # read the next one + $line = _oneline($self, $sock); + } + } + } + } + + # Now get the sum total of applicable values. First the misc values. + foreach my $stat (qw( + bytes bytes_read bytes_written + cmd_get cmd_set connection_structures curr_items + get_hits get_misses + total_connections total_items + )) { + $stats_hr->{'total'}{$stat} = 0; + foreach my $host (@hosts) { + $stats_hr->{'total'}{$stat} += + $stats_hr->{'hosts'}{$host}{'misc'}{$stat}; + } + } + + # Then all the malloc values, if any. + foreach my $malloc_stat (keys %malloc_keys) { + $stats_hr->{'total'}{"malloc_$malloc_stat"} = 0; + foreach my $host (@hosts) { + $stats_hr->{'total'}{"malloc_$malloc_stat"} += + $stats_hr->{'hosts'}{$host}{'malloc'}{$malloc_stat}; + } + } + + return $stats_hr; +} + +sub stats_reset { + my Cache::Memcached $self = shift; + my ($types) = @_; + return 0 unless $self->{'active'}; + + $self->init_buckets() unless $self->{'buckets'}; + + HOST: foreach my $host (@{$self->{'buckets'}}) { + my $sock = $self->sock_to_host($host); + my $ok = _oneline($self, $sock, "stats reset"); + unless ($ok eq "RESET\r\n") { + _dead_sock($sock); + } + } + return 1; +} + + + +1; +__END__ + +=head1 NAME + +Cache::Memcached - client library for memcached (memory cache daemon) + +=head1 SYNOPSIS + + use Cache::Memcached; + + $memd = new Cache::Memcached { + 'servers' => [ "10.0.0.15:11211", "10.0.0.15:11212", + "10.0.0.17:11211", [ "10.0.0.17:11211", 3 ] ], + 'debug' => 0, + 'compress_threshold' => 10_000, + }; + $memd->set_servers($array_ref); + $memd->set_compress_threshold(10_000); + $memd->enable_compress(0); + + $memd->set("my_key", "Some value"); + $memd->set("object_key", { 'complex' => [ "object", 2, 4 ]}); + + $val = $memd->get("my_key"); + $val = $memd->get("object_key"); + if ($val) { print $val->{'complex'}->[2]; } + + $memd->incr("key"); + $memd->decr("key"); + $memd->incr("key", 2); + +=head1 DESCRIPTION + +This is the Perl API for memcached, a distributed memory cache daemon. +More information is available at: + + http://www.danga.com/memcached/ + +=head1 CONSTRUCTOR + +=over 4 + +=item C + +Takes one parameter, a hashref of options. The most important key is +C, but that can also be set later with the C +method. The servers must be an arrayref of hosts, each of which is +either a scalar of the form C<10.0.0.10:11211> or an arrayref of the +former and an integer weight value. (The default weight if +unspecified is 1.) It's recommended that weight values be kept as low +as possible, as this module currently allocates memory for bucket +distribution proportional to the total host weights. + +Use C to set a compression threshold, in bytes. +Values larger than this threshold will be compressed by C and +decompressed by C. + +Use C to disable finding a new memcached server when one +goes down. Your application may or may not need this, depending on +your expirations and key usage. + +Use C to disable writes to backend memcached servers. Only +get and get_multi will work. This is useful in bizarre debug and +profiling cases only. + +The other useful key is C, which when set to true will produce +diagnostics on STDERR. + +=back + +=head1 METHODS + +=over 4 + +=item C + +Sets the server list this module distributes key gets and sets between. +The format is an arrayref of identical form as described in the C +constructor. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the C flag. See C constructor for more information. + +=item C + +Sets the compression threshold. See C constructor for more information. + +=item C + +Temporarily enable or disable compression. Has no effect if C +isn't set, but has an overriding effect if it is. + +=item C + +my $val = $memd->get($key); + +Retrieves a key from the memcache. Returns the value (automatically +thawed with Storable, if necessary) or undef. + +The $key can optionally be an arrayref, with the first element being the +hash value, if you want to avoid making this module calculate a hash +value. You may prefer, for example, to keep all of a given user's +objects on the same memcache server, so you could use the user's +unique id as the hash value. + +=item C + +my $hashref = $memd->get_multi(@keys); + +Retrieves multiple keys from the memcache doing just one query. +Returns a hashref of key/value pairs that were available. + +This method is recommended over regular 'get' as it lowers the number +of total packets flying around your network, reducing total latency, +since your app doesn't have to wait for each round-trip of 'get' +before sending the next one. + +=item C + +$memd->set($key, $value[, $exptime]); + +Unconditionally sets a key to a given value in the memcache. Returns true +if it was stored successfully. + +The $key can optionally be an arrayref, with the first element being the +hash value, as described above. + +The $exptime (expiration time) defaults to "never" if unspecified. If +you want the key to expire in memcached, pass an integer $exptime. If +value is less than 60*60*24*30 (30 days), time is assumed to be relative +from the present. If larger, it's considered an absolute Unix time. + +=item C + +$memd->add($key, $value[, $exptime]); + +Like C, but only stores in memcache if the key doesn't already exist. + +=item C + +$memd->replace($key, $value[, $exptime]); + +Like C, but only stores in memcache if the key already exists. The +opposite of C. + +=item C + +$memd->delete($key[, $time]); + +Deletes a key. You may optionally provide an integer time value (in seconds) to +tell the memcached server to block new writes to this key for that many seconds. +(Sometimes useful as a hacky means to prevent races.) Returns true if key +was found and deleted, and false otherwise. + +=item C + +$memd->incr($key[, $value]); + +Sends a command to the server to atomically increment the value for +$key by $value, or by 1 if $value is undefined. Returns undef if $key +doesn't exist on server, otherwise it returns the new value after +incrementing. Value should be zero or greater. Overflow on server +is not checked. Be aware of values approaching 2**32. See decr. + +=item C + +$memd->decr($key[, $value]); + +Like incr, but decrements. Unlike incr, underflow is checked and new +values are capped at 0. If server value is 1, a decrement of 2 +returns 0, not -1. + +=item C + +$memd->stats([$keys]); + +Returns a hashref of statistical data regarding the memcache server(s), +the $memd object, or both. $keys can be an arrayref of keys wanted, a +single key wanted, or absent (in which case the default value is malloc, +sizes, self, and the empty string). These keys are the values passed +to the 'stats' command issued to the memcached server(s), except for +'self' which is internal to the $memd object. Allowed values are: + +=over 4 + +=item C + +The stats returned by a 'stats' command: pid, uptime, version, +bytes, get_hits, etc. + +=item C + +The stats returned by a 'stats malloc': total_alloc, arena_size, etc. + +=item C + +The stats returned by a 'stats sizes'. + +=item C + +The stats for the $memd object itself (a copy of $memd->{'stats'}). + +=item C + +The stats returned by a 'stats maps'. + +=item C + +The stats returned by a 'stats cachedump'. + +=item C + +The stats returned by a 'stats slabs'. + +=item C + +The stats returned by a 'stats items'. + +=back + +=item C + +$memd->disconnect_all(); + +Closes all cached sockets to all memcached servers. You must do this +if your program forks and the parent has used this module at all. +Otherwise the children will try to use cached sockets and they'll fight +(as children do) and garble the client/server protocol. + +=back + +=head1 BUGS + +When a server goes down, this module does detect it, and re-hashes the +request to the remaining servers, but the way it does it isn't very +clean. The result may be that it gives up during its rehashing and +refuses to get/set something it could've, had it been done right. + +=head1 COPYRIGHT + +This module is Copyright (c) 2003 Brad Fitzpatrick. +All rights reserved. + +You may distribute under the terms of either the GNU General Public +License or the Artistic License, as specified in the Perl README file. + +=head1 WARRANTY + +This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + +=head1 FAQ + +See the memcached website: + http://www.danga.com/memcached/ + +=head1 AUTHORS + +Brad Fitzpatrick + +Anatoly Vorobey + +Brad Whitaker + +Jamie McCarthy diff --git a/wcmtools/memcached/api/perl/README b/wcmtools/memcached/api/perl/README new file mode 100755 index 0000000..fd08729 --- /dev/null +++ b/wcmtools/memcached/api/perl/README @@ -0,0 +1,14 @@ +This is the Perl API for memcached, a distributed memory cache daemon. +See the documentation within the module for details on its use. + +Information on the big picture is available at: + + http://www.danga.com/memcached/ + +Feel free to join the mailing list and ask any questions. + +-- +Brad Fitzpatrick +brad@danga.com + + diff --git a/wcmtools/memcached/api/perl/TODO b/wcmtools/memcached/api/perl/TODO new file mode 100755 index 0000000..bc1d0de --- /dev/null +++ b/wcmtools/memcached/api/perl/TODO @@ -0,0 +1,3 @@ +(currently empty) + + diff --git a/wcmtools/memcached/api/perl/t/use.t b/wcmtools/memcached/api/perl/t/use.t new file mode 100755 index 0000000..357667e --- /dev/null +++ b/wcmtools/memcached/api/perl/t/use.t @@ -0,0 +1,7 @@ +#!/usr/bin/env perl -w +use strict; +use Test; +BEGIN { plan tests => 1 } + +use Cache::Memcached; ok(1); +exit; diff --git a/wcmtools/memcached/api/php/ChangeLog b/wcmtools/memcached/api/php/ChangeLog new file mode 100755 index 0000000..86792f6 --- /dev/null +++ b/wcmtools/memcached/api/php/ChangeLog @@ -0,0 +1,45 @@ +Release 1.0.10 +-------------- +* bug fix: changes hashing function to crc32, sprintf %u +* feature: optional compression + +Release 1.0.9 +------------- +* protocol parsing bug + +Release 1.0.8 +------------- +* whitespace/punctuation/wording cleanups + +Release 1.0.7 +------------- +* added 3 functions which handle error reporting + error() - returns error number of last error generated, else returns 0 + error_string() - returns a string description of error number retuned + error_clear() - clears the last error number and error string +* removed call to preg_match() in _loaditems() +* only non-scalar values are serialize() before being + sent to the server +* added the optional timestamp argument for delete() + read Documentation file for details +* PHPDocs/PEAR style comments added +* abstract debugging (Brion Vibber ) + +Release 1.0.6 +------------- +* removed all array_push() calls +* applied patch provided by Stuart Herbert + corrects possible endless loop. Available at + http://bugs.gentoo.org/show_bug.cgi?id=25385 +* fixed problem with storing large binary files +* added more error checking, specifically on all socket functions +* added support for the INCR and DECR commands + which increment or decrement a value stored in MemCached +* Documentation removed from source and is now available + in the file Documentation + +Release 1.0.4 +------------- +* initial release, version numbers kept + in sync with MemCached version +* capable of storing any datatype in MemCached diff --git a/wcmtools/memcached/api/php/Documentation b/wcmtools/memcached/api/php/Documentation new file mode 100755 index 0000000..4782807 --- /dev/null +++ b/wcmtools/memcached/api/php/Documentation @@ -0,0 +1,258 @@ +Ryan Gilfether +http://www.gilfether.com +This module is Copyright (c) 2003 Ryan Gilfether. +All rights reserved. + +You may distribute under the terms of the GNU General Public License +This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + +See the memcached website: http://www.danga.com/memcached/ + + +// Takes one parameter, a array of options. The most important key is +// options["servers"], but that can also be set later with the set_servers() +// method. The servers must be an array of hosts, each of which is +// either a scalar of the form <10.0.0.10:11211> or an array of the +// former and an integer weight value. (the default weight if +// unspecified is 1.) It's recommended that weight values be kept as low +// as possible, as this module currently allocates memory for bucket +// distribution proportional to the total host weights. +// $options["debug"] turns the debugging on if set to true +MemCachedClient::MemCachedClient($options); + +// sets up the list of servers and the ports to connect to +// takes an array of servers in the same format as in the constructor +MemCachedClient::set_servers($servers); + +// Retrieves a key from the memcache. Returns the value (automatically +// unserialized, if necessary) or FALSE if it fails. +// The $key can optionally be an array, with the first element being the +// hash value, if you want to avoid making this module calculate a hash +// value. You may prefer, for example, to keep all of a given user's +// objects on the same memcache server, so you could use the user's +// unique id as the hash value. +// Possible errors set are: +// MC_ERR_GET +MemCachedClient::get($key); + +// just like get(), but takes an array of keys, returns FALSE on error +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +MemCachedClient::get_multi($keys) + +// Unconditionally sets a key to a given value in the memcache. Returns true +// if it was stored successfully. +// The $key can optionally be an arrayref, with the first element being the +// hash value, as described above. +// returns TRUE on success else FALSE +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// MC_ERR_SET +MemCachedClient::set($key, $value, $exptime); + +// Like set(), but only stores in memcache if the key doesn't already exist. +// returns TRUE on success else FALSE +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// MC_ERR_SET +MemCachedClient::add($key, $value, $exptime); + +// Like set(), but only stores in memcache if the key already exists. +// returns TRUE on success else FALSE +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// MC_ERR_SET +MemCachedClient::replace($key, $value, $exptime); + +// removes the key from the MemCache +// $time is the amount of time in seconds (or Unix time) until which +// the client wishes the server to refuse "add" and "replace" commands +// with this key. For this amount of item, the item is put into a +// delete queue, which means that it won't possible to retrieve it by +// the "get" command, but "add" and "replace" command with this key +// will also fail (the "set" command will succeed, however). After the +// time passes, the item is finally deleted from server memory. +// The parameter $time is optional, and, if absent, defaults to 0 +// (which means that the item will be deleted immediately and further +// storage commands with this key will succeed). +// returns TRUE on success else returns FALSE +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// MC_ERR_DELETE +MemCachedClient::delete($key, $time = 0); + +// Sends a command to the server to atomically increment the value for +// $key by $value, or by 1 if $value is undefined. Returns FALSE if $key +// doesn't exist on server, otherwise it returns the new value after +// incrementing. Value should be zero or greater. Overflow on server +// is not checked. Be aware of values approaching 2**32. See decr. +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// returns new value on success, else returns FALSE +// ONLY WORKS WITH NUMERIC VALUES +MemCachedClient::incr($key[, $value]); + +// Like incr, but decrements. Unlike incr, underflow is checked and new +// values are capped at 0. If server value is 1, a decrement of 2 +// returns 0, not -1. +// Possible errors set are: +// MC_ERR_NOT_ACTIVE +// MC_ERR_GET_SOCK +// MC_ERR_SOCKET_WRITE +// MC_ERR_SOCKET_READ +// returns new value on success, else returns FALSE +// ONLY WORKS WITH NUMERIC VALUES +MemCachedClient::decr($key[, $value]); + +// disconnects from all servers +MemCachedClient::disconnect_all(); + +// if $do_debug is set to true, will print out +// debugging info, else debug is turned off +MemCachedClient::set_debug($do_debug); + +// remove all cached hosts that are no longer good +MemCachedClient::forget_dead_hosts(); + +// When a function returns FALSE, an error code is set. +// This funtion will return the error code. +// See error_string() +// returns last error code set +MemCachedClient::error() + +// Returns a string describing the error set in error() +// See error() +// returns a string describing the error code given +MemCachedClient::error_string() + +// Resets the error number and error string +MemCachedClient::error_clear() + +Error codes are as follows: +MC_ERR_NOT_ACTIVE // no active servers +MC_ERR_SOCKET_WRITE // socket_write() failed +MC_ERR_SOCKET_READ // socket_read() failed +MC_ERR_SOCKET_CONNECT // failed to connect to host +MC_ERR_DELETE // delete() did not recieve DELETED command +MC_ERR_HOST_FORMAT // sock_to_host() invalid host format +MC_ERR_HOST_DEAD // sock_to_host() host is dead +MC_ERR_GET_SOCK // get_sock() failed to find a valid socket +MC_ERR_SET // _set() failed to receive the STORED response +MC_ERR_LOADITEM_HEADER // _load_items failed to receive valid data header +MC_ERR_LOADITEM_END // _load_items failed to receive END response +MC_ERR_LOADITEM_BYTES // _load_items bytes read larger than bytes available +MC_ERR_GET // failed to get value associated with key + +// Turns compression on or off; 0=off, 1=on +MemCacheClient::set_compression($setting) + +EXAMPLE: +set("key_one", $myarr); +$val = $memc->get("key_one"); +print $val[0]."\n"; // prints 'one' +print $val[1]."\n"; // prints 'two' +print $val[2]."\n"; // prints 3 + + +print "\n"; + + +/*********************** + * STORE A CLASS + ***********************/ +class tester +{ + var $one; + var $two; + var $three; +} + +$t = new tester; +$t->one = "one"; +$t->two = "two"; +$t->three = 3; +$memc->set("key_two", $t); +$val = $memc->get("key_two"); +print $val->one."\n"; +print $val->two."\n"; +print $val->three."\n"; + + +print "\n"; + + +/*********************** + * STORE A STRING + ***********************/ +$memc->set("key_three", "my string"); +$val = $memc->get("key_three"); +print $val; // prints 'my string' + +$memc->delete("key_one"); +$memc->delete("key_two"); +$memc->delete("key_three"); + +$memc->disconnect_all(); + + + +print "\n"; + + +/*********************** + * STORE A BINARY FILE + ***********************/ + + // first read the file and save it in memcache +$fp = fopen( "./image.jpg", "rb" ) ; +if ( !$fp ) +{ + print "Could not open ./file.dat!\n" ; + exit ; +} +$data = fread( $fp, filesize( "./image.jpg" ) ) ; +fclose( $fp ) ; +print "Data length is " . strlen( $data ) . "\n" ; +$memc->set( "key", $data ) ; + +// now open a file for writing and write the data +// retrieved from memcache +$fp = fopen("./test.jpg","wb"); +$data = $memc->get( "key" ) ; +print "Data length is " . strlen( $data ) . "\n" ; +fwrite($fp,$data,strlen( $data )); +fclose($fp); + + +?> + + diff --git a/wcmtools/memcached/api/php/MemCachedClient.inc.php b/wcmtools/memcached/api/php/MemCachedClient.inc.php new file mode 100755 index 0000000..a737e5d --- /dev/null +++ b/wcmtools/memcached/api/php/MemCachedClient.inc.php @@ -0,0 +1,1143 @@ + + * http://www.gilfether.com + * + * Originally translated from Brad Fitzpatrick's MemCached Perl client + * See the memcached website: + * http://www.danga.com/memcached/ + * + * This module is Copyright (c) 2003 Ryan Gilfether. + * All rights reserved. + * You may distribute under the terms of the GNU General Public License + * This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. + * + */ + +/** + * version string + */ +define("MC_VERSION", "1.0.10"); +/** + * int, buffer size used for sending and receiving + * data from sockets + */ +define("MC_BUFFER_SZ", 1024); +/** + * MemCached error numbers + */ +define("MC_ERR_NOT_ACTIVE", 1001); // no active servers +define("MC_ERR_SOCKET_WRITE", 1002); // socket_write() failed +define("MC_ERR_SOCKET_READ", 1003); // socket_read() failed +define("MC_ERR_SOCKET_CONNECT", 1004); // failed to connect to host +define("MC_ERR_DELETE", 1005); // delete() did not recieve DELETED command +define("MC_ERR_HOST_FORMAT", 1006); // sock_to_host() invalid host format +define("MC_ERR_HOST_DEAD", 1007); // sock_to_host() host is dead +define("MC_ERR_GET_SOCK", 1008); // get_sock() failed to find a valid socket +define("MC_ERR_SET", 1009); // _set() failed to receive the STORED response +define("MC_ERR_GET_KEY", 1010); // _load_items no values returned for key(s) +define("MC_ERR_LOADITEM_END", 1011); // _load_items failed to receive END response +define("MC_ERR_LOADITEM_BYTES", 1012); // _load_items bytes read larger than bytes available + + +/** + * MemCached PHP client Class. + * + * Communicates with the MemCached server, and executes the MemCached protocol + * MemCached available at http://www.danga.com/memcached + * + * @author Ryan Gilfether + * @package MemCachedClient + * @access public + * @version 1.0.10 + */ +class MemCachedClient +{ + /** + * array of servers no long available + * @var array + */ + var $host_dead; + /** + * array of open sockets + * @var array + */ + var $cache_sock; + /** + * determine if debugging is either on or off + * @var bool + */ + var $debug; + /** + * array of servers to attempt to use, "host:port" string format + * @var array + */ + var $servers; + /** + * count of currently active connections to servers + * @var int + */ + var $active; + /** + * error code if one is set + * @var int + */ + var $errno; + /** + * string describing error + * @var string + */ + var $errstr; + /** + * size of val to force compression; 0 turns off; defaults 1 + * @ var int + */ + var $compress = 1; + /** + * temp flag to turn compression on/off; defaults on + * @ var int + */ + var $comp_active = 1; + + /** + * array that contains parsed out buckets + * @ var array + */ + var $bucket; + + + /** + * Constructor + * + * Creates a new MemCachedClient object + * Takes one parameter, a array of options. The most important key is + * $options["servers"], but that can also be set later with the set_servers() + * method. The servers must be an array of hosts, each of which is + * either a scalar of the form <10.0.0.10:11211> or an array of the + * former and an integer weight value. (the default weight if + * unspecified is 1.) It's recommended that weight values be kept as low + * as possible, as this module currently allocates memory for bucket + * distribution proportional to the total host weights. + * $options["debug"] turns the debugging on if set to true + * + * @access public + * @param array $option an array of servers and debug status + * @return object MemCachedClient the new MemCachedClient object + */ + function MemCachedClient($options = 0) + { + if(is_array($options)) + { + $this->set_servers($options["servers"]); + $this->debug = $options["debug"]; + $this->compress = $options["compress"]; + $this->cache_sock = array(); + } + + $this->errno = 0; + $this->errstr = ""; + } + + + /** + * sets up the list of servers and the ports to connect to + * takes an array of servers in the same format as in the constructor + * + * @access public + * @param array $servers array of servers in the format described in the constructor + */ + function set_servers($servers) + { + $this->servers = $servers; + $this->active = count($this->servers); + } + + + /** + * if $do_debug is set to true, will print out + * debugging info, else debug is turned off + * + * @access public + * @param bool $do_debug set to true to turn debugging on, false to turn off + */ + function set_debug($do_debug) + { + $this->debug = $do_debug; + } + + + /** + * remove all cached hosts that are no longer good + * + * @access public + */ + function forget_dead_hosts() + { + unset($this->host_dead); + } + + + /** + * disconnects from all servers + * + * @access public + */ + function disconnect_all() + { + foreach($this->cache_sock as $sock) + socket_close($sock); + + unset($this->cache_sock); + $this->active = 0; + } + + + /** + * removes the key from the MemCache + * $time is the amount of time in seconds (or Unix time) until which + * the client wishes the server to refuse "add" and "replace" commands + * with this key. For this amount of item, the item is put into a + * delete queue, which means that it won't possible to retrieve it by + * the "get" command, but "add" and "replace" command with this key + * will also fail (the "set" command will succeed, however). After the + * time passes, the item is finally deleted from server memory. + * The parameter $time is optional, and, if absent, defaults to 0 + * (which means that the item will be deleted immediately and further + * storage commands with this key will succeed). + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_DELETE + * + * @access public + * @param string $key the key to delete + * @param timestamp $time optional, the amount of time server will refuse commands on key + * @return bool TRUE on success, FALSE if key does not exist + */ + function delete($key, $time = 0) + { + if(!$this->active) + { + $this->errno = MC_ERR_NOT_ACTIVE; + $this->errstr = "No active servers are available"; + + if($this->debug) + $this->_debug("delete(): There are no active servers available."); + + return FALSE; + } + + $sock = $this->get_sock($key); + + if(!is_resource($sock)) + { + $this->errno = MC_ERR_GET_SOCK; + $this->errstr = "Unable to retrieve a valid socket."; + + if($this->debug) + $this->_debug("delete(): get_sock() returned an invalid socket."); + + return FALSE; + } + + if(is_array($key)) + $key = $key[1]; + + $cmd = "delete $key $time\r\n"; + $cmd_len = strlen($cmd); + $offset = 0; + + // now send the command + while($offset < $cmd_len) + { + $result = socket_write($sock, substr($cmd, $offset, MC_BUFFER_SZ), MC_BUFFER_SZ); + + if($result !== FALSE) + $offset += $result; + else if($offset < $cmd_len) + { + $this->errno = MC_ERR_SOCKET_WRITE; + $this->errstr = "Failed to write to socket."; + + if($this->debug) + { + $sockerr = socket_last_error($sock); + $this->_debug("delete(): socket_write() returned FALSE. Socket Error $sockerr: ".socket_strerror($sockerr)); + } + + return FALSE; + } + } + + // now read the server's response + if(($retval = socket_read($sock, MC_BUFFER_SZ, PHP_NORMAL_READ)) === FALSE) + { + $this->errno = MC_ERR_SOCKET_READ; + $this->errstr = "Failed to read from socket."; + + if($this->debug) + { + $sockerr = socket_last_error($sock); + $this->_debug("delete(): socket_read() returned FALSE. Socket Error $sockerr: ".socket_strerror($sockerr)); + } + + return FALSE; + } + + // remove the \r\n from the end + $retval = rtrim($retval); + + // now read the server's response + if($retval == "DELETED") + return TRUE; + else + { + // something went wrong, create the error + $this->errno = MC_ERR_DELETE; + $this->errstr = "Failed to receive DELETED response from server."; + + if($this->debug) + $this->_debug("delete(): Failed to receive DELETED response from server. Received $retval instead."); + + return FALSE; + } + } + + + /** + * Like set(), but only stores in memcache if the key doesn't already exist. + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_SET + * + * @access public + * @param string $key the key to set + * @param mixed $val the value of the key + * @param timestamp $exptime optional, the to to live of the key + * @return bool TRUE on success, else FALSE + */ + function add($key, $val, $exptime = 0) + { + return $this->_set("add", $key, $val, $exptime); + } + + + /** + * Like set(), but only stores in memcache if the key already exists. + * returns TRUE on success else FALSE + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_SET + * + * @access public + * @param string $key the key to set + * @param mixed $val the value of the key + * @param timestamp $exptime optional, the to to live of the key + * @return bool TRUE on success, else FALSE + */ + function replace($key, $val, $exptime = 0) + { + return $this->_set("replace", $key, $val, $exptime); + } + + + /** + * Unconditionally sets a key to a given value in the memcache. Returns true + * if it was stored successfully. + * The $key can optionally be an arrayref, with the first element being the + * hash value, as described above. + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_SET + * + * @access public + * @param string $key the key to set + * @param mixed $val the value of the key + * @param timestamp $exptime optional, the to to live of the key + * @return bool TRUE on success, else FALSE + */ + function set($key, $val, $exptime = 0) + { + return $this->_set("set", $key, $val, $exptime); + } + + + /** + * Retrieves a key from the memcache. Returns the value (automatically + * unserialized, if necessary) or FALSE if it fails. + * The $key can optionally be an array, with the first element being the + * hash value, if you want to avoid making this module calculate a hash + * value. You may prefer, for example, to keep all of a given user's + * objects on the same memcache server, so you could use the user's + * unique id as the hash value. + * Possible errors set are: + * MC_ERR_GET_KEY + * + * @access public + * @param string $key the key to retrieve + * @return mixed the value of the key, FALSE on error + */ + function get($key) + { + $val =& $this->get_multi($key); + + if(!$val) + { + $this->errno = MC_ERR_GET_KEY; + $this->errstr = "No value found for key $key"; + + if($this->debug) + $this->_debug("get(): No value found for key $key"); + + return FALSE; + } + + return $val[$key]; + } + + + /** + * just like get(), but takes an array of keys, returns FALSE on error + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * + * @access public + * @param array $keys the keys to retrieve + * @return array the value of each key, FALSE on error + */ + function get_multi($keys) + { + $sock_keys = array(); + $socks = array(); + $val = 0; + + if(!$this->active) + { + $this->errno = MC_ERR_NOT_ACTIVE; + $this->errstr = "No active servers are available"; + + if($this->debug) + $this->_debug("get_multi(): There are no active servers available."); + + return FALSE; + } + + if(!is_array($keys)) + { + $arr[] = $keys; + $keys = $arr; + } + + foreach($keys as $k) + { + $sock = $this->get_sock($k); + + if($sock) + { + $k = is_array($k) ? $k[1] : $k; + + if(@!is_array($sock_keys[$sock])) + $sock_keys[$sock] = array(); + + // if $sock_keys[$sock] doesn't exist, create it + if(!$sock_keys[$sock]) + $socks[] = $sock; + + $sock_keys[$sock][] = $k; + } + } + + if(!is_array($socks)) + { + $arr[] = $socks; + $socks = $arr; + } + + foreach($socks as $s) + { + $this->_load_items($s, $val, $sock_keys[$sock]); + } + + if($this->debug) + { + while(list($k, $v) = @each($val)) + $this->_debug("MemCache: got $k = $v\n"); + } + + return $val; + } + + + /** + * Sends a command to the server to atomically increment the value for + * $key by $value, or by 1 if $value is undefined. Returns FALSE if $key + * doesn't exist on server, otherwise it returns the new value after + * incrementing. Value should be zero or greater. Overflow on server + * is not checked. Be aware of values approaching 2**32. See decr. + * ONLY WORKS WITH NUMERIC VALUES + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * + * @access public + * @param string $key the keys to increment + * @param int $value the amount to increment the key bye + * @return int the new value of the key, else FALSE + */ + function incr($key, $value = 1) + { + return $this->_incrdecr("incr", $key, $value); + } + + + /** + * Like incr, but decrements. Unlike incr, underflow is checked and new + * values are capped at 0. If server value is 1, a decrement of 2 + * returns 0, not -1. + * ONLY WORKS WITH NUMERIC VALUES + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * + * @access public + * @param string $key the keys to increment + * @param int $value the amount to increment the key bye + * @return int the new value of the key, else FALSE + */ + function decr($key, $value = 1) + { + return $this->_incrdecr("decr", $key, $value); + } + + + /** + * When a function returns FALSE, an error code is set. + * This funtion will return the error code. + * See error_string() + * + * @access public + * @return int the value of the last error code + */ + function error() + { + return $this->errno; + } + + + /** + * Returns a string describing the error set in error() + * See error() + * + * @access public + * @return int a string describing the error code given + */ + function error_string() + { + return $this->errstr; + } + + + /** + * Resets the error number and error string + * + * @access public + */ + function error_clear() + { + // reset to no error + $this->errno = 0; + $this->errstr = ""; + } + + + /** + * temporarily sets compression on or off + * turning it off, and then back on will result in the compression threshold going + * back to the original setting from $options + * @param int $setting setting of compression (0=off|1=on) + */ + + function set_compression($setting=1) { + if ($setting != 0) { + $this->comp_active = 1; + } else { + $this->comp_active = 0; + } + } + + + + /* + * PRIVATE FUNCTIONS + */ + + + /** + * connects to a server + * The $host may either a string int the form of host:port or an array of the + * former and an integer weight value. (the default weight if + * unspecified is 1.) See the constructor for details + * Possible errors set are: + * MC_ERR_HOST_FORMAT + * MC_ERR_HOST_DEAD + * MC_ERR_SOCKET_CONNECT + * + * @access private + * @param mixed $host either an array or a string + * @return resource the socket of the new connection, else FALSE + */ + function sock_to_host($host) + { + if(is_array($host)) + $host = array_shift($host); + + $now = time(); + + // seperate the ip from the port, index 0 = ip, index 1 = port + $conn = explode(":", $host); + if(count($conn) != 2) + { + $this->errno = MC_ERR_HOST_FORMAT; + $this->errstr = "Host address was not in the format of host:port"; + + if($this->debug) + $this->_debug("sock_to_host(): Host address was not in the format of host:port"); + + return FALSE; + } + + if(@($this->host_dead[$host] && $this->host_dead[$host] > $now) || + @($this->host_dead[$conn[0]] && $this->host_dead[$conn[0]] > $now)) + { + $this->errno = MC_ERR_HOST_DEAD; + $this->errstr = "Host $host is not available."; + + if($this->debug) + $this->_debug("sock_to_host(): Host $host is not available."); + + return FALSE; + } + + // connect to the server, if it fails, add it to the host_dead below + $sock = socket_create (AF_INET, SOCK_STREAM, getprotobyname("TCP")); + + // we need surpress the error message if a connection fails + if(!@socket_connect($sock, $conn[0], $conn[1])) + { + $this->host_dead[$host]=$this->host_dead[$conn[0]]=$now+60+intval(rand(0, 10)); + + $this->errno = MC_ERR_SOCKET_CONNECT; + $this->errstr = "Failed to connect to ".$conn[0].":".$conn[1]; + + if($this->debug) + $this->_debug("sock_to_host(): Failed to connect to ".$conn[0].":".$conn[1]); + + return FALSE; + } + + // success, add to the list of sockets + $cache_sock[$host] = $sock; + + return $sock; + } + + + /** + * retrieves the socket associated with a key + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * + * @access private + * @param string $key the key to retrieve the socket from + * @return resource the socket of the connection, else FALSE + */ + function get_sock($key) + { + if(!$this->active) + { + $this->errno = MC_ERR_NOT_ACTIVE; + $this->errstr = "No active servers are available"; + + if($this->debug) + $this->_debug("get_sock(): There are no active servers available."); + + return FALSE; + } + + $hv = is_array($key) ? intval($key[0]) : $this->_hashfunc($key); + + if(!$this->buckets) + { + $bu = $this->buckets = array(); + + foreach($this->servers as $v) + { + if(is_array($v)) + { + for($i = 1; $i <= $v[1]; ++$i) + $bu[] = $v[0]; + } + else + $bu[] = $v; + } + + $this->buckets = $bu; + } + + $real_key = is_array($key) ? $key[1] : $key; + $tries = 0; + while($tries < 20) + { + $host = @$this->buckets[$hv % count($this->buckets)]; + $sock = $this->sock_to_host($host); + + if(is_resource($sock)) + return $sock; + + $hv += $this->_hashfunc($tries.$real_key); + ++$tries; + } + + $this->errno = MC_ERR_GET_SOCK; + $this->errstr = "Unable to retrieve a valid socket."; + + if($this->debug) + $this->_debug("get_sock(): Unable to retrieve a valid socket."); + + return FALSE; + } + + + /** + * increments or decrements a numerical value in memcached. this function is + * called from incr() and decr() + * ONLY WORKS WITH NUMERIC VALUES + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * + * @access private + * @param string $cmdname the command to send, either incr or decr + * @param string $key the key to perform the command on + * @param mixed $value the value to incr or decr the key value by + * @return int the new value of the key, FALSE if something went wrong + */ + function _incrdecr($cmdname, $key, $value) + { + if(!$this->active) + { + $this->errno = MC_ERR_NOT_ACTIVE; + $this->errstr = "No active servers are available"; + + if($this->debug) + $this->_debug("_incrdecr(): There are no active servers available."); + + return FALSE; + } + + $sock = $this->get_sock($key); + if(!is_resource($sock)) + { + $this->errno = MC_ERR_GET_SOCK; + $this->errstr = "Unable to retrieve a valid socket."; + + if($this->debug) + $this->_debug("_incrdecr(): Invalid socket returned by get_sock()."); + + return FALSE; + } + + if($value == "") + $value = 1; + + $cmd = "$cmdname $key $value\r\n"; + $cmd_len = strlen($cmd); + $offset = 0; + + // write the command to the server + while($offset < $cmd_len) + { + $result = socket_write($sock, substr($cmd, $offset, MC_BUFFER_SZ), MC_BUFFER_SZ); + + if($result !== FALSE) + $offset += $result; + else if($offset < $cmd_len) + { + $this->errno = MC_ERR_SOCKET_WRITE; + $this->errstr = "Failed to write to socket."; + + if($this->debug) + { + $sockerr = socket_last_error($sock); + $this->_debug("_incrdecr(): socket_write() returned FALSE. Error $errno: ".socket_strerror($sockerr)); + } + + return FALSE; + } + } + + // now read the server's response + if(($retval = socket_read($sock, MC_BUFFER_SZ, PHP_NORMAL_READ)) === FALSE) + { + $this->errno = MC_ERR_SOCKET_READ; + $this->errstr = "Failed to read from socket."; + + if($this->debug) + { + $sockerr = socket_last_error($sock); + $this->_debug("_incrdecr(): socket_read() returned FALSE. Socket Error $errno: ".socket_strerror($sockerr)); + } + + return FALSE; + } + + // strip the /r/n from the end and return value + return trim($retval); + } + + /** + * sends the command to the server + * Possible errors set are: + * MC_ERR_NOT_ACTIVE + * MC_ERR_GET_SOCK + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_SET + * + * @access private + * @param string $cmdname the command to send, either incr or decr + * @param string $key the key to perform the command on + * @param mixed $value the value to set the key to + * @param timestamp $exptime expiration time of the key + * @return bool TRUE on success, else FALSE + */ + function _set($cmdname, $key, $val, $exptime = 0) + { + if(!$this->active) + { + $this->errno = MC_ERR_NOT_ACTIVE; + $this->errstr = "No active servers are available"; + + if($this->debug) + $this->_debug("_set(): No active servers are available."); + + return FALSE; + } + + $sock = $this->get_sock($key); + if(!is_resource($sock)) + { + $this->errno = MC_ERR_GET_SOCK; + $this->errstr = "Unable to retrieve a valid socket."; + + if($this->debug) + $this->_debug("_set(): Invalid socket returned by get_sock()."); + + return FALSE; + } + + $flags = 0; + $key = is_array($key) ? $key[1] : $key; + + $raw_val = $val; + + // if the value is not scalar, we need to serialize it + if(!is_scalar($val)) + { + $val = serialize($val); + $flags |= 1; + } + + if (($this->compress_active) && ($this->compress > 0) && (strlen($val) > $this->compress)) { + $this->_debug("_set(): compressing data. size in:".strlen($val)); + $cval=gzcompress($val); + $this->_debug("_set(): done compressing data. size out:".strlen($cval)); + if ((strlen($cval) < strlen($val)) && (strlen($val) - strlen($cval) > 2048)){ + $flags |= 2; + $val=$cval; + } + unset($cval); + } + + $len = strlen($val); + if (!is_int($exptime)) + $exptime = 0; + + // send off the request + $cmd = "$cmdname $key $flags $exptime $len\r\n$val\r\n"; + $cmd_len = strlen($cmd); + $offset = 0; + + // write the command to the server + while($offset < $cmd_len) + { + $result = socket_write($sock, substr($cmd, $offset, MC_BUFFER_SZ), MC_BUFFER_SZ); + + if($result !== FALSE) + $offset += $result; + else if($offset < $cmd_len) + { + $this->errno = MC_ERR_SOCKET_WRITE; + $this->errstr = "Failed to write to socket."; + + if($this->debug) + { + $errno = socket_last_error($sock); + $this->_debug("_set(): socket_write() returned FALSE. Error $errno: ".socket_strerror($errno)); + } + + return FALSE; + } + } + + // now read the server's response + if(($l_szResponse = socket_read($sock, 6, PHP_NORMAL_READ)) === FALSE) + { + $this->errno = MC_ERR_SOCKET_READ; + $this->errstr = "Failed to read from socket."; + + if($this->debug) + { + $errno = socket_last_error($sock); + $this->_debug("_set(): socket_read() returned FALSE. Error $errno: ".socket_strerror($errno)); + } + + return FALSE; + } + + if($l_szResponse == "STORED") + { + if($this->debug) + $this->_debug("MemCache: $cmdname $key = $raw_val"); + + return TRUE; + } + + $this->errno = MC_ERR_SET; + $this->errstr = "Failed to receive the STORED response from the server."; + + if($this->debug) + $this->_debug("_set(): Did not receive STORED as the server response! Received $l_szResponse instead."); + + return FALSE; + } + + + /** + * retrieves the value, and returns it unserialized + * Possible errors set are: + * MC_ERR_SOCKET_WRITE + * MC_ERR_SOCKET_READ + * MC_ERR_GET_KEY + * MC_ERR_LOADITEM_END + * MC_ERR_LOADITEM_BYTES + * + * @access private + * @param resource $sock the socket to connection we are retriving from + * @param array $val reference to the values retrieved + * @param mixed $sock_keys either a string or an array of keys to retrieve + * @return array TRUE on success, else FALSE + */ + function _load_items($sock, &$val, $sock_keys) + { + $val = array(); + $cmd = "get "; + + if(!is_array($sock_keys)) + { + $arr[] = $sock_keys; + $sock_keys = $arr; + } + + foreach($sock_keys as $sk) + $cmd .= $sk." "; + + $cmd .="\r\n"; + $cmd_len = strlen($cmd); + $offset = 0; + + // write the command to the server + while($offset < $cmd_len) + { + $result = socket_write($sock, substr($cmd, $offset, MC_BUFFER_SZ), MC_BUFFER_SZ); + + if($result !== FALSE) + $offset += $result; + else if($offset < $cmd_len) + { + $this->errno = MC_ERR_SOCKET_WRITE; + $this->errstr = "Failed to write to socket."; + + if($this->debug) + { + $errno = socket_last_error($sock); + $this->_debug("_load_items(): socket_write() returned FALSE. Error $errno: ".socket_strerror($errno)); + } + + return FALSE; + } + } + + $len = 0; + $buf = ""; + $flags_array = array(); + + // now read the response from the server + while($line = socket_read($sock, MC_BUFFER_SZ, PHP_BINARY_READ)) + { + // check for a socket_read error + if($line === FALSE) + { + $this->errno = MC_ERR_SOCKET_READ; + $this->errstr = "Failed to read from socket."; + + if($this->debug) + { + $errno = socket_last_error($sock); + $this->_debug("_load_items(): socket_read() returned FALSE. Error $errno: ".socket_strerror($errno)); + } + + return FALSE; + } + + if($len == 0) + { + $header = substr($line, 0, strpos($line, "\r\n")); + $matches = explode(" ", $header); + + if(is_string($matches[1]) && is_numeric($matches[2]) && is_numeric($matches[3])) + { + $rk = $matches[1]; + $flags = $matches[2]; + $len = $matches[3]; + + if($flags) + $flags_array[$rk] = $flags; + + $len_array[$rk] = $len; + $bytes_read = 0; + + // get the left over data after the header is read + $line = substr($line, strpos($line, "\r\n")+2, strlen($line)); + } + else + { + $this->errno = MC_ERR_GET_KEY; + $this->errstr = "Requested key(s) returned no values."; + + // something went wrong, we never recieved the header + if($this->debug) + $this->_debug("_load_items(): Requested key(s) returned no values."); + + return FALSE; + } + } + + // skip over the extra return or newline + if($line == "\r" || $line == "\n") + continue; + + $bytes_read += strlen($line); + $buf .= $line; + + // we read the all of the data, take in account + // for the /r/nEND/r/n + if($bytes_read == ($len + 7)) + { + $end = substr($buf, $len+2, 3); + if($end == "END") + { + $val[$rk] = substr($buf, 0, $len); + + foreach($sock_keys as $sk) + { + if(!isset($val[$sk])) + continue; + + if(strlen($val[$sk]) != $len_array[$sk]) + continue; + if(@$flags_array[$sk] & 2) + $val[$sk] = gzuncompress($val[$sk]); + + if(@$flags_array[$sk] & 1) + $val[$sk] = unserialize($val[$sk]); + } + + return TRUE; + } + else + { + $this->errno = MC_ERR_LOADITEM_END; + $this->errstr = "Failed to receive END response from server."; + + if($this->debug) + $this->_debug("_load_items(): Failed to receive END. Received $end instead."); + + return FALSE; + } + } + + // take in consideration for the "\r\nEND\r\n" + if($bytes_read > ($len + 7)) + { + $this->errno = MC_ERR_LOADITEM_BYTES; + $this->errstr = "Bytes read from server greater than size of data."; + + if($this->debug) + $this->_debug("_load_items(): Bytes read is greater than requested data size."); + + return FALSE; + } + + } + } + + + /** + * creates our hash + * + * @access private + * @param int $num + * @return hash + */ + function _hashfunc($num) + { + $hash = sprintf("%u",crc32($num)); + + return $hash; + } + + /** + * function that can be overridden to handle debug output + * by default debug info is print to the screen + * + * @access private + * @param $text string to output debug info + */ + function _debug($text) + { + print $text . "\r\n"; + } +} + +?> \ No newline at end of file diff --git a/wcmtools/memcached/api/php/dist.pl b/wcmtools/memcached/api/php/dist.pl new file mode 100755 index 0000000..ca8516c --- /dev/null +++ b/wcmtools/memcached/api/php/dist.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl +# +# Simplify Brad's life. I'm sure there's a PHP-specific way +# to do this (or there should be), but I don't do the PHP, +# so this is my answer. +# +# Heavily documented for the PHP programmers who might be +# reading this. +# + +use strict; +use Getopt::Long; + +my $opt_tar = 0; +my $opt_upload = 0; +exit 1 unless GetOptions("tar" => \$opt_tar, + "upload" => \$opt_upload); + +# chdir to the directory the script's at, so future +# paths need only be relative +use FindBin qw($Bin); +chdir $Bin or die "Couldn't cd to $Bin\n"; + +die "Must use --tar or --upload\n" unless $opt_tar || $opt_upload; + +# files to distribute +my @manifest = qw( + ChangeLog + Documentation + MemCachedClient.inc.php + ); + +# figure out the version number +open (PHP, "MemCachedClient.inc.php") or die; +{ local $/ = undef; $_ = ; } # suck in the whole file +close PHP; +die "Can't find version number\n" unless + /MC_VERSION.+?(\d[^\'\"]+)/s; +my $ver = $1; +my $dir = "php-memcached-$ver"; +my $dist = "$dir.tar.gz"; + +if ($opt_tar) { + # make a fresh directory + mkdir $dir or die "Couldn't make directory: $dir\n"; + + # copy files to fresh directory + foreach my $file (@manifest) { + system("cp", $file, "$dir/$file") + and die "Error copying file $file\n"; + } + + # tar it up + system("tar", "zcf", $dist, $dir) + and die "Error running tar.\n"; + + # remove temp directory + system("rm", "-rf", $dir) + and die "Error cleaning up temp directory\n"; + + print "$dist created.\n"; +} + +if ($opt_upload) { + print "Uploading $dist...\n"; + system("scp", $dist, 'bradfitz@danga.com:memd/dist/') + and die "Error uploading to memcached/dist\n"; +} + +print "Done.\n"; diff --git a/wcmtools/memcached/api/python/ChangeLog b/wcmtools/memcached/api/python/ChangeLog new file mode 100755 index 0000000..b843423 --- /dev/null +++ b/wcmtools/memcached/api/python/ChangeLog @@ -0,0 +1,16 @@ +Thu, 10 Aug 2003 12:17:50 -0700 Evan Martin + + * Slightly more verbose self-test output. + * Fix mark_dead() to use proper classname. + * Make pooltest.py run from the test directory. + +Thu, 07 Aug 2003 16:32:32 -0700 Evan Martin + + * Add incr, decr, and delete. + * Better Python (based on comments from Uriah Welcome). + * Docs, using epydoc. + +Thu, 07 Aug 2003 14:20:27 -0700 Evan Martin + + * Initial prerelease. + diff --git a/wcmtools/memcached/api/python/DISTNOTES b/wcmtools/memcached/api/python/DISTNOTES new file mode 100755 index 0000000..9180feb --- /dev/null +++ b/wcmtools/memcached/api/python/DISTNOTES @@ -0,0 +1,3 @@ +Note for Brad, on how to make new releases: + +$ python setup.py sdist diff --git a/wcmtools/memcached/api/python/MANIFEST b/wcmtools/memcached/api/python/MANIFEST new file mode 100755 index 0000000..9b3df00 --- /dev/null +++ b/wcmtools/memcached/api/python/MANIFEST @@ -0,0 +1,2 @@ +memcache.py +setup.py diff --git a/wcmtools/memcached/api/python/PKG-INFO b/wcmtools/memcached/api/python/PKG-INFO new file mode 100755 index 0000000..9f0d67a --- /dev/null +++ b/wcmtools/memcached/api/python/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: python-memcache +Version: 1.1 +Summary: UNKNOWN +Home-page: http://www.danga.com/memcached/ +Author: Evan Martin +Author-email: martine@danga.com +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/wcmtools/memcached/api/python/memcache.py b/wcmtools/memcached/api/python/memcache.py new file mode 100755 index 0000000..b10c016 --- /dev/null +++ b/wcmtools/memcached/api/python/memcache.py @@ -0,0 +1,585 @@ +#!/usr/bin/env python + +""" +client module for memcached (memory cache daemon) + +Overview +======== + +See U{the MemCached homepage} for more about memcached. + +Usage summary +============= + +This should give you a feel for how this module operates:: + + import memcache + mc = memcache.Client(['127.0.0.1:11211'], debug=0) + + mc.set("some_key", "Some value") + value = mc.get("some_key") + + mc.set("another_key", 3) + mc.delete("another_key") + + mc.set("key", "1") # note that the key used for incr/decr must be a string. + mc.incr("key") + mc.decr("key") + +The standard way to use memcache with a database is like this:: + + key = derive_key(obj) + obj = mc.get(key) + if not obj: + obj = backend_api.get(...) + mc.set(obj) + + # we now have obj, and future passes through this code + # will use the object from the cache. + +Detailed Documentation +====================== + +More detailed documentation is available in the L{Client} class. +""" + +import sys +import socket +import time +import types +try: + import cPickle as pickle +except ImportError: + import pickle + +__author__ = "Evan Martin " +__version__ = "1.2" +__copyright__ = "Copyright (C) 2003 Danga Interactive" +__license__ = "Python" + +class _Error(Exception): + pass + +class Client: + """ + Object representing a pool of memcache servers. + + See L{memcache} for an overview. + + In all cases where a key is used, the key can be either: + 1. A simple hashable type (string, integer, etc.). + 2. A tuple of C{(hashvalue, key)}. This is useful if you want to avoid + making this module calculate a hash value. You may prefer, for + example, to keep all of a given user's objects on the same memcache + server, so you could use the user's unique id as the hash value. + + @group Setup: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog + @group Insertion: set, add, replace + @group Retrieval: get, get_multi + @group Integers: incr, decr + @group Removal: delete + @sort: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog,\ + set, add, replace, get, get_multi, incr, decr, delete + """ + _FLAG_PICKLE = 1<<0 + _FLAG_INTEGER = 1<<1 + _FLAG_LONG = 1<<2 + + _SERVER_RETRIES = 10 # how many times to try finding a free server. + + def __init__(self, servers, debug=0): + """ + Create a new Client object with the given list of servers. + + @param servers: C{servers} is passed to L{set_servers}. + @param debug: whether to display error messages when a server can't be + contacted. + """ + self.set_servers(servers) + self.debug = debug + self.stats = {} + + def set_servers(self, servers): + """ + Set the pool of servers used by this client. + + @param servers: an array of servers. + Servers can be passed in two forms: + 1. Strings of the form C{"host:port"}, which implies a default weight of 1. + 2. Tuples of the form C{("host:port", weight)}, where C{weight} is + an integer weight value. + """ + self.servers = [_Host(s, self.debuglog) for s in servers] + self._init_buckets() + + def debuglog(self, str): + if self.debug: + sys.stderr.write("MemCached: %s\n" % str) + + def _statlog(self, func): + if not self.stats.has_key(func): + self.stats[func] = 1 + else: + self.stats[func] += 1 + + def forget_dead_hosts(self): + """ + Reset every host in the pool to an "alive" state. + """ + for s in self.servers: + s.dead_until = 0 + + def _init_buckets(self): + self.buckets = [] + for server in self.servers: + for i in range(server.weight): + self.buckets.append(server) + + def _get_server(self, key): + if type(key) == types.TupleType: + serverhash = key[0] + key = key[1] + else: + serverhash = hash(key) + + for i in range(Client._SERVER_RETRIES): + server = self.buckets[serverhash % len(self.buckets)] + if server.connect(): + #print "(using server %s)" % server, + return server, key + serverhash = hash(str(serverhash) + str(i)) + return None, None + + def disconnect_all(self): + for s in self.servers: + s.close_socket() + + def delete(self, key, time=0): + '''Deletes a key from the memcache. + + @return: Nonzero on success. + @rtype: int + ''' + server, key = self._get_server(key) + if not server: + return 0 + self._statlog('delete') + if time != None: + cmd = "delete %s %d" % (key, time) + else: + cmd = "delete %s" % key + + try: + server.send_cmd(cmd) + server.expect("DELETED") + except socket.error, msg: + server.mark_dead(msg[1]) + return 0 + return 1 + + def incr(self, key, delta=1): + """ + Sends a command to the server to atomically increment the value for C{key} by + C{delta}, or by 1 if C{delta} is unspecified. Returns None if C{key} doesn't + exist on server, otherwise it returns the new value after incrementing. + + Note that the value for C{key} must already exist in the memcache, and it + must be the string representation of an integer. + + >>> mc.set("counter", "20") # returns 1, indicating success + 1 + >>> mc.incr("counter") + 21 + >>> mc.incr("counter") + 22 + + Overflow on server is not checked. Be aware of values approaching + 2**32. See L{decr}. + + @param delta: Integer amount to increment by (should be zero or greater). + @return: New value after incrementing. + @rtype: int + """ + return self._incrdecr("incr", key, delta) + + def decr(self, key, delta=1): + """ + Like L{incr}, but decrements. Unlike L{incr}, underflow is checked and + new values are capped at 0. If server value is 1, a decrement of 2 + returns 0, not -1. + + @param delta: Integer amount to decrement by (should be zero or greater). + @return: New value after decrementing. + @rtype: int + """ + return self._incrdecr("decr", key, delta) + + def _incrdecr(self, cmd, key, delta): + server, key = self._get_server(key) + if not server: + return 0 + self._statlog(cmd) + cmd = "%s %s %d" % (cmd, key, delta) + try: + server.send_cmd(cmd) + line = server.readline() + return int(line) + except socket.error, msg: + server.mark_dead(msg[1]) + return None + + def add(self, key, val, time=0): + ''' + Add new key with value. + + Like L{set}, but only stores in memcache if the key doesn't already exist. + + @return: Nonzero on success. + @rtype: int + ''' + return self._set("add", key, val, time) + def replace(self, key, val, time=0): + '''Replace existing key with value. + + Like L{set}, but only stores in memcache if the key already exists. + The opposite of L{add}. + + @return: Nonzero on success. + @rtype: int + ''' + return self._set("replace", key, val, time) + def set(self, key, val, time=0): + '''Unconditionally sets a key to a given value in the memcache. + + The C{key} can optionally be an tuple, with the first element being the + hash value, if you want to avoid making this module calculate a hash value. + You may prefer, for example, to keep all of a given user's objects on the + same memcache server, so you could use the user's unique id as the hash + value. + + @return: Nonzero on success. + @rtype: int + ''' + return self._set("set", key, val, time) + + def _set(self, cmd, key, val, time): + server, key = self._get_server(key) + if not server: + return 0 + + self._statlog(cmd) + + flags = 0 + if isinstance(val, types.StringTypes): + pass + elif isinstance(val, int): + flags |= Client._FLAG_INTEGER + val = "%d" % val + elif isinstance(val, long): + flags |= Client._FLAG_LONG + val = "%d" % val + else: + flags |= Client._FLAG_PICKLE + val = pickle.dumps(val, 2) + + fullcmd = "%s %s %d %d %d\r\n%s" % (cmd, key, flags, time, len(val), val) + try: + server.send_cmd(fullcmd) + server.expect("STORED") + except socket.error, msg: + server.mark_dead(msg[1]) + return 0 + return 1 + + def get(self, key): + '''Retrieves a key from the memcache. + + @return: The value or None. + ''' + server, key = self._get_server(key) + if not server: + return None + + self._statlog('get') + + try: + server.send_cmd("get %s" % key) + rkey, flags, rlen, = self._expectvalue(server) + if not rkey: + return None + value = self._recv_value(server, flags, rlen) + server.expect("END") + except (_Error, socket.error), msg: + if type(msg) is types.TupleType: + msg = msg[1] + server.mark_dead(msg) + return None + return value + + def get_multi(self, keys): + ''' + Retrieves multiple keys from the memcache doing just one query. + + >>> success = mc.set("foo", "bar") + >>> success = mc.set("baz", 42) + >>> mc.get_multi(["foo", "baz", "foobar"]) == {"foo": "bar", "baz": 42} + 1 + + This method is recommended over regular L{get} as it lowers the number of + total packets flying around your network, reducing total latency, since + your app doesn't have to wait for each round-trip of L{get} before sending + the next one. + + @param keys: An array of keys. + @return: A dictionary of key/value pairs that were available. + + ''' + + self._statlog('get_multi') + + server_keys = {} + + # build up a list for each server of all the keys we want. + for key in keys: + server, key = self._get_server(key) + if not server: + continue + if not server_keys.has_key(server): + server_keys[server] = [] + server_keys[server].append(key) + + # send out all requests on each server before reading anything + dead_servers = [] + for server in server_keys.keys(): + try: + server.send_cmd("get %s" % " ".join(server_keys[server])) + except socket.error, msg: + server.mark_dead(msg[1]) + dead_servers.append(server) + + # if any servers died on the way, don't expect them to respond. + for server in dead_servers: + del server_keys[server] + + retvals = {} + for server in server_keys.keys(): + try: + line = server.readline() + while line and line != 'END': + rkey, flags, rlen = self._expectvalue(server, line) + val = self._recv_value(server, flags, rlen) + retvals[rkey] = val + line = server.readline() + except (_Error, socket.error), msg: + server.mark_dead(msg) + return retvals + + def _expectvalue(self, server, line=None): + if not line: + line = server.readline() + + if line[:5] == 'VALUE': + resp, rkey, flags, len = line.split() + flags = int(flags) + rlen = int(len) + return (rkey, flags, rlen) + else: + return (None, None, None) + + def _recv_value(self, server, flags, rlen): + rlen += 2 # include \r\n + buf = server.recv(rlen) + if len(buf) != rlen: + raise _Error("received %d bytes when expecting %d" % (len(buf), rlen)) + + if len(buf) == rlen: + buf = buf[:-2] # strip \r\n + + if flags == 0: + val = buf + elif flags & Client._FLAG_INTEGER: + val = int(buf) + elif flags & Client._FLAG_LONG: + val = long(buf) + elif flags & Client._FLAG_PICKLE: + val = pickle.loads(buf) + else: + self.debuglog("unknown flags on get: %x\n" % flags) + + return val + + +class _Host: + _DEAD_RETRY = 30 # number of seconds before retrying a dead server. + + def __init__(self, host, debugfunc=None): + if isinstance(host, types.TupleType): + host = host[0] + self.weight = host[1] + else: + self.weight = 1 + + if host.find(":") > 0: + self.ip, self.port = host.split(":") + self.port = int(self.port) + else: + self.ip, self.port = host, 11211 + + if not debugfunc: + debugfunc = lambda x: x + self.debuglog = debugfunc + + self.deaduntil = 0 + self.socket = None + + def _check_dead(self): + if self.deaduntil and self.deaduntil > time.time(): + return 1 + self.deaduntil = 0 + return 0 + + def connect(self): + if self._get_socket(): + return 1 + return 0 + + def mark_dead(self, reason): + print "MemCache: %s: %s. Marking dead." % (self, reason) + self.deaduntil = time.time() + _Host._DEAD_RETRY + self.close_socket() + + def _get_socket(self): + if self._check_dead(): + return None + if self.socket: + return self.socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # Python 2.3-ism: s.settimeout(1) + try: + s.connect((self.ip, self.port)) + except socket.error, msg: + self.mark_dead("connect: %s" % msg[1]) + return None + self.socket = s + return s + + def close_socket(self): + if self.socket: + self.socket.close() + self.socket = None + + def send_cmd(self, cmd): + self.socket.sendall(cmd + "\r\n") + + def readline(self): + newlines = 0 + buf = '' + while newlines < 2: + char = self.socket.recv(1) # XXX does this buffer or is this slow? + if len(char) == 0: + # connection closed. + print "MemCache: Connection closed while reading from %s. Marking dead." % self + self.mark_dead + return buf + if char == '\r' and newlines == 0: + newlines = 1 + elif char == '\n' and newlines == 1: + newlines = 2 + else: + newlines = 0 + buf = buf + char + return buf + + def expect(self, text): + line = self.readline() + if line != text: + self.debuglog("while expecting '%s', got unexpected response '%s'" % (text, line)) + return line + + def recv(self, rlen): + buf = '' + while len(buf) < rlen: + buf = buf + self.socket.recv(rlen - len(buf)) + return buf + + def __str__(self): + d = '' + if self.deaduntil: + d = " (dead until %d)" % self.deaduntil + return "%s:%d%s" % (self.ip, self.port, d) + +def _doctest(): + import doctest, memcache + servers = ["127.0.0.1:11211"] + mc = Client(servers, debug=1) + globs = {"mc": mc} + return doctest.testmod(memcache, globs=globs) + +if __name__ == "__main__": + print "Testing docstrings..." + _doctest() + print "Running tests:" + print + #servers = ["127.0.0.1:11211", "127.0.0.1:11212"] + servers = ["127.0.0.1:11211"] + mc = Client(servers, debug=1) + + def to_s(val): + if not isinstance(val, types.StringTypes): + return "%s (%s)" % (val, type(val)) + return "%s" % val + def test_setget(key, val): + print "Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)), + mc.set(key, val) + newval = mc.get(key) + if newval == val: + print "OK" + return 1 + else: + print "FAIL" + return 0 + + class FooStruct: + def __init__(self): + self.bar = "baz" + def __str__(self): + return "A FooStruct" + def __eq__(self, other): + if isinstance(other, FooStruct): + return self.bar == other.bar + return 0 + + test_setget("a_string", "some random string") + test_setget("an_integer", 42) + if test_setget("long", long(1<<30)): + print "Testing delete ...", + if mc.delete("long"): + print "OK" + else: + print "FAIL" + print "Testing get_multi ...", + print mc.get_multi(["a_string", "an_integer"]) + + print "Testing get(unknown value) ...", + print to_s(mc.get("unknown_value")) + + f = FooStruct() + test_setget("foostruct", f) + + print "Testing incr ...", + x = mc.incr("an_integer", 1) + if x == 43: + print "OK" + else: + print "FAIL" + + print "Testing decr ...", + x = mc.decr("an_integer", 1) + if x == 42: + print "OK" + else: + print "FAIL" + + + +# vim: ts=4 sw=4 et : diff --git a/wcmtools/memcached/api/python/setup.py b/wcmtools/memcached/api/python/setup.py new file mode 100755 index 0000000..57fd343 --- /dev/null +++ b/wcmtools/memcached/api/python/setup.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +from distutils.core import setup +import memcache + +setup(name="python-memcached", + version=memcache.__version__, + author="Evan Martin", + author_email="martine@danga.com", + url="http://www.danga.com/memcached/", + py_modules=["memcache"]) + diff --git a/wcmtools/memcached/api/python/tests/pooltest.py b/wcmtools/memcached/api/python/tests/pooltest.py new file mode 100755 index 0000000..80a3d94 --- /dev/null +++ b/wcmtools/memcached/api/python/tests/pooltest.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +"""pooltest + +Bring up two memcaches on :11211 and :11212. Try killing one or both. +If this code raises any exceptions, it's a bug.""" + +import sys +sys.path.append("..") +import memcache +import time + +mc = memcache.Client(["127.0.0.1:11211", "127.0.0.1:11212"], debug=1) + +def test_setget(key, val): + print "Testing set/get {'%s': %s} ..." % (key, val), + mc.set(key, val) + newval = mc.get(key) + if newval == val: + print "OK" + else: + print "FAIL" + +i = 0 +while 1: + test_setget("foo%d" % i, "bar%d" % i) + time.sleep(1) + i += 1 diff --git a/wcmtools/memcached/assoc.c b/wcmtools/memcached/assoc.c new file mode 100755 index 0000000..43e3733 --- /dev/null +++ b/wcmtools/memcached/assoc.c @@ -0,0 +1,186 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Hash table + * + * The hash function used here is by Bob Jenkins, 1996: + * + * "By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. + * You may use this code any way you wish, private, educational, + * or commercial. It's free." + * + * The rest of the file is licensed under the BSD license. See LICENSE. + * + * $Id: assoc.c,v 1.6 2003/08/11 05:44:26 bradfitz Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "memcached.h" + +typedef unsigned long int ub4; /* unsigned 4-byte quantities */ +typedef unsigned char ub1; /* unsigned 1-byte quantities */ + +/* hard-code one million buckets, for now (2**20 == 4MB hash) */ +#define HASHPOWER 20 + +#define hashsize(n) ((ub4)1<<(n)) +#define hashmask(n) (hashsize(n)-1) + +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* +-------------------------------------------------------------------- +hash() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Every 1-bit and 2-bit delta achieves avalanche. +About 6*len+35 instructions. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i= 12) + { + a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24)); + b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24)); + c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24)); + mix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 11: c+=((ub4)k[10]<<24); + case 10: c+=((ub4)k[9]<<16); + case 9 : c+=((ub4)k[8]<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((ub4)k[7]<<24); + case 7 : b+=((ub4)k[6]<<16); + case 6 : b+=((ub4)k[5]<<8); + case 5 : b+=k[4]; + case 4 : a+=((ub4)k[3]<<24); + case 3 : a+=((ub4)k[2]<<16); + case 2 : a+=((ub4)k[1]<<8); + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + mix(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} + +static item** hashtable = 0; + +void assoc_init(void) { + unsigned int hash_size = hashsize(HASHPOWER) * sizeof(void*); + hashtable = malloc(hash_size); + if (! hashtable) { + fprintf(stderr, "Failed to init hashtable.\n"); + exit(1); + } + memset(hashtable, 0, hash_size); +} + +item *assoc_find(char *key) { + ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER); + item *it = hashtable[hv]; + + while (it) { + if (strcmp(key, ITEM_key(it)) == 0) + return it; + it = it->h_next; + } + return 0; +} + +/* returns the address of the item pointer before the key. if *item == 0, + the item wasn't found */ + +static item** _hashitem_before (char *key) { + ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER); + item **pos = &hashtable[hv]; + + while (*pos && strcmp(key, ITEM_key(*pos))) { + pos = &(*pos)->h_next; + } + return pos; +} + +/* Note: this isn't an assoc_update. The key must not already exist to call this */ +int assoc_insert(char *key, item *it) { + ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER); + it->h_next = hashtable[hv]; + hashtable[hv] = it; + return 1; +} + +void assoc_delete(char *key) { + item **before = _hashitem_before(key); + if (*before) { + item *nxt = (*before)->h_next; + (*before)->h_next = 0; /* probably pointless, but whatever. */ + *before = nxt; + return; + } + /* Note: we never actually get here. the callers don't delete things + they can't find. */ + assert(*before != 0); +} + diff --git a/wcmtools/memcached/autogen.sh b/wcmtools/memcached/autogen.sh new file mode 100755 index 0000000..56b8e82 --- /dev/null +++ b/wcmtools/memcached/autogen.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# This is hacky, because there are so many damn versions +# of autoconf/automake. It works with Debian woody, at least. +# + +echo "aclocal..." +ACLOCAL=${ACLOCAL:-aclocal-1.7} +$ACLOCAL || aclocal-1.5 || aclocal || exit 1 + +echo "autoheader..." +AUTOHEADER=${AUTOHEADER:-autoheader} +$AUTOHEADER || exit 1 + +echo "automake..." +AUTOMAKE=${AUTOMAKE:-automake-1.7} +$AUTOMAKE --foreign --add-missing || automake --gnu --add-missing || exit 1 + +echo "autoconf..." +AUTOCONF=${AUTOCONF:-autoconf} +$AUTOCONF || exit 1 + diff --git a/wcmtools/memcached/configure.ac b/wcmtools/memcached/configure.ac new file mode 100755 index 0000000..d4d3206 --- /dev/null +++ b/wcmtools/memcached/configure.ac @@ -0,0 +1,56 @@ +AC_PREREQ(2.52) +AC_INIT(memcached, 1.1.11, brad@danga.com) +AC_CANONICAL_SYSTEM +AC_CONFIG_SRCDIR(memcached.c) +AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) +AM_CONFIG_HEADER(config.h) + +AC_PROG_CC +AC_PROG_INSTALL + +AC_ARG_WITH(libevent, + AC_HELP_STRING([--with-libevent=DIRECTORY],[base directory for libevent])) +if test "$with_libevent" != "no"; then + CFLAGS="$CFLAGS -I$with_libevent/include" + LDFLAGS="$LDFLAGS -L$with_libevent/lib" +fi + +LIBEVENT_URL=http://www.monkey.org/~provos/libevent/ +AC_CHECK_LIB(event, event_set, , + [AC_MSG_ERROR(libevent is required. You can get it from $LIBEVENT_URL)]) + +AC_CHECK_HEADER(malloc.h, AC_DEFINE(HAVE_MALLOC_H,,[do we have malloc.h?])) +AC_CHECK_MEMBER([struct mallinfo.arena], [ + AC_DEFINE(HAVE_STRUCT_MALLINFO,,[do we have stuct mallinfo?]) + ], ,[ +# include + ] +) + +dnl From licq: Copyright (c) 2000 Dirk Mueller +dnl Check if the type socklen_t is defined anywhere +AC_DEFUN(AC_C_SOCKLEN_T, +[AC_CACHE_CHECK(for socklen_t, ac_cv_c_socklen_t, +[ + AC_TRY_COMPILE([ + #include + #include + ],[ + socklen_t foo; + ],[ + ac_cv_c_socklen_t=yes + ],[ + ac_cv_c_socklen_t=no + ]) +]) +if test $ac_cv_c_socklen_t = no; then + AC_DEFINE(socklen_t, int, [define to int if socklen_t not available]) +fi +]) + +AC_C_SOCKLEN_T + +AC_CHECK_FUNCS(mlockall) + +AC_CONFIG_FILES(Makefile doc/Makefile) +AC_OUTPUT diff --git a/wcmtools/memcached/doc/Makefile.am b/wcmtools/memcached/doc/Makefile.am new file mode 100755 index 0000000..80cb280 --- /dev/null +++ b/wcmtools/memcached/doc/Makefile.am @@ -0,0 +1,3 @@ +man_MANS = memcached.1 + +EXTRA_DIST = *.txt diff --git a/wcmtools/memcached/doc/memcached.1 b/wcmtools/memcached/doc/memcached.1 new file mode 100755 index 0000000..2c3b713 --- /dev/null +++ b/wcmtools/memcached/doc/memcached.1 @@ -0,0 +1,86 @@ +.TH MEMCACHED 1 "April 11, 2005" +.SH NAME +memcached \- high-performance memory object caching system +.SH SYNOPSIS +.B memcached +.RI [ options ] +.br +.SH DESCRIPTION +This manual page documents briefly the +.B memcached +memory object caching daemon. +.PP +.B memcached +is a flexible memory object caching daemon designed to alleviate database load +in dynamic web applications by storing objects in memory. It's based on +libevent to scale to any size needed, and is specifically optimized to avoid +swapping and always use non-blocking I/O. +.br +.SH OPTIONS +These programs follow the usual GNU command line syntax. A summary of options +is included below. +.TP +.B \-l +Listen on ; default to INDRR_ANY. This is an important option to +consider as there is no other way to secure the installation. Binding to an +internal or firewalled network interface is suggested. +.TP +.B \-d +Run memcached as a daemon. +.TP +.B \-u +Assume the identity of (only when run as root). +.TP +.B \-m +Use MB memory max to use for object storage; the default is 64 megabytes. +.TP +.B \-c +Use max simultaneous connections; the default is 1024. +.TP +.B \-k +Lock down all paged memory. This is a somewhat dangerous option with large +caches, so consult the README and memcached homepage for configuration +suggestions. +.TP +.B \-p +Listen on port , the default is port 11211. +.TP +.B \-M +Disable automatic removal of items from the cache when out of memory. +Additions will not be possible until adequate space is freed up. +.TP +.B \-r +Raise the core file size limit to the maximum allowable. +.TP +.B \-h +Show the version of memcached and a summary of options. +.TP +.B \-v +Be verbose during the event loop; print out errors and warnings. +.TP +.B \-vv +Be even more verbose; same as \-v but also print client commands and +responses. +.TP +.B \-i +Print memcached and libevent licenses. +.TP +.B \-P +Print pidfile to , only used under -d option. +.br +.SH LICENSE +The memcached daemon is copyright Danga Interactive and is distributed under +the BSD license. Note that daemon clients are licensed separately. +.br +.SH SEE ALSO +The README file that comes with memcached +.br +.B http://www.danga.com/memcached +.SH AUTHOR +The memcached daemon was written by Anatoly Vorobey +.B +and Brad Fitzpatrick +.B +and the rest of the crew of Danga Interactive +.B http://www.danga.com +.br diff --git a/wcmtools/memcached/doc/memory_management.txt b/wcmtools/memcached/doc/memory_management.txt new file mode 100755 index 0000000..efb743c --- /dev/null +++ b/wcmtools/memcached/doc/memory_management.txt @@ -0,0 +1,83 @@ +Date: Fri, 5 Sep 2003 20:31:03 +0300 +From: Anatoly Vorobey +To: memcached@lists.danga.com +Subject: Re: Memory Management... + +On Fri, Sep 05, 2003 at 12:07:48PM -0400, Kyle R. Burton wrote: +> prefixing keys with a container identifier). We have just begun to +> look at the implementation of the memory management sub-system with +> regards to it's allocation, de-allocation and compaction approaches. +> Is there any documentation or discussion of how this subsystem +> operates? (slabs.c?) + +There's no documentation yet, and it's worth mentioning that this +subsystem is the most active area of memcached under development at the +moment (however, all the changes to it won't modify the way memcached +presents itself towards clients, they're primarily directed at making +memcached use memory more efficiently). + +Here's a quick recap of what it does now and what is being worked +on. + +The primary goal of the slabs subsystem in memcached was to eliminate +memory fragmentation issues totally by using fixed-size memory chunks +coming from a few predetermined size classes (early versions of +memcached relied on malloc()'s handling of fragmentation which proved +woefully inadequate for our purposes). For instance, suppose +we decide at the outset that the list of possible sizes is: 64 bytes, +128 bytes, 256 bytes, etc. - doubling all the way up to 1Mb. For each +size class in this list (each possible size) we maintain a list of free +chunks of this size. Whenever a request comes for a particular size, +it is rounded up to the closest size class and a free chunk is taken +from that size class. In the above example, if you request from the +slabs subsystem 100 bytes of memory, you'll actually get a chunk 128 +bytes worth, from the 128-bytes size class. If there are no free chunks +of the needed size at the moment, there are two ways to get one: 1) free +an existing chunk in the same size class, using LRU queues to free the +least needed objects; 2) get more memory from the system, which we +currently always do in _slabs_ of 1Mb each; we malloc() a slab, divide +it to chunks of the needed size, and use them. + +The tradeoff is between memory fragmentation and memory utilisation. In +the scheme we're now using, we have zero fragmentation, but a relatively +high percentage of memory is wasted. The most efficient way to reduce +the waste is to use a list of size classes that closely matches (if +that's at all possible) common sizes of objects that the clients +of this particular installation of memcached are likely to store. +For example, if your installation is going to store hundreds of thousands of objects of the size exactly 120 bytes, you'd be much better +off changing, in the "naive" list of sizes outlined above, the class +of 128 bytes to something a bit higher (because the overhead of +storing an item, while not large, will push those 120-bytes objects over +128 bytes of storage internally, and will require using 256 bytes for +each of them in the naive scheme, forcing you to waste almost 50% of +memory). Such tinkering with the list of size classes is not currently +possible with memcached, but enabling it is one of the immediate goals. + +Ideally, the slabs subsystem would analyze at runtime the common sizes +of objects that are being requested, and would be able to modify the +list of sizes dynamically to improve memory utilisation. This is not +planned for the immediate future, however. What is planned is the +ability to reassign slabs to different classes. Here's what this means. +Currently, the total amount of memory allocated for each size class is +determined by how clients interact with memcached during the initial +phase of its execution, when it keeps malloc()'ing more slabs and +dividing them into chunks, until it hits the specified memory limit +(say, 2Gb, or whatever else was specified). Once it hits the limit, to +allocate a new chunk it'll always delete an existing chunk of the same +size (using LRU queues), and will never malloc() or free() any memory +from/to the system. So if, for example, during those initial few hours +of memcached's execution your clients mainly wanted to store very small +items, the bulk of memory allocated will be divided to small-sized +chunks, and the large size classes will get fewer memory, therefore the +life-cycle of large objects you'll store in memcached will henceforth +always be much shorter, with this instance of memcached (their LRU +queues will be shorter and they'll be pushed out much more often). In +general, if your system starts producing a different pattern of common +object sizes, the memcached servers will become less efficient, unless +you restart them. Slabs reassignment, which is the next feature being +worked on, will ensure the server's ability to reclaim a slab (1Mb of +memory) from one size class and put it into another class size, where +it's needed more. + +-- +avva diff --git a/wcmtools/memcached/doc/protocol.txt b/wcmtools/memcached/doc/protocol.txt new file mode 100755 index 0000000..00ae7a6 --- /dev/null +++ b/wcmtools/memcached/doc/protocol.txt @@ -0,0 +1,389 @@ +Protocol +-------- + +Clients of memcached communicate with server through TCP +connections. A given running memcached server listens on some +(configurable) port; clients connect to that port, send commands to +the server, read responses, and eventually close the connection. + +There is no need to send any command to end the session. A client may +just close the connection at any moment it no longer needs it. Note, +however, that clients are encouraged to cache their connections rather +than reopen them every time they need to store or retrieve data. This +is because memcached is especially designed to work very efficiently +with a very large number (many hundreds, more than a thousand if +necessary) of open connections. Caching connections will eliminate the +overhead associated with establishing a TCP connection (the overhead +of preparing for a new connection on the server side is insignificant +compared to this). + +There are two kinds of data sent in the memcache protocol: text lines +and unstructured data. Text lines are used for commands from clients +and responses from servers. Unstructured data is sent when a client +wants to store or retrieve data. The server will transmit back +unstructured data in exactly the same way it received it, as a byte +stream. The server doesn't care about byte order issues in +unstructured data and isn't aware of them. There are no limitations on +characters that may appear in unstructured data; however, the reader +of such data (either a client or a server) will always know, from a +preceding text line, the exact length of the data block being +transmitted. + +Text lines are always terminated by \r\n. Unstructured data is _also_ +terminated by \r\n, even though \r, \n or any other 8-bit characters +may also appear inside the data. Therefore, when a client retrieves +data from a server, it must use the length of the data block (which it +will be provided with) to determine where the data block ends, and not +the fact that \r\n follows the end of the data block, even though it +does. + +Keys +---- + +Data stored by memcached is identified with the help of a key. A key +is a text string which should uniquely identify the data for clients +that are interested in storing and retrieving it. Currently the +length limit of a key is set at 250 characters (of course, normally +clients wouldn't need to use such long keys); the key must not include +control characters or whitespace. + +Commands +-------- + +There are three types of commands. + +Storage commands (there are three: "set", "add" and "replace") ask the +server to store some data identified by a key. The client sends a +command line, and then a data block; after that the client expects one +line of response, which will indicate success or faulure. + +Retrieval commands (there is only one: "get") ask the server to +retrieve data corresponding to a set of keys (one or more keys in one +request). The client sends a command line, which includes all the +requested keys; after that for each item the server finds it sends to +the client one response line with information about the item, and one +data block with the item's data; this continues until the server +finished with the "END" response line. + +All other commands don't involve unstructured data. In all of them, +the client sends one command line, and expects (depending on the +command) either one line of response, or several lines of response +ending with "END" on the last line. + +A command line always starts with the name of the command, followed by +parameters (if any) delimited by whitespace. Command names are +lower-case and are case-sensitive. + +Expiration times +---------------- + +Some commands involve a client sending some kind of expiration time +(relative to an item or to an operation requested by the client) to +the server. In all such cases, the actual value sent may either be +Unix time (number of seconds since January 1, 1970, as a 32-bit +value), or a number of seconds starting from current time. In the +latter case, this number of seconds may not exceed 60*60*24*30 (number +of seconds in 30 days); if the number sent by a client is larger than +that, the server will consider it to be real Unix time value rather +than an offset from current time. + + +Error strings +------------- + +Each command sent by a client may be answered with an error string +from the server. These error strings come in three types: + +- "ERROR\r\n" + + means the client sent a nonexistent command name. + +- "CLIENT_ERROR \r\n" + + means some sort of client error in the input line, i.e. the input + doesn't conform to the protocol in some way. is a + human-readable error string. + +- "SERVER_ERROR \r\n" + + means some sort of server error prevents the server from carrying + out the command. is a human-readable error string. In cases + of severe server errors, which make it impossible to continue + serving the client (this shouldn't normally happen), the server will + close the connection after sending the error line. This is the only + case in which the server closes a connection to a client. + + +In the descriptions of individual commands below, these error lines +are not again specifically mentioned, but clients must allow for their +possibility. + + +Storage commands +---------------- + +First, the client sends a command line which looks like this: + + \r\n + +- is "set", "add" or "replace" + + "set" means "store this data". + + "add" means "store this data, but only if the server *doesn't* already + hold data for this key". + + "replace" means "store this data, but only if the server *does* + already hold data for this key". + +- is the key under which the client asks to store the data + +- is an arbitrary 16-bit unsigned integer (written out in + decimal) that the server stores along with the data and sends back + when the item is retrieved. Clients may use this as a bit field to + store data-specific information; this field is opaque to the server. + +- is expiration time. If it's 0, the item never expires + (although it may be deleted from the cache to make place for other + items). If it's non-zero (either Unix time or offset in seconds from + current time), it is guaranteed that clients will not be able to + retrieve this item after the expiration time arrives (measured by + server time). + +- is the number of bytes in the data block to follow, *not* + including the delimiting \r\n. may be zero (in which case + it's followed by an empty data block). + +After this line, the client sends the data block: + +\r\n + +- is a chunk of arbitrary 8-bit data of length + from the previous line. + +After sending the command line and the data blockm the client awaits +the reply, which may be: + +- "STORED\r\n", to indicate success. + +- "NOT_STORED\r\n" to indicate the data was not stored, but not +because of an error. This normally means that either that the +condition for an "add" or a "replace" command wasn't met, or that the +item is in a delete queue (see the "delete" command below). + + +Retrieval command: +------------------ + +The retrieval command looks like this: + +get *\r\n + +- * means one or more key strings separated by whitespace. + +After this command, the client expects zero or more items, each of +which is received as a text line followed by a data block. After all +the items have been transmitted, the server sends the string + +"END\r\n" + +to indicate the end of response. + +Each item sent by the server looks like this: + +VALUE \r\n +\r\n + +- is the key for the item being sent + +- is the flags value set by the storage command + +- is the length of the data block to follow, *not* including + its delimiting \r\n + +- is the data for this item. + +If some of the keys appearing in a retrieval request are not sent back +by the server in the item list this means that the server does not +hold items with such keys (because they were never stored, or stored +but deleted to make space for more items, or expired, or explicitly +deleted by a client). + + + +Deletion +-------- + +The command "delete" allows for explicit deletion of items: + +delete

  • >> %%yyyy%% + +CALENDAR_YEAR_LINK=>
    %%yyyy%% + +CALENDAR_DAY=>
    %%d%%
    %%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>%%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + + + +%%head%% +%%title%% + + + + + + + +
    + +%%months%% + + + + + + + + + + + + + + + +
     
     
     
    + + + + + + + + + + + + +
     
     
     
    + +
    + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= + + + + + + + + + + + + + + + + + + + + + + +
    %%monlong%% %%yyyy%%%%altposter%% 
     
      + + + + + + + + + + +%%weeks%% +
    SunMonTueWedThuFriSat
    +

     
      View Subjects
     
    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=>
    %%name%% + +CALENDAR_NEW_YEAR=> + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=> + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + + +<=CALENDAR_WEEK + + +. + +Style: calendar/Generator +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:52:06 + +CALENDAR_YEAR_DISPLAYED=>%%yyyy%%  + +CALENDAR_YEAR_LINK=>%%yyyy%%  + +CALENDAR_DAY<= +
    %%d%%
    +%%dayevent%% +%%daynoevent%% + + +<=CALENDAR_DAY + +CALENDAR_DAY_NOEVENT=>  + +CALENDAR_YEAR_LINKS<= + + + + +
    + + + + + + + +
    Years
    +%%years%% + +
    +
    + +<=CALENDAR_YEAR_LINKS + +CALENDAR_EMPTY_DAYS=> + +CALENDAR_PAGE<= + + + +%%head%% +%%title%% -- Calendar + + +
    + + +
    + + + + +
    %%title%% -- Calendar[entries|friends|calendar]
    + + + +
    + + +%%userpic%% + + +
    +
    %%name%%

    + +%%website%% + + + + + + + + + + + + + + +
    [userinfo|livejournal userinfo]
    [calendar|livejournal calendar]
    +

    +
    +
    +

    +%%yearlinks%% +

    +%%months%% + +

    + + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= + + + + +
    + + + + + + + + +
    %%monlong%% %%yyyy%%[subjects]
    + + + + + + + + + + + +%%weeks%% +
    SunMonTueWedThuFriSat
    +
    +

    + +<=CALENDAR_MONTH + +CALENDAR_WEBSITE<= + +[ +website +| +%%name%% +] + + +<=CALENDAR_WEBSITE + +CALENDAR_NEW_YEAR=> + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>

    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + + +<=CALENDAR_WEEK + + +. + +Style: calendar/Magazine +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:52:41 + +CALENDAR_YEAR_DISPLAYED=> (%%yyyy%%) + +CALENDAR_YEAR_LINK=> (%%yyyy%%) + +CALENDAR_DAY<= + %%d%%%%dayevent%%%%daynoevent%% + +<=CALENDAR_DAY + +CALENDAR_DAY_NOEVENT=>

    + +CALENDAR_YEAR_LINKS=>Navigate: %%years%% + +CALENDAR_EMPTY_DAYS<= + + +<=CALENDAR_EMPTY_DAYS + +CALENDAR_PAGE<= + + + + +%%head%% + %%title%% - Calendar + + +

    %%title%% - Calendar

    + +%%months%% + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= + + + + + + + + + + + +%%weeks%%
    %%monlong%% %%yyyy%%
    SunMonTueWedThuFriSat
    + +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=>(%%name%%) + +CALENDAR_NEW_YEAR<= +

    %%yyyy%%

    + +<=CALENDAR_NEW_YEAR + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=> + +CALENDAR_WEEK<= + +%%emptydays_beg%%%%days%%%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Notepad +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 21:55:24 + +CALENDAR_YEAR_DISPLAYED=> + +CALENDAR_YEAR_LINK=> %%yyyy%% + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>Skip to... %%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + + + %%head%% + %%title%% - Calendar + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
      Journal  Friends  Calendar  User Info  Memories
    +
    +   + +

    %%title%% - Calendar

    +

    +%%months%% +

    %%yearlinks%%

    +
    +   +
    + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +

    + + + + + + + + + + + +%%weeks%% + +
    %%monlong%%, %%yyyy%%
    SunMonTueWedThuFriSat
    View Subjects +
    +

    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=> + +CALENDAR_NEW_YEAR=>

    %%yyyy%%...

    + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>
    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Punquin Elegant w/ Sidebar +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:56:16 + +CALENDAR_YEAR_DISPLAYED=>> %%yyyy%%
    + +CALENDAR_YEAR_LINK=>> %%yyyy%%
    + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>%%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + +%%title%% - calendar + +%%head%% + + + +
    + + +
    + +
    + +
    +
    + +%%title%% - calendar + +
    +

    + +> %%numitems%% recent entries
    +> calendar
    +> friends
    +%%website%% +> profile
    +%%yearlinks%% +
    +

    +
    + +
    + +
    + +
    +%%months%% +
    +
    +
    + +
    + +
    + +
    + +> top of page
    +
    +
    +
    + +
    +%%cons:sitename%% +
    +
    + + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +

    + + + + + + + + + + + +%%weeks%% + +
    %%monlong%%, %%yyyy%% +
    SunMonTueWedThuFriSat
    view subjects +
    +

    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=>> %%name%%
    + +CALENDAR_NEW_YEAR=>

    %%yyyy%%

    + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>
    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Refried Paper +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 21:57:33 + +CALENDAR_YEAR_DISPLAYED=>%%yyyy%%
    + +CALENDAR_YEAR_LINK=>%%yyyy%%
    + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>%%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + +%%title%% - Archive + +%%head%% + + + + + + + + + + + + + + + + + + + + +
    %%title%% +
    Archive +
    + + + + + + + + + + + + + + + + + + + + + + +
    + +%%months%% + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    select year
    my journal
    + +
    + + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +

    + + + + + + + + + + + +%%weeks%% + +
    %%monlong%%, %%yyyy%% +
    SunMonTueWedThuFriSat
    view subjects +
    +

    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=>%%name%%
    + +CALENDAR_NEW_YEAR=> + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>
    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: calendar/Tabular Indent +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2004-12-06 18:04:07 + +CALENDAR_YEAR_DISPLAYED=> %%yyyy%% + +CALENDAR_YEAR_LINK=> %%yyyy%% + +CALENDAR_DAY=>%%d%%%%dayevent%%%%daynoevent%% + +CALENDAR_DAY_NOEVENT=>
     
    + +CALENDAR_YEAR_LINKS=>%%years%% + +CALENDAR_EMPTY_DAYS=>  + +CALENDAR_PAGE<= + + + + %%head%% + %%title%% - Calendar + + + + + + + +
    + %%userpic%% + + %%title%%
    + + + + +
    View:Personal Journal.
    View:Friends.
    %%yearlinks%%
    +
    +

    + %%months%% +

    +

    + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + %%website%%
    + + +
    View:User Info.
    View:Personal Journal.
    View:Friends.
    View:Memories.
    %%yearlinks%%
    +
    +

    + + +<=CALENDAR_PAGE + +CALENDAR_MONTH<= +
    + + + + + + + + + + + +%%weeks%% + +
    %%monlong%%, %%yyyy%%
    SunMonTueWedThuFriSat
    View Subjects +
    +
    +<=CALENDAR_MONTH + +CALENDAR_WEBSITE=>View:Website (%%name%%). + +CALENDAR_NEW_YEAR=> + +CALENDAR_SORT_MODE=> + +CALENDAR_DAY_EVENT=>
    %%eventcount%%
    + +CALENDAR_WEEK<= + +%%emptydays_beg%% +%%days%% +%%emptydays_end%% + +<=CALENDAR_WEEK + + +. + +Style: day/Clean and Simple +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 21:59:25 + +DAY_TALK_LINKS=> + +DAY_CURRENT<= +
    Current %%what%%: %%value%%
    + +<=DAY_CURRENT + +DAY_EVENT_PRIVATE<= +
    +
    + +%%datetime%%: [Private] %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=>
  • %%name%%
  • + +DAY_EVENT_PROTECTED<= +
    +
    + +%%datetime%%: [Protected] %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT<= + %%subject%%
    + +<=DAY_SUBJECT + +DAY_NOEVENTS=>

    There were no entries made on this day.

    + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% - + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%12h%%:%%min%%%%ampm%% + +DAY_EVENT<= +
    +
    +%%datetime%%: %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=DAY_EVENT + +DAY_CURRENTS<= +
    +%%currents%% +
    + +<=DAY_CURRENTS + +DAY_PAGE<= + + + +%%head%% +%%title%% -- Entries on %%dth%% %%monlong%% %%yyyy%% + + + + + + + + +
    +

    %%title%%

    +

    History

    +
    +
    +
    %%range%%
    + +
    +

    %%dth%% %%monlong%% %%yyyy%%

    +%%events%% + +
    + +
    + +
    Powered by %%cons:sitename%%
    + +
    + + + + +<=DAY_PAGE + + +. + +Style: day/Default Day View +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:01:26 + +DAY_TALK_LINKS<= +
    + (%%readlink%%Comment on this)
    +<=DAY_TALK_LINKS + +DAY_CURRENT=>
    Current %%what%%: %%value%% + +DAY_EVENT_PRIVATE<= +%%datetime%%
    +Private +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE<= + + %%name%% + +  +<=DAY_WEBSITE + +DAY_EVENT_PROTECTED<= +%%datetime%%
    +Protected +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=>%%subject%%
    + +DAY_NOEVENTS=>(no journal entries for this day) + +DAY_EVENTS<= + + + + + +%%events%% +
    TimeEvent
    +<=DAY_EVENTS + +DAY_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% | + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%12h%%:%%min%%%%ap%% + +DAY_EVENT<= +%%datetime%% +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=DAY_EVENT + +DAY_CURRENTS=>
    %%currents%% + +DAY_PAGE<= + + + %%title%% +%%head%% + + + + + +
    + +%%title%%
     
    + +[Most Recent Entries] +[Calendar View] +[Friends View] + + +

    %%daylong%%, %%monlong%% %%dth%%, %%yyyy%% +

    + +
    + + + +%%website%% + +
    About %%cons:sitename%%
    + + + +<=DAY_PAGE + + +. + +Style: day/Disjointed +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:02:12 + +DAY_TALK_LINKS=>%%readlink%%Post + +DAY_CURRENT=>
    %%lc:what%%: %%value%%
    + +DAY_EVENT_PRIVATE<= + + + + + + + + + + + + + + + + + + + + + +
    %%subject%%  
    %%datetime%%
      + %%currents%% + %%event%% 
      %%talklinks%%
     
    +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=>
    %%name%% + +DAY_EVENT_PROTECTED<= + + + + + + + + + + + + + + + + + + + + + +
    %%subject%%  
    %%datetime%%
      + %%currents%% + %%event%% 
      %%talklinks%%
     
    +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=>%%subject%% + +DAY_NOEVENTS<= + + + + + + + + + + + + + + + + + + + + + +
    No Events 
     
      + There are no events on this day 
       
     
    +<=DAY_NOEVENTS + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>Read %%messagecount%% -  + +DAY_SORT_MODE=> + +DAY_DATE_FORMAT=>%%12hh%%:%%min%%%%ampm%% %%dd%%/%%mm%%/%%yyyy%% + +DAY_EVENT<= + + + + + + + + + + + + + + + + + + + + + +
    %%subject%%  
    %%datetime%%
      + %%currents%% + %%event%% 
      %%talklinks%%
     
    +<=DAY_EVENT + +DAY_CURRENTS<= + +
    +%%currents%% +
    +<=DAY_CURRENTS + +DAY_PAGE<= + + + + +%%head%% +%%title%% - %%dth%% %%monlong%% '%%yy%% + + + + + + + +
    + +%%events%% + + + + + + + + + + + + + + +
     
     
     
    + + + + + + + + + + + + +
     
     
     
    + +
    + + +<=DAY_PAGE + + +. + +Style: day/Generator +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:02:47 + +DAY_TALK_LINKS<= + + +%%readlink%%post comment + + +<=DAY_TALK_LINKS + +DAY_CURRENT<= + +[ +%%lc:what%% +| +%%value%% +] + + +<=DAY_CURRENT + +DAY_EVENT_PRIVATE<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%currents%% +%%event%% +
    +

    + +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE<= + +[ +website +| +%%name%% +] + + +<=DAY_WEBSITE + +DAY_EVENT_PROTECTED<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%currents%% +%%event%% +
    +

    + +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=>%%subject%% + +DAY_NOEVENTS=> + +DAY_EVENTS<= +%%events%% + +<=DAY_EVENTS + +DAY_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%%| + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%dd%% %%monshort%% %%yyyy%%|%%12hh%%:%%min%%%%ampm%% + +DAY_EVENT<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%currents%% +%%event%% +
    +

    + +<=DAY_EVENT + +DAY_CURRENTS<= + +%%currents%% +

    +<=DAY_CURRENTS + +DAY_PAGE<= + + + +%%head%% +%%title%% -- Day + + +

    + + +
    + + + + +
    %%title%% -- Day[entries|friends|calendar]
    + + + +
    + + +%%userpic%% + + +
    +
    %%name%%

    + +%%website%% + + + + + + + + + + + + + + +
    [userinfo|livejournal userinfo]
    [calendar|livejournal calendar]
    +

    +
    +
    +

    +%%events%% + + + +
    + + + + + + + +
    navigation
    + + + + + + + + + + + + + + + + +
    [viewing|%%monlong%% %%dth%%, %%yyyy%%]
    [go|previous day|next day]
    +
    +
    + + + +<=DAY_PAGE + + +. + +Style: day/Magazine +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:03:36 + +DAY_TALK_LINKS=>

    (%%readlink%%comment on this)
    + +DAY_CURRENT=>
    Current %%lc:what%%: %%value%%
    + +DAY_EVENT_PRIVATE<= +
    +

    %%datetime%%%%subject%% Private

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=>(%%name%%) + +DAY_EVENT_PROTECTED<= +
    +

    %%datetime%%%%subject%% Protected

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=> - %%subject%% + +DAY_NOEVENTS=>

    (No journal entries for this day)

    + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%12h%%:%%min%%%%AMPM%% + +DAY_EVENT<= +
    +

    %%datetime%%%%subject%%

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=DAY_EVENT + +DAY_CURRENTS=>
    %%currents%%
    + +DAY_PAGE<= + + + + +%%head%% + %%title%% - %%monlong%% %%d%%, %%yyyy%% + + +

    %%title%% - Day

    + + +

    %%daylong%%, %%monlong%% %%d%%, %%yyyy%%

    +%%events%% + + + + + + +
    Previous day(Calendar)Next day
    + + +<=DAY_PAGE + + +. + +Style: day/Notepad +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:04:36 + +DAY_TALK_LINKS=>

    %%readlink%%Make Notes

    + +DAY_CURRENT=>
    Current %%lc:what%%: %%value%%. + +DAY_EVENT_PRIVATE<= +Private %%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=> + +DAY_EVENT_PROTECTED<= +Protected %%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=> %%subject%% + +DAY_NOEVENTS=>No journal entries for this day. + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>Read %%messagecount%% Note%%mc-plural-s%% - + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%dth%% %%monlong%%, %%yyyy%%. %%12h%%:%%min%% %%ampm%%. + +DAY_EVENT<= +%%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=DAY_EVENT + +DAY_CURRENTS=>
    %%currents%% + +DAY_PAGE<= + + + + %%head%% + %%title%% + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
      Journal  Friends  Calendar  User Info  Memories
    +
    +   + +

    %%title%%

    +

    +%%events%% +

    Back A Day - Forward A Day

    +
    +   +
    + + +<=DAY_PAGE + + +. + +Style: day/Punquin Elegant w/ Sidebar +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:05:28 + +DAY_TALK_LINKS=>

    (%%readlink%%comment on this)

    + +DAY_CURRENT=>
    current %%lc:what%%: %%value%% + +DAY_EVENT_PRIVATE<= + + +%%datetime%%%%subject%%  Private +
    + +%%event%% + +%%currents%% %%talklinks%% +

    + + +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=>> %%name%%
    + +DAY_EVENT_PROTECTED<= + + +%%datetime%%%%subject%%  Protected +
    + +%%event%% + +%%currents%% %%talklinks%% +

    + + +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=> - %%subject%% + +DAY_NOEVENTS=>


    (no journal entries for this day)



    + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% | + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%12h%%:%%min%%%%ap%% + +DAY_EVENT<= + + +%%datetime%%%%subject%% + +
    + +%%event%% + +%%currents%% %%talklinks%% +

    + + +<=DAY_EVENT + +DAY_CURRENTS=>
    %%currents%% + +DAY_PAGE<= + + +%%title%% +%%head%% + + + + +

    + + +
    + +
    + +
    +
    + +%%title%% + +
    +

    + +> %%numitems%% recent entries
    +> calendar
    +> friends
    +%%website%% +> profile
    +%%skiplinks%% +
    +

    +
    + +
    + +
    + +
    + + +%%events%% +
    %%daylong%%, %%monlong%% %%dth%%, %%yyyy%%
    +
    + + + + + + +
    +<< previous day + +[calendar] + +next day >> + +
    +
    +
    +
    + +
    + +
    + +
    + +> top of page
    +
    +
    +
    + +
    +%%cons:sitename%% +
    +
    + + + +<=DAY_PAGE + + +. + +Style: day/Refried Paper +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:06:15 + +DAY_TALK_LINKS=>%%readlink%%post a comment + +DAY_CURRENT=>%%what%%:%%value%% + +DAY_EVENT_PRIVATE<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Private
    +

    %%event%%

    +%%talklinks%% +


    +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE<= +
    + %%name%% +<=DAY_WEBSITE + +DAY_EVENT_PROTECTED<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Protected
    +

    %%event%%

    +%%talklinks%% +


    +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=>%%subject%% + +DAY_NOEVENTS=>



    (no journal entries for this day)



    + +DAY_EVENTS<= +%%events%% + +<=DAY_EVENTS + +DAY_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%yyyy%%-%%mm%%-%%dd%% %%24hh%%:%%min%% + +DAY_EVENT<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Public
    +

    %%event%%

    +%%talklinks%% +


    +<=DAY_EVENT + +DAY_CURRENTS=>%%currents%% + +DAY_PAGE<= + + +%%head%% +%%title%% - %%monlong%% %%dth%% %%yyyy%% + + + + + + + + + + + + + + + + + + + + + + +
    %%title%%
    %%daylong%%, %%monlong%% %%dth%%, %%yyyy%% +
    + + + + + + + + + + + + + + + + + + + + +
    + + +%%events%% + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    browse days
    my journal
    + +
    + + + +<=DAY_PAGE + + +. + +Style: day/Tabular Indent +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2004-12-06 18:04:07 + +DAY_TALK_LINKS<= + + + + +Comments: %%readlink%%Add Your Own. + + + + +<=DAY_TALK_LINKS + +DAY_CURRENT=>%%what%%:%%value%%. + +DAY_EVENT_PRIVATE<= +
    + + + + + + + +%%talklinks%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=DAY_EVENT_PRIVATE + +DAY_WEBSITE=>View:Website (%%name%%). + +DAY_EVENT_PROTECTED<= +
    + + + + + + + +%%talklinks%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=DAY_EVENT_PROTECTED + +DAY_SUBJECT=>Subject:%%subject%% + +DAY_NOEVENTS=>No journal entries for this day. + +DAY_EVENTS=>%%events%% + +DAY_TALK_READLINK=>Read %%messagecount%% or + +DAY_SORT_MODE=>forward + +DAY_DATE_FORMAT=>%%12h%%:%%min%% %%ampm%%. + +DAY_EVENT<= +
    + + + + + + + +%%talklinks%% +
    + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=DAY_EVENT + +DAY_CURRENTS=>%%currents%% + +DAY_PAGE<= + + + + %%head%% + %%title%% + + + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + +
    View:Personal Journal.
    View:Friends.
    View:Calendar.
    Missed some entries? Then simply jump to the previous day or the next day.
    +
    +

    + + + + +
    + +%%daylong%%, %%monlong%% %%dth%%, %%yyyy%% + +
    +
    + %%events%% +

    +

    + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + %%website%%
    + + +
    View:User Info.
    View:Friends.
    View:Calendar.
    View:Memories.
    Missed some entries? Then simply jump to the previous day or the next day.
    +
    +

    + + +<=DAY_PAGE + + +. + +Style: friends/Clean and Simple +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:15:03 + +FRIENDS_RANGE_HISTORY=>You are viewing %%numitems%% entries, %%skip%% into the past. + +FRIENDS_ALTPOSTER=>%%poster%%, posting in + +FRIENDS_EVENT_PROTECTED<= +
    +
    + +%%altposter%% +%%user%% @ %%datetime%%: [Protected] %%subject%% +%%friendpic%%%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>You are viewing the most recent %%numitems%% entries. + +FRIENDS_EVENT_PRIVATE<= +
    +
    + +%%altposter%% +%%user%% @ %%datetime%%: [Private] %%subject%% +%%friendpic%%%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>25 + +FRIENDS_PAGE<= + + + +%%head%% +%%title%% + + + + + + + + +
    +

    %%name%%

    +

    Friends' Entries

    +
    +
    +
    %%range%%
    + +%%events%% + +
    + +
    Powered by %%cons:sitename%%
    + +
    + + + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY<= +
    + +<=FRIENDS_END_DAY + +FRIENDS_NOFRIENDS<= +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friends' posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    + +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD<= +
  • Next %%numitems%% Entries
  • + +<=FRIENDS_SKIP_FORWARD + +FRIENDS_EVENT<= +
    +
    +%%altposter%% +%%user%% @ %%datetime%%: %%subject%% +%%friendpic%%%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> + +FRIENDS_CURRENT<= +
    Current %%what%%: %%value%%
    + +<=FRIENDS_CURRENT + +FRIENDS_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% - + +FRIENDS_SKIP_LINKS<= + +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS<= +%%events%% + +<=FRIENDS_EVENTS + +FRIENDS_NEW_DAY<= +
    +

    %%dth%% %%monlong%% %%yyyy%%

    + +<=FRIENDS_NEW_DAY + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>
  • Previous %%numitems%% Entries
  • + +FRIENDS_TALK_LINKS=> + +FRIENDS_CURRENTS<= +
    +%%currents%% +
    +<=FRIENDS_CURRENTS + +FRIENDS_DATE_FORMAT=>%%12h%%:%%min%%%%ampm%% + +FRIENDS_FRIENDPIC=> + +FRIENDS_WEBSITE=>
  • %%name%%
  • + +FRIENDS_SUBJECT=> %%subject%%
    + + +. + +Style: friends/Default Friends View +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:18:38 + +FRIENDS_RANGE_HISTORY=>Below are %%numitems%% friends' journal entries, after skipping by the %%skip%% most recent ones. + +FRIENDS_ALTPOSTER<= +
    +[ %%poster%% ] +<=FRIENDS_ALTPOSTER + +FRIENDS_EVENT_PROTECTED<= + + + %%user%%%%altposter%%%%friendpic%% + +%%datetime%%
    +Protected +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% + +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>Below are the most recent %%numitems%% friends' journal entries. + +FRIENDS_EVENT_PRIVATE<= + + + %%user%%%%altposter%%%%friendpic%% + +%%datetime%%
    +Private +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% + +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>25 + +FRIENDS_PAGE<= + + + %%title%% +%%head%% + + + + + + +
    + +%%title%%
     
    + +[Most Recent Entries] +[Calendar View] +[Friends View] + + +

    %%range%%

    + +
      +%%skiplinks%% +%%events%% +%%skiplinks%% +
    + +
    + + + +%%website%% + +
    About %%cons:sitename%%
    + + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>Next %%numitems%% >> + +FRIENDS_EVENT<= + + + %%user%%%%altposter%%%%friendpic%% + +%%datetime%% +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% + +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> --  + +FRIENDS_CURRENT=>
    Current %%what%%: %%value%% + +FRIENDS_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% | + +FRIENDS_SKIP_LINKS<= +
    [ %%skipbackward%%%%skipspacer%%%%skipforward%% ]
    + +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS<= + +%%events%% +
    +<=FRIENDS_EVENTS + +FRIENDS_NEW_DAY=>%%daylong%%, %%monlong%% %%dth%%, %%yyyy%% + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=><< Previous %%numitems%% + +FRIENDS_TALK_LINKS<= +
    + (%%readlink%%Comment on this)
    +<=FRIENDS_TALK_LINKS + +FRIENDS_CURRENTS=>
    %%currents%% + +FRIENDS_DATE_FORMAT=>%%12h%%:%%min%%%%ap%% + +FRIENDS_FRIENDPIC=>
    + +FRIENDS_WEBSITE<= + + %%name%% + +  +<=FRIENDS_WEBSITE + +FRIENDS_SUBJECT=>%%subject%%
    + + +. + +Style: friends/Disjointed +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:20:03 + +FRIENDS_RANGE_HISTORY=> + +FRIENDS_ALTPOSTER=> - (%%poster%%) + +FRIENDS_EVENT_PROTECTED<= + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% + + + + + +
     %%user%%%%altposter%%
    +
     
    %%datetime%%
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=> + +FRIENDS_EVENT_PRIVATE<= + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% + + + + + +
     %%user%%%%altposter%%
    +
     
    %%datetime%%
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>20 + +FRIENDS_PAGE<= + + + + +%%head%% +%%title%% + + + + + + + +
    + +%%events%% + + + + + + + + + + + + + + + +
     
     
     
    +%%skiplinks%% + +
    + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS=> + +FRIENDS_SKIP_FORWARD=>Forward + +FRIENDS_EVENT<= + + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% + + + + + +
     %%user%%%%altposter%%
    +
     
    %%datetime%% 
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=>
    + +FRIENDS_CURRENT=>
    %%lc:what%%: %%value%%
    + +FRIENDS_TALK_READLINK=>Read %%messagecount%% -  + +FRIENDS_SKIP_LINKS<= + + + + + + + + + + + + +
     
     
     
    +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY=> + +FRIENDS_NO_SUBJECT=>no subject + +FRIENDS_SKIP_BACKWARD=>Backward + +FRIENDS_TALK_LINKS=>%%readlink%%Post + +FRIENDS_CURRENTS<= + +
    +%%currents%% +
    +<=FRIENDS_CURRENTS + +FRIENDS_DATE_FORMAT=>%%12hh%%:%%min%%%%ampm%% %%dd%%/%%mm%%/%%yyyy%% + +FRIENDS_FRIENDPIC=> + +FRIENDS_WEBSITE=>
    %%name%% + +FRIENDS_SUBJECT=>%%subject%% + + +. + +Style: friends/Generator +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:20:36 + +FRIENDS_RANGE_HISTORY=>%%skip%% entries back + +FRIENDS_ALTPOSTER<= +
    [%%poster%%] + +<=FRIENDS_ALTPOSTER + +FRIENDS_EVENT_PROTECTED<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    + +
    + +
    + +%%friendpic%% +%%user%%%%altposter%% +
    +
    +%%currents%% +%%event%% +
    +

    + +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>most recent entries + +FRIENDS_EVENT_PRIVATE<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    + +
    + +
    + +%%friendpic%% +%%user%%%%altposter%% + +
    +
    +%%currents%% +%%event%% +
    +

    + +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=> + +FRIENDS_PAGE<= + + + +%%head%% +%%title%% + + +

    + + +
    + + + + +
    %%title%%[entries|friends|calendar]
    + + + +
    + + +%%userpic%% + + +
    +
    %%name%%

    + +%%website%% + + + + + + + + + + + + + + +
    [userinfo|livejournal userinfo]
    [calendar|livejournal calendar]
    +

    +
    +
    +

    +%%events%% + +
    + + + + + + + +
    navigation
    + + + + + + + + +%%skiplinks%% +
    [viewing|%%range%%]
    +
    +
    +

    +

    + + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= + + + + +
    + + + + + + + +
    Halted
    + +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    + +
    +

    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>later + +FRIENDS_EVENT<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    + +
    + +
    + +%%friendpic%% +%%user%%%%altposter%% +
    +
    +%%currents%% +%%event%% +
    +

    + +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=>/ + +FRIENDS_CURRENT<= + +[ +%%lc:what%% +| +%%value%% +] + + +<=FRIENDS_CURRENT + +FRIENDS_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%%| + +FRIENDS_SKIP_LINKS<= + +[ +go +| +%%skipbackward%%%%skipspacer%%%%skipforward%% +] + + +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS<= +%%events%% + +<=FRIENDS_EVENTS + +FRIENDS_NEW_DAY=> + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>earlier + +FRIENDS_TALK_LINKS<= + + +%%readlink%%post comment + + +<=FRIENDS_TALK_LINKS + +FRIENDS_CURRENTS<= + +%%currents%% +

    +<=FRIENDS_CURRENTS + +FRIENDS_DATE_FORMAT=>%%dd%% %%monshort%% %%yyyy%%|%%12hh%%:%%min%%%%ampm%% + +FRIENDS_FRIENDPIC=>
    + +FRIENDS_WEBSITE<= + +[ +website +| +%%name%% +] + + +<=FRIENDS_WEBSITE + +FRIENDS_SUBJECT=>%%subject%% + + +. + +Style: friends/Magazine +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:21:10 + +FRIENDS_RANGE_HISTORY=>(Latest friends - %%skip%%) + +FRIENDS_ALTPOSTER=>

    (%%poster%%) + +FRIENDS_EVENT_PROTECTED<= +
    +
    + +
    %%friendpic%%%%altposter%%
    +
    +

    %%datetime%%%%subject%% Protected

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>(Latest friends) + +FRIENDS_EVENT_PRIVATE<= +
    +
    + +
    %%friendpic%%%%altposter%%
    +
    +

    %%datetime%%%%subject%% Private

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>20 + +FRIENDS_PAGE<= + + + + +%%head%% + %%title%% + + +

    %%title%%

    + +%%events%% +

    %%skiplinks%%

    + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS=>%%name%% has no friends defined. %%name%% can add friends. + +FRIENDS_SKIP_FORWARD=>Next %%numitems%% friends + +FRIENDS_EVENT<= +
    +
    + +
    %%friendpic%%%%altposter%%
    +
    +

    %%datetime%%%%subject%%

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> |  + +FRIENDS_CURRENT=>
    Current %%lc:what%%: %%value%%
    + +FRIENDS_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +FRIENDS_SKIP_LINKS=>Navigate: (%%skipbackward%%%%skipspacer%%%%skipforward%%) + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY<= +

    %%daylong%%, %%monlong%% %%d%%, %%yyyy%%

    + +<=FRIENDS_NEW_DAY + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>Previous %%numitems%% friends + +FRIENDS_TALK_LINKS=>
    (%%readlink%%comment on this)
    + +FRIENDS_CURRENTS=>
    %%currents%%
    + +FRIENDS_DATE_FORMAT=>%%12h%%:%%min%%%%AMPM%% + +FRIENDS_FRIENDPIC=> + +FRIENDS_WEBSITE=>(%%name%%) + +FRIENDS_SUBJECT=> - %%subject%% + + +. + +Style: friends/Notepad +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:21:51 + +FRIENDS_RANGE_HISTORY=> + +FRIENDS_ALTPOSTER=>
    [ %%poster%% ] + +FRIENDS_EVENT_PROTECTED<= +
    %%friendpic%%%%user%%%%altposter%%
    Protected +%%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=> + +FRIENDS_EVENT_PRIVATE<= +
    %%friendpic%%%%user%%%%altposter%%
    Private +%%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>10 + +FRIENDS_PAGE<= + + + + %%head%% + %%title%% + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
      Journal  Friends  Calendar  User Info  Memories
    +
    +   + +

    %%title%%

    +

    +%%events%% +

    %%skiplinks%%

    +
    +   +
    + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>Forward A Page + +FRIENDS_EVENT<= +
    %%friendpic%%%%user%%%%altposter%%
    +%%datetime%%%%subject%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> - + +FRIENDS_CURRENT=>
    Current %%lc:what%%: %%value%%. + +FRIENDS_TALK_READLINK=>Read %%messagecount%% Note%%mc-plural-s%% - + +FRIENDS_SKIP_LINKS=>%%skipbackward%%%%skipspacer%%%%skipforward%% + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY=> + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>Back A Page + +FRIENDS_TALK_LINKS=>

    %%readlink%%Make Notes + +FRIENDS_CURRENTS=>
    %%currents%% + +FRIENDS_DATE_FORMAT=>%%dth%% %%monlong%%, %%yyyy%%. %%12h%%:%%min%% %%ampm%%. + +FRIENDS_FRIENDPIC=>
    + +FRIENDS_WEBSITE=> + +FRIENDS_SUBJECT=> %%subject%% + + +. + +Style: friends/Punquin Elegant w/ Sidebar +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:22:27 + +FRIENDS_RANGE_HISTORY=>below are %%numitems%% friends' journal entries, after skipping by the %%skip%% most recent ones + +FRIENDS_ALTPOSTER<= +
    +[ %%poster%% ] +<=FRIENDS_ALTPOSTER + +FRIENDS_EVENT_PROTECTED<= + + +
    + +%%user%%
    %%altposter%%%%friendpic%% +
    +
    + +%%datetime%%%%subject%%  Protected + +
    + +%%event%% +
    +%%currents%% +
    +
    +

    %%talklinks%%

    +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>below are the most recent %%numitems%% friends' journal entries + +FRIENDS_EVENT_PRIVATE<= + + +
    + +%%user%%
    %%altposter%%%%friendpic%% +
    +
    + +%%datetime%%%%subject%% Private + +
    + +%%event%% +
    +%%currents%% +
    +
    +

    %%talklinks%%

    +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>15 + +FRIENDS_PAGE<= + + +%%title%% +%%head%% + + + +
    +
    + + + +
    + +
    + +
    +
    + +%%title%% + +
    +

    + +> recent entries
    +> calendar
    +> friends
    +%%website%% +> profile
    +%%skiplinks%% +
    +

    +

    +%%userpic%% +
    +
    +
    + +
    + +
    + +
    +%%events%% +
    +
    +
    + +
    + +
    + +
    + +%%skiplinks%%
    +> top of page
    +
    +
    +
    + +
    +%%cons:sitename%% +
    +
    + + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>> next %%numitems%% entries + +FRIENDS_EVENT<= + + +
    + +%%user%%
    %%altposter%%%%friendpic%% +
    +
    + +%%datetime%%%%subject%% + +
    + +%%event%% +
    +%%currents%% +
    +
    +

    %%talklinks%%

    +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=>
    + +FRIENDS_CURRENT=>
    current %%lc:what%%: %%value%% + +FRIENDS_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +FRIENDS_SKIP_LINKS<= +%%skipbackward%%%%skipspacer%%%%skipforward%% + +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY=>

    %%daylong%%, %%monlong%% %%dth%%, %%yyyy%%


    + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>> previous %%numitems%% entries + +FRIENDS_TALK_LINKS=>(%%readlink%%comment on this) + +FRIENDS_CURRENTS=>
    %%currents%% + +FRIENDS_DATE_FORMAT=>%%12h%%:%%min%%%%ap%% + +FRIENDS_FRIENDPIC=>
    + +FRIENDS_WEBSITE=>> %%name%%
    + +FRIENDS_SUBJECT=>
    %%subject%% + + +. + +Style: friends/Refried Paper +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:23:20 + +FRIENDS_RANGE_HISTORY=>%%skip%% entries back + +FRIENDS_ALTPOSTER=> (posted by ) + +FRIENDS_EVENT_PROTECTED<= +
    + +%%friendpic%% + + + +%%currents%% +
    User:%%altposter%%
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Protected
    +

    %%event%%

    +%%talklinks%% +


    +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>%%numitems%% most recent entries + +FRIENDS_EVENT_PRIVATE<= +
    + +%%friendpic%% + + + +%%currents%% +
    User:%%user%%%%altposter%%
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Private
    +

    %%event%%

    +%%talklinks%% +


    + +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>20 + +FRIENDS_PAGE<= + + +%%head%% +%%title%% + + + + + + + + + + + + + + + + + + + + + + +
    %%title%%
    %%range%% +
    + + + + + + + + + + + + + + + + + + + + +
    + + +%%events%% + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    browse
    my journal
    + +
    + + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= +
    + + +
    Oops:There's a problem...
    +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might not have any friends defined. If you are %%name%%, you can edit your friend list so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    +


    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>forward %%lc:numitems%% entries + +FRIENDS_EVENT<= +
    + +%%friendpic%% + + + +%%currents%% +
    User:%%user%%%%altposter%%
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Public
    +

    %%event%%

    +%%talklinks%% +


    +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> + +FRIENDS_CURRENT=>%%what%%:%%value%% + +FRIENDS_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% | + +FRIENDS_SKIP_LINKS<= +%%skipbackward%%
    +%%skipforward%% +<=FRIENDS_SKIP_LINKS + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY=> + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>back %%lc:numitems%% entries + +FRIENDS_TALK_LINKS=>%%readlink%%post a comment + +FRIENDS_CURRENTS=>%%currents%% + +FRIENDS_DATE_FORMAT=>%%yyyy%%-%%mm%%-%%dd%% %%24hh%%:%%min%% + +FRIENDS_FRIENDPIC=>
    + +FRIENDS_WEBSITE<= +
    + my website + +<=FRIENDS_WEBSITE + +FRIENDS_SUBJECT=>%%subject%% + + +. + +Style: friends/Tabular Indent +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2004-12-06 18:04:07 + +FRIENDS_RANGE_HISTORY=>You're looking at %%numitems%% entries, after skipping %%skip%% newer ones. + +FRIENDS_ALTPOSTER=>Posted by:%%poster%%. + +FRIENDS_EVENT_PROTECTED<= +
    + + + + + + + +%%talklinks%% +
    + + + + + +
    +%%friendpic%% +
    %%user%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +
    +%%event%% +
    +
    +
    +<=FRIENDS_EVENT_PROTECTED + +FRIENDS_RANGE_MOSTRECENT=>You're looking at the latest %%numitems%% entries. + +FRIENDS_EVENT_PRIVATE<= +
    + + + + + + + +%%talklinks%% +
    + + + + + +
    +%%friendpic%% +
    %%user%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +
    +%%event%% +
    +
    +
    +<=FRIENDS_EVENT_PRIVATE + +FRIENDS_OPT_ITEMS=>40 + +FRIENDS_PAGE<= + + + + %%head%% + %%title%% + + + + + + + +
    + %%userpic%% + + %%title%%
    + + + + +
    View:Personal Journal.
    View:Calendar.
    %%range%% %%skiplinks%%
    +
    +

    + %%events%% +

    +

    + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + %%website%%
    + + +
    View:User Info.
    View:Personal Journal.
    View:Calendar.
    View:Memories.
    %%range%% %%skiplinks%%
    +
    +

    + + +<=FRIENDS_PAGE + +FRIENDS_END_DAY=> + +FRIENDS_NOFRIENDS<= +

    There are a few reasons why you might not see posts on this friends page: +

      +
    • %%name%% might have no friends defined. If you are %%name%%, you can edit your LiveJournal friends so they show up here.
    • +
    • %%name%% might have friends defined, but all of their friend's posts might be over two weeks old (according to the times on our servers), and thus wouldn't be displayed here.
    • +
    • %%name%% might have friends defined that post only protected entries that you can't view, because they haven't defined you as a friend in return.
    • +
    +

    +<=FRIENDS_NOFRIENDS + +FRIENDS_SKIP_FORWARD=>forward %%numitems%% entries + +FRIENDS_EVENT<= +
    + + + + + + + +%%talklinks%% +
    + + + + + +
    +%%friendpic%% +
    %%user%% +
    + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +
    +%%event%% +
    +
    +
    +<=FRIENDS_EVENT + +FRIENDS_SKIP_SPACER=> or + +FRIENDS_CURRENT=>%%what%%:%%value%%. + +FRIENDS_TALK_READLINK=>Read %%messagecount%% or + +FRIENDS_SKIP_LINKS=>Missed some entries? Then simply jump %%skipbackward%%%%skipspacer%%%%skipforward%%. + +FRIENDS_EVENTS=>%%events%% + +FRIENDS_NEW_DAY<= + + + + +
    + +%%daylong%%, %%monlong%% %%dth%%, %%yyyy%% + +
    +
    +<=FRIENDS_NEW_DAY + +FRIENDS_NO_SUBJECT=> + +FRIENDS_SKIP_BACKWARD=>back %%numitems%% entries + +FRIENDS_TALK_LINKS<= + + + + +Comments: %%readlink%%Add Your Own. + + + + +<=FRIENDS_TALK_LINKS + +FRIENDS_CURRENTS=>%%currents%% + +FRIENDS_DATE_FORMAT=>%%12h%%:%%min%% %%ampm%%. + +FRIENDS_FRIENDPIC=> + +FRIENDS_WEBSITE=>View:Website (%%name%%). + +FRIENDS_SUBJECT=>Subject:%%subject%% + + +. + +Style: lastn/Clean and Simple +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:25:28 + +LASTN_EVENT_PROTECTED<= +
    +
    + +%%altposter%%%%datetime%%: [Protected] %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=> %%subject%%
    + +LASTN_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% - + +LASTN_TALK_LINKS=> + +LASTN_SKIP_BACKWARD<= +
  • Previous %%numitems%% Entries
  • + +<=LASTN_SKIP_BACKWARD + +LASTN_PAGE<= + + + +%%head%% +%%title%% + + + + + + + + +
    +

    %%title%%

    +

    Recent Entries

    +
    +
    +
    %%range%%
    + +%%events%% + +
    + +
    Powered by %%cons:sitename%%
    + +
    + + + + +<=LASTN_PAGE + +LASTN_EVENT<= +
    +
    + +%%altposter%%%%datetime%%: %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD<= +
  • Next %%numitems%% Entries
  • + +<=LASTN_SKIP_FORWARD + +LASTN_RANGE_HISTORY=>You are viewing %%numitems%% entries, %%skip%% into the past. + +LASTN_USERPIC<= +
    + +
    + +<=LASTN_USERPIC + +LASTN_SKIP_SPACER=> + +LASTN_END_DAY<= +
    + +<=LASTN_END_DAY + +LASTN_CURRENTS<= +
    +%%currents%% +
    + +<=LASTN_CURRENTS + +LASTN_EVENT_PRIVATE<= +
    +
    + +%%altposter%%%%datetime%%: [Private] %%subject%% +%%event%% +%%currents%%
    +%%talklinks%% +
    + +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER=>%%pic%%%%poster%% @  + +LASTN_OPT_ITEMS=>25 + +LASTN_CURRENT<= +
    Current %%what%%: %%value%%
    + +<=LASTN_CURRENT + +LASTN_RANGE_MOSTRECENT=>You are viewing the most recent %%numitems%% entries. + +LASTN_NEW_DAY<= +
    +

    %%dth%% %%monlong%% %%yyyy%%

    + +<=LASTN_NEW_DAY + +LASTN_DATE_FORMAT=>%%12h%%:%%min%%%%ampm%% + +LASTN_SKIP_LINKS<= + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE=>
  • %%name%%
  • + + +. + +Style: lastn/Default LiveJournal +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:26:17 + +LASTN_EVENT_PROTECTED<= +%%datetime%%%%altposter%%
    +Protected + +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=>%%subject%%
    + +LASTN_TALK_READLINK=>%%messagecount%% Comment%%mc-plural-s%% | + +LASTN_TALK_LINKS<= +
    + (%%readlink%%Comment on this)
    +<=LASTN_TALK_LINKS + +LASTN_SKIP_BACKWARD=><< Previous %%numitems%% + +LASTN_PAGE<= + + + %%title%% +%%head%% + + + + + + +
    + +%%userpic%% +%%title%%
     
    + +[Most Recent Entries] +[Calendar View] +[Friends] + + +

    %%range%% recorded in +%%name%%%%name-'s%% LiveJournal: +
    +

      +%%skiplinks%% + +%%events%% +
      +
    +%%skiplinks%% + +
    + + + +%%website%% + +
    About %%cons:sitename%%
    + + + +<=LASTN_PAGE + +LASTN_EVENT<= +%%datetime%%%%altposter%% +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=>
    + +LASTN_SKIP_FORWARD=>Next %%numitems%% >> + +LASTN_RANGE_HISTORY=>Below are %%numitems%% journal entries, after skipping by the %%skip%% most recent ones + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=> --  + +LASTN_END_DAY=> + +LASTN_CURRENTS=>
    %%currents%% + +LASTN_EVENT_PRIVATE<= +%%datetime%%%%altposter%%
    +Private + +
    %%subject%% %%event%% %%currents%%
    %%talklinks%% +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER=>
    [%%poster%%]%%pic%% + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>
    Current %%what%%: %%value%% + +LASTN_RANGE_MOSTRECENT=>Below are the %%numitems%% most recent journal entries + +LASTN_NEW_DAY=>%%daylong%%, %%monlong%% %%dth%%, %%yyyy%% + +LASTN_DATE_FORMAT=>%%12h%%:%%min%% %%ampm%% + +LASTN_SKIP_LINKS<= +
    [ %%skipbackward%%%%skipspacer%%%%skipforward%% ]
    + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE<= + + %%name%% + +  +<=LASTN_WEBSITE + + +. + +Style: lastn/Disjointed +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:27:25 + +LASTN_EVENT_PROTECTED<= + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% %%altposter%% 
    %%datetime%%
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=>%%subject%% + +LASTN_TALK_READLINK=>Read %%messagecount%% -  + +LASTN_TALK_LINKS=>%%readlink%%Post + +LASTN_SKIP_BACKWARD=>Backward + +LASTN_PAGE<= + + + + +%%head%% +%%title%% + + + + + + + +
    + +%%events%% + + + + + + + + + + + + + + + +
     
     
     
    +%%skiplinks%% + +
    + + +<=LASTN_PAGE + +LASTN_EVENT<= + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% %%altposter%% 
    %%datetime%%
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD=>Forward + +LASTN_RANGE_HISTORY=> + +LASTN_USERPIC=>
    + +LASTN_SKIP_SPACER=>
    + +LASTN_END_DAY=> + +LASTN_CURRENTS<= + +
    +%%currents%% +
    +<=LASTN_CURRENTS + +LASTN_EVENT_PRIVATE<= + + + + + + + + + + + + + + + + + + + + + + +
    %%subject%% %%altposter%% 
    %%datetime%%
      + %%currents%% + %%event%% 
       %%talklinks%%
     
    +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER<= + + + + + +
     %%poster%%
    +<=LASTN_ALTPOSTER + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>
    %%lc:what%%: %%value%%
    + +LASTN_RANGE_MOSTRECENT=> + +LASTN_NEW_DAY=> + +LASTN_DATE_FORMAT=>%%12hh%%:%%min%%%%ampm%% %%dd%%/%%mm%%/%%yyyy%% + +LASTN_SKIP_LINKS<= + + + + + + + + + + + + +
     
     
     
    +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE=>
    %%name%% + + +. + +Style: lastn/Generator +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:28:35 + +LASTN_EVENT_PROTECTED<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%altposter%% +%%currents%% +%%event%% +
    +

    +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=>%%subject%% + +LASTN_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%%| + +LASTN_TALK_LINKS<= + + +%%readlink%%post comment + + +<=LASTN_TALK_LINKS + +LASTN_SKIP_BACKWARD=>earlier + +LASTN_PAGE<= + + + +%%head%% +%%title%% + + +

    + + +
    + + + + +
    %%title%%[entries|friends|calendar]
    + + + +
    + + +%%userpic%% + + +
    +
    %%name%%

    + +%%website%% + + + + + + + + + + + + + + +
    [userinfo|livejournal userinfo]
    [calendar|livejournal calendar]
    +

    +
    +
    +

    +%%events%% + +
    + + + + + + + +
    navigation
    + + + + + + + + +%%skiplinks%% +
    [viewing|%%range%%]
    +
    +
    +

    +

    + + + +<=LASTN_PAGE + +LASTN_EVENT<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%altposter%% +%%currents%% +%%event%% +
    +

    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC<= +
    +<=LASTN_ALTPOSTER_PIC + +LASTN_SKIP_FORWARD=>later + +LASTN_RANGE_HISTORY=>%%skip%% entries back + +LASTN_USERPIC<= + + + + + +
    + +<=LASTN_USERPIC + +LASTN_SKIP_SPACER=>/ + +LASTN_END_DAY=> + +LASTN_CURRENTS<= + +%%currents%% +

    +<=LASTN_CURRENTS + +LASTN_EVENT_PRIVATE<= + + + + +
    + + + + + + + + +%%talklinks%% +
    %%subject%%[%%datetime%%]
    +%%altposter%% +%%currents%% +%%event%% +
    +

    + +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER<= + +
    + +
    + +%%pic%% +%%poster%% +
    +
    +<=LASTN_ALTPOSTER + +LASTN_OPT_ITEMS=> + +LASTN_CURRENT<= + +[ +%%lc:what%% +| +%%value%% +] + + +<=LASTN_CURRENT + +LASTN_RANGE_MOSTRECENT=>most recent entries + +LASTN_NEW_DAY=> + +LASTN_DATE_FORMAT=>%%dd%% %%monshort%% %%yyyy%%|%%12hh%%:%%min%%%%ampm%% + +LASTN_SKIP_LINKS<= + +[ +go +| +%%skipbackward%%%%skipspacer%%%%skipforward%% +] + + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE<= + +[ +website +| +%%name%% +] + + +<=LASTN_WEBSITE + + +. + +Style: lastn/Magazine +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:29:06 + +LASTN_EVENT_PROTECTED<= +

    +%%altposter%% +

    %%datetime%%%%subject%% Protected

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=> - %%subject%% + +LASTN_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +LASTN_TALK_LINKS<= +
    (%%readlink%%comment on this)
    + +<=LASTN_TALK_LINKS + +LASTN_SKIP_BACKWARD=>Previous %%numitems%% entries + +LASTN_PAGE<= + + + + +%%head%% + %%title%% + + +

    %%title%%

    + +%%events%% +

    %%skiplinks%%

    + + +<=LASTN_PAGE + +LASTN_EVENT<= +
    +%%altposter%% +

    %%datetime%%%%subject%%

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD=>Next %%numitems%% entries + +LASTN_RANGE_HISTORY=>Latest entries - %%skip%% + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=> |  + +LASTN_END_DAY=> + +LASTN_CURRENTS=>
    %%currents%%
    + +LASTN_EVENT_PRIVATE<= +
    +%%altposter%% +

    %%datetime%%%%subject%% Private

    +

    %%event%%

    +%%currents%% +%%talklinks%% +
    + +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER<= + +<=LASTN_ALTPOSTER + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>
    Current %%lc:what%%: %%value%%
    + +LASTN_RANGE_MOSTRECENT=>Latest %%numitems%% entries + +LASTN_NEW_DAY<= +

    %%daylong%%, %%monlong%% %%d%%, %%yyyy%%

    + +<=LASTN_NEW_DAY + +LASTN_DATE_FORMAT=>%%12h%%:%%min%%%%AMPM%% + +LASTN_SKIP_LINKS=>Navigate: (%%skipbackward%%%%skipspacer%%%%skipforward%%) + +LASTN_WEBSITE=>(%%name%%) + + +. + +Style: lastn/Notepad +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:29:50 + +LASTN_EVENT_PROTECTED<= +Protected %%datetime%%%%subject%%%%altposter%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=> %%subject%% + +LASTN_TALK_READLINK=>Read %%messagecount%% Note%%mc-plural-s%% - + +LASTN_TALK_LINKS=>

    %%readlink%%Make Notes

    + +LASTN_SKIP_BACKWARD=>Back A Page + +LASTN_PAGE<= + + + + %%head%% + %%title%% + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
      Journal  Friends  Calendar  User Info  Memories
    +
    +   + +

    %%title%%

    +

    +%%events%% +

    %%skiplinks%%

    +
    +   +
    + + +<=LASTN_PAGE + +LASTN_EVENT<= +%%datetime%%%%subject%%%%altposter%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD=>Forward A Page + +LASTN_RANGE_HISTORY=>%%numitems%% + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=> - + +LASTN_END_DAY=> + +LASTN_EVENT_PRIVATE<= +Private %%datetime%%%%subject%%%%altposter%%

    +%%event%% +%%currents%% +%%talklinks%% +

    +<=LASTN_EVENT_PRIVATE + +LASTN_CURRENTS=>
    %%currents%% + +LASTN_ALTPOSTER=>(%%poster%%) + +LASTN_OPT_ITEMS=>10 + +LASTN_CURRENT=>
    Current %%lc:what%%: %%value%%. + +LASTN_RANGE_MOSTRECENT=>below are the %%numitems%% most recent journal entries + +LASTN_NEW_DAY=> + +LASTN_DATE_FORMAT=>%%dth%% %%monlong%%, %%yyyy%%. %%12h%%:%%min%% %%ampm%%. + +LASTN_SKIP_LINKS<= +%%skipbackward%%%%skipspacer%%%%skipforward%% + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE=>> %%name%%
    + + +. + +Style: lastn/Punquin Elegant w/ Sidebar +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2003-04-15 22:30:29 + +LASTN_EVENT_PROTECTED<= + + +%%datetime%%%%subject%%   + + +%%altposter%% + + +
    +%%event%% +%%currents%% +
    +%%talklinks%% +
    + +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=> - %%subject%% + +LASTN_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +LASTN_TALK_LINKS=>

    (%%readlink%%comment on this)

    + +LASTN_SKIP_BACKWARD=>> previous %%numitems%% entries + +LASTN_PAGE<= + + +%%title%% +%%head%% + + + + +
    + + +
    + +
    + +
    +
    + +%%title%% + +
    +

    + +> recent entries
    +> calendar
    +> friends
    +%%website%% +> profile
    +%%skiplinks%% +
    +

    +

    +%%userpic%% +
    +
    +
    + +
    + +
    + +
    + +%%events%% +
    +
    +
    +
    + +
    + +
    + +
    + +%%skiplinks%%
    +> top of page
    +
    +
    +
    + +
    +%%cons:sitename%% +
    +
    + + + +<=LASTN_PAGE + +LASTN_EVENT<= + + +%%datetime%%%%subject%% + + +%%altposter%% + + +
    +%%event%% +%%currents%% +
    +%%talklinks%% +
    + +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC<= +
    +<=LASTN_ALTPOSTER_PIC + +LASTN_SKIP_FORWARD=>> next %%numitems%% entries + +LASTN_RANGE_HISTORY=>%%numitems%% + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=>
    + +LASTN_END_DAY=> + +LASTN_CURRENTS=>
    %%currents%% + +LASTN_EVENT_PRIVATE<= + + +%%datetime%%%%subject%%   + + +%%altposter%% + + +
    +%%event%% +%%currents%% +
    +%%talklinks%% +
    + +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER<= + + +%%pic%% +%%poster%% + +<=LASTN_ALTPOSTER + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>
    current %%lc:what%%: %%value%% + +LASTN_RANGE_MOSTRECENT=>below are the %%numitems%% most recent journal entries + +LASTN_NEW_DAY=>%%daylong%%, %%monlong%% %%dth%%, %%yyyy%%
    + +LASTN_DATE_FORMAT=>%%12h%%:%%min%% %%ampm%% + +LASTN_SKIP_LINKS<= +%%skipbackward%%%%skipspacer%%%%skipforward%% + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE=>> %%name%%
    + + +. + +Style: lastn/Refried Paper +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:31:12 + +LASTN_EVENT_PROTECTED<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Protected
    +

    %%event%%

    +%%talklinks%% +


    +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=>%%subject%% + +LASTN_TALK_READLINK=>%%messagecount%% comment%%mc-plural-s%% |  + +LASTN_TALK_LINKS=>%%readlink%%post a comment + +LASTN_SKIP_BACKWARD=>back %%lc:numitems%% entries + +LASTN_PAGE<= + + +%%head%% +%%title%% + + + + + + + + + + + + + + + + + + + + + + +
    %%title%%
    %%range%% +
    + + + + + + + + + + + + + + + + + + + + +
    + + +%%events%% + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    browse
    my journal
    + +
    + + + +<=LASTN_PAGE + +LASTN_EVENT<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Public
    +

    %%event%%

    +%%talklinks%% +


    + +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD=>forward %%lc:numitems%% entries + +LASTN_RANGE_HISTORY=>%%skip%% entries back + +LASTN_USERPIC=>
    %%name%%
    + +LASTN_SKIP_SPACER=> + +LASTN_END_DAY=> + +LASTN_EVENT_PRIVATE<= +
    + +%%altposter%% + + + +%%currents%% +
    Date:%%datetime%%
    Subject:%%subject%%
    Security:Private
    +

    %%event%%

    +%%talklinks%% +


    +<=LASTN_EVENT_PRIVATE + +LASTN_CURRENTS=>%%currents%% + +LASTN_ALTPOSTER=>Poster: + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>%%what%%:%%value%% + +LASTN_RANGE_MOSTRECENT=>%%numitems%% most recent entries + +LASTN_NEW_DAY=> + +LASTN_DATE_FORMAT=>%%yyyy%%-%%mm%%-%%dd%% %%24hh%%:%%min%% + +LASTN_SKIP_LINKS<= +%%skipbackward%%
    +%%skipforward%% +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE<= +
    + my website + +<=LASTN_WEBSITE + + +. + +Style: lastn/Tabular Indent +is_public: Y +is_embedded: N +is_colorfree: Y +opt_cache: N +lastupdate: 2004-12-06 18:04:07 + +LASTN_EVENT_PROTECTED<= +
    + + + + + + + +%%talklinks%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=LASTN_EVENT_PROTECTED + +LASTN_SUBJECT=>Subject:%%subject%% + +LASTN_TALK_READLINK=>Read %%messagecount%% or + +LASTN_TALK_LINKS<= + + + + +Comments: %%readlink%%Add Your Own. + + + + +<=LASTN_TALK_LINKS + +LASTN_SKIP_BACKWARD=>back %%numitems%% entries + +LASTN_PAGE<= + + + + %%head%% + %%title%% + + + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + %%website%%
    + + +
    View:User Info.
    View:Friends.
    View:Calendar.
    View:Memories.
    %%range%% %%skiplinks%%
    +
    +

    + %%events%% +

    +

    + + + + + +
    + %%userpic%% + + %%title%%
    + + + + + %%website%%
    + + +
    View:User Info.
    View:Friends.
    View:Calendar.
    View:Memories.
    %%range%% %%skiplinks%%
    +
    +

    + + +<=LASTN_PAGE + +LASTN_EVENT<= +
    + + + + + + + +%%talklinks%% +
    + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=> + +LASTN_SKIP_FORWARD=>forward %%numitems%% entries + +LASTN_RANGE_HISTORY=>You're looking at %%numitems%% entries, after skipping %%skip%% newer ones. + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=> or + +LASTN_END_DAY=> + +LASTN_CURRENTS=>%%currents%% + +LASTN_EVENT_PRIVATE<= +
    + + + + + + + +%%talklinks%% +
    + + +%%subject%% +%%altposter%% + +%%currents%% +
    Time:%%datetime%%
    +
    +%%event%% +
    +
    +
    +<=LASTN_EVENT_PRIVATE + +LASTN_ALTPOSTER=>Posted by:%%poster%%. + +LASTN_OPT_ITEMS=>20 + +LASTN_CURRENT=>%%what%%:%%value%%. + +LASTN_RANGE_MOSTRECENT=>You're looking at the latest %%numitems%% entries. + +LASTN_NEW_DAY<= + + + + +
    + +%%daylong%%, %%monlong%% %%dth%%, %%yyyy%% + +
    +
    +<=LASTN_NEW_DAY + +LASTN_DATE_FORMAT=>%%12h%%:%%min%% %%ampm%%. + +LASTN_SKIP_LINKS=>Missed some entries? Then simply jump %%skipbackward%%%%skipspacer%%%%skipforward%%. + +LASTN_WEBSITE=>View:Website (%%name%%). + + +. + +Style: lastn/Webley Boxes on White +is_public: Y +is_embedded: N +is_colorfree: N +opt_cache: N +lastupdate: 2003-04-15 22:32:25 + +LASTN_EVENT_PROTECTED=> + +LASTN_SUBJECT=>%%subject%% + +LASTN_TALK_READLINK=>%%messagecount%% + +LASTN_TALK_LINKS<= + + +<=LASTN_TALK_LINKS + +LASTN_SKIP_BACKWARD=><< Previous %%numitems%% + +LASTN_PAGE<= + + + %%title%% +%%head%% + + + + +
    + + + + + + +
    %%userpic%% +User Profile
    +Friends
    +Calendar +
    + +%%title%%

    + +%%range%%
    +%%skiplinks%% + +

     
    +%%events%% + +%%skiplinks%%
    +%%website%% + + + +<=LASTN_PAGE + +LASTN_EVENT<= +

    + + + + + + + + + + + + + + + + + + + + + + +
     
      +%%datetime%%
    +%%subject%%

    +%%event%%

    +%%currents%% +
     
     %%talklinks%%
    +


    +<=LASTN_EVENT + +LASTN_ALTPOSTER_PIC=>
    + +LASTN_SKIP_FORWARD=>Next %%numitems%% >> + +LASTN_RANGE_HISTORY=>Below are %%numitems%% recent journal entries, after skipping %%skip%% + +LASTN_USERPIC=> + +LASTN_SKIP_SPACER=> --  + +LASTN_END_DAY=> + +LASTN_EVENT_PRIVATE=> + +LASTN_CURRENTS=>
    %%currents%% + +LASTN_ALTPOSTER=>%%pic%%%%poster%% + +LASTN_OPT_ITEMS=>25 + +LASTN_CURRENT=>
    %%what%%: %%value%% + +LASTN_RANGE_MOSTRECENT=>Below are the %%numitems%% most recent journal entries. + +LASTN_NEW_DAY=> + +LASTN_DATE_FORMAT=>%%yyyy%%.%%mm%%.%%dd%%  %%24hh%%.%%min%% + +LASTN_SKIP_LINKS<= +
    [ %%skipbackward%%%%skipspacer%%%%skipforward%% ]
    + +<=LASTN_SKIP_LINKS + +LASTN_WEBSITE=>[ %%name%% ] + + +. + diff --git a/livejournal/bin/upgrading/s2layers.dat b/livejournal/bin/upgrading/s2layers.dat new file mode 100755 index 0000000..dac85c9 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers.dat @@ -0,0 +1,54 @@ +################################################################ +# base filename layer type parent + +core1 core - +i18nc/da1 i18nc core1 +i18nc/de1 i18nc core1 +i18nc/en1 i18nc core1 +i18nc/eo1 i18nc core1 +i18nc/fi1 i18nc core1 +i18nc/fr1 i18nc core1 +i18nc/ja1 i18nc core1 +i18nc/ru1 i18nc core1 + +classic/layout layout core1 +classic/en i18n classic/layout +classic/themes theme+ classic/layout + +cleansimple/layout layout core1 +cleansimple/en i18n cleansimple/layout +cleansimple/themes theme+ cleansimple/layout + +digitalmultiplex/layout layout core1 +digitalmultiplex/en i18n digitalmultiplex/layout + +haven/layout layout core1 +haven/themes theme+ haven/layout + +generator/layout layout core1 +generator/en i18n generator/layout +generator/themes theme+ generator/layout + +magazine/layout layout core1 +magazine/en i18n magazine/layout +magazine/themes theme+ magazine/layout + +notepad/layout layout core1 +notepad/en i18n notepad/layout +#notepad/themes theme+ notepad/layout + +punquin/layout layout core1 +punquin/en i18n punquin/layout +punquin/themes theme+ punquin/layout + +tabularindent/layout layout core1 +tabularindent/en i18n tabularindent/layout +tabularindent/themes theme+ tabularindent/layout + +sturdygesture/layout layout core1 +sturdygesture/themes theme+ sturdygesture/layout + +variableflow/layout layout core1 + +# include local file +s2layers-local.dat INCLUDE diff --git a/livejournal/bin/upgrading/s2layers/classic/classic.jpg b/livejournal/bin/upgrading/s2layers/classic/classic.jpg new file mode 100755 index 0000000000000000000000000000000000000000..51d9618bb6a975ca5ffc869b68fdd03e0fec6431 GIT binary patch literal 21054 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 literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/classic/en.s2 b/livejournal/bin/upgrading/s2layers/classic/en.s2 new file mode 100755 index 0000000..bea0cf2 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/classic/en.s2 @@ -0,0 +1,16 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "classic/en"; + +set text_meta_music = "Current Music"; +set text_meta_mood = "Current Mood"; + +set text_permalink = "Link"; + +set text_post_comment = "Comment on This"; +set text_post_comment_friends = "Comment on This"; + +set text_read_comments = "1 comment // # comments"; +set text_read_comments_friends = "1 comment // # comments"; diff --git a/livejournal/bin/upgrading/s2layers/classic/layout.s2 b/livejournal/bin/upgrading/s2layers/classic/layout.s2 new file mode 100755 index 0000000..dcc2e37 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/classic/layout.s2 @@ -0,0 +1,785 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Classic"; +layerinfo redist_uniq = "classic/layout"; +layerinfo previews = "classic/classic.jpg"; + +propgroup colors { + property Color body_bgcolor { + des = "Background color of page"; + s1color = "stronger_back"; + } + property Color main_bgcolor { + des = "Background color of main text area"; + s1color = "page_back"; + } + property Color main_fgcolor { + des = "Color of text on main text areas"; + s1color = "page_text"; + } + property Color headerbar_bgcolor { + des = "Background color of header bars"; + s1color = "strong_back"; + } + property Color headerbar_fgcolor { + des = "Color of text on header bars"; + s1color = "strong_text"; + } + property Color metabar_bgcolor { + des = "Background color of side bar"; + s1color = "weak_back"; + } + property Color metabar_fgcolor { + des = "Color of text on side bar"; + s1color = "weak_text"; + } + property Color page_title_color { + des = "Text color of the page's main title"; + s1color = "page_text_title"; + } + property Color page_subtitle_color { + des = "Text color of the page's subtitles"; + s1color = "page_text_em"; + } + property Color link_color { + des = "Text color of links"; + s1color = "page_link"; + } + property Color vlink_color { + des = "Text color of visited links"; + s1color = "page_vlink"; + } + property Color alink_color { + des = "Text color of active links"; + s1color = "page_alink"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} +set body_bgcolor = "#6666cc"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#c0c0ff"; +set headerbar_fgcolor = "#000000"; +set metabar_bgcolor = "#eeeeff"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#8b1a1a"; +set page_subtitle_color = "#c00000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#dddddd"; +set comment_bar_screened_fgcolor = "#000000"; +set tags_aware = true; + +propgroup presentation { + property bool show_entry_userpic { + des = "Show your userpic with your journal's entries?"; + } + property use font_base; + property use font_fallback; + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; +} +set show_entry_userpic = false; +set font_base = "Arial, Helvetica"; +set font_fallback = "sans-serif"; +set page_recent_items = 20; +set page_friends_items = 25; +set view_entry_disabled = false; +set show_entrynav_icons = true; +set page_background_image = ""; + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_website_default_name; +} + +function print_stylesheet () +{ + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; + var string font; + if ($*font_base) { + $font = "\"$*font_base\""; + if ($*font_fallback != "none") { + $font = "$font, "; + } + } + if ($*font_fallback != "none") { + $font = "$font $*font_fallback"; + } + +if ($font != "") { +""" +body, table, td, th, .page_title, #yearheader { +font-family: $font; +} +"""; +} + + """ +body,.body { + background-color: $*body_bgcolor; + color: $*main_fgcolor; + padding: 5pt; +} +a, a:link { + color: $*link_color; +} +a:vlink { + color: $*vlink_color; +} +a:alink { + color: $*alink_color; +} +table.main { + background-color: $*main_bgcolor; + color: $*main_fgcolor; +} +.page_title { + color: $*page_title_color; + font-size: 18pt; +} +.view_links { + font-family: monospace; + white-space: nowrap; +} +.view_links2 { + font-family: monospace; + font-size: 9pt; +} +th.headerbar { + background-color: $*headerbar_bgcolor; + color: $*headerbar_fgcolor; + font-weight: bold; + font-size: 16pt; + text-align: left; +} +td.metabar { + text-align: right; + white-space: nowrap; + background-color: $*metabar_bgcolor; + color: $*metabar_fgcolor; +} +.subject { + color: $*page_subtitle_color; + font-weight: bold; +} +.comments { + text-align: right; +} +#yearheader { + color: $*page_subtitle_color; + font-weight: bold; + font-style: italic; + font-size: 14pt; +} +th.monthheader { + background-color: $*headerbar_bgcolor; + font-size: 12pt; +} +th.daysheader { + background-color: $*metabar_bgcolor; + font-weight: normal; +} +td.weekday_empty { + background-color: $*metabar_bgcolor; +} +.day_id { + font-weight: bold; + font-size: 10pt; +} +#archiveyearpage_nav { + font-size: 14pt; + font-weight: bold; +} + """; +} + +function Page::lay_nav_blurb() { } + +function Page::lay_primary_userpic() : Image { + return $.journal.default_pic; +} + +function EntryPage::lay_primary_userpic() : Image { + return $.entry.userpic; +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var bool section_open = false; + + println ""; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + println "
    "; + } + println """$l.title """; + $section_open = true; + } else { + println """[$l.title]"""; + } + } + } + if ($section_open) { + println "


    "; + } + println ""; +} + +function Page::print () +{ + var string title = $this->title(); + var string userpic; + var Image default_userpic = $this->lay_primary_userpic(); + if (defined $default_userpic) + { + $userpic = ""; + } + var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name; + var string website = $.journal.website_url ? + """$website_name """ : + ""; + var string links; + foreach var string v ($.views_order) { + $links = $links + ($.view == $v ? + "["+lang_viewname($v)+"]" : + "["+lang_viewname($v)+"]"); + } +""" + + +"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + +""" + $title + + +
    + $userpic + $title + +"""; +if (size $.linklist > 0 and $*linklist_support) { +$this->print_linklist(); +} + + $this->lay_nav_blurb(); + $this->print_body(); + "
    \n"; + + ### Affliations + + ""; + + print $website; ""; + + "
    "; server_sig(); "
    \n\n"; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + var string userpic = ""; + if (defined $e.userpic) + { + $userpic = "[User Picture]"; + } + if ($e.new_day or $p.view == "entry") + { + ""; + print $e.time->date_format("%%month%% %%dayord%%, %%yyyy%%"); + "\n"; + } elseif ($p.view == "day") { + "TimeEvent"; + } + ""; + + # Metabar + ""; + # Time + "$time
    "; + # Altposter crap + if ($p.view == "friends") + { + ""; + print $e.journal.username; + "
    "; + } + if ($e.journal.username != $e.poster.username) + { + "["; + print $e.poster.username; + "]
    "; + } + if ($userpic != "" and ($p.view == "friends" or $*show_entry_userpic == true)) + { + print $userpic; + } + # Security icon + if ($e.security) { print $e.security_icon; } + # Permalink + "

    [$*text_permalink]

    "; + ""; + + # Entry + ""; + + if ($p.view == "entry" and $*show_entrynav_icons) + { + print "
    "; + $e->print_linkbar(); + print "
    "; + } + + if ($e.subject) { "\n\n$e.subject
    "; } + if (not $hide_text) { + print $e.text; "\n\n"; + if (size $e.metadata or size $e.tags) + { + "

    "; + foreach var string k ($e.metadata) + { + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { $key = $*text_meta_mood; } + if ($k == "music") { $key = $*text_meta_music; } + if ($k == "mood" and defined $e.mood_icon) + { + var Image i = $e.mood_icon; + $val = " $val"; + } + "$key: $val
    "; + } + + if ($e.tags) { + var int tcount = 0; + "Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    "; + } + + "

    "; + } + } + $e.comments->print(); + ""; + "\n"; +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, $*metabar_bgcolor, $*metabar_fgcolor, false); +} + +function FriendsPage::print_entry (Entry e) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function RecentPage::lay_nav_blurb () +{ + var string user = "$.journal.name"; + if ($.nav.skip > 0) + { + "Below are $.nav.count entries, after skipping $.nav.skip most recent ones in the \"$user\" journal:"; + } else { + "Below are the $.nav.count most recent journal entries recorded in the \"$user\" journal:"; + } +} + +function RecentPage::print_body () +{ + var string nav = ""; + if ($.nav.forward_url != "" or $.nav.backward_url != "") + { + if ($.nav.backward_url != "") + { + $nav = "<< Previous $.nav.backward_count entries"; + } + if ($.nav.backward_url != "" and $.nav.forward_url != "") + { + $nav = "$nav --"; + } + if ($.nav.forward_url != "") + { + $nav = "$nav Next $.nav.forward_count entries >>"; + } + $nav = "

    [$nav]

    "; + } + if ($nav != "") { print $nav; } + "\n"; + foreach var Entry e ($.entries) { $this->print_entry($e); } + "
    \n"; + if ($nav != "") { print $nav; } +} + +function FriendsPage::lay_nav_blurb () +{ + var int total = size $.entries; + if ($.nav.skip > 0) + { + "Below are $total friends entries, after skipping $.nav.skip most recent ones:"; + } else { + "Below are the $total most recent friends journal entries:"; + } +} + +function CommentInfo::print () +{ + if (not $.enabled) { return; } + "

    ("; + if ($.count > 0 or $.screened) { + $this->print_readlink(); + " | "; + } + $this->print_postlink(); + ")

    "; +} + +function YearPage::lay_nav_blurb() +{ + "

    "; + $this->print_year_links(); + "

    "; +} + +function YearPage::print_body +{ + "

    $.year…

    \n"; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearPage::print_year_links () +{ + foreach var YearYear y ($.years) { + if ($y.displayed) { + "[ $y.year ]"; + } else { + "[ $y.year ]"; + } + } +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + # Table Wrapper + "

    \n"; + + # Month Header + "\n"; + + # Weekdays Header + "\n"; + foreach var int d (weekdays()) { + "\n"; + } + "\n"; + + # Weeks + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + # Footer + "\n"; + + # End Table + "
    \n"; + print $m->month_format(); + "
    "+$*lang_dayname_short[$d]+"

    \n"; +} + +function YearWeek::print () +{ + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) { + "$d.day
    "; + if ($d.num_entries) { + "$d.num_entries"; + } else { + " "; + } + "
    \n"; + } + if ($.post_empty) { " "; } + ""; +} + +function DayPage::print_body () +{ + "

    "; print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%"); "

    "; + if (not $.has_entries) + { + "
    "; print ehtml($*text_noentries_day); "
    "; + } else { + ""; + foreach var Entry e ($.entries) { $this->print_entry($e); } + "
    "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + "\n"; + + "\n"; + "\n"; + "\n"; + + "
    $tprev"; + ""; print $.date->date_format("%%yyyy%%/%%mm%%/%%dd%%"); "
    "; + "[$*text_view_archive]
    $tnext
    "; + +} + +function EntryPage::print_body () { + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + "\n"; + print_entry($this, $.entry, $*metabar_bgcolor, $*metabar_fgcolor, $.viewing_thread); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + ""; + ""; + if ($this.multiform_on) { + ""; + ""; + } + } + "
    Comments
     "; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + "
    Mass Action
     "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
    \n"; +} + +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + + "
    [User Picture]"; + + ### From, date, etc + ""; + + ### Gadgets + ""; + + ### Subject / icon + print ""; + + ### Permalink + print ""; + + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    From:$poster
    Date:"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + print (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + print "
    (Link)
    "; + print "
    $c.text
    "; + print "
    "; + if ($c.frozen) { + print "(Replies frozen) "; + } else { + print "(Reply to this) "; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    "; +} + +function ReplyPage::print_body() +{ + "\n"; + if (not $.entry.comments.enabled) { + print "
    $*text_reply_nocomments_header
    $*text_reply_nocomments
    "; + return; + } + var string time = $.replyto.time->time_format(); + var string userpic = ""; + if (defined $.replyto.userpic) + { + $userpic = ""; + } + "TimeText"; + ""; + + # Metabar + ""; + # Time + "$time
    "; + if ($userpic) + { + print $userpic + "
    \n"; + } + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + # Permalink + "

    [$*text_permalink]

    "; + ""; + + # Text + ""; + if ($.replyto.subject != "") { "\n\n$.replyto.subject
    "; } + print $.replyto.text; "\n\n"; + + "\n"; + ""; + "Reply:"; + " "; + $.form->print(); + ""; +} + +function print_theme_preview () +{ + + """ + + +
    + + +
    + John Doe + +
      + + +
      + Friday, November 15th, 2002 +
      + +10:21 pm + + +

      + +Neque porro quisquam est… +
      + +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit + +

      + (1 Comment | + Comment on this) + +

      + +
    +
    +
    + """; +} diff --git a/livejournal/bin/upgrading/s2layers/classic/themes.s2 b/livejournal/bin/upgrading/s2layers/classic/themes.s2 new file mode 100755 index 0000000..b35fb4c --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/classic/themes.s2 @@ -0,0 +1,419 @@ +#NEWLAYER: classic/calmfire +layerinfo type = theme; +layerinfo name = "Calm Fire"; +layerinfo redist_uniq = "classic/calmfire"; +set body_bgcolor = "#9e0610"; +set main_bgcolor = "#7d7d7d"; +set main_fgcolor = "#ffffff"; +set headerbar_bgcolor = "#ff6c1d"; +set headerbar_fgcolor = "#000000"; +set metabar_bgcolor = "#ff9364"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#8b1a1a"; +set page_subtitle_color = "#c00000"; +set link_color = "#ff1010"; +set vlink_color = "#f10707"; +set alink_color = "#ff1d1d"; +set comment_bar_one_bgcolor = "#ff6c1d"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#ff9364"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/shrinkvio +layerinfo type = theme; +layerinfo name = "Shrinking Violet"; +layerinfo redist_uniq = "classic/shrinkvio"; +set body_bgcolor = "#ad22e7"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#5d0383"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#5d0343"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#d9a1f1"; +set page_subtitle_color = "#d9a1f1"; +set link_color = "#2e053f"; +set vlink_color = "#611627"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#5d0383"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#5d0343"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/pistmint +layerinfo type = theme; +layerinfo name = "Pistachio Mint"; +layerinfo redist_uniq = "classic/pistmint"; +set body_bgcolor = "#133422"; +set main_bgcolor = "#a7c4b4"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#096d36"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#096d36"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#096d36"; +set page_subtitle_color = "#096d36"; +set link_color = "#8afabc"; +set vlink_color = "#1da65a"; +set alink_color = "#f9f5f5"; +set comment_bar_one_bgcolor = "#096d36"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#096d36"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/mexicanfood +layerinfo type = theme; +layerinfo name = "Mexican Food"; +layerinfo redist_uniq = "classic/mexicanfood"; +set body_bgcolor = "#ff0000"; +set main_bgcolor = "#f8ff3e"; +set main_fgcolor = "#f15601"; +set headerbar_bgcolor = "#bdbf3e"; +set headerbar_fgcolor = "#ff0000"; +set metabar_bgcolor = "#ffc664"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#ff0000"; +set page_subtitle_color = "#e15a18"; +set link_color = "#f49e08"; +set vlink_color = "#b05403"; +set alink_color = "#ff7405"; +set comment_bar_one_bgcolor = "#bdbf3e"; +set comment_bar_one_fgcolor = "#ff0000"; +set comment_bar_two_bgcolor = "#ffc664"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/ashfire +layerinfo type = theme; +layerinfo name = "Ash and Fire"; +layerinfo redist_uniq = "classic/ashfire"; +set body_bgcolor = "#b5b5b5"; +set main_bgcolor = "#ffb6af"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#e75454"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#ff9696"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#ff1106"; +set page_subtitle_color = "#f06c88"; +set link_color = "#f70208"; +set vlink_color = "#b0161d"; +set alink_color = "#d70106"; +set comment_bar_one_bgcolor = "#e75454"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ff9696"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/desktop +layerinfo type = theme; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "classic/desktop"; +set body_bgcolor = "#00545c"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#ff7b05"; +set headerbar_fgcolor = "#ffeddd"; +set metabar_bgcolor = "#ffffff"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#ff7b05"; +set page_subtitle_color = "#ffeddd"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#5a76ff"; +set comment_bar_one_bgcolor = "#ff7b05"; +set comment_bar_one_fgcolor = "#ffeddd"; +set comment_bar_two_bgcolor = "#ffffff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/satinhandshake +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "classic/satinhandshake"; +set body_bgcolor = "#480c0c"; +set main_bgcolor = "#d06464"; +set main_fgcolor = "#00001d"; +set headerbar_bgcolor = "#aaaaaa"; +set headerbar_fgcolor = "#000000"; +set metabar_bgcolor = "#dddddd"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#9d0404"; +set page_subtitle_color = "#9d0404"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#dddddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/deepmelodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "classic/deepmelodrama"; +set body_bgcolor = "#872d89"; +set main_bgcolor = "#719cff"; +set main_fgcolor = "#8e48b2"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set metabar_bgcolor = "#65b2c1"; +set metabar_fgcolor = "#f5d3ff"; +set page_title_color = "#8e48b2"; +set page_subtitle_color = "#65b2c1"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#dfd3ff"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#f5d3ff"; + +#NEWLAYER: classic/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "classic/everwhite"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set comment_bar_one_bgcolor = "#ffffff"; +set comment_bar_one_fgcolor = "#000000"; +set metabar_bgcolor = "#ffffff"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#000000"; +set page_subtitle_color = "#ff0000"; +set link_color = "#e60000"; +set vlink_color = "#c10602"; +set alink_color = "#ff0600"; +set comment_bar_one_bgcolor = "#ffffff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#ffffff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Greys"; +layerinfo redist_uniq = "classic/everblue"; +set body_bgcolor = "#0f0c6d"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#000000"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#aaaaaa"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#000000"; +set page_subtitle_color = "#aaaaaa"; +set link_color = "#2f00f2"; +set vlink_color = "#060667"; +set alink_color = "#6691ff"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/brownleather +layerinfo type = theme; +layerinfo name = "Brown Leather Coat"; +layerinfo redist_uniq = "classic/brownleather"; +set body_bgcolor = "#d2b48c"; +set main_bgcolor = "#ffebcd"; +set main_fgcolor = "#8b4513"; +set headerbar_bgcolor = "#d48050"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#d48014"; +set metabar_fgcolor = "#d48014"; +set page_title_color = "#d48014"; +set page_subtitle_color = "#ffe1a1"; +set link_color = "#000050"; +set vlink_color = "#867a55"; +set alink_color = "#fffab3"; +set comment_bar_one_bgcolor = "#d48014"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d48050"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "classic/bruise"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#bcbcbc"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#1114a0"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#21c2f1"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#1114a0"; +set page_subtitle_color = "#21c2f1"; +set link_color = "#0000cc"; +set vlink_color = "#000088"; +set alink_color = "#0000ff"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/ranchhand +layerinfo type = theme; +layerinfo name = "Ranch Hand"; +layerinfo redist_uniq = "classic/ranchhand"; +set body_bgcolor = "#2999c2"; +set main_bgcolor = "#cfe0ff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#54442c"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#bababa"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#9d995d"; +set page_subtitle_color = "#704400"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#6a20ff"; +set comment_bar_one_bgcolor = "#54442c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#bababa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: classic/victim +layerinfo type = theme; +layerinfo name = "Victim"; +layerinfo redist_uniq = "classic/victim"; +set body_bgcolor = "#2cd0ff"; +set main_bgcolor = "#505050"; +set main_fgcolor = "#ffffff"; +set headerbar_bgcolor = "#166bac"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#2098f3"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#26b6ff"; +set page_subtitle_color = "#353535"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#166bac"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#2098f3"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/forest +layerinfo type = theme; +layerinfo name = "Forest"; +layerinfo redist_uniq = "classic/forest"; +set body_bgcolor = "#778e64"; +set main_bgcolor = "#9b9ba5"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#72784c"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#72781c"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#a0ac62"; +set page_subtitle_color = "#73777a"; +set link_color = "#3811e1"; +set vlink_color = "#310cbb"; +set alink_color = "#4e7bef"; +set comment_bar_one_bgcolor = "#72784c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#72781c"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/drone +layerinfo type = theme; +layerinfo name = "Drone"; +layerinfo redist_uniq = "classic/drone"; +set body_bgcolor = "#395f82"; +set main_bgcolor = "#f9fcfe"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#904094"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#f56efc"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#ff93ff"; +set page_subtitle_color = "#eeeeff"; +set link_color = "#395f82"; +set vlink_color = "#395f82"; +set alink_color = "#5266ce"; +set comment_bar_one_bgcolor = "#904094"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#f56efc"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/lowercurtain +layerinfo type = theme; +layerinfo name = "Lower the Curtain"; +layerinfo redist_uniq = "classic/lowercurtain"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#6b6b6b"; +set main_fgcolor = "#ffffff"; +set headerbar_bgcolor = "#363636"; +set headerbar_fgcolor = "#f0f5fb"; +set metabar_bgcolor = "#c6c6c6"; +set metabar_fgcolor = "#222222"; +set page_title_color = "#363636"; +set page_subtitle_color = "#c5c8ca"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#3314ba"; +set comment_bar_one_bgcolor = "#363636"; +set comment_bar_one_fgcolor = "#f0f5fb"; +set comment_bar_two_bgcolor = "#c6c6c6"; +set comment_bar_two_fgcolor = "#222222"; + +#NEWLAYER: classic/sunny +layerinfo type = theme; +layerinfo name = "Sunny Day"; +layerinfo redist_uniq = "classic/sunny"; +set body_bgcolor = "#55e0f9"; +set main_bgcolor = "#e38202"; +set main_fgcolor = "#ffffff"; +set headerbar_bgcolor = "#fff500"; +set headerbar_fgcolor = "#e38202"; +set metabar_bgcolor = "#fff5c5"; +set metabar_fgcolor = "#e38202"; +set page_title_color = "#efe052"; +set page_subtitle_color = "#ffba03"; +set link_color = "#df0d12"; +set vlink_color = "#ac1b25"; +set alink_color = "#fe3b3b"; +set comment_bar_one_bgcolor = "#fff500"; +set comment_bar_one_fgcolor = "#e38202"; +set comment_bar_two_bgcolor = "#fff5c5"; +set comment_bar_two_fgcolor = "#e38202"; + +#NEWLAYER: classic/valentine +layerinfo type = theme; +layerinfo name = "Be Mine"; +layerinfo redist_uniq = "classic/valentine"; +set body_bgcolor = "#6f104a"; +set main_bgcolor = "#f2bce9"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#ff37ff"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#df2096"; +set metabar_fgcolor = "#ffffff"; +set page_title_color = "#ae1774"; +set page_subtitle_color = "#df2096"; +set link_color = "#ffffff"; +set vlink_color = "#a51014"; +set alink_color = "#ed8188"; +set comment_bar_one_bgcolor = "#ff37ff"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#df2096"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: classic/stripes +layerinfo type = theme; +layerinfo name = "Stripes"; +layerinfo redist_uniq = "classic/stripes"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set headerbar_bgcolor = "#e7212a"; +set headerbar_fgcolor = "#ffffff"; +set metabar_bgcolor = "#ffffff"; +set metabar_fgcolor = "#000000"; +set page_title_color = "#ffffff"; +set page_subtitle_color = "#ffcfdc"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ffafc1"; +set comment_bar_one_bgcolor = "#e7212a"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffffff"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/cleansimple/cleansimple.jpg b/livejournal/bin/upgrading/s2layers/cleansimple/cleansimple.jpg new file mode 100755 index 0000000000000000000000000000000000000000..d4c25c2472643a7a3e22c481ecb55deb9851d5db GIT binary patch literal 20049 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"; + if ($.nav.forward_url != "") { + println """
  • Next
  • """; + } + if ($.nav.backward_url != "") { + println """
  • Previous
  • """; + } + ""; + } + +} + +# This DEFINITELY should be in core +function Page::lay_view_name(string view) : string + "Don't bother overriding this, because it'll be deleted as soon as core can do it" { + if ($view == "recent") { + return $*text_view_recent; + } elseif ($view == "friends") { + return $*text_view_friends; + } elseif ($view == "userinfo") { + return $*text_view_userinfo; + } elseif ($view == "archive") { + return $*text_view_archive; + } else { + return "Something"; + } +} + +function Page::lay_viewspec_heading() : string + "Returns some text to display under the main heading. Overridden in subclasses." { + return ""; +} +function RecentPage::lay_viewspec_heading() : string { + return $*text_view_recent; +} +function FriendsPage::lay_viewspec_heading() : string { + if ($.journal.journal_type == "C") { + return $*text_view_friends_comm; + } else { + return $*text_view_friends; + } +} +function DayPage::lay_viewspec_heading() : string { + return $*text_view_archive; +} +function YearPage::lay_viewspec_heading() : string { + return $*text_view_archive; +} +function MonthPage::lay_viewspec_heading() : string { + return $*text_view_archive; +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + var bool section_open = false; + + println ""; + } + println """
  • $l.title\n
      """; + $section_open = true; + } else { + println """
    • $l.title
    • """; + } + } + } + if ($section_open) { + println "
  • "; + } + println ""; +} + + +function Page::lay_print_navbar() { + var string userpic; + var Image up_img = $.journal.default_pic; + if (defined $up_img) { + $userpic = """
    """; + } + var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name; + var string website; + if ($.journal.website_url != "") { + $website = """
  • $website_name
  • """; + } + +""" + + +"""; + $this->lay_viewspec_nav(); +"$userpic"; + +$this->print_linklist(); + +""; +} + +function Page::print () +{ + var string title = $this->title(); + +"""\n\n"""; + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); +"""$title + + + + + + +"""; + +if ($*opt_navbar_pos == "left") { + $this->lay_print_navbar(); +} + +""" +"""; + +if ($*opt_navbar_pos == "right") { + $this->lay_print_navbar(); +} + +""" + +
    +"""; + +"

    $.journal.name

    "; +"

    " + $this->lay_viewspec_heading() + "

    "; + +""" +
    +
    +"""; + + $this->print_body(); + +""" +
    + +
    """; server_sig(); """
    + +
    + + + +"""; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + if ($e.new_day) { + """

    """+$e.time->date_format("long")+"

    "; + } + """
    """; + + if ($p.view == "entry" and $*show_entrynav_icons) + { + print "
    "; + $e->print_linkbar(); + print "
    "; + } + + """"""; + + if ($p.view == "friends") { + if ($e.poster.username != $e.journal.username) { + ""+$e.poster.username; + ", posting in "; + } + + "$e.journal.username @ "; + } else { + if ($e.poster.username != $e.journal.username) { + ""; + if (defined $e.userpic) { + """"""; + } + "$e.poster.username @ "; + } + } + ""+$e.time->time_format()+": "; + + if ($e.security) { + $e.security_icon->print(); + } + if ($e.subject) { + " $e.subject"; + } + println ""+($e.subject != "" ? "
    " : ""); + + if ($p.view == "friends" and defined $e.userpic) { + """"""; + } + + if (not $hide_text) { + print "$e.text

    "; + if (size $e.metadata) { + """
    """; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + """
    $text: $val
    """; + } + "
    \n"; + } + if ($e.tags) { + var int tcount = 0; + "Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    "; + } + } + + $e.comments->print(); "\n"; + + "
    "; + + if ($e.end_day) { + "
    "; + } +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function CommentInfo::print () +{ + if (not $.enabled) { return; } + """"; +} + +# This should really be provided in core +function RecentPage::lay_range_text() : string { + if ($.nav.skip == 0) { + return "You are viewing the most recent "+(size $.entries)+" entries"; + } else { + return "You are viewing "+(size $.entries)+" entries, $.nav.skip into the past"; + } +} + +function RecentPage::print_body () +{ + """

    """+$this->lay_range_text()+"""

    """; + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function YearPage::print_year_links () +{ + """"; + +} + +function YearPage::print_month (YearMonth m) +{ + if (not $m.has_entries) { return; } + """
    """; + """"""; + + """"""; + + foreach var int d (weekdays()) { + """\n"; + } + + ""; + + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + "
    """; + + ""; print $m->month_format(); """ (...)
    """; print $*lang_dayname_short[$d]; "
    "; +} + +function YearPage::lay_viewspec_nav() { + $this->print_year_links(); +} + +function YearPage::print_body() { + "

    $.year

    "; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearWeek::print () { + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) { + """$d.day"""; + if ($d.num_entries) { + """
    $d.num_entries
    """; + } else { + "
     
    "; + } + ""; + } + if ($.post_empty) { " "; } + ""; +} + +function DayPage::lay_viewspec_nav() { +""" + +"""; +} + +function DayPage::print_body() { + + """

    """ + $.date->date_format("long") + "

    "; + + if (not $.has_entries) { + println $*text_noentries_day; + } + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + println "
    "; +} + +function EntryPage::print_body () { + + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + """

    Comments

    """; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + if ($this.multiform_on) { + """

    Mass Action

    """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } +} + +# Clean style. Hate to clutter it up with this: +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + + "
    [User Picture]"; + + ### From, date, etc + ""; + + ### Gadgets + ""; + + ### Subject / icon + print ""; + + ### Permalink + print ""; + + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    From:$poster
    Date:"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + print (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + print "
    (Link)
    "; + print "
    $c.text
    "; + print "
    "; + if ($c.frozen) { + print "(Replies frozen) "; + } else { + print "(Reply to this) "; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    "; +} + +function ReplyPage::print_body () { + var string time = $.replyto.time->time_format(); + """ +
    +
    + + """; + + if (not $.entry.comments.enabled) + { + print "$*text_reply_nocomments_header
    + $*text_reply_nocomments
    "; + return; + } + ""; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + " @ "; + "$time: "; + + if ($.replyto.subject) { + " $.replyto.subject"; + } + println ""+($.replyto.subject ? "
    " : ""); + + if (defined $.replyto.userpic) { + """"""; + } + + print $.replyto.text; + + """"""; + + "
    "; + + """

    Reply

    """; + $.form->print(); + +} + +function print_theme_preview () +{ + print """ +
    + + + +
    +

    John Doe

    +

    Recent Entries

    +
    + + +
    +
    +

    December 17th, 2002

    +
    + + 06:42 pm: + Neque porro quisquam… + +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit + +
    +
    +
    + """; +} diff --git a/livejournal/bin/upgrading/s2layers/cleansimple/themes.s2 b/livejournal/bin/upgrading/s2layers/cleansimple/themes.s2 new file mode 100755 index 0000000..23e6986 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/cleansimple/themes.s2 @@ -0,0 +1,420 @@ +#NEWLAYER: cleansimple/purpleblues +layerinfo type = theme; +layerinfo name = "Purples and Blues"; +layerinfo redist_uniq = "cleansimple/purpleblues"; +set body_bgcolor = "#660099"; +set entry_bgcolor = "#9966cc"; +set entry_fgcolor = "#ffff00"; +set meta_color = "#003399"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#00ffff"; +set topbar_bgcolor = "#c0c0ff"; +set topbar_fgcolor = "#000000"; +set navbar_bgcolor = "#eeeeff"; +set navbar_fgcolor = "#000000"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/flesh +layerinfo type = "theme"; +layerinfo name = "Flesh"; +layerinfo redist_uniq = "cleansimple/flesh"; +set body_bgcolor = "#eeeeff"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#ff0000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#00ffff"; +set topbar_bgcolor = "#fa83d7"; +set topbar_fgcolor = "#000000"; +set navbar_bgcolor = "#f677ad"; +set navbar_fgcolor = "#000000"; +set comment_bar_one_bgcolor = "#fa83d7"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#f677ad"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/shrinkvio +layerinfo type = theme; +layerinfo name = "Shrinking Violet"; +layerinfo redist_uniq = "cleansimple/shrinkvio"; +set body_bgcolor = "#ad22e7"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#381a45"; +set topbar_bgcolor = "#5d0383"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#d9a1f1"; +set navbar_fgcolor = "#000000"; +set link_color = "#2e053f"; +set vlink_color = "#611627"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#5d0383"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d9a1f1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/pistmint +layerinfo type = theme; +layerinfo name = "Pistachio Mint"; +layerinfo redist_uniq = "cleansimple/pistmint"; +set body_bgcolor = "#133422"; +set entry_bgcolor = "#a7c4b4"; +set entry_fgcolor = "#000000"; +set meta_color = "#096d36"; +set topbar_bgcolor = "#096d36"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#094f36"; +set navbar_fgcolor = "#000000"; +set link_color = "#8afabc"; +set vlink_color = "#1da65a"; +set alink_color = "#f9f5f5"; +set comment_bar_one_bgcolor = "#096d36"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#094f36"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/mexicanfood +layerinfo type = theme; +layerinfo name = "Mexican Food"; +layerinfo redist_uniq = "cleansimple/mexicanfood"; +set body_bgcolor = "#ff0000"; +set entry_bgcolor = "#f8ff3e"; +set entry_fgcolor = "#f15601"; +set meta_color = "#f50701"; +set topbar_bgcolor = "#bdbf3e"; +set topbar_fgcolor = "#ff0000"; +set navbar_bgcolor = "#e15a18"; +set navbar_fgcolor = "#ffffff"; +set link_color = "#f49e08"; +set vlink_color = "#b05403"; +set alink_color = "#ff7405"; +set comment_bar_one_bgcolor = "#bdbf3e"; +set comment_bar_two_fgcolor = "#ff0000"; +set comment_bar_two_bgcolor = "#e15a18"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: cleansimple/ashfire +layerinfo type = theme; +layerinfo name = "Ash and Fire"; +layerinfo redist_uniq = "cleansimple/ashfire"; +set body_bgcolor = "#b5b5b5"; +set entry_bgcolor = "#ffb6af"; +set entry_fgcolor = "#000000"; +set meta_color = "#d90308"; +set topbar_bgcolor = "#e75454"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#f06c88"; +set navbar_fgcolor = "#000000"; +set link_color = "#f70208"; +set vlink_color = "#b0161d"; +set alink_color = "#d70106"; +set comment_bar_one_bgcolor = "#e75454"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#f06c88"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/desktop +# for layout: 13 (cleansimple/layout) +layerinfo type = theme; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "cleansimple/desktop"; +set body_bgcolor = "#00545c"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#000000"; +set topbar_bgcolor = "#ff7b05"; +set topbar_fgcolor = "#ffeddd"; +set navbar_bgcolor = "#ffeddd"; +set navbar_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#5a76ff"; +set comment_bar_one_bgcolor = "#ff7b05"; +set comment_bar_one_fgcolor = "#ffeddd"; +set comment_bar_two_bgcolor = "#ffeddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/satinhandshake +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "cleansimple/satinhandshake"; +set body_bgcolor = "#480c0c"; +set entry_bgcolor = "#d06464"; +set entry_fgcolor = "#00001d"; +set meta_color = "#000000"; +set topbar_bgcolor = "#aaaaaa"; +set topbar_fgcolor = "#000000"; +set navbar_bgcolor = "#9d0404"; +set navbar_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#9d0404"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/deepmelodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "cleansimple/deepmelodrama"; +set body_bgcolor = "#872d89"; +set entry_bgcolor = "#719cff"; +set entry_fgcolor = "#8e48b2"; +set meta_color = "#8e48b2"; +set topbar_bgcolor = "#3794b3"; +set topbar_fgcolor = "#84b8e7"; +set navbar_bgcolor = "#65b2c1"; +set navbar_fgcolor = "#f5d3ff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#dfd3ff"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#f5d3ff"; + +#NEWLAYER: cleansimple/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "cleansimple/everwhite"; +set body_bgcolor = "#ffffff"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#000000"; +set topbar_bgcolor = "#ffffff"; +set topbar_fgcolor = "#000000"; +set navbar_bgcolor = "#ffffff"; +set navbar_fgcolor = "#000000"; +set link_color = "#e60000"; +set vlink_color = "#c10602"; +set alink_color = "#ff0600"; +set comment_bar_one_bgcolor = "#ffffff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#ffffff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Greys"; +layerinfo redist_uniq = "cleansimple/everblue"; +set body_bgcolor = "#0f0c6d"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#000000"; +set topbar_bgcolor = "#000000"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#aaaaaa"; +set navbar_fgcolor = "#000000"; +set link_color = "#2f00f2"; +set vlink_color = "#060667"; +set alink_color = "#6691ff"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/brownleather +layerinfo type = theme; +layerinfo name = "Brown Leather Coat"; +layerinfo redist_uniq = "cleansimple/brownleather"; +set body_bgcolor = "#d2b48c"; +set entry_bgcolor = "#ffebcd"; +set entry_fgcolor = "#8b4513"; +set meta_color = "#000000"; +set topbar_bgcolor = "#d48014"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#ffe1a1"; +set navbar_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#867a55"; +set alink_color = "#fffab3"; +set comment_bar_one_bgcolor = "#d48014"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffe1a1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "cleansimple/bruise"; +set body_bgcolor = "#000000"; +set entry_bgcolor = "#bcbcbc"; +set entry_fgcolor = "#000000"; +set meta_color = "#000000"; +set topbar_bgcolor = "#1114a0"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#21c2f1"; +set navbar_fgcolor = "#0000ff"; +set link_color = "#0000cc"; +set vlink_color = "#000088"; +set alink_color = "#0000ff"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#0000ff"; + +#NEWLAYER: cleansimple/ranchhand +layerinfo type = theme; +layerinfo name = "Ranch Hand"; +layerinfo redist_uniq = "cleansimple/ranchhand"; +set body_bgcolor = "#2999c2"; +set entry_bgcolor = "#cfe0ff"; +set entry_fgcolor = "#000000"; +set meta_color = "#060667"; +set topbar_bgcolor = "#54442c"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#704400"; +set navbar_fgcolor = "#bababa"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#6a20ff"; +set comment_bar_one_bgcolor = "#54442c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#704400"; +set comment_bar_two_fgcolor = "#bababa"; + +#NEWLAYER: cleansimple/victim +layerinfo type = theme; +layerinfo name = "Victim"; +layerinfo redist_uniq = "cleansimple/victim"; +set body_bgcolor = "#2cd0ff"; +set entry_bgcolor = "#505050"; +set entry_fgcolor = "#ffffff"; +set meta_color = "#000000"; +set topbar_bgcolor = "#166bac"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#353535"; +set navbar_fgcolor = "#ffffff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#166bac"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#353535"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: cleansimple/forest +layerinfo type = theme; +layerinfo name = "Forest"; +layerinfo redist_uniq = "cleansimple/forest"; +set body_bgcolor = "#778e64"; +set entry_bgcolor = "#9b9ba5"; +set entry_fgcolor = "#000000"; +set meta_color = "#ffffff"; +set topbar_bgcolor = "#72784c"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#73777a"; +set navbar_fgcolor = "#000000"; +set link_color = "#3811e1"; +set vlink_color = "#310cbb"; +set alink_color = "#4e7bef"; +set comment_bar_one_bgcolor = "#72784c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#73777a"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/drone +layerinfo type = theme; +layerinfo name = "Drone"; +layerinfo redist_uniq = "cleansimple/drone"; +set body_bgcolor = "#395f82"; +set entry_bgcolor = "#f9fcfe"; +set entry_fgcolor = "#000000"; +set meta_color = "#000000"; +set topbar_bgcolor = "#904094"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#eeeeff"; +set navbar_fgcolor = "#000000"; +set link_color = "#395f82"; +set vlink_color = "#395f82"; +set alink_color = "#5266ce"; +set comment_bar_one_bgcolor = "#904094"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/lowercurtain +layerinfo type = theme; +layerinfo name = "Lower the Curtain"; +layerinfo redist_uniq = "cleansimple/lowercurtain"; +set body_bgcolor = "#000000"; +set entry_bgcolor = "#6b6b6b"; +set entry_fgcolor = "#ffffff"; +set meta_color = "#ffffff"; +set topbar_bgcolor = "#363636"; +set topbar_fgcolor = "#f0f5fb"; +set navbar_bgcolor = "#c5c8ca"; +set navbar_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#3314ba"; +set comment_bar_one_bgcolor = "#363636"; +set comment_bar_one_fgcolor = "#f0f5fb"; +set comment_bar_two_bgcolor = "#c5c8ca"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/sunny +layerinfo type = theme; +layerinfo name = "Sunny Day"; +layerinfo redist_uniq = "cleansimple/sunny"; +set body_bgcolor = "#55e0f9"; +set entry_bgcolor = "#e38202"; +set entry_fgcolor = "#ffffff"; +set meta_color = "#000000"; +set topbar_bgcolor = "#ffba03"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#ffba55"; +set navbar_fgcolor = "#ffffff"; +set link_color = "#df0d12"; +set vlink_color = "#ac1b25"; +set alink_color = "#fe3b3b"; +set comment_bar_one_bgcolor = "#ffba03"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffba55"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: cleansimple/valentine +layerinfo type = theme; +layerinfo name = "Be Mine"; +layerinfo redist_uniq = "cleansimple/valentine"; +set body_bgcolor = "#6f104a"; +set entry_bgcolor = "#f2bce9"; +set entry_fgcolor = "#000000"; +set meta_color = "#ff24ab"; +set topbar_bgcolor = "#ff37ff"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#df2096"; +set navbar_fgcolor = "#000000"; +set link_color = "#ffffff"; +set vlink_color = "#a51014"; +set alink_color = "#ed8188"; +set comment_bar_one_bgcolor = "#ff37ff"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#df2096"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: cleansimple/stripes +layerinfo type = theme; +layerinfo name = "Stripes"; +layerinfo redist_uniq = "cleansimple/stripes"; +set body_bgcolor = "#ffffff"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#000000"; +set meta_color = "#ff0000"; +set topbar_bgcolor = "#e7212a"; +set topbar_fgcolor = "#ffffff"; +set navbar_bgcolor = "#ffcfdc"; +set navbar_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ffafc1"; +set comment_bar_one_bgcolor = "#e7212a"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffcfdc"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/core1.s2 b/livejournal/bin/upgrading/s2layers/core1.s2 new file mode 100755 index 0000000..91b25c0 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/core1.s2 @@ -0,0 +1,2020 @@ +# -*-s2-*- + +##[ layerinfo ] + +layerinfo "type" = "core"; +layerinfo "name" = "LiveJournal S2 Core, v1"; +layerinfo "redist_uniq" = "core1"; +layerinfo "majorversion" = "1"; +layerinfo "author_name" = "LiveJournal Webmaster"; +layerinfo "author_email" = "webmaster@livejournal.com"; + +##[ S2 core classes ] + +class int +"An integer number. This isn't really a class, as suggested by its lower-case name. Parameters of type int pass by value, unlike all variables of real object types, which pass by reference. Instead, this is just a pseudo-class which provides convenience methods on instances of integers. The other pseudo-class is [class[string]]." +{ + function builtin zeropad(int digits) : string + "Return the integer as a string formatted at least \$digits characters long, left-padded with zeroes."; +} + +class string +"A series of characters. This isn't really a class, as suggested by its lower-case name. Parameters of type string pass by value, unlike all variables of real object types, which pass by reference. Instead, this is just a pseudo-class which provides convenience methods on instances of strings. The other pseudo-class is [class[int]]." +{ + function builtin substr(int start, int length) : string + "Returns up to \$length characters from string, skipping \$start characters from the beginning."; + + function builtin ends_with (string sub) : bool + "Returns true if string ends in \$sub"; + + function builtin starts_with (string sub) : bool + "Returns true if string begins with \$sub"; + + function builtin contains (string sub) : bool + "Return true if string contains \$sub"; + + function builtin lower : string + "Returns string in lower case."; + + function builtin upper : string + "Returns string in upper case"; + + function builtin upperfirst : string + "Return string with the first character capitalized."; + + function builtin length() : int + "Return the number of characters in the string."; + + function builtin repeat(int n) : string + "Returns the string repeated n times"; +} + +class Color +"Represents a color." +{ + var readonly int r "Red value, 0-255."; + var readonly int g "Green value, 0-255."; + var readonly int b "Blue value, 0-255."; + var string as_string "HTML hex encoded: #rrggbb"; + function builtin Color(string s) : Color "Constructor for color class. Lets you make a Color object from a string of form #rrggbb"; + function builtin set_hsl (int h, int s, int v) "Set the HSL value for a color class."; + + function builtin red(int r) "Set the red value. (0-255)"; + function builtin green(int g) "Set the green value. (0-255)"; + function builtin blue(int b) "Set the blue value. (0-255)"; + function builtin red() : int "Get the red value."; + function builtin green() : int "Get the green value."; + function builtin blue() : int "Get the blue value."; + + function builtin hue(int h) "Set the hue value. (0-255)"; + function builtin saturation(int s) "Set the saturation value. (0-255)"; + function builtin lightness(int v) "Set the lightness value. (0-255)"; + function builtin hue() : int "Get the hue value. (0-255)"; + function builtin saturation() : int "Get the saturation value. (0-255)"; + function builtin lightness() : int "Get the lightness value. (0-255)"; + + function builtin clone() : Color "Returns identical color."; + function builtin lighter() : Color "Returns a new color with lightness increased by 30."; + function builtin lighter(int amt) : Color "Returns a new color with lightness increased by amount given."; + function builtin darker() : Color "Returns a new color with lightness decreased by 30."; + function builtin darker(int amt) : Color "Returns a new color with lightness decreased by amount given."; + function builtin inverse() : Color "Returns inverse of color."; + function builtin average(Color other) : Color "Returns color averaged with \$other color."; +} + + +##[ site-core classes ] + +class Date +"Represents a date." +{ + var int year "Year; 4 digits."; + var int month "Month; 1-12."; + var int day "Day; 1-31."; + + function builtin day_of_week() : int + "Returns the day of the week this date falls on, from Sunday=1 to Saturday=7"; + + function builtin date_format () : string + "Returns date formatted as normal. // SeeAlso: siteapi.core1.dateformats"; + + function builtin date_format (string fmt) : string + "Returns date formatted as indicated by \$fmt. One of: short, med, long, med_day, long_day. Or a custom format. Default is 'short'. // SeeAlso: siteapi.core1.dateformats"; +} + +class DateTime extends Date +"Represents both a date and time." +{ + var int hour "Hour; 0-23."; + var int min "Minute; 0-59."; + var int sec "Second; 0-59."; + + function builtin time_format () : string + "Returns time formatted as normal. // SeeAlso: siteapi.core1.dateformats"; + + function builtin time_format (string fmt) : string + "Returns time formatted as indicated by \$fmt, or normal if blank. // SeeAlso: siteapi.core1.dateformats"; +} + +class Image +"Represents an image." +{ + var readonly string url "URL of the image"; + var int width "Width in pixels"; + var int height "Height in pixels"; + var string alttext "Default alternative text for image"; + + function builtin set_url (string url) + "Sets the URL, doing any necessary escaping."; + + function print () + "Print an HTML tag for this Image"; + + function print (string alttext) + "Print an HTML tag for this Image with given alttext"; + + function print (string{} opts) + "Print the HTML for an image, Supported keys are 'href' to create a link to the image source + and 'a_attr' which adds attributes to the anchor tag if a link is to be printed."; + + function as_string () : string + "Return the HTML tag for this image"; + + function as_string (string alttext) : string + "Return an HTML tag for this Image with given alttext"; + + function as_string (string{} opts) : string + "Return the HTML for an image, Supported keys are 'href' to create a link to the image source + and 'a_attr' which adds attributes to the anchor tag if a link is to be printed."; +} + +class Link +"A link or button" +{ + var readonly string url "URL which the link points to"; + var readonly string caption "The caption for the link"; + var Image icon + "A suggestion from the server as to which icon to use. layouts/users can override this of course. + alt text works similarly to [member[Link.caption]]."; + + function print_button + "Output this Link as a clickable button using [member[Link.icon]]"; + + function as_string() : string + "Return the button HTML link."; +} + +class ItemRange +"Represents a range of items which optionally contain items." +{ + var bool all_subitems_displayed "True if the subitems in this range represent the entire set. In this case, all of the URL members are blank."; + var int num_subitems_displayed "The number of subitems in this range."; + var int total "The total number of items that are navigable to."; + var int current "The currently-active item."; + var int from_subitem "The index of the first subitem in this range."; + var int to_subitem "The index of the last subitem in this range."; + var int total_subitems "The number of subitems."; + var readonly string url_next "URL for the 'next' link. Blank if there isn't a next URL."; + var readonly string url_prev "URL for the 'previous' link. Blank if there isn't a previous URL."; + var readonly string url_first "URL for the 'first' link. Blank if already on the first page."; + var readonly string url_last "URL for the 'last' link. Blank if already on the last page."; + function builtin url_of(int n) : string "Returns the URL to use to link to the nth item"; + + function print () "Prints the item range links"; + function print(string labeltext) "Prints the item range links with the given \$labeltext"; +} + +### LJ Specific Classes + +class CommentInfo +"Information about comments attached to something." +{ + var readonly string read_url "URL pointer to the 'Read Comments' view."; + var readonly string post_url "URL pointer to the 'Post Comments' view."; + var int count "Current number of comments available to be read by the viewer."; + var bool screened "Set to true if there are screened comments and remote user can unscreen them."; + var bool enabled "Set to false if comments disabled journal-wide or just on this item."; + var bool maxcomments "Set to true if entry has reached a comment maximum."; + + function print + "Print all comment related links"; + function print_readlink + "Print the formatted link to the 'Read Comments' view"; + function print_postlink + "Print the formatted link to the 'Post Comments' view"; +} + +class UserLink +"A user-defined link to an outside resource." +{ + var readonly bool is_heading "Is this link a heading or category name? If so, it has no url and a list of children."; + var readonly string title "The title or label for the link"; + var readonly string url "The url to which the link points"; + var readonly UserLink[] children "Not Implemented: An array of child UserLink objects."; +} + +class UserLite +"A 'lite' version of a [class[User]] which the system often has more readily-available than a full version." +{ + var readonly string username "Canonical Username, ex: johnqpub. Note that if journal_type is an external identity, there will be no username, so this field will be a display version of their URL, longer than 15 characters, and with characters other than a-z, 0-9 and underscore."; + var readonly string name "User's formatted name, ex: John Q. Public"; + var readonly string journal_type "Type of account: P (personal), C (community), Y (syndicated), S (shared), I (external identity) etc"; + + function builtin equals(UserLite u) : bool "Returns true if the two user objects refer to the same user. Use this rather than comparing usernames, since usernames aren't globally unique."; + function base_url () : string "Returns URL of user's journal."; + function tag_manage_url () : string "Returns URL to user's tag management page."; + function as_string() : string; + function print (); +} + +class Tag +"Represents a tag." +{ + var readonly string name "Textual representation of this tag."; + var readonly string url "URL to view entries with this tag."; +} + +class EntryLite +"Base class for both journal entries and comments." +{ + var readonly string subject "Subject. May contain HTML. Don't do substring chops on this."; + var readonly string text "Text (will be blank on some viewtypes, like 'month' view, or with collapsed threads)"; + var DateTime time "The user-specified time of the post, or the GMT time if it's a comment."; + + var UserLite poster "Author of the entry, or null if an anonymous comment"; + var UserLite journal "Journal the entry has been posted to"; + + var readonly Tag[] tags "Array of tags applied to this entry."; + + var Image userpic "The userpic selected to relate to this entry."; + + var readonly string{} metadata "Post metadata. Keys: 'music', 'mood'"; + + var readonly string dom_id "The DOM 'id' attribute you should put on your outer-most element"; + + var readonly string permalink_url "A URL at which this specific entry can be viewed, for linking purposes."; + var int depth "Visual depth of entry. Top-level journal entries are always depth zero. Comments have a depth greater than or equal to one, depending on where the thread is rooted at."; + + var string[] link_keyseq "An array of keys which you should pass to [method[EntryLite.get_link(string)]] to produce an entry 'toolbar'. Does not contain nav_next and nav_prev for entries; you should retrieve those separately and put them somewhere appropriate for your layout."; + + function builtin get_link (string key) : Link "Get a link to some action related to this entry or comment. You can iterate over [member[EntryLite.link_keyseq]] to get keys to pass in here to produce a 'toolbar' of links."; + function builtin get_plain_subject () : string "For Entries that can contain HTML subjects, this returns the subjeft without HTML. Comments can't have HTML in subjects, so this is equivalent to just using \$.subject. The returned 'plain' subject may still contain HTML entities, so don't do substring chops on it either."; + function builtin get_tags_text () : string "Returns a string containing a div of class 'ljtags' with the tags for the entry. If there are no tags on the entry, returns a blank string. The string is formatted according to the 'text_tags' property."; + function print_linkbar() "Print the link bar for this entry or comment."; +} + +class Entry extends EntryLite +"A journal entry" +{ + var readonly string security "The security level of the entry ('private', 'protected'), or blank if public."; + var Image security_icon "A little icon which should be displayed somewhere on an entry to represent the security setting"; + + var Image mood_icon "Mood icon, or null."; + var CommentInfo comments "Comment information on this entry"; + + var bool new_day "Is this entry on a different day to the previous one?"; + var bool end_day "Is this the last entry of a day?"; + + var int itemid "Server stored ID number for this entry"; + + function print_metadata (); + function builtin plain_subject () : string + "Return entry's subject as plain text, with all HTML removed."; + + function print_link_next() "Print the link to the next entry in this journal."; + function print_link_prev() "Print the link to the previous entry in this journal."; +} + +class Comment extends EntryLite +"A comment to a journal entry, or to another comment." +{ + var Image subject_icon "Subject icon, or null."; + var int talkid "Server stored ID number for this comment."; + var Comment[] replies "Comments replying to this comment."; + var bool full "True if all information is available for this comment. False if only the subject, poster, and date are available. (collapsed threads)"; + var readonly string parent_url "URL to parent comment, or blank if a top-level comment."; + var readonly string reply_url "URL to reply to this comment."; + var readonly string thread_url "URL to view threaded rooted at this comment, or blank if comment has no children."; + var readonly bool screened "True if comment is in screened state."; + var readonly bool frozen "True if comment is in frozen state."; + var readonly string anchor "Direct link to comment, via HTML name anchors"; + + function builtin print_multiform_check "Prints the select checkbox in CSS class 'ljcomsel' with DOM id 'ljcomsel_\$talkid' for a multi-action form started with [method[EntryPage.print_multiform_start()]]."; +} + +### Userinfo + +class Friend extends UserLite +"Represents a friends or friendof list" +{ + var Color bgcolor "Background color selected for friend"; + var Color fgcolor "Foreground color selected for friend"; +} + +class User extends UserLite +"A more information-rich userinfo structure" +{ + var Image default_pic "Information about default userpic"; + var readonly string userpic_listing_url "URL of a page listing this user's userpics"; + var readonly string website_url "URL pointer to user's website"; + var readonly string website_name "'pretty' name of user's website"; +} + +### Other + +class Redirector +"A redirector makes either a GET URL which redirects to a pretty URL or an HTML form which posts to a URL that redirects to a pretty URL. This class exists because it's often desirable to use a form to end up at a URL, instead of doing a GET request. It's also used in cases where finding the previous or next URL would incur database overhead which would be wasteful, considering most people don't click previous/next links. Instead, the system will give you a Redirector object which has a URL that'll do the lookup for you later, followed by a redirect." + +{ + var readonly string user; + var readonly string vhost; + var readonly string type; + var readonly string url; + + function start_form() "Starts an inline HTML form, then calls [method[Redirector.print_hiddens()]]. You can also make it yourself, using [member[Redirector.url]], if you need special form attributes."; + function print_hiddens() "Prints the necessary hidden elements for a form. Called automatically by [method[Redirector.start_form()]]."; + function end_form() "Prints a form close tag."; + + function builtin get_url(string redir_key) "Returns a GET URL, given a redir_key"; +} + +### Pages + +class Page +"Base template for all views" +{ + var readonly string view "The view type (recent, friends, archive, month, day, entry)"; + var readonly string{} args + "Arguments from the URL's query string (after the question mark). S2 code can only access arguments starting with a period, and this period is not included in the hash key."; + + var User journal "User whose journal is being viewed"; + var readonly string journal_type "Journal type, ex: 'P' (personal), 'C' (community), etc."; + var readonly string base_url "The base URL of the journal being viewed."; + var readonly string{} view_url + "Links to top-level views where id equals the name of the view being linked to. + (if one of views == \$.view, already looking at that view)"; + + var readonly string[] views_order "An array of view identifiers which can be used to order the views hash."; + var readonly string head_content + "Extra tags supplied by the server to go in the section of the output HTML document. Layouts + should include this in the head section if they are writing HTML."; + + var readonly string stylesheet_url + "The URL to use in a link element for the server-supported external stylesheet to put stuff in it)"; + + var readonly string global_title + "A title selected by the user for their whole journal."; + + var readonly string global_subtitle + "A sub-title selected by the user for their whole journal."; + + var readonly UserLink[] linklist + "An array of UserLink objects defined by the user to be displayed on their journal."; + + var readonly DateTime time + "A DateTime object filled with the time (GMT) when the page was created."; + + function print + "The main entry point that LiveJournal calls. Layouts should override this to create HTML that's the + same for all view types, and use \$this->title, \$this->head and \$this->body to include view-specific + content into the template."; + + function view_title : string + "Return a title for this particular page, such as \"Friends' Recent Entries\" for the friends view, + or a date for the day view. Should be overridden in i18n layers. Ideally, layout layers should never override + this. See [method[Page.title()]]."; + + function title : string + "Return a relevant combination of [member[Page.global_title]] and [method[Page.view_title()]]. May be + overridden in layout layers or left untouched for the core layer to handle."; + + function print_body + "Call from [method[Page.print()]] to render parts of the view that are specific to the view, eg print + the recent set of journal entries, recent friends entries, or rows of user information"; + + function print_head [fixed] + "Print server side supplied head content. This is a fixed function, so you can't override it. See + [method[Page.print_custom_head()]] if you want to supply custom head content."; + + function print_custom_head + "Layers can override this to add extra HTML to the head section of the HTML document. + Note that layouts are not intended to override this method."; + + function print_linklist + "Print the list of UserLink objects specified by the user."; + + function print_entry(Entry e) + "Output a journal entry. Layouts should override this and the inherited versions in RecentPage, FriendsPage + and DayPage to change how entries display."; + + function print_entry_poster(Entry e) + "Output a line of text which says who posted an entry (just \"user\", or \"user posting in somejournal\")"; + + function builtin get_latest_month() : YearMonth + "Returns information about the latest month the user posted (or the current month, if no posts), so that the page may include a mini-calendar or similar features."; + + function builtin visible_tag_list() : Tag[] + "Returns a list of tags that the logged in user can see for the journal being viewed."; +} + +class RecentNav +"Navigation position within a [class[RecentPage]] or [class[FriendsPage]] and URLs to move about." +{ + var int version "Currently version 1. A new method of navigation has been frequently discussed, so this is planning for the future"; + + # version 1 attributes: + var int skip "Indicates how many entries are being skipped back."; + var int count "Indicates how many entries we're currently seeing"; + var readonly string forward_url "URL to go forward in time, or blank if furthest forward."; + var int forward_skip "Number of items we'd be skipping going forward."; + var int forward_count "Number of items we'd be potentially seeing going forward."; + var readonly string backward_url "URL to go backward in time, or blank if furthest back server will allow."; + var int backward_skip "Number of items we'd be skipping going back more."; + var int backward_count "Number of items we'd be potentially seeing going backward."; +} + +class RecentPage extends Page +"Most recent entries page, formally known as the LASTN view in the previous style system" +{ + var Entry[] entries + "Array of entries available to be seen by the viewer of the page."; + + var RecentNav nav; +} + +class FriendsPage extends RecentPage +"Friends most recent entries" +{ + var Friend{} friends + "A mapping from friend username to color association information. There will only be keys for friends whose entries are in the entries array."; + + var readonly string friends_title + "A user-selected title for their friends page."; + + var string friends_mode + "The 'mode' of this view. An empty string indicates a normal friends view, while 'friendsfriends' indicates the Friends-of-friends view."; + + var bool filter_active + "If true, some kind of filter is in effect. If this filter has a name, it will be included in [member[FriendsPage.filter_name]]"; + + var string filter_name + "The name of the filter in effect, if it has a name. This is only used when 'custom' [member[FriendsPage.filter_active]] is true."; +} + +class DayPage extends Page +"View entries by specifc day" +{ + var Date prev_date "Previous day"; + var Date next_date "Next day"; + var readonly string prev_url "URL to previous day"; + var readonly string next_url "URL to next day"; + var bool has_entries "True if there are entries on the specified day"; + var Entry[] entries "Array of entries available to be seen by the viewer of the page"; + var Date date "Date of the current day"; +} + +### Archive classes + +class YearYear +"Information on how to link to a year in the year archive" +{ + var int year "Number of the year, eg 2001."; + var readonly string url "URL to link to for this year."; + var bool displayed "If this is the year currently being displayed, this will be true."; +} + +class YearDay +"Information on how to link to a day in the year archive" +{ + var int day "Day of month number"; + var Date date "Date of day"; + + # http://zilla.livejournal.org/show_bug.cgi?id=504 + # var bool is_today "True if the day represents the current day."; + + var int num_entries "Number of entries made on this day"; + var readonly string url "A URL to view the day, if there are entries, else blank."; +} + +class YearWeek +"Represents a week on the [class[YearMonth]] on the [class[YearPage]]." +{ + var int pre_empty "How many days at the start of the week are blank? (From previous month)"; + var int post_empty "How many days at the end of the week are blank? (From next month)"; + var YearDay[] days "An array of the days of the week (0=sunday)"; + + function print() + "Print formatted week"; +} + +class YearMonth +"A month on the [class[YearPage]]." +{ + var bool has_entries "If this is false, you probably don't want to display this month."; + var int month "The number of the month"; + var int year "The number of the year"; + var YearWeek[] weeks "An array of the weeks of the month (for ease of building a row-per-week calendar)"; + var readonly string url "A url to link to in order to view this month."; + var readonly string prev_url "A url to link to in order to view the previous month."; + var readonly string next_url "A url to link to in order to view the next month."; + var Date prev_date "Date of previous month, with day of zero, or null if none."; + var Date next_date "Date of next month, with day of zero, or null if none."; + + function builtin month_format () : string + "Returns month formatted long (February 1980) // SeeAlso: siteapi.core1.dateformats"; + function builtin month_format (string fmt) : string + "Returns time formatted as indicated by \$fmt, or 'long' if blank. // SeeAlso: siteapi.core1.dateformats"; +} + +class YearPage extends Page +"Entire calendar page for a single year." +{ + var int year "The year being viewed"; + var YearYear[] years "Information for linking to other years"; + var YearMonth[] months "12 months objects, even if no entries are in that month."; + + function print_month(YearMonth m) + "Print the calendar cell for the given month"; + + function print_year_links() + "Print the navigation links to move between years"; +} + +class MonthDay extends YearDay +"Summaries of posts on a given day on the [class[MonthPage]]." +{ + var bool has_entries "True if there are entries on this day."; + var Entry[] entries "Only populated on the month view. Entry text not present."; + + function print_subjectlist + "Print a list of entry summaries including subjects"; +} + +class MonthEntryInfo +"A month the user has journal entries, along with information to link to it." +{ + var Date date "Date of month, with day of zero."; + var readonly string url "URL for the [class[MonthPage]] month view."; + var readonly string redir_key "The 'redir_key' parameter for a [class[Redirector]] instance."; +} + +class MonthPage extends Page +"A page which contains a list of posts made in that month" +{ + var Date date "Date of this month, with day of zero."; + var MonthDay[] days "One entry for each day of the month."; + var MonthEntryInfo[] months "Other months this journal has entries."; + var Date prev_date "Date of previous month, with day of zero, or null if none."; + var Date next_date "Date of next month, with day of zero, or null if none."; + var readonly string prev_url "URL of previous month, or empty string if none."; + var readonly string next_url "URL of next month, or empty string if none."; + var Redirector redir "Necessary to make a form which POSTs to a redirector"; +} + +class EntryPage extends Page +"A page with a single journal entry and associated comments." +{ + var Entry entry "Journal entry being viewed"; + var ItemRange comment_pages "Represents what comment page is being displayed."; + var Comment[] comments "Comments to journal entry, or at least some of them."; + var bool viewing_thread "True if viewing a specific sub-thread of the comments. Style may which to hide the journal entry at this point, since the focus is the comments."; + + function print_comments(Comment[] comments) "Prints comments"; + function print_comment(Comment comment) "Prints a full comment"; + function print_comment_partial(Comment comment) "Prints a collapsed comment"; + + var bool multiform_on "Set to true if the multi-action is to be printed, which requires both comments and applicable permissions for the remote user."; + function builtin print_multiform_start "Prints start of form tag and hidden elements to do a multi-comment action (multiple delete, screen, unscreen, etc...)"; + function builtin print_multiform_end "Prints end of form tag to do a multi-comment action."; + function builtin print_multiform_actionline "Prints the line of the multiform giving instructions, options, and the submit button, using the text of the different \$*text_multiform_ properties."; +} + +class ReplyForm +"This class will be used more in the future to set options on the reply form before +it's printed out by the system. The system has to print it since it contains +sensitive information which can't be made available to S2." +{ + var readonly bool subj_icons "Whether user has enabled subject icons or not. Currently read-only until policy is decided on whether layers should be able to change it (rather than changing it in the user preferences)"; + function builtin print() "Prints the reply form"; +} + +class ReplyPage extends Page +"A page to reply to a journal entry or comment" +{ + var Entry entry "The journal entry for this talk page"; + var EntryLite replyto "The object which is being replied to, either the entry or a comment"; + var ReplyForm form "The reply form."; +} + +class PalItem +"A specification for a numbered palette index in a GIF or PNG to be changed to a certain color" +{ + var int index "Integer palette index."; + var Color color "Color to put at specified index."; +} + +##[ Built-in Functions ] + +function builtin eurl (string s) : string +"URL escape"; + +function builtin ehtml (string s) : string +"Escapes all HTML tags and entities from the text"; + +function builtin etags (string s) : string +"Escapes all HTML tags (but not entities) from text"; + +function builtin clean_url (string s) : string +"Returns the given URL back if it's a valid URL."; + +function builtin rand (int high) : int +"Returns a random integer between 1 and \$high, inclusive."; + +function builtin rand (int low, int high) : int +"Returns a random integer between \$low and \$high, inclusive."; + +function builtin alternate (string a, string b) : string +"With each call, this function will alternate between the two values and return one of them. +Useful for making tables whose rows alternate in background color."; + +function builtin zeropad (int n, int digits) : string +"Returns the number padded with zeroes so it has the amount of digits indicated."; + +function builtin zeropad (string n, int digits) : string +"Returns the number padded with zeroes so it has the amount of digits indicated."; + +function builtin striphtml (string s) : string +"Similar to ehtml, but the HTML tags are stripped rather than escaped."; + +function builtin viewer_logged_in() : bool +"Returns true if the user viewing the page is logged in. It's recommended that your page links to the site +login page if the user isn't logged in."; + +function builtin viewer_is_owner() : bool +"Returns true if the user viewing the page is both logged in, and is the owner of the content in question. +Useful for returning links to manage information, or edit entries."; + +function builtin get_page () : Page +"Gets the top-level [class[Page]] instance that LiveJournal ran the [method[Page.print()]] method on."; + +function builtin get_url(string user, string view) : string +"Returns a URL to the specified view for the specified user. Views use the same names as elsewhere. (recent, friends, archive, month, userinfo)"; + +function builtin get_url(UserLite user, string view) : string +"Returns a URL to the specified view for the specified user. Views use the same names as elsewhere. (recent, friends, archive, month, userinfo)"; + +function builtin string(int i) : string +"Return the given integer as a string"; + +function builtin int(string s) : int +"Convert the string to an integer and return"; + +function builtin set_content_type(string text) +"Set the HTTP Content-type response header (for example, if outputting XML). Must be called before printing any data."; + +function builtin get_plural_phrase(int n, string prop) : string +"Picks the phrase with the proper plural form from those in the property \$prop, passing \$n to [function[lang_map_plural(int)]] to get the proper form for the current language, and then substituting the # character with \$n. Also, returned string is HTML-escaped."; + +function builtin weekdays() : int[] +"Integers representing the days of the week. This will start on Monday (2) or Sunday (1) depending on the property setting for start-of-week and go to Sunday (1) or Saturday (7)"; + +function builtin PalItem(int index, Color c) : PalItem +"Convenience constructor to make populating an array of PalItems (like in [function[palimg_modify]]) easy."; + +function builtin palimg_modify(string filename, PalItem[] items) : string +"Return a URL to the specified filename (relative to the palimg root) with its palette table altered, once for each provided [class[PalItem]]. Restrictions: only 7 palette entries may be modified, and the PalItem indexes must be 0-15."; + +function builtin palimg_tint(string filename, Color bright) : string + "Return a URL to the specified filename (relative to the palimg root) with its palette table tinted. The given 'bright' color will be the new white, and darkest color remains black."; + +function builtin palimg_tint(string filename, Color bright, Color dark) : string + "Return a URL to the specified filename (relative to the palimg root) with its palette table tinted. The given 'bright' color will be the new white, and the given 'dark' color is the new black."; + +function builtin palimg_gradient(string filename, PalItem start, PalItem end) : string + "Return a URL to the specified filename (relative to the palimg root) with its palette table made into a gradient. All palette entries between the inclusive indexes of \$start and \$end will fade from the colors in \$start and \$end. The palette indexes for the start and end can be between 0 and 255."; + +function builtin set_handler(string eventname, string[][] commands); + +function builtin userlite_base_url(UserLite ul) : string; +function builtin userlite_as_string(UserLite ul) : string "Access to the LJ::ljuser function"; + +##[ properties ] + +propgroup colors = "Colors"; +propgroup fonts = "Fonts"; +propgroup presentation = "Presentation"; +propgroup other = "Other"; +propgroup text = "Text"; + +property string lang_current { + noui = 1; + des = "Current language code. So layouts can change date/time formats more safely if they want."; +} +set lang_current = "en"; # core is English. + +property string lang_fmt_date_short { + noui = 1; + des = "Short date format. All numeric."; +} +set lang_fmt_date_short = "%%m%%/%%d%%/%%yy%%"; + +property string lang_fmt_date_med { + noui = 1; + des = "Medium date format. Abbreviated month name, no day of the week."; +} +set lang_fmt_date_med = "%%mon%%. %%dayord%%, %%yyyy%%"; + +property string lang_fmt_date_med_day { + noui = 1; + des = "Medium date format with day of week. Abbreviated month name and abbreviated day of the week."; +} +set lang_fmt_date_med_day = "%%da%%, %%mon%%. %%dayord%%, %%yyyy%%"; + +property string lang_fmt_date_long { + noui = 1; + des = "Long date format. With full month name, but no day of the week."; +} +set lang_fmt_date_long = "%%month%% %%dayord%%, %%yyyy%%"; + +property string lang_fmt_date_long_day { + noui = 1; + des = "Long date format. With full month name and full day of the week."; +} +set lang_fmt_date_long_day = "%%day%%, %%month%% %%dayord%%, %%yyyy%%"; + +property string lang_fmt_time_short { + noui = 1; + des = "Time format."; +} +set lang_fmt_time_short = "%%hh%%:%%min%% %%a%%m"; + +property string lang_fmt_month_short { + noui = 1; + des = "Short month format."; +} +set lang_fmt_month_short = "%%m%%/%%yy%%"; + +property string lang_fmt_month_med { + noui = 1; + des = "Medium month format."; +} +set lang_fmt_month_med = "%%mon%% %%yyyy%%"; + +property string lang_fmt_month_long { + noui = 1; + des = "Long month format."; +} +set lang_fmt_month_long = "%%month%% %%yyyy%%"; + +property string[] lang_monthname_long { + noui = 1; + des = "Months of the year. Indexed from 1 (January) to 12 (December)."; +} +set lang_monthname_long = [ "", "January", "February", "March", + "April", "May", "June", + "July", "August", "September", + "October", "November", "December" ]; + +property string[] lang_monthname_short { + noui = 1; + des = "Months of the year, in their short forms. Indexed from 1 (Jan) to 12 (Dec)."; +} +set lang_monthname_short = [ "", "Jan", "Feb", "Mar", + "Apr", "May", "Jun", + "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" ]; + +property string[] lang_dayname_long { + noui = 1; + des = "Days of the week. Indexed from 1 (Sunday) to 7 (Saturday)."; +} +set lang_dayname_long = [ "", "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" ]; + +property string[] lang_dayname_short { + noui = 1; + des = "Days of the week, in their short forms. Indexed from 1 (Sun) to 7 (Sat)."; +} +set lang_dayname_short = [ "", "Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat" ]; + +property string IMGDIR { + noui = 1; + doc_flags = "[sys]"; + des = "The base URL of the current LiveJournal site's image directory, without a trailing slash. Example: \"http://www.livejournal.com/img\"."; +} +property builtin string SITENAME { + noui = 1; + doc_flags = "[sys]"; + des = "Name of the current LiveJournal site. Example: \"LiveJournal.com\"."; +} + +property builtin string SITENAMESHORT { + noui = 1; + doc_flags = "[sys]"; + des = "Shorter name of the current LiveJournal site. Example: \"LiveJournal\"."; +} + +property builtin string SITENAMEABBREV { + noui = 1; + doc_flags = "[sys]"; + des = "Abbreviation of the current LiveJournal site. Example: \"LJ\"."; +} + +property builtin string SITEROOT { + noui = 1; + doc_flags = "[sys]"; + des = "The base URL of the current LiveJournal site, without a trailing slash. Example: \"http://www.livejournal.com\"."; +} + +property builtin string PALIMGROOT { + noui = 1; + doc_flags = "[sys]"; + des = "The base URL of palimg files, without a trailing slash. Example: \"http://www.livejournal.com/palimg\"."; +} + +property int page_recent_items { + des = "Number of journal entries to show on recent entry page"; + doc_flags = "[construct]"; + min = 1; + max = 50; +} +property int page_friends_items { + des = "Number of journal entries to show on friends page"; + doc_flags = "[construct]"; + min = 5; + max = 50; +} +set page_recent_items = 20; +set page_friends_items = 20; + +property string page_day_sortorder { + des = "Order of entries shown on a Day page"; + values = "forward|Least recent first|reverse|Most recent first"; +} +property string page_year_sortorder { + des = "Order of months shown on the year archive page"; + values = "forward|Least recent first|reverse|Most recent first"; +} +set page_day_sortorder = "forward"; +set page_year_sortorder = "forward"; + +property bool page_month_textsubjects { + des = "If set, subjects will be provided for the month view in plain text only, with HTML removed."; + doc = "If set, subjects will be provided for the [class[MonthPage]] in plain text only, with HTML removed."; +} +set page_month_textsubjects = true; + +property string text_meta_music { + des = "Text for 'Current Music'"; +} +set text_meta_music = "Current Music"; + +property string text_meta_mood { + des = "Text for 'Current Mood'"; +} +set text_meta_mood = "Current Mood"; + +property string text_post_comment { + des = "Link text to leave a comment."; + example = "Leave a comment"; +} +property string text_max_comments { + des = "Text when entry has reached a comment maximum"; + example = "Maximum comments reached"; +} +property string text_read_comments { + des = "Link text to read comments."; + format = "plurals"; + example = "1 comment // # comments"; +} +set text_post_comment = "Leave a comment"; +set text_max_comments = "Maximum comments reached"; +set text_read_comments = "1 comment // # comments"; + +property string text_post_comment_friends { + des = "Link text to leave a comment on friends view entry."; + example = "Leave a comment"; +} +property string text_read_comments_friends { + des = "Link text to read comments on a friends view entry."; + format = "plurals"; + example = "1 comment // # comments"; +} +set text_post_comment_friends = "Leave a comment"; +set text_read_comments_friends = "1 comment // # comments"; + +property string text_skiplinks_back { + des = "Text to show in a link to skip back through entries"; + maxlength = 20; + "size" = 15; + example = "Go back #"; + note = "Include a # character to insert the number of entries that will be viewable when skipping back."; +} +property string text_skiplinks_forward { + des = "Text to show in a link to skip forward through entries"; + maxlength = 20; + "size" = 15; + example = "Go forward #"; + note = "Include a # character to insert the number of entries that will be viewable when skipping forward."; +} +property string text_skiplinks_forward_words { + des = "Text to show in a link to skip forward through entries"; + maxlength = 20; + "size" = 15; + example = "Go forward"; +} +set text_skiplinks_back="Previous #"; +set text_skiplinks_forward="Next #"; + +property string text_view_recent { + des = "Text used to link to the 'Recent Entries' view."; + maxlength = 20; + "size" = 15; + example = "Recent Posts"; +} +property string text_view_friends { + des = "Text used to link to the 'Friends' view, if no custom friends title set"; + maxlength = 20; + "size" = 15; + example = "My Friends' Entries"; +} +property string text_view_friends_comm { + des = "Text used to link to the 'Friends' view for a community, if no custom friends title set"; + maxlength = 20; + "size" = 15; + example = "Members' Journals"; +} +property string text_view_friendsfriends { + des = "Title of the 'Friends of Friends' view"; + maxlength = 20; + "size" = 15; + example = "Friends of Friends"; +} +property string text_view_friends_filter { + des = "Title of a Friends page with an unnamed filter in effect"; + maxlength = 20; + "size" = 15; + example = "Friends (Custom filter)"; +} +property string text_view_friendsfriends_filter { + des = "Title of a Friends of Friends page with an unnamed filter in effect"; + maxlength = 20; + "size" = 15; + example = "Friends of Friends (Custom filter)"; +} +property string text_view_archive { + des = "Text used to link to the archive view."; + maxlength = 20; + "size" = 15; + example = "Journal Archive"; +} +property string text_view_userinfo { + des = "Text used to link to the 'User Information' view."; + maxlength = 20; + "size" = 15; + example = "My Profile"; +} +property string text_view_month { + des = "Text used to link to a list of subjects for a month."; + maxlength = 20; + "size" = 15; + example = "View Subjects"; +} +set text_view_recent = "Recent Entries"; +set text_view_friends = "Friends"; +set text_view_friends_comm = "Members"; +set text_view_friends_filter = "Friends (Custom filter)"; +set text_view_friendsfriends = "Friends of Friends"; +set text_view_friendsfriends_filter = "Friends of Friends (Custom filter)"; +set text_view_archive = "Archive"; +set text_view_userinfo = "User Info"; +set text_view_month = "View Subjects"; + +property string text_nosubject { + des = "Text to replace a subject line when no subject is specified"; + maxlength = 20; + size = 10; + example = "No Subject"; + note = "This only appears in places where a subject line is required, such as on a month view."; +} +set text_nosubject = "(no subject)"; + +property string text_noentries_recent { + des = "Text to display when there are no entries on the recent or friends views"; + maxlength = 255; + size = 50; +} +set text_noentries_recent = "There are no entries to display."; + +property string text_noentries_day { + des = "Text to display when there are no entries on the day view"; + maxlength = 255; + size = 50; +} +set text_noentries_day = "There were no entries on this day."; + +property string text_permalink { + des = "Text for a entry's permanent link"; + maxlength = 50; + size = 20; +} +set text_permalink = "Link"; + +property string text_month_screened_comments { + des = "Text to indicate there are screened comments."; +} +set text_month_screened_comments = "w/ Screened"; + +property string text_multiform_check { + des = "Text beside a comment multi-action checkbox."; +} +set text_multiform_check = "Select:"; + +property string text_multiform_des { + des = "Text on the multiform action line."; +} +set text_multiform_des = "Mass action on selected comments:"; + +property string text_multiform_btn { + des = "Text on the multiform action button."; +} +set text_multiform_btn = "Perform Action"; + +property string text_multiform_opt_unscreen { + des = "Text for the comment unscreening action"; +} +set text_multiform_opt_unscreen = "Unscreen"; + +property string text_multiform_opt_screen { + des = "Text for the comment screening action"; +} +set text_multiform_opt_screen = "Screen"; + +property string text_multiform_opt_unfreeze { + des = "Text for the comment unfreezing action"; +} +set text_multiform_opt_unfreeze = "Unfreeze"; + +property string text_multiform_opt_freeze { + des = "Text for the comment freezing action"; +} +set text_multiform_opt_freeze = "Freeze"; + +property string text_multiform_opt_delete { + des = "Text for the comment delete action"; +} +set text_multiform_opt_delete = "Delete"; + +property string text_multiform_conf_delete { + des = "Text for the confirming mass-delete action"; +} +set text_multiform_conf_delete = "Delete selected comments?"; + +property string text_tags { + des = "Text for 'Tags' header, use a # where you want the tag list inserted."; + example = "Tags: #"; +} +set text_tags = "Tags: #"; + +property string font_base { + des = "Preferred Font"; + maxlength = 25; + "size" = 10; + example = "Arial"; + note = "Leave blank if you don't care."; +} +set font_base = ""; # In core, default is not to care. Layouts will probably specify fonts the author likes instead. + +property string font_fallback { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; +} +set font_fallback = "none"; # Default in core is to let the browser handle it. + +property string reg_firstdayofweek { + des = "The day of the week the calendar weeks starts on."; + doc = "The day of the week the calendar weeks starts on. Either 'sunday' or 'monday'."; + doc_flags = "[construct]"; + values = "sunday|Sunday|monday|Monday"; +} +set reg_firstdayofweek = "sunday"; + +property string text_day_prev { + des = "Text to link to the previous day"; + example = "Previous Day"; + maxlength = 20; +} +property string text_day_next { + des = "Text to link to the next day"; + example = "Next Day"; + maxlength = 20; +} +set text_day_prev = "Previous Day"; +set text_day_next = "Next Day"; + +property string text_comment_from { + des = "Text of the 'from' header in comments"; + example = "From:"; + maxlength = "20"; +} +property string text_comment_date { + des = "Text of the 'date' header in comments"; + example = "Date:"; + maxlength = "20"; +} +property string text_comment_ipaddr { + des = "Text of the 'IP Address' header in comments"; + example = "IP Address:"; + maxlength = "20"; +} +set text_comment_from = "From:"; +set text_comment_date = "Date:"; +set text_comment_ipaddr = "IP Address:"; + +property string text_comment_reply { + des = "Text to link to reply for for comment"; + example = "Reply to this"; + maxlength = "50"; +} +property string text_comment_frozen { + des = "Text to replace reply link with if comment is frozen"; + example = "Replies frozen"; + maxlength = "50"; +} +property string text_comment_parent { + des = "Text to link to parent comment of current comment"; + example = "Parent"; + maxlength = "50"; +} +property string text_comment_thread { + des = "Text to link to the thread stemming from the comment"; + example = "Thread"; + maxlength = "50"; +} +set text_comment_reply = "Reply"; +set text_comment_frozen = "Frozen"; +set text_comment_parent = "Parent"; +set text_comment_thread = "Thread"; + +property string text_poster_anonymous { + des = "The placeholder used when something is posted by an anonymous user"; + example = "(Anonymous)"; +} +set text_poster_anonymous = "(Anonymous)"; + +property string text_reply_back { + des = "Text to link back to the single entry view from the read comments page"; + example = "Read Comments"; + maxlength = "50"; +} +set text_reply_back = "Read Comments"; + +property string text_reply_nocomments_header { + des = "Heading text that explains that comments are disabled"; + example = "Comments Disabled:"; + maxlength = "50"; +} +set text_reply_nocomments_header = "Comments Disabled:"; + +property string text_reply_nocomments { + des = "Text that explains that comments are not allowed for this post."; + example = "Comments have been disabled for this post."; + maxlength = "100"; +} +set text_reply_nocomments = "Comments have been disabled for this post."; + +property string text_website_default_name { + des = "If an account's website is specified, but there's no website name, use this text instead"; + noui = 1; +} +set text_website_default_name = "My Website"; + +property string text_icon_alt_protected { + des = "Alternative text for icons of protected entries"; + noui = 1; +} +property string text_icon_alt_private { + des = "Alternative text for icons of protected entries"; + noui = 1; +} +set text_icon_alt_protected = "[protected post]"; +set text_icon_alt_private = "[private post]"; + +property bool use_shared_pic { + des = "Use shared journal user pictures instead of poster's user picture."; +} +set use_shared_pic = false; + +property bool view_entry_disabled { + des = "Enable to use the old comment page instead of the newer style specific view"; +} +set view_entry_disabled = false; + +property bool tags_aware { + des = "When enabled, style is responsible for handling tags. When disabled, tags are automatically inserted into entry bodies."; + noui = 1; +} +set tags_aware = false; + +property Color color_comment_bar { + des = "Color of comment bar header"; +} +set color_comment_bar = "#d0d0ff"; + +property string comment_userpic_style { + des = "Userpic display style for comments"; + doc = "Userpic display style for comments. Either '' for full, 'small' for small, or 'off' for none."; + doc_flags = "[construct]"; + values = "|Full|small|Small|off|Off"; +} +set comment_userpic_style = ""; + +property bool linklist_support { + des = "Link List Support"; + note = "If you've created a list of links that you would like to include in this layout, change this option to 'yes'."; +} +set linklist_support = true; + +property bool external_stylesheet { + des = "Use linked stylesheet"; + note = "If true, a stylesheet link element will point to a file containing the layout's CSS data."; + noui = 1; +} +set external_stylesheet = false; + +###[ global function implementations ] + +function prop_init () + "This function is the first thing called and is the place to set properties based on the values of other properties. It's called before the style system looks at its builtin properties, so if you need to conditionally setup something based on your own custom properties, do it here. You can't print from this function." +{ + # do nothing, just exist. +} + +function print_stylesheet () + "Prints a stylesheet, the URL of which can be referenced by [member[Page.stylesheet_url]]. This is another S2 entry point, in addition to [method[Page.print()]]." { +} + +function builtin htmlattr(string name, string value) : string +"If the value isn't blank, return in HTML attribute format with a leading space. HTML of name is not escaped."; + +function builtin htmlattr(string name, int value) : string +"If the value isn't blank, return in HTML attribute format with a leading space. HTML of name is not escaped."; + +### Language + +function lang_map_plural (int n) : int { + if ($n == 1) { return 0; } # singular + return 1; # plural +} + +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "Page $pg of $pgs"; +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" wrote"; + } + else { + return "An anonymous user wrote"; + } +} + +function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the data and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." { + return "on " + $d->date_format("long") + " at " + $d->time_format(); +} + +function lang_ordinal(int num) [notags] : string +"Make an ordinal number from a cardinal number" +{ + if ($num % 100 >= 4 and $num % 100 <= 20) { return $num+"th"; } + if ($num % 10 == 1) { return $num+"st"; } + if ($num % 10 == 2) { return $num+"nd"; } + if ($num % 10 == 3) { return $num+"rd"; } + return $num+"th"; +} + +function lang_ordinal(string num) [notags, fixed] : string +"Make an ordinal number from a cardinal number. Don't override this, since the core layer implementation just calls [func[lang_ordinal(int)]], which i18nc layers should override." +{ + return lang_ordinal(int($num)); +} + + +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Day"; } + if ($viewid == "month") { return "Month"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Read Comments"; } + if ($viewid == "reply") { return "Post Comment"; } + return "Unknown View"; +} + +### Navigation + + +### Image Manipulation + +function Image::as_string(string{} opts) [fixed] : string { + var string img = ""; + if ($opts{"href"} != "") { $img = $img + ""; } + $img = $img + $this->as_string($opts{"alt"}); + if ($opts{"href"} != "") { $img = $img + ""; } + + return $img; +} + +function Image::as_string(string alttext) [fixed] : string { + return "\"""; +} + +function Image::as_string() [fixed] : string { + return $this->as_string($this.alttext); +} + +function Image::print (string{} opts) +{ + # must do safe here because opts could have the 'a_attr' key set + print safe $this->as_string($opts); +} + +function Image::print (string alttext) +{ + print $this->as_string($alttext); +} + +function Image::print +{ + print $this->as_string($this.alttext); +} + +function userinfoicon(UserLite user) : Image { + var Image uimage; + $uimage.width = 16; + $uimage.height = 16; + + if ($user.journal_type == "C") { + $uimage->set_url("$*IMGDIR/community.gif"); + } elseif ($user.journal_type == "Y") { + $uimage->set_url("$*IMGDIR/syndicated.gif"); + } elseif ($user.journal_type == "N") { + $uimage->set_url("$*IMGDIR/newsinfo.gif"); + } else { + $uimage->set_url("$*IMGDIR/userinfo.gif"); + $uimage.width = 17; + $uimage.height = 17; + } + return $uimage; +} + +### UserLite functions + +function UserLite::base_url() [fixed] : string { + return userlite_base_url($this); +} + +function UserLite::tag_manage_url() [fixed] : string { + return "$*SITEROOT/manage/tags.bml?authas=$.username"; +} + +function UserLite::as_string() [fixed] : string { + return userlite_as_string($this); +} + +function UserLite::print() { + print $this->as_string(); +} + +function Friend::print() { + print $this->as_string(); +} + +### Generic Page Functions + +function Page::view_title() [notags] : string { + return lang_viewname($.view); +} +function FriendsPage::view_title() : string { + if ($.friends_mode == "") { + if ($.filter_active) { + if ($.filter_name != "") { + if ($.friends_title != "") { + return $.friends_title+" ("+$.filter_name+")"; + } else { + return $*text_view_friends+" ("+$.filter_name+")"; + } + } else { + return $*text_view_friends_filter; + } + } else { + if ($.friends_title != "") { + return $.friends_title; + } elseif ($.journal.journal_type == "C") { + return $*text_view_friends_comm; + } else { + return $*text_view_friends; + } + } + } + elseif ($.friends_mode == "friendsfriends") { + if ($.filter_active) { + if ($.filter_name != "") { + return $*text_view_friendsfriends+" ("+$.filter_name+")"; + } + else { + return $*text_view_friendsfriends_filter; + } + } + else { + return $*text_view_friendsfriends; + } + } + else { + return "Unknown Friends View"; + } +} +function DayPage::view_title : string { + return $.date->date_format("long"); +} +function YearPage::view_title() : string { + return string($.year); +} +function EntryPage::view_title() : string { + return $.entry.subject ? $.entry->get_plain_subject() : ""; +} +function ReplyPage::view_title() : string { + return "Post a comment"; +} +function Page::title() [notags] : string { + var string title = $.global_title; + if ($title == "") { + $title = $.journal.name; + } + if ($.view != "recent") { + $title = $title + " - " + $this->view_title(); + } + if ($.view == "friends") { + $title = $this->view_title(); + } + return $title; +} + +function server_sig() { + """Powered by $*SITENAME"""; +} + +function Page::print() { + "\n\n"+$this->title()+"\n"; + + if ($*font_base != "" or $*font_fallback != "none") { +"""\n"; + } + + $this->print_head(); + "\n\n"; + if (defined $.journal.default_pic and + $.view != "entry" and + $.view != "reply") { + $.journal.default_pic->print(); + } + print "

    " + $this->title() + "

    \n"; + + $this->print_body(); + """\n
    """; + server_sig(); + """
    \n"""; +} + +function Page::print_body() { + """

    No Default Renderer

    There is no body renderer for viewtype $.view defined.

    """; +} + +function Page::print_head() { + print $.head_content; + $this->print_custom_head(); +} + +function Page::print_custom_head() { + # blank +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + "$l.title"; + } else { + "$l.title"; + } + } + "
    "; + } +} + +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " posting in "; + $e.journal->print(); + } +} +function Page::print_entry(Entry e) { + ## For most styles, this will be overridden by FriendsPage::print_entry and such. + """
    \n"""; + "

    $e.security_icon $e.subject

    \n"; + if ($.view == "friends" or $e.poster.username != $e.journal.username) { + "
    "; $this->print_entry_poster($e); "
    "; + } + """
    \n$e.text\n
    \n"""; + $e->print_metadata(); + if ($e.comments.enabled) { + $e.comments->print(); + } + "
    \n\n"; +} +function FriendsPage::print_entry(Entry e) { + ## For most styles, this will be overridden by FriendsPage::print_entry and such. + """
    \n"""; + var Color bg; + var Color fg; + $bg = $.friends{$e.journal.username}.bgcolor; + $fg = $.friends{$e.journal.username}.fgcolor; + "

    "; + $this->print_entry_poster($e); + "$e.security_icon $e.subject"; + "

    \n"; + """
    """; $this->print_entry_poster($e); "
    "; + """
    \n$e.text\n
    \n"""; + $e->print_metadata(); + if ($e.comments.enabled) { + $e.comments->print(); + } + "
    \n\n"; +} +function Entry::print_metadata() { + if (size $.metadata) { + """\n"; + } +} + +function Comment::print_linkbar() { + var Link link; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + " $link "; + } +} +function Entry::print_link_next() { + var Link link = $this->get_link("nav_next"); + " $link"; +} +function Entry::print_link_prev() { + var Link link = $this->get_link("nav_prev"); + "$link "; +} +function Entry::print_linkbar() { + ## There's no point in showing previous/next links on pages which show + ## multiple entries anyway, so we only print them on EntryPage and ReplyPage. + + var Page p = get_page(); + var bool show_interentry = ($p.view == "entry" or $p.view == "reply"); + if ($show_interentry) { + $this->print_link_prev(); + } + var Link link; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + " $link "; + } + if ($show_interentry) { + $this->print_link_next(); + } +} + +### RecentPage and related functions + +function RecentPage::print_body { + # Creator for both the Recent and Friends views, since they are similar + # If someone wants to do the two views differently, they can create + # FriendsPage::print_body since FriendsPage extends RecentPage. + + foreach var Entry e ($.entries) { + if ($e.end_day) { + "
    "; + } + if ($e.new_day) { + """
    \n

    """; + print $e.time->date_format("long_day"); + "

    \n"; + } + # Print the entry + $this->print_entry($e); + } +} + + +### Year view + +function YearPage::print_body { + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} +function YearPage::print_year_links() { + """
      \n"""; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """
    • $y.year
    • \n"""; + } else { + """
    • $y.year
    • \n"""; + } + } + """
    \n"""; +} +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + """\n + \n\n"""; + foreach var int d (weekdays()) { + "\n"; + } + "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """\n"""; + "
    """; + print $m->month_format(); + """
    "+$*lang_dayname_short[$d]+"
    + $*text_view_month
    "; +} + +function YearWeek::print() { + """\n"""; + if ($.pre_empty > 0) { + """ \n"""; + } + foreach var YearDay d ($.days) { + """\n"""; + """
    $d.day
    \n"""; + if ($d.num_entries > 0) { + """\n"""; + } + """\n"""; + } + if ($.post_empty > 0) { + """ \n"""; + } + ""; +} + +function MonthPage::view_title : string { + return $.date->date_format($*lang_fmt_month_long); +} + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + if ($.prev_url != "") { "[<<<]\n"; } + if (size $.months > 1) { + "\n"; + } + if ($.next_url != "") { "\n[>>>]\n"; } + "
    \n
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n"; +} + +function MonthDay::print_subjectlist() { + # Too many tables... + foreach var Entry e ($.entries) { + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + " ($*text_nosubject)"; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
    \n"; + } +} + +### Day view + +function DayPage::print_body() { + if ($.has_entries) { + "
    \n

    "; + print $.date->date_format("long"); + "

    \n"; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + "
    "; + } else { + "

    $*text_noentries_day

    "; + } + + ""; + +} + +### CommentInfo functions + +function CommentInfo::print_readlink { + var Page p = get_page(); + ""+ + get_plural_phrase($.count, $p.view == "friends" ? + "text_read_comments_friends" : "text_read_comments")+ + ""; +} +function CommentInfo::print_postlink() { + var Page p = get_page(); + if ($.maxcomments) { + "$*text_max_comments"; + } else { + ""+($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment)+""; + } +} +function CommentInfo::print() { + if (not $.enabled) { return; } + """
    \n("""; + if ($.count > 0 or $.screened) { + $this->print_readlink(); + " | "; + } + $this->print_postlink(); + ")
    "; +} + +### Link object functions + +function Link::print_button() [fixed] { + print $this->as_string(); +} + +function Link::as_string() [fixed] : string { + if ($.url == "") { return ""; } + var string ealt = ehtml($.caption); + return """$ealt"""; +} + +# Redirector + +function Redirector::start_form () +{ + "
    "; + $this->print_hiddens(); +} +function Redirector::print_hiddens () +{ + "\n"; + "\n"; + "\n"; +} +function Redirector::end_form () +{ + "
    "; +} + +### EntryPage functions + +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + var int indent = ($c.depth - 1) * 25; + "
    \n"; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + "
    "; + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment (Comment c) { + var Color barlight = $*color_comment_bar->clone(); + $barlight->lightness(($barlight->lightness() + 255) / 2); + var Color barc = $c.depth % 2 ? $*color_comment_bar : $barlight; + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + "
    "; + + ""; + + print ""; + + print ""; + + print "\n"; + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    $*text_comment_from$poster
    $*text_comment_date"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    $*text_comment_ipaddr(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + if (defined $c.subject_icon or $c.subject != "") { "

    $c.subject_icon $c.subject

    \n"; } + print "
    ($*text_permalink)
    "; + + print "
    $c.text
    \n"; + print "
    "; + if ($c.frozen) { + "($*text_comment_frozen) "; + } else { + "($*text_comment_reply) "; + } + if ($c.parent_url != "") { "($*text_comment_parent) "; } + if ($c.thread_url != "") { "($*text_comment_thread) "; } + "
    \n"; +} + +function EntryPage::print_comment_partial (Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + print "$subj - $poster"; +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + print ""; + print ""; + var string url_prev = $this->url_of($.current - 1); + if ($.current != 1) { + print ""; + } else { + print ""; + } + print ""; + } else { + print ""; + } + print "
    " + + lang_page_of_pages($.current, $.total) + ""; + print "
    <<
    <<"; + foreach var int i (1..$.total) { + if ($i == $.current) { "[$i] "; } + else { + var string url_of = $this->url_of($i); + "[$i] "; + } + } + var string url_next = $this->url_of($.current + 1); + if ($.current != $.total) { + print ">>>>
    "; +} + +function EntryPage::print_body +{ + var Entry e = $.entry; + """
    \n"""; + + ""; + if (defined $e.userpic) { + print ""; + } + print "
    $e.userpic"+lang_user_wrote($e.poster); + print "
    "+lang_at_datetime($e.time); + "
    \n"; + + print "
    "; + var Link link; + $link = $e->get_link("nav_prev"); " $link"; + $link = $e->get_link("edit_entry"); " $link"; + $link = $e->get_link("mem_add"); " $link"; + $link = $e->get_link("tell_friend"); " $link"; + $link = $e->get_link("nav_next"); " $link"; + print "
    "; + + "

    $e.security_icon $e.subject

    \n"; + + if (not $.viewing_thread) { + "
    \n$e.text\n
    \n"; + $e->print_metadata(); + "
    \n\n"; + } + + if ($.entry.comments.enabled) + { + print """
    ($*text_post_comment)"""; + if ($.comment_pages.total_subitems > 0) { + "
    "; + $.comment_pages->print(); + $this->print_multiform_start(); + $this->print_comments($.comments); + print "
    "; + print """($*text_post_comment)"""; + if ($.comment_pages.all_subitems_displayed) { print "
    "; } + $this->print_multiform_actionline(); + $this->print_multiform_end(); + $.comment_pages->print(); + } + } +} + +function ReplyPage::print_body +{ + if (not $.entry.comments.enabled) { + print "

    $*text_reply_nocomments_header/h2>

    $*text_reply_nocomments

    "; + return; + } + + ""; + if (defined $.replyto.userpic) { + print ""; + } + print "
    $.replyto.userpic"+lang_user_wrote($.replyto.poster); + print "
    "+lang_at_datetime($.replyto.time); + "
    \n"; + + print "

    $.replyto.subject

    "; + print "
    $.replyto.text
    "; + + print "\n
    \n"; + print """($*text_reply_back)"""; + $.form->print(); +} diff --git a/livejournal/bin/upgrading/s2layers/digitalmultiplex/digitalmultiplex.jpg b/livejournal/bin/upgrading/s2layers/digitalmultiplex/digitalmultiplex.jpg new file mode 100755 index 0000000000000000000000000000000000000000..9ad403a9bbcca0062664ce61168df905cf280451 GIT binary patch literal 26558 zcmd421yo$iwl3VbOVHpD+=IIZYrJs}9;6|-Yaj%7cXtWaI0^0~I5e)oHMsojbN0Uf zJMWzP?znf{JKn1v-Ce6z&FWdTR?nLAo8Nk#e_jJ%17+l805GrsfceV{@O%h(_0HAI z))N2&fCm5osxM8)089yU2U81x`L~xAm}e*;7y$ck1@5H=2mkU32af>%M?pYD_*+3l zL_$JFLPA7AK}AJDLI1}B0|y6(0FQuzh=_uLhJuEHh51sju>RKR&oA`9AN`};za2e) z1H3|pL5E?1gLwsjeFX#e3g)>NF!rK000{=><@2us^M_)HNXRItFRid}|9B1#_HXB~ z0WbQ%!oeb;pdys6!2@0);2=`rB5~kJyqV-u$0ty8{K_erkVuGZ68IBTN9{bN z;i9P(=S0IjU4-)8w1+k+FJ7vi$L&*tYa_o|K?oi1i(;?cFH<#R9=7#{OT08Fwb~d(dWQDhxED8XBlzny0w47dHNGD(a{*QKVzw)wF(CqZm%kSg zSxWI#VP!PwZEDCNSVC=cSZkD(%nVL3LueSWb)E%%m#V5Qjwloub3x#Z)|IKK#1@CV z`ePO}Mub**p9?b^;ztHury1Fj{J;rTTH+Fvl&5MU*~BlimIu+TLbwuNafsr)-A_EV``!W)Yf-`I~?ca-S7I&fj&AA6f)ODBp+4WgdXReQ`kguB`RZ^#>Fc>+4_0s;DsHAeS=QP@KiAZPBT4N!ALW7E0qFDbjKU zuU&=90^P)?iM~$>ifONCi}J{3hd)`1awaa2!anwca>12%GG=(~GCsQ@b<`SN(O^b;wXae}k8qHJhs^tJe zuR7I@C^f4}0?A2kgfU-~Wgu*-jfP@)4HY4uZ?s=CGBMjY{qFjf0juEy5)wW7V+zBY z_08x8LpX2fymS-Dg;2i~OTe{JCoiDR_(yyTcikJ6$hg|Y`bFn6cwRPF!ufxDl~A-h z-)^IlhP6wOzg#yFFK28gw?GVTJnm8|DtS>j`{CX8AtntNaiw$7M;N$8-#b`5*Z@^h zXhqF-fy=e%G0L8z1<3SEbT?@7hEBmm56zDcZ{_M#vkgV43@Kd1VPZ|I+Bfou|*V-4MD;8!Aqxjdvo!KIan^f6}kfr zVXqIj_NwxH29~lIb>5hOItKf{Pw z!lD6-1q~&zGgaD*9?dyO;Ru4RTYaE%Ce#C{82t1UABn(V|6-W0~HF>mwBxsBuMJ?I>*e_&>P zve?!}($3y)JAAWF`ur^d`~i~YSAOiBGC^+K|Lh(*_Ed%4ZU62vzrU~1th?r=n`yKZ&INR!9&Sif`P zoAu!{K<>&SXIvYK{BKztEd=;b2A4Y-H-!g(mR(L+BC(m zU%+g~X+zf9?-oqx4F!(oHma1k?~5+owG-UzV?5c=RMsy1l{IL;zAm4rtl-FQc4vg8 zS1_xOSI5!Bb3ZKnOyUV4+bXhQf2&0hOkGPKey?5_9zHcR&btyRmU8OVD0M$i$UCV;bmy7r%FB(ywirM(BCo6mKVq<5*0bQ2htR9$*ZQlGzl-L&niyB#DH= z94IIrIGj)zxS;2~dLUngcTN;leH-^AG}HSE{90_*LPx|j(y_gfX$9t^Vj=L#1;81K|SBm z#9dv+*kCH4f_&7-Mq(kH{rK=YbVr5AfWlG5daCBr2{?JmZ=(IzE^auwdqPLkY0O?k zUAH&;df2g6W9P@ynWmIw@I=*P-{q~66oG6 zAL*Dsv92-Q|E)~xEReC>v@vQ4=3@L%79 zMVi%C6-(cGB&WFX5)b^HG>x^>A|@O9L>^1&YvBraTdneQ{TUEih)nT6Dpfn|YU^j} zn1)`^mh6&z_H!w=`A{av@FQ=06-LP0Sd9uDgJ@A=@lQ%ISDAiNc7oXj!hv*40j4s7 zL75oT;ij>uiG@)#A+X|V1~jmI+V3jZ;O<@}&LR|6P13Ts)BQh$l7<7lU=|Oq8N#_Q0c`>=O~tQL&2Q z$cA&0r_36;<*XVB{7pP)m-;F`E8G_6;VE~-r2UXX2;KV=6Q?d{qbYt~QOcE3T^B~A zu;Q3$5L+$jD&uXA7fW<0o?Hw$X~}}3&H;#Mkh6>+2JUQ7dwlAjaBiK3rQMVtT9yMkT!ySittK?m_=*e>3d2sHmFJL1W7Rk$KAgdh0|NiexXGluL-(T6?fsJm7i9fPu5 zttB(<%49FXK|s`yu^XeJhOd@3Rn5|adsja{(0-lPN(YJ~+r6`RU*7$20zwev=EfV!wNXDeTWJ8&CaD>sf8v}AUEzJr>WwlQgI-Do_YB@VC z6p{|V8)?Mv60L5lWq)Kmg5j~sWc<^&d{Me)fBe^*acc58G9@#dU4%DniM1Bj8VXCv ze@Hm>s!G^+A%rr4#x3d^A6)OMd1h|M9dN66FS5mcx7)992O=b%)PJ5I%G)xhmrYrD z!vr_Zj!%(VTHaYK5NKjj@9gr)o;wiU=$`*5^wwwZYqG8$sfAxzI9^E8nky`?s?&MylD+A(0I<`D~8jPsFJP-0?XKrDZNw=|_hti$1buyyL!pJ@oG@_HtD9y=dsq%bwi~r5_u~XL5WSdv4sH5_wm@VvR2_D-{r8$ z?nU1l>n-`y^&AW0kU5SjYL-dB0VTr|2JRj=nnfF!s0T zCCdc`iEdcz1?n)}QcGTLH=hx)0+nyfadz|nyyxQ0?NU8m4s3_FK^}X7qVE0`?9YJk z(`UeSKlL*pCC!i-(a-OY#b&-W-!tF=IgZzwWPlh2MiMi>SVIBytw7(bu&1YSi?IGg!3uFR__ zC3C&fn$-~-fLj*O#V$4xunrmV6O3&@!ogFn_vKZ=BhmH~r0u2gTdnml*3(Ow&JzX>8Td zu&3A3^v-K%-Jyl&jkBYUJ|_3ZY!QDlR6lH1H3X1YCV!I*3UmhfN{lg#?~7@fN`H#e zR-i@1r)+#fjZrRDVLdy*IvH(>7Z4JQ$72wYxIc-L%h|c;%CmIVLv1NS_IcK_CDDLS z0QC!M!t!L@(QTmogUV|kbteQEE}@e0{mB**2_>q}d9<_8@FLdVt*0lVx@pJ z7{js4AFu6l)b83a;nCv-b@s^&lKPT9BYSSgLf{nJ4OQTC^;2{CgR^H?1ql$1c%K3L z8f60fX2lZ&&g2J5?kU7B+#5y?x}F82t&^+6@+g}9flj&NWZu}9L$4z>A`|F%c-ht!QTL+__3l9`TIuU|3TZa-CGl&#h+!P6K5 zS9Lxjb@qNYBpX0gOfpQDyQ%uANO#e_^H#T`hRukCAtn5kNPq{G=?L&U0+VFIM^LT= z{zm)GwL=@k#(~!6++Xog_Q#Xq(F{SwHquJx=Wl)Hd<66!Lr{+;KW}`P60W+uyrzr{ zkqSJ~VEqdqMg&uT|Hfm|+5^|GlMmC&>h|^N1|?y#X&nu%HelhBApUD;P9?P71Dr-C z7Sj|>Pe^CL$ZEBajJJWtHXjrKL;0!q(|V03)E?^ZuDL;oReEu+FT$eUySKX67n2qF ztMfP__G9~ zYA$WuGY7S6R{t4rAwvEPSiVnq20%<1&FIrbRb7O$2rwktzh2r|<98pZQ zLY4_l-qG41eVN+yPTCSRIcp85QNZyYclPzuxvca7wWjiy$Z#ZKxBIAcGk_ z8m~H9r(g}TCpZn#ai)S7b`iz%(Ov{LQox`R(vYmoob#1jWC@ry~bnGkKMg( zfsocmA}=hZ--L{ft+t<`H@D6GpdHt_MOSGP6jK(R7+?xxp9l5`INtZnXt)#C7P6qJ zZ@tJN?8{fvVP$0(`3zX7aN6VxRn%F2Eoc9|$MU>|kw1CGT9I{dM?Vj8YkL+?F1JJX zV3%wAON{;S(wnT+BzUdadjhNU$GQ5Pb0+&*^rK;c_&>yEaM~-ctv#2h=WiqhS3rrm zz4^H#DHi>cge6h2jYZ$DLHwUg*^k@_W`DC=hcECEbvp+VfYJrlp^xw51Rz_-I%;_= z^zGjQHlt|aW%ad86wnw+yHi*?wBPiet^ew(I^!wOT&#y6nde;4pS=5+zD|_5x0E?@ zGcQ`)EB?W%cbb}&K+iCZhIK~5LM%JHh$<07h2c!I5%s~X1Z^AFy29k4eYxl09yu?;BZ3#Y)phb{h4(6?&^(? z*l-hClCN<6dJdK{&4;BOJ0TTY2L>X1#ia!obNS>jC6N_lU&Xvvn)qtz3ayo)KC%Q3 zPPGLCeN!XnkE^zwO>+)Pg6f$#Y0hi{3JOV}%VhBEutiojQhLIPf9>3>G@W&p+hl*4 zoB-`N3$+@h|9hm*STip5xEC{m@9uE_CDBo=kzRb|Ue;v=@w?T>uT7C6-_dwm&R-h@ zvvOdc3+Q1N#%hiobp=7Zqe|LjHP%z?j+u0M3(pA@4imUc#F{uTU2!pBsiH3`d^2sU zS!HwA0b@6?o7!+m1yUu9CmB?g|PX8tylGV+q00$fDItoCg$1e#3BJwy z)!R3vQ75f;=9o|GK#2{h{OT`TP+??QF?wVCRENR1-1c*t5~rY@j}qX2d8lO4_5q{| zY}1vvs5$&~r45&EMRqvL<@Vm4%Z@J_x?qX3slwZn{-Z(Q{iZTyLXo^EIpti?ZFu5p zag|%quaykV9;G`@>oeKOcEtXuVrZo3)bYf^rnOyETC-DIz5V8H&$k{k{f|bVOve%$ zNZHLdSWp9ZeinV;^^uX)cXz&ysnzQ$BLhz{-Qf%G`?f}ndcDrnY~_2e-$UcMqfn@^ zmBgT_<%apzn=Oj;?^2wmijj#`g;n(78n_l%$Til`)w>L#1xZ~}a8#RJ>BfZrV^Hx{ zotR}-5!c(smIQz5^pkMIlQIDTMie=|IuHPb96o?~`ifg)zDi5gSqN&gQh#UeP1iIg z@h{ODI9j+d`RlHETLLq);QAfiM`Ax1g9yv-pj=c~hq#w41^LuVNcYE1_RU_m&T&44 zu1CjS(S5V5sEq18&c1A)FczG)+cSWe=BG&OvN5Fo(()OA;4(z%-v3La-mD^|x$nbi z$K!;HQ9uGzY3N?jIIn(fLl_T!)8{zQRw=T`SXH;ZR~ zg@T*|%J;!Z-!~YA%2^joIug{0xEnR`YQ2hr@H{kjzNuE7kePj#?qr2C9 zRmaOtJvZcED#HIYHiw>w#Y4aH3^1wGjf%$k3!G!kKmZ0XpmfTv=2CjAbcsv8V0v(B ztL%IfU`5YuYcRwNzq}WE@rx{|`sj%plj>l}>Ii9PZfg$sF7L1UjD=xl|L=X7dnz?R z+Z*6*>B{scXSo9qVv*=MsBkscTuK76PaA|8pSS7hNMDwdwrFp|X!khO9E z>wi7Voxoww7x4=urXeL?8~jps{L6E1{!;Ybg0-eykYGQH?Sf1dq?!*4ip?@CynNqJ z(3e?lbCHhtPWfCo+yXaW^8Y0d=x#RAo%S3kn{~B&~OGw zU!I9zs(d$!Qc6&^wr%cK`;FL**>E8T`fqwgjs;;pS-wnzNZGT5SSNcYgELY&4Gp|f zozt$MAS`Uf{o-E(mVD#_E1C8NnJkLeo10D^7nBW`ANFL*n3+k{%M3hCWcq{~T3vq) zjvl1$)s>j#DtngA4;1%XUw^I3*6|a}6bGfb1E;e-&;u*wnsb9L^t&45Zg+jkk%^Zd z^JOQ5wpGPvPmXXzJy)565F!2_;x5K-HL!Ww?%%~^yAS6ER;@15_*`^q!eiJ!{iNQ_ zIxnTPb-xOu5I#wgfcrlUhOX>Q9oui>`+@&ElH&?QudPo--6`-Ds5nLuN>-d{V3&;F3 z)zQPODYuU#7g}cUxJg4pW07zp>#QVNF!LvQwU0i9G^zwQY=t{@Bpu!kT#e^9{OmIF zpHj5_^i6d#-f%=;6csk0Lct{<$x7I-mCMmagnA-Dm!3*o8mfX1wurD;WFFK2x&MmBr0cFC!zD4u~#@&?ELlof1Pji2F# zhSQ}sFyg0#+=%kyMLX;3yt68_4bCj`sQu z39WSH!XI!5F62`6)H29a${JWPSQr&!NenyHzD|jIlN>H5I}3!4ZR7P0O8V%qXZlS3 z@(f|l#tX^&kpznjdEX($VX2nGIq_@i6m<*AEC0{iQgN36)^)KMi{^6I@f)=SUr#lG zhPS;IX6V`)mr1M=XEYRJR2YGUxe@X59j+R{%rF71sb!%n83nBHv9)v5$aNs6fTxG< zNB>hits?e*YZ}4Cy;Cxv3I-$SQ6=H5BZT*)rM^XXUGG@y;bYH+-{Ay4%4S*lPlXkb z?V%8lC+JL^0iy;6Q&bkE`MrXK6U$6$OZRD9 zHC``&29$SsCU`sf=4{rbVL@7nt^HpCy*UP=+IWl_R-Xalr@%#Hr;?|a_-Vrq{E)MC zElSq#4CqpM2tU0rM9djEwzChtEm80?9*M~LXlR<>^@#LsaZ%eTW4rhT$xU?d`MP@e z;G%H<`+htxU~g5~os?E31dVru(NzggZfFARl>l`itY-1h3I8pU;#t1}W<5&bcE%(g z>iOO?y6Ir2Z+VDm6x#}wus$P-xX_jDkZzin8UXUz}aPJ)Z&9g~)tWY4x>2N|lf@ zz4%XJDJzdh5MP3dEQ-Oj=DI*ezVXW*)8<*Wp6mvKb^lfMScb}XpuB(S5$21 zLz=Hn^ed;7d}Y)8#vkQIT~U-xR}^&=O|t@az$k2C;LmtT!Bo|Pst^(s=9@Ca?oP4` zvCq)63BBZ_3S~Wm3!h16qGr*FO`i~KrLw0 zc?6%_4#U|74DYG$;;sDz_{q$HUB2$RqG6k>((bXE+N3}wVZwSRUSqR{#~Y2D!a3BU zqJI9SFDm|S?L1p{@SqJyJ?ldSHl(hsi0Lk#1XxeZ>i4LYrQdXLDWmHPCelsg44#bLbE!7K%5JK~B z%7?g*fTS=a%}9rTC5BeL#4E)TMn>qkTN;eS_^?o>qwmEK6Qem8gZfAE5KIbE> z3c$uz+p;_n5`@s-pu?=^5{t}77Fw78`VC$@3@SYCdwU_@VR2fvhMdTKTr)FQn1Pt( z`_Cl`J}}sumRF8QD*bh#SpHGmo#GA33gj)4sC0E(bwKY{0=(SZfa3()`CnAxCY$<8lG*s*~ zL59t$WQA0;Oh~EPFA=GAi@pqWCL%c*`)uTV>ye%Om7%(Ua{lxUd$#}`-PR5fTfu zWt;rS7=0Mo$;%v*7j!<1P3~GymRm(*GnschmvoWQCaATtS<}Hp5*97LdqsY-oqo&= z%=CRNCOfI}gK&Y}U##m)ej)98)52L**LunF{o9}x^xTDB!F(8IyO=gdGh?1-z`H7l z%M4BBscP*5^+H_R1*$jiZ0%0Tk!)e-4>E<2Nm8xZ$cN8w-X&X&jt=UJXRk*D9fm^f z+z1VgSsUn^_G?U9Hdkh6+{$oCplX58v?ZZfnNteh?QQsmC=OSoQT`pF8!56OGK z?%9wFPf~DCA+s<3*1QM{S|f`!W0DSkQsFXYsUwB^cP+bPmlOTo9%YKWK^qOy z?WgGV?J)tAmcz`2XybM{&t_@+`0h0@Usp!*rX zaeOS$$OJ7YggAU&cn0wLpG~~_sqn?Qu(`xgeSD{czlc4};wyqYQhjZ|C;*9E%ooVS zo_Y-m0p2^jWNW6T69t)bPFY2ZYX^)fk0mSy1S&uUn^8+=c6I0qINYc7^YY{%7-G&G~5>M*k0!chu{BeCO9)0q;iWiGz)&E4Yhs@{yGbon@Sw9yw<*axI zrJN0O98Nd6s)?M-Qkh~5z5={Qxk%EqGHLurxn+?sK^X!mU%7$N*JY8Bw#YV|Jc9}j zd7lsC@hUFJ^sxDvcIISJubOVdK#-ctBU@#o3Sp88ho{Bj8_6d-CHu&JI@;(YGY&-) zVr})@RQ?vQ_(0u;E(VjM4<6OGsZy}AM^P?8Hie@+etpY@{<6FOl!&$xgw16DMXBgv zUf5T$&+Ux-Y`&@f2K+TZ0r%QX(2P0x;z-H0-}EeTgMgTUmZn1e7wo3mY{pWl@rWlY z^aZ~@XgWA9dJSDy$=Q#y|+3J#m^EEC1z4-%uoe-*|D7>VEJ0n4#`g zJ`%c;ZM!d;wC-lzSofRd=e5;Kj<8>8%%M4z#h%TIf#F+>Wtx);OTNP1nSHcP3^xDA zuH_o8^Q+B;y6P%DE!>fmVobu6nGaBKS6kp(PSdKY`-GeYiaN5;R(mKRYD@tMX<{gf$y7p7@0WS!-4vO5$7zb_GpLnrz+`g zr+CfEif&EsgyXsL!%2M}xvlG{4k+K{w<}*TasIy|7~vrT{|>Rvvh)w2SdG@-aX-Me z5R3)=2RwxQW2x6XI|U+Cj{P1IzNIGi!ClLEdE*Qcs;!b$Wm@aUb80w_K7La@gGrc* z_9f;CqC#KwtO zDXN_!mc#h?Zru{jVTP#96f?^@b`jQn<80?#(GQ0zYQojHq=4%P|h@pe3Ec%Zo>HF}P;XnYtO)9?xUviz`D_d5j9$}sCww`oWA3M(pN$UG?O+O8b6@geZnh&_5|{`F_8ht`zG{O!A~t#e{@8I850IVu!u=>xi7 zSdN%Ri}CrGxi(qHbM58!$E_MI_U*V1C=)8@yBNyoNj9f~M)Ps7MoZu2``#WJnElYz zK%Q7lhw8~BR&QklUfU+D+O1mo-Md>a=oZha|6-|7qKg{j-_&RJ;h&tIit0}+UXox0 z$$ieimc_P}-;u5t&ZOUBeFl_{+(~t6D&oR*ZHayPTb)w;j3WMj{z?%@Fu9zV&ezCOLzgCDhDoShxj&1BjxaJOPYN zY+Cwc!8M{c9M`)i%T1?psc;WE5qr3(FW{k2x?|!G$Tngt6@`_>!oBfN*rQxx0-f zE><%Ul@@d9c<#O&B8%xVQ}Zu2pu^*2=nUCAMjHferG!mXWLa5g#@ENOz&?9qr#eT| z?RlKnF^mIxz9=+NY?Kv&>o@!$lwixY|Bhw(cNWoo<@3->wBBg#r#^`j{Ek7Pn(;mE zL<@0P;~^7K1S8jgJoxc930Nsws z1gPP=qIjoLU9vA_{G}jXAO5-*p#60b?~*H|=n|h-->704xmguJ5mks6WIN+v=e`f= za6g<>(c)D>!qjl|^i_|LMwvp#u#`F9`(%k@dPrBO;HC<0&Zki}%`civY9H=N7e1N{ z-fvCuBP%CE^{8R^ZF8(Aueje}6Ul6Wd%9_bT`>^&X{m&o5lL+7R=PQCLA7^A@H1W8 z@@74L5$h~5vwCzHO(AQq0YLLRO#ohqR_C?F79;NgR1w%eK7sZ^TX>sOz!RY*1Dy83 zY=h9gaa-*kbs%-b7!Dq(+8BguE0Txj1=QA(`8QqNM-2GLlg^ zNW>)c?4C`2*U&v?6Ams+j1Q%5O45lQM{GzV7(H)t;Hv$YcH?nTd+nxxLI3))(VS9n zDGWJrX~48tFkK-JPLFt}V1QO$&x5`Px_CO_42G6zns1P!QVEPqVWCs)fUZrlQmkE0 z-aDY9D?Z2(ReIyh?&A{J-jS20;QiE$*WxZM0V&-Se(G-V9q*ZME3h7T(`PL+@|(HN zpTK`I>4qtcPIkI_=t1`x0MuS945I+G(Vtm8G8zZP)A#}pbNX^Fi(aV8asMX3_~zg3 zpXy>}83Ayjq~D0XswTYV2fd3EAzCP2t9T=EM0RB0e^?j>S0KcXL8VJ6GJaL@@$eM% zE~YFi<7R=PsA37yB98;~Vy&B&R~=-?p0r@dc~K$sze~4&XD&(=V7pB635Pcy_k5Ts z6Wv2Z_nbdT=!th!okd9?QUB%mXpN=)$8eA~t-P{ys(gRzmMk^@MT_AF1=i*uSY43( zoNF{6AaK1pk3N%gS+85NXV8fG6~sxGr-z+;u>cWgI!f{^@tZ=(Hvkng8qB*Om;C*j zJhxSrlVb%u1iH|w;kXrF6NrG4 z@Yi95kXrKvnA+OJh(u<{=W4=f=&g6#zERY1_Y`4rGKc6f*Xx(3H!l0>RJ^|Odqr0F ztTZ1TH9Nhov3&cAYq9(|4`E8_1KUTsPJLRrj^J7>w*COcYnQ^f1QbB+ze!v-|G@vr zOHzoqUANBk1J*$Ptof!L%K@%CfQOU%fVG}6B@=eLft5+K0}6Nj0WJMs@%ZB=c)Rv< zf&wlo{*T$Ne`F{P3+^ZhAjXbBqvZhm zr}~DcZwBL>@IO6~K$Ont@42v4GJS9!bQr~9D_#!H`=WGC20 z^Qd@dwpFIpT?mUbqmf;=pP;bf?Ix*FTF6A?=J9aHO+hYrdz3WtZuU=OcTXHpk5IRE2?=3kWTM1(##3okp+JCPzBj|X|4Pm=Vo5#ZLyJnu zDlacL=bZrcZ(Hve`<6yxg}h`%^@XzE)q#K0!j@0{7i)`i`2z?nE>B@=Vmj_mxuoBD zW)~&1j?ng?4jl;jPG74xi-(}-xA@&O+xo$cr?k2@MRoXx=0?#r0zbkKIR_vePUs(~ z1*j@zy>HJKWI49-qzfq$bNR74KVY(4tMl2(s-e4F(8f8o)JUfZ$Z5QTF9zyMjWxwl zR^?9qPO?E2)HKJ0?U0%KbmY!lb&X#+!`(@LI-;^3VWWmUnRH?ay0&X3Jo-)jF>k(V zWL_QF%}ta$G{5+>)&y80b`tnWX- zJ2#M3JLhons%j%jfNAnFPE5i-|H>i(3)>c zJCV&5dKG&OzE!ZiYwRF6*VmRmkK&kMWddcX333;YBlc)dmB#gcGAUm{ty^WgvR3)+ zVoygs7d*i(n;YHO#W;7Gu(MTrq&O&Z9B*Vz+t1BPpa!OWkHk`eun&l3LpT_@Cb4yJ zo2f|52p#)4^1~>zAoMRLhLGjxa1uZj*C(b+T>L7>FCgUQfg1##+d=;hj$6~}qi294 zPGot%`fOa{V*XvKtaB%owXqi`52mi&rvjOb{pOA%o4t5PQns-J%-NJ?bBoqAA)kRU z6}Gi}cRKywwp5LHggBdDT7gw=P%8RmSjdCv{G3(ilvh1V2anDetto zVA}rW#Tk_VzMPeMsYSL5C2yx?tYOD=6+y?7Ha0R`>6NgRI@*2gO-q_uPvT>C@xWtH?BH zXJvff%)cY$o%yQ4bjyM8y!jcR+nYRUfmaSXB5EEBZo1~7WzfsiYAmabNO+%dO0$}^ zq+VY=)9O~?BT8=-Wk!%Esg+r5hM%nImZ^MJKbF5W(ZWFS46tZjYacyI+hIMwHa@S* zQ-R)^A1(Pjd@$J-5PCgKuFgf4x|Ev7l^k1Grw_L2NRF+N|4MMj7jZ0VcyzV68qoo& zZTtRHb9PFa$yL`+Yg#~O&(MJ{^y;;pZO(`JTLSH*B}dxvES9mp&4ocTJ%wob?bc)| zV0yJJEqXCM!!aB2(LvVlj01_p#A~ z6?U@S_n9fD&_r9S`0%}R{E#nT()GtO%#_2rkANh6jFn(+yw(f1KZ0dC{9JJ{D zs{CfhNSmRgG6q)3qf!X1 zx}#7$8=smZ=bLx&=LLd|Ls-HkIJ<9?mhkrJRX0mBYP8)RPi!rUFCADWGixJjH%C&C z%Roy+bz_TdL+#Ks1JJq&`d*PTD;FtN^K{Tbb%P2ERbSb5ZvNgRP6l4-{A`C%Rtlte z>VrY88mccU*YBM$S0~%AP5wF=i0^!Nky@@LQ#s~6&&Wy$HfscLjT#x3EhPBVc;#q3 zX5ZXj8)oi#+glLPyxcyZ(htB#cRPuJ|Hl$EwMtK(bV9eZ6^Fj>$Fm%uur6Y*hWZsX~3F zVGjd|Frf~d1@ytlB`ZGjxwDICBbpRLNfkkTCQ$npdqj!akGKtT0(oR580qXtmuu!1 zv^aKUPjSIsGBlxYAEf?4xmwXRsCjX6F?l>!GM+`!!=o%$$PLlXuqM3sJ$28JyhUAd zdK?3#@J1m+vxcO;1%1CU88QJ`o=761eAME4=*rf55udv`6^aF>*hcLfH$yOArOiex z_sRppF#}5Ka=Dkns}8AndDmn8>T}Y`MWBJIUYMi=lK4&G)!8*NVXEO^W^d59zVV>= zZe!~OMgB<*Vb#K{4@!yg6*`ama2EgS@jw*P3)`o%8wM=Fzsy{PM?4o~4nwYt++xPFAVcmO(OK646MjHNQKx&MaJ;`pKvPg4mg(`#Gof zn&OH>sI=Jx|1e0k*H3Xpua2$e!b*=GA za_GFH^LH)mG&H&&W{XM@+yXR|JY(oPz{dw}R}~d*;F9zKdKC8B&Tyu<*(Qf;yOa~N zX8>*ME{EM{wyeuhrqr34g*&1U*&A?M0gidY&H!To;sW8xfl4;THK1FG^s%Ypn zZya~jONMbU6i3;gw6`+QLn3-BIUds10&@f?-%Zwlt(uoZYKnj?)qyp;Cony|-{p@G zbzFV67+C1HS9BRDP)I_!QoVzndV?F)NYz0Tq+sh=3%=QVF!6y1DIGQPR_M^DAhG%* z9h&HJQTA^@&v)sG2nAx2;;C#D5epk2mGknt+eOkw40`hG^RjI^B2mM0>J`x+X^GNH zs1_n2*|?$^cuym}PMJE|Km1ZmcjirkihIo3j7`JD#m;*e zM{Dg#8>(Gq#EJST1x1)edZJ|h{4tA>a6zkHo_D%o#^t{AT($mly-s3Bo3ceOIHuE7 zh^XH^at^!q(53O~8&6j@K7=CPEmOs}lC=1?ZcDB{`t%{v4>cApQw!BRt=(TSk2O1m z_mX^xMtYg_(||I)tI@+Dj8$uw66pMdL@kpFD$Y2GK^q#MoPx6CPhpk5lQJ`T+7CB2 z8Vx(Y-m5I#jv>vN7IfRur7jVAeg>%MzQhKVyO~~Z)k!_#rW$r!E9pd)xp0=`?TdDycC>3O*5Gi_nI$zR0 z-&>w%$2+2GY(%exca`N44R$M!RNzmt&4xa&<$pw0HWEX^JhtH;7%}5bWtR;{>tl1* zEG2Y-l*01p?L)BKTElwcmBCTp!R}j9DOjF@bX1NcK#e83OiwvUb-d<<_YC`zIBMTW z^kxwUrrpVQUG)~5=JkAEQmG1F>-&);&gp3z;rO-_H^fVi8BAgedChoQo;Z z8fuIyXzEb}lCa&lMGB3R5m&GUh8Q`_TZhZm(ECMKiGBtXD{%H-Co69_B zcfA&h@s$28qA+PFH(5Ykad>jvBKEfcAoqe`^n$PaPO06Q%@muD*%L|U)p@f_?i)0K zwC8PA)iyj8gw#~AL~9Z1_)f4xzGYHY+hNrHs1oOQivvv#X}Ubm5MD>asG?!ZPw*KM zA%3%Wxhb_*x3@=0UO96dSq4T)Ap+yKMU6tLrbUOu#v&#ZWM1M5LC>)}-UFO<|EZKS z=TVWuQ9r4IRjcLFX4E0+CAArm?d}M?+V)RQUG)<2p4GgelZmt_l1LoZs7x+^+r=u&k1Me)N*VQA6zRk^n9K`Xd*47I+q$n7Kszd07 zq4IoF7C0Ez?xNc6%@tMg12M1DVl+0)OXH^AJm&JUG&}C_5%RAzp@)54>2IBi1AW%_ z{I=#Sr>nxl@c&hE)^Aa^d%Fh#B?JWlDUpUDm5w15fuTb>l#=e0ROybPON60^j-izp zQse;!7-j~9A!G;z92$8!_WP{;?zP@^9P8LW+<(D!U)MLz^ZZ#T@*KARR*J zV(l|w;5r?+@g=)ZRdnB4TGi6rG@Gj)F)P`cTmBDs_cK@CmmqF(``RZ*pa&n zN@o+y&~{{ledZLU?74|qQOj3_B%jA^v5vXnKFxXb6>xuzCl=3MlRHu1$k`}Ot_hkW zzy9C2%O?#*TRGXWrfY?PF&)b+d&x}bqM)+Gd_PVB621VOX#9uvMV#s>3 zY$2TFdI&yEW?UD9H4c4XsN!yHaS&OvNr-*(y16JDzoqTSxo3DyKwZtjuwS;DRFzOA zmmv1Z^?+lTpTg7PsKBtPfMuu>?$5`~cJ*aRbzwKKTFm6VC(i8RR{OM^rw?nHc zpT96fL&dTs8B8LzCdlV{YrB($#w}b9X8OY$AI31BJop$Kn+NYmk8G>ws?ggZ_ik(c z6lJbMiNmRd;HA8F`GO{rK!z*ebY5$+fmwoXV{0+yH5ZwM@`EY*b`MMY%6FpQTR$zOauFIr~4(_pW?) zLPF{@#2eT3-XpEdx-7)A59%?G^N+11u3!Z~f#w5VL0XdODt?1RmRSYcp>~w|$C`)S z6(#`c0+r4^xH|&i!vqLQyhAxnNTLapK7d~J&5qj`*RS#qO`KZg4>VvdJ7LZ*?P6{V zqg>ymkF1|Z0CWFpFBouHcJCw^?qre??wJVv0>$;aXI%27o_VR!{P$$sd_PnAq)dP6PUOk;juIc_@+$(kk(OJQV z4{DFp)Vn(4CE6l#>T3l83V9hcItwGZV-=r^(*OLp9pYMh5Gc70|89mdW3dai@2m3R zt*%(76{E`oZm5E?%Ugq^A%Z1z)Av;oYd<_sM_StVcMD$_GPXVVmgF-uW^J}uo9p=h zLQwAB_H}&~$YG}A%92+a9m~{(c8lf$uwmM`3P`FbE-IkNmA=`0=?tb!8#T>#PWLAR zUI0o}ho@N19(8s~c5Z-*$4>&nM!Jwg=Dn$grm!I=)f!plS;slrHA)j{z6SFfUDZ$TZE@*XR4;rM*n1xKu`7S0i4_S8K@F-%J^8|#kNX2 zHH#>dzUaAY^CRz$!Y}L|%}1hUUVUeLZ=cLe!~>_u-I%#jIKSw1U#*v!EW)-1<7N`y z$m-8-87*N@TCjG{ar2_kYT4*4yGa;~USZF^C)KOJ;FOXyOP+gs$=FI~@s%v(i1vr~ zm1+Rl+{?*MN%|95fYCKUbs(ebA0ibg)1cEJ7zZtVFm=8%=?jS9u|-0*29N}nKigJR z*fW`OgE9MWwv5ofW6S)D66i6NHm{KjfNQ+vOt(zi)F%Ogh1v)h*ostLSyZEYmvG#I znVHy*0Mc%HL1;(xGf}i%_gK;lk#bH3eK|N=FiWCVH%ZAj>oNVR#E#UZ>5uLoqnR z^yo-*w0sYI8n`b+9VJz56Wd*5W$a$>ED|)lU$1&8|1&;~A?kQxXvAzf-b@V(p-x+x zkD1#72*Nbf_4PeXh__|?B=ZA9U+nShy!|O%GJ`T9hEng z9{D7HL_LQr$2xMjQyZW`TuKNeVBPxA-19AMseZw?6NE$xNQg*nJIwhSO+i{IOE<{a z2>I8GznsPFs3tmkNyBuY6Va&-4~}1t1MUe`7Qj`=!Nuen1{AeT%|Sl!4CyLFQP{W1 ztGWT|qz{jw(qryP<6Xf*m21NZRfnbt%GU#(nj*8vhPOvEwGvmVwvj zsKm+jO1ZqHpOQ=|Nk+QHSZvn}GO1Np7#jQjx36*ZB40`7TKNGS)zKV-Iv@Mc;+BVk zP}6VznzZAEQ@`dA)`%*NmgB3K86U7TAP}zNCZlhIVy*F!QW55MGVdBphd0yOZl8@J z9A{`-T$jg)AMBIg>ZVy6U%-^Nab~-10i3Nfk#^+;0eTPrPuKY`+6f_Nv3mqUk%Vx| z_-_P5mK!qtKcyDH{=4};THS;awV4vS&iPvuV%MdepLCtHhHw{mRF8W#C?g zE#A~5nm%w2kBgNz*>R@y)9vekBW`!C4WSr>ePb(e_2&*bPzEVT^)o-aL`&Oh_g$+K zR{aMW+BY(s57^{=aL=l(?TN@}UvjUM?FVEwi}q7G}{hMT&1CtMbH)hd~5a#}-f?)fN#(AR<%t+h-?6IHc~4~G#1Izk>V`@TreeAL9Lla)wG9oiA+ z-Ja(oTj-)t`lwC1nVB5)0KzIoaEl~z_hK{hQAZqXmO*my8T8Qbi>&pF=zD&YKtakX zGNz@|09$xmHoaMbAO>yqZHs0rNtvm~K4m4OIkI;5m}iQ&3qu8&gJnRNkMx*Ll5`pp z1f_p&Nfg_ za?9ePsJgUBWoqh(UL4W63TKvh0$EtCkNB1!EG+$9HZ}d#HG!d&p--vgg06#l!io4~ zMh+`U5kSL@nE%O~vBslz`u^9o&fmM=SV*C{=2W6nf&Q-_JK<32%8&Fgxb!g-ZJtta zclp$2U8(v;v5pQ(?H#N&qTrW&Mc$u^7Dkn+U|dqu1t|`7SY${c>!?N(@0&|q zE*oh)tujq0R1Rg6z7+==Q|F>sI&P3cyF+^?jOz_N9!m@gQe=X?Hvhh1@ovbx|9!*K zEv;fb6qo+T?rr8Y@pkO}Od0Qe&W0X{lUe%mjY^_S%&GKnjt}@$`S_j<=g0l zW&@z7BFG+NOS|&^=r&gahjIRPM6g94JNq0Z0z3nmVcL=j`x1Qo)| zaxT{ddDSunih;{n_oyV`JP&0Go$JGPQz{)U60Ql_dyv7D{FjDTv~0_gUL2AjY-$LL z;;GQQh#0e@4-g&RxxOyh^L%lygD#TEKi0PSOZH?n$)h&ys1U~vUjsl+q z?B{EE8-o0jgn2Dc=-h?CdgVM*e=>@39+?=lAJ>SxkT^=a zW6B^Ys`|CV1UIWt{L9&)!-8VQ<6|qRc^}go!;Ybi_T}7Ja`Cl;EC!Tnr@{edXY66Z zzr55pI@gpr=k+U`$)4vW?wWwo@AFTCe%FXC zlT)WVZ?i6LQXsPZgGzF94NEI$h(An(%aHK-Yl5kUU(>9gel%wve;e~P#zM>m6TE((5h*f|k@(STf!6kSU8&dmKX z_G~7DP707-bF73pe1iTXxACTfr1FTShYB)m(-sCU9gd-{i%eFv^z^v3u&QK`+{vYw z=;%D8P%R?acH68AHTR(s3yyZ?9WadOR5Cg)0*kSq9L(BDFhaU^>N`paB#~aH<7`y7 z78F=%N&YAbi_);#A&xkF(&!(hEl2S^aOE}uhDx6B-5vh>2>$6{)VB(3@VZ}=f)RgD zavT44k`wRyIPsjaGCg8a_+3bguVn6GK|(Bp!?` zr$L%0{g84Mlmt9n7vmnn5j56-rSB6!TRyFK_6k{8<4A*D%=H#o@e&H{1q4_RM zsrF$doADR?_K|+PD2+NigZcNlbm`V1@DIQXkFP-h^|YHFHdK* z`OLK4swK`GL__OW8u#VEdu<)A{F^f#(ssA0#vI3Id>8qA4}y@vLHdWm^(FGCQ?4ylhPd3J#&-4pZ zP}RbBN`)xLUKA|v0p>_T@-z1nik3$rT)G-Gxn_JBR5Se}mNiDI582HWxTnW$bL1J; z*Ewo=%7xs&P<`yvOD3`BIIolVbP43d&{^!A(8=ao7kgnDlfo-^?Z-z)5nO3(eD{^u zez6@h-4g$2Ws$bTt!HpDI(wqZfapUTx5@%5p78VLZeJrAu6Ast0!UMBN+$$iPaq;RtO%9%WBQ`Nf>K`- z&LUCE(`c)y2;J8XoNxU9LVDS^b$h3$-7pZhi1@8SCH*v@uqPuhn0FcQ?`5hJT__~2D0tjZ2X-jI-uh{E z;k|J)R5qT?GSm85cOT}Y!M$?^^)8!7WCH=kLBuBQ0{_pi>ohOTU@?d0E zbOMesf^9bdl6l40q)M_@WuN4Xs{-b7tA1 zM7v9+yonk^Ey~t11j@>jc?2FF^T1z2#==B1*(uEFC?50p4GbBvaj{dj(-bMu;z+)N z`eWPoI5l$NVQJn$flV1tzbdC3KXUI(u?fxZGjmrr2$$FwUJ41@pQ4=+FQT-fLI2o5FHuL%gV7p;Wy5>mvN zw9ndNsH4GraOxIrX>y=2YzrT1~t0Y?9uBvd2ewXk)A-F7CIf_Gj=z#@yaL zB=s7*hM)M66UcbY2=p0XkY#DZeWY`ezSNFruPG{Z(b=Dd)`AdkOan$ljOYzt>rWOT zt!=cDC=rD$UuF5=m0O9{p=h2pp74vAvgV^Hk~j8MKi@D1IzsbW==3}5fORT^9;oZVwRN0>Nh=9)k(1$=IuDnxBG z3#GTPF3-|(W>J!jr~j^PticfWX8Vtd(XJm$OQvXUdk9>UWhfAg)h20N%GOZQP#4wn zxJT_HM@eWXG*6ivl`?d8#>+G;Lw(k;{yY$zZSJuC)SsPC;2^u3;@+KJB~^KAq$P4Y zf~{&#*}3B^!5JZ>EkvSfS^lxkG+B~k{WxHnUZ%dyZTH2>#6B@kxN@C%IG#s9{}Ct= zv_(Ic1qCQm+|4Ms>G-@P^cc;;jFEM=8ymT!c~3t{V_nP~ZYERF7>so^Y!MWbV`wW( zCV8j*v#HFyeCd7PLtVMl_f;ucw&p1B(4qF<+2aN=(`B_RE)OPf)_5 zvIOh+Oasg}zbK`NHFp)X-_*G>;pcgbck_mxCBc3+z68*87ewYT)06t~(U~s;+6WVd z@HtKn7LJ&Mcn=tp4}oisG}2t9V9qW_9~;f_nXjN)VUJKn%`$+CSSu$xU5+v?=E7Uv zQ9IJL7n%KgbliXb*+e4yJ7_ZS%h~2% z$U4(wR>|IE!d5*RnazbO!(V!={{PMs8~>Lt3U$Iq8dMSx`H!!nmt{1p|9=vpswvo5pP@(cvn7){DUJ>Hnd%9O0#{wj~Ic?z|{~*5Y7cKM# z7U}w)e9H63BOS|qiFj-N5#;Kl3ZwI?FxdPjPE+P2ff0|O6&i?DfNEWr5&O2WQX`L5%RN8`t-NE_4e zklx@vlc(kv@ct>>?!qKC%;b#r4zxYHej|G$H2i4Irp1K4+gNY_S*ZIEf3(7cFKM~# za|u~4#x8eP^8J{t9G;!rbn1U()hC1_6|n7t^}2Tl1M78zhR-|tePm2Fq*j6hSIcyV zXR)q*{Un6R+q|uq!K#~BVei5`GS$SlyCVdj`Zi)}=K${$%p`*rKmIkVqyavMZp1Cz5h0(zFzh4(QNNE!Rks+p!N+-Z>V1c-mC3sUP`fnog87Gfl z`d*aC%l>vCo!F%!+ z)I1DDl#MKScoc+tns`!K*CQ=f1p`CCWXkf12f;i;l$*eS_y;f7*9f z2H*oyjVm)Tmn=|of16l2>;6n@lb#(sbfLKXVyO@CJ7=ErZhZ0iHr`|DxTO1hXK8f# z<5r-&l;8TLPw;60zr_`0=n{T!g1wRKE!d5wH*3aM?ePP@Fgd zezlaaj>I%SHt$lD!Y%LMjyo06XFV92&MR!*S%2#2QMk~b%^D(OREc@-)IBf!o#rrP z>YHADw2aj^3wcyl#Dg46+lp??InYX+$S*A5LPTsbFx8;4=WRpxN&U&F?Pa$&;_DVl zjnc9^sH=*yG{U0y8{s(KGibiV3b&tgw9{7*)Ukf}M`Uc_uyvYV^iS)>yz3lhC4G5$ zf4Ox(-|y%SXZQAMS!T`2*;|p30wpV~Li?5J2sF%UN9XuNEDODd!Ap$yzduGGZ)&*D z+-=Hl4dHI}TR3;~Pv;FK=vEuOpM`&HQp>c@%z>UGzw~I2Z(s{jK_fVPU{!FVT&myA zA$6a`gj}6P?Azp&CF5<@^&Y$mZx7kQVAWc#4j+eZo(NxsJ-yhvCV-418rCBE%hvVi zZz!&K{hzE2=iT_wZ&q(dU_NIGwST^i_HPC=L2E8WLQcD?C?-V~JOg8KKVQBr>9z~$ z@ZUEV8q*D$EgSj^IkEBUFVC#EMAf_ZJT79Mq4ro?ekv}W$**LN&IpxdVnbb5Y*;7s nm{I>&>IL}unC+d$|4lQ$c}G6pd$2$KASgfF#1s8d@f!JG@#WBm literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/digitalmultiplex/en.s2 b/livejournal/bin/upgrading/s2layers/digitalmultiplex/en.s2 new file mode 100755 index 0000000..f27c11a --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/digitalmultiplex/en.s2 @@ -0,0 +1,10 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "digitalmultiplex/en"; + +set text_meta_music = "Music"; +set text_meta_mood = "Mood"; + +set text_sidebar_link_separator = "  »  "; diff --git a/livejournal/bin/upgrading/s2layers/digitalmultiplex/layout.s2 b/livejournal/bin/upgrading/s2layers/digitalmultiplex/layout.s2 new file mode 100755 index 0000000..d3021d9 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/digitalmultiplex/layout.s2 @@ -0,0 +1,1379 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Digital Multiplex (OSWD)"; +layerinfo author_name = "Ported by Jesse Proulx"; +layerinfo author_email = "jproulx@livejournal.com"; +layerinfo redist_uniq = "digitalmultiplex/layout"; +layerinfo des = "Based on the Digital Multiplex design available from Open Source Web Designs. Originally written by Jonathan Sutherland."; +layerinfo previews = "digitalmultiplex/digitalmultiplex.jpg"; + +################################################################################ +# +# Properties +# + +propgroup colors { + ### Main / Misc + property Color page_background_color { + des = "Page background color"; + } + set page_background_color = "#dedfce"; + property Color main_bgcolor { + des = "Color for main content"; + } + set main_bgcolor = "#ffffff"; + property Color main_fgcolor { + des = "Main text color"; + } + set main_fgcolor = "#000000"; + + property Color main_link_color { + des = "Main link color"; + } + set main_link_color = "#0000ff"; + property Color main_active_link_color { + des = "Main active link color"; + noui = 1; + } + property Color main_visited_link_color { + des = "Main visited link color"; + noui = 1; + } + + property Color border_color { + des = "Border color around most areas"; + noui = 1; + } + + property Color full_entry_bgcolor { + des = "Background color for full entries"; + noui = 1; + } + property Color short_entry_meta_color { + des = "Text color for meta information on small display entries"; + noui = 1; + } + + + ### Sidebar Colors ### + property Color sidebar_bgcolor { + des = "Sidebar main background color"; + } + set sidebar_bgcolor = "#bdbabd"; + + property Color sidebar_box_bgcolor { + des = "Sidebar box background color"; + } + set sidebar_box_bgcolor = "#e2e2e2"; + property Color sidebar_box_fgcolor { + des = "Sidebar box text color"; + } + set sidebar_box_fgcolor = "#000000"; + + property Color sidebar_box_header_bgcolor { + des = "Sidebar box header background color"; + noui = 1; + } + property Color sidebar_box_header_fgcolor { + des = "Sidebar box header text color"; + noui = 1; + } + + ### Heading colors ### + property Color heading_bgcolor { + des = "Background color for heading bars"; + } + set heading_bgcolor = "#bdbabd"; + property Color heading_fgcolor { + des = "Text color for heading bars"; + } + set heading_fgcolor = "#000000"; + property Color heading_border_color { + des = "Border color around heading bars"; + noui = 1; + } + property Color heading_link_color { + des = "Heading bar link color"; + } + set heading_link_color = "#0000ff"; + property Color heading_active_link_color { + des = "Heading bar active link color"; + noui = 1; + } + property Color heading_visited_link_color { + des = "Heading bar visited link color"; + noui = 1; + } + + + ### Title colors ### + property Color title_fgcolor { + des = "Text color for main title"; + } + set title_fgcolor = "#c6c6c6"; + property Color title_bgcolor { + des = "Background color for main title"; + } + set title_bgcolor = "#ffffff"; + property Color title_speck_color { + des = "Color for the small speck next to the title"; + noui = 1; + } + + + ### Subtitle colors ### + property Color main_title_bgcolor { + des = "Background color for the view specific title"; + } + set main_title_bgcolor = "#f7df84"; + property Color main_title_fgcolor { + des = "Text color for the view specific title"; + } + set main_title_fgcolor = "#000000"; + + property Color sidebar_title_bgcolor { + des = "Background color for sidebar title"; + } + set sidebar_title_bgcolor = "#808080"; + property Color sidebar_title_fgcolor { + des = "Text color for sidebar title"; + } + set sidebar_title_fgcolor = "#000000"; + + + ### Comment Bar Colors ### + property Color comment_bar_one_bgcolor { + des = "Background color for comment bars"; + } + set comment_bar_one_bgcolor = "#bebbb6"; + property Color comment_bar_one_fgcolor { + des = "Text color on comment bars"; + } + set comment_bar_one_fgcolor = "#000000"; + + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars"; + moui = 1; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars"; + noui = 1; + } + + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + set comment_bar_screened_bgcolor = "#dddddd"; + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } + set comment_bar_screened_fgcolor = "#000000"; + + ### Server Sig ### + property Color server_sig_bgcolor { + des = "Background color for bottom server signature"; + } + set server_sig_bgcolor = "#808080"; + property Color server_sig_fgcolor { + des = "Text color for bottom server signature"; + } + set server_sig_fgcolor = "#000000"; +} +propgroup fonts { + property use font_base; + set font_base = "Georgia"; + property use font_fallback; + set font_fallback = "sans-serif"; +} +propgroup presentation { + property bool show_entry_userpic { + des = "Show the userpic on the full journal entries? [Excludes friends page]"; + } + set show_entry_userpic = true; + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + set view_entry_disabled = false; + property use use_shared_pic; + + property int leading_full_entries { + des = "Number of entries on the Recent Entries page to display in full"; + note = "Set to zero to display all recent entries in short form. Set to the same number of page items to display all recent entries in full form."; + } + set leading_full_entries = 5; + property string page_content_width { + des = "Total page width for sidebar and content"; + values = "60%|60%|70%|70%|80%|80%|90%|90%|100%|100%"; + } + set page_content_width = "60%"; +} +propgroup background { + property string page_background_image { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + set page_background_image = ""; + property string page_background_repeat { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + set page_background_repeat = "repeat"; + property string page_background_position { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + set page_background_position = "center"; + property string page_background_scrolling { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set page_background_scrolling = "scroll"; +} +propgroup sidebar { + property string sidebar_width { + des = "Sidebar width specification"; + values = "155px|Skinny|185px|Default|215px|Wide"; + } + set sidebar_width = "185px"; + property string sidebar_profile_text { + des = "Text to be added to the 'Profile' sidebar, underneath the name and user picture icon"; + } + property string sidebar_blurb { + des = "Free text to be added to the sidebar"; + note = "Appears in the sidebar 'Blurb'"; + cols = 30; + rows = 10; + } + property bool sidebar_disable_recent_summary { + des = "Disable 'Page Summary' on Recent Entries and Friends view"; + note = "This is only a temporary measure, available until we find a way to enforce a specific sidebar width."; + } + set sidebar_disable_recent_summary = false; + property string sidebar_position_one { + note = "Set to 'Nothing' to hide box"; + des = "First Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|navigation|Navigation|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_one = "summary"; + property string sidebar_position_two { + note = "Set to 'Nothing' to hide box"; + des = "Second Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|navigation|Navigation|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_two = "navigation"; + property string sidebar_position_three { + note = "Set to 'Nothing' to hide box"; + des = "Third Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|navigation|Navigation|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_three = "links"; + property string sidebar_position_four { + note = "Set to 'Nothing' to hide box"; + des = "Fourth Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|navigation|Navigation|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_four = "blurb"; + property string sidebar_position_five { + note = "Set to 'Nothing' to hide box"; + des = "Fifth Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|navigation|Navigation|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_five = "calendar"; +} +propgroup text { + property string text_sidebar_link_separator { + des = "Leading text for links in the sidebar"; + } + set text_sidebar_link_separator = ""; + property use text_meta_music; + property use text_meta_mood; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_website_default_name; + property string text_sidebar_title { + des = "Title of the sidebar"; + noui = 1; + } + property string text_sidebar_userpic { + des = "Title of the userpic sidebar box"; + noui = 1; + } + property string text_sidebar_blurb { + des = "Title of the blurb sidebar box"; + noui = 1; + } + property string text_sidebar_navigation { + des = "Title of the navigation sidebar box"; + noui = 1; + } + property string text_sidebar_summary { + des = "Title of the summary sidebar box"; + noui = 1; + } + set text_sidebar_title = "About"; + set text_sidebar_userpic = "Profile"; + set text_sidebar_blurb = "Blurb"; + set text_sidebar_navigation = "Navigation"; + set text_sidebar_summary = "Page Summary"; +} + +set tags_aware = true; + +################################################################################ +# +# Layout specific functions +# + +### Sidebar related functions ### +function sidebar_html_width : string "Return an appropriate HTML tag width for the sidebar" { + var int length = $*sidebar_width->length(); + # Percentages are fine + if ($*sidebar_width->substr($length-1, $length) == "%") { + return $*sidebar_width; + # px measurements are fine, minus the 'px' specification + } elseif ($*sidebar_width->substr($length-2, $length) == "px") { + return $*sidebar_width->substr(0, $length-2); + # Otherwise, just forget it and return nothing. + } else { + return ""; + } +} +function print_sidebar_box(string id, string body, string title) { + println """
    """; + println """
    """; +} +function Page::lay_sidebar_view_userpic() : string { + return ""; +} +function print_sidebar_userpic () { + var Page page = get_page(); + var string return; + + var Image up_img = $page.journal.default_pic; + if ($page->lay_sidebar_view_userpic() != "") { + $return = $page->lay_sidebar_view_userpic(); + } else { + if (defined $up_img) { + $return = """
    """; + } + $return = $return + $page.journal.name; + } + if ($*sidebar_profile_text) { $return = $return + "

    " + $*sidebar_profile_text + "

    "; } + print_sidebar_box("userpic",$return, $*text_sidebar_userpic); +} +function print_sidebar_blurb () { + if ($*sidebar_blurb != "") { + print_sidebar_box("blurb",$*sidebar_blurb,$*text_sidebar_blurb); + } +} +function Page::lay_sidebar_view_navigation() : string { + return ""; +} +function print_sidebar_navigation() { + var string navigation = """"""; + var Page page = get_page(); + + var string website_name = $page.journal.website_name ? $page.journal.website_name : $*text_website_default_name; + var string website; + if ($page.journal.website_url != "") { + $website = """"""; + } + + foreach var string v ($page.views_order) { + if ($v == $page.view) { + $navigation = """$navigation"; + } else { + $navigation = """$navigation"; + } + } + $navigation = $navigation + $website; + if ($page->lay_sidebar_view_navigation() != "") { + $navigation = $navigation + ""; + $navigation = $navigation + $page->lay_sidebar_view_navigation(); + } + $navigation = $navigation + "
    $*text_sidebar_link_separator$website_name
    $*text_sidebar_link_separator""" + lang_viewname($v) + "
    $*text_sidebar_link_separator""" + lang_viewname($v) + "
     
    "; + print_sidebar_box("navigation",$navigation,$*text_sidebar_navigation); +} +function print_sidebar_calendar() { + var string calendar; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """"""; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + var int num = $d.num_entries; + $calendar = $calendar + """"; + } + $calendar = $calendar + ""; + } + $calendar = $calendar + "
     """; + if ($num > 0) { + $calendar = $calendar + """$d.date.day"""; + } else { + $calendar = $calendar + $d.date.day; + } + $calendar = $calendar + "
    "; + } + if ($calendar != "") { + print_sidebar_box("calendar", $calendar, $month); + } +} +function Page::lay_sidebar_view_summary() : string { + return ""; +} +function print_sidebar_summary() { + var Page page = get_page(); + if ($page->lay_sidebar_view_summary() != "") { + var string summary = """"""; + $summary = $summary + $page->lay_sidebar_view_summary(); + $summary = $summary + "
    "; + print_sidebar_box("summary",$summary,$*text_sidebar_summary); + } +} +function print_sidebar(Page p) +{ + print_sidebar_userpic(); + if ($*sidebar_position_one != "nothing") { + if ($*sidebar_position_one == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_one == "navigation") { + print_sidebar_navigation(); + } elseif ($*sidebar_position_one == "links") { + $p->print_linklist(); + } elseif ($*sidebar_position_one == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_one == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_two != "nothing") { + if ($*sidebar_position_two == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_two == "navigation") { + print_sidebar_navigation(); + } elseif ($*sidebar_position_two == "links") { + $p->print_linklist(); + } elseif ($*sidebar_position_two == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_two == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_three != "nothing") { + if ($*sidebar_position_three == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_three == "navigation") { + print_sidebar_navigation(); + } elseif ($*sidebar_position_three == "links") { + $p->print_linklist(); + } elseif ($*sidebar_position_three == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_three == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_four != "nothing") { + if ($*sidebar_position_four == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_four == "navigation") { + print_sidebar_navigation(); + } elseif ($*sidebar_position_four == "links") { + $p->print_linklist(); + } elseif ($*sidebar_position_four == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_four == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_five != "nothing") { + if ($*sidebar_position_five == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_five == "navigation") { + print_sidebar_navigation(); + } elseif ($*sidebar_position_five == "links") { + $p->print_linklist(); + } elseif ($*sidebar_position_five == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_five == "calendar") { + print_sidebar_calendar(); + } + } +} + +function print_heading_bar(string center) +{ + println """"""; + println """
    $center
    """; +} + +function print_heading_bar(string left, string right) +{ + println """"""; + println """
    $left$right
    """; +} +function print_entry_short (Page p, Entry e, Color bgcolor, Color fgcolor) { + var string subject = $e.subject ? $e.subject : "(No Subject)"; + println """"""; + println """"""; + println """
    » $subject
    $e.text
    "; +} +function print_entry_full (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + println "
    "; + + var string time = $p.view != "day" ? $e.time->date_format("med") + " @ " : ""; + $time = $time + $e.time->time_format(); + var string subject = $e.subject; + if ($e.security) { + $subject = "$e.security_icon $subject"; + } + if ($subject) { + $subject = """$subject"""; + } + var Link prev; var Link next; + if ($p.view == "entry") { + $prev = $e->get_link("nav_prev"); + $next = $e->get_link("nav_next"); + } + print_heading_bar("$prev $subject", "$time $next"); + + println """"""; + + if (($p.view == "friends" or + $e.poster.username != $e.journal.username or + ($*show_entry_userpic and defined $e.userpic)) and $p.view != "entry") { + println """"; + } + println """
    """; + if ($p.view == "friends") { + if ($e.poster.username != $e.journal.username) { + print $e.poster->as_string() + ", posting in "; + } + print $e.journal->as_string() + "
    "; + if (defined $e.userpic) { + """"""; + } + } elseif ($e.poster.username != $e.journal.username) { + print $e.poster->as_string() + "
    "; + if (defined $e.userpic) { + """"""; + } + } elseif (defined $e.userpic and $p.view != "entry") { + """"""; + } + println "
    """; + if (not $hide_text) { + print $e.text; + if (size $e.metadata) { + """
    """; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + """
    $text: $val
    """; + } + "
    \n"; + } + if ($e.tags) { + var int tcount = 0; + "
    Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    \n"; + } + + + } + if ($p.view != "entry") { $e.comments->print(); } + println "
    "; +} + +################################################################################ +# +# Overriden functions +# + +function prop_init() { + + if ($*leading_full_entries > $*page_recent_items) { $*leading_full_entries = $*page_recent_items; } + + ### Main / Misc Colors + if($*border_color.as_string == "") { $*border_color = $*main_bgcolor->average($*main_fgcolor); } + if($*title_speck_color.as_string == "") { $*title_speck_color = $*title_bgcolor->darker(); } + if($*full_entry_bgcolor.as_string == "") { $*full_entry_bgcolor = $*main_bgcolor->darker(15); } + if($*short_entry_meta_color.as_string == "") { $*short_entry_meta_color = $*main_fgcolor->lighter(120); } + if($*main_active_link_color.as_string == "") { $*main_active_link_color = $*main_link_color->lighter(60); } + if($*main_visited_link_color.as_string == "") { $*main_visited_link_color = $*main_link_color->darker(60); } + + ### Heading Bar colors + if($*heading_border_color.as_string == "") { $*heading_border_color = $*heading_bgcolor->average($*heading_fgcolor); } + if($*heading_active_link_color.as_string == "") { $*heading_active_link_color = $*heading_link_color->lighter(60); } + if($*heading_visited_link_color.as_string == "") { $*heading_visited_link_color = $*heading_link_color->darker(60); } + + ### Sidebar colors + if($*sidebar_box_header_bgcolor.as_string == "") { $*sidebar_box_header_bgcolor = $*sidebar_box_bgcolor->darker(60); } + if($*sidebar_box_header_fgcolor.as_string == "") { $*sidebar_box_header_fgcolor = $*sidebar_box_fgcolor->darker(60); } + + ### Comment bar colors + if($*comment_bar_two_bgcolor.as_string == "") { $*comment_bar_two_bgcolor = $*comment_bar_one_bgcolor->darker(); } + if($*comment_bar_two_fgcolor.as_string == "") { $*comment_bar_two_fgcolor = $*comment_bar_one_fgcolor->darker(); } +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + var string list = ""; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + $list = $list + """"""; + } else { + $list = $list + """"""; + } + } else { + $list = $list + ""; + } + } + $list = $list + "
    $l.title
    $*text_sidebar_link_separator$l.title
     
    "; + print_sidebar_box("linklist", $list, "Links"); +} + +function print_stylesheet() { + + """ +body { + background-color: $*page_background_color; +"""; + if (clean_url($*page_background_image) != "") { + """ + background-image: url("$*page_background_image"); + background-repeat: $*page_background_repeat; + background-position: $*page_background_position; + background-attachment: $*page_background_scrolling; + """; + } + """ + font-family: $*font_base, $*font_fallback; + font-size: 100%; +} +h1 { + font-size: 2.0em; +} +p, td, blockquote { + font-size: 1.0em; +} +pre, code, kbd, tt { + font-family: monospace; +} +a { + color: $*main_link_color; +} +a:active { + color: $*main_active_link_color; +} +a:hover { + color: $*main_active_link_color; +} +a:visited { + color: $*main_visited_link_color; +} + + +/* Title */ +#top_title { + width: $*page_content_width; + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; + border: 1px solid $*border_color; +} +#journal_title { + background-color: $*title_bgcolor; + color: $*title_fgcolor; + text-align: center; +} +#speck { + background-color: $*title_speck_color; + border-right: 1px solid $*border_color; + height: 100%; + width: 21px; +} +.short_entry { + font-size: .8em; + text-align: justify; +} +.short_entry_meta { + color: $*short_entry_meta_color; +} +.full_entry { + background-color: $*full_entry_bgcolor; + padding: 10px; + width: 100%; +} +.full_entry_userpic { + font-size: .8em; + border: 1px solid $*border_color; + padding: 3px; +} +.heading_bar { + background-color: $*heading_bgcolor; + border: 1px solid $*heading_border_color; + color: $*heading_fgcolor; + margin-top: .2em; + padding: 5px; + width: 100%; +} + +.heading_bar a { + color: $*heading_link_color; +} +.heading_bar a:active { + color: $*heading_active_link_color; +} +.heading_bar a:hover { + color: $*heading_active_link_color; +} +.heading_bar a:visited { + color: $*heading_visited_link_color; +} + +/* Side bars */ +#sidebar { + background-color: $*sidebar_bgcolor; + border-right: 1px solid $*border_color; + border-top: 1px solid $*border_color; + max-width: $*sidebar_width; + text-align: center; + width: $*sidebar_width; +} +.sidebar_box { + font-size: 0.8em; + width: 100%; +} +.sidebar_box_contents { + background-color: $*sidebar_box_bgcolor; + border-bottom: 1px solid $*border_color; + border-top: 1px solid $*border_color; + color: $*sidebar_box_fgcolor; + padding: 5px; +} +.sidebar_box_header { + background-color: $*sidebar_box_header_bgcolor; + border-top: 1px solid $*border_color; + color: $*sidebar_box_header_fgcolor; + text-align: left; + padding: 5px; +} +#sidebar_userpic { + text-align: center; +} +#sidebar_navigation { + text-align: left; +} +#sidebar_linklist { + text-align: left; +} +#sidebar_blurb { + text-align: justify; +} +#sidebar_summary { + text-align: left; +} +#subtitles { + border: 1px solid $*border_color; + width: $*page_content_width; + text-align: left; +} +#sidebar_title { + background-color: $*sidebar_title_bgcolor; + border-right: 1px solid $*border_color; + color: $*sidebar_title_fgcolor; + text-align: center; + width: $*sidebar_width; +} +#main_title { + background-color: $*main_title_bgcolor; + color: $*main_title_fgcolor; + text-align: center; +} +#main { + border: 1px solid $*border_color; + width: $*page_content_width; +} +#content { + background-color: $*main_bgcolor; + border-top: 1px solid $*border_color; + color: $*main_fgcolor; + text-align: left; + width: 90%; +} +#top_of_page, #server_sig{ + background-color: $*server_sig_bgcolor; + border-top: 1px solid $*border_color; + color: $*server_sig_fgcolor; + padding: 5px; +} +#top_of_page { + width: $*sidebar_width; +} +#server_sig { + text-align: right; + width: $*page_content_width; +} +#multiform_form { + padding: 3px; +} +.calendar_day { + border-bottom: 1px solid $*border_color; + border-right: 1px solid $*border_color; + width: 14%; +} +.calendar_day .day { + font-size: .9em; +} +"""; +} + +################################################################################ +# +# Page +# + +function Page::print() { + var string title = $this->title(); + var string view_title = $this->view_title() != "" ? $this->view_title() : " "; + + println """"""; + + println ""; + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + println "$title"; + println ""; + + println """
    """; + + var string sidebar_html_width = sidebar_html_width(); + println """
     

    $title

    """; + println """"""; + println """"""; + println """"""; + + println """"; + + ### Content ### + println """"; + + println """
    $*text_sidebar_title$view_title
    """; + $this->print_body(); + println "
    Top of Page"""; + server_sig(); + println """
    """; + + println "
    "; +} + +function Page::print_entry (Entry e) +{ + print_entry_full($this, $e, null Color, null Color, false); +} + +################################################################################ +# +# RecentPage +# + +function RecentPage::print_body () +{ + var int count = 0; + foreach var Entry e ($.entries) { + $count++; + if ($count <= $*leading_full_entries) { + print_entry_full($this, $e, null Color, null Color, false); + } else { + print_entry_short($this, $e, null Color, null Color); + } + if ($count == $*leading_full_entries and $*leading_full_entries != $*page_recent_items) { print_heading_bar("Other entries"); } + } +} + +function RecentPage::lay_sidebar_view_navigation() : string { + var string return; + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.forward_url != "") { + $return = $return + """$*text_sidebar_link_separatorNext Page"""; + } + if ($.nav.backward_url != "") { + $return = $return + """$*text_sidebar_link_separatorPrevious Page"""; + } + } + return $return; +} + +function RecentPage::lay_sidebar_view_summary() : string { + var string return; + if (not $*sidebar_disable_recent_summary) { + foreach var Entry e ($.entries) { + if ($e.subject != "") { + $return = $return + """$*text_sidebar_link_separator [#] $e.subject $e.security_icon"""; + } else { + $return = $return + """$*text_sidebar_link_separator [#] $*text_nosubject $e.security_icon"""; + } + } + } + return $return; +} + +################################################################################ +# +# FriendsPage +# + +function FriendsPage::print_body () +{ + foreach var Entry e ($.entries) { + var Friend f = $.friends{$e.journal.username}; + print_entry_full($this, $e, $f.bgcolor, $f.fgcolor, false); + } +} + +################################################################################ +# +# EntryPage +# + +function EntryPage::lay_sidebar_view_summary() : string { + var string return; + foreach var Comment c ($.comments) { + if ($c.depth == 1) { + if ($c.subject != "") { + $return = $return + """$*text_sidebar_link_separator [#] $c.subject"""; + } else { + $return = $return + """$*text_sidebar_link_separator [#] $*text_nosubject"""; + } + } + } + return $return; +} + +function EntryPage::lay_sidebar_view_navigation() : string { + var string return; + var Link link; + foreach var string k ($.entry.link_keyseq) { + $link = $.entry->get_link($k); + if ($link.url != "") { + $return = """$return$*text_sidebar_link_separator$link.caption"""; + } + } + return $return; +} +function EntryPage::lay_sidebar_view_userpic() : string { + var string return; + if (defined $.entry.userpic) { + $return = """
    """; + } + if ($.entry.poster.username != $.entry.journal.username) { + $return = $return + $.entry.poster->as_string() + " posting in " ; + } + $return = $return + $.entry.journal->as_string(); + return $return; +} + +function EntryPage::print_body () { + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + print_entry_full($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled) + { + var string pages; + if ($.comment_pages.all_subitems_displayed) { + print_heading_bar("""($*text_post_comment)"""); + } else { + $pages = lang_page_of_pages($.comment_pages.current, $.comment_pages.total) + " - "; + foreach var int i (1 .. $.comment_pages.total) { + if ($i == $.comment_pages.current) { + $pages = "$pages [$i] "; + } else { + var string url_of = $.comment_pages->url_of($i); + $pages = """$pages [$i] """; + } + } + print_heading_bar("""($*text_post_comment)""", $pages); + } + if ($.comment_pages.total_subitems > 0) { + if ($this.multiform_on) { $this->print_multiform_start(); } + $this->print_comments($.comments); + if ($.comment_pages.all_subitems_displayed) { + print_heading_bar("""($*text_post_comment)"""); + } else { + $pages = lang_page_of_pages($.comment_pages.current, $.comment_pages.total) + " - "; + foreach var int i (1 .. $.comment_pages.total) { + if ($i == $.comment_pages.current) { + $pages = "$pages [$i] "; + } else { + var string url_of = $.comment_pages->url_of($i); + $pages = """$pages [$i] """; + } + } + print_heading_bar("""($*text_post_comment)""", $pages); + } + if ($this.multiform_on) { + println """
    """; + $this->print_multiform_actionline(); + println "
    "; + $this->print_multiform_end(); + } + } + } +} + +function EntryPage::print_comment(Comment c) +{ + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + println """
    """; + println """"""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + println """"""; + } + + println """
    [User Picture Icon]"""; + + println """"; + + println """"; + + println """"; + + println """"""; + + println "
    """; + println ""; + println """"""; + println """"; + if ($c.metadata{"poster_ip"}) { println """"; } + println "
    From:$poster
    Date:"""; + println $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(""" + $c.metadata{"poster_ip"} + ")
    """; + if ($this.multiform_on) { + println """ """; + $c->print_multiform_check(); + } + $c->print_linkbar(); + println "
    """; + println (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + println "
    (Link)
    "; + println """
    $c.text
    """; + println """
    """; + if ($c.frozen) { + println """(Replies frozen) """; + } else { + println """(Reply to this) """; + } + if ($c.parent_url != "") { println """(Parent) """; } + if ($c.thread_url != "") { println """(Thread) """; } + println "
    "; +} + +################################################################################ +# +# ReplyPage +# + +function ReplyPage::lay_sidebar_view_userpic() : string { + var string return; + if (defined $.replyto.poster) { + if (defined $.replyto.userpic) { + $return = $.replyto.userpic + "
    "; + } + $return = $return + $.replyto.poster->as_string(); + if ($.replyto.poster.username != $.entry.poster.username) { + $return = $return + " commented on " + $.entry.poster->as_string() + "'s post"; + } + if ($.entry.poster.username != $.entry.journal.username) { + var string preposition = $.entry.poster.username == $.replyto.poster.username ? + " posted in " : " in "; + $return = $return + $preposition + $.entry.journal->as_string(); + } + } else { + $return = "Anonymous commented on " + $.entry.poster->as_string() + "'s post"; + if ($.entry.poster.username != $.entry.journal.username) { + $return = $return + " in " + $.entry.journal->as_string(); + } + } + return $return; +} + +function ReplyPage::print_body +{ + if (not $.entry.comments.enabled) { + print_heading_bar("$*text_reply_nocomments_header"); + print "

    $*text_reply_nocomments

    "; + return; + } + + var string datetime = $.replyto.time->date_format("long") + " - " + $.replyto.time->time_format(); + + print_heading_bar($.replyto.subject, $datetime); + print "
    $.replyto.text
    "; + print_heading_bar("Reply to this:","""($*text_reply_back)"""); + $.form->print(); +} + +################################################################################ +# +# YearPage +# + +function YearPage::lay_sidebar_view_summary() : string { + var string return; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + $return = $return + """$*text_sidebar_link_separator [#] """ + $m->month_format() + ""; + } + } + return $return; +} + +function YearPage::lay_sidebar_view_navigation() : string { + var string return; + foreach var YearYear y (reverse $.years) { + if ($y.displayed) { + $return = "$return$*text_sidebar_link_separator$y.year"; + } else { + $return = """$return$*text_sidebar_link_separator$y.year"""; + } + } + return $return; +} + +function YearPage::print_body +{ + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + + print_heading_bar("""""" + $m->month_format() + ""); + println """"""; + foreach var int d (weekdays()) { + println """"; + } + println "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + println """
    """ + $*lang_dayname_short[$d] + "
    """; +} + +function YearWeek::print () +{ + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) { + """$d.day
    """; + if ($d.num_entries) { + """$d.num_entries"""; + } else { + " "; + } + "
    \n"; + } + if ($.post_empty) { " "; } + ""; +} + +################################################################################ +# +# MonthPage +# + +function MonthPage::lay_sidebar_view_navigation() : string { + var string return; + if ($.prev_url != "") { $return = """$*text_sidebar_link_separatorPrevious Month"""; } + if ($.next_url != "") { $return = """$return$*text_sidebar_link_separatorNext Month"""; } + return $return; +} +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + + var string selector; + if (size $.months > 1) { + $selector = "\n"; + print_heading_bar("Switch to: $selector"); + } + + "
    \n
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n"; +} + +################################################################################ +# +# DayPage +# + +function DayPage::lay_sidebar_view_summary() : string { + var string return; + if ($.has_entries) { + foreach var Entry e ($.entries) { + if ($e.subject != "") { + $return = $return + """$*text_sidebar_link_separator [#] $e.subject $e.security_icon"""; + } else { + $return = $return + """$*text_sidebar_link_separator [#] $*text_nosubject $e.security_icon """; + } + } + } + return $return; +} + +function DayPage::lay_sidebar_view_navigation() : string { + var string return; + $return = """$return$*text_sidebar_link_separator$*text_day_prev"""; + $return = """$return$*text_sidebar_link_separator$*text_day_next"""; + return $return; +} + +function DayPage::print_body() { + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } else { + "

    $*text_noentries_day

    "; + } +} + +################################################################################ +# +# Preview +# + +function print_theme_preview () +{ + println """
    """; + +"""
    + + + + +
    AboutRecent Entries
    +
    +
    Profile
    John Doe

    + +
    +
    Page Summary
      »  foo
      »  foo
      »  foo
      »  hhfdhgfd
      »  (no subject)

    + +
    +
    + +
    Full EntryNov. 29th, 2003 @ 01:10 am
    +
    +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
    + +
    Other entries
    + + +
    » Short Entry
    Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
    Nov. 29th, 2003 @ 12:50 am +
    +
    +"""; +server_sig(); +"
    "; +} diff --git a/livejournal/bin/upgrading/s2layers/generator/en.s2 b/livejournal/bin/upgrading/s2layers/generator/en.s2 new file mode 100755 index 0000000..bca4eb4 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/generator/en.s2 @@ -0,0 +1,17 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "generator/en"; + +set text_meta_music = "music"; +set text_meta_mood = "mood"; + +set text_permalink = "link"; + +set text_post_comment = "post comment"; +set text_post_comment_friends = "post comment"; + +set text_read_comments = "1 comment // # comments"; +set text_read_comments_friends = "1 comment // # comments"; + diff --git a/livejournal/bin/upgrading/s2layers/generator/generator.jpg b/livejournal/bin/upgrading/s2layers/generator/generator.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f4d0b121d0e7c4eadf246f38fd1ad903b8d68fa8 GIT binary patch literal 10141 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 literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/generator/layout.s2 b/livejournal/bin/upgrading/s2layers/generator/layout.s2 new file mode 100755 index 0000000..fb4ccab --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/generator/layout.s2 @@ -0,0 +1,945 @@ +# -*-s2-*- +layerinfo type = "layout"; +layerinfo name = "Generator"; +layerinfo redist_uniq = "generator/layout"; +layerinfo previews = "generator/generator.jpg"; + +propgroup colors { + property Color entry_back { + des = "Entry background"; + s1color = "page_back"; + } + property Color entry_text { + des = "Entry text color"; + s1color = "page_text"; + } + property Color page_link { + des = "Link color"; + s1color = "page_link"; + } + property Color page_vlink { + des = "Visited link color"; + s1color = "page_vlink"; + } + property Color page_alink { + des = "Active link color"; + s1color = "page_alink"; + } + property Color page_back { + des = "Page background color (and around userpics)"; + s1color = "strong_back"; + } + property Color stronger_back { + des = "Background color for the bar above entries"; + s1color = "strong_back"; + } + property Color stronger_text { + des = "Text color for the bar above entries"; + s1color = "stronger_text"; + } + property Color weak_back { + des = "Background color for the bar below entries"; + s1color = "weak_back"; + } + property Color weak_text { + des = "Text color for the bar below entries"; + s1color = "weak_text"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} + +propgroup fonts { + property use font_base; + property use font_fallback; +} + +propgroup presentation { + property use page_recent_items; + property use page_friends_items; + + property int box_width { + des = "Box width (pixels)"; + } + + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; + property use linklist_support; +} + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + + property string text_website { + des = "The label for the 'website' field"; + noui = 1; + } +} + +# Set default colors +set entry_back = "#ffffff"; +set entry_text = "#000000"; +set page_link = "#0000ff"; +set page_vlink = "#0000ff"; +set page_alink = "#00ffff"; +set page_back = "#2d4f89"; +set stronger_back = "#000000"; +set stronger_text = "#ffffff"; +set weak_back = "#aaaaaa"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#dddddd"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#5f6f99"; +set comment_bar_screened_fgcolor = "#000000"; + +set box_width = 600; +set show_entrynav_icons = true; +set page_background_image = ""; + +set font_base = "Verdana"; +set font_fallback = "sans-serif"; + +# Customize the view names to be short and lowercase +# (Sorry translators, you'll have to do these again - keep them short!) +set text_view_recent = "entries"; +set text_view_friends = "friends"; +set text_view_archive = "archive"; +set text_view_userinfo = "userinfo"; + +set tags_aware = true; + +set text_website = "website"; + +function print_stylesheet () { + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; +"""body, td { +"""; +if ($*font_base != "" or $*font_fallback != "none") { + "font-family: "; + if ($*font_base != "") { + "\"$*font_base\""; + if ($*font_fallback != "none") { + ", "; + } + } + if ($*font_fallback != "none") { + print $*font_fallback; + } + ";\n"; +} +"""font-size: 10pt; +} +tt, pre { +font-family: monospace; +} +a { +text-decoration: none; +} +a:hover { +text-decoration: underline; +} +.shadowed { +font-size: 8pt; +background: $*weak_back; +} +.meta { +font-size: 8pt; +} +.index { +font-size: 8pt; +} +.caption, .index { +color: $*stronger_text; +} +.comments { +font-size: 8pt; +} + +"""; +} + +function Page::lay_top_userpic () { + var Image up_img = $.journal.default_pic; + if (defined $up_img) { + """ + +
    +"""; + } +} +function FriendsPage::lay_top_userpic () { } + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + println """ +

    + + +
    + + + +
    Links
    + + + + +
    + +"""; + var bool section_open = false; + if (not $.linklist[0].is_heading) { + println """"""; + } + println """"""; + +"
    [Links:|"""; + $section_open = true; + } + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + println """]
    [$l.title|"""; + $section_open = true; + } else { + println """$l.title """; + } + } + } + println """]
    +
    +
    +

    +"; +} + +function Page::print () +{ + var string title = $this->title(); + + var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name; + var string website; + if ($.journal.website_url != "") { + $website = """[ +$*text_website +| +
    $website_name +]"""; + } + + var string links; + var bool firstlink = true; + foreach var string v ($.views_order) { + if ($firstlink == false) { + $links = "$links|"; + } + else { + $firstlink = false; + } + $links = $links + ($.view == $v ? + ""+lang_viewname($v)+"" : + ""+lang_viewname($v)+""); + } + +"""\n\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + +"""$title + + +
    + + +
    + + + + +
    $title[$links]
    + + + +
    + +"""; + $this->lay_top_userpic(); + + var string sitename_lc = $*SITENAMESHORT->lower(); + +""" + +
    +
    $.journal.name

    + +$website + + + + + + + + + + + + + + +
    ["""+lang_viewname("userinfo")+"""|$sitename_lc userinfo]
    ["""+lang_viewname("archive")+"""|journal archive]
    +

    +
    +
    + +"""; +if (size $.linklist > 0 and $*linklist_support) { +$this->print_linklist(); +} +""" + +

    +"""; + $this->print_body(); + +""" +

    +

    + + +"""; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string datetime; + $datetime = $e.time->date_format("med")+"|" + + $e.time->time_format() + ""; + + """ + + +
    + + + + + + + +"""; + if ($p.view != "entry" and $p.view != "reply") { + ""; + } elseif ($e.comments.enabled) { + ""; + } else { + ""; + } + """
    """; + + if ($e.security != "") { + $e.security_icon->print(); + } + + """ $e.subject[$datetime]
    +"""; + + if ($p.view == "entry" and $*show_entrynav_icons) + { + print "
    "; + $e->print_linkbar(); + print "
    "; + } + + if ($p.view == "friends" or + $p.journal_type == "C" or + $e.poster.username != $e.journal.username) + { + var UserLite linkto; + var bool showposter; + if ($p.view == "recent" and $p.journal_type == "C") { + $linkto = $e.poster; + $showposter = false; + } else { + $linkto = $e.journal; + $showposter = true; + } + + """
    """; + """"""; + """
    base_url() + "\">"; + if (defined $e.userpic) { + """
    """; + } + + "$linkto.username
    "; + if ($e.poster.username != $e.journal.username and $showposter) { + "
    [base_url() + "/\">$e.poster.username]"; + } + "
    "; + } + + var string metadata; + if ($e.metadata) { + $metadata = """"""; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $metadata = """$metadata\n + """; + } + $metadata = """$metadata
    [$text|$val]
    """; + } + + var string tags; + if ($e.tags) { + var int tcount = 0; + $tags = """"""; + $tags = """$tags
    [Tags|"""; + foreach var Tag t ($e.tags) { + $tags = """$tags"""; + $tcount++; + if ($tcount != size $e.tags) { $tags = """$tags, """; } + } + $tags = """$tags]
    """; + } + + if (not $hide_text) { + if ($tags or $metadata) { + print $tags; + print $metadata; + print "
    "; + } + print $e.text; + } +"""
    +$*text_permalink"; $e.comments->print(); ""; $e.comments->print_postlink(); "

    """; + +} # print_entry(Page,Entry,Color,Color,bool) + +function Page::print_entry (Entry e) { + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function RecentPage::print_body () +{ + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + var string range = "most recent entries"; + if ($.nav.skip > 0) { + $range = "$.nav.skip entries back"; + } + +""" + +
    + + + + + +
    navigation
    + + + + + + + + +"""; + + # go forward/backward if possible + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + var string sep; + var string back; + var string forward; + if ($.nav.backward_url != "") { + $back = """earlier"""; + } + if ($.nav.forward_url != "") { + $forward = """later"""; + } + if ($back != "" and $forward != "") { $sep = "/"; } + """ + + + + + +"""; + } + + "
    [viewing|$range]
    [go|$back$sep$forward]
    "; +} + +function CommentInfo::print () +{ + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + ""; $this->print_readlink(); ""; + "|"; + } + $this->print_postlink(); +} + +function YearPage::print_year_links () +{ + """ +
    + + +
    Years
    """; + foreach var YearYear y ($.years) { + if ($y.displayed) { + "$y.year "; + } else { + "$y.year "; + } + } + """

    """; + +} + +function YearPage::print_month (YearMonth m) +{ + if (not $m.has_entries) { return; } + """ +
    + + + + + + +
    """; + print $m->month_format(); + """[subjects]
    + + + +"""; + foreach var int d (weekdays()) { + "\n"; + } + + ""; + + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + """
    "+$*lang_dayname_short[$d]+"

    """; +} + +function YearWeek::print () { + ""; + if ($.pre_empty) { ""; } + foreach var YearDay d ($.days) { + """

    $d.day
    """; + if ($d.num_entries) { + """"""; + } else { + " "; + } + ""; + } + if ($.post_empty) { ""; } + ""; +} + +function DayPage::print_body() { + + """ +
    + +
    """; + + if ($.has_entries) { + print $.date->date_format("long"); + } else { + print ehtml($*text_noentries_day); + } + + """

    """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + var string daylong = $.date->date_format("long"); + +""" +
    + + + + + + + +
    navigation
    + + + + + + + + + + + + + + + + +
    [viewing|$daylong]
    [go|$tprev|$tnext]
    +
    +
    """; + +} + +function MonthPage::print_body () { + """ + +
    + + + + +
    """; + + print $.date->date_format($*lang_fmt_month_long); + + """
    """; + + #Lifted from core, looks decent: + "
    "; + $.redir->print_hiddens(); + if ($.prev_url != "") { "[<<<]\n"; } + if (size $.months > 1) { + "\n"; + } + if ($.next_url != "") { "\n[>>>]\n"; } + "
    \n
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n"; + """
    +

    """; +} + +function EntryPage::print_body () { + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + """ + +
    + + +"""; + + """
    Comments:
    """; + + $.comment_pages->print(); + + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + $this->print_comments($.comments); + $.comment_pages->print(); + """

    """; + + if ($this.multiform_on) { + """ + +
    + + +"""; + + """
    Mass Action:
    """; + $this->print_multiform_actionline(); + """

    """; + $this->print_multiform_end(); + } + } +} + +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + "

    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + + "
    [User Picture]"; + + ### From, date, etc + ""; + + ### Gadgets + ""; + + ### Subject / icon + print ""; + + ### Permalink + print ""; + + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    From:$poster
    Date:"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + print (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + print "
    (Link)
    "; + print "
    $c.text
    "; + print "
    "; + + ""; + if ($c.frozen) { + "(Replies frozen) "; + } else { + "(Reply to this) "; + } + ""; + + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    "; +} + +function ReplyPage::print_body () { + if (not $.entry.comments.enabled) { + """ + +
    + + + + +
    $*text_reply_nocomments_header
    """; + + print "

    $*text_reply_nocomments

    "; + """

    """; + return; + } + var string datetime; + $datetime = $.replyto.time->date_format("med")+"|" + $.replyto.time->time_format() + ""; + """ + +
    + + + + + + + + +
    $.replyto.subject$datetime
    + +
    + +
    """; + +if (defined $.replyto.poster) { + ""; + if (defined $.replyto.userpic) { + """
    """; + } + "$.replyto.poster.username
    "; +} else { + print "Anonymous"; +} + +"""
    $.replyto.text
    +$*text_permalinkRead Comments

    """; + + """ + +
    + + + + +
    Reply:
    """; + + $.form->print(); + + """

    """; +} + +function print_theme_preview () { + """
    + + +
    + + + + + + +
    Preview Subject[Feb. 5th, 2002|8:46 pm]
    +Preview text, preview text, etc, etc..... words, words and more words. + +
    +$*text_permalink + +1 comment|post comment + +
    +
    +
    +"""; +} diff --git a/livejournal/bin/upgrading/s2layers/generator/themes.s2 b/livejournal/bin/upgrading/s2layers/generator/themes.s2 new file mode 100755 index 0000000..886c41a --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/generator/themes.s2 @@ -0,0 +1,369 @@ +#NEWLAYER: generator/mintchoc +layerinfo "type" = "theme"; +layerinfo "name" = "Mint Chocolate Chip"; +layerinfo "redist_uniq" = "generator/mintchoc"; +layerinfo "author_name" = "Andrea Hartmann"; +layerinfo "author_email" = "mullenkamp@livejournal.com"; +set entry_back = "#ddffee"; +set entry_text = "#330000"; +set page_link = "#993333"; +set page_vlink = "#663333"; +set page_alink = "#000000"; +set page_back = "#ccffdd"; +set stronger_back = "#663333"; +set stronger_text = "#ccffdd"; +set weak_back = "#88ffdd"; +set weak_text = "#663333"; +set comment_bar_one_bgcolor = "#88ffdd"; +set comment_bar_one_fgcolor = "#663333"; +set comment_bar_two_fgcolor = "#663333"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/purple +layerinfo "type" = "theme"; +layerinfo "name" = "Purple"; +layerinfo "redist_uniq" = "generator/purple"; +layerinfo "author_name" = "Andrea Hartmann"; +layerinfo "author_email" = "mullenkamp@livejournal.com"; +set entry_back = "#9933cc"; +set entry_text = "#ddccff"; +set page_link = "#ffffff"; +set page_vlink = "#330033"; +set page_alink = "#ffccff"; +set page_back = "#bb55ee"; +set stronger_back = "#660099"; +set stronger_text = "#f5eeff"; +set weak_back = "#bb88dd"; +set weak_text = "#ddccff"; +set comment_bar_one_bgcolor = "#660099"; +set comment_bar_one_fgcolor = "#f5eeff"; +set comment_bar_two_bgcolor = "#bb88dd"; +set comment_bar_two_fgcolor = "#ddccff"; + +#NEWLAYER: generator/ocean +layerinfo "type" = "theme"; +layerinfo "name" = "Deep Blue Xenogears Ocean"; +layerinfo "redist_uniq" = "generator/ocean"; +layerinfo "author_name" = "Andrea Hartmann"; +layerinfo "author_email" = "mullenkamp@livejournal.com"; +set entry_back = "#1100dd"; +set entry_text = "#ccccff"; +set page_link = "#ffffff"; +set page_vlink = "#ddddff"; +set page_alink = "#ffffff"; +set page_back = "#3333ff"; +set stronger_back = "#aabbff"; +set stronger_text = "#0033cc"; +set weak_back = "#3399ff"; +set weak_text = "#0033cc"; +set comment_bar_one_bgcolor = "#aabbff"; +set comment_bar_one_fgcolor = "#0033cc"; +set comment_bar_two_bgcolor = "#3399ff"; +set comment_bar_two_fgcolor = "#0033cc"; + +#NEWLAYER: generator/harvest +layerinfo "type" = "theme"; +layerinfo "name" = "Harvest"; +layerinfo "redist_uniq" = "generator/harvest"; +layerinfo "author_name" = "Andrea Hartmann"; +layerinfo "author_email" = "mullenkamp@livejournal.com"; +set entry_back = "#ff9900"; +set entry_text = "#663333"; +set page_link = "#ffeeaa"; +set page_vlink = "#993300"; +set page_alink = "#ffcc88"; +set page_back = "#ffaa11"; +set stronger_back = "#ffcc33"; +set stronger_text = "#663333"; +set weak_back = "#cc6600"; +set weak_text = "#ffcc88"; +set comment_bar_one_bgcolor = "#ffcc33"; +set comment_bar_one_fgcolor = "#663333"; +set comment_bar_two_bgcolor = "#cc6600"; +set comment_bar_two_fgcolor = "#ffcc88"; + +#NEWLAYER: generator/jeweled +layerinfo "type" = "theme"; +layerinfo "name" = "Jeweled"; +layerinfo "redist_uniq" = "generator/jeweled"; +layerinfo "author_name" = "Andrea Hartmann"; +layerinfo "author_email" = "mullenkamp@livejournal.com"; +set entry_back = "#aa6699"; +set entry_text = "#330066"; +set page_link = "#ccddee"; +set page_vlink = "#cc99cc"; +set page_alink = "#cceecc"; +set page_back = "#881188"; +set stronger_back = "#006699"; +set stronger_text = "#ceecc"; +set weak_back = "#008888"; +set weak_text = "#002222"; +set comment_bar_one_bgcolor = "#006699"; +set comment_bar_one_fgcolor = "#ceecc"; +set comment_bar_two_bgcolor = "#008888"; +set comment_bar_two_fgcolor = "#002222"; + +#NEWLAYER: generator/darkgreens +layerinfo type = "theme"; +layerinfo name = "Dark Greens"; +layerinfo redist_uniq = "generator/darkgreens"; +layerinfo author_name = "Ryan Fitzpatrick"; +set entry_back = "#020202"; +set entry_text = "#fbfbfb"; +set page_link = "#9aff8d"; +set page_vlink = "#e3ee39"; +set page_alink = "#ff0220"; +set page_back = "#117218"; +set stronger_back = "#38e616"; +set stronger_text = "#020100"; +set weak_back = "#020100"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#38e616"; +set comment_bar_one_fgcolor = "#020100"; +set comment_bar_two_bgcolor = "#117218"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/satin +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "generator/satin"; +set entry_back = "#d06464"; +set entry_text = "#000000"; +set page_link = "#ffffff"; +set page_vlink = "#6f2222"; +set page_alink = "#333333"; +set page_back = "#480c0c"; +set stronger_back = "#9d0404"; +set stronger_text = "#ffffff"; +set weak_back = "#d06464"; +set weak_text = "#ffffff"; +set comment_bar_one_bgcolor = "#9d0404"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d06464"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: generator/sunset +layerinfo type = theme; +layerinfo name = "Sunset"; +layerinfo redist_uniq = "generator/sunset"; +set entry_back = "#ff7301"; +set entry_text = "#fdb54f"; +set page_link = "#ffe65e"; +set page_vlink = "#ff9879"; +set page_alink = "#ffb866"; +set page_back = "#070494"; +set stronger_back = "#f8a402"; +set stronger_text = "#ffd510"; +set weak_back = "#f51700"; +set weak_text = "#f77603"; +set comment_bar_one_bgcolor = "#f8a402"; +set comment_bar_one_fgcolor = "#ffd510"; +set comment_bar_two_bgcolor = "#f51700"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/redbliss +layerinfo type = theme; +layerinfo name = "Red Bliss"; +layerinfo redist_uniq = "generator/redbliss"; +set entry_back = "#ffcccc"; +set entry_text = "#000000"; +set page_link = "#ffffff"; +set page_vlink = "#ffcccc"; +set page_alink = "#00ffff"; +set page_back = "#ff3300"; +set stronger_back = "#cc3333"; +set stronger_text = "#ffffff"; +set weak_back = "#cc3333"; +set weak_text = "#fafafa"; +set comment_bar_one_bgcolor = "#cc3333"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ff3333"; +set comment_bar_two_fgcolor = "#fafafa"; + +#NEWLAYER: generator/pastelneons +layerinfo type = theme; +layerinfo name = "Pastel Neons"; +layerinfo redist_uniq = "generator/pastelneons"; +set entry_back = "#ffffff"; +set entry_text = "#1a6b6a"; +set page_link = "#330f42"; +set page_vlink = "#033339"; +set page_alink = "#9923ca"; +set page_back = "#00ffff"; +set stronger_back = "#60d2cb"; +set stronger_text = "#000000"; +set weak_back = "#d385f3"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#60d2cb"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#d385f3"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/classdesk +layerinfo type = "theme"; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "generator/classdesk"; +set page_link = "#ff7b05"; +set page_vlink = "#ce4900"; +set page_alink = "#ff9e2b"; +set page_back = "#007782"; +set stronger_back = "#00545c"; +set stronger_text = "#ffffff"; +set weak_back = "#ffeddd"; +set weak_text = "#ffffff"; +set comment_bar_one_bgcolor = "#00545c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffeddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "generator/everwhite"; +set entry_back = "#ffffff"; +set entry_text = "#000000"; +set page_link = "#ff0000"; +set page_vlink = "#ff0000"; +set page_alink = "#ffffff"; +set page_back = "#ffffff"; +set stronger_back = "#ffffff"; +set stronger_text = "#ff0000"; +set weak_back = "#ffffff"; +set weak_text = "#ffffff"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Grey"; +layerinfo redist_uniq = "generator/everblue"; +set entry_back = "#ffffff"; +set entry_text = "#000000"; +set page_link = "#0000ff"; +set page_vlink = "#060667"; +set page_alink = "#ffffff"; +set page_back = "#0f0c6d"; +set stronger_back = "#000000"; +set stronger_text = "#ffffff"; +set weak_back = "#aaaaaa"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/purplesky +layerinfo type = theme; +layerinfo name = "Purple Sky"; +layerinfo redist_uniq = "generator/purplesky"; +set entry_back = "#24d8df"; +set entry_text = "#0424e4"; +set page_link = "#a917c4"; +set page_vlink = "#9911e8"; +set page_alink = "#ea09ff"; +set page_back = "#99e3e2"; +set stronger_back = "#8802fa"; +set stronger_text = "#ffffff"; +set weak_back = "#89e5e9"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#8802fa"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#89e5e9"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "generator/bruise"; +set entry_back = "#bcbcbc"; +set entry_text = "#000000"; +set page_link = "#0000ff"; +set page_vlink = "#0000ff"; +set page_alink = "#0000ff"; +set page_back = "#000000"; +set stronger_back = "#1114a0"; +set stronger_text = "#ffffff"; +set weak_back = "#21c2f1"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/elegant +layerinfo type = theme; +layerinfo name = "Elegant"; +layerinfo redist_uniq = "generator/elegant"; +set entry_back = "#ffffff"; +set entry_text = "#000000"; +set page_link = "#e91822"; +set page_vlink = "#bf1418"; +set page_alink = "#f71e28"; +set page_back = "#ffffff"; +set stronger_back = "#777777"; +set stronger_text = "#000000"; +set weak_back = "#e6e6e6"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#777777"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#e6e6e6"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/bananapeel +layerinfo type = theme; +layerinfo name = "Banana Peel"; +layerinfo redist_uniq = "generator/bananapeel"; +set entry_back = "#f2f688"; +set entry_text = "#ee2914"; +set page_link = "#db9129"; +set page_vlink = "#c58f1b"; +set page_alink = "#ffc518"; +set page_back = "#ffffff"; +set stronger_back = "#f0f905"; +set stronger_text = "#000000"; +set weak_back = "#dcdf02"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#f0f905"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#dcdf02"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: generator/melodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "generator/melodrama"; +set entry_back = "#719cff"; +set entry_text = "#9348a1"; +set page_link = "#f5d3ff"; +set page_vlink = "#e2ffe3"; +set page_alink = "#e2ffe3"; +set page_back = "#872d89"; +set stronger_back = "#3794b3"; +set stronger_text = "#a4b8ff"; +set weak_back = "#65b2c1"; +set weak_text = "#98bac5"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#a4b8ff"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#872d89"; + +#NEWLAYER: generator/iceburg +layerinfo type = theme; +layerinfo name = "Iceburg"; +layerinfo redist_uniq = "generator/iceburg"; +set entry_back = "#ffffff"; +set entry_text = "#000000"; +set page_link = "#0000ff"; +set page_vlink = "#0000ff"; +set page_alink = "#387bf7"; +set page_back = "#c6c2f5"; +set stronger_back = "#7c6ccd"; +set stronger_text = "#ffffff"; +set weak_back = "#eef0fd"; +set weak_text = "#000000"; +set comment_bar_one_bgcolor = "#7c6ccd"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#eef0fd"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/haven/haven.png b/livejournal/bin/upgrading/s2layers/haven/haven.png new file mode 100755 index 0000000000000000000000000000000000000000..6f0cee63dc5e9d35d5a8ce0d85a91e4402793d1f GIT binary patch literal 16042 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 T<$Dwe_`84ip?bM0D&+qFL7KmR literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/haven/layout.s2 b/livejournal/bin/upgrading/s2layers/haven/layout.s2 new file mode 100755 index 0000000..6b66fd6 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/haven/layout.s2 @@ -0,0 +1,1655 @@ +# -*-s2-*- +layerinfo type = "layout"; +layerinfo name = "Haven"; +layerinfo lang = "en"; + +layerinfo author_name = "Jesse Proulx"; +layerinfo author_email = "jproulx@livejournal.com"; +layerinfo redist_uniq = "haven/layout"; +layerinfo des = "This style is more conceptual and boring than it is innovative and pretty. The goal for this style was to see how well I could automate color palette generation, given the functions available in S2."; +layerinfo previews = "haven/haven.png"; + +propgroup presentation +{ + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property bool show_entry_userpic + { + des = "Show user picture icons with each of your entries?"; + } + set show_entry_userpic = true; + property string content_width + { + des = "Entire width of the main content, in percentages"; + values = "60%|60%|70%|70%|80%|80%|90%|90%|100%|100%"; + } + set content_width = "90%"; + property string title_position + { + des = "Location of the title bar in regards to the entire page"; + values = "top|Top of the page|bottom|Bottom of the page|both|Both top and bottom of the page"; + } + set title_position = "both"; +} +propgroup background = "Background"; +propgroup background +{ + property string page_background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + property string page_background_repeat + { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string page_background_position + { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + property string page_background_scrolling + { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set page_background_image = ""; + set page_background_repeat = "repeat"; + set page_background_position = "center"; + set page_background_scrolling = "scroll"; +} +propgroup fonts +{ + property string main_font + { + des = "Preferred Font"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set main_font = "Trebuchet MS"; + set main_font_fallback = "sans-serif"; + property string sidebar_font + { + des = "Font for the sidebar boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string sidebar_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set sidebar_font = "Verdana"; + set sidebar_font_fallback = "sans-serif"; + property string content_font + { + des = "Font for the content boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + set content_font = "Tahoma"; + set content_font_fallback = "sans-serif"; +} +propgroup colors +{ + ### Main page colors ### + property Color page_bgcolor + { + des = "Background color for the page"; + } + property Color page_fgcolor + { + des = "Text color for the page"; + } + #set page_bgcolor = "#ffffff"; + #set page_fgcolor = "#000000"; + + ### Content colors ### + property Color content_bgcolor + { + des = "Background color for content on the page"; + } + property Color content_fgcolor + { + des = "Text color for the content on the page"; + } + property Color content_border + { + des = "Color for borders around content"; + } + #set content_bgcolor = "#ffffff"; + #set content_fgcolor = "#000000"; + #set content_border = "#c2c2c2"; + + ### Page title colors ### + property Color title_bgcolor + { + des = "Title box background color"; + } + property Color title_fgcolor + { + des = "Title box text color"; + } + property Color title_border + { + des = "Border color between title bar boxes"; + } + #set title_bgcolor = "#cccccc"; + #set title_fgcolor = "#000000"; + #set title_border = "#cccccc"; + + ### Navigation box colors ### + property Color nav_bgcolor + { + des = "Background color on navigation box"; + } + property Color nav_fgcolor + { + des = "Text color on navigation box"; + } + #set nav_bgcolor = "#e2e2e2"; + #set nav_fgcolor = "#000000"; + + ### Tabbed box title colors ### + property Color tabs_bgcolor + { + des = "Background color on tabs and headers"; + } + property Color tabs_fgcolor + { + des = "Text color on tabs and headers"; + } + + ### Sidebar boxes ### + property Color sidebar_box_bgcolor + { + des = "Background color on sidebar boxes"; + } + property Color sidebar_box_fgcolor + { + des = "Text color on sidebar boxes"; + } + property Color sidebar_box_title_bgcolor + { + des = "Background color on sidebar box titles"; + } + property Color sidebar_box_title_fgcolor + { + des = "Text color on sidebar box titles"; + } + property Color sidebar_box_border + { + des = "Border color on sidebar boxes"; + } + #set sidebar_box_bgcolor = "#ffffff"; + #set sidebar_box_fgcolor = "#000000"; + #set sidebar_box_title_bgcolor = "#cccccc"; + #set sidebar_box_title_fgcolor = "#000000"; + #set sidebar_box_border = "#000000"; + + ### Accent color ### + property Color accent_bgcolor + { + des = "Color used to accent hotspot areas"; + } + property Color accent_fgcolor + { + des = "Text color used on accent hotspot areas"; + } + #set accent_bgcolor = "#c0c0c0"; + #set accent_fgcolor = "#000000"; + + ### Comment bar colors ### + property Color comment_bar_one_bgcolor + { + des = "Background color for comment bars"; + } + property Color comment_bar_one_fgcolor + { + des = "Text color on comment bars"; + } + property Color comment_bar_two_bgcolor + { + des = "Alternating background color for comment bars"; + } + property Color comment_bar_two_fgcolor + { + des = "Text color on alternating comment bars"; + } + property Color comment_bar_screened_bgcolor + { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor + { + des = "Text color on background bar for screened comments"; + } + #set comment_bar_one_bgcolor = "#c0c0c0"; + #set comment_bar_one_fgcolor = "#000000"; + #set comment_bar_two_bgcolor = "#dddddd"; + #set comment_bar_two_fgcolor = "#000000"; + #set comment_bar_screened_bgcolor = "#f1f1f1"; + #set comment_bar_screened_fgcolor = "#000000"; + + ### Footer colors ### + property Color footer_bgcolor + { + des = "Background color on the footer"; + } + property Color footer_fgcolor + { + des = "Text color on the footer"; + } +} +propgroup automatic_color_palettes = "Automatic Color Palettes"; +propgroup automatic_color_palettes +{ + property Color color_scheme_base + { + des = "Core color used to determine the entire color scheme."; + note = "After you select a base color and choose a color scheme, an entire palette will be built automatically for your journal colors."; + } + property string color_scheme + { + des = "Color scheme"; + values = "monochromatic|Monochromatic: use variations of light and saturation without straying from your suggested color|analogous|Analogous: use slightly similar hues to enhance your suggested color|complementary|Complementary: create a high contrast scheme based on your suggested color|split_complementary|Split Complementary: A variation of the Complementary scheme using varying hues of the complementary color|double_complementary|Double Complementary: use slightly varying hues of the base and complementary colors|triadic|Triadic: offers less contrast than the complementary scheme, but is richer in color|tetradic|Tetradic: a combination of the Complementary and Triadic schemes"; + } + set color_scheme_base = "#1111cc"; + set color_scheme = "analogous"; +} +propgroup sidebar = "Sidebar"; +propgroup sidebar +{ + property string sidebar_width + { + des = "Sidebar width specification"; + values = "10%|Skinny|15%|Default|25%|Wide"; + } + property string sidebar_position + { + des = "Page position of the sidebar"; + values = "left|Left|right|Right"; + } + set sidebar_width = "15%"; + set sidebar_position = "left"; + property string sidebar_blurb { + des = "Text to be added to the sidebar"; + note = "Appears in the sidebar 'Blurb'"; + rows = 10; + cols = 25; + } + + ### Positions ### + property string sidebar_position_one { + note = "Set to 'Nothing' to hide box"; + des = "First Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_one = "summary"; + property string sidebar_position_two { + note = "Set to 'Nothing' to hide box"; + des = "Second Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_two = "links"; + property string sidebar_position_three { + note = "Set to 'Nothing' to hide box"; + des = "Third Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_three = "blurb"; + property string sidebar_position_four { + note = "Set to 'Nothing' to hide box"; + des = "Fourth Sidebar Box"; + values = "nothing|Nothing|summary|Page Summary|links|Link List|blurb|Blurb|calendar|Calendar"; + } + set sidebar_position_four = "calendar"; +} +propgroup text +{ + property use text_meta_music; + property use text_meta_mood; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_website_default_name; + property string text_sidebar_profile + { + des = "Title of the profile sidebar box"; + noui = 1; + } + property string text_sidebar_blurb + { + des = "Title of the blurb sidebar box"; + noui = 1; + } + property string text_sidebar_links + { + des = "Title of the links sidebar box"; + noui = 1; + } + property string text_sidebar_summary + { + des = "Title of the summary sidebar box"; + noui = 1; + } + set text_sidebar_profile = "Profile"; + set text_sidebar_blurb = "Blurb"; + set text_sidebar_links = "Links"; + set text_sidebar_summary = "Page Summary"; +} + +set tags_aware = true; + +################################################################################ +# +# Color scheme functions +# + +function color_triadic(Color base) : Color[] +{ + var int red = $base->red(); + var int green = $base->green(); + var int blue = $base->blue(); + var Color color_two = $base->clone(); + var Color color_one = $base->clone(); + + $color_one->blue($red); + $color_one->red($green); + $color_one->green($blue); + + $color_two->red($blue); + $color_two->green($red); + $color_two->blue($green); + + return [$base, $color_one, $color_two]; +} + +function color_tetradic(Color base) : Color[] +{ + var Color[] tetradic_one = color_triadic($base); + var Color[] tetradic_two = color_triadic($base->inverse()); + var Color color_one = $tetradic_one[1]->average($tetradic_two[2]); + var Color color_two = $tetradic_one[2]->average($tetradic_two[1]); + + return [$base, $base->inverse(), $color_one, $color_two]; +} + +function color_analogous(Color base) : Color[] +{ + var Color[] triad = color_triadic($base->inverse()); + var Color color_one = $base->average($triad[1]); + var Color color_two = $base->average($triad[2]); + + return [$base, $color_one, $color_two]; +} + +function color_split_complementary(Color base) : Color[] +{ + var Color[] analogous = color_analogous($base->inverse()); + var Color color_one = $analogous[1]; + var Color color_two = $analogous[2]; + + return [$base, $color_one, $color_two]; +} +function color_double_complementary(Color base) : Color[] +{ + var Color[] analogous_one = color_analogous($base); + var Color color_one = $analogous_one[1]; + var Color color_two = $analogous_one[2]; + var Color[] analogous_two = color_analogous($base->inverse()); + var Color color_three = $analogous_two[1]; + var Color color_four = $analogous_two[2]; + + return [$base, $color_one, $color_two, $color_three, $color_four]; +} + +function color_ideal_foreground(Color bg) : Color "Used to determine the best text color (out of white and black currently) given a single solid background color" +{ + var Color fg = $bg->inverse(); + var int saturation = $fg->saturation(); + $saturation = $saturation >= 127 ? 255 : 0; + $fg->saturation($saturation); + var int lightness = $fg->lightness(); + $lightness = $lightness >= 120 ? 255 : 0; + $fg->lightness($lightness); + return $fg; +} + +function prop_init() +{ + # If the user has selected a base color for a scheme, we build a palette + # with that color as the base. All of the isnull checks allows a user to tweak individual + # color settings without having to set them all explicitly. + if ($*color_scheme_base) { + if (isnull $*title_bgcolor) { $*title_bgcolor = $*color_scheme_base->clone(); } + if (isnull $*sidebar_box_bgcolor) { $*sidebar_box_bgcolor = "#ffffff"; } + if (isnull $*footer_bgcolor) { $*footer_bgcolor = "#ffffff"; } + if ($*color_scheme == "monochromatic") { + + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $*title_bgcolor->lighter(20); } + if (isnull $*page_bgcolor) { $*page_bgcolor = $*title_bgcolor->darker(40); } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $*title_bgcolor->darker(20); } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $*title_bgcolor->lighter(40); } + + } elseif ($*color_scheme == "complementary") { + var Color inverse = $*title_bgcolor->inverse(); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $inverse->lighter(20); } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $inverse->darker(20); } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $*title_bgcolor->lighter(20); } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $*title_bgcolor->darker(20); } + + } elseif ($*color_scheme == "split_complementary") { + var Color[] split_complementary = color_split_complementary($*title_bgcolor); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $split_complementary[1]->lighter(20); } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $split_complementary[0]->darker(20); } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $split_complementary[1]; } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $split_complementary[2]; } + + } elseif ($*color_scheme == "double_complementary") { + var Color[] double_complementary = color_double_complementary($*title_bgcolor); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $double_complementary[3]; } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $double_complementary[1]; } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $double_complementary[4]; } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $double_complementary[2]; } + + } elseif ($*color_scheme == "analogous") { + var Color[] analogous = color_analogous($*title_bgcolor); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $analogous[1]; } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $*page_bgcolor->average($analogous[0]); } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $analogous[2]; } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $*nav_bgcolor->average($analogous[0]); } + + } elseif ($*color_scheme == "triadic") { + var Color[] triadic = color_triadic($*title_bgcolor); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $triadic[1]->lighter(20); } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $triadic[1]->darker(20); } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $triadic[2]->lighter(20); } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $triadic[2]->darker(20); } + + } elseif ($*color_scheme == "tetradic") { + var Color[] tetradic = color_tetradic($*title_bgcolor); + + if (isnull $*page_bgcolor) { $*page_bgcolor = $tetradic[1]; } + if (isnull $*nav_bgcolor) { $*nav_bgcolor = $tetradic[0]->darker(20); } + if (isnull $*tabs_bgcolor) { $*tabs_bgcolor = $tetradic[2]; } + if (isnull $*sidebar_box_title_bgcolor) { $*sidebar_box_title_bgcolor = $tetradic[3]; } + } + } + if (isnull $*page_fgcolor) { $*page_fgcolor = color_ideal_foreground($*page_bgcolor); } + if (isnull $*title_fgcolor) { $*title_fgcolor = color_ideal_foreground($*title_bgcolor); } + if (isnull $*tabs_fgcolor) { $*tabs_fgcolor = color_ideal_foreground($*tabs_bgcolor); } + if (isnull $*title_border) { $*title_border = $*title_bgcolor->average($*nav_bgcolor); } + if (isnull $*footer_fgcolor) { $*footer_fgcolor = color_ideal_foreground($*footer_bgcolor); } + # Content + if (isnull $*content_bgcolor) { $*content_bgcolor = "#ffffff"; } + if (isnull $*content_fgcolor) { $*content_fgcolor = color_ideal_foreground($*content_bgcolor); } + if (isnull $*content_border) { $*content_border = $*content_fgcolor; } + # Sidebar + if (isnull $*sidebar_box_title_fgcolor) { $*sidebar_box_title_fgcolor = color_ideal_foreground($*sidebar_box_title_bgcolor); } + if (isnull $*sidebar_box_fgcolor) { $*sidebar_box_fgcolor = color_ideal_foreground($*sidebar_box_bgcolor); } + if (isnull $*sidebar_box_border) { $*sidebar_box_border = $*sidebar_box_fgcolor; } + # Accent + if (isnull $*accent_bgcolor) { $*accent_bgcolor = $*nav_bgcolor; } + if (isnull $*accent_fgcolor) { $*accent_fgcolor = color_ideal_foreground($*accent_bgcolor); } + # Comment bar colors + if (isnull $*comment_bar_one_bgcolor) { $*comment_bar_one_bgcolor = $*nav_bgcolor; } + if (isnull $*comment_bar_two_bgcolor) { $*comment_bar_two_bgcolor = $*sidebar_box_title_bgcolor; } + if (isnull $*comment_bar_one_fgcolor) { $*comment_bar_one_fgcolor = color_ideal_foreground($*comment_bar_one_bgcolor); } + if (isnull $*comment_bar_two_fgcolor) { $*comment_bar_two_fgcolor = color_ideal_foreground($*comment_bar_two_bgcolor); } +} + +function css_font_family(string base, string fallback) : string +{ + var string return; + if ($base != "" or $fallback != "none") { + $return = $return + "font-family: "; + if ($base != "") { + $return = $return + "\"$base\""; + if ($fallback != "none") { + $return = $return + ", "; + } + } + if ($fallback != "none") { + $return = $return + $fallback; + } + } + return $return; +} + +function print_stylesheet () +{ + var string body_font_family = css_font_family($*main_font, $*main_font_fallback); + var string sidebar_font_family = css_font_family($*sidebar_font, $*sidebar_font_fallback); + var string content_font_family = css_font_family($*content_font, $*content_font_fallback); + var string body_background = ""; + if ($*page_background_image != "") { + $body_background = """ + background-image: url("$*page_background_image"); + background-repeat: $*page_background_repeat; + background-position: $*page_background_position; + background-attachment: $*page_background_scrolling; + """; + } + print """ +body +{ + background-color: $*page_bgcolor; + $body_background + color: $*page_fgcolor; + $body_font_family; + font-size: 100%; + margin: 0px; +} +a +{ + color: $*page_fgcolor; +} +p, td, blockquote +{ + font-size: 1.0em; +} +code, kbd, pre, tt +{ + font-family: monospace; +} +h1 +{ + font-size: 2.0em; +} +h2 +{ + font-size: 1.5em; +} +.title_navigation +{ + border: 1px solid $*title_border; + width: 100%; +} +.title +{ + background-color: $*title_bgcolor; + color: $*title_fgcolor; + text-align: center; + width: 40%; +} +.main_subtitle +{ + line-height: .5em; +} +.navigation +{ + background-color: $*nav_bgcolor; + color: $*nav_fgcolor; + text-align: left; + white-space: nowrap; +} +.navigation_title +{ + width: 100%; + border-bottom: $*nav_fgcolor 1px solid; + text-align: left; +} +#sidebar +{ + $sidebar_font_family; + width: $*sidebar_width; +} +.sidebar_box +{ + background-color: $*sidebar_box_bgcolor; + color: $*sidebar_box_fgcolor; + width: 100%; +} +.sidebar_box th +{ + border-left: 1px solid $*sidebar_box_border; + border-right: 1px solid $*sidebar_box_border; + border-top: 1px solid $*sidebar_box_border; + background-color: $*sidebar_box_title_bgcolor; + color: $*sidebar_box_title_fgcolor; + text-align: center; +} +.sidebar_box td +{ + border: 1px solid $*sidebar_box_border; + font-size: .85em; + width: 100%; +} +.sidebar_box a +{ + color: $*sidebar_box_fgcolor; +} +.tabs +{ + background-color: $*tabs_bgcolor; + border-left: 1px solid $*content_border; + border-right: 1px solid $*content_border; + border-top: 1px solid $*content_border; + color: $*tabs_fgcolor; + $content_font_family; + margin-bottom: 0; + padding: 1em 1em .5em 1em; + text-decoration: none; + width: 40%; +} +.content +{ + background-color: $*content_bgcolor; + border: 1px solid $*content_border; + color: $*content_fgcolor; + $content_font_family; + width: 100%; + padding: .5em; +} +.content a +{ + color: $*content_fgcolor; +} +/* Box effect */ +.entry, .calendar_month, .month_day, .comment_page, .replyto +{ + margin: 0.25em 0.5em 0.25em 0.5em; + padding: 0.25em 0.5em 0.25em 0.5em; + text-align: justify; +} +.entry .text, .calendar_month .calendar, .month_day .posts, .comment_page .comments, .replyto .text +{ + margin: 0; + border-right: 1px solid $*content_border; + border-left: 1px solid $*content_border; + border-bottom: 1px solid $*content_bgcolor; + padding: .5em; +} + +html>body .entry .text, html>body .calendar_month .calendar, html>body .month_day .posts, html>body .comment_page .comments, html>body .replyto .text { + border-bottom-width: 0; +} + +.entry .subject, .calendar_month .header, .month_day .header, .comment_page .header, .replyto .subject +{ + border-bottom: 1px solid $*content_border; + border-left: 1em solid $*content_border; + font-size: 0.8em; + margin-bottom: 0; + padding-left: 0.8em; +} +.entry .comments, .calendar_month .subjects, .month_day .footer, .comment_page .footer, .replyto .footer +{ + border-right: 1em solid $*content_border; + border-top: 1px solid $*content_border; + font-size: 0.8em; + margin-top: 0; + padding-right: 0.8em; + text-align: right; +} +/* Entry */ +.entry .text .userpic, .replyto .text .userpic +{ + float: left; + margin: .1em .5em .1em .5em; +} +.entry .text .clearer, .replyto .text .clearer +{ + clear: left; + display: block; +} +.entry .text .currents +{ + margin-top: 0; +} +/* Comments */ +.comment_page .leave_comment, .selector +{ + text-align: center; +} +.comment_page .footer .pages +{ + text-align: left; +} +/* YearPage specific CSS */ +.calendar +{ + width: 100%; +} +.calendar .day, .calendar .day_with_posts +{ + border: 1px solid #000; + width: 14%; +} +.calendar .day_with_posts +{ + background-color: $*accent_bgcolor; +} +.calendar .day_with_posts a +{ + display: block; + text-decoration: none; + width: 100%; +} +.comment_bar_one, .comment_bar_two, .comment_bar_screened +{ + width: 100%; margin-top: 1em; +} +.comment_bar_one +{ + background-color: $*comment_bar_one_bgcolor; + color: $*comment_bar_one_fgcolor; +} +.comment_bar_two +{ + background-color: $*comment_bar_two_bgcolor; + color: $*comment_bar_two_fgcolor; +} +.comment_bar_screened +{ + background-color: $*comment_bar_screened_bgcolor; + color: $*comment_bar_screened_fgcolor; +} +#footer +{ + background-color: $*footer_bgcolor; + color: $*footer_fgcolor; + font-size: .8em; + margin-left: 10%; + margin-right: 10%; + text-align: center; + width: 80%; +} +#footer a +{ + color: $*footer_fgcolor; +} + """; +} + +################################################################################ +# +# Sidebar Boxes +# + +# A simple sidebar box: +# print_sidebar_box("Title", "My screenname: test"); +# +# The same sidebar box, but with some additional css rules: +# print_sidebar_box("Title", "My screenname: test", "text-decoration: underline"); + +function print_sidebar_box(string title, string body, string style) +{ + println """"""; + println """ """; + println """ """; + println """
    """; +} + +function print_sidebar_box(string title, string body) +{ + print_sidebar_box($title, $body, ""); +} + +function Page::lay_sidebar_view_userpic() : string +{ + return ""; +} +function print_sidebar_userpic () +{ + var Page page = get_page(); + var string return; + + var Image up_img = $page.journal.default_pic; + if ($page->lay_sidebar_view_userpic() != "") { + $return = $page->lay_sidebar_view_userpic(); + } else { + if (defined $up_img) { + $return = """
    """; + } + $return = $return + $page.journal.name + "
    " + $page.journal; + } + print_sidebar_box($*text_sidebar_profile,$return,"text-align: center"); +} + +function Page::lay_sidebar_view_summary() : string +{ + return ""; +} +function print_sidebar_summary() +{ + var Page page = get_page(); + if ($page->lay_sidebar_view_summary() != "") { + var string summary = """

    """; + $summary = $summary + $page->lay_sidebar_view_summary(); + $summary = $summary + "
    "; + print_sidebar_box($*text_sidebar_summary,$summary); + } +} + +function print_sidebar_linklist() +{ + var Page p = get_page(); + if (size $p.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + var string list = "
    "; + foreach var UserLink l ($p.linklist) { + if ($l.title) { + if ($l.is_heading) { + $list = $list + """$l.title
    """; + } else { + $list = $list + """$l.title
    """; + } + } else { + $list = $list + "

    "; + } + } + $list = $list + "
    "; + print_sidebar_box($*text_sidebar_links, $list); +} + +function print_sidebar_blurb () +{ + if ($*sidebar_blurb != "") { + print_sidebar_box($*text_sidebar_blurb,$*sidebar_blurb); + } +} + +function print_sidebar_calendar() +{ + var string calendar; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """"""; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + if ($d.num_entries) { + $calendar = $calendar + """"""; + } else { + $calendar = $calendar + """"""; + } + } + $calendar = $calendar + "\n"; + } + $calendar = $calendar + "
     $d.day$d.day
    "; + } + if ($calendar != "") { + print_sidebar_box($month, $calendar, "text-align: left"); + } +} + +# By default, the first sidebar box (profile) is fixed, +# and the order of the rest is determined by the sidebar properties. +# +# If you want to override the top two boxes, or want to define the order +# of boxes without using the provided properties, just write a new user layer +# and put each print_sidebar_foo function in the order that you want them: +# +# function print_sidebar() +# { +# print_sidebar_linklist(); +# print_sidebar_calendar(); +# [etc] +# } + +function print_sidebar() +{ + print_sidebar_userpic(); + if ($*sidebar_position_one != "nothing") { + if ($*sidebar_position_one == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_one == "links") { + print_sidebar_linklist(); + } elseif ($*sidebar_position_one == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_one == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_two != "nothing") { + if ($*sidebar_position_two == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_two == "links") { + print_sidebar_linklist(); + } elseif ($*sidebar_position_two == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_two == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_three != "nothing") { + if ($*sidebar_position_three == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_three == "links") { + print_sidebar_linklist(); + } elseif ($*sidebar_position_three == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_three == "calendar") { + print_sidebar_calendar(); + } + } + if ($*sidebar_position_four != "nothing") { + if ($*sidebar_position_four == "summary") { + print_sidebar_summary(); + } elseif ($*sidebar_position_four == "links") { + print_sidebar_linklist(); + } elseif ($*sidebar_position_four == "blurb") { + print_sidebar_blurb(); + } elseif ($*sidebar_position_four == "calendar") { + print_sidebar_calendar(); + } + } +} + +################################################################################ +# +# Content Boxes +# + + +# Main body content should be placed in these generic content boxes +function print_content_box (string title, string body) +{ + # title + println """"""; + println """ """; + println """
    """; + println """  $title"""; + println """
    """; + + # body + println """"""; + println """
    $body
    """; +} + +function print_content_tab (string content) +{ + println """

    $content

    """; +} + +function format_replyto(Page p, Entry e, EntryLite el) : string +{ + var string replyto = ""; + + # Named anchor to link from page summary + $replyto = $replyto + """
    """; + var string subject = $el.subject != "" ? $el.subject : $*text_nosubject; + var string time = $el.time->time_format(); + $replyto = $replyto + """

    $subject @ $time

    """; + $replyto = $replyto + """
    """; + if (defined $el.poster) { + if (defined $el.userpic) { + $replyto = $replyto + """"""; + } + $replyto = $replyto + $el.poster->as_string(); + if ($el.poster.username != $e.poster.username) { + $replyto = $replyto + " commented on " + $e.poster->as_string() + "'s post"; + } + if ($e.poster.username != $e.journal.username) { + var string preposition = $e.poster.username == $el.poster.username ? + " posted in " : " in "; + $replyto = $replyto + $preposition + $e.journal->as_string(); + } + } else { + $replyto = $replyto + "Anonymous commented on " + $e.poster->as_string() + "'s post"; + if ($e.poster.username != $e.journal.username) { + $replyto = $replyto + " in " + $e.journal->as_string(); + } + } + $replyto = $replyto + ":

    " + $el.text; + $replyto = $replyto + """
     
    """; + $replyto = $replyto + "
    "; + $replyto = $replyto + """
    """; + return $replyto; +} + +function print_replyto(Page p, Entry e, EntryLite el) +{ + print format_replyto($p, $e, $el); +} + +function format_entry(Page p, Entry e, Color bgcolor, Color fgcolor, bool viewing_thread) : string +{ + var string entry = ""; + + # Named anchor to link from page summary + $entry = $entry + """"""; + $entry = $entry + """
    """; + var string subject = $e.subject != "" ? $e.subject : $*text_nosubject; + var string time = $e.time->time_format(); + $entry = $entry + """

    $e.security_icon $subject @ $time

    """; + $entry = $entry + """
    """; + + if (($p.view == "friends" or + $e.poster.username != $e.journal.username or + ($*show_entry_userpic and defined $e.userpic))) { + if ($p.view == "friends") { + if (defined $e.userpic) { + $entry = $entry + """"""; + } + if ($e.poster.username != $e.journal.username) { + $entry = $entry + $e.poster->as_string() + ", posting in "; + } + $entry = $entry + $e.journal->as_string() + ":
    "; + } elseif ($e.poster.username != $e.journal.username) { + if (defined $e.userpic) { + $entry = $entry + """"""; + } + $entry = $entry + $e.poster->as_string() + ":
    "; + } elseif (defined $e.userpic) { + $entry = $entry + """

    """; + } + } + if (size $e.metadata) { + $entry = $entry + """

    """; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $entry = $entry + """
    $text: $val
    """; + } + $entry = $entry + "
    \n"; + } + + if ($e.tags) { + var int tcount = 0; + $entry = $entry + """
    Tags: """; + foreach var Tag t ($e.tags) { + $entry = """$entry"""; + $tcount++; + if ($tcount != size $e.tags) { $entry = """$entry, """; } + } + $entry = """$entry
    """; + } + + if (size $e.tags or size $e.metadata) { $entry = "$entry
    "; } + if (not $viewing_thread) { $entry = $entry + $e.text; } + $entry = $entry + """
     
    """; + $entry = $entry + "
    "; + + # Comments + $entry = $entry + """
    """; + if ($e.comments.enabled and $p.view != "entry") { + if ($e.comments.count > 0 or $e.comments.screened) { + $entry = $entry + """""" + + get_plural_phrase($e.comments.count, $p.view == "friends" ? + "text_read_comments_friends" : "text_read_comments") + + ""; + $entry = $entry + " | "; + } + $entry = $entry + """""" + ($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment) + ""; + } elseif ($p.view == "entry") { + var Link l = new Link; + foreach var string ls ($e.link_keyseq) { + $l = $e->get_link($ls); + if (defined $l) { + $entry = $entry + """$l.caption """; + } + if($ls != $e.link_keyseq[size($e.link_keyseq) - 1]) { $entry = $entry + """ | """; } + } + } else { + $entry = $entry + " "; + } + $entry = $entry + "
    "; + $entry = $entry + """
    """; + return $entry; +} + +function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor, bool viewing_thread) { + print format_entry($p, $e, $bgcolor, $fgcolor, $viewing_thread); +} + +################################################################################ +# +# Page +# + +function Page::lay_view_nav() : string +{ + return ""; +} + +function Page::print_entry(Entry e) { + print_entry($this, $e, null Color, null Color, false); +} + +function Page::print() +{ + var string subtitle = $.global_subtitle ? """

    $.global_subtitle

    """: ""; + var string view_title = $this->view_title() != "" ? $this->view_title() + ":" : " "; + var string title_bar = """"""; + $title_bar = $title_bar + """ """; + $title_bar = $title_bar + """ """; + $title_bar = $title_bar + """

    $.global_title

    $subtitle
    """; + + + println """"""; + # Head + println ""; + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + println """$.global_title"""; + println ""; + + if ($*title_position == "top" or $*title_position == "both") { println $title_bar; print "
    "; } + + println """"""; + if ($*sidebar_position == "left") { println """"; } + println """"; + if ($*sidebar_position == "right") { println """"; } + println """
    """; $this->print_body(); "
    """; + + println """
    """; + + if ($*title_position == "bottom" or $*title_position == "both") { println $title_bar; } + + println ""; +} + +################################################################################ +# +# RecentPage +# + +function RecentPage::lay_view_nav() : string +{ + var string return; + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + $return = $return + " | "; + if ($.nav.backward_url != "") { + $return = $return + """Previous Page"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { $return = $return + " | "; } + if ($.nav.forward_url != "") { + $return = $return + """Next Page"""; + } + } + return $return; +} + +function RecentPage::lay_sidebar_view_summary() : string +{ + var string return; + foreach var Entry e ($.entries) { + var string subject = $e.subject != "" ? $e.subject : $*text_nosubject; + $return = $return + "→"; + if ($e.security) { $return = $return + " $e.security_icon"; } + $return = $e.poster.username != $.journal.username ? + $return + """ $e.poster:
    $subject
    """ : + $return + """ $subject
    """; + } + return $return; +} + +function RecentPage::print_body() { + foreach var Entry e ($.entries) { + if ($e.new_day) { print_content_tab($e.time->date_format("long")); print """
    """; } + $this->print_entry($e); + if ($e.end_day) { print """
    """; } + } +} + +################################################################################ +# +# FriendsPage +# + +function FriendsPage::lay_sidebar_view_summary() : string +{ + var string return; + foreach var Entry e ($.entries) { + var string poster = $e.poster.username != $e.journal.username ? $e.poster->as_string() + ", posting in " + $e.journal->as_string() : $e.journal->as_string(); + var string subject = $e.subject != "" ? $e.subject : $*text_nosubject; + $return = $return + "→"; + if ($e.security) { $return = $return + " $e.security_icon"; } + $return = $return + """ $poster:
    $subject
    """; + } + return $return; +} + +################################################################################ +# +# EntryPage +# + +function EntryPage::lay_view_nav() : string +{ + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + var string return; + if ($prev.url != "" or $next.url != "") { + $return = $return + " | "; + if ($prev.url != "") { + $return = $return + """$prev.caption"""; + } + if ($prev.url != "" and $next.url != "") { $return = $return + " | "; } + if ($next.url != "") { + $return = $return + """$next.caption"""; + } + } + return $return; +} + +function EntryPage::lay_sidebar_view_summary() : string { + var string return; + foreach var Comment c ($.comments) { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subject = $c.subject != "" ? $c.subject : $*text_nosubject; + $return = $return + """→ $poster:
    $subject
    """; + } + return $return; +} + +function EntryPage::print_body () { + print_content_tab($.entry.time->date_format("long")); + println """
    """; + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + println "
    "; + + if ($.entry.comments.enabled) + { + print_content_tab("Comments"); + println """
    """; + + var string pages; + if (not $.comment_pages.all_subitems_displayed) { + $pages = lang_page_of_pages($.comment_pages.current, $.comment_pages.total) + " - "; + foreach var int i (1 .. $.comment_pages.total) { + if ($i == $.comment_pages.current) { + $pages = "$pages [$i] "; + } else { + var string url_of = $.comment_pages->url_of($i); + $pages = """$pages [$i] """; + } + } + println $pages; + } else { + println " "; + } + println """
    """; + if ($.comment_pages.total_subitems > 0) { + if ($this.multiform_on) { $this->print_multiform_start(); } + $this->print_comments($.comments); + } + if ($.entry.comments.count > 5) { println """"""; } + println """
    "; + if ($this.multiform_on) { + println """
    """; + $this->print_multiform_actionline(); + println "
    "; + $this->print_multiform_end(); + } + println "
    "; + } +} + +function EntryPage::print_comment(Comment c) +{ + var string class = ""; + if ($c.screened) { + $class = "comment_bar_screened"; + } elseif ($c.depth % 2) { + $class = "comment_bar_one"; + } else { + $class = "comment_bar_two"; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + println """
    """; + println """"""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + println """"""; + } + + println """
    [User Picture Icon]"""; + + println """"; + + println """"; + + println """"; + + println """"""; + + println "
    """; + println ""; + println """"""; + println """"; + if ($c.metadata{"poster_ip"}) { println """"; } + println "
    From:$poster
    Date:"""; + println $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(""" + $c.metadata{"poster_ip"} + ")
    """; + if ($this.multiform_on) { + println """ """; + $c->print_multiform_check(); + } + $c->print_linkbar(); + println "
    """; + println (defined $c.subject_icon or $c.subject != "") ? """

    $c.subject_icon $c.subject

    """ : ""; + println "
    (Link)
    "; + println """
    $c.text
    """; + println """
    """; + if ($c.frozen) { + println """(Replies frozen) """; + } else { + println """(Reply to this) """; + } + if ($c.parent_url != "") { println """(Parent) """; } + if ($c.thread_url != "") { println """(Thread) """; } + println "
    "; +} + +################################################################################ +# +# ReplyPage +# + +function ReplyPage::print_body () +{ + print_content_tab("Reply To:"); + println """
    """; + print_replyto($this, $.entry, $.replyto); + println "
    "; + + print_content_tab("Your Reply:"); + println """
    """; + $.form->print(); + println "
    "; +} + +################################################################################ +# +# YearPage +# + +function YearPage::lay_view_nav() : string +{ + var string return = " | "; + foreach var YearYear y ($.years) + { + $return = $y.displayed ? $return + $y.year : $return + """$y.year"""; + if ($y.url != $.years[size($.years) - 1].url) { $return = $return + """ | """; } + } + return $return; +} + +function YearPage::lay_sidebar_view_summary () : string +{ + var string return; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + $return = $return + """→ """ + $m->month_format() + "
    "; + } + } + return $return; +} + +function YearPage::print_body() +{ + print_content_tab(string($.year)); + println """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + println "
    "; +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + + println """
    "; + println """"""; + foreach var int d (weekdays()) { + println """"; + } + println "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + println "
    """ + $*lang_dayname_short[$d] + "
    "; + println """
    """; +} + +function YearWeek::print () +{ + println ""; + if ($.pre_empty) { println """ """; } + foreach var YearDay d ($.days) { + if ($d.num_entries) { + println """$d.day ($d.num_entries)"""; + } else { + println """$d.day"""; + } + } + if ($.post_empty) { println """ """; } + println ""; +} + +################################################################################ +# +# MonthPage +# + +function MonthPage::lay_view_nav() : string +{ + var string return; + if ($.prev_url != "" or $.next_url != "") + { + $return = $return + " | "; + if ($.prev_url != "") { $return = $return + """Previous Month"""; } + if ($.prev_url != "" and $.next_url != "") { $return = $return + " | "; } + if ($.next_url != "") { $return = $return + """Next Month"""; } + } + return $return; +} + +function MonthPage::lay_sidebar_view_summary () : string +{ + var string return; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + $return = $return + """→ """ + lang_ordinal($d.day) + "
    "; + } + } + return $return; +} + +function MonthPage::print_body() +{ + println """
    """; + $.redir->print_hiddens(); + + var string selector; + if (size $.months > 1) { + $selector = "\n"; + } + + print_content_tab($.date->date_format($*lang_fmt_month_long)); + println """
    """; + if ($selector != "") { println """
    Switch to: $selector
    """; } + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + println """

    """; + print lang_ordinal($d.day); + println """

    \n
    """; + $d->print_subjectlist(); + println """
    \n
    """; + } + } + println "
    \n"; +} + +################################################################################ +# +# DayPage +# + +function DayPage::lay_view_nav() : string { + var string return; + if ($.prev_url != "" or $.next_url != "") + { + $return = $return + " | "; + if ($.prev_url != "") { $return = $return + """$*text_day_prev"""; } + if ($.prev_url != "" and $.next_url != "") { $return = $return + " | "; } + if ($.next_url != "") { $return = $return + """$*text_day_next"""; } + } + return $return; +} + +function DayPage::print_body() { + if ($.has_entries) { + println """
    """; + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + println "
    "; + } else { + println """

    $*text_noentries_day

    """; + } +} + +################################################################################ +# +# DayPage +# + +function print_theme_preview () +{ + print """ +
    + + +
    + Journal Title + + +
    Sed ut perspiciatis:
    Recent Entries | Archive | Friends | User Info +
    +
    +
    + + +
    + + + +
     Profile 
    John Doe
    test

    +
    +
    Sed ut perspiciatis:
    +
    +
    +
    gfdsgdsgfdsgd @ 01:18 am
    +
    Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
     
    +
     
    +
    +
    +
    """; +} diff --git a/livejournal/bin/upgrading/s2layers/haven/themes.s2 b/livejournal/bin/upgrading/s2layers/haven/themes.s2 new file mode 100755 index 0000000..b02020b --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/haven/themes.s2 @@ -0,0 +1,392 @@ +#NEWLAYER: haven/bluemonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Adaywien"; +layerinfo "redist_uniq" = "haven/bluemonochromatic"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/blueanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Gwirasien"; +layerinfo "redist_uniq" = "haven/blueanalogous"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/bluecomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Etaella"; +layerinfo "redist_uniq" = "haven/bluecomplementary"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/bluesplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Sevaeviel"; +layerinfo "redist_uniq" = "haven/bluesplit_complementary"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/bluedouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Glirewen"; +layerinfo "redist_uniq" = "haven/bluedouble_complementary"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/bluetriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Uloewiel"; +layerinfo "redist_uniq" = "haven/bluetriadic"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/bluetetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Yberawen"; +layerinfo "redist_uniq" = "haven/bluetetradic"; + +set color_scheme_base = "#1575C7"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/orangemonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Olerassa"; +layerinfo "redist_uniq" = "haven/orangemonochromatic"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/orangeanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Vardothiel"; +layerinfo "redist_uniq" = "haven/orangeanalogous"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/orangecomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Cadelaviel"; +layerinfo "redist_uniq" = "haven/orangecomplementary"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/orangesplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Eriralle"; +layerinfo "redist_uniq" = "haven/orangesplit_complementary"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/orangedouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Bemeth"; +layerinfo "redist_uniq" = "haven/orangedouble_complementary"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/orangetriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Welamma"; +layerinfo "redist_uniq" = "haven/orangetriadic"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/orangetetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Jerodia"; +layerinfo "redist_uniq" = "haven/orangetetradic"; + +set color_scheme_base = "#F3904E"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/greenmonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Cendarien"; +layerinfo "redist_uniq" = "haven/greenmonochromatic"; + +set color_scheme_base = "#48C754"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/greenanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Wicarede"; +layerinfo "redist_uniq" = "haven/greenanalogous"; + +set color_scheme_base = "#48C754"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/greencomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Laylla"; +layerinfo "redist_uniq" = "haven/greencomplementary"; + +set color_scheme_base = "#48C754"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/greensplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Dwiama"; +layerinfo "redist_uniq" = "haven/greensplit_complementary"; + +set color_scheme_base = "#48C754"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/greendouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Missi"; +layerinfo "redist_uniq" = "haven/greendouble_complementary"; + +set color_scheme_base = "#48C754"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/greentriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Gwuwien"; +layerinfo "redist_uniq" = "haven/greentriadic"; + +set color_scheme_base = "#48C754"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/greentetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Gerrathien"; +layerinfo "redist_uniq" = "haven/greentetradic"; + +set color_scheme_base = "#48C754"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/violetmonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Erudith"; +layerinfo "redist_uniq" = "haven/violetmonochromatic"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/violetanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Narwen"; +layerinfo "redist_uniq" = "haven/violetanalogous"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/violetcomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Yballan"; +layerinfo "redist_uniq" = "haven/violetcomplementary"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/violetsplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Araymwen"; +layerinfo "redist_uniq" = "haven/violetsplit_complementary"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/violetdouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Cydia"; +layerinfo "redist_uniq" = "haven/violetdouble_complementary"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/violettriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Eowiresa"; +layerinfo "redist_uniq" = "haven/violettriadic"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/violettetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Waedith"; +layerinfo "redist_uniq" = "haven/violettetradic"; + +set color_scheme_base = "#9D1EC7"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/yellowmonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Vauwen"; +layerinfo "redist_uniq" = "haven/yellowmonochromatic"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/yellowanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Praressi"; +layerinfo "redist_uniq" = "haven/yellowanalogous"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/yellowcomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Lelivia"; +layerinfo "redist_uniq" = "haven/yellowcomplementary"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/yellowsplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Afalewen"; +layerinfo "redist_uniq" = "haven/yellowsplit_complementary"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/yellowdouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Umoenna"; +layerinfo "redist_uniq" = "haven/yellowdouble_complementary"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/yellowtriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Trirwen"; +layerinfo "redist_uniq" = "haven/yellowtriadic"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/yellowtetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Jerilisien"; +layerinfo "redist_uniq" = "haven/yellowtetradic"; + +set color_scheme_base = "#F3EAA0"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/redmonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Ethowiel"; +layerinfo "redist_uniq" = "haven/redmonochromatic"; + +set color_scheme_base = "#F35951"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/redanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Dwyweth"; +layerinfo "redist_uniq" = "haven/redanalogous"; + +set color_scheme_base = "#F35951"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/redcomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Bylind"; +layerinfo "redist_uniq" = "haven/redcomplementary"; + +set color_scheme_base = "#F35951"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/redsplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Qiradia"; +layerinfo "redist_uniq" = "haven/redsplit_complementary"; + +set color_scheme_base = "#F35951"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/reddouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Kairawen"; +layerinfo "redist_uniq" = "haven/reddouble_complementary"; + +set color_scheme_base = "#F35951"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/redtriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Piliwien"; +layerinfo "redist_uniq" = "haven/redtriadic"; + +set color_scheme_base = "#F35951"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/redtetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Gwiradia"; +layerinfo "redist_uniq" = "haven/redtetradic"; + +set color_scheme_base = "#F35951"; +set color_scheme = "tetradic"; + +#NEWLAYER: haven/indigomonochromatic +layerinfo "type" = "theme"; +layerinfo "name" = "Elirethiel"; +layerinfo "redist_uniq" = "haven/indigomonochromatic"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "monochromatic"; + +#NEWLAYER: haven/indigoanalogous +layerinfo "type" = "theme"; +layerinfo "name" = "Oneawia"; +layerinfo "redist_uniq" = "haven/indigoanalogous"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "analogous"; + +#NEWLAYER: haven/indigocomplementary +layerinfo "type" = "theme"; +layerinfo "name" = "Gwicia"; +layerinfo "redist_uniq" = "haven/indigocomplementary"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "complementary"; + +#NEWLAYER: haven/indigosplit_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Grabeth"; +layerinfo "redist_uniq" = "haven/indigosplit_complementary"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "split_complementary"; + +#NEWLAYER: haven/indigodouble_complementary +layerinfo "type" = "theme"; +layerinfo "name" = "Alalicien"; +layerinfo "redist_uniq" = "haven/indigodouble_complementary"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "double_complementary"; + +#NEWLAYER: haven/indigotriadic +layerinfo "type" = "theme"; +layerinfo "name" = "Legeinia"; +layerinfo "redist_uniq" = "haven/indigotriadic"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "triadic"; + +#NEWLAYER: haven/indigotetradic +layerinfo "type" = "theme"; +layerinfo "name" = "Olowen"; +layerinfo "redist_uniq" = "haven/indigotetradic"; + +set color_scheme_base = "#6F60C7"; +set color_scheme = "tetradic"; + diff --git a/livejournal/bin/upgrading/s2layers/i18nc/da1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/da1.s2 new file mode 100755 index 0000000..0c07cef --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/da1.s2 @@ -0,0 +1,161 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/da1"; +layerinfo "name" = "Danish"; +layerinfo "langcode" = "da"; +layerinfo "author_name" = "LiveJournal Danish Translation Team"; +layerinfo "author_email" = "lj_dansk@livejournal.com"; + +layerinfo "source_viewable" = 1; + +set lang_current = "da"; + +#[[ date and time l12n ]] + +# Kort datoformat +set lang_fmt_date_short = "%%d%%/%%m%%/%%yy%%"; +# Mellem dato +set lang_fmt_date_med = "%%dayord%% %%mon%%., %%yyyy%%"; +# Mellem dato med forkortet ugedag +set lang_fmt_date_med_day = "%%da%%, d. %%dayord%% %%mon%%., %%yyyy%%"; +# Lang dato +set lang_fmt_date_long = "%%dayord%% %%month%%, %%yyyy%%"; +# Lang dato med ugedag +set lang_fmt_date_long_day = "%%day%%, d. %%dayord%% %%month%%, %%yyyy%%"; +# Tidsformat +set lang_fmt_time_short = "%%HH%%:%%min%%"; +# Kort mÃ¥nedsformat (samme som engelsk) +set lang_fmt_month_short = "%%m%%/%%yy%%"; +# Mellem mÃ¥ned (samme som engelsk) +set lang_fmt_month_med = "%%mon%% %%yyyy%%"; +# Lang mÃ¥ned (samme som engelsk) +set lang_fmt_month_long = "%%month%% %%yyyy%%"; +# Ã…rets mÃ¥neder, lang +set lang_monthname_long = [ "", "Januar", "Februar", "Marts", + "April", "Maj", "Juni", + "Juli", "August", "September", + "Oktober", "November", "December" ]; +# Ã…rets mÃ¥neder, kort +set lang_monthname_short = [ "", "Jan", "Feb", "Mar", + "Apr", "Maj", "Jun", + "Jul", "Aug", "Sep", + "Okt", "Nov", "Dec" ]; +# Ugens dage, lang +set lang_dayname_long = [ "", "Søndag", "Mandag", "Tirsdag", "Onsdag", + "Torsdag", "Fredag", "Lørdag" ]; +# Ugens dage, kort +set lang_dayname_short = [ "", "Søn", "Man", "Tirs", "Ons", + "Tors", "Fre", "Lør" ]; +set reg_firstdayofweek = "monday"; + +#[[ texttranslation ]] + +# Currents +set text_meta_music = "Nuværende musik"; +set text_meta_mood = "Nuværende humør"; +# Comments +set text_post_comment = "Skriv kommentar"; +set text_read_comments = "1 kommentar // # kommentarer"; +set text_post_comment_friends = "Skriv kommentar"; +set text_read_comments_friends = "1 kommentar // # kommentarer"; +# Skiplinks +set text_skiplinks_back="Forrige #"; +set text_skiplinks_forward="Næste #"; +# Views +set text_view_recent = "Seneste poster"; +set text_view_friends = "Venner"; +set text_view_archive = "Arkiv"; +set text_view_userinfo = "Brugerinfo"; +set text_view_month = "Vis emner"; # "Vis overskrifter"? +# Misc. texts +set text_nosubject = "(intet emne)"; +set text_noentries_recent = "Der er ingen poster at vise."; +set text_noentries_day = "Der blev ikke skrevet nogle poster denne dag."; +set text_permalink = "Link"; +set text_month_screened_comments = "m. skærmede"; +set text_multiform_check = "Vælg:"; +set text_multiform_des = "Massehandling pÃ¥ valgte kommentarer:"; +set text_multiform_btn = "Udfør handling"; +set text_multiform_opt_unscreen = "Afskærm"; +set text_multiform_opt_screen = "Skærm"; +set text_multiform_opt_delete = "Slet"; +set text_multiform_conf_delete = "Slet valgte kommentarer?"; +set text_day_prev = "Forrige dag"; +set text_day_next = "Næste dag"; +set text_comment_from = "Fra:"; +set text_comment_date = "Dato:"; +set text_comment_ipaddr = "IP adresse:"; +set text_comment_reply = "Svar"; +set text_comment_parent = "Forælder"; +set text_comment_thread = "TrÃ¥d"; +set text_reply_back = "Læs kommentarer"; +set text_reply_nocomments_header = "Kommentarer slÃ¥et fra:"; +set text_reply_nocomments = "Kommentarer til denne post er blevet slÃ¥et fra."; +set text_poster_anonymous = "(Anonym)"; +set text_website_default_name = "Mit websted"; + +#[[ function translations ]] + +# Samme som engelsk: +#function lang_map_plural (int n) : int { +# if ($n == 1) { return 0; } # singular +# return 1; # plural +#} + +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "Side $pg af $pgs"; +} + +function lang_ordinal(int num) [notags] : string { + return $num+"."; +} + +function lang_user_wrote(UserLite u) : string +"Returns text describing that the user wrote something. i18nc layers should override this." +{ + if (defined $u) { + return $u->as_string()+" skrev"; + } + else { + return "En anonym bruger skrev"; + } +} + +function lang_at_datetime(DateTime d) : string +"Returns a string saying \"at {the data and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." +{ +# return "d. 1. Januar, 2004, kl. 23:01"; + return "d. " + $d->date_format("long") + ", kl. " + $d->time_format(); +} +### OvenstÃ¥ende skal testes i brug ASAP. ### + +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Dag"; } + if ($viewid == "month") { return "MÃ¥ned"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Læs kommentarer"; } + if ($viewid == "reply") { return "Skriv kommentar"; } + return "Ukendt visningstype"; +} + +function server_sig() { + """Kørt af $*SITENAME"""; +} + +function ReplyPage::view_title() : string { + return "Skriv kommentar"; +} + +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " skrev i "; + $e.journal->print(); + } +} diff --git a/livejournal/bin/upgrading/s2layers/i18nc/de1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/de1.s2 new file mode 100755 index 0000000..2e52c14 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/de1.s2 @@ -0,0 +1,147 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/de1"; +layerinfo "name" = "German"; +layerinfo "langcode" = "de"; +layerinfo "author_name" = "Timwi"; +layerinfo "author_email" = "timwi@livejournal.com"; + +layerinfo "source_viewable" = 1; + +set lang_current = "de"; + +# Kurzes Datumsformat +set lang_fmt_date_short = "%%d%%.%%m%%.%%yy%%"; +# Mittellanges Datumsformat +set lang_fmt_date_med = "%%dayord%% %%mon%% %%yyyy%%"; +# Mittellanges Datumsformat mit Wochentag +set lang_fmt_date_med_day = "%%da%%, %%dayord%% %%mon%% %%yyyy%%"; +# Langes Datumsformat +set lang_fmt_date_long = "%%dayord%% %%month%% %%yyyy%%"; +# Langes Datumsformat mit Wochentag +set lang_fmt_date_long_day = "%%day%%, %%dayord%% %%month%% %%yyyy%%"; +# Zeitformat +set lang_fmt_time_short = "%%HH%%:%%min%%"; +# Kurzes Monatsformat +#set lang_fmt_month_short = "%%mon%% %%yy%%"; +# Mittleres Monatsformat +#set lang_fmt_month_med = "%%mon%% %%yyyy%%"; +# Langes Monatsformat +#set lang_fmt_month_long = "%%month%% %%yyyy%%"; +# Monatsnamen +set lang_monthname_long = [ "", "Januar", "Februar", "März", + "April", "Mai", "Juni", + "Juli", "August", "September", + "Oktober", "November", "Dezember" ]; +# Monatsabkürzungen +set lang_monthname_short = [ "", "Jan", "Feb", "Mär", + "Apr", "Mai", "Jun", + "Jul", "Aug", "Sep", + "Okt", "Nov", "Dez" ]; +# Wochentagnamen +set lang_dayname_long = [ "", "Sonntag", "Montag", "Dienstag", "Mittwoch", + "Donnerstag", "Freitag", "Samstag" ]; +# Wochentagabkürzungen +set lang_dayname_short = [ "", "So", "Mo", "Di", "Mi", + "Do", "Fr", "Sa" ]; +set reg_firstdayofweek = "monday"; + +#[[ texttranslation ]] + +# Currents +set text_meta_music = "Aktuelle Musik"; +set text_meta_mood = "Aktuelle Stimmung"; +# Comments +set text_post_comment = "Kommentar hinterlassen"; +set text_read_comments = "1 Kommentar // # Kommentare"; +set text_post_comment_friends = "Kommentar hinterlassen"; +set text_read_comments_friends = "1 Kommentar // # Kommentare"; +# Skiplinks +set text_skiplinks_back="Vorherige #"; +set text_skiplinks_forward="Nächste #"; +# Views +set text_view_recent = "Neueste Einträge"; +set text_view_friends = "Freunde"; +set text_view_archive = "Archiv"; +set text_view_userinfo = "Benutzerprofil"; +set text_view_month = "Monatsansicht"; # "Vis overskrifter"? +# Misc. texts +set text_nosubject = "(kein Betreff)"; +set text_noentries_recent = "Keine Einträge."; +set text_noentries_day = "An diesem Tag wurden keine Einträge gemacht."; +set text_permalink = "Link"; +set text_month_screened_comments = "zzgl. verdeckte"; +set text_multiform_check = "Auswählen:"; +set text_multiform_des = "Alle ausgewählten Kommentare:"; +set text_multiform_btn = "Ausführen"; +set text_multiform_opt_unscreen = "Aufdecken"; +set text_multiform_opt_screen = "Verdecken"; +set text_multiform_opt_delete = "Löschen"; +set text_multiform_conf_delete = "Bist du dir sicher, dass du die ausgewählten Kommentare löschen möchtest?"; +set text_day_prev = "Vorheriger Tag"; +set text_day_next = "Nächster Tag"; +set text_comment_from = "Von:"; +set text_comment_date = "Datum:"; +set text_comment_ipaddr = "IP-Adresse:"; +set text_comment_reply = "Darauf antworten"; +set text_comment_parent = "Kommentar davor"; +set text_comment_thread = "Nachfolgende Kommentare"; +set text_reply_back = "Kommentare lesen"; +set text_reply_nocomments_header = "Kommentarfunktion deaktiviert:"; +set text_reply_nocomments = "Für diesen Eintrag wurde die Kommentarfunktion deaktiviert."; +set text_website_default_name = "Meine Webseite"; +set text_poster_anonymous = "(Anonym)"; + +#[[ function translations ]] + +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "Seite $pg von $pgs"; +} + +function lang_ordinal(int num) [notags] : string { + return $num+"."; +} + +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Tag"; } + if ($viewid == "month") { return "Monat"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Kommentare lesen"; } + if ($viewid == "reply") { return "Kommentar hinterlassen"; } + return "Unbekannte Ansicht"; +} + +function ReplyPage::view_title() : string { + return "Kommentar hinterlassen"; +} + +function server_sig() { + """Gehostet von $*SITENAME"""; +} + +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " schrieb in "; + $e.journal->print(); + } +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" schrieb"; + } + else { + return "Ein anonymer Benutzer schrieb"; + } +} + +function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." { + return "am " + $d->date_format("long") + " um " + $d->time_format(); +} diff --git a/livejournal/bin/upgrading/s2layers/i18nc/en1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/en1.s2 new file mode 100755 index 0000000..33dc7f5 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/en1.s2 @@ -0,0 +1,9 @@ +#-*-s2-*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/en1"; +layerinfo "name" = "English"; +layerinfo "langcode" = "en"; + +# Note: this file doesn't actually override anything, since the core +# is in English diff --git a/livejournal/bin/upgrading/s2layers/i18nc/eo1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/eo1.s2 new file mode 100755 index 0000000..8242ebd --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/eo1.s2 @@ -0,0 +1,139 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/eo1"; +layerinfo "name" = "Esperanto"; +layerinfo "langcode" = "eo"; +layerinfo "author_name" = "Timwi, Amuzulo"; +layerinfo "author_email" = "timwi@livejournal.com, amuzulo@livejournal.com"; + +layerinfo "source_viewable" = 1; + +set lang_current = "eo"; + +set lang_fmt_date_short = "%%yyyy%%-%%mm%%-%%dd%%"; +set lang_fmt_date_med = "%%dayord%% de %%mon%% %%yyyy%%"; +set lang_fmt_date_med_day = "%%da%%, la %%dayord%% de %%mon%% %%yyyy%%"; +set lang_fmt_date_long = "la %%dayord%% de %%month%% %%yyyy%%"; +set lang_fmt_date_long_day = "%%day%%, la %%dayord%% de %%month%% %%yyyy%%"; + +set lang_fmt_time_short = "%%HH%%:%%min%%"; +set lang_fmt_month_short = "%%mon%% %%yy%%"; +set lang_fmt_month_med = "%%mon%% %%yyyy%%"; +set lang_fmt_month_long = "%%month%% %%yyyy%%"; + +set lang_monthname_long = [ "", "januaro", "februaro", "marto", + "aprilo", "majo", "junio", + "julio", "aÅ­gusto", "septembro", + "oktobro", "novembro", "decembro" ]; + +set lang_monthname_short = [ "", "jan", "feb", "mar", + "apr", "maj", "jun", + "jul", "aÅ­g", "sep", + "okt", "nov", "dec" ]; + +set lang_dayname_long = [ "", "dimanĉo", "lundo", "mardo", "merkredo", + "ĵaÅ­do", "vendredo", "sabato" ]; + +set lang_dayname_short = [ "", "di", "lu", "ma", "me", + "ĵa", "ve", "sa" ]; +set reg_firstdayofweek = "monday"; + +#[[ texttranslation ]] + +# Currents +set text_meta_music = "Nuna muziko"; +set text_meta_mood = "Nuna humoro"; +# Comments +set text_post_comment = "AfiÅu novan komenton"; +set text_read_comments = "1 komento // # komentoj"; +set text_post_comment_friends = "AfiÅu novan komenton"; +set text_read_comments_friends = "1 komento // # komentoj"; +# Skiplinks +set text_skiplinks_back="# antaÅ­aj komentoj"; +set text_skiplinks_forward="# sekvontaj komentoj"; +# Views +set text_view_recent = "Lastatempaj enskribojn"; +set text_view_friends = "Geamikoj"; +set text_view_archive = "ArÄ¥ivo"; +set text_view_userinfo = "Uzantinformoj"; +set text_view_month = "Monataj temoj"; +# Misc. texts +set text_nosubject = "(neniu temo)"; +set text_noentries_recent = "Neniuj enskriboj."; +set text_noentries_day = "Ekzistas neniuj enskriboj en tiu tago."; +set text_permalink = "Ligilo"; +set text_month_screened_comments = "+ kaÅitoj"; +set text_multiform_check = "Elektu:"; +set text_multiform_des = "Amasagado por elektitaj komentoj:"; +set text_multiform_btn = "Agu"; +set text_multiform_opt_unscreen = "MalkaÅu"; +set text_multiform_opt_screen = "KaÅu"; +set text_multiform_opt_delete = "Forigu"; +set text_multiform_conf_delete = "Ĉu vi certas ke vi viÅas forigi la elektitajn komentojn?"; +set text_day_prev = "AntaÅ­a tago"; +set text_day_next = "Sekvonta tago"; +set text_comment_from = "De:"; +set text_comment_date = "Dato:"; +set text_comment_ipaddr = "IP-adreso:"; +set text_comment_reply = "Respondu al ĉi tiu"; +set text_comment_parent = "Patro"; +set text_comment_thread = "Fadeno"; +set text_reply_back = "Legu komentojn"; +set text_reply_nocomments_header = "Komentoj malebligitaj:"; +set text_reply_nocomments = "La uzanto malebligis komentojn por ĉi tiu enskribo."; +set text_website_default_name = "Mia TTT-ejo"; +set text_poster_anonymous = "(sennoma)"; + +#[[ function translations ]] + +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "PaÄo $pg da $pgs"; +} + +function lang_ordinal(int num) [notags] : string { + return $num + "-a"; +} + +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Tago"; } + if ($viewid == "month") { return "Monato"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Legu komentojn"; } + if ($viewid == "reply") { return "AfiÅu komenton"; } + return "Nekonata vido"; +} + +function ReplyPage::view_title() : string { + return "AfiÅu komenton"; +} + +function server_sig() { + """Funkciigita de $*SITENAME"""; +} + +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " skribis en "; + $e.journal->print(); + } +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" skribis"; + } + else { + return "Sennoma uzanto skribis"; + } +} + +function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." { + return "je " + $d->date_format("long") + " je " + $d->time_format(); +} diff --git a/livejournal/bin/upgrading/s2layers/i18nc/fi1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/fi1.s2 new file mode 100755 index 0000000..def8353 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/fi1.s2 @@ -0,0 +1,171 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/fi1"; +layerinfo "name" = "Finnish"; +layerinfo "langcode" = "fi"; +layerinfo "author_name" = "shiningkianna, zell_d"; + +layerinfo "source_viewable" = 1; + +set lang_current = "fi"; + +# Ajat ja päiväykset + +# Viikonpäivät +set lang_dayname_long = [ "", "sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai" ]; +set lang_dayname_short = [ "", "su", "ma", "ti", "ke", "to", "pe", "la" ]; + +# Pitkä päiväys +set lang_fmt_date_long = "%%dayord%% %%month%%ta %%yyyy%%"; +# Pitkä päiväys viikonpäivällä +set lang_fmt_date_long_day = "%%day%%, %%dayord%% %%month%%ta %%yyyy%%"; +# Keskipitkä päiväys +set lang_fmt_date_med = "%%d%%. %%mon%%. %%yyyy%%"; +# Keskipitkä päiväys viikonpäivällä +set lang_fmt_date_med_day = "%%da%%, %%dayord%% %%mon%%. %%yyyy%%"; +# Lyhyt päiväys +set lang_fmt_date_short = "%%d%%.%%m%%.%%yyyy%%"; +# Pitkä kuukausipäiväys +set lang_fmt_month_long = "%%month%% %%yyyy%%"; +# Keskipitkä kuukausipäiväys +set lang_fmt_month_med = "%%mon%% %%yyyy%%"; +# Lyhyt kuukausipäiväys +set lang_fmt_month_short = "%%m%%/%%yyyy%%"; +# Aika +set lang_fmt_time_short ="%%HH%%:%%min%%"; + +# Kuukaudet +set lang_monthname_long = [ "", "tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu" ]; +set lang_monthname_short = [ "", "tammik", "helmik", "maalisk", "huhtik", "toukok", "kesäk", "heinäk", "elok", "syysk", "lokak", "marrask", "jouluk" ]; + +# Viikko alkaa maanantaista +set reg_firstdayofweek = "monday"; + + +# Tekstit + +# Tämänhetkinen musiikki ja mieliala +set text_meta_mood = "Mieliala"; +set text_meta_music = "Musiikki"; +# Kommentit +set text_post_comment = "Jätä vastaus tähän"; +set text_post_comment_friends = "Jätä vastaus tähän"; +set text_read_comments = "1 kommentti // # kommenttia"; +set text_read_comments_friends = "1 kommentti // # kommenttia"; +# Linkit, joilla hypätään viestien yli +set text_skiplinks_back = "Edelliset #"; +set text_skiplinks_forward = "Seuraavat #"; +# Näkymät +set text_view_archive = "Arkisto"; +set text_view_friends = "Kaverit"; +set text_view_friends_comm = "Jäsenet"; +set text_view_friends_filter = "Kaverit (mukautettu suodatin)"; +set text_view_friendsfriends = "Kavereiden kaverit"; +set text_view_friendsfriends_filter = "Kavereiden kaverit (mukautettu suodatin)"; +set text_view_month = "Otsikot"; +set text_view_recent = "Merkinnät"; +set text_view_userinfo = "Käyttäjätiedot"; +# Sekalaisia tekstejä +set text_comment_date = "Päiväys:"; +set text_comment_from = "Lähettäjä:"; +set text_comment_frozen = "Jäädytetty"; +set text_comment_ipaddr = "IP-osoite:"; +set text_comment_parent = "Ylempi"; +set text_comment_reply = "Vastaa"; +set text_comment_thread = "Viestiketju"; +set text_day_next = "Seuraava päivä"; +set text_day_prev = "Edellinen päivä"; +set text_max_comments = "Maksimimäärä kommentteja saatu"; +set text_month_screened_comments = "ja peitettyjä kommentteja"; +set text_multiform_btn = "Muokkaa"; +set text_multiform_check = "Valitse:"; +set text_multiform_conf_delete = "Poista valitut kommentit?"; +set text_multiform_des = "Muokkaa kaikkia valittuja kommentteja:"; +set text_multiform_opt_delete = "Poista"; +set text_multiform_opt_freeze = "Jäädytä"; +set text_multiform_opt_screen = "Peitä"; +set text_multiform_opt_unfreeze = "Poista jäädytys"; +set text_multiform_opt_unscreen = "Poista peitto"; +set text_noentries_day = "Kyseisenä päivänä ei tehty merkintöjä"; +set text_noentries_recent = "Ei merkintöjä"; +set text_nosubject = "(ei otsikkoa)"; +set text_permalink = "Linkki"; +set text_poster_anonymous = "(tuntematon)"; +set text_reply_back = "Lue kommentteja"; +set text_reply_nocomments = "Kommentointi on estetty tämän merkinnän kohdalla"; +set text_reply_nocomments_header = "Kommentointi estetty:"; +set text_website_default_name = "Kotisivut"; + + +# Funktiot + + +# Antaa eri tuloksen riippuen siitä tuleeko tekstiä käsitellä yksikkönä vai monikkona +function lang_map_plural (int n) : int { + if ($n == 1) { return 0; } # singular + return 1; # plural +} + +# Palauttaa tekstin "Sivu X/Y", esim. Sivu 3/5 +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "Sivu $pg/$pgs"; +} + +# Tekee numerosta järjestysnumeron, eli laittaa numeron perään pisteen +function lang_ordinal(int num) : string { + return $num+"."; +} + +# Palauttaa tekstin joka kertoo millainen näkymä on kyseessä +function lang_viewname(string viewid) [notags] : string "Get some words representing a view" { + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Päivä"; } + if ($viewid == "month") { return "Kuukausi"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Lue kommentteja"; } + if ($viewid == "reply") { return "Jätä kommentti"; } + return "Tuntematon näkymä"; +} + +# Vastaussivun otsikko +function ReplyPage::view_title() : string { + return "Jätä kommentti"; +} + +# Kirjoittaa palvelimen allekirjoituksen, +# Esim. "Sivun tarjoaa LiveJournal.com" +function server_sig() { + """Sivun tarjoaa $*SITENAME"""; +} + +# Kirjoittaa kaverisivulla tekstin, joka kertoo missä yhteisössä joku kirjoitti jotakin, +# Esim. "Esimerkkilähettäjä kirjoitti yhteisössä esimerkkiyhteisö" +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " kirjoitti yhteisössä "; + $e.journal->print(); + } +} + +# Palauttaa tekstin joka kertoo että joku kirjoitti, +# Esim. "Esimerkkikäyttäjä kirjoitti" tai "Tuntematon käyttäjä kirjoitti" +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" kirjoitti"; + } + else { + return "Tuntematon käyttäjä kirjoitti"; + } +} + +# Palauttaa tekstin joka ilmoittaa päiväyksen ja kellonajan, +# Esim. "3. lokakuuta 2004 kello 14:45" +function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." { + return $d->date_format("long") + " kello " + $d->time_format(); +} + + diff --git a/livejournal/bin/upgrading/s2layers/i18nc/fr1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/fr1.s2 new file mode 100755 index 0000000..4192e88 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/fr1.s2 @@ -0,0 +1,144 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/fr1"; +layerinfo "name" = "French"; +layerinfo "langcode" = "fr"; +layerinfo "author_name" = "Timwi, Diziet Sma, Eclips1st"; +layerinfo "author_email" = "timwi@livejournal.com, dizietsma@livejournal.com, eclips1st@livejournal.com"; + +layerinfo "source_viewable" = 1; + +set lang_current = "fr"; + +set lang_fmt_date_short = "%%d%% %%mon%% %%yy%%"; +set lang_fmt_date_med = "%%dd%% %%mon%% %%yyyy%%"; +set lang_fmt_date_med_day = "%%da%%, le %%dd%% %%mon%% %%yyyy%%"; +set lang_fmt_date_long = "le %%dd%% %%month%% %%yyyy%%"; +set lang_fmt_date_long_day = "%%day%%, le %%dd%% %%month%% %%yyyy%%"; +set lang_fmt_time_short = "%%HH%%:%%min%%"; +set lang_fmt_month_short = "%%mon%% %%yy%%"; +set lang_fmt_month_med = "%%mon%% %%yyyy%%"; +set lang_fmt_month_long = "%%month%% %%yyyy%%"; + +set lang_monthname_long = [ "", "janvier", "février", "mars", + "avril", "mai", "juin", + "juillet", "août", "septembre", + "octobre", "novembre", "décembre" ]; + +set lang_monthname_short = [ "", "jan", "fév", "mar", + "avr", "mai", "juin", + "juil", "aoû", "sep", + "oct", "nov", "déc" ]; + +set lang_dayname_long = [ "", "dimanche", "lundi", "mardi", "mercredi", + "jeudi", "vendredi", "samedi" ]; + +set lang_dayname_short = [ "", "dim", "lun", "mar", "mer", + "jeu", "ven", "sam" ]; +set reg_firstdayofweek = "monday"; + +#[[ texttranslation ]] + +# Currents +set text_meta_music = "Musique actuelle"; +set text_meta_mood = "Humeur actuelle"; +# Comments +set text_post_comment = "Envoyez un commentaire"; +set text_read_comments = "1 commentaire // # commentaires"; +set text_post_comment_friends = "Envoyez un commentaire"; +set text_read_comments_friends = "1 commentaire // # commentaires"; +# Skiplinks +set text_skiplinks_back="# entrées précédentes"; +set text_skiplinks_forward="# entrées suivantes"; +# Views +set text_view_recent = "Entrées récentes"; +set text_view_friends = "Amis"; +set text_view_archive = "Archives"; +set text_view_userinfo = "Profil"; +set text_view_month = "Sujets du mois"; +# Misc. texts +set text_nosubject = "(pas de sujets)"; +set text_noentries_recent = "Pas d'entrées."; +set text_noentries_day = "Il n'y a aucune entrée cette journée."; +set text_permalink = "Lien"; +set text_month_screened_comments = "+ filtrée(s)"; +set text_multiform_check = "Cocher :"; +set text_multiform_des = "Modifier les commentaires cochés :"; +set text_multiform_btn = "Modifier"; +set text_multiform_opt_unscreen = "Rendre public"; +set text_multiform_opt_screen = "Filtrer"; +set text_multiform_opt_delete = "Effacer"; +set text_multiform_conf_delete = "Êtes-vous sûr de vouloir supprimer les commentaires sélectionnés?"; +set text_day_prev = "Journée précédente"; +set text_day_next = "Journée suivante"; +set text_comment_from = "De :"; +set text_comment_date = "Date :"; +set text_comment_ipaddr = "Adresse IP :"; +set text_comment_reply = "Répondre"; +set text_comment_parent = "Précédent"; +set text_comment_thread = "Fil"; +set text_reply_back = "Lire les commentaires"; +set text_reply_nocomments_header = "Commentaires désactivés :"; +set text_reply_nocomments = "L'utilisateur a désactivé les commentaires pour cette entrée."; +set text_website_default_name = "Mon site"; +set text_poster_anonymous = "(anonyme)"; + +#[[ function translations ]] + +function lang_page_of_pages (int pg, int pgs) [notags] : string { + return "Page $pg de $pgs"; +} + +function lang_ordinal(int num) [notags] : string { + if ($num == 1) { return $num+"er"; } + return $num+"e"; +} + +function lang_map_plural (int n) : int { + if ($n > 1) { return 1; } # plural + return 0; # singular +} + +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*text_view_recent; } + if ($viewid == "archive") { return $*text_view_archive; } + if ($viewid == "friends") { return $*text_view_friends; } + if ($viewid == "day") { return "Journée"; } + if ($viewid == "month") { return "Mois"; } + if ($viewid == "userinfo") { return $*text_view_userinfo; } + if ($viewid == "entry") { return "Lire les commentaires"; } + if ($viewid == "reply") { return "Envoyer un commentaire"; } + return "Affichage inconnue"; +} + +function ReplyPage::view_title() : string { + return "Envoyer un commentaire"; +} + +function server_sig() { + """Actionné par $*SITENAME"""; +} + +function Page::print_entry_poster(Entry e) { + $e.poster->print(); + if ($.view == "friends" and $e.poster.username != $e.journal.username) { + " a écrit dans "; + $e.journal->print(); + } +} + +function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." { + if (defined $u) { + return $u->as_string()+" a écrit"; + } + else { + return "Un utilisateur anonyme a écrit"; + } +} + +function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." { + return $d->date_format("long") + " à " + $d->time_format(); +} diff --git a/livejournal/bin/upgrading/s2layers/i18nc/ja1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/ja1.s2 new file mode 100755 index 0000000..b7d3caf --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/ja1.s2 @@ -0,0 +1,16 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/ja1"; +layerinfo "name" = "Japanese"; +layerinfo "langcode" = "ja"; +set lang_current = "ja"; + +# One form (the number is inflected) +function lang_map_plural (int n) : int { + return 0; +} +set text_read_comments = "# コメント"; +set text_post_comment = "コメントã®é€ä¿¡"; +set text_read_comments_friends = "# コメント"; +set text_post_comment_friends = "コメントã®é€ä¿¡"; diff --git a/livejournal/bin/upgrading/s2layers/i18nc/ru1.s2 b/livejournal/bin/upgrading/s2layers/i18nc/ru1.s2 new file mode 100755 index 0000000..a14f601 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/i18nc/ru1.s2 @@ -0,0 +1,21 @@ +#-*-s2-*- ;; -*- coding: utf-8 -*- + +layerinfo "type" = "i18nc"; +layerinfo "redist_uniq" = "i18nc/ru1"; +layerinfo "name" = "Russian"; +layerinfo "langcode" = "ru"; +set lang_current = "ru"; + +# Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4] +function lang_map_plural (int n) : int { + if ($n%10 == 1 and $n%100 != 11) { return 0; } + if ($n%10 >= 2 and $n%10 <= 4 and ($n%100 < 10 or $n%100>=20)) { return 1; } + return 2; +} + +set text_post_comment="ОÑтавить комментарий"; +set text_read_comments="# комментарий // # ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ // # комментариев"; +set text_post_comment_friends="ОÑтавить комментарий"; +set text_read_comments_friends="# комментарий // # ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ // # комментариев"; + + diff --git a/livejournal/bin/upgrading/s2layers/magazine/en.s2 b/livejournal/bin/upgrading/s2layers/magazine/en.s2 new file mode 100755 index 0000000..414ea55 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/magazine/en.s2 @@ -0,0 +1,14 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "magazine/en"; + +set text_meta_music = "Music"; +set text_meta_mood = "Mood"; + +set text_post_comment = "comment on this"; +set text_read_comments = "# comments"; + +set text_post_comment_friends = "comment on this"; +set text_read_comments_friends = "# comments"; \ No newline at end of file diff --git a/livejournal/bin/upgrading/s2layers/magazine/layout.s2 b/livejournal/bin/upgrading/s2layers/magazine/layout.s2 new file mode 100755 index 0000000..69d9050 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/magazine/layout.s2 @@ -0,0 +1,699 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Magazine"; +layerinfo redist_uniq = "magazine/layout"; +layerinfo previews = "magazine/magazine.jpg"; + +propgroup colors { + property Color main_bgcolor { + des = "Main Background color"; + s1color = "page_back"; + } + property Color main_fgcolor { + des = "Main text color"; + s1color = "page_text"; + } + property Color sidebar_color { + des = "Sidebar color"; + s1color = "stronger_back"; + } + property Color headerbar_bgcolor { + des = "Headerbar background color"; + s1color = "strong_back"; + } + property Color headerbar_fgcolor { + des = "Text color on headerbar"; + s1color = "strong_text"; + } + property Color headerbar_bevel_color { + des = "Accent line color for headerbar"; + s1color = "stronger_back"; + } + property Color highlight_bgcolor { + des = "Highlighting color for accented text"; + s1color = "weak_back"; + } + property Color highlight_fgcolor { + des = "Highlighted text color"; + s1color = "weak_text"; + } + property Color border_color { + des = "Color of borders"; + s1color = "weak_text"; + } + property Color title_color { + des = "Text color of top title"; + s1color = "page_text_title"; + } + property Color meta_color { + des = "Text color of meta descriptions"; + s1color = "page_text_em"; + } + property Color link_color { + des = "Text color of links"; + s1color = "page_link"; + } + property Color vlink_color { + des = "Text color of visited links"; + s1color = "page_vlink"; + } + property Color alink_color { + des = "Text color of active links"; + s1color = "page_alink"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set sidebar_color = "#6666cc"; +set headerbar_bgcolor = "#c0c0ff"; +set headerbar_fgcolor = "#000000"; +set headerbar_bevel_color = "#6666cc"; +set highlight_bgcolor = "#eeeeff"; +set highlight_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#8b1a1"; +set meta_color = "#c00000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#dddddd"; +set comment_bar_screened_fgcolor = "#000000"; + +propgroup presentation { + property bool show_entry_userpic { + des = "Show the userpic on the journal entries? [Excludes friends page]"; + } + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; +} +set show_entry_userpic = false; +set view_entry_disabled = false; +set show_entrynav_icons = true; +set page_background_image = ""; + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; +} + +set tags_aware = true; + +function Page::lay_skip_navigation() {} + +function Page::lay_bottom_navigation() {} + +function print_stylesheet () +{ + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; + """HTML { + border-left: 1cm solid $*sidebar_color; + padding: 1cm; +} +BODY { + line-height: 1.3; + margin: 0; + background-color: $*main_bgcolor; + color: $*main_fgcolor; +} +P { + margin-top: 0; + text-align: justify; +} +H1 { + font: x-large Verdana, sans-serif; text-align: center; + letter-spacing: -0.09em; + color: $*title_color; +} +H2 { + background-color: $*headerbar_bgcolor; + color: $*headerbar_fgcolor; + border-bottom: thin solid $*headerbar_bevel_color; + font: normal 1.3em Georgia, serif; +} +H3 { + color: $*highlight_fgcolor; + font: medium sans-serif; +} +H3 SPAN { + background-color: $*highlight_bgcolor; + border-right: thin solid $*border_color; + border-bottom: thin solid $*border_color; + padding-right: 0.5ex; +} +H3 EM { + color: $*meta_color; + font-style: normal; +} +.H3Holder { + clear: both; + padding-left: 2ex; + border-left: thin solid $*border_color; + border-bottom: thin solid $*border_color; + margin-bottom: 1em; +} +A:link { + color: $*link_color; +} +A:visited { + color: $*vlink_color; +} +A:active { + color: $*alink_color; +} +.Navigation { + text-align: center; + font-family: sans-serif; +} +.Comment { + font-size: 0.7em; + margin-top: -1em; + text-align: right; +} +.Comment, .Current { + margin-bottom: 1em; + clear: right; +} +.Picture { + border-left: thin solid $*border_color; + border-top: thin solid $*border_color; + float: right; + margin: 0 0 0.5em 0.5em; + padding: 0.2em; +} +.Picture DIV { + text-align: center; +} +.Active { + background-color: $*highlight_bgcolor; +} +ACRONYM { + border-bottom: thin dashed $*border_color; + cursor: help; +} +.Bottom { + border-top: thin solid $*border_color; + text-align: center; +} +.Empty { + background-color: $*highlight_bgcolor; +} +.Month { + margin-top: 1em; +} +.MonthHeader { + color: $*headerbar_fgcolor; + background-color: $*headerbar_bgcolor ! important; + line-height: 1.5; +} +.Month TD { + color: $*highlight_fgcolor; + width: 14%; + border: thin outset; +} +.Month TH { + background-color: $*highlight_bgcolor; + font-family: Verdana, sans-serif; + border: thin outset; +}"""; +} + +function Page::print () { + var string title = $this->title(); + + """\n\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + + """$title + + +

    $title

    """; + + var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name; + var string website = ($.journal.website_url != "" ? "($website_name)" : ""); + + var string links; + foreach var string v ($.views_order) { + $links = "$links(" + ($.view == $v ? + ""+lang_viewname($v)+"" : + ""+lang_viewname($v)+"") + ")\n"; + } + + """"; + + $this->print_body(); + + $this->lay_bottom_navigation(); + + ""; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + var string userpic = (defined $e.userpic ? "" : ""); + if (($p.view != "entry" and $e.new_day) or $p.view == "entry") + { + "

    " + $e.time->date_format("med") + "

    "; + } + "
    "; + + # Altposter / friends / lastn userpic + if ($p.view == "friends" or + $p.view == "entry" or + $*show_entry_userpic == true or + $e.journal.username != $e.poster.username) + { + "
    "; + if ($p.view == "friends") + { + ""; + } + if ($*show_entry_userpic == true or $p.view == "friends" or $p.view == "entry") + { + if (defined $e.userpic) { "
    "; } + } + if ($e.journal.username != $e.poster.username) + { + ""; + } + "
    "; + } + # Time / Subject / Security + var string subject = ($e.subject != "" ? " - $e.subject" : ""); + "

    $time$subject $e.security_icon

    "; + + if ($p.view == "entry" and $*show_entrynav_icons) + { + print "
    "; + $e->print_linkbar(); + print "
    "; + } + + if (not $hide_text) + { + # Entry + "

    $e.text

    "; + + # Tags + if ($e.tags) { + var int tcount = 0; + "
    Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    "; + } + + # Metadata + if (size $e.metadata) { + foreach var string k ($e.metadata) { + "
    "; + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $key = $*text_meta_mood; + } elseif ( $k == "music" ) { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "[mood icon] $val"; + } + "
    $key: $val
    "; + "
    "; + } + } + } + + # Comments + $e.comments->print(); + "
    "; +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + "
    ("; + if ($.count > 0 or $.screened) { + $this->print_readlink(); " | "; + } + $this->print_postlink(); + ")
    "; +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function RecentPage::lay_skip_navigation() +{ + var int total = size $.entries; + var string nav = ""; + if ($.nav.backward_url != "") { + $nav = """Previous $total Entries"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { + $nav = "$nav | "; + } + if ($.nav.forward_url != "") { + $nav = """$navNext $total Entries"""; + } + if ($nav != "") { print "Navigate: ($nav)"; } +} + +function RecentPage::lay_bottom_navigation() +{ + "

    "; $this->lay_skip_navigation(); "

    "; +} + +function RecentPage::print_body +{ + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function FriendsPage::lay_skip_navigation() +{ + var int total = size $.entries; + var string nav = ""; + if ($.nav.backward_url != "") { + $nav = """Previous $total Friends"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { + $nav = "$nav | "; + } + if ($.nav.forward_url != "") { + $nav = """$navNext $total Friends"""; + } + if ($nav != "") { print "Navigate: ($nav)"; } +} + +function FriendsPage::print_entry (Entry e) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function FriendsPage::print_body +{ + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function YearPage::lay_skip_navigation () +{ + $this->print_year_links(); +} + +function YearPage::lay_bottom_navigation() { } + +function YearPage::print_body() { + "

    $.year

    "; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearPage::print_year_links () +{ + "Navigate: "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + " ($y.year) "; + } else { + " ($y.year) "; + } + } +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + ""; + "\n"; + ""; + foreach var int d (weekdays()) + { + "\n"; + } + ""; + foreach var YearWeek w ($m.weeks) + { + $w->print(); + } + "
    "; + ""; print $m->month_format(); "
    "+$*lang_dayname_short[$d]+ "
    \n"; +} + +function YearWeek::print() { + ""; + if ($.pre_empty) { ""; } + foreach var YearDay d ($.days) + { + "$d.day"; + if ($d.num_entries) + { + ""; + } else { + "

    "; + } + ""; + } + if ($.post_empty) { ""; } + ""; +} + +function DayPage::lay_skip_navigation() +{ + "Navigate: (Previous Day | Next Day)"; +} + +function DayPage::lay_bottom_navigation() +{ + """ + + + + + + +
    Previous day(Calendar)Next day
    + """; +} + +function DayPage::print_body () +{ + if (not $.has_entries) { + "

    "; print $.date->date_format("med"); "

    "; + print "

    (No journal entries for this day.)

    "; + } else { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } +} + +function EntryPage::print_body () +{ + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + print "

    Comments:

    "; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + "
    "; + if ($this.multiform_on) { + "

    Mass Action

    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
    "; + } + } +} + +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + + "
    [User Picture]"; + + ### From, date, etc + ""; + + ### Gadgets + ""; + + ### Subject / icon + print ""; + + ### Permalink + print ""; + + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    From:$poster
    Date:"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + print (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + print "
    (Link)
    "; + print "
    $c.text
    "; + print "
    "; + if ($c.frozen) { + print """(Replies frozen) """; + } else { + print """(Reply to this) """; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    "; +} + +function ReplyPage::print_body () +{ + var string time = $.replyto.time->time_format(); + + if (not $.entry.comments.enabled) + { + print "

    $*text_reply_nocomments_header

    $*text_reply_nocomments

    "; + return; + } + + "

    " + $.replyto.time->date_format("med") + "

    "; + + "
    "; + + "
    "; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + if (defined $.replyto.userpic) { "
    "; } + "
    "; + + # Time / Subject / Security + var string subject = ($.replyto.subject ? " - $.replyto.subject" : ""); + "

    $time$subject

    "; + + "

    $.replyto.text

    "; + + ""; + "
    "; + print "

    Reply:

    "; + $.form->print(); +} + + +function print_theme_preview () +{ + """ + + + +
       +

    Dec. 22nd, 2002

    +
    +

    08:46 pm - subject

    +

    Words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words

    + + +
    + +
    """; +} diff --git a/livejournal/bin/upgrading/s2layers/magazine/magazine.jpg b/livejournal/bin/upgrading/s2layers/magazine/magazine.jpg new file mode 100755 index 0000000000000000000000000000000000000000..d73945bc58aefcde0d9e5dd021b0bf79a3a35a25 GIT binary patch literal 17795 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 Ae*gdg literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/magazine/themes.s2 b/livejournal/bin/upgrading/s2layers/magazine/themes.s2 new file mode 100755 index 0000000..c263df5 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/magazine/themes.s2 @@ -0,0 +1,459 @@ +#NEWLAYER: magazine/wonb +layerinfo "type" = "theme"; +layerinfo "name" = "White on Black"; +layerinfo "redist_uniq" = "magazine/wonb"; +set title_color = "#ffffff"; +set main_bgcolor = "#000000"; +set main_fgcolor = "#ffffff"; +set sidebar_color = "#555555"; +set headerbar_bgcolor = "#777777"; +set headerbar_fgcolor = "#ffffff"; +set headerbar_bevel_color = "#777777"; +set link_color = "#eeeeee"; +set alink_color = "#ffffff"; +set vlink_color = "#dddddd"; +set meta_color = "#ffffff"; +set highlight_bgcolor = "#666666"; +set highlight_fgcolor = "#dddddd"; +set border_color = "#ffffff"; +set comment_bar_one_bgcolor = "#777777"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#666666"; +set comment_bar_two_fgcolor = "#dddddd"; + +#NEWLAYER: magazine/shrinkvio +layerinfo type = theme; +layerinfo name = "Shrinking Violet"; +layerinfo redist_uniq = "magazine/shrinkvio"; +set sidebar_color = "#ad22e7"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#381a45"; +set headerbar_bgcolor = "#5d0383"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#5d0383"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#d9a1f1"; +set highlight_bgcolor = "#d9a1f1"; +set highlight_fgcolor = "#000000"; +set link_color = "#2e053f"; +set vlink_color = "#611627"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#5d0383"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d9a1f1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/pistmint +layerinfo type = theme; +layerinfo name = "Pistachio Mint"; +layerinfo redist_uniq = "magazine/pistmint"; +set sidebar_color = "#133422"; +set main_bgcolor = "#a7c4b4"; +set main_fgcolor = "#000000"; +set border_color = "#096d36"; +set headerbar_bgcolor = "#096d36"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#096d36"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#096d36"; +set highlight_bgcolor = "#096d36"; +set highlight_fgcolor = "#000000"; +set link_color = "#8afabc"; +set vlink_color = "#1da65a"; +set alink_color = "#f9f5f5"; +set comment_bar_one_bgcolor = "#096d36"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#093d36"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: magazine/mexicanfood +layerinfo type = theme; +layerinfo name = "Mexican Food"; +layerinfo redist_uniq = "magazine/mexicanfood"; +set sidebar_color = "#ff0000"; +set main_bgcolor = "#f8ff3e"; +set main_fgcolor = "#f15601"; +set border_color = "#f50701"; +set headerbar_bgcolor = "#bdbf3e"; +set headerbar_fgcolor = "#ff0000"; +set title_color = "#ffc664"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#f9ff9d"; +set highlight_bgcolor = "#e15a18"; +set highlight_fgcolor = "#ffffff"; +set link_color = "#f49e08"; +set vlink_color = "#b05403"; +set alink_color = "#ff7405"; +set comment_bar_one_bgcolor = "#bdbf3e"; +set comment_bar_one_fgcolor = "#ff0000"; +set comment_bar_two_bgcolor = "#e15a18"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: magazine/ashfire +layerinfo type = theme; +layerinfo name = "Ash and Fire"; +layerinfo redist_uniq = "magazine/ashfire"; +set sidebar_color = "#b5b5b5"; +set main_bgcolor = "#ffb6af"; +set main_fgcolor = "#000000"; +set border_color = "#d90308"; +set headerbar_bgcolor = "#e75454"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#ff9696"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#ff1106"; +set highlight_bgcolor = "#f06c88"; +set highlight_fgcolor = "#000000"; +set link_color = "#f70208"; +set vlink_color = "#b0161d"; +set alink_color = "#d70106"; +set comment_bar_one_bgcolor = "#e75454"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#f06c88"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/desktop +layerinfo type = theme; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "magazine/desktop"; +set sidebar_color = "#00545c"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#ff7b05"; +set headerbar_fgcolor = "#ffeddd"; +set title_color = "#ffffff"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#ff7b05"; +set highlight_bgcolor = "#ffeddd"; +set highlight_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#5a76ff"; +set comment_bar_one_bgcolor = "#ff7b05"; +set comment_bar_one_fgcolor = "#ffeddd"; +set comment_bar_two_bgcolor = "#ffeddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/satinhandshake +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "magazine/satinhandshake"; +set sidebar_color = "#480c0c"; +set main_bgcolor = "#d06464"; +set main_fgcolor = "#00001d"; +set border_color = "#000000"; +set headerbar_bgcolor = "#aaaaaa"; +set headerbar_fgcolor = "#000000"; +set title_color = "#aaaaaa"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#9d0404"; +set highlight_bgcolor = "#9d0404"; +set highlight_fgcolor = "#ffffff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#9d0404"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: magazine/deepmelodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "magazine/deepmelodrama"; +set sidebar_color = "#872d89"; +set main_bgcolor = "#719cff"; +set main_fgcolor = "#8e48b2"; +set border_color = "#8e48b2"; +set headerbar_bgcolor = "#3794b3"; +set headerbar_fgcolor = "#84b8e7"; +set title_color = "#65b2c1"; +set meta_color = "#f5d3ff"; +set headerbar_bevel_color = "#8e48b2"; +set highlight_bgcolor = "#65b2c1"; +set highlight_fgcolor = "#f5d3ff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#dfd3ff"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#f5d3ff"; + +#NEWLAYER: magazine/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "magazine/everwhite"; +set sidebar_color = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#ffffff"; +set headerbar_fgcolor = "#000000"; +set title_color = "#ffffff"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#ffffff"; +set highlight_bgcolor = "#ffffff"; +set highlight_fgcolor = "#000000"; +set link_color = "#e60000"; +set vlink_color = "#c10602"; +set alink_color = "#ff0600"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Greys"; +layerinfo redist_uniq = "magazine/everblue"; +set sidebar_color = "#0f0c6d"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#000000"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#aaaaaa"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#000000"; +set highlight_bgcolor = "#aaaaaa"; +set highlight_fgcolor = "#000000"; +set link_color = "#2f00f2"; +set vlink_color = "#060667"; +set alink_color = "#6691ff"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/brownleather +layerinfo type = theme; +layerinfo name = "Brown Leather Coat"; +layerinfo redist_uniq = "magazine/brownleather"; +set sidebar_color = "#d2b48c"; +set main_bgcolor = "#ffebcd"; +set main_fgcolor = "#8b4513"; +set border_color = "#000000"; +set headerbar_bgcolor = "#d48014"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#d48014"; +set meta_color = "#d48014"; +set headerbar_bevel_color = "#d48014"; +set highlight_bgcolor = "#ffe1a1"; +set highlight_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#867a55"; +set alink_color = "#fffab3"; +set comment_bar_one_bgcolor = "#d48014"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffe1a1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "magazine/bruise"; +set sidebar_color = "#000000"; +set main_bgcolor = "#bcbcbc"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#1114a0"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#21c2f1"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#1114a0"; +set highlight_bgcolor = "#21c2f1"; +set highlight_fgcolor = "#0000ff"; +set link_color = "#0000cc"; +set vlink_color = "#000088"; +set alink_color = "#0000ff"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#0000ff"; + +#NEWLAYER: magazine/ranchhand +layerinfo type = theme; +layerinfo name = "Ranch Hand"; +layerinfo redist_uniq = "magazine/ranchhand"; +set sidebar_color = "#2999c2"; +set main_bgcolor = "#cfe0ff"; +set main_fgcolor = "#000000"; +set border_color = "#060667"; +set headerbar_bgcolor = "#54442c"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#bababa"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#9d995d"; +set highlight_bgcolor = "#704400"; +set highlight_fgcolor = "#bababa"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#6a20ff"; +set comment_bar_one_bgcolor = "#54442c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#704400"; +set comment_bar_two_fgcolor = "#bababa"; + +#NEWLAYER: magazine/victim +layerinfo type = theme; +layerinfo name = "Victim"; +layerinfo redist_uniq = "magazine/victim"; +set sidebar_color = "#2cd0ff"; +set main_bgcolor = "#505050"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set headerbar_bgcolor = "#166bac"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#2098f3"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#26b6ff"; +set highlight_bgcolor = "#353535"; +set highlight_fgcolor = "#ffffff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#166bac"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#353535"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: magazine/forest +layerinfo type = theme; +layerinfo name = "Forest"; +layerinfo redist_uniq = "magazine/forest"; +set sidebar_color = "#778e64"; +set main_bgcolor = "#9b9ba5"; +set main_fgcolor = "#000000"; +set border_color = "#ffffff"; +set headerbar_bgcolor = "#72784c"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#72784c"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#a0ac62"; +set highlight_bgcolor = "#73777a"; +set highlight_fgcolor = "#000000"; +set link_color = "#3811e1"; +set vlink_color = "#310cbb"; +set alink_color = "#4e7bef"; +set comment_bar_one_bgcolor = "#72784c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#73777a"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/drone +layerinfo type = theme; +layerinfo name = "Drone"; +layerinfo redist_uniq = "magazine/drone"; +set sidebar_color = "#395f82"; +set main_bgcolor = "#f9fcfe"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#904094"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#f56efc"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#ff93ff"; +set highlight_bgcolor = "#eeeeff"; +set highlight_fgcolor = "#000000"; +set link_color = "#395f82"; +set vlink_color = "#395f82"; +set alink_color = "#5266ce"; +set comment_bar_one_bgcolor = "#904094"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/lowercurtain +layerinfo type = theme; +layerinfo name = "Lower the Curtain"; +layerinfo redist_uniq = "magazine/lowercurtain"; +set sidebar_color = "#000000"; +set main_bgcolor = "#6b6b6b"; +set main_fgcolor = "#ffffff"; +set border_color = "#ffffff"; +set headerbar_bgcolor = "#363636"; +set headerbar_fgcolor = "#f0f5fb"; +set title_color = "#c6c6c6"; +set meta_color = "#222222"; +set headerbar_bevel_color = "#363636"; +set highlight_bgcolor = "#c5c8ca"; +set highlight_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#3314ba"; +set comment_bar_one_bgcolor = "#363636"; +set comment_bar_one_fgcolor = "#f0f5fb"; +set comment_bar_two_bgcolor = "#c5c8ca"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/sunny +layerinfo type = theme; +layerinfo name = "Sunny Day"; +layerinfo redist_uniq = "magazine/sunny"; +set sidebar_color = "#55e0f9"; +set main_bgcolor = "#e38202"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set headerbar_bgcolor = "#e38202"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#fff505"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#efe052"; +set highlight_bgcolor = "#ffba03"; +set highlight_fgcolor = "#ffffff"; +set link_color = "#df0d12"; +set vlink_color = "#ac1b25"; +set alink_color = "#fe3b3b"; +set comment_bar_one_bgcolor = "#e38202"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffba03"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: magazine/valentine +layerinfo type = theme; +layerinfo name = "Be Mine"; +layerinfo redist_uniq = "magazine/valentine"; +set sidebar_color = "#6f104a"; +set main_bgcolor = "#f2bce9"; +set main_fgcolor = "#000000"; +set border_color = "#ff24ab"; +set headerbar_bgcolor = "#ff37ff"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#df2096"; +set meta_color = "#ffffff"; +set headerbar_bevel_color = "#ae1774"; +set highlight_bgcolor = "#df2096"; +set highlight_fgcolor = "#000000"; +set link_color = "#ffffff"; +set vlink_color = "#a51014"; +set alink_color = "#ed8188"; +set comment_bar_one_bgcolor = "#ff37ff"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#df2096"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: magazine/stripes +layerinfo type = theme; +layerinfo name = "Stripes"; +layerinfo redist_uniq = "magazine/stripes"; +set sidebar_color = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#ff0000"; +set headerbar_bgcolor = "#e7212a"; +set headerbar_fgcolor = "#ffffff"; +set title_color = "#ffffff"; +set meta_color = "#000000"; +set headerbar_bevel_color = "#ffffff"; +set highlight_bgcolor = "#ffcfdc"; +set highlight_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ffafc1"; +set comment_bar_one_bgcolor = "#e7212a"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffcfdc"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/notepad/en.s2 b/livejournal/bin/upgrading/s2layers/notepad/en.s2 new file mode 100755 index 0000000..8f559d0 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/notepad/en.s2 @@ -0,0 +1,14 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "notepad/en"; + +set text_meta_music = "Music"; +set text_meta_mood = "Mood"; + +set text_post_comment = "Make Notes"; +set text_read_comments = "Read # Notes"; + +set text_post_comment_friends = "Make Notes"; +set text_read_comments_friends = "Read # Notes"; \ No newline at end of file diff --git a/livejournal/bin/upgrading/s2layers/notepad/layout.s2 b/livejournal/bin/upgrading/s2layers/notepad/layout.s2 new file mode 100755 index 0000000..c70e251 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/notepad/layout.s2 @@ -0,0 +1,605 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Notepad"; +layerinfo redist_uniq = "notepad/layout"; +layerinfo previews = "notepad/notepad.jpg"; + +propgroup colors { + property Color body_bgcolor { + des = "Body background color"; + } + property Color text_color { + des = "Text color"; + } + property Color subject_color { + des = "Text color of subjects"; + } + property Color link_color { + des = "Link color"; + } + property Color vlink_color { + des = "Visited link color"; + } + property Color alink_color { + des = "Active link color"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} +set body_bgcolor = "#8cd5fe"; +set text_color = "#000000"; +set subject_color = "#ff0000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#dddddd"; +set comment_bar_screened_fgcolor = "#000000"; + +propgroup presentation { + property bool show_entry_userpic { + des = "Show the userpic on the journal entries?"; + } + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property use external_stylesheet; +} +set show_entry_userpic = false; +set view_entry_disabled = false; +set page_background_image = ""; +set show_entrynav_icons = true; + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; +} + +property string imguri { + noui = 1; + des = "URI to notepad images (no trailing slash)"; +} +set imguri = ""; + +function prop_init() +{ + if ($*imguri == "") { $*imguri = "$*SITEROOT/img/style/notepad"; } +} + +function Page::lay_bottom_navigation() { } + +function print_stylesheet () +{ + var string backgroundurl = clean_url($*page_background_image) != "" ? "background-image: url($*page_background_image);" : ""; + """body { + $backgroundurl + background-color: $*body_bgcolor; +} +td,body,p,div { + color: $*text_color; + text-decoration: none; + font-family: verdana,arial,helvetica; + font-size: 12px; +} +a:link { + color: $*link_color; + text-decoration: underline; + font-family: verdana,arial,helvetica; + font-size: 12px; +} +a:visited { + color: $*vlink_color; + text-decoration: underline; + font-family: verdana,arial,helvetica; + font-size:12px; +} +a:active { + color: $*alink_color; + text-decoration: underline; + font-family: verdana,arial,helvetica; + font-size: 12px; +} +a:hover { + color: $*alink_color; + text-decoration: underline; + font-family: verdana,arial,helvetica; + font-size:12px; +}"""; +} + +function Page::print() +{ + var string title = $this->title(); + """\n\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + + """$title + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
       + Journal +    + Friends +    + Archive +    + User Info +    + memories +
    +
    + + + + + +
    +   + +

    $title

    +

    + """; + + $this->print_body(); + + "

    "; $this->lay_bottom_navigation(); "

    "; + """ +
    +   +
    + + + + + +
    + + + """; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + ""; + + if ($p.view == "friends" or + $*show_entry_userpic == true or + $e.journal.username != $e.poster.username) + { + var string userpic = defined $e.userpic ? "
    " : ""; + ""; + } + """
    "; + if ($p.view == "friends" or $*show_entry_userpic == true) { print $userpic; } + if ($p.view == "friends") { "$e.journal.username"; } + if ($e.journal.username != $e.poster.username) + { + print ($p.view == "friends" ? + "
    [ $e.poster.username ]" : + "$e.poster.username"); + } + "
    """; print $e.time->date_format("med"); " "; print $e.time->time_format(); + if ($e.subject) { " $e.subject"; } + " $e.security_icon"; + + if (not $hide_text) + { + print "

    $e.text

    "; + if (size $e.metadata) { + "

    "; + foreach var string k ($e.metadata) { + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $key = $*text_meta_mood; + } elseif ($k == "music") { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + "$key: $val
    "; + } + "

    "; + } + } + $e.comments->print(); + if ($p.view == "entry" and $*show_entrynav_icons) + { + $e->print_linkbar(); + } + """
    """; + """

    """; +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function RecentPage::print_body () +{ + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function RecentPage::lay_bottom_navigation () +{ + var string nav = ""; + if ($.nav.backward_url != "") { + $nav = """Back a Page"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { + $nav = "$nav - "; + } + if ($.nav.forward_url != "") { + $nav = """$navForward a Page"""; + } + if ($nav != "") { print $nav; } +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) + { + $this->print_readlink(); " - "; + } + $this->print_postlink(); +} + +function YearPage::lay_bottom_navigation () +{ + $this->print_year_links(); +} + +function YearPage::print_year_links () +{ + if (size $.years <= 0) { return; } + foreach var YearYear y ($.years) + { + if ($y.displayed) { + "$y.year "; + } else { + "$y.year "; + } + } +} + +function YearPage::print_body () +{ + "

    $.year

    "; + foreach var YearMonth m ($.months) + { + $this->print_month($m); + } +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + "

    "; + + # Month Header + ""; + + # Weekdays + ""; + foreach var int d (weekdays()) + { + "\n"; + } + ""; + + # Weeks + foreach var YearWeek w ($m.weeks) + { + $w->print(); + } + "
    "; print $m->month_format(); "
    " + $*lang_dayname_short[$d] + "
    "; + "$*text_view_month"; + "

    "; +} + +function YearWeek::print() +{ + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) + { + "$d.day
    "; + if ($d.num_entries) + { + "$d.num_entries"; + } else { + " "; + } + "
    "; + } + if ($.post_empty) { " "; } +} + +function DayPage::lay_bottom_navigation() +{ + if (not $.has_entries) { "
    "; } + print "Back a Day - Forward a Day"; +} + +function DayPage::print_body() +{ + if (not $.has_entries) { + "

    No journal entries for this day.

    "; + } else { + foreach var Entry e ($.entries) { $this->print_entry($e); } + } +} + +function EntryPage::print_body () +{ + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + print "

    Comments:

    "; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + if ($this.multiform_on) { + "

    Mass Action:

    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } +} + +function EntryPage::print_comment (Comment c) { + var Color barlight = $*color_comment_bar->clone(); + $barlight->lightness(($barlight->lightness() + 255) / 2); + var Color barc = $c.depth % 2 ? $*color_comment_bar : $barlight; + if ($c.screened) { + $barc = $*comment_bar_screened_bgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + "
    "; + + ""; + + print ""; + + print ""; + + print "\n"; + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    $*text_comment_from$poster
    $*text_comment_date"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    $*text_comment_ipaddr(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + if (defined $c.subject_icon or $c.subject != "") { "

    $c.subject_icon $c.subject

    \n"; } + print "
    ($*text_permalink)
    "; + + print "
    $c.text
    \n"; + print "
    "; + if ($c.frozen) { + print "($*text_comment_frozen) "; + } else { + print "($*text_comment_reply) "; + } + if ($c.parent_url != "") { "($*text_comment_parent) "; } + if ($c.thread_url != "") { "($*text_comment_thread) "; } + "
    \n"; +} + +function ReplyPage::print_body () +{ + if (not $.entry.comments.enabled) + { + print "

    $*text_reply_nocomments_header

    $*text_reply_nocomments

    "; + return; + } + ""; + ""; + + """"""; + """
    "; + print defined $.replyto.userpic ? "
    " : ""; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + "
    """; print $.replyto.time->date_format("med"); " "; print $.replyto.time->time_format(); + if ($.replyto.subject) { " $.replyto.subject"; } + ""; + print "

    $.replyto.text

    "; + + + "Read Comments"; + """

    """; + "
    \n"; + print "

    Reply

    "; + $.form->print(); +} + +function print_theme_preview () +{ + """ +
    + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
       + Tab +    + Tab +    + Tab +    + Tab +    + Tab +
    +
    + + + + + +
    +   + +

    John Doe

    +

    +

    + + +
    +

    Dec. 16th, 2002 06:39 pm Neque porro quisquam est qui dolorem ipsum quia dolor sit amet…

    +

    +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit +

    +

    2 Comments | Leave a comment

    +

    +
    +   +
    + + + + + +
    +
    + """; +} diff --git a/livejournal/bin/upgrading/s2layers/notepad/notepad.jpg b/livejournal/bin/upgrading/s2layers/notepad/notepad.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f0ac46e55fe87e63feff7827a7108b96e1c3cb04 GIT binary patch literal 20276 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

    UEaTZO@=N74 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 by=R<%bh9|5NQy%w^5I`gD3S9_f93ug=e3k_ literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/policy.dat b/livejournal/bin/upgrading/s2layers/policy.dat new file mode 100755 index 0000000..61ad2c6 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/policy.dat @@ -0,0 +1,27 @@ +# Do not modify this file. To set the S2-usage policy for your own +# LiveJournal-based site, create a file beside this one called +# policy-local.dat, based on instructions you find in this document. +# That file will override anything not set here. +# +# 'allow' means all users get access. 'deny' means only users with +# the 's2styles' capability get access. +# + +# Default policy for layouts without their own policy section. +layer: * + use allow # can all users use it? + props allow # can all users modify any property of it? + +# If you decide to make your site's default policy for * to be 'deny', +# then you'll have to selectively allow access to parts, like so: + +#layer: generator/layout +# use allow +# props deny +# prop page_bgcolor allow + +# Notes: +# -- allowing/denying access to properties is only valid on +# layout and core layers. +# -- you can't disallow use of a core layer, or i18n layers. +# -- for theme layers, you can only set the 'use' property. diff --git a/livejournal/bin/upgrading/s2layers/punquin/en.s2 b/livejournal/bin/upgrading/s2layers/punquin/en.s2 new file mode 100755 index 0000000..436ae39 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/punquin/en.s2 @@ -0,0 +1,11 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "punquin/en"; + +set text_meta_music = "music"; +set text_meta_mood = "mood"; + +set text_post_comment = "Comment on this"; +set text_post_comment_friends = "Comment on this"; diff --git a/livejournal/bin/upgrading/s2layers/punquin/layout.s2 b/livejournal/bin/upgrading/s2layers/punquin/layout.s2 new file mode 100755 index 0000000..c9a9af4 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/punquin/layout.s2 @@ -0,0 +1,699 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Punquin Elegant"; +layerinfo redist_uniq = "punquin/layout"; +layerinfo previews = "punquin/punquin.jpg"; + +# Colors +propgroup colors { + property Color body_bgcolor { + des = "Page background color"; + s1color = "stronger_accent"; + } + property Color main_bgcolor { + des = "Background of text areas"; + s1color = "page_back"; + } + property Color main_fgcolor { + des = "Text color"; + s1color = "page_text"; + } + property Color subject_color { + des = "Color of entry subjects"; + s1color = "page_text_em"; + } + property Color title_color { + des = "Color of headers and titles"; + s1color = "page_text_title"; + } + property Color border_color { + des = "Color of borders"; + s1color = "weak_back"; + } + property Color link_color { + des = "Link color"; + s1color = "page_link"; + } + property Color vlink_color { + des = "Visited link color"; + s1color = "page_vlink"; + } + property Color alink_color { + des = "Active link color"; + s1color = "page_alink"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} +set body_bgcolor = "#6666cc"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set subject_color = "#c00000"; +set title_color = "#8b1a1a"; +set border_color = "#eeeeff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#dddddd"; +set comment_bar_screened_fgcolor = "#000000"; + +propgroup presentation { + property bool show_recent_userpic { + des = "Show the userpic on the recent entries page?"; + } + property string sidebar_position { + des = "Position of the sidebar relative to the main content"; + values = "left|Left|right|Right"; + } + property use font_base; + property use font_fallback; + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use linklist_support; + property use external_stylesheet; +} +set font_base = "Verdana, Arial, Helvetica"; +set font_fallback = "sans-serif"; +set show_recent_userpic = false; +set sidebar_position = "left"; +set page_recent_items = 20; +set page_friends_items = 20; +set view_entry_disabled = false; +set show_entrynav_icons = true; +set page_background_image = ""; +set linklist_support = false; + +propgroup text { + property string text_gotop { + des = "Link text to 'top of the page'"; + noui = 1; + } + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_website_default_name; +} +set text_gotop = "Go to Top"; +set tags_aware = true; + +function print_stylesheet () +{ + var string font = "$*font_base, $*font_fallback"; + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; + print """ +body { + background-color: $*body_bgcolor; + color: $*main_fgcolor; + font: normal normal 10pt $font; +} +a { + text-decoration: none; + color: $*link_color; + background: transparent; + font: normal normal 10pt $font; +} +a:visited { + color: $*vlink_color; + background: transparent; +} +a:active { + color: $*alink_color; + background: transparent; +} +#title { + font: normal bold 10pt $font; + color: $*title_color; + text-align: center; +} +.date { + font: normal bold 12pt $font; + color: $*title_color; + text-align: right; +} +.comments { + font: normal normal 8pt $font; +} +hr.separator { + color: $*border_color; +} +.siteplug { + font: normal normal 8pt $font; +} +#yearheader { + text-align: right; + color: $*title_color; + font: normal bold 12pt $font; +} +th.monthheader { + color: $*title_color; +} +th.daysheader { + color: $*subject_color; +} + +/* Tables. Fun. */ + +table#main { + border: solid 0px $*body_bgcolor; +} +table.standard { + border: solid 5px $*border_color; + background-color: $*main_bgcolor; + color: $*main_fgcolor; + font: normal normal 10pt $font; +} +table.standard>td { + background-color: $*main_bgcolor; + color: $*main_fgcolor; +} +table.standard td { + font: normal normal 10pt $font; +} + """; +} + + +function Page::lay_sidebar_navigation () { } + +function print_sidebar(Page p) { + var string title = $p->title(); + var string userpic; + var Image up_img = $p.journal.default_pic; + if (defined $up_img) { + $userpic = """

    """; + } + + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + var string website; + if ($p.journal.website_url != "") { + $website = """> $website_name
    """; + } + + var string links; + foreach var string v ($p.views_order) { + $links = "$links> " + ($p.view == $v ? + lang_viewname($v) : + ""+lang_viewname($v)+"") + "
    \n"; + } + + # Table Wrapper + "\n"; + "\n"; + "
    "; + + # Title + "
    $title
    \n"; + + # Links + "

    $links\n$website\n"; + $p->lay_sidebar_navigation(); + + # Userpic + "

    "; if($userpic != "") { "
    $userpic
    "; } + + # Link List + if (size $p.linklist > 0 and $*linklist_support) { + if (not $p.linklist[0].is_heading) { + "Links
    "; + } + $p->print_linklist(); + } + + # End Table + "
    \n"; +} + +function print_gotop (Page p) +{ + "\n\n"; + "\n"; + "
    \n"; + $p->lay_sidebar_navigation(); + "
    > $*text_gotop
    \n
    \n"; +} + +function Page::print () +{ + var string title = $this->title(); + var string main_position = $*sidebar_position == "left" ? "right" : "left"; + + # Head + println ""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + + "$title\n\n"; + + # Body + "\n
    \n"; + + # Table wrapper + "\n"; + + if ($*sidebar_position == "left") { print_sidebar($this); } + + # Main content + ""; + + if ($*sidebar_position == "right") { print_sidebar($this); } + + # Go to top + ""; + print_gotop($this); + ""; + + # Plug the site! + "\n"; + + "
    \n\n"; + "
    \n"; + $this->print_body(); + "
    \n\n
    \n"; + "$*SITENAME
    "; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + if ($e.new_day or $p.view == "entry") { + "

    "; print $e.time->date_format("%%month%% %%dayord%%, %%yyyy%%"); "

    "; + "
    "; + } + + if ($p.view == "entry" and $*show_entrynav_icons) + { + print "
    "; + $e->print_linkbar(); + print "
    "; + } + + ""; + + if ($p.view == "friends" or + $e.poster.username != $e.journal.username or + $*show_recent_userpic == true) + { + # Lots of muddled logic. Yay. + + """"; + } + "
    """; + if ($p.view == "friends") { + """$e.journal.username
    """; + } + if ($e.poster.username != $e.journal.username) { + if ($p.view == "friends") { + """[$e.poster.username]
    """; + } else { + """$e.poster.username
    """; + } + } + if (defined $e.userpic) { + if (($*show_recent_userpic == false) and + ($p.view != "friends") and + ($p.journal_type != "C") ) { } + else { """"""; + } + } + "
    $time"; + if ($e.subject) { " - $e.subject"; } + + if ($e.security) { + " "; $e.security_icon->print(); + } + "
    "; + if (not $hide_text) { + print $e.text; "
    "; + if (size $e.metadata) { + foreach var string k ($e.metadata) { + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $key = $*text_meta_mood; + } elseif ( $k == "music" ) { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "[mood icon] $val"; + } + "$key: $val
    "; + } + } + if ($e.tags) { + var int tcount = 0; + "
    Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
    "; + } + } + "
    "; + $e.comments->print(); +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function FriendsPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + + +function RecentPage::lay_sidebar_navigation () { + var int total = size $.entries; + var string nav = ""; + if ($.nav.backward_url != "") { + $nav = """> previous $total entries"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { + $nav = "$nav
    "; + } + if ($.nav.forward_url != "") { + $nav = """${nav}> next $total entries"""; + } + print $nav; +} + +function CommentInfo::print () +{ + if (not $.enabled) { + "

     

    "; + return; + } + "

    ("; + if ($.count > 0 or $.screened) { + $this->print_readlink(); + " | "; + } + $this->print_postlink(); + ")

    "; +} + +function YearPage::print_body { + "

    $.year

    \n"; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearPage::print_year_links () +{ + foreach var YearYear y ($.years) { + if ($y.displayed) { + "> $y.year
    "; + } else { + "> $y.year
    "; + } + } +} + +function YearPage::lay_sidebar_navigation () +{ + $this->print_year_links(); +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + # Table Wrapper + "

    \n"; + + # Month Header + "\n"; + + # Weekdays Header + "\n"; + foreach var int d (weekdays()) { + "\n"; + } + "\n"; + + # Weeks + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + # Footer + "\n"; + + # End Table + "
    \n"; + print $m->month_format(); + "
    "+$*lang_dayname_short[$d]+"

    \n"; +} + +function YearWeek::print () { + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) { + "$d.day
    "; + if ($d.num_entries) { + "$d.num_entries"; + } else { + " "; + } + "
    \n"; + } + if ($.post_empty) { " "; } + ""; +} + +function DayPage::print_body() { + if (not $.has_entries) { + ""; + "

    \n"; + print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%"); + "


    "; print ehtml($*text_noentries_day); "
    "; + } else { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + "
    \n"; + "\n"; + + "\n"; + "\n"; + "\n"; + + "
    $tprev[$*text_view_archive]$tnext
    "; +} + +function EntryPage::print_body () +{ + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + print "

    Comments:

    "; + "
    "; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + if ($this.multiform_on) { + print "

    Mass Action:

    "; + "
    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } +} + +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + if ($c.screened) { + $background = $*comment_bar_screened_bgcolor; + $color = $*comment_bar_screened_fgcolor; + } elseif ($c.depth % 2) { + $background = $*comment_bar_one_bgcolor; + $color = $*comment_bar_one_fgcolor; + } else { + $background = $*comment_bar_two_bgcolor; + $color = $*comment_bar_two_fgcolor; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + print ""; + } + + "
    [User Picture]"; + + ### From, date, etc + ""; + + ### Gadgets + ""; + + ### Subject / icon + print ""; + + ### Permalink + print ""; + + print "
    "; + print ""; + print "\n"; + print ""; + if ($c.metadata{"poster_ip"}) { print ""; } + "
    From:$poster
    Date:"; + print $c.time->date_format("long") + " - " + $c.time->time_format() + "
    IP Address:(" + $c.metadata{"poster_ip"} + ")
    "; + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + $c->print_linkbar(); + "
    "; + print (defined $c.subject_icon or $c.subject != "") ? "

    $c.subject_icon $c.subject

    " : ""; + print "
    (Link)
    "; + print "
    $c.text
    "; + print "
    "; + if ($c.frozen) { + print "(Replies frozen)"; + } else { + print "(Reply to this) "; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
    "; +} + +function ReplyPage::print_body() { + if (not $.entry.comments.enabled) + { + "

    $*text_reply_nocomments_header

    "; + "
    "; + "

    $*text_reply_nocomments

    "; + return; + } + "

    "; print $.replyto.time->date_format("%%month%% %%dayord%%, %%yyyy%%"); "

    "; + "
    "; + + ""; + + """"; + + "
    """; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + if (defined $.replyto.userpic) { + print """"""; + } + ""; print $.replyto.time->time_format(); + if ($.replyto.subject) { " - $.replyto.subject"; } + + "
    "; + + print $.replyto.text; "
    "; + + "
    "; + "

    Read Comments

    "; + "

    Reply

    "; + "
    "; + $.form->print(); +} + +function print_theme_preview () +{ + """ +
    + + +
    + + +
    +

    + December 18th, 2002


    +

    + + 01:22 am - Test
    + Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. + Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
    +

    (Read # Comments | Leave a comment)

    +
    +
    +
    + """; +} diff --git a/livejournal/bin/upgrading/s2layers/punquin/punquin.jpg b/livejournal/bin/upgrading/s2layers/punquin/punquin.jpg new file mode 100755 index 0000000000000000000000000000000000000000..e04bd1e08cd47853a08772341bc2e7291c2a165d GIT binary patch literal 12215 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 literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/punquin/themes.s2 b/livejournal/bin/upgrading/s2layers/punquin/themes.s2 new file mode 100755 index 0000000..a7e4551 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/punquin/themes.s2 @@ -0,0 +1,450 @@ +#NEWLAYER: punquin/bw +layerinfo type = "theme"; +layerinfo name = "Black on White"; +layerinfo redist_uniq = "punquin/bw"; +set body_bgcolor = "#333333"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set subject_color = "#c00000"; +set title_color = "#336699"; +set border_color = "#dddddd"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/autumn +layerinfo type = theme; +layerinfo name = "Autumn"; +layerinfo redist_uniq = "punquin/autumn"; +layerinfo author = "pumpsnail"; +set body_bgcolor = "#660033"; +set main_bgcolor = "#990022"; +set main_fgcolor = "#ffffff"; +set subject_color = "#ffffff"; +set title_color = "#ffffff"; +set border_color = "#fcc303"; +set link_color = "#cc6600"; +set vlink_color = "#cc99cc"; +set alink_color = "#ffcc33"; +set comment_bar_one_bgcolor = "#660033"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#993366"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/greyslate +layerinfo type = theme; +layerinfo name = "Grey Slate Rain"; +layerinfo redist_uniq = "punquin/greyslate"; +set body_bgcolor = "#67698f"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set subject_color = "#000000"; +set title_color = "#336699"; +set border_color = "#dddddd"; +set link_color = "#8e80f8"; +set vlink_color = "#c780f8"; +set alink_color = "#f880dd"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/minimal +layerinfo type = theme; +layerinfo name = "Minimalist"; +layerinfo redist_uniq = "punquin/minimal"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#333333"; +set subject_color = "#333333"; +set title_color = "#333333"; +set border_color = "#aaaaaa"; +set link_color = "#8e80f8"; +set vlink_color = "#c780f8"; +set alink_color = "#f880dd"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/jewel +layerinfo type = theme; +layerinfo name = "Jewel Toned"; +layerinfo redist_uniq = "punquin/jewel"; +set body_bgcolor = "#950875"; +set main_bgcolor = "#f3a8e2"; +set main_fgcolor = "#000000"; +set subject_color = "#c00000"; +set title_color = "#336699"; +set border_color = "#dddddd"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#950875"; +set comment_bar_one_fgcolor = "#f3a8e2"; +set comment_bar_two_bgcolor = "#b70875"; +set comment_bar_two_fgcolor = "#f3a8e2"; + +#NEWLAYER: punquin/bold +layerinfo type = theme; +layerinfo name = "Bold"; +layerinfo redist_uniq = "punquin/bold"; +set body_bgcolor = "#2501da"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set subject_color = "#c00453"; +set title_color = "#f50930"; +set border_color = "#000000"; +set link_color = "#5f5cd5"; +set vlink_color = "#2a2ab2"; +set alink_color = "#4a92eb"; +set comment_bar_one_bgcolor = "#2501da"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#2501fc"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/shrinkvio +layerinfo type = theme; +layerinfo name = "Shrinking Violet"; +layerinfo redist_uniq = "punquin/shrinkvio"; +set body_bgcolor = "#ad22e7"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#381a45"; +set title_color = "#5d0383"; +set subject_color = "#d9a1f1"; +set link_color = "#2e053f"; +set vlink_color = "#611627"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#5d0383"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d9a1f1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/pistmint +layerinfo type = theme; +layerinfo name = "Pistachio Mint"; +layerinfo redist_uniq = "punquin/pistmint"; +set body_bgcolor = "#133422"; +set main_bgcolor = "#a7c4b4"; +set main_fgcolor = "#000000"; +set border_color = "#096d36"; +set title_color = "#096d36"; +set subject_color = "#096d36"; +set link_color = "#8afabc"; +set vlink_color = "#1da65a"; +set alink_color = "#f9f5f5"; +set comment_bar_one_bgcolor = "#096d36"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#093d36"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/mexicanfood +layerinfo type = theme; +layerinfo name = "Mexican Food"; +layerinfo redist_uniq = "punquin/mexicanfood"; +set body_bgcolor = "#ff0000"; +set main_bgcolor = "#f8ff3e"; +set main_fgcolor = "#f15601"; +set border_color = "#f50701"; +set title_color = "#bdbf3e"; +set subject_color = "#f9ff9d"; +set link_color = "#f49e08"; +set vlink_color = "#b05403"; +set alink_color = "#ff7405"; +set comment_bar_one_bgcolor = "#bdbf3e"; +set comment_bar_one_fgcolor = "#ff0000"; +set comment_bar_two_bgcolor = "#e15a18"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/ashfire +layerinfo type = theme; +layerinfo name = "Ash and Fire"; +layerinfo redist_uniq = "punquin/ashfire"; +set body_bgcolor = "#b5b5b5"; +set main_bgcolor = "#ffb6af"; +set main_fgcolor = "#000000"; +set border_color = "#d90308"; +set title_color = "#e75454"; +set subject_color = "#ff1106"; +set link_color = "#f70208"; +set vlink_color = "#b0161d"; +set alink_color = "#d70106"; +set comment_bar_one_bgcolor = "#e75454"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#f06c88"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/desktop +layerinfo type = theme; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "punquin/desktop"; +set body_bgcolor = "#00545c"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#ff7b05"; +set subject_color = "#ff7b05"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#5a76ff"; +set comment_bar_one_bgcolor = "#ff7b05"; +set comment_bar_one_fgcolor = "#ffeddd"; +set comment_bar_two_bgcolor = "#ffeddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/satinhandshake +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "punquin/satinhandshake"; +set body_bgcolor = "#480c0c"; +set main_bgcolor = "#d06464"; +set main_fgcolor = "#00001d"; +set border_color = "#000000"; +set title_color = "#aaaaaa"; +set subject_color = "#9d0404"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#9d0404"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/deepmelodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "punquin/deepmelodrama"; +set body_bgcolor = "#872d89"; +set main_bgcolor = "#719cff"; +set main_fgcolor = "#8e48b2"; +set border_color = "#8e48b2"; +set title_color = "#3794b3"; +set subject_color = "#8e48b2"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#dfd3ff"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#f5d3ff"; + +#NEWLAYER: punquin/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "punquin/everwhite"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#ffffff"; +set subject_color = "#ff0000"; +set link_color = "#e60000"; +set vlink_color = "#c10602"; +set alink_color = "#ff0600"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Greys"; +layerinfo redist_uniq = "punquin/everblue"; +set body_bgcolor = "#0f0c6d"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#000000"; +set subject_color = "#000000"; +set link_color = "#2f00f2"; +set vlink_color = "#060667"; +set alink_color = "#6691ff"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/brownleather +layerinfo type = theme; +layerinfo name = "Brown Leather Coat"; +layerinfo redist_uniq = "punquin/brownleather"; +set body_bgcolor = "#d2b48c"; +set main_bgcolor = "#ffebcd"; +set main_fgcolor = "#8b4513"; +set border_color = "#000000"; +set title_color = "#d48014"; +set subject_color = "#d48014"; +set link_color = "#000050"; +set vlink_color = "#867a55"; +set alink_color = "#fffab3"; +set comment_bar_one_bgcolor = "#d48014"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffe1a1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "punquin/bruise"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#bcbcbc"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#1114a0"; +set subject_color = "#1114a0"; +set link_color = "#0000cc"; +set vlink_color = "#000088"; +set alink_color = "#0000ff"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#0000ff"; + +#NEWLAYER: punquin/ranchhand +layerinfo type = theme; +layerinfo name = "Ranch Hand"; +layerinfo redist_uniq = "punquin/ranchhand"; +set body_bgcolor = "#2999c2"; +set main_bgcolor = "#cfe0ff"; +set main_fgcolor = "#000000"; +set border_color = "#060667"; +set title_color = "#54442c"; +set subject_color = "#9d995d"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#6a20ff"; +set comment_bar_one_bgcolor = "#54442c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#704400"; +set comment_bar_two_fgcolor = "#bababa"; + +#NEWLAYER: punquin/victim +layerinfo type = theme; +layerinfo name = "Victim"; +layerinfo redist_uniq = "punquin/victim"; +set body_bgcolor = "#2cd0ff"; +set main_bgcolor = "#505050"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set title_color = "#166bac"; +set subject_color = "#26b6ff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#166bac"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#353535"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/forest +layerinfo type = theme; +layerinfo name = "Forest"; +layerinfo redist_uniq = "punquin/forest"; +set body_bgcolor = "#778e64"; +set main_bgcolor = "#9b9ba5"; +set main_fgcolor = "#000000"; +set border_color = "#ffffff"; +set title_color = "#72784c"; +set subject_color = "#a0ac62"; +set link_color = "#3811e1"; +set vlink_color = "#310cbb"; +set alink_color = "#4e7bef"; +set comment_bar_one_bgcolor = "#72784c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#73777a"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/drone +layerinfo type = theme; +layerinfo name = "Drone"; +layerinfo redist_uniq = "punquin/drone"; +set body_bgcolor = "#395f82"; +set main_bgcolor = "#f9fcfe"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set title_color = "#904094"; +set subject_color = "#ff93ff"; +set link_color = "#395f82"; +set vlink_color = "#395f82"; +set alink_color = "#5266ce"; +set comment_bar_one_bgcolor = "#904094"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/lowercurtain +layerinfo type = theme; +layerinfo name = "Lower the Curtain"; +layerinfo redist_uniq = "punquin/lowercurtain"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#6b6b6b"; +set main_fgcolor = "#ffffff"; +set border_color = "#ffffff"; +set title_color = "#363636"; +set subject_color = "#363636"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#3314ba"; +set comment_bar_one_bgcolor = "#363636"; +set comment_bar_one_fgcolor = "#f0f5fb"; +set comment_bar_two_bgcolor = "#c5c8ca"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/sunny +layerinfo type = theme; +layerinfo name = "Sunny Day"; +layerinfo redist_uniq = "punquin/sunny"; +set body_bgcolor = "#55e0f9"; +set main_bgcolor = "#e38202"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set title_color = "#e38202"; +set subject_color = "#efe052"; +set link_color = "#df0d12"; +set vlink_color = "#ac1b25"; +set alink_color = "#fe3b3b"; +set comment_bar_one_bgcolor = "#e38202"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffba03"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: punquin/valentine +layerinfo type = theme; +layerinfo name = "Be Mine"; +layerinfo redist_uniq = "punquin/valentine"; +set body_bgcolor = "#6f104a"; +set main_bgcolor = "#f2bce9"; +set main_fgcolor = "#000000"; +set border_color = "#ff24ab"; +set title_color = "#ff37ff"; +set subject_color = "#ae1774"; +set link_color = "#ffffff"; +set vlink_color = "#a51014"; +set alink_color = "#ed8188"; +set comment_bar_one_bgcolor = "#ff37ff"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#df2096"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: punquin/stripes +layerinfo type = theme; +layerinfo name = "Stripes"; +layerinfo redist_uniq = "punquin/stripes"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#ff0000"; +set title_color = "#e7212a"; +set subject_color = "#ffffff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ffafc1"; +set comment_bar_one_bgcolor = "#e7212a"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffcfdc"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/sturdygesture/layout.s2 b/livejournal/bin/upgrading/s2layers/sturdygesture/layout.s2 new file mode 100755 index 0000000..f35078c --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/sturdygesture/layout.s2 @@ -0,0 +1,850 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "A Sturdy Gesture"; +layerinfo lang = "en"; + +layerinfo author = "Martin Atkins"; +layerinfo author_email = "mart@livejournal.com"; + +layerinfo redist_uniq = "sturdygesture/layout"; +layerinfo previews = "sturdygesture/sturdygesture.jpg"; + +propgroup colors { + property Color clr_page_back { des = "Page background"; } + set clr_page_back = "#ffffff"; + + property Color clr_page_text { des = "Box border color"; } + set clr_page_text = "#000000"; + + property Color clr_box_text { des = "Box content color"; } + set clr_boxhead_text = "#ffffff"; + + property Color clr_box_back { des = "Box background color"; } + set clr_boxhead_back = "#000000"; + + property Color clr_boxhead_text { des = "Box heading text color"; } + set clr_boxhead_text = "#ffffff"; + + property Color clr_boxhead_back { des = "Box heading background color"; } + set clr_boxhead_back = "#000000"; + + property Color clr_page_link { des = "Link color"; } + set clr_page_link = "#0000ff"; + + property Color clr_page_vlink { des = "Visited link color"; } + set clr_page_vlink = "#0000ff"; +} + +propgroup fonts { + property use font_base; + property use font_fallback; +} + +propgroup presentation { + property string opt_navbar_pos { + des = "Navigation Bar Location"; + values = "left|Left|right|Right"; + } + set opt_navbar_pos = "left"; + + property bool opt_friends_colors { + des = "Use friend colors on friends page"; + note = "If this option is on, the titles of friends' entries will use the colors you have selected for each friend."; + } + set opt_friends_colors = true; + + property bool opt_always_userpic { + des = "Always show userpics"; + note = "With this off, userpics are only shown in the friends view."; + } + set opt_always_userpic = false; + + + + ## These have no UI, but S2 generates an empty settings page if they aren't in a group + property string text_page_prev { + des = "Text used to link to the previous page"; + noui = 1; + } + property string text_page_next { + des = "Text used to link to the next page"; + noui = 1; + } + set text_page_prev = "Previous Page"; + set text_page_next = "Next Page"; + + property string{} text_entry_links { + des = "Captions for Entry Action links"; + noui = 1; + } + set text_entry_links = {"edit_entry" => "Edit Entry", + "edit_tags" => "Edit Tags", + "mem_add" => "Add As Memory", + "tell_friend" => "Tell a Friend", + "nav_prev" => "Previous Entry", + "nav_next" => "Next Entry"}; + + property string{} text_comment_links { + des = "Captions for Comment Action links"; + noui = 1; + } + set text_comment_links = {"delete_comment" => "Delete", + "screen_comment" => "Screen", + "unscreen_comment" => "Unscreen", + "freeze_thread" => "Freeze", + "unfreeze_thread" => "Unfreeze", }; + + property use use_shared_pic; + property use linklist_support; + property use external_stylesheet; +} + +set tags_aware = true; + +function navheading(RecentNav nav, int entries) : string + "i18n layers should override this to translate the skiplink box heading." { + return ($nav.skip == 0 ? $entries+" most recent" : "skipped back "+$nav.skip); +} +function navlinktext(RecentNav nav, bool next) : string + "i18n layers should override this to translate the skiplinks. If \$next is false, output 'Previous X', else 'Next X'." { + return ($next ? "Next "+$nav.forward_count : "Previous "+$nav.backward_count); +} + +function print_stylesheet() { +""" +body { +background: $*clr_page_back; +color: $*clr_page_text; +"""; +# Ugliness +if ($*font_base != "" or $*font_fallback != "none") { + "font-family: "; + if ($*font_base != "") { + "\"$*font_base\""; + if ($*font_fallback != "none") { + ", "; + } + } + if ($*font_fallback != "none") { + print $*font_fallback; + } + ";"; +} +""" +} +a { +color: $*clr_page_link; +} +a:visited { +color: $*clr_page_vlink; +} + +img { +border: 0; +} + +.box { +border: 1px solid $*clr_page_text; +margin: 1em; +background: $*clr_box_back; +color: $*clr_box_text; +} + +#navbar { +width: 25%; +} +#body { +width: 75%; +} + +#navbar .box h1, .box h2, .box h3 { +font-size: 1em; +background: $*clr_boxhead_back; +color: $*clr_boxhead_text; +padding: 3px; +margin: 0; +} +#navbar .box h1 { +text-align: center; +} + +.box h1 a, .box h2 a, .box h3 a { +color: $*clr_boxhead_text; +background: $*clr_boxhead_back; +} + +#navbar .box div.userpic { +margin: 1em; +text-align: center; +} + +#navbar p { +margin-left: 1em; +margin-right: 1em; +margin-bottom: 0; +} +#navbar ul, #skipbar ul { +list-style: none; +padding: 0; +margin: 0.5em; +} +#navbar ul li.active, #skipbar ul li.active { +font-weight: bold; +} + +.box .entry { +margin: 1em; +} + +.box .talklinks { +margin: 1em; +text-align: right; +clear: both; +} +.box .talklinks .permalink { +float: left; +} + +.box .minicomment { +clear: both; +} + +body.day #body h1 { +font-size: 1.1em; +font-weight: bold; +} + +table.box, table.box td, table.box th { +border: 1px solid #000000; +} + +.metadata { +margin-top: 1em; +} + +form#postform table { +background: $*clr_box_back; +color: $*clr_box_text; +} +"""; +} + +function Page::lay_page_nav() { + +} +function RecentPage::lay_page_nav() { + if ($.nav.backward_url == "" and $.nav.forward_url == "") { + return; + } + println "
    "; + println "

    "+navheading($.nav,size $.entries)+"

    \n\n"; + println "
    \n"; +} +function DayPage::lay_page_nav() { + println ""; +} +function YearPage::lay_page_nav() { + println "
      "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + println "
    • $y.year
    • "; + } else { + println "
    • $y.year
    • "; + } + } + println "
    "; +} +function MonthPage::lay_page_nav() { + println "
    "; + + "
    "; + $.redir->print_hiddens(); + if (size $.months > 1) { + "\n"; + } + "
    \n
    \n"; +} + +function EntryPage::lay_page_nav() { + println "
    "; + if (size $.comments > 0 and not $.comment_pages.all_subitems_displayed) { + "

    "+lang_page_of_pages($.comment_pages.current, $.comment_pages.total)+"

    \n"; + } + print "
      \n"; + if ($.entry.comments.enabled) { + "
    • "; $.entry.comments->print_postlink(); "
    • \n"; + } + if ($.comment_pages.url_prev != "") { + """
    • $*text_page_prev
    • \n"""; + } + if ($.comment_pages.url_next != "") { + """
    • $*text_page_next
    • \n"""; + } + println "
    •  
    • "; + var Link l = new Link; + $l = $.entry->get_link("nav_next"); + println """
    • $*text_entry_links{"nav_next"}
    • """; + foreach var string ls ($.entry.link_keyseq) { + $l = $.entry->get_link($ls); + if (defined $l) { + println """
    • $*text_entry_links{$ls}
    • """; + } + } + $l = $.entry->get_link("nav_prev"); + println """
    • $*text_entry_links{"nav_prev"}
    • """; + println "
    "; +} + +function Page::lay_show_firstnav() : bool { + return false; +} +function RecentPage::lay_show_firstnav() : bool { + return ((size $.entries) > 5); +} +function DayPage::lay_show_firstnav() : bool { + return ((size $.entries) > 5); +} +function YearPage::lay_show_firstnav() : bool { + return true; +} +function MonthPage::lay_show_firstnav() : bool { + return true; +} +function EntryPage::lay_show_firstnav() : bool { + return ((size $.comments) > 5); +} +function EntryPage::lay_show_firstnav() : bool { + return false; +} + +function Page::lay_navbar() { + var string userpic; + var Image up_img = $.journal.default_pic; + if (defined $up_img) { + $userpic = """
    + +
    +"""; + } + var string website; + if ($.journal.website_url != "") { + $website = """
  • $.journal.website_name
  • \n"""; + } + +""" + +
    +

    $.journal.name

    +
      +"""; + foreach var string v ($.views_order) { + if ($.view == $v) { + println "
    • "+lang_viewname($v)+"
    • "; + } else { + println "
    • "+lang_viewname($v)+"
    • "; + } + } +""" +$website
    +$userpic +
    +"""; + + if ($this->lay_show_firstnav()) { + $this->lay_page_nav(); + } + + if (size $this.linklist > 0 and $*linklist_support) { + println "
    "; + println "

    Links

    \n"; + $this->print_linklist(); + println "
    "; + } + + ""; + +} + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var bool section_open = false; + + println "
      "; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + println "
    "; + } + println """
  • $l.title\n
      """; + $section_open = true; + } else { + println """
    • $l.title
    • """; + } + } + } + if ($section_open) { + println "
  • "; + } + println ""; +} + +function Page::print() { + var string title = $this->title(); + +"""\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + + ""+$this->title()+""; +""" + + + + +"""; + + if ($*opt_navbar_pos == "left") { + $this->lay_navbar(); + } + + "\n"; + + if ($*opt_navbar_pos == "right") { + $this->lay_navbar(); + } + + ""; + +""" + +
    \n"; + $this->print_body(); + "
    "; + $this->lay_page_nav(); + "
    + + +"""; +} + +function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor) { + var string datetime; + if ($p.view != "day") { + $datetime = $e.time->date_format("med_day")+", "+$e.time->time_format(); + } else { + $datetime = $e.time->time_format(); + } + + if (not (defined $bgcolor) or not $*opt_friends_colors) { + $bgcolor = $*clr_boxhead_back; + } + if (not (defined $fgcolor) or not $*opt_friends_colors) { + $fgcolor = $*clr_boxhead_text; + } + + """

    $datetime """; + + if ($e.security != "") { + print """"""; + } + + if ($p.view == "friends" or + $e.subject != "" or + $e.poster.username != $p.journal.username) { + + print "
    "; + if ($p.view == "friends" or $e.poster.username != $p.journal.username) { + $p->print_entry_poster($e); + print ": "; + } + print $e.subject; + } + "

    \n
    \n"; + if (defined $e.userpic and ( + $*opt_always_userpic + or ($e.poster.username != $p.journal.username and $e.userpic.url != $p.journal.default_pic.url) + or $p.view == "friends" + or $p.view == "entry")) { + + """\n"""; + } + + "$e.text"; + + $e->print_metadata(); + + """
    "; + + "
    "; + +} # print_entry(Page,Entry,Color,Color) + +function Entry::print_metadata() { + var string caption; + var string val; + var Image i; + if (size $.metadata == 0 and size $.tags == 0) { return; } + println """"; +} + +function Page::print_entry(Entry e) { + print_entry($this, $e, null Color, null Color); +} + +function FriendsPage::print_entry(Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor); +} +function colored_ljuser(UserLite u, Color fg, Color bg) : string { + var Image uiimg = userinfoicon($u); + var string dir = $u.journal_type == "C" ? "community" : "users"; + return """[i]$u.username"""; +} +function FriendsPage::print_entry_poster(Entry e) { + var Friend f = $.friends{$e.journal.username}; + var Color fg; var Color bg; + if ($*opt_friends_colors) { + $fg = $f.fgcolor; + $bg = $f.bgcolor; + } else { + $fg = $*clr_boxhead_text; + $bg = $*clr_boxhead_back; + } + print colored_ljuser($e.poster, $fg, $bg); + if ($e.poster.username != $e.journal.username) { + " posting in "; + print colored_ljuser($e.journal, $fg, $bg); + } +} + +function RecentPage::print_body() { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function CommentInfo::print() { + if ($.enabled) { + $this->print_postlink(); + if ($.count > 0 or $.screened) { + " | "; + $this->print_readlink(); + } + } +} + +function DayPage::print_body() { + println """

    """+$.date->date_format("long")+"

    "; + + if (not $.has_entries) { + print "

    $*text_noentries_day

    "; + return; + } + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function EntryPage::print_body() { + $this->print_entry($.entry); + if ($this.multiform_on) { + $this->print_multiform_start(); + } + if ($.entry.comments.enabled) { + $this->print_comments($.comments); + } + if ($this.multiform_on) { + "

    Mass Action on Selected Comments:

    "; + "

    "; $this->print_multiform_actionline(); "

    "; + "
    "; + $this->print_multiform_end(); + } +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + print "
    "; + foreach var Comment c ($cs) { + var int indent = ($c.depth - 1) * 25; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + } + print "
    "; +} + +function EntryPage::print_comment(Comment c) { + var string datetime; + $datetime = $c.time->date_format("med_day")+", "+$c.time->time_format(); + + """

    """; + + if ($c.metadata{"poster_ip"}) { print """
    (""" + + $c.metadata{"poster_ip"} + + """)
    """; } + + print $datetime; + + if (defined $c.subject_icon) { + print """"""; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + print "
    "+$poster; + + if ($c.subject != "") { + print ": "+$c.subject; + } + + "

    \n
    \n"; + if (defined $c.userpic and $*comment_userpic_style != "off") { + """\n"""; + } + + "$c.text
    "; + """"; + + if ((size $c.replies) > 0 and $c.replies[0].full == false) { + """
    \n"""; + $this->print_comments($c.replies); + "
    \n"; + } + + "
    "; + + if ((size $c.replies) > 0 and $c.replies[0].full == true) { + $this->print_comments($c.replies); + } + +} + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + print """
    $subj - $poster
    """; + $this->print_comments($c.replies); +} + + +function ReplyPage::print_body() { + + var EntryLite c = $.replyto; + var string datetime; + $datetime = $c.time->date_format("med_day")+", "+$c.time->time_format(); + + """

    $datetime """; + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + print "
    "+$poster; + + if ($c.subject != "") { + print ": "+$c.subject; + } + + "

    \n
    \n"; + if (defined $c.userpic and $*comment_userpic_style != "off") { + """\n"""; + } + + "$c.text
    "; + + if (defined $c.userpic and $*comment_userpic_style != "off") { + """
    """; + } + + "
    "; + + """
    \n"""; + $.form->print(); + "
    \n"; + +} + +function YearPage::print_body { + foreach var YearMonth m ($.months) { + $this->print_month($m); + } +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + """\n + \n"""; + foreach var int d (weekdays()) { + "\n"; + } + "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """\n"""; + "
    """; + print $m->month_format(); + """
    "+$*lang_dayname_short[$d]+"
    + $*text_view_month
    "; +} + +function YearWeek::print() { + """\n"""; + if ($.pre_empty > 0) { + """ \n"""; + } + foreach var YearDay d ($.days) { + """\n"""; + """
    $d.day
    \n"""; + if ($d.num_entries > 0) { + """\n"""; + } + """\n"""; + } + if ($.post_empty > 0) { + """ \n"""; + } + ""; +} + +function MonthPage::print_body { + """

    """+$.date->date_format($*lang_fmt_month_long)+"

    \n"; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n
    \n"; +} + + +### Handler for the theme previews + +function print_theme_preview() { +""" +
    +
    +

    Cir zuta besho cavu mabu

    +
    +Cir zuta besho cavu mabu. Jad dop fugu hige wiju. Jam nek sapu shek noshea, moz lolle jil hattou daz. +Heck mippe giffou tipe pello, govo goof wachou fenu betui, mumu niffo puffu hivoo ziv! Sap gap jozo vem +sushu jiwo peru diche gese zar. Zuk kah rec sok vapui, mumu. Puw wuti mufe bak jivo, zef kazou gipwew cus. +Cev lepp gik fego rer. Tucku mickou jeck helou soopp! Vowa vov fawea pip wok. Heg fum heafsum pele. +Piz kuzu louw rome puir. Pashi jog huku pobi ckush. Zuj bit wido guih biha. Som veh nelo ruh ruju. +Coosh jecko nuh tutt tab. Zutt ckek vano fic der, hivu? +
    +
    +
    $*text_permalink
      +
    +
    +
    + +"""; + + +} diff --git a/livejournal/bin/upgrading/s2layers/sturdygesture/sturdygesture.jpg b/livejournal/bin/upgrading/s2layers/sturdygesture/sturdygesture.jpg new file mode 100755 index 0000000000000000000000000000000000000000..5cc7ffa80150f1518a336878f74d28d4d4bd7660 GIT binary patch literal 19735 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 literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/sturdygesture/themes.s2 b/livejournal/bin/upgrading/s2layers/sturdygesture/themes.s2 new file mode 100755 index 0000000..99b4e2e --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/sturdygesture/themes.s2 @@ -0,0 +1,75 @@ +#NEWLAYER: sturdygesture/beansprout + +layerinfo "type" = "theme"; +layerinfo "name" = "Beansprout"; +layerinfo "redist_uniq" = "sturdygesture/beansprout"; + +set clr_page_link = "#006760"; +set clr_boxhead_text = "#ffffff"; +set clr_box_text = "#000000"; +set clr_page_text = "#ffffff"; +set clr_box_back = "#ffffff"; +set clr_boxhead_back = "#006760"; +set clr_page_back = "#000000"; +set clr_page_vlink = "#002C29"; + +#NEWLAYER: sturdygesture/boxless + +layerinfo "type" = "theme"; +layerinfo "name" = "Boxless"; +layerinfo "redist_uniq" = "sturdygesture/boxless"; + +set clr_page_link = "#0000ff"; +set clr_boxhead_text = "#ffffff"; +set clr_box_text = "#000000"; +set clr_page_text = "#ffffff"; +set clr_box_back = "#ffffff"; +set clr_boxhead_back = "#000000"; +set clr_page_back = "#ffffff"; +set clr_page_vlink = "#00007f"; + +#NEWLAYER: sturdygesture/martialblue + +layerinfo "type" = "theme"; +layerinfo "name" = "Martial Blue"; +layerinfo "redist_uniq" = "sturdygesture/martialblue"; + +set clr_page_link = "#0068CF"; +set clr_boxhead_text = "#000000"; +set clr_box_text = "#000000"; +set clr_page_text = "#000000"; +set clr_box_back = "#FFFFFF"; +set clr_boxhead_back = "#6FB7FF"; +set clr_page_back = "#BFD8FF"; +set clr_page_vlink = "#003070"; + +#NEWLAYER: sturdygesture/redmond + +layerinfo "type" = "theme"; +layerinfo "name" = "Redmond"; +layerinfo "redist_uniq" = "sturdygesture/redmond"; + +set clr_page_link = "#0000ff"; +set clr_boxhead_text = "#ffffff"; +set clr_box_text = "#000000"; +set clr_page_text = "#000000"; +set clr_box_back = "#ffffff"; +set clr_boxhead_back = "#00007F"; +set clr_page_back = "#007F7F"; +set clr_page_vlink = "#0000ff"; + +#NEWLAYER: sturdygesture/shadesofgray + +layerinfo "type" = "theme"; +layerinfo "name" = "Shades of Gray"; # or, indeed, "grey" :) +layerinfo "redist_uniq" = "sturdygesture/shadesofgray"; + +set clr_page_link = "#444444"; +set clr_boxhead_text = "#ffffff"; +set clr_box_text = "#000000"; +set clr_page_text = "#7f7f7f"; +set clr_box_back = "#cccccc"; +set clr_boxhead_back = "#7f7f7f"; +set clr_page_back = "#888888"; +set clr_page_vlink = "#222222"; + diff --git a/livejournal/bin/upgrading/s2layers/tabularindent/en.s2 b/livejournal/bin/upgrading/s2layers/tabularindent/en.s2 new file mode 100755 index 0000000..116a410 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/tabularindent/en.s2 @@ -0,0 +1,14 @@ +# -*-s2-*- + +layerinfo type = "i18n"; +layerinfo name = "English"; +layerinfo redist_uniq = "tabularindent/en"; + +set text_meta_music = "Music"; +set text_meta_mood = "Mood"; + +set text_post_comment = "Add Your Own"; +set text_read_comments = "Read # Comments"; + +set text_post_comment_friends = "Add Your Own"; +set text_read_comments_friends = "Read # Comments"; \ No newline at end of file diff --git a/livejournal/bin/upgrading/s2layers/tabularindent/layout.s2 b/livejournal/bin/upgrading/s2layers/tabularindent/layout.s2 new file mode 100755 index 0000000..0044a11 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/tabularindent/layout.s2 @@ -0,0 +1,741 @@ +# -*-s2-*- + +layerinfo type = "layout"; +layerinfo name = "Tabular Indent"; +layerinfo redist_uniq = "tabularindent/layout"; +layerinfo previews = "tabularindent/tabularindent.jpg"; + +propgroup colors { + property Color body_bgcolor { + des = "Body background color"; + s1color = "page_back"; + } + property Color main_bgcolor { + des = "Background of main text areas"; + s1color = "page_back"; + } + property Color main_fgcolor { + des = "Main text color"; + s1color = "page_text"; + } + property Color border_color { + des = "Color of borders"; + # No s1color equivalent + } + property Color headerbar_bgcolor { + des = "Background color of header bar(s)"; + s1color = "stronger_back"; + } + property Color headerbar_fgcolor { + des = "Header bar text color"; + s1color = "stronger_text"; + } + property Color captionbar_mainbox_bgcolor { + des = "Main background color of caption bar"; + s1color = "page_back"; + } + property Color captionbar_mainbox_fgcolor { + des = "Text color of caption bar"; + s1color = "page_text"; + } + property Color captionbar_userpicbox_color { + des = "User picture background color of caption bar"; + s1color = "strong_back"; + } + property Color accent_bgcolor { + des = "Background color of accented areas"; + s1color = "weak_back"; + } + property Color accent_fgcolor { + des = "Accented area text color"; + s1color = "weak_text"; + } + property Color link_color { + des = "Link color"; + s1color = "page_link"; + } + property Color vlink_color { + des = "Visited link color"; + s1color = "page_vlink"; + } + property Color alink_color { + des = "Active link color"; + s1color = "page_alink"; + } + property Color comment_bar_one_bgcolor { + des = "Alternating background color for comment bars (one)"; + } + property Color comment_bar_two_fgcolor { + des = "Text color on alternating comment bars (one)"; + } + property Color comment_bar_two_bgcolor { + des = "Alternating background color for comment bars (two)"; + } + property Color comment_bar_one_fgcolor { + des = "Text color on alternating comment bars (two)"; + } + property Color comment_bar_screened_bgcolor { + des = "Background bar color for screened comments"; + } + property Color comment_bar_screened_fgcolor { + des = "Text color on background bar for screened comments"; + } +} +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#6666cc"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#ffffff"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#c0c0ff"; +set accent_bgcolor = "#eeeeff"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#c0c0ff"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; +set comment_bar_screened_bgcolor = "#dddddd"; +set comment_bar_screened_fgcolor = "#000000"; + +propgroup presentation { + property bool show_entry_userpic { + des = "Show the userpic on the journal entries?"; + } + property use page_recent_items; + property use page_friends_items; + property use use_shared_pic; + property use view_entry_disabled; + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; +} +set show_entry_userpic = true; +set page_recent_items = 20; +set page_friends_items = 20; +set view_entry_disabled = false; +set page_background_image = ""; + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; +} + +set tags_aware = true; + +function Page::lay_captionbar_navigation () { } + +function captionbar (Page p) { + var string title = $p->title(); + + var string userpic; + var Image up_img = $p.journal.default_pic; + if (defined $up_img) { + $userpic = """[icon]"""; + } + + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + var string website; + if ($p.journal.website_url != "") { + $website = """View:Website ($website_name)."""; + } + + var string links; + foreach var string v ($p.views_order) { + $links = "$linksView:" + ($p.view == $v ? + lang_viewname($v) : + ""+lang_viewname($v)+"") + ".\n"; + } + + var string captionbar_userpicbox_style = "background-color: $*captionbar_userpicbox_color"; + """ + + + +
    $userpic$title
    + + $links + $website + + + +
    """; + + $p->lay_captionbar_navigation(); + " +
    +
    "; +} + +function print_stylesheet () +{ + var string backgroundurl = clean_url($*page_background_image) != "" ? "background-image: url($*page_background_image);" : ""; + """/* Tabular Indent Stylesheet */ +body { + $backgroundurl + background-color: $*body_bgcolor; +} +.captionbar { + width: 100%; + border: 1px solid $*border_color; +} +.captionbar, .captionbar td { + background-color: $*captionbar_mainbox_bgcolor; + color: $*captionbar_mainbox_fgcolor; +} +.captionbar-userpicbox { + border-right: 1px solid $*border_color; + background-color: $*captionbar_userpicbox_color; + color: $*captionbar_mainbox_fgcolor; +} +body,td,p { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 8pt; +} +a { + color: $*link_color; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 8pt; + text-decoration: none; +} +a:visited { + color: $*vlink_color; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 8pt; + text-decoration: none; +} +a:active { + color: $*alink_color; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 8pt; + text-decoration: none; +} +a:hover { + color: $*alink_color; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 8pt; + text-decoration: underline; +} +h3.page-header { + font-size: 8pt; + font-family: verdana, arial, helvetica, sans-serif; + font-weight: normal; + background-color: $*headerbar_bgcolor; + color: $*headerbar_fgcolor; + padding: 6px; + border: 1px solid $*border_color; +} +"""; +} + +function Page::print () +{ + var string title = $this->title(); + println "\n\n"; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + + """$title + + + """; + "

    "; captionbar($this); "

    "; + + "

    "; $this->print_body(); "

    "; + + "

    "; captionbar($this); "

    "; + + """ + + + """; +} + +function print_box (string{} colors, string metapic, string{} meta, string content, string footer, string domid) { + var string bgcolor = $colors{"bgcolor"}; + var string fgcolor = $colors{"fgcolor"}; + if ($domid != "") { $domid = "id='$domid'"; } + + var string style = "background-color: $bgcolor; color: $fgcolor"; + "
    "; + ""; + ""; + + if ($footer) { + ""; + } + + "
    "; + + if ($metapic) { + ""; + } + + "
    $metapic"; + + foreach var string k ($meta) { + var string key = $k; + var string val = $meta{$k}; + ""; + } + + "
    $key$val
    "; + + print $content; + + "
    $footer

    "; +} + +function print_header (string header) +{ + print ""; +} + +function print_genericbox_open () { + "
    "; + "
    "; +} + +function print_genericbox_close () +{ + "

    "; +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string{} colors; var string{} meta; var string content = ""; var string footer = ""; + $colors{"bgcolor"} = "$*accent_bgcolor"; + $colors{"fgcolor"} = "$*accent_fgcolor"; + if ($p.view == "recent") { + if ($e.new_day) { + print_header($e.time->date_format("%%month%% %%dayord%%, %%yyyy%%")); + } + } else { + print_header($e.time->date_format("%%month%% %%dayord%%, %%yyyy%%")); + } + # Userpic + var string metapic = ""; + if ($p.view == "friends" or + $*show_entry_userpic == true or + $e.journal.username != $e.poster.username) + { + var string userpic = defined $e.userpic ? "" : ""; + var string url = $e.journal->base_url() + "/"; + $metapic = "
    "; + $metapic = "$metapic $userpic"; + if ($e.journal.username != $e.poster.username) { + var string purl = $e.poster->base_url() + "/"; + $metapic = "$metapic
    [$e.poster.username]"; + } + if ($p.view == "friends") { $metapic = "$metapic
    $e.journal.username"; } + $metapic = "$metapic
    "; + } + # Security Icon + if ($e.security) { + $meta{"Security:"} = "$e.security_icon $e.security"; + } + # Subject + if ($e.subject) { + $meta{"Subject:"} = $e.subject; + } + # Time posted + var string time = $e.time->time_format(); + $meta{"Time:"} = $time; + # Current + if (size $e.metadata) { + foreach var string k ($e.metadata) { + var string key = $k; var string val = $e.metadata{$k}; + if ($k == "mood") { + $key = $*text_meta_mood; + } elseif ($k == "music") { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "[mood icon] $val"; + } + $meta{"$key:"} = $val; + } + } + # Tags + if ($e.tags) { + var int tcount = 0; + var string tag; + foreach var Tag t ($e.tags) { + $tag = $tag + """"""; + $tcount++; + if ($tcount != size $e.tags) { $tag = $tag + ", "; } + } + $meta{"Tags:"} = $tag; + } + + + if (not $hide_text) { $content = $e.text; } + + if ($e.comments.enabled) { + $footer = "comments:"; + if (($e.comments.count > 0 or $e.comments.screened) and ($p.view != "entry")) { + $footer = "$footer " + + get_plural_phrase($e.comments.count, $p.view == "friends" ? + "text_read_comments_friends" : "text_read_comments") + + " or"; + } + $footer = "$footer " + + ($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment) + + ""; + } + + # Misc Links + var Link link; + if ($p.view == "entry") + { + $link = $e->get_link("nav_prev"); $footer = "$footer $link"; + } + $link = $e->get_link("edit_entry"); $footer = "$footer $link"; + $link = $e->get_link("edit_tags"); $footer = "$footer $link"; + $link = $e->get_link("tell_friend"); $footer = "$footer $link"; + $link = $e->get_link("mem_add"); $footer = "$footer $link"; + if ($p.view == "entry") + { + $link = $e->get_link("nav_next"); $footer = "$footer $link"; + } + + # Print + print_box($colors, $metapic, $meta, $content, $footer, ""); +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function RecentPage::lay_captionbar_navigation() +{ + var int total = size $.entries; + var string nav = ""; + if ($.nav.backward_url != "") { + $nav = """back $total entries"""; + } + if ($.nav.forward_url != "" and $.nav.backward_url != "") { + $nav = "$nav or "; + } + if ($.nav.forward_url != "") { + $nav = """$navforward $total entries"""; + } + print "You're looking at the latest "; + print size $.entries; + print ($.nav.skip > 0) ? " entries, after skipping $.nav.skip newer ones." :" entries."; + if ($nav != "") { print "
    Missed some entries? Then simply jump $nav"; } +} + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function FriendsPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + ""; + "comments: "; + if ($.count > 0 or $.screened) { + $this->print_readlink(); " or "; + } + $this->print_postlink(); + ""; +} + +function YearPage::print_body { + print_header(string($.year)); + print_genericbox_open(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print_genericbox_close(); +} + +function YearPage::lay_captionbar_navigation() +{ + $this->print_year_links(); +} + +function YearPage::print_year_links () +{ + foreach var YearYear y ($.years) { + if ($y.displayed) { + "$y.year "; + } else { + "$y.year "; + } + } +} + +function YearPage::print_month(YearMonth m) +{ + if (not $m.has_entries) { return; } + "
    "; + # Month header + ""; + # Weekdays + ""; + foreach var int d (weekdays()) { + "\n"; + } + ""; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + "
    "; + ""; print $m->month_format(); "
    "+$*lang_dayname_short[$d]+"
    View Subjects"; + "
    "; +} + +function YearWeek::print () { + ""; + if ($.pre_empty) { " "; } + foreach var YearDay d ($.days) { + "$d.day"; + "
    "; + if ($d.num_entries) { + """$d.num_entries"""; + } else { + " "; + } + "
    "; + } + if ($.post_empty) { " "; } + ""; +} + +function DayPage::lay_captionbar_navigation() +{ + print "Missed some entries? Then simply jump to the previous day or the next day."; +} + +function DayPage::print_body () +{ + if (not $.has_entries) { + ""; + "
    "; + print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%"); + "

    "; + print "No journal entries for this day."; + } else { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + } +} + +function MonthPage::print_body { + print_header($.date->date_format("%%month%% %%yyyy%%")); + print_genericbox_open(); + "
    "; + $.redir->print_hiddens(); + if ($.prev_url != "") { "[<<<]\n"; } + if (size $.months > 1) { + "\n"; + } + if ($.next_url != "") { "\n[>>>]\n"; } + "
    \n
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
    "; + print lang_ordinal($d.day); + "
    \n
    "; + $d->print_subjectlist(); + "
    \n"; + } + } + "
    \n"; + print_genericbox_close(); +} + +function EntryPage::print_body () { + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ], + [ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ], + ]); + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + + print_header("Comments:"); + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + $this->print_comments($.comments); + } + if ($this.multiform_on) { + print_header("Mass Action:"); + + print_genericbox_open(); + $this->print_multiform_actionline(); + print_genericbox_close(); + + $this->print_multiform_end(); + } + } +} + +function EntryPage::print_comment_partial (Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + print_genericbox_open(); + print "$subj - $poster"; + print_genericbox_close(); +} + +function EntryPage::print_comment (Comment c) { + var string{} colors; var string{} meta; var string content = ""; var string footer = ""; + + if ($c.screened) { + $colors{"bgcolor"} = "$*comment_bar_screened_bgcolor"; + $colors{"fgcolor"} = "$*comment_bar_screened_fgcolor"; + } elseif ($c.depth % 2) { + $colors{"bgcolor"} = "$*comment_bar_one_bgcolor"; + $colors{"fgcolor"} = "$*comment_bar_one_fgcolor"; + } else { + $colors{"bgcolor"} = "$*comment_bar_two_bgcolor"; + $colors{"fgcolor"} = "$*comment_bar_two_fgcolor"; + } + + # Userpic + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string metapic = ""; + if (defined $c.userpic and $*comment_userpic_style != "off") + { + var string userpic = defined $c.userpic ? "" : ""; + $metapic = "$userpic
    $poster"; + } else { + $metapic = $poster; + } + + # Subject + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + if ($c.subject or $sub_icon) { + $meta{"Subject:"} = "$c.subject $sub_icon"; + } + + # Time posted + $meta{"Time:"} = $c.time->time_format(); + + # Link + $meta{"Link:"} = "(Link)"; + + # IP Address: + if ($c.metadata{"poster_ip"}) { + $meta{"IP Address:"} = $c.metadata{"poster_ip"}; + } + + if ($c.frozen) { + $footer = "(Replies frozen) "; + } else { + $footer = "(Reply to this) "; + } + if ($c.parent_url != "") { $footer = "$footer (Parent) "; } + if ($c.thread_url != "") { $footer = "$footer (Thread) "; } + + var Link link = new Link; + foreach var string k ($c.link_keyseq) { + $link = $c->get_link($k); $footer = "$footer $link"; + } + println ""; + print_box($colors, $metapic, $meta, $c.text, $footer, "cmtbar$c.talkid"); +} + +function ReplyPage::print_body () { + if (not $.entry.comments.enabled) + { + print_header($*text_reply_nocomments_header); + print "

    $*text_reply_nocomments

    "; + return; + } + + var string{} meta; var string metapic; + + # Userpic + if (defined $.replyto.userpic and $*comment_userpic_style != "off") + { + $metapic = ""; + } + + # Subject + if ($.replyto.subject) { + $meta{"Subject:"} = $.replyto.subject; + } + + # Time posted + $meta{"Time:"} = $.replyto.time->time_format(); + + print_box({ "bgcolor" => "$*accent_bgcolor", "fgcolor" => "$*accent_fgcolor" }, + $metapic, $meta, $.replyto.text, "", ""); + + print_header("Reply:"); + + print_genericbox_open(); + $.form->print(); + print_genericbox_close(); + +} + +function print_theme_preview() +{ + "
    "; + ""; + "
    October 29th, 2003"; + "

    "; + "
    "; + ""; + ""; + """"""; + "
    "; + ""; + "
    "; + ""; + ""; + ""; + "
    Subject:"; + "Words Words Words
    Time:1:37 pm
    Preview text, preview text, etc, etc..... words, words and more words.
    comments: 20 comments or Leave a comment

    "; + "
    "; +} diff --git a/livejournal/bin/upgrading/s2layers/tabularindent/tabularindent.jpg b/livejournal/bin/upgrading/s2layers/tabularindent/tabularindent.jpg new file mode 100755 index 0000000000000000000000000000000000000000..2a85173b4bafd9e112bea76d51c215fbd1abab93 GIT binary patch literal 19223 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 Jg?qAq|JlIYIV}JH literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2layers/tabularindent/themes.s2 b/livejournal/bin/upgrading/s2layers/tabularindent/themes.s2 new file mode 100755 index 0000000..4d9867f --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/tabularindent/themes.s2 @@ -0,0 +1,437 @@ +#NEWLAYER: tabularindent/shrinkvio +layerinfo type = theme; +layerinfo name = "Shrinking Violet"; +layerinfo redist_uniq = "tabularindent/shrinkvio"; +set body_bgcolor = "#ad22e7"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#381a45"; +set headerbar_bgcolor = "#5d0383"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#5d0383"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#d9a1f1"; +set accent_bgcolor = "#d9a1f1"; +set accent_fgcolor = "#000000"; +set link_color = "#2e053f"; +set vlink_color = "#611627"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#5d0383"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#d9a1f1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/pistmint +layerinfo type = theme; +layerinfo name = "Pistachio Mint"; +layerinfo redist_uniq = "tabularindent/pistmint"; +set body_bgcolor = "#133422"; +set main_bgcolor = "#a7c4b4"; +set main_fgcolor = "#000000"; +set border_color = "#096d36"; +set headerbar_bgcolor = "#096d36"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#096d36"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#096d36"; +set accent_bgcolor = "#096d36"; +set accent_fgcolor = "#000000"; +set link_color = "#8afabc"; +set vlink_color = "#1da65a"; +set alink_color = "#f9f5f5"; +set comment_bar_one_bgcolor = "#096d36"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#093f36"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: tabularindent/mexicanfood +layerinfo type = theme; +layerinfo name = "Mexican Food"; +layerinfo redist_uniq = "tabularindent/mexicanfood"; +set body_bgcolor = "#ff0000"; +set main_bgcolor = "#f8ff3e"; +set main_fgcolor = "#f15601"; +set border_color = "#f50701"; +set headerbar_bgcolor = "#bdbf3e"; +set headerbar_fgcolor = "#ff0000"; +set captionbar_mainbox_bgcolor = "#ffc664"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#f9ff9d"; +set accent_bgcolor = "#e15a18"; +set accent_fgcolor = "#ffffff"; +set link_color = "#f49e08"; +set vlink_color = "#b05403"; +set alink_color = "#ff7405"; +set comment_bar_one_bgcolor = "#bdbf3e"; +set comment_bar_one_fgcolor = "#ff0000"; +set comment_bar_two_bgcolor = "#e15a18"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: tabularindent/ashfire +layerinfo type = theme; +layerinfo name = "Ash and Fire"; +layerinfo redist_uniq = "tabularindent/ashfire"; +set body_bgcolor = "#b5b5b5"; +set main_bgcolor = "#ffb6af"; +set main_fgcolor = "#000000"; +set border_color = "#d90308"; +set headerbar_bgcolor = "#e75454"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#ff9696"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#ff1106"; +set accent_bgcolor = "#f06c88"; +set accent_fgcolor = "#000000"; +set link_color = "#f70208"; +set vlink_color = "#b0161d"; +set alink_color = "#d70106"; +set comment_bar_one_bgcolor = "#e75454"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#f06c88"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/desktop +# for layout: 13 (tabularindent/layout) +layerinfo type = theme; +layerinfo name = "Classic Desktop"; +layerinfo redist_uniq = "tabularindent/desktop"; +set body_bgcolor = "#00545c"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#ff7b05"; +set headerbar_fgcolor = "#ffeddd"; +set captionbar_mainbox_bgcolor = "#ffffff"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#ff7b05"; +set accent_bgcolor = "#ffeddd"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#5a76ff"; +set comment_bar_one_bgcolor = "#ff7b05"; +set comment_bar_one_fgcolor = "#ffeddd"; +set comment_bar_two_bgcolor = "#ffeddd"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/satinhandshake +layerinfo type = theme; +layerinfo name = "Satin Handshake"; +layerinfo redist_uniq = "tabularindent/satinhandshake"; +set body_bgcolor = "#480c0c"; +set main_bgcolor = "#d06464"; +set main_fgcolor = "#00001d"; +set border_color = "#000000"; +set headerbar_bgcolor = "#aaaaaa"; +set headerbar_fgcolor = "#000000"; +set captionbar_mainbox_bgcolor = "#aaaaaa"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#9d0404"; +set accent_bgcolor = "#9d0404"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#aaaaaa"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#9d0404"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/deepmelodrama +layerinfo type = theme; +layerinfo name = "Deep MeloDrama"; +layerinfo redist_uniq = "tabularindent/deepmelodrama"; +set body_bgcolor = "#872d89"; +set main_bgcolor = "#719cff"; +set main_fgcolor = "#8e48b2"; +set border_color = "#8e48b2"; +set headerbar_bgcolor = "#3794b3"; +set headerbar_fgcolor = "#84b8e7"; +set captionbar_mainbox_bgcolor = "#65b2c1"; +set captionbar_mainbox_fgcolor = "#f5d3ff"; +set captionbar_userpicbox_color = "#8e48b2"; +set accent_bgcolor = "#65b2c1"; +set accent_fgcolor = "#f5d3ff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#dfd3ff"; +set comment_bar_one_bgcolor = "#3794b3"; +set comment_bar_one_fgcolor = "#84b8e7"; +set comment_bar_two_bgcolor = "#65b2c1"; +set comment_bar_two_fgcolor = "#f5d3ff"; + +#NEWLAYER: tabularindent/everwhite +layerinfo type = theme; +layerinfo name = "Everwhite"; +layerinfo redist_uniq = "tabularindent/everwhite"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#ffffff"; +set headerbar_fgcolor = "#000000"; +set captionbar_mainbox_bgcolor = "#ffffff"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#ffffff"; +set accent_bgcolor = "#ffffff"; +set accent_fgcolor = "#000000"; +set link_color = "#e60000"; +set vlink_color = "#c10602"; +set alink_color = "#ff0600"; +set comment_bar_one_bgcolor = "#dddddd"; +set comment_bar_one_fgcolor = "#000000"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/everblue +layerinfo type = theme; +layerinfo name = "Everblue with Greys"; +layerinfo redist_uniq = "tabularindent/everblue"; +set body_bgcolor = "#0f0c6d"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#000000"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#aaaaaa"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#000000"; +set accent_bgcolor = "#aaaaaa"; +set accent_fgcolor = "#000000"; +set link_color = "#2f00f2"; +set vlink_color = "#060667"; +set alink_color = "#6691ff"; +set comment_bar_one_bgcolor = "#000000"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#aaaaaa"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/brownleather +layerinfo type = theme; +layerinfo name = "Brown Leather Coat"; +layerinfo redist_uniq = "tabularindent/brownleather"; +set body_bgcolor = "#d2b48c"; +set main_bgcolor = "#ffebcd"; +set main_fgcolor = "#8b4513"; +set border_color = "#000000"; +set headerbar_bgcolor = "#d48014"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#d48014"; +set captionbar_mainbox_fgcolor = "#d48014"; +set captionbar_userpicbox_color = "#d48014"; +set accent_bgcolor = "#ffe1a1"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#867a55"; +set alink_color = "#fffab3"; +set comment_bar_one_bgcolor = "#d48014"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffe1a1"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/bruise +layerinfo type = theme; +layerinfo name = "Bruise"; +layerinfo redist_uniq = "tabularindent/bruise"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#bcbcbc"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#1114a0"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#21c2f1"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#1114a0"; +set accent_bgcolor = "#21c2f1"; +set accent_fgcolor = "#0000ff"; +set link_color = "#0000cc"; +set vlink_color = "#000088"; +set alink_color = "#0000ff"; +set comment_bar_one_bgcolor = "#1114a0"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#21c2f1"; +set comment_bar_two_fgcolor = "#0000ff"; + +#NEWLAYER: tabularindent/ranchhand +layerinfo type = theme; +layerinfo name = "Ranch Hand"; +layerinfo redist_uniq = "tabularindent/ranchhand"; +set body_bgcolor = "#2999c2"; +set main_bgcolor = "#cfe0ff"; +set main_fgcolor = "#000000"; +set border_color = "#060667"; +set headerbar_bgcolor = "#54442c"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#bababa"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#9d995d"; +set accent_bgcolor = "#704400"; +set accent_fgcolor = "#bababa"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#6a20ff"; +set comment_bar_one_bgcolor = "#54442c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#704400"; +set comment_bar_two_fgcolor = "#bababa"; + +#NEWLAYER: tabularindent/victim +layerinfo type = theme; +layerinfo name = "Victim"; +layerinfo redist_uniq = "tabularindent/victim"; +set body_bgcolor = "#2cd0ff"; +set main_bgcolor = "#505050"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set headerbar_bgcolor = "#166bac"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#2098f3"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#26b6ff"; +set accent_bgcolor = "#353535"; +set accent_fgcolor = "#ffffff"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ff00c0"; +set comment_bar_one_bgcolor = "#166bac"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#353535"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: tabularindent/forest +layerinfo type = theme; +layerinfo name = "Forest"; +layerinfo redist_uniq = "tabularindent/forest"; +set body_bgcolor = "#778e64"; +set main_bgcolor = "#9b9ba5"; +set main_fgcolor = "#000000"; +set border_color = "#ffffff"; +set headerbar_bgcolor = "#72784c"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#72784c"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#a0ac62"; +set accent_bgcolor = "#73777a"; +set accent_fgcolor = "#000000"; +set link_color = "#3811e1"; +set vlink_color = "#310cbb"; +set alink_color = "#4e7bef"; +set comment_bar_one_bgcolor = "#72784c"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#73777a"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/drone +layerinfo type = theme; +layerinfo name = "Drone"; +layerinfo redist_uniq = "tabularindent/drone"; +set body_bgcolor = "#395f82"; +set main_bgcolor = "#f9fcfe"; +set main_fgcolor = "#000000"; +set border_color = "#000000"; +set headerbar_bgcolor = "#904094"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#f56efc"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#ff93ff"; +set accent_bgcolor = "#eeeeff"; +set accent_fgcolor = "#000000"; +set link_color = "#395f82"; +set vlink_color = "#395f82"; +set alink_color = "#5266ce"; +set comment_bar_one_bgcolor = "#904094"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#eeeeff"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/lowercurtain +layerinfo type = theme; +layerinfo name = "Lower the Curtain"; +layerinfo redist_uniq = "tabularindent/lowercurtain"; +set body_bgcolor = "#000000"; +set main_bgcolor = "#6b6b6b"; +set main_fgcolor = "#ffffff"; +set border_color = "#ffffff"; +set headerbar_bgcolor = "#363636"; +set headerbar_fgcolor = "#f0f5fb"; +set captionbar_mainbox_bgcolor = "#c6c6c6"; +set captionbar_mainbox_fgcolor = "#222222"; +set captionbar_userpicbox_color = "#363636"; +set accent_bgcolor = "#c5c8ca"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#3314ba"; +set comment_bar_one_bgcolor = "#363636"; +set comment_bar_one_fgcolor = "#f0f5fb"; +set comment_bar_two_bgcolor = "#c5c8ca"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/sunny +layerinfo type = theme; +layerinfo name = "Sunny Day"; +layerinfo redist_uniq = "tabularindent/sunny"; +set body_bgcolor = "#55e0f9"; +set main_bgcolor = "#e38202"; +set main_fgcolor = "#ffffff"; +set border_color = "#000000"; +set headerbar_bgcolor = "#e38202"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#fff505"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#efe052"; +set accent_bgcolor = "#ffba03"; +set accent_fgcolor = "#ffffff"; +set link_color = "#df0d12"; +set vlink_color = "#ac1b25"; +set alink_color = "#fe3b3b"; +set comment_bar_one_bgcolor = "#ffba03"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffba36"; +set comment_bar_two_fgcolor = "#ffffff"; + +#NEWLAYER: tabularindent/valentine +layerinfo type = theme; +layerinfo name = "Be Mine"; +layerinfo redist_uniq = "tabularindent/valentine"; +set body_bgcolor = "#6f104a"; +set main_bgcolor = "#f2bce9"; +set main_fgcolor = "#000000"; +set border_color = "#ff24ab"; +set headerbar_bgcolor = "#ff37ff"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#df2096"; +set captionbar_mainbox_fgcolor = "#ffffff"; +set captionbar_userpicbox_color = "#ae1774"; +set accent_bgcolor = "#df2096"; +set accent_fgcolor = "#000000"; +set link_color = "#ffffff"; +set vlink_color = "#a51014"; +set alink_color = "#ed8188"; +set comment_bar_one_bgcolor = "#ff37ff"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#df2096"; +set comment_bar_two_fgcolor = "#000000"; + +#NEWLAYER: tabularindent/stripes +layerinfo type = theme; +layerinfo name = "Stripes"; +layerinfo redist_uniq = "tabularindent/stripes"; +set body_bgcolor = "#ffffff"; +set main_bgcolor = "#ffffff"; +set main_fgcolor = "#000000"; +set border_color = "#ff0000"; +set headerbar_bgcolor = "#e7212a"; +set headerbar_fgcolor = "#ffffff"; +set captionbar_mainbox_bgcolor = "#ffffff"; +set captionbar_mainbox_fgcolor = "#000000"; +set captionbar_userpicbox_color = "#ffffff"; +set accent_bgcolor = "#ffcfdc"; +set accent_fgcolor = "#000000"; +set link_color = "#000050"; +set vlink_color = "#500050"; +set alink_color = "#ffafc1"; +set comment_bar_one_bgcolor = "#e7212a"; +set comment_bar_one_fgcolor = "#ffffff"; +set comment_bar_two_bgcolor = "#ffcfdc"; +set comment_bar_two_fgcolor = "#000000"; diff --git a/livejournal/bin/upgrading/s2layers/variableflow/layout.s2 b/livejournal/bin/upgrading/s2layers/variableflow/layout.s2 new file mode 100755 index 0000000..5203b75 --- /dev/null +++ b/livejournal/bin/upgrading/s2layers/variableflow/layout.s2 @@ -0,0 +1,967 @@ + + +layerinfo "type" = "layout"; +layerinfo "name" = "Variable Flow"; +layerinfo "author_name" = "Martin Atkins"; +layerinfo "des" = "A really simple layout that you can customize like crazy!"; +layerinfo "redist_uniq" = "variableflow/layout"; +layerinfo "previews" = "variableflow/preview.jpg"; + +# Originally known as "Cleanly Shaven" +# +# This layout is full of customization options, and is designed +# with code overrides in mind. +# It also uses meaningful markup an CSS, for those who like that +# sort of thing. If you like, you can override the stylesheet +# completely in your user layer to drastically change the +# presentation. + +propgroup colors { + property Color clr_margin { + des = "Page Background Color"; + } + property Color clr_line { + des = "Color of line separating the entry area from the background"; + requires = "opt_page_border"; + } + property Color clr_back { + des = "Background Color of Main Content Area"; + requires = "opt_page_background"; + } + property Color clr_text { + des = "Main Text Color"; + } + property Color clr_link { + des = "Color of normal links"; + } + property Color clr_vlink { + des = "Color of visited links"; + } + property Color clr_alink { + des = "Color of links once clicked on"; + } + property Color clr_title { + des = "Journal Title Color"; + } + set clr_margin = "#337CCD"; + set clr_line = "#000000"; + set clr_back = "#33ABCD"; + set clr_text = "#000000"; + set clr_link = "#261A72"; + set clr_vlink = "#190F57"; + set clr_alink = "#261A72"; + set clr_title = "#190F57"; +} + +propgroup layout { + property string margin_left { + des = "Page Left Margin Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string margin_right { + des = "Page Right Margin Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string margin_top { + des = "Page Top Margin Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string margin_bottom { + des = "Page Bottom Margin Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + set margin_left = "25%"; + set margin_right = "25%"; + set margin_top = "5px"; + set margin_bottom = "5px"; + + property string padding_left { + des = "Page Left Inner Padding Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string padding_right { + des = "Page Right Inner Padding Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string padding_top { + des = "Page Top Inner Padding Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + property string padding_bottom { + des = "Page Bottom Inner Padding Size"; + values = "0|None|5px|Tiny|5%|Small|10%|Medium|25%|Large|50%|Massive"; + } + set padding_left = "5px"; + set padding_right = "5px"; + set padding_top = "5px"; + set padding_bottom = "5px"; + + property string align_viewlinks { + des = "Position of links to other journal views"; + values = "left|Left|right|Right|center|Center"; + } + property string align_title { + des = "Position of journal title"; + values = "left|Left|right|Right|center|Center"; + } + property string align_talklinks { + des = "Position of comment links"; + values = "left|Left|right|Right|center|Center"; + } + set align_viewlinks = "right"; + set align_title = "left"; + set align_talklinks = "right"; + + + # Some "advanced" settings which don't appear in the UI, + # either because they have non-obvious interactions with + # other properties or they have issues in certain browsers. + property string adv_page_max_width { + des = "Maximum Width of Content Area"; + note = "If you set this, you should also set margin_left and/or margin_right to 'auto'. Internet Explorer 6 does not support this property."; + noui = 1; + } + property string adv_entry_max_width { + des = "Maximum Width of Entry Text"; + note = "Internet Explorer 6 does not support this property, and will present entries full-width."; + noui = 1; + } + property bool adv_enable_print_styles { + des = "Enable Print Stylesheet"; + note = "If you disable this, your journal views may be unsuitable for printing."; + noui = 1; + } + property bool adv_enable_projection_styles { + des = "Enable Projection Stylesheet"; + note = "With this enabled, browsers which support projection stylesheets will see a different stylesheet."; + noui = 1; + } + property bool adv_horrible_userpic_markup { + des = "Enable horrible userpic markup"; + note = "With this enabled, the layout will use a table hack to present userpics. With it disabled, the userpics will just be shown raw with class userpic. You'll have to add your own stylesheet rules for them."; + # See the comment within Page::print_entry for more details + noui = 1; + } + set adv_page_max_width = ""; + set adv_entry_max_width = ""; + set adv_enable_print_styles = true; + set adv_enable_projection_styles = true; + set adv_horrible_userpic_markup = true; +} + +propgroup presentation { + property use font_base; + property use font_fallback; + + property string font_size { + des = "Size of text"; + values = "0.75em|Tiny|1em|Normal|1.1em|Large"; + } + set font_size = "0.75em"; + + property bool opt_page_border { + des = "Draw Line Around Content Box"; + note = "With this disabled, the line color option has no effect"; + } + property bool opt_page_background { + des = "Content Box has Background"; + note = "With this disabled, the Content Box Background Color and Image options have no effect and the page background will show through instead."; + } + set opt_page_border = true; + set opt_page_background = true; + + property string url_background_img_page { + des = "Page Background Image URL"; + note = "Leave this blank if you do not wish to use a background image."; + palimg_transform = "tint;*clr_back"; # Doesn't do anything right now + } + set url_background_img_page = ""; + + property string background_properties_page { + des = "Page Background Image Display Options"; + values = "scroll|Scrolling, Tiled|scroll no-repeat|Scrolling, No repeat|scroll repeat-x|Scrolling, tile horizontally|scroll repeat-y|Scrolling, tile vertically|fixed|Fixed, Tiled|fixed no-repeat|Fixed, No repeat|fixed repeat-x|Fixed, tile horizontally|fixed repeat-y|Fixed, tile vertically"; + requires = "url_background_img_page"; + } + set background_properties_page = "scroll"; + + property string background_position_page { + des = "Page Background Position"; + values = "center|Centered|center left|Centered Vertically, Left|center right|Centered Vertically, Right|top center|Top, Centered Horizontally|top left|Top, Left|top right|Top, Right|bottom center|Bottom, Centered Horizontally|bottom left|Bottom, Left|bottom right|Bottom, Right"; + requires = "url_background_img_page"; + } + set background_position_page = "top left"; + + property string url_background_img_box { + des = "Content Box Background Image URL"; + note = "Leave this blank if you do not wish to use a background image."; + palimg_transform = "tint;*clr_back"; # Doesn't do anything right now + requires = "opt_page_background"; + } + set url_background_img_box = ""; + + property string background_properties_box { + des = "Content Box Background Image Display Options"; + values = "scroll|Scrolling, Tiled|scroll no-repeat|Scrolling, No repeat|scroll repeat-x|Scrolling, tile horizontally|scroll repeat-y|Scrolling, tile vertically|fixed|Fixed, Tiled|fixed no-repeat|Fixed, No repeat|fixed repeat-x|Fixed, tile horizontally|fixed repeat-y|Fixed, tile vertically"; + requires = "opt_page_background,url_background_img_box"; + } + set background_properties_box = "scroll"; + + property string background_position_box { + des = "Content Box Background Position"; + values = "center|Centered|center left|Centered Vertically, Left|center right|Centered Vertically, Right|top center|Top, Centered Horizontally|top left|Top, Left|top right|Top, Right|bottom center|Bottom, Centered Horizontally|bottom left|Bottom, Left|bottom right|Bottom, Right"; + requires = "opt_page_background,url_background_img_box"; + } + set background_position_box = "top left"; + + property bool opt_entry_userpics { + des = "Enable Userpics On Entries"; + note = "With this disabled, no entries will show userpics, even on the friends page."; + } + set opt_entry_userpics = true; + + property bool opt_own_userpics { + des = "Show Own Userpics"; + note = "Enable this to show userpics on your own entries. You must also have the previous option enabled. This option has no effect on community journals."; + requires = "opt_entry_userpics"; + } + set opt_own_userpics = false; + + # This layout has quite a big stylesheet so let's avoid + # transferring it over and over. + set external_stylesheet = true; + + # No good support for EntryPage/ReplyPage yet + set view_entry_disabled = true; +} + +propgroup options { + + # Some standard constructional properties + property use page_recent_items; + property use page_friends_items; + property use page_year_sortorder; + property use page_day_sortorder; + + # Tell the system this layout has no linklist support + # If you add linklist support in a user layer, you should also + # set this property to true in your layer. + set linklist_support = false; +} + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; +} + +function makefontspec() : string +"Forms a CSS 'font-family' value based on the font-related properties." +{ + var string fontspec; + if ($*font_base != "") { + $fontspec="\""+$*font_base+"\""; + if ($*font_fallback != "") { + $fontspec=$fontspec+","; + } + } + $fontspec=$fontspec+$*font_fallback; + return $fontspec; +} + +function Page::lay_print_viewlinks() +"If you override this, be sure to still use foreach or your style won't support any future views." +{ + # Output a list of textual links in a particular order + var bool first = true; + + "
      \n"; + foreach var string vl ($.views_order) { + if ($vl == $.view) { + print "
    • "+lang_viewname($vl)+"
    • \n"; + } else { + print "
    • "+lang_viewname($vl)+"
    • \n"; + } + $first = false; + } + "
    \n"; +} + +function Page::lay_print_heading() +"This can be overridden to change the main page titles to something else." +{ +"""

    """+$.global_title+"""

    +
    """; + + if ($.view == "recent" and $.global_subtitle != "") { + print $.global_subtitle; + } else { + print $this->view_title(); + } + + println """
    """; + +} + +function Page::print() { + """ + + +"""+$this->title()+""" +"""; + if ($*external_stylesheet) { + println """"""; + } + else { + println """"""; + } + $this->print_head(); +""" + + + +
    +"""; $this->lay_print_viewlinks(); """ + +
    +"""; $this->lay_print_heading(); """ +
    + +"""; $this->print_body(); """ + +
    """; server_sig(); """
    + +
    + +"""; + +} + +function lang_skipped_back(RecentNav nav) : string +"Return short text saying how many entries have been skipped back. i18n layers should override this." +{ + return "Skipped Back $nav.skip"; +} + +## The properties for these links are currently broken +## in core - they were never updated to work with lang_map_plural. +# So, FIXME: When core does them right, remove the hardcoded English +function RecentPage::lay_print_skiplinks() { + if ($.nav.backward_url != "" or $.nav.forward_url != "") { + println """"; + } +} + +function RecentPage::print_body() { + + $this->lay_print_skiplinks(); + + foreach var Entry e ($.entries) { + if ($e.new_day) { + """
    date_format("%%yyyy%%%%mm%%%%dd%%")+"\">\n"; + } + # Print the entry + $this->print_entry($e); + if ($e.end_day) { + "
    "; + } + } + + if (size $.entries > 0) { + $this->lay_print_skiplinks(); + } + +} + +function DayPage::print_body() { + + """"; + + + if ($.has_entries) { + "
    \n"; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + "
    "; + + ""; + + + } else { + "

    $*text_noentries_day

    "; + } + +} + + +## YearPage Stuff +function YearPage::print_body { + $this->print_year_links(); + println """
    """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + println "
    "; +} +function YearPage::print_year_links() { + """
      \n"""; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """
    • $y.year
    • \n"""; + } else { + """
    • $y.year
    • \n"""; + } + } + """
    \n"""; +} +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + """\n + \n"""; + foreach var int d (weekdays()) { + "\n"; + } + "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """\n"""; + "
    """; + print "

    "+$m->month_format()+"

    \n"; + """
    "+$*lang_dayname_short[$d]+"
    "; +} +function YearWeek::print() { + """\n"""; + if ($.pre_empty > 0) { + """ \n"""; + } + foreach var YearDay d ($.days) { + """\n"""; + """
    $d.day
    \n"""; + if ($d.num_entries > 0) { + """\n"""; + } + """\n"""; + } + if ($.post_empty > 0) { + """ \n"""; + } + ""; +} + + +function metadata_title(string which) : string +"Until core provides a function for this, i18n layers should override this." +{ + if ($which == "music") { + return "Current Music"; + } + elseif ($which == "mood") { + return "Current Mood"; + } + else { + return $which; + } +} + +# Since there's currently no trusted print_entry_text function +# in core, I have to do this here. Later, when something similar +# is added to core, this can become a wrapper and be deprecated. +function Page::lay_print_entry_text(Entry e) [fixed] +"Don't override this. All it does is print the entry text." +{ + print $e.text; +} + +# Since the metadata keys have to be hardcoded (bad core design) +# let's separate this out so people can override print_entry +# and still get any new metadata added later. +function Page::lay_print_entry_metadata(Entry e) +"Overriding this is strongly discouraged, since if any new entry metadata is added in the future your overridden version will not support it." +{ + if (size $e.metadata > 0) { + # This is horrible and unextensible. We have core to thank. + # C'est la vie. + "
    \n"; + if ($e.metadata{"music"} != "") { + """
    """+metadata_title("music") + ": " + + $e.metadata{"music"}+"
    \n"; + } + if ($e.metadata{"mood"} != "") { + """
    """+metadata_title("mood") + ": "; + if (defined $e.mood_icon) { + print $e.mood_icon->as_string()+" "; + } + print $e.metadata{"mood"}+"
    \n"; + } + "
    \n"; + } +} + +function Page::print_entry(Entry e) { + """
    \n"""; + + var bool altposter = $e.poster.username != $e.journal.username; + var bool showpic = $*opt_entry_userpics and (($.view == "friends" or $altposter) or $*opt_own_userpics); + + # By default, this layout uses an ugly table hack to present the userpic + # alongside the entry. This is because I've been bitten on many previous + # occasions by a bug with floats in IE causing text to vanish in certain + # cases. You can set the property adv_horrible_userpic_markup to false + # in a user layer to disable this behavior, but there are no CSS rules + # in the stock stylesheet to handle it, so you'll have to supply your + # own. + + if ($showpic) { + if ($*adv_horrible_userpic_markup) { + """ + +
    """; + } + if (defined $e.userpic) { + println """"""; + } else { + if ($*adv_horrible_userpic_markup) { + print " "; + } + } + if ($*adv_horrible_userpic_markup) { + ""; + } + } + """

    """; + if ($.view != "day") { + print $e.time->date_format()+" "; + } + print $e.time->time_format(); + if ($.view == "friends") { + " - "; $this->print_entry_poster($e); + } + elseif ($altposter) { + " - " + $e.poster->as_string(); + } + if ($e.security != "") { + " - " + $e.security_icon->as_string(); + } + if ($e.subject != "") { + " - $e.subject"; + } + "

    \n"; $this->lay_print_entry_text($e); + + $this->lay_print_entry_metadata($e); + + if ($showpic and $*adv_horrible_userpic_markup) { + "
    "; + } + $e.comments->print(); + "
    "; +} + +function CommentInfo::print { + if (not $.enabled) { return; } + """
      """; + if ($.count > 0) { + print """"; + } + print """"; + "
    "; +} + +function EntryPage::print_comment (Comment c) { + var Color barlight = $*color_comment_bar->clone(); + $barlight->lightness(($barlight->lightness() + 255) / 2); + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + + "
    "; + ""; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + $w = $w / 2; + $h = $h / 2; + print ""; + } + "
    "; + if (defined $c.subject_icon or $c.subject != "") { "

    $c.subject_icon $c.subject

    \n"; } + print "$*text_comment_from $poster
    \n"; + print "$*text_comment_date "; + print $c.time->date_format("long") + " - " + $c.time->time_format(); + if ($c.metadata{"poster_ip"}) { print " ($*text_comment_ipaddr " + $c.metadata{"poster_ip"} + ")"; } + print " ($*text_permalink)\n"; + + var Link link; + foreach var string s (["delete_comment", "screen_comment", "unscreen_comment"]) { + + } + $link = $c->get_link("delete_comment"); " $link"; + $link = $c->get_link("screen_comment"); " $link"; + $link = $c->get_link("unscreen_comment"); " $link"; + + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + + print "
    "; + print "
    $c.text
    \n"; + print "
    ($*text_comment_reply) "; + if ($c.parent_url != "") { "($*text_comment_parent) "; } + if ($c.thread_url != "") { "($*text_comment_thread) "; } + "
    \n"; +} + +function css_rule_if_set(string prop, string val) +"Print a CSS rule only if val is not an empty string." +{ + if ($val != "") { + println " $prop: $val;"; + } +} + +function custom_stylesheet() +"Override this in your user layer to add new stuff to the stylesheet" +{ + # None, by default +} + +function print_stylesheet_for_printing() +"If you have printing styles enabled, you can override this function to change how the page is styled for printing." +{ + + """ body, #page, a, a:link, a:visited, a:active, a:hover, #title, h2 { + background: #ffffff; + color: #000000; + } + body { + margin-top: 1em; + margin-bottom: 1em; + font-size: 12pt; + margin-left: auto; + margin-right: auto; + font-family: "Garamond", "Palatino", "Palatino Linotype", serif; + max-width: 15cm; + } + h1, h2, h3, h4, h5, h6, #title #viewtitle { + font-family: "Frutiger", "Frutiger Linotype", "Helvetica", sans-serif; + page-break-after: avoid; + } + .entry { + page-break-inside: avoid; + text-align: justify; + } + .calendarmonth { + page-break-inside: avoid; + } + #page { + border: 0; + margin: 0; + } + .navbar, .entryextra, .viewspecnavbar { + display: none; + } + #title { + display: block; + } + #title h1, #title #viewtitle { + display: inline; + } + #title #viewtitle { + margin-left: 2em; + font-style: italic; + } +"""; +} + +function print_stylesheet_for_projection() +"If you have projection styles enabled, you can override this function to change how the page is styled for projection." +{ + + + var string background_body = $*clr_margin; + if ($*url_background_img_page != "" and not $*url_background_img_page->contains(")")) { + $background_body = $background_body + " url($*url_background_img_page)"; + if (not $*background_properties_page->contains(";")) { + $background_body = $background_body + " $*background_properties_page"; + } + } + else { + $background_body = $background_body + " none"; + } + + var string background_page = $*clr_back; + if ($*url_background_img_box != "" and not $*url_background_img_box->contains(")")) { + $background_page = $background_page + " url($*url_background_img_box)"; + if (not $*background_properties_box->contains(";")) { + $background_page = $background_page + " $*background_properties_box"; + } + } + else { + $background_page = $background_page + " none"; + } + + """ #page { + margin: 10px; + padding: 0; + border: 0; + font-size: 2em; + } + body { + background: $background_body; + color: $*clr_text; + } + .navbar, .viewspecnavbar { display: none; } + .entry, #title { + page-break-after: always; + margin: auto; + padding: 10px; + position: absolute; + top: 10px; + bottom: 10px; + left: 10px; + right: 10px; +"""; + if ($*opt_page_border) { + println """ border: 1px solid $*clr_line;"""; + } + if ($*opt_page_background) { + println """ background: $background_page;"""; + } + " }\n"; +} + +function print_stylesheet() { + var string fontspec=makefontspec(); + if ($fontspec != "") { + $fontspec=" font-family: $fontspec;"; + } + + var string eextrastyle=""; + if ($*align_talklinks != "right") { + $eextrastyle=$eextrastyle+ + """.entryextra:after { content: " :."; }\n"""; + } + if ($*align_talklinks != "left") { + $eextrastyle=$eextrastyle+ + """.entryextra:before { content: ".: "; }\n"""; + } + $eextrastyle=$eextrastyle+ + """.entryextra { text-align: $*align_talklinks; font-size: 0.9em; }"""; + + # This tries to do a bit of "sanity" checking to ensure users + # don't inadvertently break the CSS, but it's not brilliant. + var string background_body = $*clr_margin; + if ($*url_background_img_page != "" and not $*url_background_img_page->contains(")")) { + $background_body = $background_body + " url($*url_background_img_page)"; + if (not $*background_properties_page->contains(";")) { + $background_body = $background_body + " $*background_properties_page"; + } + if (not $*background_position_page->contains(";")) { + $background_body = $background_body + " $*background_position_page"; + } + } + else { + $background_body = $background_body + " none"; + } + + var string background_page = $*clr_back; + if ($*url_background_img_box != "" and not $*url_background_img_box->contains(")")) { + $background_page = $background_page + " url($*url_background_img_box)"; + if (not $*background_properties_box->contains(";")) { + $background_page = $background_page + " $*background_properties_box"; + } + if (not $*background_position_box->contains(";")) { + $background_page = $background_page + " $*background_position_box"; + } + } + else { + $background_page = $background_page + " none"; + } + + +""" +body { + margin: 0; + padding: 0; + border: 0; + background: $background_body; + color: $*clr_text; + $fontspec font-size: $*font_size; +} +table, tr, td, th { + font-size: 1em; +} +#page { +"""; + css_rule_if_set("margin-left", $*margin_left); + css_rule_if_set("margin-right", $*margin_right); + css_rule_if_set("margin-top", $*margin_top); + css_rule_if_set("margin-bottom", $*margin_bottom); + css_rule_if_set("padding-left", $*padding_left); + css_rule_if_set("padding-right", $*padding_right); + css_rule_if_set("padding-top", $*padding_top); + css_rule_if_set("padding-bottom", $*padding_bottom); + css_rule_if_set("max-width", $*adv_page_max_width); + + if ($*opt_page_border) { + println """ border: 1px solid $*clr_line;"""; + } + if ($*opt_page_background) { + println """ background: $background_page;"""; + } +""" +} +#title h1 { + font-size: 1.4em; + font-weight: bold; + text-align: $*align_title; + margin: 0; +} +#title #viewtitle { + font-size: 1.1em; + font-weight: bold; + text-align: $*align_title; + margin: 0; +} +.navbar { + text-align: $*align_viewlinks; + list-style: none; + padding: 0; + margin: 0; + display: block; +} +.viewspecnavbar { + text-align: center; + list-style: none; + padding: 0; + margin: 0; + display: block; + margin-top: 1em; + margin-bottom: 1em; +} +.navbar li { display: inline; white-space: nowrap; } +.navbar li.active { display: inline; } +.navbar li:before { content: " :: "; } +.navbar li:first-child:before { content: ""; } +.viewspecnavbar li { display: inline; white-space: nowrap; } +.viewspecnavbar li.active { display: inline; } +.viewspecnavbar li:before { content: " :: "; } +.viewspecnavbar li:first-child:before { content: ""; } + +#title { + margin-top: 3em; + margin-bottom: 0.5em; + color: $*clr_title; + background: transparent; +} +a:link { color: $*clr_link; background: transparent; } +a:visited { color: $*clr_vlink; background: transparent; } +a:active, a:hover { color: $*clr_alink; background: transparent; } +.entry { + margin-bottom: 4em; +} +.entryheading { + font-weight: bold; font-size: 1.0em; +} +.entrytext { +"""; css_rule_if_set("max-width", $*adv_entry_max_width); +""" margin-left: auto; + margin-right: auto; +} + +.entry .metadata { + margin-top: 0.5em; + margin-bottom: 0; + margin-left: 0; + margin-right: 0; +} + +.entryextra { + list-style: none; + padding: 0; + margin-left: 0; + margin-right: 0; + display: block; +} +.entryextra li { + display: inline; +} +.entryextra li.entryreadlink:after { + content: " :: "; +} +.entryextra li.entryreadlink { + font-weight: bold; +} +$eextrastyle + +/* IE hack - center the block with text-align! */ +.calendarmonthcontainer { + text-align: center; +} + +.calendarmonth { + margin-top: 2em; + margin-bottom: 2em; + margin-left: auto; + margin-right: auto; + text-align: left; +} +.calendarmonth h2 { + font-size: 1em; + font-weight: bold; + margin: 0; +} +.calendarday { + width: 3em; + max-width: 3em; + height: 3em; +} + +"""; + +if ($*adv_enable_print_styles) { +""" +@media print { +"""; print_stylesheet_for_printing(); """ +} +"""; +} + +if ($*adv_enable_projection_styles) { +""" +@media projection { +"""; print_stylesheet_for_projection(); """ +} +"""; +} + + custom_stylesheet(); + +} + diff --git a/livejournal/bin/upgrading/s2layers/variableflow/preview.jpg b/livejournal/bin/upgrading/s2layers/variableflow/preview.jpg new file mode 100755 index 0000000000000000000000000000000000000000..b82168d76ec38108b26e2b31405a3ea3620ee8c5 GIT binary patch literal 23817 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 literal 0 HcmV?d00001 diff --git a/livejournal/bin/upgrading/s2style-wizard-update.pl b/livejournal/bin/upgrading/s2style-wizard-update.pl new file mode 100755 index 0000000..89ef314 --- /dev/null +++ b/livejournal/bin/upgrading/s2style-wizard-update.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +use strict; +$| = 1; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $sysid = LJ::get_userid("system"); +die "Couldn't find system userid" + unless $sysid; + +my $dbh = LJ::get_db_writer(); +die "Could not connect to global master" + unless $dbh; + + +# find info on styles based on public layouts + +# need to select from: +# s2styles - get style name +# s2stylelayers - get layout s2lid +# s2layers - get userid of layer +# s2info - get redist_uniq + +{ + print "Converting styles based on public layouts..."; + + my $sth = $dbh->prepare("SELECT s.styleid, i.value " . + "FROM s2styles s, s2stylelayers sl, s2layers l, s2info i " . + "WHERE s.styleid=sl.styleid AND l.s2lid=sl.s2lid AND i.s2lid=l.s2lid " . + "AND l.userid=? AND l.type='layout' AND s.name='wizard' " . + "AND i.infokey='redist_uniq'"); + $sth->execute($sysid); + my $ct = 0; + while (my ($styleid, $redist_uniq) = $sth->fetchrow_array) { + + my $layout = (split("/", $redist_uniq))[0]; + $dbh->do("UPDATE s2styles SET name=? WHERE styleid=?", + undef, "wizard-$layout", $styleid); + $ct++; + print "." if $ct % 1000 == 0; + } + + print " $ct done.\n"; +} + + +# find info on styles based on user layouts + +# need to select from: +# s2styles - get style name +# s2stylelayers - get layout s2lid +# s2layers - get userid of layer + +{ + print "Converting styles based on user layouts..."; + + my $sth = $dbh->prepare("SELECT s.styleid, l.s2lid " . + "FROM s2styles s, s2stylelayers sl, s2layers l " . + "WHERE s.styleid=sl.styleid AND l.s2lid=sl.s2lid " . + "AND l.userid<>? AND l.type='layout' AND s.name='wizard'"); + $sth->execute($sysid); + my $ct = 0; + while (my ($styleid, $s2lid) = $sth->fetchrow_array) { + + $dbh->do("UPDATE s2styles SET name=? WHERE styleid=?", + undef, "wizard-$s2lid", $styleid); + $ct++; + print "." if $ct % 1000 == 0; + } + + print " $ct done.\n"; +} diff --git a/livejournal/bin/upgrading/support-upgrade.pl b/livejournal/bin/upgrading/support-upgrade.pl new file mode 100755 index 0000000..4e30fe5 --- /dev/null +++ b/livejournal/bin/upgrading/support-upgrade.pl @@ -0,0 +1,21 @@ +#!/usr/bin/perl +# + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbh = LJ::get_dbh("master"); +my $sth; + +$sth = $dbh->prepare("SELECT spid FROM support WHERE timelasthelp IS NULL"); +$sth->execute; +while (my ($spid) = $sth->fetchrow_array) +{ + print "Fixing $spid...\n"; + my $st2 = $dbh->prepare("SELECT MAX(timelogged) FROM supportlog WHERE spid=$spid AND type='answer'"); + $st2->execute; + my ($max) = $st2->fetchrow_array; + $max = $max + 0; # turn undef -> 0 + print " time = $max\n"; + $dbh->do("UPDATE support SET timelasthelp=$max WHERE spid=$spid"); + +} diff --git a/livejournal/bin/upgrading/text.dat b/livejournal/bin/upgrading/text.dat new file mode 100755 index 0000000..873a62f --- /dev/null +++ b/livejournal/bin/upgrading/text.dat @@ -0,0 +1,9 @@ +# Note to people using LJ Server software: +# Do not modify this file. Create text-local.dat, and that will +# be read as well. See LiveJournal.com's text-local.dat in ljcom CVS. + +# one language, english, which is the master of one domain (general) +lang:1:en:English +domain:1:general +langdomain:en:general:1 + diff --git a/livejournal/bin/upgrading/texttool.pl b/livejournal/bin/upgrading/texttool.pl new file mode 100755 index 0000000..5c7bc3e --- /dev/null +++ b/livejournal/bin/upgrading/texttool.pl @@ -0,0 +1,690 @@ +#!/usr/bin/perl +# +# This program deals with inserting/extracting text/language data +# from the database. +# + +use strict; +use Getopt::Long; + +my $opt_help = 0; +my $opt_local_lang; +my $opt_extra; +my $opt_only; +my $opt_override; +my $opt_verbose; +exit 1 unless +GetOptions( + "help" => \$opt_help, + "local-lang=s" => \$opt_local_lang, + "extra=s" => \$opt_extra, + "override|r" => \$opt_override, + "verbose" => \$opt_verbose, + "only=s" => \$opt_only, + ); + +my $mode = shift @ARGV; + +help() if $opt_help or not defined $mode; + +sub help +{ + die "Usage: texttool.pl + +Where 'command' is one of: + load Runs the following four commands in order: + popstruct Populate lang data from text[-local].dat into db + poptext Populate text from en.dat, etc into database. + --extra= specifies an alternative input file + --override (-v) specifies existing values should be overwritten + for all languages. (for developer use only) + copyfaq If site is translating FAQ, copy FAQ data into trans area + loadcrumbs Load crumbs from ljcrumbs.pl and ljcrumbs-local.pl. + makeusable Setup internal indexes necessary after loading text + dumptext Dump lang text based on text[-local].dat information + check Check validity of text[-local].dat files + wipedb Remove all language/text data from database, including crumbs. + wipecrumbs Remove all crumbs from the database, leaving other text alone. + newitems Search files in htdocs, cgi-bin, & bin and insert + necessary text item codes in database. + remove takes two extra arguments: domain name and code, and removes + that code and its text in all languages + + Optionally: + --local-lang=.. If given, works on local site files too + +"; +} + +## make sure $LJHOME is set so we can load & run everything +unless (-d $ENV{'LJHOME'}) { + die "LJHOME environment variable is not set, or is not a directory.\n". + "You must fix this before you can run this database update script."; +} +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; +require "$ENV{'LJHOME'}/cgi-bin/weblib.pl"; + +my %dom_id; # number -> {} +my %dom_code; # name -> {} +my %lang_id; # number -> {} +my %lang_code; # name -> {} +my @lang_domains; + +my $set = sub { + my ($hash, $key, $val, $errmsg) = @_; + die "$errmsg$key\n" if exists $hash->{$key}; + $hash->{$key} = $val; +}; + +foreach my $scope ("general", "local") +{ + my $file = $scope eq "general" ? "text.dat" : "text-local.dat"; + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + unless (-e $ffile) { + next if $scope eq "local"; + die "$file file not found; odd: did you delete it?\n"; + } + open (F, $ffile) or die "Can't open file: $file: $!\n"; + while () { + s/\s+$//; s/^\#.+//; + next unless /\S/; + my @vals = split(/:/, $_); + my $what = shift @vals; + + # language declaration + if ($what eq "lang") { + my $lang = { + 'scope' => $scope, + 'lnid' => $vals[0], + 'lncode' => $vals[1], + 'lnname' => $vals[2], + 'parentlnid' => 0, # default. changed later. + 'parenttype' => 'diff', + }; + $lang->{'parenttype'} = $vals[3] if defined $vals[3]; + if (defined $vals[4]) { + unless (exists $lang_code{$vals[4]}) { + die "Can't declare language $lang->{'lncode'} with missing parent language $vals[4].\n"; + } + $lang->{'parentlnid'} = $lang_code{$vals[4]}->{'lnid'}; + } + $set->(\%lang_id, $lang->{'lnid'}, $lang, "Language already defined with ID: "); + $set->(\%lang_code, $lang->{'lncode'}, $lang, "Language already defined with code: "); + } + + # domain declaration + if ($what eq "domain") { + my $dcode = $vals[1]; + my ($type, $args) = split(m!/!, $dcode); + my $dom = { + 'scope' => $scope, + 'dmid' => $vals[0], + 'type' => $type, + 'args' => $args || "", + }; + $set->(\%dom_id, $dom->{'dmid'}, $dom, "Domain already defined with ID: "); + $set->(\%dom_code, $dcode, $dom, "Domain already defined with parameters: "); + } + + # langdomain declaration + if ($what eq "langdomain") { + my $ld = { + 'lnid' => + (exists $lang_code{$vals[0]} ? $lang_code{$vals[0]}->{'lnid'} : + die "Undefined language: $vals[0]\n"), + 'dmid' => + (exists $dom_code{$vals[1]} ? $dom_code{$vals[1]}->{'dmid'} : + die "Undefined domain: $vals[1]\n"), + 'dmmaster' => $vals[2] ? "1" : "0", + }; + push @lang_domains, $ld; + } + } + close F; +} + +if ($mode eq "check") { + print "all good.\n"; + exit 0; +} + +## make sure we can connect +my $dbh = LJ::get_dbh("master"); +my $sth; +unless ($dbh) { + die "Can't connect to the database.\n"; +} + +# indenter +my $idlev = 0; +my $out = sub { + my @args = @_; + while (@args) { + my $a = shift @args; + if ($a eq "+") { $idlev++; } + elsif ($a eq "-") { $idlev--; } + elsif ($a eq "x") { $a = shift @args; die " "x$idlev . $a . "\n"; } + else { print " "x$idlev, $a, "\n"; } + } +}; + +my @good = qw(load popstruct poptext dumptext newitems wipedb makeusable copyfaq remove + wipecrumbs loadcrumbs); + +popstruct() if $mode eq "popstruct" or $mode eq "load"; +poptext(@ARGV) if $mode eq "poptext" or $mode eq "load"; +copyfaq() if $mode eq "copyfaq" or $mode eq "load"; +loadcrumbs() if $mode eq "loadcrumbs" or $mode eq "load"; +makeusable() if $mode eq "makeusable" or $mode eq "load"; +dumptext(@ARGV) if $mode eq "dumptext"; +newitems() if $mode eq "newitems"; +wipedb() if $mode eq "wipedb"; +wipecrumbs() if $mode eq "wipecrumbs"; +remove(@ARGV) if $mode eq "remove" and scalar(@ARGV) == 2; +help() unless grep { $mode eq $_ } @good; +exit 0; + +sub makeusable +{ + $out->("Making usable...", '+'); + my $rec = sub { + my ($lang, $rec) = @_; + my $l = $lang_code{$lang}; + $out->("x", "Bogus language: $lang") unless $l; + my @children = grep { $_->{'parentlnid'} == $l->{'lnid'} } values %lang_code; + foreach my $cl (@children) { + $out->("$l->{'lncode'} -- $cl->{'lncode'}"); + + my %need; + # push downwards everything that has some valid text in some language (< 4) + $sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$l->{'lnid'} AND staleness < 4"); + $sth->execute; + while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) { + $need{"$dmid:$itid"} = $txtid; + } + $sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$cl->{'lnid'}"); + $sth->execute; + while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) { + delete $need{"$dmid:$itid"}; + } + while (my $k = each %need) { + my ($dmid, $itid) = split(/:/, $k); + my $txtid = $need{$k}; + my $stale = $cl->{'parenttype'} eq "diff" ? 3 : 0; + $dbh->do("INSERT INTO ml_latest (lnid, dmid, itid, txtid, chgtime, staleness) VALUES ". + "($cl->{'lnid'}, $dmid, $itid, $txtid, NOW(), $stale)"); + die $dbh->errstr if $dbh->err; + } + $rec->($cl->{'lncode'}, $rec); + } + }; + $rec->("en", $rec); + $out->("-", "done."); +} + +sub copyfaq +{ + my $faqd = LJ::Lang::get_dom("faq"); + my $ll = LJ::Lang::get_root_lang($faqd); + unless ($ll) { return; } + + my $domid = $faqd->{'dmid'}; + + $out->("Copying FAQ...", '+'); + + my %existing; + $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l ". + "WHERE l.lnid=$ll->{'lnid'} AND l.dmid=$domid AND l.itid=i.itid AND i.dmid=$domid"); + $sth->execute; + $existing{$_} = 1 while $_ = $sth->fetchrow_array; + + # faq category + $sth = $dbh->prepare("SELECT faqcat, faqcatname FROM faqcat"); + $sth->execute; + while (my ($cat, $name) = $sth->fetchrow_array) { + next if exists $existing{"cat.$cat"}; + my $opts = { 'childrenlatest' => 1 }; + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "cat.$cat", $name, $opts); + } + + # faq items + $sth = $dbh->prepare("SELECT faqid, question, answer FROM faq"); + $sth->execute; + while (my ($faqid, $q, $a) = $sth->fetchrow_array) { + next if + exists $existing{"$faqid.1question"} and + exists $existing{"$faqid.2answer"}; + my $opts = { 'childrenlatest' => 1 }; + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.1question", $q, $opts); + LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.2answer", $a, $opts); + } + + $out->('-', "done."); +} + +sub wipedb +{ + $out->("Wiping DB...", '+'); + foreach (qw(domains items langdomains langs latest text)) { + $out->("deleting from $_"); + $dbh->do("DELETE FROM ml_$_"); + } + $out->("-", "done."); +} + +sub wipecrumbs +{ + $out->('Wiping DB of all crumbs...', '+'); + + # step 1: get all items that are crumbs. [from ml_items] + my $genid = $dom_code{'general'}->{'dmid'}; + my @crumbs; + my $sth = $dbh->prepare("SELECT itcode FROM ml_items + WHERE dmid = $genid AND itcode LIKE 'crumb.\%'"); + $sth->execute; + while (my ($itcode) = $sth->fetchrow_array) { + # push onto list + push @crumbs, $itcode; + } + + # step 2: remove the items that have these unique dmid/itids + foreach my $code (@crumbs) { + $out->("deleting $code"); + remove("general", $code); + } + + # done + $out->('-', 'done.'); +} + +sub loadcrumbs +{ + $out->('Loading all crumbs into DB...', '+'); + + # get domain id of 'general' and language id of 'en' + my $genid = $dom_code{'general'}->{'dmid'}; + my $loclang = $LJ::LANGS[0] || 'en'; + + # list of crumbs + my @crumbs; + foreach (keys %LJ::CRUMBS_LOCAL) { push @crumbs, $_; } + foreach (keys %LJ::CRUMBS) { push @crumbs, $_; } + + # begin iterating, order doesn't matter... + foreach my $crumbkey (@crumbs) { + $out->("inserting crumb.$crumbkey"); + my $crumb = LJ::get_crumb($crumbkey); + my $local = $LJ::CRUMBS_LOCAL{$crumbkey} ? 1 : 0; + + # see if it exists + my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items + WHERE dmid = $genid AND itcode = 'crumb.$crumbkey'")+0; + LJ::Lang::set_text($genid, $local ? $loclang : 'en', "crumb.$crumbkey", $crumb->[0]) + unless $itid; + } + + # done + $out->('-', 'done.'); +} + +sub popstruct +{ + $out->("Populating structure...", '+'); + foreach my $l (values %lang_id) { + $out->("Inserting language: $l->{'lnname'}"); + $dbh->do("INSERT INTO ml_langs (lnid, lncode, lnname, parenttype, parentlnid) ". + "VALUES (" . join(",", map { $dbh->quote($l->{$_}) } qw(lnid lncode lnname parenttype parentlnid)) . ")"); + } + + foreach my $d (values %dom_id) { + $out->("Inserting domain: $d->{'type'}\[$d->{'args'}\]"); + $dbh->do("INSERT INTO ml_domains (dmid, type, args) ". + "VALUES (" . join(",", map { $dbh->quote($d->{$_}) } qw(dmid type args)) . ")"); + } + + $out->("Inserting language domains ..."); + foreach my $ld (@lang_domains) { + $dbh->do("INSERT IGNORE INTO ml_langdomains (lnid, dmid, dmmaster) VALUES ". + "(" . join(",", map { $dbh->quote($ld->{$_}) } qw(lnid dmid dmmaster)) . ")"); + } + $out->("-", "done."); +} + +sub poptext +{ + my @langs = @_; + push @langs, (keys %lang_code) unless @langs; + + $out->("Populating text...", '+'); + my %source; # lang -> file, or "[extra]" when given by --extra= argument + if ($opt_extra) { + $source{'[extra]'} = $opt_extra; + } else { + foreach my $lang (@langs) { + my $file = "$ENV{'LJHOME'}/bin/upgrading/${lang}.dat"; + next if $opt_only && $lang ne $opt_only; + next unless -e $file; + $source{$lang} = $file; + } + } + + my %existing_item; # langid -> code -> 1 + + foreach my $source (keys %source) + { + $out->("$source", '+'); + my $file = $source{$source}; + open (D, $file) + or $out->('x', "Can't open $source data file"); + + # fixed language in *.dat files, but in extra files + # it switches as it goes. + my $l; + if ($source ne "[extra]") { $l = $lang_code{$source}; } + + my $bml_prefix = ""; + + my $addcount = 0; + my $lnum = 0; + my ($code, $text); + my %metadata; + while (my $line = ) { + $lnum++; + my $del; + my $action_line; + + if ($line =~ /^==(LANG|BML):\s*(\S+)/) { + $out->('x', "Bogus directives in non-extra file.") + if $source ne "[extra]"; + my ($what, $val) = ($1, $2); + if ($what eq "LANG") { + $l = $lang_code{$val}; + $out->('x', 'Bogus ==LANG switch to: $what') unless $l; + $bml_prefix = ""; + } elsif ($what eq "BML") { + $out->('x', 'Bogus ==BML switch to: $what') + unless $val =~ m!^/.+\.bml$!; + $bml_prefix = $val; + } + } elsif ($line =~ /^(\S+?)=(.*)/) { + ($code, $text) = ($1, $2); + $action_line = 1; + } elsif ($line =~ /^\!\s*(\S+)/) { + $del = $code; + $action_line = 1; + } elsif ($line =~ /^(\S+?)\<\<\s*$/) { + ($code, $text) = ($1, ""); + while () { + $lnum++; + last if $_ eq ".\n"; + s/^\.//; + $text .= $_; + } + chomp $text; # remove file new-line (we added it) + $action_line = 1; + } elsif ($line =~ /^[\#\;]/) { + # comment line + next; + } elsif ($line =~ /\S/) { + $out->('x', "$source:$lnum: Bogus format."); + } + + if ($code =~ m!^\.!) { + $out->('x', "Can't use code with leading dot: $code") + unless $bml_prefix; + $code = "$bml_prefix$code"; + } + + if ($code =~ /\|(.+)/) { + $metadata{$1} = $text; + next; + } + + next unless $action_line; + + $out->('x', 'No language defined!') unless $l; + + # load existing items for target language + unless (exists $existing_item{$l->{'lnid'}}) { + $existing_item{$l->{'lnid'}} = {}; + my $sth = $dbh->prepare(qq{ + SELECT i.itcode + FROM ml_latest l, ml_items i + WHERE i.dmid=1 AND l.dmid=1 AND i.itid=l.itid AND l.lnid=$l->{'lnid'} + }); + $sth->execute; + $existing_item{$l->{'lnid'}}->{$_} = 1 + while $_ = $sth->fetchrow_array; + } + + # do deletes + if (defined $del) { + remove("general", $del) + if delete $existing_item{$l->{'lnid'}}->{$del}; + next; + } + + # if override is set (development option) then delete + if ($opt_override && $existing_item{$l->{'lnid'}}->{$code}) { + remove("general", $code); + delete $existing_item{$l->{'lnid'}}->{$code}; + } + + unless ($existing_item{$l->{'lnid'}}->{$code}) { + $addcount++; + my $staleness = $metadata{'staleness'}+0; + my $res = LJ::Lang::set_text($dbh, 1, $l->{'lncode'}, $code, $text, + { 'staleness' => $staleness, + 'notes' => $metadata{'notes'}, }); + $out->("set: $code") if $opt_verbose; + unless ($res) { + $out->('x', "ERROR: " . LJ::Lang::last_error()); + } + } + %metadata = (); + } + close D; + $out->("added: $addcount", '-'); + } + $out->("-", "done."); + + # dead phrase removal + $out->("Removing dead phrases...", '+'); + foreach my $file ("deadphrases.dat", "deadphrases-local.dat") { + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + next unless -s $ffile; + $out->("File: $file"); + open (DP, $ffile) or die; + while (my $li = ) { + $li =~ s/\#.*//; + next unless $li =~ /\S/; + $li =~ s/\s+$//; + my ($dom, $it) = split(/\s+/, $li); + next unless exists $dom_code{$dom}; + my $dmid = $dom_code{$dom}->{'dmid'}; + + my @items; + if ($it =~ s/\*$/\%/) { + my $sth = $dbh->prepare("SELECT itcode FROM ml_items WHERE dmid=? AND itcode LIKE ?"); + $sth->execute($dmid, $it); + push @items, $_ while $_ = $sth->fetchrow_array; + } else { + @items = ($it); + } + foreach (@items) { + remove($dom, $_, 1); + } + } + close DP; + } + $out->('-', "Done."); +} + +sub dumptext +{ + my @langs = @_; + unless (@langs) { @langs = keys %lang_code; } + + $out->('Dumping text...', '+'); + foreach my $lang (@langs) + { + $out->("$lang"); + my $l = $lang_code{$lang}; + open (D, ">$ENV{'LJHOME'}/bin/upgrading/${lang}.dat") + or $out->('x', "Can't open $lang.dat"); + print D ";; -*- coding: utf-8 -*-\n"; + my $sth = $dbh->prepare("SELECT i.itcode, t.text, l.staleness, i.notes FROM ". + "ml_items i, ml_latest l, ml_text t ". + "WHERE l.lnid=$l->{'lnid'} AND l.dmid=1 ". + "AND i.dmid=1 AND l.itid=i.itid AND ". + "t.dmid=1 AND t.txtid=l.txtid AND ". + # only export mappings that aren't inherited: + "t.lnid=$l->{'lnid'} ". + "ORDER BY i.itcode"); + $sth->execute; + die $dbh->errstr if $dbh->err; + my $writeline = sub { + my ($k, $v) = @_; + if ($v =~ /\n/) { + $v =~ s/\n\./\n\.\./g; + print D "$k<<\n$v\n.\n"; + } else { + print D "$k=$v\n"; + } + }; + while (my ($itcode, $text, $staleness, $notes) = $sth->fetchrow_array) { + $writeline->("$itcode|staleness", $staleness) + if $staleness; + $writeline->("$itcode|notes", $notes) + if $notes =~ /\S/; + $writeline->($itcode, $text); + print D "\n"; + } + close D; + } + $out->('-', 'done.'); +} + +sub newitems +{ + $out->("Searching for referenced text codes...", '+'); + my $top = $ENV{'LJHOME'}; + my @files; + push @files, qw(htdocs cgi-bin bin); + my %items; # $scope -> $key -> 1; + while (@files) + { + my $file = shift @files; + my $ffile = "$top/$file"; + next unless -e $ffile; + if (-d $ffile) { + $out->("dir: $file"); + opendir (MD, $ffile) or die "Can't open $file"; + while (my $f = readdir(MD)) { + next if $f eq "." || $f eq ".." || + $f =~ /^\.\#/ || $f =~ /(\.png|\.gif|~|\#)$/; + unshift @files, "$file/$f"; + } + closedir MD; + } + if (-f $ffile) { + my $scope = "local"; + $scope = "general" if -e "$top/cvs/livejournal/$file"; + + open (F, $ffile) or die "Can't open $file"; + my $line = 0; + while () { + $line++; + while (/BML::ml\([\"\'](.+?)[\"\']/g) { + $items{$scope}->{$1} = 1; + } + while (/\(=_ML\s+(.+?)\s+_ML=\)/g) { + my $code = $1; + if ($code =~ /^\./ && $file =~ m!^htdocs/!) { + $code = "$file$code"; + $code =~ s!^htdocs!!; + } + $items{$scope}->{$code} = 1; + } + } + close F; + } + } + + $out->(sprintf("%d general and %d local found.", + scalar keys %{$items{'general'}}, + scalar keys %{$items{'local'}})); + + # [ General ] + my %e_general; # code -> 1 + $out->("Checking which general items already exist in database..."); + my $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ". + "l.dmid=1 AND l.lnid=1 AND i.dmid=1 AND i.itid=l.itid "); + $sth->execute; + while (my $it = $sth->fetchrow_array) { $e_general{$it} = 1; } + $out->(sprintf("%d found", scalar keys %e_general)); + foreach my $it (keys %{$items{'general'}}) { + next if exists $e_general{$it}; + my $res = LJ::Lang::set_text($dbh, 1, "en", $it, undef, { 'staleness' => 4 }); + $out->("Adding general: $it ... $res"); + } + + if ($opt_local_lang) { + my $ll = $lang_code{$opt_local_lang}; + die "Bogus --local-lang argument\n" unless $ll; + die "Local-lang '$ll->{'lncode'}' parent isn't 'en'\n" + unless $ll->{'parentlnid'} == 1; + $out->("Checking which local items already exist in database..."); + + my %e_local; + $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ". + "l.dmid=1 AND l.lnid=$ll->{'lnid'} AND i.dmid=1 AND i.itid=l.itid "); + $sth->execute; + while (my $it = $sth->fetchrow_array) { $e_local{$it} = 1; } + $out->(sprintf("%d found\n", scalar keys %e_local)); + foreach my $it (keys %{$items{'local'}}) { + next if exists $e_general{$it}; + next if exists $e_local{$it}; + my $res = LJ::Lang::set_text($dbh, 1, $ll->{'lncode'}, $it, undef, { 'staleness' => 4 }); + $out->("Adding local: $it ... $res"); + } + } + $out->('-', 'done.'); +} + +sub remove { + my ($dmcode, $itcode, $no_error) = @_; + my $dmid; + if (exists $dom_code{$dmcode}) { + $dmid = $dom_code{$dmcode}->{'dmid'}; + } else { + $out->("x", "Unknown domain code $dmcode."); + } + + my $qcode = $dbh->quote($itcode); + my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items WHERE dmid=$dmid AND itcode=$qcode"); + return if $no_error && !$itid; + $out->("x", "Unknown item code $itcode.") unless $itid; + + $out->("Removing item $itcode from domain $dmcode ($itid)...", "+"); + + # need to delete everything from: ml_items ml_latest ml_text + + $dbh->do("DELETE FROM ml_items WHERE dmid=$dmid AND itid=$itid"); + + my $txtids = ""; + my $sth = $dbh->prepare("SELECT txtid FROM ml_latest WHERE dmid=$dmid AND itid=$itid"); + $sth->execute; + while (my $txtid = $sth->fetchrow_array) { + $txtids .= "," if $txtids; + $txtids .= $txtid; + } + $dbh->do("DELETE FROM ml_latest WHERE dmid=$dmid AND itid=$itid"); + $dbh->do("DELETE FROM ml_text WHERE dmid=$dmid AND txtid IN ($txtids)"); + + $out->("-","done."); +} + + + diff --git a/livejournal/bin/upgrading/truncate_cluster.pl b/livejournal/bin/upgrading/truncate_cluster.pl new file mode 100755 index 0000000..b185102 --- /dev/null +++ b/livejournal/bin/upgrading/truncate_cluster.pl @@ -0,0 +1,32 @@ +#!/usr/bin/perl + +use strict; + +my $clusterid = shift; +die "Usage: truncate_cluster.pl \n" + unless $clusterid; + +# load libraries now +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +# force this option on, since that's the point of the tool +$LJ::COMPRESS_TEXT = 1; + +my $master = LJ::get_db_writer(); +my $ct = $master->selectrow_array("SELECT COUNT(*) FROM user WHERE clusterid=?", + undef, $clusterid); +if ($ct) { + die "There are still $ct users on cluster $clusterid\n"; +} + +my $db = LJ::get_cluster_master($clusterid); +die "Invalid/down cluster: $clusterid\n" unless $db; + +my $sth = $db->prepare("SHOW TABLES"); +$sth->execute; + +while (my $table = $sth->fetchrow_array) { + next if $table eq "useridmap"; + print " truncating $table\n"; + $db->do("TRUNCATE TABLE $table"); +} diff --git a/livejournal/bin/upgrading/update-db-general.pl b/livejournal/bin/upgrading/update-db-general.pl new file mode 100755 index 0000000..84e6393 --- /dev/null +++ b/livejournal/bin/upgrading/update-db-general.pl @@ -0,0 +1,2578 @@ +# +# database schema & data info +# + +mark_clustered(@LJ::USER_TABLES); + +register_tablecreate("adopt", <<'EOC'); +CREATE TABLE adopt ( + adoptid int(10) unsigned NOT NULL auto_increment, + helperid int(10) unsigned NOT NULL default '0', + newbieid int(10) unsigned NOT NULL default '0', + changetime datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (adoptid), + KEY (helperid), + KEY (newbieid) +) +EOC + +register_tablecreate("adoptlast", <<'EOC'); +CREATE TABLE adoptlast ( + userid int(10) unsigned NOT NULL default '0', + lastassigned datetime NOT NULL default '0000-00-00 00:00:00', + lastadopted datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("authactions", <<'EOC'); +CREATE TABLE authactions ( + aaid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + datecreate datetime NOT NULL default '0000-00-00 00:00:00', + authcode varchar(20) default NULL, + action varchar(50) default NULL, + arg1 varchar(255) default NULL, + PRIMARY KEY (aaid) +) +EOC + +register_tablecreate("clients", <<'EOC'); +CREATE TABLE clients ( + clientid smallint(5) unsigned NOT NULL auto_increment, + client varchar(40) default NULL, + PRIMARY KEY (clientid), + KEY (client) +) +EOC + +post_create("clients", + "sqltry" => "INSERT INTO clients (client) SELECT DISTINCT client FROM logins", + ); + +register_tablecreate("clientusage", <<'EOC'); +CREATE TABLE clientusage ( + userid int(10) unsigned NOT NULL default '0', + clientid smallint(5) unsigned NOT NULL default '0', + lastlogin datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (clientid,userid), + UNIQUE KEY userid (userid,clientid) +) +EOC + +post_create("clientusage", + "sqltry" => "INSERT INTO clientusage SELECT u.userid, c.clientid, l.lastlogin FROM user u, clients c, logins l WHERE u.user=l.user AND l.client=c.client", + ); + +register_tablecreate("codes", <<'EOC'); +CREATE TABLE codes ( + type varchar(10) NOT NULL default '', + code varchar(7) NOT NULL default '', + item varchar(80) default NULL, + sortorder smallint(6) NOT NULL default '0', + PRIMARY KEY (type,code) +) PACK_KEYS=1 +EOC + +register_tablecreate("community", <<'EOC'); +CREATE TABLE community ( + userid int(10) unsigned NOT NULL default '0', + ownerid int(10) unsigned NOT NULL default '0', + membership enum('open','closed') NOT NULL default 'open', + postlevel enum('members','select','screened') default NULL, + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("dirsearchres2", <<'EOC'); +CREATE TABLE dirsearchres2 ( + qdigest varchar(32) NOT NULL default '', + dateins datetime NOT NULL default '0000-00-00 00:00:00', + userids blob, + PRIMARY KEY (qdigest), + KEY (dateins) +) +EOC + +register_tablecreate("duplock", <<'EOC'); +CREATE TABLE duplock ( + realm enum('support','log','comment') NOT NULL default 'support', + reid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + digest char(32) NOT NULL default '', + dupid int(10) unsigned NOT NULL default '0', + instime datetime NOT NULL default '0000-00-00 00:00:00', + KEY (realm,reid,userid) +) +EOC + +register_tablecreate("faq", <<'EOC'); +CREATE TABLE faq ( + faqid mediumint(8) unsigned NOT NULL auto_increment, + question text, + answer text, + sortorder int(11) default NULL, + faqcat varchar(20) default NULL, + lastmodtime datetime default NULL, + lastmoduserid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (faqid) +) +EOC + +register_tablecreate("faqcat", <<'EOC'); +CREATE TABLE faqcat ( + faqcat varchar(20) NOT NULL default '', + faqcatname varchar(100) default NULL, + catorder int(11) default '50', + PRIMARY KEY (faqcat) +) +EOC + +register_tablecreate("faquses", <<'EOC'); +CREATE TABLE faquses ( + faqid MEDIUMINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + dateview DATETIME NOT NULL, + PRIMARY KEY (userid, faqid), + KEY (faqid), + KEY (dateview) +) +EOC + +register_tablecreate("friendgroup", <<'EOC'); +CREATE TABLE friendgroup ( + userid int(10) unsigned NOT NULL default '0', + groupnum tinyint(3) unsigned NOT NULL default '0', + groupname varchar(30) NOT NULL default '', + sortorder tinyint(3) unsigned NOT NULL default '50', + is_public enum('0','1') NOT NULL default '0', + PRIMARY KEY (userid,groupnum) +) +EOC + +register_tablecreate("friends", <<'EOC'); +CREATE TABLE friends ( + userid int(10) unsigned NOT NULL default '0', + friendid int(10) unsigned NOT NULL default '0', + fgcolor char(7) default NULL, + bgcolor char(7) default NULL, + groupmask int(10) unsigned NOT NULL default '1', + showbydefault enum('1','0') NOT NULL default '1', + PRIMARY KEY (userid,friendid), + KEY (friendid) +) +EOC + +register_tablecreate("interests", <<'EOC'); +CREATE TABLE interests ( + intid int(10) unsigned NOT NULL auto_increment, + interest varchar(255) NOT NULL default '', + intcount mediumint(8) unsigned default NULL, + PRIMARY KEY (intid), + UNIQUE interest (interest) +) +EOC + +register_tablecreate("keywords", <<'EOC'); +CREATE TABLE keywords ( + kwid int(10) unsigned NOT NULL auto_increment, + keyword varchar(80) binary NOT NULL default '', + PRIMARY KEY (kwid), + UNIQUE KEY kwidx (keyword) +) +EOC + +register_tablecreate("logproplist", <<'EOC'); +CREATE TABLE logproplist ( + propid tinyint(3) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + prettyname varchar(60) default NULL, + sortorder mediumint(8) unsigned default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (propid), + UNIQUE KEY name (name) +) +EOC + +register_tablecreate("memkeyword", <<'EOC'); +CREATE TABLE memkeyword ( + memid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (memid,kwid) +) +EOC + +register_tablecreate("memorable", <<'EOC'); +CREATE TABLE memorable ( + memid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + itemid int(10) unsigned NOT NULL default '0', + des varchar(60) default NULL, + security enum('public','friends','private') NOT NULL default 'public', + PRIMARY KEY (memid), + UNIQUE KEY userid (userid,itemid), + KEY (itemid) +) +EOC + +register_tablecreate("moods", <<'EOC'); +CREATE TABLE moods ( + moodid int(10) unsigned NOT NULL auto_increment, + mood varchar(40) default NULL, + parentmood int(10) unsigned NOT NULL default '0', + PRIMARY KEY (moodid), + UNIQUE KEY mood (mood) +) +EOC + +register_tablecreate("moodthemedata", <<'EOC'); +CREATE TABLE moodthemedata ( + moodthemeid int(10) unsigned NOT NULL default '0', + moodid int(10) unsigned NOT NULL default '0', + picurl varchar(100) default NULL, + width tinyint(3) unsigned NOT NULL default '0', + height tinyint(3) unsigned NOT NULL default '0', + KEY (moodthemeid), + PRIMARY KEY (moodthemeid,moodid) +) +EOC + +register_tablecreate("moodthemes", <<'EOC'); +CREATE TABLE moodthemes ( + moodthemeid int(10) unsigned NOT NULL auto_increment, + ownerid int(10) unsigned NOT NULL default '0', + name varchar(50) default NULL, + des varchar(100) default NULL, + is_public enum('Y','N') NOT NULL default 'N', + PRIMARY KEY (moodthemeid), + KEY (is_public), + KEY (ownerid) +) +EOC + +register_tablecreate("news_sent", <<'EOC'); +CREATE TABLE news_sent ( + newsid int(10) unsigned NOT NULL auto_increment, + newsnum mediumint(8) unsigned NOT NULL default '0', + user varchar(15) NOT NULL default '', + datesent datetime default NULL, + email varchar(100) NOT NULL default '', + PRIMARY KEY (newsid), + KEY (newsnum), + KEY (user), + KEY (email) +) +EOC + +register_tablecreate("noderefs", <<'EOC'); +CREATE TABLE noderefs ( + nodetype char(1) NOT NULL default '', + nodeid int(10) unsigned NOT NULL default '0', + urlmd5 varchar(32) NOT NULL default '', + url varchar(120) NOT NULL default '', + PRIMARY KEY (nodetype,nodeid,urlmd5) +) +EOC + +register_tablecreate("overrides", <<'EOC'); # global, old +CREATE TABLE overrides ( + user varchar(15) NOT NULL default '', + override text, + PRIMARY KEY (user) +) +EOC + +register_tablecreate("pendcomments", <<'EOC'); +CREATE TABLE pendcomments ( + jid int(10) unsigned NOT NULL, + pendcid int(10) unsigned NOT NULL, + data blob NOT NULL, + datesubmit int(10) unsigned NOT NULL, + PRIMARY KEY (pendcid, jid), + KEY (datesubmit) +) +EOC + +register_tablecreate("poll", <<'EOC'); +CREATE TABLE poll ( + pollid int(10) unsigned NOT NULL auto_increment, + itemid int(10) unsigned NOT NULL default '0', + journalid int(10) unsigned NOT NULL default '0', + posterid int(10) unsigned NOT NULL default '0', + whovote enum('all','friends') NOT NULL default 'all', + whoview enum('all','friends','none') NOT NULL default 'all', + name varchar(255) default NULL, + PRIMARY KEY (pollid), + KEY (itemid), + KEY (journalid), + KEY (posterid) +) +EOC + +register_tablecreate("pollitem", <<'EOC'); +CREATE TABLE pollitem ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + pollitid tinyint(3) unsigned NOT NULL default '0', + sortorder tinyint(3) unsigned NOT NULL default '0', + item varchar(255) default NULL, + PRIMARY KEY (pollid,pollqid,pollitid) +) +EOC + +register_tablecreate("pollquestion", <<'EOC'); +CREATE TABLE pollquestion ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + sortorder tinyint(3) unsigned NOT NULL default '0', + type enum('check','radio','drop','text','scale') default NULL, + opts varchar(20) default NULL, + qtext text, + PRIMARY KEY (pollid,pollqid) +) +EOC + +register_tablecreate("pollresult", <<'EOC'); +CREATE TABLE pollresult ( + pollid int(10) unsigned NOT NULL default '0', + pollqid tinyint(3) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (pollid,pollqid,userid), + KEY (pollid,userid) +) +EOC + +register_tablecreate("pollsubmission", <<'EOC'); +CREATE TABLE pollsubmission ( + pollid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + datesubmit datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (pollid,userid), + KEY (userid) +) +EOC + +register_tablecreate("priv_list", <<'EOC'); +CREATE TABLE priv_list ( + prlid smallint(5) unsigned NOT NULL auto_increment, + privcode varchar(20) NOT NULL default '', + privname varchar(40) default NULL, + des varchar(255) default NULL, + is_public ENUM('1', '0') DEFAULT '1' NOT NULL, + PRIMARY KEY (prlid), + UNIQUE KEY privcode (privcode) +) +EOC + +register_tablecreate("priv_map", <<'EOC'); +CREATE TABLE priv_map ( + prmid mediumint(8) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + prlid smallint(5) unsigned NOT NULL default '0', + arg varchar(40) default NULL, + PRIMARY KEY (prmid), + KEY (userid), + KEY (prlid) +) +EOC + +register_tablecreate("cmdbuffer", <<'EOC'); +CREATE TABLE cmdbuffer ( + cbid INT UNSIGNED NOT NULL AUTO_INCREMENT, + journalid INT UNSIGNED NOT NULL, + cmd VARCHAR(30) NOT NULL default '', + instime datetime NOT NULL default '0000-00-00 00:00:00', + args TEXT NOT NULL, + PRIMARY KEY (cbid), + KEY (cmd), + KEY (journalid) +) +EOC + +register_tablecreate("randomuserset", <<'EOC'); +CREATE TABLE randomuserset ( + rid INT UNSIGNED NOT NULL AUTO_INCREMENT, + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (rid) +) +EOC + +register_tablecreate("schemacols", <<'EOC'); +CREATE TABLE schemacols ( + tablename varchar(40) NOT NULL default '', + colname varchar(40) NOT NULL default '', + des varchar(255) default NULL, + PRIMARY KEY (tablename,colname) +) +EOC + +register_tablecreate("schematables", <<'EOC'); +CREATE TABLE schematables ( + tablename varchar(40) NOT NULL default '', + public_browsable enum('0','1') NOT NULL default '0', + redist_mode enum('off','insert','replace') NOT NULL default 'off', + des text, + PRIMARY KEY (tablename) +) +EOC + +register_tablecreate("stats", <<'EOC'); +CREATE TABLE stats ( + statcat varchar(30) NOT NULL, + statkey varchar(150) NOT NULL, + statval int(10) unsigned NOT NULL, + UNIQUE KEY statcat_2 (statcat,statkey) +) +EOC + +register_tablecreate("blobcache", <<'EOC'); +CREATE TABLE blobcache ( + bckey VARCHAR(40) NOT NULL, + PRIMARY KEY (bckey), + dateupdate DATETIME, + value MEDIUMBLOB +) +EOC + +register_tablecreate("style", <<'EOC'); +CREATE TABLE style ( + styleid int(11) NOT NULL auto_increment, + user varchar(15) NOT NULL default '', + styledes varchar(50) default NULL, + type varchar(10) NOT NULL default '', + formatdata text, + is_public enum('Y','N') NOT NULL default 'N', + is_embedded enum('Y','N') NOT NULL default 'N', + is_colorfree enum('Y','N') NOT NULL default 'N', + opt_cache enum('Y','N') NOT NULL default 'N', + has_ads enum('Y','N') NOT NULL default 'N', + lastupdate datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (styleid), + KEY (user), + KEY (type) +) PACK_KEYS=1 +EOC + +# cache Storable-frozen pre-cleaned style variables +register_tablecreate("s1stylecache", <<'EOC'); # clustered +CREATE TABLE s1stylecache ( + styleid INT UNSIGNED NOT NULL PRIMARY KEY, + cleandate DATETIME, + type VARCHAR(10) NOT NULL DEFAULT '', + opt_cache ENUM('Y','N') NOT NULL DEFAULT 'N', + vars_stor BLOB, + vars_cleanver SMALLINT UNSIGNED NOT NULL +) +EOC + +# caches Storable-frozen pre-cleaned overrides & colors +register_tablecreate("s1usercache", <<'EOC'); # clustered +CREATE TABLE s1usercache ( + userid INT UNSIGNED NOT NULL PRIMARY KEY, + override_stor BLOB, + override_cleanver SMALLINT UNSIGNED NOT NULL, + color_stor BLOB +) +EOC + +register_tablecreate("support", <<'EOC'); +CREATE TABLE support ( + spid int(10) unsigned NOT NULL auto_increment, + reqtype enum('user','email') default NULL, + requserid int(10) unsigned NOT NULL default '0', + reqname varchar(50) default NULL, + reqemail varchar(70) default NULL, + state enum('open','closed') default NULL, + authcode varchar(15) NOT NULL default '', + spcatid int(10) unsigned NOT NULL default '0', + subject varchar(80) default NULL, + timecreate int(10) unsigned default NULL, + timetouched int(10) unsigned default NULL, + timeclosed int(10) unsigned default NULL, + PRIMARY KEY (spid), + INDEX (state), + INDEX (requserid), + INDEX (reqemail) +) +EOC + +register_tablecreate("supportcat", <<'EOC'); +CREATE TABLE supportcat ( + spcatid int(10) unsigned NOT NULL auto_increment, + catname varchar(80) default NULL, + sortorder mediumint(8) unsigned NOT NULL default '0', + basepoints tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (spcatid) +) +EOC + +register_tablecreate("supportlog", <<'EOC'); +CREATE TABLE supportlog ( + splid int(10) unsigned NOT NULL auto_increment, + spid int(10) unsigned NOT NULL default '0', + timelogged int(10) unsigned NOT NULL default '0', + type enum('req','custom','faqref') default NULL, + faqid mediumint(8) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + message text, + PRIMARY KEY (splid), + KEY (spid) +) +EOC + +register_tablecreate("supportnotify", <<'EOC'); +CREATE TABLE supportnotify ( + spcatid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + level enum('all','new') default NULL, + KEY (spcatid), + KEY (userid), + PRIMARY KEY (spcatid,userid) +) +EOC + +register_tablecreate("supportpoints", <<'EOC'); +CREATE TABLE supportpoints ( + spid int(10) unsigned NOT NULL default '0', + userid int(10) unsigned NOT NULL default '0', + points tinyint(3) unsigned default NULL, + KEY (spid), + KEY (userid) +) +EOC + +register_tablecreate("supportpointsum", <<'EOC'); +CREATE TABLE supportpointsum ( + userid INT UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid), + totpoints MEDIUMINT UNSIGNED DEFAULT 0, + lastupdate INT UNSIGNED NOT NULL, + INDEX (totpoints, lastupdate), + INDEX (lastupdate) +) +EOC + +post_create("supportpointsum", + "sqltry" => "INSERT IGNORE INTO supportpointsum (userid, totpoints, lastupdate) " . + "SELECT userid, SUM(points), 0 FROM supportpoints GROUP BY userid", + ); + + +register_tablecreate("talkproplist", <<'EOC'); +CREATE TABLE talkproplist ( + tpropid smallint(5) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + prettyname varchar(60) default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (tpropid), + UNIQUE KEY name (name) +) +EOC + +register_tablecreate("themedata", <<'EOC'); +CREATE TABLE themedata ( + themeid mediumint(8) unsigned NOT NULL default '0', + coltype varchar(30) default NULL, + color varchar(30) default NULL, + KEY (themeid) +) PACK_KEYS=1 +EOC + +register_tablecreate("themelist", <<'EOC'); +CREATE TABLE themelist ( + themeid mediumint(8) unsigned NOT NULL auto_increment, + name varchar(50) NOT NULL default '', + PRIMARY KEY (themeid) +) +EOC + +register_tablecreate("todo", <<'EOC'); +CREATE TABLE todo ( + todoid int(10) unsigned NOT NULL auto_increment, + journalid int(10) unsigned NOT NULL default '0', + posterid int(10) unsigned NOT NULL default '0', + ownerid int(10) unsigned NOT NULL default '0', + statusline varchar(40) default NULL, + security enum('public','private','friends') NOT NULL default 'public', + subject varchar(100) default NULL, + des varchar(255) default NULL, + priority enum('1','2','3','4','5') NOT NULL default '3', + datecreate datetime NOT NULL default '0000-00-00 00:00:00', + dateupdate datetime default NULL, + datedue datetime default NULL, + dateclosed datetime default NULL, + progress tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (todoid), + KEY (journalid), + KEY (posterid), + KEY (ownerid) +) +EOC + +register_tablecreate("tododep", <<'EOC'); +CREATE TABLE tododep ( + todoid int(10) unsigned NOT NULL default '0', + depid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (todoid,depid), + KEY (depid) +) +EOC + +register_tablecreate("todokeyword", <<'EOC'); +CREATE TABLE todokeyword ( + todoid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (todoid,kwid) +) +EOC + +register_tablecreate("txtmsg", <<'EOC'); +CREATE TABLE txtmsg ( + userid int(10) unsigned NOT NULL default '0', + provider varchar(25) default NULL, + number varchar(60) default NULL, + security enum('all','reg','friends') NOT NULL default 'all', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("user", <<'EOC'); +CREATE TABLE user ( + userid int(10) unsigned NOT NULL auto_increment, + user char(15) default NULL, + caps SMALLINT UNSIGNED NOT NULL DEFAULT 0, + email char(50) default NULL, + password char(30) default NULL, + status char(1) NOT NULL default 'N', + statusvis char(1) NOT NULL default 'V', + statusvisdate datetime default NULL, + name char(50) default NULL, + bdate date default NULL, + themeid int(11) NOT NULL default '1', + moodthemeid int(10) unsigned NOT NULL default '1', + opt_forcemoodtheme enum('Y','N') NOT NULL default 'N', + allow_infoshow char(1) NOT NULL default 'Y', + allow_contactshow char(1) NOT NULL default 'Y', + allow_getljnews char(1) NOT NULL default 'N', + opt_showtalklinks char(1) NOT NULL default 'Y', + opt_whocanreply enum('all','reg','friends') NOT NULL default 'all', + opt_gettalkemail char(1) NOT NULL default 'Y', + opt_htmlemail enum('Y','N') NOT NULL default 'Y', + opt_mangleemail char(1) NOT NULL default 'N', + useoverrides char(1) NOT NULL default 'N', + defaultpicid int(10) unsigned default NULL, + has_bio enum('Y','N') NOT NULL default 'N', + txtmsg_status enum('none','on','off') NOT NULL default 'none', + is_system enum('Y','N') NOT NULL default 'N', + journaltype char(1) NOT NULL default 'P', + lang char(2) NOT NULL default 'EN', + PRIMARY KEY (userid), + UNIQUE KEY user (user), + KEY (email), + KEY (status), + KEY (statusvis) +) PACK_KEYS=1 +EOC + +register_tablecreate("userbio", <<'EOC'); +CREATE TABLE userbio ( + userid int(10) unsigned NOT NULL default '0', + bio text, + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("userinterests", <<'EOC'); +CREATE TABLE userinterests ( + userid int(10) unsigned NOT NULL default '0', + intid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,intid), + KEY (intid) +) +EOC + +register_tablecreate("userpic", <<'EOC'); +CREATE TABLE userpic ( + picid int(10) unsigned NOT NULL auto_increment, + userid int(10) unsigned NOT NULL default '0', + contenttype char(25) default NULL, + width smallint(6) NOT NULL default '0', + height smallint(6) NOT NULL default '0', + state char(1) NOT NULL default 'N', + picdate datetime default NULL, + md5base64 char(22) NOT NULL default '', + PRIMARY KEY (picid), + KEY (userid), + KEY (state) +) +EOC + +register_tablecreate("userpicblob2", <<'EOC'); +CREATE TABLE userpicblob2 ( + userid int unsigned not null, + picid int unsigned not null, + imagedata blob, + PRIMARY KEY (userid, picid) +) max_rows=10000000 +EOC + +register_tablecreate("userpicmap", <<'EOC'); +CREATE TABLE userpicmap ( + userid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + picid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,kwid) +) +EOC + +register_tablecreate("userpicmap2", <<'EOC'); +CREATE TABLE userpicmap2 ( + userid int(10) unsigned NOT NULL default '0', + kwid int(10) unsigned NOT NULL default '0', + picid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid, kwid) +) +EOC + +register_tablecreate("userpic2", <<'EOC'); +CREATE TABLE userpic2 ( + picid int(10) unsigned NOT NULL, + userid int(10) unsigned NOT NULL default '0', + fmt char(1) default NULL, + width smallint(6) NOT NULL default '0', + height smallint(6) NOT NULL default '0', + state char(1) NOT NULL default 'N', + picdate datetime default NULL, + md5base64 char(22) NOT NULL default '', + comment varchar(255) BINARY NOT NULL default '', + flags tinyint(1) unsigned NOT NULL default 0, + location enum('blob','disk','mogile') default NULL, + PRIMARY KEY (userid, picid) +) +EOC + +# - blobids aren't necessarily unique between domains; +# global userpicids may collide with the counter used for the rest. +# so type must be in the key. +# - domain ids are set up in ljconfig.pl. +# - NULL length indicates the data is external-- we need another +# table for more data for that. +register_tablecreate("userblob", <<'EOC'); # clustered +CREATE TABLE userblob ( + journalid INT UNSIGNED NOT NULL, + domain TINYINT UNSIGNED NOT NULL, + blobid MEDIUMINT UNSIGNED NOT NULL, + length MEDIUMINT UNSIGNED, + PRIMARY KEY (journalid, domain, blobid), + KEY (domain) +) +EOC + +register_tablecreate("userproplist", <<'EOC'); +CREATE TABLE userproplist ( + upropid smallint(5) unsigned NOT NULL auto_increment, + name varchar(50) default NULL, + indexed enum('1','0') NOT NULL default '1', + prettyname varchar(60) default NULL, + datatype enum('char','num','bool') NOT NULL default 'char', + des varchar(255) default NULL, + PRIMARY KEY (upropid), + UNIQUE KEY name (name) +) +EOC + +# global, indexed +register_tablecreate("userprop", <<'EOC'); +CREATE TABLE userprop ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(60) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid,value) +) +EOC + +# global, not indexed +register_tablecreate("userproplite", <<'EOC'); +CREATE TABLE userproplite ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid) +) +EOC + +# clustered, not indexed +register_tablecreate("userproplite2", <<'EOC'); +CREATE TABLE userproplite2 ( + userid int(10) unsigned NOT NULL default '0', + upropid smallint(5) unsigned NOT NULL default '0', + value varchar(255) default NULL, + PRIMARY KEY (userid,upropid), + KEY (upropid) +) +EOC + +# clustered +register_tablecreate("userpropblob", <<'EOC'); +CREATE TABLE userpropblob ( + userid INT(10) unsigned NOT NULL default '0', + upropid SMALLINT(5) unsigned NOT NULL default '0', + value blob, + PRIMARY KEY (userid,upropid) +) +EOC + +register_tablecreate("backupdirty", <<'EOC'); +CREATE TABLE backupdirty ( + userid INT(10) unsigned NOT NULL default '0', + marktime INT(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("zip", <<'EOC'); +CREATE TABLE zip ( + zip varchar(5) NOT NULL default '', + state char(2) NOT NULL default '', + city varchar(100) NOT NULL default '', + PRIMARY KEY (zip), + KEY (state) +) PACK_KEYS=1 +EOC + +register_tablecreate("zips", <<'EOC'); +CREATE TABLE zips ( + FIPS char(2) default NULL, + zip varchar(5) NOT NULL default '', + State char(2) NOT NULL default '', + Name varchar(30) NOT NULL default '', + alloc float(9,7) NOT NULL default '0.0000000', + pop1990 int(11) NOT NULL default '0', + lon float(10,7) NOT NULL default '0.0000000', + lat float(10,7) NOT NULL default '0.0000000', + PRIMARY KEY (zip) +) +EOC + +################# above was a snapshot. now, changes: + +register_tablecreate("log2", <<'EOC'); +CREATE TABLE log2 ( + journalid INT UNSIGNED NOT NULL default '0', + jitemid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jitemid), + posterid int(10) unsigned NOT NULL default '0', + eventtime datetime default NULL, + logtime datetime default NULL, + compressed char(1) NOT NULL default 'N', + anum TINYINT UNSIGNED NOT NULL, + security enum('public','private','usemask') NOT NULL default 'public', + allowmask int(10) unsigned NOT NULL default '0', + replycount smallint(5) unsigned default NULL, + year smallint(6) NOT NULL default '0', + month tinyint(4) NOT NULL default '0', + day tinyint(4) NOT NULL default '0', + rlogtime int(10) unsigned NOT NULL default '0', + revttime int(10) unsigned NOT NULL default '0', + KEY (journalid,year,month,day), + KEY `rlogtime` (`journalid`,`rlogtime`), + KEY `revttime` (`journalid`,`revttime`), + KEY `posterid` (`posterid`,`journalid`) +) +EOC + +register_tablecreate("logtext2", <<'EOC'); +CREATE TABLE logtext2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + subject VARCHAR(255) DEFAULT NULL, + event TEXT, + PRIMARY KEY (journalid, jitemid) +) max_rows=100000000 +EOC + +register_tablecreate("logprop2", <<'EOC'); +CREATE TABLE logprop2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + propid TINYINT unsigned NOT NULL, + value VARCHAR(255) default NULL, + PRIMARY KEY (journalid,jitemid,propid) +) +EOC + +register_tablecreate("logsec2", <<'EOC'); +CREATE TABLE logsec2 ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + allowmask INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid,jitemid) +) +EOC + +register_tablecreate("talk2", <<'EOC'); +CREATE TABLE talk2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL DEFAULT '', + nodeid INT UNSIGNED NOT NULL default '0', + parenttalkid MEDIUMINT UNSIGNED NOT NULL, + posterid INT UNSIGNED NOT NULL default '0', + datepost DATETIME NOT NULL default '0000-00-00 00:00:00', + state CHAR(1) default 'A', + PRIMARY KEY (journalid,jtalkid), + KEY (nodetype,journalid,nodeid), + KEY (journalid,state,nodetype), + KEY (posterid) +) +EOC + +register_tablecreate("talkprop2", <<'EOC'); +CREATE TABLE talkprop2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + tpropid TINYINT UNSIGNED NOT NULL, + value VARCHAR(255) DEFAULT NULL, + PRIMARY KEY (journalid,jtalkid,tpropid) +) +EOC + +register_tablecreate("talktext2", <<'EOC'); +CREATE TABLE talktext2 ( + journalid INT UNSIGNED NOT NULL, + jtalkid MEDIUMINT UNSIGNED NOT NULL, + subject VARCHAR(100) DEFAULT NULL, + body TEXT, + PRIMARY KEY (journalid, jtalkid) +) max_rows=100000000 +EOC + +register_tablecreate("talkleft", <<'EOC'); +CREATE TABLE talkleft ( + userid INT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + INDEX (userid, posttime), + journalid INT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL, + nodeid INT UNSIGNED NOT NULL, + INDEX (journalid, nodetype, nodeid), + jtalkid MEDIUMINT UNSIGNED NOT NULL, + publicitem ENUM('1','0') NOT NULL DEFAULT '1' +) +EOC + +register_tablecreate("talkleft_xfp", <<'EOC'); +CREATE TABLE talkleft_xfp ( + userid INT UNSIGNED NOT NULL, + posttime INT UNSIGNED NOT NULL, + INDEX (userid, posttime), + journalid INT UNSIGNED NOT NULL, + nodetype CHAR(1) NOT NULL, + nodeid INT UNSIGNED NOT NULL, + INDEX (journalid, nodetype, nodeid), + jtalkid MEDIUMINT UNSIGNED NOT NULL, + publicitem ENUM('1','0') NOT NULL DEFAULT '1' +) +EOC + +register_tabledrop("ibill_codes"); +register_tabledrop("paycredit"); +register_tabledrop("payments"); +register_tabledrop("tmp_contributed"); +register_tabledrop("transferinfo"); +register_tabledrop("contest1"); +register_tabledrop("contest1data"); +register_tabledrop("logins"); +register_tabledrop("hintfriendsview"); +register_tabledrop("hintlastnview"); +register_tabledrop("batchdelete"); +register_tabledrop("ftpusers"); +register_tabledrop("ipban"); +register_tabledrop("ban"); +register_tabledrop("logaccess"); +register_tabledrop("fvcache"); +register_tabledrop("userpic_comment"); + +register_tablecreate("portal", <<'EOC'); +CREATE TABLE portal ( + userid int(10) unsigned NOT NULL default '0', + loc enum('left','main','right','moz') NOT NULL default 'left', + pos tinyint(3) unsigned NOT NULL default '0', + boxname varchar(30) default NULL, + boxargs varchar(255) default NULL, + PRIMARY KEY (userid,loc,pos), + KEY boxname (boxname) +) +EOC + +register_tablecreate("infohistory", <<'EOC'); +CREATE TABLE infohistory ( + userid int(10) unsigned NOT NULL default '0', + what varchar(15) NOT NULL default '', + timechange datetime NOT NULL default '0000-00-00 00:00:00', + oldvalue varchar(255) default NULL, + other varchar(30) default NULL, + KEY userid (userid) +) +EOC + +register_tablecreate("useridmap", <<'EOC'); +CREATE TABLE useridmap ( + userid int(10) unsigned NOT NULL, + user char(15) NOT NULL, + PRIMARY KEY (userid), + UNIQUE KEY user (user) +) +EOC + +post_create("useridmap", + "sqltry" => "REPLACE INTO useridmap (userid, user) SELECT userid, user FROM user", + ); + +register_tablecreate("userusage", <<'EOC'); +CREATE TABLE userusage +( + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid), + timecreate DATETIME NOT NULL, + timeupdate DATETIME, + timecheck DATETIME, + lastitemid INT UNSIGNED NOT NULL DEFAULT '0', + INDEX (timeupdate) +) +EOC + +# wknum - number of weeks past unix epoch time +# ubefore - units before next week (unit = 10 seconds) +# uafter - units after this week (unit = 10 seconds) +register_tablecreate("weekuserusage", <<'EOC'); +CREATE TABLE weekuserusage +( + wknum SMALLINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (wknum, userid), + ubefore SMALLINT UNSIGNED NOT NULL, + uafter SMALLINT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("userupdate", <<'EOC'); +CREATE TABLE userupdate +( + userid INT UNSIGNED NOT NULL, + groupbit TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, groupbit), + timeupdate DATETIME NOT NULL +) +EOC + + +post_create("userusage", + "sqltry" => "INSERT IGNORE INTO userusage (userid, timecreate, timeupdate, timecheck, lastitemid) SELECT userid, timecreate, timeupdate, timecheck, lastitemid FROM user", + "sqltry" => "ALTER TABLE user DROP timecreate, DROP timeupdate, DROP timecheck, DROP lastitemid", + ); + +register_tablecreate("acctcode", <<'EOC'); +CREATE TABLE acctcode +( + acid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + userid INT UNSIGNED NOT NULL, + rcptid INT UNSIGNED NOT NULL DEFAULT 0, + auth CHAR(5) NOT NULL, + INDEX (userid), + INDEX (rcptid) +) +EOC + +register_tablecreate("meme", <<'EOC'); +CREATE TABLE meme ( + url VARCHAR(150) NOT NULL, + posterid INT UNSIGNED NOT NULL, + UNIQUE (url, posterid), + ts TIMESTAMP, + itemid INT UNSIGNED NOT NULL, + INDEX (ts) +) +EOC + +register_tablecreate("statushistory", <<'EOC'); +CREATE TABLE statushistory ( + userid INT UNSIGNED NOT NULL, + adminid INT UNSIGNED NOT NULL, + shtype VARCHAR(20) NOT NULL, + shdate TIMESTAMP NOT NULL, + notes TEXT, + INDEX (userid, shdate), + INDEX (adminid, shdate), + INDEX (adminid, shtype, shdate), + INDEX (shtype, shdate) +) +EOC + +register_tablecreate("includetext", <<'EOC'); +CREATE TABLE includetext ( + incname VARCHAR(80) NOT NULL PRIMARY KEY, + inctext TEXT, + updatetime INT UNSIGNED NOT NULL, + INDEX (updatetime) +) +EOC + +register_tablecreate("oldids", <<'EOC'); +CREATE TABLE oldids ( + area CHAR(1) NOT NULL, + oldid INT UNSIGNED NOT NULL, + UNIQUE (area, oldid), + userid INT UNSIGNED NOT NULL, + newid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (area,userid, newid), + INDEX (userid) +) TYPE=MYISAM +EOC + +register_tablecreate("dudata", <<'EOC'); +CREATE TABLE dudata ( + userid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + areaid INT UNSIGNED NOT NULL, + bytes MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, area, areaid) +) +EOC + +register_tablecreate("dbinfo", <<'EOC'); +CREATE TABLE dbinfo ( + dbid TINYINT UNSIGNED NOT NULL, + name VARCHAR(25), + fdsn VARCHAR(255), + rootfdsn VARCHAR(255), + masterid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (dbid), + UNIQUE (name) +) +EOC + +register_tablecreate("dbweights", <<'EOC'); +CREATE TABLE dbweights ( + dbid TINYINT UNSIGNED NOT NULL, + role VARCHAR(25) NOT NULL, + PRIMARY KEY (dbid, role), + norm TINYINT UNSIGNED NOT NULL, + curr TINYINT UNSIGNED NOT NULL +) +EOC + +# notification/subscription stuff: + +register_tablecreate("subs", <<'EOC'); # global +CREATE TABLE subs ( + userid INT UNSIGNED NOT NULL, + etype CHAR(1) NOT NULL, + ejournalid INT UNSIGNED NOT NULL, + eiarg INT UNSIGNED NOT NULL, + UNIQUE (userid, etype, ejournalid, eiarg), + INDEX (etype, ejournalid, eiarg), + subtime DATETIME NOT NULL, + exptime DATETIME NOT NULL, + INDEX (exptime), + ntype CHAR(1) NOT NULL +) +EOC + +register_tablecreate("events", <<'EOC'); # clustered +CREATE TABLE events ( + evtime DATETIME NOT NULL, + INDEX (evtime), + etype CHAR(1) NOT NULL, + ejournalid INT UNSIGNED NOT NULL, + eiarg INT UNSIGNED NOT NULL, + duserid INT UNSIGNED NOT NULL, + diarg INT UNSIGNED NOT NULL +) +EOC + +# Begin S2 Stuff +register_tablecreate("s2layers", <<'EOC'); # global +CREATE TABLE s2layers +( + s2lid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (s2lid), + b2lid INT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + INDEX (userid), + INDEX (b2lid, type) +) +EOC + +register_tablecreate("s2info", <<'EOC'); # global +CREATE TABLE s2info +( + s2lid INT UNSIGNED NOT NULL, + infokey VARCHAR(80) NOT NULL, + value VARCHAR(255) NOT NULL, + PRIMARY KEY (s2lid, infokey) +) +EOC + +register_tablecreate("s2source", <<'EOC'); # global +CREATE TABLE s2source +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + s2code MEDIUMBLOB +) +EOC + +register_tablecreate("s2checker", <<'EOC'); # global +CREATE TABLE s2checker +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + checker MEDIUMBLOB +) +EOC + +# the original global s2compiled table. see comment below for new version. +register_tablecreate("s2compiled", <<'EOC'); # global (compdata is not gzipped) +CREATE TABLE s2compiled +( + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (s2lid), + comptime INT UNSIGNED NOT NULL, + compdata MEDIUMBLOB +) +EOC + +# s2compiled2 is only for user S2 layers (not system) and is lazily +# migrated. new saves go here. loads try this table first (unless +# system) and if miss, then try the s2compiled table on the global. +register_tablecreate("s2compiled2", <<'EOC'); # clustered (compdata is gzipped) +CREATE TABLE s2compiled2 +( + userid INT UNSIGNED NOT NULL, + s2lid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid, s2lid), + + comptime INT UNSIGNED NOT NULL, + compdata MEDIUMBLOB +) +EOC + +register_tablecreate("s2styles", <<'EOC'); # global +CREATE TABLE s2styles +( + styleid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (styleid), + userid INT UNSIGNED NOT NULL, + name VARCHAR(255), + modtime INT UNSIGNED NOT NULL, + INDEX (userid) +) +EOC + +register_tablecreate("s2stylelayers", <<'EOC'); # global +CREATE TABLE s2stylelayers +( + styleid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + UNIQUE (styleid, type), + s2lid INT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("s2stylelayers2", <<'EOC'); # clustered +CREATE TABLE s2stylelayers2 +( + userid INT UNSIGNED NOT NULL, + styleid INT UNSIGNED NOT NULL, + type ENUM('core','i18nc','layout','theme','i18n','user') NOT NULL, + PRIMARY KEY (userid, styleid, type), + s2lid INT UNSIGNED NOT NULL +) +EOC + + +register_tablecreate("ml_domains", <<'EOC'); +CREATE TABLE ml_domains +( + dmid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (dmid), + type VARCHAR(30) NOT NULL, + args VARCHAR(255) NOT NULL DEFAULT '', + UNIQUE (type,args) +) +EOC + +register_tablecreate("ml_items", <<'EOC'); +CREATE TABLE ml_items +( + dmid TINYINT UNSIGNED NOT NULL, + itid MEDIUMINT UNSIGNED AUTO_INCREMENT NOT NULL, + PRIMARY KEY (dmid, itid), + itcode VARCHAR(80) NOT NULL, + UNIQUE (dmid, itcode), + notes MEDIUMTEXT +) TYPE=MYISAM +EOC + +register_tablecreate("ml_langs", <<'EOC'); +CREATE TABLE ml_langs +( + lnid SMALLINT UNSIGNED NOT NULL, + UNIQUE (lnid), + lncode VARCHAR(16) NOT NULL, # en_US en_LJ en ch_HK ch_B5 etc... de_DE + UNIQUE (lncode), + lnname VARCHAR(60) NOT NULL, # "Deutsch" + parenttype ENUM('diff','sim') NOT NULL, + parentlnid SMALLINT UNSIGNED NOT NULL, + lastupdate DATETIME NOT NULL +) +EOC + +register_tablecreate("ml_langdomains", <<'EOC'); +CREATE TABLE ml_langdomains +( + lnid SMALLINT UNSIGNED NOT NULL, + dmid TINYINT UNSIGNED NOT NULL, + PRIMARY KEY (lnid, dmid), + dmmaster ENUM('0','1') NOT NULL, + lastgetnew DATETIME, + lastpublish DATETIME, + countokay SMALLINT UNSIGNED NOT NULL, + counttotal SMALLINT UNSIGNED NOT NULL +) +EOC + +register_tablecreate("ml_latest", <<'EOC'); +CREATE TABLE ml_latest +( + lnid SMALLINT UNSIGNED NOT NULL, + dmid TINYINT UNSIGNED NOT NULL, + itid SMALLINT UNSIGNED NOT NULL, + PRIMARY KEY (lnid, dmid, itid), + txtid INT UNSIGNED NOT NULL, + chgtime DATETIME NOT NULL, + staleness TINYINT UNSIGNED DEFAULT 0 NOT NULL, # better than ENUM('0','1','2'); + INDEX (lnid, staleness), + INDEX (dmid, itid), + INDEX (lnid, dmid, chgtime), + INDEX (chgtime) +) +EOC + +register_tablecreate("ml_text", <<'EOC'); +CREATE TABLE ml_text +( + dmid TINYINT UNSIGNED NOT NULL, + txtid INT UNSIGNED AUTO_INCREMENT NOT NULL, + PRIMARY KEY (dmid, txtid), + lnid SMALLINT UNSIGNED NOT NULL, + itid SMALLINT UNSIGNED NOT NULL, + INDEX (lnid, dmid, itid), + text TEXT NOT NULL, + userid INT UNSIGNED NOT NULL +) TYPE=MYISAM +EOC + +register_tablecreate("domains", <<'EOC'); +CREATE TABLE domains +( + domain VARCHAR(80) NOT NULL, + PRIMARY KEY (domain), + userid INT UNSIGNED NOT NULL, + INDEX (userid) +) +EOC + +register_tablecreate("procnotify", <<'EOC'); +CREATE TABLE procnotify +( + nid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (nid), + cmd VARCHAR(50), + args VARCHAR(255) +) +EOC + +register_tablecreate("syndicated", <<'EOC'); +CREATE TABLE syndicated +( + userid INT UNSIGNED NOT NULL, + synurl VARCHAR(255), + checknext DATETIME NOT NULL, + lastcheck DATETIME, + lastmod INT UNSIGNED, # unix time + etag VARCHAR(80), + PRIMARY KEY (userid), + UNIQUE (synurl), + INDEX (checknext) +) +EOC + +register_tablecreate("synitem", <<'EOC'); +CREATE TABLE synitem +( + userid INT UNSIGNED NOT NULL, + item CHAR(22), # base64digest of rss $item + dateadd DATETIME NOT NULL, + INDEX (userid, item(3)), + INDEX (userid, dateadd) +) +EOC + +register_tablecreate("ratelist", <<'EOC'); +CREATE TABLE ratelist +( + rlid TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + name varchar(50) not null, + des varchar(255) not null, + PRIMARY KEY (rlid), + UNIQUE KEY (name) + ) +EOC + +register_tablecreate("ratelog", <<'EOC'); +CREATE TABLE ratelog +( + userid INT UNSIGNED NOT NULL, + rlid TINYINT UNSIGNED NOT NULL, + evttime INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + index (userid, rlid, evttime), + quantity SMALLINT UNSIGNED NOT NULL + ) +EOC + +register_tablecreate("rateabuse", <<'EOC'); +CREATE TABLE rateabuse +( + rlid TINYINT UNSIGNED NOT NULL, + userid INT UNSIGNED NOT NULL, + evttime INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + enum ENUM('soft','hard') NOT NULL, + index (rlid, evttime), + index (userid), + index (ip) + ) +EOC + +register_tablecreate("loginstall", <<'EOC'); +CREATE TABLE loginstall +( + userid INT UNSIGNED NOT NULL, + ip INT UNSIGNED NOT NULL, + time INT UNSIGNED NOT NULL, + UNIQUE (userid, ip) + ) +EOC + +# web sessions. optionally tied to ips and with expiration times. +# whenever a session is okayed, expired ones are deleted, or ones +# created over 30 days ago. a live session can't change email address +# or password. digest authentication will be required for that, +# or javascript md5 challenge/response. +register_tablecreate("sessions", <<'EOC'); # user cluster +CREATE TABLE sessions ( + userid MEDIUMINT UNSIGNED NOT NULL, + sessid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (userid, sessid), + auth CHAR(10) NOT NULL, + exptype ENUM('short','long') NOT NULL, # browser closed or "infinite" + timecreate INT UNSIGNED NOT NULL, + timeexpire INT UNSIGNED NOT NULL, + ipfixed CHAR(15) # if null, not fixed at IP. +) +EOC + +register_tablecreate("sessions_data", <<'EOC'); # user cluster +CREATE TABLE sessions_data ( + userid MEDIUMINT UNSIGNED NOT NULL, + sessid MEDIUMINT UNSIGNED NOT NULL, + skey VARCHAR(30) NOT NULL, + PRIMARY KEY (userid, sessid, skey), + sval VARCHAR(255) +) +EOC + +# what: ip, email, ljuser, ua, emailnopay +# emailnopay means don't allow payments from that email +register_tablecreate("sysban", <<'EOC'); +CREATE TABLE sysban ( + banid MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (banid), + status ENUM('active','expired') NOT NULL DEFAULT 'active', + INDEX (status), + bandate DATETIME, + banuntil DATETIME, + what VARCHAR(20) NOT NULL, + value VARCHAR(80), + note VARCHAR(255) +) +EOC + +# clustered relationship types are defined in ljlib.pl and ljlib-local.pl in +# the LJ::get_reluser_id function +register_tablecreate("reluser2", <<'EOC'); +CREATE TABLE reluser2 ( + userid INT UNSIGNED NOT NULL, + type SMALLINT UNSIGNED NOT NULL, + targetid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid,type,targetid), + INDEX (userid,targetid) +) +EOC + +# relationship types: +# 'A' means targetid can administrate userid as a community maintainer +# 'B' means targetid is banned in userid +# 'P' means targetid can post to userid +# 'M' means targetid can moderate the community userid +# 'N' means targetid is preapproved to post to community userid w/o moderation +# new types to be added here + +register_tablecreate("reluser", <<'EOC'); +CREATE TABLE reluser ( + userid INT UNSIGNED NOT NULL, + targetid INT UNSIGNED NOT NULL, + type char(1) NOT NULL, + PRIMARY KEY (userid,type,targetid), + KEY (targetid,type) +) +EOC + +post_create("reluser", + "sqltry" => "INSERT IGNORE INTO reluser (userid, targetid, type) SELECT userid, banneduserid, 'B' FROM ban", + "sqltry" => "INSERT IGNORE INTO reluser (userid, targetid, type) SELECT u.userid, p.userid, 'A' FROM priv_map p, priv_list l, user u WHERE l.privcode='sharedjournal' AND l.prlid=p.prlid AND p.arg=u.user AND p.arg<>'all'", + "code" => sub { + my $dbh = shift; + print "# Converting logaccess rows to reluser...\n"; + my $sth = $dbh->prepare("SELECT MAX(userid) FROM user"); + $sth->execute; + my ($maxid) = $sth->fetchrow_array; + return unless $maxid; + + my $from = 1; my $to = $from + 10000 - 1; + while ($from <= $maxid) { + printf "# logaccess status: (%0.1f%%)\n", ($from * 100 / $maxid); + do_sql("INSERT IGNORE INTO reluser (userid, targetid, type) ". + "SELECT ownerid, posterid, 'P' ". + "FROM logaccess ". + "WHERE ownerid BETWEEN $from AND $to"); + $from += 10000; + $to += 10000; + } + print "# Finished converting logaccess.\n"; + }, + ); + +register_tablecreate("clustermove", <<'EOC'); +CREATE TABLE clustermove ( + cmid INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (cmid), + userid INT UNSIGNED NOT NULL, + KEY (userid), + sclust TINYINT UNSIGNED NOT NULL, + dclust TINYINT UNSIGNED NOT NULL, + timestart INT UNSIGNED, + timedone INT UNSIGNED, + sdeleted ENUM('1','0') +) +EOC + +# moderated community post summary info +register_tablecreate("modlog", <<'EOC'); +CREATE TABLE modlog ( + journalid INT UNSIGNED NOT NULL, + modid MEDIUMINT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, modid), + posterid INT UNSIGNED NOT NULL, + subject CHAR(30), + logtime DATETIME, + KEY (journalid, logtime) +) +EOC + +# moderated community post Storable object (all props/options) +register_tablecreate("modblob", <<'EOC'); +CREATE TABLE modblob ( + journalid INT UNSIGNED NOT NULL, + modid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, modid), + request_stor MEDIUMBLOB +) +EOC + +# user counters +register_tablecreate("counter", <<'EOC'); +CREATE TABLE counter ( + journalid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + PRIMARY KEY (journalid, area), + max MEDIUMINT UNSIGNED NOT NULL +) +EOC + +# user counters on the global (contrary to the name) +register_tablecreate("usercounter", <<'EOC'); +CREATE TABLE usercounter ( + journalid INT UNSIGNED NOT NULL, + area CHAR(1) NOT NULL, + PRIMARY KEY (journalid, area), + max INT UNSIGNED NOT NULL +) +EOC + +# community interests +register_tablecreate("comminterests", <<'EOC'); +CREATE TABLE comminterests ( + userid int(10) unsigned NOT NULL default '0', + intid int(10) unsigned NOT NULL default '0', + PRIMARY KEY (userid,intid), + KEY (intid) +) +EOC + +# links +register_tablecreate("links", <<'EOC'); # clustered +CREATE TABLE links ( + journalid int(10) unsigned NOT NULL default '0', + ordernum tinyint(4) unsigned NOT NULL default '0', + parentnum tinyint(4) unsigned NOT NULL default '0', + url varchar(255) default NULL, + title varchar(255) NOT NULL default '', + KEY (journalid) +) +EOC + +# supportprop +register_tablecreate("supportprop", <<'EOC'); +CREATE TABLE supportprop ( + spid int(10) unsigned NOT NULL default '0', + prop varchar(30) NOT NULL, + value varchar(255) NOT NULL, + PRIMARY KEY (spid, prop) +) +EOC + +# s1overrides +register_tablecreate("s1overrides", <<'EOC'); # clustered +CREATE TABLE s1overrides ( + userid int unsigned NOT NULL default '', + override text NOT NULL, + PRIMARY KEY (userid) +) +EOC + +# s1style +register_tablecreate("s1style", <<'EOC'); # clustered +CREATE TABLE s1style ( + styleid int(11) NOT NULL auto_increment, + userid int(11) unsigned NOT NULL, + styledes varchar(50) default NULL, + type varchar(10) NOT NULL default '', + formatdata text, + is_public enum('Y','N') NOT NULL default 'N', + is_embedded enum('Y','N') NOT NULL default 'N', + is_colorfree enum('Y','N') NOT NULL default 'N', + opt_cache enum('Y','N') NOT NULL default 'N', + has_ads enum('Y','N') NOT NULL default 'N', + lastupdate datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (styleid), + KEY (userid) + +) +EOC + +# s1stylemap +register_tablecreate("s1stylemap", <<'EOC'); # global +CREATE TABLE s1stylemap ( + styleid int unsigned NOT NULL, + userid int unsigned NOT NULL, + PRIMARY KEY (styleid) +) +EOC + +# comment urls +register_tablecreate("commenturls", <<'EOC'); # global +CREATE TABLE commenturls ( + posterid int unsigned NOT NULL, + journalid int unsigned NOT NULL, + jtalkid mediumint unsigned NOT NULL, + timecreate int unsigned NOT NULL, + url varchar(255) NOT NULL, + INDEX (timecreate) +) +EOC + +post_create("comminterests", + "code" => sub { + my $dbh = shift; + print "# Populating community interests...\n"; + + my $BLOCK = 1_000; + + my @ids = @{ $dbh->selectcol_arrayref("SELECT userid FROM community") || [] }; + my $total = @ids; + + while (@ids) { + my @set = grep { $_ } splice(@ids, 0, $BLOCK); + + printf ("# community interests status: (%0.1f%%)\n", + ((($total - @ids) / $total) * 100)) if $total > $BLOCK; + + local $" = ","; + do_sql("INSERT IGNORE INTO comminterests (userid, intid) ". + "SELECT userid, intid FROM userinterests " . + "WHERE userid IN (@set)"); + } + + print "# Finished converting community interests.\n"; + }, + ); + +# tracking where users are active +register_tablecreate("clustertrack2", <<'EOC'); # clustered +CREATE TABLE clustertrack2 ( + userid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid), + timeactive INT UNSIGNED NOT NULL, + clusterid SMALLINT UNSIGNED, + INDEX (timeactive, clusterid) +) +EOC + +# rotating site secret values +register_tablecreate("secrets", <<'EOC'); # global +CREATE TABLE secrets ( + stime INT UNSIGNED NOT NULL, + secret CHAR(32) NOT NULL, + PRIMARY KEY (stime) +) +EOC + +# Captcha table +register_tablecreate("captchas", <<'EOC'); +CREATE TABLE captchas ( + capid INT UNSIGNED NOT NULL auto_increment, + type enum('image','audio'), + issuetime INT UNSIGNED NOT NULL DEFAULT 0, + answer CHAR(10), + userid INT UNSIGNED NOT NULL DEFAULT 0, + anum SMALLINT UNSIGNED NOT NULL, + INDEX(type,issuetime), + INDEX(userid), + PRIMARY KEY(capid) +) +EOC + +# Challenges table (for non-memcache support) +register_tablecreate("challenges", <<'EOC'); +CREATE TABLE challenges ( + ctime int(10) unsigned NOT NULL DEFAULT 0, + challenge char(80) NOT NULL DEFAULT '', + PRIMARY KEY (challenge) +) +EOC + +register_tablecreate("clustermove_inprogress", <<'EOC'); +CREATE TABLE clustermove_inprogress ( + userid INT UNSIGNED NOT NULL, + locktime INT UNSIGNED NOT NULL, + dstclust SMALLINT UNSIGNED NOT NULL, + moverhost INT UNSIGNED NOT NULL, + moverport SMALLINT UNSIGNED NOT NULL, + moverinstance CHAR(22) NOT NULL, # base64ed MD5 hash + PRIMARY KEY (userid) +) +EOC + +# track open HTTP proxies +register_tablecreate("openproxy", <<'EOC'); +CREATE TABLE openproxy ( + addr VARCHAR(15) NOT NULL, + status ENUM('proxy', 'clear'), + asof INT UNSIGNED NOT NULL, + src VARCHAR(80), + PRIMARY KEY (addr) +) +EOC + +register_tablecreate("captcha_session", <<'EOC'); # clustered +CREATE TABLE captcha_session ( + sess char(20) NOT NULL default '', + sesstime int(10) unsigned NOT NULL default '0', + lastcapid int(11) default NULL, + trynum smallint(6) default '0', + PRIMARY KEY (`sess`), + KEY sesstime (`sesstime`) +) +EOC + +register_tablecreate("spamreports", <<'EOC'); # global +CREATE TABLE spamreports ( + reporttime INT(10) UNSIGNED NOT NULL, + ip VARCHAR(15), + journalid INT(10) UNSIGNED NOT NULL, + posterid INT(10) UNSIGNED NOT NULL DEFAULT 0, + subject VARCHAR(255) BINARY, + body BLOB NOT NULL, + PRIMARY KEY (reporttime, journalid), + INDEX (ip), + INDEX (posterid) +) +EOC + +register_tablecreate("tempanonips", <<'EOC'); # clustered +CREATE TABLE tempanonips ( + reporttime INT(10) UNSIGNED NOT NULL, + ip VARCHAR(15) NOT NULL, + journalid INT(10) UNSIGNED NOT NULL, + jtalkid MEDIUMINT(8) UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jtalkid), + INDEX (reporttime) +) +EOC + +# partialstats - stores calculation times: +# jobname = 'calc_country' +# clusterid = '1' +# calctime = time() +register_tablecreate("partialstats", <<'EOC'); +CREATE TABLE partialstats ( + jobname VARCHAR(50) NOT NULL, + clusterid MEDIUMINT NOT NULL DEFAULT 0, + calctime INT(10) UNSIGNED, + PRIMARY KEY (jobname, clusterid) +) +EOC + +# partialstatsdata - stores data per cluster: +# statname = 'country' +# arg = 'US' +# clusterid = '1' +# value = '500' +register_tablecreate("partialstatsdata", <<'EOC'); +CREATE TABLE partialstatsdata ( + statname VARCHAR(50) NOT NULL, + arg VARCHAR(50) NOT NULL, + clusterid INT(10) UNSIGNED NOT NULL DEFAULT 0, + value INT(11), + PRIMARY KEY (statname, arg, clusterid) +) +EOC + +# inviterecv -- stores community invitations received +register_tablecreate("inviterecv", <<'EOC'); +CREATE TABLE inviterecv ( + userid INT(10) UNSIGNED NOT NULL, + commid INT(10) UNSIGNED NOT NULL, + maintid INT(10) UNSIGNED NOT NULL, + recvtime INT(10) UNSIGNED NOT NULL, + args VARCHAR(255), + PRIMARY KEY (userid, commid) +) +EOC + +# invitesent -- stores community invitations sent +register_tablecreate("invitesent", <<'EOC'); +CREATE TABLE invitesent ( + commid INT(10) UNSIGNED NOT NULL, + userid INT(10) UNSIGNED NOT NULL, + maintid INT(10) UNSIGNED NOT NULL, + recvtime INT(10) UNSIGNED NOT NULL, + status ENUM('accepted', 'rejected', 'outstanding') NOT NULL, + args VARCHAR(255), + PRIMARY KEY (commid, userid) +) +EOC + +# memorable2 -- clustered memories +register_tablecreate("memorable2", <<'EOC'); +CREATE TABLE memorable2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + memid INT(10) UNSIGNED NOT NULL DEFAULT '0', + journalid INT(10) UNSIGNED NOT NULL DEFAULT '0', + ditemid INT(10) UNSIGNED NOT NULL DEFAULT '0', + des VARCHAR(150) DEFAULT NULL, + security ENUM('public','friends','private') NOT NULL DEFAULT 'public', + PRIMARY KEY (userid, journalid, ditemid), + UNIQUE KEY (userid, memid) +) +EOC + +# memkeyword2 -- clustered memory keyword map +register_tablecreate("memkeyword2", <<'EOC'); +CREATE TABLE memkeyword2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + memid INT(10) UNSIGNED NOT NULL DEFAULT '0', + kwid INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid, memid, kwid), + KEY (userid, kwid) +) +EOC + +# userkeywords -- clustered keywords +register_tablecreate("userkeywords", <<'EOC'); +CREATE TABLE userkeywords ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + kwid INT(10) UNSIGNED NOT NULL DEFAULT '0', + keyword VARCHAR(80) BINARY NOT NULL, + PRIMARY KEY (userid, kwid), + UNIQUE KEY (userid, keyword) +) +EOC + +# friendgroup2 -- clustered friend groups +register_tablecreate("friendgroup2", <<'EOC'); +CREATE TABLE friendgroup2 ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + groupnum TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + groupname VARCHAR(90) NOT NULL DEFAULT '', + sortorder TINYINT(3) UNSIGNED NOT NULL DEFAULT '50', + is_public ENUM('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (userid, groupnum) +) +EOC + +register_tablecreate("readonly_user", <<'EOC'); +CREATE TABLE readonly_user ( + userid INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (userid) +) +EOC + +register_tablecreate("underage", <<'EOC'); +CREATE TABLE underage ( + uniq CHAR(15) NOT NULL, + timeof INT(10) NOT NULL, + PRIMARY KEY (uniq), + KEY (timeof) +) +EOC + +register_tablecreate("support_youreplied", <<'EOC'); +CREATE TABLE support_youreplied ( + userid INT UNSIGNED NOT NULL, + spid INT UNSIGNED NOT NULL, + PRIMARY KEY (userid, spid) +) +EOC + +register_tablecreate("support_answers", <<'EOC'); +CREATE TABLE support_answers ( + ansid INT UNSIGNED NOT NULL, + spcatid INT UNSIGNED NOT NULL, + lastmodtime INT UNSIGNED NOT NULL, + lastmoduserid INT UNSIGNED NOT NULL, + subject VARCHAR(255), + body TEXT, + + PRIMARY KEY (ansid), + KEY (spcatid) +) +EOC + +register_tablecreate("userlog", <<'EOC'); +CREATE TABLE userlog ( + userid INT UNSIGNED NOT NULL, + logtime INT UNSIGNED NOT NULL, + action VARCHAR(30) NOT NULL, + actiontarget INT UNSIGNED, + remoteid INT UNSIGNED, + ip VARCHAR(15), + uniq VARCHAR(15), + extra VARCHAR(255), + + INDEX (userid) +) +EOC + +# external user mappings +# note: extuser/extuserid are expected to sometimes be NULL, even +# though they are keyed. (Null values are not taken into account when +# using indexes) +register_tablecreate("extuser", <<'EOC'); +CREATE TABLE extuser ( + userid INT UNSIGNED NOT NULL PRIMARY KEY, + siteid INT UNSIGNED NOT NULL, + extuser VARCHAR(50), + extuserid INT UNSIGNED, + UNIQUE KEY `extuser` (siteid, extuser), + UNIQUE KEY `extuserid` (siteid, extuserid) +) +EOC + +# table showing what tags a user has; parentkwid can be null +register_tablecreate("usertags", <<'EOC'); +CREATE TABLE usertags ( + journalid INT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + parentkwid INT UNSIGNED, + display ENUM('0','1') DEFAULT '1' NOT NULL, + PRIMARY KEY (journalid, kwid) +) +EOC + +# mapping of tags applied to an entry +register_tablecreate("logtags", <<'EOC'); +CREATE TABLE logtags ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, jitemid, kwid), + KEY (journalid, kwid) +) +EOC + +# logtags but only for the most recent 100 tags-to-entry +register_tablecreate("logtagsrecent", <<'EOC'); +CREATE TABLE logtagsrecent ( + journalid INT UNSIGNED NOT NULL, + jitemid MEDIUMINT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + PRIMARY KEY (journalid, kwid, jitemid) +) +EOC + +# summary counts for security on entry keywords +register_tablecreate("logkwsum", <<'EOC'); +CREATE TABLE logkwsum ( + journalid INT UNSIGNED NOT NULL, + kwid INT UNSIGNED NOT NULL, + security INT UNSIGNED NOT NULL, + entryct INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (journalid, kwid, security), + KEY (journalid, security) +) +EOC + +# action history tables +register_tablecreate("actionhistory", <<'EOC'); +CREATE TABLE actionhistory ( + time INT UNSIGNED NOT NULL, + clusterid TINYINT UNSIGNED NOT NULL, + what CHAR(2) NOT NULL, + count INT UNSIGNED NOT NULL DEFAULT 0, + INDEX(time) + +) +EOC + +register_tablecreate("recentactions", <<'EOC'); +CREATE TABLE recentactions ( + what CHAR(2) NOT NULL +) TYPE=MYISAM +EOC + +# external identities +# +# idtype ::= +# "O" - OpenID +# "L" - LID (netmesh) +# "T" - TypeKey +# ? - etc +register_tablecreate("identitymap", <<'EOC'); +CREATE TABLE identitymap ( + idtype CHAR(1) NOT NULL, + identity VARCHAR(255) BINARY NOT NULL, + userid INT unsigned NOT NULL, + PRIMARY KEY (idtype, identity), + KEY userid (userid) +) +EOC + +register_tablecreate("openid_trust", <<'EOC'); +CREATE TABLE openid_trust ( + userid int(10) unsigned NOT NULL default '0', + endpoint_id int(10) unsigned NOT NULL default '0', + trust_time int(10) unsigned NOT NULL default '0', + duration enum('always','once') NOT NULL default 'always', + last_assert_time int(10) unsigned default NULL, + flags tinyint(3) unsigned default NULL, + PRIMARY KEY (userid,endpoint_id), + KEY endpoint_id (endpoint_id) +) +EOC + +register_tablecreate("openid_endpoint", <<'EOC'); +CREATE TABLE openid_endpoint ( + endpoint_id int(10) unsigned NOT NULL auto_increment, + url varchar(255) BINARY NOT NULL default '', + last_assert_time int(10) unsigned default NULL, + PRIMARY KEY (endpoint_id), + UNIQUE KEY url (url), + KEY last_assert_time (last_assert_time) +) +EOC + +register_tablecreate("openid_external", <<'EOC'); +CREATE TABLE openid_external ( + userid int(10) unsigned NOT NULL default '0', + url varchar(255) binary default NULL, + KEY userid (userid) +) +EOC + +# NOTE: new table declarations go here + + +### changes + +register_alter(sub { + + my $dbh = shift; + my $runsql = shift; + + if (column_type("supportcat", "is_selectable") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD is_selectable ENUM('1','0') ". + "NOT NULL DEFAULT '1', ADD public_read ENUM('1','0') NOT ". + "NULL DEFAULT '1', ADD public_help ENUM('1','0') NOT NULL ". + "DEFAULT '1', ADD allow_screened ENUM('1','0') NOT NULL ". + "DEFAULT '0', ADD replyaddress VARCHAR(50), ADD hide_helpers ". + "ENUM('1','0') NOT NULL DEFAULT '0' AFTER allow_screened"); + + } + if (column_type("supportlog", "type") =~ /faqref/) + { + do_alter("supportlog", + "ALTER TABLE supportlog MODIFY type ENUM('req', 'answer', ". + "'custom', 'faqref', 'comment', 'internal', 'screened') ". + "NOT NULL"); + do_sql("UPDATE supportlog SET type='answer' WHERE type='custom'"); + do_sql("UPDATE supportlog SET type='answer' WHERE type='faqref'"); + do_alter("supportlog", + "ALTER TABLE supportlog MODIFY type ENUM('req', 'answer', ". + "'comment', 'internal', 'screened') NOT NULL"); + + } + if (table_relevant("supportcat") && column_type("supportcat", "catkey") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD catkey VARCHAR(25) AFTER spcatid"); + do_sql("UPDATE supportcat SET catkey=spcatid WHERE catkey IS NULL"); + do_alter("supportcat", + "ALTER TABLE supportcat MODIFY catkey VARCHAR(25) NOT NULL"); + } + if (column_type("supportcat", "no_autoreply") eq "") + { + do_alter("supportcat", + "ALTER TABLE supportcat ADD no_autoreply ENUM('1', '0') ". + "NOT NULL DEFAULT '0'"); + } + + if (column_type("support", "timelasthelp") eq "") + { + do_alter("supportlog", + "ALTER TABLE supportlog ADD INDEX (userid)"); + do_alter("support", + "ALTER TABLE support ADD timelasthelp INT UNSIGNED"); + } + + if (column_type("duplock", "realm") !~ /payments/) + { + do_alter("duplock", + "ALTER TABLE duplock MODIFY realm ENUM('support','log',". + "'comment','payments') NOT NULL default 'support'"); + } + + if (column_type("schematables", "redist_where") eq "") + { + do_alter("schematables", + "ALTER TABLE schematables ADD ". + "redist_where varchar(255) AFTER redist_mode"); + } + + # upgrade people to the new capabilities system. if they're + # using the the paidfeatures column already, we'll assign them + # the same capability bits that ljcom will be using. + if (table_relevant("user") && column_type("user", "caps") eq "") + { + do_alter("user", + "ALTER TABLE user ADD ". + "caps SMALLINT UNSIGNED NOT NULL DEFAULT 0 AFTER user"); + try_sql("UPDATE user SET caps=16|8|2 WHERE paidfeatures='on'"); + try_sql("UPDATE user SET caps=8|2 WHERE paidfeatures='paid'"); + try_sql("UPDATE user SET caps=4|2 WHERE paidfeatures='early'"); + try_sql("UPDATE user SET caps=2 WHERE paidfeatures='off'"); + } + + # axe this column (and its two related ones) if it exists. + if (column_type("user", "paidfeatures")) + { + try_sql("REPLACE INTO paiduser (userid, paiduntil, paidreminder) ". + "SELECT userid, paiduntil, paidreminder FROM user WHERE paidfeatures='paid'"); + try_sql("REPLACE INTO paiduser (userid, paiduntil, paidreminder) ". + "SELECT userid, COALESCE(paiduntil,'0000-00-00'), NULL FROM user WHERE paidfeatures='on'"); + do_alter("user", + "ALTER TABLE user DROP paidfeatures, DROP paiduntil, DROP paidreminder"); + } + + # move S1 _style ids to userprop table! + if (column_type("user", "lastn_style")) { + + # be paranoid and insert these in case they don't exist: + try_sql("INSERT INTO userproplist VALUES (null, 's1_lastn_style', 0, 'Recent View StyleID', 'num', 'The style ID# of the S1 style for the recent entries view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_calendar_style', 0, 'Calendar View StyleID', 'num', 'The style ID# of the S1 style for the calendar view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_day_style', 0, 'Day View StyleID', 'num', 'The style ID# of the S1 style for the day view.')"); + try_sql("INSERT INTO userproplist VALUES (null, 's1_friends_style', 0, 'Friends View StyleID', 'num', 'The style ID# of the S1 style for the friends view.')"); + + foreach my $v (qw(lastn day calendar friends)) { + do_sql("INSERT INTO userproplite SELECT u.userid, upl.upropid, u.${v}_style FROM user u, userproplist upl WHERE upl.name='s1_${v}_style'"); + } + + do_alter("user", + "ALTER TABLE user DROP lastn_style, DROP calendar_style, DROP search_style, DROP searchres_style, DROP day_style, DROP friends_style"); + } + + # add scope columns to proplist tables + if (column_type("userproplist", "scope") eq "") { + do_alter("userproplist", + "ALTER TABLE userproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("logproplist", "scope") eq "") { + do_alter("logproplist", + "ALTER TABLE logproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("talkproplist", "scope") eq "") { + do_alter("talkproplist", + "ALTER TABLE talkproplist ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + if (column_type("priv_list", "scope") eq "") { + do_alter("priv_list", + "ALTER TABLE priv_list ADD scope ENUM('general', 'local') ". + "DEFAULT 'general' NOT NULL"); + } + + # change size of stats table to accomodate meme data, and shrink statcat, + # since it's way too big + if (column_type("stats", "statcat") eq "varchar(100)") { + do_alter("stats", + "ALTER TABLE stats ". + "MODIFY statcat VARCHAR(30) NOT NULL, ". + "MODIFY statkey VARCHAR(150) NOT NULL, ". + "MODIFY statval INT UNSIGNED NOT NULL, ". + "DROP INDEX statcat"); + } + + if (column_type("priv_list", "is_public") eq "") { + do_alter("priv_list", + "ALTER TABLE priv_list ". + "ADD is_public ENUM('1', '0') DEFAULT '1' NOT NULL"); + } + + if (column_type("randomuserset", "rid") eq "") { + do_alter("randomuserset", + "ALTER TABLE randomuserset DROP PRIMARY KEY, DROP timeupdate, ". + "ADD rid INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (rid)"); + } + + # cluster stuff! + if (column_type("meme", "journalid") eq "") { + do_alter("meme", + "ALTER TABLE meme ADD journalid INT UNSIGNED NOT NULL AFTER ts"); + } + + if (column_type("memorable", "jitemid") eq "") { + do_alter("memorable", "ALTER TABLE memorable ". + "DROP INDEX userid, DROP INDEX itemid, ". + "CHANGE itemid jitemid INT UNSIGNED NOT NULL, ". + "ADD journalid INT UNSIGNED NOT NULL AFTER userid, ". + "ADD UNIQUE uniq (userid, journalid, jitemid), ". + "ADD KEY item (journalid, jitemid)"); + } + + if (column_type("user", "clusterid") eq "") { + do_alter("user", "ALTER TABLE user ". + "ADD clusterid TINYINT UNSIGNED NOT NULL AFTER caps, ". + "ADD dversion TINYINT UNSIGNED NOT NULL AFTER clusterid, ". + "ADD INDEX idxcluster (clusterid), ". + "ADD INDEX idxversion (dversion)"); + } + + if (column_type("friends", "bgcolor") eq "char(7)") { + do_alter("friends", "ALTER TABLE friends ". + "MODIFY bgcolor CHAR(8) NOT NULL DEFAULT '16777215', ". + "MODIFY fgcolor CHAR(8) NOT NULL DEFAULT '0'"); + do_sql("UPDATE friends SET ". + "bgcolor=CONV(RIGHT(bgcolor,6),16,10), ". + "fgcolor=CONV(RIGHT(fgcolor,6),16,10)") + unless skip_opt() eq "colorconv"; + } + + return if skip_opt() eq "colorconv"; + + if (column_type("friends", "bgcolor") eq "char(8)") { + do_alter("friends", "ALTER TABLE friends ". + "MODIFY bgcolor MEDIUMINT UNSIGNED NOT NULL DEFAULT 16777215, ". + "MODIFY fgcolor MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + # add the default encoding field, for recoding older pre-Unicode stuff + + if (column_type("user", "oldenc") eq "") { + do_alter("user", "ALTER TABLE user ". + "ADD oldenc TINYINT DEFAULT 0 NOT NULL, ". + "MODIFY name CHAR(80) NOT NULL"); + } + + if (column_type("user", "allow_getpromos") ne "") { + do_alter("user", "ALTER TABLE user DROP allow_getpromos"); + } + + # widen columns to accomodate larger Unicode names + if (column_type("friendgroup", "groupname") eq "varchar(30)") { + do_alter("friendgroup", + "ALTER TABLE friendgroup ". + "MODIFY groupname VARCHAR(60) NOT NULL"); + } + if (column_type("todo", "statusline") eq "varchar(15)") { + do_alter("todo", + "ALTER TABLE todo ". + "MODIFY statusline VARCHAR(40) NOT NULL, " . + "MODIFY subject VARCHAR(100) NOT NULL, " . + "MODIFY des VARCHAR(255) NOT NULL"); + } + if (column_type("memorable", "des") eq "varchar(60)") { + do_alter("memorable", + "ALTER TABLE memorable ". + "MODIFY des VARCHAR(150) NOT NULL"); + } + if (column_type("keywords", "keyword") eq "varchar(40) binary") { + do_alter("keywords", + "ALTER TABLE keywords ". + "MODIFY keyword VARCHAR(80) BINARY NOT NULL"); + } + + # change interest.interest key to being unique, if it's not already + { + my $sth = $dbh->prepare("SHOW INDEX FROM interests"); + $sth->execute; + while (my $i = $sth->fetchrow_hashref) { + if ($i->{'Key_name'} eq "interest" && $i->{'Non_unique'}) { + do_alter("interests", "ALTER IGNORE TABLE interests ". + "DROP INDEX interest, ADD UNIQUE interest (interest)"); + last; + } + } + } + + if (column_type("supportcat", "scope") eq "") + { + do_alter("supportcat", + "ALTER IGNORE TABLE supportcat ADD scope ENUM('general', 'local') ". + "NOT NULL DEFAULT 'general', ADD UNIQUE (catkey)"); + } + + # convert 'all' arguments to '*' + if (table_relevant("priv_map") && !check_dbnote("privcode_all_to_*")) { + + # arg isn't keyed, but this table is only a couple thousand rows + do_sql("UPDATE priv_map SET arg='*' WHERE arg='all'"); + + set_dbnote("privcode_all_to_*", 1); + } + + # convert 'wizard' s2 styles to 'wizard-uniq' + if (table_relevant("s2styles") && !check_dbnote("s2style-wizard-update")) { + + # set_dbnote will return true if $opt_sql is set and it sets + # the note successfully. only then do we run the wizard updater + set_dbnote("s2style-wizard-update", 1) && + system("$ENV{'LJHOME'}/bin/upgrading/s2style-wizard-update.pl"); + } + + # this never ended up being useful, and just freaked people out unnecessarily. + if (column_type("user", "track")) { + do_alter("user", "ALTER TABLE user DROP track"); + } + + # need more choices (like "Y" for sYndicated journals) + if (column_type("user", "journaltype") =~ /enum/i) { + do_alter("user", "ALTER TABLE user MODIFY journaltype CHAR(1) NOT NULL DEFAULT 'P'"); + } + + unless (column_type("syndicated", "laststatus")) { + do_alter("syndicated", + "ALTER TABLE syndicated ADD laststatus VARCHAR(80), ADD lastnew DATETIME"); + } + + # change themedata. key to being unique, if it's not already + unless (index_name("themedata", "UNIQUE:themeid-coltype")) { + do_alter("themedata", "ALTER IGNORE TABLE themedata ". + "DROP KEY themeid, MODIFY coltype VARCHAR(30) NOT NULL, ". + "ADD UNIQUE `thuniq` (themeid, coltype)"); + } + + unless (column_type("syndicated", "numreaders")) { + do_alter("syndicated", + "ALTER TABLE syndicated ". + "ADD numreaders MEDIUMINT, ADD INDEX (numreaders)"); + } + + if (column_type("community", "ownerid")) + { + do_alter("community", + "ALTER TABLE community DROP ownerid"); + } + + # if it exists, but it's the old way, just kill it. + if (column_type("weekuserusage", "ubefore") && ! column_type("weekuserusage", "uafter")) { + do_sql("DROP TABLE weekuserusage"); + create_table("weekuserusage"); + } + + unless (column_type("userproplist", "cldversion")) { + do_alter("userproplist", + "ALTER TABLE userproplist ADD cldversion TINYINT UNSIGNED NOT NULL AFTER indexed"); + } + + unless (column_type("authactions", "used") && + index_name("authactions", "INDEX:userid") && + index_name("authactions", "INDEX:datecreate")) { + + do_alter("authactions", + "ALTER TABLE authactions " . + "ADD used enum('Y', 'N') DEFAULT 'N' AFTER arg1, " . + "ADD INDEX(userid), ADD INDEX(datecreate)"); + } + + unless (column_type("s2styles", "modtime")) { + do_alter("s2styles", + "ALTER TABLE s2styles ADD modtime INT UNSIGNED NOT NULL AFTER name"); + } + + if (column_type("acctinvite", "reason") eq "varchar(20)") { + do_alter("acctinvite", + "ALTER TABLE acctinvite MODIFY reason VARCHAR(40)"); + } + + # Add BLOB flag to proplist + unless (column_type("userproplist", "datatype") =~ /blobchar/) { + if (column_type("userproplist", "is_blob")) { + do_alter("userproplist", + "ALTER TABLE userproplist DROP is_blob"); + } + do_alter("userproplist", + "ALTER TABLE userproplist MODIFY datatype ENUM('char','num','bool','blobchar') NOT NULL DEFAULT 'char'"); + } + + if (column_type("challenges", "count") eq "") + { + do_alter("challenges", + "ALTER TABLE challenges ADD ". + "count int(5) UNSIGNED NOT NULL DEFAULT 0 AFTER challenge"); + } + + if (column_type("userblob", "length") =~ /mediumint/) + { + do_alter("userblob", "ALTER TABLE userblob MODIFY length INT UNSIGNED"); + } + + unless (index_name("support", "INDEX:requserid")) { + do_alter("support", "ALTER IGNORE TABLE support ADD INDEX (requserid), ADD INDEX (reqemail)"); + } + + unless (column_type("community", "membership") =~ /moderated/i) { + do_alter("community", "ALTER TABLE community MODIFY COLUMN " . + "membership ENUM('open','closed','moderated') DEFAULT 'open' NOT NULL"); + } + + if (column_type("userproplist", "multihomed") eq '') { + do_alter("userproplist", "ALTER TABLE userproplist " . + "ADD multihomed ENUM('1', '0') NOT NULL DEFAULT '0' AFTER cldversion"); + } + + if (index_name("moodthemedata", "INDEX:moodthemeid")) { + do_alter("moodthemedata", "ALTER IGNORE TABLE moodthemedata DROP KEY moodthemeid"); + } + + if (column_type("userpic2", "flags") eq '') { + do_alter("userpic2", "ALTER TABLE userpic2 " . + "ADD flags tinyint(1) unsigned NOT NULL default 0 AFTER comment, " . + "ADD location enum('blob','disk','mogile') default NULL AFTER flags"); + } + + if (column_type("userblob", "blobid") =~ /mediumint/) { + do_alter("userblob", "ALTER TABLE userblob MODIFY blobid INT UNSIGNED NOT NULL"); + } + + if (column_type("counter", "max") =~ /mediumint/) { + do_alter("counter", "ALTER TABLE counter MODIFY max INT UNSIGNED NOT NULL DEFAULT 0"); + } + + if (column_type("userpic2", "url") eq '') { + do_alter("userpic2", "ALTER TABLE userpic2 " . + "ADD url VARCHAR(255) default NULL AFTER location"); + } + + unless (column_type("spamreports", "posttime") ne '') { + do_alter("spamreports", "ALTER TABLE spamreports ADD COLUMN posttime INT(10) UNSIGNED " . + "NOT NULL AFTER reporttime, ADD COLUMN state ENUM('open', 'closed') DEFAULT 'open' " . + "NOT NULL AFTER posttime"); + } + + if (column_type("captchas", "location") eq '') { + do_alter("captchas", "ALTER TABLE captchas " . + "ADD location ENUM('blob','mogile') DEFAULT NULL AFTER type"); + } + + if (column_type("spamreports", "report_type") eq '') { + do_alter("spamreports", "ALTER TABLE spamreports " . + "ADD report_type ENUM('entry','comment') NOT NULL DEFAULT 'comment' " . + "AFTER posterid"); + } + + if (column_type("commenturls", "ip") eq '') { + do_alter("commenturls", + "ALTER TABLE commenturls " . + "ADD ip VARCHAR(15) DEFAULT NULL " . + "AFTER journalid"); + } + + if (column_type("sessions", "exptype") !~ /once/) { + do_alter("sessions", + "ALTER TABLE sessions CHANGE COLUMN exptype ". + "exptype ENUM('short', 'long', 'once') NOT NULL"); + } + + if (column_type("ml_items", "itid") =~ /auto_increment/) { + do_alter("ml_items", + "ALTER TABLE ml_items MODIFY COLUMN " . + "itid MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + if (column_type("ml_text", "txtid") =~ /auto_increment/) { + do_alter("ml_text", + "ALTER TABLE ml_text MODIFY COLUMN " . + "txtid MEDIUMINT UNSIGNED NOT NULL DEFAULT 0"); + } + + unless (column_type("syndicated", "oldest_ourdate")) { + do_alter("syndicated", + "ALTER TABLE syndicated ADD oldest_ourdate DATETIME AFTER lastnew"); + } + + if (column_type("sessions", "userid") =~ /mediumint/) { + do_alter("sessions", + "ALTER TABLE sessions MODIFY COLUMN userid INT UNSIGNED NOT NULL"); + } + + +}); + +1; # return true diff --git a/livejournal/bin/upgrading/update-db.pl b/livejournal/bin/upgrading/update-db.pl new file mode 100755 index 0000000..7ebd7ce --- /dev/null +++ b/livejournal/bin/upgrading/update-db.pl @@ -0,0 +1,807 @@ +#!/usr/bin/perl +# +# This program will bring your LiveJournal database schema up-to-date +# + +use strict; +use lib "$ENV{LJHOME}/cgi-bin"; + +use Getopt::Long; +use File::Path (); +use File::Basename (); +use File::Copy (); +use Image::Size (); +BEGIN { require "ljlib.pl"; + require "ljviews.pl"; } +use LJ::S2; +use MogileFS; + +my $opt_sql = 0; +my $opt_drop = 0; +my $opt_pop = 0; +my $opt_confirm = ""; +my $opt_skip = ""; +my $opt_help = 0; +my $cluster = 0; # by default, upgrade master. +my $opt_listtables; +my $opt_forcebuild = 0; +my $opt_compiletodisk = 0; +my $opt_innodb; +exit 1 unless +GetOptions("runsql" => \$opt_sql, + "drop" => \$opt_drop, + "populate" => \$opt_pop, + "confirm=s" => \$opt_confirm, + "cluster=s" => \$cluster, + "skip=s" => \$opt_skip, + "help" => \$opt_help, + "listtables" => \$opt_listtables, + "forcebuild|fb" => \$opt_forcebuild, + "ctd" => \$opt_compiletodisk, + "innodb" => \$opt_innodb, + ); + +if ($opt_help) { + die "Usage: update-db.pl + -r --runsql Actually do the SQL, instead of just showing it. + -p --populate Populate the database with the latest required base data. + -d --drop Drop old unused tables (default is to never) + --cluster= Upgrade cluster number (defaut,0 is global cluster) + --cluster=,, + --cluster=user Update user clusters + --cluster=all Update user clusters, and global + -l --listtables Print used tables, one per line. +"; +} + +## make sure $LJHOME is set so we can load & run everything +unless (-d $ENV{'LJHOME'}) { + die "LJHOME environment variable is not set, or is not a directory.\n". + "You must fix this before you can run this database update script."; +} + +die "Can't --populate a cluster" if $opt_pop && $cluster; + +my @clusters; +foreach my $cl (split(/,/, $cluster)) { + die "Invalid cluster spec: $cl\n" unless + $cl =~ /^\s*((\d+)|all|user)\s*$/; + if ($cl eq "all") { push @clusters, 0, @LJ::CLUSTERS; } + elsif ($cl eq "user") { push @clusters, @LJ::CLUSTERS; } + else { push @clusters, $1; } +} +@clusters = (0) unless @clusters; + +my %status; # clusterid -> string +my %clustered_table; # $table -> 1 +my $sth; +my %table_exists; # $table -> 1 +my %table_unknown; # $table -> 1 +my %table_create; # $table -> $create_sql +my %table_drop; # $table -> 1 +my %table_status; # $table -> { SHOW TABLE STATUS ... row } +my %post_create; # $table -> [ [ $action, $what ]* ] +my %coltype; # $table -> { $col -> $type } +my %indexname; # $table -> "INDEX"|"UNIQUE" . ":" . "col1-col2-col3" -> "PRIMARY" | index_name +my @alters; +my $dbh; + +CLUSTER: foreach my $cluster (@clusters) { + print "Updating cluster: $cluster\n" unless $opt_listtables; + ## make sure we can connect + $dbh = $cluster ? LJ::get_cluster_master($cluster) : LJ::get_db_writer(); + unless ($dbh) { + $status{$cluster} = "ERROR: Can't connect to the database (clust\#$cluster), so I can't update it."; + next CLUSTER; + } + + # reset everything + %clustered_table = %table_exists = %table_unknown = + %table_create = %table_drop = %post_create = + %coltype = %indexname = %table_status = (); + @alters = (); + + ## figure out what tables already exist (but not details of their structure) + $sth = $dbh->prepare("SHOW TABLES"); + $sth->execute; + while (my ($table) = $sth->fetchrow_array) { + next if $table =~ /^access\d+$/; + $table_exists{$table} = 1; + } + %table_unknown = %table_exists; # for now, later we'll delete from table_unknown + + ## very important that local is run first! (it can define tables that + ## the site-wide would drop if it didn't know about them already) + + my $load_datfile = sub { + my $file = shift; + my $local = shift; + return if $local && ! -e $file; + open(F, $file) or die "Can't find database update file at $file\n"; + my $data; + { + local $/ = undef; + $data = ; + } + close F; + eval $data; + die "Can't run $file: $@\n" if $@; + return 1; + }; + + $load_datfile->("$LJ::HOME/bin/upgrading/update-db-local.pl", 1); + $load_datfile->("$LJ::HOME/bin/upgrading/update-db-general.pl"); + + foreach my $t (sort keys %table_create) { + delete $table_drop{$t} if ($table_drop{$t}); + print "$t\n" if $opt_listtables; + } + exit if $opt_listtables; + + foreach my $t (keys %table_drop) { + delete $table_unknown{$t}; + } + + foreach my $t (keys %table_unknown) + { + print "# Warning: unknown live table: $t\n"; + } + + ## create tables + foreach my $t (keys %table_create) + { + next if $table_exists{$t}; + create_table($t); + } + + ## drop tables + foreach my $t (keys %table_drop) + { + next unless $table_exists{$t}; + drop_table($t); + } + + ## do all the alters + foreach my $s (@alters) + { + $s->($dbh, $opt_sql); + } + + $status{$cluster} = "OKAY"; +} + +print "\ncluster: status\n"; +foreach my $clid (sort { $a <=> $b } keys %status) { + printf "%7d: %s\n", $clid, $status{$clid}; +} +print "\n"; + +if ($opt_pop) +{ + my $made_system; + + # system user + my $su = LJ::load_user("system"); + unless ($su) { + print "System user not found. Creating with random password.\n"; + my $pass = LJ::make_auth_code(10); + LJ::create_account({ 'user' => 'system', + 'name' => 'System Account', + 'password' => $pass }) + || die "Failed to create system user."; + $su = LJ::load_user("system") || die "Failed to load the newly created system user."; + $made_system = 1; + } + + # S1 + print "Populating public system styles (S1):\n"; + require "$ENV{'LJHOME'}/bin/upgrading/s1style-rw.pl"; + my $ss = s1styles_read(); + foreach my $uniq (sort keys %$ss) { + + my $s = $ss->{$uniq}; + my $existing = LJ::S1::check_dup_style($su, $s->{'type'}, $s->{'styledes'}); + + # update + if ($existing) { + if ($LJ::DONT_TOUCH_STYLES) { + next; + } + if ( LJ::S1::update_style($existing->{'styleid'}, + { map { $_, $s->{$_} } qw(formatdata is_embedded is_colorfree) }) ) { + print " $uniq: "; + print "updated \#$existing->{'styleid'}\n"; + } + next; + } + + # insert new + my %opts = ( "is_public" => 'Y', "opt_cache" => 'Y', + map { $_, $s->{$_} } qw(styledes type formatdata is_embedded is_colorfree lastupdate)); + LJ::S1::create_style($su, \%opts) + or die "Error: unable to create style! Database potentially unavailable?"; + print " $uniq: "; + print "added\n"; + } + + # delete s1pubstyc from memcache + LJ::MemCache::delete("s1pubstyc"); + + # S2 + print "Populating public system styles (S2):\n"; + { + my $LD = "s2layers"; # layers dir + + my $sysid = $su->{'userid'}; + + # find existing re-distributed layers that are in the database + # and their styleids. + my $existing = LJ::S2::get_public_layers($sysid); + + my %known_id; + chdir "$ENV{'LJHOME'}/bin/upgrading" or die; + my %layer; # maps redist_uniq -> { 'type', 'parent' (uniq), 'id' (s2lid) } + + my $compile = sub { + my ($base, $type, $parent, $s2source) = @_; + return unless $s2source =~ /\S/; + + my $id = $existing->{$base} ? $existing->{$base}->{'s2lid'} : 0; + unless ($id) { + my $parentid = 0; + $parentid = $layer{$parent}->{'id'} unless $type eq "core"; + # allocate a new one. + $dbh->do("INSERT INTO s2layers (s2lid, b2lid, userid, type) ". + "VALUES (NULL, $parentid, $sysid, ?)", undef, $type); + die $dbh->errstr if $dbh->err; + $id = $dbh->{'mysql_insertid'}; + if ($id) { + $dbh->do("INSERT INTO s2info (s2lid, infokey, value) VALUES (?,'redist_uniq',?)", + undef, $id, $base); + } + } + die "Can't generate ID for '$base'" unless $id; + + # remember it so we don't delete it later. + $known_id{$id} = 1; + + $layer{$base} = { + 'type' => $type, + 'parent' => $parent, + 'id' => $id, + }; + + my $parid = $layer{$parent}->{'id'}; + + # see if source changed + my $md5_source = Digest::MD5::md5_hex($s2source); + my $md5_exist = $dbh->selectrow_array("SELECT MD5(s2code) FROM s2source WHERE s2lid=?", undef, $id); + + # skip compilation if source is unchanged and parent wasn't rebuilt. + return if $md5_source eq $md5_exist && ! $layer{$parent}->{'built'} && ! $opt_forcebuild; + + print "$base($id) is $type"; + if ($parid) { print ", parent = $parent($parid)"; }; + print "\n"; + + # we're going to go ahead and build it. + $layer{$base}->{'built'} = 1; + + # compile! + my $lay = { + 's2lid' => $id, + 'userid' => $sysid, + 'b2lid' => $parid, + 'type' => $type, + }; + my $error = ""; + my $compiled; + my $info; + die $error unless LJ::S2::layer_compile($lay, \$error, { + 's2ref' => \$s2source, + 'redist_uniq' => $base, + 'compiledref' => \$compiled, + 'layerinfo' => \$info, + }); + + if ($info->{'previews'}) { + my @pvs = split(/\s*\,\s*/, $info->{'previews'}); + my @vals; + foreach my $pv (@pvs) { + my $from = "$LD/$pv"; + next unless -e $from; + my $dir = File::Basename::dirname($pv); + File::Path::mkpath("$LJ::HOME/htdocs/img/s2preview/$dir"); + my $target = "$LJ::HOME/htdocs/img/s2preview/$pv"; + File::Copy::copy($from, $target); + my ($w, $h) = Image::Size::imgsize($target); + push @vals, "$pv|$w|$h"; + } + $dbh->do("REPLACE INTO s2info (s2lid, infokey, value) VALUES (?,?,?)", + undef, $id, '_previews', join(",", @vals)) if @vals; + } + + if ($opt_compiletodisk) { + open (CO, ">$LD/$base.pl") or die; + print CO $compiled; + close CO; + } + + # put raw S2 in database. + $dbh->do("REPLACE INTO s2source (s2lid, s2code) ". + "VALUES ($id, ?)", undef, $s2source); + die $dbh->errstr if $dbh->err; + }; + + my @layerfiles = ("s2layers.dat"); + while (@layerfiles) + { + my $file = shift @layerfiles; + next unless -e $file; + open (SL, $file) or die; + print "SOURCE: $file\n"; + while () + { + s/\#.*//; s/^\s+//; s/\s+$//; + next unless /\S/; + my ($base, $type, $parent) = split; + + if ($type eq "INCLUDE") { + push @layerfiles, $base; + next; + } + + if ($type ne "core" && ! defined $layer{$parent}) { + die "'$base' references unknown parent '$parent'\n"; + } + + # is the referenced $base file really an aggregation of + # many smaller layers? (likely themes, which tend to be small) + my $multi = ($type =~ s/\+$//); + + my $s2source; + open (L, "$LD/$base.s2") or die "Can't open file: $base.s2\n"; + + unless ($multi) { + while () { $s2source .= $_; } + $compile->($base, $type, $parent, $s2source); + } else { + my $curname; + while () { + if (/^\#NEWLAYER:\s*(\S+)/) { + my $newname = $1; + $compile->($curname, $type, $parent, $s2source); + $curname = $newname; + $s2source = ""; + } elsif (/^\#NEWLAYER/) { + die "Badly formatted \#NEWLAYER line"; + } else { + $s2source .= $_; + } + } + $compile->($curname, $type, $parent, $s2source); + } + close L; + } + close SL; + } + + # now, delete any system layers that don't below (from previous imports?) + my $sth = $dbh->prepare("SELECT s2lid FROM s2layers WHERE userid=?"); + $sth->execute($sysid); + while (my $id = $sth->fetchrow_array) { + next if $known_id{$id}; + LJ::S2::delete_layer($id); + } + } + + # check for old style external_foaf_url (indexed:1, cldversion:0) + my $prop = LJ::get_prop('user', 'external_foaf_url'); + if ($prop->{indexed} == 1 && $prop->{cldversion} == 0) { + print "Updating external_foaf_url userprop.\n"; + system("$ENV{'LJHOME'}/bin/upgrading/migrate-userprop.pl", 'external_foaf_url'); + } + + # base data + foreach my $file ("base-data.sql", "base-data-local.sql") { + my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; + next unless -e $ffile; + print "Populating database with $file.\n"; + open (BD, $ffile) or die "Can't open $file file\n"; + while (my $q = ) + { + chomp $q; # remove newline + next unless ($q =~ /^(REPLACE|INSERT|UPDATE)/); + chop $q; # remove semicolon + $dbh->do($q); + if ($dbh->err) { + print "$q\n"; + die "# ERROR: " . $dbh->errstr . "\n"; + } + } + close (BD); + } + + # moods + my $moodfile = "$ENV{'LJHOME'}/bin/upgrading/moods.dat"; + if (open(M, $moodfile)) { + print "Populating mood data.\n"; + + my %mood; # id -> [ mood, parent_id ] + my $sth = $dbh->prepare("SELECT moodid, mood, parentmood FROM moods"); + $sth->execute; + while (@_ = $sth->fetchrow_array) { $mood{$_[0]} = [ $_[1], $_[2] ]; } + + my %moodtheme; # name -> [ id, des ] + $sth = $dbh->prepare("SELECT moodthemeid, name, des FROM moodthemes WHERE is_public='Y'"); + $sth->execute; + while (@_ = $sth->fetchrow_array) { $moodtheme{$_[1]} = [ $_[0], $_[2] ]; } + + my $themeid; # current themeid (from existing db or just made) + my %data; # moodid -> "$url$width$height" (for equality test) + + while () { + chomp; + if (/^MOOD\s+(\d+)\s+(.+)\s+(\d+)\s*$/) { + my ($id, $mood, $parid) = ($1, $2, $3); + if (! $mood{$id} || $mood{$id}->[0] ne $mood || + $mood{$id}->[1] ne $parid) { + $dbh->do("REPLACE INTO moods (moodid, mood, parentmood) VALUES (?,?,?)", + undef, $id, $mood, $parid); + } + } + + if (/^MOODTHEME\s+(.+?)\s*:\s*(.+)$/) { + my ($name, $des) = ($1, $2); + %data = (); + if ($moodtheme{$name}) { + $themeid = $moodtheme{$name}->[0]; + if ($moodtheme{$name}->[1] ne $des) { + $dbh->do("UPDATE moodthemes SET des=? WHERE moodthemeid=?", undef, + $des, $themeid); + } + $sth = $dbh->prepare("SELECT moodid, picurl, width, height ". + "FROM moodthemedata WHERE moodthemeid=?"); + $sth->execute($themeid); + while (@_ = $sth->fetchrow_array) { + $data{$_[0]} = "$_[1]$_[2]$_[3]"; + } + } else { + $dbh->do("INSERT INTO moodthemes (ownerid, name, des, is_public) ". + "VALUES (?,?,?,'Y')", undef, $su->{'userid'}, $name, $des); + $themeid = $dbh->{'mysql_insertid'}; + die "Couldn't generate themeid for theme $name\n" unless $themeid; + } + next; + } + + if (/^(\d+)\s+(\S+)\s+(\d+)\s+(\d+)\s*$/) { + next unless $themeid; + my ($moodid, $url, $w, $h) = ($1, $2, $3, $4); + next if $data{$moodid} eq "$url$w$h"; + $dbh->do("REPLACE INTO moodthemedata (moodthemeid, moodid, picurl, width, height) ". + "VALUES (?,?,?,?,?)", undef, $themeid, $moodid, $url, $w, $h); + LJ::MemCache::delete([$themeid, "moodthemedata:$themeid"]); + } + } + close M; + } + + # clean out schema documentation for old/unknown tables + foreach my $tbl (qw(schemacols schematables)) { + my $sth = $dbh->prepare("SELECT DISTINCT tablename FROM $tbl"); + $sth->execute; + while (my $doctbl = $sth->fetchrow_array) { + next if $table_create{$doctbl}; + $dbh->do("DELETE FROM $tbl WHERE tablename=?", undef, $doctbl); + } + } + + # create/update the MogileFS database if we use it + if (defined $LJ::MOGILEFS_CONFIG{hosts}) { + # create an admin MogileFS object + my $mgd = MogileFS::Admin->new(hosts => $LJ::MOGILEFS_CONFIG{hosts}) + or die "Error: Unable to initalize MogileFS connection.\n"; + my $exists = $mgd->get_domains(); + print "Verifying MogileFS configuration...\n"; + + # verify domain exists? + my $domain = $LJ::MOGILEFS_CONFIG{domain}; + unless (defined $exists->{$domain}) { + print "\tCreating domain $domain...\n"; + $mgd->create_domain($domain) + or die "Error: Unable to create domain.\n"; + $exists->{$domain} = {}; + } + + # now start verifying classes + foreach my $class (keys %{$LJ::MOGILEFS_CONFIG{classes} || {}}) { + if ($exists->{$domain}->{$class}) { + if ($exists->{$domain}->{$class} != $LJ::MOGILEFS_CONFIG{classes}->{$class}) { + # update the mindevcount since it's changed + print "\tUpdating class $class...\n"; + $mgd->update_class($domain, $class, $LJ::MOGILEFS_CONFIG{classes}->{$class}) + or die "Error: Unable to update class.\n"; + } + } else { + # create it + print "\tCreating class $class...\n"; + $mgd->create_class($domain, $class, $LJ::MOGILEFS_CONFIG{classes}->{$class}) + or die "Error: Unable to create class.\n"; + } + } + } + + # convert users from dversion2 (no weekuserusage) + if (my $d2 = $dbh->selectrow_array("SELECT userid FROM user WHERE dversion=2 LIMIT 1")) { + $dbh->do("UPDATE user SET dversion=3 WHERE dversion=2"); + } + + # convert users from dversion3 (unclustered props) + if (my $d3 = $dbh->selectrow_array("SELECT userid FROM user WHERE dversion=3 LIMIT 1")) { + system("$ENV{'LJHOME'}/bin/upgrading/pop-clusterprops.pl", 3); + } + + # convert users from dversion4 (unclustered s1styles) + if (my $d4 = $dbh->selectrow_array("SELECT userid FROM user WHERE dversion=4 LIMIT 1")) { + system("$ENV{'LJHOME'}/bin/upgrading/d4d5-global.pl"); + } + + # convert users from dversion5 (unclustered memories and friend groups) + if (my $d5 = $dbh->selectrow_array("SELECT userid FROM user WHERE dversion=5 LIMIT 1")) { + system("$ENV{'LJHOME'}/bin/upgrading/d5d6-mkf.pl"); + } + + # convert users from dversion6 (unclustered user pictures) + if (my $d6 = $dbh->selectrow_array("SELECT userid FROM user WHERE dversion=6 LIMIT 1")) { + system("$ENV{'LJHOME'}/bin/upgrading/d6d7-userpics.pl"); + } + + print "\nThe system user was created with a random password.\nRun \$LJHOME/bin/upgrading/make_system.pl to change its password and grant the necessary privileges." + if $made_system; + print "\nRemember to also run:\n bin/upgrading/texttool.pl load\n\n"; +} + +# make sure they don't have cluster0 users (support for that will be going away) +# Note: now cluster 0 means expunged (as well as statuvis 'X'), so there's +# an option to disable the warning if you're running new code and know what's up. +unless ($LJ::NOWARN{'cluster0'}) { + my $cluster0 = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE clusterid=0"); + if ($cluster0) { + print "\n", "* "x35, "\nWARNING: You have $cluster0 users on cluster 0.\n\n". + "Support for that old database schema is deprecated and will be removed soon.\n". + "You should stop updating from CVS until you've moved all your users to a cluster \n". + "(probably cluster '1', which you can run on the same database). \n". + "See bin/moveucluster.pl for instructions.\n" . "* "x35 . "\n\n"; + } +} + +print "# Done.\n"; + +sub skip_opt +{ + return $opt_skip; +} + +sub do_sql +{ + my $sql = shift; + chomp $sql; + my $disp_sql = $sql; + $disp_sql =~ s/\bIN \(.+\)/IN (...)/g; + print "$disp_sql;\n"; + if ($opt_sql) { + print "# Running...\n"; + $dbh->do($sql); + if ($dbh->err) { + die "# ERROR: " . $dbh->errstr . "\n"; + } + } +} + +sub try_sql +{ + my $sql = shift; + print "$sql;\n"; + if ($opt_sql) { + print "# Non-critical SQL (upgrading only... it might fail)...\n"; + $dbh->do($sql); + if ($dbh->err) { + print "# Acceptable failure: " . $dbh->errstr . "\n"; + } + } +} + +sub do_alter +{ + my ($table, $sql) = @_; + return if $cluster && ! defined $clustered_table{$table}; + + do_sql($sql); + + # columns will have changed, so clear cache: + clear_table_info($table); +} + +sub create_table +{ + my $table = shift; + return if $cluster && ! defined $clustered_table{$table}; + + my $create_sql = $table_create{$table}; + if ($opt_innodb && $create_sql !~ /type=myisam/i) { + $create_sql .= " TYPE=INNODB"; + } + do_sql($create_sql); + + foreach my $pc (@{$post_create{$table}}) + { + my @args = @{$pc}; + my $ac = shift @args; + if ($ac eq "sql") { + print "# post-create SQL\n"; + do_sql($args[0]); + } + elsif ($ac eq "sqltry") { + print "# post-create SQL (necessary if upgrading only)\n"; + try_sql($args[0]); + } + elsif ($ac eq "code") { + print "# post-create code\n"; + $args[0]->($dbh, $opt_sql); + } + else { print "# don't know how to do \$ac = $ac"; } + } +} + +sub drop_table +{ + my $table = shift; + return if $cluster && ! defined $clustered_table{$table}; + + if ($opt_drop) { + do_sql("DROP TABLE $table"); + } else { + print "# Not dropping table $table to be paranoid (use --drop)\n"; + } +} + +sub mark_clustered +{ + foreach (@_) { + $clustered_table{$_} = 1; + } +} + +sub register_tablecreate +{ + my ($table, $create) = @_; + # we now know of it + delete $table_unknown{$table}; + + return if $cluster && ! defined $clustered_table{$table}; + + $table_create{$table} = $create; +} + +sub register_tabledrop +{ + my ($table) = @_; + $table_drop{$table} = 1; +} + +sub post_create +{ + my $table = shift; + while (my ($type, $what) = splice(@_, 0, 2)) { + push @{$post_create{$table}}, [ $type, $what ]; + } +} + +sub register_alter +{ + my $sub = shift; + push @alters, $sub; +} + +sub clear_table_info +{ + my $table = shift; + delete $coltype{$table}; + delete $indexname{$table}; + delete $table_status{$table}; +} + +sub load_table_info +{ + my $table = shift; + + clear_table_info($table); + + my $sth = $dbh->prepare("DESCRIBE $table"); + $sth->execute; + while (my $row = $sth->fetchrow_hashref) { + my $type = $row->{'Type'}; + $type .= " $1" if $row->{'Extra'} =~ /(auto_increment)/i; + $coltype{$table}->{ $row->{'Field'} } = lc($type); + } + + # current physical table properties + $table_status{$table} = + $dbh->selectrow_hashref("SHOW TABLE STATUS LIKE '$table'"); + + $sth = $dbh->prepare("SHOW INDEX FROM $table"); + $sth->execute; + my %idx_type; # name -> "UNIQUE"|"INDEX" + my %idx_parts; # name -> [] + while (my $ir = $sth->fetchrow_hashref) { + $idx_type{$ir->{'Key_name'}} = $ir->{'Non_unique'} ? "INDEX" : "UNIQUE"; + push @{$idx_parts{$ir->{'Key_name'}}}, $ir->{'Column_name'}; + } + + foreach my $idx (keys %idx_type) { + my $val = "$idx_type{$idx}:" . join("-", @{$idx_parts{$idx}}); + $indexname{$table}->{$val} = $idx; + } +} + +sub index_name +{ + my ($table, $idx) = @_; # idx form is: INDEX:col1-col2-col3 + load_table_info($table) unless $indexname{$table}; + return $indexname{$table}->{$idx} || ""; +} + +sub table_relevant +{ + my $table = shift; + return 1 unless $cluster; + return 1 if $clustered_table{$table}; + return 0; +} + +sub column_type +{ + my ($table, $col) = @_; + load_table_info($table) unless $coltype{$table}; + my $type = $coltype{$table}->{$col}; + $type ||= ""; + return $type; +} + +sub table_status +{ + my ($table, $col) = @_; + load_table_info($table) unless $table_status{$table}; + + return $table_status{$table}->{$col} || ""; +} + +sub ensure_confirm +{ + my $area = shift; + + return 1 if ($opt_sql && ($opt_confirm eq "all" or + $opt_confirm eq $area)); + + print STDERR "To proceed with the necessary changes, rerun with -r --confirm=$area\n"; + return 0; +} + +sub set_dbnote +{ + my ($key, $value) = @_; + return unless $opt_sql && $key && $value; + + return $dbh->do("REPLACE INTO blobcache (bckey, dateupdate, value) VALUES (?,NOW(),?)", + undef, $key, $value); +} + +sub check_dbnote +{ + my $key = shift; + + return $dbh->selectrow_array("SELECT value FROM blobcache WHERE bckey=?", + undef, $key); +} + diff --git a/livejournal/bin/weblog-summarize.pl b/livejournal/bin/weblog-summarize.pl new file mode 100755 index 0000000..31083d1 --- /dev/null +++ b/livejournal/bin/weblog-summarize.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $lock = LJ::locker()->trylock("weblog-summarize"); +exit 0 unless $lock; +print "Starting.\n"; + +my %name; +while () { + next unless /(\S+)\s*\-\s*(.+)/; + $name{$1} = $2; +} + +my $db = LJ::get_dbh("logs"); + +my @tables; +my $sth = $db->prepare("SHOW TABLES LIKE 'access%'"); +$sth->execute; +push @tables, $_ while $_ = $sth->fetchrow_array; + +for (1..10*24) { pop @tables; } + +my $ct; +my $sth; + +$| = 1; + +foreach my $t (@tables) { + my $file = $t; + $file =~ s/^access//; + $file = "$LJ::HOME/var/stats-$file"; + next if -e "$file.gz"; + open (E, ">$file"); + + print "$t\n"; + + print " hits..."; + $ct = $db->selectrow_array("SELECT COUNT(*) FROM $t"); + print E "count\thits\t$ct\n"; + print $ct, "\n"; + + print " bytes..."; + $ct = $db->selectrow_array("SELECT SUM(bytes) FROM $t"); + print E "count\tbytes\t$ct\n"; + print $ct, "\n"; + + print " ljusers..."; + $ct = $db->selectrow_array("SELECT COUNT(DISTINCT ljuser) FROM $t"); + print E "count\tuniq_ljuser\t$ct\n"; + print $ct, "\n"; + + print " codepath...\n"; + $sth = $db->prepare("SELECT codepath, COUNT(*) FROM $t GROUP BY 1 ORDER BY 2 DESC"); + $sth->execute; + while (my ($p, $ct) = $sth->fetchrow_array) { + print E "codepath\t$p\t$ct\n"; + } + + print " status...\n"; + $sth = $db->prepare("SELECT status, COUNT(*) FROM $t GROUP BY 1 ORDER BY 2 DESC"); + $sth->execute; + while (my ($s, $ct) = $sth->fetchrow_array) { + print E "status\t$s\t$ct\n"; + } + + close E; + system("/bin/gzip", $file) and die "Error gzipping $t\n"; + $db->do("DROP TABLE $t"); +} + diff --git a/livejournal/bootstrap.pl b/livejournal/bootstrap.pl new file mode 100755 index 0000000..03fc2ef --- /dev/null +++ b/livejournal/bootstrap.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl +# + +use strict; +die "Must set \$LJHOME before running this.\n" + unless -d $ENV{'LJHOME'}; + +my $LJHOME = $ENV{'LJHOME'}; +my $mode = @ARGV[0]; + +if ($mode eq "") { + + chdir $LJHOME or die "Couldn't chdir to \$LJHOME directory.\n"; + + system("cvs/wcmtools/bin/multicvs.pl --conf=cvs/livejournal/cvs/multicvs.conf -c -s") + and die "Failed to run multicvs.pl ... do you have the cvs/ dir?\n"; + + print "done.\n"; + exit; +} + +if ($mode eq "makerelease") { + chdir $LJHOME or die; + my $path = $ENV{'RELDIR'}; + $path .= "/" if $path; + my @now = localtime; + my $ct = 0; + my $file; + do { + $file = sprintf("${path}livejournal-%04d%02d%02d%02d.tar.gz", $now[5]+1900, $now[4]+1, $now[3], $ct); + $ct++; + } while (-e $file); + + system("tar -zcvf $file README.txt bootstrap.pl cvs") and die; + + print "done.\n"; + exit; +} + +die "Unknown mode.\n"; diff --git a/livejournal/cgi-bin/Apache/DebateSuicide.pm b/livejournal/cgi-bin/Apache/DebateSuicide.pm new file mode 100755 index 0000000..669538b --- /dev/null +++ b/livejournal/cgi-bin/Apache/DebateSuicide.pm @@ -0,0 +1,96 @@ +#!/usr/bin/perl +# + +package Apache::DebateSuicide; + +use strict; +use Apache::Constants qw(:common); + +use vars qw($gtop); +our %known_parent; +our $ppid; + +# oh btw, this is totally linux-specific. gtop didn't work, so so much for portability. +sub handler +{ + my $r = shift; + return OK if $r->main; + return OK unless $LJ::HAVE_GTOP && $LJ::SUICIDE; + + my $meminfo; + return OK unless open (MI, "/proc/meminfo"); + $meminfo = join('', ); + close MI; + + my %meminfo; + while ($meminfo =~ m/(\w+):\s*(\d+)\skB/g) { + $meminfo{$1} = $2; + } + + my $memfree = $meminfo{'MemFree'} + $meminfo{'Cached'}; + return OK unless $memfree; + + my $goodfree = $LJ::SUICIDE_UNDER{$LJ::SERVER_NAME} || $LJ::SUICIDE_UNDER || 150_000; + return OK if $memfree > $goodfree; + + unless ($ppid) { + my $self = pid_info($$); + $ppid = $self->[3]; + } + + my $pids = child_info($ppid); + my @pids = keys %$pids; + + $gtop ||= GTop->new; + + my %stats; + my $sum_uniq = 0; + foreach my $pid (@pids) { + my $pm = $gtop->proc_mem($pid); + $stats{$pid} = [ $pm->rss - $pm->share, $pm ]; + $sum_uniq += $stats{$pid}->[0]; + } + + @pids = (sort { $stats{$b}->[0] <=> $stats{$a}->[0] } @pids, 0, 0); + + my $my_pid = $$; + if (grep { $my_pid == $_ } @pids[0,1]) { + my $my_use_k = $stats{$$}[0] >> 10; + $r->log_error("Suicide [$$]: system memory free = ${memfree}k; i'm big, using ${my_use_k}k") if $LJ::DEBUG{'suicide'}; + Apache::LiveJournal::db_logger($r) unless $r->pnotes('did_lj_logging'); + $r->child_terminate; + } + + return OK; +} + +sub pid_info { + my $pid = shift; + + open (F, "/proc/$pid/stat") or next; + $_ = ; + close(F); + my @f = split; + return \@f; +} + +sub child_info { + my $ppid = shift; + opendir(D, "/proc") or return undef; + my @pids = grep { /^\d+$/ } readdir(D); + closedir(D); + + my %ret; + foreach my $p (@pids) { + next if (defined $known_parent{$p} && + $known_parent{$p} != $ppid); + my $ary = pid_info($p); + my $this_ppid = $ary->[3]; + $known_parent{$p} = $this_ppid; + next unless $this_ppid == $ppid; + $ret{$p} = $ary; + } + return \%ret; +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal.pm b/livejournal/cgi-bin/Apache/LiveJournal.pm new file mode 100755 index 0000000..3818aeb --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal.pm @@ -0,0 +1,1508 @@ +#!/usr/bin/perl +# + +package Apache::LiveJournal; + +use strict; +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED HTTP_MOVED_PERMANENTLY + M_TRACE M_OPTIONS); +use Apache::File (); +use lib "$ENV{'LJHOME'}/cgi-bin"; +use Apache::LiveJournal::PalImg; +use LJ::S2; +use LJ::Blob; +use Apache::LiveJournal::Interface::Blogger; +use Apache::LiveJournal::Interface::AtomAPI; +use Apache::LiveJournal::Interface::S2; + +BEGIN { + $LJ::OPTMOD_ZLIB = eval "use Compress::Zlib (); 1;"; + $LJ::OPTMOD_XMLRPC = eval "use XMLRPC::Transport::HTTP (); 1;"; + + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl"; + require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl"; + if (%LJ::FOTOBILDER_IP) { + use Apache::LiveJournal::Interface::FotoBilder; + } +} + +my %RQ; # per-request data +my %USERPIC; # conf related to userpics +my %REDIR; +my $GTop; # GTop object (created if $LJ::LOG_GTOP is true) + +# Mapping of MIME types to image types understood by the blob functions. +my %MimeTypeMap = ( + 'image/gif' => 'gif', + 'image/jpeg' => 'jpg', + 'image/png' => 'png', +); +my %MimeTypeMapd6 = ( + 'G' => 'gif', + 'J' => 'jpg', + 'P' => 'png', +); + +$USERPIC{'cache_dir'} = "$ENV{'LJHOME'}/htdocs/userpics"; +$USERPIC{'use_disk_cache'} = -d $USERPIC{'cache_dir'}; +$USERPIC{'symlink'} = eval { symlink('',''); 1; }; + +# redirect data. +foreach my $file ('redirect.dat', 'redirect-local.dat') { + open (REDIR, "$ENV{'LJHOME'}/cgi-bin/$file") or next; + while () { + next unless (/^(\S+)\s+(\S+)/); + my ($src, $dest) = ($1, $2); + $REDIR{$src} = $dest; + } + close REDIR; +} + +my @req_hosts; # client IP, and/or all proxies, real or claimed + +# init handler (PostReadRequest) +sub handler +{ + my $r = shift; + + if ($LJ::SERVER_TOTALLY_DOWN) { + $r->handler("perl-script"); + $r->set_handlers(PerlHandler => [ \&totally_down_content ]); + return OK; + } + + # only perform this once in case of internal redirects + if ($r->is_initial_req) { + $r->push_handlers(PerlCleanupHandler => sub { %RQ = () }); + $r->push_handlers(PerlCleanupHandler => "Apache::LiveJournal::db_logger"); + $r->push_handlers(PerlCleanupHandler => "LJ::end_request"); + + if ($LJ::TRUST_X_HEADERS) { + # if we're behind a lite mod_proxy front-end, we need to trick future handlers + # into thinking they know the real remote IP address. problem is, it's complicated + # by the fact that mod_proxy did nothing, requiring mod_proxy_add_forward, then + # decided to do X-Forwarded-For, then did X-Forwarded-Host, so we have to deal + # with all permutations of versions, hence all the ugliness: + @req_hosts = ($r->connection->remote_ip); + if (my $forward = $r->header_in('X-Forwarded-For')) + { + my (@hosts, %seen); + foreach (split(/\s*,\s*/, $forward)) { + next if $seen{$_}++; + push @hosts, $_; + push @req_hosts, $_; + } + if (@hosts) { + my $real = pop @hosts; + $r->connection->remote_ip($real); + } + $r->header_in('X-Forwarded-For', join(", ", @hosts)); + } + + # and now, deal with getting the right Host header + if ($_ = $r->header_in('X-Host')) { + $r->header_in('Host', $_); + } elsif ($_ = $r->header_in('X-Forwarded-Host')) { + $r->header_in('Host', $_); + } + } + + # reload libraries that might've changed + if ($LJ::IS_DEV_SERVER) { + my %to_reload; + while (my ($file, $mod) = each %LJ::LIB_MOD_TIME) { + my $cur_mod = (stat($file))[9]; + next if $cur_mod == $mod; + $to_reload{$file} = 1; + } + my @key_del; + foreach (my ($key, $file) = each %INC) { + push @key_del, $key if $to_reload{$file}; + } + delete $INC{$_} foreach @key_del; + + foreach my $file (keys %to_reload) { + print STDERR "Reloading $file...\n"; + my $good = do $file; + if ($good) { + $LJ::LIB_MOD_TIME{$file} = (stat($file))[9]; + } else { + die "Failed to reload module [$file] due to error: $@\n"; + } + } + } + } + + $r->set_handlers(PerlTransHandler => [ \&trans ]); + + return OK; +} + +sub redir +{ + my ($r, $url, $code) = @_; + $r->content_type("text/html"); + $r->header_out(Location => $url); + return $code || REDIRECT; +} + +sub totally_down_content +{ + my $r = shift; + my $uri = $r->uri; + + if ($uri =~ m!^/interface/flat! || $uri =~ m!^/cgi-bin/log\.cg!) { + $r->content_type("text/plain"); + $r->send_http_header(); + $r->print("success\nFAIL\nerrmsg\n$LJ::SERVER_DOWN_MESSAGE"); + return OK; + } + + if ($uri =~ m!^/customview.cgi!) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print(""); + return OK; + } + + # FIXME: ljcom-specific, move to a hook; too lazy now. + if ($uri =~ m!^/paidaccounts/pp_notify\.bml!) { + $r->status(SERVER_ERROR); + } + + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("

    $LJ::SERVER_DOWN_SUBJECT

    $LJ::SERVER_DOWN_MESSAGE"); + return OK; +} + +sub blocked_bot +{ + my $r = shift; + + $r->status_line("403 Denied"); + $r->content_type("text/html"); + $r->send_http_header(); + my $subject = $LJ::BLOCKED_BOT_SUBJECT || "403 Denied"; + my $message = $LJ::BLOCKED_BOT_MESSAGE || "You don't have permission to view this page."; + $r->print("

    $subject

    $message"); + return OK; +} + +sub trans +{ + my $r = shift; + return DECLINED if ! $r->is_main || $r->method_number == M_OPTIONS; # don't deal with subrequests or OPTIONS + + my $uri = $r->uri; + my $args = $r->args; + my $args_wq = $args ? "?$args" : ""; + my $host = $r->header_in("Host"); + my $hostport = ($host =~ s/:\d+$//) ? $& : ""; + + # disable TRACE (so scripts on non-LJ domains can't invoke + # a trace to get the LJ cookies in the echo) + return FORBIDDEN if $r->method_number == M_TRACE; + + # If the configuration says to log statistics and GTop is available, mark + # values before the request runs so it can be turned into a delta later + if ( $LJ::LOG_GTOP && $LJ::HAVE_GTOP ) { + $GTop ||= new GTop; + $r->pnotes( 'gtop_cpu' => $GTop->cpu ); + $r->pnotes( 'gtop_mem' => $GTop->proc_mem($$) ); + } + + LJ::start_request(); + LJ::procnotify_check(); + S2::set_domain('LJ'); + + my $is_ssl = $LJ::IS_SSL = LJ::run_hook("ssl_check", { + r => $r, + }); + + # handle uniq cookies + if ($LJ::UNIQ_COOKIES && $r->is_initial_req) { + + # if cookie exists, check for sysban + my ($uniq, $uniq_time); + if (Apache->header_in("Cookie") =~ /\bljuniq\s*=\s*([a-zA-Z0-9]{15}):(\d+)/) { + ($uniq, $uniq_time) = ($1, $2); + $r->notes("uniq" => $uniq); + if (LJ::sysban_check('uniq', $uniq) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + }; + } + + # if no cookie, create one. if older than a day, revalidate + my $now = time(); + my $DAY = 3600*24; + if (! $uniq || $now - $uniq_time > $DAY) { + $uniq ||= LJ::rand_chars(15); + + # set uniq cookies for all cookie_domains + my @domains = ref $LJ::COOKIE_DOMAIN ? @$LJ::COOKIE_DOMAIN : ($LJ::COOKIE_DOMAIN); + foreach my $dom (@domains) { + $r->err_headers_out->add("Set-Cookie" => + "ljuniq=$uniq:$now; " . + "expires=" . LJ::time_to_cookie($now + $DAY*60) . "; " . + ($dom ? "domain=$dom; " : "") . "path=/"); + } + } + } + + # only allow certain pages over SSL + if ($is_ssl) { + if ($uri =~ m!^/interface/!) { + # handled later + } elsif ($LJ::SSLDOCS && $uri !~ m!(\.\.|\%|\.\/)!) { + my $file = "$LJ::SSLDOCS/$uri"; + unless (-e $file) { + # no such file. send them to the main server if it's a GET. + return $r->method eq 'GET' ? redir($r, "$LJ::SITEROOT$uri$args_wq") : 404; + } + if (-d _) { $file .= "/index.bml"; } + $file =~ s!/{2,}!/!g; + $r->filename($file); + $LJ::IMGPREFIX = "/img"; + $LJ::STATPREFIX = "/stc"; + return OK; + } + return FORBIDDEN; + } else { + $LJ::IMGPREFIX = $LJ::IMGPREFIX_BAK; + $LJ::STATPREFIX = $LJ::STATPREFIX_BAK; + } + + # let foo.com still work, but redirect to www.foo.com + if ($LJ::DOMAIN_WEB && $r->method eq "GET" && + $host eq $LJ::DOMAIN && $LJ::DOMAIN_WEB ne $LJ::DOMAIN) + { + my $url = "$LJ::SITEROOT$uri"; + $url .= "?" . $args if $args; + return redir($r, $url); + } + + # check for sysbans on ip address + foreach my $ip (@req_hosts) { + if (LJ::sysban_check('ip', $ip) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + } + } + if (LJ::run_hook("forbid_request", $r) && index($uri, $LJ::BLOCKED_BOT_URI) != 0) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&blocked_bot ); + return OK; + } + + # see if we should setup a minimal scheme based on the initial part of the + # user-agent string; FIXME: maybe this should do more than just look at the + # initial letters? + if (my $ua = $r->header_in('User-Agent')) { + if (($ua =~ /^([a-z]+)/i) && $LJ::MINIMAL_USERAGENT{$1}) { + $r->notes('use_minimal_scheme' => 1); + $r->notes('bml_use_scheme' => $LJ::MINIMAL_BML_SCHEME); + } + } + + # now we know that the request is going to succeed, so do some checking if they have a defined + # referer. clients and such don't, so ignore them. + my $referer = $r->header_in("Referer"); + if ($referer && $r->method eq 'POST' && !LJ::check_referer('', $referer)) { + $r->log_error("REFERER WARNING: POST to $uri from $referer"); + } + + my %GET = $r->args; + + # anti-squatter checking + if ($LJ::ANTI_SQUATTER && $r->method eq "GET") { + my $ref = $r->header_in("Referer"); + if ($ref && index($ref, $LJ::SITEROOT) != 0) { + # FIXME: this doesn't anti-squat user domains yet + if ($uri !~ m!^/404!) { + # So hacky! (see note below) + $LJ::SQUAT_URL = "http://$host$hostport$uri$args_wq"; + } else { + # then Apache's 404 handler takes over and we get here + # FIXME: why?? why doesn't it just work to return OK + # the first time with the handlers pushed? nothing + # else requires this chicanery! + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&anti_squatter); + } + return OK; + } + } + + my $journal_view = sub { + my $opts = shift; + $opts ||= {}; + + my $orig_user = $opts->{'user'}; + $opts->{'user'} = LJ::canonical_username($opts->{'user'}); + + if ($opts->{'mode'} eq "info") { + return redir($r, "$LJ::SITEROOT/userinfo.bml?user=$opts->{'user'}"); + } + + %RQ = %$opts; + + # redirect communities to /community/ + my $u = LJ::load_user($opts->{'user'}); + if ($u && $u->{'journaltype'} eq "C" && + ($opts->{'vhost'} eq "" || $opts->{'vhost'} eq "tilde")) { + my $newurl = $uri; + $newurl =~ s!^/(users/|~)\Q$orig_user\E!!; + $newurl = "$LJ::SITEROOT/community/$opts->{'user'}$newurl$args_wq"; + return redir($r, $newurl); + } + + # redirect case errors in username + if ($orig_user ne lc($orig_user)) { + my $url = LJ::journal_base($opts->{'user'}, $opts->{'vhost'}) . + "/$opts->{'mode'}$opts->{'pathextra'}$args_wq"; + return redir($r, $url); + } + + if ($opts->{mode} eq "data" && $opts->{pathextra} =~ m!^/(\w+)(/.*)?!) { + if (my $handler = LJ::run_hook("data_handler:$1", $RQ{'user'}, $2)) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => $handler); + return OK; + } + } + + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&journal_content); + return OK; + }; + + my $determine_view = sub { + my ($user, $vhost, $uuri) = @_; + my $mode = undef; + my $pe; + + if ($uuri =~ m#^/(\d+)\.html$#) { + if ($GET{'mode'} eq "reply" || $GET{'replyto'}) { + $mode = "reply"; + } else { + $mode = "entry"; + } + } elsif ($uuri =~ m#^/(\d\d\d\d)(?:/(\d\d)(?:/(\d\d))?)?(/?)$#) { + my ($year, $mon, $day, $slash) = ($1, $2, $3, $4); + unless ($slash) { + return redir($r, "http://$host$hostport$uri/"); + } + + # the S1 ljviews code looks at $opts->{'pathextra'}, because + # that's how it used to do it, when the pathextra was /day[/yyyy/mm/dd] + $pe = $uuri; + + if (defined $day) { + $mode = "day"; + } elsif (defined $mon) { + $mode = "month"; + } else { + $mode = "calendar"; + } + + } elsif ($uuri =~ m! + /([a-z\_]+)? # optional / + (.*) # path extra: /FriendGroup, for example + !x && ($1 eq "" || defined $LJ::viewinfo{$1})) + { + ($mode, $pe) = ($1, $2); + $mode ||= "" unless length $pe; # if no pathextra, then imply 'lastn' + + # redirect old-style URLs to new versions: + if ($mode =~ /day|calendar/ && $pe =~ m!^/\d\d\d\d!) { + my $newuri = $uri; + $newuri =~ s!$mode/(\d\d\d\d)!$1!; + return redir($r, "http://$host$hostport$newuri"); + } elsif ($mode eq 'rss') { + # code 301: moved permanently, update your links. + return redir($r, LJ::journal_base($user) . "/data/rss$args_wq", 301); + } elsif ($mode eq 'pics' && $LJ::REDIRECT_ALLOWED{$LJ::FB_DOMAIN}) { + # redirect to a user's gallery + my $url = "$LJ::FB_SITEROOT/$user"; + return redir($r, $url); + } + } elsif (($vhost eq "users" || $vhost =~ /^other:/) && + $uuri eq "/robots.txt") { + $mode = "robots_txt"; + } + + return undef unless defined $mode; + return $journal_view->({'vhost' => $vhost, + 'mode' => $mode, + 'args' => $args, + 'pathextra' => $pe, + 'user' => $user }); + }; + + # flag if we hit a domain that was configured as a "normal" domain + # which shouldn't be inspected for its domain name. (for use with + # Akamai and other CDN networks...) + my $skip_domain_checks = 0; + + # user domains + if ($LJ::USER_VHOSTS && + $host =~ /^([\w\-]{1,15})\.\Q$LJ::USER_DOMAIN\E$/ && + $1 ne "www" && + + # 1xx: info, 2xx: success, 3xx: redirect, 4xx: client err, 5xx: server err + # let the main server handle any errors + $r->status < 400) + { + my $user = $1; + + # see if the "user" is really functional code + my $func = $LJ::SUBDOMAIN_FUNCTION{$user}; + + if ($func eq "normal") { + # site admin wants this domain to be ignored and treated as if it + # were "www", so set this flag so the custom "OTHER_VHOSTS" check + # below fails. + $skip_domain_checks = 1; + + } elsif ($uri =~ m!^/(?:talkscreen|delcomment)\.bml!) { + # these URLs need to always work for the javascript comment management code + # (JavaScript can't do cross-domain XMLHttpRequest calls) + $skip_domain_checks = 1; + + } elsif ($func) { + my $code = { + 'userpics' => \&userpic_trans, + 'files' => \&files_trans, + }; + return $code->{$func}->($r) if $code->{$func}; + return 404; # bogus ljconfig + } else { + my $view = $determine_view->($user, "users", $uri); + return $view if defined $view; + return 404; + } + } + + # custom used-specified domains + if ($LJ::OTHER_VHOSTS && !$skip_domain_checks && + $host ne $LJ::DOMAIN_WEB && + $host ne $LJ::DOMAIN && $host =~ /\./ && + $host =~ /[^\d\.]/) + { + my $dbr = LJ::get_db_reader(); + my $checkhost = lc($host); + $checkhost =~ s/^www\.//i; + $checkhost = $dbr->quote($checkhost); + # FIXME: memcache this? + my $user = $dbr->selectrow_array(qq{ + SELECT u.user FROM useridmap u, domains d WHERE + u.userid=d.userid AND d.domain=$checkhost + }); + return 404 unless $user; + + my $view = $determine_view->($user, "other:$host$hostport", $uri); + return $view if defined $view; + return 404; + } + + # userpic + return userpic_trans($r) if $uri =~ m!^/userpic/!; + + # front page journal + if ($LJ::FRONTPAGE_JOURNAL) { + my $view = $determine_view->($LJ::FRONTPAGE_JOURNAL, "front", $uri); + return $view if defined $view; + } + + # normal (non-domain) journal view + if (! $LJ::ONLY_USER_VHOSTS && + $uri =~ m! + ^/(users\/|community\/|\~) # users/community/tilde + ([^/]*) # potential username + (.*)? # rest + !x) + { + my ($part1, $user, $rest) = ($1, $2, $3); + + # get what the username should be + my $cuser = LJ::canonical_username($user); + return DECLINED unless length($cuser); + + my $srest = $rest || '/'; + + # redirect to canonical username and/or add slash if needed + return redir($r, "http://$host$hostport/$part1$cuser$srest$args_wq") + if $cuser ne $user or not $rest; + + my $vhost = { 'users/' => '', 'community/' => 'community', + '~' => 'tilde' }->{$part1}; + + my $view = $determine_view->($user, $vhost, $rest); + return $view if defined $view; + } + + # protocol support + if ($uri =~ m!^/(?:interface/(\w+))|cgi-bin/log\.cgi!) { + my $int = $1 || "flat"; + $r->handler("perl-script"); + if ($int eq "fotobilder") { + return 403 unless $LJ::FOTOBILDER_IP{$r->connection->remote_ip}; + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::Interface::FotoBilder::handler); + return OK; + } + if ($int =~ /^flat|xmlrpc|blogger|atom(?:api)?$/) { + $RQ{'interface'} = $int; + $RQ{'is_ssl'} = $is_ssl; + $r->push_handlers(PerlHandler => \&interface_content); + return OK; + } + if ($int eq "s2") { + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::Interface::S2::handler); + return OK; + } + return 404; + } + + # customview + if ($uri =~ m!^/customview\.cgi!) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&customview_content); + return OK; + } + + if ($uri =~ m!^/palimg/!) { + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&Apache::LiveJournal::PalImg::handler); + return OK; + } + + # redirected resources + if ($REDIR{$uri}) { + my $new = $REDIR{$uri}; + if ($r->args) { + $new .= ($new =~ /\?/ ? "&" : "?"); + $new .= $r->args; + } + return redir($r, $new, HTTP_MOVED_PERMANENTLY); + } + + # confirm + if ($uri =~ m!^/confirm/(\w+\.\w+)!) { + return redir($r, "$LJ::SITEROOT/register.bml?$1"); + } + + # approve + if ($uri =~ m!^/approve/(\w+\.\w+)!) { + return redir($r, "$LJ::SITEROOT/approve.bml?$1"); + } + + return FORBIDDEN if $uri =~ m!^/userpics!; + return DECLINED; +} + +sub userpic_trans +{ + my $r = shift; + return 404 unless $r->uri =~ m!^/(?:userpic/)?(\d+)/(\d+)$!; + my ($picid, $userid) = ($1, $2); + + $r->notes("codepath" => "img.userpic"); + + # we can safely do this without checking since we never re-use + # picture IDs and don't let the contents get modified + return HTTP_NOT_MODIFIED if $r->header_in('If-Modified-Since'); + + $RQ{'picid'} = $picid; + $RQ{'pic-userid'} = $userid; + + if ($USERPIC{'use_disk_cache'}) { + my @dirs_make; + my $file; + + if ($picid =~ /^\d*(\d\d)(\d\d\d)$/) { + push @dirs_make, ("$USERPIC{'cache_dir'}/$2", + "$USERPIC{'cache_dir'}/$2/$1"); + $file = "$USERPIC{'cache_dir'}/$2/$1/$picid-$userid"; + } else { + my $mod = sprintf("%03d", $picid % 1000); + push @dirs_make, "$USERPIC{'cache_dir'}/$mod"; + $file = "$USERPIC{'cache_dir'}/$mod/p$picid-$userid"; + } + + foreach (@dirs_make) { + next if -d $_; + mkdir $_, 0777; + } + + # set both, so we can compared later if they're the same, + # and thus know if directories were created (if not, + # apache will give us a pathinfo) + $RQ{'userpicfile'} = $file; + $r->filename($file); + } + + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => \&userpic_content); + return OK; +} + +sub userpic_content +{ + my $r = shift; + my $file = $r->filename; + + my $picid = $RQ{'picid'}; + my $userid = $RQ{'pic-userid'}+0; + + # will we try to use disk cache? + my $disk_cache = $USERPIC{'use_disk_cache'} && + $file eq $RQ{'userpicfile'}; + + my ($data, $lastmod); + my $need_cache; + + my $mime = "image/jpeg"; + my $set_mime = sub { + my $data = shift; + if ($data =~ /^GIF/) { $mime = "image/gif"; } + elsif ($data =~ /^\x89PNG/) { $mime = "image/png"; } + }; + my $size; + + my $send_headers = sub { + $r->content_type($mime); + $r->header_out("Content-length", $size+0); + $r->header_out("Cache-Control", "no-transform"); + $r->header_out("Last-Modified", LJ::time_to_http($lastmod)); + $r->send_http_header(); + }; + + # Load the user object and pic and make sure the picture is viewable + my $u = LJ::load_userid($userid); + return NOT_FOUND unless $u && $u->{'statusvis'} !~ /[XS]/; + + my %upics; + LJ::load_userpics(\%upics, [ $u, $picid ]); + my $pic = $upics{$picid} or return NOT_FOUND; + return NOT_FOUND if $pic->{'userid'} != $userid || $pic->{state} eq 'X'; + + # Read the mimetype from the pichash if dversion 7 + $mime = { 'G' => 'image/gif', + 'J' => 'image/jpeg', + 'P' => 'image/png', }->{$pic->{fmt}}; + + ### Handle reproxyable requests + + # For dversion 7+ and mogilefs userpics, follow this path + if ($pic->{location} eq 'M' ) { # 'M' for mogilefs + my $key = $u->mogfs_userpic_key( $picid ); + + if ( !$LJ::REPROXY_DISABLE{userpics} && + $r->header_in('X-Proxy-Capabilities') && + $r->header_in('X-Proxy-Capabilities') =~ m{\breproxy-file\b}i ) + { + my $memkey = [$picid, "mogp.up.$picid"]; + + my $zone = $r->header_in('X-MogileFS-Explicit-Zone') || undef; + $memkey->[1] .= ".$zone" if $zone; + + my $paths = LJ::MemCache::get($memkey); + unless ($paths) { + my @paths = LJ::mogclient()->get_paths( $key, { noverify => 1, zone => $zone }); + $paths = \@paths; + LJ::MemCache::add($memkey, $paths, 3600) if @paths; + } + + # reproxy url + if ($paths->[0] =~ m/^http:/) { + $r->header_out('X-REPROXY-URL', join(' ', @$paths)); + } + + # reproxy file + else { + $r->header_out('X-REPROXY-FILE', $paths->[0]); + } + + $send_headers->(); + } + + else { + my $data = LJ::mogclient()->get_file_data( $key ); + return NOT_FOUND unless $data; + $size = length $$data; + $send_headers->(); + $r->print( $$data ) unless $r->header_only; + } + + return OK; + } + + # dversion < 7 reproxy file path + if ( !$LJ::REPROXY_DISABLE{userpics} && + exists $LJ::PERLBAL_ROOT{userpics} && + $r->header_in('X-Proxy-Capabilities') && + $r->header_in('X-Proxy-Capabilities') =~ m{\breproxy-file\b}i ) + { + my ( + $root, + $fmt, + $path, + ); + + # Get the blobroot and load the pic hash + $root = $LJ::PERLBAL_ROOT{userpics}; + + # sometimes we don't want to reproxy userpics + unless ($LJ::USERPIC_REPROXY_DISABLE{$u->{clusterid}}) { + # Now ask the blob lib for the path to send to the reproxy + $fmt = ($u->{'dversion'} > 6) ? $MimeTypeMapd6{ $pic->{fmt} } : $MimeTypeMap{ $pic->{contenttype} }; + $path = LJ::Blob::get_rel_path( $root, $u, "userpic", $fmt, $picid ); + + $r->header_out( 'X-REPROXY-FILE', $path ); + $send_headers->(); + + return OK; + } + } + + # try to get it from disk if in disk-cache mode + if ($disk_cache) { + if (-s $r->finfo) { + $lastmod = (stat _)[9]; + $size = -s _; + my $fh = Apache::File->new($file); + my $magic; + read($fh, $magic, 4); + $set_mime->($magic); + $send_headers->(); + $r->print($magic); + $r->send_fd($fh); + $fh->close(); + return OK; + } else { + $need_cache = 1; + } + } + + # else, get it from db. + unless ($data) { + $lastmod = $pic->{'picdate'}; + + if ($LJ::USERPIC_BLOBSERVER) { + my $fmt = ($u->{'dversion'} > 6) ? $MimeTypeMapd6{ $pic->{fmt} } : $MimeTypeMap{ $pic->{contenttype} }; + $data = LJ::Blob::get($u, "userpic", $fmt, $picid); + } + + unless ($data) { + my $dbb = LJ::get_cluster_reader($u); + return SERVER_ERROR unless $dbb; + $data = $dbb->selectrow_array("SELECT imagedata FROM userpicblob2 WHERE ". + "userid=$pic->{'userid'} AND picid=$picid"); + } + } + + return NOT_FOUND unless $data; + + if ($need_cache) { + # make $realfile /userpic-userid, and $file /userpic + my $realfile = $file; + unless ($file =~ s/-\d+$//) { + $realfile .= "-$pic->{'userid'}"; + } + + # delete short file on Unix if it exists + unlink $file if $USERPIC{'symlink'} && -f $file; + + # write real file. + open (F, ">$realfile"); print F $data; close F; + + # make symlink, or duplicate file (if on Windows) + my $symtarget = $realfile; $symtarget =~ s!.+/!!; + unless (eval { symlink($symtarget, $file) }) { + open (F, ">$file"); print F $data; close F; + } + } + + $set_mime->($data); + $size = length($data); + $send_headers->(); + $r->print($data) unless $r->header_only; + return OK; +} + +sub files_trans +{ + my $r = shift; + return 404 unless $r->uri =~ m!^/(\w{1,15})/(\w+)(/\S+)!; + my ($user, $domain, $rest) = ($1, $2, $3); + + if (my $handler = LJ::run_hook("files_handler:$domain", $user, $rest)) { + $r->notes("codepath" => "files.$domain"); + $r->handler("perl-script"); + $r->push_handlers(PerlHandler => $handler); + return OK; + } + return 404; +} + +sub journal_content +{ + my $r = shift; + my $uri = $r->uri; + + my %GET = $r->args; + + if ($RQ{'mode'} eq "robots_txt") + { + my $u = LJ::load_user($RQ{'user'}); + LJ::load_user_props($u, "opt_blockrobots"); + $r->content_type("text/plain"); + $r->send_http_header(); + $r->print("User-Agent: *\n"); + if ($u->{'opt_blockrobots'}) { + $r->print("Disallow: /\n"); + } + return OK; + } + + # handle HTTP digest authentication + if ($GET{'auth'} eq 'digest' || + $r->header_in("Authorization") =~ /^Digest/) { + my $res = LJ::auth_digest($r); + unless ($res) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Digest authentication failed."); + return OK; + } + } + + my $criterr = 0; + my $remote = LJ::get_remote({ criterr => \$criterr }); + + # check for faked cookies here, since this is pretty central. + if ($criterr) { + $r->status_line("500 Invalid Cookies"); + $r->content_type("text/html"); + # reset all cookies + foreach my $dom (@LJ::COOKIE_DOMAIN_RESET) { + my $cookiestr = 'ljsession='; + $cookiestr .= '; expires=' . LJ::time_to_cookie(1); + $cookiestr .= $dom ? "; domain=$dom" : ''; + $cookiestr .= '; path=/; HttpOnly'; + Apache->request->err_headers_out->add('Set-Cookie' => $cookiestr); + } + + $r->send_http_header(); + $r->print("Invalid cookies. Try logging out and then logging back in.\n"); + $r->print("\n") for (0..100); + return OK; + } + + # LJ::make_journal() will set this flag if the user's + # style system is unable to handle the requested + # view (S1 can't do EntryPage or MonthPage), in which + # case it's our job to invoke the legacy BML page. + my $handle_with_bml = 0; + + my %headers = (); + my $opts = { + 'r' => $r, + 'headers' => \%headers, + 'args' => $RQ{'args'}, + 'getargs' => \%GET, + 'vhost' => $RQ{'vhost'}, + 'pathextra' => $RQ{'pathextra'}, + 'header' => { + 'If-Modified-Since' => $r->header_in("If-Modified-Since"), + }, + 'handle_with_bml_ref' => \$handle_with_bml, + }; + + my $user = $RQ{'user'}; + my $html = LJ::make_journal($user, $RQ{'mode'}, $remote, $opts); + + return redir($r, $opts->{'redir'}) if $opts->{'redir'}; + return $opts->{'handler_return'} if defined $opts->{'handler_return'}; + + # if LJ::make_journal() indicated it can't handle the request: + if ($handle_with_bml) { + my $args = $r->args; + my $args_wq = $args ? "?$args" : ""; + + # can't show BML on user domains... redirect them + if ($RQ{'vhost'} eq "users" && ($RQ{'mode'} eq "entry" || + $RQ{'mode'} eq "reply" || + $RQ{'mode'} eq "month")) + { + my $u = LJ::load_user($RQ{'user'}); + my $base = "$LJ::SITEROOT/users/$RQ{'user'}"; + $base = "$LJ::SITEROOT/community/$RQ{'user'}" if $u && $u->{'journaltype'} eq "C"; + return redir($r, "$base$uri$args_wq"); + } + + if ($RQ{'mode'} eq "entry" || $RQ{'mode'} eq "reply") { + my $filename = $RQ{'mode'} eq "entry" ? + "$LJ::HOME/htdocs/talkread.bml" : + "$LJ::HOME/htdocs/talkpost.bml"; + $r->notes("_journal" => $RQ{'user'}); + $r->notes("bml_filename" => $filename); + return Apache::BML::handler($r); + } + + if ($RQ{'mode'} eq "month") { + my $filename = "$LJ::HOME/htdocs/view/index.bml"; + $r->notes("_journal" => $RQ{'user'}); + $r->notes("bml_filename" => $filename); + return Apache::BML::handler($r); + } + } + + my $status = $opts->{'status'} || "200 OK"; + $opts->{'contenttype'} ||= $opts->{'contenttype'} = "text/html"; + if ($opts->{'contenttype'} =~ m!^text/! && + $LJ::UNICODE && $opts->{'contenttype'} !~ /charset=/) { + $opts->{'contenttype'} .= "; charset=utf-8"; + } + + # Set to 1 if the code should generate junk to help IE + # display a more meaningful error message. + my $generate_iejunk = 0; + + if ($opts->{'badargs'}) + { + # No special information to give to the user, so just let + # Apache handle the 404 + return 404; + } + elsif ($opts->{'baduser'}) + { + $status = "404 Unknown User"; + $html = "

    Unknown User

    There is no user $user at $LJ::SITENAME.

    "; + $generate_iejunk = 1; + } + elsif ($opts->{'badfriendgroup'}) + { + # give a real 404 to the journal owner + if ($remote && $remote->{'user'} eq $user) { + $status = "404 Friend group does not exist"; + $html = "

    Not Found

    " . + "

    The friend group you are trying to access does not exist.

    "; + + # otherwise be vague with a 403 + } else { + # send back a 403 and don't reveal if the group existed or not + $status = "403 Friend group does not exist, or is not public"; + $html = "

    Denied

    " . + "

    Sorry, the friend group you are trying to access does not exist " . + "or is not public.

    \n"; + + $html .= "

    You're not logged in. If you're the owner of this journal, " . + "log in and try again.

    \n" + unless $remote; + } + + $generate_iejunk = 1; + + } elsif ($opts->{'suspendeduser'}) { + $status = "403 User suspended"; + $html = "

    Suspended User

    " . + "

    The content at this URL is from a suspended user.

    "; + + $generate_iejunk = 1; + } + + unless ($html) { + $status = "500 Bad Template"; + $html = "

    Error

    User $user has messed up their journal template definition.

    "; + $generate_iejunk = 1; + } + + $r->status_line($status); + foreach my $hname (keys %headers) { + if (ref($headers{$hname}) && ref($headers{$hname}) eq "ARRAY") { + foreach (@{$headers{$hname}}) { + $r->header_out($hname, $_); + } + } else { + $r->header_out($hname, $headers{$hname}); + } + } + + $r->content_type($opts->{'contenttype'}); + $r->header_out("Cache-Control", "private, proxy-revalidate"); + + $html .= ("\n" x 100) if $generate_iejunk; + + my $do_gzip = $LJ::DO_GZIP && $LJ::OPTMOD_ZLIB; + if ($do_gzip) { + my $ctbase = $opts->{'contenttype'}; + $ctbase =~ s/;.*//; + $do_gzip = 0 unless $LJ::GZIP_OKAY{$ctbase}; + $do_gzip = 0 if $r->header_in("Accept-Encoding") !~ /gzip/; + } + my $length = length($html); + $do_gzip = 0 if $length < 500; + + if ($do_gzip) { + my $pre_len = $length; + $r->notes("bytes_pregzip" => $pre_len); + $html = Compress::Zlib::memGzip($html); + $length = length($html); + $r->header_out('Content-Encoding', 'gzip'); + } + # Let caches know that Accept-Encoding will change content + $r->header_out('Vary', 'Accept-Encoding'); + + $r->header_out("Content-length", $length); + $r->send_http_header(); + $r->print($html) unless $r->header_only; + + return OK; +} + +sub customview_content +{ + my $r = shift; + + my %FORM = $r->args; + + my $charset = "utf-8"; + + if ($LJ::UNICODE && $FORM{'charset'}) { + $charset = $FORM{'charset'}; + if ($charset ne "utf-8" && ! Unicode::MapUTF8::utf8_supported_charset($charset)) { + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error: requested charset not supported."); + return OK; + } + } + + my $ctype = "text/html"; + if ($FORM{'type'} eq "xml") { + $ctype = "text/xml"; + } + + if ($LJ::UNICODE) { + $ctype .= "; charset=$charset"; + } + + $r->content_type($ctype); + + my $user = $FORM{'username'} || $FORM{'user'}; + my $styleid = $FORM{'styleid'} + 0; + my $nooverride = $FORM{'nooverride'} ? 1 : 0; + + my $remote; + if ($FORM{'checkcookies'}) { + $remote = LJ::get_remote(); + } + + my $data = (LJ::make_journal($user, "", $remote, + { "nocache" => $FORM{'nocache'}, + "vhost" => "customview", + "nooverride" => $nooverride, + "styleid" => $styleid, + "saycharset" => $charset, + "args" => scalar $r->args, + "getargs" => \%FORM, + "r" => $r, + }) + || "[$LJ::SITENAME: Bad username, styleid, or style definition]"); + + if ($FORM{'enc'} eq "js") { + $data =~ s/\\/\\\\/g; + $data =~ s/\"/\\\"/g; + $data =~ s/\n/\\n/g; + $data =~ s/\r//g; + $data = "document.write(\"$data\")"; + } + + if ($LJ::UNICODE && $charset ne 'utf-8') { + $data = Unicode::MapUTF8::from_utf8({-string=>$data, -charset=>$charset}); + } + + $r->header_out("Cache-Control", "must-revalidate"); + $r->header_out("Content-Length", length($data)); + $r->send_http_header(); + $r->print($data) unless $r->header_only; + return OK; +} + +sub interface_content +{ + my $r = shift; + my $args = $r->args; + + if ($RQ{'interface'} eq "xmlrpc") { + return 404 unless $LJ::OPTMOD_XMLRPC; + my $server = XMLRPC::Transport::HTTP::Apache + -> on_action(sub { die "Access denied\n" if $_[2] =~ /:|\'/ }) + -> dispatch_to('LJ::XMLRPC') + -> handle($r); + return OK; + } + + if ($RQ{'interface'} eq "blogger") { + return 404 unless $LJ::OPTMOD_XMLRPC; + my $pkg = "Apache::LiveJournal::Interface::Blogger"; + my $server = XMLRPC::Transport::HTTP::Apache + -> on_action(sub { die "Access denied\n" if $_[2] =~ /:|\'/ }) + -> dispatch_with({ 'blogger' => $pkg }) + -> dispatch_to($pkg) + -> handle($r); + return OK; + } + + if ($RQ{'interface'} =~ /atom(?:api)?/) { + # the interface package will set up all headers and + # print everything + Apache::LiveJournal::Interface::AtomAPI::handle($r); + return OK; + } + + if ($RQ{'interface'} ne "flat") { + $r->content_type("text/plain"); + $r->send_http_header; + $r->print("Unknown interface."); + return OK; + } + + $r->content_type("text/plain"); + + my %out = (); + my %FORM = (); + my $content; + $r->read($content, $r->header_in("Content-Length")); + LJ::decode_url_string($content, \%FORM); + + # the protocol needs the remote IP in just one place, where tracking is done. + $ENV{'_REMOTE_IP'} = $r->connection()->remote_ip(); + LJ::do_request(\%FORM, \%out); + + if ($FORM{'responseenc'} eq "urlenc") { + $r->send_http_header; + foreach (sort keys %out) { + $r->print(LJ::eurl($_) . "=" . LJ::eurl($out{$_}) . "&"); + } + return OK; + } + + my $length = 0; + foreach (sort keys %out) { + $length += length($_)+1; + $length += length($out{$_})+1; + } + + $r->header_out("Content-length", $length); + $r->send_http_header; + foreach (sort keys %out) { + my $key = $_; + my $val = $out{$_}; + $key =~ y/\r\n//d; + $val =~ y/\r\n//d; + $r->print($key, "\n", $val, "\n"); + if ($key ne $_ || $val ne $out{$_}) { + print STDERR "Stripped spurious newline in $FORM{mode} protocol request for $FORM{user}: $_ => $out{$_}\n"; + } + } + + return OK; +} + +sub db_logger +{ + my $r = shift; + my $rl = $r->last; + + $r->pnotes('did_lj_logging' => 1); + + my $uri = $r->uri; + my $ctype = $rl->content_type; + + return if $ctype =~ m!^image/! and $LJ::DONT_LOG_IMAGES; + return if $uri =~ m!^/(img|userpic)/! and $LJ::DONT_LOG_IMAGES; + + my $dbl = LJ::get_dbh("logs"); + my @dinsertd_socks; + + my $now = time; + my @now = localtime($now); + + foreach my $hostport (@LJ::DINSERTD_HOSTS) { + next if $LJ::CACHE_DINSERTD_DEAD{$hostport} > $now - 15; + + my $sock = + $LJ::CACHE_DINSERTD_SOCK{$hostport} ||= + IO::Socket::INET->new(PeerAddr => $hostport, + Proto => 'tcp', + Timeout => 1, + ); + + if ($sock) { + delete $LJ::CACHE_DINSERTD_DEAD{$hostport}; + push @dinsertd_socks, [ $hostport, $sock ]; + } else { + delete $LJ::CACHE_DINSERTD_SOCK{$hostport}; + $LJ::CACHE_DINSERTD_DEAD{$hostport} = $now; + } + } + + # why go on if we have nowhere to log to? + return unless $dbl || @dinsertd_socks; + + $ctype =~ s/;.*//; # strip charset + + # Send out DBI profiling information + if ( $LJ::DB_LOG_HOST && $LJ::HAVE_DBI_PROFILE ) { + my ( $host, $dbh ); + + while ( ($host,$dbh) = each %LJ::DB_REPORT_HANDLES ) { + $host =~ s{^(.*?);.*}{$1}; + + # For testing: append a random character to simulate different + # connections. + if ( $LJ::IS_DEV_SERVER ) { + $host .= "_" . substr( "abcdefghijklmnopqrstuvwxyz", int rand(26), 1 ); + } + + # From DBI::Profile: + # Profile data is stored at the `leaves' of the tree as references + # to an array of numeric values. For example: + # [ + # 106, # count + # 0.0312958955764771, # total duration + # 0.000490069389343262, # first duration + # 0.000176072120666504, # shortest duration + # 0.00140702724456787, # longest duration + # 1023115819.83019, # time of first event + # 1023115819.86576, # time of last event + # ] + + # The leaves are stored as values in the hash keyed by statement + # because LJ::get_dbirole_dbh() sets the profile to + # "2/DBI::Profile". The 2 part is the DBI::Profile magic number + # which means split the times by statement. + my $data = $dbh->{Profile}{Data}; + + # Make little arrayrefs out of the statement and longest + # running-time for this handle so they can be sorted. Then sort them + # by running-time so the longest-running one can be send to the + # stats collector. + my @times = + sort { $a->[0] <=> $b->[0] } + map {[ $data->{$_}[4], $_ ]} keys %$data; + + # ( host, class, time, notes ) + LJ::blocking_report( $host, 'db', @{$times[0]} ); + } + } + + my $table = sprintf("access%04d%02d%02d%02d", $now[5]+1900, + $now[4]+1, $now[3], $now[2]); + + unless ($LJ::CACHED_LOG_CREATE{"$table"}++) { + my $sql = "(". + "whn TIMESTAMP(14) NOT NULL,". + "INDEX(whn),". + "server VARCHAR(30),". + "addr VARCHAR(15) NOT NULL,". + "ljuser VARCHAR(15),". + "journalid INT UNSIGNED,". # userid of what's being looked at + "codepath VARCHAR(80),". # protocol.getevents / s[12].friends / bml.update / bml.friends.index + "anonsess INT UNSIGNED,". + "langpref VARCHAR(5),". + "uniq VARCHAR(15),". + "method VARCHAR(10) NOT NULL,". + "uri VARCHAR(255) NOT NULL,". + "args VARCHAR(255),". + "status SMALLINT UNSIGNED NOT NULL,". + "ctype VARCHAR(30),". + "bytes MEDIUMINT UNSIGNED NOT NULL,". + "browser VARCHAR(100),". + "clientver VARCHAR(100),". + "secs TINYINT UNSIGNED,". + "ref VARCHAR(200),". + "pid SMALLINT UNSIGNED,". + "cpu_user FLOAT UNSIGNED,". + "cpu_sys FLOAT UNSIGNED,". + "cpu_total FLOAT UNSIGNED,". + "mem_vsize INT,". + "mem_share INT,". + "mem_rss INT,". + "mem_unshared INT) DELAY_KEY_WRITE = 1"; + + if ($dbl) { + $dbl->do("CREATE TABLE IF NOT EXISTS $table $sql"); + $r->log_error("error creating log table ($table), perhaps due to old MySQL not supporting delayed key writes? Error is: " . + $dbl->errstr) if $dbl->err; + } + + foreach my $rec (@dinsertd_socks) { + my $sock = $rec->[1]; + my $url = LJ::eurl("CREATE TABLE IF NOT EXISTS [tablename] $sql"); + print $sock "SET_NOTE lj_create_table $url\r\n"; + my $res = <$sock>; + } + } + + my $var = { + 'whn' => sprintf("%04d%02d%02d%02d%02d%02d", $now[5]+1900, $now[4]+1, @now[3, 2, 1, 0]), + 'server' => $LJ::SERVER_NAME, + 'addr' => $r->connection->remote_ip, + 'ljuser' => $rl->notes('ljuser'), + 'journalid' => $rl->notes('journalid'), + 'codepath' => $rl->notes('codepath'), + 'anonsess' => $rl->notes('anonsess'), + 'langpref' => $rl->notes('langpref'), + 'clientver' => $rl->notes('clientver'), + 'uniq' => $r->notes('uniq'), + 'method' => $r->method, + 'uri' => $uri, + 'args' => scalar $r->args, + 'status' => $rl->status, + 'ctype' => $ctype, + 'bytes' => $rl->bytes_sent, + 'browser' => $r->header_in("User-Agent"), + 'secs' => $now - $r->request_time(), + 'ref' => $r->header_in("Referer"), + }; + + # If the configuration says to log statistics and GTop is available, then + # add those data to the log + # The GTop object is only created once per child: + # Benchmark: timing 10000 iterations of Cached GTop, New Every Time... + # Cached GTop: 2.06161 wallclock secs ( 1.06 usr + 0.97 sys = 2.03 CPU) @ 4926.11/s (n=10000) + # New Every Time: 2.17439 wallclock secs ( 1.18 usr + 0.94 sys = 2.12 CPU) @ 4716.98/s (n=10000) + STATS: { + if ( $LJ::LOG_GTOP && $LJ::HAVE_GTOP ) { + $GTop ||= new GTop or last STATS; + + my $startcpu = $r->pnotes( 'gtop_cpu' ) or last STATS; + my $endcpu = $GTop->cpu or last STATS; + my $startmem = $r->pnotes( 'gtop_mem' ) or last STATS; + my $endmem = $GTop->proc_mem( $$ ) or last STATS; + my $cpufreq = $endcpu->frequency or last STATS; + + # Map the GTop values into the corresponding fields in a slice + @$var{qw{pid cpu_user cpu_sys cpu_total mem_vsize mem_share mem_rss mem_unshared}} = ( + $$, + ($endcpu->user - $startcpu->user) / $cpufreq, + ($endcpu->sys - $startcpu->sys) / $cpufreq, + ($endcpu->total - $startcpu->total) / $cpufreq, + $endmem->vsize - $startmem->vsize, + $endmem->share - $startmem->share, + $endmem->rss - $startmem->rss, + $endmem->size - $endmem->share, + ); + } + } + + if ($dbl) { + my $delayed = $LJ::IMMEDIATE_LOGGING ? "" : "DELAYED"; + $dbl->do("INSERT $delayed INTO $table (" . join(',', keys %$var) . ") ". + "VALUES (" . join(',', map { $dbl->quote($var->{$_}) } keys %$var) . ")"); + + $dbl->disconnect if $LJ::DISCONNECT_DB_LOG; + } + + if (@dinsertd_socks) { + $var->{_table} = $table; + my $string = "INSERT " . Storable::freeze($var) . "\r\n"; + my $len = "\x01" . substr(pack("N", length($string) - 2), 1, 3); + $string = $len . $string; + + foreach my $rec (@dinsertd_socks) { + my $sock = $rec->[1]; + print $sock $string; + my $rin; + my $res; + vec($rin, fileno($sock), 1) = 1; + $res = <$sock> if select($rin, undef, undef, 0.3); + delete $LJ::CACHE_DINSERTD_SOCK{$rec->[0]} unless $res =~ /^OK\b/; + } + } + + + # Now clear the profiling data for each handle we're profiling at the last + # possible second to avoid the next request's data being skewed by + # requests that happen above. + if ( $LJ::DB_LOG_HOST && $LJ::HAVE_DBI_PROFILE ) { + for my $dbh ( values %LJ::DB_REPORT_HANDLES ) { + # DBI::Profile-recommended way of resetting profile data + $dbh->{Profile}{Data} = undef; + } + %LJ::DB_REPORT_HANDLES = (); + } +} + + +sub anti_squatter +{ + my $r = shift; + $r->push_handlers(PerlHandler => sub { + my $r = shift; + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Dev Server Warning", + "", + "

    Warning

    This server is for development and testing only. ", + "Accounts are subject to frequent deletion. Don't use this machine for anything important.

    ", + "
    ", + LJ::html_hidden("dest", "$LJ::SQUAT_URL"), + LJ::html_submit(undef, "Acknowledged"), + "
    "); + return OK; + }); + +} + +package LJ::Protocol; + +sub xmlrpc_method { + my $method = shift; + shift; # get rid of package name that dispatcher includes. + my $req = shift; + + if (@_) { + # don't allow extra arguments + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message(202)) + ->faultcode(202); + } + my $error = 0; + if (ref $req eq "HASH") { + foreach my $key ('subject', 'event') { + # get rid of the UTF8 flag in scalars + $req->{$key} = pack('C*', unpack('C*', $req->{$key})) + if $req->{$key}; + } + } + my $res = LJ::Protocol::do_request($method, $req, \$error); + if ($error) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($error)) + ->faultcode(substr($error, 0, 3)); + } + return $res; +} + +package LJ::XMLRPC; + +use vars qw($AUTOLOAD); + +sub AUTOLOAD { + my $method = $AUTOLOAD; + $method =~ s/^.*:://; + LJ::Protocol::xmlrpc_method($method, @_); +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal/Interface/AtomAPI.pm b/livejournal/cgi-bin/Apache/LiveJournal/Interface/AtomAPI.pm new file mode 100755 index 0000000..fb4c82f --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal/Interface/AtomAPI.pm @@ -0,0 +1,610 @@ +# AtomAPI support for LJ + +package Apache::LiveJournal::Interface::AtomAPI; + +use strict; +use Apache::Constants qw(:common); +use Digest::SHA1; +use MIME::Base64; +use lib "$ENV{'LJHOME'}/cgi-bin"; +require 'parsefeed.pl'; +require 'fbupload.pl'; + +BEGIN { + $LJ::OPTMOD_XMLATOM = eval q{ + use XML::Atom::Feed; + use XML::Atom::Entry; + use XML::Atom::Link; + XML::Atom->VERSION < 0.09 ? 0 : 1; + }; +}; + +# check allowed Atom upload filetypes +sub check_mime +{ + my $mime = shift; + return unless $mime; + + # TODO: add audio/etc support + my %allowed_mime = ( + image => qr{^image\/(?:gif|jpe?g|png|tiff?)$}i, + #audio => qr{^(?:application|audio)\/(?:(?:x-)?ogg|wav)$}i + ); + + foreach (keys %allowed_mime) { + return $_ if $mime =~ $allowed_mime{$_} + } + return; +} + +sub respond { + my ($r, $status, $body, $type) = @_; + + my %msgs = ( + 200 => 'OK', + 201 => 'Created', + + 400 => 'Bad Request', + 401 => 'Authentication Failed', + 403 => 'Forbidden', + 404 => 'Not Found', + 500 => 'Server Error', + ), + + my %mime = ( + html => 'text/html', + atom => 'application/x.atom+xml', + xml => "text/xml; charset='utf-8'", + ); + + # if the passed in body was a reference, send it + # without any modification. otherwise, send some + # prettier html to the client. + my $out; + if (ref $body) { + $out = $$body; + } else { + $out = <$status $msgs{$status} +

    $msgs{$status}


    $body

    + +HTML + } + + $type = $mime{$type} || 'text/html'; + $r->status_line("$status $msgs{$status}"); + $r->content_type($type); + $r->send_http_header(); + $r->print($out); + return OK; +}; + +sub handle_upload +{ + my ($r, $remote, $u, $opts, $entry) = @_; + + # entry could already be populated from a standalone + # service.post posting. + my $standalone = $entry ? 1 : 0; + unless ($entry) { + my $buff; + $r->read($buff, $r->header_in("Content-length")); + + eval { $entry = XML::Atom::Entry->new( \$buff ); }; + return respond($r, 400, "Could not parse the entry due to invalid markup.
    $@
    ") + if $@; + } + + my $mime = $entry->content()->type(); + my $mime_area = check_mime( $mime ); + return respond($r, 400, "Unsupported MIME type: $mime") unless $mime_area; + + if ($mime_area eq 'image') { + + return respond($r, 400, "Unable to upload media. Your account doesn't have the required access.") + unless LJ::get_cap($u, 'fb_can_upload') && $LJ::FB_SITEROOT; + + my $err; + LJ::load_user_props( + $u, + qw/ emailpost_gallery emailpost_imgsecurity / + ); + + my $summary = LJ::trim( $entry->summary() ); + + my $fb = LJ::FBUpload::do_upload( + $u, \$err, + { + path => $entry->title(), + rawdata => \$entry->content()->body(), + imgsec => $u->{emailpost_imgsecurity}, + caption => $summary, + galname => $u->{emailpost_gallery} || 'AtomUpload', + } + ); + + return respond($r, 500, "There was an error uploading the media: $err") + if $err || ! $fb; + + if (ref $fb && $fb->{Error}->{code}) { + my $errstr = $fb->{Error}->{content}; + return respond($r, 500, "There was an error uploading the media: $errstr"); + } + + my $atom_reply = XML::Atom::Entry->new(); + $atom_reply->title( $fb->{Title} ); + + if ($standalone) { + $atom_reply->summary('Media post'); + my $id = "atom:$u->{user}:$fb->{PicID}"; + $fb->{Summary} = $summary; + LJ::MemCache::set( $id, $fb, 1800 ); + $atom_reply->id( "urn:fb:$LJ::FB_DOMAIN:$id" ); + } + + my $link = XML::Atom::Link->new(); + $link->type('text/html'); + $link->rel('alternate'); + $link->href( $fb->{URL} ); + $atom_reply->add_link($link); + + $r->header_out("Location", $fb->{URL}); + return respond($r, 201, \$atom_reply->as_xml(), 'atom'); + } +} + +sub handle_post { + my ($r, $remote, $u, $opts) = @_; + my ($buff, $entry); + + # read the content + $r->read($buff, $r->header_in("Content-length")); + + # try parsing it + eval { $entry = XML::Atom::Entry->new( \$buff ); }; + return respond($r, 400, "Could not parse the entry due to invalid markup.
    $@
    ") + if $@; + + # on post, the entry must NOT include an id + return respond($r, 400, "Must not include an <id> field in a new entry.") + if $entry->id(); + + # detect 'standalone' media posts + return handle_upload( @_, $entry ) + if $entry->get("http://sixapart.com/atom/typepad#", 'standalone'); + + # remove the SvUTF8 flag. See same code in synsuck.pl for + # an explanation + $entry->title( pack( 'C*', unpack( 'C*', $entry->title() ) ) ); + $entry->link( pack( 'C*', unpack( 'C*', $entry->link() ) ) ); + $entry->content( pack( 'C*', unpack( 'C*', $entry->content()->body() ) ) ); + + # Retrieve fotobilder media links from clients that embed via + # standalone tags or service.upload transfers. Add to post entry + # body. + my $body = $entry->content()->body(); + my @links = $entry->link(); + my (@images, $link_count); + foreach my $link (@links) { + # $link is now a valid XML::Atom::Link object + my $rel = $link->get('rel'); + my $type = $link->get('type'); + my $id = $link->get('href'); + + next unless $rel eq 'related' && check_mime($type) && $id; + $id =~ s/^urn:fb:$LJ::FB_DOMAIN://; + my $fb = LJ::MemCache::get( $id ); + next unless $fb; + + push @images, { + url => $fb->{URL}, + width => $fb->{Width}, + height => $fb->{Height}, + caption => $fb->{Summary}, + title => $fb->{Title} + }; + } + + $body .= LJ::FBUpload::make_html( $u, \@images ); + + # build a post event request. + my $req = { + 'usejournal' => ( $remote->{'userid'} != $u->{'userid'} ) ? $u->{'user'} : undef, + 'ver' => 1, + 'username' => $u->{'user'}, + 'lineendings' => 'unix', + 'subject' => $entry->title(), + 'event' => $body, + 'props' => {}, + 'security' => 'public', + 'tz' => 'guess', + }; + + my $err; + my $res = LJ::Protocol::do_request("postevent", + $req, \$err, { 'noauth' => 1 }); + + if ($err) { + my $errstr = LJ::Protocol::error_message($err); + return respond($r, 500, "Unable to post new entry. Protocol error: $errstr."); + } + + my $atom_reply = XML::Atom::Entry->new(); + $atom_reply->title( $entry->title() ); + $atom_reply->summary( substr( $entry->content->body(), 0, 100 ) ); + + my $link; + my $edit_url = "$LJ::SITEROOT/interface/atom/edit/$res->{'itemid'}"; + + $link = XML::Atom::Link->new(); + $link->type('application/x.atom+xml'); + $link->rel('service.edit'); + $link->href( $edit_url ); + $link->title( $entry->title() ); + $atom_reply->add_link($link); + + $link = XML::Atom::Link->new(); + $link->type('text/html'); + $link->rel('alternate'); + $link->href( $res->{url} ); + $link->title( $entry->title() ); + $atom_reply->add_link($link); + + $r->header_out("Location", $edit_url); + return respond($r, 201, \$atom_reply->as_xml(), 'atom'); +} + +sub handle_edit { + my ($r, $remote, $u, $opts) = @_; + + my $method = $opts->{'method'}; + + # first, try to load the item and fail if it's not there + my $jitemid = $opts->{'param'}; + my $req = { + 'usejournal' => ($remote->{'userid'} != $u->{'userid'}) ? + $u->{'user'} : undef, + 'ver' => 1, + 'username' => $u->{'user'}, + 'selecttype' => 'one', + 'itemid' => $jitemid, + }; + + my $err; + my $olditem = LJ::Protocol::do_request("getevents", + $req, \$err, { 'noauth' => 1 }); + + if ($err) { + my $errstr = LJ::Protocol::error_message($err); + return respond($r, 404, "Unable to retrieve the item requested for editing. Protocol error: $errstr."); + } + $olditem = $olditem->{'events'}->[0]; + + if ($method eq "GET") { + # return an AtomEntry for this item + # use the interface between make_feed and create_view_atom in + # ljfeed.pl + + # get the log2 row (need logtime for createtime) + my $row = LJ::get_log2_row($u, $jitemid) || + return respond($r, 404, "Could not load the original entry."); + + # we need to put into $item: itemid, ditemid, subject, event, + # createtime, eventtime, modtime + + my $ctime = LJ::mysqldate_to_time($row->{'logtime'}, 1); + + my $item = { + 'itemid' => $olditem->{'itemid'}, + 'ditemid' => $olditem->{'itemid'}*256 + $olditem->{'anum'}, + 'eventtime' => LJ::alldatepart_s2($row->{'eventtime'}), + 'createtime' => $ctime, + 'modtime' => $olditem->{'props'}->{'revtime'} || $ctime, + 'subject' => $olditem->{'subject'}, + 'event' => $olditem->{'event'}, + }; + + my $ret = LJ::Feed::create_view_atom( + { 'u' => $u }, + $u, + { + 'saycharset' => "utf-8", + 'noheader' => 1, + 'apilinks' => 1, + }, + [$item] + ); + + return respond($r, 200, \$ret, 'xml'); + } + + if ($method eq "PUT") { + # read the content + my $buff; + $r->read($buff, $r->header_in("Content-length")); + + # try parsing it + my $entry; + eval { $entry = XML::Atom::Entry->new( \$buff ); }; + return respond($r, 400, "Could not parse the entry due to invalid markup.
    $@
    ") + if $@; + + # remove the SvUTF8 flag. See same code in synsuck.pl for + # an explanation + $entry->title( pack( 'C*', unpack( 'C*', $entry->title() ) ) ); + $entry->link( pack( 'C*', unpack( 'C*', $entry->link() ) ) ); + $entry->content( pack( 'C*', unpack( 'C*', $entry->content()->body() ) ) ); + + # the AtomEntry must include which must match the one we sent + # on GET + unless ($entry->id() =~ m#atom1:$u->{'user'}:(\d+)$# && + $1 == $olditem->{'itemid'}*256 + $olditem->{'anum'}) { + return respond($r, 400, "Incorrect <id> field in this request."); + } + + # build an edit event request. Preserve fields that aren't being + # changed by this item (perhaps the AtomEntry isn't carrying the + # complete information). + + $req = { + 'usejournal' => ( $remote->{'userid'} != $u->{'userid'} ) ? $u->{'user'} : undef, + 'ver' => 1, + 'username' => $u->{'user'}, + 'itemid' => $jitemid, + 'lineendings' => 'unix', + 'subject' => $entry->title() || $olditem->{'subject'}, + 'event' => $entry->content()->body() || $olditem->{'event'}, + 'props' => $olditem->{'props'}, + 'security' => $olditem->{'security'}, + 'allowmask' => $olditem->{'allowmask'}, + }; + + $err = undef; + my $res = LJ::Protocol::do_request("editevent", + $req, \$err, { 'noauth' => 1 }); + + if ($err) { + my $errstr = LJ::Protocol::error_message($err); + return respond($r, 500, "Unable to update entry. Protocol error: $errstr."); + } + + return respond($r, 200, "The entry was successfully updated."); + } + + if ($method eq "DELETE") { + + # build an edit event request to delete the entry. + + $req = { + 'usejournal' => ($remote->{'userid'} != $u->{'userid'}) ? + $u->{'user'}:undef, + 'ver' => 1, + 'username' => $u->{'user'}, + 'itemid' => $jitemid, + 'lineendings' => 'unix', + 'event' => '', + }; + + $err = undef; + my $res = LJ::Protocol::do_request("editevent", + $req, \$err, { 'noauth' => 1 }); + + if ($err) { + my $errstr = LJ::Protocol::error_message($err); + return respond($r, 500, "Unable to delete entry. Protocol error: $errstr."); + } + + return respond($r, 200, "Entry successfully deleted."); + } + +} + +# fetch lj tags, display as categories +sub handle_categories +{ + my ($r, $remote, $u, $opts) = @_; + my $ret = ''; + $ret .= ''; + + my $tags = LJ::Tags::get_usertags($u, { remote => $remote }) || {}; + foreach (sort { $a->{name} cmp $b->{name} } values %$tags) { + $ret .= "$_->{name}"; + } + $ret .= ''; + + return respond($r, 200, \$ret, 'xml'); +} + +sub handle_feed { + my ($r, $remote, $u, $opts) = @_; + + # simulate a call to the S1 data view creator, with appropriate + # options + + my %op = ('pathextra' => "/atom", + 'saycharset'=> "utf-8", + 'apilinks' => 1, + ); + my $ret = LJ::Feed::make_feed($r, $u, $remote, \%op); + + unless (defined $ret) { + if ($op{'redir'}) { + # this happens if the account was renamed or a syn account. + # the redir URL is wrong because ljfeed.pl is too + # dataview-specific. Since this is an admin interface, we can + # just fail. + return respond ($r, 404, "The account $u->{'user'} is of a wrong type and does not allow AtomAPI administration."); + } + if ($op{'handler_return'}) { + # this could be a conditional GET shortcut, honor it + $r->status($op{'handler_return'}); + return OK; + } + # should never get here + return respond ($r, 404, "Unknown error."); + } + + # everything's fine, return the XML body with the correct content type + return respond($r, 200, \$ret, 'xml'); + +} + +# this routine accepts the apache request handle, performs +# authentication, calls the appropriate method handler, and +# prints the response. +sub handle { + my $r = shift; + + return respond($r, 404, "This server does not support the Atom API.") + unless $LJ::OPTMOD_XMLATOM; + + # break the uri down: /interface/atom/[/] + my ( $action, $param, $oldparam ) = ( $1, $2, $3 ) + if $r->uri =~ m#^/interface/atom(?:api)?/?(\w+)?(?:/(\w+))?(?:/(\d+))?$#; + + my $valid_actions = qr{feed|edit|post|upload|categories}; + + # old uri was was: /interface/atomapi//[/] + # support both by shifting params around if we see something extra. + if ($action !~ /$valid_actions/ && $r->uri =~ /atomapi/ ) { + $action = $param; + $param = $oldparam; + } + + # let's authenticate. + # + # if wsse information is supplied, use it. + # if not, fall back to digest. + my $wsse = $r->header_in('X-WSSE'); + my $nonce_dup; + my $u = $wsse ? auth_wsse($wsse, \$nonce_dup) : LJ::auth_digest($r); + return respond( $r, 401, "Authentication failed for this AtomAPI request.") + unless $u; + + return respond( $r, 401, "Authentication failed for this AtomAPI request.") + if $nonce_dup && $action && $action ne 'post'; + + # service autodiscovery + # TODO: Add communities? + my $method = $r->method; + if ( $method eq 'GET' && ! $action ) { + LJ::load_user_props( $u, 'journaltitle' ); + my $title = $u->{journaltitle} || 'Untitled Journal'; + my $feed = XML::Atom::Feed->new(); + foreach (qw/ post feed upload categories /) { + my $link = XML::Atom::Link->new(); + $link->title($title); + $link->type('application/x.atom+xml'); + $link->rel("service.$_"); + $link->href("$LJ::SITEROOT/interface/atom/$_"); + $feed->add_link($link); + } + my $link = XML::Atom::Link->new(); + $link->title($title); + $link->type('text/html'); + $link->rel('alternate'); + $link->href( LJ::journal_base($u) ); + $feed->add_link($link); + + return respond($r, 200, \$feed->as_xml(), 'atom'); + } + + $action =~ /$valid_actions/ + or return respond($r, 400, "Unknown URI scheme: /interface/atom/$action"); + + unless (($action eq 'feed' and $method eq 'GET') or + ($action eq 'categories' and $method eq 'GET') or + ($action eq 'post' and $method eq 'POST') or + ($action eq 'upload' and $method eq 'POST') or + ($action eq 'edit' and + {'GET'=>1,'PUT'=>1,'DELETE'=>1}->{$method})) { + return respond($r, 400, "URI scheme /interface/atom/$action is incompatible with request method $method."); + } + + if (($action ne 'edit' && $param) or + ($action eq 'edit' && $param !~ m#^\d+$#)) { + return respond($r, 400, "Either the URI lacks a required parameter, or its format is improper."); + } + + # we've authenticated successfully and remote is set. But can remote + # manage the requested account? + my $remote = LJ::get_remote(); + unless (LJ::can_manage($remote, $u)) { + return respond($r, 403, "User $remote->{'user'} has no administrative access to account $u->{user}."); + } + + # handle the requested action + my $opts = { + 'action' => $action, + 'method' => $method, + 'param' => $param + }; + + { + 'feed' => \&handle_feed, + 'post' => \&handle_post, + 'edit' => \&handle_edit, + 'upload' => \&handle_upload, + 'categories' => \&handle_categories, + }->{$action}->( $r, $remote, $u, $opts ); + + return OK; +} + +# Authenticate via the WSSE header. +# Returns valid $u on success, undef on failure. +sub auth_wsse +{ + my ($wsse, $nonce_dup) = @_; + $wsse =~ s/UsernameToken // or return undef; + + # parse credentials into a hash. + my %creds; + foreach (split /, /, $wsse) { + my ($k, $v) = split '=', $_, 2; + $v =~ s/^['"]//; + $v =~ s/['"]$//; + $v =~ s/=$// if $k =~ /passworddigest/i; # strip base64 newline char + $creds{ lc($k) } = $v; + } + + # invalid create time? invalid wsse. + my $ctime = LJ::ParseFeed::w3cdtf_to_time( $creds{created} ) or return undef; + + # prevent replay attacks. + $ctime = LJ::mysqldate_to_time( $ctime, 'gmt' ); + return undef if abs(time() - $ctime) > 42300; + + my $u = LJ::load_user( LJ::canonical_username( $creds{'username'} ) ) + or return undef; + + if (@LJ::MEMCACHE_SERVERS && ref $nonce_dup) { + $$nonce_dup = 1 + unless LJ::MemCache::add( "wsse_auth:$creds{username}:$creds{nonce}", 1, 180 ) + } + + # validate hash + my $hash = + Digest::SHA1::sha1_base64( + $creds{nonce} . $creds{created} . $u->{password} ); + + # Nokia's WSSE implementation is incorrect as of 1.5, and they + # base64 encode their nonce *value*. If the initial comparison + # fails, we need to try this as well before saying it's invalid. + if ($hash ne $creds{passworddigest}) { + + $hash = + Digest::SHA1::sha1_base64( + MIME::Base64::decode_base64( $creds{nonce} ) . + $creds{created} . + $u->{password} ); + + return undef if $hash ne $creds{passworddigest}; + } + + # If we're here, we're valid. + LJ::set_remote($u); + return $u; +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal/Interface/Blogger.pm b/livejournal/cgi-bin/Apache/LiveJournal/Interface/Blogger.pm new file mode 100755 index 0000000..085a510 --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal/Interface/Blogger.pm @@ -0,0 +1,232 @@ +# Blogger API wrapper for LJ + +use strict; +package LJ::Util; + +sub blogger_deserialize { + my $content = shift; + my $event = { 'props' => {} }; + if ($content =~ s!(.*?)!!) { + $event->{'subject'} = $1; + } + if ($content =~ s/(^|\n)lj-mood:\s*(.*)\n//i) { + $event->{'props'}->{'current_mood'} = $2; + } + if ($content =~ s/(^|\n)lj-music:\s*(.*)\n//i) { + $event->{'props'}->{'current_music'} = $2; + } + $content =~ s/^\s+//; $content =~ s/\s+$//; + $event->{'event'} = $content; + return $event; +} + +sub blogger_serialize { + my $event = shift; + my $header; + my $content; + if ($event->{'subject'}) { + $header .= "$event->{'subject'}"; + } + if ($event->{'props'}->{'current_mood'}) { + $header .= "lj-mood: $event->{'props'}->{'current_mood'}\n"; + } + if ($event->{'props'}->{'current_music'}) { + $header .= "lj-music: $event->{'props'}->{'current_music'}\n"; + } + $content .= "$header\n" if $header; + $content .= $event->{'event'}; + return $content; +} + +# ISO 8601 (many formats available) +# "yyyy-mm-dd hh:mm:ss" => "yyyymmddThh:mm:ss" (literal T) +sub mysql_date_to_iso { + my $dt = shift; + $dt =~ s/ /T/; + $dt =~ s/\-//g; + return $dt; +} + +package Apache::LiveJournal::Interface::Blogger; + +sub newPost { + shift; + my ($appkey, $journal, $user, $password, $content, $publish) = @_; + + my $err; + my $event = LJ::Util::blogger_deserialize($content); + + my $req = { + 'usejournal' => $journal ne $user ? $journal : undef, + 'ver' => 1, + 'username' => $user, + 'password' => $password, + 'event' => $event->{'event'}, + 'subject' => $event->{'subject'}, + 'props' => $event->{'props'}, + 'tz' => 'guess', + }; + + my $res = LJ::Protocol::do_request("postevent", $req, \$err); + + if ($err) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($err)) + ->faultcode(substr($err, 0, 3)); + } + + return "$journal:$res->{'itemid'}"; +} + +sub deletePost { + shift; + my ($appkey, $postid, $user, $password, $content, $publish) = @_; + return editPost(undef, $appkey, $postid, $user, $password, "", $publish); +} + +sub editPost { + shift; + my ($appkey, $postid, $user, $password, $content, $publish) = @_; + + die "Invalid postid\n" unless $postid =~ /^(\w+):(\d+)$/; + my ($journal, $itemid) = ($1, $2); + + my $event = LJ::Util::blogger_deserialize($content); + + my $req = { + 'usejournal' => $journal ne $user ? $journal : undef, + 'ver' => 1, + 'username' => $user, + 'password' => $password, + 'event' => $event->{'event'}, + 'subject' => $event->{'subject'}, + 'props' => $event->{'props'}, + 'itemid' => $itemid, + }; + + my $err; + my $res = LJ::Protocol::do_request("editevent", $req, \$err); + + if ($err) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($err)) + ->faultcode(substr($err, 0, 3)); + } + + return 1; +} + +sub getUsersBlogs { + shift; + my ($appkey, $user, $password) = @_; + + my $u = LJ::load_user($user) or die "Invalid login\n"; + die "Invalid login\n" unless LJ::auth_okay($u, $password); + + my $ids = LJ::load_rel_target($u, 'P'); + my $us = LJ::load_userids(@$ids); + my @list = ($u); + foreach (sort { $a->{user} cmp $b->{user} } values %$us) { + next unless $_->{'statusvis'} eq "V"; + push @list, $_; + } + + return [ map { { + 'url' => LJ::journal_base($_) . "/", + 'blogid' => $_->{'user'}, + 'blogName' => $_->{'name'}, + } } @list ]; +} + +sub getRecentPosts { + shift; + my ($appkey, $journal, $user, $password, $numposts) = @_; + + $numposts = int($numposts); + $numposts = 1 if $numposts < 1; + $numposts = 50 if $numposts > 50; + + my $req = { + 'usejournal' => $journal ne $user ? $journal : undef, + 'ver' => 1, + 'username' => $user, + 'password' => $password, + 'selecttype' => 'lastn', + 'howmany' => $numposts, + }; + + my $err; + my $res = LJ::Protocol::do_request("getevents", $req, \$err); + + if ($err) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($err)) + ->faultcode(substr($err, 0, 3)); + } + + return [ map { { + 'content' => LJ::Util::blogger_serialize($_), + 'userID' => $_->{'poster'} || $journal, + 'postId' => "$journal:$_->{'itemid'}", + 'dateCreated' => LJ::Util::mysql_date_to_iso($_->{'eventtime'}), + } } @{$res->{'events'}} ]; +} + +sub getPost { + shift; + my ($appkey, $postid, $user, $password) = @_; + + die "Invalid postid\n" unless $postid =~ /^(\w+):(\d+)$/; + my ($journal, $itemid) = ($1, $2); + + my $req = { + 'usejournal' => $journal ne $user ? $journal : undef, + 'ver' => 1, + 'username' => $user, + 'password' => $password, + 'selecttype' => 'one', + 'itemid' => $itemid, + }; + + my $err; + my $res = LJ::Protocol::do_request("getevents", $req, \$err); + + if ($err) { + die SOAP::Fault + ->faultstring(LJ::Protocol::error_message($err)) + ->faultcode(substr($err, 0, 3)); + } + + die "Post not found\n" unless $res->{'events'}->[0]; + + return map { { + 'content' => LJ::Util::blogger_serialize($_), + 'userID' => $_->{'poster'} || $journal, + 'postId' => "$journal:$_->{'itemid'}", + 'dateCreated' => LJ::Util::mysql_date_to_iso($_->{'eventtime'}), + } } $res->{'events'}->[0]; +} + +sub getTemplate { die "$LJ::SITENAME doesn't support Blogger Templates. To customize your journal, visit $LJ::SITENAME/customize/"; } +*setTemplate = \&getTemplate; + +sub getUserInfo { + shift; + my ($appkey, $user, $password) = @_; + + my $u = LJ::load_user($user) or die "Invalid login\n"; + die "Invalid login\n" unless LJ::auth_okay($u, $password); + + LJ::load_user_props($u, "url"); + + return { + 'userid' => $u->{'userid'}, + 'nickname' => $u->{'user'}, + 'firstname' => $u->{'name'}, + 'lastname' => $u->{'name'}, + 'email' => $u->{'email'}, + 'url' => $u->{'url'}, + }; +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal/Interface/FotoBilder.pm b/livejournal/cgi-bin/Apache/LiveJournal/Interface/FotoBilder.pm new file mode 100755 index 0000000..f4140d1 --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal/Interface/FotoBilder.pm @@ -0,0 +1,207 @@ +#!/usr/bin/perl +# + +package Apache::LiveJournal::Interface::FotoBilder; + +use strict; +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED + HTTP_MOVED_PERMANENTLY BAD_REQUEST); + +sub run_method +{ + my $cmd = shift; + + # Available functions for this interface. + my $interface = { + 'checksession' => \&checksession, + 'get_user_info' => \&get_user_info, + 'makechals' => \&makechals, + 'set_quota' => \&set_quota, + 'user_exists' => \&user_exists, + 'get_auth_challenge' => \&get_auth_challenge, + 'get_groups' => \&get_groups, + }; + return undef unless $interface->{$cmd}; + + return $interface->{$cmd}->(@_); +} + +sub handler +{ + my $r = shift; + my $uri = $r->uri; + return 404 unless $uri =~ m#^/interface/fotobilder(?:/(\w+))?$#; + my $cmd = $1; + + return BAD_REQUEST unless $r->method eq "POST"; + + $r->content_type("text/plain"); + $r->send_http_header(); + + my %POST = $r->content; + my $res = run_method($cmd, \%POST) + or return BAD_REQUEST; + + $res->{"fotobilder-interface-version"} = 1; + + $r->print(join("", map { "$_: $res->{$_}\n" } keys %$res)); + + return OK; +} + +# Is there a current LJ session? +# If so, return info. +sub get_user_info +{ + my $POST = shift; + BML::reset_cookies(); + $LJ::_XFER_REMOTE_IP = $POST->{'remote_ip'}; + + # try to get a $u from the passed uid or user, falling back to the ljsession cookie + my $u; + if ($POST->{uid}) { + $u = LJ::load_userid($POST->{uid}); + } elsif ($POST->{user}) { + $u = LJ::load_user($POST->{user}); + } else { + $u = LJ::get_remote(); + } + return {} unless $u && $u->{'journaltype'} eq 'P'; + + my %ret = ( + user => $u->{user}, + userid => $u->{userid}, + statusvis => $u->{statusvis}, + can_upload => can_upload($u), + gallery_enabled => can_upload($u), + diskquota => LJ::get_cap($u, 'disk_quota') * (1 << 20), # mb -> bytes + fb_account => LJ::get_cap($u, 'fb_account'), + fb_usage => LJ::Blob::get_disk_usage($u, 'fotobilder'), + ); + + # when the set_quota rpc call is executed (below), a placholder row is inserted + # into userblob. it's just used for livejournal display of what we last heard + # fotobilder disk usage was, but we need to subtract that out before we report + # to fotobilder how much disk the user is using on livejournal's end + $ret{diskused} = LJ::Blob::get_disk_usage($u) - $ret{fb_usage}; + + return \%ret unless $POST->{fullsync}; + + LJ::fill_groups_xmlrpc($u, \%ret); + return \%ret; +} + +# Forcefully push user info out to FB. +# We use this for cases where we don't want to wait for +# sync cache timeouts, such as user suspensions. +sub push_user_info +{ + my $uid = LJ::want_userid( shift() ); + return unless $uid; + + my $ret = get_user_info({ uid => $uid }); + + eval "use XMLRPC::Lite;"; + return if $@; + + return XMLRPC::Lite + -> proxy("$LJ::FB_SITEROOT/interface/xmlrpc") + -> call('FB.XMLRPC.update_userinfo', $ret) + -> result; +} + +# get_user_info above used to be called 'checksession', maintain +# an alias for compatibility +sub checksession { get_user_info(@_); } + +sub get_groups { + my $POST = shift; + my $u = LJ::load_user($POST->{user}); + return {} unless $u; + + my %ret = (); + LJ::fill_groups_xmlrpc($u, \%ret); + return \%ret; +} + +# Pregenerate a list of challenge/responses. +sub makechals +{ + my $POST = shift; + my $count = int($POST->{'count'}) || 1; + if ($count > 50) { $count = 50; } + my $u = LJ::load_user($POST->{'user'}); + return {} unless $u; + + my %ret = ( count => $count ); + + for (my $i=1; $i<=$count; $i++) { + my $chal = LJ::rand_chars(40); + my $resp = Digest::MD5::md5_hex($chal . Digest::MD5::md5_hex($u->{'password'})); + $ret{"chal_$i"} = $chal; + $ret{"resp_$i"} = $resp; + } + + return \%ret; +} + +# Does the user exist? +sub user_exists +{ + my $POST = shift; + my $u = LJ::load_user($POST->{'user'}); + return {} unless $u; + + return { + exists => 1, + can_upload => can_upload($u), + }; +} + +# Mirror FB quota information over to LiveJournal. +# 'user' - username +# 'used' - FB disk usage in bytes +sub set_quota +{ + my $POST = shift; + my $u = LJ::load_userid($POST->{'uid'}); + return {} unless $u && defined $POST->{'used'}; + + return {} unless $u->writer; + + my $used = $POST->{'used'} * (1 << 10); # Kb -> bytes + my $result = $u->do('REPLACE INTO userblob SET ' . + 'domain=?, length=?, journalid=?, blobid=0', + undef, LJ::get_blob_domainid('fotobilder'), + $used, $u->{'userid'}); + + LJ::set_userprop($u, "fb_num_pubpics", $POST->{'pub_pics'}); + + return { + status => ($result ? 1 : 0), + }; +} + +sub get_auth_challenge +{ + my $POST = shift; + + return { + chal => LJ::challenge_generate($POST->{goodfor}+0), + }; +} + +######################################################################### +# non-interface helper functions +# + +# Does the user have upload access? +sub can_upload +{ + my $u = shift; + + return LJ::get_cap($u, 'fb_account') + && LJ::get_cap($u, 'fb_can_upload') ? 1 : 0; +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal/Interface/S2.pm b/livejournal/cgi-bin/Apache/LiveJournal/Interface/S2.pm new file mode 100755 index 0000000..234be28 --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal/Interface/S2.pm @@ -0,0 +1,124 @@ +#!/usr/bin/perl +# + +package Apache::LiveJournal::Interface::S2; + +use strict; +use MIME::Base64 (); +use Apache::Constants; + +sub handler { + my $r = shift; + + my $meth = $r->method(); + my %GET = $r->args(); + my $uri = $r->uri(); + my $id; + if ($uri =~ m!^/interface/s2/(\d+)$!) { + $id = $1 + 0; + } else { + return NOT_FOUND; + } + + my $lay = LJ::S2::load_layer($id); + return error($r, 404, 'Layer not found', "There is no layer with id $id at this site") + unless $lay; + + LJ::auth_digest($r); + my $u = LJ::get_remote(); + unless ($u) { + # Tell the client how it can authenticate + # use digest authorization. + + $r->send_http_header("text/plain; charset=utf-8"); + $r->print("Unauthorized\nYou must send your $LJ::SITENAME username and password or a valid session cookie\n"); + + return OK; + } + + my $dbr = LJ::get_db_reader(); + + my $lu = LJ::load_userid($lay->{'userid'}); + + return error($r, 500, "Error", "Unable to find layer owner.") + unless $lu; + + if ($meth eq 'GET') { + + return error($r, 403, "Forbidden", "You are not authorized to retrieve this layer") + unless $lu->{'user'} eq 'system' || LJ::can_manage($u, $lu); + + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ? + $layerinfo->{$id}->{'source_viewable'} : 1; + + # Disallow retrieval of protected system layers + return error($r, 403, "Forbidden", "The requested layer is restricted") + if $lu->{'user'} eq 'system' && ! $srcview; + + my $s2code = $dbr->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $id); + + $r->send_http_header("application/x-danga-s2-layer"); + $r->print($s2code); + + } + elsif ($meth eq 'PUT') { + + return error($r, 403, "Forbidden", "You are not authorized to edit this layer") + unless LJ::can_manage($u, $lu); + + return error($r, 403, "Forbidden", "Your account type is not allowed to edit layers") + unless LJ::get_cap($u, "s2styles"); + + # Read in the entity body to get the source + my $len = $r->header_in("Content-length")+0; + + return error($r, 400, "Bad Request", "Supply S2 layer code in the request entity body and set Content-length") + unless $len; + + return error($r, 415, "Bad Media Type", "Request body must be of type application/x-danga-s2-layer") + unless lc($r->header_in("Content-type")) eq 'application/x-danga-s2-layer'; + + my $s2code; + $r->read($s2code, $len); + + my $error = ""; + LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$s2code }); + + if ($error) { + error($r, 500, "Layer Compile Error", "An error was encountered while compiling the layer."); + + ## Strip any absolute paths + $error =~ s/LJ::.+//s; + $error =~ s!, .+?(src/s2|cgi-bin)/!, !g; + + print $error; + return OK; + } + else { + $r->status_line("201 Compiled and Saved"); + $r->header_out("Location" => "$LJ::SITEROOT/interface/s2/$id"); + $r->send_http_header("text/plain; charset=utf-8"); + $r->print("Compiled and Saved\nThe layer was uploaded successfully.\n"); + } + } + else { + # Return 'method not allowed' so that we can add methods in future + # and clients will get a sensible error from old servers. + return error($r, 405, 'Method Not Allowed', 'Only GET and PUT are supported for this resource'); + } +} + +sub error { + my ($r, $code, $string, $long) = @_; + + $r->status_line("$code $string"); + $r->send_http_header("text/plain; charset=utf-8"); + $r->print("$string\n$long\n"); + + # Tell Apache OK so it won't try to handle the error + return OK; +} + +1; diff --git a/livejournal/cgi-bin/Apache/LiveJournal/PalImg.pm b/livejournal/cgi-bin/Apache/LiveJournal/PalImg.pm new file mode 100755 index 0000000..46b0c41 --- /dev/null +++ b/livejournal/cgi-bin/Apache/LiveJournal/PalImg.pm @@ -0,0 +1,152 @@ +#!/usr/bin/perl +# + +package Apache::LiveJournal::PalImg; + +use strict; +use Apache::Constants qw(:common REDIRECT HTTP_NOT_MODIFIED); +use PaletteModify; + +# URLs of form /palimg/somedir/file.gif[extra] +# where extras can be: +# /p... - palette modify + +sub handler +{ + my $r = shift; + my $uri = $r->uri; + my ($base, $ext, $extra) = $uri =~ m!^/palimg/(.+)\.(\w+)(.*)$!; + $r->notes("codepath" => "img.palimg"); + return 404 unless $base && $base !~ m!\.\.!; + + my $disk_file = "$LJ::HOME/htdocs/palimg/$base.$ext"; + return 404 unless -e $disk_file; + + my @st = stat(_); + my $size = $st[7]; + my $modtime = $st[9]; + my $etag = "$modtime-$size"; + + my $mime = { + 'gif' => 'image/gif', + 'png' => 'image/png', + }->{$ext}; + + my $palspec; + if ($extra) { + if ($extra =~ m!^/p(.+)$!) { + $palspec = $1; + } else { + return 404; + } + } + + return send_file($r, $disk_file, { + 'mime' => $mime, + 'etag' => $etag, + 'palspec' => $palspec, + 'size' => $size, + 'modtime' => $modtime, + }); +} + +sub parse_hex_color +{ + my $color = shift; + return [ map { hex(substr($color, $_, 2)) } (0,2,4) ]; +} + +sub send_file +{ + my ($r, $disk_file, $opts) = @_; + + my $etag = $opts->{'etag'}; + + # palette altering + my %pal_colors; + if (my $pals = $opts->{'palspec'}) { + my $hx = "[0-9a-f]"; + if ($pals =~ /^g($hx{2,2})($hx{6,6})($hx{2,2})($hx{6,6})$/) { + # gradient from index $1, color $2, to index $3, color $4 + my $from = hex($1); + my $to = hex($3); + return 404 if $from == $to; + my $fcolor = parse_hex_color($2); + my $tcolor = parse_hex_color($4); + if ($to < $from) { + ($from, $to, $fcolor, $tcolor) = + ($to, $from, $tcolor, $fcolor); + } + $etag .= ":pg$pals"; + for (my $i=$from; $i<=$to; $i++) { + $pal_colors{$i} = [ map { + int($fcolor->[$_] + + ($tcolor->[$_] - $fcolor->[$_]) * + ($i-$from) / ($to-$from)) + } (0..2) ]; + } + } elsif ($pals =~ /^t($hx{6,6})($hx{6,6})?$/) { + # tint everything towards color + my ($t, $td) = ($1, $2); + $pal_colors{'tint'} = parse_hex_color($t); + $pal_colors{'tint_dark'} = $td ? parse_hex_color($td) : [0,0,0]; + } elsif (length($pals) > 42 || $pals =~ /[^0-9a-f]/) { + return 404; + } else { + my $len = length($pals); + return 404 if $len % 7; # must be multiple of 7 chars + for (my $i = 0; $i < $len/7; $i++) { + my $palindex = hex(substr($pals, $i*7, 1)); + $pal_colors{$palindex} = [ + hex(substr($pals, $i*7+1, 2)), + hex(substr($pals, $i*7+3, 2)), + hex(substr($pals, $i*7+5, 2)), + substr($pals, $i*7+1, 6), + ]; + } + $etag .= ":p$_($pal_colors{$_}->[3])" for (sort keys %pal_colors); + } + } + + $etag = '"' . $etag . '"'; + my $ifnonematch = $r->header_in("If-None-Match"); + return HTTP_NOT_MODIFIED if + defined $ifnonematch && $etag eq $ifnonematch; + + # send the file + $r->content_type($opts->{'mime'}); + $r->header_out("Content-length", $opts->{'size'}); + $r->header_out("ETag", $etag); + if ($opts->{'modtime'}) { + $r->update_mtime($opts->{'modtime'}); + $r->set_last_modified(); + } + $r->send_http_header(); + + # HEAD request? + return OK if $r->method eq "HEAD"; + + my $fh = Apache::File->new($disk_file); + return 404 unless $fh; + binmode($fh); + + my $palette; + if (%pal_colors) { + if ($opts->{'mime'} eq "image/gif") { + $palette = PaletteModify::new_gif_palette($fh, \%pal_colors); + } elsif ($opts->{'mime'} == "image/png") { + $palette = PaletteModify::new_png_palette($fh, \%pal_colors); + } + unless ($palette) { + return 404; # image isn't palette changeable? + } + } + + $r->print($palette) if $palette; # when palette modified. + $r->send_fd($fh); # sends remaining data (or all of it) quickly + $fh->close(); + return OK; +} + +1; + diff --git a/livejournal/cgi-bin/Apache/SendStats.pm b/livejournal/cgi-bin/Apache/SendStats.pm new file mode 100755 index 0000000..cb330e1 --- /dev/null +++ b/livejournal/cgi-bin/Apache/SendStats.pm @@ -0,0 +1,148 @@ +#!/usr/bin/perl +# + +package Apache::SendStats; + +BEGIN { + $LJ::HAVE_INLINE = eval q{ + use Inline (C => 'DATA', + DIRECTORY => $ENV{LJ_INLINE_DIR} ||"$ENV{'LJHOME'}/Inline", + ); + 1; + }; +} +use strict; +use IO::Socket::INET; +use Apache::Constants qw(:common); + +if ($LJ::HAVE_INLINE && $LJ::FREECHILDREN_BCAST) { + eval { + Inline->init(); + }; + if ($@ && ! $LJ::JUST_COMPILING) { + print STDERR "Warning: You seem to have Inline.pm, but you haven't run \$LJHOME/bin/lj-inline.pl. " . + "Continuing without it, but stats won't broadcast.\n"; + $LJ::HAVE_INLINE = 0; + } +} + +use vars qw(%udp_sock); + +sub handler +{ + my $r = shift; + return OK if $r->main; + return OK unless $LJ::HAVE_INLINE && $LJ::FREECHILDREN_BCAST; + + my $callback = $r->current_callback() if $r; + my $cleanup = $callback eq "PerlCleanupHandler"; + my $childinit = $callback eq "PerlChildInitHandler"; + + if ($LJ::TRACK_URL_ACTIVE) + { + my $key = "url_active:$LJ::SERVER_NAME:$$"; + if ($cleanup) { + LJ::MemCache::delete($key); + } else { + LJ::MemCache::set($key, $r->uri . "(" . $r->method . "/" . scalar($r->args) . ")"); + } + } + + my ($active, $free) = count_servers(); + + $free += $cleanup; + $free += $childinit; + $active -= $cleanup if $active; + + my $list = ref $LJ::FREECHILDREN_BCAST ? + $LJ::FREECHILDREN_BCAST : [ $LJ::FREECHILDREN_BCAST ]; + + foreach my $host (@$list) { + next unless $host =~ /^(\S+):(\d+)$/; + my $bcast = $1; + my $port = $2; + my $sock = $udp_sock{$host}; + unless ($sock) { + $udp_sock{$host} = $sock = IO::Socket::INET->new(Proto => 'udp'); + if ($sock) { + $sock->sockopt(SO_BROADCAST, 1); + } else { + $r->log_error("SendStats: couldn't create socket: $host"); + next; + } + } + + my $ipaddr = inet_aton($bcast); + my $portaddr = sockaddr_in($port, $ipaddr); + my $message = "bcast_ver=1\nfree=$free\nactive=$active\n"; + my $res = $sock->send($message, 0, $portaddr); + $r->log_error("SendStats: couldn't broadcast") + unless $res; + } + + return OK; +} + +1; + +__DATA__ +__C__ + +extern unsigned char *ap_scoreboard_image; + +/* + * the following structure is for Linux on i32 ONLY! It makes certan + * choices where apache's scoreboard.h has #ifdef's. See scoreboard.h + * for real declarations, here we only name a few things we actually need. + */ + +/* total length of struct should be 164 bytes */ +typedef struct { + int foo1; + short foo2; + unsigned char status; + int foo3[39]; +} short_score; + +/* length should be 16 bytes */ +typedef struct { + int pid; + int foo[3]; +} parent_score; + +static int hard_limit = 512; /* array size on debian */ + +/* + * Scoreboard is laid out like this: array of short_score structs, + * then array of parent_score structs, then one int, the generation + * number. Both arrays are of size HARD_SERVERS_LIMIT, 256 by default + * on Unixes. + */ + + +void count_servers() { + int i, count_free, count_active; + short_score *ss; + parent_score *ps; + Inline_Stack_Vars; + + ss = (short_score *)ap_scoreboard_image; + ps = (parent_score *) ((unsigned char *)ap_scoreboard_image + sizeof(short_score)*hard_limit); + + count_free = 0; count_active = 0; + for (i=0; i 2) /* busy doing something */ + count_active++; + } + Inline_Stack_Reset; + Inline_Stack_Push(newSViv(count_active)); + Inline_Stack_Push(newSViv(count_free)); + Inline_Stack_Done; + + return; +} + + + diff --git a/livejournal/cgi-bin/BlobClient.pm b/livejournal/cgi-bin/BlobClient.pm new file mode 100755 index 0000000..50cbc6d --- /dev/null +++ b/livejournal/cgi-bin/BlobClient.pm @@ -0,0 +1,51 @@ +#!/usr/bin/perl +# vim:ts=4 sw=4 et: + +use strict; +use BlobClient::Remote; +use BlobClient::Local; + +package BlobClient; + +sub new { + my ($class, $args) = @_; + my $self = {}; + $self->{path} = $args->{path}; + $self->{path} =~ s!/$!!; + $self->{backup_path} = $args->{backup_path}; + $self->{backup_path} =~ s!/$!!; + bless $self, ref $class || $class; + return $self; +} + +sub _make_path { + my ($cid, $uid, $domain, $fmt, $bid) = @_; + die "bogus domain" unless $domain =~ /^\w{1,40}$/; + die "bogus format" unless $fmt =~ /^\w{1,10}$/; + + sprintf("%07d", $uid) =~ /^(\d+)(\d\d\d)(\d\d\d)$/; + my ($uid1, $uid2, $uid3) = ($1, $2, $3); + + sprintf("%04d", $bid) =~ /^(\d+)(\d\d\d)$/; + my ($bid1, $bid2) = ($1, $2); + return join('/', int($cid), $uid1, $uid2, $uid3, $domain, $bid1, $bid2) . ".$fmt"; +} + +sub make_path { + my $self = shift; + return $self->{path} . '/' . _make_path(@_); +} + +sub make_backup_path { + my $self = shift; + my $path = $self->{backup_path}; + return undef unless $path; # if no backup_path, just return undef + return $path . '/' . _make_path(@_); +} + +# derived classes will override this. +sub is_dead { + return 0; +} + +1; diff --git a/livejournal/cgi-bin/BlobClient/Local.pm b/livejournal/cgi-bin/BlobClient/Local.pm new file mode 100755 index 0000000..54726d3 --- /dev/null +++ b/livejournal/cgi-bin/BlobClient/Local.pm @@ -0,0 +1,114 @@ +#!/usr/bin/perl +# vim:ts=4 sw=4 et: + +use strict; +package BlobClient::Local; + +use IO::File; +use File::Path; +use Time::HiRes qw{gettimeofday tv_interval}; + +use constant DEBUG => 0; + +use BlobClient; +our @ISA = ("BlobClient"); + +sub new { + my ($class, $args) = @_; + my $self = $class->SUPER::new($args); + bless $self, ref $class || $class; + return $self; +} + +### Time a I and send a report for the specified I with the given +### I when it finishes. +sub report_blocking_time (&@) { + my ( $block, $op, $notes, $host ) = ( @_ ); + + my $start = [gettimeofday()]; + my $rval = $block->(); + LJ::blocking_report( $host, "blob_$op", tv_interval($start), $notes ); + + return $rval; +} + +sub get { + my ($self, $cid, $uid, $domain, $fmt, $bid) = @_; + my $fh = new IO::File; + local $/ = undef; + my $path = make_path(@_); + print STDERR "Blob::Local: requesting $path\n" if DEBUG; + + my $data; + report_blocking_time { + unless (open($fh, '<', $path)) { + return undef; + } + print STDERR "Blob::Local: serving $path\n" if DEBUG; + $data = <$fh>; + close($fh); + } "get", $path, $self->{path}; + + return $data; +} + +sub get_stream { + my ($self, $cid, $uid, $domain, $fmt, $bid, $callback, $errref) = @_; + + my $fh = new IO::File; + my $path = make_path(@_); + + my $data; + report_blocking_time { + unless (open($fh, '<', $path)) { + $$errref = "Error opening '$path'"; + return undef; + } + while (read($fh, $data, 1024*50)) { + $callback->($data); + } + close($fh); + } "get_stream", $path, $self->{path}; + + return 1; +} + +sub put { + my ($self, $cid, $uid, $fmt, $domain, $bid, $content) = @_; + + my $filename = make_path(@_); + + my $dir = File::Basename::dirname($filename); + eval { File::Path::mkpath($dir, 0, 0775); }; + return undef if $@; + + report_blocking_time { + my $fh = new IO::File; + unless (open($fh, '>', $filename)) { + return undef; + } + print $fh $content; + close $fh; + } "put", $filename, $self->{path}; + + return 1; +} + +sub delete { + my ($self, $cid, $uid, $fmt, $domain, $bid) = @_; + + my $filename = make_path(@_); + + return 0 unless -e $filename; + my $rval; + report_blocking_time { + # FIXME: rmdir up the tree + $rval = unlink($filename); + } "delete", $filename, $self->{path}; + + return $rval; +} + +sub make_path { my $self = shift; return $self->SUPER::make_path(@_); } + +1; diff --git a/livejournal/cgi-bin/BlobClient/Remote.pm b/livejournal/cgi-bin/BlobClient/Remote.pm new file mode 100755 index 0000000..369a533 --- /dev/null +++ b/livejournal/cgi-bin/BlobClient/Remote.pm @@ -0,0 +1,164 @@ +#!/usr/bin/perl +# vim:ts=4 sw=4 et: + +package BlobClient::Remote; + +use BlobClient; +use LWP::UserAgent; +use Time::HiRes qw{gettimeofday tv_interval}; +use vars qw(@ISA); +@ISA = qw(BlobClient); + +use strict; + +use constant DEBUG => 0; +use constant DEADTIME => 30; + +use BlobClient; + +### Time a I and send a report for the specified I with the given +### I when it finishes. +sub report_blocking_time (&@) { + my ( $block, $op, $notes, $host ) = ( @_ ); + + my $start = [gettimeofday()]; + my $rval = $block->(); + LJ::blocking_report( $host, "blob_$op", tv_interval($start), $notes ); + + return $rval; +} + +sub new { + my ($class, $args) = @_; + my $self = $class->SUPER::new($args); + + $self->{ua} = LWP::UserAgent->new(agent=>'blobclient', timeout => 4); + + bless $self, ref $class || $class; + return $self; +} + +sub get { + my ($self, $cid, $uid, $domain, $fmt, $bid, $use_backup) = @_; + my $path = $use_backup ? make_backup_path(@_) : make_path(@_); + return undef unless $path; # if no path, we fail + + print STDERR "Blob::Remote requesting $path (backup path? $use_backup)\n" if DEBUG; + my $req = HTTP::Request->new(GET => $path); + + my $res; + report_blocking_time { + eval { $res = $self->{ua}->request($req); }; + } "get", $path, $self->{path}; + return $res->content if $res->is_success; + + # two types of failure: server dead, or just a 404. + # a 404 doesn't mean the server is necessarily bad. + + if ($res->code == 500) { + # server dead. + if ($use_backup) { + # can't reach backup server, we're really dead + $self->{deaduntil} = time() + DEADTIME; + } else { + # try using a backup + return $self->get($cid, $uid, $domain, $fmt, $bid, 1); + } + } + return undef; +} + +sub get_stream { + my ($self, $cid, $uid, $domain, $fmt, $bid, $callback, $use_backup) = @_; + my $path = $use_backup ? make_backup_path(@_) : make_path(@_); + return undef unless $path; # if no path, we fail + + my $req = HTTP::Request->new(GET => $path); + + my $res; + report_blocking_time { + eval { $res = $self->{ua}->request($req, $callback, 1024*50); }; + } "get_stream", $path, $self->{path}; + + return $res->is_success if $res->is_success; + + # must have failed + if ($res->code == 500) { + # server dead. + if ($use_backup) { + # can't reach backup server, we're really dead + $self->{deaduntil} = time() + DEADTIME; + } else { + # try using a backup + return $self->get_stream($cid, $uid, $domain, $fmt, $bid, $callback, 1); + } + } + return undef; +} + +sub put { + my ($self, $cid, $uid, $domain, $fmt, $bid, $content, $errref, $use_backup) = @_; + my $path = $use_backup ? make_backup_path(@_) : make_path(@_); + return 0 unless $path; # if no path, we fail + + my $req = HTTP::Request->new(PUT => $path); + + $req->content($content); + + my $res; + report_blocking_time { + eval { $res = $self->{ua}->request($req); }; + } "put", $path, $self->{path}; + + unless ($res->is_success) { + if ($use_backup) { + # total failure + $$errref = "$path: " . $res->status_line if $errref; + return 0; + } else { + # try backup + return $self->put($cid, $uid, $domain, $fmt, $bid, $content, $errref, 1); + } + } + return 1; +} + +sub delete { + my ($self, $cid, $uid, $domain, $fmt, $bid, $use_backup) = @_; + my $path = $use_backup ? make_backup_path(@_) : make_path(@_); + return 0 unless $path; # if no path, we fail + + my $req = HTTP::Request->new(DELETE => $path); + + my $res; + report_blocking_time { + eval { $res = $self->{ua}->request($req); }; + } "delete", $path, $self->{path}; + + return 1 if $res && $res->code == 404; + unless ($res->is_success) { + if ($res->code == 500) { + if ($use_backup) { + # total failure! + return 0; + } else { + # try again + return $self->delete($cid, $uid, $domain, $fmt, $bid, 1); + } + } + return 0; + } + return 1; +} + +sub is_dead { + my $self = shift; + delete $self->{deaduntil} if $self->{deaduntil} <= time(); + return $self->{deaduntil} > 0; +} + +### [MG]: Hmmm... no-op? +sub make_path { my $self = shift; return $self->SUPER::make_path(@_); } +sub make_backup_path { my $self = shift; return $self->SUPER::make_backup_path(@_); } + +1; diff --git a/livejournal/cgi-bin/LJ/Blob.pm b/livejournal/cgi-bin/LJ/Blob.pm new file mode 100755 index 0000000..f343abf --- /dev/null +++ b/livejournal/cgi-bin/LJ/Blob.pm @@ -0,0 +1,150 @@ +# Wrapper around BlobClient. + +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use BlobClient; + +package LJ::Blob; + +my %bc_cache = (); +my %bc_reader_cache = (); +my %bc_path_reader_cache = (); + +# read-write (i.e. HTTP connection to BlobServer, with NetApp NFS mounted) +sub get_blobclient { + my $u = shift; + my $bcid = $u->{blob_clusterid} or die "No blob_clusterid"; + return $bc_cache{$bcid} ||= + _bc_from_path($LJ::BLOBINFO{clusters}->{$bcid}, + $LJ::BLOBINFO{clusters}->{"$bcid-BACKUP"}); +} + +# read-only access. (i.e. direct HTTP connection to NetApp) +sub get_blobclient_reader { + my $u = shift; + my $bcid = $u->{blob_clusterid} or die "No blob_clusterid"; + + return $bc_reader_cache{$bcid} if $bc_reader_cache{$bcid}; + + my $path = $LJ::BLOBINFO{clusters}->{"$bcid-GET"} || + $LJ::BLOBINFO{clusters}->{$bcid}; + my $bpath = $LJ::BLOBINFO{clusters}->{"$bcid-BACKUP"}; + + return $bc_reader_cache{$bcid} = _bc_from_path($path, $bpath); +} + +sub _bc_from_path { + my ($path, $bpath) = @_; + if ($path =~ /^http/) { + $bpath = undef unless $bpath =~ /^http/; + return BlobClient::Remote->new({ path => $path, backup_path => $bpath }); + } elsif ($path) { + return BlobClient::Local->new({ path => $path }); + } + return undef; +} + +# given a $u, returns that user's blob_clusterid, conditionally loading it +sub _load_bcid { + my $u = shift; + die "No user" unless $u; + return $u->{blob_clusterid} if $u->{blob_clusterid}; + + # if the entire system only has one blob_clusterid, use that + # without querying the database/memcache + return $u->{blob_clusterid} = $LJ::ONLY_BLOB_CLUSTERID + if defined $LJ::ONLY_BLOB_CLUSTERID; + + LJ::load_user_props($u, "blob_clusterid"); + return $u->{blob_clusterid} if $u->{blob_clusterid}; + die "Couldn't find user $u->{user}'s blob_clusterid\n"; +} + +# args: u, domain, fmt, bid +# des-fmt: string file extension ("jpg", "gif", etc) +# des-bid: numeric blob id for this domain +# des-domain: string name of domain ("userpic", "phonephost", etc) +sub get { + my ($u, $domain, $fmt, $bid) = @_; + _load_bcid($u); + my $bc = get_blobclient_reader($u); + return $bc->get($u->{blob_clusterid}, $u->{userid}, $domain, $fmt, $bid); +} + +# Return a path relative to the specified I for the given arguments. +# args: root, u, domain, fmt, bid +# des-root: Root path +# des-fmt: string file extension ("jpg", "gif", etc) +# des-bid: numeric blob id for this domain +# des-domain: string name of domain ("userpic", "phonephost", etc) +sub get_rel_path { + my ( $root, $u, $domain, $fmt, $bid ) = @_; + + my $bcid = _load_bcid( $u ); + my $bc = $bc_path_reader_cache{ "$bcid:$root" } ||= new BlobClient::Local ({ path => $root }); + + return $bc->make_path( $bcid, $u->{userid}, $domain, $fmt, $bid ); +} + + +sub get_stream { + my ($u, $domain, $fmt, $bid, $callback) = @_; + _load_bcid($u); + my $bc = get_blobclient_reader($u); + return $bc->get_stream($u->{blob_clusterid}, $u->{userid}, $domain, $fmt, $bid, $callback); +} + +sub put { + my ($u, $domain, $fmt, $bid, $data, $errref) = @_; + _load_bcid($u); + my $bc = get_blobclient($u); + + unless ($u->writer) { + $$errref = "nodb"; + return 0; + } + + unless ($bc->put($u->{blob_clusterid}, $u->{userid}, $domain, + $fmt, $bid, $data, $errref)) { + return 0; + } + + $u->do("INSERT IGNORE INTO userblob (journalid, domain, blobid, length) ". + "VALUES (?, ?, ?, ?)", undef, + $u->{userid}, LJ::get_blob_domainid($domain), + $bid, length($data)); + die "Error doing userblob accounting: " . $u->errstr if $u->err; + return 1; +} + +sub delete { + my ($u, $domain, $fmt, $bid) = @_; + _load_bcid($u); + my $bc = get_blobclient($u); + + return 0 unless $u->writer; + + my $bdid = LJ::get_blob_domainid($domain); + return 0 unless $bc->delete($u->{blob_clusterid}, $u->{userid}, $domain, + $fmt, $bid); + + $u->do("DELETE FROM userblob WHERE journalid=? AND domain=? AND blobid=?", + undef, $u->{userid}, $bdid, $bid); + die "Error doing userblob accounting: " . $u->errstr if $u->err; + return 1; +} + +sub get_disk_usage { + my ($u, $domain) = @_; + my $dbcr = LJ::get_cluster_reader($u); + if ($domain) { + return $dbcr->selectrow_array("SELECT SUM(length) FROM userblob ". + "WHERE journalid=? AND domain=?", undef, + $u->{userid}, LJ::get_blob_domainid($domain)); + } else { + return $dbcr->selectrow_array("SELECT SUM(length) FROM userblob ". + "WHERE journalid=?", undef, $u->{userid}); + } +} + +1; diff --git a/livejournal/cgi-bin/LJ/Cache.pm b/livejournal/cgi-bin/LJ/Cache.pm new file mode 100755 index 0000000..6be610e --- /dev/null +++ b/livejournal/cgi-bin/LJ/Cache.pm @@ -0,0 +1,291 @@ +#!/usr/bin/perl +# +# LJ::Cache class +# See perldoc documentation at the end of this file. +# +# ------------------------------------------------------------------------- +# +# This package is released under the LGPL (GNU Library General Public License) +# +# A copy of the license has been included with the software as LGPL.txt. +# If not, the license is available at: +# http://www.gnu.org/copyleft/library.txt +# +# ------------------------------------------------------------------------- +# + +package LJ::Cache; + +use strict; +use fields qw(items size tail head bytes maxsize maxbytes); + +use vars qw($VERSION); +use constant PREVKEY => 0; +use constant VALUE => 1; +use constant NEXTKEY => 2; +use constant BYTES => 3; +use constant INSTIME => 4; +use constant FLAGS => 5; # caller-defined metadata + +$VERSION = '1.0'; + +sub new { + my ($class, $args) = @_; + my $self = fields::new($class); + + $self->init($args); + return $self; +} + +sub walk_items { + my LJ::Cache $self = shift; + my $code = shift; + + my $iter = $self->{'head'}; + while ($iter) { + my $it = $self->{'items'}->{$iter}; + $code->($iter, $it->[BYTES], $it->[INSTIME]); + $iter = $it->[NEXTKEY]; + } +} + +sub init { + my LJ::Cache $self = shift; + my $args = shift; + + $self->{'head'} = 0; + $self->{'tail'} = 0; + $self->{'items'} = {}; # key -> arrayref, indexed by constants above + $self->{'size'} = 0; + $self->{'bytes'} = 0; + $self->{'maxsize'} = $args->{'maxsize'}+0; + $self->{'maxbytes'} = $args->{'maxbytes'}+0; +} + +sub get_item_count { + my LJ::Cache $self = shift; + $self->{'size'}; +} + +sub get_byte_count { + my LJ::Cache $self = shift; + $self->{'bytes'}; +} + +sub get_max_age { + my LJ::Cache $self = shift; + return undef unless $self->{'tail'}; + return $self->{'items'}->{$self->{'tail'}}->[INSTIME]; +} + +sub validate_list +{ + my ($self, $source) = @_; + print "Validate list: $self->{'size'} (max: $self->{'maxsize'})\n"; + + my $count = 1; + if ($self->{'size'} && ! defined $self->{'head'}) { + die "$source: no head pointer\n"; + } + if ($self->{'size'} && ! defined $self->{'tail'}) { + die "$source: no tail pointer\n"; + } + if ($self->{'size'}) { + print " head: $self->{'head'}\n"; + print " tail: $self->{'tail'}\n"; + } + + my $iter = $self->{'head'}; + my $last = undef; + while ($count <= $self->{'size'}) { + if (! defined $iter) { + die "$source: undefined iterator\n"; + } + my $item = $self->{'items'}->{$iter}; + unless (defined $item) { + die "$source: item '$iter' isn't in items\n"; + } + my $prevtext = $item->[PREVKEY] || "--"; + my $nexttext = $item->[NEXTKEY] || "--"; + print " #$count ($iter): [$prevtext, $item->[VALUE], $nexttext]\n"; + if ($count == 1 && defined($item->[0])) { + die "$source: Head element shouldn't have previous pointer!\n"; + } + if ($count == $self->{'size'} && defined($item->[NEXTKEY])) { + die "$source: Last element shouldn't have next pointer!\n"; + } + if (defined $last && ! defined $item->[PREVKEY]) { + die "$source: defined \$last but not defined previous pointer.\n"; + } + if (! defined $last && defined $item->[PREVKEY]) { + die "$source: not defined \$last but previous pointer defined.\n"; + } + if (defined $item->[PREVKEY] && defined $last && $item->[PREVKEY] ne $last) + { + die "$source: Previous pointer is wrong.\n"; + } + + $last = $iter; + $iter = defined $item->[NEXTKEY] ? $item->[NEXTKEY] : undef; + $count++; + } +} + +sub drop_tail +{ + my LJ::Cache $self = shift; + + ## who's going to die? + my $to_die = $self->{'tail'}; + + ## set the tail to the item before the one dying. + $self->{'tail'} = $self->{'items'}->{$to_die}->[PREVKEY]; + + ## adjust the forward pointer on the tail to be undef + if (defined $self->{'tail'}) { + undef $self->{'items'}->{$self->{'tail'}}->[NEXTKEY]; + } + + ## kill the item + my $bytes = $self->{'items'}->{$to_die}->[BYTES]; + delete $self->{'items'}->{$to_die}; + + ## shrink the overall size + $self->{'size'}--; + $self->{'bytes'} -= $bytes; +} + +sub print_list { + my LJ::Cache $self = shift; + + print "Size: $self->{'size'} (max: $self->{'maxsize'})\n"; + + my $count = 1; + my $iter = $self->{'head'}; + while (defined $iter) { #$count <= $self->{'size'}) { + my $item = $self->{'items'}->{$iter}; + print "$count: $iter = $item->[VALUE]\n"; + $iter = $item->[NEXTKEY]; + $count++; + } +} + +sub get { + my LJ::Cache $self = shift; + my ($key, $out_flags) = @_; + + if (exists $self->{'items'}->{$key}) + { + my $item = $self->{'items'}->{$key}; + + # promote this to the head + unless ($self->{'head'} eq $key) + { + if ($self->{'tail'} eq $key) { + $self->{'tail'} = $item->[PREVKEY]; + } + # remove this element from the linked list. + my $next = $item->[NEXTKEY]; + my $prev = $item->[PREVKEY]; + if (defined $next) { $self->{'items'}->{$next}->[PREVKEY] = $prev; } + if (defined $prev) { $self->{'items'}->{$prev}->[NEXTKEY] = $next; } + + # make current head point backwards to this item + $self->{'items'}->{$self->{'head'}}->[PREVKEY] = $key; + + # make this item point forwards to current head, and backwards nowhere + $item->[NEXTKEY] = $self->{'head'}; + undef $item->[PREVKEY]; + + # make this the new head + $self->{'head'} = $key; + } + + $$out_flags = $item->[FLAGS] if $out_flags; + return $item->[VALUE]; + } + return undef; +} + +# bytes is optional +sub set { + my LJ::Cache $self = shift; + my ($key, $value, $bytes, $flags) = @_; + + $self->drop_tail() while ($self->{'maxsize'} && + $self->{'size'} >= $self->{'maxsize'} && + ! exists $self->{'items'}->{$key}) || + ($self->{'maxbytes'} && $self->{'size'} && + $self->{'bytes'} + $bytes >= $self->{'maxbytes'} && + ! exists $self->{'items'}->{$key}); + + + if (exists $self->{'items'}->{$key}) { + # update the value + my $it = $self->{'items'}->{$key}; + $it->[VALUE] = $value; + my $bytedelta = $bytes - $it->[BYTES]; + $self->{'bytes'} += $bytedelta; + $it->[BYTES] = $bytes; + $it->[FLAGS] = $flags; + } else { + # stick it at the end, for now + my $it = $self->{'items'}->{$key} = []; + $it->[PREVKEY] = undef; + $it->[NEXTKEY] = undef; + $it->[VALUE] = $value; + $it->[BYTES] = $bytes; + $it->[INSTIME] = time(); + $it->[FLAGS] = $flags; + if ($self->{'size'}) { + $self->{'items'}->{$self->{'tail'}}->[NEXTKEY] = $key; + $self->{'items'}->{$key}->[PREVKEY] = $self->{'tail'}; + } else { + $self->{'head'} = $key; + } + $self->{'tail'} = $key; + $self->{'size'}++; + $self->{'bytes'} += $bytes; + } + + # this will promote it to the top: + $self->get($key); +} + +1; +__END__ + +=head1 NAME + +LJ::Cache - LRU Cache + +=head1 SYNOPSIS + + use LJ::Cache; + my $cache = new LJ::Cache { 'maxsize' => 20 }; + my $value = $cache->get($key); + unless (defined $value) { + $val = "load some value"; + $cache->set($key, $value); + } + +=head1 DESCRIPTION + +This class implements an LRU dictionary cache. The two operations on it +are get() and set(), both of which promote the key being referenced to +the "top" of the cache, so it will stay alive longest. + +When the cache is full and and a new item needs to be added, the oldest +one is thrown away. + +You should be able to regenerate the data at any time, if get() +returns undef. + +This class is useful for caching information from a slower data source +while also keeping a bound on memory usage. + +=head1 AUTHOR + +Brad Fitzpatrick, bradfitz@bradfitz.com + +=cut diff --git a/livejournal/cgi-bin/LJ/Captcha.pm b/livejournal/cgi-bin/LJ/Captcha.pm new file mode 100755 index 0000000..870a1f1 --- /dev/null +++ b/livejournal/cgi-bin/LJ/Captcha.pm @@ -0,0 +1,423 @@ +#!/usr/bin/perl + +use strict; +package LJ::Captcha; +use GD; +use File::Temp; +use Cwd (); +use Digest::MD5 (); +use LJ::Blob qw{}; +require "$ENV{LJHOME}/cgi-bin/ljlib.pl"; + + +# stolen from Authen::Captcha. code was small enough that duplicating +# was easier than requiring that module, and removing all its automatic +# database tracking stuff and replacing it with ours. maybe we'll move +# to using it in the future, but for now this works. (both their code +# and ours is GPL) +sub generate_visual +{ + my ($code) = @_; + + my $im_width = 25; + my $im_height = 35; + my $length = length($code); + + my $img = "$LJ::HOME/htdocs/img/captcha"; + + # create a new image and color + my $im = new GD::Image(($im_width * $length),$im_height); + my $black = $im->colorAllocate(0,0,0); + + # copy the character images into the code graphic + for(my $i=0; $i < $length; $i++) + { + my $letter = substr($code,$i,1); + my $letter_png = "$img/$letter.png"; + my $source = new GD::Image($letter_png); + $im->copy($source,($i*($im_width),0,0,0,$im_width,$im_height)); + my $a = int(rand (int(($im_width)/14)))+0; + my $b = int(rand (int(($im_height)/12)))+0; + my $c = int(rand (int(($im_width)/3)))-(int(($im_width)/5)); + my $d = int(rand (int(($im_height)/3)))-(int(($im_height)/5)); + $im->copyResized($source,($i*($im_width))+$a,$b,0,0,($im_width)+$c,($im_height)+$d,$im_width,$im_height); + } + + # distort the code graphic + for(my $i=0; $i<($length*$im_width*$im_height/14+150); $i++) + { + my $a = int(rand($length*$im_width)); + my $b = int(rand($im_height)); + my $c = int(rand($length*$im_width)); + my $d = int(rand($im_height)); + my $index = $im->getPixel($a,$b); + if ($i < (($length*($im_width)*($im_height)/14+200)/100)) + { + $im->line($a,$b,$c,$d,$index); + } elsif ($i < (($length*($im_width)*($im_height)/14+200)/2)) { + $im->setPixel($c,$d,$index); + } else { + $im->setPixel($c,$d,$black); + } + } + + # generate a background + my $a = int(rand 5)+1; + my $background_img = "$img/background$a.png"; + my $source = new GD::Image($background_img); + my ($background_width, $background_height) = $source->getBounds(); + my $b = int(rand (int($background_width/13)))+0; + my $c = int(rand (int($background_height/7)))+0; + my $d = int(rand (int($background_width/13)))+0; + my $e = int(rand (int($background_height/7)))+0; + my $source2 = new GD::Image(($length*($im_width)),$im_height); + $source2->copyResized($source,0,0,$b,$c,$length*$im_width,$im_height,$background_width-$b-$d,$background_height-$c-$e); + + # merge the background onto the image + $im->copyMerge($source2,0,0,0,0,($length*($im_width)),$im_height,40); + + # add a border + $im->rectangle(0, 0, $length*$im_width-1, $im_height-1, $black); + + return $im->png; + +} + + +### get_visual_id() -> ( $capid, $anum ) +sub get_visual_id { get_id('image') } +sub get_audio_id { get_id('audio') } + + +### get_id( $type ) -> ( $capid, $anum ) +sub get_id +{ + my ( $type ) = @_; + my ( + $dbh, # Database handle (writer) + $sql, # SQL statement + $row, # Row arrayref + $capid, # Captcha id + $anum, # Unseries-ifier number + $issuedate, # unixtime of issue + ); + + # Fetch database handle and lock the captcha table + $dbh = LJ::get_db_writer() + or return LJ::error( "Couldn't fetch a db writer." ); + $dbh->selectrow_array("SELECT GET_LOCK('get_captcha', 10)") + or return LJ::error( "Failed lock on getting a captcha." ); + + # Fetch the first unassigned row + $sql = q{ + SELECT capid, anum + FROM captchas + WHERE + issuetime = 0 + AND type = ? + LIMIT 1 + }; + $row = $dbh->selectrow_arrayref( $sql, undef, $type ) + or $dbh->do("DO RELEASE_LOCK('get_captcha')") && die "No $type captchas available"; + die "selectrow_arrayref: $sql: ", $dbh->errstr if $dbh->err; + ( $capid, $anum ) = @$row; + + # Mark the captcha as issued + $issuedate = time(); + $sql = qq{ + UPDATE captchas + SET issuetime = $issuedate + WHERE capid = $capid + }; + $dbh->do( $sql ) or die "do: $sql: ", $dbh->errstr; + $dbh->do("DO RELEASE_LOCK('get_captcha')"); + + return ( $capid, $anum ); +} + + +### get_visual_data( $capid, $anum, $want_paths ) +# if want_paths is true, this function may return an arrayref containing +# one or more paths (disk or HTTP) to the resource +sub get_visual_data +{ + my ( $capid, $anum, $want_paths ) = @_; + $capid = int($capid); + + my ( + $dbr, # Database handle (reader) + $sql, # SQL statement + $valid, # Are the capid/anum valid? + $data, # The PNG data + $u, # System user + $location, # Location of the file (mogile/blob) + ); + + $dbr = LJ::get_db_reader(); + $sql = q{ + SELECT capid, location + FROM captchas + WHERE + capid = ? + AND anum = ? + }; + + ( $valid, $location ) = $dbr->selectrow_array( $sql, undef, $capid, $anum ); + return undef unless $valid; + + if ($location eq 'mogile') { + die "MogileFS object not loaded.\n" unless LJ::mogclient(); + if ($want_paths) { + # return path(s) to the content if they want + my @paths = LJ::mogclient()->get_paths("captcha:$capid"); + return \@paths; + } else { + $data = ${LJ::mogclient()->get_file_data("captcha:$capid")}; + } + } else { + $u = LJ::load_user( "system" ) + or die "Couldn't load the system user."; + + $data = LJ::Blob::get( $u, 'captcha_image', 'png', $capid ) + or die "Failed to fetch captcha_image $capid from media server"; + } + return $data; +} + + +### get_audio_data( $capid, $anum, $want_paths ) +# if want_paths is true, this function may return an arrayref containing +# one or more paths (disk or HTTP) to the resource +sub get_audio_data +{ + my ( $capid, $anum, $want_paths ) = @_; + $capid = int($capid); + + my ( + $dbr, # Database handle (reader) + $sql, # SQL statement + $valid, # Are the capid/anum valid? + $data, # The PNG data + $u, # System user + $location, # Location of the file (mogile/blob) + ); + + $dbr = LJ::get_db_reader(); + $sql = q{ + SELECT capid, location + FROM captchas + WHERE + capid = ? + AND anum = ? + }; + + ( $valid, $location ) = $dbr->selectrow_array( $sql, undef, $capid, $anum ); + return undef unless $valid; + + if ($location eq 'mogile') { + die "MogileFS object not loaded.\n" unless LJ::mogclient(); + if ($want_paths) { + # return path(s) to the content if they want + my @paths = LJ::mogclient()->get_paths("captcha:$capid"); + return \@paths; + } else { + $data = ${LJ::mogclient()->get_file_data("captcha:$capid")}; + } + } else { + $u = LJ::load_user( "system" ) + or die "Couldn't load the system user."; + + $data = LJ::Blob::get( $u, 'captcha_audio', 'wav', $capid ) + or die "Failed to fetch captcha_audio $capid from media server"; + } + return $data; +} + + + +# ($dir) -> ("$dir/speech.wav", $code) +# Callers must: +# -- create unique temporary directory, shared by no other process +# calling this function +# -- after return, do something with speech.wav (save on disk server/ +# db/etc), remove speech.wav, then rmdir $dir +# Requires festival and sox. +sub generate_audio +{ + my ($dir) = @_; + my $old_dir = Cwd::getcwd(); + chdir($dir) or return 0; + + my $bin_festival = $LJ::BIN_FESTIVAL || "festival"; + my $bin_sox = $LJ::BIN_SOX || "sox"; + + # make up 7 random numbers, without any numbers in a row + my @numbers; + my $lastnum; + for (1..7) { + my $num; + do { + $num = int(rand(9)+1); + } while ($num == $lastnum); + $lastnum = $num; + push @numbers, $num; + } + my $numbers_speak = join("... ", @numbers); + my $numbers_clean = join('', @numbers); + + # generate the clean speech + open FEST, '|-', $bin_festival or die "Couldn't invoke festival"; + print FEST "(Parameter.set 'Audio_Method 'Audio_Command)\n"; + print FEST "(Parameter.set 'Audio_Required_Format 'wav)\n"; + print FEST "(Parameter.set 'Audio_Required_Rate 44100)\n"; + print FEST "(Parameter.set 'Audio_Command \"mv \$FILE speech.wav\")\n"; + print FEST "(SayText \"$numbers_speak\")\n"; + close FEST or die "Error closing festival"; + + my $sox = sub { + my ($effect, $filename, $inopts, $outopts) = @_; + $effect = [] unless $effect; + $filename = "speech.wav" unless $filename; + $inopts = [] unless $inopts; + $outopts = [] unless $outopts; + command($bin_sox, @$inopts, $filename, @$outopts, "tmp.wav", @$effect); + rename('tmp.wav', $filename) + or die; + }; + + # distort the speech + $sox->([qw(reverb 0.5 200 100 60 echo 1 0.7 100 0.03 400 0.15)]); + command($bin_sox, qw(speech.wav noise.wav synth brownnoise 0 vibro 3 0.8 vol 0.1)); + $sox->([qw(fade 0.5)], 'noise.wav'); + $sox->([qw(reverse)], 'noise.wav'); + $sox->([qw(fade 0.5)], 'noise.wav'); + + command("${bin_sox}mix", qw(-v 4 speech.wav noise.wav -r 16000 tmp.wav)); + rename('tmp.wav', 'speech.wav') or die; + unlink('oldspeech.wav', 'noise.wav'); + + chdir($old_dir) or return 0; + return ("$dir/speech.wav", $numbers_clean); +} + +sub command { + system(@_) >> 8 == 0 or die "audio command failed, died"; +} + + +### check_code( $capid, $anum, $code, $u ) -> +sub check_code { + my ( $capid, $anum, $code, $u ) = @_; + + my ( + $dbr, # Database handle (reader) + $sql, # SQL query + $answer, # Challenge answer + $userid, # userid of previous answerer (or 0 if none) + ); + + $sql = q{ + SELECT answer, userid + FROM captchas + WHERE + capid = ? + AND anum = ? + }; + + # Fetch the challenge's answer based on id and anum. + $dbr = LJ::get_db_writer(); + ( $answer, $userid ) = $dbr->selectrow_array( $sql, undef, $capid, $anum ); + + # if it's already been answered, it must have been answered by the $u + # given to this function (double-click protection) + return 0 if $userid && ( ! $u || $u->{userid} != $userid ); + + # otherwise, just check answer. + return lc $answer eq lc $code; +} + +# Verify captcha answer if using a captcha session. +# (captcha challenge, code, $u) +# Returns capid and anum if answer correct. (for expire) +sub session_check_code { + my ($sess, $code, $u) = @_; + return 0 unless $sess && $code; + $sess = LJ::get_challenge_attributes($sess); + + $u = LJ::load_user('system') unless $u; + + my $dbcm = LJ::get_cluster_master($u); + my $dbr = LJ::get_db_reader(); + + my ($lcapid, $try) = # clustered + $dbcm->selectrow_array('SELECT lastcapid, trynum ' . + 'FROM captcha_session ' . + 'WHERE sess=?', undef, $sess); + my ($capid, $anum) = # global + $dbr->selectrow_array('SELECT capid,anum ' . + 'FROM captchas '. + 'WHERE capid=?', undef, $lcapid); + if (! LJ::Captcha::check_code($capid, $anum, $code, $u)) { + # update try and lastcapid + $u->do('UPDATE captcha_session SET lastcapid=NULL, ' . + 'trynum=trynum+1 WHERE sess=?', undef, $sess); + return 0; + } + return ($capid, $anum); +} + +### expire( $capid ) -> +sub expire { + my ( $capid, $anum, $userid ) = @_; + + my ( + $dbh, # Database handle (writer) + $sql, # SQL update query + ); + + $sql = q{ + UPDATE captchas + SET userid = ? + WHERE capid = ? AND anum = ? AND userid = 0 + }; + + # Fetch the challenge's answer based on id and anum. + $dbh = LJ::get_db_writer(); + $dbh->do( $sql, undef, $userid, $capid, $anum ) or return undef; + + return 1; +} + +# Update/create captcha sessions, return new capid/anum pairs on success. +# challenge, type, optional journalu->{clusterid} for clustering. +# Type is either 'image' or 'audio' +sub session +{ + my ($chal, $type, $cid) = @_; + return unless $chal && $type; + + my $chalinfo = {}; + LJ::challenge_check($chal, $chalinfo); + return unless $chalinfo->{valid}; + + my $sess = LJ::get_challenge_attributes($chal); + my ($capid, $anum) = ($type eq 'image') ? + LJ::Captcha::get_visual_id() : + LJ::Captcha::get_audio_id(); + + + $cid = LJ::load_user('system')->{clusterid} unless $cid; + my $dbcm = LJ::get_cluster_master($cid); + + # Retain try count + my $try = $dbcm->selectrow_array('SELECT trynum FROM captcha_session ' . + 'WHERE sess=?', undef, $sess); + $try ||= 0; + # Add/update session + $dbcm->do('REPLACE INTO captcha_session SET sess=?, sesstime=?, '. + 'lastcapid=?, trynum=?', undef, $sess, time(), $capid, $try); + return ($capid, $anum); +} + + +1; diff --git a/livejournal/cgi-bin/LJ/LDAP.pm b/livejournal/cgi-bin/LJ/LDAP.pm new file mode 100755 index 0000000..42ae49f --- /dev/null +++ b/livejournal/cgi-bin/LJ/LDAP.pm @@ -0,0 +1,94 @@ +#!/usr/bin/perl +# + +package LJ::LDAP; + +use strict; +use Net::LDAP; +use Digest::MD5 qw(md5); +use Digest::SHA1 qw(sha1); +use MIME::Base64; + +sub load_ldap_user { + my ($user) = @_; + return undef unless $user =~ /^[\w ]+$/; + + my $ldap = Net::LDAP->new($LJ::LDAP_HOST) + or return undef; + my $mesg = $ldap->bind; # an anonymous bind + + my $uid = $LJ::LDAP_UID || "uid"; + + my $urec = $ldap->search( # perform a search + base => $LJ::LDAP_BASE, + scope => "sub", + filter => "$uid=$user", + #filter => "(&(sn=Barr) (o=Texas Instruments))" + )->pop_entry + or return undef; + + my $up = $urec->get_value('userPassword') + or return undef; + + my ($nick, $email) = ($urec->get_value('gecos'), $urec->get_value('mailLocalAddress')); + unless ($nick && $email) { + $@ = "Necessary information not found in LDAP record: name=$nick; email=$email"; + return undef; + } + + # $res comes out as...? + my $res = { + name => $user, + nick => $nick, + email => $email, + ldap_pass => $up, + }; + + return $res; +} + +sub is_good_ldap +{ + my ($user, $pass) = @_; + my $lrec = load_ldap_user($user) + or return undef; + + # get auth type and data, then decode it + return undef unless $lrec->{ldap_pass} =~ /^\{(\w+)\}(.+)$/; + my ($auth, $data) = ($1, decode_base64($2)); + + if ($auth eq 'MD5') { + unless ($data eq md5($pass)) { + $@ = "Password mismatch (MD5) from LDAP server; is your password correct?"; + return undef; + } + } elsif ($auth eq 'SSHA') { + my $salt = substr($data, 20); + my $orig = substr($data, 0, 20); + unless ($orig eq sha1($pass, $salt)) { + $@ = "Password mismatch (SSHA) from LDAP server; is your password correct?"; + return undef; + } + + } elsif ($auth eq 'SMD5') { + # this didn't work + my $salt = substr($data, 16); + my $orig = substr($data, 0, 16); + unless ($orig eq md5($pass, $salt)) { + $@ = "Password mismatch (SMD5) from LDAP server; is your password correct?"; + return undef; + } + + } else { + print STDERR "Unsupported LDAP auth method: $auth\n"; + $@ = "userPassword field from LDAP server not of supported format; type: $auth" +; + return undef; + } + + return $lrec; +} + + +1; + diff --git a/livejournal/cgi-bin/LJ/MemCache.pm b/livejournal/cgi-bin/LJ/MemCache.pm new file mode 100755 index 0000000..c4d201e --- /dev/null +++ b/livejournal/cgi-bin/LJ/MemCache.pm @@ -0,0 +1,111 @@ +# +# Wrapper around MemCachedClient + +use lib "$ENV{'LJHOME'}/cgi-bin"; +use Cache::Memcached; +use strict; + +package LJ::MemCache; + +%LJ::MEMCACHE_ARRAYFMT = ( + 'user' => + [qw[1 userid user caps clusterid dversion email password status statusvis statusvisdate + name bdate themeid moodthemeid opt_forcemoodtheme allow_infoshow allow_contactshow + allow_getljnews opt_showtalklinks opt_whocanreply opt_gettalkemail opt_htmlemail + opt_mangleemail useoverrides defaultpicid has_bio txtmsg_status is_system + journaltype lang oldenc]], + 'fgrp' => [qw[1 userid groupnum groupname sortorder is_public]], + # version #101 because old userpic format in memcached was an arrayref of + # [width, height, ...] and widths could have been 1 before, although unlikely + 'userpic' => [qw[101 width height userid fmt state picdate location flags]], + ); + + +my $memc; # memcache object + +sub init { + $memc = new Cache::Memcached; + reload_conf(); +} + +sub get_memcache { + init() unless $memc; + return $memc +} + +sub client_stats { + return $memc->{'stats'} || {}; +} + +sub reload_conf { + my $stat_callback; + + $memc->set_servers(\@LJ::MEMCACHE_SERVERS); + $memc->set_debug($LJ::MEMCACHE_DEBUG); + $memc->set_pref_ip(\%LJ::MEMCACHE_PREF_IP); + $memc->set_compress_threshold($LJ::MEMCACHE_COMPRESS_THRESHOLD); + if ($LJ::DB_LOG_HOST) { + $stat_callback = sub { + my ($stime, $etime, $host, $action) = @_; + LJ::blocking_report($host, 'memcache', $etime - $stime, "memcache: $action"); + }; + } else { + $stat_callback = undef; + } + $memc->set_stat_callback($stat_callback); + $memc->set_readonly(1) if $ENV{LJ_MEMC_READONLY}; + return $memc; +} + +sub forget_dead_hosts { $memc->forget_dead_hosts(); } +sub disconnect_all { $memc->disconnect_all(); } + +sub delete { + # use delete time if specified + return $memc->delete(@_) if defined $_[1]; + + # else default to 4 seconds: + # version 1.1.7 vs. 1.1.6 + $memc->delete(@_, 4) || $memc->delete(@_); +} + +sub add { $memc->add(@_); } +sub replace { $memc->replace(@_); } +sub set { $memc->set(@_); } +sub get { $memc->get(@_); } +sub get_multi { $memc->get_multi(@_); } +sub incr { $memc->incr(@_); } +sub decr { $memc->decr(@_); } + +sub _get_sock { $memc->get_sock(@_); } + +sub run_command { $memc->run_command(@_); } + + +sub array_to_hash { + my ($fmtname, $ar) = @_; + my $fmt = $LJ::MEMCACHE_ARRAYFMT{$fmtname}; + return undef unless $fmt; + return undef unless $ar && ref $ar eq "ARRAY" && $ar->[0] == $fmt->[0]; + my $hash = {}; + my $ct = scalar(@$fmt); + for (my $i=1; $i<$ct; $i++) { + $hash->{$fmt->[$i]} = $ar->[$i]; + } + return $hash; +} + +sub hash_to_array { + my ($fmtname, $hash) = @_; + my $fmt = $LJ::MEMCACHE_ARRAYFMT{$fmtname}; + return undef unless $fmt; + return undef unless $hash && ref $hash; + my $ar = [$fmt->[0]]; + my $ct = scalar(@$fmt); + for (my $i=1; $i<$ct; $i++) { + $ar->[$i] = $hash->{$fmt->[$i]}; + } + return $ar; +} + +1; diff --git a/livejournal/cgi-bin/LJ/OpenID.pm b/livejournal/cgi-bin/LJ/OpenID.pm new file mode 100755 index 0000000..0275076 --- /dev/null +++ b/livejournal/cgi-bin/LJ/OpenID.pm @@ -0,0 +1,189 @@ +package LJ::OpenID; + +use strict; +use Digest::SHA1 qw(sha1 sha1_hex); +use LWPx::ParanoidAgent; + +BEGIN { + $LJ::OPTMOD_OPENID_CONSUMER = $LJ::OPENID_CONSUMER ? eval "use Net::OpenID::Consumer; 1;" : 0; + $LJ::OPTMOD_OPENID_SERVER = $LJ::OPENID_SERVER ? eval "use Net::OpenID::Server; 1;" : 0; +} + +# returns boolean whether consumer support is enabled and available +sub consumer_enabled { + return 0 unless $LJ::OPENID_CONSUMER; + return $LJ::OPTMOD_OPENID_CONSUMER || eval "use Net::OpenID::Consumer; 1;"; +} + +# returns boolean whether consumer support is enabled and available +sub server_enabled { + return 0 unless $LJ::OPENID_SERVER; + return $LJ::OPTMOD_OPENID_CONSUMER || eval "use Net::OpenID::Server; 1;"; +} + +sub server { + my ($get, $post) = @_; + + return Net::OpenID::Server->new( + get_args => $get || {}, + post_args => $post || {}, + + get_user => \&LJ::get_remote, + is_identity => sub { + my ($u, $ident) = @_; + return LJ::OpenID::is_identity($u, $ident, $get); + }, + is_trusted => \&LJ::OpenID::is_trusted, + + setup_url => "$LJ::SITEROOT/openid/approve.bml", + + server_secret => \&LJ::OpenID::server_secret, + secret_gen_interval => 3600, + secret_expire_age => 86400 * 14, + ); +} + +# Returns a Consumer object +# When planning to verify identity, needs GET +# arguments passed in +sub consumer { + my $get_args = shift || {}; + + my $ua; + unless ($LJ::IS_DEV_SERVER) { + $ua = LWPx::ParanoidAgent->new( + timeout => 10, + max_size => 1024*300, + ); + } + + my $csr = Net::OpenID::Consumer->new( + ua => $ua, + args => $get_args, + cache => eval { LJ::MemCache::get_memcache() }, + debug => $LJ::IS_DEV_SERVER || 0, + ); + + return $csr; +} + +sub server_secret { + my $time = shift; + my ($t2, $secret) = LJ::get_secret($time); + die "ASSERT: didn't get t2 (t1=$time)" unless $t2; + die "ASSERT: didn't get secret (t2=$t2)" unless $secret; + die "ASSERT: time($time) != t2($t2)\n" unless $t2 == $time; + return $secret; +} + +sub is_trusted { + my ($u, $trust_root, $is_identity) = @_; + return 0 unless $u; + # we always look up $is_trusted, even if $is_identity is false, to avoid timing attacks + + my $dbh = LJ::get_db_writer(); + my ($endpointid, $duration) = $dbh->selectrow_array("SELECT t.endpoint_id, t.duration ". + "FROM openid_trust t, openid_endpoint e ". + "WHERE t.userid=? AND t.endpoint_id=e.endpoint_id AND e.url=?", + undef, $u->{userid}, $trust_root); + return 0 unless $endpointid; + + if ($duration eq "once") { + $dbh->do("DELETE FROM openid_trust WHERE userid=? AND endpoint_id=?", undef, $u->{userid}, $endpointid); + } + return 1; +} + +sub is_identity { + my ($u, $ident, $get) = @_; + return 0 unless $u && $u->{journaltype} eq "P"; + + my $user = $u->{user}; + return 1 if + $ident eq "$LJ::SITEROOT/users/$user/" || + $ident eq "$LJ::SITEROOT/~$user/" || + $ident eq "http://$user.$LJ::USER_DOMAIN/"; + + if ($get->{'ljuser_sha1'} eq sha1_hex($user) || + $get->{'ljuser'} eq $user) { + my $dbh = LJ::get_db_writer(); + return $dbh->selectrow_array("SELECT COUNT(*) FROM openid_external WHERE userid=? AND url=?", + undef, $u->{userid}, $ident); + } + + return 0; +} + +sub getmake_endpointid { + my $site = shift; + + my $dbh = LJ::get_db_writer() + or return undef; + + my $rv = $dbh->do("INSERT IGNORE INTO openid_endpoint (url) VALUES (?)", undef, $site); + my $end_id; + if ($rv > 0) { + $end_id = $dbh->{'mysql_insertid'}; + } else { + $end_id = $dbh->selectrow_array("SELECT endpoint_id FROM openid_endpoint WHERE url=?", + undef, $site); + } + return $end_id; +} + +sub add_trust { + my ($u, $site, $dur) = @_; + + return 0 unless $dur =~ /^always|once$/; + + my $end_id = LJ::OpenID::getmake_endpointid($site) + or return 0; + + my $dbh = LJ::get_db_writer() + or return undef; + + my $rv = $dbh->do("REPLACE INTO openid_trust (userid, endpoint_id, duration, trust_time) ". + "VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $u->{userid}, $end_id, $dur); + return $rv; +} + +# From Digest::HMAC +sub hmac_sha1_hex { + unpack("H*", &hmac_sha1); +} +sub hmac_sha1 { + hmac($_[0], $_[1], \&sha1, 64); +} +sub hmac { + my($data, $key, $hash_func, $block_size) = @_; + $block_size ||= 64; + $key = &$hash_func($key) if length($key) > $block_size; + + my $k_ipad = $key ^ (chr(0x36) x $block_size); + my $k_opad = $key ^ (chr(0x5c) x $block_size); + + &$hash_func($k_opad, &$hash_func($k_ipad, $data)); +} + +# Returns 1 if destination identity server +# is blocked +sub blocked_hosts { + my $csr = shift; + + return do { my $dummy = 0; \$dummy; } if $LJ::IS_DEV_SERVER; + + my $tried_local_id = 0; + $csr->ua->blocked_hosts( + sub { + my $dest = shift; + # NEEDS TO BE NOT HARDCODED + if ($dest =~ /livejournal\.com$/i) { + $tried_local_id = 1; + return 1; + } + return 0; + }); + return \$tried_local_id; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2.pm b/livejournal/cgi-bin/LJ/S2.pm new file mode 100755 index 0000000..6991927 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2.pm @@ -0,0 +1,2669 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'LJHOME'}/src/s2"; +use S2; +use S2::Checker; +use S2::Color; +use S2::Compiler; +use Storable; +use Apache::Constants (); +use HTMLCleaner; +use POSIX (); + +use LJ::S2::RecentPage; +use LJ::S2::YearPage; +use LJ::S2::DayPage; +use LJ::S2::FriendsPage; +use LJ::S2::MonthPage; +use LJ::S2::EntryPage; +use LJ::S2::ReplyPage; + +package LJ::S2; + +# TEMP HACK +sub get_s2_reader { + return LJ::get_dbh("s2slave", "slave", "master"); +} + +sub make_journal +{ + my ($u, $styleid, $view, $remote, $opts) = @_; + + my $r = $opts->{'r'}; + my $ret; + $LJ::S2::ret_ref = \$ret; + + my ($entry, $page); + my $con_opts = {}; + + if ($view eq "res") { + if ($opts->{'pathextra'} =~ m!/(\d+)/stylesheet$!) { + $styleid = $1; + $entry = "print_stylesheet()"; + $opts->{'contenttype'} = 'text/css'; + $con_opts->{'use_modtime'} = 1; + } else { + $opts->{'handler_return'} = 404; + return; + } + } + + $u->{'_s2styleid'} = $styleid + 0; + $con_opts->{'u'} = $u; + $con_opts->{'style_u'} = $opts->{'style_u'}; + my $ctx = s2_context($r, $styleid, $con_opts); + unless ($ctx) { + $opts->{'handler_return'} = Apache::Constants::OK(); + return; + } + + my $lang = 'en'; + LJ::run_hook('set_s2bml_lang', $ctx, \$lang); + + # note that's it's very important to pass LJ::Lang::get_text here explicitly + # rather than relying on BML::set_language's fallback mechanism, which won't + # work in this context since BML::cur_req won't be loaded if no BML requests + # have been served from this Apache process yet + BML::set_language($lang, \&LJ::Lang::get_text); + + # let layouts disable EntryPage / ReplyPage, using the BML version + # instead. + if ($ctx->[S2::PROPS]->{'view_entry_disabled'} && ($view eq "entry" || $view eq "reply")) { + ${$opts->{'handle_with_bml_ref'}} = 1; + return; + } + + # make sure capability supports it + if (($view eq "entry" || $view eq "reply") && + ! LJ::get_cap(($opts->{'checkremote'} ? $remote : $u), "s2view$view")) { + ${$opts->{'handle_with_bml_ref'}} = 1; + return; + } + + # setup tags backwards compatibility + unless ($ctx->[S2::PROPS]->{'tags_aware'}) { + $opts->{enable_tags_compatibility} = 1; + } + + escape_context_props($ctx->[S2::PROPS]); + + $opts->{'ctx'} = $ctx; + $LJ::S2::CURR_CTX = $ctx; + + foreach ("name", "url", "urlname") { LJ::text_out(\$u->{$_}); } + + $u->{'_journalbase'} = LJ::journal_base($u->{'user'}, $opts->{'vhost'}); + + if ($view eq "lastn") { + $entry = "RecentPage::print()"; + $page = RecentPage($u, $remote, $opts); + } elsif ($view eq "calendar") { + $entry = "YearPage::print()"; + $page = YearPage($u, $remote, $opts); + } elsif ($view eq "day") { + $entry = "DayPage::print()"; + $page = DayPage($u, $remote, $opts); + } elsif ($view eq "friends" || $view eq "friendsfriends") { + $entry = "FriendsPage::print()"; + $page = FriendsPage($u, $remote, $opts); + } elsif ($view eq "month") { + $entry = "MonthPage::print()"; + $page = MonthPage($u, $remote, $opts); + } elsif ($view eq "entry") { + $entry = "EntryPage::print()"; + $page = EntryPage($u, $remote, $opts); + } elsif ($view eq "reply") { + $entry = "ReplyPage::print()"; + $page = ReplyPage($u, $remote, $opts); + } + + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + + # the friends mode=live returns raw HTML in $page, in which case there's + # nothing to "run" with s2_run. so $page isn't runnable, return it now. + # but we have to make sure it's defined at all first, otherwise things + # like print_stylesheet() won't run, which don't have an method invocant + return $page if $page && ref $page ne 'HASH'; + + s2_run($r, $ctx, $opts, $entry, $page); + + if (ref $opts->{'errors'} eq "ARRAY" && @{$opts->{'errors'}}) { + return join('', + "Errors occurred processing this page:
      ", + map { "
    • $_
    • " } @{$opts->{'errors'}}, + "
    "); + } + + # unload layers that aren't public + LJ::S2::cleanup_layers($ctx); + + return $ret; +} + +sub s2_run +{ + my ($r, $ctx, $opts, $entry, $page) = @_; + + my $ctype = $opts->{'contenttype'} || "text/html"; + my $cleaner; + if ($ctype =~ m!^text/html!) { + $cleaner = new HTMLCleaner ('output' => sub { $$LJ::S2::ret_ref .= $_[0]; }); + } + + my $send_header = sub { + my $status = $ctx->[S2::SCRATCH]->{'status'} || 200; + $r->status($status); + $r->content_type($ctx->[S2::SCRATCH]->{'ctype'} || $ctype); + $r->send_http_header(); + }; + + my $need_flush; + my $out_straight = sub { + # Hacky: forces text flush. see: + # http://zilla.livejournal.org/906 + if ($need_flush) { + $cleaner->parse(""); + $need_flush = 0; + } + $$LJ::S2::ret_ref .= $_[0]; + }; + my $out_clean = sub { + $cleaner->parse($_[0]); + $need_flush = 1; + }; + S2::set_output($out_straight); + S2::set_output_safe($cleaner ? $out_clean : $out_straight); + + $LJ::S2::CURR_PAGE = $page; + $LJ::S2::RES_MADE = 0; # standard resources (Image objects) made yet + + eval { + S2::run_code($ctx, $entry, $page); + }; + $LJ::S2::CURR_PAGE = undef; + $LJ::S2::CURR_CTX = undef; + + if ($@) { + my $error = $@; + $error =~ s/\n/
    \n/g; + S2::pout("Error running style: $error"); + return 0; + } + $cleaner->eof if $cleaner; # flush any remaining text/tag not yet spit out + return 1; +} + +# +# name: LJ::S2::get_tags_text +# class: s2 +# des: Gets text for display in entry for tags compatibility. +# args: ctx, taglistref +# des-ctx: Current S2 context +# des-taglistref: Arrayref containing "Tag" S2 objects +# returns: String; can be appended to entry... undef on error (no context, no taglistref) +# +sub get_tags_text { + my ($ctx, $taglist) = @_; + return undef unless $ctx && $taglist; + return "" unless @$taglist; + + # now get the customized tag text and insert the tag list and append to body + my $tags = join(', ', map { "" } @$taglist); + my $tagtext = S2::get_property_value($ctx, 'text_tags'); + $tagtext =~ s/#/$tags/; + return "
    $tagtext
    "; +} + +# returns hashref { lid => $u }; undef on error +sub get_layer_owners { + my @lids = map { $_ + 0 } @_; + return {} unless @lids; + + my $ret = {}; # lid => uid/$u + my %need = ( map { $_ => 1 } @lids ); # layerid => 1 + + # see what we can get out of memcache first + my @keys; + push @keys, [ $_, "s2lo:$_" ] foreach @lids; + my $memc = LJ::MemCache::get_multi(@keys); + foreach my $lid (@lids) { + if (my $uid = $memc->{"s2lo:$lid"}) { + delete $need{$lid}; + $ret->{$lid} = $uid; + } + } + + # if we still need any from the database, get them now + if (%need) { + my $dbh = LJ::get_db_writer(); + my $in = join(',', keys %need); + my $res = $dbh->selectall_arrayref("SELECT s2lid, userid FROM s2layers WHERE s2lid IN ($in)"); + die "Database error in LJ::S2::get_layer_owners: " . $dbh->errstr . "\n" if $dbh->err; + + foreach my $row (@$res) { + # save info and add to memcache + $ret->{$row->[0]} = $row->[1]; + LJ::MemCache::add([ $row->[0], "s2lo:$row->[0]" ], $row->[1]); + } + } + + # now load these users; they're likely process cached anyway, so it should + # be pretty fast + my $us = LJ::load_userids(values %$ret); + foreach my $lid (keys %$ret) { + $ret->{$lid} = $us->{$ret->{$lid}} + } + return $ret; +} + +# returns max comptime of all lids requested to be loaded +sub load_layers { + my @lids = map { $_ + 0 } @_; + return 0 unless @lids; + + my $maxtime = 0; # to be returned + + # figure out what is process cached...that goes to DB always + # if it's not in process cache, hit memcache first + my @from_db; # lid, lid, lid, ... + my @need_memc; # lid, lid, lid, ... + + # initial sweep, anything loaded for less than 60 seconds is golden + foreach my $lid (@lids) { + if (my $loaded = S2::layer_loaded($lid, 60)) { + # it's loaded and not more than 60 seconds load, so we just go + # with it and assume it's good... if it's been recompiled, we'll + # figure it out within the next 60 seconds + $maxtime = $loaded if $loaded > $maxtime; + } else { + push @need_memc, $lid; + } + } + + # attempt to get things in @need_memc from memcache + my $memc = LJ::MemCache::get_multi(map { [ $_, "s2c:$_"] } @need_memc); + foreach my $lid (@need_memc) { + if (my $row = $memc->{"s2c:$lid"}) { + # load the layer from memcache; memcache data should always be correct + my ($updtime, $data) = @$row; + if ($data) { + $maxtime = $updtime if $updtime > $maxtime; + S2::load_layer($lid, $data, $updtime); + } + } else { + # make it exist, but mark it 0 + push @from_db, $lid; + } + } + + # it's possible we don't need to hit the database for anything + return $maxtime unless @from_db; + + # figure out who owns what we need + my $us = LJ::S2::get_layer_owners(@from_db); + my $sysid = LJ::get_userid('system'); + + # break it down by cluster + my %bycluster; # cluster => [ lid, lid, ... ] + foreach my $lid (@from_db) { + next unless $us->{$lid}; + if ($us->{$lid}->{userid} == $sysid) { + push @{$bycluster{0} ||= []}, $lid; + } else { + push @{$bycluster{$us->{$lid}->{clusterid}} ||= []}, $lid; + } + } + + # big loop by cluster + foreach my $cid (keys %bycluster) { + # if we're talking about cluster 0, the global, pass it off to the old + # function which already knows how to handle that + unless ($cid) { + my $dbr = LJ::S2::get_s2_reader(); + S2::load_layers_from_db($dbr, @{$bycluster{$cid}}); + next; + } + + my $db = LJ::get_cluster_master($cid); + die "Unable to obtain handle to cluster $cid for LJ::S2::load_layers\n" + unless $db; + + # create SQL to load the layers we want + my $where = join(' OR ', map { "(userid=$us->{$_}->{userid} AND s2lid=$_)" } @{$bycluster{$cid}}); + my $sth = $db->prepare("SELECT s2lid, compdata, comptime FROM s2compiled2 WHERE $where"); + $sth->execute; + + # iterate over data, memcaching as we go + while (my ($id, $comp, $comptime) = $sth->fetchrow_array) { + LJ::text_uncompress(\$comp); + LJ::MemCache::set([ $id, "s2c:$id" ], [ $comptime, $comp ]) + if length $comp <= $LJ::MAX_S2COMPILED_CACHE_SIZE; + S2::load_layer($id, $comp, $comptime); + $maxtime = $comptime if $comptime > $maxtime; + } + } + + # now we have to go through everything again and verify they're all loaded and + # otherwise do a fallback to the global + my @to_load; + foreach my $lid (@from_db) { + next if S2::layer_loaded($lid); + + unless ($us->{$lid}) { + print STDERR "Style $lid has no available owner.\n"; + next; + } + + if ($us->{$lid}->{userid} == $sysid) { + print STDERR "Style $lid is owned by system but failed load from global.\n"; + next; + } + + if ($LJ::S2COMPILED_MIGRATION_DONE) { + LJ::MemCache::set([ $lid, "s2c:$lid" ], [ time(), 0 ]); + next; + } + + push @to_load, $lid; + } + return $maxtime unless @to_load; + + # get the dbh and start loading these + my $dbr = LJ::S2::get_s2_reader(); + die "Failure getting S2 database handle in LJ::S2::load_layers\n" + unless $dbr; + + my $where = join(' OR ', map { "s2lid=$_" } @to_load); + my $sth = $dbr->prepare("SELECT s2lid, compdata, comptime FROM s2compiled WHERE $where"); + $sth->execute; + while (my ($id, $comp, $comptime) = $sth->fetchrow_array) { + S2::load_layer($id, $comp, $comptime); + $maxtime = $comptime if $comptime > $maxtime; + } + return $maxtime; +} + +# find existing re-distributed layers that are in the database +# and their styleids. +sub get_public_layers +{ + my $sysid = shift; # optional system userid (usually not used) + $LJ::CACHED_PUBLIC_LAYERS ||= LJ::MemCache::get("s2publayers") + unless $LJ::LESS_CACHING; + return $LJ::CACHED_PUBLIC_LAYERS if $LJ::CACHED_PUBLIC_LAYERS; + + $sysid ||= LJ::get_userid("system"); + my $layers = get_layers_of_user($sysid, "is_system"); + + return $layers if $LJ::LESS_CACHING; + $LJ::CACHED_PUBLIC_LAYERS = $layers if $layers; + LJ::MemCache::set("s2publayers", $layers, 60*10) if $layers; + return $LJ::CACHED_PUBLIC_LAYERS; +} + +# update layers whose b2lids have been remapped to new s2lids +sub b2lid_remap +{ + my ($uuserid, $s2lid, $b2lid) = @_; + my $b2lid_new = $LJ::S2LID_REMAP{$b2lid}; + return undef unless $uuserid && $s2lid && $b2lid && $b2lid_new; + + my $sysid = LJ::get_userid("system"); + return undef unless $sysid; + + LJ::statushistory_add($uuserid, $sysid, 'b2lid_remap', "$s2lid: $b2lid=>$b2lid_new"); + + my $dbh = LJ::get_db_writer(); + return $dbh->do("UPDATE s2layers SET b2lid=? WHERE s2lid=?", + undef, $b2lid_new, $s2lid); +} + +sub get_layers_of_user +{ + my ($u, $is_system) = @_; + my $userid = LJ::want_userid($u); + return undef unless $userid; + undef $u unless LJ::isu($u); + + return $u->{'_s2layers'} if $u && $u->{'_s2layers'}; + + my %layers; # id -> {hashref}, uniq -> {same hashref} + my $dbr = LJ::S2::get_s2_reader(); + + my $extrainfo = $is_system ? "'redist_uniq', " : ""; + my $sth = $dbr->prepare("SELECT i.infokey, i.value, l.s2lid, l.b2lid, l.type ". + "FROM s2layers l, s2info i ". + "WHERE l.userid=? AND l.s2lid=i.s2lid AND ". + "i.infokey IN ($extrainfo 'type', 'name', 'langcode', ". + "'majorversion', '_previews')"); + $sth->execute($userid); + die $dbr->errstr if $dbr->err; + while (my ($key, $val, $id, $bid, $type) = $sth->fetchrow_array) { + $layers{$id}->{'b2lid'} = $bid; + $layers{$id}->{'s2lid'} = $id; + $layers{$id}->{'type'} = $type; + $key = "uniq" if $key eq "redist_uniq"; + $layers{$id}->{$key} = $val; + } + + foreach (keys %layers) { + # setup uniq alias. + if ($layers{$_}->{'uniq'} ne "") { + $layers{$layers{$_}->{'uniq'}} = $layers{$_}; + } + + # setup children keys + my $bid = $layers{$_}->{b2lid}; + next unless $layers{$_}->{'b2lid'}; + + # has the b2lid for this layer been remapped? + # if so update this layer's specified b2lid + if ($bid && $LJ::S2LID_REMAP{$bid}) { + my $s2lid = $layers{$_}->{s2lid}; + b2lid_remap($userid, $s2lid, $bid); + $layers{$_}->{b2lid} = $LJ::S2LID_REMAP{$bid}; + } + + if ($is_system) { + my $bid = $layers{$_}->{'b2lid'}; + unless ($layers{$bid}) { + delete $layers{$layers{$_}->{'uniq'}}; + delete $layers{$_}; + next; + } + push @{$layers{$bid}->{'children'}}, $_; + } + } + + if ($u) { + $u->{'_s2layers'} = \%layers; + } + return \%layers; +} + + +# get_style: +# +# many calling conventions: +# get_style($styleid, $verify) +# get_style($u, $verify) +# get_style($styleid, $opts) +# get_style($u, $opts) +# +# opts may contain keys: +# - 'u' -- $u object +# - 'verify' -- if verify, the $u->{'s2_style'} key is deleted if style isn't found +sub get_style +{ + my ($arg, $opts) = @_; + + my $verify = 0; + my ($styleid, $u); + + if (ref $opts eq "HASH") { + $verify = $opts->{'verify'}; + $u = $opts->{'u'}; + } elsif ($opts) { + $verify = 1; + die "Bogus second arg to LJ::S2::get_style" if ref $opts; + } + + if (ref $arg) { + $u = $arg; + $styleid = $u->{'s2_style'} + 0; + } else { + $styleid = $arg + 0; + } + + my %style; + my $have_style = 0; + + if ($verify && $styleid) { + my $dbr = LJ::S2::get_s2_reader(); + my $style = $dbr->selectrow_hashref("SELECT * FROM s2styles WHERE styleid=$styleid"); + if (! $style && $u) { + delete $u->{'s2_style'}; + $styleid = 0; + } + } + + if ($styleid) { + my $stylay = $u ? + LJ::S2::get_style_layers($u, $styleid) : + LJ::S2::get_style_layers($styleid); + while (my ($t, $id) = each %$stylay) { $style{$t} = $id; } + $have_style = scalar %style; + } + + # this is a hack to add remapping support for s2lids + # - if a layerid is loaded above but it has a remapping + # defined in ljconfig, use the remap id instead and + # also save to database using set_style_layers + if (%LJ::S2LID_REMAP) { + my @remaps = (); + + # all system layer types (no user layers) + foreach (qw(core i18nc i18n layout theme)) { + my $lid = $style{$_}; + if (exists $LJ::S2LID_REMAP{$lid}) { + $style{$_} = $LJ::S2LID_REMAP{$lid}; + push @remaps, "$lid=>$style{$_}"; + } + } + if (@remaps) { + my $sysid = LJ::get_userid("system"); + LJ::statushistory_add($u, $sysid, 's2lid_remap', join(", ", @remaps)); + LJ::S2::set_style_layers($u, $styleid, %style); + } + } + + unless ($have_style) { + my $public = get_public_layers(); + while (my ($layer, $name) = each %$LJ::DEFAULT_STYLE) { + next unless $name ne ""; + next unless $public->{$name}; + my $id = $public->{$name}->{'s2lid'}; + $style{$layer} = $id if $id; + } + } + + return %style; +} + +sub s2_context +{ + my $r = shift; + my $styleid = shift; + my $opts = shift || {}; + + my $u = $opts->{u}; + my $style_u = $opts->{style_u} || $u; + + # but it doesn't matter if we're using the minimal style ... + my %style; + eval { + my $r = Apache->request; + if ($r->notes('use_minimal_scheme')) { + my $public = get_public_layers(); + while (my ($layer, $name) = each %LJ::MINIMAL_STYLE) { + next unless $name ne ""; + next unless $public->{$name}; + my $id = $public->{$name}->{'s2lid'}; + $style{$layer} = $id if $id; + } + } + }; + + # fall back to the standard call to get a user's styles + unless (%style) { + %style = $u ? get_style($styleid, { 'u' => $style_u }) : get_style($styleid); + } + + my @layers; + foreach (qw(core i18nc layout i18n theme user)) { + push @layers, $style{$_} if $style{$_}; + } + + # TODO: memcache this. only make core S2 (which uses the DB) load + # when we can't get all the s2compiled stuff from memcache. + # compare s2styles.modtime with s2compiled.comptime to see if memcache + # version is accurate or not. + my $dbr = LJ::S2::get_s2_reader(); + my $modtime = LJ::S2::load_layers(@layers); + + # check that all critical layers loaded okay from the database, otherwise + # fall back to default style. if i18n/theme/user were deleted, just proceed. + my $okay = 1; + foreach (qw(core layout)) { + next unless $style{$_}; + $okay = 0 unless S2::layer_loaded($style{$_}); + } + unless ($okay) { + # load the default style instead, if we just tried to load a real one and failed + if ($styleid) { return s2_context($r, 0, $opts); } + + # were we trying to load the default style? + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error preparing to run: One or more layers required to load the stock style have been deleted."); + return undef; + } + + if ($opts->{'use_modtime'}) + { + my $ims = $r->header_in("If-Modified-Since"); + my $ourtime = LJ::time_to_http($modtime); + if ($ims eq $ourtime) { + # 304 return; unload non-public layers + LJ::S2::cleanup_layers(@layers); + $r->status_line("304 Not Modified"); + $r->send_http_header(); + return undef; + } else { + $r->header_out("Last-Modified", $ourtime); + } + } + + my $ctx; + eval { + $ctx = S2::make_context(@layers); + }; + + if ($ctx) { + LJ::S2::populate_system_props($ctx); + S2::set_output(sub {}); # printing suppressed + S2::set_output_safe(sub {}); + eval { S2::run_code($ctx, "prop_init()"); }; + return $ctx unless $@; + } + + # failure to generate context; unload our non-public layers + LJ::S2::cleanup_layers(@layers); + + my $err = $@; + $r->content_type("text/html"); + $r->send_http_header(); + $r->print("Error preparing to run: $err"); + return undef; + +} + +# parameter is either a single context, or just a bunch of layerids +# will then unregister the non-public layers +sub cleanup_layers { + my $pub = get_public_layers(); + my @unload = ref $_[0] ? S2::get_layers($_[0]) : @_; + S2::unregister_layer($_) foreach grep { ! $pub->{$_} } @unload; +} + +sub clone_layer +{ + die "LJ::S2::clone_layer() has not been ported to use s2compiled2, but this function is not currently in use anywhere; if you use this function, please update it to use s2compiled2.\n"; + + my $id = shift; + return 0 unless $id; + + my $dbh = LJ::get_db_writer(); + my $r; + + $r = $dbh->selectrow_hashref("SELECT * FROM s2layers WHERE s2lid=?", undef, $id); + return 0 unless $r; + $dbh->do("INSERT INTO s2layers (b2lid, userid, type) VALUES (?,?,?)", + undef, $r->{'b2lid'}, $r->{'userid'}, $r->{'type'}); + my $newid = $dbh->{'mysql_insertid'}; + return 0 unless $newid; + + foreach my $t (qw(s2compiled s2info s2source)) { + $r = $dbh->selectrow_hashref("SELECT * FROM $t WHERE s2lid=?", undef, $id); + next unless $r; + $r->{'s2lid'} = $newid; + + # kinda hacky: we have to update the layer id + if ($t eq "s2compiled") { + $r->{'compdata'} =~ s/\$_LID = (\d+)/\$_LID = $newid/; + } + + $dbh->do("INSERT INTO $t (" . join(',', keys %$r) . ") VALUES (". + join(',', map { $dbh->quote($_) } values %$r) . ")"); + } + + return $newid; +} + +sub create_style +{ + my ($u, $name, $cloneid) = @_; + + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my $uid = $u->{userid} + 0 + or return 0; + + my $clone; + $clone = load_style($cloneid) if $cloneid; + + # can't clone somebody else's style + return 0 if $clone && $clone->{'userid'} != $uid; + + # can't create name-less style + return 0 unless $name =~ /\S/; + + $dbh->do("INSERT INTO s2styles (userid, name, modtime) VALUES (?,?, UNIX_TIMESTAMP())", + undef, $u->{'userid'}, $name); + my $styleid = $dbh->{'mysql_insertid'}; + return 0 unless $styleid; + + if ($clone) { + $clone->{'layer'}->{'user'} = + LJ::clone_layer($clone->{'layer'}->{'user'}); + + my $values; + foreach my $ly ('core','i18nc','layout','theme','i18n','user') { + next unless $clone->{'layer'}->{$ly}; + $values .= "," if $values; + $values .= "($uid, $styleid, '$ly', $clone->{'layer'}->{$ly})"; + } + $u->do("REPLACE INTO s2stylelayers2 (userid, styleid, type, s2lid) ". + "VALUES $values") if $values; + } + + return $styleid; +} + +sub load_user_styles +{ + my $u = shift; + my $opts = shift; + return undef unless $u; + + my $dbr = LJ::S2::get_s2_reader(); + + my %styles; + my $load_using = sub { + my $db = shift; + my $sth = $db->prepare("SELECT styleid, name FROM s2styles WHERE userid=?"); + $sth->execute($u->{'userid'}); + while (my ($id, $name) = $sth->fetchrow_array) { + $styles{$id} = $name; + } + }; + $load_using->($dbr); + return \%styles if scalar(%styles) || ! $opts->{'create_default'}; + + # create a new default one for them, but first check to see if they + # have one on the master. + my $dbh = LJ::get_db_writer(); + $load_using->($dbh); + return \%styles if %styles; + + $dbh->do("INSERT INTO s2styles (userid, name, modtime) VALUES (?,?, UNIX_TIMESTAMP())", undef, + $u->{'userid'}, $u->{'user'}); + my $styleid = $dbh->{'mysql_insertid'}; + return { $styleid => $u->{'user'} }; +} + +sub delete_user_style +{ + my ($u, $styleid) = @_; + return 1 unless $styleid; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my $style = load_style($dbh, $styleid); + delete_layer($style->{'layer'}->{'user'}); + + foreach my $t (qw(s2styles s2stylelayers)) { + $dbh->do("DELETE FROM $t WHERE styleid=?", undef, $styleid) + } + $u->do("DELETE FROM s2stylelayers2 WHERE userid=? AND styleid=?", undef, + $u->{userid}, $styleid); + + return 1; +} + +sub load_style +{ + my $db = ref $_[0] ? shift : undef; + my $id = shift; + return undef unless $id; + + my $memkey = [$id, "s2s:$id"]; + my $style = LJ::MemCache::get($memkey); + unless ($style) { + $db ||= LJ::S2::get_s2_reader(); + $style = $db->selectrow_hashref("SELECT styleid, userid, name, modtime ". + "FROM s2styles WHERE styleid=?", + undef, $id); + LJ::MemCache::add($memkey, $style, 3600); + } + return undef unless $style; + + my $u = LJ::load_userid($style->{userid}) + or return undef; + + $style->{'layer'} = LJ::S2::get_style_layers($u, $id) || {}; + + return $style; +} + +sub create_layer +{ + my ($userid, $b2lid, $type) = @_; + $userid = LJ::want_userid($userid); + + return 0 unless $b2lid; # caller should ensure b2lid exists and is of right type + return 0 unless + $type eq "user" || $type eq "i18n" || $type eq "theme" || + $type eq "layout" || $type eq "i18nc" || $type eq "core"; + + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + + $dbh->do("INSERT INTO s2layers (b2lid, userid, type) ". + "VALUES (?,?,?)", undef, $b2lid, $userid, $type); + return $dbh->{'mysql_insertid'}; +} + +# takes optional $u as first argument... if user argument is specified, will +# look through s2stylelayers and delete all mappings that this user has to +# this particular layer. +sub delete_layer +{ + my $u = LJ::isu($_[0]) ? shift : undef; + my $lid = shift; + return 1 unless $lid; + my $dbh = LJ::get_db_writer(); + foreach my $t (qw(s2layers s2compiled s2info s2source s2checker)) { + $dbh->do("DELETE FROM $t WHERE s2lid=?", undef, $lid); + } + + # make sure we have a user object if possible + unless ($u) { + my $us = LJ::S2::get_layer_owners($lid); + $u = $us->{$lid} if $us->{$lid}; + } + + # delete s2compiled2 if this is a layer owned by someone other than system + if ($u && $u->{user} ne 'system') { + $u->do("DELETE FROM s2compiled2 WHERE userid = ? AND s2lid = ?", + undef, $u->{userid}, $lid); + } + + # now clear memcache of the compiled data + LJ::MemCache::delete([ $lid, "s2c:$lid" ]); + + # now delete the mappings for this particular layer + if ($u) { + my $styles = LJ::S2::load_user_styles($u); + my @ids = keys %{$styles || {}}; + if (@ids) { + # map in the ids we got from the user's styles and clear layers referencing + # this particular layer id + my $in = join(',', map { $_ + 0 } @ids); + $dbh->do("DELETE FROM s2stylelayers WHERE styleid IN ($in) AND s2lid = ?", + undef, $lid); + + $u->do("DELETE FROM s2stylelayers2 WHERE userid=? AND styleid IN ($in) AND s2lid = ?", + undef, $u->{userid}, $lid); + + # now clean memcache so this change is immediately visible + LJ::MemCache::delete([ $_, "s2sl:$_" ]) foreach @ids; + } + } + + return 1; +} + +sub get_style_layers +{ + my $u = LJ::isu($_[0]) ? shift : undef; + my ($styleid, $force) = @_; + return undef unless $styleid; + + # check memcache unless $force + my $stylay = undef; + my $memkey = [$styleid, "s2sl:$styleid"]; + $stylay = LJ::MemCache::get($memkey) unless $force; + return $stylay if $stylay; + + unless ($u) { + my $sty = LJ::S2::load_style($styleid) or + die "couldn't load styleid $styleid"; + $u = LJ::load_userid($sty->{userid}) or + die "couldn't load userid $sty->{userid} for styleid $styleid"; + } + + my %stylay; + + my $fetch = sub { + my ($db, $qry, @args) = @_; + + my $sth = $db->prepare($qry); + $sth->execute(@args); + die "ERROR: " . $sth->errstr if $sth->err; + while (my ($type, $s2lid) = $sth->fetchrow_array) { + $stylay{$type} = $s2lid; + } + return 0 unless %stylay; + return 1; + }; + + unless ($fetch->($u, "SELECT type, s2lid FROM s2stylelayers2 " . + "WHERE userid=? AND styleid=?", $u->{userid}, $styleid)) { + my $dbh = LJ::get_db_writer(); + if ($fetch->($dbh, "SELECT type, s2lid FROM s2stylelayers WHERE styleid=?", + $styleid)) { + LJ::S2::set_style_layers_raw($u, $styleid, %stylay); + } + } + + # set in memcache + LJ::MemCache::set($memkey, \%stylay); + return \%stylay; +} + +# the old interfaces. handles merging with global database data if necessary. +sub set_style_layers +{ + my ($u, $styleid, %newlay) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + my @lay = ('core','i18nc','layout','theme','i18n','user'); + my %need = map { $_, 1 } @lay; + delete $need{$_} foreach keys %newlay; + if (%need) { + # see if the needed layers are already on the user cluster + my ($sth, $t, $lid); + + $sth = $u->prepare("SELECT type FROM s2stylelayers2 WHERE userid=? AND styleid=?"); + $sth->execute($u->{'userid'}, $styleid); + while (($t) = $sth->fetchrow_array) { + delete $need{$t}; + } + + # if we still don't have everything, see if they exist on the + # global cluster, and we'll merge them into the %newlay being + # posted, so they end up on the user cluster + if (%need) { + $sth = $dbh->prepare("SELECT type, s2lid FROM s2stylelayers WHERE styleid=?"); + $sth->execute($styleid); + while (($t, $lid) = $sth->fetchrow_array) { + $newlay{$t} = $lid; + } + } + } + + set_style_layers_raw($u, $styleid, %newlay); +} + +# just set in user cluster, not merging with global +sub set_style_layers_raw { + my ($u, $styleid, %newlay) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + + $u->do("REPLACE INTO s2stylelayers2 (userid,styleid,type,s2lid) VALUES ". + join(",", map { sprintf("(%d,%d,%s,%d)", $u->{userid}, $styleid, + $dbh->quote($_), $newlay{$_}) } + keys %newlay)); + return 0 if $u->err; + + $dbh->do("UPDATE s2styles SET modtime=UNIX_TIMESTAMP() WHERE styleid=?", + undef, $styleid); + + # delete memcache key + LJ::MemCache::delete([$styleid, "s2sl:$styleid"]); + LJ::MemCache::delete([$styleid, "s2s:$styleid"]); + + return 1; +} + +sub load_layer +{ + my $db = ref $_[0] ? shift : LJ::S2::get_s2_reader(); + my $lid = shift; + + return $db->selectrow_hashref("SELECT s2lid, b2lid, userid, type ". + "FROM s2layers WHERE s2lid=?", undef, + $lid); +} + +sub escape_context_props +{ + my $obj = shift; + if (ref $obj eq "HASH") { + while (my ($k, $v) = each %{$obj}) { + if (ref $v) { + escape_context_props($v); + } else { + $obj->{$k} =~ s/{$k} =~ s/>/>/g; + $obj->{$k} =~ s!\n!
    !g; + } + } + } elsif (ref $obj eq "ARRAY") { + foreach (@$obj) { + if (ref) { + escape_context_props($_); + } else { + s//>/g; + s!\n!
    !g; + } + } + } +} + +sub populate_system_props +{ + my $ctx = shift; + $ctx->[S2::PROPS]->{'SITEROOT'} = $LJ::SITEROOT; + $ctx->[S2::PROPS]->{'PALIMGROOT'} = $LJ::PALIMGROOT; + $ctx->[S2::PROPS]->{'SITENAME'} = $LJ::SITENAME; + $ctx->[S2::PROPS]->{'SITENAMESHORT'} = $LJ::SITENAMESHORT; + $ctx->[S2::PROPS]->{'SITENAMEABBREV'} = $LJ::SITENAMEABBREV; + $ctx->[S2::PROPS]->{'IMGDIR'} = $LJ::IMGPREFIX; +} + +sub layer_compile_user +{ + my ($layer, $overrides) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless ref $layer; + return 0 unless $layer->{'s2lid'}; + return 1 unless ref $overrides; + my $id = $layer->{'s2lid'}; + my $s2 = "layerinfo \"type\" = \"user\";\n"; + + foreach my $name (keys %$overrides) { + next if $name =~ /\W/; + my $prop = $overrides->{$name}->[0]; + my $val = $overrides->{$name}->[1]; + if ($prop->{'type'} eq "int") { + $val = int($val); + } elsif ($prop->{'type'} eq "bool") { + $val = $val ? "true" : "false"; + } else { + $val =~ s/[\\\$\"]/\\$&/g; + $val = "\"$val\""; + } + $s2 .= "set $name = $val;\n"; + } + + my $error; + return 1 if LJ::S2::layer_compile($layer, \$error, { 's2ref' => \$s2 }); + return LJ::error($error); +} + +sub layer_compile +{ + my ($layer, $err_ref, $opts) = @_; + my $dbh = LJ::get_db_writer(); + + my $lid; + if (ref $layer eq "HASH") { + $lid = $layer->{'s2lid'}+0; + } else { + $lid = $layer+0; + $layer = LJ::S2::load_layer($dbh, $lid) or return 0; + } + return 0 unless $lid; + + # get checker (cached, or via compiling) for parent layer + my $checker = get_layer_checker($layer); + unless ($checker) { + $$err_ref = "Error compiling parent layer."; + return undef; + } + + # do our compile (quickly, since we probably have the cached checker) + my $s2ref = $opts->{'s2ref'}; + unless ($s2ref) { + my $s2 = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $lid); + unless ($s2) { $$err_ref = "No source code to compile."; return undef; } + $s2ref = \$s2; + } + + my $is_system = $layer->{'userid'} == LJ::get_userid("system"); + my $untrusted = ! $LJ::S2_TRUSTED{$layer->{'userid'}} && ! $is_system; + + # system writes go to global. otherwise to user clusters. + my $dbcm; + if ($is_system) { + $dbcm = $dbh; + } else { + my $u = LJ::load_userid($layer->{'userid'}); + $dbcm = $u; + } + return 0 unless $dbcm; + + my $compiled; + my $cplr = S2::Compiler->new({ 'checker' => $checker }); + eval { + $cplr->compile_source({ + 'type' => $layer->{'type'}, + 'source' => $s2ref, + 'output' => \$compiled, + 'layerid' => $lid, + 'untrusted' => $untrusted, + 'builtinPackage' => "S2::Builtin::LJ", + }); + }; + if ($@) { $$err_ref = "Compile error: $@"; return undef; } + + # save the source, since it at least compiles + if ($opts->{'s2ref'}) { + $dbh->do("REPLACE INTO s2source (s2lid, s2code) VALUES (?,?)", + undef, $lid, ${$opts->{'s2ref'}}) or return 0; + } + + # save the checker object for later + if ($layer->{'type'} eq "core" || $layer->{'type'} eq "layout") { + $checker->cleanForFreeze(); + my $chk_frz = Storable::freeze($checker); + LJ::text_compress(\$chk_frz); + $dbh->do("REPLACE INTO s2checker (s2lid, checker) VALUES (?,?)", undef, + $lid, $chk_frz) or die; + } + + # load the compiled layer to test it loads and then get layerinfo/etc from it + S2::unregister_layer($lid); + eval $compiled; + if ($@) { $$err_ref = "Post-compilation error: $@"; return undef; } + if ($opts->{'redist_uniq'}) { + # used by update-db loader: + my $redist_uniq = S2::get_layer_info($lid, "redist_uniq"); + die "redist_uniq value of '$redist_uniq' doesn't match $opts->{'redist_uniq'}\n" + unless $redist_uniq eq $opts->{'redist_uniq'}; + } + + # put layerinfo into s2info + my %info = S2::get_layer_info($lid); + my $values; + my $notin; + foreach (keys %info) { + $values .= "," if $values; + $values .= sprintf("(%d, %s, %s)", $lid, + $dbh->quote($_), $dbh->quote($info{$_})); + $notin .= "," if $notin; + $notin .= $dbh->quote($_); + } + if ($values) { + $dbh->do("REPLACE INTO s2info (s2lid, infokey, value) VALUES $values") or die; + $dbh->do("DELETE FROM s2info WHERE s2lid=? AND infokey NOT IN ($notin)", undef, $lid); + } + if ($opts->{'layerinfo'}) { + ${$opts->{'layerinfo'}} = \%info; + } + + # put compiled into database, with its ID number + if ($is_system) { + $dbh->do("REPLACE INTO s2compiled (s2lid, comptime, compdata) ". + "VALUES (?, UNIX_TIMESTAMP(), ?)", undef, $lid, $compiled) or die; + } else { + my $gzipped = LJ::text_compress($compiled); + $dbcm->do("REPLACE INTO s2compiled2 (userid, s2lid, comptime, compdata) ". + "VALUES (?, ?, UNIX_TIMESTAMP(), ?)", undef, + $layer->{'userid'}, $lid, $gzipped) or die; + + # delete from memcache; we can't store since we don't know the exact comptime + LJ::MemCache::delete([ $lid, "s2c:$lid" ]); + } + + # caller might want the compiled source + if (ref $opts->{'compiledref'} eq "SCALAR") { + ${$opts->{'compiledref'}} = $compiled; + } + + S2::unregister_layer($lid); + return 1; +} + +sub get_layer_checker +{ + my $lay = shift; + my $err_ref = shift; + return undef unless ref $lay eq "HASH"; + return S2::Checker->new() if $lay->{'type'} eq "core"; + my $parid = $lay->{'b2lid'}+0 or return undef; + my $dbh = LJ::get_db_writer(); + + my $get_cached = sub { + my $frz = $dbh->selectrow_array("SELECT checker FROM s2checker WHERE s2lid=?", + undef, $parid) or return undef; + LJ::text_uncompress(\$frz); + return Storable::thaw($frz); # can be undef, on failure + }; + + # the good path + my $checker = $get_cached->(); + return $checker if $checker; + + # no cached checker (or bogus), so we have to [re]compile to get it + my $parlay = LJ::S2::load_layer($dbh, $parid); + return undef unless LJ::S2::layer_compile($parlay); + return $get_cached->(); +} + +sub load_layer_info +{ + my ($outhash, $listref) = @_; + return 0 unless ref $listref eq "ARRAY"; + return 1 unless @$listref; + my $in = join(',', map { $_+0 } @$listref); + my $dbr = LJ::S2::get_s2_reader(); + my $sth = $dbr->prepare("SELECT s2lid, infokey, value FROM s2info WHERE ". + "s2lid IN ($in)"); + $sth->execute; + while (my ($id, $k, $v) = $sth->fetchrow_array) { + $outhash->{$id}->{$k} = $v; + } + return 1; +} + +sub get_layout_langs +{ + my $src = shift; + my $layid = shift; + my %lang; + foreach (keys %$src) { + next unless /^\d+$/; + my $v = $src->{$_}; + next unless $v->{'langcode'}; + $lang{$v->{'langcode'}} = $src->{$_} + if ($v->{'type'} eq "i18nc" || + ($v->{'type'} eq "i18n" && $layid && $v->{'b2lid'} == $layid)); + } + return map { $_, $lang{$_}->{'name'} } sort keys %lang; +} + +# returns array of hashrefs +sub get_layout_themes +{ + my $src = shift; $src = [ $src ] unless ref $src eq "ARRAY"; + my $layid = shift; + my @themes; + foreach my $src (@$src) { + foreach (sort { $src->{$a}->{'name'} cmp $src->{$b}->{'name'} } keys %$src) { + next unless /^\d+$/; + my $v = $src->{$_}; + push @themes, $v if + ($v->{'type'} eq "theme" && $layid && $v->{'b2lid'} == $layid); + } + } + return @themes; +} + +sub get_layout_themes_select +{ + my @sel; + my $last_uid; + foreach my $t (get_layout_themes(@_)) { + if ($last_uid && $t->{'userid'} != $last_uid) { + push @sel, 0, '---'; # divider between system & user + } + $last_uid = $t->{'userid'}; + push @sel, $t->{'s2lid'}, $t->{'name'}; + } + return @sel; +} + +sub get_policy +{ + return $LJ::S2::CACHE_POLICY if $LJ::S2::CACHE_POLICY; + my $policy = {}; + + # localize $_ so that the while (

    ) below doesn't clobber it and cause problems + # in anybody that happens to be calling us + local $_; + + foreach my $infix ("", "-local") { + my $file = "$LJ::HOME/bin/upgrading/s2layers/policy${infix}.dat"; + my $layer = undef; + open (P, $file) or next; + while (

    ) { + s/\#.*//; + next unless /\S/; + if (/^\s*layer\s*:\s*(\S+)\s*$/) { + $layer = $1; + next; + } + next unless $layer; + s/^\s+//; s/\s+$//; + my @words = split(/\s+/, $_); + next unless $words[-1] eq "allow" || $words[-1] eq "deny"; + my $allow = $words[-1] eq "allow" ? 1 : 0; + if ($words[0] eq "use" && @words == 2) { + $policy->{$layer}->{'use'} = $allow; + } + if ($words[0] eq "props" && @words == 2) { + $policy->{$layer}->{'props'} = $allow; + } + if ($words[0] eq "prop" && @words == 3) { + $policy->{$layer}->{'prop'}->{$words[1]} = $allow; + } + } + } + + return $LJ::S2::CACHE_POLICY = $policy; +} + +sub can_use_layer +{ + my ($u, $uniq) = @_; # $uniq = redist_uniq value + return 1 if LJ::get_cap($u, "s2styles"); + my $pol = get_policy(); + my $can = 0; + foreach ('*', $uniq) { + next unless defined $pol->{$_}; + next unless defined $pol->{$_}->{'use'}; + $can = $pol->{$_}->{'use'}; + } + return $can; +} + +sub can_use_prop +{ + my ($u, $uniq, $prop) = @_; # $uniq = redist_uniq value + return 1 if LJ::get_cap($u, "s2styles"); + my $pol = get_policy(); + my $can = 0; + my @layers = ('*'); + my $pub = get_public_layers(); + if ($pub->{$uniq} && $pub->{$uniq}->{'type'} eq "layout") { + my $cid = $pub->{$uniq}->{'b2lid'}; + push @layers, $pub->{$cid}->{'uniq'} if $pub->{$cid}; + } + push @layers, $uniq; + foreach my $lay (@layers) { + foreach my $it ('props', 'prop') { + if ($it eq "props" && defined $pol->{$lay}->{'props'}) { + $can = $pol->{$lay}->{'props'}; + } + if ($it eq "prop" && defined $pol->{$lay}->{'prop'}->{$prop}) { + $can = $pol->{$lay}->{'prop'}->{$prop}; + } + } + } + return $can; +} + +sub get_journal_day_counts +{ + my ($s2page) = @_; + return $s2page->{'_day_counts'} if defined $s2page->{'_day_counts'}; + + my $u = $s2page->{'_u'}; + my $counts = {}; + + my $remote = LJ::get_remote(); + my $days = LJ::get_daycounts($u, $remote) or return {}; + foreach my $day (@$days) { + $counts->{$day->[0]}->{$day->[1]}->{$day->[2]} = $day->[3]; + } + + return $s2page->{'_day_counts'} = $counts; +} + + +## S2 object constructors + +sub CommentInfo +{ + my $opts = shift; + $opts->{'_type'} = "CommentInfo"; + $opts->{'count'} += 0; + return $opts; +} + +sub Date +{ + my @parts = @_; + my $dt = { '_type' => 'Date' }; + $dt->{'year'} = $parts[0]+0; + $dt->{'month'} = $parts[1]+0; + $dt->{'day'} = $parts[2]+0; + $dt->{'_dayofweek'} = $parts[3]; + die "S2 Builtin Date() takes day of week 1-7, not 0-6" + if defined $parts[3] && $parts[3] == 0; + return $dt; +} + +sub DateTime_unix +{ + my $time = shift; + my @gmtime = gmtime($time); + my $dt = { '_type' => 'DateTime' }; + $dt->{'year'} = $gmtime[5]+1900; + $dt->{'month'} = $gmtime[4]+1; + $dt->{'day'} = $gmtime[3]; + $dt->{'hour'} = $gmtime[2]; + $dt->{'min'} = $gmtime[1]; + $dt->{'sec'} = $gmtime[0]; + $dt->{'_dayofweek'} = $gmtime[6] + 1; + return $dt; +} + +sub DateTime_parts +{ + my @parts = split(/\s+/, shift); + my $dt = { '_type' => 'DateTime' }; + $dt->{'year'} = $parts[0]+0; + $dt->{'month'} = $parts[1]+0; + $dt->{'day'} = $parts[2]+0; + $dt->{'hour'} = $parts[3]+0; + $dt->{'min'} = $parts[4]+0; + $dt->{'sec'} = $parts[5]+0; + # the parts string comes from MySQL which has range 0-6, + # but internally and to S2 we use 1-7. + $dt->{'_dayofweek'} = $parts[6] + 1 if defined $parts[6]; + return $dt; +} + +sub Tag +{ + my ($u, $kwid, $kw) = @_; + + my $e = { + _type => 'Tag', + _id => $kwid, + name => LJ::ehtml($kw), + url => LJ::journal_base($u) . '/tag/' . LJ::eurl($kw), + }; + + return $e; +} + +sub Entry +{ + my ($u, $arg) = @_; + my $e = { + '_type' => 'Entry', + 'link_keyseq' => [ 'edit_entry', 'edit_tags' ], + 'metadata' => {}, + }; + foreach (qw(subject _rawsubject text journal poster new_day end_day + comments userpic permalink_url itemid tags)) { + $e->{$_} = $arg->{$_}; + } + + $e->{'tags'} ||= []; + $e->{'time'} = DateTime_parts($arg->{'dateparts'}); + $e->{'depth'} = 0; # Entries are always depth 0. Comments are 1+. + + my $link_keyseq = $e->{'link_keyseq'}; + push @$link_keyseq, 'mem_add' unless $LJ::DISABLED{'memories'}; + push @$link_keyseq, 'tell_friend' unless $LJ::DISABLED{'tellafriend'}; + # Note: nav_prev and nav_next are not included in the keyseq anticipating + # that their placement relative to the others will vary depending on + # layout. + + if ($arg->{'security'} eq "public") { + # do nothing. + } elsif ($arg->{'security'} eq "usemask") { + $e->{'security'} = "protected"; + $e->{'security_icon'} = Image_std("security-protected"); + } elsif ($arg->{'security'} eq "private") { + $e->{'security'} = "private"; + $e->{'security_icon'} = Image_std("security-private"); + } + + my $p = $arg->{'props'}; + if ($p->{'current_music'}) { + $e->{'metadata'}->{'music'} = $p->{'current_music'}; + LJ::CleanHTML::clean_subject(\$e->{'metadata'}->{'music'}); + } + if (my $mid = $p->{'current_moodid'}) { + my $theme = defined $arg->{'moodthemeid'} ? $arg->{'moodthemeid'} : $u->{'moodthemeid'}; + my %pic; + $e->{'mood_icon'} = Image($pic{'pic'}, $pic{'w'}, $pic{'h'}) + if LJ::get_mood_picture($theme, $mid, \%pic); + if (my $mood = LJ::mood_name($mid)) { + $e->{'metadata'}->{'mood'} = $mood; + } + } + if ($p->{'current_mood'}) { + $e->{'metadata'}->{'mood'} = $p->{'current_mood'}; + LJ::CleanHTML::clean_subject(\$e->{'metadata'}->{'mood'}); + } + + return $e; +} + +sub Friend +{ + my ($u) = @_; + my $o = UserLite($u); + $o->{'_type'} = "Friend"; + $o->{'bgcolor'} = S2::Builtin::LJ::Color__Color($u->{'bgcolor'}); + $o->{'fgcolor'} = S2::Builtin::LJ::Color__Color($u->{'fgcolor'}); + return $o; +} + +sub Null +{ + my $type = shift; + return { + '_type' => $type, + '_isnull' => 1, + }; +} + +sub Page +{ + my ($u, $opts) = @_; + my $styleid = $u->{'_s2styleid'} + 0; + my $base_url = $u->{'_journalbase'}; + + my $get = $opts->{'getargs'}; + my %args; + foreach my $k (keys %$get) { + my $v = $get->{$k}; + next unless $k =~ s/^\.//; + $args{$k} = $v; + } + + # get MAX(modtime of style layers) + my $stylemodtime = S2::get_style_modtime($opts->{'ctx'}); + my $style = load_style($u->{'s2_style'}); + $stylemodtime = $style->{'modtime'} if $style->{'modtime'} > $stylemodtime; + + my $linkobj = LJ::Links::load_linkobj($u); + my $linklist = [ map { UserLink($_) } @$linkobj ]; + + my $p = { + '_type' => 'Page', + '_u' => $u, + 'view' => '', + 'args' => \%args, + 'journal' => User($u), + 'journal_type' => $u->{'journaltype'}, + 'time' => DateTime_unix(time), + 'base_url' => $base_url, + 'stylesheet_url' => "$base_url/res/$styleid/stylesheet?$stylemodtime", + 'view_url' => { + 'recent' => "$base_url/", + 'userinfo' => "$LJ::SITEROOT/userinfo.bml?user=$u->{'user'}", + 'archive' => "$base_url/calendar", + 'friends' => "$base_url/friends", + }, + 'linklist' => $linklist, + 'views_order' => [ 'recent', 'archive', 'friends', 'userinfo' ], + 'global_title' => LJ::ehtml($u->{'journaltitle'} || $u->{'name'}), + 'global_subtitle' => LJ::ehtml($u->{'journalsubtitle'}), + 'head_content' => '', + }; + + if (LJ::are_hooks('s2_head_content_extra')) { + my $remote = LJ::get_remote(); + $p->{head_content} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + if ($LJ::UNICODE && $opts && $opts->{'saycharset'}) { + $p->{'head_content'} .= '\n"; + } + + # Automatic Discovery of RSS/Atom + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + $p->{'head_content'} .= qq{\n}; + + # FOAF autodiscovery + my $foafurl = $u->{external_foaf_url} ? LJ::eurl($u->{external_foaf_url}) : "$p->{base_url}/data/foaf"; + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{email}); + $p->{head_content} .= qq{\n}; + $p->{head_content} .= qq{\n}; + + return $p; +} + +sub Image +{ + my ($url, $w, $h, $alttext) = @_; + return { + '_type' => 'Image', + 'url' => $url, + 'width' => $w, + 'height' => $h, + 'alttext' => $alttext, + }; +} + +sub Image_std +{ + my $name = shift; + my $ctx = $LJ::S2::CURR_CTX or die "No S2 context available "; + + unless ($LJ::S2::RES_MADE++) { + $LJ::S2::RES_CACHE = { + 'security-protected' => Image("$LJ::IMGPREFIX/icon_protected.gif", 14, 15, $ctx->[S2::PROPS]->{'text_icon_alt_protected'}), + 'security-private' => Image("$LJ::IMGPREFIX/icon_private.gif", 16, 16, $ctx->[S2::PROPS]->{'text_icon_alt_private'}), + }; + } + return $LJ::S2::RES_CACHE->{$name}; +} + +sub Image_userpic +{ + my ($u, $picid, $kw) = @_; + + $picid ||= LJ::get_picid_from_keyword($u, $kw); + + my $pi = LJ::get_userpic_info($u); + my $p = $pi->{'pic'}->{$picid}; + + return Null("Image") unless $p; + return { + '_type' => "Image", + 'url' => "$LJ::USERPIC_ROOT/$picid/$u->{'userid'}", + 'width' => $p->{'width'}, + 'height' => $p->{'height'}, + 'alttext' => "", + }; +} + +sub ItemRange_fromopts +{ + my $opts = shift; + my $ir = {}; + + my $items = $opts->{'items'}; + my $page_size = ($opts->{'pagesize'}+0) || 25; + my $page = $opts->{'page'}+0 || 1; + my $num_items = scalar @$items; + + my $pages = POSIX::ceil($num_items / $page_size) || 1; + if ($page > $pages) { $page = $pages; } + + splice(@$items, 0, ($page-1)*$page_size) if $page > 1; + splice(@$items, $page_size) if @$items > $page_size; + + $ir->{'current'} = $page; + $ir->{'total'} = $pages; + $ir->{'total_subitems'} = $num_items; + $ir->{'from_subitem'} = ($page-1) * $page_size + 1; + $ir->{'num_subitems_displayed'} = @$items; + $ir->{'to_subitem'} = $ir->{'from_subitem'} + $ir->{'num_subitems_displayed'} - 1; + $ir->{'all_subitems_displayed'} = ($pages == 1); + $ir->{'_url_of'} = $opts->{'url_of'}; + return ItemRange($ir); +} + +sub ItemRange +{ + my $h = shift; # _url_of = sub($n) + $h->{'_type'} = "ItemRange"; + + my $url_of = ref $h->{'_url_of'} eq "CODE" ? $h->{'_url_of'} : sub {"";}; + + $h->{'url_next'} = $url_of->($h->{'current'} + 1) + unless $h->{'current'} >= $h->{'total'}; + $h->{'url_prev'} = $url_of->($h->{'current'} - 1) + unless $h->{'current'} <= 1; + $h->{'url_first'} = $url_of->(1) + unless $h->{'current'} == 1; + $h->{'url_last'} = $url_of->($h->{'total'}) + unless $h->{'current'} == $h->{'total'}; + + return $h; +} + +sub User +{ + my ($u) = @_; + my $o = UserLite($u); + $o->{'_type'} = "User"; + $o->{'default_pic'} = Image_userpic($u, $u->{'defaultpicid'}); + $o->{'userpic_listing_url'} = "$LJ::SITEROOT/allpics.bml?user=".$u->{'user'}; + $o->{'website_url'} = LJ::ehtml($u->{'url'}); + $o->{'website_name'} = LJ::ehtml($u->{'urlname'}); + return $o; +} + +sub UserLink +{ + my $link = shift; # hashref + + # a dash means pass to s2 as blank so it will just insert a blank line + $link->{'title'} = '' if $link->{'title'} eq "-"; + + return { + '_type' => 'UserLink', + 'is_heading' => $link->{'url'} ? 0 : 1, + 'url' => LJ::ehtml($link->{'url'}), + 'title' => LJ::ehtml($link->{'title'}), + 'children' => $link->{'children'} || [], # TODO: implement parent-child relationships + }; +} + +sub UserLite +{ + my ($u) = @_; + my $o = { + '_type' => 'UserLite', + '_u' => $u, + 'username' => LJ::ehtml($u->display_name), + 'name' => LJ::ehtml($u->{'name'}), + 'journal_type' => $u->{'journaltype'}, + }; + return $o; +} + + +############### + +package S2::Builtin::LJ; +use strict; + +sub AUTOLOAD { + no strict; + if ($AUTOLOAD =~ /::(\w+)$/) { + my $real = \&{"S2::Builtin::$1"}; + *{$AUTOLOAD} = $real; + return $real->(@_); + } + die "No such builtin: $AUTOLOAD"; +} + +sub ehtml +{ + my ($ctx, $text) = @_; + return LJ::ehtml($text); +} + +sub eurl +{ + my ($ctx, $text) = @_; + return LJ::eurl($text); +} + +# escape tags only +sub etags { + my ($ctx, $text) = @_; + $text =~ s//>/g; + return $text; +} + +# sanitize URLs +sub clean_url { + my ($ctx, $text) = @_; + unless ($text =~ m!^https?://[^\'\"\\]*$!) { + $text = ""; + } + return $text; +} + +sub get_page +{ + return $LJ::S2::CURR_PAGE; +} + +sub get_plural_phrase +{ + my ($ctx, $n, $prop) = @_; + my $form = S2::run_function($ctx, "lang_map_plural(int)", $n); + my $a = $ctx->[S2::PROPS]->{"_plurals_$prop"}; + unless (ref $a eq "ARRAY") { + $a = $ctx->[S2::PROPS]->{"_plurals_$prop"} = [ split(m!\s*//\s*!, $ctx->[S2::PROPS]->{$prop}) ]; + } + my $text = $a->[$form]; + + # this fixes missing plural forms for russians (who have 2 plural forms) + # using languages like english with 1 plural form + $text = $a->[-1] unless defined $text; + + $text =~ s/\#/$n/; + return LJ::ehtml($text); +} + +sub get_url +{ + my ($ctx, $obj, $view) = @_; + my $dir = "users"; + my $journal_type; + my $user; + + # now get data from one of two paths, depending on if we were given a UserLite + # object or a string for the username + if (ref $obj eq 'HASH') { + $journal_type = $obj->{journal_type}; + $user = $obj->{username}; + } else { + my $u = LJ::load_user($obj); + $journal_type = $u ? $u->{journaltype} : 'P'; + $user = $u ? $u->{user} : $obj; + } + + # construct URL to return + $dir = 'community' if $journal_type eq 'C'; + $view = "info" if $view eq "userinfo"; + $view = "calendar" if $view eq "archive"; + $view = "" if $view eq "recent"; + return "$LJ::SITEROOT/$dir/$user/$view"; +} + +sub htmlattr +{ + my ($ctx, $name, $value) = @_; + return "" if $value eq ""; + $name = lc($name); + return "" if $name =~ /[^a-z]/; + return " $name=\"" . LJ::ehtml($value) . "\""; +} + +sub rand +{ + my ($ctx, $aa, $bb) = @_; + my ($low, $high); + if (ref $aa eq "ARRAY") { + ($low, $high) = (0, @$aa - 1); + } elsif (! defined $bb) { + ($low, $high) = (1, $aa); + } else { + ($low, $high) = ($aa, $bb); + } + return int(rand($high - $low + 1)) + $low; +} + +sub viewer_logged_in +{ + my ($ctx) = @_; + my $remote = LJ::get_remote(); + return defined $remote; +} + +sub viewer_is_owner +{ + my ($ctx) = @_; + my $remote = LJ::get_remote(); + return 0 unless $remote; + return $remote->{'userid'} == $LJ::S2::CURR_PAGE->{'_u'}->{'userid'}; +} + +sub weekdays +{ + my ($ctx) = @_; + return [ 1..7 ]; # FIXME: make this conditionally monday first: [ 2..7, 1 ] +} + +sub set_handler +{ + my ($ctx, $hook, $stmts) = @_; + my $p = $LJ::S2::CURR_PAGE; + return unless $hook =~ /^\w+\#?$/; + $hook =~ s/\#$/ARG/; + + $S2::pout->("\n"); +} + +sub zeropad +{ + my ($ctx, $num, $digits) = @_; + $num += 0; + $digits += 0; + return sprintf("%0${digits}d", $num); +} +*int__zeropad = \&zeropad; + + +sub Color__update_hsl +{ + my ($this, $force) = @_; + return if $this->{'_hslset'}++; + ($this->{'_h'}, $this->{'_s'}, $this->{'_l'}) = + S2::Color::rgb_to_hsl($this->{'r'}, $this->{'g'}, $this->{'b'}); + $this->{$_} = int($this->{$_} * 255 + 0.5) foreach qw(_h _s _l); +} + +sub Color__update_rgb +{ + my ($this) = @_; + + ($this->{'r'}, $this->{'g'}, $this->{'b'}) = + S2::Color::hsl_to_rgb( map { $this->{$_} / 255 } qw(_h _s _l) ); + Color__make_string($this); +} + +sub Color__make_string +{ + my ($this) = @_; + $this->{'as_string'} = sprintf("\#%02x%02x%02x", + $this->{'r'}, + $this->{'g'}, + $this->{'b'}); +} + +# public functions +sub Color__Color +{ + my ($s) = @_; + $s =~ s/^\#//; + $s =~ s/^(\w)(\w)(\w)$/$1$1$2$2$3$3/s; # 'c30' => 'cc3300' + return if $s =~ /[^a-fA-F0-9]/ || length($s) != 6; + + my $this = { '_type' => 'Color' }; + $this->{'r'} = hex(substr($s, 0, 2)); + $this->{'g'} = hex(substr($s, 2, 2)); + $this->{'b'} = hex(substr($s, 4, 2)); + $this->{$_} = $this->{$_} % 256 foreach qw(r g b); + + Color__make_string($this); + return $this; +} + +sub Color__clone +{ + my ($ctx, $this) = @_; + return { %$this }; +} + +sub Color__set_hsl +{ + my ($this, $h, $s, $l) = @_; + $this->{'_h'} = $h % 256; + $this->{'_s'} = $s % 256; + $this->{'_l'} = $l % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); +} + +sub Color__red { + my ($ctx, $this, $r) = @_; + if (defined $r) { + $this->{'r'} = $r % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'r'}; +} + +sub Color__green { + my ($ctx, $this, $g) = @_; + if (defined $g) { + $this->{'g'} = $g % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'g'}; +} + +sub Color__blue { + my ($ctx, $this, $b) = @_; + if (defined $b) { + $this->{'b'} = $b % 256; + delete $this->{'_hslset'}; + Color__make_string($this); + } + $this->{'b'}; +} + +sub Color__hue { + my ($ctx, $this, $h) = @_; + + if (defined $h) { + $this->{'_h'} = $h % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + $this->{'_h'}; +} + +sub Color__saturation { + my ($ctx, $this, $s) = @_; + if (defined $s) { + $this->{'_s'} = $s % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + $this->{'_s'}; +} + +sub Color__lightness { + my ($ctx, $this, $l) = @_; + + if (defined $l) { + $this->{'_l'} = $l % 256; + $this->{'_hslset'} = 1; + Color__update_rgb($this); + } elsif (! $this->{'_hslset'}) { + Color__update_hsl($this); + } + + $this->{'_l'}; +} + +sub Color__inverse { + my ($ctx, $this) = @_; + my $new = { + '_type' => 'Color', + 'r' => 255 - $this->{'r'}, + 'g' => 255 - $this->{'g'}, + 'b' => 255 - $this->{'b'}, + }; + Color__make_string($new); + return $new; +} + +sub Color__average { + my ($ctx, $this, $other) = @_; + my $new = { + '_type' => 'Color', + 'r' => int(($this->{'r'} + $other->{'r'}) / 2 + .5), + 'g' => int(($this->{'g'} + $other->{'g'}) / 2 + .5), + 'b' => int(($this->{'b'} + $other->{'b'}) / 2 + .5), + }; + Color__make_string($new); + return $new; +} + +sub Color__lighter { + my ($ctx, $this, $amt) = @_; + $amt = defined $amt ? $amt : 30; + + Color__update_hsl($this); + + my $new = { + '_type' => 'Color', + '_hslset' => 1, + '_h' => $this->{'_h'}, + '_s' => $this->{'_s'}, + '_l' => ($this->{'_l'} + $amt > 255 ? 255 : $this->{'_l'} + $amt), + }; + + Color__update_rgb($new); + return $new; +} + +sub Color__darker { + my ($ctx, $this, $amt) = @_; + $amt = defined $amt ? $amt : 30; + + Color__update_hsl($this); + + my $new = { + '_type' => 'Color', + '_hslset' => 1, + '_h' => $this->{'_h'}, + '_s' => $this->{'_s'}, + '_l' => ($this->{'_l'} - $amt < 0 ? 0 : $this->{'_l'} - $amt), + }; + + Color__update_rgb($new); + return $new; +} + +sub Comment__get_link +{ + my ($ctx, $this, $key) = @_; + if ($key eq "delete_comment" || $key eq "unscreen_comment" || $key eq "screen_comment" || + $key eq "freeze_thread" || $key eq "unfreeze_thread") { + my $page = get_page(); + my $u = $page->{'_u'}; + my $post_user = $page->{'entry'} ? $page->{'entry'}->{'poster'}->{'username'} : undef; + my $com_user = $this->{'poster'} ? $this->{'poster'}->{'username'} : undef; + my $remote = LJ::get_remote(); + if ($key eq "delete_comment") { + return undef unless LJ::Talk::can_delete($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/delcomment.bml?journal=$u->{'user'}&id=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_delete"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_del.gif", 22, 20), + }; + } + if ($key eq "freeze_thread") { + return undef if $this->{'frozen'}; + return undef unless LJ::Talk::can_freeze($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=freeze&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_freeze"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_freeze.gif", 22, 20), + }; + } + if ($key eq "unfreeze_thread") { + return undef unless $this->{'frozen'}; + return undef unless LJ::Talk::can_unfreeze($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=unfreeze&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_unfreeze"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_unfreeze.gif", 22, 20), + }; + } + if ($key eq "screen_comment") { + return undef if $this->{'screened'}; + return undef unless LJ::Talk::can_screen($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=screen&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_screen"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_scr.gif", 22, 20), + }; + } + if ($key eq "unscreen_comment") { + return undef unless $this->{'screened'}; + return undef unless LJ::Talk::can_unscreen($remote, $u, $post_user, $com_user); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/talkscreen.bml?mode=unscreen&journal=$u->{'user'}&talkid=$this->{'talkid'}", + 'caption' => $ctx->[S2::PROPS]->{"text_multiform_opt_unscreen"}, + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_unscr.gif", 22, 20), + }; + } + } +} + +sub Comment__print_multiform_check +{ + my ($ctx, $this) = @_; + my $tid = $this->{'talkid'} >> 8; + $S2::pout->(""); +} + +# class 'date' +sub Date__day_of_week +{ + my ($ctx, $dt) = @_; + return $dt->{'_dayofweek'} if defined $dt->{'_dayofweek'}; + return $dt->{'_dayofweek'} = LJ::day_of_week($dt->{'year'}, $dt->{'month'}, $dt->{'day'}) + 1; +} +*DateTime__day_of_week = \&Date__day_of_week; + +my %dt_vars = ( + 'm' => "\$time->{month}", + 'mm' => "sprintf('%02d', \$time->{month})", + 'd' => "\$time->{day}", + 'dd' => "sprintf('%02d', \$time->{day})", + 'yy' => "sprintf('%02d', \$time->{year} % 100)", + 'yyyy' => "\$time->{year}", + 'mon' => "\$ctx->[S2::PROPS]->{lang_monthname_short}->[\$time->{month}]", + 'month' => "\$ctx->[S2::PROPS]->{lang_monthname_long}->[\$time->{month}]", + 'da' => "\$ctx->[S2::PROPS]->{lang_dayname_short}->[Date__day_of_week(\$ctx, \$time)]", + 'day' => "\$ctx->[S2::PROPS]->{lang_dayname_long}->[Date__day_of_week(\$ctx, \$time)]", + 'dayord' => "S2::run_function(\$ctx, \"lang_ordinal(int)\", \$time->{day})", + 'H' => "\$time->{hour}", + 'HH' => "sprintf('%02d', \$time->{hour})", + 'h' => "(\$time->{hour} % 12 || 12)", + 'hh' => "sprintf('%02d', (\$time->{hour} % 12 || 12))", + 'min' => "sprintf('%02d', \$time->{min})", + 'sec' => "sprintf('%02d', \$time->{sec})", + 'a' => "(\$time->{hour} < 12 ? 'a' : 'p')", + 'A' => "(\$time->{hour} < 12 ? 'A' : 'P')", + ); + +sub Date__date_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "short"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_datefmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_datefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_date_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_date_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} +*DateTime__date_format = \&Date__date_format; + +sub DateTime__time_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "short"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_timefmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_timefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_time_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_time_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} + +sub EntryLite__get_link +{ + my ($ctx, $this, $key) = @_; + return undef; +} + +sub EntryLite__get_tags_text +{ + my ($ctx, $this) = @_; + return LJ::S2::get_tags_text($ctx, $this->{tags}) || ""; +} +*Entry__get_tags_text = \&EntryLite__get_tags_text; + +sub EntryLite__get_plain_subject +{ + my ($ctx, $this) = @_; + return $this->{'_plainsubject'} if $this->{'_plainsubject'}; + return $this->{'subject'} unless $this->{'_rawsubject'}; + my $subj = $this->{'subject'}; + LJ::CleanHTML::clean_subject_all(\$subj); + return $this->{'_plainsubject'} = $subj; +} +*Entry__get_plain_subject = \&EntryLite__get_plain_subject; + +sub Entry__get_link +{ + my ($ctx, $this, $key) = @_; + if ($key eq "nav_prev" || $key eq "edit_entry" || $key eq "mem_add" || + $key eq "tell_friend" || $key eq "nav_next" || $key eq "edit_tags") + { + my $journal = $this->{'journal'}->{'username'}; + my $poster = $this->{'poster'}->{'username'}; + my $remote = LJ::get_remote(); + + if ($key eq "edit_entry") { + return undef unless $remote && ($remote->{'user'} eq $journal || + $remote->{'user'} eq $poster || + LJ::can_manage($remote, LJ::load_user($journal))); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/editjournal.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Edit Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_edit.gif", 22, 20), + } + } + if ($key eq "edit_tags") { + return undef unless $remote && LJ::Tags::can_add_tags(LJ::load_user($journal), $remote); + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/edittags.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => 'Edit Tags', + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_edittags.gif", 22, 20), + }; + } + if ($key eq "tell_friend") { + return undef if $LJ::DISABLED{'tellafriend'}; + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/tools/tellafriend.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Tell A Friend", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_tellfriend.gif", 22, 20), + }; + } + if ($key eq "mem_add") { + return undef if $LJ::DISABLED{'memories'}; + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/tools/memadd.bml?journal=$journal&itemid=$this->{'itemid'}", + 'caption' => "Add to Memories", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_memories.gif", 22, 20), + }; + } + if ($key eq "nav_prev") { + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/go.bml?journal=$journal&itemid=$this->{'itemid'}&dir=prev", + 'caption' => "Previous Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_prev.gif", 22, 20), + }; + } + if ($key eq "nav_next") { + return { + '_type' => "Link", + 'url' => "$LJ::SITEROOT/go.bml?journal=$journal&itemid=$this->{'itemid'}&dir=next", + 'caption' => "Next Entry", + 'icon' => LJ::S2::Image("$LJ::IMGPREFIX/btn_next.gif", 22, 20), + }; + } + } +} + +sub Entry__plain_subject +{ + my ($ctx, $this) = @_; + return $this->{'_subject_plain'} if defined $this->{'_subject_plain'}; + $this->{'_subject_plain'} = $this->{'subject'}; + LJ::CleanHTML::clean_subject_all(\$this->{'_subject_plain'}); + return $this->{'_subject_plain'}; +} + +sub EntryPage__print_multiform_actionline +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + my $pr = $ctx->[S2::PROPS]; + $S2::pout->($pr->{'text_multiform_des'} . "\n" . + LJ::html_select({'name' => 'mode' }, + "" => "", + map { $_ => $pr->{"text_multiform_opt_$_"} } + qw(unscreen screen delete)) . "\n" . + LJ::html_submit('', $pr->{'text_multiform_btn'}, + { "onclick" => "return (document.multiform.mode.value != \"delete\") " . + "|| confirm(\"" . LJ::ejs($pr->{'text_multiform_conf_delete'}) . "\");" })); +} + +sub EntryPage__print_multiform_end +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + $S2::pout->(""); +} + +sub EntryPage__print_multiform_start +{ + my ($ctx, $this) = @_; + return unless $this->{'multiform_on'}; + $S2::pout->("

    \n" . + LJ::html_hidden("ditemid", $this->{'entry'}->{'itemid'}, + "journal", $this->{'entry'}->{'journal'}->{'username'}) . "\n"); +} + +sub Page__visible_tag_list +{ + my $ctx = shift; + my $remote = LJ::get_remote(); + my $u = $LJ::S2::CURR_PAGE->{'_u'}; + return [] unless $u; + + my $tags = LJ::Tags::get_usertags($u, { remote => $remote }); + return [] unless $tags; + + my @taglist; + foreach my $kwid (keys %{$tags}) { + # only show tags for display + next unless $tags->{$kwid}->{display}; + + # create tag object + push @taglist, LJ::S2::Tag($u, $kwid => $tags->{$kwid}->{name}); + } + + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + return \@taglist; +} +*RecentPage__visible_tag_list = \&Page__visible_tag_list; +*DayPage__visible_tag_list = \&Page__visible_tag_list; +*MonthPage__visible_tag_list = \&Page__visible_tag_list; +*YearPage__visible_tag_list = \&Page__visible_tag_list; +*FriendsPage__visible_tag_list = \&Page__visible_tag_list; +*EntryPage__visible_tag_list = \&Page__visible_tag_list; +*ReplyPage__visible_tag_list = \&Page__visible_tag_list; + +sub Page__get_latest_month +{ + my ($ctx, $this) = @_; + return $this->{'_latest_month'} if defined $this->{'_latest_month'}; + my $counts = LJ::S2::get_journal_day_counts($this); + my ($year, $month); + my @years = sort { $a <=> $b } keys %$counts; + if (@years) { + # year/month of last post + $year = $years[-1]; + $month = (sort { $a <=> $b } keys %{$counts->{$year}})[-1]; + } else { + # year/month of current date, if no posts + my @now = gmtime(time); + ($year, $month) = ($now[5]+1900, $now[4]+1); + } + return $this->{'_latest_month'} = LJ::S2::YearMonth($this, { + 'year' => $year, + 'month' => $month, + }); +} +*RecentPage__get_latest_month = \&Page__get_latest_month; +*DayPage__get_latest_month = \&Page__get_latest_month; +*MonthPage__get_latest_month = \&Page__get_latest_month; +*YearPage__get_latest_month = \&Page__get_latest_month; +*FriendsPage__get_latest_month = \&Page__get_latest_month; +*EntryPage__get_latest_month = \&Page__get_latest_month; +*ReplyPage__get_latest_month = \&Page__get_latest_month; + +sub palimg_modify +{ + my ($ctx, $filename, $items) = @_; + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + return $url unless $items && @$items; + return undef if @$items > 7; + $url .= "/p"; + foreach my $pi (@$items) { + die "Can't modify a palette index greater than 15 with palimg_modify\n" if + $pi->{'index'} > 15; + $url .= sprintf("%1x%02x%02x%02x", + $pi->{'index'}, + $pi->{'color'}->{'r'}, + $pi->{'color'}->{'g'}, + $pi->{'color'}->{'b'}); + } + return $url; +} + +sub palimg_tint +{ + my ($ctx, $filename, $bcol, $dcol) = @_; # bright color, dark color [opt] + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + $url .= "/pt"; + foreach my $col ($bcol, $dcol) { + next unless $col; + $url .= sprintf("%02x%02x%02x", + $col->{'r'}, $col->{'g'}, $col->{'b'}); + } + return $url; +} + +sub palimg_gradient +{ + my ($ctx, $filename, $start, $end) = @_; + return undef unless $filename =~ /^\w[\w\/\-]*\.(gif|png)$/; + my $url = "$LJ::PALIMGROOT/$filename"; + $url .= "/pg"; + foreach my $pi ($start, $end) { + next unless $pi; + $url .= sprintf("%02x%02x%02x%02x", + $pi->{'index'}, + $pi->{'color'}->{'r'}, + $pi->{'color'}->{'g'}, + $pi->{'color'}->{'b'}); + } + return $url; +} + +sub userlite_base_url +{ + my ($ctx, $UserLite) = @_; + my $u = $UserLite->{_u}; + if ($u->{journaltype} eq "P") { + return "$LJ::SITEROOT/users/$u->{user}"; + } elsif ($u->{journaltype} eq "C") { + return "$LJ::SITEROOT/community/$u->{user}"; + } elsif ($u->{journaltype} eq "I") { + return $u->url; + } +} + +sub userlite_as_string +{ + my ($ctx, $UserLite) = @_; + return LJ::ljuser($UserLite->{'_u'}); +} + +sub PalItem +{ + my ($ctx, $idx, $color) = @_; + return undef unless $color && $color->{'_type'} eq "Color"; + return undef unless $idx >= 0 && $idx <= 255; + return { + '_type' => 'PalItem', + 'color' => $color, + 'index' => $idx+0, + }; +} + +sub YearMonth__month_format +{ + my ($ctx, $this, $fmt) = @_; + $fmt ||= "long"; + my $c = \$ctx->[S2::SCRATCH]->{'_code_monthfmt'}->{$fmt}; + return $$c->($this) if ref $$c eq "CODE"; + if (++$ctx->[S2::SCRATCH]->{'_code_timefmt_count'} > 15) { return "[too_many_fmts]"; } + my $realfmt = $fmt; + if (defined $ctx->[S2::PROPS]->{"lang_fmt_month_$fmt"}) { + $realfmt = $ctx->[S2::PROPS]->{"lang_fmt_month_$fmt"}; + } + my @parts = split(/\%\%/, $realfmt); + my $code = "\$\$c = sub { my \$time = shift; return join('',"; + my $i = 0; + foreach (@parts) { + if ($i % 2) { $code .= $dt_vars{$_} . ","; } + else { $_ = LJ::ehtml($_); $code .= "\$parts[$i],"; } + $i++; + } + $code .= "); };"; + eval $code; + return $$c->($this); +} + +sub Image__set_url { + my ($ctx, $img, $newurl) = @_; + $img->{'url'} = LJ::eurl($newurl); +} + +sub ItemRange__url_of +{ + my ($ctx, $this, $n) = @_; + return "" unless ref $this->{'_url_of'} eq "CODE"; + return $this->{'_url_of'}->($n+0); +} + +sub UserLite__equals +{ + return $_[1]->{'_u'}{'userid'} == $_[2]->{'_u'}{'userid'}; +} +*User__equals = \&UserLite__equals; +*Friend__equals = \&UserLite__equals; + +sub string__substr +{ + my ($ctx, $this, $start, $length) = @_; + use utf8; + return substr($this, $start, $length); +} + +sub string__length +{ + use utf8; + my ($ctx, $this) = @_; + return length($this); +} + +sub string__lower +{ + use utf8; + my ($ctx, $this) = @_; + return lc($this); +} + +sub string__upper +{ + use utf8; + my ($ctx, $this) = @_; + return uc($this); +} + +sub string__upperfirst +{ + use utf8; + my ($ctx, $this) = @_; + return ucfirst($this); +} + +sub string__starts_with +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /^\Q$str\E/; +} + +sub string__ends_with +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /\Q$str\E$/; +} + +sub string__contains +{ + use utf8; + my ($ctx, $this, $str) = @_; + return $this =~ /\Q$str\E/; +} + +sub string__repeat +{ + use utf8; + my ($ctx, $this, $num) = @_; + $num += 0; + my $size = length($this) * $num; + return "[too large]" if $size > 5000; + return $this x $num; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/DayPage.pm b/livejournal/cgi-bin/LJ/S2/DayPage.pm new file mode 100755 index 0000000..f48c5f8 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/DayPage.pm @@ -0,0 +1,239 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub DayPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "DayPage"; + $p->{'view'} = "day"; + $p->{'entries'} = []; + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/calendar" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + my $get = $opts->{'getargs'}; + + my $month = $get->{'month'}; + my $day = $get->{'day'}; + my $year = $get->{'year'}; + my @errors = (); + + if ($opts->{'pathextra'} =~ m!^/(\d\d\d\d)/(\d\d)/(\d\d)\b!) { + ($month, $day, $year) = ($2, $3, $1); + } + + $opts->{'errors'} = []; + if ($year !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant year."; } + if ($month !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant month."; } + if ($day !~ /^\d+$/) { push @{$opts->{'errors'}}, "Corrupt or non-existant day."; } + if ($month < 1 || $month > 12 || int($month) != $month) { push @{$opts->{'errors'}}, "Invalid month."; } + if ($year < 1970 || $year > 2038 || int($year) != $year) { push @{$opts->{'errors'}}, "Invalid year: $year"; } + if ($day < 1 || $day > 31 || int($day) != $day) { push @{$opts->{'errors'}}, "Invalid day."; } + if (scalar(@{$opts->{'errors'}})==0 && $day > LJ::days_in_month($month, $year)) { push @{$opts->{'errors'}}, "That month doesn't have that many days."; } + return if @{$opts->{'errors'}}; + + $p->{'date'} = Date($year, $month, $day); + + my $secwhere = "AND security='public'"; + my $viewall = 0; + my $viewsome = 0; # see public posts from suspended users + if ($remote) { + + # do they have the viewall priv? + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "day: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (security='public' OR (security='usemask' AND allowmask & $gmask))" + if $gmask; + } + } + + my $dbcr = LJ::get_cluster_reader($u); + unless ($dbcr) { + push @{$opts->{'errors'}}, "Database temporarily unavailable"; + return; + } + + # load the log items + my $dateformat = "%Y %m %d %H %i %s %w"; # yyyy mm dd hh mm ss day_of_week + my $sth = $dbcr->prepare("SELECT jitemid AS itemid, posterid, security, DATE_FORMAT(eventtime, \"$dateformat\") AS 'alldatepart', anum ". + "FROM log2 " . + "WHERE journalid=$u->{'userid'} AND year=$year AND month=$month AND day=$day $secwhere " . + "ORDER BY eventtime, logtime LIMIT 200"); + $sth->execute; + + my @items; + push @items, $_ while $_ = $sth->fetchrow_hashref; + my @itemids = map { $_->{'itemid'} } @items; + + # load 'opt_ljcut_disable_lastn' prop for $remote. + LJ::load_user_props($remote, "opt_ljcut_disable_lastn"); + + ### load the log properties + my %logprops = (); + my $logtext; + LJ::load_log_props2($dbcr, $u->{'userid'}, \@itemids, \%logprops); + $logtext = LJ::get_logtext2($u, @itemids); + + my (%apu, %apu_lite); # alt poster users; UserLite objects + foreach (@items) { + next unless $_->{'posterid'} != $u->{'userid'}; + $apu{$_->{'posterid'}} = undef; + } + if (%apu) { + LJ::load_userids_multiple([map { $_, \$apu{$_} } keys %apu], [$u]); + $apu_lite{$_} = UserLite($apu{$_}) foreach keys %apu; + } + + # load tags + my $tags = LJ::Tags::get_logtags($u, \@itemids); + + my $userlite_journal = UserLite($u); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart, $anum) = + map { $item->{$_} } qw(posterid itemid security alldatepart anum); + + my $replycount = $logprops{$itemid}->{'replycount'}; + my $subject = $logtext->{$itemid}->[0]; + my $text = $logtext->{$itemid}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + # don't show posts from suspended users + next ENTRY if $apu{$posterid} && $apu{$posterid}->{'statusvis'} eq 'S' && ! $viewsome; + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$subject, \$text, $logprops{$itemid}); + } + + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid*256 + $anum; + + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $anum), + 'ljcut_disable' => $remote->{'opt_ljcut_disable_lastn'}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$text); + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $logprops{$itemid}->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($logprops{$itemid}->{'hasscreened'} && $remote && + ($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $apu_lite{$posterid} or die "No apu_lite for posterid=$posterid"; + $pu = $apu{$posterid}; + } + my $userpic = Image_userpic($pu, 0, $logprops{$itemid}->{'picture_keyword'}); + + my @taglist; + while (my ($kwid, $kw) = each %{$tags->{$itemid} || {}}) { + push @taglist, Tag($u, $kwid => $kw); + } + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + + if ($opts->{enable_tags_compatibility} && @taglist) { + $text .= LJ::S2::get_tags_text($opts->{ctx}, \@taglist); + } + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $logprops{$itemid}, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'tags' => \@taglist, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + }); + + push @{$p->{'entries'}}, $entry; + } + + if (@{$p->{'entries'}}) { + $p->{'has_entries'} = 1; + $p->{'entries'}->[0]->{'new_day'} = 1; + $p->{'entries'}->[-1]->{'end_day'} = 1; + } + + # calculate previous day + my $pdyear = $year; + my $pdmonth = $month; + my $pdday = $day-1; + if ($pdday < 1) + { + if (--$pdmonth < 1) + { + $pdmonth = 12; + $pdyear--; + } + $pdday = LJ::days_in_month($pdmonth, $pdyear); + } + + # calculate next day + my $nxyear = $year; + my $nxmonth = $month; + my $nxday = $day+1; + if ($nxday > LJ::days_in_month($nxmonth, $nxyear)) + { + $nxday = 1; + if (++$nxmonth > 12) { ++$nxyear; $nxmonth=1; } + } + + $p->{'prev_url'} = "$u->{'_journalbase'}/" . sprintf("%04d/%02d/%02d/", $pdyear, $pdmonth, $pdday); + $p->{'prev_date'} = Date($pdyear, $pdmonth, $pdday); + $p->{'next_url'} = "$u->{'_journalbase'}/" . sprintf("%04d/%02d/%02d/", $nxyear, $nxmonth, $nxday); + $p->{'next_date'} = Date($nxyear, $nxmonth, $nxday); + + return $p; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/EntryPage.pm b/livejournal/cgi-bin/LJ/S2/EntryPage.pm new file mode 100755 index 0000000..45020fe --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/EntryPage.pm @@ -0,0 +1,377 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub EntryPage +{ + my ($u, $remote, $opts) = @_; + + my $get = $opts->{'getargs'}; + + my $p = Page($u, $opts); + $p->{'_type'} = "EntryPage"; + $p->{'view'} = "entry"; + $p->{'comment_pages'} = undef; + $p->{'comments'} = []; + $p->{'comment_pages'} = undef; + + # setup viewall options + my ($viewall, $viewsome) = (0, 0); + if ($get->{viewall} && LJ::check_priv($remote, 'canview')) { + # we don't log here, as we don't know what entry we're viewing yet. the logging + # is done when we call EntryPage_entry below. + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + my ($entry, $s2entry) = EntryPage_entry($u, $remote, $opts); + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + + $p->{'multiform_on'} = $remote && + ($remote->{'userid'} == $u->{'userid'} || + $remote->{'userid'} == $entry->{'posterid'} || + LJ::can_manage($remote, $u)); + + my $itemid = $entry->{'itemid'}; + my $ditemid = $entry->{'itemid'} * 256 + $entry->{'anum'}; + my $permalink = LJ::journal_base($u) . "/$ditemid.html"; + my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : ""; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/$ditemid.html" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $p->{'head_content'} .= '\n"; + } + + $p->{'entry'} = $s2entry; + + # add the comments + my %userpic; + my %user; + my $copts = { + 'thread' => ($get->{'thread'} >> 8), + 'page' => $get->{'page'}, + 'view' => $get->{'view'}, + 'userpicref' => \%userpic, + 'userref' => \%user, + # user object is cached from call just made in EntryPage_entry + 'up' => LJ::load_user($s2entry->{'poster'}->{'username'}), + 'viewall' => $viewall, + }; + + my $userlite_journal = UserLite($u); + + my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $copts); + + my $pics = LJ::Talk::get_subjecticons()->{'pic'}; # hashref of imgname => { w, h, img } + my $convert_comments = sub { + my ($self, $destlist, $srclist, $depth) = @_; + + foreach my $com (@$srclist) { + my $dtalkid = $com->{'talkid'} * 256 + $entry->{'anum'}; + my $text = $com->{'body'}; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + LJ::CleanHTML::clean_comment(\$text, { 'preformatted' => $com->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$com->{posterid}}); + + # local time in mysql format to gmtime + my $datetime = DateTime_unix(LJ::mysqldate_to_time($com->{'datepost'})); + + my $subject_icon = undef; + if (my $si = $com->{'props'}->{'subjecticon'}) { + my $pic = $pics->{$si}; + $subject_icon = Image("$LJ::IMGPREFIX/talk/$pic->{'img'}", + $pic->{'w'}, $pic->{'h'}) if $pic; + } + + my $comment_userpic; + if (my $pic = $userpic{$com->{'picid'}}) { + $comment_userpic = Image("$LJ::USERPIC_ROOT/$com->{'picid'}/$pic->{'userid'}", + $pic->{'width'}, $pic->{'height'}); + } + + my $reply_url = LJ::Talk::talkargs($permalink, "replyto=$dtalkid", $stylemine); + + my $par_url; + if ($com->{'parenttalkid'}) { + my $dparent = ($com->{'parenttalkid'} << 8) + $entry->{'anum'}; + $par_url = LJ::Talk::talkargs($permalink, "thread=$dparent", $stylemine) . "#t$dparent"; + } + + my $poster; + if ($com->{'posterid'}) { + if ($user{$com->{'posterid'}}) { + $poster = UserLite($user{$com->{'posterid'}}); + } else { + $poster = { + '_type' => 'UserLite', + 'username' => $com->{'userpost'}, + 'name' => $com->{'userpost'}, # we don't have this, so fake it + 'journal_type' => 'P', # fake too, but only people can post, so correct + }; + } + } + + my $s2com = { + '_type' => 'Comment', + 'journal' => $userlite_journal, + 'metadata' => { + 'picture_keyword' => $com->{'props'}->{'picture_keyword'}, + }, + 'permalink_url' => "$permalink?thread=$dtalkid#t$dtalkid", + 'reply_url' => $reply_url, + 'poster' => $poster, + 'replies' => [], + 'subject' => LJ::ehtml($com->{'subject'}), + 'subject_icon' => $subject_icon, + 'talkid' => $dtalkid, + 'text' => $text, + 'userpic' => $comment_userpic, + 'time' => $datetime, + 'tags' => [], + 'full' => $com->{'_loaded'} ? 1 : 0, + 'depth' => $depth, + 'parent_url' => $par_url, + 'screened' => $com->{'state'} eq "S" ? 1 : 0, + 'frozen' => $com->{'state'} eq "F" ? 1 : 0, + 'link_keyseq' => [ 'delete_comment' ], + 'anchor' => "t$dtalkid", + 'dom_id' => "ljcmt$dtalkid", + }; + + # don't show info from suspended users + # FIXME: ideally the load_comments should only return these + # items if there are children, otherwise they should be hidden entirely + my $pu = $com->{'posterid'} ? $user{$com->{'posterid'}} : undef; + if ($pu && $pu->{'statusvis'} eq "S" && !$viewsome) { + $s2com->{'text'} = ""; + $s2com->{'subject'} = ""; + $s2com->{'full'} = 0; + $s2com->{'subject_icon'} = undef; + $s2com->{'userpic'} = undef; + } + + # Conditionally add more links to the keyseq + my $link_keyseq = $s2com->{'link_keyseq'}; + push @$link_keyseq, $s2com->{'screened'} ? 'unscreen_comment' : 'screen_comment'; + push @$link_keyseq, $s2com->{'frozen'} ? 'unfreeze_thread' : 'freeze_thread'; + + if (@{$com->{'children'}}) { + $s2com->{'thread_url'} = LJ::Talk::talkargs($permalink, "thread=$dtalkid", $stylemine) . "#t$dtalkid"; + } + + # add the poster_ip metadata if remote user has + # access to see it. + $s2com->{'metadata'}->{'poster_ip'} = $com->{'props'}->{'poster_ip'} if + ($com->{'props'}->{'poster_ip'} && $remote && + ($remote->{'userid'} == $entry->{'posterid'} || + LJ::can_manage($remote, $u) || $viewall)); + + push @$destlist, $s2com; + + $self->($self, $s2com->{'replies'}, $com->{'children'}, $depth+1); + } + }; + $p->{'comments'} = []; + $convert_comments->($convert_comments, $p->{'comments'}, \@comments, 1); + + # prepare the javascript data structure to put in the top of the page + # if the remote user is a manager of the comments + my $do_commentmanage_js = $p->{'multiform_on'}; + if ($LJ::DISABLED{'commentmanage'}) { + if (ref $LJ::DISABLED{'commentmanage'} eq "CODE") { + $do_commentmanage_js = $LJ::DISABLED{'commentmanage'}->($remote); + } else { + $do_commentmanage_js = 0; + } + } + + if ($do_commentmanage_js) { + my $js = "\n"; + $p->{'head_content'} .= $js; + $p->{'head_content'} .= "\n"; + + } + + + $p->{'viewing_thread'} = $get->{'thread'} ? 1 : 0; + + # default values if there were no comments, because + # LJ::Talk::load_comments() doesn't provide them. + if ($copts->{'out_error'} eq 'noposts') { + $copts->{'out_pages'} = $copts->{'out_page'} = 1; + $copts->{'out_items'} = 0; + $copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef; + } + + $p->{'comment_pages'} = ItemRange({ + 'all_subitems_displayed' => ($copts->{'out_pages'} == 1), + 'current' => $copts->{'out_page'}, + 'from_subitem' => $copts->{'out_itemfirst'}, + 'num_subitems_displayed' => scalar @comments, + 'to_subitem' => $copts->{'out_itemlast'}, + 'total' => $copts->{'out_pages'}, + 'total_subitems' => $copts->{'out_items'}, + '_url_of' => sub { return "$permalink?page=" . int($_[0]) . + ($stylemine ? "&$stylemine" : ''); }, + }); + + return $p; +} + +sub EntryPage_entry +{ + my ($u, $remote, $opts) = @_; + + my $get = $opts->{'getargs'}; + + my $r = $opts->{'r'}; + my $uri = $r->uri; + + my ($ditemid, $itemid, $anum); + unless ($uri =~ /(\d+)\.html/) { + $opts->{'handler_return'} = 404; + return; + } + + $ditemid = $1; + $anum = $ditemid % 256; + $itemid = $ditemid >> 8; + + my $entry = LJ::Talk::get_journal_item($u, $itemid); + unless ($entry && $entry->{'anum'} == $anum) { + $opts->{'handler_return'} = 404; + return; + } + + my $userlite_journal = UserLite($u); + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($entry->{'posterid'} != $entry->{'ownerid'}) { + $pu = LJ::load_userid($entry->{'posterid'}); + $userlite_poster = UserLite($pu); + } + + # do they have the viewall priv? + my $viewall = 0; + my $viewsome = 0; + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "entry: $u->{'user'}, itemid: $itemid, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + # check using normal rules + unless (LJ::can_view($remote, $entry) || $viewall) { + $opts->{'handler_return'} = 403; + return; + } + if (($pu && $pu->{'statusvis'} eq 'S') && !$viewsome) { + $opts->{'suspendeduser'} = 1; + return; + } + + my $replycount = $entry->{'props'}->{'replycount'}; + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $stylemine = $get->{'style'} eq "mine" ? "style=mine" : ""; + + my $userpic = Image_userpic($pu, 0, $entry->{'props'}->{'picture_keyword'}); + + my $permalink = LJ::journal_base($u) . "/$ditemid.html"; + my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine); + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine); + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! + $entry->{'props'}->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($entry->{'props'}->{'hasscreened'} && $remote && + ($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + # format it + if ($opts->{'getargs'}->{'nohtml'}) { + # quote all non-LJ tags + $entry->{'subject'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $entry->{'event'} =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + my $raw_subj = $entry->{'subject'}; + LJ::CleanHTML::clean_subject(\$entry->{'subject'}); + LJ::CleanHTML::clean_event(\$entry->{'event'}, $entry->{'props'}->{'opt_preformatted'}); + LJ::expand_embedded($u, $ditemid, $remote, \$entry->{'event'}); + + # load tags + my @taglist; + my $tags = LJ::Tags::get_logtags($u, $itemid); + while (my ($kwid, $kw) = each %{$tags->{$itemid} || {}}) { + push @taglist, Tag($u, $kwid => $kw); + } + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + + if ($opts->{enable_tags_compatibility} && @taglist) { + $entry->{event} .= LJ::S2::get_tags_text($opts->{ctx}, \@taglist); + } + + my $s2entry = Entry($u, { + '_rawsubject' => $raw_subj, + 'subject' => $entry->{'subject'}, + 'text' => $entry->{'event'}, + 'dateparts' => $entry->{'alldatepart'}, + 'security' => $entry->{'security'}, + 'props' => $entry->{'props'}, + 'itemid' => $ditemid, + 'comments' => $comments, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'tags' => \@taglist, + 'new_day' => 0, + 'end_day' => 0, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + }); + + return ($entry, $s2entry); +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/FriendsPage.pm b/livejournal/cgi-bin/LJ/S2/FriendsPage.pm new file mode 100755 index 0000000..c473345 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/FriendsPage.pm @@ -0,0 +1,441 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub FriendsPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "FriendsPage"; + $p->{'view'} = "friends"; + $p->{'entries'} = []; + $p->{'friends'} = {}; + $p->{'friends_title'} = LJ::ehtml($u->{'friendspagetitle'}); + $p->{'filter_active'} = 0; + $p->{'filter_name'} = ""; + + my $sth; + my $user = $u->{'user'}; + + # see how often the remote user can reload this page. + # "friendsviewupdate" time determines what granularity time + # increments by for checking for new updates + my $nowtime = time(); + + # update delay specified by "friendsviewupdate" + my $newinterval = LJ::get_cap_min($remote, "friendsviewupdate") || 1; + + # when are we going to say page was last modified? back up to the + # most recent time in the past where $time % $interval == 0 + my $lastmod = $nowtime; + $lastmod -= $lastmod % $newinterval; + + # see if they have a previously cached copy of this page they + # might be able to still use. + if ($opts->{'header'}->{'If-Modified-Since'}) { + my $theirtime = LJ::http_to_time($opts->{'header'}->{'If-Modified-Since'}); + + # send back a 304 Not Modified if they say they've reloaded this + # document in the last $newinterval seconds: + unless ($theirtime < $lastmod) { + $opts->{'handler_return'} = 304; + return 1; + } + } + $opts->{'headers'}->{'Last-Modified'} = LJ::time_to_http($lastmod); + + my $get = $opts->{'getargs'}; + + my $ret; + + if ($get->{'mode'} eq "live") { + $ret .= "${user}'s friends: live!\n"; + $ret .= "\n"; + $ret .= " \n"; + $ret .= " \n"; + $ret .= "\n"; + return $ret; + } + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . "/friends"; + return 1; + } + + LJ::load_user_props($remote, "opt_nctalklinks", "opt_stylemine", "opt_imagelinks", "opt_ljcut_disable_friends"); + + # load options for image links + my ($maximgwidth, $maximgheight) = (undef, undef); + ($maximgwidth, $maximgheight) = ($1, $2) + if ($remote && $remote->{'userid'} == $u->{'userid'} && + $remote->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/); + + ## never have spiders index friends pages (change too much, and some + ## people might not want to be indexed) + $p->{'head_content'} .= LJ::robot_meta_tags(); + + my $itemshow = S2::get_property_value($opts->{'ctx'}, "page_friends_items")+0; + if ($itemshow < 1) { $itemshow = 20; } + elsif ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = ($LJ::MAX_SCROLLBACK_FRIENDS || 1000) - $itemshow; + if ($skip > $maxskip) { $skip = $maxskip; } + if ($skip < 0) { $skip = 0; } + my $itemload = $itemshow+$skip; + + my $filter; + my $group; + my $common_filter = 1; + + if (defined $get->{'filter'} && $remote && $remote->{'user'} eq $user) { + $filter = $get->{'filter'}; + $common_filter = 0; + $p->{'filter_active'} = 1; + $p->{'filter_name'} = ""; + } else { + if ($opts->{'pathextra'}) { + $group = $opts->{'pathextra'}; + $group =~ s!^/!!; + $group =~ s!/$!!; + if ($group) { $group = LJ::durl($group); $common_filter = 0; } + } + if ($group) { + $p->{'filter_active'} = 1; + $p->{'filter_name'} = LJ::ehtml($group); + } + my $grp = LJ::get_friend_group($u, { 'name' => $group || "Default View" }); + my $bit = $grp->{'groupnum'}; + my $public = $grp->{'is_public'}; + if ($bit && ($public || ($remote && $remote->{'user'} eq $user))) { + $filter = (1 << $bit); + } elsif ($group) { + $opts->{'badfriendgroup'} = 1; + return 1; + } + } + + if ($opts->{'view'} eq "friendsfriends") { + $p->{'friends_mode'} = "friendsfriends"; + } + + if ($get->{'mode'} eq "livecond") + { + ## load the itemids + my @items = LJ::get_friend_items({ + 'u' => $u, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => 1, + 'skip' => 0, + 'filter' => $filter, + 'common_filter' => $common_filter, + }); + my $first = @items ? $items[0]->{'itemid'} : 0; + + $ret .= "time = " . scalar(time()) . "
    "; + $opts->{'headers'}->{'Refresh'} = "30;URL=$LJ::SITEROOT/users/$user/friends?mode=livecond&lastitemid=$first"; + if ($get->{'lastitemid'} == $first) { + $ret .= "nothing new!"; + } else { + if ($get->{'lastitemid'}) { + $ret .= "New stuff!\n"; + $ret .= "\n"; + $opts->{'trusted_html'} = 1; + } else { + $ret .= "Friends Live! started."; + } + } + return $ret; + } + + ## load the itemids + my %friends; + my %friends_row; + my %idsbycluster; + my @items = LJ::get_friend_items({ + 'u' => $u, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'filter' => $filter, + 'common_filter' => $common_filter, + 'friends_u' => \%friends, + 'friends' => \%friends_row, + 'idsbycluster' => \%idsbycluster, + 'showtypes' => $get->{'show'}, + 'friendsoffriends' => $opts->{'view'} eq "friendsfriends", + 'dateformat' => 'S2', + }); + + while ($_ = each %friends) { + # we expect fgcolor/bgcolor to be in here later + $friends{$_}->{'fgcolor'} = $friends_row{$_}->{'fgcolor'} || '#ffffff'; + $friends{$_}->{'bgcolor'} = $friends_row{$_}->{'bgcolor'} || '#000000'; + } + + return $p unless %friends; + + ### load the log properties + my %logprops = (); # key is "$owneridOrZero $[j]itemid" + LJ::load_log_props2multi(\%idsbycluster, \%logprops); + + # load the text of the entries + my $logtext = LJ::get_logtext2multi(\%idsbycluster); + + # load tags on these entries + my $logtags = LJ::Tags::get_logtagsmulti(\%idsbycluster); + + my %posters; + { + my @posterids; + foreach my $item (@items) { + next if $friends{$item->{'posterid'}}; + push @posterids, $item->{'posterid'}; + } + LJ::load_userids_multiple([ map { $_ => \$posters{$_} } @posterids ]) + if @posterids; + } + + my %objs_of_picid; + my @userpic_load; + + my %lite; # posterid -> s2_UserLite + my $get_lite = sub { + my $id = shift; + return $lite{$id} if $lite{$id}; + return $lite{$id} = UserLite($posters{$id} || $friends{$id}); + }; + + my $eventnum = 0; + my $hiddenentries = 0; + ENTRY: + foreach my $item (@items) + { + my ($friendid, $posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(ownerid posterid itemid security alldatepart); + + my $fr = $friends{$friendid}; + $p->{'friends'}->{$fr->{'user'}} ||= Friend($fr); + + my $clusterid = $item->{'clusterid'}+0; + my $datakey = "$friendid $itemid"; + + my $replycount = $logprops{$datakey}->{'replycount'}; + my $subject = $logtext->{$datakey}->[0]; + my $text = $logtext->{$datakey}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + if ($LJ::UNICODE && $logprops{$datakey}->{'unknown8bit'}) { + LJ::item_toutf8($friends{$friendid}, \$subject, \$text, $logprops{$datakey}); + } + + my ($friend, $poster); + $friend = $poster = $friends{$friendid}->{'user'}; + + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid * 256 + $item->{'anum'}; + + my $stylemine = ""; + $stylemine .= "style=mine" if $remote && $remote->{'opt_stylemine'} && + $remote->{'userid'} != $friendid; + + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $logprops{$datakey}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($friends{$friendid}, $itemid, $item->{'anum'}, $stylemine), + 'maximgwidth' => $maximgwidth, + 'maximgheight' => $maximgheight, + 'ljcut_disable' => $remote->{'opt_ljcut_disable_friends'}, }); + LJ::expand_embedded($friends{$friendid}, $ditemid, $remote, \$text); + + my $userlite_poster = $get_lite->($posterid); + my $userlite_journal = $get_lite->($friendid); + + # get the poster user + my $po = $posters{$posterid} || $friends{$posterid}; + + # don't allow posts from suspended users + if ($po->{'statusvis'} eq 'S') { + $hiddenentries++; # Remember how many we've skipped for later + next ENTRY; + } + + # do the picture + my $picid = 0; + my $picu = undef; + if ($friendid != $posterid && S2::get_property_value($opts->{ctx}, 'use_shared_pic')) { + # using the community, the user wants to see shared pictures + $picu = $friends{$friendid}; + + # use shared pic for community + $picid = $friends{$friendid}->{defaultpicid}; + } else { + # we're using the poster for this picture + $picu = $po; + + # check if they specified one + $picid = LJ::get_picid_from_keyword($po, $logprops{$datakey}->{picture_keyword}) + if $logprops{$datakey}->{picture_keyword}; + + # fall back on the poster's default + $picid ||= $po->{defaultpicid}; + } + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $journalbase = LJ::journal_base($friends{$friendid}); + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine); + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine); + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($friends{$friendid}->{'opt_showtalklinks'} eq "Y" && + ! $logprops{$datakey}->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($logprops{$datakey}->{'hasscreened'} && $remote && + ($remote->{'user'} eq $fr->{'user'} || LJ::can_manage($remote, $fr))) ? 1 : 0, + }); + + my $moodthemeid = $u->{'opt_forcemoodtheme'} eq 'Y' ? + $u->{'moodthemeid'} : $friends{$friendid}->{'moodthemeid'}; + + my @taglist; + while (my ($kwid, $kw) = each %{$logtags->{$datakey} || {}}) { + push @taglist, Tag($friends{$friendid}, $kwid => $kw); + } + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + + if ($opts->{enable_tags_compatibility} && @taglist) { + $text .= LJ::S2::get_tags_text($opts->{ctx}, \@taglist); + } + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $logprops{$datakey}, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'new_day' => 0, # setup below + 'end_day' => 0, # setup below + 'userpic' => undef, + 'tags' => \@taglist, + 'permalink_url' => $permalink, + 'moodthemeid' => $moodthemeid, + }); + $entry->{'_ymd'} = join('-', map { $entry->{'time'}->{$_} } qw(year month day)); + + if ($picid && $picu) { + push @userpic_load, [ $picu, $picid ]; + push @{$objs_of_picid{$picid}}, \$entry->{'userpic'}; + } + + push @{$p->{'entries'}}, $entry; + $eventnum++; + + } # end while + + # set the new_day and end_day members. + if ($eventnum) { + for (my $i = 0; $i < $eventnum; $i++) { + my $entry = $p->{'entries'}->[$i]; + $entry->{'new_day'} = 1; + my $last = $i; + for (my $j = $i+1; $j < $eventnum; $j++) { + my $ej = $p->{'entries'}->[$j]; + if ($ej->{'_ymd'} eq $entry->{'_ymd'}) { + $last = $j; + } + } + $p->{'entries'}->[$last]->{'end_day'} = 1; + $i = $last; + } + } + + # load the pictures that were referenced, then retroactively populate + # the userpic fields of the Entries above + my %userpics; + LJ::load_userpics(\%userpics, \@userpic_load); + + foreach my $picid (keys %userpics) { + my $up = Image("$LJ::USERPIC_ROOT/$picid/$userpics{$picid}->{'userid'}", + $userpics{$picid}->{'width'}, + $userpics{$picid}->{'height'}); + foreach (@{$objs_of_picid{$picid}}) { $$_ = $up; } + } + + # make the skip links + my $nav = { + '_type' => 'RecentNav', + 'version' => 1, + 'skip' => $skip, + 'count' => $eventnum, + }; + + my $base = "$u->{'_journalbase'}/$opts->{'view'}"; + if ($group) { + $base .= "/" . LJ::eurl($group); + } + + # $linkfilter is distinct from $filter: if user has a default view, + # $filter is now set according to it but we don't want it to show in the links. + # $incfilter may be true even if $filter is 0: user may use filter=0 to turn + # off the default group + my $linkfilter = $get->{'filter'} + 0; + my $incfilter = defined $get->{'filter'}; + + # if we've skipped down, then we can skip back up + if ($skip) { + my %linkvars; + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + my $newskip = $skip - $itemshow; + if ($newskip > 0) { $linkvars{'skip'} = $newskip; } + else { $newskip = 0; } + $nav->{'forward_url'} = LJ::make_link($base, \%linkvars); + $nav->{'forward_skip'} = $newskip; + $nav->{'forward_count'} = $itemshow; + } + + ## unless we didn't even load as many as we were expecting on this + ## page, then there are more (unless there are exactly the number shown + ## on the page, but who cares about that) + # Must remember to count $hiddenentries or we'll have no skiplinks when > 1 + unless (($eventnum + $hiddenentries) != $itemshow || $skip == $maxskip) { + my %linkvars; + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + my $newskip = $skip + $itemshow; + $linkvars{'skip'} = $newskip; + $nav->{'backward_url'} = LJ::make_link($base, \%linkvars); + $nav->{'backward_skip'} = $newskip; + $nav->{'backward_count'} = $itemshow; + } + + $p->{'nav'} = $nav; + + if ($get->{'mode'} eq "framed") { + $p->{'head_content'} .= ""; + } + + return $p; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/MonthPage.pm b/livejournal/cgi-bin/LJ/S2/MonthPage.pm new file mode 100755 index 0000000..9fcd3ee --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/MonthPage.pm @@ -0,0 +1,232 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub MonthPage +{ + my ($u, $remote, $opts) = @_; + + my $get = $opts->{'getargs'}; + + my $p = Page($u, $opts); + $p->{'_type'} = "MonthPage"; + $p->{'view'} = "month"; + $p->{'days'} = []; + + my $ctx = $opts->{'ctx'}; + + my $dbcr = LJ::get_cluster_reader($u); + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + my ($year, $month); + if ($opts->{'pathextra'} =~ m!^/(\d\d\d\d)/(\d\d)\b!) { + ($year, $month) = ($1, $2); + } + + $opts->{'errors'} = []; + if ($month < 1 || $month > 12) { push @{$opts->{'errors'}}, "Invalid month: $month"; } + if ($year < 1970 || $year > 2038) { push @{$opts->{'errors'}}, "Invalid year: $year"; } + unless ($dbcr) { push @{$opts->{'errors'}}, "Database temporarily unavailable"; } + return if @{$opts->{'errors'}}; + + $p->{'date'} = Date($year, $month, 0); + + # load the log items + my $dateformat = "%Y %m %d %H %i %s %w"; # yyyy mm dd hh mm ss day_of_week + my $sth; + + my $secwhere = "AND l.security='public'"; + my $viewall = 0; + my $viewsome = 0; + if ($remote) { + + # do they have the viewall priv? + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "month: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (l.security='public' OR (l.security='usemask' AND l.allowmask & $gmask))" + if $gmask; + } + } + + $sth = $dbcr->prepare("SELECT l.jitemid, l.posterid, l.anum, l.day, ". + " DATE_FORMAT(l.eventtime, '$dateformat') AS 'alldatepart', ". + " l.replycount, l.security ". + "FROM log2 l ". + "WHERE l.journalid=? AND l.year=? AND l.month=? ". + "$secwhere LIMIT 2000"); + $sth->execute($u->{userid}, $year, $month); + + my @items; + push @items, $_ while $_ = $sth->fetchrow_hashref; + @items = sort { $a->{'alldatepart'} cmp $b->{'alldatepart'} } @items; + + my @itemids = map { $_->{'jitemid'} } @items; + + # load the log properties + my %logprops = (); + LJ::load_log_props2($u->{'userid'}, \@itemids, \%logprops); + my $lt = LJ::get_logtext2($u, @itemids); + + my (%pu, %pu_lite); # poster users; UserLite objects + foreach (@items) { + $pu{$_->{'posterid'}} = undef; + } + LJ::load_userids_multiple([map { $_, \$pu{$_} } keys %pu], [$u]); + $pu_lite{$_} = UserLite($pu{$_}) foreach keys %pu; + + my %day_entries; # -> [ Entry+ ] + + my $opt_text_subjects = S2::get_property_value($ctx, "page_month_textsubjects"); + my $userlite_journal = UserLite($u); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart, $replycount, $anum) = + map { $item->{$_} } qw(posterid jitemid security alldatepart replycount anum); + my $subject = $lt->{$itemid}->[0]; + my $day = $item->{'day'}; + + # don't show posts from suspended users + next unless $pu{$posterid}; + next ENTRY if $pu{$posterid}->{'statusvis'} eq 'S' && !$viewsome; + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + my $text; + LJ::item_toutf8($u, \$subject, \$text, $logprops{$itemid}); + } + + if ($opt_text_subjects) { + LJ::CleanHTML::clean_subject_all(\$subject); + } else { + LJ::CleanHTML::clean_subject(\$subject); + } + + my $ditemid = $itemid*256 + $anum; + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $logprops{$itemid}->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($logprops{$itemid}->{'hasscreened'} && $remote && + ($remote->{'user'} eq $u->{'user'} || LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $userpic = $p->{'journal'}->{'default_pic'}; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $pu_lite{$posterid}; + $userpic = Image_userpic($pu{$posterid}, 0, $logprops{$itemid}->{'picture_keyword'}); + } + + my $entry = Entry($u, { + 'subject' => $subject, + 'text' => "", + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $logprops{$itemid}, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + }); + + push @{$day_entries{$day}}, $entry; + } + + my $days_month = LJ::days_in_month($month, $year); + for my $day (1..$days_month) { + my $entries = $day_entries{$day} || []; + my $month_day = { + '_type' => 'MonthDay', + 'date' => Date($year, $month, $day), + 'day' => $day, + 'has_entries' => scalar @$entries > 0, + 'num_entries' => scalar @$entries, + 'url' => $journalbase . sprintf("/%04d/%02d/%02d/", $year, $month, $day), + 'entries' => $entries, + }; + push @{$p->{'days'}}, $month_day; + } + + # populate redirector + my $vhost = $opts->{'vhost'}; + $vhost =~ s/:.*//; + $p->{'redir'} = { + '_type' => "Redirector", + 'user' => $u->{'user'}, + 'vhost' => $vhost, + 'type' => 'monthview', + 'url' => "$LJ::SITEROOT/go.bml", + }; + + # figure out what months have been posted into + my $nowval = $year*12 + $month; + + $p->{'months'} = []; + + my $days = LJ::get_daycounts($u, $remote) || []; + my $lastmo; + foreach my $day (@$days) { + my ($oy, $om) = ($day->[0], $day->[1]); + my $mo = "$oy-$om"; + next if $mo eq $lastmo; + $lastmo = $mo; + + my $date = Date($oy, $om, 0); + my $url = $journalbase . sprintf("/%04d/%02d/", $oy, $om); + push @{$p->{'months'}}, { + '_type' => "MonthEntryInfo", + 'date' => $date, + 'url' => $url, + 'redir_key' => sprintf("%04d%02d", $oy, $om), + }; + + my $val = $oy*12+$om; + if ($val < $nowval) { + $p->{'prev_url'} = $url; + $p->{'prev_date'} = $date; + } + if ($val > $nowval && ! $p->{'next_date'}) { + $p->{'next_url'} = $url; + $p->{'next_date'} = $date; + } + } + + return $p; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/RecentPage.pm b/livejournal/cgi-bin/LJ/S2/RecentPage.pm new file mode 100755 index 0000000..a0c8e92 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/RecentPage.pm @@ -0,0 +1,240 @@ +use strict; +package LJ::S2; + +sub RecentPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "RecentPage"; + $p->{'view'} = "recent"; + $p->{'entries'} = []; + + my $user = $u->{'user'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}); + return; + } + + LJ::load_user_props($remote, "opt_nctalklinks", "opt_ljcut_disable_lastn"); + + my $get = $opts->{'getargs'}; + + if ($opts->{'pathextra'}) { + $opts->{'badargs'} = 1; + return 1; + } + + if ($u->{'opt_blockrobots'} || $get->{'skip'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + $p->{'head_content'} .= qq{\n} + if LJ::OpenID::server_enabled(); + + my $itemshow = S2::get_property_value($opts->{'ctx'}, "page_recent_items")+0; + if ($itemshow < 1) { $itemshow = 20; } + elsif ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = $LJ::MAX_HINTS_LASTN-$itemshow; + if ($skip < 0) { $skip = 0; } + if ($skip > $maxskip) { $skip = $maxskip; } + + # do they want to view all entries, regardless of security? + my $viewall = 0; + my $viewsome = 0; + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "lastn: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + ## load the itemids + my @itemids; + my $err; + my @items = LJ::get_recent_items({ + 'clusterid' => $u->{'clusterid'}, + 'clustersource' => 'slave', + 'viewall' => $viewall, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'tagids' => $opts->{tagids}, + 'itemids' => \@itemids, + 'dateformat' => 'S2', + 'order' => ($u->{'journaltype'} eq "C" || $u->{'journaltype'} eq "Y") # community or syndicated + ? "logtime" : "", + 'err' => \$err, + }); + + die $err if $err; + + ### load the log properties + my %logprops = (); + my $logtext; + LJ::load_log_props2($u->{'userid'}, \@itemids, \%logprops); + $logtext = LJ::get_logtext2($u, @itemids); + + my $lastdate = ""; + my $itemnum = 0; + my $lastentry = undef; + + my (%apu, %apu_lite); # alt poster users; UserLite objects + foreach (@items) { + next unless $_->{'posterid'} != $u->{'userid'}; + $apu{$_->{'posterid'}} = undef; + } + if (%apu) { + LJ::load_userids_multiple([map { $_, \$apu{$_} } keys %apu], [$u]); + $apu_lite{$_} = UserLite($apu{$_}) foreach keys %apu; + } + + # load tags + my $idsbyc = { $u->{clusterid} => [ ] }; + push @{$idsbyc->{$u->{clusterid}}}, [ $u->{userid}, $_->{itemid} ] + foreach @items; + my $tags = LJ::Tags::get_logtagsmulti($idsbyc); + + my $userlite_journal = UserLite($u); + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(posterid itemid security alldatepart); + + my $replycount = $logprops{$itemid}->{'replycount'}; + my $subject = $logtext->{$itemid}->[0]; + my $text = $logtext->{$itemid}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $text =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + # don't show posts from suspended users unless the user doing the viewing says to (and is allowed) + next ENTRY if $apu{$posterid} && $apu{$posterid}->{'statusvis'} eq 'S' && !$viewsome; + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$subject, \$text, $logprops{$itemid}); + } + + my $date = substr($alldatepart, 0, 10); + my $new_day = 0; + if ($date ne $lastdate) { + $new_day = 1; + $lastdate = $date; + $lastentry->{'end_day'} = 1 if $lastentry; + } + + $itemnum++; + LJ::CleanHTML::clean_subject(\$subject) if $subject; + + my $ditemid = $itemid * 256 + $item->{'anum'}; + LJ::CleanHTML::clean_event(\$text, { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $item->{'anum'}), + 'ljcut_disable' => $remote->{"opt_ljcut_disable_lastn"}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$text); + + my @taglist; + while (my ($kwid, $kw) = each %{$tags->{"$u->{userid} $itemid"} || {}}) { + push @taglist, Tag($u, $kwid => $kw); + } + @taglist = sort { $a->{name} cmp $b->{name} } @taglist; + + if ($opts->{enable_tags_compatibility} && @taglist) { + $text .= LJ::S2::get_tags_text($opts->{ctx}, \@taglist); + } + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = $permalink; + $readurl .= "?$nc" if $nc; + my $posturl = $permalink . "?mode=reply"; + + my $comments = CommentInfo({ + 'read_url' => $readurl, + 'post_url' => $posturl, + 'count' => $replycount, + 'maxcomments' => ($replycount >= LJ::get_cap($u, 'maxcomments')) ? 1 : 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! $logprops{$itemid}->{'opt_nocomments'}) ? 1 : 0, + 'screened' => ($logprops{$itemid}->{'hasscreened'} && ($remote->{'user'} eq $u->{'user'}|| LJ::can_manage($remote, $u))) ? 1 : 0, + }); + + my $userlite_poster = $userlite_journal; + my $pu = $u; + if ($u->{'userid'} != $posterid) { + $userlite_poster = $apu_lite{$posterid} or die "No apu_lite for posterid=$posterid"; + $pu = $apu{$posterid}; + } + my $userpic = Image_userpic($pu, 0, $logprops{$itemid}->{'picture_keyword'}); + + my $entry = $lastentry = Entry($u, { + 'subject' => $subject, + 'text' => $text, + 'dateparts' => $alldatepart, + 'security' => $security, + 'props' => $logprops{$itemid}, + 'itemid' => $ditemid, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'comments' => $comments, + 'new_day' => $new_day, + 'end_day' => 0, # if true, set later + 'tags' => \@taglist, + 'userpic' => $userpic, + 'permalink_url' => $permalink, + }); + + push @{$p->{'entries'}}, $entry; + + } # end huge while loop + + # mark last entry as closing. + $p->{'entries'}->[-1]->{'end_day'} = 1 if $itemnum; + + #### make the skip links + my $nav = { + '_type' => 'RecentNav', + 'version' => 1, + 'skip' => $skip, + 'count' => $itemnum, + }; + + # if we've skipped down, then we can skip back up + if ($skip) { + my $newskip = $skip - $itemshow; + $newskip = 0 if $newskip <= 0; + $nav->{'forward_skip'} = $newskip; + $nav->{'forward_url'} = LJ::make_link("$p->{base_url}/", { skip => ($newskip || ""), tag => (LJ::eurl($get->{tag}) || "") }); + $nav->{'forward_count'} = $itemshow; + } + + # unless we didn't even load as many as we were expecting on this + # page, then there are more (unless there are exactly the number shown + # on the page, but who cares about that) + unless ($itemnum != $itemshow) { + $nav->{'backward_count'} = $itemshow; + if ($skip == $maxskip) { + my $date_slashes = $lastdate; # "yyyy mm dd"; + $date_slashes =~ s! !/!g; + $nav->{'backward_url'} = "$p->{'base_url'}/day/$date_slashes"; + } else { + my $newskip = $skip + $itemshow; + $nav->{'backward_url'} = LJ::make_link("$p->{'base_url'}/", { skip => ($newskip || ""), tag => (LJ::eurl($get->{tag}) || "") }); + $nav->{'backward_skip'} = $newskip; + } + } + + $p->{'nav'} = $nav; + return $p; +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/ReplyPage.pm b/livejournal/cgi-bin/LJ/S2/ReplyPage.pm new file mode 100755 index 0000000..72a2c83 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/ReplyPage.pm @@ -0,0 +1,139 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub ReplyPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "ReplyPage"; + $p->{'view'} = "reply"; + + my $get = $opts->{'getargs'}; + + my ($entry, $s2entry) = EntryPage_entry($u, $remote, $opts); + return if $opts->{'suspendeduser'}; + return if $opts->{'handler_return'}; + my $ditemid = $entry->{'itemid'}*256 + $entry->{'anum'}; + $p->{'head_content'} .= $LJ::COMMON_CODE{'chalresp_js'}; + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + + $p->{'entry'} = $s2entry; + + # setup the replying item + my $replyto = $s2entry; + my $parpost; + if ($get->{'replyto'}) { + my $re_talkid = int($get->{'replyto'} >> 8); + my $re_anum = $get->{'replyto'} % 256; + unless ($re_anum == $entry->{'anum'}) { + $opts->{'handler_return'} = 404; + return; + } + + my $sql = "SELECT jtalkid, posterid, state, datepost FROM talk2 ". + "WHERE journalid=$u->{'userid'} AND jtalkid=$re_talkid ". + "AND nodetype='L' AND nodeid=$entry->{'jitemid'}"; + foreach my $pass (1, 2) { + my $db = $pass == 1 ? LJ::get_cluster_reader($u) : LJ::get_cluster_def_reader($u); + $parpost = $db->selectrow_hashref($sql); + last if $parpost; + } + unless ($parpost and $parpost->{'state'} ne 'D') { + $opts->{'handler_return'} = 404; + return; + } + if ($parpost->{'state'} eq 'S' && !LJ::Talk::can_unscreen($remote, $u, $s2entry->{'poster'}->{'username'}, undef)) { + $opts->{'handler_return'} = 403; + return; + } + if ($parpost->{'state'} eq 'F') { + # frozen comment, no replies allowed + + # FIXME: eventually have S2 ErrorPage to handle this and similar + # For now, this hack will work; this error is pretty uncommon anyway. + $opts->{status} = "403 Forbidden"; + return "

    This thread has been frozen; no more replies are allowed.

    "; + } + + my $tt = LJ::get_talktext2($u, $re_talkid); + $parpost->{'subject'} = $tt->{$re_talkid}->[0]; + $parpost->{'body'} = $tt->{$re_talkid}->[1]; + $parpost->{'props'} = + LJ::load_talk_props2($u, [ $re_talkid ])->{$re_talkid} || {}; + + if($LJ::UNICODE && $parpost->{'props'}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$parpost->{'subject'}, \$parpost->{'body'}, {}); + } + + LJ::CleanHTML::clean_comment(\$parpost->{'body'}, + { 'preformatted' => $parpost->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$parpost->{posterid} }); + + my $datetime = DateTime_unix(LJ::mysqldate_to_time($parpost->{'datepost'})); + + my ($s2poster, $pu); + my $comment_userpic; + if ($parpost->{'posterid'}) { + $pu = LJ::load_userid($parpost->{'posterid'}); + return $opts->{handler_return} = 403 if $pu->{statusvis} eq 'S'; # do not show comments by suspended users + $s2poster = UserLite($pu); + + # FIXME: this is a little heavy: + $comment_userpic = Image_userpic($pu, 0, $parpost->{'props'}->{'picture_keyword'}); + } + + my $dtalkid = $re_talkid * 256 + $entry->{'anum'}; + $replyto = { + '_type' => 'EntryLite', + 'subject' => LJ::ehtml($parpost->{'subject'}), + 'text' => $parpost->{'body'}, + 'userpic' => $comment_userpic, + 'poster' => $s2poster, + 'journal' => $s2entry->{'journal'}, + 'metadata' => {}, + 'permalink_url' => $u->{'_journalbase'} . "/$ditemid.html?view=$dtalkid#t$dtalkid", + 'depth' => 1, + 'time' => $datetime, + }; + } + + $p->{'replyto'} = $replyto; + + $p->{'form'} = { + '_type' => "ReplyForm", + '_remote' => $remote, + '_u' => $u, + '_ditemid' => $ditemid, + '_parpost' => $parpost, + }; + + return $p; +} + +package S2::Builtin::LJ; + +sub ReplyForm__print +{ + my ($ctx, $form) = @_; + my $remote = $form->{'_remote'}; + my $u = $form->{'_u'}; + my $parpost = $form->{'_parpost'}; + my $parent = $parpost ? $parpost->{'jtalkid'} : 0; + + $S2::pout->(LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $u, + 'parpost' => $parpost, + 'replyto' => $parent, + 'ditemid' => $form->{'_ditemid'}, + 'form' => $form })); + +} + +1; diff --git a/livejournal/cgi-bin/LJ/S2/YearPage.pm b/livejournal/cgi-bin/LJ/S2/YearPage.pm new file mode 100755 index 0000000..f5ab597 --- /dev/null +++ b/livejournal/cgi-bin/LJ/S2/YearPage.pm @@ -0,0 +1,181 @@ +#!/usr/bin/perl +# + +use strict; +package LJ::S2; + +sub YearPage +{ + my ($u, $remote, $opts) = @_; + + my $p = Page($u, $opts); + $p->{'_type'} = "YearPage"; + $p->{'view'} = "archive"; + + my $user = $u->{'user'}; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/calendar" . $opts->{'pathextra'}; + return 1; + } + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $p->{'head_content'} .= '\n"; + } + + my $get = $opts->{'getargs'}; + + my $count = LJ::S2::get_journal_day_counts($p); + my @years = sort { $a <=> $b } keys %$count; + my $maxyear = @years ? $years[-1] : undef; + my $year = $get->{'year'}; # old form was /users//calendar?year=1999 + + # but the new form is purtier: */calendar/2001 + if (! $year && $opts->{'pathextra'} =~ m!^/(\d\d\d\d)/?\b!) { + $year = $1; + } + + # else... default to the year they last posted. + $year ||= $maxyear; + + $p->{'year'} = $year; + $p->{'years'} = []; + foreach (@years) { + push @{$p->{'years'}}, YearYear($_, "$p->{'base_url'}/$_/", $_ == $p->{'year'}); + } + + $p->{'months'} = []; + + for my $month (1..12) { + push @{$p->{'months'}}, YearMonth($p, { + 'month' => $month, + 'year' => $year, + }); + } + + return $p; +} + +sub YearMonth { + my ($p, $calmon) = @_; + + my ($month, $year) = ($calmon->{'month'}, $calmon->{'year'}); + $calmon->{'_type'} = 'YearMonth'; + $calmon->{'weeks'} = []; + $calmon->{'url'} = sprintf("$p->{'_u'}->{'_journalbase'}/$year/%02d/", $month); + + my $count = LJ::S2::get_journal_day_counts($p); + my $has_entries = $count->{$year} && $count->{$year}->{$month} ? 1 : 0; + $calmon->{'has_entries'} = $has_entries; + + my $start_monday = 0; # FIXME: check some property to see if weeks start on monday + my $week = undef; + + my $flush_week = sub { + my $end_month = shift; + return unless $week; + push @{$calmon->{'weeks'}}, $week; + if ($end_month) { + $week->{'post_empty'} = + 7 - $week->{'pre_empty'} - @{$week->{'days'}}; + } + $week = undef; + }; + + my $push_day = sub { + my $d = shift; + unless ($week) { + my $leading = $d->{'date'}->{'_dayofweek'}-1; + if ($start_monday) { + $leading = 6 if --$leading < 0; + } + $week = { + '_type' => 'YearWeek', + 'days' => [], + 'pre_empty' => $leading, + 'post_empty' => 0, + }; + } + push @{$week->{'days'}}, $d; + if ($week->{'pre_empty'} + @{$week->{'days'}} == 7) { + $flush_week->(); + my $size = scalar @{$calmon->{'weeks'}}; + } + }; + + my $day_of_week = LJ::day_of_week($year, $month, 1); + + my $daysinmonth = LJ::days_in_month($month, $year); + + for my $day (1..$daysinmonth) { + # so we don't auto-vivify years/months + my $daycount = $has_entries ? $count->{$year}->{$month}->{$day} : 0; + my $d = YearDay($p->{'_u'}, $year, $month, $day, + $daycount, $day_of_week+1); + $push_day->($d); + $day_of_week = ($day_of_week + 1) % 7; + } + $flush_week->(1); # end of month flag + + my $nowval = $year * 12 + $month; + + # determine the most recent month with posts that is older than + # the current time $month/$year. gives calendars the ability to + # provide smart next/previous links. + my $maxbefore; + while (my ($iy, $h) = each %$count) { + next if $iy > $year; + while (my $im = each %$h) { + next if $im >= $month; + my $val = $iy * 12 + $im; + if ($val < $nowval && $val > $maxbefore) { + $maxbefore = $val; + $calmon->{'prev_url'} = $p->{'_u'}->{'_journalbase'} . sprintf("/%04d/%02d/", $iy, $im); + $calmon->{'prev_date'} = Date($iy, $im, 0); + } + } + } + + # same, except inverse: next month after current time with posts + my $minafter; + while (my ($iy, $h) = each %$count) { + next if $iy < $year; + while (my $im = each %$h) { + next if $im <= $month; + my $val = $iy * 12 + $im; + if ($val > $nowval && (!$minafter || $val < $minafter)) { + $minafter = $val; + $calmon->{'next_url'} = $p->{'_u'}->{'_journalbase'} . sprintf("/%04d/%02d/", $iy, $im); + $calmon->{'next_date'} = Date($iy, $im, 0); + } + } + } + return $calmon; +} + +sub YearYear { + my ($year, $url, $displayed) = @_; + return { '_type' => "YearYear", + 'year' => $year, 'url' => $url, 'displayed' => $displayed }; +} + +sub YearDay { + my ($u, $year, $month, $day, $count, $dow) = @_; + my $d = { + '_type' => 'YearDay', + 'day' => $day, + 'date' => Date($year, $month, $day, $dow), + 'num_entries' => $count + }; + if ($count) { + $d->{'url'} = sprintf("$u->{'_journalbase'}/$year/%02d/%02d/", + $month, $day); + } + return $d; +} + +1; diff --git a/livejournal/cgi-bin/LJ/SixDegrees.pm b/livejournal/cgi-bin/LJ/SixDegrees.pm new file mode 100755 index 0000000..06d1ed5 --- /dev/null +++ b/livejournal/cgi-bin/LJ/SixDegrees.pm @@ -0,0 +1,207 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +require 'ljlib.pl'; + +package LJ::SixDegrees; + +sub find_path +{ + my ($fu, $tu, $timeout) = @_; + return () unless $fu && $tu; + return () unless $fu->{journaltype} eq "P" && $tu->{journaltype} eq "P"; + + $LJ::SixDegrees::MEMC_EXPIRE ||= 86400; + + my $cache = {}; # keys for links in/out -> listrefs, userids -> $u's, "notes" -> why pass/fail + $cache->{$fu->{userid}} = $fu; + $cache->{$tu->{userid}} = $tu; + + my $memkey = [ $fu->{'userid'}, "6dpath:$fu->{userid}:$tu->{userid}" ]; + my $exp = 3600; + my $path = LJ::MemCache::get($memkey); + unless ($path) { + $path = _find_path_helper($fu, $tu, $timeout, $cache); + LJ::MemCache::set($memkey, $path, $exp) if $path; + } + + return () unless $path; + return map { $cache->{$_} || LJ::load_userid($_) } @$path; +} + +# returns arrayref of userids in path on success (even if empty), or undef on timeout +sub _find_path_helper +{ + my ($fu, $tu, $timeout, $cache) = @_; + + my $time_start = time(); + + # user is themselves (one element in path) + return [$fu->{userid}] if $fu->{'userid'} == $tu->{'userid'}; + + # from user befriends to user (two elements in path + my $fu_friends = links_out($fu, $cache); + if (intersect($fu_friends, [ $tu->{'userid'} ])) { + $cache->{'note'} = "2 way path"; + return [$fu->{userid}, $tu->{userid}]; + } + + # try to find a three-way path (fu has a friend who lists tu as a friend) + my $tu_friendofs = links_in($tu, $cache); + if (my $via = intersect($fu_friends, $tu_friendofs)) { + $cache->{'note'} = "3 way path"; + return [$fu->{userid}, $via, $tu->{userid}]; + } + + # try to find four-way path by expanding fu's friends' friends, + # one at a time, looking for intersections. along the way, + # keep track of all friendsfriends, then we can walk along + # tu's friendofs-friendofs looking for intersections there later + # if necessary. + my %friendsfriends = (); # uid -> 1 + my %friends = (); # uid -> 1 + my $tried = 0; + foreach my $fid (@$fu_friends) { + $friends{$fid} = 1; + next if ++$tried > 100; + if (time() > $time_start + $timeout) { + $cache->{'note'} = "timeout"; + return undef; + } + + # a group of one friend's ($fid's) friends + my $ffset = links_out($fid, $cache); + + # see if $fid's friends intersect $tu's friendofs + if (intersect($ffset, [ $tu->{userid} ])) { + $cache->{'note'} = "returning via fid's friends to tu"; + return [$fu->{userid}, $fid, $tu->{userid}]; + } + + # see if $fid's friends intersect $tu's friendofs + if (my $via = intersect($ffset, $tu_friendofs)) { + $cache->{'note'} = "returning via fid's friends to tu's friendofs"; + return [$fu->{userid}, $fid, $via, $tu->{userid}]; + } + + # otherwise, track who's a friends-of-friend, and the friend we're on + # so we don't try doing the same search later + foreach (@$ffset) { + $friendsfriends{$_} ||= $fid; + } + } + + # try to find a path by looking at tu's friendof-friendofs + $tried = 0; + foreach my $foid (@$tu_friendofs) { + last if ++$tried > 100; + if (time() > $time_start + $timeout) { + $cache->{'note'} = "timeout"; + return undef; + } + + if (my $fid = $friendsfriends{$foid}) { + $cache->{'note'} = "returning via friend-of-friend is friend of target"; + return [$fu->{userid}, $fid, $foid, $tu->{userid}]; + } + + my $foset = links_in($foid, $cache); + + # see if we can go from $tu to $foid's friends. (now, this shouldn't normally + # happen, but we limit the links_in/out to 1000, so there's a possibility + # we stopped during the friend-of-friend search above) + if (intersect([ $fu->{userid} ], $foset)) { + $cache->{'note'} = "returning via friend-of-friend but discovered backwards"; + return [$fu->{userid}, $foid, $tu->{userid}]; + } + + # otherwise, see if any of this group of friendof-friendofs are a friend-friend + foreach my $uid (@$foset) { + if (my $fid = $friends{$uid}) { + $cache->{'note'} = "returning via friend intersection with friendof-friendof"; + return [$fu->{userid}, $fid, $foid, $tu->{userid}]; + } + if (my $fid = $friendsfriends{$uid}) { + $cache->{'note'} = "returning via friend-of-friend intersection with friendof-friendof"; + return [$fu->{userid}, $fid, $uid, $foid, $tu->{userid}]; + } + } + } + + return []; # no path, but not a timeout (as opposed to undef above) +} + +sub intersect +{ + my ($list_a, $list_b) = @_; + return 0 unless ref $list_a && ref $list_b; + my %temp; + $temp{$_} = 1 foreach @$list_a; + foreach (@$list_b) { + return $_ if $temp{$_}; + } + return 0; +} + +sub link_fetch +{ + my ($uid, $key, $sql, $cache) = @_; + + # first try from the pre-load/already-done per-process cache + return $cache->{$key} if defined $cache->{$key}; + + # then try memcache + my $memkey = [$uid, $key]; + my $listref = LJ::MemCache::get($memkey); + if (ref $listref eq "ARRAY") { + $cache->{$key} = $listref; + return $listref; + } + + # finally fall back to the database. + my $dbr = LJ::get_db_reader(); + $listref = $dbr->selectcol_arrayref($sql, undef, $uid) || []; + + # get the $u's for everybody (bleh, since we need to know if they're a community + # or not) + my @need_load; # userids necessary to load + foreach my $uid (@$listref) { + push @need_load, $uid unless $cache->{$uid}; + } + if (@need_load) { + LJ::load_userids_multiple([ map { $_, \$cache->{$_} } @need_load ]); + } + + # filter out communities/deleted/suspended/etc + my @clean_list; # visible users, not communities + foreach my $uid (@$listref) { + my $u = $cache->{$uid}; + next unless $u && $u->{'statusvis'} eq "V" && $u->{'journaltype'} eq "P"; + push @clean_list, $uid; + } + + $listref = \@clean_list; + LJ::MemCache::set($memkey, $listref, $LJ::SixDegrees::MEMC_EXPIRE); + $cache->{$key} = $listref; + return $listref; +} + +sub links_out +{ + my $uid = LJ::want_userid($_[0]); + return link_fetch($uid, "6dlo:$uid", + "SELECT friendid FROM friends WHERE userid=? LIMIT 1000", + $_[1]); +} + +sub links_in +{ + my $uid = LJ::want_userid($_[0]); + return link_fetch($uid, "6dli:$uid", + "SELECT userid FROM friends WHERE friendid=? LIMIT 1000", + $_[1]); +} + +1; diff --git a/livejournal/cgi-bin/LJ/SpellCheck.pm b/livejournal/cgi-bin/LJ/SpellCheck.pm new file mode 100755 index 0000000..16cedf7 --- /dev/null +++ b/livejournal/cgi-bin/LJ/SpellCheck.pm @@ -0,0 +1,158 @@ +#!/usr/bin/perl +# +# LJ::SpellCheck class +# See perldoc documentation at the end of this file. +# +# ------------------------------------------------------------------------- +# +# This package is released under the LGPL (GNU Library General Public License) +# +# A copy of the license has been included with the software as LGPL.txt. +# If not, the license is available at: +# http://www.gnu.org/copyleft/library.txt +# +# ------------------------------------------------------------------------- + + +package LJ::SpellCheck; + +use strict; +use FileHandle; +use IPC::Open2; +use POSIX ":sys_wait_h"; + +use vars qw($VERSION); +$VERSION = '1.0'; + +# Good spellcommand values: +# ispell -a -h (default) +# /usr/local/bin/aspell pipe -H --sug-mode=fast --ignore-case + +sub new { + my ($class, $args) = @_; + my $self = {}; + bless $self, ref $class || $class; + + $self->{'command'} = $args->{'spellcommand'} || "ispell -a -h"; + $self->{'color'} = $args->{'color'} || "#FF0000"; + return $self; +} + +# This function takes a block of text to spell-check and returns HTML +# to show suggesting correction, if any. If the return from this +# function is empty, then there were no misspellings found. + +sub check_html { + my $self = shift; + my $journal = shift; + + my $iread = new FileHandle; + my $iwrite = new FileHandle; + my $ierr = new FileHandle; + my $pid; + + # work-around for mod_perl + my $tie_stdin = tied *STDIN; + untie *STDIN if $tie_stdin; + + $iwrite->autoflush(1); + + $pid = open2($iread, $iwrite, $self->{'command'}) || die "spell process failed"; + die "Couldn't find spell checker\n" unless $pid; + my $banner = <$iread>; + die "banner=$banner\n" unless ($banner =~ /^@\(\#\)/); + print $iwrite "!\n"; + + my $output = ""; + my $footnotes = ""; + + my ($srcidx, $lineidx, $mscnt, $other_bad); + $lineidx = 1; + $mscnt = 0; + foreach my $inline (split(/\n/, $$journal)) { + $srcidx = 0; + chomp($inline); + print $iwrite "^$inline\n"; + + my $idata; + do { + $idata = <$iread>; + chomp($idata); + + if ($idata =~ /^& /) { + $idata =~ s/^& (\S+) (\d+) (\d+): //; + $mscnt++; + my ($word, $sugcount, $ofs) = ($1, $2, $3); + $ofs -= 1; # because ispell reports "1" for first character + + $output .= substr($inline, $srcidx, $ofs-$srcidx); + $output .= "{'color'}\">$word"; + + $footnotes .= "{'color'}>$word$idata"; + + $srcidx = $ofs + length($word); + } elsif ($idata =~ /^\# /) { + $other_bad = 1; + $idata =~ /^\# (\S+) (\d+)/; + my ($word, $ofs) = ($1, $2); + $ofs -= 1; # because ispell reports "1" for first character + $output .= substr($inline, $srcidx, $ofs-$srcidx); + $output .= "{'color'}\">$word"; + $srcidx = $ofs + length($word); + } + } while ($idata ne ""); + $output .= substr($inline, $srcidx, length($inline)-$srcidx) . "
    \n"; + $lineidx++; + } + + $iread->close; + $iwrite->close; + + $pid = waitpid($pid, 0); + + # return mod_perl to previous state, though not necessary? + tie *STDIN, $tie_stdin if $tie_stdin; + + return (($mscnt || $other_bad) ? "$output

    Suggestions:$footnotes
    " : ""); +} + +1; +__END__ + +=head1 NAME + +LJ::SpellCheck - let users check spelling on web pages + +=head1 SYNOPSIS + + use LJ::SpellCheck; + my $s = new LJ::SpellCheck { 'spellcommand' => 'ispell -a -h', + 'color' => '#ff0000', + }; + + my $text = "Lets mispell thigns!"; + my $correction = $s->check_html(\$text); + if ($correction) { + print $correction; # contains a ton of HTML + } else { + print "No spelling problems."; + } + +=head1 DESCRIPTION + +The object constructor takes a 'spellcommand' argument. This has to be some ispell compatible program, like aspell. Optionally, it also takes a color to highlight mispelled words. + +The only method on the object is check_html, which takes a reference to the text to check and returns a bunch of HTML highlighting misspellings and showing suggestions. If it returns nothing, then there no misspellings found. + +=head1 BUGS + +Sometimes the opened spell process hangs and eats up tons of CPU. Fixed now, though... I think. + +check_html returns HTML we like. You may not. :) + +=head1 AUTHORS + +Evan Martin, evan@livejournal.com +Brad Fitzpatrick, bradfitz@livejournal.com + +=cut diff --git a/livejournal/cgi-bin/LJ/TagGenerator.pm b/livejournal/cgi-bin/LJ/TagGenerator.pm new file mode 100755 index 0000000..10fc6ee --- /dev/null +++ b/livejournal/cgi-bin/LJ/TagGenerator.pm @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +package LJ::TagGenerator; +use Carp; + +my %_tag_groups = ( + ":common" => [qw(a b body br code col colgroup dd del div dl dt em + font form frame frameset h1 h2 h3 h4 h5 h6 head hr + html i img input li nobr ol option p pre table td th + tr Tr TR tt title u ul)], + ":html4" => [qw(a abbr acronym address applet area b base basefont + bdo big blockquote body br button caption center cite + code col colgroup dd del dfn dir div dl dt em fieldset + font form frame frameset h1 h2 h3 h4 h5 h6 head hr html + i iframe img input ins isindex kbd label legend li link + map menu meta noframes noscript object ol optgroup option + p param pre q s samp script select small span strike + strong style sub sup table tbody td textarea tfoot th + thead title tr Tr TR tt u ul var)], + ); + +sub import { + shift; # ditch the class name + my %args = @_; + my $tags = $args{tags} || $_tag_groups{":common"}; + ref $tags and UNIVERSAL::isa($tags, "ARRAY") + or croak "Invalid tags argument"; + my $prefix = $args{prefix} || ""; + my $suffix = $args{suffix} || ""; + my $uppercase = $args{uppercase} || 1; + my $package = (caller)[0]; + while (my $tag = shift @$tags) { + if (exists $_tag_groups{$tag}) { + push @$tags, @{$_tag_groups{$tag}}; + next; + } + if ($uppercase) { + $tag = uc $tag; + } + # print "aliasing __$tag to ${package}::$prefix$tag$suffix\n"; + *{"${package}::$prefix$tag$suffix"} = \&{"__$tag"}; + } +} + +sub AUTOLOAD { + $AUTOLOAD =~ /::__([^:]*)$/ or croak "No such method $AUTOLOAD"; + my $tagname = lc $1; + my $sub = "sub $AUTOLOAD " . q{ + { + my $result = '<__TAGNAME__'; + if (ref($_[0]) && ref($_[0]) eq 'HASH') { + my $attrs = shift; + while (my ($key, $value) = each %$attrs) { + $key =~ s/^\-//; + $key =~ s/_/-/g; + $result .= (defined $value ? qq( $key="$value") : qq( $key)); + } + } + if (@_) { + $result .= ">" . join("", @_) . ""; + } else { + $result .= " />"; + } + return $result; + } + }; + $sub =~ s/__TAGNAME__/$tagname/g; + eval $sub; + goto &$AUTOLOAD; +} + +1; diff --git a/livejournal/cgi-bin/LJ/TextMessage.pm b/livejournal/cgi-bin/LJ/TextMessage.pm new file mode 100755 index 0000000..154773e --- /dev/null +++ b/livejournal/cgi-bin/LJ/TextMessage.pm @@ -0,0 +1,2164 @@ +#!/usr/bin/perl +# +# LJ::TextMessage class +# See perldoc documentation at the end of this file. +# +# ------------------------------------------------------------------------- +# +# This package is released under the LGPL (GNU Library General Public License) +# +# A copy of the license has been included with the software as LGPL.txt. +# If not, the license is available at: +# http://www.gnu.org/copyleft/library.txt +# +# ------------------------------------------------------------------------- +# + +package LJ::TextMessage; + +use URI::Escape; +use LWP::UserAgent; +use MIME::Lite; + +use strict; +use vars qw($VERSION $SENDMAIL %providers); + +$VERSION = '1.5.3'; + +# default path to sendmail, if none other specified. we should probably +# use something more perl-ish and less unix-specific, but whateva' + +$SENDMAIL = "/usr/sbin/sendmail -t"; + +%providers = ( + + 'email' => { + 'name' => 'Other', + 'notes' => 'If your provider isn\'t supported directly, enter the email address that sends you a text message in phone number field. To be safe, the entire message is sent in the body of the message, and the length limit is really short. We\'d prefer you give us information about your provider so we can support it directly.', + 'fromlimit' => 15, + 'msglimit' => 100, + 'totlimit' => 100, + }, + + 'a1telekom' => { + 'name' => 'A1/Telekom Austria', + 'notes' => 'Enter your phone number. Messages are sent via web gateway. Number must start 43664, 43676, 43699, 43650, 43660, 38640, 38591 or 42379', + 'fromlimit' => 20, + 'msglimit' => 420, + 'totlimit' => 420, + }, + + 'airtouch' => { + 'name' => 'Verizon Wireless (formerly Airtouch)', + 'notes' => 'Enter your phone number. Messages are sent to number@airtouchpaging.com. This is ONLY for former AirTouch customers. Verizon Wireless customers should use Verizon Wireless instead.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + 'aliant' => { + 'name' => 'Alianet (NBTel, MTT, NewTel, and Island Tel)', + 'notes' => 'Enter your phone number. Message is sent to number@wirefree.informe.ca', + 'fromlimit' => 11, + 'msglimit' => 140, + 'totlimit' => 140, + }, + 'alltel' => { + 'name' => 'Alltel', + 'notes' => 'Enter your phone number. Goes to number@message.alltel.com.', + 'fromlimit' => 50, + 'msglimit' => 116, + 'totlimit' => 116, + }, + + 'ameritech' => { + 'name' => 'Ameritech (ACSWireless)', + 'notes' => 'Enter your phone number. Goes to number@paging.acswireless.com', + 'fromlimit' => 120, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'arch' => { + 'name' => 'Arch Wireless', + 'notes' => 'Enter your phone number. Sent via http://www.arch.com/message/ (assumes blank PIN)', + 'fromlimit' => 15, + 'msglimit' => 240, + 'totlimit' => 240, + }, + + 'aubykddi' => { + 'name' => 'AU by KDDI', + 'notes' => 'Enter your phone number. Goes to username@ezweb.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 10000, + 'totlimit' => 10000, + }, + + 'bellmobilityca' => { + 'name' => 'Bell Mobility Canada', + 'notes' => 'Enter your phone number, including the 1 prefix. Goes to number@txt.bellmobility.ca', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'beemail' => { + 'name' => 'BeeLine GSM', + 'notes' => 'Enter your phone number. Goes to number@sms.beemail.ru', + 'fromlimit' => 50, + 'msglimit' => 255, + 'totlimit' => 255, + }, + + 'bellsouth' => { + 'name' => 'Bellsouth', + 'notes' => 'Enter your phone number. Goes to number@bellsouth.cl', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'bellsouthmobility' => { + 'name' => 'BellSouth Mobility', + 'notes' => 'Enter your phone number. Goes to number@blsdcs.net', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'blueskyfrog' => { + 'name' => 'Blue Sky Frog', + 'notes' => 'Enter your phone number. Goes to number@blueskyfrog.com', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'boost' => { + 'name' => 'Boost', + 'notes' => 'Enter your phone number. Goes to number@myboostmobile.com', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'cellularonedobson' => { + 'name' => 'CellularOne (Dobson)', + 'notes' => 'Enter your phone number. Goes to number@mobile.celloneusa.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'cellularonewest' => { + 'name' => 'CellularOne West', + 'notes' => 'Enter your phone number. Goes to number@mycellone.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'centennial' => { + 'name' => 'Centennial Wireless', + 'notes' => 'Enter your phone number. Sent via http://www.centennialwireless.com', + 'fromlimit' => 10, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'cingular' => + { + 'name' => 'Cingular', + 'notes' => 'Enter your phone number. Goes to number@mobile.mycingular.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'cingularblue' => { + 'name' => 'Cingular Blue (formerly AT&T Wireless)', + 'notes' => 'Enter your phone number. Goes to number@mmode.com', + 'fromlimit' => 50, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'claro' => + { + 'name' => 'Claro', + 'notes' => 'Enter your phone number. Goes to number@clarotorpedo.com.br', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'comviq' => + { + 'name' => 'Comviq', + 'notes' => 'Enter your phone number. Goes to number@sms.comviq.se', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'csouth1' => { + 'name' => 'Cellular South', + 'notes' => 'Enter your phone number. Messages are sent to number@csouth1.com', + 'fromlimit' => 50, + 'msglimit' => 155, + 'totlimit' => 155, + }, + + 'dutchtone' => { + 'name' => 'Dutchtone/Orange-NL', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.orange.nl', + 'fromlimit' => 15, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'edgewireless' => { + 'name' => 'Edge Wireless', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.edgewireless.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'emt' => { + 'name' => 'Estonia Mobile Telefon', + 'notes' => 'Enter your phone number. Sent via webform.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'eplus' => { + 'name' => 'EPlus', + 'notes' => 'Enter your phone number. Goes to number@smsmail.eplus.de.', + 'fromlimit' => 20, + 'msglimit' => 480, + 'totlimit' => 480, + }, + + 'fidoca' => { + 'name' => 'Fido Canada', + 'notes' => 'Enter your phone number. Goes to number@fido.ca.', + 'fromlimit' => 15, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'goldentelecom' => { + 'name' => 'Golden Telecom', + 'notes' => 'Enter your phone number or nickname. Messages are sent to number@sms.goldentele.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ideacellular' => { + 'name' => 'Idea Cellular', + 'notes' => 'Enter your phone number. Messages are sent to number@ideacellular.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'imcingular' => + { + 'name' => 'Cingular IM Plus/Bellsouth IPS', + 'notes' => 'Enter 8 digit PIN or user name. Goes to @imcingular.com', + 'fromlimit' => 100, + 'msglimit' => 16000, + 'totlimit' => 16000, + }, + + 'imcingular-cell' => + { + 'name' => 'Cingular IM Plus/Bellsouth IPS Cellphones', + 'notes' => 'Enter phone number. Goes to @mobile.mycingular.com', + 'fromlimit' => 100, + 'msglimit' => 16000, + 'totlimit' => 16000, + }, + + 'kyivstar' => { + 'name' => 'Kyivstar', + 'notes' => 'Sent by addressing the message to number@sms.kyivstar.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'lmt' => { + 'name' => 'LMT', + 'notes' => 'Sent by addressing the message to number@smsmail.lmt.lv', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'meteor' => { + 'name' => 'Meteor', + 'notes' => 'Enter your phone number. Goes to number@sms.mymeteor.ie', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'megafonmoscow' => { + 'name' => 'Megafon Moscow', + 'notes' => 'Enter your phone number. Sent via web form', + 'fromlimit' => 20, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'metrocall' => { + 'name' => 'Metrocall Pager', + 'notes' => '10-digit phone number. Goes to number@page.metrocall.com', + 'fromlimit' => 120, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'metropcs' => { + 'name' => 'Metro PCS', + 'notes' => '10-digit phone number. Goes to number@mymetropcs.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'movistar' => { + 'name' => 'Telefonica Movistar', + 'notes' => '10-digit phone number. Goes to number@movistar.net', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'mtsmobility' => { + 'name' => 'Manitoba Telecom Systems', + 'notes' => '10-digit phone number. Goes to @text.mtsmobility.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'mtsprimtel' => { + 'name' => 'MTS Primtel', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobileone' => { + 'name' => 'MobileOne', + 'notes' => 'Enter your phone number. Goes to number@m1.com.sg', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobilfone' => { + 'name' => 'Mobilfone', + 'notes' => 'Enter your phone number. Goes to number@page.mobilfone.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'mobility' => { + 'name' => 'Mobility Bermuda', + 'notes' => 'Enter your phone number. Goes to number@ml.bm', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + 'netcom' => { + 'name' => 'Netcom', + 'notes' => 'Enter your phone number. Goes to number@sms.netcom.no', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'nextel' => { + 'name' => 'Nextel', + 'notes' => '10-digit phone number. Goes to 10digits@messaging.nextel.com. Note: do not use dashes in your phone number.', + 'fromlimit' => 50, + 'msglimit' => 126, + 'totlimit' => 126, + }, + + 'nwgsm-megafon' => { + 'name' => 'North-WestGSM Megafon', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'npiwireless' => { + 'name' => 'NPI Wireless', + 'notes' => 'Enter your phone number. Goes to number@npiwireless.com.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ntc' => { + 'name' => 'NTC', + 'notes' => 'Enter your phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'ntelos' => { + 'name' => 'NTELOS', + 'notes' => '10-digit phone number. Goes to 10digits@pcs.ntelos.com.', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'o2' => { + 'name' => 'O2 (formerly BTCellnet)', + 'notes' => 'Enter O2 username - must be enabled first at http://www.o2.co.uk. Goes to username@o2.co.uk.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'o2mmail' => { + 'name' => 'O2 M-mail (formerly BTCellnet)', + 'notes' => 'Enter phone number, omitting intial zero - must be enabled first by sending an SMS saying "ON" to phone number "212". Goes to +44[number]@mmail.co.uk.', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'optus' => { + 'name' => 'Optus', + 'notes' => 'Enter your phone number. Goes to @optusmobile.com.au', + 'fromlimit' => 20, + 'msglimit' => 114, + 'totlimit' => 114, + }, + + 'orange' => { + 'name' => 'Orange', + 'notes' => 'Enter your phone number. Goes to @orange.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'oskar' => { + 'name' => 'Oskar', + 'notes' => 'Enter your phone number. Goes to @mujoskar.cz', + 'fromlimit' => 20, + 'msglimit' => 320, + 'totlimit' => 320, + }, + + 'pacbell' => { + 'name' => 'Pacific Bell Cingular', + 'notes' => '10-digit phone number. Goes to @mobile.mycingular.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'pagenet' => { + 'name' => 'Pagenet', + 'notes' => '10-digit phone number (or gateway and pager number separated by a period). Goes to number@pagenet.net.', + 'fromlimit' => 20, + 'msglimit' => 220, + 'totlimit' => 240, + }, + + 'pcom' => { + 'name' => 'Personal Communication (Sonet)', + 'notes' => 'Enter your phone number. Goes to sms@pcom.ru with your number in the subject line.', + 'fromlimit' => 20, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'pcsrogers' => { + 'name' => 'PCS Rogers', + 'notes' => '10-digit phone number. Sent via web gateway.', + 'fromlimit' => 20, + 'msglimit' => 125, + 'totlimit' => 125, + }, + + 'phonehouse' => { + 'name' => 'The Phone House', + 'notes' => '10-digit phone number. Goes to number@sms.phonehouse.de.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'plusgsm' => { + 'name' => 'Plus GSM Poland', + 'notes' => '10-digit phone number. Goes to number@text.plusgsm.pl.', + 'fromlimit' => 20, + 'msglimit' => 620, + 'totlimit' => 620, + }, + + 'pscwireless' => { + 'name' => 'PSC Wireless', + 'notes' => 'Enter your phone number. Goes to number@sms.pscel.com', + 'fromlimit' => 20, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'primtel' => { + 'name' => 'Primtel', + 'notes' => 'Enter your phone number. Goes to number@sms.primtel.ru', + 'fromlimit' => 20, + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'ptel' => { + 'name' => 'Powertel', + 'notes' => '10-digit phone number. Goes to number@ptel.net', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'qualcomm' => { + 'name' => 'Qualcomm', + 'notes' => 'Enter your username. Goes to username@pager.qualcomm.com', + 'fromlimit' => 20, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'qwest' => { + 'name' => 'Qwest', + 'notes' => '10-digit phone number. Goes to @qwestmp.com', + 'fromlimit' => 14, + 'msglimit' => 100, + 'totlimit' => 100, + }, + + 'safaricom' => { + 'name' => 'Safaricom', + 'notes' => 'Goes to @safaricomsms.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'satelindogsm' => { + 'name' => 'Satelindo GSM', + 'notes' => 'Goes to @satelindogsm.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'scs900' => { + 'name' => 'SCS-900', + 'notes' => 'Goes to @scs-900.ru', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'simplefreedom' => { + 'name' => 'Simple Freedom', + 'notes' => 'Goes to @text.simplefreedom.net', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'skytelalpha' => { + 'name' => 'Skytel - Alphanumeric', + 'notes' => 'Enter your 7-digit pin number as your number and your message will be mailed to pin@skytel.com', + 'fromlimit' => 15, + 'msglimit' => 240, + 'totlimit' => 240, + }, + + 'smarttelecom' => { + 'name' => 'Smart Telecom', + 'notes' => 'Enter your phone number. Goes to @mysmart.mymobile.ph', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'smartsgsm' => { + 'name' => 'Smarts GSM', + 'notes' => 'Enter your phone number. Sent via http://www.samara-gsm.ru/scripts/smsgate.exe', + 'fromlimit' => 11, + 'msglimit' => 70, + 'totlimit' => 70, + }, + + 'southernlinc' => { + 'name' => 'Southern Linc', + 'notes' => 'Enter your 10-digit phone number. Goes to @page.southernlinc.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'sprintpcs' => { + 'name' => 'Sprint PCS', + 'notes' => 'Enter your 10-digit phone number. Goes to @messaging.sprintpcs.com', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'sprintpcs-shortmail' => { + 'name' => 'Sprint PCS - Short Mail', + 'notes' => 'Enter your phone number. Goes to @sprintpcs.com', + 'fromlimit' => 15, + 'msglimit' => 1000, + 'totlimit' => 1000, + }, + + 'suncom' => { + 'name' => 'SunCom', + 'notes' => 'Enter your number. Email will be sent to number@tms.suncom.com.', + 'fromlimit' => 18, + 'msglimit' => 110, + 'totlimit' => 110, + }, + + 'surewest' => { + 'name' => 'SureWest Communications', + 'notes' => 'Enter your phone number. Message will be sent to number@mobile.surewest.com', + 'fromlimit' => 20, + 'msglimit' => 200, + 'totlimit' => 200, + }, + + 'swisscom' => { + 'name' => 'SwissCom Mobile', + 'notes' => 'Enter your phone number. Message will be sent to number@bluewin.ch', + 'fromlimit' => 20, + 'msglimit' => 10000, + 'totlimit' => 10000, + }, + + 'tele2' => { + 'name' => 'Tele2 Latvia', + 'notes' => '10-digit phone number. Goes to number@sms.tele2.lv.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telenor' => { + 'name' => 'Telenor', + 'notes' => '10-digit phone number. Goes to number@mobilpost.no.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telia' => { + 'name' => 'Telia Denmark', + 'notes' => '8-digit phone number. Goes to number@gsm1800.telia.dk.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'telus' => { + 'name' => 'Telus Mobility', + 'notes' => '10-digit phone number. Goes to 10digits@msg.telus.com.', + 'fromlimit' => 30, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'timnet' => { + 'name' => 'TIM', + 'notes' => '10-digit phone number. Goes to number@timnet.com.', + 'fromlimit' => 30, + 'msglimit' => 350, + 'totlimit' => 350, + }, + + 'tmobilegermany' => { + 'name' => 'T-Mobile Germany', + 'notes' => 'Enter your number. Email will be sent to number@T-D1-SMS.de', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileholland' => { + 'name' => 'T-Mobile Netherlands', + 'notes' => 'Send "EMAIL ON" to 555 from your phone, then enter your number starting with 316. Email will be sent to number@gin.nl', + 'fromlimit' => 15, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileuk' => { + 'name' => 'T-Mobile UK', + 'notes' => 'Messages are sent to number@t-mobile.uk.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'tmobileusa' => { + 'name' => 'T-Mobile USA', + 'notes' => 'Messages are sent to number@tmomail.net', + 'fromlimit' => 30, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'umc' => { + 'name' => 'UMC', + 'notes' => 'Sent by addressing the message to number@sms.umc.com.ua', + 'fromlimit' => 10, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'uscc' => { + 'name' => 'US Cellular', + 'notes' => 'Enter a 10 digit USCC Phone Number. Messages are sent via http://usc.ztango.com/uscwmss', + 'msglimit' => 150, + 'totlimit' => 150, + }, + + 'unicel' => { + 'name' => 'Unicel', + 'notes' => 'Sent by addressing the message to number@utext.com', + 'fromlimit' => 10, + 'msglimit' => 120, + 'totlimit' => 120, + }, + + 'vzw' => { + 'name' => 'Verizon Wireless', + 'notes' => 'Enter your 10-digit phone number. Messages are sent via email to number@vtext.com.', + 'fromlimit' => 34, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'vzw-myairmail' => { + 'name' => 'Verizon Wireless (myairmail.com)', + 'notes' => 'Enter your phone number. Messages are sent via to number@myairmail.com.', + 'fromlimit' => 34, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'vessotel' => { + 'name' => 'Vessotel', + 'notes' => 'Enter your phone number. Messages are sent to roumer@pager.irkutsk.ru.', + 'fromlimit' => 20, + 'msglimit' => 800, + 'totlimit' => 800, + }, + + 'virginmobileusa' => { + 'name' => 'Virgin Mobile USA', + 'notes' => 'Enter your phone number. Messages are sent to number@vmobl.com.', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonees' => { + 'name' => 'Vodafone Spain', + 'notes' => 'Enter your username. Messages are sent to username@vodafone.es', + 'fromlimit' => 20, + 'msglimit' => 90, + 'totlimit' => 90, + }, + + 'vodafoneit' => { + 'name' => 'Vodafone Italy', + 'notes' => 'Enter your phone number. Messages are sent to number@sms.vodafone.it', + 'fromlimit' => 20, + 'msglimit' => 132, + 'totlimit' => 132, + }, + + 'vodafonejp-c' => { + 'name' => 'Vodafone Japan (Toukai/Central)', + 'notes' => 'Enter your phone number. Messages are sent to number@c.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-d' => { + 'name' => 'Vodafone Japan (Hokkaido)', + 'notes' => 'Enter your phone number. Messages are sent to number@d.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-h' => { + 'name' => 'Vodafone Japan (Touhoku/Niigata/North)', + 'notes' => 'Enter your phone number. Messages are sent to number@h.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-k' => { + 'name' => 'Vodafone Japan (Kansai/West -- including Osaka)', + 'notes' => 'Enter your phone number. Messages are sent to number@k.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-n' => { + 'name' => 'Vodafone Japan (Chuugoku/Western)', + 'notes' => 'Enter your phone number. Messages are sent to number@n.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-q' => { + 'name' => 'Vodafone Japan (Kyuushu/Okinawa)', + 'notes' => 'Enter your phone number. Messages are sent to number@q.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-r' => { + 'name' => 'Vodafone Japan (Hokuriko/Central North)', + 'notes' => 'Enter your phone number. Messages are sent to number@r.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-s' => { + 'name' => 'Vodafone Japan (Shikoku)', + 'notes' => 'Enter your phone number. Messages are sent to number@s.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafonejp-t' => { + 'name' => 'Vodafone Japan (Kanto/Koushin/East -- including Tokyo)', + 'notes' => 'Enter your phone number. Messages are sent to number@t.vodafone.ne.jp', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'vodafoneuk' => { + 'name' => 'Vodafone UK', + 'notes' => 'Enter your username. Messages are sent to username@vodafone.net', + 'fromlimit' => 20, + 'msglimit' => 70, + 'totlimit' => 90, + }, + + 'voicestream' => { + 'name' => 'Voicestream', + 'notes' => 'Enter your 10-digit phone number. Message is sent via the email gateway, since they changed their web gateway and we have not gotten it working with the new one yet.', + 'fromlimit' => 15, + 'msglimit' => 140, + 'totlimit' => 140, + }, + + 'weblinkwireless' => { + 'name' => 'Weblink Wireless', + 'notes' => 'Enter your phone number. Goes to @airmessage.net', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'wellcom' => { + 'name' => 'WellCom', + 'notes' => 'Enter your phone number. Goes to @sms.welcome2well.com', + 'fromlimit' => 20, + 'msglimit' => 160, + 'totlimit' => 160, + }, + + 'wyndtell' => { + 'name' => 'WyndTell', + 'notes' => 'Enter username/phone number. Goes to @wyndtell.com', + 'fromlimit' => 20, + 'msglimit' => 480, + 'totlimit' => 500, + }, + +); + +sub providers +{ + return sort { lc($providers{$a}->{'name'}) cmp lc($providers{$b}->{'name'}) } keys %providers; +} + +sub provider_info +{ + my $provider = remap(shift); + return { %{$providers{$provider}} }; +} + +sub remap { + my $provider = shift; + return "o2mmail" if $provider eq "btcellnet"; + return "voicestream" if $provider eq "voicestream2"; + return "tmobileusa" if $provider eq "tmomail"; + return "suncom" if $provider eq "tms-suncom"; + return "cingular" if $provider eq "cingular-acs"; + return "cingular" if $provider eq "cingular-texas"; + return "cingularblue" if $provider eq "att"; + return "aliant" if $provider eq "nbtel"; + return $provider; +} + +sub new { + my ($class, $args) = @_; + my $self = {}; + bless $self, ref $class || $class; + + $self->init($args); + return $self; +} + +sub init { + my $self = shift; + my $args = shift; + $self->{'sendmail'} = $args->{'mailcommand'} || $SENDMAIL; + $self->{'provider'} = remap($args->{'provider'}); + $self->{'number'} = $args->{'number'}; + $self->{'smtp'} = $args->{'smtp'}; +} + +sub send +{ + my $self = shift; + my $msg = shift; # hashref: 'from', 'message' + my $errors = shift; # arrayref + my $provider = $self->{'provider'}; + + unless ($provider) { + push @$errors, "No provider specified in object constructor."; + return; + } + + unless ($msg) { + push @$errors, "No message specified in object constructor."; + return; + } + unless ($self) { + push @$errors, "No self specified in object constructor."; + return; + } + unless ($self->{'sendmail'}) { + push @$errors, "No sendmail specified in object constructor."; + return; + } + unless ($self->{'provider'}) { + push @$errors, "No provider specified in object constructor."; + return; + } + unless ($self->{'number'}) { + push @$errors, "No number specified in object constructor."; + return; + } + + my $prov = $providers{$provider}; + + ## + ## truncate 'from' if it's too long for the given provider + ## + + if (length($msg->{'from'}) > $prov->{'fromlimit'}) { + $msg->{'from'} = substr($msg->{'from'}, 0, $prov->{'fromlimit'}); + } + + ## + ## now send the message, based on the provider + ## + + if ($provider eq "email") + { + send_mail($self, { + 'to' => $self->{'number'}, + 'from' => "LiveJournal", + 'body' => "(f:$msg->{'from'})$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "a1telekom") + { + $self->{'number'} =~ /(\d\d\d\d\d)(\d+)/; + post_webform("http://www.a1.net/sms_check_tr/1,2855,14-813-html-de,00.html", { + 'an1' => $1, + 'an2' => $2, + 'msg' => $msg->{'message'}, + 'userEmail' => $msg->{'from'}, + },$errors); + } + + elsif ($provider eq "airtouch") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sender.airtouchpaging.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "aliant") + { + send_mail($self, { + 'to' => "$self->{'number'}\@wirefree.informe.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "alltel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@message.alltel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ameritech") + { + send_mail($self, { + 'to' => "$self->{'number'}\@paging.acswireless.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "arch") + { + send_mail($self, { + 'to' => "$self->{'number'}\@archwireless.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "aubykddi") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ezweb.ne.jp", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "beemail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.beemail.ru", + 'body' => "$msg->{'from'} - $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellmobilityca") + { + send_mail($self, { + 'to' => "$self->{'number'}\@txt.bellmobility.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellsouth") + { + send_mail($self, { + 'to' => "$self->{'number'}\@bellsouth.cl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "bellsouthmobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@blsdcs.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + + elsif ($provider eq "blueskyfrog") + { + send_mail($self, { + 'to' => "$self->{'number'}\@blueskyfrog.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "boost") + { + send_mail($self, { + 'to' => "$self->{'number'}\@myboostmobile.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "cellularonedobson") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.celloneusa.com", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "cellularonewest") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mycellone.net", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "centennial") + { + post_webform("http://www.centennialwireless.com/home/sms.php", { + 'deviceid' => $self->{'number'}, + 'mess' => $msg->{'message'}, + 'yournumber' => $msg->{'from'}, + },$errors); + } + + elsif ($provider eq "cingular") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "cingularblue") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mmode.com", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "claro") + { + send_mail($self, { + 'to' => "$self->{'number'}\@clarotorpedo.com.br", + 'from' => "$msg->{'from'}", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "comviq") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.comviq.se", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "csouth1") { + send_mail($self, { + 'to' => "$self->{'number'}\@csouth1.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "dutchtone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.orange.nl", + 'body' => "$msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "edgewireless") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.edgewireless.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "emt") + { + post_webform("http://www.emt.ee/wwwmain", { + 'actionId' => "send", + 'phoneNo' => $self->{'number'}, + 'userEmail' => $msg->{'from'}, + 'message' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "eplus") + { + send_mail($self, { + 'to' => "$self->{'number'}\@smsmail.eplus.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "fidoca" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@fido.ca", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "goldentelecom") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.goldentele.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "ideacellular") { + send_mail($self, { + 'to' => "$self->{'number'}\@ideacellular.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "imcingular") + { + send_mail($self, { + 'to' => "$self->{'number'}\@imcingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "imcingular-cell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "kyivstar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.kyivstar.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "lmt") + { + send_mail($self, { + 'to' => "$self->{'number'}\@smsmail.lmt.lv", + + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "megafonmoscow") + { + my $prefix = substr($self->{'number'},0,4); + post_webform("http://www.megafonmoscow.ru/misc/sms2", { + 'prefix' => "$prefix", + 'message' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "meteor") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.mymeteor.ie", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "metrocall") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.metrocall.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "metropcs") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mymetropcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mobileone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@m1.com.sg", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mobilfone") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.mobilfone.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "movistar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@movistar.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mtsmobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.mtsmobility.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "mtsprimtel") + { + post_webform("http://80.83.224.19/sms/sent_sakh.shtml", { + 'ref' => 8, + 'txtAddr' => $self->{'number'}, + 'textSM' => "(f:".$msg->{'from'}.")".$msg->{'message'}, + },$errors); + } + + elsif ($provider eq "mobility") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ml.bm", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "netcom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.netcom.no", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "nextel") # Nextel + { + send_mail($self, { + 'to' => "$self->{'number'}\@messaging.nextel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "nwgsm-megafon") + { + post_webform("http://www-old.nwgsm.ru:8101/sendsms.htm", { + "tll" => $self->{'number'}, + "txt" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "npiwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@npiwireless.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ntc") + { + my $prefix; + my $number; + if ($self->{'number'} =~ /^74232(\d\d\d\d\d\d)/) { + $prefix = "74232"; + $number = $1; + } + if ($self->{'number'} =~ /^(7902\d\d\d)(\d\d\d\d)/) { + $prefix = $1; + $number = $2; + } + post_webform("http://www.ntconline.ru/data/pages/sms/send.php", { + 'sent' => 1, + 'prefix' => $prefix, + 'number' => $number, + 'lang' => "eng", + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "ntelos") # NTELOS PCS + { + send_mail($self, { + 'to' => "$self->{'number'}\@pcs.ntelos.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "o2") + { + send_mail($self, { + 'to' => $self->{'number'}."\@o2.co.uk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "o2mmail") + { + send_mail($self, { + 'to' => "+44".$self->{'number'}."\@mmail.co.uk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "optus") + { + send_mail($self, { + 'to' => "$self->{'number'}\@optusmobile.com.au", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "orange") + { + send_mail($self, { + 'to' => "$self->{'number'}\@orange.net", + 'from' => "$msg->{'from'}", + 'subject' => "$msg->{'message'}", + 'body' => "Textmessage in subject line.", + },$errors); + } + + elsif ($provider eq "oskar") + { + send_mail($self, { + 'to' => "$self->{'number'}\@musoskar.cz", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pacbell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.mycingular.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pagenet") + { + send_mail($self, { + 'to' => "$self->{'number'}\@pagenet.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pcom") + { + send_mail($self, { + 'to' => "sms\@pcom.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "$self->{'number'}", + },$errors); + } + + elsif ($provider eq "pcsrogers") + { + $self->{'number'} =~ /(\d\d\d)(\d\d\d)(\d\d\d\d)/; + post_webform("http://216.129.53.44:8080/cgi-bin/send_sm_rogers.new", { + "area" => $1, + "num1" => $2, + "num2" => $3, + "text" => "From $msg->{'from'}: $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "phonehouse") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.phonehouse.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "plusgsm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.plusgsm.pl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "pscwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.pscel.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "primtel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.primtel.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "ptel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@ptel.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "qualcomm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@pager.qualcomm.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "qwest") + { + send_mail($self, { + 'to' => "(f:$msg->{'from'})$self->{'number'}\@qwestmp.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "safaricom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@safaricomsms.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "satelindogsm") + { + send_mail($self, { + 'to' => "$self->{'number'}\@satelindogsm.com", + 'from' => $LJ::BOGUS_EMAIL, + 'body' => "From: $msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "scs900") + { + send_mail($self, { + 'to' => "$self->{'number'}\@scs-900.ru", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "simplefreedom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@text.simplefreedom.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "skytelalpha") + { + send_mail($self, { + 'to' => "$self->{'number'}\@skytel.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "smarttelecom") { + send_mail($self, { + 'to' => "$self->{'number'}\@mysmart.mymobile.ph", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "smartsgsm") + { + post_webform("http://www.samara-gsm.ru/scripts/smsgate.exe/send", { + "phone" => $self->{'number'}, + "sendtext" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "southernlinc") + { + send_mail($self, { + 'to' => "$self->{'number'}\@page.southernlinc.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "sprintpcs") # SprintPCS + { + send_mail($self, { + 'to' => "(f:$msg->{'from'}) $self->{'number'}\@messaging.sprintpcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "sprintpcs-shortmail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sprintpcs.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "suncom") { + send_mail($self, { + 'to' => "$self->{'number'}\@tms.suncom.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "surewest") { + send_mail($self, { + 'to' => "$self->{'number'}\@mobile.surewest.com", + 'body' => "(f:$msg->{'from'}) $msg->{'message'}", + },$errors); + } + + elsif ($provider eq "swisscom") { + send_mail($self, { + 'to' => "$self->{'number'}\@bluewin.ch", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tele2") { + post_webform("http://sms.tele2.lv/cgi-bin/send_sm_t2.cgi", { + "msisdn" => $self->{'number'}, + "text" => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "telenor") { + send_mail($self, { + 'to' => "$self->{'number'}\@mobilpost.no", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "telia") { + send_mail($self, { + 'to' => "$self->{'number'}\@gsm1800.telia.dk", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "telus") # Telus Mobility + { + send_mail($self, { + 'to' => "$self->{'number'}\@msg.telus.com", + 'from' => "$msg->{'from'}", + 'body' => "(f:$msg->{'from'})$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "timnet") + { + send_mail($self, { + 'to' => "$self->{'number'}\@timnet.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileaustria") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.t-mobile.at", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobilegermany") + { + send_mail($self, { + 'to' => "$self->{'number'}\@T-D1-SMS.de", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileholland") + { + send_mail($self, { + 'to' => "$self->{'number'}\@gin.nl", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "tmobileuk") + { + send_mail($self, { + 'to' => "$self->{'number'}\@t-mobile.uk.net", + 'subject' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'from' => "LJ", + },$errors); + } + + elsif ($provider eq "tmobileusa") + { + send_mail($self, { + 'to' => "$self->{'number'}\@tmomail.net", + 'subject' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'from' => "LJ", + },$errors); + } + + elsif ($provider eq "umc") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.umc.com.ua", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "uscc") # U.S Cellular + { + post_webform("http://usc.ztango.com/uscwmss", { + "addresses" => $self->{'number'}, + "MSG" => "$msg->{'from'}\n$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "unicel") + { + send_mail($self, { + 'to' => "$self->{'number'}\@utext.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vzw") # Verizon Wireless + { + send_mail($self, { + 'to' => "$self->{'number'}\@vtext.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "LJ", + },$errors); + } + + elsif ($provider eq "vzw-myairmail") + { + send_mail($self, { + 'to' => "$self->{'number'}\@myairmail.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vessotel" ) + { + send_mail($self, { + 'to' => "roumer\@pager.irkutsk.ru", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + 'subject' => "$self->{'number'}", + },$errors); + } + + elsif ($provider eq "virginmobileusa" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@vmobl.com", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "vodafonees") { + send_mail($self, { + 'to' => "$self->{'number'}\@vodafone.es", + 'from' => $msg->{'from'}, + 'subject' => $msg->{'message'}, + 'body' => "Your LiveJournal Text Message has been placed into the subject line." + },$errors); + } + + elsif ($provider eq "vodafoneit") { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.vodafone.it", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-c") { + send_mail($self, { + 'to' => "$self->{'number'}\@c.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-d") { + send_mail($self, { + 'to' => "$self->{'number'}\@d.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-h") { + send_mail($self, { + 'to' => "$self->{'number'}\@h.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-k") { + send_mail($self, { + 'to' => "$self->{'number'}\@k.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-n") { + send_mail($self, { + 'to' => "$self->{'number'}\@n.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-q") { + send_mail($self, { + 'to' => "$self->{'number'}\@q.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-r") { + send_mail($self, { + 'to' => "$self->{'number'}\@r.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-s") { + send_mail($self, { + 'to' => "$self->{'number'}\@s.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafonejp-t") { + send_mail($self, { + 'to' => "$self->{'number'}\@t.vodafone.ne.jp", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "vodafoneuk") { + send_mail($self, { + 'to' => "$self->{'number'}\@vodafone.net", + 'from' => $msg->{'from'}, + 'subject' => $msg->{'message'}, + 'body' => "Your LiveJournal Text Message has been placed into the subject line." + },$errors); + } + + elsif ($provider eq "voicestream" ) + { + send_mail($self, { + 'to' => "$self->{'number'}\@voicestream.net", + 'from' => "$msg->{'from'}", + 'body' => "$msg->{'message'}", + },$errors); + } + + elsif ($provider eq "weblinkwireless") + { + send_mail($self, { + 'to' => "$self->{'number'}\@airmessage.net", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "wellcom") + { + send_mail($self, { + 'to' => "$self->{'number'}\@sms.welcome2well.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + elsif ($provider eq "wyndtell") + { + send_mail($self, { + 'to' => "$self->{'number'}\@wyndtell.com", + 'from' => $msg->{'from'}, + 'body' => $msg->{'message'}, + },$errors); + } + + else { + push @$errors, "Tried to send a message to an unknown or unsupported provider."; + } +} + +sub post_webform +{ + my ($url, $postvars, $errors) = @_; + + ### we're going to POST to provider's page + my $ua = new LWP::UserAgent; + $ua->agent("Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"); + $ua->timeout(5); + + my $req = new HTTP::Request POST => $url; + $req->content_type('application/x-www-form-urlencoded'); + $req->content(request_string($postvars)); + + # Pass request to the user agent and get a response back + my $res = $ua->request($req); + if ($res->is_success || $res->is_redirect) { + return; + } else { + push @$errors, "There was some error contacting the user's text messaging service via its web gateway. The message was most likely not sent."; + return; + } +} + +sub send_mail +{ + my $self = shift; + my $opt = shift; + my $errors = shift; + my $status; + unless ($opt->{'to'}) { + push @$errors, "To not defined in provider description."; + return; + } + unless ($opt->{'body'}) { + push @$errors, "Data not defined in provider description."; + return; + } + $opt->{'from'} =~ s,[!\\/\@#],_,g; # I haven't escaped too much/too little, have I? + my $msg = new MIME::Lite ('From' => $opt->{'from'} . "\@$LJ::DOMAIN", + 'To' => $opt->{'to'}, + 'Subject' => $opt->{'subject'}, + 'Data' => $opt->{'body'}); + if ($self->{'smtp'}) { + $status = eval { $msg->send_by_smtp($self->{'smtp'}, Timeout => 10) && 1; }; + } else { + $status = eval { $msg->send_by_sendmail($self->{'sendmail'}) && 1; }; + } + unless ($status) { + if ($@ =~ /(bad address syntax|syntax illegal)/i) { + push @$errors, "Recipient has an invalid email address on file."; + } else { + push @$errors, "There may have been a problem sending your message through the email gateway. The error reported was: $@"; + } + } + return $status; +} + +sub request_string +{ + my ($vars) = shift; + my $req = ""; + foreach (sort keys %{$vars}) + { + my $val = uri_escape($vars->{$_},"\+\=\&"); + $val =~ s/ /+/g; + $req .= "&" if $req; + $req .= "$_=$val"; + } + return $req; +} + +1; +__END__ +# Below is the stub of documentation for your module. You better edit it! + +=head1 NAME + +LJ::TextMessage - text message phones/pages using a variety of methods/services + +=head1 SYNOPSIS + + use LJ::TextMessage; + + @providers = LJ::TextMessage::providers(); + foreach my $p (@providers) { + my $info = LJ::TextMessage::provider_info($p); + print "Name: $info->{'name'}\n"; + print "Notes: $info->{'notes'}\n"; + print "Limits: \n"; + foreach my $limit (qw(from msg tot)) { + print " $limit: ", $info->{"${limit}limit"}, "\n"; + } + } + + my $phone = new LJ::TextMessage { + 'provider' => 'voicestream', + 'number' => '2045551212', + 'mailcommand' => '/usr/local/sbin/sendmail -t', + }; + + my @errors; + $phone->send({ 'from' => 'Bob', + 'message' => "Hello! This is my message!" }, + \@errors); + if (@errors) { + ... + } else { + print "Message sent!\n"; + } + +=head1 DESCRIPTION + +The synopsis pretty much shows all the functionality that's available, +but details would be nice here. + +=head1 BUGS + +This library is highly volatile, as cellphone and pager providers can +change the details of their web or email gateways at any time. In +practice I haven't had to update this library much, but providers have +no responsibility to tell me when they change their form field names +on their website, or change URLs*. + +This documentation sucks rancid goats**. + + +* - This will, of course, change once LJ has conquered the world. +** - No, not Frank. + +=head1 AUTHOR + +Current maintainers: + - Aaron B. Russell (idigital) - + - Eric Carr (iicarrii) - + +Based on (mostly still, actually) code by: + - Brad Fitzpatrick (bradfitz) - + - Nicholas Tang (ntang) - + +Additional code provided by: + - Larry Gilbert (l2g) - + - (delphy) + - (rory) + - Tony Sutton (tsutton) - + - Chris Bartow (christowang) - + - Gavin Mogan (halkeye) - + - Steven Kreuzer (22dip) - +(if you've been forgotten, please give a holler!) + +Information about text messaging gateways from many. + +=cut diff --git a/livejournal/cgi-bin/LJ/User.pm b/livejournal/cgi-bin/LJ/User.pm new file mode 100755 index 0000000..705bc66 --- /dev/null +++ b/livejournal/cgi-bin/LJ/User.pm @@ -0,0 +1,682 @@ +# +# LiveJournal user object +# +# 2004-07-21: we're transition from $u hashrefs to $u objects, currently +# backed by hashrefs, to ease migration. in the future, +# more methods from ljlib.pl and other places will move here, +# and the representation of a $u object will change to 'fields'. +# at present, the motivation to moving to $u objects is to do +# all database access for a given user through his/her $u object +# so the queries can be tagged for use by the star replication +# daemon. + +use strict; + +package LJ::User; +use Carp; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJ::MemCache; + +sub readonly { + my $u = shift; + return LJ::get_cap($u, "readonly"); +} + +# returns self (the $u object which can be used for $u->do) if +# user is writable, else 0 +sub writer { + my $u = shift; + return $u if $u->{'_dbcm'} ||= LJ::get_cluster_master($u); + return 0; +} + +# returns a true value if the user is underage; or if you give it an argument, +# will turn on/off that user's underage status. can also take a second argument +# when you're setting the flag to also update the underage_status userprop +# which is used to record if a user was ever marked as underage. +sub underage { + # has no bearing if this isn't on + return undef unless $LJ::UNDERAGE_BIT; + + # now get the args and continue + my $u = shift; + return LJ::get_cap($u, 'underage') unless @_; + + # now set it on or off + my $on = shift() ? 1 : 0; + if ($on) { + LJ::modify_caps($u, [ $LJ::UNDERAGE_BIT ], []); + $u->{caps} |= 1 << $LJ::UNDERAGE_BIT; + } else { + LJ::modify_caps($u, [], [ $LJ::UNDERAGE_BIT ]); + $u->{caps} &= !(1 << $LJ::UNDERAGE_BIT); + } + + # now set their status flag if one was sent + my $status = shift(); + if ($status || $on) { + # by default, just records if user was ever underage ("Y") + $u->underage_status($status || 'Y'); + } + + # add to statushistory + if (my $shwhen = shift()) { + my $text = $on ? "marked" : "unmarked"; + my $status = $u->underage_status; + LJ::statushistory_add($u, undef, "coppa", "$text; status=$status; when=$shwhen"); + } + + # now fire off any hooks that are available + LJ::run_hooks('set_underage', { + u => $u, + on => $on, + status => $u->underage_status, + }); + + # return what we set it to + return $on; +} + +# log a line to our userlog +sub log_event { + my $u = shift; + + my ($type, $info) = @_; + return undef unless $type; + $info ||= {}; + + # now get variables we need; we use delete to remove them from the hash so when we're + # done we can just encode what's left + my $ip = delete($info->{ip}) || LJ::get_remote_ip() || undef; + my $uniq = delete $info->{uniq}; + unless ($uniq) { + eval { + $uniq = Apache->request->notes('uniq'); + }; + } + my $remote = delete($info->{remote}) || LJ::get_remote() || undef; + my $targetid = (delete($info->{actiontarget})+0) || undef; + my $extra = %$info ? join('&', map { LJ::eurl($_) . '=' . LJ::eurl($info->{$_}) } keys %$info) : undef; + + # now insert the data we have + $u->do("INSERT INTO userlog (userid, logtime, action, actiontarget, remoteid, ip, uniq, extra) " . + "VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?, ?, ?, ?)", undef, $u->{userid}, $type, + $targetid, $remote ? $remote->{userid} : undef, $ip, $uniq, $extra); + return undef if $u->err; + return 1; +} + +# return or set the underage status userprop +sub underage_status { + return undef unless $LJ::UNDERAGE_BIT; + + my $u = shift; + + # return if they aren't setting it + unless (@_) { + LJ::load_user_props($u, 'underage_status'); + return $u->{underage_status}; + } + + # set and return what it got set to + LJ::set_userprop($u, 'underage_status', shift()); + return $u->{underage_status}; +} + +# returns a true value if user has a reserved 'ext' name. +sub external { + my $u = shift; + return $u->{user} =~ /^ext_/; +} + +# this is for debugging/special uses where you need to instruct +# a user object on what database handle to use. returns the +# handle that you gave it. +sub set_dbcm { + my $u = shift; + return $u->{'_dbcm'} = shift; +} + +sub begin_work { + my $u = shift; + return 1 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->begin_work; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +sub commit { + my $u = shift; + return 1 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->commit; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +sub rollback { + my $u = shift; + return 0 unless $LJ::INNODB_DB{$u->{clusterid}}; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->rollback; + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +# get an $sth from the writer +sub prepare { + my $u = shift; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + my $rv = $dbcm->prepare(@_); + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + return $rv; +} + +# $u->do("UPDATE foo SET key=?", undef, $val); +sub do { + my $u = shift; + my $query = shift; + + my $uid = $u->{userid}+0 + or croak "Database update called on null user object"; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + $query =~ s!^(\s*\w+\s+)!$1/* uid=$uid */ !; + + my $rv = $dbcm->do($query, @_); + if ($u->{_dberr} = $dbcm->err) { + $u->{_dberrstr} = $dbcm->errstr; + } + + $u->{_mysql_insertid} = $dbcm->{'mysql_insertid'} if $dbcm->{'mysql_insertid'}; + + return $rv; +} + +sub selectrow_array { + my $u = shift; + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + return $dbcm->selectrow_array(@_); +} + +sub selectrow_hashref { + my $u = shift; + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + return $dbcm->selectrow_hashref(@_); +} + +sub err { + my $u = shift; + return $u->{_dberr}; +} + +sub errstr { + my $u = shift; + return $u->{_dberrstr}; +} + +sub quote { + my $u = shift; + my $text = shift; + + my $dbcm = $u->{'_dbcm'} ||= LJ::get_cluster_master($u) + or croak "Database handle unavailable"; + + return $dbcm->quote($text); +} + +sub mysql_insertid { + my $u = shift; + if ($u->isa("LJ::User")) { + return $u->{_mysql_insertid}; + } elsif (LJ::isdb($u)) { + my $db = $u; + return $db->{'mysql_insertid'}; + } else { + die "Unknown object '$u' being passed to LJ::User::mysql_insertid."; + } +} + +# +# name: LJ::User::dudata_set +# class: logging +# des: Record or delete disk usage data for a journal +# args: u, area, areaid, bytes +# area: One character: "L" for log, "T" for talk, "B" for bio, "P" for pic. +# areaid: Unique ID within $area, or '0' if area has no ids (like bio) +# bytes: Number of bytes item takes up. Or 0 to delete record. +# returns: 1. +# +sub dudata_set { + my ($u, $area, $areaid, $bytes) = @_; + $bytes += 0; $areaid += 0; + if ($bytes) { + $u->do("REPLACE INTO dudata (userid, area, areaid, bytes) ". + "VALUES (?, ?, $areaid, $bytes)", undef, + $u->{userid}, $area); + } else { + $u->do("DELETE FROM dudata WHERE userid=? AND ". + "area=? AND areaid=$areaid", undef, + $u->{userid}, $area); + } + return 1; +} + +sub generate_session +{ + my ($u, $opts) = @_; + my $udbh = LJ::get_cluster_master($u); + return undef unless $udbh; + + # clean up any old, expired sessions they might have (lazy clean) + $u->do("DELETE FROM sessions WHERE userid=? AND timeexpire < UNIX_TIMESTAMP()", + undef, $u->{userid}); + + my $sess = {}; + $opts->{'exptype'} = "short" unless $opts->{'exptype'} eq "long" || + $opts->{'exptype'} eq "once"; + $sess->{'auth'} = LJ::rand_chars(10); + my $expsec = $opts->{'expsec'}+0 || { + 'short' => 60*60*24*1.5, # 36 hours + 'long' => 60*60*24*60, # 60 days + 'once' => 60*60*24*1.5, # same as short; just doesn't renew + }->{$opts->{'exptype'}}; + my $id = LJ::alloc_user_counter($u, 'S'); + return undef unless $id; + $u->do("REPLACE INTO sessions (userid, sessid, auth, exptype, ". + "timecreate, timeexpire, ipfixed) VALUES (?,?,?,?,UNIX_TIMESTAMP(),". + "UNIX_TIMESTAMP()+$expsec,?)", undef, + $u->{'userid'}, $id, $sess->{'auth'}, $opts->{'exptype'}, $opts->{'ipfixed'}); + return undef if $u->err; + $sess->{'sessid'} = $id; + $sess->{'userid'} = $u->{'userid'}; + $sess->{'ipfixed'} = $opts->{'ipfixed'}; + $sess->{'exptype'} = $opts->{'exptype'}; + + # clean up old sessions + my $old = $udbh->selectcol_arrayref("SELECT sessid FROM sessions WHERE ". + "userid=$u->{'userid'} AND ". + "timeexpire < UNIX_TIMESTAMP()"); + $u->kill_sessions(@$old) if $old; + + # mark account as being used + LJ::mark_user_active($u, 'login'); + + return $sess; +} + +sub make_login_session { + my ($u, $exptype, $ipfixed) = @_; + $exptype ||= 'short'; + return 0 unless $u; + + my $etime = 0; + eval { Apache->request->notes('ljuser' => $u->{'user'}); }; + + my $sess = $u->generate_session({ + 'exptype' => $exptype, + 'ipfixed' => $ipfixed, + }); + $BML::COOKIE{'ljsession'} = [ "ws:$u->{'user'}:$sess->{'sessid'}:$sess->{'auth'}", $etime, 1 ]; + LJ::set_remote($u); + + LJ::load_user_props($u, "browselang", "schemepref" ); + my $bl = LJ::Lang::get_lang($u->{'browselang'}); + if ($bl) { + BML::set_cookie("langpref", $bl->{'lncode'} . "/" . time(), 0, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + BML::set_language($bl->{'lncode'}); + } + + # restore default scheme + if ($u->{'schemepref'} ne "") { + BML::set_cookie("BMLschemepref", $u->{'schemepref'}, 0, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN); + BML::set_scheme($u->{'schemepref'}); + } + + LJ::run_hooks("post_login", { + "u" => $u, + "form" => {}, + "expiretime" => $etime, + }); + + LJ::mark_user_active($u, 'login'); + + return 1; +} + +sub tosagree_set +{ + my ($u, $err) = @_; + return undef unless $u; + + unless (-f "$LJ::HOME/htdocs/inc/legal-tos") { + $$err = "TOS include file could not be found"; + return undef; + } + + my $rev; + open (TOS, "$LJ::HOME/htdocs/inc/legal-tos"); + while ((!$rev) && (my $line = )) { + my $rcstag = "Revision"; + if ($line =~ /\$$rcstag:\s*(\S+)\s*\$/) { + $rev = $1; + } + } + close TOS; + + # if the required version of the tos is not available, error! + my $rev_req = $LJ::REQUIRED_TOS{rev}; + if ($rev_req > 0 && $rev ne $rev_req) { + $$err = "Required Terms of Service revision is $rev_req, but system version is $rev."; + return undef; + } + + my $newval = join(', ', time(), $rev); + my $rv = LJ::set_userprop($u, "legal_tosagree", $newval); + + # set in $u object for callers later + $u->{legal_tosagree} = $newval if $rv; + + return $rv; +} + +sub tosagree_verify { + my $u = shift; + + return 1 unless $LJ::TOS_CHECK; + + my $rev_req = $LJ::REQUIRED_TOS{rev}; + return 1 unless $rev_req > 0; + + LJ::load_user_props($u, 'legal_tosagree') + unless $u->{legal_tosagree}; + + my $rev_cur = (split(/\s*,\s*/, $u->{legal_tosagree}))[1]; + + return $rev_cur eq $rev_req; +} + +sub kill_sessions { + my $u = shift; + my (@sessids) = @_; + my $in = join(',', map { $_+0 } @sessids); + return 1 unless $in; + my $userid = $u->{'userid'}; + foreach (qw(sessions sessions_data)) { + $u->do("DELETE FROM $_ WHERE userid=? AND ". + "sessid IN ($in)", undef, $userid); + } + foreach my $id (@sessids) { + $id += 0; + my $memkey = [$userid,"sess:$userid:$id"]; + LJ::MemCache::delete($memkey); + } + return 1; +} + +sub kill_all_sessions { + my $u = shift; + return 0 unless $u; + my $udbh = LJ::get_cluster_master($u); + my $sessions = $udbh->selectcol_arrayref("SELECT sessid FROM sessions WHERE ". + "userid=$u->{'userid'}"); + $u->kill_sessions(@$sessions) if @$sessions; + + # forget this user, if we knew they were logged in + delete $BML::COOKIE{'ljsession'}; + LJ::set_remote(undef) if + $LJ::CACHE_REMOTE && + $LJ::CACHE_REMOTE->{userid} == $u->{userid}; + + return 1; +} + +sub kill_session { + my $u = shift; + return 0 unless $u; + return 0 unless exists $u->{'_session'}; + $u->kill_sessions($u->{'_session'}->{'sessid'}); + + # forget this user, if we knew they were logged in + delete $BML::COOKIE{'ljsession'}; + LJ::set_remote(undef) if + $LJ::CACHE_REMOTE && + $LJ::CACHE_REMOTE->{userid} == $u->{userid}; + + return 1; +} + +# +# name: LJ::User::mogfs_userpic_key +# class: mogilefs +# des: Make a mogilefs key for the given pic for the user +# args: pic +# pic: Either the userpic hash or the picid of the userpic. +# returns: 1. +# +sub mogfs_userpic_key { + my $self = shift or return undef; + my $pic = shift or croak "missing required arg: userpic"; + + my $picid = ref $pic ? $pic->{picid} : $pic+0; + return "up:$self->{userid}:$picid"; +} + +# all reads/writes to talk2 must be done inside a lock, so there's +# no race conditions between reading from db and putting in memcache. +# can't do a db write in between those 2 steps. the talk2 -> memcache +# is elsewhere (talklib.pl), but this $dbh->do wrapper is provided +# here because non-talklib things modify the talk2 table, and it's +# nice to centralize the locking rules. +# +# return value is return of $dbh->do. $errref scalar ref is optional, and +# if set, gets value of $dbh->errstr +# +# write: (LJ::talk2_do) +# GET_LOCK +# update/insert into talk2 +# RELEASE_LOCK +# delete memcache +# +# read: (LJ::Talk::get_talk_data) +# try memcache +# GET_LOCk +# read db +# update memcache +# RELEASE_LOCK + +sub talk2_do { + my ($u, $nodetype, $nodeid, $errref, $sql, @args) = @_; + return undef unless $nodetype =~ /^\w$/; + return undef unless $nodeid =~ /^\d+$/; + return undef unless $u->writer; + + my $dbcm = $u->{_dbcm}; + + my $memkey = [$u->{'userid'}, "talk2:$u->{'userid'}:$nodetype:$nodeid"]; + my $lockkey = $memkey->[1]; + + $dbcm->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + my $ret = $u->do($sql, undef, @args); + $$errref = $u->errstr if ref $errref && $u->err; + $dbcm->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + LJ::MemCache::delete($memkey, 0) if int($ret); + return $ret; +} + +# log2_do +# see comments for talk2_do + +sub log2_do { + my ($u, $errref, $sql, @args) = @_; + return undef unless $u->writer; + + my $dbcm = $u->{_dbcm}; + + my $memkey = [$u->{'userid'}, "log2lt:$u->{'userid'}"]; + my $lockkey = $memkey->[1]; + + $dbcm->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + my $ret = $u->do($sql, undef, @args); + $$errref = $u->errstr if ref $errref && $u->err; + $dbcm->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + LJ::MemCache::delete($memkey, 0) if int($ret); + return $ret; +} + +sub url { + my $u = shift; + LJ::load_user_props($u, "url"); + if ($u->{'journaltype'} eq "I" && ! $u->{url}) { + my $id = $u->identity; + if ($id && $id->[0] eq "O") { + LJ::set_userprop($u, "url", $id->[1]) if $id->[1]; + return $id->[1]; + } + } + return $u->{url}; +} + +# returns arrayref of [idtype, identity] +sub identity { + my $u = shift; + return $u->{_identity} if $u->{_identity}; + return undef unless $u->{'journaltype'} eq "I"; + my $memkey = [$u->{userid}, "ident:$u->{userid}"]; + my $ident = LJ::MemCache::get($memkey); + if ($ident) { + return $u->{_identity} = $ident; + } + + my $dbh = LJ::get_db_writer(); + $ident = $dbh->selectrow_arrayref("SELECT idtype, identity FROM identitymap ". + "WHERE userid=? LIMIT 1", undef, $u->{userid}); + if ($ident) { + LJ::MemCache::set($memkey, $ident); + return $ident; + } + return undef; +} + +# returns a URL iff account is an OpenID identity. undef otherwise. +sub openid_identity { + my $u = shift; + my $ident = $u->identity; + return undef unless $ident && $ident->[0] == 0; + return $ident->[1]; +} + +# returns username or identity display name, not escaped +sub display_name { + my $u = shift; + return $u->{'user'} unless $u->{'journaltype'} eq "I"; + + my $id = $u->identity; + return "[ERR:unknown_identity]" unless $id; + + my ($url, $name); + if ($id->[0] eq "O") { + require Net::OpenID::Consumer; + $url = $id->[1]; + $name = Net::OpenID::VerifiedIdentity::DisplayOfURL($url, $LJ::IS_DEV_SERVER); + # FIXME: make a good out of this + $name =~ s/\[(live|dead)journal\.com/\[${1}journal/; + } + return $name; +} + +sub ljuser_display { + my $u = shift; + my $opts = shift; + + return LJ::ljuser($u, $opts) unless $u->{'journaltype'} eq "I"; + + my $id = $u->identity; + return "????" unless $id; + + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::IMGPREFIX; + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + + my ($url, $name); + + if ($id->[0] eq "O") { + $url = $id->[1]; + $name = $u->display_name; + + $url ||= "about:blank"; + $name ||= "[no_name]"; + + $url = LJ::ehtml($url); + $name = LJ::ehtml($name); + + return "[info]$name"; + + } else { + return "????"; + } +} + +sub load_identity_user { + my ($type, $ident, $vident) = @_; + + my $dbh = LJ::get_db_writer(); + my $uid = $dbh->selectrow_array("SELECT userid FROM identitymap WHERE idtype=? AND identity=?", + undef, $type, $ident); + return LJ::load_userid($uid) if $uid; + + # increment ext_ counter until we successfully create an LJ + # account. hard cap it at 10 tries. (arbitrary, but we really + # shouldn't have *any* failures here, let alone 10 in a row) + + for (1..10) { + my $extuser = 'ext_' . LJ::alloc_global_counter('E'); + + my $name = $extuser; + if ($type eq "O" && ref $vident) { + $name = $vident->display; + } + + $uid = LJ::create_account({ + caps => undef, + user => $extuser, + name => $name, + journaltype => 'I', + }); + last if $uid; + select undef, undef, undef, .10; # lets not thrash over this + } + return undef unless $uid && + $dbh->do("INSERT INTO identitymap (idtype, identity, userid) VALUES (?,?,?)", + undef, $type, $ident, $uid); + return LJ::load_userid($uid); +} + +1; diff --git a/livejournal/cgi-bin/PaletteModify.pm b/livejournal/cgi-bin/PaletteModify.pm new file mode 100755 index 0000000..7877e26 --- /dev/null +++ b/livejournal/cgi-bin/PaletteModify.pm @@ -0,0 +1,122 @@ +#!/usr/bin/perl +# + +use strict; +BEGIN { + $PaletteModify::HAVE_CRC = eval "use String::CRC32 (); 1;"; +} + +package PaletteModify; + +sub common_alter +{ + my ($palref, $table) = @_; + my $length = length $table; + + my $pal_size = $length / 3; + + # tinting image? if so, we're remaking the whole palette + if (my $tint = $palref->{'tint'}) { + my $dark = $palref->{'tint_dark'}; + my $diff = [ map { $tint->[$_] - $dark->[$_] } (0..2) ]; + $palref = {}; + for (my $idx=0; $idx<$pal_size; $idx++) { + for my $c (0..2) { + my $curr = ord(substr($table, $idx*3+$c)); + my $p = \$palref->{$idx}->[$c]; + $$p = int($dark->[$c] + $diff->[$c] * $curr / 255); + } + } + } + + while (my ($idx, $c) = each %$palref) { + next if $idx >= $pal_size; + substr($table, $idx*3+$_, 1) = chr($c->[$_]) for (0..2); + } + + return $table; +} + +sub new_gif_palette +{ + my ($fh, $palref) = @_; + my $header; + + # 13 bytes for magic + image info (size, color depth, etc) + # and then the global palette table (3*256) + read($fh, $header, 13+3*256); + + # figure out how big global color table is (don't want to overwrite it) + my $pf = ord substr($header, 10, 1); + my $gct = 2 ** (($pf & 7) + 1); # last 3 bits of packaged fields + + substr($header, 13, 3*$gct) = common_alter($palref, substr($header, 13, 3*$gct)); + return $header; +} + +sub new_png_palette +{ + my ($fh, $palref) = @_; + + # without this module, we can't proceed. + return undef unless $PaletteModify::HAVE_CRC; + + my $imgdata; + + # Validate PNG signature + my $png_sig = pack("H16", "89504E470D0A1A0A"); + my $sig; + read($fh, $sig, 8); + return undef unless $sig eq $png_sig; + $imgdata .= $sig; + + # Start reading in chunks + my ($length, $type) = (0, ''); + while (read($fh, $length, 4)) { + + $imgdata .= $length; + $length = unpack("N", $length); + return undef unless read($fh, $type, 4) == 4; + $imgdata .= $type; + + if ($type eq 'IHDR') { + my $header; + read($fh, $header, $length+4); + my ($width,$height,$depth,$color,$compression, + $filter,$interlace, $CRC) + = unpack("NNCCCCCN", $header); + return undef unless $color == 3; # unpaletted image + $imgdata .= $header; + } elsif ($type eq 'PLTE') { + # Finally, we can go to work + my $palettedata; + read($fh, $palettedata, $length); + $palettedata = common_alter($palref, $palettedata); + $imgdata .= $palettedata; + + # Skip old CRC + my $skip; + read($fh, $skip, 4); + + # Generate new CRC + my $crc = String::CRC32::crc32($type . $palettedata); + $crc = pack("N", $crc); + + $imgdata .= $crc; + return $imgdata; + } else { + my $skip; + # Skip rest of chunk and add to imgdata + # Number of bytes is +4 becauses of CRC + # + for (my $count=0; $count < $length + 4; $count++) { + read($fh, $skip, 1); + $imgdata .= $skip; + } + } + } + + return undef; +} + +1; diff --git a/livejournal/cgi-bin/XML/Atom.pm b/livejournal/cgi-bin/XML/Atom.pm new file mode 100755 index 0000000..c5946b2 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom.pm @@ -0,0 +1,75 @@ +# $Id: Atom.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom; +use strict; + +BEGIN { + @XML::Atom::EXPORT = qw( LIBXML ); + if (eval { require XML::LibXML }) { + *{XML::Atom::LIBXML} = sub() {1}; + } else { + require XML::XPath; + *{XML::Atom::LIBXML} = sub() {0}; + } + local $^W = 0; + *XML::XPath::Function::namespace_uri = sub { + my $self = shift; + my($node, @params) = @_; + my $ns = $node->getNamespace($node->getPrefix); + if (!$ns) { + $ns = ($node->getNamespaces)[0]; + } + XML::XPath::Literal->new($ns ? $ns->getExpanded : ''); + }; +} + +use base qw( XML::Atom::ErrorHandler Exporter ); + +our $VERSION = '0.11'; + +package XML::Atom::Namespace; +use strict; + +sub new { + my $class = shift; + my($prefix, $uri) = @_; + bless { prefix => $prefix, uri => $uri }, $class; +} + +sub DESTROY { } + +use vars qw( $AUTOLOAD ); +sub AUTOLOAD { + (my $var = $AUTOLOAD) =~ s!.+::!!; + no strict 'refs'; + ($_[0], $var); +} + +1; +__END__ + +=head1 NAME + +XML::Atom - Atom feed and API implementation + +=head1 SYNOPSIS + + use XML::Atom; + +=head1 DESCRIPTION + +Atom is a syndication, API, and archiving format for weblogs and other +data. I implements the feed format as well as a client for the +API. + +=head1 LICENSE + +I is free software; you may redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 AUTHOR & COPYRIGHT + +Except where otherwise noted, I is Copyright 2003 Benjamin +Trott, cpan@stupidfool.org. All rights reserved. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/Client.pm b/livejournal/cgi-bin/XML/Atom/Client.pm new file mode 100755 index 0000000..20d41b5 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Client.pm @@ -0,0 +1,348 @@ +# $Id: Client.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Client; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); +use LWP::UserAgent; +use XML::Atom::Entry; +use XML::Atom::Feed; +use XML::Atom::Util qw( first textValue ); +use Digest::SHA1 qw( sha1 ); +use MIME::Base64 qw( encode_base64 ); +use DateTime; + +use constant NS_ATOM => 'http://purl.org/atom/ns#'; +use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/'; + +sub new { + my $class = shift; + my $client = bless { }, $class; + $client->init(@_) or return $class->error($client->errstr); + $client; +} + +sub init { + my $client = shift; + my %param = @_; + $client->{ua} = LWP::UserAgent::AtomClient->new($client); + $client->{ua}->agent('XML::Atom/' . XML::Atom->VERSION); + $client; +} + +sub username { + my $client = shift; + $client->{username} = shift if @_; + $client->{username}; +} + +sub password { + my $client = shift; + $client->{password} = shift if @_; + $client->{password}; +} + +sub use_soap { + my $client = shift; + $client->{use_soap} = shift if @_; + $client->{use_soap}; +} + +sub auth_digest { + my $client = shift; + $client->{auth_digest} = shift if @_; + $client->{auth_digest}; +} + +sub getEntry { + my $client = shift; + my($url) = @_; + my $req = HTTP::Request->new(GET => $url); + my $res = $client->make_request($req); + return $client->error("Error on GET $url: " . $res->status_line) + unless $res->code == 200; + XML::Atom::Entry->new(Stream => \$res->content); +} + +sub createEntry { + my $client = shift; + my($uri, $entry) = @_; + return $client->error("Must pass a PostURI before posting") + unless $uri; + my $req = HTTP::Request->new(POST => $uri); + $req->content_type('application/x.atom+xml'); + my $xml = $entry->as_xml; + _utf8_off($xml); + $req->content_length(length $xml); + $req->content($xml); + my $res = $client->make_request($req); + return $client->error("Error on POST $uri: " . $res->status_line) + unless $res->code == 201; + $res->header('Location') || 1; +} + +sub updateEntry { + my $client = shift; + my($url, $entry) = @_; + my $req = HTTP::Request->new(PUT => $url); + $req->content_type('application/x.atom+xml'); + my $xml = $entry->as_xml; + _utf8_off($xml); + $req->content_length(length $xml); + $req->content($xml); + my $res = $client->make_request($req); + return $client->error("Error on PUT $url: " . $res->status_line) + unless $res->code == 200; + 1; +} + +sub deleteEntry { + my $client = shift; + my($url) = @_; + my $req = HTTP::Request->new(DELETE => $url); + my $res = $client->make_request($req); + return $client->error("Error on DELETE $url: " . $res->status_line) + unless $res->code == 200; + 1; +} + +sub getFeed { + my $client = shift; + my($uri) = @_; + return $client->error("Must pass a FeedURI before retrieving feed") + unless $uri; + my $req = HTTP::Request->new(GET => $uri); + my $res = $client->make_request($req); + return $client->error("Error on GET $uri: " . $res->status_line) + unless $res->code == 200; + my $feed = XML::Atom::Feed->new(Stream => \$res->content) + or return $client->error(XML::Atom::Feed->errstr); + $feed; +} + +sub make_request { + my $client = shift; + my($req) = @_; + $client->munge_request($req); + my $res = $client->{ua}->request($req); + $client->munge_response($res); + $res; +} + +sub munge_request { + my $client = shift; + my($req) = @_; + $req->header( + Accept => 'application/x.atom+xml, application/xml, text/xml, */*', + ); + my $nonce = $client->make_nonce; + my $nonce_enc = encode_base64($nonce, ''); + my $now = DateTime->now->iso8601 . 'Z'; + my $digest = encode_base64(sha1($nonce . $now . ($client->password || '')), ''); + if ($client->use_soap) { + my $xml = $req->content || ''; + $xml =~ s!^(<\?xml.*?\?>)!!; + my $method = $req->method; + $xml = ($1 || '') . < + + + + @{[ $client->username || '' ]} + $digest + $nonce_enc + $now + + + + + <$method xmlns="http://schemas.xmlsoap.org/wsdl/http/"> +$xml + + + +SOAP + $req->content($xml); + $req->content_length(length $xml); + $req->header('SOAPAction', 'http://schemas.xmlsoap.org/wsdl/http/' . $method); + $req->method('POST'); + $req->content_type('text/xml'); + } else { + $req->header('X-WSSE', sprintf + qq(UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"), + $client->username || '', $digest, $nonce_enc, $now); + $req->header('Authorization', 'WSSE profile="UsernameToken"'); + } +} + +sub munge_response { + my $client = shift; + my($res) = @_; + if ($client->use_soap && (my $xml = $res->content)) { + my $doc; + if (LIBXML) { + my $parser = XML::LibXML->new; + $doc = $parser->parse_string($xml); + } else { + my $xp = XML::XPath->new(xml => $xml); + $doc = ($xp->find('/')->get_nodelist)[0]; + } + my $body = first($doc, NS_SOAP, 'Body'); + if (my $fault = first($body, NS_SOAP, 'Fault')) { + $res->code(textValue($fault, undef, 'faultcode')); + $res->message(textValue($fault, undef, 'faultstring')); + $res->content(''); + $res->content_length(0); + } else { + $xml = join '', map $_->toString(LIBXML ? 1 : 0), + LIBXML ? $body->childNodes : $body->getChildNodes; + $res->content($xml); + $res->content_length(1); + } + } +} + +sub make_nonce { sha1(sha1(time() . {} . rand() . $$)) } + +sub _utf8_off { + my $val = shift; + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($val); + } +} + +package LWP::UserAgent::AtomClient; +use strict; + +use base qw( LWP::UserAgent ); + +my %ClientOf; +sub new { + my($class, $client) = @_; + my $ua = $class->SUPER::new; + $ClientOf{$ua} = $client; + $ua; +} + +sub get_basic_credentials { + my($ua, $realm, $url, $proxy) = @_; + my $client = $ClientOf{$ua} or die "Cannot find $ua"; + return $client->username, $client->password; +} + +sub DESTROY { + my $self = shift; + delete $ClientOf{$self}; +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Client - A client for the Atom API + +=head1 SYNOPSIS + + use XML::Atom::Client; + use XML::Atom::Entry; + my $api = XML::Atom::Client->new; + $api->username('Melody'); + $api->password('Nelson'); + + my $entry = XML::Atom::Entry->new; + $entry->title('New Post'); + $entry->content('Content of my post.'); + my $EditURI = $api->createEntry($PostURI, $entry); + + my $feed = $api->getFeed($FeedURI); + my @entries = $feed->entries; + + my $entry = $api->getEntry($EditURI); + +=head1 DESCRIPTION + +I implements a client for the Atom API described at +I, with the +authentication scheme described at +I. + +B the API, and particularly the authentication scheme, are still +in flux. + +=head1 USAGE + +=head2 XML::Atom::Client->new(%param) + +=head2 $api->use_soap([ 0 | 1 ]) + +I supports both the REST and SOAP-wrapper versions of the +Atom API. By default, the REST version of the API will be used, but you can +turn on the SOAP wrapper--for example, if you need to connect to a server +that supports only the SOAP wrapper--by calling I with a value of +C<1>: + + $api->use_soap(1); + +If called without arguments, returns the current value of the flag. + +=head2 $api->username([ $username ]) + +If called with an argument, sets the username for login to I<$username>. + +Returns the current username that will be used when logging in to the +Atom server. + +=head2 $api->password([ $password ]) + +If called with an argument, sets the password for login to I<$password>. + +Returns the current password that will be used when logging in to the +Atom server. + +=head2 $api->createEntry($PostURI, $entry) + +Creates a new entry. + +I<$entry> must be an I object. + +=head2 $api->getEntry($EditURI) + +Retrieves the entry with the given URL I<$EditURI>. + +Returns an I object. + +=head2 $api->updateEntry($EditURI, $entry) + +Updates the entry at URL I<$EditURI> with the entry I<$entry>, which must be +an I object. + +Returns true on success, false otherwise. + +=head2 $api->deleteEntry($EditURI) + +Deletes the entry at URL I<$EditURI>. + +=head2 $api->getFeed($FeedURI) + +Retrieves the feed at I<$FeedURI>. + +Returns an I object representing the feed returned +from the server. + +=head2 ERROR HANDLING + +Methods return C on error, and the error message can be retrieved +using the I method. + +=head1 AUTHOR & COPYRIGHT + +Please see the I manpage for author, copyright, and license +information. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/Content.pm b/livejournal/cgi-bin/XML/Atom/Content.pm new file mode 100755 index 0000000..2120ac7 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Content.pm @@ -0,0 +1,157 @@ +# $Id: Content.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Content; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); +use XML::Atom::Util qw( remove_default_ns ); +use MIME::Base64 qw( encode_base64 decode_base64 ); + +use constant NS => 'http://purl.org/atom/ns#'; + +sub new { + my $class = shift; + my $content = bless {}, $class; + $content->init(@_) or return $class->error($content->errstr); + $content; +} + +sub init { + my $content = shift; + my %param = @_ == 1 ? (Body => $_[0]) : @_; + my $elem; + unless ($elem = $param{Elem}) { + if (LIBXML) { + my $doc = XML::LibXML::Document->createDocument('1.0', 'utf-8'); + $elem = $doc->createElementNS(NS, 'content'); + $doc->setDocumentElement($elem); + } else { + $elem = XML::XPath::Node::Element->new('content'); + } + } + $content->{elem} = $elem; + if ($param{Body}) { + $content->body($param{Body}); + } + if ($param{Type}) { + $content->type($param{Type}); + } + $content; +} + +sub elem { $_[0]->{elem} } + +sub type { + my $content = shift; + if (@_) { + $content->elem->setAttribute('type', shift); + } + $content->elem->getAttribute('type'); +} + +sub mode { + my $content = shift; + $content->elem->getAttribute('mode'); +} + +sub body { + my $content = shift; + my $elem = $content->elem; + if (@_) { + my $data = shift; + if (LIBXML) { + $elem->removeChildNodes; + } else { + $elem->removeChild($_) for $elem->getChildNodes; + } + if (!_is_printable($data)) { + if (LIBXML) { + $elem->appendChild(XML::LibXML::Text->new(encode_base64($data, ''))); + } else { + $elem->appendChild(XML::XPath::Node::Text->new(encode_base64($data, ''))); + } + $elem->setAttribute('mode', 'base64'); + } else { + my $copy = '

    ' . + $data . + '
    '; + my $node; + eval { + if (LIBXML) { + my $parser = XML::LibXML->new; + my $tree = $parser->parse_string($copy); + $node = $tree->getDocumentElement; + } else { + my $xp = XML::XPath->new(xml => $copy); + $node = (($xp->find('/')->get_nodelist)[0]->getChildNodes)[0] + if $xp; + } + }; + if (!$@ && $node) { + $elem->appendChild($node); + $elem->setAttribute('mode', 'xml'); + } else { + if (LIBXML) { + $elem->appendChild(XML::LibXML::Text->new($data)); + } else { + $elem->appendChild(XML::XPath::Node::Text->new($data)); + } + $elem->setAttribute('mode', 'escaped'); + } + } + } else { + unless (exists $content->{__body}) { + my $mode = $elem->getAttribute('mode') || 'xml'; + if ($mode eq 'xml') { + my @children = grep ref($_) =~ /Element/, + LIBXML ? $elem->childNodes : $elem->getChildNodes; + if (@children) { + if (@children == 1 && $children[0]->getLocalName eq 'div') { + @children = + LIBXML ? $children[0]->childNodes : + $children[0]->getChildNodes + } + $content->{__body} = ''; + for my $n (@children) { + remove_default_ns($n) if LIBXML; + $content->{__body} .= $n->toString(LIBXML ? 1 : 0); + } + } else { + $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value; + } + } elsif ($mode eq 'base64') { + $content->{__body} = decode_base64(LIBXML ? $elem->textContent : $elem->string_value); + } elsif ($mode eq 'escaped') { + $content->{__body} = LIBXML ? $elem->textContent : $elem->string_value; + } else { + $content->{__body} = undef; + } + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($content->{__body}); + } + } + } + $content->{__body}; +} + +sub _is_printable { + my $data = shift; + + # printable ASCII or UTF-8 bytes + $data =~ /^(?:[\x09\x0a\x0d\x20-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])*$/; +} + +sub as_xml { + my $content = shift; + if (LIBXML) { + my $doc = XML::LibXML::Document->new('1.0', 'utf-8'); + $doc->setDocumentElement($content->elem); + return $doc->toString(1); + } else { + return $content->elem->toString; + } +} + +1; diff --git a/livejournal/cgi-bin/XML/Atom/Entry.pm b/livejournal/cgi-bin/XML/Atom/Entry.pm new file mode 100755 index 0000000..f928f64 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Entry.pm @@ -0,0 +1,131 @@ +# $Id: Entry.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Entry; +use strict; + +use XML::Atom; +use base qw( XML::Atom::Thing ); +use MIME::Base64 qw( encode_base64 decode_base64 ); +use XML::Atom::Person; +use XML::Atom::Content; +use XML::Atom::Util qw( first ); + +use constant NS => 'http://purl.org/atom/ns#'; + +sub element_name { 'entry' } + +sub content { + my $entry = shift; + my @arg = @_; + if (@arg && ref($arg[0]) ne 'XML::Atom::Content') { + $arg[0] = XML::Atom::Content->new($arg[0]); + } + $entry->_element('XML::Atom::Content', 'content', @arg); +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Entry - Atom entry + +=head1 SYNOPSIS + + use XML::Atom::Entry; + my $entry = XML::Atom::Entry->new; + $entry->title('My Post'); + $entry->content('The content of my post.'); + my $xml = $entry->as_xml; + my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); + $entry->set($dc, 'subject', 'Food & Drink'); + +=head1 USAGE + +=head2 XML::Atom::Entry->new([ $stream ]) + +Creates a new entry object, and if I<$stream> is supplied, fills it with the +data specified by I<$stream>. + +Automatically handles autodiscovery if I<$stream> is a URI (see below). + +Returns the new I object. On failure, returns C. + +I<$stream> can be any one of the following: + +=over 4 + +=item * Reference to a scalar + +This is treated as the XML body of the entry. + +=item * Scalar + +This is treated as the name of a file containing the entry XML. + +=item * Filehandle + +This is treated as an open filehandle from which the entry XML can be read. + +=back + +=head2 $entry->content([ $content ]) + +Returns the content of the entry. If I<$content> is given, sets the content +of the entry. Automatically handles all necessary escaping. + +=head2 $entry->author([ $author ]) + +Returns an I object representing the author of the entry, +or C if there is no author information present. + +If I<$author> is supplied, it should be an I object +representing the author. For example: + + my $author = XML::Atom::Person->new; + $author->name('Foo Bar'); + $author->email('foo@bar.com'); + $entry->author($author); + +=head2 $entry->link + +If called in scalar context, returns an I object +corresponding to the first IlinkE> tag found in the entry. + +If called in list context, returns a list of I objects +corresponding to all of the IlinkE> tags found in the entry. + +=head2 $entry->add_link($link) + +Adds the link I<$link>, which must be an I object, to +the entry as a new IlinkE> tag. For example: + + my $link = XML::Atom::Link->new; + $link->type('text/html'); + $link->rel('alternate'); + $link->href('http://www.example.com/2003/12/post.html'); + $entry->add_link($link); + +=head2 $entry->get($ns, $element) + +Given an I element I<$ns> and an element name +I<$element>, retrieves the value for the element in that namespace. + +This is useful for retrieving the value of elements not in the main Atom +namespace, like categories. For example: + + my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/'); + my $subj = $entry->get($dc, 'subject'); + +=head2 $entry->getlist($ns, $element) + +Just like I<$entry-Eget>, but if there are multiple instances of the +element I<$element> in the namespace I<$ns>, returns all of them. I +will return only the first. + +=head1 AUTHOR & COPYRIGHT + +Please see the I manpage for author, copyright, and license +information. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/ErrorHandler.pm b/livejournal/cgi-bin/XML/Atom/ErrorHandler.pm new file mode 100755 index 0000000..614559a --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/ErrorHandler.pm @@ -0,0 +1,21 @@ +# $Id: ErrorHandler.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::ErrorHandler; +use strict; + +use vars qw( $ERROR ); + +sub new { bless {}, shift } +sub error { + my $msg = $_[1] || ''; + $msg .= "\n" unless $msg =~ /\n$/; + if (ref($_[0])) { + $_[0]->{_errstr} = $msg; + } else { + $ERROR = $msg; + } + return; + } +sub errstr { ref($_[0]) ? $_[0]->{_errstr} : $ERROR } + +1; diff --git a/livejournal/cgi-bin/XML/Atom/Feed.pm b/livejournal/cgi-bin/XML/Atom/Feed.pm new file mode 100755 index 0000000..d9a83ca --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Feed.pm @@ -0,0 +1,256 @@ +# $Id: Feed.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Feed; +use strict; + +use XML::Atom; +use base qw( XML::Atom::Thing ); +use XML::Atom::Entry; +BEGIN { + if (LIBXML) { + *entries = \&entries_libxml; + *add_entry = \&add_entry_libxml; + } else { + *entries = \&entries_xpath; + *add_entry = \&add_entry_xpath; + } +} + +use constant NS => 'http://purl.org/atom/ns#'; + +sub init { + my $atom = shift; + my %param = @_ == 1 ? (Stream => $_[0]) : @_; + if (UNIVERSAL::isa($param{Stream}, 'URI')) { + my @feeds = __PACKAGE__->find_feeds($param{Stream}); + return $atom->error("Can't find Atom file") unless @feeds; + my $ua = LWP::UserAgent->new; + my $req = HTTP::Request->new(GET => $feeds[0]); + my $res = $ua->request($req); + if ($res->is_success) { + $param{Stream} = \$res->content; + } + } + $atom->SUPER::init(%param); +} + +sub find_feeds { + my $class = shift; + my($uri) = @_; + my $ua = LWP::UserAgent->new; + my $req = HTTP::Request->new(GET => $uri); + my $res = $ua->request($req); + return unless $res->is_success; + my @feeds; + if ($res->content_type eq 'text/html' || $res->content_type eq 'application/xhtml+xml') { + my $base_uri = $uri; + my $find_links = sub { + my($tag, $attr) = @_; + if ($tag eq 'link') { + return unless $attr->{rel}; + my %rel = map { $_ => 1 } split /\s+/, lc($attr->{rel}); + (my $type = lc $attr->{type}) =~ s/^\s*//; + $type =~ s/\s*$//; + push @feeds, URI->new_abs($attr->{href}, $base_uri)->as_string + if $rel{alternate} && + $type eq 'application/atom+xml'; + } elsif ($tag eq 'base') { + $base_uri = $attr->{href}; + } + }; + require HTML::Parser; + my $p = HTML::Parser->new(api_version => 3, + start_h => [ $find_links, "tagname, attr" ]); + $p->parse($res->content); + } else { + @feeds = ($uri); + } + @feeds; +} + +sub element_name { 'feed' } + +sub language { + my $feed = shift; + if (LIBXML) { + my $elem = $feed->{doc}->getDocumentElement; + if (@_) { + $elem->setAttributeNS('http://www.w3.org/XML/1998/namespace', + 'lang', $_[0]); + } + return $elem->getAttribute('lang'); + } else { + if (@_) { + $feed->{doc}->setAttribute('xml:lang', $_[0]); + } + return $feed->{doc}->getAttribute('xml:lang'); + } +} + +sub version { + my $feed = shift; + my $elem = LIBXML ? $feed->{doc}->getDocumentElement : $feed->{doc}; + if (@_) { + $elem->setAttribute('version', $_[0]); + } + $elem->getAttribute('version'); +} + +sub entries_libxml { + my $feed = shift; + my @res = $feed->{doc}->getElementsByTagNameNS(NS, 'entry') or return; + my @entries; + for my $res (@res) { + my $entry = XML::Atom::Entry->new(Elem => $res->cloneNode(1)); + push @entries, $entry; + } + @entries; +} + +sub entries_xpath { + my $feed = shift; + my $set = $feed->{doc}->find("descendant-or-self::*[local-name()='entry' and namespace-uri()='" . NS . "']"); + my @entries; + for my $elem ($set->get_nodelist) { + ## Delete the link to the parent (feed) element, and append + ## the default Atom namespace. + $elem->del_parent_link; + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $elem->appendNamespace($ns); + my $entry = XML::Atom::Entry->new(Elem => $elem); + push @entries, $entry; + } + @entries; +} + +sub add_entry_libxml { + my $feed = shift; + my($entry) = @_; + $feed->{doc}->getDocumentElement->appendChild($entry->{doc}->getDocumentElement); +} + +sub add_entry_xpath { + my $feed = shift; + my($entry) = @_; + $feed->{doc}->appendChild($entry->{doc}); +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Feed - Atom feed + +=head1 SYNOPSIS + + use XML::Atom::Feed; + use XML::Atom::Entry; + my $feed = XML::Atom::Feed->new; + $feed->title('My Weblog'); + my $entry = XML::Atom::Entry->new; + $entry->title('First Post'); + $entry->content('Post Body'); + $feed->add_entry($entry); + my @entries = $feed->entries; + my $xml = $feed->as_xml; + + ## Get a list of the tags in the feed. + my $links = $feed->link; + + ## Find all of the Atom feeds on a given page, using auto-discovery. + my @uris = XML::Atom::Feed->find_feeds('http://www.example.com/'); + + ## Use auto-discovery to load the first Atom feed on a given page. + my $feed = XML::Atom::Feed->new(URI->new('http://www.example.com/')); + +=head1 USAGE + +=head2 XML::Atom::Feed->new([ $stream ]) + +Creates a new feed object, and if I<$stream> is supplied, fills it with the +data specified by I<$stream>. + +Automatically handles autodiscovery if I<$stream> is a URI (see below). + +Returns the new I object. On failure, returns C. + +I<$stream> can be any one of the following: + +=over 4 + +=item * Reference to a scalar + +This is treated as the XML body of the feed. + +=item * Scalar + +This is treated as the name of a file containing the feed XML. + +=item * Filehandle + +This is treated as an open filehandle from which the feed XML can be read. + +=item * URI object + +This is treated as a URI, and the feed XML will be retrieved from the URI. + +If the content type returned from fetching the content at URI is +I, this method will automatically try to perform auto-discovery +by looking for a IlinkE> tag describing the feed URL. If such +a URL is found, the feed XML will be automatically retrieved. + +If the URI is already of a feed, no auto-discovery is necessary, and the +feed XML will be retrieved and parsed as normal. + +=back + +=head2 XML::Atom::Feed->find_feeds($uri) + +Given a URI I<$uri>, use auto-discovery to find all of the Atom feeds linked +from that page (using IlinkE> tags). + +Returns a list of feed URIs. + +=head2 $feed->link + +If called in scalar context, returns an I object +corresponding to the first IlinkE> tag found in the feed. + +If called in list context, returns a list of I objects +corresponding to all of the IlinkE> tags found in the feed. + +=head2 $feed->add_link($link) + +Adds the link I<$link>, which must be an I object, to +the feed as a new IlinkE> tag. For example: + + my $link = XML::Atom::Link->new; + $link->type('text/html'); + $link->rel('alternate'); + $link->href('http://www.example.com/'); + $feed->add_link($link); + +=head2 $feed->language + +Returns the language of the feed, from I. + +=head2 $feed->author([ $author ]) + +Returns an I object representing the author of the entry, +or C if there is no author information present. + +If I<$author> is supplied, it should be an I object +representing the author. For example: + + my $author = XML::Atom::Person->new; + $author->name('Foo Bar'); + $author->email('foo@bar.com'); + $feed->author($author); + +=head1 AUTHOR & COPYRIGHT + +Please see the I manpage for author, copyright, and license +information. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/Link.pm b/livejournal/cgi-bin/XML/Atom/Link.pm new file mode 100755 index 0000000..86e53ef --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Link.pm @@ -0,0 +1,92 @@ +# $Id: Link.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Link; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); + +use constant NS => 'http://purl.org/atom/ns#'; + +sub new { + my $class = shift; + my $link = bless {}, $class; + $link->init(@_) or return $class->error($link->errstr); + $link; +} + +sub init { + my $link = shift; + my %param = @_ == 1 ? (Body => $_[0]) : @_; + my $elem; + unless ($elem = $param{Elem}) { + if (LIBXML) { + my $doc = XML::LibXML::Document->createDocument('1.0', 'utf-8'); + $elem = $doc->createElementNS(NS, 'link'); + $doc->setDocumentElement($elem); + } else { + $elem = XML::XPath::Node::Element->new('link'); + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $elem->appendNamespace($ns); + } + } + $link->{elem} = $elem; + $link; +} + +sub elem { $_[0]->{elem} } + +sub get { + my $link = shift; + my($attr) = @_; + my $val = $link->elem->getAttribute($attr); + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($val); + } + $val; +} + +sub set { + my $link = shift; + if (@_ == 2) { + my($attr, $val) = @_; + $link->elem->setAttribute($attr, $val); + } elsif (@_ == 3) { + my($ns, $attr, $val) = @_; + my $attribute = "$ns->{prefix}:$attr"; + if (LIBXML) { + $link->elem->setAttributeNS($ns->{uri}, $attribute, $val); + } else { + my $ns = XML::XPath::Node::Namespace->new($ns->{prefix} => $ns->{uri}); + $link->elem->appendNamespace($ns); + $link->elem->setAttribute($attribute => $val); + } + } +} + +sub as_xml { + my $link = shift; + if (LIBXML) { + my $doc = XML::LibXML::Document->new('1.0', 'utf-8'); + $doc->setDocumentElement($link->elem); + return $doc->toString(1); + } else { + return '' . "\n" . + $link->elem->toString; + } +} + +sub DESTROY { } + +use vars qw( $AUTOLOAD ); +sub AUTOLOAD { + (my $var = $AUTOLOAD) =~ s!.+::!!; + no strict 'refs'; + *$AUTOLOAD = sub { + @_ > 1 ? $_[0]->set($var, @_[1..$#_]) : $_[0]->get($var) + }; + goto &$AUTOLOAD; +} + +1; diff --git a/livejournal/cgi-bin/XML/Atom/Person.pm b/livejournal/cgi-bin/XML/Atom/Person.pm new file mode 100755 index 0000000..ed1a087 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Person.pm @@ -0,0 +1,120 @@ +# $Id: Person.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Person; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); +use XML::Atom::Util qw( first ); + +use constant NS => 'http://purl.org/atom/ns#'; + +sub new { + my $class = shift; + my $person = bless {}, $class; + $person->init(@_) or return $class->error($person->errstr); + $person; +} + +sub init { + my $person = shift; + my %param = @_; + my $elem; + unless ($elem = $param{Elem}) { + if (LIBXML) { + my $doc = XML::LibXML::Document->createDocument('1.0', 'utf-8'); + $elem = $doc->createElementNS(NS, 'author'); ## xxx + $doc->setDocumentElement($elem); + } else { + $elem = XML::XPath::Node::Element->new('author'); ## xxx + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $elem->appendNamespace($ns); + } + } + $person->{elem} = $elem; + $person; +} + +sub elem { $_[0]->{elem} } + +sub get { + my $person = shift; + my($name) = @_; + my $node = first($person->elem, NS, $name) or return; + my $val = LIBXML ? $node->textContent : $node->string_value; + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($val); + } + $val; +} + +sub set { + my $person = shift; + my($name, $val) = @_; + my $elem; + unless ($elem = first($person->elem, NS, $name)) { + if (LIBXML) { + $elem = XML::LibXML::Element->new($name); + $elem->setNamespace(NS); + } else { + $elem = XML::XPath::Node::Element->new($name); + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $elem->appendNamespace($ns); + } + $person->elem->appendChild($elem); + } + if (LIBXML) { + $elem->removeChildNodes; + $elem->appendChild(XML::LibXML::Text->new($val)); + } else { + $elem->removeChild($_) for $elem->getChildNodes; + $elem->appendChild(XML::XPath::Node::Text->new($val)); + } + $val; +} + +sub as_xml { + my $person = shift; + if (LIBXML) { + my $doc = XML::LibXML::Document->new('1.0', 'utf-8'); + $doc->setDocumentElement($person->elem); + return $doc->toString(1); + } else { + return '' . "\n" . + $person->elem->toString; + } +} + +sub DESTROY { } + +use vars qw( $AUTOLOAD ); +sub AUTOLOAD { + (my $var = $AUTOLOAD) =~ s!.+::!!; + no strict 'refs'; + *$AUTOLOAD = sub { + @_ > 1 ? $_[0]->set($var, @_[1..$#_]) : $_[0]->get($var) + }; + goto &$AUTOLOAD; +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Person - Author or contributor object + +=head1 SYNOPSIS + + my $author = XML::Atom::Person->new; + $author->email('foo@example.com'); + $author->name('Foo Bar'); + $entry->author($author); + +=head1 DESCRIPTION + +I represents an author or contributor element in an +Atom feed or entry. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/Server.pm b/livejournal/cgi-bin/XML/Atom/Server.pm new file mode 100755 index 0000000..76a5b20 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Server.pm @@ -0,0 +1,538 @@ +# $Id: Server.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Server; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); +use MIME::Base64 qw( encode_base64 decode_base64 ); +use Digest::SHA1 qw( sha1 ); +use XML::Atom::Util qw( first encode_xml textValue ); +use XML::Atom::Entry; + +use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/'; +use constant NS_WSSE => 'http://schemas.xmlsoap.org/ws/2002/07/secext'; +use constant NS_WSU => 'http://schemas.xmlsoap.org/ws/2002/07/utility'; + +sub handler ($$) { + my $class = shift; + my($r) = @_; + require Apache::Constants; + if (lc($r->dir_config('Filter') || '') eq 'on') { + $r = $r->filter_register; + } + my $server = $class->new or die $class->errstr; + $server->{apache} = $r; + $server->run; + return Apache::Constants::OK(); +} + +sub new { + my $class = shift; + my $server = bless { }, $class; + $server->init(@_) or return $class->error($server->errstr); + $server; +} + +sub init { + my $server = shift; + $server->{param} = {}; + unless ($ENV{MOD_PERL}) { + require CGI; + $server->{cgi} = CGI->new(); + } + $server; +} + +sub run { + my $server = shift; + (my $pi = $server->path_info) =~ s!^/!!; + my @args = split /\//, $pi; + for my $arg (@args) { + my($k, $v) = split /=/, $arg, 2; + $server->request_param($k, $v); + } + if (my $action = $server->request_header('SOAPAction')) { + $server->{is_soap} = 1; + $action =~ s/"//g; + my($method) = $action =~ m!/([^/]+)$!; + $server->request_method($method); + } + my $out; + eval { + defined($out = $server->handle_request) or die $server->errstr; + if (defined $out && $server->{is_soap}) { + $out =~ s!^(<\?xml.*?\?>)!!; + $out = < + $out + +SOAP + } + }; + if ($@) { + $out = $server->show_error($@); + } + $server->send_http_header; + $server->print($out); + 1; +} + +sub handle_request; +sub password_for_user; + +sub uri { + my $server = shift; + $ENV{MOD_PERL} ? $server->{apache}->uri : $server->{cgi}->url; +} + +sub path_info { + my $server = shift; + return $server->{__path_info} if exists $server->{__path_info}; + my $path_info; + if ($ENV{MOD_PERL}) { + ## mod_perl often leaves part of the script name (Location) + ## in the path info, for some reason. This should remove it. + $path_info = $server->{apache}->path_info; + if ($path_info) { + my($script_last) = $server->{apache}->location =~ m!/([^/]+)$!; + $path_info =~ s!^/$script_last!!; + } + } else { + $path_info = $server->{cgi}->path_info; + } + $server->{__path_info} = $path_info; +} + +sub request_header { + my $server = shift; + my($key) = @_; + if ($ENV{MOD_PERL}) { + return $server->{apache}->header_in($key); + } else { + ($key = uc($key)) =~ tr/-/_/; + return $ENV{'HTTP_' . $key}; + } +} + +sub request_method { + my $server = shift; + if (@_) { + $server->{request_method} = shift; + } elsif (!exists $server->{request_method}) { + $server->{request_method} = + $ENV{MOD_PERL} ? $server->{apache}->method : $ENV{REQUEST_METHOD}; + } + $server->{request_method}; +} + +sub request_content { + my $server = shift; + unless (exists $server->{request_content}) { + if ($ENV{MOD_PERL}) { + ## Read from $server->{apache} + my $r = $server->{apache}; + my $len = $server->request_header('Content-length'); + $r->read($server->{request_content}, $len); + } else { + ## Read from STDIN + my $len = $ENV{CONTENT_LENGTH} || 0; + read STDIN, $server->{request_content}, $len; + } + } + $server->{request_content}; +} + +sub request_param { + my $server = shift; + my $k = shift; + $server->{param}{$k} = shift if @_; + $server->{param}{$k}; +} + +sub response_header { + my $server = shift; + my($key, $val) = @_; + if ($ENV{MOD_PERL}) { + $server->{apache}->header_out($key, $val); + } else { + unless ($key =~ /^-/) { + ($key = lc($key)) =~ tr/-/_/; + $key = '-' . $key; + } + $server->{cgi_headers}{$key} = $val; + } +} + +sub response_code { + my $server = shift; + $server->{response_code} = shift if @_; + $server->{response_code}; +} + +sub response_content_type { + my $server = shift; + $server->{response_content_type} = shift if @_; + $server->{response_content_type}; +} + +sub send_http_header { + my $server = shift; + my $type = $server->response_content_type || 'application/x.atom+xml'; + if ($ENV{MOD_PERL}) { + $server->{apache}->status($server->response_code || 200); + $server->{apache}->send_http_header($type); + } else { + $server->{cgi_headers}{-status} = $server->response_code || 200; + $server->{cgi_headers}{-type} = $type; + print $server->{cgi}->header(%{ $server->{cgi_headers} }); + } +} + +sub print { + my $server = shift; + if ($ENV{MOD_PERL}) { + $server->{apache}->print(@_); + } else { + CORE::print(@_); + } +} + +sub error { + my $server = shift; + my($code, $msg) = @_; + $server->response_code($code) if ref($server); + return $server->SUPER::error($msg); +} + +sub show_error { + my $server = shift; + my($err) = @_; + chomp($err = encode_xml($err)); + if ($server->{is_soap}) { + my $code = $server->response_code; + if ($code >= 400) { + $server->response_code(500); + } + return < + + + $code + $err + + + +FAULT + } else { + return < +$err +ERR + } +} + +sub get_auth_info { + my $server = shift; + my %param; + if ($server->{is_soap}) { + my $xml = $server->xml_body; + my $auth = first($xml, NS_WSSE, 'UsernameToken'); + $param{Username} = textValue($auth, NS_WSSE, 'Username'); + $param{PasswordDigest} = textValue($auth, NS_WSSE, 'Password'); + $param{Nonce} = textValue($auth, NS_WSSE, 'Nonce'); + $param{Created} = textValue($auth, NS_WSSE, 'Created'); + } else { + my $req = $server->request_header('X-WSSE') + or return $server->auth_failure(401, 'X-WSSE authentication required'); + $req =~ s/^(?:WSSE|UsernameToken) //; + for my $i (split /,\s*/, $req) { + my($k, $v) = split /=/, $i, 2; + $v =~ s/^"//; + $v =~ s/"$//; + $param{$k} = $v; + } + } + \%param; +} + +sub authenticate { + my $server = shift; + my $auth = $server->get_auth_info or return; + for my $f (qw( Username PasswordDigest Nonce Created )) { + return $server->auth_failure(400, "X-WSSE requires $f") + unless $auth->{$f}; + } + my $password = $server->password_for_user($auth->{Username}); + defined($password) or return $server->auth_failure(403, 'Invalid login'); + my $expected = encode_base64(sha1( + decode_base64($auth->{Nonce}) . $auth->{Created} . $password + ), ''); + return $server->auth_failure(403, 'Invalid login') + unless $expected eq $auth->{PasswordDigest}; + return 1; +} + +sub auth_failure { + my $server = shift; + $server->response_header('WWW-Authenticate', 'WSSE profile="UsernameToken"'); + return $server->error(@_); +} + +sub xml_body { + my $server = shift; + unless (exists $server->{xml_body}) { + if (LIBXML) { + my $parser = XML::LibXML->new; + $server->{xml_body} = + $parser->parse_string($server->request_content); + } else { + $server->{xml_body} = + XML::XPath->new(xml => $server->request_content); + } + } + $server->{xml_body}; +} + +sub atom_body { + my $server = shift; + my $atom; + if ($server->{is_soap}) { + my $xml = $server->xml_body; + $atom = XML::Atom::Entry->new(Doc => first($xml, NS_SOAP, 'Body')) + or return $server->error(500, XML::Atom::Entry->errstr); + } else { + $atom = XML::Atom::Entry->new(Stream => \$server->request_content) + or return $server->error(500, XML::Atom::Entry->errstr); + } + $atom; +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Server - A server for the Atom API + +=head1 SYNOPSIS + + package My::Server; + use base qw( XML::Atom::Server ); + sub handle_request { + my $server = shift; + $server->authenticate or return; + my $method = $app->request_method; + if ($method eq 'POST') { + return $server->new_post; + } + ... + } + + my %Passwords; + sub password_for_user { + my $server = shift; + my($username) = @_; + $Passwords{$username}; + } + + sub new_post { + my $server = shift; + my $entry = $server->atom_body or return; + ## $entry is an XML::Atom::Entry object. + ## ... Save the new entry ... + } + + package main; + my $server = My::Server->new; + $server->run; + +=head1 DESCRIPTION + +I provides a base class for Atom API servers. It handles +all core server processing, both the SOAP and REST formats of the protocol, +and WSSE authentication. It can also run as either a mod_perl handler or as +part of a CGI program. + +It does not provide functions specific to any particular implementation, +such as posting an entry, retrieving a list of entries, deleting an entry, etc. +Implementations should subclass I, overriding the +I method, and handle all functions such as this themselves. + +=head1 SUBCLASSING + +=head2 Request Handling + +Subclasses of I must override the I +method to perform all request processing. The implementation must set all +response headers, including the response code and any relevant HTTP headers, +and should return a scalar representing the response body to be sent back +to the client. + +For example: + + sub handle_request { + my $server = shift; + my $method = $server->request_method; + if ($method eq 'POST') { + return $server->new_post; + } + ## ... handle GET, PUT, etc + } + + sub new_post { + my $server = shift; + my $entry = $server->atom_body or return; + my $id = save_this_entry($entry); ## Implementation-specific + $server->response_header(Location => $app->uri . '/entry_id=' . $id); + $server->response_code(201); + $server->response_content_type('application/x.atom+xml'); + return serialize_entry($entry); ## Implementation-specific + } + +=head2 Authentication + +Servers that require authentication for posting or retrieving entries or +feeds should override the I method. Given a username +(from the WSSE header), I should return that user's +password in plaintext. This will then be combined with the nonce and the +creation time to generate the digest, which will be compared with the +digest sent in the WSSE header. If the supplied username doesn't exist in +your user database or alike, just return C. + +For example: + + my %Passwords = ( foo => 'bar' ); ## The password for "foo" is "bar". + sub password_for_user { + my $server = shift; + my($username) = @_; + $Passwords{$username}; + } + +=head1 METHODS + +I provides a variety of methods to be used by subclasses +for retrieving headers, content, and other request information, and for +setting the same on the response. + +=head2 Client Request Parameters + +=over 4 + +=item * $server->uri + +Returns the URI of the Atom server implementation. + +=item * $server->request_method + +Returns the name of the request method sent to the server from the client +(for example, C, C, etc). Note that if the client sent the +request in a SOAP envelope, the method is obtained from the I +HTTP header. + +=item * $server->request_header($header) + +Retrieves the value of the HTTP request header I<$header>. + +=item * $server->request_content + +Returns a scalar containing the contents of a POST or PUT request from the +client. + +=item * $server->request_param($param) + +I automatically parses the PATH_INFO sent in the request +and breaks it up into key-value pairs. This can be used to pass parameters. +For example, in the URI + + http://localhost/atom-server/entry_id=1 + +the I parameter would be set to C<1>. + +I returns the value of the value of the parameter I<$param>. + +=back + +=head2 Setting up the Response + +=over 4 + +=item * $server->response_header($header, $value) + +Sets the value of the HTTP response header I<$header> to I<$value>. + +=item * $server->response_code([ $code ]) + +Returns the current response code to be sent back to the client, and if +I<$code> is given, sets the response code. + +=item * $server->response_content_type([ $type ]) + +Returns the current I header to be sent back to the client, and +I<$type> is given, sets the value for that header. + +=back + +=head2 Processing the Request + +=over 4 + +=item * $server->authenticate + +Attempts to authenticate the request based on the authentication +information present in the request (currently just WSSE). This will call +the I method in the subclass to obtain the cleartext +password for the username given in the request. + +=item * $server->atom_body + +Returns an I object containing the entry sent in the +request. + +=back + +=head1 USAGE + +Once you have defined your server subclass, you can set it up either as a +CGI program or as a mod_perl handler. + +A simple CGI program would look something like this: + + #!/usr/bin/perl -w + use strict; + + use My::Server; + my $server = My::Server->new; + $server->run; + +A simple mod_perl handler configuration would look something like this: + + PerlModule My::Server + + SetHandler perl-script + PerlHandler My::Server + + +=head1 ERROR HANDLING + +If you wish to return an error from I, you can use the +built-in I method: + + sub handle_request { + my $server = shift; + ... + return $server->error(500, "Something went wrong"); + } + +This will be returned to the client with a response code of 500 and an +error string of C. Errors are automatically +serialized into SOAP faults if the incoming request is enclosed in a SOAP +envelope. + +=head1 AUTHOR & COPYRIGHT + +Please see the I manpage for author, copyright, and license +information. + +=cut diff --git a/livejournal/cgi-bin/XML/Atom/Thing.pm b/livejournal/cgi-bin/XML/Atom/Thing.pm new file mode 100755 index 0000000..0eec8ad --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Thing.pm @@ -0,0 +1,322 @@ +# $Id: Thing.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Thing; +use strict; + +use XML::Atom; +use base qw( XML::Atom::ErrorHandler ); +use XML::Atom::Util qw( first nodelist remove_default_ns ); +use XML::Atom::Link; +use LWP::UserAgent; +BEGIN { + if (LIBXML) { + *init = \&init_libxml; + *set = \&set_libxml; + *link = \&link_libxml; + } else { + *init = \&init_xpath; + *set = \&set_xpath; + *link = \&link_xpath; + } +} + +use constant NS => 'http://purl.org/atom/ns#'; + +sub new { + my $class = shift; + my $atom = bless {}, $class; + $atom->init(@_) or return $class->error($atom->errstr); + $atom; +} + +sub init_libxml { + my $atom = shift; + my %param = @_ == 1 ? (Stream => $_[0]) : @_; + if (%param) { + if (my $stream = $param{Stream}) { + my $parser = XML::LibXML->new; + if (ref($stream) eq 'SCALAR') { + $atom->{doc} = $parser->parse_string($$stream); + } elsif (ref($stream)) { + $atom->{doc} = $parser->parse_fh($stream); + } else { + $atom->{doc} = $parser->parse_file($stream); + } + } elsif (my $doc = $param{Doc}) { + $atom->{doc} = $doc; + } elsif (my $elem = $param{Elem}) { + $atom->{doc} = XML::LibXML::Document->createDocument('1.0', 'utf-8'); + $atom->{doc}->setDocumentElement($elem); + } + } else { + my $doc = $atom->{doc} = XML::LibXML::Document->createDocument('1.0', 'utf-8'); + my $root = $doc->createElementNS(NS, $atom->element_name); + $doc->setDocumentElement($root); + } + $atom; +} + +sub init_xpath { + my $atom = shift; + my %param = @_ == 1 ? (Stream => $_[0]) : @_; + my $elem_name = $atom->element_name; + if (%param) { + if (my $stream = $param{Stream}) { + my $xp; + if (ref($stream) eq 'SCALAR') { + $xp = XML::XPath->new(xml => $$stream); + } elsif (ref($stream)) { + $xp = XML::XPath->new(ioref => $stream); + } else { + $xp = XML::XPath->new(filename => $stream); + } + my $set = $xp->find('/' . $elem_name); + unless ($set && $set->size) { + $set = $xp->find('/'); + } + $atom->{doc} = ($set->get_nodelist)[0]; + } elsif (my $doc = $param{Doc}) { + $atom->{doc} = $doc; + } elsif (my $elem = $param{Elem}) { + my $xp = XML::XPath->new(context => $elem); + my $set = $xp->find('/' . $elem_name); + unless ($set && $set->size) { + $set = $xp->find('/'); + } + $atom->{doc} = ($set->get_nodelist)[0]; + } + } else { + my $xp = XML::XPath->new; + $xp->set_namespace(atom => NS); + $atom->{doc} = XML::XPath::Node::Element->new($atom->element_name); + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $atom->{doc}->appendNamespace($ns); + } + $atom; +} + +sub get { + my $atom = shift; + my($ns, $name) = @_; + my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; + my $node = first($atom->{doc}, $ns_uri, $name); + return unless $node; + my $val = LIBXML ? $node->textContent : $node->string_value; + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($val); + } + $val; +} + +sub getlist { + my $atom = shift; + my($ns, $name) = @_; + my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; + my @node = nodelist($atom->{doc}, $ns_uri, $name); + map { + my $val = LIBXML ? $_->textContent : $_->string_value; + if ($] >= 5.008) { + require Encode; + Encode::_utf8_off($val); + } + $val; + } @node; +} + +sub set_libxml { + my $atom = shift; + my($ns, $name, $val, $attr) = @_; + my $elem; + my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; + unless ($elem = first($atom->{doc}, $ns_uri, $name)) { + $elem = $atom->{doc}->createElementNS($ns_uri, $name); + $atom->{doc}->getDocumentElement->appendChild($elem); + } + if ($ns ne NS) { + $atom->{doc}->getDocumentElement->setNamespace($ns->{uri}, $ns->{prefix}, 0); + } + if (ref($val) =~ /Element$/) { + $elem->appendChild($val); + } elsif (defined $val) { + $elem->removeChildNodes; + my $text = XML::LibXML::Text->new($val); + $elem->appendChild($text); + } + if ($attr) { + while (my($k, $v) = each %$attr) { + $elem->setAttribute($k, $v); + } + } + $val; +} + +sub set_xpath { + my $atom = shift; + my($ns, $name, $val, $attr) = @_; + my $elem; + my $ns_uri = ref($ns) eq 'XML::Atom::Namespace' ? $ns->{uri} : $ns; + unless ($elem = first($atom->{doc}, $ns_uri, $name)) { + $elem = XML::XPath::Node::Element->new($name); + if ($ns ne NS) { + my $ns = XML::XPath::Node::Namespace->new($ns->{prefix} => $ns->{uri}); + $elem->appendNamespace($ns); + } + $atom->{doc}->appendChild($elem); + } + if (ref($val) =~ /Element$/) { + $elem->appendChild($val); + } elsif (defined $val) { + $elem->removeChild($_) for $elem->getChildNodes; + my $text = XML::XPath::Node::Text->new($val); + $elem->appendChild($text); + } + if ($attr) { + while (my($k, $v) = each %$attr) { + $elem->setAttribute($k, $v); + } + } + $val; +} + +sub add_link { + my $thing = shift; + my($link) = @_; + my $elem; + if (ref($link) eq 'XML::Atom::Link') { + if (LIBXML) { + $thing->{doc}->getDocumentElement->appendChild($link->elem); + } else { + $thing->{doc}->appendChild($link->elem); + } + } else { + if (LIBXML) { + $elem = $thing->{doc}->createElementNS(NS, 'link'); + $thing->{doc}->getDocumentElement->appendChild($elem); + } else { + $elem = XML::XPath::Node::Element->new('link'); + my $ns = XML::XPath::Node::Namespace->new('#default' => NS); + $elem->appendNamespace($ns); + $thing->{doc}->appendChild($elem); + } + } + if (ref($link) eq 'HASH') { + for my $k (qw( type rel href title )) { + my $v = $link->{$k} or next; + $elem->setAttribute($k, $v); + } + } +} + +sub link_libxml { + my $thing = shift; + if (wantarray) { + my @res = $thing->{doc}->getDocumentElement->getChildrenByTagNameNS(NS, 'link'); + my @links; + for my $elem (@res) { + push @links, XML::Atom::Link->new(Elem => $elem); + } + return @links; + } else { + my $elem = first($thing->{doc}, NS, 'link') or return; + return XML::Atom::Link->new(Elem => $elem); + } +} + +sub link_xpath { + my $thing = shift; + if (wantarray) { + my $set = $thing->{doc}->find("*[local-name()='link' and namespace-uri()='" . NS . "']"); + my @links; + for my $elem ($set->get_nodelist) { + push @links, XML::Atom::Link->new(Elem => $elem); + } + return @links; + } else { + my $elem = first($thing->{doc}, NS, 'link') or return; + return XML::Atom::Link->new(Elem => $elem); + } +} + +sub author { + my $thing = shift; + $thing->_element('XML::Atom::Person', 'author', @_); +} + +sub as_xml { + my $doc = $_[0]->{doc}; + if (eval { require XML::LibXSLT }) { + my $parser = XML::LibXML->new; + my $xslt = XML::LibXSLT->new; + my $style_doc = $parser->parse_string(<<'EOX'); + + + + + + + + +EOX + my $sheet = $xslt->parse_stylesheet($style_doc); + my $results = $sheet->transform($doc); + return $sheet->output_string($results); + } else { + remove_default_ns($doc->getDocumentElement); + return $doc->toString(LIBXML ? 1 : 0); + } +} + +sub _element { + my $thing = shift; + my($class, $name) = (shift, shift); + my $root = LIBXML ? $thing->{doc}->getDocumentElement : $thing->{doc}; + if (@_) { + my $obj = shift; + if (my $node = first($thing->{doc}, NS, $name)) { + $root->removeChild($node); + } + my $elem = LIBXML ? + $thing->{doc}->createElementNS(NS, $name) : + XML::XPath::Node::Element->new($name); + $root->appendChild($elem); + if (LIBXML) { + for my $child ($obj->elem->childNodes) { + $elem->appendChild($child->cloneNode(1)); + } + for my $attr ($obj->elem->attributes) { + next unless ref($attr) eq 'XML::LibXML::Attr'; + $elem->setAttribute($attr->getName, $attr->getValue); + } + } else { + for my $child ($obj->elem->getChildNodes) { + $elem->appendChild($child); + } + for my $attr ($obj->elem->getAttributes) { + $elem->appendAttribute($attr); + } + } + $obj->{elem} = $elem; + $thing->{'__' . $name} = $obj; + } else { + unless (exists $thing->{'__' . $name}) { + my $elem = first($thing->{doc}, NS, $name) or return; + $thing->{'__' . $name} = $class->new(Elem => $elem); + } + } + $thing->{'__' . $name}; +} + +sub DESTROY { } + +use vars qw( $AUTOLOAD ); +sub AUTOLOAD { + (my $var = $AUTOLOAD) =~ s!.+::!!; + no strict 'refs'; + *$AUTOLOAD = sub { + @_ > 1 ? $_[0]->set(NS, $var, @_[1..$#_]) : $_[0]->get(NS, $var) + }; + goto &$AUTOLOAD; +} + +1; diff --git a/livejournal/cgi-bin/XML/Atom/Util.pm b/livejournal/cgi-bin/XML/Atom/Util.pm new file mode 100755 index 0000000..4462f21 --- /dev/null +++ b/livejournal/cgi-bin/XML/Atom/Util.pm @@ -0,0 +1,106 @@ +# $Id: Util.pm,v 1.1 2005/04/15 17:37:32 bradfitz Exp $ + +package XML::Atom::Util; +use strict; + +use XML::Atom; +use vars qw( @EXPORT_OK @ISA ); +use Exporter; +@EXPORT_OK = qw( first nodelist textValue iso2dt encode_xml remove_default_ns ); +@ISA = qw( Exporter ); + +sub first { + my @nodes = nodelist(@_); + return unless @nodes; + return $nodes[0]; +} + +sub nodelist { + if (LIBXML) { + return $_[1] ? $_[0]->getElementsByTagNameNS($_[1], $_[2]) : + $_[0]->getElementsByTagName($_[2]); + } else { + my $set = $_[1] ? + $_[0]->find("descendant::*[local-name()='$_[2]' and namespace-uri()='$_[1]']") : + $_[0]->find("descendant::$_[2]"); + return unless $set && $set->isa('XML::XPath::NodeSet'); + return $set->get_nodelist; + } +} + +sub textValue { + my $node = first(@_) or return; + LIBXML ? $node->textContent : $node->string_value; +} + +sub iso2dt { + my($iso) = @_; + return unless $iso =~ /^(\d{4})(?:-?(\d{2})(?:-?(\d\d?)(?:T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}:\d{2}))?)?)?)?/; + my($y, $mo, $d, $h, $m, $s, $zone) = + ($1, $2 || 1, $3 || 1, $4 || 0, $5 || 0, $6 || 0, $7); + require DateTime; + my $dt = DateTime->new( + year => $y, + month => $mo, + day => $d, + hour => $h, + minute => $m, + second => $s, + time_zone => 'UTC', + ); + if ($zone && $zone ne 'Z') { + my $seconds = DateTime::TimeZone::offset_as_seconds($zone); + $dt->subtract(seconds => $seconds); + } + $dt; +} + +my %Map = ('&' => '&', '"' => '"', '<' => '<', '>' => '>', + '\'' => '''); +my $RE = join '|', keys %Map; + +sub encode_xml { + my($str) = @_; + $str =~ s!($RE)!$Map{$1}!g; + $str; +} + +sub remove_default_ns { + my($node) = @_; + $node->setNamespace('http://www.w3.org/1999/xhtml', '') + if $node->nodeName =~ /^default:/ && ref($node) =~ /Element$/; + for my $n ($node->childNodes) { + remove_default_ns($n); + } +} + +1; +__END__ + +=head1 NAME + +XML::Atom::Util - Utility functions + +=head1 SYNOPSIS + + use XML::Atom::Util qw( iso2dt ); + my $dt = iso2dt($entry->issued); + +=head1 USAGE + +=head2 iso2dt($iso) + +Transforms the ISO-8601 date I<$iso> into a I object and returns +the I object. + +=head2 encode_xml($str) + +Encodes characters with special meaning in XML into entities and returns +the encoded string. + +=head1 AUTHOR & COPYRIGHT + +Please see the I manpage for author, copyright, and license +information. + +=cut diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.enc b/livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.enc new file mode 100755 index 0000000000000000000000000000000000000000..326cae822ebb09fdac9a8588df10e49529286e8f GIT binary patch literal 1072 zcmb8uM^0676u@D@V{a4z6=@F-RTQvLY@lF8#oiTr7kh652M!!qHsI8mapErAhzl@r zVEkTOfiL;;Pj2qZ&HbHo|NQ*@^ITZhGit6{}gpTKec` zfI-%=o(*hd6GIHMnJtVk%2u|qogM6C7h~*Z4|^GBANx7LK@M@4BOK)z$2q}CPH~zu zOmLQSoaX`;xx{6zaFuIZ=LR>q#U!`6LviBwxX%L~@`%Sg;VI8}&I?}h>R;+Cb((9M zWtv}_S(;OtMe3cJrf&I~H@xK?@A<$-J{e!5^RrQ!cfq_1+7-M{q4++oH#a%I@{RBO za{oB`rG8O7HB1dt!_+V}Obt`R)G#$n4O7F^Fg45xG>j6bj;UjMZhCI&m^!A8sblJx zI%cus7ymKG=%xoV5APcGCq`JsDE$mDh#d+o!VZNU3Of|`Ach!bGxjL#U-UADy@@{b z2)h&ZDeP9*sj$aUMma6$A5|=)lEgeh)6g_(F`KBPo(6me(TKiLpqXkaFu&-ehBkaV J(M~HJe*tF$QF8zQ literal 0 HcmV?d00001 diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.xml b/livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.xml new file mode 100755 index 0000000..f1584d6 --- /dev/null +++ b/livejournal/cgi-bin/XML/Parser/Encodings/koi8-r.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.enc b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.enc new file mode 100755 index 0000000000000000000000000000000000000000..e64960c6d5bea526a52a5c6b2ce1aaf1c25c5c9c GIT binary patch literal 1072 zcma*l=~9jX7zW^$r?P}LC84)XlA=9J`zEFA`z}kCLdfnEI0HWnV=TiD{BRCV#2NU3 z>pcVC%r(#VHhnYibKlROU%!7Y&d$xuFD^8-w05*){NE?jzh#k4kV7tcEMY0jSWZ4G zSjj31D5QvDN?1)PWvro`wN$W<^=zP$get13p_V!}QqLwD*i0i^Xrh^|Y$M&Xl{VVx zpp!1T+0G7jvWp&i>7$q>7tu7_cXhm?4pNW`sinXL53J+gi*$DzcG&cjR_`k IzcI!1KV)!DV*mgE literal 0 HcmV?d00001 diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.xml b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.xml new file mode 100755 index 0000000..e3ff4f1 --- /dev/null +++ b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1251.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.enc b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.enc new file mode 100755 index 0000000000000000000000000000000000000000..9abd0d78bf4245d5208fda7694f0e9d07a6aab44 GIT binary patch literal 1072 zcma*lg>Dc*6a~;O?rudFcc-|!ON+ZZEl{91|G*dE?(XjH?(VKd%4zxoyyWC%H?x_Y zcjxcx#B&K_Vu!~i#8<9fBdSKk|5adFDpHe%w4@_F8OTT`GLwa@WFtE{$Vo18lZU+I zBR>U*q#%VTOc9DwjF94#pd_UzO&Q8kj`CEXB9*926{=E=>Lj1FCbfv7Hg%{=J?hhd zhBTrvO=wCpn$v=ow4ya_XiGcV(}9k3qBC9SN;jg3p*ub3NiTZShraZqKLZ%ZAO|rna*v|nDa)`qm z;V8}>ahwyJ literal 0 HcmV?d00001 diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.xml b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.xml new file mode 100755 index 0000000..4d6d7ad --- /dev/null +++ b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1252.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/cgi-bin/XML/Parser/Encodings/windows-1255.enc b/livejournal/cgi-bin/XML/Parser/Encodings/windows-1255.enc new file mode 100755 index 0000000000000000000000000000000000000000..87ee299fd75ab8af5d518173fb9b2a0094c8f726 GIT binary patch literal 1072 zcma*l)oxZn6b8_?FgPvlawsl^QYg^k?(S|yiWDhOoOj>}kl@9&!6D(2;O;IrSVF=D zu>JrEDK|{AvNJjJ<;={U@9)1|&dbipT9lWY(mE|YJ?{TTyk!X#p(uf36sH6wDMe|@ zP?kiJC`WlJP?1VhrV3T5Ms;dXlUmfK4t0sBM>6$kKtmeQm?ku(8O>=y3N2|xDy>PQ z4Q+{?yB+Q6Kn9s~q!XR#LRY%cogVb07rp62U;5FX0SsgigBik5hB2HGjARs}8N*n{ zF`fxbWD=8^!c?X)of*s|i&@NO4s*$79`jkiLULHdVwSL!T$Zt%738s!Rjg(WYgxy7 zHn{%$ABL(w@f%friQIh@p)U!S)YRW=GGevx@Li81J&yD?(%VQcBX1${77`w4Z*nYS zp80P!Zj*g%W(!-b*{yD4J3H9PE^f1jeD<=B{T$#Rhd9g;j&h9SoS=ZOoa7XzIm1~` zT|USM`5+(UgM5$=@fMLzJ6PkiP};WPg|_x%c2xyE&F taFbg&bGXA@?r|UY86NV8$2{RF&v?!YUh<09yx}eH{`}V+Cz2GK{{*=q%i#b3 literal 0 HcmV?d00001 diff --git a/livejournal/cgi-bin/XML/README.txt b/livejournal/cgi-bin/XML/README.txt new file mode 100755 index 0000000..00c0e8b --- /dev/null +++ b/livejournal/cgi-bin/XML/README.txt @@ -0,0 +1,4 @@ +XML::Atom is not part of the LiveJournal codebase. It's being +sucked in here to avoid library incompatibilities. Long story. + + diff --git a/livejournal/cgi-bin/bml/scheme/bluewhite.look b/livejournal/cgi-bin/bml/scheme/bluewhite.look new file mode 100755 index 0000000..8cc44b2 --- /dev/null +++ b/livejournal/cgi-bin/bml/scheme/bluewhite.look @@ -0,0 +1,263 @@ +# +# Welcome to GENERIC.LOOK for the WhiteBlue scheme +# +# by.... +# Brad Fitzpatrick +# brad@danga.com +# + +######################### little stuff + +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT +SOERROR=>
    %%data%%
    +EMAILEX=>
    %%data%%
    + +######################### choices stuff + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F}

    + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{Fps} + + +%%TITLE%% +%%head%% +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> + + + + + + + +
    + + + + + + + +
      +'; +} +return ""; +_code?> + + + "; + } + return ""; +_code?> +
    + +
    +
    + + + + + + + + + + + + + + + + +
    + + +
    + + +"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name
    "; + } else { + $$ret .= "$name
    "; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name
    "; + } else { + $$ret .= "{'uri'}\">$name
    "; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
    + +
    +
    +
    + +
    + +
    +%%BODY%% + +
     
    +  + 
    + + + + + + +
    + + Privacy Policy - + COPPA
    + Legal Disclaimer - + Site Map
    +
    +
    + + + +<=PAGE + diff --git a/livejournal/cgi-bin/bml/scheme/global.look b/livejournal/cgi-bin/bml/scheme/global.look new file mode 100755 index 0000000..ff90c1c --- /dev/null +++ b/livejournal/cgi-bin/bml/scheme/global.look @@ -0,0 +1,365 @@ +_parent=>../../lj-bml-blocks.pl + +loginboxstyle=>{Ss}background: url(/userinfo.gif) no-repeat; background-color: #fff; background-position: 0px 1px; padding-left: 18px; color: #00C; font-weight: bold; +commloginboxstyle=>{Ss}background: url(/community.gif) no-repeat; background-color: #fff; background-position: 0px 2px; padding-left: 19px; color: #00C; font-weight: bold; + +SECURITYPRIVATE=>{Ss} +SECURITYPROTECTED=>{Ss} +LJUSER=>{DRs}userinfo%%data%% +LJCOMM=>{DRs}userinfo%%data%% +LJUSERF=>{DRs}userinfo%%data%% +HELP=>{DR}(help) +INERR=>{DR}%%data%% +SOERROR=>{DR}
    %%data%%
    +EMAILEX=>
    %%data%%
    + +ENTRYFORMCSS<= +{Ss} + +<=ENTRYFORMCSS + +NEEDLOGIN<= + h1?> + p?> +<=NEEDLOGIN + +BADINPUT<= + h1?> + p?> +<=BADINPUT + +REQUIREPOST=> + +LOAD_PAGE_INFO<= + 'Home', + 'uri' => '/', + 'match' => "^/(index\\.bml)?(\\?.*)?\$", + 'children' => [ + { 'name' => 'Create Journal', + 'uri' => '/create.bml', }, + { 'name' => 'Update', + 'uri' => '/update.bml', +# 'children' => [ +# { 'name' => 'Full Update', +# 'uri' => '/update.bml?mode=full', } +# ], + }, + { 'name' => 'Download', + 'uri' => '/download/', }, + ], + }, + { 'name' => 'LiveJournal', + 'children' => [ + { 'name' => 'News', + 'match' => '^/news\\.bml\$', + 'uri' => '/news.bml', }, + { 'name' => 'Paid Accounts', + 'uri' => '/paidaccounts/', + 'recursematch' => '^/paidaccounts/', + 'children' => [ + { 'name' => 'Is this safe?', + 'uri' => '/paidaccounts/whysafe.bml', }, + { 'name' => 'Progress', + 'uri' => '/paidaccounts/progress.bml', }, + ], + }, +# { 'name' => 'To-Do list', +# 'uri' => '/todo.bml', }, + { 'name' => 'Contributors', + 'uri' => '/contributors.bml', }, + ], + }, + { 'name' => 'Customize', + 'children' => [ + { 'name' => 'Modify Journal', + 'uri' => '/modify.bml', }, + { 'name' => 'Create Style', + 'uri' => '/createstyle.bml', }, + { 'name' => 'Edit Style', + 'uri' => '/editstyle.bml', }, + ], + }, + { 'name' => 'Find Users', + 'children' => [ + { 'name' => 'Random!', + 'uri' => '/random.bml', }, + { 'name' => 'By Region', + 'uri' => '/directory.bml', }, + { 'name' => 'By Interest', + 'uri' => '/interests.bml', }, + { 'name' => 'Search', + 'uri' => '/directorysearch.bml', } + ], }, + { 'name' => 'Edit ...', + 'children' => [ + { 'name' => 'Personal Info &', + 'uri' => '/editinfo.bml', }, + { 'name' => 'Settings', cont => 1, + 'uri' => '/editinfo.bml', }, + { 'name' => 'Your Friends', + 'uri' => '/editfriends.bml', }, + { 'name' => 'Old Entries', + 'uri' => '/editjournal.bml', }, + { 'name' => 'Your Pictures', + 'uri' => '/editpics.bml', }, + { 'name' => 'Your Password', + 'uri' => '/changepassword.bml', }, + ], + }, + { 'name' => 'Developer Area', + 'uri' => '/developer/', + 'match' => "^/developer/\$", + 'recursematch' => "^/developer/", + 'children' => [ + { 'name' => 'Style System', + 'uri' => '/developer/styles.bml', + 'children' => [ + { 'name' => 'View Types', + 'uri' => '/developer/views.bml', }, + { 'name' => 'Variable List', + 'uri' => '/developer/varlist.bml', }, + ], + }, + { 'name' => 'Embedding', + 'uri' => '/developer/embedding.bml', }, + { 'name' => 'Protocol', + 'uri' => '/developer/protocol.bml', + 'children' => [ + { 'name' => 'Mode List', + 'uri' => '/developer/modelist.bml', } + ], + }, + ], + }, + { 'name' => 'Need Help?', + 'children' => [ + { 'name' => 'Lost Password?', + 'uri' => '/lostinfo.bml', }, + { 'name' => 'Freq. Asked', + 'uri' => '/support/faq.bml', }, + { 'name' => 'Questions', + 'uri' => '/support/faq.bml', cont => 1, }, + { 'name' => 'Support Area', + 'uri' => '/support/', }, + ], + }, + ); + + my $remote = LJ::get_remote(); + my $remuser = $remote ? $remote->{'user'} : ""; + my $uri = BML::get_uri(); + if ($remuser ne "" && $uri ne "/logout.bml") + { + my $subdomain = $remuser; + $subdomain =~ s/_/-/g; + unshift @sidebar, { 'name' => "Hello, $remuser!", + 'children' => [ + { 'name' => 'Your Journal', + 'children' => [ + { 'name' => 'Recent', + 'uri' => "/users/$remuser/", }, + { 'name' => 'Calendar', + 'uri' => "/users/$remuser/calendar", }, + { 'name' => 'Friends', + 'uri' => "/users/$remuser/friends", + 'extra' => "/friendsfilter.bml", + }, + ], + }, + { 'name' => 'User Info', + 'uri' => "/userinfo.bml?user=$remuser", }, + { 'name' => 'Memories', + 'uri' => "/memories.bml?user=$remuser", }, + { 'name' => 'Logout', + 'uri' => '/logout.bml', }, + ] + }; + } elsif ($uri ne "/login.bml") { + unshift @sidebar, { 'name' => "Log In", + 'uri' => '/login.bml', } + } + +return ""; +_code?> +<=LOAD_PAGE_INFO + +AL=>{P}%%data2%% +AWAYLINK=>{P}%%data2%% + +H1=>{D}

    %%data%%

    +H2=>{D}

    %%data%%

    + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%data%% + +GRIN=>{S}<grin> +HR=>{S}


    + +NEWLINE=>{S}
         +P=>{D}

    %%data%%

    + +STANDOUT<= +{D}
    +
    +%%data%% +
    +
    +<=STANDOUT + +ERRORBAR<= +{D}
    +
    +%%data%% +
    +
    +<=ERRORBAR + +WARNINGBAR<= +{D}
    +
    +%%data%% +
    +
    +<=WARNINGBAR + +BADCONTENT<= + h1?> + p?> +<=BADCONTENT + +DE<= +%%data%% +<=DE + +EMCOLOR=>{S}#c0c0c0 +HOTCOLOR=>{S}#ff0000 +EMCOLORLITE=>{S}#e2e2e2 +ALTCOLOR1=>{S}#eeeeee +ALTCOLOR2=>{S}#dddddd +screenedbarcolor=>{S}#d0d0d0 + +CHOICE=>{P}
    %%data1%%
    %%data3%% + +CHOICES<= +{F} + + + + +
    +
    +%%items%% +
    +
    +
    +%%itemsb%% +
    +
    +<=CHOICES + +PAGE<= +{Fp} +%%title%%%%head%% + +%%body%% + + +<=PAGE + +BREADCRUMBS<= +{Fp}[3]; # no blank crumbs + if ($crumb->[3] eq 'dynamic') { + # dynamic + unshift @ret, "$crumb->[0]"; + $count++; + } else { + # non-dynamic + unshift @ret, $count++ == 0 ? + "$ML{'crumb.'.$crumb->[3]}" : + $crumb->[1] ne '' ? + "[1]\">$ML{'crumb.'.$crumb->[3]}" : + "$ML{'crumb.'.$crumb->[3]}"; + } + } + return "
    " . join(" : ", @ret) . "
    "; +_code?> +<=BREADCRUMBS diff --git a/livejournal/cgi-bin/bml/scheme/lynx.look b/livejournal/cgi-bin/bml/scheme/lynx.look new file mode 100755 index 0000000..d8c1903 --- /dev/null +++ b/livejournal/cgi-bin/bml/scheme/lynx.look @@ -0,0 +1,55 @@ +### +### Lynx Scheme - Very simple for text browsers +### + +_parent=>global.look + +h1=>{D}

    %%DATA%%

    +h2=>{D}

    %%DATA%%

    + +loginboxstyle=>{S} +commloginboxstyle=>{S} + +page<= +{Fps} + + + + + +[0]' href='$parentcrumb->[1]' />"; + } + return $crumb_up; +_code?> + +<?_code { + my $elhash = $_[2]; + return $elhash->{'WINDOWTITLE'} || $elhash->{'TITLE'}; +} _code?> +%%HEAD%% + + + + +%%BODY%% + +
    + +

    [ | | {'user'}/'>$ML{'lynx.nav.recent'} | $ML{'lynx.nav.friends'} | "; + } +_code?>/ | | ]

    + + + +<=page diff --git a/livejournal/cgi-bin/bml/scheme/opalcat.look b/livejournal/cgi-bin/bml/scheme/opalcat.look new file mode 100755 index 0000000..f8f5cc8 --- /dev/null +++ b/livejournal/cgi-bin/bml/scheme/opalcat.look @@ -0,0 +1,225 @@ +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +DE<= +%%DATA%% +<=DE + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT + +######################### choices stuff + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F}

    + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +################################################################################## +################################### MAIN PAGE #################################### +################################################################################## + +PAGE<= +{F} + + + +%%TITLE%% +%%HEAD%% + + + + + + + + + + + + + + + + + +
    + +
    + + +/opal/bullet.gif\" WIDTH=10 HEIGHT=10 HSPACE=2 ALIGN=ABSMIDDLE>"; + } else { + $$ret .= " " x ($depth*3+1); + $$ret .= $mi->{'cont'} ? "  " : "- "; + } + + my $extra = ""; + if ($mi->{'extra'}) { + $extra = " {'extra'}\">..."; + } + + my $name = $mi->{'name'}; + $name =~ s/ / /g; + if (! defined $mi->{'uri'}) { + if ($depth == 0) { + $$ret .= "$name$extra
    "; + } else { + $$ret .= "$name$extra
    "; + } + } elsif ($mi->{'match'} ? + (BML::get_uri() =~ /$mi->{'match'}/) : + (BML::get_uri() eq $mi->{'uri'}) + ){ + $$ret .= "$name$extra
    "; + } else { + $$ret .= "{'uri'}\">$name$extra
    "; + } + + if ($mi->{'children'} && + ($mi->{'recursematch'} ? BML::get_uri() =~ /$mi->{'recursematch'}/ : 1)) { + &dump_entry($ret, $mi->{'children'}, $depth+1); + } + } + + } + +&dump_entry(\$ret, \@sidebar, 0); + + return $ret; + +_code?> +
    + +

    + + + + + +
    +

    '; +} else { + return "

     

    "; +} +return ""; +_code?> + +

    %%TITLE%% +

    + +
    + + +
    + + + + + +
    +%%BODY%% + 
    + +
       +

     

    + + Terms of Service
    + Privacy Policy - + COPPA +
    +

    + + + +<=PAGE + diff --git a/livejournal/cgi-bin/bml/scheme/woais.look b/livejournal/cgi-bin/bml/scheme/woais.look new file mode 100755 index 0000000..bf09bbe --- /dev/null +++ b/livejournal/cgi-bin/bml/scheme/woais.look @@ -0,0 +1,198 @@ +_parent=>global.look + +AL=>{P}%%DATA2%% +AWAYLINK=>{P}%%DATA2%% + +H1=>{D}

    %%DATA%% +H1/FOLLOW_CHOICES=>{D}%%DATA%% +HEAD1=>{D}

    %%DATA%% + +H2=>{D}

    %%DATA%% +HEAD2=>{D}

    %%DATA%% + +# Banner Header: search results banner, content desriptor, etc... +BH=>{D}

    %%DATA%% + +GRIN=><grin> +HR=>

    *

    + +NEWLINE=>{D}
         +P=>{D}
    %%DATA%% +P/FOLLOW_P=>{D}

    %%DATA%% + +STANDOUTO<= +{D}

    +%%DATA%% + +
    +<=STANDOUTO + +STANDOUT<= +{D}

    + + + + + + + + + + + + + + +
    + + +
    + +%%DATA%% + + +
    + + +
    + +
    +<=STANDOUT + +CHOICE=>{P}
    %%DATA1%%
    %%DATA3%% + +CHOICES<= +{F} + + + + +
    +
    +%%ITEMS%% +
    +
    +
    +%%ITEMSB%% +
    +
    +<=CHOICES + +PAGE<= +{F} + + +%%TITLE%% [LiveJournal.com] +%%head%% + + + +
    + + + + + + + + + + +
    + %%TITLE%% +

    + + + 55, href => "/", text => "Home" }, + { width => 50, href => "/news.bml", text => "News" }, + { width => 105, href => "/create.bml", text => "Create Journal" }, + { width => 105, href => "/update.bml", text => "Update Journal" }, + { width => 70, href => "/download/", text => "Download" }, + { width => 75, href => "/directory.bml", text => "Directory" }, + { width => 60, href => "/support.bml", text => "Support" }, + ); + + my $ret = ""; + my $uri = BML::get_uri(); + foreach $h (@headers) + { + if ($uri eq $h->{'href'}) + { + $ret .= "\n"; + } + else + { + $ret .= "\n"; + } + } + return $ret; +_code?> + + + + +
    {'width'} BGCOLOR=#000066>$h->{'text'}
    {'width'} BGCOLOR=#6666CC>{'href'}\">$h->{'text'}
    + +Logged in: $remote->{'user'}, Logout"; + } else { + return "Not Logged in. Login"; + } +_code?> + +
    +
    + + +
    + + + + + + +
    + + +%%BODY%% + + + +
    + + +
    + +

    +
    + + + + + +
    +
    + + Privacy Policy - + COPPA
    + Legal Disclaimer - + Site Map
    +
    +
    + + +
    + + + +<=PAGE + diff --git a/livejournal/cgi-bin/cleanhtml.pl b/livejournal/cgi-bin/cleanhtml.pl new file mode 100755 index 0000000..68af096 --- /dev/null +++ b/livejournal/cgi-bin/cleanhtml.pl @@ -0,0 +1,1021 @@ +#!/usr/bin/perl +# +# +# lib: HTML::TokeParser, cgi-bin/ljconfig.pl, cgi-bin/ljlib.pl +# link: htdocs/userinfo.bml, htdocs/users +# + +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + +use strict; +use HTML::TokeParser (); +use URI (); + +# LJ::CleanHTML::clean(\$u->{'bio'}, { +# 'wordlength' => 100, # maximum length of an unbroken "word" +# 'addbreaks' => 1, # insert
    after newlines where appropriate +# 'tablecheck' => 1, # make sure they aren't closing that weren't opened. +# 'eat' => [qw(head title style layer iframe)], +# 'mode' => 'allow', +# 'deny' => [qw(marquee)], +# 'remove' => [qw()], +# 'maximgwidth' => 100, +# 'maximgheight' => 100, +# 'keepcomments' => 1, +# 'cuturl' => 'http://www.domain.com/full_item_view.ext', +# 'ljcut_disable' => 1, # stops the cleaner from using the lj-cut tag +# 'cleancss' => 1, +# 'extractlinks' => 1, # remove a hrefs; implies noautolinks +# 'noautolinks' => 1, # do not auto linkify +# 'extractimages' => 1, # placeholder images +# }); + +package LJ::CleanHTML; + +sub helper_preload +{ + my $p = HTML::TokeParser->new(""); + eval {$p->DESTROY(); }; +} + + +# this treats normal characters and &entities; as single characters +# also treats UTF-8 chars as single characters if $LJ::UNICODE +my $onechar; +{ + my $utf_longchar = '[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]'; + my $match; + if (not $LJ::UNICODE) { + $match = '[^&\s]|(&\#?\w{1,7};)'; + } else { + $match = $utf_longchar . '|[^&\s\x80-\xff]|(?:&\#?\w{1,7};)'; + } + $onechar = qr/$match/o; +} + +# Some browsers, such as Internet Explorer, have decided to alllow +# certain HTML tags to be an alias of another. This has manifested +# itself into a problem, as these aliases act in the browser in the +# same manner as the original tag, but are not treated the same by +# the HTML cleaner. +# 'alias' => 'real' +my %tag_substitute = ( + 'image' => 'img', + ); + +# +# name: LJ::CleanHTML::clean +# class: text +# des: Multifaceted HTML parse function +# info: +# args: data, opts +# des-data: A reference to html to parse to output, or HTML if modified in-place. +# des-opts: An hash of options to pass to the parser. +# returns: Nothing. +# + +sub clean +{ + my $data = shift; + my $opts = shift; + my $newdata; + + # remove the auth portion of any see_request.bml links + $$data =~ s/(see_request\.bml.+?)auth=\w+/$1/ig; + + my $p = HTML::TokeParser->new($data); + + my $wordlength = $opts->{'wordlength'}; + my $addbreaks = $opts->{'addbreaks'}; + my $keepcomments = $opts->{'keepcomments'}; + my $mode = $opts->{'mode'}; + my $cut = $opts->{'cuturl'} || $opts->{'cutpreview'}; + my $ljcut_disable = $opts->{'ljcut_disable'}; + my $s1var = $opts->{'s1var'}; + my $extractlinks = 0 || $opts->{'extractlinks'}; + my $noautolinks = $extractlinks || $opts->{'noautolinks'}; + + my @canonical_urls; # extracted links + + my %action = (); + my %remove = (); + if (ref $opts->{'eat'} eq "ARRAY") { + foreach (@{$opts->{'eat'}}) { $action{$_} = "eat"; } + } + if (ref $opts->{'allow'} eq "ARRAY") { + foreach (@{$opts->{'allow'}}) { $action{$_} = "allow"; } + } + if (ref $opts->{'deny'} eq "ARRAY") { + foreach (@{$opts->{'deny'}}) { $action{$_} = "deny"; } + } + if (ref $opts->{'remove'} eq "ARRAY") { + foreach (@{$opts->{'remove'}}) { $action{$_} = "deny"; $remove{$_} = 1; } + } + + $action{'script'} = "eat"; + + my @attrstrip = qw(); + if ($opts->{'cleancss'}) { + push @attrstrip, 'id'; + } + + if (ref $opts->{'attrstrip'} eq "ARRAY") { + foreach (@{$opts->{'attrstrip'}}) { push @attrstrip, $_; } + } + + my %opencount = (); + my @tablescope = (); + + my $cutcount = 0; + + my $total_fail = sub { + my $tag = LJ::ehtml(@_); + $$data = LJ::ehtml($$data); + $$data =~ s/\r?\n/
    /g if $addbreaks; + $$data = "[Error: Irreparable invalid markup ('<$tag>') in entry. ". + "Owner must fix manually. Raw contents below.]

    " . + '
    ' . + $$data . + '
    '; + return undef; + }; + + TOKEN: + while (my $token = $p->get_token) + { + my $type = $token->[0]; + + # See if this tag should be treated as an alias + + $token->[1] = $tag_substitute{$token->[1]} if defined $tag_substitute{$token->[1]} && + ($type eq 'S' || $type eq 'E'); + + if ($type eq "S") # start tag + { + my $tag = $token->[1]; + + # check for exploit using TIME namespace to set data and introduce javascript that + # would affect IE users. + if ($tag =~ m/:set$/ && $token->[2]->{attributename} =~ /innerHTML/i) { + next; + } + + # do some quick checking to see if this is an email address/URL, and if so, just + # escape it and ignore it + if ($tag =~ m!(?:\@|://)!) { + $newdata .= LJ::ehtml("<$tag>"); + next; + } + + my $slashclose = 0; # If set to 1, use XML-style empty tag marker + # for tags like , pretend it's and reinsert the slash later + $slashclose = 1 if ($tag =~ s!/$!!); + + return $total_fail->($tag) unless $tag =~ /^\w([\w\-:_]*\w)?$/; + + # for incorrect tags like (note the lack of a space) + # delete everything after 'name' to prevent a security loophole which happens + # because IE understands them. + $tag =~ s!/.+$!!; + + if ($action{$tag} eq "eat") { + $p->unget_token($token); + $p->get_tag("/$tag"); + } + elsif ($tag eq "lj-cut" && !$ljcut_disable) + { + my $attr = $token->[2]; + $cutcount++; + if ($cut) { + my $text = "Read more..."; + if ($attr->{'text'}) { + $text = $attr->{'text'}; + if ($text =~ /[^\x01-\x7f]/) { + $text = pack('C*', unpack('C*', $text)); + } + $text =~ s//>/g; + } + my $url = LJ::ehtml($cut); + $newdata .= "$text )"; + $p->get_tag("/lj-cut") unless $opts->{'cutpreview'} + } else { + $newdata .= ""; + next; + } + } + elsif ($tag eq "lj") + { + my $attr = $token->[2]; + + # keep working for backwards compatibility, but pretend + # it was so we don't have to account for it below. + my $user = $attr->{'user'} = exists $attr->{'user'} ? $attr->{'user'} : + exists $attr->{'comm'} ? $attr->{'comm'} : undef; + + if (length $user) { + $user = LJ::canonical_username($user); + if ($s1var) { + $newdata .= "%%ljuser:$1%%" if $attr->{'user'} =~ /^\%\%([\w\-\']+)\%\%$/; + } elsif (length $user) { + if ($opts->{'textonly'}) { + $newdata .= $user; + } else { + $newdata .= LJ::ljuser($user); + } + } else { + $newdata .= "[Bad username in LJ tag]"; + } + } else { + $newdata .= "[Unknown LJ tag]"; + } + } + elsif ($tag eq "lj-raw") + { + # Strip it out, but still register it as being open + $opencount{$tag}++; + } + else + { + my $alt_output = 0; + + my $hash = $token->[2]; + my $attrs = $token->[3]; # attribute names, in original order + + $slashclose = 1 if delete $hash->{'/'}; + + foreach (@attrstrip) { + delete $hash->{$_}; + } + + if ($tag eq "form") { + my $action = lc($hash->{'action'}); + my $deny = 0; + if ($action =~ m!^https?://?([^/]+)!) { + my $host = $1; + $deny = 1 if + $host =~ /[%\@\s]/ || + $LJ::FORM_DOMAIN_BANNED{$host}; + } else { + $deny = 1; + } + delete $hash->{'action'} if $deny; + } + + foreach my $attr (keys %$hash) + { + delete $hash->{$attr} if $attr =~ /^(?:on|dynsrc|data)/; + if ($attr =~ /(?:^=)|[\x0b\x0d]/) { + # Cleaner attack:

    ' onmouseover="javascript:alert(document/**/.cookie)" > + # is returned by HTML::Parser as P_tag("='" => "='") Text( onmouseover...) + # which leads to reconstruction of valid HTML. Clever! + # detect this, and fail. + return $total_fail->("$tag $attr"); + } + + # ignore attributes that do not fit this strict scheme + return $total_fail->("$tag " . (%$hash > 1 ? "[...] " : "") . "$attr") + unless $attr =~ /^[\w_:-]+$/; + + $hash->{$attr} =~ s/[\t\n]//g; + # IE sucks: + if ($hash->{$attr} =~ /(j\s*a\s*v\s*a\s*s\s*c\s*r\s*i\s*p\s*t| + v\s*b\s*s\s*c\s*r\s*i\s*p\s*t| + a\s*b\s*o\s*u\s*t)\s*:/ix) { + delete $hash->{$attr}; + } + + if ($attr eq 'style' && $opts->{'cleancss'}) { + # css2 spec, section 4.1.3 + # position === p\osition :( + # strip all slashes no matter what. + $hash->{$attr} =~ s/\\//g; + # and catch the obvious ones. + foreach my $css (qw(absolute fixed)) { + if ($hash->{$attr} =~ /$css/i) { + delete $hash->{$attr}; + last; + } + } + } + + # reserve ljs_* ids for divs, etc so users can't override them to replace content + if ($attr eq 'id' && $hash->{$attr} =~ /^ljs_/i) { + delete $hash->{$attr}; + } + + if ($s1var) { + if ($attr =~ /%%/) { + delete $hash->{$attr}; + next; + } + + my $props = $LJ::S1::PROPS->{$s1var}; + + if ($hash->{$attr} =~ /^%%([\w:]+:)?(\S+?)%%$/ && $props->{$2} =~ /[aud]/) { + # don't change it. + } elsif ($hash->{$attr} =~ /^%%cons:\w+%%[^\%]*$/) { + # a site constant with something appended is also fine. + } elsif ($hash->{$attr} =~ /%%/) { + my $clean_var = sub { + my ($mods, $prop) = @_; + # HTML escape and kill line breaks + $mods = "attr:$mods" unless + $mods =~ /^(color|cons|siteroot|sitename|img):/ || + $props->{$prop} =~ /[ud]/; + return '%%' . $mods . $prop . '%%'; + }; + + $hash->{$attr} =~ s/[\n\r]//g; + $hash->{$attr} =~ s/%%([\w:]+:)?(\S+?)%%/$clean_var->(lc($1), $2)/eg; + + if ($attr =~ /^(href|src|lowsrc|style)$/) { + $hash->{$attr} = "\%\%[attr[$hash->{$attr}]]\%\%"; + } + } + + } + } + if (exists $hash->{href}) { + unless ($hash->{href} =~ s/^lj:(?:\/\/)?(.*)$/ExpandLJURL($1)/ei) { + $hash->{href} = canonical_url($hash->{href}, 1); + } + } + if ($hash->{'style'} =~ /expression/i) { + delete $hash->{'style'}; + } + + if ($tag eq "img") + { + my $img_bad = 0; + if (defined $opts->{'maximgwidth'} && + (! defined $hash->{'width'} || + $hash->{'width'} > $opts->{'maximgwidth'})) { $img_bad = 1; } + if (defined $opts->{'maximgheight'} && + (! defined $hash->{'height'} || + $hash->{'height'} > $opts->{'maximgheight'})) { $img_bad = 1; } + if ($opts->{'extractimages'}) { $img_bad = 1; } + + $hash->{src} = canonical_url($hash->{src}, 1); + + if ($img_bad) { + $newdata .= "{'src'}) . "\">" . + LJ::img('placeholder') . ''; + $alt_output = 1; + } + } + + if ($tag eq "a" && $extractlinks) + { + push @canonical_urls, canonical_url($token->[2]->{href}, 1); + $newdata .= ""; + next; + } + + unless ($alt_output) + { + my $allow; + if ($mode eq "allow") { + $allow = 1; + if ($action{$tag} eq "deny") { $allow = 0; } + } else { + $allow = 0; + if ($action{$tag} eq "allow") { $allow = 1; } + } + + if ($allow && ! $remove{$tag}) + { + if ($opts->{'tablecheck'}) { + + $allow = 0 if + + # can't open table elements from outside a table + ($tag =~ /^(?:tbody|thead|tfoot|tr|td|th)$/ && ! @tablescope) || + + # can't open td or th if not inside tr + ($tag =~ /^(?:td|th)$/ && ! $tablescope[-1]->{'tr'}) || + + # can't open a table unless inside a td or th + ($tag eq 'table' && @tablescope && ! grep { $tablescope[-1]->{$_} } qw(td th)); + } + + if ($allow) { $newdata .= "<$tag"; } + else { $newdata .= "<$tag"; } + + # output attributes in original order, but only those + # that are allowed (by still being in %$hash after cleaning) + foreach (@$attrs) { + if ($hash->{$_} =~ /[^\x01-\x7f]/) { + # FIXME: this is so ghetto. make faster. make generic. + # HTML::Parser decodes entities for us (which is good) + # but in Perl 5.8 also includes the "poison" SvUTF8 + # flag on the scalar it returns, thus poisoning the + # rest of the content this scalar is appended with. + # we need to remove that poison at this point. *sigh* + $hash->{$_} = pack('C*', unpack('C*', $hash->{$_})); + } + $newdata .= " $_=\"" . LJ::ehtml($hash->{$_}) . "\"" + if exists $hash->{$_}; + } + + if ($slashclose) { + $newdata .= " /"; + $opencount{$tag}--; + $tablescope[-1]->{$tag}-- if $opts->{'tablecheck'} && @tablescope; + } + if ($allow) { + $newdata .= ">"; + $opencount{$tag}++; + + # maintain current table scope + if ($opts->{'tablecheck'}) { + + # open table + if ($tag eq 'table') { + push @tablescope, {}; + + # new tag within current table + } elsif (@tablescope) { + $tablescope[-1]->{$tag}++; + } + } + + } + else { $newdata .= ">"; } + } + } + } + } + # end tag + elsif ($type eq "E") + { + my $tag = $token->[1]; + + my $allow; + if ($tag eq "lj-raw") { + $opencount{$tag}--; + $tablescope[-1]->{$tag}-- if $opts->{'tablecheck'} && @tablescope; + } + elsif ($tag eq "lj-cut") { + if ($opts->{'cutpreview'}) { + $newdata .= "</lj-cut>"; + } + } else { + if ($mode eq "allow") { + $allow = 1; + if ($action{$tag} eq "deny") { $allow = 0; } + } else { + $allow = 0; + if ($action{$tag} eq "allow") { $allow = 1; } + } + + if ($extractlinks && $tag eq "a") { + if (@canonical_urls) { + my $url = LJ::ehtml(pop @canonical_urls); + $newdata .= " ($url)"; + } + } + + if ($allow && ! $remove{$tag}) + { + + if ($opts->{'tablecheck'}) { + + $allow = 0 if + + # can't close table elements from outside a table + ($tag =~ /^(?:table|tbody|thead|tfoot|tr|td|th)$/ && ! @tablescope) || + + # can't close td or th unless open tr + ($tag =~ /^(?:td|th)$/ && ! $tablescope[-1]->{'tr'}); + } + + if ($allow && ! ($opts->{'noearlyclose'} && ! $opencount{$tag})) { + + # maintain current table scope + if ($opts->{'tablecheck'}) { + + # open table + if ($tag eq 'table') { + pop @tablescope; + + # closing tag within current table + } elsif (@tablescope) { + $tablescope[-1]->{$tag}--; + } + } + + $newdata .= ""; + $opencount{$tag}--; + + } else { $newdata .= "</$tag>"; } + } + } + } + elsif ($type eq "D") { + # remove everything past first closing tag + $token->[1] =~ s/>.+/>/s; + # kill any opening tag except the starting one + $token->[1] =~ s/.[1]; + } + elsif ($type eq "T") { + my %url = (); + my $urlcount = 0; + + if ($opencount{'style'}) { + # remove anything that might run javascript/vbscript code + # (Note: Ghetto. Need to use CSS.pm to build full tree, analyze, redump) + my $reduced = lc($token->[1]); + $reduced =~ s/\s+//g; + $reduced =~ s/\\//g; + $reduced =~ s/&\#(\d+);?/chr($1)/eg; + $reduced =~ s/&\#x(\w+);?/chr(hex($1))/eg; + $token->[1] = "/* potential scripting */" + if $reduced =~ /javascript|vbscript|expression/; + + $token->[1] =~ s//[COME]/g; + } + my $auto_format = $addbreaks && + ($opencount{'table'} <= ($opencount{'td'} + $opencount{'th'})) && + ! $opencount{'pre'} && + ! $opencount{'lj-raw'}; + + if ($auto_format && ! $noautolinks && ! $opencount{'a'} && ! $opencount{'textarea'}) { + my $match = sub { + my $str = shift; + if ($str =~ /^(.*?)(&(#39|quot|lt|gt)(;.*)?)$/) { + $url{++$urlcount} = $1; + return "&url$urlcount;$1&urlend;$2"; + } else { + $url{++$urlcount} = $str; + return "&url$urlcount;$str&urlend;"; + } + }; + $token->[1] =~ s!https?://[^\s\'\"\<\>]+[a-zA-Z0-9_/&=\-]! $match->($&); !ge; + } + + # escape tags in text tokens. shouldn't belong here! + # especially because the parser returns things it's + # confused about (broken, ill-formed HTML) as text. + $token->[1] =~ s/[1] =~ s/>/>/g; + } + if ($opencount{'style'}) { + $token->[1] =~ s/\[COMS\]//g; + } + + # put tags into long words, except inside

     and ";
    +    return $ret;
    +}
    +
    +# 
    +# name: html_color
    +# class: component
    +# des: A text field with attached color preview and button to choose a color
    +# info: Depends on the client-side Color Picker
    +# args:
    +# des-:
    +# returns:
    +# 
    +sub html_color
    +{
    +    my $opts = shift;
    +
    +    my $htmlname = ehtml($opts->{'name'});
    +    my $des = ehtml($opts->{'des'}) || "Pick a Color";
    +    my $ret;
    +
    +    ## Output the preview box and picker button with script so that
    +    ## they don't appear when JavaScript is unavailable.
    +    $ret .= "\n";
    +
    +    # 'onchange' argument happens when color picker button is clicked,
    +    # or when focus is changed to text box
    +
    +    $ret .= html_text({ 'size' => 8, 'maxlength' => 7, 'name' => $htmlname, 'id' => $htmlname,
    +                        'onchange' => "setBGColor(findel('${htmlname}_disp'),${htmlname}.value);",
    +                        'onfocus' => $opts->{'onchange'},
    +                        'disabled' => $opts->{'disabled'}, 'value' => $opts->{'default'},
    +                        'noescape' => 1, 'raw' => $opts->{'raw'},
    +                      });
    +
    +    my $disabled = $opts->{'disabled'} ? "disabled=\'disabled\'" : '';
    +    $ret .= "\n";
    +
    +    # A little help for the non-JavaScript folks
    +    $ret .= "";
    +
    +    return $ret;
    +}
    +
    +# 
    +# name: html_hidden
    +# class: component
    +# des: Makes the HTML for a hidden form element
    +# args: name, val
    +# des-name: Name of form element (will be HTML escaped)
    +# des-val: Value of form element (will be HTML escaped)
    +# returns: HTML
    +# 
    +sub html_hidden
    +{
    +    my $ret;
    +
    +    while (@_) {
    +        my $name = shift;
    +        my $val;
    +        my $ehtml = 1;
    +        my $extra;
    +        if (ref $name eq 'HASH') {
    +            my $opts = $name;
    +
    +            $val = $opts->{value};
    +            $name = $opts->{name};
    +
    +            $ehtml = $opts->{'noescape'} ? 0 : 1;
    +            foreach (grep { ! /^(name|value|raw|noescape)$/ } keys %$opts) {
    +                $extra .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\"";
    +            }
    +
    +            $extra .= " $opts->{'raw'}" if $opts->{'raw'};
    +
    +        } else {
    +            $val = shift;
    +        }
    +
    +        $ret .= "
    +# name: html_submit
    +# class: component
    +# des: Makes the HTML for a submit button
    +# args: name, val, opts?
    +# des-name: Name of form element (will be HTML escaped)
    +# des-val: Value of form element, and label of button (will be HTML escaped)
    +# des-opts: Optional hashref of additional tag attributes
    +# returns: HTML
    +# 
    +sub html_submit
    +{
    +    my ($name, $val, $opts) = @_;
    +
    +    # if one argument, assume (undef, $val)
    +    if (@_ == 1) {
    +        $val = $name;
    +        $name = undef;
    +    }
    +
    +    my ($eopts, $disabled, $raw);
    +    my $type = 'submit';
    +
    +    my $ehtml;
    +    if ($opts && ref $opts eq 'HASH') {
    +        $disabled = " disabled='disabled'" if $opts->{'disabled'};
    +        $raw = " $opts->{'raw'}" if $opts->{'raw'};
    +        $type = 'reset' if $opts->{'type'} eq 'reset';
    +
    +        $ehtml = $opts->{'noescape'} ? 0 : 1;
    +        foreach (grep { ! /^(raw|disabled|noescape|type)$/ } keys %$opts) {
    +            $eopts .= " $_=\"" . ($ehtml ? ehtml($opts->{$_}) : $opts->{$_}) . "\"";
    +        }
    +    }
    +    my $ret = " '/btn_up.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Up',
    +};
    +
    +$img{'btn_down'} = { 
    +    'src' => '/btn_dn.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Down',
    +};
    +
    +$img{'btn_del'} = { 
    +    'src' => '/btn_del.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Delete',
    +};
    +
    +$img{'btn_freeze'} = {
    +    'src' => '/btn_freeze.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Freeze',
    +};
    +
    +$img{'btn_unfreeze'} = {
    +    'src' => '/btn_unfreeze.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Unfreeze',
    +};
    +
    +$img{'btn_scr'} = { 
    +    'src' => '/btn_scr.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Screen',
    +};
    +
    +$img{'btn_unscr'} = { 
    +    'src' => '/btn_unscr.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Unscreen',
    +};
    +
    +$img{'prev_entry'} = { 
    +    'src' => '/btn_prev.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Previous Entry',
    +};
    +
    +$img{'next_entry'} = { 
    +    'src' => '/btn_next.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Next Entry',
    +};
    +
    +$img{'memadd'} = { 
    +    'src' => '/memadd.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Add to memories!',
    +};
    +
    +$img{'editentry'} = { 
    +    'src' => '/btn_edit.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Edit Entry',
    +};
    +
    +$img{'edittags'} = {
    +    'src' => '/btn_edittags.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Edit Tags',
    +};
    +
    +$img{'tellfriend'} = { 
    +    'src' => '/btn_tellfriend.gif',
    +    'width' => 22,
    +    'height' => 20,
    +    'alt' => 'Tell a Friend!',
    +};
    +
    +$img{'placeholder'} = {
    +    'src' => '/imageplaceholder2.png',
    +    'width' => 35,
    +    'height' => 35,
    +    'alt' => 'Image',
    +};
    +
    +$img{'xml'} = {
    +    'src' => '/xml.gif',
    +    'width' => 36,
    +    'height' => 14,
    +    'alt' => 'XML Source',
    +};
    +
    +# load the site-local version, if it's around.
    +if (-e "$LJ::HOME/cgi-bin/imageconf-local.pl") {
    +    require "$LJ::HOME/cgi-bin/imageconf-local.pl";
    +}
    +
    +1;
    +
    diff --git a/livejournal/cgi-bin/lj-bml-blocks.pl b/livejournal/cgi-bin/lj-bml-blocks.pl
    new file mode 100755
    index 0000000..dc9a89c
    --- /dev/null
    +++ b/livejournal/cgi-bin/lj-bml-blocks.pl
    @@ -0,0 +1,30 @@
    +#!/usr/bin/perl
    +#
    +    
    +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl";
    +
    +BML::register_block("DOMAIN", "S", $LJ::DOMAIN);
    +BML::register_block("IMGPREFIX", "S", $LJ::IMGPREFIX);
    +BML::register_block("STATPREFIX", "S", $LJ::STATPREFIX);
    +BML::register_block("SITEROOT", "S", $LJ::SITEROOT);
    +BML::register_block("SITENAME", "S", $LJ::SITENAME);
    +BML::register_block("ADMIN_EMAIL", "S", $LJ::ADMIN_EMAIL);
    +BML::register_block("SUPPORT_EMAIL", "S", $LJ::SUPPORT_EMAIL);
    +BML::register_block("CHALRESPJS", "", $LJ::COMMON_CODE{'chalresp_js'});
    +
    +{
    +    my $dl = "HTTP";
    +    if ($LJ::FTPPREFIX) {
    +        $dl .= " - FTP";
    +    }
    +    BML::register_block("DL", "DR", $dl);
    +}
    +
    +if ($LJ::UNICODE) {
    +    BML::register_block("METACTYPE", "S", '')
    +} else {
    +    BML::register_block("METACTYPE", "S", '')
    +}
    +
    +
    +1;
    diff --git a/livejournal/cgi-bin/lj-bml-init.pl b/livejournal/cgi-bin/lj-bml-init.pl
    new file mode 100755
    index 0000000..2aa62d3
    --- /dev/null
    +++ b/livejournal/cgi-bin/lj-bml-init.pl
    @@ -0,0 +1,53 @@
    +#!/usr/bin/perl
    +#
    +
    +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl";
    +
    +foreach (@LJ::LANGS, @LJ::LANGS_IN_PROGRESS) {
    +    BML::register_isocode(substr($_, 0, 2), $_);
    +    BML::register_language($_);
    +}
    +
    +# set default path/domain for cookies
    +BML::set_config("CookieDomain" => $LJ::COOKIE_DOMAIN);
    +BML::set_config("CookiePath"   => $LJ::COOKIE_PATH);
    +
    +BML::register_hook("startup", sub {
    +    my $r = Apache->request;
    +    my $uri = "bml" . $r->uri;
    +    unless ($uri =~ s/\.bml$//) {
    +        $uri .= ".index";
    +    }
    +    $uri =~ s!/!.!g;
    +    $r->notes("codepath" => $uri);
    +});
    +
    +BML::register_hook("codeerror", sub {
    +    my $msg = shift;
    +    if ($msg =~ /Can\'t call method.*on an undefined value/) {
    +        return $LJ::MSG_DB_UNAVAILABLE ||
    +               "Sorry, database temporarily unavailable.";
    +    }
    +    chomp $msg;
    +    $msg .= " \@ $LJ::SERVER_NAME" if $LJ::SERVER_NAME;
    +    warn "$msg\n";
    +    return "[Error: $msg]";
    +}) unless $LJ::IS_DEV_SERVER;
    +
    +if ($LJ::UNICODE) {
    +    BML::set_config("DefaultContentType", "text/html; charset=utf-8");
    +}
    +
    +# register BML multi-language hook
    +BML::register_hook("ml_getter", \&LJ::Lang::get_text);
    +
    +# include file handling
    +BML::register_hook('include_getter', sub {
    +    # simply call LJ::load_include, as it does all the work of hitting up
    +    # memcache/db for us and falling back to disk if necessary...
    +    my ($file, $source) = @_;
    +    $$source = LJ::load_include($file);
    +    return 1;
    +});
    +
    +1;
    diff --git a/livejournal/cgi-bin/ljcmdbuffer.pl b/livejournal/cgi-bin/ljcmdbuffer.pl
    new file mode 100755
    index 0000000..bd8ef83
    --- /dev/null
    +++ b/livejournal/cgi-bin/ljcmdbuffer.pl
    @@ -0,0 +1,322 @@
    +#!/usr/bin/perl
    +#
    +
    +use strict;
    +
    +require "$ENV{LJHOME}/cgi-bin/ljlib.pl";
    +require "$ENV{LJHOME}/cgi-bin/supportlib.pl";
    +require "$ENV{LJHOME}/cgi-bin/ljmail.pl";
    +
    +package LJ::Cmdbuffer;
    +
    +# built-in commands
    +%LJ::Cmdbuffer::cmds = 
    +    (
    +
    +     # delete journal entries
    +     delitem => {
    +         run => \&LJ::Cmdbuffer::_delitem,
    +     },
    +
    +     # ping weblogs.com with updates?  takes a $u argument
    +     weblogscom => {
    +         too_old => 60*60*2,  # 2 hours old = qbufferd not running?
    +         once_per_user => 1,
    +         run => \&LJ::Cmdbuffer::_weblogscom,
    +     },
    +
    +     # emails that previously failed to send
    +     send_mail => {
    +         arg_format => 'raw',
    +         run => \&LJ::Cmdbuffer::_send_mail,
    +     },
    +
    +     # notify fotobilder of dirty friends
    +     dirty => {
    +         once_per_user => 1,
    +         kill_mem_size => 50_000, # bytes
    +         kill_job_ct   => 250,    # calls to LJ::Cmdbuffer::flush
    +         run => \&LJ::Cmdbuffer::_dirty,
    +     },
    +     
    +     # send notifications for support requests
    +     support_notify => {
    +         too_old => 60*60*2, # after two hours, notification seems kinda pointless
    +         run => \&LJ::Cmdbuffer::_support_notify,
    +     },
    +
    +     );
    +
    +# 
    +# name: LJ::Cmdbuffer::flush
    +# des: flush up to 500 rows of a given command type from the cmdbuffer table
    +# args: dbh, db, cmd, userid?
    +# des-dbh: master database handle
    +# des-db: database cluster master
    +# des-cmd: a command type registered in %LJ::Cmdbuffer::cmds
    +# des-userid: optional userid to which flush should be constrained
    +# returns: 1 on success, 0 on failure
    +# 
    +sub LJ::Cmdbuffer::flush
    +{
    +    my ($dbh, $db, $cmd, $userid) = @_;
    +    return 0 unless $cmd;
    +
    +    my $mode = "run";
    +    if ($cmd =~ s/:(\w+)//) {
    +        $mode = $1;
    +    }
    +
    +    my $code = $LJ::Cmdbuffer::cmds{$cmd} ?
    +        $LJ::Cmdbuffer::cmds{$cmd}->{$mode} : $LJ::HOOKS{"cmdbuf:$cmd:$mode"}->[0];
    +    return 0 unless $code;
    +
    +    # start/finish modes
    +    if ($mode ne "run") {
    +        $code->($dbh);
    +        return 1;
    +    }
    +
    +    # 0 = never too old
    +    my $too_old = LJ::Cmdbuffer::get_property($cmd, 'too_old') || 0;
    +
    +    # 0 == okay to run more than once per user
    +    my $once_per_user = LJ::Cmdbuffer::get_property($cmd, 'once_per_user') || 0;
    +
    +    # 'url' = urlencode, 'raw' = don't urlencode
    +    my $arg_format = LJ::Cmdbuffer::get_property($cmd, 'arg_format') || 'url';
    +
    +    my $clist;
    +    my $loop = 1;
    +
    +    my $where = "cmd=" . $dbh->quote($cmd);
    +    if ($userid) {
    +        $where .= " AND journalid=" . $dbh->quote($userid);
    +    }
    +
    +    my $LIMIT = 500;
    +
    +    while ($loop &&
    +           ($clist = $db->selectall_arrayref("SELECT cbid, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(instime), journalid ".
    +                                             "FROM cmdbuffer ".
    +                                             "WHERE $where ORDER BY cbid LIMIT $LIMIT")) &&
    +           $clist && @$clist)
    +    {
    +        my @too_old;
    +        my @cbids;
    +
    +        # citem: [ cbid, age, journalid ]
    +        foreach my $citem (@$clist) {
    +            if ($too_old && $citem->[1] > $too_old) {
    +                push @too_old, $citem->[0];
    +            } else {
    +                push @cbids, $citem->[0];
    +            }
    +        }
    +        if (@too_old) {
    +            local $" = ",";
    +            $db->do("DELETE FROM cmdbuffer WHERE cbid IN (@too_old)");
    +        }
    +
    +        foreach my $cbid (@cbids) {
    +            my $got_lock = $db->selectrow_array("SELECT GET_LOCK('cbid-$cbid',10)");
    +            return 0 unless $got_lock;
    +            # sadly, we have to do another query here to verify the job hasn't been
    +            # done by another thread.  (otherwise we could've done it above, instead
    +            # of just getting the id)
    +
    +            my $c = $db->selectrow_hashref("SELECT cbid, journalid, cmd, instime, args " .
    +                                           "FROM cmdbuffer WHERE cbid=?", undef, $cbid);
    +            next unless $c;
    +
    +            if ($arg_format eq "url") {
    +                my $a = {};
    +                LJ::decode_url_string($c->{'args'}, $a);
    +                $c->{'args'} = $a;
    +            }
    +            # otherwise, arg_format eq "raw"
    +
    +            # run handler
    +            $code->($dbh, $db, $c);
    +
    +            # if this task is to be run once per user, go ahead and delete any jobs 
    +            # for this user of this type and remove them from the queue
    +            my $wh = "cbid=$cbid";
    +            if ($once_per_user) {
    +                $wh = "cmd=" . $db->quote($cmd) . " AND journalid=" . $db->quote($c->{journalid});
    +                @$clist = grep { $_->[2] != $c->{journalid} } @$clist;
    +            }
    +
    +            $db->do("DELETE FROM cmdbuffer WHERE $wh");
    +            $db->do("SELECT RELEASE_LOCK('cbid-$cbid')");
    +        }
    +        $loop = 0 unless scalar(@$clist) == $LIMIT;
    +    }
    +
    +    return 1;
    +}
    +
    +# 
    +# name: LJ::Cmdbuffer::get_property
    +# des: get a property of an async job type, either built-in or site-specific
    +# args: cmd, prop
    +# des-cmd: a registered async job type
    +# des-prop: the property name to look up
    +# returns: value of property (whatever it may be) on success, undef on failure
    +# 
    +sub get_property {
    +    my ($cmd, $prop) = @_;
    +    return undef unless $cmd && $prop;
    +
    +    if (my $c = $LJ::Cmdbuffer::cmds{$cmd}) {
    +        return $c->{$prop};
    +    }
    +
    +    if (LJ::are_hooks("cmdbuf:$cmd:$prop")) {
    +        return LJ::run_hook("cmdbuf:$cmd:$prop");
    +    }
    +
    +    return undef;
    +}
    +
    +sub _delitem {
    +    my ($dbh, $db, $c) = @_;
    +    my $a = $c->{'args'};
    +    return LJ::delete_entry($c->{'journalid'}, $a->{'itemid'},
    +                            0, $a->{'anum'});
    +}
    +
    +sub _weblogscom {
    +    # user, title, url
    +    my ($dbh, $db, $c) = @_;
    +    my $a = $c->{'args'};
    +    eval {
    +        eval "use XMLRPC::Lite;";
    +        unless ($@) {
    +            XMLRPC::Lite
    +                ->new( proxy => "http://rpc.weblogs.com/RPC2",
    +                       timeout => 5 )
    +                ->call('weblogUpdates.ping', # xml-rpc method call
    +                       LJ::ehtml($a->{'title'}) . " \@ $LJ::SITENAMESHORT",
    +                       $a->{'url'},
    +                       "$LJ::SITEROOT/misc/weblogs-change.bml?user=$a->{'user'}");
    +        }
    +    };
    +
    +    return 1;
    +}
    +
    +sub _send_mail {
    +    my ($dbh, $db, $c) = @_;
    +
    +    my $msg = Storable::thaw($c->{'args'});
    +    return LJ::send_mail($msg, "async");
    +}
    +
    +sub _dirty {
    +    my ($dbh, $db, $c) = @_;
    +
    +    my $a = $c->{args};
    +    my $what = $a->{what};
    +
    +    if ($what eq 'friends') {
    +        eval {
    +            eval qq{
    +                use RPC::XML;
    +                use RPC::XML::Client;
    +            };
    +            unless ($@) {
    +                my $u = LJ::load_userid($c->{journalid});
    +                my %req = ( user => $u->{user} );
    +
    +                # fill in groups info
    +                LJ::fill_groups_xmlrpc($u, \%req);
    +
    +                my $res = RPC::XML::Client
    +                    ->new("$LJ::FB_SITEROOT/interface/xmlrpc")
    +                    ->send_request('FB.XMLRPC.groups_push',
    +                                   # FIXME: don't be lazy with the smart_encode
    +                                   # FIXME: log useful errors from outcome
    +                                   RPC::XML::smart_encode(\%req));
    +            }
    +        };
    +    }
    +    
    +    return 1;
    +}
    +
    +sub _support_notify {
    +    my ($dbh, $db, $c) = @_;
    +
    +    # load basic stuff common to both paths
    +    my $a = $c->{args};
    +    my $type = $a->{type};
    +    my $spid = $a->{spid}+0;
    +    my $sp = LJ::Support::load_request($spid, $type eq 'new' ? 1 : 0); # 1 means load body
    +    my $dbr = LJ::get_db_reader();
    +
    +    # now branch a bit to select the right user information
    +    my ($select, $level) = $type eq 'new' ?
    +        ('u.email', "'new', 'all'") :
    +        ('u.email, u.userid, u.user', "'all'");
    +
    +    my $data = $dbr->selectall_arrayref("SELECT $select FROM supportnotify sn, user u " .
    +                                        "WHERE sn.userid=u.userid AND sn.spcatid=? " .
    +                                        "AND sn.level IN ($level)", undef, $sp->{_cat}{spcatid});
    +    
    +    # prepare the email
    +    my $body;
    +    my @emails;
    +    if ($type eq 'new') {
    +        $body = "A $LJ::SITENAME support request has been submitted regarding the following:\n\n";
    +        $body .= "Category: $sp->{_cat}{catname}\n";
    +        $body .= "Subject:  $sp->{subject}\n\n";
    +        $body .= "You can track its progress or add information here:\n\n";
    +        $body .= "$LJ::SITEROOT/support/see_request.bml?id=$spid";
    +        $body .= "\n\nIf you do not wish to receive notifications of incoming support requests, you may change your notification settings here:\n\n";
    +        $body .= "$LJ::SITEROOT/support/changenotify.bml";
    +        $body .= "\n\n" . "="x70 . "\n\n";
    +        $body .= $sp->{body};
    +
    +        # just copy this out
    +        push @emails, $_->[0] foreach @$data;
    +    } elsif ($type eq 'update') {
    +        # load the response we want to stuff in the email
    +        my ($resp, $rtype, $posterid) = 
    +            $dbr->selectrow_array("SELECT message, type, userid FROM supportlog WHERE spid = ? AND splid = ?",
    +                                  undef, $sp->{spid}, $a->{splid}+0);
    +
    +        # build body
    +        $body = "A follow-up to the request regarding \"$sp->{subject}\" has ";
    +        $body .= "been submitted.  You can track its progress or add ";
    +        $body .= "information here:\n\n  ";
    +        $body .= "$LJ::SITEROOT/support/see_request.bml?id=$spid";
    +        $body .= "\n\n" . "="x70 . "\n\n";
    +        $body .= $resp;
    +
    +        # now see who this should be sent to
    +        foreach my $erow (@$data) {
    +            next if $posterid == $erow->[1];
    +            next if $rtype eq 'screened' &&
    +                !LJ::Support::can_read_screened($sp, LJ::make_remote($erow->[2], $erow->[1]));
    +            next if $rtype eq 'internal' &&
    +                !LJ::Support::can_read_internal($sp, LJ::make_remote($erow->[2], $erow->[1]));
    +            push @emails, $erow->[0];
    +        }
    +    }
    +
    +    # send the email
    +    LJ::send_mail({ 
    +        bcc => join(', ', @emails),
    +        from => $LJ::BOGUS_EMAIL,
    +        fromname => "$LJ::SITENAME Support",
    +        charset => 'utf-8',
    +        subject => ($type eq 'update' ? 'Re: ' : '') . "Support Request \#$spid",
    +        body => $body,
    +        wrap => 1,
    +    }) if @emails;
    +
    +    return 1;
    +}
    +
    +1;
    diff --git a/livejournal/cgi-bin/ljdb.pl b/livejournal/cgi-bin/ljdb.pl
    new file mode 100755
    index 0000000..64b0ab4
    --- /dev/null
    +++ b/livejournal/cgi-bin/ljdb.pl
    @@ -0,0 +1,55 @@
    +#!/usr/bin/perl
    +#
    +
    +use strict;
    +use lib "$ENV{LJHOME}/cgi-bin";
    +use DBI::Role;
    +use DBI;
    +
    +require "$ENV{LJHOME}/cgi-bin/ljconfig.pl";
    +
    +package LJ::DB;
    +
    +our $DBIRole = new DBI::Role {
    +    'timeout' => 2,
    +    'sources' => \%LJ::DBINFO,
    +    'default_db' => "livejournal",
    +    'time_check' => 60,
    +};
    +
    +sub dbh_by_role {
    +    return $DBIRole->get_dbh( @_ );
    +}
    +
    +sub dbh_by_name {
    +    my $name = shift;
    +    my $dbh = dbh_by_role("master")
    +	or die "Couldn't contact master to find name of '$name'\n";
    +
    +    my $fdsn = $dbh->selectrow_array("SELECT fdsn FROM dbinfo WHERE name=?", undef, $name);
    +    die "No fdsn found for db name '$name'\n" unless $fdsn;
    +
    +    return $DBIRole->get_dbh_conn($fdsn);
    +  
    +}
    +
    +sub dbh_by_fdsn {
    +    my $fdsn = shift;
    +    return $DBIRole->get_dbh_conn($fdsn);
    +}
    +
    +sub root_dbh_by_name {
    +    my $name = shift;
    +    my $dbh = dbh_by_role("master")
    +	or die "Couldn't contact master to find name of '$name'";
    +   
    +    my $fdsn = $dbh->selectrow_array("SELECT rootfdsn FROM dbinfo WHERE name=?", undef, $name);
    +    die "No rootfdsn found for db name '$name'\n" unless $fdsn;
    +
    +    return $DBIRole->get_dbh_conn($fdsn);
    +}
    +
    +
    +1;
    +
    +
    diff --git a/livejournal/cgi-bin/ljdefaults.pl b/livejournal/cgi-bin/ljdefaults.pl
    new file mode 100755
    index 0000000..0beb3af
    --- /dev/null
    +++ b/livejournal/cgi-bin/ljdefaults.pl
    @@ -0,0 +1,245 @@
    +#!/usr/bin/perl
    +#
    +# Do not edit this file.  You should edit ljconfig.pl, which you should have at
    +# cgi-bin/ljconfig.pl.  If you don't, copy it from doc/ljconfig.pl.txt to cgi-bin
    +# and edit it there.  This file only provides backup default values for upgrading.
    +#
    +
    +{
    +    package LJ;
    +    use Sys::Hostname ();
    +
    +    $DEFAULT_STYLE ||= { 
    +        'core' => 'core1',
    +        'layout' => 'generator/layout',
    +        'i18n' => 'generator/en',
    +    };
    +
    +    # cluster 0 is no longer supported
    +    $DEFAULT_CLUSTER ||= 1;
    +    @CLUSTERS = (1) unless @CLUSTERS;
    +
    +    $HOME = $ENV{'LJHOME'};
    +    $HTDOCS = "$HOME/htdocs";
    +    $BIN = "$HOME/bin";
    +
    +    $SERVER_NAME ||= Sys::Hostname::hostname();
    +    
    +    $UNICODE = 1 unless defined $UNICODE;
    +
    +    @LANGS = ("en") unless @LANGS;
    +    $DEFAULT_LANG ||= $LANGS[0];
    +
    +    $SITENAME ||= "NameNotConfigured.com";
    +    unless ($SITENAMESHORT) {
    +        $SITENAMESHORT = $SITENAME;
    +        $SITENAMESHORT =~ s/\..*//;  # remove .net/.com/etc
    +    }
    +    $SITENAMEABBREV ||= "[??]";
    +
    +    $NODB_MSG ||= "Database temporarily unavailable.  Try again shortly.";
    +    $MSG_READONLY_USER ||= "Database temporarily in read-only mode during maintenance.";
    +
    +    $SITEROOT ||= "http://www.$DOMAIN:8011";
    +    $IMGPREFIX ||= "$SITEROOT/img";
    +    $STATPREFIX ||= "$SITEROOT/stc";
    +    $JSPREFIX ||= "$SITEROOT/js";
    +    $USERPIC_ROOT ||= "$LJ::SITEROOT/userpic";
    +    $PALIMGROOT ||= "$LJ::SITEROOT/palimg";
    +
    +    if ($LJ::DB_USERIDMAP ||= "") {
    +        $LJ::DB_USERIDMAP .= "." unless  $LJ::DB_USERIDMAP =~ /\.$/;
    +    }
    +
    +    # path to sendmail and any necessary options
    +    $SENDMAIL ||= "/usr/sbin/sendmail -t -oi";
    +
    +    # protocol, mailserver hostname, and preferential weight.
    +    # qmtp, smtp, dmtp, and sendmail are the currently supported protocols.
    +    @MAIL_TRANSPORTS = ( [ 'sendmail', $SENDMAIL, 1 ] ) unless @MAIL_TRANSPORTS;
    +
    +    # where we set the cookies (note the period before the domain)
    +    $COOKIE_DOMAIN ||= ".$DOMAIN";
    +    $COOKIE_PATH   ||= "/";
    +    @COOKIE_DOMAIN_RESET = ("", "$DOMAIN", ".$DOMAIN") unless @COOKIE_DOMAIN_RESET;
    +
    +    ## default portal options
    +    @PORTAL_COLS = qw(main right moz) unless (@PORTAL_COLS);
    +
    +    $PORTAL_URI ||= "/portal/";           # either "/" or "/portal/"    
    +
    +    $PORTAL_LOGGED_IN ||= {'main' => [ 
    +                                     [ 'update', 'mode=full'],
    +                                     ],
    +                         'right' => [ 
    +                                      [ 'stats', '', ],
    +                                      [ 'bdays', '', ],
    +                                      [ 'popfaq', '', ],
    +                                      ] };
    +    $PORTAL_LOGGED_OUT ||= {'main' => [ 
    +                                      [ 'update', 'mode='],
    +                                      ],
    +                          'right' => [ 
    +                                       [ 'login', '', ],
    +                                       [ 'stats', '', ],
    +                                       [ 'randuser', '', ],
    +                                       [ 'popfaq', '', ],
    +                                       ],
    +                          'moz' => [
    +                                    [ 'login', '', ],
    +                                    ],
    +                          };
    +
    +    $MAX_HINTS_LASTN ||= 100;
    +    $MAX_SCROLLBACK_FRIENDS ||= 1000;
    +    $MAX_USERPIC_KEYWORDS ||= 10;
    +
    +    # this option can be a boolean or a URL, but internally we want a URL
    +    # (which can also be a boolean)
    +    if ($LJ::OPENID_SERVER && $LJ::OPENID_SERVER == 1) {
    +        $LJ::OPENID_SERVER = "$LJ::SITEROOT/openid/server.bml";
    +    }
    +
    +    # set default capability limits if the site maintainer hasn't.
    +    {
    +        my %defcap = (
    +                      'checkfriends' => 1,
    +                      'checkfriends_interval' => 60,
    +                      'friendsviewupdate' => 30,
    +                      'makepoll' => 1,
    +                      'maxfriends' => 500,
    +                      'moodthemecreate' => 1,
    +                      'styles' => 1,
    +                      's2styles' => 1,
    +                      's2viewentry' => 1,
    +                      's2viewreply' => 1,
    +                      's2stylesmax' => 10,
    +                      's2layersmax' => 50,
    +                      'textmessage' => 1,
    +                      'todomax' => 100,
    +                      'todosec' => 1,
    +                      'userdomain' => 0,
    +                      'useremail' => 0,
    +                      'userpics' => 5,
    +                      'findsim' => 1,
    +                      'full_rss' => 1,
    +                      'can_post' => 1,
    +                      'get_comments' => 1,
    +                      'leave_comments' => 1,
    +                      'mod_queue' => 50,
    +                      'mod_queue_per_poster' => 1,
    +                      'weblogscom' => 0,
    +                      'hide_email_after' => 0,
    +                      'userlinks' => 5,
    +                      'maxcomments' => 5000,
    +                      'rateperiod-lostinfo' => 24*60, # 24 hours
    +                      'rateallowed-lostinfo' => 5,
    +                      'tools_recent_comments_display' => 50,
    +                      );
    +        foreach my $k (keys %defcap) {
    +            next if (defined $LJ::CAP_DEF{$k});
    +            $LJ::CAP_DEF{$k} = $defcap{$k};	    
    +        }
    +    }
    +
    +    # FIXME: should forcibly limit userlinks to 255 (tinyint)
    +
    +    # set default userprop limits if site maintainer hasn't
    +    {
    +        my %defuser = (
    +                       's1_lastn_style'    => 'lastn/Default LiveJournal',
    +                       's1_friends_style'  => 'friends/Default Friends View',
    +                       's1_calendar_style' => 'calendar/Default Calendar',
    +                       's1_day_style'      => 'day/Default Day View',
    +                       );
    +        foreach my $k (keys %defuser) {
    +            next if (defined $LJ::USERPROP_DEF{$k});
    +            $LJ::USERPROP_DEF{$k} = $defuser{$k};
    +        }
    +    }
    +
    +    # Send community invites from the admin address unless otherwise specified
    +    $COMMUNITY_EMAIL ||= $ADMIN_EMAIL;
    +
    +    # By default, auto-detect account types for
    +    #  tags only if using memcache
    +    unless (defined $LJ::DYNAMIC_LJUSER) {
    +        $LJ::DYNAMIC_LJUSER = scalar(@LJ::MEMCACHE_SERVERS) ? 1 : 0;
    +    }
    +
    +    # The list of content types that we consider valid for gzip compression.
    +    %GZIP_OKAY = (
    +        'text/html' => 1,               # regular web pages; XHTML 1.0 "may" be this
    +        'text/xml' => 1,                # regular XML files
    +        'application/xml' => 1,         # XHTML 1.1 "may" be this
    +        'application/xhtml+xml' => 1,   # XHTML 1.1 "should" be this
    +        'application/rdf+xml' => 1,     # FOAF should be this
    +    ) unless %GZIP_OKAY;
    +
    +    # maximum FOAF friends to return (so the server doesn't get overloaded)
    +    $MAX_FOAF_FRIENDS ||= 1000;
    +
    +    # maximum number of friendofs to load/memcache (affects userinfo.bml display)
    +    $MAX_FRIENDOF_LOAD ||= 5000;
    +
    +    # whether to proactively delete any comments associated with an entry when we assign
    +    # a new jitemid (see the big comment above LJ::Protocol::new_entry_cleanup_hack)
    +    $NEW_ENTRY_CLEANUP_HACK ||= 0;
    +
    +    # block size is used in stats generation code that gets n rows from the db at a time
    +    $STATS_BLOCK_SIZE ||= 10_000;
    +
    +    # Maximum number of comments to display on Recent Comments page
    +    $TOOLS_RECENT_COMMENTS_MAX = 50;
    +
    +    # setup the mogilefs defaults so we can create the necessary domains
    +    # and such. it is not recommended that you change the name of the
    +    # classes. you can feel free to add your own or alter the mindevcount
    +    # from within ljconfig.pl, but the LiveJournal code uses these class
    +    # names elsewhere and depends on them existing if you're using MogileFS
    +    # for storage.
    +    #
    +    # also note that this won't actually do anything unless you have
    +    # defined a MOGILEFS_CONFIG hash in ljconfig.pl and you explicitly set
    +    # at least the hosts key to be an arrayref of ip:port combinations
    +    # indicating where to reach your local MogileFS server.
    +    %MOGILEFS_CONFIG = () unless defined %MOGILEFS_CONFIG;
    +    $MOGILEFS_CONFIG{domain}                 ||= 'livejournal';
    +    $MOGILEFS_CONFIG{classes}                ||= {};
    +    $MOGILEFS_CONFIG{classes}->{userpics}    ||= 3;
    +    $MOGILEFS_CONFIG{classes}->{captcha}     ||= 2;
    +
    +    # Default to allow all reproxying.
    +    %REPROXY_DISABLE = () unless %REPROXY_DISABLE;
    +
    +    # Default error message for age verification needed
    +    $UNDERAGE_ERROR ||= "Sorry, your account needs to be age verified before you can leave any comments.";
    +
    +    # Terms of Service revision requirements
    +    foreach (
    +             [ rev   => '0.0' ],
    +             [ title => 'Terms of Service agreement required' ],
    +             [ html  => '' ],
    +             [ text  => '' ]
    +             )
    +    {
    +        $LJ::REQUIRED_TOS{$_->[0]} = $_->[1]
    +            unless defined $LJ::REQUIRED_TOS{$_->[0]};
    +    }
    +
    +    # setup default minimal style information
    +    $MINIMAL_USERAGENT{$_} ||= 1 foreach qw(Links Lynx w BlackBerry); # w is for w3m
    +    $MINIMAL_BML_SCHEME ||= 'lynx';
    +    $MINIMAL_STYLE{'core'} ||= 'core1';
    +
    +    # maximum size to cache s2compiled data
    +    $MAX_S2COMPILED_CACHE_SIZE ||= 7500; # bytes
    +    $S2COMPILED_MIGRATION_DONE ||= 0;    # turn on after s2compiled2 migration
    +
    +}
    +
    +# no dependencies.
    +# 
    +# 
    +
    +return 1;
    diff --git a/livejournal/cgi-bin/ljemailgateway.pl b/livejournal/cgi-bin/ljemailgateway.pl
    new file mode 100755
    index 0000000..0e89cd2
    --- /dev/null
    +++ b/livejournal/cgi-bin/ljemailgateway.pl
    @@ -0,0 +1,647 @@
    +#!/usr/bin/perl
    +
    +package LJ::Emailpost;
    +use strict;
    +use lib "$ENV{LJHOME}/cgi-bin";
    +
    +BEGIN {
    +    require 'ljconfig.pl';
    +    if ($LJ::USE_PGP) {
    +        eval 'use GnuPG::Interface';
    +        die "Could not load GnuPG::Interface." if $@;
    +    }
    +}
    +
    +require 'ljlib.pl';
    +require 'ljprotocol.pl';
    +require 'fbupload.pl';
    +use HTML::Entities;
    +use IO::Handle;
    +use LWP::UserAgent;
    +use MIME::Words ();
    +use XML::Simple;
    +
    +# $rv - scalar ref from mailgated.
    +# set to 1 to dequeue, 0 to leave for further processing.
    +sub process {
    +    my ($entity, $to, $rv) = @_;
    +
    +    my (
    +        # journal vars
    +        $head, $user, $journal,
    +        $pin, $u, $req, $post_error,
    +
    +        # email vars
    +        $from, $addrlist, $return_path,
    +        $body, $subject, $charset,
    +        $format, $tent,
    +
    +        # pict upload vars
    +        $fb_upload, $fb_upload_errstr,
    +    );
    +
    +    $head = $entity->head;
    +    $head->unfold;
    +
    +    $$rv = 1;  # default dequeue
    +
    +    # Parse email for lj specific info
    +    ($user, $pin) = split(/\+/, $to);
    +    ($user, $journal) = split(/\./, $user) if $user =~ /\./;
    +    $u = LJ::load_user($user);
    +    return unless $u;
    +    LJ::load_user_props($u, 'emailpost_pin') unless (lc($pin) eq 'pgp' && $LJ::USE_PGP);
    +
    +    # Pick what address to send potential errors to.
    +    $addrlist = LJ::Emailpost::get_allowed_senders($u);
    +    $from = ${(Mail::Address->parse( $head->get('From:') ))[0] || []}[1];
    +    return unless $from;
    +    my $err_addr;
    +    foreach (keys %$addrlist) {
    +        if (lc($from) eq lc &&
    +                $addrlist->{$_}->{'get_errors'}) {
    +            $err_addr = $from;
    +            last;
    +        }
    +    }
    +    $err_addr ||= $u->{email};
    +
    +    my $err = sub {
    +        my ($msg, $opt) = @_;
    +
    +        # FIXME: Need to log last 10 errors to DB / memcache
    +        # and create a page to watch this stuff.
    +
    +        my $errbody;
    +        $errbody .= "There was an error during your email posting:\n\n";
    +        $errbody .= $msg;
    +        if ($body) {
    +            $errbody .= "\n\n\nOriginal posting follows:\n\n";
    +            $errbody .= $body;
    +        }
    +
    +        # Rate limit email to 1/5min/address
    +        if ($opt->{'sendmail'} && $err_addr &&
    +            LJ::MemCache::add("rate_eperr:$err_addr", 5, 300)) {
    +            LJ::send_mail({
    +                    'to' => $err_addr,
    +                    'from' => $LJ::BOGUS_EMAIL,
    +                    'fromname' => "$LJ::SITENAME Error",
    +                    'subject' => "$LJ::SITENAME posting error: $subject",
    +                    'body' => $errbody
    +                    });
    +        }
    +        $$rv = 0 if $opt->{'retry'};
    +        return $msg;
    +    };
    +
    +    # The return path should normally not ever be perverted enough to require this,
    +    # but some mailers nowadays do some very strange things.
    +    $return_path = ${(Mail::Address->parse( $head->get('Return-Path') ))[0] || []}[1];
    +
    +    # Use text/plain piece first - if it doesn't exist, then fallback to text/html
    +    $tent = get_entity( $entity );
    +    $tent = get_entity( $entity, 'html' ) unless $tent;
    +
    +    $body = $tent ? $tent->bodyhandle->as_string : "";
    +    $body =~ s/^\s+//;
    +    $body =~ s/\s+$//;
    +
    +    # Snag charset and do utf-8 conversion
    +    my $content_type = $head->get('Content-type:');
    +    $charset = $1 if $content_type =~ /\bcharset=['"]?(\S+?)['"]?[\s\;]/i;
    +    $format = $1 if $content_type =~ /\bformat=['"]?(\S+?)['"]?[\s\;]/i;
    +    if (defined($charset) && $charset !~ /^UTF-?8$/i) { # no charset? assume us-ascii
    +        return $err->("Unknown charset encoding type.", { sendmail => 1 })
    +            unless Unicode::MapUTF8::utf8_supported_charset($charset);
    +        $body = Unicode::MapUTF8::to_utf8({-string=>$body, -charset=>$charset});
    +    }
    +
    +    # check subject for rfc-1521 junk
    +    $subject ||= $head->get('Subject:');
    +    if ($subject =~ /^=\?/) {
    +        my @subj_data = MIME::Words::decode_mimewords( $subject );
    +        if (@subj_data) {
    +            if ($subject =~ /utf-8/i) {
    +                $subject = $subj_data[0][0];
    +            } else {
    +                $subject = Unicode::MapUTF8::to_utf8(
    +                    {
    +                        -string  => $subj_data[0][0],
    +                        -charset => $subj_data[0][1]
    +                    }
    +                );
    +            }
    +        }
    +    }
    +    
    +    # Strip (and maybe use) pin data from viewable areas
    +    if ($subject =~ s/^\s*\+([a-z0-9]+)\s+//i) {
    +        $pin = $1 unless defined $pin;
    +    }
    +    if ($body =~ s/^\s*\+([a-z0-9]+)\s+//i) {
    +        $pin = $1 unless defined $pin;
    +    }
    +
    +    # Validity checks.  We only care about these if they aren't using PGP.
    +    unless (lc($pin) eq 'pgp' && $LJ::USE_PGP) {
    +        return $err->("No allowed senders have been saved for your account.") unless ref $addrlist;
    +
    +        # don't mail user due to bounce spam
    +        return $err->("Unauthorized sender address: $from")
    +            unless grep { lc($from) eq lc($_) } keys %$addrlist;
    +
    +        return $err->("Unable to locate your PIN.", { sendmail => 1 }) unless $pin;
    +        return $err->("Invalid PIN.", { sendmail => 1 }) unless lc($pin) eq lc($u->{emailpost_pin});
    +    }
    +
    +    return $err->("Email gateway access denied for your account type.", { sendmail => 1 })
    +        unless LJ::get_cap($u, "emailpost");
    +
    +    # Is this message from a sprint PCS phone?  Sprint doesn't support
    +    # MMS (yet) - when it does, we should just be able to rip this block
    +    # of code completely out.
    +    #
    +    # Sprint has two methods of non-mms mail sending.
    +    #   -  Normal text messaging just sends a text/plain piece.
    +    #   -  Sprint "PictureMail".
    +    # PictureMail sends a text/html piece, that contains XML with
    +    # the location of the image on their servers - and a text/plain as well.
    +    # (The text/plain used to be blank, now it's really text/plain.  We still
    +    # can't use it, however, without heavy and fragile parsing.)
    +    # We assume the existence of a text/html means this is a PictureMail message,
    +    # as there is no other method (headers or otherwise) to tell the difference,
    +    # and Sprint tells me that their text messaging never contains text/html.
    +    # Currently, PictureMail can only contain one image per message
    +    # and the image is always a jpeg. (2/2/05)
    +    if ($return_path =~ /(?:messaging|pm)\.sprint(?:pcs)?\.com/ &&
    +        $content_type =~ m#^multipart/alternative#i) {
    +
    +        $tent = get_entity( $entity, 'html' );
    +
    +        return $err->(
    +            "Unable to find Sprint HTML content in PictureMail message.",
    +            { sendmail => 1 }
    +          ) unless $tent;
    +
    +        # ok, parse the XML.
    +        my $html = $tent->bodyhandle->as_string();
    +        my $xml_string = $1 if $html =~ //is;
    +        return $err->(
    +            "Unable to find XML content in PictureMail message.",
    +            { sendmail => 1 }
    +          ) unless $xml_string;
    +
    +        HTML::Entities::decode_entities( $xml_string );
    +        my $xml = eval { XML::Simple::XMLin( $xml_string ); };
    +        return $err->(
    +            "Unable to parse XML content in PictureMail message.",
    +            { sendmail => 1 }
    +          ) if ( ! $xml || $@ );
    +
    +        return $err->(
    +            "Sorry, we currently only support image media.",
    +            { sendmail => 1 }
    +          ) unless $xml->{messageContents}->{type} eq 'PICTURE';
    +
    +        my $url =
    +          HTML::Entities::decode_entities(
    +            $xml->{messageContents}->{mediaItems}->{mediaItem}->{content} );
    +        $url = LJ::trim($url);
    +        $url =~ s###g;
    +
    +        return $err->(
    +            "Invalid remote SprintPCS URL.", { sendmail => 1 }
    +          ) unless $url =~ m#^http://pictures.sprintpcs.com/#;
    +
    +        # we've got the url to the full sized image.
    +        # fetch!
    +        my ($tmpdir, $tempfile);
    +        $tmpdir = File::Temp::tempdir( "ljmailgate_" . 'X' x 20, DIR=> $main::workdir );
    +        ( undef, $tempfile ) = File::Temp::tempfile(
    +            'sprintpcs_XXXXX',
    +            SUFFIX => '.jpg',
    +            OPEN   => 0,
    +            DIR    => $tmpdir
    +        );
    +        my $ua = LWP::UserAgent->new(
    +            timeout => 20,
    +            agent   => 'Mozilla',
    +        );
    +        my $ua_rv = $ua->get( $url, ':content_file' => $tempfile );
    +
    +        $body = $xml->{messageContents}->{messageText};
    +        $body = ref $body ? "" : HTML::Entities::decode( $body );
    +
    +        if ($ua_rv->is_success) {
    +            # (re)create a basic mime entity, so the rest of the
    +            # emailgateway can function without modifications.
    +            # (We don't need anything but Data, the other parts have
    +            # already been pulled from $head->unfold)
    +            $subject = 'Picture Post';
    +            $entity = MIME::Entity->build( Data => $body );
    +            $entity->attach(
    +                Path => $tempfile,
    +                Type => 'image/jpeg'
    +            );
    +        }
    +        else {
    +            # Retry if we are unable to connect to the remote server.
    +            # Otherwise, the image has probably expired.  Dequeue.
    +            my $reason = $ua_rv->status_line;
    +            return $err->(
    +                "Unable to fetch SprintPCS image. ($reason)",
    +                { 
    +                    sendmail => 1,
    +                    retry => $reason =~ /Connection refused/
    +                }
    +            );
    +        }
    +    } 
    +
    +    # tmobile hell.
    +    # if there is a message, then they send text/plain and text/html,
    +    # with a slew of their tmobile specific images.  If no message
    +    # is attached, there is no text/plain piece, and the journal is
    +    # polluted with their advertising.  (The tmobile images (both good
    +    # and junk) are posted to scrapbook either way.)
    +    # gross.  do our best to strip out the nasty stuff.
    +    if ($return_path && $return_path =~ /tmomail\.net$/ &&
    +        $head->get("X-Operator") =~ /^T-Mobile/i) {
    +
    +        # if we aren't using their text/plain, then it's just
    +        # advertising, and nothing else.  kill it.
    +        $body = "" if $tent->effective_type eq 'text/html';
    +
    +        # strip all images but tmobile phone dated.
    +        # 06-03-05_12394.jpg
    +        my @imgs;
    +        foreach my $img ( get_entity($entity, 'image') ) {
    +            my $path = $img->bodyhandle->path;
    +            $path =~ s#.*/##;
    +            # intentionally not being explicit with regexp, in case
    +            # they go to 4 digit year or whatever.
    +            push @imgs, $img if $path =~ /^\d+-\d+-\d+_\d+.\w+$/;
    +        }
    +        $entity->parts(\@imgs);
    +    }
    +
    +    # PGP signed mail?  We'll see about that.
    +    if (lc($pin) eq 'pgp' && $LJ::USE_PGP) {
    +        my %gpg_errcodes = ( # temp mapping until translation
    +                'bad'         => "PGP signature found to be invalid.",
    +                'no_key'      => "You don't have a PGP key uploaded.",
    +                'bad_tmpdir'  => "Problem generating tempdir: Please try again.",
    +                'invalid_key' => "Your PGP key is invalid.  Please upload a proper key.",
    +                'not_signed'  => "You specified PGP verification, but your message isn't PGP signed!");
    +        my $gpgerr;
    +        my $gpgcode = LJ::Emailpost::check_sig($u, $entity, \$gpgerr);
    +        unless ($gpgcode eq 'good') {
    +            my $errstr = $gpg_errcodes{$gpgcode};
    +            $errstr .= "\nGnuPG error output:\n$gpgerr\n" if $gpgerr;
    +            return $err->($errstr, { sendmail => 1 });
    +        }
    +
    +        # Strip pgp clearsigning and any extra text surrounding it
    +        # This takes into account pgp 'dash escaping' and a possible lack of Hash: headers
    +        $body =~ s/.*?^-----BEGIN PGP SIGNED MESSAGE-----(?:\n[^\n].*?\n\n|\n\n)//ms;
    +        $body =~ s/-----BEGIN PGP SIGNATURE-----.+//s;
    +    }
    +
    +    $body =~ s/^(?:\- )?[\-_]{2,}\s*\r?\n.*//ms; # trim sigs
    +    $body =~ s/ \n/ /g if lc($format) eq 'flowed'; # respect flowed text
    +
    +    # trim off excess whitespace (html cleaner converts to breaks)
    +    $body =~ s/\n+$/\n/;
    +
    +    # Find and set entry props.
    +    my $props = {};
    +    my (%lj_headers, $amask);
    +    if ($body =~ s/^(lj-.+?)\n\n//is) {
    +        map { $lj_headers{lc($1)} = $2 if /^lj-(\w+):\s*(.+?)\s*$/i } split /\n/, $1;
    +    }
    +
    +    LJ::load_user_props(
    +        $u,
    +        qw/
    +          emailpost_userpic emailpost_security
    +          emailpost_comments emailpost_gallery
    +          emailpost_imgsecurity /
    +    );
    +
    +    # Get post options, using lj-headers first, and falling back
    +    # to user props.  If neither exist, the regular journal defaults
    +    # are used.
    +    $props->{taglist} = $lj_headers{tags};
    +    $props->{picture_keyword} = $lj_headers{'userpic'} ||
    +                                $u->{'emailpost_userpic'};
    +    $props->{current_mood}   = $lj_headers{'mood'};
    +    $props->{current_music}  = $lj_headers{'music'};
    +    $props->{opt_nocomments} = 1
    +      if $lj_headers{comments}      =~ /off/i
    +      || $u->{'emailpost_comments'} =~ /off/i;
    +    $props->{opt_noemail} = 1
    +      if $lj_headers{comments}      =~ /noemail/i
    +      || $u->{'emailpost_comments'} =~ /noemail/i;
    +
    +    $lj_headers{security} = lc($lj_headers{security}) || $u->{'emailpost_security'};
    +    if ($lj_headers{security} =~ /^(public|private|friends)$/) {
    +        if ($1 eq 'friends') {
    +            $lj_headers{security} = 'usemask';
    +            $amask = 1;
    +        }
    +    } elsif ($lj_headers{security}) { # Assume a friendgroup if unknown security mode.
    +        # Get the mask for the requested friends group, or default to private.
    +        my $group = LJ::get_friend_group($u, { 'name'=>$lj_headers{security} });
    +        if ($group) {
    +            $amask = (1 << $group->{groupnum});
    +            $lj_headers{security} = 'usemask';
    +        } else {
    +            $err->("Friendgroup \"$lj_headers{security}\" not found.  Your journal entry was posted privately.",
    +                   { sendmail => 1 });
    +            $lj_headers{security} = 'private';
    +        }
    +    }
    +
    +    # if they specified a imgsecurity header but it isn't valid, default
    +    # to private.  Otherwise, set to what they specified.
    +    $lj_headers{'imgsecurity'} = lc($lj_headers{'imgsecurity'}) ||
    +                                 $u->{'emailpost_imgsecurity'}  || 'public';
    +    $lj_headers{'imgsecurity'} = 'private'
    +      unless $lj_headers{'imgsecurity'} =~ /^(private|regusers|friends|public)$/;
    +
    +    # upload picture attachments to fotobilder.
    +    # undef return value? retry posting for later.
    +    $fb_upload = upload_images(
    +        $entity, $u,
    +        \$fb_upload_errstr,
    +        {
    +            imgsec  => $lj_headers{'imgsecurity'},
    +            galname => $lj_headers{'gallery'} || $u->{'emailpost_gallery'}
    +        }
    +      ) || return $err->( $fb_upload_errstr, { retry => 1 } );
    +
    +    # if we found and successfully uploaded some images...
    +    $body .= LJ::FBUpload::make_html( $u, $fb_upload, \%lj_headers )
    +      if ref $fb_upload eq 'ARRAY';
    +
    +    # at this point, there are either no images in the message ($fb_upload == 1)
    +    # or we had some error during upload that we may or may not want to retry
    +    # from.  $fb_upload contains the http error code.
    +    if (   $fb_upload == 400   # bad http request
    +        || $fb_upload == 1401  # user has exceeded the fb quota         
    +        || $fb_upload == 1402  # user has exceeded the fb quota
    +    ) {
    +        # don't retry these errors, go ahead and post the body
    +        # to the journal, postfixed with the remote error.
    +        $body .= "\n";
    +        $body .= "(Your picture was not posted: $fb_upload_errstr)";
    +    }
    +
    +    # Fotobilder server error.  Retry.
    +    return $err->( $fb_upload_errstr, { retry => 1 } ) if $fb_upload == 500;
    +
    +    # build lj entry
    +    $req = {
    +        'usejournal' => $journal,
    +        'ver' => 1,
    +        'username' => $user,
    +        'event' => $body,
    +        'subject' => $subject,
    +        'security' => $lj_headers{security},
    +        'allowmask' => $amask,
    +        'props' => $props,
    +        'tz'    => 'guess',
    +    };
    +
    +    # post!
    +    LJ::Protocol::do_request("postevent", $req, \$post_error, { noauth=>1 });
    +    return $err->(LJ::Protocol::error_message($post_error), { sendmail => 1}) if $post_error;
    +
    +    return "Email post success";
    +}
    +
    +# By default, returns first plain text entity from email message.
    +# Specifying a type will return an array of MIME::Entity handles
    +# of that type. (image, application, etc)
    +# Specifying a type of 'all' will return all MIME::Entities,
    +# regardless of type.
    +sub get_entity
    +{
    +    my ($entity, $type) = @_;
    +
    +    # old arguments were a hashref
    +    $type = $type->{'type'} if ref $type eq "HASH";
    +
    +    # default to text
    +    $type ||= 'text';
    +
    +    my $head = $entity->head;
    +    my $mime_type = $head->mime_type;
    +
    +    return $entity if $type eq 'text' && $mime_type eq "text/plain";
    +    return $entity if $type eq 'html' && $mime_type eq "text/html";
    +    my @entities;
    +
    +    # Only bother looking in messages that advertise attachments
    +    my $mimeattach_re = qr{ m|^multipart/(?:alternative|signed|mixed|related)$| };
    +    if ($mime_type =~ $mimeattach_re) {
    +        my $partcount = $entity->parts;
    +        for (my $i=0; $i<$partcount; $i++) {
    +            my $alte = $entity->parts($i);
    +
    +            return $alte if $type eq 'text' && $alte->mime_type eq "text/plain";
    +            return $alte if $type eq 'html' && $alte->mime_type eq "text/html";
    +            push @entities, $alte if $type eq 'all';
    +
    +            if ($type eq 'image' &&
    +                $alte->mime_type =~ m#^application/octet-stream#) {
    +                my $alte_head = $alte->head;
    +                my $filename = $alte_head->recommended_filename;
    +                push @entities, $alte if $filename =~ /\.(?:gif|png|tiff?|jpe?g)$/;
    +            }
    +            push @entities, $alte if $alte->mime_type =~ /^$type/ &&
    +                                     $type ne 'all';
    +
    +            # Recursively search through nested MIME for various pieces
    +            if ($alte->mime_type =~ $mimeattach_re) {
    +                if ($type =~ /^(?:text|html)$/) {
    +                    my $text_entity = get_entity($entity->parts($i), $type);
    +                    return $text_entity if $text_entity;
    +                } else {
    +                    push @entities, get_entity($entity->parts($i), $type);
    +                }
    +            }
    +        }
    +    }
    +
    +    return @entities if $type ne 'text' && scalar @entities;
    +    return;
    +}
    +
    +# Verifies an email pgp signature as being valid.
    +# Returns codes so we can use the pre-existing err subref,
    +# without passing everything all over the place.
    +#
    +# note that gpg interaction requires gpg version 1.2.4 or better.
    +sub check_sig {
    +    my ($u, $entity, $gpg_err) = @_;
    +
    +    LJ::load_user_props($u, 'public_key');
    +    my $key = $u->{public_key};
    +    return 'no_key' unless $key;
    +
    +    # Create work directory.
    +    my $tmpdir = File::Temp::tempdir("ljmailgate_" . 'X' x 20, DIR=>$main::workdir);
    +    return 'bad_tmpdir' unless -e $tmpdir;
    +
    +    my ($in, $out, $err, $status,
    +        $gpg_handles, $gpg, $gpg_pid, $ret);
    +
    +    my $check = sub {
    +        my %rets =
    +            (
    +             'NODATA 1'     => 1,   # no key or no signed data
    +             'NODATA 2'     => 2,   # no signed content
    +             'NODATA 3'     => 3,   # error checking sig (crc)
    +             'IMPORT_RES 0' => 4,   # error importing key (crc)
    +             'BADSIG'       => 5,   # good crc, bad sig
    +             'GOODSIG'      => 6,   # all is well
    +            );
    +        while (my $gline = <$status>) {
    +            foreach (keys %rets) {
    +                next unless $gline =~ /($_)/;
    +                return $rets{$1};
    +            }
    +        }
    +        return 0;
    +    };
    +
    +    my $gpg_cleanup = sub {
    +        close $in;
    +        close $out;
    +        waitpid $gpg_pid, 0;
    +        undef foreach $gpg, $gpg_handles;
    +    };
    +
    +    my $gpg_pipe = sub {
    +        $_ = IO::Handle->new() foreach $in, $out, $err, $status;
    +        $gpg_handles = GnuPG::Handles->new( stdin  => $in,  stdout=> $out,
    +                                            stderr => $err, status=> $status );
    +        $gpg = GnuPG::Interface->new();
    +        $gpg->options->hash_init( armor=>1, homedir=>$tmpdir );
    +        $gpg->options->meta_interactive( 0 );
    +    };
    +
    +    # Pull in user's key, add to keyring.
    +    $gpg_pipe->();
    +    $gpg_pid = $gpg->import_keys( handles=>$gpg_handles );
    +    print $in $key;
    +    $gpg_cleanup->();
    +    $ret = $check->();
    +    if ($ret && $ret == 1 || $ret == 4) {
    +        $$gpg_err .= "    $_" while (<$err>);
    +        return 'invalid_key';
    +    }
    +
    +    my ($txt, $txt_f, $txt_e, $sig_e);
    +    $txt_e = (get_entity($entity))[0];
    +    return 'bad' unless $txt_e;
    +
    +    if ($entity->effective_type() eq 'multipart/signed') {
    +        # attached signature
    +        $sig_e = (get_entity($entity, 'application/pgp-signature'))[0];
    +        $txt = $txt_e->as_string();
    +        my $txt_fh;
    +        ($txt_fh, $txt_f) =
    +            File::Temp::tempfile('plaintext_XXXXXXXX', DIR => $tmpdir);
    +        print $txt_fh $txt;
    +        close $txt_fh;
    +    } # otherwise, it's clearsigned
    +
    +    # Validate message.
    +    # txt_e->bodyhandle->path() is clearsigned message in its entirety.
    +    # txt_f is the ascii text that was signed (in the event of sig-as-attachment),
    +    #     with MIME headers attached.
    +    $gpg_pipe->();
    +    $gpg_pid =
    +        $gpg->wrap_call( handles => $gpg_handles,
    +                         commands => [qw( --trust-model always --verify )],
    +                         command_args => $sig_e ? 
    +                             [$sig_e->bodyhandle->path(), $txt_f] :
    +                             $txt_e->bodyhandle->path()
    +                    );
    +    $gpg_cleanup->();
    +    $ret = $check->();
    +    if ($ret && $ret != 6) {
    +        $$gpg_err .= "    $_" while (<$err>);
    +        return 'bad' if $ret =~ /[35]/;
    +        return 'not_signed' if $ret =~ /[12]/;
    +    }
    +
    +    return 'good' if $ret == 6;
    +    return undef;
    +}
    +
    +# Upload images to a Fotobilder installation.
    +# Return codes:
    +# 1 - no images found in mime entity
    +# undef - failure during upload
    +# http_code - failure during upload w/ code
    +# hashref - { title => url } for each image uploaded
    +sub upload_images
    +{
    +    my ($entity, $u, $rv, $opts) = @_;
    +    return 1 unless LJ::get_cap($u, 'fb_can_upload') && $LJ::FB_SITEROOT;
    +
    +    my @imgs = get_entity($entity, 'image');
    +    return 1 unless scalar @imgs;
    +
    +    my @images;
    +    foreach my $img_entity (@imgs) {
    +        my $img     = $img_entity->bodyhandle;
    +        my $path    = $img->path;
    +        
    +        my $result = LJ::FBUpload::do_upload(
    +            $u, $rv,
    +            {
    +                path    => $path,
    +                rawdata => \$img->as_string,
    +                imgsec  => $opts->{'imgsec'},
    +                galname => $opts->{'galname'},
    +            }
    +        );
    +
    +        # do upload() returned undef?  This is a posting error
    +        # that should most likely be retried, due to something 
    +        # wrong on our side of things.
    +        return if ! defined $result && $$rv;
    +
    +        # http error during upload attempt
    +        # decide retry based on error type in caller
    +        return $result unless ref $result; 
    +
    +        # examine $result for errors
    +        if ($result->{Error}->{code}) {
    +            $$rv = $result->{Error}->{content};
    +
    +            # add 1000 to error code, so we can easily tell the
    +            # difference between fb protocol error and
    +            # http error when checking results.
    +            return $result->{Error}->{code} + 1000; 
    +        }
    +
    +        push @images, {
    +            url     => $result->{URL},
    +            width   => $result->{Width},
    +            height  => $result->{Height},
    +            title   => $result->{Title},
    +        };
    +    }
    +
    +    return \@images if scalar @images;
    +    return;
    +}
    +
    +1;
    +
    diff --git a/livejournal/cgi-bin/ljfeed.pl b/livejournal/cgi-bin/ljfeed.pl
    new file mode 100755
    index 0000000..fc92029
    --- /dev/null
    +++ b/livejournal/cgi-bin/ljfeed.pl
    @@ -0,0 +1,556 @@
    +#!/usr/bin/perl
    +
    +use strict;
    +
    +package LJ::Feed;
    +
    +my %feedtypes = (
    +    rss  => \&create_view_rss,
    +    atom => \&create_view_atom,
    +    foaf => \&create_view_foaf,
    +);
    +
    +sub make_feed
    +{
    +    my ($r, $u, $remote, $opts) = @_;
    +
    +    $opts->{pathextra} =~ s!^/(\w+)!!;
    +    my $feedtype = $1;
    +    my $viewfunc = $feedtypes{$feedtype};
    +
    +    unless ($viewfunc) {
    +        $opts->{'handler_return'} = 404;
    +        return undef;
    +    }
    +    
    +    $opts->{noitems} = 1 if $feedtype eq 'foaf';
    +
    +    $r->notes('codepath' => "feed.$feedtype") if $r;
    +
    +    my $dbr = LJ::get_db_reader();
    +
    +    my $user = $u->{'user'};
    +    
    +    if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") {
    +        $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . "/data/$feedtype";
    +        return undef;
    +    }
    +
    +    LJ::load_user_props($u, qw/ journaltitle journalsubtitle opt_synlevel /);
    +
    +    LJ::text_out(\$u->{$_}) 
    +        foreach ("name", "url", "urlname");
    +    
    +    # opt_synlevel will default to 'full'
    +    $u->{'opt_synlevel'} = 'full' 
    +        unless $u->{'opt_synlevel'} =~ /^(?:full|summary|title)$/;
    +
    +    # some data used throughout the channel
    +    my $journalinfo = {
    +        u         => $u,
    +        link      => LJ::journal_base($u) . "/",
    +        title     => $u->{journaltitle} || $u->{name} || $u->{user},
    +        subtitle  => $u->{journalsubtitle} || $u->{name},
    +        builddate => LJ::time_to_http(time()),
    +    };
    +
    +    # if we do not want items for this view, just call out
    +    return $viewfunc->($journalinfo, $u, $opts)
    +        if ($opts->{'noitems'});
    +
    +    # for syndicated accounts, redirect to the syndication URL
    +    # However, we only want to do this if the data we're returning
    +    # is similar. (Not FOAF, for example)
    +    if ($u->{'journaltype'} eq 'Y') {
    +        my $synurl = $dbr->selectrow_array("SELECT synurl FROM syndicated WHERE userid=$u->{'userid'}");
    +        unless ($synurl) {
    +            return 'No syndication URL available.';
    +        }
    +        $opts->{'redir'} = $synurl;
    +        return undef;
    +    }
    +
    +    ## load the itemids
    +    my @itemids;
    +    my @items = LJ::get_recent_items({
    +        'clusterid' => $u->{'clusterid'},
    +        'clustersource' => 'slave',
    +        'remote' => $remote,
    +        'userid' => $u->{'userid'},
    +        'itemshow' => 25,
    +        'order' => "logtime",
    +        'itemids' => \@itemids,
    +        'friendsview' => 1,           # this returns rlogtimes
    +        'dateformat' => "S2",         # S2 format time format is easier
    +    });
    +
    +    $opts->{'contenttype'} = 'text/xml; charset='.$opts->{'saycharset'};
    +
    +    ### load the log properties
    +    my %logprops = ();
    +    my $logtext;
    +    my $logdb = LJ::get_cluster_reader($u);
    +    LJ::load_log_props2($logdb, $u->{'userid'}, \@itemids, \%logprops);
    +    $logtext = LJ::get_logtext2($u, @itemids);
    +
    +    # set last-modified header, then let apache figure out
    +    # whether we actually need to send the feed.
    +    my $lastmod = 0;
    +    foreach my $item (@items) {
    +        # revtime of the item.
    +        my $revtime = $logprops{$item->{itemid}}->{revtime};
    +        $lastmod = $revtime if $revtime > $lastmod;
    +
    +        # if we don't have a revtime, use the logtime of the item.
    +        unless ($revtime) {
    +            my $itime = $LJ::EndOfTime - $item->{rlogtime};
    +            $lastmod = $itime if $itime > $lastmod;
    +        }
    +    }
    +    $r->set_last_modified($lastmod) if $lastmod;
    +
    +    # use this $lastmod as the feed's last-modified time
    +    # we would've liked to use something like 
    +    # LJ::get_timeupdate_multi instead, but that only changes
    +    # with new updates and doesn't change on edits.
    +    $journalinfo->{'modtime'} = $lastmod;
    +
    +    # regarding $r->set_etag:
    +    # http://perl.apache.org/docs/general/correct_headers/correct_headers.html#Entity_Tags
    +    # It is strongly recommended that you do not use this method unless you
    +    # know what you are doing. set_etag() is expecting to be used in
    +    # conjunction with a static request for a file on disk that has been
    +    # stat()ed in the course of the current request. It is inappropriate and
    +    # "dangerous" to use it for dynamic content.
    +    if ((my $status = $r->meets_conditions) != Apache::Constants::OK()) {
    +        $opts->{handler_return} = $status;
    +        return undef;
    +    }
    +
    +    # email address of journal owner, but respect their privacy settings
    +    if ($u->{'allow_contactshow'} eq "Y" && $u->{'opt_whatemailshow'} ne "N" && $u->{'opt_mangleemail'} ne "Y") {
    +        my $cemail;
    +        
    +        # default to their actual email
    +        $cemail = $u->{'email'};
    +        
    +        # use their livejournal email if they have one
    +        if ($LJ::USER_EMAIL && $u->{'opt_whatemailshow'} eq "L" &&
    +            LJ::get_cap($u, "useremail") && ! $u->{'no_mail_alias'}) {
    +
    +            $cemail = "$u->{'user'}\@$LJ::USER_DOMAIN";
    +        } 
    +
    +        # clean it up since we know we have one now
    +        $journalinfo->{email} = $cemail;
    +    }
    +
    +    # load tags now that we have no chance of jumping out early
    +    my $logtags = LJ::Tags::get_logtags($u, \@itemids);
    +
    +    my %posteru = ();  # map posterids to u objects
    +    LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @items], [$u]);
    +
    +    my @cleanitems;
    +  ENTRY:
    +    foreach my $it (@items) 
    +    {
    +        # load required data
    +        my $itemid  = $it->{'itemid'};
    +        my $ditemid = $itemid*256 + $it->{'anum'};
    +
    +        next ENTRY if $posteru{$it->{'posterid'}} && $posteru{$it->{'posterid'}}->{'statusvis'} eq 'S';
    +
    +        if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) {
    +            LJ::item_toutf8($u, \$logtext->{$itemid}->[0],
    +                            \$logtext->{$itemid}->[1], $logprops{$itemid});
    +        }
    +
    +        # see if we have a subject and clean it
    +        my $subject = $logtext->{$itemid}->[0];
    +        if ($subject) {
    +            $subject =~ s/[\r\n]/ /g;
    +            LJ::CleanHTML::clean_subject_all(\$subject);
    +        }
    +
    +        # an HTML link to the entry. used if we truncate or summarize
    +        my $readmore = "({link}$ditemid.html\">Read more ...)";
    +
    +        # empty string so we don't waste time cleaning an entry that won't be used
    +        my $event = $u->{'opt_synlevel'} eq 'title' ? '' : $logtext->{$itemid}->[1];
    +
    +        # clean the event, if non-empty
    +        my $ppid = 0;
    +        if ($event) {
    +
    +            # users without 'full_rss' get their logtext bodies truncated
    +            # do this now so that the html cleaner will hopefully fix html we break
    +            unless (LJ::get_cap($u, 'full_rss')) {
    +                my $trunc = LJ::text_trim($event, 0, 80);
    +                $event = "$trunc $readmore" if $trunc ne $event;
    +            }
    +
    +            LJ::CleanHTML::clean_event(\$event, 
    +                                       { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'} });
    +        
    +            # do this after clean so we don't have to about know whether or not
    +            # the event is preformatted
    +            if ($u->{'opt_synlevel'} eq 'summary') {
    +
    +                # assume the first paragraph is terminated by two 
    or a

    + # valid XML tags should be handled, even though it makes an uglier regex + if ($event =~ m!((()?\s*){2})|()!i) { + # everything before the matched tag + the tag itself + # + a link to read more + $event = $` . $& . $readmore; + } + } + + if ($event =~ //) { + my $pollid = $1; + my $name = $dbr->selectrow_array("SELECT name FROM poll WHERE pollid=?", + undef, $pollid); + + if ($name) { + LJ::Poll::clean_poll(\$name); + } else { + $name = "#$pollid"; + } + + $event =~ s!!!g; + } + + $ppid = $1 + if $event =~ m!!; + } + + my $mood; + if ($logprops{$itemid}->{'current_mood'}) { + $mood = $logprops{$itemid}->{'current_mood'}; + } elsif ($logprops{$itemid}->{'current_moodid'}) { + $mood = LJ::mood_name($logprops{$itemid}->{'current_moodid'}+0); + } + + my $createtime = $LJ::EndOfTime - $it->{rlogtime}; + my $cleanitem = { + itemid => $itemid, + ditemid => $ditemid, + subject => $subject, + event => $event, + createtime => $createtime, + eventtime => $it->{alldatepart}, # ugly: this is of a different format than the other two times. + modtime => $logprops{$itemid}->{revtime} || $createtime, + comments => ($logprops{$itemid}->{'opt_nocomments'} == 0), + music => $logprops{$itemid}->{'current_music'}, + mood => $mood, + ppid => $ppid, + tags => [ values %{$logtags->{$itemid} || {}} ], + }; + push @cleanitems, $cleanitem; + } + + # fix up the build date to use entry-time + $journalinfo->{'builddate'} = LJ::time_to_http($LJ::EndOfTime - $items[0]->{'rlogtime'}), + + return $viewfunc->($journalinfo, $u, $opts, \@cleanitems); +} + +# the creator for the RSS XML syndication view +sub create_view_rss +{ + my ($journalinfo, $u, $opts, $cleanitems) = @_; + + my $ret; + + # header + $ret .= "{'saycharset'}' ?>\n"; + $ret .= LJ::run_hook("bot_director", "") . "\n"; + $ret .= "\n"; + + # channel attributes + $ret .= "\n"; + $ret .= " " . LJ::exml($journalinfo->{title}) . "\n"; + $ret .= " $journalinfo->{link}\n"; + $ret .= " " . LJ::exml("$journalinfo->{title} - $LJ::SITENAME") . "\n"; + $ret .= " " . LJ::exml($journalinfo->{email}) . "\n" if $journalinfo->{email}; + $ret .= " $journalinfo->{builddate}\n"; + $ret .= " LiveJournal / $LJ::SITENAME\n"; + # TODO: add 'language' field when user.lang has more useful information + + ### image block, returns info for their current userpic + if ($u->{'defaultpicid'}) { + my $pic = {}; + LJ::load_userpics($pic, [ $u, $u->{'defaultpicid'} ]); + $pic = $pic->{$u->{'defaultpicid'}}; # flatten + + $ret .= " \n"; + $ret .= " $LJ::USERPIC_ROOT/$u->{'defaultpicid'}/$u->{'userid'}\n"; + $ret .= " " . LJ::exml($journalinfo->{title}) . "\n"; + $ret .= " $journalinfo->{link}\n"; + $ret .= " $pic->{'width'}\n"; + $ret .= " $pic->{'height'}\n"; + $ret .= " \n\n"; + } + + my %posteru = (); # map posterids to u objects + LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @$cleanitems], [$u]); + + # output individual item blocks + + foreach my $it (@$cleanitems) + { + my $itemid = $it->{itemid}; + my $ditemid = $it->{ditemid}; + $ret .= "\n"; + $ret .= " $journalinfo->{link}$ditemid.html\n"; + $ret .= " " . LJ::time_to_http($it->{createtime}) . "\n"; + $ret .= " " . LJ::exml($it->{subject}) . "\n" if $it->{subject}; + $ret .= " " . LJ::exml($journalinfo->{email}) . "" if $journalinfo->{email}; + $ret .= " $journalinfo->{link}$ditemid.html\n"; + # omit the description tag if we're only syndicating titles + # note: the $event was also emptied earlier, in make_feed + unless ($u->{'opt_synlevel'} eq 'title') { + $ret .= " " . LJ::exml($it->{event}) . "\n"; + } + if ($it->{comments}) { + $ret .= " $journalinfo->{link}$ditemid.html\n"; + } + $ret .= " $_\n" foreach map { LJ::exml($_) } @{$it->{tags} || []}; + # support 'podcasting' enclosures + $ret .= LJ::run_hook( "pp_rss_enclosure", + { userid => $u->{userid}, ppid => $it->{ppid} }) if $it->{ppid}; + # TODO: add author field with posterid's email address, respect communities + $ret .= " " . LJ::exml($it->{music}) . "\n" if $it->{music}; + $ret .= " " . LJ::exml($it->{mood}) . "\n" if $it->{mood}; + $ret .= "\n"; + } + + $ret .= "\n"; + $ret .= "\n"; + + return $ret; +} + + +# the creator for the Atom view +# keys of $opts: +# saycharset - required: the charset of the feed +# noheader - only output an .. block. off by default +# apilinks - output AtomAPI links for posting a new entry or +# getting/editing/deleting an existing one. off by default +# TODO: define and use an 'lj:' namespace + +sub create_view_atom +{ + my ($journalinfo, $u, $opts, $cleanitems) = @_; + + my $ret; + + # prolog line + $ret .= "{'saycharset'}' ?>\n"; + $ret .= LJ::run_hook("bot_director", ""); + + # AtomAPI interface + my $api = $opts->{'apilinks'} ? "$LJ::SITEROOT/interface/atom" : + "$LJ::SITEROOT/users/$u->{user}/data/atom"; + + # header + unless ($opts->{'noheader'}) { + $ret .= "\n"; + + # attributes + $ret .= "" . LJ::exml($journalinfo->{title}) . "\n"; + $ret .= "" . LJ::exml($journalinfo->{subtitle}) . "\n" + if $journalinfo->{subtitle}; + $ret .= "\n"; + + # last update + $ret .= "" . LJ::time_to_w3c($journalinfo->{'modtime'}, 'Z') + . ""; + + # link to the AtomAPI version of this feed + $ret .= "" : "' href='$api' />"; + + if ($opts->{'apilinks'}) { + $ret .= ""; + } + } + + # output individual item blocks + + foreach my $it (@$cleanitems) + { + my $itemid = $it->{itemid}; + my $ditemid = $it->{ditemid}; + + $ret .= " \n"; + # include empty tag if we don't have a subject. + $ret .= " " . LJ::exml($it->{subject}) . "\n"; + $ret .= " urn:lj:$LJ::DOMAIN:atom1:$journalinfo->{u}{user}:$ditemid\n"; + $ret .= " \n"; + if ($opts->{'apilinks'}) { + $ret .= ""; + } + $ret .= " " . LJ::time_to_w3c($it->{createtime}, 'Z') . "\n" + if $it->{createtime} != $it->{modtime}; + + my ($year, $mon, $mday, $hour, $min, $sec) = split(/ /, $it->{eventtime}); + $ret .= " " . sprintf("%04d-%02d-%02dT%02d:%02d:%02d", + $year, $mon, $mday, + $hour, $min, $sec) . "\n"; + $ret .= " " . LJ::time_to_w3c($it->{modtime}, 'Z') . "\n"; + $ret .= " \n"; + $ret .= " " . LJ::exml($journalinfo->{u}{name}) . "\n"; + $ret .= " " . LJ::exml($journalinfo->{email}) . "\n" if $journalinfo->{email}; + $ret .= " \n"; + $ret .= " \n" foreach map { LJ::exml($_) } @{$it->{tags} || []}; + # if syndicating the complete entry + # -print a content tag + # elsif syndicating summaries + # -print a summary tag + # else (code omitted), we're syndicating title only + # -print neither (the title has already been printed) + # note: the $event was also emptied earlier, in make_feed + if ($u->{'opt_synlevel'} eq 'full') { + $ret .= " " . LJ::exml($it->{event}) . "\n"; + } elsif ($u->{'opt_synlevel'} eq 'summary') { + $ret .= " " . LJ::exml($it->{event}) . "\n"; + } + + $ret .= " \n"; + } + + unless ($opts->{'noheader'}) { + $ret .= "\n"; + } + + return $ret; +} + +# create a FOAF page for a user +sub create_view_foaf { + my ($journalinfo, $u, $opts) = @_; + my $comm = ($u->{journaltype} eq 'C'); + + my $ret; + + # return nothing if we're not a user + unless ($u->{journaltype} eq 'P' || $comm) { + $opts->{handler_return} = 404; + return undef; + } + + # set our content type + $opts->{contenttype} = 'application/rdf+xml; charset=' . $opts->{saycharset}; + + # setup userprops we will need + LJ::load_user_props($u, qw{ + aolim icq yahoo jabber msn url urlname external_foaf_url + }); + + # create bare foaf document, for now + $ret = "\n"; + $ret .= LJ::run_hook("bot_director", ""); + $ret .= "\n"; + + # precompute some values + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{email}); + + # channel attributes + $ret .= ($comm ? " \n" : " \n"); + $ret .= " $u->{user}\n"; + if ($u->{bdate} && $u->{bdate} ne "0000-00-00" && !$comm && $u->{allow_infoshow} eq 'Y') { + my $bdate = $u->{bdate}; + $bdate =~ s/^0000-//; + $ret .= " $bdate\n"; + } + $ret .= " $digest\n"; + $ret .= " \n"; + $ret .= " {user}\">\n"; + $ret .= " $LJ::SITENAME Profile\n"; + $ret .= " Full $LJ::SITENAME profile, including information such as interests and bio.\n"; + $ret .= " \n"; + $ret .= " \n"; + + # we want to bail out if they have an external foaf file, because + # we want them to be able to provide their own information. + if ($u->{external_foaf_url}) { + $ret .= " {external_foaf_url}) . "\" />\n"; + $ret .= ($comm ? " \n" : " \n"); + $ret .= "\n"; + return $ret; + } + + # contact type information + my %types = ( + aolim => 'aimChatID', + icq => 'icqChatID', + yahoo => 'yahooChatID', + msn => 'msnChatID', + jabber => 'jabberID', + ); + if ($u->{allow_contactshow} eq 'Y') { + foreach my $type (keys %types) { + next unless $u->{$type}; + $ret .= " " . LJ::exml($u->{$type}) . "\n"; + } + } + + # include a user's journal page and web site info + $ret .= " \n"; + if ($u->{url}) { + $ret .= " {url}); + $ret .= "\" dc:title=\"" . LJ::exml($u->{urlname}) . "\" />\n"; + } + + # interests, please! + # arrayref of interests rows: [ intid, intname, intcount ] + my $intu = LJ::get_interests($u); + foreach my $int (@$intu) { + LJ::text_out(\$int->[1]); # 1==interest + $ret .= " [1]) . "\" " . + "rdf:resource=\"$LJ::SITEROOT/interests.bml?int=" . LJ::eurl($int->[1]) . "\" />\n"; + } + + # check if the user has a "FOAF-knows" group + my $groups = LJ::get_friend_group($u->{userid}, { name => 'FOAF-knows' }); + my $mask = $groups ? 1 << $groups->{groupnum} : 0; + + # now information on who you know, limited to a certain maximum number of users + my $friends = LJ::get_friends($u->{userid}, $mask); + my @ids = keys %$friends; + @ids = splice(@ids, 0, $LJ::MAX_FOAF_FRIENDS) if @ids > $LJ::MAX_FOAF_FRIENDS; + + # now load + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } @ids ], [$u]); + + # iterate to create data structure + foreach my $friendid (@ids) { + next if $friendid == $u->{userid}; + my $fu = $users{$friendid}; + next if $fu->{statusvis} =~ /[DXS]/ || $fu->{journaltype} ne 'P'; + $ret .= $comm ? " \n" : " \n"; + $ret .= " \n"; + $ret .= " $fu->{'user'}\n"; + $ret .= " \n"; + $ret .= " \n"; + $ret .= " \n"; + $ret .= $comm ? " \n" : " \n"; + } + + # finish off the document + $ret .= $comm ? " \n" : " \n"; + $ret .= "\n"; + + return $ret; +} + +1; diff --git a/livejournal/cgi-bin/ljlang.pl b/livejournal/cgi-bin/ljlang.pl new file mode 100755 index 0000000..60f5f1e --- /dev/null +++ b/livejournal/cgi-bin/ljlang.pl @@ -0,0 +1,416 @@ +#!/usr/bin/perl +# + +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use LJ::Cache; + +package LJ::Lang; + +my @day_short = (qw[Sun Mon Tue Wed Thu Fri Sat]); +my @day_long = (qw[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]); +my @month_short = (qw[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec]); +my @month_long = (qw[January February March April May June July August September October November December]); + +# get entire array of days and months +sub day_list_short { return @LJ::Lang::day_short; } +sub day_list_long { return @LJ::Lang::day_long; } +sub month_list_short { return @LJ::Lang::month_short; } +sub month_list_long { return @LJ::Lang::month_long; } + +# access individual day or month given integer +sub day_short { return $day_short[$_[0] - 1]; } +sub day_long { return $day_long[$_[0] - 1]; } +sub month_short { return $month_short[$_[0] - 1]; } +sub month_long { return $month_long[$_[0] - 1]; } + +# lang codes for individual day or month given integer +sub day_short_langcode { return "date.day." . lc(LJ::Lang::day_long(@_)) . ".short"; } +sub day_long_langcode { return "date.day." . lc(LJ::Lang::day_long(@_)) . ".long"; } +sub month_short_langcode { return "date.month." . lc(LJ::Lang::month_long(@_)) . ".short"; } +sub month_long_langcode { return "date.month." . lc(LJ::Lang::month_long(@_)) . ".long"; } + +## ordinal suffix +sub day_ord { + my $day = shift; + + # teens all end in 'th' + if ($day =~ /1\d$/) { return "th"; } + + # otherwise endings in 1, 2, 3 are special + if ($day % 10 == 1) { return "st"; } + if ($day % 10 == 2) { return "nd"; } + if ($day % 10 == 3) { return "rd"; } + + # everything else (0,4-9) end in "th" + return "th"; +} + +sub time_format +{ + my ($hours, $h, $m, $formatstring) = @_; + + if ($formatstring eq "short") { + if ($hours == 12) { + my $ret; + my $ap = "a"; + if ($h == 0) { $ret .= "12"; } + elsif ($h < 12) { $ret .= ($h+0); } + elsif ($h == 12) { $ret .= ($h+0); $ap = "p"; } + else { $ret .= ($h-12); $ap = "p"; } + $ret .= sprintf(":%02d$ap", $m); + return $ret; + } elsif ($hours == 24) { + return sprintf("%02d:%02d", $h, $m); + } + } + return ""; +} + +#### ml_ stuff: +my $LS_CACHED = 0; +my %DM_ID = (); # id -> { type, args, dmid, langs => { => 1, => 0, => 1 } } +my %DM_UNIQ = (); # "$type/$args" => ^^^ +my %LN_ID = (); # id -> { ..., ..., 'children' => [ $ids, .. ] } +my %LN_CODE = (); # $code -> ^^^^ +my $LAST_ERROR; +my $TXT_CACHE; # LJ::Cache for text + +sub get_cache_object { return $TXT_CACHE; } + +sub last_error +{ + return $LAST_ERROR; +} + +sub set_error +{ + $LAST_ERROR = $_[0]; + return 0; +} + +sub get_lang +{ + my $code = shift; + load_lang_struct() unless $LS_CACHED; + return $LN_CODE{$code}; +} + +sub get_lang_id +{ + my $id = shift; + load_lang_struct() unless $LS_CACHED; + return $LN_ID{$id}; +} + +sub get_dom +{ + my $dmcode = shift; + load_lang_struct() unless $LS_CACHED; + return $DM_UNIQ{$dmcode}; +} + +sub get_dom_id +{ + my $dmid = shift; + load_lang_struct() unless $LS_CACHED; + return $DM_ID{$dmid}; +} + +sub get_domains +{ + load_lang_struct() unless $LS_CACHED; + return values %DM_ID; +} + +sub get_root_lang +{ + my $dom = shift; # from, say, get_dom + return undef unless ref $dom eq "HASH"; + foreach (keys %{$dom->{'langs'}}) { + if ($dom->{'langs'}->{$_}) { + return get_lang_id($_); + } + } + return undef; +} + +sub load_lang_struct +{ + return 1 if $LS_CACHED; + my $dbr = LJ::get_db_reader(); + return set_error("No database available") unless $dbr; + my $sth; + + $TXT_CACHE = new LJ::Cache { 'maxbytes' => $LJ::LANG_CACHE_BYTES || 50_000 }; + + $sth = $dbr->prepare("SELECT dmid, type, args FROM ml_domains"); + $sth->execute; + while (my ($dmid, $type, $args) = $sth->fetchrow_array) { + my $uniq = $args ? "$type/$args" : $type; + $DM_UNIQ{$uniq} = $DM_ID{$dmid} = { + 'type' => $type, 'args' => $args, 'dmid' => $dmid, + 'uniq' => $uniq, + }; + } + + $sth = $dbr->prepare("SELECT lnid, lncode, lnname, parenttype, parentlnid FROM ml_langs"); + $sth->execute; + while (my ($id, $code, $name, $ptype, $pid) = $sth->fetchrow_array) { + $LN_ID{$id} = $LN_CODE{$code} = { + 'lnid' => $id, + 'lncode' => $code, + 'lnname' => $name, + 'parenttype' => $ptype, + 'parentlnid' => $pid, + }; + } + foreach (values %LN_CODE) { + next unless $_->{'parentlnid'}; + push @{$LN_ID{$_->{'parentlnid'}}->{'children'}}, $_->{'lnid'}; + } + + $sth = $dbr->prepare("SELECT lnid, dmid, dmmaster FROM ml_langdomains"); + $sth->execute; + while (my ($lnid, $dmid, $dmmaster) = $sth->fetchrow_array) { + $DM_ID{$dmid}->{'langs'}->{$lnid} = $dmmaster; + } + + $LS_CACHED = 1; +} + +sub get_itemid +{ + &LJ::nodb; + my ($dmid, $itcode, $opts) = @_; + load_lang_struct() unless $LS_CACHED; + + my $dbr = LJ::get_db_reader(); + $dmid += 0; + my $itid = $dbr->selectrow_array("SELECT itid FROM ml_items WHERE dmid=$dmid AND itcode=?", undef, $itcode); + return $itid if defined $itid; + + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + + # allocate a new id + LJ::get_lock($dbh, 'global', 'mlitem_dmid') || return 0; + $itid = $dbh->selectrow_array("SELECT MAX(itid)+1 FROM ml_items WHERE dmid=?", undef, $dmid); + $itid ||= 1; # if the table is empty, NULL+1 == NULL + $dbh->do("INSERT INTO ml_items (dmid, itid, itcode, notes) ". + "VALUES (?, ?, ?, ?)", undef, $dmid, $itid, $itcode, $opts->{'notes'}); + LJ::release_lock($dbh, 'global', 'mlitem_dmid'); + + if ($dbh->err) { + return $dbh->selectrow_array("SELECT itid FROM ml_items WHERE dmid=$dmid AND itcode=?", + undef, $itcode); + } + return $itid; +} + +sub set_text +{ + &LJ::nodb; + my ($dmid, $lncode, $itcode, $text, $opts) = @_; + load_lang_struct() unless $LS_CACHED; + + my $l = $LN_CODE{$lncode} or return set_error("Language not defined."); + my $lnid = $l->{'lnid'}; + $dmid += 0; + + # is this domain/language request even possible? + return set_error("Bogus domain") + unless exists $DM_ID{$dmid}; + return set_error("Bogus lang for that domain") + unless exists $DM_ID{$dmid}->{'langs'}->{$lnid}; + + my $itid = get_itemid($dmid, $itcode, { 'notes' => $opts->{'notes'}}); + return set_error("Couldn't allocate itid.") unless $itid; + + my $dbh = LJ::get_db_writer(); + my $txtid = 0; + if (defined $text) { + my $userid = $opts->{'userid'} + 0; + # Strip bad characters + $text =~ s/\r//; + my $qtext = $dbh->quote($text); + LJ::get_lock( $dbh, 'global', 'ml_text_txtid' ) || return 0; + $txtid = $dbh->selectrow_array("SELECT MAX(txtid)+1 FROM ml_text WHERE dmid=?", undef, $dmid); + $txtid ||= 1; + $dbh->do("INSERT INTO ml_text (dmid, txtid, lnid, itid, text, userid) ". + "VALUES ($dmid, $txtid, $lnid, $itid, $qtext, $userid)"); + LJ::release_lock( $dbh, 'global', 'ml_text_txtid' ); + return set_error("Error inserting ml_text: ".$dbh->errstr) if $dbh->err; + } + if ($opts->{'txtid'}) { + $txtid = $opts->{'txtid'}+0; + } + + my $staleness = $opts->{'staleness'}+0; + $dbh->do("REPLACE INTO ml_latest (lnid, dmid, itid, txtid, chgtime, staleness) ". + "VALUES ($lnid, $dmid, $itid, $txtid, NOW(), $staleness)"); + return set_error("Error inserting ml_latest: ".$dbh->errstr) if $dbh->err; + LJ::MemCache::set("ml.${lncode}.${dmid}.${itcode}", $text) if defined $text; + + { + my $vals; + my $langids; + my $rec = sub { + my $l = shift; + my $rec = shift; + foreach my $cid (@{$l->{'children'}}) { + my $clid = $LN_ID{$cid}; + if ($opts->{'childrenlatest'}) { + my $stale = $clid->{'parenttype'} eq "diff" ? 3 : 0; + $vals .= "," if $vals; + $vals .= "($cid, $dmid, $itid, $txtid, NOW(), $stale)"; + } + $langids .= "," if $langids; + $langids .= $cid+0; + LJ::MemCache::delete("ml.$clid->{'lncode'}.${dmid}.${itcode}"); + $rec->($clid, $rec); + } + }; + $rec->($l, $rec); + + # set descendants to use this mapping + $dbh->do("INSERT IGNORE INTO ml_latest (lnid, dmid, itid, txtid, chgtime, staleness) ". + "VALUES $vals") if $vals; + + # update languages that have no translation yet + $dbh->do("UPDATE ml_latest SET txtid=$txtid WHERE dmid=$dmid ". + "AND lnid IN ($langids) AND itid=$itid AND staleness >= 3") if $langids; + } + + if ($opts->{'changeseverity'} && $l->{'children'} && @{$l->{'children'}}) { + my $in = join(",", @{$l->{'children'}}); + my $newstale = $opts->{'changeseverity'} == 2 ? 2 : 1; + $dbh->do("UPDATE ml_latest SET staleness=$newstale WHERE lnid IN ($in) AND ". + "dmid=$dmid AND itid=$itid AND txtid<>$txtid AND staleness < $newstale"); + } + + return 1; +} + +sub get_text +{ + my ($lang, $code, $dmid, $vars) = @_; + $dmid = int($dmid || 1); + $lang ||= $LJ::DEFAULT_LANG; + load_lang_struct() unless $LS_CACHED; + my $cache_key = "ml.${lang}.${dmid}.${code}"; + + my $text = $TXT_CACHE->get($cache_key); + + unless (defined $text) { + my $mem_good = 1; + $text = LJ::MemCache::get($cache_key); + unless (defined $text) { + $mem_good = 0; + my $l = $LN_CODE{$lang} or return "?lang?"; + my $dbr = LJ::get_db_reader(); + $text = $dbr->selectrow_array("SELECT t.text". + " FROM ml_text t, ml_latest l, ml_items i". + " WHERE t.dmid=$dmid AND t.txtid=l.txtid". + " AND l.dmid=$dmid AND l.lnid=$l->{lnid} AND l.itid=i.itid". + " AND i.dmid=$dmid AND i.itcode=?", undef, + $code); + } + if (defined $text) { + $TXT_CACHE->set($cache_key, $text); + LJ::MemCache::set($cache_key, $text) unless $mem_good; + } + } + + if ($vars) { + $text =~ s/\[\[\?([\w\-]+)\|(.+?)\]\]/resolve_plural($lang, $vars, $1, $2)/eg; + $text =~ s/\[\[([^\[]+?)\]\]/$vars->{$1}/g; + } + + return $text; +} + +# The translation system now supports the ability to add multiple plural forms of the word +# given different rules in a languge. This functionality is much like the plural support +# in the S2 styles code. To use this code you must use the BML::ml function and pass +# the number of items as one of the variables. To make sure that you are allowing the +# utmost compatibility for each language you should not hardcode the placement of the +# number of items in relation to the noun. Let the translation string do this for you. +# A translation string is in the format of, with num being the variable storing the +# number of items. +# =[[num]] [[?num|singular|plural1|plural2|pluralx]] + +sub resolve_plural { + my ($lang, $vars, $varname, $wordlist) = @_; + my $count = $vars->{$varname}; + my @wlist = split(/\|/, $wordlist); + my $plural_form = plural_form($lang, $count); + return $wlist[$plural_form]; +} + +# TODO: make this faster, using AUTOLOAD and symbol tables pointing to dynamically +# generated subs which only use $_[0] for $count. +sub plural_form { + my ($lang, $count) = @_; + return plural_form_en($count) if $lang =~ /^en/; + return plural_form_ru($count) if $lang =~ /^ru/ || $lang =~ /^uk/; + return plural_form_fr($count) if $lang =~ /^fr/ || $lang =~ /^pt_BR/; + return plural_form_lt($count) if $lang =~ /^lt/; + return plural_form_pl($count) if $lang =~ /^pl/; + return plural_form_singular() if $lang =~ /^hu/ || $lang =~ /^ja/ || $lang =~ /^tr/; + return plural_form_lv($count) if $lang =~ /^lv/; + return plural_form_en($count); # default +} + +# English, Danish, German, Norwegian, Swedish, Estonian, Finnish, Greek, Hebrew, Italian, Portugese, Spanish, Esperanto +sub plural_form_en { + my ($count) = shift; + return 0 if $count == 1; + return 1; +} + +# French, Brazilian Portuguese +sub plural_form_fr { + my ($count) = shift; + return 1 if $count > 1; + return 0; +} + +# Croatian, Czech, Russian, Slovak, Ukrainian +sub plural_form_ru { + my ($count) = shift; + return 0 if ($count%10 == 1 and $count%100 != 11); + return 1 if ($count%10 >= 2 and $count%10 <= 4 and ($count%100 < 10 or $count%100>=20)); + return 2; +} + +# Polish +sub plural_form_pl { + my ($count) = shift; + return 0 if($count == 1); + return 1 if($count%10 >= 2 && $count%10 <= 4 && ($count%100 < 10 || $count%100 >= 20)); + return 2; +} + +# Lithuanian +sub plural_form_lt { + my ($count) = shift; + return 0 if($count%10 == 1 && $count%100 != 11); + return 1 if ($count%10 >= 2 && ($count%100 < 10 || $count%100 >= 20)); + return 2; +} + +# Hungarian, Japanese, Korean (not supported), Turkish +sub plural_form_singular { + return 0; +} + +# Latvian +sub plural_form_lv { + my ($count) = shift; + return 0 if($count%10 == 1 && $count%100 != 11); + return 1 if($count != 0); + return 2; +} + +1; diff --git a/livejournal/cgi-bin/ljlib.pl b/livejournal/cgi-bin/ljlib.pl new file mode 100755 index 0000000..f9711e8 --- /dev/null +++ b/livejournal/cgi-bin/ljlib.pl @@ -0,0 +1,9400 @@ +#!/usr/bin/perl +# +# +# lib: DBI::, Digest::MD5, URI::URL +# lib: cgi-bin/ljconfig.pl, cgi-bin/ljlang.pl, cgi-bin/ljpoll.pl +# lib: cgi-bin/cleanhtml.pl +# link: htdocs/paidaccounts/index.bml, htdocs/users, htdocs/view/index.bml +# hook: canonicalize_url, name_caps, name_caps_short, post_create +# hook: validate_get_remote +# + +package LJ; + +use strict; +use Carp; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use DBI; +use DBI::Role; +use DBIx::StateKeeper; +use Digest::MD5 (); +use Digest::SHA1 (); +use HTTP::Date (); +use LJ::MemCache; +use LJ::User; +use Time::Local (); +use Storable (); +use Compress::Zlib (); +use IO::Socket::INET qw{}; +use Unicode::MapUTF8; + +do "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; +do "$ENV{'LJHOME'}/cgi-bin/ljdefaults.pl"; + +sub END { LJ::end_request(); } + +# tables on user databases (ljlib-local should define @LJ::USE_TABLES_LOCAL) +# this is here and no longer in bin/upgrading/update-db-{general|local}.pl +# so other tools (in particular, the inter-cluster user mover) can verify +# that it knows how to move all types of data before it will proceed. +@LJ::USER_TABLES = ("userbio", "cmdbuffer", "dudata", + "log2", "logtext2", "logprop2", "logsec2", + "talk2", "talkprop2", "talktext2", "talkleft", + "userpicblob2", "events", + "ratelog", "loginstall", "sessions", "sessions_data", + "s1usercache", "modlog", "modblob", + "userproplite2", "links", "s1overrides", "s1style", + "s1stylecache", "userblob", "userpropblob", + "clustertrack2", "captcha_session", "reluser2", + "tempanonips", "inviterecv", "invitesent", + "memorable2", "memkeyword2", "userkeywords", + "friendgroup2", "userpicmap2", "userpic2", + "s2stylelayers2", "s2compiled2", "userlog", + "logtags", "logtagsrecent", "logkwsum", + "recentactions", "usertags", "pendcomments", + ); + +# keep track of what db locks we have out +%LJ::LOCK_OUT = (); # {global|user} => caller_with_lock + +require "$ENV{'LJHOME'}/cgi-bin/ljlib-local.pl" + if -e "$ENV{'LJHOME'}/cgi-bin/ljlib-local.pl"; +require "$ENV{LJHOME}/cgi-bin/taglib.pl"; + +# if this is a dev server, alias LJ::D to Data::Dumper::Dumper +if ($LJ::IS_DEV_SERVER) { + eval "use Data::Dumper ();"; + *LJ::D = \&Data::Dumper::Dumper; +} + +$LJ::DBIRole = new DBI::Role { + 'timeout' => $LJ::DB_TIMEOUT, + 'sources' => \%LJ::DBINFO, + 'default_db' => "livejournal", + 'time_check' => 60, + 'time_report' => \&dbtime_callback, +}; + +LJ::MemCache::init(); + +# $LJ::PROTOCOL_VER is the version of the client-server protocol +# used uniformly by server code which uses the protocol. +$LJ::PROTOCOL_VER = ($LJ::UNICODE ? "1" : "0"); + +# user.dversion values: +# 0: unclustered (unsupported) +# 1: clustered, not pics (unsupported) +# 2: clustered +# 3: weekuserusage populated (Note: this table's now gone) +# 4: userproplite2 clustered, and cldversion on userproplist table +# 5: overrides clustered, and style clustered +# 6: clustered memories, friend groups, and keywords (for memories) +# 7: clustered userpics, keyword limiting, and comment support +$LJ::MAX_DVERSION = 7; + +# constants +use constant ENDOFTIME => 2147483647; +$LJ::EndOfTime = 2147483647; # for string interpolation + +# width constants. BMAX_ constants are restrictions on byte width, +# CMAX_ on character width (character means byte unless $LJ::UNICODE, +# in which case it means a UTF-8 character). + +use constant BMAX_SUBJECT => 255; # *_SUBJECT for journal events, not comments +use constant CMAX_SUBJECT => 100; +use constant BMAX_COMMENT => 9000; +use constant CMAX_COMMENT => 4300; +use constant BMAX_MEMORY => 150; +use constant CMAX_MEMORY => 80; +use constant BMAX_NAME => 100; +use constant CMAX_NAME => 50; +use constant BMAX_KEYWORD => 80; +use constant CMAX_KEYWORD => 40; +use constant BMAX_PROP => 255; # logprop[2]/talkprop[2]/userproplite (not userprop) +use constant CMAX_PROP => 100; +use constant BMAX_GRPNAME => 60; +use constant CMAX_GRPNAME => 30; +use constant BMAX_GRPNAME2 => 90; # introduced in dversion6, when we widened the groupname column +use constant CMAX_GRPNAME2 => 40; # but we have to keep the old GRPNAME around while dversion5 exists +use constant BMAX_EVENT => 65535; +use constant CMAX_EVENT => 65535; +use constant BMAX_INTEREST => 100; +use constant CMAX_INTEREST => 50; +use constant BMAX_UPIC_COMMENT => 255; +use constant CMAX_UPIC_COMMENT => 120; + +# declare views (calls into ljviews.pl) +@LJ::views = qw(lastn friends calendar day); +%LJ::viewinfo = ( + "lastn" => { + "creator" => \&LJ::S1::create_view_lastn, + "des" => "Most Recent Events", + }, + "calendar" => { + "creator" => \&LJ::S1::create_view_calendar, + "des" => "Calendar", + }, + "day" => { + "creator" => \&LJ::S1::create_view_day, + "des" => "Day View", + }, + "friends" => { + "creator" => \&LJ::S1::create_view_friends, + "des" => "Friends View", + "owner_props" => ["opt_usesharedpic", "friendspagetitle"], + }, + "friendsfriends" => { + "creator" => \&LJ::S1::create_view_friends, + "des" => "Friends of Friends View", + "styleof" => "friends", + }, + "data" => { + "creator" => \&LJ::Feed::create_view, + "des" => "Data View (RSS, etc.)", + "owner_props" => ["opt_whatemailshow", "no_mail_alias"], + }, + "rss" => { # this is now provided by the "data" view. + "des" => "RSS View (XML)", + }, + "res" => { + "des" => "S2-specific resources (stylesheet)", + }, + "pics" => { + "des" => "FotoBilder pics (root gallery)", + }, + "info" => { + # just a redirect to userinfo.bml for now. + # in S2, will be a real view. + "des" => "Profile Page", + }, + "tag" => { + "creator" => \&LJ::S1::create_view_lastn, + "des" => "Filtered Most Recent Events", + }, + + ); + +## we want to set this right away, so when we get a HUP signal later +## and our signal handler sets it to true, perl doesn't need to malloc, +## since malloc may not be thread-safe and we could core dump. +## see LJ::clear_caches and LJ::handle_caches +$LJ::CLEAR_CACHES = 0; + +# DB Reporting UDP socket object +$LJ::ReportSock = undef; + +# DB Reporting handle collection. ( host => $dbh ) +%LJ::DB_REPORT_HANDLES = (); + + +## if this library is used in a BML page, we don't want to destroy BML's +## HUP signal handler. +if ($SIG{'HUP'}) { + my $oldsig = $SIG{'HUP'}; + $SIG{'HUP'} = sub { + &{$oldsig}; + LJ::clear_caches(); + }; +} else { + $SIG{'HUP'} = \&LJ::clear_caches; +} + +# given two db roles, returns true only if the two roles are for sure +# served by different database servers. this is useful for, say, +# the moveusercluster script: you wouldn't want to select something +# from one db, copy it into another, and then delete it from the +# source if they were both the same machine. +# +# name: LJ::use_diff_db +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub use_diff_db { + $LJ::DBIRole->use_diff_db(@_); +} + +sub get_blob_domainid +{ + my $name = shift; + my $id = { + "userpic" => 1, + "phonepost" => 2, + "captcha_audio" => 3, + "captcha_image" => 4, + "fotobilder" => 5, + }->{$name}; + # FIXME: add hook support, so sites can't define their own + # general code gets priority on numbers, say, 1-200, so verify + # hook returns a number 201-255 + return $id if $id; + die "Unknown blob domain: $name"; +} + +sub locker { + return $LJ::LOCKER_OBJ if $LJ::LOCKER_OBJ; + eval "use DDLockClient ();"; + die "Couldn't load locker client: $@" if $@; + + return $LJ::LOCKER_OBJ = + new DDLockClient ( + servers => [ @LJ::LOCK_SERVERS ], + lockdir => $LJ::LOCKDIR || "$LJ::HOME/locks", + ); +} + +sub mogclient { + return $LJ::MogileFS if $LJ::MogileFS; + + if (%LJ::MOGILEFS_CONFIG && $LJ::MOGILEFS_CONFIG{hosts}) { + eval "use MogileFS;"; + die "Couldn't load MogileFS: $@" if $@; + + $LJ::MogileFS = new MogileFS ( + domain => $LJ::MOGILEFS_CONFIG{domain}, + root => $LJ::MOGILEFS_CONFIG{root}, + hosts => $LJ::MOGILEFS_CONFIG{hosts}, + ) + or die "Could not initialize MogileFS"; + + # set preferred ip list if we have one + $LJ::MogileFS->set_pref_ip(\%LJ::MOGILEFS_PREF_IP) + if %LJ::MOGILEFS_PREF_IP; + } + + return $LJ::MogileFS; +} + +# +# name: LJ::get_dbh +# class: db +# des: Given one or more roles, returns a database handle. +# info: +# args: +# des-: +# returns: +# +sub get_dbh { + my $opts = ref $_[0] eq "HASH" ? shift : {}; + # supported options: + # 'raw': don't return a DBIx::StateKeeper object + + unless (exists $opts->{'max_repl_lag'}) { + # for slave or clusterslave roles, don't allow lag + if ($_[0] =~ /slave$/) { + $opts->{'max_repl_lag'} = $LJ::MAX_REPL_LAG || 100_000; + } + } + + if ($LJ::DEBUG{'get_dbh'} && $_[0] ne "logs") { + my $errmsg = "get_dbh(@_) at \n"; + my $i = 0; + while (my ($p, $f, $l) = caller($i++)) { + next if $i > 3; + $errmsg .= " $p, $f, $l\n"; + } + warn $errmsg; + } + + my $mapping; + ROLE: + foreach my $role (@_) { + # let site admin turn off global master write access during + # maintenance + return undef if $LJ::DISABLE_MASTER && $role eq "master"; + + if (($mapping = $LJ::WRAPPED_DB_ROLE{$role}) && ! $opts->{raw}) { + if (my $keeper = $LJ::REQ_DBIX_KEEPER{$role}) { + return $keeper->set_database() ? $keeper : undef; + } + my ($canl_role, $dbname) = @$mapping; + my $tracker; + # DBIx::StateTracker::new will die if it can't connect to the database, + # so it's wrapper in an eval + eval { + $tracker = + $LJ::REQ_DBIX_TRACKER{$canl_role} ||= + DBIx::StateTracker->new(sub { LJ::get_dbirole_dbh({unshared=>1}, + $canl_role) }); + }; + if ($tracker) { + my $keeper = DBIx::StateKeeper->new($tracker, $dbname); + $LJ::REQ_DBIX_KEEPER{$role} = $keeper; + return $keeper->set_database() ? $keeper : undef; + } + next ROLE; + } + my $db = LJ::get_dbirole_dbh($opts, $role); + return $db if $db; + } + return undef; +} + + +# +# name: LJ::get_dbirole_dbh +# class: db +# des: Internal function for get_dbh(). Uses the DBIRole to fetch a dbh, with +# hooks into db stats-generation if that's turned on. +# info: +# args: opts, role +# des-opts: A hashref of options. +# des-role: The database role. +# returns: A dbh. +# +sub get_dbirole_dbh { + my $dbh = $LJ::DBIRole->get_dbh( @_ ) or return undef; + + if ( $LJ::DB_LOG_HOST && $LJ::HAVE_DBI_PROFILE ) { + $LJ::DB_REPORT_HANDLES{ $dbh->{Name} } = $dbh; + + # :TODO: Explain magic number + $dbh->{Profile} ||= "2/DBI::Profile"; + + # And turn off useless (to us) on_destroy() reports, too. + undef $DBI::Profile::ON_DESTROY_DUMP; + } + + return $dbh; +} + +# +# name: LJ::get_lock +# des: get a mysql lock on a given key/dbrole combination +# returns: undef if called improperly, true on success, die() on failure +# args: db, dbrole, lockname, wait_time? +# des-dbrole: the role this lock should be gotten on, either 'global' or 'user' +# des-lockname: the name to be used for this lock +# des-wait_time: an optional timeout argument, defaults to 10 seconds +# +sub get_lock +{ + my ($db, $dbrole, $lockname, $wait_time) = @_; + return undef unless $db && $lockname; + return undef unless $dbrole eq 'global' || $dbrole eq 'user'; + + my $curr_sub = (caller 1)[3]; # caller of current sub + + # die if somebody already has a lock + die "LOCK ERROR: $curr_sub; can't get lock from: $LJ::LOCK_OUT{$dbrole}\n" + if exists $LJ::LOCK_OUT{$dbrole}; + + # get a lock from mysql + $wait_time ||= 10; + $db->do("SELECT GET_LOCK(?,?)", undef, $lockname, $wait_time) + or return undef; + + # successfully got a lock + $LJ::LOCK_OUT{$dbrole} = $curr_sub; + return 1; +} + +# +# name: LJ::may_lock +# des: see if we COULD get a mysql lock on a given key/dbrole combination, +# but don't actually get it. +# returns: undef if called improperly, true on success, die() on failure +# args: db, dbrole +# des-dbrole: the role this lock should be gotten on, either 'global' or 'user' +# +sub may_lock +{ + my ($db, $dbrole) = @_; + return undef unless $db && ($dbrole eq 'global' || $dbrole eq 'user'); + + # die if somebody already has a lock + if ($LJ::LOCK_OUT{$dbrole}) { + my $curr_sub = (caller 1)[3]; # caller of current sub + die "LOCK ERROR: $curr_sub; can't get lock from $LJ::LOCK_OUT{$dbrole}\n"; + } + + # see if a lock is already out + return undef if exists $LJ::LOCK_OUT{$dbrole}; + + return 1; +} + +# +# name: LJ::release_lock +# des: release a mysql lock on a given key/dbrole combination +# returns: undef if called improperly, true on success, die() on failure +# args: db, dbrole, lockname +# des-dbrole: the role this lock should be gotten on, either 'global' or 'user' +# des-lockname: the name to be used for this lock +# +sub release_lock +{ + my ($db, $dbrole, $lockname) = @_; + return undef unless $db && $lockname; + return undef unless $dbrole eq 'global' || $dbrole eq 'user'; + + # get a lock from mysql + $db->do("SELECT RELEASE_LOCK(?)", undef, $lockname); + delete $LJ::LOCK_OUT{$dbrole}; + + return 1; +} + +# +# name: LJ::get_newids +# des: Lookup an old global ID and see what journal it belongs to and its new ID. +# info: Interface to [dbtable[oldids]] table (URL compatability) +# returns: Undef if non-existent or unconverted, or arrayref of [$userid, $newid]. +# args: area, oldid +# des-area: The "area" of the id. Legal values are "L" (log), to lookup an old itemid, +# or "T" (talk) to lookup an old talkid. +# des-oldid: The old globally-unique id of the item. +# +sub get_newids +{ + my $sth; + my $db = LJ::get_dbh("oldids") || LJ::get_db_reader(); + return $db->selectrow_arrayref("SELECT userid, newid FROM oldids ". + "WHERE area=? AND oldid=?", undef, + $_[0], $_[1]); +} + +sub get_groupmask +{ + # TAG:FR:ljlib:get_groupmask + my ($journal, $remote) = @_; + return 0 unless $journal && $remote; + + my $jid = LJ::want_userid($journal); + my $fid = LJ::want_userid($remote); + return 0 unless $jid && $fid; + + my $memkey = [$jid,"frgmask:$jid:$fid"]; + my $mask = LJ::MemCache::get($memkey); + unless (defined $mask) { + my $dbr = LJ::get_db_reader(); + die "No database reader available" unless $dbr; + + $mask = $dbr->selectrow_array("SELECT groupmask FROM friends ". + "WHERE userid=? AND friendid=?", + undef, $jid, $fid); + LJ::MemCache::set($memkey, $mask+0, time()+60*15); + } + + return $mask+0; # force it to a numeric scalar +} + +# +# returns a row from log2, trying memcache +# accepts $u + $jitemid +# returns hash with: posterid, eventtime, logtime, +# security, allowmask, journalid, jitemid, anum. + +sub get_log2_row +{ + my ($u, $jitemid) = @_; + my $jid = $u->{'userid'}; + + my $memkey = [$jid, "log2:$jid:$jitemid"]; + my ($row, $item); + + $row = LJ::MemCache::get($memkey); + + if ($row) { + @$item{'posterid', 'eventtime', 'logtime', 'allowmask', 'ditemid'} = unpack("NNNNN", $row); + $item->{'security'} = ($item->{'allowmask'} == 0 ? 'private' : + ($item->{'allowmask'} == 2**31 ? 'public' : 'usemask')); + $item->{'journalid'} = $jid; + @$item{'jitemid', 'anum'} = ($item->{'ditemid'} >> 8, $item->{'ditemid'} % 256); + $item->{'eventtime'} = LJ::mysql_time($item->{'eventtime'}, 1); + $item->{'logtime'} = LJ::mysql_time($item->{'logtime'}, 1); + + return $item; + } + + my $db = LJ::get_cluster_def_reader($u); + return undef unless $db; + + my $sql = "SELECT posterid, eventtime, logtime, security, allowmask, " . + "anum FROM log2 WHERE journalid=? AND jitemid=?"; + + $item = $db->selectrow_hashref($sql, undef, $jid, $jitemid); + return undef unless $item; + $item->{'journalid'} = $jid; + $item->{'jitemid'} = $jitemid; + $item->{'ditemid'} = $jitemid*256 + $item->{'anum'}; + + my ($sec, $eventtime, $logtime); + $sec = $item->{'allowmask'}; + $sec = 0 if $item->{'security'} eq 'private'; + $sec = 2**31 if $item->{'security'} eq 'public'; + $eventtime = LJ::mysqldate_to_time($item->{'eventtime'}, 1); + $logtime = LJ::mysqldate_to_time($item->{'logtime'}, 1); + + $row = pack("NNNNN", $item->{'posterid'}, $eventtime, $logtime, $sec, + $item->{'ditemid'}); + LJ::MemCache::set($memkey, $row); + + return $item; +} + +# get 2 weeks worth of recent items, in rlogtime order, +# using memcache +# accepts $u or ($jid, $clusterid) + $notafter - max value for rlogtime +# $update is the timeupdate for this user, as far as the caller knows, +# in UNIX time. +# returns hash keyed by $jitemid, fields: +# posterid, eventtime, rlogtime, +# security, allowmask, journalid, jitemid, anum. + +sub get_log2_recent_log +{ + my ($u, $cid, $update, $notafter) = @_; + my $jid = LJ::want_userid($u); + $cid ||= $u->{'clusterid'} if ref $u; + + my $DATAVER = "3"; # 1 char + + my $memkey = [$jid, "log2lt:$jid"]; + my $lockkey = $memkey->[1]; + my ($rows, $ret); + + $rows = LJ::MemCache::get($memkey); + $ret = []; + + my $rows_decode = sub { + return 0 + unless $rows && substr($rows, 0, 1) eq $DATAVER; + my $tu = unpack("N", substr($rows, 1, 4)); + + # if update time we got from upstream is newer than recorded + # here, this data is unreliable + return 0 if $update > $tu; + + my $n = (length($rows) - 5 )/20; + for (my $i=0; $i<$n; $i++) { + my ($posterid, $eventtime, $rlogtime, $allowmask, $ditemid) = + unpack("NNNNN", substr($rows, $i*20+5, 20)); + next if $notafter and $rlogtime > $notafter; + $eventtime = LJ::mysql_time($eventtime, 1); + my $security = $allowmask == 0 ? 'private' : + ($allowmask == 2**31 ? 'public' : 'usemask'); + my ($jitemid, $anum) = ($ditemid >> 8, $ditemid % 256); + my $item = {}; + @$item{'posterid','eventtime','rlogtime','allowmask','ditemid', + 'security','journalid', 'jitemid', 'anum'} = + ($posterid, $eventtime, $rlogtime, $allowmask, + $ditemid, $security, $jid, $jitemid, $anum); + $item->{'ownerid'} = $jid; + $item->{'itemid'} = $jitemid; + push @$ret, $item; + } + return 1; + }; + + return $ret + if $rows_decode->(); + $rows = ""; + + my $db = LJ::get_cluster_def_reader($cid); + # if we use slave or didn't get some data, don't store in memcache + my $dont_store = 0; + unless ($db) { + $db = LJ::get_cluster_reader($cid); + $dont_store = 1; + return undef unless $db; + } + + my $lock = $db->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + return undef unless $lock; + + $rows = LJ::MemCache::get($memkey); + if ($rows_decode->()) { + $db->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + return $ret; + } + $rows = ""; + + # get reliable update time from the db + # TODO: check userprop first + my $tu; + my $dbh = LJ::get_db_writer(); + if ($dbh) { + $tu = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP(timeupdate) " . + "FROM userusage WHERE userid=?", + undef, $jid); + # if no mistake, treat absence of row as tu==0 (new user) + $tu = 0 unless $tu || $dbh->err; + + LJ::MemCache::set([$jid, "tu:$jid"], pack("N", $tu), 30*60) + if defined $tu; + # TODO: update userprop if necessary + } + + # if we didn't get tu, don't bother to memcache + $dont_store = 1 unless defined $tu; + + # get reliable log2lt data from the db + + my $max_age = $LJ::MAX_FRIENDS_VIEW_AGE || 3600*24*14; # 2 weeks default + + my $sql = "SELECT jitemid, posterid, eventtime, rlogtime, " . + "security, allowmask, anum, replycount FROM log2 " . + "USE INDEX (rlogtime) WHERE journalid=? AND " . + "rlogtime <= ($LJ::EndOfTime - UNIX_TIMESTAMP()) + $max_age"; + + my $sth = $db->prepare($sql); + $sth->execute($jid); + my @row; + push @row, $_ while $_ = $sth->fetchrow_hashref; + @row = sort { $a->{'rlogtime'} <=> $b->{'rlogtime'} } @row; + my $itemnum = 0; + + foreach my $item (@row) { + $item->{'ownerid'} = $item->{'journalid'} = $jid; + $item->{'itemid'} = $item->{'jitemid'}; + push @$ret, $item; + + my ($sec, $ditemid, $eventtime, $logtime); + $sec = $item->{'allowmask'}; + $sec = 0 if $item->{'security'} eq 'private'; + $sec = 2**31 if $item->{'security'} eq 'public'; + $ditemid = $item->{'jitemid'}*256 + $item->{'anum'}; + $eventtime = LJ::mysqldate_to_time($item->{'eventtime'}, 1); + + $rows .= pack("NNNNN", + $item->{'posterid'}, + $eventtime, + $item->{'rlogtime'}, + $sec, + $ditemid); + + if ($itemnum++ < 50) { + LJ::MemCache::add([$jid, "rp:$jid:$item->{'jitemid'}"], $item->{'replycount'}); + } + } + + $rows = $DATAVER . pack("N", $tu) . $rows; + LJ::MemCache::set($memkey, $rows) unless $dont_store; + + $db->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + return $ret; +} + +sub get_log2_recent_user +{ + my $opts = shift; + my $ret = []; + + my $log = LJ::get_log2_recent_log($opts->{'userid'}, $opts->{'clusterid'}, + $opts->{'update'}, $opts->{'notafter'}); + + my $left = $opts->{'itemshow'}; + my $notafter = $opts->{'notafter'}; + my $remote = $opts->{'remote'}; + + foreach my $item (@$log) { + last unless $left; + last if $notafter and $item->{'rlogtime'} > $notafter; + next unless $remote || $item->{'security'} eq 'public'; + next if $item->{'security'} eq 'private' + and $item->{'journalid'} != $remote->{'userid'}; + if ($item->{'security'} eq 'usemask') { + next unless $remote->{'journaltype'} eq "P"; + my $permit = ($item->{'journalid'} == $remote->{'userid'}); + unless ($permit) { + my $mask = LJ::get_groupmask($item->{'journalid'}, $remote->{'userid'}); + $permit = $item->{'allowmask'}+0 & $mask+0; + } + next unless $permit; + } + + # date conversion + if ($opts->{'dateformat'} eq "S2") { + $item->{'alldatepart'} = LJ::alldatepart_s2($item->{'eventtime'}); + } else { + $item->{'alldatepart'} = LJ::alldatepart_s1($item->{'eventtime'}); + } + push @$ret, $item; + } + + return @$ret; +} + +# +# name: LJ::get_friend_group +# des: Returns friendgroup row(s) for a given user. +# args: uuserid, opt? +# des-uuserid: a userid or u object +# des-opt: a hashref with keys: 'bit' => bit number of group to return +# 'name' => name of group to return +# returns: hashref; if bit/name are specified, returns hashref with keys being +# friendgroup rows, or undef if the group wasn't found. +# +# otherwise, returns hashref of all group rows with keys being +# group bit numbers and values being row col => val hashrefs +# +sub get_friend_group { + my ($uuid, $opt) = @_; + my $u = LJ::want_user($uuid); + return undef unless $u; + my $uid = $u->{userid}; + + # data version number + my $ver = 1; + + # sanity check bitnum + delete $opt->{'bit'} if + $opt->{'bit'} > 31 || $opt->{'bit'} < 0; + + my $fg; + my $find_grp = sub { + + # $fg format: + # [ version, [userid, bitnum, name, sortorder, public], [...], ... ] + + my $memver = shift @$fg; + return undef unless $memver == $ver; + + # bit number was specified + if ($opt->{'bit'}) { + foreach (@$fg) { + return LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) + if $_->[1] == $opt->{'bit'}; + } + return undef; + } + + # group name was specified + if ($opt->{'name'}) { + foreach (@$fg) { + return LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) + if lc($_->[2]) eq lc($opt->{'name'}); + } + return undef; + } + + # no arg, return entire object + return { map { $_->[1] => LJ::MemCache::array_to_hash("fgrp", [$memver, @$_]) } @$fg }; + }; + + # check memcache + my $memkey = [$uid, "fgrp:$uid"]; + $fg = LJ::MemCache::get($memkey); + return $find_grp->() if $fg; + + # check database + $fg = [$ver]; + my ($db, $fgtable) = $u->{dversion} > 5 ? + (LJ::get_cluster_def_reader($u), 'friendgroup2') : # if dversion is 6+, use definitive reader + (LJ::get_db_writer(), 'friendgroup'); # else, use regular db writer + return undef unless $db; + + my $sth = $db->prepare("SELECT userid, groupnum, groupname, sortorder, is_public " . + "FROM $fgtable WHERE userid=?"); + $sth->execute($uid); + return LJ::error($db) if $db->err; + + my @row; + push @$fg, [ @row ] while @row = $sth->fetchrow_array; + + # set in memcache + LJ::MemCache::set($memkey, $fg); + + return $find_grp->(); +} + +# +# name: LJ::fill_groups_xmlrpc +# des: Fills a hashref (presumably to be sent to an XMLRPC client, EG fotobilder) +# with user friend group information +# args: u, ret +# des-ret: a response hashref to fill with friend group data +# returns: undef if called incorrectly, 1 otherwise +# +sub fill_groups_xmlrpc { + my ($u, $ret) = @_; + return undef unless ref $u && ref $ret; + + # layer on friend group information in the following format: + # + # grp:1 => 'mygroup', + # ... + # grp:30 => 'anothergroup', + # + # grpu:whitaker => '0,1,2,3,4', + # grpu:test => '0', + + my $grp = LJ::get_friend_group($u) || {}; + + $ret->{"grp:0"} = "_all_"; + foreach my $bit (1..30) { + next unless my $g = $grp->{$bit}; + $ret->{"grp:$bit"} = $g->{groupname}; + } + + my $fr = LJ::get_friends($u) || {}; + my $users = LJ::load_userids(keys %$fr); + while (my ($fid, $f) = each %$fr) { + my $u = $users->{$fid}; + next unless $u->{journaltype} =~ /[PS]/; + + my $fname = $u->{user}; + $ret->{"grpu:$fid:$fname"} = + join(",", 0, grep { $grp->{$_} && $f->{groupmask} & 1 << $_ } 1..30); + } + + return 1; +} + +# +# name: LJ::get_friends +# des: Returns friends rows for a given user. +# args: uuserid, mask?, memcache_only?, force? +# des-uuserid: a userid or u object +# des-mask: a security mask to filter on +# des-memcache_only: flag, set to only return data from memcache +# des-force: flag, set to ignore memcache and always hit db +# returns: hashref; keys = friend userids +# values = hashrefs of 'friends' columns and their values +# +sub get_friends { + # TAG:FR:ljlib:get_friends + my ($uuid, $mask, $memcache_only, $force) = @_; + my $userid = LJ::want_userid($uuid); + return undef unless $userid; + return undef if $LJ::FORCE_EMPTY_FRIENDS{$userid}; + + # memcache data version + my $ver = 1; + + my $packfmt = "NH6H6NC"; + my $packlen = 15; # bytes + + my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault); + + # first, check memcache + my $memkey = [$userid, "friends:$userid"]; + + unless ($force) { + my $memfriends = LJ::MemCache::get($memkey); + if ($memfriends) { + my %friends; # rows to be returned + + # first byte of object is data version + # only version 1 is meaningful right now + my $memver = substr($memfriends, 0, 1, ''); + return undef unless $memver == $ver; + + # get each $packlen-byte row + while (length($memfriends) >= $packlen) { + my @row = unpack($packfmt, substr($memfriends, 0, $packlen, '')); + + # don't add into %friends hash if groupmask doesn't match + next if $mask && ! ($row[3]+0 & $mask+0); + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + # turn unpacked row into hashref + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + + # got from memcache, return + return \%friends; + } + } + return {} if $memcache_only; # no friends + + # nothing from memcache, select all rows from the + # database and insert those into memcache + # then return rows that matched the given groupmask + + my $mempack = $ver; # full packed string to insert into memcache, byte 1 is dversion + my %friends; # friends object to be returned, all groupmasks match + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT friendid, fgcolor, bgcolor, groupmask, showbydefault " . + "FROM friends WHERE userid=?"); + $sth->execute($userid); + die $dbh->errstr if $dbh->err; + while (my @row = $sth->fetchrow_array) { + + # convert color columns to hex + $row[$_] = sprintf("%06x", $row[$_]) foreach 1..2; + + $mempack .= pack($packfmt, @row); + + # unless groupmask matches, skip adding to %friends + next if $mask && ! ($row[3]+0 & $mask+0); + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + + LJ::MemCache::add($memkey, $mempack); + + return \%friends; +} + +# +# name: LJ::get_friendofs +# des: Returns userids of friendofs for a given user. +# args: uuserid, opts? +# des-opts: options hash, keys: 'force' => don't check memcache +# returns: userid for friendofs +# +sub get_friendofs { + # TAG:FR:ljlib:get_friends + my ($uuid, $opts) = @_; + my $userid = LJ::want_userid($uuid); + return undef unless $userid; + + # first, check memcache + my $memkey = [$userid, "friendofs:$userid"]; + + unless ($opts->{force}) { + my $memfriendofs = LJ::MemCache::get($memkey); + return @$memfriendofs if $memfriendofs; + } + + # nothing from memcache, select all rows from the + # database and insert those into memcache + + my $dbh = LJ::get_db_writer(); + my $limit = $opts->{force} ? '' : " LIMIT " . ($LJ::MAX_FRIENDOF_LOAD+1); + my $friendofs = $dbh->selectcol_arrayref + ("SELECT userid FROM friends WHERE friendid=?$limit", + undef, $userid) || []; + die $dbh->errstr if $dbh->err; + + LJ::MemCache::add($memkey, $friendofs); + + return @$friendofs; +} + +# +# name: LJ::get_timeupdate_multi +# des: Get the last time a list of users updated +# args: opt?, uids +# des-opt: optional hashref, currently can contain 'memcache_only' +# to only retrieve data from memcache +# des-uids: list of userids to load timeupdates for +# returns: hashref; uid => unix timeupdate +# +sub get_timeupdate_multi { + my ($opt, @uids) = @_; + + # allow optional opt hashref as first argument + unless (ref $opt eq 'HASH') { + push @uids, $opt; + $opt = {}; + } + return {} unless @uids; + + my @memkeys = map { [$_, "tu:$_"] } @uids; + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + + my @need; + my %timeupdate; # uid => timeupdate + foreach (@uids) { + if ($mem->{"tu:$_"}) { + $timeupdate{$_} = unpack("N", $mem->{"tu:$_"}); + } else { + push @need, $_; + } + } + + # if everything was in memcache, return now + return \%timeupdate if $opt->{'memcache_only'} || ! @need; + + # fill in holes from the database. safe to use the reader because we + # only do an add to memcache, whereas postevent does a set, overwriting + # any potentially old data + my $dbr = LJ::get_db_reader(); + my $need_bind = join(",", map { "?" } @need); + my $sth = $dbr->prepare("SELECT userid, UNIX_TIMESTAMP(timeupdate) " . + "FROM userusage WHERE userid IN ($need_bind)"); + $sth->execute(@need); + while (my ($uid, $tu) = $sth->fetchrow_array) { + $timeupdate{$uid} = $tu; + + # set memcache for this row + LJ::MemCache::add([$uid, "tu:$uid"], pack("N", $tu), 30*60); + } + + return \%timeupdate; +} + +# returns undef on error, or otherwise arrayref of arrayrefs, +# each of format [ year, month, day, count ] for all days with +# non-zero count. examples: +# [ [ 2003, 6, 5, 3 ], [ 2003, 6, 8, 4 ], ... ] +# +sub get_daycounts +{ + my ($u, $remote, $not_memcache) = @_; + # NOTE: $remote not yet used. one of the oldest LJ shortcomings is that + # it's public how many entries users have per-day, even if the entries + # are protected. we'll be fixing that with a new table, but first + # we're moving everything to this API. + + my $uid = LJ::want_userid($u) or return undef; + + my @days; + my $memkey = [$uid,"dayct:$uid"]; + unless ($not_memcache) { + my $list = LJ::MemCache::get($memkey); + return $list if $list; + } + + my $dbcr = LJ::get_cluster_def_reader($u) or return undef; + my $sth = $dbcr->prepare("SELECT year, month, day, COUNT(*) ". + "FROM log2 WHERE journalid=? GROUP BY 1, 2, 3"); + $sth->execute($uid); + while (my ($y, $m, $d, $c) = $sth->fetchrow_array) { + # we force each number from string scalars (from DBI) to int scalars, + # so they store smaller in memcache + push @days, [ int($y), int($m), int($d), int($c) ]; + } + LJ::MemCache::add($memkey, \@days); + return \@days; +} + +# +# name: LJ::get_friend_items +# des: Return friend items for a given user, filter, and period. +# args: dbarg?, opts +# des-opts: Hashref of options: +# - userid +# - remoteid +# - itemshow +# - skip +# - filter (opt) defaults to all +# - friends (opt) friends rows loaded via LJ::get_friends() +# - friends_u (opt) u objects of all friends loaded +# - idsbycluster (opt) hashref to set clusterid key to [ [ journalid, itemid ]+ ] +# - dateformat: either "S2" for S2 code, or anything else for S1 +# - common_filter: set true if this is the default view +# - friendsoffriends: load friends of friends, not just friends +# - u: hashref of journal loading friends of +# - showtypes: /[PYC]/ +# returns: Array of item hashrefs containing the same elements +# +sub get_friend_items +{ + &nodb; + my $opts = shift; + + my $dbr = LJ::get_db_reader(); + my $sth; + + my $userid = $opts->{'userid'}+0; + return () if $LJ::FORCE_EMPTY_FRIENDS{$userid}; + + # 'remote' opt takes precendence, then 'remoteid' + my $remote = $opts->{'remote'}; + my $remoteid = $remote ? $remote->{'userid'} : 0; + if ($remoteid == 0 && $opts->{'remoteid'}) { + $remoteid = $opts->{'remoteid'} + 0; + $remote = LJ::load_userid($remoteid); + } + + my @items = (); + my $itemshow = $opts->{'itemshow'}+0; + my $skip = $opts->{'skip'}+0; + my $getitems = $itemshow + $skip; + + my $filter = $opts->{'filter'}+0; + + my $max_age = $LJ::MAX_FRIENDS_VIEW_AGE || 3600*24*14; # 2 week default. + my $lastmax = $LJ::EndOfTime - time() + $max_age; + my $lastmax_cutoff = 0; # if nonzero, never search for entries with rlogtime higher than this (set when cache in use) + + # sanity check: + $skip = 0 if $skip < 0; + + # given a hash of friends rows, strip out rows with invalid journaltype + my $filter_journaltypes = sub { + my ($friends, $friends_u, $memcache_only, $valid_types) = @_; + return unless $friends && $friends_u; + $valid_types ||= uc($opts->{'showtypes'}); + + # load u objects for all the given + LJ::load_userids_multiple([ map { $_, \$friends_u->{$_} } keys %$friends ], [$remote], + $memcache_only); + + # delete u objects based on 'showtypes' + foreach my $fid (keys %$friends_u) { + my $fu = $friends_u->{$fid}; + if ($fu->{'statusvis'} ne "V" || + $valid_types && index(uc($valid_types), $fu->{journaltype}) == -1) + { + delete $friends_u->{$fid}; + delete $friends->{$fid}; + } + } + + # all args passed by reference + return; + }; + + my @friends_buffer = (); + my $fr_loaded = 0; # flag: have we loaded friends? + + # normal friends mode + my $get_next_friend = sub + { + # return one if we already have some loaded. + return $friends_buffer[0] if @friends_buffer; + return undef if $fr_loaded; + + # get all friends for this user and groupmask + my $friends = LJ::get_friends($userid, $filter) || {}; + my %friends_u; + + # strip out rows with invalid journal types + $filter_journaltypes->($friends, \%friends_u); + + # get update times for all the friendids + my $tu_opts = {}; + my $fcount = scalar keys %$friends; + if ($LJ::SLOPPY_FRIENDS_THRESHOLD && $fcount > $LJ::SLOPPY_FRIENDS_THRESHOLD) { + $tu_opts->{memcache_only} = 1; + } + my $timeupdate = LJ::get_timeupdate_multi($tu_opts, keys %$friends); + + # now push a properly formatted @friends_buffer row + foreach my $fid (keys %$timeupdate) { + my $fu = $friends_u{$fid}; + my $rupdate = $LJ::EndOfTime - $timeupdate->{$fid}; + my $clusterid = $fu->{'clusterid'}; + push @friends_buffer, [ $fid, $rupdate, $clusterid, $friends->{$fid}, $fu ]; + } + + @friends_buffer = sort { $a->[1] <=> $b->[1] } @friends_buffer; + + # note that we've already loaded the friends + $fr_loaded = 1; + + # return one if we just found some, else we're all + # out and there's nobody else to load. + return @friends_buffer ? $friends_buffer[0] : undef; + }; + + # memcached friends of friends mode + $get_next_friend = sub + { + # return one if we already have some loaded. + return $friends_buffer[0] if @friends_buffer; + return undef if $fr_loaded; + + # get journal's friends + my $friends = LJ::get_friends($userid) || {}; + return undef unless %$friends; + + my %friends_u; + + # fill %allfriends with all friendids and cut $friends + # down to only include those that match $filter + my %allfriends = (); + foreach my $fid (keys %$friends) { + $allfriends{$fid}++; + + # delete from friends if it doesn't match the filter + next unless $filter && ! ($friends->{$fid}->{'groupmask'}+0 & $filter+0); + delete $friends->{$fid}; + } + + # strip out invalid friend journaltypes + $filter_journaltypes->($friends, \%friends_u, "memcache_only", "P"); + + # get update times for all the friendids + my $f_tu = LJ::get_timeupdate_multi({'memcache_only' => 1}, keys %$friends); + + # get friends of friends + my $ffct = 0; + my %ffriends = (); + foreach my $fid (sort { $f_tu->{$b} <=> $f_tu->{$a} } keys %$friends) { + last if $ffct > 50; + my $ff = LJ::get_friends($fid, undef, "memcache_only") || {}; + my $ct = 0; + while (my $ffid = each %$ff) { + last if $ct > 100; + next if $allfriends{$ffid} || $ffid == $userid; + $ffriends{$ffid} = $ff->{$ffid}; + $ct++; + } + $ffct++; + } + + # strip out invalid friendsfriends journaltypes + my %ffriends_u; + $filter_journaltypes->(\%ffriends, \%ffriends_u, "memcache_only"); + + # get update times for all the friendids + my $ff_tu = LJ::get_timeupdate_multi({'memcache_only' => 1}, keys %ffriends); + + # build friends buffer + foreach my $ffid (sort { $ff_tu->{$b} <=> $ff_tu->{$a} } keys %$ff_tu) { + my $rupdate = $LJ::EndOfTime - $ff_tu->{$ffid}; + my $clusterid = $ffriends_u{$ffid}->{'clusterid'}; + + # since this is ff mode, we'll force colors to ffffff on 000000 + $ffriends{$ffid}->{'fgcolor'} = "#000000"; + $ffriends{$ffid}->{'bgcolor'} = "#ffffff"; + + push @friends_buffer, [ $ffid, $rupdate, $clusterid, $ffriends{$ffid}, $ffriends_u{$ffid} ]; + } + + @friends_buffer = sort { $a->[1] <=> $b->[1] } @friends_buffer; + + # note that we've already loaded the friends + $fr_loaded = 1; + + # return one if we just found some fine, else we're all + # out and there's nobody else to load. + return @friends_buffer ? $friends_buffer[0] : undef; + + } if $opts->{'friendsoffriends'} && @LJ::MEMCACHE_SERVERS; + + # old friends of friends mode + # - use this when there are no memcache servers + $get_next_friend = sub + { + # return one if we already have some loaded. + return $friends_buffer[0] if @friends_buffer; + return undef if $fr_loaded; + + # load all user's friends + # TAG:FR:ljlib:old_friendsfriends_getitems + my %f; + my $sth = $dbr->prepare(qq{ + SELECT f.friendid, f.groupmask, $LJ::EndOfTime-UNIX_TIMESTAMP(uu.timeupdate), + u.journaltype FROM friends f, userusage uu, user u + WHERE f.userid=? AND f.friendid=uu.userid AND u.userid=f.friendid AND u.journaltype='P' + }); + $sth->execute($userid); + while (my ($id, $mask, $time, $jt) = $sth->fetchrow_array) { + next if $id == $userid; # don't follow user's own friends + $f{$id} = { 'userid' => $id, 'timeupdate' => $time, 'jt' => $jt, + 'relevant' => ($filter && !($mask & $filter)) ? 0 : 1 , }; + } + + # load some friends of friends (most 20 queries) + my %ff; + my $fct = 0; + foreach my $fid (sort { $f{$a}->{'timeupdate'} <=> $f{$b}->{'timeupdate'} } keys %f) + { + next unless $f{$fid}->{'jt'} eq "P" && $f{$fid}->{'relevant'}; + last if ++$fct > 20; + my $extra; + if ($opts->{'showtypes'}) { + my @in; + if ($opts->{'showtypes'} =~ /P/) { push @in, "'P'"; } + if ($opts->{'showtypes'} =~ /Y/) { push @in, "'Y'"; } + if ($opts->{'showtypes'} =~ /C/) { push @in, "'C','S','N'"; } + $extra = "AND u.journaltype IN (".join (',', @in).")" if @in; + } + + # TAG:FR:ljlib:old_friendsfriends_getitems2 + my $sth = $dbr->prepare(qq{ + SELECT u.*, UNIX_TIMESTAMP(uu.timeupdate) AS timeupdate + FROM friends f, userusage uu, user u WHERE f.userid=? AND + f.friendid=uu.userid AND f.friendid=u.userid AND u.statusvis='V' $extra + AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 14 DAY) LIMIT 100 + }); + $sth->execute($fid); + while (my $u = $sth->fetchrow_hashref) { + my $uid = $u->{'userid'}; + next if $f{$uid} || $uid == $userid; # we don't wanna see our friends + + # timeupdate + my $time = $LJ::EndOfTime-$u->{'timeupdate'}; + delete $u->{'timeupdate'}; # not a proper $u column + + $ff{$uid} = [ $uid, $time, $u->{'clusterid'}, {}, $u ]; + } + } + + @friends_buffer = sort { $a->[1] <=> $b->[1] } values %ff; + $fr_loaded = 1; + + return @friends_buffer ? $friends_buffer[0] : undef; + + } if $opts->{'friendsoffriends'} && ! @LJ::MEMCACHE_SERVERS; + + my $loop = 1; + my $itemsleft = $getitems; # even though we got a bunch, potentially, they could be old + my $fr; + + while ($loop && ($fr = $get_next_friend->())) + { + shift @friends_buffer; + + # load the next recent updating friend's recent items + my $friendid = $fr->[0]; + + $opts->{'friends'}->{$friendid} = $fr->[3]; # friends row + $opts->{'friends_u'}->{$friendid} = $fr->[4]; # friend u object + + my @newitems = LJ::get_log2_recent_user({ + 'clusterid' => $fr->[2], + 'userid' => $friendid, + 'remote' => $remote, + 'itemshow' => $itemsleft, + 'notafter' => $lastmax, + 'dateformat' => $opts->{'dateformat'}, + 'update' => $LJ::EndOfTime - $fr->[1], # reverse back to normal + }); + + # stamp each with clusterid if from cluster, so ljviews and other + # callers will know which items are old (no/0 clusterid) and which + # are new + if ($fr->[2]) { + foreach (@newitems) { $_->{'clusterid'} = $fr->[2]; } + } + + if (@newitems) + { + push @items, @newitems; + + $itemsleft--; # we'll need at least one less for the next friend + + # sort all the total items by rlogtime (recent at beginning). + # if there's an in-second tie, the "newer" post is determined by + # the higher jitemid, which means nothing if the posts are in the same + # journal, but means everything if they are (which happens almost never + # for a human, but all the time for RSS feeds, once we remove the + # synsucker's 1-second delay between postevents) + @items = sort { $a->{'rlogtime'} <=> $b->{'rlogtime'} || + $b->{'jitemid'} <=> $a->{'jitemid'} } @items; + + # cut the list down to what we need. + @items = splice(@items, 0, $getitems) if (@items > $getitems); + } + + if (@items == $getitems) + { + $lastmax = $items[-1]->{'rlogtime'}; + $lastmax = $lastmax_cutoff if $lastmax_cutoff && $lastmax > $lastmax_cutoff; + + # stop looping if we know the next friend's newest entry + # is greater (older) than the oldest one we've already + # loaded. + my $nextfr = $get_next_friend->(); + $loop = 0 if ($nextfr && $nextfr->[1] > $lastmax); + } + } + + # remove skipped ones + splice(@items, 0, $skip) if $skip; + + # get items + foreach (@items) { + $opts->{'owners'}->{$_->{'ownerid'}} = 1; + } + + # return the itemids grouped by clusters, if callers wants it. + if (ref $opts->{'idsbycluster'} eq "HASH") { + foreach (@items) { + push @{$opts->{'idsbycluster'}->{$_->{'clusterid'}}}, + [ $_->{'ownerid'}, $_->{'itemid'} ]; + } + } + + return @items; +} + +# +# name: LJ::get_recent_items +# class: +# des: Returns journal entries for a given account. +# info: +# args: dbarg, opts +# des-opts: Hashref of options with keys: +# -- err: scalar ref to return error code/msg in +# -- userid +# -- remote: remote user's $u +# -- remoteid: id of remote user +# -- clusterid: clusterid of userid +# -- tagids: arrayref of tagids to return entries with +# -- clustersource: if value 'slave', uses replicated databases +# -- order: if 'logtime', sorts by logtime, not eventtime +# -- friendsview: if true, sorts by logtime, not eventtime +# -- notafter: upper bound inclusive for rlogtime/revttime (depending on sort mode), +# defaults to no limit +# -- skip: items to skip +# -- itemshow: items to show +# -- viewall: if set, no security is used. +# -- dateformat: if "S2", uses S2's 'alldatepart' format. +# -- itemids: optional arrayref onto which itemids should be pushed +# returns: array of hashrefs containing keys: +# -- itemid (the jitemid) +# -- posterid +# -- security +# -- alldatepart (in S1 or S2 fmt, depending on 'dateformat' req key) +# -- ownerid (if in 'friendsview' mode) +# -- rlogtime (if in 'friendsview' mode) +# +sub get_recent_items +{ + &nodb; + my $opts = shift; + + my $sth; + + my @items = (); # what we'll return + my $err = $opts->{'err'}; + + my $userid = $opts->{'userid'}+0; + + # 'remote' opt takes precendence, then 'remoteid' + my $remote = $opts->{'remote'}; + my $remoteid = $remote ? $remote->{'userid'} : 0; + if ($remoteid == 0 && $opts->{'remoteid'}) { + $remoteid = $opts->{'remoteid'} + 0; + $remote = LJ::load_userid($remoteid); + } + + my $max_hints = $LJ::MAX_HINTS_LASTN; # temporary + my $sort_key = "revttime"; + + my $clusterid = $opts->{'clusterid'}+0; + my @sources = ("cluster$clusterid"); + if (my $ab = $LJ::CLUSTER_PAIR_ACTIVE{$clusterid}) { + @sources = ("cluster${clusterid}${ab}"); + } + unshift @sources, ("cluster${clusterid}lite", "cluster${clusterid}slave") + if $opts->{'clustersource'} eq "slave"; + my $logdb = LJ::get_dbh(@sources); + + # community/friend views need to post by log time, not event time + $sort_key = "rlogtime" if ($opts->{'order'} eq "logtime" || + $opts->{'friendsview'}); + + # 'notafter': + # the friends view doesn't want to load things that it knows it + # won't be able to use. if this argument is zero or undefined, + # then we'll load everything less than or equal to 1 second from + # the end of time. we don't include the last end of time second + # because that's what backdated entries are set to. (so for one + # second at the end of time we'll have a flashback of all those + # backdated entries... but then the world explodes and everybody + # with 32 bit time_t structs dies) + my $notafter = $opts->{'notafter'} + 0 || $LJ::EndOfTime - 1; + + my $skip = $opts->{'skip'}+0; + my $itemshow = $opts->{'itemshow'}+0; + if ($itemshow > $max_hints) { $itemshow = $max_hints; } + my $maxskip = $max_hints - $itemshow; + if ($skip < 0) { $skip = 0; } + if ($skip > $maxskip) { $skip = $maxskip; } + my $itemload = $itemshow + $skip; + + my $mask = 0; + if ($remote && $remote->{'journaltype'} eq "P" && $remoteid != $userid) { + $mask = LJ::get_groupmask($userid, $remoteid); + } + + # decide what level of security the remote user can see + my $secwhere = ""; + if ($userid == $remoteid || $opts->{'viewall'}) { + # no extra where restrictions... user can see all their own stuff + # alternatively, if 'viewall' opt flag is set, security is off. + } elsif ($mask) { + # can see public or things with them in the mask + $secwhere = "AND (security='public' OR (security='usemask' AND allowmask & $mask != 0))"; + } else { + # not a friend? only see public. + $secwhere = "AND security='public' "; + } + + # because LJ::get_friend_items needs rlogtime for sorting. + my $extra_sql; + if ($opts->{'friendsview'}) { + $extra_sql .= "journalid AS 'ownerid', rlogtime, "; + } + + # if we need to get by tag, get an itemid list now + my $jitemidwhere; + if (ref $opts->{tagids} eq 'ARRAY' && @{$opts->{tagids}}) { + # select jitemids uniquely + my $in = join(',', map { $_+0 } @{$opts->{tagids}}); + my $jitemids = $logdb->selectcol_arrayref(qq{ + SELECT DISTINCT jitemid FROM logtagsrecent WHERE journalid = ? AND kwid IN ($in) + }, undef, $userid); + die $logdb->errstr if $logdb->err; + + # set $jitemidwhere iff we have jitemids + if (@$jitemids) { + $jitemidwhere = " AND jitemid IN (" . + join(',', map { $_+0 } @$jitemids) . + ")"; + } else { + # no items, so show no entries + return (); + } + } + + my $sql; + + my $dateformat = "%a %W %b %M %y %Y %c %m %e %d %D %p %i %l %h %k %H"; + if ($opts->{'dateformat'} eq "S2") { + $dateformat = "%Y %m %d %H %i %s %w"; # yyyy mm dd hh mm ss day_of_week + } + + $sql = qq{ + SELECT jitemid AS 'itemid', posterid, security, $extra_sql + DATE_FORMAT(eventtime, "$dateformat") AS 'alldatepart', anum + FROM log2 USE INDEX ($sort_key) + WHERE journalid=$userid AND $sort_key <= $notafter $secwhere $jitemidwhere + ORDER BY journalid, $sort_key + LIMIT $skip,$itemshow + }; + + unless ($logdb) { + $$err = "nodb" if ref $err eq "SCALAR"; + return (); + } + + $sth = $logdb->prepare($sql); + $sth->execute; + if ($logdb->err) { die $logdb->errstr; } + + # keep track of the last alldatepart, and a per-minute buffer + my $last_time; + my @buf; + my $flush = sub { + return unless @buf; + push @items, sort { $b->{itemid} <=> $a->{itemid} } @buf; + @buf = (); + }; + + while (my $li = $sth->fetchrow_hashref) { + push @{$opts->{'itemids'}}, $li->{'itemid'}; + + $flush->() if $li->{alldatepart} ne $last_time; + push @buf, $li; + $last_time = $li->{alldatepart}; + } + $flush->(); + + return @items; +} + +# +# name: LJ::set_userprop +# des: Sets/deletes a userprop by name for a user. +# info: This adds or deletes from the +# [dbtable[userprop]]/[dbtable[userproplite]] tables. One +# crappy thing about this interface is that it doesn't allow +# a batch of userprops to be updated at once, which is the +# common thing to do. +# args: dbarg?, uuserid, propname, value, memonly? +# des-uuserid: The userid of the user or a user hashref. +# des-propname: The name of the property. Or a hashref of propname keys and corresponding values. +# des-value: The value to set to the property. If undefined or the +# empty string, then property is deleted. +# des-memonly: if true, only writes to memcache, and not to database. +# +sub set_userprop +{ + &nodb; + + my ($u, $propname, $value, $memonly) = @_; + $u = ref $u ? $u : LJ::load_userid($u); + my $userid = $u->{'userid'}+0; + + my $hash = ref $propname eq "HASH" ? $propname : { $propname => $value }; + + my %action; # $table -> {"replace"|"delete"} -> [ "($userid, $propid, $qvalue)" | propid ] + my %multihomed; # { $propid => $value } + + foreach $propname (keys %$hash) { + my $p = LJ::get_prop("user", $propname) or + die "Invalid userprop $propname passed to LJ::set_userprop."; + if ($p->{multihomed}) { + # collect into array for later handling + $multihomed{$p->{id}} = $hash->{$propname}; + next; + } + my $table = $p->{'indexed'} ? "userprop" : "userproplite"; + if ($p->{datatype} eq 'blobchar') { + $table = 'userpropblob'; + } + elsif ($p->{'cldversion'} && $u->{'dversion'} >= $p->{'cldversion'}) { + $table = "userproplite2"; + } + unless ($memonly) { + my $db = $action{$table}->{'db'} ||= ( + $table !~ m{userprop(lite2|blob)} + ? LJ::get_db_writer() + : $u->writer ); + return 0 unless $db; + } + $value = $hash->{$propname}; + if (defined $value && $value) { + push @{$action{$table}->{"replace"}}, [ $p->{'id'}, $value ]; + } else { + push @{$action{$table}->{"delete"}}, $p->{'id'}; + } + } + + my $expire = time() + 3600*24; + foreach my $table (keys %action) { + my $db = $action{$table}->{'db'}; + if (my $list = $action{$table}->{"replace"}) { + if ($db) { + my $vals = join(',', map { "($userid,$_->[0]," . $db->quote($_->[1]) . ")" } @$list); + $db->do("REPLACE INTO $table (userid, upropid, value) VALUES $vals"); + } + LJ::MemCache::set([$userid,"uprop:$userid:$_->[0]"], $_->[1], $expire) foreach (@$list); + } + if (my $list = $action{$table}->{"delete"}) { + if ($db) { + my $in = join(',', @$list); + $db->do("DELETE FROM $table WHERE userid=$userid AND upropid IN ($in)"); + } + LJ::MemCache::set([$userid,"uprop:$userid:$_"], "", $expire) foreach (@$list); + } + } + + # if we had any multihomed props, set them here + if (%multihomed) { + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh && $u->writer; + while (my ($propid, $pvalue) = each %multihomed) { + if (defined $pvalue && $pvalue) { + # replace data into master + $dbh->do("REPLACE INTO userprop VALUES (?, ?, ?)", + undef, $userid, $propid, $pvalue); + } else { + # delete data from master, but keep in cluster + $dbh->do("DELETE FROM userprop WHERE userid = ? AND upropid = ?", + undef, $userid, $propid); + } + + # fail out? + return 0 if $dbh->err; + + # put data in cluster + $pvalue ||= ''; + $u->do("REPLACE INTO userproplite2 VALUES (?, ?, ?)", + undef, $userid, $propid, $pvalue); + return 0 if $u->err; + + # set memcache + LJ::MemCache::set([$userid,"uprop:$userid:$propid"], $pvalue, $expire); + } + } + + return 1; +} + +# +# name: LJ::register_authaction +# des: Registers a secret to have the user validate. +# info: Some things, like requiring a user to validate their email address, require +# making up a secret, mailing it to the user, then requiring them to give it +# back (usually in a URL you make for them) to prove they got it. This +# function creates a secret, attaching what it's for and an optional argument. +# Background maintenance jobs keep track of cleaning up old unvalidated secrets. +# args: dbarg?, userid, action, arg? +# des-userid: Userid of user to register authaction for. +# des-action: Action type to register. Max chars: 50. +# des-arg: Optional argument to attach to the action. Max chars: 255. +# returns: 0 if there was an error. Otherwise, a hashref +# containing keys 'aaid' (the authaction ID) and the 'authcode', +# a 15 character string of random characters from +# [func[LJ::make_auth_code]]. +# +sub register_authaction +{ + &nodb; + my $dbh = LJ::get_db_writer(); + + my $userid = shift; $userid += 0; + my $action = $dbh->quote(shift); + my $arg1 = $dbh->quote(shift); + + # make the authcode + my $authcode = LJ::make_auth_code(15); + my $qauthcode = $dbh->quote($authcode); + + $dbh->do("INSERT INTO authactions (aaid, userid, datecreate, authcode, action, arg1) ". + "VALUES (NULL, $userid, NOW(), $qauthcode, $action, $arg1)"); + + return 0 if $dbh->err; + return { 'aaid' => $dbh->{'mysql_insertid'}, + 'authcode' => $authcode, + }; +} + +# +# class: logging +# name: LJ::statushistory_add +# des: Adds a row to a user's statushistory +# info: See the [dbtable[statushistory]] table. +# returns: boolean; 1 on success, 0 on failure +# args: dbarg?, userid, adminid, shtype, notes? +# des-userid: The user being acted on. +# des-adminid: The site admin doing the action. +# des-shtype: The status history type code. +# des-notes: Optional notes associated with this action. +# +sub statushistory_add +{ + &nodb; + my $dbh = LJ::get_db_writer(); + + my $userid = shift; + $userid = LJ::want_userid($userid) + 0; + + my $actid = shift; + $actid = LJ::want_userid($actid) + 0; + + my $qshtype = $dbh->quote(shift); + my $qnotes = $dbh->quote(shift); + + $dbh->do("INSERT INTO statushistory (userid, adminid, shtype, notes) ". + "VALUES ($userid, $actid, $qshtype, $qnotes)"); + return $dbh->err ? 0 : 1; +} + +# +# name: LJ::make_link +# des: Takes a group of key=value pairs to append to a url +# returns: The finished url +# args: url, vars +# des-url: A string with the URL to append to. The URL +# shouldn't have a question mark in it. +# des-vars: A hashref of the key=value pairs to append with. +# +sub make_link +{ + my $url = shift; + my $vars = shift; + my $append = "?"; + foreach (keys %$vars) { + next if ($vars->{$_} eq ""); + $url .= "${append}${_}=$vars->{$_}"; + $append = "&"; + } + return $url; +} + +# +# class: time +# name: LJ::ago_text +# des: Converts integer seconds to English time span +# info: Turns a number of seconds into the largest possible unit of +# time. "2 weeks", "4 days", or "20 hours". +# returns: A string with the number of largest units found +# args: secondsold +# des-secondsold: The number of seconds from now something was made. +# +sub ago_text +{ + my $secondsold = shift; + return "Never." unless defined $secondsold; + my $num; + my $unit; + if ($secondsold > 60*60*24*7) { + $num = int($secondsold / (60*60*24*7)); + $unit = "week"; + } elsif ($secondsold > 60*60*24) { + $num = int($secondsold / (60*60*24)); + $unit = "day"; + } elsif ($secondsold > 60*60) { + $num = int($secondsold / (60*60)); + $unit = "hour"; + } elsif ($secondsold > 60) { + $num = int($secondsold / (60)); + $unit = "minute"; + } else { + $num = $secondsold; + $unit = "second"; + } + return "$num $unit" . ($num==1?"":"s") . " ago"; +} + +# +# name: LJ::get_shared_journals +# des: Gets an array of shared journals a user has access to. +# returns: An array of shared journals. +# args: u +# +sub get_shared_journals +{ + my $u = shift; + my $ids = LJ::load_rel_target($u, 'A') || []; + + # have to get usernames; + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } @$ids ], [$u]); + return sort map { $_->{'user'} } values %users; +} + +# +# name: LJ::get_authas_user +# des: Given a username, will return a user object if remote is an admin for the +# username. Otherwise returns undef +# returns: user object if authenticated, otherwise undef. +# args: user +# des-opts: Username of user to attempt to auth as. +# +sub get_authas_user { + my $user = shift; + return undef unless $user; + + # get a remote + my $remote = LJ::get_remote(); + return undef unless $remote; + + # remote is already what they want? + return $remote if $remote->{'user'} eq $user; + + # load user and authenticate + my $u = LJ::load_user($user); + return undef unless $u; + return undef unless $u->{clusterid}; + + # does $u have admin access? + return undef unless LJ::can_manage($remote, $u); + + # passed all checks, return $u + return $u; +} + +# +# name: LJ::can_manage +# des: Given a user and a target user, will determine if the first user is an +# admin for the target user. +# returns: bool: true if authorized, otherwise fail +# args: remote, u +# des-remote: user object or userid of user to try and authenticate +# des-u: user object or userid of target user +# +sub can_manage { + my $remote = LJ::want_user(shift); + my $u = LJ::want_user(shift); + return undef unless $remote && $u; + + # is same user? + return 1 if LJ::u_equals($u, $remote); + + # people/syn/rename accounts can only be managed by the one account + return undef if $u->{journaltype} =~ /^[PYR]$/; + + # check for admin access + return undef unless LJ::check_rel($u, $remote, 'A'); + + # passed checks, return true + return 1; +} + +# +# name: LJ::can_manage_other +# des: Given a user and a target user, will determine if the first user is an +# admin for the target user, but not if the two are the same. +# returns: bool: true if authorized, otherwise fail +# args: remote, u +# des-remote: user object or userid of user to try and authenticate +# des-u: user object or userid of target user +# +sub can_manage_other { + my ($remote, $u) = @_; + return 0 if LJ::want_userid($remote) == LJ::want_userid($u); + return LJ::can_manage($remote, $u); +} + +sub can_delete_journal_item { + return LJ::can_manage(@_); +} + +# +# name: LJ::get_authas_list +# des: Get a list of usernames a given user can authenticate as +# returns: an array of usernames +# args: u, opts? +# des-opts: Optional hashref. keys are: +# - type: 'P' to only return users of journaltype 'P' +# - cap: cap to filter users on +# +sub get_authas_list { + my ($u, $opts) = @_; + + # used to accept a user type, now accept an opts hash + $opts = { 'type' => $opts } unless ref $opts; + + # only one valid type right now + $opts->{'type'} = 'P' if $opts->{'type'}; + + my $ids = LJ::load_rel_target($u, 'A'); + return undef unless $ids; + + # load_userids_multiple + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } @$ids ], [$u]); + + return $u->{'user'}, sort map { $_->{'user'} } + grep { ! $opts->{'cap'} || LJ::get_cap($_, $opts->{'cap'}) } + grep { ! $opts->{'type'} || $opts->{'type'} eq $_->{'journaltype'} } + grep { $_->{clusterid} > 0 } + grep { $_->{statusvis} !~ /[XS]/ } + values %users; +} + +# +# name: LJ::shared_member_request +# des: Registers an authaction to add a user to a +# shared journal and sends an approval email +# returns: Hashref; output of LJ::register_authaction() +# includes datecreate of old row if no new row was created +# args: ju, u, attr? +# des-ju: Shared journal user object +# des-u: User object to add to shared journal +# +sub shared_member_request { + my ($ju, $u) = @_; + return undef unless ref $ju && ref $u; + + my $dbh = LJ::get_db_writer(); + + # check for duplicates + my $oldaa = $dbh->selectrow_hashref("SELECT aaid, authcode, datecreate FROM authactions " . + "WHERE userid=? AND action='shared_invite' AND used='N' " . + "AND NOW() < datecreate + INTERVAL 1 HOUR " . + "ORDER BY 1 DESC LIMIT 1", + undef, $ju->{'userid'}); + return $oldaa if $oldaa; + + # insert authactions row + my $aa = LJ::register_authaction($ju->{'userid'}, 'shared_invite', "targetid=$u->{'userid'}"); + return undef unless $aa; + + # if there are older duplicates, invalidate any existing unused authactions of this type + $dbh->do("UPDATE authactions SET used='Y' WHERE userid=? AND aaid<>? " . + "AND action='shared_invite' AND used='N'", + undef, $ju->{'userid'}, $aa->{'aaid'}); + + my $body = "The maintainer of the $ju->{'user'} shared journal has requested that " . + "you be given posting access.\n\n" . + "If you do not wish to be added to this journal, just ignore this email. " . + "However, if you would like to accept posting rights to $ju->{'user'}, click " . + "the link below to authorize this action.\n\n" . + " $LJ::SITEROOT/approve/$aa->{'aaid'}.$aa->{'authcode'}\n\n" . + "Regards\n$LJ::SITENAME Team\n"; + + LJ::send_mail({ + 'to' => $u->{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => "Community Membership: $ju->{'name'}", + 'body' => $body + }); + + return $aa; +} + +# +# name: LJ::is_valid_authaction +# des: Validates a shared secret (authid/authcode pair) +# info: See [func[LJ::register_authaction]]. +# returns: Hashref of authaction row from database. +# args: dbarg?, aaid, auth +# des-aaid: Integer; the authaction ID. +# des-auth: String; the auth string. (random chars the client already got) +# +sub is_valid_authaction +{ + &nodb; + + # we use the master db to avoid races where authactions could be + # used multiple times + my $dbh = LJ::get_db_writer(); + my ($aaid, $auth) = @_; + return $dbh->selectrow_hashref("SELECT * FROM authactions WHERE aaid=? AND authcode=?", + undef, $aaid, $auth); +} + +# +# name: LJ::mark_authaction_used +# des: Marks an authaction as being used. +# args: aaid +# des-aaid: Either an authaction hashref or the id of the authaction to mark used. +# returns: 1 on success, undef on error. +# +sub mark_authaction_used +{ + my $aaid = ref $_[0] ? $_[0]->{aaid}+0 : $_[0]+0 + or return undef; + my $dbh = LJ::get_db_writer() + or return undef; + $dbh->do("UPDATE authactions SET used='Y' WHERE aaid = ?", undef, $aaid); + return undef if $dbh->err; + return 1; +} + +# +# name: LJ::get_mood_picture +# des: Loads a mood icon hashref given a themeid and moodid. +# args: themeid, moodid, ref +# des-themeid: Integer; mood themeid. +# des-moodid: Integer; mood id. +# des-ref: Hashref to load mood icon data into. +# returns: Boolean; 1 on success, 0 otherwise. +# +sub get_mood_picture +{ + my ($themeid, $moodid, $ref) = @_; + LJ::load_mood_theme($themeid) unless $LJ::CACHE_MOOD_THEME{$themeid}; + LJ::load_moods() unless $LJ::CACHED_MOODS; + do + { + if ($LJ::CACHE_MOOD_THEME{$themeid} && + $LJ::CACHE_MOOD_THEME{$themeid}->{$moodid}) { + %{$ref} = %{$LJ::CACHE_MOOD_THEME{$themeid}->{$moodid}}; + if ($ref->{'pic'} =~ m!^/!) { + $ref->{'pic'} =~ s!^/img!!; + $ref->{'pic'} = $LJ::IMGPREFIX . $ref->{'pic'}; + } + $ref->{'moodid'} = $moodid; + return 1; + } else { + $moodid = (defined $LJ::CACHE_MOODS{$moodid} ? + $LJ::CACHE_MOODS{$moodid}->{'parent'} : 0); + } + } + while ($moodid); + return 0; +} + +# mood id to name (or undef) +sub mood_name +{ + my ($moodid) = @_; + LJ::load_moods() unless $LJ::CACHED_MOODS; + my $m = $LJ::CACHE_MOODS{$moodid}; + return $m ? $m->{'name'} : undef; +} + +# mood name to id (or undef) +sub mood_id +{ + my ($mood) = @_; + return undef unless $mood; + LJ::load_moods() unless $LJ::CACHED_MOODS; + foreach my $m (values %LJ::CACHE_MOODS) { + return $m->{'id'} if $mood eq $m->{'name'}; + } + return undef; +} + +sub get_moods +{ + LJ::load_moods() unless $LJ::CACHED_MOODS; + return \%LJ::CACHE_MOODS; +} + +# +# class: time +# name: LJ::http_to_time +# des: Converts HTTP date to Unix time. +# info: Wrapper around HTTP::Date::str2time. +# See also [func[LJ::time_to_http]]. +# args: string +# des-string: HTTP Date. See RFC 2616 for format. +# returns: integer; Unix time. +# +sub http_to_time { + my $string = shift; + return HTTP::Date::str2time($string); +} + +sub mysqldate_to_time { + my ($string, $gmt) = @_; + return undef unless $string =~ /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/; + my ($y, $mon, $d, $h, $min, $s) = ($1, $2, $3, $4, $5, $6); + my $calc = sub { + $gmt ? + Time::Local::timegm($s, $min, $h, $d, $mon-1, $y) : + Time::Local::timelocal($s, $min, $h, $d, $mon-1, $y); + }; + + # try to do it. it'll die if the day is bogus + my $ret = eval { $calc->(); }; + return $ret unless $@; + + # then fix the day up, if so. + my $max_day = LJ::days_in_month($mon, $y); + $d = $max_day if $d > $max_day; + return $calc->(); +} + +# +# class: time +# name: LJ::time_to_http +# des: Converts a Unix time to an HTTP date. +# info: Wrapper around HTTP::Date::time2str to make an +# HTTP date (RFC 1123 format) See also [func[LJ::http_to_time]]. +# args: time +# des-time: Integer; Unix time. +# returns: String; RFC 1123 date. +# +sub time_to_http { + my $time = shift; + return HTTP::Date::time2str($time); +} + +# +# name: LJ::time_to_cookie +# des: Converts unix time to format expected in a Set-Cookie header +# args: time +# des-time: unix time +# returns: string; Date/Time in format expected by cookie. +# +sub time_to_cookie { + my $time = shift; + $time = time() unless defined $time; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time); + $year+=1900; + + my @day = qw{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + return sprintf("$day[$wday], %02d-$month[$mon]-%04d %02d:%02d:%02d GMT", + $mday, $year, $hour, $min, $sec); +} + +# http://www.w3.org/TR/NOTE-datetime +# http://www.w3.org/TR/xmlschema-2/#dateTime +sub time_to_w3c { + my ($time, $ofs) = @_; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time); + + $mon++; + $year += 1900; + + $ofs =~ s/([\-+]\d\d)(\d\d)/$1:$2/; + $ofs = 'Z' if $ofs =~ /0000$/; + return sprintf("%04d-%02d-%02dT%02d:%02d:%02d$ofs", + $year, $mon, $mday, + $hour, $min, $sec); +} + +# +# class: component +# name: LJ::ljuser +# des: Make link to userinfo/journal of user. +# info: Returns the HTML for a userinfo/journal link pair for a given user +# name, just like LJUSER does in BML. This is for files like cleanhtml.pl +# and ljpoll.pl which need this functionality too, but they aren't run as BML. +# args: user, opts? +# des-user: Username to link to, or user hashref. +# des-opts: Optional hashref to control output. Key 'full' when true causes +# a link to the mode=full userinfo. Key 'type' when 'C' makes +# a community link, when 'Y' makes a syndicated account link, +# when 'N' makes a news account link, otherwise makes a user account +# link. If user parameter is a hashref, its 'journaltype' overrides +# this 'type'. Key 'del', when true, makes a tag for a deleted user. +# If user parameter is a hashref, its 'statusvis' overrides 'del'. +# Key 'no_follow', when true, disables traversal of renamed users. +# returns: HTML with a little head image & bold text link. +# +sub ljuser +{ + my $user = shift; + my $opts = shift; + my $u; + my $do_dynamic = $LJ::DYNAMIC_LJUSER || ($user =~ /^ext_/); + if ($do_dynamic && ! isu($user) && ! $opts->{'type'}) { + # Try to automatically pick the user type, but still + # make something if we can't (user doesn't exist?) + $user = LJ::load_user($user) || $user; + + my $hops = 0; + + # Traverse the renames to the final journal + while (ref $user and $user->{'journaltype'} eq 'R' + and ! $opts->{'no_follow'} && $hops++ < 5) { + + LJ::load_user_props($user, 'renamedto'); + last unless length $user->{'renamedto'}; + $user = LJ::load_user($user->{'renamedto'}); + } + } + + if (isu($user)) { + $u = $user; + $opts->{'type'} = $user->{'journaltype'}; + # Mark accounts as deleted that aren't visible, memorial, or locked + $opts->{'del'} = $user->{'statusvis'} ne 'V' && + $user->{'statusvis'} ne 'M' && + $user->{'statusvis'} ne 'L'; + $user = $user->{'user'}; + } + my $andfull = $opts->{'full'} ? "&mode=full" : ""; + my $img = $opts->{'imgroot'} || $LJ::IMGPREFIX; + my $strike = $opts->{'del'} ? ' text-decoration: line-through;' : ''; + my $make_tag = sub { + my ($fil, $dir, $x, $y) = @_; + $y ||= $x; # make square if only one dimension given + + return "[info]$user"; + }; + + if ($opts->{'type'} eq 'C') { + return $make_tag->('community.gif', 'community', 16); + } elsif ($opts->{'type'} eq 'Y') { + return $make_tag->('syndicated.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'N') { + return $make_tag->('newsinfo.gif', 'users', 16); + } elsif ($opts->{'type'} eq 'I') { + return $u->ljuser_display($opts); + } else { + return $make_tag->('userinfo.gif', 'users', 17); + } +} + +# +# name: LJ::get_urls +# des: Returns a list of all referenced URLs from a string +# args: text +# des-text: Text to extra URLs from +# returns: list of URLs +# +sub get_urls +{ + return ($_[0] =~ m!http://[^\s\"\'\<\>]+!g); +} + +# +# name: LJ::record_meme +# des: Records a URL reference from a journal entry to the meme table. +# args: dbarg?, url, posterid, itemid, journalid? +# des-url: URL to log +# des-posterid: Userid of person posting +# des-itemid: Itemid URL appears in. This is the display itemid, +# which is the jitemid*256+anum from the [dbtable[log2]] table. +# des-journalid: Optional, journal id of item, if item is clustered. Otherwise +# this should be zero or undef. +# +sub record_meme +{ + my ($url, $posterid, $itemid, $jid) = @_; + return if $LJ::DISABLED{'meme'}; + + $url =~ s!/$!!; # strip / at end + LJ::run_hooks("canonicalize_url", \$url); + + # canonicalize_url hook might just erase it, so + # we don't want to record it. + return unless $url; + + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE DELAYED INTO meme (url, posterid, journalid, itemid) " . + "VALUES (?, ?, ?, ?)", undef, $url, $posterid, $jid, $itemid); +} + +# +# name: LJ::name_caps +# des: Given a user's capability class bit mask, returns a +# site-specific string representing the capability class name. +# args: caps +# des-caps: 16 bit capability bitmask +# +sub name_caps +{ + return undef unless LJ::are_hooks("name_caps"); + my $caps = shift; + return LJ::run_hook("name_caps", $caps); +} + +# +# name: LJ::name_caps_short +# des: Given a user's capability class bit mask, returns a +# site-specific short string code. +# args: caps +# des-caps: 16 bit capability bitmask +# +sub name_caps_short +{ + return undef unless LJ::are_hooks("name_caps_short"); + my $caps = shift; + return LJ::run_hook("name_caps_short", $caps); +} + +# +# name: LJ::get_cap +# des: Given a user object or capability class bit mask and a capability/limit name, +# returns the maximum value allowed for given user or class, considering +# all the limits in each class the user is a part of. +# args: u_cap, capname +# des-u_cap: 16 bit capability bitmask or a user object from which the +# bitmask could be obtained +# des-capname: the name of a limit, defined in doc/capabilities.txt +# +sub get_cap +{ + my $caps = shift; # capability bitmask (16 bits), or user object + my $cname = shift; # capability limit name + my $u = ref $caps ? $caps : undef; + if (! defined $caps) { $caps = 0; } + elsif ($u) { $caps = $u->{'caps'}; } + my $max = undef; + + # allow a way for admins to force-set the read-only cap + # to lower writes on a cluster. + if ($cname eq "readonly" && $u && + ($LJ::READONLY_CLUSTER{$u->{clusterid}} || + $LJ::READONLY_CLUSTER_ADVISORY{$u->{clusterid}} && + ! LJ::get_cap($u, "avoid_readonly"))) { + + # HACK for desperate moments. in when_needed mode, see if + # database is locky first + my $cid = $u->{clusterid}; + if ($LJ::READONLY_CLUSTER_ADVISORY{$cid} eq "when_needed") { + my $now = time(); + return 1 if $LJ::LOCKY_CACHE{$cid} > $now - 15; + + my $dbcm = LJ::get_cluster_master($u->{clusterid}); + return 1 unless $dbcm; + my $sth = $dbcm->prepare("SHOW PROCESSLIST"); + $sth->execute; + return 1 if $dbcm->err; + my $busy = 0; + my $too_busy = $LJ::WHEN_NEEDED_THRES || 300; + while (my $r = $sth->fetchrow_hashref) { + $busy++ if $r->{Command} ne "Sleep"; + } + if ($busy > $too_busy) { + $LJ::LOCKY_CACHE{$cid} = $now; + return 1; + } + } else { + return 1; + } + } + + # underage/coppa check etc + if ($cname eq "underage" && $u && + ($LJ::UNDERAGE_BIT && + $caps & 1 << $LJ::UNDERAGE_BIT)) { + return 1; + } + + # is there a hook for this cap name? + if (LJ::are_hooks("check_cap_$cname")) { + die "Hook 'check_cap_$cname' requires full user object" + unless defined $u; + + my $val = LJ::run_hook("check_cap_$cname", $u); + return $val if defined $val; + + # otherwise fall back to standard means + } + + # otherwise check via other means + foreach my $bit (keys %LJ::CAP) { + next unless ($caps & (1 << $bit)); + my $v = $LJ::CAP{$bit}->{$cname}; + next unless (defined $v); + next if (defined $max && $max > $v); + $max = $v; + } + return defined $max ? $max : $LJ::CAP_DEF{$cname}; +} + +# +# name: LJ::get_cap_min +# des: Just like [func[LJ::get_cap]], but returns the minimum value. +# Although it might not make sense at first, some things are +# better when they're low, like the minimum amount of time +# a user might have to wait between getting updates or being +# allowed to refresh a page. +# args: u_cap, capname +# des-u_cap: 16 bit capability bitmask or a user object from which the +# bitmask could be obtained +# des-capname: the name of a limit, defined in doc/capabilities.txt +# +sub get_cap_min +{ + my $caps = shift; # capability bitmask (16 bits), or user object + my $cname = shift; # capability name + if (! defined $caps) { $caps = 0; } + elsif (isu($caps)) { $caps = $caps->{'caps'}; } + my $min = undef; + foreach my $bit (keys %LJ::CAP) { + next unless ($caps & (1 << $bit)); + my $v = $LJ::CAP{$bit}->{$cname}; + next unless (defined $v); + next if (defined $min && $min < $v); + $min = $v; + } + return defined $min ? $min : $LJ::CAP_DEF{$cname}; +} + +# +# name: LJ::are_hooks +# des: Returns true if the site has one or more hooks installed for +# the given hookname. +# args: hookname +# +sub are_hooks +{ + my $hookname = shift; + return defined $LJ::HOOKS{$hookname}; +} + +# +# name: LJ::clear_hooks +# des: Removes all hooks. +# +sub clear_hooks +{ + %LJ::HOOKS = (); +} + +# +# name: LJ::run_hooks +# des: Runs all the site-specific hooks of the given name. +# returns: list of arrayrefs, one for each hook ran, their +# contents being their own return values. +# args: hookname, args* +# des-args: Arguments to be passed to hook. +# +sub run_hooks +{ + my ($hookname, @args) = @_; + my @ret; + foreach my $hook (@{$LJ::HOOKS{$hookname} || []}) { + push @ret, [ $hook->(@args) ]; + } + return @ret; +} + +# +# name: LJ::run_hook +# des: Runs single site-specific hook of the given name. +# returns: return value from hook +# args: hookname, args* +# des-args: Arguments to be passed to hook. +# +sub run_hook +{ + my ($hookname, @args) = @_; + return undef unless @{$LJ::HOOKS{$hookname} || []}; + return $LJ::HOOKS{$hookname}->[0]->(@args); + return undef; +} + +# +# name: LJ::register_hook +# des: Installs a site-specific hook. +# info: Installing multiple hooks per hookname is valid. +# They're run later in the order they're registered. +# args: hookname, subref +# des-subref: Subroutine reference to run later. +# +sub register_hook +{ + my $hookname = shift; + my $subref = shift; + push @{$LJ::HOOKS{$hookname}}, $subref; +} + +# +# name: LJ::register_setter +# des: Installs code to run for the "set" command in the console. +# info: Setters can be general or site-specific. +# args: key, subref +# des-key: Key to set. +# des-subref: Subroutine reference to run later. +# +sub register_setter +{ + my $key = shift; + my $subref = shift; + $LJ::SETTER{$key} = $subref; +} + +register_setter('synlevel', sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^(title|summary|full)$/) { + $$err = "Illegal value. Must be 'title', 'summary', or 'full'"; + return 0; + } + + LJ::set_userprop($u, 'opt_synlevel', $value); + return 1; +}); + +register_setter("newpost_minsecurity", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^(public|friends|private)$/) { + $$err = "Illegal value. Must be 'public', 'friends', or 'private'"; + return 0; + } + # Don't let commmunities be private + if ($u->{'journaltype'} eq "C" && $value eq "private") { + $$err = "newpost_minsecurity cannot be private for communities"; + return 0; + } + $value = "" if $value eq "public"; + LJ::set_userprop($u, "newpost_minsecurity", $value); + return 1; +}); + +register_setter("stylesys", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^[sS]?(1|2)$/) { + $$err = "Illegal value. Must be S1 or S2."; + return 0; + } + $value = $1 + 0; + LJ::set_userprop($u, "stylesys", $value); + return 1; +}); + +register_setter("maximagesize", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ m/^(\d+)[x,|](\d+)$/) { + $$err = "Illegal value. Must be width,height."; + return 0; + } + $value = "$1|$2"; + LJ::set_userprop($u, "opt_imagelinks", $value); + return 1; +}); + +register_setter("opt_ljcut_disable_lastn", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^(0|1)$/) { + $$err = "Illegal value. Must be '0' or '1'"; + return 0; + } + LJ:set_userprop($u, "opt_ljcut_disable_lastn", $value); + return 1; +}); + +register_setter("opt_ljcut_disable_friends", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^(0|1)$/) { + $$err = "Illegal value. Must be '0' or '1'"; + return 0; + } + LJ:set_userprop($u, "opt_ljcut_disable_friends", $value); + return 1; +}); + +register_setter("disable_quickreply", sub { + my ($dba, $u, $remote, $key, $value, $err) = @_; + unless ($value =~ /^(0|1)$/) { + $$err = "Illegal value. Must be '0' or '1'"; + return 0; + } + LJ:set_userprop($u, "opt_no_quickreply", $value); + return 1; +}); + +# +# name: LJ::make_auth_code +# des: Makes a random string of characters of a given length. +# returns: string of random characters, from an alphabet of 30 +# letters & numbers which aren't easily confused. +# args: length +# des-length: length of auth code to return +# +sub make_auth_code +{ + my $length = shift; + my $digits = "abcdefghjkmnpqrstvwxyz23456789"; + my $auth; + for (1..$length) { $auth .= substr($digits, int(rand(30)), 1); } + return $auth; +} + +# +# name: LJ::acid_encode +# des: Given a decimal number, returns base 30 encoding +# using an alphabet of letters & numbers that are +# not easily mistaken for each other. +# returns: Base 30 encoding, alwyas 7 characters long. +# args: number +# des-number: Number to encode in base 30. +# +sub acid_encode +{ + my $num = shift; + my $acid = ""; + my $digits = "abcdefghjkmnpqrstvwxyz23456789"; + while ($num) { + my $dig = $num % 30; + $acid = substr($digits, $dig, 1) . $acid; + $num = ($num - $dig) / 30; + } + return ("a"x(7-length($acid)) . $acid); +} + +# +# name: LJ::acid_decode +# des: Given an acid encoding from [func[LJ::acid_encode]], +# returns the original decimal number. +# returns: Integer. +# args: acid +# des-acid: base 30 number from [func[LJ::acid_encode]]. +# +sub acid_decode +{ + my $acid = shift; + $acid = lc($acid); + my %val; + my $digits = "abcdefghjkmnpqrstvwxyz23456789"; + for (0..30) { $val{substr($digits,$_,1)} = $_; } + my $num = 0; + my $place = 0; + while ($acid) { + return 0 unless ($acid =~ s/[$digits]$//o); + $num += $val{$&} * (30 ** $place++); + } + return $num; +} + +# +# name: LJ::acct_code_generate +# des: Creates invitation code(s) from an optional userid +# for use by anybody. +# returns: Code generated (if quantity 1), +# number of codes generated (if quantity>1), +# or undef on failure. +# args: dbarg?, userid?, quantity? +# des-userid: Userid to make the invitation code from, +# else the code will be from userid 0 (system) +# des-quantity: Number of codes to generate (default 1) +# +sub acct_code_generate +{ + &nodb; + my $userid = int(shift); + my $quantity = shift || 1; + + my $dbh = LJ::get_db_writer(); + + my @authcodes = map {LJ::make_auth_code(5)} 1..$quantity; + my @values = map {"(NULL, $userid, 0, '$_')"} @authcodes; + my $sql = "INSERT INTO acctcode (acid, userid, rcptid, auth) " + . "VALUES " . join(",", @values); + my $num_rows = $dbh->do($sql) or return undef; + + if ($quantity == 1) { + my $acid = $dbh->{'mysql_insertid'} or return undef; + return acct_code_encode($acid, $authcodes[0]); + } else { + return $num_rows; + } +} + +# +# name: LJ::acct_code_encode +# des: Given an account ID integer and a 5 digit auth code, returns +# a 12 digit account code. +# returns: 12 digit account code. +# args: acid, auth +# des-acid: account ID, a 4 byte unsigned integer +# des-auth: 5 random characters from base 30 alphabet. +# +sub acct_code_encode +{ + my $acid = shift; + my $auth = shift; + return lc($auth) . acid_encode($acid); +} + +# +# name: LJ::acct_code_decode +# des: Breaks an account code down into its two parts +# returns: list of (account ID, auth code) +# args: code +# des-code: 12 digit account code +# +sub acct_code_decode +{ + my $code = shift; + return (acid_decode(substr($code, 5, 7)), lc(substr($code, 0, 5))); +} + +# +# name: LJ::acct_code_check +# des: Checks the validity of a given account code +# returns: boolean; 0 on failure, 1 on validity. sets $$err on failure. +# args: dbarg?, code, err?, userid? +# des-code: account code to check +# des-err: optional scalar ref to put error message into on failure +# des-userid: optional userid which is allowed in the rcptid field, +# to allow for htdocs/create.bml case when people double +# click the submit button. +# +sub acct_code_check +{ + &nodb; + my $code = shift; + my $err = shift; # optional; scalar ref + my $userid = shift; # optional; acceptable userid (double-click proof) + + my $dbh = LJ::get_db_writer(); + + unless (length($code) == 12) { + $$err = "Malformed code; not 12 characters."; + return 0; + } + + my ($acid, $auth) = acct_code_decode($code); + + my $ac = $dbh->selectrow_hashref("SELECT userid, rcptid, auth ". + "FROM acctcode WHERE acid=?", + undef, $acid); + + unless ($ac && $ac->{'auth'} eq $auth) { + $$err = "Invalid account code."; + return 0; + } + + if ($ac->{'rcptid'} && $ac->{'rcptid'} != $userid) { + $$err = "This code has already been used: $code"; + return 0; + } + + # is the journal this code came from suspended? + my $u = LJ::load_userid($ac->{'userid'}); + if ($u && $u->{'statusvis'} eq "S") { + $$err = "Code belongs to a suspended account."; + return 0; + } + + return 1; +} + +# +# name: LJ::load_mood_theme +# des: Loads and caches a mood theme, or returns immediately if already loaded. +# args: dbarg?, themeid +# des-themeid: the mood theme ID to load +# +sub load_mood_theme +{ + &nodb; + my $themeid = shift; + return if $LJ::CACHE_MOOD_THEME{$themeid}; + return unless $themeid; + + # check memcache + my $memkey = [$themeid, "moodthemedata:$themeid"]; + return if $LJ::CACHE_MOOD_THEME{$themeid} = LJ::MemCache::get($memkey) and + %{$LJ::CACHE_MOOD_THEME{$themeid} || {}}; + + # fall back to db + my $dbh = LJ::get_db_writer() + or return 0; + + $LJ::CACHE_MOOD_THEME{$themeid} = {}; + + my $sth = $dbh->prepare("SELECT moodid, picurl, width, height FROM moodthemedata WHERE moodthemeid=?"); + $sth->execute($themeid); + return 0 if $dbh->err; + + while (my ($id, $pic, $w, $h) = $sth->fetchrow_array) { + $LJ::CACHE_MOOD_THEME{$themeid}->{$id} = { 'pic' => $pic, 'w' => $w, 'h' => $h }; + } + + # set in memcache + LJ::MemCache::set($memkey, $LJ::CACHE_MOOD_THEME{$themeid}, 3600) + if %{$LJ::CACHE_MOOD_THEME{$themeid} || {}}; + + return 1; +} + +# +# name: LJ::load_props +# des: Loads and caches one or more of the various *proplist tables: +# logproplist, talkproplist, and userproplist, which describe +# the various meta-data that can be stored on log (journal) items, +# comments, and users, respectively. +# args: dbarg?, table* +# des-table: a list of tables' proplists to load. can be one of +# "log", "talk", "user", or "rate" +# +sub load_props +{ + my $dbarg = ref $_[0] ? shift : undef; + my @tables = @_; + my $dbr; + my %keyname = qw(log propid + talk tpropid + user upropid + rate rlid + ); + + foreach my $t (@tables) { + next unless defined $keyname{$t}; + next if defined $LJ::CACHE_PROP{$t}; + my $tablename = $t eq "rate" ? "ratelist" : "${t}proplist"; + $dbr ||= LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT * FROM $tablename"); + $sth->execute; + while (my $p = $sth->fetchrow_hashref) { + $p->{'id'} = $p->{$keyname{$t}}; + $LJ::CACHE_PROP{$t}->{$p->{'name'}} = $p; + $LJ::CACHE_PROPID{$t}->{$p->{'id'}} = $p; + } + } +} + +# +# name: LJ::get_prop +# des: This is used to retrieve +# a hashref of a row from the given tablename's proplist table. +# One difference from getting it straight from the database is +# that the 'id' key is always present, as a copy of the real +# proplist unique id for that table. +# args: table, name +# returns: hashref of proplist row from db +# des-table: the tables to get a proplist hashref from. can be one of +# "log", "talk", or "user". +# des-name: the name of the prop to get the hashref of. +# +sub get_prop +{ + my $table = shift; + my $name = shift; + unless (defined $LJ::CACHE_PROP{$table}) { + LJ::load_props($table); + return undef unless $LJ::CACHE_PROP{$table}; + } + return $LJ::CACHE_PROP{$table}->{$name}; +} + +# +# name: LJ::load_codes +# des: Populates hashrefs with lookup data from the database or from memory, +# if already loaded in the past. Examples of such lookup data include +# state codes, country codes, color name/value mappings, etc. +# args: dbarg?, whatwhere +# des-whatwhere: a hashref with keys being the code types you want to load +# and their associated values being hashrefs to where you +# want that data to be populated. +# +sub load_codes +{ + &nodb; + my $req = shift; + + my $dbr = LJ::get_db_reader(); + + foreach my $type (keys %{$req}) + { + my $memkey = "load_codes:$type"; + unless ($LJ::CACHE_CODES{$type} ||= LJ::MemCache::get($memkey)) + { + $LJ::CACHE_CODES{$type} = []; + my $sth = $dbr->prepare("SELECT code, item, sortorder FROM codes WHERE type=?"); + $sth->execute($type); + while (my ($code, $item, $sortorder) = $sth->fetchrow_array) + { + push @{$LJ::CACHE_CODES{$type}}, [ $code, $item, $sortorder ]; + } + @{$LJ::CACHE_CODES{$type}} = + sort { $a->[2] <=> $b->[2] } @{$LJ::CACHE_CODES{$type}}; + LJ::MemCache::set($memkey, $LJ::CACHE_CODES{$type}, 60*15); + } + + foreach my $it (@{$LJ::CACHE_CODES{$type}}) + { + if (ref $req->{$type} eq "HASH") { + $req->{$type}->{$it->[0]} = $it->[1]; + } elsif (ref $req->{$type} eq "ARRAY") { + push @{$req->{$type}}, { 'code' => $it->[0], 'item' => $it->[1] }; + } + } + } +} + +# +# name: LJ::load_user_props +# des: Given a user hashref, loads the values of the given named properties +# into that user hashref. +# args: dbarg?, u, opts?, propname* +# des-opts: hashref of opts. set key 'cache' to use memcache. +# des-propname: the name of a property from the userproplist table. +# +sub load_user_props +{ + &nodb; + + my $u = shift; + return unless isu($u); + return if $u->{'statusvis'} eq "X"; + + my $opts = ref $_[0] ? shift : {}; + my (@props) = @_; + + my ($sql, $sth); + LJ::load_props("user"); + + ## user reference + my $uid = $u->{'userid'}+0; + $uid = LJ::get_userid($u->{'user'}) unless $uid; + + my $mem = {}; + my $use_master = 0; + my $used_slave = 0; # set later if we ended up using a slave + + if (@LJ::MEMCACHE_SERVERS) { + my @keys; + foreach (@props) { + next if exists $u->{$_}; + my $p = LJ::get_prop("user", $_); + die "Invalid userprop $_ passed to LJ::load_user_props." unless $p; + push @keys, [$uid,"uprop:$uid:$p->{'id'}"]; + } + $mem = LJ::MemCache::get_multi(@keys) || {}; + $use_master = 1; + } + + $use_master = 1 if $opts->{'use_master'}; + + my @needwrite; # [propid, propname] entries we need to save to memcache later + + my %loadfrom; + my %multihomed; # ( $propid => 0/1 ) # 0 if we haven't loaded it, 1 if we have + unless (@props) { + # case 1: load all props for a given user. + # multihomed props are stored on userprop and userproplite2, but since they + # should always be in sync, it doesn't matter which gets loaded first, the + # net results should be the same. see doc/designnotes/multihomed_props.txt + # for more information. + $loadfrom{'userprop'} = 1; + $loadfrom{'userproplite'} = 1; + $loadfrom{'userproplite2'} = 1; + $loadfrom{'userpropblob'} = 1; + } else { + # case 2: load only certain things + foreach (@props) { + next if exists $u->{$_}; + my $p = LJ::get_prop("user", $_); + die "Invalid userprop $_ passed to LJ::load_user_props." unless $p; + if (defined $mem->{"uprop:$uid:$p->{'id'}"}) { + $u->{$_} = $mem->{"uprop:$uid:$p->{'id'}"}; + next; + } + push @needwrite, [ $p->{'id'}, $_ ]; + my $source = $p->{'indexed'} ? "userprop" : "userproplite"; + if ($p->{datatype} eq 'blobchar') { + $source = "userpropblob"; # clustered blob + } + elsif ($p->{'cldversion'} && $u->{'dversion'} >= $p->{'cldversion'}) { + $source = "userproplite2"; # clustered + } + elsif ($p->{multihomed}) { + $multihomed{$p->{id}} = 0; + $source = "userproplite2"; + } + push @{$loadfrom{$source}}, $p->{'id'}; + } + } + + foreach my $table (qw{userproplite userproplite2 userpropblob userprop}) { + next unless exists $loadfrom{$table}; + my $db; + if ($use_master) { + $db = ($table =~ m{userprop(lite2|blob)}) ? + LJ::get_cluster_master($u) : + LJ::get_db_writer(); + } + unless ($db) { + $db = ($table =~ m{userprop(lite2|blob)}) ? + LJ::get_cluster_reader($u) : + LJ::get_db_reader(); + $used_slave = 1; + } + $sql = "SELECT upropid, value FROM $table WHERE userid=$uid"; + if (ref $loadfrom{$table}) { + $sql .= " AND upropid IN (" . join(",", @{$loadfrom{$table}}) . ")"; + } + $sth = $db->prepare($sql); + $sth->execute; + while (my ($id, $v) = $sth->fetchrow_array) { + delete $multihomed{$id} if $table eq 'userproplite2'; + $u->{$LJ::CACHE_PROPID{'user'}->{$id}->{'name'}} = $v; + } + + # push back multihomed if necessary + if ($table eq 'userproplite2') { + push @{$loadfrom{userprop}}, $_ foreach keys %multihomed; + } + } + + # see if we failed to get anything above and need to hit the master. + # this usually happens the first time a multihomed prop is hit. this + # code will propogate that prop down to the cluster. + if (%multihomed) { + + # verify that we got the database handle before we try propogating data + if ($u->writer) { + my @values; + foreach my $id (keys %multihomed) { + my $pname = $LJ::CACHE_PROPID{user}{$id}{name}; + if (defined $u->{$pname} && $u->{$pname}) { + push @values, "($uid, $id, " . $u->quote($u->{$pname}) . ")"; + } else { + push @values, "($uid, $id, '')"; + } + } + $u->do("REPLACE INTO userproplite2 VALUES " . join ',', @values); + } + } + + # Add defaults to user object. + + # defaults for S1 style IDs in config file are magic: really + # uniq strings representing style IDs, so on first use, we need + # to map them + unless ($LJ::CACHED_S1IDMAP) { + + my $pubsty = LJ::S1::get_public_styles(); + foreach (values %$pubsty) { + my $k = "s1_$_->{'type'}_style"; + next unless $LJ::USERPROP_DEF{$k} eq "$_->{'type'}/$_->{'styledes'}"; + + $LJ::USERPROP_DEF{$k} = $_->{'styleid'}; + } + + $LJ::CACHED_S1IDMAP = 1; + } + + # If this was called with no @props, then the function tried + # to load all metadata. but we don't know what's missing, so + # try to apply all defaults. + unless (@props) { @props = keys %LJ::USERPROP_DEF; } + + foreach my $prop (@props) { + next if (defined $u->{$prop}); + $u->{$prop} = $LJ::USERPROP_DEF{$prop}; + } + + unless ($used_slave) { + my $expire = time() + 3600*24; + foreach my $wr (@needwrite) { + my ($id, $name) = ($wr->[0], $wr->[1]); + LJ::MemCache::set([$uid,"uprop:$uid:$id"], $u->{$name} || "", $expire); + } + } +} + +# +# name: LJ::debug +# des: When $LJ::DEBUG is set, logs the given message to +# the Apache error log. Or, if $LJ::DEBUG is 2, then +# prints to STDOUT. +# returns: 1 if logging disabled, 0 on failure to open log, 1 otherwise +# args: message +# des-message: Message to log. +# +sub debug +{ + return 1 unless ($LJ::DEBUG); + if ($LJ::DEBUG == 2) { + print $_[0], "\n"; + return 1; + } + my $r = Apache->request; + return 0 unless $r; + $r->log_error($_[0]); + return 1; +} + +# +# name: LJ::auth_okay +# des: Validates a user's password. The "clear" or "md5" argument +# must be present, and either the "actual" argument (the correct +# password) must be set, or the first argument must be a user +# object ($u) with the 'password' key set. Note that this is +# the preferred way to validate a password (as opposed to doing +# it by hand) since this function will use a pluggable authenticator +# if one is defined, so LiveJournal installations can be based +# off an LDAP server, for example. +# returns: boolean; 1 if authentication succeeded, 0 on failure +# args: u, clear, md5, actual?, ip_banned? +# des-clear: Clear text password the client is sending. (need this or md5) +# des-md5: MD5 of the password the client is sending. (need this or clear). +# If this value instead of clear, clear can be anything, as md5 +# validation will take precedence. +# des-actual: The actual password for the user. Ignored if a pluggable +# authenticator is being used. Required unless the first +# argument is a user object instead of a username scalar. +# des-ip_banned: Optional scalar ref which this function will set to true +# if IP address of remote user is banned. +# +sub auth_okay +{ + my $u = shift; + my $clear = shift; + my $md5 = shift; + my $actual = shift; + my $ip_banned = shift; + return 0 unless isu($u); + + $actual ||= $u->{'password'}; + + my $user = $u->{'user'}; + + # set the IP banned flag, if it was provided. + my $fake_scalar; + my $ref = ref $ip_banned ? $ip_banned : \$fake_scalar; + if (LJ::login_ip_banned($u)) { + $$ref = 1; + return 0; + } else { + $$ref = 0; + } + + my $bad_login = sub { + LJ::handle_bad_login($u); + return 0; + }; + + # setup this auth checker for LDAP + if ($LJ::LDAP_HOST && ! $LJ::AUTH_CHECK) { + require LJ::LDAP; + $LJ::AUTH_CHECK = sub { + my ($user, $try, $type) = @_; + die unless $type eq "clear"; + return LJ::LDAP::is_good_ldap($user, $try); + }; + } + + ## custom authorization: + if (ref $LJ::AUTH_CHECK eq "CODE") { + my $type = $md5 ? "md5" : "clear"; + my $try = $md5 || $clear; + my $good = $LJ::AUTH_CHECK->($user, $try, $type); + return $good || $bad_login->(); + } + + ## LJ default authorization: + return 0 unless $actual; + return 1 if ($md5 && lc($md5) eq LJ::hash_password($actual)); + return 1 if ($clear eq $actual); + return $bad_login->(); +} + +# Implement Digest authentication per RFC2617 +# called with Apache's request oject +# modifies outgoing header fields appropriately and returns +# 1/0 according to whether auth succeeded. If succeeded, also +# calls LJ::set_remote() to set up internal LJ auth. +# this routine should be called whenever it's clear the client +# wants/the server demands digest auth, and if it returns 1, +# things proceed as usual; if it returns 0, the caller should +# $r->send_http_header(), output an auth error message in HTTP +# data and return to apache. +# Note: Authentication-Info: not sent (optional and nobody supports +# it anyway). Instead, server nonces are reused within their timeout +# limits and nonce counts are used to prevent replay attacks. + +sub auth_digest { + my ($r) = @_; + + my $decline = sub { + my $stale = shift; + + my $nonce = LJ::challenge_generate(180); # 3 mins timeout + my $authline = "Digest realm=\"lj\", nonce=\"$nonce\", algorithm=MD5, qop=\"auth\""; + $authline .= ", stale=\"true\"" if $stale; + $r->header_out("WWW-Authenticate", $authline); + $r->status_line("401 Authentication required"); + return 0; + }; + + unless ($r->header_in("Authorization")) { + return $decline->(0); + } + + my $header = $r->header_in("Authorization"); + + # parse it + # TODO: could there be "," or " " inside attribute values, requiring + # trickier parsing? + + my @vals = split(/[, \s]/, $header); + my $authname = shift @vals; + my %attrs; + foreach (@vals) { + if (/^(\S*?)=(\S*)$/) { + my ($attr, $value) = ($1,$2); + if ($value =~ m/^\"([^\"]*)\"$/) { + $value = $1; + } + $attrs{$attr} = $value; + } + } + + # sanity checks + unless ($authname eq 'Digest' && $attrs{'qop'} eq 'auth' && + $attrs{'realm'} eq 'lj' && $attrs{'algorithm'} eq 'MD5') { + return $decline->(0); + } + + my %opts; + LJ::challenge_check($attrs{'nonce'}, \%opts); + + return $decline->(0) unless $opts{'valid'}; + + # if the nonce expired, force a new one + return $decline->(1) if $opts{'expired'}; + + # check the nonce count + # be lenient, allowing for error of magnitude 1 (Mozilla has a bug, + # it repeats nc=00000001 twice...) + # in case the count is off, force a new nonce; if a client's + # nonce count implementation is broken and it doesn't send nc= or + # always sends 1, this'll at least work due to leniency above + + my $ncount = hex($attrs{'nc'}); + + unless (abs($opts{'count'} - $ncount) <= 1) { + return $decline->(1); + } + + # the username + my $user = LJ::canonical_username($attrs{'username'}); + my $u = LJ::load_user($user); + + return $decline->(0) unless $u; + + # don't allow empty passwords + + return $decline->(0) unless $u->{'password'}; + + # recalculate the hash and compare to response + + my $a1src="$u->{'user'}:lj:$u->{'password'}"; + my $a1 = Digest::MD5::md5_hex($a1src); + my $a2src = $r->method . ":$attrs{'uri'}"; + my $a2 = Digest::MD5::md5_hex($a2src); + my $hashsrc = "$a1:$attrs{'nonce'}:$attrs{'nc'}:$attrs{'cnonce'}:$attrs{'qop'}:$a2"; + my $hash = Digest::MD5::md5_hex($hashsrc); + + return $decline->(0) + unless $hash eq $attrs{'response'}; + + # set the remote + LJ::set_remote($u); + + return $u; +} + + +# Create a challenge token for secure logins +sub challenge_generate +{ + my ($goodfor, $attr) = @_; + + $goodfor ||= 60; + $attr ||= LJ::rand_chars(20); + + my ($stime, $secret) = LJ::get_secret(); + + # challenge version, secret time, secret age, time in secs token is good for, random chars. + my $s_age = time() - $stime; + my $chalbare = "c0:$stime:$s_age:$goodfor:$attr"; + my $chalsig = Digest::MD5::md5_hex($chalbare . $secret); + my $chal = "$chalbare:$chalsig"; + + return $chal; +} + +# Return challenge info. +# This could grow later - for now just return the rand chars used. +sub get_challenge_attributes +{ + return (split /:/, shift)[4]; +} + +# Validate a challenge string previously supplied by challenge_generate +# return 1 "good" 0 "bad", plus sets keys in $opts: +# 'valid'=1/0 whether the string itself was valid +# 'expired'=1/0 whether the challenge expired, provided it's valid +# 'count'=N number of times we've seen this challenge, including this one, +# provided it's valid and not expired +# $opts also supports in parameters: +# 'dont_check_count' => if true, won't return a count field +# the return value is 1 if 'valid' and not 'expired' and 'count'==1 +sub challenge_check { + my ($chal, $opts) = @_; + my ($valid, $expired, $count) = (1, 0, 0); + + my ($c_ver, $stime, $s_age, $goodfor, $rand, $chalsig) = split /:/, $chal; + my $secret = LJ::get_secret($stime); + my $chalbare = "$c_ver:$stime:$s_age:$goodfor:$rand"; + + # Validate token + $valid = 0 + unless $secret && $c_ver eq 'c0'; # wrong version + $valid = 0 + unless Digest::MD5::md5_hex($chalbare . $secret) eq $chalsig; + + $expired = 1 + unless (not $valid) or time() - ($stime + $s_age) < $goodfor; + + # Check for token dups + if ($valid && !$expired && !$opts->{dont_check_count}) { + if (@LJ::MEMCACHE_SERVERS) { + $count = LJ::MemCache::incr("chaltoken:$chal", 1); + unless ($count) { + LJ::MemCache::add("chaltoken:$chal", 1, $goodfor); + $count = 1; + } + } else { + my $dbh = LJ::get_db_writer(); + my $rv = $dbh->do("SELECT GET_LOCK(?,5)", undef, $chal); + if ($rv) { + $count = $dbh->selectrow_array("SELECT count FROM challenges WHERE challenge=?", + undef, $chal); + if ($count) { + $dbh->do("UPDATE challenges SET count=count+1 WHERE challenge=?", + undef, $chal); + $count++; + } else { + $dbh->do("INSERT INTO challenges SET ctime=?, challenge=?, count=1", + undef, $stime + $s_age, $chal); + $count = 1; + } + } + $dbh->do("SELECT RELEASE_LOCK(?)", undef, $chal); + } + # if we couldn't get the count (means we couldn't store either) + # , consider it invalid + $valid = 0 unless $count; + } + + if ($opts) { + $opts->{'expired'} = $expired; + $opts->{'valid'} = $valid; + $opts->{'count'} = $count; + } + + return ($valid && !$expired && ($count==1 || $opts->{dont_check_count})); +} + + +# Validate login/talk md5 responses. +# Return 1 on valid, 0 on invalid. +sub challenge_check_login +{ + my ($u, $chal, $res, $banned, $opts) = @_; + return 0 unless $u; + my $pass = $u->{'password'}; + return 0 if $pass eq ""; + + # set the IP banned flag, if it was provided. + my $fake_scalar; + my $ref = ref $banned ? $banned : \$fake_scalar; + if (LJ::login_ip_banned($u)) { + $$ref = 1; + return 0; + } else { + $$ref = 0; + } + + # check the challenge string validity + return 0 unless LJ::challenge_check($chal, $opts); + + # Validate password + my $hashed = Digest::MD5::md5_hex($chal . Digest::MD5::md5_hex($pass)); + if ($hashed eq $res) { + return 1; + } else { + LJ::handle_bad_login($u); + return 0; + } +} + +# create externally mapped user. +# return uid of LJ user on success, undef on error. +# opts = { +# extuser or extuserid (or both, but one is required.), +# caps +# } +# opts also can contain any additional options that create_account takes. (caps?) +sub create_extuser +{ + my ($type, $opts) = @_; + return undef unless $type && $LJ::EXTERNAL_NAMESPACE{$type}->{id}; + return undef unless ref $opts && + ($opts->{extuser} || defined $opts->{extuserid}); + + my $uid; + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + # make sure a mapping for this user doesn't already exist. + $uid = LJ::get_extuser_uid( $type, $opts, 'force' ); + return $uid if $uid; + + # increment ext_ counter until we successfully create an LJ account. + # hard cap it at 10 tries. (arbitrary, but we really shouldn't have *any* + # failures here, let alone 10 in a row.) + for (1..10) { + my $extuser = 'ext_' . LJ::alloc_global_counter( 'E' ); + $uid = + LJ::create_account( + { caps => $opts->{caps}, user => $extuser, name => $extuser } ); + last if $uid; + select undef, undef, undef, .10; # lets not thrash over this. + } + return undef unless $uid; + + # add extuser mapping. + my $sql = "INSERT INTO extuser SET userid=?, siteid=?"; + my @bind = ($uid, $LJ::EXTERNAL_NAMESPACE{$type}->{id}); + + if ($opts->{extuser}) { + $sql .= ", extuser=?"; + push @bind, $opts->{extuser}; + } + + if ($opts->{extuserid}) { + $sql .= ", extuserid=? "; + push @bind, $opts->{extuserid}+0; + } + + $dbh->do($sql, undef, @bind) or return undef; + return $uid; +} + +# given an extuserid or extuser, return the LJ uid. +# return undef if there is no mapping. +sub get_extuser_uid +{ + my ($type, $opts, $force) = @_; + return undef unless $type && $LJ::EXTERNAL_NAMESPACE{$type}->{id}; + return undef unless ref $opts && + ($opts->{extuser} || defined $opts->{extuserid}); + + my $dbh = $force ? LJ::get_db_writer() : LJ::get_db_reader(); + return undef unless $dbh; + + my $sql = "SELECT userid FROM extuser WHERE siteid=?"; + my @bind = ($LJ::EXTERNAL_NAMESPACE{$type}->{id}); + + if ($opts->{extuser}) { + $sql .= " AND extuser=?"; + push @bind, $opts->{extuser}; + } + + if ($opts->{extuserid}) { + $sql .= $opts->{extuser} ? ' OR ' : ' AND '; + $sql .= "extuserid=?"; + push @bind, $opts->{extuserid}+0; + } + + return $dbh->selectrow_array($sql, undef, @bind); +} + +# given a LJ userid/u, return a hashref of: +# type, extuser, extuserid +# returns undef if user isn't an externally mapped account. +sub get_extuser_map +{ + my $uid = LJ::want_userid(shift); + return undef unless $uid; + + my $dbr = LJ::get_db_reader(); + return undef unless $dbr; + + my $sql = "SELECT * FROM extuser WHERE userid=?"; + my $ret = $dbr->selectrow_hashref($sql, undef, $uid); + return undef unless $ret; + + my $type = 'unknown'; + foreach ( keys %LJ::EXTERNAL_NAMESPACE ) { + $type = $_ if $LJ::EXTERNAL_NAMESPACE{$_}->{id} == $ret->{siteid}; + } + + $ret->{type} = $type; + return $ret; +} + +# +# name: LJ::create_account +# des: Creates a new basic account. Note: This function is +# not really too useful but should be extended to be useful so +# htdocs/create.bml can use it, rather than doing the work itself. +# returns: integer of userid created, or 0 on failure. +# args: dbarg?, opts +# des-opts: hashref containing keys 'user', 'name', 'password', 'email', 'caps', 'journaltype' +# +sub create_account +{ + &nodb; + my $o = shift; + + my $user = LJ::canonical_username($o->{'user'}); + unless ($user) { + return 0; + } + + my $dbh = LJ::get_db_writer(); + my $quser = $dbh->quote($user); + my $cluster = defined $o->{'cluster'} ? $o->{'cluster'} : LJ::new_account_cluster(); + my $caps = $o->{'caps'} || $LJ::NEWUSER_CAPS; + my $journaltype = $o->{'journaltype'} || "P"; + + # new non-clustered accounts aren't supported anymore + return 0 unless $cluster; + + $dbh->do("INSERT INTO user (user, name, password, clusterid, dversion, caps, email, journaltype) ". + "VALUES ($quser, ?, ?, ?, $LJ::MAX_DVERSION, ?, ?, ?)", undef, + $o->{'name'}, $o->{'password'}, $cluster, $caps, $o->{'email'}, $journaltype); + return 0 if $dbh->err; + + my $userid = $dbh->{'mysql_insertid'}; + return 0 unless $userid; + + $dbh->do("INSERT INTO useridmap (userid, user) VALUES ($userid, $quser)"); + $dbh->do("INSERT INTO userusage (userid, timecreate) VALUES ($userid, NOW())"); + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + 'code' => undef, + }); + return $userid; +} + +# +# name: LJ::new_account_cluster +# des: Which cluster to put a new account on. $DEFAULT_CLUSTER if it's +# a scalar, random element from @$DEFAULT_CLUSTER if it's arrayref. +# also verifies that the database seems to be available. +# returns: clusterid where the new account should be created; 0 on error +# (such as no clusters available) +# +sub new_account_cluster +{ + # if it's not an arrayref, put it in an array ref so we can use it below + my $clusters = ref $LJ::DEFAULT_CLUSTER ? $LJ::DEFAULT_CLUSTER : [ $LJ::DEFAULT_CLUSTER+0 ]; + + # iterate through the new clusters from a random point + my $size = @$clusters; + my $start = int(rand() * $size); + foreach (1..$size) { + my $cid = $clusters->[$start++ % $size]; + + # verify that this cluster is in @LJ::CLUSTERS + my @check = grep { $_ == $cid } @LJ::CLUSTERS; + next unless scalar(@check) >= 1 && $check[0] == $cid; + + # try this cluster to see if we can use it, return if so + my $dbcm = LJ::get_cluster_master($cid); + return $cid if $dbcm; + } + + # if we get here, we found no clusters that were up... + return 0; +} + +# +# name: LJ::is_friend +# des: Checks to see if a user is a friend of another user. +# returns: boolean; 1 if user B is a friend of user A or if A == B +# args: usera, userb +# des-usera: Source user hashref or userid. +# des-userb: Destination user hashref or userid. (can be undef) +# +sub is_friend +{ + &nodb; + + my ($ua, $ub) = @_[0, 1]; + + $ua = LJ::want_userid($ua); + $ub = LJ::want_userid($ub); + + return 0 unless $ua && $ub; + return 1 if $ua == $ub; + + # get group mask from the first argument to the second argument and + # see if first bit is set. if it is, they're a friend. get_groupmask + # is memcached and used often, so it's likely to be available quickly. + return LJ::get_groupmask(@_[0, 1]) & 1; +} + +# +# name: LJ::is_banned +# des: Checks to see if a user is banned from a journal. +# returns: boolean; 1 iff "user" is banned from "journal" +# args: user, journal +# des-user: User hashref or userid. +# des-journal: Journal hashref or userid. +# +sub is_banned +{ + &nodb; + + # get user and journal ids + my $uid = LJ::want_userid(shift); + my $jid = LJ::want_userid(shift); + return 1 unless $uid && $jid; + + # for speed: common case is non-community posting and replies + # in own journal. avoid db hit. + return 0 if ($uid == $jid); + + # edge from journal -> user + return LJ::check_rel($jid, $uid, 'B'); +} + +# +# name: LJ::can_view +# des: Checks to see if the remote user can view a given journal entry. +# Note: This is meant for use on single entries at a time, +# not for calling many times on every entry in a journal. +# returns: boolean; 1 if remote user can see item +# args: remote, item +# des-item: Hashref from the 'log' table. +# +sub can_view +{ + &nodb; + my $remote = shift; + my $item = shift; + + # public is okay + return 1 if $item->{'security'} eq "public"; + + # must be logged in otherwise + return 0 unless $remote; + + my $userid = int($item->{'ownerid'} || $item->{'journalid'}); + my $remoteid = int($remote->{'userid'}); + + # owners can always see their own. + return 1 if ($userid == $remoteid); + + # other people can't read private + return 0 if ($item->{'security'} eq "private"); + + # should be 'usemask' security from here out, otherwise + # assume it's something new and return 0 + return 0 unless ($item->{'security'} eq "usemask"); + + # if it's usemask, we have to refuse non-personal journals, + # so we have to load the user + return 0 unless $remote->{'journaltype'} eq 'P'; + + # TAG:FR:ljlib:can_view (turn off bit 0 for just watching? hmm.) + my $gmask = LJ::get_groupmask($userid, $remoteid); + my $allowed = (int($gmask) & int($item->{'allowmask'})); + return $allowed ? 1 : 0; # no need to return matching mask +} + +# +# name: LJ::wipe_major_memcache +# des: invalidate all major memcache items associated with a given user +# args: u +# returns: nothing +# +sub wipe_major_memcache +{ + my $u = shift; + my $userid = LJ::want_userid($u); + foreach my $key ("userid","bio","talk2ct","talkleftct","log2ct", + "log2lt","memkwid","dayct","s1overr","s1uc","fgrp", + "friends","friendofs","tu","upicinf","upiccom", + "upicurl", "intids", "memct", "lastcomm") + { + LJ::memcache_kill($userid, $key); + } +} + +# +# name: LJ::get_logtext2 +# des: Efficiently retrieves a large number of journal entry text, trying first +# slave database servers for recent items, then the master in +# cases of old items the slaves have already disposed of. See also: +# [func[LJ::get_talktext2]]. +# args: u, opts?, jitemid* +# returns: hashref with keys being jitemids, values being [ $subject, $body ] +# des-opts: Optional hashref of special options. Currently only 'usemaster' +# key is supported, which always returns a definitive copy, +# and not from a cache or slave database. +# des-jitemid: List of jitemids to retrieve the subject & text for. +# +sub get_logtext2 +{ + my $u = shift; + my $clusterid = $u->{'clusterid'}; + my $journalid = $u->{'userid'}+0; + + my $opts = ref $_[0] ? shift : {}; + + # return structure. + my $lt = {}; + return $lt unless $clusterid; + + # keep track of itemids we still need to load. + my %need; + my @mem_keys; + foreach (@_) { + my $id = $_+0; + $need{$id} = 1; + push @mem_keys, [$journalid,"logtext:$clusterid:$journalid:$id"]; + } + + # pass 0: memory, avoiding databases + unless ($opts->{'usemaster'}) { + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $v; + $k =~ /:(\d+):(\d+):(\d+)/; + delete $need{$3}; + $lt->{$3} = $v; + } + } + + return $lt unless %need; + + # pass 1 (slave) and pass 2 (master) + foreach my $pass (1, 2) { + next unless %need; + next if $pass == 1 && $opts->{'usemaster'}; + my $db = $pass == 1 ? LJ::get_cluster_reader($clusterid) : + LJ::get_cluster_def_reader($clusterid); + next unless $db; + + my $jitemid_in = join(", ", keys %need); + my $sth = $db->prepare("SELECT jitemid, subject, event FROM logtext2 ". + "WHERE journalid=$journalid AND jitemid IN ($jitemid_in)"); + $sth->execute; + while (my ($id, $subject, $event) = $sth->fetchrow_array) { + LJ::text_uncompress(\$event); + my $val = [ $subject, $event ]; + $lt->{$id} = $val; + LJ::MemCache::add([$journalid,"logtext:$clusterid:$journalid:$id"], $val); + delete $need{$id}; + } + } + return $lt; +} + +# +# name: LJ::get_talktext2 +# des: Retrieves comment text. Tries slave servers first, then master. +# info: Efficiently retreives batches of comment text. Will try alternate +# servers first. See also [func[LJ::get_logtext2]]. +# returns: Hashref with the talkids as keys, values being [ $subject, $event ]. +# args: u, opts?, jtalkids +# des-opts: A hashref of options. 'onlysubjects' will only retrieve subjects. +# des-jtalkids: A list of talkids to get text for. +# +sub get_talktext2 +{ + my $u = shift; + my $clusterid = $u->{'clusterid'}; + my $journalid = $u->{'userid'}+0; + + my $opts = ref $_[0] ? shift : {}; + + # return structure. + my $lt = {}; + return $lt unless $clusterid; + + # keep track of itemids we still need to load. + my %need; + my @mem_keys; + foreach (@_) { + my $id = $_+0; + $need{$id} = 1; + push @mem_keys, [$journalid,"talksubject:$clusterid:$journalid:$id"]; + unless ($opts->{'onlysubjects'}) { + push @mem_keys, [$journalid,"talkbody:$clusterid:$journalid:$id"]; + } + } + + # try the memory cache + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + $k =~ /^talk(.*):(\d+):(\d+):(\d+)/; + if ($opts->{'onlysubjects'} && $1 eq "subject") { + delete $need{$4}; + $lt->{$4} = [ $v ]; + } + if (! $opts->{'onlysubjects'} && $1 eq "body" && + exists $mem->{"talksubject:$2:$3:$4"}) { + delete $need{$4}; + $lt->{$4} = [ $mem->{"talksubject:$2:$3:$4"}, $v ]; + } + } + return $lt unless %need; + + my $bodycol = $opts->{'onlysubjects'} ? "" : ", body"; + + # pass 1 (slave) and pass 2 (master) + foreach my $pass (1, 2) { + next unless %need; + my $db = $pass == 1 ? LJ::get_cluster_reader($clusterid) : + LJ::get_cluster_def_reader($clusterid); + next unless $db; + my $in = join(",", keys %need); + my $sth = $db->prepare("SELECT jtalkid, subject $bodycol FROM talktext2 ". + "WHERE journalid=$journalid AND jtalkid IN ($in)"); + $sth->execute; + while (my ($id, $subject, $body) = $sth->fetchrow_array) { + LJ::text_uncompress(\$body); + $lt->{$id} = [ $subject, $body ]; + LJ::MemCache::add([$journalid,"talkbody:$clusterid:$journalid:$id"], $body) + unless $opts->{'onlysubjects'}; + LJ::MemCache::add([$journalid,"talksubject:$clusterid:$journalid:$id"], $subject); + delete $need{$id}; + } + } + return $lt; +} + +# +# name: LJ::get_logtext2multi +# des: Gets log text from clusters. +# info: Fetches log text from clusters. Trying slaves first if available. +# returns: hashref with keys being "jid jitemid", values being [ $subject, $body ] +# args: idsbyc +# des-idsbyc: A hashref where the key is the clusterid, and the data +# is an arrayref of [ ownerid, itemid ] array references. +# +sub get_logtext2multi +{ + &nodb; + return _get_posts_raw_wrapper(shift, "text"); +} + +# this function is used to translate the old get_logtext2multi and load_log_props2multi +# functions into using the new get_posts_raw. eventually, the above functions should +# be taken out of the rest of the code, at which point this function can also die. +sub _get_posts_raw_wrapper { + # args: + # { cid => [ [jid, jitemid]+ ] } + # "text" or "props" + # optional hashref to put return value in. (see get_logtext2multi docs) + # returns: that hashref. + my ($idsbyc, $type, $ret) = @_; + + my $opts = {}; + if ($type eq 'text') { + $opts->{text_only} = 1; + } elsif ($type eq 'prop') { + $opts->{prop_only} = 1; + } else { + return undef; + } + + my @postids; + while (my ($cid, $ids) = each %$idsbyc) { + foreach my $pair (@$ids) { + push @postids, [ $cid, $pair->[0], $pair->[1] ]; + } + } + my $rawposts = LJ::get_posts_raw($opts, @postids); + + # add replycounts fields to props + if ($type eq "prop") { + while (my ($k, $v) = each %{$rawposts->{"replycount"}||{}}) { + $rawposts->{prop}{$k}{replycount} = $rawposts->{replycount}{$k}; + } + } + + # translate colon-separated (new) to space-separated (old) keys. + $ret ||= {}; + while (my ($id, $data) = each %{$rawposts->{$type}}) { + $id =~ s/:/ /; + $ret->{$id} = $data; + } + return $ret; +} + +# +# name: LJ::get_posts_raw +# des: Gets raw post data (text and props) efficiently from clusters. +# info: Fetches posts from clusters, trying memcache and slaves first if available. +# returns: hashref with keys 'text', 'prop', or 'replycount', and values being +# hashrefs with keys "jid:jitemid". values of that are as follows: +# text: [ $subject, $body ], props: { ... }, and replycount: scalar +# args: opts?, id+ +# des-opts: An optional hashref of options: +# - memcache_only: Don't fall back on the database. +# - text_only: Retrieve only text, no props (used to support old API). +# - prop_only: Retrieve only props, no text (used to support old API). +# des-id: An arrayref of [ clusterid, ownerid, itemid ]. +# +sub get_posts_raw +{ + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $ret = {}; + my $sth; + + LJ::load_props('log') unless $opts->{text_only}; + + # throughout this function, the concept of an "id" + # is the key to identify a single post. + # it is of the form "$jid:$jitemid". + + # build up a list for each cluster of what we want to get, + # as well as a list of all the keys we want from memcache. + my %cids; # cid => 1 + my $needtext; # text needed: $cid => $id => 1 + my $needprop; # props needed: $cid => $id => 1 + my $needrc; # replycounts needed: $cid => $id => 1 + my @mem_keys; + + # if we're loading entries for a friends page, + # silently failing to load a cluster is acceptable. + # but for a single user, we want to die loudly so they don't think + # we just lost their journal. + my $single_user; + + # because the memcache keys for logprop don't contain + # which cluster they're in, we also need a map to get the + # cid back from the jid so we can insert into the needfoo hashes. + # the alternative is to not key the needfoo hashes on cluster, + # but that means we need to grep out each cluster's jids when + # we do per-cluster queries on the databases. + my %cidsbyjid; + foreach my $post (@_) { + my ($cid, $jid, $jitemid) = @{$post}; + my $id = "$jid:$jitemid"; + if (not defined $single_user) { + $single_user = $jid; + } elsif ($single_user and $jid != $single_user) { + # multiple users + $single_user = 0; + } + $cids{$cid} = 1; + $cidsbyjid{$jid} = $cid; + unless ($opts->{prop_only}) { + $needtext->{$cid}{$id} = 1; + push @mem_keys, [$jid,"logtext:$cid:$id"]; + } + unless ($opts->{text_only}) { + $needprop->{$cid}{$id} = 1; + push @mem_keys, [$jid,"logprop:$id"]; + $needrc->{$cid}{$id} = 1; + push @mem_keys, [$jid,"rp:$id"]; + } + } + + # first, check memcache. + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + next unless defined $v; + next unless $k =~ /(\w+):(?:\d+:)?(\d+):(\d+)/; + my ($type, $jid, $jitemid) = ($1, $2, $3); + my $cid = $cidsbyjid{$jid}; + my $id = "$jid:$jitemid"; + if ($type eq "logtext") { + delete $needtext->{$cid}{$id}; + $ret->{text}{$id} = $v; + } elsif ($type eq "logprop" && ref $v eq "HASH") { + delete $needprop->{$cid}{$id}; + $ret->{prop}{$id} = $v; + } elsif ($type eq "rp") { + delete $needrc->{$cid}{$id}; + $ret->{replycount}{$id} = int($v); # remove possible spaces + } + } + + # we may be done already. + return $ret if $opts->{memcache_only}; + return $ret unless values %$needtext or values %$needprop + or values %$needrc; + + # otherwise, hit the database. + foreach my $cid (keys %cids) { + # for each cluster, get the text/props we need from it. + my $cneedtext = $needtext->{$cid} || {}; + my $cneedprop = $needprop->{$cid} || {}; + my $cneedrc = $needrc->{$cid} || {}; + + next unless %$cneedtext or %$cneedprop or %$cneedrc; + + my $make_in = sub { + my @in; + foreach my $id (@_) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + push @in, "(journalid=$jid AND jitemid=$jitemid)"; + } + return join(" OR ", @in); + }; + + # now load from each cluster. + my $fetchtext = sub { + my $db = shift; + return unless %$cneedtext; + my $in = $make_in->(keys %$cneedtext); + $sth = $db->prepare("SELECT journalid, jitemid, subject, event ". + "FROM logtext2 WHERE $in"); + $sth->execute; + while (my ($jid, $jitemid, $subject, $event) = $sth->fetchrow_array) { + LJ::text_uncompress(\$event); + my $id = "$jid:$jitemid"; + my $val = [ $subject, $event ]; + $ret->{text}{$id} = $val; + LJ::MemCache::add([$jid,"logtext:$cid:$id"], $val); + delete $cneedtext->{$id}; + } + }; + + my $fetchprop = sub { + my $db = shift; + return unless %$cneedprop; + my $in = $make_in->(keys %$cneedprop); + $sth = $db->prepare("SELECT journalid, jitemid, propid, value ". + "FROM logprop2 WHERE $in"); + $sth->execute; + my %gotid; + while (my ($jid, $jitemid, $propid, $value) = $sth->fetchrow_array) { + my $id = "$jid:$jitemid"; + my $propname = $LJ::CACHE_PROPID{'log'}->{$propid}{name}; + $ret->{prop}{$id}{$propname} = $value; + $gotid{$id} = 1; + } + foreach my $id (keys %gotid) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + LJ::MemCache::add([$jid, "logprop:$id"], $ret->{prop}{$id}); + delete $cneedprop->{$id}; + } + }; + + my $fetchrc = sub { + my $db = shift; + return unless %$cneedrc; + my $in = $make_in->(keys %$cneedrc); + $sth = $db->prepare("SELECT journalid, jitemid, replycount FROM log2 WHERE $in"); + $sth->execute; + while (my ($jid, $jitemid, $rc) = $sth->fetchrow_array) { + my $id = "$jid:$jitemid"; + $ret->{replycount}{$id} = $rc; + LJ::MemCache::add([$jid, "rp:$id"], $rc); + delete $cneedrc->{$id}; + } + }; + + my $dberr = sub { + die "Couldn't connect to database" if $single_user; + next; + }; + + # run the fetch functions on the proper databases, with fallbacks if necessary. + my ($dbcm, $dbcr); + if (@LJ::MEMCACHE_SERVERS or $opts->{use_master}) { + $dbcm ||= LJ::get_cluster_master($cid) or $dberr->(); + $fetchtext->($dbcm) if %$cneedtext; + $fetchprop->($dbcm) if %$cneedprop; + $fetchrc->($dbcm) if %$cneedrc; + } else { + $dbcr ||= LJ::get_cluster_reader($cid); + if ($dbcr) { + $fetchtext->($dbcr) if %$cneedtext; + $fetchprop->($dbcr) if %$cneedprop; + $fetchrc->($dbcr) if %$cneedrc; + } + # if we still need some data, switch to the master. + if (%$cneedtext or %$cneedprop) { + $dbcm ||= LJ::get_cluster_master($cid) or $dberr->(); + $fetchtext->($dbcm); + $fetchprop->($dbcm); + $fetchrc->($dbcm); + } + } + + # and finally, if there were no errors, + # insert into memcache the absence of props + # for all posts that didn't have any props. + foreach my $id (keys %$cneedprop) { + my ($jid, $jitemid) = map { $_ + 0 } split(/:/, $id); + LJ::MemCache::set([$jid, "logprop:$id"], {}); + } + } + return $ret; +} + +sub get_posts +{ + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $rawposts = get_posts_raw($opts, @_); + + # fix up posts as needed for display, following directions given in opts. + + + # XXX this function is incomplete. it should also HTML clean, etc. + # XXX we need to load users when we have unknown8bit data, but that + # XXX means we have to load users. + + + while (my ($id, $rp) = each %$rawposts) { + if ($LJ::UNICODE && $rp->{props}{unknown8bit}) { + #LJ::item_toutf8($u, \$rp->{text}[0], \$rp->{text}[1], $rp->{props}); + } + } + + return $rawposts; +} + +# +# name: LJ::get_remote +# des: authenticates the user at the remote end based on their cookies +# and returns a hashref representing them +# returns: hashref containing 'user' and 'userid' if valid user, else +# undef. +# args: opts? +# des-opts: 'criterr': scalar ref to set critical error flag. if set, caller +# should stop processing whatever it's doing and complain +# about an invalid login with a link to the logout page.. +# 'ignore_ip': ignore IP address of remote for IP-bound sessions +# +sub get_remote +{ + my $opts = ref $_[0] eq "HASH" ? shift : {}; + my $dummy; + + return $LJ::CACHE_REMOTE if $LJ::CACHED_REMOTE && ! $opts->{'ignore_ip'}; + + my $criterr = $opts->{criterr} || \$dummy; + $$criterr = 0; + + my $cookie = sub { return $BML::COOKIE{$_[0]}; }; + + my $no_remote = sub { + LJ::set_remote(undef); + return undef; + }; + + # set this flag if any of their ljsession cookies contained the ".FS" + # opt to use the fast server. if we later find they're not logged + # in and set it, or set it with a free account, then we give them + # the invalid cookies error. + my $tried_fast = 0; + my @errs = (); + my $now = time(); + + my ($u, $sess); # what we eventually care about + my $memkey; + + foreach my $sessdata (@{ $cookie->('ljsession[]'); }) { + my ($authtype, $user, $sessid, $auth, $sopts) = split(/:/, $sessdata); + $tried_fast = 1 if $sopts =~ /\.FS\b/; + my $err = sub { + $sess = undef; + push @errs, "$sessdata: $_[0]"; + }; + + # fail unless authtype is 'ws' (more might be added in future) + unless ($authtype eq "ws") { + $err->("no ws auth"); + next; + } + + $u = LJ::load_user($user); + unless ($u) { + $err->("user doesn't exist"); + next; + } + + # locked accounts can't be logged in + if ($u->{statusvis} eq 'L') { + $err->("User account is locked."); + next; + } + + my $sess_db; + my $get_sess = sub { + return undef unless $sess_db; + $sess = $sess_db->selectrow_hashref("SELECT * FROM sessions ". + "WHERE userid=? AND sessid=? AND auth=?", + undef, $u->{'userid'}, $sessid, $auth); + }; + $memkey = [$u->{'userid'},"sess:$u->{'userid'}:$sessid"]; + # try memory + $sess = LJ::MemCache::get($memkey); + # try master + unless ($sess) { + $sess_db = LJ::get_cluster_def_reader($u); + $get_sess->(); + LJ::MemCache::set($memkey, $sess) if $sess; + } + # try slave + unless ($sess) { + $sess_db = LJ::get_cluster_reader($u); + $get_sess->(); + } + + unless ($sess) { + $err->("Couldn't find session"); + next; + } + + unless ($sess->{auth} eq $auth) { + $err->("Invald auth"); + next; + } + + if ($sess->{'timeexpire'} < $now) { + $err->("Invalid auth"); + next; + } + + if ($sess->{'ipfixed'} && ! $opts->{'ignore_ip'}) { + my $remote_ip = $LJ::_XFER_REMOTE_IP || LJ::get_remote_ip(); + if ($sess->{'ipfixed'} ne $remote_ip) { + $err->("Session wrong IP"); + next; + } + } + + last; + } + + # inform the caller that this user is faking their fast-server cookie + # attribute. + if ($tried_fast && ! LJ::get_cap($u, "fastserver")) { + $$criterr = 1; + } + + if (! $sess) { + LJ::set_remote(undef); + return undef; + } + + # renew short session + my $sess_length = { + 'short' => 60*60*24*1.5, + 'long' => 60*60*24*60, + 'once' => 0, # do not renew these + }->{$sess->{exptype}}; + + # only long cookies should be given an expiration time + # other should get 0 (when browser closes) + my $cookie_length = $sess->{exptype} eq 'long' ? $sess_length : 0; + + # if there is a new session length to be set and the user's db writer is available, + # go ahead and set the new session expiration in the database. then only update the + # cookies if the database operation is successful + if ($sess_length && $sess->{'timeexpire'} - $now < $sess_length/2 && + $u->writer && $u->do("UPDATE sessions SET timeexpire=? WHERE userid=? AND sessid=?", + undef, $now + $sess_length, $u->{userid}, $sess->{sessid})) + { + + # delete old, now-bogus memcache data + LJ::MemCache::delete($memkey); + + # update their ljsession cookie unless it's a session-length cookie + if ($cookie_length) { + + eval { + my @domains = ref $LJ::COOKIE_DOMAIN ? @$LJ::COOKIE_DOMAIN : ($LJ::COOKIE_DOMAIN); + foreach my $dom (@domains) { + my $cookiestr = 'ljsession=' . $cookie->('ljsession'); + $cookiestr .= '; expires=' . LJ::time_to_cookie($now + $cookie_length); + $cookiestr .= $dom ? "; domain=$dom" : ''; + $cookiestr .= '; path=/; HttpOnly'; + + Apache->request->err_headers_out->add('Set-Cookie' => $cookiestr); + } + }; + } + } + + # augment hash with session data; + $u->{'_session'} = $sess; + + LJ::set_remote($u); + + eval { + Apache->request->notes("ljuser" => $u->{'user'}); + }; + + return $u; +} + +sub set_remote +{ + my $remote = shift; + $LJ::CACHED_REMOTE = 1; + $LJ::CACHE_REMOTE = $remote; + 1; +} + +sub unset_remote +{ + $LJ::CACHED_REMOTE = 0; + $LJ::CACHE_REMOTE = undef; + 1; +} + +sub load_remote +{ + # function is no longer used, since get_remote returns full objects. + # keeping this here so we don't break people's local site code +} + +# +# name: LJ::get_remote_noauth +# des: returns who the remote user says they are, but doesn't check +# their login token. disadvantage: insecure, only use when +# you're not doing anything critical. advantage: faster. +# returns: hashref containing only key 'user', not 'userid' like +# [func[LJ::get_remote]]. +# +sub get_remote_noauth +{ + my $sess = $BML::COOKIE{'ljsession'}; + return { 'user' => $1 } if $sess =~ /^ws:(\w+):/; + return undef; +} + +# +# name: LJ::clear_caches +# des: This function is called from a HUP signal handler and is intentionally +# very very simple (1 line) so we don't core dump on a system without +# reentrant libraries. It just sets a flag to clear the caches at the +# beginning of the next request (see [func[LJ::handle_caches]]). +# There should be no need to ever call this function directly. +# +sub clear_caches +{ + $LJ::CLEAR_CACHES = 1; +} + +# +# name: LJ::handle_caches +# des: clears caches if the CLEAR_CACHES flag is set from an earlier +# HUP signal that called [func[LJ::clear_caches]], otherwise +# does nothing. +# returns: true (always) so you can use it in a conjunction of +# statements in a while loop around the application like: +# while (LJ::handle_caches() && FCGI::accept()) +# +sub handle_caches +{ + return 1 unless $LJ::CLEAR_CACHES; + $LJ::CLEAR_CACHES = 0; + + do "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + do "$ENV{'LJHOME'}/cgi-bin/ljdefaults.pl"; + + $LJ::DBIRole->flush_cache(); + + %LJ::CACHE_PROP = (); + %LJ::CACHE_STYLE = (); + $LJ::CACHED_MOODS = 0; + $LJ::CACHED_MOOD_MAX = 0; + %LJ::CACHE_MOODS = (); + %LJ::CACHE_MOOD_THEME = (); + %LJ::CACHE_USERID = (); + %LJ::CACHE_USERNAME = (); + %LJ::CACHE_CODES = (); + %LJ::CACHE_USERPROP = (); # {$prop}->{ 'upropid' => ... , 'indexed' => 0|1 }; + %LJ::CACHE_ENCODINGS = (); + return 1; +} + +# +# name: LJ::start_request +# des: Before a new web request is obtained, this should be called to +# determine if process should die or keep working, clean caches, +# reload config files, etc. +# returns: 1 if a new request is to be processed, 0 if process should die. +# +sub start_request +{ + handle_caches(); + # TODO: check process growth size + + # clear per-request caches + LJ::unset_remote(); # clear cached remote + $LJ::ACTIVE_CRUMB = ''; # clear active crumb + %LJ::CACHE_USERPIC = (); # picid -> hashref + %LJ::CACHE_USERPIC_INFO = (); # uid -> { ... } + %LJ::REQ_CACHE_USER_NAME = (); # users by name + %LJ::REQ_CACHE_USER_ID = (); # users by id + %LJ::REQ_CACHE_REL = (); # relations from LJ::check_rel() + %LJ::REQ_CACHE_DIRTY = (); # caches calls to LJ::mark_dirty() + %LJ::S1::REQ_CACHE_STYLEMAP = (); # styleid -> uid mappings + %LJ::REQ_DBIX_TRACKER = (); # canonical dbrole -> DBIx::StateTracker + %LJ::REQ_DBIX_KEEPER = (); # dbrole -> DBIx::StateKeeper + %LJ::REQ_HEAD_HAS = (); # avoid code duplication for js + + # we use this to fake out get_remote's perception of what + # the client's remote IP is, when we transfer cookies between + # authentication domains. see the FotoBilder interface. + $LJ::_XFER_REMOTE_IP = undef; + + # clear the handle request cache (like normal cache, but verified already for + # this request to be ->ping'able). + $LJ::DBIRole->clear_req_cache(); + + # need to suck db weights down on every request (we check + # the serial number of last db weight change on every request + # to validate master db connection, instead of selecting + # the connection ID... just as fast, but with a point!) + $LJ::DBIRole->trigger_weight_reload(); + + # reset BML's cookies + eval { BML::reset_cookies() }; + + # check the modtime of ljconfig.pl and reload if necessary + # only do a stat every 10 seconds and then only reload + # if the file has changed + my $now = time(); + if ($now - $LJ::CACHE_CONFIG_MODTIME_LASTCHECK > 10) { + my $modtime = (stat("$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"))[9]; + if ($modtime > $LJ::CACHE_CONFIG_MODTIME) { + # reload config and update cached modtime + $LJ::CACHE_CONFIG_MODTIME = $modtime; + eval { + do "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; + do "$ENV{'LJHOME'}/cgi-bin/ljdefaults.pl"; + + # reload MogileFS config + if (LJ::mogclient()) { + LJ::mogclient()->reload + ( domain => $LJ::MOGILEFS_CONFIG{domain}, + root => $LJ::MOGILEFS_CONFIG{root}, + hosts => $LJ::MOGILEFS_CONFIG{hosts}, ); + LJ::mogclient()->set_pref_ip(\%LJ::MOGILEFS_PREF_IP) + if %LJ::MOGILEFS_PREF_IP; + } + }; + $LJ::IMGPREFIX_BAK = $LJ::IMGPREFIX; + $LJ::STATPREFIX_BAK = $LJ::STATPREFIX; + $LJ::LOCKER_OBJ = undef; + $LJ::DBIRole->set_sources(\%LJ::DBINFO); + LJ::MemCache::reload_conf(); + if ($modtime > $now - 60) { + # show to stderr current reloads. won't show + # reloads happening from new apache children + # forking off the parent who got the inital config loaded + # hours/days ago and then the "updated" config which is + # a different hours/days ago. + # + # only print when we're in web-context + print STDERR "ljconfig.pl reloaded\n" + if eval { Apache->request }; + } + } + $LJ::CACHE_CONFIG_MODTIME_LASTCHECK = $now; + } + + return 1; +} + + +# +# name: LJ::end_request +# des: Clears cached DB handles/trackers/keepers (if $LJ::DISCONNECT_DBS is +# true) and disconnects MemCache handles (if $LJ::DISCONNECT_MEMCACHE is +# true). +# +sub end_request +{ + LJ::flush_cleanup_handlers(); + LJ::disconnect_dbs() if $LJ::DISCONNECT_DBS; + LJ::MemCache::disconnect_all() if $LJ::DISCONNECT_MEMCACHE; +} + +# +# name: LJ::flush_cleanup_handlers +# des: Runs all cleanup handlers registered in @LJ::CLEANUP_HANDLERS +# +sub flush_cleanup_handlers { + while (my $ref = shift @LJ::CLEANUP_HANDLERS) { + next unless ref $ref eq 'CODE'; + $ref->(); + } +} + +# +# name: LJ::disconnect_dbs +# des: Clear cached DB handles and trackers/keepers to partitioned DBs. +# +sub disconnect_dbs { + # clear cached handles + $LJ::DBIRole->disconnect_all( { except => [qw(logs)] }); + + # and cached trackers/keepers to partitioned dbs + while (my ($role, $tk) = each %LJ::REQ_DBIX_TRACKER) { + $tk->disconnect if $tk; + } + %LJ::REQ_DBIX_TRACKER = (); + %LJ::REQ_DBIX_KEEPER = (); +} + +# +# name: LJ::load_userpics +# des: Loads a bunch of userpic at once. +# args: dbarg?, upics, idlist +# des-upics: hashref to load pictures into, keys being the picids +# des-idlist: [$u, $picid] or [[$u, $picid], [$u, $picid], +] objects +# also supports depreciated old method of an array ref of picids +# +sub load_userpics +{ + &nodb; + my ($upics, $idlist) = @_; + + return undef unless ref $idlist eq 'ARRAY' && $idlist->[0]; + + # deal with the old calling convention, just an array ref of picids eg. [7, 4, 6, 2] + if (! ref $idlist->[0] && $idlist->[0]) { # assume we have an old style caller + my $in = join(',', map { $_+0 } @$idlist); + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT userid, picid, width, height " . + "FROM userpic WHERE picid IN ($in)"); + + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + my $id = $_->{'picid'}; + undef $_->{'picid'}; + $upics->{$id} = $_; + } + return; + } + + # $idlist needs to be an arrayref of arrayrefs, + # HOWEVER, there's a special case where it can be + # an arrayref of 2 items: $u (which is really an arrayref) + # as well due to 'fields' and picid which is an integer. + # + # [$u, $picid] needs to map to [[$u, $picid]] while allowing + # [[$u1, $picid1], [$u2, $picid2], [etc...]] to work. + if (scalar @$idlist == 2 && ! ref $idlist->[1]) { + $idlist = [ $idlist ]; + } + + my @load_list; + foreach my $row (@{$idlist}) + { + my ($u, $id) = @$row; + next unless ref $u; + + if ($LJ::CACHE_USERPIC{$id}) { + $upics->{$id} = $LJ::CACHE_USERPIC{$id}; + } elsif ($id+0) { + push @load_list, [$u, $id+0]; + } + } + return unless @load_list; + + if (@LJ::MEMCACHE_SERVERS) { + my @mem_keys = map { [$_->[1],"userpic.$_->[1]"] } @load_list; + my $mem = LJ::MemCache::get_multi(@mem_keys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $v && $k =~ /(\d+)/; + my $id = $1; + $upics->{$id} = LJ::MemCache::array_to_hash("userpic", $v); + } + @load_list = grep { ! $upics->{$_->[1]} } @load_list; + return unless @load_list; + } + + my %db_load; + my @load_list_d6; + foreach my $row (@load_list) { + # ignore users on clusterid 0 + next unless $row->[0]->{clusterid}; + + if ($row->[0]->{'dversion'} > 6) { + push @{$db_load{$row->[0]->{'clusterid'}}}, $row; + } else { + push @load_list_d6, $row; + } + } + + foreach my $cid (keys %db_load) { + my $dbcr = LJ::get_cluster_def_reader($cid); + unless ($dbcr) { + print STDERR "Error: LJ::load_userpics unable to get handle; cid = $cid\n"; + next; + } + + my (@bindings, @data); + foreach my $row (@{$db_load{$cid}}) { + push @bindings, "(userid=? AND picid=?)"; + push @data, ($row->[0]->{userid}, $row->[1]); + } + next unless @data && @bindings; + + my $sth = $dbcr->prepare("SELECT userid, picid, width, height, fmt, state, ". + " UNIX_TIMESTAMP(picdate) AS 'picdate', location, flags ". + "FROM userpic2 WHERE " . join(' OR ', @bindings)); + $sth->execute(@data); + + while (my $ur = $sth->fetchrow_hashref) { + my $id = delete $ur->{'picid'}; + $upics->{$id} = $ur; + + # force into numeric context so they'll be smaller in memcache: + foreach my $k (qw(userid width height flags picdate)) { + $ur->{$k} += 0; + } + $ur->{location} = uc(substr($ur->{location}, 0, 1)); + + $LJ::CACHE_USERPIC{$id} = $ur; + LJ::MemCache::set([$id,"userpic.$id"], LJ::MemCache::hash_to_array("userpic", $ur)); + } + } + + # following path is only for old style d6 userpics... don't load any if we don't + # have any to load + return unless @load_list_d6; + + my $dbr = LJ::get_db_writer(); + my $picid_in = join(',', map { $_->[1] } @load_list_d6); + my $sth = $dbr->prepare("SELECT userid, picid, width, height, contenttype, state, ". + " UNIX_TIMESTAMP(picdate) AS 'picdate' ". + "FROM userpic WHERE picid IN ($picid_in)"); + $sth->execute; + while (my $ur = $sth->fetchrow_hashref) { + my $id = delete $ur->{'picid'}; + $upics->{$id} = $ur; + + # force into numeric context so they'll be smaller in memcache: + foreach my $k (qw(userid width height picdate)) { + $ur->{$k} += 0; + } + $ur->{location} = "?"; + $ur->{flags} = undef; + $ur->{fmt} = { + 'image/gif' => 'G', + 'image/jpeg' => 'J', + 'image/png' => 'P', + }->{delete $ur->{contenttype}}; + + $LJ::CACHE_USERPIC{$id} = $ur; + LJ::MemCache::set([$id,"userpic.$id"], LJ::MemCache::hash_to_array("userpic", $ur)); + } +} + +# +# name: LJ::modify_caps +# des: Given a list of caps to add and caps to remove, updates a user's caps +# args: uuid, cap_add, cap_del, res +# arg-cap_add: arrayref of bit numbers to turn on +# arg-cap_del: arrayref of bit numbers to turn off +# arg-res: hashref returned from 'modify_caps' hook +# returns: updated u object, retrieved from $dbh, then 'caps' key modified +# otherwise, returns 0 unless all hooks run properly +# +sub modify_caps { + my ($argu, $cap_add, $cap_del, $res) = @_; + my $userid = LJ::want_userid($argu); + return undef unless $userid; + + $cap_add ||= []; + $cap_del ||= []; + my %cap_add_mod = (); + my %cap_del_mod = (); + + # convert capnames to bit numbers + if (LJ::are_hooks("get_cap_bit")) { + foreach my $bit (@$cap_add, @$cap_del) { + next if $bit =~ /^\d+$/; + + # bit is a magical reference into the array + $bit = LJ::run_hook("get_cap_bit", $bit); + } + } + + # get a u object directly from the db + my $u = LJ::load_userid($userid, "force"); + + # add new caps + my $newcaps = int($u->{'caps'}); + foreach (@$cap_add) { + my $cap = 1 << $_; + + # about to turn bit on, is currently off? + $cap_add_mod{$_} = 1 unless $newcaps & $cap; + $newcaps |= $cap; + } + + # remove deleted caps + foreach (@$cap_del) { + my $cap = 1 << $_; + + # about to turn bit off, is it currently on? + $cap_del_mod{$_} = 1 if $newcaps & $cap; + $newcaps &= ~$cap; + } + + # run hooks for modified bits + if (LJ::are_hooks("modify_caps")) { + $res = LJ::run_hook("modify_caps", + { 'u' => $u, + 'newcaps' => $newcaps, + 'oldcaps' => $u->{'caps'}, + 'cap_on_req' => { map { $_ => 1 } @$cap_add }, + 'cap_off_req' => { map { $_ => 1 } @$cap_del }, + 'cap_on_mod' => \%cap_add_mod, + 'cap_off_mod' => \%cap_del_mod, + }); + + # hook should return a status code + return undef unless defined $res; + } + + # update user row + LJ::update_user($u, { 'caps' => $newcaps }); + + return $u; +} + +# +# name: LJ::expunge_userpic +# des: Expunges a userpic so that the system will no longer deliver this userpic. If +# your site has off-site caching or something similar, you can also define a hook +# "expunge_userpic" which will be called with a picid and userid when a pic is +# expunged. +# args: u, picid +# des-picid: Id of the picture to expunge. +# des-u: User object +# returns: undef on error, or the userid of the picture owner on success. +# +sub expunge_userpic { + # take in a picid and expunge it from the system so that it can no longer be used + my ($u, $picid) = @_; + $picid += 0; + return undef unless $picid && ref $u; + + # get the pic information + my $state; + + if ($u->{'dversion'} > 6) { + my $dbcm = LJ::get_cluster_master($u); + return undef unless $dbcm && $u->writer; + + $state = $dbcm->selectrow_array('SELECT state FROM userpic2 WHERE userid = ? AND picid = ?', + undef, $u->{'userid'}, $picid); + + return $u->{'userid'} if $state eq 'X'; # already expunged + + # else now mark it + $u->do("UPDATE userpic2 SET state='X' WHERE userid = ? AND picid = ?", undef, $u->{'userid'}, $picid); + return LJ::error($dbcm) if $dbcm->err; + $u->do("DELETE FROM userpicmap2 WHERE userid = ? AND picid = ?", undef, $u->{'userid'}, $picid); + } else { + my $dbr = LJ::get_db_reader(); + return undef unless $dbr; + + $state = $dbr->selectrow_array('SELECT state FROM userpic WHERE picid = ?', + undef, $picid); + + return $u->{'userid'} if $state eq 'X'; # already expunged + + # else now mark it + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + $dbh->do("UPDATE userpic SET state='X' WHERE picid = ?", undef, $picid); + return LJ::error($dbh) if $dbh->err; + $dbh->do("DELETE FROM userpicmap WHERE userid = ? AND picid = ?", undef, $u->{'userid'}, $picid); + } + + # now clear the user's memcache picture info + LJ::MemCache::delete([$u->{'userid'}, "upicinf:$u->{'userid'}"]); + + # call the hook and get out of here + my $rval = LJ::run_hook('expunge_userpic', $picid, $u->{'userid'}); + return ($u->{'userid'}, $rval); +} + +# +# name: LJ::activate_userpics +# des: Sets/unsets userpics as inactive based on account caps +# args: uuserid +# returns: nothing +# +sub activate_userpics +{ + # this behavior is optional, but enabled by default + return 1 if $LJ::ALLOW_PICS_OVER_QUOTA; + + my $u = shift; + return undef unless LJ::isu($u); + + # if a userid was given, get a real $u object + $u = LJ::load_userid($u, "force") unless isu($u); + + # should have a $u object now + return undef unless isu($u); + + # can't get a cluster read for expunged users since they are clusterid 0, + # so just return 1 to the caller from here and act like everything went fine + return 1 if $u->{'statusvis'} eq 'X'; + + my $userid = $u->{'userid'}; + + # active / inactive lists + my @active = (); + my @inactive = (); + my $allow = LJ::get_cap($u, "userpics"); + + # get a database handle for reading/writing + my $dbh = LJ::get_db_writer(); + my $dbcr = LJ::get_cluster_def_reader($u); + + # select all userpics and build active / inactive lists + my $sth; + if ($u->{'dversion'} > 6) { + return undef unless $dbcr; + $sth = $dbcr->prepare("SELECT picid, state FROM userpic2 WHERE userid=?"); + } else { + return undef unless $dbh; + $sth = $dbh->prepare("SELECT picid, state FROM userpic WHERE userid=?"); + } + $sth->execute($userid); + while (my ($picid, $state) = $sth->fetchrow_array) { + next if $state eq 'X'; # expunged, means userpic has been removed from site by admins + if ($state eq 'I') { + push @inactive, $picid; + } else { + push @active, $picid; + } + } + + # inactivate previously activated userpics + if (@active > $allow) { + my $to_ban = @active - $allow; + + # find first jitemid greater than time 2 months ago using rlogtime index + # ($LJ::EndOfTime - UnixTime) + my $jitemid = $dbcr->selectrow_array("SELECT jitemid FROM log2 USE INDEX (rlogtime) " . + "WHERE journalid=? AND rlogtime > ? LIMIT 1", + undef, $userid, $LJ::EndOfTime - time() + 86400*60); + + # query all pickws in logprop2 with jitemid > that value + my %count_kw = (); + my $propid = LJ::get_prop("log", "picture_keyword")->{'id'}; + my $sth = $dbcr->prepare("SELECT value, COUNT(*) FROM logprop2 " . + "WHERE journalid=? AND jitemid > ? AND propid=?" . + "GROUP BY value"); + $sth->execute($userid, $jitemid, $propid); + while (my ($value, $ct) = $sth->fetchrow_array) { + # keyword => count + $count_kw{$value} = $ct; + } + + my $keywords_in = join(",", map { $dbh->quote($_) } keys %count_kw); + + # map pickws to picids for freq hash below + my %count_picid = (); + if ($keywords_in) { + my $sth; + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT k.keyword, m.picid FROM userkeywords k, userpicmap2 m ". + "WHERE k.keyword IN ($keywords_in) AND k.kwid=m.kwid AND k.userid=m.userid " . + "AND k.userid=?"); + } else { + $sth = $dbh->prepare("SELECT k.keyword, m.picid FROM keywords k, userpicmap m " . + "WHERE k.keyword IN ($keywords_in) AND k.kwid=m.kwid " . + "AND m.userid=?"); + } + $sth->execute($userid); + while (my ($keyword, $picid) = $sth->fetchrow_array) { + # keyword => picid + $count_picid{$picid} += $count_kw{$keyword}; + } + } + + # we're only going to ban the least used, excluding the user's default + my @ban = (grep { $_ != $u->{'defaultpicid'} } + sort { $count_picid{$a} <=> $count_picid{$b} } @active); + + @ban = splice(@ban, 0, $to_ban) if @ban > $to_ban; + my $ban_in = join(",", map { $dbh->quote($_) } @ban); + if ($u->{'dversion'} > 6) { + $u->do("UPDATE userpic2 SET state='I' WHERE userid=? AND picid IN ($ban_in)", + undef, $userid) if $ban_in; + } else { + $dbh->do("UPDATE userpic SET state='I' WHERE userid=? AND picid IN ($ban_in)", + undef, $userid) if $ban_in; + } + } + + # activate previously inactivated userpics + if (@inactive && @active < $allow) { + my $to_activate = $allow - @active; + $to_activate = @inactive if $to_activate > @inactive; + + # take the $to_activate newest (highest numbered) pictures + # to reactivated + @inactive = sort @inactive; + my @activate_picids = splice(@inactive, -$to_activate); + + my $activate_in = join(",", map { $dbh->quote($_) } @activate_picids); + if ($activate_in) { + if ($u->{'dversion'} > 6) { + $u->do("UPDATE userpic2 SET state='N' WHERE userid=? AND picid IN ($activate_in)", + undef, $userid); + } else { + $dbh->do("UPDATE userpic SET state='N' WHERE userid=? AND picid IN ($activate_in)", + undef, $userid); + } + } + } + + # delete userpic info object from memcache + LJ::MemCache::delete([$userid, "upicinf:$userid"]); + + return 1; +} + +# +# name: LJ::get_userpic_info +# des: Given a user gets their user picture info +# args: uuid, opts (optional) +# des-u: user object or userid +# des-opts: hash of options, 'load_comments' +# returns: hash of userpicture information +# for efficiency, we store the userpic structures +# in memcache in a packed format. +# +# memory format: +# [ +# version number of format, +# userid, +# "packed string", which expands to an array of {width=>..., ...} +# "packed string", which expands to { 'kw1' => id, 'kw2' => id, ...} +# ] +# + +sub get_userpic_info +{ + my ($uuid, $opts) = @_; + return undef unless $uuid; + my $userid = LJ::want_userid($uuid); + my $u = LJ::want_user($uuid); # This should almost always be in memory already + return undef unless $u && $u->{clusterid}; + + # in the cache, cool, well unless it doesn't have comments or urls + # and we need them + if (my $cachedata = $LJ::CACHE_USERPIC_INFO{$userid}) { + my $good = 1; + if ($u->{'dversion'} > 6) { + $good = 0 if $opts->{'load_comments'} && ! $cachedata->{'_has_comments'}; + $good = 0 if $opts->{'load_urls'} && ! $cachedata->{'_has_urls'}; + } + return $cachedata if $good; + } + + my $VERSION_PICINFO = 3; + + my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"]; + my ($info, $minfo); + + if ($minfo = LJ::MemCache::get($memkey)) { + # the pre-versioned memcache data was a two-element hash. + # since then, we use an array and include a version number. + + if (ref $minfo eq 'HASH' || + $minfo->[0] != $VERSION_PICINFO) { + # old data in the cache. delete. + LJ::MemCache::delete($memkey); + } else { + my (undef, $picstr, $kwstr) = @$minfo; + $info = { + 'pic' => {}, + 'kw' => {}, + }; + while (length $picstr >= 7) { + my $pic = { userid => $u->{'userid'} }; + ($pic->{picid}, + $pic->{width}, $pic->{height}, + $pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, ''); + $info->{pic}->{$pic->{picid}} = $pic; + } + + my ($pos, $nulpos); + $pos = $nulpos = 0; + while (($nulpos = index($kwstr, "\0", $pos)) > 0) { + my $kw = substr($kwstr, $pos, $nulpos-$pos); + my $id = unpack("N", substr($kwstr, $nulpos+1, 4)); + $pos = $nulpos + 5; # skip NUL + 4 bytes. + $info->{kw}->{$kw} = $info->{pic}->{$id} if $info; + } + } + + if ($u->{'dversion'} > 6) { + + # Load picture comments + if ($opts->{'load_comments'}) { + my $commemkey = [$u->{'userid'}, "upiccom:$u->{'userid'}"]; + my $comminfo = LJ::MemCache::get($commemkey); + + if ($comminfo) { + my ($pos, $nulpos); + $pos = $nulpos = 0; + while (($nulpos = index($comminfo, "\0", $pos)) > 0) { + my $comment = substr($comminfo, $pos, $nulpos-$pos); + my $id = unpack("N", substr($comminfo, $nulpos+1, 4)); + $pos = $nulpos + 5; # skip NUL + 4 bytes. + $info->{'pic'}->{$id}->{'comment'} = $comment; + } + $info->{'_has_comments'} = 1; + } else { # Requested to load comments, but they aren't in memcache + # so force a db load + undef $info; + } + } + + # Load picture urls + if ($opts->{'load_urls'} && $info) { + my $urlmemkey = [$u->{'userid'}, "upicurl:$u->{'userid'}"]; + my $urlinfo = LJ::MemCache::get($urlmemkey); + + if ($urlinfo) { + my ($pos, $nulpos); + $pos = $nulpos = 0; + while (($nulpos = index($urlinfo, "\0", $pos)) > 0) { + my $url = substr($urlinfo, $pos, $nulpos-$pos); + my $id = unpack("N", substr($urlinfo, $nulpos+1, 4)); + $pos = $nulpos + 5; # skip NUL + 4 bytes. + $info->{'pic'}->{$id}->{'url'} = $url; + } + $info->{'_has_urls'} = 1; + } else { # Requested to load urls, but they aren't in memcache + # so force a db load + undef $info; + } + } + } + } + + my %minfocom; # need this in this scope + my %minfourl; + unless ($info) { + $info = { + 'pic' => {}, + 'kw' => {}, + }; + my ($picstr, $kwstr); + my $sth; + my $dbcr = LJ::get_cluster_def_reader($u); + my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + return undef unless $dbcr && $db; + + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT picid, width, height, state, userid, comment, url ". + "FROM userpic2 WHERE userid=?"); + } else { + $sth = $db->prepare("SELECT picid, width, height, state, userid ". + "FROM userpic WHERE userid=?"); + } + $sth->execute($u->{'userid'}); + my @pics; + while (my $pic = $sth->fetchrow_hashref) { + next if $pic->{state} eq 'X'; # no expunged pics in list + push @pics, $pic; + $info->{'pic'}->{$pic->{'picid'}} = $pic; + $minfocom{int($pic->{picid})} = $pic->{comment} if $u->{'dversion'} > 6 + && $opts->{'load_comments'} && $pic->{'comment'}; + $minfourl{int($pic->{'picid'})} = $pic->{'url'} if $u->{'dversion'} > 6 + && $opts->{'load_urls'} && $pic->{'url'}; + } + + + $picstr = join('', map { pack("NCCA", $_->{picid}, + $_->{width}, $_->{height}, $_->{state}) } @pics); + + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT k.keyword, m.picid FROM userpicmap2 m, userkeywords k ". + "WHERE k.userid=? AND m.kwid=k.kwid AND m.userid=k.userid"); + } else { + $sth = $db->prepare("SELECT k.keyword, m.picid FROM userpicmap m, keywords k ". + "WHERE m.userid=? AND m.kwid=k.kwid"); + } + $sth->execute($u->{'userid'}); + my %minfokw; + while (my ($kw, $id) = $sth->fetchrow_array) { + next unless $info->{'pic'}->{$id}; + next if $kw =~ /[\n\r\0]/; # used to be a bug that allowed these to get in. + $info->{'kw'}->{$kw} = $info->{'pic'}->{$id}; + $minfokw{$kw} = int($id); + } + $kwstr = join('', map { pack("Z*N", $_, $minfokw{$_}) } keys %minfokw); + + $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"]; + $minfo = [ $VERSION_PICINFO, $picstr, $kwstr ]; + LJ::MemCache::set($memkey, $minfo); + + if ($u->{'dversion'} > 6) { + + if ($opts->{'load_comments'}) { + $info->{'comment'} = \%minfocom; + my $commentstr = join('', map { pack("Z*N", $minfocom{$_}, $_) } keys %minfocom); + + my $memkey = [$u->{'userid'}, "upiccom:$u->{'userid'}"]; + LJ::MemCache::set($memkey, $commentstr); + + $info->{'_has_comments'} = 1; + } + + if ($opts->{'load_urls'}) { + my $urlstr = join('', map { pack("Z*N", $minfourl{$_}, $_) } keys %minfourl); + + my $memkey = [$u->{'userid'}, "upicurl:$u->{'userid'}"]; + LJ::MemCache::set($memkey, $urlstr); + + $info->{'_has_urls'} = 1; + } + } + } + + $LJ::CACHE_USERPIC_INFO{$u->{'userid'}} = $info; + return $info; +} + +# +# name: LJ::get_pic_from_keyword +# des: Given a userid and keyword, returns the pic row hashref +# args: u, keyword +# des-keyword: The keyword of the userpic to fetch +# returns: hashref of pic row found +# +sub get_pic_from_keyword +{ + my ($u, $kw) = @_; + my $info = LJ::get_userpic_info($u); + return undef unless $info; + return $info->{'kw'}{$kw}; +} + +sub get_picid_from_keyword +{ + my ($u, $kw, $default) = @_; + $default ||= (ref $u ? $u->{'defaultpicid'} : 0); + return $default unless $kw; + my $info = LJ::get_userpic_info($u); + return $default unless $info; + my $pr = $info->{'kw'}{$kw}; + return $pr ? $pr->{'picid'} : $default; +} + +# +# name: LJ::get_timezone +# des: Gets the timezone offset for the user. +# args: u, offsetref, fakedref +# des-u: user object. +# des-offsetref: reference to scalar to hold timezone offset; +# des-fakedref: reference to scalar to hold whether this timezone was +# faked. 0 if it is the timezone specified by the user (not supported yet). +# returns: nonzero if successful. +# +sub get_timezone { + my ($u, $offsetref, $fakedref) = @_; + + # we currently don't support timezones, + # but when we do this will be the function to modify. + + my $offset; + + my $dbcr = LJ::get_cluster_def_reader($u); + return 0 unless $dbcr; + + # we guess their current timezone's offset + # by comparing the gmtime of their last post + # with the time they specified on that post. + + # grab the times on the last post. + if (my $last_row = $dbcr->selectrow_hashref( + "SELECT rlogtime, eventtime ". + "FROM log2 WHERE journalid=? ". + "ORDER BY rlogtime LIMIT 1", + undef, $u->{userid})) { + my $logtime = $LJ::EndOfTime - $last_row->{'rlogtime'}; + my $eventtime = LJ::mysqldate_to_time($last_row->{'eventtime'}, 1); + my $hourdiff = ($eventtime - $logtime) / 3600; + + # if they're up to a quarter hour behind, round up. + $$offsetref = $hourdiff > 0 ? int($hourdiff + 0.25) : int($hourdiff - 0.25); + } + + # until we store real timezones, the timezone is always faked. + $$fakedref = 1 if $fakedref; + + return 1; +} + +# +# name: LJ::strip_bad_code +# class: security +# des: Removes malicious/annoying HTML. +# info: This is just a wrapper function around [func[LJ::CleanHTML::clean]]. +# args: textref +# des-textref: Scalar reference to text to be cleaned. +# returns: Nothing. +# +sub strip_bad_code +{ + my $data = shift; + LJ::CleanHTML::clean($data, { + 'eat' => [qw[layer iframe script object embed]], + 'mode' => 'allow', + 'keepcomments' => 1, # Allows CSS to work + }); +} + +# +# name: LJ::server_down_html +# des: Returns an HTML server down message. +# returns: A string with a server down message in HTML. +# +sub server_down_html +{ + return "$LJ::SERVER_DOWN_SUBJECT
    $LJ::SERVER_DOWN_MESSAGE"; +} + +# +# name: LJ::make_journal +# class: +# des: +# info: +# args: dbarg, user, view, remote, opts +# des-: +# returns: +# +sub make_journal +{ + &nodb; + my ($user, $view, $remote, $opts) = @_; + + my $r = $opts->{'r'}; # mod_perl $r, or undef + my $geta = $opts->{'getargs'}; + + if ($LJ::SERVER_DOWN) { + if ($opts->{'vhost'} eq "customview") { + return ""; + } + return LJ::server_down_html(); + } + + # if we're using the 'tag' view, then convert to lastn and set option, this + # is done early so it can propogate to S1 and S2 as appropriate + if ($view eq 'tag') { + # FIXME: would be nice to have boolean logic "foo AND bar" or "+foo -bar" etc + # "foo,bar" is interpreted as "foo or bar" for now, common case + my $tags = LJ::durl($opts->{pathextra}); + $tags =~ s/^\///; # clear leading / + $opts->{getargs}->{tag} = $tags; + + # use a lastn view to render + delete $opts->{pathextra}; + $view = 'lastn'; + } + + # S1 style hashref. won't be loaded now necessarily, + # only if via customview. + my $style; + + my ($styleid); + if ($opts->{'styleid'}) { # s1 styleid + $styleid = $opts->{'styleid'}+0; + + # if we have an explicit styleid, we have to load + # it early so we can learn its type, so we can + # know which uprops to load for its owner + $style = LJ::S1::load_style($styleid, \$view); + } else { + $view ||= "lastn"; # default view when none specified explicitly in URLs + if ($LJ::viewinfo{$view} || $view eq "month" || + $view eq "entry" || $view eq "reply") { + $styleid = -1; # to get past the return, then checked later for -1 and fixed, once user is loaded. + } else { + $opts->{'badargs'} = 1; + } + } + return unless $styleid; + + my $u; + if ($opts->{'u'}) { + $u = $opts->{'u'}; + } else { + $u = LJ::load_user($user); + } + + unless ($u) { + $opts->{'baduser'} = 1; + return "

    Error

    No such user $user"; + } + + my $eff_view = $LJ::viewinfo{$view}->{'styleof'} || $view; + my $s1prop = "s1_${eff_view}_style"; + + my @needed_props = ("stylesys", "s2_style", "url", "urlname", "opt_nctalklinks", + "renamedto", "opt_blockrobots", "opt_usesharedpic", + "journaltitle", "journalsubtitle", "external_foaf_url"); + + # S2 is more fully featured than S1, so sometimes we get here and $eff_view + # is reply/month/entry/res and that means it *has* to be S2--S1 defaults to a + # BML page to handle those, but we don't want to attempt to load a userprop + # because now load_user_props dies if you try to load something invalid + push @needed_props, $s1prop if $eff_view =~ /^(?:calendar|day|friends|lastn)$/; + + # preload props the view creation code will need later (combine two selects) + if (ref $LJ::viewinfo{$eff_view}->{'owner_props'} eq "ARRAY") { + push @needed_props, @{$LJ::viewinfo{$eff_view}->{'owner_props'}}; + } + + if ($eff_view eq "reply") { + push @needed_props, "opt_logcommentips"; + } + + LJ::load_user_props($u, @needed_props); + + # FIXME: remove this after all affected accounts have been fixed + # see http://zilla.livejournal.org/1443 for details + if ($u->{$s1prop} =~ /^\D/) { + $u->{$s1prop} = $LJ::USERPROP_DEF{$s1prop}; + LJ::set_userprop($u, $s1prop, $u->{$s1prop}); + } + + # if the remote is the user to be viewed, make sure the $remote + # hashref has the value of $u's opt_nctalklinks (though with + # LJ::load_user caching, this may be assigning between the same + # underlying hashref) + $remote->{'opt_nctalklinks'} = $u->{'opt_nctalklinks'} if + ($remote && $remote->{'userid'} == $u->{'userid'}); + + my $stylesys = 1; + if ($styleid == -1) { + + my $get_styleinfo = sub { + + my $get_s1_styleid = sub { + my $id = $u->{$s1prop}; + LJ::run_hooks("s1_style_select", { + 'styleid' => \$id, + 'u' => $u, + 'view' => $view, + }); + return $id; + }; + + # forced s2 style id + if ($geta->{'s2id'} && LJ::get_cap($u, "s2styles")) { + + # see if they own the requested style + my $dbr = LJ::get_db_reader(); + my $style_userid = $dbr->selectrow_array("SELECT userid FROM s2styles WHERE styleid=?", + undef, $geta->{'s2id'}); + + # if remote owns the style or the journal owns the style, it's okay + if ($u->{'userid'} == $style_userid || + $remote->{'userid'} == $style_userid ) { + return (2, $geta->{'s2id'}); + } + } + + # style=mine passed in GET? + if ($remote && $geta->{'style'} eq 'mine') { + + # get remote props and decide what style remote uses + LJ::load_user_props($remote, "stylesys", "s2_style"); + + # remote using s2; make sure we pass down the $remote object as the style_u to + # indicate that they should use $remote to load the style instead of the regular $u + if ($remote->{'stylesys'} == 2 && $remote->{'s2_style'}) { + $opts->{'checkremote'} = 1; + $opts->{'style_u'} = $remote; + return (2, $remote->{'s2_style'}); + } + + # remote using s1 + return (1, $get_s1_styleid->()); + } + + # resource URLs have the styleid in it + if ($view eq "res" && $opts->{'pathextra'} =~ m!^/(\d+)/!) { + return (2, $1); + } + + my $forceflag = 0; + LJ::run_hooks("force_s1", $u, \$forceflag); + + # if none of the above match, they fall through to here + if ( !$forceflag && $u->{'stylesys'} == 2 ) { + return (2, $u->{'s2_style'}); + } + + # no special case and not s2, fall through to s1 + return (1, $get_s1_styleid->()); + }; + + ($stylesys, $styleid) = $get_styleinfo->(); + } + + # signal to LiveJournal.pm that we can't handle this + if ($stylesys == 1 && ($view eq "entry" || $view eq "reply" || $view eq "month")) { + ${$opts->{'handle_with_bml_ref'}} = 1; + return; + } + + if ($r) { + $r->notes('journalid' => $u->{'userid'}); + } + + my $notice = sub { + my $msg = shift; + my $status = shift; + + my $url = "$LJ::SITEROOT/users/$user/"; + $opts->{'status'} = $status if $status; + + my $head; + $head .= qq{\n} + if LJ::OpenID::server_enabled(); + + return qq{ + + + $head + + +

    Notice

    +

    $msg

    +

    Instead, please use $url

    + + + }.("\n" x 50); + }; + my $error = sub { + my $msg = shift; + my $status = shift; + $opts->{'status'} = $status if $status; + + return qq{ +

    Error

    +

    $msg

    + }.("\n" x 50); + }; + if ($LJ::USER_VHOSTS && $opts->{'vhost'} eq "users" && $u->{'journaltype'} ne 'R' && + ! LJ::get_cap($u, "userdomain")) { + return $notice->("URLs like http://username.$LJ::USER_DOMAIN/" . + " are not available for this user's account type."); + } + if ($opts->{'vhost'} =~ /^other:/ && ! LJ::get_cap($u, "userdomain")) { + return $notice->("This user's account type doesn't permit domain aliasing."); + } + if ($opts->{'vhost'} eq "customview" && ! LJ::get_cap($u, "styles")) { + return $notice->("This user's account type is not permitted to create and embed styles."); + } + if ($opts->{'vhost'} eq "community" && $u->{'journaltype'} !~ /[CR]/) { + $opts->{'badargs'} = 1; # Output a generic 'bad URL' message if available + return "

    Notice

    This account isn't a community journal.

    "; + } + if ($view eq "friendsfriends" && ! LJ::get_cap($u, "friendsfriendsview")) { + return "Sorry
    This user's account type doesn't permit showing friends of friends."; + } + + # now, if there's a GET argument for tags, split those out + if (exists $opts->{getargs}->{tag}) { + my $tagfilter = $opts->{getargs}->{tag}; + return $error->("You must provide tags to filter by.", "404 Not Found") + unless $tagfilter; + + # error if disabled + return $error->("Sorry, the tag system is currently disabled.", "404 Not Found") + if $LJ::DISABLED{tags}; + + # throw an error for S1, but only on non-rename accounts. + return $error->("Sorry, tag filtering is not supported within S1 styles.", "404 Not Found") + if $stylesys == 1 && $u->{journaltype} ne 'R'; + + # overwrite any tags that exist + $opts->{tags} = []; + return $error->("Sorry, the tag list specified is invalid.", "404 Not Found") + unless LJ::Tags::is_valid_tagstring($tagfilter, $opts->{tags}); + + # get user's tags so we know what remote can see, and setup an inverse mapping + # from keyword to tag + $opts->{tagids} = []; + my $tags = LJ::Tags::get_usertags($u, { remote => $remote }); + my %kwref = ( map { $tags->{$_}->{name} => $_ } keys %{$tags || {}} ); + + foreach (@{$opts->{tags}}) { + return $error->("Sorry, one or more specified tags do not exist.", "404 Not Found") + unless $kwref{$_}; + push @{$opts->{tagids}}, $kwref{$_}; + } + } + + unless ($geta->{'viewall'} && LJ::check_priv($remote, "canview") || + $opts->{'pathextra'} =~ m#/(\d+)/stylesheet$#) { # don't check style sheets + return $error->("Journal has been deleted. If you are $user, you have a period of 30 days to decide to undelete your journal.", "404 Not Found") if ($u->{'statusvis'} eq "D"); + return $error->("This journal has been suspended.", "403 Forbidden") if ($u->{'statusvis'} eq "S"); + } + return $error->("This journal has been deleted and purged.", "410 Gone") if ($u->{'statusvis'} eq "X"); + + return $error->("This user has no journal here.", "404 Not here") if $u->{'journaltype'} eq "I" && $view ne "friends"; + + $opts->{'view'} = $view; + + # what charset we put in the HTML + $opts->{'saycharset'} ||= "utf-8"; + + if ($view eq 'data') { + return LJ::Feed::make_feed($r, $u, $remote, $opts); + } + + if ($stylesys == 2) { + $r->notes('codepath' => "s2.$view") if $r; + return LJ::S2::make_journal($u, $styleid, $view, $remote, $opts); + } + + # Everything from here on down is S1. FIXME: this should be moved to LJ::S1::make_journal + # to be more like LJ::S2::make_journal. + $r->notes('codepath' => "s1.$view") if $r; + + # For embedded polls + BML::set_language($LJ::LANGS[0] || 'en', \&LJ::Lang::get_text); + + # load the user-related S1 data (overrides and colors) + my $s1uc = {}; + my $s1uc_memkey = [$u->{'userid'}, "s1uc:$u->{'userid'}"]; + if ($u->{'useoverrides'} eq "Y" || $u->{'themeid'} == 0) { + $s1uc = LJ::MemCache::get($s1uc_memkey); + unless ($s1uc) { + my $db; + my $setmem = 1; + if (@LJ::MEMCACHE_SERVERS) { + $db = LJ::get_cluster_def_reader($u); + } else { + $db = LJ::get_cluster_reader($u); + $setmem = 0; + } + $s1uc = $db->selectrow_hashref("SELECT * FROM s1usercache WHERE userid=?", + undef, $u->{'userid'}); + LJ::MemCache::set($s1uc_memkey, $s1uc) if $s1uc && $setmem; + } + } + + # we should have our cache row! we'll update it in a second. + my $dbcm; + if (! $s1uc) { + $u->do("INSERT IGNORE INTO s1usercache (userid) VALUES (?)", undef, $u->{'userid'}); + $s1uc = {}; + } + + # conditionally rebuild parts of our cache that are missing + my %update; + + # is the overrides cache old or missing? + my $dbh; + if ($u->{'useoverrides'} eq "Y" && (! $s1uc->{'override_stor'} || + $s1uc->{'override_cleanver'} < $LJ::S1::CLEANER_VERSION)) { + + my $overrides = LJ::S1::get_overrides($u); + $update{'override_stor'} = LJ::CleanHTML::clean_s1_style($overrides); + $update{'override_cleanver'} = $LJ::S1::CLEANER_VERSION; + } + + # is the color cache here if it's a custom user theme? + if ($u->{'themeid'} == 0 && ! $s1uc->{'color_stor'}) { + my $col = {}; + $dbh ||= LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT coltype, color FROM themecustom WHERE user=?"); + $sth->execute($u->{'user'}); + $col->{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref; + $update{'color_stor'} = Storable::freeze($col); + } + + # save the updates + if (%update) { + my $set; + foreach my $k (keys %update) { + $s1uc->{$k} = $update{$k}; + $set .= ", " if $set; + $set .= "$k=" . $u->quote($update{$k}); + } + my $rv = $u->do("UPDATE s1usercache SET $set WHERE userid=?", undef, $u->{'userid'}); + if ($rv && $update{'color_stor'}) { + $dbh ||= LJ::get_db_writer(); + $dbh->do("DELETE FROM themecustom WHERE user=?", undef, $u->{'user'}); + } + LJ::MemCache::set($s1uc_memkey, $s1uc); + } + + # load the style + my $viewref = $view eq "" ? \$view : undef; + $style ||= $LJ::viewinfo{$view}->{'nostyle'} ? {} : + LJ::S1::load_style($styleid, $viewref); + + my %vars = (); + + # apply the style + foreach (keys %$style) { + $vars{$_} = $style->{$_}; + } + + # apply the overrides + if ($opts->{'nooverride'}==0 && $u->{'useoverrides'} eq "Y") { + my $tw = Storable::thaw($s1uc->{'override_stor'}); + foreach (keys %$tw) { + $vars{$_} = $tw->{$_}; + } + } + + # apply the color theme + my $cols = $u->{'themeid'} ? LJ::S1::get_themeid($u->{'themeid'}) : + Storable::thaw($s1uc->{'color_stor'}); + foreach (keys %$cols) { + $vars{"color-$_"} = $cols->{$_}; + } + + # instruct some function to make this specific view type + return unless defined $LJ::viewinfo{$view}->{'creator'}; + my $ret = ""; + + # call the view creator w/ the buffer to fill and the construction variables + my $res = $LJ::viewinfo{$view}->{'creator'}->(\$ret, $u, \%vars, $remote, $opts); + + unless ($res) { + my $errcode = $opts->{'errcode'}; + my $errmsg = { + 'nodb' => 'Database temporarily unavailable during maintenance.', + 'nosyn' => 'No syndication URL available.', + }->{$errcode}; + return "" if ($opts->{'vhost'} eq "customview"); + + # If not customview, set the error response code. + $opts->{'status'} = { + 'nodb' => '503 Maintenance', + 'nosyn' => '404 Not Found', + }->{$errcode} || '500 Server Error'; + return $errmsg; + } + + if ($opts->{'redir'}) { + return undef; + } + + # clean up attributes which we weren't able to quickly verify + # as safe in the Storable-stored clean copy of the style. + $ret =~ s/\%\%\[attr\[(.+?)\]\]\%\%/LJ::CleanHTML::s1_attribute_clean($1)/eg; + + # return it... + return $ret; +} + +# +# name: LJ::canonical_username +# des: +# info: +# args: user +# returns: the canonical username given, or blank if the username is not well-formed +# +sub canonical_username +{ + my $user = shift; + if ($user =~ /^\s*([\w\-]{1,15})\s*$/) { + # perl 5.8 bug: $user = lc($1) sometimes causes corruption when $1 points into $user. + $user = $1; + $user = lc($user); + $user =~ s/-/_/g; + return $user; + } + return ""; # not a good username. +} + +# +# name: LJ::decode_url_string +# class: web +# des: Parse URL-style arg/value pairs into a hash. +# args: buffer, hashref +# des-buffer: Scalar or scalarref of buffer to parse. +# des-hashref: Hashref to populate. +# returns: boolean; true. +# +sub decode_url_string +{ + my $a = shift; + my $buffer = ref $a ? $a : \$a; + my $hashref = shift; # output hash + + my $pair; + my @pairs = split(/&/, $$buffer); + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $hashref->{$name} .= $hashref->{$name} ? "\0$value" : $value; + } + return 1; +} + +sub get_db_reader { + return LJ::get_dbh("slave", "master"); +} + +sub get_db_writer { + return LJ::get_dbh("master"); +} + +# +# name: LJ::get_cluster_reader +# class: db +# des: Returns a cluster slave for a user, or cluster master if no slaves exist. +# args: uarg +# des-uarg: Either a userid scalar or a user object. +# returns: DB handle. Or undef if all dbs are unavailable. +# +sub get_cluster_reader +{ + my $arg = shift; + my $id = isu($arg) ? $arg->{'clusterid'} : $arg; + my @roles = ("cluster${id}slave", "cluster${id}"); + if (my $ab = $LJ::CLUSTER_PAIR_ACTIVE{$id}) { + $ab = lc($ab); + # master-master cluster + @roles = ("cluster${id}${ab}") if $ab eq "a" || $ab eq "b"; + } + return LJ::get_dbh(@roles); +} + +# +# name: LJ::get_cluster_def_reader +# class: db +# des: Returns a definitive cluster reader for a given user, used +# when the caller wants the master handle, but will only +# use it to read. +# args: uarg +# des-uarg: Either a clusterid scalar or a user object. +# returns: DB handle. Or undef if definitive reader is unavailable. +# +sub get_cluster_def_reader +{ + my @dbh_opts = scalar(@_) == 2 ? (shift @_) : (); + my $arg = shift; + my $id = isu($arg) ? $arg->{'clusterid'} : $arg; + return LJ::get_cluster_reader(@dbh_opts, $id) if + $LJ::DEF_READER_ACTUALLY_SLAVE{$id}; + return LJ::get_dbh(@dbh_opts, LJ::master_role($id)); +} + +# +# name: LJ::get_cluster_master +# class: db +# des: Returns a cluster master for a given user, used when the caller +# might use it to do a write (insert/delete/update/etc...) +# args: uarg +# des-uarg: Either a clusterid scalar or a user object. +# returns: DB handle. Or undef if master is unavailable. +# +sub get_cluster_master +{ + my @dbh_opts = scalar(@_) == 2 ? (shift @_) : (); + my $arg = shift; + my $id = isu($arg) ? $arg->{'clusterid'} : $arg; + return undef if $LJ::READONLY_CLUSTER{$id}; + return LJ::get_dbh(@dbh_opts, LJ::master_role($id)); +} + +# returns the DBI::Role role name of a cluster master given a clusterid +sub master_role { + my $id = shift; + my $role = "cluster${id}"; + if (my $ab = $LJ::CLUSTER_PAIR_ACTIVE{$id}) { + $ab = lc($ab); + # master-master cluster + $role = "cluster${id}${ab}" if $ab eq "a" || $ab eq "b"; + } + return $role; +} + +# +# name: LJ::item_link +# class: component +# des: Returns URL to view an individual journal item. +# info: The returned URL may have an ampersand in it. In an HTML/XML attribute, +# these must first be escaped by, say, [func[LJ::ehtml]]. This +# function doesn't return it pre-escaped because the caller may +# use it in, say, a plain-text email message. +# args: u, itemid, anum? +# des-itemid: Itemid of entry to link to. +# des-anum: If present, $u is assumed to be on a cluster and itemid is assumed +# to not be a $ditemid already, and the $itemid will be turned into one +# by multiplying by 256 and adding $anum. +# returns: scalar; unescaped URL string +# +sub item_link +{ + my ($u, $itemid, $anum, @args) = @_; + my $ditemid = $itemid*256 + $anum; + + # XXX: should have an option of returning a url with escaped (&) + # or non-escaped (&) arguments. a new link object would be best. + my $args = @args ? "?" . join("&", @args) : ""; + return LJ::journal_base($u) . "/$ditemid.html$args"; +} + +# +# name: LJ::make_graphviz_dot_file +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub make_graphviz_dot_file +{ + &nodb; + my $user = shift; + + # the code below is inefficient. let sites disable it. + return if $LJ::DISABLED{'graphviz_dot'}; + + my $dbr = LJ::get_db_reader(); + + my $quser = $dbr->quote($user); + my $sth; + my $ret; + + my $u = LJ::load_user($user); + return unless $u; + + $ret .= "digraph G {\n"; + $ret .= " node [URL=\"$LJ::SITEROOT/userinfo.bml?user=\\N\"]\n"; + $ret .= " node [fontsize=10, color=lightgray, style=filled]\n"; + $ret .= " \"$user\" [color=yellow, style=filled]\n"; + + # TAG:FR:ljlib:make_graphviz_dot_file1 + my @friends = (); + $sth = $dbr->prepare("SELECT friendid FROM friends WHERE userid=$u->{'userid'} AND userid<>friendid"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + push @friends, $_->{'friendid'}; + } + + # TAG:FR:ljlib:make_graphviz_dot_file2 + my $friendsin = join(", ", map { $dbr->quote($_); } ($u->{'userid'}, @friends)); + my $sql = "SELECT uu.user, uf.user AS 'friend' FROM friends f, user uu, user uf WHERE f.userid=uu.userid AND f.friendid=uf.userid AND f.userid<>f.friendid AND uu.statusvis='V' AND uf.statusvis='V' AND (f.friendid=$u->{'userid'} OR (f.userid IN ($friendsin) AND f.friendid IN ($friendsin)))"; + $sth = $dbr->prepare($sql); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $ret .= " \"$_->{'user'}\"->\"$_->{'friend'}\"\n"; + } + + $ret .= "}\n"; + + return $ret; +} + +# +# name: LJ::expand_embedded +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub expand_embedded +{ + &nodb; + my ($u, $ditemid, $remote, $eventref) = @_; + + LJ::Poll::show_polls($ditemid, $remote, $eventref); + LJ::run_hooks("expand_embedded", $u, $ditemid, $remote, $eventref); +} + +# +# name: LJ::make_remote +# des: Returns a minimal user structure ($remote-like) from +# a username and userid. +# args: user, userid +# des-user: Username. +# des-userid: User ID. +# returns: hashref with 'user' and 'userid' keys, or undef if +# either argument was bogus (so caller can pass +# untrusted input) +# +sub make_remote +{ + my $user = LJ::canonical_username(shift); + my $userid = shift; + if ($user && $userid && $userid =~ /^\d+$/) { + return { 'user' => $user, + 'userid' => $userid, }; + } + return undef; +} + +sub update_user +{ + my ($arg, $ref) = @_; + my @uid; + + if (ref $arg eq "ARRAY") { + @uid = @$arg; + } else { + @uid = want_userid($arg); + } + @uid = grep { $_ } map { $_ + 0 } @uid; + return 0 unless @uid; + + my @sets; + my @bindparams; + while (my ($k, $v) = each %$ref) { + if ($k eq "raw") { + push @sets, $v; + } else { + push @sets, "$k=?"; + push @bindparams, $v; + } + } + return 1 unless @sets; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + { + local $" = ","; + my $where = @uid == 1 ? "userid=$uid[0]" : "userid IN (@uid)"; + $dbh->do("UPDATE user SET @sets WHERE $where", undef, + @bindparams); + return 0 if $dbh->err; + } + if (@LJ::MEMCACHE_SERVERS) { + LJ::memcache_kill($_, "userid") foreach @uid; + } + return 1; +} + +# simple interface to LJ::load_userids_multiple. takes userids, +# returns hashref with keys ids, values $u refs. +sub load_userids +{ + my %u; + LJ::load_userids_multiple([ map { $_ => \$u{$_} } @_ ]); + return \%u; +} + +# +# name: LJ::load_userids_multiple +# des: Loads a number of users at once, efficiently. +# info: loads a few users at once, their userids given in the keys of $map +# listref (not hashref: can't have dups). values of $map listref are +# scalar refs to put result in. $have is an optional listref of user +# object caller already has, but is too lazy to sort by themselves. +# args: dbarg?, map, have, memcache_only? +# des-map: Arrayref of pairs (userid, destination scalarref) +# des-have: Arrayref of user objects caller already has +# des-memcache_only: Flag to only retrieve data from memcache +# returns: Nothing. +# +sub load_userids_multiple +{ + &nodb; + my ($map, $have, $memcache_only) = @_; + + my $sth; + + my %need; + while (@$map) { + my $id = shift @$map; + my $ref = shift @$map; + next unless int($id); + push @{$need{$id}}, $ref; + + if ($LJ::REQ_CACHE_USER_ID{$id}) { + push @{$have}, $LJ::REQ_CACHE_USER_ID{$id}; + } + } + + my $satisfy = sub { + my $u = shift; + next unless ref $u eq "LJ::User"; + foreach (@{$need{$u->{'userid'}}}) { + $$_ = $u; + } + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + delete $need{$u->{'userid'}}; + }; + + if ($have) { + foreach my $u (@$have) { + $satisfy->($u); + } + } + + if (%need) { + foreach (LJ::memcache_get_u(map { [$_,"userid:$_"] } keys %need)) { + $satisfy->($_); + } + } + + if (%need && ! $memcache_only) { + my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + _load_user_raw($db, "userid", [ keys %need ], sub { + my $u = shift; + LJ::memcache_set_u($u); + $satisfy->($u); + }); + } +} + +# des-db: $dbh/$dbr +# des-key: either "userid" or "user" (the WHERE part) +# des-vals: value or arrayref of values for key to match on +# des-hoook: optional code ref to run for each $u +# returns: last $u found +sub _load_user_raw +{ + my ($db, $key, $vals, $hook) = @_; + $hook ||= sub {}; + $vals = [ $vals ] unless ref $vals eq "ARRAY"; + + my $use_isam; + unless ($LJ::CACHE_NO_ISAM{user} || scalar(@$vals) > 10) { + eval { $db->do("HANDLER user OPEN"); }; + if ($@ || $db->err) { + $LJ::CACHE_NO_ISAM{user} = 1; + } else { + $use_isam = 1; + } + } + + my $last; + + if ($use_isam) { + $key = "PRIMARY" if $key eq "userid"; + foreach my $v (@$vals) { + my $sth = $db->prepare("HANDLER user READ `$key` = (?) LIMIT 1"); + $sth->execute($v); + my $u = $sth->fetchrow_hashref; + if ($u) { + bless $u, 'LJ::User'; + $hook->($u); + $last = $u; + } + } + $db->do("HANDLER user close"); + } else { + my $in = join(", ", map { $db->quote($_) } @$vals); + my $sth = $db->prepare("SELECT * FROM user WHERE $key IN ($in)"); + $sth->execute; + while (my $u = $sth->fetchrow_hashref) { + bless $u, 'LJ::User'; + $hook->($u); + $last = $u; + } + } + + return $last; +} + +# +# name: LJ::load_user +# des: Loads a user record given a username. +# info: From the [dbarg[user]] table. +# args: dbarg?, user, force? +# des-user: Username of user to load. +# des-force: if set to true, won't return cached user object and will +# query a dbh +# returns: Hashref with keys being columns of [dbtable[user]] table. +# +sub load_user +{ + &nodb; + my ($user, $force) = @_; + + $user = LJ::canonical_username($user); + return undef unless length $user; + + my $set_req_cache = sub { + my $u = shift; + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + return $u; + }; + + my $get_user = sub { + my $use_dbh = shift; + my $db = $use_dbh ? LJ::get_db_writer() : LJ::get_db_reader(); + my $u = _load_user_raw($db, "user", $user); + return $u unless $u && $use_dbh; + + # set caches since we got a u from the master + LJ::memcache_set_u($u); + return $set_req_cache->($u); + }; + + # caller is forcing a master, return now + return $get_user->("master") if $force; + + my $u; + + # return process cache if we have one + $u = $LJ::REQ_CACHE_USER_NAME{$user}; + return $u if $u; + + # check memcache + { + my $uid = LJ::MemCache::get("uidof:$user"); + $u = LJ::memcache_get_u([$uid, "userid:$uid"]); + return $set_req_cache->($u) if $u; + } + + # try to load from master if using memcache, otherwise from slave + $u = $get_user->(scalar @LJ::MEMCACHE_SERVERS); + return $u if $u; + + # setup LDAP handler if this is the first time + if ($LJ::LDAP_HOST && ! $LJ::AUTH_EXISTS) { + require LJ::LDAP; + $LJ::AUTH_EXISTS = sub { + my $user = shift; + my $rec = LJ::LDAP::load_ldap_user($user); + return $rec ? $rec : undef; + }; + } + + # if user doesn't exist in the LJ database, it's possible we're using + # an external authentication source and we should create the account + # implicitly. + my $lu; + if (ref $LJ::AUTH_EXISTS eq "CODE" && ($lu = $LJ::AUTH_EXISTS->($user))) + { + my $name = ref $lu eq "HASH" ? ($lu->{'nick'} || $lu->{name} || $user) : $user; + if (LJ::create_account({ + 'user' => $user, + 'name' => $name, + 'email' => ref $lu eq "HASH" ? $lu->{email} : "", + 'password' => "", + })) + { + # this should pull from the master, since it was _just_ created + return $get_user->("master"); + } + } + + return undef; +} + +# +# name: LJ::u_equals +# des: Compares two user objects to see if they're the same user. +# args: userobj1, userobj2 +# des-userobj1: First user to compare. +# des-userobj2: Second user to compare. +# returns: Boolean, true if userobj1 and userobj2 are defined and have equal userids. +# +sub u_equals { + my ($u1, $u2) = @_; + return $u1 && $u2 && $u1->{'userid'} == $u2->{'userid'}; +} + +# +# name: LJ::get_cluster_description +# des: Get descriptive text for a cluster id. +# args: clusterid, bold? +# des-clusterid: id of cluster to get description of +# des-bold: 1 == bold cluster name and subcluster id, else don't +# returns: string representing the cluster description +# +sub get_cluster_description { + my ($cid, $dobold) = @_; + $cid += 0; + my $text = LJ::run_hook('cluster_description', $cid, $dobold ? 1 : 0); + return $text if $text; + + # default behavior just returns clusterid + return $cid; +} + +sub memcache_get_u +{ + my @keys = @_; + my @ret; + foreach my $ar (values %{LJ::MemCache::get_multi(@keys) || {}}) { + my $u = LJ::MemCache::array_to_hash("user", $ar); + if ($u) { + bless $u, 'LJ::User'; + push @ret, $u; + } + } + return wantarray ? @ret : $ret[0]; +} + +sub memcache_set_u +{ + my $u = shift; + return unless $u; + my $expire = time() + 1800; + my $ar = LJ::MemCache::hash_to_array("user", $u); + return unless $ar; + LJ::MemCache::set([$u->{'userid'}, "userid:$u->{'userid'}"], $ar, $expire); + LJ::MemCache::set("uidof:$u->{user}", $u->{userid}); +} + +# +# name: LJ::load_userid +# des: Loads a user record given a userid. +# info: From the [dbarg[user]] table. +# args: dbarg?, userid, force? +# des-userid: Userid of user to load. +# des-force: if set to true, won't return cached user object and will +# query a dbh +# returns: Hashref with keys being columns of [dbtable[user]] table. +# +sub load_userid +{ + &nodb; + my ($userid, $force) = @_; + return undef unless $userid; + + my $set_req_cache = sub { + my $u = shift; + $LJ::REQ_CACHE_USER_NAME{$u->{'user'}} = $u; + $LJ::REQ_CACHE_USER_ID{$u->{'userid'}} = $u; + return $u; + }; + + my $get_user = sub { + my $use_dbh = shift; + my $db = $use_dbh ? LJ::get_db_writer() : LJ::get_db_reader(); + my $u = _load_user_raw($db, "userid", $userid); + return $u unless $u && $use_dbh; + + # set caches since we got a u from the master + LJ::memcache_set_u($u); + return $set_req_cache->($u); + }; + + # user is forcing master, return now + return $get_user->("master") if $force; + + my $u; + + # check process cache + $u = $LJ::REQ_CACHE_USER_ID{$userid}; + return $u if $u; + + # check memcache + $u = LJ::memcache_get_u([$userid,"userid:$userid"]); + return $set_req_cache->($u) if $u; + + # get from master if using memcache + return $get_user->("master") if @LJ::MEMCACHE_SERVERS; + + # check slave + $u = $get_user->(); + return $u if $u; + + # if we didn't get a u from the reader, fall back to master + return $get_user->("master"); +} + +# +# name: LJ::get_bio +# des: gets a user bio, from db or memcache +# args: u, force +# des-force: true to get data from cluster master +# returns: string +# +sub get_bio { + my ($u, $force) = @_; + return unless $u && $u->{'has_bio'} eq "Y"; + + my $bio; + + my $memkey = [$u->{'userid'}, "bio:$u->{'userid'}"]; + unless ($force) { + my $bio = LJ::MemCache::get($memkey); + return $bio if defined $bio; + } + + # not in memcache, fall back to disk + my $db = @LJ::MEMCACHE_SERVERS || $force ? + LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + $bio = $db->selectrow_array("SELECT bio FROM userbio WHERE userid=?", + undef, $u->{'userid'}); + + # set in memcache + LJ::MemCache::add($memkey, $bio); + + return $bio; +} + +# +# name: LJ::load_moods +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub load_moods +{ + return if $LJ::CACHED_MOODS; + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT moodid, mood, parentmood FROM moods"); + $sth->execute; + while (my ($id, $mood, $parent) = $sth->fetchrow_array) { + $LJ::CACHE_MOODS{$id} = { 'name' => $mood, 'parent' => $parent, 'id' => $id }; + if ($id > $LJ::CACHED_MOOD_MAX) { $LJ::CACHED_MOOD_MAX = $id; } + } + $LJ::CACHED_MOODS = 1; +} + +# +# name: LJ::do_to_cluster +# des: Given a subref, this function will pick a random cluster and run the subref, +# passing it the cluster id. If the subref returns a 1, this function will exit +# with a 1. Else, the function will call the subref again, with the next cluster. +# args: subref +# des-subref: Reference to a sub to call; @_ = (clusterid) +# returns: 1 if the subref returned a 1 at some point, undef if it didn't ever return +# success and we tried every cluster. +# +sub do_to_cluster { + my $subref = shift; + + # start at some random point and iterate through the clusters one by one until + # $subref returns a true value + my $size = @LJ::CLUSTERS; + my $start = int(rand() * $size); + my $rval = undef; + my $tries = $size > 15 ? 15 : $size; + foreach (1..$tries) { + # select at random + my $idx = $start++ % $size; + + # get subref value + $rval = $subref->($LJ::CLUSTERS[$idx]); + last if $rval; + } + + # return last rval + return $rval; +} + +# +# name: LJ::mark_dirty +# des: Marks a given user as being $what type of dirty +# args: u, what +# des-what: type of dirty being marked (EG 'friends') +# returns: 1 +# +sub mark_dirty { + my ($uuserid, $what) = @_; + + my $userid = LJ::want_userid($uuserid); + return 1 if $LJ::REQ_CACHE_DIRTY{$what}->{$userid}; + + my $u = LJ::want_user($userid); + + # friends dirtiness is only necessary to track + # if we're exchange XMLRPC with fotobilder + if ($what eq 'friends' && $LJ::FB_SITEROOT) { + push @LJ::CLEANUP_HANDLERS, sub { + my $res = LJ::cmd_buffer_add($u->{clusterid}, $u->{userid}, 'dirty', { what => 'friends' }); + }; + } else { + return 1; + } + + $LJ::REQ_CACHE_DIRTY{$what}->{$userid}++; + + return 1; +} + +# +# name: LJ::cmd_buffer_add +# des: Schedules some command to be run sometime in the future which would +# be too slow to do syncronously with the web request. An example +# is deleting a journal entry, which requires recursing through a lot +# of tables and deleting all the appropriate stuff. +# args: db, journalid, cmd, hargs +# des-db: Global db handle to run command on, or user clusterid if cluster +# des-journalid: Journal id command affects. This is indexed in the +# [dbtable[cmdbuffer]] table so that all of a user's queued +# actions can be run before that user is potentially moved +# between clusters. +# des-cmd: Text of the command name. 30 chars max. +# des-hargs: Hashref of command arguments. +# +sub cmd_buffer_add +{ + my ($db, $journalid, $cmd, $args) = @_; + + return 0 unless $cmd; + + my $cid = ref $db ? 0 : $db+0; + $db = $cid ? LJ::get_cluster_master($cid) : $db; + my $ab = $LJ::CLUSTER_PAIR_ACTIVE{$cid}; + + return 0 unless $db; + + my $arg_str; + if (ref $args eq 'HASH') { + foreach (sort keys %$args) { + $arg_str .= LJ::eurl($_) . "=" . LJ::eurl($args->{$_}) . "&"; + } + chop $arg_str; + } else { + $arg_str = $args || ""; + } + + my $rv; + if ($ab eq 'a' || $ab eq 'b') { + # get a lock + my $locked = $db->selectrow_array("SELECT GET_LOCK('cmd-buffer-$cid',10)"); + return 0 unless $locked; # 10 second timeout elapsed + + # a or b -- a goes odd, b goes even! + my $max = $db->selectrow_array('SELECT MAX(cbid) FROM cmdbuffer'); + $max += $ab eq 'a' ? ($max & 1 ? 2 : 1) : ($max & 1 ? 1 : 2); + + # insert command + $db->do('INSERT INTO cmdbuffer (cbid, journalid, instime, cmd, args) ' . + 'VALUES (?, ?, NOW(), ?, ?)', undef, + $max, $journalid, $cmd, $arg_str); + $rv = $db->err ? 0 : 1; + + # release lock + $db->selectrow_array("SELECT RELEASE_LOCK('cmd-buffer-$cid')"); + } else { + # old method + $db->do("INSERT INTO cmdbuffer (journalid, cmd, instime, args) ". + "VALUES (?, ?, NOW(), ?)", undef, + $journalid, $cmd, $arg_str); + $rv = $db->err ? 0 : 1; + } + + return $rv; +} + +# +# name: LJ::journal_base +# des: Returns URL of a user's journal. +# info: The tricky thing is that users with underscores in their usernames +# can't have some_user.site.com as a hostname, so that's changed into +# some-user.site.com. +# args: uuser, vhost? +# des-uuser: User hashref or username of user whose URL to make. +# des-vhost: What type of URL. Acceptable options are "users", to make a +# http://user.site.com/ URL; "tilde" to make http://site.com/~user/; +# "community" for http://site.com/community/user; or the default +# will be http://site.com/users/user. If unspecifed and uuser +# is a user hashref, then the best/preferred vhost will be chosen. +# returns: scalar; a URL. +# +sub journal_base +{ + my ($user, $vhost) = @_; + if (isu($user)) { + my $u = $user; + $user = $u->{'user'}; + unless (defined $vhost) { + if ($LJ::FRONTPAGE_JOURNAL eq $user) { + $vhost = "front"; + } elsif ($u->{'journaltype'} eq "P") { + $vhost = ""; + } elsif ($u->{'journaltype'} eq "C") { + $vhost = "community"; + } + + } + } + if ($vhost eq "users") { + my $he_user = $user; + $he_user =~ s/_/-/g; + return "http://$he_user.$LJ::USER_DOMAIN"; + } elsif ($vhost eq "tilde") { + return "$LJ::SITEROOT/~$user"; + } elsif ($vhost eq "community") { + return "$LJ::SITEROOT/community/$user"; + } elsif ($vhost eq "front") { + return $LJ::SITEROOT; + } elsif ($vhost =~ /^other:(.+)/) { + return "http://$1"; + } else { + return "$LJ::SITEROOT/users/$user"; + } +} + + +# loads all of the given privs for a given user into a hashref +# inside the user record ($u->{_privs}->{$priv}->{$arg} = 1) +# +# name: LJ::load_user_privs +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub load_user_privs +{ + &nodb; + my $remote = shift; + my @privs = @_; + return unless $remote and @privs; + + # return if we've already loaded these privs for this user. + @privs = grep { ! $remote->{'_privloaded'}->{$_} } @privs; + return unless @privs; + + my $dbr = LJ::get_db_reader(); + return unless $dbr; + foreach (@privs) { $remote->{'_privloaded'}->{$_}++; } + @privs = map { $dbr->quote($_) } @privs; + my $sth = $dbr->prepare("SELECT pl.privcode, pm.arg ". + "FROM priv_map pm, priv_list pl ". + "WHERE pm.prlid=pl.prlid AND ". + "pl.privcode IN (" . join(',',@privs) . ") ". + "AND pm.userid=$remote->{'userid'}"); + $sth->execute; + while (my ($priv, $arg) = $sth->fetchrow_array) { + unless (defined $arg) { $arg = ""; } # NULL -> "" + $remote->{'_priv'}->{$priv}->{$arg} = 1; + } +} + +# +# name: LJ::check_priv +# des: Check to see if a user has a certain privilege. +# info: Usually this is used to check the privs of a $remote user. +# See [func[LJ::get_remote]]. As such, a $u argument of undef +# is okay to pass: 0 will be returned, as an unknown user can't +# have any rights. +# args: dbarg?, u, priv, arg? +# des-priv: Priv name to check for (see [dbtable[priv_list]]) +# des-arg: Optional argument. If defined, function only returns true +# when $remote has a priv of type $priv also with arg $arg, not +# just any priv of type $priv, which is the behavior without +# an $arg +# returns: boolean; true if user has privilege +# +sub check_priv +{ + &nodb; + my ($u, $priv, $arg) = @_; + return 0 unless $u; + + if (! $u->{'_privloaded'}->{$priv}) { + LJ::load_user_privs($u, $priv); + } + + if (defined $arg) { + return (defined $u->{'_priv'}->{$priv} && + defined $u->{'_priv'}->{$priv}->{$arg}); + } else { + return (defined $u->{'_priv'}->{$priv}); + } +} + +# +# +# +# name: LJ::remote_has_priv +# class: +# des: Check to see if the given remote user has a certain priviledge +# info: DEPRECATED. should use load_user_privs + check_priv +# args: +# des-: +# returns: +# +sub remote_has_priv +{ + &nodb; + my $remote = shift; + my $privcode = shift; # required. priv code to check for. + my $ref = shift; # optional, arrayref or hashref to populate + return 0 unless ($remote); + + ### authentication done. time to authorize... + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT pm.arg FROM priv_map pm, priv_list pl WHERE pm.prlid=pl.prlid AND pl.privcode=? AND pm.userid=?"); + $sth->execute($privcode, $remote->{'userid'}); + + my $match = 0; + if (ref $ref eq "ARRAY") { @$ref = (); } + if (ref $ref eq "HASH") { %$ref = (); } + while (my ($arg) = $sth->fetchrow_array) { + $match++; + if (ref $ref eq "ARRAY") { push @$ref, $arg; } + if (ref $ref eq "HASH") { $ref->{$arg} = 1; } + } + return $match; +} + +# +# name: LJ::get_userid +# des: Returns a userid given a username. +# info: Results cached in memory. On miss, does DB call. Not advised +# to use this many times in a row... only once or twice perhaps +# per request. Tons of serialized db requests, even when small, +# are slow. Opposite of [func[LJ::get_username]]. +# args: dbarg?, user +# des-user: Username whose userid to look up. +# returns: Userid, or 0 if invalid user. +# +sub get_userid +{ + &nodb; + my $user = shift; + + $user = LJ::canonical_username($user); + + if ($LJ::CACHE_USERID{$user}) { return $LJ::CACHE_USERID{$user}; } + + my $userid = LJ::MemCache::get("uidof:$user"); + return $LJ::CACHE_USERID{$user} = $userid if $userid; + + my $dbr = LJ::get_db_reader(); + $userid = $dbr->selectrow_array("SELECT userid FROM useridmap WHERE user=?", undef, $user); + + # implictly create an account if we're using an external + # auth mechanism + if (! $userid && ref $LJ::AUTH_EXISTS eq "CODE") + { + $userid = LJ::create_account({ 'user' => $user, + 'name' => $user, + 'password' => '', }); + } + + if ($userid) { + $LJ::CACHE_USERID{$user} = $userid; + LJ::MemCache::set("uidof:$user", $userid); + } + + return ($userid+0); +} + +# +# name: LJ::want_userid +# des: Returns userid when passed either userid or the user hash. Useful to functions that +# want to accept either. Forces its return value to be a number (for safety). +# args: userid +# des-userid: Either a userid, or a user hash with the userid in its 'userid' key. +# returns: The userid, guaranteed to be a numeric value. +# +sub want_userid +{ + my $uuserid = shift; + return ($uuserid->{'userid'} + 0) if ref $uuserid; + return ($uuserid + 0); +} + +# +# name: LJ::want_user +# des: Returns user object when passed either userid or the user hash. Useful to functions that +# want to accept either. +# args: user +# des-user: Either a userid, or a user hash with the userid in its 'userid' key. +# returns: The user hash represented by said userid. +# +sub want_user +{ + my $uuser = shift; + return $uuser if ref $uuser; + return LJ::load_userid($uuser+0); +} + +# +# name: LJ::get_username +# des: Returns a username given a userid. +# info: Results cached in memory. On miss, does DB call. Not advised +# to use this many times in a row... only once or twice perhaps +# per request. Tons of serialized db requests, even when small, +# are slow. Opposite of [func[LJ::get_userid]]. +# args: dbarg?, user +# des-user: Username whose userid to look up. +# returns: Userid, or 0 if invalid user. +# +sub get_username +{ + &nodb; + my $userid = shift; + $userid += 0; + + # Checked the cache first. + if ($LJ::CACHE_USERNAME{$userid}) { return $LJ::CACHE_USERNAME{$userid}; } + + # if we're using memcache, it's faster to just query memcache for + # an entire $u object and just return the username. otherwise, we'll + # go ahead and query useridmap + if (@LJ::MEMCACHE_SERVERS) { + my $u = LJ::load_userid($userid); + return undef unless $u; + + $LJ::CACHE_USERNAME{$userid} = $u->{'user'}; + return $u->{'user'}; + } + + my $dbr = LJ::get_db_reader(); + my $user = $dbr->selectrow_array("SELECT user FROM useridmap WHERE userid=?", undef, $userid); + + # Fall back to master if it doesn't exist. + unless (defined $user) { + my $dbh = LJ::get_db_writer(); + $user = $dbh->selectrow_array("SELECT user FROM useridmap WHERE userid=?", undef, $userid); + } + + return undef unless defined $user; + + $LJ::CACHE_USERNAME{$userid} = $user; + return $user; +} + +sub get_itemid_near2 +{ + my $u = shift; + my $jitemid = shift; + my $after_before = shift; + + $jitemid += 0; + + my ($inc, $order); + if ($after_before eq "after") { + ($inc, $order) = (-1, "DESC"); + } elsif ($after_before eq "before") { + ($inc, $order) = (1, "ASC"); + } else { + return 0; + } + + my $dbr = LJ::get_cluster_reader($u); + my $jid = $u->{'userid'}+0; + my $field = $u->{'journaltype'} eq "P" ? "revttime" : "rlogtime"; + + my $stime = $dbr->selectrow_array("SELECT $field FROM log2 WHERE ". + "journalid=$jid AND jitemid=$jitemid"); + return 0 unless $stime; + + + my $day = 86400; + foreach my $distance ($day, $day*7, $day*30, $day*90) { + my ($one_away, $further) = ($stime + $inc, $stime + $inc*$distance); + if ($further < $one_away) { + # swap them, BETWEEN needs lower number first + ($one_away, $further) = ($further, $one_away); + } + my ($id, $anum) = + $dbr->selectrow_array("SELECT jitemid, anum FROM log2 WHERE journalid=$jid ". + "AND $field BETWEEN $one_away AND $further ". + "ORDER BY $field $order LIMIT 1"); + if ($id) { + return wantarray() ? ($id, $anum) : ($id*256 + $anum); + } + } + return 0; +} + +sub get_itemid_after2 { return get_itemid_near2(@_, "after"); } +sub get_itemid_before2 { return get_itemid_near2(@_, "before"); } + + +# +# name: LJ::mysql_time +# des: +# class: time +# info: +# args: +# des-: +# returns: +# +sub mysql_time +{ + my ($time, $gmt) = @_; + $time ||= time(); + my @ltime = $gmt ? gmtime($time) : localtime($time); + return sprintf("%04d-%02d-%02d %02d:%02d:%02d", + $ltime[5]+1900, + $ltime[4]+1, + $ltime[3], + $ltime[2], + $ltime[1], + $ltime[0]); +} + +# gets date in MySQL format, produces s2dateformat +# s1 dateformat is: +# "%a %W %b %M %y %Y %c %m %e %d %D %p %i %l %h %k %H" +# sample string: +# Tue Tuesday Sep September 03 2003 9 09 30 30 30th AM 22 9 09 9 09 +# Thu Thursday Oct October 03 2003 10 10 2 02 2nd AM 33 9 09 9 09 + +sub alldatepart_s1 +{ + my $time = shift; + my ($sec,$min,$hour,$mday,$mon,$year,$wday) = + gmtime(LJ::mysqldate_to_time($time, 1)); + my $ret = ""; + + $ret .= LJ::Lang::day_short($wday+1) . " " . + LJ::Lang::day_long($wday+1) . " " . + LJ::Lang::month_short($mon+1) . " " . + LJ::Lang::month_long($mon+1) . " " . + sprintf("%02d %04d %d %02d %d %02d %d%s ", + $year % 100, $year + 1900, $mon+1, $mon+1, + $mday, $mday, $mday, LJ::Lang::day_ord($mday)); + $ret .= $hour < 12 ? "AM " : "PM "; + $ret .= sprintf("%02d %d %02d %d %02d", $min, + ($hour+11)%12 + 1, + ($hour+ 11)%12 +1, + $hour, + $hour); + + return $ret; +} + + +# gets date in MySQL format, produces s2dateformat +# s2 dateformat is: yyyy mm dd hh mm ss day_of_week +sub alldatepart_s2 +{ + my $time = shift; + my ($sec,$min,$hour,$mday,$mon,$year,$wday) = + gmtime(LJ::mysqldate_to_time($time, 1)); + return + sprintf("%04d %02d %02d %02d %02d %02d %01d", + $year+1900, + $mon+1, + $mday, + $hour, + $min, + $sec, + $wday); +} + + +# +# name: LJ::get_keyword_id +# class: +# des: Get the id for a keyword. +# args: uuid?, keyword, autovivify? +# des-uuid: User object or userid to use. Pass this only if you want to use the userkeywords +# clustered table! If you do not pass user information, the keywords table on the global +# will be used. +# des-keyword: A string keyword to get the id of. +# returns: Returns a kwid into keywords or userkeywords, depending on if you passed a user or +# not. If the keyword doesn't exist, it is automatically created for you. +# des-autovivify: If present and 1, automatically create keyword. If present and 0, do not +# automatically create the keyword. If not present, default behavior is the old style -- +# yes, do automatically create the keyword. +# +sub get_keyword_id +{ + &nodb; + + # see if we got a user? if so we use userkeywords on a cluster + my $u; + if (@_ >= 2) { + $u = LJ::want_user(shift); + return undef unless $u; + } + + my ($kw, $autovivify) = @_; + $autovivify = 1 unless defined $autovivify; + + # setup the keyword for use + unless ($kw =~ /\S/) { return 0; } + $kw = LJ::text_trim($kw, LJ::BMAX_KEYWORD, LJ::CMAX_KEYWORD); + + # get the keyword and insert it if necessary + my $kwid; + if ($u && $u->{dversion} > 5) { + # new style userkeywords -- but only if the user has the right dversion + $kwid = $u->selectrow_array('SELECT kwid FROM userkeywords WHERE userid = ? AND keyword = ?', + undef, $u->{userid}, $kw) + 0; + if ($autovivify && ! $kwid) { + # create a new keyword + $kwid = LJ::alloc_user_counter($u, 'K'); + return undef unless $kwid; + + # attempt to insert the keyword + my $rv = $u->do("INSERT IGNORE INTO userkeywords (userid, kwid, keyword) VALUES (?, ?, ?)", + undef, $u->{userid}, $kwid, $kw) + 0; + return undef if $u->err; + + # at this point, if $rv is 0, the keyword is already there so try again + unless ($rv) { + $kwid = $u->selectrow_array('SELECT kwid FROM userkeywords WHERE userid = ? AND keyword = ?', + undef, $u->{userid}, $kw) + 0; + } + } + } else { + # old style global + my $dbh = LJ::get_db_writer(); + my $qkw = $dbh->quote($kw); + + # Making this a $dbr could cause problems due to the insertion of + # data based on the results of this query. Leave as a $dbh. + $kwid = $dbh->selectrow_array("SELECT kwid FROM keywords WHERE keyword=$qkw"); + if ($autovivify && ! $kwid) { + $dbh->do("INSERT INTO keywords (kwid, keyword) VALUES (NULL, $qkw)"); + $kwid = $dbh->{'mysql_insertid'}; + } + } + return $kwid; +} + +# +# name: LJ::trim +# class: text +# des: Removes whitespace from left and right side of a string. +# args: string +# des-string: string to be trimmed +# returns: string trimmed +# +sub trim +{ + my $a = $_[0]; + $a =~ s/^\s+//; + $a =~ s/\s+$//; + return $a; +} + +# +# name: LJ::delete_user +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub delete_user +{ + # TODO: Is this function even being called? + # It doesn't look like it does anything useful + my $dbh = shift; + my $user = shift; + my $quser = $dbh->quote($user); + my $sth; + $sth = $dbh->prepare("SELECT user, userid FROM useridmap WHERE user=$quser"); + my $u = $sth->fetchrow_hashref; + unless ($u) { return; } + + ### so many issues. +} + +# +# name: LJ::hash_password +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub hash_password +{ + return Digest::MD5::md5_hex($_[0]); +} + +# +# name: LJ::can_use_journal +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub can_use_journal +{ + &nodb; + my ($posterid, $reqownername, $res) = @_; + + ## find the journal owner's info + my $uowner = LJ::load_user($reqownername); + unless ($uowner) { + $res->{'errmsg'} = "Journal \"$reqownername\" does not exist."; + return 0; + } + my $ownerid = $uowner->{'userid'}; + + # the 'ownerid' necessity came first, way back when. but then + # with clusters, everything needed to know more, like the + # journal's dversion and clusterid, so now it also returns the + # user row. + $res->{'ownerid'} = $ownerid; + $res->{'u_owner'} = $uowner; + + ## check if user has access + return 1 if LJ::check_rel($ownerid, $posterid, 'P'); + + # let's check if this community is allowing post access to non-members + LJ::load_user_props($uowner, "nonmember_posting"); + if ($uowner->{'nonmember_posting'}) { + my $dbr = LJ::get_db_reader() or die "nodb"; + my $postlevel = $dbr->selectrow_array("SELECT postlevel FROM ". + "community WHERE userid=$ownerid"); + return 1 if $postlevel eq 'members'; + } + + # is the poster an admin for this community? + return 1 if LJ::can_manage($posterid, $uowner); + + $res->{'errmsg'} = "You do not have access to post to this journal."; + return 0; +} + +sub set_logprop +{ + my ($u, $jitemid, $hashref, $logprops) = @_; # hashref to set, hashref of what was done + + $jitemid += 0; + my $uid = $u->{'userid'} + 0; + my $kill_mem = 0; + my $del_ids; + my $ins_values; + while (my ($k, $v) = each %{$hashref||{}}) { + my $prop = LJ::get_prop("log", $k); + next unless $prop; + $kill_mem = 1 unless $prop eq "commentalter"; + if ($v) { + $ins_values .= "," if $ins_values; + $ins_values .= "($uid, $jitemid, $prop->{'id'}, " . $u->quote($v) . ")"; + $logprops->{$k} = $v; + } else { + $del_ids .= "," if $del_ids; + $del_ids .= $prop->{'id'}; + } + } + + $u->do("REPLACE INTO logprop2 (journalid, jitemid, propid, value) ". + "VALUES $ins_values") if $ins_values; + $u->do("DELETE FROM logprop2 WHERE journalid=? AND jitemid=? ". + "AND propid IN ($del_ids)", undef, $u->{'userid'}, $jitemid) if $del_ids; + + LJ::MemCache::delete([$uid,"logprop:$uid:$jitemid"]) if $kill_mem; +} + +# +# name: LJ::load_log_props2 +# class: +# des: +# info: +# args: db?, uuserid, listref, hashref +# des-: +# returns: +# +sub load_log_props2 +{ + my $db = isdb($_[0]) ? shift @_ : undef; + + my ($uuserid, $listref, $hashref) = @_; + my $userid = want_userid($uuserid); + return unless ref $hashref eq "HASH"; + + my %needprops; + my %needrc; + my %rc; + my @memkeys; + foreach (@$listref) { + my $id = $_+0; + $needprops{$id} = 1; + $needrc{$id} = 1; + push @memkeys, [$userid, "logprop:$userid:$id"]; + push @memkeys, [$userid, "rp:$userid:$id"]; + } + return unless %needprops || %needrc; + + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $k =~ /(\w+):(\d+):(\d+)/; + if ($1 eq 'logprop') { + next unless ref $v eq "HASH"; + delete $needprops{$3}; + $hashref->{$3} = $v; + } + if ($1 eq 'rp') { + delete $needrc{$3}; + $rc{$3} = int($v); # change possible "0 " (true) to "0" (false) + } + } + + foreach (keys %rc) { + $hashref->{$_}{'replycount'} = $rc{$_}; + } + + return unless %needprops || %needrc; + + unless ($db) { + my $u = LJ::load_userid($userid); + $db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + return unless $db; + } + + if (%needprops) { + LJ::load_props("log"); + my $in = join(",", keys %needprops); + my $sth = $db->prepare("SELECT jitemid, propid, value FROM logprop2 ". + "WHERE journalid=? AND jitemid IN ($in)"); + $sth->execute($userid); + while (my ($jitemid, $propid, $value) = $sth->fetchrow_array) { + $hashref->{$jitemid}->{$LJ::CACHE_PROPID{'log'}->{$propid}->{'name'}} = $value; + } + foreach my $id (keys %needprops) { + LJ::MemCache::set([$userid,"logprop:$userid:$id"], $hashref->{$id} || {}); + } + } + + if (%needrc) { + my $in = join(",", keys %needrc); + my $sth = $db->prepare("SELECT jitemid, replycount FROM log2 WHERE journalid=? AND jitemid IN ($in)"); + $sth->execute($userid); + while (my ($jitemid, $rc) = $sth->fetchrow_array) { + $hashref->{$jitemid}->{'replycount'} = $rc; + LJ::MemCache::add([$userid, "rp:$userid:$jitemid"], $rc); + } + } + + +} + +# +# name: LJ::load_log_props2multi +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub load_log_props2multi +{ + &nodb; + my ($ids, $props) = @_; + _get_posts_raw_wrapper($ids, "prop", $props); +} + +# +# name: LJ::load_talk_props2 +# class: +# des: +# info: +# args: +# des-: +# returns: +# +sub load_talk_props2 +{ + my $db = isdb($_[0]) ? shift @_ : undef; + my ($uuserid, $listref, $hashref) = @_; + + my $userid = want_userid($uuserid); + my $u = ref $uuserid ? $uuserid : undef; + + $hashref = {} unless ref $hashref eq "HASH"; + + my %need; + my @memkeys; + foreach (@$listref) { + my $id = $_+0; + $need{$id} = 1; + push @memkeys, [$userid,"talkprop:$userid:$id"]; + } + return $hashref unless %need; + + my $mem = LJ::MemCache::get_multi(@memkeys) || {}; + while (my ($k, $v) = each %$mem) { + next unless $k =~ /(\d+):(\d+)/ && ref $v eq "HASH"; + delete $need{$2}; + $hashref->{$2}->{$_[0]} = $_[1] while @_ = each %$v; + } + return $hashref unless %need; + + if (!$db || @LJ::MEMCACHE_SERVERS) { + $u ||= LJ::load_userid($userid); + $db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + return $hashref unless $db; + } + + LJ::load_props("talk"); + my $in = join(',', keys %need); + my $sth = $db->prepare("SELECT jtalkid, tpropid, value FROM talkprop2 ". + "WHERE journalid=? AND jtalkid IN ($in)"); + $sth->execute($userid); + while (my ($jtalkid, $propid, $value) = $sth->fetchrow_array) { + my $p = $LJ::CACHE_PROPID{'talk'}->{$propid}; + next unless $p; + $hashref->{$jtalkid}->{$p->{'name'}} = $value; + } + foreach my $id (keys %need) { + LJ::MemCache::set([$userid,"talkprop:$userid:$id"], $hashref->{$id} || {}); + } + return $hashref; +} + +# +# name: LJ::eurl +# class: text +# des: Escapes a value before it can be put in a URL. See also [func[LJ::durl]]. +# args: string +# des-string: string to be escaped +# returns: string escaped +# +sub eurl +{ + my $a = $_[0]; + $a =~ s/([^a-zA-Z0-9_\,\-.\/\\\: ])/uc sprintf("%%%02x",ord($1))/eg; + $a =~ tr/ /+/; + return $a; +} + +# +# name: LJ::durl +# class: text +# des: Decodes a value that's URL-escaped. See also [func[LJ::eurl]]. +# args: string +# des-string: string to be decoded +# returns: string decoded +# +sub durl +{ + my ($a) = @_; + $a =~ tr/+/ /; + $a =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + return $a; +} + +# +# name: LJ::exml +# class: text +# des: Escapes a value before it can be put in XML. +# args: string +# des-string: string to be escaped +# returns: string escaped. +# +sub exml +{ + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[&\"\'<>\x00-\x08\x0B\x0C\x0E-\x1F]/; + # what are those character ranges? XML 1.0 allows: + # #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + + my $a = shift; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/'/g; + $a =~ s//>/g; + $a =~ s/[\x00-\x08\x0B\x0C\x0E-\x1F]//g; + return $a; +} + +# +# name: LJ::ehtml +# class: text +# des: Escapes a value before it can be put in HTML. +# args: string +# des-string: string to be escaped +# returns: string escaped. +# +sub ehtml +{ + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[&\"\'<>]/; + + # this is faster than doing one substitution with a map: + my $a = $_[0]; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} +*eall = \&ehtml; # old BML syntax required eall to also escape BML. not anymore. + +# +# name: LJ::etags +# class: text +# des: Escapes < and > from a string +# args: string +# des-string: string to be escaped +# returns: string escaped. +# +sub etags +{ + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[<>]/; + + my $a = $_[0]; + $a =~ s//>/g; + return $a; +} + +# +# name: LJ::ejs +# class: text +# des: Escapes a string value before it can be put in JavaScript. +# args: string +# des-string: string to be escaped +# returns: string escaped. +# +sub ejs +{ + my $a = $_[0]; + $a =~ s/[\"\'\\]/\\$&/g; + $a =~ s/\r?\n/\\n/gs; + $a =~ s/\r//; + return $a; +} + +# +# name: LJ::days_in_month +# class: time +# des: Figures out the number of days in a month. +# args: month, year? +# des-month: Month +# des-year: Year. Necessary for February. If undefined or zero, function +# will return 29. +# returns: Number of days in that month in that year. +# +sub days_in_month +{ + my ($month, $year) = @_; + if ($month == 2) + { + return 29 unless $year; # assume largest + if ($year % 4 == 0) + { + # years divisible by 400 are leap years + return 29 if ($year % 400 == 0); + + # if they're divisible by 100, they aren't. + return 28 if ($year % 100 == 0); + + # otherwise, if divisible by 4, they are. + return 29; + } + } + return ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[$month-1]); +} + +sub day_of_week +{ + my ($year, $month, $day) = @_; + my $time = Time::Local::timelocal(0,0,0,$day,$month-1,$year); + return (localtime($time))[6]; +} + +# +# name: LJ::delete_entry +# des: Deletes a user's journal entry +# args: uuserid, jitemid, quick?, anum? +# des-uuserid: Journal itemid or $u object of journal to delete entry from +# des-jitemid: Journal itemid of item to delete. +# des-quick: Optional boolean. If set, only [dbtable[log2]] table +# is deleted from and the rest of the content is deleted +# later using [func[LJ::cmd_buffer_add]]. +# des-anum: The log item's anum, which'll be needed to delete lazily +# some data in tables which includes the anum, but the +# log row will already be gone so we'll need to store it for later. +# returns: boolean; 1 on success, 0 on failure. +# +sub delete_entry +{ + my ($uuserid, $jitemid, $quick, $anum) = @_; + my $jid = LJ::want_userid($uuserid); + my $u = ref $uuserid ? $uuserid : LJ::load_userid($jid); + $jitemid += 0; + + my $and; + if (defined $anum) { $and = "AND anum=" . ($anum+0); } + + my $dc = $u->log2_do(undef, "DELETE FROM log2 WHERE journalid=$jid AND jitemid=$jitemid $and"); + return 0 unless $dc; + LJ::MemCache::delete([$jid, "log2:$jid:$jitemid"]); + LJ::MemCache::decr([$jid, "log2ct:$jid"]); + LJ::memcache_kill($jid, "dayct"); + + # delete tags + LJ::Tags::delete_logtags($u, $jitemid); + + # if this is running the second time (started by the cmd buffer), + # the log2 row will already be gone and we shouldn't check for it. + if ($quick) { + return 1 if $dc < 1; # already deleted? + return LJ::cmd_buffer_add($u->{clusterid}, $jid, "delitem", { + 'itemid' => $jitemid, + 'anum' => $anum, + }); + } + + # delete from clusters + foreach my $t (qw(logtext2 logprop2 logsec2)) { + $u->do("DELETE FROM $t WHERE journalid=$jid AND jitemid=$jitemid"); + } + $u->dudata_set('L', $jitemid, 0); + + # delete all comments + LJ::delete_all_comments($u, 'L', $jitemid); + + return 1; +} + +# +# name: LJ::mark_entry_as_spam +# class: web +# des: Copies an entry in a community into the global spamreports table +# args: journalu, jitemid +# des-journalu: User object of journal (community) entry was posted in. +# des-jitemid: ID of this entry. +# returns: 1 for success, 0 for failure +# +sub mark_entry_as_spam { + my ($journalu, $jitemid) = @_; + $journalu = LJ::want_user($journalu); + $jitemid += 0; + return 0 unless $journalu && $jitemid; + + my $dbcr = LJ::get_cluster_def_reader($journalu); + my $dbh = LJ::get_db_writer(); + return 0 unless $dbcr && $dbh; + + my $item = LJ::get_log2_row($journalu, $jitemid); + return 0 unless $item; + + # step 1: get info we need + my $logtext = LJ::get_logtext2($journalu, $jitemid); + my ($subject, $body, $posterid) = ($logtext->{$jitemid}[0], $logtext->{$jitemid}[1], $item->{posterid}); + return 0 unless $body; + + # step 2: insert into spamreports + $dbh->do('INSERT INTO spamreports (reporttime, posttime, journalid, posterid, subject, body, report_type) ' . + 'VALUES (UNIX_TIMESTAMP(), UNIX_TIMESTAMP(?), ?, ?, ?, ?, \'entry\')', + undef, $item->{logtime}, $journalu->{userid}, $posterid, $subject, $body); + + return 0 if $dbh->err; + return 1; +} + +# +# name: LJ::delete_all_comments +# des: deletes all comments from a post, permanently, for when a post is deleted +# info: The tables [dbtable[talk2]], [dbtable[talkprop2]], [dbtable[talktext2]], +# are deleted from, immediately. +# args: u, nodetype, nodeid +# des-nodetype: The thread nodetype (probably 'L' for log items) +# des-nodeid: The thread nodeid for the given nodetype (probably the jitemid from the log2 row) +# returns: boolean; success value +# +sub delete_all_comments { + my ($u, $nodetype, $nodeid) = @_; + + my $dbcm = LJ::get_cluster_master($u); + return 0 unless $dbcm && $u->writer; + + # delete comments + my ($t, $loop) = (undef, 1); + my $chunk_size = 200; + while ($loop && + ($t = $dbcm->selectcol_arrayref("SELECT jtalkid FROM talk2 WHERE ". + "nodetype=? AND journalid=? ". + "AND nodeid=? LIMIT $chunk_size", undef, + $nodetype, $u->{'userid'}, $nodeid)) + && $t && @$t) + { + my $in = join(',', map { $_+0 } @$t); + return 1 unless $in; + foreach my $table (qw(talkprop2 talktext2 talk2)) { + $u->do("DELETE FROM $table WHERE journalid=? AND jtalkid IN ($in)", + undef, $u->{'userid'}); + } + # decrement memcache + LJ::MemCache::decr([$u->{'userid'}, "talk2ct:$u->{'userid'}"], scalar(@$t)); + $loop = 0 unless @$t == $chunk_size; + } + return 1; + +} + +# +# name: LJ::memcache_kill +# des: Kills a memcache entry, given a userid and type +# args: uuserid, type +# des-uuserid: a userid or u object +# des-args: memcache key type, will be used as "$type:$userid" +# returns: results of LJ::MemCache::delete +# +sub memcache_kill { + my ($uuid, $type) = @_; + my $userid = want_userid($uuid); + return undef unless $userid && $type; + + return LJ::MemCache::delete([$userid, "$type:$userid"]); +} + + +# +# name: LJ::blocking_report +# des: Log a report on the total amount of time used in a slow operation to a +# remote host via UDP. +# args: host, time, notes, type +# des-host: The DB host the operation used. +# des-type: The type of service the operation was talking to (e.g., 'database', +# 'memcache', etc.) +# des-time: The amount of time (in floating-point seconds) the operation took. +# des-notes: A short description of the operation. +# +sub blocking_report { + my ( $host, $type, $time, $notes ) = @_; + + if ( $LJ::DB_LOG_HOST ) { + unless ( $LJ::ReportSock ) { + my ( $host, $port ) = split /:/, $LJ::DB_LOG_HOST, 2; + return unless $host && $port; + + $LJ::ReportSock = new IO::Socket::INET ( + PeerPort => $port, + Proto => 'udp', + PeerAddr => $host + ) or return; + } + + my $msg = join( "\x3", $host, $type, $time, $notes ); + $LJ::ReportSock->send( $msg ); + } +} + +# +# name: LJ::_friends_do +# des: Runs given sql, then deletes the given userid's friends from memcache +# args: uuserid, sql, args +# des-uuserid: a userid or u object +# des-sql: sql to run via $dbh->do() +# des-args: a list of arguments to pass use via: $dbh->do($sql, undef, @args) +# returns: return false on error +# +sub _friends_do { + my ($uuid, $sql, @args) = @_; + my $uid = want_userid($uuid); + return undef unless $uid && $sql; + + my $dbh = LJ::get_db_writer() or return 0; + + my $ret = $dbh->do($sql, undef, @args); + return 0 if $dbh->err; + + LJ::memcache_kill($uid, "friends"); + + # pass $uuid in case it's a $u object which mark_dirty wants + LJ::mark_dirty($uuid, "friends"); + + return 1; +} + + +# replycount_do +# input: $u, $jitemid, $action, $value +# action is one of: "init", "incr", "decr" +# $value is amount to incr/decr, 1 by default + +sub replycount_do { + my ($u, $jitemid, $action, $value) = @_; + $value = 1 unless defined $value; + my $uid = $u->{'userid'}; + my $memkey = [$uid, "rp:$uid:$jitemid"]; + + # "init" is easiest and needs no lock (called before the entry is live) + if ($action eq 'init') { + LJ::MemCache::set($memkey, "0 "); + return 1; + } + + return 0 unless $u->writer; + + my $lockkey = $memkey->[1]; + $u->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + + my $ret; + + if ($action eq 'decr') { + $ret = LJ::MemCache::decr($memkey, $value); + $u->do("UPDATE log2 SET replycount=replycount-$value WHERE journalid=$uid AND jitemid=$jitemid"); + } + + if ($action eq 'incr') { + $ret = LJ::MemCache::incr($memkey, $value); + $u->do("UPDATE log2 SET replycount=replycount+$value WHERE journalid=$uid AND jitemid=$jitemid"); + } + + if (@LJ::MEMCACHE_SERVERS && ! defined $ret) { + my $rc = $u->selectrow_array("SELECT replycount FROM log2 WHERE journalid=$uid AND jitemid=$jitemid"); + if (defined $rc) { + $rc = sprintf("%-4d", $rc); + LJ::MemCache::set($memkey, $rc); + } + } + + $u->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + return 1; +} + +# +# name: LJ::delete_comments +# des: deletes comments, but not the relational information, so threading doesn't break +# info: The tables [dbtable[talkprop2]] and [dbtable[talktext2]] are deleted from. [dbtable[talk2]] +# just has its state column modified to 'D'. +# args: u, nodetype, nodeid, talkids+ +# des-nodetype: The thread nodetype (probably 'L' for log items) +# des-nodeid: The thread nodeid for the given nodetype (probably the jitemid from the log2 row) +# des-talkids: List of talkids to delete. +# returns: scalar integer; number of items deleted. +# +sub delete_comments { + my ($u, $nodetype, $nodeid, @talkids) = @_; + + return 0 unless $u->writer; + + my $jid = $u->{'userid'}+0; + my $in = join(',', map { $_+0 } @talkids); + return 1 unless $in; + my $where = "WHERE journalid=$jid AND jtalkid IN ($in)"; + + my $num = $u->talk2_do($nodetype, $nodeid, undef, + "UPDATE talk2 SET state='D' $where"); + return 0 unless $num; + $num = 0 if $num == -1; + + if ($num > 0) { + $u->do("UPDATE talktext2 SET subject=NULL, body=NULL $where"); + $u->do("DELETE FROM talkprop2 WHERE $where"); + } + return $num; +} + +# +# name: LJ::color_fromdb +# des: Takes a value of unknown type from the db and returns an #rrggbb string. +# args: color +# des-color: either a 24-bit decimal number, or an #rrggbb string. +# returns: scalar; #rrggbb string, or undef if unknown input format +# +sub color_fromdb +{ + my $c = shift; + return $c if $c =~ /^\#[0-9a-f]{6,6}$/i; + return sprintf("\#%06x", $c) if $c =~ /^\d+$/; + return undef; +} + +# +# name: LJ::color_todb +# des: Takes an #rrggbb value and returns a 24-bit decimal number. +# args: color +# des-color: scalar; an #rrggbb string. +# returns: undef if bogus color, else scalar; 24-bit decimal number, can be up to 8 chars wide as a string. +# +sub color_todb +{ + my $c = shift; + return undef unless $c =~ /^\#[0-9a-f]{6,6}$/i; + return hex(substr($c, 1, 6)); +} + +# +# name: LJ::add_friend +# des: Simple interface to add a friend edge. +# args: uuid, to_add, opts? +# des-to_add: a single uuid or an arrayref of uuids to add (befriendees) +# des-opts: hashref; 'defaultview' key means add target uuids to $uuid's Default View friends group +# returns: boolean; 1 on success (or already friend), 0 on failure (bogus args) +# +sub add_friend +{ + &nodb; + my ($userid, $to_add, $opts) = @_; + + $userid = LJ::want_userid($userid); + return 0 unless $userid; + + my @add_ids = ref $to_add eq 'ARRAY' ? map { LJ::want_userid($_) } @$to_add : ( LJ::want_userid($to_add) ); + return 0 unless @add_ids; + + my $dbh = LJ::get_db_writer(); + + my $black = LJ::color_todb("#000000"); + my $white = LJ::color_todb("#ffffff"); + + my $groupmask = 1; + if ($opts->{'defaultview'}) { + # TAG:FR:ljlib:add_friend_getdefviewmask + my $group = LJ::get_friend_group($userid, { name => 'Default View' }); + my $grp = $group ? $group->{groupnum}+0 : 0; + $groupmask |= (1 << $grp) if $grp; + } + + # TAG:FR:ljlib:add_friend + my $bind = join(",", map { "(?,?,?,?,?)" } @add_ids); + my @vals = map { $userid, $_, $black, $white, $groupmask } @add_ids; + + my $res = LJ::_friends_do + ($userid, "INSERT IGNORE INTO friends (userid, friendid, fgcolor, bgcolor, groupmask) VALUES $bind", @vals); + + # delete friend-of memcache keys for anyone who was added + foreach (@add_ids) { + LJ::MemCache::delete([ $userid, "frgmask:$userid:$_" ]); + LJ::memcache_kill($_, 'friendofs'); + } + + return $res; +} + +# +# name: LJ::remove_friend +# args: uuid, to_del +# des-to_del: a single uuid or an arrayref of uuids to remove +# +sub remove_friend +{ + my ($userid, $to_del) = @_; + + $userid = LJ::want_userid($userid); + return undef unless $userid; + + my @del_ids = ref $to_del eq 'ARRAY' ? map { LJ::want_userid($_) } @$to_del : ( LJ::want_userid($to_del) ); + return 0 unless @del_ids; + + my $bind = join(",", map { "?" } @del_ids); + my $res = LJ::_friends_do($userid, "DELETE FROM friends WHERE userid=? AND friendid IN ($bind)", + $userid, @del_ids); + + # delete friend-of memcache keys for anyone who was removed + foreach my $fid (@del_ids) { + LJ::MemCache::delete([ $userid, "frgmask:$userid:$fid" ]); + LJ::memcache_kill($fid, 'friendofs'); + } + + return $res; +} +*delete_friend_edge = \&LJ::remove_friend; + +# +# name: LJ::event_register +# des: Logs a subscribable event, if anybody's subscribed to it. +# args: dbarg?, dbc, etype, ejid, eiarg, duserid, diarg +# des-dbc: Cluster master of event +# des-type: One character event type. +# des-ejid: Journalid event occurred in. +# des-eiarg: 4 byte numeric argument +# des-duserid: Event doer's userid +# des-diarg: Event's 4 byte numeric argument +# returns: boolean; 1 on success; 0 on fail. +# +sub event_register +{ + &nodb; + my ($dbc, $etype, $ejid, $eiarg, $duserid, $diarg) = @_; + my $dbr = LJ::get_db_reader(); + + # see if any subscribers first of all (reads cheap; writes slow) + return 0 unless $dbr; + my $qetype = $dbr->quote($etype); + my $qejid = $ejid+0; + my $qeiarg = $eiarg+0; + my $qduserid = $duserid+0; + my $qdiarg = $diarg+0; + + my $has_sub = $dbr->selectrow_array("SELECT userid FROM subs WHERE etype=$qetype AND ". + "ejournalid=$qejid AND eiarg=$qeiarg LIMIT 1"); + return 1 unless $has_sub; + + # so we're going to need to log this event + return 0 unless $dbc; + $dbc->do("INSERT INTO events (evtime, etype, ejournalid, eiarg, duserid, diarg) ". + "VALUES (NOW(), $qetype, $qejid, $qeiarg, $qduserid, $qdiarg)"); + return $dbc->err ? 0 : 1; +} + +# +# name: LJ::procnotify_add +# des: Sends a message to all other processes on all clusters. +# info: You'll probably never use this yourself. +# args: cmd, args? +# des-cmd: Command name. Currently recognized: "DBI::Role::reload" and "rename_user" +# des-args: Hashref with key/value arguments for the given command. See +# relevant parts of [func[LJ::procnotify_callback]] for required args for different commands. +# returns: new serial number on success; 0 on fail. +# +sub procnotify_add +{ + &nodb; + my ($cmd, $argref) = @_; + my $dbh = LJ::get_db_writer(); + return 0 unless $dbh; + + my $args = join('&', map { LJ::eurl($_) . "=" . LJ::eurl($argref->{$_}) } + sort keys %$argref); + $dbh->do("INSERT INTO procnotify (cmd, args) VALUES (?,?)", + undef, $cmd, $args); + + return 0 if $dbh->err; + return $dbh->{'mysql_insertid'}; +} + +# +# name: LJ::procnotify_callback +# des: Call back function process notifications. +# info: You'll probably never use this yourself. +# args: cmd, argstring +# des-cmd: Command name. +# des-argstring: String of arguments. +# returns: new serial number on success; 0 on fail. +# +sub procnotify_callback +{ + my ($cmd, $argstring) = @_; + my $arg = {}; + LJ::decode_url_string($argstring, $arg); + + if ($cmd eq "rename_user") { + # this looks backwards, but the cache hash names are just odd: + delete $LJ::CACHE_USERNAME{$arg->{'userid'}}; + delete $LJ::CACHE_USERID{$arg->{'user'}}; + return; + } + + # ip bans + if ($cmd eq "ban_ip") { + $LJ::IP_BANNED{$arg->{'ip'}} = $arg->{'exptime'}; + return; + } + + if ($cmd eq "unban_ip") { + delete $LJ::IP_BANNED{$arg->{'ip'}}; + return; + } + + # uniq key bans + if ($cmd eq "ban_uniq") { + $LJ::UNIQ_BANNED{$arg->{'uniq'}} = $arg->{'exptime'}; + return; + } + + if ($cmd eq "unban_uniq") { + delete $LJ::UNIQ_BANNED{$arg->{'uniq'}}; + return; + } +} + +sub procnotify_check +{ + my $now = time; + return if $LJ::CACHE_PROCNOTIFY_CHECK + 30 > $now; + $LJ::CACHE_PROCNOTIFY_CHECK = $now; + + my $dbr = LJ::get_db_reader(); + my $max = $dbr->selectrow_array("SELECT MAX(nid) FROM procnotify"); + return unless defined $max; + my $old = $LJ::CACHE_PROCNOTIFY_MAX; + if (defined $old && $max > $old) { + my $sth = $dbr->prepare("SELECT cmd, args FROM procnotify ". + "WHERE nid > ? AND nid <= $max ORDER BY nid"); + $sth->execute($old); + while (my ($cmd, $args) = $sth->fetchrow_array) { + LJ::procnotify_callback($cmd, $args); + } + } + $LJ::CACHE_PROCNOTIFY_MAX = $max; +} + +sub dbtime_callback { + my ($dsn, $dbtime, $time) = @_; + my $diff = abs($dbtime - $time); + if ($diff > 2) { + $dsn =~ /host=([^:\;\|]*)/; + my $db = $1; + print STDERR "Clock skew of $diff seconds between web($LJ::SERVER_NAME) and db($db)\n"; + } +} + +# +# name: LJ::is_ascii +# des: checks if text is pure ASCII +# args: text +# des-text: text to check for being pure 7-bit ASCII text +# returns: 1 if text is indeed pure 7-bit, 0 otherwise. +# +sub is_ascii { + my $text = shift; + return ($text !~ m/[\x00\x80-\xff]/); +} + +# +# name: LJ::is_utf8 +# des: check text for UTF-8 validity +# args: text +# des-text: text to check for UTF-8 validity +# returns: 1 if text is a valid UTF-8 stream, 0 otherwise. +# +sub is_utf8 { + my $text = shift; + + if (LJ::are_hooks("is_utf8")) { + return LJ::run_hook("is_utf8", $text); + } + + # for a discussion of the different utf8 validity checking methods, + # see: http://zilla.livejournal.org/657 + # in summary, this isn't the fastest, but it's pretty fast, it doesn't make + # perl segfault, and it doesn't add new crazy dependencies. if you want + # speed, check out ljcom's is_utf8 version in C, using Inline.pm + + my $u = Unicode::String::utf8($text); + my $text2 = $u->utf8; + return $text eq $text2; +} + +# +# name: LJ::text_out +# des: force outgoing text into valid UTF-8 +# args: text +# des-text: reference to text to pass to output. Text if modified in-place. +# returns: nothing. +# +sub text_out +{ + my $rtext = shift; + + # if we're not Unicode, do nothing + return unless $LJ::UNICODE; + + # is this valid UTF-8 already? + return if LJ::is_utf8($$rtext); + + # no. Blot out all non-ASCII chars + $$rtext =~ s/[\x00\x80-\xff]/\?/g; + return; +} + +# +# name: LJ::text_in +# des: do appropriate checks on input text. Should be called on all +# user-generated text. +# args: text +# des-text: text to check +# returns: 1 if the text is valid, 0 if not. +# +sub text_in +{ + my $text = shift; + return 1 unless $LJ::UNICODE; + if (ref ($text) eq "HASH") { + return ! (grep { !LJ::is_utf8($_) } values %{$text}); + } + if (ref ($text) eq "ARRAY") { + return ! (grep { !LJ::is_utf8($_) } @{$text}); + } + return LJ::is_utf8($text); +} + +# +# name: LJ::text_convert +# des: convert old entries/comments to UTF-8 using user's default encoding +# args: dbs?, text, u, error +# des-text: old possibly non-ASCII text to convert +# des-u: user hashref of the journal's owner +# des-error: ref to a scalar variable which is set to 1 on error +# (when user has no default encoding defined, but +# text needs to be translated) +# returns: converted text or undef on error +# +sub text_convert +{ + &nodb; + my ($text, $u, $error) = @_; + + # maybe it's pure ASCII? + return $text if LJ::is_ascii($text); + + # load encoding id->name mapping if it's not loaded yet + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + + if ($u->{'oldenc'} == 0 || + not defined $LJ::CACHE_ENCODINGS{$u->{'oldenc'}}) { + $$error = 1; + return undef; + }; + + # convert! + my $name = $LJ::CACHE_ENCODINGS{$u->{'oldenc'}}; + unless (Unicode::MapUTF8::utf8_supported_charset($name)) { + $$error = 1; + return undef; + } + + return Unicode::MapUTF8::to_utf8({-string=>$text, -charset=>$name}); +} + + +# +# name: LJ::text_length +# des: returns both byte length and character length of a string. In a non-Unicode +# environment, this means byte length twice. In a Unicode environment, +# the function assumes that its argument is a valid UTF-8 string. +# args: text +# des-text: the string to measure +# returns: a list of two values, (byte_length, char_length). +# + +sub text_length +{ + my $text = shift; + my $bl = length($text); + unless ($LJ::UNICODE) { + return ($bl, $bl); + } + my $cl = 0; + my $utf_char = "([\x00-\x7f]|[\xc0-\xdf].|[\xe0-\xef]..|[\xf0-\xf7]...)"; + + while ($text =~ m/$utf_char/go) { $cl++; } + return ($bl, $cl); +} + +# +# name: LJ::text_trim +# des: truncate string according to requirements on byte length, char +# length, or both. "char length" means number of UTF-8 characters if +# $LJ::UNICODE is set, or the same thing as byte length otherwise. +# args: text, byte_max, char_max +# des-text: the string to trim +# des-byte_max: maximum allowed length in bytes; if 0, there's no restriction +# des-char_max: maximum allowed length in chars; if 0, there's no restriction +# returns: the truncated string. +# +sub text_trim +{ + my ($text, $byte_max, $char_max) = @_; + return $text unless $byte_max or $char_max; + if (!$LJ::UNICODE) { + $byte_max = $char_max if $char_max and $char_max < $byte_max; + $byte_max = $char_max unless $byte_max; + return substr($text, 0, $byte_max); + } + my $cur = 0; + my $utf_char = "([\x00-\x7f]|[\xc0-\xdf].|[\xe0-\xef]..|[\xf0-\xf7]...)"; + + # if we don't have a character limit, assume it's the same as the byte limit. + # we will never have more characters than bytes, but we might have more bytes + # than characters, so we can't inherit the other way. + $char_max ||= $byte_max; + + while ($text =~ m/$utf_char/gco) { + last unless $char_max; + last if $cur + length($1) > $byte_max and $byte_max; + $cur += length($1); + $char_max--; + } + return substr($text,0,$cur); +} + +# +# name: LJ::text_compress +# des: Compresses a chunk of text, to gzip, if configured for site. Can compress +# a scalarref in place, or return a compressed copy. Won't compress if +# value is too small, already compressed, or size would grow by compressing. +# args: text +# des-test: either a scalar or scalarref +# returns: nothing if given a scalarref (to compress in-place), or original/compressed value, +# depending on site config +# +sub text_compress +{ + my $text = shift; + my $ref = ref $text; + return $ref ? undef : $text unless $LJ::COMPRESS_TEXT; + die "Invalid reference" if $ref && $ref ne "SCALAR"; + + my $tref = $ref ? $text : \$text; + my $pre_len = length($$tref); + unless (substr($$tref,0,2) eq "\037\213" || $pre_len < 100) { + my $gz = Compress::Zlib::memGzip($$tref); + if (length($gz) < $pre_len) { + $$tref = $gz; + } + } + + return $ref ? undef : $$tref; +} + +# +# name: LJ::text_uncompress +# des: Uncompresses a chunk of text, from gzip, if configured for site. Can uncompress +# a scalarref in place, or return a compressed copy. Won't uncompress unless +# it finds the gzip magic number at the beginning of the text. +# args: text +# des-test: either a scalar or scalarref. +# returns: nothing if given a scalarref (to uncompress in-place), or original/uncompressed value, +# depending on if test was compressed or not +# +sub text_uncompress +{ + my $text = shift; + my $ref = ref $text; + die "Invalid reference" if $ref && $ref ne "SCALAR"; + my $tref = $ref ? $text : \$text; + + # check for gzip's magic number + if (substr($$tref,0,2) eq "\037\213") { + $$tref = Compress::Zlib::memGunzip($$tref); + } + + return $ref ? undef : $$tref; +} + +# +# name: LJ::item_toutf8 +# des: convert one item's subject, text and props to UTF8. +# item can be an entry or a comment (in which cases props can be +# left empty, since there are no 8bit talkprops). +# args: u, subject, text, props +# des-u: user hashref of the journal's owner +# des-subject: ref to the item's subject +# des-text: ref to the item's text +# des-props: hashref of the item's props +# returns: nothing. +# +sub item_toutf8 +{ + my ($u, $subject, $text, $props) = @_; + return unless $LJ::UNICODE; + + my $convert = sub { + my $rtext = shift; + my $error = 0; + my $res = LJ::text_convert($$rtext, $u, \$error); + if ($error) { + LJ::text_out($rtext); + } else { + $$rtext = $res; + }; + return; + }; + + $convert->($subject); + $convert->($text); + foreach(keys %$props) { + $convert->(\$props->{$_}); + } + return; +} + +# returns 1 if action is permitted. 0 if above rate or fail. +# action isn't logged on fail. +# +# opts keys: +# -- "limit_by_ip" => "1.2.3.4" (when used for checking rate) +# -- +sub rate_log +{ + my ($u, $ratename, $count, $opts) = @_; + my $rateperiod = LJ::get_cap($u, "rateperiod-$ratename"); + return 1 unless $rateperiod; + + return 0 unless $u->writer; + + my $rp = LJ::get_prop("rate", $ratename); + return 0 unless $rp; + + my $now = time(); + my $beforeperiod = $now - $rateperiod; + + # delete inapplicable stuff (or some of it) + $u->do("DELETE FROM ratelog WHERE userid=$u->{'userid'} AND rlid=$rp->{'id'} ". + "AND evttime < $beforeperiod LIMIT 1000"); + + # check rate. (okay per period) + my $opp = LJ::get_cap($u, "rateallowed-$ratename"); + return 1 unless $opp; + my $udbr = LJ::get_cluster_reader($u); + my $ip = $udbr->quote($opts->{'limit_by_ip'} || "0.0.0.0"); + my $sum = $udbr->selectrow_array("SELECT COUNT(quantity) FROM ratelog WHERE ". + "userid=$u->{'userid'} AND rlid=$rp->{'id'} ". + "AND ip=INET_ATON($ip) ". + "AND evttime > $beforeperiod"); + + # would this transaction go over the limit? + if ($sum + $count > $opp) { + # TODO: optionally log to rateabuse, unless caller is doing it themselves + # somehow, like with the "loginstall" table. + return 0; + } + + # log current + $count = $count + 0; + $u->do("INSERT INTO ratelog (userid, rlid, evttime, ip, quantity) VALUES ". + "($u->{'userid'}, $rp->{'id'}, $now, INET_ATON($ip), $count)"); + return 1; +} + +# We're not always running under mod_perl... sometimes scripts (syndication sucker) +# call paths which end up thinking they need the remote IP, but don't. +sub get_remote_ip +{ + my $ip; + eval { + $ip = Apache->request->connection->remote_ip; + }; + return $ip || $ENV{'FAKE_IP'}; +} + +sub login_ip_banned +{ + my $u = shift; + return 0 unless $u; + + my $ip; + return 0 unless ($ip = LJ::get_remote_ip()); + + my $udbr; + my $rateperiod = LJ::get_cap($u, "rateperiod-failed_login"); + if ($rateperiod && ($udbr = LJ::get_cluster_reader($u))) { + my $bantime = $udbr->selectrow_array("SELECT time FROM loginstall WHERE ". + "userid=$u->{'userid'} AND ip=INET_ATON(?)", + undef, $ip); + if ($bantime && $bantime > time() - $rateperiod) { + return 1; + } + } + return 0; +} + +sub handle_bad_login +{ + my $u = shift; + return 1 unless $u; + + my $ip; + return 1 unless ($ip = LJ::get_remote_ip()); + # an IP address is permitted such a rate of failures + # until it's banned for a period of time. + my $udbh; + if (! LJ::rate_log($u, "failed_login", 1, { 'limit_by_ip' => $ip }) && + ($udbh = LJ::get_cluster_master($u))) + { + $udbh->do("REPLACE INTO loginstall (userid, ip, time) VALUES ". + "(?,INET_ATON(?),UNIX_TIMESTAMP())", undef, $u->{'userid'}, $ip); + } + return 1; +} + +sub md5_struct +{ + my ($st, $md5) = @_; + $md5 ||= Digest::MD5->new; + unless (ref $st) { + # later Digest::MD5s die while trying to + # get at the bytes of an invalid utf-8 string. + # this really shouldn't come up, but when it + # does, we clear the utf8 flag on the string and retry. + # see http://zilla.livejournal.org/show_bug.cgi?id=851 + eval { $md5->add($st); }; + if ($@) { + $st = pack('C*', unpack('C*', $st)); + $md5->add($st); + } + return $md5; + } + if (ref $st eq "HASH") { + foreach (sort keys %$st) { + md5_struct($_, $md5); + md5_struct($st->{$_}, $md5); + } + return $md5; + } + if (ref $st eq "ARRAY") { + foreach (@$st) { + md5_struct($_, $md5); + } + return $md5; + } +} + +sub rand_chars +{ + my $length = shift; + my $chal = ""; + my $digits = "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWZYZ0123456789"; + for (1..$length) { + $chal .= substr($digits, int(rand(62)), 1); + } + return $chal; +} + +# ($time, $secret) = LJ::get_secret(); # will generate +# $secret = LJ::get_secret($time); # won't generate +# ($time, $secret) = LJ::get_secret($time); # will generate (in wantarray) +sub get_secret +{ + my $time = int($_[0]); + return undef if $_[0] && ! $time; + my $want_new = ! $time || wantarray; + + if (! $time) { + $time = time(); + $time -= $time % 3600; # one hour granularity + } + + my $memkey = "secret:$time"; + my $secret = LJ::MemCache::get($memkey); + return $want_new ? ($time, $secret) : $secret if $secret; + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + $secret = $dbh->selectrow_array("SELECT secret FROM secrets ". + "WHERE stime=?", undef, $time); + if ($secret) { + LJ::MemCache::set($memkey, $secret) if $secret; + return $want_new ? ($time, $secret) : $secret; + } + + # return if they specified an explicit time they wanted. + # (calling with no args means generate a new one if secret + # doesn't exist) + return undef unless $want_new; + + # don't generate new times that don't fall in our granularity + return undef if $time % 3600; + + $secret = LJ::rand_chars(32); + $dbh->do("INSERT IGNORE INTO secrets SET stime=?, secret=?", + undef, $time, $secret); + # check for races: + $secret = get_secret($time); + return ($time, $secret); +} + +# +# name: LJ::get_reluser_id +# des: for reluser2, numbers 1 - 31999 are reserved for livejournal stuff, whereas +# numbers 32000-65535 are used for local sites. if you wish to add your +# own hooks to this, you should define a hook "get_reluser_id" in ljlib-local.pl +# no reluser2 types can be a single character, those are reserved for the +# reluser table so we don't have namespace problems. +# args: type +# des-type: the name of the type you're trying to access, e.g. "hide_comm_assoc" +# returns: id of type, 0 means it's not a reluser2 type +# +sub get_reluser_id { + my $type = shift; + return 0 if length $type == 1; # must be more than a single character + my $val = + { + 'hide_comm_assoc' => 1, + }->{$type}+0; + return $val if $val; + return 0 unless $type =~ /^local-/; + return LJ::run_hook('get_reluser_id', $type)+0; +} + +# +# name: LJ::load_rel_user +# des: Load user relationship information. Loads all relationships of type 'type' in +# which user 'userid' participates on the left side (is the source of the +# relationship). +# args: db?, userid, type +# arg-userid: userid or a user hash to load relationship information for. +# arg-type: type of the relationship +# returns: reference to an array of userids +# +sub load_rel_user +{ + my $db = isdb($_[0]) ? shift : undef; + my ($userid, $type) = @_; + return undef unless $type and $userid; + my $u = LJ::want_user($userid); + $userid = LJ::want_userid($userid); + my $typeid = LJ::get_reluser_id($type)+0; + if ($typeid) { + # clustered reluser2 table + $db = LJ::get_cluster_reader($u); + return $db->selectcol_arrayref("SELECT targetid FROM reluser2 WHERE userid=? AND type=?", + undef, $userid, $typeid); + } else { + # non-clustered reluser global table + $db ||= LJ::get_db_reader(); + return $db->selectcol_arrayref("SELECT targetid FROM reluser WHERE userid=? AND type=?", + undef, $userid, $type); + } +} + +# +# name: LJ::load_rel_target +# des: Load user relationship information. Loads all relationships of type 'type' in +# which user 'targetid' participates on the right side (is the target of the +# relationship). +# args: db?, targetid, type +# arg-targetid: userid or a user hash to load relationship information for. +# arg-type: type of the relationship +# returns: reference to an array of userids +# +sub load_rel_target +{ + my $db = isdb($_[0]) ? shift : undef; + my ($targetid, $type) = @_; + return undef unless $type and $targetid; + my $u = LJ::want_user($targetid); + $targetid = LJ::want_userid($targetid); + my $typeid = LJ::get_reluser_id($type)+0; + if ($typeid) { + # clustered reluser2 table + $db = LJ::get_cluster_reader($u); + return $db->selectcol_arrayref("SELECT userid FROM reluser2 WHERE targetid=? AND type=?", + undef, $targetid, $typeid); + } else { + # non-clustered reluser global table + $db ||= LJ::get_db_reader(); + return $db->selectcol_arrayref("SELECT userid FROM reluser WHERE targetid=? AND type=?", + undef, $targetid, $type); + } +} + +# +# name: LJ::_get_rel_memcache +# des: Helper function: returns memcached value for a given (userid, targetid, type) triple, if valid +# args: userid, targetid, type +# arg-userid: source userid, nonzero +# arg-targetid: target userid, nonzero +# arg-type: type (reluser) or typeid (rel2) of the relationship +# returns: undef on failure, 0 or 1 depending on edge existence +# +sub _get_rel_memcache { + return undef unless @LJ::MEMCACHE_SERVERS; + return undef if $LJ::DISABLED{memcache_reluser}; + + my ($userid, $targetid, $type) = @_; + return undef unless $userid && $targetid && defined $type; + + # memcache keys + my $relkey = [$userid, "rel:$userid:$targetid:$type"]; # rel $uid->$targetid edge + my $modukey = [$userid, "relmodu:$userid:$type" ]; # rel modtime for uid + my $modtkey = [$targetid, "relmodt:$targetid:$type" ]; # rel modtime for targetid + + # do a get_multi since $relkey and $modukey are both hashed on $userid + my $memc = LJ::MemCache::get_multi($relkey, $modukey); + return undef unless $memc && ref $memc eq 'HASH'; + + # [{0|1}, modtime] + my $rel = $memc->{$relkey->[1]}; + return undef unless $rel && ref $rel eq 'ARRAY'; + + # check rel modtime for $userid + my $relmodu = $memc->{$modukey->[1]}; + return undef if ! $relmodu || $relmodu > $rel->[1]; + + # check rel modtime for $targetid + my $relmodt = LJ::MemCache::get($modtkey); + return undef if ! $relmodt || $relmodt > $rel->[1]; + + # return memcache value if it's up-to-date + return $rel->[0] ? 1 : 0; +} + +# +# name: LJ::_set_rel_memcache +# des: Helper function: sets memcache values for a given (userid, targetid, type) triple +# args: userid, targetid, type +# arg-userid: source userid, nonzero +# arg-targetid: target userid, nonzero +# arg-type: type (reluser) or typeid (rel2) of the relationship +# returns: 1 on success, undef on failure +# +sub _set_rel_memcache { + return 1 unless @LJ::MEMCACHE_SERVERS; + + my ($userid, $targetid, $type, $val) = @_; + return undef unless $userid && $targetid && defined $type; + $val = $val ? 1 : 0; + + # memcache keys + my $relkey = [$userid, "rel:$userid:$targetid:$type"]; # rel $uid->$targetid edge + my $modukey = [$userid, "relmodu:$userid:$type" ]; # rel modtime for uid + my $modtkey = [$targetid, "relmodt:$targetid:$type" ]; # rel modtime for targetid + + my $now = time(); + my $exp = $now + 3600*6; # 6 hour + LJ::MemCache::set($relkey, [$val, $now], $exp); + LJ::MemCache::set($modukey, $now, $exp); + LJ::MemCache::set($modtkey, $now, $exp); + + return 1; +} + +# +# name: LJ::check_rel +# des: Checks whether two users are in a specified relationship to each other. +# args: db?, userid, targetid, type +# arg-userid: source userid, nonzero; may also be a user hash. +# arg-targetid: target userid, nonzero; may also be a user hash. +# arg-type: type of the relationship +# returns: 1 if the relationship exists, 0 otherwise +# +sub check_rel +{ + my $db = isdb($_[0]) ? shift : undef; + my ($userid, $targetid, $type) = @_; + return undef unless $type && $userid && $targetid; + + my $u = LJ::want_user($userid); + $userid = LJ::want_userid($userid); + $targetid = LJ::want_userid($targetid); + + my $typeid = LJ::get_reluser_id($type)+0; + my $eff_type = $typeid || $type; + + my $key = "$userid-$targetid-$eff_type"; + return $LJ::REQ_CACHE_REL{$key} if defined $LJ::REQ_CACHE_REL{$key}; + + # did we get something from memcache? + my $memval = LJ::_get_rel_memcache($userid, $targetid, $eff_type); + return $memval if defined $memval; + + # are we working on reluser or reluser2? + my $table; + if ($typeid) { + # clustered reluser2 table + $db = LJ::get_cluster_reader($u); + $table = "reluser2"; + } else { + # non-clustered reluser table + $db ||= LJ::get_db_reader(); + $table = "reluser"; + } + + # get data from db, force result to be {0|1} + my $dbval = $db->selectrow_array("SELECT COUNT(*) FROM $table ". + "WHERE userid=? AND targetid=? AND type=? ", + undef, $userid, $targetid, $eff_type) + ? 1 : 0; + + # set in memcache + LJ::_set_rel_memcache($userid, $targetid, $eff_type, $dbval); + + # return and set request cache + return $LJ::REQ_CACHE_REL{$key} = $dbval; +} + +# +# name: LJ::set_rel +# des: Sets relationship information for two users. +# args: dbs?, userid, targetid, type +# arg-userid: source userid, or a user hash +# arg-targetid: target userid, or a user hash +# arg-type: type of the relationship +# returns: 1 if set succeeded, otherwise undef +# +sub set_rel +{ + &nodb; + my ($userid, $targetid, $type) = @_; + return undef unless $type and $userid and $targetid; + + my $u = LJ::want_user($userid); + $userid = LJ::want_userid($userid); + $targetid = LJ::want_userid($targetid); + + my $typeid = LJ::get_reluser_id($type)+0; + my $eff_type = $typeid || $type; + + # working on reluser or reluser2? + my ($db, $table); + if ($typeid) { + # clustered reluser2 table + $db = LJ::get_cluster_master($u); + $table = "reluser2"; + } else { + # non-clustered reluser global table + $db = LJ::get_db_writer(); + $table = "reluser"; + } + return undef unless $db; + + # set in database + $db->do("REPLACE INTO $table (userid, targetid, type) VALUES (?, ?, ?)", + undef, $userid, $targetid, $eff_type); + return undef if $db->err; + + # set in memcache + LJ::_set_rel_memcache($userid, $targetid, $eff_type, 1); + + return 1; +} + +# +# name: LJ::set_rel_multi +# des: Sets relationship edges for lists of user tuples. +# args: @edges +# arg-edges: array of arrayrefs of edges to set: [userid, targetid, type] +# Where: +# userid: source userid, or a user hash +# targetid: target userid, or a user hash +# type: type of the relationship +# returns: 1 if all sets succeeded, otherwise undef +# +sub set_rel_multi { + return _mod_rel_multi({ mode => 'set', edges => \@_ }); +} + +# +# name: LJ::clear_rel_multi +# des: Clear relationship edges for lists of user tuples. +# args: @edges +# arg-edges: array of arrayrefs of edges to clear: [userid, targetid, type] +# Where: +# userid: source userid, or a user hash +# targetid: target userid, or a user hash +# type: type of the relationship +# returns: 1 if all clears succeeded, otherwise undef +# +sub clear_rel_multi { + return _mod_rel_multi({ mode => 'clear', edges => \@_ }); +} + +# +# name: LJ::_mod_rel_multi +# des: Sets/Clears relationship edges for lists of user tuples. +# args: $opts +# arg-opts: keys: mode => {clear|set} +# edges => array of arrayrefs of edges to set: [userid, targetid, type] +# Where: +# userid: source userid, or a user hash +# targetid: target userid, or a user hash +# type: type of the relationship +# returns: 1 if all updates succeeded, otherwise undef +# +sub _mod_rel_multi +{ + my $opts = shift; + return undef unless @{$opts->{edges}}; + + my $mode = $opts->{mode} eq 'clear' ? 'clear' : 'set'; + my $memval = $mode eq 'set' ? 1 : 0; + + my @reluser = (); # [userid, targetid, type] + my @reluser2 = (); + foreach my $edge (@{$opts->{edges}}) { + my ($userid, $targetid, $type) = @$edge; + $userid = LJ::want_userid($userid); + $targetid = LJ::want_userid($targetid); + next unless $type && $userid && $targetid; + + my $typeid = LJ::get_reluser_id($type)+0; + my $eff_type = $typeid || $type; + + # working on reluser or reluser2? + push @{$typeid ? \@reluser2 : \@reluser}, [$userid, $targetid, $eff_type]; + } + + # now group reluser2 edges by clusterid + my %reluser2 = (); # cid => [userid, targetid, type] + my $users = LJ::load_userids(map { $_->[0] } @reluser2); + foreach (@reluser2) { + my $cid = $users->{$_->[0]}->{clusterid} or next; + push @{$reluser2{$cid}}, $_; + } + @reluser2 = (); + + # try to get all required cluster masters before we start doing database updates + my %cache_dbcm = (); + foreach my $cid (keys %reluser2) { + next unless @{$reluser2{$cid}}; + + # return undef immediately if we won't be able to do all the updates + $cache_dbcm{$cid} = LJ::get_cluster_master($cid) + or return undef; + } + + # if any error occurs with a cluster, we'll skip over that cluster and continue + # trying to process others since we've likely already done some amount of db + # updates already, but we'll return undef to signify that everything did not + # go smoothly + my $ret = 1; + + # do clustered reluser2 updates + foreach my $cid (keys %cache_dbcm) { + # array of arrayrefs: [userid, targetid, type] + my @edges = @{$reluser2{$cid}}; + + # set in database, then in memcache. keep the two atomic per clusterid + my $dbcm = $cache_dbcm{$cid}; + + my @vals = map { @$_ } @edges; + + if ($mode eq 'set') { + my $bind = join(",", map { "(?,?,?)" } @edges); + $dbcm->do("REPLACE INTO reluser2 (userid, targetid, type) VALUES $bind", + undef, @vals); + } + + if ($mode eq 'clear') { + my $where = join(" OR ", map { "(userid=? AND targetid=? AND type=?)" } @edges); + $dbcm->do("DELETE FROM reluser2 WHERE $where", undef, @vals); + } + + # don't update memcache if db update failed for this cluster + if ($dbcm->err) { + $ret = undef; + next; + } + + # updates to this cluster succeeded, set memcache + LJ::_set_rel_memcache(@$_, $memval) foreach @edges; + } + + # do global reluser updates + if (@reluser) { + + # nothing to do after this block but return, so we can + # immediately return undef from here if there's a problem + my $dbh = LJ::get_db_writer() + or return undef; + + my @vals = map { @$_ } @reluser; + + if ($mode eq 'set') { + my $bind = join(",", map { "(?,?,?)" } @reluser); + $dbh->do("REPLACE INTO reluser (userid, targetid, type) VALUES $bind", + undef, @vals); + } + + if ($mode eq 'clear') { + my $where = join(" OR ", map { "userid=? AND targetid=? AND type=?" } @reluser); + $dbh->do("DELETE FROM reluser WHERE $where", undef, @vals); + } + + # don't update memcache if db update failed for this cluster + return undef if $dbh->err; + + # $_ = [userid, targetid, type] for each iteration + LJ::_set_rel_memcache(@$_, $memval) foreach @reluser; + } + + return $ret; +} + + +# +# name: LJ::clear_rel +# des: Deletes a relationship between two users or all relationships of a particular type +# for one user, on either side of the relationship. One of userid,targetid -- bit not +# both -- may be '*'. In that case, if, say, userid is '*', then all relationship +# edges with target equal to targetid and of the specified type are deleted. +# If both userid and targetid are numbers, just one edge is deleted. +# args: dbs?, userid, targetid, type +# arg-userid: source userid, or a user hash, or '*' +# arg-targetid: target userid, or a user hash, or '*' +# arg-type: type of the relationship +# returns: 1 if clear succeeded, otherwise undef +# +sub clear_rel +{ + &nodb; + my ($userid, $targetid, $type) = @_; + return undef if $userid eq '*' and $targetid eq '*'; + + my $u = LJ::want_user($userid); + $userid = LJ::want_userid($userid) unless $userid eq '*'; + $targetid = LJ::want_userid($targetid) unless $targetid eq '*'; + return undef unless $type && $userid && $targetid; + + my $typeid = LJ::get_reluser_id($type)+0; + + if ($typeid) { + # clustered reluser2 table + return undef unless $u->writer; + + $u->do("DELETE FROM reluser2 WHERE " . ($userid ne '*' ? "userid=$userid AND " : "") . + ($targetid ne '*' ? "targetid=$targetid AND " : "") . "type=$typeid"); + + return undef if $u->err; + } else { + # non-clustered global reluser table + my $dbh = LJ::get_db_writer() + or return undef; + + my $qtype = $dbh->quote($type); + $dbh->do("DELETE FROM reluser WHERE " . ($userid ne '*' ? "userid=$userid AND " : "") . + ($targetid ne '*' ? "targetid=$targetid AND " : "") . "type=$qtype"); + + return undef if $dbh->err; + } + + # if one of userid or targetid are '*', then we need to note the modtime + # of the reluser edge from the specified id (the one that's not '*') + # so that subsequent gets on rel:userid:targetid:type will know to ignore + # what they got from memcache + my $eff_type = $typeid || $type; + if ($userid eq '*') { + LJ::MemCache::set([$targetid, "relmodt:$targetid:$eff_type"], time()); + } elsif ($targetid eq '*') { + LJ::MemCache::set([$userid, "relmodu:$userid:$eff_type"], time()); + + # if neither userid nor targetid are '*', then just call _set_rel_memcache + # to update the rel:userid:targetid:type memcache key as well as the + # userid and targetid modtime keys + } else { + LJ::_set_rel_memcache($userid, $targetid, $eff_type, 0); + } + + return 1; +} + +# $dom: 'L' == log, 'T' == talk, 'M' == modlog, 'S' == session, +# 'R' == memory (remembrance), 'K' == keyword id, +# 'P' == phone post, 'C' == pending comment +sub alloc_user_counter +{ + my ($u, $dom, $recurse) = @_; + + ################################################################## + # IF YOU UPDATE THIS MAKE SURE YOU ADD INITIALIZATION CODE BELOW # + return undef unless $dom =~ /^[LTMPSRKC]$/; # + ################################################################## + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + my $newmax; + my $uid = $u->{'userid'}+0; + return undef unless $uid; + my $memkey = [$uid, "auc:$uid:$dom"]; + + # in a master-master DB cluster we need to be careful that in + # an automatic failover case where one cluster is slightly behind + # that the same counter ID isn't handed out twice. use memcache + # as a sanity check to record/check latest number handed out. + my $memmax = int(LJ::MemCache::get($memkey) || 0); + + my $rs = $dbh->do("UPDATE usercounter SET max=LAST_INSERT_ID(GREATEST(max,$memmax)+1) ". + "WHERE journalid=? AND area=?", undef, $uid, $dom); + if ($rs > 0) { + $newmax = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + LJ::MemCache::set($memkey, $newmax); + return $newmax; + } + + if ($recurse) { + # We shouldn't ever get here if all is right with the world. + return undef; + } + + my $qry_map = { + # for entries: + 'log' => "SELECT MAX(jitemid) FROM log2 WHERE journalid=?", + 'logtext' => "SELECT MAX(jitemid) FROM logtext2 WHERE journalid=?", + 'talk_nodeid' => "SELECT MAX(nodeid) FROM talk2 WHERE nodetype='L' AND journalid=?", + # for comments: + 'talk' => "SELECT MAX(jtalkid) FROM talk2 WHERE journalid=?", + 'talktext' => "SELECT MAX(jtalkid) FROM talktext2 WHERE journalid=?", + }; + + my $consider = sub { + my @tables = @_; + foreach my $t (@tables) { + my $res = $u->selectrow_array($qry_map->{$t}, undef, $uid); + $newmax = $res if $res > $newmax; + } + }; + + # Make sure the counter table is populated for this uid/dom. + if ($dom eq "L") { + # back in the ol' days IDs were reused (because of MyISAM) + # so now we're extra careful not to reuse a number that has + # foreign junk "attached". turns out people like to delete + # each entry by hand, but we do lazy deletes that are often + # too lazy and a user can see old stuff come back alive + $consider->("log", "logtext", "talk_nodeid"); + } elsif ($dom eq "T") { + # just paranoia, not as bad as above. don't think we've ever + # run into cases of talktext without a talk, but who knows. + # can't hurt. + $consider->("talk", "talktext"); + } elsif ($dom eq "M") { + $newmax = $u->selectrow_array("SELECT MAX(modid) FROM modlog WHERE journalid=?", + undef, $uid); + } elsif ($dom eq "S") { + $newmax = $u->selectrow_array("SELECT MAX(sessid) FROM sessions WHERE userid=?", + undef, $uid); + } elsif ($dom eq "R") { + $newmax = $u->selectrow_array("SELECT MAX(memid) FROM memorable2 WHERE userid=?", + undef, $uid); + } elsif ($dom eq "K") { + $newmax = $u->selectrow_array("SELECT MAX(kwid) FROM userkeywords WHERE userid=?", + undef, $uid); + } elsif ($dom eq "P") { + my $userblobmax = $u->selectrow_array("SELECT MAX(blobid) FROM userblob WHERE journalid=? AND domain=?", + undef, $uid, LJ::get_blob_domainid("phonepost")); + my $ppemax = $u->selectrow_array("SELECT MAX(blobid) FROM phonepostentry WHERE userid=?", + undef, $uid); + $newmax = ($ppemax > $userblobmax) ? $ppemax : $userblobmax; + } elsif ($dom eq "C") { + my $commentmax = $u->selectrow_array("SELECT MAX(pendid) FROM pendcomments WHERE jid=?", + undef, $uid); + } else { + die "No user counter initializer defined for area '$dom'.\n"; + } + $newmax += 0; + $dbh->do("INSERT IGNORE INTO usercounter (journalid, area, max) VALUES (?,?,?)", + undef, $uid, $dom, $newmax) or return undef; + + # The 2nd invocation of the alloc_user_counter sub should do the + # intended incrementing. + return LJ::alloc_user_counter($u, $dom, 1); +} + +# $dom: 'S' == style, 'P' == userpic, 'A' == stock support answer +# 'C' == captcha, 'E' == external user +sub alloc_global_counter +{ + my ($dom, $recurse) = @_; + return undef unless $dom =~ /^[SPCEA]$/; + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + my $newmax; + my $uid = 0; # userid is not needed, we just use '0' + + my $rs = $dbh->do("UPDATE counter SET max=LAST_INSERT_ID(max+1) WHERE journalid=? AND area=?", + undef, $uid, $dom); + if ($rs > 0) { + $newmax = $dbh->selectrow_array("SELECT LAST_INSERT_ID()"); + return $newmax; + } + + return undef if $recurse; + + # no prior counter rows - initialize one. + if ($dom eq "S") { + $newmax = $dbh->selectrow_array("SELECT MAX(styleid) FROM s1stylemap"); + } elsif ($dom eq "P") { + $newmax = $dbh->selectrow_array("SELECT MAX(picid) FROM userpic"); + } elsif ($dom eq "C") { + $newmax = $dbh->selectrow_array("SELECT MAX(capid) FROM captchas"); + } elsif ($dom eq "E") { + # if there is no extuser counter row, start making extuser names at + # 'ext_1' - ( the 0 here is incremented after the recurse ) + $newmax = 0; + } elsif ($dom eq "A") { + $newmax = $dbh->selectrow_array("SELECT MAX(ansid) FROM support_answers"); + } else { + die "No alloc_global_counter initalizer for domain '$dom'"; + } + $newmax += 0; + $dbh->do("INSERT IGNORE INTO counter (journalid, area, max) VALUES (?,?,?)", + undef, $uid, $dom, $newmax) or return undef; + return LJ::alloc_global_counter($dom, 1); +} + +sub note_recent_action { + my ($cid, $action) = @_; + + # accept a user object + $cid = ref $cid ? $cid->{clusterid}+0 : $cid+0; + return undef unless $cid; + + my $flag = { post => 'P' }->{$action}; + + if (! $flag && LJ::are_hooks("recent_action_flags")) { + $flag = LJ::run_hook("recent_action_flags", $action); + die "Invalid flag received from hook: $flag" + unless $flag =~ /^_\w$/; # must be prefixed with '_' + } + + # should have a flag by now + return undef unless $flag; + + my $dbcm = LJ::get_cluster_master($cid) + or return undef; + + # append to recentactions table + $dbcm->do("INSERT DELAYED INTO recentactions VALUES (?)", undef, $flag); + return undef if $dbcm->err; + + return 1; +} + +# +# name: LJ::make_user_active +# des: Record user activity per cluster to +# make per-activity cluster stats easier. +# args: userobj, type +# arg-userid: source userobj ref +# arg-type: currently unused +# +sub mark_user_active { + my ($u, $type) = @_; # not currently using type + return 0 unless $u; # do not auto-vivify $u + my $uid = $u->{userid}; + return 0 unless $uid && $u->{clusterid}; + + # Update the clustertrack table, but not if we've done it for this + # user in the last hour. if no memcache servers are configured + # we don't do the optimization and just always log the activity info + if (@LJ::MEMCACHE_SERVERS == 0 || + LJ::MemCache::add("rate:tracked:$uid", 1, 3600)) { + + return 0 unless $u->writer; + $u->do("REPLACE INTO clustertrack2 SET ". + "userid=?, timeactive=?, clusterid=?", undef, + $uid, time(), $u->{clusterid}) or return 0; + } + return 1; +} + +# given a unix time, returns; +# ($week, $ubefore) +# week: week number (week 0 is first 3 days of unix time) +# ubefore: seconds before the next sunday, divided by 10 +sub weekuu_parts { + my $time = shift; + $time -= 86400*3; # time from the sunday after unixtime 0 + my $WEEKSEC = 86400*7; + my $week = int(($time+$WEEKSEC) / $WEEKSEC); + my $uafter = int(($time % $WEEKSEC) / 10); + my $ubefore = int(60480 - ($time % $WEEKSEC) / 10); + return ($week, $uafter, $ubefore); +} + +sub weekuu_before_to_time +{ + my ($week, $ubefore) = @_; + my $WEEKSEC = 86400*7; + my $time = $week * $WEEKSEC + 86400*3; + $time -= 10 * $ubefore; + return $time; +} + +sub weekuu_after_to_time +{ + my ($week, $uafter) = @_; + my $WEEKSEC = 86400*7; + my $time = ($week-1) * $WEEKSEC + 86400*3; + $time += 10 * $uafter; + return $time; +} + +sub is_open_proxy +{ + my $ip = shift; + eval { $ip ||= Apache->request; }; + return 0 unless $ip; + if (ref $ip) { $ip = $ip->connection->remote_ip; } + + my $dbr = LJ::get_db_reader(); + my $stat = $dbr->selectrow_hashref("SELECT status, asof FROM openproxy WHERE addr=?", + undef, $ip); + + # only cache 'clear' hosts for a day; 'proxy' for two days + $stat = undef if $stat && $stat->{'status'} eq "clear" && $stat->{'asof'} > 0 && $stat->{'asof'} < time()-86400; + $stat = undef if $stat && $stat->{'status'} eq "proxy" && $stat->{'asof'} < time()-2*86400; + + # open proxies are considered open forever, unless cleaned by another site-local mechanism + return 1 if $stat && $stat->{'status'} eq "proxy"; + + # allow things to be cached clear for a day before re-checking + return 0 if $stat && $stat->{'status'} eq "clear"; + + # no RBL defined? + return 0 unless @LJ::RBL_LIST; + + my $src = undef; + my $rev = join('.', reverse split(/\./, $ip)); + foreach my $rbl (@LJ::RBL_LIST) { + my @res = gethostbyname("$rev.$rbl"); + if ($res[4]) { + $src = $rbl; + last; + } + } + + my $dbh = LJ::get_db_writer(); + if ($src) { + $dbh->do("REPLACE INTO openproxy (addr, status, asof, src) VALUES (?,?,?,?)", undef, + $ip, "proxy", time(), $src); + return 1; + } else { + $dbh->do("INSERT IGNORE INTO openproxy (addr, status, asof, src) VALUES (?,?,?,?)", undef, + $ip, "clear", time(), $src); + return 0; + } +} + +# loads an include file, given the bare name of the file. +# ($filename) +# returns the text of the file. if the file is specified in %LJ::FILEEDIT_VIA_DB +# then it is loaded from memcache/DB, else it falls back to disk. +sub load_include { + my $file = shift; + return unless $file && $file =~ /^[a-zA-Z0-9-_\.]{1,255}$/; + + # okay, edit from where? + if ($LJ::FILEEDIT_VIA_DB || $LJ::FILEEDIT_VIA_DB{$file}) { + # we handle, so first if memcache... + my $val = LJ::MemCache::get("includefile:$file"); + return $val if $val; + + # straight database hit + my $dbh = LJ::get_db_writer(); + $val = $dbh->selectrow_array("SELECT inctext FROM includetext ". + "WHERE incname=?", undef, $file); + LJ::MemCache::set("includefile:$file", $val, time() + 3600); + return $val; + } + + # hit it up from the file, if it exists + my $filename = "$ENV{'LJHOME'}/htdocs/inc/$file"; + return unless -e $filename; + + # get it and return it + my $val; + open (INCFILE, $filename) + or return "Could not open include file: $file."; + { local $/ = undef; $val = ; } + close INCFILE; + return $val; +} + +# +# name: LJ::infohistory_add +# des: Add a line of text to the infohistory table for an account. +# args: uuid, what, value, other? +# des-uuid: User id or user object to insert infohistory for. +# des-what: What type of history being inserted (15 chars max). +# des-value: Value for the item (255 chars max). +# des-other: Extra information (30 chars max). +# returns: 1 on success, 0 on error. +# +sub infohistory_add { + my ($uuid, $what, $value, $other) = @_; + $uuid = LJ::want_userid($uuid); + return unless $uuid && $what && $value; + + # get writer and insert + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO infohistory (userid, what, timechange, oldvalue, other) VALUES (?, ?, NOW(), ?, ?)", + undef, $uuid, $what, $value, $other); + return $dbh->err ? 0 : 1; +} + +# +# name: LJ::bit_breakdown +# des: Breaks down a bitmask into an array of bits enabled. +# args: mask +# des-mask: The number to break down. +# returns: A list of bits enabled. E.g., 3 returns (0, 2) indicating that bits 0 and 2 (numbering +# from the right) are currently on. +# +sub bit_breakdown { + my $mask = shift()+0; + + # check each bit 0..31 and return only ones that are defined + return grep { defined } + map { $mask & (1<<$_) ? $_ : undef } 0..31; +} + +sub last_error_code +{ + return $LJ::last_error; +} + +sub last_error +{ + my $err = { + 'utf8' => "Encoding isn't valid UTF-8", + 'db' => "Database error", + 'comm_not_found' => "Community not found", + 'comm_not_comm' => "Account not a community", + 'comm_not_member' => "User not a member of community", + 'comm_invite_limit' => "Outstanding invitation limit reached", + 'comm_user_has_banned' => "Unable to invite; user has banned community", + }; + my $des = $err->{$LJ::last_error}; + if ($LJ::last_error eq "db" && $LJ::db_error) { + $des .= ": $LJ::db_error"; + } + return $des || $LJ::last_error; +} + +sub error +{ + my $err = shift; + if (isdb($err)) { + $LJ::db_error = $err->errstr; + $err = "db"; + } elsif ($err eq "db") { + $LJ::db_error = ""; + } + $LJ::last_error = $err; + return undef; +} + +# to be called as &nodb; (so this function sees caller's @_) +sub nodb { + shift @_ if + ref $_[0] eq "LJ::DBSet" || ref $_[0] eq "DBI::db" || + ref $_[0] eq "DBIx::StateKeeper" || ref $_[0] eq "Apache::DBI::db"; +} + +sub isdb { return ref $_[0] && (ref $_[0] eq "DBI::db" || + ref $_[0] eq "DBIx::StateKeeper" || + ref $_[0] eq "Apache::DBI::db"); } + +# is a user object (at least a hashref) +sub isu { return ref $_[0] && (ref $_[0] eq "LJ::User" || + ref $_[0] eq "HASH" && $_[0]->{userid}); } + +use vars qw($AUTOLOAD); +sub AUTOLOAD { + if ($AUTOLOAD eq "LJ::send_mail") { + require "$ENV{'LJHOME'}/cgi-bin/ljmail.pl"; + goto &$AUTOLOAD; + } + croak "Undefined subroutine: $AUTOLOAD"; +} + +# LJ::S1::get_public_styles lives here in ljlib.pl so that +# cron jobs can call LJ::load_user_props without including +# ljviews.pl +package LJ::S1; + +sub get_public_styles { + + my $opts = shift; + + # Try memcache if no extra options are requested + my $memkey = "s1pubstyc"; + my $pubstyc = {}; + unless ($opts) { + my $pubstyc = LJ::MemCache::get($memkey); + return $pubstyc if $pubstyc; + } + + # not cached, build from db + my $sysid = LJ::get_userid("system"); + + # all cols *except* formatdata, which is big and unnecessary for most uses. + # it'll be loaded by LJ::S1::get_style + my $cols = "styleid, styledes, type, is_public, is_embedded, ". + "is_colorfree, opt_cache, has_ads, lastupdate"; + $cols .= ", formatdata" if $opts->{'formatdata'}; + + # first try new table + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT userid, $cols FROM s1style WHERE userid=? AND is_public='Y'"); + $sth->execute($sysid); + $pubstyc->{$_->{'styleid'}} = $_ while $_ = $sth->fetchrow_hashref; + + # fall back to old table + unless (%$pubstyc) { + $sth = $dbh->prepare("SELECT user, $cols FROM style WHERE user='system' AND is_public='Y'"); + $sth->execute(); + $pubstyc->{$_->{'styleid'}} = $_ while $_ = $sth->fetchrow_hashref; + } + return undef unless %$pubstyc; + + # set in memcache + unless ($opts) { + my $expire = time() + 60*30; # 30 minutes + LJ::MemCache::set($memkey, $pubstyc, $expire); + } + + return $pubstyc; +} + +# this package also doesn't belong in ljlib.pl, and should probably be +# moved back to ljemailgateway.pl soon, but the web code needed this, +# as well as the mailgated code, so putting it in weblib.pl doesn't +# work, and making modperl-subs.pl include ljemailgateway.pl was +# problematic during the woody-sarge transition (still happening), so +# for now it's here in ljlib. +package LJ::Emailpost; + +# Retreives an allowed email addr list for a given user object. +# Returns a hashref with addresses / flags. +# Used for ljemailgateway and manage/emailpost.bml +sub get_allowed_senders { + my $u = shift; + my (%addr, @address); + + LJ::load_user_props($u, 'emailpost_allowfrom'); + @address = split(/\s*,\s*/, $u->{emailpost_allowfrom}); + return undef unless scalar(@address) > 0; + + my %flag_english = ( 'E' => 'get_errors' ); + + foreach my $add (@address) { + my $flags; + $flags = $1 if $add =~ s/\((.+)\)$//; + $addr{$add} = {}; + if ($flags) { + $addr{$add}->{$flag_english{$_}} = 1 foreach split(//, $flags); + } + } + + return \%addr; +} + +# Inserts email addresses into the database. +# Adds flags if needed. +# Used in manage/emailpost.bml +sub set_allowed_senders { + my ($u, $addr) = @_; + my %flag_letters = ( 'get_errors' => 'E' ); + + my @addresses; + foreach (keys %$addr) { + my $email = $_; + my $flags = $addr->{$_}; + if (%$flags) { + $email .= '('; + foreach my $flag (keys %$flags) { + $email .= $flag_letters{$flag}; + } + $email .= ')'; + } + push(@addresses, $email); + } + close T; + LJ::set_userprop($u, "emailpost_allowfrom", join(", ", @addresses)); +} + +1; diff --git a/livejournal/cgi-bin/ljlinks.pl b/livejournal/cgi-bin/ljlinks.pl new file mode 100755 index 0000000..c715142 --- /dev/null +++ b/livejournal/cgi-bin/ljlinks.pl @@ -0,0 +1,218 @@ +#!/usr/bin/perl + +# +# Functions for lists of links created by users for display in their journals +# + +use strict; + +package LJ::Links; + +# linkobj structure: +# +# $linkobj = [ +# { 'title' => 'link title', +# 'url' => 'http://www.somesite.com', +# 'children' => [ ... ], +# }, +# { ... }, +# { ... }, +# ]; + +sub load_linkobj +{ + my ($u, $use_master) = @_; + return unless LJ::isu($u); + + # check memcache for linkobj + my $memkey = [$u->{'userid'}, "linkobj:$u->{'userid'}"]; + my $linkobj = LJ::MemCache::get($memkey); + return $linkobj if defined $linkobj; + + # didn't find anything in memcache + $linkobj = []; + + { + # not in memcache, need to build one from db + my $db = $use_master ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + + local $" = ","; + my $sth = $db->prepare("SELECT ordernum, parentnum, title, url " . + "FROM links WHERE journalid=?"); + $sth->execute($u->{'userid'}); + push @$linkobj, $_ while $_ = $sth->fetchrow_hashref; + } + + # sort in perl-space + @$linkobj = sort { $a->{'ordernum'} <=> $b->{'ordernum'} } @$linkobj; + + # fix up the data structure + foreach (@$linkobj) { + + # TODO: build child relationships + # and store in $_->{'children'} + + # ordernum/parentnum are only exposed via the + # array structure, delete them here + delete $_->{'ordernum'}; + delete $_->{'parentnum'}; + } + + # set linkobj in memcache + LJ::MemCache::set($memkey, $linkobj); + + return $linkobj; +} + +sub save_linkobj +{ + my ($u, $linkobj) = @_; + return undef unless LJ::isu($u) && ref $linkobj eq 'ARRAY' && $u->writer; + + # delete old links, we'll rebuild them shortly + $u->do("DELETE FROM links WHERE journalid=?", undef, $u->{'userid'}); + + # only save allowed number of links + my $numlinks = @$linkobj; + my $caplinks = LJ::get_cap($u, "userlinks"); + $numlinks = $caplinks if $numlinks > $caplinks; + + # build insert query + my (@bind, @vals); + foreach my $ct (1..$numlinks) { + my $it = $linkobj->[$ct-1]; + + # journalid, ordernum, parentnum, url, title + push @bind, "(?,?,?,?,?)"; + push @vals, ($u->{'userid'}, $ct, 0, $it->{'url'}, $it->{'title'}); + } + + # invalidate memcache + my $memkey = [$u->{'userid'}, "linkobj:$u->{'userid'}"]; + LJ::MemCache::delete($memkey); + + # insert into database + { + local $" = ","; + return $u->do("INSERT INTO links (journalid, ordernum, parentnum, url, title) " . + "VALUES @bind", undef, @vals); + } +} + +sub make_linkobj_from_form +{ + my ($u, $post) = @_; + return unless LJ::isu($u) && ref $post eq 'HASH'; + + my $linkobj = []; + + # remove leading and trailing spaces + my $stripspaces = sub { + my $str = shift; + $str =~ s/^\s*//; + $str =~ s/\s*$//; + return $str; + }; + + # find number of links allowed + my $numlinks = $post->{'numlinks'}; + my $caplinks = LJ::get_cap($u, "userlinks"); + $numlinks = $caplinks if $numlinks > $caplinks; + + foreach my $num (sort { $post->{"link_${a}_ordernum"} <=> + $post->{"link_${b}_ordernum"} } (1..$numlinks)) { + + # title is required + my $title = $post->{"link_${num}_title"}; + $title = $stripspaces->($title); + next unless $title; + + my $url = $post->{"link_${num}_url"}; + $url = $stripspaces->($url); + + # smartly add http:// to url unless they are just inserting a blank line + if ($url && $title ne '-') { + $url = LJ::CleanHTML::canonical_url($url); + } + + # build link object element + $post->{"link_${num}_url"} = $url; + push @$linkobj, { 'title' => $title, 'url' => $url }; + + # TODO: build child relationships + # push @{$linkobj->[$parentnum-1]->{'children'}}, $myself + } + + return $linkobj; +} + +# this form is in the lib so we can put it in /customize/ directly later +sub make_modify_form +{ + my ($u, $linkobj, $post) = @_; + return unless LJ::isu($u) && ref $linkobj eq 'ARRAY' && ref $post eq 'HASH'; + + # TODO: parentnum column is not implemented yet + # -- it should link to the ordernum of the parent link + # so we can support nesting/categories of links + + my $LINK_MIN = 5; # how many do they start with ? + my $LINK_MORE = 5; # how many do they get when they click "more" + my $ORDER_STEP = 10; # step order numbers by + + # how many link inputs to show? + my $showlinks = $post->{'numlinks'} || @$linkobj; + my $caplinks = LJ::get_cap($u, "userlinks"); + $showlinks += $LINK_MORE if $post->{'action:morelinks'}; + $showlinks = $LINK_MIN if $showlinks < $LINK_MIN; + $showlinks = $caplinks if $showlinks > $caplinks; + + my $ret = ""; + $ret .= ""; + + foreach my $ct (1..$showlinks) { + my $it = $linkobj->[$ct-1] || {}; + + $ret .= ""; + + $ret .= ""; + + # blank line unless this is the last line + $ret .= "" + unless $ct >= $showlinks; + } + + # submit button + $ret .= ""; + + $ret .= "
    OrderTitle/URL 
    "; + $ret .= LJ::html_text({ 'name' => "link_${ct}_ordernum", + 'size' => 2, + 'value' => $ct * $ORDER_STEP }); + $ret .= ""; + + $ret .= LJ::html_text({ 'name' => "link_${ct}_title", + 'size' => 50, 'maxlength' => 255, + 'value' => $it->{'title'} }); + $ret .= " 
     "; + $ret .= LJ::html_text({ 'name' => "link_${ct}_url", + 'size' => 50, 'maxlength' => 255, + 'value' => $it->{'url'} || "http://"}); + + # more button at the end of the last line, but only if + # they are allowed more than the minimum + $ret .= " "; + if ($ct >= $showlinks && $caplinks > $LINK_MIN) { + $ret .= LJ::html_submit('action:morelinks', "More →", + { 'disabled' => $ct >= $caplinks, + 'noescape' => 1 }); + } + $ret .= "
     
    "; + $ret .= LJ::html_hidden('numlinks' => $showlinks); + $ret .= LJ::html_submit('action:savelinks', "Save Changes"); + $ret .= " 
    "; + + return $ret; +} + +1; diff --git a/livejournal/cgi-bin/ljmail.pl b/livejournal/cgi-bin/ljmail.pl new file mode 100755 index 0000000..5c4e470 --- /dev/null +++ b/livejournal/cgi-bin/ljmail.pl @@ -0,0 +1,356 @@ +#!/usr/bin/perl +# +# Send mail outbound using a weighted random selection. +# Supports a variety of mail protocols. +# + +package LJ; + +use strict; +use Text::Wrap (); +use MIME::Lite (); +use Time::HiRes qw/ gettimeofday tv_interval /; + +use IO::Socket::INET (); # temp, for use with DMTP + +require "$ENV{LJHOME}/cgi-bin/ljlib.pl"; + +sub maildebug ($); +sub store_message (%$$); + +# +# name: LJ::send_mail +# des: Sends email. Character set will only be used if message is not ascii. +# args: opt[, async_caller] +# des-opt: Hashref of arguments. Required: to, from, subject, body. +# Optional: toname, fromname, cc, bcc, charset, wrap +# +sub send_mail +{ + my $opts = shift; + my $async_caller = shift; + my $time = [gettimeofday()]; + + my ( + $proto, # what protocol we decided to use + $msg, # email message (ascii) + $data, # email message (MIME::Lite) + $server, # remote server object + $hostname # hostname of mailserver selected + ); + + # support being given a direct MIME::Lite object, + # for queued cmdbuffer 'frozen' retries + $data = ( ref $opts eq 'MIME::Lite' ) ? $opts : build_message($opts); + return 0 unless $data; + $msg = $data->as_string(); + + # ok, we're sending via the network. + # get a preferred server/protocol, or failover to cmdbuffer. + ( $server, $proto, $hostname ) = find_server(); + unless ( $server && $proto ) { + maildebug "Suitable mail transport not found."; + return store_message $data, undef; + } + my $info = "$hostname-$proto"; + + # Now we have an active server connection, + # and we know what protocol to use. + + # clean addresses. + my ( @recips, %headers ); + $headers{$_} = $data->get( $_ ) foreach qw/ from to cc bcc /; + + $opts->{'from'} = + ( Mail::Address->parse( $data->get('from') ) )[0]->address() + if $headers{'from'}; + + push @recips, map { $_->address() } Mail::Address->parse( $headers{'to'} ) if $headers{'to'}; + push @recips, map { $_->address() } Mail::Address->parse( $headers{'cc'} ) if $headers{'cc'}; + push @recips, map { $_->address() } Mail::Address->parse( $headers{'bcc'} ) if $headers{'bcc'}; + + unless (scalar @recips) { + maildebug "No recipients to send to!"; + return 0; + } + + # QMTP + if ( $proto eq 'qmtp' ) { + $server->recipient($_) foreach @recips; + $server->sender( $opts->{'from'} ); + $server->message($msg); + + # send! + my $response = $server->send() or return store_message $data, $info; + foreach ( keys %$response ) { + return store_message $data, $info + if $response->{$_} !~ /success/; + } + $server->disconnect(); + } + + # SMTP + if ( $proto eq 'smtp' ) { + + $server->mail( $opts->{'from'} ); + + # this would only fail on denied relay access + # or somesuch. + return store_message $data, $info unless + $server->to( join ', ', @recips ); + + $server->data(); + $server->datasend($msg); + $server->dataend(); + + $server->quit; + } + + # DMTP (Danga Mail Transfer Protocol) + # (slated for removal if our QMTP stuff is worry-free.) + if ( $proto eq 'dmtp' ) { + + my $len = length $msg; + my $env = $opts->{'from'}; + + $server->print("Content-Length: $len\r\n"); + $server->print("Envelope-Sender: $env\r\n\r\n$msg"); + + return store_message $data, $info + unless $server->getline() =~ /^OK/; + } + + # system mailer + if ( $proto eq 'sendmail' ) { + MIME::Lite->send( 'sendmail', $hostname ); + unless ( $data->send() ) { + maildebug "Unable to send via system mailer!"; + return store_message $data, 'sendmail'; + } + } + + report( $data, $time, $info, $async_caller ); + return 1; +} + +sub report +{ + my ( $data, $time, $info, $async_caller ) = @_; + + # report deliveries + my $notes = sprintf( + "Direct mail send to %s succeeded: %s", + $data->get('to') || + $data->get('cc') || + $data->get('bcc'), $data->get('subject') + ); + maildebug $notes; + + LJ::blocking_report( + $info, 'send_mail', + tv_interval( $time ), $notes + ) + unless $async_caller; + + return; +} + +# locate a network server, +# return (serverobj, protocol, hostname) +sub find_server +{ + # operate on a copy of the server list. + my @objects = @LJ::MAIL_TRANSPORTS; + + # backwards compatibility with earlier ljconfig. + unless (@objects) { + push @objects, [ 'sendmail', $LJ::SENDMAIL, 0 ] if $LJ::SENDMAIL; + push @objects, [ 'smtp', $LJ::SMTP_SERVER, 0 ] if $LJ::SMTP_SERVER; + push @objects, [ 'dmtp', $LJ::DMTP_SERVER, 1 ] if $LJ::DMTP_SERVER; + } + + my ( $server, $proto, $hostname ); + + while ( @objects && !$proto ) { + my $item = get_slice(@objects); + my $select = $objects[$item]; + + maildebug "Trying server $select->[1] ($select->[0])..."; + + # check service connectivity + + # QMTP + if ( $select->[0] eq 'qmtp' ) { + eval 'use Net::QMTP'; + if ($@) { + maildebug "Net::QMTP not installed?"; + splice @objects, $item, 1; + next; + } + + eval { + $server = Net::QMTP->new( $select->[1], ConnectTimeout => 10 ); + }; + } + + # SMTP + elsif ( $select->[0] eq 'smtp' ) { + eval 'use Net::SMTP'; + if ($@) { + maildebug "Net::SMTP not installed?"; + splice @objects, $item, 1; + next; + } + + eval { $server = Net::SMTP->new( $select->[1], Timeout => 10 ); }; + } + + # DMTP + elsif ( $select->[0] eq 'dmtp' ) { + my $host = $select->[1]; + my $port = $host =~ s/:(\d+)$// ? $1 : 7005; + + $server = IO::Socket::INET->new( + PeerAddr => $host, + PeerPort => $port, + Proto => 'tcp' + ); + } + + # system sendmail binary + elsif ( $select->[0] eq 'sendmail' ) { + my $sendmail = $1 if $select->[1] =~ /(\S+)/; + $server = $sendmail if -e $sendmail && -x _; + } + + else { + maildebug "Unknown mail protocol"; + splice @objects, $item, 1; + next; + } + + # do we have a server connection? + # if not, remove from our selection pool and try again. + if ( ! $server ) { + maildebug "Could not connect"; + splice @objects, $item, 1; + } + else { + maildebug "Connected"; + ( $proto, $hostname ) = ( $select->[0], $select->[1] ); + } + } + + return ( $server, $proto, $hostname ); +} + +# return a ready to stringify MIME::Lite object. +sub build_message +{ + my $opts = shift; + + my $body = $opts->{'wrap'} ? + Text::Wrap::wrap( '', '', $opts->{'body'} ) : + $opts->{'body'}; + + my $to = Mail::Address->new( $opts->{'toname'}, $opts->{'to'} ); + my $from = Mail::Address->new( $opts->{'fromname'}, $opts->{'from'} ); + + my $msg = MIME::Lite->new + ( + To => $to->format(), + From => $from->format(), + Cc => $opts->{'cc'} || '', + Bcc => $opts->{'bcc'} || '', + Data => "$body\n", + Subject => $opts->{'subject'}, + ); + return unless $msg; + + $msg->add(%{ $opts->{'headers'} }) if ref $opts->{'headers'}; + + $msg->attr("content-type.charset" => $opts->{'charset'}) + if $opts->{'charset'} && + ! (LJ::is_ascii($opts->{'body'}) && + LJ::is_ascii($opts->{'subject'})); + + return $msg; +} + +# return a weighted random slice from an array. +sub get_slice +{ + my @objects = @_; + + # Find cumulative values between weights, and in total. + my (@csums, $cumulative_sum); + @csums = map { $cumulative_sum += abs $_->[2] } @objects; + + # *nothing* has weight? (all zeros?) just choose one. + # same thing as equal weights. + return int rand scalar @objects unless $cumulative_sum; + + # Get a random number that will be compared to + # the 'window' of probability for quotes. + my $rand = rand $cumulative_sum; + + # Create number ranges between each cumulative value, + # and check the random number to see if it falls within + # the weighted 'window size'. + # Remember the array slice for matching the original object to. + my $lastval = 0; + my $slice = 0; + foreach (@csums) { + last if $rand >= $lastval && $rand <= $_; + $slice++; + $lastval = $_; + } + + return $slice; +} + +sub store_message (%$$) +{ + my ( $data, $type ) = @_; + $type ||= 'none'; + + maildebug "Storing message for retry."; + my $time = [ gettimeofday() ]; + + # try this on each cluster + my $frozen = Storable::freeze($data); + my $rval = LJ::do_to_cluster( + sub { + # first parameter is cluster id + return LJ::cmd_buffer_add( shift(@_), 0, 'send_mail', $frozen ); + } + ); + return undef unless $rval; + + my $notes = sprintf( + "Queued mail send to %s %s: %s", + $data->get('to'), $rval ? "succeeded" : "failed", + $data->get('subject') + ); + maildebug $notes; + + LJ::blocking_report( + $type, 'send_mail', + tv_interval($time), $notes + ); + + # we only attempt to store the message + # on delivery failure. if we're here, something + # failed, so always return false. + return 0; +} + +sub maildebug ($) +{ + return unless $LJ::EMAIL_OUTGOING_DEBUG; + print STDERR "ljmail: " . shift() . "\n"; +} + + +1; + diff --git a/livejournal/cgi-bin/ljmemories.pl b/livejournal/cgi-bin/ljmemories.pl new file mode 100755 index 0000000..e8e9b94 --- /dev/null +++ b/livejournal/cgi-bin/ljmemories.pl @@ -0,0 +1,543 @@ +#!/usr/bin/perl + +package LJ::Memories; +use strict; + +# +# name: LJ::Memories::count +# class: web +# des: Returns the number of memories that a user has. +# args: uuobj +# des-uuobj: Userid or user object to count memories of. +# returns: Some number; undef on error. +# +sub count { + my $u = shift; + $u = LJ::want_user($u); + return undef unless $u; + + # check memcache first + my $count = LJ::MemCache::get([$u->{userid}, "memct:$u->{userid}"]); + return $count if $count; + + # now count + if ($u->{dversion} > 5) { + my $dbcr = LJ::get_cluster_def_reader($u); + $count = $dbcr->selectrow_array('SELECT COUNT(*) FROM memorable2 WHERE userid = ?', + undef, $u->{userid}); + return undef if $dbcr->err; + } else { + my $dbh = LJ::get_db_writer(); + $count = $dbh->selectrow_array('SELECT COUNT(*) FROM memorable WHERE userid = ?', + undef, $u->{userid}); + return undef if $dbh->err; + } + $count += 0; + + # now put in memcache and return it + LJ::MemCache::set([$u->{userid}, "memct:$u->{userid}"], $count, 43200); # 12 hours + return $count; +} + +# +# name: LJ::Memories::create +# class: web +# des: Create a new memory for a user. +# args: uuobj, opts, kwids? +# des-uuobj: User id or user object to insert memory for. +# des-opts: Hashref of options that define the memory; keys = journalid, ditemid, des, security +# des-kwids: Optional; arrayref of keyword ids to categorize this memory under +# returns: 1 on success, undef on error +# +sub create { + my ($u, $opts, $kwids) = @_; + $u = LJ::want_user($u); + return undef unless $u && %{$opts || {}}; + + # make sure we got enough options + my ($userid, $journalid, $ditemid, $des, $security) = + ($u->{userid}, map { $opts->{$_} } qw(journalid ditemid des security)); + $userid += 0; + $journalid += 0; + $ditemid += 0; + $security ||= 'public'; + $kwids ||= [ LJ::get_keyword_id($u, '*') ]; # * means no category + $des = LJ::trim($des); + return undef unless $userid && $journalid && $ditemid && $des && $security && @$kwids; + return undef unless $security =~ /^(?:public|friends|private)$/; + + # we have valid data, now let's insert it + if ($u->{dversion} > 5) { + return undef unless $u->writer; + + # allocate memory id to use + my $memid = LJ::alloc_user_counter($u, 'R'); + return undef unless $memid; + + # insert main memory + $u->do("INSERT INTO memorable2 (userid, memid, journalid, ditemid, des, security) " . + "VALUES (?, ?, ?, ?, ?, ?)", undef, $userid, $memid, $journalid, $ditemid, $des, $security); + return undef if $u->err; + + # insert keywords + my $val = join ',', map { "($u->{userid}, $memid, $_)" } @$kwids; + $u->do("REPLACE INTO memkeyword2 (userid, memid, kwid) VALUES $val"); + + } else { + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + # insert main memory + $dbh->do("INSERT INTO memorable (userid, journalid, jitemid, des, security) " . + "VALUES (?, ?, ?, ?, ?)", undef, $userid, $journalid, $ditemid, $des, $security); + return undef if $dbh->err; + + # insert keywords + my $memid = $dbh->{mysql_insertid}+0; + my $val = join ',', map { "($memid, $_)" } @$kwids; + $dbh->do("REPLACE INTO memkeyword (memid, kwid) VALUES $val"); + } + + # clear out memcache + LJ::MemCache::delete([$u->{userid}, "memct:$u->{userid}"]); + return 1; +} + +# +# name: LJ::Memories::delete_by_id +# class: web +# des: Deletes a bunch of memories by memid. +# args: uuboj, memids +# des-uuobj: User id or user object to delete memories of. +# des-memids: Arrayref of memids. +# returns: 1 on success; undef on error. +# +sub delete_by_id { + my ($u, $memids) = @_; + $u = LJ::want_user($u); + $memids = [ $memids ] if $memids && !ref $memids; # so they can just pass a single thing... + return undef unless $u && @{$memids || []}; + + # setup + my ($db, $table) = $u->{dversion} > 5 ? + ($u, '2') : + (LJ::get_db_writer(), ''); + + # if dversion 5, verify the ids + my $in = join ',', map { $_+0 } @$memids; + if ($u->{dversion} == 5) { + $memids = $db->selectcol_arrayref("SELECT memid FROM memorable WHERE userid = ? AND memid IN ($in)", + undef, $u->{userid}); + return undef if $db->err; + return 1 unless @{$memids || []}; # if we got nothing, pretend success + $in = join ',', map { $_+0 } @$memids; + } + + # delete actual memory + $db->do("DELETE FROM memorable$table WHERE userid = ? AND memid IN ($in)", undef, $u->{userid}); + return undef if $db->err; + + # delete keyword associations + my $euser = $u->{dversion} > 5 ? "userid = $u->{userid} AND" : ''; + $db->do("DELETE FROM memkeyword$table WHERE $euser memid IN ($in)"); + + # delete cache of count + LJ::MemCache::delete([$u->{userid}, "memct:$u->{userid}"]); + + # success at this point, since the first delete succeeded + return 1; +} + +# +# name: LJ::Memories::get_keyword_counts +# class: web +# des: Get a list of keywords and the counts for memories, showing how many memories are under +# each keyword. +# args: uuobj, opts? +# des-uuobj: User id or object of user. +# des-opts: Optional; hashref passed to _memory_getter, suggested keys are security and filter +# if you want to get only certain memories in the keyword list +# returns: Hashref { kwid => count }; undef on error +# +sub get_keyword_counts { + my ($u, $opts) = @_; + $u = LJ::want_user($u); + return undef unless $u; + + # get all of the user's memories that fit the filtering + my $memories = LJ::Memories::get_by_user($u, { %{$opts || {}}, notext => 1 }); + return undef unless defined $memories; # error case + return {} unless %$memories; # just no memories case + my @memids = map { $_+0 } keys %$memories; + + # now let's get the keywords these memories use + my $in = join ',', @memids; + my $kwids; + if ($u->{dversion} > 5) { + my $dbcr = LJ::get_cluster_reader($u); + $kwids = $dbcr->selectcol_arrayref("SELECT kwid FROM memkeyword2 WHERE userid = ? AND memid IN ($in)", + undef, $u->{userid}); + return undef if $dbcr->err; + } else { + my $dbr = LJ::get_db_reader(); + $kwids = $dbr->selectcol_arrayref("SELECT kwid FROM memkeyword WHERE memid IN ($in)"); + return undef if $dbr->err; + } + + # and now combine them + my %res; + $res{$_}++ foreach @$kwids; + + # done, return + return \%res; +} + +# +# name: LJ::Memories::get_keywordids +# class: web +# des: Get all keyword ids a user has used for a certain memory. +# args: uuobj, memid +# des-uuobj: User id or user object to check memory of. +# des-memid: Memory id to get keyword ids for. +# returns: Arrayref of keywordids; undef on error. +# +sub get_keywordids { + my ($u, $memid) = @_; + $u = LJ::want_user($u); + $memid += 0; + return undef unless $u && $memid; + + # definitive reader/master because this function is usually called when + # someone is on an edit page. + my $kwids; + if ($u->{dversion} > 5) { + my $dbcr = LJ::get_cluster_def_reader($u); + $kwids = $dbcr->selectcol_arrayref('SELECT kwid FROM memkeyword2 WHERE userid = ? AND memid = ?', + undef, $u->{userid}, $memid); + return undef if $dbcr->err; + + } else { + my $dbh = LJ::get_db_writer(); + $kwids = $dbh->selectcol_arrayref('SELECT kwid FROM memkeyword WHERE memid = ?', undef, $memid); + return undef if $dbh->err; + } + + # all good, return + return $kwids; +} + +# +# name: LJ::Memories::update_memory +# class: web +# des: Updates the description and security of a memory. +# args: uuobj, memid, updopts +# des-uuobj: User id or user object to update memory of. +# des-memid: Memory id to update. +# des-updopts: Update options, hashref with keys 'des' and 'security', values being what +# you want to update the memory to have. +# returns: 1 on success, undef on error +# +sub update_memory { + my ($u, $memid, $upd) = @_; + $u = LJ::want_user($u); + $memid += 0; + return unless $u && $memid && %{$upd || {}}; + + # get database handle + my ($db, $table) = $u->{dversion} > 5 ? + ($u, '2') : + (LJ::get_db_writer(), ''); + return undef unless $db; + + # construct update lines... only valid things we can update are des and security + my @updates; + foreach my $what (keys %$upd) { + next unless $what =~ m/^(?:des|security)$/; + push @updates, "$what=" . $db->quote($upd->{$what}); + } + my $updstr = join ',', @updates; + + # now perform update + $db->do("UPDATE memorable$table SET $updstr WHERE userid = ? AND memid = ?", + undef, $u->{userid}, $memid); + return undef if $db->err; + return 1; +} + +# this messy function gets memories based on an options hashref. this is an +# API API and isn't recommended for use by BML etc... add to the API and have +# API functions call this if needed. +# +# options in $opts hashref: +# security => [ 'public', 'private', ... ], or some subset thereof +# filter => 'all' | 'own' | 'other', filter -- defaults to all +# notext => 1/0, if on, do not load/return description field +# byid => [ 1, 2, 3, ... ], load memories by *memid* +# byditemid => [ 1, 2, 3 ... ], load by ditemid (MUST specify journalid too) +# journalid => 1, find memories by ditemid (see above) for this journalid +# +# note that all memories are loaded from a single user, specified as the first +# parameter. does not let you load memories from more than one user. +sub _memory_getter { + my ($u, $opts) = @_; + $u = LJ::want_user($u); + $opts ||= {}; + return undef unless $u; + + # various selection options + my $secwhere = ''; + if (@{$opts->{security} || []}) { + my @secs; + foreach my $sec (@{$opts->{security}}) { + push @secs, $sec + if $sec =~ /^(?:public|friends|private)$/; + } + $secwhere = "AND security IN (" . join(',', map { "'$_'" } @secs) . ")"; + } + my $extrawhere; + if ($opts->{filter} eq 'all') { $extrawhere = ''; } + elsif ($opts->{filter} eq 'own') { $extrawhere = "AND journalid = $u->{userid}"; } + elsif ($opts->{filter} eq 'other') { $extrawhere = "AND journalid <> $u->{userid}"; } + my $des = $opts->{notext} ? '' : 'des, '; + my $selwhere; + if (@{$opts->{byid} || []}) { + # they want to get some explicit memories by memid + my $in = join ',', map { $_+0 } @{$opts->{byid}}; + $selwhere = "AND memid IN ($in)"; + } elsif ($opts->{byditemid} && $opts->{journalid}) { + # or, they want to see if a memory exists for a particular item + my $selitemid = $u->{dversion} > 5 ? "ditemid" : "jitemid"; + $opts->{byditemid} += 0; + $opts->{journalid} += 0; + $selwhere = "AND journalid = $opts->{journalid} AND $selitemid = $opts->{byditemid}"; + } elsif ($opts->{byditemid}) { + # get memory, OLD STYLE so journalid is 0 + my $selitemid = $u->{dversion} > 5 ? "ditemid" : "jitemid"; + $opts->{byditemid} += 0; + $selwhere = "AND journalid = 0 AND $selitemid = $opts->{byditemid}"; + } + + # load up memories into hashref + my (%memories, $sth); + if ($u->{dversion} > 5) { + # new clustered memories + my $dbcr = LJ::get_cluster_reader($u); + $sth = $dbcr->prepare("SELECT memid, userid, journalid, ditemid, $des security " . + "FROM memorable2 WHERE userid = ? $selwhere $secwhere $extrawhere"); + } else { + # old global memories + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT memid, userid, journalid, jitemid, $des security " . + "FROM memorable WHERE userid = ? $selwhere $secwhere $extrawhere"); + } + + # general execution and fetching for return + $sth->execute($u->{userid}); + return undef if $sth->err; + while ($_ = $sth->fetchrow_hashref()) { + # we have to do this ditemid->jitemid to make old code work, + # but this can probably go away at some point... + if (defined $_->{ditemid}) { + $_->{jitemid} = $_->{ditemid}; + } else { + $_->{ditemid} = $_->{jitemid}; + } + $memories{$_->{memid}} = $_; + } + return \%memories; +} + +# +# name: LJ::Memories::get_by_id +# class: web +# des: Get memories given some memory ids. +# args: uuobj, memids +# des-uuobj: User id or user object to get memories for. +# des-memids: The rest of the memory ids. Array. (Pass them in as individual parameters...) +# returns: Hashref of memories with keys being memid; undef on error. +# +sub get_by_id { + my $u = shift; + return {} unless @_; # make sure they gave us some ids + + # pass to getter to get by id + return LJ::Memories::_memory_getter($u, { byid => [ map { $_+0 } @_ ] }); +} + +# +# name: LJ::Memories::get_by_ditemid +# class: web +# des: Get memory for a given journal entry. +# args: uuobj, journalid, ditemid +# des-uuobj: User id or user object to get memories for. +# des-journalid: Userid for journal entry is in. +# des-ditemid: Display itemid of entry. +# returns: Hashref of individual memory. +# +sub get_by_ditemid { + my ($u, $jid, $ditemid) = @_; + $jid += 0; + $ditemid += 0; + return undef unless $ditemid; # _memory_getter checks $u and $jid isn't necessary + # because this might be an old-style memory + + # pass to getter with appropriate options + my $memhash = LJ::Memories::_memory_getter($u, { byditemid => $ditemid, journalid => $jid }); + return undef unless %{$memhash || {}}; + return [ values %$memhash ]->[0]; # ugly +} + +# +# name: LJ::Memories::get_by_user +# class: web +# des: Get memories given a user. +# args: uuobj +# des-uuobj: User id or user object to get memories for. +# returns: Hashref of memories with keys being memid; undef on error. +# +sub get_by_user { + # simply passes through to _memory_getter + return LJ::Memories::_memory_getter(@_); +} + +# +# name: LJ::Memories::get_by_keyword +# class: web +# des: Get memories given a user and a keyword/keyword id. +# args: uuobj, kwoid, opts +# des-uuobj: User id or user object to get memories for. +# des-kwoid: Keyword (string) or keyword id (number) to get memories for. +# des-opts: Hashref of extra options to pass through to memory getter. Suggested options +# are filter and security for limiting the memories returned. +# returns: Hashref of memories with keys being memid; undef on error. +# +sub get_by_keyword { + my ($u, $kwoid, $opts) = @_; + $u = LJ::want_user($u); + my $kwid = $kwoid+0; + my $kw = defined $kwoid && !$kwid ? $kwoid : undef; + return undef unless $u && ($kwid || defined $kw); + + # two entirely separate codepaths, depending on the user's dversion. + my $memids; + if ($u->{dversion} > 5) { + # the smart way + my $dbcr = LJ::get_cluster_reader($u); + return undef unless $dbcr; + + # get keyword id if we don't have it + if (defined $kw) { + $kwid = $dbcr->selectrow_array('SELECT kwid FROM userkeywords WHERE userid = ? AND keyword = ?', + undef, $u->{userid}, $kw)+0; + } + return undef unless $kwid; + + # now get the actual memory ids + $memids = $dbcr->selectcol_arrayref('SELECT memid FROM memkeyword2 WHERE userid = ? AND kwid = ?', + undef, $u->{userid}, $kwid); + return undef if $dbcr->err; + } else { + # the dumb way + my $dbr = LJ::get_db_reader(); + return undef unless $dbr; + + # get keyword id if we don't have it + if (defined $kw) { + $kwid = $dbr->selectrow_array('SELECT kwid FROM keywords WHERE keyword = ?', undef, $kw)+0; + } + return undef unless $kwid; + + # now get memory ids. this has to join. :( + $memids = $dbr->selectcol_arrayref('SELECT m.memid FROM memorable m, memkeyword mk ' . + 'WHERE m.userid = ? AND mk.memid = m.memid AND mk.kwid = ?', + undef, $u->{userid}, $kwid); + return undef if $dbr->err; + } + + # standard in both cases + return {} unless @{$memids || []}; + return LJ::Memories::_memory_getter($u, { %{$opts || {}}, byid => $memids }); +} + +# +# name: LJ::Memories::get_keywords +# class: +# des: Retrieves keyword/keyids without big joins, returns a hashref. +# args: uobj +# des-uobj: User object to get keyword pairs for. +# returns: Hashref; { keywordid => keyword } +# +sub get_keywords { + my $u = shift; + $u = LJ::want_user($u); + return undef unless $u; + + my $use_reader = 0; + my $memkey = [$u->{userid},"memkwid:$u->{userid}"]; + my $ret = LJ::MemCache::get($memkey); + return $ret if defined $ret; + $ret = {}; + + if ($u->{dversion} > 5) { + # new style clustered code + my $dbcm = LJ::get_cluster_def_reader($u); + unless ($dbcm) { + $use_reader = 1; + $dbcm = LJ::get_cluster_reader($u); + } + my $ids = $dbcm->selectcol_arrayref('SELECT DISTINCT kwid FROM memkeyword2 WHERE userid = ?', + undef, $u->{userid}); + if (@{$ids || []}) { + my $in = join ",", @$ids; + my $rows = $dbcm->selectall_arrayref('SELECT kwid, keyword FROM userkeywords ' . + "WHERE userid = ? AND kwid IN ($in)", undef, $u->{userid}); + $ret->{$_->[0]} = $_->[1] foreach @{$rows || []}; + } + + } else { + # old style code using global + my $dbh = LJ::get_db_writer(); + unless ($dbh) { + $use_reader = 1; + $dbh = LJ::get_db_reader(); + } + my $sth = $dbh->prepare("SELECT DISTINCT mk.kwid ". + "FROM ". + " memorable m FORCE INDEX (uniq),". + " memkeyword mk ". + "WHERE mk.memid=m.memid AND m.userid=?"); + $sth->execute($u->{userid}); + my @ids; + push @ids, $_ while $_ = $sth->fetchrow_array; + + if (@ids) { + my $in = join(",", @ids); + $sth = $dbh->prepare("SELECT kwid, keyword FROM keywords WHERE kwid IN ($in)"); + $sth->execute; + + while (my ($id,$kw) = $sth->fetchrow_array) { + $ret->{$id} = $kw; + } + } + } + + LJ::MemCache::set($memkey, $ret, 86400) unless $use_reader; + return $ret; +} + +# +# name: LJ::Memories::updated_keywords +# class: web +# des: Deletes memcached keyword data. +# args: uobj +# des-uobj: User object to clear memcached keywords for. +# returns: undef. +# +sub updated_keywords { + my $u = shift; + return unless ref $u; + LJ::MemCache::delete([$u->{userid},"memkwid:$u->{userid}"]); + return undef; +} + +1; diff --git a/livejournal/cgi-bin/ljpoll.pl b/livejournal/cgi-bin/ljpoll.pl new file mode 100755 index 0000000..f6e09c6 --- /dev/null +++ b/livejournal/cgi-bin/ljpoll.pl @@ -0,0 +1,952 @@ +#!/usr/bin/perl +# + +package LJ::Poll; + +use strict; +use HTML::TokeParser (); + +require "$ENV{'LJHOME'}/cgi-bin/cleanhtml.pl"; + +sub clean_poll +{ + my $ref = shift; + if ($$ref !~ /[<>]/) { + LJ::text_out($ref); + return; + } + + my $poll_eat = [qw[head title style layer iframe applet object]]; + my $poll_allow = [qw[a b i u strong em img]]; + my $poll_remove = [qw[bgsound embed object caption link font]]; + + LJ::CleanHTML::clean($ref, { + 'wordlength' => 40, + 'addbreaks' => 0, + 'eat' => $poll_eat, + 'mode' => 'deny', + 'allow' => $poll_allow, + 'remove' => $poll_remove, + }); + LJ::text_out($ref); +} + + +sub contains_new_poll +{ + my $postref = shift; + return ($$postref =~ /{'posterid'} += 0; + $iteminfo->{'journalid'} += 0; + + my $newdata; + + my $popen = 0; + my %popts; + + my $qopen = 0; + my %qopts; + + my $iopen = 0; + my %iopts; + + my @polls; # completed parsed polls + + my $p = HTML::TokeParser->new($postref); + + # if we're being called from mailgated, then we're not in web context and therefore + # do not have any BML::ml functionality. detect this now and report errors in a + # plaintext, non-translated form to be bounced via email. + my $have_bml = eval { BML::ml() } || ! $@; + + my $err = sub { + # more than one element, either make a call to BML::ml + # or build up a semi-useful error string from it + if (@_ > 1) { + if ($have_bml) { + $$error = BML::ml(@_); + return 0; + } + + $$error = shift() . ": "; + while (my ($k, $v) = each %{$_[0]}) { + $$error .= "$k=$v,"; + } + chop $$error; + return 0; + } + + # single element, either look up in %BML::ML or return verbatim + $$error = $have_bml ? $BML::ML{$_[0]} : $_[0]; + return 0; + }; + + while (my $token = $p->get_token) + { + my $type = $token->[0]; + my $append; + + if ($type eq "S") # start tag + { + my $tag = $token->[1]; + my $opts = $token->[2]; + + ######## Begin poll tag + + if ($tag eq "lj-poll") { + return $err->('poll.error.nested', { 'tag' => 'lj-poll' }) + if $popen; + + $popen = 1; + %popts = (); + $popts{'questions'} = []; + + $popts{'name'} = $opts->{'name'}; + $popts{'whovote'} = lc($opts->{'whovote'}) || "all"; + $popts{'whoview'} = lc($opts->{'whoview'}) || "all"; + + if ($popts{'whovote'} ne "all" && + $popts{'whovote'} ne "friends") + { + return $err->('poll.error.whovote'); + } + if ($popts{'whoview'} ne "all" && + $popts{'whoview'} ne "friends" && + $popts{'whoview'} ne "none") + { + return $err->('poll.error.whoview'); + } + } + + ######## Begin poll question tag + + elsif ($tag eq "lj-pq") + { + return $err->('poll.error.nested', { 'tag' => 'lj-pq' }) + if $qopen; + + return $err->('poll.error.missingljpoll') + unless $popen; + + $qopen = 1; + %qopts = (); + $qopts{'items'} = []; + + $qopts{'type'} = $opts->{'type'}; + if ($qopts{'type'} eq "text") { + my $size = 35; + my $max = 255; + if (defined $opts->{'size'}) { + if ($opts->{'size'} > 0 && + $opts->{'size'} <= 100) + { + $size = $opts->{'size'}+0; + } else { + return $err->('poll.error.badsize'); + } + } + if (defined $opts->{'maxlength'}) { + if ($opts->{'maxlength'} > 0 && + $opts->{'maxlength'} <= 255) + { + $max = $opts->{'maxlength'}+0; + } else { + return $err->('poll.error.badmaxlength'); + } + } + + $qopts{'opts'} = "$size/$max"; + } + if ($qopts{'type'} eq "scale") + { + my $from = 1; + my $to = 10; + my $by = 1; + + if (defined $opts->{'from'}) { + $from = int($opts->{'from'}); + } + if (defined $opts->{'to'}) { + $to = int($opts->{'to'}); + } + if (defined $opts->{'by'}) { + $by = int($opts->{'by'}); + } + if ($by < 1) { + return $err->('poll.error.scaleincrement'); + } + if ($from >= $to) { + return $err->('poll.error.scalelessto'); + } + if ((($to-$from)/$by) > 20) { + return $err->('poll.error.scaletoobig'); + } + $qopts{'opts'} = "$from/$to/$by"; + } + + $qopts{'type'} = lc($opts->{'type'}) || "text"; + + if ($qopts{'type'} ne "radio" && + $qopts{'type'} ne "check" && + $qopts{'type'} ne "drop" && + $qopts{'type'} ne "scale" && + $qopts{'type'} ne "text") + { + return $err->('poll.error.unknownpqtype'); + } + + + } + + ######## Begin poll item tag + + elsif ($tag eq "lj-pi") + { + if ($iopen) { + return $err->('poll.error.nested', { 'tag' => 'lj-pi' }); + } + if (! $qopen) { + return $err->('poll.error.missingljpq'); + } + if ($qopts{'type'} eq "text") + { + return $err->('poll.error.noitemstext'); + } + + $iopen = 1; + %iopts = (); + } + + #### not a special tag. dump it right back out. + + else + { + $append .= "<$tag"; + foreach (keys %$opts) { + $append .= " $_=\"$opts->{$_}\""; + } + $append .= ">"; + } + } + elsif ($type eq "E") + { + my $tag = $token->[1]; + + ##### end POLL + + if ($tag eq "lj-poll") { + return $err->('poll.error.tagnotopen', { 'tag' => 'lj-poll' }) + unless $popen; + + $popen = 0; + + return $err->('poll.error.noquestions') + unless @{$popts{'questions'}}; + + $popts{'journalid'} = $iteminfo->{'journalid'}; + $popts{'posterid'} = $iteminfo->{'posterid'}; + + push @polls, { %popts }; + + $append .= ""; + } + + ##### end QUESTION + + elsif ($tag eq "lj-pq") { + return $err->('poll.error.tagnotopen', { 'tag' => 'lj-pq' }) + unless $qopen; + + unless ($qopts{'type'} eq "scale" || + $qopts{'type'} eq "text" || + @{$qopts{'items'}}) + { + return $err->('poll.error.noitems'); + } + + $qopts{'qtext'} =~ s/^\s+//; + $qopts{'qtext'} =~ s/\s+$//; + my $len = length($qopts{'qtext'}) + or return $err->('poll.error.notext'); + + push @{$popts{'questions'}}, { %qopts }; + $qopen = 0; + + } + + ##### end ITEM + + elsif ($tag eq "lj-pi") { + return $err->('poll.error.tagnotopen', { 'tag' => 'lj-pi' }) + unless $iopen; + + $iopts{'item'} =~ s/^\s+//; + $iopts{'item'} =~ s/\s+$//; + + my $len = length($iopts{'item'}); + return $err->('poll.error.pitoolong', { 'len' => $len, }) + if $len > 255 || $len < 1; + + push @{$qopts{'items'}}, { %iopts }; + $iopen = 0; + } + + ###### not a special tag. + + else + { + $append .= ""; + } + } + elsif ($type eq "T" || $type eq "D") + { + $append = $token->[1]; + } + elsif ($type eq "C") { + # ignore comments + } + elsif ($type eq "PI") { + $newdata .= "[1]>"; + } + else { + $newdata .= "\n"; + } + + ##### append stuff to the right place + if (length($append)) + { + if ($iopen) { + $iopts{'item'} .= $append; + } + elsif ($qopen) { + $qopts{'qtext'} .= $append; + } + elsif ($popen) { + 0; # do nothing. + } else { + $newdata .= $append; + } + } + + } + + if ($popen) { return $err->('poll.error.unlockedtag', { 'tag' => 'lj-poll' }); } + if ($qopen) { return $err->('poll.error.unlockedtag', { 'tag' => 'lj-pq' }); } + if ($iopen) { return $err->('poll.error.unlockedtag', { 'tag' => 'lj-pi' }); } + + $$postref = $newdata; + return @polls; +} + +# preview poll +# -- accepts $poll hashref as found in the array returned by LJ::Poll::parse() +sub preview { + my $poll = shift; + return unless ref $poll eq 'HASH'; + + my $ret = ''; + + $ret .= "\n"; + $ret .= "" . BML::ml('poll.pollnum', { 'num' => 'xxxx' }) . ""; + if ($poll->{'name'}) { + LJ::Poll::clean_poll(\$poll->{'name'}); + $ret .= " $poll->{'name'}"; + } + $ret .= "
    \n"; + $ret .= BML::ml('poll.security', { 'whovote' => $BML::ML{'poll.security.'.$poll->{whovote}}, 'whoview' => $BML::ML{'poll.security.'.$poll->{whoview}}, }); + + # iterate through all questions + foreach my $q (@{$poll->{'questions'}}) { + if ($q->{'qtext'}) { + LJ::Poll::clean_poll(\$q->{'qtext'}); + $ret .= "

    $q->{'qtext'}

    \n"; + } + $ret .= "
    "; + + # text questions + if ($q->{'type'} eq 'text') { + my ($size, $max) = split(m!/!, $q->{'opts'}); + $ret .= LJ::html_text({ 'size' => $size, 'maxlength' => $max }); + + # scale questions + } elsif ($q->{'type'} eq 'scale') { + my ($from, $to, $by) = split(m!/!, $q->{'opts'}); + $by ||= 1; + my $count = int(($to-$from)/$by) + 1; + my $do_radios = ($count <= 11); + + # few opts, display radios + if ($do_radios) { + $ret .= "\n"; + for (my $at = $from; $at <= $to; $at += $by) { + $ret .= "\n"; + } + $ret .= "
    " . LJ::html_check({ 'type' => 'radio' }) . "
    $at
    \n"; + + # many opts, display select + } else { + my @optlist = (); + for (my $at = $from; $at <= $to; $at += $by) { + push @optlist, ('', $at); + } + $ret .= LJ::html_select({}, @optlist); + } + + # questions with items + } else { + + # drop-down list + if ($q->{'type'} eq 'drop') { + my @optlist = ('', ''); + foreach my $it (@{$q->{'items'}}) { + LJ::Poll::clean_poll(\$it->{'item'}); + push @optlist, ('', $it->{'item'}); + } + $ret .= LJ::html_select({}, @optlist); + + + # radio or checkbox + } else { + foreach my $it (@{$q->{'items'}}) { + LJ::Poll::clean_poll(\$it->{'item'}); + $ret .= LJ::html_check({ 'type' => $q->{'type'} }) . "$it->{'item'}
    \n"; + } + } + } + + $ret .= "
    \n"; + + } + + $ret .= LJ::html_submit('', $BML::ML{'poll.submit'}, { 'disabled' => 1 }) . "\n"; + $ret .= ""; + + return $ret; +} + +# note: $itemid is a $ditemid (display itemid, *256 + anum) +sub register +{ + &LJ::nodb; + my $dbh = LJ::get_db_writer(); + my $post = shift; + my $error = shift; + my $itemid = shift; + my @polls = @_; + + foreach my $po (@polls) + { + my %popts = %$po; + $popts{'itemid'} = $itemid+0; + + #### CREATE THE POLL! + + my $sth = $dbh->prepare("INSERT INTO poll (itemid, journalid, posterid, whovote, whoview, name) " . + "VALUES (?, ?, ?, ?, ?, ?)"); + $sth->execute($itemid, $popts{'journalid'}, $popts{'posterid'}, + $popts{'whovote'}, $popts{'whoview'}, $popts{'name'}); + if ($dbh->err) { + $$error = BML::ml('poll.dberror', { errmsg => $dbh->errstr }); + return 0; + } + my $pollid = $dbh->{'mysql_insertid'}; + + $$post =~ s///; # NOT global replace! + + ## start inserting poll questions + my $qnum = 0; + foreach my $q (@{$popts{'questions'}}) + { + $qnum++; + $sth = $dbh->prepare("INSERT INTO pollquestion (pollid, pollqid, sortorder, type, opts, qtext) " . + "VALUES (?, ?, ?, ?, ?, ?)"); + $sth->execute($pollid, $qnum, $qnum, $q->{'type'}, $q->{'opts'}, $q->{'qtext'}); + if ($dbh->err) { + $$error = BML::ml('poll.dberror.questions', { errmsg => $dbh->errstr }); + return 0; + } + + my $pollqid = $dbh->{'mysql_insertid'}; + + ## start inserting poll items + my $inum = 0; + foreach my $it (@{$q->{'items'}}) { + $inum++; + $dbh->do("INSERT INTO pollitem (pollid, pollqid, pollitid, sortorder, item) " . + "VALUES (?, ?, ?, ?, ?)", undef, $pollid, $qnum, $inum, $inum, $it->{'item'}); + if ($dbh->err) { + $$error = BML::ml('poll.dberror.items', { errmsg => $dbh->errstr }); + return 0; + } + } + ## end inserting poll items + + } + ## end inserting poll questions + + } ### end while over all poles + +} + +sub show_polls +{ + &LJ::nodb; + my $itemid = shift; + my $remote = shift; + my $postref = shift; + + $$postref =~ s//&show_poll($itemid, $remote, $1)/eg; +} + +sub show_poll +{ + &LJ::nodb; + my $dbr = LJ::get_db_reader(); + my $itemid = shift; + my $remote = shift; + my $pollid = shift; + my $opts = shift; # hashref. {"mode" => results/enter/ans} + my $sth; + + my $mode = $opts->{'mode'}; + $pollid += 0; + + my $po = $dbr->selectrow_hashref("SELECT * FROM poll WHERE pollid=?", undef, $pollid); + return "[" . BML::ml('poll.error.pollnotfound', { 'num' => $pollid }) . "]" unless $po; + return "[$BML::ML{'poll.error.noentry'}]" + if $itemid && $po->{'itemid'} != $itemid; + + my ($can_vote, $can_view) = find_security($po, $remote); + + # update the mode if we need to + $mode = 'results' unless $remote; + if (!$mode && $remote) { + my $time = $dbr->selectrow_array('SELECT datesubmit FROM pollsubmission '. + 'WHERE pollid=? AND userid=?', undef, $pollid, $remote->{userid}); + $mode = $time ? 'results' : $can_vote ? 'enter' : 'results'; + } + + ### load all the questions + my @qs; + $sth = $dbr->prepare('SELECT * FROM pollquestion WHERE pollid=?'); + $sth->execute($pollid); + push @qs, $_ while $_ = $sth->fetchrow_hashref; + @qs = sort { $a->{sortorder} <=> $b->{sortorder} } @qs; + + ### load all the items + my %its; + $sth = $dbr->prepare("SELECT pollqid, pollitid, item FROM pollitem WHERE pollid=? ORDER BY sortorder"); + $sth->execute($pollid); + while (my ($qid, $itid, $item) = $sth->fetchrow_array) { + push @{$its{$qid}}, [ $itid, $item ]; + } + + # see if we have a hook for alternate poll contents + my $ret = LJ::run_hook('alternate_show_poll_html', $po, $mode, \@qs); + return $ret if $ret; + + ### view answers to a particular question in a poll + if ($mode eq "ans") + { + return "[$BML::ML{'poll.error.cantview'}]" + unless $can_view; + + # get the question from @qs, which we loaded earlier + my $q; + foreach (@qs) { + $q = $_ if $_->{pollqid} == $opts->{qid}; + } + return "[$BML::ML{'poll.error.questionnotfound'}]" + unless $q; + + # get the item information from %its, also loaded earlier + my %it; + $it{$_->[0]} = $_->[1] foreach (@{$its{$opts->{qid}}}); + + LJ::Poll::clean_poll(\$q->{'qtext'}); + $ret .= $q->{'qtext'}; + $ret .= "

    "; + + my $LIMIT = 2000; + $sth = $dbr->prepare("SELECT u.user, pr.value, ps.datesubmit ". + "FROM useridmap u, pollresult pr, pollsubmission ps " . + "WHERE u.userid=pr.userid AND pr.pollid=? AND pollqid=? " . + "AND ps.pollid=pr.pollid AND ps.userid=pr.userid LIMIT $LIMIT"); + $sth->execute($pollid, $opts->{'qid'}); + + my @res; + push @res, $_ while $_ = $sth->fetchrow_hashref; + @res = sort { $a->{datesubmit} cmp $b->{datesubmit} } @res; + + foreach my $res (@res) { + my ($user, $value) = ($res->{user}, $res->{value}); + + ## some question types need translation; type 'text' doesn't. + if ($q->{'type'} eq "radio" || $q->{'type'} eq "drop") { + $value = $it{$value}; + } + elsif ($q->{'type'} eq "check") { + $value = join(", ", map { $it{$_} } split(/,/, $value)); + } + + LJ::Poll::clean_poll(\$value); + $ret .= "

    " . LJ::ljuser($user) . " -- $value

    \n"; + } + + # temporary + if (@res == $LIMIT) { + $ret .= "

    [$BML::ML{'poll.error.truncated'}]

    "; + } + + return $ret; + } + + # Users cannot vote unless they are logged in + return "" + if $mode eq 'enter' && !$remote; + + my $do_form = $mode eq 'enter' && $can_vote; + my %preval; + + if ($do_form) { + $sth = $dbr->prepare("SELECT pollqid, value FROM pollresult WHERE pollid=? AND userid=?"); + $sth->execute($pollid, $remote->{'userid'}); + while (my ($qid, $value) = $sth->fetchrow_array) { + $preval{$qid} = $value; + } + + $ret .= "
    "; + $ret .= LJ::form_auth(); + $ret .= LJ::html_hidden('pollid', $pollid); + } + + $ret .= "" . BML::ml('poll.pollnum', { 'num' => $pollid }) . " "; + if ($po->{'name'}) { + LJ::Poll::clean_poll(\$po->{'name'}); + $ret .= "$po->{'name'}"; + } + $ret .= "
    \n"; + $ret .= BML::ml('poll.security', { 'whovote' => $BML::ML{'poll.security.'.$po->{whovote}}, + 'whoview' => $BML::ML{'poll.security.'.$po->{whoview}} }); + my $text = LJ::run_hook('extra_poll_description', $po, \@qs); + $ret .= "
    $text" if $text; + + ## go through all questions, adding to buffer to return + foreach my $q (@qs) + { + my $qid = $q->{'pollqid'}; + LJ::Poll::clean_poll(\$q->{'qtext'}); + $ret .= "

    $q->{'qtext'}

    "; + + ### get statistics, for scale questions + my ($valcount, $valmean, $valstddev, $valmedian); + if ($q->{'type'} eq "scale") + { + ## manually add all the possible values, since they aren't in the database + ## (which was the whole point of making a "scale" type): + my ($from, $to, $by) = split(m!/!, $q->{'opts'}); + $by = 1 unless ($by > 0 and int($by) == $by); + for (my $at=$from; $at<=$to; $at+=$by) { + push @{$its{$qid}}, [ $at, $at ]; # note: fake itemid, doesn't matter, but needed to be unique + } + + $sth = $dbr->prepare("SELECT COUNT(*), AVG(value), STDDEV(value) FROM pollresult WHERE pollid=? AND pollqid=?"); + $sth->execute($pollid, $qid); + ($valcount, $valmean, $valstddev) = $sth->fetchrow_array; + + # find median: + $valmedian = 0; + if ($valcount == 1) { + $valmedian = $valmean; + } elsif ($valcount > 1) { + my ($mid, $fetch); + # fetch two mids and average if even count, else grab absolute middle + $fetch = ($valcount % 2) ? 1 : 2; + $mid = int(($valcount+1)/2); + my $skip = $mid-1; + + $sth = $dbr->prepare("SELECT value FROM pollresult WHERE pollid=? AND pollqid=? " . + "ORDER BY value+0 LIMIT $skip,$fetch"); + $sth->execute($pollid, $qid); + while (my ($v) = $sth->fetchrow_array) { + $valmedian += $v; + } + $valmedian /= $fetch; + } + } + + my $usersvoted = 0; + my %itvotes; + my $maxitvotes = 1; + + if ($mode eq "results") + { + ### to see individual's answers + $ret .= "$BML::ML{'poll.viewanswers'}
    "; + + ### but, if this is a non-text item, and we're showing results, need to load the answers: + if ($q->{'type'} ne "text") { + $sth = $dbr->prepare("SELECT value FROM pollresult WHERE pollid=? AND pollqid=?"); + $sth->execute($pollid, $qid); + while (my ($val) = $sth->fetchrow_array) { + $usersvoted++; + if ($q->{'type'} eq "check") { + foreach (split(/,/,$val)) { + $itvotes{$_}++; + } + } else { + $itvotes{$val}++; + } + } + + foreach (values %itvotes) { + $maxitvotes = $_ if ($_ > $maxitvotes); + } + } + } + + #### text questions are the easy case + + if ($q->{'type'} eq "text" && $do_form) { + my ($size, $max) = split(m!/!, $q->{'opts'}); + + $ret .= LJ::html_text({ 'size' => $size, 'maxlength' => $max, + 'name' => "pollq-$qid", 'value' => $preval{$qid} }); + } + + #### drop-down list + elsif ($q->{'type'} eq 'drop' && $do_form) { + my @optlist = ('', ''); + foreach my $it (@{$its{$qid}}) { + my ($itid, $item) = @$it; + LJ::Poll::clean_poll(\$item); + push @optlist, ($itid, $item); + } + $ret .= LJ::html_select({ 'name' => "pollq-$qid", + 'selected' => $preval{$qid} }, @optlist); + } + + #### scales (from 1-10) questions + + elsif ($q->{'type'} eq "scale" && $do_form) { + my ($from, $to, $by) = split(m!/!, $q->{'opts'}); + $by ||= 1; + my $count = int(($to-$from)/$by) + 1; + my $do_radios = ($count <= 11); + + # few opts, display radios + if ($do_radios) { + + $ret .= ""; + + for (my $at=$from; $at<=$to; $at+=$by) { + $ret .= ""; + } + + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => "pollq-$qid", + 'value' => $at, 'id' => "pollq-$pollid-$qid-$at", + 'selected' => (defined $preval{$qid} && $at == $preval{$qid}) }); + $ret .= "
    \n"; + + # many opts, display select + # but only if displaying form + } else { + + my @optlist = ('', ''); + for (my $at=$from; $at<=$to; $at+=$by) { + push @optlist, ($at, $at); + } + $ret .= LJ::html_select({ 'name' => "pollq-$qid", 'selected' => $preval{$qid} }, @optlist); + } + + } + + #### now, questions with items + + else + { + my $do_table = 0; + + if ($q->{'type'} eq "scale") { # implies ! do_form + my $stddev = sprintf("%.2f", $valstddev); + my $mean = sprintf("%.2f", $valmean); + $ret .= BML::ml('poll.scaleanswers', { 'mean' => $mean, 'median' => $valmedian, 'stddev' => $stddev }); + $ret .= "
    \n"; + $do_table = 1; + $ret .= ""; + } + + foreach my $it (@{$its{$qid}}) + { + my ($itid, $item) = @$it; + LJ::Poll::clean_poll(\$item); + + # displaying a radio or checkbox + if ($do_form) { + $ret .= LJ::html_check({ 'type' => $q->{'type'}, 'name' => "pollq-$qid", + 'value' => $itid, 'id' => "pollq-$pollid-$qid-$itid", + 'selected' => ($preval{$qid} =~ /\b$itid\b/) }); + $ret .= "
    "; + next; + } + + # displaying results + my $count = $itvotes{$itid}+0; + my $percent = sprintf("%.1f", (100 * $count / ($usersvoted||1))); + my $width = 20+int(($count/$maxitvotes)*380); + + if ($do_table) { + $ret .= ""; + $ret .= ""; + } else { + $ret .= "

    $item
    "; + $ret .= ""; + $ret .= "$count ($percent%)"; + $ret .= " "; + $ret .= "$count ($percent%)

    "; + } + } + + if ($do_table) { + $ret .= "
    $item"; + $ret .= "$count ($percent%)"; + $ret .= " "; + $ret .= "$count ($percent%)
    "; + } + + } + + $ret .= "
    "; + } + + if ($do_form) { + $ret .= LJ::html_submit('poll-submit', $BML::ML{'poll.submit'}) . "
    \n";; + } + + return $ret; +} + +sub find_security +{ + &LJ::nodb; + + my $po = shift; + my $remote = shift; + my $sth; + + ## if remote is poll owner, can do anything. + if ($remote && $remote->{'userid'} == $po->{'posterid'}) { + return (1, 1); + } + + ## need to be both a person and with a visible journal to vote + if ($remote && + ($remote->{'journaltype'} ne "P" || $remote->{'statusvis'} ne "V")) { + return (0, 0); + } + + my $is_friend = 0; + if (($po->{'whoview'} eq "friends" || + $po->{'whovote'} eq "friends") && $remote) + { + $is_friend = LJ::is_friend($po->{'journalid'}, $remote->{'userid'}); + } + + my %sec; + if ($po->{'whoview'} eq "all" || + ($po->{'whoview'} eq "friends" && $is_friend) || + ($po->{'whoview'} eq "none" && $remote && $remote->{'userid'} == $po->{'posterid'})) + { + $sec{'view'} = 1; + } + + if ($po->{'whovote'} eq "all" || + ($po->{'whovote'} eq "friends" && $is_friend)) + { + $sec{'vote'} = 1; + } + + if ($sec{'vote'} && (LJ::is_banned($remote, $po->{'journalid'}) || + LJ::is_banned($remote, $po->{'posterid'}))) { + $sec{'vote'} = 0; + } + + return ($sec{'vote'}, $sec{'view'}); +} + +sub submit +{ + &LJ::nodb; + + my $remote = shift; + my $form = shift; + my $error = shift; + my $sth; + + my $dbh = LJ::get_db_writer(); + + unless ($remote) { + $$error = $BML::ML{'error.noremote'}; # instead of , because errors are displayed in LJ::bad_input() + return 0; + } + + my $pollid = $form->{'pollid'}+0; + my $po = $dbh->selectrow_hashref("SELECT itemid, whovote, journalid, posterid, whoview, whovote, name ". + "FROM poll WHERE pollid=?", undef, $pollid); + unless ($po) { + $$error = $BML::ML{'poll.error.nopollid'}; + return 0; + } + + my ($can_vote, undef) = find_security($po, $remote); + + unless ($can_vote) { + $$error = $BML::ML{'poll.error.cantvote'}; + return 0; + } + + ### load all the questions + my @qs; + $sth = $dbh->prepare("SELECT pollqid, type, opts, qtext FROM pollquestion WHERE pollid=?"); + $sth->execute($pollid); + push @qs, $_ while $_ = $sth->fetchrow_hashref; + + foreach my $q (@qs) { + my $qid = $q->{'pollqid'}+0; + my $val = $form->{"pollq-$qid"}; + if ($q->{'type'} eq "check") { + ## multi-selected items are comma separated from htdocs/poll/index.bml + $val = join(",", sort { $a <=> $b } split(/,/, $val)); + } + if ($q->{'type'} eq "scale") { + my ($from, $to, $by) = split(m!/!, $q->{'opts'}); + if ($val < $from || $val > $to) { + # bogus! cheating? + $val = ""; + } + } + if ($val ne "") { + $dbh->do("REPLACE INTO pollresult (pollid, pollqid, userid, value) VALUES (?, ?, ?, ?)", + undef, $pollid, $qid, $remote->{'userid'}, $val); + } else { + $dbh->do("DELETE FROM pollresult WHERE pollid=? AND pollqid=? AND userid=?", + undef, $pollid, $qid, $remote->{'userid'}); + } + } + + ## finally, register the vote happened + $dbh->do("REPLACE INTO pollsubmission (pollid, userid, datesubmit) VALUES (?, ?, NOW())", + undef, $pollid, $remote->{'userid'}); + + return 1; +} + +1; diff --git a/livejournal/cgi-bin/ljprotocol.pl b/livejournal/cgi-bin/ljprotocol.pl new file mode 100755 index 0000000..d7106fb --- /dev/null +++ b/livejournal/cgi-bin/ljprotocol.pl @@ -0,0 +1,3287 @@ +#!/usr/bin/perl +# + +use strict; +use Unicode::MapUTF8 (); + +BEGIN { + # declare some charset aliases + # we need this at least for cases when the only name supported + # by MapUTF8.pm isn't recognized by browsers + # note: newer versions of MapUTF8 know these + { + my %alias = ( 'windows-1251' => 'cp1251', + 'windows-1252' => 'cp1252', + 'windows-1253' => 'cp1253', ); + foreach (keys %alias) { + next if Unicode::MapUTF8::utf8_supported_charset($_); + Unicode::MapUTF8::utf8_charset_alias($_, $alias{$_}); + } + } +} + +require "$ENV{'LJHOME'}/cgi-bin/ljpoll.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; +require "$ENV{'LJHOME'}/cgi-bin/console.pl"; +require "$ENV{'LJHOME'}/cgi-bin/taglib.pl"; + +# have to do this else mailgate will croak with email posting, but only want +# to do it if the site has enabled the hack +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl" if $LJ::NEW_ENTRY_CLEANUP_HACK; + +#### New interface (meta handler) ... other handlers should call into this. +package LJ::Protocol; + +# global declaration of this text since we use it in two places +our $CannotBeShown = '(cannot be shown)'; + +sub translate +{ + my ($u, $msg, $vars) = @_; + + LJ::load_user_props($u, "browselang") unless $u->{'browselang'}; + return LJ::Lang::get_text($u->{'browselang'}, "protocol.$msg", undef, $vars); +} + +sub error_message +{ + my $code = shift; + my $des; + if ($code =~ /^(\d\d\d):(.+)/) { + ($code, $des) = ($1, $2); + } + my %e = ( + # User Errors + "100" => "Invalid username", + "101" => "Invalid password", + "102" => "Can't use custom/private security on shared/community journals.", + "103" => "Poll error", + "104" => "Error adding one or more friends", + "105" => "Challenge expired", + "150" => "Can't post as non-user", + "151" => "Banned from journal", + "152" => "Can't make back-dated entries in non-personal journal.", + "153" => "Incorrect time value", + "154" => "Can't add a redirected account as a friend", + "155" => "Non-authenticated email address", + "156" => sub { # to reload w/o restart + LJ::tosagree_str('protocol' => 'text') || + LJ::tosagree_str('protocol' => 'title') + }, + + # Client Errors + "200" => "Missing required argument(s)", + "201" => "Unknown method", + "202" => "Too many arguments", + "203" => "Invalid argument(s)", + "204" => "Invalid metadata datatype", + "205" => "Unknown metadata", + "206" => "Invalid destination journal username.", + "207" => "Protocol version mismatch", + "208" => "Invalid text encoding", + "209" => "Parameter out of range", + "210" => "Client tried to edit with corrupt data. Preventing.", + "211" => "Invalid or malformed tag list", + + # Access Errors + "300" => "Don't have access to requested journal", + "301" => "Access of restricted feature", + "302" => "Can't edit post from requested journal", + "303" => "Can't edit post in community journal", + "304" => "Can't delete post in this community journal", + "305" => "Action forbidden; account is suspended.", + "306" => "This journal is temporarily in read-only mode. Try again in a couple minutes.", + "307" => "Selected journal no longer exists.", + "308" => "Account is locked and cannot be used.", + "309" => "Account is marked as a memorial.", + "310" => "Account needs to be age verified before use.", + "311" => "Access temporarily disabled.", + "312" => "Not allowed to add tags to entries in this journal", + "313" => "Must use existing tags for entries in this journal (can't create new ones)", + + # Limit errors + "402" => "Your IP address is temporarily banned for exceeding the login failure rate.", + "404" => "Cannot post", + "405" => "Post frequency limit.", + "406" => "Client is making repeated requests. Perhaps it's broken?", + "407" => "Moderation queue full", + "408" => "Maximum queued posts for this community+poster combination reached.", + "409" => "Post too large.", + "410" => "Your trial account has expired. Posting now disabled.", + + # Server Errors + "500" => "Internal server error", + "501" => "Database error", + "502" => "Database temporarily unavailable", + "503" => "Error obtaining necessary database lock", + "504" => "Protocol mode no longer supported.", + "505" => "Account data format on server is old and needs to be upgraded.", # cluster0 + "506" => "Journal sync temporarily unavailable.", + ); + + my $prefix = ""; + my $error = (ref $e{$code} eq 'CODE' ? $e{$code}->() : $e{$code}) || "BUG: Unknown error code!"; + if ($code >= 200) { $prefix = "Client error: "; } + if ($code >= 500) { $prefix = "Server error: "; } + my $totalerror = "$prefix$error"; + $totalerror .= ": $des" if $des; + return $totalerror; +} + +sub do_request +{ + # get the request and response hash refs + my ($method, $req, $err, $flags) = @_; + + # if version isn't specified explicitly, it's version 0 + if (ref $req eq "HASH") { + $req->{'ver'} = 0 unless defined $req->{'ver'}; + } + + $flags ||= {}; + my @args = ($req, $err, $flags); + + my $r = eval { Apache->request }; + $r->notes("codepath" => "protocol.$method") + if $r && ! $r->notes("codepath"); + + if ($method eq "login") { return login(@args); } + if ($method eq "getfriendgroups") { return getfriendgroups(@args); } + if ($method eq "getfriends") { return getfriends(@args); } + if ($method eq "friendof") { return friendof(@args); } + if ($method eq "checkfriends") { return checkfriends(@args); } + if ($method eq "getdaycounts") { return getdaycounts(@args); } + if ($method eq "postevent") { return postevent(@args); } + if ($method eq "editevent") { return editevent(@args); } + if ($method eq "syncitems") { return syncitems(@args); } + if ($method eq "getevents") { return getevents(@args); } + if ($method eq "editfriends") { return editfriends(@args); } + if ($method eq "editfriendgroups") { return editfriendgroups(@args); } + if ($method eq "consolecommand") { return consolecommand(@args); } + if ($method eq "getchallenge") { return getchallenge(@args); } + if ($method eq "sessiongenerate") { return sessiongenerate(@args); } + if ($method eq "sessionexpire") { return sessionexpire(@args); } + + $r->notes("codepath" => "") if $r; + return fail($err,201); +} + +sub login +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + + my $u = $flags->{'u'}; + my $res = {}; + my $ver = $req->{'ver'}; + + ## check for version mismatches + ## non-Unicode installations can't handle versions >=1 + + return fail($err,207, "This installation does not support Unicode clients") + if $ver>=1 and not $LJ::UNICODE; + + # do not let locked people log in + return fail($err, 308) if $u->{statusvis} eq 'L'; + + ## return a message to the client to be displayed (optional) + login_message($req, $res, $flags); + LJ::text_out(\$res->{'message'}) if $ver>=1 and defined $res->{'message'}; + + ## report what shared journals this user may post in + $res->{'usejournals'} = list_usejournals($u); + + ## return their friend groups + $res->{'friendgroups'} = list_friendgroups($u); + return fail($err, 502, "Error loading friend groups") unless $res->{'friendgroups'}; + if ($ver >= 1) { + foreach (@{$res->{'friendgroups'}}) { + LJ::text_out(\$_->{'name'}); + } + } + + ## if they gave us a number of moods to get higher than, then return them + if (defined $req->{'getmoods'}) { + $res->{'moods'} = list_moods($req->{'getmoods'}); + if ($ver >= 1) { + # currently all moods are in English, but this might change + foreach (@{$res->{'moods'}}) { LJ::text_out(\$_->{'name'}) } + } + } + + ### picture keywords, if they asked for them. + if ($req->{'getpickws'}) { + my $pickws = list_pickws($u); + $res->{'pickws'} = [ map { $_->[0] } @$pickws ]; + if ($req->{'getpickwurls'}) { + if ($u->{'defaultpicid'}) { + $res->{'defaultpicurl'} = "$LJ::USERPIC_ROOT/$u->{'defaultpicid'}/$u->{'userid'}"; + } + $res->{'pickwurls'} = [ map { + "$LJ::USERPIC_ROOT/$_->[1]/$u->{'userid'}" + } @$pickws ]; + } + if ($ver >= 1) { + # validate all text + foreach(@{$res->{'pickws'}}) { LJ::text_out(\$_); } + foreach(@{$res->{'pickwurls'}}) { LJ::text_out(\$_); } + LJ::text_out(\$res->{'defaultpicurl'}); + } + } + + ## return client menu tree, if requested + if ($req->{'getmenus'}) { + $res->{'menus'} = hash_menus($u); + if ($ver >= 1) { + # validate all text, just in case, even though currently + # it's all English + foreach (@{$res->{'menus'}}) { + LJ::text_out(\$_->{'text'}); + LJ::text_out(\$_->{'url'}); # should be redundant + } + } + } + + ## tell some users they can hit the fast servers later. + $res->{'fastserver'} = 1 if LJ::get_cap($u, "fastserver"); + + ## user info + $res->{'userid'} = $u->{'userid'}; + $res->{'fullname'} = $u->{'name'}; + LJ::text_out(\$res->{'fullname'}) if $ver >= 1; + + if ($req->{'clientversion'} =~ /^\S+\/\S+$/) { + eval { + my $r = Apache->request; + $r->notes("clientver", $req->{'clientversion'}); + }; + } + + ## update or add to clientusage table + if ($req->{'clientversion'} =~ /^\S+\/\S+$/ && + ! $LJ::DISABLED{'clientversionlog'}) + { + my $client = $req->{'clientversion'}; + + return fail($err, 208, "Bad clientversion string") + if $ver >= 1 and not LJ::text_in($client); + + my $dbh = LJ::get_db_writer(); + my $qclient = $dbh->quote($client); + my $cu_sql = "REPLACE INTO clientusage (userid, clientid, lastlogin) " . + "SELECT $u->{'userid'}, clientid, NOW() FROM clients WHERE client=$qclient"; + my $sth = $dbh->prepare($cu_sql); + $sth->execute; + unless ($sth->rows) { + # only way this can be 0 is if client doesn't exist in clients table, so + # we need to add a new row there, to get a new clientid for this new client: + $dbh->do("INSERT INTO clients (client) VALUES ($qclient)"); + # and now we can do the query from before and it should work: + $sth = $dbh->prepare($cu_sql); + $sth->execute; + } + } + + return $res; +} + +sub getfriendgroups +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + my $u = $flags->{'u'}; + my $res = {}; + $res->{'friendgroups'} = list_friendgroups($u); + return fail($err, 502, "Error loading friend groups") unless $res->{'friendgroups'}; + if ($req->{'ver'} >= 1) { + foreach (@{$res->{'friendgroups'} || []}) { + LJ::text_out(\$_->{'name'}); + } + } + return $res; +} + +sub getfriends +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return fail($req,502) unless LJ::get_db_reader(); + my $u = $flags->{'u'}; + my $res = {}; + if ($req->{'includegroups'}) { + $res->{'friendgroups'} = list_friendgroups($u); + return fail($err, 502, "Error loading friend groups") unless $res->{'friendgroups'}; + if ($req->{'ver'} >= 1) { + foreach (@{$res->{'friendgroups'} || []}) { + LJ::text_out(\$_->{'name'}); + } + } + } + # TAG:FR:protocol:getfriends_of + if ($req->{'includefriendof'}) { + $res->{'friendofs'} = list_friends($u, { + 'limit' => $req->{'friendoflimit'}, + 'friendof' => 1, + }); + if ($req->{'ver'} >= 1) { + foreach(@{$res->{'friendofs'}}) { LJ::text_out(\$_->{'fullname'}) }; + } + } + # TAG:FR:protocol:getfriends + $res->{'friends'} = list_friends($u, { + 'limit' => $req->{'friendlimit'}, + 'includebdays' => $req->{'includebdays'}, + }); + if ($req->{'ver'} >= 1) { + foreach(@{$res->{'friends'}}) { LJ::text_out(\$_->{'fullname'}) }; + } + return $res; +} + +sub friendof +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return fail($req,502) unless LJ::get_db_reader(); + my $u = $flags->{'u'}; + my $res = {}; + + # TAG:FR:protocol:getfriends_of2 (same as TAG:FR:protocol:getfriends_of) + $res->{'friendofs'} = list_friends($u, { + 'friendof' => 1, + 'limit' => $req->{'friendoflimit'}, + }); + if ($req->{'ver'} >= 1) { + foreach(@{$res->{'friendofs'}}) { LJ::text_out(\$_->{'fullname'}) }; + } + return $res; +} + +sub checkfriends +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + my $u = $flags->{'u'}; + my $res = {}; + + # return immediately if they can't use this mode + unless (LJ::get_cap($u, "checkfriends")) { + $res->{'new'} = 0; + $res->{'interval'} = 36000; # tell client to bugger off + return $res; + } + + ## have a valid date? + my $lastupdate = $req->{'lastupdate'}; + if ($lastupdate) { + return fail($err,203) unless + ($lastupdate =~ /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/); + } else { + $lastupdate = "0000-00-00 00:00:00"; + } + + my $interval = LJ::get_cap_min($u, "checkfriends_interval"); + $res->{'interval'} = $interval; + + my $mask; + if ($req->{'mask'} and $req->{'mask'} !~ /\D/) { + $mask = $req->{'mask'}; + } + + my $memkey = [$u->{'userid'},"checkfriends:$u->{userid}:$mask"]; + my $update = LJ::MemCache::get($memkey); + unless ($update) { + # TAG:FR:protocol:checkfriends (wants reading list of mask, not "friends") + my $fr = LJ::get_friends($u, $mask); + unless ($fr && %$fr) { + $res->{'new'} = 0; + $res->{'lastupdate'} = $lastupdate; + return $res; + } + if (@LJ::MEMCACHE_SERVERS) { + my $tu = LJ::get_timeupdate_multi({ memcache_only => 1 }, keys %$fr); + my $max = 0; + while ($_ = each %$tu) { + $max = $tu->{$_} if $tu->{$_} > $max; + } + $update = LJ::mysql_time($max) if $max; + } else { + my $dbr = LJ::get_db_reader(); + unless ($dbr) { + # rather than return a 502 no-db error, just say no updates, + # because problem'll be fixed soon enough by db admins + $res->{'new'} = 0; + $res->{'lastupdate'} = $lastupdate; + return $res; + } + my $list = join(", ", map { int($_) } keys %$fr); + if ($list) { + my $sql = "SELECT MAX(timeupdate) FROM userusage ". + "WHERE userid IN ($list)"; + $update = $dbr->selectrow_array($sql); + } + } + LJ::MemCache::set($memkey,$update,time()+$interval) if $update; + } + $update ||= "0000-00-00 00:00:00"; + + if ($req->{'lastupdate'} && $update gt $lastupdate) { + $res->{'new'} = 1; + } else { + $res->{'new'} = 0; + } + + $res->{'lastupdate'} = $update; + return $res; +} + +sub getdaycounts +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return undef unless check_altusage($req, $err, $flags); + + my $u = $flags->{'u'}; + my $uowner = $flags->{'u_owner'} || $u; + my $ownerid = $flags->{'ownerid'}; + + my $res = {}; + my $daycts = LJ::get_daycounts($uowner, $u); + return fail($err,502) unless $daycts; + + foreach my $day (@$daycts) { + my $date = sprintf("%04d-%02d-%02d", $day->[0], $day->[1], $day->[2]); + push @{$res->{'daycounts'}}, { 'date' => $date, 'count' => $day->[3] }; + } + return $res; +} + +sub common_event_validation +{ + my ($req, $err, $flags) = @_; + + # clean up event whitespace + # remove surrounding whitespace + $req->{event} =~ s/^\s+//; + $req->{event} =~ s/\s+$//; + + # convert line endings to unix format + if ($req->{'lineendings'} eq "mac") { + $req->{event} =~ s/\r/\n/g; + } else { + $req->{event} =~ s/\r//g; + } + + # date validation + if ($req->{'year'} !~ /^\d\d\d\d$/ || + $req->{'year'} < 1970 || # before unix time started = bad + $req->{'year'} > 2037) # after unix time ends = worse! :) + { + return fail($err,203,"Invalid year value."); + } + if ($req->{'mon'} !~ /^\d{1,2}$/ || + $req->{'mon'} < 1 || + $req->{'mon'} > 12) + { + return fail($err,203,"Invalid month value."); + } + if ($req->{'day'} !~ /^\d{1,2}$/ || $req->{'day'} < 1 || + $req->{'day'} > LJ::days_in_month($req->{'mon'}, + $req->{'year'})) + { + return fail($err,203,"Invalid day of month value."); + } + if ($req->{'hour'} !~ /^\d{1,2}$/ || + $req->{'hour'} < 0 || $req->{'hour'} > 23) + { + return fail($err,203,"Invalid hour value."); + } + if ($req->{'min'} !~ /^\d{1,2}$/ || + $req->{'min'} < 0 || $req->{'min'} > 59) + { + return fail($err,203,"Invalid minute value."); + } + + # column width + # we only trim Unicode data + + if ($req->{'ver'} >=1 ) { + $req->{'subject'} = LJ::text_trim($req->{'subject'}, LJ::BMAX_SUBJECT, LJ::CMAX_SUBJECT); + $req->{'event'} = LJ::text_trim($req->{'event'}, LJ::BMAX_EVENT, LJ::CMAX_EVENT); + foreach (keys %{$req->{'props'}}) { + # do not trim these properties as they're magical and handled later + next if $_ eq 'taglist'; + + $req->{'props'}->{$_} = LJ::text_trim($req->{'props'}->{$_}, LJ::BMAX_PROP, LJ::CMAX_PROP); + } + } + + # setup non-user meta-data. it's important we define this here to + # 0. if it's not defined at all, then an editevent where a user + # removes random 8bit data won't remove the metadata. not that + # that matters much. but having this here won't hurt. false + # meta-data isn't saved anyway. so the only point of this next + # line is making the metadata be deleted on edit. + $req->{'props'}->{'unknown8bit'} = 0; + + # we don't want attackers sending something that looks like gzipped data + # in protocol version 0 (unknown8bit allowed), otherwise they might + # inject a 100MB string of single letters in a few bytes. + return fail($err,208,"Cannot send gzipped data") + if substr($req->{'event'},0,2) eq "\037\213"; + + # non-ASCII? + unless ( LJ::is_ascii($req->{'event'}) && + LJ::is_ascii($req->{'subject'}) && + LJ::is_ascii(join(' ', values %{$req->{'props'}}) )) + { + if ($req->{'ver'} < 1) { # client doesn't support Unicode + # only people should have unknown8bit entries. + my $uowner = $flags->{u_owner} || $flags->{u}; + return fail($err,207,'Posting in a community with international or special characters require a Unicode-capable LiveJournal client. Download one at http://www.livejournal.com/download/.') + if $uowner->{journaltype} ne 'P'; + + # so rest of site can change chars to ? marks until + # default user's encoding is set. (legacy support) + $req->{'props'}->{'unknown8bit'} = 1; + } else { + return fail($err,207, "This installation does not support Unicode clients") unless $LJ::UNICODE; + # validate that the text is valid UTF-8 + if (!LJ::text_in($req->{'subject'}) || + !LJ::text_in($req->{'event'}) || + grep { !LJ::text_in($_) } values %{$req->{'props'}}) { + return fail($err, 208, "The text entered is not a valid UTF-8 stream"); + } + } + } + + ## handle meta-data (properties) + LJ::load_props("log"); + foreach my $pname (keys %{$req->{'props'}}) + { + my $p = LJ::get_prop("log", $pname); + + # does the property even exist? + unless ($p) { + $pname =~ s/[^\w]//g; + return fail($err,205,$pname); + } + + # don't validate its type if it's 0 or undef (deleting) + next unless ($req->{'props'}->{$pname}); + + my $ptype = $p->{'datatype'}; + my $val = $req->{'props'}->{$pname}; + + if ($ptype eq "bool" && $val !~ /^[01]$/) { + return fail($err,204,"Property \"$pname\" should be 0 or 1"); + } + if ($ptype eq "num" && $val =~ /[^\d]/) { + return fail($err,204,"Property \"$pname\" should be numeric"); + } + } + + # check props for inactive userpic + if (my $pickwd = $req->{'props'}->{'picture_keyword'}) { + my $pic = LJ::get_pic_from_keyword($flags->{'u'}, $pickwd); + + # need to make sure they aren't trying to post with an inactive keyword, but also + # we don't want to allow them to post with a keyword that has no pic at all to prevent + # them from deleting the keyword, posting, then adding it back with editpics.bml + delete $req->{'props'}->{'picture_keyword'} if ! $pic || $pic->{'state'} eq 'I'; + } + + # validate incoming list of tags + return fail($err, 211) + if $req->{props}->{taglist} && + ! LJ::Tags::is_valid_tagstring($req->{props}->{taglist}); + + return 1; +} + +sub postevent +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return undef unless check_altusage($req, $err, $flags); + + my $u = $flags->{'u'}; + my $ownerid = $flags->{'ownerid'}+0; + my $uowner = $flags->{'u_owner'} || $u; + # Make sure we have a real user object here + $uowner = LJ::want_user($uowner) unless LJ::isu($uowner); + my $clusterid = $uowner->{'clusterid'}; + + my $dbh = LJ::get_db_writer(); + my $dbcm = LJ::get_cluster_master($uowner); + + return fail($err,306) unless $dbh && $dbcm && $uowner->writer; + return fail($err,200) unless $req->{'event'} =~ /\S/; + + ### make sure community, shared, or news journals don't post + ### note: shared and news journals are deprecated. every shared journal + ## should one day be a community journal, of some form. + return fail($err,150) if ($u->{'journaltype'} eq "C" || + $u->{'journaltype'} eq "S" || + $u->{'journaltype'} eq "I" || + $u->{'journaltype'} eq "N"); + + # underage users can't do this + return fail($err,310) if $u->underage; + + # suspended users can't post + return fail($err,305) if ($u->{'statusvis'} eq "S"); + + # memorials can't post + return fail($err,309) if $u->{statusvis} eq 'M'; + + # locked accounts can't post + return fail($err,308) if $u->{statusvis} eq 'L'; + + # check the journal's read-only bit + return fail($err,306) if LJ::get_cap($uowner, "readonly"); + + # is the user allowed to post? + return fail($err,404,$LJ::MSG_NO_POST) unless LJ::get_cap($u, "can_post"); + + # is the user allowed to post? + return fail($err,410) if LJ::get_cap($u, "disable_can_post"); + + # can't post to deleted/suspended community + return fail($err,307) unless $uowner->{'statusvis'} eq "V"; + + # must have a validated email address to post to a community + return fail($err, 155, "You must have an authenticated email address in order to post to another account") + unless LJ::u_equals($u, $uowner) || $u->{'status'} eq 'A'; + + # post content too large + # NOTE: requires $req->{event} be binary data, but we've already + # removed the utf-8 flag in the XML-RPC path, and it never gets + # set in the "flat" protocol path. + return fail($err,409) if length($req->{'event'}) >= LJ::BMAX_EVENT; + + my $time_was_faked = 0; + my $offset = 0; # assume gmt at first. + + if (defined $req->{'tz'}) { + if ($req->{tz} eq 'guess') { + LJ::get_timezone($uowner, \$offset, \$time_was_faked); + } elsif ($req->{'tz'} =~ /^[+\-]\d\d\d\d$/) { + # FIXME we ought to store this timezone and make use of it somehow. + $offset = $req->{'tz'} / 100.0; + } else { + return fail($err, 203, "Invalid tz"); + } + } + + if (defined $req->{'tz'} and not grep { defined $req->{$_} } qw(year mon day hour min)) { + my @ltime = gmtime(time() + ($offset*3600)); + $req->{'year'} = $ltime[5]+1900; + $req->{'mon'} = $ltime[4]+1; + $req->{'day'} = $ltime[3]; + $req->{'hour'} = $ltime[2]; + $req->{'min'} = $ltime[1]; + } + + return undef + unless common_event_validation($req, $err, $flags); + + # confirm we can add tags, at least + return fail($err, 312) + if $req->{props} && $req->{props}->{taglist} && + ! LJ::Tags::can_add_tags($uowner, $u); + + my $event = $req->{'event'}; + + ### allow for posting to journals that aren't yours (if you have permission) + my $posterid = $u->{'userid'}+0; + + # make the proper date format + my $eventtime = sprintf("%04d-%02d-%02d %02d:%02d", + $req->{'year'}, $req->{'mon'}, + $req->{'day'}, $req->{'hour'}, + $req->{'min'}); + my $qeventtime = $dbh->quote($eventtime); + + # load userprops all at once + my @poster_props = qw(newesteventtime dupsig_post); + my @owner_props = qw(newpost_minsecurity moderated); + push @owner_props, 'opt_weblogscom' unless $req->{'props'}->{'opt_backdated'}; + + LJ::load_user_props($u, @poster_props, @owner_props); + if ($uowner->{'userid'} == $u->{'userid'}) { + $uowner->{$_} = $u->{$_} foreach (@owner_props); + } else { + LJ::load_user_props($uowner, @owner_props); + } + + # are they trying to post back in time? + if ($posterid == $ownerid && !$time_was_faked && + $u->{'newesteventtime'} && $eventtime lt $u->{'newesteventtime'} && + !$req->{'props'}->{'opt_backdated'}) { + return fail($err, 153, "Your most recent journal entry is dated $u->{'newesteventtime'}, but you're trying to post one at $eventtime without the backdate option turned on. Please check your computer's clock. Or, if you really mean to post in the past, use the backdate option."); + } + + my $qallowmask = $req->{'allowmask'}+0; + my $security = "public"; + my $uselogsec = 0; + if ($req->{'security'} eq "usemask" || $req->{'security'} eq "private") { + $security = $req->{'security'}; + } + if ($req->{'security'} eq "usemask") { + $uselogsec = 1; + } + + ## if newpost_minsecurity is set, new entries have to be + ## a minimum security level + $security = "private" + if $uowner->{'newpost_minsecurity'} eq "private"; + ($security, $qallowmask) = ("usemask", 1) + if $uowner->{'newpost_minsecurity'} eq "friends" + and $security eq "public"; + + my $qsecurity = $dbh->quote($security); + + ### make sure user can't post with "custom/private security" on shared journals + return fail($err,102) + if ($ownerid != $posterid && # community post + ($req->{'security'} eq "private" || + ($req->{'security'} eq "usemask" && $qallowmask != 1 ))); + + # make sure this user isn't banned from posting here (if + # this is a community journal) + return fail($err,151) if + LJ::is_banned($posterid, $ownerid); + + # don't allow backdated posts in communities + return fail($err,152) if + ($req->{'props'}->{"opt_backdated"} && + $uowner->{'journaltype'} ne "P"); + + # do processing of embedded polls (doesn't add to database, just + # does validity checking) + my @polls = (); + if (LJ::Poll::contains_new_poll(\$event)) + { + return fail($err,301,"Your account type doesn't permit creating polls.") + unless (LJ::get_cap($u, "makepoll") + || ($uowner->{'journaltype'} eq "C" + && LJ::get_cap($uowner, "makepoll") + && LJ::can_manage_other($u, $uowner))); + + my $error = ""; + @polls = LJ::Poll::parse(\$event, \$error, { + 'journalid' => $ownerid, + 'posterid' => $posterid, + }); + return fail($err,103,$error) if $error; + } + + my $now = $dbcm->selectrow_array("SELECT UNIX_TIMESTAMP()"); + my $anum = int(rand(256)); + + # by default we record the true reverse time that the item was entered. + # however, if backdate is on, we put the reverse time at the end of time + # (which makes it equivalent to 1969, but get_recent_items will never load + # it... where clause there is: < $LJ::EndOfTime). but this way we can + # have entries that don't show up on friends view, now that we don't have + # the hints table to not insert into. + my $rlogtime = $LJ::EndOfTime; + unless ($req->{'props'}->{"opt_backdated"}) { + $rlogtime -= $now; + } + + my $dupsig = Digest::MD5::md5_hex(join('', map { $req->{$_} } + qw(subject event usejournal security allowmask))); + my $lock_key = "post-$ownerid"; + + # release our duplicate lock + my $release = sub { $dbcm->do("SELECT RELEASE_LOCK(?)", undef, $lock_key); }; + + # our own local version of fail that releases our lock first + my $fail = sub { $release->(); return fail(@_); }; + + my $res = {}; + my $res_done = 0; # set true by getlock when post was duplicate, or error getting lock + + my $getlock = sub { + my $r = $dbcm->selectrow_array("SELECT GET_LOCK(?, 2)", undef, $lock_key); + unless ($r) { + $res = undef; # a failure case has an undef result + fail($err,503); # set error flag to "can't get lock"; + $res_done = 1; # tell caller to bail out + return; + } + my @parts = split(/:/, $u->{'dupsig_post'}); + if ($parts[0] eq $dupsig) { + # duplicate! let's make the client think this was just the + # normal first response. + $res->{'itemid'} = $parts[1]; + $res->{'anum'} = $parts[2]; + $res_done = 1; + $release->(); + } + }; + + # if posting to a moderated community, store and bail out here + if ($uowner->{'journaltype'} eq 'C' && $uowner->{'moderated'} && !$flags->{'nomod'}) { + # don't moderate admins, moderators & pre-approved users + my $dbh = LJ::get_db_writer(); + my $relcount = $dbh->selectrow_array("SELECT COUNT(*) FROM reluser ". + "WHERE userid=$ownerid AND targetid=$posterid ". + "AND type IN ('A','M','N')"); + unless ($relcount) { + # moderation queue full? + my $modcount = $dbcm->selectrow_array("SELECT COUNT(*) FROM modlog WHERE journalid=$ownerid"); + return fail($err, 407) if $modcount >= LJ::get_cap($uowner, "mod_queue"); + + $modcount = $dbcm->selectrow_array("SELECT COUNT(*) FROM modlog ". + "WHERE journalid=$ownerid AND posterid=$posterid"); + return fail($err, 408) if $modcount >= LJ::get_cap($uowner, "mod_queue_per_poster"); + + $req->{'_moderate'}->{'authcode'} = LJ::make_auth_code(15); + my $fr = $dbcm->quote(Storable::freeze($req)); + return fail($err, 409) if length($fr) > 200_000; + + # store + my $modid = LJ::alloc_user_counter($uowner, "M"); + return fail($err, 501) unless $modid; + + $uowner->do("INSERT INTO modlog (journalid, modid, posterid, subject, logtime) ". + "VALUES ($ownerid, $modid, $posterid, ?, NOW())", undef, + LJ::text_trim($req->{'subject'}, 30, 0)); + return fail($err, 501) if $uowner->err; + + $uowner->do("INSERT INTO modblob (journalid, modid, request_stor) ". + "VALUES ($ownerid, $modid, $fr)"); + if ($uowner->err) { + $uowner->do("DELETE FROM modlog WHERE journalid=$ownerid AND modid=$modid"); + return fail($err, 501); + } + + # alert moderator(s) + my $mods = LJ::load_rel_user($dbh, $ownerid, 'M') || []; + if (@$mods) { + # load up all these mods and figure out if they want email or not + my $modlist = LJ::load_userids(@$mods); + my @mailtomods; + foreach my $mod (values %$modlist) { + LJ::load_user_props($mod, 'opt_nomodemail'); + push @mailtomods, $mod->{userid} + unless $mod->{opt_nomodemail}; + } + + # now get the email addresses of people who want email + if (@mailtomods) { + my $in = join(", ", map { $_+0 } @mailtomods ); + my $emails = $dbh->selectcol_arrayref("SELECT email FROM user USE INDEX (PRIMARY) ". + "WHERE userid IN ($in) AND status='A'") || []; + my $ct; + foreach my $to (@$emails) { + last if ++$ct > 20; # don't send more than 20 emails. + my $body = ("There has been a new submission into the community '$uowner->{'user'}'\n". + "which you moderate.\n\n". + " User: $u->{'user'}\n". + " Subject: $req->{'subject'}\n\n". + "To accept or reject the submission, please go to this address:\n\n" . + " $LJ::SITEROOT/community/moderate.bml?comm=$uowner->{'user'}\n\n". + "Regards,\n$LJ::SITENAME Team\n\n$LJ::SITEROOT/\n"); + LJ::send_mail({ + 'to' => $to, + 'from' => $LJ::ADMIN_EMAIL, + 'charset' => 'utf-8', + 'subject' => "Moderated submission notification", + 'body' => $body, + }); + } + } + } + + my $msg = translate($u, "modpost", undef); + return { 'message' => $msg }; + } + } # /moderated comms + + # posting: + + $getlock->(); return $res if $res_done; + + # do rate-checking + if ($u->{'journaltype'} ne "Y" && ! LJ::rate_log($u, "post", 1)) { + return $fail->($err,405); + } + + my $jitemid = LJ::alloc_user_counter($uowner, "L"); + return $fail->($err,501,"No itemid could be generated.") unless $jitemid; + + LJ::replycount_do($uowner, $jitemid, "init"); + + # remove comments and logprops on new entry ... see comment by this sub for clarification + LJ::Protocol::new_entry_cleanup_hack($u, $jitemid) if $LJ::NEW_ENTRY_CLEANUP_HACK; + my $verb = $LJ::NEW_ENTRY_CLEANUP_HACK ? 'REPLACE' : 'INSERT'; + + my $dberr; + $uowner->log2_do(\$dberr, "INSERT INTO log2 (journalid, jitemid, posterid, eventtime, logtime, security, ". + "allowmask, replycount, year, month, day, revttime, rlogtime, anum) ". + "VALUES ($ownerid, $jitemid, $posterid, $qeventtime, FROM_UNIXTIME($now), $qsecurity, $qallowmask, ". + "0, $req->{'year'}, $req->{'mon'}, $req->{'day'}, $LJ::EndOfTime-". + "UNIX_TIMESTAMP($qeventtime), $rlogtime, $anum)"); + return $fail->($err,501,$dberr) if $dberr; + + LJ::MemCache::incr([$ownerid, "log2ct:$ownerid"]); + LJ::memcache_kill($ownerid, "dayct"); + + # set userprops. + { + my %set_userprop; + + # keep track of itemid/anum for later potential duplicates + $set_userprop{"dupsig_post"} = "$dupsig:$jitemid:$anum"; + + # record the eventtime of the last update (for own journals only) + $set_userprop{"newesteventtime"} = $eventtime + if $posterid == $ownerid and not $req->{'props'}->{'opt_backdated'} and not $time_was_faked; + + LJ::set_userprop($u, \%set_userprop); + } + + # end duplicate locking section + $release->(); + + my $ditemid = $jitemid * 256 + $anum; + + ### finish embedding stuff now that we have the itemid + { + ### this should NOT return an error, and we're mildly fucked by now + ### if it does (would have to delete the log row up there), so we're + ### not going to check it for now. + + my $error = ""; + LJ::Poll::register(\$event, \$error, $ditemid, @polls); + } + #### /embedding + + ### extract links for meme tracking + unless ($req->{'security'} eq "usemask" || + $req->{'security'} eq "private") + { + foreach my $url (LJ::get_urls($event)) { + LJ::record_meme($url, $posterid, $ditemid, $ownerid); + } + } + + # record journal's disk usage + my $bytes = length($event) + length($req->{'subject'}); + $uowner->dudata_set('L', $jitemid, $bytes); + + $uowner->do("$verb INTO logtext2 (journalid, jitemid, subject, event) ". + "VALUES ($ownerid, $jitemid, ?, ?)", undef, $req->{'subject'}, + LJ::text_compress($event)); + if ($uowner->err) { + my $msg = $uowner->errstr; + LJ::delete_entry($uowner, $jitemid); # roll-back + return fail($err,501,"logtext:$msg"); + } + LJ::MemCache::set([$ownerid,"logtext:$clusterid:$ownerid:$jitemid"], + [ $req->{'subject'}, $event ]); + + # keep track of custom security stuff in other table. + if ($uselogsec) { + $uowner->do("INSERT INTO logsec2 (journalid, jitemid, allowmask) ". + "VALUES ($ownerid, $jitemid, $qallowmask)"); + if ($uowner->err) { + my $msg = $uowner->errstr; + LJ::delete_entry($uowner, $jitemid); # roll-back + return fail($err,501,"logsec2:$msg"); + } + } + + # construct valid prop list + if ($req->{props} && $req->{props}->{taglist}) { + my $tags = []; + LJ::Tags::is_valid_tagstring($req->{props}->{taglist}, $tags); + $req->{props}->{taglist} = join(', ', @$tags); + + # handle tags if they're defined + LJ::Tags::update_logtags($uowner, $jitemid, { + set_string => $req->{props}->{taglist}, + remote => $u, + }); + } + + # meta-data + if (%{$req->{'props'}}) { + my $propset = {}; + foreach my $pname (keys %{$req->{'props'}}) { + next unless $req->{'props'}->{$pname}; + next if $pname eq "revnum" || $pname eq "revtime"; + my $p = LJ::get_prop("log", $pname); + next unless $p; + next unless $req->{'props'}->{$pname}; + $propset->{$pname} = $req->{'props'}->{$pname}; + } + my %logprops; + LJ::set_logprop($uowner, $jitemid, $propset, \%logprops) if %$propset; + + # if set_logprop modified props above, we can set the memcache key + # to be the hashref of modified props, since this is a new post + LJ::MemCache::set([$uowner->{'userid'}, "logprop:$uowner->{'userid'}:$jitemid"], + \%logprops) if %logprops; + } + + $dbh->do("UPDATE userusage SET timeupdate=NOW(), lastitemid=$jitemid ". + "WHERE userid=$ownerid"); + LJ::MemCache::set([$ownerid, "tu:$ownerid"], pack("N", time()), 30*60); + + # note this post in recentactions table + LJ::note_recent_action($uowner, 'post'); + + # update user update table (on which friends views rely) + # NOTE: as of Mar-25-2003, we don't actually use this yet. we might + # use it in the future though, for faster ?skip=0 friends views. + # for now, we'll keep it disabled to lessen writes + if (0) { + my @bits; + if ($security eq "public") { + push @bits, 31; # 31 means public + } elsif ($security eq "private") { + push @bits, 32; # 1<<32 doesn't exist (too big), but we'll use it in this table + } else { + for (my $i=0; $i<=30; $i++) { + next unless $qallowmask & (1<<$i); + push @bits, $i; + } + } + if (@bits) { + $dbh->do("REPLACE INTO userupdate (userid, groupbit, timeupdate) VALUES ". + join(",", map { "($ownerid, $_, NOW())" } @bits)); + } + } + + # notify weblogs.com of post if necessary + if ($u->{'opt_weblogscom'} && LJ::get_cap($u, "weblogscom") && + $security eq "public" && ! $req->{'props'}->{'opt_backdated'}) + { + LJ::cmd_buffer_add($uowner->{clusterid}, $u->{'userid'}, 'weblogscom', { + 'user' => $u->{'user'}, + 'title' => $u->{'journaltitle'} || $u->{'name'}, + 'url' => LJ::journal_base($u) . "/", + }); + } + + # run local site-specific actions + LJ::run_hooks("postpost", { + 'itemid' => $jitemid, + 'anum' => $anum, + 'journal' => $uowner, + 'poster' => $u, + 'event' => $event, + 'subject' => $req->{'subject'}, + 'security' => $security, + 'allowmask' => $qallowmask, + 'props' => $req->{'props'}, + }); + + # cluster tracking + LJ::mark_user_active($u, 'post'); + LJ::mark_user_active($uowner, 'post') unless LJ::u_equals($u, $uowner); + + $res->{'itemid'} = $jitemid; # by request of mart + $res->{'anum'} = $anum; + $res->{'url'} = LJ::item_link($uowner, $jitemid, $anum); + return $res; +} + +sub editevent +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + + # we check later that user owns entry they're modifying, so all + # we care about for check_altusage is that the target journal + # exists, and we want it to setup some data in $flags. + $flags->{'ignorecanuse'} = 1; + return undef unless check_altusage($req, $err, $flags); + + my $u = $flags->{'u'}; + my $ownerid = $flags->{'ownerid'}; + my $uowner = $flags->{'u_owner'} || $u; + # Make sure we have a user object here + $uowner = LJ::want_user($uowner) unless LJ::isu($uowner); + my $clusterid = $uowner->{'clusterid'}; + my $posterid = $u->{'userid'}; + my $qallowmask = $req->{'allowmask'}+0; + my $sth; + + my $itemid = $req->{'itemid'}+0; + + # underage users can't do this + return fail($err,310) if $u->underage; + + # check the journal's read-only bit + return fail($err,306) if LJ::get_cap($uowner, "readonly"); + + # can't edit in deleted/suspended community + return fail($err,307) unless $uowner->{'statusvis'} eq "V"; + + my $dbcm = LJ::get_cluster_master($uowner); + return fail($err,306) unless $dbcm; + + ### make sure user can't change a post to "custom/private security" on shared journals + return fail($err,102) + if ($ownerid != $posterid && # community post + ($req->{'security'} eq "private" || + ($req->{'security'} eq "usemask" && $qallowmask != 1 ))); + + # fetch the old entry from master database so we know what we + # really have to update later. usually people just edit one part, + # not every field in every table. reads are quicker than writes, + # so this is worth it. + my $oldevent = $dbcm->selectrow_hashref + ("SELECT journalid AS 'ownerid', posterid, eventtime, logtime, ". + "compressed, security, allowmask, year, month, day, ". + "rlogtime, anum FROM log2 WHERE journalid=$ownerid AND jitemid=$itemid"); + + ($oldevent->{event}, $oldevent->{subject}) = $dbcm->selectrow_array + ("SELECT subject, event FROM logtext2 ". + "WHERE journalid=$ownerid AND jitemid=$itemid"); + + LJ::text_uncompress(\$oldevent->{'event'}); + + # kill seconds in eventtime, since we don't use it, then we can use 'eq' and such + $oldevent->{'eventtime'} =~ s/:00$//; + + ### make sure this user is allowed to edit this entry + return fail($err,302) + unless ($ownerid == $oldevent->{'ownerid'}); + + ### what can they do to somebody elses entry? (in shared journal) + if ($posterid != $oldevent->{'posterid'}) + { + ## deleting. + return fail($err,304) + if ($req->{'event'} !~ /\S/ && ! + ($ownerid == $u->{'userid'} || + # community account can delete it (ick) + + LJ::can_manage_other($posterid, $ownerid) + # if user is a community maintainer they can delete + # it too (good) + )); + + ## editing: + return fail($err,303) + if ($req->{'event'} =~ /\S/); + } + + # simple logic for deleting an entry + if ($req->{'event'} !~ /\S/) + { + # if their newesteventtime prop equals the time of the one they're deleting + # then delete their newesteventtime. + if ($u->{'userid'} == $uowner->{'userid'}) { + LJ::load_user_props($u, { use_master => 1 }, "newesteventtime"); + if ($u->{'newesteventtime'} eq $oldevent->{'eventtime'}) { + LJ::set_userprop($u, "newesteventtime", undef); + } + } + + # log this event, unless noauth is on, which means it is being done internally and we should + # rely on them to log why they're deleting the entry if they need to. that way we don't have + # double entries, and we have as much information available as possible at the location the + # delete is initiated. + $uowner->log_event('delete_entry', { + remote => $u, + actiontarget => ($req->{itemid} * 256 + $oldevent->{anum}), + method => 'protocol', + }) + unless $flags->{noauth}; + + LJ::delete_entry($uowner, $req->{'itemid'}, 'quick', $oldevent->{'anum'}); + + # clear their duplicate protection, so they can later repost + # what they just deleted. (or something... probably rare.) + LJ::set_userprop($u, "dupsig_post", undef); + + my $res = { 'itemid' => $itemid, + 'anum' => $oldevent->{'anum'} }; + return $res; + } + + # now make sure the new entry text isn't $CannotBeShown + return fail($err, 210) + if $req->{event} eq $CannotBeShown; + + # don't allow backdated posts in communities + return fail($err,152) if + ($req->{'props'}->{"opt_backdated"} && + $uowner->{'journaltype'} ne "P"); + + # make year/mon/day/hour/min optional in an edit event, + # and just inherit their old values + { + $oldevent->{'eventtime'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/; + $req->{'year'} = $1 unless defined $req->{'year'}; + $req->{'mon'} = $2+0 unless defined $req->{'mon'}; + $req->{'day'} = $3+0 unless defined $req->{'day'}; + $req->{'hour'} = $4+0 unless defined $req->{'hour'}; + $req->{'min'} = $5+0 unless defined $req->{'min'}; + } + + # updating an entry: + return undef + unless common_event_validation($req, $err, $flags); + + ### load existing meta-data + my %curprops; + + LJ::load_log_props2($dbcm, $ownerid, [ $itemid ], \%curprops); + + ## handle meta-data (properties) + my %props_byname = (); + foreach my $key (keys %{$req->{'props'}}) { + ## changing to something else? + if ($curprops{$itemid}->{$key} ne $req->{'props'}->{$key}) { + $props_byname{$key} = $req->{'props'}->{$key}; + } + } + + my $event = $req->{'event'}; + my $bytes = length($event) + length($req->{'subject'}); + + my $eventtime = sprintf("%04d-%02d-%02d %02d:%02d", + map { $req->{$_} } qw(year mon day hour min)); + my $qeventtime = $dbcm->quote($eventtime); + + # preserve old security by default, use user supplied if it's understood + my $security = $oldevent->{security}; + $security = $req->{security} + if $req->{security} && + $req->{security} =~ /^(?:public|private|usemask)$/; + + my $do_tags = $req->{props} && $req->{props}->{taglist}; + if ($oldevent->{security} ne $security || $qallowmask != $oldevent->{allowmask}) { + # FIXME: this is a hopefully temporary hack which deletes tags from the entry + # when the security has changed. the real fix is to make update_logtags aware + # of security changes so it can update logkwsum appropriately. + + unless ($do_tags) { + # we need to fix security on this entry's tags, but the user didn't give us a tag list + # to work with, so we have to go get the tags on the entry, and construct a tag list, + # in order to pass to update_logtags down at the bottom of this whole update + my $tags = LJ::Tags::get_logtags($uowner, $itemid); + $tags = $tags->{"$uowner->{userid} $itemid"}; + $req->{props}->{taglist} = join(',', sort map { $_->{name} } values %{$tags || {}}); + $do_tags = 1; # bleh, force the update later + } + + LJ::Tags::delete_logtags($uowner, $itemid); + } + + my $qyear = $req->{'year'}+0; + my $qmonth = $req->{'mon'}+0; + my $qday = $req->{'day'}+0; + + if ($eventtime ne $oldevent->{'eventtime'} || + $security ne $oldevent->{'security'} || + (!$curprops{opt_backdated} && $req->{props}{opt_backdated}) || + $qallowmask != $oldevent->{'allowmask'}) + { + # are they changing their most recent post? + LJ::load_user_props($u, "newesteventtime"); + if ($u->{userid} == $uowner->{userid} && + $u->{newesteventtime} eq $oldevent->{eventtime}) { + # did they change the time? + if ($eventtime ne $oldevent->{eventtime}) { + # the newesteventtime is this event's new time. + LJ::set_userprop($u, "newesteventtime", $eventtime); + } elsif (!$curprops{opt_backdated} && $req->{props}{opt_backdated}) { + # otherwise, if they set the backdated flag, + # then we no longer know the newesteventtime. + LJ::set_userprop($u, "newesteventtime", undef); + } + } + + my $qsecurity = $uowner->quote($security); + my $dberr; + $uowner->log2_do(\$dberr, "UPDATE log2 SET eventtime=$qeventtime, revttime=$LJ::EndOfTime-". + "UNIX_TIMESTAMP($qeventtime), year=$qyear, month=$qmonth, day=$qday, ". + "security=$qsecurity, allowmask=$qallowmask WHERE journalid=$ownerid ". + "AND jitemid=$itemid"); + return fail($err,501,$dberr) if $dberr; + + # update memcached + my $sec = $qallowmask; + $sec = 0 if $security eq 'private'; + $sec = 2**31 if $security eq 'public'; + + my $row = pack("NNNNN", $oldevent->{'posterid'}, + LJ::mysqldate_to_time($eventtime, 1), + LJ::mysqldate_to_time($oldevent->{'logtime'}, 1), + $sec, + $itemid*256 + $oldevent->{'anum'}); + + LJ::MemCache::set([$ownerid, "log2:$ownerid:$itemid"], $row); + + } + + if ($security ne $oldevent->{'security'} || + $qallowmask != $oldevent->{'allowmask'}) + { + if ($security eq "public" || $security eq "private") { + $uowner->do("DELETE FROM logsec2 WHERE journalid=$ownerid AND jitemid=$itemid"); + } else { + $uowner->do("REPLACE INTO logsec2 (journalid, jitemid, allowmask) ". + "VALUES ($ownerid, $itemid, $qallowmask)"); + } + return fail($err,501,$dbcm->errstr) if $uowner->err; + } + + LJ::MemCache::set([$ownerid,"logtext:$clusterid:$ownerid:$itemid"], + [ $req->{'subject'}, $event ]); + + if ($event ne $oldevent->{'event'} || + $req->{'subject'} ne $oldevent->{'subject'}) + { + $uowner->do("UPDATE logtext2 SET subject=?, event=? ". + "WHERE journalid=$ownerid AND jitemid=$itemid", undef, + $req->{'subject'}, LJ::text_compress($event)); + return fail($err,501,$uowner->errstr) if $uowner->err; + + # update disk usage + $uowner->dudata_set('L', $itemid, $bytes); + } + + # up the revision number + $req->{'props'}->{'revnum'} = ($curprops{$itemid}->{'revnum'} || 0) + 1; + $req->{'props'}->{'revtime'} = time(); + + # handle tags if they're defined + LJ::Tags::update_logtags($uowner, $itemid, { + set_string => $req->{props}->{taglist}, + remote => $u, + }) + if $do_tags; + + # handle the props + { + my $propset = {}; + foreach my $pname (keys %{$req->{'props'}}) { + my $p = LJ::get_prop("log", $pname); + next unless $p; + $propset->{$pname} = $req->{'props'}->{$pname}; + } + LJ::set_logprop($uowner, $itemid, $propset); + } + + # deal with backdated changes. if the entry's rlogtime is + # $EndOfTime, then it's backdated. if they want that off, need to + # reset rlogtime to real reverse log time. also need to set + # rlogtime to $EndOfTime if they're turning backdate on. + if ($req->{'props'}->{'opt_backdated'} eq "1" && + $oldevent->{'rlogtime'} != $LJ::EndOfTime) { + my $dberr; + $uowner->log2_do(undef, "UPDATE log2 SET rlogtime=$LJ::EndOfTime WHERE ". + "journalid=$ownerid AND jitemid=$itemid"); + return fail($err,501,$dberr) if $dberr; + } + if ($req->{'props'}->{'opt_backdated'} eq "0" && + $oldevent->{'rlogtime'} == $LJ::EndOfTime) { + my $dberr; + $uowner->log2_do(\$dberr, "UPDATE log2 SET rlogtime=$LJ::EndOfTime-UNIX_TIMESTAMP(logtime) ". + "WHERE journalid=$ownerid AND jitemid=$itemid"); + return fail($err,501,$dberr) if $dberr; + } + return fail($err,501,$dbcm->errstr) if $dbcm->err; + + LJ::memcache_kill($ownerid, "dayct"); + + my $res = { 'itemid' => $itemid }; + if (defined $oldevent->{'anum'}) { + $res->{'anum'} = $oldevent->{'anum'}; + $res->{'url'} = LJ::item_link($uowner, $itemid, $oldevent->{'anum'}); + } + return $res; +} + +sub getevents +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return undef unless check_altusage($req, $err, $flags); + + my $u = $flags->{'u'}; + my $uowner = $flags->{'u_owner'} || $u; + + ### shared-journal support + my $posterid = $u->{'userid'}; + my $ownerid = $flags->{'ownerid'}; + + my $dbr = LJ::get_db_reader(); + my $sth; + + my $dbcr = LJ::get_cluster_reader($uowner); + return fail($err,502) unless $dbcr && $dbr; + + # can't pull events from deleted/suspended journal + return fail($err,307) unless $uowner->{'statusvis'} eq "V"; + + my $reject_code = $LJ::DISABLE_PROTOCOL{getevents}; + if (ref $reject_code eq "CODE") { + my $r = eval { Apache->request }; + my $errmsg = $reject_code->($req, $flags, $r); + if ($errmsg) { return fail($err, "311", $errmsg); } + } + + # if this is on, we sort things different (logtime vs. posttime) + # to avoid timezone issues + my $is_community = ($uowner->{'journaltype'} eq "C" || + $uowner->{'journaltype'} eq "S"); + + # in some cases we'll use the master, to ensure there's no + # replication delay. useful cases: getting one item, use master + # since user might have just made a typo and realizes it as they + # post, or wants to append something they forgot, etc, etc. in + # other cases, slave is pretty sure to have it. + my $use_master = 0; + + # the benefit of this mode over actually doing 'lastn/1' is + # the $use_master usage. + if ($req->{'selecttype'} eq "one" && $req->{'itemid'} eq "-1") { + $req->{'selecttype'} = "lastn"; + $req->{'howmany'} = 1; + undef $req->{'itemid'}; + $use_master = 1; # see note above. + } + + # build the query to get log rows. each selecttype branch is + # responsible for either populating the following 3 variables + # OR just populating $sql + my ($orderby, $where, $limit); + my $sql; + if ($req->{'selecttype'} eq "day") + { + return fail($err,203) + unless ($req->{'year'} =~ /^\d\d\d\d$/ && + $req->{'month'} =~ /^\d\d?$/ && + $req->{'day'} =~ /^\d\d?$/ && + $req->{'month'} >= 1 && $req->{'month'} <= 12 && + $req->{'day'} >= 1 && $req->{'day'} <= 31); + + my $qyear = $dbr->quote($req->{'year'}); + my $qmonth = $dbr->quote($req->{'month'}); + my $qday = $dbr->quote($req->{'day'}); + $where = "AND year=$qyear AND month=$qmonth AND day=$qday"; + $limit = "LIMIT 200"; # FIXME: unhardcode this constant (also in ljviews.pl) + + # see note above about why the sort order is different + $orderby = $is_community ? "ORDER BY logtime" : "ORDER BY eventtime"; + } + elsif ($req->{'selecttype'} eq "lastn") + { + my $howmany = $req->{'howmany'} || 20; + if ($howmany > 50) { $howmany = 50; } + $howmany = $howmany + 0; + $limit = "LIMIT $howmany"; + + # okay, follow me here... see how we add the revttime predicate + # even if no beforedate key is present? you're probably saying, + # that's retarded -- you're saying: "revttime > 0", that's like + # saying, "if entry occurred at all." yes yes, but that hints + # mysql's braindead optimizer to use the right index. + my $rtime_after = 0; + my $rtime_what = $is_community ? "rlogtime" : "revttime"; + if ($req->{'beforedate'}) { + return fail($err,203,"Invalid beforedate format.") + unless ($req->{'beforedate'} =~ + /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/); + my $qd = $dbr->quote($req->{'beforedate'}); + $rtime_after = "$LJ::EndOfTime-UNIX_TIMESTAMP($qd)"; + } + $where .= "AND $rtime_what > $rtime_after "; + $orderby = "ORDER BY $rtime_what"; + } + elsif ($req->{'selecttype'} eq "one") + { + my $id = $req->{'itemid'} + 0; + $where = "AND jitemid=$id"; + } + elsif ($req->{'selecttype'} eq "syncitems") + { + return fail($err,506) if $LJ::DISABLED{'syncitems'}; + my $date = $req->{'lastsync'} || "0000-00-00 00:00:00"; + return fail($err,203,"Invalid syncitems date format") + unless ($date =~ /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/); + + my $now = time(); + # broken client loop prevention + if ($req->{'lastsync'}) { + my $pname = "rl_syncitems_getevents_loop"; + LJ::load_user_props($u, $pname); + # format is: time/date/time/date/time/date/... so split + # it into a hash, then delete pairs that are older than an hour + my %reqs = split(m!/!, $u->{$pname}); + foreach (grep { $_ < $now - 60*60 } keys %reqs) { delete $reqs{$_}; } + my $count = grep { $_ eq $date } values %reqs; + $reqs{$now} = $date; + if ($count >= 2) { + # 2 prior, plus this one = 3 repeated requests for same synctime. + # their client is busted. (doesn't understand syncitems semantics) + return fail($err,406); + } + LJ::set_userprop($u, $pname, + join('/', map { $_, $reqs{$_} } + sort { $b <=> $a } keys %reqs)); + } + + my %item; + $sth = $dbcr->prepare("SELECT jitemid, logtime FROM log2 WHERE ". + "journalid=? and logtime > ?"); + $sth->execute($ownerid, $date); + while (my ($id, $dt) = $sth->fetchrow_array) { + $item{$id} = $dt; + } + + my $p_revtime = LJ::get_prop("log", "revtime"); + $sth = $dbcr->prepare("SELECT jitemid, FROM_UNIXTIME(value) ". + "FROM logprop2 WHERE journalid=? ". + "AND propid=$p_revtime->{'id'} ". + "AND value+0 > UNIX_TIMESTAMP(?)"); + $sth->execute($ownerid, $date); + while (my ($id, $dt) = $sth->fetchrow_array) { + $item{$id} = $dt; + } + + my $limit = 100; + my @ids = sort { $item{$a} cmp $item{$b} } keys %item; + if (@ids > $limit) { @ids = @ids[0..$limit-1]; } + + my $in = join(',', @ids) || "0"; + $where = "AND jitemid IN ($in)"; + } + elsif ($req->{'selecttype'} eq "multiple") + { + my @ids; + foreach my $num (split(/\s*,\s*/, $req->{'itemids'})) { + return fail($err,203,"Non-numeric itemid") unless $num =~ /^\d+$/; + push @ids, $num; + } + my $limit = 100; + return fail($err,209,"Can't retrieve more than $limit entries at once") if @ids > $limit; + my $in = join(',', @ids); + $where = "AND jitemid IN ($in)"; + } + else + { + return fail($err,200,"Invalid selecttype."); + } + + # common SQL template: + unless ($sql) { + $sql = "SELECT jitemid, eventtime, security, allowmask, anum, posterid ". + "FROM log2 WHERE journalid=$ownerid $where $orderby $limit"; + } + + # whatever selecttype might have wanted us to use the master db. + $dbcr = LJ::get_cluster_def_reader($uowner) if $use_master; + + return fail($err,502) unless $dbcr; + + ## load the log rows + ($sth = $dbcr->prepare($sql))->execute; + return fail($err,501,$dbcr->errstr) if $dbcr->err; + + my $count = 0; + my @itemids = (); + my $res = {}; + my $events = $res->{'events'} = []; + my %evt_from_itemid; + + while (my ($itemid, $eventtime, $sec, $mask, $anum, $jposterid) = $sth->fetchrow_array) + { + $count++; + my $evt = {}; + $evt->{'itemid'} = $itemid; + push @itemids, $itemid; + + $evt_from_itemid{$itemid} = $evt; + + $evt->{"eventtime"} = $eventtime; + if ($sec ne "public") { + $evt->{'security'} = $sec; + $evt->{'allowmask'} = $mask if $sec eq "usemask"; + } + $evt->{'anum'} = $anum; + $evt->{'poster'} = LJ::get_username($dbr, $jposterid) if $jposterid != $ownerid; + $evt->{'url'} = LJ::item_link($uowner, $itemid, $anum); + push @$events, $evt; + } + + # load properties. Even if the caller doesn't want them, we need + # them in Unicode installations to recognize older 8bit non-UF-8 + # entries. + unless ($req->{'noprops'} && !$LJ::UNICODE) + { + ### do the properties now + $count = 0; + my %props = (); + LJ::load_log_props2($dbcr, $ownerid, \@itemids, \%props); + + # load the tags for these entries, unless told not to + unless ($req->{notags}) { + # construct %idsbycluster for the multi call to get these tags + my $tags = LJ::Tags::get_logtags($uowner, \@itemids); + + # add to props + foreach my $itemid (@itemids) { + next unless $tags->{$itemid}; + $props{$itemid}->{taglist} = join(', ', values %{$tags->{$itemid}}); + } + } + + foreach my $itemid (keys %props) { + # 'replycount' is a pseudo-prop, don't send it. + # FIXME: this goes away after we restructure APIs and + # replycounts cease being transferred in props + delete $props{$itemid}->{'replycount'}; + + my $evt = $evt_from_itemid{$itemid}; + $evt->{'props'} = {}; + foreach my $name (keys %{$props{$itemid}}) { + my $value = $props{$itemid}->{$name}; + $value =~ s/\n/ /g; + $evt->{'props'}->{$name} = $value; + } + } + } + + ## load the text + my $gt_opts = { + 'usemaster' => $use_master, + }; + my $text = LJ::get_logtext2($uowner, $gt_opts, @itemids); + + foreach my $i (@itemids) + { + my $t = $text->{$i}; + my $evt = $evt_from_itemid{$i}; + + # if they want subjects to be events, replace event + # with subject when requested. + if ($req->{'prefersubject'} && length($t->[0])) { + $t->[1] = $t->[0]; # event = subject + $t->[0] = undef; # subject = undef + } + + # now that we have the subject, the event and the props, + # auto-translate them to UTF-8 if they're not in UTF-8. + if ($LJ::UNICODE && $req->{'ver'} >= 1 && + $evt->{'props'}->{'unknown8bit'}) { + my $error = 0; + $t->[0] = LJ::text_convert($t->[0], $uowner, \$error); + $t->[1] = LJ::text_convert($t->[1], $uowner, \$error); + foreach (keys %{$evt->{'props'}}) { + $evt->{'props'}->{$_} = LJ::text_convert($evt->{'props'}->{$_}, $uowner, \$error); + } + return fail($err,208,"Cannot display this post. Please see $LJ::SITEROOT/support/encodings.bml for more information.") + if $error; + } + + if ($LJ::UNICODE && $req->{'ver'} < 1 && !$evt->{'props'}->{'unknown8bit'}) { + unless ( LJ::is_ascii($t->[0]) && + LJ::is_ascii($t->[1]) && + LJ::is_ascii(join(' ', values %{$evt->{'props'}}) )) { + # we want to fail the client that wants to get this entry + # but we make an exception for selecttype=day, in order to allow at least + # viewing the daily summary + + if ($req->{'selecttype'} eq 'day') { + $t->[0] = $t->[1] = $CannotBeShown; + } else { + return fail($err,207,"Cannot display/edit a Unicode post with a non-Unicode client. Please see $LJ::SITEROOT/support/encodings.bml for more information."); + } + } + } + + if ($t->[0]) { + $t->[0] =~ s/[\r\n]/ /g; + $evt->{'subject'} = $t->[0]; + } + + # truncate + if ($req->{'truncate'} >= 4) { + my $original = $t->[1]; + if ($req->{'ver'} > 1) { + $t->[1] = LJ::text_trim($t->[1], $req->{'truncate'} - 3, 0); + } else { + $t->[1] = LJ::text_trim($t->[1], 0, $req->{'truncate'} - 3); + } + # only append the elipsis if the text was actually truncated + $t->[1] .= "..." if $t->[1] ne $original; + } + + # line endings + $t->[1] =~ s/\r//g; + if ($req->{'lineendings'} eq "unix") { + # do nothing. native format. + } elsif ($req->{'lineendings'} eq "mac") { + $t->[1] =~ s/\n/\r/g; + } elsif ($req->{'lineendings'} eq "space") { + $t->[1] =~ s/\n/ /g; + } elsif ($req->{'lineendings'} eq "dots") { + $t->[1] =~ s/\n/ ... /g; + } else { # "pc" -- default + $t->[1] =~ s/\n/\r\n/g; + } + $evt->{'event'} = $t->[1]; + } + + # maybe we don't need the props after all + if ($req->{'noprops'}) { + foreach(@$events) { delete $_->{'props'}; } + } + + return $res; +} + +sub editfriends +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + + my $u = $flags->{'u'}; + my $userid = $u->{'userid'}; + my $dbh = LJ::get_db_writer(); + my $sth; + + return fail($err,306) unless $dbh; + + # do not let locked people do this + return fail($err, 308) if $u->{statusvis} eq 'L'; + + my $res = {}; + + ## first, figure out who the current friends are to save us work later + my %curfriend; + my $friend_count = 0; + # TAG:FR:protocol:editfriends1 + $sth = $dbh->prepare("SELECT u.user FROM useridmap u, friends f ". + "WHERE u.userid=f.friendid AND f.userid=$userid"); + $sth->execute; + while (my ($friend) = $sth->fetchrow_array) { + $curfriend{$friend} = 1; + $friend_count++; + } + $sth->finish; + + # perform the deletions + DELETEFRIEND: + foreach (@{$req->{'delete'}}) + { + my $deluser = LJ::canonical_username($_); + next DELETEFRIEND unless ($curfriend{$deluser}); + + my $friendid = LJ::get_userid($deluser); + # TAG:FR:protocol:editfriends2_del + LJ::remove_friend($userid, $friendid); + $friend_count--; + } + + my $error_flag = 0; + my $friends_added = 0; + my $fail = sub { + LJ::memcache_kill($userid, "friends"); + LJ::mark_dirty($userid, "friends"); + return fail($err, $_[0], $_[1]); + }; + + # only people, shared journals, and owned syn feeds can add friends + return $fail->(104, "Journal type cannot add friends") + unless ($u->{'journaltype'} eq 'P' || + $u->{'journaltype'} eq 'S' || + $u->{'journaltype'} eq 'I' || + ($u->{'journaltype'} eq "Y" && $u->{'password'})); + + # perform the adds + ADDFRIEND: + foreach my $fa (@{$req->{'add'}}) + { + unless (ref $fa eq "HASH") { + $fa = { 'username' => $fa }; + } + + my $aname = LJ::canonical_username($fa->{'username'}); + unless ($aname) { + $error_flag = 1; + next ADDFRIEND; + } + + $friend_count++ unless $curfriend{$aname}; + + my $maxfriends = LJ::get_cap($u, "maxfriends"); + return $fail->(104, "Exceeded $maxfriends friends limit (now: $friend_count)") + if ($friend_count > $maxfriends); + + my $fg = $fa->{'fgcolor'} || "#000000"; + my $bg = $fa->{'bgcolor'} || "#FFFFFF"; + if ($fg !~ /^\#[0-9A-F]{6,6}$/i || $bg !~ /^\#[0-9A-F]{6,6}$/i) { + return $fail->(203, "Invalid color values"); + } + + my $row = LJ::load_user($aname); + + # XXX - on some errors we fail out, on others we continue and try adding + # any other users in the request. also, error message for redirect should + # point the user to the redirected username. + if (! $row) { + $error_flag = 1; + } elsif ($row->{'journaltype'} eq "R") { + return $fail->(154); + } elsif ($row->{'statusvis'} ne "V") { + $error_flag = 1; + } else { + $friends_added++; + my $added = { 'username' => $aname, + 'fullname' => $row->{'name'}, + }; + if ($req->{'ver'} >= 1) { + LJ::text_out(\$added->{'fullname'}); + } + push @{$res->{'added'}}, $added; + + my $qfg = LJ::color_todb($fg); + my $qbg = LJ::color_todb($bg); + + my $friendid = $row->{'userid'}; + + my $gmask = $fa->{'groupmask'}; + if (! $gmask && $curfriend{$aname}) { + # if no group mask sent, use the existing one if this is an existing friend + # TAG:FR:protocol:editfriends3_getmask + my $sth = $dbh->prepare("SELECT groupmask FROM friends ". + "WHERE userid=$userid AND friendid=$friendid"); + $sth->execute; + $gmask = $sth->fetchrow_array; + } + # force bit 0 on. + $gmask |= 1; + + # TAG:FR:protocol:editfriends4_addeditfriend + $sth = $dbh->prepare("REPLACE INTO friends (userid, friendid, fgcolor, bgcolor, groupmask) ". + "VALUES ($userid, $friendid, $qfg, $qbg, $gmask)"); + $sth->execute; + + unless ($dbh->err) { + my $memkey = [$userid,"frgmask:$userid:$friendid"]; + LJ::MemCache::set($memkey, $gmask+0, time()+60*15); + LJ::memcache_kill($friendid, 'friendofs'); + } + return $fail->(501,$dbh->errstr) if $dbh->err; + } + } + + return $fail->(104) if $error_flag; + + # invalidate memcache of friends + LJ::memcache_kill($userid, "friends"); + LJ::mark_dirty($userid, "friends"); + + return $res; +} + +sub editfriendgroups +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + + my $u = $flags->{'u'}; + my $userid = $u->{'userid'}; + my ($db, $fgtable, $bmax, $cmax) = $u->{dversion} > 5 ? + ($u->writer, 'friendgroup2', LJ::BMAX_GRPNAME2, LJ::CMAX_GRPNAME2) : + (LJ::get_db_writer(), 'friendgroup', LJ::BMAX_GRPNAME, LJ::CMAX_GRPNAME); + my $sth; + + return fail($err,306) unless $db; + + # do not let locked people do this + return fail($err, 308) if $u->{statusvis} eq 'L'; + + my $res = {}; + + ## make sure tree is how we want it + $req->{'groupmasks'} = {} unless + (ref $req->{'groupmasks'} eq "HASH"); + $req->{'set'} = {} unless + (ref $req->{'set'} eq "HASH"); + $req->{'delete'} = [] unless + (ref $req->{'delete'} eq "ARRAY"); + + # Keep track of what bits are already set, so we can know later + # whether to INSERT or UPDATE. + my %bitset; + my $groups = LJ::get_friend_group($userid); + foreach my $bit (keys %{$groups || {}}) { + $bitset{$bit} = 1; + } + + ## before we perform any DB operations, validate input text + # (groups' names) for correctness so we can fail gracefully + if ($LJ::UNICODE) { + foreach my $bit (keys %{$req->{'set'}}) + { + my $name = $req->{'set'}->{$bit}->{'name'}; + return fail($err,207,"non-ASCII names require a Unicode-capable client") + if $req->{'ver'} < 1 and not LJ::is_ascii($name); + return fail($err,208,"Invalid group names. Please see $LJ::SITEROOT/support/encodings.bml for more information.") + unless LJ::text_in($name); + } + } + + ## figure out deletions we'll do later + foreach my $bit (@{$req->{'delete'}}) + { + $bit += 0; + next unless ($bit >= 1 && $bit <= 30); + $bitset{$bit} = 0; # so later we replace into, not update. + } + + ## do additions/modifications ('set' hash) + my %added; + foreach my $bit (keys %{$req->{'set'}}) + { + $bit += 0; + next unless ($bit >= 1 && $bit <= 30); + my $sa = $req->{'set'}->{$bit}; + my $name = LJ::text_trim($sa->{'name'}, $bmax, $cmax); + + # can't end with a slash + $name =~ s!/$!!; + + # setting it to name is like deleting it. + unless ($name =~ /\S/) { + push @{$req->{'delete'}}, $bit; + next; + } + + my $qname = $db->quote($name); + my $qsort = defined $sa->{'sort'} ? ($sa->{'sort'}+0) : 50; + my $qpublic = $db->quote(defined $sa->{'public'} ? ($sa->{'public'}+0) : 0); + + if ($bitset{$bit}) { + # so update it + my $sets; + if (defined $sa->{'public'}) { + $sets .= ", is_public=$qpublic"; + } + $db->do("UPDATE $fgtable SET groupname=$qname, sortorder=$qsort ". + "$sets WHERE userid=$userid AND groupnum=$bit"); + } else { + $db->do("REPLACE INTO $fgtable (userid, groupnum, ". + "groupname, sortorder, is_public) VALUES ". + "($userid, $bit, $qname, $qsort, $qpublic)"); + } + $added{$bit} = 1; + } + + + ## do deletions ('delete' array) + my $dbcm = LJ::get_cluster_master($u); + + # ignore bits that aren't integers or that are outside 1-30 range + my @delete_bits = grep {$_ >= 1 and $_ <= 30} map {$_+0} @{$req->{'delete'}}; + my $delete_mask = 0; + foreach my $bit (@delete_bits) { + $delete_mask |= (1 << $bit) + } + + # remove the bits for deleted groups from all friends groupmasks + my $dbh = LJ::get_db_writer(); + if ($delete_mask) { + # TAG:FR:protocol:editfriendgroups_removemasks + $dbh->do("UPDATE friends". + " SET groupmask = groupmask & ~$delete_mask". + " WHERE userid = $userid"); + } + + foreach my $bit (@delete_bits) + { + # remove all posts from allowing that group: + my @posts_to_clean = (); + $sth = $dbcm->prepare("SELECT jitemid FROM logsec2 WHERE journalid=$userid AND allowmask & (1 << $bit)"); + $sth->execute; + while (my ($id) = $sth->fetchrow_array) { push @posts_to_clean, $id; } + while (@posts_to_clean) { + my @batch; + if (scalar(@posts_to_clean) < 20) { + @batch = @posts_to_clean; + @posts_to_clean = (); + } else { + @batch = splice(@posts_to_clean, 0, 20); + } + + my $in = join(",", @batch); + $u->do("UPDATE log2 SET allowmask=allowmask & ~(1 << $bit) ". + "WHERE journalid=$userid AND jitemid IN ($in) AND security='usemask'"); + $u->do("UPDATE logsec2 SET allowmask=allowmask & ~(1 << $bit) ". + "WHERE journalid=$userid AND jitemid IN ($in)"); + + foreach my $id (@batch) { + LJ::MemCache::delete([$userid, "log2:$userid:$id"]); + } + LJ::MemCache::delete([$userid, "log2lt:$userid"]); + } + LJ::Tags::deleted_friend_group($u, $bit); + LJ::run_hooks('delete_friend_group', $u, $bit); + + # remove the friend group, unless we just added it this transaction + unless ($added{$bit}) { + $db->do("DELETE FROM $fgtable WHERE ". + "userid=$userid AND groupnum=$bit"); + } + } + + ## change friends' masks + # TAG:FR:protocol:editfriendgroups_changemasks + foreach my $friend (keys %{$req->{'groupmasks'}}) + { + my $mask = int($req->{'groupmasks'}->{$friend}) | 1; + my $friendid = LJ::get_userid($dbh, $friend); + + $dbh->do("UPDATE friends SET groupmask=$mask ". + "WHERE userid=$userid AND friendid=?", + undef, $friendid); + LJ::MemCache::set([$userid, "frgmask:$userid:$friendid"], $mask); + } + + # invalidate memcache of friends/groups + LJ::memcache_kill($userid, "friends"); + LJ::memcache_kill($userid, "fgrp"); + LJ::mark_dirty($u, "friends"); + + # return value for this is nothing. + return {}; +} + +sub sessionexpire { + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + my $u = $flags->{u}; + + # expunge one? or all? + if ($req->{expireall}) { + $u->kill_all_sessions; + return {}; + } + + # just expire a list + my $list = $req->{expire} || []; + return {} unless @$list; + return fail($err,502) unless $u->writer; + $u->kill_sessions(@$list); + return {}; +} + +sub sessiongenerate { + # generate a session + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + + # sanitize input + $req->{expiration} = 'short' unless $req->{expiration} eq 'long'; + my $boundip; + $boundip = LJ::get_remote_ip() if $req->{bindtoip}; + + my $u = $flags->{u}; + my $sess_opts = { + exptype => $req->{expiration}, + ipfixed => $boundip, + }; + + # do not let locked people do this + return fail($err, 308) if $u->{statusvis} eq 'L'; + + my $sess = $u->generate_session($sess_opts); + + # return our hash + return { + ljsession => "ws:$u->{user}:$sess->{sessid}:$sess->{auth}", + }; +} + +sub list_friends +{ + my ($u, $opts) = @_; + + my %hide_fo; # userid -> 1 + if ($LJ::HIDE_FRIENDOF_VIA_BAN) { + if (my $list = LJ::load_rel_user($u, 'B')) { + $hide_fo{$_} = 1 foreach @$list; + } + } + + # TAG:FR:protocol:list_friends + my $sql; + unless ($opts->{'friendof'}) { + $sql = "SELECT friendid, fgcolor, bgcolor, groupmask FROM friends WHERE userid=?"; + } else { + $sql = "SELECT userid FROM friends WHERE friendid=?"; + } + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare($sql); + $sth->execute($u->{'userid'}); + + my @frow; + while (my @row = $sth->fetchrow_array) { + next if $hide_fo{$row[0]}; + push @frow, [ @row ]; + } + + my $us = LJ::load_userids(map { $_->[0] } @frow); + my $limitnum = $opts->{'limit'}+0; + + my $res = []; + foreach my $f (sort { $us->{$a->[0]}{'user'} cmp $us->{$b->[0]}{'user'} } + grep { $us->{$_->[0]} } @frow) + { + my $u = $us->{$f->[0]}; + next if $opts->{'friendof'} && $u->{'statusvis'} ne 'V'; + + my $r = { + 'username' => $u->{'user'}, + 'fullname' => $u->{'name'}, + }; + + if ($opts->{'includebdays'} && + $u->{'bdate'} && + $u->{'bdate'} ne "0000-00-00" && + $u->{'allow_infoshow'} eq 'Y') + { + $r->{'birthday'} = $u->{'bdate'}; + } + + unless ($opts->{'friendof'}) { + $r->{'fgcolor'} = LJ::color_fromdb($f->[1]); + $r->{'bgcolor'} = LJ::color_fromdb($f->[2]); + $r->{"groupmask"} = $f->[3] if $f->[3] != 1; + } else { + $r->{'fgcolor'} = "#000000"; + $r->{'bgcolor'} = "#ffffff"; + } + + $r->{"type"} = { + 'C' => 'community', + 'Y' => 'syndicated', + 'N' => 'news', + 'S' => 'shared', + 'I' => 'identity', + }->{$u->{'journaltype'}} if $u->{'journaltype'} ne 'P'; + + $r->{"status"} = { + 'D' => "deleted", + 'S' => "suspended", + 'X' => "purged", + }->{$u->{'statusvis'}} if $u->{'statusvis'} ne 'V'; + + push @$res, $r; + # won't happen for zero limit (which means no limit) + last if @$res == $limitnum; + } + return $res; +} + +sub syncitems +{ + my ($req, $err, $flags) = @_; + return undef unless authenticate($req, $err, $flags); + return undef unless check_altusage($req, $err, $flags); + return fail($err,506) if $LJ::DISABLED{'syncitems'}; + + my $ownerid = $flags->{'ownerid'}; + my $uowner = $flags->{'u_owner'} || $flags->{'u'}; + my $sth; + + my $db = LJ::get_cluster_reader($uowner); + return fail($err,502) unless $db; + + ## have a valid date? + my $date = $req->{'lastsync'}; + if ($date) { + return fail($err,203,"Invalid date format") + unless ($date =~ /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/); + } else { + $date = "0000-00-00 00:00:00"; + } + + my $LIMIT = 500; + + my %item; + $sth = $db->prepare("SELECT jitemid, logtime FROM log2 WHERE ". + "journalid=? and logtime > ?"); + $sth->execute($ownerid, $date); + while (my ($id, $dt) = $sth->fetchrow_array) { + $item{$id} = [ 'L', $id, $dt, "create" ]; + } + + my %cmt; + my $p_calter = LJ::get_prop("log", "commentalter"); + my $p_revtime = LJ::get_prop("log", "revtime"); + $sth = $db->prepare("SELECT jitemid, propid, FROM_UNIXTIME(value) ". + "FROM logprop2 WHERE journalid=? ". + "AND propid IN ($p_calter->{'id'}, $p_revtime->{'id'}) ". + "AND value+0 > UNIX_TIMESTAMP(?)"); + $sth->execute($ownerid, $date); + while (my ($id, $prop, $dt) = $sth->fetchrow_array) { + if ($prop == $p_calter->{'id'}) { + $cmt{$id} = [ 'C', $id, $dt, "update" ]; + } elsif ($prop == $p_revtime->{'id'}) { + $item{$id} = [ 'L', $id, $dt, "update" ]; + } + } + + my @ev = sort { $a->[2] cmp $b->[2] } (values %item, values %cmt); + + my $res = {}; + my $list = $res->{'syncitems'} = []; + $res->{'total'} = scalar @ev; + my $ct = 0; + while (my $ev = shift @ev) { + $ct++; + push @$list, { 'item' => "$ev->[0]-$ev->[1]", + 'time' => $ev->[2], + 'action' => $ev->[3], }; + last if $ct >= $LIMIT; + } + $res->{'count'} = $ct; + return $res; +} + +sub consolecommand +{ + my ($req, $err, $flags) = @_; + + my $dbh = LJ::get_db_writer(); + return fail($err,502) unless $dbh; + + # logging in isn't necessary, but most console commands do require it + my $remote = undef; + $remote = $flags->{'u'} if authenticate($req, $err, $flags); + + # underage users can't do this, since we don't want to sanitize for + # what in particular they're trying to do, might as well disallow it + return fail($err, 310) if $remote->underage; + + # do not let locked people do this + return fail($err, 308) if $remote->{statusvis} eq 'L'; + + my $res = {}; + my $cmdout = $res->{'results'} = []; + + foreach my $cmd (@{$req->{'commands'}}) + { + # callee can pre-parse the args, or we can do it bash-style + $cmd = [ LJ::Con::parse_line($cmd) ] unless (ref $cmd eq "ARRAY"); + + my @output; + my $rv = LJ::Con::execute($dbh, $remote, $cmd, \@output); + push @{$cmdout}, { + 'success' => $rv, + 'output' => \@output, + }; + } + + return $res; +} + +sub getchallenge +{ + my ($req, $err, $flags) = @_; + my $res = {}; + my $now = time(); + my $etime = 60; + $res->{'challenge'} = LJ::challenge_generate($etime); + $res->{'server_time'} = $now; + $res->{'expire_time'} = $now + $etime; + $res->{'auth_scheme'} = "c0"; # fixed for now, might support others later + return $res; +} + +sub login_message +{ + my ($req, $res, $flags) = @_; + my $u = $flags->{'u'}; + + my $msg = sub { + my $code = shift; + my $args = shift || {}; + $args->{'sitename'} = $LJ::SITENAME; + $args->{'siteroot'} = $LJ::SITEROOT; + $res->{'message'} = translate($u, $code, $args); + }; + + return $msg->("readonly") if LJ::get_cap($u, "readonly"); + return $msg->("not_validated") if ($u->{'status'} eq "N" and not $LJ::EVERYONE_VALID); + return $msg->("must_revalidate") if ($u->{'status'} eq "T" and not $LJ::EVERYONE_VALID); + return $msg->("mail_bouncing") if $u->{'status'} eq "B"; + + my @checkpass = LJ::run_hooks("bad_password", $u); + return $msg->("bad_password") if (@checkpass and $checkpass[0]->[0]); + + return $msg->("old_win32_client") if $req->{'clientversion'} =~ /^Win32-MFC\/(1.2.[0123456])$/; + return $msg->("old_win32_client") if $req->{'clientversion'} =~ /^Win32-MFC\/(1.3.[01234])\b/; + return $msg->("hello_test") if $u->{'user'} eq "test"; +} + +sub list_friendgroups +{ + my $u = shift; + + # get the groups for this user, return undef if error + my $groups = LJ::get_friend_group($u); + return undef unless $groups; + + # we got all of the groups, so put them into an arrayref sorted by the + # group sortorder; also note that the map is used to construct a new hashref + # out of the old group hashref so that we have all of the field names converted + # to a format our callers can recognize + my @res = map { { id => $_->{groupnum}, name => $_->{groupname}, + public => $_->{is_public}, sortorder => $_->{sortorder}, } } + sort { $a->{sortorder} <=> $b->{sortorder} } + values %$groups; + + return \@res; +} + +sub list_usejournals +{ + my $u = shift; + + my @res; + + my $ids = LJ::load_rel_target($u, 'P'); + my $us = LJ::load_userids(@$ids); + foreach (values %$us) { + next unless $_->{'statusvis'} eq "V"; + push @res, $_->{user}; + } + @res = sort @res; + return \@res; +} + +sub hash_menus +{ + my $u = shift; + my $user = $u->{'user'}; + + my $menu = [ + { 'text' => "Recent Entries", + 'url' => "$LJ::SITEROOT/users/$user/", }, + { 'text' => "Calendar View", + 'url' => "$LJ::SITEROOT/users/$user/calendar", }, + { 'text' => "Friends View", + 'url' => "$LJ::SITEROOT/users/$user/friends", }, + { 'text' => "-", }, + { 'text' => "Your Profile", + 'url' => "$LJ::SITEROOT/userinfo.bml?user=$user", }, + { 'text' => "Your To-Do List", + 'url' => "$LJ::SITEROOT/todo/?user=$user", }, + { 'text' => "-", }, + { 'text' => "Change Settings", + 'sub' => [ { 'text' => "Personal Info", + 'url' => "$LJ::SITEROOT/editinfo.bml", }, + { 'text' => "Journal Settings", + 'url' =>"$LJ::SITEROOT/modify.bml", }, ] }, + { 'text' => "-", }, + { 'text' => "Support", + 'url' => "$LJ::SITEROOT/support/", } + ]; + + LJ::run_hooks("modify_login_menu", { + 'menu' => $menu, + 'u' => $u, + 'user' => $user, + }); + + return $menu; +} + +sub list_pickws +{ + my $u = shift; + + my $pi = LJ::get_userpic_info($u); + my @res; + + # FIXME: should be a utf-8 sort + foreach my $kw (sort keys %{$pi->{'kw'}}) { + my $pic = $pi->{'kw'}{$kw}; + next if $pic->{'state'} eq "I"; + push @res, [ $kw, $pic->{'picid'} ]; + } + + return \@res; +} + +sub list_moods +{ + my $mood_max = int(shift); + LJ::load_moods(); + + my $res = []; + return $res if $mood_max >= $LJ::CACHED_MOOD_MAX; + + for (my $id = $mood_max+1; $id <= $LJ::CACHED_MOOD_MAX; $id++) { + next unless defined $LJ::CACHE_MOODS{$id}; + my $mood = $LJ::CACHE_MOODS{$id}; + next unless $mood->{'name'}; + push @$res, { 'id' => $id, + 'name' => $mood->{'name'}, + 'parent' => $mood->{'parent'} }; + } + + return $res; +} + +sub check_altusage +{ + my ($req, $err, $flags) = @_; + + # see note in ljlib.pl::can_use_journal about why we return + # both 'ownerid' and 'u_owner' in $flags + + my $alt = $req->{'usejournal'}; + my $u = $flags->{'u'}; + $flags->{'ownerid'} = $u->{'userid'}; + + # all good if not using an alt journal + return 1 unless $alt; + + # complain if the username is invalid + return fail($err,206) unless LJ::canonical_username($alt); + + my $r = eval { Apache->request }; + + # allow usage if we're told explicitly that it's okay + if ($flags->{'usejournal_okay'}) { + $flags->{'u_owner'} = LJ::load_user($alt); + $flags->{'ownerid'} = $flags->{'u_owner'}->{'userid'}; + $r->notes("journalid" => $flags->{'ownerid'}) if $r && !$r->notes("journalid"); + return 1 if $flags->{'ownerid'}; + return fail($err,206); + } + + # otherwise, check for access: + my $info = {}; + my $canuse = LJ::can_use_journal($u->{'userid'}, $alt, $info); + $flags->{'ownerid'} = $info->{'ownerid'}; + $flags->{'u_owner'} = $info->{'u_owner'}; + $r->notes("journalid" => $flags->{'ownerid'}) if $r && !$r->notes("journalid"); + + return 1 if $canuse || $flags->{'ignorecanuse'}; + + # not allowed to access it + return fail($err,300); +} + +sub authenticate +{ + my ($req, $err, $flags) = @_; + + my $username = $req->{'username'}; + return fail($err,200) unless $username; + return fail($err,100) unless LJ::canonical_username($username); + + my $u = $flags->{'u'}; + unless ($u) { + my $dbr = LJ::get_db_reader(); + return fail($err,502) unless $dbr; + $u = LJ::load_user($username); + } + + return fail($err,100) unless $u; + return fail($err,100) if ($u->{'statusvis'} eq "X"); + return fail($err,505) unless $u->{'clusterid'}; + + my $r = eval { Apache->request }; + my $ip; + if ($r) { + $r->notes("ljuser" => $u->{'user'}) unless $r->notes("ljuser"); + $r->notes("journalid" => $u->{'userid'}) unless $r->notes("journalid"); + $ip = $r->connection->remote_ip; + } + + my $ip_banned = 0; + my $chal_expired = 0; + my $auth_check = sub { + my $auth_meth = $req->{'auth_method'} || "clear"; + if ($auth_meth eq "clear") { + return LJ::auth_okay($u, + $req->{'password'}, + $req->{'hpassword'}, + $u->{'password'}, + \$ip_banned); + } + if ($auth_meth eq "challenge") { + my $chal_opts = {}; + my $chall_ok = LJ::challenge_check_login($u, + $req->{'auth_challenge'}, + $req->{'auth_response'}, + \$ip_banned, + $chal_opts); + $chal_expired = 1 if $chal_opts->{expired}; + return $chall_ok; + } + if ($auth_meth eq "cookie") { + return unless $r && $r->header_in("X-LJ-Auth") eq "cookie"; + my $remote = LJ::get_remote(); + return $remote && $remote->{'user'} eq $username ? 1 : 0; + } + }; + + # predefined allowed auths (no pw required) + my $post_wo_auth = $LJ::POST_WITHOUT_AUTH{$ip}; + $flags->{'noauth'} = 1 if + $post_wo_auth && + $post_wo_auth->{ $req->{usejournal} } && + grep { $_ eq $req->{user} } @{ $post_wo_auth->{ $req->{usejournal} } }; + + unless ($flags->{'nopassword'} || + $flags->{'noauth'} || + $auth_check->() ) + { + return fail($err,402) if $ip_banned; + return fail($err,105) if $chal_expired; + return fail($err,101); + } + + # if there is a require TOS revision, check for it now + return fail($err, 156, LJ::tosagree_str('protocol' => 'text')) + unless $u->tosagree_verify; + + # remember the user record for later. + $flags->{'u'} = $u; + return 1; +} + +sub fail +{ + my $err = shift; + my $code = shift; + my $des = shift; + $code .= ":$des" if $des; + $$err = $code if (ref $err eq "SCALAR"); + return undef; +} + +# PROBLEM: a while back we used auto_increment fields in our tables so that we could have +# automatically incremented itemids and such. this was eventually phased out in favor of +# the more portable alloc_user_counter function which uses the 'counter' table. when the +# counter table has no data, it finds the highest id already in use in the database and adds +# one to it. +# +# a problem came about when users who last posted before alloc_user_counter went +# and deleted all their entries and posted anew. alloc_user_counter would find no entries, +# this no ids, and thus assign id 1, thinking it's all clean and new. but, id 1 had been +# used previously, and now has comments attached to it. +# +# the comments would happen because there was an old bug that wouldn't delete comments when +# an entry was deleted. this has since been fixed. so this all combines to make this +# a necessity, at least until no buggy data exist anymore! +# +# this code here removes any comments that happen to exist for the id we're now using. +sub new_entry_cleanup_hack { + my ($u, $jitemid) = @_; + + # sanitize input + $jitemid += 0; + return unless $jitemid; + my $ownerid = LJ::want_userid($u); + return unless $ownerid; + + # delete logprops + $u->do("DELETE FROM logprop2 WHERE journalid=$ownerid AND jitemid=$jitemid"); + + # delete comments + my $ids = LJ::Talk::get_talk_data($u, 'L', $jitemid); + return unless ref $ids eq 'HASH' && %$ids; + my $list = join ',', map { $_+0 } keys %$ids; + $u->do("DELETE FROM talk2 WHERE journalid=$ownerid AND jtalkid IN ($list)"); + $u->do("DELETE FROM talktext2 WHERE journalid=$ownerid AND jtalkid IN ($list)"); + $u->do("DELETE FROM talkprop2 WHERE journalid=$ownerid AND jtalkid IN ($list)"); +} + +#### Old interface (flat key/values) -- wrapper aruond LJ::Protocol +package LJ; + +sub do_request +{ + # get the request and response hash refs + my ($req, $res, $flags) = @_; + + # initialize some stuff + %{$res} = (); # clear the given response hash + $flags = {} unless (ref $flags eq "HASH"); + + # did they send a mode? + unless ($req->{'mode'}) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = "Client error: No mode specified."; + return; + } + + # this method doesn't require auth + if ($req->{'mode'} eq "getchallenge") { + return getchallenge($req, $res, $flags); + } + + # mode from here on out require a username + my $user = LJ::canonical_username($req->{'user'}); + unless ($user) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = "Client error: No username sent."; + return; + } + + ### see if the server's under maintenance now + if ($LJ::SERVER_DOWN) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = $LJ::SERVER_DOWN_MESSAGE; + return; + } + + ## dispatch wrappers + if ($req->{'mode'} eq "login") { + return login($req, $res, $flags); + } + if ($req->{'mode'} eq "getfriendgroups") { + return getfriendgroups($req, $res, $flags); + } + if ($req->{'mode'} eq "getfriends") { + return getfriends($req, $res, $flags); + } + if ($req->{'mode'} eq "friendof") { + return friendof($req, $res, $flags); + } + if ($req->{'mode'} eq "checkfriends") { + return checkfriends($req, $res, $flags); + } + if ($req->{'mode'} eq "getdaycounts") { + return getdaycounts($req, $res, $flags); + } + if ($req->{'mode'} eq "postevent") { + return postevent($req, $res, $flags); + } + if ($req->{'mode'} eq "editevent") { + return editevent($req, $res, $flags); + } + if ($req->{'mode'} eq "syncitems") { + return syncitems($req, $res, $flags); + } + if ($req->{'mode'} eq "getevents") { + return getevents($req, $res, $flags); + } + if ($req->{'mode'} eq "editfriends") { + return editfriends($req, $res, $flags); + } + if ($req->{'mode'} eq "editfriendgroups") { + return editfriendgroups($req, $res, $flags); + } + if ($req->{'mode'} eq "consolecommand") { + return consolecommand($req, $res, $flags); + } + if ($req->{'mode'} eq "sessiongenerate") { + return sessiongenerate($req, $res, $flags); + } + if ($req->{'mode'} eq "sessionexpire") { + return sessionexpire($req, $res, $flags); + } + + ### unknown mode! + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = "Client error: Unknown mode ($req->{'mode'})"; + return; +} + +## flat wrapper +sub login +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("login", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + $res->{'name'} = $rs->{'fullname'}; + $res->{'message'} = $rs->{'message'} if $rs->{'message'}; + $res->{'fastserver'} = 1 if $rs->{'fastserver'}; + + # shared journals + my $access_count = 0; + foreach my $user (@{$rs->{'usejournals'}}) { + $access_count++; + $res->{"access_${access_count}"} = $user; + } + if ($access_count) { + $res->{"access_count"} = $access_count; + } + + # friend groups + populate_friend_groups($res, $rs->{'friendgroups'}); + + my $flatten = sub { + my ($prefix, $listref) = @_; + my $ct = 0; + foreach (@$listref) { + $ct++; + $res->{"${prefix}_$ct"} = $_; + } + $res->{"${prefix}_count"} = $ct; + }; + + ### picture keywords + $flatten->("pickw", $rs->{'pickws'}) + if defined $req->{"getpickws"}; + $flatten->("pickwurl", $rs->{'pickwurls'}) + if defined $req->{"getpickwurls"}; + $res->{'defaultpicurl'} = $rs->{'defaultpicurl'} if $rs->{'defaultpicurl'}; + + ### report new moods that this client hasn't heard of, if they care + if (defined $req->{"getmoods"}) { + my $mood_count = 0; + foreach my $m (@{$rs->{'moods'}}) { + $mood_count++; + $res->{"mood_${mood_count}_id"} = $m->{'id'}; + $res->{"mood_${mood_count}_name"} = $m->{'name'}; + $res->{"mood_${mood_count}_parent"} = $m->{'parent'}; + } + if ($mood_count) { + $res->{"mood_count"} = $mood_count; + } + } + + #### send web menus + if ($req->{"getmenus"} == 1) { + my $menu = $rs->{'menus'}; + my $menu_num = 0; + populate_web_menu($res, $menu, \$menu_num); + } + + return 1; +} + +## flat wrapper +sub getfriendgroups +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("getfriendgroups", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + $res->{'success'} = "OK"; + populate_friend_groups($res, $rs->{'friendgroups'}); + + return 1; +} + +## flat wrapper +sub getfriends +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("getfriends", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + if ($req->{'includegroups'}) { + populate_friend_groups($res, $rs->{'friendgroups'}); + } + if ($req->{'includefriendof'}) { + populate_friends($res, "friendof", $rs->{'friendofs'}); + } + populate_friends($res, "friend", $rs->{'friends'}); + + return 1; +} + +## flat wrapper +sub friendof +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("friendof", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + populate_friends($res, "friendof", $rs->{'friendofs'}); + return 1; +} + +## flat wrapper +sub checkfriends +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("checkfriends", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + $res->{'new'} = $rs->{'new'}; + $res->{'lastupdate'} = $rs->{'lastupdate'}; + $res->{'interval'} = $rs->{'interval'}; + return 1; +} + +## flat wrapper +sub getdaycounts +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("getdaycounts", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + foreach my $d (@{ $rs->{'daycounts'} }) { + $res->{$d->{'date'}} = $d->{'count'}; + } + return 1; +} + +## flat wrapper +sub syncitems +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("syncitems", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + $res->{'sync_total'} = $rs->{'total'}; + $res->{'sync_count'} = $rs->{'count'}; + + my $ct = 0; + foreach my $s (@{ $rs->{'syncitems'} }) { + $ct++; + foreach my $a (qw(item action time)) { + $res->{"sync_${ct}_$a"} = $s->{$a}; + } + } + return 1; +} + +## flat wrapper: limited functionality. (1 command only, server-parsed only) +sub consolecommand +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + delete $rq->{'command'}; + + $rq->{'commands'} = [ $req->{'command'} ]; + + my $rs = LJ::Protocol::do_request("consolecommand", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'cmd_success'} = $rs->{'results'}->[0]->{'success'}; + $res->{'cmd_line_count'} = 0; + foreach my $l (@{$rs->{'results'}->[0]->{'output'}}) { + $res->{'cmd_line_count'}++; + my $line = $res->{'cmd_line_count'}; + $res->{"cmd_line_${line}_type"} = $l->[0] + if $l->[0]; + $res->{"cmd_line_${line}"} = $l->[1]; + } + + $res->{'success'} = "OK"; + +} + +## flat wrapper +sub getchallenge +{ + my ($req, $res, $flags) = @_; + my $err = 0; + my $rs = LJ::Protocol::do_request("getchallenge", $req, \$err, $flags); + + # stupid copy (could just return $rs), but it might change in the future + # so this protects us from future accidental harm. + foreach my $k (qw(challenge server_time expire_time auth_scheme)) { + $res->{$k} = $rs->{$k}; + } + + $res->{'success'} = "OK"; + return $res; +} + +## flat wrapper +sub editfriends +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + $rq->{'add'} = []; + $rq->{'delete'} = []; + + foreach (keys %$req) { + if (/^editfriend_add_(\d+)_user$/) { + my $n = $1; + next unless ($req->{"editfriend_add_${n}_user"} =~ /\S/); + my $fa = { 'username' => $req->{"editfriend_add_${n}_user"}, + 'fgcolor' => $req->{"editfriend_add_${n}_fg"}, + 'bgcolor' => $req->{"editfriend_add_${n}_bg"}, + 'groupmask' => $req->{"editfriend_add_${n}_groupmask"}, + }; + push @{$rq->{'add'}}, $fa; + } elsif (/^editfriend_delete_(\w+)$/) { + push @{$rq->{'delete'}}, $1; + } + } + + my $rs = LJ::Protocol::do_request("editfriends", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + + my $ct = 0; + foreach my $fa (@{ $rs->{'added'} }) { + $ct++; + $res->{"friend_${ct}_user"} = $fa->{'username'}; + $res->{"friend_${ct}_name"} = $fa->{'fullname'}; + } + + $res->{'friends_added'} = $ct; + + return 1; +} + +## flat wrapper +sub editfriendgroups +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + $rq->{'groupmasks'} = {}; + $rq->{'set'} = {}; + $rq->{'delete'} = []; + + foreach (keys %$req) { + if (/^efg_set_(\d+)_name$/) { + next unless ($req->{$_} ne ""); + my $n = $1; + my $fs = { + 'name' => $req->{"efg_set_${n}_name"}, + 'sort' => $req->{"efg_set_${n}_sort"}, + }; + if (defined $req->{"efg_set_${n}_public"}) { + $fs->{'public'} = $req->{"efg_set_${n}_public"}; + } + $rq->{'set'}->{$n} = $fs; + } + elsif (/^efg_delete_(\d+)$/) { + if ($req->{$_}) { + # delete group if value is true + push @{$rq->{'delete'}}, $1; + } + } + elsif (/^editfriend_groupmask_(\w+)$/) { + $rq->{'groupmasks'}->{$1} = $req->{$_}; + } + } + + my $rs = LJ::Protocol::do_request("editfriendgroups", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + return 1; +} + +sub flatten_props +{ + my ($req, $rq) = @_; + + ## changes prop_* to props hashref + foreach my $k (keys %$req) { + next unless ($k =~ /^prop_(.+)/); + $rq->{'props'}->{$1} = $req->{$k}; + } +} + +## flat wrapper +sub postevent +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + flatten_props($req, $rq); + + my $rs = LJ::Protocol::do_request("postevent", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'message'} = $rs->{'message'} if $rs->{'message'}; + $res->{'success'} = "OK"; + $res->{'itemid'} = $rs->{'itemid'}; + $res->{'anum'} = $rs->{'anum'} if defined $rs->{'anum'}; + $res->{'url'} = $rs->{'url'} if defined $rs->{'url'}; + return 1; +} + +## flat wrapper +sub editevent +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + flatten_props($req, $rq); + + my $rs = LJ::Protocol::do_request("editevent", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + $res->{'success'} = "OK"; + $res->{'itemid'} = $rs->{'itemid'}; + $res->{'anum'} = $rs->{'anum'} if defined $rs->{'anum'}; + $res->{'url'} = $rs->{'url'} if defined $rs->{'url'}; + return 1; +} + +## flat wrapper +sub sessiongenerate { + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request('sessiongenerate', $rq, \$err, $flags); + unless ($rs) { + $res->{success} = 'FAIL'; + $res->{errmsg} = LJ::Protocol::error_message($err); + } + + $res->{success} = 'OK'; + $res->{ljsession} = $rs->{ljsession}; + return 1; +} + +## flat wrappre +sub sessionexpire { + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + $rq->{expire} = []; + foreach my $k (keys %$rq) { + push @{$rq->{expire}}, $1 + if $k =~ /^expire_id_(\d+)$/; + } + + my $rs = LJ::Protocol::do_request('sessionexpire', $rq, \$err, $flags); + unless ($rs) { + $res->{success} = 'FAIL'; + $res->{errmsg} = LJ::Protocol::error_message($err); + } + + $res->{success} = 'OK'; + return 1; +} + +## flat wrapper +sub getevents +{ + my ($req, $res, $flags) = @_; + + my $err = 0; + my $rq = upgrade_request($req); + + my $rs = LJ::Protocol::do_request("getevents", $rq, \$err, $flags); + unless ($rs) { + $res->{'success'} = "FAIL"; + $res->{'errmsg'} = LJ::Protocol::error_message($err); + return 0; + } + + my $ect = 0; + my $pct = 0; + foreach my $evt (@{$rs->{'events'}}) { + $ect++; + foreach my $f (qw(itemid eventtime security allowmask subject anum url poster)) { + if (defined $evt->{$f}) { + $res->{"events_${ect}_$f"} = $evt->{$f}; + } + } + $res->{"events_${ect}_event"} = LJ::eurl($evt->{'event'}); + + if ($evt->{'props'}) { + foreach my $k (sort keys %{$evt->{'props'}}) { + $pct++; + $res->{"prop_${pct}_itemid"} = $evt->{'itemid'}; + $res->{"prop_${pct}_name"} = $k; + $res->{"prop_${pct}_value"} = $evt->{'props'}->{$k}; + } + } + } + + unless ($req->{'noprops'}) { + $res->{'prop_count'} = $pct; + } + $res->{'events_count'} = $ect; + $res->{'success'} = "OK"; + + return 1; +} + + +sub populate_friends +{ + my ($res, $pfx, $list) = @_; + my $count = 0; + foreach my $f (@$list) + { + $count++; + $res->{"${pfx}_${count}_name"} = $f->{'fullname'}; + $res->{"${pfx}_${count}_user"} = $f->{'username'}; + $res->{"${pfx}_${count}_birthday"} = $f->{'birthday'} if $f->{'birthday'}; + $res->{"${pfx}_${count}_bg"} = $f->{'bgcolor'}; + $res->{"${pfx}_${count}_fg"} = $f->{'fgcolor'}; + if (defined $f->{'groupmask'}) { + $res->{"${pfx}_${count}_groupmask"} = $f->{'groupmask'}; + } + if (defined $f->{'type'}) { + $res->{"${pfx}_${count}_type"} = $f->{'type'}; + } + if (defined $f->{'status'}) { + $res->{"${pfx}_${count}_status"} = $f->{'status'}; + } + } + $res->{"${pfx}_count"} = $count; +} + + +sub upgrade_request +{ + my $r = shift; + my $new = { %{ $r } }; + $new->{'username'} = $r->{'user'}; + + # but don't delete $r->{'user'}, as it might be, say, %FORM, + # that'll get reused in a later request in, say, update.bml after + # the login before postevent. whoops. + + return $new; +} + +## given a $res hashref and friend group subtree (arrayref), flattens it +sub populate_friend_groups +{ + my ($res, $fr) = @_; + + my $maxnum = 0; + foreach my $fg (@$fr) + { + my $num = $fg->{'id'}; + $res->{"frgrp_${num}_name"} = $fg->{'name'}; + $res->{"frgrp_${num}_sortorder"} = $fg->{'sortorder'}; + if ($fg->{'public'}) { + $res->{"frgrp_${num}_public"} = 1; + } + if ($num > $maxnum) { $maxnum = $num; } + } + $res->{'frgrp_maxnum'} = $maxnum; +} + +## given a menu tree, flattens it into $res hashref +sub populate_web_menu +{ + my ($res, $menu, $numref) = @_; + my $mn = $$numref; # menu number + my $mi = 0; # menu item + foreach my $it (@$menu) { + $mi++; + $res->{"menu_${mn}_${mi}_text"} = $it->{'text'}; + if ($it->{'text'} eq "-") { next; } + if ($it->{'sub'}) { + $$numref++; + $res->{"menu_${mn}_${mi}_sub"} = $$numref; + &populate_web_menu($res, $it->{'sub'}, $numref); + next; + + } + $res->{"menu_${mn}_${mi}_url"} = $it->{'url'}; + } + $res->{"menu_${mn}_count"} = $mi; +} + +1; diff --git a/livejournal/cgi-bin/ljtodo.pl b/livejournal/cgi-bin/ljtodo.pl new file mode 100755 index 0000000..c590d8d --- /dev/null +++ b/livejournal/cgi-bin/ljtodo.pl @@ -0,0 +1,45 @@ +#!/usr/bin/perl +# + +package LJ::Todo; + +sub get_permissions +{ + my ($dbh, $perm, $opts) = @_; + my $sth; + my $u = $opts->{'user'}; + my $remote = $opts->{'remote'}; + my $it = $opts->{'item'}; + + return () unless $remote; + + if ($u->{'userid'} == $remote->{'userid'}) { + $perm->{'delete'} = 1; + $perm->{'edit'} = 1; + $perm->{'add'} = 1; + } else { + my $quser = $dbh->quote($u->{'user'}); + + ## check if you're an admin of that journal + my $is_manager = LJ::can_manage($remote, $u); + if ($is_manager) { + $perm->{'add'} = 1; + $perm->{'delete'} = 1; + $perm->{'edit'} = 1; + } else { + # TAG:FR:ljtodo:get_friends_in_group + foreach my $priv (qw(add edit delete)) { + my $group = LJ::get_friend_group($u, { name => "priv-todo-$priv" }); + next unless $group; + my $mask = 1 << $group->{groupnum}; + my $friends = LJ::get_friends($u, $mask); + $perm->{$priv} = 1 if $friends->{$remote->{userid}}; + } + } + } + + return %permission; +} + + +1; diff --git a/livejournal/cgi-bin/ljviews.pl b/livejournal/cgi-bin/ljviews.pl new file mode 100755 index 0000000..1e4a916 --- /dev/null +++ b/livejournal/cgi-bin/ljviews.pl @@ -0,0 +1,2361 @@ +#!/usr/bin/perl +# +# +# lib: cgi-bin/ljlib.pl, cgi-bin/ljconfig.pl, cgi-bin/ljlang.pl, cgi-bin/cleanhtml.pl +# + +use strict; + +package LJ::S1; + +use vars qw(@themecoltypes); + +# this used to be in a table, but that was kinda useless +@themecoltypes = ( + [ 'page_back', 'Page background' ], + [ 'page_text', 'Page text' ], + [ 'page_link', 'Page link' ], + [ 'page_vlink', 'Page visited link' ], + [ 'page_alink', 'Page active link' ], + [ 'page_text_em', 'Page emphasized text' ], + [ 'page_text_title', 'Page title' ], + [ 'weak_back', 'Weak accent' ], + [ 'weak_text', 'Text on weak accent' ], + [ 'strong_back', 'Strong accent' ], + [ 'strong_text', 'Text on strong accent' ], + [ 'stronger_back', 'Stronger accent' ], + [ 'stronger_text', 'Text on stronger accent' ], + ); + +# updated everytime new S1 style cleaning rules are added, +# so cached cleaned versions are invalidated. +$LJ::S1::CLEANER_VERSION = 5; + +# PROPERTY Flags: + +# /a/: +# safe in styles as sole attributes, without any cleaning. for +# example: is okay, # if we're in +# LASTN_TALK_READLINK, because the system generates # %%urlread%%. +# by default, if we don't declare things trusted here, # we'll +# double-check all attributes at the end for potential XSS # +# problems. +# +# /u/: +# is a URL. implies /a/. +# +# +# /d/: +# is a number. implies /a/. +# +# /t/: +# tainted! User controls via other some other variable. +# +# /s/: +# some system string... probably safe. but maybe possible to coerce it +# alongside something else. + +my $commonprop = { + 'dateformat' => { + 'yy' => 'd', 'yyyy' => 'd', + 'm' => 'd', 'mm' => 'd', + 'd' => 'd', 'dd' => 'd', + 'min' => 'd', + '12h' => 'd', '12hh' => 'd', + '24h' => 'd', '24hh' => 'd', + }, + 'talklinks' => { + 'messagecount' => 'd', + 'urlread' => 'u', + 'urlpost' => 'u', + 'itemid' => 'd', + }, + 'talkreadlink' => { + 'messagecount' => 'd', + 'urlread' => 'u', + }, + 'event' => { + 'itemid' => 'd', + }, + 'pic' => { + 'src' => 'u', + 'width' => 'd', + 'height' => 'd', + }, + 'newday' => { + yy => 'd', yyyy => 'd', m => 'd', mm => 'd', + d => 'd', dd => 'd', + }, + 'skip' => { + 'numitems' => 'd', + 'url' => 'u', + }, + +}; + +$LJ::S1::PROPS = { + 'CALENDAR_DAY' => { + 'd' => 'd', + 'eventcount' => 'd', + 'dayevent' => 't', + 'daynoevent' => 't', + }, + 'CALENDAR_DAY_EVENT' => { + 'eventcount' => 'd', + 'dayurl' => 'u', + }, + 'CALENDAR_DAY_NOEVENT' => { + }, + 'CALENDAR_EMPTY_DAYS' => { + 'numempty' => 'd', + }, + 'CALENDAR_MONTH' => { + 'monlong' => 's', + 'monshort' => 's', + 'yy' => 'd', + 'yyyy' => 'd', + 'weeks' => 't', + 'urlmonthview' => 'u', + }, + 'CALENDAR_NEW_YEAR' => { + 'yy' => 'd', + 'yyyy' => 'd', + }, + 'CALENDAR_PAGE' => { + 'name' => 't', + "name-'s" => 's', + 'yearlinks' => 't', + 'months' => 't', + 'username' => 's', + 'website' => 't', + 'head' => 't', + 'urlfriends' => 'u', + 'urllastn' => 'u', + }, + 'CALENDAR_WEBSITE' => { + 'url' => 't', + 'name' => 't', + }, + 'CALENDAR_WEEK' => { + 'days' => 't', + 'emptydays_beg' => 't', + 'emptydays_end' => 't', + }, + 'CALENDAR_YEAR_DISPLAYED' => { + 'yyyy' => 'd', + 'yy' => 'd', + }, + 'CALENDAR_YEAR_LINK' => { + 'yyyy' => 'd', + 'yy' => 'd', + 'url' => 'u', + }, + 'CALENDAR_YEAR_LINKS' => { + 'years' => 't', + }, + + # day + 'DAY_DATE_FORMAT' => $commonprop->{'dateformat'}, + 'DAY_EVENT' => $commonprop->{'event'}, + 'DAY_EVENT_PRIVATE' => $commonprop->{'event'}, + 'DAY_EVENT_PROTECTED' => $commonprop->{'event'}, + 'DAY_PAGE' => { + 'prevday_url' => 'u', + 'nextday_url' => 'u', + 'yy' => 'd', 'yyyy' => 'd', + 'm' => 'd', 'mm' => 'd', + 'd' => 'd', 'dd' => 'd', + 'urllastn' => 'u', + 'urlcalendar' => 'u', + 'urlfriends' => 'u', + }, + 'DAY_TALK_LINKS' => $commonprop->{'talklinks'}, + 'DAY_TALK_READLINK' => $commonprop->{'talkreadlink'}, + + # friends + 'FRIENDS_DATE_FORMAT' => $commonprop->{'dateformat'}, + 'FRIENDS_EVENT' => $commonprop->{'event'}, + 'FRIENDS_EVENT_PRIVATE' => $commonprop->{'event'}, + 'FRIENDS_EVENT_PROTECTED' => $commonprop->{'event'}, + 'FRIENDS_FRIENDPIC' => $commonprop->{'pic'}, + 'FRIENDS_NEW_DAY' => $commonprop->{'newday'}, + 'FRIENDS_RANGE_HISTORY' => { + 'numitems' => 'd', + 'skip' => 'd', + }, + 'FRIENDS_RANGE_MOSTRECENT' => { + 'numitems' => 'd', + }, + 'FRIENDS_SKIP_BACKWARD' => $commonprop->{'skip'}, + 'FRIENDS_SKIP_FORWARD' => $commonprop->{'skip'}, + 'FRIENDS_TALK_LINKS' => $commonprop->{'talklinks'}, + 'FRIENDS_TALK_READLINK' => $commonprop->{'talkreadlink'}, + + # lastn + 'LASTN_ALTPOSTER' => { + 'poster' => 's', + 'owner' => 's', + 'pic' => 't', + }, + 'LASTN_ALTPOSTER_PIC' => $commonprop->{'pic'}, + 'LASTN_CURRENT' => { + 'what' => 's', + 'value' => 't', + }, + 'LASTN_CURRENTS' => { + 'currents' => 't', + }, + 'LASTN_DATEFORMAT' => $commonprop->{'dateformat'}, + 'LASTN_EVENT' => $commonprop->{'event'}, + 'LASTN_EVENT_PRIVATE' => $commonprop->{'event'}, + 'LASTN_EVENT_PROTECTED' => $commonprop->{'event'}, + 'LASTN_NEW_DAY' => $commonprop->{'newday'}, + 'LASTN_PAGE' => { + 'urlfriends' => 'u', + 'urlcalendar' => 'u', + }, + 'LASTN_RANGE_HISTORY' => { + 'numitems' => 'd', + 'skip' => 'd', + }, + 'LASTN_RANGE_MOSTRECENT' => { + 'numitems' => 'd', + }, + 'LASTN_SKIP_BACKWARD' => $commonprop->{'skip'}, + 'LASTN_SKIP_FORWARD' => $commonprop->{'skip'}, + 'LASTN_TALK_LINKS' => $commonprop->{'talklinks'}, + 'LASTN_TALK_READLINK' => $commonprop->{'talkreadlink'}, + 'LASTN_USERPIC' => { + 'src' => 'u', + 'width' => 'd', + 'height' => 'd', + }, + +}; + +# +# name: LJ::S1::get_themeid +# des: Loads or returns cached version of given color theme data. +# returns: Hashref with color names as keys +# args: dbarg?, themeid +# des-themeid: S1 themeid. +# +sub get_themeid +{ + &LJ::nodb; + my $themeid = shift; + return $LJ::S1::CACHE_THEMEID{$themeid} if $LJ::S1::CACHE_THEMEID{$themeid}; + my $dbr = LJ::get_db_reader(); + my $ret = {}; + my $sth = $dbr->prepare("SELECT coltype, color FROM themedata WHERE themeid=?"); + $sth->execute($themeid); + $ret->{$_->{'coltype'}} = $_->{'color'} while $_ = $sth->fetchrow_hashref; + return $LJ::S1::CACHE_THEMEID{$themeid} = $ret; +} + +# returns: hashref of vars (cleaned) +sub load_style +{ + &LJ::nodb; + my ($styleid, $viewref) = @_; + + # first try local cache for this process + my $cch = $LJ::S1::CACHE_STYLE{$styleid}; + if ($cch && $cch->{'cachetime'} > time() - 300) { + $$viewref = $cch->{'type'} if ref $viewref eq "SCALAR"; + return $cch->{'style'}; + } + + # try memcache + my $memkey = [$styleid, "s1styc:$styleid"]; + my $styc = LJ::MemCache::get($memkey); + + # database handle we'll use if we have to rebuild the cache + my $db; + + # function to return a given a styleid + my $find_db = sub { + my $sid = shift; + + # should we work with a global or clustered table? + my $userid = LJ::S1::get_style_userid($sid); + + # if the user's style is clustered, need to get a $u + my $u = $userid ? LJ::load_userid($userid) : undef; + + # return appropriate db handle + if ($u && $u->{'dversion'} >= 5) { # users' styles are clustered + return LJ::S1::get_s1style_writer($u); + } + + return @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + }; + + # get database stylecache + unless ($styc) { + + $db = $find_db->($styleid); + $styc = $db->selectrow_hashref("SELECT * FROM s1stylecache WHERE styleid=?", + undef, $styleid); + LJ::MemCache::set($memkey, $styc, time()+60*30) if $styc; + } + + # no stylecache in db, built a new one + if (! $styc || $styc->{'vars_cleanver'} < $LJ::S1::CLEANER_VERSION) { + my $style = LJ::S1::get_style($styleid); + return {} unless $style; + + $db ||= $find_db->($styleid); + + $styc = { + 'type' => $style->{'type'}, + 'opt_cache' => $style->{'opt_cache'}, + 'vars_stor' => LJ::CleanHTML::clean_s1_style($style->{'formatdata'}), + 'vars_cleanver' => $LJ::S1::CLEANER_VERSION, + }; + + # do this query on the db handle we used above + $db->do("REPLACE INTO s1stylecache (styleid, cleandate, type, opt_cache, vars_stor, vars_cleanver) ". + "VALUES (?,NOW(),?,?,?,?)", undef, $styleid, + map { $styc->{$_} } qw(type opt_cache vars_stor vars_cleanver)); + } + + my $ret = Storable::thaw($styc->{'vars_stor'}); + $$viewref = $styc->{'type'} if ref $viewref eq "SCALAR"; + + if ($styc->{'opt_cache'} eq "Y") { + $LJ::S1::CACHE_STYLE{$styleid} = { + 'style' => $ret, + 'cachetime' => time(), + 'type' => $styc->{'type'}, + }; + } + + return $ret; +} + +# LJ::S1::get_public_styles +# +# LJ::load_user_props calls LJ::S1::get_public_styles and since +# a lot of cron jobs call LJ::load_user_props, we've moved +# LJ::S1::get_public_styles to ljlib so that it can be used +# without including ljviews.pl + +sub get_s1style_writer { + my $u = shift; + return undef unless LJ::isu($u); + + # special case system, its styles live on + # the global master's s1style table alone + if ($u->{'user'} eq 'system') { + return LJ::get_db_writer(); + } + + return $u->writer; +} + +sub get_s1style_reader { + my $u = shift; + return undef unless LJ::isu($u); + + # special case system, its styles live on + # the global master's s1style table alone + if ($u->{'user'} eq 'system') { + return @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + } + + return @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); +} + +# takes either $u object or userid +sub get_user_styles { + my $u = shift; + $u = LJ::isu($u) ? $u : LJ::load_user($u); + return undef unless $u; + + my %styles; + + # all cols *except* formatdata, which is big and unnecessary for most uses. + # it'll be loaded by LJ::S1::get_style + my $cols = "styleid, styledes, type, is_public, is_embedded, ". + "is_colorfree, opt_cache, has_ads, lastupdate"; + + # new clustered table + my ($db, $sth); + if ($u->{'dversion'} >= 5) { + $db = LJ::S1::get_s1style_reader($u); + $sth = $db->prepare("SELECT userid, $cols FROM s1style WHERE userid=?"); + $sth->execute($u->{'userid'}); + + # old global table + } else { + $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + $sth = $db->prepare("SELECT user, $cols FROM style WHERE user=?"); + $sth->execute($u->{'user'}); + } + + # build data structure + while (my $row = $sth->fetchrow_hashref) { + + # fix up both userid and user values for consistency + $row->{'userid'} = $u->{'userid'}; + $row->{'user'} = $u->{'user'}; + + $styles{$row->{'styleid'}} = $row; + next unless @LJ::MEMCACHE_SERVERS; + + # now update memcache while we have this data? + LJ::MemCache::set([$row->{'styleid'}, "s1style:$row->{'styleid'}"], $row); + } + + return \%styles; +} + +# includes formatdata row. +sub get_style { + my $styleid = shift; + return unless $styleid; + + my $memkey = [$styleid, "s1style_all:$styleid"]; + my $style = LJ::MemCache::get($memkey); + return $style if $style; + + # query global mapping table, returns undef if style isn't clustered + my $userid = LJ::S1::get_style_userid($styleid); + + my $u; + $u = LJ::load_userid($userid) if $userid; + + # new clustered table + if ($u && $u->{'dversion'} >= 5) { + my $db = LJ::S1::get_s1style_reader($u); + $style = $db->selectrow_hashref("SELECT * FROM s1style WHERE styleid=?", undef, $styleid); + + # fill in user since the caller may expect it + $style->{'user'} = $u->{'user'}; + + # old global table + } else { + my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + $style = $db->selectrow_hashref("SELECT * FROM style WHERE styleid=?", undef, $styleid); + + # fill in userid since the caller may expect it + $style->{'userid'} = LJ::get_userid($style->{'user'}); + } + return unless $style; + + LJ::MemCache::set($memkey, $style); + + return $style; +} + +sub check_dup_style { + my ($u, $type, $styledes) = @_; + return unless $type && $styledes; + + $u = LJ::isu($u) ? $u : LJ::load_user($u); + + # new clustered table + if ($u && $u->{'dversion'} >= 5) { + # get writer since this function is to check duplicates. as such, + # the write action we're checking for probably happened recently + my $db = LJ::S1::get_s1style_writer($u); + return $db->selectrow_hashref("SELECT * FROM s1style WHERE userid=? AND type=? AND styledes=?", + undef, $u->{'userid'}, $type, $styledes); + + # old global table + } else { + my $dbh = LJ::get_db_writer(); + return $dbh->selectrow_hashref("SELECT * FROM style WHERE user=? AND type=? AND styledes=?", + undef, $u->{'user'}, $type, $styledes); + } +} + +# returns undef if style isn't clustered +sub get_style_userid { + my $styleid = shift; + + # check cache + my $userid = $LJ::S1::REQ_CACHE_STYLEMAP{$styleid}; + return $userid if $userid; + + my $memkey = [$styleid, "s1stylemap:$styleid"]; + my $style = LJ::MemCache::get($memkey); + return $style if $style; + + # fetch from db + my $dbr = LJ::get_db_reader(); + $userid = $dbr->selectrow_array("SELECT userid FROM s1stylemap WHERE styleid=?", + undef, $styleid); + return unless $userid; + + # set cache + $LJ::S1::REQ_CACHE_STYLEMAP{$styleid} = $userid; + LJ::MemCache::set($memkey, $userid); + + return $userid; +} + +sub create_style { + my ($u, $opts) = @_; + return unless LJ::isu($u) && ref $opts eq 'HASH'; + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + my $styleid = LJ::alloc_global_counter('S'); + return undef unless $styleid; + + my (@cols, @bind, @vals); + foreach (qw(styledes type formatdata is_public is_embedded is_colorfree opt_cache has_ads)) { + next unless $opts->{$_}; + + push @cols, $_; + push @bind, "?"; + push @vals, $opts->{$_}; + } + my $cols = join(",", @cols); + my $bind = join(",", @bind); + return unless @cols; + + if ($u->{'dversion'} >= 5) { + my $db = LJ::S1::get_s1style_writer($u); + $db->do("INSERT INTO s1style (styleid,userid,$cols) VALUES (?,?,$bind)", + undef, $styleid, $u->{'userid'}, @vals); + my $insertid = LJ::User::mysql_insertid($db); + die "Couldn't allocate insertid for s1style for userid $u->{userid}" unless $insertid; + + $dbh->do("INSERT INTO s1stylemap (styleid, userid) VALUES (?,?)", undef, $insertid, $u->{'userid'}); + return $insertid; + + } else { + $dbh->do("INSERT INTO style (styleid, user,$cols) VALUES (?,?,$bind)", + undef, $styleid, $u->{'user'}, @vals); + return $dbh->{'mysql_insertid'}; + } +} + +sub update_style { + my ($styleid, $opts) = @_; + return unless $styleid && ref $opts eq 'HASH'; + + # query global mapping table, returns undef if style isn't clustered + my $userid = LJ::S1::get_style_userid($styleid); + + my $u; + $u = LJ::load_userid($userid) if $userid; + + my @cols = qw(styledes type formatdata is_public is_embedded + is_colorfree opt_cache has_ads lastupdate); + + # what table to operate on ? + my ($db, $table); + + # clustered table + if ($u && $u->{'dversion'} >= 5) { + $db = LJ::S1::get_s1style_writer($u); + $table = "s1style"; + + # global table + } else { + $db = LJ::get_db_writer(); + $table = "style"; + } + + my (@sets, @vals); + foreach (@cols) { + if ($opts->{$_}) { + push @sets, "$_=?"; + push @vals, $opts->{$_}; + } + } + + # update style + my $now_lastupdate = $opts->{'lastupdate'} ? ", lastupdate=NOW()" : ''; + my $rows = $db->do("UPDATE $table SET " . join(", ", @sets) . "$now_lastupdate WHERE styleid=?", + undef, @vals, $styleid); + + # clear out stylecache + $db->do("UPDATE s1stylecache SET vars_stor=NULL, vars_cleanver=0 WHERE styleid=?", + undef, $styleid); + + # update memcache keys + LJ::MemCache::delete([$styleid, "s1style:$styleid"]); + LJ::MemCache::delete([$styleid, "s1style_all:$styleid"]); + LJ::MemCache::delete([$styleid, "s1styc:$styleid"]); + + return $rows; +} + +sub delete_style { + my $styleid = shift; + return unless $styleid; + + # query global mapping table, returns undef if style isn't clustered + my $userid = LJ::S1::get_style_userid($styleid); + + my $u; + $u = LJ::load_userid($userid) if $userid; + + my $dbh = LJ::get_db_writer(); + + # new clustered table + if ($u && $u->{'dversion'} >= 5) { + $dbh->do("DELETE FROM s1stylemap WHERE styleid=?", undef, $styleid); + + my $db = LJ::S1::get_s1style_writer($u); + $db->do("DELETE FROM s1style WHERE styleid=?", undef, $styleid); + $db->do("DELETE FROM s1stylecache WHERE styleid=?", undef, $styleid); + + # old global table + } else { + # they won't have an s1stylemap entry + + $dbh->do("DELETE FROM style WHERE styleid=?", undef, $styleid); + $dbh->do("DELETE FROM s1stylecache WHERE styleid=?", undef, $styleid); + } + + # clear out some memcache space + LJ::MemCache::delete([$styleid, "s1style:$styleid"]); + LJ::MemCache::delete([$styleid, "s1style_all:$styleid"]); + LJ::MemCache::delete([$styleid, "s1stylemap:$styleid"]); + LJ::MemCache::delete([$styleid, "s1styc:$styleid"]); + + return; +} + +sub get_overrides { + my $u = shift; + return unless LJ::isu($u); + + # try memcache + my $memkey = [$u->{'userid'}, "s1overr:$u->{'userid'}"]; + my $overr = LJ::MemCache::get($memkey); + return $overr if $overr; + + # new clustered table + if ($u->{'dversion'} >= 5) { + my $db = @LJ::MEMCACHE_SERVERS ? LJ::get_cluster_def_reader($u) : LJ::get_cluster_reader($u); + $overr = $db->selectrow_array("SELECT override FROM s1overrides WHERE userid=?", undef, $u->{'userid'}); + + # old global table + } else { + my $dbh = @LJ::MEMCACHE_SERVERS ? LJ::get_db_writer() : LJ::get_db_reader(); + $overr = $dbh->selectrow_array("SELECT override FROM overrides WHERE user=?", undef, $u->{'user'}); + } + + # set in memcache + LJ::MemCache::set($memkey, $overr); + + return $overr; +} + +sub clear_overrides { + my $u = shift; + return unless LJ::isu($u); + + my $overr; + my $db; + + # new clustered table + if ($u->{'dversion'} >= 5) { + $overr = $u->do("DELETE FROM s1overrides WHERE userid=?", undef, $u->{'userid'}); + $db = $u; + + # old global table + } else { + my $dbh = LJ::get_db_writer(); + $overr = $dbh->do("DELETE FROM overrides WHERE user=?", undef, $u->{'user'}); + $db = $dbh; + } + + # update s1usercache + $db->do("UPDATE s1usercache SET override_stor=NULL WHERE userid=?", + undef, $u->{'userid'}); + + LJ::MemCache::delete([$u->{'userid'}, "s1uc:$u->{'userid'}"]); + LJ::MemCache::delete([$u->{'userid'}, "s1overr:$u->{'userid'}"]); + + return $overr; +} + +sub save_overrides { + my ($u, $overr) = @_; + return unless LJ::isu($u) && $overr; + + # new clustered table + my $insertid; + if ($u->{'dversion'} >= 5) { + $u->do("REPLACE INTO s1overrides (userid, override) VALUES (?, ?)", + undef, $u->{'userid'}, $overr); + $insertid = $u->mysql_insertid; + + # old global table + } else { + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO overrides (user, override) VALUES (?, ?)", + undef, $u->{'user'}, $overr); + $insertid = $dbh->{'mysql_insertid'}; + } + + # update s1usercache + my $override_stor = LJ::CleanHTML::clean_s1_style($overr); + $u->do("UPDATE s1usercache SET override_stor=?, override_cleanver=? WHERE userid=?", + undef, $override_stor, $LJ::S1::CLEANER_VERSION, $u->{'userid'}); + + LJ::MemCache::delete([$u->{'userid'}, "s1uc:$u->{'userid'}"]); + LJ::MemCache::delete([$u->{'userid'}, "s1overr:$u->{'userid'}"]); + + return $insertid; +} + +package LJ; + +# +# name: LJ::alldateparts_to_hash +# class: s1 +# des: Given a date/time format from MySQL, breaks it into a hash. +# info: This is used by S1. +# args: alldatepart +# des-alldatepart: The output of the MySQL function +# DATE_FORMAT(sometime, "%a %W %b %M %y %Y %c %m %e %d +# %D %p %i %l %h %k %H") +# returns: Hash (whole, not reference), with keys: dayshort, daylong, +# monshort, monlong, yy, yyyy, m, mm, d, dd, dth, ap, AP, +# ampm, AMPM, min, 12h, 12hh, 24h, 24hh + +# +sub alldateparts_to_hash +{ + my $alldatepart = shift; + my @dateparts = split(/ /, $alldatepart); + return ( + 'dayshort' => $dateparts[0], + 'daylong' => $dateparts[1], + 'monshort' => $dateparts[2], + 'monlong' => $dateparts[3], + 'yy' => $dateparts[4], + 'yyyy' => $dateparts[5], + 'm' => $dateparts[6], + 'mm' => $dateparts[7], + 'd' => $dateparts[8], + 'dd' => $dateparts[9], + 'dth' => $dateparts[10], + 'ap' => substr(lc($dateparts[11]),0,1), + 'AP' => substr(uc($dateparts[11]),0,1), + 'ampm' => lc($dateparts[11]), + 'AMPM' => $dateparts[11], + 'min' => $dateparts[12], + '12h' => $dateparts[13], + '12hh' => $dateparts[14], + '24h' => $dateparts[15], + '24hh' => $dateparts[16], + ); +} + +# +# class: s1 +# name: LJ::fill_var_props +# args: vars, key, hashref +# des: S1 utility function to interpolate %%variables%% in a variable. If +# a modifier is given like %%foo:var%%, then [func[LJ::fvp_transform]] +# is called. +# des-vars: hashref with keys being S1 vars +# des-key: the variable in the vars hashref we're expanding +# des-hashref: hashref of values that could interpolate. +# returns: Expanded string. +# +sub fill_var_props +{ + my ($vars, $key, $hashref) = @_; + $_ = $vars->{$key}; + s/%%([\w:]+:)?([\w\-\']+)%%/$1 ? LJ::fvp_transform(lc($1), $vars, $hashref, $2) : $hashref->{$2}/eg; + return $_; +} + +# +# class: s1 +# name: LJ::fvp_transform +# des: Called from [func[LJ::fill_var_props]] to do trasformations. +# args: transform, vars, hashref, attr +# des-transform: The transformation type. +# des-vars: hashref with keys being S1 vars +# des-hashref: hashref of values that could interpolate. (see +# [func[LJ::fill_var_props]]) +# des-attr: the attribute name that's being interpolated. +# returns: Transformed interpolated variable. +# +sub fvp_transform +{ + my ($transform, $vars, $hashref, $attr) = @_; + my $ret = $hashref->{$attr}; + while ($transform =~ s/(\w+):$//) { + my $trans = $1; + if ($trans eq "color") { + return $vars->{"color-$attr"}; + } + elsif ($trans eq "ue") { + $ret = LJ::eurl($ret); + } + elsif ($trans eq "cons") { + if ($attr eq "img") { return $LJ::IMGPREFIX; } + if ($attr eq "siteroot") { return $LJ::SITEROOT; } + if ($attr eq "sitename") { return $LJ::SITENAME; } + } + elsif ($trans eq "attr") { + $ret =~ s/\"/"/g; + $ret =~ s/\'/&\#39;/g; + $ret =~ s//>/g; + $ret =~ s/\]\]//g; # so they can't end the parent's [attr[..]] wrapper + } + elsif ($trans eq "lc") { + $ret = lc($ret); + } + elsif ($trans eq "uc") { + $ret = uc($ret); + } + elsif ($trans eq "xe") { + $ret = LJ::exml($ret); + } + elsif ($trans eq 'ljuser' or $trans eq 'ljcomm') { + my $user = LJ::canonical_username($ret); + $ret = LJ::ljuser($user); + } + elsif ($trans eq 'userurl') { + my $u = LJ::load_user($ret); + $ret = LJ::journal_base($u) if $u; + } + } + return $ret; +} + +# +# class: s1 +# name: LJ::parse_vars +# des: Parses S1 style data into hashref. +# returns: Nothing. Modifies a hashref. +# args: dataref, hashref +# des-dataref: Reference to scalar with data to parse. Format is +# a BML-style full block, as used in the S1 style system. +# des-hashref: Hashref to populate with data. +# +sub parse_vars +{ + my ($dataref, $hashref) = @_; + my @data = split(/\n/, $$dataref); + my $curitem = ""; + + foreach (@data) + { + $_ .= "\n"; + s/\r//g; + if ($curitem eq "" && /^([A-Z0-9\_]+)=>([^\n\r]*)/) + { + $hashref->{$1} = $2; + } + elsif ($curitem eq "" && /^([A-Z0-9\_]+)<=\s*$/) + { + $curitem = $1; + $hashref->{$curitem} = ""; + } + elsif ($curitem && /^<=$curitem\s*$/) + { + chop $hashref->{$curitem}; # remove the false newline + $curitem = ""; + } + else + { + $hashref->{$curitem} .= $_ if ($curitem =~ /\S/); + } + } +} + +sub current_mood_str { + my ($themeid, $moodid, $mood) = @_; + + # ideal behavior: if there is a moodid, that defines the picture. + # if there is a current_mood, that overrides as the mood name, + # otherwise show the mood name associated with current_moodid + + my $moodname; + my $moodpic; + + # favor custom mood over system mood + if (my $val = $mood) { + LJ::CleanHTML::clean_subject(\$val); + $moodname = $val; + } + + if (my $val = $moodid) { + $moodname ||= LJ::mood_name($val); + my %pic; + if (LJ::get_mood_picture($themeid, $val, \%pic)) { + $moodpic = " "; + } + } + + return "$moodpic$moodname"; +} + +sub current_music_str { + my $val = shift; + + LJ::CleanHTML::clean_subject(\$val); + return $val; +} + +# +# class: s1 +# name: LJ::prepare_currents +# des: do all the current music/mood/weather/whatever stuff. only used by ljviews.pl. +# args: dbarg, args +# des-args: hashref with keys: 'props' (a hashref with itemid keys), 'vars' hashref with +# keys being S1 variables. +# +sub prepare_currents +{ + my $args = shift; + + my $datakey = $args->{'datakey'} || $args->{'itemid'}; # new || old + + my %currents = (); + my $val; + if ($val = $args->{'props'}->{$datakey}->{'current_music'}) { + $currents{'Music'} = LJ::current_music_str($val); + } + + $currents{'Mood'} = LJ::current_mood_str($args->{'user'}->{'moodthemeid'}, + $args->{'props'}->{$datakey}->{'current_moodid'}, + $args->{'props'}->{$datakey}->{'current_mood'}); + delete $currents{'Mood'} unless $currents{'Mood'}; + + if (%currents) { + if ($args->{'vars'}->{$args->{'prefix'}.'_CURRENTS'}) + { + ### PREFIX_CURRENTS is defined, so use the correct style vars + + my $fvp = { 'currents' => "" }; + foreach (sort keys %currents) { + $fvp->{'currents'} .= LJ::fill_var_props($args->{'vars'}, $args->{'prefix'}.'_CURRENT', { + 'what' => $_, + 'value' => $currents{$_}, + }); + } + $args->{'event'}->{'currents'} = + LJ::fill_var_props($args->{'vars'}, $args->{'prefix'}.'_CURRENTS', $fvp); + } else + { + ### PREFIX_CURRENTS is not defined, so just add to %%events%% + $args->{'event'}->{'event'} .= "
     "; + foreach (sort keys %currents) { + $args->{'event'}->{'event'} .= "
    Current $_: " . $currents{$_} . "\n"; + } + } + } +} + + +package LJ::S1; +use strict; +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; +require "$ENV{'LJHOME'}/cgi-bin/cleanhtml.pl"; + +# the creator for the 'lastn' view: +sub create_view_lastn +{ + my ($ret, $u, $vars, $remote, $opts) = @_; + + my $user = $u->{'user'}; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}); + return 1; + } + + foreach ("name", "url", "urlname", "journaltitle") { LJ::text_out(\$u->{$_}); } + + my $get = $opts->{'getargs'}; + + if ($opts->{'pathextra'}) { + $opts->{'badargs'} = 1; + return 1; + } + + LJ::load_user_props($remote, "opt_ljcut_disable_lastn"); + + my %lastn_page = (); + $lastn_page{'name'} = LJ::ehtml($u->{'name'}); + $lastn_page{'name-\'s'} = ($u->{'name'} =~ /s$/i) ? "'" : "'s"; + $lastn_page{'username'} = $user; + $lastn_page{'title'} = LJ::ehtml($u->{'journaltitle'} || + $u->{'name'} . $lastn_page{'name-\'s'} . " Journal"); + $lastn_page{'numitems'} = $vars->{'LASTN_OPT_ITEMS'} || 20; + + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + $lastn_page{'urlfriends'} = "$journalbase/friends"; + $lastn_page{'urlcalendar'} = "$journalbase/calendar"; + + if ($u->{'url'} =~ m!^https?://!) { + $lastn_page{'website'} = + LJ::fill_var_props($vars, 'LASTN_WEBSITE', { + "url" => LJ::ehtml($u->{'url'}), + "name" => LJ::ehtml($u->{'urlname'} || "My Website"), + }); + } + + $lastn_page{'events'} = ""; + $lastn_page{'head'} = ""; + + if (LJ::are_hooks('s2_head_content_extra')) { + $lastn_page{'head'} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + # if user has requested, or a skip back link has been followed, don't index or follow + if ($u->{'opt_blockrobots'} || $get->{'skip'}) { + $lastn_page{'head'} .= LJ::robot_meta_tags() + } + if ($LJ::UNICODE) { + $lastn_page{'head'} .= '\n"; + } + + # Automatic Discovery of RSS/Atom + $lastn_page{'head'} .= qq{\n}; + $lastn_page{'head'} .= qq{\n}; + $lastn_page{'head'} .= qq{\n}; + $lastn_page{'head'} .= qq{\n}; + $lastn_page{'head'} .= qq{\n} + if LJ::OpenID::server_enabled(); + + # FOAF autodiscovery + my $foafurl = $u->{external_foaf_url} ? LJ::eurl($u->{external_foaf_url}) : "$journalbase/data/foaf"; + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{email}); + $lastn_page{head} .= qq{\n}; + $lastn_page{head} .= qq{\n}; + + $lastn_page{'head'} .= + $vars->{'GLOBAL_HEAD'} . "\n" . $vars->{'LASTN_HEAD'}; + + my $events = \$lastn_page{'events'}; + + # to show + my $itemshow = $vars->{'LASTN_OPT_ITEMS'} + 0; + if ($itemshow < 1) { $itemshow = 20; } + if ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = $LJ::MAX_HINTS_LASTN-$itemshow; + if ($skip < 0) { $skip = 0; } + if ($skip > $maxskip) { $skip = $maxskip; } + + # do they have the viewall priv? + my $viewall = 0; + my $viewsome = 0; + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "lastn: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + ## load the itemids + my @itemids; + my $err; + my @items = LJ::get_recent_items({ + 'clusterid' => $u->{'clusterid'}, + 'clustersource' => 'slave', + 'viewall' => $viewall, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'itemids' => \@itemids, + 'order' => ($u->{'journaltype'} eq "C" || $u->{'journaltype'} eq "Y") # community or syndicated + ? "logtime" : "", + 'err' => \$err, + }); + + if ($err) { + $opts->{'errcode'} = $err; + $$ret = ""; + return 0; + } + + ### load the log properties + my %logprops = (); + my $logtext; + LJ::load_log_props2($u->{'userid'}, \@itemids, \%logprops); + $logtext = LJ::get_logtext2($u, @itemids); + + my $lastday = -1; + my $lastmonth = -1; + my $lastyear = -1; + my $eventnum = 0; + + my %posteru = (); # map posterids to u objects + LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } + @items], [$u]); + + # pre load things in a batch (like userpics) to minimize db calls + my @userpic_load; + push @userpic_load, [ $u, $u->{'defaultpicid'} ] if $u->{'defaultpicid'}; + foreach my $item (@items) { + next if $item->{'posterid'} == $u->{'userid'}; + my $itemid = $item->{'itemid'}; + my $pu = $posteru{$item->{'posterid'}}; + + my $picid = LJ::get_picid_from_keyword($pu, $logprops{$itemid}->{'picture_keyword'}); + $item->{'_picid'} = $picid; + push @userpic_load, [ $pu, $picid ] if ($picid && ! grep { $_ eq $picid } @userpic_load); + } + my %userpics; + LJ::load_userpics(\%userpics, \@userpic_load); + + if (my $picid = $u->{'defaultpicid'}) { + $lastn_page{'userpic'} = + LJ::fill_var_props($vars, 'LASTN_USERPIC', { + "src" => "$LJ::USERPIC_ROOT/$picid/$u->{'userid'}", + "width" => $userpics{$picid}->{'width'}, + "height" => $userpics{$picid}->{'height'}, + }); + } + + # spit out the S1 + + ENTRY: + foreach my $item (@items) + { + my ($posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(posterid itemid security alldatepart); + + my $pu = $posteru{$posterid}; + next ENTRY if $pu && $pu->{'statusvis'} eq 'S' && !$viewsome; + + my $replycount = $logprops{$itemid}->{'replycount'}; + my $subject = $logtext->{$itemid}->[0]; + my $event = $logtext->{$itemid}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $event =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$subject, \$event, $logprops{$itemid}); + } + + my %lastn_date_format = LJ::alldateparts_to_hash($alldatepart); + + if ($lastday != $lastn_date_format{'d'} || + $lastmonth != $lastn_date_format{'m'} || + $lastyear != $lastn_date_format{'yyyy'}) + { + my %lastn_new_day = (); + foreach (qw(dayshort daylong monshort monlong m mm yy yyyy d dd dth)) + { + $lastn_new_day{$_} = $lastn_date_format{$_}; + } + unless ($lastday==-1) { + $$events .= LJ::fill_var_props($vars, 'LASTN_END_DAY', {}); + } + $$events .= LJ::fill_var_props($vars, 'LASTN_NEW_DAY', \%lastn_new_day); + + $lastday = $lastn_date_format{'d'}; + $lastmonth = $lastn_date_format{'m'}; + $lastyear = $lastn_date_format{'yyyy'}; + } + + my %lastn_event = (); + $eventnum++; + $lastn_event{'eventnum'} = $eventnum; + $lastn_event{'itemid'} = $itemid; + $lastn_event{'datetime'} = LJ::fill_var_props($vars, 'LASTN_DATE_FORMAT', \%lastn_date_format); + if ($subject ne "") { + LJ::CleanHTML::clean_subject(\$subject); + $lastn_event{'subject'} = LJ::fill_var_props($vars, 'LASTN_SUBJECT', { + "subject" => $subject, + }); + } + + my $ditemid = $itemid * 256 + $item->{'anum'}; + my $itemargs = "journal=$user&itemid=$ditemid"; + $lastn_event{'itemargs'} = $itemargs; + + LJ::CleanHTML::clean_event(\$event, { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $item->{'anum'}), + 'ljcut_disable' => $remote->{'opt_ljcut_disable_lastn'}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$event); + $lastn_event{'event'} = $event; + + if ($u->{'opt_showtalklinks'} eq "Y" && + ! $logprops{$itemid}->{'opt_nocomments'} + ) + { + + my $nc; + $nc = "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply"); + my $readurl = LJ::Talk::talkargs($permalink, $nc); + + my $dispreadlink = $replycount || + ($logprops{$itemid}->{'hasscreened'} && + ($remote->{'user'} eq $user + || LJ::can_manage($remote, $u))); + + $lastn_event{'talklinks'} = LJ::fill_var_props($vars, 'LASTN_TALK_LINKS', { + 'itemid' => $ditemid, + 'itemargs' => $itemargs, + 'urlpost' => $posturl, + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'readlink' => $dispreadlink ? LJ::fill_var_props($vars, 'LASTN_TALK_READLINK', { + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'mc-plural-s' => $replycount == 1 ? "" : "s", + 'mc-plural-es' => $replycount == 1 ? "" : "es", + 'mc-plural-ies' => $replycount == 1 ? "y" : "ies", + }) : "", + }); + } + + ## current stuff + LJ::prepare_currents({ + 'props' => \%logprops, + 'itemid' => $itemid, + 'vars' => $vars, + 'prefix' => "LASTN", + 'event' => \%lastn_event, + 'user' => $u, + }); + + if ($u->{'userid'} != $posterid) + { + my %lastn_altposter = (); + + my $poster = $pu->{'user'}; + $lastn_altposter{'poster'} = $poster; + $lastn_altposter{'owner'} = $user; + + if (my $picid = $item->{'_picid'}) { + my $pic = $userpics{$picid}; + $lastn_altposter{'pic'} = LJ::fill_var_props($vars, 'LASTN_ALTPOSTER_PIC', { + "src" => "$LJ::USERPIC_ROOT/$picid/$pic->{'userid'}", + "width" => $pic->{'width'}, + "height" => $pic->{'height'}, + }); + } + $lastn_event{'altposter'} = + LJ::fill_var_props($vars, 'LASTN_ALTPOSTER', \%lastn_altposter); + } + + my $var = 'LASTN_EVENT'; + if ($security eq "private" && + $vars->{'LASTN_EVENT_PRIVATE'}) { $var = 'LASTN_EVENT_PRIVATE'; } + if ($security eq "usemask" && + $vars->{'LASTN_EVENT_PROTECTED'}) { $var = 'LASTN_EVENT_PROTECTED'; } + $$events .= LJ::fill_var_props($vars, $var, \%lastn_event); + } # end huge while loop + + $$events .= LJ::fill_var_props($vars, 'LASTN_END_DAY', {}); + + my $item_shown = $eventnum; + my $item_total = @items; + my $item_hidden = $item_total - $item_shown; + + if ($skip) { + $lastn_page{'range'} = + LJ::fill_var_props($vars, 'LASTN_RANGE_HISTORY', { + "numitems" => $item_shown, + "skip" => $skip, + }); + } else { + $lastn_page{'range'} = + LJ::fill_var_props($vars, 'LASTN_RANGE_MOSTRECENT', { + "numitems" => $item_shown, + }); + } + + #### make the skip links + my ($skip_f, $skip_b) = (0, 0); + my %skiplinks; + + ### if we've skipped down, then we can skip back up + + if ($skip) { + $skip_f = 1; + my $newskip = $skip - $itemshow; + if ($newskip <= 0) { $newskip = ""; } + else { $newskip = "?skip=$newskip"; } + + $skiplinks{'skipforward'} = + LJ::fill_var_props($vars, 'LASTN_SKIP_FORWARD', { + "numitems" => $itemshow, + "url" => "$journalbase/$newskip", + }); + } + + ## unless we didn't even load as many as we were expecting on this + ## page, then there are more (unless there are exactly the number shown + ## on the page, but who cares about that) + + unless ($item_total != $itemshow) { + $skip_b = 1; + + if ($skip==$maxskip) { + $skiplinks{'skipbackward'} = + LJ::fill_var_props($vars, 'LASTN_SKIP_BACKWARD', { + "numitems" => "Day", + "url" => "$journalbase/" . sprintf("%04d/%02d/%02d/", $lastyear, $lastmonth, $lastday), + }); + } else { + my $newskip = $skip + $itemshow; + $newskip = "?skip=$newskip"; + $skiplinks{'skipbackward'} = + LJ::fill_var_props($vars, 'LASTN_SKIP_BACKWARD', { + "numitems" => $itemshow, + "url" => "$journalbase/$newskip", + }); + } + } + + ### if they're both on, show a spacer + if ($skip_b && $skip_f) { + $skiplinks{'skipspacer'} = $vars->{'LASTN_SKIP_SPACER'}; + } + + ### if either are on, put skiplinks into lastn_page + if ($skip_b || $skip_f) { + $lastn_page{'skiplinks'} = + LJ::fill_var_props($vars, 'LASTN_SKIP_LINKS', \%skiplinks); + } + + $$ret = LJ::fill_var_props($vars, 'LASTN_PAGE', \%lastn_page); + + return 1; +} + +# the creator for the 'friends' view: +sub create_view_friends +{ + my ($ret, $u, $vars, $remote, $opts) = @_; + my $sth; + my $user = $u->{'user'}; + + # see how often the remote user can reload this page. + # "friendsviewupdate" time determines what granularity time + # increments by for checking for new updates + my $nowtime = time(); + + # update delay specified by "friendsviewupdate" + my $newinterval = LJ::get_cap_min($remote, "friendsviewupdate") || 1; + + # when are we going to say page was last modified? back up to the + # most recent time in the past where $time % $interval == 0 + my $lastmod = $nowtime; + $lastmod -= $lastmod % $newinterval; + + # see if they have a previously cached copy of this page they + # might be able to still use. + if ($opts->{'header'}->{'If-Modified-Since'}) { + my $theirtime = LJ::http_to_time($opts->{'header'}->{'If-Modified-Since'}); + + # send back a 304 Not Modified if they say they've reloaded this + # document in the last $newinterval seconds: + unless ($theirtime < $lastmod) { + $opts->{'handler_return'} = 304; + return 1; + } + } + $opts->{'headers'}->{'Last-Modified'} = LJ::time_to_http($lastmod); + + $$ret = ""; + + my $get = $opts->{'getargs'}; + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + if ($get->{'mode'} eq "live") { + $$ret .= "${user}'s friends: live!\n"; + $$ret .= "\n"; + $$ret .= " \n"; + $$ret .= " \n"; + $$ret .= "\n"; + return 1; + } + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . "/friends"; + return 1; + } + + foreach ("name", "url", "urlname", "friendspagetitle") { LJ::text_out(\$u->{$_}); } + + my %friends_page = (); + $friends_page{'name'} = LJ::ehtml($u->{'name'}); + $friends_page{'name-\'s'} = ($u->{'name'} =~ /s$/i) ? "'" : "'s"; + $friends_page{'username'} = $user; + $friends_page{'title'} = LJ::ehtml($u->{'friendspagetitle'} || + $u->{'name'} . $friends_page{'name-\'s'} . " Friends"); + $friends_page{'numitems'} = $vars->{'FRIENDS_OPT_ITEMS'} || 20; + + $friends_page{'head'} = ""; + + if (LJ::are_hooks('s2_head_content_extra')) { + $friends_page{'head'} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + ## never have spiders index friends pages (change too much, and some + ## people might not want to be indexed) + $friends_page{'head'} .= LJ::robot_meta_tags(); + if ($LJ::UNICODE) { + $friends_page{'head'} .= ''; + } + $friends_page{'head'} .= + $vars->{'GLOBAL_HEAD'} . "\n" . $vars->{'FRIENDS_HEAD'}; + + if ($u->{'url'} =~ m!^https?://!) { + $friends_page{'website'} = + LJ::fill_var_props($vars, 'FRIENDS_WEBSITE', { + "url" => LJ::ehtml($u->{'url'}), + "name" => LJ::ehtml($u->{'urlname'} || "My Website"), + }); + } + + $friends_page{'urlcalendar'} = "$journalbase/calendar"; + $friends_page{'urllastn'} = "$journalbase/"; + + $friends_page{'events'} = ""; + + my $itemshow = $vars->{'FRIENDS_OPT_ITEMS'} + 0; + if ($itemshow < 1) { $itemshow = 20; } + if ($itemshow > 50) { $itemshow = 50; } + + my $skip = $get->{'skip'}+0; + my $maxskip = ($LJ::MAX_SCROLLBACK_FRIENDS || 1000) - $itemshow; + if ($skip > $maxskip) { $skip = $maxskip; } + if ($skip < 0) { $skip = 0; } + my $itemload = $itemshow+$skip; + + my $filter; + my $group; + my $common_filter = 1; + + if (defined $get->{'filter'} && $remote && $remote->{'user'} eq $user) { + $filter = $get->{'filter'}; + $common_filter = 0; + } else { + if ($opts->{'pathextra'}) { + $group = $opts->{'pathextra'}; + $group =~ s!^/!!; + $group =~ s!/$!!; + if ($group) { $group = LJ::durl($group); $common_filter = 0;} + } + my $grp = LJ::get_friend_group($u, { 'name' => $group || "Default View" }); + my $bit = $grp ? $grp->{'groupnum'} : 0; + my $public = $grp ? $grp->{'is_public'} : 0; + if ($bit && ($public || ($remote && $remote->{'user'} eq $user))) { + $filter = (1 << $bit); + } elsif ($group) { + $opts->{'badfriendgroup'} = 1; + return 1; + } + } + + + if ($get->{'mode'} eq "livecond") + { + ## load the itemids + my @items = LJ::get_friend_items({ + 'u' => $u, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => 1, + 'skip' => 0, + 'filter' => $filter, + 'common_filter' => $common_filter, + }); + my $first = @items ? $items[0]->{'itemid'} : 0; + + $$ret .= "time = " . scalar(time()) . "
    "; + $opts->{'headers'}->{'Refresh'} = "30;URL=$LJ::SITEROOT/users/$user/friends?mode=livecond&lastitemid=$first"; + if ($get->{'lastitemid'} == $first) { + $$ret .= "nothing new!"; + } else { + if ($get->{'lastitemid'}) { + $$ret .= "New stuff!\n"; + $$ret .= "\n"; + $opts->{'trusted_html'} = 1; + } else { + $$ret .= "Friends Live! started."; + } + } + return 1; + } + + ## load the itemids + my %friends; + my %friends_row; + my %idsbycluster; + my @items = LJ::get_friend_items({ + 'u' => $u, + 'userid' => $u->{'userid'}, + 'remote' => $remote, + 'itemshow' => $itemshow, + 'skip' => $skip, + 'filter' => $filter, + 'common_filter' => $common_filter, + 'friends_u' => \%friends, + 'friends' => \%friends_row, + 'idsbycluster' => \%idsbycluster, + 'showtypes' => $get->{'show'}, + 'friendsoffriends' => $opts->{'view'} eq "friendsfriends", + }); + + while ($_ = each %friends) { + # we expect fgcolor/bgcolor to be in here later + $friends{$_}->{'fgcolor'} = $friends_row{$_}->{'fgcolor'} || '#000000'; + $friends{$_}->{'bgcolor'} = $friends_row{$_}->{'bgcolor'} || '#ffffff'; + } + + unless (%friends) + { + $friends_page{'events'} = LJ::fill_var_props($vars, 'FRIENDS_NOFRIENDS', { + "name" => LJ::ehtml($u->{'name'}), + "name-\'s" => ($u->{'name'} =~ /s$/i) ? "'" : "'s", + "username" => $user, + }); + + $$ret .= "" if ($get->{'mode'} eq "framed"); + $$ret .= LJ::fill_var_props($vars, 'FRIENDS_PAGE', \%friends_page); + return 1; + } + + my %aposter; # alt-posterid -> u object (if not in friends already) + LJ::load_userids_multiple([map { $_->{'posterid'}, \$aposter{$_->{'posterid'}} } + grep { $friends{$_->{'ownerid'}} && + ! $friends{$_->{'posterid'}} } @items], + [ $u, $remote ]); + + ### load the log properties + my %logprops = (); # key is "$owneridOrZero $[j]itemid" + LJ::load_log_props2multi(\%idsbycluster, \%logprops); + + # load the pictures for the user + my %userpics; + my @picids = map { [$friends{$_}, $friends{$_}->{'defaultpicid'}] } keys %friends; + LJ::load_userpics(\%userpics, [ @picids, map { [ $_, $_->{'defaultpicid'} ] } values %aposter ]); + + # load the text of the entries + my $logtext = LJ::get_logtext2multi(\%idsbycluster); + + # load 'opt_stylemine' prop for $remote. don't need to load opt_nctalklinks + # because that was already faked in LJ::make_journal previously + LJ::load_user_props($remote, "opt_stylemine", "opt_imagelinks", "opt_ljcut_disable_friends"); + + # load options for image links + my ($maximgwidth, $maximgheight) = (undef, undef); + ($maximgwidth, $maximgheight) = ($1, $2) + if ($remote && $remote->{'userid'} == $u->{'userid'} && + $remote->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/); + + my %friends_events = (); + my $events = \$friends_events{'events'}; + + my $lastday = -1; + my $eventnum = 0; + + ENTRY: + foreach my $item (@items) + { + my ($friendid, $posterid, $itemid, $security, $alldatepart) = + map { $item->{$_} } qw(ownerid posterid itemid security alldatepart); + + my $pu = $friends{$posterid} || $aposter{$posterid}; + next ENTRY if $pu && $pu->{'statusvis'} eq 'S'; + + # counting excludes skipped entries + $eventnum++; + + my $clusterid = $item->{'clusterid'}+0; + + my $datakey = "$friendid $itemid"; + + my $replycount = $logprops{$datakey}->{'replycount'}; + my $subject = $logtext->{$datakey}->[0]; + my $event = $logtext->{$datakey}->[1]; + if ($get->{'nohtml'}) { + # quote all non-LJ tags + $subject =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + $event =~ s{<(?!/?lj)(.*?)>} {<$1>}gi; + } + + if ($LJ::UNICODE && $logprops{$datakey}->{'unknown8bit'}) { + LJ::item_toutf8($friends{$friendid}, \$subject, \$event, $logprops{$datakey}); + } + + my ($friend, $poster); + $friend = $poster = $friends{$friendid}->{'user'}; + $poster = $pu->{'user'}; + + my %friends_date_format = LJ::alldateparts_to_hash($alldatepart); + + if ($lastday != $friends_date_format{'d'}) + { + my %friends_new_day = (); + foreach (qw(dayshort daylong monshort monlong m mm yy yyyy d dd dth)) + { + $friends_new_day{$_} = $friends_date_format{$_}; + } + unless ($lastday==-1) { + $$events .= LJ::fill_var_props($vars, 'FRIENDS_END_DAY', {}); + } + $$events .= LJ::fill_var_props($vars, 'FRIENDS_NEW_DAY', \%friends_new_day); + $lastday = $friends_date_format{'d'}; + } + + my %friends_event = (); + $friends_event{'itemid'} = $itemid; + $friends_event{'datetime'} = LJ::fill_var_props($vars, 'FRIENDS_DATE_FORMAT', \%friends_date_format); + if ($subject ne "") { + LJ::CleanHTML::clean_subject(\$subject); + $friends_event{'subject'} = LJ::fill_var_props($vars, 'FRIENDS_SUBJECT', { + "subject" => $subject, + }); + } else { + $friends_event{'subject'} = LJ::fill_var_props($vars, 'FRIENDS_NO_SUBJECT', { + "friend" => $friend, + "name" => $friends{$friendid}->{'name'}, + }); + } + + my $ditemid = $itemid * 256 + $item->{'anum'}; + my $itemargs = "journal=$friend&itemid=$ditemid"; + $friends_event{'itemargs'} = $itemargs; + + my $stylemine = ""; + $stylemine .= "style=mine" if $remote && $remote->{'opt_stylemine'} && + $remote->{'userid'} != $friendid; + + LJ::CleanHTML::clean_event(\$event, { 'preformatted' => $logprops{$datakey}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($friends{$friendid}, $itemid, $item->{'anum'}, $stylemine), + 'maximgwidth' => $maximgwidth, + 'maximgheight' => $maximgheight, + 'ljcut_disable' => $remote->{'opt_ljcut_disable_friends'}, }); + LJ::expand_embedded($friends{$friendid}, $ditemid, $remote, \$event); + $friends_event{'event'} = $event; + + # do the picture + { + my $picid = $friends{$friendid}->{'defaultpicid'}; # this could be the shared journal pic + my $picuserid = $friendid; + if ($friendid != $posterid && ! $u->{'opt_usesharedpic'}) { + if ($pu->{'defaultpicid'}) { + $picid = $pu->{'defaultpicid'}; + $picuserid = $posterid; + } + } + if ($logprops{$datakey}->{'picture_keyword'} && + (! $u->{'opt_usesharedpic'} || ($posterid == $friendid))) + { + my $alt_picid = LJ::get_picid_from_keyword($posterid, $logprops{$datakey}->{'picture_keyword'}); + if ($alt_picid) { + LJ::load_userpics(\%userpics, [ $pu, $alt_picid ]); + $picid = $alt_picid; + $picuserid = $posterid; + } + } + if ($picid) { + $friends_event{'friendpic'} = + LJ::fill_var_props($vars, 'FRIENDS_FRIENDPIC', { + "src" => "$LJ::USERPIC_ROOT/$picid/$picuserid", + "width" => $userpics{$picid}->{'width'}, + "height" => $userpics{$picid}->{'height'}, + }); + } + } + + if ($friend ne $poster) { + $friends_event{'altposter'} = + LJ::fill_var_props($vars, 'FRIENDS_ALTPOSTER', { + "poster" => $poster, + "owner" => $friend, + "fgcolor" => $friends{$friendid}->{'fgcolor'} || "#000000", + "bgcolor" => $friends{$friendid}->{'bgcolor'} || "#ffffff", + }); + } + + # friends view specific: + $friends_event{'user'} = $friend; + $friends_event{'fgcolor'} = $friends{$friendid}->{'fgcolor'} || "#000000"; + $friends_event{'bgcolor'} = $friends{$friendid}->{'bgcolor'} || "#ffffff"; + + if ($friends{$friendid}->{'opt_showtalklinks'} eq "Y" && + ! $logprops{$datakey}->{'opt_nocomments'} + ) + { + my $dispreadlink = $replycount || + ($logprops{$datakey}->{'hasscreened'} && + ($remote->{'user'} eq $friend + || LJ::can_manage($remote, $friendid))); + + my $journalbase = LJ::journal_base($friends{$friendid}); + + my $nc = ""; + $nc .= "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $readurl = LJ::Talk::talkargs($permalink, $nc, $stylemine); + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply", $stylemine); + + $friends_event{'talklinks'} = LJ::fill_var_props($vars, 'FRIENDS_TALK_LINKS', { + 'itemid' => $ditemid, + 'itemargs' => $itemargs, + 'urlpost' => $posturl, + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'readlink' => $dispreadlink ? LJ::fill_var_props($vars, 'FRIENDS_TALK_READLINK', { + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'mc-plural-s' => $replycount == 1 ? "" : "s", + 'mc-plural-es' => $replycount == 1 ? "" : "es", + 'mc-plural-ies' => $replycount == 1 ? "y" : "ies", + }) : "", + }); + } + + ## current stuff + LJ::prepare_currents({ + 'props' => \%logprops, + 'datakey' => $datakey, + 'vars' => $vars, + 'prefix' => "FRIENDS", + 'event' => \%friends_event, + 'user' => ($u->{'opt_forcemoodtheme'} eq "Y" ? $u : + $friends{$friendid}), + }); + + my $var = 'FRIENDS_EVENT'; + if ($security eq "private" && + $vars->{'FRIENDS_EVENT_PRIVATE'}) { $var = 'FRIENDS_EVENT_PRIVATE'; } + if ($security eq "usemask" && + $vars->{'FRIENDS_EVENT_PROTECTED'}) { $var = 'FRIENDS_EVENT_PROTECTED'; } + + $$events .= LJ::fill_var_props($vars, $var, \%friends_event); + } # end while + + $$events .= LJ::fill_var_props($vars, 'FRIENDS_END_DAY', {}); + $friends_page{'events'} = LJ::fill_var_props($vars, 'FRIENDS_EVENTS', \%friends_events); + + my $item_shown = $eventnum; + my $item_total = @items; + my $item_hidden = $item_total - $item_shown; + + ### set the range property (what entries are we looking at) + + if ($skip) { + $friends_page{'range'} = + LJ::fill_var_props($vars, 'FRIENDS_RANGE_HISTORY', { + "numitems" => $item_shown, + "skip" => $skip, + }); + } else { + $friends_page{'range'} = + LJ::fill_var_props($vars, 'FRIENDS_RANGE_MOSTRECENT', { + "numitems" => $item_shown, + }); + } + + my ($skip_f, $skip_b) = (0, 0); + my %skiplinks; + my $base = "$journalbase/$opts->{'view'}"; + if ($group) { + $base .= "/" . LJ::eurl($group); + } + + # $linkfilter is distinct from $filter: if user has a default view, + # $filter is now set according to it but we don't want it to show in the links. + # $incfilter may be true even if $filter is 0: user may use filter=0 to turn + # off the default group + my $linkfilter = $get->{'filter'} + 0; + my $incfilter = defined $get->{'filter'}; + + # if we've skipped down, then we can skip back up + if ($skip) { + $skip_f = 1; + my %linkvars; + + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + + my $newskip = $skip - $itemshow; + if ($newskip > 0) { $linkvars{'skip'} = $newskip; } + + $skiplinks{'skipforward'} = + LJ::fill_var_props($vars, 'FRIENDS_SKIP_FORWARD', { + "numitems" => $itemshow, + "url" => LJ::make_link($base, \%linkvars), + }); + } + + ## unless we didn't even load as many as we were expecting on this + ## page, then there are more (unless there are exactly the number shown + ## on the page, but who cares about that) + + unless ($item_total != $itemshow || $skip == $maxskip) { + $skip_b = 1; + my %linkvars; + + $linkvars{'filter'} = $linkfilter if $incfilter; + $linkvars{'show'} = $get->{'show'} if $get->{'show'} =~ /^\w+$/; + + my $newskip = $skip + $itemshow; + $linkvars{'skip'} = $newskip; + + $skiplinks{'skipbackward'} = + LJ::fill_var_props($vars, 'FRIENDS_SKIP_BACKWARD', { + "numitems" => $itemshow, + "url" => LJ::make_link($base, \%linkvars), + }); + } + + ### if they're both on, show a spacer + if ($skip_f && $skip_b) { + $skiplinks{'skipspacer'} = $vars->{'FRIENDS_SKIP_SPACER'}; + } + + ### if either are on, put skiplinks into lastn_page + if ($skip_b || $skip_f) { + $friends_page{'skiplinks'} = + LJ::fill_var_props($vars, 'FRIENDS_SKIP_LINKS', \%skiplinks); + } + + $$ret .= "" if ($get->{'mode'} eq "framed"); + $$ret .= LJ::fill_var_props($vars, 'FRIENDS_PAGE', \%friends_page); + + return 1; +} + +# the creator for the 'calendar' view: +sub create_view_calendar +{ + my ($ret, $u, $vars, $remote, $opts) = @_; + + my $user = $u->{'user'}; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/calendar" . $opts->{'pathextra'}; + return 1; + } + + foreach ("name", "url", "urlname", "journaltitle") { LJ::text_out(\$u->{$_}); } + + my $get = $opts->{'getargs'}; + + my %calendar_page = (); + $calendar_page{'name'} = LJ::ehtml($u->{'name'}); + $calendar_page{'name-\'s'} = ($u->{'name'} =~ /s$/i) ? "'" : "'s"; + $calendar_page{'username'} = $user; + $calendar_page{'title'} = LJ::ehtml($u->{'journaltitle'} || + $u->{'name'} . $calendar_page{'name-\'s'} . " Journal"); + + $calendar_page{'head'} = ""; + + if (LJ::are_hooks('s2_head_content_extra')) { + $calendar_page{'head'} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + if ($u->{'opt_blockrobots'}) { + $calendar_page{'head'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $calendar_page{'head'} .= ''; + } + $calendar_page{'head'} .= + $vars->{'GLOBAL_HEAD'} . "\n" . $vars->{'CALENDAR_HEAD'}; + + $calendar_page{'months'} = ""; + + if ($u->{'url'} =~ m!^https?://!) { + $calendar_page{'website'} = + LJ::fill_var_props($vars, 'CALENDAR_WEBSITE', { + "url" => LJ::ehtml($u->{'url'}), + "name" => LJ::ehtml($u->{'urlname'} || "My Website"), + }); + } + + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + + $calendar_page{'urlfriends'} = "$journalbase/friends"; + $calendar_page{'urllastn'} = "$journalbase/"; + + my $months = \$calendar_page{'months'}; + + my $quserid = int($u->{'userid'}); + my $maxyear = 0; + + my $daycts = LJ::get_daycounts($u, $remote); + unless ($daycts) { + $opts->{'errcode'} = "nodb"; + $$ret = ""; + return 0; + } + + my (%count, %dayweek); + foreach my $dy (@$daycts) { + my ($year, $month, $day, $count) = @$dy; + + # calculate day of week + my $time = eval { Time::Local::timegm(0, 0, 0, $day, $month-1, $year) } || + eval { Time::Local::timegm(0, 0, 0, LJ::days_in_month($month, $year), $month-1, $year) } || + 0; + next unless $time; + + my $dayweek = (gmtime($time))[6] + 1; + + $count{$year}->{$month}->{$day} = $count; + $dayweek{$year}->{$month}->{$day} = $dayweek; + if ($year > $maxyear) { $maxyear = $year; } + } + + my @allyears = sort { $b <=> $a } keys %count; + if ($vars->{'CALENDAR_SORT_MODE'} eq "forward") { @allyears = reverse @allyears; } + + my @years = (); + my $dispyear = $get->{'year'}; # old form was /users//calendar?year=1999 + + # but the new form is purtier: */calendar/2001 + # but the NEWER form is purtier: */2001 + unless ($dispyear) { + if ($opts->{'pathextra'} =~ m!^/(\d\d\d\d)/?\b!) { + $dispyear = $1; + } + } + + # else... default to the year they last posted. + $dispyear ||= $maxyear; + + # we used to show multiple years. now we only show one at a time: (hence the @years confusion) + if ($dispyear) { push @years, $dispyear; } + + if (scalar(@allyears) > 1) { + my $yearlinks = ""; + foreach my $year (@allyears) { + my $yy = sprintf("%02d", $year % 100); + my $url = "$journalbase/$year/"; + if ($year != $dispyear) { + $yearlinks .= LJ::fill_var_props($vars, 'CALENDAR_YEAR_LINK', { + "url" => $url, "yyyy" => $year, "yy" => $yy }); + } else { + $yearlinks .= LJ::fill_var_props($vars, 'CALENDAR_YEAR_DISPLAYED', { + "yyyy" => $year, "yy" => $yy }); + } + } + $calendar_page{'yearlinks'} = + LJ::fill_var_props($vars, 'CALENDAR_YEAR_LINKS', { "years" => $yearlinks }); + } + + foreach my $year (@years) + { + $$months .= LJ::fill_var_props($vars, 'CALENDAR_NEW_YEAR', { + 'yyyy' => $year, + 'yy' => substr($year, 2, 2), + }); + + my @months = sort { $b <=> $a } keys %{$count{$year}}; + if ($vars->{'CALENDAR_SORT_MODE'} eq "forward") { @months = reverse @months; } + foreach my $month (@months) + { + my $daysinmonth = LJ::days_in_month($month, $year); + + # this picks a random day there were journal entries (thus, we know + # the %dayweek from above) from that we go backwards and forwards + # to find the rest of the days of week + my $firstday = (%{$count{$year}->{$month}})[0]; + + # go backwards from first day + my $dayweek = $dayweek{$year}->{$month}->{$firstday}; + for (my $i=$firstday-1; $i>0; $i--) + { + if (--$dayweek < 1) { $dayweek = 7; } + $dayweek{$year}->{$month}->{$i} = $dayweek; + } + # go forwards from first day + $dayweek = $dayweek{$year}->{$month}->{$firstday}; + for (my $i=$firstday+1; $i<=$daysinmonth; $i++) + { + if (++$dayweek > 7) { $dayweek = 1; } + $dayweek{$year}->{$month}->{$i} = $dayweek; + } + + my %calendar_month = (); + $calendar_month{'monlong'} = LJ::Lang::month_long($month); + $calendar_month{'monshort'} = LJ::Lang::month_short($month); + $calendar_month{'yyyy'} = $year; + $calendar_month{'yy'} = substr($year, 2, 2); + $calendar_month{'weeks'} = ""; + $calendar_month{'urlmonthview'} = sprintf("$journalbase/%04d/%02d/", $year, $month); + my $weeks = \$calendar_month{'weeks'}; + + my %calendar_week = (); + $calendar_week{'emptydays_beg'} = ""; + $calendar_week{'emptydays_end'} = ""; + $calendar_week{'days'} = ""; + + # start the first row and check for its empty spaces + my $rowopen = 1; + if ($dayweek{$year}->{$month}->{1} != 1) + { + my $spaces = $dayweek{$year}->{$month}->{1} - 1; + $calendar_week{'emptydays_beg'} = + LJ::fill_var_props($vars, 'CALENDAR_EMPTY_DAYS', + { 'numempty' => $spaces }); + } + + # make the days! + my $days = \$calendar_week{'days'}; + + for (my $i=1; $i<=$daysinmonth; $i++) + { + $count{$year}->{$month}->{$i} += 0; + if (! $rowopen) { $rowopen = 1; } + + my %calendar_day = (); + $calendar_day{'d'} = $i; + $calendar_day{'eventcount'} = $count{$year}->{$month}->{$i}; + if ($count{$year}->{$month}->{$i}) + { + $calendar_day{'dayevent'} = LJ::fill_var_props($vars, 'CALENDAR_DAY_EVENT', { + 'eventcount' => $count{$year}->{$month}->{$i}, + 'dayurl' => "$journalbase/" . sprintf("%04d/%02d/%02d/", $year, $month, $i), + }); + } + else + { + $calendar_day{'daynoevent'} = $vars->{'CALENDAR_DAY_NOEVENT'}; + } + + $$days .= LJ::fill_var_props($vars, 'CALENDAR_DAY', \%calendar_day); + + if ($dayweek{$year}->{$month}->{$i} == 7) + { + $$weeks .= LJ::fill_var_props($vars, 'CALENDAR_WEEK', \%calendar_week); + $rowopen = 0; + $calendar_week{'emptydays_beg'} = ""; + $calendar_week{'emptydays_end'} = ""; + $calendar_week{'days'} = ""; + } + } + + # if rows is still open, we have empty spaces + if ($rowopen) + { + if ($dayweek{$year}->{$month}->{$daysinmonth} != 7) + { + my $spaces = 7 - $dayweek{$year}->{$month}->{$daysinmonth}; + $calendar_week{'emptydays_end'} = + LJ::fill_var_props($vars, 'CALENDAR_EMPTY_DAYS', + { 'numempty' => $spaces }); + } + $$weeks .= LJ::fill_var_props($vars, 'CALENDAR_WEEK', \%calendar_week); + } + + $$months .= LJ::fill_var_props($vars, 'CALENDAR_MONTH', \%calendar_month); + } # end foreach months + + } # end foreach years + + ######## new code + + $$ret .= LJ::fill_var_props($vars, 'CALENDAR_PAGE', \%calendar_page); + + return 1; +} + +# the creator for the 'day' view: +sub create_view_day +{ + my ($ret, $u, $vars, $remote, $opts) = @_; + my $sth; + + my $user = $u->{'user'}; + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'} ne "") { + $opts->{'redir'} = LJ::journal_base($u->{'renamedto'}, $opts->{'vhost'}) . + "/day" . $opts->{'pathextra'}; + return 1; + } + + foreach ("name", "url", "urlname", "journaltitle") { LJ::text_out(\$u->{$_}); } + + my %day_page = (); + $day_page{'username'} = $user; + $day_page{'head'} = ""; + + if (LJ::are_hooks('s2_head_content_extra')) { + $day_page{'head'} .= LJ::run_hook('s2_head_content_extra', $remote, $opts->{r}); + } + + if ($u->{'opt_blockrobots'}) { + $day_page{'head'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $day_page{'head'} .= ''; + } + $day_page{'head'} .= + $vars->{'GLOBAL_HEAD'} . "\n" . $vars->{'DAY_HEAD'}; + $day_page{'name'} = LJ::ehtml($u->{'name'}); + $day_page{'name-\'s'} = ($u->{'name'} =~ /s$/i) ? "'" : "'s"; + $day_page{'title'} = LJ::ehtml($u->{'journaltitle'} || + $u->{'name'} . $day_page{'name-\'s'} . " Journal"); + + if ($u->{'url'} =~ m!^https?://!) { + $day_page{'website'} = + LJ::fill_var_props($vars, 'DAY_WEBSITE', { + "url" => LJ::ehtml($u->{'url'}), + "name" => LJ::ehtml($u->{'urlname'} || "My Website"), + }); + } + + my $journalbase = LJ::journal_base($user, $opts->{'vhost'}); + $day_page{'urlfriends'} = "$journalbase/friends"; + $day_page{'urlcalendar'} = "$journalbase/calendar"; + $day_page{'urllastn'} = "$journalbase/"; + + my $initpagedates = 0; + + my $get = $opts->{'getargs'}; + + my $month = $get->{'month'}; + my $day = $get->{'day'}; + my $year = $get->{'year'}; + my @errors = (); + + if ($opts->{'pathextra'} =~ m!^(?:/day)?/(\d\d\d\d)/(\d\d)/(\d\d)\b!) { + ($month, $day, $year) = ($2, $3, $1); + } + + if ($year !~ /^\d+$/) { push @errors, "Corrupt or non-existant year."; } + if ($month !~ /^\d+$/) { push @errors, "Corrupt or non-existant month."; } + if ($day !~ /^\d+$/) { push @errors, "Corrupt or non-existant day."; } + if ($month < 1 || $month > 12 || int($month) != $month) { push @errors, "Invalid month."; } + if ($year < 1970 || $year > 2038 || int($year) != $year) { push @errors, "Invalid year: $year"; } + if ($day < 1 || $day > 31 || int($day) != $day) { push @errors, "Invalid day."; } + if (scalar(@errors)==0 && $day > LJ::days_in_month($month, $year)) { push @errors, "That month doesn't have that many days."; } + + if (@errors) { + $$ret .= "Errors occurred processing this page:\n
      \n"; + foreach (@errors) { + $$ret .= "
    • $_
    • \n"; + } + $$ret .= "
    \n"; + return 0; + } + + my $logdb = LJ::get_cluster_reader($u); + unless ($logdb) { + $opts->{'errcode'} = "nodb"; + $$ret = ""; + return 0; + } + + my $optDESC = $vars->{'DAY_SORT_MODE'} eq "reverse" ? "DESC" : ""; + + my $secwhere = "AND security='public'"; + my $viewall = 0; + my $viewsome = 0; + if ($remote) { + + # do they have the viewall priv? + if ($get->{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "day: $user, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (security='public' OR (security='usemask' AND allowmask & $gmask))" + if $gmask; + } + } + + # load the log items + my $dateformat = "%a %W %b %M %y %Y %c %m %e %d %D %p %i %l %h %k %H"; + $sth = $logdb->prepare("SELECT jitemid AS itemid, posterid, security, ". + " DATE_FORMAT(eventtime, \"$dateformat\") AS 'alldatepart', anum " . + "FROM log2 " . + "WHERE journalid=? AND year=? AND month=? AND day=? $secwhere " . + "ORDER BY eventtime $optDESC, logtime $optDESC LIMIT 200"); + $sth->execute($u->{'userid'}, $year, $month, $day); + my @items; + push @items, $_ while $_ = $sth->fetchrow_hashref; + my @itemids = map { $_->{'itemid'} } @items; + + # load 'opt_ljcut_disable_lastn' prop for $remote. + LJ::load_user_props($remote, "opt_ljcut_disable_lastn"); + + ### load the log properties + my %logprops = (); + LJ::load_log_props2($logdb, $u->{'userid'}, \@itemids, \%logprops); + my $logtext = LJ::get_logtext2($u, @itemids); + + my %posteru = (); # map posterids to u objects + LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @items], [$u]); + + my $events = ""; + + ENTRY: + foreach my $item (@items) { + my ($itemid, $posterid, $security, $alldatepart, $anum) = + map { $item->{$_} } qw(itemid posterid security alldatepart anum); + + next ENTRY if $posteru{$posterid} && $posteru{$posterid}->{'statusvis'} eq 'S' && !$viewsome; + + my $replycount = $logprops{$itemid}->{'replycount'}; + my $subject = $logtext->{$itemid}->[0]; + my $event = $logtext->{$itemid}->[1]; + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$subject, \$event, $logprops{$itemid}); + } + + my %day_date_format = LJ::alldateparts_to_hash($alldatepart); + + unless ($initpagedates++) { + foreach (qw(dayshort daylong monshort monlong yy yyyy m mm d dd dth)) { + $day_page{$_} = $day_date_format{$_}; + } + } + + my %day_event = (); + $day_event{'itemid'} = $itemid; + $day_event{'datetime'} = LJ::fill_var_props($vars, 'DAY_DATE_FORMAT', \%day_date_format); + if ($subject ne "") { + LJ::CleanHTML::clean_subject(\$subject); + $day_event{'subject'} = LJ::fill_var_props($vars, 'DAY_SUBJECT', { + "subject" => $subject, + }); + } + + my $ditemid = $itemid*256 + $anum; + my $itemargs = "journal=$user&itemid=$ditemid"; + $day_event{'itemargs'} = $itemargs; + + LJ::CleanHTML::clean_event(\$event, { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'}, + 'cuturl' => LJ::item_link($u, $itemid, $anum), + 'ljcut_disable' => $remote->{'opt_ljcut_disable_lastn'}, }); + LJ::expand_embedded($u, $ditemid, $remote, \$event); + $day_event{'event'} = $event; + + if ($u->{'opt_showtalklinks'} eq "Y" && + ! $logprops{$itemid}->{'opt_nocomments'} + ) + { + my $nc; + $nc = "nc=$replycount" if $replycount && $remote && $remote->{'opt_nctalklinks'}; + + my $permalink = "$journalbase/$ditemid.html"; + my $posturl = LJ::Talk::talkargs($permalink, "mode=reply"); + my $readurl = LJ::Talk::talkargs($permalink, $nc); + + my $dispreadlink = $replycount || + ($logprops{$itemid}->{'hasscreened'} && + ($remote->{'user'} eq $user + || LJ::can_manage($remote, $u))); + $day_event{'talklinks'} = LJ::fill_var_props($vars, 'DAY_TALK_LINKS', { + 'itemid' => $ditemid, + 'itemargs' => $itemargs, + 'urlpost' => $posturl, + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'readlink' => $dispreadlink ? LJ::fill_var_props($vars, 'DAY_TALK_READLINK', { + 'urlread' => $readurl, + 'messagecount' => $replycount, + 'mc-plural-s' => $replycount == 1 ? "" : "s", + 'mc-plural-es' => $replycount == 1 ? "" : "es", + 'mc-plural-ies' => $replycount == 1 ? "y" : "ies", + }) : "", + }); + } + + ## current stuff + LJ::prepare_currents({ + 'props' => \%logprops, + 'itemid' => $itemid, + 'vars' => $vars, + 'prefix' => "DAY", + 'event' => \%day_event, + 'user' => $u, + }); + + my $var = 'DAY_EVENT'; + if ($security eq "private" && + $vars->{'DAY_EVENT_PRIVATE'}) { $var = 'DAY_EVENT_PRIVATE'; } + if ($security eq "usemask" && + $vars->{'DAY_EVENT_PROTECTED'}) { $var = 'DAY_EVENT_PROTECTED'; } + + $events .= LJ::fill_var_props($vars, $var, \%day_event); + } + + if (! $initpagedates) + { + # if no entries were on that day, we haven't populated the time shit! + # FIXME: don't use the database for this. it can be done in Perl. + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT DATE_FORMAT('$year-$month-$day', '%a %W %b %M %y %Y %c %m %e %d %D') AS 'alldatepart'"); + $sth->execute; + my @dateparts = split(/ /, $sth->fetchrow_arrayref->[0]); + foreach (qw(dayshort daylong monshort monlong yy yyyy m mm d dd dth)) + { + $day_page{$_} = shift @dateparts; + } + + $day_page{'events'} = LJ::fill_var_props($vars, 'DAY_NOEVENTS', {}); + } + else + { + $day_page{'events'} = LJ::fill_var_props($vars, 'DAY_EVENTS', { 'events' => $events }); + $events = ""; # free some memory maybe + } + + # calculate previous day + my $pdyear = $year; + my $pdmonth = $month; + my $pdday = $day-1; + if ($pdday < 1) + { + if (--$pdmonth < 1) + { + $pdmonth = 12; + $pdyear--; + } + $pdday = LJ::days_in_month($pdmonth, $pdyear); + } + + # calculate next day + my $nxyear = $year; + my $nxmonth = $month; + my $nxday = $day+1; + if ($nxday > LJ::days_in_month($nxmonth, $nxyear)) + { + $nxday = 1; + if (++$nxmonth > 12) { ++$nxyear; $nxmonth=1; } + } + + $day_page{'prevday_url'} = "$journalbase/" . sprintf("%04d/%02d/%02d/", $pdyear, $pdmonth, $pdday); + $day_page{'nextday_url'} = "$journalbase/" . sprintf("%04d/%02d/%02d/", $nxyear, $nxmonth, $nxday); + + $$ret .= LJ::fill_var_props($vars, 'DAY_PAGE', \%day_page); + return 1; +} + +1; diff --git a/livejournal/cgi-bin/modperl.pl b/livejournal/cgi-bin/modperl.pl new file mode 100755 index 0000000..b4af0fe --- /dev/null +++ b/livejournal/cgi-bin/modperl.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# + +package LJ::ModPerl; +use strict; +use lib "$ENV{'LJHOME'}/cgi-bin"; +use Apache; + +# pull in libraries and do per-start initialization once. +require "modperl_subs.pl"; + +# do per-restart initialization +LJ::ModPerl::setup_restart(); + +# delete itself from %INC to make sure this file is run again +# when apache is restarted +delete $INC{"$ENV{'LJHOME'}/cgi-bin/modperl.pl"}; + +# remember modtime of all loaded libraries +if ($LJ::IS_DEV_SERVER) { + %LJ::LIB_MOD_TIME = (); + while (my ($k, $file) = each %INC) { + next if $LJ::LIB_MOD_TIME{$file}; + next unless $file =~ m!^\Q$LJ::HOME\E!; + my $mod = (stat($file))[9]; + $LJ::LIB_MOD_TIME{$file} = $mod; + } +} + +# compatibility with old location of LJ::email_check: +*BMLCodeBlock::check_email = \&LJ::check_email; + +1; diff --git a/livejournal/cgi-bin/modperl_subs.pl b/livejournal/cgi-bin/modperl_subs.pl new file mode 100755 index 0000000..7a43521 --- /dev/null +++ b/livejournal/cgi-bin/modperl_subs.pl @@ -0,0 +1,137 @@ +#!/usr/bin/perl +# + +# to be require'd by modperl.pl + +use strict; + +package LJ; + +use Apache; +use Apache::LiveJournal; +use Apache::CompressClientFixup; +use Apache::BML; +use Apache::SendStats; +use Apache::DebateSuicide; + +use Digest::MD5; +use MIME::Words; +use Text::Wrap (); +use LWP::UserAgent (); +use Storable; +use Time::HiRes (); +use Image::Size (); +use POSIX (); + +use LJ::SpellCheck; +use LJ::TextMessage; +use LJ::Blob; +use LJ::Captcha; +use LJ::OpenID; +use MogileFS qw(+preload); +use DDLockClient (); + +# Try to load GTop library +BEGIN { $LJ::HAVE_GTOP = eval "use GTop (); 1;" } + +# Try to load DBI::Profile +BEGIN { $LJ::HAVE_DBI_PROFILE = eval "use DBI::Profile (); 1;" } + +require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljpoll.pl"; +require "$ENV{'LJHOME'}/cgi-bin/htmlcontrols.pl"; +require "$ENV{'LJHOME'}/cgi-bin/weblib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/imageconf.pl"; +require "$ENV{'LJHOME'}/cgi-bin/propparse.pl"; +require "$ENV{'LJHOME'}/cgi-bin/supportlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/cleanhtml.pl"; +require "$ENV{'LJHOME'}/cgi-bin/portal.pl"; +require "$ENV{'LJHOME'}/cgi-bin/talklib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljtodo.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljfeed.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlinks.pl"; +require "$ENV{'LJHOME'}/cgi-bin/directorylib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/emailcheck.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljmemories.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljmail.pl"; +require "$ENV{'LJHOME'}/cgi-bin/sysban.pl"; +require "$ENV{'LJHOME'}/cgi-bin/synlib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/communitylib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/taglib.pl"; + +# preload site-local libraries, if present: +require "$ENV{'LJHOME'}/cgi-bin/modperl_subs-local.pl" + if -e "$ENV{'LJHOME'}/cgi-bin/modperl_subs-local.pl"; + +$LJ::IMGPREFIX_BAK = $LJ::IMGPREFIX; +$LJ::STATPREFIX_BAK = $LJ::STATPREFIX; + +package LJ::ModPerl; + +# pull in a lot of useful stuff before we fork children + +sub setup_start { + + # auto-load some stuff before fork: + Storable::thaw(Storable::freeze({})); + foreach my $minifile ("GIF89a", "\x89PNG\x0d\x0a\x1a\x0a", "\xFF\xD8") { + Image::Size::imgsize(\$minifile); + } + DBI->install_driver("mysql"); + LJ::CleanHTML::helper_preload(); + + # set this before we fork + $LJ::CACHE_CONFIG_MODTIME = (stat("$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"))[9]; + + eval { setup_start_local(); }; +} + +sub setup_restart { + + # setup httpd.conf things for the user: + Apache->httpd_conf("DocumentRoot $LJ::HTDOCS") + if $LJ::HTDOCS; + Apache->httpd_conf("ServerAdmin $LJ::ADMIN_EMAIL") + if $LJ::ADMIN_EMAIL; + + Apache->httpd_conf(qq{ + +# This interferes with LJ's /~user URI, depending on the module order + + UserDir disabled + + +PerlInitHandler Apache::LiveJournal +PerlInitHandler Apache::SendStats +PerlFixupHandler Apache::CompressClientFixup +PerlCleanupHandler Apache::SendStats +PerlCleanupHandler Apache::DebateSuicide +PerlChildInitHandler Apache::SendStats +DirectoryIndex index.html index.bml +}); + + if ($LJ::BML_DENY_CONFIG) { + Apache->httpd_conf("PerlSetVar BML_denyconfig \"$LJ::BML_DENY_CONFIG\"\n"); + } + + unless ($LJ::SERVER_TOTALLY_DOWN) + { + Apache->httpd_conf(qq{ +# BML support: + + SetHandler perl-script + PerlHandler Apache::BML + + +# User-friendly error messages +ErrorDocument 404 /404-error.html +ErrorDocument 500 /500-error.html + +}); + } + +} + +setup_start(); + +1; diff --git a/livejournal/cgi-bin/parsefeed.pl b/livejournal/cgi-bin/parsefeed.pl new file mode 100755 index 0000000..73f6c8d --- /dev/null +++ b/livejournal/cgi-bin/parsefeed.pl @@ -0,0 +1,481 @@ +#!/usr/bin/perl + +use strict; + +package LJ::ParseFeed; + +use XML::RSS; +use XML::Parser; + + +# parse_feed parses an RSS/Atom feed +# arguments: content and, optionally, type, specifying "atom" or +# "rss". If type isn't supplied, the function will try to guess it +# based on contents. +# It returns $feed, which is a hash +# with the following keys: +# type - 'atom' or 'rss' +# version - version of the feed in its standard +# link - URL of the feed +# title - title of the feed +# description - description of the feed +# # TODO: more kinds of info? +# +# items - arrayref of item hashes, in the same order they were in the feed +# each item contains: +# link - URL of the item +# id - unique identifier (optional) +# text - text of the item +# subject - subject +# time - in format 'yyyy-mm-dd hh:mm' (optional) +# the second argument returned is $error, which, if defined, is a human-readable +# error string. the third argument is arrayref of items, same as +# $feed->{'items'}. + +sub parse_feed +{ + my ($content, $type) = @_; + my ($feed, $items, $error); + my $parser; + + # is it RSS or Atom? + # Atom feeds are rare for now, so prefer to err in favor of RSS + # simple heuristic: Atom feeds will have ''Stream', Pkg=>'LJ::ParseFeed::Atom'); + return ("", "failed to create XML parser") unless $parser; + eval { + $parser->parse($content); + }; + if ($@) { + $error = "XML parser error: $@"; + } else { + ($feed, $items, $error) = LJ::ParseFeed::Atom::results(); + }; + + if ($feed || $type eq 'atom') { + # there was a top-level there, or we're forced to treat + # as an Atom feed, so even if $error is set, + # don't try RSS + $feed->{'type'} = 'atom'; + return ($feed, $error, $items); + } + } + + # try parsing it as RSS + $parser = new XML::RSS; + return ("", "failed to create RSS parser") unless $parser; + eval { + $parser->parse($content); + }; + if ($@) { + $error = "RSS parser error: $@"; + return ("", $error); + } + + $feed = {}; + $feed->{'type'} = 'rss'; + $feed->{'version'} = $parser->{'version'}; + + foreach (qw (link title description)) { + $feed->{$_} = $parser->{'channel'}->{$_} + if $parser->{'channel'}->{$_}; + } + + $feed->{'items'} = []; + + foreach(@{$parser->{'items'}}) { + my $item = {}; + $item->{'subject'} = $_->{'title'}; + $item->{'text'} = $_->{'description'}; + $item->{'link'} = $_->{'link'} if $_->{'link'}; + $item->{'id'} = $_->{'guid'} if $_->{'guid'}; + + my $nsdc = 'http://purl.org/dc/elements/1.1/'; + my $nsenc = 'http://purl.org/rss/1.0/modules/content/'; + if ($_->{$nsenc} && ref($_->{$nsenc}) eq "HASH") { + # prefer content:encoded if present + $item->{'text'} = $_->{$nsenc}->{'encoded'} + if defined $_->{$nsenc}->{'encoded'}; + } + + if ($_->{'pubDate'}) { + my $time = time822_to_time($_->{'pubDate'}); + $item->{'time'} = $time if $time; + } + if ($_->{$nsdc} && ref($_->{$nsdc}) eq "HASH") { + if ($_->{$nsdc}->{date}) { + my $time = w3cdtf_to_time($_->{$nsdc}->{date}); + $item->{'time'} = $time if $time; + } + } + push @{$feed->{'items'}}, $item; + } + + return ($feed, undef, $feed->{'items'}); +} + +# convert rfc822-time in RSS's to our time +# see http://www.faqs.org/rfcs/rfc822.html +# RFC822 specifies 2 digits for year, and RSS2.0 refers to RFC822, +# but real RSS2.0 feeds apparently use 4 digits. +sub time822_to_time { + my $t822 = shift; + # remove day name if present + $t822 =~ s/^\s*\w+\s*,//; + # remove whitespace + $t822 =~ s/^\s*//; + # break it up + if ($t822 =~ m!(\d?\d)\s+(\w+)\s+(\d\d\d\d)\s+(\d?\d):(\d\d)!) { + my ($day, $mon, $year, $hour, $min) = ($1,$2,$3,$4,$5); + $day = "0" . $day if length($day) == 1; + $hour = "0" . $hour if length($hour) == 1; + $mon = {'Jan'=>'01', 'Feb'=>'02', 'Mar'=>'03', 'Apr'=>'04', + 'May'=>'05', 'Jun'=>'06', 'Jul'=>'07', 'Aug'=>'08', + 'Sep'=>'09', 'Oct'=>'10', 'Nov'=>'11', 'Dec'=>'12'}->{$mon}; + return undef unless $mon; + return "$year-$mon-$day $hour:$min"; + } else { + return undef; + } +} + +# convert W3C-DTF to our internal format +# see http://www.w3.org/TR/NOTE-datetime +# Based very loosely on code from DateTime::Format::W3CDTF, +# which isn't stable yet so we can't use it directly. +sub w3cdtf_to_time { + my $tw3 = shift; + + # TODO: Should somehow return the timezone offset + # so that it can stored... but we don't do timezones + # yet anyway. For now, just strip the timezone + # portion if it is present, along with the decimal + # fractions of a second. + + $tw3 =~ s/(?:\.\d+)?(?:[+-]\d{1,2}:\d{1,2}|Z)$//; + $tw3 =~ s/^\s*//; $tw3 =~ s/\s*$//; # Eat any superflous whitespace + + # We can only use complete times, so anything which + # doesn't feature the time part is considered invalid. + + # This is working around clients that don't implement W3C-DTF + # correctly, and only send single digit values in the dates. + # 2004-4-8T16:9:4Z vs 2004-04-08T16:09:44Z + # If it's more messed up than that, reject it outright. + $tw3 =~ /^(\d{4})-(\d{1,2})-(\d{1,2})T(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/ + or return undef; + + my %pd; # parsed date + $pd{Y} = $1; $pd{M} = $2; $pd{D} = $3; + $pd{h} = $4; $pd{m} = $5; $pd{s} = $6; + + # force double digits + foreach (qw/ M D h m s /) { + next unless defined $pd{$_}; + $pd{$_} = sprintf "%02d", $pd{$_}; + } + + return $pd{s} ? "$pd{Y}-$pd{M}-$pd{D} $pd{h}:$pd{m}:$pd{s}" : + "$pd{Y}-$pd{M}-$pd{D} $pd{h}:$pd{m}"; +} + +package LJ::ParseFeed::Atom; + +our ($feed, $item, $data); +our ($ddepth, $dholder); # for accumulating; +our @items; +our $error; + +sub err { + $error = shift unless $error; +} + +sub results { + return ($feed, \@items, $error); +} + +# $name under which we'll store accumulated data may be different +# from $tag which causes us to store it +# $name may be a scalarref pointing to where we should store +# swallowing is achieved by calling startaccum(''); + +sub startaccum { + my $name = shift; + + return err("Tag found under neither nor ") + unless $feed || $item; + $data = ""; # defining $data triggers accumulation + $ddepth = 1; + + $dholder = undef + unless $name; + # if $name is a scalarref, it's actually our $dholder + if (ref($name) eq 'SCALAR') { + $dholder = $name; + } else { + $dholder = ($item ? \$item->{$name} : \$feed->{$name}) + if $name; + } + return; +} + +sub swallow { + return startaccum(''); +} + +sub StartDocument { + ($feed, $item, $data) = (undef, undef, undef); + @items = (); + undef $error; +} + +sub StartTag { + # $_ carries the unparsed tag + my ($p, $tag) = @_; + my $holder; + + # do nothing if there has been an error + return if $error; + + # are we just accumulating data? + if (defined $data) { + $data .= $_; + $ddepth++; + return; + } + + # where we'll usually store info + $holder = $item ? $item : $feed; + + TAGS: { + if ($tag eq 'feed') { + return err("Nested tags") + if $feed; + $feed = {}; + $feed->{'standard'} = 'atom'; + $feed->{'version'} = $_{'version'}; + return err("No version specified in ") + unless $feed->{'version'}; + return err("Incompatible version specified in ") + unless $feed->{'version'} eq '0.3'; + last TAGS; + } + if ($tag eq 'entry') { + return err("Nested tags") + if $item; + $item = {}; + last TAGS; + } + + # at this point, we must have a top-level or + # to write into + return err("Tag found under neither nor ") + unless $holder; + + if ($tag eq 'link') { + # ignore links with rel= anything but alternate + unless ($_{'rel'} eq 'alternate') { + swallow(); + last TAGS; + } + $holder->{'link'} = $_{'href'}; + return err("No href attribute in ") + unless $holder->{'link'}; + last TAGS; + } + + if ($tag eq 'content') { + return err(" outside ") + unless $item; + # if type is multipart/alternative, we continue recursing + # otherwise we accumulate + my $type = $_{'type'} || "text/plain"; + unless ($type eq "multipart/alternative") { + push @{$item->{'contents'}}, [$type, ""]; + startaccum(\$item->{'contents'}->[-1]->[1]); + last TAGS; + } + # it's multipart/alternative, so recurse, but don't swallow + last TAGS; + } + + # store tags which should require no further + # processing as they are, and others under _atom_*, to be processed + # in EndTag under + if ($tag eq 'title') { + if ($item) { # entry's subject + startaccum("subject"); + } else { # feed's title + startaccum($tag); + } + last TAGS; + } + if ($tag eq 'id') { + unless ($item) { + swallow(); # we don't need feed-level + } else { + startaccum($tag); + } + last TAGS; + } + + if ($tag eq 'tagline' && !$item) { # feed's tagline, our "description" + startaccum("description"); + last TAGS; + } + + # accumulate and store + startaccum("_atom_" . $tag); + last TAGS; + } + + return; +} + +sub EndTag { + # $_ carries the unparsed tag + my ($p, $tag) = @_; + + # do nothing if there has been an error + return if $error; + + # are we accumulating data? + if (defined $data) { + $ddepth--; + if ($ddepth == 0) { # stop accumulating + $$dholder = $data + if $dholder; + undef $data; + return; + } + $data .= $_; + return; + } + + TAGS: { + if ($tag eq 'entry') { + # finalize item... + # generate suitable text from $item->{'contents'} + my $content; + $item->{'contents'} ||= []; + unless (scalar(@{$item->{'contents'}}) >= 1) { + # this item had no + # maybe it has
    ? if so, use + # TODO: type= or encoding issues here? perhaps unite + # handling of with that of ? + if ($item->{'_atom_summary'}) { + $item->{'text'} = $item->{'_atom_summary'}; + delete $item->{'contents'}; + } else { + # nothing to display, so ignore this entry + undef $item; + last TAGS; + } + } + + unless ($item->{'text'}) { # unless we already have text + if (scalar(@{$item->{'contents'}}) == 1) { + # only one section + $content = $item->{'contents'}->[0]; + } else { + # several section, must choose the best one + foreach (@{$item->{'contents'}}) { + if ($_->[0] eq "application/xhtml+xml") { # best match + $content = $_; + last; # don't bother to look at others + } + if ($_->[0] =~ m!html!) { # some kind of html/xhtml/html+xml, etc. + # choose this unless we've already chosen some html + $content = $_ + unless $content->[0] =~ m!html!; + next; + } + if ($_->[0] eq "text/plain") { + # choose this unless we have some html already + $content = $_ + unless $content->[0] =~ m!html!; + next; + } + } + # if we didn't choose anything, pick the first one + $content = $item->{'contents'}->[0] + unless $content; + } + + # we ignore the 'mode' attribute of . If it's "xml", we've + # stringified it by accumulation; if it's "escaped", our parser + # unescaped it + # TODO: handle mode=base64? + + $item->{'text'} = $content->[1]; + delete $item->{'contents'}; + } + + # generate time + my $w3time = $item->{'_atom_modified'} || $item->{'_atom_created'}; + my $time; + if ($w3time) { + # see http://www.w3.org/TR/NOTE-datetime for format + # we insist on having granularity up to a minute, + # and ignore finer data as well as the timezone, for now + if ($w3time =~ m!^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d)!) { + $time = "$1-$2-$3 $4:$5"; + } + } + if ($time) { + $item->{'time'} = $time; + } + + # get rid of all other tags we don't need anymore + foreach (keys %$item) { + delete $item->{$_} if substr($_, 0, 6) eq '_atom_'; + } + + push @items, $item; + undef $item; + last TAGS; + } + if ($tag eq 'feed') { + # finalize feed + # get rid of all other tags we don't need anymore + foreach (keys %$feed) { + delete $feed->{$_} if substr($_, 0, 6) eq '_atom_'; + } + + # link the feed with its itms + $feed->{'items'} = \@items + if $feed; + last TAGS; + } + } + return; +} + +sub Text { + my $p = shift; + + # do nothing if there has been an error + return if $error; + + $data .= $_ if defined $data; +} + +sub PI { + # ignore processing instructions + return; +} + +sub EndDocument { + # if we parsed a feed, link items to it + $feed->{'items'} = \@items + if $feed; + return; +} + + +1; diff --git a/livejournal/cgi-bin/portal.pl b/livejournal/cgi-bin/portal.pl new file mode 100755 index 0000000..e778fa1 --- /dev/null +++ b/livejournal/cgi-bin/portal.pl @@ -0,0 +1,1141 @@ +#!/usr/bin/perl +# + +require "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl"; + +use strict; + +package LJ::Portal; +use vars qw(%box %colname); + +%colname = ("left" => "Left Sidebar", + "main" => "Main Area", + "right" => "Right Sidebar", + "moz" => "Mozilla Sidebar", + ); + +# was using "use constant" here but the error logs filled up with +# warnings about redefinitions of subroutines. (constants are subs... great, perl.) +my $BOX_NAME = 0; +my $BOX_ARGS = 1; +my $BOX_POS = 2; +my $BOX_DIRTY = 3; + +sub get_box_size +{ + my $loc = shift; + return $loc eq "main" ? "large" : "small"; +} + +sub get_box_types +{ + my $loc = shift; + my $size = get_box_size($loc); + return map { $_, $box{$_}->{'name'} } grep { $box{$_}->{$size} } sort keys %box; +} + +sub construct_page +{ + my $opts = shift; + + my $body = $opts->{'body'}; + my $remote = $opts->{'remote'}; + my $puri = $opts->{'puri'}; + $opts->{'border'} += 0; + + my %tdopts = ('main' => "", + 'right' => "width=180", + 'left' => "width=180", + ); + + my $portopts = load_portopts($remote); + + $$body .= "{'border'} cellpadding=3 width=100% height=500>\n"; + $$body .= "\n"; + foreach my $loc (@LJ::PORTAL_COLS) + { + next if ($loc eq "moz"); + + $$body .= "\n"; + } + $$body .= "\n"; + $$body .= "
    \n"; + + $portopts->{$loc} ||= []; + foreach my $pbox (@{$portopts->{$loc}}) + { + my $bname = $pbox->[$BOX_NAME]; + my $bargs = $pbox->[$BOX_ARGS]; + next unless (ref $box{$bname}->{'handler'} eq "CODE"); + + my $args = {}; + LJ::decode_url_string(\$bargs, $args); + + my $box = $box{$bname}; + $box->{'key'} = $bname; # so we don't have to set it explicitly + $box->{'args'} = $args; + $box->{'loc'} = $loc; + $box->{'pos'} = "$pbox->[$BOX_POS]"; + $box->{'uniq'} = "$loc$pbox->[$BOX_POS]"; + + $box{$bname}->{'handler'}->($remote, $opts, $box); + } + + $$body .= "
    \n"; + + if ($opts->{'onload'}) { + ${$opts->{'bodyopts'}} .= "onLoad=\"" . join('', keys %{$opts->{'onload'}}) . "\""; + } + +} + +sub load_portopts +{ + my $remote = shift; + my $dbr = LJ::get_db_reader(); + + my $portopts; + + # if user is logged in, see if they've defined their portal box settings: + if ($remote) + { + my $sth = $dbr->prepare("SELECT loc, pos, boxname, boxargs FROM portal WHERE userid=$remote->{'userid'} ORDER BY loc, pos"); + $sth->execute; + while (my $row = $sth->fetchrow_hashref) + { + push @{$portopts->{$row->{'loc'}}}, [ $row->{'boxname'}, $row->{'boxargs'}, $row->{'pos'} ]; + } + } + + # if the user isn't logged in, or they haven't defined their portal boxes, + # then give them the defaults: + unless ($portopts) + { + if ($remote) { + $portopts = $LJ::PORTAL_LOGGED_IN; + } else { + $portopts = $LJ::PORTAL_LOGGED_OUT; + } + + ## set the 'pos' argument on each box arrayref + ## so it doesn't have to be set explicitly in ljconfig.pl, which would be tedious. + ## also, set the dirty flag to true, so a subsequent save will change it + foreach my $loc (keys %$portopts) { + for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { + $portopts->{$loc}->[$i]->[$BOX_POS] = $i+1; + $portopts->{$loc}->[$i]->[$BOX_DIRTY] = 1; + } + } + + } + + return $portopts; +} + +sub count_boxes +{ + my $portopts = shift; + my $count = 0; + foreach my $loc (keys %$portopts) { + for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { + my $box = $portopts->{$loc}->[$i]; + if ($box->[$BOX_NAME]) { $count++; } + } + } + return $count; +} + +# FIXME: portal info should be clustered! +sub save_portopts +{ + my $remote = shift; + my $portopts = shift; + + my $dbh = LJ::get_db_writer(); + my $userid = $remote->{'userid'}+0; + return unless $userid; + + my @delsql; + + my $sql; + foreach my $loc (keys %$portopts) { + for (my $i=0; $i < scalar(@{$portopts->{$loc}}); $i++) { + my $box = $portopts->{$loc}->[$i]; + next unless ($box->[$BOX_DIRTY]); + + my $qloc = $dbh->quote($loc); + my $qpos = $box->[2] + 0; + if ($box->[$BOX_NAME]) { + # modifying + my $qboxname = $dbh->quote($box->[$BOX_NAME]); + my $qboxargs = $dbh->quote($box->[$BOX_ARGS]); + $sql ||= "REPLACE INTO portal (userid, loc, pos, boxname, boxargs) VALUES "; + $sql .= "($userid, $qloc, $qpos, $qboxname, $qboxargs),"; + } else { + # deleting + push @delsql, "DELETE FROM portal WHERE userid=$userid AND loc=$qloc AND pos=$qpos"; + } + $box->[$BOX_DIRTY] = 0; + } + } + + if ($sql) { + chop $sql; + $dbh->do($sql); + } + foreach (@delsql) { + $dbh->do($_); + } +} + +sub delete_box +{ + my $portopts = shift; + my $loc = shift; + my $pos = shift; + my $bname = shift; + + return unless (defined $portopts->{$loc}->[$pos-1]); + my $box = $portopts->{$loc}->[$pos-1]; + return unless ($box->[$BOX_NAME] eq $bname); + + # time to delete it... move everything else up. + my $locsize = scalar(@{$portopts->{$loc}}); + + # else, move everything else up, and mark the file one dirty; + for (my $i=$pos; $i < $locsize; $i++) { + $portopts->{$loc}->[$i-1] = $portopts->{$loc}->[$i]; + $portopts->{$loc}->[$i-1]->[$BOX_POS] = $i; + $portopts->{$loc}->[$i-1]->[$BOX_DIRTY] = 1; + } + + # final one is dirty and marked for deletion + $portopts->{$loc}->[$locsize-1] = [ "", "", $locsize, 1]; + +} + +sub move_box +{ + my $portopts = shift; + my $loc = shift; + my $pos = shift; + my $bname = shift; + my $op = shift; + + return unless (defined $portopts->{$loc}->[$pos-1]); + my $box = $portopts->{$loc}->[$pos-1]; + return unless ($box->[$BOX_NAME] eq $bname); + + # how many are in that column? + my $locsize = scalar(@{$portopts->{$loc}}); + + # can't move top up or bottom down. + return if ($op eq "u" && $pos == 1); + return if ($op eq "d" && $pos == $locsize); + + # destination position + my $dpos = $pos + ($op eq "u" ? -1 : 1); + + # does that location exist to swap with? + return unless (defined $portopts->{$loc}->[$dpos-1]); + + # swap locations! + ($portopts->{$loc}->[$dpos-1], $portopts->{$loc}->[$pos-1]) = + ($portopts->{$loc}->[$pos-1], $portopts->{$loc}->[$dpos-1]); + + # set their locations and dirty flags + foreach my $p ($pos, $dpos) + { + $portopts->{$loc}->[$p-1]->[$BOX_POS] = $p; + $portopts->{$loc}->[$p-1]->[$BOX_DIRTY] = 1; + } +} + +sub make_box_modify_form +{ + my $portopts = shift; + my $loc = shift; + my $pos = shift; + + return "" unless (defined $portopts->{$loc}->[$pos-1]); + my $box = $portopts->{$loc}->[$pos-1]; + + my $curargs = {}; + LJ::decode_url_string(\$box->[$BOX_ARGS], $curargs); + + my $ret = ""; + + foreach my $opt (@{$box{$box->[$BOX_NAME]}->{'opts'}}) + { + unless ($ret) { + $ret .= "
    "; + } + + $ret .= "

    $opt->{'name'}: "; + my $key = $opt->{'key'}; + if ($opt->{'type'} eq "select") { + $ret .= LJ::html_select({ 'name' => "arg_$key", + 'selected' => $curargs->{$key}, + 'noescape' => 1, + }, + @{$opt->{'values'}}); + } + if ($opt->{'type'} eq "check") { + $ret .= LJ::html_check({ 'name' => "arg_$key", + 'selected' => $curargs->{$key}, + 'value' => 1, + }); + } + if ($opt->{'type'} eq "text") { + $ret .= LJ::html_text({ 'name' => "arg_$key", + 'maxlength' => $opt->{'maxlength'}, + 'size' => $opt->{'size'}, + 'value' => $curargs->{$key}, + }); + } + if ($opt->{'des'}) { + $ret .= "
    $opt->{'des'}"; + } + + } + if ($ret) { + $ret .= "

    "; + $ret .= "

    "; + } + + return $ret; + +} + +sub modify_box +{ + my $remote = shift; + my $portopts = shift; + my $loc = shift; + my $pos = shift; + my $form = shift; + + return "" unless (defined $portopts->{$loc}->[$pos-1]); + my $box = $portopts->{$loc}->[$pos-1]; + + my $newargs; + + foreach my $opt (@{$box{$box->[$BOX_NAME]}->{'opts'}}) + { + if ($newargs) { $newargs .= "&"; } + $newargs .= LJ::eurl($opt->{'key'}) . "=" . LJ::eurl($form->{"arg_$opt->{'key'}"}); + $box->[$BOX_ARGS] = $newargs; + $box->[$BOX_DIRTY] = 1; + } + + save_portopts($remote, $portopts); + return $newargs; +} + +sub create_new_box +{ + my ($portopts, $bname, $loc) = @_; + my $defargs; + foreach my $opt (@{$box{$bname}->{'opts'}}) + { + # if non-zero or non-blank default, remember it + if ($opt->{'default'}) { + $defargs .= "&" if ($defargs); + $defargs .= LJ::eurl($opt->{'key'}) . "=" . LJ::eurl($opt->{'default'}); + } + } + + $portopts->{$loc} ||= []; + my $size = scalar(@{$portopts->{$loc}}); + + push @{$portopts->{$loc}}, [ $bname, $defargs, $size+1, 1 ]; +} + +sub make_box_link +{ + my $form = shift; + my $bname = $form->{'bname'}; + + my $args = ""; + foreach my $arg (@{$box{$bname}->{'args'}}) + { + my $key = $arg->{'key'}; + my $val = $form->{"arg_$key"}; + if ($val) { + $args .= "&$key=$val"; + } + } + my $title = $box{$bname}->{'name'} . " ($LJ::SITENAME)"; + + return "$LJ::SITEROOT/portal/box.bml?bname=$bname$args"; +} + +# XXXXXXXX DEAD / OLD + sub make_mozilla_box +{ + my $remote = shift; + my $form = shift; + my $opts = shift; + + my $bname = $form->{'bname'}; + return "" unless (ref $box{$bname}->{'handler'} eq "CODE"); + + my $box = $box{$bname}; + $box->{'key'} = $bname; + $box->{'args'} = $form; + $box->{'pos'} = "moz"; + $box->{'loc'} = 1; + $box->{'uniq'} = "moz1"; + $box{$bname}->{'handler'}->($remote, $opts, $box); +} + +sub make_mozilla_bar +{ + my $remote = shift; + my $form = shift; + my $opts = shift; + + my $portopts = load_portopts($remote); + my $loc = "moz"; + + foreach my $pbox (@{$portopts->{$loc}}) + { + my $bname = $pbox->[$BOX_NAME]; + my $bargs = $pbox->[$BOX_ARGS]; + next unless (ref $box{$bname}->{'handler'} eq "CODE"); + + my $args = {}; + LJ::decode_url_string(\$bargs, $args); + + my $box = $box{$bname}; + $box->{'key'} = $bname; # so we don't have to set it explicitly + $box->{'args'} = $args; + $box->{'loc'} = $loc; + $box->{'pos'} = "$pbox->[$BOX_POS]"; + $box->{'uniq'} = "$loc$pbox->[$BOX_POS]"; + + $box{$bname}->{'handler'}->($remote, $opts, $box); + } + + + if ($opts->{'onload'}) { + ${$opts->{'bodyopts'}} .= "onLoad=\"" . join('', keys %{$opts->{'onload'}}) . "\""; + } +} + +sub box_start +{ + my ($b, $box, $opts) = @_; + my $title = $opts->{'title'} || $box->{'name'}; + my $mapname = $box->{'uniq'}; + my $align = $opts->{'align'} || "left"; + my $t = join("-", $box->{'key'}, $box->{'loc'}, $box->{'pos'}); + + $$b .= "\n"; + $$b .= "Down\n"; + $$b .= "Up\n"; + $$b .= "\"Add/Modify\"\n"; + $$b .= "Kill\n"; + $$b .= "\n"; + + if ($box->{'pos'} > 1) { $$b .= "

    "; } + $$b .= ""; + $$b .= "\n"; + + if ($box->{'loc'} eq "main") { + $$b .="
    "; + $$b .= ""; + + $$b .= " "; + if ($opts->{'url'}) { $$b .= "{'url'}\">"; } + $$b .= $title; + if ($opts->{'url'}) { $$b .= ""; } + $$b .= "
    \n"; + } else { + $$b .= "
    "; + } +} + +sub box_end +{ + my ($b, $box) = @_; + unless ($box->{'loc'} eq "main") + { + $$b .= "
    \n"; + $$b .= "\n"; + } +} + +# Load site-specific boxes +if (-e "$LJ::HOME/cgi-bin/portal-local.pl") { + require "$LJ::HOME/cgi-bin/portal-local.pl"; +} + +############################################################################ + +$box{'login'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $b = $opts->{'body'}; + + box_start($b, $box, { 'title' => "Login", + 'align' => "center", + 'url' => '/login.bml', }); + + my $chal = LJ::challenge_generate(300); # 5 minute auth token + + $$b .= "

    "; + $$b .= ""; + $$b .= "
    "; + $$b .= "Username:

    "; + $$b .= "Password:

    "; + $$b .= " Remember me"; + $$b .= ""; + $$b .= ""; + $$b .= ""; + $$b .= "
    "; + + $$b .= < + + + +LOGIN + $$b .= "
    "; + + box_end($b, $box); + $$b .= "
    \n"; + }, +}; + +############################################################################ + +############################################################################ + +$box{'stats'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $dbr = LJ::get_db_reader(); + my $b = $opts->{'body'}; + my $sth; + my @stats; + my ($k, $v); + + box_start($b, $box, { 'title' => BML::ml('portal.stats.portaltitle'), + 'url' => '/stats.bml' }); + + my %stat; + $sth = $dbr->prepare("SELECT statkey, statval FROM stats WHERE statcat='statbox'"); + $sth->execute; + while (my ($k, $v) = $sth->fetchrow_array) { + $stat{$k} = $v; + } + + push @stats, BML::ml('portal.stats.totalusers'), $stat{'totusers'}; + push @stats, BML::ml('portal.stats.journalentyest'), $stat{'postyester'}; + + $$b .= ""; + while (@stats) { + $k = shift @stats; + $v = shift @stats; + $$b .= ""; + $$b .= ""; + } + $$b .= "
    $k
    $v
    "; + + box_end($b, $box); + }, +}; + +############################################################################ + +$box{'bdays'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'opts' => [ { 'key' => 'count', + 'name' => '', + 'des' => '', + 'type' => 'text', + 'maxlength' => 3, + 'size' => 3, + 'default' => 5 }, + ], + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $dbr = LJ::get_db_reader(); + my $bd = $opts->{'body'}; + my $sth; + + box_start($bd, $box, { 'title' => BML::ml('portal.bdays.portaltitle'), + 'url' => '/birthdays.bml' }); + + # TAG:FR:portal:get_bdays + $sth = $dbr->prepare("SELECT u.user, MONTH(bdate) AS 'month', DAYOFMONTH(bdate) AS 'day' FROM friends f, user u WHERE f.userid=$remote->{'userid'} AND f.friendid=u.userid AND u.journaltype='P' AND u.statusvis='V' AND u.allow_infoshow='Y' AND MONTH(bdate) != 0 AND DAYOFMONTH(bdate) != 0"); + $sth->execute; + + # what day is it now? server time... suck, yeah. + my @time = localtime(); + my ($mnow, $dnow) = ($time[4]+1, $time[3]); + + my @bdays; + while (my ($user, $m, $d) = $sth->fetchrow_array) { + my $ref = [ $user, $m, $d ]; + if ($m < $mnow || ($m == $mnow && $d < ($dnow))) { + # birthday passed this year already + $ref->[3] = 1; + } + push @bdays, $ref; + } + + # sort birthdays that have passed this year after ones that haven't, + # otherwise sort by month, otherwise by day. + @bdays = sort { + + # passed sort + ($a->[3] <=> $b->[3]) || + + # month sort + ($a->[1] <=> $b->[1]) || + + + # day sort + ($a->[2] <=> $b->[2]) + + } @bdays; + + # cut the list down + my $show = ($box->{'args'}->{'count'} + 0) || 10; + if ($show > 100) { $show = 100; } + if (@bdays > $show) { @bdays = @bdays[0..$show-1]; } + + $$bd .= ""; + my $add_ord = BML::get_language() =~ /^en/i; + foreach my $bi (@bdays) + { + my $mon = BML::ml( LJ::Lang::month_short_langcode($bi->[1]) ); + my $day = $bi->[2]; + $day .= LJ::Lang::day_ord($bi->[2]) if $add_ord; + + $$bd .= ""; + $$bd .= ""; + } + $$bd .= "
    " . LJ::ljuser($bi->[0]) . "$mon $day
    "; + + box_end($bd, $box); + }, +}; +############################################################################ + +$box{'lastnview'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 1, + 'opts' => [ { 'key' => 'journal', + 'name' => '', + 'des' => '', + 'type' => 'text', + 'maxlength' => 15, + 'size' => 15, + 'default' => '' }, + { 'key' => 'items', + 'name' => '', + 'des' => '', + 'type' => 'text', + 'maxlength' => 2, + 'size' => 2, + 'default' => 1 }, + { 'key' => 'showtext', + 'name' => '', + 'des' => '', + 'type' => 'check', + 'value' => 1, + 'default' => 0 }, + ], + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $bd = $opts->{'body'}; + my $sth; + + my $user = LJ::canonical_username($box->{'args'}->{'journal'}); + my $items = $box->{'args'}->{'items'}+0 || 1; + if ($items > 50) { $items = 50; } + + unless ($user) + { + box_start($bd, $box,{'title' => BML::ml('portal.recent.portaltitle') ,}); + $$bd .= BML::ml('portal.recent.error.notsetup'); + box_end($bd, $box); + return; + } + + my $u = LJ::load_user($user); + my $dbcr = LJ::get_cluster_reader($u); + + box_start($bd, $box, { 'title' => "$u->{'name'}", + 'url' => "$LJ::SITEROOT/users/$user" }); + + unless ($u->{'statusvis'} eq "V") { + $$bd .= BML::ml('portal.recent.error.userstatus'); + box_end($bd, $box); + return; + } + + my @itemids; + my @items = LJ::get_recent_items({ + 'clustersource' => 'slave', + 'clusterid' => $u->{'clusterid'}, + 'remote' => $remote, + 'userid' => $u->{'userid'}, + 'skip' => 0, + 'itemshow' => $items, + 'itemids' => \@itemids, + 'order' => ($u->{'journaltype'} eq "C") ? "logtime" : "", + }); + + unless(@itemids) { + $$bd .= BML::ml('portal.recent.error.noentries'); + box_end($bd, $box); + return; + } + + my %logprops = (); + my $text = LJ::get_logtext2($u, @itemids); + + my %posteru = (); # map posterids to u objects + LJ::load_userids_multiple([map { $_->{'posterid'}, \$posteru{$_->{'posterid'}} } @items], [$u]); + # Loads the log table into cache, in the unlikely event that it is not already in cache + LJ::load_log_props2($dbcr, $u->{'userid'}, \@itemids, \%logprops); + + foreach my $i (@items) { + next if $posteru{$i->{'posterid'}}->{'statusvis'} eq 'S'; + + my $itemid = $i->{'itemid'}; + my $event = $text->{$itemid}->[1]; + my $subject = $text->{$itemid}->[0]; + LJ::CleanHTML::clean_subject(\$subject) if ($subject); + $subject ||= "(no subject)"; + + LJ::CleanHTML::clean_event(\$event, + { 'preformatted' => $logprops{$itemid}->{'opt_preformatted'} }) if ($event); + + my $linkurl = "
    (Link)"; + if ($box->{'args'}->{'showtext'}) { + $$bd .= "$subject $linkurl
    "; + $$bd .= "$event
    "; + } else { + $$bd .= "$subject $linkurl
    "; + } + } + + box_end($bd, $box); + }, +}; + +############################################################################ + + +$box{'update'} = +{ + 'name' => '', + 'small' => 0, + 'large' => 1, + 'opts' => [ { 'key' => 'mode', + 'name' => '', + 'type' => 'select', + 'des' => '', + 'values' => [ "", '', + "full", '' ], + 'default' => "" }, + ], + 'handler' => sub + { + my ($remote, $opts, $box) = @_; + my $bd = $opts->{'body'}; + my $h = $opts->{'head'}; + + $opts->{'onload'}->{"settime(document.updateForm$box->{'uniq'});"} = 1; + + box_start($bd, $box, {'title' => BML::ml('portal.update.portalname'), + 'url' => "$LJ::SITEROOT/update.bml", + }); + + my $mode = $opts->{'form'}->{'mode'} || $box->{'args'}->{'mode'}; + + my $chal = LJ::challenge_generate(300); # 5 minute auth token + $$bd .= "
    "; + $$bd .= ""; + $$bd .= ""; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $year+=1900; + $mon=sprintf("%02d", $mon+1); + $mday=sprintf("%02d", $mday); + $min=sprintf("%02d", $min); + + $$bd .= ""; + if ($remote) { + $$bd .= "\n"; + } else { + $$bd .= ""; + } + $$bd .= "
    Logged in user: $remote->{'user'} (other user?)
    User: "; + $$bd .= "Password: "; + $$bd .= "
    "; + + $$bd .= "\n"; + $$bd .= ""; + + $$bd .= "
    Date: yyyy-mm-ddLocal time: hh:mm (24 hour time)
    -"; + $$bd .= "-"; + $$bd .= "   :"; + $$bd .= "
    \n"; + + + $$bd .= ""; + + $$bd .= ""; + + if ($mode eq "full") + { + my %res; + + if (! $opts->{'form'}->{'altlogin'} && $remote) + { + LJ::do_request({ "mode" => "login", + "ver" => $LJ::PROTOCOL_VER, + "user" => $remote->{'user'}, + "getpickws" => 1, + }, \%res, { "noauth" => 1, "userid" => $remote->{'userid'} }); + } + + $$bd .= ""; + + } + else + { + $$bd .= "\n"; + } + + $$bd .= "
    Subject: (optional)
    "; + $$bd .= "{'form'}->{'subject'}) . "\">
    "; + + $$bd .= "Event:
    "; + $$bd .= ""; + $$bd .= "
    <BR>) de?>
    "; + $$bd .= " "; + $$bd .= "
    "; + + $$bd .= < + + + +UPDATE + $$bd .= "
    "; + + if ($res{'access_count'}) { + $$bd .= "

    Journal to post in: "; + my @access; + for (my $i=1; $i<=$res{'access_count'}; $i++) { + push @access, $res{"access_$i"}; + } + $$bd .= LJ::html_select({ 'name' => 'usejournal', 'selected' => $opts->{'form'}->{'usejournal'}, }, + "", "($remote->{'user'}) -- default", map { $_, $_ } @access); + } + + $$bd .= "

    Security Level: "; + $$bd .= LJ::html_select({ 'name' => 'security', 'selected' => $opts->{'form'}->{'security'}, }, + "public", "Public", + "private", "Private", + "friends", "Friends"); + $$bd .= LJ::help_icon("security", " "); + my $checked; + $checked = $opts->{'form'}->{'prop_opt_preformatted'} ? "CHECKED" : ""; + $$bd .= "

    Don't auto-format:"; + $$bd .= LJ::help_icon("noautoformat", " "); + $$bd .= "   "; + $checked = $opts->{'form'}->{'prop_opt_nocomments'} ? "CHECKED" : ""; + $$bd .= "Disallow Comments:"; + + $checked = $opts->{'form'}->{'prop_opt_backdated'} ? "CHECKED" : ""; + $$bd .= "

    Backdate Entry: (will only show on calendar)"; + + if ($res{'pickw_count'}) { + $$bd .= "

    Picture to use: "; + my @pics; + for (my $i=1; $i<=$res{'pickw_count'}; $i++) { + push @pics, $res{"pickw_$i"}; + } + @pics = sort { lc($a) cmp lc($b) } @pics; + $$bd .= LJ::html_select({'name' => 'prop_picture_keyword', + 'selected' => $opts->{'form'}->{'prop_picture_keyword'}, }, + ("", "(default)", map { ($_, $_) } @pics)); + $$bd .= LJ::help_icon("userpics", " "); + } else { + $$bd .= "

    $res{'errmsg'}"; + } + + $$bd .= "

    Current Mood:"; + + my @sel; + my $moods = LJ::get_moods(); + foreach my $moodid (sort { $moods->{$a}->{'name'} cmp $moods->{$b}->{'name'} } keys %$moods) + { + push @sel, $moodid, $moods->{$moodid}->{'name'}; + } + + $$bd .= LJ::html_select({'name' => 'prop_current_moodid', + 'selected' => $opts->{'form'}->{'prop_current_moodid'}, }, + ("", "None, or other:", @sel)); + + $$bd .= "Other: {'form'}->{'prop_current_mood'}) . "\">"; + $$bd .= "

    Current Music: {'form'}->{'prop_current_music'}) . "\">"; + $$bd .= '

    Tags: '; + $$bd .= LJ::html_text( + { + 'name' => 'prop_taglist', + 'size' => '35', + 'maxlength' => '255', + } + ); + $$bd .= "

    go here. de?>
    "; + + $$h .= <<'JAVASCRIPT_STUFF'; + +JAVASCRIPT_STUFF + +box_end($bd, $box); + + + }, +}; + +#################################### + +## TODO: let user specify number of random people, and have them +## go horizontally or vertically. +$box{'randuser'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 1, + 'opts' => [ { 'key' => 'hidepic', + 'name' => '', + 'type' => 'check', + 'des' => '', + 'default' => 0 }, + { 'key' => 'hidename', + 'name' => '', + 'type' => 'check', + 'des' => '', + 'default' => 0 }, + { 'key' => 'count', + 'name' => '', + 'des' => "", + 'type' => 'text', + 'maxlength' => 2, + 'size' => 2, + 'default' => 1 }, + ], + 'handler' => sub + { + my ($remote, $opts, $box) = @_; + my $dbr = LJ::get_db_reader(); + my $b = $opts->{'body'}; + my $h = $opts->{'head'}; + + my $size = get_box_size($box->{'loc'}); + my $count = int($box->{'args'}->{'count'}); + if ($count < 1) { $count = 1; } + if ($size eq "small" && $count > 5) { $count = 5; } + if ($size eq "large" && $count > 10) { $count = 10; } + + my $max = $dbr->selectrow_array("SELECT statval FROM stats WHERE statcat='userinfo' AND statkey='randomcount'"); + $count = $max if ($count > $max); + my %ruserid; + while (keys %ruserid < $count) { + $ruserid{int(rand($max))+1} = 1; + } + + unless ($count) { + box_start($b, $box, {'title' => BML::ml('portal.randuser.portaltitle'), + 'align' => "center", + }); + $$b .= BML::ml('portal.randuser.error.tableempty'); + box_end($b, $box); + return; + } + + box_start($b, $box, { + 'title' => (keys %ruserid > 1 ? BML::ml('portal.randuser.portaltitleplural') : BML::ml('portal.randuser.portaltitle')), + 'align' => "center", + }); + + my @ruser; + my $sth = $dbr->prepare(qq{ + SELECT userid, user, name, defaultpicid FROM user WHERE userid IN + } . "(" . join(",", keys %ruserid) . ")"); + $sth->execute; + push @ruser, $_ while $_ = $sth->fetchrow_hashref; + + my %pic; + unless ($box->{'args'}->{'hidepic'}) { + LJ::load_userpics(\%pic, [ map { [ $_, $_->{'defaultpicid'} ] } @ruser ]); + } + + if ($size eq "large") { $$b .= ""; } + + my $rct = 1; + foreach my $r (@ruser) + { + if ($size eq "large") { $$b .= ""; } + $rct++; + } + if ($size eq "large") { $$b .= "
    "; } + elsif ($size eq "small" && $rct > 1) { $$b .= "

    "; } + + my $picid = $r->{'defaultpicid'}; + if ($picid && ! $box->{'args'}->{'hidepic'}) { + $$b .= "{'userid'}\" width=$pic{$picid}->{'width'} height=$pic{$picid}->{'height'}>
    "; + } + $$b .= "{'user'} ljuser?>"; + unless ($box->{'args'}->{'hidename'}) { + $$b .= "
    " . LJ::ehtml($r->{'name'}); + } + + if ($size eq "large") { $$b .= "

    "; } + + box_end($b, $box); + } +}; + +$box{'popfaq'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $b = $opts->{'body'}; + + box_start($b, $box, { 'title' => BML::ml('portal.popfaq.portaltitle'), + 'align' => "left", + 'url' => '/support/faqpop.bml', }); + my $dbr = LJ::get_db_reader(); + + my $sth = $dbr->prepare("SELECT f.faqid, f.question, s.statval AS 'uses' ". + "FROM faq f, stats s WHERE f.faqcat<>'int-abuse' AND s.statcat='popfaq' ". + "AND s.statkey=f.faqid ORDER BY s.statval DESC LIMIT 10"); + $sth->execute; + + $$b .= "
      "; + while (my $f = $sth->fetchrow_hashref) + { + my $q = LJ::ehtml($f->{'question'}); + $q =~ s/^\s+//; $q =~ s/\s+$//; + $q =~ s/\n/
      /g; + $$b .= "
    • {'faqid'}\">$q ($f->{'uses'})
    • \n"; + } + $$b .= "
    \n"; + box_end($b, $box); + }, +}; + +############################################################################ + +$box{'memories'} = +{ + 'name' => '', + 'small' => 1, + 'large' => 0, + 'handler' => sub { + my ($remote, $opts, $box) = @_; + my $dbr = LJ::get_db_reader(); + my $b = $opts->{'body'}; + + box_start($b, $box, { 'title' => BML::ml('portal.memories.portaltitle'), + 'url' => '/tools/memories.bml', }); + + my $userid = $remote->{'userid'}; + my $kws = LJ::Memories::get_keywords($remote); + my $kwcs = LJ::Memories::get_keyword_counts($remote); + my $rows = 0; + foreach my $id (sort { $kwcs->{$a} <=> $kwcs->{$b} } keys %{$kwcs || {}}) + { + $$b .= "
      " if ++$rows == 1; + my $noun = $kwcs->{$id} == 1 ? BML::ml('portal.memories.entrynoun') : BML::ml('portal.memories.entriesnoun'); + my $ue_keyword = LJ::eurl($kws->{$id}); + my $keyword = $kws->{$id}; + LJ::text_out(\$keyword); + if ($keyword eq "*") { $keyword = BML::ml('/tools/memories.bml.uncategorized'); } + $$b .= "
    • {'user'}&keyword=$ue_keyword&filter=all\">"; + $$b .= "$keyword: $kwcs->{$id} $noun
    • \n"; + } + unless ($rows) { + $$b .= " h1?>"; + $$b .= " p?>"; + } else { + $$b .= "
    "; + } + box_end($b, $box); + } +}; + +1; diff --git a/livejournal/cgi-bin/propparse.pl b/livejournal/cgi-bin/propparse.pl new file mode 100755 index 0000000..19890cf --- /dev/null +++ b/livejournal/cgi-bin/propparse.pl @@ -0,0 +1,167 @@ +#!/usr/bin/perl +# + +package LJ; + +$verbose = 0; +@obs = (); + +sub load_objects_from_file +{ + my ($file, $oblist) = @_; + + # hard-code these common (er, only) cases + if ($file eq "views.dat" || $file eq "vars.dat") { + $file = "$LJ::HOME/doc/raw/s1/$file"; + } + + open (FIL, $file); + load_objects(\*FIL, $oblist); + close FIL; +} + +sub load_objects +{ + my ($fh, $oblist) = @_; + my $l; + + while ($l = <$fh>) + { + chomp $l; + next unless ($l =~ /\S/); + next if ($l =~ /^\#/); + if ($l =~ /^\{\s*(\S+)\s*$/) + { + &load_object($fh, $1, $oblist); + } + else + { + print STDERR "Unexpected line: $l\n"; + } + } +} + +sub load_object +{ + my ($fh, $obname, $listref) = @_; + my $var = ""; + my $vartype = ""; + my $ob = { name => $obname, props => {} }; + my $l; + + print "Loading object $obname ... \n" if $verbose; + SUCKLINES: + while ($l = <$fh>) + { + chomp $l; + if ($l =~ /^\.(\S+)\s*$/) + { + $var = $1; + print "current var = $var\n" if $verbose; + next SUCKLINES; + } + if ($l =~ /^\}\s*$/) + { + print "End object $obname.\n" if $verbose; + last SUCKLINES; + } + next unless $var; + next unless ($l =~ /\S/); + next if ($l =~ /^\#/); + + if ($l =~ /^\{\s*(\S+)\s*$/) + { + print "Encounted object ($1) as property.\n" if $verbose; + if (defined $ob->{'props'}->{$var}) + { + if (ref $ob->{'props'}->{$var} ne "ARRAY") + { + print STDERR "Object encountered where text expected.\n"; + my $blah = []; + &load_object($fh, "blah", $blah); # ignore object + } + else + { + &load_object($fh, $1, $ob->{'props'}->{$var}); + } + } + else + { + $ob->{'props'}->{$var} = []; + &load_object($fh, $1, $ob->{'props'}->{$var}); + } + } + else + { + print "Normal line.\n" if $verbose; + if (defined $ob->{'props'}->{$var}) + { + print "defined.\n" if $verbose; + if (ref $ob->{'props'}->{$var} eq "ARRAY") + { + print STDERR "Scalar found where object expected!\n"; + } + else + { + print "appending var \"$var\".\n" if $verbose; + $ob->{'props'}->{$var} .= "\n$l"; + } + } + else + { + print "setting $var to $l\n" if $verbose; + $ob->{'props'}->{$var} = $l; + } + } + + } # end while + print "done loading object $obname\n" if $verbose; + + push @{$listref}, $ob; + +} # end sub + +sub xlinkify +{ + my ($a) = $_[0]; + $$a =~ s/\[var\[([A-Z0-9\_]{2,})\]\]/$1<\/a>/g; + $$a =~ s/\[view\[(\S+?)\]\]/$1<\/a>/g; +} + +sub dump_struct +{ + my ($ref, $depth) = @_; + my $type = ref $ref; + my $indent = " "x$depth; + if ($type eq "ARRAY") + { + print "ARRAY\n"; + my $count = 0; + foreach (@{$ref}) + { + print $indent, "[$count] = "; + &dump_struct($_, $depth+1); + $count++; + } + } + elsif ($type eq "HASH") + { + print "HASH\n"; + my $k; + foreach $k (sort keys %{$ref}) + { + print $indent, "{$k} = "; + &dump_struct($ref->{$k}, $depth+1); + } + } + elsif ($type eq "") + { + print $ref, "\n"; + } + else + { + print $indent, "UNKNOWN_TYPE"; + } +} + +1; diff --git a/livejournal/cgi-bin/redirect.dat b/livejournal/cgi-bin/redirect.dat new file mode 100755 index 0000000..503fe5a --- /dev/null +++ b/livejournal/cgi-bin/redirect.dat @@ -0,0 +1,24 @@ +/community.bml /community/ +/communities /community/ +/support.bml /support/ +/addfriend.bml /friends/add.bml +/editfriendgroups.bml /friends/editgroups.bml +/editfriends.bml /friends/edit.bml +/editfriends_do.bml /friends/edit_do.bml +/friendgraph.bml /friends/graph.bml +/friendsfilter.bml /friends/filter.bml +/createstyle.bml /styles/create.bml +/editstyle.bml /styles/edit.bml +/stylebrowser /styles/browse/ +/friendgraph.bml /friends/graph.bml +/textmessage.bml /tools/textmessage.bml +/memories.bml /tools/memories.bml +/memadd.bml /tools/memadd.bml +/faq.bml /support/faq.bml +/faqbrowse.bml /support/faqbrowse.bml +/setscheme.bml /manage/siteopts.bml +/setlang.bml /manage/siteopts.bml +/uploadpic.bml /editpics.bml +/uploadpic_do.bml /editpics.bml +/modify_do.bml /modify.bml +/editjournal_do.bml /editjournal.bml diff --git a/livejournal/cgi-bin/statslib.pl b/livejournal/cgi-bin/statslib.pl new file mode 100755 index 0000000..1e7f950 --- /dev/null +++ b/livejournal/cgi-bin/statslib.pl @@ -0,0 +1,285 @@ +#!/usr/bin/perl + +# +# Partial Stats +# + +use strict; + +package LJ::Stats; + +%LJ::Stats::INFO = ( + # jobname => { type => 'global' || 'clustered', + # jobname => jobname + # statname => statname || [statname1, statname2] + # handler => sub {}, + # max_age => age } + ); + +sub LJ::Stats::register_stat { + my $stat = shift; + return undef unless ref $stat eq 'HASH'; + + $stat->{'type'} = $stat->{'type'} eq 'clustered' ? 'clustered' : 'global'; + return undef unless $stat->{'jobname'}; + $stat->{'statname'} ||= $stat->{'jobname'}; + return undef unless ref $stat->{'handler'} eq 'CODE'; + delete $stat->{'max_age'} unless $stat->{'max_age'} > 0; + + # register in master INFO hash + $LJ::Stats::INFO{$stat->{'jobname'}} = $stat; + + return 1; +}; + +sub LJ::Stats::run_stats { + my @stats = @_ ? @_ : sort keys %LJ::Stats::INFO; + + foreach my $jobname (@stats) { + + my $stat = $LJ::Stats::INFO{$jobname}; + + # stats calculated on global db reader + if ($stat->{'type'} eq "global") { + unless (LJ::Stats::need_calc($jobname)) { + print "-I- Up-to-date: $jobname\n"; + next; + } + + # rather than passing an actual db handle to the stat handler, + # just pass a getter subef so it can be revalidated as necessary + my $dbr_getter = sub { + return LJ::Stats::get_db("dbr") + or die "Can't get db reader handle."; + }; + + print "-I- Running: $jobname\n"; + + my $res = $stat->{'handler'}->($dbr_getter); + die "Error running '$jobname' handler on global reader." + unless $res; + + # 2 cases: + # - 'statname' is an arrayref, %res structure is ( 'statname' => { 'arg' => 'val' } ) + # - 'statname' is scalar, %res structure is ( 'arg' => 'val' ) + { + if (ref $stat->{'statname'} eq 'ARRAY') { + foreach my $statname (@{$stat->{'statname'}}) { + foreach my $key (keys %{$res->{$statname}}) { + LJ::Stats::save_stat($statname, $key, $res->{$statname}->{$key}); + } + } + } else { + my $statname = $stat->{'statname'}; + foreach my $key (keys %$res) { + LJ::Stats::save_stat($statname, $key, $res->{$key}); + } + } + } + + LJ::Stats::save_calc($jobname); + + next; + } + + # stats calculated per-cluster + if ($stat->{'type'} eq "clustered") { + + foreach my $cid (@LJ::CLUSTERS) { + unless (LJ::Stats::need_calc($jobname, $cid)) { + print "-I- Up-to-date: $jobname, cluster $cid\n"; + next; + } + + # pass a dbcr getter subref so the stat handler knows how + # to revalidate its database handles, by invoking this closure + my $dbcr_getter = sub { + return LJ::Stats::get_db("dbcr", $cid) + or die "Can't get cluster $cid db handle."; + }; + + print "-I- Running: $jobname, cluster $cid\n"; + + my $res = $stat->{'handler'}->($dbcr_getter, $cid); + die "Error running '$jobname' handler on cluster $cid." + unless $res; + + # 2 cases: + # - 'statname' is an arrayref, %res structure is ( 'statname' => { 'arg' => 'val' } ) + # - 'statname' is scalar, %res structure is ( 'arg' => 'val' ) + { + if (ref $stat->{'statname'} eq 'ARRAY') { + foreach my $statname (@{$stat->{'statname'}}) { + foreach my $key (keys %{$res->{$statname}}) { + LJ::Stats::save_part($statname, $cid, $key, $res->{$statname}->{$key}); + } + } + } else { + my $statname = $stat->{'statname'}; + foreach my $key (keys %$res) { + LJ::Stats::save_part($statname, $cid, $key, $res->{$key}); + } + } + } + + LJ::Stats::save_calc($jobname, $cid); + } + + # save the summation(s) of the statname(s) we found above + if (ref $stat->{'statname'} eq 'ARRAY') { + foreach my $statname (@{$stat->{'statname'}}) { + LJ::Stats::save_sum($statname); + } + } else { + LJ::Stats::save_sum($stat->{'statname'}); + } + } + + } + + return 1; +}; + +# get raw dbr/dbh/cluster handle +sub LJ::Stats::get_db { + my $type = shift; + return undef unless $type; + my $cid = shift; + + # tell DBI to revalidate connections before returning them + $LJ::DBIRole->clear_req_cache(); + + my $opts = {raw=>1,nocache=>1}; # get_dbh opts + + # global handles + if ($type eq "dbr") { + my @roles = $LJ::STATS_FORCE_SLOW ? ("slow") : ("slave", "master"); + + my $db = LJ::get_dbh($opts, @roles); + return $db if $db; + + # don't fall back to slave/master if STATS_FORCE_SLOW is on + die "ERROR: Could not get handle for slow database role\n" + if $LJ::STATS_FORCE_SLOW; + + return undef; + } + + return LJ::get_dbh($opts, 'master') + if $type eq "dbh"; + + # cluster handles + return undef unless $cid > 0; + return LJ::get_cluster_def_reader($opts, $cid) + if $type eq "dbcm" || $type eq "dbcr"; + + return undef; +} + +# save a given stat to the 'stats' table in the db +sub LJ::Stats::save_stat { + my ($cat, $statkey, $val) = @_; + return undef unless $cat && $statkey && $val; + + # replace/insert stats row + my $dbh = LJ::Stats::get_db("dbh"); + $dbh->do("REPLACE INTO stats (statcat, statkey, statval) VALUES (?, ?, ?)", + undef, $cat, $statkey, $val); + die $dbh->errstr if $dbh->err; + + return 1; +} + +# note the last calctime of a given stat +sub LJ::Stats::save_calc { + my ($jobname, $cid) = @_; + return unless $jobname; + + my $dbh = LJ::Stats::get_db("dbh"); + $dbh->do("REPLACE INTO partialstats (jobname, clusterid, calctime) " . + "VALUES (?,?,UNIX_TIMESTAMP())", undef, $jobname, $cid || 1); + die $dbh->errstr if $dbh->err; + + return 1; +} + +# save partial stats +sub LJ::Stats::save_part { + my ($statname, $cid, $arg, $value) = @_; + return undef unless $statname && $cid > 0; + + # replace/insert partialstats(data) row + my $dbh = LJ::Stats::get_db("dbh"); + $dbh->do("REPLACE INTO partialstatsdata (statname, arg, clusterid, value) " . + "VALUES (?,?,?,?)", undef, $statname, $arg, $cid, $value); + die $dbh->errstr if $dbh->err; + + return 1; +}; + +# see if a given stat is stale +sub LJ::Stats::need_calc { + my ($jobname, $cid) = @_; + return undef unless $jobname; + + my $dbr = LJ::Stats::get_db("dbr"); + my $calctime = $dbr->selectrow_array("SELECT calctime FROM partialstats " . + "WHERE jobname=? AND clusterid=?", + undef, $jobname, $cid || 1); + + my $max = $LJ::Stats::INFO{$jobname}->{'max_age'} || 3600*6; # 6 hours default + return ($calctime < time() - $max); +} + +# sum up counts for all clusters +sub LJ::Stats::save_sum { + my $statname = shift; + return undef unless $statname; + + # get sum of this stat for all clusters + my $dbr = LJ::Stats::get_db("dbr"); + my $sth = $dbr->prepare("SELECT arg, SUM(value) FROM partialstatsdata " . + "WHERE statname=? GROUP BY 1"); + $sth->execute($statname); + while (my ($arg, $count) = $sth->fetchrow_array) { + next unless $count; + LJ::Stats::save_stat($statname, $arg, $count); + } + + return 1; +} + +# get number of pages, given a total row count +sub LJ::Stats::num_blocks { + my $row_tot = shift; + return 0 unless $row_tot; + + return int($row_tot / $LJ::STATS_BLOCK_SIZE) + (($row_tot % $LJ::STATS_BLOCK_SIZE) ? 1 : 0); +} + +# get low/high ids for a BETWEEN query based on page number +sub LJ::Stats::get_block_bounds { + my ($block, $offset) = @_; + return ($offset+0, $offset+$LJ::Stats::BLOCK_SIZE) unless $block; + + # calculate min, then add one to not overlap previous max, + # unless there was no previous max so we set to 0 so we don't + # miss rows with id=0 + my $min = ($block-1)*$LJ::STATS_BLOCK_SIZE + 1; + $min = $min == 1 ? 0 : $min; + + return ($offset+$min, $offset+$block*$LJ::STATS_BLOCK_SIZE); +} + +sub LJ::Stats::block_status_line { + my ($block, $total) = @_; + return "" unless $LJ::Stats::VERBOSE; + return "" if $total == 1; # who cares about percentage for one block? + + # status line gets called AFTER work is done, so we show percentage + # for $block+1, that way the final line displays 100% + my $pct = sprintf("%.2f", 100*($block / ($total || 1))); + return " [$pct%] Processing block $block of $total.\n"; +} + +1; diff --git a/livejournal/cgi-bin/supportlib.pl b/livejournal/cgi-bin/supportlib.pl new file mode 100755 index 0000000..c1a8f85 --- /dev/null +++ b/livejournal/cgi-bin/supportlib.pl @@ -0,0 +1,742 @@ +#!/usr/bin/perl +# + +package LJ::Support; + +use strict; +use Digest::MD5 qw(md5_hex); + +require "$ENV{'LJHOME'}/cgi-bin/sysban.pl"; + +## pass $id of zero or blank to get all categories +sub load_cats +{ + my ($id) = @_; + my $hashref = {}; + $id += 0; + my $where = $id ? "WHERE spcatid=$id" : ""; + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT * FROM supportcat $where"); + $sth->execute; + $hashref->{$_->{'spcatid'}} = $_ while ($_ = $sth->fetchrow_hashref); + return $hashref; +} + +sub load_email_to_cat_map +{ + my $map = {}; + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT * FROM supportcat ORDER BY sortorder DESC"); + $sth->execute; + while (my $sp = $sth->fetchrow_hashref) { + next unless ($sp->{'replyaddress'}); + $map->{$sp->{'replyaddress'}} = $sp; + } + return $map; +} + +sub calc_points +{ + my ($sp, $secs) = @_; + my $base = $sp->{_cat}->{'basepoints'}; + $secs = int($secs / (3600*6)); + my $total = ($base + $secs); + if ($total > 10) { $total = 10; } + $total ||= 1; + return $total; +} + +sub init_remote +{ + my $remote = shift; + return unless $remote; + LJ::load_user_privs($remote, + qw(supportclose supporthelp + supportdelete supportread + supportviewinternal supportmakeinternal + supportmovetouch supportviewscreened + supportchangesummary)); +} + +# given all the categories, maps a catkey into a cat +sub get_cat_by_key +{ + my ($cats, $cat) = @_; + foreach (keys %$cats) { + if ($cats->{$_}->{'catkey'} eq $cat) { + return $cats->{$_}; + } + } + return undef; +} + +sub filter_cats +{ + my $remote = shift; + my $cats = shift; + + return grep { + can_read_cat($_, $remote); + } sorted_cats($cats); +} + +sub sorted_cats +{ + my $cats = shift; + return sort { $a->{'catname'} cmp $b->{'catname'} } values %$cats; +} + +# takes raw support request record and puts category info in it +# so it can be used in other functions like can_* +sub fill_request_with_cat +{ + my ($sp, $cats) = @_; + $sp->{_cat} = $cats->{$sp->{'spcatid'}}; +} + +sub is_poster +{ + my ($sp, $remote, $auth) = @_; + + # special case with non-logged in requesters that use miniauth + if ($auth && $auth eq mini_auth($sp)) { + return 1; + } + return 0 unless $remote; + + if ($sp->{'reqtype'} eq "email") { + if ($remote->{'email'} eq $sp->{'reqemail'} && $remote->{'status'} eq "A") { + return 1; + } + } elsif ($sp->{'reqtype'} eq "user") { + if ($remote->{'userid'} eq $sp->{'requserid'}) { return 1; } + } + return 0; +} + +sub can_see_helper +{ + my ($sp, $remote) = @_; + if ($sp->{_cat}->{'hide_helpers'}) { + if (can_help($sp, $remote)) { + return 1; + } + if (LJ::check_priv($remote, "supportviewinternal", $sp->{_cat}->{'catkey'})) { + return 1; + } + if (LJ::check_priv($remote, "supportviewscreened", $sp->{_cat}->{'catkey'})) { + return 1; + } + return 0; + } + return 1; +} + +sub can_read +{ + my ($sp, $remote, $auth) = @_; + return (is_poster($sp, $remote, $auth) || + can_read_cat($sp->{_cat}, $remote)); +} + +sub can_read_cat +{ + my ($cat, $remote) = @_; + return unless ($cat); + return ($cat->{'public_read'} || + LJ::check_priv($remote, "supportread", $cat->{'catkey'})); +} + +sub can_bounce +{ + my ($sp, $remote) = @_; + if ($sp->{_cat}->{'public_read'}) { + if (LJ::check_priv($remote, "supportclose", "")) { return 1; } + } + my $catkey = $sp->{_cat}->{'catkey'}; + if (LJ::check_priv($remote, "supportclose", $catkey)) { return 1; } + return 0; +} + +sub can_lock +{ + my ($sp, $remote) = @_; + return 1 if $sp->{_cat}->{public_read} && LJ::check_priv($remote, 'supportclose', ''); + return 1 if LJ::check_priv($remote, 'supportclose', $sp->{_cat}->{catkey}); + return 0; +} + +sub can_close +{ + my ($sp, $remote, $auth) = @_; + if (is_poster($sp, $remote, $auth)) { return 1; } + if ($sp->{_cat}->{'public_read'}) { + if (LJ::check_priv($remote, "supportclose", "")) { return 1; } + } + my $catkey = $sp->{_cat}->{'catkey'}; + if (LJ::check_priv($remote, "supportclose", $catkey)) { return 1; } + return 0; +} + +sub can_append +{ + my ($sp, $remote, $auth) = @_; + if (is_poster($sp, $remote, $auth)) { return 1; } + return 0 unless $remote; + return 0 unless $remote->{'statusvis'} eq "V"; + if ($sp->{_cat}->{'allow_screened'}) { return 1; } + if (can_help($sp, $remote)) { return 1; } + return 0; +} + +sub is_locked +{ + my $sp = shift; + my $spid = ref $sp ? $sp->{spid} : $sp+0; + return undef unless $spid; + my $props = LJ::Support::load_props($spid); + return $props->{locked} ? 1 : 0; +} + +sub lock +{ + my $sp = shift; + my $spid = ref $sp ? $sp->{spid} : $sp+0; + return undef unless $spid; + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO supportprop (spid, prop, value) VALUES (?, 'locked', 1)", undef, $spid); +} + +sub unlock +{ + my $sp = shift; + my $spid = ref $sp ? $sp->{spid} : $sp+0; + return undef unless $spid; + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM supportprop WHERE spid = ? AND prop = 'locked'", undef, $spid); +} + +# privilege policy: +# supporthelp with no argument gives you all abilities in all public_read categories +# supporthelp with a catkey arg gives you all abilities in that non-public_read category +# supportread with a catkey arg is required to view requests in a non-public_read category +# all other privs work like: +# no argument = global, where category is public_read or user has supportread on that category +# argument = local, priv applies in that category only if it's public or user has supportread +sub support_check_priv +{ + my ($sp, $remote, $priv) = @_; + return 1 if can_help($sp, $remote); + return 0 unless can_read_cat($sp->{_cat}, $remote); + return 1 if LJ::check_priv($remote, $priv, '') && $sp->{_cat}->{public_read}; + return 1 if LJ::check_priv($remote, $priv, $sp->{_cat}->{catkey}); + return 0; +} + +# can they read internal comments? if they're a helper or have +# extended supportread (with a plus sign at the end of the category key) +sub can_read_internal +{ + my ($sp, $remote) = @_; + return 1 if LJ::Support::support_check_priv($sp, $remote, 'supportviewinternal'); + return 1 if LJ::check_priv($remote, "supportread", $sp->{_cat}->{catkey}."+"); + return 0; +} + +sub can_make_internal +{ + return LJ::Support::support_check_priv(@_, 'supportmakeinternal'); +} + +sub can_read_screened +{ + return LJ::Support::support_check_priv(@_, 'supportviewscreened'); +} + +sub can_perform_actions +{ + return LJ::Support::support_check_priv(@_, 'supportmovetouch'); +} + +sub can_change_summary +{ + return LJ::Support::support_check_priv(@_, 'supportchangesummary'); +} + +sub can_help +{ + my ($sp, $remote) = @_; + if ($sp->{_cat}->{'public_read'}) { + if ($sp->{_cat}->{'public_help'}) { + return 1; + } + if (LJ::check_priv($remote, "supporthelp", "")) { return 1; } + } + my $catkey = $sp->{_cat}->{'catkey'}; + if (LJ::check_priv($remote, "supporthelp", $catkey)) { return 1; } + return 0; +} + +sub load_props +{ + my $spid = shift; + return unless $spid; + + my %props = (); # prop => value + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT prop, value FROM supportprop WHERE spid=?"); + $sth->execute($spid); + while (my ($prop, $value) = $sth->fetchrow_array) { + $props{$prop} = $value; + } + + return \%props; +} + +# $loadreq is used by /abuse/report.bml and +# ljcmdbuffer.pl to signify that the full request +# should not be loaded. To simplify code going live, +# Whitaker and I decided to not try and merge it +# into the new $opts hash. + +# $opts->{'db_force'} loads the request from a +# global master. Needed to prevent a race condition +# where the request may not have replicated to slaves +# in the time needed to load an auth code. + +sub load_request +{ + my ($spid, $loadreq, $opts) = @_; + my $sth; + + $spid += 0; + + # load the support request + my $db = $opts->{'db_force'} ? LJ::get_db_writer() : LJ::get_db_reader(); + + $sth = $db->prepare("SELECT * FROM support WHERE spid=$spid"); + $sth->execute; + my $sp = $sth->fetchrow_hashref; + + return undef unless $sp; + + # load the category the support requst is in + $sth = $db->prepare("SELECT * FROM supportcat WHERE spcatid=$sp->{'spcatid'}"); + $sth->execute; + $sp->{_cat} = $sth->fetchrow_hashref; + + # now load the user's request text, if necessary + if ($loadreq) { + $sp->{body} = $db->selectrow_array("SELECT message FROM supportlog WHERE spid = ? AND type = 'req'", + undef, $sp->{spid}); + } + + return $sp; +} + +sub load_response +{ + my $splid = shift; + my $sth; + + $splid += 0; + + # load the support request + my $dbh = LJ::get_db_writer(); + $sth = $dbh->prepare("SELECT * FROM supportlog WHERE splid=$splid"); + $sth->execute; + my $res = $sth->fetchrow_hashref; + + return $res; +} + +sub get_answer_types +{ + my ($sp, $remote, $auth) = @_; + my @ans_type; + + if (is_poster($sp, $remote, $auth)) { + push @ans_type, ("comment", "More information"); + return @ans_type; + } + + if (can_help($sp, $remote)) { + push @ans_type, ("screened" => "Screened Response", + "answer" => "Answer", + "comment" => "Comment or Question"); + } elsif ($sp->{_cat}->{'allow_screened'}) { + push @ans_type, ("screened" => "Screened Response"); + } + + if (can_make_internal($sp, $remote) && + ! $sp->{_cat}->{'public_help'}) + { + push @ans_type, ("internal" => "Internal Comment / Action"); + } + + if (can_bounce($sp, $remote)) { + push @ans_type, ("bounce" => "Bounce to Email & Close"); + } + + return @ans_type; +} + +sub file_request +{ + my $errors = shift; + my $o = shift; + + my $email = $o->{'reqtype'} eq "email" ? $o->{'reqemail'} : ""; + my $log = { 'uniq' => $o->{'uniq'}, + 'email' => $email }; + my $userid = 0; + + unless ($email) { + if ($o->{'reqtype'} eq "user") { + my $u = LJ::load_userid($o->{'requserid'}); + $userid = $u->{'userid'}; + + $log->{'user'} = $u->{'user'}; + $log->{'email'} = $u->{'email'}; + + if (LJ::sysban_check('support_user', $u->{'user'})) { + return LJ::sysban_block($userid, "Support request blocked based on user", $log); + } + + $email = $u->{'email'}; + } + } + + if (LJ::sysban_check('support_email', $email)) { + return LJ::sysban_block($userid, "Support request blocked based on email", $log); + } + if (LJ::sysban_check('support_uniq', $o->{'uniq'})) { + return LJ::sysban_block($userid, "Support request blocked based on uniq", $log); + } + + my $reqsubject = LJ::trim($o->{'subject'}); + my $reqbody = LJ::trim($o->{'body'}); + + unless ($reqsubject) { + push @$errors, "You must enter a problem summary."; + } + unless ($reqbody) { + push @$errors, "You did not enter a support request."; + } + + my $cats = LJ::Support::load_cats(); + push @$errors, "Invalid support category" unless $cats->{$o->{'spcatid'}+0}; + + if (@$errors) { return 0; } + + my $dbh = LJ::get_db_writer(); + + my $dup_id = 0; + my $qsubject = $dbh->quote($reqsubject); + my $qbody = $dbh->quote($reqbody); + my $qreqtype = $dbh->quote($o->{'reqtype'}); + my $qrequserid = $o->{'requserid'}+0; + my $qreqname = $dbh->quote($o->{'reqname'}); + my $qreqemail = $dbh->quote($o->{'reqemail'}); + my $qspcatid = $o->{'spcatid'}+0; + + my $scat = $cats->{$qspcatid}; + + # make the authcode + my $authcode = LJ::make_auth_code(15); + my $qauthcode = $dbh->quote($authcode); + + my $md5 = md5_hex("$qreqname$qreqemail$qsubject$qbody"); + my $sth; + + $dbh->do("LOCK TABLES support WRITE, duplock WRITE"); + $sth = $dbh->prepare("SELECT dupid FROM duplock WHERE realm='support' AND reid=0 AND userid=$qrequserid AND digest='$md5'"); + $sth->execute; + ($dup_id) = $sth->fetchrow_array; + if ($dup_id) { + $dbh->do("UNLOCK TABLES"); + return $dup_id; + } + + my ($urlauth, $url, $spid); # used at the bottom + + my $sql = "INSERT INTO support (spid, reqtype, requserid, reqname, reqemail, state, authcode, spcatid, subject, timecreate, timetouched, timeclosed, timelasthelp) VALUES (NULL, $qreqtype, $qrequserid, $qreqname, $qreqemail, 'open', $qauthcode, $qspcatid, $qsubject, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0, 0)"; + $sth = $dbh->prepare($sql); + $sth->execute; + + if ($dbh->err) { + my $error = $dbh->errstr; + $dbh->do("UNLOCK TABLES"); + push @$errors, "Database error: (report this)
    $error"; + return 0; + } + $spid = $dbh->{'mysql_insertid'}; + + $dbh->do("INSERT INTO duplock (realm, reid, userid, digest, dupid, instime) VALUES ('support', 0, $qrequserid, '$md5', $spid, NOW())"); + $dbh->do("UNLOCK TABLES"); + + unless ($spid) { + push @$errors, "Database error: (report this)
    Didn't get a spid."; + return 0; + } + + # save meta-data for this request + my @data; + my $add_data = sub { + my $q = $dbh->quote($_[1]); + return unless $q && $q ne 'NULL'; + push @data, "($spid, '$_[0]', $q)"; + }; + $add_data->($_, $o->{$_}) foreach qw(uniq useragent); + $dbh->do("INSERT INTO supportprop (spid, prop, value) VALUES " . join(',', @data)); + + $dbh->do("INSERT INTO supportlog (splid, spid, timelogged, type, faqid, userid, message) ". + "VALUES (NULL, $spid, UNIX_TIMESTAMP(), 'req', 0, $qrequserid, $qbody)"); + + my $body; + my $miniauth = mini_auth({ 'authcode' => $authcode }); + $url = "$LJ::SITEROOT/support/see_request.bml?id=$spid"; + $urlauth = "$url&auth=$miniauth"; + + $body = "Your $LJ::SITENAME support request regarding \"$o->{'subject'}\" has been filed and will be answered as soon as possible. Your request tracking number is $spid.\n\n"; + $body .= "You can track your request's progress or add information here:\n\n "; + $body .= $urlauth; + $body .= "\n\nIf you figure out the problem before somebody gets back to you, please cancel your request by clicking this:\n\n "; + $body .= "$LJ::SITEROOT/support/act.bml?close;$spid;$authcode"; + + unless ($scat->{'no_autoreply'}) + { + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::BOGUS_EMAIL, + 'fromname' => "$LJ::SITENAME Support", + 'charset' => 'utf-8', + 'subject' => "Support Request \#$spid", + 'body' => $body + }); + } + + # attempt to buffer job to send email (but don't care if it fails) + LJ::do_to_cluster(sub { + # first parameter is cluster id + return LJ::cmd_buffer_add(shift(@_), 0, 'support_notify', { spid => $spid, type => 'new' }); + }); + + # and we're done + return $spid; +} + +sub append_request +{ + my $sp = shift; # support request to be appended to. + my $re = shift; # hashref of attributes of response to be appended + my $sth; + + # $re->{'body'} + # $re->{'type'} (req, answer, comment, internal, screened) + # $re->{'faqid'} + # $re->{'remote'} (remote if known) + # $re->{'uniq'} (uniq of remote) + + my $remote = $re->{'remote'}; + my $posterid = $remote ? $remote->{'userid'} : 0; + + # check for a sysban + my $log = { 'uniq' => $re->{'uniq'} }; + if ($remote) { + + $log->{'user'} = $remote->{'user'}; + $log->{'email'} = $remote->{'email'}; + + if (LJ::sysban_check('support_user', $remote->{'user'})) { + return LJ::sysban_block($remote->{'userid'}, "Support request blocked based on user", $log); + } + if (LJ::sysban_check('support_email', $remote->{'email'})) { + return LJ::sysban_block($remote->{'userid'}, "Support request blocked based on email", $log); + } + } + + if (LJ::sysban_check('support_uniq', $re->{'uniq'})) { + my $userid = $remote ? $remote->{'userid'} : 0; + return LJ::sysban_block($userid, "Support request blocked based on uniq", $log); + } + + my $message = $re->{'body'}; + $message =~ s/^\s+//; + $message =~ s/\s+$//; + + my $dbh = LJ::get_db_writer(); + + my $qmessage = $dbh->quote($message); + my $qtype = $dbh->quote($re->{'type'}); + + my $qfaqid = $re->{'faqid'}+0; + my $quserid = $posterid+0; + my $spid = $sp->{'spid'}+0; + + my $sql = "INSERT INTO supportlog (splid, spid, timelogged, type, faqid, userid, message) VALUES (NULL, $spid, UNIX_TIMESTAMP(), $qtype, $qfaqid, $quserid, $qmessage)"; + $dbh->do($sql); + my $splid = $dbh->{'mysql_insertid'}; + + if ($posterid) { + # add to our index of recently replied to support requests per-user. + $dbh->do("INSERT IGNORE INTO support_youreplied (userid, spid) VALUES (?, ?)", undef, + $posterid, $spid); + die $dbh->errstr if $dbh->err; + + # and also lazily clean out old stuff: + $sth = $dbh->prepare("SELECT s.spid FROM support s, support_youreplied yr ". + "WHERE yr.userid=? AND yr.spid=s.spid AND s.state='closed' ". + "AND s.timeclosed < UNIX_TIMESTAMP() - 3600*72"); + $sth->execute($posterid); + my @to_del; + push @to_del, $_ while ($_) = $sth->fetchrow_array; + if (@to_del) { + my $in = join(", ", map { $_ + 0 } @to_del); + $dbh->do("DELETE FROM support_youreplied WHERE userid=? AND spid IN ($in)", + undef, $posterid); + } + } + + # attempt to buffer job to send email (but don't care if it fails) + LJ::do_to_cluster(sub { + # first parameter is cluster id + return LJ::cmd_buffer_add(shift(@_), 0, 'support_notify', { spid => $spid, splid => $splid, type => 'update' }); + }); + + return $splid; +} + +# userid may be undef/0 in the setting to zero case +sub set_points +{ + my ($spid, $userid, $points) = @_; + + my $dbh = LJ::get_db_writer(); + if ($points) { + $dbh->do("REPLACE INTO supportpoints (spid, userid, points) ". + "VALUES (?,?,?)", undef, $spid, $userid, $points); + } else { + $userid ||= $dbh->selectrow_array("SELECT userid FROM supportpoints WHERE spid=?", + undef, $spid); + $dbh->do("DELETE FROM supportpoints WHERE spid=?", undef, $spid); + } + + $dbh->do("REPLACE INTO supportpointsum (userid, totpoints, lastupdate) ". + "SELECT userid, SUM(points), UNIX_TIMESTAMP() FROM supportpoints ". + "WHERE userid=? GROUP BY 1", undef, $userid) if $userid; +} + +sub touch_request +{ + my ($spid) = @_; + + # no touching if the request is locked + return 0 if LJ::Support::is_locked($spid); + + my $dbh = LJ::get_db_writer(); + + $dbh->do("UPDATE support". + " SET state='open', timeclosed=0, timetouched=UNIX_TIMESTAMP()". + " WHERE spid=?", + undef, $spid) + or return 0; + + set_points($spid, undef, 0); + + return 1; +} + +sub mail_response_to_user +{ + my $sp = shift; + my $splid = shift; + + $splid += 0; + + my $res = load_response($splid); + + my $email; + if ($sp->{'reqtype'} eq "email") { + $email = $sp->{'reqemail'}; + } else { + my $u = LJ::load_userid($sp->{'requserid'}); + $email = $u->{'email'}; + } + + my $spid = $sp->{'spid'}+0; + my $faqid = $res->{'faqid'}+0; + + my $type = $res->{'type'}; + + # don't mail internal comments (user shouldn't see) or + # screened responses (have to wait for somebody to approve it first) + return if ($type eq "internal" || $type eq "screened"); + + # the only way it can be zero is if it's a reply to an email, so it's + # problem the person replying to their own request, so we don't want + # to mail them: + return unless ($res->{'userid'}); + + # also, don't send them their own replies: + return if ($sp->{'requserid'} == $res->{'userid'}); + + my $body = ""; + my $dbh = LJ::get_db_writer(); + my $what = $type eq "answer" ? "an answer to" : "a comment on"; + $body .= "Below is $what your support question regarding \"$sp->{'subject'}\"\n"; + + my $miniauth = mini_auth($sp); + $body .= "($LJ::SITEROOT/support/see_request.bml?id=$spid&auth=$miniauth).\n\n"; + + $body .= "="x70 . "\n\n"; + if ($faqid) { + my $faqname = ""; + my $sth = $dbh->prepare("SELECT question FROM faq WHERE faqid=$faqid"); + $sth->execute; + ($faqname) = $sth->fetchrow_array; + if ($faqname) { + $body .= "FAQ REFERENCE: $faqname\n"; + $body .= "$LJ::SITEROOT/support/faqbrowse.bml?faqid=$faqid"; + $body .= "\n\n"; + } + } + + $body .= "$res->{'message'}\n\nDid this answer your question?\nYES:\n"; + + $body .= "$LJ::SITEROOT/support/act.bml?close;$spid;$sp->{'authcode'}"; + $body .= ";$splid" if $type eq "answer"; + $body .= "\nNO:\n$LJ::SITEROOT/support/see_request.bml?id=$spid&auth=$miniauth\n\n"; + $body .= "If you are having problems using any of the links in this email, please try copying and pasting the *entire* link into your browser's address bar rather than clicking on it."; + + my $fromemail = $LJ::BOGUS_EMAIL; + if ($sp->{_cat}->{'replyaddress'}) { + my $miniauth = mini_auth($sp); + $fromemail = $sp->{_cat}->{'replyaddress'}; + # insert mini-auth stuff: + my $rep = "+${spid}z$miniauth\@"; + $fromemail =~ s/\@/$rep/; + } + + LJ::send_mail({ + 'to' => $email, + 'from' => $fromemail, + 'fromname' => "$LJ::SITENAME Support", + 'charset' => 'utf-8', + 'subject' => "Re: $sp->{'subject'}", + 'body' => $body + }); + + if ($type eq "answer") { + $dbh->do("UPDATE support SET timelasthelp=UNIX_TIMESTAMP() WHERE spid=$spid"); + } +} + +sub mini_auth +{ + my $sp = shift; + return substr($sp->{'authcode'}, 0, 4); +} + +1; diff --git a/livejournal/cgi-bin/synlib.pl b/livejournal/cgi-bin/synlib.pl new file mode 100755 index 0000000..d723ffe --- /dev/null +++ b/livejournal/cgi-bin/synlib.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl +# + +package LJ::Syn; +use strict; + +sub get_popular_feeds +{ + my $popsyn = LJ::MemCache::get("popsyn"); + unless ($popsyn) { + $popsyn = []; + + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT userid, synurl, numreaders FROM syndicated ". + "WHERE numreaders > 0 ". + "AND lastnew > DATE_SUB(NOW(), INTERVAL 14 DAY) ". + "ORDER BY numreaders DESC LIMIT 1000"); + $sth->execute(); + while (my @row = $sth->fetchrow_array) { + push @$popsyn, [ @row ]; + } + + # load u objects so we can get usernames + my %users; + LJ::load_userids_multiple([ map { $_, \$users{$_} } map { $_->[0] } @$popsyn ]); + unshift @$_, $users{$_->[0]}->{'user'}, $users{$_->[0]}->{'name'} foreach @$popsyn; + # format is: [ user, name, userid, synurl, numreaders ] + # set in memcache + my $expire = time() + 3600; # 1 hour + LJ::MemCache::set("popsyn", $popsyn, $expire); + } + return $popsyn; +} + +1; diff --git a/livejournal/cgi-bin/sysban.pl b/livejournal/cgi-bin/sysban.pl new file mode 100755 index 0000000..7100f17 --- /dev/null +++ b/livejournal/cgi-bin/sysban.pl @@ -0,0 +1,175 @@ +#!/usr/bin/perl +# + +use strict; + +package LJ; + +# +# name: LJ::sysban_check +# des: Given a 'what' and 'value', checks to see if a ban exists +# args: what, value +# des-what: The ban type +# des-value: The value which triggers the ban +# returns: 1 if a ban exists, 0 otherwise +# +sub sysban_check { + my ($what, $value) = @_; + + # cache if ip ban + if ($what eq 'ip') { + + my $now = time(); + my $ip_ban_delay = $LJ::SYSBAN_IP_REFRESH || 120; + + # check memcache first if not loaded + unless ($LJ::IP_BANNED_LOADED + $ip_ban_delay > $now) { + my $memval = LJ::MemCache::get("sysban:ip"); + if ($memval) { + *LJ::IP_BANNED = $memval; + $LJ::IP_BANNED_LOADED = $now; + } else { + $LJ::IP_BANNED_LOADED = 0; + } + } + + # is it already cached in memory? + if ($LJ::IP_BANNED_LOADED) { + return (defined $LJ::IP_BANNED{$value} && + ($LJ::IP_BANNED{$value} == 0 || # forever + $LJ::IP_BANNED{$value} > time())); # not-expired + } + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + # build cache from db + %LJ::IP_BANNED = (); + my $sth = $dbh->prepare("SELECT value, UNIX_TIMESTAMP(banuntil) FROM sysban " . + "WHERE status='active' AND what='ip' " . + "AND NOW() > bandate " . + "AND (NOW() < banuntil OR banuntil IS NULL)"); + $sth->execute; + return undef if $dbh->err; + while (my ($val, $exp) = $sth->fetchrow_array) { + $LJ::IP_BANNED{$val} = $exp || 0; + } + + # set in memcache + LJ::MemCache::set("sysban:ip", \%LJ::IP_BANNED, $ip_ban_delay); + $LJ::IP_BANNED_LOADED = time(); + + # return value to user + return $LJ::IP_BANNED{$value}; + } + + # cache if uniq ban + if ($what eq 'uniq') { + + # check memcache first if not loaded + unless ($LJ::UNIQ_BANNED_LOADED) { + my $memval = LJ::MemCache::get("sysban:uniq"); + if ($memval) { + *LJ::UNIQ_BANNED = $memval; + $LJ::UNIQ_BANNED_LOADED++; + } + } + + # is it already cached in memory? + if ($LJ::UNIQ_BANNED_LOADED) { + return (defined $LJ::UNIQ_BANNED{$value} && + ($LJ::UNIQ_BANNED{$value} == 0 || # forever + $LJ::UNIQ_BANNED{$value} > time())); # not-expired + } + + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + # set this now before the query + $LJ::UNIQ_BANNED_LOADED++; + + # build cache from db + %LJ::UNIQ_BANNED = (); + my $sth = $dbh->prepare("SELECT value, UNIX_TIMESTAMP(banuntil) FROM sysban " . + "WHERE status='active' AND what='uniq' " . + "AND NOW() > bandate " . + "AND (NOW() < banuntil OR banuntil IS NULL)"); + $sth->execute(); + return undef $LJ::UNIQ_BANNED_LOADED if $sth->err; + while (my ($val, $exp) = $sth->fetchrow_array) { + $LJ::UNIQ_BANNED{$val} = $exp || 0; + } + + # set in memcache + my $exp = 60*15; # 15 minutes + LJ::MemCache::set("sysban:uniq", \%LJ::UNIQ_BANNED, $exp); + + # return value to user + return $LJ::UNIQ_BANNED{$value}; + } + + # non-ip bans come straight from the db + my $dbh = LJ::get_db_writer(); + return undef unless $dbh; + + return $dbh->selectrow_array("SELECT COUNT(*) FROM sysban " . + "WHERE status='active' AND what=? AND value=? " . + "AND NOW() > bandate " . + "AND (NOW() < banuntil OR banuntil=0 OR banuntil IS NULL)", + undef, $what, $value); +} + +# +# name: LJ::sysban_note +# des: Inserts a properly-formatted row into statushistory noting that a ban has been triggered +# args: userid?, notes, vars +# des-userid: The userid which triggered the ban, if available +# des-notes: A very brief description of what triggered the ban +# des-vars: A hashref of helpful variables to log, keys being variable name and values being values +# returns: nothing +# +sub sysban_note +{ + my ($userid, $notes, $vars) = @_; + + $notes .= ":"; + map { $notes .= " $_=$vars->{$_};" if $vars->{$_} } sort keys %$vars; + LJ::statushistory_add($userid, 0, 'sysban_trig', $notes); + + return; +} + +# +# name: LJ::sysban_block +# des: Notes a sysban in statushistory and returns a fake http error message to the user +# args: userid?, notes, vars +# des-userid: The userid which triggered the ban, if available +# des-notes: A very brief description of what triggered the ban +# des-vars: A hashref of helpful variables to log, keys being variable name and values being values +# returns: nothing +# +sub sysban_block +{ + my ($userid, $notes, $vars) = @_; + + LJ::sysban_note($userid, $notes, $vars); + + my $msg = <<'EOM'; + + +503 Service Unavailable + + +

    503 Service Unavailable

    +The service you have requested is temporarily unavailable. + + +EOM + + # may not run from web context (e.g. mailgated.pl -> supportlib -> ..) + eval { BML::http_response(200, $msg); }; + + return; +} + +1; diff --git a/livejournal/cgi-bin/taglib.pl b/livejournal/cgi-bin/taglib.pl new file mode 100755 index 0000000..39bd1ae --- /dev/null +++ b/livejournal/cgi-bin/taglib.pl @@ -0,0 +1,1185 @@ +#!/usr/bin/perl + +package LJ::Tags; + +use strict; + +# +# name: LJ::Tags::get_usertagsmulti +# class: tags +# des: Gets a bunch of tags for the specified list of users. +# args: uobj* +# des-uobj: One or more user ids or objects to load the tags for. +# returns: Hashref; { userid => *tagref*, userid => *tagref*, ... } where *tagref* is the +# return value of LJ::Tags::get_usertags -- undef on failure +# +sub get_usertagsmulti { + return {} if $LJ::DISABLED{tags}; + + # get input users + my @uobjs = grep { defined } map { LJ::want_user($_) } @_; + return {} unless @uobjs; + + # now setup variables we'll need + my @memkeys; # memcache keys to fetch + my @resjids; # final list of journal ids + my $res = {}; # { jid => { tagid => {}, ... }, ... }; results return hashref + my %jid2cid; # ( jid => cid ); cross reference journals to clusters + my %need; # ( cid => { jid => 1 } ); what we still need + + # prepopulate our structures + foreach my $u (@uobjs) { + $jid2cid{$u->{userid}} = $u->{clusterid}; + $need{$u->{clusterid}}->{$u->{userid}} = 1; + push @memkeys, [ $u->{userid}, "tags:$u->{userid}" ]; + } + + # gather data from memcache if available + my $memc = LJ::MemCache::get_multi(@memkeys) || {}; + foreach my $key (keys %$memc) { + if ($key =~ /^tags:(\d+)$/) { + my $jid = $1; + my $cid = $jid2cid{$jid}; + + # set this up in our return hash + $res->{$jid} = $memc->{$key}; + + # no longer need this user + delete $need{$cid}->{$jid}; + + # delete cluster if no more users + delete $need{$cid} + unless %{$need{$cid}}; + } + } + + # now, what we need per cluster... + foreach my $cid (keys %need) { + # get db for this cluster + my $dbcr = LJ::get_cluster_def_reader($cid) + or next; + + # useful sql + my $in = join(',', map { $_ + 0 } keys %{$need{$cid}}); + + # get the tags from the database + my $tagrows = $dbcr->selectall_arrayref(qq{ + SELECT journalid, kwid, parentkwid, display + FROM usertags + WHERE journalid IN ($in) + }); + next if $dbcr->err || ! $tagrows; + + # break down into data structures + my %tags; # ( jid => ( id => display ) ) + $tags{$_->[0]}->{$_->[1]} = $_->[3] + foreach @$tagrows; + + # if they have no tags... + next unless %tags; + + # create SQL for finding the proper ids... (userid = ? AND kwid IN (...)) OR (userid = ? ...) ... + my @stmts; + foreach my $uid (keys %tags) { + push @stmts, "(userid = " . ($uid+0) . " AND kwid IN (" . + join(',', map { $_+0 } keys %{$tags{$uid}}) . + "))"; + } + my $where = join(' OR ', @stmts); + + # get the keyword ids they have used as tags + my $rows = $dbcr->selectall_arrayref("SELECT userid, kwid, keyword FROM userkeywords WHERE $where"); + next if $dbcr->err || ! $rows; + + # now turn this into a tentative results hash: { userid => { tagid => { name => tagname, ... }, ... } } + foreach my $row (@$rows) { + $res->{$row->[0]}->{$row->[1]} = + { + name => $row->[2], + security => { + public => 0, + groups => {}, + private => 0, + friends => 0 + }, + uses => 0, + display => $tags{$row->[0]}->{$row->[1]}, + }; + } + @resjids = keys %$res; + + # get security counts + my $ids = join(',', map { $_+0 } @resjids); + + # populate security counts + my $counts = $dbcr->selectall_arrayref("SELECT journalid, kwid, security, entryct FROM logkwsum WHERE journalid IN ($ids)"); + next if $dbcr->err || ! $counts; + + # setup some helper values + my $public_mask = 1 << 31; + my $friends_mask = 1 << 0; + + # melt this information down into the hashref + foreach my $row (@$counts) { + my ($jid, $kwid, $sec, $ct) = @$row; + + # make sure this journal and keyword are present in the results already + # so we don't auto-vivify something with security that has no keyword with it + next unless $res->{$jid} && $res->{$jid}->{$kwid}; + + # add these to the total uses + $res->{$jid}->{$kwid}->{uses} += $ct; + + if ($sec & $public_mask) { + $res->{$jid}->{$kwid}->{security}->{public} += $ct; + $res->{$jid}->{$kwid}->{security_level} = 'public'; + } elsif ($sec & $friends_mask) { + $res->{$jid}->{$kwid}->{security}->{friends} += $ct; + $res->{$jid}->{$kwid}->{security_level} = 'friends' + unless $res->{$jid}->{$kwid}->{security_level} eq 'public'; + } elsif ($sec) { + # if $sec is true (>0), and not friends/public, then it's a group. but it's + # still in the form of a number, and we want to know which group it is. so + # we must convert the mask back to a bit number with LJ::bit_breakdown. but + # we will only ever have one mask, so we just accept that. + my $grpid = (LJ::bit_breakdown($sec))[0] + 0; + $res->{$jid}->{$kwid}->{security}->{groups}->{$grpid} += $ct; + $res->{$jid}->{$kwid}->{security_level} ||= 'group'; + } else { + # $sec must be 0 + $res->{$jid}->{$kwid}->{security}->{private} += $ct; + } + } + + # default securities to private and store to memcache + foreach my $jid (@resjids) { + $res->{$jid}->{$_}->{security_level} ||= 'private' + foreach keys %{$res->{$jid}}; + + LJ::MemCache::add([ $jid, "tags:$jid" ], $res->{$jid}); + } + } + + return $res; +} + +# +# name: LJ::Tags::get_usertags +# class: tags +# des: Returns the tags that a user has defined for their account. +# args: uobj, opts? +# des-uobj: User object to get tags for. +# des-opts: Optional hashref; key can be 'remote' to filter tags to only ones that remote can see +# returns: Hashref; key being tag id, value being a large hashref (FIXME: document) +# +sub get_usertags { + return {} if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift) + or return undef; + my $opts = shift() || {}; + + # get tags for this user + my $tags = LJ::Tags::get_usertagsmulti($u); + return undef unless $tags; + + # get the tags for this user + my $res = $tags->{$u->{userid}} || {}; + return {} unless %$res; + + # now if they provided a remote, remove the ones they don't want to see; note that + # remote may be undef so we have to check exists + if (exists $opts->{remote}) { + # never going to cull anything if it's you, so return it + return $res if LJ::u_equals($u, $opts->{remote}); + + # setup helper variables from u to remote + my ($is_friend, $grpmask) = (0, 0); + if ($opts->{remote}) { + $is_friend = LJ::is_friend($u, $opts->{remote}); + $grpmask = LJ::get_groupmask($u, $opts->{remote}); + } + + # figure out what we need to purge + my @purge; +TAG: foreach my $tagid (keys %$res) { + my $sec = $res->{$tagid}->{security_level}; + next TAG if $sec eq 'public'; + next TAG if $is_friend && $sec eq 'friends'; + if ($grpmask && $sec eq 'group') { + foreach my $grpid (%{$res->{$tagid}->{security}->{groups}}) { + next TAG if $grpmask & (1 << $grpid); + } + } + push @purge, $tagid; + } + delete $res->{$_} foreach @purge; + } + + return $res; +} + +# +# name: LJ::Tags::get_entry_tags +# class: tags +# des: Gets tags that have been used on an entry +# args: uuserid, jitemid +# des-uuserid: User id or object of account with entry +# des-jitemid: Journal itemid of entry; may also be arrayref of jitemids in journal. +# returns: Hashref; { jitemid => { tagid => tagname, tagid => tagname, ... }, ... } +# +sub get_logtags { + return {} if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + return undef unless $u; + + # handle magic jitemid parameter + my $jitemid = shift; + unless (ref $jitemid eq 'ARRAY') { + $jitemid = [ $jitemid+0 ]; + return undef unless $jitemid->[0]; + } + return undef unless @$jitemid; + + # transform to a call to get_logtagsmulti + my $ret = LJ::Tags::get_logtagsmulti({ $u->{clusterid} => [ map { [ $u->{userid}, $_ ] } @$jitemid ] }); + return undef unless $ret && ref $ret eq 'HASH'; + + # now construct result hashref + return { map { $_ => $ret->{"$u->{userid} $_"} } @$jitemid }; +} + +# +# name: LJ::Tags::get_logtagsmulti +# class: tags +# des: Load tags on a given set of entries +# args: idsbyc +# des-idsbyc: { clusterid => [ [ jid, jitemid ], [ jid, jitemid ], ... ] } +# returns: hashref with "jid jitemid" keys, value of each being a hashref of +# { tagid => tagname, ... } +# +sub get_logtagsmulti { + return {} if $LJ::DISABLED{tags}; + + # get parameter (only one!) + my $idsbycluster = shift; + return undef unless $idsbycluster && ref $idsbycluster eq 'HASH'; + + # the mass of variables to make this mess work! + my @jids; # journalids we've seen + my @memkeys; # memcache keys to load + my %ret; # ( jid => { jitemid => [ tagid, tagid, ... ], ... } ); storage for data pre-final conversion + my %set; # ( jid => ( jitemid => [ tagid, tagid, ... ] ) ); for setting in memcache + my $res = {}; # { "jid jitemid" => { tagid => kw, tagid => kw, ... } }; final results hashref for return + my %need; # ( cid => { jid => { jitemid => 1, jitemid => 1 } } ); what still needs loading + my %jid2cid; # ( jid => cid ); map of journal id to clusterid + + # construct memcache keys for loading below + foreach my $cid (keys %$idsbycluster) { + foreach my $row (@{$idsbycluster->{$cid} || []}) { + $need{$cid}->{$row->[0]}->{$row->[1]} = 1; + $jid2cid{$row->[0]} = $cid; + push @memkeys, [ $row->[0], "logtag:$row->[0]:$row->[1]" ]; + } + } + + # now hit up memcache to try to find what we can + my $memc = LJ::MemCache::get_multi(@memkeys) || {}; + foreach my $key (keys %$memc) { + if ($key =~ /^logtag:(\d+):(\d+)$/) { + my ($jid, $jitemid) = ($1, $2); + my $cid = $jid2cid{$jid}; + + # save memcache output hashref to out %ret var + $ret{$jid}->{$jitemid} = $memc->{$key}; + + # no longer need this jid->jitemid combo + delete $need{$cid}->{$jid}->{$jitemid}; + + # no longer need this user if no more jitemids for them + delete $need{$cid}->{$jid} + unless %{$need{$cid}->{$jid}}; + + # delete cluster from need if no more users on it + delete $need{$cid} + unless %{$need{$cid}}; + } + } + + # iterate over clusters and construct SQL to get the data... + foreach my $cid (keys %need) { + my $dbcm = LJ::get_cluster_master($cid) + or return undef; + + # list of (jid, jitemid) pairs that we get from %need + my @bind; + foreach my $jid (keys %{$need{$cid} || {}}) { + push @bind, ($jid, $_) + foreach keys %{$need{$cid}->{$jid} || {}}; + } + + # @bind is always even (from above), so the count of query elements we need is the + # number of items in @bind, divided by 2 + my $sql = join(' OR ', map { "(journalid = ? AND jitemid = ?)" } 1..(scalar(@bind)/2)); + + # prepare the query to run + my $sth = $dbcm->prepare("SELECT journalid, jitemid, kwid FROM logtags WHERE ($sql)"); + return undef if $dbcm->err || ! $sth; + + # execute, fail on error + $sth->execute(@bind); + return undef if $sth->err; + + # get data into %set so we add it to memcache later + while (my ($jid, $jitemid, $kwid) = $sth->fetchrow_array) { + push @{$set{$jid}->{$jitemid} ||= []}, $kwid; + } + } + + # now add the things to memcache that we loaded from the clusters and also + # transport them into the $ret hashref or returning to the user + foreach my $jid (keys %set) { + foreach my $jitemid (keys %{$set{$jid}}) { + LJ::MemCache::add([ $jid, "logtag:$jid:$jitemid" ], $set{$jid}->{$jitemid}); + $ret{$jid}->{$jitemid} = $set{$jid}->{$jitemid}; + } + } + + # quickly load all tags for the users we've found + @jids = keys %ret; + my $utags = LJ::Tags::get_usertagsmulti(@jids); + return undef unless $utags; + + # last step: convert keywordids to keywords + foreach my $jid (@jids) { + my $tags = $utags->{$jid}; + next unless $tags; + + # transpose data from %ret into $res hashref which has (kwid => keyword) pairs + foreach my $jitemid (keys %{$ret{$jid}}) { + $res->{"$jid $jitemid"}->{$_} = $tags->{$_}->{name} + foreach @{$ret{$jid}->{$jitemid} || []}; + } + } + + # finally return the result hashref + return $res; +} + +# +# name: LJ::Tags::can_add_tags +# class: tags +# des: Determines if one account is allowed to add tags to another's post +# args: u, remote +# des-u: User id or object of account tags are being added to +# des-remote: User id or object of account performing the action +# returns: 1 if allowed, 0 if not, undef on error +# +sub can_add_tags { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my $remote = LJ::want_user(shift); + return undef unless $u && $remote; + return undef unless $remote->{journaltype} eq 'P'; + return undef if LJ::is_banned($remote, $u); + + # get permission hashref and check it; note that we fall back to the control + # permission, which will allow people to add even if they can't add by default + my $perms = LJ::Tags::get_permission_levels($u); + return LJ::Tags::_remote_satisfies_permission($u, $remote, $perms->{add}) || + LJ::Tags::_remote_satisfies_permission($u, $remote, $perms->{control}); +} + +# +# name: LJ::Tags::can_control_tags +# class: tags +# des: Determines if one account is allowed to control (add, edit, delete) the tags of another +# args: u, remote +# des-u: User id or object of account tags are being edited on +# des-remote: User id or object of account performing the action +# returns: 1 if allowed, 0 if not, undef on error +# +sub can_control_tags { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my $remote = LJ::want_user(shift); + return undef unless $u && $remote; + return undef unless $remote->{journaltype} eq 'P'; + return undef if LJ::is_banned($remote, $u); + + # get permission hashref and check it + my $perms = LJ::Tags::get_permission_levels($u); + return LJ::Tags::_remote_satisfies_permission($u, $remote, $perms->{control}); +} + +# helper sub internal used by can_*_tags functions +sub _remote_satisfies_permission { + my ($u, $remote, $perm) = @_; + return undef unless $u && $remote && $perm; + + # permission checks + if ($perm eq 'public') { + return 1; + } elsif ($perm eq 'none') { + return 0; + } elsif ($perm eq 'friends') { + return LJ::is_friend($u, $remote); + } elsif ($perm eq 'private') { + return LJ::can_manage($remote, $u); + } elsif ($perm =~ /^group:(\d+)$/) { + my $grpid = $1+0; + return undef unless $grpid >= 1 && $grpid <= 30; + + my $mask = LJ::get_groupmask($u, $remote); + return ($mask & (1 << $grpid)) ? 1 : 0; + } else { + # else, problem! + return undef; + } +} + +# +# name: LJ::Tags::get_permission_levels +# class: tags +# des: Gets the permission levels on an account +# args: uobj +# des-uobj: User id or object of account to get permissions for +# returns: Hashref; keys one of 'add', 'control'; values being 'private' (only the account +# in question), 'friends' (all friends), 'public' (everybody), 'group:N' (one +# friend group with given id), or 'none' (nobody can) +# +sub get_permission_levels { + return { add => 'none', control => 'none' } + if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + return undef unless $u; + + # get the prop + LJ::load_user_props($u, 'opt_tagpermissions'); + + # return defaults for accounts + unless ($u->{opt_tagpermissions}) { + if ($u->{journaltype} eq 'C') { + # communities are members (friends) add, private (maintainers) control + return { add => 'friends', control => 'private' }; + } elsif ($u->{journaltype} eq 'P') { + # people let friends add, self control + return { add => 'private', control => 'private' }; + } else { + # other account types can't add tags + return { add => 'none', control => 'none' }; + } + } + + # now split and return + my ($add, $control) = split(/\s*,\s*/, $u->{opt_tagpermissions}); + return { add => $add, control => $control }; +} + +# +# name: LJ::Tags::is_valid_tagstring +# class: tags +# des: Determines if a string contains a valid list of tags. +# args: tagstring, listref? +# des-tagstring: Opaque tag string provided by the user. +# des-listref: If specified, return valid list of canonical tags in arrayref here. +# returns: 1 if list is valid, 0 if not. +# +sub is_valid_tagstring { + my ($tagstring, $listref) = @_; + return 0 unless $tagstring; + $listref ||= []; + + # setup helper subs + my $valid_tag = sub { + my $tag = shift; + return 0 if $tag =~ /^_/; # reserved for future use (starting with underscore) + return 0 if $tag =~ /[\<\>\r\n\t]/; # no HTML, newlines, tabs, etc + return 0 unless $tag =~ /^(?:.+\s?)+$/; # one or more "words" + return 1; + }; + my $canonical_tag = sub { + my $tag = shift; + $tag = LJ::trim($tag); + $tag =~ s/\s+/ /g; # condense multiple spaces to a single space + $tag = LJ::text_trim($tag, LJ::BMAX_KEYWORD, LJ::CMAX_KEYWORD); + $tag = lc $tag + if $tag !~ /[\x7f-\xff]/; + return $tag; + }; + + # now iterate + my @list = grep { length $_ } # only keep things that are something + map { LJ::trim($_) } # remove leading/trailing spaces + split(/\s*,\s*/, $tagstring); # split on comma with optional spaces + return 0 unless @list; + + # now validate each one as we go + foreach my $tag (@list) { + # canonicalize and determine validity + $tag = $canonical_tag->($tag); + return 0 unless $valid_tag->($tag); + + # now push on our list + push @$listref, $tag; + } + + # well, it must have been okay if we got here + return 1; +} + +# +# name: LJ::Tags::get_security_breakdown +# class: tags +# des: Returns a list of security levels that apply to the given security information. +# args: security, allowmask +# des-security: 'private', 'public', or 'usemask' +# des-allowmask: a bitmask in standard allowmask form +# returns: List of broken down security levels to use for logkwsum table. +# +sub get_security_breakdown { + my ($sec, $mask) = @_; + + my @out; + + if ($sec eq 'private') { + @out = (0); + } elsif ($sec eq 'public') { + @out = (1 << 31); + } else { + # have to get each group bit into a mask + foreach my $bit (0..30) { # include 0 for friends only + if ($mask & (1 << $bit)) { + push @out, (1 << $bit); + } + } + } + + return @out; +} + +# +# name: LJ::Tags::update_logtags +# class: tags +# des: Updates the tags on an entry. Tags not in the list you provide are deleted. +# args: uobj, jitemid, uobj, tags, +# des-uobj: User id or object of account with entry +# des-jitemid: Journal itemid of entry to tag +# des-opts: Hashref; keys being the action and values of the key being an arrayref of +# tags to involve in the action. Possible actions are 'add', 'set', and +# 'delete'. With those, the value is a hashref of the tags (textual tags) +# to add, set, or delete. Other actions are 'add_ids', 'set_ids', and +# 'delete_ids'. The value arrayref should then contain the tag ids to +# act with. Can also specify 'add_string', 'set_string', or 'delete_string' +# as a comma separated list of user-supplied tags which are then canonicalized +# and used. 'remote' is the remote user taking the actions (required). +# returns: 1 on success, undef on error +# +sub update_logtags { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my $jitemid = shift() + 0; + return undef unless $u && $jitemid; + return undef unless $u->writer; + + # ensure we have an options hashref + my $opts = shift; + return undef unless $opts && ref $opts eq 'HASH'; + + # perform set logic? + my $do_set = exists $opts->{set} || exists $opts->{set_ids} || exists $opts->{set_string}; + + # now get extra options + my $remote = LJ::want_user(delete $opts->{remote}); + return undef unless $remote || $opts->{force}; + + # get access levels + my $can_control = LJ::Tags::can_control_tags($u, $remote); + my $can_add = $can_control || LJ::Tags::can_add_tags($u, $remote); + return undef unless $can_add || $opts->{force}; + + # load the user's tags + my $utags = LJ::Tags::get_usertags($u); + return undef unless $utags; + + # take arrayrefs of tag strings and stringify them for validation + foreach my $verb (qw(add set delete)) { + # if given tags, combine into a string + if ($opts->{$verb}) { + $opts->{"${verb}_string"} = join(',', @{$opts->{$verb}}); + $opts->{$verb} = []; + } + + # now validate the string, if we have one + if ($opts->{"${verb}_string"}) { + $opts->{$verb} = []; + return undef + unless LJ::Tags::is_valid_tagstring($opts->{"${verb}_string"}, $opts->{$verb}); + } + + # and turn everything into ids + $opts->{"${verb}_ids"} ||= []; + foreach my $kw (@{$opts->{$verb} || []}) { + my $kwid = LJ::get_keyword_id($u, $kw, $can_control); + if ($can_control) { + # error if we failed to create + return undef unless $kwid; + } else { + # if we're not creating, who cares, just skip; also skip if the keyword + # is not really a tag (don't promote it) + next unless $kwid && $utags->{$kwid}; + } + + # create it if necessary + LJ::Tags::create_usertag($u, $kw, { display => 1 }) + unless $utags->{$kwid}; + + push @{$opts->{"${verb}_ids"}}, $kwid; + } + } + + # setup %add/%delete hashes, for easier duplicate removal + my %add = ( map { $_ => 1 } @{$opts->{add_ids} || []} ); + my %delete = ( map { $_ => 1 } @{$opts->{delete_ids} || []} ); + + # used to keep counts in sync + my $tags = LJ::Tags::get_logtags($u, $jitemid); + return undef unless $tags; + + # now get tags for this entry; which there might be none, so make it a hashref + $tags = $tags->{$jitemid} || {}; + + # set is broken down into add/delete as necessary + if ($do_set || ($opts->{set_ids} && @{$opts->{set_ids}})) { + # mark everything to delete, we'll fix it shortly + $delete{$_} = 1 foreach keys %{$tags}; + + # and now go through the set we want, things that are in the delete + # pile are just nudge so we don't touch them, and everything else we + # throw in the add pile + foreach my $id (@{$opts->{set_ids}}) { + $add{$id} = 1 + unless delete $delete{$id}; + } + } + + + # now don't readd things we already have + delete $add{$_} foreach keys %{$tags}; + + # but delete nothing if we're not a controller + %delete = () unless $can_control || $opts->{force}; + + # bail out if nothing needs to be done + return 1 unless %add || %delete; + + # %add and %delete are accurate, but we need to track necessary + # security updates; this is a hash of keyword ids and a modification + # value (a delta; +/-N) to be applied to that row later + my %security; + + # get the security of this post for use in %security; do this now so + # we don't interrupt the transaction below + my $l2row = LJ::get_log2_row($u, $jitemid); + return undef unless $l2row; + + # calculate security masks + my @sec = LJ::Tags::get_security_breakdown($l2row->{security}, $l2row->{allowmask}); + + # setup a rollback bail path so that we can undo everything we've done + # if anything fails in the middle; and if the rollback fails, scream loudly + # and burst into flames! + my $rollback = sub { + die $u->errstr unless $u->rollback; + return undef; + }; + + # start the big transaction, for great justice! + $u->begin_work; + + # process additions first + my @bind; + foreach my $kwid (keys %add) { + $security{$kwid}++; + push @bind, $u->{userid}, $jitemid, $kwid; + } + + # now add all to both tables; only do 100 rows (300 bind vars) at a time + while (my @list = splice(@bind, 0, 300)) { + my $sql = join(',', map { "(?,?,?)" } 1..(scalar(@list)/3)); + + $u->do("REPLACE INTO logtags (journalid, jitemid, kwid) VALUES $sql", undef, @list); + return $rollback->() if $u->err; + + $u->do("REPLACE INTO logtagsrecent (journalid, jitemid, kwid) VALUES $sql", undef, @list); + return $rollback->() if $u->err; + } + + # now process deletions + @bind = (); + foreach my $kwid (keys %delete) { + $security{$kwid}--; + push @bind, $kwid; + } + + # now run the SQL + while (my @list = splice(@bind, 0, 100)) { + my $sql = join(',', map { $_ + 0 } @list); + + $u->do("DELETE FROM logtags WHERE journalid = ? AND jitemid = ? AND kwid IN ($sql)", + undef, $u->{userid}, $jitemid); + return $rollback->() if $u->err; + + $u->do("DELETE FROM logtagsrecent WHERE journalid = ? AND kwid IN ($sql) AND jitemid = ?", + undef, $u->{userid}, $jitemid); + return $rollback->() if $u->err; + } + + # now handle lazy cleaning of this table for these tag ids; note that the + # %security hash contains all of the keywords we've operated on in total + my @kwids = keys %security; + my $sql = join(',', map { $_ + 0 } @kwids); + my $sth = $u->prepare("SELECT kwid, COUNT(*) FROM logtagsrecent WHERE journalid = ? AND kwid IN ($sql) GROUP BY 1"); + return $rollback->() if $u->err || ! $sth; + $sth->execute($u->{userid}); + return $rollback->() if $sth->err; + + # now iterate over counts and find ones that are too high + my %delrecent; # kwid => [ jitemid, jitemid, ... ] + while (my ($kwid, $ct) = $sth->fetchrow_array) { + next unless $ct > 120; + + # get the times of the entries, the user time (lastn view uses user time), sort it, and then + # we can chop off jitemids that fall below the threshold -- but only in this keyword and only clean + # up some number at a time (25 at most, starting at our threshold) + my $sth2 = $u->prepare(qq{ + SELECT t.jitemid + FROM logtagsrecent t, log2 l + WHERE t.journalid = l.journalid + AND t.jitemid = l.jitemid + AND t.journalid = ? + AND t.kwid = ? + ORDER BY l.eventtime DESC + LIMIT 100,25 + }); + return $rollback->() if $u->err || ! $sth2; + $sth2->execute($u->{userid}, $kwid); + return $rollback->() if $sth2->err; + + # push these onto the hash for deleting below + while (my $jit = $sth2->fetchrow_array) { + push @{$delrecent{$kwid} ||= []}, $jit; + } + } + + # now delete any recents we need to into this format: + # (kwid = 3 AND jitemid IN (2, 3, 4)) OR (kwid = ...) OR ... + # but only if we have some to delete + if (%delrecent) { + my $del = join(' OR ', map { + "(kwid = " . ($_+0) . " AND jitemid IN (" . join(',', map { $_+0 } @{$delrecent{$_}}) . "))" + } keys %delrecent); + $u->do("DELETE FROM logtagsrecent WHERE journalid = ? AND ($del)", undef, $u->{userid}); + return $rollback->() if $u->err; + } + + # now we must get the current security values in order to come up with a proper update; note that + # we select for update, which locks it so we have a consistent view of the rows + $sth = $u->prepare("SELECT kwid, security, entryct FROM logkwsum WHERE journalid = ? AND kwid IN ($sql) FOR UPDATE"); + return $rollback->() if $u->err || ! $sth; + $sth->execute($u->{userid}); + return $rollback->() if $sth->err; + + # now iterate and get the security counts + my %counts; + while (my ($kwid, $sec, $ct) = $sth->fetchrow_array) { + $counts{$kwid}->{$sec} = $ct; + } + + # now we want to update them, and delete any at 0 + my (@replace, @delete); + foreach my $kwid (@kwids) { + foreach my $sec (@sec) { + if (exists $counts{$kwid} && exists $counts{$kwid}->{$sec}) { + # an old one exists + my $new = $counts{$kwid}->{$sec} + $security{$kwid}; + if ($new > 0) { + # update it + push @replace, [ $kwid, $sec, $new ]; + } else { + # delete this one + push @delete, [ $kwid, $sec ]; + } + } else { + # add a new one + push @replace, [ $kwid, $sec, $security{$kwid} ]; + } + } + } + + # handle deletes in one move; well, 100 at a time + while (my @list = splice(@delete, 0, 100)) { + my $sql = join(' OR ', map { "(kwid = ? AND security = ?)" } 1..scalar(@list)); + $u->do("DELETE FROM logkwsum WHERE journalid = ? AND ($sql)", + undef, $u->{userid}, map { @$_ } @list); + return $rollback->() if $u->err; + } + + # handle replaces and inserts + while (my @list = splice(@replace, 0, 100)) { + my $sql = join(',', map { "(?,?,?,?)" } 1..scalar(@list)); + $u->do("REPLACE INTO logkwsum (journalid, kwid, security, entryct) VALUES $sql", + undef, map { $u->{userid}, @$_ } @list); + return $rollback->() if $u->err; + } + + # commit everything and smack caches and we're done! + die $u->errstr unless $u->commit; + LJ::Tags::reset_cache($u); + LJ::Tags::reset_cache($u => $jitemid); + return 1; + +} + +# +# name: LJ::Tags::delete_logtags +# class: tags +# des: Deletes all tags on an entry. +# args: uobj, jitemid +# des-uobj: User id or object of account with entry +# des-jitemid: Journal itemid of entry to delete tags from +# returns: undef on error; 1 on success +# +sub delete_logtags { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my $jitemid = shift() + 0; + return undef unless $u && $jitemid; + + # maybe this is ghetto, but it does all of the logic we would otherwise + # have to duplicate here, so no sense in doing that. + return LJ::Tags::update_logtags($u, $jitemid, { set_string => "", force => 1, }); +} + +# +# name: LJ::Tags::reset_cache +# class: tags +# des: Clears out all cached information for a user's tags. +# args: uobj, jitemid? +# des-uobj: User id or object of account to clear cache for +# des-jitemid: Either a single jitemid or an arrayref of jitemids to clear for the user. If +# not present, the user's tags cache is cleared. If present, the cache for those +# entries only are cleared. +# returns: undef on error; 1 on success +# +sub reset_cache { + return undef if $LJ::DISABLED{tags}; + + while (my ($u, $jitemid) = splice(@_, 0, 2)) { + next unless + $u = LJ::want_user($u); + + # standard user tags cleanup + unless ($jitemid) { + LJ::MemCache::delete([ $u->{userid}, "tags:$u->{userid}" ]); + } + + # now, cleanup entries if necessary + if ($jitemid) { + $jitemid = [ $jitemid ] + unless ref $jitemid eq 'ARRAY'; + LJ::MemCache::delete([ $u->{userid}, "logtag:$u->{userid}:$_" ]) + foreach @$jitemid; + } + } + return 1; +} + +# +# name: LJ::Tags::create_usertag +# class: tags +# des: Creates tags for a user, returning the keyword ids allocated. +# args: uobj, kw, opts? +# des-uobj: User object to create tag on. +# des-kw: Tag string (comma separated list of tags) to create. +# des-opts: Optional; hashref, possible keys being 'display' and value being whether or +# not this tag should be a display tag and 'parenttagid' being the tagid of a +# parent tag for heirarchy. +# returns: undef on error, else a hashref of { keyword => tagid } for each keyword defined +# +sub create_usertag { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my $kw = shift; + my $opts = shift || {}; + return undef unless $u && $kw; + + my $tags = []; + my $isvalid = LJ::Tags::is_valid_tagstring($kw, $tags); + return undef unless $isvalid; + + my $display = $opts->{display} ? 1 : 0; + my $parentkwid = $opts->{parenttagid} ? ($opts->{parenttagid}+0) : undef; + + my %res; + foreach my $tag (@$tags) { + my $kwid = LJ::get_keyword_id($u, $tag); + return undef unless $kwid; + + $res{$tag} = $kwid; + } + + my $ct = scalar keys %res; + my $bind = join(',', map { "(?,?,?,?)" } 1..$ct); + $u->do("INSERT IGNORE INTO usertags (journalid, kwid, parentkwid, display) VALUES $bind", + undef, map { $u->{userid}, $_, $parentkwid, $display } values %res); + return undef if $u->err; + + LJ::Tags::reset_cache($u); + return \%res; +} + +# +# name: LJ::Tags::validate_tag +# class: tags +# des: Check the validity of a single tag. +# args: tag +# des-tag: The tag to check. +# returns: If valid, the canonicalized tag, else, undef. +# +sub validate_tag { + my $tag = shift; + return undef unless $tag; + + my $list = []; + return undef unless + LJ::Tags::is_valid_tagstring($tag, $list); + return undef if scalar(@$list) > 1; + + return $list->[0]; +} + +# +# name: LJ::Tags::delete_usertag +# class: tags +# des: Deletes a tag for a user, and all mappings. +# args: uobj, type, tag +# des-uobj: User object to delete tag on. +# des-type: Either 'id' or 'name', indicating the type of the third parameter. +# des-tag: If type is 'id', this is the tag id (kwid). If type is 'name', this is the name of the +# tag that we want to delete from the user. +# returns: undef on error, 1 for success, 0 for tag not found +# +sub delete_usertag { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + return undef unless $u; + + my ($type, $val) = @_; + + my $kwid; + if ($type eq 'name') { + my $tag = LJ::Tags::validate_tag($val); + return undef unless $tag; + + $kwid = LJ::get_keyword_id($u, $tag, 0); + } elsif ($type eq 'id') { + $kwid = $val + 0; + } + return undef unless $kwid; + + # escape sub + my $rollback = sub { + die $u->errstr unless $u->rollback; + return undef; + }; + + # start the big transaction + $u->begin_work; + + # get items this keyword is on + my $sth = $u->prepare('SELECT jitemid FROM logtags WHERE journalid = ? AND kwid = ? FOR UPDATE'); + return $rollback->() if $u->err || ! $sth; + + # now get the items + $sth->execute($u->{userid}, $kwid); + return $rollback->() if $sth->err; + + # now get list of jitemids for later cache clearing + my @jitemids; + push @jitemids, $_ + while $_ = $sth->fetchrow_array; + + # delete this tag's information from the relevant tables + foreach my $table (qw(usertags logtags logtagsrecent logkwsum)) { + # no error checking, we're just deleting data that's already semi-unlinked due + # to us already updating the userprop above + $u->do("DELETE FROM $table WHERE journalid = ? AND kwid = ?", + undef, $u->{userid}, $kwid); + } + + # all done with our updates + die $u->errstr unless $u->commit; + + # reset caches, have to do both of these, one for the usertags one for logtags + LJ::Tags::reset_cache($u); + LJ::Tags::reset_cache($u => \@jitemids); + return 1; +} + +# +# name: LJ::Tags::rename_usertag +# class: tags +# des: Deletes a tag for a user, and all mappings. +# args: uobj, type, tag, newname +# des-uobj: User object to delete tag on. +# des-type: Either 'id' or 'name', indicating the type of the third parameter. +# des-tag: If type is 'id', this is the tag id (kwid). If type is 'name', this is the name of the +# tag that we want to rename for the user. +# des-newname: The new name of this tag. +# returns: undef on error, 1 for success, 0 for tag not found +# +sub rename_usertag { + return undef if $LJ::DISABLED{tags}; + + # FIXME/TODO: make this function do merging? + + my $u = LJ::want_user(shift); + return undef unless $u; + + my ($type, $val, $newname) = @_; + return undef unless $type && $val && $newname; + + # validate new tag + $newname = LJ::Tags::validate_tag($newname); + return undef unless $newname; + + # get a list of keyword ids to operate on + my $kwid; + if ($type eq 'name') { + $val = LJ::Tags::validate_tag($val); + return undef unless $val; + + $kwid = LJ::get_keyword_id($u, $val, 0); + } elsif ($type eq 'id') { + $kwid = $val + 0; + } + return undef unless $kwid; + + # see if this is already a keyword + my $newkwid = LJ::get_keyword_id($u, $newname); + return undef unless $newkwid; + + # see if the tag we're renaming TO already exists as a keyword, + # if so, don't allow the rename because we don't do merging (yet) + my $tags = LJ::Tags::get_usertags($u); + return undef if $tags->{$newkwid}; + + # escape sub + my $rollback = sub { + die $u->errstr unless $u->rollback; + return undef; + }; + + # start the big transaction + $u->begin_work; + + # get items this keyword is on + my $sth = $u->prepare('SELECT jitemid FROM logtags WHERE journalid = ? AND kwid = ? FOR UPDATE'); + return $rollback->() if $u->err || ! $sth; + + # now get the items + $sth->execute($u->{userid}, $kwid); + return $rollback->() if $sth->err; + + # now get list of jitemids for later cache clearing + my @jitemids; + push @jitemids, $_ + while $_ = $sth->fetchrow_array; + + # do database update to migrate from old to new + foreach my $table (qw(usertags logtags logtagsrecent logkwsum)) { + $u->do("UPDATE $table SET kwid = ? WHERE journalid = ? AND kwid = ?", + undef, $newkwid, $u->{userid}, $kwid); + return $rollback->() if $u->err; + } + + # all done with our updates + die $u->errstr unless $u->commit; + + # reset caches, have to do both of these, one for the usertags one for logtags + LJ::Tags::reset_cache($u); + LJ::Tags::reset_cache($u => \@jitemids); + return 1; +} + +# +# name: LJ::Tags::set_usertag_display +# class: tags +# des: Set the display bool for a tag. +# args: uobj, vartype, var, val +# des-uobj: User id or object of account to edit tag on +# des-vartype: Either 'id' or 'name'; indicating what the next parameter is +# des-var: If vartype is 'id', this is the tag (keyword) id; else, it's the tag/keyword itself +# des-val: 1/0; whether to turn the display flag on or off +# returns: 1 on success, undef on error +# +sub set_usertag_display { + return undef if $LJ::DISABLED{tags}; + + my $u = LJ::want_user(shift); + my ($type, $var, $val) = @_; + return undef unless $u; + + my $kwid; + if ($type eq 'id') { + $kwid = $var + 0; + } elsif ($type eq 'name') { + $var = LJ::Tags::validate_tag($var); + return undef unless $var; + + # do not auto-vivify but get the keyword id + $kwid = LJ::get_keyword_id($u, $var, 0); + } + return undef unless $kwid; + + $u->do("UPDATE usertags SET display = ? WHERE journalid = ? AND kwid = ?", + undef, $val ? 1 : 0, $u->{userid}, $kwid); + return undef if $u->err; + + return 1; +} + +# +# name: LJ::Tags::deleted_friend_group +# class: tags +# des: Called internally when a friends group is deleted. +# args: uobj, bit +# des-uobj: User id or object of account deleting the group. +# des-bit: The id (1..30) of the friends group being deleted. +# returns: 1 of success undef on failure. +# +sub deleted_friend_group { + my $u = LJ::want_user(shift); + my $bit = shift() + 0; + return undef unless $u && $bit >= 1 && $bit <= 30; + + # delete from logkwsum and then nuke the user's tags + $u->do("DELETE FROM logkwsum WHERE journalid = ? AND security = ?", + undef, $u->{userid}, 1 << $bit); + return undef if $u->err; + + # that was simple + LJ::Tags::reset_cache($u); + return 1; +} + +1; diff --git a/livejournal/cgi-bin/talklib.pl b/livejournal/cgi-bin/talklib.pl new file mode 100755 index 0000000..042b338 --- /dev/null +++ b/livejournal/cgi-bin/talklib.pl @@ -0,0 +1,3095 @@ +#!/usr/bin/perl +# +# +# link: htdocs/userinfo.bml, htdocs/go.bml, htdocs/tools/memadd.bml, htdocs/editjournal.bml +# link: htdocs/tools/tellafriend.bml +# img: htdocs/img/btn_prev.gif, htdocs/img/memadd.gif, htdocs/img/btn_edit.gif +# img: htdocs/img/btn_next.gif, htdocs/img/btn_tellafriend.gif +# + +use strict; +package LJ::Talk; + +sub get_subjecticons +{ + my %subjecticon; + $subjecticon{'types'} = [ 'sm', 'md' ]; + $subjecticon{'lists'}->{'md'} = [ + { img => "md01_alien.gif", w => 32, h => 32 }, + { img => "md02_skull.gif", w => 32, h => 32 }, + { img => "md05_sick.gif", w => 25, h => 25 }, + { img => "md06_radioactive.gif", w => 20, h => 20 }, + { img => "md07_cool.gif", w => 20, h => 20 }, + { img => "md08_bulb.gif", w => 17, h => 23 }, + { img => "md09_thumbdown.gif", w => 25, h => 19 }, + { img => "md10_thumbup.gif", w => 25, h => 19 } + ]; + $subjecticon{'lists'}->{'sm'} = [ + { img => "sm01_smiley.gif", w => 15, h => 15 }, + { img => "sm02_wink.gif", w => 15, h => 15 }, + { img => "sm03_blush.gif", w => 15, h => 15 }, + { img => "sm04_shock.gif", w => 15, h => 15 }, + { img => "sm05_sad.gif", w => 15, h => 15 }, + { img => "sm06_angry.gif", w => 15, h => 15 }, + { img => "sm07_check.gif", w => 15, h => 15 }, + { img => "sm08_star.gif", w => 20, h => 18 }, + { img => "sm09_mail.gif", w => 14, h => 10 }, + { img => "sm10_eyes.gif", w => 24, h => 12 } + ]; + + # assemble ->{'id'} portion of hash. the part of the imagename before the _ + foreach (keys %{$subjecticon{'lists'}}) { + foreach my $pic (@{$subjecticon{'lists'}->{$_}}) { + next unless ($pic->{'img'} =~ /^(\D{2}\d{2})\_.+$/); + $subjecticon{'pic'}->{$1} = $pic; + $pic->{'id'} = $1; + } + } + + return \%subjecticon; +} + +# entryid-commentid-emailrecipientpassword hash +sub ecphash { + my ($itemid, $talkid, $password) = @_; + return "ecph-" . Digest::MD5::md5_hex($itemid . $talkid . $password); +} + +# Returns talkurl with GET args added (don't pass #anchors to this :-) +sub talkargs { + my $talkurl = shift; + my $args = join("&", grep {$_} @_); + my $sep; + $sep = ($talkurl =~ /\?/ ? "&" : "?") if $args; + return "$talkurl$sep$args"; +} + +# Returns HTML to display an image, given the image id as an argument. +sub show_image +{ + my $pics = shift; + my $id = shift; + my $extra = shift; + return unless defined $pics->{'pic'}->{$id}; + my $p = $pics->{'pic'}->{$id}; + my $pfx = "$LJ::IMGPREFIX/talk"; + return ""; +} + +# Returns 'none' icon. +sub show_none_image +{ + my $extra = shift; + my $img = 'none.gif'; + my $w = 15; + my $h = 15; + my $pfx = "$LJ::IMGPREFIX/talk"; + return ""; +} + +sub link_bar +{ + my $opts = shift; + my ($u, $up, $remote, $headref, $itemid) = + map { $opts->{$_} } qw(u up remote headref itemid); + my $ret; + + my @linkele; + + my $mlink = sub { + my ($url, $piccode) = @_; + return ("
    " . + LJ::img($piccode, "", { 'align' => 'absmiddle' }) . + ""); + }; + + my $jarg = "journal=$u->{'user'}&"; + my $jargent = "journal=$u->{'user'}&"; + + # << Previous + push @linkele, $mlink->("/go.bml?${jargent}itemid=$itemid&dir=prev", "prev_entry"); + $$headref .= "\n"; + + # memories + unless ($LJ::DISABLED{'memories'}) { + push @linkele, $mlink->("/tools/memadd.bml?${jargent}itemid=$itemid", "memadd"); + } + + if (defined $remote && ($remote->{'user'} eq $u->{'user'} || + $remote->{'user'} eq $up->{'user'} || + LJ::can_manage($remote, $u))) + { + push @linkele, $mlink->("/editjournal.bml?${jargent}itemid=$itemid", "editentry"); + } + + unless ($LJ::DISABLED{tags}) { + if (defined $remote && LJ::Tags::can_add_tags($u, $remote)) { + push @linkele, $mlink->("/edittags.bml?${jargent}itemid=$itemid", "edittags"); + } + } + + unless ($LJ::DISABLED{'tellafriend'}) { + push @linkele, $mlink->("/tools/tellafriend.bml?${jargent}itemid=$itemid", "tellfriend"); + } + + ## >>> Next + push @linkele, $mlink->("/go.bml?${jargent}itemid=$itemid&dir=next", "next_entry"); + $$headref .= "\n"; + + if (@linkele) { + $ret .= BML::fill_template("standout", { + 'DATA' => "
    " . + join("  ", @linkele) . + "
    ", + }); + } + + return $ret; +} + +sub init +{ + my ($form) = @_; + my $init = {}; # structure to return + + my $journal = $form->{'journal'}; + my $ju = undef; + my $item = undef; # hashref; journal item conversation is in + + # defaults, to be changed later: + $init->{'itemid'} = $form->{'itemid'}+0; + $init->{'ditemid'} = $init->{'itemid'}; + $init->{'thread'} = $form->{'thread'}+0; + $init->{'dthread'} = $init->{'thread'}; + $init->{'clustered'} = 0; + $init->{'replyto'} = $form->{'replyto'}+0; + $init->{'style'} = $form->{'style'} ? "mine" : undef; + + if ($journal) { + # they specified a journal argument, which indicates new style. + $ju = LJ::load_user($journal); + return { 'error' => BML::ml('talk.error.nosuchjournal')} unless $ju; + return { 'error' => BML::ml('talk.error.bogusargs')} unless $ju->{'clusterid'}; + $init->{'clustered'} = 1; + foreach (qw(itemid replyto)) { + next unless $init->{$_}; + $init->{'anum'} = $init->{$_} % 256; + $init->{$_} = int($init->{$_} / 256); + last; + } + $init->{'thread'} = int($init->{'thread'} / 256) + if $init->{'thread'}; + } else { + # perhaps it's an old URL for a user that's since been clustered. + # look up the itemid and see what user it belongs to. + if ($form->{'itemid'}) { + my $itemid = $form->{'itemid'}+0; + my $newinfo = LJ::get_newids('L', $itemid); + if ($newinfo) { + $ju = LJ::load_userid($newinfo->[0]); + return { 'error' => BML::ml('talk.error.nosuchjournal')} unless $ju; + $init->{'clustered'} = 1; + $init->{'itemid'} = $newinfo->[1]; + $init->{'oldurl'} = 1; + if ($form->{'thread'}) { + my $tinfo = LJ::get_newids('T', $init->{'thread'}); + $init->{'thread'} = $tinfo->[1] if $tinfo; + } + } else { + return { 'error' => BML::ml('talk.error.noentry') }; + } + } elsif ($form->{'replyto'}) { + my $replyto = $form->{'replyto'}+0; + my $newinfo = LJ::get_newids('T', $replyto); + if ($newinfo) { + $ju = LJ::load_userid($newinfo->[0]); + return { 'error' => BML::ml('talk.error.nosuchjournal')} unless $ju; + $init->{'replyto'} = $newinfo->[1]; + $init->{'oldurl'} = 1; + } else { + return { 'error' => BML::ml('talk.error.noentry') }; + } + } + } + + $init->{'journalu'} = $ju; + return $init; +} + +# $u, $itemid +sub get_journal_item +{ + my ($u, $itemid) = @_; + return unless $u && $itemid; + + my $uid = $u->{'userid'}+0; + $itemid += 0; + + my $item = LJ::get_log2_row($u, $itemid); + return undef unless $item; + + $item->{'alldatepart'} = LJ::alldatepart_s2($item->{'eventtime'}); + + $item->{'itemid'} = $item->{'jitemid'}; # support old & new keys + $item->{'ownerid'} = $item->{'journalid'}; # support old & news keys + + my $lt = LJ::get_logtext2($u, $itemid); + my $v = $lt->{$itemid}; + $item->{'subject'} = $v->[0]; + $item->{'event'} = $v->[1]; + + ### load the log properties + my %logprops = (); + LJ::load_log_props2($u->{'userid'}, [ $itemid ], \%logprops); + $item->{'props'} = $logprops{$itemid} || {}; + + if ($LJ::UNICODE && $logprops{$itemid}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$item->{'subject'}, \$item->{'event'}, + $item->{'logprops'}->{$itemid}); + } + return $item; +} + +sub check_viewable +{ + my ($remote, $item, $form, $errref) = @_; + # note $form no longer used + + my $err = sub { + $$errref = " h1?>"; + return 0; + }; + + unless (LJ::can_view($remote, $item)) { + return $err->(BML::ml('talk.error.mustlogin')) + unless defined $remote; + return $err->(BML::ml('talk.error.notauthorised')); + } + + return 1; +} + +# +# name: LJ::Talk::can_delete +# des: Determines if a user can delete a comment or entry. Basically, you can +# delete anything you've posted. You can delete anything posted in something +# you own (i.e. a comment in your journal, a comment to an entry you made in +# a community). You can also delete any item in an account you have the +# "A"dministration edge for. +# args: remote, u, up, userpost +# des-remote: User object we're checking access of. From LJ::get_remote. +# des-u: Username or object of the account the thing is located in. +# des-up: Username or object of person who owns the parent of the thing. (I.e. the poster +# of the entry a comment is in.) +# des-userpost: Username (NOT object) of person who posted the item. +# returns: Boolean indicating whether remote is allowed to delete the thing +# specified by the other options. +# +sub can_delete { + my ($remote, $u, $up, $userpost) = @_; # remote, journal, posting user, commenting user + return 0 unless $remote; + return 1 if $remote->{'user'} eq $userpost || + $remote->{'user'} eq (ref $u ? $u->{'user'} : $u) || + $remote->{'user'} eq (ref $up ? $up->{'user'} : $up) || + LJ::can_manage($remote, $u); + return 0; +} + +sub can_screen { + my ($remote, $u, $up, $userpost) = @_; + return 0 unless $remote; + return 1 if $remote->{'user'} eq $u->{'user'} || + $remote->{'user'} eq (ref $up ? $up->{'user'} : $up) || + LJ::can_manage($remote, $u); + return 0; +} + +sub can_unscreen { + return LJ::Talk::can_screen(@_); +} + +sub can_view_screened { + return LJ::Talk::can_delete(@_); +} + +sub can_freeze { + return LJ::Talk::can_screen(@_); +} + +sub can_unfreeze { + return LJ::Talk::can_unscreen(@_); +} + +# +# name: LJ::Talk::screening_level +# des: Determines the screening level of a particular post given the relevent information. +# args: journalu, jitemid +# des-journalu: User object of the journal the post is in. +# des-jitemid: Itemid of the post. +# returns: Single character that indicates the screening level. Undef means don't screen +# anything, 'A' means screen All, 'R' means screen Anonymous (no-remotes), 'F' means +# screen non-friends. +# +sub screening_level { + my ($journalu, $jitemid) = @_; + die 'LJ::screening_level needs a user object.' unless ref $journalu; + $jitemid += 0; + die 'LJ::screening_level passed invalid jitemid.' unless $jitemid; + + # load the logprops for this entry + my %props; + LJ::load_log_props2($journalu->{userid}, [ $jitemid ], \%props); + + # determine if userprop was overriden + my $val = $props{$jitemid}{opt_screening}; + return if $val eq 'N'; # N means None, so return undef + return $val if $val; + + # now return userprop, as it's our last chance + LJ::load_user_props($journalu, 'opt_whoscreened'); + return if $journalu->{opt_whoscreened} eq 'N'; + return $journalu->{opt_whoscreened}; +} + +sub update_commentalter { + my ($u, $itemid) = @_; + LJ::set_logprop($u, $itemid, { 'commentalter' => time() }); +} + +# +# name: LJ::Talk::get_comments_in_thread +# class: web +# des: Gets a list of comment ids that are contained within a thread, including the +# comment at the top of the thread. You can also limit this to only return comments +# of a certain state. +# args: u, jitemid, jtalkid, onlystate, screenedref +# des-u: user object of user to get comments from +# des-jitemid: journal itemid to get comments from +# des-jtalkid: journal talkid of comment to use as top of tree +# des-onlystate: if specified, return only comments of this state (e.g. A, F, S...) +# des-screenedref: if provided and an array reference, will push on a list of comment +# ids that are being returned and are screened (mostly for use in deletion so you can +# unscreen the comments) +# returns: undef on error, array reference of jtalkids on success +# +sub get_comments_in_thread { + my ($u, $jitemid, $jtalkid, $onlystate, $screened_ref) = @_; + $u = LJ::want_user($u); + $jitemid += 0; + $jtalkid += 0; + $onlystate = uc $onlystate; + return undef unless $u && $jitemid && $jtalkid && + (!$onlystate || $onlystate =~ /^\w$/); + + # get all comments to post + my $comments = LJ::Talk::get_talk_data($u, 'L', $jitemid) || {}; + + # see if our comment exists + return undef unless $comments->{$jtalkid}; + + # create relationship hashref and count screened comments in post + my %parentids; + $parentids{$_} = $comments->{$_}{parenttalkid} foreach keys %$comments; + + # now walk and find what to update + my %to_act; + foreach my $id (keys %$comments) { + my $act = ($id == $jtalkid); + my $walk = $id; + while ($parentids{$walk}) { + if ($parentids{$walk} == $jtalkid) { + # we hit the one we want to act on + $act = 1; + last; + } + last if $parentids{$walk} == $walk; + + # no match, so move up a level + $walk = $parentids{$walk}; + } + + # set it as being acted on + $to_act{$id} = 1 if $act && (!$onlystate || $comments->{$id}{state} eq $onlystate); + + # push it onto the list of screened comments? (if the caller is doing a delete, they need + # a list of screened comments in order to unscreen them) + push @$screened_ref, $id if ref $screened_ref && # if they gave us a ref + $to_act{$id} && # and we're acting on this comment + $comments->{$id}{state} eq 'S'; # and this is a screened comment + } + + # return list from %to_act + return [ keys %to_act ]; +} + +# +# name: LJ::Talk::delete_thread +# class: web +# des: Deletes an entire thread of comments. +# args: u, jitemid, jtalkid +# des-u: Userid or user object to delete thread from. +# des-jitemid: Journal itemid of item to delete comments from. +# des-jtalkid: Journal talkid of comment at top of thread to delete. +# returns: 1 on success; undef on error +# +sub delete_thread { + my ($u, $jitemid, $jtalkid) = @_; + + # get comments and delete 'em + my @screened; + my $ids = LJ::Talk::get_comments_in_thread($u, $jitemid, $jtalkid, undef, \@screened); + LJ::Talk::unscreen_comment($u, $jitemid, @screened) if @screened; # if needed only! + my $num = LJ::delete_comments($u, "L", $jitemid, @$ids); + LJ::replycount_do($u, $jitemid, "decr", $num); + LJ::Talk::update_commentalter($u, $jitemid); + return 1; +} + +# +# name: LJ::Talk::freeze_thread +# class: web +# des: Freezes an entire thread of comments. +# args: u, jitemid, jtalkid +# des-u: Userid or user object to freeze thread from. +# des-jitemid: Journal itemid of item to freeze comments from. +# des-jtalkid: Journal talkid of comment at top of thread to freeze. +# returns: 1 on success; undef on error +# +sub freeze_thread { + my ($u, $jitemid, $jtalkid) = @_; + + # now we need to update the states + my $ids = LJ::Talk::get_comments_in_thread($u, $jitemid, $jtalkid, 'A'); + LJ::Talk::freeze_comments($u, "L", $jitemid, 0, $ids); + return 1; +} + +# +# name: LJ::Talk::unfreeze_thread +# class: web +# des: unfreezes an entire thread of comments. +# args: u, jitemid, jtalkid +# des-u: Userid or user object to unfreeze thread from. +# des-jitemid: Journal itemid of item to unfreeze comments from. +# des-jtalkid: Journal talkid of comment at top of thread to unfreeze. +# returns: 1 on success; undef on error +# +sub unfreeze_thread { + my ($u, $jitemid, $jtalkid) = @_; + + # now we need to update the states + my $ids = LJ::Talk::get_comments_in_thread($u, $jitemid, $jtalkid, 'F'); + LJ::Talk::freeze_comments($u, "L", $jitemid, 1, $ids); + return 1; +} + +# +# name: LJ::Talk::freeze_comments +# class: web +# des: Freezes comments. This is the internal helper function called by +# freeze_thread/unfreeze_thread. Use those if you wish to freeze or +# unfreeze a thread. This function just freezes specific comments. +# args: u, nodetype, nodeid, unfreeze, ids +# des-u: Userid or object of user to manipulate comments in. +# des-nodetype: Nodetype of the thing containing the specified ids. Typically "L". +# des-nodeid: Id of the node to manipulate comments from. +# des-unfreeze: If 1, unfreeze instead of freeze. +# des-ids: Array reference containing jtalkids to manipulate. +# returns: 1 on success; undef on error +# +sub freeze_comments { + my ($u, $nodetype, $nodeid, $unfreeze, $ids) = @_; + $u = LJ::want_user($u); + $nodeid += 0; + $unfreeze = $unfreeze ? 1 : 0; + return undef unless LJ::isu($u) && $nodetype =~ /^\w$/ && $nodeid && @$ids; + + # get database and quote things + return undef unless $u->writer; + my $quserid = $u->{userid}+0; + my $qnodetype = $u->quote($nodetype); + my $qnodeid = $nodeid+0; + + # now perform action + my $in = join(',', map { $_+0 } @$ids); + my $newstate = $unfreeze ? 'A' : 'F'; + my $res = $u->talk2_do($nodetype, $nodeid, undef, + "UPDATE talk2 SET state = '$newstate' " . + "WHERE journalid = $quserid AND nodetype = $qnodetype " . + "AND nodeid = $qnodeid AND jtalkid IN ($in)"); + return undef unless $res; + return 1; +} + +sub screen_comment { + my $u = shift; + return undef unless LJ::isu($u); + my $itemid = shift(@_) + 0; + + my $in = join (',', map { $_+0 } @_); + return unless $in; + + my $userid = $u->{'userid'} + 0; + + my $updated = $u->talk2_do("L", $itemid, undef, + "UPDATE talk2 SET state='S' ". + "WHERE journalid=$userid AND jtalkid IN ($in) ". + "AND nodetype='L' AND nodeid=$itemid ". + "AND state NOT IN ('S','D')"); + return undef unless $updated; + + if ($updated > 0) { + LJ::replycount_do($u, $itemid, "decr", $updated); + LJ::set_logprop($u, $itemid, { 'hasscreened' => 1 }); + } + + LJ::Talk::update_commentalter($u, $itemid); + return; +} + +sub unscreen_comment { + my $u = shift; + return undef unless LJ::isu($u); + my $itemid = shift(@_) + 0; + + my $in = join (',', map { $_+0 } @_); + return unless $in; + + my $userid = $u->{'userid'} + 0; + my $prop = LJ::get_prop("log", "hasscreened"); + + my $updated = $u->talk2_do("L", $itemid, undef, + "UPDATE talk2 SET state='A' ". + "WHERE journalid=$userid AND jtalkid IN ($in) ". + "AND nodetype='L' AND nodeid=$itemid ". + "AND state='S'"); + return undef unless $updated; + + if ($updated > 0) { + LJ::replycount_do($u, $itemid, "incr", $updated); + my $dbcm = LJ::get_cluster_master($u); + my $hasscreened = $dbcm->selectrow_array("SELECT COUNT(*) FROM talk2 " . + "WHERE journalid=$userid AND nodeid=$itemid AND nodetype='L' AND state='S'"); + LJ::set_logprop($u, $itemid, { 'hasscreened' => 0 }) unless $hasscreened; + } + + LJ::Talk::update_commentalter($u, $itemid); + return; +} + +# retrieves data from the talk2 table (but preferrably memcache) +# returns a hashref (key -> { 'talkid', 'posterid', 'datepost', +# 'parenttalkid', 'state' } , or undef on failure +sub get_talk_data +{ + my ($u, $nodetype, $nodeid) = @_; + return undef unless LJ::isu($u); + return undef unless $nodetype =~ /^\w$/; + return undef unless $nodeid =~ /^\d+$/; + + my $ret = {}; + + # check for data in memcache + my $DATAVER = "1"; # single character + my $memkey = [$u->{'userid'}, "talk2:$u->{'userid'}:$nodetype:$nodeid"]; + my $lockkey = $memkey->[1]; + my $packed = LJ::MemCache::get($memkey); + + # we check the replycount in memcache, the value we count, and then fix it up + # if it seems necessary. + my $rp_memkey = $nodetype eq "L" ? [$u->{'userid'}, "rp:$u->{'userid'}:$nodeid"] : undef; + my $rp_count = $rp_memkey ? LJ::MemCache::get($rp_memkey) : 0; + my $rp_ourcount = 0; + my $fixup_rp = sub { + return unless $nodetype eq "L"; + return if $rp_count == $rp_ourcount; + return unless @LJ::MEMCACHE_SERVERS; + return unless $u->writer; + + # attempt to get a database lock to make sure that nobody else is in this section + # at the same time we are + my $db_key = "rp:fix:$u->{userid}:$nodetype:$nodeid"; + my $got_lock = $u->selectrow_array("SELECT GET_LOCK(?, 1)", undef, $db_key); + return unless $got_lock; + + # setup an unlock handler + my $unlock = sub { + $u->do("SELECT RELEASE_LOCK(?)", undef, $db_key); + return undef; + }; + + # check memcache to see if someone has previously fixed this entry in this journal + # with this reply count + my $fix_key = "rp_fixed:$u->{userid}:$nodetype:$nodeid:$rp_count"; + my $was_fixed = LJ::MemCache::get($fix_key); + return $unlock->() if $was_fixed; + + # if we're doing innodb, begin a transaction, else lock tables + my $sharedmode = ""; + if ($LJ::INNODB_DB{$u->{clusterid}}) { + $sharedmode = "LOCK IN SHARE MODE"; + $u->begin_work; + } else { + $u->do("LOCK TABLES log2 WRITE, talk2 READ"); + } + + # get count and then update. this should be totally safe because we've either + # locked the tables or we're in a transaction. + my $ct = $u->selectrow_array("SELECT COUNT(*) FROM talk2 WHERE ". + "journalid=? AND nodetype='L' AND nodeid=? ". + "AND state IN ('A','F') $sharedmode", + undef, $u->{'userid'}, $nodeid); + $u->do("UPDATE log2 SET replycount=? WHERE journalid=? AND jitemid=?", + undef, int($ct), $u->{'userid'}, $nodeid); + print STDERR "Fixing replycount for $u->{'userid'}/$nodeid from $rp_count to $ct\n" + if $LJ::DEBUG{'replycount_fix'}; + + # now, commit or unlock as appropriate + if ($LJ::INNODB_DB{$u->{clusterid}}) { + $u->commit; + } else { + $u->do("UNLOCK TABLES"); + } + + # mark it as fixed in memcache, so we don't do this again + LJ::MemCache::add($fix_key, 1, 60); + $unlock->(); + LJ::MemCache::delete($rp_memkey); + }; + + my $memcache_good = sub { + return $packed && substr($packed,0,1) eq $DATAVER && + length($packed) % 16 == 1; + }; + + my $memcache_decode = sub { + my $n = (length($packed) - 1) / 16; + for (my $i=0; $i<$n; $i++) { + my ($f1, $par, $poster, $time) = unpack("NNNN",substr($packed,$i*16+1,16)); + my $state = chr($f1 & 255); + my $talkid = $f1 >> 8; + $ret->{$talkid} = { + talkid => $talkid, + state => $state, + posterid => $poster, + datepost => LJ::mysql_time($time), + parenttalkid => $par, + }; + + # comments are counted if they're 'A'pproved or 'F'rozen + $rp_ourcount++ if $state eq "A" || $state eq "F"; + } + $fixup_rp->(); + return $ret; + }; + + return $memcache_decode->() if $memcache_good->(); + + my $dbcr = LJ::get_cluster_def_reader($u); + return undef unless $dbcr; + + my $lock = $dbcr->selectrow_array("SELECT GET_LOCK(?,10)", undef, $lockkey); + return undef unless $lock; + + # it's quite likely (for a popular post) that the memcache was + # already populated while we were waiting for the lock + $packed = LJ::MemCache::get($memkey); + if ($memcache_good->()) { + $dbcr->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + $memcache_decode->(); + return $ret; + } + + my $memval = $DATAVER; + my $sth = $dbcr->prepare("SELECT t.jtalkid AS 'talkid', t.posterid, ". + "t.datepost, t.parenttalkid, t.state ". + "FROM talk2 t ". + "WHERE t.journalid=? AND t.nodetype=? AND t.nodeid=?"); + $sth->execute($u->{'userid'}, $nodetype, $nodeid); + die $dbcr->errstr if $dbcr->err; + while (my $r = $sth->fetchrow_hashref) { + $ret->{$r->{'talkid'}} = $r; + $memval .= pack("NNNN", + ($r->{'talkid'} << 8) + ord($r->{'state'}), + $r->{'parenttalkid'}, + $r->{'posterid'}, + LJ::mysqldate_to_time($r->{'datepost'})); + $rp_ourcount++ if $r->{'state'} eq "A"; + } + LJ::MemCache::set($memkey, $memval); + $dbcr->selectrow_array("SELECT RELEASE_LOCK(?)", undef, $lockkey); + + $fixup_rp->(); + + return $ret; + +} + +# LJ::Talk::load_comments($u, $remote, $nodetype, $nodeid, $opts) +# +# nodetype: "L" (for log) ... nothing else has been used +# noteid: the jitemid for log. +# opts keys: +# thread -- jtalkid to thread from ($init->{'thread'} or $GET{'thread'} >> 8) +# page -- $GET{'page'} +# view -- $GET{'view'} (picks page containing view's ditemid) +# up -- [optional] hashref of user object who posted the thing being replied to +# only used to make things visible which would otherwise be screened? +# out_error -- set by us if there's an error code: +# nodb: database unavailable +# noposts: no posts to load +# out_pages: number of pages +# out_page: page number being viewed +# out_itemfirst: first comment number on page (1-based, not db numbers) +# out_itemlast: last comment number on page (1-based, not db numbers) +# out_pagesize: size of each page +# out_items: number of total top level items +# +# userpicref -- hashref to load userpics into, or undef to +# not load them. +# userref -- hashref to load users into, keyed by userid +# +# returns: +# array of hashrefs containing keys: +# - talkid (jtalkid) +# - posterid (or zero for anon) +# - userpost (string, or blank if anon) +# - upost ($u object, or undef if anon) +# - datepost (mysql format) +# - parenttalkid (or zero for top-level) +# - state ("A"=approved, "S"=screened, "D"=deleted stub) +# - userpic number +# - picid (if userpicref AND userref were given) +# - subject +# - body +# - props => { propname => value, ... } +# - children => [ hashrefs like these ] +# - _loaded => 1 (if fully loaded, subject & body) +# unknown items will never be _loaded +# - _show => {0|1}, if item is to be ideally shown (0 if deleted or screened) +sub load_comments +{ + my ($u, $remote, $nodetype, $nodeid, $opts) = @_; + + my $n = $u->{'clusterid'}; + my $viewall = $opts->{viewall}; + + my $posts = get_talk_data($u, $nodetype, $nodeid); # hashref, talkid -> talk2 row, or undef + unless ($posts) { + $opts->{'out_error'} = "nodb"; + return; + } + my %users_to_load; # userid -> 1 + my @posts_to_load; # talkid scalars + my %children; # talkid -> [ childenids+ ] + + my $uposterid = $opts->{'up'} ? $opts->{'up'}->{'userid'} : 0; + + my $post_count = 0; + { + my %showable_children; # $id -> $count + + foreach my $post (sort { $b->{'talkid'} <=> $a->{'talkid'} } values %$posts) { + # see if we should ideally show it or not. even if it's + # zero, we'll still show it if it has any children (but we won't show content) + my $should_show = $post->{'state'} eq 'D' ? 0 : 1; + unless ($viewall) { + $should_show = 0 if + $post->{'state'} eq "S" && ! ($remote && ($remote->{'userid'} == $u->{'userid'} || + $remote->{'userid'} == $uposterid || + $remote->{'userid'} == $post->{'posterid'} || + LJ::can_manage($remote, $u) )); + } + $post->{'_show'} = $should_show; + $post_count += $should_show; + + # make any post top-level if it says it has a parent but it isn't + # loaded yet which means either a) row in database is gone, or b) + # somebody maliciously/accidentally made their parent be a future + # post, which could result in an infinite loop, which we don't want. + $post->{'parenttalkid'} = 0 + if $post->{'parenttalkid'} && ! $posts->{$post->{'parenttalkid'}}; + + $post->{'children'} = [ map { $posts->{$_} } @{$children{$post->{'talkid'}} || []} ]; + + # increment the parent post's number of showable children, + # which is our showability plus all those of our children + # which were already computed, since we're working new to old + # and children are always newer. + # then, if we or our children are showable, add us to the child list + my $sum = $should_show + $showable_children{$post->{'talkid'}}; + if ($sum) { + $showable_children{$post->{'parenttalkid'}} += $sum; + unshift @{$children{$post->{'parenttalkid'}}}, $post->{'talkid'}; + } + } + } + + # with a wrong thread number, silently default to the whole page + my $thread = $opts->{'thread'}+0; + $thread = 0 unless $posts->{$thread}; + + unless ($thread || $children{$thread}) { + $opts->{'out_error'} = "noposts"; + return; + } + + my $page_size = $LJ::TALK_PAGE_SIZE || 25; + my $max_subjects = $LJ::TALK_MAX_SUBJECTS || 200; + my $threading_point = $LJ::TALK_THREAD_POINT || 50; + + # we let the page size initially get bigger than normal for awhile, + # but if it passes threading_point, then everything's in page_size + # chunks: + $page_size = $threading_point if $post_count < $threading_point; + + my $top_replies = $thread ? 1 : scalar(@{$children{$thread}}); + my $pages = int($top_replies / $page_size); + if ($top_replies % $page_size) { $pages++; } + + my @top_replies = $thread ? ($thread) : @{$children{$thread}}; + my $page_from_view = 0; + if ($opts->{'view'} && !$opts->{'page'}) { + # find top-level comment that this comment is under + my $viewid = $opts->{'view'} >> 8; + while ($posts->{$viewid} && $posts->{$viewid}->{'parenttalkid'}) { + $viewid = $posts->{$viewid}->{'parenttalkid'}; + } + for (my $ti = 0; $ti < @top_replies; ++$ti) { + if ($posts->{$top_replies[$ti]}->{'talkid'} == $viewid) { + $page_from_view = int($ti/$page_size)+1; + last; + } + } + } + my $page = int($opts->{'page'}) || $page_from_view || 1; + $page = $page < 1 ? 1 : $page > $pages ? $pages : $page; + + my $itemfirst = $page_size * ($page-1) + 1; + my $itemlast = $page==$pages ? $top_replies : ($page_size * $page); + + @top_replies = @top_replies[$itemfirst-1 .. $itemlast-1]; + + push @posts_to_load, @top_replies; + + # mark child posts of the top-level to load, deeper + # and deeper until we've hit the page size. if too many loaded, + # just mark that we'll load the subjects; + my @check_for_children = @posts_to_load; + my (@subjects_to_load, @subjects_ignored); + while (@check_for_children) { + my $cfc = shift @check_for_children; + next unless defined $children{$cfc}; + foreach my $child (@{$children{$cfc}}) { + if (@posts_to_load < $page_size) { + push @posts_to_load, $child; + } else { + if (@subjects_to_load < $max_subjects) { + push @subjects_to_load, $child; + } else { + push @subjects_ignored, $child; + } + } + push @check_for_children, $child; + } + } + + $opts->{'out_pages'} = $pages; + $opts->{'out_page'} = $page; + $opts->{'out_itemfirst'} = $itemfirst; + $opts->{'out_itemlast'} = $itemlast; + $opts->{'out_pagesize'} = $page_size; + $opts->{'out_items'} = $top_replies; + + # load text of posts + my ($posts_loaded, $subjects_loaded); + $posts_loaded = LJ::get_talktext2($u, @posts_to_load); + $subjects_loaded = LJ::get_talktext2($u, {'onlysubjects'=>1}, @subjects_to_load) if @subjects_to_load; + foreach my $talkid (@posts_to_load) { + next unless $posts->{$talkid}->{'_show'}; + $posts->{$talkid}->{'_loaded'} = 1; + $posts->{$talkid}->{'subject'} = $posts_loaded->{$talkid}->[0]; + $posts->{$talkid}->{'body'} = $posts_loaded->{$talkid}->[1]; + $users_to_load{$posts->{$talkid}->{'posterid'}} = 1; + } + foreach my $talkid (@subjects_to_load) { + next unless $posts->{$talkid}->{'_show'}; + $posts->{$talkid}->{'subject'} = $subjects_loaded->{$talkid}->[0]; + $users_to_load{$posts->{$talkid}->{'posterid'}} ||= 0.5; # only care about username + } + foreach my $talkid (@subjects_ignored) { + next unless $posts->{$talkid}->{'_show'}; + $posts->{$talkid}->{'subject'} = "..."; + $users_to_load{$posts->{$talkid}->{'posterid'}} ||= 0.5; # only care about username + } + + # load meta-data + { + my %props; + LJ::load_talk_props2($u->{'userid'}, \@posts_to_load, \%props); + foreach (keys %props) { + next unless $posts->{$_}->{'_show'}; + $posts->{$_}->{'props'} = $props{$_}; + } + } + + if ($LJ::UNICODE) { + foreach (@posts_to_load) { + if ($posts->{$_}->{'props'}->{'unknown8bit'}) { + LJ::item_toutf8($u, \$posts->{$_}->{'subject'}, + \$posts->{$_}->{'body'}, + {}); + } + } + } + + # load users who posted + delete $users_to_load{0}; + my %up = (); + if (%users_to_load) { + LJ::load_userids_multiple([ map { $_, \$up{$_} } keys %users_to_load ]); + + # fill in the 'userpost' member on each post being shown + while (my ($id, $post) = each %$posts) { + my $up = $up{$post->{'posterid'}}; + next unless $up; + $post->{'upost'} = $up; + $post->{'userpost'} = $up->{'user'}; + } + } + + # optionally give them back user refs + if (ref($opts->{'userref'}) eq "HASH") { + my %userpics = (); + # copy into their ref the users we've already loaded above. + while (my ($k, $v) = each %up) { + $opts->{'userref'}->{$k} = $v; + } + + # optionally load userpics + if (ref($opts->{'userpicref'}) eq "HASH") { + my @load_pic; + foreach my $talkid (@posts_to_load) { + my $post = $posts->{$talkid}; + my $kw; + if ($post->{'props'} && $post->{'props'}->{'picture_keyword'}) { + $kw = $post->{'props'}->{'picture_keyword'}; + } + my $pu = $opts->{'userref'}->{$post->{'posterid'}}; + my $id = LJ::get_picid_from_keyword($pu, $kw); + $post->{'picid'} = $id; + push @load_pic, [ $pu, $id ]; + } + LJ::load_userpics($opts->{'userpicref'}, \@load_pic); + } + } + return map { $posts->{$_} } @top_replies; +} + +sub talkform { + # Takes a hashref with the following keys / values: + # remote: optional remote u object + # journalu: prequired journal u object + # parpost: parent post object + # replyto: init->replyto + # ditemid: init->ditemid + # form: optional full form hashref + # do_captcha: optional toggle for creating a captcha challenge + # require_tos: optional toggle to include TOS requirement form + # errors: optional error arrayref + my $opts = shift; + return "Invalid talkform values." unless ref $opts eq 'HASH'; + + my $ret; + my ($remote, $journalu, $parpost, $form) = + map { $opts->{$_} } qw(remote journalu parpost form); + + my $pics = LJ::Talk::get_subjecticons(); + + # early bail if the user can't be making comments yet + return $LJ::UNDERAGE_ERROR + if $remote && $remote->underage; + + # once we clean out talkpost.bml, this will need to be changed. + BML::set_language_scope('/talkpost.bml'); + + # make sure journal isn't locked + return "Sorry, this journal is locked and comments cannot be posted to it at this time." + if $journalu->{statusvis} eq 'L'; + + # check max comments + my $jitemid = $opts->{'ditemid'} >> 8; + return "Sorry, this entry already has the maximum number of comments allowed." + if LJ::Talk::Post::over_maxcomments($journalu, $jitemid); + + if ($parpost->{'state'} eq "S") { + $ret .= "
    $BML::ML{'.warnscreened'}
    "; + } + $ret .= "
    "; + + # Login challenge/response + my $authchal = LJ::challenge_generate(900); # 15 minute auth token + $ret .= ""; + $ret .= ""; + + if ($opts->{errors} && @{$opts->{errors}}) { + $ret .= '
      '; + $ret .= "
    • $_
    • " foreach @{$opts->{errors}}; + $ret .= '
    '; + $ret .= "
    "; + } + + # hidden values + my $parent = $opts->{replyto}+0; + $ret .= LJ::html_hidden("replyto", $opts->{replyto}, + "parenttalkid", $parent, + "itemid", $opts->{ditemid}, + "journal", $journalu->{'user'}); + + # rate limiting challenge + { + my ($time, $secret) = LJ::get_secret(); + my $rchars = LJ::rand_chars(20); + my $chal = $opts->{ditemid} . "-$journalu->{userid}-$time-$rchars"; + my $res = Digest::MD5::md5_hex($secret . $chal); + $ret .= LJ::html_hidden("chrp1", "$chal-$res"); + } + + # if we know the user who is posting (error on talkpost_do POST action), + # then see if we + if ($opts->{require_tos}) { + $ret .= LJ::tosagree_html('comment', $form->{agree_tos}, BML::ml('tos.error')); + } + + my $oid_identity = $remote ? $remote->openid_identity : undef; + + # Default radio button + # 4 possible scenarios: + # remote - initial form load, error and redisplay + # no remote - initial load, error and redisplay + my $whocheck = sub { + my $type = shift; + my $default = " checked='checked'"; + + # Initial page load (no remote) + return $default if $type eq 'anonymous' && + ! $form->{'usertype'} && ! $remote && ! $oid_identity; + + # Anonymous + return $default if $type eq 'anonymous' && + $form->{'usertype'} eq 'anonymous'; + + if (LJ::OpenID::consumer_enabled()) { + # OpenID + return $default if $type eq 'openid' && + $form->{'usertype'} eq 'openid'; + + return $default if $type eq 'openid_cookie' && + ($form->{'usertype'} eq 'openid_cookie' || + (defined $oid_identity)); + } + + # Remote user, remote equals userpost + return $default if $type eq 'remote' && + ($form->{'usertype'} eq 'cookieuser' || + $form->{'userpost'} eq $form->{'cookieuser'}); + + # Possible remote, using ljuser field + if ($type eq 'ljuser') { + return $default if + # Remote user posting as someone else. + ($form->{'userpost'} && $form->{'userpost'} ne $form->{'cookieuser'} && $form->{'usertype'} ne 'anonymous') || + ($form->{'usertype'} eq 'user' && ! $form->{'userpost'}); + } + + return; + }; + + # from registered user or anonymous? + $ret .= "\n"; + $ret .= ""; + $ret .= " + + Column name + Type + Null + Default + Description + + + + + + + + YES + + + + + + + + + + + + Key name + Type + Column(s) + + + + + + + + + + + + + + + + , + + + + + + + + + No keys defined. + + + + + + + ljp.dbschema. + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/build/db/dbschema.dtd b/livejournal/doc/raw/build/db/dbschema.dtd new file mode 100755 index 0000000..d1675c8 --- /dev/null +++ b/livejournal/doc/raw/build/db/dbschema.dtd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/doc/raw/build/db/dbschema.pl b/livejournal/doc/raw/build/db/dbschema.pl new file mode 100755 index 0000000..7723428 --- /dev/null +++ b/livejournal/doc/raw/build/db/dbschema.pl @@ -0,0 +1,125 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbr = LJ::get_dbh("slave", "master"); +my $sth; + +sub magic_links +{ + my $des = shift; + $$des =~ s!!>!g; + $$des =~ s!\[dbtable\[(\w+?)\]\]!$1!g; +} + +sub dump_xml +{ + my $tables = shift; + + print "\n"; + print "\n"; + print "\n"; + foreach my $table (sort keys %$tables) + { + print "\n"; + + # table name + print "$table\n"; + + # description of table + if ($tables->{$table}->{'des'}) { + my $des = $tables->{$table}->{'des'}; + magic_links(\$des); + print "$des\n"; + } + + # columns + foreach my $col (@{$tables->{$table}->{'cols'}}) + { + print "{'name'}\" type=\"$col->{'type'}\" required=\"$col->{'required'}\" default=\"$col->{'default'}\">\n"; + print "$col->{'name'}\n"; + if ($col->{'des'}) { + my $des = $col->{'des'}; + magic_links(\$des); + print "$des\n"; + } + print "\n"; + } + + # indexes + foreach my $indexname (sort keys %{$tables->{$table}->{'index'}}) + { + my $index = $tables->{$table}->{'index'}->{$indexname}; + + print "{'type'}\" colids=\"", join(" ", @{$index->{'cols'}}), "\" />\n"; + } + + print "\n"; + } + print "\n"; +} + +my %table; +my %coldes; + +foreach (`$ENV{'LJHOME'}/bin/upgrading/update-db.pl --listtables`) { + chomp; + $table{$_} = {}; +} + +$sth = $dbr->prepare("SELECT tablename, public_browsable, des FROM schematables"); +$sth->execute; +while (my ($name, $public, $des) = $sth->fetchrow_array) { + next unless (defined $table{$name}); + $table{$name} = { 'public' => $public, 'des' => $des }; +} + +$sth = $dbr->prepare("SELECT tablename, colname, des FROM schemacols"); +$sth->execute; +while (my ($table, $col, $des) = $sth->fetchrow_array) { + next unless (defined $table{$table}); + $coldes{$table}->{$col} = $des; +} + +foreach my $table (sort keys %table) +{ + $sth = $dbr->prepare("DESCRIBE $table"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) + { + my $col = {}; + $col->{'name'} = $r->{'Field'}; + + my $type = $r->{'Type'}; + $type =~ s/int\(\d+\)/int/g; + if ($r->{'Extra'} eq "auto_increment") { + $type .= " auto_increment"; + } + $col->{'type'} = $type; + + $col->{'default'} = $r->{'Default'}; + $col->{'required'} = $r->{'Null'} eq "YES" ? "false" : "true"; + + $col->{'des'} = $coldes{$table}->{$r->{'Field'}}; + + push @{$table{$table}->{'cols'}}, $col; + } + + $sth = $dbr->prepare("SHOW INDEX FROM $table"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) + { + my $name = $r->{'Key_name'}; + my $type = $r->{'Non_unique'} ? "INDEX" : "UNIQUE"; + if ($name eq "PRIMARY") { $type = "PRIMARY"; } + + $table{$table}->{'index'}->{$name}->{'type'} = $type; + push @{$table{$table}->{'index'}->{$name}->{'cols'}}, "$table.$r->{'Column_name'}"; + } +} + +dump_xml(\%table); diff --git a/livejournal/doc/raw/build/docbooklib.pl b/livejournal/doc/raw/build/docbooklib.pl new file mode 100755 index 0000000..fb3384d --- /dev/null +++ b/livejournal/doc/raw/build/docbooklib.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# + + use strict; + + my %special = ( + 'logprops' => '', + 'ljhome' => '\$LJHOME', + 'helpurls' => '', + 'disabled' => '', + 'reluser' => '', + 'cspversion' => '', + ); + + sub cleanse + { + my $text = shift; + # Escape bare ampersands + $$text =~ s/&(?!(?:[a-zA-Z0-9]+|#\d+);)/&/g; + # Escape HTML + $$text =~ s//>/g; + # Convert intended markup to docbook + $$text =~ s/<b>(.+?)<\/b>/$1<\/emphasis>/ig; + $$text =~ s/<tt>(.+?)<\/tt>/$1<\/literal>/ig; + $$text =~ s/<i>(.+?)<\/i>/$1<\/replaceable>/ig; + $$text =~ s/<u>(.+?)<\/u>/$1<\/emphasis>/ig; + xlinkify($text); + } + + sub canonize + { + my $type = lc(shift); + my $name = shift; + my $function = shift; + my $string = lc($name); + if ($type eq "func") { + $string =~ s/::/./g; + my $format = "ljp.api.$string"; + $string = $function eq "link" ? "$name" : $format; + } elsif($type eq "dbtable") { + $string = "$name"; + } elsif($type eq "special") { + $string = %special->{$string}; + } elsif($type eq "ljconfig") { + $string = ""; + } elsif($type eq "var") { + $string = ""; + } + } + + sub xlinkify + { + my $a = shift; + $$a =~ s/\[(\S+?)\[(\S+?)\]\]/canonize($1, $2, "link")/ge; + } diff --git a/livejournal/doc/raw/build/generate.pl b/livejournal/doc/raw/build/generate.pl new file mode 100755 index 0000000..419acfb --- /dev/null +++ b/livejournal/doc/raw/build/generate.pl @@ -0,0 +1,185 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; + +my $XSL_VERSION_RECOMMENDED = "1.55.0"; + +my $opt_clean; +my ($opt_myxsl, $opt_getxsl, $opt_single); +exit 1 unless GetOptions('clean' => \$opt_clean, + 'myxsl' => \$opt_myxsl, + 'getxsl' => \$opt_getxsl, + 'single' => \$opt_single, + ); + +my $home = $ENV{'LJHOME'}; +require "$home/cgi-bin/ljlib.pl"; +$ENV{'SGML_CATALOG_FILES'} = $LJ::CATALOG_FILES || "/usr/share/sgml/docbook/dtd/xml/4.1/docbook.cat"; + +unless (-e $ENV{'SGML_CATALOG_FILES'}) { + die "Catalog files don't exist. Either set \$LJ::CATALOG_FILES, install docbook-xml (on Debian), or symlink $ENV{'SGML_CATALOG_FILES'} to XML DocBook 4.1's docbook.cat."; +} + +die "Siteroot not set" unless $LJ::SITEROOT; +open F, "> $home/doc/raw/entities/pregen.ent" or die "Can't open pregen.ent : $!"; +{ + print F "\n"; +} +close F; + +if ($opt_getxsl) { + chdir "$home/doc/raw/build" or die "Where is build dir?"; + unlink "xsl-docbook.tar.gz"; + my $fetched = 0; + my $url = "http://www.livejournal.org/misc/xsl-docbook.tar.gz"; + my @fetcher = ([ 'wget', "wget $url", ], + [ 'lynx', "lynx -source $url > xsl-docbook.tar.gz", ], + [ 'GET', "GET $url > xsl-docbook.tar.gz", ]); + foreach my $fet (@fetcher) { + next if $fetched; + print "Looking for $fet->[0] ...\n"; + next unless `which $fet->[0]`; + print "RUNNING: $fet->[1]\n"; + system($fet->[1]) + and die "Error running $fet->[0]. Interrupted?\n"; + $fetched = 1; + } + unless ($fetched) { + die "Couldn't find a program to download things from the web. I looked for:\n\t". + join(", ", map { $_->[0] } @fetcher) . "\n"; + } + system("tar", "zxvf", "xsl-docbook.tar.gz") + and die "Error extracting xsl-doxbook.tar.gz; have GNU tar?\n"; +} + +my $output_dir = "$home/htdocs/doc/server"; +my $docraw_dir = "$home/doc/raw"; +my $XSL = "$docraw_dir/build/xsl-docbook"; +my $stylesheet = "$XSL/html/chunk.xsl"; +open (F, "$XSL/VERSION"); +my $XSL_VERSION; +{ + local $/ = undef; my $file = ; + $XSL_VERSION = $1 if $file =~ /VERSION.+\>(.+?)\ $docraw_dir/ljp.book/api/api.gen.xml") + and die "Errror generating General API reference.\n"; +system("api/api2db.pl --include=BML:: --book=bml > $docraw_dir/bml.book/api.gen.xml") + and die "Errror generating BML API reference.\n"; + +print "Generating DB Schema reference\n"; +chdir "$docraw_dir/build/db" or die; +system("./dbschema.pl > dbschema.gen.xml") + and die "Error generating DB schema\n"; + +my $err = system("xsltproc", "-o", "$docraw_dir/ljp.book/db/schema.gen.xml", + "db2ref.xsl", "dbschema.gen.xml"); +if ($err == -1) { die "Error; Package 'xsltproc' not installed?\n"; } +elsif ($err) { $err<<8; die "Error transforming DB schema. (error=$err)\n"; } + +unlink "dbschema.gen.xml"; + +print "Generating XML-RPC protocol reference\n"; +chdir "$docraw_dir/build/protocol" or die; +system("xsltproc", "-o", "$docraw_dir/ljp.book/csp/xml-rpc/protocol.gen.xml", + "xml-rpc2db.xsl", "xmlrpc.xml") + and die "Error processing protocol reference.\n"; + +print "Generating Flat protocol reference\n"; +system("./flat2db.pl > $docraw_dir/ljp.book/csp/flat/protocol.gen.xml") + and die "Error processing protocol reference.\n"; + +print "Generating Log Prop List\n"; +system("./proplist2db.pl > $docraw_dir/ljp.book/csp/proplist.ref.gen.xml") + and die "Error generating log prop list\n"; + +print "Generating Privilege list reference\n"; +chdir "$docraw_dir/build/priv" or die; +system("./priv2db.pl > $docraw_dir/lj.book/admin/privs.ref.gen.xml") + and die "Error generating privilege list\n"; + +print "Generating Console Command Reference\n"; +chdir "$docraw_dir/build/console" or die; +system("./console2db.pl > $docraw_dir/lj.book/admin/console.ref.gen.xml") + and die "Error generating console reference\n"; + +print "Generating Capability Class Reference\n"; +chdir "$docraw_dir/build/caps" or die; +system("./cap2db.pl > $docraw_dir/lj.book/admin/cap.ref.gen.xml") + and die "Error generating caps reference\n"; +system("./cap2db.pl > $docraw_dir/ljp.book/int/cap.ref.gen.xml") + and die "Error generating caps reference\n"; + +print "Generating Hook Function Reference\n"; +chdir "$docraw_dir/build/hooks" or die; +system("./hooks2db.pl > $docraw_dir/lj.book/customize/hooks.ref.gen.xml") + and die "Error generating hooks reference\n"; +system("./hooks2db.pl > $docraw_dir/ljp.book/int/hooks.ref.gen.xml") + and die "Error generating hooks reference\n"; + +print "Generating Configuration Variable Reference\n"; +chdir "$docraw_dir/build/ljconfig" or die; +system("./ljconfig2db.pl > $docraw_dir/lj.book/install/ljconfig.vars.gen.xml") + and die "Error generating ljconfig.pl variable reference\n"; + +print "Generating S1 Variable Reference\n"; +chdir "$docraw_dir/s1" or die; +system("./s1ref2db.pl > $docraw_dir/ljp.book/styles/s1/ref.gen.xml") + and die "Error generating s1 variable reference\n"; + +print "Generating Perl Module List\n"; +chdir "$docraw_dir/build/install" or die; +system("./modulelist2db.pl > $docraw_dir/lj.book/install/perl.module.gen.xml") + and die "Error generating perl module list\n"; + +print "Converting to HTML\n"; +mkdir $output_dir, 0755 unless -d $output_dir; +chdir $output_dir or die "Couldn't chdir to $output_dir\n"; + +my $cssparam; +if (-e "$docraw_dir/build/style.css") { + $cssparam = "--stringparam html.stylesheet style.css"; + system("cp", "$docraw_dir/build/style.css", "$output_dir") + and die "Error copying stylesheet.\n"; +} + +system("xsltproc --nonet --catalogs $cssparam ". + "$docraw_dir/build/chunk.xsl $docraw_dir/index.xml") + and die "Error generating chunked HTML.\n"; + +if ($opt_single) +{ + system("xsltproc --nonet --catalogs --output manual.html $cssparam ". + "$docraw_dir/build/nochunk.xsl $docraw_dir/index.xml") + and die "Error generating single HTML.\n"; +} + +if ($opt_clean) { + print "Removing Auto-generated files\n"; + system("find $docraw_dir -name '*.gen.*' -exec rm {} \;"); +} diff --git a/livejournal/doc/raw/build/hooks/hooks2db.pl b/livejournal/doc/raw/build/hooks/hooks2db.pl new file mode 100755 index 0000000..d9e8d5c --- /dev/null +++ b/livejournal/doc/raw/build/hooks/hooks2db.pl @@ -0,0 +1,404 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +use vars qw(%hooks); + +my $LJHOME = $ENV{'LJHOME'}; + +require "$LJHOME/doc/raw/build/docbooklib.pl"; + +$hooks{'canonicalize_url'} = { + desc => "Cleans up a URL into its canonical form.", + args => [ + { + 'desc' => "URL to be cleaned", + 'name' => "\$url", + } + ], + source => ["bin/maint/stats.pl"], +}; + +$hooks{'emailconfirmed'} = { + desc => "After a user has confirmed their email address, this hook is called ". + "with a dbs/dbh and a user object. This is useful to update a ". + "database alias table which you also have your mail system using for ". + "address lookups.", + args => [ + { + 'desc' => "Either a dbs or dbh resource object.", + 'name' => "\$dbarg", + }, + { + 'desc' => "User object.", + 'name' => "\$u", + }, + ], + source => ["htdocs/register.bml"], +}; + +$hooks{'login_formopts'} = { + desc => "Returns extra HTML for login options on login.bml", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "Scalar return reference", + 'name' => "ret", + }, + ], + }, + ], + source => ["htdocs/login.bml"], +}; + +$hooks{'modify_login_menu'} = { + desc => "Modifies or resets entirely the web menu data structure that is sent to the client.", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "Menu item", + 'name' => "menu", + }, + { + 'desc' => "User object", + 'name' => "u", + }, + { + 'desc' => "Resource object", + 'name' => "dbs", + }, + { + 'desc' => "Username string", + 'name' => "user", + }, + ], + }, + ], + source => ["cgi-bin/ljprotocol.pl"], +}; + +$hooks{'post_login'} = { + desc => "Action to take after logging in, before HTML is sent to ". + "to client (possible to print HTTP headers directly)", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "User object", + 'name' => "u", + }, + { + 'desc' => "Hash of form elements", + 'name' => "form", + }, + { + 'desc' => "Used for cookies. Can either be a unix timestamp, or '0' for session cookies.", + 'name' => "expiretime", + }, + ], + }, + ], + source => ["htdocs/login.bml", "htdocs/talkread_do.bml"], +}; + +$hooks{'post_changepassword'} = { + desc => "Action to take after changing password, before HTML is sent to ". + "to client (possible to print HTTP headers directly)", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "User object", + 'name' => "u", + }, + { + 'desc' => "Resource object", + 'name' => "dbs", + }, + { + 'desc' => "New password.", + 'name' => "newpassword", + }, + { + 'desc' => "Old password.", + 'name' => "oldpassword", + }, + ], + }, + ], + source => ["htdocs/changepassword.bml"], +}; + +$hooks{'post_create'} = { + desc => "Action to take after creating an account.", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "Resource object", + 'name' => "dbs", + }, + { + 'desc' => "Username string", + 'name' => "user", + }, + { + 'desc' => "Integer", + 'name' => "userid", + }, + { + 'desc' => "Auth code, if in use", + 'name' => "code", + }, + ], + }, + ], + source => ["cgi-bin/ljlib.pl"], +}; + +$hooks{'userinfo_html_by_user'} = { + desc => "Extra HTML to show next to username & id on userinfo.bml", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "Scalar return reference", + 'name' => "ret", + }, + { + 'desc' => "User object", + 'name' => "u", + }, + ], + }, + ], + source => ["htdocs/userinfo.bml"], +}; + +$hooks{'userinfo_rows'} = { + desc => "Returns a two-element arrayref for a row on a userinfo page, ". + "containing first the left side label, then the body.", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "Resource Object (read-only)", + 'name' => "dbr", + }, + { + 'desc' => "User object", + 'name' => "u", + }, + { + 'desc' => "Remote user object", + 'name' => "remote", + }, + ], + }, + ], + source => ["htdocs/userinfo.bml"], +}; + +$hooks{'validate_get_remote'} = { + desc => "This hook lets you ignore the remote user's cookies or flag them ". + "as intentionally forged to LJ::get_remote(). If you return a ". + "true value, no action is taken. If you return false, LJ::get_remote() ". + "returns undef. You can optionally set \$\$criterr to something true as well.", + args => [ + { + 'desc' => "Hash of arguments", + 'name' => "\%args", + 'keys' => [ + { + 'desc' => "May be an empty string or undef", + 'name' => "user", + }, + { + 'desc' => "May be 0", + 'name' => "userid", + }, + { + 'desc' => "Resource object", + 'name' => "dbs", + }, + { + 'desc' => "Capabilities", + 'name' => "caps", + }, + { + 'desc' => "Scalar error reference", + 'name' => "criterr", + }, + { + 'desc' => "Sub reference which takes a cookie name and returns its value", + 'name' => "cookiesource", + }, + ], + }, + ], + source => ["cgi-bin/ljlib.pl"], +}; + +$hooks{'bad_password'} = { + desc => "Check the given password, and either return a string explaining why ". + "the password is bad, or undef if the password is ok.", + args => [ + { + 'desc' => "Password to check", + 'name' => "\$password", + }, + ], + source => ["cgi-bin/ljprotocol.pl","htdocs/changepassword.bml","htdocs/create.bml","htdocs/update.bml"], +}; + +$hooks{'name_caps'} = { + desc => "Returns the long name of the given capability bit.", + args => [ + { + 'desc' => "Capability bit to check", + 'name' => "\$cap", + }, + ], + source => ["cgi-bin/ljlib.pl"], +}; + +$hooks{'name_caps_short'} = { + desc => "Returns the short name of the given capability bit.", + args => [ + { + 'desc' => "Capability bit to check", + 'name' => "\$cap", + }, + ], + source => ["cgi-bin/ljlib.pl"], +}; + +$hooks{'login_add_opts'} = { + desc => "Appends options to the cookie value. Each option should be short, and preceeded by a period.", + args => [ + { + 'desc' => "", + 'name' => '%args', + 'keys' => [ + { + 'desc' => "User object", + 'name' => "u", + }, + { + 'desc' => "Login form elements", + 'name' => "form", + }, + { + 'desc' => "Hash reference of options to append to login cookie", + 'name' => "opts", + }, + ], + }, + ], + source => ["htdocs/login.bml"], +}; + +$hooks{'set_s2bml_lang'} = { + desc => "Given an S2 Context, return the correct BML language id", + args => [ + { + 'desc' => "S2 Context", + 'name' => '$ctx', + }, + { + 'desc' => "Language id reference", + 'name' => '\$langref', + }, + ], + source => ["cgi-bin/LJ/S2.pm"], +}; + +sub hooks +{ + my $hooks = shift; + my $arg; + print "\n"; + foreach my $hook (sort keys %$hooks) + { + print " \n"; + print " $hook\n"; + print " Synopsis:\n"; + print " \n"; + print " $hook\n"; + if (@{$hooks->{$hook}->{'args'}}) + { + print " \n"; + foreach $arg (@{$hooks->{$hook}->{'args'}}) + { + print " $arg->{'name'}\n"; + } + print " \n"; + } else { + print " "; + } + print " \n"; + print " \n"; + print " $hooks->{$hook}->{'desc'}\n"; + print " \n"; + if (@{$hooks->{$hook}->{'args'}}) + { + print " Arguments:\n"; + print " \n"; + foreach $arg (@{$hooks->{$hook}->{'args'}}) + { + print " \n"; + print " $arg->{'name'}\n"; + print " \n"; + print " $arg->{'desc'}\n"; + if ($arg->{'keys'}) + { + print " Keys\n"; + foreach my $key (@{$arg->{'keys'}}) + { + print " $key->{'name'}"; + print " — $key->{'desc'}\n"; + } + print " "; + } + print " \n"; + print " \n"; + } + print " \n"; + print " \n"; + } + print " Source:\n"; + print " "; + foreach my $i ( 0 .. $#{ $hooks->{$hook}->{'source'} } ) { + print ""; + print $hooks->{$hook}->{'source'}[$i]; + print ""; + } + print " \n"; + print " \n"; + print " \n"; + } + print "\n"; +} + +hooks(\%hooks); diff --git a/livejournal/doc/raw/build/install/modulelist2db.pl b/livejournal/doc/raw/build/install/modulelist2db.pl new file mode 100755 index 0000000..c005552 --- /dev/null +++ b/livejournal/doc/raw/build/install/modulelist2db.pl @@ -0,0 +1,112 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +my $LJHOME = $ENV{'LJHOME'}; +my (%modules, @debs, $line); +require "$LJHOME/doc/raw/build/docbooklib.pl"; +require "$LJHOME/cgi-bin/ljlib.pl"; + +my @modules; +my $indoc; my $curmod; +open (CFG, "$LJHOME/bin/checkconfig.pl") or return 0; +while ($line = ) +{ + $line = LJ::trim($line); + next if $line =~ /^\},/; + if ($line =~ /\Qmy %modules\E/) { $indoc = 1; next; } + if ($indoc && $line =~ /\Q);\E/) { $indoc = 0; next; } + if ($indoc) { + if ($line =~ /^\"(.+?)\"/) { + push @modules, $curmod if $curmod->{'name'}; + $curmod = {}; + $curmod->{'name'} = $1; + } + if ($line =~ /\'deb\' \=> \'(.+?)\'/) { $curmod->{'deb'} = $1; } + if ($line =~ /^\'opt\' \=> [\'\"](.+?)[\'\"]/) { $curmod->{'opt'} = $1; } + } elsif ($curmod->{'name'}) { + push @modules, $curmod if $curmod->{'name'}; + $curmod = {}; + } +} +close CFG; + +# Print reference + +print "
    $BML::ML{'.opt.from'}"; + $ret .= ""; # Internal for "From" options + my $screening = LJ::Talk::screening_level($journalu, $opts->{ditemid} >> 8); + + if ($journalu->{'opt_whocanreply'} eq "all") { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + if (LJ::OpenID::consumer_enabled()) { + # OpenID!! + # Logged in + if (defined $oid_identity) { + # Don't worry about a real href since js hides the row anyway + my $other_user = ""; + + $ret .= ""; + $ret .= "\n"; + } + + # logged out + $ret .= ""; + $ret .= "\n"; + + # URL: [ ] Verify? [ ] + my $url_def = $form->{'oidurl'} || $oid_identity if defined $oid_identity; + + $ret .= "\n"; + } + } + + if ($journalu->{'opt_whocanreply'} eq "reg") { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + if (LJ::OpenID::consumer_enabled()) { + # OpenID - At some point we will include "trusted" + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + } + } + + if ($journalu->{'opt_whocanreply'} eq 'friends') { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + if (LJ::OpenID::consumer_enabled()) { + # OpenID - At some point we will include "trusted" + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + } + } + + if ($remote && !defined $oid_identity) { + $ret .= ""; + my $logged_in = LJ::ehtml($remote->display_name); + + # Don't worry about a real href since js hides the row anyway + my $other_user = ""; + + if (LJ::is_banned($remote, $journalu)) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + } else { + $ret .= ""; + $ret .= ""; + } + $ret .= "\n"; + } + + # ( ) LiveJournal user: + $ret .= ""; + $ret .= "\n"; + + if ($remote && ! defined $oid_identity) { + $ret .= ""; + } + + # Username: [ ] Password: [ ] Login? [ ] + $ret .= "\n"; + + # textarea for their message body + $ret .= "
    ('anonymous') . + " />"; + $ret .= " " . $BML::ML{'.opt.willscreen'} if $screening; + $ret .= "
    ('openid_cookie') . "/>"; + $ret .= " "; + + $ret .= "" . $remote->display_name . ""; + $ret .= $other_user . " "; + + $ret .= $BML::ML{'.opt.willscreen'} if $screening; + $ret .= "
    ('openid') . "/>"; + $ret .= " "; + + if (defined $LJ::HELPURL{'openid'}) { + $ret .= "$BML::ML{ "; + } + + $ret .= $BML::ML{'.opt.willscreen'} if $screening; + $ret .= "
    "; + $ret .= "Identity URL:  "; + $ret .= "
    {'oiddo_login'}; + $ret .= "/>
    $BML::ML{'.opt.from'}( )$BML::ML{'.opt.anonymous'}$BML::ML{'.opt.noanonpost'}
    ( )OpenID"; + + if (defined $LJ::HELPURL{'openid'}) { + $ret .= "$BML::ML{ "; + } + + $ret .= "
    ( )$BML::ML{'.opt.anonymous'}"; + $ret .= BML::ml(".opt.friendsonly", {'username'=>"$journalu->{'user'}"}); + $ret .= "
    ( )OpenID"; + + if (defined $LJ::HELPURL{'openid'}) { + $ret .= "$BML::ML{ "; + } + + $ret .= "
    ( )" . BML::ml(".opt.loggedin", {'username'=>"$logged_in"}) . "" . BML::ml(".opt.bannedfrom", {'journal'=>$journalu->{'user'}}) . $other_user . "('remote') . + " />\n"; + + $ret .= $other_user; + + $ret .= "\n"; + if ($screening eq 'A' || + ($screening eq 'F' && !LJ::is_friend($journalu, $remote))) { + $ret .= " " . $BML::ML{'.opt.willscreen'}; + } + $ret .= "
    ('ljuser') . "/>"; + $ret .= " "; + $ret .= $BML::ML{'.opt.willscreenfriend'} if $screening eq 'F'; + $ret .= $BML::ML{'.opt.willscreen'} if $screening eq 'A'; + $ret .= "
    "; + my $ljuser_def = ($form->{'userpost'} ne $form->{'cookieuser'} && $form->{'usertype'} ne 'anonymous') ? + BML::eall($form->{userpost}) : "$remote->{'user'}" unless $oid_identity; + + $ret .= "\n"; + } + + my $basesubject = $form->{subject} || ""; + if ($opts->{replyto} && !$basesubject && $parpost->{'subject'}) { + $basesubject = $parpost->{'subject'}; + $basesubject =~ s/^Re:\s*//i; + $basesubject = "Re: $basesubject"; + } + + # Closing internal "From" table + $ret .= "
    "; + $ret .= "$BML::ML{'Username'}:"; + $ret .= " "href='$LJ::SITEROOT/create.bml'"}); + $ret .= "
    "; + + # subject + $basesubject = BML::eall($basesubject) if $basesubject; + $ret .= "
    $BML::ML{'.opt.subject'}\n"; + + # Subject Icon toggle button + { + my $subjicon = $form->{subjecticon} || 'none'; + my $foundicon = 0; + $ret .= "\n"; + $ret .= "\n"; + } + + # finish off subject line + $ret .= "
    $BML::ML{'.nosubjecthtml'}
    \n"; + + $ret .= "
    "; + my %res; + if ($remote) { + LJ::do_request({ "mode" => "login", + "ver" => ($LJ::UNICODE ? "1" : "0"), + "user" => $remote->{'user'}, + "getpickws" => 1, + }, \%res, { "noauth" => 1, "userid" => $remote->{'userid'} }); + } + if ($res{'pickw_count'}) { + $ret .= BML::ml('.label.picturetouse2', + { + 'aopts'=>"href='$LJ::SITEROOT/allpics.bml?user=$remote->{'user'}'"}) . " "; + my @pics; + for (my $i=1; $i<=$res{'pickw_count'}; $i++) { + push @pics, $res{"pickw_$i"}; + } + @pics = sort { lc($a) cmp lc($b) } @pics; + $ret .= LJ::html_select({'name' => 'prop_picture_keyword', + 'selected' => $form->{'prop_picture_keyword'}, }, + ("", $BML::ML{'.opt.defpic'}, map { ($_, $_) } @pics)); + + if (defined $LJ::HELPURL{'userpics'}) { + $ret .= " $BML::ML{"; + } + } + $ret .= "
    "; + $ret .= "
    $BML::ML{'.opt.message'}
    "; + + # only show on initial compostion + my $quickquote; + unless ($opts->{errors} && @{$opts->{errors}}) { + # quick quote button + $quickquote = "
    " . LJ::ejs(''); + } + + $ret .= "\n"; + + $ret .= "
    "; + $ret .= ""; + + # Display captcha challenge if over rate limits. + if ($opts->{do_captcha}) { + my ($wants_audio, $captcha_sess, $captcha_chal); + $wants_audio = 1 if lc($form->{answer}) eq 'audio'; + + # Captcha sessions + my $cid = $journalu->{clusterid}; + $captcha_chal = $form->{captcha_chal} || LJ::challenge_generate(900); + $captcha_sess = LJ::get_challenge_attributes($captcha_chal); + my $dbcr = LJ::get_cluster_reader($journalu); + + my $try = 0; + if ($form->{captcha_chal}) { + $try = $dbcr->selectrow_array('SELECT trynum FROM captcha_session ' . + 'WHERE sess=?', undef, $captcha_sess); + } + $ret .= '

    '; + + # Visual challenge + if (! $wants_audio && ! $form->{audio_chal}) { + $ret .= "
    $BML::ML{'/create.bml.captcha.desc'}
    "; + $ret .= ""; + $ret .= "

    $BML::ML{'/create.bml.captcha.answer'}"; + } + # Audio challenge + else { + $ret .= "
    $BML::ML{'/create.bml.captcha.audiodesc'}
    "; + $ret .= "$BML::ML{'/create.bml.captcha.play'}   "; + $ret .= LJ::html_hidden(audio_chal => 1); + } + $ret .= LJ::html_text({ name =>'answer', size =>15 }); + $ret .= LJ::html_hidden(captcha_chal => $captcha_chal); + $ret .= '
    '; + } + + if ($LJ::SPELLER) { + $ret .= " "; + } + + $ret .= ""; + $ret .= LJ::html_check( + { + name => 'prop_opt_preformatted', + id => 'prop_opt_preformatted', + value => 1, + selected => $form->{'prop_opt_preformatted'} + } + ); + if (defined $LJ::HELPURL{'noautoformat'}) { + $ret .= " $BML::ML{"; + } + + # post and preview buttons + my $limit = LJ::CMAX_COMMENT; # javascript String.length uses characters + $ret .= < + + +LOGIN + + if ($journalu->{'opt_logcommentips'} eq "A") { + $ret .= "
    $BML::ML{'.logyourip'}"; + $ret .= LJ::help_icon("iplogging", " "); + } + if ($journalu->{'opt_logcommentips'} eq "S") { + $ret .= "
    $BML::ML{'.loganonip'}"; + $ret .= LJ::help_icon("iplogging", " "); + } + + $ret .= "
    \n"; + + # Some JavaScript to help the UI out + + $ret .= ""; + $ret .= "\n"; + + return $ret; +} + +# +# name: LJ::record_anon_comment_ip +# class: web +# des: Records the IP address of an anonymous comment +# args: journalu, jtalkid, ip +# des-journalu: User object of journal comment was posted in. +# des-jtalkid: ID of this comment. +# des-ip: IP address of the poster. +# returns: 1 for success, 0 for failure +# +sub record_anon_comment_ip { + my ($journalu, $jtalkid, $ip) = @_; + $journalu = LJ::want_user($journalu); + $jtalkid += 0; + return 0 unless LJ::isu($journalu) && $jtalkid && $ip; + + $journalu->do("INSERT INTO tempanonips (reporttime, journalid, jtalkid, ip) VALUES (UNIX_TIMESTAMP(),?,?,?)", + undef, $journalu->{userid}, $jtalkid, $ip); + return 0 if $journalu->err; + return 1; +} + +# +# name: LJ::mark_comment_as_spam +# class: web +# des: Copies a comment into the global spamreports table +# args: journalu, jtalkid +# des-journalu: User object of journal comment was posted in. +# des-jtalkid: ID of this comment. +# returns: 1 for success, 0 for failure +# +sub mark_comment_as_spam { + my ($journalu, $jtalkid) = @_; + $journalu = LJ::want_user($journalu); + $jtalkid += 0; + return 0 unless $journalu && $jtalkid; + + my $dbcr = LJ::get_cluster_def_reader($journalu); + my $dbh = LJ::get_db_writer(); + + # step 1: get info we need + my $row = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $jtalkid); + my $temp = LJ::get_talktext2($journalu, $jtalkid); + my ($subject, $body, $posterid) = ($temp->{$jtalkid}[0], $temp->{$jtalkid}[1], $row->{posterid}); + return 0 unless $body; + + # step 2: get ip if anon + my $ip; + unless ($posterid) { + $ip = $dbcr->selectrow_array('SELECT ip FROM tempanonips WHERE journalid=? AND jtalkid=?', + undef, $journalu->{userid}, $jtalkid); + return 0 if $dbcr->err; + + # we want to fail out if we have no IP address and this is anonymous, because otherwise + # we have a completely useless spam report. pretend we were successful, too. + return 1 unless $ip; + } + + # step 3: insert into spamreports + $dbh->do('INSERT INTO spamreports (reporttime, posttime, ip, journalid, posterid, subject, body) ' . + 'VALUES (UNIX_TIMESTAMP(), UNIX_TIMESTAMP(?), ?, ?, ?, ?, ?)', + undef, $row->{datepost}, $ip, $journalu->{userid}, $posterid, $subject, $body); + return 0 if $dbh->err; + return 1; +} + +# +# name: LJ::Talk::get_talk2_row +# class: web +# des: Gets a row of data from talk2. +# args: dbcr, journalid, jtalkid +# des-dbcr: Database handle to read from. +# des-journalid: Journal id that comment is posted in. +# des-jtalkid: Journal talkid of comment. +# returns: Hashref of row data, or undef on error. +# +sub get_talk2_row { + my ($dbcr, $journalid, $jtalkid) = @_; + return $dbcr->selectrow_hashref('SELECT journalid, jtalkid, nodetype, nodeid, parenttalkid, ' . + ' posterid, datepost, state ' . + 'FROM talk2 WHERE journalid = ? AND jtalkid = ?', + undef, $journalid+0, $jtalkid+0); +} + +# get a comment count for a journal entry. +sub get_replycount { + my ($ju, $jitemid) = @_; + $jitemid += 0; + return undef unless $ju && $jitemid; + + my $memkey = [$ju->{'userid'}, "rp:$ju->{'userid'}:$jitemid"]; + my $count = LJ::MemCache::get($memkey); + return $count if $count; + + my $dbcr = LJ::get_cluster_def_reader($ju); + return unless $dbcr; + + $count = $dbcr->selectrow_array("SELECT replycount FROM log2 WHERE " . + "journalid=? AND jitemid=?", undef, + $ju->{'userid'}, $jitemid); + LJ::MemCache::add($memkey, $count); + return $count; +} + +package LJ::Talk::Post; + +sub format_text_mail { + my ($targetu, $parent, $comment, $talkurl, $item) = @_; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + + $Text::Wrap::columns = 76; + + my $who = "Somebody"; + if ($comment->{u}) { + $who = "$comment->{u}{name} ($comment->{u}{user})"; + } + + my $text = ""; + if (LJ::u_equals($targetu, $comment->{u})) { + if ($parent->{ispost}) { + $who = "$parent->{u}{name} ($parent->{u}{user})"; + $text .= "You left a comment in a post by $who. "; + $text .= "The entry you replied to was:"; + } else { + $text .= "You left a comment in reply to another comment. "; + $text .= "The comment you replied to was:"; + } + } elsif (LJ::u_equals($targetu, $item->{entryu})) { + if ($parent->{ispost}) { + $text .= "$who replied to your $LJ::SITENAMESHORT post in which you said:"; + } else { + $text .= "$who replied to another comment somebody left in your $LJ::SITENAMESHORT post. "; + $text .= "The comment they replied to was:"; + } + } else { + $text .= "$who replied to your $LJ::SITENAMESHORT comment in which you said:"; + } + $text .= "\n\n"; + $text .= indent($parent->{body}, ">") . "\n\n"; + $text .= (LJ::u_equals($targetu, $comment->{u}) ? 'Your' : 'Their') . " reply was:\n\n"; + if ($comment->{subject}) { + $text .= Text::Wrap::wrap(" Subject: ", + " ", + $comment->{subject}) . "\n\n"; + } + $text .= indent($comment->{body}); + $text .= "\n\n"; + + my $can_unscreen = $comment->{state} eq 'S' && + LJ::Talk::can_unscreen($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef); + + if ($comment->{state} eq 'S') { + $text .= "This comment was screened. "; + $text .= $can_unscreen ? + "You must respond to it or unscreen it before others can see it.\n\n" : + "Someone else must unscreen it before you can reply to it.\n\n"; + } + + my $opts = ""; + $opts .= "Options:\n\n"; + $opts .= " - View the discussion:\n"; + $opts .= " " . LJ::Talk::talkargs($talkurl, "thread=$dtalkid") . "\n"; + $opts .= " - View all comments on the entry:\n"; + $opts .= " $talkurl\n"; + $opts .= " - Reply to the comment:\n"; + $opts .= " " . LJ::Talk::talkargs($talkurl, "replyto=$dtalkid") . "\n"; + if ($can_unscreen) { + $opts .= " - Unscreen the comment:\n"; + $opts .= " $LJ::SITEROOT/talkscreen.bml?mode=unscreen&journal=$item->{journalu}{user}&talkid=$dtalkid\n"; + } + if (LJ::Talk::can_delete($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef)) { + $opts .= " - Delete the comment:\n"; + $opts .= " $LJ::SITEROOT/delcomment.bml?journal=$item->{journalu}{user}&id=$dtalkid\n"; + } + + my $footer = ""; + $footer .= "-- $LJ::SITENAME\n\n"; + $footer .= "(If you'd prefer to not get these updates, go to $LJ::SITEROOT/editinfo.bml and turn off the relevant options.)"; + return Text::Wrap::wrap("", "", $text) . "\n" . $opts . "\n" . Text::Wrap::wrap("", "", $footer); +} + +sub format_html_mail { + my ($targetu, $parent, $comment, $encoding, $talkurl, $item) = @_; + my $ditemid = $item->{itemid}*256 + $item->{anum}; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + my $threadurl = LJ::Talk::talkargs($talkurl, "thread=$dtalkid"); + + my $who = "Somebody"; + if ($comment->{u}) { + $who = "$comment->{u}{name} ". + "({u}{user}\">$comment->{u}{user})"; + } + + my $html = ""; + $html .= "\n\n"; + + my $intro; + my $cleanbody = $parent->{body}; + if (LJ::u_equals($targetu, $comment->{u})) { + if ($parent->{ispost}) { + $who = "$parent->{u}{name} " . + "({u}{user}\">$parent->{u}{user})"; + $intro = "You replied to a $LJ::SITENAMESHORT post in which $who said:"; + LJ::CleanHTML::clean_event(\$cleanbody, {preformatted => $parent->{preformat}}); + } else { + $intro = "You replied to a comment somebody left in "; + $intro .= "a $LJ::SITENAMESHORT post. "; + $intro .= "The comment you replied to was:"; + LJ::CleanHTML::clean_comment(\$cleanbody, { 'preformatted' => $parent->{preformat}, + 'anon_comment' => !$comment->{u} }); + } + } elsif (LJ::u_equals($targetu, $item->{entryu})) { + if ($parent->{ispost}) { + $intro = "$who replied to your $LJ::SITENAMESHORT post in which you said:"; + LJ::CleanHTML::clean_comment(\$cleanbody, { 'preformatted' => $parent->{preformat}, + 'anon_comment' => !$comment->{u} }); + } else { + $intro = "$who replied to another comment somebody left in "; + $intro .= "your $LJ::SITENAMESHORT post. "; + $intro .= "The comment they replied to was:"; + LJ::CleanHTML::clean_comment(\$cleanbody, { 'preformatted' => $parent->{preformat}, + 'anon_comment' => !$comment->{u} }); + } + } else { + $intro = "$who replied to your $LJ::SITENAMESHORT comment "; + $intro .= "in which you said:"; + LJ::CleanHTML::clean_comment(\$cleanbody, { 'preformatted' => $parent->{preformat}, + 'anon_comment' => !$comment->{u} }); + } + + my $pichtml; + if ($comment->{u} && $comment->{u}{defaultpicid} || $comment->{pic}) { + my $picid = $comment->{pic} ? $comment->{pic}{'picid'} : $comment->{u}{'defaultpicid'}; + unless ($comment->{pic}) { + my %pics; + LJ::load_userpics(\%pics, [ $comment->{u}, $comment->{u}{'defaultpicid'} ]); + $comment->{pic} = $pics{$picid}; + # load_userpics doesn't return picid, but we rely on it above + $comment->{pic}{'picid'} = $picid; + } + if ($comment->{pic}) { + $pichtml = "{pic}{'userid'}\" align='absmiddle' ". + "width='$comment->{pic}{'width'}' height='$comment->{pic}{'height'}' ". + "hspace='1' vspace='2' alt='' /> "; + } + } + + if ($pichtml) { + $html .= "
    $pichtml$intro
    \n"; + } else { + $html .= "
    $intro
    \n"; + } + $html .= blockquote($cleanbody); + + $html .= "\n\n" . (LJ::u_equals($targetu, $comment->{u}) ? 'Your' : 'Their') . " reply was:\n\n"; + $cleanbody = $comment->{body}; + LJ::CleanHTML::clean_comment(\$cleanbody, $comment->{preformat}); + my $pics = LJ::Talk::get_subjecticons(); + my $icon = LJ::Talk::show_image($pics, $comment->{subjecticon}); + + my $heading; + if ($comment->{subject}) { + $heading = "Subject: " . LJ::ehtml($comment->{subject}); + } + $heading .= $icon; + $heading .= "
    " if $heading; + # this needs to be one string so blockquote handles it properly. + $html .= blockquote("$heading$cleanbody"); + + my $can_unscreen = $comment->{state} eq 'S' && + LJ::Talk::can_unscreen($targetu, $item->{journalu}, $item->{entryu}, + $comment->{u} ? $comment->{u}{user} : undef); + + if ($comment->{state} eq 'S') { + $html .= "

    This comment was screened. "; + $html .= $can_unscreen ? + "You must respond to it or unscreen it before others can see it.

    \n" : + "Someone else must unscreen it before you can reply to it.

    \n"; + } + + $html .= "

    From here, you can:\n"; + $html .= "

    "; + + my $want_form = $comment->{state} eq 'A' || $can_unscreen; # this should probably be a preference, or maybe just always off. + if ($want_form) { + $html .= "If your mail client supports it, you can also reply here:\n"; + $html .= "
    \n"; + + $html .= LJ::html_hidden( + usertype => "user", + parenttalkid => $comment->{talkid}, + itemid => $ditemid, + journal => $item->{journalu}{user}, + userpost => $targetu->{user}, + ecphash => LJ::Talk::ecphash($item->{itemid}, $comment->{talkid}, $targetu->{password}) + ); + + $html .= "" unless $encoding eq "UTF-8"; + my $newsub = $comment->{subject}; + unless (!$newsub || $newsub =~ /^Re:/) { $newsub = "Re: $newsub"; } + $html .= "Subject: "; + $html .= "

    Message
    "; + $html .= "
    "; + $html .= "

    \n"; + } + $html .= "

    (If you'd prefer to not get these updates, go to your user profile page and turn off the relevant options.)

    \n"; + $html .= "\n"; + + return $html; +} + +sub indent { + my $a = shift; + my $leadchar = shift || " "; + $Text::Wrap::columns = 76; + return Text::Wrap::fill("$leadchar ", "$leadchar ", $a); +} + +sub blockquote { + my $a = shift; + return "
    $a
    "; +} + +sub generate_messageid { + my ($type, $journalu, $did) = @_; + # $type = {"entry" | "comment"} + # $journalu = $u of journal + # $did = display id of comment/entry + + my $jid = $journalu->{userid}; + return "<$type-$jid-$did\@$LJ::DOMAIN>"; +} + +# entryu : user who posted the entry this comment is under. +# journalu : journal this entry is in. +# parent : comment/entry this post is in response to. +# comment : the comment itself. +# item : entry this comment falls under. +sub mail_comments { + my ($entryu, $journalu, $parent, $comment, $item) = @_; + my $itemid = $item->{itemid}; + my $ditemid = $itemid*256 + $item->{anum}; + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + my $talkurl = LJ::journal_base($journalu) . "/$ditemid.html"; + my $threadurl = LJ::Talk::talkargs($talkurl, "thread=$dtalkid"); + + # check to see if parent post is from a registered livejournal user, and + # mail them the response + my $parentcomment = ""; + my $parentmailed = ""; # who if anybody was just mailed + + # message ID of the mythical top-level journal entry (which + # currently is never emailed) so mail clients can group things + # together with a comment ancestor if parents are missing + my $top_msgid = generate_messageid("entry", $journalu, $ditemid); + # find first parent + my $par_msgid; + if (my $ptid = $parent->{talkid}) { + $par_msgid = generate_messageid("comment", $journalu, + $ptid * 256 + $item->{anum}); + } else { + # is a reply to the top-level + $par_msgid = $top_msgid; + $top_msgid = ""; # so it's not duplicated + } + # and this message ID + my $this_msgid = generate_messageid("comment", $journalu, $dtalkid); + + # if a response to another comment, send a mail to the parent commenter. + if ($parent->{talkid}) { + my $dbcr = LJ::get_cluster_def_reader($journalu); + + # get row of data + my $row = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $parent->{talkid}); + my $paruserid = $row->{posterid}; + + # now get body of comment + my $temp = LJ::get_talktext2($journalu, $parent->{talkid}); + my $parbody = $temp->{$parent->{talkid}}[1]; + LJ::text_uncompress(\$parbody); + $parentcomment = $parbody; + + my %props = ($parent->{talkid} => {}); + LJ::load_talk_props2($dbcr, $journalu->{'userid'}, [$parent->{talkid}], \%props); + $parent->{preformat} = $props{$parent->{talkid}}->{'opt_preformatted'}; + + # convert to UTF-8 if necessary + my $parentsubject = $parent->{subject}; + if ($LJ::UNICODE && $props{$parent->{talkid}}->{'unknown8bit'}) { + LJ::item_toutf8($journalu, \$parentsubject, \$parentcomment, {}); + } + + if ($paruserid) { + my $paru = LJ::load_userid($paruserid); + LJ::load_user_props($paru, 'mailencoding'); + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + + # we don't want to send email to a parent if the email address on the + # parent's user is the same as the email address on this comment's user + # is_diff_email: also so we don't auto-vivify $comment->{u} + my $is_diff_email = !$comment->{u} || + $paru->{'email'} ne $comment->{u}{'email'}; + + if ($paru->{'opt_gettalkemail'} eq "Y" && + $is_diff_email && + $paru->{'status'} eq "A") + { + $parentmailed = $paru->{'email'}; + my $encoding = $paru->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$paru->{'mailencoding'}} : "UTF-8"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $fromname = $comment->{u} ? "$comment->{u}{'user'} - $LJ::SITENAMEABBREV Comment" : "$LJ::SITENAMESHORT Comment"; + + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)", + 'To' => $paru->{'email'}, + 'Subject' => ($headersubject || "Reply to your comment..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + $parent->{u} = $paru; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + my $text = format_text_mail($paru, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + + if ($paru->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($paru, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + } + + LJ::send_mail($msg); + } + } + } + + # send mail to the poster of the entry + if ($entryu->{'opt_gettalkemail'} eq "Y" && + !$item->{props}->{'opt_noemail'} && + !LJ::u_equals($comment->{u}, $entryu) && + $entryu->{'email'} ne $parentmailed && + $entryu->{'status'} eq "A") + { + LJ::load_user_props($entryu, 'mailencoding'); + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + my $encoding = $entryu->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$entryu->{'mailencoding'}} : "UTF-8"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $fromname = $comment->{u} ? "$comment->{u}{'user'} - $LJ::SITENAMEABBREV Comment" : "$LJ::SITENAMESHORT Comment"; + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)", + 'To' => $entryu->{'email'}, + 'Subject' => ($headersubject || "Reply to your post..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + my $quote = $parentcomment ? $parentcomment : $item->{'event'}; + + # if this is a response to a comment inside our journal, + # we don't know who made the parent comment + # (and it's potentially anonymous). + if ($parentcomment) { + $parent->{u} = undef; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + } else { + $parent->{u} = $entryu; + $parent->{body} = $item->{'event'}, + $parent->{ispost} = 1; + $parent->{preformat} = $item->{'props'}->{'opt_preformatted'}; + } + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + + my $text = format_text_mail($entryu, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + + if ($entryu->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($entryu, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + } + + LJ::send_mail($msg); + } + + # now send email to the person who posted the comment we're using? only if userprop + # opt_getselfemail is turned on. no need to check for active/suspended accounts, as + # they couldn't have posted if they were. (and if they did somehow, we're just emailing + # them, so it shouldn't matter.) + my $u = $comment->{u}; + LJ::load_user_props($u, 'opt_getselfemail', 'mailencoding') if $u; + if ($u && $u->{'opt_getselfemail'} && LJ::get_cap($u, 'getselfemail')) { + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + my $encoding = $u->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$u->{'mailencoding'}} : "UTF-8"; + my $part; + + my $headersubject = $comment->{subject}; + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $headersubject = Unicode::MapUTF8::from_utf8({-string=>$headersubject, -charset=>$encoding}); + } + + if (!LJ::is_ascii($headersubject)) { + $headersubject = MIME::Words::encode_mimeword($headersubject, 'B', $encoding); + } + + my $msg = new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($u->{'user'} - $LJ::SITENAMEABBREV Comment)", + 'To' => $u->{'email'}, + 'Subject' => ($headersubject || "Comment you posted..."), + 'Type' => 'multipart/alternative', + 'Message-Id' => $this_msgid, + 'In-Reply-To:' => $par_msgid, + 'References' => "$top_msgid $par_msgid", + ); + $msg->add('X-LJ-JOURNAL' => $journalu->{'user'}); # for mail filters + + my $quote = $parentcomment ? $parentcomment : $item->{'event'}; + + # if this is a response to a comment inside our journal, + # we don't know who made the parent comment + # (and it's potentially anonymous). + if ($parentcomment) { + $parent->{u} = undef; + $parent->{body} = $parentcomment; + $parent->{ispost} = 0; + } else { + $parent->{u} = $entryu; + $parent->{body} = $item->{'event'}, + $parent->{ispost} = 1; + $parent->{preformat} = $item->{'props'}->{'opt_preformatted'}; + } + $item->{entryu} = $entryu; + $item->{journalu} = $journalu; + + my $text = format_text_mail($u, $parent, $comment, $talkurl, $item); + + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'TEXT', + 'Data' => $text, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + + if ($u->{'opt_htmlemail'} eq "Y") { + my $html = format_html_mail($u, $parent, $comment, $encoding, $talkurl, $item); + if ($LJ::UNICODE && $encoding ne "UTF-8") { + $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding}); + } + $part = $msg->attach('Type' => 'text/html', + 'Data' => $html, + 'Encoding' => 'quoted-printable', + ); + $part->attr("content-type.charset" => $encoding) + if $LJ::UNICODE; + } + + LJ::send_mail($msg); + + } +} + +sub enter_comment { + my ($journalu, $parent, $item, $comment, $errref) = @_; + + my $partid = $parent->{talkid}; + my $itemid = $item->{itemid}; + + my $err = sub { + $$errref = join(": ", @_); + return 0; + }; + + return $err->("Invalid user object passed.") + unless LJ::isu($journalu); + + my $jtalkid = LJ::alloc_user_counter($journalu, "T"); + return $err->("Database Error", "Could not generate a talkid necessary to post this comment.") + unless $jtalkid; + + # insert the comment + my $posterid = $comment->{u} ? $comment->{u}{userid} : 0; + + my $errstr; + $journalu->talk2_do("L", $itemid, \$errstr, + "INSERT INTO talk2 ". + "(journalid, jtalkid, nodetype, nodeid, parenttalkid, posterid, datepost, state) ". + "VALUES (?,?,'L',?,?,?,NOW(),?)", + $journalu->{userid}, $jtalkid, $itemid, $partid, $posterid, $comment->{state}); + if ($errstr) { + return $err->("Database Error", + "There was an error posting your comment to the database. " . + "Please report this. The error is: $errstr"); + } + + LJ::MemCache::incr([$journalu->{'userid'}, "talk2ct:$journalu->{'userid'}"]); + + $comment->{talkid} = $jtalkid; + + # record IP if anonymous + LJ::Talk::record_anon_comment_ip($journalu, $comment->{talkid}, LJ::get_remote_ip()) + unless $posterid; + + # add to poster's talkleft table, or the xfer place + if ($posterid) { + my $table; + my $db = LJ::get_cluster_master($comment->{u}); + + if ($db) { + # remote's cluster is writable + $table = "talkleft"; + } else { + # log to global cluster, another job will move it later. + $db = LJ::get_db_writer(); + $table = "talkleft_xfp"; + } + my $pub = $item->{'security'} eq "public" ? 1 : 0; + if ($db) { + $db->do("INSERT INTO $table (userid, posttime, journalid, nodetype, ". + "nodeid, jtalkid, publicitem) VALUES (?, UNIX_TIMESTAMP(), ". + "?, 'L', ?, ?, ?)", undef, + $posterid, $journalu->{userid}, $itemid, $jtalkid, $pub); + + LJ::MemCache::incr([$posterid, "talkleftct:$posterid"]); + } else { + # both primary and backup talkleft hosts down. can't do much now. + } + } + + $journalu->do("INSERT INTO talktext2 (journalid, jtalkid, subject, body) ". + "VALUES (?, ?, ?, ?)", undef, + $journalu->{userid}, $jtalkid, $comment->{subject}, + LJ::text_compress($comment->{body})); + die $journalu->errstr if $journalu->err; + + my $memkey = "$journalu->{'clusterid'}:$journalu->{'userid'}:$jtalkid"; + LJ::MemCache::set([$journalu->{'userid'},"talksubject:$memkey"], $comment->{subject}); + LJ::MemCache::set([$journalu->{'userid'},"talkbody:$memkey"], $comment->{body}); + + # dudata + my $bytes = length($comment->{subject}) + length($comment->{body}); + # we used to do a LJ::dudata_set(..) on 'T' here, but decided + # we could defer that. to find size of a journal, summing + # bytes in dudata is too slow (too many seeks) + + my %talkprop; # propname -> value + # meta-data + $talkprop{'unknown8bit'} = 1 if $comment->{unknown8bit}; + $talkprop{'subjecticon'} = $comment->{subjecticon}; + + $talkprop{'picture_keyword'} = $comment->{picture_keyword}; + + $talkprop{'opt_preformatted'} = $comment->{preformat} ? 1 : 0; + if ($journalu->{'opt_logcommentips'} eq "A" || + ($journalu->{'opt_logcommentips'} eq "S" && $comment->{usertype} ne "user")) + { + my $ip = BML::get_remote_ip(); + my $forwarded = BML::get_client_header('X-Forwarded-For'); + $ip = "$forwarded, via $ip" if $forwarded && $forwarded ne $ip; + $talkprop{'poster_ip'} = $ip; + } + + # remove blank/0 values (defaults) + foreach (keys %talkprop) { delete $talkprop{$_} unless $talkprop{$_}; } + + # update the talkprops + LJ::load_props("talk"); + if (%talkprop) { + my $values; + my $hash = {}; + foreach (keys %talkprop) { + my $p = LJ::get_prop("talk", $_); + next unless $p; + $hash->{$_} = $talkprop{$_}; + my $tpropid = $p->{'tpropid'}; + my $qv = $journalu->quote($talkprop{$_}); + $values .= "($journalu->{'userid'}, $jtalkid, $tpropid, $qv),"; + } + if ($values) { + chop $values; + $journalu->do("INSERT INTO talkprop2 (journalid, jtalkid, tpropid, value) ". + "VALUES $values"); + die $journalu->errstr if $journalu->err; + } + LJ::MemCache::set([$journalu->{'userid'}, "talkprop:$journalu->{'userid'}:$jtalkid"], $hash); + } + + # record up to 25 (or $LJ::TALK_MAX_URLS) urls from a comment + my (%urls, $dbh); + if ($LJ::TALK_MAX_URLS && + ( %urls = map { $_ => 1 } LJ::get_urls($comment->{body}) ) && + ( $dbh = LJ::get_db_writer() )) # don't log if no db available + { + my (@bind, @vals); + my $ip = LJ::get_remote_ip(); + while (my ($url, undef) = each %urls) { + push @bind, '(?,?,?,?,UNIX_TIMESTAMP(),?)'; + push @vals, $posterid, $journalu->{userid}, $ip, $jtalkid, $url; + last if @bind >= $LJ::TALK_MAX_URLS; + } + my $bind = join(',', @bind); + my $sql = qq{ + INSERT DELAYED INTO commenturls + (posterid, journalid, ip, jtalkid, timecreate, url) + VALUES $bind + }; + $dbh->do($sql, undef, @vals); + } + + # update the "replycount" summary field of the log table + if ($comment->{state} eq 'A') { + LJ::replycount_do($journalu, $itemid, "incr"); + } + + # update the "hasscreened" property of the log item if needed + if ($comment->{state} eq 'S') { + LJ::set_logprop($journalu, $itemid, { 'hasscreened' => 1 }); + } + + # update the comment alter property + LJ::Talk::update_commentalter($journalu, $itemid); + return $jtalkid; +} + +# XXX these strings should be in talk, but moving them means we have +# to retranslate. so for now we're just gonna put it off. +my $SC = '/talkpost_do.bml'; + +sub init { + my ($form, $remote, $need_captcha, $errret) = @_; + my $sth; + + my $err = sub { + my $error = shift; + push @$errret, $error; + return undef; + }; + my $bmlerr = sub { + return $err->($BML::ML{$_[0]}); + }; + + my $init = LJ::Talk::init($form); + return $err->($init->{error}) if $init->{error}; + + my $journalu = $init->{'journalu'}; + return $bmlerr->('talk.error.nojournal') unless $journalu; + return $err->($LJ::MSG_READONLY_USER) if LJ::get_cap($journalu, "readonly"); + + return $err->("Account is locked, unable to post comment.") if $journalu->{statusvis} eq 'L'; + + my $r = Apache->request; + $r->notes("journalid" => $journalu->{'userid'}); + + my $dbcr = LJ::get_cluster_def_reader($journalu); + return $bmlerr->('error.nodb') unless $dbcr; + + my $itemid = $init->{'itemid'}+0; + + my $item = LJ::Talk::get_journal_item($journalu, $itemid); + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + return $bmlerr->('talk.error.noentry'); + } + + my $iprops = $item->{'props'}; + my $ditemid = $init->{'ditemid'}+0; + + my $talkurl = LJ::journal_base($journalu) . "/$ditemid.html"; + $init->{talkurl} = $talkurl; + + ### load users + LJ::load_userids_multiple([ + $item->{'posterid'} => \$init->{entryu}, + ], [ $journalu ]); + LJ::load_user_props($journalu, "opt_logcommentips"); + + if ($form->{'userpost'} && $form->{'usertype'} ne "user") { + unless ($form->{'usertype'} eq "cookieuser" && + $form->{'userpost'} eq $form->{'cookieuser'}) { + $bmlerr->("$SC.error.confused_identity"); + } + } + + # anonymous/cookie users cannot authenticate with ecphash + if ($form->{'ecphash'} && $form->{'usertype'} ne "user") { + $bmlerr->("$SC.error.badusername"); + return undef; + } + + my $cookie_auth; + if ($form->{'usertype'} eq "cookieuser") { + $bmlerr->("$SC.error.lostcookie") + unless ($remote && $remote->{'user'} eq $form->{'cookieuser'}); + return undef if @$errret; + + $cookie_auth = 1; + $form->{'userpost'} = $remote->{'user'}; + $form->{'usertype'} = "user"; + } + # XXXevan hack: remove me when we fix preview. + $init->{cookie_auth} = $cookie_auth; + + # test accounts may only comment on other test accounts. + if ((grep { $form->{'userpost'} eq $_ } @LJ::TESTACCTS) && + !(grep { $journalu->{'user'} eq $_ } @LJ::TESTACCTS)) + { + $bmlerr->("$SC.error.testacct"); + } + + my $userpost = lc($form->{'userpost'}); + my $up; # user posting + my $exptype; # set to long if ! after username + my $ipfixed; # set to remote ip if < after username + my $used_ecp; # ecphash was validated and used + + if ($form->{'usertype'} eq "user") { + if ($form->{'userpost'}) { + + # parse inline login opts + if ($form->{'userpost'} =~ s/[!<]{1,2}$//) { + $exptype = 'long' if index($&, "!") >= 0; + $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; + } + + $up = LJ::load_user($form->{'userpost'}); + if ($up) { + ### see if the user is banned from posting here + if (LJ::is_banned($up, $journalu)) { + $bmlerr->("$SC.error.banned"); + } + + unless ($up->{'journaltype'} eq "P" || + ($up->{'journaltype'} eq "I" && $cookie_auth)) { + $bmlerr->("$SC.error.postshared"); + } + + # if we're already authenticated via cookie, then userpost was set + # to the authenticated username, so we got into this block, but we + # don't want to re-authenticate, so just skip this + unless ($cookie_auth) { + + # if ecphash present, authenticate on that + if ($form->{'ecphash'}) { + + if ($form->{'ecphash'} eq + LJ::Talk::ecphash($itemid, $form->{'parenttalkid'}, $up->{'password'})) + { + $used_ecp = 1; + } else { + $bmlerr->("$SC.error.badpassword"); + } + + # otherwise authenticate on username/password + } else { + my $ok; + if ($form->{response}) { + $ok = LJ::challenge_check_login($up, $form->{chal}, $form->{response}); + } else { + $ok = LJ::auth_okay($up, $form->{'password'}, $form->{'hpassword'}); + } + $bmlerr->("$SC.error.badpassword") unless $ok; + } + } + + # if the user chooses to log in, do so + if ($form->{'do_login'} && ! @$errret) { + $init->{didlogin} = $up->make_login_session($exptype, $ipfixed); + } + } else { + $bmlerr->("$SC.error.badusername"); + } + } else { + $bmlerr->("$SC.error.nousername"); + } + } + + # OpenID + if (LJ::OpenID::consumer_enabled() && ($form->{'usertype'} eq 'openid' || $form->{'usertype'} eq 'openid_cookie')) { + return $err->("No OpenID identity URL entered") unless $form->{'oidurl'}; + + use LJ::OpenID; # to-TOP + + if ($remote && defined $remote->openid_identity) { + $up = $remote; + + if ($form->{'oiddo_login'}) { + $up->make_login_session($form->{'exptype'}, $form->{'ipfixed'}); + } + } else { # First time through + my $csr = LJ::OpenID::consumer(); + my $exptype = 'short'; + my $ipfixed = 0; + my $etime = 0; + + # parse inline login opts + if ($form->{'oidurl'} =~ s/[!<]{1,2}$//) { + if (index($&, "!") >= 0) { + $exptype = 'long'; + $etime = time()+60*60*24*60; + } + $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; + } + + my $tried_local_ref = LJ::OpenID::blocked_hosts($csr); + + my $claimed_id = $csr->claimed_identity($form->{'oidurl'}); + + unless ($claimed_id) { + return $err->("You can't use a $LJ::SITENAMESHORT OpenID account on $LJ::SITENAME — ". + "just go login with your actual $LJ::SITENAMESHORT account.") if $$tried_local_ref; + return $err->("No claimed id: ".$csr->err); + } + + # Store their cleaned up identity url vs what they + # actually typed in + $form->{'oidurl'} = $claimed_id->claimed_url(); + + # Store the entry + my $pendcid = LJ::alloc_user_counter($journalu, "C"); + + $err->("Unable to allocate pending id") unless $pendcid; + + # Since these were gotten from the oidurl and won't + # persist in the form data + $form->{'exptype'} = $exptype; + $form->{'etime'} = $etime; + $form->{'ipfixed'} = $ipfixed; + my $penddata = Storable::freeze($form); + + $err->("Unable to get database handle to store pending comment") unless $journalu->writer; + + $journalu->do("INSERT INTO pendcomments (jid, pendcid, data, datesubmit) VALUES (?, ?, ?, UNIX_TIMESTAMP())", undef, $journalu->{'userid'}, $pendcid, $penddata); + + $err->($journalu->errstr) if $journalu->err; + + my $check_url = $claimed_id->check_url( + return_to => "$LJ::SITEROOT/talkpost_do.bml?jid=$journalu->{'userid'}&pendcid=$pendcid", + trust_root => "http://*.$LJ::DOMAIN/", + delayed_return => 1, + ); + # Don't redirect them if errors + return undef if @$errret; + return BML::redirect($check_url); + } + } + + # validate the challenge/response value (anti-spammer) + unless ($used_ecp) { + my $chrp_err; + if (my $chrp = $form->{'chrp1'}) { + my ($c_ditemid, $c_uid, $c_time, $c_chars, $c_res) = + split(/\-/, $chrp); + my $chal = "$c_ditemid-$c_uid-$c_time-$c_chars"; + my $secret = LJ::get_secret($c_time); + my $res = Digest::MD5::md5_hex($secret . $chal); + if ($res ne $c_res) { + $chrp_err = "invalid"; + } elsif ($c_time < time() - 2*60*60) { + $chrp_err = "too_old" if $LJ::REQUIRE_TALKHASH_NOTOLD; + } + } else { + $chrp_err = "missing"; + } + if ($chrp_err) { + my $ip = LJ::get_remote_ip(); + if ($LJ::DEBUG_TALKSPAM) { + my $ruser = $remote ? $remote->{user} : "[nonuser]"; + print STDERR "talkhash error: from $ruser \@ $ip - $chrp_err - $talkurl\n"; + } + if ($LJ::REQUIRE_TALKHASH) { + return $err->("Sorry, form expired. Press back, copy text, reload form, paste into new form, and re-submit.") + if $chrp_err eq "too_old"; + return $err->("Missing parameters"); + } + } + } + + # check that user can even view this post, which is required + # to reply to it + #### Check security before viewing this post + unless (LJ::can_view($up, $item)) { + $bmlerr->("$SC.error.mustlogin") unless (defined $up); + $bmlerr->("$SC.error.noauth"); + return undef; + } + + # If the reply is to a comment, check that it exists. + # if it's screened, check that the user has permission to + # reply and unscreen it + + my $parpost; + my $partid = $form->{'parenttalkid'}+0; + + if ($partid) { + $parpost = LJ::Talk::get_talk2_row($dbcr, $journalu->{userid}, $partid); + unless ($parpost) { + $bmlerr->("$SC.error.noparent"); + } + + # can't use $remote because we may get here + # with a reply from email. so use $up instead of $remote + # in the call below. + + if ($parpost && $parpost->{'state'} eq "S" && + !LJ::Talk::can_unscreen($up, $journalu, $init->{entryu}, $init->{entryu}{'user'})) { + $bmlerr->("$SC.error.screened"); + } + } + $init->{parpost} = $parpost; + + # don't allow anonymous comments on syndicated items + if ($journalu->{'journaltype'} eq "Y" && $journalu->{'opt_whocanreply'} eq "all") { + $journalu->{'opt_whocanreply'} = "reg"; + } + + if ($form->{'usertype'} ne "user" && $journalu->{'opt_whocanreply'} ne "all") { + $bmlerr->("$SC.error.noanon"); + } + + if ($iprops->{'opt_nocomments'}) { + $bmlerr->("$SC.error.nocomments"); + } + + if ($up) { + if ($up->{'status'} eq "N" && $up->{'journaltype'} ne "I") { + $bmlerr->("$SC.error.noverify"); + } + if ($up->{'statusvis'} eq "D") { + $bmlerr->("$SC.error.deleted"); + } elsif ($up->{'statusvis'} eq "S") { + $bmlerr->("$SC.error.suspended"); + } + } + + if ($journalu->{'opt_whocanreply'} eq "friends") { + if ($up) { + if ($up->{'userid'} != $journalu->{'userid'}) { + unless (LJ::is_friend($journalu, $up)) { + $err->(BML::ml("$SC.error.notafriend", {'user'=>$journalu->{'user'}})); + } + } + } else { + $err->(BML::ml("$SC.error.friendsonly", {'user'=>$journalu->{'user'}})); + } + } + + $bmlerr->("$SC.error.blankmessage") unless $form->{'body'} =~ /\S/; + + # in case this post comes directly from the user's mail client, it + # may have an encoding field for us. + if ($form->{'encoding'}) { + $form->{'body'} = Unicode::MapUTF8::to_utf8({-string=>$form->{'body'}, -charset=>$form->{'encoding'}}); + $form->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$form->{'subject'}, -charset=>$form->{'encoding'}}); + } + + # unixify line-endings + $form->{'body'} =~ s/\r\n/\n/g; + + # now check for UTF-8 correctness, it must hold + + return $err->("") unless LJ::text_in($form); + + $init->{unknown8bit} = 0; + unless (LJ::is_ascii($form->{'body'}) && LJ::is_ascii($form->{'subject'})) { + if ($LJ::UNICODE) { + # no need to check if they're well-formed, we did that above + } else { + # so rest of site can change chars to ? marks until + # default user's encoding is set. (legacy support) + $init->{unknown8bit} = 1; + } + } + + my ($bl, $cl) = LJ::text_length($form->{'body'}); + if ($cl > LJ::CMAX_COMMENT) { + $err->(BML::ml("$SC.error.manychars", {'current'=>$cl, 'limit'=>LJ::CMAX_COMMENT})); + } elsif ($bl > LJ::BMAX_COMMENT) { + $err->(BML::ml("$SC.error.manybytes", {'current'=>$bl, 'limit'=>LJ::BMAX_COMMENT})); + } + # the Subject can be silently shortened, no need to reject the whole comment + $form->{'subject'} = LJ::text_trim($form->{'subject'}, 100, 100); + + my $subjecticon = ""; + if ($form->{'subjecticon'} ne "none" && $form->{'subjecticon'} ne "") { + $subjecticon = LJ::trim(lc($form->{'subjecticon'})); + } + + # figure out whether to post this comment screened + my $state = 'A'; + my $screening = LJ::Talk::screening_level($journalu, $ditemid >> 8); + if ($screening eq 'A' || + ($screening eq 'R' && ! $up) || + ($screening eq 'F' && !($up && LJ::is_friend($journalu, $up)))) { + $state = 'S'; + } + $state = 'A' if LJ::Talk::can_unscreen($up, $journalu, $init->{entryu}, $init->{entryu}{user}); + + my $parent = { + state => $parpost->{state}, + talkid => $partid, + }; + my $comment = { + u => $up, + usertype => $form->{'usertype'}, + subject => $form->{'subject'}, + body => $form->{'body'}, + unknown8bit => $init->{unknown8bit}, + subjecticon => $subjecticon, + preformat => $form->{'prop_opt_preformatted'}, + picture_keyword => $form->{'prop_picture_keyword'}, + state => $state, + }; + + $init->{item} = $item; + $init->{parent} = $parent; + $init->{comment} = $comment; + + # anti-spam captcha check + if (ref $need_captcha eq 'SCALAR') { + + # see if they're in the second+ phases of a captcha check. + # are they sending us a response? + if ($form->{captcha_chal}) { + + # assume they won't pass and re-set the flag + $$need_captcha = 1; + + # if they typed "audio", we don't double-check if they still need + # a captcha (they still do), they just want an audio version. + if (lc($form->{answer}) eq 'audio') { + return; + } + + my ($capid, $anum) = LJ::Captcha::session_check_code($form->{captcha_chal}, + $form->{answer}, $journalu); + + return $err->("Incorrect response to spam robot challenge.") unless $capid && $anum; + my $expire_u = $comment->{'u'} || LJ::load_user('system'); + LJ::Captcha::expire($capid, $anum, $expire_u->{userid}); + + } else { + + my $show_captcha = sub { + return 1 if $LJ::HUMAN_CHECK{'comment_html_auth'}; + + # Anonymous commenter + return 1 if $LJ::HUMAN_CHECK{'comment_html_anon'} && ! LJ::isu($comment->{'u'}); + + # Identity commenter + return 1 if $LJ::HUMAN_CHECK{'comment_html_anon'} && + $comment->{'u'}->identity() && + ! LJ::is_friend($journalu, $comment->{'u'}); + }; + + $$need_captcha = + ($LJ::HUMAN_CHECK{anonpost} || $LJ::HUMAN_CHECK{authpost}) && + ! LJ::Talk::Post::check_rate($comment->{'u'}, $journalu); + + if ($show_captcha->()) { + # see if they have any tags or URLs + if ($form->{'body'} =~ /<[a-z]/i) { + # strip white-listed bare tags w/o attributes, + # then see if they still have HTML. if so, it's + # questionable. (can do evil spammy-like stuff w/ + # attributes and other elements) + my $body_copy = $form->{'body'}; + $body_copy =~ s/<(?:q|blockquote|b|strong|i|em|cite|sub|sup|var|del|tt|code|pre|p)>//ig; + $$need_captcha = 1 if $body_copy =~ /<[a-z]/i; + } + # multiple URLs is questionable too + $$need_captcha = 1 if + $form->{'body'} =~ /\b(?:http|ftp)\b.+\b(?:http|ftp)\b/s; + } + + # if the user is anonymous and the IP is marked, ignore rates and always human test. + $$need_captcha = 1 if $LJ::HUMAN_CHECK{anonpost} && + ! $comment->{'u'} && + LJ::sysban_check('talk_ip_test', LJ::get_remote_ip()); + + if ($$need_captcha) { + return $err->("Please confirm you are a human below."); + } + } + } + + return undef if @$errret; + return $init; +} + +# returns 1 on success. 0 on fail (with $$errref set) +sub post_comment { + my ($entryu, $journalu, $comment, $parent, $item, $errref) = @_; + + # unscreen the parent comment if needed + if ($parent->{state} eq 'S') { + LJ::Talk::unscreen_comment($journalu, $item->{itemid}, $parent->{talkid}); + $parent->{state} = 'A'; + } + + # make sure they're not underage + if ($comment->{u} && $comment->{u}->underage) { + $$errref = $LJ::UNDERAGE_ERROR; + return 0; + } + + # check for duplicate entry (double submission) + # Note: we don't do it inside a locked section like ljprotocol.pl's postevent, + # so it's not perfect, but it works pretty well. + my $posterid = $comment->{u} ? $comment->{u}{userid} : 0; + my $jtalkid; + + # check for dup ID in memcache. + my $memkey; + if (@LJ::MEMCACHE_SERVERS) { + my $md5_b64 = Digest::MD5::md5_base64( + join(":", ($comment->{body}, $comment->{subject}, + $comment->{subjecticon}, $comment->{preformat}, + $comment->{picture_keyword}))); + $memkey = [$journalu->{userid}, "tdup:$journalu->{userid}:$item->{itemid}-$parent->{talkid}-$posterid-$md5_b64" ]; + $jtalkid = LJ::MemCache::get($memkey); + } + + # they don't have a duplicate... + unless ($jtalkid) { + # XXX do select and delete $talkprop{'picture_keyword'} if they're lying + my $pic = LJ::get_pic_from_keyword($comment->{u}, $comment->{picture_keyword}); + delete $comment->{picture_keyword} unless $pic && $pic->{'state'} eq 'N'; + $comment->{pic} = $pic; + + # put the post in the database + my $ditemid = $item->{itemid}*256 + $item->{anum}; + $jtalkid = enter_comment($journalu, $parent, $item, $comment, $errref); + return 0 unless $jtalkid; + + # save its identifying characteristics to protect against duplicates. + LJ::MemCache::set($memkey, $jtalkid+0, time()+60*10); + + # send some emails + mail_comments($entryu, $journalu, $parent, $comment, $item); + + # log the event + # this function doesn't do anything. + # LJ::event_register($dbcm, "R", $journalu->{'userid'}, $ditemid); + # FUTURE: log events type 'T' (thread) up to root + } + + # the caller wants to know the comment's talkid. + $comment->{talkid} = $jtalkid; + + # cluster tracking + LJ::mark_user_active($comment->{u}, 'comment'); + + return 1; +} + +# XXXevan: this function should have its functionality migrated to talkpost. +# because of that, it's probably not worth the effort to make it not mangle $form... +sub make_preview { + my ($talkurl, $cookie_auth, $form) = @_; + my $ret = ""; + + my $cleansubject = $form->{'subject'}; + LJ::CleanHTML::clean_subject(\$cleansubject); + + $ret .= ""; + $ret .= ""; + + my $event = $form->{'body'}; + my $spellcheck_html; + if ($LJ::SPELLER && $form->{'do_spellcheck'}) { + my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, + 'color' => '', }; + $spellcheck_html = $s->check_html(\$event); + } + LJ::CleanHTML::clean_comment(\$event, $form->{'prop_opt_preformatted'}); + + $ret .= "$BML::ML{'/talkpost_do.bml.preview.subject'} " . LJ::ehtml($cleansubject) . "
    \n"; + if ($spellcheck_html) { + $ret .= $spellcheck_html; + $ret .= "

    "; + } else { + $ret .= $event; + } + + $ret .= "


    "; + $ret .= "

    \n"; + $ret .= "
    "; + $ret .= "

    "; + + # change mode: + delete $form->{'submitpreview'}; $form->{'submitpost'} = 1; + if ($cookie_auth) { + $form->{'usertype'} = "cookieuser"; + delete $form->{'userpost'}; + } + delete $form->{'do_spellcheck'}; + foreach (keys %$form) { + $ret .= LJ::html_hidden($_, $form->{$_}) + unless $_ eq 'body' || $_ eq 'subject' || $_ eq 'prop_opt_preformatted'; + } + + $ret .= "
    \n"; + $ret .= "\n"; + if ($LJ::SPELLER) { + $ret .= " "; + } + $ret .= "

    "; + $ret .= "$BML::ML{'/talkpost.bml.opt.noautoformat'} ". + LJ::html_check({ 'name' => 'prop_opt_preformatted', + selected => $form->{'prop_opt_preformatted'} }); + $ret .= LJ::help_icon("noautoformat", " "); + $ret .= "

    "; + + $ret .= "

    "; + + $ret .= "
    "; + return $ret; +} + +# given a journalu and jitemid, return 1 if the entry +# is over the maximum comments allowed. +sub over_maxcomments { + my ($journalu, $jitemid) = @_; + $journalu = LJ::want_user($journalu); + $jitemid += 0; + return 0 unless $journalu && $jitemid; + + my $count = LJ::Talk::get_replycount($journalu, $jitemid); + return ($count >= LJ::get_cap($journalu, 'maxcomments')) ? 1 : 0; +} + +# more anti-spammer rate limiting. returns 1 if rate is okay, 0 if too fast. +sub check_rate { + my ($remote, $journalu) = @_; + + # we require memcache to do rate limiting efficiently + return 1 unless @LJ::MEMCACHE_SERVERS; + + # return right away if the account is suspended + return 0 if $remote && $remote->{'statusvis'} =~ /[SD]/; + + my $ip = LJ::get_remote_ip(); + my $now = time(); + my @watch; + + if ($remote) { + # registered human (or human-impersonating robot) + push @watch, + [ + "talklog:$remote->{userid}", + $LJ::RATE_COMMENT_AUTH || [ [ 200, 3600 ], [ 20, 60 ] ], + ]; + } else { + # anonymous, per IP address (robot or human) + push @watch, + [ + "talklog:$ip", + $LJ::RATE_COMMENT_ANON || + [ [ 300, 3600 ], [ 200, 1800 ], [ 150, 900 ], [ 15, 60 ] ] + ]; + + # anonymous, per journal. + # this particular limit is intended to combat flooders, instead + # of the other 'spammer-centric' limits. + push @watch, + [ + "talklog:anonin:$journalu->{userid}", + $LJ::RATE_COMMENT_ANON || + [ [ 300, 3600 ], [ 200, 1800 ], [ 150, 900 ], [ 15, 60 ] ] + ]; + } + + + WATCH: + foreach my $watch (@watch) { + my ($key, $rates) = ($watch->[0], $watch->[1]); + my $max_period = $rates->[0]->[1]; + + my $log = LJ::MemCache::get($key); + my $DATAVER = "1"; + + # parse the old log + my @times; + if (length($log) % 4 == 1 && substr($log,0,1) eq $DATAVER) { + my $ct = (length($log)-1) / 4; + for (my $i=0; $i<$ct; $i++) { + my $time = unpack("N", substr($log,$i*4+1,4)); + push @times, $time if $time > $now - $max_period; + } + } + + # add this event + push @times, $now; + + # check rates + foreach my $rate (@$rates) { + my ($allowed, $period) = ($rate->[0], $rate->[1]); + my $events = scalar grep { $_ > $now-$period } @times; + if ($events > $allowed) { + + my $ruser = (exists $remote->{'user'}) ? $remote->{'user'} : 'Not logged in'; + my $nowtime = localtime($now); + my $body = < $allowed allowed / $period secs + Remote user: $ruser + Remote IP: $ip + Time caught: $nowtime + Posting to: $journalu->{'user'} +EOM + if ($LJ::DEBUG_TALK_RATE && + LJ::MemCache::add("warn:$key", 1, 600)) { + LJ::send_mail({ + 'to' => $LJ::DEBUG_TALK_RATE, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => "talk spam: $key", + 'body' => $body, + }); + } + + return 0 if $LJ::ANTI_TALKSPAM; + last WATCH; + } + } + + # build the new log + my $newlog = $DATAVER; + foreach (@times) { + $newlog .= pack("N", $_); + } + + LJ::MemCache::set($key, $newlog, $max_period); + } + + return 1; +} + +1; diff --git a/livejournal/cgi-bin/userpicmagic.txt b/livejournal/cgi-bin/userpicmagic.txt new file mode 100755 index 0000000..ebb2a14 --- /dev/null +++ b/livejournal/cgi-bin/userpicmagic.txt @@ -0,0 +1,3 @@ +0 beshort 0xffd8 image/jpeg +0 string GIF image/gif +0 string \211PNG image/png diff --git a/livejournal/cgi-bin/weblib.pl b/livejournal/cgi-bin/weblib.pl new file mode 100755 index 0000000..30cf44f --- /dev/null +++ b/livejournal/cgi-bin/weblib.pl @@ -0,0 +1,1762 @@ +#!/usr/bin/perl +# + +package LJ; +use strict; + +# load the bread crumb hash +require "$ENV{'LJHOME'}/cgi-bin/crumbs.pl"; + +# +# name: LJ::img +# des: Returns an HTML <img> or <input> tag to an named image +# code, which each site may define with a different image file with +# its own dimensions. This prevents hard-coding filenames & sizes +# into the source. The real image data is stored in LJ::Img, which +# has default values provided in cgi-bin/imageconf.pl but can be +# overridden in cgi-bin/ljconfig.pl. +# args: imagecode, type?, attrs? +# des-imagecode: The unique string key to reference the image. Not a filename, +# but the purpose or location of the image. +# des-type: By default, the tag returned is an <img> tag, but if 'type' +# is "input", then an input tag is returned. +# des-attrs: Optional hashref of other attributes. If this isn't a hashref, +# then it's assumed to be a scalar for the 'name' attribute for +# input controls. +# +sub img +{ + my $ic = shift; + my $type = shift; # either "" or "input" + my $attr = shift; + + my $attrs; + if ($attr) { + if (ref $attr eq "HASH") { + foreach (keys %$attr) { + $attrs .= " $_=\"" . LJ::ehtml($attr->{$_}) . "\""; + } + } else { + $attrs = " name=\"$attr\""; + } + } + + my $i = $LJ::Img::img{$ic}; + if ($type eq "") { + return "{'src'}\" width=\"$i->{'width'}\" ". + "height=\"$i->{'height'}\" alt=\"$i->{'alt'}\" title=\"$i->{'alt'}\" ". + "border='0'$attrs />"; + } + if ($type eq "input") { + return "{'src'}\" ". + "width=\"$i->{'width'}\" height=\"$i->{'height'}\" title=\"$i->{'alt'}\" ". + "alt=\"$i->{'alt'}\" border='0'$attrs />"; + } + return "XXX"; +} + +# +# name: LJ::date_to_view_links +# class: component +# des: Returns HTML of date with links to user's journal. +# args: u, date +# des-date: date in yyyy-mm-dd form. +# returns: HTML with yyy, mm, and dd all links to respective views. +# +sub date_to_view_links +{ + my ($u, $date) = @_; + return unless $date =~ /^(\d\d\d\d)-(\d\d)-(\d\d)/; + + my ($y, $m, $d) = ($1, $2, $3); + my ($nm, $nd) = ($m+0, $d+0); # numeric, without leading zeros + my $user = $u->{'user'}; + my $base = LJ::journal_base($u); + + my $ret; + $ret .= "$y-"; + $ret .= "$m-"; + $ret .= "$d"; + return $ret; +} + + +# +# name: LJ::auto_linkify +# des: Takes a plain-text string and changes URLs into tags (auto-linkification) +# args: str +# arg-str: The string to perform auto-linkification on. +# returns: The auto-linkified text. +# +sub auto_linkify +{ + my $str = shift; + my $match = sub { + my $str = shift; + if ($str =~ /^(.*?)(&(#39|quot|lt|gt)(;.*)?)$/) { + return "$1$2"; + } else { + return "$str"; + } + }; + $str =~ s!https?://[^\s\'\"\<\>]+[a-zA-Z0-9_/&=\-]! $match->($&); !ge; + return $str; +} + + +# +# name: LJ::make_authas_select +# des: Given a u object and some options, determines which users the given user +# can switch to. If the list exists, returns a select list and a submit +# button with labels. Otherwise returns a hidden element. +# returns: string of html elements +# args: u, opts? +# des-opts: Optional. Valid keys are: +# 'authas' - current user, gets selected in drop-down +# 'label' - label to go before form elements +# 'button' - button label for submit button +# others - arguments to pass to LJ::get_authas_list +# +sub make_authas_select { + my ($u, $opts) = @_; # type, authas, label, button + + my @list = LJ::get_authas_list($u, $opts); + + # only do most of form if there are options to select from + if (@list > 1) { + return ($opts->{'label'} || 'Work as user:') . " " . + LJ::html_select({ 'name' => 'authas', + 'selected' => $opts->{'authas'} || $u->{'user'}}, + map { $_, $_ } @list) . " " . + LJ::html_submit(undef, $opts->{'button'} || 'Switch'); + } + + # no communities to choose from, give the caller a hidden + return LJ::html_hidden('authas', $opts->{'authas'} || $u->{'user'}); +} + +# +# name: LJ::help_icon +# des: Returns BML to show a help link/icon given a help topic, or nothing +# if the site hasn't defined a URL for that topic. Optional arguments +# include HTML/BML to place before and after the link/icon, should it +# be returned. +# args: topic, pre?, post? +# des-topic: Help topic key. See doc/ljconfig.pl.txt for examples. +# des-pre: HTML/BML to place before the help icon. +# des-post: HTML/BML to place after the help icon. +# +sub help_icon +{ + my $topic = shift; + my $pre = shift; + my $post = shift; + return "" unless (defined $LJ::HELPURL{$topic}); + return "$pre$post"; +} + + +# +# name: LJ::bad_input +# des: Returns common BML for reporting form validation errors in +# a bulletted list. +# returns: BML showing errors. +# args: error* +# des-error: A list of errors +# +sub bad_input +{ + my @errors = @_; + my $ret = ""; + $ret .= "\n
      \n"; + foreach (@errors) { + $ret .= "
    • $_
    • \n"; + } + $ret .= "
    \n"; + return $ret; +} + + +# +# name: LJ::error_list +# des: Returns an error bar with bulleted list of errors +# returns: BML showing errors +# args: error* +# des-error: A list of errors +# +sub error_list +{ + my @errors = @_; + my $ret; + $ret .= ""; + $ret .= BML::ml('error.procrequest'); + $ret .= "
      "; + + foreach (@errors) { + $ret .= "
    • $_
    • "; + } + $ret .= "
    errorbar?>"; + return $ret; +} + +# +# name: LJ::warning_list +# des: Returns a warning bar with bulleted list of warnings +# returns: BML showing warnings +# args: warnings* +# des-warnings: A list of warnings +# +sub warning_list +{ + my @warnings = @_; + my $ret; + + $ret .= ""; + $ret .= BML::ml('label.warning'); + $ret .= "
      "; + + foreach (@warnings) { + $ret .= "
    • $_
    • "; + } + $ret .= "
    warningbar?>"; + return $ret; +} + +sub tosagree_widget { + my ($checked, $errstr) = @_; + + return + "
    " . + BML::ml('tos.mustread', + { aopts => "target='_new' href='$LJ::SITEROOT/legal/tos.bml'" }) . + "
    " . + "" . + "
    " . LJ::html_check({ name => 'agree_tos', id => 'agree_tos', + value => '1', selected => $checked }) . + "
    " . + ($errstr ? "" : ''); +} + +sub tosagree_html { + my $domain = shift; + + my $ret = ""; + + my $html_str = LJ::tosagree_str($domain => 'html'); + $ret .= "" if $html_str; + + $ret .= "
    "; + $ret .= LJ::tosagree_widget(@_); + $ret .= "
    "; + + return $ret; +} + +sub tosagree_str { + my ($domain, $key) = @_; + + return ref $LJ::REQUIRED_TOS{$domain} && $LJ::REQUIRED_TOS{$domain}->{$key} ? + $LJ::REQUIRED_TOS{$domain}->{$key} : $LJ::REQUIRED_TOS{$key}; +} + +# +# name: LJ::did_post +# des: When web pages using cookie authentication, you can't just trust that +# the remote user wants to do the action they're requesting. It's way too +# easy for people to force other people into making GET requests to +# a server. What if a user requested http://server/delete_all_journal.bml +# and that URL checked the remote user and immediately deleted the whole +# journal. Now anybody has to do is embed that address in an image +# tag and a lot of people's journals will be deleted without them knowing. +# Cookies should only show pages which make no action. When an action is +# being made, check that it's a POST request. +# returns: true if REQUEST_METHOD == "POST" +# +sub did_post +{ + return (BML::get_method() eq "POST"); +} + +# +# name: LJ::robot_meta_tags +# des: Returns meta tags to block a robot from indexing or following links +# returns: A string with appropriate meta tags +# +sub robot_meta_tags +{ + return "\n" . + "\n"; +} + +sub paging_bar +{ + my ($page, $pages, $opts) = @_; + + my $self_link = $opts->{'self_link'} || + sub { BML::self_link({ 'page' => $_[0] }) }; + + my $navcrap; + if ($pages > 1) { + $navcrap .= "
    "; + $navcrap .= BML::ml('ljlib.pageofpages',{'page'=>$page, 'total'=>$pages}) . "
    "; + my $left = "<<"; + if ($page > 1) { $left = "$left"; } + my $right = ">>"; + if ($page < $pages) { $right = "$right"; } + $navcrap .= $left . " "; + for (my $i=1; $i<=$pages; $i++) { + my $link = "[$i]"; + if ($i != $page) { $link = "$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + } + $navcrap .= "$right"; + $navcrap .= "
    \n"; + $navcrap = BML::fill_template("standout", { 'DATA' => $navcrap }); + } + return $navcrap; +} + +# +# class: web +# name: LJ::make_cookie +# des: Prepares cookie header lines. +# returns: An array of cookie lines. +# args: name, value, expires, path?, domain? +# des-name: The name of the cookie. +# des-value: The value to set the cookie to. +# des-expires: The time (in seconds) when the cookie is supposed to expire. +# Set this to 0 to expire when the browser closes. Set it to +# undef to delete the cookie. +# des-path: The directory path to bind the cookie to. +# des-domain: The domain (or domains) to bind the cookie to. +# +sub make_cookie +{ + my ($name, $value, $expires, $path, $domain) = @_; + my $cookie = ""; + my @cookies = (); + + # let the domain argument be an array ref, so callers can set + # cookies in both .foo.com and foo.com, for some broken old browsers. + if ($domain && ref $domain eq "ARRAY") { + foreach (@$domain) { + push(@cookies, LJ::make_cookie($name, $value, $expires, $path, $_)); + } + return; + } + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($expires); + $year+=1900; + + my @day = qw{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}; + my @month = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}; + + $cookie = sprintf "%s=%s", LJ::eurl($name), LJ::eurl($value); + + # this logic is confusing potentially + unless (defined $expires && $expires==0) { + $cookie .= sprintf "; expires=$day[$wday], %02d-$month[$mon]-%04d %02d:%02d:%02d GMT", + $mday, $year, $hour, $min, $sec; + } + + $cookie .= "; path=$path" if $path; + $cookie .= "; domain=$domain" if $domain; + push(@cookies, $cookie); + return @cookies; +} + +# +# name: LJ::set_interests +# des: Change a user's interests +# args: dbarg?, u, old, new +# arg-old: hashref of old interests (hashing being interest => intid) +# arg-new: listref of new interests +# returns: 1 on success, undef on failure +# +sub set_interests +{ + my ($u, $old, $new) = @_; + + $u = LJ::want_user($u); + my $userid = $u->{'userid'}; + return undef unless $userid; + + return undef unless ref $old eq 'HASH'; + return undef unless ref $new eq 'ARRAY'; + + my $dbh = LJ::get_db_writer(); + my %int_new = (); + my %int_del = %$old; # assume deleting everything, unless in @$new + + # user interests go in a different table than user interests, + # though the schemas are the same so we can run the same queries on them + my $uitable = $u->{'journaltype'} eq 'C' ? 'comminterests' : 'userinterests'; + + # track if we made changes to refresh memcache later. + my $did_mod = 0; + + foreach my $int (@$new) + { + $int = lc($int); # FIXME: use utf8? + $int =~ s/^i like //; # *sigh* + next unless $int; + next if $int =~ / .+ .+ .+ /; # prevent sentences + next if $int =~ /[\<\>]/; + my ($bl, $cl) = LJ::text_length($int); + next if $bl > LJ::BMAX_INTEREST or $cl > LJ::CMAX_INTEREST; + $int_new{$int} = 1 unless $old->{$int}; + delete $int_del{$int}; + } + + ### were interests removed? + if (%int_del) + { + ## easy, we know their IDs, so delete them en masse + my $intid_in = join(", ", values %int_del); + $dbh->do("DELETE FROM $uitable WHERE userid=$userid AND intid IN ($intid_in)"); + $dbh->do("UPDATE interests SET intcount=intcount-1 WHERE intid IN ($intid_in)"); + $did_mod = 1; + } + + ### do we have new interests to add? + if (%int_new) + { + $did_mod = 1; + + ## difficult, have to find intids of interests, and create new ints for interests + ## that nobody has ever entered before + my $int_in = join(", ", map { $dbh->quote($_); } keys %int_new); + my %int_exist; + my @new_intids = (); ## existing IDs we'll add for this user + + ## find existing IDs + my $sth = $dbh->prepare("SELECT interest, intid FROM interests WHERE interest IN ($int_in)"); + $sth->execute; + while (my ($intr, $intid) = $sth->fetchrow_array) { + push @new_intids, $intid; # - we'll add this later. + delete $int_new{$intr}; # - so we don't have to make a new intid for + # this next pass. + } + + if (@new_intids) { + my $sql = ""; + foreach my $newid (@new_intids) { + if ($sql) { $sql .= ", "; } + else { $sql = "REPLACE INTO $uitable (userid, intid) VALUES "; } + $sql .= "($userid, $newid)"; + } + $dbh->do($sql); + + my $intid_in = join(", ", @new_intids); + $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid IN ($intid_in)"); + } + } + + ### do we STILL have interests to add? (must make new intids) + if (%int_new) + { + foreach my $int (keys %int_new) + { + my $intid; + my $qint = $dbh->quote($int); + + $dbh->do("INSERT INTO interests (intid, intcount, interest) ". + "VALUES (NULL, 1, $qint)"); + if ($dbh->err) { + # somebody beat us to creating it. find its id. + $intid = $dbh->selectrow_array("SELECT intid FROM interests WHERE interest=$qint"); + $dbh->do("UPDATE interests SET intcount=intcount+1 WHERE intid=$intid"); + } else { + # newly created + $intid = $dbh->{'mysql_insertid'}; + } + if ($intid) { + ## now we can actually insert it into the userinterests table: + $dbh->do("INSERT INTO $uitable (userid, intid) ". + "VALUES ($userid, $intid)"); + } + } + } + + ### if journaltype is community, clean their old userinterests from 'userinterests' + if ($u->{'journaltype'} eq 'C') { + $dbh->do("DELETE FROM userinterests WHERE userid=?", undef, $u->{'userid'}); + } + + LJ::memcache_kill($u, "intids") if $did_mod; + return 1; +} + +# $opts is optional, with keys: +# forceids => 1 : don't use memcache for loading the intids +# forceints => 1 : don't use memcache for loading the interest rows +# justids => 1 : return arrayref of intids only, not names/counts +# returns otherwise an arrayref of interest rows, sorted by interest name +sub get_interests +{ + my ($u, $opts) = @_; + $opts ||= {}; + return undef unless $u; + my $uid = $u->{userid}; + my $uitable = $u->{'journaltype'} eq 'C' ? 'comminterests' : 'userinterests'; + + # load the ids + my $ids; + my $mk_ids = [$uid, "intids:$uid"]; + $ids = LJ::MemCache::get($mk_ids) unless $opts->{'forceids'}; + unless ($ids && ref $ids eq "ARRAY") { + $ids = []; + my $dbh = LJ::get_db_writer(); + my $sth = $dbh->prepare("SELECT intid FROM $uitable WHERE userid=?"); + $sth->execute($uid); + push @$ids, $_ while ($_) = $sth->fetchrow_array; + LJ::MemCache::add($mk_ids, $ids, 3600*12); + } + return $ids if $opts->{'justids'}; + + # load interest rows + my %need; + $need{$_} = 1 foreach @$ids; + my @ret; + + unless ($opts->{'forceints'}) { + if (my $mc = LJ::MemCache::get_multi(map { [$_, "introw:$_"] } @$ids)) { + while (my ($k, $v) = each %$mc) { + next unless $k =~ /^introw:(\d+)/; + delete $need{$1}; + push @ret, $v; + } + } + } + + if (%need) { + my $ids = join(",", map { $_+0 } keys %need); + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT intid, interest, intcount FROM interests ". + "WHERE intid IN ($ids)"); + $sth->execute; + my $memc_store = 0; + while (my ($intid, $int, $count) = $sth->fetchrow_array) { + # minimize latency... only store 25 into memcache at a time + # (too bad we don't have set_multi.... hmmmm) + my $aref = [$intid, $int, $count]; + if ($memc_store++ < 25) { + # if the count is fairly high, keep item in memcache longer, + # since count's not so important. + my $expire = $count < 10 ? 3600*12 : 3600*48; + LJ::MemCache::add([$intid, "introw:$intid"], $aref, $expire); + } + push @ret, $aref; + } + } + + @ret = sort { $a->[1] cmp $b->[1] } @ret; + return \@ret; +} + +sub set_active_crumb +{ + $LJ::ACTIVE_CRUMB = shift; + return undef; +} + +sub set_dynamic_crumb +{ + my ($title, $parent) = @_; + $LJ::ACTIVE_CRUMB = [ $title, $parent ]; +} + +sub get_parent_crumb +{ + my $thiscrumb = LJ::get_crumb(LJ::get_active_crumb()); + return LJ::get_crumb($thiscrumb->[2]); +} + +sub get_active_crumb +{ + return $LJ::ACTIVE_CRUMB; +} + +sub get_crumb_path +{ + my $cur = LJ::get_active_crumb(); + my @list; + while ($cur) { + # get crumb, fix it up, and then put it on the list + if (ref $cur) { + # dynamic crumb + push @list, [ $cur->[0], '', $cur->[1], 'dynamic' ]; + $cur = $cur->[1]; + } else { + # just a regular crumb + my $crumb = LJ::get_crumb($cur); + last unless $crumb; + last if $cur eq $crumb->[2]; + $crumb->[3] = $cur; + push @list, $crumb; + + # now get the next one we're going after + $cur = $crumb->[2]; # parent of this crumb + } + } + return @list; +} + +sub get_crumb +{ + my $crumbkey = shift; + if (defined $LJ::CRUMBS_LOCAL{$crumbkey}) { + return $LJ::CRUMBS_LOCAL{$crumbkey}; + } else { + return $LJ::CRUMBS{$crumbkey}; + } +} + +# +# name: LJ::check_referer +# class: web +# des: Checks if the user is coming from a given URI. +# args: uri?, referer? +# des-uri: string; the URI we want the user to come from +# des-referer: string; the location the user is posting from. if not supplied, +# will be retrieved with BML::get_client_header. in general, you don't want to +# pass this yourself unless you already have it or know we can't get it from BML. +# returns: 1 if they're coming from that URI, else undef +# +sub check_referer { + my $uri = shift(@_) || ''; + my $referer = shift(@_) || BML::get_client_header('Referer'); + + # get referer and check + return 1 unless $referer; + return 1 if $LJ::SITEROOT && $referer =~ m!^$LJ::SITEROOT$uri!; + return 1 if $LJ::DOMAIN && $referer =~ m!^http://$LJ::DOMAIN$uri!; + return 1 if $LJ::DOMAIN_WEB && $referer =~ m!^http://$LJ::DOMAIN_WEB$uri!; + return 1 if $uri =~ m!^http://! && $referer eq $uri; + return undef; +} + +# +# name: LJ::form_auth +# class: web +# des: Creates an authentication token to be used later to verify that a form +# submission came from a particular user. +# returns: HTML hidden field to be inserted into the output of a page. +# +sub form_auth { + my $remote = LJ::get_remote() or return ""; + my $sess = $remote->{'_session'} or return ""; + my $auth = join('-', + LJ::rand_chars(10), + $remote->{userid}, + $sess->{auth}); + return LJ::html_hidden("lj_form_auth", LJ::challenge_generate(86400, $auth)); +} + +# +# name: LJ::check_form_auth +# class: web +# des: Verifies form authentication created with LJ::form_auth. +# returns: Boolean; true if the current data in %POST is a valid form submitted +# by the user in $remote using the current session, false if the user has changed, +# the challenge has expired, or the user has changed session (logged out and in +# again, or something). +# +sub check_form_auth { + my $remote = LJ::get_remote() or return 0; + my $sess = $remote->{'_session'} or return 0; + my $formauth = $BMLCodeBlock::POST{'lj_form_auth'} or return 0; + + # check the attributes are as they should be + my $attr = LJ::get_challenge_attributes($formauth); + my ($randchars, $userid, $sessauth) = split(/\-/, $attr); + return 0 unless $userid == $remote->{userid} && + $sessauth eq $sess->{auth}; + + # check the signature is good and not expired + my $opts = { dont_check_count => 1 }; # in/out + LJ::challenge_check($formauth, $opts); + return $opts->{valid} && ! $opts->{expired}; +} + +# +# name: LJ::create_qr_div +# class: web +# des: Creates the hidden div that stores the Quick Reply form +# returns: undef upon failure or HTML for the div upon success +# args: user, remote, ditemid, stylemine, userpic +# des-u: user object or userid for journal reply in +# des-ditemid: ditemid for this comment +# des-stylemine: if the user has specified style=mine for this page +# des-userpic: alternate default userpic +# +sub create_qr_div { + + my ($user, $ditemid, $stylemine, $userpic, $viewing_thread) = @_; + my $u = LJ::want_user($user); + my $remote = LJ::get_remote(); + return undef unless $u && $remote && $ditemid; + return undef if $remote->underage; + + $stylemine ||= 0; + my $qrhtml; + + LJ::load_user_props($remote, "opt_no_quickreply"); + return undef if $remote->{'opt_no_quickreply'}; + + my $stylemineuri = $stylemine ? "style=mine&" : ""; + my $basepath = LJ::journal_base($u) . "/$ditemid.html?${stylemineuri}replyto="; + $qrhtml .= LJ::html_hidden({'name' => 'replyto', 'id' => 'replyto', 'value' => ''}, + {'name' => 'parenttalkid', 'id' => 'parenttalkid', 'value' => ''}, + {'name' => 'itemid', 'id' => 'itemid', 'value' => $ditemid}, + {'name' => 'usertype', 'id' => 'usertype', 'value' => 'cookieuser'}, + {'name' => 'userpost', 'id' => 'userpost', 'value' => $remote->{'user'}}, + {'name' => 'qr', 'id' => 'qr', 'value' => '1'}, + {'name' => 'cookieuser', 'id' => 'cookieuser', 'value' => $remote->{'user'}}, + {'name' => 'dtid', 'id' => 'dtid', 'value' => ''}, + {'name' => 'basepath', 'id' => 'basepath', 'value' => $basepath}, + {'name' => 'stylemine', 'id' => 'stylemine', 'value' => $stylemine}, + {'name' => 'saved_subject', 'id' => 'saved_subject'}, + {'name' => 'saved_body', 'id' => 'saved_body'}, + {'name' => 'saved_spell', 'id' => 'saved_spell'}, + {'name' => 'saved_upic', 'id' => 'saved_upic'}, + {'name' => 'saved_dtid', 'id' => 'saved_dtid'}, + {'name' => 'saved_ptid', 'id' => 'saved_ptid'}, + {'name' => 'viewing_thread', 'id' => 'viewing_thread', 'value' => $viewing_thread}, + ); + + # rate limiting challenge + { + my ($time, $secret) = LJ::get_secret(); + my $rchars = LJ::rand_chars(20); + my $chal = $ditemid . "-$u->{userid}-$time-$rchars"; + my $res = Digest::MD5::md5_hex($secret . $chal); + $qrhtml .= LJ::html_hidden("chrp1", "$chal-$res"); + } + + # Start making the div itself + $qrhtml .= ""; + + my $ret; + $ret = ""; + return $ret; +} + +# +# name: LJ::make_qr_link +# class: web +# des: Creates the link to toggle the QR reply form or if +# JavaScript is not enabled, then forwards the user through +# to replyurl. +# returns: undef upon failure or HTML for the link +# args: dtid, basesubject, linktext, replyurl +# des-dtid: dtalkid for this comment +# des-basesubject: parent comment's subject +# des-linktext: text for the user to click +# des-replyurl: URL to forward user to if their browser +# does not support QR +# +sub make_qr_link +{ + my ($dtid, $basesubject, $linktext, $replyurl) = @_; + + return undef unless defined $dtid && $linktext && $replyurl; + + my $remote = LJ::get_remote(); + LJ::load_user_props($remote, "opt_no_quickreply"); + unless ($remote->{'opt_no_quickreply'}) { + my $pid = int($dtid / 256); + + $basesubject =~ s/^(Re:\s*)*//i; + $basesubject = "Re: $basesubject" if $basesubject; + $basesubject = LJ::ejs($basesubject); + my $onclick = "return quickreply('$dtid', $pid, '$basesubject')"; + $onclick = LJ::ehtml($onclick); + return "$linktext"; + } else { # QR Disabled + return "$linktext"; + } +} + +# +# name: LJ::get_lastcomment +# class: web +# des: Looks up the last talkid and journal the remote user posted in +# returns: talkid, jid +# args: +# +sub get_lastcomment { + my $remote = LJ::get_remote; + return (undef, undef) unless $remote; + + # Figure out their last post + my $memkey = [$remote->{'userid'}, "lastcomm:$remote->{'userid'}"]; + my $memval = LJ::MemCache::get($memkey); + my ($jid, $talkid) = split(/:/, $memval) if $memval; + + return ($talkid, $jid); +} + +# +# name: LJ::make_qr_target +# class: web +# des: Returns a div usable for Quick Reply boxes +# returns: HMTML for the div +# args: +# +sub make_qr_target { + my $name = shift; + + return "
    "; +} + +# +# name: LJ::set_lastcomment +# class: web +# des: Sets the lastcomm Memcache key for this user's last comment +# returns: undef on failure +# args: u, remote, dtalkid, life? +# des-u: Journal they just posted in, either u or userid +# des-remote: Remote user +# des-dtalkid: Talkid for the comment they just posted +# des-life: How long, in seconds, the Memcache key should live +# +sub set_lastcomment +{ + my ($u, $remote, $dtalkid, $life) = @_; + + my $userid = LJ::want_userid($u); + return undef unless $userid && $remote && $dtalkid; + + # By default, this key lasts for 10 seconds. + $life ||= 10; + + # Set memcache key for highlighting the comment + my $memkey = [$remote->{'userid'}, "lastcomm:$remote->{'userid'}"]; + LJ::MemCache::set($memkey, "$userid:$dtalkid", time()+$life); + + return; +} + +# +# name: LJ::entry_form +# class: web +# des: Returns a properly formatted form for creating/editing entries +# args: opts, head +# des-head: string reference for the section (javascript previews, etc) +# des-onload: string reference for javascript functions to be called on page load +# des-opts: hashref of keys/values: +# mode: either "update" or "edit", depending on context +# datetime: date and time, formatted yyyy-mm-dd hh:mm +# remote: remote u object +# subject: entry subject +# event: entry text +# richtext: allow rich text formatting +# richtext_on: rich text formatting has been turned on +# auth_as_remote: bool option to authenticate as remote user, prefilling pic/friend groups/etc +# return: form to include in BML pages +# +sub entry_form { + my ($opts, $head, $onload, $errors) = @_; + + my $out = ""; + my $remote = $opts->{'remote'}; + my ($moodlist, $moodpics, $userpics); + + # usejournal has no point if you're trying to use the account you're logged in as, + # so disregard it so we can assume that if it exists, we're trying to post to an + # account that isn't us + if ($remote && $opts->{usejournal} && $remote->{user} eq $opts->{usejournal}) { + delete $opts->{usejournal}; + } + + my $tabnum = 1; + my $tabindex = sub { return $tabnum++; }; + $opts->{'event'} = LJ::durl($opts->{'event'}) if $opts->{'mode'} eq "edit"; + + # 15 minute auth token, should be adequate + my $chal = LJ::challenge_generate(900); + $out .= ""; + $out .= ""; + + $out .= "
    "; + $out .= "\n"; + ### Meta Information Column 1 + { + $out .= ""; + } + ### Meta Information Column 2 + { + $out .= ""; + } + + $out .= "
    "; + + # Authentication box + $out .= $opts->{'auth'}; + $out .= "\n" if $errors->{'auth'}; + # Date / Time + { + my ($year, $mon, $mday, $hour, $min) = split( /\D/, $opts->{'datetime'}); + # date entry boxes / formatting note + my $datetime = LJ::html_datetime({ 'name' => "date_ymd", 'notime' => 1, 'default' => "$year-$mon-$mday", 'disabled' => $opts->{'disabled_save'}}) . " " x 5; + $datetime .= LJ::html_text({ size => 2, maxlength => 2, value => $hour, name => "hour", tabindex => $tabindex->(), disabled => $opts->{'disabled_save'} }) . ":"; + $datetime .= LJ::html_text({ size => 2, maxlength => 2, value => $min, name => "min", tabindex => $tabindex->(), disabled => $opts->{'disabled_save'} }); + + $out .= ""; + $out .= "\n"; + } + + ### Subject + $out .= ""; + $out .= "
    {'auth'} inerr?>
    " . BML::ml('entryform.date') . "$datetime "; + $out .= "
    " . BML::ml('entryform.subject') . ""; + $out .= LJ::html_text({ 'name' => 'subject', 'value' => $opts->{'subject'}, + 'size' => '60', 'maxlength' => '100', 'tabindex' => $tabindex->(), 'disabled' => $opts->{'disabled_save'} }) . "\n"; + $out .= "
    "; + $out .= LJ::run_hook('entryforminfo'); + $out .= "
    \n"; + + ### Display Spell Check Results: + $out .= "

    " . BML::ml('entryform.spellchecked') . "
    $opts->{'spellcheck_html'}

    " + if $opts->{'spellcheck_html'}; + $out .= "


    $errors->{'entry'}

    " + if $errors->{'entry'}; + + ### Event Text Area: + $out .= "

    " . BML::ml('entryform.entry') . "

    " unless $opts->{'richtext_on'}; + if ($opts->{'richtext_on'}) { + my $jevent = $opts->{'event'}; + + # manually typed tags + $jevent =~ s//<lj user="$1" \/>/ig; + $jevent =~ s/<(\/)?lj-cut(.*?)(?: \/)?>/<$1lj-cut$2>/ig; + + $jevent = LJ::ejs($jevent); + my $rte_nosupport = LJ::ejs(BML::fill_template("de", { DATA => BML::ml('entryform.htmlokay.rte_nosupport') })); + + $out .= LJ::html_hidden('richtext', '1') . "\n"; + $out .= LJ::html_hidden('saved_entry', '') . "\n"; + + $out .= <
    "; + return $out; +} + +# +# name: LJ::entry_form_decode +# class: web +# des: Decodes an entry_form into a protocol compatible hash +# info: Generate form with [func[entry_form]]. +# args: req, post +# des-req: protocol request hash to build +# des-post: entry_form POST contents +# returns: req +# +sub entry_form_decode +{ + my ($req, $POST) = @_; + + # find security + my $sec = "public"; + my $amask = 0; + if ($POST->{'security'} eq "private") { + $sec = "private"; + } elsif ($POST->{'security'} eq "friends") { + $sec = "usemask"; $amask = 1; + } elsif ($POST->{'security'} eq "custom") { + $sec = "usemask"; + foreach my $bit (1..30) { + next unless $POST->{"custom_bit_$bit"}; + $amask |= (1 << $bit); + } + } + $req->{'security'} = $sec; + $req->{'allowmask'} = $amask; + + # date/time + my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, $POST); + my ($year, $mon, $day) = split( /\D/, $date); + $req->{'year'} = $year; $req->{'mon'} = $mon; $req->{'day'} = $day; + + foreach ( "year", "mon", "day" ) { + $req->{$_} = $POST->{$_} if $POST->{$_} ne ""; + } + + # copy some things from %POST + foreach (qw(subject hour min + prop_picture_keyword prop_current_moodid + prop_current_mood prop_current_music + prop_opt_screening prop_opt_noemail + prop_opt_preformatted prop_opt_nocomments + prop_taglist)) { + $req->{$_} = $POST->{$_}; + } + + $req->{"prop_opt_preformatted"} ||= $POST->{'event_format'} eq "preformatted" ? 1 : 0; + $req->{"prop_opt_nocomments"} ||= $POST->{'comment_settings'} eq "nocomments" ? 1 : 0; + $req->{"prop_opt_noemail"} ||= $POST->{'comment_settings'} eq "noemail" ? 1 : 0; + $req->{'prop_opt_backdated'} = $POST->{'prop_opt_backdated'} ? 1 : 0; + + # Convert the rich text editor output back to parsable lj tags. + my $event = $POST->{'event'}; + if ($POST->{'richtext'}) { + # check for blank entry + (my $event_tmp = $event) =~ s!(?:
    |

    (?: |\s)+

    | )\s*?!!gm; + if ($event_tmp =~ /\w/) { # ok, we still have content + $event =~ s/<(\/)?lj-cut(.*?)(?: \/)?>/<$1lj-cut$2>/ig; + $event =~ s/<lj user=['"]?(\w{1,15})['"]?\s?\/?>//ig; # manually typed tags + $event =~ s/<\/a>(?:<\/span>)?//ig; + } else { # RTE blanks (just
    , newlines,   - no real content) + $event = undef; # force protocol error + } + } + $req->{'event'} = $event; + + ## see if an "other" mood they typed in has an equivalent moodid + if ($POST->{'prop_current_mood'}) { + if (my $id = LJ::mood_id($POST->{'prop_current_mood'})) { + $req->{'prop_current_moodid'} = $id; + delete $req->{'prop_current_mood'}; + } + } + return $req; +} + +# returns exactly what was passed to it normally. but in developer mode, +# it includes a link to a page that automatically grants the needed priv. +sub no_access_error { + my ($text, $priv, $privarg) = @_; + if ($LJ::IS_DEV_SERVER) { + my $remote = LJ::get_remote(); + return "$text (DEVMODE: Grant $priv\[$privarg\])"; + } else { + return $text; + } +} + +# Data::Dumper for JavaScript +sub js_dumper { + my $obj = shift; + if (ref $obj eq "HASH") { + my $ret = "{"; + foreach my $k (keys %$obj) { + $ret .= "$k: " . js_dumper($obj->{$k}) . ","; + } + chop $ret; + $ret .= "}"; + return $ret; + } elsif (ref $obj eq "ARRAY") { + my $ret = "[" . join(", ", map { js_dumper($_) } @$obj) . "]"; + return $ret; + } else { + return $obj if $obj =~ /^\d+$/; + return "\"" . LJ::ejs($obj) . "\""; + } +} + +# Common challenge/response javascript, needed by both login pages and comment pages alike. +# Forms that use this should onclick='return sendForm()' in the submit button. +# Returns true to let the submit continue. +$LJ::COMMON_CODE{'chalresp_js'} = qq{ + + +}; + +# Common Javascript function for auto-checking radio buttons on form +# input field data changes +$LJ::COMMON_CODE{'autoradio_check'} = q{ + +}; + +# Common Javascript functions for Quick Reply +$LJ::COMMON_CODE{'quickreply'} = q{ + + +}; + +1; diff --git a/livejournal/cvs/multicvs.conf b/livejournal/cvs/multicvs.conf new file mode 100755 index 0000000..f16a50e --- /dev/null +++ b/livejournal/cvs/multicvs.conf @@ -0,0 +1,55 @@ +# +# This file determine how files from multiple CVS repositories (or just snapshots +# of them) map onto the live file space +# +# You should've already read the installation documentation[1], but for reference, the +# repositories you'll need are: +# +# livejournal: +# CVSROOT=':pserver:anonymous@cvs.livejournal.org:/home/cvslj' +# bml, wcmtools: +# CVSROOT=':pserver:anonymous@danga.com:/home/cvspub' +# +# [1] http://www.livejournal.com/doc/server/ + +LIVEDIR=$LJHOME +CVSDIR=$LJHOME/cvs + +livejournal . +bml/lib/Apache/BML.pm cgi-bin/Apache/BML.pm +bml/doc/docbook doc/raw/bml.book +wcmtools/spud/bin/cmdshell bin/cmdshell +wcmtools/spud/bin/gatherer bin/spud/gatherer +wcmtools/spud/bin/replicator bin/spud/replicator +wcmtools/spud/bin/server bin/spud/server +wcmtools/spud/bin/wrapper bin/spud/wrapper +wcmtools/spud/bin/plugins bin/spud/plugins +wcmtools/bin/multicvs.pl bin/multicvs.pl +wcmtools/bin/apidoc.pl bin/apidoc.pl +wcmtools/lib/DBI cgi-bin/DBI +wcmtools/lib/DBIx cgi-bin/DBIx +wcmtools/lib/Apache/CompressClientFixup.pm cgi-bin/Apache/CompressClientFixup.pm +wcmtools/lib/HTMLCleaner.pm cgi-bin/HTMLCleaner.pm +wcmtools/lib/S2/Color.pm cgi-bin/S2/Color.pm +wcmtools/lib/MultiCVS.pm cgi-bin/MultiCVS.pm +wcmtools/s2 src/s2 +wcmtools/perlbal src/perlbal +wcmtools/memcached src/memcached +wcmtools/memcached/api/perl/Memcached.pm cgi-bin/Cache/Memcached.pm +wcmtools/s2/doc/docbook doc/raw/s2 +wcmtools/ddlockd/api/perl/DDLockClient.pm cgi-bin/DDLockClient.pm +wcmtools/ddlockd/server/ddlockd bin/ddlockd +wcmtools/dmtpd/server/dmtpd bin/dmtpd +wcmtools/mogilefs/api/perl/MogileFS.pm cgi-bin/MogileFS.pm +wcmtools/lib/Danga-Daemon/Daemon.pm cgi-bin/Danga/Daemon.pm +wcmtools/lib/Danga-Socket/Socket.pm cgi-bin/Danga/Socket.pm +wcmtools/lib/LWPx-ParanoidAgent/lib/LWPx cgi-bin/LWPx +wcmtools/openid/perl/Net-OpenID-Consumer/lib cgi-bin +wcmtools/openid/perl/Net-OpenID-Server/lib cgi-bin +livejournal/htdocs/login.bml ssldocs/login.bml +livejournal/htdocs/create.bml ssldocs/create.bml +livejournal/htdocs/changepassword.bml ssldocs/changepassword.bml +livejournal/htdocs/captcha ssldocs/captcha +livejournal/htdocs/img/icon_protected.gif ssldocs/img/icon_protected.gif +livejournal/htdocs/img/userinfo.gif ssldocs/img/userinfo.gif +local? . diff --git a/livejournal/doc/designnotes/multihomed_userprops.txt b/livejournal/doc/designnotes/multihomed_userprops.txt new file mode 100755 index 0000000..2187fd9 --- /dev/null +++ b/livejournal/doc/designnotes/multihomed_userprops.txt @@ -0,0 +1,46 @@ + Explanation of Multihomed Userprops + +The LiveJournal code provides a directory service that enables users to search +for other users based on various criteria, including AOL Instant Messenger +screen name, ICQ number, Jabber address, and others. These values are all +stored as userprops. + +Userprops themselves can either be stored on the global database or on the +user's cluster. Putting things on the cluster is generally better, especially +when the things relate to the user in such an integral way. However, that +doesn't work so well with the userprops that are used for searching, because +then you'd have to hit every cluster and repeat the search, which causes a lot +of extra work to be done. Therefore, the properties that are used for +searching have remained on the global database. + +This is a problem too, though, because while searching is done fairly often, +most of the time properties are loaded for such purposes as displaying the +user's profile page. This doesn't require a search through all data, so +should really be done using just the user's cluster. + +Thus, multihomed userprops were born. Basically, a multihomed userprop is one +that is stored in two locations for the express purpose of making it easier to +load these properties in the majority of cases. The two locations are on the +global database on the "userprop" table and on the user clusters in the +"userproplite2" tables. + +When a property is defined as multihomed (multihomed = '1' in the userproplist +table), LJ::set_userprop and LJ::load_user_props know how to deal with it. No +differences in coding style are required. It's completely transparent to the +rest of the system. + +Pseudo-logic for saving a multihomed userprop goes like this: + - Save data to global (standard behavior, empty values are not saved) + - Save data to cluster (empty values ARE saved as '') + +Pseudo-logic for loading a multihomed userprop goes like this: + - Load data from cluster + - If data not found, try loading from master + - If we had to load from master, save data to cluster (empty values saved) + +The only real difference between the old and new way of doing things is that +empty userprops, which were previously just deleted from the table, are +instead saved. This is to prevent hitting up the cluster and thinking that we +have not gotten this property from the global before and hitting the global +repeatedly. Instead, we save it locally as blank, and don't hit the global +ever again. diff --git a/livejournal/doc/ljconfig.pl.txt b/livejournal/doc/ljconfig.pl.txt new file mode 100755 index 0000000..e1d67d6 --- /dev/null +++ b/livejournal/doc/ljconfig.pl.txt @@ -0,0 +1,595 @@ +#!/usr/bin/perl +# -*-perl-*- + +# LiveJournal configuration file. Copy this out of the documentation +# directory to cgi-bin/ljconfig.pl and edit as necessary. The reason +# it's not in the cgi-bin directory already is to protect it from +# getting clobbered when you upgrade to the newest LiveJournal code in +# the future. + +# This should be the only file you need to change to get the +# LiveJournal code to run on your site. If not, it's considered a bug +# and you should report it. + +{ + package LJ; + + ### + ### Site Information + ### + + $HOME = $ENV{'LJHOME'}; + $HTDOCS = "$HOME/htdocs"; + $BIN = "$HOME/bin"; + $TEMP = "$HOME/temp"; + $VAR = "$HOME/var"; + + # human readable name of this site as well as shortened versions + # CHANGE THIS + $SITENAME = "Some LiveJournal Site"; + $SITENAMESHORT = "YourSite"; + $SITENAMEABBREV = "YS"; + + # the base domain of your site. + # CHANGE THIS + $DOMAIN = "ljsite.com"; + + # this is what gets prepended to all URLs + $SITEROOT = "http://www.$DOMAIN"; + + # prefix for images + $IMGPREFIX = "$SITEROOT/img"; + + # set this if you're running an FTP server that mirrors your htdocs/files + #$FTPPREFIX = "ftp://ftp.$DOMAIN"; + + # where we set the cookies (note the period before the domain) + # can be one value or an array ref (to accomodate certain old + # broken browsers) + $COOKIE_DOMAIN = ["", ".$DOMAIN"]; + $COOKIE_PATH = "/"; + + # email addresses + $ADMIN_EMAIL = "webmaster\@$DOMAIN"; + $SUPPORT_EMAIL = "support\@$DOMAIN"; + $COMMUNITY_EMAIL = "community_invitation\@$DOMAIN"; + $BOGUS_EMAIL = "lj_dontreply\@$DOMAIN"; + + # news site support. if set, that journal loads on the main page. + #$FRONTPAGE_JOURNAL = "news"; + + # if you define these, little help bubbles appear next to common + # widgets to the URL you define: + %HELPURL = ( + #"accounttype" => "", + #"renaming" => "$SITEROOT/support/faqbrowse.bml?faqid=25", + #"security" => "$SITEROOT/support/faqbrowse.bml?faqid=24", + #"noautoformat" => "$SITEROOT/support/faqbrowse.bml?faqid=26", + #"userpics" => "$SITEROOT/support/faqbrowse.bml?faqid=46", + #"iplogging" => "$SITEROOT/support/faqbrowse.bml?faqid=66", + #"s2propoff" => '$SITEROOT/support/faqbrowse.bml?faqid=145', + #"userpic_inactive" => "$SITEROOT/support/faqbrowse.bml?faqid=46", + #"textmessaging_about" => "$SITEROOT/support/faqbrowse.bml?faqid=30", + #"linklist_support" => "$SITEROOT/manage/links.bml", + ); + + + + ### + ### Policy Options + ### + + # collect birthdays to mark users as underage (under 13). note that you will + # need to create a new cap class for underage users... + $COPPA_CHECK = 0; + #$UNDERAGE_BIT = ?; + # and then set $UNDERAGE_BIT to be the bit number for the capability class to + # put underage users in. off by default. + + $TOS_CHECK = 1; # require users to agree to TOS + #$UNIQ_COOKIES = 1; # give users uniq cookies to help fight abuse + + %REQUIRED_TOS = + ( + # revision must be found in first line of your htdocs/inc/legal-tos include file: + # + + # set required version to enable tos version requirement mechanism + #rev => '1.0', + + # these are the defaults and are used if no "domain"-specific + # values are defined below + title => 'Configurable Title for TOS requirement', + html => 'Configurable HTML for TOS requirement', + text => 'Configurable text error message for TOS requirement', + + # text/html to use when message displayed for a login action + login => { + html => "Before logging in, you must update your TOS agreement", + }, + + # ... an update action + update => { + html => "HTML to use in update.bml", + }, + + # ... posting a comment (this will just use the defaults above) + comment => { + }, + + # ... protocol actions + protocol => { + text => "Please visit $LJ::SITEROOT/legal/tos.bml to update your TOS agreement", + }, + + # ... support requests + support => { + html => "Text to use when viewing a support request", + }, + + ); + + # filter comments for spam using this list of regular expressions: + #@TALKSPAM = ( + # "morphese", + # ); + + # require new free acounts to be referred by an existing user? + # NOTE: mostly ljcom-specific. some features unimplemented in + # the livejournal-only tree. + #$USE_ACCT_CODES = 1; + + #$EVERYONE_PAID = 1; # are all users paid by default? + #$EVERYONE_VALID = 1; # are all users validated by default? + + + ### + ### System Information + ### + + # on a larger installation, it's useful to have multiple qbufferd.pl + # processes, one for each command type. this is unecessary on a + # small installation. you can also specify a delay between runs. + #@QBUFFERD_ISOLATE = ('weblogscom', 'ljcom_newpost'); + #$QBUFFERD_DELAY = 10; + + # MemCache information, if you have MemCache servers running + #@MEMCACHE_SERVERS = ('hostname:port'); + #$MEMCACHE_COMPRESS_THRESHOLD = 1_000; # bytes + + # path to sendmail and any necessary options + $SENDMAIL = "/usr/sbin/sendmail -t"; + + # optional SMTP server if it is to be used instead of sendmail + #$SMTP_SERVER = "127.0.0.1"; + + # command-line to spell checker, or undefined if you don't want spell checking + #$SPELLER = "/usr/local/bin/ispell -a"; + #$SPELLER = "/usr/local/bin/aspell pipe --sug-mode=fast --ignore-case"; + + # to save bandwidth, should we compress pages before they go out? + # require Compress::Zlib to be installed + #$DO_GZIP = 1; + + # Support signed PGP email for email posting? + # Requires GnuPG::Interface and Mail::GnuPG to be installed. + #$USE_PGP = 1; + + # HINTS: + # how far you can scroll back on lastn and friends pages. + # big performance implications if you make these too high. + # also, once you lower them, increasing them won't change anything + # until there are new posts numbering the difference you increased + # it by. + $MAX_HINTS_LASTN = 100; + $MAX_SCROLLBACK_LASTN = 400; + + # do paid users get email addresses? username@$USER_DOMAIN ? + # (requires additional mail system configuration) + #$USER_EMAIL = 1; + + # Support URLs of the form http://username.yoursite.com/ ? + # If so, what's the part after "username." ? + #$USER_VHOSTS = 1; + #$USER_DOMAIN = $DOMAIN; + + # If you ONLY want USER_VHOSTS to work and not the typical /users/USER and /community/USER + # then set this option: + #$ONLY_USER_VHOSTS = 1; + + # Support updating of journals via email? + # Users can post to user@$EMAIL_POST_DOMAIN. + #$EMAIL_POST_DOMAIN = "post.$DOMAIN"; + + # This should be a path to a Maildir, matching the delivery + # location of your MTA. + # If you are using sendmail, you should deliver with procmail + # (versions 3.14 and above) for Maildir support. + #$MAILSPOOL = '/home/livejournal/mail'; + + # Allow users to point their own domains here? + #OTHER_VHOSTS = 1; + + # turns these from 0 to 1 to disable parts of the site that are + # CPU & database intensive or that you simply don't want to use + %DISABLED = ( + 'interests-findsim' => 0, + 'directory' => 0, + 'stats-recentupdates' => 0, + 'stats-newjournals' => 0, + 'stats-postsbyday' => 0, + 'show-talkleft' => 0, + 'memories' => 0, + 'topicdir' => 0, + 'tellafriend' => 0, + 'feedster_search' => 0, + 'community-logins' => 0, + ); + + # turn $SERVER_DOWN on while you do any maintenance + $SERVER_TOTALLY_DOWN = 0; + $SERVER_DOWN = 0; + $SERVER_DOWN_SUBJECT = "Maintenance"; + $SERVER_DOWN_MESSAGE = "$SITENAME is down right now while we upgrade. It should be up in a few minutes."; + $MSG_READONLY_USER = "This journal is in read-only mode right now while database maintenance is performed " . + "on the server where the journal is located. Try again in several minutes."; + $MSG_NO_POST = "Due to hardware maintenance, you cannot post at this time. Watch the news page for updates."; + $MSG_NO_COMMENT = "Due to hardware maintenance, you cannot leave comments at this time. Watch the news " . + "page for updates."; + #$MSG_DB_UNAVAILABLE = "Sorry, database temporarily unavailable. Please see ... for status updates."; + + ### + ### Language / Scheme support + ### + + # schemes available to users. + # schemes will be displayed according to their order in the array, + # but the first item in the array is the default scheme + # 'title' is the printed name, while 'scheme' is the scheme name. + @SCHEMES = ( + { scheme => 'lynx', title => 'Lynx', + #thumb => [ 'schemethumb/lynx.png', 200, 166 ] + }, + { scheme => 'bluewhite', title => 'Blue White' }, + ); + + # supported languages + #@LANGS = qw(en_LJ en_GB de da es fr it ru ja pt eo he nl hu ga is fi nb sv pl zh lv tr ms); + + # support unicode (posts in multiple languages)? leave enabled. + $UNICODE = 1; + + + ### + ### Database Configuration + ### + + # database info. only the master is necessary. + # you should probably CHANGE THIS + %DBINFO = ( + 'master' => { # master must be named 'master' + 'host' => "localhost", + 'port' => 3306, + 'user' => 'lj', + 'pass' => 'ljpass', + 'role' => { + 'cluster1' => 1, + + # optionally, apache write its access logs to a mysql database + #logs => 1, + }, + }, + # example of a TCP-based DB connection + #'somehostname' => { + # 'host' => "somehost", + # 'port' => 1234, + # 'user' => 'username', + # 'pass' => 'password', + #}, + # example of a UNIX domain-socket DB connection + #'otherhost' => { + # 'sock' => "$HOME/var/mysqld.sock", + # 'user' => 'username', + # 'pass' => 'password', + #}, + ); + + # if database logging is enabled above, should we log images or just page requests? + #$DONT_LOG_IMAGES = 1; + + # Turn on memory/cpu usage statistics generation for database logs (requires the + # GTop module to be installed) + #$LOG_GTOP = 1; + + # directory optimizations + $DIR_DB_HOST = "master"; # DB role to use when connecting to directory DB + $DIR_DB = ""; # by default, hit the main database (bad for big sites!) + #$DIRECTORY_SEPARATE = 1; # don't let the directory use master databases + + # list of all clusters - each one needs a 'cluster$i' role in %DBINFO + @CLUSTERS = (1); # eg: (1, 2, 3) (for scalability) + + # if any of your clusters are InnoDB based, uncomment this and update the qw() + # appropriately. this changes some locking behavior for those particular + # clusters in some of the hot codepaths that use lots of locking. + #%INNODB_DB = ( map { $_ => 1 } qw( 1 ) ); + + # can users choose which cluster they're assigned to? leave this off. + $ALLOW_CLUSTER_SELECT = 0; + + # which cluster(s) get new users? + # if it's an arrayref, choose one of the listed clusters at random. you can weight + # new users by repeating cluster numbers, e.g. [ 1, 1, 1, 2 ] puts 75% of people on + # cluster 1, 25% of people on cluster 2. clusters are checked for validity before + # being used. + $DEFAULT_CLUSTER = [ 1 ]; + + # which cluster should syndication accounts live on? + $SYND_CLUSTER = 1; + + # Only turn this on if you are using MySQL replication between + # multiple databases and have one or more slaves set to not + # replicated the logtext and talktext tables. Turning this on + # makes LJ duplicate all logtext & talktext rows into + # recent_logtext & recent_talktext which is then replicated. + # However, a cron job cleans up that table so it's never too big. + # LJ will try the slaves first, then the master. This is the best + # method of scaling your LJ installation, as disk seeks on the + # database for journal text is the slowest part. + $USE_RECENT_TABLES = 0; + + + ### + ### Account Information + ### + + # initial friends for new accounts. + # leave undefined if you don't want to use it. + #@INITIAL_FRIENDS = qw(news); + + # some system accounts have so many friends it is harmful to display + # them. list these accounts here. + #%FORCE_EMPTY_FRIENDS = ( + # '81752' => 'paidmembers' + # ); + + # list of regular expressions matching usernames that people can't have. + @PROTECTED_USERNAMES = ("^ex_", "^lj_"); + + # test accounts are special + @TESTACCTS = qw(test); + + # props users should have by default + #%USERPROP_DEF = ( + # 's1_lastn_style' => 29, + # 's1_friends_style' => 20, + # 's1_calendar_style' => 2, + # 's1_day_style' => 11, + # ); + + + ### User Capabilities Classes: + + # default capability limits, used only when no other + # class-specific limit below matches. + %CAP_DEF = ( + 'maxfriends' => 500, + 'userpics' => 1, + 'checkfriends_interval' => 60, + 'checkfriends' => 1, + 'styles' => 0, + 'todomax' => 25, + 'todosec' => 0, + 'friendsviewupdate' => 30, + 'findsim' => 1, + 'getselfemail' => 0, + ); + + # capability class limits. + # keys are bit numbers, from 0 .. 15. values are hashrefs + # with limit names and values (see doc/capabilities.txt) + # NOTE: you don't even need to have different capability classes! + # all users can be the same if you want, just delete all + # this. the important part then is %CAP_DEF, above. + %CAP = ( + '0' => { # 0x01 + '_name' => 'new user', + 'userpics' => 1, + }, + '1' => { # 0x02 + '_name' => 'free user', + 'userpics' => 3, + }, + '2' => { # 0x04 + '_name' => 'early adopter', + 'userpics' => 5, + 'styles' => 1, + }, + '3' => { # 0x08 + '_name' => 'paid user', + 'styles' => 1, + 'makepoll' => 1, + 'userpics' => 10, + 'paid' => 1, + 'useremail' => 1, + 'textmessaging' => 1, + }, + '4' => { # 0x10 + '_name' => 'permanent account', + 'paid' => 1, + 'useremail' => 1, + }, + # a capability class with a name of "_moveinprogress" is required + # if you want to be able to move users between clusters with the + # provided tool. further, this class must define 'readonly' => 1 + '5' => { + '_name' => '_moveinprogress', + 'readonly' => 1, + }, + ); + + # default capability class mask for new users: + # (16 bit unsigned int ... each bit is capability class flag) + $NEWUSER_CAPS = 2; + + + ### S1 style options + + $SYN_LASTN_S1 = 1; # lastn style to use for syndication accounts + $DONT_TOUCH_STYLES = 0; # don't touch existing styles + + $DEFAULT_STYLE = { + 'core' => 'core1', + 'layout' => 'generator/layout', + 'i18n' => 'generator/en', + }; + + ### /admin/fileedit setup + # If you are using the files in htdocs/inc and are frequently editing + # those, you may wish to put all of these files into the database. + # You can instruct BML to treat all statements as being + # pulled from memcached (failover to the database) by uncommenting: + # $FILEEDIT_VIA_DB = 1; + # Alternately, you can specify that only particular files should be + # kept in memcache and the database by doing: + # %FILEEDIT_VIA_DB = ( 'support_links' => 1, ); + + ### S2 Style Options + + # which users' s2 layers should always run trusted un-cleaned? + #%S2_TRUSTED = ( '2' => 'whitaker' ); # userid => username + + + ### + ### Portal Options + ### + + # most of the portal options have sane default values, but if you + # need to override them, here's the format: + + #@PORTAL_COLS = qw(main right moz); # can also include left, if you want. + #$PORTAL_URI = "/portal/"; # either "/" or "/portal/" + + #$PORTAL_LOGGED_IN ||= {'main' => [ + # [ 'newtolj', ''], + # [ 'update', 'mode=full'], + # ], + # 'right' => [ + # [ 'goat', '', ], + # [ 'stats', '', ], + # [ 'bdays', '', ], + # [ 'memories', '', ], + # [ 'popfaq', '', ], + # ] }; + + #$PORTAL_LOGGED_OUT ||= {'main' => [ + # [ 'newtolj', ''], + # [ 'update', 'mode='], + # ], + # 'right' => [ + # [ 'goat', '', ], + # [ 'login', '', ], + # [ 'stats', '', ], + # [ 'randuser', '', ], + # [ 'popfaq', '', ], + # ], + # 'moz' => [ + # [ 'login', '', ], + # ], + # }; + + # Setup support email address to not accept new emails. Basically if an + # address is specified below, any user who emails it out of the blue will + # be sent back a copy of the specified file along with their email. Users + # will still be allowed to respond to emails from the support system, but + # they can't open a request by emailing the address. The value part of + # the hash is the name of an include file. It will be loaded out of + # LJHOME/htdocs/inc. See %FILEEDIT_VIA_DB for how to make it read + # from memcache/DB. + #%DENY_REQUEST_FROM_EMAIL = ( + # "abuse\@$DOMAIN" => "bounce-abuse", + #); + + # Support diagnostics can be helpful if you are trying to track down a + # bug that has been occurring. You can turn on and off various tracking + # features here. Just uncomment any/all of the following lines. The + # gathered information will be appended to requests that the user opens + # through the web interface. + %SUPPORT_DIAGNOSTICS = ( + # 'track_useragent' => 1, + ); + + # If you want to change the limit on how many bans a user can make, uncomment + # the following line. Default is 5000. + #$MAX_BANS = 5000; + + # If you are using MogileFS on your site for userpics or other purposes, you + # will need to define the following hash and complete the information in it. + #%MOGILEFS_CONFIG = ( + # hosts => [ '10.0.0.1:6001' ], + # root => '/mnt/mogdata', + # classes => { + # 'your_class' => 3, # define any special MogileFS classes you need + # }, + #); + + # If you have multiple internal networks and would like the MogileFS libraries + # to pick one network over the other, you can set the preferred IP list... + #%MOGILEFS_PREF_IP = ( + # 10.0.0.1 => 10.10.0.1, + #); + #That says "if we try to connect to 10.0.0.1, instead try 10.10.0.1 first and + #then fall back to 10.0.0.1". + + # In addition to setting up MogileFS above, you need to enable some options + # if you want to use MogileFS. + #$CAPTCHA_MOGILEFS = 1; # turn this on to put captchas in MogileFS + #$USERPIC_MOGILEFS = 1; # uncomment to put new userpics in MogileFS + + # if you are using Perlbal to balance your web site, by default it uses + # reproxying to distribute the files itself. however, in some situations + # you may not want to do that. use this option to disable that on an + # item by item basis. + #%REPROXY_DISABLE = ( + # userpics => 1, + # captchas => 1, + #); + + # Some people on portable devices may have troubles viewing the nice site + # scheme you've setup, so you can specify that some user-agent prefixes + # should instead use fallback presentation information. + %MINIMAL_USERAGENT = ( + #'Foo' => 1, # if the user-agent field starts with "Foo" ... + # note you can only put text here; no numbers, spaces, or symbols. + ); + $MINIMAL_BML_SCHEME = 'lynx'; + %MINIMAL_STYLE = ( + 'core' => 'core1', # default, but you can add more layers and styles... note + # that they must be public styles + ); + + # this is on in the default file here because most of the time you + # want this flag to be on. if you have an existing site and you're + # copying this file, make sure to only turn this flag on if you've + # actually migrated everything. + $S2COMPILED_MIGRATION_DONE = 1; + + # optional LDAP support + # required: + # $LJ::LDAP_HOST = "ldap.example.com"; # anything that the Net::LDAP constructor takes + # $LJ::LDAP_BASE = "ou=People,dc=exampleorg,dc=com"; + # optional: + # $LJ::LDAP_UID = "uid"; # field containing the username. defaults to "uid". + + # if you know that your installation is behind a proxy or other fence that inserts + # X-Forwarded-For headers that you can trust, enable this. otherwise, don't! + # $TRUST_X_HEADERS = 1; + + # the following values allow you to control enabling your OpenID server and consumer + # support. + $OPENID_SERVER = 1; + $OPENID_CONSUMER = 0; + +} + +1; # return true diff --git a/livejournal/doc/notes/user-statusvis.txt b/livejournal/doc/notes/user-statusvis.txt new file mode 100755 index 0000000..d56312a --- /dev/null +++ b/livejournal/doc/notes/user-statusvis.txt @@ -0,0 +1,36 @@ +"statusvis" stands for "status visibility" and is the basic way that +accounts are marked with various statuses. This column in the user table +is a single character and is taken from the list below: + + +V - visible +This is the normal status that applies to most accounts. Nothing special. + +S - suspended +Accounts that are suspended are effectively invisible. Normal people +cannot see the contents of suspended journals. People with the 'canview' +privilege have some access to see these accounts. (See information on that +privilege.) + +D - deleted +When someone deletes their own account. Has much the same effects as being +suspended, except the user is allowed to undelete their account. + +X - expunged +After an account has been deleted for a while it is expunged. This process +removes all data for an account. At this point the account can no longer +be undeleted. + +R - renamed +When a user is renamed a row is created in the user table with their OLD +username and a statusvis of R. This means that any requests for this user +need to be mapped to the username they renamed to. + +M - memorial +No changes from a normal account except that memorial accounts cannot have +new posts added to them. + +L - locked +Accounts in this status are frozen. They cannot be logged in to, cannot +receive comments or post comments, cannot post entries, cannot edit +entries, and basically can't do anything on the site with this account. diff --git a/livejournal/doc/raw/appendices/gfdl.xml b/livejournal/doc/raw/appendices/gfdl.xml new file mode 100755 index 0000000..268aec6 --- /dev/null +++ b/livejournal/doc/raw/appendices/gfdl.xml @@ -0,0 +1,450 @@ + +GNU Free Documentation License + + + + + + + Version 1.1, March 2000 + +
    + Copyright (C) 2000 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +
    + + + PREAMBLE + + The purpose of this License is to make a manual, textbook, + or other written document "free" in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by + others. + + This License is a kind of "copyleft", which means that + derivative works of the document must themselves be free in the + same sense. It complements the GNU General Public License, which + is a copyleft license designed for free software. + + We have designed this License in order to use it for manuals + for free software, because free software needs free documentation: + a free program should come with manuals providing the same + freedoms that the software does. But this License is not limited + to software manuals; it can be used for any textual work, + regardless of subject matter or whether it is published as a + printed book. We recommend this License principally for works + whose purpose is instruction or reference. + + + + APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work that + contains a notice placed by the copyright holder saying it can be + distributed under the terms of this License. The "Document", + below, refers to any such manual or work. Any member of the + public is a licensee, and is addressed as "you". + + A "Modified Version" of the Document means any work + containing the Document or a portion of it, either copied + verbatim, or with modifications and/or translated into another + language. + + A "Secondary Section" is a named appendix or a front-matter + section of the Document that deals exclusively with the + relationship of the publishers or authors of the Document to the + Document's overall subject (or to related matters) and contains + nothing that could fall directly within that overall subject. + (For example, if the Document is in part a textbook of + mathematics, a Secondary Section may not explain any mathematics.) + The relationship could be a matter of historical connection with + the subject or with related matters, or of legal, commercial, + philosophical, ethical or political position regarding + them. + + The "Invariant Sections" are certain Secondary Sections + whose titles are designated, as being those of Invariant Sections, + in the notice that says that the Document is released under this + License. + + The "Cover Texts" are certain short passages of text that + are listed, as Front-Cover Texts or Back-Cover Texts, in the + notice that says that the Document is released under this + License. + + A "Transparent" copy of the Document means a + machine-readable copy, represented in a format whose specification + is available to the general public, whose contents can be viewed + and edited directly and straightforwardly with generic text + editors or (for images composed of pixels) generic paint programs + or (for drawings) some widely available drawing editor, and that + is suitable for input to text formatters or for automatic + translation to a variety of formats suitable for input to text + formatters. A copy made in an otherwise Transparent file format + whose markup has been designed to thwart or discourage subsequent + modification by readers is not Transparent. A copy that is not + "Transparent" is called "Opaque". + + Examples of suitable formats for Transparent copies include + plain ASCII without markup, Texinfo input format, LaTeX input + format, SGML or XML using a publicly available DTD, and + standard-conforming simple HTML designed for human modification. + Opaque formats include PostScript, PDF, proprietary formats that + can be read and edited only by proprietary word processors, SGML + or XML for which the DTD and/or processing tools are not generally + available, and the machine-generated HTML produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page + itself, plus such following pages as are needed to hold, legibly, + the material this License requires to appear in the title page. + For works in formats which do not have any title page as such, + "Title Page" means the text near the most prominent appearance of + the work's title, preceding the beginning of the body of the + text. + + + + VERBATIM COPYING + + You may copy and distribute the Document in any medium, + either commercially or noncommercially, provided that this + License, the copyright notices, and the license notice saying this + License applies to the Document are reproduced in all copies, and + that you add no other conditions whatsoever to those of this + License. You may not use technical measures to obstruct or + control the reading or further copying of the copies you make or + distribute. However, you may accept compensation in exchange for + copies. If you distribute a large enough number of copies you + must also follow the conditions in section 3. + + You may also lend copies, under the same conditions stated + above, and you may publicly display copies. + + + + COPYING IN QUANTITY + + If you publish printed copies of the Document numbering more + than 100, and the Document's license notice requires Cover Texts, + you must enclose the copies in covers that carry, clearly and + legibly, all these Cover Texts: Front-Cover Texts on the front + cover, and Back-Cover Texts on the back cover. Both covers must + also clearly and legibly identify you as the publisher of these + copies. The front cover must present the full title with all + words of the title equally prominent and visible. You may add + other material on the covers in addition. Copying with changes + limited to the covers, as long as they preserve the title of the + Document and satisfy these conditions, can be treated as verbatim + copying in other respects. + + If the required texts for either cover are too voluminous to + fit legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a + machine-readable Transparent copy along with each Opaque copy, or + state in or with each Opaque copy a publicly-accessible + computer-network location containing a complete Transparent copy + of the Document, free of added material, which the general + network-using public has access to download anonymously at no + charge using public-standard network protocols. If you use the + latter option, you must take reasonably prudent steps, when you + begin distribution of Opaque copies in quantity, to ensure that + this Transparent copy will remain thus accessible at the stated + location until at least one year after the last time you + distribute an Opaque copy (directly or through your agents or + retailers) of that edition to the public. + + It is requested, but not required, that you contact the + authors of the Document well before redistributing any large + number of copies, to give them a chance to provide you with an + updated version of the Document. + + + + MODIFICATIONS + + You may copy and distribute a Modified Version of the + Document under the conditions of sections 2 and 3 above, provided + that you release the Modified Version under precisely this + License, with the Modified Version filling the role of the + Document, thus licensing distribution and modification of the + Modified Version to whoever possesses a copy of it. In addition, + you must do these things in the Modified Version: + + + Use in the Title Page + (and on the covers, if any) a title distinct from that of the + Document, and from those of previous versions (which should, if + there were any, be listed in the History section of the + Document). You may use the same title as a previous version if + the original publisher of that version gives permission. + + + List on the Title Page, + as authors, one or more persons or entities responsible for + authorship of the modifications in the Modified Version, + together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than + five). + + + State on the Title page + the name of the publisher of the Modified Version, as the + publisher. + + + Preserve all the + copyright notices of the Document. + + + Add an appropriate + copyright notice for your modifications adjacent to the other + copyright notices. + + + Include, immediately + after the copyright notices, a license notice giving the public + permission to use the Modified Version under the terms of this + License, in the form shown in the Addendum below. + + + Preserve in that license + notice the full lists of Invariant Sections and required Cover + Texts given in the Document's license notice. + + + Include an unaltered + copy of this License. + + + Preserve the section + entitled "History", and its title, and add to it an item stating + at least the title, year, new authors, and publisher of the + Modified Version as given on the Title Page. If there is no + section entitled "History" in the Document, create one stating + the title, year, authors, and publisher of the Document as given + on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. + + + Preserve the network + location, if any, given in the Document for public access to a + Transparent copy of the Document, and likewise the network + locations given in the Document for previous versions it was + based on. These may be placed in the "History" section. You + may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. + + + In any section entitled + "Acknowledgements" or "Dedications", preserve the section's + title, and preserve in the section all the substance and tone of + each of the contributor acknowledgements and/or dedications + given therein. + + + Preserve all the + Invariant Sections of the Document, unaltered in their text and + in their titles. Section numbers or the equivalent are not + considered part of the section titles. + + + Delete any section + entitled "Endorsements". Such a section may not be included in + the Modified Version. + + + Do not retitle any + existing section as "Endorsements" or to conflict in title with + any Invariant Section. + + + + If the Modified Version includes new front-matter sections + or appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option + designate some or all of these sections as invariant. To do this, + add their titles to the list of Invariant Sections in the Modified + Version's license notice. These titles must be distinct from any + other section titles. + + You may add a section entitled "Endorsements", provided it + contains nothing but endorsements of your Modified Version by + various parties--for example, statements of peer review or that + the text has been approved by an organization as the authoritative + definition of a standard. + + You may add a passage of up to five words as a Front-Cover + Text, and a passage of up to 25 words as a Back-Cover Text, to the + end of the list of Cover Texts in the Modified Version. Only one + passage of Front-Cover Text and one of Back-Cover Text may be + added by (or through arrangements made by) any one entity. If the + Document already includes a cover text for the same cover, + previously added by you or by arrangement made by the same entity + you are acting on behalf of, you may not add another; but you may + replace the old one, on explicit permission from the previous + publisher that added the old one. + + The author(s) and publisher(s) of the Document do not by + this License give permission to use their names for publicity for + or to assert or imply endorsement of any Modified Version. + + + + COMBINING DOCUMENTS + + You may combine the Document with other documents released + under this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination + all of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice. + + The combined work need only contain one copy of this + License, and multiple identical Invariant Sections may be replaced + with a single copy. If there are multiple Invariant Sections with + the same name but different contents, make the title of each such + section unique by adding at the end of it, in parentheses, the + name of the original author or publisher of that section if known, + or else a unique number. Make the same adjustment to the section + titles in the list of Invariant Sections in the license notice of + the combined work. + + In the combination, you must combine any sections entitled + "History" in the various original documents, forming one section + entitled "History"; likewise combine any sections entitled + "Acknowledgements", and any sections entitled "Dedications". You + must delete all sections entitled "Endorsements." + + + + COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and + other documents released under this License, and replace the + individual copies of this License in the various documents with a + single copy that is included in the collection, provided that you + follow the rules of this License for verbatim copying of each of + the documents in all other respects. + + You may extract a single document from such a collection, + and distribute it individually under this License, provided you + insert a copy of this License into the extracted document, and + follow this License in all other respects regarding verbatim + copying of that document. + + + + AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of + a storage or distribution medium, does not as a whole count as a + Modified Version of the Document, provided no compilation + copyright is claimed for the compilation. Such a compilation is + called an "aggregate", and this License does not apply to the + other self-contained works thus compiled with the Document, on + account of their being thus compiled, if they are not themselves + derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to + these copies of the Document, then if the Document is less than + one quarter of the entire aggregate, the Document's Cover Texts + may be placed on covers that surround only the Document within the + aggregate. Otherwise they must appear on covers around the whole + aggregate. + + + + TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires + special permission from their copyright holders, but you may + include translations of some or all Invariant Sections in addition + to the original versions of these Invariant Sections. You may + include a translation of this License provided that you also + include the original English version of this License. In case of + a disagreement between the translation and the original English + version of this License, the original English version will + prevail. + + + + TERMINATION + + You may not copy, modify, sublicense, or distribute the + Document except as expressly provided for under this License. Any + other attempt to copy, modify, sublicense or distribute the + Document is void, and will automatically terminate your rights + under this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full + compliance. + + + + FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised + versions of the GNU Free Documentation License from time to time. + Such new versions will be similar in spirit to the present + version, but may differ in detail to address new problems or + concerns. See http://www.gnu.org/copyleft/. + + Each version of the License is given a distinguishing + version number. If the Document specifies that a particular + numbered version of this License "or any later version" applies to + it, you have the option of following the terms and conditions + either of that specified version or of any later version that has + been published (not as a draft) by the Free Software Foundation. + If the Document does not specify a version number of this License, + you may choose any version ever published (not as a draft) by the + Free Software Foundation. + + + + How to use this License for your documents + + To use this License in a document you have written, include + a copy of the License in the document and put the following + copyright and license notices just after the title page: + +
    + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +
    + + If you have no Invariant Sections, write "with no Invariant + Sections" instead of saying which ones are invariant. If you have + no Front-Cover Texts, write "no Front-Cover Texts" instead of + "Front-Cover Texts being LIST"; likewise for Back-Cover + Texts. + + If your document contains nontrivial examples of program + code, we recommend releasing these examples in parallel under your + choice of free software license, such as the GNU General Public + License, to permit their use in free software. +
    + +
    \ No newline at end of file diff --git a/livejournal/doc/raw/build/api/api2db.pl b/livejournal/doc/raw/build/api/api2db.pl new file mode 100755 index 0000000..058862d --- /dev/null +++ b/livejournal/doc/raw/build/api/api2db.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl +# + +use strict; +use Getopt::Long; + +my ($opt_include, $opt_exclude, $opt_book); +die unless GetOptions( + 'include=s' => \$opt_include, + 'exclude=s' => \$opt_exclude, + 'book=s' => \$opt_book, + ); +die "Unknown arguments.\n" if @ARGV; +die "Can't exclude and include at same time!\n" if $opt_include && $opt_exclude; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +require "$ENV{'LJHOME'}/doc/raw/build/docbooklib.pl"; + +chdir $ENV{'LJHOME'} or die "Can't cd to $ENV{'LJOME'}\n"; + +unless ($opt_book) { $opt_book = "ljp"; } + +### apidoc.pl does all the hard work. +my $VAR1; +my $param; +$param = "--include=$opt_include" if $opt_include; +$param = "--exclude=$opt_exclude" if $opt_exclude; +eval `$ENV{'LJHOME'}/bin/apidoc.pl --conf=$ENV{'LJHOME'}/doc/raw/build/api/apidoc.conf $param`; +my $api = $VAR1; + +print "\n"; +print " API Documentation\n"; + +foreach my $func (sort keys %$api) { + my $f = $api->{$func}; + my $argstring; + + my $canonized = canonize("func" , $func, "", $opt_book); + print " \n"; + + ### name and short description: + cleanse(\$f->{'des'}, $opt_book); + print " \n"; + print " $func\n"; + print " $f->{'des'}\n"; + print " \n"; + + ### usage: + print " \n"; + print " Use\n"; + print " \n"; + print " \n"; + print " $func\n"; + if (@{$f->{'args'}}) { + foreach my $arg (@{$f->{'args'}}) { + print " $arg->{'name'}\n"; + } + } + print " \n"; + print " \n"; + print " \n"; + + ### arguments: + if (@{$f->{'args'}}) { + print " \n"; + print " Arguments\n"; + print " \n"; + + foreach my $arg (@{$f->{'args'}}) { + print " \n"; + print " $arg->{'name'}\n"; + my $des = $arg->{'des'}; + cleanse(\$des, $opt_book); + print " $des\n"; + print " \n"; + } + print " \n"; + print " \n"; + } + + ### info: + if ($f->{'info'}) { + cleanse(\$f->{'info'}, $opt_book); + print " \n"; + print " Info\n"; + print " $f->{'info'}\n"; + print " \n"; + } + + ### source file: + print " \n"; + print " Source:\n"; + print " $f->{'source'}\n"; + print " \n"; + + ### returning: + if ($f->{'returns'}) { + cleanse(\$f->{'returns'}, $opt_book); + print " \n"; + print " Returns:\n"; + print " $f->{'returns'}\n"; + print " \n"; + } + + print " \n"; +} + +print "\n"; diff --git a/livejournal/doc/raw/build/api/apidoc.conf b/livejournal/doc/raw/build/api/apidoc.conf new file mode 100755 index 0000000..33941b9 --- /dev/null +++ b/livejournal/doc/raw/build/api/apidoc.conf @@ -0,0 +1,19 @@ +basedir $LJHOME +dodir cgi-bin + +class general General +class api API +class db Database +class logging Logging +class time Date & Time +class component Components +class s1 Style System v1 +class security Security +class web Web Programming +class text Text Processing + +arg dbarg Deprecated; a master database handle ($dbh) or a master/slave set of database handles ($dbs). +arg hookname Name of hook. See doc/hooks.txt. +arg u A hashref of a row from the user table, sometimes called a "user object". Although only initially a row from the user table, gets a lot of tacked onto it from various other LJ API functions. +arg remote Hashref of remote user containing \'user\' and \'userid\' keys if obtained from [func[LJ::get_remote]] or just \'user\' if untrusted and obtained from [func[LJ::get_remote_noauth]]. +arg dbcm Cluster master database handle diff --git a/livejournal/doc/raw/build/caps/cap-local.pl b/livejournal/doc/raw/build/caps/cap-local.pl new file mode 100755 index 0000000..9851e52 --- /dev/null +++ b/livejournal/doc/raw/build/caps/cap-local.pl @@ -0,0 +1,15 @@ +#!/usr/bin/perl +# + +use strict; + +use vars qw(%cap_local); + +$caps_local{'paid'} = { + type => 'boolean', + desc => 'User has paid for their account type.', +}; +$caps_local{'fastserver'} = { + type => 'boolean', + desc => 'User has access to the faster (paid) servers.', +}; diff --git a/livejournal/doc/raw/build/caps/cap2db.pl b/livejournal/doc/raw/build/caps/cap2db.pl new file mode 100755 index 0000000..7a5eb9d --- /dev/null +++ b/livejournal/doc/raw/build/caps/cap2db.pl @@ -0,0 +1,167 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +use vars qw(%caps_general %caps_local); + +my $LJHOME = $ENV{'LJHOME'}; + +require "$LJHOME/doc/raw/build/docbooklib.pl"; + +if (-e "$LJHOME/doc/raw/build/caps/cap-local.pl") { + require "$LJHOME/doc/raw/build/caps/cap-local.pl"; +} + +$caps_general{'checkfriends'} = { + type => 'boolean', + desc => 'User can use checkfriends.', +}; +$caps_general{'checkfriends_interval'} = { + type => 'integer', + desc => 'Time before clients can call "checkfriends" (use min).', +}; +$caps_general{'synd_create'} = { + type => 'boolean', + desc => 'User can create syndicated accounts.', +}; +$caps_general{'findsim'} = { + type => 'boolean', + desc => 'User is able to use the similar interests matching feature', +}; +$caps_general{'friendsfriendsview'} = { + type => 'boolean', + desc => 'User\'s "friends of friends" /friendsfriends view is enabled', +}; +$caps_general{'friendsviewupdate'} = { + type => 'integer', + desc => 'After how many seconds user see new friends view items.', +}; +$caps_general{'makepoll'} = { + type => 'boolean', + desc => 'User can user make a poll', +}; +$caps_general{'maxfriends'} = { + type => 'integer', + desc => 'Maximum number of friends that are allowed per account', +}; +$caps_general{'moodthemecreate'} = { + type => 'boolean', + desc => 'User can create new mood themes.', +}; +$caps_general{'readonly'} = { + type => 'boolean', + desc => 'No writes to the database for this journal are permitted. '. + '(this is used by cluster management tool: a journal is readonly '. + 'while it is being moved to another cluster)', +}; +$caps_general{'styles'} = { + type => 'boolean', + desc => 'User can create & use their own styles.', +}; +$caps_general{'textmessage'} = { + type => 'boolean', + desc => 'User can use text messaging.', +}; +$caps_general{'todomax'} = { + type => 'integer', + desc => 'Maximum number of todo items allowed', +}; +$caps_general{'todosec'} = { + type => 'boolean', + desc => 'Can user make non-public todo items?', +}; +$caps_general{'userdomain'} = { + type => 'boolean', + desc => 'Can view journal at http://user.$LJ::DOMAIN/', +}; +$caps_general{'useremail'} = { + type => 'boolean', + desc => 'User has email address @$LJ::USER_DOMAIN', +}; +$caps_general{'userpics'} = { + type => 'integer', + desc => 'Maximum number of user pictures allowed.', +}; +$caps_general{'hide_email_after'} = { + type => 'integer', + desc => "Hide an account's email address who has not used the site in a time period longer than the given setting. ". + "If 0, the email is never hidden. The time period is in days.", +}; +$caps_general{'weblogscom'} = { + type => 'boolean', + desc => "Allow the account to ping weblogs.com with new updates", +}; +$caps_general{'full_rss'} = { + type => 'boolean', + desc => "Show the full text in the RSS view", +}; +$caps_general{'get_comments'} = { + type => 'boolean', + desc => "Can receive comments", +}; +$caps_general{'leave_comments'} = { + type => 'boolean', + desc => "Can leave comments on other accounts", +}; +$caps_general{'can_post'} = { + type => 'boolean', + desc => "Can post new entries", +}; +$caps_general{'rateperiod-failed_login'} = { + type => 'integer', + desc => "The period of time an account can try to repeat logging in for", +}; +$caps_general{'rateallowed-failed_login'} = { + type => 'integer', + desc => "How many times a period an account can try to log in for", +}; +$caps_general{'s2everything'} = { + type => 'boolean', + desc => "Can use all properties of S2 layouts", +}; +$caps_general{'friendspopwithfriends'} = { + type => 'boolean', + desc => "Can use Popular with Friends tool", +}; +$caps_general{'emailpost'} = { + type => 'boolean', + desc => "User has ability to post via an email gateway.", +}; +$caps_general{'disable_can_post'} = { + type => "boolean", + desc => "Posting new journal entries is disabled for this account, presumably because a trial period of some sort has expired.", +}; +$caps_general{'disable_get_comments'} = { + type => "boolean", + desc => "Getting new comments in this journal is disabled, presumably because a trial period of some sort has expired.", +}; +$caps_general{'disable_leave_comments'} = { + type => "boolean", + desc => "This account can no longer leave comments, presumably because a trial period of some sort has expired.", +}; + + +sub dump_caps +{ + my $title = shift; + my $caps = shift; + print "\n $title Capabilities\n"; + foreach my $cap (sort keys %$caps) + { + print " \n"; + print " $cap\n"; + print " \n"; + print " ($caps->{$cap}->{'type'}) - $caps->{$cap}->{'desc'}\n"; + print " \n"; + print " \n"; + } + print "\n"; +} + +dump_caps("General", \%caps_general); +if (%caps_local) { dump_caps("Local", \%caps_local); } diff --git a/livejournal/doc/raw/build/chunk.xsl b/livejournal/doc/raw/build/chunk.xsl new file mode 100755 index 0000000..1d92b34 --- /dev/null +++ b/livejournal/doc/raw/build/chunk.xsl @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/livejournal/doc/raw/build/console/console2db.pl b/livejournal/doc/raw/build/console/console2db.pl new file mode 100755 index 0000000..d85b0f2 --- /dev/null +++ b/livejournal/doc/raw/build/console/console2db.pl @@ -0,0 +1,39 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +require "$ENV{'LJHOME'}/doc/raw/build/docbooklib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/console.pl"; +my $ret; + +$ret .= "Administrative Console Commands\n"; +foreach my $cmdname (sort keys %LJ::Con::cmd) { + my $cmd = $LJ::Con::cmd{$cmdname}; + next if ($cmd->{'hidden'}); + $ret .= "\n"; + $ret .= " $cmdname\n"; + my $des = $cmd->{'des'}; + cleanse(\$des); + $ret .= " \n$des\n"; + if ($cmd->{'args'}) { + $ret .= " \n Arguments:\n"; + my @args = @{$cmd->{'args'}}; + while (my ($argname, $argdes) = splice(@args, 0, 2)) { + $ret .= " "; + $ret .= "$argname\n"; + cleanse(\$argdes); + $ret .= " $argdes\n"; + $ret .= " \n"; + } + $ret .= " \n"; + } + $ret .= " \n"; + $ret .= "\n"; +} +$ret .= "\n"; +print $ret; diff --git a/livejournal/doc/raw/build/db/db2ref.xsl b/livejournal/doc/raw/build/db/db2ref.xsl new file mode 100755 index 0000000..a22cc52 --- /dev/null +++ b/livejournal/doc/raw/build/db/db2ref.xsl @@ -0,0 +1,87 @@ + + + + + + + + + + + + + ljp.dbschema. + + + + + + <database class="table"><xsl:value-of select="name"/></database> + +
    \n Required Modules\n"; +print " \n \n"; +foreach my $module ( @modules ) +{ + print " $module->{'name'}$module->{'deb'}\n" unless $module->{'opt'}; +} +print " \n \n
    "; +print "\n Optional modules\n"; +foreach my $module ( @modules ) +{ + print " $module->{'name'}$module->{'deb'}$module->{'opt'}\n" if $module->{'opt'}; +} +print ""; + +print "Debian Install"; +print "If you're using Debian the following command should retrieve and build every required module:"; +print "# apt-get install "; +my $i = 0; +foreach my $module ( @modules ) { + next if $module->{'opt'}; + if ($i == 3) { print "\\\n"; $i = 0; } $i++; + print "$module->{'deb'} "; +} +print " + +And likewise for the optional modules: + +# apt-get install "; +$i = 0; +foreach my $module ( @modules ) { + next unless $module->{'opt'}; + if ($i == 3) { print "\\\n"; $i = 0; } $i++; + print "$module->{'deb'} "; +} + +print " + + + Using CPAN + + Otherwise you'll want to use CPAN to install the modules by performing the following steps: + + +From the root prompt on your server, invoke the CPAN shell: +# perl -MCPAN -e shell + + + Once the Perl interpreter has loaded (and been configured), you can install + modules by issuing the command install MODULENAME. + +The first thing you should do is upgrade your CPAN: + +cpan> install Bundle::CPAN + +Once it's done, type: + +cpan> reload cpan + +Now, enter the following command to retrieve all of the required modules: + +"; +foreach my $module ( @modules ) { + print "cpan> install $module->{'name'}\n" unless $module->{'opt'}; +} +print " +And likewise for the optional modules: + +"; +foreach my $module ( @modules ) { + print "cpan> install $module->{'name'}\n" if $module->{'opt'}; +} +print ""; diff --git a/livejournal/doc/raw/build/ljconfig/ljconfig2db.pl b/livejournal/doc/raw/build/ljconfig/ljconfig2db.pl new file mode 100755 index 0000000..47a58d4 --- /dev/null +++ b/livejournal/doc/raw/build/ljconfig/ljconfig2db.pl @@ -0,0 +1,488 @@ +#!/usr/bin/perl +# + +use strict; +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +my $LJHOME = $ENV{'LJHOME'}; +require "$LJHOME/doc/raw/build/docbooklib.pl"; + +my %ljconfig = +( + 'user' => { + 'name' => 'User-Configurable', + 'desc' => "New installations will probably want to set these variables. Some are ". + "automatically set by ljdefaults.pl based on your other settings, but it ". + "wouldn't hurt to specify them all explicitly.", + + 'domain' => { + 'name' => 'Domain Related', + 'sitename' => { + 'desc' => "The name of the site", + }, + 'sitenameshort' => { + 'desc' => "The shortened name of the site, for brevity purposes.", + 'default' => "LiveJournal", + }, + 'sitenameabbrev' => { + 'desc' => "The abbreviated version of the name of the site.", + 'default' => "LJ", + }, + 'siteroot' => { + 'desc' => "The URL prefix to construct canonical pages. This can include the port number, if 80 is not in use.", + 'default' => "http://www.\$DOMAIN:8011/", + }, + 'imgprefix' => { + 'desc' => "The URL prefix of the image directory or subdomain.", + 'default' => '$SITEROOT/img', + }, + 'statprefix' => { + 'desc' => "The URL prefix to the static content directory or subdomain.", + 'default' => '$SITEROOT/stc', + }, + 'userpic_root' => { + 'desc' => "The URL prefix to the userpic directory or subdomain.", + 'default' => '$SITEROOT/userpic', + }, + 'domain' => { + 'desc' => "The minimal domain of the site, excluding the 'www.' prefix if applicable.", + }, + 'domain_web' => { + 'desc' => "Optional. If defined and different from [ljconfig[domain]], any GET requests to [ljconfig[domain]] will be redirected to [ljconfig[domain_web]].", + }, + 'cookie_domain' => { + 'desc' => "Cookie domains should simply be set to .\$domain.com, based on the Netscape Cookie Spec, ". + "but some older browsers don't adhere to the specs too well. [ljconfig[cookie_domain]] can ". + "be a single string value, or it can be a perl array ref.", + 'example' => '["", ".$DOMAIN"]', + 'default' => ".\$DOMAIN", + }, + #'cookie_path' => { + # 'desc' => "According to the RFCs concerning cookies, the cookie path needs to be explicitly set as well. If LiveJournal is installed ". + # "underneath a directory other than the top level domain directory, this needs to be set accordingly.", + # 'default' => "/", + #}, + 'server_name' => { + 'desc' => "Optional. If using db-based web logging, this field is stored in the database in the server column, so you can see later how well each server performed. ". + "To share the same ljconfig.pl on each host (say, over NFS), you can put something like this in your ljconfig.pl: It's kinda ugly, but it works. ", + 'example' => 'chomp($SERVER_NAME = `hostname`);', + }, + 'frontpage_journal' => { + 'desc' => "If set, the main page of the site loads the specified journal, not the default index page. ". + "Use this if you're running a news site where there's only one journal, or one journal is dominant.", + }, + 'tos_check' => { + 'desc' => "If set, the account creation dialog shows a checkbox, asking users if they agree to the site's Terms of Service, ". + "and won't allow them to create an account if they refuse. This depends on a few files being located in the proper directories, ". + "namely tos.bml and tos-mini.bml under \$LJHOME/htdocs/legal/. ". + "The account creation dialog can also check for new instances of the Terms of Service if the Terms of Service text is located in a ". + "CVS managed include file (\$LJHOME/htdocs/inc/legal-tos), ". + "and if the include file includes the following line at the top: ]]>", + }, + 'coppa_check' => { + 'desc' => "If set, the account creation dialog shows a checkbox, asking users if they're under 13 years old and won't let them create an account if they check it.", + }, + }, + + 'database' => { + 'name' => "Database Related", + 'dbinfo' => { + 'desc' => "This is a hash that contains the necessary information to connect to your database, as well as ". + "the configuration for multiple database clusters, if your installation supports them. ". + "Consult [special[dbinfo]] for more details.", + 'type' => "hash", + }, + 'clusters' => { + 'default' => "(1)", + 'desc' => "This is an array that contains the names of the clusters that your configuration uses.", + 'example' => 'qw(fast slow)', + 'type' => "array", + }, + 'default_cluster' => { + 'desc' => "The default cluster to choose when creating new accounts.", + 'default' => "1", + }, + 'dir_db' => { + 'desc' => "This setting tells the installation which database to read from for directory usage. ". + "By default this is left blank, meaning that it will use the main database. This can make larger installations work much slower.", + }, + 'dir_db_host' => { + 'desc' => "The database role to use when connecting to the directory database.", + 'example' => "master", + }, + }, + + 'system_tools' => { + 'name' => "System Tools", + 'sendmail' => { + 'desc' => "The system path to the sendmail program, along with any necessary parameters.", + 'example' => '"/usr/bin/sendmail -t"', + }, + 'speller' => { + 'desc' => "The system path to a spell checking binary, along with any necessary parameters.", + 'example' => '"/usr/local/bin/aspell pipe --sug-mode=fast --ignore-case"', + }, + 'smtp_server' => { + 'desc' => "This the recommended system to use for sending email. This requires the perl Net::SMTP module to work properly.", + 'example' => "10.2.0.1", + }, + }, + + 'optimizations' => { + 'name' => "Optimization", + 'max_hints_lastn' => { + 'desc' => "Sets how many entries a user can have on their LASTN page. A higher value can majorly affect the speed of the installation.", + 'default' => "100", + }, + 'max_scrollback_friends' => { + 'desc' => "Sets how far back someone can go on a user's FRIENDS page. A higher value can majorly affect the speed of the installation.", + 'default' => "1000", + }, + 'use_recent_tables' => { + 'desc' => "Only turn this on if you are using MySQL replication between multiple databases and have one or more slaves set to not ". + "replicated the logtext and talktext tables. Turning this on makes LJ duplicate all logtext & talktext rows into ". + "recent_logtext & recent_talktext which is then replicated. However, a cron job cleans up that table so it's never too big. ". + "LJ will try the slaves first, then the master. This is the best method of scaling your LJ installation, as disk seeks on the ". + "database for journal text is the slowest part.", + }, + 'do_gzip' => { + 'desc' => "Boolean setting that when enabled, signals to the installation to use gzip encoding wherever possible. In most cases this is known ". + "to cut bandwidth usage in half. Requires the Compress::Zlib perl module.", + }, + 'msg_readonly_user' => { + 'desc' => "Message to send to users if their account becomes readonly during maintenance.", + 'example' => "This journal is in read-only mode right now while database maintenance is being performed. Try again in a few minutes.", + }, + 'compress_text' => { + 'desc' => "Boolean setting that compresses log and comment text in the database, to save disk space.", + } + }, + + 'syndication' => { + 'name' => "Syndicated Account Options", + 'syn_lastn_s1' => { + 'desc' => "When set to an appropriate LASTN style, all syndicated accounts on this installation will use this style.", + }, + 'synd_cluster' => { + 'desc' => "Syndicated accounts tend to have more database traffic than normal accounts, so its a good idea to set up a seperate cluster for them.". + "If set to a cluster (defined by [ljconfig[clusters]]), all newly created syndicated accounts will reside on that cluster.", + }, + }, + + 'debug' => { + 'name' => "Development/Debugging Options", + 'allow_cluster_select' => { + 'desc' => "When set true, the journal creation page will display a drop-down list of clusters (from [ljconfig[clusters]]) along ". + "with the old 'cluster 0' which used the old db schema and the user creating an account can choose where they go. ". + "In reality, there's no use for this, it's only useful when working on the code.", + }, + 'nodb_msg' => { + 'desc' => "Message to send to users when the database is unavailable", + 'default' => "Database temporarily unavailable. Try again shortly.", + }, + 'server_down' => { + 'desc' => "Set true when performing maintenance that requires user activity to be minimum, such as database defragmentation and cluster movements.", + 'default' => "0", + }, + 'server_down_subject' => { + 'desc' => "While [ljconfig[server_down]] is set true, a message with this subject is displayed for anyone trying to access the LiveJournal installation.", + 'example' => "Maintenance", + }, + 'server_down_message' => { + 'desc' => "While [ljconfig[server_down]] is set true, this message will be displayed for anyone trying to access the LiveJournal installation.", + 'example' => '$SITENAME is down right now while we upgrade. It should be up in a few minutes.', + }, + 'is_dev_server' => { + 'desc' => "Enable this option to signify that the server running the LiveJournal software is being used as a development server.", + }, + }, + + 'email_addresses' => { + 'name' => "Contact email addresses", + 'admin_email' => { + 'desc' => "Given as the administrative address for functions like changing passwords or information.", + }, + 'support_email' => { + 'desc' => "Used as a contact method for people to report problems with the LiveJournal installation.", + }, + 'bogus_email' => { + 'desc' => "Used for automated notices like comment replies and general support request messages. It should be encouraged not to reply to this address.", + }, + }, + + 'caps' => { + 'name' => "Capabilities/User Options", + 'newuser_caps' => { + 'desc' => "The default capability class mask for new users.", + }, + 'cap_def' => { + 'desc' => "The default capability limits, used only when no other class-specific limit below matches.", + 'type' => "hash", + }, + 'cap' => { + 'desc' => "A hash that defines the capability class limits. The keys are bit numbers, from 0 .. 15, and the values ". + "are hashrefs with limit names and values. Consult [special[cabalities]] for more information.", + 'type' => "hash", + }, + 'user_email' => { + 'desc' => "Do certain users get a forwarding email address, such as user\@\$DOMAIN?. This requires additional mail system configuration.", + }, + 'user_vhosts' => { + 'desc' => "If enabled, the LiveJournal installation will support username URLs of the form http://username.yoursite.com/", + }, + 'user_domain' => { + 'desc' => "If [ljconfig[user_vhosts]] is enabled, this will is the part of the URL that follows 'username'.", + 'example' => '$DOMAIN', + }, + 'email_post_domain' => { + 'desc' => "If set, and your MTA is configured, users can post to their account via username@\$EMAIL_POST_DOMAIN.", + 'example' => 'post.$DOMAIN', + }, + 'default_style' => { + 'desc' => "A hash that defines the default S2 layers to use for accounts.", + 'default' => "{ + 'core' => 'core1', + 'layout' => 'generator/layout', + 'i18n' => 'generator/en', + };", + }, + 'allow_pics_over_quota' => { + 'desc' => "By default, when a user's account expires, their least often used userpics will get marked ". + "as inactive and will not be available for use. Turning this boolean setting true will circumvent this behavior.", + }, + 'userprop_def' => { + 'desc' => "This option defines the userproperties that users should have by default.", + 'type' => "hash", + 'example' => '%USERPROP_DEF = ( + "s1_lastn_style" => 29, + "s1_friends_style" => 20, + "s1_calendar_style" => 2, + "s1_day_style" => 11, +);', + }, + }, + 'misc' => { + 'name' => "Miscellaneous settings", + 'helpurls' => { + 'desc' => "A hash of URLs. If defined, little help bubbles appear next to common widgets to the URL you define. ". + "Consult [special[helpurls]] for more information.", + 'example' => '%HELPURLS = ( + "accounttype" => "http://www.example.com/doc/faq/", + "security" => "http://www.example.com/doc/security", +);', + 'type' => "hash", + }, + 'use_acct_codes' => { + 'desc' => "A boolean setting that makes the LiveJournal installation require an invitation code before anyone can create an account.". + "Consult [special[invitecodes]] for more information.", + }, + 'disabled' => { + 'desc' => "Boolean hash, signifying that separate parts of this LiveJournal installation are working and are avaiable to use. ". + "Consult [special[disabled]] for more information.", + 'type' => "hash", + }, + 'protected_usernames' => { + 'desc' => "This is a list of regular expressions matching usernames that users on this LiveJournal installation can't create on their own.", + 'type' => "array", + 'example' => '("^ex_", "^lj_")', + }, + 'initial_friends' => { + 'desc' => "This is a list of usernames that will be added to the friends list of all newly created accounts on this installation.", + 'type' => "array", + 'example' => "qw(news)", + }, + 'testaccts' => { + 'desc' => "A list of usernames used for testing purposes. The password to these accounts cannot be changed through the user interface.", + 'type' => "array", + 'example' => "qw(test test2);", + }, + 'no_password_check' => { + 'desc' => "Set this option true if you are running an installation using ljcom code and if you haven't installed the Crypt::Cracklib perl module.", + }, + 'schemes' => { + 'desc' => "An array of hashes with keys being a BML scheme name and the values being the scheme description. When set, users can change their ". + "default BML scheme to the scheme of their choice.", + 'type' => "array", + 'example' => "( + { scheme => 'bluewhite', title => 'Blue White' }, + { scheme => 'lynx', title => 'Lynx' }, + { scheme => 'opalcat', title => 'Opalcat' }, +);", + }, + 'force_empty_friends' => { + 'desc' => "A hash of userids whose friends views should be disabled for performance reasons. This is useful if new accounts are auto-added to ". + "another account upon creation (described in [ljconfig[initial_friends]]), as in most situations building a friends view for those ". + "accounts would be superflous and taxing on your installation.", + 'type' => "hash", + 'example' => "( + 234 => 1, + 232252 => 1, +);", + }, + 'anti_squatter' => { + 'desc' => "Set true if your installation is a publically available development server and if you would like ". + "beta testers to ensure that they understand as such. If left alone your installation might become susceptible to ". + "hordes of squatter accounts.", + }, + 's2_trusted' => { + 'desc' => "Allows a specific user's S2 layers to run javascript, something that is considered a potential security risk and is disabled for all accounts. The hash structure is a series of userid => username pairs. Note that the system account is trusted by default, so it is not necessary to add to this hash.", + 'type' => "hash", + 'example' => "( '2' => 'whitaker', '3' => 'test', );", + }, + 'dynamic_ljuser' => { + 'desc' => "Boolean variable that defines whether the user-types of users is looked up when [func[LJ::ljuser]] is called. This is not recommended unless the site is using memcached.", + }, + 'hide_friendof_via_ban' => { + 'desc' => "Allows a user to hide usernames from appearing on their 'friend-of' list via use of the 'ban' mechanism.", + }, + }, + + 'portal' => { + 'name' => "Portal Configuration", + 'portal_cols' => { + 'desc' => 'This is a list that specifies which columns can be used for the portal pages.', + 'type' => 'array', + 'default' => 'qw(main right moz)', + }, + 'portal_uri' => { + 'desc' => "The URI to the portal. Only two options are supported at this time, '/portal/' and '/'.", + 'default' => "/portal/", + }, + 'portal_logged_in' => { + 'desc' => "The default positions for portal boxes that a user will see when they are logged in.", + 'default' => "{'main' => [ + [ 'update', 'mode=full'], + ], + 'right' => [ + [ 'stats', '', ], + [ 'bdays', '', ], + [ 'popfaq', '', ], + ] };", + }, + 'portal_logged_out' => { + 'desc' => "The default positions for portal boxes that a user will see when they are logged out.", + 'default' => "{'main' => [ + [ 'update', 'mode='], + ], + 'right' => [ + [ 'login', '', ], + [ 'stats', '', ], + [ 'randuser', '', ], + [ 'popfaq', '', ], + ], + 'moz' => [ + [ 'login', '', ], + ], +};", + }, + }, + 'blob' => { + 'name' => "Blob Server", + 'blobinfo' => { + 'desc' => "Hash that contains the details for a number of blob servers. The format of the paramater is 'cluster' => 'director'. The webserver user also needs to be able to the directory given as the directory. If you wish to use Captcha Image and Audio Generation for Human Checks, then this is a necessary paramater", + 'type' => "hash", + 'example' => '%BLOBINFO = ( + "clusters" => { + "1" => "/path/to/some/directory/", + }, +);' + }, + 'userpric_blobserver' => { + 'desc' => "If set to true, userpics are store as a file on the server rather than in the database. This depends on a Blob Server being setup in the [ljconfig[blobinfo]] section", + }, + }, + 'captcha' => { + 'name' => "Human Checks", + 'human_check' => { + 'desc' => 'This option enables human checks at various places throughout the site. Enabling this requires a "Blob Server" setup (for details of setting one up, refer to the [ljconfig[blobinfo]] section of the document.) Currently, the only option is "create"', + 'type' => "hash", + 'example' => "('create' => 1);", + }, + }, + }, + 'auto' => { + 'name' => 'Auto-Configured', + 'desc' => "These \$LJ:: settings are automatically set in ". + "ljdefaults.pl. They're only documented here for ". + "people interested in extending LiveJournal. Or, you can define them in ". + "ljconfig.pl ahead of time so you can use them in ". + "definitions of future variables. ", + + 'directories' => { + 'name' => "Configuration Directories", + 'home' => { + 'desc' => "Set to the same value as [special[ljhome]]", + 'default' => "\$ENV{'LJHOME'}", + }, + 'htdocs' => { + 'desc' => "Points to the htdocs directory under [special[ljhome]]", + 'default' => "\$HOME/htdocs", + }, + 'bin' => { + 'desc' => "Points to the under bin directory under [special[ljhome]]", + 'default' => "\$HOME/bin", + }, + 'temp' => { + 'desc' => "Points to the temp directory under [special[ljhome]]", + 'default' => "\$HOME/temp", + }, + 'var' => { + 'desc' => "Points to the var directory under [special[ljhome]]", + 'default' => "\$HOME/var", + }, + }, + + 'i18n' => { + 'name' => "Internationalization", + 'unicode' => { + 'desc' => "Boolean setting that allows UTF-8 support. This is enabled by default.", + }, + }, + }, +); + +for my $type ( keys %ljconfig ) +{ + print "
    \n"; + print " " . %ljconfig->{$type}->{'name'} . "\n"; + print " " . %ljconfig->{$type}->{'desc'} . "\n"; + for my $list ( sort keys %{%ljconfig->{$type}} ) { + next if ($list eq "name" || $list eq "desc"); + print " \n"; + print " " . %ljconfig->{$type}->{$list}->{'name'} . "\n"; + foreach my $var ( sort keys %{%ljconfig->{$type}->{$list}} ) { + next if $var eq "name"; + my $vartype = '$'; + if (%ljconfig->{$type}->{$list}->{$var}->{'type'} eq "hash") { $vartype = '%'; } + if (%ljconfig->{$type}->{$list}->{$var}->{'type'} eq "array") { $vartype = '@'; } + print " \n"; + print " " . $vartype . "LJ::" . uc($var) . "\n"; + my $des = %ljconfig->{$type}->{$list}->{$var}->{'desc'}; + $des =~ s/&(?!(?:[a-zA-Z0-9]+|#\d+);)/&/g; + xlinkify(\$des); + print " $des\n"; + if (%ljconfig->{$type}->{$list}->{$var}->{'example'}) + { + print " Example: "; + print ""; + print %ljconfig->{$type}->{$list}->{$var}->{'example'}; + print "\n"; + } + if (%ljconfig->{$type}->{$list}->{$var}->{'default'}) + { + print " Default: "; + print ""; + print %ljconfig->{$type}->{$list}->{$var}->{'default'}; + print "\n"; + } + print " \n"; + print " \n"; + } + print " \n"; + } + print "
    \n"; +} + +#hooks(); diff --git a/livejournal/doc/raw/build/ljdocs2html.xsl b/livejournal/doc/raw/build/ljdocs2html.xsl new file mode 100755 index 0000000..dc025fd --- /dev/null +++ b/livejournal/doc/raw/build/ljdocs2html.xsl @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + +2 + + + + + +1 + + + + + + + + + + + + + + + + + + » + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [o]» + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/build/nochunk.xsl b/livejournal/doc/raw/build/nochunk.xsl new file mode 100755 index 0000000..4d66697 --- /dev/null +++ b/livejournal/doc/raw/build/nochunk.xsl @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/livejournal/doc/raw/build/priv/priv2db.pl b/livejournal/doc/raw/build/priv/priv2db.pl new file mode 100755 index 0000000..c520e8d --- /dev/null +++ b/livejournal/doc/raw/build/priv/priv2db.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +# + +use strict; + +unless (-d $ENV{'LJHOME'}) { + die "\$LJHOME not set.\n"; +} + +require "$ENV{'LJHOME'}/doc/raw/build/docbooklib.pl"; +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbr = LJ::get_dbh("slave", "master"); +my $sth; + +sub dump_privs +{ + my $privs = shift; + + print "\n User Privileges\n"; + foreach my $priv (sort keys %$privs) + { + + my ($des, $args) = split(/arg=/, $privs->{$priv}->{'des'}); + my $scope = $privs->{$priv}->{'scope'}; + + print "\n"; + print "$priv"; + print " -- (scope: $scope)" if $scope eq "local"; + print "\n"; + + print "\n"; + print "$privs->{$priv}->{'name'}\n"; + cleanse(\$des); + print "$des\n"; + + print "Argument: $args\n" if $args; + print "\n"; + + print "\n"; + } + print "\n"; +} + +my %privs; + +$sth = $dbr->prepare("SELECT * FROM priv_list"); +$sth->execute; +while (my ($prlid, $privcode, $privname, $des, $is_public, $scope) = $sth->fetchrow_array) { + $privs{$privcode} = { 'public' => $is_public, 'name' => $privname, 'des' => $des, 'scope' => $scope}; +} + +dump_privs(\%privs); diff --git a/livejournal/doc/raw/build/protocol/authinfo.ent.xml b/livejournal/doc/raw/build/protocol/authinfo.ent.xml new file mode 100755 index 0000000..410d936 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/authinfo.ent.xml @@ -0,0 +1,36 @@ + + + Username of user logging in. + + + + + Authentication method used for this request. The default value is "clear", for plain-text authentication. "cookie" and any of the challenge / response methods are also acceptable. + + + + + DEPRECATED. Password of user logging in in plaintext. If using the "clear" authentication method, either this or "hpassword" must be present. + + + + + DEPRECATED. MD5 digest of user's password. Not much more secure than password, but at least it's not in plain text. + + + + + If using challenge / response authentication, this should be the challenge that was issued to you by the server. + + + + + If using challenge / response authentication, this should be the response hash that you generate, based on the formula required for your challenge. + + + + + Protocol version supported by the client; assumed to be 0 if not specified. See for details on the protocol version + + + diff --git a/livejournal/doc/raw/build/protocol/checkfriends.mode.xml b/livejournal/doc/raw/build/protocol/checkfriends.mode.xml new file mode 100755 index 0000000..ed1dd4d --- /dev/null +++ b/livejournal/doc/raw/build/protocol/checkfriends.mode.xml @@ -0,0 +1,109 @@ + + +Checks to see if your friends list has been updated since a specified time. + + +Mode that clients can use to poll the server to see if their friends list has been updated. This request is extremely quick, and is the preferred way for users to see when their friends list is updated, rather than pounding on reload in their browser, which is stressful on the serves. + + + +&authInfo; + + +The time that this mode request returned last time you called it. If this is the first time you've ever called it (since your client has been running), leave this blank. It's strongly recommended that you do not remember this value across invocations of your client, as it's very likely your friends will update since the client was running so the notification is pointless... the user probably read his/her friends page already before starting the client. + + + +The friend group(s) in which the client is checking for new entries, represented as a 32-bit unsigned int. Turn on any combination of bits 1-30 to check for entries by friends in the respective friend groups. Turn on bit 0, or leave the mask off entirely, to check for entries by any friends. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 481 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.checkfriends</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>lastupdate</name> +<value><string></string></value> +</member> +</struct></value> + +</param> +</params> +</methodCall> + + + + + + +This is what you should use to determine if there are new entries. Its value is "1" if there is new stuff, or "0" if there isn't. Note that once this values becomes "1" and you alert the user, stop polling! It'd be pointless to have the client hitting the server all night while the user slept. Once the user acknowleges the notifcation (double-clicks the system tray or panel applet or whatnot), then resume your polling. + + + +How many seconds you must wait before polling the server again. If your client disobeys, this protocol will just return error messages saying "slow down, bad client!" instead of giving you the data you were trying to cheat to obtain. Note that this also means your client should have an option to disable polling for updates, since some users run multiple operating systems with multiple LiveJournal clients, and both would be fighting each other. + + + +The number of items that are contained in this response (numbered started at 1). If sync_count is equal to sync_total, then you can stop your sync after you complete fetching every item in this response. + + + +The total number of items that have been updated since the time specified. + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 358 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 22:49:07 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> + +<value><struct> +<member><name>lastupdate</name> +<value><string>2002-07-16 14:22:16</string></value> +</member> +<member><name>new</name> + +<value><int>0</int></value> +</member> +<member><name>interval</name> +<value><int>90</int></value> + +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/consolecommand.mode.xml b/livejournal/doc/raw/build/protocol/consolecommand.mode.xml new file mode 100755 index 0000000..694f85c --- /dev/null +++ b/livejournal/doc/raw/build/protocol/consolecommand.mode.xml @@ -0,0 +1,176 @@ + + +Run an administrative command. + + +The LiveJournal server has a text-based shell-like admininistration +console where less-often used commands can be entered. There's a web +interface to this shell online, and this is another gateway to that. + + + +&authInfo; + + + +The commands to send, with double quotes around any arguments with spaces, +and double quotes escaped by backslashes, and backslashes escaped with +backslashes. Optionally, you can send a listref instead of a string +for this argument, in which case, we'll use your argument separation +and not parse it ourselves. + + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 542 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.consolecommand</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>commands</name> +<value><array> +<data> +<value><string>help print</string></value> + +</data> +</array></value> +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + + + One stuct returned for each command run, + that struct containing both the overall return value, + and the line-by-line output of the command, with + each line of output being tagged by type (think + stdout vs. stderr, but with stdinfo also). The web interface + shows 'error' with red, '' (stdout) with black, and 'info' + with green. Clients are encouraged to also, if possible. + + + + + Return status of nth command. 0 or 1. + + + + + + Type of output line. Either "" (normal output), "error", or "info", + something to be emphasized over normal output. + + + The text of that line. + + + + + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 1189 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 22:59:33 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> +<member><name>results</name> + +<value><array> +<data> +<value><struct> +<member><name>success</name> +<value><int>1</int></value> + +</member> +<member><name>output</name> +<value><array> +<data> +<value><array> +<data> + +<value><string></string></value> +<value><string>print ...</string></value> +</data> +</array></value> +<value><array> + +<data> +<value><string></string></value> +<value><string> This is a debugging function. Given an arbitrary number of</string></value> +</data> +</array></value> + +<value><array> +<data> +<value><string></string></value> +<value><string> meaningless arguments, it'll print each one back to you. If an</string></value> + +</data> +</array></value> +<value><array> +<data> +<value><string></string></value> +<value><string> argument begins with a bang (!) then it'll be printed to the error</string></value> + +</data> +</array></value> +<value><array> +<data> +<value><string></string></value> +<value><string> stream instead.</string></value> + +</data> +</array></value> +</data> +</array></value> +</member> +</struct></value> +</data> + +</array></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/editevent.mode.xml b/livejournal/doc/raw/build/protocol/editevent.mode.xml new file mode 100755 index 0000000..e430c17 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/editevent.mode.xml @@ -0,0 +1,184 @@ + + +Edit or delete a user's past journal entry + + +Modify an already created event. If fields are empty, it will delete the event. + + + +&authInfo; + + +The unique ItemID of the item being modified or deleted. + + + +The revised event/log text the user is submitting. Or, to delete an entry, just send no text at all. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac ( +0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-form +atted text, and it does the conversion by removing all \r characters. If you're sending a + multi-line event on Mac, you have to be sure and send a lineendings value of mac or you +r line endings will be removed. PC and Unix clients can ignore this setting, or you can s +end it. It may be used for something more in the future. + + + +The subject for this post. Limited to 255 characters. No newlines. + + + +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. + + + +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. + + + + + Set arbitrary (but restricted) meta-data properties to this log item. See + for the documentation of the keys and value data types. + + + The following 'struct' should have property names as the keys, and the values should be a scalar data type. + + + + + +If editing a shared journal entry, include this key and the username you wish to edit the entry in. By default, you edit the entry as if it were in user "user"'s journal, as specified above. + + + +If modifying only, the 4-digit year of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit month of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit day of the month of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit hour from 0 to 23 of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit minute of the event (from the user's local timezone). + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 1032 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.editevent</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>itemid</name> +<value><int>1959</int></value> + +</member> +<member><name>event</name> +<value><string>This &lt;strike&gt;is&lt;/strike&gt; was a test post. +</string></value> + +</member> +<member><name>subject</name> +<value><string>Test</string></value> +</member> +<member><name>lineendings</name> + +<value><string>pc</string></value> +</member> +<member><name>year</name> +<value><int>2002</int></value> + +</member> +<member><name>mon</name> +<value><int>7</int></value> +</member> +<member><name>day</name> + +<value><int>13</int></value> +</member> +<member><name>hour</name> +<value><int>20</int></value> + +</member> +<member><name>min</name> +<value><int>35</int></value> +</member> +</struct></value> + +</param> +</params> +</methodCall> + + + + + + +The unique ItemID of the item being modified or deleted. + + + +The authentication number generated for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) + + + +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 267 +Content-Type: text/xml +Date: Sat, 13 Jul 2002 23:57:17 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> + +<value><struct> +<member><name>anum</name> +<value><int>141</int></value> +</member> +<member><name>itemid</name> + +<value><int>1959</int></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/editfriendgroups.mode.xml b/livejournal/doc/raw/build/protocol/editfriendgroups.mode.xml new file mode 100755 index 0000000..eac7f18 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/editfriendgroups.mode.xml @@ -0,0 +1,119 @@ + + +Edit the user's defined groups of friends. + + +Given several optional lists, will add/delete/update/rename the friends groups for a user. + + + +&authInfo; + + + +A structure of friend userids. The values of each are a string representing an unsigned 32-bit integer with bit 0 set (or the server will force it on anyway), bits 1-30 set for each group the friend belongs to, and bit 31 unset (reserved for future use). + + + + + +Given the bit of a friend group, the value contains a structure of information on it. + + + + Create or rename the friend group by sending this key. The value is the name of the group. + + + This field should be sent to indicate the sorting order of this group. The value must be in the range of 0-255. The default is 50. + + + If this is "1", then this group is marked as public. If public, other users can see the name of the group and the people that are in it. + + + + + +A number of a friend group to delete (which can be from 1-30, inclusive). The server will modify all old entries that allow access to that friend group, so a new friend group using that number won't have access to old non-related entries, and unset the bit for that friend group on the groupmask of each friend, unless your client sends the friend's new groupmask explicitly. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 780 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.editfriendgroups</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>set</name> +<value><struct> +<member><name>1</name> +<value><struct> + +<member><name>name</name> +<value><string>Good Friends</string></value> +</member> +<member><name>sort</name> + +<value><int>25</int></value> +</member> +<member><name>public</name> +<value><boolean>1</boolean></value> + +</member> +</struct></value> +</member> +</struct></value> +</member> +</struct></value> +</param> + +</params> +</methodCall> + + + + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 132 +Content-Type: text/xml +Date: Mon, 15 Jul 2002 23:16:33 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> + +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/editfriends.mode.xml b/livejournal/doc/raw/build/protocol/editfriends.mode.xml new file mode 100755 index 0000000..8f09aa9 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/editfriends.mode.xml @@ -0,0 +1,147 @@ + + +Add, edit, or delete friends from the user's friends list. + + +Takes up to two lists, one of friends to delete and one of friends to add. Several options are allowed to be specified when adding a friend. It returns a verbose list of the friends added, if any were. + + + +&authInfo; + + + +A list of variable of this form removes the friend users from the user's friend list. It is not an error to delete an already non-existant friend. The value should just be 1. + + +A username of a friend to remove. + + + + + +To add friends, send a variable list of this form. + + + + A username of a friend to remove. + + + Sets the text color of the friend being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #000000, black. + + + Sets the background color of the friend being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #FFFFFF, white. + + + Sets this user's groupmask. Only use this in clients if you've very recently loaded the friend groups. If your client has been loaded on the end user's desktop for days and you haven't loaded friend groups since it started, they may be inaccurate if they've modified their friend groups through the website or another client. In general, don't use this key unless you know what you're doing. + + + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 774 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.editfriends</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>add</name> +<value><array> +<data> +<value><struct> +<member><name>username</name> + +<value><string>bradfitz</string></value> +</member> +<member><name>fgcolor</name> +<value><string>#000000</string></value> + +</member> +<member><name>bgcolor</name> +<value><string>#ffffff</string></value> +</member> +</struct></value> + +</data> +</array></value> +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + +A list of the users who have been added with this transaction. + + + + The username of the friend that was added. + + + The full name of the friend that was added. + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 420 +Content-Type: text/xml +Date: Mon, 15 Jul 2002 23:52:18 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> +<member><name>added</name> + +<value><array> +<data> +<value><struct> +<member><name>username</name> +<value><string>bradfitz</string></value> + +</member> +<member><name>fullname</name> +<value><string>Brad Fitzpatrick</string></value> +</member> +</struct></value> + +</data> +</array></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/flat2db.pl b/livejournal/doc/raw/build/protocol/flat2db.pl new file mode 100755 index 0000000..de70562 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/flat2db.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# + + use strict; + + unless (-d $ENV{'LJHOME'}) { die "\$LJHOME not set.\n"; } + + require "$ENV{'LJHOME'}/doc/raw/build/docbooklib.pl"; + require "$ENV{'LJHOME'}/cgi-bin/propparse.pl"; + + my @vars; + LJ::load_objects_from_file("$ENV{'LJHOME'}/htdocs/protocol.dat", \@vars); + + foreach my $mode (sort { $a->{'name'} cmp $b->{'name'} } @vars) + { + my $name = $mode->{'name'}; + my $des = $mode->{'props'}->{'des'}; + cleanse(\$des); + + unshift (@{$mode->{'props'}->{'request'}}, + { 'name' => "mode", 'props' => { 'des' => "The protocol request mode: $name", } }, + { 'name' => "user", 'props' => { 'des' => "Username. Leading and trailing whitespace is ignored, as is case.", } }, + { 'name' => "auth_method", 'props' => { 'des' => "The authentication method used for this request. Default is 'clear', for plain-text authentication. 'cookie' or any of the challenge / response methods are also acceptable.", } }, + { 'name' => "password", 'props' => { 'des' => "DEPRECATED. Password in plain-text. For the default authentication method, either this needs to be sent, or hpassword.", } }, + { 'name' => "hpassword", 'props' => { 'des' => "DEPRECATED. Alternative to plain-text password. Password as an MD5 hex digest. Not perfectly secure, but defeats the most simple of network sniffers.", } }, + { 'name' => "auth_challenge", 'props' => { 'des' => "If using challenge / response authentication, this should be the challenge that was generated for your client.", } }, + { 'name' => "auth_response", 'props' => { 'des' => "If using challenge / response authentication, this should be the response hash you generate based on the challenge's formula.", } }, + { 'name' => "ver", 'props' => { 'des' => "Protocol version supported by the client; assumed to be 0 if not specified. See [special[cspversion]] for details on the protocol version.", 'optional' => 1, } }, + ) unless $name eq "getchallenge"; + unshift (@{$mode->{'props'}->{'response'}}, + { 'name' => "success", 'props' => { 'des' => "OK on success or FAIL when there's an error. When there's an error, see errmsg for the error text. The absence of this variable should also be considered an error.", } }, + { 'name' => "errmsg", 'props' => { 'des' => "The error message if success was FAIL, not present if OK. If the success variable isn't present, this variable most likely won't be either (in the case of a server error), and clients should just report \"Server Error, try again later.\".", } }, + ); + print "\n"; + print " \n $name\n"; + print " $des\n \n"; + + print " \n Mode Description\n"; + print " $des\n \n"; + foreach my $rr (qw(request response)) + { + print "\n"; + my $title = $rr eq "request" ? "Arguments" : "Return Values"; + print " $title\n"; + print " \n"; + foreach (@{$mode->{'props'}->{$rr}}) + { + print " \n"; + cleanse(\$_->{'name'}); + print " $_->{'name'}\n"; + print " \n"; + if ($_->{'props'}->{'optional'}) { + print "(Optional)\n"; + } + cleanse(\$_->{'props'}->{'des'}); + print "$_->{'props'}->{'des'}\n"; + print " \n"; + print " \n"; + } + print " \n"; + print "\n"; + } + print "\n"; + } diff --git a/livejournal/doc/raw/build/protocol/friendgroups.ent.xml b/livejournal/doc/raw/build/protocol/friendgroups.ent.xml new file mode 100755 index 0000000..46b9ea3 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/friendgroups.ent.xml @@ -0,0 +1,21 @@ + + + + +The bit number for this friend group, from 1-30. + + + +The name of this friend group. + + + +The sort integer for this friend group, from 0-255. + + + +Either '0' or '1' for if this friend group is public. + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/build/protocol/friendof.mode.xml b/livejournal/doc/raw/build/protocol/friendof.mode.xml new file mode 100755 index 0000000..e4229fb --- /dev/null +++ b/livejournal/doc/raw/build/protocol/friendof.mode.xml @@ -0,0 +1,122 @@ + + +Returns a list of which other LiveJournal users list this user as their friend. + + +Returns a "friends of" list for a specified user. An optional limit of returned friends can be supplied. + + + +&authInfo; + + +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 475 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.friendof</methodName> +<params> +<param> +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> +</member> +<member><name>friendoflimit</name> +<value><int>2</int></value> +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + + +The list of people who list this user as a friend. + +&friendsList; + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 936 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 00:53:15 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> + +<value><struct> +<member><name>friendofs</name> +<value><array> +<data> +<value><struct> +<member><name>fgcolor</name> + +<value><string>#000000</string></value> +</member> +<member><name>username</name> +<value><string>aisha_plushie</string></value> + +</member> +<member><name>fullname</name> +<value><string>Stripe</string></value> +</member> +<member><name>bgcolor</name> + +<value><string>#ffffff</string></value> +</member> +</struct></value> +<value><struct> +<member><name>fgcolor</name> + +<value><string>#000000</string></value> +</member> +<member><name>username</name> +<value><string>badcharlotte</string></value> + +</member> +<member><name>fullname</name> +<value><string>Charlotte</string></value> +</member> +<member><name>bgcolor</name> + +<value><string>#ffffff</string></value> +</member> +</struct></value> +</data> +</array></value> +</member> + +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/friendslist.ent.xml b/livejournal/doc/raw/build/protocol/friendslist.ent.xml new file mode 100755 index 0000000..20f32ac --- /dev/null +++ b/livejournal/doc/raw/build/protocol/friendslist.ent.xml @@ -0,0 +1,29 @@ + + + + +The username of the friend. + + + +The full name of the friend. + + + +The type of journal the friend item is. This value can be one of 'community', 'syndicated', 'news', or 'shared', depending on the journaltype of the account in question. The account is a normal personal account when this value is not sent. + + + +The foreground color of the friend item. + + + +The background color of the friend item. + + + +If the group mask is not "1" (just bit 0 set), then this variable is returned with an 32-bit unsigned integer with a bit 0 always set, and bits 1-30 set for each group this friend is a part of. Bit 31 is reserved. + + + + diff --git a/livejournal/doc/raw/build/protocol/getchallenge.mode.xml b/livejournal/doc/raw/build/protocol/getchallenge.mode.xml new file mode 100755 index 0000000..bf94144 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/getchallenge.mode.xml @@ -0,0 +1,81 @@ + + +Generate a server challenge string for authentication. + + +Generate a one-time, quick expiration challenge to be used in challenge/response authentication methods. + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 97 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.getchallenge</methodName> +</methodCall> + + + + + + +You can ignore this for now. By default this is the highest version of our +authentication schemes, if in the future if we implement other auth schemes or change the default. +In that case we'd add a new capabilities exchange: your client could say, "I know c0 and c1", and +our server would then say, "Use c1, it's the best." + + + +An opaque cookie to generate a hashed response from. + + + +The expiration time of the challenge, as measured in seconds since the Unix epoch. + + + +The server time when the challenge was generated, as measured in seconds since the Unix epoch. + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 557 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 00:30:01 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> +<member><name>auth_scheme</name> +<value><string>c0</string></value> + +</member> +<member><name>challenge</name> +<value><string>c0:1073113200:2831:60:2TCbFBYR72f2jhVDuowz:0fba728f5964ea54160a5b18317d92df</string></value> + +</member> +<member><name>expire_time</name> +<value><int>1073116091</int></value> + +</member> +<member><name>server_time</name> +<value><int>1073116031</int></value> + +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/getdaycounts.mode.xml b/livejournal/doc/raw/build/protocol/getdaycounts.mode.xml new file mode 100755 index 0000000..303e65d --- /dev/null +++ b/livejournal/doc/raw/build/protocol/getdaycounts.mode.xml @@ -0,0 +1,143 @@ + + +This mode retrieves the number of journal entries per day. + + +This mode retrieves the number of journal entries per day. Useful for populating calendar widgets in GUI clients. Optionally a journal can be specified. It returns a list of the dates and accompanied counts. + + + +&authInfo; + + + +If getting the day counts of a shared journal, include this key and the username you wish to get the counts of. By default, you load the counts of "user" as specified above. + +&useJournal; + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 403 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.getdaycounts</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + +For each day that the user has posted a journal entry, a struct is returned in the list. + +The date, in yyyy-dd-mm format. +The number of journal entries on that date. + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 70580 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 20:50:28 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> + +<methodResponse> +<params> +<param> +<value><struct> +<member><name>daycounts</name> +<value><array> + +<data> +<value><struct> +<member><name>count</name> +<value><int>1</int></value> +</member> + +<member><name>date</name> +<value><string>1995-05-01</string></value> +</member> +</struct></value> +<value><struct> + +<member><name>count</name> +<value><int>1</int></value> +</member> +<member><name>date</name> + +<value><string>1997-05-01</string></value> +</member> +</struct></value> +<value><struct> +<member><name>count</name> + +<value><int>1</int></value> +</member> +<member><name>date</name> +<value><string>1999-05-03</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>count</name> +<value><int>17</int></value> + +</member> +<member><name>date</name> +<value><string>1999-05-04</string></value> +</member> +</struct></value> + +... + +<value><struct> +<member><name>count</name> +<value><int>1</int></value> +</member> +<member><name>date</name> + +<value><string>2020-02-20</string></value> +</member> +</struct></value> +</data> +</array></value> +</member> + +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/getevents.mode.xml b/livejournal/doc/raw/build/protocol/getevents.mode.xml new file mode 100755 index 0000000..bcc1d9d --- /dev/null +++ b/livejournal/doc/raw/build/protocol/getevents.mode.xml @@ -0,0 +1,235 @@ + + +Download parts of the user's journal. + + +Given a set of specifications, will return a segment of entries up to a limit set by the server. Has a set of options for less, extra, or special data to be returned. + + + +&authInfo; + + +A value that if greater than or equal to 4, truncates the length of the returned events (after being decoded) to the value specified. Entries less than or equal to this length are left untouched. Values greater than this length are truncated to the specified length minus 3, and then have "... " appended to them, bringing the total length back up to what you specified. This is good for populating list boxes where only the beginning of the entry is important, and you'll double-click it to bring up the full entry. + + + +If this setting is set to true (1 ), then no subjects are returned, and the events are actually subjects if they exist, or if not, then they're the real events. This is useful when clients display history and need to give the user something to double-click. The subject is shorter and often more informative, so it'd be best to download only this. + + + +If this setting is set to true (1), then no meta-data properties are returned. + + + +Determines how you want to specify what part of the journal to download. Valid values are day to download one entire day, lastn to get the most recent n entries (where n is specified in the howmany field), one to download just one specific entry, or syncitems to get some number of items (which the server decides) that have changed since a given time (specified in the lastsync parameter>). Not that because the server decides what items to send, you may or may not be getting everything that's changed. You should use the syncitems selecttype in conjuntions with the syncitems protocol mode. + + + +For a selecttype of syncitems, the date (in "yyyy-mm-dd hh:mm:ss" format) that you want to get updates since. + + + +For a selecttype of day, the 4-digit year of events you want to retrieve. + + + +For a selecttype of day, the 1- or 2-digit month of events you want to retrieve. + + + +For a selecttype of day, the 1- or 2-digit day of the month of events you want to retrieve. + + + +For a selecttype of lastn, how many entries to get. Defaults to 20. Maximum is 50. + + + +For a selecttype of lastn, you can optionally include this variable and restrict all entries returned to be before the date you specify, which must be of the form yyyy-mm-dd hh:mm:ss. + + + +For a selecttype of one, the journal entry's unique ItemID for which you want to retrieve. Or, to retrieve the most recent entry, use the value -1. Using -1 has the added effect that the data is retrieved from the master database instead of a replicated slave. Clients with an "Edit last entry" feature might want to send -1, to make sure the data that comes back up is accurate, in case a slave database is a few seconds behind in replication. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. + + + + +If getting the history of a shared journal, include this key and the username you wish to get the history of. By default, you load the history of "user" as specified above. + +&useJournal; + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 786 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.getevents</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>truncate</name> +<value><int>20</int></value> +</member> +<member><name>selecttype</name> + +<value><string>lastn</string></value> +</member> +<member><name>howmany</name> +<value><int>2</int></value> + +</member> +<member><name>noprops</name> +<value><boolean>1</boolean></value> +</member> +<member><name>lineendings</name> + +<value><string>unix</string></value> +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + +A list of structs for all of the returned events. + + + + +The unique integer ItemID of the item being returned. + + + +The time the user posted (or said they posted, rather, since users can back-date posts) the item being returned. + + + +If this variable is not returned, then the security of the post is public, otherwise this value will be private or usemask. + + + +If security is usemask then this is defined with the 32-bit unsigned int bit-mask of who is allowed to access this post. + + + +The subject of the journal entry. This won't be returned if "prefersubjects" is set, instead the subjects will show up as the events. + + + +The event text itself. This value is first truncated if the truncate variable is set, and then it is URL-encoded (alphanumerics stay the same, weird symbols to %hh, and spaces to + signs, just like URLs or post request). This allows posts with line breaks to come back on one line. + + + +The authentication number generated for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) + + + +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. + + + +If the poster of this event is different from the user value sent above, then this key will be included and will specify the username of the poster of this event. If this key is not present, then it is safe to assume that the poster of this event is none other than user. + + + +Properties and their values for the item being returned. + + + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 1002 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 00:30:01 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> +<member><name>events</name> + +<value><array> +<data> +<value><struct> +<member><name>eventtime</name> +<value><string>2020-02-20 02:20:00</string></value> + +</member> +<member><name>event</name> +<value><string>yes its true its ...</string></value> +</member> +<member><name>anum</name> + +<value><int>108</int></value> +</member> +<member><name>itemid</name> +<value><int>1965</int></value> + +</member> +</struct></value> +<value><struct> +<member><name>eventtime</name> +<value><string>2002-07-14 11:17:00</string></value> + +</member> +<member><name>event</name> +<value><string>Yes, Yes, YES!</string></value> +</member> +<member><name>anum</name> + +<value><int>66</int></value> +</member> +<member><name>subject</name> +<value><string>Is this private?</string></value> + +</member> +<member><name>itemid</name> +<value><int>1964</int></value> +</member> +</struct></value> + +</data> +</array></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/getfriendgroups.mode.xml b/livejournal/doc/raw/build/protocol/getfriendgroups.mode.xml new file mode 100755 index 0000000..b4b61cc --- /dev/null +++ b/livejournal/doc/raw/build/protocol/getfriendgroups.mode.xml @@ -0,0 +1,100 @@ + + +Retrieves a list of the user's defined groups of friends. + + +Retrieves a list of the user's defined groups of friends. + + + +&authInfo; + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 406 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.getfriendgroups</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + + +&friendGroups; + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 536 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 01:03:10 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> + +<methodResponse> +<params> +<param> +<value><struct> +<member><name>friendgroups</name> +<value><array> + +<data> +<value><struct> +<member><name>sortorder</name> +<value><int>25</int></value> +</member> + +<member><name>id</name> +<value><int>1</int></value> +</member> +<member><name>public</name> + +<value><int>1</int></value> +</member> +<member><name>name</name> +<value><string>Good Friends</string></value> + +</member> +</struct></value> +</data> +</array></value> +</member> +</struct></value> +</param> + +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/getfriends.mode.xml b/livejournal/doc/raw/build/protocol/getfriends.mode.xml new file mode 100755 index 0000000..32e572c --- /dev/null +++ b/livejournal/doc/raw/build/protocol/getfriends.mode.xml @@ -0,0 +1,156 @@ + + +Returns a list of which other LiveJournal users this user lists as their friend. + + +Returns a verbose list of information on friends a user has listed. Optionally able to include their friends of list, the friends group associated with each user, and a limit on the number of friends to return. + + + +&authInfo; + + +If set to 1, you will also get back the info from the "friendof" mode. Some clients show friends and friendof data in separate tabs/panes. If you're always going to load both, then use this flag (as opposed to a tabbed dialog approach, where the user may not go to the second tab and thus would not need to load the friendof data.) friendof request variables can be used. + + + +If set to 1, you will also get back the info from the "getfriendgroups" mode. See above for the reason why this would be useful. + + + +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 401 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.getfriends</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + +&friendGroups; + + + +&friendsList; + + + +&friendsList; + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 1377 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 00:44:23 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> + +<methodResponse> +<params> +<param> +<value><struct> +<member><name>friends</name> +<value><array> + +<data> +<value><struct> +<member><name>fgcolor</name> +<value><string>#000000</string></value> +</member> + +<member><name>username</name> +<value><string>bradfitz</string></value> +</member> +<member><name>fullname</name> + +<value><string>Brad Fitzpatrick</string></value> +</member> +<member><name>bgcolor</name> +<value><string>#ffffff</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>fgcolor</name> +<value><string>#efcfff</string></value> + +</member> +<member><name>username</name> +<value><string>ljfresno</string></value> +</member> +<member><name>fullname</name> + +<value><string>Fresno LJ users</string></value> +</member> +<member><name>type</name> +<value><string>community</string></value> + +</member> +<member><name>bgcolor</name> +<value><string>#000000</string></value> +</member> +</struct></value> + +<value><struct> +<member><name>fgcolor</name> +<value><string>#520155</string></value> +</member> +<member><name>username</name> + +<value><string>webkin</string></value> +</member> +<member><name>fullname</name> +<value><string>Ellen Stafford</string></value> + +</member> +<member><name>bgcolor</name> +<value><string>#fcddff</string></value> +</member> +</struct></value> + +</data> +</array></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/login.mode.xml b/livejournal/doc/raw/build/protocol/login.mode.xml new file mode 100755 index 0000000..a7feafb --- /dev/null +++ b/livejournal/doc/raw/build/protocol/login.mode.xml @@ -0,0 +1,198 @@ + + +validate user's password and get base information needed for client to function + + +Login to the server, while announcing your client version. The server returns with whether the password is good or not, the user's name, an optional message to be displayed to the user, the list of the user's friend groups, and other things. + + + +&authInfo; + + +Although optional, this should be a string of the form Platform-ProductName/ClientVersionMajor.Minor.Rev, like Win32-MFC/1.2.7 or Gtk-LoserJabber/1.0.4. Note in this case that "Gtk" is not a platform, but rather a toolkit, since the toolkit is multi-platform (Linux, FreeBSD, Solaris, Windows...). You make the judge what is best to send, but if it's of this form, we'll give you cool statistics about your users. + + + +If your client supports moods, send this key with a value of the highest mood ID you have cached/stored on the user's computer. For example, if you logged in last time with and got mood IDs 1, 2, 4, and 5, then send "5" as the value of "getmoods". The server will return every new mood that has an internal MoodID greater than 5. If you've never downloaded moods before, send "0". If you don't care about getting any moods at all (if your client doesn't support them), then don't send this key at all. + + + +Send something for this key if you want to get a list/tree of web jump menus to show in your client. + + + +If your client supports picture keywords and you want to receive that list, send something for this key, like "1", and you'll receieve the list of picture keywords the user has defined. + + + +If your client supports picture keywords and can also display the pictures somehow, send something for this key, like "1", and you'll receieve the list of picture keyword URLs that correspond to the picture keywords as well as the URL for the default picture. You must send getpickws for this option to even matter. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 396 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.login</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +</struct></value> +</param> +</params> +</methodCall> + + + + + + +The user's full name. Often, clients use this to change the top-level window's title bar text to say something like "LiveJournal - User name". You can just ignore this if you'd like. + + + +A message that should be displayed in a dialog box (or to the screen in a console application). The message is rarely present but when used notifies the user of software updates they've requested to hear about, problems with their account (if mail is bouncing to them, we'd like them to give us a current email address), etc. To test this if you're developing a client, use the user account test with the password test and a message will always be returned. + + + +&friendGroups; + + + +&useJournals; + + + + + If you sent the 'getmoods' key in your request, this is returned. The contents are the new moods that have been added on the server since you last requested the list. Your client should cache the mood list on the client's computer to avoid requesting the whole list everytime. + + &moods; + + + + +This is requrned if you set "getpickws" in your request. Picture keywords are used to identify which userpic (100x100 icon) to use for that particular post. For instance, the user may have "Angry", "Happy", and "Sleepy" picture keywords which map to certain pictures. The client should also do a case-insensitive compare on this list when a mood is selected or entered, and auto-select the current picture keyword. That way it seems that selecting a mood also sets their corresponding picture. + + +The picture keyword. + + + + + +The URLs of the user pictures. They correspond with the list of +picture keywords returned. Note that the content behind these URLs +can never change, so if your client downloads these to display, just +cache them locally and never hit the servers again to re-download them +or to even check if they've been modified. + + +The picture URL. + + + + +The URL of the default picture (if you sent the 'getpickwurls' key). Note that the content behind this URL can never change, so you can cache it locally; also note that the default picture might have no keyword associated with it. + + + +LiveJournal sites may have priority servers for paying customers. If this key is both present and set to value "1", then the client has permission to set the "ljfastserver" cookie in subsequent requests. The HTTP request header to send is "Cookie: ljfastserver=1". If you send this header without getting permission from the login mode, your requests will fail. That is, you'll trick the load balancer into directing your request towards the priority servers, but the server you end up hitting won't be happy that you're trying to scam faster access and will deny your request. + + + +The userid of this user on the system. Not required for any other requests to +the server, but some developers have wanted it. + + + +Returned if you set "getmenus" in your request. + +List of menu items in order that should be in the LiveJournal web menu in the client application. + + + The text of the menu item, or "-" for a separator. + + + The URL the menu item should launch, present for all menu items + except separators and submenus. + + + If this is present, this menu item is a submenu. + + Same format as top-level menu structure + + + + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 755 +Content-Type: text/xml +Date: Sun, 14 Jul 2002 23:45:59 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> +<value><struct> +<member><name>userid</name> +<value><int>3</int></value> + +</member> +<member><name>message</name> +<value><string>You need to validate your new email address. +Your old one was good, but since you've changed it, you need to re-validate the new one. +Visit the support area for more information.</string></value> +</member> +<member><name>fullname</name> + +<value><string>Test Account</string></value> +</member> +<member><name>friendgroups</name> +<value><array> +<data> + +</data> +</array></value> +</member> +<member><name>usejournals</name> +<value><array> +<data> + +<value><string>test2</string></value> +</data> +</array></value> +</member> +</struct></value> +</param> + +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/moods.ent.xml b/livejournal/doc/raw/build/protocol/moods.ent.xml new file mode 100755 index 0000000..47f5bd6 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/moods.ent.xml @@ -0,0 +1,15 @@ + + + + + The integer moodid. + + + The mood name. + + + The mood's parent (base) moodid. + + + + diff --git a/livejournal/doc/raw/build/protocol/postevent.mode.xml b/livejournal/doc/raw/build/protocol/postevent.mode.xml new file mode 100755 index 0000000..2c18462 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/postevent.mode.xml @@ -0,0 +1,178 @@ + + +The most important mode, this is how a user actually submits a new log entry to the server. + + +Given all of the require information on a post, optioanlly adding security or meta data, will create a new entry. Will return the itemid of the new post. + + + +&authInfo; + + +The event/log text the user is submitting. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. + + + +The subject for this post. Limited to 255 characters. No newlines. + + + +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. + + + +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. + + + +The current 4-digit year (from the user's local timezone). + + + +The current 1- or 2-digit month (from the user's local timezone). + + + +The current 1- or 2-digit day of the month (from the user's local timezone). + + + +The current 1- or 2-digit hour from 0 to 23 (from the user's local timezone). + + + +The current 1- or 2-digit minute (from the user's local timezone). + + + + + Set arbitrary (but restricted) meta-data properties to this log item. See + for the documentation of the keys and value data types. + + + The following 'struct' should have property names as the keys, and the values should be a scalar data type. + + + + + + +If posting to a shared journal, include this key and the username you wish to post to. By default, you post to the journal of "user" as specified above. + +&useJournal; + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 927 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.postevent</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>event</name> +<value><string>This is a test post. +</string></value> + +</member> +<member><name>subject</name> +<value><string>Test</string></value> +</member> +<member><name>lineendings</name> + +<value><string>pc</string></value> +</member> +<member><name>year</name> +<value><int>2002</int></value> + +</member> +<member><name>mon</name> +<value><int>7</int></value> +</member> +<member><name>day</name> + +<value><int>13</int></value> +</member> +<member><name>hour</name> +<value><int>20</int></value> + +</member> +<member><name>min</name> +<value><int>35</int></value> +</member> +</struct></value> + +</param> +</params> +</methodCall> + + + + + + +The key number used to calculate the public itemid ID number for URLs. + + + +The unique number the server assigned to this post. Currently nothing else in the protocol requires the use of this number so it's pretty much useless, but somebody requested it be returned, so it is. + + + +The authentication number generated for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) + + + +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. + + + + + + +HTTP/1.1 200 OK +Connection: closer +Content-length: 239 +Content-Type: text/xml +Date: Sat, 13 Jul 2002 23:49:53 GMT +Server: Apache/1.3.4 (Unix) + +<methodResponse> +<params> +<param> +<value><struct> + +<member><name>anum</name> +<value><int>141</int></value> +</member> +<member><name>itemid</name> + +<value><int>1959</int></value> +</member> +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/proplist2db.pl b/livejournal/doc/raw/build/protocol/proplist2db.pl new file mode 100755 index 0000000..9b89fe3 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/proplist2db.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbr = LJ::get_dbh("slave", "master"); +my $sth; + +my $sth = $dbr->prepare("SELECT * FROM logproplist ORDER BY sortorder"); +$sth->execute; + +print "\n"; +print " Log Prop List\n\n"; + +while (my $r = $sth->fetchrow_hashref) +{ + print " \n"; + print " $r->{'name'}\n"; + print " $r->{'prettyname'}\n"; + print " $r->{'des'}\n"; + print " \n"; + print " Datatype\n"; + print " $r->{'datatype'}\n"; + print " \n"; + print " Scope\n"; + print " $r->{'scope'}\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n\n"; +} + +print "\n"; diff --git a/livejournal/doc/raw/build/protocol/sessionexpire.mode.xml b/livejournal/doc/raw/build/protocol/sessionexpire.mode.xml new file mode 100755 index 0000000..3d51880 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/sessionexpire.mode.xml @@ -0,0 +1,89 @@ + + +Expires session cookies. + + +Using this request mode, you can expire previously generated sessions, whether you +generated them using the sessiongenerate call or the user logged in on the web site. + + + +&authInfo; + + + +If present and true, then all of the user's sessions will be expired. + + + + + + +Given a list of session ids, will expire each one individually. Session ids can be +obtained from previous calls to sessiongenerate--notably, the id is the third field +in the session. + + + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 542 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.sessionexpire</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>expireall</name> +<value><int>1</int></value> +</member> + +</struct></value> +</param> +</params> +</methodCall> + + + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 1189 +Content-Type: text/xml +Date: Fri, 26 Mar 2004 18:39:38 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0" encoding="UTF-8"?> +<methodResponse> +<params> +<param> +<value><struct/></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/sessiongenerate.mode.xml b/livejournal/doc/raw/build/protocol/sessiongenerate.mode.xml new file mode 100755 index 0000000..b9a7df3 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/sessiongenerate.mode.xml @@ -0,0 +1,108 @@ + + +Generate a session cookie. + + +In order to interact with some web based parts of the site, such as the +comment exporter, it is often useful to be able to generate a login cookie +without having to actually post login information to the login.bml page. +This mode will, with proper authentication, provide you with a session +cookie to use for authentication purposes. + + + +&authInfo; + + + +Sessions can either expire in a short amount of time or last for a long period +of time. You can specify either "short" or "long" as the value of this parameter. + + + + + +If specified and true, this will cause the server to generate a session that is +only valid from the IP address the sessiongenerate request was sent from. If you +leave out this value, it will default to allowing any IP address to use this +session information. + + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 542 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.sessiongenerate</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>expiration</name> +<value><string>long</string></value> +</member> + +<member><name>ipfixed</name> +<value><string>1</string></value> +</member> + +</struct></value> +</param> +</params> +</methodCall> + + + + + + + + The session generated. + + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 228 +Content-Type: text/xml +Date: Fri, 26 Mar 2004 18:14:17 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0" encoding="UTF-8"?> +<methodResponse> +<params> +<param> +<value><struct> + +<member><name>ljsession</name> +<value><string>ws:test:124:zfFG136kSz</string> +</value></member> + +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/syncitems.mode.xml b/livejournal/doc/raw/build/protocol/syncitems.mode.xml new file mode 100755 index 0000000..a9dcc04 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/syncitems.mode.xml @@ -0,0 +1,259 @@ + + +Returns a list of all the items that have been created or updated for a user. + + +Returns a list (or part of a list) of all the items (journal entries, to-do items, comments) that have been created or updated on LiveJournal since you last downloaded them. Note that the items themselves are not returned --- only the item type and the item number. After you get this you have to go fetch the items using another protocol mode. For journal entries (type "L"), use the getevents mode with a selecttype of "syncitems". + + + +&authInfo; + + +The date you last downloaded synced, in "yyyy-mm-dd hh:mm:ss" format. Note: do not make this date up from the client's local computer... send the date from this mode's response of the newest item you have saved on disk. + + + + + +POST /interface/xmlrpc HTTP/1.0 +User-Agent: XMLRPC Client 1.0 +Host: www.livejournal.com +Content-Type: text/xml +Content-Length: 495 + +<?xml version="1.0"?> +<methodCall> +<methodName>LJ.XMLRPC.syncitems</methodName> +<params> +<param> + +<value><struct> +<member><name>username</name> +<value><string>test</string></value> +</member> +<member><name>password</name> + +<value><string>test</string></value> +</member> +<member><name>ver</name> +<value><int>1</int></value> + +</member> +<member><name>lastsync</name> +<value><string>2002-07-13 00:00:00</string></value> +</member> +</struct></value> + +</param> +</params> +</methodCall> + + + + + + + +The nth item, in the form "Type-Number". Type can be one of "L" for log entries (journal entries), "C" for comments (not implemented), "T" for to-do items (not implemented), or many other things presumably. If your client doesn't know how to fetch an item of a certain type, just ignore them. A new version of your client could later see that it has never downloaded anything of type "T" and go back and fetch everything of that type from the beginning. + + +Either "create" or "update". This field isn't too useful, but you may want to make your client verbose and tell the user what it's doing. For example, "Downloading entry 5 of 17: Updated". + + +The server time (in the form "yyyy-mm-dd hh:mm:ss") that this creation or update took place. Remember in your local store the most recent for each item type ("L", "T", "C", etc...). This is what you send in subsequent requests in lastsync. + + + + +The number of items that are contained in this response (numbered started at 1). If sync_count is equal to sync_total, then you can stop your sync after you complete fetching every item in this response. + + + +The total number of items that have been updated since the time specified. + + + + + +HTTP/1.1 200 OK +Connection: close +Content-length: 3360 +Content-Type: text/xml +Date: Tue, 16 Jul 2002 22:39:30 GMT +Server: Apache/1.3.4 (Unix) + +<?xml version="1.0"?> +<methodResponse> +<params> +<param> + +<value><struct> +<member><name>total</name> +<value><int>11</int></value> +</member> +<member><name>count</name> + +<value><int>11</int></value> +</member> +<member><name>syncitems</name> +<value><array> +<data> + +<value><struct> +<member><name>item</name> +<value><string>L-1947</string></value> +</member> +<member><name>time</name> + +<value><string>2002-07-13 00:06:26</string></value> +</member> +<member><name>action</name> +<value><string>del</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>item</name> +<value><string>L-1954</string></value> + +</member> +<member><name>time</name> +<value><string>2002-07-13 00:09:05</string></value> +</member> +<member><name>action</name> + +<value><string>del</string></value> +</member> +</struct></value> +<value><struct> +<member><name>item</name> + +<value><string>L-1958</string></value> +</member> +<member><name>time</name> +<value><string>2002-07-13 02:01:07</string></value> + +</member> +<member><name>action</name> +<value><string>create</string></value> +</member> +</struct></value> + +<value><struct> +<member><name>item</name> +<value><string>L-1948</string></value> +</member> +<member><name>time</name> + +<value><string>2002-07-13 08:27:56</string></value> +</member> +<member><name>action</name> +<value><string>update</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>item</name> +<value><string>L-1960</string></value> + +</member> +<member><name>time</name> +<value><string>2002-07-14 02:52:18</string></value> +</member> +<member><name>action</name> + +<value><string>create</string></value> +</member> +</struct></value> +<value><struct> +<member><name>item</name> + +<value><string>L-1961</string></value> +</member> +<member><name>time</name> +<value><string>2002-07-14 03:07:55</string></value> + +</member> +<member><name>action</name> +<value><string>create</string></value> +</member> +</struct></value> + +<value><struct> +<member><name>item</name> +<value><string>L-1962</string></value> +</member> +<member><name>time</name> + +<value><string>2002-07-14 03:08:14</string></value> +</member> +<member><name>action</name> +<value><string>create</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>item</name> +<value><string>L-1963</string></value> + +</member> +<member><name>time</name> +<value><string>2002-07-14 03:13:26</string></value> +</member> +<member><name>action</name> + +<value><string>create</string></value> +</member> +</struct></value> +<value><struct> +<member><name>item</name> + +<value><string>L-1964</string></value> +</member> +<member><name>time</name> +<value><string>2002-07-14 03:17:03</string></value> + +</member> +<member><name>action</name> +<value><string>create</string></value> +</member> +</struct></value> + +<value><struct> +<member><name>item</name> +<value><string>L-1959</string></value> +</member> +<member><name>time</name> + +<value><string>2002-07-14 14:25:07</string></value> +</member> +<member><name>action</name> +<value><string>update</string></value> + +</member> +</struct></value> +<value><struct> +<member><name>item</name> +<value><string>L-1965</string></value> + +</member> +<member><name>time</name> +<value><string>2002-07-16 04:36:15</string></value> +</member> +<member><name>action</name> + +<value><string>update</string></value> +</member> +</struct></value> +</data> +</array></value> +</member> + +</struct></value> +</param> +</params> +</methodResponse> + + + diff --git a/livejournal/doc/raw/build/protocol/usejournal.ent.xml b/livejournal/doc/raw/build/protocol/usejournal.ent.xml new file mode 100755 index 0000000..8e7b55b --- /dev/null +++ b/livejournal/doc/raw/build/protocol/usejournal.ent.xml @@ -0,0 +1,3 @@ + +Journal username that authenticating user has 'usejournal' access in, as given in the 'login' mode. + diff --git a/livejournal/doc/raw/build/protocol/usejournals.ent.xml b/livejournal/doc/raw/build/protocol/usejournals.ent.xml new file mode 100755 index 0000000..e6a3038 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/usejournals.ent.xml @@ -0,0 +1,7 @@ + +List of shared/news/community journals that the user has permission +to post in. + + +Username of community journal. + diff --git a/livejournal/doc/raw/build/protocol/xml-rpc2db.xsl b/livejournal/doc/raw/build/protocol/xml-rpc2db.xsl new file mode 100755 index 0000000..3763836 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/xml-rpc2db.xsl @@ -0,0 +1,129 @@ + + + + + + + + + + ljp.csp.xml-rpc. + + + + + + + Mode Description + + + + + + + Arguments + + + + + + + + Sample call to <literal>LJ.XMLRPC.<xsl:value-of select="@name"/></literal> + + + + + + + + + Return Values + + + + + + + + Sample return value for <literal>LJ.XMLRPC.<xsl:value-of select="@name"/></literal> + + + + + + + + + + + + + + + + + [struct] + + + + + + Containing keys: + + + + + + + + + + + [scalar] + + + + + + + + + + + : + + + + + + + + + + + + + + [array] + + + Containing items: + + + + + + + + + + + (required) + (optional) + (required; multiple allowed) + (optional; multiple allowed) + + + + diff --git a/livejournal/doc/raw/build/protocol/xmlrpc.dtd b/livejournal/doc/raw/build/protocol/xmlrpc.dtd new file mode 100755 index 0000000..fd49643 --- /dev/null +++ b/livejournal/doc/raw/build/protocol/xmlrpc.dtd @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/build/protocol/xmlrpc.xml b/livejournal/doc/raw/build/protocol/xmlrpc.xml new file mode 100755 index 0000000..bc8059e --- /dev/null +++ b/livejournal/doc/raw/build/protocol/xmlrpc.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + +]> + + +&mode.checkfriends; +&mode.consolecommand; +&mode.editevent; +&mode.editfriendgroups; +&mode.editfriends; +&mode.friendof; +&mode.getchallenge; +&mode.getdaycounts; +&mode.getevents; +&mode.getfriends; +&mode.getfriendgroups; +&mode.login; +&mode.postevent; +&mode.sessionexpire; +&mode.sessiongenerate; +&mode.syncitems; + + diff --git a/livejournal/doc/raw/build/titlepage.xsl b/livejournal/doc/raw/build/titlepage.xsl new file mode 100755 index 0000000..9e2c408 --- /dev/null +++ b/livejournal/doc/raw/build/titlepage.xsl @@ -0,0 +1,66 @@ + + + + +
    +

    Abstract

    +

    +
    +
    + + +
    +

    Authors

    +

    + +

    +
    +
    + + + + + +
    +
    + + + Editor: + + +
    +
    + + + + + + + + + + +
    +

    + + + +

    +
    +
    + + + + +
    +
    + + + + + +
    \ No newline at end of file diff --git a/livejournal/doc/raw/entities/authors.ent b/livejournal/doc/raw/entities/authors.ent new file mode 100755 index 0000000..7db76f8 --- /dev/null +++ b/livejournal/doc/raw/entities/authors.ent @@ -0,0 +1,23 @@ + + Jesse + Proulx + +
    + jproulx@livejournal.com +
    +
    + +"> + + + Brad + Fitzpatrick + +
    + bradfitz@livejournal.com +
    +
    + +"> \ No newline at end of file diff --git a/livejournal/doc/raw/entities/books.ent b/livejournal/doc/raw/entities/books.ent new file mode 100755 index 0000000..c1fac6c --- /dev/null +++ b/livejournal/doc/raw/entities/books.ent @@ -0,0 +1,30 @@ + + + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version + 1.1 or any later version published by the Free Software + Foundation; with no invariant sections, nor Front-Cover/Back-Cover + Texts. + A copy of the license is included in + + +"> + + 1999 + 2000 + 2001 + 2002 + 2003 + 2004 + LiveJournal + +'> +%lj.book; +%ljp.book; +%bml.book; \ No newline at end of file diff --git a/livejournal/doc/raw/entities/content.ent b/livejournal/doc/raw/entities/content.ent new file mode 100755 index 0000000..2046906 --- /dev/null +++ b/livejournal/doc/raw/entities/content.ent @@ -0,0 +1,6 @@ + + + +%books; +%authors; +%pregen; diff --git a/livejournal/doc/raw/entities/entities.xml b/livejournal/doc/raw/entities/entities.xml new file mode 100755 index 0000000..712eae2 --- /dev/null +++ b/livejournal/doc/raw/entities/entities.xml @@ -0,0 +1 @@ + diff --git a/livejournal/doc/raw/entities/lj.book.ent b/livejournal/doc/raw/entities/lj.book.ent new file mode 100755 index 0000000..89979b0 --- /dev/null +++ b/livejournal/doc/raw/entities/lj.book.ent @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/entities/ljp.book.ent b/livejournal/doc/raw/entities/ljp.book.ent new file mode 100755 index 0000000..2deb5f5 --- /dev/null +++ b/livejournal/doc/raw/entities/ljp.book.ent @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/http-interface.txt b/livejournal/doc/raw/http-interface.txt new file mode 100755 index 0000000..c6d7ef3 --- /dev/null +++ b/livejournal/doc/raw/http-interface.txt @@ -0,0 +1,372 @@ +accountstatus.bml +GET + authas +POST + statusvis + +allpics.bml +GET + user + +betatest.bml - 11/24 +POST + yes + no + +changepassword.bml - 11/24 +POST + user + password + newpass1 + newpass2 + mode + +comment_post.bml - dead page +Form + user + month + +comment_recv.bml - dead page +Form + user + month + +create.bml - 11/24 +GET + code +POST + mode + code + user + name + email + password1 + password2 + under13 + over13 + agree_tos + code + cluster_id + agree_tos + initial_optional_friend_$friend + +delcomment.bml +GET + journal + id +POST + ban + +directory.bml 11/24 +GET + opt_sort + opt_format + int_like + s_com + +POST + s_com + +editinfo.bml +GET + authas +POST + unban + name + name_absent + country + zip + stateother + statedrop + city + year + month + day + email + use_txtmsg + txtmsg_provider + txtmsg_number + url + bio_absent + allow_infosho + allow_getljnews + opt_showtalklinks + opt_gettalkemail + opt_htmlemail + opt_mangleemail + opt_whocanreply + allow_contactshow + contact_showsec + oldenc + journaltitle + journalsubtitle + friendspagetitle + opt_stylemine + opt_blockrobots + opt_bdaymail + opt_hidefriendsofs + opt_nctalklinks + opt_weblogscom + opt_whoscreened + sidx_bdate + sidx_loc + state + howhear + bio + txtmsg_security + interests_absent + interests + +editjournal.bml +GET + authas + usejournal + journal + itemid +POST + usejournal + itemid + $_ + prop_current_mood + secuirty + custom_bit_$bit + selecttype + howmany + +editpics.bml +GET + authas +POST + action:save + delete_$pic->{'picid'} + defaultpic + src + urlpic + userpic + make_default + +export.bml +GET + authas + +export_do.bml +GET + authas +POST + year + month + encid + encoding + field_${f} + field_currents + format + header + notranslation + +go.bml 11/25 +GET + redir_type + redir_user + redir_vhost + redir_key + itemid + journal + dir + +index.bml 11/25 +GET + frank + +interests.bml +GET + view + mode + intid + user + authas + fromuser +POST + mode + allintids + int_$fromint + fromuser + +login.bml +GET + authas + ret +POST + user + expire + bindip + password + action:change + action:login + action:logout + ref + +logout.bml 11/25 +GET + user + sessid +POST + user + sessid +POST + action:killall + +lostinfo.bml +POST + lostpass + email_p + user + lostuser + email_u + +modify.bml +GET + authas + user +POST + journaldomain + moodthemeid + opt_forcemoodtheme + themetype + themeid + theme_cust:$_ + themecolors_dig + theme_cust:$col->[0] + overrides + opt_usesharedpic + s1_${view}_style + $uprop + +meme.bml 11/25 +GET + url + skip + +moodlist.bml 11/25 +GET + moodtheme + hidederived + details + +multisearch.bml 11/25 +GET + type + q +POST + type + q + +pupkey.bml +GET + user + +register.bml +POST + action:Send + +talkmulti.bml +POST + mode + journal + ditemid + +talkpost.bml +Form + itemid + replyto + journal + prop_picture_keyword + +talkpost_do.bml +FORM + body + submitpreview + usertype + +talkread.bml +GET + itemid + journal + thread + viewall + page + view + +talkscreen.bml 11/25 +GET + mode + talkid + journal + confirm +POST + mode + talkid + journal + confirm + +unsubscribe.bml 11/25 +GET + aaid + auth +POST + aaid + auth + confirm + +update.bml +GET + altlogin + mode + user + subject + event +POST + do_spellcheck + event + user + altlogin + password + showform + webversion + hpassword + security + custom_bit_$bit + usejournal + $_ + prop_opt_$_ + prop_current_mood + year + mon + day + hour + min + subject + event + prop_opt_$prop + prop_picture_keyword + prop_current_mood + prop_current_moodid + prop_current_music + +userinfo.bml +GET + mode + user + userid + viewall + +utf8convert.bml 11/25 +GET + authas + mode + area + encid + forceview +POST + mode + area + encid \ No newline at end of file diff --git a/livejournal/doc/raw/index.xml b/livejournal/doc/raw/index.xml new file mode 100755 index 0000000..0aa9c63 --- /dev/null +++ b/livejournal/doc/raw/index.xml @@ -0,0 +1,27 @@ + + +%content; +]> + + + LiveJournal Server + Technical Info + + &author.jproulx; + &author.bradfitz; + + + + This documentation intends to cover everything related to + installing, administrating, and programming the LiveJournal + Server software. + + + ©right; + &legalnotice; + + &lj.index; + &bml.index; + &ljp.index; + \ No newline at end of file diff --git a/livejournal/doc/raw/int/db/db2ref.xsl b/livejournal/doc/raw/int/db/db2ref.xsl new file mode 100755 index 0000000..61550a4 --- /dev/null +++ b/livejournal/doc/raw/int/db/db2ref.xsl @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + Schema Browser + + + + + + + + <database class="table"><xsl:value-of select="name"/></database> + + + + Column name + Type + Null + Default + Description + + + + + + + + YES + + + + + + + + + + + + Key name + Type + Column(s) + + + + + + + + + + + + + + + + , + + + + + + + + + No keys defined. + + + + + + + + + + + + + + diff --git a/livejournal/doc/raw/int/db/dbschema.dtd b/livejournal/doc/raw/int/db/dbschema.dtd new file mode 100755 index 0000000..ac52ea6 --- /dev/null +++ b/livejournal/doc/raw/int/db/dbschema.dtd @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/doc/raw/int/db/dbschema.pl b/livejournal/doc/raw/int/db/dbschema.pl new file mode 100755 index 0000000..b6a9618 --- /dev/null +++ b/livejournal/doc/raw/int/db/dbschema.pl @@ -0,0 +1,126 @@ +#!/usr/bin/perl +# + +use strict; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbr = LJ::get_dbh("slave", "master"); +my $sth; + +sub magic_links +{ + my $des = shift; + $$des =~ s!table\[(\w+?)\]!$1!g; +} + +sub dump_xml +{ + my $tables = shift; + + print "\n"; + print "\n"; + print "\n"; + foreach my $table (sort keys %$tables) + { + print "\n"; + + # table name + print "$table\n"; + + # description of table + if ($tables->{$table}->{'des'}) { + my $des = $tables->{$table}->{'des'}; + &magic_links(\$des); + print "$des\n"; + } + + # columns + foreach my $col (@{$tables->{$table}->{'cols'}}) + { + print "{'name'}\" type=\"$col->{'type'}\" required=\"$col->{'required'}\" default=\"$col->{'default'}\">\n"; + print "$col->{'name'}\n"; + if ($col->{'des'}) { + my $des = $col->{'des'}; + &magic_links(\$des); + print "$des\n"; + } + print "\n"; + } + + # indexes + foreach my $indexname (sort keys %{$tables->{$table}->{'index'}}) + { + my $index = $tables->{$table}->{'index'}->{$indexname}; + + print "{'type'}\" colids=\"", join(" ", @{$index->{'cols'}}), "\" />\n"; + } + + print "\n"; + } + print "\n"; +} + +my %table; +my %coldes; + +$sth = $dbr->prepare("SHOW TABLES"); +$sth->execute; +while (my ($table) = $sth->fetchrow_array) { + $table{$table} = {}; +} + +$sth = $dbr->prepare("SELECT tablename, public_browsable, des FROM schematables"); +$sth->execute; +while (my ($name, $public, $des) = $sth->fetchrow_array) { + next unless (defined $table{$name}); + $table{$name} = { 'public' => $public, 'des' => $des }; +} + +$sth = $dbr->prepare("SELECT tablename, colname, des FROM schemacols"); +$sth->execute; +while (my ($table, $col, $des) = $sth->fetchrow_array) { + next unless (defined $table{$table}); + $coldes{$table}->{$col} = $des; +} + +foreach my $table (sort keys %table) +{ + $sth = $dbr->prepare("DESCRIBE $table"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) + { + my $col = {}; + $col->{'name'} = $r->{'Field'}; + + my $type = $r->{'Type'}; + $type =~ s/int\(\d+\)/int/g; + if ($r->{'Extra'} eq "auto_increment") { + $type .= " auto_increment"; + } + $col->{'type'} = $type; + + $col->{'default'} = $r->{'Default'}; + $col->{'required'} = $r->{'Null'} eq "YES" ? "false" : "true"; + + $col->{'des'} = $coldes{$table}->{$r->{'Field'}}; + + push @{$table{$table}->{'cols'}}, $col; + } + + $sth = $dbr->prepare("SHOW INDEX FROM $table"); + $sth->execute; + while (my $r = $sth->fetchrow_hashref) + { + my $name = $r->{'Key_name'}; + my $type = $r->{'Non_unique'} ? "INDEX" : "UNIQUE"; + if ($name eq "PRIMARY") { $type = "PRIMARY"; } + + $table{$table}->{'index'}->{$name}->{'type'} = $type; + push @{$table{$table}->{'index'}->{$name}->{'cols'}}, "_$table.$r->{'Column_name'}"; + } + +} + + +&dump_xml(\%table); diff --git a/livejournal/doc/raw/int/db/schema.xml b/livejournal/doc/raw/int/db/schema.xml new file mode 100755 index 0000000..4b8b90d --- /dev/null +++ b/livejournal/doc/raw/int/db/schema.xml @@ -0,0 +1,9 @@ + + +Database Schema + + +FIXME: Since a reference can't go in a chapter (?), this has nothing here. Go look at the reference in the book. :P + + + diff --git a/livejournal/doc/raw/int/programming-guidelines.xml b/livejournal/doc/raw/int/programming-guidelines.xml new file mode 100755 index 0000000..5fd141e --- /dev/null +++ b/livejournal/doc/raw/int/programming-guidelines.xml @@ -0,0 +1,204 @@ + + +Programming Guidelines + + +If you're contributing code back into LiveJournal, be sure to follow +the following guidelines: + + + + + +Security + + +all GET/POST form values go into %FORM into BML, but check +LJ::did_post() on critical actions. GET requests can be easily +spoofed, or hidden in images, etc. + + +never read in arbitrary amounts of input + + +never use unsanitized data in a command or SQL + + + + + + +General + + +BML pages shouldn't interface with the database much. Use the +LJ::* API & the protocol handler. + + +always use the LJ:: functions that take an explicit database +handle. don't use the old main:: functions that use the global +$dbh. + + +all files should have <LJDEP> edge dependency somewhere, usually +at the bottom. + + +using userids (integers) for things is better than using +users (strings), except in URL arguments, where pretty +is more important than speed. + + +in BML page, use BML blocks defined in global.look: +LJUSER, P, H1, H2, STANDOUT, HR, etc... + + +all HTML should be XHTML compliant.: + + + lower case tags, <BR><br /> + + + quotes around attributes <font face="helvetica"> + + + no bare & chars ... always escape them: &amp; and + <a href="foo.bml?a=1&amp;b=2">...</a> + + + + +use of multiple files to do one function is deprecated. there +should no longer be "foo.bml" and "foo_do.bml" like there used +to. that's ugly. + + +tab is a formatting command, not a character. (TODO: add note +about save hooks for emacs & vi) there should be spaces in the +files, not tab characters + + + + + + +Database + +check your db index usage... mysql's "EXPLAIN" is your friend. + + +between LOCK TABLES & UNLOCK TABLES, never call a subroutine. + + +check the DB error code after an SQL statement. just because +it worked once and the SQL is correct, that doesn't mean the +table might not go corrupt, a disk might fill up, or index +space within the file might not fill up. errors happen. +deal with them. + + +preferred way to break up a long SQL query: + + $sth = $dbh->prepare("SELECT cola, colb, colc, cold FROM foo ". + "WHERE colb<>cola AND colc=22"); + + + +Note on variable naming: + + + + +$sth +statement handle + + +$dbh +one database handle (usually the master) + + +$dbs +set of database handles [master(, slave)] + + +$dbr +read-only slave db handle (used for selects) + + +$dbarg +argument that can take a $dbh/r or $dbs + + +$remote + +hashref of remote user, based on cookies. will contain 'userid' and +'user' params, unless faster get_remote_noauth was used, in which case +only 'user' will be present. + + + +$u +a user 'object' (a hashref) + + + + + + + + + + +Performance & Scalability + +Large chunks of code should be preloaded in libraries. Code +in BML pages is re-evaled on every request, so it should +be small. If you need a lot of code, put it in a library +and load it in cgi-bin/lj-bml-(init|local).pl + + +don't write temporary files to disk... all LJ code should be able +to run on a cluster of web servers with no session persistence + + +if you're calling a function with a $dbarg parameter and you +have both a $dbs and $dbh available, call the function with +your $dbs ... otherwise the function and all its callees +can't ever use the slave databases. + + + + + + +Patches + +all patches sent in should be in diff -u format + + +don't send in patches that comment out old code. if +we want the old code, we'll go get it from CVS.. that's +what it's for + + + + + + +Perl Style + +foo() looks prettier than +&foo(). let perl 4 die. + + +lines longer than 80 characters are okay, but not great. + + +if you're in package LJ and calling an LJ::* API function, +go ahead and type the extra four characters (LJ::) even +if they're not necessary... being explicit is nice for +the reader. + + + + diff --git a/livejournal/doc/raw/int/protocol/Makefile b/livejournal/doc/raw/int/protocol/Makefile new file mode 100755 index 0000000..32a3721 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/Makefile @@ -0,0 +1,14 @@ +all: reference.gen testbook.html + +reference.gen: to_docbook.xsl xmlrpc.xml + (xsltproc to_docbook.xsl xmlrpc.xml > reference.gen~) || true + mv reference.gen~ reference.gen + +xmlrpc.xml: xmlrpc.dtd authinfo.ent.xml checkfriends.mode.xml editevent.mode.xml editfriendgroups.mode.xml editfriends.mode.xml friendgroups.ent.xml friendof.mode.xml friendslist.ent.xml getdaycounts.mode.xml getevents.mode.xml getfriendgroups.mode.xml getfriends.mode.xml login.mode.xml moods.ent.xml postevent.mode.xml syncitems.mode.xml usejournal.ent.xml usejournals.ent.xml + +testbook.html: reference.gen testbook.xml + xsltproc $(LJHOME)/doc/raw/docbook-xsl-1.45/html/docbook.xsl testbook.xml > testbook.html~ || true + mv testbook.html~ testbook.html + +clean: + rm reference.gen testbook.html diff --git a/livejournal/doc/raw/int/protocol/authinfo.ent.xml b/livejournal/doc/raw/int/protocol/authinfo.ent.xml new file mode 100755 index 0000000..49499fc --- /dev/null +++ b/livejournal/doc/raw/int/protocol/authinfo.ent.xml @@ -0,0 +1,16 @@ + + + Username of user logging in. + + + + + Password of user logging in in plaintext. Either this or "hpassword" must be present. + + + + + MD5 digest of user's password. Not much more secure than password, but at least it's not in plain text. + + + diff --git a/livejournal/doc/raw/int/protocol/checkfriends.mode.xml b/livejournal/doc/raw/int/protocol/checkfriends.mode.xml new file mode 100755 index 0000000..18df24d --- /dev/null +++ b/livejournal/doc/raw/int/protocol/checkfriends.mode.xml @@ -0,0 +1,42 @@ + + +Checks to see if your friends list has been updated since a specified time. + + +Mode that clients can use to poll the server to see if their friends list has been updated. This request is extremely quick, and is the preferred way for users to see when their friends list is updated, rather than pounding on reload in their browser, which is stressful on the serves. + + + +&authInfo; + + +The time that this mode request returned last time you called it. If this is the first time you've ever called it (since your client has been running), leave this blank. It's strongly recommended that you do not remember this value across invocations of your client, as it's very likely your friends will update since the client was running so the notification is pointless... the user probably read his/her friends page already before starting the client. + + + +The friend group(s) in which the client is checking for new entries, represented as a 32-bit unsigned int. Turn on any combination of bits 1-30 to check for entries by friends in the respective friend groups. Turn on bit 0, or leave the mask off entirely, to check for entries by any friends. + + + + + + + + +This is what you should use to determine if there are new entries. Its value is "1" if there is new stuff, or "0" if there isn't. A few people requested that this return the number of new entries, but that's a lot more resource intensive, and this protocol mode is supposed to be very quick and painless. In the future we may add a "new_count" response value that says how many new items there are. Note that once this values becomes "1" and you alert the user, stop polling! It'd be pointless to have the client hitting the server all night while the user slept. Once the user acknowleges the notifcation (double-clicks the system tray or panel applet or whatnot), then resume your polling. + + + +How many seconds you must wait before polling the server again. If your client disobeys, this protocol will just return error messages saying "slow down, bad client!" instead of giving you the data you were trying to cheat to obtain. Note that this also means your client should have an option to disable polling for updates, since some users run multiple operating systems with multiple LiveJournal clients, and both would be fighting each other. + + + +The number of items that are contained in this response (numbered started at 1). If sync_count is equal to sync_total, then you can stop your sync after you complete fetching every item in this response. + + + +The total number of items that have been updated since the time specified. + + + + diff --git a/livejournal/doc/raw/int/protocol/consolecommand.mode.xml b/livejournal/doc/raw/int/protocol/consolecommand.mode.xml new file mode 100755 index 0000000..b7fd582 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/consolecommand.mode.xml @@ -0,0 +1,61 @@ + + +Run an administrative command. + + +The LiveJournal server has a text-based shell-like admininistration +console where less-often used commands can be entered. There's a web +interface to this shell online, and this is another gateway to that. + + + +&authInfo; + + + +The commands to send, with double quotes around any arguments with spaces, +and double quotes escaped by backslashes, and backslashes escaped with +backslashes. Optionally, you can send a listref instead of a string +for this argument, in which case, we'll use your argument separation +and not parse it ourselves. + + + + + + + + + + + One stuct returned for each command run, + that struct containing both the overall return value, + and the line-by-line output of the command, with + each line of output being tagged by type (think + stdout vs. stderr, but with stdinfo also). The web interface + shows 'error' with red, '' (stdout) with black, and 'info' + with green. Clients are encouraged to also, if possible. + + + + + Return status of nth command. 0 or 1. + + + + + + Type of output line. Either "" (normal output), "error", or "info", + something to be emphasized over normal output. + + + The text of that line. + + + + + + + + + diff --git a/livejournal/doc/raw/int/protocol/editevent.mode.xml b/livejournal/doc/raw/int/protocol/editevent.mode.xml new file mode 100755 index 0000000..cc164ef --- /dev/null +++ b/livejournal/doc/raw/int/protocol/editevent.mode.xml @@ -0,0 +1,79 @@ + + +Edit or delete a user's past journal entry + + +Modify an already created event. If fields are empty, it will delete the event. + + + +&authInfo; + + +The unique ItemID of the item being modified or deleted. + + + +The revised event/log text the user is submitting. Or, to delete an entry, just send no text at all. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac ( +0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-form +atted text, and it does the conversion by removing all \r characters. If you're sending a + multi-line event on Mac, you have to be sure and send a lineendings value of mac or you +r line endings will be removed. PC and Unix clients can ignore this setting, or you can s +end it. It may be used for something more in the future. + + + +The subject for this post. Limited to 255 characters. No newlines. + + + +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. + + + +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. + + + +Properties and their values for the item being returned. + + + +If editing a shared journal entry, include this key and the username you wish to edit the entry in. By default, you edit the entry as if it were in user "user"'s journal, as specified above. + + + +If modifying only, the 4-digit year of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit month of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit day of the month of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit hour from 0 to 23 of the event (from the user's local timezone). + + + +If modifying only, the 1- or 2-digit minute of the event (from the user's local timezone). + + + + + + + + +The unique ItemID of the item being modified or deleted. + + + + diff --git a/livejournal/doc/raw/int/protocol/editfriendgroups.mode.xml b/livejournal/doc/raw/int/protocol/editfriendgroups.mode.xml new file mode 100755 index 0000000..3d6e48e --- /dev/null +++ b/livejournal/doc/raw/int/protocol/editfriendgroups.mode.xml @@ -0,0 +1,45 @@ + + +Edit the user's defined groups of friends. + + +Given several optional lists, will add/delete/update/rename the friends groups for a user. + + + +&authInfo; + + + +A structure of friend userids. The values of each are a string representing an unsigned 32-bit integer with bit 0 set (or the server will force it on anyway), bits 1-30 set for each group the friend belongs to, and bit 31 unset (reserved for future use). + + + + + +Given the bit of a friend group, the value contains a structure of information on it. + + + + Create or rename the friend group by sending this key. The value is the name of the group. + + + This field should be sent to indicate the sorting order of this group. The value must be in the range of 0-255. The default is 50. + + + If this is "1", then this group is marked as public. If public, other users can see the name of the group and the people that are in it. + + + + + +A number of a friend group to delete (which can be from 1-30, inclusive). The server will modify all old entries that allow access to that friend group, so a new friend group using that number won't have access to old non-related entries. However, it is the client's responsibility to modify each friend's groupmask to remove them from the group as it's deleted. + + + + + + + + + diff --git a/livejournal/doc/raw/int/protocol/editfriends.mode.xml b/livejournal/doc/raw/int/protocol/editfriends.mode.xml new file mode 100755 index 0000000..1b55172 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/editfriends.mode.xml @@ -0,0 +1,59 @@ + + +Add, edit, or delete friends from the user's friends list. + + +Takes up to two lists, one of friends to delete and one of friends to add. Several options are allowed to be specified when adding a friend. It returns a verbose list of the friends added, if any were. + + + +&authInfo; + + + +A list of variable of this form removes the friend users from the user's friend list. It is not an error to delete an already non-existant friend. The value should just be 1. + + +A username of a friend to remove. + + + + + +To add friends, send a variable list of this form. + + + + A username of a friend to remove. + + + Sets the text color of the friend being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #000000, black. + + + Sets the background color of the friend being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #FFFFFF, white. + + + Sets this user's groupmask. Only use this in clients if you've very recently loaded the friend groups. If your client has been loaded on the end user's desktop for days and you haven't loaded friend groups since it started, they may be inaccurate if they've modified their friend groups through the website or another client. In general, don't use this key unless you know what you're doing. + + + + + + + + + + +A list of the users who have been added with this transaction. + + + + The username of the friend that was added. + + + The full name of the friend that was added. + + + + + diff --git a/livejournal/doc/raw/int/protocol/friendgroups.ent.xml b/livejournal/doc/raw/int/protocol/friendgroups.ent.xml new file mode 100755 index 0000000..46b9ea3 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/friendgroups.ent.xml @@ -0,0 +1,21 @@ + + + + +The bit number for this friend group, from 1-30. + + + +The name of this friend group. + + + +The sort integer for this friend group, from 0-255. + + + +Either '0' or '1' for if this friend group is public. + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/int/protocol/friendof.mode.xml b/livejournal/doc/raw/int/protocol/friendof.mode.xml new file mode 100755 index 0000000..a6bed65 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/friendof.mode.xml @@ -0,0 +1,29 @@ + + +Returns a list of which other LiveJournal users list this user as their friend. + + +Returns a "friends of" list for a specified user. An optional limit of returned friends can be supplied. + + + +&authInfo; + + +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. + + + + + + + + + +The list of people who list this user as a friend. + +&friendsList; + + + + diff --git a/livejournal/doc/raw/int/protocol/friendslist.ent.xml b/livejournal/doc/raw/int/protocol/friendslist.ent.xml new file mode 100755 index 0000000..cd3a802 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/friendslist.ent.xml @@ -0,0 +1,29 @@ + + + + +The username of the friend. + + + +The full name of the friend. + + + +The type of journal the friend item is. + + + +The foreground color of the friend item. + + + +The background color of the friend item. + + + +If the group mask is not "1" (just bit 0 set), then this variable is returned with an 32-bit unsigned integer with a bit 0 always set, and bits 1-30 set for each group this friend is a part of. Bit 31 is reserved. + + + + diff --git a/livejournal/doc/raw/int/protocol/getdaycounts.mode.xml b/livejournal/doc/raw/int/protocol/getdaycounts.mode.xml new file mode 100755 index 0000000..11c0ef8 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/getdaycounts.mode.xml @@ -0,0 +1,33 @@ + + +This mode retrieves the number of journal entries per day. + + +This mode retrieves the number of journal entries per day. Useful for populating calendar widgets in GUI clients. Optionally a journal can be specified. It returns a list of the dates and accompanied counts. + + + +&authInfo; + + + +If getting the day counts of a shared journal, include this key and the username you wish to get the counts of. By default, you load the counts of "user" as specified above. + +&useJournal; + + + + + + + + +For each day that the user has posted a journal entry, a struct is returned in the list. + +The date, in yyyy-dd-mm format. +The number of journal entries on that date. + + + + + diff --git a/livejournal/doc/raw/int/protocol/getevents.mode.xml b/livejournal/doc/raw/int/protocol/getevents.mode.xml new file mode 100755 index 0000000..7bcb6bc --- /dev/null +++ b/livejournal/doc/raw/int/protocol/getevents.mode.xml @@ -0,0 +1,109 @@ + + +Download parts of the user's journal. + + +Given a set of specifications, will return a segment of entries up to a limit set by the server. Has a set of options for less, extra, or special data to be returned. + + + +&authInfo; + + +A value that if greater than or equal to 4, truncates the length of the returned events (after being decoded) to the value specified. Entries less than or equal to this length are left untouched. Values greater than this length are truncated to the specified length minus 3, and then have "... " appended to them, bringing the total length back up to what you specified. This is good for populating list boxes where only the beginning of the entry is important, and you'll double-click it to bring up the full entry. + + + +If this setting is set to true (1 ), then no subjects are returned, and the events are actually subjects if they exist, or if not, then they're the real events. This is useful when clients display history and need to give the user something to double-click. The subject is shorter and often more informative, so it'd be best to download only this. + + + +If this setting is set to true (1), then no meta-data properties are returned. + + + +Determines how you want to specify what part of the journal to download. Valid values are day to download one entire day, lastn to get the most recent n entries (where n is specified in the howmany field), one to download just one specific entry, or syncitems to get some number of items (which the server decides) that have changed since a given time (specified in the lastsync parameter>). Not that because the server decides what items to send, you may or may not be getting everything that's changed. You should use the syncitems selecttype in conjuntions with the syncitems protocol mode. + + + +For a selecttype of syncitems, the date (in "yyyy-mm-dd hh:mm:ss" format) that you want to get updates since. + + + +For a selecttype of day, the 4-digit year of events you want to retrieve. + + + +For a selecttype of day, the 1- or 2-digit month of events you want to retrieve. + + + +For a selecttype of day, the 1- or 2-digit day of the month of events you want to retrieve. + + + +For a selecttype of lastn, how many entries to get. Defaults to 20. Maximum is 50. + + + +For a selecttype of lastn, you can optionally include this variable and restrict all entries returned to be before the date you specify, which must be of the form yyyy-mm-dd hh:mm:ss. + + + +For a selecttype of one, the journal entry's unique ItemID for which you want to retrieve. Or, to retrieve the most recent entry, use the value -1. Using -1 has the added effect that the data is retrieved from the master database instead of a replicated slave. Clients with an "Edit last entry" feature might want to send -1, to make sure the data that comes back up is accurate, in case a slave database is a few seconds behind in replication. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. + + + + +If getting the history of a shared journal, include this key and the username you wish to get the history of. By default, you load the history of "user" as specified above. + +&useJournal; + + + + + + + + +A list of structs for all of the returned events. + + + + +The unique integer ItemID of the item being returned. + + + +The time the user posted (or said they posted, rather, since users can back-date posts) the item being returned. + + + +If this variable is not returned, then the security of the post is public, otherwise this value will be private or usemask. + + + +If security is usemask then this is defined with the 32-bit unsigned int bit-mask of who is allowed to access this post. + + + +The subject of the journal entry. This won't be returned if "prefersubjects" is set, instead the subjects will show up as the events. + + + +The event text itself. This value is first truncated if the truncate variable is set, and then it is URL-encoded (alphanumerics stay the same, weird symbols to %hh, and spaces to + signs, just like URLs or post request). This allows posts with line breaks to come back on one line. + + + +Properties and their values for the item being returned. + + + + + + + diff --git a/livejournal/doc/raw/int/protocol/getfriendgroups.mode.xml b/livejournal/doc/raw/int/protocol/getfriendgroups.mode.xml new file mode 100755 index 0000000..104b043 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/getfriendgroups.mode.xml @@ -0,0 +1,22 @@ + + +Retrieves a list of the user's defined groups of friends. + + +Retrieves a list of the user's defined groups of friends. + + + +&authInfo; + + + + + + + +&friendGroups; + + + + diff --git a/livejournal/doc/raw/int/protocol/getfriends.mode.xml b/livejournal/doc/raw/int/protocol/getfriends.mode.xml new file mode 100755 index 0000000..58ddfdd --- /dev/null +++ b/livejournal/doc/raw/int/protocol/getfriends.mode.xml @@ -0,0 +1,40 @@ + + +Returns a list of which other LiveJournal users this user lists as their friend. + + +Returns a verbose list of information on friends a user has listed. Optionally able to include their friends of list, the friends group associated with each user, and a limit on the number of friends to return. + + + +&authInfo; + + +If set to 1, you will also get back the info from the "friendof" mode. Some clients show friends and friendof data in separate tabs/panes. If you're always going to load both, then use this flag (as opposed to a tabbed dialog approach, where the user may not go to the second tab and thus would not need to load the friendof data.) friendof request variables can be used. + + + +If set to 1, you will also get back the info from the "getfriendgroups" mode. See above for the reason why this would be useful. + + + +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. + + + + + + + +&friendGroups; + + +&friendsList; + + + +&friendsList; + + + + diff --git a/livejournal/doc/raw/int/protocol/login.mode.xml b/livejournal/doc/raw/int/protocol/login.mode.xml new file mode 100755 index 0000000..a0aaadf --- /dev/null +++ b/livejournal/doc/raw/int/protocol/login.mode.xml @@ -0,0 +1,118 @@ + + +validate user's password and get base information needed for client to function + + +Login to the server, while announcing your client version. The server returns with whether the password is good or not, the user's name, an optional message to be displayed to the user, the list of the user's friend groups, and other things. + + + +&authInfo; + + +Although optional, this should be a string of the form Platform-ProductName/ClientVersionMajor.Minor.Rev, like Win32-MFC/1.2.7 or Gtk-LoserJabber/1.0.4. Note in this case that "Gtk" is not a platform, but rather a toolkit, since the toolkit is multi-platform (Linux, FreeBSD, Solaris, Windows...). You make the judge what is best to send, but if it's of this form, we'll give you cool statistics about your users. + + + +If your client supports moods, send this key with a value of the highest mood ID you have cached/stored on the user's computer. For example, if you logged in last time with and got mood IDs 1, 2, 4, and 5, then send "5" as the value of "getmoods". The server will return every new mood that has an internal MoodID greater than 5. If you've never downloaded moods before, send "0". If you don't care about getting any moods at all (if your client doesn't support them), then don't send this key at all. + + + +Send something for this key if you want to get a list/tree of web jump menus to show in your client. + + + +If your client supports picture keywords and you want to receive that list, send something for this key, like "1", and you'll receieve the list of picture keywords the user has defined. + + + +If your client supports picture keywords and can also display the pictures somehow, send something for this key, like "1", and you'll receieve the list of picture keyword URLs that correspond to the picture keywords as well as the URL for the default picture. You must send getpickws for this option to even matter. + + + + + + + + +The user's full name. Often, clients use this to change the top-level window's title bar text to say something like "LiveJournal - User name". You can just ignore this if you'd like. + + + +A message that should be displayed in a dialog box (or to the screen in a console application). The message is rarely present but when used notifies the user of software updates they've requested to hear about, problems with their account (if mail is bouncing to them, we'd like them to give us a current email address), etc. To test this if you're developing a client, use the user account test with the password test and a message will always be returned. + + + +&friendGroups; + + + +&useJournals; + + + + + If you sent the 'getmoods' key in your request, this is returned. The contents are the new moods that have been added on the server since you last requested the list. Your client should cache the mood list on the client's computer to avoid requesting the whole list everytime. + + &moods; + + + + +This is requrned if you set "getpickws" in your request. Picture keywords are used to identify which userpic (100x100 icon) to use for that particular post. For instance, the user may have "Angry", "Happy", and "Sleepy" picture keywords which map to certain pictures. The client should also do a case-insensitive compare on this list when a mood is selected or entered, and auto-select the current picture keyword. That way it seems that selecting a mood also sets their corresponding picture. + + +The picture keyword. + + + + + +The URLs of the user pictures. They correspond with the list of +picture keywords returned. Note that the content behind these URLs +can never change, so if your client downloads these to display, just +cache them locally and never hit the servers again to re-download them +or to even check if they've been modified. + + +The picture URL. + + + + +The URL of the default picture (if you sent the 'getpickwurls' key). Note that the content behind this URL can never change, so you can cache it locally; also note that the default picture might have no keyword associated with it. + + + +LiveJournal sites may have priority servers for paying customers. If this key is both present and set to value "1", then the client has permission to set the "ljfastserver" cookie in subsequent requests. The HTTP request header to send is "Cookie: ljfastserver=1". If you send this header without getting permission from the login mode, your requests will fail. That is, you'll trick the load balancer into directing your request towards the priority servers, but the server you end up hitting won't be happy that you're trying to scam faster access and will deny your request. + + + +The userid of this user on the system. Not required for any other requests to +the server, but some developers have wanted it. + + + +Returned if you set "getmenus" in your request. + +List of menu items in order that should be in the LiveJournal web menu in the client application. + + + The text of the menu item, or "-" for a separator. + + + The URL the menu item should launch, present for all menu items + except separators and submenus. + + + If this is present, this menu item is a submenu. + + Same format as top-level menu structure + + + + + + + + diff --git a/livejournal/doc/raw/int/protocol/moods.ent.xml b/livejournal/doc/raw/int/protocol/moods.ent.xml new file mode 100755 index 0000000..47f5bd6 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/moods.ent.xml @@ -0,0 +1,15 @@ + + + + + The integer moodid. + + + The mood name. + + + The mood's parent (base) moodid. + + + + diff --git a/livejournal/doc/raw/int/protocol/postevent.mode.xml b/livejournal/doc/raw/int/protocol/postevent.mode.xml new file mode 100755 index 0000000..21ba99c --- /dev/null +++ b/livejournal/doc/raw/int/protocol/postevent.mode.xml @@ -0,0 +1,74 @@ + + +The most important mode, this is how a user actually submits a new log entry to the server. + + +Given all of the require information on a post, optioanlly adding security or meta data, will create a new entry. Will return the itemid of the new post. + + + +&authInfo; + + +The event/log text the user is submitting. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. + + + +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r) ). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. + + + +The subject for this post. Limited to 255 characters. No newlines. + + + +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. + + + +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. + + + +The current 4-digit year (from the user's local timezone). + + + +The current 1- or 2-digit month (from the user's local timezone). + + + +The current 1- or 2-digit day of the month (from the user's local timezone). + + + +The current 1- or 2-digit hour from 0 to 23 (from the user's local timezone). + + + +The current 1- or 2-digit minute (from the user's local timezone). + + + +Set an arbitrary (but restricted) meta-data property to this log item. See the document on properties for the discussion of them and the list of valid names. You may send zero or more keys like this, one for each property you're setting. + + + + + +If posting to a shared journal, include this key and the username you wish to post to. By default, you post to the journal of "user" as specified above. + +&useJournal; + + + + + + + + +The unique number the server assigned to this post. Currently nothing else in the protocol requires the use of this number so it's pretty much useless, but somebody requested it be returned, so it is. + + + + diff --git a/livejournal/doc/raw/int/protocol/syncitems.mode.xml b/livejournal/doc/raw/int/protocol/syncitems.mode.xml new file mode 100755 index 0000000..51bed20 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/syncitems.mode.xml @@ -0,0 +1,42 @@ + + +Returns a list of all the items that have been created or updated for a user. + + +Returns a list (or part of a list) of all the items (journal entries, to-do items, comments) that have been created or updated on LiveJournal since you last downloaded them. Note that the items themselves are not returned --- only the item type and the item number. After you get this you have to go fetch the items using another protocol mode. For journal entries (type "L"), use the getevents mode with a selecttype of "syncitems". + + + +&authInfo; + + +The date you last downloaded synced, in "yyyy-mm-dd hh:mm:ss" format. Note: do not make this date up from the client's local computer... send the date from this mode's response of the newest item you have saved on disk. + + + + + + + + + +The nth item, in the form "Type-Number". Type can be one of "L" for log entries (journal entries), "C" for comments (not implemented), "T" for to-do items (not implemented), or many other things presumably. If your client doesn't know how to fetch an item of a certain type, just ignore them. A new version of your client could later see that it has never downloaded anything of type "T" and go back and fetch everything of that type from the beginning. + + +Either "create" or "update". This field isn't too useful, but you may want to make your client verbose and tell the user what it's doing. For example, "Downloading entry 5 of 17: Updated". + + +The server time (in the form "yyyy-mm-dd hh:mm:ss") that this creation or update took place. Remember in your local store the most recent for each item type ("L", "T", "C", etc...). This is what you send in subsequent requests in lastsync. + + + + +The number of items that are contained in this response (numbered started at 1). If sync_count is equal to sync_total, then you can stop your sync after you complete fetching every item in this response. + + + +The total number of items that have been updated since the time specified. + + + + diff --git a/livejournal/doc/raw/int/protocol/testbook.xml b/livejournal/doc/raw/int/protocol/testbook.xml new file mode 100755 index 0000000..d1a129e --- /dev/null +++ b/livejournal/doc/raw/int/protocol/testbook.xml @@ -0,0 +1,13 @@ + + +]> + + +xmlrpc ref test + +&ref; + + diff --git a/livejournal/doc/raw/int/protocol/to_docbook.xsl b/livejournal/doc/raw/int/protocol/to_docbook.xsl new file mode 100755 index 0000000..7a9b93b --- /dev/null +++ b/livejournal/doc/raw/int/protocol/to_docbook.xsl @@ -0,0 +1,108 @@ + + + + + + + + + + + + XML/RPC Protocol Reference + + + + + + + + + + + + + Mode Description + + + + + + + Arguments + + + + + + + + + Return Values + + + + + + + + + + + + +[struct] + +Containing keys: + + + + + + + + + + +[scalar] + + + + + + + +: + + + + + + + + + + + +[list] + + + Containing items: + + + + + + + + + + + (required) + (optional) + (required; multiple allowed) + (optional; multiple allowed) + + + + diff --git a/livejournal/doc/raw/int/protocol/usejournal.ent.xml b/livejournal/doc/raw/int/protocol/usejournal.ent.xml new file mode 100755 index 0000000..8e7b55b --- /dev/null +++ b/livejournal/doc/raw/int/protocol/usejournal.ent.xml @@ -0,0 +1,3 @@ + +Journal username that authenticating user has 'usejournal' access in, as given in the 'login' mode. + diff --git a/livejournal/doc/raw/int/protocol/usejournals.ent.xml b/livejournal/doc/raw/int/protocol/usejournals.ent.xml new file mode 100755 index 0000000..e6a3038 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/usejournals.ent.xml @@ -0,0 +1,7 @@ + +List of shared/news/community journals that the user has permission +to post in. + + +Username of community journal. + diff --git a/livejournal/doc/raw/int/protocol/xmlrpc.dtd b/livejournal/doc/raw/int/protocol/xmlrpc.dtd new file mode 100755 index 0000000..c1a3f11 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/xmlrpc.dtd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livejournal/doc/raw/int/protocol/xmlrpc.xml b/livejournal/doc/raw/int/protocol/xmlrpc.xml new file mode 100755 index 0000000..4d8b3c9 --- /dev/null +++ b/livejournal/doc/raw/int/protocol/xmlrpc.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + +]> + + +&mode.login; +&mode.postevent; +&mode.editevent; +&mode.editfriendgroups; +&mode.editfriends; +&mode.getevents; +&mode.getfriends; +&mode.friendof; +&mode.getfriendgroups; +&mode.getdaycounts; +&mode.syncitems; +&mode.checkfriends; +&mode.consolecommand; + + diff --git a/livejournal/doc/raw/lj.book/admin/caps_list.xml b/livejournal/doc/raw/lj.book/admin/caps_list.xml new file mode 100755 index 0000000..c07d406 --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/caps_list.xml @@ -0,0 +1,52 @@ + + + Capabilities Classes + + Capabilities Classes +
    + Introduction + + To introduce user limitations as defined on a per site basis, LiveJournal has implemented + the use of capabilities — customizable limits that can be defined én massé, or + split between different user types. + + + Completing the idea of per site definitions, we've implemented a system where + capabilities can be defined in classes, and classes can either be turned on or + off for each account. + + + Capability classes are most effectively used when making distinctions between normal + user accounts and privileged user accounts; for example, on LiveJournal.com, we make + a distinction between normal accounts, early adopter accounts, and + paid accounts, (with a couple of variations on the latter) — the purpose of the + distinction being to give paying members a better incentive to stick around and help fund the site. + +
    +
    + Setting Capabilities + + explains how to initially set the capability defaults, and + how to setup capability classes that you can use to define different account types. + + + If there comes a need where a user's account should change classes, then it is easy to administrate from + the URI /admin/capedit.bml. Simply login as the system account, + and apply (or unapply) the different classes as necessary for a specific user. + + Setting the same capability twice + If two capability classes set the same capability, and an account is defined under both classes, then + the conflicting capability values are compared against each other, and the optimal setting is used + where appropriate. + +
    +
    + Capabilities Reference + + The following is a list of capabilities that you can define per class. + If you have any capabilities that you have defined locally, then they will + be listed here as well. + + &lj.admin.cap_list; +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/admin/console.xml b/livejournal/doc/raw/lj.book/admin/console.xml new file mode 100755 index 0000000..18cd10e --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/console.xml @@ -0,0 +1,50 @@ + + The Administrative Console + + If you would consider BML pages to be the GUI + of LiveJournal, then the administrative console would be the command line interface. + +
    + Taking control of the Console + + The administrative console (or console, for the sake of brevity) is + a text only interface to LiveJournal that allows you to perform certain administrative + tasks not accessibly anywhere else in your installation. The console, located at the + URI /admin/console/ of a working LiveJournal + installation, works very similarly to a DOS or bash + prompt, in that it reads commands and arguments seperated by whitespace. + + Inputting Comands + The first word inputted is the command you would like to perform. Every word after that + is an argument to that command, and whitespace delimits multiple arguments. If an argument + requires a space, such as writing suspension notes, it needs to be wrapped in quotation marks. + If an argument requires spaces and quotation marks, then the quotation marks + can be escaped with a leading backslash, like: \". If + an explicit backslash is required when writing an argument in quotation marks, it can be escaped + with a leading backslash, like \\. + + Using the console to suspend a user + + To cover all points, here is a typical input line that suspends + username with a complex suspension note: + + suspend username "Indefinite suspension \\ might become \"permanent\" \\ harassment and libel" + + +
    +
    + Console Command Reference + + Arguments are defined on a per command basis, and some arguments are required for the command to work. + If you're ever stuck, you can simply type help command + in the console for a short explanation of command. + + + + Included with the installation is a live reference located at the URI + /admin/console/reference.bml + + + &lj.admin.console.ref; +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/admin/create_users.xml b/livejournal/doc/raw/lj.book/admin/create_users.xml new file mode 100755 index 0000000..ccbe61d --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/create_users.xml @@ -0,0 +1,20 @@ + + + Creating Users + + Creating Users + + Once you have your LiveJournal server tuned and tweaked, you're probably going to want to create some users and communitiies. + + + Creating users is relatively simple, and depends on which options you are using in your cgi-bin/ljconfig.pl. + + + If you are not using this file for your setup, then the default options defined in cgi-bin/ljdefaults.pl will be assumed. + + + + + If your service is live, simple visit create.bml in your htdocs/ directory. With this page, you can create as many users as you'd like. + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/admin/creating_users.xml b/livejournal/doc/raw/lj.book/admin/creating_users.xml new file mode 100755 index 0000000..ccc0710 --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/creating_users.xml @@ -0,0 +1,20 @@ + + + Creating Users + + Creating Users + + Once you have your LiveJournal server tuned and tweaked, you're probably going to want to create some users and communitiies. + + + Creating users is relatively simple, and depends on which options you are using in your cgi-bin/ljconfig.pl. + + + If you are not using this file for your setup, then the default options defined in cgi-bin/ljdefaults.pl will be assumed. + + + + + If your service is live, simple visit create.bml in your htdocs/ directory. With this page, you can create as many users as you'd like. + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/admin/index.xml b/livejournal/doc/raw/lj.book/admin/index.xml new file mode 100755 index 0000000..7e49fa6 --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/index.xml @@ -0,0 +1,17 @@ + + Administering a LiveJournal Site + + Part III covers all of the information necessary to fine-tune and run your LiveJournal site. + + &lj.admin.createusers; + &lj.admin.caps; + &lj.admin.privs; + &lj.admin.console; + &lj.admin.sysban; + + diff --git a/livejournal/doc/raw/lj.book/admin/privs.xml b/livejournal/doc/raw/lj.book/admin/privs.xml new file mode 100755 index 0000000..db7e9c8 --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/privs.xml @@ -0,0 +1,29 @@ + + + Administrating Privileges + + Administrating Privileges + + Privileges on LiveJournal are used to delegate responsibilities to other users, + without having to modify access files or setting explicit file permissions on + .bml files. + +
    + Using privs effectively + + All privileges can be administered through the privilege portal, located at the + URI /admin/priv/ in installations of LiveJournal. + To start administrating privs, you should login as the system account you created in + + The script bin/upgrading/make_system.pl creates the system account, + and grants it the admin priv with the argument of all. + . By visiting the /admin/priv portal, you can start + assigning privs either by username or privilege name. + +
    +
    + A list of all Privs + The following is a complete privilege reference. + &lj.admin.privs.ref; +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/admin/sysban.xml b/livejournal/doc/raw/lj.book/admin/sysban.xml new file mode 100755 index 0000000..27906fc --- /dev/null +++ b/livejournal/doc/raw/lj.book/admin/sysban.xml @@ -0,0 +1,55 @@ + + Banning Users + The LiveJournal sysban mechanism provides the means for generic bans on + site functionality given a block type and value. The type is what + is being checked (IP address, email address, etc) and the value is the value which + causes the block to activate. (10.0.0.10, for example) + A tool is available to create and modify bans: $LJHOME/htdocs/admin/sysban.bml. + This tool requires the sysban privilege. + + There are three statushistory types tied to the sysban tool: + + sysban_add + Logs the creation of new bans + + + sysban_mod + Logs the modification of bans + + + sysban_trig + Logs when bans are triggered + + + The most notable of the three is the sysban_trig type. The data it + logs varies depending on the type of ban and the information + available when it was triggered. If a userid is available, it + will be logged and the notes column will contain a short description + of what caused the trigger along with a number of variables that + may be useful in investigation of the situation. + Below are the ban types that exist as of now. More can and will be added + as necessary: + + General + + ip + Blocked from site if IP address matches + + + email + Blocked if email matches. + + /create.bml + Return a fake 503 Service Unavailable message to a user + who tries to create a new account with the given email address. + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/customize/hooks.xml b/livejournal/doc/raw/lj.book/customize/hooks.xml new file mode 100755 index 0000000..4c6e10c --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/hooks.xml @@ -0,0 +1,65 @@ + + Setting Site-Specific Hooks + + + The LiveJournal code provides a number of hooks, which you can use to + alter or extend the functionality of the code, tailored for your own site. + You're free to implement as few or as many as you want. + + If there's a hook you want but don't see, email us at dev@livejournal.com + or file an issue in our + Bug and Project Tracking System + and we'll be more than happy to add it in. + + + + One of the reasons for implementing hooks on LiveJournal came from a + need to make distinctions between account status types, without leaving + a lot of kludge in the code base, and without having to write extensive + code libraries in the ljcom CVS repository. + + + Hooks are code references, subroutines that perform functions or return information + based on objects passed to the subroutine. Some programming knowledge is necessary + to write your own hooks. + + +
    + Writing Hooks + + Hooks are written either in your cgi-bin/ljconfig.pl file, or in a seperate + site-specific library file. Hooks are defined by the function LJ::register_hook(), + which takes two arguments: the name of the hook, and the hook's perl coderef. + + + Most hook coderefs are passed a single hash of various objects as their argument, though there are a few + exceptions. Consult for more information. + + + Sample hook: userinfo_html_by_user + + To give you an idea of how a hook is set up, a smaller hook is sampled below: + + {'ret'}; + my $u = $o->{'u'}; + return unless (LJ::get_cap($u, "normal")); + $$r .= "⋆"; + });]]> + + $o is the argument hash that is passed to the hook's subroutine, + and consists of the scalar reference member $o->{'r'} and the user object + member $o->{'u'}. The subroutine then checks to see if the user + is part of the capability class normal, and if so it will pass the + HTML image directive as the scalar reference. Now when someone loads + a user information page for a normal user, a small star will appear + next to their username and userid. + + +
    +
    + Hooks Reference + &lj.customize.hooks.ref; +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/customize/images.xml b/livejournal/doc/raw/lj.book/customize/images.xml new file mode 100755 index 0000000..52004ea --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/images.xml @@ -0,0 +1,18 @@ + + + Using your own images and icons +
    + Using <filename>imageconf.pl</filename> + + LiveJournal uses a standard set of icons for specific pages that are distributed through the /img directory, and handles the configuration for these images in the file: cgi-bin/imageconf.pl. + Each image is configured as an associative array in perl, setup with attributes for each file. + (FIXME - this needs a lot of work.) + + + cgi-bin/imageconf.pl is provided. Don't + change that. But go ahead and add a new file, + imageconf-local.txt beside it in the same + format, which imageconf.pl will find and use. + +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/customize/index.xml b/livejournal/doc/raw/lj.book/customize/index.xml new file mode 100755 index 0000000..f7636dd --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/index.xml @@ -0,0 +1,40 @@ + + Customizing Your Installation + + + Unless you're helping on the LiveJournal development team, + you're probably running the LiveJournal Server for your own + purposes and will want to customize its appearance, behavior, + limits, and other settings to suit your needs. The next couple + of chapters have been written with that aim in mind. + + + More importantly, however, the following sections tell you how + to customize the installation in the supported way. Although + you're welcome to just hack random parts up until it's working + how you want it too, you'll run into trouble later when you try + to stay in sync with the latest LiveJournal code. + + + By following these instructions, your life will be much easier, + as all our tools assume you are doing things this way. If you + end up not being able to change something, post in the + lj_everywhere community on LiveJournal.com and ask for help. + We'll either tell you the right way to do it, or add hooks/options + such that you can. + + + &lj.customize.local_cvs; + &lj.customize.images; + &lj.customize.text; + &lj.customize.limits; + &lj.customize.hooks; + &lj.customize.layout; + &lj.customize.tasks; + + diff --git a/livejournal/doc/raw/lj.book/customize/layout.xml b/livejournal/doc/raw/lj.book/customize/layout.xml new file mode 100755 index 0000000..e680989 --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/layout.xml @@ -0,0 +1,206 @@ + + <abbrev>BML</abbrev> Schemes + Changing your site's layout + + BML is the language used to serve pages to users that they don't manage + themselves. To get an idea of what BMLis, the following is a quote from the + BML manual: +
    + The Better Markup Language + + BML is a server-side markup language that lets you define your own + BML blocks and use them as templates within your BML + pages. Your templates don't even have to be static. Because BML pages are + converted to HTML on the server when users request them, this also enables + you to embed live code within your BML pages, just like a + CGI script. + +
    +
    + With LiveJournal, we used BML because it makes it easier for us to write the + layouts that comprise LiveJournal, without requiring frequent changes or rewrites on our part + to come up with a customized look and feel. In the next section you will read how to make the + necessary additions to the LiveJournal schemes to tailor your LiveJournal installation to your + exact needs. + + For more information on BML, please refer to . +
    + Writing a <abbrev>BML</abbrev> Scheme + + BML is essentially a simple macro language. Macros are called + templates in BML. Templates are defined in + lookup files and are invoked in + BML files. Templates accept parameters and are divided into several types + according to how parameters are transmitted and how the definition of the template is able to make + use of them. Definitions of templates are essentially chunks of HTML with + potentially more recursive BML template invocations inside them. + + For LiveJournal, the most common templates are defined in the file + $LJHOME/cgi-bin/bml/scheme/global.look; all other + schemes either replace all of the templates, or inherit whichever + is not replaced. + + To write your own scheme, all you have to do is write your own BML + lookup file that use the same templates as $LJHOME/cgi-bin/bml/global.look. + Then, implementing a new scheme becomes pretty painless: + Creating a new <abbrev>BML</abbrev> scheme: <replaceable>foo</replaceable>: + + Create a new file under $LJHOME/cgi-bin/bml/scheme, labelled + after the scheme name (foo). For example: + $LJHOME/cgi-bin/bml/scheme/foo.look. + This file should contain all of the BML directives you've written for your unique layout. + The first line in this file should be _parent=>global.look. + + + If you don't have a local BML configuration file (_config-local.bml) + in your $LJHOME/htdocs/ directory, you should create one now. + The contents of that file should look like: + + Sample <filename>_config-local.bml</filename> + DefaultScheme foo + + + + Manually restart the apache process. + + + + After you've written your scheme, consider adding it to the array in , so that + your users can use their preferred scheme. + +
    +
    + <abbrev>BML</abbrev> Template Reference + For reference, here are the most commonly used BML templates in the LiveJournal repository: + + Pre-configured + The following are BML templates that are set from configuration options in $LJHOME/cgi-bin/ljconfig.pl. + All templates here are defined as S (static). + DOMAIN + IMGPREFIX + STATPREFIX + SITEROOT + SITENAME + ADMIN_EMAIL + SUPPORT_EMAIL + + The following BML templates are defined in $LJHOME/cgi-bin/bml/scheme/global.look + and are available in every scheme. + + Global + + SECURITYPRIVATE + HTML image sourcing from /img/icon_private.gif + + + SECURITYPROTECTED + HTML image sourcing from /img/icon_protected.gif + + + LJUSER + Given a username, it creates a properly formated LiveJournal username reference + + + LJCOMM + Given a community username, it creates a properly formatted LiveJournal community username reference + + + LJUSERF + Same as LJUSER, except that the link to the userinfo page includes the additional user information + + + HELP + Given a URL, this provides a small link with the caption help + + + INERR + Displays an error message in an easily identifiable manner (bold red text) + + + NEEDLOGIN + A small blurb that's included on pages where the user is not logged in and is required to be + + + BADINPUT + An error message that displays when there is an encoding problem with the user's browser + + + REQUIREPOST + An error message explaining that certain user actions require POSTing information through an HTML form, rather than manually GETting the page + + + LOAD_PAGE_INFO + Initializes and populates a perl array that is used to create a sidebar of links along a page layout + + + H1 + Top level header on a page + + + H2 + Sub level header on a page + + + P + Generic HTML paragraph wrapper + + + STANDOUT + Given a block of text, this template tries grab the user's attention by using different text and background colors + + + BADCONTENT + An error message that displays when a problem (that the user can fix) has occurred during a request + + + DE + A template that de-emphasizes text + + + EMCOLOREMCOLORLITEHOTCOLOR + Various emphasis colors + + + SCREENEDBARCOLOR + A color that is used to highlight screened comments in comment threads + + + CHOICE + Given 3 arguments (a URL, a title, and an explanatory blurb), this template fashions an item to be used in a CHOICES list + + + CHOICES + Given 2 arguments, this template tries to construct a side by side list of options and appropriate links + + + PAGE + This template is the BML template that governs the look of the entire scheme, and takes 4 arguments: + + + title + The page title + + + head + Page-specific elements that belong in a HTML head + + + bodyopts + Additional attributes for the HTML body element + + + body + The main content of the page + + + + + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/customize/limits.xml b/livejournal/doc/raw/lj.book/customize/limits.xml new file mode 100755 index 0000000..16a45e4 --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/limits.xml @@ -0,0 +1,6 @@ + + Setting your own Limits + + (FIXME - discuss the necessity of setting good connection/throttle settings) + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/customize/local_cvs.xml b/livejournal/doc/raw/lj.book/customize/local_cvs.xml new file mode 100755 index 0000000..1579f81 --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/local_cvs.xml @@ -0,0 +1,82 @@ + + Using your own <abbrev>CVS</abbrev> directory + + CVS is a version control system for source code. We don't care + whether or not you actually use it to control your site-local + modifications. However, even if you don't, it's still important + you put your modifications under a directory in $LJHOME/cvs. + + + At this point, you already have a directory named + cvs underneath your $LJHOME + directory. Further, that directory already has under it a directory called livejournal, + which holds the general files. + + + What you want to do now is make a directory that holds the + local files. The LiveJournal tools look for your + files in a directory beside livejournal named + local, but local can + actually be a symlink to your real directory. + + LiveJournal.com uses the directory name + ljcom for its site-local modifications, so + the livejournal directory is entirely free + of LiveJournal.com-specific code. If you're helping with + LiveJournal.com development, you'll want to symlink ljcom to + local. + + + +
    + <application>cvsreport.pl</application>: Adding & Overlaying + + In $LJHOME/bin there's a tool named + cvsreport.pl which manages (among other + things) merging together the general files and your site-local + files into the live area under $LJHOME. + + + The command you'll need most of the time is: + +$ cvsreport.pl -c -s + + -c is short for --cvsonly + (only copies from the cvs directory back to the live area, not + vice-versa) and -s is short for --sync + (which means actually do the copying, don't just print out what it would've done, + which is the default without -s). + + + So, say you want to override the provided + htdocs/index.bml file. Create the + htdocs under + $LJHOME/cvs/local and put a + index.bml file in it, then run + cvsreport.pl -c -s and you're set. + + + More commonly, you'll be adding new files, rather than replacing + provided ones. In general, you should never really need to + replace files, since you should already be able to change all + the text, images, and layout of any given page. Replacing a + file would mean duplicating functionality, and that's bad. + + + One popular strategy with the general code libraries is to look + for a similarly named file with -local in it + and load that also. That way you inherit all the functionality + that's provided, and change only what you want. When general + changes, you don't have to update right away... you can change + things later if you want, or keep the newly added stuff as it + was given to you. + +
    + +
    + diff --git a/livejournal/doc/raw/lj.book/customize/tasks.xml b/livejournal/doc/raw/lj.book/customize/tasks.xml new file mode 100755 index 0000000..3fcc498 --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/tasks.xml @@ -0,0 +1,12 @@ + + Running your own Maintanence Tasks + + (FIXME - describe the different tasks from ljmaint.pl, etc... note: build.pl should auto-extract the taskinfo.txt text and put it in here somewhere?) + + + bin/maint/taskinfo.txt is provided. Don't + change that. But go ahead and add a new file, + taskinfo-local.txt beside it in the same + format, which ljmaint.pl will find and use. + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/customize/text.xml b/livejournal/doc/raw/lj.book/customize/text.xml new file mode 100755 index 0000000..7a9f2d6 --- /dev/null +++ b/livejournal/doc/raw/lj.book/customize/text.xml @@ -0,0 +1,48 @@ + + Customizing <abbrev>LJ</abbrev>'s Content + + (FIXME - describe the /translate/ system) + +
    + Using site-specific text + + To create your own site-specific language file, all you have to do is select which strings you'd like to override from + $LJHOME/bin/upgrading/en.dat and put them in a new file: en_LOCAL.dat + Then, you add the language to your database using the steps below: + Creating a new site-specific language file: <replaceable>en_LOCAL</replaceable>: + + Create a new file under $LJHOME/bin/upgrading/, labelled + en_LOCAL.dat. This file should contain all of the text that you'd like to override from + $LJHOME/bin/upgrading/en.dat. + + + If you don't have a local BML configuration file (_config-local.bml) + in your $LJHOME/htdocs/ directory, you should create one now. + Add the following line to your local configuration file: + DefaultLanguage en_LOCAL + + + If you don't have a local language directive file ($LJHOME/bin/upgrading/text-local.dat) + create one now. Add the following lines to your local language file: + +# EnglishLOCAL is child of English for general domain: +lang:100:en_LOCAL:English (Local):sim:en +langdomain:en_LOCAL:general + +# EnglishLOCAL is root of FAQ: +langdomain:en_LOCAL:faq:1 + + + + Run $LJHOME/bin/upgrading/texttool.pl . + + + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/features/index.xml b/livejournal/doc/raw/lj.book/features/index.xml new file mode 100755 index 0000000..d9fac66 --- /dev/null +++ b/livejournal/doc/raw/lj.book/features/index.xml @@ -0,0 +1,10 @@ + + LiveJournal Features + + + Part IV gives a review of all of the interesting features LiveJournal has to offer you. + + + &lj.features.support; + &lj.features.topics; + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/features/support.xml b/livejournal/doc/raw/lj.book/features/support.xml new file mode 100755 index 0000000..e54c564 --- /dev/null +++ b/livejournal/doc/raw/lj.book/features/support.xml @@ -0,0 +1,20 @@ + + + Internal Support System + + Internal Support System +
    + Introduction + + Packaged with every LiveJournal distribution is an internal support center; a set of pages that logs user requests and assigns them a ticket, so that they can return (FIX) + + + The support system was written and tailors to 3 types of users: + + RequesterThe user who files the support request + VolunteerThe user who answers the question as best as they can + AdminThe user who approves screened answers and closes old/dead requests + + +
    +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/features/topics.xml b/livejournal/doc/raw/lj.book/features/topics.xml new file mode 100755 index 0000000..57f8f40 --- /dev/null +++ b/livejournal/doc/raw/lj.book/features/topics.xml @@ -0,0 +1,9 @@ + + + Topics System + + Topics System + + TODO: Describe the packaged topics system + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/index.xml b/livejournal/doc/raw/lj.book/index.xml new file mode 100755 index 0000000..967859c --- /dev/null +++ b/livejournal/doc/raw/lj.book/index.xml @@ -0,0 +1,27 @@ + + + LiveJournal Server + LiveJournal Server Manual Version 1.0 + + + This part of the documentation covers installation, + customization, and maintenance of a LiveJournal server. + + + ©right; + &legalnotice; + + &lj.preface; + &lj.intro.index; + &lj.install.index; + &lj.customize.index; + &lj.admin.index; + &lj.features.index; + &appx.gfdl; + + diff --git a/livejournal/doc/raw/lj.book/install/apache_setup.xml b/livejournal/doc/raw/lj.book/install/apache_setup.xml new file mode 100755 index 0000000..daf96c4 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/apache_setup.xml @@ -0,0 +1,117 @@ + + Apache + + Apache is the most popular HTTP server software used today, and it's completely free. + We use Apache for our projects because there is simply no equivalent. In this chapter we'll + briefly explain how to setup and configure an Apache installation. + +
    + Installation +
    + mod_perl + + LiveJournal in the past has been server API agnostic, working on + either FastCGI or mod_perl, but we've dropped FastCGI support, as + there's really no need to maintain it anymore. LiveJournal now solely + requires mod_perl; seeing as how it's everywhere and well supported, + and you might already have it on your machine. If not, you can read up + on the official installation docs located at + + + + We've found that more people have success when mod_perl is statically + linked, rather than using a DSO. + + Consult + + mod_perl Installation User Guide: When DSO Can Be Used + for more information. + + + Debian + Typically, if you already have a working apache installation in Debian + and would like to install mod_perl support, then installing the package + libapache-mod-perl should suit your needs. Otherwise, + you should install the package apache-perl. + +
    +
    + Apache suEXEC Support + + If you want the LiveJournal code to run as a user other than + what your webserver runs as, then you'll need suEXEC + Official + Apache suEXEC documentation support in + Apache. You're free to figure that out yourself. We'll assume + your webserver is running as user lj, + though it doesn't have to run as any certain user to work. + + + In fact, the LiveJournal code never writes to disk, so as long + as it can write to the database (which is essential, obviously), + you can run the code as any user, including + nobody or + www-data, both + of which are common in out-of-the-box configurations. + +
    +
    + Virtual Hosts + + You can run the LiveJournal code inside or outside of a + <VirtualHost> section in Apache's + httpd.conf file. However, make note that you + can't (yet) have two VirtualHosts running parallel copies of the + code. In the future we'll fix that, but for now if you really + need two installations on the same machine, you'll need to run + two sets of Apache processes, listening on different ports. + +
    +
    +
    + Example <literal>httpd.conf</literal> + + + + This will work by itself (assuming mod_perl statically linked), + or you can just tack on parts to your existing config. + + /home/lj is only an example directory. You'll want to use the same directory used in . + + If you'd like, you can put those last three lines in a VirtualHost block. + + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/install/finishing.xml b/livejournal/doc/raw/lj.book/install/finishing.xml new file mode 100755 index 0000000..f623cfd --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/finishing.xml @@ -0,0 +1,52 @@ + + Finishing Up + + You should now just about have a working LiveJournal installation. + There are many things you can still do, but all are outside the scope of this document. + + + Configuration check + + To check that everything is setup okay, you should run the provided configuration checking tool, + located at $LJHOME/bin/checkconfig.pl. checkconfig.pl + will check for missing perl modules, attempt to connect to your database, and do other checks to ensure everything will work smoothly. + + + + Start things up + If you haven't restarted Apache, you'll want to do that now: + +# apachectl stop +# apachectl start + + Note that doing a "graceful" or "restart" is not guaranteed to work. The LiveJournal code + doesn't implement any mod_perl restart handlers, and weird things have been reported to happen + using apachectl restart. + + + + The system user + + To administrate your site properly, you will need to create the system user that'll have + privileges to give privileges to other users: + + +$ $LJHOME/bin/upgrading/make_system.pl + + It'll prompt you for the password to use for the system account and then sets it all up. + You now have the ability to login to your LJ site as user system with the password + you set and then grant priviledges from the admin section to other users: + + http://your-lj-server/admin/priv/ + + + If you have any questions, join the "lj_everywhere" + community on LiveJournal.com and post your questions. We'd love to help you out. + + + diff --git a/livejournal/doc/raw/lj.book/install/general_setup.xml b/livejournal/doc/raw/lj.book/install/general_setup.xml new file mode 100755 index 0000000..7b706c3 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/general_setup.xml @@ -0,0 +1,128 @@ + + General Setup + +
    + $LJHOME Environment Variable + + Be aware that nearly all LiveJournal code depends on the $LJHOME + environment variable being set to the top-level directory that LiveJournal is installed at. + + + has the necessary directives to make + sure the web code always has $LJHOME set, but if you're running LJ maintenance + commands from a terminal, you'll need to make sure $LJHOME is set + for yourself. + + + For example, we'll assume that you've installed LiveJournal on an operating system + using the Bourne Shell: The easiest way to set $LJHOME is to put + the following in your ~/.bash_profile: + + +LJHOME=/home/lj; export LJHOME + + + To test that it's set: + + +$ . ~/.bash_profile +$ echo $LJHOME + + + If the above was successful, it should print out /home/lj + (or whatever the value of $LJHOME may be). + + + + Other shells + + If you use another shell interface, you might be able to see what it reads on + start-up by looking for the file: ~/.profile. Please + refer to the documentation provided with your shell, which can usually be + found by typing: + + +$ help + + +
    +
    + Installing the files + + The typical directory to install LiveJournal is + /home/lj, but it is not a requirement at + all. To ease documentation, we'll assume that you'll want to + install in that directory. We'll also assume you'll be using + user lj, but that also doesn't matter at all. + Feel free to install wherever and as whoever … there shouldn't + be any problems. + + + Prerequisite: <envar>$LJHOME</envar> + + Before you install using either method, you should create the directory + where your LiveJournal installation will reside. This needs to be the same + directory that the environment variable $LJHOME is set to, + otherwise your installation will not work properly. Consult + for more information on setting $LJHOME. + + +Creating the <envar>$LJHOME</envar> directory: +# mkdir /home/lj +# chown lj.lj /home/lj + + + + + Using Tarballs + + LiveJournal maintains the server code in tar.gz (tarball) + format, which can be downloaded from: . + The tarballs are labelled by date, so be sure to grab the latest one. + + + Untar the tarball from the $LJHOME directory, and then run the provided + installation script, bootstrap.pl. + + Tarball Install: +$ cd $LJHOME +$ tar zxvf LiveJournal-YYYYMMDDNN.tar.gz +$ ./bootstrap.pl + + + + Using <abbrev>CVS</abbrev> + + Bleeding edge releases of the code can be found in CVS at the CVS + server: cvs.livejournal.org. + + + Installing and updating LiveJournal from CVS is not guaranteed as stable as tarball releases. + If you need a more stable release, you're better off using the packaged tarballs as mentioned above. + + CVS Install: +$ mkdir $LJHOME/cvs +$ cd $LJHOME/cvs +$ cvs -z3 -d:pserver:anonymous@cvs.livejournal.org:/home/cvslj co livejournal +$ cvs -z3 -d:pserver:anonymous@danga.com:/home/cvspub co wcmtools bml +$ wcmtools/bin/multicvs.pl --conf=livejournal/cvs/multicvs.conf --init + + + That last command will copy everything from the CVS directory + over to $LJHOME, the live area. + + + Having two copies of the code laying around may not make sense + now, but it will later when we write the docs to explain how + to run a heavily-customized version of the site and still stay + up-to-date with the mainstream CVS. (FIXME: write/link that section) + + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/install/index.xml b/livejournal/doc/raw/lj.book/install/index.xml new file mode 100755 index 0000000..c648fcb --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/index.xml @@ -0,0 +1,35 @@ + + LiveJournal Installation + + + The following chapters cover the basics of installing LiveJournal, and is geared towards LiveJournal being + installed on any operating system that resembles unix. Throughout this part we'll include installation tips + for users of Debian GNU/Linux, because this is our operating system + of choice. + + + We do assume that you are familiar, at least somewhat, with the technologies covered in this manual, because + although it's certainly not necessary to be an expert to install LiveJournal, it helps to know the concepts + and tasks involved in this kind of undertaking. + + + If you have any questions, or encounter any problems not easily remedied, feel free to join the + LiveJournal Everywhere! + Community. + + + &lj.install.reqs; + &lj.install.perl_setup; + &lj.install.general_setup; + &lj.install.apache_setup; + &lj.install.ljconfig; + &lj.install.mysql_setup; + &lj.install.schedule_tasks; + &lj.install.finishing; + + diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.caps.xml b/livejournal/doc/raw/lj.book/install/ljconfig.caps.xml new file mode 100755 index 0000000..3790a8f --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.caps.xml @@ -0,0 +1,68 @@ +
    + Setting Capabilities + + Capabilities are used to define limits that are imposed on user accounts. + For more information, please read . + + + Consult for reference when defining capabilities. + + + No matter what your setup is, %LJ::CAP_DEF should always be defined, + set with sane limits per capability. + + + Sample <literal>%LJ::CAP_DEF</literal> + + 5, + 'userpics' => 1, + 'checkfriends_interval' => 60, + 'checkfriends' => 1, + 'styles' => 0, + 'todomax' => 25, + 'todosec' => 0, + 'friendsviewupdate' => 30, + 'findsim' => 1, +);]]> + + + + Classes + Classes are defined as hashes under the single hash %LJ::CAP. + The keys of %LJ::CAP are the 16 different bits (0-15). The keys of those hashrefs are the capability names, and + the values are the capability settings. + + + Sample <literal>%LJ::CAP</literal> + + { # 0x01 + '_name' => 'new user', + 'userpics' => 1, + }, + '1' => { # 0x02 + '_name' => 'free user', + 'userpics' => 3, + }, + '2' => { # 0x04 + '_name' => 'paid user', + 'styles' => 1, + 'makepoll' => 1, + 'userpics' => 10, + 'paid' => 1, + 'useremail' => 1, + 'textmessaging' => 1, + }, + '3' => { # 0x08 + '_name' => 'permanent account', + 'paid' => 1, + 'useremail' => 1, + }, +);]]> + + + +
    diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.dbinfo.xml b/livejournal/doc/raw/lj.book/install/ljconfig.dbinfo.xml new file mode 100755 index 0000000..deba164 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.dbinfo.xml @@ -0,0 +1,46 @@ +
    + + Configuring <literal>%LJ::DBINFO</literal> + + Configuring <literal>%LJ::DBINFO</literal> + + %LJ::DBINFO is a hash that contains the necessary information for LiveJournal to connect to your database. + For installations that require more than one database server, the directives to define each cluster database are also defined here. + + Connection keys + %LJ::DBINFO requires a master key that is labelled 'master', and also requires the correct address for connection to the database itself. + If you're using a TCP based connection, you can specify a host key with the value of the location of the server, and a port key for the database port (typically 3306). + If instead you're using a socket based connection, you can specify a sock key with the value set to the socket file. + Specify a user key for your database username, and a password key for your database password. + If you used a different database name than the suggested livejournal, you can specify a dbname key with the value of the database name. + + Roles + The role key in %LJ::DBINFO is a hash that sets different role keys to the current configuration with boolean values. + Roles are basically tasks assigned to the configuration. For example, to set up a server that will host your directory (which can get pretty intensive with a fair amount of users), you would do the following: + { + 'directory' => 1, +},]]> + + + + Sample <literal role="variable">%LJ::DBINFO</literal> hash + { + 'host' => "localhost", + 'port' => 3306, + # or, leave out host/port and use a socket to connect: + #'sock' => "/var/run/mysqld.sock"; + # optional dbname, if not "livejournal": + #'dbname' => 'livejournal', + 'user' => 'lj', + 'pass' => 'ljpass', + 'role' => { + 'cluster1' => 1, + }, }, +);]]> + + + That's the basic configuration for an installation with only one database server. (FIXME: add link to new section on configuring a site with many database servers) + +
    \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.disabled.xml b/livejournal/doc/raw/lj.book/install/ljconfig.disabled.xml new file mode 100755 index 0000000..f3d56c7 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.disabled.xml @@ -0,0 +1,51 @@ +
    + <varname>%LJ::DISABLED</varname> + %LJ::DISABLED is a hash that defines parts of the installation that + are CPU or database intensive as active or inactive. + This following list briefly explains each option. + + Optional Features + + interests-findsim + The Find Users by Similar Interests feature. + + + directory + The user directory, which houses some of the largest and slowest database queries. + + + stats-recentupdates + Logs the most recent updates to the stats page. + + + stats-newjournals + Logs the most recently created journals to the stats page. + + + show-talkleft + Show the received and posted comment counts for each account on the userinfo.bml page. + + + memories + Show the Add to Memories button on comment pages. + + + topicdir + The topic directory, which hasn't yet been rewritten to support clustered installations. + + + tellafriend + Show the Tell a Friend button on comment pages. + + + clientversionlog + Show the client usage statistics on the stats.bml page. + + +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.helpurls.xml b/livejournal/doc/raw/lj.book/install/ljconfig.helpurls.xml new file mode 100755 index 0000000..1f3b9cd --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.helpurls.xml @@ -0,0 +1,45 @@ +
    + <varname>%LJ::HELPURLS</varname> + + %LJ::HELPURLS is a hash that defines URLs to + supplemental documentation regarding a specific feature or widget in the LiveJournal interface. + The following list describes the suggested content of each URL. + + + Help URL Keys & Values + + security + Explains the different security settings available for posts + + + noautoformat + Explains how the Don't automatically format option works + + + userpics + Explains the differing amount of userpics available to each capability class + + + iplogging + Explains what the IP Logging feature is, and what it is useful for + + + s2propoff + Explains why certain S2 settings might not be available to certain capability classes + + + userpic_inactive + Explains why a userpic may be inactive for, and how to make the userpic active again + + + textmessaging_about + Explains what the text messaging feature is and how it works + + +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.vars.xml b/livejournal/doc/raw/lj.book/install/ljconfig.vars.xml new file mode 100755 index 0000000..4a1e09f --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.vars.xml @@ -0,0 +1,11 @@ +
    + <literal>$LJ::</literal> Variables + + Each $LJ:: variable is explained below. There are two types: + user-configurable ones and those that are automatically set and interesting only + to people extending the LiveJournal code. + + + &lj.install.ljconfig.vars.gen; + +
    diff --git a/livejournal/doc/raw/lj.book/install/ljconfig.xml b/livejournal/doc/raw/lj.book/install/ljconfig.xml new file mode 100755 index 0000000..5895ff2 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/ljconfig.xml @@ -0,0 +1,34 @@ + + + Configuring ljconfig.pl + + Configuring ljconfig.pl + + You need to make a LiveJournal configuration file. There's an + example ljconfig.pl in the doc directory by the + name of "ljconfig.pl.txt". You need to copy + this file to cgi-bin/ljconfig.pl and then + edit it to suit your needs. + + + + $ cd /home/lj + $ cp doc/ljconfig.pl.txt cgi-bin/ljconfig.pl + + + The reason it's not there already is so that future upgrades don't + destroy your configuration. The end of + ljconfig.pl reads in + ljdefaults.pl so that if we add new options, + ljdefaults.pl will be updated and will set + sane defaults. After an upgrade you want to glance at + ljdefaults.pl (or the original + doc/ljconfig.pl.txt) and see if there are any + new options you feel like setting. + + &lj.install.ljconfig.vars; + &lj.install.ljconfig.helpurls; + &lj.install.ljconfig.disabled; + &lj.install.ljconfig.dbinfo; + &lj.install.ljconfig.caps; + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/install/mysql_setup.xml b/livejournal/doc/raw/lj.book/install/mysql_setup.xml new file mode 100755 index 0000000..8f2b847 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/mysql_setup.xml @@ -0,0 +1,72 @@ + + MySQL + + There are a few simple reasons why we chose MySQL when picking a database backend for LiveJournal: + It's fast, + free, + stable, + secure, and well supported + by a large community of users. In this chapter we'll deal with installing and setting up MySQL on + your server, then we'll show you how to populate your installation with the required base data. + +
    + Install MySQL + + LiveJournal requires a MySQL install of at least version 3.23.x, + but highly recommends installing the latest stable release that is + available, expecially if you're going to need clustering and + replication abilities. + + + MySQL offers binaries for many operating aystems, including Win32 + and several different flavors of Unix. + Installations on any of these systems should be fairly easy, as + most offer a simple installation program that guides you through + setup. + + Debian + The MySQL server package for Debian is mysql-server. + +
    +
    + Create the LiveJournal Database + + Login to MySQL as the root MySQL user and create the database that + will hold the LiveJournal data: + + +$ mysql -uroot -p +mysql> CREATE DATABASE livejournal; +mysql> GRANT ALL PRIVILEGES ON livejournal.* TO + > lj@'localhost' IDENTIFIED BY 'ljpass'; + + + If you know what you're doing, you can set this up however you + like. You tell LiveJournal how to connect to its database server(s) + in your ljconfig.pl, as + detailed in: . + +
    +
    + Populate the Database + + In order to use your site, you're going to need to populate your MySQL + database with the required information to get the service started. + + +$ cd $LJHOME +$ bin/upgrading/update-db.pl --runsql --populate +$ bin/upgrading/texttool.pl load + + + That'll bring your database schema up-to-date and populate it with any + look-up data it needs. + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/install/perl_setup.xml b/livejournal/doc/raw/lj.book/install/perl_setup.xml new file mode 100755 index 0000000..81e7c6c --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/perl_setup.xml @@ -0,0 +1,77 @@ + + Perl + + The Perl motto is There is more than one way to do it and the three principles for any + programmer are Laziness, Impatience, & Hubris, according to the Perl manual. On top of that, Perl is + well suited for any purpose, and. Why not use Perl? Anyways, in this chapter we'll briefly cover a Perl installation, + and then we'll show you which Perl modules are required for a working LiveJournal installation. + +
    + Installing Perl + + Perl offers distributions for many operating systems, including Win32 and + almost all of the different flavors of Unix. Installations + on any of these systems should be fairly easy, as most offer a simple + installation program that guides you through setup. + + + The complete Perl documentation is included with every Perl install, so if + you have any Perl specific questions, you might want to refer to the + specific documentation first. As quoted from the Perl FAQs: The + complete Perl documentation is available with the Perl distribution. If you + have Perl installed locally, you probably have the documentation installed + as well: type man perl if you're on a system resembling Unix. This will lead + you to other important man pages, including how to set your $MANPATH. If you're + not on a Unix system, access to the documentation will be different; for + example, it might be only in HTML format. But all proper Perl installations + have fully-accessible documentation. + + Consult + Obtaining and Learning about Perl (perlfaq2) + + + Debian + If you're using Debian, Perl should already be installed. If not, the required package is + simply perl + +
    +
    + Installing Perl Modules + + LiveJournal requires several Perl modules to be installed. Installing these + modules requires a fully working perl and C development environment + (including a C compiler and make tool). + + + Some modules such as GD and Compress::Zlib require certain C libraries to be pre-installed + on your machine in order to work. Please read the author-provided README files for each + module before proceeding further. + + &lj.install.perl.module.list; + + + There used to be a few custom LJ:: modules that + needed installing. Those no longer need to be installed on the system, + as LJ uses them right out of /cgi-bin/* instead. + If by chance you have those old LJ modules installed, it's best to go + remove them since Perl will prefer system-level ones over the (newer) + local ones. + + + + To ensure that you have installed the necessary modules, be sure to + run the included tool: $LJHOME/bin/checkconfig.pl. + If checkconfig.pl doesn't detect all of the + required modules, it will tell you which ones you are missing. Note that this tool will + fail after checking for modules, because it will also check for a database connection, which + hasn't been set up yet. This will be fixed later when we add options to + checkconfig.pl to detect for specific sections of installation. + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/install/reqs.xml b/livejournal/doc/raw/lj.book/install/reqs.xml new file mode 100755 index 0000000..4e3f448 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/reqs.xml @@ -0,0 +1,46 @@ + + Requirements + Software + The main software components you need for a working LiveJournal installation + are as follows (the recommended version is noted): + + + Perl + Version 5.6.1 + + + MySQL + Version 3.23.57 + + + Apache + Version 1.3.28 + + + mod_perl + Version 1.28 + + + + Apache 2 & mod_perl 2 + At this time, LiveJournal has not been ported to & will not work with Apache 2 & mod_perl 2. + + Perl Module Dependencies + A complete list of modules need to run a LiveJournal installation can be found at . + Some modules such as GD and Compress::Zlib require certain system libraries to be pre-installed + on your machine in order to work. The author-provided README files for perl modules explain what is necessary. + + Hardware + There are no specific hardware requirements for a LiveJournal installation, but Apache/mod_perl + and MySQL can utilize a lot of memory very quickly. Determining the right amount of processor + speed, storage space, and RAM depends on how busy your LiveJournal installation will be. A + simple rule of thumb to remember is that posts and comments drive site traffic, not necessarily the presence + of more users. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/install/schedule_tasks.xml b/livejournal/doc/raw/lj.book/install/schedule_tasks.xml new file mode 100755 index 0000000..9fe8665 --- /dev/null +++ b/livejournal/doc/raw/lj.book/install/schedule_tasks.xml @@ -0,0 +1,64 @@ + + Scheduling Maintenence tasks + + From the LiveJournal user account (or whatever user is running LJ), you need to + install some crontabs. These are periodic commands that run and manage your + LiveJournal installation. + + +$ crontab -e + + + This will bring up either your $EDITOR, or vi. + If you want to set your editor explicitly, do: + +$ EDITOR=pico crontab -e + + + + + + Now, enter the following stuff between the dotted lines below. Not all of it is necessary. + See the comments below. The LJHOME= line is required. See the section + above about how the $LJHOME environment + variable is required everywhere. This is another place. + + +/dev/null + +# Optional, if you want birthday mail, and the random user feature: +# (you can remove parts) +5 1 * * * /home/lj/bin/ljmaint.pl bdaymail build_randomuserset >/dev/null + +# If you want statistics: +30 1 * * * /home/lj/bin/ljmaint.pl genstats genstatspics genstats_size >/dev/null +5 2 * * 0 /home/lj/bin/ljmaint.pl genstats_weekly > /dev/null + +# Various tasks +15 1 * * * /home/lj/bin/ljmaint.pl joinmail > /dev/null +30 * * * * /home/lj/bin/ljmaint.pl synsuck > /dev/null +5 2 * * 0 /home/lj/bin/ljmaint.pl memeclean > /dev/null + +# If you're running a high-load site with $LJ::BUFFER_QUERIES on, +# there's another one to install: +*/5 * * * * /home/lj/bin/qbufferd.pl >/dev/null +]]> + + + If query buffering is off, you can still run that, but it's not needed. + Packagers should make their packages install it, since it doesn't hurt if it's + running and not used. It'll die off right away if it realizes it's not needed. + Otherwise it'll start up in the background and run every 10 seconds or so. + Future startups by cron will only make sure it hasn't died (like if the database dies). + + + diff --git a/livejournal/doc/raw/lj.book/intro/goat.xml b/livejournal/doc/raw/lj.book/intro/goat.xml new file mode 100755 index 0000000..472d2c3 --- /dev/null +++ b/livejournal/doc/raw/lj.book/intro/goat.xml @@ -0,0 +1,32 @@ + + Frank the Goat + + So what's the story behind the goat? + + + Back when Brad was living in the dorms and was also still running + FreeVote.com + FreeVote is currently run by one of Brad's friends. + his roommate Eli and him got bored and decided to make some joke ads to put up + on FreeVote.com to advertise LiveJournal.com. + + + Those original 8 banners, as much as they sucked, are archived for historical + reasons at . + + + After the first four they'd both run out of ideas and one of them just spouted out, + LiveJournal.com... because goats are cool. It made no sense, so it was perfect! + Then Brad went and found a picture of a goat. That goat then became the unofficial LiveJournal mascot. + + + So basically, the goat means nothing. But he's so damn cool, and + uber sexy. + + + diff --git a/livejournal/doc/raw/lj.book/intro/index.xml b/livejournal/doc/raw/lj.book/intro/index.xml new file mode 100755 index 0000000..8b494b4 --- /dev/null +++ b/livejournal/doc/raw/lj.book/intro/index.xml @@ -0,0 +1,21 @@ + + Introduction to LiveJournal + + + Part I takes a look at the system that is LiveJournal, and how it can be used to create successful on-line communitites. + + + In addition, we offer a brief history on the actual LiveJournal site: () + + + &lj.intro.what_is; + &lj.intro.story; + &lj.intro.why; + &lj.intro.goat; + + \ No newline at end of file diff --git a/livejournal/doc/raw/lj.book/intro/story.xml b/livejournal/doc/raw/lj.book/intro/story.xml new file mode 100755 index 0000000..6bae750 --- /dev/null +++ b/livejournal/doc/raw/lj.book/intro/story.xml @@ -0,0 +1,26 @@ + + The Story Behind LiveJournal + + LiveJournal.com, a website and online community built around + personal journals, was created by Brad Fitzpatrick in March of + 1999 for himself and some of his friends. Friends told friends + and it became a huge success, soon growing bigger than a single + person could easily handle. + + + As a result, a team of volunteers working with LiveJournal's + creator have transformed LiveJournal into a Webby Award winning + site used by over one million people worldwide. The site is now an + open-source software development project funded entirely by its + members, assisted by numerous volunteers and developers, and + overseen by a small paid staff. It's been expanded to allow easy + creation of journals, weblogs, and even interest-based online + communities. + + + diff --git a/livejournal/doc/raw/lj.book/intro/what_is.xml b/livejournal/doc/raw/lj.book/intro/what_is.xml new file mode 100755 index 0000000..62fa7e1 --- /dev/null +++ b/livejournal/doc/raw/lj.book/intro/what_is.xml @@ -0,0 +1,24 @@ + + What is LiveJournal? + + LiveJournal is an open source + content management system, written mainly in Perl and + utilizing MySQL as a database backend. By itself, it + serves as a powerful content updating system. In other uses, it is the framework application behind + many successful online communities, including LiveJournal.com + and DeadJournal.com. + + + Under the employ of LiveJournal.com, LiveJournal was presented two + People's Voice Awards from the + The International Academy of Digital Arts and Sciences, one each + for Personal Web Site and Service, during the + 5th Annual Webby Awards. + + + diff --git a/livejournal/doc/raw/lj.book/intro/why.xml b/livejournal/doc/raw/lj.book/intro/why.xml new file mode 100755 index 0000000..1b90db6 --- /dev/null +++ b/livejournal/doc/raw/lj.book/intro/why.xml @@ -0,0 +1,295 @@ + + Why Use LiveJournal? + + LiveJournal is an open source software project, with many uses + limited only by the imagination. Use LiveJournal to start your + own weblogging community, or just about any site with a community + focus. You can use the features such as the support system and + feedback technology, that comes bundled with LiveJournal, to run + your own online business site. + + + LiveJournal has many intra-office uses as well, with its easy + update and polling features. Use LiveJournal for: + + + Work journals + + Record what you're working on, or scribble notes for future reference. + + + + Project logs + + Multiple members of a project team to record + their work, post meeting minutes, and discuss ideas. + + + + Announcement pages + + Recording status updates to projects or + systems on a single page, while notifying interested users. + + + + Discussion boards + + Brainstorming ideas or soliciting opinions + with a group, in a persistent but nonintrusive medium. + + + + Weblogs + + Posting links to web content of interest to a particular group. + + + + + + There are many benefits of using LiveJournal + + + Enhances personal productivity by providing a convenient way to + record notes in a searchable, web-accessible medium + + + Provides visibility between departments or geographically separate offices + + + Encourages communication by making it easy to share thoughts and comments + + + Encourages people to get knowledge out of their heads and notebooks + and into a visible, searchable, central location + + + Provides more powerful tools for creating and accessing content than + are available for ad-hoc log-structured web pages + + + +
    + A LiveJournal installation comes with many configurable features available + out of the box, including but not limited to: + Features + + Journal related + + Journaling service + LiveJournal's core function. Users are able to submit journal + entries and "publish" them on their account's journal page. + + + Community journals + Journals that many users can post top-level entries to. This allows + for more long-term and public discussion than comments in a user's journal. + + + Friends list aggregation + Users are able to add other users to their friends list, which + permits them to view all journal entries from their friends in an aggregate form. + + + Friends filters + Users can view a subset of their friends lists at any given time. + + + Calendar view + Users can see a record of all of their posts in the past, and + choose to view those posts by a specific day (allowing easy access to old posts). + + + Message boards + Users can enable or disable message boards for individual + entries or journals as a whole. Users can choose to allow anyone, + registered users only, or friends only to post. Users can choose to + screen comments — make them visible only to the owner of the journal — + and choose to set certain levels of comments to be automatically screened + until approved (such as a user who may choose to screen all comments by + non-friends until they are approved). + + + Email notification of comments + Users can choose to receive an email + notification when someone comments on one of their posts (in the user's + personal journal or in a community journal) or replies to one of their + comments (in the user's personal journal, a friend's journal, or a + community journal). + + + Security levels + Users can specify who can read their journal entries. + Entries can be public (all can read), private (only the user can read), + protected (only the user's named "friends" can read), or custom. Custom + security allows a user to specify up to 30 subgroups of their friends who + can read the entries. + + + RSS feeds + Your installation publishes all public journal content as a RSS feed for + syndication on other sites. LiveJournal allows users to syndicate external RSS + feeds onto LiveJournal, to read on users' Friends page. (Adding RSS feeds to user's + friends list needs "syndication points", and each feed costs a certain + number of points based on how many users are watching the feed). + + + Moodsmood icons + Each entry can be given a mood, to + describe what the user is feeling at that time. Users can choose to add a + mood icon, which is a small picture to depict that mood. Users can + create their own mood icon themes for use in their journal. + + + Polls + Users can create different types of polls, to get opinions, + information, or thoughts from readers. + + + User picture icons + The ability to upload small "avatars" that + represent the user throughout the site. + + + Personalized subdomain + If configured, users can view their journals at + http://username.domain.com, as well as + http://www.domain.com/users/username and + http://www.domain.com/~username. + + + Customizing the display of the journal page + Users can create journal "styles" from scratch and have + precise control over appearance of their journals. + + + Friends of Friends feature + Users are able to see a list of entries by + the users who are named as a friend by their friends, but not by + the user. + + + Downloaded clients + Users can download a program to make journal entries + (and perform some other actions on the site) from their computer, rather + than from the website. + + + Tell a Friend + With one click on the read entry page, users can send an + email to someone else about an entry, calling the recipient's attention to + it. + + + Export feature + Users can download their journal month-by-month, in XML or + CSV format. + + + meme tracking + Users can view a list of URLs that have been most + referenced in journal entries site-wide. Users can also check to see where + those URLs are being referenced. (By some slight alteration, users can + also see if anyone on your installation is linking to a specific URL, and where.) + + + Random feature + Users can view a random journal from a subset of users who + have updated in the past 24 hours. + + + + Account related + + User bio + Users can provide information about themselves, which is + displayed on a page that can be viewed by visitors to their journal (the + user bio). Users can specify contact and location information (email, + AIM username, Yahoo! ID, ICQ #, MSN Messenger username, Jabber address, + city, state, country, etc) and specify the security level of that + information (public, private, protected) + + + Site search + Users can search by contact information — finding other + users by email address, AIM username, Yahoo ID, ICQ #, MSN Messenger + username, Jabber address, etc — to locate people on your installation. + + + Interests + Users can list up to 150 one to four-word interests in their + user bio, which other users can search for. + + + Similar interest search + Users can see a list of those users whose + interests match most closely to their own, based on an index that weights + both number of interests in common and rarity of interests in common. + + + Popular with friends search + The ability to see a list of the users who + are named most often as a friend by the user's friends, but not by the + user. + + + Domain forwarding + Users can forward their domain to their LiveJournal (so that, for example, http://journal.example.com would + forward to the user's LiveJournal at http://www.domain.com/users/username) + + + Journal embedding + Users can embed their journal into their home pages, + displaying their journal as part of an external home page. (This is + different from domain forwarding; with domain forwarding, the content is + served from the LiveJournal installation; with embedding, the content is first pulled + onto the user's server and then re-presented.) + + + Text messaging + Users can specify their text message information and + display an option on their user bio page to allow others to text message + them. (This allows users to receive text messages without having to make + their information public.) + + + Memory list + Users can name any post on the service as a memory — a LiveJournal + version of bookmarking. Memories can be categorized with different + keywords, so that users can more easily sort their memories. + + + To-do list + Users can create their own to-do list — reminders or + important things to do — and track percentage complete and progress on + each item. + + + Birthday list + Users can see a list of all of their friends who are having + an upcoming birthday (assuming the user has provided his or her birthday). + + + + Site related + + Directory + Users have access to the directory of users, where they + can search by location, age, interest, etc. + + + Portal + Users can use a more complex update page, which includes "boxes" + of several other features, such as statistics and birthdays, on the same + page as the update page. + + +
    +
    + diff --git a/livejournal/doc/raw/lj.book/preface.xml b/livejournal/doc/raw/lj.book/preface.xml new file mode 100755 index 0000000..6b8b104 --- /dev/null +++ b/livejournal/doc/raw/lj.book/preface.xml @@ -0,0 +1,71 @@ + + + + Preface + + This is a comprehensive manual aimed towards people wishing to + use the LiveJournal set of tools for their online-community + needs. Topics covered are installation, customization, and + administration, with included information on built-in + LiveJournal features, and a brief glimpse into what LiveJournal + is, and how it can be used to its fullest. + + + Target Audience + + This book was written for anyone interested in setting up and + maintaining a LiveJournal powered site, be it for intra or inter + net purposes. + + + + Readers of this book should be familiar with administering a web + site and should have a thorough knowledge of whatever system + they are installing LiveJournal on. + + + + Organization of this manual + + - Introduction + A basic introduction to LiveJournal + + + - Installation + Step by step instructions for installing LiveJournal on a server + + + - Customization + Instructions for customizing a LiveJournal installation + + + - Administration + A guide to administering a LiveJournal site + + + - Features + Introductions and instructions to different LiveJournal features + + + + + Versions + + LiveJournal maintains an online version of this book at: + + + + To compile these pages for your own, refer to: + /doc/raw/notes.txt in CVS. + + + + + + + diff --git a/livejournal/doc/raw/ljp.book/api/index.xml b/livejournal/doc/raw/ljp.book/api/index.xml new file mode 100755 index 0000000..f83752e --- /dev/null +++ b/livejournal/doc/raw/ljp.book/api/index.xml @@ -0,0 +1,9 @@ + + Application Programming Interface + + + This is the complete API documentation. + + + &ljp.api.ref; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/bml/core.xml b/livejournal/doc/raw/ljp.book/bml/core.xml new file mode 100755 index 0000000..835094b --- /dev/null +++ b/livejournal/doc/raw/ljp.book/bml/core.xml @@ -0,0 +1,36 @@ + + + Core <abbrev>BML</abbrev> blocks + + Core <abbrev>BML</abbrev> blocks + + Core blocks are predefined blocks that are named with a leading underscore. + Most core blocks have a higher purpose than simple template use: + + + + _code + + <?_code _code?> blocks are perhaps the most useful feature of + BML outside of the ability to have global site templates. + These blocks allow template authors to embed pieces of executable Perl code + within the bml page that get executed on the server. + + + The code you write gets executed in its own package (namespace) called + BMLCodeBlock::. + Any variables you declare in one code block on a page without using + my are carried on to the next _code block. + + Because the BML parser must evaluate everything on the page before sending the + HTTP headers, make sure you don't print anything. + Any output printed to STDOUT will just be interpreted as + HTTP headers. How the _code blocks work is + that you need to return a value at the end. + Whatever value your code fragment returns is what the block evaluates to. + Usually what you end up doing is building a string, concatenating things to it + over and over, and then returning it at the end. + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/bml/flags.xml b/livejournal/doc/raw/ljp.book/bml/flags.xml new file mode 100755 index 0000000..963ec17 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/bml/flags.xml @@ -0,0 +1,89 @@ + + Template Flags Explained + + This documents the flags in braces at the beginning of .look file block template definitions. + The flags fall into one of three classes: + + + + Varible definition types: + + F + + Full, mix of multi & single line property definitions: + Single line string +template?>]]> + + + + + P + + Pipe delimited, properites are named DATA<n>, where <n> starts at 1 and increases. + <?template DATA1|second arg|DATA3 template?> + + + + + D + + One proprety, and it's named DATA + <?template I am the DATA template?> + + + + + + Static template definitions: + + S + + Static: output won't have more BML to expand, or properties to fill-in, so don't try. + + + + R + + Less static: add pRoperties, but then don't BML expand. + + + + + Controlling expansion vs. interpolation order: + + p + + + Pre-parsed. + BML-expand parameters first, then interpolate into template. + By default, parameters are interpolated first, then everything is expanded. + But if you use %%TITLE%% twice in your PAGE, for example, and your .bml file defines TITLE=> with a _CODE block, it will be run twice, so it's generally a good idea to make PAGE definitions pre-parsed. + Also, then, you avoid re-running most of your output through the BML expander a second time. + + + + + s + + + Expand embedded parameterless static blocks in definition early. + When the template file is read, any blocks of the form <?foo?> are expanded ahead of time. + Useful in conjunction with the {S} flag. consider: + {S}http://www.site.com:8080/ + +# Some block that has an image: +SPACER=>{Ss}]]> + The SPACER block isn't really static, but because {s} is used and (=IMGPREFIX=) is static, then SPACER can also be static. + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/bml/index.xml b/livejournal/doc/raw/ljp.book/bml/index.xml new file mode 100755 index 0000000..98938cc --- /dev/null +++ b/livejournal/doc/raw/ljp.book/bml/index.xml @@ -0,0 +1,21 @@ + + + The Better Markup Language + BML + + The Better Markup Language + BML + + + BML is a server-side markup language that lets you define your own + BML blocks and use them as templates within your BML pages. + Your templates don't even have to be static. Because BML pages are + converted to HTML on the server when users request them, this also + enables you to embed live code within your BML pages, just like a + CGI script. + + + &ljp.bml.flags; + &ljp.bml.core; + &ljp.bml.api.ref; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/appx.faq.xml b/livejournal/doc/raw/ljp.book/csp/appx.faq.xml new file mode 100755 index 0000000..e1e95e5 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/appx.faq.xml @@ -0,0 +1,72 @@ + + Frequently Asked Questions + + + How do I calculate the protocol itemid to get the URL itemid? + For protocol methods that return an itemid, there is also another variable returned called anum. + To calculate the public URL itemid, use the following formula: (itemid * 256) + anum. + + + + What are the limitations on post and user information data? + To help calculate portions of your client, here are the upper limits of client affected data: + + Posts: 65,535 bytes + Entry Properties (Currents): 255 bytes or 100 characters + Entry Subjects: 255 bytes or 100 characters + User Picture Keywords: 40 characters + Usernames: 15 characters + Name: 50 characters + Webpage URL: 255 bytes + Webpage Name: 255 bytes + + + + + I just wrote a client for LiveJournal. How do I go about getting it on the Download page? + + The Downloads page currently requires manual updates, which happen infrequently. + Due to the large userbase which uses clients offered up via the Downloads page, we + prefer to only add well-established clients to the page at this point. + + + All too often, someone will code a client and then abandon it after a certain amount of time. + If you feel that you are willing and able to commit to maintaining and providing support for + a client, then by all means produce one and announce it on + lj_clients. It is + recommended that you create a community for the users of your client, so you can announce new + versions and provide a forum for troubleshooting and user support. Once your client has + matured, it will likely be included on the Downloads page. If your program has reached a + point where you feel it should be included in the page and it hasn't been yet, feel free to + drop a post to lj_clients + asking why. + + + Client Listing Guidelines for the <ulink url="http://www.livejournal.com/download/">Download a Client</ulink> page + As a minimum, clients MUST support the basic features of LiveJournal, + such as logging in, posting new entries, editing old entries, history views, etc. + Client MUST be mature and well-established before being listed. Having minor bugs is ok, but + we don't want to link to clients that have the potential to mess up an account. + Client MUST be free to use. You're welcome to create and maintain a + client that isn't free/open, we just don't want to provide free advertising for such a client. + Client MUST be originally written for LiveJournal. We support the Blogger and Atom APIs, and + we encourage interoperational clients, but we don't want to get in the habit of listing clients for + competitor services. + + + + + Why doesn't my client show up on my user info page? + Recently client logging was disabled because its current implementation was consuming + far too many database resources. It will likely reappear in the future, once a more efficient design + is coded and tested. + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/auth.xml b/livejournal/doc/raw/ljp.book/csp/auth.xml new file mode 100755 index 0000000..cc25e07 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/auth.xml @@ -0,0 +1,122 @@ + + Authentication in the Client Server Protocol +
    + Clear + Although this method is still supported, it is DEPRECATED and should not be used. Client authors + SHOULD use another authentication method if it is available to them. + The default authentication method is known as clear, which refers to the fact that passwords + are being sent as plain-text (in the clear). Though clients have the ability to encrypt passwords + in a one way hash function (MD5) and send them to the server (as hpassword), they are still + vulnerable to replay attacks if the hashed password becomes known. + Clear authentication occurs when a username and either password + or hpassword is passed to any client server protocol method. +
    +
    + HTTP Cookies + If you specify auth_method with the value of cookie, you can use + session cookies generated by the server in your client. To prevent against the usage of modified forms to perform + actions without the consent of the user, we require the HTTP header X-LJ-Auth + be set to cookie as well. + + Using Wget 1.9 with <literal>auth_method=cookie</literal> in flat protocol + $ wget &siteroot;/interface/flat + +
    +
    + Challenge / Response + Another way to authenticate your client is to build a hex digest consisting of the user's password and + a challenge as issued by the server. This is currently known as auth_method challenge. + Essentially, you generate a challenge by issuing a blank request to the getchallenge method. If your + method call is successful you're given: + + + string auth_scheme + You can ignore this for now. By default this is the highest version of our + authentication schemes, if in the future if we implement other auth schemes or change the default. + In that case we'd add a new capabilities exchange: your client could say, "I know c0 and c1", and + our server would then say, "Use c1, it's the best." + + + string challenge + challenge is an opaque cookie, as generated by + . Challenges may only be used once. + + + int expire_time + expire_time is the expiration time for the challenge + as measured in seconds since the Unix epoch. + + + int server_time + servertime is the time of when the challenge was generated, + as measured in seconds since the Unix epoch. The formula (server_time - + expire_time) is the life span of the challenge, in seconds. + + + For your response, you then build a MD5 hex digest of the formula (challenge + + MD5_hex(password)). To authenticate your client now, you simply send back the following 3 + parameters, along with your username: + + + string auth_method + Set to challenge + + + string auth_challenge + The challenge issued by the server + + + string auth_response + MD5_hex(challenge + MD5_hex(password)) + + + + Sample Perl script using <methodname>getchallenge</methodname> + proxy("http://www.lj.com/interface/xmlrpc"); +my $get_chal = xmlrpc_call("LJ.XMLRPC.getchallenge"); +my $chal = $get_chal->{'challenge'}; + +my $user = "test"; +my $pass = "pass"; +print "chal: $chal\n"; + +my $response = md5_hex($chal . md5_hex($pass)); + +my $login = xmlrpc_call('LJ.XMLRPC.login', { + 'username' => $user, + 'auth_method' => 'challenge', + 'auth_challenge' => $chal, + 'auth_response' => $response, +}); + +print Dumper($login); + +sub xmlrpc_call { + my ($method, $req) = @_; + my $res = $xmlrpc->call($method, $req); + if ($res->fault) { + print STDERR "Error:\n". + " String: " . $res->faultstring . "\n" . + " Code: " . $res->faultcode . "\n"; + exit 1; + } + return $res->result; +}]]> + + +
    +
    + diff --git a/livejournal/doc/raw/ljp.book/csp/blogger.xml b/livejournal/doc/raw/ljp.book/csp/blogger.xml new file mode 100755 index 0000000..2413439 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/blogger.xml @@ -0,0 +1,36 @@ + + Supporting the Blogger API + + Like LiveJournal, the weblog service Blogger provides a programmatic interface that's been built with XML-RPC. To allow our users to make use of popular Blogger-compatible tools (Radio, Blogbuddy, w.bloggar, TextRouter), we've added internal support for their API. However, the Blogger API is currently labeled as experimental and alpha, and will not be developed further.Blogger: We are working along with others in the blogging industry to produce a new, more robust API. You can view the current state of the Echo Project here. + + + The Blogger interface address for a LiveJournal installation is . + + + Supported Methods + LiveJournal supports the following Blogger API methods (methods are linked to relevant documentation): + blogger.newPost + blogger.editPost + blogger.deletePost + blogger.getUsersBlogs + blogger.getRecentPosts + blogger.getPost + blogger.getUserInfo + + + Notes + LiveJournal makes no use of the appkey parameter. + The Blogger API does not support the use of post titles (subjects). To set a title for your post + include the title wrapped in <title> tags in your post body. + LiveJournal specific meta data (current mood and music) are supported by including a line consisting of lj-metadatakey: metadata in the post body (e.g. lj-mood: happy). + The publish parameter is always set true. + blogger.getUserInfo will return the account's name for both firstname and lastname. + Due to the differences between Blogger's and LiveJournal's template systems, the blogger.getTemplate and blogger.setTemplate methods are not supported. + + + diff --git a/livejournal/doc/raw/ljp.book/csp/cs.xml b/livejournal/doc/raw/ljp.book/csp/cs.xml new file mode 100755 index 0000000..d3be423 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/cs.xml @@ -0,0 +1,151 @@ + + + Client / Server Protocol - Quick Reference + + Client / Server Protocol - Quick Reference +
    + Introduction to the Protocol + + + Before reading this document, it is assumed you know at least some + basics about network programming, at least the whole idea of opening + sockets and reading/writing to them. If not, this might be kinda + confusing. + + + Basically, sending a LiveJournal request is like this: + + Handshake + + Open a socket to www.livejournal.com on port 80 + + + Send an HTTP POST request, containing the request variables (mode, user, password, etc...) + + + Read the socket to get the response. The response is really easy to parse. + + + Close the socket. Do any approriate action based on the server's response. + + + For example, your client would output a request: + + + + + + + All values must be quoted or the values can interfere with the encoding form. + For example, if someone's password was blah&=2+&something=yeah, + it could quite possibly ruin the encoding format. + Here are some guidelines on how to encode values: + + Leave all values from a-z, A-Z, and 0-9 alone. These are fine. + Convert spaces to a + (plus) sign. + Convert everything else to %hh where hh is the hex representation of the character's ASCII value. + + + + For example, the phrase I'm going to the mall could encoded as I%27m+going+to+the+mall. + There should be CGI libraries for all major languages which do this encoding for you. + If not, it isn't that hard to do it yourself. + + + + After you construct the big long ugly string of variables/values, find the length of + it and send it in the Content-length field, as in the example above. + Then send a blank line, then the big long ugly string. + + Line Endings + + Please note that the end of lines should be a carriage return + (ASCII 13, 0x0D) and then a + newline (ASCII 10, 0x0A). + In Perl, C/C++ or Java this is \r\n. + In Basic, this is Chr(13) & Chr(10). + Sending just the newline may work too, but it's generally better to send both. + + + A typical response would be: + + + + + + The top stuff is headers from the HTTP request. + There may be a lot of other stuff in there too. + First thing to do is make sure the first lines ends with 200 OK. + If the first line does not end with 200 OK, + tell the user that an error occurred on the server and that it's not their fault. + If you see 200 OK at the end, proceed with parsing the output. + The format is as follows: + +variable +value +someothervariable +someothervalue + + The ordering of the variable/value pairs does not matter. + As you read them in, read them into a hash structure + (associative array, dictionary, collection…whatever it's called in your language. + Just a data structure that links one string variable key to another string variable value.). + + + After your hash is loaded, proceed with the logic of reporting errors if needed, as governed by the variables and logic above. + +
    +
    + Working with Proxies + + As a final feature, once you get that stuff working, is to implement + support for HTTP proxies. This is very easy. Give the + user a checkbox if they want to use a proxy or not, and if so, + ask the proxy host and proxy port. Now, if they selected to use a proxy, do + not connect to www.livejournal.com and port 80, but instead connect to their + proxy host on whatever proxy port they specified. The rest is basically the + same, except for one difference. Instead of doing: + + + + You would do: + + + + + + That line tells the proxy what host it needs to connect to in order to + make the real request. The rest of the HTTP you should leave just as you did + before. + +
    + Client Developer Community + + If you ever have any questions about building clients for LiveJournal, then + you'd probably interested in the lj_clients community + on LiveJournal.com + + +
    \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/flat/index.xml b/livejournal/doc/raw/ljp.book/csp/flat/index.xml new file mode 100755 index 0000000..49428e4 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/flat/index.xml @@ -0,0 +1,28 @@ + + + Flat Client/Server Protocol Reference + + Flat Client/Server Protocol Reference + + + This is a reference to the flat interface to LiveJournal, + where flat is simpy a term describing the raw + HTTP request sent to a LiveJournal server. + + + This interface passes uses simple key/value pairs for every request and response. + The benefit is that it's easy to parse the response given by the server, if you + are left to your own devices, and have to do it yourself. + As an alternative, there exists an XML-RPC Interface + + + XML-RPC is something most programming languages have a library for. + Check to see if there is an + implementation for your language of choice. + + , + which returns the data in a predetermined (nested) format that is easier to work with directly. + + + &ljp.csp.flat.protocol; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/index.xml b/livejournal/doc/raw/ljp.book/csp/index.xml new file mode 100755 index 0000000..06e3052 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/index.xml @@ -0,0 +1,33 @@ + + Client/Server Protocol + + + Currently there are a few types of interfaces available to the LiveJournal + protocol: the older "flat" interface, the custom XML-RPC interface, and a modified version of the Blogger API. + The XMLRPC interface is probably easiest to use, because there are quite a few XML-RPC + resources available to developers in just about any programming language. If + you're in a situation that requires you to write your own interface wrapper, + then the flat interface is probably best to use. + + + + Internally, all interfaces are just wrappers around the same functions. Don't + worry too much about which one you use, as they accomplish the same thing. + + + + &ljp.csp.guide; + &ljp.csp.auth; + &ljp.csp.flat.index; + &ljp.csp.xml-rpc.index; + &ljp.csp.blogger; + &ljp.csp.versions; + &ljp.csp.proplist; + &ljp.csp.appx.faq; + + diff --git a/livejournal/doc/raw/ljp.book/csp/proplist.xml b/livejournal/doc/raw/ljp.book/csp/proplist.xml new file mode 100755 index 0000000..9d194d4 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/proplist.xml @@ -0,0 +1,7 @@ + + Journal Item Meta-data + + This is a list of the meta-data that can be assigned to journal items. + + &ljp.csp.proplist.ref; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/versions.xml b/livejournal/doc/raw/ljp.book/csp/versions.xml new file mode 100755 index 0000000..eb8a318 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/versions.xml @@ -0,0 +1,46 @@ + + Protocol Versions + + The LiveJournal protocol (so far) has been more or less static; while new + modes have been added, the basic operation has not changed much. However, + recent introduction of Unicode support in LiveJournal necessitated changes + in the way text is encoded in protocol requests and responses. In order to + allow new clients to take advantage of Unicode support and at the same time + avoid breaking existing clients, a versioning scheme has been put into the + protocol. The client sends the number of the highest protocol version it + supports in every request, inside a ver attribute; version + 0 is implicit if the client does not send the + ver attribute. Currently there are two versions of the + protocol, and the Unicode-enabled server code supports both of them. + + + Version <literal>0</literal> + + If a client does not send a ver key on a request, + it assumed to support protocol Version 0. In protocol + Version 0, textual information transmitted from or to + the server is always assumed to be a stream of 8-bit bytes, not necessarily + ASCII, but without any guarantee that the + non-ASCII bytes are presented in any particular encoding. + + Version <literal>1</literal> + + Version 1 differs from Version 0 only + by imposing additional requirements on the text transmitted through requests + and responses; there aren't any changes in protocol modes. The additional + requirements are that in a Version 1 request, the client + must transmit all textual information as a stream of + Unicode data encoded in UTF-8; the server must + respond to Version 1 requests with Version 1 + responses; in such Version 1 responses, the server + must also transmit all textual information encoded in + UTF-8; and the client must expect that + and handle such responses correctly. In other words, all information transmitted + via protocol when Version 1 is used is always encoded in + UTF-8. UTF-8 is a representation of Unicode + in a bytestream format compatible with ASCII. + See the Unicode Consortium website + for more information on Unicode and UTF-8. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/csp/xml-rpc/index.xml b/livejournal/doc/raw/ljp.book/csp/xml-rpc/index.xml new file mode 100755 index 0000000..8d2be84 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/csp/xml-rpc/index.xml @@ -0,0 +1,23 @@ + + + XML-RPC Client/Server Protocol Reference + + XML-RPC Client/Server Protocol Reference + + + This the XML-RPCFor the XML-RPC spec, see: version of the Client/Server protocol. + XML-RPC allows programs to make procedure calls over the internet, regardless of differing operating systems and environments. + It's also handy for returning preconstructed libraries of information (instead of having to have your program parse the regular server feedback). + + + In order to use the XML-RPC interface, make sure your client is referencing the /interface/xmlrpc section of the LiveJournal site it is communicating with. + + + Method Names + + The full title of each method is actually LJ.XMLRPC.foo, where foo is the short name given below: + + + + &ljp.csp.xml-rpc.protocol; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/db/index.xml b/livejournal/doc/raw/ljp.book/db/index.xml new file mode 100755 index 0000000..fe50465 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/db/index.xml @@ -0,0 +1,22 @@ + + + Database Schema + + Database Schema + + + This is the complete database layout (schema) documentation. + + + &ljp.dbschema.reluser; + + Database Schema Browser + &ljp.dbschema.ref; + + + diff --git a/livejournal/doc/raw/ljp.book/db/reluser.xml b/livejournal/doc/raw/ljp.book/db/reluser.xml new file mode 100755 index 0000000..1fb22de --- /dev/null +++ b/livejournal/doc/raw/ljp.book/db/reluser.xml @@ -0,0 +1,49 @@ + + Relationships between users + The reluser Table + + The reluser table is used to track special relationships + between accounts, such as community maintainers/moderators and their communities, which communities + a user is allowed to post to, and which users are banned from commenting in specific journals. + These relationships are defined as a single character in the database: + + + + A + targetid can + administrate userid as a community maintainer + + + + B + targetid is + banned in userid, either in comments, or from + posting, if userid is a shared or community account + + + + P + targetid can + post to userid + + + + M + targetid can + moderate the community userid + + + + N + targetid is preapproved + to post in userid without moderation + + + + + diff --git a/livejournal/doc/raw/ljp.book/index.xml b/livejournal/doc/raw/ljp.book/index.xml new file mode 100755 index 0000000..3932b16 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/index.xml @@ -0,0 +1,21 @@ + + + LiveJournal Programming + Goathacking For a Better World + This book covers all topics LiveJournal Programming! + ©right; + &legalnotice; + + &ljp.prog-guide.index; + &ljp.int.index; + &ljp.csp.index; + &ljp.styles.index; + &ljp.api.index; + &ljp.dbschema.index; + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/int/bml_faq.xml b/livejournal/doc/raw/ljp.book/int/bml_faq.xml new file mode 100755 index 0000000..85aa98a --- /dev/null +++ b/livejournal/doc/raw/ljp.book/int/bml_faq.xml @@ -0,0 +1,103 @@ + + + A Short FAQ on BML + + A short FAQ on BML + + + This is a crash guide to BML and its implementation. It's meant to be read by programmers or sysadmins with a working knowledge of Perl, who want to understand the implementation or improve it. This document is not a gentle introduction; it's meant to be terse and to-the-point. + + + + + + + What is BML? + + + + + BML is a server-side markup language designed by Brad Fitzpatrick. The official site is . However, the actual BML distribution there is outdated, so don't use it. Use the BML files inside LiveJournal source tree. See for information about LiveJournal CVS repository. The relevant files there which make up the implementation of BML all reside in /livejournal/cgi-bin directory, and they are: + + BML components + + bmlp.pl + + The main program; the BML interpreter written in Perl. + + + + bmlp.cfg + + The configuration file which alllows for customizing BML's run-time options. + + + + bml-client.pl + + Helper functions to maintain persistent information between client requests. + + + + bml/schemes + + A directory holding customizable template files for the site (see below). + + + + + + + + + + What is BML for? + + + + + BML allows the site designer to encapsulate common chunks of HTML in abstract blocks, which are then used inside .bml files instead of repeating the same chunks of HTML many times. The BML interpreter processes a .bml file at runtime, transforming all the blocks which are placed there into HTML; it does this by using the definitions of blocks stored in site-wide template files. Since template files are site-wide, consistent use of BML blocks throughout the site ensures consistent user interface; in addition, simply changing the template (telling the BML interpreter to use another template file) automagically changes the user interface for the entire site in a consistent manner. Finally, a special kind of a block allows for embedding executable Perl code in a BML file, which is executed dynamically when the page is requested. This makes BML especially useful for writing sites with dynamic, database-driven content. + + + + + + + How does BML work? + + + + + All requests to BML documents end up as dynamic requests on the server side. Whenever a page is requested that is associated with a BML file, the HTTP server transfers control to the BML interpreter and asks it to return the appropriate HTML content to the user. The interpreter loads the page, processes it using appropriate template files and configuration options, creates HTML content and passes it back to the server. + + + + + + + How does the BML interpreter do what it needs to do? + + + + + The HTTP server config file is modified to tell the server to execute the intrepreter whenever a URI is requested which corresponds to a file with extension .bml. As the interpreter is executed, it receives from the server the name of the file to run and additional parameters such as environment variables, the remote user's HTTP headers and parameters embedded in the URL, and so on. The interpreter reads its config file to determine runtime options, finds the appropriate template files, loads the definitions of blocks from the template files, and processes the BML file, transforming all the block invocations into appropriate HTML text, which is fed back to the HTTP server. + + + + + + + What is the interface between the HTTP server and the BML interpreter? + + + + + Currently the interpreter is written to conform to FastCGI interface. See: for comprehensive information on what FastCGI is. Briefly, FastCGI allows for more efficient execution of scripts than the original CGI interface, but scripts must be written to process many requests in a loop, rather than just process one request and exit as in CGI. This requirement determines some important details of the interpreter's design, which are discussed below. + + + Nevertheless, one of the short-term goals of BML's evolution is to modify the interpreter so that it is able to run unchanged under three different interfaces: CGI, FastCGI and mod_perl.See: for more information of mod_perl. + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/int/cap_classes.xml b/livejournal/doc/raw/ljp.book/int/cap_classes.xml new file mode 100755 index 0000000..f35bffe --- /dev/null +++ b/livejournal/doc/raw/ljp.book/int/cap_classes.xml @@ -0,0 +1,8 @@ + + Capabilities Classes + + The 'caps' column in the 'user' table is a 16 bit mask with a bit on for each capability class the user is a part of. Each site can define their own capability classes in cgi-bin/ljconfig.pl. Then, each capability class can define its own limits for the following things. The LJ::get_cap() and LJ::get_cap_min() functions will consider the limits of all the classes the member is a part of and return the max or min limit, depending on what it's being used for in the code. + + This text should reflect a different view, as the developer is writing the cap _for_ the administrator. + &ljp.int.cap_list; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/int/index.xml b/livejournal/doc/raw/ljp.book/int/index.xml new file mode 100755 index 0000000..e0819bb --- /dev/null +++ b/livejournal/doc/raw/ljp.book/int/index.xml @@ -0,0 +1,9 @@ + + Internals + + + This part covers all of the sections not normally covered in other sections. + + + &ljp.int.cap_classes; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/database.xml b/livejournal/doc/raw/ljp.book/prog-guide/database.xml new file mode 100755 index 0000000..83fba88 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/database.xml @@ -0,0 +1,74 @@ + + Database + + Database + + Check your db index usage... mysql's EXPLAIN is your friend. + + + Between LOCK TABLES & UNLOCK TABLES, + never call a subroutine. + + + Check the DB error code after an SQL statement. Just because it worked once and the SQL is correct, + that doesn't mean the table might not go corrupt, a disk might fill up, or index space within the + file might not fill up. Errors happen. Deal with them. + + + Preferred way to break up a long SQL query: + + $sth = $dbh->prepare("SELECT cola, colb, colc, cold FROM foo ". + "WHERE colb<>cola AND colc=22"); + + + + Note on variable naming: + + + + + $sth + statement handle + + + $dbh + one database handle (usually the master) + + + $dbs + set of database handles [master(, slave)] + + + $dbr + read-only slave db handle (used for selects) + + + $dbarg + argument that can take a $dbh/r or $dbs + + + $remote + hashref of remote user, based on cookies. will contain 'userid' and 'user' params, + unless faster get_remote_noauth was used, in which case only 'user' will be present. + + + $u + a user 'object' (a hashref) + + + + + + + Call for database handles as you need them, instead of predeclaring $dbx variables. + Use LJ::get_db_writer to get a writable handle to the database, and + LJ::get_db_reader to get a read-only handle. + + + + diff --git a/livejournal/doc/raw/ljp.book/prog-guide/general.xml b/livejournal/doc/raw/ljp.book/prog-guide/general.xml new file mode 100755 index 0000000..8cb7d33 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/general.xml @@ -0,0 +1,44 @@ + + General + + General + + BML pages shouldn't interface with the database much. See . + + + Always use the LJ:: functions that take an explicit database handle. Don't use the old main:: functions that use the global $dbh. + + + All files should have <LJDEP> edge dependency somewhere, usually at the bottom. + + + Using userids (integers) for things is better than using users (strings), except in URL arguments, where pretty is more important than speed. + + + In BML page, use BML blocks defined in global.look: LJUSER, P, H1, H2, STANDOUT, HR, etc... + + + All HTML should be XHTML compliant.: + + + Lower case, XML compliant tags: <br /> instead of <BR> + + + Quotes around attributes <span class="test"> + + + No bare & chars ... always escape them: &amp; and <a href="foo.bml?a=1&amp;b=2">...</a> + + + + + Use of multiple files to do one function is deprecated. There should no longer be "foo.bml" and "foo_do.bml" like there used to. That's ugly. + + + Tab is a formatting command, not a character See: . There should be spaces in the files, not tab characters. + + + All subs in a package need LJFUNC documentation. All tables in the database need schema documentation. All files need LJDEP documentation. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/index.xml b/livejournal/doc/raw/ljp.book/prog-guide/index.xml new file mode 100755 index 0000000..94d67b6 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/index.xml @@ -0,0 +1,14 @@ + + Programming Guidelines + + + Content that goes into CVS needs to follow these guidelines: + + + &ljp.prog-guide.general; + &ljp.prog-guide.security; + &ljp.prog-guide.database; + &ljp.prog-guide.performance; + &ljp.prog-guide.perl_style; + &ljp.prog-guide.patches; + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/patches.xml b/livejournal/doc/raw/ljp.book/prog-guide/patches.xml new file mode 100755 index 0000000..2d70b40 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/patches.xml @@ -0,0 +1,12 @@ + + Patches + + Patches + + All patches sent in should be in diff -u format. + + + Don't send in patches that comment out old code. If we want the old code, we'll go get it from CVS.. that's what it's for. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/performance.xml b/livejournal/doc/raw/ljp.book/prog-guide/performance.xml new file mode 100755 index 0000000..93e62cc --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/performance.xml @@ -0,0 +1,15 @@ + + Performance & Scalability + + Performance & Scalability + + Large chunks of code should be preloaded in libraries. Code in BML pages is re-evaled on every request, so it should be small. If you need a lot of code, put it in a library and load it in cgi-bin/lj-bml-(init|local).pl + + + Don't write temporary files to disk... all LJ code should be able to run on a cluster of web servers with no disk-based session persistence. + + + If you're calling a function with a $dbarg parameter and you have both a $dbs and $dbh available, call the function with your $dbs ... otherwise the function and all its callees can't ever use the slave databases. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/perl_style.xml b/livejournal/doc/raw/ljp.book/prog-guide/perl_style.xml new file mode 100755 index 0000000..101b37d --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/perl_style.xml @@ -0,0 +1,15 @@ + + Perl Style + + Perl Style + + foo() looks prettier than &foo(). Let perl 4 die. + + + Lines longer than 80 characters are okay, but not great. + + + If you're in package LJ and calling an LJ::* API function, go ahead and type the extra four characters (LJ::) even if they're not necessary... being explicit is nice for the reader. + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/prog-guide/security.xml b/livejournal/doc/raw/ljp.book/prog-guide/security.xml new file mode 100755 index 0000000..5680f50 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/prog-guide/security.xml @@ -0,0 +1,21 @@ + + Security + + Security + + + All GET/POST form values go into %FORM into BML, but check LJ::did_post() on critical actions. GET requests can be easily spoofed, or hidden in images, etc. + + + + + Never read in arbitrary amounts of input + + + + + Never use unsanitized data in a command or SQL + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/compare.xml b/livejournal/doc/raw/ljp.book/styles/compare.xml new file mode 100755 index 0000000..36b38d4 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/compare.xml @@ -0,0 +1,105 @@ + + Comparing Style Systems + When we designed S2, there were specific features that we had in mind + that would fix certain design flaws inherit with S1. The table belows + explains some of the reasoning behind these changes. + + + + + Feature + S1 + S2 + + + + + Flexible & Extensible + S1 forces users to define a template for each new type + of view: recent entries, friends page, day view, calendar, etc. If + we want to add a new view type, users have to basically write their + style again. + + In S2 you describe the formatting of objects, not the + formatting of views. Thus, we can easily add new views in the future, + and making a recent view pretty much makes all your + other views automatically. + + + + Safety + S1 is completely safe. It's so brain-dead that it + can't be anything but but safe. You have to have some intelligence + to be harmful. + + The new style system is its own language that gets + compiled into another language, and run on the webserver. Letting + users run code on the server is inherently dangerous... it obviously + has to be free of things like + rm , but also, it has to be + free from infinite loops, and anything that could consume large + amounts of resources. + The S2 language does not have while loops, gotos, or any + other control construct that would permit an infinite loops. It only + has if/else blocks and foreach over finite lists. + There is also a limit on execution time of a resulting style, + to avoid situations we can't easily trap such as functions calling + each other in cycle, or badly-written recursion. + + + + Speed + S1 is a CPU hog, doing tons of parsing, text munging + and substitutions and run-time. + + In the new system, S2 code will be parsed, checked, and + compiled before the page is loaded. When a page is loaded in the + future, the code will just be run, which will already be in the + language that the LiveJournal server runs on. At the moment + this is Perl but in the future we could write a PHP or Java servlet + backend to the S2 compiler. + + + + Internationalizablilty + S1 can support non-English languages and locales, but + hardly: + + The server injects a lot of English into S1 + variables, especially in dates. + The calendar always begins weeks on + Sunday. + The system to make nouns plural (2 Comments, 3 + Replies) is very English-specific. + Porting a style to a new language involves + forking the style and modifying away, losing all future changes + to the original style. S1 forces users to define a template for + each new type. + + + The new style system has been designed for + internationalization. One of the S2 layers is an + i18n layer, which overrides English method definitions + from the core and sets properties, like the day weeks start on. + + + + Ease of Use + S1 was never designed to be easy. It was designed for a + few administrators to make styles, which would then be made public. + + Wizards and tools generate S2 behind the scenes for + most users. The hard-core users can write their own layouts and overlay + other layers in the raw S2 language. + + + + + + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/index.xml b/livejournal/doc/raw/ljp.book/styles/index.xml new file mode 100755 index 0000000..a6e8dc8 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/index.xml @@ -0,0 +1,25 @@ + + Making Journal Styles + + + Styles are the part of LiveJournal that allows users to customize the look + of their accounts. + + + Currently there are two types of style interfaces available to use, + the older S1 which is very linear and dumb, and the newer + S2 which features its own sort of programming language. + Read on for more information on S1, or visit The S2 + Manual for more information on S2. + + + &ljp.styles.compare; + &ljp.styles.s1; + &ljp.styles.s1.ref.gen; + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s1/design.xml b/livejournal/doc/raw/ljp.book/styles/s1/design.xml new file mode 100755 index 0000000..5760429 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s1/design.xml @@ -0,0 +1,10 @@ +
    + Design Overview + STUB +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s1/history.xml b/livejournal/doc/raw/ljp.book/styles/s1/history.xml new file mode 100755 index 0000000..39b3aa2 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s1/history.xml @@ -0,0 +1,10 @@ +
    + History & Motivations + STUB +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s1/index.xml b/livejournal/doc/raw/ljp.book/styles/s1/index.xml new file mode 100755 index 0000000..5c2603f --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s1/index.xml @@ -0,0 +1,15 @@ + + + Style System 1 (<acronym>S1</acronym>) + + Style System 1 (<acronym>S1</acronym>) + Finish S1 docs, build reference from views.dat + vars.dat + &ljp.styles.s1.history; + &ljp.styles.s1.design; + + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s2/design.xml b/livejournal/doc/raw/ljp.book/styles/s2/design.xml new file mode 100755 index 0000000..adec3b0 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s2/design.xml @@ -0,0 +1,10 @@ +
    + Design Overview + STUB +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s2/history.xml b/livejournal/doc/raw/ljp.book/styles/s2/history.xml new file mode 100755 index 0000000..f2e7824 --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s2/history.xml @@ -0,0 +1,10 @@ +
    + History & Motivations + STUB +
    + \ No newline at end of file diff --git a/livejournal/doc/raw/ljp.book/styles/s2/index.xml b/livejournal/doc/raw/ljp.book/styles/s2/index.xml new file mode 100755 index 0000000..f4fa9bc --- /dev/null +++ b/livejournal/doc/raw/ljp.book/styles/s2/index.xml @@ -0,0 +1,15 @@ + + + Style System 2 (<acronym>S2</acronym>) + + Style System 2 (<acronym>S2</acronym>) + Language Reference + &ljp.styles.s2.history; + &ljp.styles.s2.design; + + \ No newline at end of file diff --git a/livejournal/doc/raw/memcache-keys.txt b/livejournal/doc/raw/memcache-keys.txt new file mode 100755 index 0000000..b2fa7e0 --- /dev/null +++ b/livejournal/doc/raw/memcache-keys.txt @@ -0,0 +1,78 @@ + userid: == $u, 30 min (in arrayref packed form) + uidof: == userid + uprop:: == scalar, 30 minutes + tags: == { tagid => { **tag info hashref, see LJ::Tags::get_usertags** } } + sess:: == sessions row hashref + bio: == user bio text + + talkprop:: == { propname => $value, ... } + talksubject::: == scalar + talkbody::: == scalar + talk2::: == packed data + talk2ct: == # rows for user + talkleftct: == # rows for user + + logtext::: == [ subject, text ] + logprop:: == { propname => $value, ... } + logtag:: == [ kwid, kwid, kwid, ... ] + log2:: == packed data + log2ct: == # of rows for user + log2lt: == packed data: array of recent log2 entries in rlogtime order, last 2 weeks by default + rp:: == scalar, the replycount value + + memkwid: == hashref of 'memories' keyword ids to keywords. + + dayct: == arrayref of arrayrefs (see LJ::get_daycounts) + + auc:: == last ID from LJ::alloc_user_counter() for $uid/$domain + + moodthemedata: = { $moodid => { 'pic' => $pic, 'w' => $w, 'h' => $h } } + + s1overr: == overrides for a given user + s1uc: == s1usercache row hashref + s1pubstyc == hashref keyed on styleid with values being rows from s1style table + s1styc: == s1stylecache row hashref, 30 minutes + s1style: == hashref of s1style row, without formatdata + s1style_all: == hashref of s1style row, including formatdata + s1stylemap: == userid who owns the given styleid + + s2sl: == hashref of s2stylelayers { type => s2lid } + s2s: == hashref of s2styles row + s2publayers == memoize LJ::S2::get_public_layers for 10 mins + s2lo: == userid of the owner of this layer + s2c: == arrayref; [ compile time, compiled data (or 0 meaning no data) ] + + checkfriends:: == scalar maxupdate, expires after refresh interval + frgmask:: -- scalar numeric mask, 15 minutes + fgrp: == packed data, friendgroup rows for a given user + friends: == packed data, friends rows for a user + friendofs: == packed data, friendofs for a user + tu: == packed number: unixtime when user last updated + popsyn == 100 most read syndicated accounts [user, userid, synurl, numreaders], 1 hour + +sysban:ip == hashref of ip => unix expiration time +sysban:uniq == hashref of uniq => unix expiration time + + userpic. == hashref-as-arrayref (ARRAYFMT: 'userpic' in LJ::MemCache) + upicinf: == packed data, userpic keywords + upiccom: == packed data, userpic comments + upicurl: == packed data, userpic urls + mogp.up. == arrayref of paths (URLs) + +rate_eperr: == rate limiting errors sent via email for email gateway +rate:tracked: == cluster tracking on login, posts, and comments + +ml... + +includefile: == text of BML include file + + introw: -- arrayref of [ $intid, $interest, $intcount ] + intids: -- arrayref of intids for this userid + + rel::: == [{0|1}, as_of_time] + relmodu:: == as_of_time, updated when rel edges of uid change + relmodt:: == as_of_time, updated when rel edges of targetid change + + memct: -- number of memories user has + + lastcomm: -- id of the last comment the user posted via quickreply diff --git a/livejournal/doc/raw/mogile-keys.txt b/livejournal/doc/raw/mogile-keys.txt new file mode 100755 index 0000000..2a95ab8 --- /dev/null +++ b/livejournal/doc/raw/mogile-keys.txt @@ -0,0 +1,4 @@ +pp:: --- phonepost audio +up:: --- userpic image +captcha: --- captcha challenge +userbackup: --- user backup file diff --git a/livejournal/doc/raw/notes.txt b/livejournal/doc/raw/notes.txt new file mode 100755 index 0000000..aab98f7 --- /dev/null +++ b/livejournal/doc/raw/notes.txt @@ -0,0 +1,25 @@ +Debian packages required to build documentation: + + xsltproc + docbook-xml + +Useful package to edit XML in emacs, but not required: + + psgml + +The build/generate.pl will auto-download the recommended XSL if you +have a network connection and livejournal.org is alive, but you can +also use: + + docbook-xsl-stylesheets + +However, the DocBook XSL stylesheets are in a lot of flux, so using +the ones we develop and test with is recommended. + +To build: + +$ $LJHOME/doc/raw/build/generate.pl + +The docs will show up at: + + http://your.lj.server/doc/server/ diff --git a/livejournal/doc/raw/s1/s1ref2db.pl b/livejournal/doc/raw/s1/s1ref2db.pl new file mode 100755 index 0000000..054986b --- /dev/null +++ b/livejournal/doc/raw/s1/s1ref2db.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +# + + use strict; + + unless (-d $ENV{'LJHOME'}) { die "\$LJHOME not set.\n"; } + + require "$ENV{'LJHOME'}/doc/raw/build/docbooklib.pl"; + require "$ENV{'LJHOME'}/cgi-bin/propparse.pl"; + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + + my @views; + my @vars; + + LJ::load_objects_from_file("views.dat", \@views); + LJ::load_objects_from_file("vars.dat", \@vars); + + my $ret; + my %done; + foreach my $vi (@views) + { + $ret .= "S1 Variable Reference: $vi->{'props'}->{'name'}\n"; + cleanse->(\$vi->{'props'}->{'des'}); + $ret .= " $vi->{'props'}->{'des'}"; + $ret .= " {'url'}) . "'>Example page\n"; + foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars) + { + next unless ($v->{'props'}->{'scope'} =~ /\b$vi->{'name'}\b/); + next if $done{$v}; + + cleanse->(\$v->{'props'}->{'des'}); + + my $id = lc($v->{'name'}); + $ret .= "\n"; + $ret .= " \n$v->{'name'}\n$v->{'props'}->{'des'}\n"; + + $ret .= " View Types:\n"; + foreach (split (/\s*\,\s*/, $v->{'props'}->{'scope'})) + { + $ret .= "$_, "; + } + chop $ret; chop $ret; + $ret .= ""; + + # overrideable? + $ret .= " Overrideable:"; + if ($v->{'props'}->{'override'} eq "yes") { + $ret .= "Yes; users of this style may override this"; + } elsif ($v->{'props'}->{'override'} eq "only") { + $ret .= "Only; Only users of this style may override this, it cannot be defined in a style."; + } else { + $ret .= "No; users of the style cannot override this. It may only be defined in the style."; + } + $ret .= "\n"; + + if (defined $v->{'props'}->{'type'}) + { + $ret .= " Variable Type$v->{'props'}->{'type'}\n"; + } + if (defined $v->{'props'}->{'default'}) + { + $ret .= " Default Value$v->{'props'}->{'default'}\n"; + } + if (defined $v->{'props'}->{'props'}) + { + $ret .= " Properties\n"; + $ret .= " \n"; + foreach my $p (@{$v->{'props'}->{'props'}}) + { + cleanse->(\$p->{'props'}->{'des'}); + $ret .= "$p->{'name'}\n"; + $ret .= "$p->{'props'}->{'des'} "; + if ($p->{'props'}->{'min'} > 0) + { + $ret .= "[required]"; + } + $ret .= "\n"; + } + $ret .= "\n"; + } + $ret .= "\n"; + $done{$v} = 1; + } + $ret .= "\n"; + } + + print $ret; diff --git a/livejournal/doc/raw/s1/vars.dat b/livejournal/doc/raw/s1/vars.dat new file mode 100755 index 0000000..88032b5 --- /dev/null +++ b/livejournal/doc/raw/s1/vars.dat @@ -0,0 +1,2419 @@ +{ LASTN_WEBSITE +.scope +lastn +.override +yes +.editrows +4 +.type +HTML +.des +When the user has specified their website URL, this variable goes into the %%website%% property of [var[LASTN_PAGE]]. +.props +{ url +.des +The URL of the user's website. +} +{ name +.des +The name of the user's website, or "my website" if they haven't specified it. +} +} + +{ DAY_WEBSITE +.scope +day +.override +yes +.editrows +4 +.type +HTML +.des +When the user has specified their website URL, this variable goes into the %%website%% property of [var[DAY_PAGE]]. +.props +{ url +.des +The URL of the user's website. +} +{ name +.des +The name of the user's website, or "my website" if they haven't specified it. +} +} + +{ CALENDAR_WEBSITE +.scope +calendar +.override +yes +.editrows +4 +.type +HTML +.des +When the user has specified their website URL, this variable goes into the %%website%% property of [var[CALENDAR_PAGE]]. +.props +{ url +.des +The URL of the user's website. +} +{ name +.des +The name of the user's website, or "my website" if they haven't specified it. +} +} + +{ FRIENDS_WEBSITE +.scope +friends +.override +yes +.editrows +4 +.type +HTML +.des +When the user has specified their website URL, this variable goes into the %%website%% property of [var[FRIENDS_PAGE]]. +.props +{ url +.des +The URL of the user's website. +} +{ name +.des +The name of the user's website, or "my website" if they haven't specified it. +} +} + +{ FRIENDS_SKIP_FORWARD +.scope +friends +.editrows +4 +.type +HTML +.override +no +.des +The HTML to make the link to the previous (more recent) page of the friends view... going forward in time. +.props +{ numitems +.des +The number of items being displayed on the next page. +} +{ url +.des +The URL of the page. (the HREF of your A tag) +} +} + +{ FRIENDS_SKIP_BACKWARD +.scope +friends +.editrows +4 +.override +no +.type +HTML +.des +The HTML to make the link to the next (less recent) page of the friends view... going back in time. +.props +{ numitems +.des +The number of items being displayed on the next page. +} +{ url +.des +The URL of the page. (the HREF of your A tag) +} +} + +{ FRIENDS_SKIP_SPACER +.scope +friends +.editrows +2 +.type +HTML +.des +The HTML shown if both the skip backward and skip forward elements are displayed. +} + +{ FRIENDS_RANGE_MOSTRECENT +.scope +friends +.editrows +2 +.override +no +.type +HTML +.des +This should be the text that says the user is viewing the top (most recent) entries, and there are %%numitems%% of them. +.props +{ numitems +.des +The number of items being displayed. +} +} + +{ FRIENDS_RANGE_HISTORY +.scope +friends +.editrows +2 +.type +HTML +.des +This should be the text that says the user is not viewing the most recent entries, but are rather viewing a ways into the history. +.props +{ numitems +.des +The number of items being displayed. +} +{ skip +.des +The number of items that were skipped to get to this point in the history. +} +} + +{ LASTN_SKIP_LINKS +.scope +lastn +.editrows +3 +.override +no +.type +HTML +.des +If the user can go back a page or forward a page, this variable is inserted into the %%skiplinks%% property of [var[LASTN_PAGE]]. +.deps +LASTN_SKIP_BACKWARD, LASTN_SKIP_FORWARD, LASTN_SKIP_SPACER +.props +{ skipbackward +.des +If there are more entries that have been pushed off the bottom, this property +is filled with the contents of [var[LASTN_SKIP_BACKWARD]]. +} +{ skipforward +.des +If the user is not at the top of the journal (the most recent entries), +this property is filled with the contents of [var[LASTN_SKIP_FORWARD]]. +} +{ skipspacer +.des +If %%skipbackward%% and %%skipforward%% are both displayed, then +this property is equal to [var[LASTN_SKIP_SPACER]]. +} +} + +{ LASTN_SKIP_FORWARD +.scope +lastn +.editrows +4 +.override +no +.type +HTML +.des +The HTML to make the link to the previous (more recent) page of the lastn view... going forward in time. +.props +{ numitems +.des +The number of items being displayed on the next page. +} +{ url +.des +The URL of the page. (the HREF of your A tag) +} +} + +{ LASTN_SKIP_BACKWARD +.scope +lastn +.editrows +4 +.type +HTML +.des +The HTML to make the link to the next (less recent) page of the lastn view... going back in time. +.props +{ numitems +.des +The number of items being displayed on the next page. +} +{ url +.des +The URL of the page. (the HREF of your A tag) +} +} + +{ LASTN_SKIP_SPACER +.scope +lastn +.editrows +2 +.type +HTML +.des +The HTML shown if both the skip backward and skip forward elements are displayed. +} + +{ LASTN_RANGE_MOSTRECENT +.scope +lastn +.editrows +2 +.override +no +.type +HTML +.des +This should be the text that says the user is viewing the top (most recent) entries, and there are %%numitems%% of them. +.props +{ numitems +.des +The number of items being displayed. +} +} + +{ LASTN_RANGE_HISTORY +.scope +lastn +.editrows +2 +.override +no +.type +HTML +.des +This should be the text that says the user is not viewing the most recent entries, but are rather viewing a ways into the history. +.props +{ numitems +.des +The number of items being displayed. +} +{ skip +.des +The number of items that were skipped to get to this point in the history. +} +} + +{ LASTN_PAGE +.scope +lastn +.deps +LASTN_EVENT, LASTN_NEW_DAY, LASTN_END_DAY, LASTN_OPT_ITEMS, LASTN_USERPIC, LASTN_RANGE_MOSTRECENT, LASTN_RANGE_HISTORY, LASTN_SKIP_LINKS, LASTN_WEBSITE +.editrows +30 +.override +no +.des +The HTML for the most recent journal entries page (lastn mode) that's sent to the browser. Customize this as you'd like your page to look. +.type +HTML +.props +{ name +.des +The user's full name, from the "user" field in the database. +} +{ name-'s +.des +An apostrophe folled by an "s" if the user's name does not end in "s", else +just an apostrophe. Used in conjunction with the "name" property, can be +used to show possession. For instance, "%%name%%%%name-'s%% Journal" could +translate to "Bob's Journal". +} +{ events +.des +The actual 'n' number of most recent events from the user's journal. +Each individual event is formatted according to the [var[LASTN_EVENT]] and related variables. Before +events that occur on a new day, [var[LASTN_NEW_DAY]] variables are inserted as well. +.min +1 +.max +1 +} +{ username +.des +The system username of the current user, useful in creating links to other +views of your journal, like to the calendar view. +} +{ title +.des +The base title of the user's journal, which is normally used in the HTML +title tags and also sometimes in a page heading. +} +{ range +.des +Text that describes the range of items being displayed. Will be equal +to either [var[LASTN_RANGE_MOSTRECENT]] or [var[LASTN_RANGE_HISTORY]]. +} +{ skiplinks +.des +The "skiplinks" are the things that let you go back a page and forward a page. +If one of "back" or "forward" is applicable, then [var[LASTN_SKIP_LINKS]] is put here. +} +{ numitems +.des +The number of events that are going to show in the "events" property, as +specified by the [var[LASTN_OPT_ITEMS]] variable. +Deprecated: you should now use %%range%% instead of this property. +} +{ userpic +.des +An IMG tag showing your uploaded picture, if any. See [var[LASTN_USERPIC]]. +} +{ website +.des +If the user has specified their website, this block is filled with the contents of [var[LASTN_WEBSITE]]. +} +{ head +.des +Any user-specified content to go inside the document's <HEAD>, like CSS or META tags. The value is [var[GLOBAL_HEAD]] followed by [var[LASTN_HEAD]]. You shouldn't define the *_HEAD variables in the style, as users should set them themselves. +} +{ urlfriends +.des +URL to user's friends view. +} +{ urlcalendar +.des +URL to user's calendar view. +} +} + +{ LASTN_USERPIC +.scope +lastn +.type +HTML +.des +Creates the IMG tag needed to show your picture on the last-n page. +.props +{ src +.des +The IMG SRC= attribute. +} +{ width +.des +The IMG WIDTH= attribute. +} +{ height +.des +The IMG HEIGHT= attribute. +} +} + +{ LASTN_END_DAY +.scope +lastn +.deps +LASTN_NEW_DAY +.type +HTML +.des +The opposite of [var[LASTN_NEW_DAY]]. This variable is inserted into %%events%% in the [var[LASTN_PAGE]]. +} + +{ LASTN_NEW_DAY +.scope +lastn +.type +HTML +.des +Before any [var[LASTN_EVENT]] that's on a day that no other event has been shown before, this block is inserted into %%events%% in the [var[LASTN_PAGE]]. +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +} + +{ LASTN_SUBJECT +.scope +lastn +.editrows +5 +.des +When a journal entry has a subject, this variable is inserted into the %%subject%% property of [var[LASTN_EVENT]]. +.type +HTML +.props +{ subject +.des +The journal entry's subject. +} +} + +{ LASTN_EVENT_PRIVATE +.scope +lastn +.editrows +10 +.override +no +.des +An optional specialized form of [var[LASTN_EVENT]] to be used on entries that are marked as "private" (only the original poster can see them). If you leave this blank, the standard event variable will be used instead. +} + +{ LASTN_EVENT_PROTECTED +.scope +lastn +.editrows +10 +.des +An optional specialized form of [var[LASTN_EVENT]] to be used on entries that are marked as "friends" or "custom" (only a select group of people can see them). If you leave this blank, the standard event variable will be used instead. +.override +no +} + +{ FRIENDS_EVENT_PRIVATE +.scope +friends +.editrows +10 +.des +An optional specialized form of [var[FRIENDS_EVENT]] to be used on entries that are marked as "private" (only the original poster can see them). If you leave this blank, the standard event variable will be used instead. +.override +no +} + +{ FRIENDS_EVENT_PROTECTED +.scope +friends +.editrows +10 +.override +no +.des +An optional specialized form of [var[FRIENDS_EVENT]] to be used on entries that are marked as "friends" or "custom" (only a select group of people can see them). If you leave this blank, the standard event variable will be used instead. +} + +{ DAY_EVENT_PRIVATE +.scope +day +.editrows +10 +.override +no +.des +An optional specialized form of [var[DAY_EVENT]] to be used on entries that are marked as "private" (only the original poster can see them). If you leave this blank, the standard event variable will be used instead. +} + +{ DAY_EVENT_PROTECTED +.scope +day +.editrows +10 +.override +no +.des +An optional specialized form of [var[DAY_EVENT]] to be used on entries that are marked as "friends" or "custom" (only a select group of people can see them). If you leave this blank, the standard event variable will be used instead. +} + +{ LASTN_EVENT +.scope +lastn +.deps +LASTN_OPT_ITEMS, LASTN_DATE_FORMAT, LASTN_TALK_LINKS, LASTN_SUBJECT, LASTN_EVENT_PRIVATE, LASTN_EVENT_PROTECTED, LASTN_CURRENTS, LASTN_ALTPOSTER +.editrows +10 +.des +An event from the user's journal. A bunch of these (as specified by [var[LASTN_OPT_ITEMS]]) get put together to form the %%events%% property of the [var[LASTN_PAGE]] variable. See also [var[LASTN_EVENT_PRIVATE]] and [var[LASTN_EVENT_PROTECTED]]. +.type +HTML +.props +{ datetime +.des +The date and/or time of the event, as formatted by [var[LASTN_DATE_FORMAT]]. +} +{ event +.des +The actual event from the journal. +.min +1 +} +{ talklinks +.des +The value of [var[LASTN_TALK_LINKS]]. If you don't want message boards on your journal, don't use this, or make [var[LASTN_TALK_LINKS]] empty. +} +{ subject +.des +When the journal entry has a subject, then a [var[LASTN_SUBJECT]] is inserted into this property. That way you can do some specialized HTML only when there's a subject. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +{ currents +.des +If the user has specified either a current mood or their current music, then a [var[LASTN_CURRENTS]] gets inserted in here. +} +{ altposter +.des +If this is a shared journal (like a news account) and somebody other than the journal owner is posting, [var[LASTN_ALTPOSTER]] goes into this. +} +} + +{ LASTN_CURRENTS +.scope +lastn +.deps +LASTN_CURRENT +.des +When a user has specified "current" information (like current music or current mood), then this variable separates those entries apart from the rest of the journal entry in [var[LASTN_EVENT]]. +.editrows +4 +.type +HTML +.props +{ currents +.des +This property is one or more [var[LASTN_CURRENT]] variables joined together, one for each current item. +} +} + +{ LASTN_CURRENT +.scope +lastn +.des +When a user has specified "current" information (like current music or current mood), then this variable is added to the %%currents%% property of [var[LASTN_CURRENTS]]. +.editrows +4 +.type +HTML +.props +{ what +.des +Specifies what this is the current item of. It'll be something like "Mood", "Music", or "Weather". You can change the case with the transforms (%%lc:what%%, etc...) +} +{ value +.des +The actual current whatever. +} +} + +{ FRIENDS_CURRENTS +.scope +friends +.deps +FRIENDS_CURRENT +.des +When a user has specified "current" information (like current music or current mood), then this variable separates those entries apart from the rest of the journal entry in [var[FRIENDS_EVENT]]. +.editrows +4 +.type +HTML +.props +{ currents +.des +This property is one or more [var[FRIENDS_CURRENT]] variables joined together, one for each current item. +} +} + +{ FRIENDS_CURRENT +.scope +friends +.des +When a user has specified "current" information (like current music or current mood), then this variable is added to the %%currents%% property of [var[FRIENDS_CURRENTS]]. +.editrows +4 +.type +HTML +.props +{ what +.des +Specifies what this is the current item of. It'll be something like "Mood", "Music", or "Weather". You can change the case with the transforms (%%lc:what%%, etc...) +} +{ value +.des +The actual current whatever. +} +} + +{ DAY_CURRENTS +.scope +day +.deps +DAY_CURRENT +.des +When a user has specified "current" information (like current music or current mood), then this variable separates those entries apart from the rest of the journal entry in [var[DAY_EVENT]]. +.editrows +4 +.type +HTML +.props +{ currents +.des +This property is one or more [var[DAY_CURRENT]] variables joined together, one for each current item. +} +} + +{ DAY_CURRENT +.scope +day +.des +When a user has specified "current" information (like current music or current mood), then this variable is added to the %%currents%% property of [var[DAY_CURRENTS]]. +.editrows +4 +.type +HTML +.props +{ what +.des +Specifies what this is the current item of. It'll be something like "Mood", "Music", or "Weather". You can change the case with the transforms (%%lc:what%%, etc...) +} +{ value +.des +The actual current whatever. +} +} + +{ LASTN_DATE_FORMAT +.scope +lastn +.override +yes +.des +Describes how dates/times are formatted in each [var[LASTN_EVENT]] variable. +.type +HTML +.editrows +1 +.editcols +60 +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +{ ap +.des +AM or PM as a one-character lower-case "a" or "p". +} +{ AP +.des +AM or PM as a one-character upper-case "A" or "P". +} +{ ampm +.des +AM or PM as a two-character lower-case "am" or "pm". +} +{ AMPM +.des +AM or PM as a two-character upper-case "AM" or "PM". +} +{ min +.des +Minutes. 00-59. +} +{ 12h +.des +Hour. 1-12. +} +{ 12hh +.des +Hour. 01-12. +} +{ 24h +.des +Hour. 1-23. +} +{ 24hh +.des +Hour. 01-23. +} +} + +{ LASTN_OPT_ITEMS +.scope +lastn +.override +yes +.des +This is an integer value between 1 and 50 that sets how many +items are shown in the "events" property of the [var[LASTN_PAGE]] variable. +.type +integer +.editrows +1 +.editcols +10 +.default +20 +} + +{ CALENDAR_YEAR_LINK +.scope +calendar +.editrows +2 +.type +HTML +.des +A link to view a different year in the calendar. +.props +{ url +.des +The URL to go to the other year. +} +{ yyyy +.des +The 4 digit year this link goes to. +} +{ yy +.des +The 2 digit year this link goes to. +} +} + +{ CALENDAR_YEAR_DISPLAYED +.scope +calendar +.editrows +2 +.type +HTML +.des +An bit of HTML that goes in the [var[CALENDAR_YEAR_LINKS]] for the displayed year. +.props +{ yyyy +.des +The 4 digit year that's being displayed. +} +{ yy +.des +The 2 digit year that's being displayed. +} +} + +{ CALENDAR_YEAR_LINKS +.scope +calendar +.deps +CALENDAR_YEAR_LINK, CALENDAR_YEAR_DISPLAYED +.editrows +2 +.type +HTML +.des +When there are more than 1 year of entries to be shown, this variable is inserted into the %%yearlinks%% property of [var[CALENDAR_PAGE]]. The purpose of it is to indicate which year is selected and let you move between the different years by clicking links. +.props +{ years +.des +This property is made up of [var[CALENDAR_YEAR_LINK]] and [var[CALENDAR_YEAR_DISPLAYED]] variables, in the order you indicated in [var[CALENDAR_SORT_MODE]]. +} +} + +{ CALENDAR_PAGE +.scope +calendar +.deps +CALENDAR_SORT_MODE, CALENDAR_MONTH, CALENDAR_NEW_YEAR, CALENDAR_WEBSITE, CALENDAR_YEAR_LINKS +.editrows +30 +.des +The HTML page layout for the [view[calendar]] view. +.type +HTML +.props +{ name +.des +The user's full name, from the "user" field in the database. +} +{ name-'s +.des +An apostrophe folled by an "s" if the user's name does not end in "s", else +just an apostrophe. Used in conjunction with the "name" property, can be +used to show possession. For instance, "%%name%%%%name-'s%% Journal" could +translate to "Bob's Journal". This is old. You should just use the title instead. +} +{ title +.des +The base title of the user's journal, which is normally used in the HTML +title tags and headings alongside something which indicates that this is +a calendar view. +} +{ yearlinks +.des +When more than one year of entries are being displayed, the [var[CALENDAR_YEAR_LINKS]] variable goes in here. +} +{ months +.des +All the [var[CALENDAR_MONTH]] and [var[CALENDAR_NEW_YEAR]] variables grouped together, either in forward or reverse chronological order, depending on the value of [var[CALENDAR_SORT_MODE]]. +.min +1 +.max +1 +} +{ username +.des +The system username of the current user, useful in creating links to other +views of your journal, like to the calendar view. +} +{ website +.des +If the user has specified their website, this block is filled with the contents of [var[CALENDAR_WEBSITE]]. +} +{ head +.des +Any user-specified content to go inside the document's <HEAD>, like CSS or META tags. The value is [var[GLOBAL_HEAD]] followed by [var[CALENDAR_HEAD]]. You shouldn't define the *_HEAD variables in the style, as users should set them themselves. +} +{ urlfriends +.des +URL to user's friends view. +} +{ urllastn +.des +URL to user's lastn view. +} +} + +{ CALENDAR_NEW_YEAR +.scope +calendar +.des +Before any [var[CALENDAR_MONTH]] HTML for a month of a year that hasn't been shown yet, one of these variables gets inserted into %%months%% of [var[CALENDAR_PAGE]]. +.type +HTML +.props +{ yy +.des +Year. Two digit. +} +{ yyyy +.des +Year. Four digit. +} +} + +{ CALENDAR_MONTH +.scope +calendar +.deps +CALENDAR_WEEK +.editrows +20 +.des +The HTML for a month in the [view[calendar]] view. A bunch of these variables as well as [var[CALENDAR_NEW_YEAR]] variables form the %%months%% property of the [var[CALENDAR_PAGE]] variable. +.props +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ weeks +.des +All the weeks for this month, consisting of a bunch of [var[CALENDAR_WEEK]] variables. +} +{ urlmonthview +.des +The URL to a page showing all posts in this month, by subject. +} +} + +{ CALENDAR_WEEK +.scope +calendar +.deps +CALENDAR_DAY, CALENDAR_EMPTY_DAYS +.editrows +10 +.des +HTML for a week in the calendar. 4-5 of these week objects get concatenated together into the %%weeks%% property of the [var[CALENDAR_MONTH]]. +.props +{ days +.des +The days in the week, made up from a bunch of [var[CALENDAR_DAY]] variables. +} +{ emptydays_beg +.des +The empty days at the beginning of the month, from the [var[CALENDAR_EMPTY_DAYS]] variable. +} +{ emptydays_end +.des +The empty days at the end of the month, from the [var[CALENDAR_EMPTY_DAYS]] variable. +} +} + +{ CALENDAR_EMPTY_DAYS +.scope +calendar +.des +At the beginning and end of the month, there are possibilities that squares on the calendar are blank. For instance, if the 1st of the month lands on a Wednesday, the Sunday-Tuesdays squares are non-existant. In the contruction of a pretty HTML table, it will be necessary to make a TD cell with a COLSPAN equal to the number of empty days. If you are not making your calendar view look like a calendar, then simply leave this variable blank. Note: this variable is used in the %%empydays_beg%% and %%emptydays_end%% properties of the [var[CALENDAR_WEEK]] variable. +.props +{ numempty +.des +The number of empty days. Useful as the COLSPAN of table cells. +} +} + +{ CALENDAR_DAY +.scope +calendar +.deps +CALENDAR_DAY_EVENT, CALENDAR_DAY_NOEVENT +.des +This is a block of HTML for a day on the calendar, which gets insert into %%days%% in the [var[CALENDAR_WEEK]] variable. +.props +{ d +.des +Day of the month. (1-31) +} +{ eventcount +.des +The number of events (journal entries) that occurred on that day. +} +{ dayevent +.des +If the number of events (journal entries) is greater than zero for any given day, +this property will be equal to the contents of a [var[CALENDAR_DAY_EVENT]] variable. This is +useful for when you only want to show certain HTML on days with events. +} +{ daynoevent +.des +If the number of events (journal entries) is equal to zero for any given day, +this property will be equal to the contents of a [var[CALENDAR_DAY_NOEVENT]] variable. This is +useful for when you only want to show certain HTML on days without events. +} +} + +{ CALENDAR_DAY_EVENT +.scope +calendar +.des +Some HTML that gets inserted into [var[CALENDAR_DAY]] variables when the number of events (journal entries) for that day is non-zero. For instance, this is useful if you want to display a link to the [view[day]] view to see what the user's events for that day were. On a day with zero events, you wouldn't want a link, so you'd put your HTML into this variable, not in [var[CALENDAR_DAY]]. However, in [var[CALENDAR_DAY]], make sure you use %%dayevent%% somewhere. +.props +{ eventcount +.des +The number of events that occured on that day. +} +{ dayurl +.des +The URL of the corresponding [view[day]] view, which shows all the events. +} +} + +{ CALENDAR_DAY_NOEVENT +.scope +calendar +.des +Some HTML that gets inserted into [var[CALENDAR_DAY]] variables when the number of events (journal entries) for that day is zero. +} + +{ CALENDAR_SORT_MODE +.scope +calendar +.override +yes +.editrows +1 +.type +option +.des +Determines whether months in the calendar mode (variable: [var[CALENDAR_MONTH]]) are shown in "reverse" order (most recent month at top) or in "forward" order (oldest months at top). The value of this variable should be either "forward" or "reverse", without quotes. By default, reverse will be assumed. +} + +{ DAY_PAGE +.scope +day +.deps +DAY_EVENTS, DAY_NOEVENTS, DAY_WEBSITE +.editrows +30 +.type +HTML +.des +The HTML for the [view[day]] view, after somebody clicks a day on the [view[calendar]]. +.props +{ username +.des +The username of the user. +} +{ title +.des +The base title of the user's journal, which is normally used in the HTML +title tags and headings, alongside a reference to the date being viewed. +} +{ name +.des +The name of the user whose journal it is. +} +{ name-'s +.des +An apostrophe folled by an "s" if the user's name does not end in "s", else +just an apostrophe. Used in conjunction with the "name" property, can be +used to show possession. For instance, "%%name%%%%name-'s%% Journal" could +translate to "Bob's Journal". +} +{ website +.des +If the user has specified their website, this block is filled with the contents of [var[DAY_WEBSITE]]. +} +{ events +.des +If events occurred on this day, then this is equal to [var[DAY_EVENTS]], else it is equal to [var[DAY_NOEVENTS]]. +.min +1 +.max +1 +} +{ prevday_url +.des +A URL to the day view for the previous day. +} +{ nextday_url +.des +A URL to the day view for the next day. +} +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +{ head +.des +Any user-specified content to go inside the document's <HEAD>, like CSS or META tags. The value is [var[GLOBAL_HEAD]] followed by [var[DAY_HEAD]]. You shouldn't define the *_HEAD variables in the style, as users should set them themselves. +} +{ urllastn +.des +URL to user's lastn view. +} +{ urlcalendar +.des +URL to user's calendar view. +} +{ urlfriends +.des +URL to user's friends view. +} +} + +{ DAY_EVENTS +.scope +day +.deps +DAY_SORT_MODE, DAY_EVENT +.editrows +10 +.type +HTML +.des +When events occur on a given day in the [view[day]] view, this variable gets inserted into %%events%% of [var[DAY_PAGE]]. +.props +{ events +.des +A bunch of [var[DAY_EVENT]] variables for the events that occured on that day, in the order dictated by [var[DAY_SORT_MODE]]. +} +} + +{ DAY_NOEVENTS +.scope +day +.editrows +8 +.type +HTML +.des +When no events occur on a given day in the [view[day]] view, this variable gets inserted into %%events%% of [var[DAY_PAGE]]. +} + +{ DAY_SORT_MODE +.scope +day +.editrows +1 +.type +option +.des +Determines whether events in the [view[day]] view (variable: [var[DAY_PAGE]]) are shown in "forward" order (earlier events first) or in "reverse" order (newest events shown first). The value of this variable should be either "forward" or "reverse", without quotes. +.default +forward +} + +{ DAY_SUBJECT +.scope +day +.editrows +5 +.des +When a journal entry has a subject, this variable is inserted into the %%subject%% property of [var[DAY_EVENT]]. +.type +HTML +.props +{ subject +.des +The journal entry's subject. +} +} + +{ DAY_EVENT +.scope +day +.deps +DAY_DATE_FORMAT, DAY_TALK_LINKS, DAY_SUBJECT, DAY_EVENT_PRIVATE, DAY_EVENT_PROTECTED, DAY_CURRENTS +.des +An event in the journal, which goes in %%events%% of [var[DAY_PAGE]]. See also [var[DAY_EVENT_PRIVATE]] and [var[DAY_EVENT_PROTECTED]]. +.type +HTML +.props +{ datetime +.des +The date and/or time of the event, as formatted by [var[DAY_DATE_FORMAT]]. +} +{ event +.des +The actual event from the journal. +} +{ talklinks +.des +The value of [var[DAY_TALK_LINKS]]. If you don't want message boards on your journal, don't use this, or make [var[DAY_TALK_LINKS]] empty. +} +{ subject +.des +When the journal entry has a subject, then a [var[DAY_SUBJECT]] is inserted into this property. That way you can do some specialized HTML only when there's a subject. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +{ currents +.des +If the user has specified either a current mood or their current music, then a [var[DAY_CURRENTS]] gets inserted in here. +} +} + +{ DAY_DATE_FORMAT +.scope +day +.editrows +1 +.override +yes +.des +Describes how dates/times are formatted in each [var[DAY_EVENT]] variable. +.type +HTML +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +{ ap +.des +AM or PM as a one-character lower-case "a" or "p". +} +{ AP +.des +AM or PM as a one-character upper-case "A" or "P". +} +{ ampm +.des +AM or PM as a two-character lower-case "am" or "pm". +} +{ AMPM +.des +AM or PM as a two-character upper-case "AM" or "PM". +} +{ min +.des +Minutes. 00-59. +} +{ 12h +.des +Hour. 1-12. +} +{ 12hh +.des +Hour. 01-12. +} +{ 24h +.des +Hour. 1-23. +} +{ 24hh +.des +Hour. 01-23. +} +} + + +{ SEARCH_PAGE +.scope +search +.des +HTML for a page that lets people search journals. +.type +HTML +.props +{ username +.des +The username of the user whose journal it is. +} +{ name +.des +The name of the user. +} +{ form +.des +The HTML <FORM> to the end </FORM> so you don't have to generate it yourself. (which is actually from [var[SEARCH_FORM]]) +} +} + +{ SEARCH_FORM +.scope +search +.des +HTML for the <FORM> to let users search journals. Unless you know what you're doing, don't override this... just leave it as is and use it as %%form%% in the [var[SEARCH_PAGE]] variable. +.type +HTML +.props +{ username +.des +The username of the user whose journal it is. +} +} + +{ SEARCHRES_PAGE +.scope +searchres +.des +HTML for the search results page. +.type +HTML +.props +{ username +.des +The username of the user whose journal it is. +} +{ name +.des +The name of the user. +} +{ nummatches +.des +The number of matches that were found +} +{ matches +.des +The matches that were found. If zero matches are found, this will equal [var[SEARCHRES_NOMATCHES]], else it will equal [var[SEARCHRES_MATCHES]]. +.min +1 +} +} + +{ SEARCHRES_NOMATCHES +.scope +searchres +.des +HTML for when people perform a search and there are no matching journal entries. +.type +HTML +} + +{ SEARCHRES_MATCHES +.scope +searchres +.des +The matching journal entries that were found after performing a search. +.type +HTML +.props +{ matches +.des +All the [var[SEARCHRES_MATCH]] variables added together, one for each match. +.min +1 +} +} + +{ SEARCHRES_MATCH +.scope +searchres +.des +A search match, which goes in %%matches%% of [var[SEARCHRES_MATCHES]]. +.type +HTML +.props +{ datetime +.des +The date and/or time of the event, as formatted by [var[SEARCHRES_DATE_FORMAT]]. +} +{ event +.des +The actual event from the journal. +} +} + +{ SEARCHRES_DATE_FORMAT +.scope +searchres +.des +Describes how dates/times are formatted in each [var[SEARCHRES_MATCH]] variable. +.type +HTML +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +{ ap +.des +AM or PM as a one-character lower-case "a" or "p". +} +{ AP +.des +AM or PM as a one-character upper-case "A" or "P". +} +{ ampm +.des +AM or PM as a two-character lower-case "am" or "pm". +} +{ AMPM +.des +AM or PM as a two-character upper-case "AM" or "PM". +} +{ min +.des +Minutes. 00-59. +} +{ 12h +.des +Hour. 1-12. +} +{ 12hh +.des +Hour. 01-12. +} +{ 24h +.des +Hour. 1-23. +} +{ 24hh +.des +Hour. 01-23. +} +} + +{ FRIENDS_SKIP_LINKS +.scope +friends +.editrows +3 +.type +HTML +.des +If the user can go back a page or forward a page, this variable is inserted into the %%skiplinks%% property of [var[FRIENDS_PAGE]]. +.deps +FRIENDS_SKIP_BACKWARD, FRIENDS_SKIP_FORWARD, FRIENDS_SKIP_SPACER +.props +{ skipbackward +.des +If there are more entries that have been pushed off the bottom, this property +is filled with the contents of [var[FRIENDS_SKIP_BACKWARD]]. +} +{ skipforward +.des +If the user is not at the top of the journal (the most recent entries), +this property is filled with the contents of [var[FRIENDS_SKIP_FORWARD]]. +} +{ skipspacer +.des +If %%skipbackward%% and %%skipforward%% are both displayed, then +this property is equal to [var[FRIENDS_SKIP_SPACER]]. +} +} + + +{ FRIENDS_PAGE +.scope +friends +.deps +FRIENDS_OPT_ITEMS, FRIENDS_NOFRIENDS, FRIENDS_EVENTS, FRIENDS_RANGE_MOSTRECENT, FRIENDS_RANGE_HISTORY, FRIENDS_SKIP_LINKS, FRIENDS_WEBSITE +.editrows +30 +.des +The HTML for the friends' most recent journal entries page (friends view) that's sent to the browser. Customize this as you'd like your page to look. +.type +HTML +.props +{ name +.des +The user's full name, from the "user" field in the database. +} +{ name-'s +.des +An apostrophe folled by an "s" if the user's name does not end in "s", else +just an apostrophe. Used in conjunction with the "name" property, can be +used to show possession. For instance, "%%name%%%%name-'s%% Journal" could +translate to "Bob's Journal". +} +{ website +.des +If the user has specified their website, this block is filled with the contents of [var[FRIENDS_WEBSITE]]. +} +{ events +.des +If friends are defined, this is equal to the [var[FRIENDS_EVENTS]] variable, else it is equal to a message saying that no friends is defined... [var[FRIENDS_NOFRIENDS]]. +.min +1 +.max +1 +} +{ username +.des +The system username of the current user, useful in creating links to other +views of your journal, like to the calendar view. +} +{ title +.des +A title the user has chosen for their friends page. Normally used in the HTML +title tags and also sometimes in a page heading. +} +{ range +.des +Text that describes the range of items being displayed. Will be equal +to either [var[FRIENDS_RANGE_MOSTRECENT]] or [var[FRIENDS_RANGE_HISTORY]]. +} +{ skiplinks +.des +The "skiplinks" are the things that let you go back a page and forward a page. +If one of "back" or "forward" is applicable, then [var[FRIENDS_SKIP_LINKS]] is put here. +} +{ numitems +.des +The number of events that are going to show in the "events" property, as +specified by the [var[FRIENDS_OPT_ITEMS]] variable. +Deprecated: you should now use %%range%% instead of this property. +} +{ head +.des +Any user-specified content to go inside the document's <HEAD>, like CSS or META tags. The value is [var[GLOBAL_HEAD]] followed by [var[FRIENDS_HEAD]]. You shouldn't define the *_HEAD variables in the style, as users should set them themselves. +} +{ urllastn +.des +URL to user's lastn view. +} +{ urlcalendar +.des +URL to user's calendar view. +} +} + +{ FRIENDS_EVENTS +.scope +friends +.deps +FRIENDS_NEW_DAY, FRIENDS_EVENT, FRIENDS_END_DAY +.type +HTML +.des +A container for a bunch of [var[FRIENDS_EVENT]] variables. Gets inserted into %%events%% of [var[FRIENDS_PAGE]]. +.props +{ events +.des +The actual 'n' number of most recent events from the user's friends' journals. +Each individual event is formatted according to the [var[FRIENDS_EVENT]] variable. Before +and after unique days, [var[FRIENDS_NEW_DAY]] and [var[FRIENDS_END_DAY]] variables are inserted as well. +} +} + +{ FRIENDS_END_DAY +.scope +friends +.type +HTML +.des +The opposite of [var[FRIENDS_NEW_DAY]]. This variable is inserted into %%events%% in the [var[FRIENDS_EVENTS]]. +} + +{ FRIENDS_NEW_DAY +.scope +friends +.type +HTML +.des +Before any [var[FRIENDS_EVENT]] that's on a day that no other event has been shown before, this block is inserted into %%events%% in the [var[FRIENDS_EVENTS]]. +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +} + +{ FRIENDS_SUBJECT +.scope +friends +.editrows +5 +.des +When a journal entry has a subject, this variable is inserted into the %%subject%% property of [var[FRIENDS_EVENT]]. +.type +HTML +.props +{ subject +.des +The journal entry's subject. +} +} + +{ FRIENDS_NO_SUBJECT +.scope +friends +.editrows +5 +.des +When a journal entry does NOT have a subject, this variable is inserted into the %%subject%% property of [var[FRIENDS_EVENT]]. +.type +HTML +.props +{ friend +.des +Friend's user name. +} +{ name +.des +Friend's name +} +} + +{ FRIENDS_EVENT +.scope +friends +.deps +FRIENDS_DATE_FORMAT, FRIENDS_FRIENDPIC, FRIENDS_TALK_LINKS, FRIENDS_SUBJECT, FRIENDS_NO_SUBJECT, FRIENDS_EVENT_PRIVATE, FRIENDS_EVENT_PROTECTED, FRIENDS_ALTPOSTER, FRIENDS_CURRENTS +.editrows +10 +.des +An event from the user's journal. A bunch of these (as specified by [var[FRIENDS_OPT_ITEMS]]) get put together to form the %%events%% property of the [var[FRIENDS_EVENTS]] variable. See also [var[FRIENDS_EVENT_PRIVATE]] and [var[FRIENDS_EVENT_PROTECTED]]. +.type +HTML +.props +{ user +.des +The username of the friend whose journal entry is being displayed. +} +{ bgcolor +.des +The background color of the friend. +} +{ fgcolor +.des +The foreground color of the friend. +} +{ datetime +.des +The date and/or time of the event, as formatted by [var[FRIENDS_DATE_FORMAT]]. +} +{ event +.des +The actual event from the journal. +.min +1 +} +{ friendpic +.des +A picture of this friend, if they've uploaded a picture. See [var[FRIENDS_FRIENDPIC]]. +} +{ talklinks +.des +The value of [var[FRIENDS_TALK_LINKS]]. If you don't want message boards on your journal, don't use this, or make [var[FRIENDS_TALK_LINKS]] empty. +} +{ subject +.des +When the journal entry has a subject, then a [var[FRIENDS_SUBJECT]] is inserted into this property. That way you can do some specialized HTML only when there's a subject. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +{ altposter +.des +If this is a shared journal, and somebody other than the journal creator is posting an item, this property gets the value of [var[FRIENDS_ALTPOSTER]]. +} +{ currents +.des +If the user has specified either a current mood or their current music, then a [var[FRIENDS_CURRENTS]] gets inserted in here. +} +} + +{ FRIENDS_ALTPOSTER +.scope +friends +.type +HTML +.des +When a user other than the journal owner posts a top-level journal entry in a journal, this variable is inserted into the %%altposter%% proprety of [var[FRIENDS_EVENT]]. +.editrows +4 +.props +{ poster +.des +The username that's posting. +} +{ owner +.des +The username that owns the journal (the friend's username). +} +{ bgcolor +.des +The background color of the friend. +} +{ fgcolor +.des +The foreground color of the friend. +} +} + +{ LASTN_ALTPOSTER +.scope +lastn +.deps +LASTN_ALTPOSTER_PIC +.type +HTML +.des +When a user other than the journal owner posts a top-level journal entry in a journal, this variable is inserted into the %%altposter%% property of [var[LASTN_EVENT]]. +.editrows +4 +.props +{ poster +.des +The username that's posting. +} +{ owner +.des +The username that owns the journal. +} +{ pic +.des +If the user posting has a picture, the contents of [var[LASTN_ALTPOSTER_PIC]] go here. +} +} + +{ LASTN_ALTPOSTER_PIC +.scope +lastn +.type +HTML +.des +Goes into %%pic%% in [var[LASTN_ALTPOSTER]]. +.editrows +3 +.props +{ src +.des +The IMG SRC= attribute. +} +{ width +.des +The IMG WIDTH= attribute. +} +{ height +.des +The IMG HEIGHT= attribute. +} +} + +{ FRIENDS_FRIENDPIC +.scope +friends +.type +HTML +.des +Creates the IMG tag needed to show your friend's picture on the friends view page. +.props +{ src +.des +The IMG SRC= attribute. +} +{ width +.des +The IMG WIDTH= attribute. +} +{ height +.des +The IMG HEIGHT= attribute. +} +} + +{ FRIENDS_DATE_FORMAT +.scope +friends +.override +yes +.editrows +1 +.des +Describes how dates/times are formatted in each [var[FRIENDS_EVENT]] variable. +.type +HTML +.props +{ dayshort +.des +Day of week. Short form. Example: Mon, Tue, Wed... +} +{ daylong +.des +Day of week. Long form. Example: Monday, Tuesday, Wednesday... +} +{ monshort +.des +Month. Short form. Example: Jan, Feb, Mar... +} +{ monlong +.des +Month. Long form. Example: January, February, March... +} +{ yy +.des +Year, two digit. +} +{ yyyy +.des +Year, four digit. +} +{ m +.des +Month. 1-12. +} +{ mm +.des +Month. 01-12. +} +{ d +.des +Day. 1-31. +} +{ dd +.des +Day. 01-31. +} +{ dth +.des +Day plus ordinal. 1st, 2nd, 3rd, 4th, 5th... +} +{ ap +.des +AM or PM as a one-character lower-case "a" or "p". +} +{ AP +.des +AM or PM as a one-character upper-case "A" or "P". +} +{ ampm +.des +AM or PM as a two-character lower-case "am" or "pm". +} +{ AMPM +.des +AM or PM as a two-character upper-case "AM" or "PM". +} +{ min +.des +Minutes. 00-59. +} +{ 12h +.des +Hour. 1-12. +} +{ 12hh +.des +Hour. 01-12. +} +{ 24h +.des +Hour. 1-23. +} +{ 24hh +.des +Hour. 01-23. +} +} + +{ FRIENDS_OPT_ITEMS +.scope +friends +.override +yes +.editrows +1 +.editcols +10 +.des +This is an integer value between 1 and 50 that sets how many +items are shown in the "events" property of the [var[FRIENDS_PAGE]] variable. +.type +integer +.default +20 +} + +{ FRIENDS_NOFRIENDS +.scope +friends +.type +HTML +.des +This variable is used as %%events%% in [var[FRIENDS_PAGE]] if the user has not defined +any friends. +.props +{ name +.des +The user's full name, from the "user" field in the database. +} +{ name-'s +.des +An apostrophe folled by an "s" if the user's name does not end in "s", else +just an apostrophe. Used in conjunction with the "name" property, can be +used to show possession. For instance, "%%name%%%%name-'s%% Journal" could +translate to "Bob's Journal". +} +{ username +.des +The system username of the current user, useful in creating links to other +views of your journal, like to the calendar view. +} +} + +{ LASTN_TALK_LINKS +.scope +lastn +.override +yes +.deps +LASTN_TALK_READLINK +.type +HTML +.des +Define here HTML (if any) that you want to be displayed for the links to read comments and post comments on the current event. The contents of this variable are inserted into %%talklinks%% in [var[LASTN_EVENT]] if the user has their message boards enabled. +.props +{ readlink +.des +If there are existing comments for this event, then the value of [var[LASTN_TALK_READLINK]] is inserted into %%readlink%% +} +{ urlpost +.des +The URL you need to use in your <a href=...> tag to link to the "leave a comment" page. +} +{ urlread +.des +The URL to use in your <a href=...> tag to link to the "read comments" page. +} +{ messagecount +.des +The number of replies, or zero. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +} + +{ LASTN_TALK_READLINK +.scope +lastn +.override +yes +.type +HTML +.des +If there are comments on the existing journal entry being displayed, then one of these variables is inserted into the %%readlink%% property of [var[LASTN_TALK_LINKS]]. +.props +{ urlread +.des +The URL you need to use in your <A HREF=...> tag to link to the page where you read the comments. +} +{ messagecount +.des +The number of comments that people have left in response to this journal entry. +} +{ mc-plural-s +.des +This property is "s" if messagecount is not equal to 1, so you can do things like "1 comment" or "2 comments". Use like: %%messagecount%% comment%%mc-plural-s%% +} +{ mc-plural-es +.des +This property is "es" if messagecount is not equal to 1, so you can do things like "1 kiss" or "2 kisses". Use like: %%messagecount%% comment%%mc-plural-es%% +} +{ mc-plural-ies +.des +This property is "ies" if messagecount is not equal to 1, else it is "y", so you can do things like "1 reply" or "2 replies". Use like: %%messagecount%% comment%%mc-plural-ies%% +} +} + +{ DAY_TALK_LINKS +.scope +day +.override +yes +.deps +DAY_TALK_READLINK +.type +HTML +.des +Define here HTML (if any) that you want to be displayed for the links to read comments and post comments on the current event. The contents of this variable are inserted into %%talklinks%% in [var[DAY_EVENT]] if the user has their message boards enabled. +.props +{ readlink +.des +If there are existing comments for this event, then the value of [var[DAY_TALK_READLINK]] is inserted into %%readlink%% +} +{ urlpost +.des +The URL you need to use in your <a href=...> tag to link to the "leave a comment" page. +} +{ urlread +.des +The URL to use in your <a href=...> tag to link to the "read comments" page. +} +{ messagecount +.des +The number of replies, or zero. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +} + +{ DAY_TALK_READLINK +.scope +day +.override +yes +.type +HTML +.des +If there are comments on the existing journal entry being displayed, then one of these variables is inserted into the %%readlink%% property of [var[DAY_TALK_LINKS]]. +.props +{ urlread +.des +The URL you need to use in your <A HREF=...> tag to link to the page where you read the comments. +} +{ messagecount +.des +The number of comments that people have left in response to this journal entry. +} +{ mc-plural-s +.des +This property is "s" if messagecount is not equal to 1, so you can do things like "1 comment" or "2 comments". Use like: %%messagecount%% comment%%mc-plural-s%% +} +{ mc-plural-es +.des +This property is "es" if messagecount is not equal to 1, so you can do things like "1 kiss" or "2 kisses". Use like: %%messagecount%% comment%%mc-plural-es%% +} +{ mc-plural-ies +.des +This property is "ies" if messagecount is not equal to 1, else it is "y", so you can do things like "1 reply" or "2 replies". Use like: %%messagecount%% comment%%mc-plural-ies%% +} +} + +{ FRIENDS_TALK_LINKS +.scope +friends +.override +yes +.deps +FRIENDS_TALK_READLINK +.type +HTML +.des +Define here HTML (if any) that you want to be displayed for the links to read comments and post comments on the current event. The contents of this variable are inserted into %%talklinks%% in [var[FRIENDS_EVENT]] if the user has their message boards enabled. +.props +{ readlink +.des +If there are existing comments for this event, then the value of [var[FRIENDS_TALK_READLINK]] is inserted into %%readlink%% +} +{ urlpost +.des +The URL you need to use in your <A HREF=...> tag to link to the "leave a comment" page. +} +{ urlread +.des +The URL to use in your <a href=...> tag to link to the "read comments" page. +} +{ messagecount +.des +The number of replies, or zero. +} +{ itemid +.des +A unique integer that represents this journal entry. You probably won't ever have to use this. +} +{ itemargs +.des +A portion of a URL which identifies this event. This should be used when referring to memadd.bml, editjournal.bml or other similar actions which require an event to be identified in the URL. Do NOT use itemid=%%itemid%% for this purpose, or a similarly hardcoded scheme, use %%itemargs%%. +} +} + +{ FRIENDS_TALK_READLINK +.scope +friends +.override +yes +.type +HTML +.des +If there are comments on the existing journal entry being displayed, then one of these variables is inserted into the %%readlink%% property of [var[FRIENDS_TALK_LINKS]]. +.props +{ urlread +.des +The URL you need to use in your <A HREF=...> tag to link to the page where you read the comments. +} +{ messagecount +.des +The number of comments that people have left in response to this journal entry. +} +{ mc-plural-s +.des +This property is "s" if messagecount is not equal to 1, so you can do things like "1 comment" or "2 comments". Use like: %%messagecount%% comment%%mc-plural-s%% +} +{ mc-plural-es +.des +This property is "es" if messagecount is not equal to 1, so you can do things like "1 kiss" or "2 kisses". Use like: %%messagecount%% comment%%mc-plural-es%% +} +{ mc-plural-ies +.des +This property is "ies" if messagecount is not equal to 1, else it is "y", so you can do things like "1 reply" or "2 replies". Use like: %%messagecount%% comment%%mc-plural-ies%% +} +} + +{ GLOBAL_HEAD +.scope +lastn, calendar, day, friends +.override +only +.type +HTML +.des +Any arbitrary HTML you want placed in the <HEAD> of the page being displayed. +This is a good place to put CSS or META tags. Being global, this +will be placed in any view type. If you want to add tags for one certain view +type, use [var[LASTN_HEAD]], [var[DAY_HEAD]], [var[FRIENDS_HEAD]], or [var[CALENDAR_HEAD]]. +} + +{ LASTN_HEAD +.scope +lastn +.override +only +.type +HTML +.des +Any arbitrary HTML you want placed in the <HEAD> of the [view[lastn]] page. +This is a good place to put CSS or META tags. If you want to add the +same tags to all your pages, use [var[GLOBAL_HEAD]]. +} + +{ DAY_HEAD +.scope +day +.override +only +.type +HTML +.des +Any arbitrary HTML you want placed in the <HEAD> of the [view[day]] page. +This is a good place to put CSS or META tags. If you want to add the +same tags to all your pages, use [var[GLOBAL_HEAD]]. +} + +{ CALENDAR_HEAD +.scope +calendar +.override +only +.type +HTML +.des +Any arbitrary HTML you want placed in the <HEAD> of the [view[calendar]] page. +This is a good place to put CSS or META tags. If you want to add the +same tags to all your pages, use [var[GLOBAL_HEAD]]. +} + +{ FRIENDS_HEAD +.scope +friends +.override +only +.type +HTML +.des +Any arbitrary HTML you want placed in the <HEAD> of the [view[friends]] page. +This is a good place to put CSS or META tags. If you want to add the +same tags to all your pages, use [var[GLOBAL_HEAD]]. +} diff --git a/livejournal/doc/raw/s1/views.dat b/livejournal/doc/raw/s1/views.dat new file mode 100755 index 0000000..e54cf26 --- /dev/null +++ b/livejournal/doc/raw/s1/views.dat @@ -0,0 +1,55 @@ +{ lastn +.name +Most Recent Entries +.des +The default view, a reverse-chronological list of the last 'n' items in your journal, where 'n' is an integer value that the user may specify. Usually 'n' defaults to something like 20. +.url +http://www.livejournal.com/users/exampleusername/ +} + +{ calendar +.name +Calendar view +.des +A page that looks like a calendar, with months shown for any month that you've submitted a journal entry. Each day on the calendar with entries for that day shows a number of how many entries were submitted on that day, and clicking the day brings you to the [view[day]] view. +.url +http://www.livejournal.com/users/exampleusername/calendar +} + +{ day +.name +Day view +.des +After clicking a day on the [view[calendar]] view, the user can see all the journal entries recorded on one specific day. +.url +http://www.livejournal.com/users/bradfitz/day?year=1999&month=11&day=8 +} + +#{ search +#.name +#Search page +#.des +#From the user's search page, people can search their journal for keywords in a certain time frame. +#.url +#http://www.livejournal.com/users/test/search +#} + +#{ searchres +#.name +#Search Results +#.des +#After going to the user's [view[search]] page and submitting something to search for, they see +#the search results view. +#.url +#http://www.livejournal.com/users/test/search?BeOS +#} + +{ friends +.name +Friends View +.des +Shows what all of the user's friends have been doing, all mixed in together in a page +that looks almost identical to the [view[lastn]] view. +.url +http://www.livejournal.com/users/exampleusername/friends +} \ No newline at end of file diff --git a/livejournal/doc/raw/s2/lj/build.pl b/livejournal/doc/raw/s2/lj/build.pl new file mode 100755 index 0000000..55b8efd --- /dev/null +++ b/livejournal/doc/raw/s2/lj/build.pl @@ -0,0 +1,320 @@ +#!/usr/bin/perl +# +use strict; +use Getopt::Long; + +my $XSL_VERSION_RECOMMENDED = "1.55.0"; +my $opt_clean; +my ($opt_myxsl, $opt_getxsl, $opt_single); +exit 1 unless GetOptions('clean' => \$opt_clean, + 'myxsl' => \$opt_myxsl, + 'getxsl' => \$opt_getxsl, + 'single' => \$opt_single, + ); + +my $home = $ENV{'LJHOME'}; +require "$home/cgi-bin/ljlib.pl"; +require "$home/cgi-bin/LJ/S2.pm"; + +$ENV{'SGML_CATALOG_FILES'} = $LJ::CATALOG_FILES || "/usr/share/sgml/docbook/dtd/xml/4.1/docbook.cat"; +unless (-e $ENV{'SGML_CATALOG_FILES'}) { + die "Catalog files don't exist. Either set \$LJ::CATALOG_FILES, install docbook-xml (on Debian), or symlink $ENV{'SGML_CATALOG_FILES'} to XML DocBook 4.1's docbook.cat."; +} +if ($opt_getxsl) { + chdir "$home/doc/raw/build" or die "Where is build dir?"; + unlink "xsl-docbook.tar.gz"; + my $fetched = 0; + my $url = "http://www.livejournal.org/misc/xsl-docbook.tar.gz"; + my @fetcher = ([ 'wget', "wget $url", ], + [ 'lynx', "lynx -source $url > xsl-docbook.tar.gz", ], + [ 'GET', "GET $url > xsl-docbook.tar.gz", ]); + foreach my $fet (@fetcher) { + next if $fetched; + print "Looking for $fet->[0] ...\n"; + next unless `which $fet->[0]`; + print "RUNNING: $fet->[1]\n"; + system($fet->[1]) + and die "Error running $fet->[0]. Interrupted?\n"; + $fetched = 1; + } + unless ($fetched) { + die "Couldn't find a program to download things from the web. I looked for:\n\t". + join(", ", map { $_->[0] } @fetcher) . "\n"; + } + system("tar", "zxvf", "xsl-docbook.tar.gz") + and die "Error extracting xsl-doxbook.tar.gz; have GNU tar?\n"; +} +my $output_dir = "$home/htdocs/doc/s2"; +my $docraw_dir = "$home/doc/raw"; +my $XSL = "$docraw_dir/build/xsl-docbook"; +open (F, "$XSL/VERSION"); +my $XSL_VERSION; +{ + local $/ = undef; my $file = ; + $XSL_VERSION = $1 if $file =~ /VERSION.+\>(.+?)\$docraw_dir/s2/lj/autogen-entities.xml") || die "Can't open autogen-entities.xml\n"; +print AUTOGEN "\n"; +close(AUTOGEN); + +autogen_core(); + +mkdir $output_dir, 0755 unless -d $output_dir; +chdir $output_dir or die "Couldn't chdir to $output_dir\n"; + +my $cssparam; +if (-e "$docraw_dir/build/style.css") { + $cssparam = "--stringparam html.stylesheet style.css"; + system("cp", "$docraw_dir/build/style.css", "$output_dir") + and die "Error copying stylesheet.\n"; +} + +system("xsltproc --nonet --catalogs $cssparam ". + "$docraw_dir/build/chunk.xsl $docraw_dir/s2/lj/index.xml") + and die "Error generating chunked HTML. (no xsltproc?)\n"; + +if ($opt_single) +{ + system("xsltproc --nonet --catalogs --output manual.html $cssparam ". + "$docraw_dir/build/nochunk.xsl $docraw_dir/s2/lj/index.xml") + and die "Error generating single HTML. (no xsltproc?)\n"; +} + +sub autogen_core +{ + my $cv = shift; + unless ($cv) { + autogen_core(1); + return; + } + + my $pub = LJ::S2::get_public_layers(); + my $id = $pub->{"core$cv"}; + $id = $id ? $id->{'s2lid'} : 0; + die unless $id; + + my $dbr = LJ::get_db_reader(); + my $rv = S2::load_layers_from_db($dbr, $id); + my $s2info = S2::get_layer_all($id); + my $class = $s2info->{'class'} || {}; + + open (AC, ">$docraw_dir/s2/lj/autogen-core$cv.xml") or die "Can't open autogen-core$cv.xml\n"; + + my $xlink = sub { + my $r = shift; + $$r =~ s/\[class\[(\w+)\]\]/$1<\/link>/g; + $$r =~ s/\[method\[(.+?)\]\]/$1<\/link>/g; + $$r =~ s/\[function\[(.+?)\]\]/$1<\/link>/g; + $$r =~ s/\[member\[(.+?)\]\]/$1<\/link>/g; + + my @parts = split(/\s*\/\/\s*/, $$r); + if (@parts > 1) { + $$r = shift @parts; + my $see_also; + foreach my $p (@parts) { + if ($p =~ /^SeeAlso:\s*(.+)/) { + my $ids = $1; + my $str = " (See also: " . join(', ', + map { ""; } + split(/\s*\,\s*/, $ids)) . ")"; + $$r .= $str; + } + } + } + }; + + my $xlink_args = sub { + my $r = shift; + return unless + $$r =~ /^(.+?\()(.*)\)$/; + my ($new, @args) = ($1, split(/\s*\,\s*/, $2)); + foreach (@args) { + s/^(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + } + $new .= join(", ", @args) . ")"; + $$r = $new; + $xlink->($r); + }; + + # layerinfo + #if (my $info = $s2info->{'info'}) { + # $body .= ""; + # $body .= ""; + # foreach my $k (sort keys %$info) { + # my ($ek, $ev) = map { LJ::ehtml($_) } ($k, $info->{$k}); + # $title = $ev if $k eq "name"; + # $body .= "\n"; + # } + # $body .= "
    $ek$ev
    "; + #} + + # sets + if (my $prop = $s2info->{'prop'}) { + my $set = $s2info->{'set'}; + print AC "
    \n"; + print AC "Properties"; + print AC "\n"; + + foreach my $pname (sort keys %$prop) { + my $prop = $prop->{$pname}; + my $des = $prop->{'doc'} || $prop->{'des'}; + $xlink->(\$des); + print AC "\$*$pname : $prop->{type}\n"; + print AC "$des"; + + my $v = $set->{$pname}; + if (defined $v) { + if (ref $v eq "HASH") { + if ($v->{'_type'} eq "Color") { + # FIXME: emit something we can turn into a colored box in DocBoox XSLT + $v = $v->{'as_string'}; + } else { + $v = "[unknown object type]"; + } + } elsif (ref $v eq "ARRAY") { + $v = "List: (" . join(", ", @$v) . ")"; + } + + print AC "Base value: $v\n"; + } + + print AC "\n"; + } + + print AC "\n"; + print AC "
    \n"; + } + + # global functions + my $gb = $s2info->{'global'}; + if (ref $gb eq "HASH" && %$gb) { + print AC "
    \n"; + print AC "Functions"; + print AC "\n"; + + foreach my $fname (sort keys %$gb) { + my $rt = $gb->{$fname}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = $gb->{$fname}->{'docstring'}; + $xlink->(\$ds); + + my $args = $gb->{$fname}->{'args'}; + $xlink_args->(\$args); + + my $idsig = $fname; + print AC "$args : $rt$ds\n"; + } + + print AC "\n"; + print AC "
    \n"; + } + + if (%$class) + { + print AC "
    \n"; + print AC " Classes\n"; + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + print AC ""; + print AC "$cname Class"; + my $ds = "$cname Class$class->{$cname}->{'docstring'}"; + if ($class->{$cname}->{'parent'}) { + $ds .= "Parent Class Child class of [class[$class->{$cname}->{'parent'}]]."; + } + + my @children = grep { $class->{$_}->{'parent'} eq $cname } keys %$class; + if (@children) { + $ds .= "Derived Classes Child classes: " . + join(", ", map { "[class[$_]]" } @children) . "."; + } + + if ($ds) { + $xlink->(\$ds); + print AC $ds; + } + + # build functions & methods + my (%func, %var); + my $add = sub { + my ($self, $aname) = @_; + foreach (keys %{$class->{$aname}->{'funcs'}}) { + $func{$_} = $class->{$aname}->{'funcs'}->{$_}; + $func{$_}->{'_declclass'} = $aname; + } + foreach (keys %{$class->{$aname}->{'vars'}}) { + $var{$_} = $class->{$aname}->{'vars'}->{$_}; + $var{$_}->{'_declclass'} = $aname; + } + + my $parent = $class->{$aname}->{'parent'}; + $self->($self, $parent) if $parent; + }; + $add->($add, $cname); + + print AC "Members" if %var; + foreach (sort keys %var) { + my $type = $var{$_}->{'type'}; + $type =~ s/(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + $xlink->(\$type); + + my $ds = LJ::ehtml($var{$_}->{'docstring'}); + $xlink->(\$ds); + + if ($var{$_}->{'readonly'}) { + $ds = "(Read-only) $ds"; + } + + print AC ""; + print AC "$type $_"; + print AC "$ds"; + } + print AC "" if %var; + + print AC "Methods" if %func; + foreach (sort keys %func) { + my $rt = $func{$_}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = LJ::ehtml($func{$_}->{'docstring'}); + $xlink->(\$ds); + + my $args = $_; + $xlink_args->(\$args); + + print AC ""; + print AC "$args : $rt"; + print AC "$ds"; + } + print AC "" if %func; + print AC ""; + } + print AC "
    "; + } + + close AC; + + return; +} +__END__ diff --git a/livejournal/doc/raw/s2/lj/dateformats.xml b/livejournal/doc/raw/s2/lj/dateformats.xml new file mode 100755 index 0000000..d951b4d --- /dev/null +++ b/livejournal/doc/raw/s2/lj/dateformats.xml @@ -0,0 +1,191 @@ +
    + Date Formats + The Date class has a method date_format() and its subclass DateTime adds the method time_format(). There's also a month_format() on objects dealing with only a month. All these methods take an optional format string which can be either a named format or a custom format string. If no format is provided, a default sensible version is used. The default is indicated in the table below. + +
    + Named Date Formats + + The following named date formats are supported and localized for internationalization. The English representation is shown only as an example. + + + + + + + Method + Named Format + Default? + English Format + English Result + + + + + date_format + short + X + %%m%%/%%d%%/%%yy%% + 2/5/80 + + + date_format + med + + %%mon%%. %%dayord%%, %%yyyy%% + Feb. 5th, 1980 + + + date_format + med_day + + %%da%%, %%mon%%. %%dayord%%, %%yyyy%% + Tue, Feb. 5th, 1980 + + + date_format + long + + %%month%% %%dayord%%, %%yyyy%% + February 5th, 1980 + + + date_format + long_day + + %%day%%, %%month%% %%dayord%%, %%yyyy%% + Tuesday, February 5th, 1980 + + + time_format + short + X + %%hh%%:%%min%% %%a%%m + 12:34 am + + + month_format + short + + %%m%%/%%yy%% + 04/03 + + + month_format + med + + %%mon%% %%yyyy%% + Apr 2003 + + + month_format + long + X + %%month%% %%yyyy%% + April 2003 + + + + + + +
    + +
    + Custom Date Formats + + If you're making a style for yourself and don't care about keeping the date formats generic for internationalization, you can construct your own date format string with interpolated variables which you surround in double percent signs. + + + + + + + Variable + Description + + + + + m + Month, 1-12. + + + mm + Month, 01-12. + + + d + Day, 1-31. + + + dd + Day, 01-31. + + + yy + Year, two digits. + + + yyyy + Year, four digits. + + + mon + Short month name, translated. (English: Jan, Feb, …) + + + month + Long month name, translated. (English: January, February, …) + + + da + Short day of week, translated. (English: Sun, Mon, …) + + + day + Long day of week, translated. (English: Sunday, Monday, …) + + + dayord + Ordinal day of month, translated. (English: 1st, 2nd, 3rd, …) + + + H + Hour, 0-23. + + + HH + Hour, 00-23. + + + h + Hour, 1-12. + + + hh + Hour, 01-12. + + + min + Minute, 00-59. + + + sec + Second, 00-59. + + + a + "a" for am, "p" for pm. + + + A + "A" for am, "P" for pm. + + + + + + +
    + +
    diff --git a/livejournal/doc/raw/s2/lj/entities.xml b/livejournal/doc/raw/s2/lj/entities.xml new file mode 100755 index 0000000..c5cad8b --- /dev/null +++ b/livejournal/doc/raw/s2/lj/entities.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%autogen; \ No newline at end of file diff --git a/livejournal/doc/raw/s2/lj/faq.xml b/livejournal/doc/raw/s2/lj/faq.xml new file mode 100755 index 0000000..fc73cca --- /dev/null +++ b/livejournal/doc/raw/s2/lj/faq.xml @@ -0,0 +1,17 @@ + + Will there be an S1 to S2 converter? + + Short answer: No. + Long answer: Maybe, but we're not going to help make it. The problem is that there's no proper way to convert an S1 style to S2. A converter could be made, with much pain, but it'd generate totally ugly S2 code which ignores all the benefits of S2. The resultant code would be so horrid that the potential migrator from S1 would see it, cry, and never come back to S2, the auto-converted code having left such a rotten taste in his or her mouth. + Actually, what we hope will happen is that somebody (or many people) will get inspired and start making new style languages on top of S2, many of which would likely be targetted at the HTML-hacker audience who want a style system more like S1. + + + + Why is S2 so large/complex/difficult? + + It's not, really. You're probably just overwhelmed and frustrated, hoping it was like S1 with more support for certain pages. Unfortunately, S1 was a dead-end and couldn't be usefully extended. + S2 has more than you'll ever use, but that's not to say the rest of it is a waste. Just because you only speak English, does that mean we shouldn't address the problem of internationalization? + S2's been designed to be as easy as possible on both regular users and programmers. Once you start creating/modifying S2 code, you should find it's not so bad. And once you have a wild idea of something you want to do with your style, it'll actually be possible... just consult the S2 core layer reference and figure out how to get what you're looking for. + Also, see the last paragraph to the previous question. + + \ No newline at end of file diff --git a/livejournal/doc/raw/s2/lj/index.xml b/livejournal/doc/raw/s2/lj/index.xml new file mode 100755 index 0000000..8246762 --- /dev/null +++ b/livejournal/doc/raw/s2/lj/index.xml @@ -0,0 +1,32 @@ + + +%content; +]> + + &s2.bookinfo; + + &s2.preface; + + &s2.quickstart; + + &s2.overview; + + + &s2.langref; + + + &s2.notes; + + + &s2.csp; + + &s2.s2onlj; + + &s2.siteapi; + + + &s2.faq; + + &appx.gfdl; + \ No newline at end of file diff --git a/livejournal/doc/raw/s2/lj/quickstart.xml b/livejournal/doc/raw/s2/lj/quickstart.xml new file mode 100755 index 0000000..5c7ba8f --- /dev/null +++ b/livejournal/doc/raw/s2/lj/quickstart.xml @@ -0,0 +1,277 @@ + + Quick Start Guide + Quick Start Guide to using S2 on LiveJournal + + + + Widely considered a myth by many users of LiveJournal.com, S2 is the + long-awaited new style system for LiveJournal. In four years of use, + the original LiveJournal style system has allowed LiveJournal users + to create truly unique layouts for their journals, but shown many + limitations due to things not considered during its initial design. + Some functionality has been cobbled on as an afterthought, and this + has left the style system clunky and restrictive, with some ugly + kludges which noone really likes. + + + S2 was conceived to remove all limitations and make LiveJournal + truly customizable in almost any conceivable way. Redesigned from + the ground up, S2 is completely different from the old style system, + but introduces new functionality and makes it easier to create a + complimentary set of journal views. It also adds new views, including + customized comment views and, in the future, photo gallery, memory, + and user information views. + + + +
    + Getting to know S2 +
    + Common Terms + + General Terms + + Journal View + + + A journal view is the name for the different parts of a + LiveJournal account which a user can create or customize a layout for. + Someone's journal itself is called the Recent view, + meaning that it shows all of that user's recent entries. The most + popular view is the Friends view, with which a user + can read all of their friends' updates. + + + + + Layers + + + S2 uses the concept of layers to provide different levels + of customization - each layer in a style deals with a different aspect of the + style, ranging from color to translation to HTML options and settings. A + complete style is the result of putting its different layers together for use. + + + + + + Style Layers + + Core + + + The core layer is the foundation of all styles. The core layer + defines all of the functions and classes available to the lower + layers. The core layer itself is fully functional as well; + someone could use just the core definitions for each journal view + to create a working (yet rather bland) style. The core layer is mostly + just a base to work from, a guide to help form a complete style that + helps by patching holes where necessary. + + + + + Core - Internationalization + + + The core internationalization layer provides all of the text information + to help display someone's journal in a different language. This layer, + like the core layer, is only really a base or a guide to create new + internationalization layers from. + + + + + Layout + + + A layout layer is where the real customization starts. To draw a loose + comparison to the old style system, a layout layer can be regarded as an + S1 style except that the S2 layout covers each journal view, unlike the + s1 style that only dealt with a single view. A layout layer, much like the core + layer, defines its own set of properties that change the appearance and + behavior of the layout. + + + + + Internationalization + + + An internationalization layer provides all of the text information + that pertains to a specific layout layer, so that users can select + which language their journal should display in. A complete style uses + text from both an internationalization layer and the core internationalization + layer. + + + + + Theme + + + A theme layer uses the color properties available in a layout layer to create + a unique look for the style. To draw another loose comparison to the old style + system, a theme layer is much like a color theme, except that a theme is only + unique to one layout, unlike its S1 counterpart, which only worked for all styles. + + + + + User + + + A user layer is the final layer where most people's options will be set. Few people + will create a user layer by hand, because a user layer is mostly handled by the customization + wizards. To draw a final comparison to the old style system, you can think of a user + layer as the equivalent to the Overrides box for S1, except there is + a lot less headache involved in creating a user layer. + + + + +
    + +
    + +
    + + + MelissaDella + JesseProulx + + + Configuring your account to use S2 + + To start using S2, you'll need to turn S2 on for your account. Go to + , make sure the appropriate account + is selected (if you control more than one account from the one you're + logged into), and choose New System (S2) from the + drop-down menu. Now save your changes (click Change). + + + You can always switch back to S1; all of your S1 styles and overrides + are kept intact. + + + + + In this section, we'll go through the use of wizards. They are relatively + self-explanitory by design, so this will only breifly take you through + the steps. + + Selecting a Style + + + The first step is to choose a layout. You'll notice most of the S1 system + styles have been ported to S2. For example purposes we'll use the default + style, Generator. This should already be selected, if you haven't done + any tweaking prior to reading this guide. Next to the Change + button there is a link for layout previews. If you wish to see examples of + other styles you may use, open this page in a new window and peruse. + + + + + Again, for example purposes, and because we're assuming that english is your primary language, + select English in the language section. + + + + + Next you can choose a theme for your layout. Themes are basically just + default sets of colors that we've chosen to help you start customizing your journal. + You can preview each theme by selecting the (previews) link, + located next to the Change button. If no color themes are to your liking, + you can override any color by creating a new user layer, which we'll explain how to + do next. + + + + + Now that you've chosen a style, a language, and a color theme, you can + begin creating a custom user layer by clicking the Customize… + button at the bottom of the page. + + + + Creating a user layer + + + On the Customize page, the first set of options is devoted to tweaking all of the + available colors from the style you've chosen. For brevity purposes we'll only + change two colors (feel free to change more as you see fit). + + + Assuming you've chosen the Generator style, scroll down to the Page background color + (and around userpics) option and select the + Override button; from here you can press Choose + for a pop-up color selector, or you can simply enter the hexadecimal color code if you know it. + For demonstration purposes you can simply type #cef5c1 in the given box. + Scroll down to the Background color for the bar below entries option, + select Override, and enter the following hex code: + #f1fded. If you have JavaScript enabled in your browser, you'll see the + color previews dynamically change when you click outside of the option box. + + + + + Now that a couple of colors have changed, scroll down to the Box width (pixels) + option. Select Override and enter the value 400. + + + + + Move to the next section labelled Link text to leave a comment, select + Override, and enter Post a new comment. For the next + option, Link text to read comment, select Override + and enter A single, lonely comment // Its a party in here with # people!. + Enter these same values for the friends view entry comment links. + + + + + Click on the Save button when you've completed the steps above. Now, + view your journal. Notice th colors, the width, and the comment links. + + + +
    + +
    + Where to go from here + + + + + We've made a manual available that covers every topic related to using S2 on LiveJournal. As a + matter of fact you're currently reading a chapter from the manual. To start from the beginning, + navigate to . + + + + LJ Style Discussion + + LJ Style Discussion is a community + on LiveJournal.com that covers most S1 and S2 discussions. + This community has been sanctioned by administrators of LiveJournal as an official community. + + + + S2 Practice Discussion + + S2 Practice Discussion is a community + on LiveJournal.com that deals with introducing S2 to + members of LiveJournal's support team. The introductory text available in the community was actually used + to write portions of this chapter. + + + +
    + +
    diff --git a/livejournal/doc/raw/s2/lj/s2onlj.xml b/livejournal/doc/raw/s2/lj/s2onlj.xml new file mode 100755 index 0000000..f97484d --- /dev/null +++ b/livejournal/doc/raw/s2/lj/s2onlj.xml @@ -0,0 +1,204 @@ + + Using S2 on LiveJournal +
    + Resources + + + Customization area + Regular end-user destination to select layouts and corresponding themes with + pretty graphical previews, and graphical wizard to override text/colors. + + + Advanced area + Create styles & layers. View the S2 source and documentation page of any + public layer, notably the core layer and all the classes, functions and properties it provides. + + + +
    +
    + Layer Guidelines + This section is a list of suggestions for making good layers for LiveJournal, and also forms + the requirements for creating layers to be offered as standard by LiveJournal. You should read + this if you're designing a LiveJournal layout, or if you're writing the code to implement + a layout designed by someone else, or if you're just interested. + It seems that most people start creation of a layout by creating a static HTML mockup of + roughly what the layout will include. With this in mind, the guide is separated into two parts, + the first for those creating a design, and the second for those who are implementing a design + in S2 code. You might, of course, be both! + +
    + Guidelines For Layout Designers + When starting to design a layout, you should keep in mind the following points. + + + + Beware Copyright + Practically everything creative is copyrighted, from images to site designs + to program code. If you copy or clone someone else's design or HTML, or use an + image created by someone else, you may find yourself in a copyright lawsuit. + Also, any style which is to be part of the LiveJournal system must be distributable + under the GNU General Public Licence (GPL) under which the LiveJournal source + distribution is licenced. The easiest way to keep to this is to only use your + own work in creating a layer. + + + + + Design Flexibly + S2 is designed to be extensible, and if you think about extensibility + early on your will make it much easier to adapt to suit additions to LiveJournal + later on. + + Some particular things to bear in mind are: + + Try to allow for new view types to be added in future. + If you've got a list of views (Recent Entries, Friends etc) then + will it be easy to add more views to it later on without breaking + the design? + Try to keep the global HTML distinct + from the view-specific HTML. That is, decide what is part of the + recent view and what will be present on all views. Try to avoid + the view-specific HTML depending on the global HTML if you can. + + + + + + Design for standard page elements + There are certain things which users expect to find in LiveJournal + styles. These include: + + Links from the archive calendar view to see the + month view for each month shown. + A way to easily obtain permalink for each entry + which can be used to link to the entry. The S2 system will provide + the URL for this, but you need to decide where to put it. + Links on the Recent Entries and Friends views to + navigate to older entries and back to newer entries. + Links on a day page to view the previous and next day. + Links on the Archive calendar to view other years. + Titles and subtitles. The system allows the user + to give their journal a title and a subtitle, as well as a special + title for their friends view. You should display at least the main + titles as headings, and try to include the subtitle at least on + the Recent Entries view. + + + + + + + Design for Customization + As you are creating your design, try to think of things that users + might want to customize. Colors are the easiest to think of, but + you could also provide options for margin sizes, the position of + navigation bars and chosing classes of fonts. + + A gotcha with customization is that it can make it hard to incorporate + images into a style, since colors and alignments can change. If you are + writing a potential system layout, the system can provide dynamic image + color changes for your style in certain cases, but try to avoid this if + you can. + + + + Design for Internationalization + If you are designing a layout you should try to allow for + the text in your layout to be translated. A lot of commonly-used text + is already provided by the system translated, and it will be a lot + easier to make your style multi-lingual if you make use of the + standard text. + + One example is comment links on entries. The system provides functions + to create the comment links with text set in an internationalization layer, + including the correct pluralization for the comment count. If you design + such that any text could be used in your comment links (and anywhere else where + text appears, for that matter) your layout will be easily translatable. + Another thing to avoid is including text in images, as this is practically + impossible to translate flexibly. + + +
    + +
    + Guidelines For Implementors + If you are a programmer writing the S2 code for an S2 layout (or, to a lesser extent, + some other layer) then this section is for you. + + + + + Use Properties + If you expose properties from your layout, the end-user will be able + to customize these properties from a web-based GUI interface. In general, + the more of these you have the better, but don't go overboard. + + + Colors are the main customizable feature of most layouts. + Try to allow the user to change the color of all major page elements, but + also dynamically generate similar colors based on user-supplied properties using + the methods of the Color class to lighten, darken, + invert or average. + + Font selection is supported by the core layer, but you'll + have to explicitly state that you wish to expose these properties in your + layout. (See documentation on properties) + The core layer provides options to select a primary font family + as well as a fallback CSS generic font family, and one or both of + these can be ommitted. You should generate a sensible CSS font-family + property rule or equivalent FONT FACE value from these two properties. + + + + + + + Let the System Help You + The core layer has lots of useful default implementations of various + page features. For example, it can generate + links to users and form page titles and subtitles from the relevant + user settings and translation properties. Using these defaults can save + you a lot of work. + + + The system also has several features to help layouts be expandable + without modifying a layout at all: + + You can generate a list of views by iterating over + the views_order member of Page, + and if new top-level views are added in future, or if the URL to + one changes, your layout will automatically reflect the change. + The body of each view is separated from the + navigation and layout around it, so that if you make sure you + separate the view-specific code from the global code, new views + can be added in future and the default HTML generated by the core + layer will be used until the layout is revised to provide customized + output. + + + + + + + Text Abstraction + All text in a layout should be easily overridable either by properties + or by functions. Functions are required when text includes a number which + affects the grammar of a sentence, such You are viewing the 10 most recent + entries. + + + Don't break up sentences when allowing sentences to be changed, as sentence + construction differs wildly between languages. + Finally, check to see if the text you need is already provided by a function in + the core layer, as this will not only save you effort, but also save the effort of + anyone who tries to create internationalization layers for your layout. The core + layer provides functions and properties which are useful in practically all layouts, + including text for comment links and view names. + + + +
    + +
    +
    diff --git a/livejournal/doc/raw/s2/lj/siteapi.xml b/livejournal/doc/raw/s2/lj/siteapi.xml new file mode 100755 index 0000000..8a74021 --- /dev/null +++ b/livejournal/doc/raw/s2/lj/siteapi.xml @@ -0,0 +1,9 @@ +LiveJournal's S2 API +S2 is a generic system which sites like LiveJournal can use. This appendix documents the LiveJournal-specific core layers, which provide the basic functionality that's available to all other layers. At present there's only one core layer (version 1), but in the future there may be more. + +
    + Core Layer 1 + LiveJournal's only core layer, at present. + &s2.siteapi.core1.autogen; + &s2.siteapi.core1.dateformats; +
    diff --git a/livejournal/doc/todo.txt b/livejournal/doc/todo.txt new file mode 100755 index 0000000..8526038 --- /dev/null +++ b/livejournal/doc/todo.txt @@ -0,0 +1,140 @@ + (Don't try to make much sense of this list. It's mainly for the + core developers to keep track of things.) + +DOCUMENTATION: (JPROULX) + +-- how to modify site-local text (like: en_LJ from en) (done?) + +-- document all the db roles, and how to set 'em up in %LJ::DBINFO. (done?) + +ANYBODY: + +-- Windows syncitem client. Use Perl+Win::Forms+ActiveState compiler + ... make local GDBM/etc file. Export to HTML/XML/etc from that + file. + +-- user journal stats (have most of plan) + +-- ESN system (Event/Subscription/Notification) (have plan/API) + +* need a 'replyanywhere' priv that lets site admins reply in journals + that are friends only, when the site admins aren't part of the + community. + +* fix LJ::get_itemid_{before|after} to respect security of $remote + NOTE: not easy to do fast. maybe best not to do it. not a big deal. + ++----------+ +| bradfitz | ++----------+ + +* version checking in login protocol mode: + -- each client string: versionid|version|security|noteline + -- new protocol login req opt: "checklevel" = { all | none | securityonly } + -- priv for client authors to update db + +misc: +developers/doc link wrong +topics / named entries (url space control) +logaccess bypass +talkleft_xfp investigation + +* clustering: + -- console + -- after user's moved, update their memories: + (0,global)->(userid,ditemid) + that way, filtering on "my own" will work. + +* rate limiting + +MISC: + +* new authentication/login system... + -- SSL logins & login tokens + -- for non-SSL clients: challenge/response (with challenge + being request body, plus GMT yyyymmddhh) +* ljcom: automate username changes (payments and renaming) +* BML::500_on_die option: make BML send a 500 server error on any + _CODE block failure +* BML: let VarInitScript define a hook to run on server error to + get error message, look at it, and decide new error message. +* Syndicating channels: + http://www.livejournal.com/talkread.bml?itemid=14311193 +* /fz/ joins on logtext (requires master) +* talk* joins on logtext (requires master) +* cvsreport: + * -c doesn't need to scan maind.. perf. + * -s with args doesn't need to scan everything, just args. +* support: dakus wants to be able to mark requests as "still needs help" +* LJ::delete_user() +* require POST for all do actions (use LJ::did_post to check) +* perf: don't preload friends in ljprotocol.pl:editfriends, check $sth->rows +* comprehensive fix for adding communities as friends: befriending vs. + watching: provide a way for users to turn bit 0 off in allowmask, + essentially. + ++-------------+ +| Cleanliness | ++-------------+ + +* should never need to login as community! + -- e.g. uploadpic/editinfo/etc needs to let community admins + select their community to modify while logged in as + themselves + -- start using auth_info_2 everywhere like editpics/uploadpic +* use LJ::send_mail everywhere, not sendmail pipe by hand +* XHTML compliant everywhere +* remove *_do.bml pages, merge into one page instead. + ++--------+ +| Future | ++--------+ + +* HTML email we send out with images should be the images in the MIME body + and then HTML part reference those, not the ones on the site +* attach files to posts (good for groupware) + -- new cap limits: canattachfile, filemaxsize (0 for no limit) +* support system tweaks: + - ugly green to blue + - allow touching by helpers + - allow 5 minute locks + - allow full email address to be shown to helpers +* use
    "; + $ret .= "

    Raw data for $host

    "; + $ret .= "
    $log
    "; + } + + } + + LJ::MemCache::set([$u->{'userid'},"mcrate:$u->{'userid'}"], \%now_hits) + if $u; + + if ($mode eq "overview") { + $ret .= "\n"; + + my $new_whatev = $tot_hits + $tot_misses; + my $new_rate = $tot_hits / ($new_whatev || 1); + $ret .= sprintf("Global [%0.02f%% {$new_whatev}]", $new_rate * 100); + } + + return $ret; +} +_code?> + diff --git a/livejournal/htdocs/admin/memcache_view.bml b/livejournal/htdocs/admin/memcache_view.bml new file mode 100755 index 0000000..4749ca6 --- /dev/null +++ b/livejournal/htdocs/admin/memcache_view.bml @@ -0,0 +1,275 @@ + +Memcache view + +Error: You don't have access to viewing memcache info." + unless (LJ::check_priv($remote, "siteadmin", "memcacheview")); + + return "Error: No memcache servers defined." + unless @LJ::MEMCACHE_SERVERS; + + my $uid = sub { + my $u = LJ::load_user(shift); + return $u ? $u->{'userid'} : ""; + }; + my $cuid = sub { + my $u = LJ::load_user(shift); + return $u ? "$u->{'clusterid'}:$u->{'userid'}" : ""; + }; + + # key: unique prefix of a memcache key + # value: number n, means the n-th component of the key when + # split by ':' is the hash key. 0 means no hash key. + # the default, when absent from this hash, is "n=2 if the 2nd component + # is a number". + + my %MEMC_HASHKEYS = ( + 'uidof:' => 0, + 'talksubject:' => 3, + 'talkbody:' => 3, + 'logtext:' => 3, + 's1pubstyc:' => 0, + 'popsyn:' => 0, + 'rate_eperr:' => 0, + 'rate:' => 0, + 'ml.' => 0, + ); + + my $get_hashkey = sub { + my $key = shift; + return undef unless $key; + + my $hk; + my $component; + + foreach (keys %MEMC_HASHKEYS) { + if ($key =~ /^$_/) { + $component = $MEMC_HASHKEYS{$_}; + } + } + return undef if defined ($component) and $component == 0; + my $sep = ':'; + $sep = '.' if $key =~ /userpic\./; #special case + my @els = split (/\Q$sep\E/, $key); + $hk = $els[defined($component) ? $component-1 : 2-1]; + $hk = undef + unless defined($component) || int($hk)==$hk; + return $hk; + }; + + my $display = sub { + my ($key, $val) = @_; + + # first, transform array->hash if necessary + $val = LJ::MemCache::array_to_hash("user", $val) + if $key =~ /^user:/ + or $key =~ /^userid:/; + + # blot out passwords + if (ref $val eq 'HASH' && defined($val->{'password'})) { + $val->{'password'} = '*' x 8; + } + + # unpack packed data + if ($key =~ /^talk2:/) { + my $newval; + my $n = (length($val) - 1) / 16; + for (my $i=0; $i<$n; $i++) { + my ($f1, $par, $poster, $time) = unpack("NNNN",substr($val,$i*16+1,16)); + my $state = chr($f1 & 255); + my $talkid = $f1 >> 8; + $newval->{$talkid} = { + talkid => $talkid, + state => $state, + posterid => $poster, + datepost => LJ::mysql_time($time), + parenttalkid => $par, + }; + } + $val = [substr($val,0,1), $newval]; + } + + if ($key =~ /^log2:/) { + my $item = {}; + @$item{'posterid', 'eventtime', 'logtime', 'allowmask', 'ditemid'} = unpack("NNNNN", $val); + $item->{'security'} = ($item->{'allowmask'} == 0 ? 'private' : + ($item->{'allowmask'} == 2**31 ? 'public' : 'usemask')); + @$item{'jitemid', 'anum'} = ($item->{'ditemid'} >> 8, $item->{'ditemid'} % 256); + $item->{'eventtime'} = LJ::mysql_time($item->{'eventtime'}, 1); + $item->{'logtime'} = LJ::mysql_time($item->{'logtime'}, 1); + $val = $item; + } + + if ($key =~ /^log2lt:/) { + my $items = []; + my $ver = substr($val, 0, 1); + my $offset = {1=>1, 2=>5, 3=>5}->{$ver}; + my $newval; + + push @$newval, $ver; + push @$newval, unpack("N", substr($val, 1, 4)) + if $ver>=2; + + my $n = (length($val) - $offset )/20; + for (my $i=0; $i<$n; $i++) { + my ($posterid, $eventtime, $rlogtime, $allowmask, $ditemid) = + unpack("NNNNN", substr($val, $i*20+$offset, 20)); + $eventtime = LJ::mysql_time($eventtime, 1); + my $security = $allowmask == 0 ? 'private' : + ($allowmask == 2**31 ? 'public' : 'usemask'); + my ($jitemid, $anum) = ($ditemid >> 8, $ditemid % 256); + my $item = {}; + @$item{'posterid','eventtime','rlogtime','allowmask','ditemid', + 'security', 'jitemid', 'anum'} = + ($posterid, $eventtime, $rlogtime, $allowmask, + $ditemid, $security, $jitemid, $anum); + push @$items, $item; + } + push @$newval, $items; + $val = $newval; + } + + if ($key =~ /^fgrp:/) { + my $newval = []; + my $ver = shift @$val; + push @$newval, $ver; + foreach(@$val) { + push @$newval, LJ::MemCache::array_to_hash("fgrp", [$ver, @$_]); + } + $val = $newval; + } + + if ($key =~ /^upicinf:(\d+)$/) { + my $userid = $1; + my ($ver, $picstr, $kwstr) = @$val; + my $info = { + 'version' => $ver, + 'pic' => {}, + 'kw' => {}, + }; + + while (length $picstr >= 7) { + my $pic = { userid => $userid }; + ($pic->{picid}, + $pic->{width}, $pic->{height}, + $pic->{state}) = unpack "NCCA", substr($picstr, 0, 7, ''); + $info->{pic}{$pic->{picid}} = $pic; + } + + my ($pos, $nulpos); + $pos = $nulpos = 0; + while (($nulpos = index($kwstr, "\0", $pos)) > 0) { + my $kw = substr($kwstr, $pos, $nulpos-$pos); + my $id = unpack("N", substr($kwstr, $nulpos+1, 4)); + $pos = $nulpos + 5; # skip NUL + 4 bytes. + $info->{kw}{$kw} = $info->{pic}{$id} if $info; + } + $val = $info; + } + + if ($key =~ /^friends:/) { + my $ver = substr($val, 0, 1, ''); + my $packfmt = "NH6H6NC"; + my $packlen = 15; + my @cols = qw(friendid fgcolor bgcolor groupmask showbydefault); + my %friends; + + while (length($val) >= $packlen) { + my @row = unpack($packfmt, substr($val, 0, $packlen, '')); + + # add "#" to beginning of colors + $row[$_] = "\#$row[$_]" foreach 1..2; + + # turn unpacked row into hashref + my $fid = $row[0]; + my $idx = 1; + foreach my $col (@cols[1..$#cols]) { + $friends{$fid}->{$col} = $row[$idx]; + $idx++; + } + } + $val = [$ver, \%friends]; + } + + if ($key =~ /^tu:/) { + $val = unpack("N", $val); + } + # just in case this remains a packed scalar + if (not ref $val) { + $val =~ s/([\x00-\x1f])/sprintf("\\x%02x", $1)/eg; + } + $ret .= "Data: "; + + my $dumper = Data::Dumper->new([$val],["Value"]); + $dumper->Terse(1); + $dumper->Indent(2); + my $d = $dumper->Dump(); + + $ret.= "
    " . LJ::ehtml($d) . "
    "; + + return; + }; + + + if ($POST{'query'}) { + foreach my $key (split(/\r\n/, $POST{'query'})) { + + next unless $key =~ /\S/; + # shortcuts + $key =~ s/(##)(\w+)/$cuid->($2)/eg; + $key =~ s/(#)(\w+)/$uid->($2)/eg; + $key =~ s!\((\d+)\)!int($1/256)!eg; + + my $sock = LJ::MemCache::_get_sock($key); + $ret .= "

    Key: $key
    "; + + unless ($sock) { + $ret .= "Error: Could not connect to server

    "; + next; + } + + if ($POST{'sock'}) { + $ret .= "Socket: $sock
    "; + } + + my $hashkey = $get_hashkey->($key); + if ($hashkey) { + $ret .= "Hashkey: $hashkey
    "; + } + my $pars = defined($hashkey) ? [$hashkey, $key] : $key; + my $val = LJ::MemCache::get($pars); + unless (defined $val) { + $ret .= "Data: not found

    "; + next; + } + $display->($key, $val); + $ret .= "

    "; + } + return $ret; + } + + $ret .= "

    Enter your memcache query(-ies) below.

    "; + $ret .= '

    Here\'s the reference of key names.

    '; + $ret .= "

    Shortcuts:

    #username -> userid
    ##username -> cid:userid
    (number) -> number/256

    "; + + $ret .= '
    '; + $ret .= " "; + $ret .= "

    " . LJ::html_check({ 'type' => 'check', 'name' => 'sock', 'id' => 'sock' }); + $ret .= "

    "; + + $ret .= ""; + return $ret; + + +_code?> + + diff --git a/livejournal/htdocs/admin/mysql_status.bml b/livejournal/htdocs/admin/mysql_status.bml new file mode 100755 index 0000000..83ecc0c --- /dev/null +++ b/livejournal/htdocs/admin/mysql_status.bml @@ -0,0 +1,129 @@ +Error: You don't have access to administer databases." + unless (LJ::check_priv($remote, "siteadmin", "mysqlstatus")); + + my $dbh = LJ::get_db_writer(); + + if ($format eq "text") { + BML::set_content_type("text/plain"); + } + + my ($sth, $ret); + + if ($format eq "html") { + $ret .= "\n"; + } + + my @modes = qw(status variables tables); + my $mode = $FORM{'mode'} || "status"; + foreach my $m (@modes) { + if ($mode eq $m) { + $mode = $m; + $ret .= "[ $mode ] " if ($format eq "html"); + } else { + if ($format eq "html") { + $ret .= "[ $m}); + $ret .= "\">$m ] "; + } + } + } + if ($format eq "html") { + $ret .= "

    Or, view as text.

    "; + } + + if ($mode eq "status") + { + $sth = $dbh->prepare("SHOW STATUS"); + $sth->execute; + my %s; + while (my ($k, $v) = $sth->fetchrow_array) { + $s{$k} = $v; + } + + $sth = $dbh->prepare("SHOW STATUS"); + $sth->execute; + if ($format eq "html") { + $ret .= ""; + } + while (my ($k, $v) = $sth->fetchrow_array) { + my $delta = $v - $s{$k}; + if ($delta == 0) { + $delta = ""; + } elsif ($delta > 0) { + $delta = "+$delta"; + } else { + $delta = "-$delta"; + } + if ($format eq "html") { + $ret .= "\n"; + } elsif ($format eq "text") { + $ret .= "$k,$v,$delta\n"; + } + } + $ret .= "
    $k$v$delta
    \n" if ($format eq "html"); + return $ret; + } + + if ($mode eq "variables") + { + $sth = $dbh->prepare("SHOW VARIABLES"); + $sth->execute; + + $ret .= "" if ($format eq "html"); + while (my ($k, $v) = $sth->fetchrow_array) { + if ($format eq "html") { + $ret .= "\n"; + } else { + $ret .= "$k,$v\n"; + } + } + $ret .= "
    $k$v
    \n" if ($format eq "html"); + return $ret; + } + + if ($mode eq "tables") + { + $sth = $dbh->prepare("SHOW TABLE STATUS"); + $sth->execute; + + if ($format eq "html") { + $ret .= ""; + $ret .= ""; + } + my @cols = @{$sth->{'NAME'}}; + foreach (@cols) { + if ($format eq "html") { + $ret .= ""; + } else { + $ret .= "$_,"; + } + } + if ($format eq "html") { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + while (my $t = $sth->fetchrow_hashref) { + $ret .= "" if ($format eq "html"); + foreach my $c (@cols) { + if ($format eq "html") { + $ret .= ""; + } elsif ($format eq "text") { + $ret .= "$t->{$c},"; + } + } + if ($format eq "html") { + $ret .= ""; + } elsif ($format eq "text") { + $ret .= "\n"; + } + } + $ret .= "
    $_
    $t->{$c}
    \n" if ($format eq "html"); + return $ret; + } + +_code?> diff --git a/livejournal/htdocs/admin/priv/index.bml b/livejournal/htdocs/admin/priv/index.bml new file mode 100755 index 0000000..dc7759f --- /dev/null +++ b/livejournal/htdocs/admin/priv/index.bml @@ -0,0 +1,338 @@ + + + +Privilege Management + +prepare("SELECT prlid, privcode, privname, des, is_public, scope FROM priv_list ORDER BY privcode"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + push @privs, $_; + $priv{$_->{'prlid'}} = $_; + $pcode2id{$_->{'privcode'}} = $_->{'prlid'}; + } + + if (LJ::did_post()) { + return "

    ERROR: Invalid form submission" unless LJ::check_form_auth(); + } + + unless ($mode) + { + if ($FORM{'user'}) { $mode = "viewuser"; } + elsif ($FORM{'priv'}) { $mode = "viewpriv"; } + } + + if ($FORM{'devmode'}) { + return "not in dev mode" unless $LJ::IS_DEV_SERVER; + my $userid = $remote->{userid}; + if ($dbh->do("INSERT INTO priv_map (userid, prlid, arg) SELECT ?, prlid, ? FROM priv_list WHERE privcode=?", + undef, $userid, $FORM{arg}, $FORM{priv})) { + LJ::statushistory_add($dbh, $userid, $userid, "privadd", "DEVMODE Granting: \"$FORM{priv}\" with arg \"$FORM{arg}\""); + return "done."; + } else { + return "fail."; + } + } + + unless ($mode) + { + $ret .= "

    Privilege Management

    \n"; + $ret .= ""; + $ret .= "

    View all privileges of user

    "; + + $ret .= "

    Or, show all users with privilege:

    "; + foreach my $priv (@privs) { + my ($des, $args) = split(/arg=/, $priv->{'des'}); + $ret .= "
    $priv->{'privcode'}: $priv->{'privname'}"; + $ret .= " (Site Specific)" if $priv->{'scope'} eq 'local'; + $ret .= "
    "; + $ret .= "
    $des\n"; + $ret .= "
    Argument: $args" if $args; + $ret .= "
    "; + } + $ret .= "
    "; + return $ret; + } + + + # Returns true if the remote user can grant the given priv + sub remote_can_grant + { + my ($remote, $priv, $arg) = @_; + return 0 unless defined $priv; + return LJ::check_priv($remote, 'admin', $priv) || LJ::check_priv($remote, 'admin', '*') || LJ::check_priv($remote, 'admin', "$priv/$arg"); + } + + if ($mode eq "userchange" || $mode eq "privchange") + { + unless (LJ::did_post()) { + return "

    Error: requires post

    "; + } + + unless ($FORM{'submit:refresh'}) { + foreach my $key (keys %FORM) { + if ($key =~ /^revoke:(\d+):(\d+)$/) { + my $prmid = $1; + my $del_userid1 = $2; + my $sth = $dbh->prepare("SELECT userid, prlid, arg FROM priv_map WHERE prmid=$prmid"); + $sth->execute; + my ($del_userid2, $prlid, $arg) = $sth->fetchrow_array; + + unless (remote_can_grant($remote, $priv{$prlid}->{'privcode'}, $arg)) { + $ret .= "ERROR: Invalid access to remove priv $priv{$prlid}->{'privcode'}.
    "; + } else { + if ($del_userid1 && $del_userid1 == $del_userid2) + { + $dbh->do("DELETE FROM priv_map WHERE prmid=$prmid"); + my $privcode = $priv{$prlid}->{'privcode'}; + LJ::statushistory_add($dbh, $del_userid1, $remote->{'userid'}, "privdel", + "Denying: \"$privcode\" with arg \"$arg\""); + $ret .= "Privilege removed.
    \n"; + } + } + } + } + if ($FORM{'grantpriv'}) { + my $u = LJ::load_user($FORM{'user'}); + return "ERROR: Invalid user." unless $u; + my $userid = $u->{'userid'}; + my $qpriv = $FORM{'grantpriv'}+0; + my $privcode = $priv{$qpriv}->{'privcode'}; + my $arg = $FORM{'arg'}; + + if ($privcode) { + if (remote_can_grant($remote, $privcode, $arg)) { + if (LJ::check_priv($u, $privcode, $arg)) { + $ret .= "ERROR: User already has specified priv $privcode $arg.
    "; + } else { + my $qarg = $dbh->quote($arg); + $dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $qpriv, $qarg)"); + LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$arg\""); + $ret .= "Privilege $privcode $arg granted.
    \n"; + } + } else { + $ret .= "ERROR: You don't have access to grant $privcode $arg.
    \n"; + } + } else { + $ret .= "ERROR: Unknown privilege.
    \n"; + } + } + if ($FORM{'grantuser'}) { + my $u = LJ::load_user($FORM{'grantuser'}); + return "ERROR: Invalid user." unless $u; + my $userid = $u->{'userid'}; + my $privid = $pcode2id{$FORM{'priv'}}; + my $arg = $FORM{'arg'}; + my $qarg = $dbh->quote($arg); + my $privcode = $priv{$privid}->{'privcode'}; + if ($privcode) { + if (remote_can_grant($remote, $privcode, $arg)) { + if (LJ::check_priv($u, $privcode, $arg)) { + $ret .= "ERROR: User already has specified priv $privcode $arg.
    "; + } + elsif ($userid && $privid) { + my $qarg = $dbh->quote($FORM{'arg'}); + $dbh->do("INSERT INTO priv_map (prmid, userid, prlid, arg) VALUES (NULL, $userid, $privid, $qarg)"); + LJ::statushistory_add($dbh, $userid, $remote->{'userid'}, "privadd", "Granting: \"$privcode\" with arg \"$FORM{'arg'}\""); + $ret .= "Privilege added.
    \n"; + } + else { + my $euser = LJ::ehtml($FORM{'grantuser'}); + unless ($userid) { + $ret .= "ERROR: cannot grant priv to non-existent user $euser
    "; + } + else { $ret .= "privid is 0!
    "; } + } + } else { + $ret .= "ERROR: You don't have access to grant $privcode with argument '$arg'.
    \n"; + } + } else { + $ret .= "ERROR: Unknown privilege.
    \n"; + } + } # end if grantuser + } + + if ($mode eq "userchange") { $mode = "viewuser"; } + if ($mode eq "privchange") { $mode = "viewpriv"; } + } + + if ($mode eq "viewuser") + { + my $user = LJ::canonical_username($FORM{'user'}); + my $userid = LJ::get_userid($user); + + $ret .= "

    << view user \"$user\"

    \n"; + unless ($userid) { + $ret .= "Error: non-existent user\n"; + return $ret; + } + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= "\n"; + $ret .= "\n"; + $sth = $dbh->prepare("SELECT pm.prmid, pm.prlid, pm.arg FROM priv_map pm, priv_list pl WHERE pm.prlid=pl.prlid AND pm.userid=$userid ORDER BY pl.privcode,pm.arg"); + $sth->execute; + $ret .= "\n"; + while (my ($prmid, $prlid, $arg) = $sth->fetchrow_array) + { + my $prec = $priv{$prlid}; + my $pcode = $priv{$prlid}->{'privcode'}; + my $can_grant = remote_can_grant($remote, $pcode, $arg); + + next unless ($prec->{'is_public'} || ($remote && $remote->{'userid'} == $userid) || $can_grant); + + $ret .= ""; + if ($arg) + { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + $ret .= "
    RevokePrivilegeArg
    "; + if ($can_grant) { + $ret .= ""; + } else { + $ret .= "--"; + } + + $ret .= "$pcode$arg
     
    "; + + if (LJ::check_priv($remote, 'admin')) { + $ret .= "

    Grant $user privilege:

    \n"; + $ret .= "\n"; + $ret .= "Arg:
    \n"; + } else { + $ret .= "

    (you do not have access to grant any privileges)

    \n"; + } + + $ret .= "

    \n"; + if (LJ::check_priv($remote, 'admin')) { + $ret .= ""; + } + $ret .= " "; + $ret .= "

    "; + return $ret; + } + + if ($mode eq "viewpriv") { + my $priv = $pcode2id{$FORM{'priv'}}; + my $prec = $priv{$priv}; + my $pcode = $prec->{'privcode'}; + my $skip = $FORM{'skip'} + 0; + my $limit = 100; + + my $viewarg; + if ($FORM{'viewarg'}) { + $viewarg = " AND pm.arg=" . $dbh->quote($FORM{'viewarg'}); + } + + my $privname = join(' ', grep { $_ } $priv{$priv}->{'privcode'}, $FORM{'viewarg'}); + $ret .= "

    << view priv \"$privname\"

    \n"; + $ret .= "

    Privilege Name: $priv{$priv}->{'privname'}"; + my ($des, $args) = split(/arg=/, $priv{$priv}->{'des'}); + $ret .= "
    Description: $des" if $des; + $ret .= "
    Argument: $args" if $args; + $ret .= "

    "; + + my ($check_priv, $check_arg) = split("/", $FORM{'viewarg'}); + unless ($prec->{'is_public'} || remote_can_grant($remote, $check_priv, $check_arg)) { + $ret .= "

    ERROR: This privilege's access list is not public.

    \n"; + return $ret; + } + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= "

    View only privs with arg: "; + $ret .= " "; + $ret .= "

    \n"; + + $ret .= "\n"; + $ret .= ""; + $sth = $dbh->prepare("SELECT pm.prmid, u.user, u.userid, pm.arg ". + "FROM priv_map pm, useridmap u WHERE pm.prlid=$priv AND pm.userid=u.userid$viewarg ". + "ORDER BY u.user,pm.arg LIMIT $skip,$limit"); + $sth->execute; + $ret .= "\n"; + + my $showgrant = remote_can_grant($remote, $pcode, $FORM{'viewarg'}); + my $foundcount = 0; + + while ($_ = $sth->fetchrow_hashref) + { + $foundcount++; + $ret .= ""; + if ($_->{'arg'} ne "") + { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + $ret .= "\n"; + $ret .= "
    RevokeUserArg
    "; + if (remote_can_grant($remote, $priv{$priv}->{'privcode'}, $_->{'arg'})) + { + $ret .= "{'prmid'}:$_->{'userid'}\" />"; + } else { + $ret .= "--"; + } + $ret .= "{'user'}\">$_->{'user'}{'privcode'}&viewarg=$_->{'arg'}\">$_->{'arg'}
     
    $foundcount users
    "; + + if ($foundcount >= $limit) { + $ret .= "($skip +$limit)}) . "'>See more...\n"; + } + + if ($showgrant) { + $ret .= "

    Grant $privname privilege to:

      "; + $ret .= "User: "; + $ret .= "Arg:
    \n"; + } else { + $ret .= "

    (you don't have access to grant this privilege to other users)

    \n"; + } + + if ($showgrant) { + $ret .= "\n"; + } + $ret .= "
    \n"; + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + $ret .= LJ::html_hidden('mode', 'privchange', + 'priv', $pcode, + 'viewarg', $FORM{'viewarg'}) . "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + return $ret; + } + + return "Unknown mode."; + +_code?> + + + +lib: cgi-bin/ljlib.pl +link: htdocs/admin/priv/index.bml +post: htdocs/admin/priv/index.bml + diff --git a/livejournal/htdocs/admin/recent_comments.bml b/livejournal/htdocs/admin/recent_comments.bml new file mode 100755 index 0000000..5e4f292 --- /dev/null +++ b/livejournal/htdocs/admin/recent_comments.bml @@ -0,0 +1,60 @@ + +Comment view + +Error: You don't have access to viewing recent comments." + unless LJ::check_priv($remote, "siteadmin", "commentview"); + + my $user = $GET{'user'}; + my $u; + if ($user =~ /^\#(\d+)/) { + $u = LJ::load_userid($1); + } elsif ($user) { + $u = LJ::load_user($user); + } + unless ($u) { + return "
    Username or (#userid) to view comments of: ". + "
    "; + } + $user = $u->{'user'}; + $ret .= "<< Recent comments of " . LJ::ljuser($u) . " (\#$u->{userid})
    \n"; + + my $dbcr = LJ::get_cluster_reader($u); + return "Error: can't get DB for user" unless $dbcr; + + my $now = time(); + + my $sth = $dbcr->prepare("SELECT posttime, journalid, nodetype, nodeid, jtalkid, publicitem ". + "FROM talkleft ". + "WHERE userid=? ORDER BY posttime DESC LIMIT 250"); + $sth->execute($u->{'userid'}); + my %jcount; # jid -> ct + while (my $r = $sth->fetchrow_hashref) { + $jcount{$r->{'journalid'}}++; + next unless $r->{'nodetype'} eq "L"; # log2 comment + + my $ju = LJ::load_userid($r->{'journalid'}); + my $lrow = LJ::get_log2_row($ju, $r->{'nodeid'}); + my $hr_ago = sprintf("%.1f", ($now - $r->{'posttime'}) / 3600); + + if ($lrow) { + my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'}; + my $url = "$LJ::SITEROOT/users/$ju->{user}/$lrow->{ditemid}.html?thread=$talkid\#t$talkid"; + $ret .= "$hr_ago hr ago in " . LJ::ljuser($ju) . ": $url
    \n"; + } else { + $ret .= "$hr_ago hr ago in " . LJ::ljuser($ju) . ": link unavailable
    "; + } + } + + return $ret; + +} +_code?> + + diff --git a/livejournal/htdocs/admin/schema/index.bml b/livejournal/htdocs/admin/schema/index.bml new file mode 100755 index 0000000..76a3547 --- /dev/null +++ b/livejournal/htdocs/admin/schema/index.bml @@ -0,0 +1,278 @@ +schema documentation, "; + $body .= "but you don't have the 'schemadoc' priv."; + return; + } + + sub magic_links + { + my $des = shift; + $$des =~ s!\[dbtable\[(\w+?)\]\]!$1!g; + } + + if ($FORM{'mode'} eq "") + { + my %table; + $sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables"); + $sth->execute; + while (my ($name, $public, $des) = $sth->fetchrow_array) { + $table{$name} = { 'public' => $public, 'des' => $des }; + } + + $body .= "

    >\n"; + $sth = $dbh->prepare("SHOW TABLES"); + $sth->execute; + while (my ($table) = $sth->fetchrow_array) { + my $des = $table{$table}->{'des'} || "no description, yet"; + magic_links(\$des); + $body .= "\n"; + } + $body .= "
    TableDescription
    $table"; + if ($table{$table}->{'public'}) { + $body .= " (data)"; + } + $body .= "$des
    \n"; + return; + } + + if ($FORM{'mode'} eq "viewtable") + { + my $table = $FORM{'table'}; + if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; } + my $qtable = $dbh->quote($table); + + $sth = $dbh->prepare("SELECT des, public_browsable FROM schematables WHERE tablename=$qtable"); + $sth->execute; + my ($tabledes, $browsable) = $sth->fetchrow_array; + + $body .= "<< Tables"; + if ($browsable) { + $body .= " | View Data"; + } + if ($can_doc) { + $body .= " | Edit Documentation"; + } + $body .= "$table table."; + } + $body .= " p?>

    \n"; + + my %coldes; + $sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable"); + $sth->execute; + while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; } + + $sth = $dbh->prepare("DESCRIBE $table"); + $sth->execute; + $body .= ">"; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "\n"; + while (my $row = $sth->fetchrow_hashref) + { + my $name = $row->{'Field'}; + my $type = $row->{'Type'}; + my $key = $row->{'Key'}; + my $null = $row->{'Null'}; + my $def = $row->{'Default'}; + my $des = BML::eall($coldes{$name}); + + magic_links(\$des); + + $type =~ s/int\(\d+\)/int/g; + + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "\n"; + } + $body .= "
    Key?ColumnTypeNullDefaultDescription
    $key$name$type$null$def$des
    \n"; + return; + } + + if ($FORM{'mode'} eq "viewdata") { + my $table = $FORM{'table'}; + if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; } + + my $MAX_ROWS = 100; + + $body .= "<< Tables
    << Table: $table$table table. If the table has more than $MAX_ROWS records, only the top $MAX_ROWS are shown. p?>

    \n"; + + $sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables WHERE tablename='$table'"); + $sth->execute; + my ($tablename, $public, $des) = $sth->fetchrow_array; + unless ($public) { $body .= "This table's data is not public.\n"; return; } + + $sth = $dbh->prepare("SELECT * FROM $table LIMIT $MAX_ROWS"); + $sth->execute; + $body .= ">"; + foreach my $col (@{$sth->{'NAME'}}) { + $body .= "\n"; + } + $body .= "\n"; + + while (my $row = $sth->fetchrow_arrayref) { + $body .= "\n"; + foreach my $val (@$row) { + $body .= "\n"; + } + $body .= "\n"; + } + $body .= "
    $col
    $val
    \n"; + return; + } + + # show form to enter documentation + if ($FORM{'mode'} eq "doc") + { + unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; } + my $table = $FORM{'table'}; + if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; } + + $body .= "<< Tables"; + + my $qtable = $dbh->quote($table); + my $sth; + + $sth = $dbh->prepare("SELECT des FROM schematables WHERE tablename=$qtable"); + $sth->execute; + my ($tabledes) = $sth->fetchrow_array; + + my %coldes; + $sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable"); + $sth->execute; + while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; } + + $body .= "

    \n"; + $body .= "\n"; + $body .= "\n"; + $body .= "

    Description:
    "; + + $sth = $dbh->prepare("DESCRIBE $table"); + $sth->execute; + $body .= "

    >"; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "\n"; + while (my $row = $sth->fetchrow_hashref) + { + my $name = $row->{'Field'}; + my $type = $row->{'Type'}; + $type =~ s/int\(\d+\)/int/g; + + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "\n"; + } + $body .= "
    ColumnTypeDescription
    $name$type
    \n"; + $body .= "

    "; + return; + } + + # save documentation + if ($FORM{'mode'} eq "docsave") + { + unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; } + my $table = $FORM{'table'}; + if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; } + + $body .= "<< Tables"; + + my $qtable = $dbh->quote($table); + my $sth; + + $sth = $dbh->prepare("SELECT tablename, des FROM schematables WHERE tablename=$qtable"); + $sth->execute; + my ($tablename, $tabledes) = $sth->fetchrow_array; + $FORM{'table-des'} =~ s/\r//; + my $qdes = $dbh->quote($FORM{'table-des'}); + if ($tablename) { + # row exists, update. + $dbh->do("UPDATE schematables SET des=$qdes WHERE tablename=$qtable"); + } else { + # no row exists, so insert + $dbh->do("INSERT INTO schematables (tablename, public_browsable, des) VALUES ($qtable, '0', $qdes)"); + } + if ($dbh->err) { $body .= $dbh->errstr; return; } + + my %olddes; + my %newdes; + + ### load old descriptions + $sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable"); + $sth->execute; + while (my ($col, $des) = $sth->fetchrow_array) { $olddes{$col} = $des; } + + ### check new descriptions (only for valid columns) + $sth = $dbh->prepare("DESCRIBE $table"); + $sth->execute; + if ($dbh->err) { $body .= $dbh->errstr; return; } + while (my $row = $sth->fetchrow_hashref) + { + my $name = $row->{'Field'}; + my $type = $row->{'Type'}; + + $FORM{"col-$name"} =~ s/\r//; + if ($FORM{"col-$name"} ne $olddes{$name}) { + $newdes{$name} = $FORM{"col-$name"}; + } + } + if (%newdes) { + my $sql = "REPLACE INTO schemacols (tablename, colname, des) VALUES "; + foreach my $col (keys %newdes) { + my $qcol = $dbh->quote($col); + my $qdes = $dbh->quote($newdes{$col}); + $sql .= "($qtable, $qcol, $qdes),"; + } + chop $sql; + $dbh->do($sql); + if ($dbh->err) { $body .= "[3] ($sql)

    " . $dbh->errstr; return; } + } + + $body .= "View. p?>"; + + return; + } + + + return; + +_code?> +body=> +page?> +link: htdocs/admin/scheme/index.bml + _c?> diff --git a/livejournal/htdocs/admin/spamreports.bml b/livejournal/htdocs/admin/spamreports.bml new file mode 100755 index 0000000..e583fbd --- /dev/null +++ b/livejournal/htdocs/admin/spamreports.bml @@ -0,0 +1,276 @@ +$reporttime"; + }; + my $dellink = sub { + my ($by, $what, $text) = @_; + return "

    " . + LJ::html_hidden('mode', $by) . + LJ::html_hidden('what', $what) . + LJ::html_hidden('ret', "spamreports.bml?" . join('&', map { "$_=" . LJ::eurl($GET{$_}) } keys %GET)) . + LJ::html_submit('submit', $text) . + "
    "; + }; + + # login check + my $remote = LJ::get_remote(); + return $error->("You must be logged in to be here.") + unless $remote; + + # priv check + return $error->("You do not have the necessary privilege to be here.") + unless LJ::check_priv($remote, 'siteadmin', 'spamreports'); + + # show the top 10 spam reports by IP + my $mode = lc($GET{mode} || $POST{mode}); + $mode = '' if $mode =~ /^del/ && !LJ::did_post() && !LJ::check_referer('/admin/spamreports.bml'); + + # combined/user/anon viewing? + my $view = $mode =~ /_([cua])$/ ? $1 : 'c'; + my ($extrawhere, $extratitle); + if ($view eq 'c') { $extrawhere = '1'; } + elsif ($view eq 'u') { $extrawhere = 'posterid > 0'; $extratitle = " - Users Only"; } + elsif ($view eq 'a') { $extrawhere = 'posterid = 0'; $extratitle = " - Anonymous Only"; } + $mode =~ s/_[cua]$//; # strip out viewing option + + my $dbr = LJ::get_db_reader(); + return $error->("Unable to get database reader handle.") unless $dbr; + my @rows; + my @headers; + if ($mode eq 'top10ip') { + # top 10 by ip + $title = "Spam Reports - Top 10 by IP Address"; + @headers = ('Number of Reports', 'IP Address', 'Most Recent Report'); + my $res = $dbr->selectall_arrayref('SELECT COUNT(ip) AS num, ip, MAX(reporttime) FROM spamreports ' . + "WHERE state = 'open' AND ip IS NOT NULL " . + 'GROUP BY ip ORDER BY num DESC LIMIT 10'); + foreach (@$res) { + push @rows, [ $_->[0], $_->[1], $makelink->('ip', $_->[1], 'open', $_->[2]) ]; + } + + } elsif ($mode eq 'top10user') { + # top 10 by user + $title = "Spam Reports - Top 10 by User"; + @headers = ('Number of Reports', 'Posted By User', 'Most Recent Report'); + my $res = $dbr->selectall_arrayref('SELECT COUNT(posterid) AS num, posterid, MAX(reporttime) FROM spamreports ' . + "WHERE state = 'open' AND posterid > 0 " . + 'GROUP BY posterid ORDER BY num DESC LIMIT 10'); + foreach (@$res) { + my $u = LJ::load_userid($_->[1]); + push @rows, [ $_->[0], LJ::ljuser($u), $makelink->('posterid', $_->[1], 'open', $_->[2]) ]; + } + + } elsif ($mode eq 'tlast10') { + # most recent 10 reports + $title = "Spam Reports - Last 10$extratitle"; + @headers = ('Posted By', 'Posted In', 'Report Time'); + my $res = $dbr->selectall_arrayref('SELECT posterid, ip, journalid, reporttime FROM spamreports ' . + "WHERE state = 'open' AND $extrawhere ORDER BY reporttime DESC LIMIT 10"); + foreach (@$res) { + my $u2 = LJ::load_userid($_->[2]); + if ($_->[0] > 0) { + my $u = LJ::load_userid($_->[0]); + push @rows, [ LJ::ljuser($u), LJ::ljuser($u2), $makelink->('posterid', $_->[0], 'open', $_->[3]) ]; + } else { + push @rows, [ "$_->[1]", LJ::ljuser($u2), $makelink->('ip', $_->[1], 'open', $_->[3]) ]; + } + } + + } elsif ($mode =~ /^last(\d+)hr$/) { + # reports in last X hours + my $hours = $1+0; + my $secs = $hours * 3600; # seconds in an hour + $title = "Spam Reports - Last $hours Hour" . ($hours == 1 ? '' : 's') . $extratitle; + @headers = ('Number of Reports', 'Posted By', 'Report Time'); + my $res = $dbr->selectall_arrayref('SELECT journalid, ip, posterid, reporttime FROM spamreports ' . + "WHERE $extrawhere AND reporttime > (UNIX_TIMESTAMP() - $secs) LIMIT 1000"); + + # count up items and their most recent report + my %hits; + my %times; + foreach (@$res) { + my $key; + if ($_->[2] > 0) { + my $u = LJ::load_userid($_->[2]); + next unless $u; + $key = $u->{userid}; + } else { + next unless $_->[1]; + $key = $_->[1]; + } + $hits{$key}++; + $times{$key} = $_->[3] unless $times{$key} gt $_->[3]; + } + + # now reverse to number => item list + my %revhits; + foreach (keys %hits) { + if ($revhits{$hits{$_}}) { + push @{$revhits{$hits{$_}}}, $_; + } else { + $revhits{$hits{$_}} = [ $_ ]; + } + } + + # now push them onto @rows + foreach (sort { $b <=> $a } keys %revhits) { + my $r = $revhits{$_}; + foreach (@$r) { + my $isip = $_ =~ /\./ ? 1 : 0; + push @rows, [ $hits{$_}, $isip ? $_ : LJ::ljuser(LJ::load_userid($_)), + $makelink->($isip ? 'ip' : 'posterid', $_, 'open', $times{$_}) ]; + } + } + + } elsif ($mode eq 'view') { + # view a particular report + my ($by, $what, $state) = (lc($GET{by}), $GET{what}, lc($GET{state})); + $by = '' unless $by =~ /^(?:ip|poster(?:id)?)$/; + $state = 'open' unless $state =~ /^(?:open|closed)$/; + $body .= "<< Front Page ] "; + + # open/closed links + my $eargs = LJ::eurl("?by=$by&what=$what&state"); + if ($state eq 'open') { + $body .= " [ " . $makelink->($by, $what, 'closed', undef, "View Closed Reports") . " ]"; + } else { + $body .= " [ " . $makelink->($by, $what, 'open', undef, "View Open Reports") . " ]"; + } + $body .= " p?>\n"; + + # setup title and verify that the data is right + if ($by eq 'posterid') { + $what += 0; + my $u = LJ::load_userid($what); + return $error->('No such posterid.') unless $u; + $title = "Spam Reports - By $u->{user} ($state)"; + } elsif ($by eq 'poster') { + my $u = LJ::load_user($what); + return $error->('No such user.') unless $u; + $title = "Spam Reports - Comments By $u->{user}"; + + # Now just pretend that user used 'posterid' + $by = 'posterid'; + $what = $u->{userid}; + } elsif ($by eq 'ip') { + # check for right format x.x.x.x, not necessarily a valid IP + return $error->('No such IP.') if $what !~ /^\d+\.\d+\.\d+\.\d+$/ or length $what > 15; + $title = "Spam Reports - By IP $what ($state)"; + } + + # see if we should call a hook for extra actions? + $body .= LJ::run_hook('spamreport_notification', $remote, { $by => $what }) + if $state eq 'open' && $by eq 'posterid'; + + # now the general info gathering + my $res = $dbr->selectall_arrayref('SELECT reporttime, journalid, subject, body, ip, posttime, report_type ' . + "FROM spamreports WHERE state=? AND $by=? ORDER BY reporttime DESC LIMIT 1000", + undef, $state, $what); + unless ($res && @$res) { + $body .= "No reports found."; + return undef; + } + $body .= ''; + foreach (@$res) { + my $u2 = LJ::load_userid($_->[1]); + my $x = $by eq 'ip' ? 4 : 1; + my $comment_body = $_->[3]; + LJ::text_uncompress(\$comment_body); + my $spamlocation = ($_->[6] eq 'entry') ? 'Entry' : 'Comment'; + $body .= ''; + } + $body .= "
    ' . ($state eq 'open' ? $dellink->("del$by", "$_->[0]:$_->[$x]", 'Close') : '') . '' . + "$spamlocation in: " . LJ::ljuser($u2) . '
    ' . + 'Report Time: ' . LJ::mysql_time($_->[0]) . '
    ' . + "$spamlocation Time: " . ($_->[5] ? LJ::mysql_time($_->[5]) : 'not recorded') . '
    ' . + 'Subject: ' . LJ::ehtml($_->[2] || 'no subject') . '
    ' . + 'Body: ' . LJ::ehtml($comment_body || 'no body') . '
    ' . + '
     

    " . ($state eq 'open' ? $dellink->("delby$by", $what, 'Close All') : ''); + + } elsif ($mode =~ /^del/) { + # figure out our combination + my $dbh = LJ::get_db_writer(); + return $error->("Unable to get database writer handle.") unless $dbh; + my ($sql, $count, $backlink); + if ($mode =~ /^delby/) { + # enmasse deletion + my $where = $mode =~ /ip$/ ? 'ip' : 'posterid'; + $sql = "UPDATE spamreports SET state='closed' WHERE $where=?"; + $count = $dbh->do($sql, undef, $POST{what}); + return $error->($dbh->errstr) if $dbh->err; + } else { + # single item deletion + my $where = $mode =~ /ip$/ ? 'ip' : 'journalid'; + my ($time, $data) = ($1, $2) + if $POST{what} =~ /^(\d+):(.+)$/; + $data ||= $POST{what}; + $count = $dbh->do("UPDATE spamreports SET state='closed' WHERE reporttime=? AND $where=? AND state='open'", undef, $time, $data); + return $error->($dbh->errstr) if $dbh->err; + $backlink = "[ << Go Back ]"; + } + $title = "Close Reports"; + $body .= "<< Front Page ] $backlink p?>\n"; + my $s = $count == 1 ? '' : 's'; + $body .= "Closed $count report$s.\n"; + + } else { + # standard + my %modes = (top10user => 'Top 10 by User', top10ip => 'Top 10 by IP Address', tlast10 => 'Last 10 Reports', + last01hr => 'Last 1 Hour', last06hr => 'Last 6 Hours', last24hr => 'Last 24 Hours'); + $body .= "\n
      "; + foreach (sort keys %modes) { + $body .= "
    • $modes{$_}"; + if ($_ =~ /last/) { + # this is a last view, so we have other options + $body .= " [users, "; + $body .= "anonymous]"; + } + $body .= "
    • "; + } + $body .= qq{
    • +
    • + }; + $body .= "
    \n"; + } + + # now spit out the requested table + return unless @headers; + $body .= "<< Front Page ] p?>"; + $body .= "\n"; + $body .= "" foreach @headers; + $body .= "\n"; + foreach (@rows) { + $body .= ""; + $body .= "" foreach @$_; + $body .= "\n"; + } + $body .= "
    $_
    $_
    \n"; + + return; +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/admin/statushistory.bml b/livejournal/htdocs/admin/statushistory.bml new file mode 100755 index 0000000..bc070a9 --- /dev/null +++ b/livejournal/htdocs/admin/statushistory.bml @@ -0,0 +1,122 @@ + +Status History + +\n"; + $ret .= LJ::html_hidden('orderby', $FORM{'orderby'}, 'flow', $FORM{'flow'}) . "\n"; + $ret .= "User: " . LJ::html_text({ 'name' => 'user', 'size' => '15', 'maxlength' => '15' }) . "\n"; + $ret .= "Admin: " . LJ::html_text({ 'name' => 'admin', 'size' => '15', 'maxlength' => '15' }) . "\n"; + $ret .= "Type: " . LJ::html_text({ 'name' => 'type', 'size' => '20', 'maxlength' => '20' }) . "\n"; + $ret .= LJ::html_submit('query_submit', 'Search'); + $ret .= "\n\n"; + + return $ret unless ($FORM{'user'} || $FORM{'admin'} || $FORM{'type'}); + + $ret .= "
    \n\n"; + + # build query + my @where; + if ($FORM{'user'} ne "") { + my $userid = LJ::get_userid($FORM{'user'}); + unless ($userid) { return "unknown user"; } + push @where, "s.userid=$userid"; + } + + if ($FORM{'admin'} ne "") { + my $userid = LJ::get_userid($FORM{'admin'}); + unless ($userid) { return "unknown admin"; } + push @where, "s.adminid=$userid"; + } + + if ($FORM{'type'} ne "") { + my $qt = $dbr->quote($FORM{'type'}); + push @where, "s.shtype=$qt"; + } + + my $where = "WHERE " . join(" AND ", @where) . " " if @where; + + my $orderby = 'shdate'; + foreach (qw(user admin shdate shtype notes)) { + $orderby = "u.$_", next if $FORM{'orderby'} eq $_ && $_ eq 'user'; + $orderby = "ua.$_", next if $FORM{'orderby'} eq $_ && $_ eq 'admin'; + $orderby = "s.$_" if $FORM{'orderby'} eq $_; + } + my $flow = $FORM{'flow'} eq 'asc' ? 'ASC' : 'DESC'; + + my $sth = $dbr->prepare("SELECT u.user, ua.user AS admin, s.shtype, s.shdate, s.notes " . + "FROM statushistory s " . + "LEFT JOIN useridmap ua ON s.adminid=ua.userid " . + "LEFT JOIN useridmap u ON s.userid=u.userid " . + $where . + "ORDER BY $orderby $flow LIMIT 1000"); + $sth->execute; + return $dbr->errstr if $dbr->err; + + # column headings w/ sort links + $ret .= "

    Query:"; + foreach (qw(user admin type)) { + $ret .= "  $_=" . LJ::eall($FORM{$_}) if $FORM{$_} + } + $ret .= "

    \n"; + $ret .= "\n"; + foreach (qw(user admin shtype shdate notes)) { + my $link = "statushistory.bml?user=$FORM{'user'}&admin=$FORM{'admin'}&type=$FORM{'type'}&orderby=$_"; + $link .= $FORM{'orderby'} eq $_ && $FORM{'flow'} eq 'asc' ? "&flow=desc" : "&flow=asc"; + $ret .= ""; + } + $ret .= "\n"; + + # query built above + my $ct = 0; + while (my $hist = $sth->fetchrow_hashref) { + # see if they can see this item: either they have unarged historyview or + # they have historyview:shtype + next unless LJ::check_priv($remote, 'historyview', '') || + LJ::check_priv($remote, 'historyview', $hist->{shtype}); + + $ret .= ""; + foreach (qw(user admin shtype shdate notes)) { + + $ret .= ""; + } + $ret .= "\n"; + $ct++; + } + + $ret .= "\n"; + $ret .= "
    $_
    "; + if ($hist->{$_} && ($_ eq 'user' || $_ eq 'admin')) { + $ret .= LJ::ljuser($hist->{$_}); + } elsif ($_ eq 'notes') { + # notes need to be ehtml'd, but afterwards, we can convert \n to
    + my $enotes = LJ::ehtml($hist->{$_}); + $enotes =~ s!\n!
    \n!g; + $ret .= $enotes; + } else { + $ret .= LJ::ehtml($hist->{$_}); + } + $ret .= "
    $ct rows in set"; + $ret .= "[truncated]" if $ct >= 1000; + $ret .= "
    \n\n"; + + return $ret; +} +_code?> + + + diff --git a/livejournal/htdocs/admin/topics/blank.bml b/livejournal/htdocs/admin/topics/blank.bml new file mode 100755 index 0000000..c0c0ffe --- /dev/null +++ b/livejournal/htdocs/admin/topics/blank.bml @@ -0,0 +1 @@ +  diff --git a/livejournal/htdocs/admin/topics/index.bml b/livejournal/htdocs/admin/topics/index.bml new file mode 100755 index 0000000..4ab4312 --- /dev/null +++ b/livejournal/htdocs/admin/topics/index.bml @@ -0,0 +1,34 @@ +Topic Directory Administration +body<= + +Screen Topic Submissions that are awaiting approval into a category."; + } + + if (LJ::remote_has_priv($remote, "topicscreencat")) { + $ret .= "

    Screen Entry Submissions that are awaiting approval into a topic."; + } + + unless ($ret) { + $ret .= "You have no administrative priviledges in this area, or you are not logged in."; + } + + return $ret; + +_code?> + + +<=body +page?> +link: htdocs/admin/topics/screentop.bml, htdocs/admin/topics/screen.html + _c?> + diff --git a/livejournal/htdocs/admin/topics/links.bml b/livejournal/htdocs/admin/topics/links.bml new file mode 100755 index 0000000..cbd8cef --- /dev/null +++ b/livejournal/htdocs/admin/topics/links.bml @@ -0,0 +1,30 @@ +prepare("SELECT styleid, user, styledes, type, is_embedded, is_colorfree FROM style WHERE is_public='Y' ORDER BY user"); + $sth->execute; + + my $ret = ""; + my $last = ""; + while ($sty = $sth->fetchrow_hashref) { + if ($last ne $sty->{'user'}) { + $last = $sty->{'user'}; + $ret .= "$last
    \n"; + } + if ($user) { + $ret .= "  - {'styleid'}&user=$user\">$sty->{'styledes'}
    \n"; + } else { + $ret .= "  - {'styleid'}\">$sty->{'styledes'}
    \n"; + } + } + + return $ret; + +_code?> +link: htdocs/customview.cgi, htdocs/admin/topics/styleinfo.bml + _c?> + diff --git a/livejournal/htdocs/admin/topics/screen.html b/livejournal/htdocs/admin/topics/screen.html new file mode 100755 index 0000000..781451d --- /dev/null +++ b/livejournal/htdocs/admin/topics/screen.html @@ -0,0 +1,17 @@ + + + Topic Directory Administration + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/htdocs/admin/topics/screen_do.bml b/livejournal/htdocs/admin/topics/screen_do.bml new file mode 100755 index 0000000..4b38baa --- /dev/null +++ b/livejournal/htdocs/admin/topics/screen_do.bml @@ -0,0 +1,50 @@ +prepare("UPDATE topic_map SET status='on', screendate=NOW(), " . + "screenuserid=? WHERE tptopid=? AND itemid=? AND status='new'"); + $sth->execute($remote->{'userid'}, $topid, $itemid); + if ($sth->rows) { + $ret .= "$itemid approved.
    \n"; + } else { + $ret .= "$itemid already acted on.
    \n"; + } + } + if ($act eq "D") { + my $sth = $dbh->prepare("UPDATE topic_map SET status='deny', screendate=NOW(), " . + "screenuserid=? WHERE tptopid=? AND itemid=? AND status='new'"); + $sth->execute($remote->{'userid'}, $topid, $itemid); + if ($sth->rows) { + $ret .= "$itemid denied.
    \n"; + } else { + $ret .= "$itemid already acted on.
    \n"; + } + } + } + + return $ret; + +_code?> +# None + _c?> + diff --git a/livejournal/htdocs/admin/topics/screen_instructions.bml b/livejournal/htdocs/admin/topics/screen_instructions.bml new file mode 100755 index 0000000..09485ad --- /dev/null +++ b/livejournal/htdocs/admin/topics/screen_instructions.bml @@ -0,0 +1,6 @@ +Click an item on the left and it will appear here. Read it, decide if it's applicable to the category, and then select "Approve" or "Deny". + \ No newline at end of file diff --git a/livejournal/htdocs/admin/topics/screen_links.bml b/livejournal/htdocs/admin/topics/screen_links.bml new file mode 100755 index 0000000..9eb9ad8 --- /dev/null +++ b/livejournal/htdocs/admin/topics/screen_links.bml @@ -0,0 +1,106 @@ +quote($_); } keys %cataccess); + $and_cat_in = "AND tl.tpcatid IN ($in)"; + } + + $sth = $dbh->prepare("SELECT tm.tpmapid, tm.tptopid, tm.itemid FROM topic_map tm, topic_list tl WHERE tm.tptopid=tl.tptopid AND tm.status='new' $and_cat_in LIMIT 50"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + my %topic; + while (my $map = $sth->fetchrow_hashref) + { + push @maps, $map; + $topic{$map->{'tptopid'}} = undef; + } + + unless (@maps) { + return "Empty! ... no items are awaiting approval"; + } + + my $top_in = join(",", keys %topic); + $sth = $dbh->prepare("SELECT tptopid, tpcatid, topname FROM topic_list WHERE tptopid IN ($top_in)"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + my %cat; + while (my $top = $sth->fetchrow_hashref) + { + $topic{$top->{'tptopid'}} = $top; + $cat{$top->{'tpcatid'}} = undef; + } + + my $cat_in = join(",", keys %cat); + $sth = $dbh->prepare("SELECT tpcatid, parent, catname FROM topic_cats WHERE tpcatid IN ($cat_in)"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + while (my $cat = $sth->fetchrow_hashref) + { + $cat{$cat->{'tpcatid'}} = $cat; + } + + $ret .= "

    "; + + foreach my $map (@maps) + { + my $catid = $topic{$map->{'tptopid'}}->{'tpcatid'}; + next unless ($cataccess{'all'} || $cataccess{$catid}); + &load_cats_up($catid, \%cat); + $ret .= "

    "; + my $fullcat; + my $catup = $catid; + while ($catup) { + $fullcat = "$cat{$catup}->{'catname'} : $fullcat"; + $catup = $cat{$catup}->{'parent'}; + } + $fullcat .= $topic{$map->{'tptopid'}}->{'topname'}; + $ret .= "[$fullcat]"; + $ret .= "
    {'itemid'}\" TARGET=\"main\">$map->{'itemid'}"; + my %opts = ("L" => "Leave", "A" => "Approve", "D" => "Deny"); + foreach (qw(L A D)) { + $ret .= "
    {'tptopid'}:$map->{'itemid'}\" VALUE=\"$_\">$opts{$_}\n"; + } + } + + $ret .= "

    "; + + return $ret; + + sub load_cats_up + { + my $catid = shift; + my $hashref = shift; + $catid += 0; + while ($catid) + { + unless ($hashref->{$catid}) { + $sth = $dbh->prepare("SELECT parent, catname FROM topic_cats WHERE tpcatid=$catid"); + $sth->execute; + my $cat = $sth->fetchrow_hashref; + if ($cat) { + $hashref->{$catid} = $cat; + $catid = $cat->{'parent'} + } + } else { + $catid = $hashref->{$catid}->{'parent'}; + } + } + } + +_code?> +link: htdocs/talkpost.bml +post: htdocs/admin/topics/screen_links.bml + _c?> + diff --git a/livejournal/htdocs/admin/topics/screentop.bml b/livejournal/htdocs/admin/topics/screentop.bml new file mode 100755 index 0000000..b34836b --- /dev/null +++ b/livejournal/htdocs/admin/topics/screentop.bml @@ -0,0 +1,87 @@ +Screen Topics +body<= + +quote($_); } keys %cataccess); + $and_cat_in = "AND tpcatid IN ($in)"; + } + + $sth = $dbh->prepare("SELECT tptopid, tpcatid, topname FROM topic_list WHERE status='new' $and_cat_in"); + $sth->execute; + if ($dbh->err) { return $dbh->errstr; } + + @new = (); + push @new, $_ while ($_ = $sth->fetchrow_hashref); + + unless (@new) { + return "Empty! ... no topics are awaiting approval"; + } + + $ret .= "
    "; + + my $count = 0; + foreach my $new (@new) + { + next if (++$count > 50); + &load_cats_up($new->{'tpcatid'}, \%cat); + $ret .= "

    "; + my $fullcat; + my $catup = $new->{'tpcatid'}; + while ($catup) { + $fullcat = "$cat{$catup}->{'catname'} : $fullcat"; + $catup = $cat{$catup}->{'parent'}; + } + $fullcat =~ s/\s+:\s+$//; + $ret .= "[$fullcat]"; + $ret .= "
    $new->{'topname'}"; + my %opts = ("L" => "Leave", "A" => "Approve", "D" => "Deny"); + foreach (qw(L A D)) { + $ret .= "
    {'tptopid'}\" VALUE=\"$_\">$opts{$_}\n"; + } + } + + $ret .= "

    "; + + return $ret; + + sub load_cats_up + { + my $catid = shift; + my $hashref = shift; + $catid += 0; + while ($catid) + { + unless ($hashref->{$catid}) { + $sth = $dbh->prepare("SELECT parent, catname FROM topic_cats WHERE tpcatid=$catid"); + $sth->execute; + my $cat = $sth->fetchrow_hashref; + if ($cat) { + $hashref->{$catid} = $cat; + $catid = $cat->{'parent'} + } + } else { + $catid = $hashref->{$catid}->{'parent'}; + } + } + } + + +_code?> +<=body +page?> +post: htdocs/admin/topics/screentop_do.bml + _c?> + diff --git a/livejournal/htdocs/admin/topics/screentop.html b/livejournal/htdocs/admin/topics/screentop.html new file mode 100755 index 0000000..ef7ba27 --- /dev/null +++ b/livejournal/htdocs/admin/topics/screentop.html @@ -0,0 +1,18 @@ + + + Topic Directory Administration + + + + + + + + + + + \ No newline at end of file diff --git a/livejournal/htdocs/admin/topics/screentop_do.bml b/livejournal/htdocs/admin/topics/screentop_do.bml new file mode 100755 index 0000000..b27f559 --- /dev/null +++ b/livejournal/htdocs/admin/topics/screentop_do.bml @@ -0,0 +1,49 @@ +prepare("UPDATE topic_list SET status='on' WHERE tptopid=$topid AND status='new'"); + $sth->execute; + if ($sth->rows) { + $ret .= "$topid approved.
    \n"; + } else { + $ret .= "$topid already acted on.
    \n"; + } + } + if ($act eq "D") { + $sth = $dbh->prepare("UPDATE topic_list SET status='deny' WHERE tptopid=$topid AND status='new'"); + $sth->execute; + if ($sth->rows) { + $ret .= "$topid denied.
    \n"; + } else { + $ret .= "$topid already acted on.
    \n"; + } + + } + + } + + return $ret; + +_code?> +# None + _c?> + diff --git a/livejournal/htdocs/admin/topics/start.bml b/livejournal/htdocs/admin/topics/start.bml new file mode 100755 index 0000000..5d82141 --- /dev/null +++ b/livejournal/htdocs/admin/topics/start.bml @@ -0,0 +1,12 @@ +
    +Username to preview: + + +

    +

    + + \ No newline at end of file diff --git a/livejournal/htdocs/admin/userlog.bml b/livejournal/htdocs/admin/userlog.bml new file mode 100755 index 0000000..25c0a02 --- /dev/null +++ b/livejournal/htdocs/admin/userlog.bml @@ -0,0 +1,111 @@ +User Log Viewer +head<= + +<=head +body<= +" unless $remote; + + my $err = sub { + return ""; + }; + + return $err->("You do not have the necessary privilege to view this page.") + unless LJ::check_priv($remote, 'canview', 'userlog') || + LJ::check_priv($remote, 'canview', '*'); + + my $user = LJ::canonical_username($POST{user}); + + my $ret = < +Username: + +FORM + return $ret unless $user; + + my $u = LJ::load_user($user); + return $err->("User does not exist.") + unless $u; + + my $dbcr = LJ::get_cluster_reader($u); + return $err->("Unable to get user cluster reader.") + unless $dbcr; + + my $sth = $dbcr->prepare('SELECT * FROM userlog WHERE userid = ? ORDER BY logtime DESC LIMIT 1000'); + $sth->execute($u->{userid}); + return $err->("Database error: " . $sth->errstr) + if $sth->err; + + $ret .= ""; + $ret .= "\n"; + $ret .= ""; + $ret .= join('', map { "" } ("Date and Time", "Action", "Initiator", "IP Address", "Uniq Cookie")); + $ret .= "\n"; + + while (my $row = $sth->fetchrow_hashref) { + my $extra = {}; + LJ::decode_url_string($row->{extra}, $extra); + + my $action = "Action undefined for: $row->{action}"; + if ($row->{action} eq 'delete_entry') { + $action = "Deleted entry $row->{actiontarget} via $extra->{method}"; + } elsif ($row->{action} eq 'account_create') { + $action = "Account created"; + } elsif ($row->{action} eq 'ban_set') { + my $u = LJ::load_userid($row->{actiontarget}); + $action = "Banned " . LJ::ljuser($u) if $u; + } elsif ($row->{action} eq 'ban_unset') { + my $u = LJ::load_userid($row->{actiontarget}); + $action = "Unbanned " . LJ::ljuser($u) if $u; + } elsif ($row->{action} eq 'maintainer_add') { + my $u = LJ::load_userid($row->{actiontarget}); + $action = "Added maintainer " . LJ::ljuser($u) if $u; + } elsif ($row->{action} eq 'maintainer_remove') { + my $u = LJ::load_userid($row->{actiontarget}); + $action = "Removed maintainer " . LJ::ljuser($u) if $u; + } else { + $action = "Unknown action ($row->{action})"; + } + + my $time = LJ::mysql_time($row->{logtime}); + + my $actor; + if ($row->{remoteid}) { + my $u = LJ::load_userid($row->{remoteid}); + $actor = LJ::ljuser($u); + } else { + $actor = "not recorded"; + } + + my $ip = $row->{ip} || "not recorded"; + my $uniq = $row->{uniq} || "not recorded"; + + $ret .= "" . join('', map { "" } ($time, $action, $actor, $ip, $uniq)) . "\n"; + } + + $ret .= "
    $_
    $_
    "; + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/allpics.bml b/livejournal/htdocs/allpics.bml new file mode 100755 index 0000000..d87013a --- /dev/null +++ b/livejournal/htdocs/allpics.bml @@ -0,0 +1,184 @@ +{'user'} eq $user ? $remote : LJ::load_user($user); + + unless ($u) { + $body = ""; + return; + } + + LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head .= LJ::robot_meta_tags(); + } + + # no need for viewsome, due to the fact that none of this is private anyway. just + # allow anybody with any version of viewall to see userpics for non-V statusvis users + if ($GET{viewall} && LJ::check_priv($remote, 'canview')) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "allpics: $u->{'user'}, statusvis: $u->{'statusvis'}"); + } else { + if ($u->{'statusvis'} eq "S") { + $title = $ML{'error.suspended.title'}; + $body = " LJ::ljuser($u), + 'sitename' => $LJ::SITENAME }) . " p?>"; + return; + } + + if ($u->{'statusvis'} eq "D") { + $title = $ML{'error.deleted.title'}; + $body = " LJ::ljuser($u) }) . + " p?>"; + return; + } + + if ($u->{'statusvis'} eq "X") { + $title = $ML{'error.purged.title'}; + $body = " LJ::ljuser($u) }) . + " p?>"; + return; + } + } + + # redirect renamed users + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + return BML::redirect("$LJ::SITEROOT/allpics.bml?user=$u->{'renamedto'}") + if $u->{'renamedto'}; + } + + my ($can_manage, $getextra); + if ($remote) { + $can_manage = LJ::can_manage($remote, $u->{'userid'}); + $getextra = $can_manage && $remote->{'user'} ne $u->{'user'} ? "?authas=$u->{'user'}" : ''; + } + + #### show pictures + + my $info = LJ::get_userpic_info($u, {'load_comments' => 1, 'load_urls' => 1}); + + my %keywords = (); + while (my ($kw, $pic) = each %{$info->{'kw'}}) { + LJ::text_out(\$kw); + push @{$keywords{$pic->{'picid'}}}, $kw; + } + + my %comments = (); + while (my ($pic, $comment) = each %{$info->{'comment'}}) { + LJ::text_out(\$comment); + $comments{$pic} = $comment; + } + + my $piccount = 0; + + my @pics; + my $defaultpicid = $u ? $u->{'defaultpicid'} : undef; + push @pics, $info->{'pic'}->{$u->{'defaultpicid'}} if $defaultpicid; + push @pics, map { $info->{'pic'}->{$_} } sort { $a <=> $b } + grep { $_ != $defaultpicid && ($info->{'pic'}->{$_}->{'state'} eq 'N' || $can_manage) && + $info->{'pic'}->{$_}->{'state'} ne 'X' } + keys %{$info->{'pic'}}; + + foreach my $pic (@pics) { + + if ($piccount++ == 0) { + $body .= " LJ::ljuser($u)}); + if ($can_manage) { + $body .= ' ' . BML::ml('.edit2', + { 'editlink' => "$LJ::SITEROOT/editpics.bml$getextra", + 'uploadlink' => "$LJ::SITEROOT/editpics.bml$getextra#upload" }); + } + $body .= " p?>
    "; + } + + ### Keywords + my $eh_keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}||[]}); + $eh_keywords = LJ::ehtml($eh_keywords); + + if ($piccount % 2 == 1) { + $body .= ""; + } + + $body .= ""; + + if ($piccount % 2 == 1) { + $body .= ""; + } else { + $body .= "\n"; + } + } + + if ($piccount) { + if ($piccount % 2 == 1) { + # finish off this row. + # we need 2 columns: the pic and the text. + $body .= ""; + } + $body .= "
    "; + + my ($apre, $apost); + if ($pic->{'url'}) { + $apre = ""; + $apost = ""; + } + + $body .= "$apre{'userid'}' "; + $body .= "width='$pic->{'width'}' height='$pic->{'height'}' alt='' border='0'/>$apost"; + + if ($u->{'defaultpicid'} == $pic->{'picid'}) { + $body .= "$ML{'.default'}
    "; + } + + if ($can_manage && $pic->{'state'} eq 'I') { + $body .= "[$ML{'userpic.inactive'}] " . LJ::help_icon('userpic_inactive') . "
    "; + } + + if ($eh_keywords) { + $body .= "$ML{'.keywords'} $eh_keywords
    "; + } + + # Comments + my $eh_comments = $comments{$pic->{'picid'}}; + if ($eh_comments) { + LJ::CleanHTML::clean(\$eh_comments, { + 'wordlength' => 40, + 'addbreaks' => 0, + 'tablecheck' => 1, + 'mode' => 'deny', + }); + + $body .= "$eh_comments\n"; + } + + $body .= "
    "; + } else { + if ($can_manage) { + $body = " "$LJ::SITEROOT/editpics.bml$getextra#upload" }) . " p?>"; + } else { + $body = ""; + } + } + + return; +} +_code?> +head=> +body=> +page?> +link: htdocs/editpics.bml + _c?> diff --git a/livejournal/htdocs/approve.bml b/livejournal/htdocs/approve.bml new file mode 100755 index 0000000..b52ba84 --- /dev/null +++ b/livejournal/htdocs/approve.bml @@ -0,0 +1,112 @@ +1 +_info?> + +body<= +{'used'} eq 'Y'; + + my $arg = {}; + LJ::decode_url_string($aa->{'arg1'}, $arg); + + ### perform actions according to the action type + + # invite users to communities + if ($aa->{'action'} eq 'comm_invite') { + + my $dbh = LJ::get_db_writer(); + + my $targetid = $arg->{'targetid'}; + return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid; + + # add to community + if ($arg->{'member'}) { + LJ::add_friend($aa->{userid}, $targetid); + } + + # set up rels with this community + my @rels = (); + push @rels, 'A' if $arg->{'admin'}; + push @rels, 'P' if $arg->{'post'}; + push @rels, 'M' if $arg->{'moderate'}; + push @rels, 'N' if $arg->{'preapprove'}; + + if (@rels) { + LJ::set_rel_multi( map { [$aa->{userid}, $targetid, $_] } @rels ); + } + + # mark this authaction as used + $dbh->do("UPDATE authactions SET used='Y' WHERE aaid=?", undef, $aa->{'aaid'}); + + # return success + my $username = LJ::get_username($aa->{'userid'}); + return "". + 'LJ::ljuser($username, { 'type' => 'C' }), + 'aopts'=>'href="'.$LJ::SITEROOT.'/friends/add.bml?user='.$username.'"'}). + ' p?>'; + } + + # invite users to shared journals + if ($aa->{'action'} eq 'shared_invite') { + my $dbh = LJ::get_db_writer(); + + my $targetid = $arg->{'targetid'}; + return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid; + + LJ::set_rel($aa->{'userid'}, $targetid, 'P'); + + # mark this authaction as used + $dbh->do("UPDATE authactions SET used='Y' WHERE aaid=?", undef, $aa->{'aaid'}); + + my $username = LJ::get_username($aa->{'userid'}); + return "". + 'LJ::ljuser($username, { 'type' => 'S' }), + 'aopts'=>'href="'.$LJ::SITEROOT.'/friends/add.bml?user='.$username.'"'}). + ' p?>'; + } + + # approve someone joining a community + if ($aa->{action} eq 'comm_join_request') { + my $dbh = LJ::get_db_writer(); + + # get user we're adding + my $targetid = $arg->{targetid}; + return LJ::bad_input($ML{'.error.internerr.invalidaction'}) unless $targetid; + + # add to community + return "" + unless LJ::approve_pending_member($aa->{userid}, $targetid); + + # return success + my $commname = LJ::get_username($aa->{userid}); + my $username = LJ::get_username($targetid); + return "". + ' LJ::ljuser($username, { type => 'P' }), + comm => LJ::ljuser($commname, { type => 'C' }), + aopts => "href=\"$LJ::SITEROOT/community/members.bml?comm=$commname\"", + }) . ' p?>'; + } + + # not other action types right now + return LJ::bad_input($ML{'.error.unknownactiontype'}); +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/birthdays.bml b/livejournal/htdocs/birthdays.bml new file mode 100755 index 0000000..1493013 --- /dev/null +++ b/livejournal/htdocs/birthdays.bml @@ -0,0 +1,92 @@ + +body<= +" unless $remote; + + my $u; + if ($GET{user}) { + $u = LJ::load_user($GET{user}); + return BML::ml('.error.invaliduser', { user => LJ::ehtml($GET{user}) }) + unless $u; + return BML::ml('.error.badstatus', { user => LJ::ljuser($u->{user}) }) + if $u->{statusvis} ne 'V'; + } + + my $body; + my $lastmon = 0; + + $body .= ""; + $body .= "
    "; + $body .= LJ::html_text({ name => 'user', maxlength => 15, size => 15 }); + $body .= LJ::html_submit(undef, $ML{'.view'}); + $body .= "
    "; + + $body .= ' LJ::ljuser($u) }); + } else { + $body .= $ML{'.description'}; + } + $body .= ' p?>'; + + # TAG:fr:bml_birthdays:get_bdays + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare( + qq|SELECT u.user, u.name, MONTH(bdate) AS 'month', DAYOFMONTH(bdate) AS 'day' + FROM friends f, user u + WHERE f.userid = ? + AND f.friendid = u.userid + AND u.journaltype = 'P' + AND u.statusvis = 'V' + AND u.allow_infoshow = 'Y' + AND MONTH(bdate) != 0 + AND DAYOFMONTH(bdate) != 0 + LIMIT 750|); + $sth->execute($u ? $u->{userid} : $remote->{userid}); + + my @bdays; + push @bdays, $_ while $_ = $sth->fetchrow_hashref; + @bdays = sort { + ($a->{'month'} <=> $b->{'month'}) || + ($a->{'day'} <=> $b->{'day'}) || + ($a->{'user'} cmp $b->{'user'}) + } @bdays; + + foreach my $bday (@bdays) { + LJ::text_out(\$bday->{'name'}); + + if ($bday->{'month'} != $lastmon) { + if ($lastmon) { $body .= "\n"; } + $lastmon = $bday->{'month'}; + $body .= "
      \n"; + } + + my $day = sprintf("%2s", $bday->{'day'}); + $day =~ s/ / /; + + my $name = LJ::ehtml($bday->{'name'}); + $body .= "$day: " . LJ::ljuser($bday->{'user'}) . " - $name
      \n"; + } + + if (@bdays) { + $body .= "
    \n"; + } else { + $body .= ""; + } + + return $body; +} +_code?> +<=body +page?> +link: htdocs/login.bml + _c?> + diff --git a/livejournal/htdocs/captcha/audio.bml b/livejournal/htdocs/captcha/audio.bml new file mode 100755 index 0000000..c4f35fc --- /dev/null +++ b/livejournal/htdocs/captcha/audio.bml @@ -0,0 +1,35 @@ +[0] =~ m!http://!) { + Apache->request->header_out('X-REPROXY-URL', join(' ', @$wav)); + } else { + Apache->request->header_out('X-REPROXY-FILE', $wav->[0]); + } + BML::set_content_type("audio/x-wav"); + + } elsif ($wav) { + BML::set_content_type("audio/x-wav"); + return BML::noparse($wav); + } else { + return "Error: $@"; + } + +} +_code?> diff --git a/livejournal/htdocs/captcha/image.bml b/livejournal/htdocs/captcha/image.bml new file mode 100755 index 0000000..b8ee611 --- /dev/null +++ b/livejournal/htdocs/captcha/image.bml @@ -0,0 +1,34 @@ +[0] =~ m!http://!) { + Apache->request->header_out('X-REPROXY-URL', join(' ', @$png)); + } else { + Apache->request->header_out('X-REPROXY-FILE', $png->[0]); + } + BML::set_content_type("image/png"); + + } elsif ($png) { + BML::set_content_type("image/png"); + return BML::noparse($png); + } else { + return "Error: $@"; + } + +} +_code?> diff --git a/livejournal/htdocs/changepassword.bml b/livejournal/htdocs/changepassword.bml new file mode 100755 index 0000000..634a8fe --- /dev/null +++ b/livejournal/htdocs/changepassword.bml @@ -0,0 +1,165 @@ + +body<= +\n"; + $ret .= LJ::html_hidden(mode => 'submit', + ssl => $GET{'ssl'}); + + $ret .= "\n"; + $ret .= "\n"; + + my $remote = LJ::get_remote(); + + # Warn them if logged in and not validated + if (!LJ::did_post() && $remote && $remote->{'status'} ne 'A') { + $ret .= "$ML{'label.warning'} $ML{'.error.notvalidated'} warningbar?>"; + $ret .= "
    "; + } + + $ret .= "\n"; + + # we make the field for the new password *longer* than the max length + # for a password - that way we can tell if someone is trying to use an + # excessively long password, instead of silently truncating it. + + my $hval = LJ::ehtml($remote ? $remote->{'user'} : $POST{'user'}); + $ret .= "
    \n"; + $ret .= "$ML{'.oldpassword'}
    \n"; + $ret .= "
    \n"; + $ret .= "$ML{'.newpassword'}
    \n"; + $ret .= "
    \n"; + $ret .= "$ML{'.newpasswordagain'}
    \n"; + $ret .= "
    \n"; + $ret .= "standout?>\n"; + + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "standout?>\n"; + $ret .= "\n"; + return $ret; + }; + + unless (LJ::did_post()) { + $body .= $update_form->(); + } elsif ($POST{'mode'} eq 'submit') { + my $user = LJ::canonical_username($POST{'user'}); + my $password = $POST{'password'}; + my $newpass1 = LJ::trim($POST{'newpass1'}); + my $newpass2 = LJ::trim($POST{'newpass2'}); + + my $remote = LJ::get_remote(); + my $u = LJ::load_user($user); + + my @errors = (); + if ($user eq "test") { push @errors, $ML{'.error.changetestaccount'}; } + unless ($user) { + push @errors, $ML{'.error.mustenterusername'}; + } else { + unless (defined $u) { + push @errors, BML::ml('.error.invaliduser', {'user' => $user} ); + } else { + if (LJ::login_ip_banned($u)) { + push @errors, $ML{'error.ipbanned'}; + } elsif ($u->{'password'} eq "" || $u->{'password'} ne $password) { + push @errors, $ML{'.error.badoldpassword'}; + LJ::handle_bad_login($u); + } + } + } + if ($newpass1 ne $newpass2) { + push @errors, $ML{'.error.badnewpassword'}; + } else { + if ($newpass1 eq "") { + push @errors, $ML{'.error.blankpassword'}; + } elsif (length $newpass1 > 30) { + push @errors, $ML{'.error.characterlimit'}; + } else { + + my @checkpass = LJ::run_hooks("bad_password", + { 'user' => $u->{'user'}, 'password' => $newpass1, + 'name' => $u->{'name'}, 'email' => $u->{'email'} }); + if (@checkpass && $checkpass[0]->[0]) { + push @errors, BML::ml('.error.badcheck', {'error' => $checkpass[0]->[0]}); + } + } + } + + # don't allow changes if email address is not validated + unless ($u->{'status'} eq 'A') { + push @errors, $ML{'.error.notvalidated'}; + } + + unless (LJ::is_ascii($newpass1)) { + push @errors, $ML{'.error.nonascii'}; + } + + if (@errors) { + $body .= LJ::error_list(@errors); + $body .= $update_form->(); + return $body; + } + + ## make note of changed password + my $dbh = LJ::get_db_writer(); + my $oldval = Digest::MD5::md5_hex($u->{'password'} . "change"); + LJ::infohistory_add($u, 'password', $oldval); + + LJ::update_user($u, { password => $POST{'newpass1'} }); + + # Kill all sessions, forcing user to relogin + $u->kill_all_sessions; + + LJ::send_mail({ + 'to' => $u->{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => $ML{'.email.subject'}, + 'body' => BML::ml('.email.body', {'sitename'=>$LJ::SITENAME, 'siteroot'=>$LJ::SITEROOT})}); + + $body = ""; + + # if they were logged in, tell them to relogin + $body .= " "href='/login.bml'" }) . " p?>" if $remote; + + LJ::run_hooks("post_changepassword", { + "u" => $u, + "newpassword" => $POST{'newpass1'}, + "oldpassword" => $u->{'password'}, + }); + } + + return $body; +_code?> +<=body +page?> +post: htdocs/changepassword.bml +lib: Digest::MD5 +hook: post_changepassword + _c?> diff --git a/livejournal/htdocs/community/create.bml b/livejournal/htdocs/community/create.bml new file mode 100755 index 0000000..817641a --- /dev/null +++ b/livejournal/htdocs/community/create.bml @@ -0,0 +1,269 @@ + +body<= +" unless LJ::text_in(\%POST); + + my $mode = $POST{mode} || 'getinfo'; + + my $remote = LJ::get_remote(); + return "" if !$remote; + return "" + if $remote->{journaltype} ne 'P'; + return "" + unless $remote->{statusvis} eq 'V'; + + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + # fix up the incoming data (is used in getinfo mode and submit mode so it's here) + $POST{membership} = 'open' + unless $POST{membership} =~ m/^(?:open|moderated|closed)$/; + $POST{postlevel} = 'members' + unless $POST{postlevel} =~ m/^(?:members|select)$/; + $POST{nonmember_posting} = '0' + unless $POST{nonmember_posting} =~ m/^[01]$/; + $POST{moderated} = '0' + unless $POST{moderated} =~ m/^[01]$/; + + # MODE: submit - try to create an account. might change mode + # if there are errors, we'll populate $error and + # return to "getinfo" mode below + my $error; +SUBMIT: + while ($mode eq 'submit') # using while instead of if so we can 'last' out of it + { + return "$ML{'Error'}: $ML{'.error.postrequired'}" unless LJ::did_post(); + + my $user = LJ::canonical_username($POST{user}); + my $title = $POST{title} || $user; + + # reject this email? + return LJ::sysban_block(0, "Create user blocked based on email", + { new_user => $user, email => $remote->{email}, name => $user }) + if LJ::sysban_check('email', $remote->{email}); + + $error = "$ML{'error.usernamelong'}" if length($user) > 15; + $error = "$ML{'error.usernameinvalid'}" if $POST{user} && !$user; + $error = "$ML{'.error.username.mustenter'}" unless $POST{user}; + + foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { + next unless $user =~ /$re/; + + # you can give people sharedjournal priv ahead of time to create + # reserved communities: + next if LJ::check_priv($remote, "sharedjournal", $user); + + $error = "$ML{'.error.username.reserved'}"; + } + + my $u = LJ::load_user($user); + my $second_submit = 0; + if ($u) { + my $in_use = 1; + + if ($u->{email} eq $remote->{email}) { + if (LJ::login_ip_banned($u)) { + # brute-force possible going on + } else { + if ($u->{password} eq $remote->{password}) { + # oh, they double-clicked the submit button + $second_submit = 1; + + # if we found a comm and everything matches, they double hit. if + # we found a person/etc, then they tried to recreate their community, + # which isn't allowed anymore + $in_use = $u->{journaltype} eq 'C' ? 0 : 1; + } else { + LJ::handle_bad_login($u); + } + } + } + + if ($in_use) { + $error = "$ML{'.error.username.inuse'}"; + } + } + + last SUBMIT if $error; + + my $qclusterid = LJ::new_account_cluster() + 0; + die "Cluster 0 not supported" unless $qclusterid; + + my $userid = ref $u ? $u->{userid} : 0; + unless ($second_submit) { + my $dbh = LJ::get_db_writer(); + $dbh->do("INSERT INTO user (user, email, status, caps, name, clusterid, dversion, journaltype) ". + "VALUES (?, ?, ?, ?, ?, ?, $LJ::MAX_DVERSION, 'C')", + undef, $user, $remote->{email}, $remote->{status}, int($LJ::NEWUSER_CAPS), $title, $qclusterid); + if ($dbh->err) { + return "" . $dbh->errstr . " p?>"; + } + $userid = $dbh->{'mysql_insertid'}; + $dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user); + $dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid); + + # set any properties that get set in new users + $u = LJ::load_userid($userid); + while (my ($name, $val) = each %LJ::USERPROP_INIT) { + LJ::set_userprop($u, $name, $val); + } + + # since they're a community, let's do more setup + $dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES (?, ?, ?)", + undef, $userid, $POST{membership}, $POST{postlevel}); + LJ::set_userprop($u, 'nonmember_posting', $POST{nonmember_posting} + 0); + LJ::set_userprop($u, 'moderated', $POST{moderated} + 0); + LJ::set_rel($userid, $remote->{userid}, 'M') if $POST{moderated}; # moderator if moderated + LJ::set_rel($userid, $remote->{userid}, 'A'); # maintainer + LJ::join_community($remote, $u, 0, 1); # make them a member of the community + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + }); + } + + my $nu = LJ::load_userid($userid, "force"); + + # log creation + $nu->log_event('account_create', { remote => $remote }); + + # local sites may want to override what happens at this point + my $ret; + my $redirect; + my $stop_output; + LJ::run_hooks("create.bml_postsession", { + post => \%POST, + u => $nu, + type => 'community', + redirect => \$redirect, + ret => \$ret, + stop_output => \$stop_output, + }); + return BML::redirect($redirect) if $redirect; + return $ret if $stop_output; + + $ret = ""; + my $uri = LJ::journal_base($nu); + $ret .= "\n"; + $ret .= "$uri/
    standout?>\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= "

    " . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "

    "; + $ret .= "
    \n"; + + return $ret; + + } + + if ($mode eq "getinfo" || $error) + { + my $ret; + + if ($error) { + $ret .= "$ML{'.errors.label'}
      "; + $ret .= "
    • $error
    • "; + $ret .= "
    errorbar?>"; + } + + $ret .= "" unless $error; + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'submit', ssl => $FORM{'ssl'}); + + $ret .= "
      "; + + # username + my $v = LJ::ehtml($FORM{'user'}); + $ret .= "
    1. $ML{'.username.head'}
      "; + $ret .= "

      $error

      "; + $ret .= "
      " . BML::ml(".username.text", { sitename => $LJ::SITENAME }) . "
      "; + $ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style=""' }); + $ret .= "
      " . BML::ml('.person', { aopts => "href='$LJ::SITEROOT/create.bml'" }); + $ret .= "
      $ML{'.username.charsallowed'}
      " unless $error; + $ret .= "
    2. "; + + # account title + $v = LJ::ehtml($FORM{'title'}); + $ret .= "
    3. $ML{'.name.head'}
      "; + $ret .= "
      $ML{'.name.text'}
      "; + $ret .= LJ::html_text({ name => 'title', style => 'width: 60%;', maxlength => 80, value => $v, }); + $ret .= "
    4. "; + + # membership levels + $ret .= "
    5. $ML{'/community/settings.bml.label.membership'}" . + "
      $ML{'/community/settings.bml.label.whocanjoin'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen', + value => 'open', selected => ($POST{membership} eq 'open' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated', + value => 'moderated', selected => ($POST{membership} eq 'moderated' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed', + value => 'closed', selected => ($POST{membership} eq 'closed' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    6. "; + + # posting access options + $ret .= "
    7. $ML{'/community/settings.bml.label.postaccess'}" . + "
      $ML{'/community/settings.bml.label.whocanpost'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postopen', + value => 'members', selected => ($POST{postlevel} eq 'members' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'postlevel', id => 'postclosed', + value => 'select', selected => ($POST{postlevel} eq 'select' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    8. "; + + # nonmember posting options + $ret .= "
    9. $ML{'/community/settings.bml.label.nmheader'}" . + "
      $ML{'/community/settings.bml.label.nmtext'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonopen', + value => '0', selected => ($POST{nonmember_posting} eq '0' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'nonmember_posting', id => 'nonclosed', + value => '1', selected => ($POST{nonmember_posting} eq '1' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    10. "; + + # moderated options + $ret .= "
    11. $ML{'/community/settings.bml.label.modheader'}" . + "
      $ML{'/community/settings.bml.label.modtext'}

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radunmod', + value => '0', selected => ($POST{moderated} eq '0' ? 1 : 0)}); + $ret .= "

      "; + $ret .= LJ::html_check({ type => 'radio', name => 'moderated', id => 'radmod', + value => '1', selected => ($POST{moderated} eq '1' ? 1 : 0)}); + $ret .= "

      "; + $ret .= "
    12. "; + + LJ::run_hooks("create.bml_opts", { + post => \%POST, + get => \%GET, + ret => \$ret, + }); + + $ret .= "
    "; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + $ret .= "
    "; + + return $ret; + } + + return "$ML{'error.unknownmode'}: $mode"; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/community/index.bml b/livejournal/htdocs/community/index.bml new file mode 100755 index 0000000..b6fa1d9 --- /dev/null +++ b/livejournal/htdocs/community/index.bml @@ -0,0 +1,12 @@ + +body<= + +<=body +page?> +# NONE + _c?> + diff --git a/livejournal/htdocs/community/join.bml b/livejournal/htdocs/community/join.bml new file mode 100755 index 0000000..9028dc2 --- /dev/null +++ b/livejournal/htdocs/community/join.bml @@ -0,0 +1,134 @@ +"; + return; + } + + # bad statusvis? + unless ($remote->{statusvis} eq 'V') { + $body = ""; + return; + } + + # get info about the community + my $cuserid = $FORM{'cuserid'}+0; + my $cu = $FORM{comm} ? + LJ::load_user($FORM{comm}) : # they gave us the comm name + LJ::load_userid($cuserid); # they gave us the comm id + + # NOTE: we wrapped this in an eval due to code going live; the library isn't going to go + # live at the same time as the BML file, and we don't want weird things happening, so we + # verify that this is all good and return an error if it's not okay. + my $ci; + eval { $ci = LJ::get_community_row($cu); }; + if ($@) { + $body = ""; + return; + } + $cuserid = $ci->{'userid'}; + + LJ::text_out(\$ci->{'name'}); + my $ecname = LJ::ehtml($ci->{'name'}); + + # does this community even exit? + unless ($cu) { + $body .= ""; + return; + } + + # make sure a community doesn't join a community (that's confusing + # or something) + unless ($remote->{'journaltype'} eq "P") { + $body .= ""; + return; + } + + # ensure this user isn't banned + if (LJ::is_banned($remote, $cuserid)) { + $body .= ""; + return; + } + + # and make sure they're not already a member + if (LJ::is_friend($cuserid, $remote->{userid})) { + $body .= ""; + return; + } + + # get the list of maintainers and their usernames + my $dbr = LJ::get_db_reader(); + my $admins = $dbr->selectcol_arrayref("SELECT u.user FROM useridmap u, reluser r ". + "WHERE r.userid=$cuserid AND r.targetid=u.userid AND r.type='A'") || []; + my $list = "
      "; + foreach (sort @$admins) { $list .= "
    • "}; + $list .= "
    "; + + # can't join closed communities + if ($ci->{membership} eq 'closed') { + $body .= " $list }) . + " p?>"; + return; + } + + # now do the join + if ($POST{confirm}) { + # can members join this community openly? + if ($ci->{membership} ne 'open') { + # hit up the maintainers to let them know a join was requested + LJ::comm_join_request($cu, $remote); + $body .= ""; + return; + } + + # make remote user a friend of the community + LJ::join_community($remote, $cu, $FORM{addfriend}); + + # success message + $body .= " $ci->{user}, commname => $ecname}) . " p?>"; + + # if community permits it, tell the user they have access + if ($ci->{postlevel} eq "members") { + $body .= ""; + } else { + $body .= " $list }) . " p?>"; + } + } else { + if ($ci->{membership} ne 'open') { + $body .= " LJ::ljuser($cu) }) . "
    p?>"; + $body .= "
    "; + $body .= ""; + $body .= ""; + $body .= "
    "; + return; + } + + $body .= " $ecname }); + $body .= "
    "; + $body .= ""; + $body .= "
    "; + $body .= ""; + $body .= BML::ml('.label.addtofriends', { maintainer => $ecname }); + $body .= "
    p?>"; + } + + return; + +_code?> +body=> +page?> +link: htdocs/login.bml, htdocs/userinfo.bml +post: htdocs/community/join.bml + _c?> + diff --git a/livejournal/htdocs/community/leave.bml b/livejournal/htdocs/community/leave.bml new file mode 100755 index 0000000..928b49e --- /dev/null +++ b/livejournal/htdocs/community/leave.bml @@ -0,0 +1,68 @@ +"; + return; + }; + + my $remote = LJ::get_remote(); + return $error->($ML{'.label.logoutfirst'}) unless $remote; + + # get info about the community + my $cuserid = $FORM{'cuserid'}+0; + my $cu = $FORM{comm} ? + LJ::load_user($FORM{comm}) : # they gave us the comm name + LJ::load_userid($cuserid); # they gave us the comm id + + # error check + return $error->($ML{'.label.infoerror'}) + unless $cu && $cu->{journaltype} =~ /[CS]/; + + # used in both paths below + my $ecname = LJ::ehtml($cu->{'name'}); + + if ($FORM{confirm}) { + # get current list of maintainers to make sure the last one doesn't leave + my $maintids = LJ::load_rel_user($cu->{userid}, 'A'); + return $error->($ML{'error.nodb'}) unless ref $maintids eq 'ARRAY'; + + # error if we're a maintainer and there are no others + my $ismaint = grep { $_ == $remote->{userid} } @$maintids; + my $othermaints = grep { $_ != $remote->{userid} } @$maintids; + return $error->($ML{'.label.lastmaintainer'}) if $ismaint && !$othermaints; + + # remove user from community's friends list + LJ::leave_community($remote, $cu, $FORM{removefriend}); + + # success message + $body .= " $cu->{user}, commname => $ecname }) . + " p?>"; + } else { + # show a confirmation form + $body .= " $ecname }) . " p?>"; + $body .= '
    '; + $body .= LJ::html_hidden("cuserid", $cu->{userid}, "confirm", 1) . "

    "; + $body .= LJ::html_check({ name => 'removefriend', selected => 1, value => 1 }) . " "; + $body .= BML::ml('.label.removefromfriends', { user => $ecname }); + $body .= '

    ' . LJ::html_submit(undef, $ML{'.button.leave'}) . '

    '; + } + + return; +} +_code?> +body=> +page?> +link: htdocs/login.bml, htdocs/userinfo.bml +post: htdocs/community/leave.bml + _c?> + diff --git a/livejournal/htdocs/community/manage.bml b/livejournal/htdocs/community/manage.bml new file mode 100755 index 0000000..06d3969 --- /dev/null +++ b/livejournal/htdocs/community/manage.bml @@ -0,0 +1,189 @@ + +body<= +"; + } + + return "" + unless $remote->{journaltype} eq 'P'; + + $ret .= ""; + $ret .= "
    "; + + my %show; + + # what communities does remote + my $cids = LJ::load_rel_target($remote, 'A'); + my %admin; + if ($cids) { foreach (@$cids) { $admin{$_} = $show{$_} = 1; } } + + # keep track of what communities remote moderates + my $mods = LJ::load_rel_target($remote, 'M'); + my %mods; + my %modcount; + if ($mods) { foreach (@$mods) { $mods{$_} = $show{$_} = 1; } } + + my %names = (); + my %pending = (); + if (%show) { + my $in = join(',', keys %show); + my $us = LJ::load_userids(keys %show); + + my $sth = $dbr->prepare("SELECT userid, membership FROM community ". + "WHERE userid IN ($in)"); + $sth->execute; + my $udbr; + while (my ($uid, $membership) = $sth->fetchrow_array) { + my $cu = $us->{$uid}; + next unless $cu && $cu->{statusvis} eq "V"; + $names{$uid} = [ $cu->{user}, $cu->{name}, -1 ]; + if ($mods{$uid}) { + $udbr = LJ::get_cluster_reader($cu); + my $sql = "SELECT COUNT(*) FROM modlog WHERE journalid=$uid"; + $modcount{$uid} = $names{$uid}[2] = $udbr->selectrow_array($sql) || 0; + } + if ($membership eq 'moderated') { + my $ids = LJ::get_pending_members($uid) || []; + $pending{$uid} = scalar @$ids; + } + } + } + + # deleted and expunged communities won't show up in this + if (%names) { + + # Make up the first table row, linking to the other sort methods + my @snames; + $ret .= ""; + + if (!defined $GET{'sortby'} || $GET{'sortby'} eq 'username') { + $ret .= ""; + @snames = sort { $names{$a}->[0] cmp $names{$b}->[0] } keys %names; + } else { + $ret .= ""; + } + + if ($GET{'sortby'} eq 'title') { + $ret .= ""; + @snames = sort { $names{$a}->[1] cmp $names{$b}->[1] } keys %names; + } else { + $ret .= ""; + } + + $ret .= ""; + + if ($GET{'sortby'} eq 'mod') { + $ret .= ""; + @snames = sort { $names{$b}->[2] <=> $names{$a}->[2] } keys %names; + } elsif (@$mods) { + $ret .= ""; + } + + foreach my $id (@snames) { + my $user = $names{$id}->[0]; + my $name = $names{$id}->[1]; + $ret .= ""; + } + $ret .= "
    $ML{'.commlist.username'} 'username'}) . "'>$ML{'.commlist.username'}$ML{'.commlist.title'} 'title'}) . "'>$ML{'.commlist.title'}$ML{'.commlist.actions'}$ML{'.commlist.moderation'} 'mod'}) . "'>$ML{'.commlist.moderation'}
    " . LJ::eall($name) . ""; + if ($admin{$id}) { + $ret .= BML::ml('Actionlink', { + 'link'=>"$ML{'.commlist.actinfo'}"}) . "  "; + $ret .= BML::ml('Actionlink', { + 'link'=>"$ML{'.commlist.actsettings2'}"}) . "  "; + $ret .= BML::ml('Actionlink', { + 'link'=>"$ML{'.commlist.actinvites'}"}) . "  "; + my $pend = $pending{$id} ? BML::ml('.commlist.actpending', { num => $pending{$id}, + aopts => "href=\"/community/pending.bml?comm=$user\"" }) : ''; + $ret .= BML::ml('Actionlink', { + 'link'=>"$ML{'.commlist.actmembers2'}$pend"}) . "  "; + } + $ret .= ""; + if ($mods{$id}) { + my $num = $modcount{$id} || "0"; # relying on this to be -wrapped + $ret .= BML::ml('.commlist.moderation.num', { num => $num, + link => "/community/moderate.bml?comm=$user" }); + } + $ret .= "
    "; + } else { + $ret .= "$ML{'.commlist.none'}"; + } + + $ret .= "
    "; + + # save any changes + if (LJ::did_post()) { + my $op = $POST{email}; + $op = '' if $op && $op !~ /[N]/; # add D back in here when Digest goes live + LJ::set_userprop($remote, 'opt_communityjoinemail', $op); + + my $mod_emails = $POST{modemail} ? 1 : 0; + LJ::set_userprop($remote, 'opt_nomodemail', $mod_emails ? undef : 1); + } + + # load up our userprop + LJ::load_user_props($remote, 'opt_communityjoinemail', 'opt_nomodemail'); + my $op = $remote->{opt_communityjoinemail}; + $op ||= 'Y'; + my $mod_emails = $remote->{opt_nomodemail} ? 0 : 1; + + # form for setting email option + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + $ret .= "
    "; + $ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_all', + value => '', selected => ($op eq 'Y') }); + $ret .= "
    "; + if (0) { + # we don't do this right now, because the maintenance job to send email isn't + # ready for use on LJ. this will be removed and the option enabled when that + # task is rewritten. NOTE: add D up above in did_post() block. + $ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_digest', + value => 'D', selected => ($op eq 'D') }); + $ret .= "
    "; + } + $ret .= LJ::html_check({ type => 'radio', name => 'email', id => 'email_none', + value => 'N', selected => ($op eq 'N') }); + $ret .= "
    "; + $ret .= "
    "; + + # options for getting moderation emails + $ret .= ""; + $ret .= "
    "; + + $ret .= LJ::html_check({ type => 'radio', name => 'modemail', id => 'modemail_yes', + value => '1', selected => $mod_emails }); + $ret .= "
    "; + + $ret .= LJ::html_check({ type => 'radio', name => 'modemail', id => 'modemail_no', + value => '0', selected => !$mod_emails }); + $ret .= "
    "; + $ret .= "
    "; + + $ret .= ""; + $ret .= "'/community/create.bml'}) . " p?>"; + + return $ret; + +_code?> + +<=body +page?> + diff --git a/livejournal/htdocs/community/members.bml b/livejournal/htdocs/community/members.bml new file mode 100755 index 0000000..d527c57 --- /dev/null +++ b/livejournal/htdocs/community/members.bml @@ -0,0 +1,455 @@ + +body<= + '/community/manage.bml', + 'text' => $ML{'.manage2'}, + }); + + # get remote + my $remote = LJ::get_remote(); + unless ($remote) { + $ret .= ""; + return $ret; + } + + my $cname = $GET{'comm'}; + return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname; + + # get $c object + my $c = LJ::load_user($cname); + unless ($c) { + $ret .= ""; + return $ret; + } + my $cid = $c->{'userid'}; + + # is $remote an admin? + unless (LJ::can_manage_other($remote, $c)) { + $ret .= " LJ::ljuser($cname, { 'type' => 'C' }) }); + $ret .= " p?>"; + return $ret; + } + + my @allattribs = ('member', 'post', 'preapprove', 'moderate', 'admin'); + my %attrshort = ( X => 'member', P => 'post', N => 'preapprove', M => 'moderate', A => 'admin'); + my %attrshort_r = ( map { $attrshort{$_} => $_ } keys %attrshort ); # reversed + + # saving a form submission + if ($POST{'action:update'}) { + # validate form auth + return "" + unless LJ::check_form_auth(); + + my @userids = split(',', $POST{'ids'}); + my @saveattribs = split(',', $POST{'attribs'}); + + # now we need to create our 'was' list + my %was; # ( userid => { attrib => 1; } ) + my %users; # ( userid => username ) + foreach my $row (split ';', $POST{was}) { # UID:UNAME:MNPX;UID:UNAME:MX;UID:UNAME:AM + # if this row matches... + if ($row =~ /^(\d+):(\w+):(\w+)$/) { + my ($uid, $name, $attrs) = ($1, $2, $3); + $uid += 0; + next unless $uid && $name && $attrs; + + # split attrs and setup + $was{$uid}->{$attrshort{$_}} = 1 foreach split '', $attrs; + $users{$uid} = $name; + } + } + + # invite new users + my @to_add; + my @add_errors; + foreach my $num (1..5) { + $POST{"add_$num"} = LJ::trim($POST{"add_$num"}); + next unless $POST{"add_$num"} =~ /^\w+$/; + + my $target = LJ::load_user($POST{"add_$num"}); + unless ($target) { + push @add_errors, BML::ml('.error.nouser', + { 'user' => $POST{"add_$num"} }); + next; + } + + unless ($target->{statusvis} eq 'V') { + push @add_errors, BML::ml('.error.notactive', + { 'user' => LJ::ljuser($POST{"add_$num"}) }); + next; + } + + my @attr = grep { defined $POST{"add_${num}_$_"} } @saveattribs; + unless (@attr) { + push @add_errors, BML::ml('.error.noattr', + { 'user' => LJ::ljuser($POST{"add_$num"}, + { 'type' => $target->{'journaltype'} }) }); + next; + } + + unless ($target->{'journaltype'} eq 'P') { + push @add_errors, BML::ml('.error.invaliduser', + { 'user' => LJ::ljuser($POST{"add_$num"}, + { 'type' => $target->{'journaltype'} }) }); + next; + } + + if (grep { $target->{'userid'} == $_ } @userids) { + push @add_errors, BML::ml('.error.alreadyadded', + { 'user' => LJ::ljuser($POST{"add_$num"}, + { 'type' => $target->{'journaltype'} }) }); + next; + } + + # insert authactions row + push @to_add, [ $target, \@attr ]; + } + return LJ::bad_input(@add_errors) if @add_errors; + + # now do the additions if any were needed + my @fail; + my @invited; + if (@to_add) { + foreach my $row (@to_add) { + # good, let's extend an invite to this person + my ($target, $attrs) = @$row; + if (LJ::send_comm_invite($target, $c, $remote, $attrs)) { + push @invited, $row; + } else { + push @fail, [ $target, LJ::last_error_code() ]; + } + } + } + if (@fail) { + my @bad; + foreach (@fail) { + if ($_->[1] eq 'comm_user_has_banned') { + push @bad, BML::ml('.error.adding', { user => LJ::ljuser($_->[0], { type => 'P' }) }); + } elsif ($_->[1] eq 'comm_invite_limit') { + push @bad, BML::ml('.error.limit', { user => LJ::ljuser($_->[0], { type => 'P' }) }); + } else { + push @bad, BML::ml('.error.unknown', { user => LJ::ljuser($_->[0], { type => 'P' }) }); + } + } + return LJ::bad_input(@bad); + } + + # initialize lists of users to update and delete + # keyed on attribute type + my %add = (); + my %delete = (); + foreach (@allattribs) { + $add{$_} = {}; + $delete{$_} = {}; + } + + # need a db handle now + my $dbh = LJ::get_db_writer(); + + # if we have $other_maints, then there are maintainers not in our + # current view, so they will not be modified, so the user can delete + # all maintainers from the current view + my $in = join(',', map { $dbh->quote($_) } @userids); + my $other_maints = $dbh->selectrow_array("SELECT COUNT(*) FROM reluser " . + "WHERE userid=? AND type='A' " . + "AND targetid NOT IN ($in)", + undef, $cid); + + # users already in community + my $maints = 0; + my (%addr, %delr); # store additions and removals sorted by userid + foreach my $id (@userids) { + $id = $id + 0; + my $str; + foreach (@allattribs) { + if ($POST{"edit_${id}_$_"}) { + unless ($was{$id}->{$_}) { + $add{$_}->{$id} = 1; + $addr{$id}->{$_} = 1; + } + } else { + if ($was{$id}->{$_}) { + $delete{$_}->{$id} = 1; + $delr{$id}->{$_} = 1; + } + } + } + $maints++ if $POST{"edit_${id}_admin"}; + } + + # can't remove ALL maintainers, give them an error so they can + # go back and decide who to keep + if (! $other_maints && $maints < 1) { + $ret .= " 'C' }) . + ", must have at least one maintainer. " . + "Please " . + "go back and add a maintainer. p?>"; + return $ret; + } + + # delete members + if (%{$delete{'member'}}) { + # TAG:FR:bml_comm_members:del_members + LJ::remove_friend($cid, [ keys %{$delete{'member'}} ]); + } + + # log maintainer deletions + foreach my $uid (keys %{$delete{admin} || {}}) { + $c->log_event('maintainer_remove', { actiontarget => $uid, remote => $remote }); + } + + # delete other rel edges + LJ::clear_rel_multi( + (map { [$cid, $_, 'A'] } keys %{$delete{admin} || {}}), + (map { [$cid, $_, 'P'] } keys %{$delete{post} || {}}), + (map { [$cid, $_, 'M'] } keys %{$delete{moderate} || {}}), + (map { [$cid, $_, 'N'] } keys %{$delete{preapprove} || {}}), + ); + + # perform additions + my @msgs; + if (%{$add{'member'}}) { + foreach my $id (keys %{$add{'member'}}) { + next if $was{$id}->{'member'}; + my $u = LJ::load_userid($id); + if (LJ::u_equals($u, $remote)) { + # you're allowed to add yourself as member + LJ::join_community($remote, $c); + } else { + if (LJ::send_comm_invite($u, $c, $remote, [ 'member' ])) { + # if it succeeded, push the reinvited information + push @msgs, BML::ml('.reinvited2', + { user => LJ::ljuser($u, { type => 'P' }), + aopts => "href='$LJ::SITEROOT/manage/invites.bml'" }); + } + } + } + } + + # log maintainer additions + foreach my $uid (keys %{$add{admin} || {}}) { + $c->log_event('maintainer_add', { actiontarget => $uid, remote => $remote }); + } + + # set rels in db/memcache + LJ::set_rel_multi( (map { [$cid, $_, 'A'] } keys %{$add{admin} || {}}), + (map { [$cid, $_, 'P'] } keys %{$add{post} || {}}), + (map { [$cid, $_, 'M'] } keys %{$add{moderate} || {}}), + (map { [$cid, $_, 'N'] } keys %{$add{preapprove} || {}}), + ); + + # create some other messages + my %done; # keep track of who we've done + foreach my $id (keys %addr, keys %delr) { + next if $done{$id}++; + + my ($str, @astr, @dstr); + push @astr, $ML{"/manage/invites.bml.label.$_"} + foreach keys %{$addr{$id} || {}}; + push @dstr, $ML{"/manage/invites.bml.label.$_"} + foreach keys %{$delr{$id} || {}}; + $str .= "
  • " . BML::ml('.success.added', { list => join(', ', @astr) }) . "
  • \n" if @astr; + $str .= "
  • " . BML::ml('.success.deleted', { list => join(', ', @dstr) }) . "
  • \n" if @dstr; + push @msgs, LJ::ljuser($users{$id}, { type => 'P' }) . ":
      $str
    " if $str; + } + + $ret .= ""; + if (@msgs) { + $ret .= "\n
      "; + $ret .= "
    • $_
    • \n" foreach @msgs; + $ret .= "
    "; + } + if (@invited) { + $ret .= " "href='$LJ::SITEROOT/manage/invites.bml'" }); + $ret .= " p?>
      "; + foreach my $row (@invited) { + $ret .= "
    • " . LJ::ljuser($row->[0], { type => 'P' }) . ": "; + $ret .= "$ML{\"/manage/invites.bml.label.$_\"}, " foreach @{$row->[1] || []}; + chop $ret; chop $ret; + $ret .= "
    • \n"; + } + $ret .= "
    "; + } + $ret .= "" unless @msgs || @invited; + $ret .= " BML::get_uri() . "?comm=$cname" }) . " p?>"; + + return $ret; + + } + + # browsing mode + + # now get lists of: members, admins, able to post, moderators + my %users = (); + + # need a dbr now + my $dbr = LJ::get_db_reader(); + + # get community members + # TAG:FR:bml_comm_members:get_members + my $sth = $dbr->prepare("SELECT u.userid, u.user FROM useridmap u, friends f " . + "WHERE u.userid=f.friendid AND f.userid=?"); + $sth->execute($cid); + + while (my ($id, $user) = $sth->fetchrow_array) { + $users{$id}->{'userid'} = $id; + $users{$id}->{'name'} = $user; + $users{$id}->{'member'} = 1; + } + + my $sth = $dbr->prepare("SELECT r.targetid, r.type, u.user FROM reluser r, useridmap u " . + "WHERE r.targetid = u.userid AND r.userid=? AND r.type IN ('A','P','M','N')"); + $sth->execute($cid); + + my %count; + while (my ($id, $type, $user) = $sth->fetchrow_array) { + $users{$id}->{'userid'} = $id; + $users{$id}->{'name'} = $user; + my $key = {'A'=>'admin','P'=>'post','M'=>'moderate','N'=>'preapprove'}->{$type}; + $users{$id}->{$key} = 1; + $count{$type}++; + } + + # columns of our table, excluding username + my @attribs = ('member', 'post'); + LJ::load_user_props($c, 'moderated'); + push @attribs, ('preapprove') + if $c->{'moderated'} || $count{'N'}; + push @attribs, ('moderate') + if $c->{'moderated'} || $count{'M'}; + push @attribs, 'admin'; + + # sorting method; + my $method = $GET{'sort'}; + + my $cmp = sub {$a->{'name'} cmp $b->{'name'}}; + $cmp = sub {$b->{'member'} <=> $a->{'member'}} if $method eq 'member'; + $cmp = sub {$b->{'admin'} <=> $a->{'admin'}} if $method eq 'admin'; + $cmp = sub {$b->{'post'} <=> $a->{'post'}} if $method eq 'post'; + $cmp = sub {$b->{'moderate'} <=> $a->{'moderate'}} if $method eq 'moderate'; + $cmp = sub {$b->{'preapprove'} <=> $a->{'preapprove'}} if $method eq 'preapprove'; + + my @users = sort $cmp values %users; + my $page_size = 100; # change to adjust page size + + # are we going to jump to a specific user ? + my $jumppage; + my $jumpuser; + if (@users > $page_size && $POST{'jumpto'} =~ /^\w+$/) { + my $ct; + foreach (@users) { + $jumppage++ if $ct % $page_size == 0; + if ($POST{'jumpto'} eq $_->{'name'}) { + $jumpuser = $_->{'name'}; + last; + } + $ct++; + } + undef $jumppage unless $jumpuser; + } + + # how to make links back to this page + my $self_link = sub { + my $sort = "&sort=$GET{'sort'}" if $GET{'sort'}; + return "members.bml?comm=$cname&page=$_[0]$sort"; + }; + + my %items = BML::paging(\@users, $jumppage || $GET{'page'}, $page_size); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}, + { 'self_link' => $self_link }); + @users = @{$items{'items'}}; + + # output starts here + $ret .= " LJ::ljuser($cname, { 'type' => 'C' }) }); + $ret .= " " . BML::ml('.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>"; + + $ret .= "
    "; + $ret .= LJ::form_auth(); + + # jump to user + if ($items{'pages'} > 1) { + $ret .= "
    Jump to user: "; + $ret .= LJ::html_text({ 'name' => 'jumpto', 'value' => $POST{'jumpto'}, + 'size' => '10', 'maxlength' => '15' }) . " "; + $ret .= LJ::html_submit(undef, 'Go') . "
    "; + + $ret .= $navbar; + } + + my $sortlink = BML::get_uri() . "?comm=$cname&sort="; + $ret .= "
    \n" . + ""; + $ret .= "" for (@attribs); + $ret .= "\n"; + + # rows for existing users + my $rc = 0; + my @wstrs; + foreach(@users) { + my $rstyle = ($rc++ & 1) ? "" : ""; + $ret .= ""; + my $wstr; + foreach my $key (@attribs) { + $ret .= ""; + } + push @wstrs, "$_->{userid}:$_->{name}:$wstr" if $wstr; + $ret .= "\n"; + } + + # if on the last page, let users add to the list + if ($items{'page'} == $items{'pages'}) { + foreach(1..5) { + my $rstyle = ($rc++ & 1) ? "" : ""; + $ret .= ""; + foreach my $key (@attribs) { + $ret .= ""; + } + $ret .= "\n"; + } + } + + # some hidden values + $ret .= "
    $ML{'.key.user'}".$ML{".key.$_"}."
    " . LJ::ljuser($_->{'name'}) . ""; + $ret .= LJ::html_check({ 'name' => "edit_$_->{'userid'}_$key", + 'selected' => $_->{$key} }); + $wstr .= $attrshort_r{$key} if $_->{$key}; + $ret .= "
    "; + $ret .= LJ::html_text({ 'name' => "add_$_", 'size' => '10', 'maxlength' => '15' }) . ""; + if ($key eq 'member' || $key eq 'post') { + $ret .= LJ::html_check({ name => "add_${_}_$key", selected => 1, }); + } else { + $ret .= LJ::html_check({ name => "add_${_}_$key" }); + } + $ret .= "
    "; + $ret .= LJ::html_hidden('ids', join(',', map { $_->{'userid'}} @users), + 'attribs', join(',', @attribs), + 'was', join(';', @wstrs)) . "\n"; + + $ret .= "

    " . LJ::html_submit('action:update', $ML{'.update'}) . "

    \n"; + $ret .= "
    \n\n"; + + $ret .= $navbar; + + return $ret; + +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/community/moderate.bml b/livejournal/htdocs/community/moderate.bml new file mode 100755 index 0000000..84467fd --- /dev/null +++ b/livejournal/htdocs/community/moderate.bml @@ -0,0 +1,425 @@ + +body<= +"; + return $ret; + } + + my $mode = $POST{'mode'}; + my ($saved_comm, $saved_modid) = ("", 0); + + if (LJ::did_post() && ($mode eq 'approve_do' || $mode eq 'reject_do')) { + my $cid = $POST{'cid'}+0; + my $modid = $POST{'modid'}+0; + + my $c = LJ::load_userid($cid); + unless ($c) { + $ret .= ""; + return $ret; + } + my $dbcm = LJ::get_cluster_master($c); + + unless (LJ::check_rel($c, $remote, 'M')) { + $ret .= ""{'user'} ljcomm?>"}) . " p?>"; + return $ret; + } + # use dbcm to read to minimize collisions between moderators due to replication lag + my $entry = $dbcm->selectrow_hashref("SELECT * FROM modlog WHERE journalid=? AND modid=?", + undef, $c->{'userid'}, $modid); + my $frozen = $dbcm->selectrow_array("SELECT request_stor FROM modblob WHERE journalid=? AND modid=?", + undef, $c->{'userid'}, $modid); + + my $req = Storable::thaw($frozen) if $frozen; + unless ($frozen && $entry && $req->{'_moderate'}->{'authcode'} && $req->{'_moderate'}->{'authcode'} eq $POST{'auth'}) { + $ret .= ""; + return $ret; + } + + my $poster = LJ::load_userid($entry->{'posterid'}); + my ($success, $do_mail) = (0, 0); + my $why_mail; + my $prot_err; + my $posturl; + + if ($mode eq 'approve_do') { + my $res = LJ::Protocol::do_request('postevent', $req, \$prot_err, {'nomod'=>1, 'noauth'=>1}); + if ($res) { # succeeded + $success = 1; + $ret .= ""; + # does the poster want to know? if they have working email and notification on + ($do_mail, $why_mail) = (1, 'success') + if ($poster->{'opt_gettalkemail'} eq "Y" && $poster->{'status'} eq "A"); + $posturl = LJ::item_link($c, $res->{'itemid'}, $res->{'anum'}) . "\n\n"; + } else { + $prot_err = LJ::Protocol::error_message($prot_err) if $prot_err; + $ret .= ""$prot_err"}) . " p?>"; + ($do_mail, $why_mail) = (1, 'proterror') + if $poster->{'status'} eq "A"; + } + if ($POST{'preapprove'}) { + LJ::set_rel($c, $poster, 'N'); + $ret .= ""{'user'} ljuser?>"}) . " p?>"; + } + } + if ($mode eq 'reject_do') { + $success = 1; + $ret .= ""; + ($do_mail, $why_mail) = (1, 'reject') + if $poster->{'status'} eq 'A'; + } + + $do_mail = 1 unless $poster->{'statusvis'} eq 'V'; + + # mail the poster + if ($do_mail) { + my $subject="Moderated submission notification"; + my $to = $poster->{'email'}; + my $body = "Your message submitted to the moderated community $c->{'user'} "; + if ($why_mail eq 'success') { + $body .= "has been approved and successfully posted.\n\n$posturl"; + } elsif ($why_mail eq 'proterror') { + $body .= "has been approved, but failed to be posted due to the following protocol error:\n$prot_err\n\n"; + } elsif ($why_mail eq 'reject') { + $body .= "has been rejected by a moderator of that community.\n\nPlease note that replies to this email are not sent to the community's moderator(s). If you would like to discuss the reasons for your entry's rejection, you will need to contact a moderator directly.\n\n"; + } + if ($why_mail eq 'reject' && $POST{'why'}) { + $body .= "Here are the reasons for the rejection as provided by the moderator: \n\n" . $POST{'why'} . "\n\n"; + } + unless ($why_mail eq 'success') { + $body .= "This is the message you submitted:\n\n"; + my $etime = sprintf("%04d-%02d-%02d %02d:%02d", + $req->{'year'}, $req->{'mon'}, + $req->{'day'}, $req->{'hour'}, + $req->{'min'}); + $body .= "Time: $etime\n"; + $body .= "Subject: " . $req->{'subject'} . "\n"; + if ($req->{'props'}->{'current_music'}) { + $body .= "Current Music: " . $req->{'props'}->{'current_music'} . "\n"; + } + if ($req->{'props'}->{'current_mood'}) { + $body .= "Current Mood: " . $req->{'props'}->{'current_mood'} . "\n"; + } + if ($req->{'props'}->{'picture_keyword'}) { + $body .= "Picture Keyword: " . $req->{'props'}->{'picture_keyword'} . "\n"; + } + $body .= "Text:\n" . $req->{'event'} . "\n\n"; + $body .= "Regards,\n$LJ::SITENAME Team\n\n$LJ::SITEROOT/\n"; + } + LJ::send_mail({ + 'to' => $to, + 'from' => $LJ::BOGUS_EMAIL, + 'charset' => 'utf-8', + 'subject' => $subject, + 'body' => $body, + }); + } + + if ($success) { + $saved_comm = $c->{'user'}; + $saved_modid = 0; + + # Delete this moderated entry from the list + $c->do("DELETE FROM modlog WHERE journalid=? AND modid=?", + undef, $c->{'userid'}, $modid); + $c->do("DELETE FROM modblob WHERE journalid=? AND modid=?", + undef, $c->{'userid'}, $modid); + + # FALL THROUGH to showing the list of entries in this community + } else { + $ret .= "

    "; + $ret .= BML::ml('Backlink', { + 'link'=>'/community/manage.bml', + 'text'=>$ML{'.manage'}, + }) . "
    "; + $ret .= BML::ml('Backlink', { + 'link'=>"/community/moderate.bml?comm=$c->{'user'}", + 'text'=>$ML{'.moderate'}, + }) . "
    "; + $ret .= "

    "; + return $ret; + } + } + + my $comm = $saved_comm || ($mode eq 'action' ? $POST{'comm'} : $GET{'comm'}); + my $modid = $saved_modid || ($mode eq 'action' ? $POST{'modid'} : $GET{'modid'}); + $modid += 0; + + # redirect to community/manage if a GET request with no arg + return BML::redirect("manage.bml") unless $comm; + + my $c = LJ::load_user($comm); + unless ($c) { + $ret .= ""; + return $ret; + } + my $dbcr = LJ::get_cluster_def_reader($c); + + unless (LJ::check_rel($c, $remote, 'M')) { + $ret .= """}) . " p?>"; + return $ret; + } + + if ($mode eq 'action' && $POST{'action:approve'}) { + my ($posterid, $frreq); + if ($modid) { + ($posterid, $frreq) = $dbcr->selectrow_array + ("SELECT l.posterid, b.request_stor FROM modlog l, modblob b " . + "WHERE l.journalid=? AND l.modid=? AND l.journalid=b.journalid AND l.modid=b.modid", + undef, $c->{'userid'}, $modid); + } + unless ($posterid) { + $ret .= ""; + return $ret; + } + my $req = Storable::thaw($frreq); + my $poster = LJ::load_userid($posterid); + $ret .= ""; + $ret .= "

    "; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "{'authcode'} . "'>"; + $ret .= ""; + $ret .= "
    "; + $ret .= "

    " . + BML::ml('.approve.preapprove', {'user'=>"{'user'} ljuser?>"}); + $ret .= "

    "; + return $ret; + } + + if ($mode eq 'action' && $POST{'action:reject'}) { + my ($posterid, $frreq); + if ($modid) { + ($posterid, $frreq) = $dbcr->selectrow_array + ("SELECT l.posterid, b.request_stor FROM modlog l, modblob b " . + "WHERE l.journalid=? AND l.modid=? AND l.journalid=b.journalid AND l.modid=b.modid", + undef, $c->{'userid'}, $modid); + } + unless ($posterid) { + $ret .= ""; + return $ret; + } + my $req = Storable::thaw($frreq); + my $poster = LJ::load_userid($posterid); + $ret .= ""; + $ret .= "

    "; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "{'authcode'} . "'>"; + $ret .= ""; + $ret .= "
    "; + if ($poster->{'status'} eq 'A') { + $ret .= ""; + $ret .= " p?>"; + } + $ret .= "
    "; + return $ret; + } + + # browse either the list of entries or an entry + unless ($modid) { + # present a list of entries + $ret .= """}) . " p?>"; + $ret .= "
    "; + my @entries; + my $sth = $dbcr->prepare("SELECT * FROM modlog WHERE journalid=$c->{'userid'}"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + push @entries, $_; + } + unless (@entries) { + $ret .= "$ML{'.browse.empty'}"; + } else { + $ret .= "" . + "" . + ""; + + my %users; + LJ::load_userids_multiple([ map { $_->{'posterid'}, \$users{$_->{'posterid'}} } @entries ]); + foreach (sort { $a->{'logtime'} lt $b->{'logtime'} } @entries) { + my $link = "/community/moderate.bml?comm=$comm&modid=" . $_->{'modid'}; + my $subject = $_->{'subject'} ? LJ::eall($_->{'subject'}) : "[No Subject]"; + $ret .= "" . + "" . + "" . + ""; + } + $ret .= "
    $ML{'.brlist.time'}$ML{'.brlist.poster'}$ML{'.brlist.subject'}$ML{'.brlist.actions'}
    $_->{'logtime'}{'posterid'}}->{'user'} . " ljuser?>$subject" . + BML::ml('Actionlink', { + 'link'=>"$ML{'.brlist.view'}" + }) . "
    "; + } + $ret .= "
    "; + $ret .= BML::ml('Backlink', { + 'link'=>'/community/manage.bml', + 'text'=>$ML{'.manage'}, + }) . "
    "; + + } else { + # view an entry + my $frozen = $dbcr->selectrow_array("SELECT request_stor FROM modblob WHERE journalid=? AND modid=?", + undef, $c->{'userid'}, $modid); + unless ($frozen) { + $ret .= ""; + return $ret; + } + my $req = Storable::thaw($frozen); + + # cleaning + my $event = $req->{'event'}; + $event =~ s/^\s+//; + $event =~ s/\s+$//; + if ($req->{'lineendings'} eq "mac") { + $event =~ s/\r/\n/g; + } else { + $event =~ s/\r//g; + } + my $etime = sprintf("%04d-%02d-%02d %02d:%02d", + $req->{'year'}, $req->{'mon'}, + $req->{'day'}, $req->{'hour'}, + $req->{'min'}); + my $subject = $req->{'subject'}; + my $props = $req->{'props'}; + my $up = LJ::load_user($req->{'username'}); + my $posterid = $up->{'userid'}; + my $error; + my @polls = LJ::Poll::parse(\$event, \$error, { + 'journalid' => $c->{'userid'}, + 'posterid' => $posterid, + }); + $event =~ s//LJ::Poll::preview(shift @polls);/eg; + LJ::CleanHTML::clean_event(\$event, {'preformatted' => $req->{'props'}->{'opt_preformatted'}, + 'cutpreview' => 1, + 'cuturl' => '#', + }); + BML::ebml(\$event); + + $ret .= "

    "; + $ret .= BML::ml('Backlink', { + 'link'=>'/community/manage.bml', + 'text'=>$ML{'.manage'}, + }) . "
    "; + $ret .= BML::ml('Backlink', { + 'link'=>"/community/moderate.bml?comm=$comm", + 'text'=>$ML{'.moderate'}, + }) . "
    "; + $ret .= "

    "; + + $ret .= "

    "; + $ret .= ""; + + my $picid = LJ::get_picid_from_keyword($up, $props->{'picture_keyword'}); + + my %userpics; + if ($picid) { + LJ::load_userpics(\%userpics, [ $up, $picid ]); + my $alt = $up->{'name'}; + if ($props->{'picture_keyword'}) { + $alt .= ": $props->{'picture_keyword'}"; + } + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
    "; + $ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => BML::eall($up->{'name'}), + 'userlink' => LJ::ljuser($up->{'user'}), + 'commlink' => "{'user'} ljcomm?>" }); + + $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($c, $&)!e; + $ret .= "
    @ $etime"; + $ret .= "
    "; + + + my $actions .= ""; + $actions .= ""; + $actions .= ""; + $actions .= ""; + $actions .= "  "; + + $ret .= "

    "; + $ret .= BML::fill_template("standout", {'DATA'=> $actions}); + $ret .= "
    "; + + my %current; + if ($props->{'current_mood'} || $props->{'current_moodid'}) { + $current{'Mood'} = $props->{'current_mood'}; + LJ::CleanHTML::clean_subject(\$current{'Mood'}); + my $mid = $props->{'current_moodid'}; + if ($mid) { + my $theme = $up->{'moodthemeid'}; + my %pic; + my $name = LJ::mood_name($mid); + if (LJ::get_mood_picture($theme, $mid, \%pic)) { + $current{'Mood'} = " $name"; + } else { + $current{'Mood'} = $name; + } + } + } + if ($props->{'current_music'}) { + $current{'Music'} = $props->{'current_music'}; + LJ::CleanHTML::clean_subject(\$current{'Music'}); + } + $ret .= "
    "; + if (%current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
    $curname$current{$_}

    \n"; + } + + ### security indicator + my $sec = ""; + if ($req->{'security'} eq "private") { + $sec = ""; + } elsif ($req->{'security'} eq "usemask") { + $sec = ""; + } + + $sec .= "
    \n" unless $sec eq "" or $subject; + $ret .= $sec; + + if ($subject) { + LJ::CleanHTML::clean_subject(\$subject); + BML::ebml(\$subject); + $ret .= "$subject
    \n"; + } + $ret .= $event; + $ret .= "

    "; + $ret .= "

    "; + } + + return $ret; +} + +_code?> + +<=body +page?> + diff --git a/livejournal/htdocs/community/pending.bml b/livejournal/htdocs/community/pending.bml new file mode 100755 index 0000000..31f9ab5 --- /dev/null +++ b/livejournal/htdocs/community/pending.bml @@ -0,0 +1,135 @@ + +body<= + '/community/manage.bml', + 'text' => $ML{'/community/members.bml.manage2'}, + }); + + # get remote + my $remote = LJ::get_remote(); + return "" + unless $remote; + + my $cname = $GET{'comm'}; + return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname; + + # get $c object + my $c = LJ::load_user($cname); + return "" + unless $c; + my $cid = $c->{'userid'}; + + # is $remote an admin? + unless (LJ::can_manage($remote, $c)) { + $ret .= " LJ::ljuser($cname, { type => 'C' }) }); + $ret .= " p?>"; + return $ret; + } + + # hit up the database to find pending members + my $pendids = LJ::get_pending_members($c) || []; + my $us = LJ::load_userids(@$pendids); + + # nothing pending? + return "" + unless @$pendids || LJ::did_post(); + + # saving a form submission + if ($POST{'action:update'}) { + my @userids = split(',', $POST{'ids'}); + + # need a db handle now + my $dbh = LJ::get_db_writer(); + + # hit up each user to find out what to do with them + my ($added, $rejected, $ignored, $previous); + foreach my $id (@userids) { + unless ($us->{$id}) { + $previous++; + next; + } + if ($POST{"pending_$id"} eq 'yes') { + LJ::approve_pending_member($cid, $id); + $added++; + } elsif ($POST{"pending_$id"} eq 'no') { + LJ::reject_pending_member($cid, $id); + $rejected++; + } else { + $ignored++; + } + } + + $ret .= ""; + $ret .= " $added }) . " p?>" if $added; + $ret .= " $rejected }) . " p?>" if $rejected; + $ret .= " $ignored }) . " p?>" if $ignored; + $ret .= " $previous }) . " p?>" if $previous; + $ret .= " BML::get_uri() . "?comm=$cname" }) . " p?>"; + + return $ret; + } + + my @users = sort { $a->{user} cmp $b->{user} } values %$us; + my $page_size = 100; # change to adjust page size + + # how to make links back to this page + my $self_link = sub { + return "pending.bml?comm=$cname&page=$_[0]"; + }; + + my %items = BML::paging(\@users, $GET{page}, $page_size); + my $navbar = LJ::paging_bar($items{page}, $items{pages}, + { self_link => $self_link }); + @users = @{$items{items}}; + + # output starts here + $ret .= " LJ::ljuser($cname, { type => 'C' }) }); + $ret .= " " . BML::ml('/community/members.bml.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>"; + + $ret .= "
    "; + + # table headers + $ret .= "
    \n" . + "\n"; + + # rows for existing users + my $rc = 0; + foreach (@users) { + my $rstyle = ($rc++ & 1) ? '' : ''; + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + } + + # some hidden values + $ret .= LJ::html_hidden('ids', join(',', map { $_->{userid}} @users)) . "\n"; + $ret .= "
    $ML{'/community/members.bml.key.user'}$ML{'.approve.title'}
    " . LJ::ljuser($_->{user}) . "" . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}", + id => "pending_$_->{userid}_yes", value => 'yes' }); + $ret .= " " . LJ::html_check({ type => 'radio', name => "pending_$_->{userid}", + id => "pending_$_->{userid}_no", value => 'no' }); + $ret .= "

    " . LJ::html_submit('action:update', $ML{'/community/members.bml.update'}) . "

    \n"; + $ret .= "
    \n\n"; + + $ret .= $navbar; + + return $ret; + +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/community/search.bml b/livejournal/htdocs/community/search.bml new file mode 100755 index 0000000..71ffc7d --- /dev/null +++ b/livejournal/htdocs/community/search.bml @@ -0,0 +1,165 @@ +'> +%%name%% + + %%form%% +<=crit +bar<= +{F} + +  +%%name%% + + %%form%% +<=bar +<=localblocks +_info?> +body<= + + h1?> + +p?> + + + +
    + +
    + + + + + + +code=>s_loc +form<= + +
    + + + +
    + \%countries }); + return LJ::html_select({ 'name' => 'loc_cn', }, + '', '', + map { $_, $countries{$_} } + ("US", sort { $countries{$a} cmp $countries{$b} } keys %countries)); +} +_code?> +
    + +<=form +crit?> + + + +code=>s_ut +form<= + + +<=form +crit?> + + + +code=>s_int +form<= +Community interest: +<=form +crit?> + + + +code=>s_fr +form<= +Contains user as a member. +<=form +crit?> + + +form<= + +<=form +bar?> + + + +form<= + + + + + + + + + + + +
    + + + +
    + + + +
    + + + +
    +<=form +bar?> + + + + + + + + +
    + +
    + +<=body +page?> + +form: htdocs/directory.bml + _c?> diff --git a/livejournal/htdocs/community/sentinvites.bml b/livejournal/htdocs/community/sentinvites.bml new file mode 100755 index 0000000..7d036ad --- /dev/null +++ b/livejournal/htdocs/community/sentinvites.bml @@ -0,0 +1,208 @@ + +body<= + '/community/manage.bml', + 'text' => $ML{'/community/members.bml.manage2'}, + }); + + # get remote + my $remote = LJ::get_remote(); + unless ($remote) { + $ret .= ""; + return $ret; + } + + my $cname = $GET{comm}; + return BML::redirect("$LJ::SITEROOT/community/manage.bml") unless $cname; + + # get $c object + my $c = LJ::load_user($cname); + unless ($c) { + $ret .= ""; + return $ret; + } + my $cid = $c->{'userid'}; + + # is $remote an admin? + unless (LJ::can_manage_other($remote, $c)) { + $ret .= " LJ::ljuser($cname, { 'type' => 'C' }) }); + $ret .= " p?>"; + return $ret; + } + + # columns of our table, excluding username + my @attribs = ('post'); + my @titleattribs = ('P'); + LJ::load_user_props($c, 'moderated'); + if ($c->{moderated}) { + push @attribs, ('preapprove', 'moderate'); + push @titleattribs, ('U', 'M'); + } + push @attribs, 'admin'; + push @titleattribs, 'A'; + + # now get sent invites and the users involved + my $sent = LJ::get_sent_invites($c) || []; + my @ids; + push @ids, ($_->{userid}, $_->{maintid}) foreach @$sent; + my $us = LJ::load_userids(@ids); + + # populate %users hash + my %users = (); + foreach my $invite (@$sent) { + my $id = $invite->{userid}; + next if $GET{show} && $GET{show} ne 'all' && $invite->{status} ne $GET{show}; + $users{$id}{userid} = $id; + $users{$id}{maintainer} = $us->{$invite->{maintid}}{user}; + $users{$id}{user} = $us->{$id}{user}; + $users{$id}{$_} = 1 foreach keys %{$invite->{args}}; + $users{$id}{status} = $invite->{status}; + $users{$id}{date} = LJ::mysql_time($invite->{recvtime}); + $users{$id}{date} =~ s/\s.+$//; # we just want the date, ignore time + } + + # hop out if there were no invites + unless (%users) { + return "$ret "href='/community/members.bml?comm=$c->{user}'" }) . + " p?>"; + } + + # sorting method; + my $method = $GET{'sort'}; + + my $cmp = sub {$a->{'user'} cmp $b->{'user'}}; + $cmp = sub {$b->{'admin'} <=> $a->{'admin'}} if $method eq 'A'; + $cmp = sub {$b->{'post'} <=> $a->{'post'}} if $method eq 'P'; + $cmp = sub {$b->{'moderate'} <=> $a->{'moderate'}} if $method eq 'M'; + $cmp = sub {$b->{'preapprove'} <=> $a->{'preapprove'}} if $method eq 'U'; + $cmp = sub {$a->{'status'} cmp $b->{'status'}} if $method eq 'status'; + $cmp = sub {$b->{'date'} cmp $a->{'date'}} if $method eq 'date'; + $cmp = sub {$b->{'maintainer'} cmp $a->{'maintainer'}} if $method eq 'maint'; + + my @users = sort $cmp values %users; + my $page_size = 100; # change to adjust page size + + # are we going to jump to a specific user ? + my $jumppage; + my $jumpuser; + if (@users > $page_size && $POST{'jumpto'} =~ /^\w+$/) { + my $ct; + foreach (@users) { + $jumppage++ if $ct % $page_size == 0; + if ($POST{'jumpto'} eq $_->{'name'}) { + $jumpuser = $_->{'name'}; + last; + } + $ct++; + } + undef $jumppage unless $jumpuser; + } + + # how to make links back to this page + my $self_link = sub { + my $sort = "&sort=$GET{'sort'}" if $GET{'sort'}; + my $filter = "&show=$GET{'show'}" if $GET{'show'}; + return "sentinvites.bml?comm=$cname&page=$_[0]$sort$filter"; + }; + + my %items = BML::paging(\@users, $jumppage || $GET{'page'}, $page_size); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}, + { 'self_link' => $self_link }); + @users = @{$items{'items'}}; + + # output starts here + $ret .= " LJ::ljuser($cname, { 'type' => 'C' }) }); + $ret .= " " . BML::ml('/community/members.bml.settings', { 'link' => "settings.bml?comm=$cname"}) . " p?>"; + + # jump to user + if ($items{'pages'} > 1) { + $ret .= "
    "; + $ret .= "
    Jump to user: "; + $ret .= LJ::html_text({ 'name' => 'jumpto', 'value' => $POST{'jumpto'}, + 'size' => '10', 'maxlength' => '15' }) . " "; + $ret .= LJ::html_submit(undef, 'Go') . "
    "; + $ret .= "
    "; + $ret .= $navbar; + } + + # setup showlinks + my $showlinks = "
    "; + $showlinks .= LJ::html_hidden('comm', $c->{user}); + $showlinks .= "Filter to: "; + $showlinks .= LJ::html_select({ name => 'show', selected => $GET{show} }, map { $_, $_ } qw(all accepted outstanding rejected)); + $showlinks .= LJ::html_submit(undef, 'Refresh'); + $showlinks .= "
    "; + + my $filter = "&show=$GET{show}" if $GET{show}; + my $sortlink = BML::get_uri() . "?comm=$cname$filter&sort="; + $ret .= "
    $showlinks"; + $ret .= < + + P + Posting Access + U + Unmoderated + + + M + Moderator + A + Maintainer + + +
    +END + $ret .= "\n" . + ""; + $ret .= "" foreach @titleattribs; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + # checkboxes and such + my $yes = ''; + my $no = '-'; + + # rows for existing users + my $rc = 0; + foreach(@users) { + my $rstyle = ($rc++ & 1) ? "" : ""; + $ret .= ""; + foreach my $key (@attribs) { + $ret .= ""; + } + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + } + + $ret .= "
    $ML{'/community/members.bml.key.user'}$_$ML{'.key.sentby'}$ML{'.key.date'}$ML{'.key.status'}
    " . LJ::ljuser($_->{user}) . ""; + $ret .= $_->{$key} ? $yes : $no; + $ret .= "" . LJ::ljuser($_->{maintainer}, { type => 'P' }) . "$_->{date}$_->{status}
    \n"; + $ret .= "
    $ML{'.send'}"; + $ret .= "
    \n\n"; + $ret .= $navbar; + return $ret; + +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/community/settings.bml b/livejournal/htdocs/community/settings.bml new file mode 100755 index 0000000..1620752 --- /dev/null +++ b/livejournal/htdocs/community/settings.bml @@ -0,0 +1,252 @@ + +<=title +head<= + +<=head +body<= + '/community/manage.bml', + 'text' => $ML{'/community/members.bml.manage2'}, + }); + my %errors; + + my $remote = LJ::get_remote(); + + unless ($remote) { + $ret .= ""; + return $ret; + } + + unless ($remote->{'journaltype'} eq 'P') { + $ret .= ""; + return $ret; + } + + my $mode = "modify"; + $mode = "create" if $GET{'mode'} eq 'create'; + + if (LJ::did_post()) + { + my $sth; + my $cuser = LJ::canonical_username($POST{'cuser'}); + my $cu = LJ::load_user($cuser); + + unless ($cu) { + $errors{'username'} = $ML{'.error.notfound'}; + } + + if ($cu && $cu->{'userid'} == $remote->{'userid'}) { + $errors{'username'} = $ML{'.error.samenames'}; + } + + # if we're changing rather than creating, check that we can + if ($mode eq 'modify' && !LJ::can_manage_other($remote, $cu)) { + $errors{'username'} = BML::ml('.error.noaccess', {'comm'=>$cuser}); + } + + # if we're creating, community password must match + if ($mode eq 'create' && $cu && !LJ::auth_okay($cu, $POST{'cpassword'})) { + $errors{'password'} = $ML{'.error.badpassword'}; + } + + # disallow changing the journal type if the journal has entries + if ($mode eq 'create' && !%errors && !LJ::check_priv($remote, "changejournaltype", "")) { + my $count; + my $userid=$cu->{'userid'}+0; + + my $dbcr = LJ::get_cluster_reader($cu); + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=$userid AND posterid=journalid"); + + $errors{'username'} = $ML{'.error.hasentries'} if $count; + } + + # if it's already a community, don't let them turn it into a community + if ($mode eq 'create' && !%errors && $cu->{journaltype} eq 'C') { + $errors{'username'} = $ML{'.error.alreadycomm'}; + } + + # if we found errors, we'll redisplay the form below. otherwise, + # proceed. + unless (%errors) { + my $dbh = LJ::get_db_writer(); + my $cid = $cu->{'userid'}; + my $qmembership = $POST{membership}; + $qmembership = 'closed' unless $qmembership =~ m/(?:open|moderated|closed)/; + $qmembership = $dbh->quote($qmembership); + my $qpostlevel = $dbh->quote($POST{'postlevel'} eq "members" ? "members" : "select"); + + LJ::update_user($cu, { journaltype => 'C' }); + if ($mode eq 'create') { + $dbh->do("REPLACE INTO community (userid, membership, postlevel) VALUES ($cid, $qmembership, $qpostlevel)"); + LJ::set_rel($cu, $remote, 'A'); + + # delete existing friends + my $friends = LJ::get_friends($cid, undef, undef, 'force') || {}; + LJ::remove_friend($cid, [ keys %$friends ]); + + } else { + $dbh->do("UPDATE community SET membership=$qmembership, postlevel=$qpostlevel WHERE userid=$cid"); + } + + my $nonmembers = $POST{'nonmember_posting'} + 0; + my $moderated = $POST{'moderated'} + 0; + + LJ::set_userprop($cu, 'nonmember_posting', $nonmembers); + LJ::set_userprop($cu, 'moderated', $moderated); + + if ($moderated && ! LJ::load_rel_user($cu->{'userid'}, 'M')->[0]) { + LJ::set_rel($cu->{'userid'}, $remote->{'userid'}, 'M'); + } + + $ret .= ""; + if ($mode eq 'create') { + $ret .= ""; + } else { + $ret .= ""; + } + + $ret .= "
  • $ML{'.label.commsite'}
  • "; + $ret .= "
  • $ML{'.label.comminfo'}
  • " + . BML::ml('.label.managepage', { 'aopts' => 'href="/community/manage.bml"' }) . "
  • p?>"; + + return $ret; + } + } + + # we're either creating a new community or modifying settings of an existing one + # based on whether $mode is 'create' or 'modify'. Most of the page is the same in + # either case, and additionally we must preload existing settings when modifying. + + my ($cname, $c); + + $cname = $POST{'cuser'}; # if we're falling through with errors when creating + + my %info = ( + 'membership'=>$POST{'membership'} || 'open', + 'postlevel'=>$POST{'postlevel'} || 'members', + 'nonmember_posting'=>$POST{'nonmember_posting'} || 0, + 'moderated'=>$POST{'moderated'} || 0, + ); + + if ($mode eq 'modify') { + $cname = LJ::canonical_username($GET{'comm'}); + $c = LJ::load_user($cname); + unless ($c) { + # if no community was specified, redirect to manage.bml + return BML::redirect("$LJ::SITEROOT/community/manage.bml"); + } + unless ($c->{'journaltype'} eq 'C') { + $ret = ""; + return $ret; + } + my $dbr = LJ::get_db_reader(); + ($info{'membership'},$info{'postlevel'}) = + $dbr->selectrow_array("SELECT membership, postlevel FROM community WHERE userid=$c->{'userid'}"); + LJ::load_user_props($c, "nonmember_posting", "moderated"); + $info{'nonmember_posting'} = $c->{'nonmember_posting'} ? 1 : 0; + $info{'moderated'} = $c->{'moderated'} ? 1 : 0; + } + + $ret .= "
    "; + + if ($mode eq 'modify') { + $ret .= ""; + } else { + $ret .= ""; + } + + if ($mode eq 'create') { + LJ::set_active_crumb('createcommunity'); + $ret .= "" . + ($mode eq 'modify' ? "" : ""); + $ret .= "$ML{'.label.maintainer'}"; + $ret .= "{'user'} ljuser?>
    $ML{'.label.maintainer.login'}"; + $ret .= "$ML{'.label.community'}"; + $ret .= "$ML{'.label.username'}

    "; + $ret .= "
    "; + $ret .= "$ML{'.label.password'}

    "; + $ret .= " standout?>"; + } else { + LJ::set_active_crumb('commsettings'); + $ret .= LJ::html_hidden('cuser', $cname); + $ret .= """}); + $ret .= " " . BML::ml('.members',{'link'=>"/community/members.bml?comm=$cname"}) . " p?>"; + } + + $ret .= ""; + $ret .= "
    "; + + # membership levels + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memopen', + value => 'open', selected => ($info{membership} eq 'open' ? 1 : 0)}); + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memmoderated', + value => 'moderated', selected => ($info{membership} eq 'moderated' ? 1 : 0)}); + $ret .= "

    "; + $ret .= LJ::html_check({ type => 'radio', name => 'membership', id => 'memclosed', + value => 'closed', selected => ($info{membership} eq 'closed' ? 1 : 0)}); + $ret .= "

    "; + $ret .= "
    "; + + my ($optopen,$optclosed); + if ($info{'postlevel'} eq 'members') { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    "; + + if ($info{'nonmember_posting'}) { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    "; + + if ($info{'moderated'}) { + ($optopen,$optclosed)=(" checked='checked'",""); + } else { + ($optopen,$optclosed)=("", " checked='checked'"); + } + + $ret .= "
    "; + $ret .= ""; + $ret .= "

    "; + $ret .= "

    \n"; + + $ret .= "
    "; + + return $ret; + +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/community/transfer.bml b/livejournal/htdocs/community/transfer.bml new file mode 100755 index 0000000..ea0d665 --- /dev/null +++ b/livejournal/htdocs/community/transfer.bml @@ -0,0 +1,66 @@ +" unless $remote; + + # bad statusvis? + unless ($remote->{statusvis} eq 'V') { + $body = ""; + return; + } + + # see if they posted and perform actions if so + if (LJ::did_post()) { + # get info about the community + my $cu = LJ::load_user($POST{comm}); + $errors{username} = $ML{'.error.notfound'} unless $cu; + + # the rest of the errors assume a community exists + if ($cu) { + # status/type errors + $errors{username} = $ML{'.error.notcomm'} unless $cu->{journaltype} eq 'C'; + $errors{username} = $ML{'.error.badstatus'} if !%errors && $cu->{statusvis} !~ /[VD]/; + + # are they already a maintainer? + $errors{username} = $ML{'.error.alreadyadmin'} if !%errors && LJ::can_manage($remote, $cu); + + # check the password last + $errors{password} = $ML{'.error.nopassword'} if !%errors && !$POST{password}; + $errors{password} = $ML{'.error.mismatch'} if !%errors && !LJ::auth_okay($cu, $POST{password}); + } + + # everything checks out, transfer it + unless (%errors) { + $cu->log_event('maintainer_add', { actiontarget => $remote->{userid}, remote => $remote }); + LJ::set_rel($cu, $remote, 'A'); + $body = " LJ::ljuser($cu, { type => 'C' }) }); + $body .= " p?>"; + return; + } + } + + # setup the form to transfer the community + $body .= ""; + $body .= "
    "; + $body .= ""; + $body .= "\n"; + $body .= "" if $errors{username}; + $body .= ""; + $body .= "\n"; + $body .= "" if $errors{password}; + $body .= ""; + $body .= "
    $ML{'.account'}" . LJ::html_text({ name => 'comm', id => 'comm', value => $POST{comm} }) . "
    $ML{'.password'}" . LJ::html_text({ type => 'password', name => 'password', id => 'password' }) . "
    " . LJ::html_submit(undef, $ML{'.button.title'}) . "
    "; + + return; +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/create.bml b/livejournal/htdocs/create.bml new file mode 100755 index 0000000..144f200 --- /dev/null +++ b/livejournal/htdocs/create.bml @@ -0,0 +1,620 @@ + +head<= + +<=head +body<= +" unless LJ::text_in(\%POST); + + my $mode = $POST{'mode'}; + my $code = $POST{'code'} || $GET{'code'}; + + if ($LJ::USE_SSL && ! $LJ::IS_SSL && $FORM{'ssl'} ne "no") { + return BML::redirect("$LJ::SSLROOT/create.bml"); + } + + # with no mode, decide which screen the user sees first, based + # on whether or not this LJ installation lets in free users + if ($mode eq "") { + $mode = $LJ::USE_ACCT_CODES ? + ($code ? "codesubmit" : "entercode") + : "getinfo"; + } + + my $remote = LJ::get_remote(); + + my %errors; + my $error_msg = sub { + my $key = shift; + my $pre = shift; + my $post = shift; + my $msg = $errors{$key}; + return unless $msg; + return "$pre $msg $post"; + }; + + # Flag to indicate they've submitted with 'audio' as the answer to the spambot + # challenge. + my $wants_audio = 0; + + # Captcha id + my ($capid, $anum); + + # validate a code they've entered and throw them back to entercode + # mode if it's invalid + if ($code && $mode eq "submit" || # account codes turned off, but one specified anyway + $LJ::USE_ACCT_CODES && ($mode eq "codesubmit" || $mode eq "submit")) # account codes required + { + my $error; + my $userid = 0; # acceptable userid for double-click protection + if ($mode eq "submit") { + my $u = LJ::load_user($POST{'user'}); + $userid = $u->{'userid'}; + } + $errors{'code'} = $error + unless (LJ::acct_code_check($code, \$error, $userid)); + if (%errors) { + $mode = "entercode"; + } elsif ($mode eq "codesubmit") { + $mode = "getinfo"; + } + } + + # MODE: entercode - enter an account code to proceed making an account + if ($LJ::USE_ACCT_CODES && $mode eq "entercode") + { + my $ret; + my $v; + + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'codesubmit', + ssl => $FORM{'ssl'}); + + $ret .= ""; + + $v = LJ::ehtml($code); + $ret .= " "; + $ret .= $error_msg->('code', '
    '); + $ret .= " standout?>"; + $ret .= "
    \n"; + + open (REM, "$LJ::HOME/htdocs/inc/account-codes"); + while () { + $ret .= $_; + } + close REM; + + return $ret; + } + +# MODE: submit - if they've given 'audio' as the answer to the spambot-blocker, +# reset the mode to 'getinfo' and set the audio flag +if ( $LJ::HUMAN_CHECK{create} && $mode eq 'submit' && lc($POST{answer}) eq 'audio' ) +{ + $mode = 'getinfo'; + $wants_audio = 1; +} + + # MODE: submit - try to create an account. might change mode + # if there are errors, we'll populate %errors and + # return to "getinfo" mode below + SUBMIT: + while ($mode eq "submit") # using while instead of if so we can 'last' out of it + { + return "$ML{'Error'}: $ML{'.error.postrequired'}" unless LJ::did_post(); + + my $user = LJ::canonical_username($POST{'user'}); + my $email = LJ::trim(lc($POST{'email'})); + + # setup global things that can be used to modify the user later + my $is_underage = 0; # turn on if the user should be marked as underage + my $ofage = 0; # turn on to note that the user is over 13 in actuality + # (but is_underage might be on which just means that their + # account is being marked as underage--even if they're old + # enough [unique cookie check]) + + # reject this email? + return LJ::sysban_block(0, "Create user blocked based on email", + { 'new_user' => $user, 'email' => $email, 'name' => $user }) + if LJ::sysban_check('email', $email); + + my $dbh = LJ::get_db_writer(); + + if (length($user) > 15) { + $errors{'username'} = "$ML{'error.usernamelong'}"; + } + if ($POST{'user'} && ! $user) { + $errors{'username'} = "$ML{'error.usernameinvalid'}"; + } + unless ($POST{'user'}) { + $errors{'username'} = "$ML{'.error.username.mustenter'}"; + } + foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { + next unless ($user =~ /$re/); + + # you can give people sharedjournal priv ahead of time to create + # reserved communities: + next if LJ::check_priv($remote, "sharedjournal", $user); + + $errors{'username'} = "$ML{'.error.username.reserved'}"; + } + + # see if they're confused and entered a valid account code + # for their username (happens often) + if ($LJ::USE_ACCT_CODES && $user =~ /^.....a[ab].....$/) { + # see if the acctcode is valid and unused + my ($acid, $auth) = LJ::acct_code_decode($user); + my $is_valid = $dbh->selectrow_array("SELECT COUNT(*) FROM acctcode ". + "WHERE acid=? AND rcptid=0", + undef, $acid); + $errors{'username'} = "$ML{'.error.username.iscode'}" + if $is_valid; + } + + my $u = LJ::load_user($user); + my $second_submit = 0; + if ($u) { + my $in_use = 1; + + if ($u->{'email'} eq $POST{'email'}) { + if (LJ::login_ip_banned($u)) { + # brute-force possible going on + } else { + if ($u->{'password'} eq $POST{'password1'}) { + # oh, they double-clicked the submit button + $second_submit = 1; + $in_use = 0; + } else { + LJ::handle_bad_login($u); + } + } + } + + if ($in_use) { + $errors{'username'} = "$ML{'.error.username.inuse'}"; + } + } + + $POST{'password1'} = LJ::trim($POST{'password1'}); + $POST{'password2'} = LJ::trim($POST{'password2'}); + + if ($POST{'password1'} ne $POST{'password2'}) { + $errors{'password'} = "$ML{'.error.password.nomatch'}"; + } else { + my @checkpass = LJ::run_hooks("bad_password", + { 'user' => $user, 'name' => $user, + 'email' => $email, 'password' => $POST{'password1'} }); + if (@checkpass && $checkpass[0]->[0]) { + $errors{'password'} = "Bad password: $checkpass[0]->[0]"; + } + } + if (! $POST{'password1'}) { + $errors{'password'} = "$ML{'.error.password.blank'}"; + } elsif (length $POST{'password1'} > 30) { + $errors{'password'} = "$ML{'password.max30'}"; + } + + unless (LJ::is_ascii($POST{'password1'})) { + $errors{'password'} = "$ML{'.error.password.asciionly'}"; + } + + ### start COPPA_CHECK + # age checking to determine how old they are + if ($LJ::COPPA_CHECK) { + my $uniq; + if ($LJ::UNIQ_COOKIES) { + $uniq = Apache->request->notes('uniq'); + if ($uniq) { + my $timeof = $dbh->selectrow_array('SELECT timeof FROM underage WHERE uniq = ?', undef, $uniq); + $is_underage = 1 if $timeof && $timeof > 0; + } + } + + my ($year, $mon, $day) = ( $POST{"bday_yyyy"}+0, $POST{"bday_mm"}+0, $POST{"bday_dd"}+0 ); + if ($year < 100) { + $POST{'bday_yyyy'} += 1900; + $year += 1900; + } + + # get current time + my ($nday, $nmon, $nyear) = (gmtime())[3, 4, 5]; + $nyear += 1900; + $nmon += 1; + + # require dates in the 1900s (or beyond) + if ($year && $mon && $day && $year >= 1900 && $year <= $nyear) { + # now see how many years back they are + my $ofageyear = $year + 13; + if ($ofageyear > $nyear) { + $is_underage = 1; + } elsif ($ofageyear == $nyear) { + # years match, see if they were born after this month + if ($mon > $nmon) { + $is_underage = 1; + } elsif ($mon == $nmon) { + # now check the day + if ($day > $nday) { + $is_underage = 1; + } else { + $ofage = 1; + } + } else { + $ofage = 1; + } + } else { + $ofage = 1; + } + } else { + $errors{'bday'} = "$ML{'.error.birthday.invalid'}"; + } + + # note this unique cookie as underage (if we have a unique cookie) + if ($is_underage && $uniq) { + $dbh->do("REPLACE INTO underage (uniq, timeof) VALUES (?, UNIX_TIMESTAMP())", undef, $uniq); + } + } + ### end COPPA_CHECK + + if ($LJ::TOS_CHECK && ! $POST{'agree_tos'}) { + $errors{'agree_tos'} = $ML{'tos.error'}; + } + + # check the email address + { + my @email_errors; + LJ::check_email($email, \@email_errors); + if ($LJ::USER_EMAIL and $email =~ /\@\Q$LJ::USER_DOMAIN\E$/i) { + push @email_errors, BML::ml(".error.email.lj_domain", + {domain => $LJ::USER_DOMAIN}); + } + $errors{'email'} = join(", ", @email_errors) if @email_errors; + } + + # Check the turing test answer if it's turned on + if ($LJ::HUMAN_CHECK{create}) { + ($capid, $anum) = LJ::Captcha::session_check_code($POST{captcha_chal}, $POST{answer}); + $errors{'captcha'} = $ML{'.captcha.invalid'} unless $capid && $anum; + } + last SUBMIT if %errors; + + my $clusterid = ($LJ::ALLOW_CLUSTER_SELECT + ? $POST{'cluster_id'} + : LJ::new_account_cluster()) + 0; + die "Cluster 0 not supported" unless $clusterid; + + my $userid = $u ? $u->{'userid'}+0 : 0; + unless ($second_submit) + { + my $caps = int($LJ::NEWUSER_CAPS); + my $status = ($LJ::EVERYONE_VALID ? 'A' : 'N'); + $dbh->do("INSERT INTO user (user, email, password, status, caps, name, clusterid, dversion) ". + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + undef, $user, $email, $POST{'password1'}, $status, $caps, + $user, $clusterid, $LJ::MAX_DVERSION); + if ($dbh->err) { + return "" . $dbh->errstr . " p?>"; + } + $userid = $dbh->{'mysql_insertid'}; + $dbh->do("REPLACE INTO useridmap (userid, user) VALUES (?, ?)", undef, $userid, $user); + $dbh->do("REPLACE INTO userusage (userid, timecreate) VALUES (?, NOW())", undef, $userid); + + # if we're using account codes on this site, mark the code as used + if ($code) { + my ($acid, $auth) = LJ::acct_code_decode($code); + $dbh->do("UPDATE acctcode SET rcptid=$userid WHERE acid=$acid"); + if ($dbh->err) { return $dbh->errstr; } + } + + # if we have initial friends for new accounts, add them. + foreach my $friend (@LJ::INITIAL_FRIENDS) { + my $friendid = LJ::get_userid($friend); + LJ::add_friend($userid, $friendid) if $friendid; + } + foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) { + my $friendid = LJ::get_userid($friend); + LJ::add_friend($userid, $friendid) if $friendid and $POST{"initial_optional_friend_$friend"}; + } + + # Set any properties that get set in new users + while (my ($name, $val) = each %LJ::USERPROP_INIT) { + LJ::set_userprop($userid, $name, $val); + } + + # Mark the turing test for deletion + if ($LJ::HUMAN_CHECK{create}) { + LJ::Captcha::expire($capid, $anum, $userid); + } + + LJ::run_hooks("post_create", { + 'userid' => $userid, + 'user' => $user, + 'code' => $code, + }); + } + + # send welcome mail... unless they're underage + unless ($is_underage) { + my $aa = {}; + if ($userid) { + $aa = LJ::register_authaction($userid, "validateemail", $email); + } + + my $body = BML::ml('email.newacct2.body', { + "email" => $email, + "regurl" => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}", + "username" => $user, + "sitename" => $LJ::SITENAME, + "siteroot" => $LJ::SITEROOT, + "admin_email" => $LJ::ADMIN_EMAIL, + "bogus_email" => $LJ::BOGUS_EMAIL, + }); + + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'charset' => 'utf-8', + 'subject' => BML::ml('email.newacct.subject', {'sitename' => $LJ::SITENAME}), + 'body' => $body, + }); + } + + my $nu = LJ::load_userid($userid, "force"); + + # now flag as underage (and set O to mean was old or Y to mean was young) + $nu->underage(1, $ofage ? 'O' : 'Y', 'account creation') if $is_underage; + + if ($LJ::TOS_CHECK) { + my $err = ""; + $nu->tosagree_set(\$err) + or return LJ::bad_input($err); + } + + # record create information + $nu->log_event('account_create', { remote => $remote }); + + $nu->make_login_session; + + # local sites may want to override what happens at this point + my $redirect = undef; + my $stop_output; + LJ::run_hooks("create.bml_postsession", { + post => \%POST, + u => $nu, + redirect => \$redirect, + ret => \$ret, + stop_output => \$stop_output, + }); + return BML::redirect($redirect) if $redirect; + return $ret if $stop_output; + + $ret = " $email, 'username' => $user}) ." p?>"; + my $uri = LJ::journal_base($nu); + $ret .= "\n"; + $ret .= "$uri/
    standout?>\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= "

    " . LJ::html_submit(undef, "$ML{'.success.btn.enterinfo'} →") . "

    "; + $ret .= "
    \n"; + + return $ret; + + } + + if ($mode eq "getinfo" || %errors) + { + my $ret; + my $v; + + if (%errors) { + my @errors_order = ('code', 'username', 'email', 'password', 'agree_tos', 'captcha'); + my %errors_def; + $errors_def{$_} = 1 for @errors_order; + foreach my $key (keys %errors) { push @errors_order, $key unless $errors_def{$key}; } + $ret .= "$ML{'.errors.label'}
    • "; + $ret .= join ("
    • ", grep { $_ } map { $errors{$_} } @errors_order); + $ret .= "
    standout?>"; + } + + $ret .= "" unless %errors; + $ret .= "
    \n"; + $ret .= LJ::html_hidden(mode => 'submit', + code => $code, + ssl => $FORM{'ssl'}); + + $ret .= "
      "; + + ### username + $v = LJ::ehtml($FORM{'user'}); + $ret .= "
    1. $ML{'.username.box.head'}
      "; + $ret .= $error_msg->('username', '

      ', '

      '); + $ret .= "
      " . BML::ml(".username.text", {'sitename' => $LJ::SITENAME}) . "
      "; + $ret .= LJ::html_text({'name' => 'user', 'size' => 15, 'maxlength' => 15, 'value' => $v, raw => 'style=""' }); + $ret .= "
      " . BML::ml('.community', { aopts => "href='$LJ::SITEROOT/community/create.bml'" }); + $ret .= "
      $ML{'.username.charsallowed'}
      " if (!%errors || exists $errors{'username'}); + $ret .= "
    2. "; + + ### email address + $v = LJ::ehtml($FORM{'email'}); + $ret .= "
    3. $ML{'.email.input.head'}
      "; + $ret .= $error_msg->('email', '

      ', '

      '); + $ret .= "
      " . BML::ml('.email.text3', { + aopts => "target='_new' href='$LJ::SITEROOT/legal/privacy.bml'", + }) . "
      "; + $ret .= LJ::html_text({'name' => 'email', 'size' => 40, 'maxlength' => 50, 'value' => $v,}); + $ret .= "
    4. "; + + $ret .= "
    5. $ML{'.password.input.head1'}
      "; + $ret .= $error_msg->('password', '

      ', '

      '); + $ret .= "
      $ML{'.password.secure'}
      " if exists $errors{'password'}; + $ret .= "
      $ML{'.password.text'}
      "; + my $pass_value = $errors{'password'} ? "" : $POST{'password1'}; + $ret .= LJ::html_text({'name' => 'password1', 'size' => 30, 'maxlength' => 31, 'type' => "password", + value => $pass_value, }); + $ret .= "
      $ML{'.password.input.head2'}
      "; + $ret .= LJ::html_text({'name' => 'password2', 'size' => 30, 'maxlength' => 31, 'type' => "password", + value => $pass_value, }); + $ret .= "
    6. "; + + if (@LJ::INITIAL_OPTIONAL_FRIENDS) { + $ret .= "
    7. $ML{'.initialfriends.heading'}
      "; + $ret .= "
      $ML{'.initialfriends'}
      "; + $ret .= "
      "; + foreach my $friend (@LJ::INITIAL_OPTIONAL_FRIENDS) { + $ret .= LJ::html_check({'name' => "initial_optional_friend_$friend", + 'value' => 1, + 'selected' => $POST{"initial_optional_friend_$friend"}, + 'id' => "optfriend_$friend", + }); + $ret .= "
      "; + } + $ret .= "
    8. "; + } + + if ($LJ::COPPA_CHECK) + { + $ret .= "
    9. $ML{'.birthday.head'}
      "; + $ret .= "
      $errors{'bday'}
      " if exists $errors{'bday'}; + $ret .= "
      $ML{'.birthday.question'}
      "; + $ret .= ""; + $ret .= "
      $ML{'.birthday.birthdate'}"; + $ret .= LJ::html_datetime({ name => 'bday', notime => 1, + default => sprintf("%04d-%02d-%02d", $POST{bday_yyyy}, $POST{bday_mm}, $POST{bday_dd}) }); + $ret .= "$ML{'.birthday.required'}
    10. "; + } + + LJ::run_hooks("create.bml_opts", { + post => \%POST, + get => \%GET, + ret => \$ret, + }); + + if ($LJ::TOS_CHECK) + { + $ret .= "
    11. $ML{'.tos.heading'}
      "; + $ret .= LJ::tosagree_widget($POST{agree_tos}, $errors->{agree_tos}); + $ret .= "
    12. "; + } + + if ($LJ::ALLOW_CLUSTER_SELECT) { + $ret .= "
    13. $ML{'.clusterselect.head'}
      "; + $ret .= "
      $ML{'.clusterselect.text'}
      "; + $ret .= LJ::html_select({ 'name' => 'cluster_id' }, + "0", "$BML{'.clusterselect.nocluster'}", + map { $_, BML::ml(".clusterselect.clusternum", {'number' => $_}) } @LJ::CLUSTERS); + + $ret .= "
      $ML{'.clusterselect.cluster'}
      "; + $ret .= "
    14. "; + } + + if ($LJ::HUMAN_CHECK{create}) { + my ($captcha_chal, $captcha_sess); + $captcha_chal = $POST{captcha_chal} || LJ::challenge_generate(900); + $captcha_sess = LJ::get_challenge_attributes($captcha_chal); + + my $answer = $POST{answer}; + undef $answer if $errors{'captcha'} || $wants_audio; + + + my $try = 0; + if ($form->{captcha_chal}) { + my $dbcm = LJ::get_cluster_reader(); + $try = $dbcm->selectrow_array('SELECT trynum FROM captcha_session ' . + 'WHERE sess=?', undef, $captcha_sess); + } + + $ret .= "
    15. $ML{'.captcha.prove'}
      "; + + # Visual challenge + unless ( $wants_audio || $POST{audio_chal} ) { + $ret .= "
      $ML{'.captcha.desc'}
      "; + if ($capid && $anum) { # previously entered correctly + $ret .= ""; + } else { + $ret .= ""; + } + } + + # Audio challenge + else { + $ret .= "
      $ML{'.captcha.audiodesc'}
      "; + if ($capid && $anum) { + $ret .= "$ML{'.captcha.play'}"; + } else { + $ret .= "$ML{'.captcha.play'}"; + } + $ret .= LJ::html_hidden(audio_chal => 1); + } + + $ret .= "

      $ML{'.captcha.answer'}"; + $ret .= LJ::html_text({ name => 'answer', size => 15, value => $answer }); + $ret .= LJ::html_hidden(captcha_chal => $captcha_chal); + $ret .= $error_msg->('captcha', '

      ', '

      '); + $ret .= "
    16. "; + } + + $ret .= "
    "; + + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + $ret .= "
    "; + + return $ret; + } + + return "$ML{'error.unknownmode'}: $mode"; + +_code?> +<=body +page?> +link: htdocs/legal/privacy.bml +post: htdocs/create.bml, htdocs/editinfo.bml +file: htdocs/inc/account-codes +hook: post_create + _c?> diff --git a/livejournal/htdocs/customize/advanced/index.bml b/livejournal/htdocs/customize/advanced/index.bml new file mode 100755 index 0000000..d198191 --- /dev/null +++ b/livejournal/htdocs/customize/advanced/index.bml @@ -0,0 +1,29 @@ +Advanced Customization +body<= + + + +main customization area, which is designed for anybody to use. +p?> + + + + + + + + +<=body +page?> diff --git a/livejournal/htdocs/customize/advanced/layerbrowse.bml b/livejournal/htdocs/customize/advanced/layerbrowse.bml new file mode 100755 index 0000000..4a8110c --- /dev/null +++ b/livejournal/htdocs/customize/advanced/layerbrowse.bml @@ -0,0 +1,308 @@ + './', + 'text' => 'Advanced Customization', + }); + + my $err = sub { + $title = "Error"; + $body = shift; + return; + }; + + my $pub = LJ::S2::get_public_layers(); + + my $id; + if ($GET{'id'} =~ /^\d+$/) { # numeric + $id = $GET{'id'}; + } elsif ($GET{'id'}) { # redist_uniq + $id = $pub->{$GET{'id'}}->{'s2lid'}; + } + + my $dbr = LJ::get_db_reader(); + my $remote = LJ::get_remote(); + + # show the public layers + unless ($id) { + $title = "Public Layers"; + my %layerinfo; + my @to_load = grep { /^\d+$/ } keys %$pub; + LJ::S2::load_layer_info(\%layerinfo, \@to_load); + + my $recurse = sub { + my $self = shift; + my $lid = shift; # layer id + my $lay = $pub->{$lid}; + return unless $lay; + + # set to true if the layer is not core and is not a layout + my $is_child = $lay->{'type'} ne 'core' && $lay->{'type'} ne 'layout'; + + my $typedes = " ($lay->{'type'}" . (! $is_child ? ": $lid" : '') . ")"; + + # show link to detailed view + $body .= "
  • " . LJ::ehtml($layerinfo{$lid}->{'name'}); + $body .= "$typedes
  • "; + + # done unless there are children to recurse through + return unless ! $is_child && $lay->{'children'}; + + # if we're not expanding these children, stop and show a link + if ($lay->{'type'} eq 'layout' && $GET{'expand'} != $lid) { + $body .= ""; + return; + } + + # expand children + $body .= "
      "; + foreach (@{$lay->{'children'}}) { + $self->($self, $_); + } + $body .= "
    "; + + return; + }; + + # iterate through core layers + $body .= "
      "; + foreach (grep { $pub->{$_}->{'b2lid'} == 0 } grep { /^\d+$/ } keys %$pub) { + $recurse->($recurse, $_); # start from the top + } + $body .= "
    "; + + return; + } + + ### details on a specific layer ### + + my $xlink = sub { + my $r = shift; + $$r =~ s/\[class\[(\w+)\]\]/$1<\/a>/g; + $$r =~ s/\[method\[(.+?)\]\]/$1<\/a>/g; + $$r =~ s/\[function\[(.+?)\]\]/$1<\/a>/g; + $$r =~ s/\[member\[(.+?)\]\]/$1<\/a>/g; + }; + + # load layer info + my $layer = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id); + return $err->("The specified layer does not exist.") + unless $layer; + + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ? + $layerinfo->{$id}->{'source_viewable'} : undef; + + # do they have access? + my $isadmin = !defined $pub->{$id} && # public styles are pulled from the system + (LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges + LJ::check_priv($remote, 'canview', '*')); # in case they're private styles + return $err->("You are not authorized to view this layer.") + unless defined $pub->{$id} || $srcview == 1 || + LJ::can_manage($remote, $layer->{'userid'}) || + $isadmin; + + LJ::S2::load_layers($id); + my $s2info = S2::get_layer_all($id); + my $class = $s2info->{'class'} || {}; + + my $xlink_args = sub { + my $r = shift; + return unless + $$r =~ /^(.+?\()(.*)\)$/; + my ($new, @args) = ($1, split(/\s*\,\s*/, $2)); + foreach (@args) { + s/^(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + } + $new .= join(", ", @args) . ")"; + $$r = $new; + $xlink->($r); + }; + + $body .= "
    "; + # link to layer list if this is a public layer, otherwise user's layer list + if (defined $pub->{$id}) { + $body .= BML::ml('backlink', { 'link' => 'layerbrowse.bml', 'text' => 'Public Layers' }) . "\n"; + } else { + $body .= BML::ml('backlink', { 'link' => "layers.bml", 'text' => 'Your Layers' }) . "\n"; + $body .= BML::ml('actionlink', { 'link' => "
    Edit Layer" }) . "\n"; + } + + if ($layer->{'b2lid'}) { + $body .= "[{'b2lid'}\">Parent Layer]\n"; + } + if (defined $pub->{$id} && (! defined $srcview || $srcview != 0) || + $srcview == 1 || + LJ::can_manage($remote, $layer->{'userid'}) || + $isadmin) { + + $body .= "[Download]\n"; + $body .= "[View as HTML]\n"; + } + + # layerinfo + if (my $info = $s2info->{'info'}) { + $body .= ""; + $body .= ""; + foreach my $k (sort keys %$info) { + my ($ek, $ev) = map { LJ::ehtml($_) } ($k, $info->{$k}); + $title = $ev if $k eq "name"; + $body .= "\n"; + } + $body .= "
    $ek$ev
    "; + } + + # sets + if (my $set = $s2info->{'set'}) { + $body .= ""; + $body .= ""; + foreach my $k (sort keys %$set) { + my $v = $set->{$k}; + if (ref $v eq "HASH") { + if ($v->{'_type'} eq "Color") { + $v = "{'as_string'}\"> $v->{'as_string'}"; + } else { + $v = "[unknown object type]"; + } + } elsif (ref $v eq "ARRAY") { + $v = "List: (" . join(", ", map { LJ::ehtml($_) } @$v) . ")"; + } else { + $v = LJ::ehtml($v); + } + $body .= "\n"; + } + $body .= "
    $k$v
    "; + } + + # global functions + my $gb = $s2info->{'global'}; + if (ref $gb eq "HASH" && %$gb) { + $body .= ""; + $body .= ""; + foreach my $fname (sort keys %$gb) { + my $rt = $gb->{$fname}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = LJ::ehtml($gb->{$fname}->{'docstring'}); + $xlink->(\$ds); + + my $args = $gb->{$fname}->{'args'}; + $xlink_args->(\$args); + + $body .= ""; + } + $body .= "
    $args : $rt$ds
    "; + } + + + if (%$class) + { + # class index + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "
    Alphabetical"; + $body .= "
      "; + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + $body .= "
    • $cname
    • \n"; + } + $body .= "
    "; + $body .= "
    Hierarchical"; + my $dumpsub = sub { + my $self = shift; + my $parent = shift; + $body .= "
  • $parent
  • \n" + if $parent; + my $didul = 0; + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + next unless $class->{$cname}->{'parent'} eq $parent; + unless ($didul++) { $body .= "
      "; } + $self->($self, $cname); + } + if ($didul) { $body .= "
    "; } + }; + $dumpsub->($dumpsub, ""); + $body .= "
    "; + + # classes + foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) { + $body .= ""; + my $ds = LJ::ehtml($class->{$cname}->{'docstring'}); + if ($class->{$cname}->{'parent'}) { + $ds = "Child class of [class[$class->{$cname}->{'parent'}]]. $ds"; + } + if ($ds) { + $xlink->(\$ds); + $body .= ""; + } + + # build functions & methods + my (%func, %var); + my $add = sub { + my ($self, $aname) = @_; + foreach (keys %{$class->{$aname}->{'funcs'}}) { + $func{$_} = $class->{$aname}->{'funcs'}->{$_}; + $func{$_}->{'_declclass'} = $aname; + } + foreach (keys %{$class->{$aname}->{'vars'}}) { + $var{$_} = $class->{$aname}->{'vars'}->{$_}; + $var{$_}->{'_declclass'} = $aname; + } + + my $parent = $class->{$aname}->{'parent'}; + $self->($self, $parent) if $parent; + }; + $add->($add, $cname); + + $body .= "" if %var; + foreach (sort keys %var) { + my $type = $var{$_}->{'type'}; + $type =~ s/(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg; + $xlink->(\$type); + + my $ds = LJ::ehtml($var{$_}->{'docstring'}); + $xlink->(\$ds); + + if ($var{$_}->{'readonly'}) { + $ds = "(Read-only) $ds"; + } + + $body .= ""; + } + $body .= "
    $type $_$ds
    " if %var; + + $body .= "" if %func; + foreach (sort keys %func) { + my $rt = $func{$_}->{'returntype'}; + if (defined $class->{$rt}) { + $rt = "[class[$rt]]"; + } + $xlink->(\$rt); + my $ds = LJ::ehtml($func{$_}->{'docstring'}); + $xlink->(\$ds); + + my $args = $_; + $xlink_args->(\$args); + + $body .= ""; + } + $body .= "
    $args : $rt$ds
    " if %func; + } + } + + return; +} +_code?> +body=> +page?> + diff --git a/livejournal/htdocs/customize/advanced/layeredit.bml b/livejournal/htdocs/customize/advanced/layeredit.bml new file mode 100755 index 0000000..1b9c948 --- /dev/null +++ b/livejournal/htdocs/customize/advanced/layeredit.bml @@ -0,0 +1,139 @@ + +Error\n

    Error

    " . shift; + }; + + # we need a valid id + my $id = $GET{'id'} if $GET{'id'} =~ /^\d+$/; + return $err->("You have not specified a layer to edit.") + unless $id; + + # authenticate user; + my $remote = LJ::get_remote(); + return $err->("You must be logged in to edit layers.") + unless $remote; + + # load layer + my $lay = LJ::S2::load_layer($id); + return $err->("The specified layer does not exist.") + unless $lay; + + # if the b2lid of this layer has been remapped to a new layerid + # then update the b2lid mapping for this layer + my $b2lid = $lay->{b2lid}; + if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) { + LJ::S2::b2lid_remap($remote, $id, $b2lid); + $lay->{b2lid} = $LJ::S2LID_REMAP{$b2lid}; + } + + # is authorized admin for this layer? + return $err->('You are not authorized to edit this layer.') + unless LJ::can_manage($remote, $lay->{'userid'}); + + # get u of user they are acting as + my $u = $lay->{'userid'} == $remote->{'userid'} ? $remote : LJ::load_userid($lay->{'userid'}); + + # check priv and ownership + return $err->("You are not authorized to edit styles.") + unless LJ::get_cap($u, "s2styles"); + + # at this point, they are authorized, allow viewing & editing + my $ret; + $ret .= "
    \n"; + $ret .= BML::ml('backlink', { 'text' => 'Your Layers', 'link' => "layers.bml?authas=$u->{'user'}" }) . "\n"; + + # get s2 code from db - use writer so we know it's up-to-date + my $dbh = LJ::get_db_writer(); + my $s2code = $POST{'s2code'}; + $s2code = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", + undef, $lay->{'s2lid'}) unless $s2code; + + # we tried to compile something + if ($POST{'action'} eq "compile") { + $ret .= "
    \n"; + $ret .= "S2 Compiler Output at " . scalar(localtime) . "
    \n"; + + my $error; + $POST{'s2code'} =~ s/\r//g; # just in case + unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$POST{'s2code'} })) { + + $error =~ s/LJ::S2,.+//s; + $error =~ s!, .+?(src/s2|cgi-bin)/!, !g; + + $ret .= "Error compiling layer:\n
    $error
    "; + + # display error with helpful context + if ($error =~ /^compile error: line (\d+)/i) { + my $errline = $1; + my $kill = $errline - 5 < 0 ? 0 : $errline - 5; + my $prehilite = $errline - 1 > 4 ? 4: $errline - 1; + my $snippet = $s2code; + + # make sure there's a newlilne at the end + chomp $snippet; + $snippet .= "\n"; + + # and now, fun with regular expressions + my $ct = 0; + $snippet =~ s!(.*?)\n!sprintf("%3d", ++$ct) . ": " . + $1 . "\n"!ge; # add line breaks and numbering + $snippet = LJ::ehtml($snippet); + $snippet =~ s!^((?:.*?\n){$kill,$kill}) # kill before relevant lines + ((?:.*?\n){$prehilite,$prehilite}) # capture context before error + (.*?\n){0,1} # capture error + ((?:.*?\n){0,4}) # capture context after error + .* # kill after relevant lines + !$2$3$4!sx; + + $ret .= "Context
    $snippet
    \n"; + } + + } else { + $ret .= "No errors\n"; + } + $ret .= "
    \n\n"; + } + + $ret .= LJ::html_hidden("action", "compile") . "\n"; + $ret .= "

    " . LJ::html_submit('submit', 'Compile', { + 'style' => 'float: right; margin-bottom: 2px', + 'accesskey' => 'c', + 'title' => 'alt-C: compile', + } ) . "\n"; + $ret .= "Edit layer source\n"; + $ret .= LJ::html_textarea({ 'name' => 's2code', 'class' => 's2code', 'wrap' => 'off', + 'cols' => '50', 'rows' => '40', 'value' => $s2code }) . "\n"; + $ret .= LJ::html_submit('submit', 'Compile') . "\n"; + $ret .= "

    \n"; + + # load layer info + my $layinf = {}; + LJ::S2::load_layer_info($layinf, [ $id ]); + + # find a title to display on this page + my $type = $layinf->{$id}->{'type'}; + my $name = $layinf->{$id}->{'name'}; + + # find name of parent layer if this is a child layer + if (! $name && $type =~ /^(user|theme|i18n)$/) { + my $par = $lay->{'b2lid'} + 0; + LJ::S2::load_layer_info($layinf, [$par]); + $name = $layinf->{$par}->{'name'}; + } + + # Only use the layer name if there is one and it's more than just whitespace + my $title = "[$type] "; + $title .= $name && $name =~ /[^\s]/ ? "$name [\#$id]" : "Layer \#$id"; + + return "" . LJ::ehtml($title) . " - Edit\n" . $ret; +} +_code?> diff --git a/livejournal/htdocs/customize/advanced/layers.bml b/livejournal/htdocs/customize/advanced/layers.bml new file mode 100755 index 0000000..3e1d00a --- /dev/null +++ b/livejournal/htdocs/customize/advanced/layers.bml @@ -0,0 +1,260 @@ +\n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "\n\n"; + }; + + # used for error messages + my $err = sub { + $title = "Error"; + $body = ''; + $authasform->() if $remote; + $body .= ""; + return; + }; + + # id is optional + my $id = $POST{'id'} if $POST{'id'} =~ /^\d+$/; + + # this catches core_hidden if it's set + $POST{'parid'} ||= $POST{'parid_hidden'}; + + # authenticate user + $remote = LJ::get_remote(); + return $err->('You must be logged in to view your layers.') + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + + # if we don't have a u, maybe they're an admin and can view stuff anyway? + my $noactions = 0; + if ($GET{user} && (LJ::check_priv($remote, 'canview', 'styles') || + LJ::check_priv($remote, 'canview', '*'))) { + return $err->('This privilege cannot be used on the system account.') + if $GET{user} eq 'system'; + $u = LJ::load_user($GET{user}); + $noactions = 1; # don't let admins change anything + } + return $err->('You could not be authenticated as the specified user.') + unless $u; + + # load user and public layers + my $pub = LJ::S2::get_public_layers(); + my $ulay = LJ::S2::get_layers_of_user($u); + + my $has_priv = LJ::get_cap($u, 's2styles'); + return $err->($remote->{user} eq $u->{user} ? + 'Your account type does not allow advanced customization.' : + 'The selected user\'s account type does not allow advanced customization.' ) + unless $has_priv; + + # start of output + $title = "Your Layers"; + $body .= BML::ml("backlink", { + 'link' => './', + 'text' => 'Advanced Customization', + }) . "\n"; + $body .= BML::ml("actionlink", { + 'link' => "Your Styles", + }) . "\n"; + + + ### perform actions ### + + # create + if ($POST{'action:create'} && !$noactions) { + return $err->("You have reached your maximum number of allowed layers") + if keys %$ulay >= LJ::get_cap($u, 's2layersmax'); + + my $err_badparid = "No/bogus parent layer ID given (for layouts and core languages, use core parent ID; for themes and layout languages, use layout ID)"; + my $type = $POST{'type'} or return $err->("No layer type selected."); + my $parid = $POST{'parid'}+0 or return $err->($err_badparid); + return $err->("Invalid layer type") unless $type =~ /^layout|theme|user|i18nc?$/; + my $parent_type = ($type eq "theme" || $type eq "i18n" || $type eq "user") ? "layout" : "core"; + + # parent ID is public layer + if ($pub->{$parid}) { + # of the wrong type + return $err->($err_badparid) if $pub->{$parid}->{'type'} ne $parent_type; + + # parent ID is user layer, or completely invalid + } else { + return $err->($err_badparid) if + ! $ulay->{$parid} || $ulay->{$parid}->{'type'} != $parent_type; + } + + my $id = LJ::S2::create_layer($u, $parid, $type); + return $err->("Error creating layer") unless $id; + + my $lay = { + 'userid' => $u->{'userid'}, + 'type' => $type, + 'b2lid' => $parid, + 's2lid' => $id, + }; + + # help user out a bit, creating the beginning of their layer. + my $s2 = "layerinfo \"type\" = \"$type\";\n"; + $s2 .= "layerinfo \"name\" = \"\";\n\n"; + my $error; + unless (LJ::S2::layer_compile($lay, \$error, { 's2ref' => \$s2 })) { + return $err->("Error setting up & compiling layer: $error"); + } + + # redirect so they can't refresh and create a new layer again + return BML::redirect("layers.bml?authas=$authas"); + } + + # delete + if ($POST{'action:del'} && !$noactions) { + my $id = $POST{'id'}+0; + my $lay = LJ::S2::load_layer($id); + return $err->("The specified layer does not exist") + unless $lay; + + return $err->("You do not own the specified layer") + unless $lay->{'userid'} == $u->{'userid'}; + + unless ($POST{'confirm'}) { + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $name = $layerinfo->{$id}->{'name'} ? "'$layerinfo->{$id}->{'name'}'" : "#$id"; + $name = LJ::ehtml($name); + + $title = "Deleting layer $name"; + $body .= "
    "; + $body .= BML::ml("backlink", { + 'link' => "layers.bml?authas=$authas", + 'text' => 'Your Layers', + }) . "\n"; + $body .= "
    "; + $body .= LJ::html_hidden('action:del', '1', 'id', $id); + + $body .= "Are you sure you want to delete $lay->{'type'} layer $name?"; + $body .= "

    " . LJ::html_submit('confirm', 'Delete') . "

    \n";; + $body .= "
    \n"; + return; + } + + LJ::S2::delete_layer($u, $id); + return BML::redirect("layers.bml?authas=$authas"); + } + + # authas switcher form + unless ($noactions) { + $authasform->(); + } + + # show list of layers + $body .= "\n"; + if (%$ulay) { + $body .= "\n"; + $body .= "\n"; + my $lastbase = 0; + foreach my $lid (sort { $ulay->{$a}->{'b2lid'} <=> $ulay->{$b}->{'b2lid'} || $a <=> $b } + keys %$ulay) + { + my $bid = $ulay->{$lid}->{'b2lid'}; + if ($bid != $lastbase) { + $lastbase = $bid; + my $parlay = $ulay->{$bid} || $pub->{$bid}; + my $pname = LJ::ehtml($parlay->{'name'}); + $body .= "\n"; + } + my $lay = $ulay->{$lid}; + my $name = LJ::ehtml($lay->{'name'}) || "(none)"; + $body .= "\n" + } + $body .= "
    LayerIDTypeNameActions
    Child of layer $bid: $pname
    $lid$lay->{'type'}$name"; + $body .= "
    "; + $body .= LJ::html_submit('action:edit', 'Edit...', { disabled => $noactions }); + $body .= "
    "; + + $body .= "
    "; + $body .= LJ::html_hidden('id', $lid); + $body .= LJ::html_submit('action:del', 'Delete...', { disabled => $noactions }); + $body .= "
    "; + $body .= "
    \n\n"; + } else { + $body .= "None p?>\n\n"; + } + + # jump out if we're just viewing + return if $noactions; + + # create layer + $body .= "\n"; + + $body .= "
    \n"; + $body .= "\n"; + $body .= "
    \n"; + + $body .= "Type: " . LJ::html_select({ 'name' => 'type' }, + "" => "", + "layout" => "Layout", + "i18nc" => "Language", + ) . "\n"; + + my @corelayers = map { $_, $pub->{$_}->{'majorversion'} } + sort { $pub->{$b}->{'majorversion'} <=> $pub->{$a}->{'majorversion'} } + grep { $pub->{$_}->{'b2lid'} == 0 && $pub->{$_}->{'type'} eq 'core' && /^\d+$/} + keys %$pub; + $body .= " Core Version: " . LJ::html_select({ 'name' => 'parid', + 'selected' => $corelayers[0], + 'disabled' => @corelayers > 2 ? 0: 1 }, + @corelayers ) . "\n"; + + # store value in hidden to later be copied to 'parid' if necessary + # defaults to $corelayers[0] which should be the highest numbered core + $body .= LJ::html_hidden("parid_hidden", $POST{'parid'} || $corelayers[0]) . "\n"; + $body .= LJ::html_submit("action:create", "Create") . "\n"; + $body .= "
    \n"; + $body .= "
    \n\n"; + + $body .= "\n"; + $body .= "
    \n"; + + $body .= "Type: " . LJ::html_select({ 'name' => 'type' }, + "" => "", + "theme" => "Theme", + "i18n" => "Language", + "user" => "User" + ) . "\n"; + + my @layouts = ('', ''); + push @layouts, map { $_, $pub->{$_}->{'name'} } + sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} || $a <=> $b} + grep { $pub->{$_}->{'type'} eq 'layout' && /^\d+$/} + keys %$pub; + if (%$ulay) { + my @ulayouts = (); + push @ulayouts, map { $_, "$ulay->{$_}->{'name'} (#$_)" } + sort { $ulay->{$a}->{'name'} cmp $ulay->{$b}->{'name'} || $a <=> $b} + grep { $ulay->{$_}->{'type'} eq 'layout' } + keys %$ulay; + push @layouts, ('', '---', @ulayouts) if @ulayouts; + } + + $body .= "Layout: " . LJ::html_select({ 'name' => 'parid' }, @layouts) . "\n"; + + $body .= LJ::html_submit("action:create", "Create") . "\n"; + $body .= "
    \n\n"; + + return; +} +_code?> +body=> +page?> + diff --git a/livejournal/htdocs/customize/advanced/layersource.bml b/livejournal/htdocs/customize/advanced/layersource.bml new file mode 100755 index 0000000..ca89b51 --- /dev/null +++ b/livejournal/htdocs/customize/advanced/layersource.bml @@ -0,0 +1,78 @@ +Error" . shift; + }; + + my $dbr = LJ::get_db_reader(); + my $remote = LJ::get_remote(); + + my $id = $GET{'id'}; + return BML::redirect('layerbrowse.bml') unless $id =~ /^\d+$/; + + my $lay = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id); + return $err->("The specified layer does not exist.") + unless $lay; + + my $layerinfo = {}; + LJ::S2::load_layer_info($layerinfo, [ $id ]); + my $srcview = exists $layerinfo->{$id}->{'source_viewable'} ? + $layerinfo->{$id}->{'source_viewable'} : undef; + + # authorized to view this layer? + my $isadmin = !defined $pub->{$id} && # public styles are pulled from the system + (LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges + LJ::check_priv($remote, 'canview', '*')); # in case they're private styles + return $err->("You are not authorized to view this layer.") + unless defined $pub->{$id} && (! defined $srcview || $srcview != 0) || + $srcview == 1 || + LJ::can_manage($remote, $lay->{'userid'}) || + $isadmin; + + my $s2code = $dbr->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $id); + + # get html version of the code? + if ($GET{'fmt'} eq "html") { + my $html; + my ($md5, $save_cache); + if ($pub->{$id}) { + # let's see if we have it cached + $md5 = Digest::MD5::md5_hex($s2code); + my $cache = $dbr->selectrow_array("SELECT value FROM blobcache WHERE bckey='s2html-$id'"); + if ($cache =~ s/^\[$md5\]//) { + $html = $cache; + } else { + $save_cache = 1; + } + } + + unless ($html) { + my $cr = new S2::Compiler; + $cr->compile_source({ + 'source' => \$s2code, + 'output' => \$html, + 'format' => "html", + 'type' => $pub->{$id}->{'type'}, + }); + } + + if ($save_cache) { + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO blobcache (bckey, dateupdate, value) VALUES (?,NOW(),?)", + undef, "s2html-$id", "[$md5]$html"); + } + return $html; + } + + # return text version + BML::set_content_type("text/plain"); + BML::noparse(); + return $s2code; +} +_code?> diff --git a/livejournal/htdocs/customize/advanced/styles.bml b/livejournal/htdocs/customize/advanced/styles.bml new file mode 100755 index 0000000..3ba568f --- /dev/null +++ b/livejournal/htdocs/customize/advanced/styles.bml @@ -0,0 +1,465 @@ +\n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "\n\n"; + }; + + # used for error messages + my $err = sub { + $title = "Error"; + $body = ''; + $authasform->() if $remote; + $body .= ""; + return; + }; + + # authenticate user + $remote = LJ::get_remote(); + return $err->('You must be logged in to view your styles.') + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->('You could not be authenticated as the specified user.') + unless $u; + + return $err->($remote->{user} eq $u->{user} ? + 'Your account type does not allow advanced customization.' : + 'The selected user\'s account type does not allow advanced customization.' ) + unless LJ::get_cap($u, 's2styles'); + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + my $getextra_amp = "&authas=$authas" if $getextra; + + # style id to edit, if we have one + # if we have this we're assumed to be in 'edit' mode + my $id = $GET{'id'}+0; + + my $dbh = LJ::get_db_writer(); + + # variables declared here, but only filled in if $id + my ($core, $layout); # scalars + my ($pub, $ulay, $style); # hashrefs + + # start of output + $title = "Styles"; + $body = BML::ml("backlink", { + 'link' => './', + 'text' => 'Advanced Customization', + }) . "\n"; + $body .= BML::ml("actionlink", { + 'link' => "Your Layers", + }) . "\n"; + + # edit mode + if ($id) { + + # load style + $style = LJ::S2::load_style($id); + return $err->('Style not found') unless $style; + + # check that they own the style + return $err->("You do not own this style.") + unless $style->{'userid'} == $u->{'userid'}; + + # use selected style + if ($POST{'action:usestyle'}) { + + # save to db and update user object + LJ::set_userprop($u, "stylesys", '2'); + LJ::set_userprop($u, "s2_style", $id); + return BML::redirect("styles.bml$getextra"); + } + + # get public layers + $pub = LJ::S2::get_public_layers(); + + # get user layers + $ulay = LJ::S2::get_layers_of_user($u); + + # find effective layerids being used + my %eff_layer = (); + my @other_layers = (); + foreach (qw(i18nc layout theme i18n user)) { + my $lid = $POST{$_} eq "_other" ? $POST{"other_$_"} : $POST{$_}; + next unless $lid; + $eff_layer{$_} = $lid; + + unless ($ulay->{$eff_layer{$_}} || $pub->{$eff_layer{$_}}) { + push @other_layers, $lid; + } + } + + # core lid (can't use user core layer) + $POST{'core'} ||= $POST{'core_hidden'}; + $core = defined $POST{'core'} ? $POST{'core'} : $style->{'layer'}->{'core'}; + unless ($core) { # default to highest numbered core + map { $core = $_ if $pub->{$_}->{'type'} eq 'core' && /^\d+$/ && + $pub->{$_}->{'majorversion'} > $pub->{$core}->{'majorversion'} } keys %$pub; + + # update in POST to keep things in sync + $POST{'core'} = $core; + } + + # layout lid + $layout = $POST{'action:change'} ? $eff_layer{'layout'} : $style->{'layer'}->{'layout'}; + + # if we're changing core, clear everything + if ($POST{'core'} && $style->{'layer'}->{'core'} && + $POST{'core'} != $style->{'layer'}->{'core'}) { + foreach (qw(i18nc layout theme i18n user)) { + delete $eff_layer{$_}; + } + undef $layout; + } + + # if we're changing layout, clear everything below + if ($eff_layer{'layout'} && $style->{'layer'}->{'layout'} && + $eff_layer{'layout'} != $style->{'layer'}->{'layout'}) { + foreach (qw(theme i18n user)) { + delete $eff_layer{$_}; + } + } + + # set up start of output + $title = "Edit Style"; + $body .= "
    " . BML::ml('backlink', { 'text' => 'Your Styles', 'link' => "styles.bml$getextra" }) . "\n"; + + ### process edit actions + + # delete + if ($POST{'action:delete'}) { + LJ::S2::delete_user_style($u, $id); + undef $id; # don't show form below + return BML::redirect("styles.bml$getextra"); + } + + # save changes + if ($POST{'action:change'} || $POST{'action:savechanges'}) { + + # are they renaming their style? + if ($POST{'stylename'} && $style->{'name'} && + $POST{'stylename'} ne $style->{'name'}) { + + # update db + my $styleid = $style->{'styleid'}; + $dbh->do("UPDATE s2styles SET name=? WHERE styleid=? AND userid=?", + undef, $POST{'stylename'}, $styleid, $u->{'userid'}); + LJ::MemCache::delete([$styleid, "s2s:$styleid"]); + + # update style object + $style->{'name'} = $POST{'stylename'}; + } + + # load layer info of any "other" layers + my %other_info = (); + if (@other_layers) { + LJ::S2::load_layer_info(\%other_info, \@other_layers); + foreach (@other_layers) { + return $err->("Layer not found: $_") unless exists $other_info{$_}; + return $err->("Layer not public: $_") unless $other_info{$_}->{'is_public'}; + } + } + + # error check layer modifications + my $get_layername = sub { + my $lid = shift; + + my $name; + $name = $pub->{$lid}->{'name'} if $pub->{$lid}; + $name ||= $ulay->{$lid}->{'name'} if $ulay->{$lid}; + $name ||= "#$lid"; + + return $name; + }; + + # check layer hierarchy + my $error_check = sub { + my ($type, $parentid) = @_; + + my $lid = $eff_layer{$type}; + next if ! $lid; + + my $layer = $ulay->{$lid} || $pub->{$lid} || LJ::S2::load_layer($lid); + my $parentname = $get_layername->($parentid); + my $layername = $get_layername->($lid); + + # is valid layer type? + return "Invalid layer type: $layername is not a $type layer" + if $layer->{'type'} ne $type; + + # is a child? + return "Layer hierarchy mismatch: $layername is not a child $type layer of $parentname" + unless $layer->{'b2lid'} == $parentid; + + return undef; + }; + + # check child layers of core + foreach my $type (qw(i18nc layout)) { + my $errmsg = $error_check->($type, $core); + return $err->($errmsg) if $errmsg; + } + + # don't check sub-layout layers if there's no layout + if ($layout) { + + # check child layers of selected layout + foreach my $type (qw(theme i18n user)) { + my $errmsg = $error_check->($type, $layout); + return $err->($errmsg) if $errmsg; + } + } + + # save in database + my @layers = ( 'core' => $core ); + push @layers, map { $_, $eff_layer{$_} } qw(i18nc layout i18n theme user); + LJ::S2::set_style_layers($u, $style->{'styleid'}, @layers); + + # redirect if they clicked the bottom button + return BML::redirect("styles.bml$getextra") if $POST{'action:savechanges'}; + } + + # no style id, process actions for non-edit mode + # and load in data necessary for style list + } else { + + # load user styles + my $ustyle = LJ::S2::load_user_styles($u); + + # process create action + if ($POST{'action:create'} && $POST{'stylename'}) { + + return $err->('You have reached your maximum number of styles.') + if scalar(keys %$ustyle) >= LJ::get_cap($u, 's2stylesmax'); + + my $styleid = LJ::S2::create_style($u, $POST{'stylename'}); + return $err->('Style not created: Database error') unless $styleid; + + return BML::redirect("styles.bml?id=$styleid$getextra_amp"); + } + + # load style currently in use + LJ::load_user_props($u, 's2_style'); + + # set up page header + $title = "Your Styles"; + + $authasform->(); + + $body .= "
    \n"; + + # show style listing + $body .= "\n"; + if (%$ustyle) { + my $journalbase = LJ::journal_base($u); + foreach my $styleid (sort { $ustyle->{$a} cmp $ustyle->{$b} || $a <=> $b} keys %$ustyle) { + $body .= "\n"; + } + } else { + $body .= "\n"; + } + $body .= "
    "; + my @b = $styleid == $u->{'s2_style'} ? "" : ""; + $body .= $b[0] . LJ::ehtml($ustyle->{$styleid}); + $body .= " (\#$styleid)$b[1] "; + $body .= "
    "; + $body .= LJ::html_submit('action:edit', 'Edit') . " "; + $body .= LJ::html_submit('action:delete', 'Delete', + { 'onclick' => "return confirm('Are you sure you want to delete style \#$styleid?')" }) . " "; + $body .= LJ::html_submit('action:usestyle', 'Use', { 'disabled' => $styleid == $u->{'s2_style'} }), + $body .= "
    none
    \n"; + } + + + ### show create / edit form + + my $extra = $id ? "?id=$id" : ''; + $extra .= $extra ? $getextra_amp : $getextra; + $body .= "
    "; + + # create a new style, or change the name of the style currently being edited + # note: this little bit of code appears whether there is an id passed or not. + # the textbox just has a different purpose depending on the context. + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Name: "; + $body .= LJ::html_text({ 'name' => 'stylename', 'size' => '30', 'maxlength' => '255', + 'value' => defined $POST{'stylename'} ? $POST{'stylename'} : $style->{'name'} }); + $body .= " " . LJ::html_submit('action:create', 'Create') unless $id; + $body .= "
    \n"; + + # if no id to edit, we're finished + $body .= "
    \n", return unless $id; + + # from here on we have $pub, $ulay, and $style filled in + + # sub to take a layer type, core, and parent layout + # and return a list of options to feed to LJ::html_select() + my $layerselect = sub { + my ($type, $b2lid) = @_; + + my @opts = (); + + # returns html_select to caller + my $html_select = sub { + my $dis = scalar(@opts) > 2 ? 0 : 1; + + my $lid = $POST{'action:change'} ? $POST{$type} : $style->{'layer'}->{$type}; + $lid = $POST{"other_$type"} if $lid eq "_other"; + my $sel = ($lid && ! $pub->{$lid} && ! $ulay->{$lid}) ? "_other" : $lid; + return [ LJ::html_select({ 'name' => $type, 'id' => "select_$type", + 'onChange' => "showOther('$type')", + 'selected' => $sel, + 'disabled' => $dis }, @opts), { 'disabled' => $dis, } ]; + }; + + # greps, and sorts a list + my $greplist = sub { + my $ref = shift; + return sort { $ref->{$a}->{'name'} cmp $ref->{$b}->{'name'} || $a <=> $b} + grep { $ref->{$_}->{'type'} eq $type && $ref->{$_}->{'b2lid'} == $b2lid && /^\d+$/} + keys %$ref; + }; + + # public layers + my $name = $type eq 'core' ? 'majorversion' : 'name'; + push @opts, map { $_, $pub->{$_}->{$name} } $greplist->($pub); + + # no user core layers + return $html_select->() if $type eq 'core'; + + # user layers + push @opts, ('', '---'); + my $startsize = scalar(@opts); + push @opts, map { $_, "$ulay->{$_}->{'name'} (\#$_)" } $greplist->($ulay); + + # if we didn't push anything above, remove dividing line + pop @opts, pop @opts unless scalar(@opts) > $startsize; + + # add option for other layerids + push @opts, ('_other', 'Other ...'); + + # add blank option to beginning of list + unshift @opts, ('', @opts ? '' : ' '); + + return $html_select->(); + }; + + my $layerother = sub { + my $name = shift; + + my $olid = $POST{'action:change'} ? $POST{"other_$name"} : $style->{'layer'}->{$name}; + my $disp = 'none'; + my $val; + if ($olid && ! $pub->{$olid} && ! $ulay->{$olid}) { + $disp = 'inline'; + $val = $olid; + } + + return "
    Layerid: " . + LJ::html_text({ 'name' => "other_$name", 'id' => "other_$name", + 'size' => 6, 'value' => $val }) . + "
    "; + }; + + ### core version + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Core Version: "; + my $coresel = $layerselect->('core', 0); + $body .= $coresel->[0]; + $body .= LJ::html_hidden('core_hidden', $core); + my $dis = $coresel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef; + $body .= " " . LJ::html_submit('action:change', 'Change', $dis) . "
    \n"; + + ### i18nc / layout + + $body .= "\n"; + + # i18nc + $body .= "\n"; + + # layout + $body .= "\n"; + $body .= "
    Language (i18nc): "; + $body .= $layerselect->('i18nc', $core)->[0]; + $body .= $layerother->('i18nc'); + $body .= "
    Layout: "; + my $layoutsel = $layerselect->('layout', $core); + $body .= $layoutsel->[0]; + $body .= $layerother->('layout'); + my $dis = $layoutsel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef; + $body .= " " . LJ::html_submit("action:change", "Change", $dis) . "
    \n"; + + # do we need to show the rest of the form? + $body .= "\n", return unless $layout; + + ### theme / i18n / user + + # theme + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "
    Language (i18n): "; + $body .= $layerselect->('i18n', $layout)->[0]; + $body .= $layerother->('i18n') . "
    Theme: "; + $body .= $layerselect->('theme', $layout)->[0]; + $body .= $layerother->('theme') . "
    User: "; + $body .= $layerselect->('user', $layout)->[0]; + $body .= $layerother->('user') . "
     "; + $body .= LJ::html_submit('action:savechanges', 'Save Changes') . "
    \n"; + + # end edit form + $body .= "\n"; + + return; +} +_code?> +head<= + +<=head +body=> +bodyopts=>onLoad="pageload();" +page?> + diff --git a/livejournal/htdocs/customize/index.bml b/livejournal/htdocs/customize/index.bml new file mode 100755 index 0000000..a0b4eae --- /dev/null +++ b/livejournal/htdocs/customize/index.bml @@ -0,0 +1,361 @@ + +head<= + +<=head + +body<= +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my $userid = $u->{'userid'}; + my $has_cap = LJ::get_cap($u, "s2styles"); + + return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly"); + + my $ret; + + # authas switcher form + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} || $GET{'journal'} }) . "\n"; + $ret .= "
    \n\n"; + + LJ::load_user_props($u, "stylesys", "s2_style"); + $u->{'stylesys'} ||= 1; + + my $pub = LJ::S2::get_public_layers(); + my $userlay = LJ::S2::get_layers_of_user($u); + my %style = LJ::S2::get_style($u, "verify"); + + my $get_lang = sub { + my $styleid = shift; + foreach ($userlay, $pub) { + return $_->{$styleid}->{'langcode'} if + $_->{$styleid} && $_->{$styleid}->{'langcode'}; + } + return undef; + }; + my $langcode = $get_lang->($style{'i18n'}) || $get_lang->($style{'i18nc'}); + + if ($POST{'save:stylesys'}) { + my $num = $POST{'stylesys'} == 2 ? 2 : 1; + LJ::set_userprop($u, "stylesys", $num); + return BML::redirect("/customize/?journal=$u->{'user'}"); + } + + my $implicit_style_create = sub { + + # create new style if necessary + unless ($u->{'s2_style'}) { + my $layid = $style{'layout'}; + my $lay = $pub->{$layid} || $userlay->{$layid}; + my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'}; + + unless ($u->{'s2_style'} = LJ::S2::create_style($u, "wizard-$uniq")) { + die ""; + } + LJ::set_userprop($u, "s2_style", $u->{'s2_style'}); + } + + # save values in %style to db + LJ::S2::set_style_layers($u, $u->{'s2_style'}, %style); + }; + + if ($POST{'save:layout'}) { + my $layid = $POST{'layoutid'}+0; + return BML::redirect("/customize/?journal=$u->{'user'}") + if $layid == $style{'layout'}; + + my $lay = $pub->{$layid}; + return "" + if ! $lay and $lay ||= $userlay->{$layid} and ! $has_cap; + return "" + unless $lay && LJ::S2::can_use_layer($u, $lay->{'uniq'}); + + my $coreid = $lay->{'b2lid'}; + return "" + unless $coreid; + + # delete s2_style and replace it with a new + # or existing style for this layout + delete $u->{'s2_style'}; + + my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'}; + my $usersty = LJ::S2::load_user_styles($u); + foreach (keys %$usersty) { + next unless $usersty->{$_} eq "wizard-$uniq"; + + $u->{'s2_style'} = $_; + LJ::set_userprop($u, "s2_style", $u->{'s2_style'}); + + # now we have to populate %style from this style, but not core and layout, + # as those are reset below + my $stylay = LJ::S2::get_style_layers($u, $u->{'s2_style'}); + foreach my $layer (qw(user theme i18nc i18n)) { + $style{$layer} = exists $stylay->{$layer} ? $stylay->{$layer} : 0; + } + + last; + } + + # no existing style found, create a new one + unless ($u->{'s2_style'}) { + $style{'user'} = $style{'theme'} = $style{'i18nc'} = $style{'i18n'} = 0; + } + + # even if we're using an existing style that we found by name (uniq), we need to + # set layout and core layers to make sure the style still has the proper layout + $style{'layout'} = $layid; + $style{'core'} = $coreid; + + $implicit_style_create->(); + + return BML::redirect("/customize/?journal=$u->{'user'}"); + } + + if ($POST{'action:deluser'}) { + LJ::S2::delete_layer($style{'user'}); + LJ::S2::set_style_layers($u, $u->{'s2_style'}, "user", 0) if $style{'user'}; + return BML::redirect("/customize/?journal=$u->{'user'}"); + } + + if ($POST{'action:edituser'}) { + + unless ($style{'user'}) { + $style{'user'} = LJ::S2::create_layer($u, $style{'layout'}, "user"); + return " " + unless $style{'user'}; + } + + $implicit_style_create->(); + + return BML::redirect("/customize/layer.bml?w=user&journal=$authas"); + } + + if ($POST{'save:theme'}) { + my $themeid = $POST{'themeid'}+0; + return BML::redirect("/customize/?journal=$u->{'user'}") + if $themeid == $style{'theme'}; + + my $lay = $pub->{$themeid}; + return "" + if ! $lay and $lay ||= $userlay->{$themeid} and ! $has_cap; + return "" if $themeid && ! $lay; + $style{'theme'} = $themeid; + + $implicit_style_create->(); + + # TODO: conflict resolution. check if there + # exists a user layer, and ask user if they want to + # override it using the theme exclusively. + return BML::redirect("/customize/?journal=$u->{'user'}"); + } + + if ($POST{'save:langcode'}) { + my $langcode = $POST{'langcode'}; + return BML::redirect("/customize/?journal=$u->{'user'}") + if $langcode eq 'custom'; + + my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'}); + my ($i18n, $i18nc); + + # scan for an i18n user layer + foreach (values %$userlay) { + last if + $_->{'b2lid'} == $style{'layout'} && + $_->{'type'} eq 'i18n' && + $_->{'langcode'} eq $langcode && + ($i18n = $_->{'s2lid'}); + } + + # scan for i18nc public layer and i18n layer if necessary + foreach (values %$pub) { + last if $i18nc && $i18n; + + next if + ! $i18nc && + $_->{'type'} eq 'i18nc' && + $_->{'langcode'} eq $langcode && + ($i18nc = $_->{'s2lid'}); + + next if + ! $i18n && + $_->{'b2lid'} == $style{'layout'} && + $_->{'type'} eq 'i18n' && + $_->{'langcode'} eq $langcode && + ($i18n = $_->{'s2lid'}); + } + + $style{'i18nc'} = $i18nc; + $style{'i18n'} = $i18n; + + $implicit_style_create->(); + + # TODO: conflict resolution. check if there + # exists a user layer, and ask user if they want to + # override it using the theme exclusively. + return BML::redirect("/customize/?journal=$u->{'user'}"); + } + + # choose style system + $ret .= "
    "; + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_select({ 'name' => 'stylesys', 'selected' => $u->{'stylesys'} }, + 1, "$ML{'.choose.s1'}", + 2, "$ML{'.choose.s2'}"); + $ret .= " "; + $ret .= "
    "; + + # no more options if they're using S1. + if ($u->{'stylesys'} == 1) { + $ret .= " "href='$LJ::SITEROOT/modify.bml?authas=$authas'" }); + $ret .= " p?>
    "; + return $ret; + } + + # choose layout + my @layouts = map { $_, $pub->{$_}->{'name'} } + sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} } + grep { my $tmp = $_; + $tmp =~ /^\d+$/ && + $pub->{$tmp}->{'type'} eq "layout" && + LJ::S2::can_use_layer($u, $pub->{$tmp}->{'uniq'}) && + ($_ = $tmp) + } keys %$pub; + + # custom layers can will be shown in the "Custom Layers" and "Disabled Layers" groups + # depending on the user's account status. if they don't have the s2styles cap, then + # they will have all layers disabled, except for the one they are currently using. + my $custom_layer_list = sub { + my ($type, $ptype) = @_; + my @layers = (); + + my @user = map { $_, $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_" } + sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} || $a <=> $b } + grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} && + $userlay->{$_}->{'type'} eq $type && + ($has_cap || $_ == $style{$type}) } + keys %$userlay; + if (@user) { + push @layers, { value => "", + text => "--- Custom Layers: ---", + disabled => 1 }, @user; + } + + unless ($has_cap) { + my @disabled = + map { { value => $_, + text => $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_", + disabled => 1 } } + sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} || + $userlay->{$a}->{'s2lid'} <=> $userlay->{$b}->{'s2lid'} } + grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} && + $userlay->{$_}->{'type'} eq $type && $_ != $style{$type} } + keys %$userlay; + if (@disabled) { + push @layers, { value => "", + text => "--- Disabled Layers: ---", + disabled => 1 }, @disabled; + } + } + + return @layers; + }; + + # add user/disabled ones + push @layouts, $custom_layer_list->('layout', 'core'); + + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_select({ 'name' => 'layoutid', + 'selected' => $style{'layout'}, }, + @layouts); + $ret .= " {'user'}\">$ML{'.previews'}"; + $ret .= "
    "; + + # pick other stuff + $ret .= ""; + $ret .= ""; + + # langauge + my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'}); + + # they have set a custom i18n layer + if ($style{'i18n'} && + ($style{'i18nc'} != $style{'i18n'} || ! defined $pub->{$style{'i18n'}})) { + push @langs, 'custom', $ML{'.s2.customize.language.custom'}; + $langcode = 'custom'; + } + + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_select({ 'name' => 'langcode', + 'selected' => $langcode, }, + 0 => $ML{'.s2.customize.language.default'}, + @langs); + $ret .= " "; + $ret .= "
    "; + + # theme + my @themes = LJ::S2::get_layout_themes_select([$pub], $style{'layout'}); + + # add user/disabled ones + push @themes, $custom_layer_list->('theme', 'layout'); + + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_select({ 'name' => 'themeid', + 'selected' => $style{'theme'}, }, + '0' => $ML{'.s2.customize.themes.default'}, + @themes); + $ret .= " {'user'}\">$ML{'.previews'}"; + $ret .= "
    "; + + # customize + $ret .= ""; + $ret .= "
    "; + if ($style{'user'}) { + $ret .= LJ::html_submit('action:edituser', $ML{'.s2.customize.settings.edit'}); + $ret .= LJ::html_submit('action:deluser', $ML{'.s2.customize.settings.delete'}, + { 'onclick' => "return confirm('" . LJ::ejs($ML{'.s2.customize.settings.delete.confirm'}) . "')" }); + } else { + $ret .= "\n"; + } + $ret .= "
    "; + + $ret .= ""; + + $ret .= ""; + $ret .= "
    $ML{'.s2.advanced.header'}
    "; + $ret .= $has_cap ? $ML{'.s2.advanced.permitted'} : $ML{'.s2.advanced.denied'}; + $ret .= "
    $ML{'/manage/links.bml.title'}
    $ML{'.s2.related.links.about'}
    "; + $ret .= "
    $ML{'/modify.bml.title'}
    $ML{'.s2.related.modify.about'}
    "; + $ret .= "
    $ML{'/editinfo.bml.title'}
    $ML{'.s2.related.editinfo.about'}
    "; + + return $ret; +} +_code?> +<=body +head<= + +<=head +page?> diff --git a/livejournal/htdocs/customize/layer.bml b/livejournal/htdocs/customize/layer.bml new file mode 100755 index 0000000..16d094b --- /dev/null +++ b/livejournal/htdocs/customize/layer.bml @@ -0,0 +1,438 @@ +login. p?>" + unless $remote; + + my @journals = ($remote->{'user'}); + push @journals, LJ::get_shared_journals($remote); + my $journal = $GET{'journal'} || $remote->{'user'}; + unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); } + + my $u = $remote; + $u = LJ::load_user($journal) unless $journal eq $remote->{'user'}; + my $userid = $u->{'userid'}; + + LJ::load_user_props($u, "stylesys", "s2_style"); + + $body = ""; + $title = "Customize"; + $js = ""; + + my $err = sub { + $title = "Error"; + $body = shift; + return; + }; + + my ($style, $layer); + my $save_arg; + my $save_redir; + + # when given 'w' argument, load user's current style, and edit the user layer. + # this is the mode redirected to from /customize/ (the simple customization UI) + if ($GET{'w'} eq "user" && $u->{'stylesys'} == 2) + { + $style = LJ::S2::load_style($u->{'s2_style'}); + return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'}; + $layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'}); + + # if the b2lid of this layer has been remapped to a new layerid + # then update the b2lid mapping for this layer + my $b2lid = $layer->{b2lid}; + if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) { + LJ::S2::b2lid_remap($u, $style->{'layer'}->{'user'}, $b2lid); + $layer->{b2lid} = $LJ::S2LID_REMAP{$b2lid}; + } + + $save_arg = "w=user&journal=$journal"; + $save_redir = "/customize/?journal=$journal"; + } + + return BML::redirect("/customize/") unless $layer; + return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'}; + return $err->("Layer isn't of type user or theme.") + unless $layer->{'type'} eq "user" || $layer->{'type'} eq "theme"; + + my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'}); + return $err->("Layout layer for this $layer->{'type'} layer not found.") + unless $lyr_layout; + my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'}); + return $err->("Core layer for layout not found.") + unless $lyr_core; + + $lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?", + undef, $lyr_layout->{'s2lid'}, "redist_uniq"); + + my ($lid_i18nc, $lid_theme, $lid_i18n); + $lid_i18nc = $style->{'layer'}->{'i18nc'}; + $lid_theme = $style->{'layer'}->{'theme'}; + $lid_i18n = $style->{'layer'}->{'i18n'}; + + my $layerid = $layer->{'s2lid'}; + + my @layers; + push @layers, ([ 'core' => $lyr_core->{'s2lid'} ], + [ 'i18nc' => $lid_i18nc ], + [ 'layout' => $lyr_layout->{'s2lid'} ], + [ 'i18n' => $lid_i18n ]); + if ($layer->{'type'} eq "user" && $lid_theme) { + push @layers, [ 'theme' => $lid_theme ]; + } + push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ]; + + my @layerids = grep { $_ } map { $_->[1] } @layers; + LJ::S2::load_layers(@layerids); + + my %layerinfo; + + # load the language and layout choices for core. + LJ::S2::load_layer_info(\%layerinfo, \@layerids); + + # action path + if (LJ::did_post()) { + # prevent spoofing: + return BML::redirect("/customize") + unless $POST{'userid'} == $u->{'userid'}; + + my %override; + foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'})) + { + $prop = S2::get_property($lyr_core->{'s2lid'}, $prop) + unless ref $prop; + next unless ref $prop; + next if $prop->{'noui'}; + my $name = $prop->{'name'}; + next unless $POST{"$name:override"}; + next unless LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name); + $override{$name} = [ $prop, $POST{"${name}_value"} ]; + } + + if (LJ::S2::layer_compile_user($layer, \%override)) { + return BML::redirect($save_redir) if $save_redir; + $body = "Saved."; + return; + } else { + my $error = LJ::last_error(); + $body = "Error saving layer:
    $error
    "; + } + return; + } + + $body .= "
    "; + $body .= LJ::html_hidden("userid", $u->{'userid'}); + + my %prop; # name -> hashref, deleted when added to a category + my @propnames; + foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'})) { + unless (ref $prop) { + $prop = S2::get_property($lyr_core->{'s2lid'}, $prop); + next unless ref $prop; + } + $prop{$prop->{'name'}} = $prop; + push @propnames, $prop->{'name'}; + } + + my @groups = S2::get_property_groups($lyr_layout->{'s2lid'}); + my $misc_group; + my %groupprops; # gname -> [ propname ] + my %propgroup; # pname -> gname; + + foreach my $gname (@groups) { + if ($gname eq "misc" || $gname eq "other") { $misc_group = $gname; } + foreach my $pname (S2::get_property_group_props($lyr_layout->{'s2lid'}, $gname)) { + my $prop = $prop{$pname}; + next if ! $prop || $propgroup{$pname}; + $propgroup{$pname} = $gname; + push @{$groupprops{$gname}}, $pname; + } + } + # put unsorted props into an existing or new unsorted/misc group + if (@groups) { + my @unsorted; + foreach my $pname (@propnames) { + my $prop = $prop{$pname}; + next if ! $prop || $propgroup{$pname}; + push @unsorted, $pname; + } + if (@unsorted) { + unless ($misc_group) { + $misc_group = "misc"; + push @groups, "misc"; + } + push @{$groupprops{$misc_group}}, @unsorted; + } + } + + my $group_name = sub { + my $gname = shift; + foreach my $lid ($lid_i18n, $lyr_layout->{'s2lid'}, $lid_i18nc, $lyr_core->{'s2lid'}) { + next unless $lid; + my $name = S2::get_property_group_name($lid, $gname); + return LJ::ehtml($name) if $name; + } + return "Misc" if $gname eq "misc"; + return $gname; + }; + + my $prop_js = ""; + my $output_prop = sub { + my $name = shift; + my $prop = $prop{$name}; + return if ! $prop || $prop->{'noui'}; + + my $name = $prop->{'name'}; + my $type = $prop->{'type'}; + + my $can_use = LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name); + + # figure out existing value (if there was no user/theme layer) + my $existing; + foreach my $lid (reverse @layerids) { + next if $lid == $layerid; + $existing = S2::get_set($lid, $name); + last if defined $existing; + } + + if (ref $existing eq "HASH") { $existing = $existing->{'as_string'}; } + + if ($type eq "bool") { + $prop->{'values'} ||= "1|Yes|0|No"; + } + + my %values = split(/\|/, $prop->{'values'}); + my $existing_display = defined $values{$existing} ? + $values{$existing} : $existing; + + $existing_display = LJ::eall($existing_display); + + my $override = S2::get_set($layerid, $name); + my $had_override = defined $override; + $override = $existing unless defined $override; + + if (ref $override eq "HASH") { $override = $override->{'as_string'}; } + + $body .= "{'des'}) . " h1?>"; + { + my $t = ""; + $t .= LJ::eall($prop->{'note'}) if $prop->{'note'}; + $t .= "" if $LJ::HELPURL{"s2opt_$name"}; + $body .= "" if $t; + } + $body .= "
    \n"; + $body .= LJ::html_check({ 'name' => "$name:override", 'id' => "$name:override", + 'selected' => $had_override, 'disabled' => ! $can_use, + 'onchange' => "toggleOverride('$name');" }); + my $offhelp = ! $can_use ? LJ::help_icon('s2propoff', ' ') : ""; + $body .= "$offhelp
    \n"; + $body .= "
    \n
    Default:
    \n
    \n"; + if ($type eq "int" || $type eq "string") { + if ($existing_display ne "") { + $body .= $existing_display; + } else { + $body .= "(nothing)"; + } + } elsif ($type eq "Color") { + $body .= "  $existing_display"; + } elsif ($type eq "bool") { + $body .= $existing_display; + } + $body .= "
    \n
    Override:
    \n
    \n"; + if ($prop->{'values'}) { + $body .= LJ::html_select({ 'name' => "${name}_value", + 'disabled' => ! $can_use, + 'selected' => $override }, + split(/\|/, $prop->{'values'})); + } elsif ($type eq "int") { + $body .= LJ::html_text({ 'name' => "${name}_value", + 'disabled' => ! $can_use, + 'value' => $override, + 'maxlength' => 5, + 'size' => 7 }); + } elsif ($type eq "string") { + my ($rows, $cols) = ($prop->{'rows'} + 0, + $prop->{'cols'} + 0); + if ($rows > 0 && $cols > 0) { + $body .= LJ::html_textarea({ 'name' => "${name}_value", + 'disabled' => ! $can_use, + 'value' => $override, + 'onfocus' => "toggleOverride('$name');", + 'rows' => $rows, + 'cols' => $cols }); + } else { + my ($size, $maxlength) = ($prop->{'size'} || 30, + $prop->{'maxlength'} || 255); + $body .= LJ::html_text({ 'name' => "${name}_value", + 'disabled' => ! $can_use, + 'value' => $override, + 'maxlength' => $maxlength, + 'size' => $size }); + } + } elsif ($type eq "Color") { + $body .= LJ::html_color({ 'name' => "${name}_value", + 'disabled' => ! $can_use, + 'default' => $override, + 'des' => $prop->{'des'} }); + } + $body .= "
    \n
    \n"; + $prop_js .= "toggleOverride('$name');\n"; + }; + + if (@groups) { + $body .= "
    "; + my $num = 0; + foreach my $gname (@groups) { + my $name = $group_name->($gname); + $num++; + my $class = $num == 1 ? "propgrouptabsel" : "propgrouptab"; + $js .= " propgroups[$num] = \"$gname\";\n"; + $body .= "$name\n"; + } + $body .= "
    "; + $body .= "
    "; + + + foreach my $gname (@groups) { + $body .= "\n"; + $body .= "
    \n"; + foreach my $pname (@{$groupprops{$gname}}) { + $output_prop->($pname); + } + $body .= "
    "; + } + $body .= "
    \n"; + + $body .= "\n"; + + } else { + foreach my $pname (@propnames) { + $output_prop->($pname); + } + } + + $body .= ""; + + $body .= "
    "; + $body .= LJ::html_submit('action:save', "Save"); + $body .= "
    "; + + $body .= "
    "; + + return; + +} +_code?> +body=> +head<= + + + + + + + +<=head +page?> diff --git a/livejournal/htdocs/customize/preview.bml b/livejournal/htdocs/customize/preview.bml new file mode 100755 index 0000000..5a689e6 --- /dev/null +++ b/livejournal/htdocs/customize/preview.bml @@ -0,0 +1,39 @@ +Layout Previews +body<= +[<< Back]

    "; + + my $pub = LJ::S2::get_public_layers(); + + my @layouts = + sort { $a->{'name'} cmp $b->{'name'} } + map { $pub->{$_} } grep { /^\d+$/ && $pub->{$_}->{'type'} eq "layout" } keys %$pub; + + foreach my $l (@layouts) { + $ret .= "{'name'}) . " h1?>"; + unless ($l->{'_previews'}) { + $ret .= "No preview available. p?>"; + next; + } + foreach (split(/\,/, $l->{'_previews'})) { + my ($img, $w, $h) = split(/\|/, $_); + $ret .= "

    "; + } + } + + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/customize/themes.bml b/livejournal/htdocs/customize/themes.bml new file mode 100755 index 0000000..08136e2 --- /dev/null +++ b/livejournal/htdocs/customize/themes.bml @@ -0,0 +1,79 @@ +Theme Previews +body<= +login. p?>" + unless $remote; + + my @journals = ($remote->{'user'}); + push @journals, LJ::get_shared_journals($remote); + my $journal = $GET{'journal'} || $remote->{'user'}; + unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); } + + $ret .= "

    [<< Back]

    "; + + my $u = $remote; + $u = LJ::load_user($journal) unless $journal eq $remote->{'user'}; + my $userid = $u->{'userid'}; + + LJ::load_user_props($u, "stylesys", "s2_style"); + $u->{'stylesys'} ||= 1; + my $pub = LJ::S2::get_public_layers(); + my $userlay = {}; # TODO: add API call to fetch these + my %style = LJ::S2::get_style($u->{'s2_style'}); + + return "S2 required" unless $u->{'stylesys'} == 2 && $style{'layout'}; + + # get themes for this layer + my @themes = LJ::S2::get_layout_themes([$pub, $userlay], $style{'layout'}); + + # make the context, without the theme + my @layers; + foreach (qw(core i18nc layout i18n)) { + push @layers, $style{$_} if $style{$_}; + } + LJ::S2::load_layers(@layers, map { $_->{'s2lid'} } @themes); + + my $cleaner = new HTMLCleaner ('output' => sub { $ret .= $_[0]; }); + my $out_straight = sub { $ret .= $_[0]; }; + my $out_clean = sub { $cleaner->parse($_[0]); }; + + $LJ::S2::CURR_PAGE = undef; + + foreach my $t (0, @themes) { + my $id = ref $t ? $t->{'s2lid'} : 0; + my $name = ref $t ? LJ::eall($t->{'name'}) : "Layout Default"; + my $ctx = S2::make_context(@layers, $id); + LJ::S2::escape_context_props($ctx); + LJ::S2::populate_system_props($ctx); + + S2::set_output(sub {}); # printing suppressed + S2::set_output_safe(sub {}); + eval { S2::run_code($ctx, "prop_init()"); }; + S2::set_output($out_straight); + S2::set_output_safe($out_straight); + $ret .= ""; + $ret .= "
    "; + eval { S2::run_code($ctx, "print_theme_preview()"); }; + $ret .= "
    "; + + } + $cleaner->eof if $cleaner; # flush any remaining text/tag not yet spit out + + return $ret; + +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/customize/viewuser.bml b/livejournal/htdocs/customize/viewuser.bml new file mode 100755 index 0000000..230374e --- /dev/null +++ b/livejournal/htdocs/customize/viewuser.bml @@ -0,0 +1,159 @@ +login. p?>" + unless $remote; + + my @journals = ($remote->{'user'}); + push @journals, LJ::get_shared_journals($remote); + my $journal = $GET{'journal'} || $remote->{'user'}; + unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); } + + my $u = $remote; + $u = LJ::load_user($journal) unless $journal eq $remote->{'user'}; + my $userid = $u->{'userid'}; + + LJ::load_user_props($u, "stylesys", "s2_style"); + + $body = ""; + $title = "User Layer"; + + if (@journals > 1) { + $body .= "
    "; + $body .= "Work with journal: "; + $body .= LJ::html_select({ + 'name' => 'journal', + 'selected' => $journal, + }, map { $_, $_ } @journals); + $body .= "
    "; + } + + $body .= "<< customize

    "; + + my $err = sub { + $title = "Error"; + $body = shift; + return; + }; + + my ($style, $layer); + my $save_arg; + my $save_redir; + + # when given 'w' argument, load user's current style, and edit the user layer. + # this is the mode redirected to from /customize/ (the simple customization UI) + if ($u->{'stylesys'} == 2) + { + $style = LJ::S2::load_style($u->{'s2_style'}); + return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'}; + $layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'}); + } + + unless ($layer) { + $body .= "No user layer"; + return; + } + + return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'}; + return $err->("Layer isn't of type user or theme.") + unless $layer->{'type'} eq "user"; + + my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'}); + return $err->("Layout layer for this $layer->{'type'} layer not found.") + unless $lyr_layout; + my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'}); + return $err->("Core layer for layout not found.") + unless $lyr_core; + + $lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?", + undef, $lyr_layout->{'s2lid'}, "redist_uniq"); + + my ($lid_i18nc, $lid_theme, $lid_i18n); + $lid_i18nc = $style->{'layer'}->{'i18nc'}; + $lid_theme = $style->{'layer'}->{'theme'}; + $lid_i18n = $style->{'layer'}->{'i18n'}; + + my $layerid = $layer->{'s2lid'}; + + my @layers; + push @layers, ([ 'core' => $lyr_core->{'s2lid'} ], + [ 'i18nc' => $lid_i18nc ], + [ 'layout' => $lyr_layout->{'s2lid'} ], + [ 'i18n' => $lid_i18n ]); + if ($layer->{'type'} eq "user" && $lid_theme) { + push @layers, [ 'theme' => $lid_theme ]; + } + push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ]; + + my @layerids = grep { $_ } map { $_->[1] } @layers; + LJ::S2::load_layers(@layerids); + + my %layerinfo; + + # load the language and layout choices for core. + LJ::S2::load_layer_info(\%layerinfo, \@layerids); + + $body .= "Raw | "; + $body .= "As Theme\n"; + + $body .= "

    "; + + return; + +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/delcomment.bml b/livejournal/htdocs/delcomment.bml new file mode 100755 index 0000000..359ef01 --- /dev/null +++ b/livejournal/htdocs/delcomment.bml @@ -0,0 +1,174 @@ +1 +_info?>"; + return; + }; + my $bad_input = sub { + return $error->("Bad input: $_[0]") if $jsmode; + $body = LJ::bad_input($_[0]); + return; + }; + + LJ::set_active_crumb('delcomment'); + + my $remote = LJ::get_remote(); + return $bad_input->($ML{'error.noremote'}) + unless $remote; + + return $error->("Missing parameters.") unless $GET{'journal'} ne "" && $GET{'id'}; + + # $u is user object of journal that owns the talkpost + my $u = LJ::load_user($GET{'journal'}); + return $bad_input->($ML{'error.nojournal'}) + unless $u; + + # can't delete if you're suspended + return $bad_input->($ML{'.error.suspended'}) + if $remote->{statusvis} eq 'S'; + + return $error->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + return $error->($ML{'error.nodb'}) + unless $dbcr; + + # $tp is a hashref of info about this individual talkpost row + my $tpid = $GET{'id'} >> 8; + my $tp = $dbcr->selectrow_hashref("SELECT jtalkid AS 'talkid', nodetype, state, " . + "nodeid AS 'itemid', parenttalkid, journalid, posterid " . + "FROM talk2 ". + "WHERE journalid=? AND jtalkid=?", + undef, $u->{'userid'}, $tpid); + + return $bad_input->($ML{'.error.nocomment'}) + unless $tp; + + return $bad_input->($ML{'.error.invalidtype'}) + unless $tp->{'nodetype'} eq 'L'; + + return $bad_input->($ML{'.error.alreadydeleted'}) + if $tp->{'state'} eq "D"; + + # get username of poster + $tp->{'userpost'} = LJ::get_username($tp->{'posterid'}); + + # userid of user who posted journal entry + my $jposterid = $dbcr->selectrow_array("SELECT posterid FROM log2 WHERE " . + "journalid=? AND jitemid=?", + undef, $u->{'userid'}, $tp->{'itemid'}); + my $jposter = LJ::load_userid($jposterid); + + # can $remote delete this comment? + unless (LJ::Talk::can_delete($remote, $u, $jposter, $tp->{'userpost'})) { + my $err = $u->{'journaltype'} eq 'C' ? $ML{'.error.cantdelete.comm'} : $ML{'.error.cantdelete'}; + return $error->($err); + } + + my $can_manage = LJ::can_manage($remote, $u); + + # can ban if can manage and the comment is by someone else and not anon + my $can_ban = $can_manage && $tp->{'posterid'} + && $remote && $remote->{'userid'} != $tp->{'posterid'}; + my $can_delthread = $can_manage || $jposterid == $remote->{userid}; + + ### perform actions + if (LJ::did_post() && $POST{'confirm'}) { + # mark this as spam? + LJ::Talk::mark_comment_as_spam($u, $tp->{talkid}) + if $POST{spam}; + + # delete entire thread? or just the one comment? + if ($POST{delthread} && $can_delthread) { + # delete entire thread ... + LJ::Talk::delete_thread($u, $tp->{'itemid'}, $tpid); + } else { + # delete single comment... + + # if it's screened, unscreen it first to properly adjust + # replycount and the hasscreened logprop + LJ::Talk::unscreen_comment($u, $tp->{'itemid'}, $tpid) + if $tp->{'state'} eq 'S'; + + # now do the deletion + my $num = LJ::delete_comments($u, "L", $tp->{'itemid'}, $tpid); + LJ::replycount_do($u, $tp->{'itemid'}, "decr", $num); + LJ::Talk::update_commentalter($u, $tp->{'itemid'}); + } + + # ban the user, if selected + my $msg; + if ($POST{'ban'} && $can_ban) { + LJ::set_rel($u->{'userid'}, $tp->{'posterid'}, 'B'); + $msg = BML::ml('.success.andban', { 'user' => LJ::ljuser($tp->{'userpost'}) }); + } + $msg ||= $ML{'.success.noban'}; + $msg .= "" if $POST{spam}; + + if ($jsmode) { + BML::finish(); + return "1;"; + } else { + $body = ""; + return; + } + } + + ### show confirmation form + + $body .= ""; + $body .= ""; + $body .= "

    \n"; + $body .= "" . LJ::html_submit('confirm', $ML{'.confirm.submit'}) . "
    \n"; + + if ($can_ban) { + $body .= "
    " . LJ::html_check({ 'type' => 'check', 'name' => 'ban', 'id' => 'ban' }); + $body .= "
    "; + } + + if ($tp->{'posterid'} != $remote->{'userid'}) { # Despite the idea of natural selection, don't let users report their own comments as spam + $body .= "
    " . LJ::html_check({name => 'spam', id => 'spam'}); + $body .= "
    "; + } + + if ($can_delthread) { + $body .= "
    " . LJ::html_check({name => 'delthread', id => 'delthread'}); + $body .= "
    "; + } + + $body .= " standout?>"; + + if ($can_manage) { + my $msg = BML::ml('.changeoptions', { 'link' => + "$ML{'/editinfo.bml.title'}" }); + $body .= ""; + } + + $body .= "\n"; + return; +} +_code?> +body=> +page?> +link: htdocs/editinfo.bml +post: htdocs/delcomment.bml + _c?> diff --git a/livejournal/htdocs/dev/userlist.bml b/livejournal/htdocs/dev/userlist.bml new file mode 100755 index 0000000..b2d90cb --- /dev/null +++ b/livejournal/htdocs/dev/userlist.bml @@ -0,0 +1,85 @@ +Users on this server +body<= +prepare("SELECT userid,user,journaltype,statusvis FROM user ORDER BY $orderby LIMIT $offset,$pagesizeplus1"); + $h->execute; + my @userids; + while (my $row = $h->fetchrow_hashref) { + $ss{$row->{'userid'}} = $row; + push @userids, $row->{'userid'}; + } + my $islastpage = 1; + if (scalar(@userids) > $pagesize) { + pop @userids; + $islastpage = 0; + } + my $inclause = join (",", @userids); + $h = $dbr->prepare("SELECT * FROM reluser WHERE userid IN ($inclause)"); + $h->execute; + while (my $row = $h->fetchrow_hashref) { + push @{$ss{$row->{'userid'}}->{'reluser'}}, $row; + } + + # sort bar + my $pagearg = $GET{'page'} > 1 ? "&page=$GET{'page'}" : ""; + my $pagearg2 = $GET{'page'} > 1 ? "?page=$GET{'page'}" : ""; + $ret .= "Sort by: [ User ID + | Username + | Journal Type + | Status Vis + ] p?>"; + + # page bar + my $next = $page + 2; + $pagearg = $page > 1 ? "&page=$page" : ""; + $ret .= " Previous Page " if $page; + $ret .= "|" if $page && !$islastpage; + $ret .= " Next Page " if !$islastpage; + $ret .= "] p?>" if $page || !$islastpage; + + $ret .= "

    + + "; + + foreach my $userid (@userids) { + my $hr = $ss{$userid}; + $ret .= ""; + } + $ret .= "
    User IDUsernameT/SReluser Edges
    $userid"; + $ret .= LJ::ljuser($hr->{'user'}, {type=> $hr->{'journaltype'}}); + $ret .= "$hr->{'journaltype'}/$hr->{'statusvis'}"; + if ($hr->{'reluser'} && scalar(@{$hr->{'reluser'}})) { + my $c = 0; + foreach my $t (sort { $a->{'type'} cmp $b->{'type'} } + @{$hr->{'reluser'}}) { + $ret .= "; " if $c; + $ret .= "$t->{'type'}/"; + $ret .= LJ::ljuser($ss{$t->{'targetid'}}->{'user'}, {type=> + $ss{$t->{'targetid'}}->{'journaltype'}}); + $c = 1; + } + } + $ret .= "
    "; + return $ret; +} +_code?> +page?> diff --git a/livejournal/htdocs/directory.bml b/livejournal/htdocs/directory.bml new file mode 100755 index 0000000..94b343b --- /dev/null +++ b/livejournal/htdocs/directory.bml @@ -0,0 +1,380 @@ +Search Results +body<= + + \%state, country => \%country }); + $ret = ""; + $ret .= "\n"; + $ret .= "

    "; + $ret .= "\n"; + + $ret .= "\n"; + + $ret .= "US Map

    \n"; + + $sth = $dbr->prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('country', 'stateus')"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $count{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'}; + } + + my @shapes = ( + "1,235,1,309,108,309,108,235,18,235,1,235", "AK", + "328,196,328,236,355,235,345,195,328,196,328,196", "AL", + "267,182,272,215,294,216,293,206,300,182,267,182,267,182", "AR", + "86,162,72,205,113,225,124,167,86,162,86,162", "AZ", + "14,86,6,110,22,166,54,198,69,189,29,123,38,90,14,86,14,86", "CA", + "137,122,133,160,191,169,191,128,137,122,137,122", "CO", + "444,91,443,99,456,92,456,88,444,91,444,91", "CT", + "445,158,460,158,460,168,445,158", "DC", + "428,122,433,134,436,132,430,121,428,122", "DE", + "450,126,464,135", "DE", + "335,240,335,244,371,242,391,259,410,293,414,279,390,238,335,240,335,240", "FL", + "352,194,366,234,388,233,389,216,364,192,352,194,352,194", "GA", + "119,269,185,312", "HI", + "248,101,254,126,289,126,286,97,248,101,248,101", "IA", + "86,24,73,90,114,99,118,76,100,72,86,24,86,24", "ID", + "302,111,293,135,313,162,321,147,316,111,302,111,302,111", "IL", + "326,119,328,154,344,143,343,114,326,119,326,119", "IN", + "199,140,196,167,257,170,254,141,199,140,199,140", "KS", + "325,172,324,161,341,160,348,148,366,149,367,164,325,172,325,172", "KY", + "274,224,277,255,307,254,307,244,290,244,291,221,274,224,274,224", "LA", + "471,79,488,88", "MA", + "442,82,442,89,458,84,464,89,466,87,457,79,442,82,442,82", "MA", + "465,142,483,153", "MD", + "397,128,426,122,432,135,437,136,431,142,419,138,420,128,411,128,409,126,397,129,397,128", "MD", + "462,27,457,52,461,64,476,38,469,25,462,27,462,27", "ME", + "309,56,361,61,359,107,331,110,309,56,309,56", "MI", + "243,36,250,92,277,92,268,65,283,46,243,36,243,36", "MN", + "260,134,267,173,308,173,283,133,260,134,260,134", "MO", + "322,196,321,240,299,237,301,204,322,196,322,196", "MS", + "96,22,111,64,176,73,180,33,96,22,96,22", "MT", + "388,171,374,181,415,186,423,166,388,171,388,171", "NC", + "189,33,186,59,240,63,236,36,189,33,189,33", "ND", + "184,104,182,119,200,121,200,134,248,135,237,108,184,104,184,104", "NE", + "453,51,459,74,449,79,450,61,452,60,452,51,453,51,453,51", "NH", + "435,27,452,36", "NH", + "432,102,431,109,436,114,431,121,437,125,441,111,437,111,438,103,432,102,432,102", "NJ", + "132,170,125,221,176,227,180,174,132,170,132,170", "NM", + "45,93,37,122,72,173,82,102,45,93,45,93", "NV", + "433,59,439,77,440,99,430,98,429,91,391,100,401,87,417,78,419,63,433,59", "NY", + "450,99,440,106,445,109,455,100,450,99", "NY", + "379,112,350,116,352,139,368,143,381,127,379,112,379,112", "OH", + "186,172,186,175,212,177,214,201,259,207,259,174,186,172,186,172", "OK", + "27,42,13,75,64,91,72,51,27,42,27,42", "OR", + "386,106,388,125,428,117,425,99,386,106,386,106", "PA", + "421,229,485,260", "PR", + "472,100,482,110", "RI", + "458,86,457,94,461,89,458,86", "RI", + "375,191,395,210,410,193,375,191,375,191", "SC", + "187,69,183,97,240,101,241,71,187,69,187,69", "SD", + "315,180,311,190,355,188,372,172,315,180,315,180", "TN", + "188,180,183,235,151,230,174,258,184,250,202,254,223,292,242,263,266,252,266,216,204,205,207,181,188,180,188,180", "TX", + "97,103,86,153,126,160,131,120,112,119,114,106,97,103,97,103", "UT", + "411,135,383,163,425,158,411,135,411,135", "VA", + "454,272,481,307", "VI", + "416,34,430,43", "VT", + "437,58,442,80,446,79,447,54,437,58,437,58", "VT", + "41,6,82,17,75,45,34,37,41,6,41,6", "WA", + "282,62,283,81,293,87,297,103,313,102,308,66,282,62,282,62", "WI", + "385,133,374,148,383,156,401,133,385,133,385,133", "WV", + "126,73,122,111,174,120,178,80,126,73,126,73", "WY", + ); + + while (my ($coords, $state) = splice(@shapes, 0, 2)) + { + next unless ($count{'stateus'}->{$state}); + my $shape = "poly"; + if ($coords =~ /^[^,]+,[^,]+,[^,]+,[^,]+$/) { $shape = "RECTANGLE"; } + $ret .= "$state{$state}+0); + $s = $count{'stateus'}->{$state} != 1 ? "s" : ""; + $ret .= " Journal$s'); return true;\" onmouseout=\"updateStatus(''); return true;\" />\n"; + } + + $ret .= "\n"; + + # by country + $ret .= ""; + $ret .= "
      "; + my $total = scalar(keys %{$count{'country'}}); + my $count = 0; + my $col = 0; + foreach (sort { $country{$a} cmp $country{$b} } keys %{$count{'country'}}) + { + $count++; + $ret .= "
    • $country{$_} ($count{'country'}->{$_})
    • \n"; + if ($col==0 && $count > ($total/2)) { $ret .= "
      "; $col = 1; } + } + $ret .= "
    \n"; + return $ret; + } + + my $remote = LJ::get_remote(); + + unless (LJ::check_priv($remote, "betatest", "directory") || + LJ::get_cap($remote, "directory") || + (@filters == 1 && $filters[0] eq "int" && $GET{'opt_format'} eq "simple")) + { + return $ML{'.error.accounttype'}; + } + + unless (LJ::Dir::do_search($dbr, $dbdir, \%FORM, \@matches, \%info)) { + return ""; + } + + # opt_format and opt_sort might've been modified by do_search, + # filling in appropriate defaults based on other parameters + my $opt_format = $FORM{'opt_format'}; + my $opt_sort = $FORM{'opt_sort'}; + + $info{'allwhat'} ||= "users"; + + if ($info{'searching'}) { + my ($uri, $args) = (BML::get_uri(), BML::get_query_string()); + $uri .= '?' . $args if $args; + $head .= "\n"; + return "
    $ML{'.search.title'}...

    $ML{'.search.monkey'}

    "; + } + + if ($POST{'com_do'} || $GET{'com_do'}) { + $ret .= "<< $ML{'.search.new'}

    \n"; + } else { + $ret .= "<< $ML{'.search.new'}

    \n"; + } + unless (@{$info{'english'}}) { + push @{$info{'english'}}, "wish to be listed in the public directory"; + } + + $ret .= "Below are all $info{'allwhat'} that "; + + my $count_preds = @{$info{'english'}}; + + ### remove consecutive "are"s + my $last_are = 0; + foreach (@{$info{'english'}}) { + if (/^are /) { + if ($last_are) { + s/^are //; + } + $last_are = 1; + } else { + $last_are = 0; + } + } + my $last = pop @{$info{'english'}}; + if (@{$info{'english'}}) { + $ret .= join(", ", map { LJ::ehtml($_) } @{$info{'english'}}) . ", and "; + } + $ret .= LJ::ehtml($last) . ".\n"; + + if ($info{'overflow'}) { + $ret .= BML::ml(".search.overflow", {'count' => $info{'count'}}); + } + + if ($count_preds == 1 && $GET{'int_like'}) { + my $intid = $dbr->selectrow_array("SELECT intid FROM interests WHERE interest=?", + undef, $GET{'int_like'}); + LJ::run_hooks("interests_bml", { + 'intid' => $intid, + 'int' => $interest, + 'ret' => \$ret, + }) if $intid; + } + + ########## make the navcrap + my $navcrap; + $navcrap .= "".BML::ml(".navcrap.matches", {'count' => $info{'count'}}).""; + if ($info{'count'}) { + if ($info{'pages'} > 1) { + $navcrap .= "
    "; + $navcrap .= BML::ml(".navcrap.xofy", {'curpage' => $info{'page'}, 'totpages' => $info{'pages'}, 'reca' => $info{'first'}, 'recb' => $info{'last'}}); + $navcrap .= "
    "; + my $left = "<<"; + if ($info{'page'} > 1) { $left = " $info{'page'}-1 }) . "\">$left"; } + my $right = ">>"; + if ($info{'page'} < $info{'pages'}) { $right = " $info{'page'}+1 }) . "\">$right"; } + $navcrap .= $left . " "; + for (my $i=1; $i<=$info{'pages'}; $i++) { + my $link = "[$i]"; + if ($i != $info{'page'}) { $link = " $i }) . "\">$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + } + $navcrap .= "$right"; + } + $navcrap .= "
    standout?>\n"; + } else { + $navcrap .= " standout?>\n"; + } + ####### end navcrap + + $ret .= $navcrap . "

    "; + + unless ($info{'count'}) { return $ret; } + + if ($opt_sort eq "loc") { + LJ::load_codes({ state => \%state, country => \%country }); + } + + if ($opt_format eq "simple") + { + my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0; + my %last = (); + $ret .= "

      \n"; + foreach my $rec (@matches) + { + if ($showloc) { + if ($last{'country'} ne $rec->{'country'} || + $last{'state'} ne $rec->{'state'} || + $last{'city'} ne $rec->{'city'}) { + foreach (qw(country state city)) { $last{$_} = $rec->{$_}; } + my $country = $country{$rec->{'country'}}; + my ($state, $city); + if ($rec->{'state'}) { + $state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'}); + } + if ($rec->{'city'}) { + $city = ", $rec->{'city'}"; + } + $ret .= "
      "; + } + } + + $ret .= "{'user'}\">"; + if ($rec->{'journaltype'} eq "C") { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= " "; + $ret .= "{'user'}/\">$rec->{'user'} - " . LJ::ehtml($rec->{'name'}) . ", Updated "; + $ret .= LJ::ago_text($rec->{'secondsold'}); + $ret .= "
      \n"; + } + $ret .= "
    \n"; + } + + if ($opt_format eq "com") + { + $ret .= "\n"; + $ret .= "\n"; + foreach my $rec (@matches) + { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + my $color; + if ($rec->{'membership'} eq "open") { $color = "green"; } else { $color = "red"; } + $ret .= ""; + if ($rec->{'postlevel'} eq "members") { $color = "green"; } else { $color = "red"; } + $ret .= ""; + + $ret .= ""; + } + $ret .= "
     $ML{'.user'}$ML{'.community'}$ML{'.open'}$ML{'.post'}
    {'user'}\">"; + if ($rec->{'journaltype'} eq "C") { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= "{'user'}/\">$rec->{'user'}" . LJ::ehtml($rec->{'name'}) . "
    \n"; + } + + if ($opt_format eq "pics") + { + my $showloc = $GET{'opt_sort'} eq "loc" ? 1 : 0; + my %last = (); + + my %pic; + my @picids = map { [$_, $_->{'defaultpicid'}] } @matches; + LJ::load_userpics(\%pic, \@picids); + + my $count = 0; + my $pos = 0; + my $more_to_show = 0; + $ret .= "\n"; + foreach my $rec (@matches) + { + if ($pos==5) { $ret .= "\n"; } + $pos++; $pos %= 5; + + if ($showloc) { + if ($last{'country'} ne $rec->{'country'} || + $last{'state'} ne $rec->{'state'} || + $last{'city'} ne $rec->{'city'}) { + foreach (qw(country state city)) { $last{$_} = $rec->{$_}; } + my $country = $country{$rec->{'country'}}; + my ($state, $city); + if ($rec->{'state'}) { + $state = ", " . ($rec->{'country'} eq "US" ? $state{$rec->{'state'}} : $rec->{'state'}); + } + if ($rec->{'city'}) { + $city = ", $rec->{'city'}"; + } + if ($pos > 1) { $ret .= ""; $pos = 1; } + $ret .= "
    "; + $ret .= "
    "; + $ret .= "\n"; + } + } + + + if ($pos==1) { $ret .= "\n"; } + my $picid = $rec->{'defaultpicid'}; + my $updateago = LJ::ago_text($rec->{'secondsold'}); + my $img; + if ($picid) { + $img = "{'userid'}\" ALT=\"$_->{'user'}\" WIDTH=$pic{$picid}->{'width'} HEIGHT=$pic{$picid}->{'height'} BORDER=0>
    "; + } + $ret .= "\n"; + } + $ret .= "
    "; + $ret .= $img; + $ret .= LJ::ljuser($rec->{'user'}); + $ret .= "
    $Ml{'.update'} $updateago
    \n"; + } + + if ($info{'pages'} > 1) { $ret .= $navcrap; } + return $ret; + + +_code?> + +<=body +head<= + + +<=head +page?> diff --git a/livejournal/htdocs/directorysearch.bml b/livejournal/htdocs/directorysearch.bml new file mode 100755 index 0000000..eb2b4fc --- /dev/null +++ b/livejournal/htdocs/directorysearch.bml @@ -0,0 +1,205 @@ +'> +%%name%% + + %%form%% +<=crit +bar<= +{FpRs} +  +%%name%% + + %%form%% +<=bar +<=localblocks +_info?>Directory Search +body<= + + + + + +
    + +
    + + + + +By Location +code=>s_loc +form<= + +
    + + + +
    Country: + \%countries }); + return LJ::html_select({ + 'name' => 'loc_cn', + }, "", "", map { $_, $countries{$_} } "US", sort { $countries{$a} cmp $countries{$b} } keys %countries); + +_code?> +
    State/Province:
    City:
    + +<=form +crit?> + + +By Journal Update Time +code=>s_ut +form<= +Updated in last + +<=form +crit?> + + +By Age +code=>s_age +form<= +Between + and + years old. +<=form +crit?> + + +By Gender +code=>s_gen +form<= +User is: +<=form +crit?> +_c?> + + +By Interest +code=>s_int +form<= +User likes: +<=form +crit?> + + +Has Friend +code=>s_fr +form<= +User lists as a friend. +<=form +crit?> + + +Friend of +code=>s_fro +form<= + lists user as a friend. +<=form +crit?> + + +Client Usage +code=>s_client +form<= +Has used update client named: +<=form +crit?> +_c?> + + +Other Criteria +form<= + Only users with pictures +<=form +bar?> +_c?> + + +Display Options +form<= + + + + + + + + + + + +
    +Output Format: + + +
    +Sorting Method: + + +
    +Records per page: + + +
    +<=form +bar?> + + + + + + + + +
    + +
    + +<=body +page?> +form: htdocs/directory.bml + _c?> diff --git a/livejournal/htdocs/doc/.placeholder b/livejournal/htdocs/doc/.placeholder new file mode 100755 index 0000000..cff1c21 --- /dev/null +++ b/livejournal/htdocs/doc/.placeholder @@ -0,0 +1,3 @@ +This file exists to make sure the directory is created. +Other things (like doc/raw/build/generate.pl) depend +on this directory existing, and populating into it. diff --git a/livejournal/htdocs/editinfo.bml b/livejournal/htdocs/editinfo.bml new file mode 100755 index 0000000..4b3cc1e --- /dev/null +++ b/livejournal/htdocs/editinfo.bml @@ -0,0 +1,886 @@ + +body<= + + +underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + return $LJ::MSG_READONLY_USER if $u->readonly; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + ### user is now authenticated ### + + my $dbr = LJ::get_db_reader(); + my $sth; + + # load user props + LJ::load_user_props($u, { use_master => 1 }, "opt_whatemailshow", + "country", "state", "city", + "zip", "icq", "aolim", "yahoo", "msn", "url", + "urlname", "gender", "jabber", "opt_blockrobots", + "opt_logcommentips", + "howhear", "opt_bdaymail", "opt_hidefriendofs", + "sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks", + "opt_whoscreened", "journaltitle", "journalsubtitle", + "friendspagetitle", "opt_weblogscom", "opt_stylemine", + "opt_imagelinks", "opt_getselfemail", "external_foaf_url", + "opt_showmutualfriends", + ); + + # to store values before they undergo normalisation + my %saved = (); + $saved{'name'} = $u->{'name'}; + + # clean userprops + foreach (values %$u) { LJ::text_out(\$_); } + + # load and clean bio + $u->{'bio'} = LJ::get_bio($u); + $saved{'bio'} = $u->{'bio'}; + LJ::text_out(\$u->{'bio'}, "force"); + + # load interests + my $uints = LJ::get_interests($u, { forceids => 1 }); + my %interests = (); + foreach (@$uints) { + $interests{$_->[1]} = $_->[0]; # $interests{name} = intid + } + + # load state and country codes + my %countries; + my %states; + LJ::load_codes({ "country" => \%countries, "state" => \%states }); + + + ### + ### no post, show edit form + ### + + unless (LJ::did_post()) { + + my $ret; + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + $ret .= "
    \n"; + $ret .= LJ::form_auth(); + + # personal information + $ret .= "\n"; + + $ret .= "\n"; + + # name + $ret .= ""; + if (LJ::text_in($saved{'name'})) { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + + # birthday + $ret .= "\n"; + + # gender + $ret .= "\n"; + + # email + $ret .= "\n"; + + # url + $ret .= "\n"; + + # urlname + $ret .= "\n"; + + # chat thingies + foreach my $p (["aolim", $ML{'.chat.aolim.title'}, 28], ["icq", $ML{'.chat.icquin.title'}, 12], + ["yahoo", $ML{'.chat.yahooid.title'}, 33], ["msn", $ML{'.chat.msnusername.title'}, 60], + ["jabber", $ML{'.chat.jabber.title'}, 60]) + { + $ret .= "\n"; + } + + # country + $ret .= "\n"; + + # city + $ret .= "\n"; + + # state + $ret .= "\n"; + + # zip + $ret .= "\n"; + + # text messaging + if (LJ::get_cap($u, "textmessaging")) + { + $sth = $dbr->prepare("SELECT provider, number, security FROM txtmsg WHERE userid=?"); + $sth->execute($u->{'userid'}); + my $tminfo = $sth->fetchrow_hashref; + foreach (values %$tminfo) { LJ::text_out(\$_); } + + # text messaging + $ret .= "\n"; + } + + # end personal info + $ret .= "
    $ML{'.name.title'}" . LJ::html_text({ 'name' => 'name', 'value' => $u->{'name'}, + 'maxlength' => '50' }) . "
    " . LJ::html_hidden('name_absent', 'yes'); + $ret .= "
    $ML{'.bday.title'}"; + my %bdpart; + if ($u->{'bdate'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/) { + ($bdpart{'year'}, $bdpart{'month'}, $bdpart{'day'}) = ($1, $2, $3); + if ($bdpart{'year'} eq "0000") { $bdpart{'year'} = ""; } + if ($bdpart{'day'} eq "00") { $bdpart{'day'} = ""; } + } + $ret .= LJ::html_select({ 'name' => 'month', 'selected' => int($bdpart{'month'}) }, + '', '', map { $_, $ML{LJ::Lang::month_long_langcode($_)} } (1..12)) . " "; + + $ret .= LJ::html_text({ 'name' => 'day', 'value' => $bdpart{'day'}, 'size' => '3', 'maxlength' => '2' }) . " "; + $ret .= LJ::html_text({ 'name' => 'year', 'value' => $bdpart{'year'}, 'size' => '5', 'maxlength' => '4' }); + $ret .= " ($ML{'.bday.year.opt'})"; + + $ret .= "
    $ML{'.gender.title'}"; + $ret .= LJ::html_select({ 'name' => 'gender', 'selected' => $u->{'gender'} }, + 'U' => "(Unspecified)", 'M' => "Male", 'F' => "Female" ); + $ret .= "
    $ML{'.email.title'}"; + $ret .= LJ::html_text({ 'name' => 'email', 'value' => $u->{'email'}, 'size' => '40', 'maxlength' => '50' }); + $ret .= "
    $ML{'.webpageurl.title'}"; + $ret .= LJ::html_text({ 'name' => 'url', 'value' => $u->{'url'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= " ($ML{'.optional'})
    $ML{'.webpagename.title'}"; + $ret .= LJ::html_text({ 'name' => 'urlname', 'value' => $u->{'urlname'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= " ($ML{'.optional'})
    $p->[1]"; + $ret .= LJ::html_text({ 'name' => $p->[0], 'value' => $u->{$p->[0]}, 'size' => '20', 'maxlength' => $p->[2] }); + $ret .= " ($ML{'.optional'})
    $ML{'.country.title'}"; + $ret .= LJ::html_select({ 'name' => 'country', 'selected' => $u->{'country'} }, + '', $ML{'.country.choose'}, + 'US', 'United States', + map { $_, $countries{$_} } sort { $countries{$a} cmp $countries{$b} } keys %countries ); + $ret .= "
    $ML{'.city.title'}"; + $ret .= LJ::html_text({ 'name' => 'city', 'value' => $u->{'city'}, 'size' => '20', 'maxlength' => '255' }); + $ret .= "
    $ML{'.state.title'}"; + $ret .= LJ::html_select({ 'name' => 'statedrop', 'selected' => $u->{'state'} }, + '', "($ML{'.state.us'})", + map { $_, $states{$_} } sort { $states{$a} cmp $states{$b} } keys %states ); + + # other state? + $ret .= "
    $ML{'.state.other'}: "; + $ret .= LJ::html_text({ 'name' => 'stateother', 'size' => '20', 'maxlength' => '50', + 'value' => defined $states{$u->{'state'}} ? '' : $u->{'state'} }); + $ret .= "
    $ML{'.zip.title'}"; + $ret .= LJ::html_text({ 'name' => 'zip', 'value' => $u->{'zip'}, 'size' => '6', 'maxlength' => '5' }); + $ret .= " ($ML{'.zip.usonly'})
    "; + $ret .= LJ::help_icon('textmessage', "", " "); + $ret .= "$ML{'.tm.title'}\n\n\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'use_txtmsg', 'id' => 'use_txtmsg', + 'selected' => $u->{'txtmsg_status'} eq 'on' }); + + $ret .= "
     $ML{'.tm.sec.title'}"; + + $ret .= LJ::html_select({ 'name' => 'txtmsg_security', 'selected' => $tminfo->{'security'} }, + "all" => BML::ml(".security.visibility.anybody"), + "reg" => BML::ml(".security.visibility.regusers"), + "friends" => BML::ml(".security.visibility.friends") ); + $ret .= "
    $ML{'.tm.servprov'}"; + { + my @opts = ("", ""); + foreach my $p (LJ::TextMessage::providers()) { + my $info = LJ::TextMessage::provider_info($p); + push @opts, ($p, $info->{'name'}); + } + $ret .= LJ::html_select({ 'name' => 'txtmsg_provider', + 'selected' => $tminfo->{'provider'}, }, + @opts); + } + + $ret .= " ($ML{'.tm.details'})
    $ML{'.tm.phonenum'}"; + $ret .= LJ::html_text({ 'name' => 'txtmsg_number', 'value' => $tminfo->{'number'}, + 'size' => '15', 'maxlength' => '40' }); + $ret .= "
    \n
    \n\n"; + + ### User bio + $ret .= ""; + if (LJ::text_in($saved{'bio'})) { + $ret .= "
    "; + $ret .= LJ::html_textarea({ 'name' => 'bio', 'rows' => '10', 'cols' => '50', + 'wrap' => 'soft', 'value' => $u->{'bio'}, 'style' => "width: 90%", }) . "
    \n"; + } else { + $ret .= LJ::html_hidden('bio_absent', 'yes'); + $ret .= " p?>\n"; + } + + ### How heard Settings + unless ($u->{'howhear'}) { + $ret .= "\n"; + $ret .= " $LJ::SITENAME }) . " p?>\n"; + $ret .= "
    "; + $ret .= LJ::html_text({ 'name' => 'howhear', 'size' => '60', 'maxlength' => '100' }); + $ret .= "
    \n\n"; + } + + { + ### Interests + $ret .= "\n"; + my @eintsl; + foreach (sort keys %interests) { + push @eintsl, $_ if LJ::text_in($_); + } + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_textarea({ 'name' => 'interests', 'value' => join(", ", @eintsl), + 'rows' => '10', 'cols' => '50', 'wrap' => 'soft' }); + $ret .= "
    \n\n"; + } + + ### Picture Settings + $ret .= "\n\n"; + $ret .= "

    "; + if ($u->{'defaultpicid'}) + { + my $picid = $u->{'defaultpicid'}; + my %userpics = (); + LJ::load_userpics(\%userpics, [ $u, $picid ]); + $ret .= "{'userid'}\" width='$userpics{$picid}->{'width'}' height='$userpics{$picid}->{'height'} alt='$u->{'user'}' border='0'>"; + } else + { + $ret .= "($ML{'.userpic.none'})"; + } + $ret .= "

    $ML{'.userpic.edit'}

    \n\n"; + + + ### + ### Journal Options + ### + + $ret .= "\n"; + + + ### display options + $ret .= "\n"; + $ret .= "\n"; + + # journaltitle + $ret .= ""; + $ret .= "\n"; + + # journalsubtitle + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + + # friendspagetitle + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    $ML{'.settings.journal.title'} " . LJ::html_text({ 'name' => 'journaltitle', 'value' => $u->{'journaltitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.journal.subtitle'} " . LJ::html_text({ 'name' => 'journalsubtitle', 'value' => $u->{'journalsubtitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.journal.subtitle.optional'}
    $ML{'.settings.friendspage.title'} " . LJ::html_text({ 'name' => 'friendspagetitle', 'value' => $u->{'friendspagetitle'}, 'size' => '30', 'maxlength' => '80' }) . "
    $ML{'.settings.friendspage.title.optional'}
    \n\n"; + + ### privacy options + $ret .= "\n"; + $ret .= "\n"; + + # allow_contactshow + $ret .= "\n"; + $ret .= "\n"; + + # allow_infoshow + $ret .= "\n"; + $ret .= "\n"; + + # opt_blockrobots + $ret .= "\n"; + $ret .= "\n"; + + # opt_weblogscom + if (LJ::get_cap($u, "weblogscom")) { + $ret .= "\n"; + $ret .= "\n"; + } + + # opt_showmutualfriends + $ret .= "\n"; + $ret .= "\n"; + + # opt_hidefriendofs + $ret .= "\n"; + $ret .= "\n"; + + + # allow_getljnews + $ret .= "\n"; + $ret .= "\n"; + + # opt_bdaymail + $ret .= "\n"; + $ret .= "\n"; + + # opt_imagelinks + my ($maxwidth, $maxheight) = (0, 0); + ($maxwidth, $maxheight) = ($1, $2) + if ($u->{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/); + my $is_stock = {'320|240' => 1, '640|480' => 1, '0|0' => 1, '' => 1}->{$u->{'opt_imagelinks'}}; + my $extra = $is_stock ? '' : BML::ml('.imagelinks.size.custom', + {'width' => $maxwidth, 'height' => $maxheight}); + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + # opt_getselfemail + $ret .= "\n"; + $ret .= "\n"; + + # opt_showtalklinks + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_contactshow', 'id' => 'allow_contactshow', + 'selected' => $u->{'allow_contactshow'} ne 'N' }); + $ret .= "
     $ML{'.allowshowcontact.about'}"; + + { + # contactshow_sec + $ret .= "\n

    $ML{'.security.header'} "; + $ret .= LJ::html_select({ 'name' => 'contactshow_sec', + 'selected' => $u->{'allow_contactshow'} }, + "Y" => BML::ml(".security.visibility.everybody"), + "F" => BML::ml(".security.visibility.friends") ); + $ret .= "

    \n"; + + # opt_whatemailshow + $ret .= "

    $ML{'.allowshowcontact.email'}\n"; + $ret .= "

    "; + my $cur = $u->{'opt_whatemailshow'} || "N"; + my @vals = ( ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail")) + ? ("B" => BML::ml(".allowshowcontact.email.both", { 'domain' => $LJ::USER_DOMAIN}), + "A" => BML::ml(".allowshowcontact.email.actual_only"), + "L" => BML::ml(".allowshowcontact.email.lj_only"), + "N" => BML::ml(".allowshowcontact.email.neither")) + : ("A" => BML::ml(".allowshowcontact.email.show"), + "N" => BML::ml(".allowshowcontact.email.no_show"))); + $ret .= LJ::html_select({ 'name' => 'opt_whatemailshow', 'selected' => $cur }, @vals) . "\n"; + + $ret .= "

    " . ($LJ::USER_EMAIL + ? $ML{'.allowshowcontact.email.withdomainaddr'} + : $ML{'.allowshowcontact.email.withoutdomainaddr'}) . "

    \n
    \n"; + + # opt_mangleemail + $ret .= "\n\n"; + $ret .= "\n
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_mangleemail', 'id' => 'opt_mangleemail', + 'selected' => $u->{'opt_mangleemail'} eq 'Y' }); + $ret .= "
     $ML{'.mangleaddress.about'}
    \n"; + + } + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_infoshow', 'id' => 'allow_infoshow', + 'selected' => $u->{'allow_infoshow'} eq 'Y' }); + $ret .= "
     $ML{'.allowshowinfo.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_blockrobots', 'id' => 'opt_blockrobots', + 'selected' => $u->{'opt_blockrobots'} }); + $ret .= "
     $ML{'.blockrobots.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_weblogscom', 'id' => 'opt_weblogscom', + 'selected' => $u->{'opt_weblogscom'} }); + $ret .= "
     $ML{'.weblogscom.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showmutualfriends', 'id' => 'opt_showmutualfriends', + 'selected' => $u->{'opt_showmutualfriends'} }); + $ret .= "
     $ML{'.mutualfriends.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_hidefriendofs', 'id' => 'opt_hidefriendofs', + 'selected' => $u->{'opt_hidefriendofs'} }); + $ret .= "
     $ML{'.hidefriendof.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'allow_getljnews', 'id' => 'allow_getljnews', + 'selected' => $u->{'allow_getljnews'} eq 'Y' }); + $ret .= "
     $ML{'.opt_in.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_bdaymail', 'id' => 'opt_bdaymail', + 'selected' => $u->{'opt_bdaymail'} }); + $ret .= "
     $ML{'.bdayreminders.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_imagelinks_on', 'id' => 'opt_imagelinks_on', + 'selected' => $u->{'opt_imagelinks'} }); + $ret .= "
     $ML{'.imagelinks.about'}
     "; + $ret .= LJ::html_select({'name' => 'opt_imagelinks', 'selected' => $u->{'opt_imagelinks'}}, + '0|0', BML::ml('.imagelinks.size.all'), + '320|240', BML::ml('.imagelinks.size.small', {'width' => 320, 'height' => 240}), + '640|480', BML::ml('.imagelinks.size.medium', {'width' => 640, 'height' => 480}), + $extra ? ("$maxwidth|$maxheight", $extra) : ()); + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_getselfemail', 'id' => 'opt_getselfemail', + 'selected' => $u->{'opt_getselfemail'}, + 'disabled' => !LJ::get_cap($u, 'getselfemail') }); + $ret .= "
     $ML{'.getselfemails.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_showtalklinks', 'id' => 'opt_showtalklinks', + 'selected' => $u->{'opt_showtalklinks'} eq 'Y' }); + $ret .= "
     $ML{'.enableboards.about'}"; + + { + # opt_whocanreply + $ret .= "\n

    $ML{'.whoreply.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_whocanreply', 'selected' => $u->{'opt_whocanreply'} }, + "all" => BML::ml(".security.visibility.anybody"), + "reg" => BML::ml(".security.visibility.regusers"), + "friends" => BML::ml(".security.visibility.friends")); + $ret .= "

    \n"; + + # opt_logcommentips + $ret .= "

    $ML{'.logip.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_logcommentips', 'selected' => $u->{'opt_logcommentips'} }, + "N" => BML::ml(".donotlog"), + "S" => BML::ml(".logip.anon_only"), + "A" => BML::ml(".logip.always") ); + $ret .= "

    \n"; + + # opt_whoscreened + $ret .= "

    $ML{'.screen.header'} "; + $ret .= LJ::html_select({ 'name' => 'opt_whoscreened', 'selected' => $u->{'opt_whoscreened'} }, + "N" => $ML{'.screen.none'}, + "R" => $ML{'.screen.anon'}, + "F" => ($u->{'journaltype'} eq 'C' ? $ML{'.screen.nonmembers'} : $ML{'.screen.nonfriends'}), + "A" => $ML{'.screen.all'} ); + $ret .= "

    \n"; + + $ret .= "\n"; + + # opt_nctalklinks + $ret .= "\n"; + $ret .= "\n"; + + # stylemine + $ret .= "\n"; + $ret .= "\n"; + + # opt_gettalkemail + $ret .= "\n"; + $ret .= "\n"; + + # opt_htmlemail + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_nctalklinks', 'id' => 'opt_nctalklinks', + 'selected' => $u->{'opt_nctalklinks'} }); + $ret .= "
     $ML{'.numcomments.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_stylemine', 'id' => 'opt_stylemine', + 'value' => 1, 'selected' => $u->{'opt_stylemine'} }); + $ret .= "
     $ML{'.stylemine.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_gettalkemail', 'id' => 'opt_gettalkemail', + 'selected' => $u->{'opt_gettalkemail'} eq 'Y' }); + $ret .= "
     $ML{'.getreplies.about'}
    "; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'opt_htmlemail', 'id' => 'opt_htmlemail', + 'selected' => $u->{'opt_htmlemail'} eq 'Y' }); + $ret .= "
     $ML{'.htmlemail.about'}
    \n"; + + } + $ret .= "
    \n\n"; + + ### advanced options + $ret .= "\n"; + $ret .= "\n"; + + # external foaf link + $ret .= ""; + + # done + $ret .= "
    $ML{'.foafurl.title'}"; + $ret .= LJ::html_text({ 'name' => 'external_foaf_url', + 'value' => $u->{'external_foaf_url'}, 'size' => '40', 'maxlength' => '255' }); + $ret .= "
    $ML{'.foafurl.about'}
    \n"; + + ### unicode options + if ($LJ::UNICODE) { + my (%old_encnames, %mail_encnames, %encodings); + LJ::load_codes({ "encoding" => \%encodings } ); + LJ::load_codes({ "encname" => \%old_encnames } ); + %mail_encnames = %old_encnames; + + # which encodings to show? For now, we just delete utf-8 from the old encodings + # list because it doesn't make sense there. + foreach my $id (keys %encodings) { + delete $old_encnames{$id} if lc($encodings{$id}) eq 'utf-8'; + } + + $ret .= "\n"; + $ret .= "\n"; + $ret .= ""; + $ret .= "\n"; + $ret .= ""; + + if ($u->{journaltype} eq 'P') { + $ret .= ""; + $ret .= "\n"; + $ret .= ""; + } + + $ret .= "
    $ML{'.autotranslate.header'}" . LJ::html_select({ 'name' => 'oldenc', 'selected' => $u->{'oldenc'}}, + map { $_, $old_encnames{$_} } sort keys %old_encnames ) . "
    " . $ML{'.autotranslate.about'} . "
    $ML{'.translatemailto.header'}" . LJ::html_select({ 'name' => 'mailencoding', 'selected' => $u->{'mailencoding'}}, + map { $_, $mail_encnames{$_} } sort keys %mail_encnames ) . "
    $ML{'.translatemailto.about'}
    \n"; + } + + ### let them un-ban users if they've banned users + my $banned = LJ::load_rel_user($u, 'B'); + if ($banned && @$banned) { + my $us = LJ::load_userids(@$banned); + + $ret .= "\n"; + $ret .= "
    \n"; + foreach (@$banned) { + my $bu = $us->{$_}; + next unless $bu; + $ret .= LJ::html_check({ 'type' => 'check', 'name' => 'unban', 'id' => "unban-$bu->{'user'}", + 'value' => $bu->{'userid'} }); + $ret .= "
    \n"; + } + $ret .= "
    \n"; + } + + # ending submit block + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + + return $ret; + } + + + ### + ### we have a post, process edits + ### + + if (LJ::did_post()) { + return "" unless LJ::check_form_auth(); + + $POST{'unban'} =~ s/\0/,/g; + return "" unless LJ::text_in(\%POST); + + my @errors = (); + + # name + unless ($POST{'name'} || defined($POST{'name_absent'})) { + push @errors, $ML{'.error.noname'}; + } + + # state and zip + my ($zipcity, $zipstate); + if ($POST{'country'} eq "US") { + $sth = $dbr->prepare("SELECT city, state FROM zip WHERE zip=?"); + $sth->execute($POST{'zip'}); + ($zipcity, $zipstate) = $sth->fetchrow_array; + } + + # country + if ($POST{'country'} ne "US" && $POST{'zip'}) { + push @errors, $ML{'.error.locale.zip_requires_us'}; + } + + if ($POST{'country'} eq "US" && $POST{'stateother'}) { + push @errors, $ML{'.error.locale.country_ne_state'}; + } elsif ($POST{'country'} && $POST{'country'} ne "US" && $POST{'statedrop'}) { + push @errors, $ML{'.error.locale.state_ne_country'}; + } + + # zip-code validation stuff + if ($POST{'country'} eq "US") { + if ($POST{'statedrop'} && $zipstate && $POST{'statedrop'} ne $zipstate) { + push @errors, $ML{'.error.locale.zip_ne_state'}; + } + if ($zipcity) { + $POST{'statedrop'} = $zipstate; + $POST{'city'} = $zipcity; + } + } + + if ($POST{'country'} && !defined($countries{$POST{'country'}})) { + push @errors, $ML{'.error.locale.invalid_country'}; + } + + # birthday + my $this_year = (localtime())[5]+1900; + + if ($POST{'year'} && $POST{'year'} < 100) { + push @errors, $ML{'.error.year.notenoughdigits'}; + } + + if ($POST{'year'} && $POST{'year'} >= 100 && ($POST{'year'} < 1890 || $POST{'year'} > $this_year)) { + push @errors, $ML{'.error.year.outofrange'}; + } + + if ($POST{'month'} && ($POST{'month'} < 1 || $POST{'month'} > 12)) { + push @errors, $ML{'.error.month.outofrange'}; + } + + if ($POST{'day'} && ($POST{'day'} < 1 || $POST{'day'} > 31)) { + push @errors, $ML{'.error.day.outofrange'}; + } + + if (@errors == 0 && $POST{'day'} > LJ::days_in_month($POST{'month'}, $POST{'year'})) { + push @errors, $ML{'.error.day.notinmonth'}; + } + + # email + unless ($POST{'email'}) { + push @errors, $ML{'.error.email.none'}; + } + + if ($LJ::USER_EMAIL and $POST{'email'} =~ /\@\Q$LJ::USER_DOMAIN\E$/i) { + push @errors, BML::ml(".error.email.lj_domain", { 'user' => $u->{'user'}, 'domain' => $LJ::USER_DOMAIN, }); + } + + if ($POST{'email'} =~ /\s/) { + push @errors, $ML{'.error.email.no_space'}; + } + + unless (@errors) { + LJ::check_email($POST{'email'}, \@errors); + } + + # text messaging + if ($POST{'use_txtmsg'}) { + unless ($POST{'txtmsg_provider'}) { + push @errors, $ML{'.error.tm.require_provider'}; + } + unless ($POST{'txtmsg_number'}) { + push @errors, $ML{'.error.tm.require.number'}; + } + } + + return LJ::bad_input(@errors) if @errors; + + ### no errors + + my $dbh = LJ::get_db_writer(); + + my $email_changed = ($u->{'email'} ne $POST{'email'}); + if ($email_changed) { + # record old email address; + LJ::infohistory_add($u, 'email', $u->{email}, $u->{status}); + } + + $POST{'url'} =~ s/\s+$//; $POST{'url'} =~ s/^\s+//; + if ($POST{'url'} && $POST{'url'} !~ /^https?:\/\//) { + $POST{'url'} =~ s/^http\W*//; + $POST{'url'} = "http://$POST{'url'}"; + } + + my $newname = defined $POST{'name_absent'} ? $saved{'name'} : $POST{'name'}; + $newname =~ s/[\n\r]//g; + $newname = LJ::text_trim($newname, LJ::BMAX_NAME, LJ::CMAX_NAME); + + my $newbio = defined($POST{'bio_absent'}) ? $saved{'bio'} : $POST{'bio'}; + my $has_bio = ($newbio =~ /\S/) ? "Y" : "N"; + my $txtmsg_status = $POST{'use_txtmsg'} ? "on" : "off"; + # setup what we're gonna update in the user table: + my %update = ( + 'name' => $newname, + 'bdate' => sprintf("%04d-%02d-%02d", $POST{'year'}, $POST{'month'}, $POST{'day'}), + 'email' => $POST{'email'}, + 'status' => ($email_changed && $u->{'status'} eq "A") ? "T" : $u->{'status'}, + 'has_bio' => $has_bio, + 'allow_infoshow' => $POST{'allow_infoshow'} ? "Y" : "N", + 'allow_getljnews' => $POST{'allow_getljnews'} ? "Y" : "N", + 'opt_showtalklinks' => $POST{'opt_showtalklinks'} ? "Y" : "N", + 'opt_gettalkemail' => $POST{'opt_gettalkemail'} ? "Y" : "N", + 'opt_htmlemail' => $POST{'opt_htmlemail'} ? "Y" : "N", + 'opt_mangleemail' => $POST{'opt_mangleemail'} ? "Y" : "N", + 'opt_whocanreply' => $POST{'opt_whocanreply'}, + 'txtmsg_status' => $txtmsg_status, + ); + + if ($POST{'allow_contactshow'}) { + $update{'allow_contactshow'} = "Y"; + $update{'allow_contactshow'} = "F" if $POST{'contactshow_sec'} eq "F"; + } else { + $update{'allow_contactshow'} = "N"; + } + + if (defined $POST{'oldenc'}) { + $update{'oldenc'} = $POST{'oldenc'}; + } + + LJ::update_user($u, \%update); + + ### change any of the userprops ? + { + # journal / friends titles + $POST{'journaltitle'} = LJ::text_trim($POST{'journaltitle'}, 0, 80) if $POST{'journaltitle'}; + $POST{'journalsubtitle'} = LJ::text_trim($POST{'journalsubtitle'}, 0, 80) if $POST{'journalsubtitle'}; + $POST{'friendspagetitle'} = LJ::text_trim($POST{'friendspagetitle'}, 0, 80) if $POST{'friendspagetitle'}; + + # opts + $POST{'opt_showmutualfriends'} = $POST{'opt_showmutualfriends'} ? 1 : 0; + $POST{'opt_getselfemail'} = $POST{'opt_getselfemail'} ? 1 : 0; + $POST{'opt_stylemine'} = $POST{'opt_stylemine'} ? 1 : 0; + $POST{'opt_blockrobots'} = $POST{'opt_blockrobots'} ? 1 : 0; + $POST{'opt_bdaymail'} = $POST{'opt_bdaymail'} ? 1 : 0; + $POST{'opt_hidefriendofs'} = $POST{'opt_hidefriendofs'} ? 1 : 0; + $POST{'opt_nctalklinks'} = $POST{'opt_nctalklinks'} ? 1 : 0; + $POST{'opt_weblogscom'} = $POST{'opt_weblogscom'} ? 1 : 0; + if ($POST{'opt_logcommentips'} ne "N" && + $POST{'opt_logcommentips'} ne "S" && + $POST{'opt_logcommentips'} ne "A") { $POST{'opt_logcommentips'} = "N"; } + $POST{'opt_whoscreened'} = "N" unless $POST{'opt_whoscreened'} =~ m/^(N|R|F|A)$/; + $POST{'opt_imagelinks'} = 0 unless $POST{'opt_imagelinks_on'} && + $POST{'opt_imagelinks'} =~ m/^(\d+)\|(\d+)$/; + + # for the directory. + $POST{'sidx_bdate'} = ""; + $POST{'sidx_loc'} = ""; + $POST{'state'} = $POST{'statedrop'} || $POST{'stateother'}; + if ($update{'allow_infoshow'} eq 'Y') { + if ($POST{'year'}) { + $POST{'sidx_bdate'} = sprintf("%04d-%02d-%02d", map { $POST{$_} } + qw(year month day)); + } + + if ($POST{'country'}) { + my $state; + if ($POST{'country'} eq "US") { + $state = $POST{'statedrop'}; + } else { + $state = $POST{'stateother'}; + } + $POST{'sidx_loc'} = sprintf("%2s-%s-%s", + $POST{'country'}, + $state, + $POST{'city'}); + } + } + + my @uprops = ( + "opt_whatemailshow", + "country", "state", "city", "zip", "icq", + "aolim", "yahoo", "msn", "url", "urlname", + "gender", "jabber", "opt_blockrobots", + "opt_logcommentips", + "opt_bdaymail", "opt_hidefriendofs", + "sidx_bdate", "sidx_loc", "mailencoding", "opt_nctalklinks", + "opt_whoscreened", "journaltitle", "journalsubtitle", "friendspagetitle", + "opt_stylemine", "opt_imagelinks", "opt_getselfemail", + "external_foaf_url", "opt_showmutualfriends", + ); + + # weblogs.com requires a special cap + push @uprops, 'opt_weblogscom' if LJ::get_cap($u, 'weblogscom'); + + # this is only done once, then never appears again. + push @uprops, 'howhear' if $POST{'howhear'}; + + # set userprops + foreach my $uprop (@uprops) { + my $eff_val = $POST{$uprop}; # effective value, since 0 isn't stored + $eff_val = "" unless $eff_val; + my $mem_only = $eff_val eq $u->{$uprop}; + LJ::set_userprop($u, $uprop, $eff_val, $mem_only); + } + } + + # update their bio text + if (($u->{'bio'} ne $POST{'bio'}) && !defined($POST{'bio_absent'})) { + if ($has_bio eq "N") { + $u->do("DELETE FROM userbio WHERE userid=?", undef, $u->{'userid'}); + $u->dudata_set('B', 0, 0); + } else { + $u->do("REPLACE INTO userbio (userid, bio) VALUES (?, ?)", + undef, $u->{'userid'}, $POST{'bio'}); + $u->dudata_set('B', 0, length($POST{'bio'})); + } + LJ::MemCache::set([$u->{'userid'}, "bio:$u->{'userid'}"], $POST{'bio'}); + } + + # update their text messaging info + if ($txtmsg_status eq "off" && $u->{'txtmsg_status'} eq "on") { + $dbh->do("DELETE FROM txtmsg WHERE userid=?", undef, $u->{'userid'}); + } elsif ($txtmsg_status eq "on") { + $dbh->do("REPLACE INTO txtmsg (userid, provider, number, security) VALUES (?, ?, ?, ?)", + undef, $u->{'userid'}, $POST{'txtmsg_provider'}, $POST{'txtmsg_number'}, $POST{'txtmsg_security'}); + } + + # update interests + unless ($POST{'interests_absent'}) { + $POST{'interests'} =~ s/^\s+//; + $POST{'interests'} =~ s/\s+$//; + $POST{'interests'} =~ s/\n/,/g; + $POST{'interests'} =~ s/\s+/ /g; #Strip duplicate spaces from the interest + my @ints = split (/\s*,\s*/, $POST{'interests'}); + my $intcount = scalar(@ints); + if ($intcount > 150) { + return LJ::bad_input(BML::ml(".error.excessive_int", {'intcount' => $intcount})); + } + LJ::set_interests($u, \%interests, \@ints); + } + + # now unban users they selected to be unbanned + if ($POST{'unban'}) { + my $bannedin = join(",", map { $dbh->quote($_); } split(/,/, $POST{'unban'})); + $dbh->do("DELETE FROM reluser WHERE userid=? AND type='B' AND targetid IN ($bannedin)", undef, $u->{'userid'}); + } + + # actions if email changed + if ($email_changed) { + my $aa = {}; + $aa = LJ::register_authaction($u->{'userid'}, + "validateemail", $POST{'email'}); + + LJ::send_mail({ + 'to' => $POST{'email'}, + 'from' => $LJ::ADMIN_EMAIL, + 'charset' => 'utf-8', + 'subject' => $ML{'.newemail.subject'}, + 'body' => BML::ml('.newemail.body2', + { username => $u->{user}, + sitename => $LJ::SITENAME, + sitelink => $LJ::SITEROOT, + conflink => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}" }), + }); + } + + # tell the user all is well + return "\n" . + " $u->{'user'}, }) . " p?>"; + } + + # should never happen + return ""; + +} +_code?> + +<=body +page?> +lib: LJ::TextMessage, cgi-bin/ljlib.pl, cgi-bin/ljlang.pl +link: htdocs/legal/privacy.bml, htdocs/support/faqbrowse.bml, htdocs/tools/textmessage.bml, htdocs/uploadpic.bml +link: htdocs/paidaccounts/index.bml, htdocs/users, htdocs/userinfo.bml +post: htdocs/editinfo.bml +img: htdocs/userpic + _c?> diff --git a/livejournal/htdocs/editjournal.bml b/livejournal/htdocs/editjournal.bml new file mode 100755 index 0000000..239a1bd --- /dev/null +++ b/livejournal/htdocs/editjournal.bml @@ -0,0 +1,413 @@ + +body<= +{'head'}; + my $bodyopts = \$_[1]->{'bodyopts'}; + + LJ::set_active_crumb('editentries'); + + my $remote = LJ::get_remote(); + return LJ::bad_input($ML{'error.noremote'}) + unless $remote; + + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + my $mode = $GET{'mode'} || $POST{'mode'} || "init"; + if ($GET{'itemid'} || $POST{'itemid'}) { $mode = "edit"; } + + my $ret; + my $getextra = "?authas=$GET{'authas'}" if $GET{'authas'}; + + # are they asking to be authed as someone else? + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + return LJ::bad_input("You must be authenticated as a person.") + unless $u->{'journaltype'} eq 'P'; + + if ($mode eq "edit") + { + # are we modify a community post? + my $usejournal = $GET{'usejournal'} || $POST{'usejournal'} || $GET{'journal'}; + undef $usejournal if $usejournal eq $u->{'user'}; # ignore if it's the user + + # user object for community if we're modifying one + my $usejournal_u; + if ($usejournal) { + $usejournal_u = LJ::load_user($usejournal); + return LJ::bad_input("The community you selected does not exist.") + unless $usejournal_u; + } + + # extra get arguments + my $getextra; + $getextra .= "authas=$authas&" if $authas ne $u->{'user'}; + $getextra .= "usejournal=$usejournal&" if $usejournal; + chop $getextra; + $getextra = "?$getextra" if $getextra; + + ### + ### HAVE AN ITEMID TO EDIT + ### + + if ($GET{'itemid'} || $POST{'itemid'}) { + + # the 'itemid' form element is really an 'itemid' + my $ditemid = $GET{'itemid'} || $POST{'itemid'}; + my $anum = $ditemid % 256; + my $itemid = $ditemid >> 8; + + # do getevents request + my %res = (); + LJ::do_request({ 'mode' => 'getevents', + 'selecttype' => 'one', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $u->{'user'}, + 'usejournal' => $usejournal, + 'itemid' => $itemid }, + \%res, + { "noauth" => 1, + 'u' => $u } + ); + + # was there a protocol error? + return "" + unless $res{'success'} eq 'OK'; + + # does the requested entry exist? + return "" + unless $res{'events_count'} && $res{'events_1_anum'} == $anum; + + # are we authorized to edit other peoples' posts in this community? + my $disabled_save = 0; + my $disabled_delete = 0; + my $disabled_spamdelete = 0; + if ($usejournal && $res{'events_1_poster'} ne $u->{'user'}) { + $disabled_delete = ! LJ::can_delete_journal_item($u, $usejournal_u); + $disabled_save++; + } + $disabled_spamdelete = $disabled_delete || !$usejournal || ($res{'events_1_poster'} eq $u->{'user'}); + + ### + ### SAVE EDITS + ### + + # are we spellchecking before we post? + my $spellcheck_html; + my $did_spellcheck; + if ($LJ::SPELLER && $POST{'action:spellcheck'}) { + $did_spellcheck++; + my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, + 'color' => '', }; + my $event = LJ::ehtml($POST{'event'}); + $spellcheck_html = $s->check_html(\$event); + $spellcheck_html = "" unless $spellcheck_html ne ""; + } + + # they clicked the save or delete button + if (!$spellcheck_html && ($POST{'action:save'} || $POST{'action:delete'} || $POST{'action:deletespam'})) { + return LJ::bad_input($ML{'error.invalidform'}) unless LJ::check_form_auth(); + + my %req = ( 'mode' => 'editevent', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $u->{'user'}, + 'usejournal' => $usejournal, + 'itemid' => $itemid, + ); + LJ::entry_form_decode(\%req, \%POST); + + # Delete + $req{'event'} = '' if $POST{'action:delete'} || $POST{'action:deletespam'}; + + # mark as spam, if need be + LJ::mark_entry_as_spam($usejournal_u, $itemid) if $POST{'action:deletespam'}; + + # if the action is to delete it, then let's note that + if ($POST{'action:delete'} || $POST{'action:deletespam'}) { + # now log the event created above + ($usejournal ? $usejournal_u : $u)->log_event('delete_entry', { + remote => $remote, + actiontarget => $ditemid, + method => 'web', + }); + } + + # do editevent request + LJ::do_request(\%req, \%res, { 'noauth' => 1, 'u' => $u }); + + # check response + unless ($res{'success'} eq "OK") { + return "
  • $res{'errmsg'}
  • p?>"; + } + + # deleted + unless ($req{'event'}) { + my $result = ""; + $result .= "" if $POST{'action:deletespam'}; + return $result; + } + + # modified + return BML::redirect(LJ::item_link($usejournal ? $usejournal_u : $u, $itemid, $res{'anum'})); + } + + + ### + ### SHOW EDIT FORM + ### + + my $auth = "$ML{'.auth.poster'}"; + $auth .= $usejournal ? LJ::ljuser($res{'events_1_poster'}) . " in community " . LJ::ljuser($usejournal) : + LJ::ljuser($remote); + $auth .= ""; + + + my ($year, $mon, $mday, $hour, $min) = split(/\D/, $res{"events_1_eventtime"}); + my $datetime; my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, \%POST); + if ($date ne "0000-00-00 00:00:00") { + my ($date, $time) = split( / /, $date); + $datetime = "$date $POST{'hour'}:$POST{'min'}"; + } else { + $datetime = "$year-$mon-$mday $hour:$min"; + } + + my $subject = $POST{'subject'} || $res{'events_1_subject'}; + my $event = $POST{'event'} || $res{'events_1_event'}; + + my $curmask = $res{'events_1_allowmask'}; + my $cursec = $res{'events_1_security'} || $POST{'security'}; + if ($cursec eq 'usemask') { + $cursec = $curmask == 1 ? "friends" : "custom"; + } + + # start edit form + my $ret; my $js; + $ret .= "
    "; + $ret .= LJ::form_auth(); + $ret .= LJ::html_hidden('itemid', $ditemid,'mode','edit','edited',1) . "\n"; + + my $entry = { + 'mode' => "edit", + 'auth_as_remote' => 1, + 'subject' => $subject, + 'event' => $event, + 'datetime' => $datetime, + 'usejournal' => $usejournal, + 'security' => $cursec, + 'security_mask' => $curmask, + 'auth' => $auth, + 'remote' => $remote, + 'spellcheck_html' => $spellcheck_html, + 'richtext' => 0, + 'mood' => $res{'events_1_'}, + 'disabled_save' => $disabled_save, + 'disabled_delete' => $disabled_delete, + 'disabled_spamdelete' => $disabled_spamdelete, + }; + for (my $i = 1; $i <= $res{'prop_count'}; $i++) { + $entry->{"prop_" . $res{"prop_${i}_name"}} = $res{"prop_${i}_value"}; + } + foreach ( keys %POST ) { $entry->{$_} = %POST->{$_}; } + + my $onload = "shift_contents(); "; + $ret .= LJ::entry_form($entry, \$$head, \$onload); + $ret .= "
    "; + + $$bodyopts .= "onload='$onload' onresize='shift_contents();' "; + + return $ret; + } + + ### + ### NO ITEMID - SELECT ENTRY TO EDIT + ### + + ### already authenticated from above + + return BML::redirect("$LJ::SITEROOT/editjournal.bml") + unless LJ::did_post(); + + my %res; + my %req = ( + 'mode' => 'getevents', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $u->{'user'}, + 'usejournal' => $usejournal, + 'truncate' => 300, + 'noprops' => 1, + ); + + # last 1 + if ($POST{'selecttype'} eq "last") { + $req{'selecttype'} = 'one'; + $req{'itemid'} = -1; + + # last n + } elsif ($POST{'selecttype'} eq 'lastn') { + $req{'selecttype'} = 'lastn'; + $req{'howmany'} = $POST{'howmany'}; + + # day + } elsif ($POST{'selecttype'} eq 'day') { + $req{'selecttype'} = 'day'; + $req{$_} = $POST{$_} foreach qw(year month day); + } + + # do getevents request + LJ::do_request(\%req, \%res, { 'noauth' => 1, 'u' => $u }); + + # check response + unless ($res{'success'} eq "OK") { + return "\n" . + "
  • p?>"; + } + + # only one item returned? go directly to edit it + if ($res{'events_count'} == 1) { + my $ditemid = ($res{'events_1_itemid'} << 8) + $res{'events_1_anum'}; + my $ditemid_get = $getextra ? "$getextra&itemid=$ditemid" : "?itemid=$ditemid"; + return BML::redirect("$LJ::SITEROOT/editjournal.bml$ditemid_get"); + } + + # how many results did we get? + my $ev_count = $res{'events_count'}; + unless ($ev_count) { + if ($req{'selecttype'} eq 'lastn') { + return "\n" . + "\n"; + } + + return "\n" . + "\n"; + } + + ### display results + my $ret; + $ret .= "\n"; + + my %props = (); + for (my $i=1; $i<=$res{'prop_count'}; $i++) { + $props{$res{"prop_${i}_itemid"}}->{$res{"prop_${i}_name"}} = $res{"prop_${i}_value"}; + } + + for (my $i=1; $i<=$ev_count; $i++) { + my $itemid = $res{"events_${i}_itemid"}; + my $ditemid = $itemid * 256 + $res{"events_${i}_anum"}; + + $ret .= "
    "; + $ret .= "
    \n"; + $ret .= LJ::html_hidden('itemid',$ditemid,'mode',"edit"); + $ret .= LJ::html_submit('itemid-$ditemid','Edit this Entry'); + $ret .= "
    "; + $ret .= "
    "; + + $ret .= " "; + $ret .= " (Posted by: " . LJ::ljuser($res{"events_${i}_poster"}) . ")" if $usejournal; + + ### security indicator + my $sec = ' '; + if ($res{"events_${i}_security"} eq "private") { + $sec .= BML::fill_template("securityprivate"); + } elsif ($res{"events_${i}_security"} eq "usemask") { + $sec .= BML::fill_template("securityprotected"); + } + $ret .= $sec; + + if (my $subj = $res{"events_${i}_subject"}) { + LJ::CleanHTML::clean_subject_all(\$subj); + $ret .= " " . LJ::ehtml($subj) . ""; + } + $ret .= "
    \n"; + + my $event = LJ::ehtml(LJ::durl($res{"events_${i}_event"})); + $event =~ s!\n!
    !g; + $ret .= $event; + + $ret .= "
    \n"; + } + return $ret; + } elsif ($mode eq "init") { + # no authentication needs to be done on this page, it's just a form anyway + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'}, 'type' => 'P' }); + $ret .= "
    \n\n"; + + # header + $ret .= "\n"; + + # edit form + $ret .= "
    \n"; + $ret .= LJ::html_hidden("mode","edit"); + $ret .= "\n"; + + # view type + $ret .= "$ML{'.viewwhat'}\n\n"; + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype', 'id' => 'selecttype-last', + 'value' => 'last', 'selected' => 1 }); + $ret .= "
    \n"; + + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype', + 'id' => 'selecttype-lastn', 'value' => 'lastn' }) . " "; + $ret .= LJ::html_text({ 'name' => 'howmany', 'size' => '3', 'maxlength' => '2', 'value' => '20', + 'onchange' => "checkRadioButton('selecttype-lastn');" }) . " "; + $ret .= "
    \n"; + + $ret .= LJ::html_check({ 'type' => 'radio', 'name' => 'selecttype', + 'id' => 'selecttype-day', 'value' => 'day' }); + $ret .= ""; + + my @time = localtime(time); + my $mday = sprintf("%02d", $time[3]); + my $mon = sprintf("%02d", $time[4] + 1); + my $year = $time[5] + 1900; + + $ret .= LJ::html_text({ 'name' => 'year', 'size' => '5', 'maxlength' => '4', 'value' => $year, + 'onchange' => "checkRadioButton('selecttype-day');" }) . "-"; + $ret .= LJ::html_text({ 'name' => 'month', 'size' => '3', 'maxlength' => '2', 'value' => $mon, + 'onchange' => "checkRadioButton('selecttype-day');" }) . "-"; + $ret .= LJ::html_text({ 'name' => 'day', 'size' => '3', 'maxlength' => '2', 'value' => $mday, + 'onchange' => "checkRadioButton('selecttype-day');" }) . "\n"; + + $ret .= "\n"; + + # use journal + $ret .= "$ML{'.in'}\n\n"; + $ret .= LJ::html_text({ 'name' => 'usejournal', 'size' => '20', 'maxlength' => '15', 'value' => $GET{'usejournal'} }) . " "; + $ret .= " (optional)"; + + # submit button + $ret .= " " . LJ::html_submit(undef, $ML{'.btn.proceed'}) . "\n"; + + $ret .= " standout?>\n"; + $ret .= "
    \n"; + + return $ret; + } +} +_code?> +<=body + +bodyopts=>{'bodyopts'}; _code?> +head<= + + +{'head'}; _code?> + + + +<=head +page?> +post: htdocs/editjournal.bml +link: htdocs/lostinfo.bml + _c?> + diff --git a/livejournal/htdocs/editpics.bml b/livejournal/htdocs/editpics.bml new file mode 100755 index 0000000..2984042 --- /dev/null +++ b/livejournal/htdocs/editpics.bml @@ -0,0 +1,873 @@ +("Invalid UTF-8 Input"); + } + + my $remote = LJ::get_remote(); + return $err->($ML{'error.noremote'}) + unless $remote; + + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + my $returl = LJ::CleanHTML::canonical_url($POST{'ret'}); + my $picurl = LJ::CleanHTML::canonical_url($POST{'urlpic'}); + my $fotobilder = index($returl, $LJ::FB_SITEROOT) == 0 && + $picurl =~ m!^$LJ::FB_SITEROOT/~?$remote->{'user'}/pic/!; + + if ($fotobilder && + (LJ::check_referer($returl) || LJ::check_referer('/editpics.bml'))) { + + return $err->('Invalid referring site or redirection not allowed') + unless $returl =~ /$LJ::FB_DOMAIN/ && LJ::get_cap($u, 'fb_account'); + } + + if (LJ::get_cap($u, "readonly")) { + $title = "Read-only mode"; + $body = $LJ::MSG_READONLY_USER; + return; + } + + # update this user's activated pics + LJ::activate_userpics($u); + + my ($dbh, $dbcm, $dbcr, $sth); + + # Put $count and $max in larger scope so they can be used in output + my $count; + $dbcm = LJ::get_cluster_master($u); + return $err->($ML{'error.nodb'}) unless $dbcm; + + if ($u->{'dversion'} > 6) { + $dbcr = LJ::get_cluster_def_reader($u); + return $err->($ML{'error.nodb'}) unless $dbcr; + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM userpic2 " . + "WHERE userid=? AND state <> 'X'", undef, $u->{'userid'}); + } else { + $dbh = LJ::get_db_writer(); + return $err->($ML{'error.nodb'}) unless $dbh; + $count = $dbh->selectrow_array("SELECT COUNT(*) FROM userpic " . + "WHERE userid=? AND state <> 'X'", undef, $u->{'userid'}); + } + my $max = LJ::get_cap($u, "userpics"); + + ### save mode + if (LJ::did_post()) { + + ### save changes to existing pics + if ($POST{'action:save'}) { + # form being posted isn't multipart, since we were able to read from %POST + + my %exist_kwids; + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?"); + } else { + $sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?"); + } + $sth->execute($u->{'userid'}); + while (my ($kwid, $picid) = $sth->fetchrow_array) { + push @{$exist_kwids{$picid}}, $kwid; + } + + my @inactive_picids; + my @delete; + my %picid_of_kwid; + my %ctype; # picid -> contenttype, for delete mode + my %states; # picid -> state, for setting new default + my %locations; # picid -> location, for deleting + my @comments; + my %exist_comments; + + # select all of their userpics and iterate through them + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT picid, width, height, state, fmt, comment, location " . + "FROM userpic2 WHERE userid=?"); + } else { + $sth = $dbh->prepare("SELECT picid, width, height, state, contenttype " . + "FROM userpic WHERE userid=?"); + } + $sth->execute($u->{'userid'}); + while (my $pic = $sth->fetchrow_hashref) + { + # ignore anything expunged + next if $pic->{state} eq 'X'; + + # store picture information + $states{$pic->{picid}} = $pic->{state}; + $locations{$pic->{picid}} = $pic->{location} + if $u->{dversion} > 6; + $exist_comments{$pic->{picid}} = $pic->{comment}; + + # delete this pic + if ($POST{"delete_$pic->{'picid'}"}) { + push @delete, $pic->{'picid'}; + $ctype{$pic->{picid}} = ($u->{'dversion'} > 6) ? $pic->{'fmt'} : $pic->{'contenttype'}; + next; + } + + # make a list of inactive picids + if ($pic->{'state'} eq 'I') { + push @inactive_picids, $pic->{'picid'}; + next; + } + + # we're going to modify keywords on active pictures + my $c = 1; + my @kw_errors; + + my @keywords = split(/\s*,\s*/, $POST{"kw_$pic->{'picid'}"}); + @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords; + foreach my $kw (@keywords) { + my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw); + next unless $kwid; + + if ($c > $LJ::MAX_USERPIC_KEYWORDS) { + my $ekw = LJ::ehtml($kw); + push @kw_errors, $ekw; + next; + } + + if ($picid_of_kwid{$kwid}) { + my $ekw = LJ::ehtml($kw); + push @errors, BML::ml(".error.keywords", {'ekw' => $ekw}); + } + $picid_of_kwid{$kwid} = $pic->{'picid'}; + $c++; + } + + # Let the user know about any we didn't save + if (@kw_errors) { + my $num_words = scalar(@kw_errors); + my $kws = join (", ", @kw_errors); + push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS}); + } + + # Find if they changed the comment and then save the new one + if ($u->{'dversion'} > 6 && $POST{"com_$pic->{'picid'}"} ne $exist_comments{$pic->{'picid'}}) { + my $comment = LJ::text_trim($POST{"com_$pic->{'picid'}"}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT); + $u->do("UPDATE userpic2 SET comment=? WHERE userid=? AND picid=?", + undef, $comment, $u->{'userid'}, $pic->{'picid'}); + } + } + + # now, reapply the existing picids to the inactive pics, unless + # that picid has already been assigned to a new active one + foreach my $picid (@inactive_picids) { + next unless $exist_kwids{$picid}; + + foreach (@{$exist_kwids{$picid}}) { + $picid_of_kwid{$_} ||= $picid; + } + } + + if (@delete) { + my $id_in; + if ($u->{'dversion'} > 6) { + $id_in = join(", ", map { $dbcm->quote($_) } @delete); + } else { + $id_in = join(", ", map { $dbh->quote($_) } @delete); + } + + # delete data from user cluster + foreach my $picid (@delete) { + my $fmt; + if ($u->{'dversion'} > 6) { + $fmt = { + 'G' => 'gif', + 'J' => 'jpg', + 'P' => 'png', + }->{$ctype{$picid}}; + } else { + $fmt = { + 'image/gif' => 'gif', + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + }->{$ctype{$picid}}; + } + + my $deleted = 0; + + # try and delete from either the blob server or database, + # and only after deleting the image do we delete the metadata. + if ($locations{$picid} eq 'mogile') { + $deleted = 1 + if LJ::mogclient()->delete($u->mogfs_userpic_key($picid)); + } elsif ($LJ::USERPIC_BLOBSERVER && + LJ::Blob::delete($u, "userpic", $fmt, $picid)) { + $deleted = 1; + } elsif ($u->do("DELETE FROM userpicblob2 WHERE ". + "userid=? AND picid=?", undef, + $u->{userid}, $picid) > 0) { + $deleted = 1; + } + + # now delete the metadata if we got the real data + if ($deleted) { + if ($u->{'dversion'} > 6) { + $u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?", + undef, $picid, $u->{'userid'}); + } else { + $dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid); + } + $u->do("DELETE FROM userblob WHERE journalid=? AND blobid=? " . + "AND domain=?", undef, $u->{'userid'}, $picid, + LJ::get_blob_domainid('userpic')); + + # decrement $count to reflect deletion + $count--; + } + + # if we didn't end up deleting, it's either because of + # some transient error, or maybe there was nothing to delete + # for some bizarre reason, in which case we should verify + # that and make sure they can delete their metadata + if (! $deleted) { + my $present; + if ($locations{$picid} eq 'mogile') { + my $blob = LJ::mogclient()->get_file_data($u->mogfs_userpic_key($picid)); + $present = length($blob) ? 1 : 0; + } elsif ($LJ::USERPIC_BLOBSERVER) { + my $blob = LJ::Blob::get($u, "userpic", $fmt, $picid); + $present = length($blob) ? 1 : 0; + } + $present ||= $dbcm->selectrow_array("SELECT COUNT(*) FROM userpicblob2 WHERE ". + "userid=? AND picid=?", undef, $u->{'userid'}, + $picid); + if (! int($present)) { + if ($u->{'dversion'} > 6) { + $u->do("DELETE FROM userpic2 WHERE picid=? AND userid=?", + undef, $picid, $u->{'userid'}); + } else { + $dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid); + } + } + } + } + + # if any of the userpics they want to delete are active, then we want to + # re-run LJ::activate_userpics() - turns out it's faster to not check to + # see if we need to do this + LJ::activate_userpics($u); + } + + if (%picid_of_kwid) { + if ($u->{'dversion'} > 6) { + $u->do("REPLACE INTO userpicmap2 (userid, kwid, picid) VALUES " . + join(",", map { "(" . + join(",", + $dbcm->quote($u->{'userid'}), + $dbcm->quote($_), + $dbcm->quote($picid_of_kwid{$_})) . + ")" + } + keys %picid_of_kwid) + ); + } else { + $dbh->do("REPLACE INTO userpicmap (userid, kwid, picid) VALUES " . + join(",", map { "(" . + join(",", + $dbh->quote($u->{'userid'}), + $dbh->quote($_), + $dbh->quote($picid_of_kwid{$_})) . + ")" + } + keys %picid_of_kwid) + ); + } + } + + # Delete keywords that are no longer being used + my @kwid_del; + + foreach my $kwids (values %exist_kwids) { + foreach my $kwid (@$kwids) { + if (! $picid_of_kwid{$kwid}) { + push @kwid_del, $kwid+0; + } + } + } + + if (@kwid_del) { + my $kwid_del = join(",", @kwid_del); + if ($u->{'dversion'} > 6) { + $u->do("DELETE FROM userpicmap2 WHERE userid=$u->{userid} " . + "AND kwid IN ($kwid_del)"); + } else { + $dbh->do("DELETE FROM userpicmap WHERE userid=$u->{userid} " . + "AND kwid IN ($kwid_del)"); + } + } + + my $new_default = $POST{'defaultpic'}+0; + if ($POST{"delete_$POST{'defaultpic'}"}) { + # deleting your default + $new_default = 0; + } + if ($new_default != $u->{'defaultpicid'}) { + + # see if they are trying to make an inactive userpic their default + if ($states{$new_default} eq 'N' || !$new_default) { + LJ::update_user($u, { defaultpicid => $new_default }); + $u->{'defaultpicid'} = $new_default; + } + } + + my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"]; + LJ::MemCache::delete($memkey); + $memkey = [$u->{'userid'},"upiccom:$u->{'userid'}"]; + LJ::MemCache::delete($memkey); + $memkey = [$u->{'userid'},"upicurl:$u->{'userid'}"]; + LJ::MemCache::delete($memkey); + } + + ### no post, so we'll parse the multipart data + unless (%POST) { + + my $MAX_UPLOAD = 40960; + + my $error; + # Add some slop to account for the size of the form headers etc. + BML::parse_multipart(\%POST, \$error, $MAX_UPLOAD + 2048); + + # was there an error parsing the multipart form? + if ($error) { + if ($error =~ /^\[(\S+?)\]/) { + my $code = $1; + if ($code eq "toolarge") { + return $err->(BML::ml('.error.filetoolarge', + { 'maxsize' => int($MAX_UPLOAD / 1024) . + $ML{'.kilobytes'} })); + } + $error = BML::ml("BML.parse_multipart.$code"); + } + return $err->($error) if $error; + } + + # error check input contents + if ($POST{'src'} eq "url" && $POST{'urlpic'} !~ /^http:\/\//) { + return $err->($ML{'.error.badurl'}); + } + + if ($POST{'src'} eq "file") { + + # already loaded from multipart parse earlier + + } elsif ($POST{'src'} eq "url") { + require LWPx::ParanoidAgent; + my $ua = LWPx::ParanoidAgent->new( + timeout => 10, + max_size => $MAX_UPLOAD + 1024, + ); + my $res = $ua->get($POST{urlpic}); + $POST{userpic} = $res->content if $res && $res->is_success; + return $err->($ML{'.error.urlerror'}) unless $POST{userpic}; + } + + if (length($POST{'userpic'}) > $MAX_UPLOAD) { + return $err->(BML::ml('.error.filetoolarge', + { 'maxsize' => int($MAX_UPLOAD / 1024) . + $ML{'.kilobytes'} })); + } + + my ($sx, $sy, $filetype) = Image::Size::imgsize(\$POST{'userpic'}); + unless (defined $sx) { + return $err->($ML{'.error.invalidimage'}); + } + + unless ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG") { + return $err->(BML::ml(".error.unsupportedtype", + { 'filetype' => $filetype })); + } + + if ($sx > 100 || $sy > 100) { + return $err->( BML::ml(".error.imagetoolarge", + { 'imagesize' => "${sx}$ML{'.imagesize.by'}${sy}", + 'maxsize' => "100$ML{'.imagesize.by'}100" }) ); + } + + my $base64 = Digest::MD5::md5_base64($POST{'userpic'}); + + ## see if they have too many pictures uploaded + if ($count >= $max) { + return $err->( BML::ml(".error.toomanypics2", + { 'maxpics' => $max }) . + LJ::help_icon('userpics', " ", "")); + } + + # see if it's a duplicate + my $picid; + my $contenttype; + if ($u->{'dversion'} > 6) { + if ($filetype eq "GIF") { $contenttype = 'G'; } + elsif ($filetype eq "PNG") { $contenttype = 'P'; } + elsif ($filetype eq "JPG") { $contenttype = 'J'; } + + $picid = $dbcr->selectrow_array("SELECT picid FROM userpic2 " . + "WHERE userid=? AND fmt=? " . + "AND md5base64=?", + undef, $u->{'userid'}, $contenttype, $base64); + } else { + if ($filetype eq "GIF") { $contenttype = "image/gif"; } + elsif ($filetype eq "PNG") { $contenttype = "image/png"; } + elsif ($filetype eq "JPG") { $contenttype = "image/jpeg"; } + + $picid = $dbh->selectrow_array("SELECT picid FROM userpic " . + "WHERE userid=? AND contenttype=? " . + "AND md5base64=?", + undef, $u->{'userid'}, $contenttype, $base64); + } + # if picture isn't a duplicate, insert it + if ($picid == 0) { + + # insert the meta-data + # Make a new global picid + $picid = LJ::alloc_global_counter('P') or + return $err->('Unable to allocate new picture id'); + + # see where we're inserting this + my $target; + if ($u->{dversion} > 6 && $LJ::USERPIC_MOGILEFS) { + $target = 'mogile'; + } elsif ($LJ::USERPIC_BLOBSERVER) { + $target = 'blob'; + } + + my $dberr = 0; + if ($u->{'dversion'} > 6) { + $u->do("INSERT INTO userpic2 (picid, userid, fmt, width, height, " . + "picdate, md5base64, location) VALUES (?, ?, ?, ?, ?, NOW(), ?, ?)", + undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64, $target); + if ($u->err) { + push @errors, $err->($u->errstr); + $dberr = 1; + } + } else { + $dbh->do("INSERT INTO userpic (picid, userid, contenttype, width, height, " . + "picdate, md5base64) VALUES (?, ?, ?, ?, ?, NOW(), ?)", + undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64); + if ($dbh->err) { + push @errors, $err->($dbh->errstr); + $dberr = 1; + } + } + + my $clean_err = sub { + if ($u->{'dversion'} > 6) { + $u->do("DELETE FROM userpic2 WHERE userid=? AND picid=?", + undef, $u->{'userid'}, $picid) if $picid; + } else { + $dbh->do("DELETE FROM userpic WHERE picid=?", undef, $picid) if $picid; + } + return $err->(@_); + }; + + ### insert the blob + if ($target eq 'mogile' && !$dberr) { + my $fh = LJ::mogclient()->new_file($u->mogfs_userpic_key($picid), 'userpics'); + if (defined $fh) { + $fh->print($POST{'userpic'}); + my $rv = $fh->close; + push @errors, $clean_err->("Error saving to storage server: $@") unless $rv; + } else { + # fatal error, we couldn't get a filehandle to use + push @errors, $clean_err->("Unable to contact storage server. Your picture has not been saved."); + } + } elsif ($target eq 'blob' && !$dberr) { + my $et; + my $fmt = lc($filetype); + my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $POST{'userpic'}, \$et); + push @errors, $clean_err->("Error saving to media server: $et") unless $rv; + } elsif (!$dberr) { + my $dbcm = LJ::get_cluster_master($u); + return $err->($ML{'error.nodb'}) unless $dbcm; + $u->do("INSERT INTO userpicblob2 (userid, picid, imagedata) " . + "VALUES (?, ?, ?)", + undef, $u->{'userid'}, $picid, $POST{'userpic'}); + push @errors, $clean_err->($u->errstr) if $u->err; + } else { # We should never get here! + push @errors, "User picture uploading failed for unknown reason"; + } + + # Not a duplicate, so increment $count + $count++; + } + + # make it their default pic? + if ($POST{'make_default'}) { + LJ::update_user($u, { defaultpicid => $picid }); + $u->{'defaultpicid'} = $picid; + } + + # set default keywords? + if ($POST{'keywords'} ne '') { + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?"); + } else { + $sth = $dbh->prepare("SELECT kwid, picid FROM userpicmap WHERE userid=?"); + } + $sth->execute($u->{'userid'}); + + my @exist_kwids; + while (my ($kwid, $picid) = $sth->fetchrow_array) { + $exist_kwids[$kwid] = $picid; + } + + my @keywords = split(/\s*,\s*/, $POST{'keywords'}); + @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords; + + my (@bind, @data, @kw_errors); + my $c = 0; + + foreach my $kw (@keywords) { + my $kwid = ($u->{'dversion'} > 6) ? LJ::get_keyword_id($u, $kw) : LJ::get_keyword_id($kw); + next unless $kwid; # Houston we have a problem! This should always return an id. + + if ($c > $LJ::MAX_USERPIC_KEYWORDS) { + my $ekw = LJ::ehtml($kw); + push @kw_errors, $ekw; + next; + } + + if ($exist_kwids[$kwid]) { # Already used on another picture + my $ekw = LJ::ehtml($kw); + push @errors, BML::ml(".error.keywords", {'ekw' => $ekw}); + next; + } else { # New keyword, so save it + push @bind, '(?, ?, ?)'; + push @data, $u->{'userid'}, $kwid, $picid; + } + $c++; + } + + # Let the user know about any we didn't save + if (@kw_errors) { + my $num_words = scalar(@kw_errors); + my $kws = join (", ", @kw_errors); + push @errors, BML::ml(".error.toomanykeywords", {'numwords' => $num_words, 'words' => $kws, 'max' => $LJ::MAX_USERPIC_KEYWORDS}); + } + + if (@data && @bind) { + my $bind = join(',', @bind); + + if ($u->{'dversion'} > 6) { + $u->do("INSERT INTO userpicmap2 (userid, kwid, picid) VALUES $bind", + undef, @data); + } else { + $dbh->do("INSERT INTO userpicmap (userid, kwid, picid) VALUES $bind", + undef, @data); + } + } + } + + # set default comments and the url + if ($u->{'dversion'} > 6) { + my (@data, @set); + if ($POST{'comments'} ne '') { + push @set, 'comment=?'; + push @data, LJ::text_trim($POST{'comments'}, LJ::BMAX_UPIC_COMMENT, LJ::CMAX_UPIC_COMMENT); + } + + if ($POST{'url'} ne '') { + push @set, 'url=?'; + push @data, $POST{'url'}; + } + + if (@set) { + my $set = join(',', @set); + + $u->do("UPDATE userpic2 SET $set WHERE userid=? AND picid=?", + undef, @data, $u->{'userid'}, $picid); + } + } + + my $memkey = [$u->{'userid'},"upicinf:$u->{'userid'}"]; + LJ::MemCache::delete($memkey); + + $returl = LJ::CleanHTML::canonical_url($POST{'ret'}); + if ($returl) { + my $redir_host = $1 if $returl =~ m#^http://([\.:\w-]+)#i; + return BML::redirect($returl) if $LJ::REDIRECT_ALLOWED{$redir_host}; + } + } + + # now fall through to edit page and show the updated userpic info + } + + if ($fotobilder && $POST{'md5sum'}) { + my $id; + if ($u->{'dversion'} > 6) { + $id = $dbcm->selectrow_array("SELECT picid FROM userpic2 WHERE userid=? " . + "AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'}); + } else { + $id = $dbh->selectrow_array("SELECT picid FROM userpic WHERE userid=? " . + "AND md5base64=?", undef, $u->{'userid'}, $POST{'md5sum'}); + } + + $fotobilder = 0 if $id; + } + + # show the form to let people edit + $title = "Edit User Pictures"; + + # Fixme: Make this work with Fotobilder + if (!$fotobilder) { + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + } + + if (@errors) { + $body .= LJ::error_list(@errors); + } + + if (!$fotobilder) { + my %keywords = (); + my $dbcr = LJ::get_cluster_def_reader($u); + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT m.picid, k.keyword FROM userpicmap2 m, userkeywords k ". + "WHERE m.userid=? AND m.kwid=k.kwid AND m.userid=k.userid"); + } else { + $sth = $dbh->prepare("SELECT m.picid, k.keyword FROM userpicmap m, keywords k ". + "WHERE m.userid=? AND m.kwid=k.kwid"); + } + $sth->execute($u->{'userid'}); + while (my ($pic, $keyword) = $sth->fetchrow_array) { + LJ::text_out(\$keyword); + push @{$keywords{$pic}}, $keyword; + } + + if ($u->{'dversion'} > 6) { + $sth = $dbcr->prepare("SELECT picid, width, height, state, comment " . + "FROM userpic2 WHERE userid=?"); + } else { + $sth = $dbh->prepare("SELECT picid, width, height, state " . + "FROM userpic WHERE userid=?"); + } + $sth->execute($u->{'userid'}); + my @sortedpics; + push @sortedpics, $_ while $_ = $sth->fetchrow_hashref; + + + # See if they have any without keywords before we output the display table + foreach (@sortedpics) { + unless ($keywords{$_->{'picid'}}) { + my @w; + if (defined $LJ::HELPURL{'upic_keywords'}) { + push @w, BML::ml('.warning.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"}); + } else { + push @w, $ML{'.warning.keywords'}; + } + + $body .= LJ::warning_list(@w); + last; + } + } + + my $piccount = 0; + foreach my $pic (sort { $a->{picid} <=> $b->{picid} } @sortedpics) + { + my $pid = $pic->{'picid'}; + + if ($piccount++ == 0) { + $body .= ""; + $body .= "". BML::ml('.piclimitstatus', {current => $count, max => $max}) . " p?>"; + + $body .= "
    "; + $body .= ""; + } + $body .= ""; + $body .= ""; + $body .= "\n"; + } + + if ($piccount) { + $body .= "\n"; + $body .= "\n"; + $body .= "
    \n"; + + my ($dis, $distxt); + { + $body .= "\n"; + } + + { + my $keywords; + $keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}}) + if $keywords{$pid}; + + $body .= "\n"; + + if ($u->{'dversion'} > 6) { + $body .= "\n"; + } + } + + $body .= "
    "; + $body .= LJ::html_check({ 'type' => 'radio', 'name' => 'defaultpic', 'value' => $pid, + 'selected' => $u->{'defaultpicid'} == $pid, + 'disabled' => $pic->{'state'} eq 'I' }); + + $body .= "    "; + $body .= LJ::html_check({ 'type' => 'checkbox', 'name' => "delete_$pid", + 'id' => "$pid-del", 'value' => 1 }); + + if ($pic->{'state'} eq 'I') { + $body .= "  [$ML{'userpic.inactive'}] " . LJ::help_icon('userpic_inactive'); + } + + $body .= "
    "; + $body .= LJ::html_text({'name' => "kw_$pid", 'id' => "$pid-key", + 'size' => '30', 'value' => $keywords, + 'disabled' => $pic->{'state'} eq 'I' }); + + $body .= "
    "; + $body .= LJ::html_text({ 'name' => "com_$pid", 'id' => "$pid-com", + 'size' => '30', 'value' => $pic->{'comment'}, + 'maxlength' => LJ::CMAX_UPIC_COMMENT, + 'disabled' => $pic->{'state'} eq 'I' }); + + $body .= "
    \n
      "; + $body .= LJ::html_check({ 'name' => 'defaultpic', + 'value' => 0, + 'type' => 'radio', + 'selected' => ! $u->{'defaultpicid'}, + 'raw' => "id='nodefpic'" }); + + $body .= " 
     " . LJ::html_submit('action:save', $ML{'.btn.save'}) . "
    "; + $body .= "
    "; + } else { + $body .= ""; + } + } + + # let users upload more pics + $body .= ""; + + if ($count < $max) { + if ($fotobilder) { + $body .= "\n"; + $body .= " "href='$LJ::FB_SITEROOT'", 'sitename' => $LJ::FB_SITENAME}) . " p?>\n\n"; + } else { + $body .= "\n"; + $body .= "\n\n"; + + $body .= "
      \n"; + foreach (qw(filesize imagesize fileformat)) { + $body .= "
    • " . $ML{".restriction.$_"} . "
    • \n"; + } + + # Keywords is a little different + $body .= "
    • "; + if (defined $LJ::HELPURL{'upic_keywords'}) { + $body .= BML::ml('.restriction.keywords.faq', {'aopts' => "href='$LJ::HELPURL{'upic_keywords'}'"}); + } else { + $body .= $ML{'.restriction.keywords'}; + } + + $body .= "
    • "; + $body .= "
    \n"; + } + + # upload form + $body .= "\n"; + + $body .= "\n"; + + if ($fotobilder) { + $body .= ""; + $body .= "\n"; + + $body .= "\n"; + } + + $body .= ""; + + $body .= ""; + + if ($u->{'dversion'} > 6) { + $body .= ""; + } + + $body .= "\n"; + + $body .= "\n"; + $body .= "
    \n"; + $body .= ""; + my $url = LJ::CleanHTML::canonical_url($POST{'url'}); + $body .= LJ::html_hidden('src', 'url', 'urlpic', $picurl, 'url', $url, 'ret' => $returl); + } else { + $body .= "
    \n"; + $body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'id' => 'radio_file', + 'value' => 'file', 'selected' => '1', + 'accesskey' => $ML{'.fromfile.key'} }); + $body .= ""; + $body .= "
    "; + $body .= LJ::html_check({ 'type' => 'radio', 'name' => 'src', 'value' => 'url', + 'id' => 'radio_url', 'accesskey' => $ML{'.fromurl.key'} }); + $body .= ""; + $body .= ""; + $body .= LJ::html_text({ 'name' => 'urlpic', 'size' => '40' }) . "

    "; + $body .= LJ::help_icon('upic_keywords'); + $body .= ""; + $body .= LJ::html_text({ 'name' => 'keywords', 'size' => '40' }); + $body .= "
    "; + $body .= LJ::help_icon('upic_comments'); + $body .= ""; + my $comments = $POST{'comments'} if $fotobilder; + $body .= LJ::html_text({ 'name' => 'comments', 'size' => '40', 'maxlength' => LJ::CMAX_UPIC_COMMENT, 'value', $comments }); + $body .= "
     "; + $body .= LJ::html_check({ 'type' => 'checkbox', + 'name' => 'make_default', + 'id' => 'make_default', + 'selected' => '1', 'value' => '1', + 'accesskey' => $ML{'.makedefault.key'} }); + + $body .= "

    " .LJ::html_submit(undef, $ML{'.btn.proceed'}) . "
    \n\n"; + } else { + $body .= " $max }); + } + + $body .= " standout?>\n\n"; + + + + return; + +} +_code?> +body=> +page?> +link: htdocs/login.bml, htdocs/allpics.bml +post: htdocs/editpics.bml + _c?> diff --git a/livejournal/htdocs/edittags.bml b/livejournal/htdocs/edittags.bml new file mode 100755 index 0000000..6e23b17 --- /dev/null +++ b/livejournal/htdocs/edittags.bml @@ -0,0 +1,124 @@ + +body<= +" unless $remote; + + my $err = sub { return ""; }; + return $err->($ML{'.disabled'}) + if $LJ::DISABLED{tags}; + + my ($ret, $msg); + + return $err->($ML{'.invalid.link'}) + unless LJ::did_post() || ($GET{journal} && $GET{itemid}); + + my $journal = $GET{journal} || $POST{journal}; + my $u = LJ::load_user($journal); + return $err->($ML{'.invalid.journal'}) unless $u; + + my $ditemid = ($GET{itemid} || $POST{itemid})+0; + my $anum = $ditemid % 256; + my $jitemid = $ditemid >> 8; + return $err->($ML{'.invalid.entry'}) unless $jitemid; + + my $logrow = LJ::get_log2_row($u, $jitemid); + return $err->($ML{'.invalid.entry'}) unless $logrow; + return $err->($ML{'.invalid.entry'}) unless $logrow->{anum} == $anum; + return $err->($ML{'.invalid.notauthorized'}) + unless LJ::can_view($remote, $logrow); + + if (LJ::did_post()) { + return $err->($ML{'.invalid.link'}) + unless LJ::check_form_auth(); + + LJ::Tags::update_logtags($u, $jitemid, { + set_string => $POST{edittags}, + remote => $remote, + }); + + BML::redirect( LJ::journal_base($u) . "/$ditemid.html" ); + #$msg = "
    Tags successfully updated.
    "; + } + + my $lt2 = LJ::get_logtext2($u, $jitemid); + my ($subj, $evt) = @{$lt2->{$jitemid} || []}; + return $err->($ML{'.error.db'}) unless $evt; + + LJ::CleanHTML::clean_subject(\$subj); + LJ::CleanHTML::clean_event(\$evt); + + my $logtags = LJ::Tags::get_logtags($u, $jitemid); + my $usertags = LJ::Tags::get_usertags($u, { remote => $remote }) || {}; + $logtags = $logtags->{$jitemid} || {}; + my $logtagstr = join ', ', map { LJ::ejs($_) } sort values %$logtags; + + $ret .= "
    "; + $ret .= ""; + + $ret .= ''; + $ret .= "" if $subj; + $ret .= ""; + $ret .= ""; # spacer + + $ret .= ""; + $ret .= ''; + $ret .= LJ::form_auth(); + $ret .= ""; + + $ret .= ""; + + $ret .= '
    $ML{'.subject'}$subj
    $ML{'.entry'}$evt
      
    $ML{'.current'}
    "; + if ( LJ::Tags::can_add_tags($u, $remote) ) { + $ret .= LJ::html_text( + { + name => 'edittags', + value => (join ', ', sort values %$logtags), + size => 40, + class => 'tagfield', + id => 'tagfield', + } + ); + $ret .= '  '; + $ret .= LJ::html_submit( 'save', $ML{'.button.save'}, { class => 'btn' }); + $ret .= $msg if $msg; + } else { + # no widgets + $ret .= $ML{'.permissions.none'}; + } + $ret .= "
    $ML{'.users'}"; + + if ( scalar keys %$usertags ) { + $ret .= ""; + } else { + $ret .= "none" + } + + $ret .= "

    "; + $ret .= "$ML{'.permissions.add.yes'}
    " if LJ::Tags::can_add_tags($u, $remote); + $ret .= "$ML{'.permissions.control.yes'}
    " if LJ::Tags::can_control_tags($u, $remote); + $ret .= BML::ml('.view', { aopts => 'href="' . LJ::journal_base($u) . "/$ditemid.html" . '"' }); + $ret .= "
    '; + $ret .= LJ::html_hidden('journal', $journal); + $ret .= LJ::html_hidden('itemid', $GET{itemid} || $POST{itemid}); + $ret .= ''; + + return $ret; +} +_code?> +<=body +head<= + + +<=head +page?> diff --git a/livejournal/htdocs/export.bml b/livejournal/htdocs/export.bml new file mode 100755 index 0000000..9ebef97 --- /dev/null +++ b/livejournal/htdocs/export.bml @@ -0,0 +1,109 @@ + + +body<= + +" + unless $remote; + + my $ret; + my $authas = $GET{'authas'} || $remote->{'user'}; + + # no authentication needs to be done on this page, it's just a form anyway + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + $ret .= " h1?>\n"; + $ret .= " p?>\n"; + + $ret .= "
    \n"; + + # main form + $ret .= <<'HTMLBLOCK'; + + + + + + + + + + - + + + + + +
    +
    + +HTMLBLOCK + + # unicode encoding selection + if ($LJ::UNICODE) { + my (%encodings, %encnames); + LJ::load_codes({ "encoding" => \%encodings } ); + LJ::load_codes({ "encname" => \%encnames } ); + my $selected = 0; + foreach my $id (keys %encodings) { + $selected = $id if lc($encodings{$id}) eq 'utf-8'; + delete $encnames{$id} if lc($encodings{$id}) eq 'none'; + } + $ret .= LJ::html_select({'name'=>'encid', 'selected'=>$selected}, + map { $_, $encnames{$_} } sort keys %encnames); + } else { + $ret .= ""; + } + $ret .= "
    \n"; + + $ret .= <<'HTMLBLOCK'; + +
    + + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    + + + + +standout?> +
    + + h1?> + p?> +HTMLBLOCK + +} +_code?> +<=body +page?> +post: htdocs/export_do.bml + _c?> diff --git a/livejournal/htdocs/export_comments.bml b/livejournal/htdocs/export_comments.bml new file mode 100755 index 0000000..bef2724 --- /dev/null +++ b/livejournal/htdocs/export_comments.bml @@ -0,0 +1,158 @@ +{'r'}; + + my $remote = LJ::get_remote(); + return "" unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) unless $u; + + my @errors = (); + + my $dbcr = LJ::get_cluster_reader($u); + push @errors, $ML{'error.nodb'} unless $dbcr; + + # don't let people hit us with silly GET attacks + push @errors, "This page can't be viewed except via POST." + if BML::get_client_header('Referer') && !LJ::did_post(); + + my $mode = $GET{get}; + push @errors, "Invalid mode." + unless $mode =~ m/^comment_(?:meta|body)$/; + + # error stuff + return LJ::bad_input(@errors) if @errors; + + # from now on, we manage our own output + BML::suppress_headers(); + BML::suppress_content(); + + # print top + $r->content_type("text/xml; charset=utf-8"); + $r->send_http_header(); + $r->print("\n\n"); + + # startid specified? + my $gather = $mode eq 'comment_meta' ? 10000 : 1000; + my $startid = $GET{startid}+0; + my $endid = $startid + $gather; + + # get metadata + my $rows = $dbcr->selectall_arrayref('SELECT jtalkid, nodeid, parenttalkid, posterid, state, datepost ' . + "FROM talk2 WHERE nodetype = 'L' AND journalid = ? AND " . + " jtalkid >= $startid AND jtalkid < $endid", + undef, $u->{userid}); + + # now let's gather them all together while making a list of posterids + my %posterids; + my %comments; + foreach my $r (@{$rows || []}) { + $comments{$r->[0]} = { + nodeid => $r->[1], + parenttalkid => $r->[2], + posterid => $r->[3], + state => $r->[4], + datepost => $r->[5], + }; + $posterids{$r->[3]} = 1 if $r->[3]; # don't include 0 (anonymous) + } + + # now we have two choices: comments themselves or metadata + if ($mode eq 'comment_meta') { + # meta data is easy :) + my $max = $dbcr->selectrow_array('SELECT MAX(jtalkid) FROM talk2 ' . + "WHERE journalid = ? AND nodetype = 'L'", + undef, $u->{userid}); + $max += 0; + $r->print("$max\n"); + + # load posterids + my $us = LJ::load_userids(keys %posterids); + + # now spit out the metadata + $r->print("\n"); + while (my ($id, $data) = each %comments) { + my $ret = "{posterid}; + $ret .= " state='$data->{state}'" if $data->{state} ne 'A'; + $ret .= " />\n"; + $r->print($ret); + } + $r->print("\n\n"); + + # now spit out usermap + my $ret = ''; + while (my ($id, $user) = each %$us) { + $ret .= "\n"; + } + $r->print($ret); + $r->print("\n"); + + # comment data also presented in glorious XML: + } elsif ($mode eq 'comment_body') { + # get real comments from startid to a limit of 10k data, however far that takes us + my @ids = sort { $a <=> $b } keys %comments; + + # call a load to get comment text + my $texts = LJ::get_talktext2($u, @ids); + + # get props if we need to + my $props = {}; + if ($GET{'props'}) { + LJ::load_talk_props2($u->{userid}, \@ids, $props); + } + + # now start spitting out data + $r->print("\n"); + foreach my $id (@ids) { + # get text for this comment + my $data = $comments{$id}; + my $text = $texts->{$id}; + my ($subject, $body) = @{$text || []}; + + # only spit out valid UTF8, and make sure it fits in XML, and uncompress it + LJ::text_uncompress(\$body); + LJ::text_out(\$subject); + LJ::text_out(\$body); + $subject = LJ::exml($subject); + $body = LJ::exml($body); + + # setup the date to be GMT and formatted per W3C specs + my $date = LJ::mysqldate_to_time($data->{datepost}); + $date = LJ::time_to_w3c($date, 'Z'); + + # print the data + my $ret = "{posterid}; + $ret .= " state='$data->{state}'" if $data->{state} ne 'A'; + $ret .= " parentid='$data->{parenttalkid}'" if $data->{parenttalkid}; + if ($data->{state} eq 'D') { + $ret .= " />\n"; + } else { + $ret .= ">\n"; + $ret .= "$subject\n" if $subject; + $ret .= "$body\n" if $body; + $ret .= "$date\n"; + foreach my $propkey (keys %{$props->{$id} || {}}) { + $ret .= ""; + $ret .= LJ::exml($props->{$id}->{$propkey}); + $ret .= "\n"; + } + $ret .= "\n"; + } + $r->print($ret); + } + $r->print("\n"); + } + + # all done + $r->print("\n"); +} +_code?> + _c?> diff --git a/livejournal/htdocs/export_do.bml b/livejournal/htdocs/export_do.bml new file mode 100755 index 0000000..9340fe0 --- /dev/null +++ b/livejournal/htdocs/export_do.bml @@ -0,0 +1,203 @@ +{'r'}; + + my $remote = LJ::get_remote(); + return "" + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my @errors = (); + + my $year = $POST{'year'}+0; + my $month = $POST{'month'}+0; + + my $dbcr = LJ::get_cluster_reader($u); + push @errors, $ML{'error.nodb'} unless $dbcr; + + my $encoding; + + if ($POST{'encid'}) { + my %encodings; + LJ::load_codes({ "encoding" => \%encodings } ); + $encoding = $encodings{$POST{'encid'}}; + } + + $encoding ||= $POST{'encoding'}; + $encoding ||= $LJ::UNICODE ? 'utf-8' : 'iso-8859-1'; + + if ($LJ::UNICODE && lc($encoding) ne "utf-8" && + ! Unicode::MapUTF8::utf8_supported_charset($encoding)) { + push @errors, $ML{'.error.encoding'}; + } + + if (@errors) { + return LJ::bad_input(@errors); + } + + # from now on, we manage our own output + BML::suppress_headers(); + BML::suppress_content(); + + my $opts = {}; # information needed by printing routines + + ##### figure out what fields we're exporting + + my @fields; + foreach my $f (qw(itemid eventtime logtime subject event security allowmask)) { + if ($POST{"field_${f}"}) { + push @fields, $f; + } + } + + if ($POST{'field_currents'}) { + push @fields, ("current_music", "current_mood"); + $opts->{'currents'} = 1; + } + + #### do file-format specific initialization + + if ($POST{'format'} eq "csv") { + $opts->{'format'} = "csv"; + $r->content_type("text/plain"); + $r->send_http_header(); + if ($POST{'header'}) { + $r->print(join(",",@fields) . "\n"); + } + } + if ($POST{'format'} eq "xml") { + $opts->{'format'} = "xml"; + my $lenc = lc($encoding); + $r->content_type("text/xml; charset=$lenc"); + $r->send_http_header(); + $r->print("\n"); + $r->print("\n"); + } + + $opts->{'fields'} = \@fields; + $opts->{'encoding'} = $encoding; + $opts->{'notranslation'} = 1 + if $POST{'notranslation'}; + + $sth = $dbcr->prepare("SELECT jitemid, anum, eventtime, logtime, security, allowmask FROM log2 ". + "WHERE journalid=$u->{'userid'} AND year=$year AND month=$month"); + $sth->execute; + if ($dbcr->err) { $r->print($dbcr->errstr); return; } + my @buffer; + while ($_ = $sth->fetchrow_hashref) { + $_->{'ritemid'} = $_->{'jitemid'} || $_->{'itemid'}; + $_->{'itemid'} = $_->{'jitemid'} * 256 + $_->{'anum'} if $_->{'jitemid'}; + push @buffer, $_; + if (@buffer == 20) { + load_and_dump_buffer($u, \@buffer, $opts); + @buffer = (); + } + + } + load_and_dump_buffer($u, \@buffer, $opts); + + if ($opts->{'format'} eq "xml") { + $r->print("\n"); + } + return; + + sub load_and_dump_buffer + { + my ($u, $buf, $opts) = @_; + my $lt; + my %props; + my @ids = map { $_->{'ritemid'} } @{$buf}; + + $lt = LJ::get_logtext2($u, @ids); + LJ::load_log_props2($dbcr, $u->{'userid'}, \@ids, \%props); + + foreach my $e (@{$buf}) { + $e->{'subject'} = $lt->{$e->{'ritemid'}}->[0]; + $e->{'event'} = $lt->{$e->{'ritemid'}}->[1]; + + my $eprops = $props{$e->{'ritemid'}}; + + # convert to UTF-8 if necessary + if ($LJ::UNICODE && $eprops->{'unknown8bit'} && !$opts->{'notranslation'}) { + my $error; + $e->{'subject'} = LJ::text_convert($e->{'subject'}, $u, \$error); + $e->{'event'} = LJ::text_convert($e->{'event'}, $u, \$error); + foreach (keys %{$eprops}) { + $eprops->{$_} = LJ::text_convert($eprops->{$_}, $u, \$error); + } + } + + if ($opts->{'currents'}) { + $e->{'current_music'} = $eprops->{'current_music'}; + $e->{'current_mood'} = $eprops->{'current_mood'}; + if ($eprops->{'current_moodid'}) { + my $mood = LJ::mood_name($eprops->{'current_moodid'}) + if $eprops->{'current_moodid'}; + $e->{'current_mood'} = $mood if $mood; + } + } + + my $entry = dump_entry($e, $opts); + + # now translate this to the chosen encoding but only if this is a + # Unicode environment. In a pre-Unicode environment the chosen encoding + # is merely a label. + + if ($LJ::UNICODE && lc($opts->{'encoding'}) ne 'utf-8' && !$opts->{'notranslation'}) { + $entry = Unicode::MapUTF8::from_utf8({-string=>$entry, + -charset=>$opts->{'encoding'}}); + } + + $r->print($entry); + } + } + + sub dump_entry + { + my $e = shift; + my $opts = shift; + my $format = $opts->{'format'}; + my $entry = ""; + + my @vals = (); + if ($format eq "xml") { + $entry .= "\n"; + } + + foreach my $f (@{$opts->{'fields'}}) + { + my $v = $e->{$f}; + if ($format eq "csv") { + if ($v =~ /[\"\n\,]/) { + $v =~ s/\"/\"\"/g; + $v = "\"$v\""; + } + } + if ($format eq "xml") { + $v = LJ::exml($v); + } + push @vals, $v; + } + if ($format eq "csv") { + $entry .= join(",", @vals) . "\n"; + } + if ($format eq "xml") { + foreach my $f (@{$opts->{'fields'}}) { + my $v = shift @vals; + $entry .= "<$f>" . $v . "\n"; + } + $entry .= "\n"; + } + return $entry; + } + + +_code?> + _c?> diff --git a/livejournal/htdocs/files/.placeholder b/livejournal/htdocs/files/.placeholder new file mode 100755 index 0000000..2895e7a --- /dev/null +++ b/livejournal/htdocs/files/.placeholder @@ -0,0 +1 @@ +This file exists to make sure the directory is created. diff --git a/livejournal/htdocs/friends/add.bml b/livejournal/htdocs/friends/add.bml new file mode 100755 index 0000000..cb41149 --- /dev/null +++ b/livejournal/htdocs/friends/add.bml @@ -0,0 +1,209 @@ +{userid}; + $body = ""; + + LJ::set_active_crumb('addfriends'); + + unless ($remote) + { + $title = $ML{'.error1.title'}; + $body = ""; + return; + } + + unless ($user && $userid) + { + $title = $ML{'Error'}; + $body = $ML{'.error2.text'}; + return; + } + + if ($FORM{'mode'} eq "add") + { + unless (LJ::did_post()) { + $title = $ML{'Error'}; + $body = " p?>"; + return; + } + + unless ($remote->{'userid'} == $FORM{'remid'}) { + $title = $ML{'Error'}; + $body = ""; + return; + } + + my $gmask = 1; + foreach my $bit (1..30) { + next unless $FORM{"bit_$bit"}; + $gmask |= (1 << $bit); + } + + my $req = { + "user" => $remote->{'user'}, + "mode" => "editfriends", + "ver" => $LJ::PROTOCOL_VER, + }; + + + if ($FORM{'action:delete'}) { + $req->{"editfriend_delete_$user"} = 1; + } else { + $req->{"editfriend_add_1_user"} = $user; + $req->{"editfriend_add_1_fg"} = $FORM{'editfriend_add_1_fg'}; + $req->{"editfriend_add_1_bg"} = $FORM{'editfriend_add_1_bg'}; + $req->{"editfriend_add_1_groupmask"} = $gmask; + } + + my %res = (); + LJ::do_request($req, \%res, + { "noauth" => 1, "userid" => $remote->{'userid'} } ); + + if ($res{'success'} eq "OK") + { + if ($FORM{'action:delete'}) { + $title = $ML{'.remove.title'}; + $body = "$user, + 'ljuser' => LJ::ljuser($u), + 'url'=>"$LJ::SITEROOT/users/$remote->{'user'}/friends"}) . + " p?>"; + } else { + $title = $ML{'.add.title'}; + $body = " $user, + 'ljuser' => LJ::ljuser($u), + 'url' => "$LJ::SITEROOT/users/$remote->{'user'}/friends", }) . + " p?>"; + } + } else { + $title = $ML{'Error'}; + $body = ""; + } + return; + } + + # check to see if user is already a friend. + # TAG:fr:bml_friends_add:check_is_friend + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT * FROM friends WHERE userid=$remote->{'userid'} AND friendid=$userid"); + $sth->execute; + my $fr = $sth->fetchrow_hashref; + + if ($fr) { + $title .= $ML{'.error3.title'}; + $body .= "$user}) . " p?>"; + } else { + # was this a syndicated add? + if ($u->{journaltype} eq 'Y') { + $title = $ML{'.confirm.syn.title'}; + $body .= " $user }) . " h1?>"; + } else { + $title .= $ML{'.confirm.title'}; + $body .= " $user }) . " h1?>"; + } + $body .= " $user }) . " p?>"; + } + + $body .= "
    "; + $body .= LJ::html_hidden(mode => 'add', + user => $user, + remid => $remote->{userid}); + + if ($fr) { + $body .= "
    "; + $body .= " -
    "; + } else { + $body .= "
    $user}) . "\">
    "; + } + + ## let them pick friend groups + $body .= "
    "; + my $err; + my $greq = LJ::Protocol::do_request("getfriendgroups", { + 'username' => $remote->{'user'}, + 'ver' => $LJ::PROTOCOL_VER, + }, \$err, { 'noauth' => 1 }); + + if (@{$greq->{'friendgroups'}}) { + foreach my $g (@{$greq->{'friendgroups'}}) { + my $ck = ($fr && ($fr->{'groupmask'} & (1 << $g->{'id'}))) ? + "checked='1'" : ""; + + # by default, newly added friends are in default view unless unchecked + $ck = "checked='1'" if (! $fr && $g->{'name'} eq "Default View"); + + $body .= " "; + $body .= LJ::ehtml($g->{'name'}) . "
    \n"; + } + } else { + $body .= "$ML{'.groups.nogroup'}"; + } + $body .= "
    "; + + ## let them pick the colors + $body .= "$user}) . " p?>"; + + $ret = ""; + $ret .= "

    \n"; + + my @color = (); + LJ::load_codes({ "color" => \@color }); + + my $sel = $fr || { 'fgcolor' => hex '000000', + 'bgcolor' => hex 'FFFFFF', }; + + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    $ML{'.colors.fg'}$ML{'.colors.bg'}
    \n"; + + ### color swatch + my $col = 0; + $ret .= "

    "; + foreach (@color) { + if ($col==0) { $ret .= "\n"; } + $col++; + my $ecolor = LJ::ehtml($_->{'item'}); + $ret .= "\n"; + if ($col==23) { $ret .= "\n"; $col==0; } + } + if ($col) { $ret .= "\n"; $col==0; } + $ret .= "
    {'code'}>\"$ecolor\"
    \n"; + $ret .= "$ML{'.colors.hover'}"; + + $ret .= "

    \n"; + $body .= $ret; + + $body .= "
    "; + + return; + +_code?> + +body=> +page?> +link: htdocs/login.bml, htdocs/create.bml, htdocs/friends/edit.bml, htdocs/users +img: htdocs/img/dot.gif +post: htdocs/friends/add.bml + _c?> diff --git a/livejournal/htdocs/friends/edit.bml b/livejournal/htdocs/friends/edit.bml new file mode 100755 index 0000000..902cec8 --- /dev/null +++ b/livejournal/htdocs/friends/edit.bml @@ -0,0 +1,290 @@ + +body<= +" unless LJ::text_in(\%POST); + + LJ::set_active_crumb('editfriends'); + + # this file used to be edit_do.bml, but edit.bml died, so we moved this + # functionality to edit.bml, but we don't want the translators to have to + # retranslate all of the phrases, so we're still using /edit_do.bml scope + BML::set_language_scope("/friends/edit_do.bml"); + + my $remote = LJ::get_remote(); + return LJ::bad_input($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + return BML::redirect("$LJ::SITEROOT/community/members.bml?comm=$u->{'user'}") + if $u->{'journaltype'} eq 'C'; + return LJ::bad_input("Cannot modify friends of this journal type.") + unless $u->{'journaltype'} =~ /^[PSI]$/; + + my $ret; + + # no post, show edit form + unless (LJ::did_post()) { + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, + { 'authas' => $GET{'authas'}, + 'type' => ['P', 'S'] }); + $ret .= "
    \n\n"; + + $ret .= "
    \n"; + + ### who has you defined as a friend? + my %res = (); + LJ::do_request({ + "user" => $u->{'user'}, + "mode" => "friendof", + "ver" => $LJ::PROTOCOL_VER, + }, \%res, { "noauth" => 1, 'u' => $u }); + + ### who do you have defined as a friend? + my %resf = (); + LJ::do_request({ + "user" => $u->{'user'}, + "mode" => "getfriends", + "ver" => $LJ::PROTOCOL_VER, + }, \%resf, { "noauth" => 1, 'u' => $u }); + + # build hash for checking if user is friend + my %isfriend = map { $resf{"friend_${_}_user"}, 1 } 1..$resf{'friend_count'}; + + ### table of friend-ofs + if ($res{'friendof_count'}) { + $ret .= "\n"; + $ret .= "\n"; + $ret .= ""; + $ret .= ""; + $ret .= ""; + + my $friendnum = 6; # 1-5 are new friends from the add form + for my $i (1..$res{'friendof_count'}) { + my $fo_user = $res{"friendof_${i}_user"}; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    $ML{'.user'}$ML{'.name'}$ML{'.opt.addtolist'}
    " . LJ::ljuser($fo_user) . ""; + my $dis = $isfriend{$fo_user} ? 1 : 0; + $ret .= LJ::html_check({ 'type' => 'check', + 'name' => "editfriend_add_${friendnum}_user", + 'id' => "editfriend_add_${friendnum}_user", + 'value' => $fo_user, 'disabled' => $dis }); + $friendnum++; + $ret .= "
    "; + } + + ### table of friends + if ($resf{'friend_count'}) { + $ret .= "\n"; + $ret .= "

    "; + $ret .= ""; + $ret .= ""; + $ret .= "\n"; + + foreach my $i (1..$resf{'friend_count'}) { + my $fruser = $resf{"friend_${i}_user"}; + $isfriend{$fruser} = 1; + my $bgcolor = $resf{"friend_${i}_bg"} || "#FFFFFF"; + my $fgcolor = $resf{"friend_${i}_fg"} || "#000000"; + my $status = $resf{"friend_${i}_status"}; + my $userlink = LJ::ljuser($fruser); + if ($status eq 'deleted' || $status eq 'purged' || $status eq 'suspended') { + $userlink = "$userlink"; + } + + $ret .= ""; + $ret .= "\n"; + } + $ret .= "
    $ML{'.friend'}$ML{'.name'}$ML{'.opt.delete'}
    $userlink"; + $ret .= ""; + $ret .= ""; + $ret .= LJ::html_check({ 'type' => 'check', + 'name' => "editfriend_delete_${fruser}", + 'id' => "editfriend_delete_${fruser}"}); + $ret .= "

    \n\n"; + + } else { + $ret .= "\n\n"; + } + + ### add friends + $ret .= "\n"; + $ret .= "

    \@color }); + + foreach my $i (1..5) { + $ret .= ""; + $ret .= LJ::html_text({ 'name' => "editfriend_add_${i}_user", + 'size' => '15', 'maxlength' => '15', + 'onchange' => "updatePreview(); return true;", + 'onfocus' => "setFriend($i);" }); + $ret .= ""; + $ret .= LJ::html_select({ 'name' => "editfriend_add_${i}_fg", + 'selected' => '#000000', + 'onchange' => "updatePreview(); return true;", + 'onfocus' => "setFriend($i);" }, + map { lc($_->{'code'}), $_->{'item'} } @color ); + $ret .= ""; + $ret .= LJ::html_select({ 'name' => "editfriend_add_${i}_bg", + 'selected' => '#ffffff', + 'onchange' => "updatePreview(); return true;", + 'onfocus' => "setFriend($i);" }, + map { lc($_->{'code'}), $_->{'item'} } @color ); + + $ret .= "\n"; + } + $ret .= ""; + + ### color swatch + my $col = 0; + $ret .= ""; + foreach (@color) { + if ($col==0) { $ret .= "\n"; } + $col++; + my $ecolor = LJ::ehtml($_->{'item'}); + $ret .= ""; + if ($col==23) { $ret .= "\n"; $col==0; } + } + + if ($col) { $ret .= "\n"; $col==0; } + $ret .= ""; + $ret .= "
    $ecolor
    ($ML{'.hover'})
    "; + + $ret .= "

    $ML{'.needmore'}

    \n"; + + ### ending submit block + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + + return $ret; + } + + # if they did a post, then process their changes + if (LJ::did_post()) { + + my %request = (); + $request{'mode'} = "editfriends"; + $request{'ver'} = $LJ::PROTOCOL_VER; + $request{'user'} = $u->{'user'}; + foreach (grep { /^editfriend_/ } keys %POST) { + $request{$_} = $POST{$_}; + } + + my %response = (); + LJ::do_request(\%request, \%response, { 'noauth' => 1, 'u' => $u }); + + if ($response{'success'} eq "OK") { + # tell the user all is well + return " LJ::journal_base($u) . "/friends"})." p?>"; + } else { + return "
  • $response{'errmsg'} p?>\n"; + } + } + + return $ML{'error.unknownmode'}; +} +_code?> +<=body + +head<= + + +}; # end qq{ } + +} +_code?> +<=head + +page?> +link: htdocs/create.bml, htdocs/lostinfo.bml +post: htdocs/friends/edit.bml + _c?> diff --git a/livejournal/htdocs/friends/editgroups.bml b/livejournal/htdocs/friends/editgroups.bml new file mode 100755 index 0000000..4cabe00 --- /dev/null +++ b/livejournal/htdocs/friends/editgroups.bml @@ -0,0 +1,425 @@ +"; + return; + } + + my $remote = LJ::get_remote(); + return $err->($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $u; + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + if ($POST{'mode'} eq "save") { + my %res; + $POST{'mode'} = "editfriendgroups"; + $POST{'user'} = $u->{'user'}; + $POST{'ver'} = $LJ::PROTOCOL_VER; + LJ::do_request(\%POST, \%res, { + 'u' => $u, + 'noauth' => 1, + }); + + if ($res{'success'} eq "OK") { + $body .= ""; + } else { + $body .= ""; + } + return; + } + + my %res; + LJ::do_request({ 'mode' => 'getfriends', + 'user' => $u->{'user'}, + 'ver' => $LJ::PROTOCOL_VER, + 'includegroups' => 1 }, + \%res, { 'u' => $u, + 'noauth' => 1, }); + my @num_used; + my @num_free; + + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + + $body .= "

    "; + $body .= "

    "; + $body .= ""; + for (my $i=1; $i<=30; $i++) { + my $sort = 255; + my $name = ""; + my $public = 0; + if ($res{"frgrp_${i}_name"}) { + $sort = $res{"frgrp_${i}_sortorder"}+0; + $name = LJ::ehtml($res{"frgrp_${i}_name"}); + $public = $res{"frgrp_${i}_public"}+0; + push @num_used, $i; + } else { + push @num_free, $i; + } + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + } + for (my $i=1; $i<=$res{'friend_count'}; $i++) { + my $user = $res{"friend_${i}_user"}; + my $mask = $res{"friend_${i}_groupmask"} || 1; + $body .= ""; + } + + # escape strings for JavaScript + my %T = qw(public .group.public + rename .prompt.rename + newname .prompt.newname + delete .confirm.delete + max30 .error.max30 + ); + foreach (keys %T) { $T{$_} = LJ::ejs($ML{$T{$_}}); } + + $body .= <<"END_JS"; + +END_JS + + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + + $body .= ""; + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= ""; + + $body .= "
    $ML{'.yourgroups'}$ML{'.ingroup.not'}$ML{'.ingroup'}
    "; + $body .= "

    "; + $body .= "
    "; + $body .= "

    "; + $body .= "
    "; + $body .= ""; + $body .= " "; + $body .= " "; + $body .= ""; + $body .= "
    "; + $body .= " "; + $body .= ""; + $body .= "
    "; + + $body .= ""; + $body .= " p?>"; + $body .= "
    "; + + return; +} +_code?> +body=> +page?> +link: htdocs/login.bml +post: htdocs/friends/editgroups.bml + _c?> diff --git a/livejournal/htdocs/friends/filter.bml b/livejournal/htdocs/friends/filter.bml new file mode 100755 index 0000000..29b28df --- /dev/null +++ b/livejournal/htdocs/friends/filter.bml @@ -0,0 +1,74 @@ + 30); + $filter |= (1 << $bit); + } + my $extra = "?filter=$filter"; + + return BML::redirect("$LJ::SITEROOT/users/$user/friends${extra}"); + } + + my $remote = LJ::get_remote(); + + unless ($remote) { $body .= ""; return; } + + my %res; + # FIXME: make this use LJ::Protocol::do_request + LJ::do_request({ 'mode' => 'getfriendgroups', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $remote->{'user'}, }, + \%res, { 'noauth' => 1, 'userid' => $remote->{'userid'} }); + + + unless ($res{'frgrp_maxnum'}) { + $body = ""; + return; + } + + my %group; + foreach $k (keys %res) { + if ($k =~ /^frgrp_(\d+)_name/) { + $group{$1}->{'name'} = $res{$k}; + } + elsif ($k =~ /^frgrp_(\d+)_sortorder/) { + $group{$1}->{'sortorder'} = $res{$k}; + } + } + + $body .= ""; + $body .= "
    \n"; + $body .= LJ::html_hidden("user", $remote->{'user'}, + "mode", "view"); + $body .= "
    "; + + foreach my $g (sort { $group{$a}->{'sortorder'} <=> $group{$b}->{'sortorder'} } keys %group) + { + my $url = "$LJ::SITEROOT/users/$remote->{'user'}/friends/" . LJ::eurl($group{$g}->{'name'}); + $body .= " " . LJ::ehtml($group{$g}->{'name'}) . "
    \n"; + } + + $body .= "
    "; + $body .= " "$ML{'/friends/editgroups.bml.title'}" }) . " p?>"; + $body .= "
    "; + + return; + +_code?> +body=> +page?> +link: htdocs/users, htdocs/friends/editgroups.bml +post: htdocs/friends/filter.bml + _c?> diff --git a/livejournal/htdocs/friends/graph.bml b/livejournal/htdocs/friends/graph.bml new file mode 100755 index 0000000..9f4784c --- /dev/null +++ b/livejournal/htdocs/friends/graph.bml @@ -0,0 +1,27 @@ +1 +_info?>"; + } + my $user = $u->{'user'}; + + my $ret = ""; + $ret .= "User: $user (user info)
    If image doesn't load, press reload.

    "; + + $ret .= " diff --git a/livejournal/htdocs/friends/index.bml b/livejournal/htdocs/friends/index.bml new file mode 100755 index 0000000..f1e2a8e --- /dev/null +++ b/livejournal/htdocs/friends/index.bml @@ -0,0 +1,34 @@ + +body<= + + + p?> + h1?> +

    +
    +
    +
    + p?> +
    +
    +
    +
    + p?> +
    +
    +
    +
    + h1?> + p?> +
      +
    • +
    • +
    +<=body +page?> +link: htdocs/friends/edit.bml, htdocs/friends/editgroups.bml +link: htdocs/friends/filter.bml, htdocs/download/index.bml + _c?> diff --git a/livejournal/htdocs/go.bml b/livejournal/htdocs/go.bml new file mode 100755 index 0000000..828b85e --- /dev/null +++ b/livejournal/htdocs/go.bml @@ -0,0 +1,60 @@ +{'userid'}+0; + + $itemid = int($itemid / 256); + + my $jumpid = 0; + $title = $ML{'.error.noentrytitle'}; + + if ($GET{'dir'} eq "next") { + $jumpid = LJ::get_itemid_after2($u, $itemid); + $body = $ML{'.error.noentry.next'}; + } elsif ($GET{'dir'} eq "prev") { + $jumpid = LJ::get_itemid_before2($u, $itemid); + $body = $ML{'.error.noentry.prev'}; + } + + if ($jumpid) { + return BML::redirect(LJ::journal_base($u) . "/$jumpid.html"); + } + } + + return; +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/img/addfriend.gif b/livejournal/htdocs/img/addfriend.gif new file mode 100755 index 0000000000000000000000000000000000000000..49a8cfbc4dd1338bf4d4397b9d9d9947593c130f GIT binary patch literal 905 zcmZ?wbhEHb6krfw_|5>}tm~h}wBd4;K499{+uARKBQFk~R9Gsc>ESW3{ z91`4m#n@#O6b>w8oFJk*N#*6H2X0ff8FlVh1V8ti%FMu0A)&zF!NlAp$D`oj5Xj`y RuBYo2`ttBjl(aG_FU-u&=-U$6O-4~@F`RQv_Y|q%2_d-FqQP{qkC!d3Zmw~sZ LmmyY1k--`Or0-dj literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/blackdot.gif b/livejournal/htdocs/img/blackdot.gif new file mode 100755 index 0000000000000000000000000000000000000000..26735dd150c446b7a35b39f2b611b61df7aa273f GIT binary patch literal 35 jcmZ?wbh9u|WMp7uXkY+=|NsB%fM}2i0~3=ABZD;nd{G71 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluedot.gif b/livejournal/htdocs/img/bluedot.gif new file mode 100755 index 0000000000000000000000000000000000000000..b23ce814560e1f2f72a094b3df2e51af3e5f53c3 GIT binary patch literal 799 tcmZ?wbhEHbWMp7u_|5eXb6nd5YPc-0Z?9G;9y~3WMN^j1^_|q{iFZ@ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/bluefade.jpg b/livejournal/htdocs/img/bluewhite/bluefade.jpg new file mode 100755 index 0000000000000000000000000000000000000000..29fd31fca92a27300d5a3bd4e6807e12f600c987 GIT binary patch literal 1445 zcmex=LJ%Z3brs z7G`D;Vqs=sWnp1u<6>t60$xro4laIP0Retqem+5A2@yddaUni_Q5jKjNl9sGX#o*g zd08oW2`OnQkRgmLtgLLTY&`7jJW_)Ef>I=d{|6WZIT%tH8JHQB7?=bZnFSgDA7PLH z`2pw)B*4bX!~v9%5ny0uU}Qy-U=T@M$jBrt8U&P;1nXi(mStgMVh3rI5(L@-gh+r% zNJLOL@&7Fb9%e?M-OPdv_6(mjOadA?s@pf|?RYqcS46>y@5CJA#zie0jyHwd3P5t! zN(JZGx&##2Q~V?kTy$blc++{K=USbo(CBVnFPvQC@_MnMZrnr zg+q(6)!uNILjsCiB??ZwaZ`L0nFN*tExr13&jp?r+ynYw}48s+R;@3B?Z*>w-WLq>qN*8iAv>Xg*IpCCVGAq_) zmoOt|6G-U5l|Vg^;0mV%MFUe2?}Y{eGqeO|aQN`L3cc`QQR8Y+V-jW#93&b*2}4Vu zkt1cR-lA9z0cd~%QwTKZFEnyMLmn6{kbtM7GEiFBe|-D7=KlP-JnK63Rx@%4wEbt0 zyKlv3yRSq_CA6W1!?_+P$qp3a71BC@q@Jx)Gy#}q?mxc$+!17iOVyG MQsIKhWdDB?0JMd`I{*Lx literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/bullet.gif b/livejournal/htdocs/img/bluewhite/bullet.gif new file mode 100755 index 0000000000000000000000000000000000000000..53083b720f79e09fd0698d22f2251f6ffedbd394 GIT binary patch literal 116 zcmZ?wbhEHb9_og=WMyvz4_Y0 i-~4TlJf^8>E_roo+dJ;#pM0)=>wW&~-1k~W25SHU!X*Cy literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/home.gif b/livejournal/htdocs/img/bluewhite/home.gif new file mode 100755 index 0000000000000000000000000000000000000000..ea17d70b0bb406f4fc6cf8c194247429c3b1d676 GIT binary patch literal 1300 zcmZ?wbhEHbRAEqI_|5TBZnqwLD-zoXOSI``Cuh$|uKu6h^1ry}fAy6AJ#+p~ zS^9s@+W$+p{@=Ry|K4N&j{(8C|L3m#zjp8c^XLEHzyJUJ`~Oie8Uh0t0tXHpQ2fcl z$iVQQK?jr*KzV|J;~&F+P8p943l27O2y4Zh*s$<$J9Fp)i^e1+t`08$6*o>4CU=QQ z84B5a6g+x-l6r955ep?(*Df*LpgEmMEJp-|edky#oc#RUJllG!Cz*>@1TI$YP%|}T z(mcFOb8I-SvR&{07SkIquu~Z}>JPmlrq$Ft^`7P~Xp6XS(C#{XOhyHxBHv{Jinp zU#t216n7rrmfDnlVqUGz_jh6YKXqR}(D0y@Tk_KC^9E(M)vMoKUF_}gP47tqMc(&zf1sYo|tL8GXIhJ&M!Pr}1ii8PJyHVHNZ2S))9fkhok zehiJBLLD!{yHvJGG&m|bDJ1t8wM8tBF}bAixSLHk;BmjhFIGopBcaG-1{<-GgG}5e z2bN6s(JPo0!y9sQ$>a#N%m7wSoeQbc1Cx%XFvVBBRGq{nS>V9LzUJn#*(sYe(`V<% zH9T_?76~}OSoLY=@_F_DPA;Dtr8Q;wf(|CD7xT)kR2UZ3?UP)=(CgH)WWhu+hs>o) ToGmJoW*6Ohxq^k2g~1vCPrRIZ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/hr_divdot.gif b/livejournal/htdocs/img/bluewhite/hr_divdot.gif new file mode 100755 index 0000000000000000000000000000000000000000..76dd2c718e98e196fafaf67bbcfb12c48712e692 GIT binary patch literal 166 zcmZ?wbhEHb#u-@o5`|NYwg@8_O>Klc1RgX*5W_ug;4_kQWM=X1_I zpK|Vb&$;I<$L{?H104n+0O@65i56&3II?3qo29O%TZBOKhQRxcEo?p=VmJbI1Y%mEfBNyOwoE S1hmF4nar-DG?PJ)!5RPoFiPx!EC2ui02u%o z0009*2)f+}*y*TU5yI+AY41`sjXo^y5yGpJ*8FX!@v#lF%wCg>{?{>-!c}2;Q X7JMv`1>+DEP%fK}C$^zYMiKx!N%1z2 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/sidebarfade.gif b/livejournal/htdocs/img/bluewhite/sidebarfade.gif new file mode 100755 index 0000000000000000000000000000000000000000..132de86b831052dc753699efeae209cc422a1c85 GIT binary patch literal 284 zcmZ?wbhEHblw^=(XklQue&hL#TQ6?id3opVtGoAK-+%Dt!K1g2p1gbV^!>BvAD+MX z`0~}K*Ka<*dHdzv`>*dmeEaz6`{&O;zJC4r?fb7EKYsuG_2>8RzkmP!`;Pt;^ZXRiJZzi_M*ib?+@7{y(rlAVNc`|HPAv2Xd_D2Ru*oS{t=K zw59Cy+p3+N8!CMC`bA%CsX7~`fA7PN8oBfv?|h% literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/sidebarfade_line.gif b/livejournal/htdocs/img/bluewhite/sidebarfade_line.gif new file mode 100755 index 0000000000000000000000000000000000000000..5376a2245ce128b7427f9bd87a50c62e59f95799 GIT binary patch literal 428 zcmZ?wbhEHblw^=(Sjxa~{l;?!28RFt|KGUvf`^Ca)}5CU5)!xXzEV+9xqJV$fq}vO z2XAa_Y#uy%>*3+?=<&OdkdVhu-zO#}K7IBfH#hhBi;tC+l`md?YHe+O_4@O~i4$MH z`8;>-+_&$(tX#SB{rj)mwr%_H@!O$8hdzD!e(v14&tHDrx^?U8*PqXxJ^TLs*QZaP ze*F0T>(`&(zyJRI`w!?0Qi0-67Dg@xdj=h#FMvLhWME)B>CjN%!NStlw4_K=!eagf z#>7)=#Ma%&Ie1{L5&we?KN>Wur+03tnj5g={HfL&zj%XpA5xOfzc-g@sAS@AX>H>d z=xh?~>FpB~n%E>fW$H9xk(o`RbLP$y6iqPK;*jy!!0N!LC!`hg;!%PCgEatqQ~av{ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/title.gif b/livejournal/htdocs/img/bluewhite/title.gif new file mode 100755 index 0000000000000000000000000000000000000000..f04875695800e156e457dd5a5a7077eed3b84ddc GIT binary patch literal 2906 zcmeIxi8~XF1HkbKx#pHK$IB3N=h%2jNpr0z4QtsQvFhP?N0sx!= zsQfwM&l3PnCV-t&!mO$6eIlo@lJjs=`9O+*tVNL-uHr-51uZ|yFs^baQ`-2sgn4rn zF-Oq`<4kO>9(kkT2?kzmLES9i4%!4tx1h&MuODj}&e&NX2W68cu9g*^Ec zb*j!m){Y%;Z+!;qsAnfB-d0aeaT~|*cIhlTVExrI8bJ8n`L>7yQ2dr?qwBNK!v0eP z9kSH_%nfyCKrv*6G#kqEuCHe$=3csc4qi_!3PSgce$Ns~4ycKQe!4?47*sPT-o zRqcY_n`c|`uv~u;=H2ljpMNbCH(ixh@Z+0&B{y z%Vooh)3l}R!AZ&$!!I-RA1R1FHZnw?OM_$Rp0~}fk-@iZ#^hyRKwZQNVvXHXCsQrv zIputdvTB7Mx63$ITYk!=Ro}U=23su*P7s?f%F-dOC*3vaxStnAazvN(=E`l9Jp$2g z-NkzQ`ea6HiqZ;_dUZW3G*D;3)%j-`1+l>WeCm@5DUfWrYYfB5C&A=CrkaWBCqt@A z4Y{O33_8i^$`nFJ?NwaAlQKrUJZ`<`Qw}oqiS${y%{2jW7XmgG3;h&rK>a==q0#vT30&-QTSTu9u(sUDdCzed zSWKj4Z{vI=8xb4vbor6}Aze|R7XHiUPD;8a6^MNIMzo=2SZ6^ZaAH()N-GBeUED=e zh+Ibv+E%BnLzc!PMdO6;24Tb2_>=NLzwvGzyi1BxK^;2%%eGKZ#*+~#P!e# z1`f*Szq}eNNd=y7-R`*Q#LimwF{R&1$<%!VAy{)kG{qSgFxKj>-oy+zbSKvR1OxaO)ZbwCFnGE${K9TaX=sQ=1 zV)mY$CRTj+814c2J#aW|cCYg>Gm>=`OcQ(IB02yyVoGKtdR?F5vv2?Ktz-PDX4R5N zwIco!;bltDlr(RC)R5XbF4gW(20O?xq|FrYHv+CPJ>rqAEhS?w~P-hQ!9n2@k8dx@UHXQCfmZF1W5Q%Xy|yiw zpIfczM9G_$rl=H4w|W91l?|$_DkMgjr|(;OUwcK>I7qe1-fVeo#O4E!Of~Q(HCOO` zSOUs}Zu?@atCUqMIT{_|NNby4r`f}qVdek2v+RdX4=N%jZak=;IW z8$me?(zei6X9J@w(sZHAwUeh8%Da1f1JSi#5>_hwbt=Y1PP-j6_g+@d%})?$JMRHO z{c^#mrxjd^wYKk-YHa{boLy$M$r~hx-*g~@Og^{0#kJ%Fu1J%u3@s56BTl#%rIn7O zo%9~cDiX0QiM4WC*ktFX4VUP#7Ts!Z~-IH8$verB(?uZx0H3mH~m)AAl) zAaY`;uFlD-%$%VYW*gV?->t3s<}Fih@YqCWDiOTjq#S<{NmOWhXaX^AQt>*3&W)(d z_{XuU%m9vmggo87Sd72^)pUjKBXky*!X@G5#ZoYlA7ECM8P^4)wNE^~87}DFJri%? zs9$NhU-b(jI2u5oR%$y^bWz@ze(mJ@cqFW>L3GQF#_-X6MJ=eKt=9C4;REiB<8mk$ zBR>U!CzBWIc5Jr0JM_ADd4I0Fz3eB?ztAG860y<#D&W~l2XQ4(!JNeLpv1ik1^N!9 zVxR`${L^65g`aK5>1#UzCx%BR^q!r|zDufAi#<6n29#mQ=UNhAmhO-q_T>|{mM zEwko|kzw|8;k(PND7>k!U+{yLlPSpkU+{17-yWw>)&(!=)!$|Y=gxMo!8jOW(HY<0 Vs28F16n+umOe9KQP8tBv{};#eGgJTo literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/bluewhite/vline.gif b/livejournal/htdocs/img/bluewhite/vline.gif new file mode 100755 index 0000000000000000000000000000000000000000..ad6a3feb0bf737df913a0d8ed3f960e4308b30e9 GIT binary patch literal 115 zcmZ?wbhEHblw^=(SjfO|{pJe>28RD&p!k!8k&A(uK?f)Tl$B&)U~*~c7tnsIKPiSW zYUYYoiI;Cnj@QnZS_SefModn+%QKeNfOU~@n=Ig(d Qa*j(?uXo?7RSXQ)0I$(5?*IS* literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_addfriend.gif b/livejournal/htdocs/img/btn_addfriend.gif new file mode 100755 index 0000000000000000000000000000000000000000..59dd43c4186fa6aba7666cd212b986e9fbd55610 GIT binary patch literal 1006 zcmZ?wbhEHb6k`x!_|5yzpT8>Ft z6i4l_cy!2TmRa<^B_}ScpPkBWS`-rTW%;RzTvKPoT)dp=wL)0i=xfAOHSRTh$xSy7 zD5-Yysv5+_Fcux@7Pr0ZCBp5%WLG1^z%W7DY#}QHw}Q!q+YC%BYz)(kTrwIR+t}OK z%}?A^XnM4^*HmJj0MmhXfd$Sr3?C-6wQ`G!=@c|DGPGUa;Hj_XxO>~%+dDj2SQxAU Dz$BrHQKMF=eVC02>4g(N?@&W@#0RuaSjK_ur2N{@I zG-6I{NOW%DQ+8|7*tp24i;023Ln2Vwol(NHD#xNo@mPI80wywUuK7pBq Hg~1vCGFd2S literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_dn.gif b/livejournal/htdocs/img/btn_dn.gif new file mode 100755 index 0000000000000000000000000000000000000000..2ebc830aee472de071713e77a10a1e3e080046aa GIT binary patch literal 598 zcmZ?wbhEHb6k`x!IL5$m=FFLvmX`nj|8L&BdDEs%J9q9BRc6?@aifS5Lr}Eq%$YOS zuV0_JSYYOvw5FYUX=%niJG>|C2@sNHNSnzpVZYbZBmV8}?HwH*zR?y=&JKamPHAar zTeogqd#0|kvNAN6zHFW5@_w@F5^i7;Nq1%F; zg?Z*o78ch2&Mt0gUo9(6&LAlbX&2_6DGXdb&O8Ew3dW*lPUc+e7celp`I`zm1Q>ej zsQYp6@8NQ_3p5fI=HoRHo8MzEr(~;qO@vpT zdRV1ZBs3;IKB|(?z_V&VdgCi&Pj`%VzA5__)}8vb^D< S8qozyPfs^UX5(OCum%8}uMraf literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_edit.gif b/livejournal/htdocs/img/btn_edit.gif new file mode 100755 index 0000000000000000000000000000000000000000..6adddc8fc04350e54b3787def2a618d95192c128 GIT binary patch literal 380 zcmZ?wbh9u|6k`x!Sjxcg|NsA%mX>43jxiV}S4S21Bv)GoRktKp2Nh4@FidtzZt=?Q zvCN($;niXoR4rhc9o2Je>AnAR&iz*mYSE0E5;f)6oNND=Ui+`;lwG{^o>%o&ua>Qv zK|K;))!B2dWiP!J)Us7EsHb}C^Xjed85EAW<#gR2?D343jxiV}S4S21Bv)GoRktKp2Nh4@FidtzZt=?Q zvCN($;niXoR4rhc9o2Je>AnAR&iz*mYSE0E5;f)6oNND=Ui+`;lwG{^o>%o&ua>Qv zK|K;))!B2dWiP!J)Us7EsHb}C^Xjed85EAW<#gR2?CBD!6<41~BL_00GF83~Ut+4Fw)LQp^mEMJIF2CZ5X>(aPmx^T`Ue)DYR=m0PO7 zSTp^RMr1Hk`{ZQK+kfQ_C*-P!9)6$A#%RD?<6j`<%;Xu)?9`Ic);^J8Vx3gKSIuPS uNt0_!nPyI!GI!eig|nv3Ub<}R+ST);gEBWp7Hp|v+_`J_p1q8Y4Aua=VXbul literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_freeze.gif b/livejournal/htdocs/img/btn_freeze.gif new file mode 100755 index 0000000000000000000000000000000000000000..8e4b2cd16c282e91cca3c1f71d5a990e148edac0 GIT binary patch literal 1052 zcmeIxYfn-E0LJlCxwNu!rLMNt+N>=rn=V_L%bBF2)wmW~Zdyj0K{BPh24J zk~sO&$kEFq$pwSQi^Unm(yS7B)*UIfbUg2#;`GC@iw{*7YUKqrQg#VFDkfa9qRz18KlW>d1B%AlDhLR*I{41t?Ih|-2F^kFM~#L5^$Iwh;nF3C)n6lIROpUKc}*$ijY z$5hxkQV&<+>yym0#~nP`0!QiWRk^q-SKp+of9j=Z+%Hrv@YHUx(l4Cy4QOWt+F7C2 zE7HyhA&&_1h;`mUy?03O9ey!40{djTz$omKPX{E1d8u(;W_l$zzfxEh#x09RqjAEz zsI)GsO(CVtuQ7#GHow_yR@(xQWqAsHt)5xZ*q5~SCCCxbIp4f^`PSeLnmq5!tGpqL zH)QoKqx0|W3m=^Rk1H!Hv8nz4{mTP~fYtqN0f_hwq;A-SmGcadyrly?&lDnvW>U9A zM*=XM#fUF*q+E&0z%cs{AEc4_0t{i@?)2!pybm7niSsepSOx}-O|DJc0b(My?K@j$ z+^GGwHXHxR=d(xBeV2=RN_6ArUg8)9D8!prYBeEv|LPt^E3-mdLDxJaW`h;%sH} c?M@+ug>~1oCMXIVupavPHK$tjJ2p{Ay0>(;H}3=IFDJ^O#=j2{Do1OtO41B0ih=lkv3jTsn@ zD=OX!2zWDh?sj(e6RxiQ3=At*u51U|m6o;=XwJ-;JJ{Lp<>nsn^xUee+r_}Jm7DwF zym{}-%ioulE)*2J=PO`q5&PCyBR=!VPM;R zprOD+M~aoPq3C3e*~D`hBD;KCMA%sv3Ikk(&My&424kt*19CGLt+BjyCk?zCi)(-5K!c~a_ZW3 r7HPA)!DoCp___J>{X+bN)P#Z<-hB@G`t2>#?>~S4{by=oV6X-N$-R{W literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_next.gif b/livejournal/htdocs/img/btn_next.gif new file mode 100755 index 0000000000000000000000000000000000000000..32f51612821d22c21561de4718471bb4b06b042c GIT binary patch literal 604 zcmZ?wbhEHb6k`x!c*ekR=FFLvmX`nj|8L&BdDEs%J9q9BRc6?@aifS5Lr}Eq%$YOS zuV0_JSYYOvw5FYUX=%niJG>|C2@sNHNSnzpVZYbZBmV8}?HwH*zR?y=&JKamPHAar zTeogqd#0|kvNAN6zHFW5-(%Qzz#L(5<)7#t8H*w;G zNmIL~bTe~tPn+J^&FW(AC&n^u1_O(pyyC`(wMo!`aGsSt2USCfrHPnz|1&pkm0BV|uEAuny2p8Zw= z!hyCNHqweUh2Be>9C_uHj5IvdCtPe)bDk&iv0#CamW=caiNFt!uQ)JpiyV2?vg-2U Uezn=G5hph-Jw2U~iIKq?0N~rGK>z>% literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_prev.gif b/livejournal/htdocs/img/btn_prev.gif new file mode 100755 index 0000000000000000000000000000000000000000..052ee2ecb229da547b657def8ce8560a88a151a4 GIT binary patch literal 600 zcmZ?wbhEHb6k`x!c*ekR=FFLvmX`nj|8L&BdDEs%J9qAsP-j@be!a1=@ywYs!}=L` z#Thnk+*nps@bUW#89fFKXU4!b2IDjabti_jv^2j)hKR`UC-1LxbaYfyREVlD9J{lu zv#X6?l40xCt>yJuMj;GNE)IO+48dIt#>Nb3GmYI!7&dI!@bvw)o39SEx3`O_GECbO zckRJ3g8&8|5k^TZ29I(EXguZ{Wrb#*No(lKmQ@lbanUi_IC75oH$|9)UGMh*g2W|JEyW}iCD?A_RQ#ImJo5( zwRU7#Hm`?M(nQ8w!(ESKL-z~|P7yH%K5=OsXCsa|`!=b2xM(`rTdH~q8JynO&B`kv zq$bG4r7XmD>uislDF>U1kfErM_KWG8x*bIH*@T4@q`orDc{EMoNE5rQ)rVVZodkXaui{Icemez+epkJVc{b literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_scr.gif b/livejournal/htdocs/img/btn_scr.gif new file mode 100755 index 0000000000000000000000000000000000000000..44b4c3c1b78e3a037b4d51be387011fc0eb9ae6e GIT binary patch literal 138 zcmZ?wbhEHb6k`x!Sj524!ocwV|Nmphj;9XmE-#*Cw;-am8Ckux^7c2(8Y*KR*NapFWkKtOC(}4B`{>StC#NsoICJUdjXMu3Dyz3`+a@j{X=!b{WcixIr!HApS=ZLqtyr-l zAUGl?zi`5Y3DaiGYG|L>-Q67!7`$=Uktfez9XWDj+4|k`@(QosywAxma(3}}|MBy| zLx+}c+*4cMl$eq>f92M-+YTN*bGfl|Qe0y4w(UC>E?;-xz=4-<-fh{wtEFd}xVXgb z!>2D_zdLvC+=Z*ROG-(tUANxO-m!ne#K6$#)45NU?A)xq^ z1#E*3hy>*c29Ey>f}AoM8yF5YGxIBY9hs2W%*M!6li{&(p;H^*P z$)in4h~eOgUe4S(R#%miG8);%&#js0?6~^8z2Y7{1pyXc5#u(#FJCy9cZF;5`7jh3 zJ!xQFTfD}j_Q6p$PNSe7e>x@~WMb2cU82>X(Cp4`o0FWpJ0+?aIEw<0IP_i@(Pukw@d!U7J0C|3$6B7gj)e`G2&emvVQ2ZT#6B(9W(U9Wu`&$dpRcBg4E@59e)gzB!SmDQ9uW#9N(^|^Li#1{>(re-rv25SIw C4N6ooOQKMg7w^v)g+0dcR+@;FGXNsYr zLGUt@;8muft4zX|PjK+CN?10-C)hP@ok!{>ugr}zLu0-3*97Hn4J_FZUc5cDW=(YM z=BWA&QH|>pYInvouTQSqnOwgszIk&)Lqkr>!HkZb+3kC?I(8Ry?xao>TW z{(Xg$x0UrBspvaaICV$a#DkR+j@C>%UOr<_+05P5(+^e5+FdvGSnZ6%)pPbXPCwB! z{Z!-3rPHzePPP_ zle1S}oxS16^o^%yue&sN?bUf}ug%@-$JvVRLx%u1AFWq!& z$(9=nc3fDt<<_EI7Z>lkxOCT*CA%*z-F<1_311(D}QEFFibR>EY4KkB(h=aPr!d(>I=;z4`3yt!HY}Jqi!Evhx^SsbFddlG2orn)1P^M6E;A zqG7=b14qUNBdHw@tF|m(b%@Wf&fw*yWquq?3_6-cCM$byIw!?YHD7$#$iN^xX}3;ajAOF9z+!Q$ z2M-uk5+_gG-I!3b;E?*o#ggWCu4Fzs;-Geii<|dkV}~2JXuGK11CbXKj literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_unscr.gif b/livejournal/htdocs/img/btn_unscr.gif new file mode 100755 index 0000000000000000000000000000000000000000..165cb2b87185e30341a17558b4a2f700120ab65f GIT binary patch literal 120 zcmZ?wbhEHb6k`x!n8*MEhYlTTXlVHV|G(l-7O;R0hy=+qFnP}DUupD^KRIPnSk~sl zw?1*SJiOY#pyIbwW!}LbHGa3fK1uSelwQALVwGcx@vWQ}&a9QQpLBCNM`bPXYs<(@ RTYbCp0XJXw@g^n)YXIWhE`|UA literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/btn_up.gif b/livejournal/htdocs/img/btn_up.gif new file mode 100755 index 0000000000000000000000000000000000000000..0b9fcbf6383479c8944742cb8c65256366cbaded GIT binary patch literal 590 zcmZ?wbhEHb6k`x!IL5$m=FFLvmX`nj|8L&BdDEs%J9qAsP-j@be!a1=@ywYs!}=L` z#Thnk+*nps@bUW#89fFKXU4!b2IDjabti_jv^2j)hKR`UC-1LxbaYfyREVlD9J{lu zv#X6?l40xCt>yJuMj;GNE)IO+48dIt#>Nb3GmYI!7&dI!@bvw)o39SEx3`O_GECbO zckRJ3g8&8|5k^TZ29I(EXguZ{Wrb#*No(lKmQ@lgOblJ!J-xjheG?~6n8d1XF=jJbskxm2aiMOgZea=P&g zi7I>PXt-+K?Pj*)wp9@N=s}vTGQ$q=W)|LR|m<|37o)Odu~UE$z&i zGsecoT(%FAf&4;G7srr_Ia~W3`5F{>SQH=3eZZcg%zr^#KYf&Ey4`SOt%8nu x#`9@{E9b7C&b>Kf-#q?HopZJ<@Vsz-7o$@;Us%$LVnLwg44$rjF6*2UngIU~O9cP` literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/3.png b/livejournal/htdocs/img/captcha/3.png new file mode 100755 index 0000000000000000000000000000000000000000..780a608a61b403c9d3e06cb4f58eb186f53e7f7f GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|37o)%(S#Lpn$Ql z@tHGcI=oU>0y#~dE{-7;bGA-6$lIX6>dAu%g8&-DISefK!$+ixbDPJA)G_3+Q;`mYRf_k<4Ky!~r6 P&@~L6u6{1-oD!MQ$q=W)|LR|m<|DTqY2IQSNb7tnu zna0M(Z?~JI1Nr`*E{-7;bGDv8$jP9{<8skuBfqS)fVang*Odw>MR!ua&;OL5C-~FA zRrRdG29pf7#-#?6wmv!aLglDJq;UAX>8leae4Eg6J9uu;k8f-1au{Vjctu=RuG9e< O&EVQ$q=W)|LR|m<{|{uIIdf*_%$aFv zX~xFJ`Rl(#0)@&vT^vIy<|HR9kP={F)@bK!J>GLD+3}$v7ng$MB8`lOBgP^j4v#Fk zq`0{bvmQw6SP&)NkTjR$jukUos^f}4pJPr5%@fxqwqzc8q#)6M(}m%U4f~3jhdh=U zIOaBFakAXjQ$q=W)|LR|m<|9|GpnVBFMq5O^|U*7HII~YOZ7pn73)8a)6=F z%8i^JTQz-VD^4&8YWXnZL6kw|nPZHLjyZC~XQ$q=W)|LR|m<{|{u&oH_H%nKNl= zX~xFJCw*@%0SbkBx;TbZ%t=mIAeJD~!my~)$zzr%tEhlXnxmkKrkG=*$~?tQPHhf> zDty9SPGJWb=G>BDohaLvB)v*er-{kK#?6s^j++#hl)^`mixnEz9zMJ%#K6$LnC(~c Sl8j2A1q`09elF{r5}E)s(lmYm literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/8.png b/livejournal/htdocs/img/captcha/8.png new file mode 100755 index 0000000000000000000000000000000000000000..550eab55520f93e395e9bd3d925348ddc4730c18 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|9|GpnVByTlQ|e?OCDed=3+TlFnuONC7VH?hR3;32G{w_XMEIE zj2C{}DO4u8%FbQ$q=W)|LR|m<|37o)%(S#Lpn$Ql z@tHGcI=oU>0yzzyE{-7;bGDxM=4&?KVF{RSRxR*qUyz=I(Mir74q8?JH(%kiI8r_1 zZm?alaO|{p|MzU{=T_WuacrGcw8u%yu-g*UtVd?5_gyQ7UA#D_!IfWU4AUTQ$q=W)|LR|m<|37o)Odu~UE$z&i zGsecoT(%FAf&5%g7srr_IcLxNay2Ljv?c!M6G;30=M1xmY{CZVlK+RNJeskEe^%=U zg?+08_RD1o${bcWA279R+A7^i77u>jsMB|df0cU7{n#^~Rz2Tqoi9361$T8F`ZFyh uljYRae;3!z%>T?8Vy?bs$*t*jbGhAJcxJtnRdNGb%;4$j=d#Wzp$PywLrn|- literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/b.png b/livejournal/htdocs/img/captcha/b.png new file mode 100755 index 0000000000000000000000000000000000000000..d59eef1b7f5cf9b339129f857f76fb90230c3fed GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{uIIddj0Ep6t^ zna0M(Nf!4?fkM%qE{-7;bCMGlhzW=+;q;HZz;ZBIR78ZQ=`&NKjU%gse?;TS00V|& z#t8`tq9RQn8@gt&xK79w5OI6RDRem4;o|d#B()1kX)U#j6t+t&*dg35FEK~(-(p<` Z1}07}arNAWwLohaJYD@<);T3K0RReWH|YQX literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/background1.png b/livejournal/htdocs/img/captcha/background1.png new file mode 100755 index 0000000000000000000000000000000000000000..1a949a112a1a0896396d7345c63199702a2aed6f GIT binary patch literal 13205 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 N002ovPDHLkV1k0ltzZBE literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/background3.png b/livejournal/htdocs/img/captcha/background3.png new file mode 100755 index 0000000000000000000000000000000000000000..a3ead9b1e3f44454b0eedb58feeb9c4366def826 GIT binary patch literal 6965 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 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/c.png b/livejournal/htdocs/img/captcha/c.png new file mode 100755 index 0000000000000000000000000000000000000000..ce3860d79c02c7dff6bdc8305d618674e1ded622 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|9|GpnVBV527Pu5gmawC(0m#*;N-iz?3~1Sc?D^>GsqSNR=qx9OQ*h<(GK=Pb`Jh%qp% X?iG-_D12!p&=LkuS3j3^P6Q$q=W)|LR|m<{|{u&oH;WsE$z&i zGseco2f|`*TOcD#k zT0TXvxE^#8kej@KBf_%fIM1@gWd=fLov*fMsjaHzX>-`V{8`@c ds{9rs!{*ss3uk;a4+Gl7;OXk;vd$@?2>`&uKVSd= literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/e.png b/livejournal/htdocs/img/captcha/e.png new file mode 100755 index 0000000000000000000000000000000000000000..2a960cea61dc6caf011ee462f16b3ccf71ba2472 GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|9|GpnVBXbGom>X14yd@sFgZB! z3C!#2W?*Js+^y^*-BD85^dUy!fMo0Qre5(!O>guz%q(Eo#(#3=Iwl?;M*~*11m^|c n3^(jrP~oI;M3v*FiWC!rioIyGqH0Pv&{76ZS3j3^P6Q$q=W)|LR|m<|37o)Ok-nXpg>w$ z+L<$Fv{ZvO06B)9E{-7;bCMGlND3I0xfC?@_WBCgBqk?2vz)(S(ZD$KctdwO4-1>i h#}6}&QYx;nGOV1;qwzhg^%zhygQu&X%Q~loCIIgzDwzNP literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/g.png b/livejournal/htdocs/img/captcha/g.png new file mode 100755 index 0000000000000000000000000000000000000000..971631fbb080c734eda8369a879c79c296a5bf56 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|37o)%(S#Lpum|k zXN--FD*`n^+A2L=978JRoSk6F)nFjt%HFv*d;JU6GySy+H@J8Hk3C~{F(T5+x5D7_ zbb-IsR%=*PEEs%z4l$N3;|k(Fol+ol)yK9ZqJK-vbk6xJ_h_4X?>F*3p;^rSc*RK< z<+k1NB~v|9IgU$bYu%5xHMtuv(Ed>@a^cn)rhA_=xvde8U>4+g19Sv~r>mdKI;Vst E0GCoq9{>OV literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/h.png b/livejournal/htdocs/img/captcha/h.png new file mode 100755 index 0000000000000000000000000000000000000000..27ca6f48d6f471d6c0ca16c8d03a1b83100d7d64 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{uIIdf*_%$aFv zX~xFJ`Rl(#0)^~6T^vIy<|HR9;7kw^S-{$VGT;cqL1PgSk&uRuEsZjciW2@8Ivhg- vB#sFuCL}Nk3dng(T%fRtw|Sy_DFcIj2iuayXvWh(lNdZ*{an^LB{Ts5I0Y>B literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/i.png b/livejournal/htdocs/img/captcha/i.png new file mode 100755 index 0000000000000000000000000000000000000000..e3a0e915406ddb7d2e85406d416b7248f62aa561 GIT binary patch literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?$P6T-j~TxPQfvV}A+G=b{|7Qd4_&SUQX-x% rjv*Cuk`oT_=LB&6*>pwm10zGrB9@IF0uL7eQ$q=W)|LR|m<{|{su8ynA@IrGe! zGihmQTejuq0)_NET^vIy<|HR9P)ZOHQJCb;ZQQQx&)Au+k-?B|%+1ARrSREB@YM`a eSHU0-28O5BEHhr`y*&)n$>8bg=d#Wzp$Py7ye2LH literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/k.png b/livejournal/htdocs/img/captcha/k.png new file mode 100755 index 0000000000000000000000000000000000000000..a48ca17e01645f1090e89baa3bc06681df5e9db9 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{uQrKK4g8_%3M z^URquoQ#hhfkLsKE{-7;bCMGlunUMR;qCVfkm!7_kf*wQGuP~?r6VoJC*7n{Pz853i9L$sRSM7!SAQLGl^rQ$q=W)|LR|m<{|{uIIddj0Ep6t^ zna0M(Nf!4?fkLjHE{-7;bCMGzCOHI5aE!dr(RecS0_T}zQ4tZ70u~`Yg*b%?id;vU zoD}A9FdMfBFn*Mgn4!?3(XpICT|vT;M@=r2fuZs!=YRdVXDQ$q=W)|LR|m<{|{uIIdf*_%$df< z#%XD3on=PsKp|UC7srr_ImrnUs~iF*I7VKGWIUHFDk37%_F1OU#*tORKcw+w;01Q$q=W)|LR|m<|37o)%(S#Lpum|k zXN--FD*`n^+G0Fi978JRBqvDhayW4#fZ?2=85cf literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/p.png b/livejournal/htdocs/img/captcha/p.png new file mode 100755 index 0000000000000000000000000000000000000000..71e6a72cbfe917f635aaef383ffc2f49ecaf8775 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{u&oH;WsEzQ{2 z_{^Cz20lyA1BKE&T^vIy<|HRb9BBv)XgC=V!FaG(L_~zM;iC&nql3sXVUtu2F_E^@ zjGpcX88rBpXaoc>rg6Gb*?aY9HSUawvnRtDnm{r-UW|f*d?D literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/q.png b/livejournal/htdocs/img/captcha/q.png new file mode 100755 index 0000000000000000000000000000000000000000..3c6a1136b5556aa50287381246b0663aa7b6bd2f GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|37o)%(S#Lpum|k zXN--FD*`n^+R{B;978JRBqvB*aX1k%@!$=KQ-!8xW_%4FBN}9qgC+V;-ni1}DtWBf zj4vS}q4i@+uk3+SiZ-bRypJV?&oaMGb~KzUm^hz_nc4V|t{b1u!Gdsh<=w(hv|8jH l{slY!;6EAm>eB%RhKo-{lIEq@{sCIa;OXk;vd$@?2>?9)LM{LR literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/r.png b/livejournal/htdocs/img/captcha/r.png new file mode 100755 index 0000000000000000000000000000000000000000..f75c2ee43e2d0b59a7532afe18d0db4755f72d71 GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{u&oH^6j*f=dM z?aY}oCI|Ou1BJ9bT^vIy<|HRbY;p*gaPk6Yr?`ej*AZip5Qj&di(UjfJY;?F(2z$; c?kEGpGe4Fz`SQ$q=W)|LR|m<|9|GpnVB7tx+JdlH7;t`>xJ2EUQ$q=W)|LR|m<|37o)%(S#Lpum|k zXN--FD*`n^+N?ZX978JRBquBoPH=gssazb>JF)WEkxxC12O2cwKBir26wi6na75V5 qOw8fKoZenh0UNPYWfe;=Muvm#+z!*VOH_fTFnGH9xvXQ$q=W)|LR|m<{|{uIIddj0Ep6t^ zna0M(Nf!4?fkL*PE{-7;bCMGz7BvJ0FnDlr@de2V_Z-*JIC9_s)8maCU0Mc`hbkOg uo0=9G$TcfX5NCL9xRcB3;MpZi3=AJ_*<^K>aQ_Ax#Ng@b=d#Wzp$P!+Y%M|n literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/v.png b/livejournal/htdocs/img/captcha/v.png new file mode 100755 index 0000000000000000000000000000000000000000..71df0d6e9b25b75fc86973279fe899ae523b6fa1 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|9|Gp86a=w%$df< z#%XD3yO{$+f&4O07srr_Iam7*@-`?4u!LW*-^djEB!9($h{lEglWZ*fr9M2iGn3>v z%w&J|fX3UMTJvUKIpM4se5x>fmSmPKzk8g6Cx4}$L-5v)ycO!Rgr5F0IyHL_uUp^2 znL;ymJP!{NeST}X(am*gOW$6~jg4HoviXnf$Jo4G$2kA=U#Lt4x`4sc)z4*}Q$iB} D^si6~ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/w.png b/livejournal/htdocs/img/captcha/w.png new file mode 100755 index 0000000000000000000000000000000000000000..115c919340ad647d5be3f3bc6a55a0203b6f1d82 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<|DTqY2IQSNb7tnu zna0M(Z?~JI1NoCYT^vIy=3MQ+$a~m;!$rUBmwYAD?>GP4=N(9DTJf9za&t<{KM_ur zj%tPv)59v5I!~$b|NP{l8|<-W-U?UVoHz4AQp_|;Dp|H3Y@GYdQ7F@7?kooF1L;}P z`Rl%?owqq#p7n17*E*v;r`A|4y5hhzUvV#QT%hFA`8-RUU#@Xr(tj)dy7vE;-FC$` g`o}!^KZ$>1wI~+K%2zsg2Ix8lPgg&ebxsLQ0IJ+v3;+NC literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/x.png b/livejournal/htdocs/img/captcha/x.png new file mode 100755 index 0000000000000000000000000000000000000000..ca5cc35fd82d6040fc6cb022dcffa1054a6ef9c8 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{uQrKO!Yb7tnu zna0M(UwT{50fn+WT^vIy<|HRbta1q8@X+9Ls%&fG>L1)Lj{1LjCB o6FF4SqLs=z`#4LummvcK%RG+$fQ^gNfVMJty85}Sb4q9e02}o>8~^|S literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/captcha/y.png b/livejournal/htdocs/img/captcha/y.png new file mode 100755 index 0000000000000000000000000000000000000000..2a996b85e458a7b59e0ba77adf463034e7ab62f4 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA?!VDxQtL>Q$q=W)|LR|m<{|{uQrKQcBIrGe! zGseco9~kCn0fj0(T^vIy=A1ouo3}xMhc&=~?E}}p!)!Aw7~bulqI-UlMT2if(L!6t zmG;x!7RUu&ZkuZr<14mrYfw!r`wqPiMOiN$^_DMQxu@J@#fz#g6mdC%$sGvACSA$7MngWEfKkm8ezPBlz<89NNMIt~)FnGH9xvXQ$q=W)|LR|m<{|{uIIdf*_%$aFv zX~xFJ`Rl(#0)^Z>T^vIy<|HRbY;q9b>3GP#!hjKt|N(pA`XuvxwI54 z&Sa!XD9l!DI+7^L0r5dH3`}x8{FSFUd78U@FMeHTrgz;g UG2ut0bZXp^tW51&a;yy20Ba@_^Z)<= literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/colorpicker/pointer.gif b/livejournal/htdocs/img/colorpicker/pointer.gif new file mode 100755 index 0000000000000000000000000000000000000000..09f896acf9847e9985421106173401fc3298df58 GIT binary patch literal 52 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 OAjj;SZL1CkUHM;*I}c)dt&hd>5| Rxf_Cq>+G6nKS=iy!iJY2T=UU!pOkD k!Jxwc1RygQScET#7`ZU0%}y?T7H8JN<|wvAkdeU}08P+1p#T5? literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/corn_nw.gif b/livejournal/htdocs/img/corn_nw.gif new file mode 100755 index 0000000000000000000000000000000000000000..33285e211dc11f9025c8feaa4f8e74f422f6e2f5 GIT binary patch literal 102 zcmZ?wbhEHbWM^P!c+9}?@87@g-~WC3^zZH4e~%yiyLj>6nKS=iy!iJY2T=UU!pOkD k!Jxwc1RygQScC;w3_T1#&&X|gc8nqKNJh*uNk#^109c(mIRF3v literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/corn_se.gif b/livejournal/htdocs/img/corn_se.gif new file mode 100755 index 0000000000000000000000000000000000000000..b6fc2c82d35495c4e6829c25ea6135d45a1b4c35 GIT binary patch literal 101 zcmZ?wbhEHbWM^P!c+9}?@87@g-~WC3^zZH4e~%yiyLj>6nKS=iy!iJY2T=UU!pOkD j!Jxwc1RygQScEQ|@JwIX_8_o-L0p2!5d{_p76xkoI5#?R literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/corn_sw.gif b/livejournal/htdocs/img/corn_sw.gif new file mode 100755 index 0000000000000000000000000000000000000000..f3a2cc40c8a27bc88c871558a48d5b13f0718fb7 GIT binary patch literal 100 zcmZ?wbhEHbWM^P!c+9}?@87@g-~WC3^zZH4e~%yiyLj>6nKS=iy!iJY2T=UU!pOkD j!Jxwc1RygQSOhPe$mE*(WY)r?I~&~@A38(`GFSru1FAbK literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/delcomment.gif b/livejournal/htdocs/img/delcomment.gif new file mode 100755 index 0000000000000000000000000000000000000000..a7448d28fdf882ef31c00294f62d54801c19f2bc GIT binary patch literal 907 zcmZ?wbhEHb6k`x!_|Cx40z@q>$BrHQKMF=eVC02>4g(N?@&W@#0RuaSjK_ur2N{@I zG-6I{NOW%DQ+8|7*tp24i;023Ln2Vwol(NHD#xNo@mPI80wywUuK7pBq Hg~1vCGFd2S literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/dot.gif b/livejournal/htdocs/img/dot.gif new file mode 100755 index 0000000000000000000000000000000000000000..7cc6edcc6dd8ece798e36da0104fb8b82d1291d2 GIT binary patch literal 807 zcmZ?wbhEHbWMp7u_|CxazlGs{56Ax=f&Wt^{?AeTKS%TbQp5jio&K-&`oA^k|JJDg zdz1ek%l?0?`v19>|JQo{Uz_s(-kkr>m;Qgg_W%36|Gyvm|NY$m|M&ing3%Bdf+3*z alZBCiL7YK{0SG{Of`NmDL7#<%!5RPqR_)sW literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/dot_green.gif b/livejournal/htdocs/img/dot_green.gif new file mode 100755 index 0000000000000000000000000000000000000000..ba883b8006129c4d42262bec61cc9bf1333199fc GIT binary patch literal 152 zcmZ?wbhEHbH}b;eSI0Lk5Oq28KBdUeA*mfZTJ2 zhUb!#&&^>l1WGU{{$ybUQVcpE0%V2*i>ts1Pwj+`1zYuV+9#@uZF`PS*ME%Iz^)yq!@HS1jq~r7I%RYp4tvt+jGw>@GBBIG*P2BdF|?E70yLr zj}$r5jSZ$A=9zo0$#u>iz7x$%fsP8yjZW{38zaqm+43J9cqJj*badnI&hFJ54AubS Cx;B*n literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/dot_yellow.gif b/livejournal/htdocs/img/dot_yellow.gif new file mode 100755 index 0000000000000000000000000000000000000000..f66ad86b2bc289f3309392c32f9fd35368c9364d GIT binary patch literal 154 zcmZ?wbhEHbUw?jC{<6IL=Wf8SfSG@03j7h+{AaW4AJ>(CR>u5^S^jIe z?=RovU&-!&+*N<6GX7%J|D`YdOIYNWi1#mVre918|15O;<;eMqv;9xI`Y(0)U-JKv zfZ|UUMlJ?<1|5)1AUhdY!yl;krDV>_;9_{TiYema-Xebi1BreVol7E!pdTvryu>T z+Wk+x?7Pm_qKi*{-hBEk@OrJoi;9rx&vhIA9zA;W@}tkH-?CnR__gxFj}!NPXG}V> z^WZ#2Wt{Ftm_nh)lIOul9l2=}>SI?X|Q`s?N+T6uw z?tHm>=bxzi*#id-JUsHBGx++?FaO1VCHdc~ee(9dXzb%pU;p2G@il+?u@CS6Ke+MT z`)Q}`+xlgPUtK%;ZS~1d<}-fV&G=^3{W0_CwyQh-UOVw)%Zfj5UjNhknBO{K&Xd<) z3|jx@bZoM1c)#V^?>~S3e|z^|x%|bg$Nw)J{%<$+^Wr6Uj@(+VQt8Ux<@$%)%ch3A#4c-3f+fQJmjRI+=L#f9K3?oM&A8KtOO)#o8>2esq$Cf9lgFm=vH2?)F}gG~h_WQfI4)T1CFsne zDR4@-^V-|sMtL$1GBp`} z&NMY<{7Kld;1d&%t$;@4#dc3eVJE%_QGu2-GMxMZYi34FI6X}|ghl3u5ObH5Y?O?z zVbF(`DKaV+1re8)oSr9M;#DJ|Bf#2f(VsOV(c!OvpuW75M1ru`VkKK;rVdW=`~wF# L_Ej-6F<1it+tQGM literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/grey_gradbg.gif b/livejournal/htdocs/img/grey_gradbg.gif new file mode 100755 index 0000000000000000000000000000000000000000..e65c46a922aa29c35bdbeb19ed1532c799295d6b GIT binary patch literal 272 zcmZ?wbhEHb zW<1W;ym{s|=k*WV?_-R)(%_OT6d9v2%lBw;q)&wCwIfR1XNz{<(|**TG5h>u!v09XBxC;$Ke literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/help.gif b/livejournal/htdocs/img/help.gif new file mode 100755 index 0000000000000000000000000000000000000000..8b894f8269775475e36f98f465e0a3325ceb35f9 GIT binary patch literal 558 zcmZ?wbhEHbtskLnQmkW=rK%mFZIq&Il&oWvq-|ENZJeTQS*dMNu5FsB zV_mCbU88MPsbXHGZP%b}Td!hSWf{_E89Ko-w9hiU&mm!&d**!ijCl^pGcD3)+T<*> zOrPnLx4^w{fqT({(3)i;fxSj)GmX<`nxxIN%wKAmzr+-%taz1G{t~manRbPX?Ftq- z6fJfvTH;W+$gya#Q}Gg)lI5;t%bg47yO%EZC|%-SG~cIcMQFq7)ZQ&Z0X-rieP)?6 zZHks!WY4nBUtm|V#I|68O~E{el4TA>iyTW9xs)!BXj+xpv(Y$frb+fJ%aUc5MT;$q z7Fie0x6A?BIM2RlzC-aG^P&Z&c{8m_msl0fbu3@xST@hGbnbxz2mb&6&p;QT_>+Z^ zfgy%L2V@&4P8is`8)BN8tk_r;n>%B~1w8!yT=_)0cukyx9DIUxLK&MS%%i1am&8g( z8VWZF$*3$*Sr@DA&K~1s8?s^766Gi@1tvAsT^lz9YBF<&%kGZd6=u(1t>kicgR+IX zd ze&6Z${h{)Ch9k*8+75K3D4n(_zVJec5u0IVn1+?--U$#=T(xHH?_))b7xK&>Og;CB z_b%TFfhHHxlPps+ug$x_LZngRc|fDoqd-O(IV`?gU~ReE*z#`vMdnVeNt{}Tr&!MK zCeEnR_#K7J6KAC_6v}xGG;02nw-Yv;o4`C_1ycoQ^rVxTxQ#ML_aMlqdk!ftP?%Qy8DF6>F-s4BN>velEa(~CH;s2i z$V9Bk%Npp(e+G7nqLEDvXU$GX81{rS_AswVd9h$?*1;|pfdfl@uGHkRZ}e$M|H)cz z&1RIjQl#kIiW0A>YFN#)irBT~pSOue>yitT3<@tg-blS<&@sbIK>NAofn7pheq4!u gvG1eir5X1;9}5aqHa~t{9H}+yT$3)BCj)~u0L;iGc>n+a literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/icon_private.gif b/livejournal/htdocs/img/icon_private.gif new file mode 100755 index 0000000000000000000000000000000000000000..c4ba706922e0c238c8c5d7451fdff75ae282f122 GIT binary patch literal 120 zcmZ?wbhEHb6krfwSj524Ru=XD|NkdXo}52_o`Hb@$Oe)?p!k!8k%57gK?lSEsbyfc zjo5YPpMjI3woLO2-)J>PMur7yI`I~Ls)fr|xv?#reQ_hlrESM1Tg_WNL1=9h^OW-) TUuw))&agU9jac8q!e9*ms-G&< literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/icon_protected.gif b/livejournal/htdocs/img/icon_protected.gif new file mode 100755 index 0000000000000000000000000000000000000000..196a3e3f510361581562c8806a34d424b1e13952 GIT binary patch literal 111 zcmZ?wbhEHbCMz`~#d;)2vNFq?R+ zy0mFRtKpH3Pm`7{{Cf9Or=oD*qQz!P5B9y+I1sYttX?Ryk?oD1>FMG-$ IEFlJK0JcymR{#J2 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/imageplaceholder.png b/livejournal/htdocs/img/imageplaceholder.png new file mode 100755 index 0000000000000000000000000000000000000000..e1303d4e681dca800bebffd959981def874917e9 GIT binary patch literal 4426 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 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/imageplaceholder3.png b/livejournal/htdocs/img/imageplaceholder3.png new file mode 100755 index 0000000000000000000000000000000000000000..970437cd476893ec320b065ba96bc3502840b902 GIT binary patch literal 1280 zcmV+b1^@bqP)WFU8GbZ8({Xk{QrNlj4iWF>9@00d-7L_t(|+U=K3Y*bYg z$A9PE``(+GcG|)eii}^a1*ahmEKH0MV_X`(vtv7EC6K`VgVw`qEUpD1B(S5*Pv_wqJgNs*sSxTnh|icU<9-XCEwy{g(DC* zLd*y;1qq`_7$I)JGn#!Vm!Hr4Nnv&Y*HI*t;2A~Clcu@Tlz;-X62S8HFB24Q`FKX* ziV!z~t5-<4W~Fa5?CErvx|Ab#ZJxNRNO(eA2??dSo1cx3K!FIHpIqWnp~M%%lf)fC z8*l`S5sVQWr4S|TZc&^nEK_o~)7GBi_;*=6&k%D3*YGbQpkT2QaPne-S28;pzBtQB zZW&h;MhlJtr3Ftzx<#|ivwSspg`^RN2Y+K`*pq@y|d$@c^{LTQ(|iE}6sB-Big9>*Gw zc275rK+|h@K40X^(^q-CvxWTpGTOrFziyD()k3DL6{A2xgyG*WX_-ycR z3X@Cp@7+O!pgNx=H#kI3CQa|l830Q2l{G@?{%(3Q>Bi+3RuxgKX%5U3E4=ge0LfG< zt-HIKb&}*u!c=aVVi0k9Vcr*M#YtK+n1e1VKPwUmtUGb9WUS)oS%WYt%cgVGsms&swp#o7&k_Nw$Cg{*~-4 zmDV)jLy+kq;H*VpadEM!Cal>eguNbBpjhj?@R0wE-Uki=9a47`j{$pD_4-z$0*nDu q(vT1F)!#MQVgeCRUMpVHu>X3%^Xop(@8_I9Z}I)OF7WFi&#%YaKkxAUddU6z zCC87;g8yMa@t>%3QEFmIYKlU6W=V!ZNJgrHyQgmegW^vXMlJ?<1|0?<06B(%HS~dc zUrOe@j8*G29xx?+IJYi=+o0h6p9W#p=7fR`iZu*QNfSbJ7jC&0rwudrS8wgT<_EzeN|bMl>`wDJwEq0{}_ma6_CX>@2HRA^-& zM@dak03rDV0SW*D04x9i002M$5C8xIp@feq$++DfR6y8^F9k^rVfaS%mITPGK%n${1J_d%#3=Fdv7#1-wEN5U?#lWzJfngH^!&U}{Jq!%{7#I#P zFdSrHILyFsgn{8G1H&-}hBFKdXBimIF)*BGV7Sh}aFc=I6$8UN28J&T4F7=$2`K(# zVPs&CXV3xJ1hSKX)%SsVUrOe@3@!#uu9TeUec?LY`A65(?4QKYqk3pZPTz@MwWQO! w50f#JE&pStEl~#?ZtO{3TAK7h@!<NNfZXIa4u_t+H>7oyc4_~ONdo{fYn{{3F>bG8g zRj_t~Uo}Me8?CTru@orYM6o03UNh A>i_@% literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/level3.gif b/livejournal/htdocs/img/level3.gif new file mode 100755 index 0000000000000000000000000000000000000000..ab1d8d939bf886e955512d7d63bac2a013edd15a GIT binary patch literal 198 zcmZ?wbhEHb6lM@$SjfcSRlRlT-dq2{K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB z7RD3?W(FMwAOLA(U{aaWzw-23{>NNfZXIa4u_t+H>7oyc4_~ONdo{fYn{{3F>bG8g zRzOxMJ$FOi^rVC1Gl}9LrK%R$l%m^*o!$v(9B+j11NQ DCjUl= literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/level4.gif b/livejournal/htdocs/img/level4.gif new file mode 100755 index 0000000000000000000000000000000000000000..63403878b743d424b523f7e99e7fc927ac590c44 GIT binary patch literal 201 zcmZ?wbhEHb6lM@$SjfcSRlRlT-dq2{K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB z7RD3?W(FMwAOLA(U{aaWzw-23{>NNfZXIa4u_t+H>7oyc4_~ONdo{fYn{{3F>bG8g zR9Na&u#yBuI9?OiE~<(y{Zyn Gum%7~`$~-f literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/level5.gif b/livejournal/htdocs/img/level5.gif new file mode 100755 index 0000000000000000000000000000000000000000..ba11cd0f11a01af19601e476682162dd0881f33c GIT binary patch literal 203 zcmZ?wbhEHb6lM@$SjfcSRlRlT-dq2{K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB z7RD3?W(FMwAOLA(U{aaWzw-23{>NNfZXIa4u_t+H>7oyc4_~ONdo{fYn{{3F>bG8g zRI*z`A2uuiwRbW;8x2@p^S? I8!Lk~09olxJpcdz literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/memadd.gif b/livejournal/htdocs/img/memadd.gif new file mode 100755 index 0000000000000000000000000000000000000000..40db213873ec89eeb48f8920b49f9026b8ebe634 GIT binary patch literal 426 zcmZ?wbhEHb6k`x!xXQqA=FFM@|NpnNv@kF*xVgFQ-o4w!#ih2kcGs?5+qZ8|OG}es zV31;9Si`_DlYzm>$tjJ2p{Ay0>(;H}3=IFDJ^O#=j2{Do1OtO41B0ih=lkv3jTsn@ zD=OX!2zWDh?sj(e6RxiQ3=At*u51U|m6o;=XwJ-;JJ{Lp<>nsn^xUee+r_}Jm7DwF zym{}-%ioulE)*2J=tf#OdVu#gUj1o?@9 z?f8L)0uLQ2Rz`*dg8-}f0jfbKd!pugEZbJunzsFpp4mFPFR)?9W-oC}$|k?4+y7$Hvg;$1WW(!M!t?ifH46wF&hHwA? literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/message-error.gif b/livejournal/htdocs/img/message-error.gif new file mode 100755 index 0000000000000000000000000000000000000000..d8918d5f34754d95bdeea10ad121a7528a5c05de GIT binary patch literal 1669 zcmV;02738NNk%w1VITnX0i{3y|LEra;^6+~ue?*HlM{_ySo>+1gP?EmHC z{_gAl=;i+E=l<;J{?ya|@$dic?EmoY|LyDl@9qEW>i_HM|LW-e)ztp$>Hh5M|MBkr z>gfLO?f>fO|M2hr?(F{U>;LcU|Lp7j@$dic?f&rY{_5%d)YJd%>i*Ny{_gGn>*)UP z?EdTMEC2ui03ZPL0RRU6z>084EE)R+J&~`!mduuQ*D>R42>E64$Hs_9_EF*OzHGC|Ahjw-~f+KM(H;*uUjUzXeBbk<(f-skx zfiQuZH#a4u79$v(shpW5r>7&bB`z+X7O=V_xtXn(u&TVLrophewXhg2wam=C7_qjx zur4#OHq@{&B|OQ=Ep)G<^C2^u1el8`}EWX_yOkFGGWVg(JVI;fH`VdCi3t1?XB z*Y1&%eL_{{RHIpMVz-SfGIez6Zd80XAshf&x0oV1o)m=pY3S zW~kwX6#ig%VFw)m&|wD{c4#7r9Rh%&iUFdCqKPn;7$XHQo;V`~0(2-qjy&#YVvaZZ zsN;`5?r0>BL>dXBl0Y6Q!I4l#x#I>>3P2^5R${58ksEA@<&<51*(I1(W;v#rVWv6e zm1+{Ofdp?70B4s3xT&TDbsL8Ff*dMKlh zP7tZ11X!A>qnd7-sil{G3aY4}mMSW#rB*sY0HCtEYO1eV>ME?WvKqjxxY{aftE=AH zYp=Kh>uavW7HjOV5hR;y1h_KWYyi#@n{2euPFwA?*j9Thv)C%z?YG|!0PeWS4j^v1 z{^FV&fx70NyDqluuG{Xs^ww*yz4G3x@4o!@>+in+*NXrG^Ag;y!2>`ru(=2)Z1BJk zL(K5P5m!tw#TI9*@x~l??D5AM7w~ZbBqLBj0}YrgGRZ8jY%&5VuY7XLEH}`y$~2Q~ zbIvpK?DNk+2QBo_L>Fze(FqXkK+8$9oIukBEKPFKO+Wo~0as7`v;$dVJvG->U!8T> zWLu3j*=Lun_S$T>?e^Pn$4&MDPt$F80t_5LcijwFy>|k8Gtf8SdfT0M;dCFacixBh zjX2(fBQE*mlQX_I<(Ox#`R0-@z`5q0W4?grqa#jw=z5<%`s%E!9y;p>l-_#&>junj z`vSG&ZhP*d*KUCCzpoCw?yUcwd+@;f-h1!K8}Iz{#^av6^ur_XJoPC+ul@GiJD)=K z+JkTW_u~Jaefj36Z$9|tpHF`J-y1-F{O`|CfBo#Qf4}|w_us$y3P?c!{YO3!%x{1P zv>yltr~n0kV1W$`-~$ne!0$P*fDFW-10QHX12*t`23%kY7C1oxhLD2>9N`Eh_`nm6 z(1Rp|;R{p;=uD?N P*U8Ryy7Qe=3<3Z<$1;O9 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/message-warning.gif b/livejournal/htdocs/img/message-warning.gif new file mode 100755 index 0000000000000000000000000000000000000000..e823d8c16fd1e1b3867249a970e32278d17be68c GIT binary patch literal 2135 zcmc)HjXx9k1HkcVZYvKN(t{o_D_laAm{<|_h73F$fkf~2uR0)VgYQu12R6?UIvN}Kso_rlRz;Kl*>Rm z3gk0D#082uAfE-oULfcO;sGET0b6t+V1exqK)D1q=|IE*(lHan$ z1JNK*%mUdA5D$Z`w?H-llq+Df3kbS^;ynq#inIGAtpU1B4IBRU_~$j z4EZDtrbm8RMMk`&kdU>tm5q%pZ5^c6R%COfUenvwI$G09X#W6m0E)!$cu-6~V{l+{ z0ya9#=VL}EC(#)6(83xFtqnzQe$lS{0yRRzHr9S#Rnk`W_C*T_O+$PmwZYIrbJA-NRnl5KLSK){X)VdWY}Ri1KHfq$c>8S#FmS2x8w z|MbIkL4Lf`rP2d=K0dVUw7ycus69t%e&NX)r>J{R6bM(wYpy)M*6)@W5ukdDRq`r6 z$b4EuxpT6_^WZ*FUR$vGtkqd+T$>F=A1NQ@+rT4_6t}HZDtar5W54qE89s)?Dvu;U*Ti#=p~%)^?Ta4%3voIgwvI`9Uhy}Q z<(_Pusz!!sR~o7$??bvT$+jfTjNxCBX6a^_lyQpYZwx&uU@sDEU}j4MKaGH!gzuP2 z94hOiKXobls6Q__%Ox;q`MG~++ADZqpifWkk#574yqnQxA^Ddd1@+`ze%c$NaRlLr zhu<9!TP=zjw_AO2zkL2@wF`>2cg1+6YxnMWnA=B^nK_ld+uruuDh+E7{jjpEP@2Ol zB08|DJpZQJTItjEjjA%6GPl1ptX1o)HLA-w)nps$MmVAo*5!ntt#cT4#}u^Vb)9Ml z$y9bhkQ2PmV%m{9VDag5?yRx+`{v; z)dKmtx|L*u(P1eGvh0+J3hO$ocn2ft@^PFB%qs}@McoS(YXv(!y20pzDeZ4q_1HO( zzxHTjG@@9#-z(}_sBD~ymT5N0TFa!cFOh?4Kh)TFoYlUmc`(9(0kaj8V+QQzA`>|n z-Hxrnv(O^JkOzF$X28xsQ@}GZk7A7Z|GT4GGq9Nc+nDzYglNor1}D@t#6|8<3rnOo zPluImG|xn~92W2TtrXYtKDve4GW&p4)I4{aTPxmmqLuhS{RD|_tCo%#uwAsUz1_B$ zZ4*adDSR`(W0iDY*|u7g5=Z}7@q~h2Ev~qY{;LW))U9$T(!n0?5b;$0xgDx<;qT@V zFZq`y0|*|klCh`ZiX?kyAQ0mH*l^@1U}fVtG!wgt<b(P?DI!he2k`Z`U7X}>a;-q!VA<1QbJp38LL7%zt*f@1T z6H9bL#nMxZca}gdT6G(7d?3a-3-ILDZloG6%{v&W{lxUb0iBbn?x>r4U)nmO;v7<) z5fBK|g=vy|G96;|lRnFoX_b63^VdDbhbBz1C#&ms{(>((^wkAxU-FFbdj?W})rAQm zMr9{n)@p2o)dZW4=fP%2Jl zy-wEAS%n^DsKb0tz<6{n>BX{1%tJ1=(>JG~4|Obz?;4mjoRj_f=(mkH@`nk>vWrK^sP9xbUWDq#9674$To-@%l8()@3Dqjk zwy=>G`oc;V&uZU4IiuxhVUR literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/nerd_small.jpg b/livejournal/htdocs/img/nerd_small.jpg new file mode 100755 index 0000000000000000000000000000000000000000..eba4cd2357f4c099e53c29f40239131e5600763c GIT binary patch literal 6770 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 UcK-mnwhGNERH;&>N|h@A*?ZPT=Kufz literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/newsinfo.gif b/livejournal/htdocs/img/newsinfo.gif new file mode 100755 index 0000000000000000000000000000000000000000..4ff556a79ca433e35aaf178ef140478783578f34 GIT binary patch literal 924 zcmZ?wbhEHb6krfwXlG#H=H`}?lCrR{NJvOXOH0en&i>Evzq7M*=FFM%=FMBMV8MzN zE4FXne&E1?GiS~`c<|u=|Nji5U^E1VO9&|bWMO7tU}Mk$c?gsz7&s~!csXP|HY_;U z%)zN7ps=9fFcXI)UxmZOMGZ}?EH*PN0uM4Xval&J7%(s$XP1*!5;#$ye6&xV+hm8t zgQeb64AZSR0vev5ox)KfHQ}a0quUfN78cP52?^)fjCJ)=0|XoyR`3a*@o6wPz_`LV ST+Qc0f#adg8G>vq4AuY^nMXqa literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/bullet.gif b/livejournal/htdocs/img/opal/bullet.gif new file mode 100755 index 0000000000000000000000000000000000000000..f79712b6cb05ca42c7bedf9b843d5d3ff632432e GIT binary patch literal 852 zcmZ?wbh9u|C&}J*KS?Ab??@#$M)_$_kR?OhQM$S z0UZV)0ObV+4oe1M4jB&vM@AM_K@kCq2L}!?GjnhmOgPZc(8S3kz|pW#iJ^;?zkugK WfkIO^6RSc>gu$YNeXLAO4AuZIs{`Et literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/home.gif b/livejournal/htdocs/img/opal/home.gif new file mode 100755 index 0000000000000000000000000000000000000000..c8f5486e3c336c7842846b9494ea258961a8f6b1 GIT binary patch literal 2033 zcmeIx|3A}t00;2TXWwiy-De)M)qL5cnnUK4jLz9Co3&~jHjB=ehoQnMm6~c}N}{Z$ zqf}ccD&ih=&ZUT!^N`yL#g!X0)P5=|Y z#56DsOwR#xqjPhh=RO0Uf&cUW0{>-!4}Xs^tQZ)AK0{t#p77-p5Pkttf20W-EhYJ@ z)A|I0=SLQ~a@>TKf~HINj#K^QUOhYMi!^?5t}FSl1UFZv&+_k| zUTL?KFC;tb|Jd>ESXcev`EU6{FNx!5b0dWjSBtm! zZ0vMWew;B^y|JT7598jwX+=wqjtUl$MhZI7G>(a^%RkK5qR&PV0;sw_zzH)C+oc<&ZEK-n_z) z9fD9uA91k^6?Z*xc2XRR4DM_m-ZA2AJiXbo78(^h@WkA$COBcN06l-t6%Jb;6`QiC zo27?WIUtohL_yWyu_8$V|6GQ#B9(B@;+#1a!Gf`#Op|(jDjNwQ*_$mCD42=xQd~tb zd8f$nELFr>M9)EPv`bBD!pMrpo4N6H4u;Tb`6J6SjAh2+z3SAWGH=sX>1tAA2XQ&K zqUH?NO0P=9n@gkP-O@rh8rN)QL<;dbiwrAVATs3pks2Z51cbnL7(AlR%58YRQXf=M zT^>$xS~^B3^Tq>o0@xO@vvjHcVN4j# zZrJ3nMFnFNmwC#+w&}mZ-^MPDaWCtDn~sK=I3!%RID`)M}-|K920?{>XSFKyHGGh?|>!T7N0xK+Q87HwhVkwdph}N6_ zLEKYnB0 zGiqH4+c<13MaR(|Esjd&PWR9z7c&mE^)^QgzRz>7FqOT)@R_J~%J3oOjgg2wCZo?f z7wd}@J{=yRIlI1*YbN#U(nu%#{a**2IHa8%lKhNLj50rI`<;=?VhuW%OO)1;SEiT` z?6*_%M6t4wGef4rvpxLp`o!3SE$NlEQWfgY5^wa?BIvzWOi1up$DvG*;;BsJI&FW} zS~TtPj9bzzV%W>P=*iAcE|>D3W%OaUc&NkgKBpEUCe8LbwVkXMeYuHs_+jB}e@RRN z%8(0TrFR(@bHw@iw^9nK$LZ5|m+Kmt+RbZ9IiceD(zjMiF3~=QoUZ8d9L3;d>k2~; zNXrKXkKp_Tq;N5kZ+}+1EI`E}IqoWTdV;tWRFvFtUXytG!4&G0(?cEFe6BZe*yozg{){a7 x*p0wYdR)UhoAbKri@6m62@R*VbbHBJ@w&bwuDk9*ccpLEl8wPuIvs+7{sl0TyJ-Lb literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/home.jpg b/livejournal/htdocs/img/opal/home.jpg new file mode 100755 index 0000000000000000000000000000000000000000..1273369f29d5d029ff2f9582ab4b2074aba9bea3 GIT binary patch literal 1597 zcmbW!do$K6C@+mq=D zAP52s`2sQ#a0dt&91e#e`2$7vZ-3`rCsNuRX(2qeFXR79$wP--MR22c9WA-e-GC_n>&Fvt)nU?3O|c1cNEa`;rLCiDWNcz;W^QX|@37v{$=!qQ>BV4r2W;Q5GcYJP zVLf6(Ad=6 z()yF2qqFPoy`S&*^*{b~KsY!wEEyZ0`2FeRv#II1`Gr@Duir@DF0HyC0QRU8 zBX=pt#{x&Lx*&yk`G#TO2m`7j*3AzY9)mNqIf}w>&MCRpu0*E!za&H)=vCIF*h-A% zR%w69{v9mkf5|?<{&o!mGz^jt4~7A*VA+JYBeZS((}0%5tDL^Gr+z^iR848c%yL4n zW@N9>PS?#>(`uzua zE7rg-ysJ)z#lBNh-7r>I7hft>@xR$$Id4^t2^sd`iHr-kr`dxEEQ!9}InZ%TUD@Jl zgtgmD=7Ou9XnKF}RDp5Rx)Q#0Pqd$}QB@cdUfiXVm@Zk-92*!77RGklbDA(BulRW4 zR$4BPubt9SXl>DDRpYGWkZwEUB`CMUSH<1=rYAz>NJrOQ{ z_FzWK$~?4lvi5C=p+|}5flibGZ@GDraOf7hw?8;HsDJTf5_{tivLksPv!7V8n57qY zh?cW5YQLYz4XxwO#y!3$*0-_QDDiP;Nqs2xYK=Ik>7QU6gS7}1$kZS^s1%O6JPK)5~qjv-VQ%fyNg|;mP={U zU~i9m^hh5=-A_QOd3cSb47)U%WOOyi&^24i!)dm*rKJ2&Z}XQ zZJ4tuuoxxn#Kq6MqsiEpLS={pZ;=1JJ%4wHQs$N~XvysGC z)wxdc2>q;;=1nCB1<}9R71uskX1lY)=B}-erHy4y^ZokoQ(W9id4!LjVp^IB%&Kn$ z@QYDdk)z$OH}LdVwim@N>3a(!U+j3XwxspAz-ixRx2~A}DepUxBSE5Qs)hzpNUoKt z^?cnkx9>Gk`BhLE<1{6T;I&E7EEtB?Pz8yVDV@SJJGbbzv`fY_b1d^pcp53)wI_47 p?mC|}8P$!4s?-%v6_{2)xt?3`+dgEVRPGX0%2PJ|uw7+Ce*z~ylMVm? literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/pencil-line.gif b/livejournal/htdocs/img/opal/pencil-line.gif new file mode 100755 index 0000000000000000000000000000000000000000..55e380e38baaf3829eeaa44641eddf7b1c10496c GIT binary patch literal 1664 zcmZ?wbhEHbjARsN_|CvEXU?3ZOP8))yLRi=t$X+GJ$CHaxpU{PUAuPg-o59~pTB?q z{`>du|3|@S2n^E@Q2fcl$iVQQL5BedKzV|J;~&F+P8p943l27O2y4Zh*s$<$yMVIS z9FL8Qj&@5JXWcomaq;nf1?Mgq&rM5CPSyxs6?1ZvsyiFEh)TqRP0P-*T8L^m6fAho z$ii8omyob|Mc@SP3NZ_E> zky(I8bVULK<4#q{6E+*Ryu8k6clVW#!>rc~%$$G1dOH^wL@?X0^lRbXwc^U0)seqd zY{K4zJ?`iizdp;N^!!oB`tM=Ymc}p6F^fz&l3CvHkdam3AIH>Q1I_C%i%aDcdLkW? zKK2^xaWpij7CempSatUFm5Rn^_Fs=oZm{E(cu@7P^XQc(MwSf^693t5pT)FmWyst# z*2LwqL7tA+;utrCa$IC&o-kdge5vV<>pm}1mpCw_cTSm{uw<%QLteXJA{9@O(!Jx>Tv^4u|_Ln_uHHk~QwgkUa<#?M)4YJO81(lrmNNF**76^Qj@ zKXNrN!KSb@IWFqsmB(pQ1y!E(*a|*Vi?hg5T@X;>_C+=8h3W%^34%wDL?tq=>A38c z$tUpGqf4q`I>V04wiWI?4efymYb&RVGqQh?h@U(EkV;f6M_T3M@_%)!wq0Oi-Elo> z7HiI~2^sl@QVvNv>mm=V-xa1ZD|Xw?ay4%*4ui}^{gJm8q#tnVeC6r9c9}?VlI9eL z;PYt`4U9*b+-5J$XYx+;2)TBB;*7h#-O&NDtBxE9`#NpA!}|Pv+um#~-RALneVE*r zM?PQwome$5VehlB1&X{e4hKb_URf5Wz{V}gWMH;MKjpFzLs@M8?enZ9fd*qo|3 z{eF0xrN^riD)n6s!4h6B;@K^GZ%)}Yt#Vp^$lkiGk9Mi5&lOn9;Irpi1{>dr$rbx= znmb$;kvEyTNc=a?ygAFmjul>Wxt>*W&TDz^g$2ed*Iww}An3WIv7_`U9{}ho+flGoPBQliFL>SO?>XVO}F}u>HT%T-|hMS?)Uox?D~H`9I+M=U|_HY E04Pv}`Tzg` literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/spiral1.jpg b/livejournal/htdocs/img/opal/spiral1.jpg new file mode 100755 index 0000000000000000000000000000000000000000..d54c88fb76b76261e9988cc5a586d68373ff9824 GIT binary patch literal 1793 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}ORb!jYM!h`u$eoX$T<;(Yu8-L_oxi`cYD5-Fd>T+&>fcF2nG?puAFfq{S1i}fZy;y*4wu+L5~Dk5v* z&8#;DzjAN0%rLM}EI$1CvdrU2tW~iLB7v@>co2kv=+k=H`X?zrYX37Nv+n=b-?les z&-%yf|Mbk~-~T3I`+tUuA1<)#|91PM@`3k!+gEvsvw0@fvmK?qZPz3^NH^slkYveY z|Gg)r`Q$q3hhlrzIIds1=2y?Jh6y&0J|*v~u3f=D`?*}K#_8Ma$9KK>v1DD1qrga$D|GxLJ%Z3brs z7G@w|0+B2%EUau?Y;3HoY&;yC>|A_2{Cs>oyuAE^V#53aqJq48Hj89^!-nV1Ddf+k-C`hs0iC`8zhLn%;H zOvTvDF|n|03s8?3*f@k?U_C%_X+fYRsB(;gib{b@LjP|u@Gvt1UBoQNV9)UW0g7G* z28sBS@&>2ht`GlbFMs0GACKf&^|Bj(d~j8ntP}q^wQARj8@Kkyd&cite>HPv_2N5q z`KRt}{V2cFHj3Z=^6eM*KIQl9)Bm){_4%pE75?2P;*bA!TYPWIum23Tbt}JQ|7TFG zF}h!MTqlm_{xhtu+c#0bu7O$p$MHXI zHJP6#Cw{QizxL?Me}>qiz<<5ZcPh_a=elUI_E+`$U;TI0u2S59=ItTDWi*}M`fEbA zW9q}YB~lj_h&`QG;}2m+R>ZGl+oHkrd1eFN}JI5$LZhyGYGT)s!w~6bl>Vf!?pY3^dk|wAg?}^`aVZv{izpm=Y6_MWpYYJG{ll^jjb`pC*TL*K=aygc uhh`}(;?WBRvk!s|vvG;BuG&5Qcc%m6GjMhl8zQHa+6zX<>jkZbn< literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/opal/spiralbg.jpg b/livejournal/htdocs/img/opal/spiralbg.jpg new file mode 100755 index 0000000000000000000000000000000000000000..a6a32ffe5cd4d20da03d5a2c5c4be6c301a0710f GIT binary patch literal 2764 zcmex=LJ%Z3brs z7G@w|0+B2%EUau?Y;3HoY&;yC>|A_2{Cs>oyuAE^V#53aqJq48Hj89^!-nV1Ddf+k-C`hs0iC`8zhLn%;H zOvTvDF|n|03s8?3*f@k?U_C%_X+fYRsB(;gib{b@LjP|u@Gvt1UBoQNV9)UW0g7G* z28sBS@&>2ht`GlbFMs0GACKf&^|Bj(d~j8ntP}q^wQARj8@Kkyd&cite>HPv_2N5q z`KRt}{V2cFHj3Z=^6eM*KIQl9)Bm){_4%pE75?2P;*bA!TYPWIum23Tbt}JQ|7TFG zF}h!MTqlm_{xhtu+c#0bu7O$p$MHXI zHJP6#Cw{QizxL?Me}>qiz<<5ZcPh_a=elUI_E+`$U;TI0u2S59=ItTDWi*}M`fEbA zW9q}YB~lj_h&`QG;}2m+R>ZGl+oHkrd1eFN}JI5$LZhyGYGT)s!w~6bl>Vf!?pY3^dk|wAg?}^`aVZv{izpm=Y6_MWpYYJG{ll^jjb`pC*TL*K=aygc uhh`}(;?WBRvk!s|vvG;BuG&5Qcc%m6GjMhl8zQHa+6zX<>jkZbn< literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/openid-badge.gif b/livejournal/htdocs/img/openid-badge.gif new file mode 100755 index 0000000000000000000000000000000000000000..0a9ce30826cfb9f3002b9f4b5f6e8a992ed17cdb GIT binary patch literal 227 zcmZ?wbhEHb3}E1ASj52aCxhqg*|Xoje@{zG`ws+33=p9BlLgGs0g)iJ49qJmcHQ}B zaLQABr^V~DyZVG2VR>!d* zg@!p^tfvnhZGD)xHD<>8*L$9_T+TF=JTSX7XJ-ao44*t Wb5-28|G+^R(IZEX9p~d@um%9z#bi_f literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/openid-inputicon.gif b/livejournal/htdocs/img/openid-inputicon.gif new file mode 100755 index 0000000000000000000000000000000000000000..cde836c893f64bcfec04b9c817e3371ff122fe19 GIT binary patch literal 237 zcmVb{bmUKcqz}))c5uC(7v?)v4a2P)ZNa- z@$&T2)z|&~{r~^}A^8LV00000EC2ui01yBW000GQ;3tk`X`bk)Wk@<6#nZYULKH{p zEx|?+kif!I0vIL|#ZMubBmjWH2OtmxIFVa~6JQ7!1CK!f5W#StOTv&C3=E8h2vI1s n+#cd5;2fT3B_0kF0v!+!GARoV78n&7dMN`JIW(4+BOw4gP{MS* literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/openid-profile.gif b/livejournal/htdocs/img/openid-profile.gif new file mode 100755 index 0000000000000000000000000000000000000000..ea14f84f9e50ebd585abde4bc954d93f58adda15 GIT binary patch literal 211 zcmZ?wbhEHb6krfwXpv#~m(2V(jpJV?&;M+JKNXr6_HFsUvFZ5n;}?(YId$sP@zZC4 z;QXa4ch4QY1O!*F-@A0`>eZ`v@7{g*@X`M#SKhvT`{BcfpYLCM{PgAj*LVNFefatF z=YJ%i_>+Z^fkB=@hXDvcb~3OAJW%gT$(;AXLo(BnL06OKqq%7#gYSxBjSd;7!j36I zot)2%cHa=|Y&|h?MTZIVER9D7bu!((8k1dpyQcAnRZo%;;^$zvHpzgCB`o*+`*sEf FYXDTeaeDv& literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/pencil.gif b/livejournal/htdocs/img/pencil.gif new file mode 100755 index 0000000000000000000000000000000000000000..9fb6e836417037eb91d59ea2117787ab7ebe0f00 GIT binary patch literal 562 zcmZ?wbhEHb6krfwI2Ovlpc>6!oW^IEAZnYf?3g3&S|jdOE9Fry?bRsj)hOrPq!QS! z8rZHL++iG0p%Kz$9aL!=UauKDML&9yZrlXt#8%IgI;*Ui-dX)sF=ch}<)H8~7Dg_HdIlW^AOOV)1ABi%eLZ6fV^e!a6QiVp zKuc!_qm-<4s2x+=gk~Ah&`=3+u9=;Te0Fxs+CI+Qi`!f51ch|nyzF__b+L$8Dyq78 zy7KRAW;ZjJS9kPw;61{~X>6{f=H%-ke4fM9Tt(U1Mvvh!5RP_4mr^P literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/poll/leftbar.gif b/livejournal/htdocs/img/poll/leftbar.gif new file mode 100755 index 0000000000000000000000000000000000000000..2018e81467167f4e6403398e48e0ad8857a10825 GIT binary patch literal 115 zcmZ?wbhEHbWM|-G*v!okFRM|`D0F~bxr14}Oh9f8yZmeo%Lp#f$LyL_3Odu6rT+i_ z&wvCJf3h$#FmN;IfW$y%Ft8{Tob;URYb1DBRnqH)rmLoGSA&9(z=}7OEX=9*E7ti7 HGFSru!;Tv$ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/poll/mainbar.gif b/livejournal/htdocs/img/poll/mainbar.gif new file mode 100755 index 0000000000000000000000000000000000000000..bfe6d97aa7ec3e8a75c48671615f163dc6f13899 GIT binary patch literal 100 zcmZ?wbhEHbWM<%F*v!SSkV$Hey2WfJ$$3mtbJZE9lQW^?$VB@DMX!|1X@U&a0Bq6~SO5S3 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/poll/rightbar.gif b/livejournal/htdocs/img/poll/rightbar.gif new file mode 100755 index 0000000000000000000000000000000000000000..4826381e08e5f47b402912e802e03dff85cbcd68 GIT binary patch literal 117 zcmZ?wbhEHbWM|-G*v!okFRM|`D0F~bxr14}Oh9f8yZmeo%Lp#f$LyL_3Odu6rT+i_ z&wvCJf3h$#FmN;IfW$y%Ft8{UoZLCd_i{$l^k2-1qDz$YIFvNnr*JVU@E*JvRI%>8 JjT|F`H2@)#9Jv4h literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rightarrow.gif b/livejournal/htdocs/img/rightarrow.gif new file mode 100755 index 0000000000000000000000000000000000000000..4100a71c8a54d750d6fd2caa11918190670c8d12 GIT binary patch literal 204 zcmZ?wbhEHb6k*_FXkh?@%uI%|GKTVUhKdS?zCMQjeuk-28KzBRm^Y7M(ISQ=OBj|e zWmvwPVZ{oD!-pA;9AP+qoZ-wFhP!teorY#C7{^b`Wv5um$>dTt=?Z2pGsJAJE+Zveqyj~QUBYzfd_h?RGmRm0#u+hb zkxPkAdus}$#{1d+NdG)+_ z^7($BZ}RQ1x1VcpRU<|uH-XR$ttg5t%M8n8vsp=!QmIrd9*ZXu$z+lMV0wBwlgaGw z?-K+;QB+z?r_!k;p9Ca;5K=Tnl0cTBswiZBB}s}R2|(}yPXL@C0mpGPO~+y}2xTRI zq^N)bs;UB#l%T}MI9XQWiMSvLfFz(S;{=h*<)9?xL1H?ssH(|i+S}X9N(b%|iMXuD zP=X`{yk0MqA(i(pD>Os#f{_115O@fs#l=M&;F*jlLz$#00P@~(mSt=@|0F?M-nMHKVm;^yXNJ{pI^LDD2a63xxcX;FOm z=+VZ;2Fr02P2zx%73H5?&e~`N00e_Up669nks#z^oY`#l`FxTDIgZWqD25Vvers!M zVPS#i1u@UcWK>1n-Q8tb*6;V@1kNx_BoeV$EXe=!pCnMbQ>a0Z38el&?Vu9~x{o|x zbENaZO!%vUqQlO}gW1R9qx#a3aM*LG%rJ>vSq&HXUNXE~cmDEsZEK!a%IA7cg`Z97 z-f9{eIzd3pLE$r zj~_KPMs+juSnd0s5%m1oGBiJC4k~bN}*yR;Rnl z+zjRHM%&xpV9~%A17927aO%^akU#rdhjy;H&jh`<1H}(J);|uZ6VN;FcoJRy@?I5c zF|!_I))znX>Gp1Ke7wC1wca=tUAa?Iz5H&A2d!zcC`ASKJonP( g$d7}+ofK|atNVn&b^fP&fpK(X{SJEkFoszF1#3zN?*IS* literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_copy.gif b/livejournal/htdocs/img/rte/post_button_copy.gif new file mode 100755 index 0000000000000000000000000000000000000000..460a6d699d5b843c5347261476cd92017a292590 GIT binary patch literal 767 zcmcJM-Aj{U6u{qYl5KNiTV-2LSu<-`>ah8RR-)7@O0bB`Hs`WCp#ot^SLwD?G$X?Z z6mn!l5+z=Qu$$p3jBe^m_B`+RzW06?2obd2{So~x4(D(V=f~l=FPv-d@LLcwlJOx+ zOH0W8I6)FPfpZ*3Cuva>lc^NTvH(I1#~=#R=`@N$0DvF}0EH-q%CH>EFib9&127?p zq9E`90+J*k3TT?fFnJCY<%THb3waE~AO;0NWLb`v;W$(-c_Ew4k`$TEW=NV61rf!u zTs}w1xg=2(B}q~OfCMZB9LGtDN@vm#0(k{M0mBw>0>cQ5VG2AiNF|wU5ICO0a5Moy zK3~XYGQ1!Z@_B*hNt(=LGlD2W2qj4@$S@2=kvzvIQ}V@0jKC8hK@i0D_I9yYbh%u} z|L5@UG6jP8kP{_U=_g2e@u6=h7z#g{3Qi8r&OM%ga?=xRvFIx+^{s<#mdchk{bK9+ z=a#3zD)pLL+kZ;iX)sh(Y1JF=I^PVL944dAR9mCdIka(;&KQeFt2IBSGJfut_yP;n{r9aV=4IO=77HiuY-E#;2u36D*EB=WG zyNIvwy7N(IvS5BU>;+5i9m literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_cut.gif b/livejournal/htdocs/img/rte/post_button_cut.gif new file mode 100755 index 0000000000000000000000000000000000000000..7d89948a9f334a3c44a7bfb92192b3b168474deb GIT binary patch literal 832 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 U>Zqia8Y(^lA*3oo`UC_3J3iB^j{pDw literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_italic.gif b/livejournal/htdocs/img/rte/post_button_italic.gif new file mode 100755 index 0000000000000000000000000000000000000000..b08c791cb52f99ebf7c99da5f89faca627d06347 GIT binary patch literal 1264 zcmeHG`%fEn0RLWjwS{h7yCG~^9{XWr7KBj|EG8}MCS=nv-48yNg+-P)F<9deW-u0z zhttgA<^uy+85$RYNzKss_ytOhH9k@jws7ye_IlU5_U?PPE|#q$SpErr^7Hd2pI7pE zy5neb%b9Xe1~L;Mkw{Q96^%txsT72eX6Sf4uBvK`|bG*u-@VjCopOiH{UU^uq5wS^Hl%d!+j#kd%TqiT+) zY7nX%7t3TaQZlJPC`ma!j}sV9Zrd((02^SMHrs`dBxH#9UjTb-gPkrZLG*;EMo`uaGI>v_FLR+MZu zJ2yAi*x1;xj3Fd!NVL51G*oZ9G3Z*}X)_-4O!$zI zVBVDd^Xb;mnWFI>=H}341PSgi9&T|Z!1=`Arqb(2%Pa?iV^yWqAE6QUgV6)~sy*xF ze!IEy?AMnoPc$6^me>CHjC|4Wy882x!QJ8PsD85kUFG(-zq}PHdGch*$KLCnqEDMl zU?JS~<9AnPbcc#>_%GZ9hu&#>@cXIRMc<76x&1Xmu7cslgFiUxV`JaTx1FZu`lXjM zy+xgSPqH`hC*X|rH1mbZK67WMHR8~_!TsX83h$q&!SBq2RL1w00r4$o(%|ijC%QaC zdkT#2*LYXKhhN^)VA-3qUEhr716{aHXJ20hyB{6!uDoX$SPGh)rb-r+mn^M-;k8w; zuc!Tm+40uYBCzhS^Zu$kXAcaQRsr2_y5i&R!?p(H{Bl8lSL8_XQ>P+%rlv(7Qdqn0 za$R~T5_sO~ez?PBEHazhjc&(e2svx^x~_J76|fpxroFzxnrZ(~;p49c;)c_l7Z^v@ kyi3oHuALKR2Kb+@R1N+k3fFvhE=;)edoG%*5d=8@1=jlqc>n+a literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_list.gif b/livejournal/htdocs/img/rte/post_button_list.gif new file mode 100755 index 0000000000000000000000000000000000000000..c2693a47ae09eb24fd02bc30e04d6704a8ada05b GIT binary patch literal 798 zcmcJM?@JSL9LMjZH8quMy0Hlfu9QW#G}bRmGy9=dSW!`-E4PVcMHECtJ((`c$_xub zB1rm;RP+l%R$)!Vf}$sZci;QH+iknu-S>NC4+6o?Kcdfr&!f-#_2&I~H#BWqyDs3u zoS58>rBbO(CKHz=gitD-N-JpyAq9Y@X@Vdm5(!ZhS&pSBDw9#-QXJ4glHxQ?GYq3@ zDoq0lkcy%h2vLBdXuu1+s+wA!W@vqoRnz>@FI^41445d5J84zGOEJyJPAmi=NXPQ3=?dSfYLQB9v5|8 zH>DI!(JU=VlCHyaT45Mk({(wSWI0BblhBL`q3Nnas3>M)B`M1+%R(J$x~8fs$8%y_ zBq@^PxXH;$pU*ctJB$6FDg8SS$FO#+Vh%so31*!Qw+A8@doEp$bRWLfcfJ3{k+#SR zSH8oMUvs$9 zANba>0`Kk<=)kGi3oj9^==BV^7xpe#d6q02eh{w8a%VT%Hc63NStSqiMt9)ZmQY(a z_Ud`ZYD@0fFGGPX6HZUCW9^}a>91a_F$W_a6k%PDn+LaBULJ443oRo>p5gmr7JIq( zT;f>Si7tOZ*3VURb0yE_gTI?{E2a()Fe%=EyCYQ65ze#k})26McL7hOd0P zll@k$KK(g-vufY?-O2hh{sI5Gpwqd$Bi!X#6O@it)m`nvAGgp`e?Cq0;?CN>u`q6( qKef1f%8BsoemwfobL9K`(ck{I`#bJ6e>gu~*-dmdY$+$O_5T1PxS$vS literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_ljcut.gif b/livejournal/htdocs/img/rte/post_button_ljcut.gif new file mode 100755 index 0000000000000000000000000000000000000000..29f0a05b06d3f910451dc3a821025c7b08cb9bd0 GIT binary patch literal 834 zcmbu6>q}E{7{`y7YFL}wXt<_`Em~%y>m;)XH8i99i^M|9MOLCv^rCtZ;#_yL8x&N~ z)pA5cN%dw~nGs4<*o)|#-|u&B+c{_F{##{{MRxof`o4WWJfH8wvwBTU*|P8q!b^y4 z1kKQzrlnFTK@?2W#2D+ko=7HDRTTt*0w5))WJN{@Ns>fS6o3HH2tuIgS|XW12#S(O z0g9$+QIa5n6a4s@AEQ?Ky7@DLgNfJ4ZRaBK`P&%E)>9ndT zrUmJ`Y4N%N5z;h0k>IT%HcdsAEy%hS(U4_XQ4~o)LE0*r)O7#o?EMLoyt?o|h#)NbDY{!Qbq#Si71fmv4^g~Ka`zuX%1 zEsi^44R^#>C$qNIJnyOaMohXEJT%*TzC+k>J*)HYI=rN}C*%m)!pj0JlY6TQRy^H5 zJ33OC+1EGyQIXpDaC`h<|J8d_v*u3wys&B0&hAss0yjSOjq-Kx=R0j*{q?J|GhC&% zidaS@8~X-o4^FBtXsRMgyXTaJ;o--=;rO)Tk+zOgkp+{>_eBO~h0f&N4QpdKLQGjS z|KgF_ueVQ3brdvwFJi|AyBgQF5F~EJ__kOnb-rkSij|8$9P3qlm&y$?<z??2wv)x~m*s%f_4AOsaQr>Sb8karc9&J@`!l@Nn0%bg`% z*Jwm1lS#*MNRp&oe~_M-nCR%pnWpL5l4T_jxT>m}An=Z3o2DhpGC^3bo@LoCc!4L# z49{~E)ekY`MP8BRl35~%K}}NyQJ@jz1wqp^qhzow%k#W$Xe70W8N~5CLda#&RE^hrgQD<2RPA z^WfQ{XGiwr#^}n6p^MVi(~bXL9qJ3;sb2NW3xyX)SM~hV(HQ3E1}nFE9^DnKcooK* zfM+~a=9D;AkDJ*d_KqLGMNl7@M$(pkc23T`MiK22#TSyEHey)VQ4`tASf&d z0)nao6v0qbb#XNyQ8Y!<6s8Kta2%&7l4fWH03n~JX&NVRf#+E^jbcb9n?Vp*O#`4v zqKM;Ip&(*7N)QCasHU9dI2eT~h9W77<2WD#wF*WMNs?q06rdqpoeB zp~~3NpnKfb|DM)r?A^qtdy{Ed`;n16wP48a^EKZ9x6s$2D3{L%;#bC7>*5b|e z8_A=#=0z9@*=%twbtb9pcDaH%UeLxN$PTwdy}xD2E^Ws59c(Q()UH?}Y|;n$c~z@Ee`)AYPeHpb~bn~Z@i9A+nr-xOR@Gyci)Ezucq>?X2j*_v!k)%i{(>8 z&I^l(!GCR}bgq^<50zC0etha`Z&@lm04<*dLq$EqtzLdgJb;=G4Q+ S;P<+Z)xOxvy;`FN>i7rv5tBp! literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_paste.gif b/livejournal/htdocs/img/rte/post_button_paste.gif new file mode 100755 index 0000000000000000000000000000000000000000..cf167de8ed6dcc1e7d5cf1521556d0b7f3a99933 GIT binary patch literal 766 zcmcJM-Ahwp9LJBFICU@5+I&G$hp6+lv_*iYkf%Bw#{Hq#Y0ef#+pOO6v$REX#^4%K!n2rUXGqCX*CRvuq@hkYq_#RRx6+ zNl~(*Pz=SzI9ZmGNfi;0W@trK(nmN1s-n`FI?r)2F(C+|n3nRq03pNyh;f{nOs=e~ z-~cB{G876O9v(Uz4(z{S`;(o8VZ&HMW+C$vOm{dr?DqK|PtW+g&bj%8r_Y9N_y!A& z7K_pDtS_`=*BhVPFE1A^`5d}+UBN(mL8Ch_+fksasMu(H<+fh3nhe%vo58S|?Xnt7 zyPt!l=AT6k=ZZ=jLM~I2xv8|MD44~Tm$R*9n|bfbc$N)fSY4{B3#)QpKlt`LmGX3b zS0kaFT;GnpzjefAsXpVe1_oT6Qz!H%y|np`_p2som~|}fVciS)ZQj~E|BK0^n&JG` z(UHpTfX1`b(c<;b*4A8Ew={R^-(+3rtymijRR^+qCY)1!TCXMd?5XvQA6m`vV*TFq z?VeEWd|kiCHZa$b`yvKS_I=k}LNj@`W%xUY?NntC3NQ_;2e;;*+iQ-3?Rw2Zgzal>h($ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_redo.gif b/livejournal/htdocs/img/rte/post_button_redo.gif new file mode 100755 index 0000000000000000000000000000000000000000..fa3b7e1704fcdf461a230b5594030d2e2326f5bc GIT binary patch literal 817 zcmbtR>q}E%96rab)FzuXH@BhWm_?D9qLpEHT}{iPAdD#NGTmlWP+$dpP}j1H8AX{T z6d0sQgcq=AT_#5OA)>x@&Uw!{@7Z>CIrl?g7b-jUFZ6tTeh<%u-}bs~RqKw}5gU?d zMWV4N4QW9TD4ODVUKB-HmK8;b#p5_Zq*5sy$J1Q8zrUXV1gU`{qtU1!3IGr+%aSAj zB#8Y1kZB>z_l|IWgr7ZNlc|vk|ZgL%JIA;%P`8Y z306@REgX=9s;aUgGYm{7lNhcQ!6iwAkmk~9K#>$p3WCUS97$7(rjukEYRUwTV}K-i zfs;fLBQQl(A;Tz&3?ank>fwL_S^!CFD?lQV;L@BnHO+A_3ME-eYE&|r)<{W8BonHt z5CjpA$3(5DsBKX(9HVJ^dV0F1rlzv8a`qpP|AX^~9z~E=q-4%!?k7m*Ya_=@-+_|Q`7Hf5GwZ&u#>)7?{*-ZrnI^P~$0mrgo z6kRv7b1V8Y;PcHW*!c6~HHIaPIVa1uJi7R{qQ1Vb?8~QjrHBo!ogPx1?G-lHW&Mbu zqfTG+$NBx6;>^086%httXGW;E(LFr z>OH~Ra?{j?HcQpmi}t>ZBMb7Bvl(4+^YW61U)afDhvDFUy_#F>c3AUEM$yMujv9sVYV XKU`kC`^~HKs$cIsaKqD3gjD|pG|#(( literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_text_larger.gif b/livejournal/htdocs/img/rte/post_button_text_larger.gif new file mode 100755 index 0000000000000000000000000000000000000000..2e7b23982abafaa96ff2a39cdef4be6921ebfbf9 GIT binary patch literal 813 zcmbtR+fUPA6fZKP>ADRVOcX}PG5+`tAO_Gph zi6lveVJM1XSvD``aU!GZnx^TdVOV`@f=C7>?K?ae%>l*7nK{gfQgI5!G z?hfBe-0n+0NIiViev${r_b(RZl*WUu{Td3kNE9i9Gg z@Xb|Em#5U_sjqXny6m$aSLw`b+U;Dx+RtF_b|-e$UE1yJc4Jr?;Tjvcrpik00#Ye) zTsjupvEn}#`@6FGX9c+t2{qe(%-DDS-gU;8`*wfm+;$BOGzW%92NwIo?kF~gd5e{v zz`mjpn|=TEx&GzRwQ=$%M~^X=L9*}%g7iqY7sL!tI>4*&JsPPE>3;9B5QGMM^h zJ6!Ia;yNAM0_e?}Q1rl!Tb{~`p9ko#ds3@9 SoK3EN43@lD9>HxJkk)^3iN2)( literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_text_normal.gif b/livejournal/htdocs/img/rte/post_button_text_normal.gif new file mode 100755 index 0000000000000000000000000000000000000000..75a79dbc9682d4a45b29ae6a31625f8300356688 GIT binary patch literal 818 zcmbu6*-KP$6vyvOnNu^_m|8O~X_Jwym|3(+lUsXM4@SG8r5Pz4l;2V7I@a@6(sV`JVGRoXRZ~tJl={DIX;@ zQi()DjEeDiT-WtzEJg@1P17(8j_2Z1T+=j`V-;0NCaJbC zar4&k6QQ!K)ZEd}2_ zL&Mnk$%fHUy7I8e&+I&s=^Ja#+y3i|+p~yvZuaB_k7ZsRa~4kRtZ4g2(XNjCv#p<8 z&YcyAu6orqbjUf=b>F}Dc-w`kwLc%d)f`u{W)#(04}{PC;S##GZ+G47mhS1{P5sH? z;E(52Q+Z8Q$l;sfX(}u{cjnZ{(v{l_N4kQo2i`2WmHy~xx1;hvQsz#6WM!C8?n!t4 zyl$Dn9r-xxj=r{~-E!n4Kh19b({-_PXz8AVr+eL#JDhWR`ofO3ifMVv);FJZJfZ5n z3!D7o!aF;i^yKC5n*7VH%ac6(_s_?wJ^sa>_Kw~_nQQ*s_7~oH0~TRnQwKtDZ3 Z`16nbyFR=h{}ml}ZTdQA_~Axs-CuBfy`lgB literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_text_smaller.gif b/livejournal/htdocs/img/rte/post_button_text_smaller.gif new file mode 100755 index 0000000000000000000000000000000000000000..70d12d409e5a0a776e0af8cfc0059945ac0c08d0 GIT binary patch literal 813 zcmbV}+e;K-7{zPa@olYlHDTok+P?jZ@WiiHzsvr_!3X>#CBod+|ro}WQ5kwGU z5+Z`4C`~hI&Cqqy6gJ&RQB+BmwY7!LunfyG$n=sV!_aJk6$C-mR9!bXp3@E8G%*P_ znM!7~j3kO?76=J_4P;4-1%W3q(lQz^2m~TX3Tvv$FpR871cbc6XLJ*1G*#0LgJu{r zzNV>|rVPWNXq-$Y%x(hDV;YO1WavgJl_V(=AtXu?rbt!OBuP|N^MXboD2WmzAN%yqkStGazocbzZyaaG$B=YvRz<&DMGeAyOoI7&)vmf5#~ zncgCQQL(*f`)<44Z;KV#i|1oeSHTbK(F<1B(E@9$tGK$L+GVvy0oT;To%VRRv%n*9 zTr?EgvsBX<`n$BUyaaBP-Ry|O=W})iUL6X2+Ava><(&8(nx1-QaUJZscK-04#`36b zxC$h}i-)D>Cfod>U%-{sX$#IxPk%ddt#dZ)54PrcE6*!`>KD7tRMdP?=8Y>)Z_jLg z={oXt_nYRd=v3go*E>4!C|Gh)+>*oBOwFvZ#IKioWclQ1ED+`l7wS0`) zaBFGdTmH?bV8>97qcD6j+*!77va+SHes-jNtIrXC|M{eK)8YE`^#|TaesNAkpXEbe zVEkv!345u%;l#MN+)}x>Hn?mpjJ9}s>VmNm*S3lS#P{f+V^?-d_)>k){apS%*GGTc WKfaP-VxueX8thYx!!Ub2IQ9>`-MX*< literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_textcolor.gif b/livejournal/htdocs/img/rte/post_button_textcolor.gif new file mode 100755 index 0000000000000000000000000000000000000000..b76901a7790162347f535cdd52a5b4c9a1079b37 GIT binary patch literal 1234 zcmeH`?@tp47{{*#p(>SbiUJm-6^LUHyT}qrCn>cSnWeHt%+`zqL||lYVT2Vl)wETy zog^(n5f+mbvt|0G&Gozz_sOIF2I-9En6w6h%l*v7K=qGisHBohJ`~=X!+SPj3PLW z84QN(YS#DQf!%KRdc7MP8+yGSf*_9NBoc{CCcAj)5|`n|$H$FEqtoduEG!H`Am40# zeSLFtlcXpZg~!ImGCVrNwYRq`6p92vD3wZzA{mDH?e||)An8k99%-LX$xLkygIN4;c`O73Y?7SaA4wbeQ- zU=a#uYTv(eC$~#{Ex({*k_(udZdV_dDMo;yq<&|~UF~~sR9UYVovLwpxz6U%vb}Q6 zN`spoE9vR!47k7kt4Lk^Y^v_t-2fmp_DhATXnwKMH3To78tJ>f`||fv4`*pEJo0hP zY#WCw9NGiMycH=X>?=EFaw_f~S|WDd%c1uK461y=o4LU3k-Y6+zHR>?GzL5XCS=^N3j3e9)^gXjJ@a46r`eP3hF{bHZON6*!&t~6ad_L*?zFsJp2 zv&8V{01um7DENdvZ{5CY3EOt_@LF+qLG^%lS$g7V z=U29qkCWz#E_x`ZyyaTkPvWAp{XMR;!B-yX$A`%H?atAM6P4$u`iYqjZ#CFeqD8y2 JN+1A~{{oX}1VaD- literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_underline.gif b/livejournal/htdocs/img/rte/post_button_underline.gif new file mode 100755 index 0000000000000000000000000000000000000000..aa0938d8a66308ac6373cd8744f767300de32aea GIT binary patch literal 1247 zcmeH`+fQ2s0LBk(8KoU-JH|$FN~zso8zIg$8HiCz=gMZNMtzw20-MR^M(iH8($aD% zw+$amH;GQgq$P2e#)nc8Lo!V$C8muDV%US{)^lllPS5GNB50Sa!}3q~MNur3N`*o}k|YerAQ;YMGX{ep zN9A~)XIKVBQI6+e1co38L0~kE(lm{fg(B`jHv~fzO+yGwk|c^EI-M@hxq8Nr985wD8Y>X`~j*gD947<6xxxBnwu7{)%mSw#|LyL>CR4TQxu`%Qu!ih2; z8}|DXiA1qjly?h@vMjk=E)W7S3`-`HR;zVqX9xIS|H%SPPgNBFFaxyi(sn-qsCR%` zV?$3g6rWI5?)xYi4JU3*YHH4`gja4G>PGfL@qX3a7we8c4_>@uUkx0ufA~pPSZmb0 z_PXcY@VG+xP3z4$>ukJdPtCzsm-_nS;|7iW)P;56M&7AEG=DyN(xFhlaL6)H5pGIO znM{_RKhK3)buX#r2W}fKDFa8YonAfmv6~*R^aNP}Jl48@x);d( zMjoutceLLKIc}wn-rHK5zuY|bJMf0zZ8lcq_4nU=xF@BcSN-Vy2DkFb!X+*E zA#Mv`zx*}(cL})Z!YbVtgLf46s#Epm&aU-v$5rDykq2N$=&@QHe765*CVeJV6tTg` z4E}QWS8Bu6A8nRt-Pb2Q&z^WP6VA!++byQh*a=It+tBa%!(q6bHJSFEm|gf1IG}kY z035l{ZmYh2B|J7&_t{dd$`MrC_Uns3ke}P1a!|w&}|KN7T0i Z!UxIkuK#+Bo^v&r_1zxxY)==^`7b}H`3e94 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/rte/post_button_undo.gif b/livejournal/htdocs/img/rte/post_button_undo.gif new file mode 100755 index 0000000000000000000000000000000000000000..7d0e4f6a6bee3720442c5134736d07210caf3241 GIT binary patch literal 815 zcmbu6>q}E{7{`yBrDn^yEjP{DycCHM%M8peltW8{(lV3MoR>`LjRXn3sAlVm>s}H` zU}YCVeBrBL1Tz&RC{ltvzu)g%x3jaIooi4OMRwM|(C5_y&zJA_%k%81t*O}Bo{KrK zXfMWwSy2=znj$GOkw_?tqN=JSN#RH&7K_D&IDnAjH~_%#@GwM>&>;zw91wsYkq`ia zh(IjMG7LkKq%11{;))`Rl86w}R23%G5F$V`G{ev|P06w>$&#vS;Ye83R6Ubs8CjB| zJg=w1tZu?P_@Ed}P_xciY`u#csqLDc(@eQlBT#?(T48c$J0Hvo1vi*=J-ms89oO+IWcby`_j|Io2l8@)cz+BI>C`uO(Oco{u4 T=sd9Ickb?M^F?*mbZpyS*3q^W literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/searchingdots.gif b/livejournal/htdocs/img/searchingdots.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9908d894c8edaa75747dcdeabf83c9923be01ca GIT binary patch literal 148 zcmZ?wbhEHb6k_0En8?Hc1pmPR$WZ*x?dKX2?CcoeYNTht%m@ITz{H>fQV7z* rz{K0rzw-23{>5{)-0BWxM5th5-~=jU2C86ciAM;tV;AN@5w->Z4yhbx literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/bottom-left.jpg b/livejournal/htdocs/img/style/notepad/bottom-left.jpg new file mode 100755 index 0000000000000000000000000000000000000000..18e2ccc48ab85ac6aca40fcd39feedcfdb3ea25a GIT binary patch literal 924 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>>0k@TD|I~>xvtm>DE@q)rVLD!w)@}p zwRcF@YQJg4H~zO(ch9;16F2X-f5E$?{{G7U3_sq=f7rRF@;`$^uJXUX{{I<{XRm`f YHt_G<)c*`N!k-rZ*6L3HS^NJc09^ZUDgXcg literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/bottom-line.jpg b/livejournal/htdocs/img/style/notepad/bottom-line.jpg new file mode 100755 index 0000000000000000000000000000000000000000..b995880f00ff5d7530ab0e5cc17d6b8506150a24 GIT binary patch literal 805 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>>1wde^^}c`Cr2=_rJg9|7YmC_@9A$_VM{&*e=<>zw)2q zPuZ^bZ(i&Fd@z5i{LO3epAXt={o;SK%C>*{zw2x7JgFyDv;C$O-}v8F-96|2Pu#rU z{sr%n`ui*YGyHff|6%8z%Kr=wxyt|k`u}G*p1tnhxlR8W=5hWE{5v=GKZA|%r^Uau L`V&Cb{=W$Tb@nus literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/bottom-right.jpg b/livejournal/htdocs/img/style/notepad/bottom-right.jpg new file mode 100755 index 0000000000000000000000000000000000000000..294e7cb55e7c6e7b2f05532a0b15424620028998 GIT binary patch literal 696 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>>1wde^^}c`Cr2=_rJg9|7YmCZvSE3xks|TJrj+3%0*w^ wzj-bG^Fe#9Y24lw(S}D>)wb4}^6+S!`e^60FVX7amd+K+17n}hssDcy01aR3vj6}9 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/hr.gif b/livejournal/htdocs/img/style/notepad/hr.gif new file mode 100755 index 0000000000000000000000000000000000000000..55e380e38baaf3829eeaa44641eddf7b1c10496c GIT binary patch literal 1664 zcmZ?wbhEHbjARsN_|CvEXU?3ZOP8))yLRi=t$X+GJ$CHaxpU{PUAuPg-o59~pTB?q z{`>du|3|@S2n^E@Q2fcl$iVQQL5BedKzV|J;~&F+P8p943l27O2y4Zh*s$<$yMVIS z9FL8Qj&@5JXWcomaq;nf1?Mgq&rM5CPSyxs6?1ZvsyiFEh)TqRP0P-*T8L^m6fAho z$ii8omyob|Mc@SP3NZ_E> zky(I8bVULK<4#q{6E+*Ryu8k6clVW#!>rc~%$$G1dOH^wL@?X0^lRbXwc^U0)seqd zY{K4zJ?`iizdp;N^!!oB`tM=Ymc}p6F^fz&l3CvHkdam3AIH>Q1I_C%i%aDcdLkW? zKK2^xaWpij7CempSatUFm5Rn^_Fs=oZm{E(cu@7P^XQc(MwSf^693t5pT)FmWyst# z*2LwqL7tA+;utrCa$IC&o-kdge5vV<>pm}1mpCw_cTSm{uw<%QLteXJA{9@O(!Jx>Tv^4u|_Ln_uHHk~QwgkUa<#?M)4YJO81(lrmNNF**76^Qj@ zKXNrN!KSb@IWFqsmB(pQ1y!E(*a|*Vi?hg5T@X;>_C+=8h3W%^34%wDL?tq=>A38c z$tUpGqf4q`I>V04wiWI?4efymYb&RVGqQh?h@U(EkV;f6M_T3M@_%)!wq0Oi-Elo> z7HiI~2^sl@QVvNv>mm=V-xa1ZD|Xw?ay4%*4ui}^{gJm8q#tnVeC6r9c9}?VlI9eL z;PYt`4U9*b+-5J$XYx+;2)TBB;*7h#-O&NDtBxE9`#NpA!}|Pv+um#~-RALneVE*r zM?PQwome$5VehlB1&X{e4hKb_URf5Wz{V}gWMH;MKjpFzLs@M8?enZ9fd*qo|3 z{eF0xrN^riD)n6s!4h6B;@K^GZ%)}Yt#Vp^$lkiGk9Mi5&lOn9;Irpi1{>dr$rbx= znmb$;kvEyTNc=a?ygAFmjul>Wxt>*W&TDz^g$2ed*Iww}An3WIv7_`U9{}ho+flGoPBQliFL>SO?>XVO}F}u>HT%T-|hMS?)Uox?D~H`9I+M=U|_HY E04Pv}`Tzg` literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/middle.jpg b/livejournal/htdocs/img/style/notepad/middle.jpg new file mode 100755 index 0000000000000000000000000000000000000000..be7277faa13e72ffe89ad56dcaede6d81a31d51a GIT binary patch literal 1402 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}NYuK#QDpW*m_hTm4^{~0d(|Ed4auz4{y!F9|F2&h2P Q#xSaMGz5lH2>ibZ0BHSi^Z)<= literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/side-left.jpg b/livejournal/htdocs/img/style/notepad/side-left.jpg new file mode 100755 index 0000000000000000000000000000000000000000..0c4a8fb8eb307866d0b17b971abd1b68f12b5efa GIT binary patch literal 1533 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>>0k@I{I<{pRVuqANc?BX3kUos5f)rrvD6?SxhHA58TaE zIeL!qaV7)bUVjU_wwK^QjWjn zqGQVEtU67>pB}m12iiH0-Km>;x57R0!kV=#b@CtCyC$hQPB5`}#}HTGd8_cs=Xle= zI5WFddS||!o&V+he+Ho8Z!~WHXYl#Y@bUb=LwgR^cvdp<{4>|!JP`e#f!B!t$O4JA z-11Vfe`i%++5O?!{!Bjaxkm9?A;)8uG<^PX-G0+_XTOs2-}W!(|Fitha3gT@znT9T z9?$>Vn)Ji^h*+K4WvPGX*m_03i6$)Rvz>D7+WBAU{~7w~zlrjiygBXn5UyMr(*(Fs z5c82e;p<;W#U*@XJ-1mT=MIO?@hNwY$ux1koLA3yyWO|^Vd~xEQ)Q=js!w^+ujC={ zZ-(jXcdK57UNM@tpr`Bkp7i8Y`L=iStgTB5H}h<4a6h;8tHqvu`LmYWzFoKc^n+px zy{MRJd8hr)Jcz4rDZCwN^Q*oqNUhU%U!G{!IyM9AvUR5q{hHo>?Yx}y{*PC;R5K>Z z7uW#(myC+th%XZ?lzQp;wy}VUy@L)e#qx<36@`v~NXWND*7z-IF-8sNu zcx7qnZdmw-8JADqSa`#%{<8g_;{OaA7N`F;23l_an+uE3q<*V4@zVbpPHe3F4=iXI zE?n!IW?jb literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/side-right.jpg b/livejournal/htdocs/img/style/notepad/side-right.jpg new file mode 100755 index 0000000000000000000000000000000000000000..2dcb67b08e0581f767ac79e386305cd44aa735a2 GIT binary patch literal 688 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}NYuK#QDpW*m_hTm2{lOL-8X_bB%AN>A5!?O85{xke% oNRQX4QTfj>VR5bYYV{xYPkb((|8V{M7uBpHf$?EAGymTN0GK}KO8@`> literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/spacer.gif b/livejournal/htdocs/img/style/notepad/spacer.gif new file mode 100755 index 0000000000000000000000000000000000000000..e35332f4cabe43050b60616bd909caa1b8805d29 GIT binary patch literal 822 zcmZ?wbhEHb?>^7- zdET$jgM)Y*R;H)v(tscc*hDYDA7BHpNG6j>vgm`wVzD_PTn-(49xo__;tK>6pQ41~ z2#HV>9!gPRQDNbckusS~D3L4VQbmMRCiOo;(4`zUX9btLLMoy}(t8fP1{4o@#&5Dbz@yW|E1^XP<@mB1iKl0o~Y0qE>E>3d*OEJ0M_dbTig z8%MrZlyu-&EjK!~sXa8yHls-1UT`odSS$%!6~6lZnAo@nln+0mTAQ+N!$wV-c9Sms zi6@`Re)^ebb9TJA^QF9(ckSL+`1<~$;*vKGy;FX;;@u;L<5ee4o~l0m(HW!3{ON_d z`i90Yn!jvmy>z+lO2^mNJFQ*ceA|7qum9G-_k%;jBco%#jQ={}nEcIo$2I%=+`N0i z>ped&BdU{!sPh52u2aTNs7seN@NSxXL7df70Qzia7C%dYMa`FqLZ^` zLbn&#g2f8u$ZDq_?N73Q2X^p3ku8G-xP~EwBX;v0kGszLN>xi$Ea}N#n6l5i{2c?*9Ps=;!fYRcjOKED#p6w=ymR@B z3;yDOyqS-1p~j6sw@gFu>_VtSm@C{`elM5_9bF&1)$bW-Fcuf-ZYj^DmX_APsu<4B z=q@l#N5x-6U~nSq8`Z7RdDlGp?`mc%eDMhUMXO=DHpl$J@v7Y9Q=dssjF)IsjxsF* z@43;+B~i^P{p~ySU%Y4Xi7$1^JaLaDA+(S8B1kl$J@YEQJI5~4JIwAI2%KuQcdKls z9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>>0k@I{I<{pRVuqANc?BW@qiZ-^p|G!R>2qTJ_~8EdDc0 z>yD4@{3o(k^1~1R$Ie&l(p!B0GsxYO`OmOE;y=R|(e+FIF>6}c99iesrBgWX{hRD( z7P9wv&8v+o%Qn6_dG7x5rM1q#?N{w<`hCUxUGgjAyQ?2({n7coBCpEq{IB%?41M+A zL~{N!EUW+V{69lt*q<5o&nMO2SL#=j|M_J8_Y>=ala^sq*JALW;k?R!hJCL3lllLA R^8fuLh>1vr0qp;80sy}>OdbFL literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/notepad/top-right.jpg b/livejournal/htdocs/img/style/notepad/top-right.jpg new file mode 100755 index 0000000000000000000000000000000000000000..53a67ad825ae82d805b99e59f93d8a4d208e6698 GIT binary patch literal 801 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}NYPXBBCpW(RuZ?2E=d_UG*kJw@8!eRP0+WzJIf0q9l zZiJtf=d^#Kao_9h$+SmLrbo;9mHT=L<}dxv;C!RlRaNxMce|+Li{JcbSXTez`G1DQ zc%470ELpu1+(o~do&S~opP{e*o9L(Ghx~tXnP1u$t^Q;F>92O1Eq{og|6<$JrLlg6 zUBH+9o40=t{_>yUQT9{+mieDV@|TK)pMLV6LHK9g@~hA7nSTCj-w^03`j!2Z{QsK( D?sg*& literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/bottom.png b/livejournal/htdocs/img/style/webley/bottom.png new file mode 100755 index 0000000000000000000000000000000000000000..e3962add314d69b9097e95a8235b82bb8c2558e2 GIT binary patch literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr<)8<0$u_NoO^Ea{HEjtmSN`)Ym%P6qN7l0AZa z85pWm85kOx85n;42huMX7)lKo7+xhXFj!4zU=YurzH;Uj1_nkpPZ!6KiaAMt_*r;d z7#bLol-vY47+3@@axpS>WVA9cx@>W3U{H!ubYKu%E1=NO5ym0l;G)gKp|D7lX~-$t m*wWrEycFaOGeIQ37%<4)U`^lUbCd}fdJLYfelF{r5}E*FWLfb5 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc.png b/livejournal/htdocs/img/style/webley/jwc.png new file mode 100755 index 0000000000000000000000000000000000000000..c579d425038f2834f1a8f53c829735634f8b99de GIT binary patch literal 2381 zcmYM0dpy+J7QpvBFc?f`GIKBtlHqvFP@z-#O$o_kbS9?PG!v&()Q}w1(Qh6SNh+B+ zUX3Q*$?NKz)G3cV%dK-mF%?c3XA&dw=!mH9@80{z`D5?(S)aA`UTd$tKi{>p*kOSt zMwUhZ0Fy02{@V~)fDBKZJ~B7u*jpk3dw>yx~^JlI~J0EJ-w z%#UCcH)opJGTH$;c9q~9I=kib;z#D+S{BjiZ(H;D^M8Kxq}W$tXG(yShKEUPtc3^f z_o;^U>V9)!f~~!v-?k9athyf8G}>wNLL$mq6corM{}D_`i7;#U|*SXS3nB` zbY1Z~!2Ko0P@TNo6a3#1CqD6UQe-t2c-}_Oi5?g4k^~5lWTl|R+H|(PEz>M(rkPGD z1~gcImEfl@OFs)1=O%{qhmctMPo0(UqyJh~2tI%M%Xn~ppjLoMDLqKS`yqQIg>w~8 z4^9r=#oPL&U%S(%gmV$!(SllNqCCTx?D=l+F0pc*mzS5MwA6-DSy3Tgn3vU4y2R5c z2q^X&sW#Oe`D5+rJ4at%yhf(Mv8A<;b5nhNk!EROmOdO87l&_YX~FY&JpLS=(g4&e zdG*O|@=!d$(F&caQfEg5oKs6nOZf8g@*$U_Bs>*V*t0UQ%!z0iTpi0dRh8wIsooNe1V9C%>6k{^p^4~m8fB-to@;li?9 z6#C45!^0if%jug}s;GJuUjm4I-3AIDY=;jSK!(uW;ObGO>5Qx$Uiyz+yE;GjA zDAiw1F9RJv@cA^k$yRo!As#u}#oFYF{tVAAs9=ra)oVJ1*Zl0+C6>QGw)~d32cY~f zNsrG@2}tQ|cK0ZykAY;W*Ws3UP%j#TCG-(3VvnO|_?EHS!T$cjel@|wW?f3NaHtu@ zSZ|~BgyW&`NE{67&eFFUv_gsWR(rHe%&j+ zKp6I*c$o4kHgg|Ri7ihngRlFVxxRgLyK@bEQ-kPk^$Lm61^W{}7zP&7gz|JSZ zM4x}?P<9V&fP?C(r2vPH0LcWsKq1yUNzYr@F)uY93qPe3<^T9`GMg8)JN=b(Zd{jD zJp0^{SLX3@=hnm31L_mu(K&9eXot15jYl^Wc|Ui(shw8+WW;>UP zj}6TCG9UhE5&)bMuiS;)2f2^J{cLNlC-joY$FF>x_6~NwqiUWuhgW;~peWL^(E@kc zz0=CyN}>|PAMQi#y#BKyc6@2peBasPk;=&6oB2=Ym=7k*@2^}IQZyx$EfSr zHAdUkXN}&}tzq|0JSyLmi2uiURMyROxpj2Zsdj70nW$smOWw7%x!!oVR1(SG85(gsVRLHL2XJ{e1004OWUjZ+ zwC^BC-lk0$Yl*p~@3|v#TWGtl>LBi_fQnCpy^p?9tZ8Fx(F{=oANnOp-d)2(SXN~d1&MfqiRphQ@?(_UMOL+0(ar=`8)2? z+24NNQ2DP%zfZ=SGF+ZFzmWEz?I+BocjfK$yDj%@CkYpzsq_3ZldQp#X&w~vHeiM5 z{(*Ikm<4wzj_<&%j>3)qEV9qF**+MA@k?Lg zt8Uy7z>W^=;q0887zAn+1>6^NIB}#eY@vNt-z!F?nUZq-!N6m9-5@_ErXArlCq7!E zLy419bB=^i(}&)6UBM%W-*oV|wnKVI#SXQ$CR;e-;K=V_#6_&p%eD4xof>=Ql%k~i zFMj$Yegn{FDh!PWcH}dF?)dt&4`&M1=fo(i$KIwGpOh(D@Ktj%*}!{{h0tGBP%A9i zY>251tyHw!ieTJoK}g-4StIK2>XcmV>FE)!M#xns%@}tLjsa^Uu2)x|)9$HL@~1#| zt$u6+o|LI*$F{9mvxaW<0}|K8(D?O^{84a=SNY2?<_!x8B)r?y{B-o`Z@l(18d9dw zd8Ug2~R8 zc`}&+uQUgb1b8Ri{BB3S6sYF0Zk-0zXKnuwGJgZHKAM>~kB6{&hpd$E?X((=ASgWi zq2*B|_ie5AZ(W1;p=Ou?mX?-7*3j>flM&E*P%#W880i{cH=ZC{zwUI zdfeb6b)m2-*Ny%8PGiD1C5c-i*Kh|dLQLAY zR~iQSR-Wd^`^P!Y>%5+G-p_fK^E}VVrnyliFp3xe03@6o?LCFG zP&f=x2;tmvSzS>`M8hbDC;)K(O3H@EHQ|~N?C5z20FpET0Ac~a+K!M;13)|p0KU-y zz`O_mk}g97TGDr3=jZ1`>IfX!75=fngT&@tz^ank z0g-THMy|-E)~$^dga59wrHTLL@xH&QS9r}fW2s5v$d%}mGBi;+{lHgqD?g8eu@Inm z$hQ)T;+|Uw&ALW(54sLVar!b3V7f%!J&q3cZAme6I|l(l<&{SrT1i09Up8UB4I${^ z1X)Ai|2LvCl2?8(mA+E*RK$qdQPDbQ034a6#c16vxzNtPfX$xgY2(=d0YVrvQnxpY z85_&90)#*)3(>!~5_<73M}x7oz9c@j`i{$hCzeIXfHp#mGw!~e{)iuAO`xhxnuaHG z&u!Fg+@I#P7)}zpCO9)Y_z9{GTQ2#J1-`F4tbNagS5%J+-S;m07EBso>*Pw(X&o&) ziMaVbZ(^wC2)MJobs}+j z(|})U@djUa>{-_wR(pH)xh}#JMg|P}gWrNx-%3nl)ra?2bGanevu8G}(o$tOkx2B} zYS++@lv){x(SVnD$e8}g$g|qCC8|e71whYK&h`eKvLSZAICbL^r&z<^KKCK$9MI=c z42q;QXlJ9@oEtZIc%db)a>rXzUvkrT(q!&K5b&pW`l@;`874NgCwo}%`S88&?2s!r zZ_2Q8a`fTy7x0!8H6lrPXQ#H&M9*#!CtGp@VtEESUsPspkp6Aa@^ExofLE0iLS9< z2)!Ny504kA(#eGNb~QbEbl}lFHATymRcNA>g#_m@7;rugGa~y(F{J%U;k!7wwej=;#J#-C8Jy2FtQ|^3!N@ed#a8%8xBj)jExil91S)lB;2BWs7hnz8RJ^3}}jD za?B%PDW?VoNxX2L&}Tz6w!Qt{A%s19?4os18BW)<45z;UM#rtnC5=VYc{}&2K9@#PObor4>GXmgU`g*Wn_M4+@sXhrVWG3#TT7Lbwm& zfub`Ud%!vWt=}5xQnWurfYf^BLS8bu-4k{Zp~bPIN|F+jEeuCSO`+Upplb-Hy`ttM z5XxF)N%eLtth7#YL}%p%sK>~Ha55Tg|9ikQRW^Q$8K-JPnYj+Xq-vD_u(?`pH+pdR znXVYH3klQJMP_BEE+_{W|AW!)a*{3g7LeRRutUIEPJ?-pOdmWc5i}Su!pTxA@db4(VMZqL`q$g&3CY8H7FDotxWiI~skX**#|GfovAKC(SeQZAs z*T2WQ(KI`j!0*E|$Re*4@{`%O@hX=~6xS70tj>|`9m_@HT<{4Al7r<40s_UMJor*d z;LLlyF1JJSG->hiRso=o?5Xi)CdFO;D(S(4g^Bq%-qr5mPL+TPD2~f!Tk`kN)g2Ii z#bWg2PaLb>SD?mL1I{2nkS1FtUTdu$jH1T{5gem@#dLNd{) z!9AkaL(|e=g2-;kk;ATsTtuJLkcW=@CK7yY997^nvzJs6mpgTJ4q3135Ha=jHUBWx z_FLyq7#6CD1_-_l

    ;h?gu0BQrARUqxa!9UL0`D^Q7i1+B;vd`S2{gdv2r0!qG|0 z)tBQGDYWZ3CGm$^FFQKUYgiSyeTJ$ZSpBnNBnp?73#ZE<$mocr>ZO=%9fHyzgk;cq zu!EhWP0}N}A1i|{z@K|b3iCeto^K28MwMdgY<)w252Yvrk5AfDgc-pXOTZVp_<%W20RbZ{^f7H4l4y{KeSO3iMv1>0%g zBN`xPWjn`(*O_2pr;#7MBoB7>a>UYiT9rw;mSgmgkal4o<`o@0@eNjY^vNl*$?c%b zJ#{*Tg~zl~0P0ufK{SQpe-4%&u~ahg>a87^zTI-+$axF~LpKweH?plQK~56|`B*>+ z)`z8WPaE^bv$Nzhcqyz#_*Lzg>e;$7JuVcKmy)9#Egbe zBsoW0?P?Di>l7n4CarO+YYRj^lU2f-4f{mto1PADR21IPzpX7^PSX%5)gBlg&T7Er z`$L}qO(SnwzlxG%&PGe>MkhDyXHwS6&kv-{4eVV6Wu&tcaiS6w`c0EDVUZ)H3=N<3 z_VF=YPxuQteH9gzti{DMwX6?99M3lODLv;P*d%^WDncSY z9uZ2H1frim_tC@|O}YtP+3OzB)>a6hH1wRQWB1qLET#qHY5Gptgz#bUbbgBQ2d1#h z>~H(w+UIzkcgcVQD+%J{6!*I5-~kk&Q`q}9IO~myOt*&GO+yDlHt-6?f)w8$q2x&; z1NE5`LH6(8ix^6zJ{NCuy@9W`#DvoA4T@lTS7N01TXp@g*DvlpYhF@PVq|JwvHv9n z3BZgU<<}|w=F1HQjVa{3zB7aEnPrXn(qcLrs*)xF-8O?=_JveAJ9nsSRbMi;Ia?fK zkZ{0m*2BjqbZ%iGSRfD(@FxGlNDm7Tt5P`gLwZU@mUZnccgbUAGK%ka_m1lH?lmea zD+4n!GVCwxA_KWvdQ!k$G^#Z3=_S5?p8hX^GrNFJvz?rr48loE2Xh-5)RT*3$q)=s YvZ@J;4#Ou3zkYzzK{xw4TYAR-0f9j_2mk;8 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc1.png b/livejournal/htdocs/img/style/webley/jwc1.png new file mode 100755 index 0000000000000000000000000000000000000000..f65f8cd0b233d35b7d64711c22371836b95fa358 GIT binary patch literal 3640 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 YvZ@J;4#Ou3zkYzzK{xw4TYAR-0f9j_2mk;8 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc10.png b/livejournal/htdocs/img/style/webley/jwc10.png new file mode 100755 index 0000000000000000000000000000000000000000..251de4c7e5a98c0df2584b8fa092bfb130d723d3 GIT binary patch literal 5553 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 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc100.png b/livejournal/htdocs/img/style/webley/jwc100.png new file mode 100755 index 0000000000000000000000000000000000000000..9e3298df09cec8d21b2a2685933e88f48583c685 GIT binary patch literal 5966 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 MZe?%z)SMLmf67b(od5s; literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc12.png b/livejournal/htdocs/img/style/webley/jwc12.png new file mode 100755 index 0000000000000000000000000000000000000000..89d60933c653c54e24bd81dbc0dd7424649f14fd GIT binary patch literal 5824 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%0AD zL;KYl|B^CZ9+`gFl6V@Ix*+i(g0IUnc`Cc81%sBkDgB0-Gnod%+`xvJxwX*>&!|&{ zyrd?tQXINL6CcLzyf}pUoO_FlI$U9Gt6`NC2P3F85cCHlNX49qMsO}eOR zV1J_Bl(UKFK2F|=;UYTHv`kju*NE*gUt4)@v8d9ecPJF_xxzw!#$QJc8i5Vkhdz9^J7HJL77g_1v8F~UHejD z>WW@}%+&IwvYN4Q&OzNfJSWaHl~1tpnfxe=eB`|=`~B3tj0eUH7yJTL=*7h=$MknH z>wweo#xHZ}X4yByoq8;iRjCSAjCrMor^ySPgAE6UKwzpZ?4dO|kU3Tu4gB;e|E~w#oBx&q$VG4M z=fvP!f)3MJ)EWV+UR?~yXK?2Hn6|Gx%lP}ha0x`> z3wsok9#gs5uwxi9K?gure6YYHE&3k3965XR2Gac3=zdaClH}R5rG!K_b<~MFxWJKC z@=X3Wi{l?_ed z1OZqPH^Q_5MD)nkGw4BBQUsH&!z5TB`&sZ`4?aE#yzCD)9^h>8|(l#P3M`)e4kFIEJ9GqWS>7~+) zqsrxt09*qk%?XxH5XtUhZn6=;b&)2Qq-@Wbag94DtRO$1pZMQ@a>R-X^e7JWzgw3y zkWmP$$x5{x$and-jJTDxY$!56yREGa$zU*$jg5^+e}DfzPDMNb2sn?;R7CmxSU%Yr O0WO@kGix%zCj1YCM={R; literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc15.png b/livejournal/htdocs/img/style/webley/jwc15.png new file mode 100755 index 0000000000000000000000000000000000000000..665bd83e39cdd82f44079a94db9a452d956138d3 GIT binary patch literal 7117 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 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc18.png b/livejournal/htdocs/img/style/webley/jwc18.png new file mode 100755 index 0000000000000000000000000000000000000000..bf7cdc3dd07e22efe1762d5e8212119c175d1258 GIT binary patch literal 7127 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 lT^%AIAfSg|lL&%!2 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 GnEHR1O^Rp$ literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc2.png b/livejournal/htdocs/img/style/webley/jwc2.png new file mode 100755 index 0000000000000000000000000000000000000000..8a9ba0c21f3d8b944d924e3a914de9a5dcd7820c GIT binary patch literal 3923 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 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc20.png b/livejournal/htdocs/img/style/webley/jwc20.png new file mode 100755 index 0000000000000000000000000000000000000000..dbac8e6fdbf054c10a140b0e7cb60de8fb66a033 GIT binary patch literal 6798 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 BXPW>3 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc22.png b/livejournal/htdocs/img/style/webley/jwc22.png new file mode 100755 index 0000000000000000000000000000000000000000..51a25f76bed2b9dbad1db10a1e80ed47969813cc GIT binary patch literal 6123 zcmYLNdpy(M{~w##c(a*H8_C@7wT)bI8|F?Smnmsm3rUi0NNqEgTW%$n$lOYZb@Qd7 z%@nyS$){A5gl=+6!hZXFzkmGxIOp{^kJove*Lhve>-9R%bl=@>ax$tiAP`8-!=2_AD(`F@Z!l`Z$6>ce0cI`dt>Uv4`CKeL$c@T@Z-L27&&F#B>G(I*kK? z<|rW0u0jxK%kjcn#Uo;R#)IS-5MN4LM?iooijps=ogo^?&CO+ML6Jmn@TV(&xKjQ_ zga)n?BpGQ=y(F0-*!cS!|NpCWMg9Nh@xQ)q!VHvJvo+i>ZHCzE40W#Im3-46B$u|8jJw8*9t55C~$lMo4evG#Q z8V(ma>$CmfZ>SrCu+GSQk;n{3AaFC-|3pR&FK@b4VJa4IZ8+icak~wKCS{;WIK!VJ?!?NEN{{BU5D2Lb+yN1v9wvL z?*6srQ$2ZA?uVvjEsLdInjG^kR!M5b*4-@FtbO#Zd^H>WgU$c?J-OZC<0*Uh57(Qz z5M=`qO2n)svIV$qO>cK;+OW&v04i-_%VfmR>6eFc{V&rfhY!1C*j7(T$_2#J@i-ip zLEV?;T(c8V{G%Vmjg1*Z*9e>?z0u9{r9EkN^F{6vt}Q)q5xq`!4c2k7(Hb z=+U*w^*@USAEV!V16fJt8;(5;ZMZKIo&p$Fa*)7^@`n#6>8Uj98hlW(1m&3{qG&Zl#}Zmrbtg~dph~TK_R7#F2ov`z;dFaCmhBiij1(8 zu$?nTlm%QXgQ%*ci?g?|tGz)hxl|`zd6kSmWv!%ITATZAJ*WRz%R6@%<+ri@auKs2 zwLtLf4a?CnER`y#yd{=*UWc400YUnBnfN-lH8mjyA|&;U@YZ-}rhzPU`}XZ=;GrHv zh^)Z%h#4OHCCTLQ7{lA5ISRQwJD~q#l(c4{eYdWrHs?ZhelAPGMZRj6D92T}B(Raq zGN_qi)LNMoV;?EEb*>?r-eV@tVAoJXSx#Kl&XNx1#HX%3K<3rm5%CLCc;Q*wbXl?1 zK{VF0T4I|6U959IWgE4J|6Cv+ZMwkN1iQXi~tL7 z^@dPpugL9H7t`y9$bo#nLdTVKPUgY+XH2awW z)SRifT1jXCF%2P=^w<{oj^vtL% zkcQya>$%bLs-ggGg6*&olUL(Eg<^hJmwRDLf6yE8(qs}gp zQ>u=F>j-Qkho{kY334PItLsjNb8M%f!Qf@Qzv0CWSI-u}9gb*36zgeIHDx_KJP9o} z3Ha!D4_K3Lf9A|Xq^cw&)AZm+UpF2wSWH^)um$c$eFVH26k1Vhnu4*cpPZBXH?aIX zN=ElT+J(D#+>IO^5u)U)2v50xlN%TNk_Tw=jeX*G%6Wa`J%rs_`YS^GxPaTx@aw>1 zTMHDd71!PTGtCE5yG=UvOmt45x70+D;s`4EB!0k$qRFXQZ6N0$!^!YA(Om2`9jdy0 z5_%wf@A@G3c$0t+l__%Ifn1G$V9-3CucAtv$J4YM@~z*KaZ*9AuqcG5a(X}=cFf(P z>bYi*OCJPwR@z^3J%?)1u_>B2LcQ7$D-R1hzv(6qo-$Gi*H28VJnVWu zP{`wr6&GVdkA%0f2_+YyF*?-{{&yoZ-<#a+0a%Oh z6}l!Ke0f@PyDAhr6;x=v-~JphRv9DEQD; zuc~ziFgWV1tg~FA$I2F6sy@;yEpZPd4BK*j9M!+kDJ|!hw+pA9 zNdaH753=4Kq2KBq+WDx2RhT1P!b1is`GV z@1G%YzyaJtG^|vj(OMEesR}RO+=H<#9Uqz+LLu?GD!Z_n)H`@He5AoGLTUR+6`F%N zRh)TV73#4)P3YJv9m$yeRAH8H-~1Ou>7`@_dxk;jW8TP-@G%u0Pr(doJf?KZ)kjQB zex{Mn#;Xc{ojZ!YVS1Fdy6{WZIl)ubw_gM2I`&sOW}1<^`twQb&e}O-%wcAR^Xiky zaPAA(26A1^Tv;$L`l*5I2UTMP-#$=O8^2fvnDz}kabI!#Jh!U^(-`_FV_F^}*EMs7 zBAiL&QGk#I!yEY)ktlAj$Hv!553<_Vz6Rdw0bB z4euYn4MdeJ0A+h+G#B{YIE$bNgNCd_2E9M1s|zdI)gzLvzh{qf*pK$$lQ!2c35Nek zc68ng58EiUJ}uQ996t8sua)p#L=$=)JdUPU>!Np;J?xBCO{-yj_bpipU$XE=wXwWU<*mrZA4>lfgzzdumX z-tNl)dsSbvWF`JVUk828F1Hq9wGE#lC)HqA+Y`S+eShk6y7p+8g|?k3c69T(Jo#%e z0x-60k}gaPTiFggB;uiCzM8h{=t*!@8cxqJ@s6Y)*Cw?n9&Jx>x=LiB{x#6~DLYeB zIr|Gwwf|leSiUJ`UCUI<^c??g5-;ie^%t%(w-&AtaxCpA-Z{R(#+g*AKfZOUPRZg^ z^I@SQhckBs@P9!A9zPxjERT;z%*)2oB4Y-m>R-Q?yt*xhOT0ASK zetOnMS+}Q8;YnWQ0}1w3c(Ury;vF-G1!bSIeIScP|fIWPLp@^ihIz!*4k5 zg!(^^Rg2PeSg*!pIrCYeynP{**Bf)U-%=8nvyK2swn;!maWT=ZT(Cx*%PF(#MgI8I zg{!!cr)gzeFga%3ozh;A2NzbCghRiy;J6o#@Wu+>TB21>d(-Cco_3Wz?pmFaqEA&o zM-inzJP}cf?#Ias-KNWtms#+CA7dCz6OloXcxfW7C_9Rh{RWDzQM%j5SVGC118-}a z++3ekgYFE(xG$&WDJg{iK4U^j%UGcsn5KiTJz$71oQ}#EPEqV0sN88O-akpUp@3|- zMY0#(^1~@g-7^nB940i_N?dY4FmZwwA;?8zI_IbUctNF~SV2SJ zCpe~=;Y`JQK16e2$)){h8GjVIBvB7XR-H3j8Vz6_SpL%+%o%F1!VH_EQHoKyC1Al6;Tq;1=%RByqz*7rv z40|>YBbTu1yr*W>U2Sz$ZaK?!Gt1y_*61V(6I3~?W3J81?0{s2-e6cw4XYNQYepHT zcGkA3O?4)h^7wJw6?Cm#^6fcD(9Vd#_n=?~#$$7$4y9zi+X4!xMlAq;e_y8z1>{TA zUxF`!df8f}eNI;dBktE&g>1R;=3JF6;qg$D1a!rB8>Bn%OG0nvAaGZ!19_oV!*|ot zs*$eK$%iAWFMO%c2Hw>50FxoDu^*VI7X$2zXn!!9N&TIp+4ruDRbB=zb-Z721>3W^ z&dGM!kT$K9d?eiWnpq)T)KZ$Sg>G2Bgw`5QLZ1p8VXa-LGM|2~YTy!hNtro%gU5Yv z2PB!+43|w~Fg6DG84rv|+gV601LaQ)=#q|vZn5u@aHJzXDvAL7r_q6q8xD5yO5^*_ zP9#9(0u$ol!Y=qVTJjPhfu*Yyc?NXV7cFwqLc9>JAqv57nyA}xdyF z$tHIVJowMF2cS$B=U5@T~AMYFMnGda_`7YN$rTAO){=i{yoM!gNj&dZIhQ(ZmD zT&Zgy3DV1yENY`=JWQ>K@EtO>V0=(G{ztiClADTBm?J& z+R7z3ev)s8w2KLDk@<&*l2!dRZvq+>snv9Xb+dgV+&G(0ds#KF9iYY(kJH~?D0A8m z8>81`7ci%$=$h&1@GUStN+mK93}LN=wVhKNceYKO+$uDo~1cQoV}-4c80Dl@}HkN{D;#_MxB8FCzed zC)@Y{N)zCxsB#xblv+bLD{JVh3Hz>lbMn`ufOfx2u?2c-Mu6hnUT$l7I+b=n#`$&D z1EB0>Fw4t0!uUK#s!S?(PT{KWrei(f3hL{Q&htZcNJ1E--xBc7CGBse40jAS+D?CHUMBO0ockGAZyV_?5Oiry!mqvBf0$` z-OBR3#Lz}LCTe>3q1Dx8V|HUDL3rhx7W9I=ynA2y119<1eN0jDotxCs?s@gjmz2)?8YheV% zX3swFG)K=+m{x|lepgyekISqQc9Ckm>7bZllCjZ^`REYWq}+BWd1QBr{6*|&B7rtT zWtPaPwYoLDAj<7%nEb6_J(UZ}4*_EBs#zcSDeV)T5}d+NWIwl48H0H)h6Msl@9@4W ztRqYYKD2LiV7GT>1|kMLe>jAn(q3YM5@=BB52GbRKk#vi@*N`<^>za69BZxX-bPeuv?Z5B=*IV0$ofT~O z!Ta7Z{$@-r<{St5wnpb7C9Vdw4;?WS*QBV9jx#E{Fk41%f9&+!UZ@}V$f}+UovBI% zfbOq#X@bVt%hm8#P^d*gwM|u5h({X3h=ageQBqyR* zZe*Z(Uvzvyx{B+J5H>@F?sv!uy^H78YgSxZUKW?xmwPmDk5%Xw3xjBUd06eFyreh< zJxEFYYT}7rmHTE<{_yv8K~O6EaT!dR`?*9k^Bn4=ok`KN^S0}@p@{!AiTO_1BMh>( z+Wyl$s~Q(=JtbXzP8mc^)|336D!?%hATECFngFK(NOv6Xg_175LPx8p7(j#eAAx4{ z3Y)f>txNScVC6Dg-Q0w){(U7VmBxDp)QMS}ZO|K{a`bK-o>0{L%ZzvDj;8fC)7(vw zo1$BP1k8`z?soN1N~ZP>uV)QV1)GDEb3f5}eJQseL=Xu%3P#zn`r0KM?$euYr==@H zU4#B^(G_gCHO5TpjvNHe@*k(Xzv{H(-H?~|m1foE6c@B4Dtk@e)BCxMF`;0lXXgLfC_D5a*CAK)pu#;m1fo@ zU7Vli7V;D&qv|TUR)O99Yi!?H@|!S&8qmsto|!WQZeggqTqNoA#SoXO`@eFRxrM$4 zfu9L&jFo1z19QTiLU;N=fIPJ$LD@CW*t^(%KJ^ zHypJKW*ru+6zkg1aout!mQEP!oK%P!LTv^67i6H~V2Try8MiZ1ZVAi^7Jq(l;J6)p zf-6n|edj)w4U;yG zw~`#y?lh^vn%{thr%UObSlW!$)gtR?p%Bgf7bVU)(J7=?iyHm5R?i_hrYT$fZDf0W zVPNoGD_W>*!$$|FZFY}yUsY@`qw=?g6Bo<~AZ3*ujHC!F(X6`g%LfO{^~?pX$)(B3 zNvivvJrNV6`UIjFx^nj z2t3F*9}&O$M|;e8kksnuX@~>`GPs$=LtaK`5Dfc_$HUd_p7jNHFP_)it?8NVvc(xz zp}*^jAwWM(u9H1=FZa(pDa9hWzZ*7dC{W!sUoGo(B`XaAu_nrEaSRHPHer;Db&exW zcyCK9I{^x(?IbsboY{SRHO!&9%ry(y23w@8IClCpjC^7QmHke!_ktcn3wxf0>A zJb`e}*i8mhjc8vFO4y@bgh=+zLdR9};OPQSL^K>!XoW9=mmwawg@hCf1_yIkVDnZn zh7K9xdXw4e6P~_fk)9|8*o3F;>eSF@kBZ@biQBjH^Ydx*OG}V)p1a9^A!-*%>`sY_ z#bHHB{K6^6xr*8d^9S3 z(mD%~B?)CMqM|;DsAQYpe1E^^`F;Pm_dNGG=ehUX^PKZKOEzi0o1Dyc82|v}Jlu)C zVtPfq@KP}G{xnB>yO=;D9K9U@pyl#~b)Q1<8582}>kRB@Un9cz}JPrW9 zPyk?e2>@(6UD9xM2mn;ydk`J{63b~D3Q%}0MTG=BO%uK3a5!{rm?B{xWTwamSI)~+ zK;zm0aO6&EF8CsUbN#o)e^1%U2LI*pzP`PUdRcDE#L6oYYNb!8kf3Vj!M%&WzaN92 zp#$5!$+h%oZqjl%yU^eOtr#LzHNdix=>m`6KN&)Pdck&o5*?sb*9N)raX^2iLj?Iw zsPvlzRXp&2f>P<{e=ji9=iTzOBn%9rPa4MoiUg)Um9HVc+%C*i$o|1IM3w^>I&3F3 zWozRqb^X`3DcF?wE!blbdks}E>?FO-kC88QOylbD8 z;V(=BV+oc2v+9xDvvJe_D|O>SUNu_-P^2F|(dmd}SNFe=D>a0}G5)lvm$t6W45<4g zhhQvg2_JejbY=qIGKIaoxl#BH>%4WJym{V;MMutTbG1xg*817}Jp9pfS}Qck$?Eo0 zxtH96hyvfsDRe{VM_%4&QHRx8QeHD!@&i;*VQu*~cSgeC<#!7xdiE#SzQ0N4^Ub-T zS4v?a2cPxb&M*kRFk*UYq2zU)WaF-j3&Yh;GsnoAc!%>U;M17GX;K>R(78rbc3SJq#wc^E`ElKQP+V zYNAH0ApL=~EtNl1t#1lTtYK!?Hab60x;2sJcXlduy`LTkt|<%-REV~xA8wo%SNihW?`Z5hX5bZiYxB|LQMB# zIt2<67arTemwe{og@2u+>YBRN?a(Ix1E$o!$t~b8cgDf;Vyw1RDI@RFCB}3=`kn?W zII23kRuUe#knsX*AVU^vymagCSoEED5NNGnCCCl!fPZE=m;28+C3?uW7!)NRo76*p zrx-yfbSrfJ!lzr;?3>>_@-Vp8mzWVw16T^vXwc+UvZH!&n4W#{y7b+9>7XV^P1l8{+J$=K0T0EL zZ{23>n>SP0%ANgu|3EU*viItwkk{GSLyugdnDi(zQb*YKWFk6 zdh*#wqZzAgOGl3!+Gb+iY+;wYR?6=g&>a3YCyg-6-*8(}mM1s~Xd&UWS0vvso0QL{ z?XHo6|L9}x4J#&h5u8>10yp)*B1itzuaVP+xj77)NJPNdv^dR+k)G<1w8+A0+Z8g< zBUbjwk($EVN1docJIcBj{|p+ihl*(Rn$KFsq!W5hXO(gKA_!*&Ps7h`c51`k{NAQ1 zVuWN}FI}K)c$1rN)-tBMTTKj8L66X(3-8}kw*UL`8P38EIVo>i3d$?LpT1q!g7GQ7 zT3Q?$^}#g8m1Y58{T&U%+V7xHHlEi){-$1nb7HN-g(^YKncPqPNBLDZss*_7v6e(A zl6UBNGW=(88{BBrA71$`1<329&sNx_@VRIEvFrntPjL?(jaWpUsOO*ETsrufe!-uu zd0v4roFTD_>+QHomWWuA8C$gk{vhS#lJLp`w z3SSvw(jO$NG!bc!ce+AgAk+wePs;3GGc!5+)DGct8P>$C$dNz*{z|?em$(uI@$H}t z=8ehUO~?&*zbGB|my?Pez*l?Bb^Eu@S#+D=) z^f@T0&nlx>60*Pkd$VtfxUxEWmQ7#r;|AIq8F9AP)pB3+aq42fCwSSBH`Y}|jg2>9hFrjrHKmTUr7)>J>!C37J>p2qIKQZJ zRL&7=v%0k@DXc3#E4GD*#WKTD#o27w%XHS!N5AUCgMd+9hqXQZ*7c0JfvG5G-bj76 zvfsl<<{mhw01?svzjyu3E87gL-tN-s78_a9e?mk)?AZ^y*+q*4m}a~x7l~G|7LK8m zd279!gzP92Va1JQ-d#zF+>`KIyG~KF7Gp9MZX}M4;p$vimUgf!6Z#-t*A)(B?ganxIqW4$SYhevLc^>+=5y@Hg zaJI`A5(H0)03Tw)a~7i%Ss-xM&B9kXB9Y@5G-tIecJ79>24!bC3Wrc@_K0>5npYUo zjC|r&h3f1N2A4RwWam#MD7#MxpMy&=#i)dZJ?&Mu>VQL)+hI)=TN~hU9TV(JN?3hA zub&TkqhqoIwj&9d>O6+WaMTb|pL#B45mx!wnB|Z3?40TM$GA!33Ywv>eEh?tdOb7O zRf`_nN89l@N=TXgAf;2m@Qr^pD9drG#n>-f1caTqrsqxXd?YKCQa!Cr!kST|2 zae43uH)ni{@soOj#@R`_h=7cMxF??T(%(E6W7L?wDP~I^Zkmvqs_pl|xP{ZnR{SEe ztkPA5h2B1K%LsquNopD2_n2~&d`Kv4L`62>`C43^T+S*P#V=<~56B9hCbxCu^ z7ITPk{vNk$Lo)jai6+s)piL3sRtghyZkNl`I52!WSH!t08L1H979de-(@~uo63Tr& zD5-Dn;jS&wAQ8SVW=1{w<+1udUE!OM<&*b*qISg}2rF$#RTbv6_V7kr`?IJA-|p;< zak(v#wU4|i(;_Z?aDc2?q5wP~E_w!89Z+~Xy7Czw7jtIDKeP3E#@}W?(Pi>TG?sR} zs*n41N}4@HF)vd3ZD1a3Sy%KAzV}1}<<%j7=p{{ulnQ<~VO#Ik%10A!N^A+XcT&kG zH~l=V>jtz=1!iDMqJa%mh}l2U^=cjQRYa&-2)zW4S)Ogzqu;n@=p5i@dgSN*5I59p zyDml#i^Iw!SocU9d0G`+MX%J-oJ5ix~uIV{LMo)d}Q3u zrW=D8Ka5$F8`+?`dXlSt#{chselAE#3O_3xL+WO*78{)_i$IVZfWpd?#@@c)9`1T( zABLIar{(M!Ch6=PZpW2T4zo#J+U~r0F9SYiECXLqbERk=S{s9Bd@Dp=oN?mo4gdQy zh`+YC&l@9@fxkjXy>W%=X_IJcxrQxBN4+=S-!EoG5WUD8W7IVyK^oNPAQ-(`ed2{S zw=}m|OE}O|f_!+zj9Pkx)LUg@kXMw2{lxbgc6c^@sx9`n8h0S=`t)4JUAX10+aZzO z-C%=WlYdTwH-(U$l5buT(FdJb1`9C;S{GK=@~1UB(_rDR67>`p!FzW7rz6NnwMN^8 zkxB~n>*aNhSL>NZLu5-|C^;?1axI${nrZIGOL-Kf>yX1?H~#9t-F}KJAk!(SCzYHh zdtKo1gWKp{CJH78+40wZ!Y>du7ZD%6AB(KhE+&&Ub6zznHmL=w(wZh#*SCemASV`} zjYbN2Kv^rT{}lTaCA~mdIl}N#7A@<}x%5&=ll(2GUZ#IW)zWUxi+uSV@ZseM{OZvi z;SX>r*jJmCsK(FUA*-uDWtq+Cc;QeJ0tQOh{~(zg+_X2Ud;0<=Ml^gj=D36agE2Gf z6Zai{=u=V(3U1S0F&m*>3TK=HQgbw`TJOd{!4H%Dp1>oA^>l>8kMih@O*!NlZQidO z!-CP(6&-z^#kWvmL-4@3>EgUv^ulJ|zK~^<4y5}r#y3wc?8o*X8{X&hib5k%{wxZG zdjcslqhBh_N2Ee5`RU4%$lzGVolL~x&`@27IIFd`3+}ruI^a6(6Mv*T`X7?H9lY{G z@@p)r-gv0ZJhVWmwr=oBVR{e4^%H79Te2FxOBHg~rUH+!wV1{$gtk_2)u-`SlI|^i8^YE4uNALqHXWQa;tkcU zrm+UPDkUPfNMWf3FP~&#e7+8$5QOASGWGuDf>&5BA4ozp#p?X07ZA4fV^dx*Hnh~y z(Gg@SDYm&cdE{jc6!dDSBRBH^YDFbfsuYlo{Fl!@p`z)cr9*YhWqoyf&D3%fS=1mN z1-S2tQw-Pn8bNHli2D}SZg`S=xNM}e43`ztMevUdCKJPg=Z-pi+?(; zVd3(-aA?24KWk1mAN>C}F^d}t3POgLHEQT?jzxO@F>rEHkD z=8)EGf~pfF)`?JrEge=47dWk|9lT6Y|AJQ1v%k-Bfv*0UF%afk_oLpWtP2(cS(g~7 zz`%f@AWJD(S>dp_MDa(cJ-us~&!0(q%zLvD#J*Aa%mVtg5ihm0O!eu=LX42Rbu~V~ z;oJsw(}Bz(c}JprtU63@sanBp%6+bMSgl}vtJc8t$PJY!ZHY%BhdVM8+47T5x=xy{ zz+Je;?LKnavT0ktimC6%OW?=SHbWDQ1ah~*9UUF0BS(+=tcX?Um?2lqWD(pX3zFTh z;lCb+Mab#F;w`AFS!T#8>u9C@9aGikMq66+0NA$N}<5oKUFfWlWbA59IQu2i}^)Bi=osCF-`zqopJU zCMG7}Nl8g?Q`7n|6#|fdotw4y5(3SMSZ&92_4HA08wxQ7U7b95tj7I5Wipu@wj_s1 z2kZpMd<0IdHF4}_f};zJ4r0>eg`;~;{xoCD8i z69XxKDp2ChwN>OR9h75xNLh7dK4845&Wd3yWd;ZC2Ozxf|i7&sXhl#sZK!k!HAQbFvjrSi^sx% Nhs%CqvlAu#e*naMgS6Q&Ps(O)vc{8nEr2;h&BA5PCW7cG5%fNZl1Or#;yc)Qi%>z*?z2Jdg1Tm z;8_l!wvSQ5IVHM06DY_q^k8Q}k%is-9h+JpgO#WK7_Xvs@4w6e*hM8rXmwrU_Gho$e$jvl1#LFlC787xK0D%KH zXI))iy}??UpB#n{OV5J$7?p6^{?+KQ)|ThcLyLnV7BnLNgc4{g-Q&Cmqp;`1)KCqm zWgFf2m@ZUkV>%{i@5?cx6mmBhdp&0hlg%g;omR82-tCK8AC4ZqNY=S0U1FwK1n=AF zzJoYVxX1kmpFUUkeDmu;d^bOOH7c!0paEbwz9*ZhI6+Zo>*ib{2oesmhu`g{J>tTg zKMC!O(Pm(8SMS*&O8Kz%wYAlZNo|MqO2*n1BR&T=qDnK1oza|o)D-xYtqp_dD?V?c+GZV^IU7(5alBJBYHKNmG4AFP|kIe-vc?R;Kwco41qyycqF~L=$L{ zq+2ovuVM}NH~uV+Rm|jw2)x@>TX>Js<)G?TR$iHe9PiRrS;gUj@SU~C92>>1dXB#d zI;zR`VWu(2uNtT z<}b`nr=^l0z_Zp^qALAE=~h&Pa>8CMsHUlVM%cZEM=A$o%hW8i++Zd5-vk-&yf83} zJ!w$sCCG})s%!elrBaW@vFeKNfdw{K^%#*dFw8zT65ZkD(?}5x!v^+kgajyl-RIIy2Ut4=j$C#zPS0}PB z=|%)IQ2U!$Cm1zhD_9c2lDpFCo&M$%o-5=;W9(cRDa1rhy37Yh#$r*j=~ril#S&fI z+5Q%zb)$_O5GYTpXFHCwAu!Ba#r`B^6S_dj;>{tP&UGGcv8Ec2TeqY2mcwK^5=+hd zLw9-+97fl5?{Rl@NTQz3E8A<9A&yjOJbcK@BV(2^UpG95S`)@Xahx2l(nPI4KRC0= zS4D~w8!;(*ym8+<*AsFT(S};6>9gld_4tNn9Y@JGBn?%*$Xi?#I=dQxBp9G3CI_p) zm4(0KXAa43m{~*)P@G*7c!y`4jk^^wdGW-6uH?&^A$*y8=eh007uO_!TVLW$5gn@; z0xK~f%@)aj<0D5(94*4_?Y-h}R^#cTLRWimh53Cg$gUlOtST`$8i8TzStz+gMVV_G zp-}K$2oJ&O=esCTYcmS@g-mlhpj(eM`SBS#Am4*7EU0UtCv*Q<&{Dd-(_k&mf5*C>kS&(^FZ^jqL)cElhArIC@Elw& zFp#Odh}fs^_3n+k&2$K|<}CU>CtHNkQ$#;(t3yW53d|}tWj69ms5)5&!(NaJdFUs4 z4nN~_ELv_zY@u-V4{0r-ew;Gu7F?WbN!n#oLJz8m4y(}9HZ>Q^r5x}*X()JhNSS;^ml65c{=CC#Jv0So76VeJA(usr5kbJwj@<$jAPr|BZKl1&*HbPD5SBk6G04P94N+Id^Zn@68t)J^|f!os&-@$D7bos40->E%vZ!dIiL z>wnpmm@6N|?f=ZzCy z@9qtmhVoDCc>lZl_-h5V;;sSHIBoqWDXh8JMB-f~-TW52P{)#wX+HJjLVbXN5~Pcm z#_92fI8oV~Qm^!1kEc$sL=;NEbVazGa~&!;ceNSx?G1D2Pl!+ZkE%v+yRm6rZH&y_ zR4GMxO9SHF`($zR+AV7CtqiV$(+Sy&u#iK1;{~l`3xxx_XH*`ryL^1vxqtbh(^uw_ z>)PyY6&306v};6M$zOvD;HtIt@XqdxpzXMeziiv4$7WRF@(A@pn}ZSdRu|_XylZ8f z8m>W|aGJIV10O99_#q>dU?ixMH|npi&t)GQP5{PUM^4D`DsQSav~4|7x7_gZW!*gK zOKp~nRjjMFq>H0xvz{`|o{yynY@ccQ2jn&?H&LoDx6k|oUpcgnmL zmp*9{wQrk3s3u$izD=;;ZmWG3aA!!P(_H$()2HT(i^{g|Jp>OTV&KuyGI`_O?M6zR zA!J1ZYt^h~+{PiMRA{VZr1R9{87*p&E}lxi>I zSJ4&X`Ku5E8{uL%`Ug&DPZZ7|=RIXnHBe?Ls4nv1Tq^#L%sw-VJ5FXTGJV|D$fc>R zf;XvqhI_!B381{!EZO1YkY6~Gr}ZU4;XB^Drmhs%3O$oWk;;*%YyAy zr~F%xo1m&&3v6Q87UZio77Cq=s-&XGCVzoZ+$ea<(vY&4^_{|)z*D>%^~}z1yMcC3 zu?7);l7K5=%YrO0Eq@PuCpFrX>A#2VN+JOT6uK4qMRlSAS4y#eWOTWU#WH)h(fkxP z3-d+7IkrzcbNa`w>P;{yKzHDuwByyANSj|#l$;RIPe{)nCqg?49~QTW*2JFhEte08 z7>7CX0~*56Lrk6Wp1)WareDya{A|vHQlu#9id>@IPr7UEYx(LD9TPoR_uoGd-stY_ zh6YVyq}rF2xeV4|x30MHaR-L(4O~(!J^wLUYPUbqY@rRWV?c#>q2TJN2h4@BHWT|H zIX67Fs%Sqe{4 zHF#3P{J)%qRcV>AwT%vB#_zWnIft`EgJiX4o%cbbj~mJTj~9}630 zVa@N3u|@rTuqU=x*P6oSrmhOYn7W!isg(649@7B}x2T{dB9zL-NVvX1MCZbfGri6$ zE9&_|I~4XhE?WA^u$d2pWQRjx$lmQK;1Q485JPhsoxQ#xpD(WaPBnvA*KIiH_2~L; z=f!0!d2`1e2JI&|&ORe+)I?<0(cDyb+-W72cVP`J7w5-xp=b*#)zzeH*;0z>M1AC3 za&{&g4g!<_3D3>h19G4|YWc36-&d7SVGC4xd)DK+B{G zFu$pmxyR?@I4Fw^GR@>etZ?Gb6AvC<5ih??nH}yUR!_oA%EfnEY@O|)HS&kqTwN_6 zcAYB@#~F{$VRSVro(O90s)^LMI6Dv=Vyf}-VrtR3Pig|A6NkV^ubyc>k62!)uS`mZ zU_WQAT*7brQqvkX+a@a*v#O#z-K!sq{grj4sxD(K(u;z8j>pkyL!JhA(s|cY6es?w z>I5HGCO7e>o?`8^4=(yhNwnXEV8;ZJUV zz-i}|H7&itPYdQ_i_Z&c_nzdSLU%VbpZS8b-Us6P-z)J3cTC@a(Cs+~9l8_|-o+dQ zof<_y#noBc?!DPt>ji&pM)lZD?%>|Sai!ANL!DZu`hW8f_}czQEFo4QfGCe-Csb6x z$Coxg9ADR-tsep&R_Z?dg)7V6&bA1DnJ@8ruNNj?5%M9b(DoJOXPYtE-K_(*%-ft! zz~gY_oVLPCS6iS9UtYp}W8Ay=`dhcYm7??33PsAxJ4xCrqWxMfJPTy9-V_KtopSKx zGW&1F3LolHhcDj5&6sn8_#DOcc;SJDp_)~ff(4n*=xLyU~d^J609w&oktGKC1<$$ug+@*ub zl#O_m^p+9-(q%f9nDla^ymTdP++h~vcHgC{%kItmHQ*L0!nJ+dsUqvVUJqXf(5X)z z7noVAeq}Oa<;;jgB4<>ZmX@K=gNHH+(~=og!4a{S+mRIdJy}_crkCV)Ov<-}C#T^a z!r+r4k-mrjF6O?*;Be%V^fnt(#t-D$Pu<~C6qrq4AL&XfZ&o~MG$5Wfm5c#@SnSJ`!tSp zry1~qk1$Ufnd+Q=Uhnn2DASQK^oA4srO-DYm#Ff_Ct)ZC4u?0oZX$j6GomUivq+~{ zoXQ@R9{d$^YKnG2w&G>W%%xltJJb74 zy(yemN7cW>^|sLFrPvwc z|Kw~ns;0KVd1{dY^xDjZWHJ-?`ln%@-e1Fsmai<#ST!7QiG~LTp9na8`YnM(0(}wE z_u|4>d{^uUzjOnJ&;9%=i1E*yx`Qwe77?zDE!-7ldg$l4gru=YKjKldXP@|jq;#Eb z7+UUV?B$1l*1PwoQ zEiJ?ylTAuaHmk0!EiRQs5|WzB?V1(1*W~o(gyyFOY2dqXFVNWfsF*5q9qqwN*|U^^WVD&{xo|R>xAQ2| zWZ!fpLNt2S`mQ{*vIpg&0TT_xS6xcHqY`Zi3NAP52m8-8256d}lg#S|*yWwJ_1_>f zIj>_jOkb>Tq)F=k)&dJScYAeDXlLFvwHB)x?%8vjn~{Na*lq`;XNp>OCtt?_u1xn7 zcknRV9!xs=3oPECrc&X|&|$8n;?z-6ZTEe3NS~TJ?D&|V!6sr1;^PofZ-2>Ty-YPo z7nq=fk>@zo{J0*YMS1)%e3G{Y{5rY^QK7lI2=8B^AI99xgvik65Vg6e_XB!%fTaL0$KJwpO5Av0>uJKlx{J zAQvog3V~#MUHJ!^0lGx*El}P1i?rNhKMxb({&S_vI2_K?RihdQRn&5}zOHD0AYNR^ z4+sr?H~jNwf=PAVza_)BlFF80mHWeXR$L+{%17pRzU6tFnp5^{Q4jP8M6ACb47C5@ zFzM;z6F5CH)9|sx2?5BM6S4hF#G)d`a-WM1MCNEBqClh8+Q__iccH11k&zMH!@~nk zrG7QDwgXZPNQ%Hc6!LajJ|-c(IVXa+^@fN=xBvR}D$e}}~EiElVWgkEW4s3b} WFPJ#)x>s7~1zh&-cYI{ejQu~c)z_#1 literal 0 HcmV?d00001 diff --git a/livejournal/htdocs/img/style/webley/jwc25.png b/livejournal/htdocs/img/style/webley/jwc25.png new file mode 100755 index 0000000000000000000000000000000000000000..63a93d6d232944934a9e94b82465d3b377b68142 GIT binary patch literal 5555 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

    p?>"; + return; + } + + if ($op eq "addnew") + { + my $bname = $FORM{'bname'}; + my $loc = $FORM{'loc'}; + + my $pos = LJ::Portal::create_new_box($portopts, $bname, $loc); + LJ::Portal::save_portopts($remote, $portopts); + + my $modform = LJ::Portal::make_box_modify_form($portopts, $loc, $pos); + if ($modform) + { + $title = "Configure Box"; + $body .= $modform; + return; + } + else + { + if ($loc eq "moz") { + $op = "mozadd"; + } else { + return BML::redirect("$LJ::SITEROOT$LJ::PORTAL_URI"); + } + } + } + + if ($op eq "modbox") + { + my $newargs = LJ::Portal::modify_box($remote, $portopts, $FORM{'loc'}, $FORM{'pos'}, \%FORM); + if ($FORM{'loc'} eq "moz") { + $op = "mozadd"; + } else { + return BML::redirect("$LJ::SITEROOT$LJ::PORTAL_URI"); + } + } + + ## add sidebar to mozilla + if ($op eq "mozadd") + { + $title = "Add Mozilla Sidebar"; + $body = "If you're running Mozilla or Netscape >= 6.0 you can click the link below to add this LJ portal box to your Mozilla sidebar. If you're using Internet Explorer, sorry.

    "; + $body .= "

    "; + $body .= "If you just added a new box to the sidebar or changed a setting and the $LJ::SITENAME sidebar is already open, hit the reload link in the sidebar."; + return; + } + + return; + +_code?> +body=> +page?> +link: htdocs/portal/moz.bml, htdocs/portal/index.bml +post: htdocs/portal/alter.bml + _c?> diff --git a/livejournal/htdocs/portal/box.bml b/livejournal/htdocs/portal/box.bml new file mode 100755 index 0000000..42495c7 --- /dev/null +++ b/livejournal/htdocs/portal/box.bml @@ -0,0 +1,21 @@ + \$body, + 'head' => \$head, + 'bodyopts' => \$bodyopts, + 'remote' => $remote, + }; + + LJ::Portal::make_mozilla_box($remote, \%FORM, $opts); + + return "$head$title$body"; + +_code?> + _c?> diff --git a/livejournal/htdocs/portal/index.bml b/livejournal/htdocs/portal/index.bml new file mode 100755 index 0000000..59aa47d --- /dev/null +++ b/livejournal/htdocs/portal/index.bml @@ -0,0 +1,37 @@ + \%FORM, + 'remote' => $remote, + 'head' => \$head, + 'body' => \$body, + 'bodyopts' => \$bodyopts, + 'border' => 0, + }); + + return; + +_code?> +head<= + + + +<=head +bodyopts=> +body=> +page?> + _c?> diff --git a/livejournal/htdocs/portal/moz.bml b/livejournal/htdocs/portal/moz.bml new file mode 100755 index 0000000..3b0d028 --- /dev/null +++ b/livejournal/htdocs/portal/moz.bml @@ -0,0 +1,22 @@ + \$body, + 'head' => \$head, + 'bodyopts' => \$bodyopts, + 'remote' => $remote, + }; + + LJ::Portal::make_mozilla_bar($remote, \%FORM, $opts); + + return "$head$title
    $LJ::SITENAME
    (Reload | Add Box)

    $body"; + +_code?> +link: htdocs/index.bml, htdocs/portal/alter.bml + _c?> diff --git a/livejournal/htdocs/preview/entry.bml b/livejournal/htdocs/preview/entry.bml new file mode 100755 index 0000000..8635a71 --- /dev/null +++ b/livejournal/htdocs/preview/entry.bml @@ -0,0 +1,255 @@ +" unless LJ::did_post(); + + my $ret; + my $remote = LJ::get_remote(); + my $styleid; my $stylesys = 1; + + ### Figure out poster/journal + my ($u, $up); + if ($POST{'usejournal'}) { + $u = LJ::load_user($POST{'usejournal'}); + $up = $POST{'user'} ? LJ::load_user($POST{'user'}) : $remote; + } elsif ($POST{'user'}) { + $u = LJ::load_user($POST{'user'}); + } else { + $u = $remote; + } + $up = $u unless $up; + + ### Set up preview variables + my ($ditemid, $anum, $itemid); + my %req = ( 'usejournal' => $POST{'usejournal'}, ); + LJ::entry_form_decode(\%req, \%POST); + + my ($event, $subject) = ($req{'event'}, $req{'subject'}); + LJ::CleanHTML::clean_subject(\$subject); + LJ::CleanHTML::clean_event(\$event, $req{'prop_opt_preformatted'}); + LJ::expand_embedded($u, $ditemid, $remote, \$event); + + if ($u && $up) { + ### Load necessary props + my @needed_props = ("stylesys", "s2_style", "url", "urlname", + "opt_usesharedpic", "journaltitle", "journalsubtitle",); + + LJ::load_user_props($u, @needed_props); + + ### Determine style system to preview with + my $get_styleinfo = sub { + my $forceflag = 0; + LJ::run_hooks("force_s1", $u, \$forceflag); + if ( !$forceflag && $u->{'stylesys'} == 2 ) { + return (2, $u->{'s2_style'}); + } + # no special case and not s2, fall through to s1 + return (1, 0); + }; + + ($stylesys, $styleid) = $get_styleinfo->(); + } else { + $stylesys = 1; $styleid = 0; + } + + if ($stylesys == 1) { + # pre-load common strings for little speed and less typing later + # (we're doing this *after* set_language_scope is called, because + # two below are relative strings) + my %T = qw(postcomments talk.commentpost + readcomments talk.commentsread + link talk.commentpermlink + nosubject .nosubject + ); + foreach (keys %T) { $T{$_} = $ML{$T{$_}}; } + # make the title + { + my $subject = $req{'subject'} || $req{'event'}; + LJ::CleanHTML::clean_subject_all(\$subject); + $subject =~ s/\n.*//s; + # yes, the 3 param to text_trim is chars, and length returns bytes, but + # it works, as bytes >= chars: + $subject = LJ::text_trim($subject, 0, length($req{'subject'}) || 40); + } + + $ret .= "

    "; + + if ($u) { + $ret .= ""; + my $picid = LJ::get_picid_from_keyword($up, $req{'prop_picture_keyword'}); + my $upics = LJ::get_userpic_info($up); + my $pic = $upics->{'pic'}->{$picid}; + + if ($pic) { + my $alt = $up->{'name'}; + if ($req{'prop_picture_keyword'}) { + $alt .= ": $req{'prop_picture_keyword'}"; + } + LJ::text_out(\$alt); + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
    "; + my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; + if ($is_shared) { + $ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up), + 'commlink' => LJ::ljuser($u) }); + } else { + $ret .= BML::ml("talk.somebodywrote", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up) }); + } + + my $etime = LJ::date_to_view_links($u, "$req{'year'}-$req{'mon'}-$req{'day'}"); + $ret .= "
    @ $etime $req{'hour'}:$req{'min'}:00"; + $ret .= "
    "; + } + + ## dump the log entry, unless we're browsing a thread. + my %current; + if ($req{'prop_current_mood'} || $req{'prop_current_moodid'}) { + $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, + $req{'prop_current_moodid'}, + $req{'prop_current_mood'}); + } + if ($req{'prop_current_music'}) { + $current{'Music'} = LJ::current_music_str($req{'prop_current_music'}); + } + + $ret .= "

    "; + + if (%current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
    $curname$current{$_}

    \n"; + } + + ### security indicator + my $sec = ""; + if ($req{'security'} eq "private") { + $sec = BML::fill_template("securityprivate"); + } elsif ($req{'security'} eq "usemask") { + $sec = BML::fill_template("securityprotected"); + } + + $sec .= "
    \n" unless $sec eq "" or $req{'subject'}; + $ret .= $sec; + + ### + if ($subject) { + BML::ebml(\$subject); + $ret .= "$subject
    \n"; + } + + $ret .= $event; + $ret .= "

    "; + + $ret .= "

    "; + } else { + $LJ::S2::ret_ref = \$ret; + my $opts; + my $r = Apache->request; $opts->{'r'} = $r; + + $u->{'_s2styleid'} = $styleid + 0; + $u->{'_journalbase'} = LJ::journal_base($u->{'user'}); + + my $ctx = LJ::S2::s2_context($r, $styleid); + $LJ::S2::CURR_CTX = $ctx; + + my $p = LJ::S2::Page($u, $opts); + $p->{'_type'} = "EntryPage"; + $p->{'view'} = "entry"; + $p->{'comment_pages'} = undef; + $p->{'comments'} = []; + $p->{'comment_pages'} = undef; + + my $userlite_journal = LJ::S2::UserLite($u); + my $userlite_poster = LJ::S2::UserLite($up); + + my $userpic = LJ::S2::Image_userpic($up, 0, $req{'prop_picture_keyword'}); + + my $comments = LJ::S2::CommentInfo({ + 'read_url' => "#", + 'post_url' => "#", + 'count' => "0", + 'maxcomments' => 0, + 'enabled' => ($u->{'opt_showtalklinks'} eq "Y" && ! + $req{'prop_opt_nocomments'}) ? 1 : 0, + 'screened' => 0, + }); + + # build tag objects, faking kwid as '0' + # * invalid tags will be stripped by is_valid_tagstring() + my @taglist = (); + LJ::Tags::is_valid_tagstring($POST{prop_taglist}, \@taglist); + @taglist = map { LJ::S2::Tag($u, 0, $_) } @taglist; + + # format it + my $raw_subj = $req{'subject'}; + + my $s2entry = LJ::S2::Entry($u, { + '_rawsubject' => $req{'subject'}, + 'subject' => $subject, + 'text' => $event, + 'dateparts' => "$req{'year'} $req{'mon'} $req{'day'} $req{'hour'} $req{'min'} 00 ", + 'security' => $req{'security'}, + 'props' => $req{'props'}, + 'itemid' => 0, + 'comments' => $comments, + 'journal' => $userlite_journal, + 'poster' => $userlite_poster, + 'new_day' => 0, + 'end_day' => 0, + 'tags' => \@taglist, + 'userpic' => $userpic, + 'permalink_url' => "#", + }); + + $p->{'multiform_on'} = 0; + + if ($u->{'opt_blockrobots'}) { + $p->{'head_content'} .= LJ::robot_meta_tags(); + } + if ($LJ::UNICODE) { + $p->{'head_content'} .= '\n"; + } + + $p->{'entry'} = $s2entry; + + my $userlite_journal = LJ::S2::UserLite($u); + + $p->{'comments'} = []; + + $p->{'viewing_thread'} = 0; + + my $copts; + + $copts->{'out_pages'} = $copts->{'out_page'} = 1; + $copts->{'out_items'} = 0; + $copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef; + + $p->{'comment_pages'} = LJ::S2::ItemRange({ + 'all_subitems_displayed' => ($copts->{'out_pages'} == 1), + 'current' => $copts->{'out_page'}, + 'from_subitem' => $copts->{'out_itemfirst'}, + 'num_subitems_displayed' => 0, + 'to_subitem' => $copts->{'out_itemlast'}, + 'total' => $copts->{'out_pages'}, + 'total_subitems' => $copts->{'out_items'}, + '_url_of' => sub { return "#"; }, + }); + + LJ::S2::s2_run($r, $ctx, $opts, "EntryPage::print()", $p); + } + return $ret; +} +_code?> diff --git a/livejournal/htdocs/protocol.dat b/livejournal/htdocs/protocol.dat new file mode 100755 index 0000000..8b28ddf --- /dev/null +++ b/livejournal/htdocs/protocol.dat @@ -0,0 +1,741 @@ +{ getfriendgroups +.des +Retrieves a list of the user's defined groups of friends. +.response +{ frgrp_num_name +.des +The name of the friend group with number num. +} +{ frgrp_num_sortorder +.des +The sort-order of the friend group with number num. An integer value between 0 and 255. +} +{ frgrp_num_public +.des +If this key is returned and its value is "1", then group num is a public group. (that is, other users can see the name of the group and who is in it) +} +{ frgrp_maxnum +.des +The largest friend group number that was returned. This is not the number of friend groups returned, it is simply the upper bound. In other words, there may be holes as you iterate from 1 to frgrp_maxnum, so don't assume the presence of any key/value pairs returned. If this value is 0, however, you can safely assume there are no friend groups, as the minimum allowed friend group number is 1. +} +} + +{ editfriendgroups +.des +Edit the user's defined groups of friends. +.request +{ editfriend_groupmask_friend +.des +Send a key in the form editfriend_groupmask_friend where friend is the friend's username. The value should be a string representing an unsigned 32-bit integer with bit 0 set (or the server will force it on anyway), bits 1-30 set for each group the friend belongs to, and bit 31 unset (reserved for future use). +} +{ efg_delete_groupnum +.des +Send a key of this type to delete the friend group with number groupnum (which can be from 1-30, inclusive). The server will modify all old entries that allow access to that friend group, so a new friend group using that number won't have access to old non-related entries, and unset the bit for that friend group on the groupmask of each friend, unless your client sends the friend's new groupmask explicitly. +} +{ efg_set_groupnum_name +.des +Create or rename the friend group by sending this key, where groupnum is from 1-30. The value is the name of the group. +} +{ efg_set_groupnum_sort +.des +If efg_set_groupnum_sort is sent, this field should be sent to indicate the sorting order of this group. The value must be in the range of 0-255. The default is 50. +} +{ efg_set_groupnum_public +.des +If efg_set_groupnum_public is "1", then this group is marked as public. If public, other users can see the name of the group and the people that are in it. +.optional +1 +} +} + +{ login +.des +Log in to the server, while announcing your client version. The server returns with whether the password is good or not, the user's name, an optional message to be displayed to the user, and the list of the user's friend groups. (friend groups can also be retrieved using the getfriendgroups mode) +.request +{ clientversion +.des +Although optional, this should be a string of the form Platform-ProductName/ClientVersionMajor.Minor.Rev, like Win32-MFC/1.2.7 or Gtk-LoserJabber/1.0.4. Note in this case that "Gtk" is not a platform, but rather a toolkit, since the toolkit is multi-platform (Linux, FreeBSD, Solaris, Windows...). You make the judge what is best to send, but if it's of this form, we'll give you cool statistics about your users. +.optional +1 +} +{ getmoods +.des +If your client supports moods, send this key with a value of the highest mood ID you have cached/stored on the user's computer. For example, if you logged in last time with and got mood IDs 1, 2, 4, and 5, then send "5" as the value of "getmoods". The server will return every new mood that has an internal MoodID greater than 5. If you've never downloaded moods before, send "0". If you don't care about getting any moods at all (if your client doesn't support them), then don't send this key at all. +} +{ getmenus +.des +Send something for this key if you want to get a list/tree of web jump menus to show in your client. +} +{ getpickws +.des +If your client supports picture keywords and you want to receive that list, send something for this key, like "1", and you'll receieve the list of picture keywords the user has defined. +} +{ getpickwurls +.des +If your client supports picture keywords and can also display the pictures somehow, send something for this key, like "1", and you'll receieve the list of picture keyword URLs that correspond to the picture keywords as well as the URL for the default picture. You must send getpickws for this option to even matter. +} +.response +{ name +.des +The user's full name. Often, clients use this to change the top-level window's title bar text to say something like "LiveJournal - User name". You can just ignore this if you'd like. +} +{ message +.des +A message that should be displayed in a dialog box (or to the screen in a console application). The message is rarely present but when used notifies the user of software updates they've requested to hear about, problems with their account (if mail is bouncing to them, we'd like them to give us a current email address), etc. To test this, use the user account test with the password test... a message will always be returned. +} +{ frgrp_num_name +.des +The name of the friend group with number num. +} +{ frgrp_num_sortorder +.des +The sort-order of the friend group with number num. An integer value between 0 and 255. +} +{ frgrp_num_public +.des +If this key is returned and its value is "1", then group num is a public group. (that is, other users can see the name of the group and who is in it) +} +{ frgrp_maxnum +.des +The largest friend group number that was returned. This is not the number of friend groups returned, it is simply the upper bound. In other words, there may be holes as you iterate from 1 to frgrp_maxnum, so don't assume the presence of any key/value pairs returned. If this value is 0, however, you can safely assume there are no friend groups, as the minimum allowed friend group number is 1. +} +{ access_count +.des +If this user has access to post in shared journals (i.e., news account), then this key is returned saying how many journals (besides the user's own) he/she has access to. Then, a key is returned for each journal. +} +{ access_n +.des +The nth shared journal this user has access to post to. These are returned in alphabetical order. +} +{ mood_count +.des +The number of new moods that are being returned. +} +{ mood_n_id +.des +The server mood ID for mood n, where n is between 1 and mood_count. +} +{ mood_n_name +.des +The mood text for mood n, where n is between 1 and mood_count. +} +{ menu_menunum_count +.des +Each menu or submenu returns the number of items in it. Menunum "0" is the root menu and that's where you should start your recursive construction of the menus. +} +{ menu_menunum_itemnum_text +.des +The text of the itemnumth menu item (1-based index) in the menunumth menu (0-based index.. kinda. it's not really an array.) If the text is a single hypen "-", then show a menu separator bar instead of any text. +} +{ menu_menunum_itemnum_url +.des +The URL to jump to for the itemnumth menu item (1-based index) in the menunumth menu. This may be absent, in which case this is a menu item which opens a sub-menu. +} +{ menu_menunum_itemnum_sub +.des +For menus that don't have associated URLs, this key contains the menunum of the associated sub menu. Call your menu creation function recursively and start making that menu. +} +{ pickw_count +.des +The number of picture keywords about to be returned. Picture keywords are used to identify which userpic (100x100 icon) to use for that particular post. For instance, the user may have "Angry", "Happy", and "Sleepy" picture keywords which map to certain pictures. The client should also do a case-insensitive compare on this list when a mood is selected or entered, and auto-select the current picture keyword. That way it seems that selecting a mood also sets their corresponding picture. +} +{ pickw_n +.des +The nth picture keyword, where n is between 1 and pickw_count. If a user selects one of these, send it as postevent/editevent meta-data with the key "picture_keyword" (which of course you have to prefix with "prop_" when sending) +} +{ pickwurl_count +.des +The number of picture URLs being returned, if you sent the 'getpickwurls' key. This number will always be the same as pickw_count. +} +{ pickwurl_n +.des +The URL of the nth picture. It corresponds with the nth picture keyword returned in the other list. Note that the content behind these URLs can never change, so if your client downloads these to display, just cache them locally and never hit the servers again to re-download them or to even check if they've been modified. +} +{ defaultpicurl +.des +The URL of the default picture (if you sent the 'getpickwurls' key). Note that the content behind this URL can never change, so you can cache it locally; also note that the default picture might have no keyword associated with it. +} +{ fastserver +.des +LiveJournal sites may have priority servers for paying customers. If this key is both present and set to value "1", then the client has permission to set the "ljfastserver" cookie in subsequent requests. The HTTP request header to send is "Cookie: ljfastserver=1". If you send this header without getting permission from the login mode, your requests will fail. That is, you'll trick the load balancer into directing your request towards the priority servers, but the server you end up hitting won't be happy that you're trying to scam faster access and will deny your request. +} +} + +{ getdaycounts +.des +This mode retrieves the number of journal entries per day. Useful for populating +calendar widgets in GUI clients. +.request +{ usejournal +.des +If getting the day counts of a shared journal, include this key and the username you wish to get the counts of. By default, you load the counts of "user" as specified above. +.optional +1 +} +.response +{ yyyy-mm-dd +.des +For each day that the user has posted a journal entry, a key in the form yyyy-mm-dd is returned, with the value being the number of entries posted that day. The absence of a key implies zero entries for that day, as well as the presence of a key with the value "0". Note that mm and dd are always two digits, zero padded, so the total key length will always be 10 characters. +} +} + +{ postevent +.des +The most important mode, this is how a user actually submits a new log entry to the server. +.response +{ itemid +.des +The unique number the server assigned to this post. Currently nothing else in the protocol requires the use of this number so it's pretty much useless, but somebody requested it be returned, so it is. +} +{ anum +.des +The authentication number generated for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) +} +{ url +.des +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. +} +.request +{ event +.des +The event/log text the user is submitting. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. +} +{ lineendings +.des +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r)). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. +} +{ subject +.des +The subject for this post. Limited to 255 characters. No newlines. +} +{ security +.des +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. +.optional +1 +} +{ allowmask +.des +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. +} +{ year +.des +The current 4-digit year (from the user's local timezone). +} +{ mon +.des +The current 1- or 2-digit month (from the user's local timezone). +} +{ day +.des +The current 1- or 2-digit day of the month (from the user's local timezone). +} +{ hour +.des +The current 1- or 2-digit hour from 0 to 23 (from the user's local timezone). +} +{ min +.des +The current 1- or 2-digit minute (from the user's local timezone). +} +{ prop_name +.des +Set an arbitrary (but restricted) meta-data property to this log item. See [special[logprops]] for the documentation of them and the list of valid names. You may send zero or more keys like this, one for each property you're setting. +} +{ usejournal +.des +If posting to a shared journal, include this key and the username you wish to post to. By default, you post to the journal of "user" as specified above. +.optional +1 +} +} + +{ friendof +.des +Returns a list of which other LiveJournal users list this user as their friend. +.request +{ friendoflimit +.des +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. +.optional +1 +} +.response +{ friendof_count +.des +The number of records that will be returned. The records returned are named numerically, +using a 1-based index. (1 .. friendof_count) +} +{ friendof_n_user +.des +The nth user that lists this user as their friend. +} +{ friendof_n_name +.des +The nth user's full name. +} +{ friendof_n_bg +.des +The background color the nth user chose to represent the current user. +} +{ friendof_n_fg +.des +The text color the nth user chose to represent the current user. +} +{ friendof_n_type +.des +The account type of this user, if it's not a personal account. Currently the only possible value is "community", which means you're a member of that community. +} +{ friendof_n_status +.des +The status of this user. If this field is absent, the user has a normal active account. Otherwise the currently possible values for this field are "deleted", "suspended" and "purged". +} +} + +{ getfriends +.des +Returns a list of which other LiveJournal users this user lists as their friend. +.request +{ includefriendof +.des +If set to 1, you will also get back the info from the "friendof" mode. Some clients show friends and friendof data in separate tabs/panes. If you're always going to load both, then use this flag (as opposed to a tabbed dialog approach, where the user may not go to the second tab and thus would not need to load the friendof data.) friendof request variables can be used. +.optional +1 +} +{ includegroups +.des +If set to 1, you will also get back the info from the "getfriendgroups" mode. See above for the reason why this would be useful. +.optional +1 +} +{ includebdays +.des +If set to 1, birthdays will be included with the friends results below. +.optional +1 +} +{ friendlimit +.des +If set to a numeric value greater than zero, this mode will only return the number of results indicated. Useful only for building pretty lists for display which might have a button to view the full list nearby. +.optional +1 +} +.response +{ friend_count +.des +The number of records that will be returned. The records returned are named numerically, +using a 1-based index. (1 .. friend_count) +} +{ friend_n_user +.des +The nth friend's user name. +} +{ friend_n_name +.des +The nth friend's full name. +} +{ friend_n_birthday +.des +The nth friend's birthday. Note that this is only returned if the user has set +their info to visible and if they have set a birthday, otherwise this key is skipped. +You will also need to set includebdays to 1 when you make the request in order to +receive this field. +} +{ friend_n_bg +.des +The background color representing the nth friend. +} +{ friend_n_fg +.des +The text color representing the nth friend. +} +{ friend_n_groupmask +.des +If the group mask is not "1" (just bit 0 set), then this variable is returned with an 32-bit unsigned integer with a bit 0 always set, and bits 1-30 set for each group this friend is a part of. Bit 31 is reserved. +} +{ friend_n_type +.des +The account type of this friend, if it's not a personal account. Currently the only possible values are "community" and "syndicated", which means you're monitoring this community/syndicated feed on your friends list. (Note that it does not imply that you're a member of the community if the type is community, just that you monitor it.) +} +{ friend_n_status +.des +The status of this user. If this field is absent, the user has a normal active account. Otherwise the currently possible values for this field are "deleted", "suspended" and "purged". +} +} + +{ editfriends +.des +Add, edit, or delete friends from the user's friends list. +.request +{ editfriend_delete_user +.des +Sending a variable of this form removes the friend user from the user's friend list. It is not an error to delete an already non-existant friend. The value should just be 1. +} +{ editfriend_add_i_user +.des +To add a friend, send a variable of this form, where i is any unique integer. The value is the username of the friend to add. +} +{ editfriend_add_i_fg +.des +Sets the text color of the friend i being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #000000, black. +.optional +1 +} +{ editfriend_add_i_bg +.des +Sets the background color of the friend i being added. This value is a HTML-style hex-triplet, and must either be of the form #rrggbb or not sent at all. By default, the value assumed is #FFFFFF, white. +.optional +1 +} +{ editfriend_add_i_groupmask +.des +Sets this user's groupmask. Only use this in clients if you've very recently loaded the friend groups. If your client has been loaded on the end user's desktop for days and you haven't loaded friend groups since it started, they may be inaccurate if they've modified their friend groups through the website or another client. In general, don't use this key unless you know what you're doing. +.optional +1 +} +.response +{ friends_added +.des +The number of friends that were added with this transaction. The records returned indicate which friends were added, along with their names, named using a 1-based index. (from 1 .. friends_added) +} +{ friend_n_user +.des +The username of the nth friend that was added. +} +{ friend_n_name +.des +The name of the nth friend that was added. +} +} + +{ getevents +.des +Download parts of the user's journal. +.request +{ truncate +.des +An optional value that if greater than or equal to 4, truncates the length of the returned events (after being decoded) to the value specified. Entries less than or equal to this length are left untouched. Values greater than this length are truncated to the specified length minus 3, and then have "..." appended to them, bringing the total length back up to what you specified. This is good for populating list boxes where only the beginning of the entry is important, and you'll double-click it to bring up the full entry. +.optional +1 +} +{ prefersubject +.des +If this setting is set to true (1), then no subjects are returned, and the events are actually subjects if they exist, or if not, then they're the real events. This is useful when clients display history and need to give the user something to double-click. The subject is shorter and often more informative, so it'd be best to download only this. +} +{ noprops +.des +If this setting is set to true (1), then no meta-data properties are returned. +} +{ selecttype +.des +Determines how you want to specify what part of the journal to download. Valid values are day to download one entire day, lastn to get the most recent n entries (where n is specified in the howmany field), one to download just one specific entry, or syncitems to get some number of items (which the server decides) that have changed since a given time (specified in the lastsync parameter>). Not that because the server decides what items to send, you may or may not be getting everything that's changed. You should use the syncitems selecttype in conjuntions with the syncitems protocol mode. +} +{ lastsync +.des +For a selecttype of syncitems, the date (in "yyyy-mm-dd hh:mm:ss" format) that you want to get updates since. +} +{ year +.des +For a selecttype of day, the 4-digit year of events you want to retrieve. +} +{ month +.des +For a selecttype of day, the 1- or 2-digit month of events you want to retrieve. +} +{ day +.des +For a selecttype of day, the 1- or 2-digit day of the month of events you want to retrieve. +} +{ howmany +.des +For a selecttype of lastn, how many entries to get. Defaults to 20. Maximum is 50. +} +{ beforedate +.des +For a selecttype of lastn, you can optionally include this variable and restrict all entries returned to be before the date you specify, which must be of the form yyyy-mm-dd hh:mm:ss. +.optional +1 +} +{ itemid +.des +For a selecttype of one, the journal entry's unique ItemID for which you want to retrieve. Or, to retrieve the most recent entry, use the value -1. Using -1 has the added effect that the data is retrieved from the master database instead of a replicated slave. Clients with an "Edit last entry" feature might want to send -1, to make sure the data that comes back up is accurate, in case a slave database is a few seconds behind in replication. +} +{ lineendings +.des +The desired type of line-endings you'd like LiveJournal to return. Possible values are +unix (0x0A (\n)), +pc (0x0D0A (\r\n), the default), +mac (0x0D (\r)), +space (newlines become spaces), +or dots (newlines become " ... "). The PC format was chosen +as a default because it contains both Unix and Mac line endings in it, so if a client doesn't pick a line ending format, the worst case scenario is there are some ugly characters in the client's textbox beside the real newlines. +} +{ usejournal +.des +If getting the history of a shared journal, include this key and the username you wish to get the history of. By default, you load the history of "user" as specified above. +.optional +1 +} +.response +{ events_count +.des +The number of events being returned. The records returned are number from 1 to events_count. +} +{ events_n_itemid +.des +The unique integer ItemID of the nth item being returned. +} +{ events_n_eventtime +.des +The time the user posted (or said they posted, rather, since users can back-date posts) the nth item being returned. +} +{ events_n_event +.des +The nth event text itself. This value is first truncated if the truncate variable is set, and then it is URL-encoded (alphanumerics stay the same, weird symbols to %hh, and spaces to + signs, just like URLs or post request). This allows posts with line breaks to come back on one line. +} +{ events_n_security +.des +If this variable is not returned, then the security of the post is public, otherwise this value will be private or usemask. +} +{ events_n_allowmask +.des +If security is usemask then this is defined with the 32-bit unsigned int bit-mask of who is allowed to access this post. +} +{ events_n_subject +.des +The subject of the journal entry. This won't be returned if "prefersubjects" is set, instead the subjects will show up as the events. +} +{ events_n_poster +.des +If the poster of this event is different from the user value sent above, then this key will be included and will specify the username of the poster of this event. If this key is not present, then it is safe to assume that the poster of this event is none other than user. +} +{ events_n_anum +.des +The authentication number generated for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) +} +{ events_n_url +.des +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. +} +{ prop_count +.des +The number of event properties being returned (meta-data about journal entries). Note that this will not even be returned if you set noprops to true. +} +{ prop_n_itemid +.des +The ItemID of the journal entry that this meta-data is attached to. +} +{ prop_n_name +.des +The character string (alphanumerics and underscore only) of the meta-data property name. +} +{ prop_n_value +.des +The value of the nth meta-data property. +} +} + +{ editevent +.des +Edit or delete a user's past journal entry +.request +{ itemid +.des +The unique ItemID of the item being modified or deleted. +} +{ event +.des +The revised event/log text the user is submitting. Or, to delete an entry, just send no text at all. Carriage returns are okay (0x0A, 0x0A0D, or 0x0D0A), although 0x0D are removed internally to make everything into Unix-style line-endings (just \ns). Posts may also contain HTML, but be aware that the LiveJournal server converts newlines to HTML <BR>s when displaying them, so your client should not try to insert these itself. +} +{ lineendings +.des +Specifies the type of line-endings you're using. Possible values are unix (0x0A (\n)), pc (0x0D0A (\r\n)), or mac (0x0D (\r)). The default is not-Mac. Internally, LiveJournal stores all text as Unix-formatted text, and it does the conversion by removing all \r characters. If you're sending a multi-line event on Mac, you have to be sure and send a lineendings value of mac or your line endings will be removed. PC and Unix clients can ignore this setting, or you can send it. It may be used for something more in the future. +} +{ subject +.des +The subject for this post. Limited to 255 characters. No newlines. +} +{ security +.des +Specifies who can read this post. Valid values are public (default), private and usemask. When value is usemask, viewability is controlled by the allowmask. +.optional +1 +} +{ allowmask +.des +Relevant when security is usemask. A 32-bit unsigned integer representing which of the user's groups of friends are allowed to view this post. Turn bit 0 on to allow any defined friend to read it. Otherwise, turn bit 1-30 on for every friend group that should be allowed to read it. Bit 31 is reserved. +} +{ year +.des +If modifying only, the 4-digit year of the event (from the user's local timezone). +} +{ mon +.des +If modifying only, the 1- or 2-digit month of the event (from the user's local timezone). +} +{ day +.des +If modifying only, the 1- or 2-digit day of the month of the event (from the user's local timezone). +} +{ hour +.des +If modifying only, the 1- or 2-digit hour from 0 to 23 of the event (from the user's local timezone). +} +{ min +.des +If modifying only, the 1- or 2-digit minute of the event (from the user's local timezone). +} +{ prop_name +.des +Set an arbitrary (but restricted) meta-data property to this log item. If a key is sent, but the value is blank or zero (0), then the value of the given name is deleted from this item's property list. See [special[logprops]] for more information. +} +{ usejournal +.des +If editing a shared journal entry, include this key and the username you wish to edit the entry in. By default, you edit the entry as if it were in user "user"'s journal, as specified above. +.optional +1 +} +.response +{ itemid +.des +The unique number the server assigned to this post. +} +{ anum +.des +The authentication number for this entry. It can be used by the client to generate URLs, but that is not recommended. (See the returned 'url' element if you want to link to a post.) +} +{ url +.des +The permanent link address to this post. This is an opaque string--you should store it as is. While it will generally follow a predictable pattern, there is no guarantee of any particular format for these, and it may change in the future. +} +} + +{ syncitems +.des +Returns a list (or part of a list) of all the items (journal entries, to-do items, comments) that have been created or updated on LiveJournal since you last downloaded them. Note that the items themselves are not returned --- only the item type and the item number. After you get this you have to go fetch the items using another protocol mode. For journal entries (type "L"), use the getevents mode with a selecttype of "syncitems". +.request +{ lastsync +.des +The date you last downloaded synced, in "yyyy-mm-dd hh:mm:ss" format. Note: do not make this date up from the client's local computer... send the date from this mode's response of the newest item you have saved on disk. +.optional +1 +} +.response +{ sync_total +.des +The total number of items that have been updated since the time specified. +} +{ sync_count +.des +The number of items that are contained in this response (numbered started at 1). If sync_count is equal to sync_total, then you can stop your sync after you complete fetching every item in this response. +} +{ sync_n_item +.des +The nth item, in the form "Type-Number". Type can be one of "L" for log entries (journal entries), "C" for comments (not implemented), "T" for to-do items (not implemented), or many other things presumably. If your client doesn't know how to fetch an item of a certain type, just ignore them. A new version of your client could later see that it has never downloaded anything of type "T" and go back and fetch everything of that type from the beginning. +} +{ sync_n_action +.des +Either "create" or "update". This field isn't too useful, but you may want to make your client verbose and tell the user what it's doing. For example, "Downloading entry 5 of 17: Updated". +} +{ sync_n_time +.des +The server time (in the form "yyyy-mm-dd hh:mm:ss") that this creation or update took place. Remember in your local store the most recent for each item type ("L", "T", "C", etc...). This is what you send in subsequent requests in lastsync. +} +} + +{ checkfriends +.des +Mode that clients can use to poll the server to see if their friends list has been updated. This request +is extremely quick, and is the preferred way for users to see when their friends list is updated, rather +than pounding on reload in their browser, which is stressful on the serves. +.request +{ lastupdate +.des +The time that this mode request returned last time you called it. If this is the first time you've ever called it (since your client has been running), leave this blank. It's strongly recommended that you do not remember this value across invocations of your client, as it's very likely your friends will update since the client was running so the notification is pointless... the user probably read his/her friends page already before starting the client. +} +{ mask +.des +The friend group(s) in which the client is checking for new entries, represented as a 32-bit unsigned int. Turn on any combination of bits 1-30 to check for entries by friends in the respective friend groups. Turn on bit 0, or leave the mask off entirely, to check for entries by any friends. +.optional +1 +} +.response +{ lastupdate +.des +The time of the most recent post that one of the user's friends has made. Don't try to infer anything from this time. It's currently of the form "yyyy-mm-dd hh:mm:ss", in PST. However, in the future, it may not even be a date... just blindly store and return this value back later, ignoring its format. +} +{ new +.des +This is what you should use to determine if there are new entries. Its value is "1" if there is new stuff, or "0" if there isn't. A few people requested that this return the number of new entries, but that's a lot more resource intensive, and this protocol mode is supposed to be very quick and painless. In the future we may add a "new_count" response value that says how many new items there are. Note that once this values becomes "1" and you alert the user, stop polling! It'd be pointless to have the client hitting the server all night while the user slept. Once the user acknowleges the notifcation (double-clicks the system tray or panel applet or whatnot), then resume your polling. +} +{ interval +.des +How many seconds you must wait before polling the server again. If your client disobeys, this protocol will just return error messages saying "slow down, bad client!" instead of giving you the data you were trying to cheat to obtain. Note that this also means your client should have an option to disable polling for updates, since some users run multiple operating systems with multiple LiveJournal clients, and both would be fighting each other. +} +} + +{ getchallenge +.des +Generate a one-time, quick expiration challenge to be used in challenge/response authentication methods. +.response +{ auth_scheme +.des +You can ignore this for now. By default this is the highest version of our +authentication schemes, if in the future if we implement other auth schemes or change the default. +In that case we'd add a new capabilities exchange: your client could say, "I know c0 and c1", and +our server would then say, "Use c1, it's the best." +} +{ challenge +.des +An opaque cookie to generate a hashed response from. +} +{ expire_time +.des +The expiration time of the challenge, as measured in seconds since the Unix epoch. +} +{ server_time +.des +The server time when the challenge was generated, as measured in seconds since the Unix epoch. +} +} + +{ sessionexpire +.des +Expires one or more sessions that a user has active within the system. This can be used to log a user out of any browsers they are logged in from as well as to cancel any sessions created with the sessionexpire mode. +.request +{ expireall +.des +If present and true, will expire all of a user's sessions. +.optional +1 +} +{ expire_id_num +.des +If present and true, will expire the session with id num. You can get the id of a session from the third element of the session: ws:username:session_id:auth_code. +.optional +1 +} +} + +{ sessiongenerate +.des +Generates a session that can be used to setup a cookie for accessing the site with a user's privileges. +.request +{ expiration +.des +Sessions can either expire in a short amount of time or last for a long period of time. You can specify either "short" or "long" as the value of this parameter. +.optional +1 +} +{ ipfixed +.des +If specified and true, this will cause the server to generate a session that is only valid from the IP address the sessiongenerate request was sent from. If you leave out this value, it will default to allowing any IP address to use this session information. +.optional +1 +} +.response +{ ljsession +.des +This part of the response contains the actual session data. If you use the complete contents of this element as a cookie named "ljsession" then you will be able to access the site using the privileges of the user you authenticated as. +} +} diff --git a/livejournal/htdocs/pubkey.bml b/livejournal/htdocs/pubkey.bml new file mode 100755 index 0000000..98632a2 --- /dev/null +++ b/livejournal/htdocs/pubkey.bml @@ -0,0 +1,55 @@ + +head<= + + + +<=head +body<= +{public_key}) { + $ret .= ' LJ::ljuser($u->{user})}) . ' p?>'; + $ret .= "
    \n";
    +        $ret .= LJ::ehtml($u->{public_key});
    +        $ret .= "\n
    "; + } else { + $ret .= ' LJ::ljuser($u->{user})}) . ' p?>'; + } + $ret .= "
    "; + $ret .= " 'href="http://www.pgp.com/"', + aoptsgpg => 'href="http://www.gnupg.org/"', + }); + $ret .= " p?> 'href="/manage/pubkey.bml"', + }); + $ret .= " p?>"; + return $ret; + +} _code?> +<=body +page?> diff --git a/livejournal/htdocs/random.bml b/livejournal/htdocs/random.bml new file mode 100755 index 0000000..ba806bd --- /dev/null +++ b/livejournal/htdocs/random.bml @@ -0,0 +1,20 @@ +selectrow_array("SELECT statval FROM stats ". + "WHERE statcat='userinfo' AND statkey='randomcount'"); + if ($max) { + my $rand = int(rand($max))+1; + my $user = $dbr->selectrow_array("SELECT u.user FROM randomuserset r, useridmap u ". + "WHERE r.userid=u.userid AND r.rid=$rand"); + return BML::redirect("$LJ::SITEROOT/users/$user/") if $user; + } + + # something went wrong, redirect them back to top of site... *shrug* + return BML::redirect("$LJ::SITEROOT/"); +} +_code?>1 +_info?> +link: htdocs/users + _c?> diff --git a/livejournal/htdocs/register.bml b/livejournal/htdocs/register.bml new file mode 100755 index 0000000..4525969 --- /dev/null +++ b/livejournal/htdocs/register.bml @@ -0,0 +1,126 @@ +1 +_info?> + +body<= + +underage; + + my $foruser = $GET{foruser}; + my $foru; + if ($foruser) { + $foru = LJ::load_user($foruser) + or return ""; + return "" + if $foru && !(LJ::check_priv($remote, "siteadmin", "users") || + LJ::check_priv($remote, "siteadmin", "*")); + } + + my $show_validate = sub { + my $user = shift; + return "$user->{'email'}, 'user'=>LJ::ljuser($user)}) . " p?>" . + "
    " . + LJ::html_hidden('authas', $user->{'user'}) . + LJ::html_submit("action:send", "$ML{'.ask.button'}") . + "
    "; + }; + if ($POST{'action:send'} || $foru) { + my $u = $foru ? $foru : LJ::get_authas_user($POST{'authas'}); + return "" unless $u; + my $aa = {}; + $aa = LJ::register_authaction($u->{'userid'}, + "validateemail", $u->{'email'}); + LJ::send_mail({ + 'to' => $u->{'email'}, + 'bcc' => $foru ? $remote->{'email'} : undef, + 'from' => $LJ::ADMIN_EMAIL, + 'charset' => 'utf-8', + 'subject' => $ML{'.email.subject'}, + 'body' => BML::ml('.email.body', + { 'sitename' => $LJ::SITENAME, + 'sitelink' => $LJ::SITEROOT, + 'conflink' => "$LJ::SITEROOT/confirm/$aa->{'aaid'}.$aa->{'authcode'}" }), + }); + $ret .= "$u->{'email'}}) . " p?>"; + + } elsif ($qs =~ /^(\d+)[;\.](.+)$/) { + my ($aaid, $auth) = ($1, $2); + my $aa = LJ::is_valid_authaction($aaid, $auth); + if (!$aa) { return ""; } + my $u = LJ::load_userid($aa->{'userid'}); + + # verify their email hasn't subsequently changed + unless ($u->{email} eq $aa->{arg1}) { + return " "href='$LJ::SITEROOT/register.bml'" }) . + " p?>"; + } + + LJ::update_user($u, { status => 'A' }); + LJ::run_hooks("emailconfirmed", $u); + if ($u->{'status'} eq "T") { + $ret .= ""; + } else { + $ret .= "LJ::ljuser($u)}) . " p?>"; + $ret .= "
      "; + $ret .= "
    • $ML{'.new.login'}
    • "; + $ret .= "
    • $ML{'.new.editinfo'}
    • "; + $ret .= "
    • $ML{'.new.modify'}
    • "; + $ret .= "
    • $ML{'.new.update'}
    • "; + $ret .= "
    "; + } + } else { + return LJ::bad_input("You must be logged in to view this page.") unless $remote; + my @authas = LJ::get_authas_list($remote); + my @list; + foreach (@authas) { + my $user = LJ::load_user($_); + push @list, $_; + if ($user->{'status'} eq "A") { + push @list, $_; + } else { + push @list, BML::ml('.asterisk.name', {'journal'=>$_}); + } + } + $ret .= ""; + $ret .= "
    \n"; + $ret .= 'Select user:' . " "; + $ret .= LJ::html_select({ 'name' => 'authas' }, @list) . " "; + $ret .= LJ::html_submit(undef, 'Validate'); + $ret .= ' ' . $ML{'.asterisk.comment'}; + $ret .= "
    \n\n"; + if ($GET{'authas'}) { + my $user = LJ::get_authas_user($GET{'authas'}); + return "" unless $user; + if ($user->{'status'} eq "A") { + $ret .= "LJ::ljuser($user)}) . " p?>"; + } else { + $ret .= $show_validate->($user); + } + } else { + $ret .= $show_validate->($remote) unless $remote->{'status'} eq "A"; + } + } + + return $ret; + +_code?> + +<=body +page?> +link: htdocs/login.bml, htdocs/editinfo.bml +link: htdocs/modify.bml, htdocs/update.bml + _c?> diff --git a/livejournal/htdocs/robots.txt b/livejournal/htdocs/robots.txt new file mode 100755 index 0000000..2a1ca1f --- /dev/null +++ b/livejournal/htdocs/robots.txt @@ -0,0 +1,13 @@ +User-Agent: * +Disallow: /directory.bml + +# +# Blocked journals aren't listed here because robots.txt files +# can't be above 50k or so, depending on the spider. +# +# Instead, blocked journals have HTML inserted in them which +# should prevent behaved spiders from indexing it. +# +# Note that http://username.livejournal.com journals have an +# autogenerated robots.txt, since it can be small. +# diff --git a/livejournal/htdocs/rte/blank.html b/livejournal/htdocs/rte/blank.html new file mode 100755 index 0000000..2552c4d --- /dev/null +++ b/livejournal/htdocs/rte/blank.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/livejournal/htdocs/rte/palette.html b/livejournal/htdocs/rte/palette.html new file mode 100755 index 0000000..fa8cefa --- /dev/null +++ b/livejournal/htdocs/rte/palette.html @@ -0,0 +1,126 @@ + + + + + Text Color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + diff --git a/livejournal/htdocs/stats.bml b/livejournal/htdocs/stats.bml new file mode 100755 index 0000000..330640b --- /dev/null +++ b/livejournal/htdocs/stats.bml @@ -0,0 +1,219 @@ +Statistics +body<= + + Statistics h1?> +here. +p?> + + +prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('userinfo', 'client', 'age', 'gender', 'account', 'size')"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'}; + } + + unless (%stat) { + return "ljmaint.pl genstats
    , or ideally, put it in cron to run nightly. p?>"; + } + + $sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='country' AND s.statcat='country' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{'country'}->{$_->{'item'}} = $_->{'statval'}; + } + + $sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='state' AND s.statcat='stateus' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $stat{'state'}->{$_->{'item'}} = $_->{'statval'}; + } + + my $total = $stat{'userinfo'}->{'total'}+0; + my $usedever = $stat{'userinfo'}->{'updated'}+0; + my $used30 = $stat{'userinfo'}->{'updated_last30'}+0; + my $used7 = $stat{'userinfo'}->{'updated_last7'}+0; + my $usedlastday = $stat{'userinfo'}->{'updated_last1'}+0; + my $allow_getljnews = $stat{'userinfo'}->{'allow_getljnews'}+0; + my $active = $stat{'size'}->{'accounts_active'}+0; + + my $ret = ""; + $ret .= "\n"; + $ret .= "
      "; + $ret .= "
    • Total accounts: $total
    • \n"; + $ret .= "
    • ... active in some way: $active
    • \n" if $active; + $ret .= "
    • ... that have ever updated: $usedever
    • \n"; + $ret .= "
    • ... updating in last 30 days: $used30
    • \n"; + $ret .= "
    • ... updating in last 7 days: $used7
    • \n"; + $ret .= "
    • ... updating in past 24 hours: $usedlastday
    • \n"; + $ret .= "
    \n"; + + $ret .= "\n"; + $ret .= "
      "; + { + my $male = $stat{'gender'}->{'M'}+0; + my $female = $stat{'gender'}->{'F'}+0; + my $tot = $male+$female; + $tot ||= 1; + $ret .= "
    • Male: $male (" . sprintf("%0.1f", $male*100/($tot||1)) . "%)
    • "; + $ret .= "
    • Female: $female (" . sprintf("%0.1f", $female*100/($tot||1)) . "%)
    • "; + } + $ret .= "
    • Unspecified: " . ($stat{'gender'}->{'U'}+0) . "
    • "; + $ret .= "
    \n"; + + LJ::run_hook('statspage', { + stat => \%stat, + ret => \$ret, + }); + + unless ($LJ::DISABLED{'stats-recentupdates'}) + { + $ret .= "\n"; + $ret .= "
      "; + $sth = $dbr->prepare("SELECT u.user, u.name, uu.timeupdate FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 30 DAY) ORDER BY uu.timeupdate DESC LIMIT 10"); + $sth->execute; + my $ct; + while (my ($iuser, $iname, $itime) = $sth->fetchrow_array) { + $ret .= "
    • , $itime
    • \n"; + $ct++; + } + $ret .= "
    • stat not available
    • " unless $ct; + $ret .= "
    \n"; + } + + unless ($LJ::DISABLED{'stats-newjournals'}) + { + $ret .= "\n"; + $ret .= "
      "; + $sth = $dbr->prepare("SELECT u.user, u.name, uu.timeupdate FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate IS NOT NULL ORDER BY uu.timecreate DESC LIMIT 10"); + $sth->execute; + my $ct; + while (my ($iuser, $iname, $itime) = $sth->fetchrow_array) { + $ret .= "
    • , $itime
    • \n"; + $ct++; + } + $ret .= "
    • stat not available
    • " unless $ct; + $ret .= "
    \n"; + } + + $ret .= "\n"; + { + $ret .= "
      "; + my $ct; + foreach my $key (sort { $stat{'country'}->{$b} <=> $stat{'country'}->{$a} } + keys %{$stat{'country'}}) + { + $ret .= "
    • $key - $stat{'country'}->{$key}
    • \n"; + $ct++; + } + $ret .= "
    • stat not available
    • " unless $ct; + $ret .= "
    \n"; + } + + { + $ret .= "The following are the 15 most popular U.S. states $LJ::SITENAMESHORT is used in:
      "; + my $ct; + foreach my $key (sort { $stat{'state'}->{$b} <=> $stat{'state'}->{$a} } keys %{$stat{'state'}}) + { + $ret .= "
    • $key - $stat{'state'}->{$key}
    • \n"; + $ct++; + } + $ret .= "
    • stat not available
    • " unless $ct; + $ret .= "
    \n"; + } + + # ages + my %age = (); + my $maxage = 1; + foreach my $key (keys %{$stat{'age'}}) { + $age{$key} = $stat{'age'}->{$key}; + if ($stat{'age'}->{$key} > $maxage) { $maxage = $stat{'age'}->{$key}; } + } + my @ages = grep { $_ >= 13 && $_ <= 55 } sort { $a <=> $b } sort keys %age; + if (@ages) { + $ret .= "\n"; + $ret .= "\n"; + my $lastage = 0; + foreach my $age (@ages) { + my $width = int(400 * $age{$age}/$maxage); + $ret .= "\n"; + $lastage = $_; + } + $ret .= "
    $age$age{$age}
    \n"; + } + + # clients (if enabled) + unless ($LJ::DISABLED{'clientversionlog'}) { + + ### sum up clients over different versions + foreach my $c (keys %{$stat{'client'}}) { + next unless ($c =~ /^(.+?)\//); + $stat{'clientname'}->{$1} += $stat{'client'}->{$c}; + } + + my $out; + foreach my $cn (sort { $stat{'clientname'}->{$b} <=> $stat{'clientname'}->{$a} } + keys %{$stat{'clientname'}}) + { + last unless $stat{'clientname'}->{$cn} >= 50; + $out .= "$stat{'clientname'}->{$cn}". + "" . LJ::ehtml($cn) . "
    \n"; + $out .= "\n"; + foreach my $c (sort grep { /^\Q$cn\E\// } keys %{$stat{'client'}}) { + my $count = $stat{'client'}->{$c}; + $c =~ s/^\Q$cn\E\///; + $out .= LJ::ehtml($c) . " ($count), "; + } + chop $ret; chop $ret; # remove trailing ", " + $out .= "\n"; + $out .= "\n"; + } + + if ($out) { + $ret .= "\n"; + $ret .= "\n"; + $ret .= $out; + $ret .= "
    \n"; + } + } + + + # return early, since the graphs below are pretty much broken now + # with index changes. FIXME: make alternate means to generate stats + return $ret; + + ### graphs! + $ret .= ""; + + $ret .= ""; + $ret .= "

    "; + + $ret .= ""; + $ret .= "

    "; + + $ret .= ""; + $ret .= "

    "; + + return $ret; + +_code?> + +<=body +page?> +link: htdocs/stats/, htdocs/support/faqbrowse.bml +img: htdocs/img/bluedot.gif, htdocs/stats/postsbyday.png, htdocs/stats/postsbyweek.png, htdocs/stats/newbyday.png + _c?> diff --git a/livejournal/htdocs/stats/.placeholder b/livejournal/htdocs/stats/.placeholder new file mode 100755 index 0000000..2895e7a --- /dev/null +++ b/livejournal/htdocs/stats/.placeholder @@ -0,0 +1 @@ +This file exists to make sure the directory is created. diff --git a/livejournal/htdocs/stats/index.bml b/livejournal/htdocs/stats/index.bml new file mode 100755 index 0000000..7ccac49 --- /dev/null +++ b/livejournal/htdocs/stats/index.bml @@ -0,0 +1,4 @@ + + diff --git a/livejournal/htdocs/styles/browse/index.html b/livejournal/htdocs/styles/browse/index.html new file mode 100755 index 0000000..b3c53f7 --- /dev/null +++ b/livejournal/htdocs/styles/browse/index.html @@ -0,0 +1,16 @@ + + + Style Browser + + + + + + + + + + + diff --git a/livejournal/htdocs/styles/browse/instructions.bml b/livejournal/htdocs/styles/browse/instructions.bml new file mode 100755 index 0000000..e57fa50 --- /dev/null +++ b/livejournal/htdocs/styles/browse/instructions.bml @@ -0,0 +1,12 @@ + + +Style Browser + + +

    Style Browser

    +

    Enter a username in the box on the left and click "Preview" to see a list of that users' +public styles. In the list, click on the style name to view what the style looks like, or +click the dash to view style information.

    + + diff --git a/livejournal/htdocs/styles/browse/links.bml b/livejournal/htdocs/styles/browse/links.bml new file mode 100755 index 0000000..06caea7 --- /dev/null +++ b/livejournal/htdocs/styles/browse/links.bml @@ -0,0 +1,55 @@ + +{'user'} : $user; + my $styu = LJ::load_user($user); + my $styles; + if ($user eq 'system') { + $styles = LJ::S1::get_public_styles(); + } else { + $styles = LJ::S1::get_user_styles($user); + } + + my $admin = $remote && + (LJ::check_priv($remote, 'canview', 'styles') || + LJ::check_priv($remote, 'canview', '*')); + + my ($dday,$dmon,$dyear) = (localtime(time))[3..5]; + $dyear+=1900; $dmon++; + my %extra = ( 'day' => "&month=$dmon&day=$dday&year=$dyear" ); + + my $ret = "Styles for " . LJ::ljuser($user) . ":

    "; + + my $last; + STY: + foreach my $sty (sort { $a->{'type'} cmp $b->{'type'} || $a->{'styledes'} cmp $b->{'styledes'} } + values %$styles) { + + next STY unless $sty->{is_public} eq 'Y' || # public is always visible + LJ::u_equals($remote, $styu) || # yours are visible to you + LJ::can_manage($remote, $styu) ||# you can view things you manage + $admin; # you have appropriate canview + + if ($last ne $LJ::viewinfo{$sty->{'type'}}->{'des'}) { + $last = $LJ::viewinfo{$sty->{'type'}}->{'des'}; + $ret .= "$last
    \n"; + } + + $ret .= "  [info] "; + $ret .= " +link: htdocs/styles/browse/styleinfo.bml, htdocs/customview.cgi + _c?> diff --git a/livejournal/htdocs/styles/browse/start.bml b/livejournal/htdocs/styles/browse/start.bml new file mode 100755 index 0000000..734b653 --- /dev/null +++ b/livejournal/htdocs/styles/browse/start.bml @@ -0,0 +1,9 @@ +
    +View styles of user: + +
    + + +
    +form: htdocs/styles/browse/links.bml + _c?> diff --git a/livejournal/htdocs/styles/browse/styleinfo.bml b/livejournal/htdocs/styles/browse/styleinfo.bml new file mode 100755 index 0000000..b73ec1c --- /dev/null +++ b/livejournal/htdocs/styles/browse/styleinfo.bml @@ -0,0 +1,45 @@ +{user}) if $sty; # if $sty so we don't auto-vivify! + return "Style $styleid does not exist or is not public." + unless $sty && + ($sty->{is_public} eq 'Y' || # straight up public + LJ::u_equals($remote, $styu) || # is this your account? + LJ::can_manage($remote, $styu) || # how about your community? + LJ::check_priv($remote, 'canview', 'styles') || # can you see private styles? + LJ::check_priv($remote, 'canview', '*')); # or maybe you can see everything + + my $ret = ""; + $ret .= "

    Style Info

    \n"; + + $ret .= "
    \n"; + $ret .= "
    Author
    {'user'}\">$sty->{'user'}\n"; + $ret .= "
    Style Description
    $sty->{'styledes'}
    \n"; + $ret .= "
    Last Updated
    $sty->{'lastupdate'}
    \n"; + $ret .= "
    View Type
    $sty->{'type'}
    \n"; + $ret .= "
    Public?
    $sty->{'is_public'}
    \n"; + $ret .= "
    Embeddable?
    $sty->{'is_embedded'}
    \n"; + $ret .= "
    Color-free? (only uses color themes, not fixed colors)
    $sty->{'is_colorfree'}
    \n"; + $ret .= "
    "; + + my %vars; + LJ::parse_vars(\$sty->{'formatdata'}, \%vars); + + $ret .= "

    Style Variables

    \n"; + + foreach my $v (sort keys %vars) { + $ret .= "

    $v

    \n"; + my $val = LJ::ehtml($vars{$v}); + $val =~ s/\n/
    \n/g; + $ret .= $val; + } + + return $ret; + +_code?> +link: htdocs/userinfo.bml + _c?> diff --git a/livejournal/htdocs/styles/create.bml b/livejournal/htdocs/styles/create.bml new file mode 100755 index 0000000..cf949b5 --- /dev/null +++ b/livejournal/htdocs/styles/create.bml @@ -0,0 +1,64 @@ + +body<= + +{'user'}; + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ""; + + # no authentication needs to be done on this page, it's just a form anyway + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + $ret .= "
    \n"; + + # main form + $ret .= "\n"; + $ret .= ""; + + $ret .= "\n"; + $ret .= "\n"; + + my $pubstyles = LJ::S1::get_public_styles(); + my %styles; + push @{$styles{$_->{'type'}}}, $_ foreach values %$pubstyles; + + foreach my $view (@LJ::views) { + $ret .= "

    " . LJ::html_check({ 'type' => 'radio', 'name' => 'type', 'id' => "type-$view", 'value' => $view }); + $ret .= "

    \n"; + $ret .= "
    $ML{'.choosebase'}
    \n"; + $ret .= LJ::html_select({ 'name' => "base_$view" }, + '', $ML{'.noneorother'}, + map { $_->{'styleid'}, $_->{'styledes'} } + sort { $a->{'styledes'} cmp $b->{'styledes'} } @{$styles{$view}} ); + $ret .= "
    $ML{'.enterstyleid'} "; + $ret .= LJ::html_text({ 'name' => "basenum_$view", 'size' => '5', 'maxlength' => '10' }) . "
    \n"; + } + + $ret .= "\n"; + $ret .= "
    \n"; + + return $ret; +} +_code?> + +<=body +page?> +link: htdocs/developer/embedding.bml, htdocs/developer/views.bml +link: htdocs/paidaccounts/index.bml +post: htdocs/styles/create_do.bml + _c?> diff --git a/livejournal/htdocs/styles/create_do.bml b/livejournal/htdocs/styles/create_do.bml new file mode 100755 index 0000000..dbd1680 --- /dev/null +++ b/livejournal/htdocs/styles/create_do.bml @@ -0,0 +1,101 @@ + +body<= + +" + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.authinvalid'}) + unless $u; + + unless (LJ::get_cap($u, "styles")) { + return LJ::bad_input($ML{'.error.accounttype'}); + } + + # error check submission + return LJ::bad_input($ML{'.error.invalidview'}) + unless $POST{'type'} && defined $LJ::viewinfo{$POST{'type'}}; + + my $view = $POST{'type'}; + my $base = ""; + my $baseid = $POST{"base_$view"} || $POST{"basenum_$view"}; + + if ($baseid) { + my $rec = LJ::S1::get_style($baseid); + + return LJ::bad_input(BML::ml('.error.stylenotfound',{ 'baseid' => $baseid, })) + unless $rec && $rec->{'type'} eq $view; + + return LJ::bad_input(BML::ml('.error.stylenotpublic',{ 'baseid' => $baseid, })) + unless $rec->{'is_public'} eq "Y" || $rec->{'user'} eq $u->{'user'}; + + # they're allowed to base on this style + $base = $rec->{'formatdata'}; + } + + ### start of output + + my $ret = ""; + my $des = "$u->{'user'}-$view-new"; + + # let's see if they accidentally double-clicked: + my $double_clicked = 0; + my $new_id = 0; + my $oldstyle = LJ::S1::check_dup_style($u, $view, $des); + + # closure to show edit form + my $editform = sub { + my $getextra = "?authas=$authas" if $u->{'user'} ne $remote->{'user'}; + return "
    \n" . + LJ::html_hidden('mode', 'editstyle', 'styleid', $_[0]) . "\n" . + LJ::html_submit(undef, $ML{'.editstyle'}) . "
    \n"; + }; + + if ($oldstyle) { + if ($oldstyle->{'formatdata'} eq $base) { + # the user double-clicked + $double_clicked = 1; + $new_id = $oldstyle->{'styleid'}; + + } else { + $ret .= "" . + " $des, 'view' => $view, }) . " p?>"; + + $ret .= $editform->($oldstyle->{'styleid'}); + return $ret; + } + } + + unless ($double_clicked) { + $new_id = LJ::S1::create_style($u, + { 'styledes' => $des, + 'type' => $view, + 'formatdata' => $base }); + return "" + unless defined $new_id; + } + + $ret .= " $des, }) . " p?>\n"; + + $ret .= $editform->($new_id); + + return $ret; +} +_code?> +<=body +page?> +post: htdocs/styles/edit_do.bml + _c?> diff --git a/livejournal/htdocs/styles/edit.bml b/livejournal/htdocs/styles/edit.bml new file mode 100755 index 0000000..d7f0e71 --- /dev/null +++ b/livejournal/htdocs/styles/edit.bml @@ -0,0 +1,66 @@ +Edit Style + +body<= +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user.") + unless $u; + + # authenticated + my $ret; + + # user switcher + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }); + $ret .= "
    \n\n"; + + my $getextra = $u->{'user'} ne $remote->{'user'} ? "?authas=$authas" : ""; + + $ret .= "\n"; + $ret .= "create a style, you can edit it here. "; + $ret .= "To read more about the style system, go here. p?>\n\n"; + $ret .= "\n"; + $ret .= "
    "; + $ret .= ""; + + my $styles = LJ::S1::get_user_styles($u); + + my @list = map { $_->{'styleid'}, "$_->{'type'}($_->{'styleid'}): $_->{'styledes'}" } + sort { $a->{'styledes'} cmp $b->{'styledes'} } values %$styles; + @list = @list ? @list : ('', 'no styles'); + + $ret .= LJ::html_select({ 'name' => 'styleid', 'size' => '10', 'style' => 'width: 100%;' }, + @list) . "
    \n"; + + $ret .= "
    Action: "; + $ret .= LJ::html_select({ 'name' => 'ide' }, + 'v2', 'Edit in Easy Mode', + 'v1', 'Edit in Raw Mode (Old)', + 'delete', 'Delete this style!' ) . "
    \n"; + + $ret .= "
    "; + $ret .= LJ::html_submit(undef, "Proceed", { 'disabled' => ! @list }); + $ret .= "
    standout?>\n"; + $ret .= "
    \n"; + + return $ret; + +} +_code?> +<=body +page?> +link: htdocs/styles/create.bml, htdocs/developer/styles.bml +post: htdocs/styles/edit_do.bml + _c?> diff --git a/livejournal/htdocs/styles/edit_do.bml b/livejournal/htdocs/styles/edit_do.bml new file mode 100755 index 0000000..0c543c6 --- /dev/null +++ b/livejournal/htdocs/styles/edit_do.bml @@ -0,0 +1,316 @@ +Edit Style +body<= + +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input("You could not be authenticated as the specified user") + unless $u; + + # check styles cap + return LJ::bad_input("Your account type doesn't permit you to modify styles.") + unless LJ::get_cap($u, "styles"); + + # get a style object + my $styleid = $POST{'styleid'}+0; + my $style = LJ::S1::get_style($styleid); + return LJ::bad_input("The requested style does not exist.") + unless $style; + + # some static data + my @style_opts = ( + { 'code' => "is_public", + 'title' => 'Public?', + 'des' => "Mark this style public if you want other people to be able to use it or copy it." }, + { 'code' => "is_embedded", + 'title' => 'Embedded?', + 'des' => "Is this style designed to be embedded in somebody's homepage? Check if so, otherwise it's a full page style." }, + { 'code' => "is_colorfree", + 'title' => 'Color Free?', + 'des' => "A style is color-free if it does not contain any hard-coded color tags, but only uses the generic color codes listed in the table below." }, + ); + my @style_transforms = ( + { 'trans' => 'lc', + 'des' => "Lower case." }, + { 'trans' => 'uc', + 'des' => "Upper case." }, + { 'trans' => 'ue', + 'des' => "URL-Encode. Turn spaces to +, and all weird characters to %hh, the hex representation. This is useful for building data files to be used in Flash-4 movies." }, + { 'trans' => 'xe', + 'des' => "XML-Encode. Makes value acceptable for use in an XML attribute or element. Escapes ampersands, angle brackets, and both types of quotes. Does not however, escape ]]>, so don't use CDATA elements." }, + { 'trans' => 'color', + 'des' => "A weird transform that handles color codes. See the color code table." }, + { 'trans' => 'cons', + 'des' => "Access site constants. Currently supported are 'siteroot', 'sitename', and 'img' (the image root). Example use: %%cons:img%%/icon_protected.gif" }, + { 'trans' => 'ljuser', + 'des' => "Transform the variable as if it were surrounded by <lj user=%%variable%%>. ex: %%ljuser:username%%" }, + { 'trans' => 'ljcomm', + 'des' => "Transform the variable as if it were surrounded by <lj comm=%%variable%%>. ex: %%ljcomm:username%%" }, + { 'trans' => 'userurl', + 'des' => 'Takes in a username and transforms it into a link to their journal.' }, + ); + + # construct ide and mode variables + my $ide = $POST{'ide'}; + my $mode = $POST{'mode'} || 'editstyle'; + if ($mode eq 'editstyle') { + if ($ide eq 'delete') { + $mode = 'delete'; + } else { + $ide = $ide eq 'v1' ? 'v1' : 'v2'; + $mode = 'editstyle'; + } + } + + ### start of output + + my $ret = ""; + + # pass authas arguments in forms if necessary + my $getextra = "?authas=$authas" if $authas ne $remote->{'user'}; + + # delete confirmation + if ($mode eq "delete") { + $ret .= "$style->{'styledes'}
    ? If so, press the button below. This will temporarily break your journal if you're using this style, until you select a different style to use. p?>"; + + $ret .= "
    "; + $ret .= LJ::html_hidden("mode", "delete_confirm", "styleid", $styleid); + $ret .= "

    " . LJ::html_submit(undef, "Yes, delete it!") . "

    \n"; + return $ret; + } + + # process delete + if ($mode eq "delete_confirm") { + + LJ::S1::delete_style($styleid); + return "here. p?>"; + } + + # editing a style + if ($mode eq "editstyle") { + $ret .= "\n"; + $ret .= "
    "; + $ret .= LJ::html_hidden("mode", "savechanges", "styleid", $styleid, "ide", $ide); + + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + + $ret .= "\n"; + + $ret .= "
    Style View Type:$LJ::viewinfo{$style->{'type'}}->{'des'} -- $style->{'type'}
    Style ID Number:$style->{'styleid'}"; + + my $extravars = "&nocache=1" if $style->{'opt_cache'} eq "Y"; + if ($style->{'type'} eq 'day') { + my ($curmday, $curmon, $curyear) = (localtime(time))[3..5]; + $extravars .= sprintf("&day=%02d&month=%02d&year=%04d", + $curmday, $curmon+1, $curyear+1900); + } + $ret .= " {'user'}&styleid=$styleid$extravars\">[Preview Current Style] (must save below to see your changes, keep this window open and reload it whenever you save)"; + $ret .= "
    Style Description:"; + $ret .= LJ::html_text({ 'name' => 'styledes', 'value' => $style->{'styledes'}, + 'size' => '50', 'maxlength' => '50' }); + $ret .= "
    Style Options:\n"; + foreach my $opt (@style_opts) { + $ret .= ""; + } + $ret .= "
    "; + $ret .= LJ::html_check({ 'type' => 'check','name' => $opt->{'code'}, 'id' => $opt->{'code'}, + 'selected' => $style->{$opt->{'code'}} eq 'Y' }); + + $ret .= "
    $opt->{'des'}
    \n"; + + # color code instructions + $ret .= "The following color codes can be used in any variable below that contains HTML: p?>"; + + $ret .= "

    \n"; + foreach my $col (@LJ::S1::themecoltypes) { + $ret .= "\n"; + } + $ret .= "
    CodeDescription
    %%color:$col->[0]%%$col->[1]

    \n"; + + # transform instructions + $ret .= "%%monlong%%
    (March, April, May, etc...) but you don't like that the default has those upper case initial letters. You can apply the lc (lowercase) transform to it: %%lc:monlong%%. Transform are applied in order from the right to the left, so if you went %%a:b:c:d:property%%, d would be applied first. Here are a list of the supported transforms: p?>"; + + $ret .= "

    \n"; + foreach (@style_transforms) { + $ret .= "\n"; + } + $ret .= "
    TransformDescription
    $_->{'trans'}$_->{'des'}

    \n"; + + ### customizable vars section + + # load variables from file + my @vars; + LJ::load_objects_from_file("vars.dat", \@vars); + + # build hash of relevant variables + my %var; + foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars) { + next unless ($v->{'props'}->{'scope'} =~ /\b$style->{'type'}\b/); + $var{$v->{'name'}} = $v; + } + + # ide version 2 section + if ($ide eq "v2") { + + # closure to make variable edit fields + my $make_edit_fields = sub { + my ($self, $vars, $marked, @fields) = @_; + foreach my $f (@fields) { + next if ($marked->{$f}++); + my $prop = $vars->{$f}->{'props'}; + $self->($self, $vars, $marked, split(/\s*,\s*/, $prop->{'deps'})); + my $des = $prop->{'des'}; + $des =~ s/\[var\[(\S+?)\]\]/$1<\/a>/g; + $des =~ s/\[view\[(\S+?)\]\]/$1/g; + $des =~ s/%%\S+?%%/$&<\/tt>/g; + + $ret .= "

    $f
    $des

    \n"; + + if (defined $prop->{'props'}) { + $ret .= "

    \n"; + foreach my $p (@{$prop->{'props'}}) { + $p->{'props'}->{'des'} =~ s/\[var\[(\S+?)\]\]/$1<\/a>/g; + $p->{'props'}->{'des'} =~ s/\[view\[(\S+?)\]\]/$1/g; + $p->{'props'}->{'des'} =~ s/%%\S+?%%/$&<\/tt>/g; + $ret .= "\n"; + $ret .= "\n"; + } + $ret .= "
    $p->{'name'}$p->{'props'}->{'des'} "; + if ($p->{'props'}->{'min'} > 0) { + $ret .= "[required]"; + } + $ret .= "

    \n"; + } + + my $editrows = $prop->{'editrows'} || 5; + my $editcols = $prop->{'editcols'} || 70; + + $ret .= "

    "; + if ($vars->{$f}->{'props'}->{'override'} eq "only") { + $ret .= "Override only. Only end-users may override this. You cannot define it in a style."; + } else { + my %stylevar = (); + LJ::parse_vars(\$style->{'formatdata'}, \%stylevar); + + if ($editrows == 1) { + $ret .= LJ::html_text({ 'name' => "var:$f", 'value' => $stylevar{$f}, + 'size' => $editcols, 'maxlength' => '255' }); + } else { + $ret .= LJ::html_textarea({ 'name' => "var:$f", 'value' => $stylevar{$f}, + 'wrap' => 'soft', 'rows' => $editrows, 'cols' => $editcols, + 'style' => 'width: 100%;' }); + } + } + $ret .= "

    "; + $ret .= "\n"; + } + }; # end closure + + # display edit form + $ret .= ""; + my %mark = (); + $make_edit_fields->($make_edit_fields, \%var, \%mark, uc("$style->{'type'}_PAGE"), keys %var); + } + + # ide version 1 section + if ($ide eq "v1") { + + # show a big textarea for them to use + $ret .= "

    Style Variables: (reference information)

    \n"; + $ret .= LJ::html_textarea({ 'name' => 'formatdata', 'value' => $style->{'formatdata'}, + 'rows' => '30', 'cols' => '80', 'wrap' => 'off', + 'style' => 'width: 100%;' }) . "\n"; + } + + # save button + $ret .= "

    " . LJ::html_submit(undef, 'Save Style') . "

    \n"; + + $ret .= "
    "; + + # convenience links at bottom + if ($ide eq 'v2') { + $ret .= "
      "; + foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars) { + next unless ($v->{'props'}->{'scope'} =~ /\b$style->{'type'}\b/); + $ret .= "
    • {'name'}\">$v->{'name'}"; + } + $ret .= "
    "; + } + + return $ret; + } + + # save changes from a previous edit form + if ($mode eq "savechanges") { + + my $formatdata; + + # process form from ide v1 + if ($ide eq "v1") { + $POST{'formatdata'} =~ s/\r//; # carriage returns shouldn't be necessary + $formatdata = $POST{'formatdata'}; + + # process form from ide v2 + } elsif ($ide eq "v2") { + $formatdata = ""; + foreach (grep { /^var:.+/ } keys %POST) { + /^var:(.+)$/; + my ($key, $var) = ($&, $1); + $POST{$key} =~ s/\r//; # carriage returns shouldn't be necessary + if ($POST{$key} =~ /\n/) { + $formatdata .= "$var<=\n$POST{$key}\n<=$var\n\n"; + } else { + $formatdata .= "$var=>$POST{$key}\n\n"; + } + } + } + + # update style + LJ::S1::update_style($styleid, + { 'formatdata' => $formatdata, + 'styledes' => $POST{'styledes'}, + map { $_->{'code'} => $POST{$_->{'code'}} ? "Y" : "N" } @style_opts }); + + my $extravars; + if ($style->{'type'} eq 'day') { + my ($curmday, $curmon, $curyear) = (localtime(time))[3..5]; + $extravars = sprintf("&day=%02d&month=%02d&year=%04d", + $curmday, $curmon+1, $curyear+1900); + } + # all good + return "{'user'}" . + "&styleid=$styleid$extravars\">here. p?>"; + } + + # this should never happen + return LJ::bad_input("Unknown mode: $mode."); + +} +_code?> + +<=body +page?> +link: htdocs/styles/edit.bml, htdocs/developer/views.bml, htdocs/customview.cgi +file: htdocs/vars.dat +post: htdocs/styles/edit_do.bml + _c?> diff --git a/livejournal/htdocs/styles/index.bml b/livejournal/htdocs/styles/index.bml new file mode 100755 index 0000000..21a3c88 --- /dev/null +++ b/livejournal/htdocs/styles/index.bml @@ -0,0 +1,26 @@ + +body<= + + + + h1?> + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +<=body +page?> +link: htdocs/developer/embedding.bml, htdocs/developer/styles.bml +link: htdocs/developer/index.bml, htdocs/paidaccounts/index.bml +link: htdocs/modify.bml, htdocs/styles/create.bml, htdocs/styles/edit.bml + _c?> diff --git a/livejournal/htdocs/styles/tags.css b/livejournal/htdocs/styles/tags.css new file mode 100755 index 0000000..356e677 --- /dev/null +++ b/livejournal/htdocs/styles/tags.css @@ -0,0 +1,217 @@ +fieldset +{ + border: 1px solid #cdcdcd; + padding: 0px 6px 6px 6px; +} + +legend +{ + padding: 2px 10px 2px 10px; + border: 1px solid #cdcdcd; + font-weight: bold; + /* + font-family: Arial; + background: #eee url(/img/grey_gradbg.gif); + */ +} + +.tagsort +{ + border-top: 1px solid #cdcdcd; + font-size: 0.8em; +} + +.taginfo +{ + color: #777; + padding: 4px; + background: #eee url(/img/grey_gradbg.gif); + border: 1px solid #cdcdcd; +} + +.tagbox +{ + width: 300px; + background-color: #eee; + padding: 4px; + height: 250px; +} + +.tagbox option +{ + background-position: center left; + background-repeat: no-repeat; + padding-left: 22px; + padding-bottom: 2px; +} + +.tagbox .level1 +{ + background-image: url(/img/level1.gif); +} + +.tagbox .level2 +{ + background-image: url(/img/level2.gif); +} + +.tagbox .level3 +{ + background-image: url(/img/level3.gif); +} + +.tagbox .level4 +{ + background-image: url(/img/level4.gif); +} + +.tagbox .level5 +{ + background-image: url(/img/level5.gif); +} + +.tagfield +{ + border: 1px solid #cdcdcd; +} + +.tagfield_error +{ + border: 1px solid red; + background-color: #ecd7d7; +} + +.tagfield:focus +{ + background-color: #eee; + border: 1px solid black; +} + +.btn +{ + border-left: 1px solid #999; + border-top: 1px solid #999; + border-right: 1px solid #555; + border-bottom: 1px solid #555; +} + +.btn:hover +{ + background-color: #eee; + border-right: 1px solid #999; + border-bottom: 1px solid #999; + border-left: 1px solid #555; + border-top: 1px solid #555; +} + +#selected_tags +{ + padding: 5px; + margin-bottom: 10px; + color: #777; + width: 300px; + white-space: wrap; +} + +.proptbl +{ + width: 100%; +} + +.proptbl td +{ + padding: 4px; + width: 50%; +} + +/* table headers */ +.proptbl .h +{ + color: #777; + padding: 4px; + background: #eee url(/img/grey_gradbg.gif); + border: 1px solid #cdcdcd; + text-align: center; +} + +/* counts */ +.proptbl .c +{ + text-align: center; +} + +/* count type */ +.proptbl .t +{ + color: #777; + text-align: right; + background-color: #fbfbfb; + border-right: 1px solid #cdcdcd; +} + +/* results */ +.proptbl .r +{ + color: #777; + text-align: right; + background-color: #fbfbfb; + font-weight: bold; + border-right: 1px solid #cdcdcd; +} + +/* result value */ +.proptbl .rv +{ + text-align: center; + background-color: #eee; + font-weight: bold; +} + +/* edittags.bml */ +.edittbl td +{ + padding: 7px; +} + +/* labels */ +.edittbl .l, .lsep +{ + font-weight: bold; + text-align: right; + vertical-align: top; + white-space: nowrap; + border-right: 1px solid #777; +} + +/* separator line */ +.edittbl .sep +{ + border-top: 1px solid #777; + white-space: nowrap; +} + +.curtags +{ + color: #777; +} + +.tagbox_nohist +{ + width: 300px; + background-color: #eee; + padding: 4px; + height: 250px; +} + +.tagbox_nohist option +{ + background-position: center left; + background-repeat: no-repeat; + padding-bottom: 2px; +} + +.update_good +{ + font-weight: bold; +} + diff --git a/livejournal/htdocs/support/act.bml b/livejournal/htdocs/support/act.bml new file mode 100755 index 0000000..9e023c9 --- /dev/null +++ b/livejournal/htdocs/support/act.bml @@ -0,0 +1,169 @@ + +body<= +"; + } + my $remote = LJ::get_remote(); + + LJ::Support::init_remote($remote); + my $sp = LJ::Support::load_request($spid); + + if ($sp->{'authcode'} ne $authcode) { + return ""; + } + + if ($action eq "touch") { + return "" + if LJ::Support::is_locked($sp); + + LJ::Support::touch_request($spid) + or return ""; + + $ret .= ("{'state'} eq "open" ? "will stay open now." + : "has been re-opened now."). + " Please comment back telling us why you've touched this request:". + " p?>"); + + my $auth = LJ::Support::mini_auth($sp); + + $ret .= '
    '; + # hidden values + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + $ret .= '\n"; + + $ret .= ""; + + # textarea for their message body + $ret .= '
    From:'; + if ($remote && $remote->{'userid'}) { + $ret .= "{'user'} ljuser?>"; + } else { + $ret .= "(not logged in)"; + } + $ret .= "
    Reply Type:"; + $ret .= ''; + $ret .= "More Information"; + + $ret .= "
    Message:'; + $ret .= '
    '; + $ret .= "\nURLs are automatically link-ified, so just reference those. de?>
    \n"; + $ret .= ''; + $ret .= "\n
    "; + + return $ret; + } + + if ($action eq 'lock') { + return "" + unless $remote && LJ::Support::can_lock($sp, $remote); + return "" + if LJ::Support::is_locked($sp); + + # close this request and IC on it + LJ::Support::lock($sp); + LJ::Support::append_request($sp, { + body => '(Locking request.)', + remote => $remote, + type => 'internal', + }); + return "{spid}'>request has been locked. p?>"; + } + + if ($action eq 'unlock') { + return "" + unless $remote && LJ::Support::can_lock($sp, $remote); + return "" + unless LJ::Support::is_locked($sp); + + # reopen this request and IC on it + LJ::Support::unlock($sp); + LJ::Support::append_request($sp, { + body => '(Unlocking request.)', + remote => $remote, + type => 'internal', + }); + return "{spid}'>request has been unlocked. p?>"; + } + + if ($action eq "close") { + if ($sp->{'state'} eq "open") { + my $dbh = LJ::get_db_writer(); + $splid += 0; + if ($splid) { + $sth = $dbh->prepare("SELECT userid, timelogged, spid, type FROM supportlog WHERE splid=$splid"); + $sth->execute; + my ($userid, $timelogged, $aspid, $type) = $sth->fetchrow_array; + + if ($aspid != $spid) { + return ""; + } + + ## can't credit yourself. + if ($userid != $sp->{'requserid'} && $type eq "answer") { + my $cats = LJ::Support::load_cats($sp->{'spcatid'}); + my $secold = $timelogged - $sp->{'timecreate'}; + my $points = LJ::Support::calc_points($sp, $secold); + LJ::Support::set_points($spid, $userid, $points); + } + } + $dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() WHERE spid=$spid"); + } + + my $remote = LJ::get_remote(); + my $is_admin = LJ::check_priv($remote, "supportclose"); + if ($is_admin) + { + my $dbr = LJ::get_db_reader(); + my $catid = $sp->{'_cat'}->{'spcatid'}; + my $sql = "SELECT MIN(spid) FROM support WHERE spcatid=$catid AND state='open' AND timelasthelp>timetouched AND spid>$spid"; + my $sth = $dbr->prepare($sql); + $sth->execute; + my $next = $sth->fetchrow_array; + if ($next) { + return BML::redirect("$LJ::SITEROOT/support/see_request.bml?id=$next"); + } else { + return " +"; + } + } + + return ""; + } + + return; + +_code?> + +<=body +page?> +link: htdocs/support/see_request.bml + _c?> diff --git a/livejournal/htdocs/support/actmulti.bml b/livejournal/htdocs/support/actmulti.bml new file mode 100755 index 0000000..eb191d4 --- /dev/null +++ b/livejournal/htdocs/support/actmulti.bml @@ -0,0 +1,82 @@ +Support Request Management +body<= +" unless $remote; + + my $spcatid = $POST{spcatid}; + my $cat = LJ::Support::load_cats($spcatid); + return "" unless $cat; + + # get ids of requests + my @ids = map { $_+0 } grep { $POST{"check_$_"} } split(':', $POST{ids}); + return "" unless @ids; + + # just to be sane, limit it to 1000 requests + @ids = splice @ids, 0, 1000 if scalar @ids > 1000; + + # what action are they trying to take? + if ($POST{'action:close'}) { + my $can_close = 0; + $can_close = 1 if LJ::check_priv($remote, 'supportclose', $cat->{catkey}); + $can_close = 1 if $cat->{public_read} && LJ::check_priv($remote, 'supportclose', ''); + return "" unless $can_close; + + # now close all of these requests + my $dbh = LJ::get_db_writer(); + my $in = join ',', @ids; + $dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() " . + "WHERE spid IN ($in) AND spcatid = ?", undef, $spcatid); + + # and now insert a log comment for all of these... note that we're not using + # LJ::Support::append_request because that'd require us to load a bunch of requests + # and then do a bunch of individual queries, and that sucks. + my @stmts; + foreach (@ids) { + push @stmts, "($_, UNIX_TIMESTAMP(), 'internal', $remote->{userid}, " . + "'(Request closed as part of mass closure.)')"; + } + my $sql = "INSERT INTO supportlog (spid, timelogged, type, userid, message) VALUES "; + $sql .= join ',', @stmts; + $dbh->do($sql); + + # return redirection back? or success message otherwise + return BML::redirect($POST{ret}) if $POST{ret}; + return ""; + } elsif ($POST{'action:move'}) { + return "" + unless LJ::Support::can_perform_actions({ _cat => $cat }, $remote); + + my $newcat = $POST{'changecat'} + 0; + my $cats = LJ::Support::load_cats(); + return "" unless $cats->{$newcat}; + + # now move all of these requests + my $dbh = LJ::get_db_writer(); + my $in = join ',', @ids; + $dbh->do("UPDATE support SET spcatid = ? WHERE spid IN ($in) AND spcatid = ?", + undef, $newcat, $spcatid); + + # now add movement notices + my @stmts; + foreach (@ids) { + push @stmts, "($_, UNIX_TIMESTAMP(), 'internal', $remote->{userid}, " . + "'(Mass move from $cats->{$spcatid}->{catname} to $cats->{$newcat}->{catname}.)')"; + } + my $sql = "INSERT INTO supportlog (spid, timelogged, type, userid, message) VALUES "; + $sql .= join ',', @stmts; + $dbh->do($sql); + + # done now + return BML::redirect($POST{ret}) if $POST{ret}; + return ""; + } +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/support/append_request.bml b/livejournal/htdocs/support/append_request.bml new file mode 100755 index 0000000..5012bd4 --- /dev/null +++ b/livejournal/htdocs/support/append_request.bml @@ -0,0 +1,246 @@ +Append Request +body<= + +{'r'}; + + my $status = ""; + + my $spid = $FORM{'spid'}+0; + my $sp = LJ::Support::load_request($spid); + + return "" unless $sp; + return "" + if $sp->{'state'} eq "closed"; + + my $remote = LJ::get_remote(); + LJ::Support::init_remote($remote); + + unless (LJ::Support::can_append($sp, $remote, $FORM{'auth'}) || $remote) { + return LJ::bad_input($ML{'.login.required'}); + } + + if ($remote && ! $remote->tosagree_verify) { + my $ret = " 'title') . " h1?>"; + + my $html_str = LJ::tosagree_str('support' => 'html'); + if ($html_str) { + $ret .= ""; + } else { + $ret .= BML::ml + ('tos.mustread', + { aopts => "target='_new' href='$LJ::SITEROOT/legal/tos.bml'" }); + } + + return $ret; + } + + my $scat = $sp->{_cat}; + my $problemarea = $scat->{'catname'}; + my $catkey = $scat->{'catkey'}; + + return LJ::bad_input($ML{'.invalid.noid'}) unless $FORM{'spid'}; + return LJ::bad_input("") unless LJ::did_post(); + return LJ::bad_input($ML{'.invalid.nosummary'}) + if $FORM{'changesum'} && ! LJ::trim($FORM{'summary'}); + + ### links to show on success + my $auth_arg = $FORM{'auth'} ? "&auth=$FORM{'auth'}" : ""; + my $successlinks = BML::ml('.successlinks', + { 'number' => $sp->{'spid'}, + 'back' => "see_request.bml?id=$sp->{'spid'}$auth_arg", + 'open' => "help.bml", + 'opencat' => "help.bml?cat=$scat->{'catkey'}", + 'prevopen' => "see_request.bml?id=$sp->{'spid'}&find=prev", + 'nextopen' => "see_request.bml?id=$sp->{'spid'}&find=next", + 'cprevopen' => "see_request.bml?id=$sp->{'spid'}&find=cprev", + 'cnextopen' => "see_request.bml?id=$sp->{'spid'}&find=cnext", + }); + + ### insert record + my $faqid = $FORM{'faqid'}+0; + + my %answer_types = LJ::Support::get_answer_types($sp, $remote, $FORM{'auth'}); + + my $type = $FORM{'replytype'}; + return LJ::bad_input($ML{'.invalid.type'}) unless defined $answer_types{$type}; + + ## can we do the action we want? + return LJ::bad_input($ML{'.internal.approve'}) + if $FORM{'approveans'} && ($type ne "internal" || ! LJ::Support::can_help($sp, $remote)); + + return LJ::bad_input($ML{'.internal.changecat'}) + if $FORM{'changecat'} && ($type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote)); + + return LJ::bad_input($ML{'.internal.touch'}) + if ($FORM{'touch'} || $FORM{'untouch'}) && + ($type ne "internal" || ! LJ::Support::can_perform_actions($sp, $remote)); + + return LJ::bad_input($ML{'.internal.changesum'}) + if $FORM{'changesum'} && ($type ne "internal" || ! LJ::Support::can_change_summary($sp, $remote)); + + return LJ::bad_input($ML{'.invalid.blank'}) + if $FORM{'body'} !~ /\S/ && !$FORM{'approveans'} && !$FORM{'changecat'} && + !$FORM{'touch'} && !$FORM{'untouch'} && !$FORM{'changesum'}; + + # Load up vars for approvals + my $res; + my $splid; + if ($FORM{'approveans'}) { + $splid = $FORM{'approveans'}+0; + $res = LJ::Support::load_response($splid); + + return LJ::bad_input($ML{'.invalid.noanswer'}) + if ($res->{'spid'} == $spid && $res->{'type'} ne "screened"); + + return LJ::bad_input('Invalid type to approve screened response as.') + if (($FORM{'approveas'} ne 'answer') && ($FORM{'approveas'} ne 'comment')); + } + + # Load up vars for category moves + my $newcat; + my $cats; + if ($FORM{'changecat'}) { + $newcat = $FORM{'changecat'}+0; + $cats = LJ::Support::load_cats($newcat); + + return LJ::bad_input($ML{'.invalid.notcat'}) + unless ($cats->{$newcat}); + } + + # get dbh now, it's always needed + my $dbh = LJ::get_db_writer(); + + ## touch/untouch request + if ($FORM{'touch'}) { + $dbh->do("UPDATE support SET state='open', timetouched=UNIX_TIMESTAMP(), timeclosed=0 WHERE spid=$spid"); + $status .= "(Inserting request into queue)\n\n"; + } + if ($FORM{'untouch'}) { + $dbh->do("UPDATE support SET timelasthelp=UNIX_TIMESTAMP() WHERE spid=$spid"); + $status .= "(Removing request from queue)\n\n"; + } + + ## bounce request to email + if ($type eq 'bounce') { + + return LJ::bad_input($ML{'.bounce.noemail'}) + unless $FORM{'bounce_email'}; + + return LJ::bad_input($ML{'.bounce.notauth'}) + unless LJ::Support::can_bounce($sp, $remote); + + # check given emails using LJ::check_email + my @form_emails = split(/\s*,\s*/, $FORM{'bounce_email'}); + + return LJ::bad_input($ML{'.bounce.toomany'}) + if @form_emails > 5; + + my @emails; # error-checked, good emails + my @email_errors; + foreach my $email (@form_emails) { + + # see if it's a valid lj username + unless ($email =~ /\@/) { + my $eu = LJ::load_user($email); # $email is a username + $email = $eu->{'email'} if $eu; + } + + LJ::check_email($email, \@email_errors); + @email_errors = map { "$email: $_" } @email_errors; + return LJ::bad_input(@email_errors) if @email_errors; + + # push onto our list of valid emails + push @emails, $email; + } + + # append notice that this message was bounced + my $splid = LJ::Support::append_request($sp, { + 'body' => "(Bouncing mail to '" . join(', ', @emails) . "' and closing)\n\n" . $FORM{'body'}, + 'posterid' => $remote, + 'type' => 'internal', + 'uniq' => $r->notes('uniq'), + 'remote' => $remote, + }); + + # bounce original request to email + my $message = $dbh->selectrow_array("SELECT message FROM supportlog " . + "WHERE spid=? ORDER BY splid LIMIT 1", + undef, $sp->{'spid'}); + + LJ::send_mail({ + 'to' => join(", ", @emails), + 'from' => $sp->{'reqemail'}, + 'fromname' => $sp->{'reqname'}, + 'headers' => { 'X-Bounced-By' => $remote->{'user'} }, + 'subject' => "$sp->{'subject'} (support request #$sp->{'spid'})", + 'body' => "$message\n\n$LJ::SITEROOT/support/see_request.bml?id=$sp->{'spid'}", + }); + + # close request, nobody gets credited + $dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() WHERE spid=?", + undef, $sp->{'spid'}); + + return BML::ml('.bounced.success', { 'addresslist' => "".join(', ', @emails)."" }) + .$successlinks; + } + + $dbh->do("UPDATE support SET state='open', timetouched=UNIX_TIMESTAMP(), timeclosed=0 WHERE spid=$spid") + if LJ::Support::is_poster($sp, $remote, $FORM{'auth'}); + + ## change category + if ($FORM{'changecat'}) { + # $newcat, $cats defined above + $dbh->do("UPDATE support SET spcatid=$newcat WHERE spid=$spid"); + $status .= "Changing from $catkey => $cats->{$newcat}->{'catkey'}\n\n"; + $sp->{'spcatid'} = $newcat; # update category so IC e-mail goes to right place + } + + ## approving a screened response + if ($FORM{'approveans'}) { + # $res, $splid defined above + # approve + my $qtype = $dbh->quote($FORM{'approveas'}); + $dbh->do("UPDATE supportlog SET type=$qtype WHERE splid=$splid"); + $status .= "(Approving $FORM{'approveas'} \#$splid)\n\n"; + LJ::Support::mail_response_to_user($sp, $splid); + } + + ## change summary + if ($FORM{'changesum'}) { + $FORM{'summary'} =~ s/[\n\r]//g; + my $qnewsub = $dbh->quote($FORM{'summary'}); + $dbh->do("UPDATE support SET subject=$qnewsub WHERE spid=$spid"); + $status .= "Changing subject from \"$sp->{'subject'}\" to \"$FORM{'summary'}\".\n\n"; + } + + my $splid = LJ::Support::append_request($sp, { + 'body' => $status . $FORM{'body'}, + 'type' => $type, + 'faqid' => $faqid, + 'uniq' => $r->notes('uniq'), + 'remote' => $remote, + }); + + LJ::Support::mail_response_to_user($sp, $splid); + + return "" . $successlinks; +} +_code?> + +Back to the list of open requests.
    +Back to the support area. + +<=body +page?> +link: htdocs/login.bml, htdocs/support/see_request.bml, htdocs/support/help.bml +link: htdocs/support/index.bml + _c?> diff --git a/livejournal/htdocs/support/changenotify.bml b/livejournal/htdocs/support/changenotify.bml new file mode 100755 index 0000000..4273130 --- /dev/null +++ b/livejournal/htdocs/support/changenotify.bml @@ -0,0 +1,106 @@ +1 +_info?>Change Notifications +body<= + +login."; + } + if ($mode eq "save" && ! LJ::did_post) { + push @errors, ""; + } + return LJ::bad_input(@errors) if @errors; + + LJ::Support::init_remote($remote); + my $cats = LJ::Support::load_cats(); + my @filter_cats = LJ::Support::filter_cats($remote, $cats); + + if ($mode eq "modify") + { + my $ret = ""; + $ret .= "
    \n"; + $ret .= "\n"; + + $ret .= "off (the default), new (you'll get notifications when a new support request in that category is posted) or all (you'll get notifications and then a copy of each comment/solution posted). p?>"; + + my %notify; + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT spcatid, level FROM supportnotify WHERE userid=$remote->{'userid'}"); + $sth->execute; + while (my ($spcatid, $level) = $sth->fetchrow_array) { + ## if user used to be able to read a category, subscribed, then lost + ## privs, this ensures any future save will turn off things they + ## don't have access to: + if (LJ::Support::can_read_cat($cats->{$spcatid}, $remote)) { + $notify{$spcatid} = $level; + } + } + + my %valname = ("off" => "Off.", + "new" => "New only.", + "all" => "All", + ); + + $ret .= "
    \n"; + foreach my $cat (@filter_cats) { + $ret .= "

    $cat->{'catname'}

    \n"; + } + $ret .= "
    \n"; + + + ### ending submit block + $ret .= "\n"; + $ret .= " standout?>\n"; + $ret .= "
    \n"; + + return $ret; + } + + if ($mode eq "save") + { + my $dbh = LJ::get_db_writer(); + $dbh->do("DELETE FROM supportnotify WHERE userid=$remote->{'userid'}"); + my $sql; + + foreach my $cat (@filter_cats) + { + my $id = $cat->{'spcatid'}; + my $setting = $FORM{"spcatid_$id"}; + if ($setting eq "all" || + $setting eq "new") + { + if ($sql) { $sql .= ", "; } + else { $sql .= "REPLACE INTO supportnotify (spcatid, userid, level) VALUES "; } + $sql .= "($id, $remote->{'userid'}, '$setting')"; + } + } + if ($sql) { $dbh->do($sql); } + + return ""; + } + + return "Unknown mode." + +_code?> + +<=body +page?> +link: htdocs/login.bml +post: htdocs/support/changenotify.bml + _c?> diff --git a/livejournal/htdocs/support/encodings.bml b/livejournal/htdocs/support/encodings.bml new file mode 100755 index 0000000..4e2eb2f --- /dev/null +++ b/livejournal/htdocs/support/encodings.bml @@ -0,0 +1,19 @@ +$ML{'.overview.text'}"; + $body .= "$ML{'.edit.text'}"; + $body .= "$ML{'.editcl.text'}"; + $body .= "$ML{'.groups.text'}"; + $body .= "$ML{'.still.text'}"; + + return; + +_code?> +body=> +page?> diff --git a/livejournal/htdocs/support/faq.bml b/livejournal/htdocs/support/faq.bml new file mode 100755 index 0000000..7764370 --- /dev/null +++ b/livejournal/htdocs/support/faq.bml @@ -0,0 +1,95 @@ +FAQ +body<= + + + + +{'dmid'} AND l.dmid=$mld->{'dmid'} AND i.dmid=$mld->{'dmid'} AND ". + "l.lnid=$mll->{'lnid'} AND l.itid=i.itid AND i.itcode=CONCAT('cat.', fc.faqcat) ". + "AND l.txtid=t.txtid AND fc.faqcat<>'int-abuse'"; + $sth = $dbr->prepare($sql); + } else { + $sth = $dbr->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat ". + "WHERE faqcat<>'int-abuse'"); + } + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $faqcat{$_->{'faqcat'}} = $_; + } + + if ($altlang) { + my $sql = "SELECT f.faqid, t.text AS 'question', f.sortorder, ". + "f.faqcat, f.lastmodtime FROM faq f, ". + "ml_text t, ml_latest l, ml_items i WHERE ". + "t.dmid=$mld->{'dmid'} AND l.dmid=$mld->{'dmid'} AND i.dmid=$mld->{'dmid'} AND ". + "l.lnid=$mll->{'lnid'} AND l.itid=i.itid AND i.itcode=CONCAT(f.faqid, '.1question') ". + "AND l.txtid=t.txtid AND f.faqcat<>'int-abuse'"; + $sth = $dbr->prepare($sql); + } else { + $sth = $dbr->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime ". + "FROM faq WHERE faqcat<>'int-abuse'"); + } + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $faqq{$_->{'faqid'}} = $_; + } + + foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> + $faqcat{$b}->{'catorder'} } keys %faqcat) + { + next if $GET{'cat'} && $GET{'cat'} ne $faqcat; + $ret .= "{'faqcatname'}); + $ret .= " ("; + $ret .= "view all"; + $ret .= ") h2?>\n"; + $ret .= "
      \n"; + foreach my $faqid (sort { $faqq{$a}->{'sortorder'} <=> $faqq{$b}->{'sortorder'} } grep { $faqq{$_}->{'faqcat'} eq $faqcat } keys %faqq) + { + next unless ($faqq{$faqid}->{'question'}); + BML::note_mod_time($faqq{$faqid}->{'lastmodtime'}); + my $q = LJ::ehtml($faqq{$faqid}->{'question'}); + $q =~ s/^\s+//; $q =~ s/\s+$//; + $q =~ s!\n!
      !g; + $ret .= "
    • $q
    • \n"; + } + $ret .= "
    \n"; + } + +return $ret; + +_code?> + + +

    Back to the support area.

    + +<=body +page?> +link: htdocs/support/faqbrowse.bml, htdocs/support/index.bml + _c?> diff --git a/livejournal/htdocs/support/faqbrowse.bml b/livejournal/htdocs/support/faqbrowse.bml new file mode 100755 index 0000000..4e06d32 --- /dev/null +++ b/livejournal/htdocs/support/faqbrowse.bml @@ -0,0 +1,141 @@ +{'title'}; + my $body = \$_[1]->{'body'}; + $$body = ''; + $$title = ''; + + # get faqid and redirect to faq.bml if none + my $faqid = $GET{'faqid'} + 0; + my $faqcat = $GET{'faqcat'}; + + my $where; + + my $dbr = LJ::get_db_reader(); + # loading single faqid + if ($faqid) { + $$title = BML::ml('.title_num', { 'num' => $faqid }); + $where = "faqid=$faqid"; + + # loading entire faqcat + } elsif ($faqcat) { + my $catname = $dbr->selectrow_array("SELECT faqcatname FROM faqcat WHERE faqcat=?", + undef, $faqcat); + $$title = BML::ml('.title_cat', { 'catname' => LJ::ehtml($catname) }); + + $where = "faqcat=" . $dbr->quote($faqcat); + + # no faqid or faqcat specified, redirect + } else { + return BML::redirect("faq.bml"); + } + + my $remote = LJ::get_remote(); + + # get language settings + my $curlang = BML::get_language(); + my $deflang = BML::get_language_default(); + my $altlang = $curlang ne $deflang; + my $mld; + if ($altlang) { + my $mll = LJ::Lang::get_lang($curlang); + $mld = LJ::Lang::get_dom("faq"); + $altlang = 0 unless $mll && $mld; + } + + # query db and get data + my $sth = $dbr->prepare("SELECT faqid, question, answer, faqcat, lastmoduserid, ". + "DATE_FORMAT(lastmodtime, '%Y-%m-%d'), ". + "UNIX_TIMESTAMP(lastmodtime) FROM faq ". + "WHERE $where ORDER BY sortorder"); + $sth->execute; + if ($dbr->err) { + $$title = $ML{'Error'}; + $$body = "$ML{'error.dberror'}
    • " . $dbr->errstr . "
    \n"; + return; + } + + my $count = 0; + my $dbh; + my $backfaqcat; + while (my ($faqid, $question, $answer, $faqcat, $lastmoduserid, + $lastmodtime, $unixmodtime) = $sth->fetchrow_array) + { + + $dbh ||= LJ::get_db_writer(); + + # log this faq view + if ($remote && ! $LJ::DISABLED{faquses}) { + $dbh->do("REPLACE INTO faquses (faqid, userid, dateview) ". + "VALUES ($faqid, ?, NOW())", undef, $remote->{'userid'}); + } + + BML::note_mod_time($unixmodtime); + + # it'd be better to load them in a batch, but this works for now: + if ($altlang) { + $question = LJ::Lang::get_text($curlang, "$faqid.1question", $mld->{'dmid'}); + $answer = LJ::Lang::get_text($curlang, "$faqid.2answer", $mld->{'dmid'}); + } + + # escape question and answers + my $q = LJ::ehtml($question); + $q =~ s/^\s+//; $q =~ s/\s+$//; + $q =~ s/\n/
    /g; + + my $a = LJ::ehtml($answer); + $a =~ s/^\s+//; $a =~ s/\s+$//; + $a =~ s/\n( +)/"\n" . "  "x length($1)/eg; + $a =~ s/\n/
    /g; + + $a = LJ::auto_linkify($a); + + # display output + $$body .= "»"; + } + $$body .= " $q h1?>
    $a
    "; + + my $lastmodwho = LJ::get_username($lastmoduserid); + if ($lastmodwho) { + $$body .= "

    $ML{'.lastupdated'}
    $lastmodwho, $lastmodtime

    "; + } + if (LJ::check_priv($remote, "faqedit", "*") || + LJ::check_priv($remote, "faqedit", $faqcat)) + { + $$body .= "

    $ML{'.edit.faq'}

    "; + } + + $count++; + $backfaqcat = $faqcat; + } + + # nothing found? + unless ($count) { + $$title = $ML{'Error'}; + $$body .= "

    $ML{'.error.nofaq'}

    \n"; + } + + $$body .= ""; + $$body .= BML::ml('.backfaqcat',{'faqcat'=>$backfaqcat,}) . "
    " if $backfaqcat && $faqid; + $$body .= "$ML{'.backfaq'}
    $ML{'.backsupport'}"; + + # we're dynamic, set title as crumb title + LJ::set_dynamic_crumb($_[1]->{'title'}, 'faq'); + + return $_[1]->{'body'}; +} +_code?> +<=body +title=>{'title'}; _code?> +page?> +link: htdocs/support/index.bml, htdocs/support/faq.bml + _c?> diff --git a/livejournal/htdocs/support/faqpop.bml b/livejournal/htdocs/support/faqpop.bml new file mode 100755 index 0000000..4f48368 --- /dev/null +++ b/livejournal/htdocs/support/faqpop.bml @@ -0,0 +1,40 @@ +Popular FAQs +body<= + + + + +prepare("SELECT f.faqid, f.question, s.statval AS 'uses'". + "FROM faq f, stats s WHERE f.faqcat<>'int-abuse' AND s.statcat='popfaq' ". + "AND s.statkey=f.faqid ORDER BY s.statval DESC LIMIT 50"); + $sth->execute; + + $ret .= "
      "; + while (my $f = $sth->fetchrow_hashref) + { + my $q = LJ::ehtml($f->{'question'}); + $q =~ s/^\s+//; $q =~ s/\s+$//; + $q =~ s!\n!
      !g; + $ret .= "
    • {'faqid'}\">$q ($f->{'uses'})
    • \n"; + } + $ret .= "
    \n"; + + return $ret; + +_code?> + + +

    Back to the support area.

    + +<=body +page?> +link: htdocs/support/faqbrowse.bml, htdocs/support/index.bml + _c?> diff --git a/livejournal/htdocs/support/help.bml b/livejournal/htdocs/support/help.bml new file mode 100755 index 0000000..5d9a5b1 --- /dev/null +++ b/livejournal/htdocs/support/help.bml @@ -0,0 +1,351 @@ + +.green { + background-color: #d0eed0; +} +.yellow { + background-color: #eeeed0; +} +.red { + background-color: #eed0d0; +} +.clicked { + background-color: #d0d0ee; +} + + + +<=head +title=>Support Requests +body<= + +request; + + my $remote = LJ::get_remote(); + LJ::Support::init_remote($remote); + + return $ML{'.interim'} if + (!$remote || !$remote->{'_priv'}) && + $r->header_in("Referer") eq "$LJ::SITEROOT/support/"; + + my $cats = LJ::Support::load_cats(); + + my $state = $FORM{'state'}; + $state = 'open' unless $state =~ /^(?:open|closed|green|youreplied)$/; + + my $filtercat = $FORM{'cat'}; + $filtercat = "" unless ($filtercat =~ /^[\w\-]+$/); + my $fcat = LJ::Support::get_cat_by_key($cats, $filtercat); + my $can_read = LJ::Support::can_read_cat($fcat, $remote); + + # determine if user can close stuff + my $can_close = 0; + if ($remote && $state =~ /(?:green|open)/ && $filtercat) { + $can_close = 1 if LJ::check_priv($remote, 'supportclose', $filtercat); # private cats/only this cat + $can_close = 1 if $fcat->{public_read} && LJ::check_priv($remote, 'supportclose', ''); # public cats + } + + my $append; + if ($state eq "closed") { + $ret .= "click here. p?>"; + } elsif ($state eq "youreplied") { + return "" + unless $remote; + $ret .= ""; + } else { + $ret .= "closed reports are also " . + "available. If you help somebody out and they confirm you helped them, you get the number " . + "of points indicated in the status column. These points will show up on your userinfo page. p?>"; + $append = 1; + } + + my @support_log; + + # if we have a cat to filter to and we have abstracts for it + my $rct = 0; + my $abstracts = 0; + if ($filtercat && $LJ::SUPPORT_ABSTRACTS{$filtercat} && $fcat && $can_read && $state ne 'youreplied') { + # yes, we should show abstracts for this category, so do so + if ($state eq "closed") { + $sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " . + "FROM support s, supportlog sl " . + "WHERE s.state='closed' AND s.spid = sl.spid AND sl.type = 'req' " . + "AND s.timeclosed > (UNIX_TIMESTAMP() - (3600*24)) " . + "AND s.spcatid = ?"); + } else { # triggers on green, open + $sth = $dbr->prepare("SELECT s.*, SUBSTRING(sl.message, 1, 200) AS 'message' " . + "FROM support s, supportlog sl " . + "WHERE s.state='open' AND s.spid = sl.spid AND sl.type = 'req' " . + "AND s.spcatid = ?"); + } + $sth->execute($fcat->{spcatid}); + push @support_log, $_ while $_ = $sth->fetchrow_hashref(); + $rct = scalar(@support_log); + $abstracts = 1; + } else { + my $filterwhere; + + if ($filtercat eq "_nonpublic") { + $filterwhere = " AND s.spcatid IN (0"; + foreach my $cat (values %$cats) { + $filterwhere .= ", $cat->{'spcatid'}" + if !$cat->{'public_read'} && LJ::Support::can_read_cat($cat, $remote); + } + $filterwhere .= ")"; + } elsif ($filtercat eq "_nonprivate") { + $filterwhere = " AND s.spcatid IN (0"; + foreach my $cat (values %$cats) { + $filterwhere .= ", $cat->{'spcatid'}" if $cat->{public_read}; + } + $filterwhere .= ")"; + } else { + if ($can_read) { + $filterwhere = " AND s.spcatid=$fcat->{'spcatid'}"; + } else { + $filtercat = ""; + } + } + + my $dbr = LJ::get_db_reader(); + if ($state eq "closed") { + $sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='closed' AND " . + "s.timeclosed>UNIX_TIMESTAMP()-(3600*24) $filterwhere"); + } elsif ($state eq "youreplied") { + $sth = $dbr->prepare("SELECT s.* FROM support s, support_youreplied yr " . + "WHERE yr.userid=$remote->{'userid'} AND s.spid=yr.spid $filterwhere " . + "AND (s.state='open' OR (s.state='closed' AND s.timeclosed>UNIX_TIMESTAMP()-(3600*24)))"); + } else { # triggers on green, open + $sth = $dbr->prepare("SELECT s.* FROM support s WHERE s.state='open' $filterwhere"); + } + $sth->execute; + + # For the You Replied filter, we might be getting some rows multiple times (when + # multiple log rows exist for $remote), which is still better than using DISTINCT + # in the query which uses a temporary table, so ensure uniqueness here. + my %spids_seen; + while (my $sprow = $sth->fetchrow_hashref) { + next if $spids_seen{$sprow->{'spid'}}; + $spids_seen{$sprow->{'spid'}} = 1; + push @support_log, $sprow; + $rct++; + } + } + + my $sort = $FORM{sort}; + $sort = 'date' unless $sort =~ /^id|summary|area|date$/; + + $ret .= "

    [$rct total open requests]

    " if $append; + if ($sort eq 'id') { + @support_log = sort { $a->{spid} <=> $b->{spid} } @support_log; + } elsif ($sort eq 'date') { + @support_log = sort { $b->{timecreate} <=> $a->{timecreate} } @support_log; + } elsif ($sort eq 'summary') { + @support_log = sort { $a->{subject} cmp $b->{subject} } @support_log; + } elsif ($sort eq 'area') { + @support_log = sort { $cats->{$a->{spcatid}}->{catname} cmp $cats->{$b->{spcatid}}->{catname} } @support_log; + } + + # filter line: + $ret .= "
    Show only "; + $ret .= ""; + $ret .= ""; + + $ret .= " requests of type: \n"; + $ret .= "
    "; + # /filter line + + # mass closing table + $ret .= "
    " if $can_close; + + # start the rest of the table + my $uri = "$LJ::SITEROOT/support/help.bml?cat=$filtercat&state=$state"; + $ret .= "

    \n"; + $ret .= "\n" if $can_close; + my @headers = ( id => "ID#", summary => "Summary", area => "Problem Area", date => "Posted" ); + while (my ($sorttype, $desc) = splice(@headers, 0, 2)) { + if ($sort eq $sorttype) { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + } + $ret .= "\n"; + $ret .= ""; + + foreach my $sp (@support_log) + { + LJ::Support::fill_request_with_cat($sp, $cats); + next unless (LJ::Support::can_read($sp, $remote)); + + my $status = "open"; + my $barbg = "green"; + if ($sp->{'timeclosed'}) { + $status = "closed"; + $barbg = "red"; + } + elsif ($sp->{'timelasthelp'} > $sp->{'timetouched'}+5) { + $status = "answered
    awaiting close"; + $barbg = "yellow"; + } + elsif ($sp->{'timelasthelp'} && $sp->{'timetouched'} > $sp->{'timelasthelp'}+5) { + $status = "answered
    still needs help"; + $barbg = "green"; + } + + next if $state eq "green" && $barbg ne "green"; + + # fix up the subject if needed + eval { + if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) { + my @subj_data; + @subj_data = MIME::Words::decode_mimewords($sp->{'subject'}); + if (scalar(@subj_data)) { + if (!$1) { + $sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]}); + } else { + $sp->{'subject'} = $subj_data[0][0]; + } + } + } + }; + + # fix up the message if we have one + my $temp = LJ::text_trim($sp->{message}, 0, 100); # 100 character max + if ($temp ne $sp->{message}) { + $sp->{message} = LJ::ehtml($temp) . " ..."; + } else { + $sp->{message} = LJ::ehtml($sp->{message}) . " "; + } + my $des = $abstracts ? "
    $sp->{message}" : ''; + + # other content for this request + my $summary = LJ::ehtml($sp->{'subject'}); + my $secold = time() - $sp->{'timecreate'}; + my $age = LJ::ago_text($secold); + my $probarea = $sp->{_cat}->{'catname'}; + my $points = LJ::Support::calc_points($sp, $secold); + + unless ($status eq "closed") { + $status .= "
    ($points point"; + if ($points > 1) { $status .= "s"; } + $status .= ")"; + } + + my ($style, $js) = ("class='$barbg'", ''); + if ($can_close) { + $js = "id='r$sp->{spid}' onclick='doClick($sp->{spid});'"; + } + + # generate the HTML for this row + $ret .= "\n"; + if ($can_close) { + $ret .= "\n"; + $js = "onclick='return doClick($sp->{spid});'"; + } + $ret .= ""; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= ""; + + } + $ret .= "
     X$desc$descStatus
    " . LJ::html_check({ name => "check_$sp->{spid}", id => "check_$sp->{spid}", + onclick => "doClick($sp->{spid});", }) . + "{'spid'}\" $js>$sp->{'spid'}$summary$des$probarea$age$status
    \n"; + + # mass close button + if ($can_close && $rct) { + my $time = time(); + $ret .= LJ::html_hidden('ids', join(':', map { $_->{spid} } @support_log), + 'spcatid', $fcat->{spcatid}, + 'ret', "/support/help.bml?state=$state&cat=$filtercat&time=$time"); + $ret .= "
    "; + $ret .= LJ::html_submit('action:move', 'Move Marked Requests'); + $ret .= " to "; + $ret .= LJ::html_select({ 'name' => 'changecat', selected => '' }, + '', '(no change)', + map { $_->{'spcatid'}, "---> $_->{'catname'}" } + LJ::Support::sorted_cats($cats)); + + + $ret .= "

    "; + $ret .= LJ::html_submit('action:close', 'Close Marked Requests', + { onclick => 'return confirm("Are you sure you want to close the marked requests?");' }); + $ret .= " (this is permanent)"; + $ret .= "

    "; + } + + return $ret; + +_code?> + + +

    Back to the support area.

    + +<=body +page?> +link: htdocs/support/help.bml, htdocs/support/see_request.bml +link: htdocs/support/index.bml +form: htdocs/support/help.bml + _c?> diff --git a/livejournal/htdocs/support/highscores.bml b/livejournal/htdocs/support/highscores.bml new file mode 100755 index 0000000..271fa7e --- /dev/null +++ b/livejournal/htdocs/support/highscores.bml @@ -0,0 +1,107 @@ +High Scores +head=> +body<= + +The following people have helped other users in the support area: + +prepare("SELECT statcat, statkey, statval FROM stats ". + "WHERE statcat IN ('supportrank', 'supportrank_prev')"); + $sth->execute; + + while (my ($cat, $userid, $rank) = $sth->fetchrow_array) { + if ($cat eq "supportrank") { + $rank{$userid}->{'now'} = $rank; + } else { + $rank{$userid}->{'last'} = $rank; + } + } + return "
    Support high score data is not available.
    " + unless %rank; + + $sth = $dbr->prepare("SELECT u.userid, u.user, u.name, sp.totpoints AS 'points', sp.lastupdate ". + "FROM user u, supportpointsum sp WHERE u.userid=sp.userid"); + $sth->execute; + my @rows; + push @rows, $_ while $_ = $sth->fetchrow_hashref; + if ($GET{'sort'} eq "lastupdate") { + @rows = sort { $b->{lastupdate} <=> $a->{lastupdate} } @rows; + } else { + @rows = sort { $b->{points} <=> $a->{points} } @rows; + } + + my $page = $GET{page}+0; + my $shown = 100 * ($page - 1) - 1; + my $rank = 0; + my $lastpoints = 0; + my $buildup = 0; + foreach (@rows[0..$shown]) { + if ($_->{'points'} != $lastpoints) { + $lastpoints = $_->{'points'}; + $rank += (1 + $buildup); + $buildup = 0; + } else { + $buildup++; + } + } + my $total = scalar(@rows); + + my %items = BML::paging(\@rows, $GET{'page'}, 100); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}); + @rows = @{$items{'items'}}; + + my $ret = $navbar; + $ret .= ""; + my $count = 0; + foreach (@rows) + { + $count++; + my $userid = $_->{'userid'}; + if ($_->{'points'} != $lastpoints) { + $lastpoints = $_->{'points'}; + $rank += (1 + $buildup); + $buildup = 0; + } else { + $buildup++; + } + my $change = ""; + if ($rank{$userid}->{'now'} && $rank{$userid}->{'last'}) { + $change = $rank{$userid}->{'last'} - $rank{$userid}->{'now'}; # from 5th to 4th is 5-4 = 1 (+1 for increase) + if ($change == 0) { + $change = ""; + } elsif ($change > 0) { + $change = "(+$change)"; + } else { + $change = "($change)"; + } + } + my $pts = $_->{'points'}; + my $s = $pts > 1 ? "s" : ""; + + my $name = LJ::ehtml($_->{'name'}); + $ret .= "\n"; + } + $ret .= "
    $rank.$change{'user'} ljuser?> - $name$_->{'points'} point$s
    "; + $ret .= "

    $total total supporting users, $count displayed.

    "; + $ret .= $navbar; + return $ret; + +_code?> + +Back to the support area. + +<=body +page?> +link: htdocs/admin/priv/index.bml, htdocs/support/index.bml + _c?> diff --git a/livejournal/htdocs/support/history.bml b/livejournal/htdocs/support/history.bml new file mode 100755 index 0000000..660cd83 --- /dev/null +++ b/livejournal/htdocs/support/history.bml @@ -0,0 +1,117 @@ +Support Request History +body<= +" unless $remote; + + # supporthelp anywhere lets them in + return "You are not authorized to view this page." + unless LJ::check_priv($remote, 'supporthelp'); + + my $ret; + if ($GET{user} || $GET{email} || $GET{userid}) { + my $dbr = LJ::get_db_reader(); + return "Failed to get database handle." + unless $dbr; + + my $reqlist; + if ($GET{user} || $GET{userid}) { + # get requests by a user, regardless of email (only gets user requests) + my $userid = $GET{userid} ? $GET{userid}+0 : LJ::get_userid(LJ::trim($GET{user})); + return "Invalid user to search on." unless $userid; + $reqlist = $dbr->selectall_arrayref('SELECT spid, subject, state, spcatid, requserid, timecreate, reqemail ' . + 'FROM support WHERE reqtype = \'user\' AND requserid = ?', + undef, $userid); + } elsif ($GET{email}) { + # try by email, note that this gets requests opened by users and anonymous + # requests, so we can view them all + my $email = LJ::trim($GET{email}); + return "Invalid email to search on." unless $email =~ /^.+\@.+$/; + $reqlist = $dbr->selectall_arrayref('SELECT spid, subject, state, spcatid, requserid, timecreate, reqemail ' . + 'FROM support WHERE reqemail = ?', + undef, $email); + } + + if (@{$reqlist || []}) { + # construct a list of people who have answered these requests + my @ids; + foreach (@$reqlist) { + next unless $_->[2] eq 'closed'; + push @ids, $_->[0]; + } + my $idlist = join ',', map { $_+0 } @ids; + my $winners = $dbr->selectall_arrayref('SELECT sp.spid, u.user, sp.points FROM useridmap u, supportpoints sp ' . + "WHERE u.userid = sp.userid AND sp.spid IN ($idlist)"); + my %points; + $points{$_->[0]+0} = [ $_->[1], $_->[2]+0 ] foreach @{$winners || []}; + + # now construct the request blocks + my %reqs; + my @userids; + foreach my $row (@$reqlist) { + $reqs{$row->[0]} = { + spid => $row->[0], + winner => $points{$row->[0]}->[0], + points => $points{$row->[0]}->[1]+0, + subject => LJ::ehtml($row->[1]), + state => $row->[2], + spcatid => $row->[3], + requserid => $row->[4], + timecreate => LJ::mysql_time($row->[5]), + reqemail => LJ::ehtml($row->[6]), + }; + push @userids, $row->[4] if $row->[4]; + } + my $us = LJ::load_userids(@userids) if @userids; + + # get categories + my $cats = LJ::Support::load_cats(); + + $ret .= '' . + ''; + foreach my $id (sort { $a <=> $b } keys %reqs) { + # verify user can see this category (public_read or has supportread in it) + next unless $cats->{$reqs{$id}->{spcatid}}{public_read} || + LJ::Support::can_read_cat($cats->{$reqs{$id}->{spcatid}}, $remote); + + # print out this request row + $ret .= ''; + $ret .= "\n"; + $ret .= "\n"; + $ret .= '\n"; + $ret .= "\n\n\n"; + $ret .= ''; + } + $ret .= '
    SummaryStateAnswered ByCategoryOpened ByTime Opened
    {spid}\">$reqs{$id}->{subject}$reqs{$id}->{state}'; + if ($reqs{$id}->{state} eq 'closed' && $reqs{$id}->{winner}) { + $ret .= LJ::ljuser($reqs{$id}->{winner}) . " ($reqs{$id}->{points})"; + } else { + $ret .= '-'; + } + $ret .= "$cats->{$reqs{$id}->{spcatid}}{catname}"; + $ret .= $reqs{$id}->{requserid} ? LJ::ljuser($us->{$reqs{$id}->{requserid}}) : $reqs{$id}->{reqemail}; + $ret .= "$reqs{$id}->{timecreate}


    '; + } else { + $ret .= "No results found for the search terms you entered.

    "; + } + } + + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= "
    Search for Requests
    By Email:
    By Username:
    By Userid:
    Please fill out only one of the search fields.
    "; + return $ret; + +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/support/index.bml b/livejournal/htdocs/support/index.bml new file mode 100755 index 0000000..badf818 --- /dev/null +++ b/livejournal/htdocs/support/index.bml @@ -0,0 +1,57 @@ +LiveJournal Support +body<= + + + + +1 +code=>0 +file=>support-currentproblems +_include?> + +0 +code=>0 +file=>support-links +_include?> + + + + +
      +
    • Read the Frequently Asked Questions
      +Try and solve the problem first by yourself before asking other people. You'll probably get the answer faster, too!
    • + +
    • Ask a question
      +Is your question not in the FAQ? Click "Ask a question" and you can submit a new support request and somebody in the LiveJournal community will read it and get back to you with an answer. If they don't help you, your support request stays open until somebody does help and you confirm that your problem is solved.
    • + +
    • Help somebody out
      +Got some extra time on your hands? Help out a LiveJournal user that has an open support request. Users that help other users out will get "support points" that will show up on your userinfo page. There are multiple reasons for helping other users out: + +
        +
      • Just to be nice
      • +
      • To get points just for fun and competition
      • +
      +

      If you're curious, check out the list of high scores, showing who helps the most.

      +

      If you want to be notified when new support requests come in, set your notification settings.

      + +
    • + +
    + + +<=body +page?> +link: htdocs/support/faq.bml, htdocs/support/submit.bml, htdocs/support/help.bml +link: htdocs/support/highscores.bml, htdocs/support/changenotify.bml + _c?> diff --git a/livejournal/htdocs/support/see_overrides.bml b/livejournal/htdocs/support/see_overrides.bml new file mode 100755 index 0000000..a8fad9f --- /dev/null +++ b/livejournal/htdocs/support/see_overrides.bml @@ -0,0 +1,60 @@ + +body<= +{'user'}); + return LJ::bad_input(BML::ml("error.malformeduser")) + unless $user; + + # check for privs + unless ($remote->{'user'} eq $user || + LJ::check_priv($remote, "supportviewscreened") || + LJ::check_priv($remote, "supporthelp")) { + + return LJ::bad_input(BML::ml(".error.noprivs")); + } + + # remote is authenticated, now load $u + my $u = $remote->{'user'} eq $user ? $remote : LJ::load_user($user); + return LJ::bad_input($ML{'error.username_notfound'}) + unless $u; + + # see if they're using s2 + LJ::load_user_props($u, "stylesys"); + return LJ::bad_input(BML::ml(".error.nos1", { 'user' => $user })) + if $u->{'stylesys'} == 2; + + ### no errors + + # no overrides? + return " $user}) . " p?>" + unless $u->{'useoverrides'} eq "Y"; + + # first, load the overrides if they use 'em: + my $overrides = LJ::S1::get_overrides($u); + LJ::text_out(\$overrides); + + # textarea + my $ret; + $ret .= " $user}) . " h1?>"; + $ret .= "
    "; + $ret .= LJ::html_textarea({ 'name' => 'overrides', 'style' => 'width: 100%', + 'cols' => '60', 'rows' => '16', 'wrap' => 'off', + 'value' => $overrides }); + $ret .= "
    "; + + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/support/see_request.bml b/livejournal/htdocs/support/see_request.bml new file mode 100755 index 0000000..6ea2480 --- /dev/null +++ b/livejournal/htdocs/support/see_request.bml @@ -0,0 +1,720 @@ +Request # +head<= + + +<=head +bodyopts=>onLoad="check_replytype();updateFaqLink();" +body<= + +'; + $sort = 'ASC'; + } + my $spcatand = ''; + if ($sp && ($find eq 'cnext' || $find eq 'cprev')) { + my $spcatid = $sp->{_cat}->{'spcatid'} + 0; + $spcatand = "AND spcatid=$spcatid"; + } else { + my @filter_cats = LJ::Support::filter_cats($remote, $cats); + return "" + unless @filter_cats; + my $cats_in = join(",", map { $_->{'spcatid'} } @filter_cats); + $spcatand = "AND spcatid IN ($cats_in)"; + } + my $clause = ""; + $clause = "AND spid$op$spid" unless ($find eq 'first' || $find eq 'last'); + my $dbr = LJ::get_db_reader(); + my ($foundspid) = $dbr->selectrow_array("SELECT spid FROM support WHERE state='open' $spcatand $clause ". + "ORDER BY spid $sort LIMIT 1"); + if ($foundspid) { + return BML::redirect("see_request.bml?id=$foundspid"); + } else { + my $goback = "Request #$spid p?>" if $sp; + my $what = $find eq 'next' || $find eq 'cnext' ? 'next' : 'previous'; + my $cat = "in the same category" if $find eq 'cnext' || $find eq 'cprev'; + return "$goback"; + } + } + + unless ($sp) { return ""; } + my $sth; + my $auth = $FORM{'auth'}; + + my $email = $sp->{'reqemail'}; + + my $u = {}; + my $clusterdown = 0; + if ($sp->{'reqtype'} eq "user") { + $u = LJ::load_userid($sp->{'requserid'}); + + # now do a check for a down cluster? + my $dbr = LJ::get_cluster_reader($u); + $clusterdown = 1 unless $dbr; + + $email = $u->{'email'}; + LJ::load_user_props($u, "s1_lastn_style", "s1_calendar_style", "s1_day_style", + "s1_friends_style", "stylesys", "s2_style", ) + unless $clusterdown; + } + + my $winner; # who closed it? + if ($sp->{'state'} eq "closed") { + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT u.user, sp.points FROM useridmap u, supportpoints sp ". + "WHERE u.userid=sp.userid AND sp.spid=?"); + $sth->execute($spid); + $winner = $sth->fetchrow_hashref; + } + + # load category this request is in + my $problemarea = $sp->{_cat}->{'catname'}; + my $catkey = $sp->{_cat}->{'catkey'}; + + unless (LJ::Support::can_read($sp, $remote, $auth)) { + return ""; + } + + # helper variables for commonly called methods + my $owner_mode = LJ::Support::can_close($sp, $remote, $auth) ? 1 : 0; + my $helper_mode = LJ::Support::can_help($sp, $remote) ? 1 : 0; + my $is_poster = LJ::Support::is_poster($sp, $remote, $auth) ? 1 : 0; + + # fix up the subject if needed + eval { + if ($sp->{'subject'} =~ /^=\?(utf-8)?/i) { + my @subj_data; + @subj_data = MIME::Words::decode_mimewords($sp->{'subject'}); + if (scalar(@subj_data)) { + if (!$1) { + $sp->{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$subj_data[0][0], -charset=>$subj_data[0][1]}); + } else { + $sp->{'subject'} = $subj_data[0][0]; + } + } + } + }; + + + ### request info table + + my $ret = ""; + $ret .= "\n"; + $ret .= "\n"; + + # uniq + if (LJ::check_priv($remote, 'sysban', 'uniq') || LJ::check_priv($remote, 'sysban', '*')) { + my $uniq = $props->{'uniq'} || "none"; + $ret .= "\n"; + } + + # account type + $ret .= "\n"; + + $ret .= "\n"; + $ret .= "\n"; + + my $timecreate = LJ::time_to_http($sp->{'timecreate'}); + my $age = LJ::ago_text(time() - $sp->{'timecreate'}); + $ret .= "\n"; + my $state = $sp->{'state'}; + if ($state eq "open") { + # check if it's still open or needing help or what + if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) { + # open, answered + $state = "answered (awaiting close)"; + } elsif ($sp->{'timelasthelp'} && $sp->{'timetouched'} > $sp->{'timelasthelp'}+5) { + # open, still needs help + $state = "answered (still needs help)"; + } else { + # default + $state = "open"; + } + } + if ($state eq "closed" && $winner && LJ::Support::can_see_helper($sp, $remote)) { + my $s = $winner->{'points'} > 1 ? "s" : ""; + my $wuser = $winner->{'user'}; + $state .= " ($winner->{'points'} point$s to "; + $state .= LJ::ljuser($wuser, { 'full' => 1 }) . ")"; + } + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    From:"; + if ($u->{'defaultpicid'} && $u->{'statusvis'} ne 'S') { + my %pic; + my $picid = $u->{'defaultpicid'}; + LJ::load_userpics(\%pic, [ $u, $picid ]); + $ret .= ""; + $ret .= "$u->{"; + $ret .= ""; + } + + # show requester name + email + { + my $visemail = $email; + if ($sp->{_cat}->{'public_read'}) { + $visemail =~ s/^.+\@/********\@/; + } + my $ename = $sp->{'reqtype'} eq 'user' ? LJ::ljuser($u) : LJ::ehtml($sp->{reqname}); + + # we show links to the history page if the user is a helper in this category or if it's a + # private category and the person has supporthelp somewhere (which is the general rule of + # thumb to use the history viewer) + my $show_history = !$sp->{_cat}->{public_read} && LJ::check_priv($remote, 'supporthelp'); + if ($helper_mode || $show_history) { + $ret .= $sp->{reqtype} eq 'user' ? + "$ename {user}\">$u->{name}" : + "$ename"; + $ret .= $owner_mode || $show_history ? + " ($visemail)" : + " ($visemail)"; + } else { + # default view + $ret .= "$ename ($visemail)"; + } + } + $ret .= "
    Uniq:$uniq
    Account type:"; + $ret .= LJ::name_caps($u->{'caps'}) || "Unknown"; + $ret .= "
    $LJ::SITENAMESHORT:"; + if ($clusterdown) { + $ret .= "" . + "(unable to connect to cluster, some data temporarily unavailable)
    "; + } + + # check isu because requests don't always come from users and sometimes we + # fake the user hash + if (LJ::isu($u) && $u->readonly) { + $ret .= "" . + "(this user is currently in read-only mode)
    "; + } + + + if ($u->{'userid'}) { + $ret .= "username: {'user'} ljuserf?>"; + $ret .= "
    style: "; + if ($u->{'stylesys'} == 2) { + $ret .= "(S2) "; + if ($u->{'s2_style'}) { + my $s2style = LJ::S2::load_style($u->{'s2_style'}); + my $pub = LJ::S2::get_public_layers(); # cached + foreach my $lay (sort { $a cmp $b } keys %{$s2style->{'layer'}}) { + my $lid = $s2style->{'layer'}->{$lay}; + $ret .= "$lay: "; + $ret .= (defined $pub->{$lid} ? 'public' : 'user') . ", "; + } + } else { + $ret .= "none"; + } + } else { + $ret .= "(S1) "; + foreach my $view (@LJ::views) { + my $styid = $u->{"s1_${view}_style"}; + my $viewuri = $view eq "lastn" ? "/users/$u->{'user'}/" : "/users/$u->{'user'}/$view"; + if ($view eq "day") { + my (undef,undef,undef,$dday,$dmon,$dyear) = localtime(time); $dyear+=1900; $dmon++; + $dmon = $dmon <= 9 ? "0$dmon" : $dmon; $dday = $dday <= 9 ? "0$dday" : $dday; + $viewuri = "/users/$u->{'user'}/$dyear/$dmon/$dday/"; + } + $ret .= "$view: $styid "; + } + if ($u->{'useoverrides'} eq 'Y') { + $ret .= "
    overrides: view "; + } + } + + # if the user has siteadmin:users or siteadmin:* show them link to resend validation email? + my $extraval = sub { + return '' unless LJ::check_priv($remote, 'siteadmin', 'users') || + LJ::check_priv($remote, 'siteadmin', '*'); + return " (resend validation email)"; + }; + + $ret .= "
    email validated? "; + if ($u->{'status'} eq "A") { $ret .= "yes"; } + if ($u->{'status'} eq "N") { $ret .= "no" . $extraval->(); } + if ($u->{'status'} eq "T") { $ret .= "transitioning (used to be validated, but changed email addresses and hasn't reconfirmed)" . $extraval->(); } + if ($u->{clusterid}) { $ret .= "
    cluster: " . LJ::get_cluster_description($u->{clusterid}, 1); } + $ret .= "
    data version: $u->{dversion}"; + $ret .= "
    underage? "; + if ($clusterdown) { + $ret .= "cluster unavailable"; + } else { + if ($u->underage) { + $ret .= "yes because of "; + $ret .= "birthday" if $u->underage_status eq 'Y'; + $ret .= "unique cookie" if $u->underage_status eq 'O'; + $ret .= "manual set" if $u->underage_status eq 'M'; + $ret .= ""; + } else { + $ret .= "no"; + if ($u->underage_status) { + $ret .= "; was by "; + $ret .= "birthday" if $u->underage_status eq 'Y'; + $ret .= "unique cookie" if $u->underage_status eq 'O'; + $ret .= "manual set" if $u->underage_status eq 'M'; + } + $ret .= ""; + } + } + + if (LJ::check_priv($remote, 'historyview')) { + $ret .= "
    view: "; + $ret .= "statushistory"; + } + } else { + $ret .= "not a user"; + } + $ret .= "
    Support category:"; + if (LJ::Support::can_read_cat($sp->{_cat}, $remote)) { + $ret .= "$problemarea"; + $ret .= " [previous|"; + $ret .= "next]"; + } else { + $ret .= $problemarea; + } + $ret .= "
    Time posted:$timecreate ($age)
    Status:$state"; + if ($owner_mode) { + $ret .= $sp->{'state'} eq "open" ? ", {'authcode'}'>close without credit" : ""; + if ($sp->{state} eq 'closed') { + my $permastatus = LJ::Support::is_locked($sp); + $ret .= $sp->{'state'} eq "closed" && !$permastatus ? + ", {'authcode'}'>reopen this request" : ""; + if (LJ::Support::can_lock($sp, $remote)) { + $ret .= $permastatus ? + ", unlock request" : + ", lock request"; + } + } + } + $ret .= "
    Summary:" . LJ::ehtml($sp->{'subject'}) . "
    \n"; + + ### end request info table + + LJ::run_hooks("support_see_request_html", { + 'u' => $u, + 'email' => $email, + 'sp' => $sp, + 'retref' => \$ret, + 'remote' => $remote, + }); + + # put in a "this is private!" box if this is a private request and the user viewing + # this page is the person who opened the request + if (!$sp->{_cat}->{public_read} && $is_poster) { + $ret .= "
    " . + "This is a private request. It is not publicly visible.
    "; + } + + my %userpics; # id -> {..} + + my @screened; + + ### reply loop + my $dbr = LJ::get_db_reader(); + $sth = $dbr->prepare("SELECT splid, timelogged, UNIX_TIMESTAMP()-timelogged AS 'age', type, faqid, userid, message " . + "FROM supportlog WHERE spid=? ORDER BY timelogged"); + $sth->execute($spid); + while (my $le = $sth->fetchrow_hashref) + { + next if ($le->{'type'} eq "internal" && ! (LJ::Support::can_read_internal($sp, $remote) || + ($remote && $remote->{'userid'} == $le->{'userid'} ))); + next if ($le->{'type'} eq "screened" && ! (LJ::Support::can_read_screened($sp, $remote) || + ($remote && $remote->{'userid'} == $le->{'userid'} ))); + + if ($le->{'type'} eq "screened") { + push @screened, $le; + } + + my $message = $le->{'message'}; + my %url; + my $urlN = 0; + + $message = LJ::ehtml($message); + $message =~ s/^\s+//; + $message =~ s/\s+$//; + $message =~ s/\n( +)/"\n" . "  "x length($1)/eg; + $message =~ s/\n/
    \n/g; + $message = LJ::auto_linkify($message); + + # special case: original request + if ($le->{'type'} eq "req") { + # insert support diagnostics from props + $message .= "Diagnostics: $props->{useragent}" if $props->{useragent}; + + $ret .= "
    \n"; + $ret .= "Original Request:
    \n"; + $ret .= "
    \n$message\n
    "; + next; + } + + # reply header + my $header = ""; + if ($le->{'userid'} && LJ::Support::can_see_helper($sp, $remote)) { + my $up = LJ::load_userid($le->{'userid'}); + my $picid = $up->{'defaultpicid'}; + $userpics{$picid} or LJ::load_userpics(\%userpics, [[ $up, $picid ]]); + $header = ""; + if ($picid && $up->{'statusvis'} ne 'S') { + $header .= ""; + } + $header .= "
    $up->{" . LJ::ljuser($up->{'user'}, { 'full' => 1 }); + if ($up->{'statusvis'} ne 'S') { + $header .= " - " . LJ::ehtml($up->{'name'}); + } + $header .= "
    \n" + } + + my $what = "Answer"; + if ($le->{'type'} eq "internal") { $what = "Internal Comment"; } + elsif ($le->{'type'} eq "comment") { $what = "Comment"; } + elsif ($le->{'type'} eq "screened") { $what = "Screened Response"; } + + $header .= "$what (\#$le->{'splid'})
    "; + my $timehelped = LJ::time_to_http($le->{'timelogged'}); + my $age = LJ::ago_text($le->{'age'}); + $header .= "Posted: $timehelped ($age)"; + if ($owner_mode && $sp->{'state'} eq "open" && $le->{'type'} eq "answer") { + $header .= ", {'authcode'};$le->{'splid'}'>credit fix here"; + } + + my $bordercolor = "#000000"; + if ($le->{'type'} eq "internal") { $bordercolor = "#ff0000"; } + if ($le->{'type'} eq "answer") { $bordercolor = "#00c000"; } + if ($le->{'type'} eq "screened") { $bordercolor = "#afaf00"; } + + # reply + $ret .= "$header
    \n"; + $ret .= "\n"; + $ret .= "
    \n"; + if ($le->{'faqid'}) { + # faq question + my $dbr = LJ::get_db_reader(); + my $sth = $dbr->prepare("SELECT question FROM faq WHERE faqid=?"); + $sth->execute($le->{'faqid'}); + my $faqname = $sth->fetchrow_array; + $ret .= "
    \n"; + # whitespace between these two DIVs is necessary for proper + # rendering in IE 5 for Mac OS < X + $ret .= "
    "; + $ret .= "FAQ Reference:
    $faqname
    \n"; + } + $ret .= "

    $message

    \n"; + $ret .= "
    \n"; + } + ### end reply loop + + # return if support item is closed + if ($sp->{'state'} eq "closed") { + return $ret; + } + + # underage users can't interact with this + return $ret if $remote && $remote->underage; + + $ret .= "

    Post a comment or solution:

    \n"; + + unless ($remote || $is_poster) { + $ret .= "You must login to help people out.\n"; + return $ret; + } + + unless (LJ::Support::can_append($sp, $remote, $auth)) + { + $ret .= "Sorry, you do not have access to answer people's support requests in this category.\n"; + return $ret; + } + + my @ans_type = LJ::Support::get_answer_types($sp, $remote, $auth); + my %ans_type = @ans_type; + + if ($ans_type{'answer'} || $ans_type{'screened'}) + { + $ret .= "Important Notes:"; + $ret .= "
      "; + $ret .= "
    • Before answering somebody's question, read the support guide.
    • "; + $ret .= "
    • Do NOT answer people if you're not sure of your answer. Don't answer if your solution is just a guess. Only answer if you really know what you're talking about ... guessing only makes other people in the support area think you might be right and spread the misinformation further, until it's accepted as truth.
    • "; + if ($LJ::LJDOTCOM) { + $ret .= "
    • Never recommend asking someone else, or somewhere else. That qualifies as not knowing the answer. If a support request is open for a day or two, one of the support leaders will find out the answer and reply, and likely post about it in so all the support people will know the answer in the future.
    • "; + } + $ret .= "
    Thanks! standout?>\n"; + } + + # append_request form + + $ret .= "
    \n"; + + # hidden values + $ret .= LJ::html_hidden('spid', $spid, 'auth', $auth) . "\n"; + + # form + $ret .= "\n"; + $ret .= "\n"; + + if ($ans_type{'answer'} || $ans_type{'screened'}) + { + my $dbr = LJ::get_db_reader(); + # FAQ reference + $ret .= "\n"; + } + + # answer type + { + $ret .= "\n"; + } + + # helpers can do actions: + if (LJ::Support::can_perform_actions($sp, $remote) && ! $is_poster) + { + $ret .= "\n"; + if ($sp->{'timelasthelp'} > ($sp->{'timetouched'}+5)) { + $ret .= "\n"; + } else { + $ret .= "\n"; + } + if (LJ::Support::can_change_summary($sp, $remote)) { + $ret .= "\n"; + $ret .= "\n"; + } + } + # Prefill an e-mail validation nag, if needed. + my $validationnag; + if (!(LJ::isu($u) && ($u->underage && $u->{'status'} eq 'T')) && + ($u->{'status'} eq "N" || $u->{'status'} eq "T") && + ! $is_poster) { + my $reminder = LJ::load_include('validationreminder'); + $validationnag .= "\n\n$reminder" if $reminder; + } + + # add in canned answers if there are any for this category and the user can use them + if ($helper_mode && ! $is_poster) { + my $rows = $dbr->selectall_arrayref('SELECT subject, body FROM support_answers WHERE spcatid = ? ORDER BY subject', + undef, $sp->{_cat}->{spcatid}); + if ($rows && @$rows) { + $ret .= ""; + } + } + + # textarea for their message body + $ret .= "
    From:"; + if ($remote && $remote->{'userid'}) { + $ret .= "{'user'} ljuser?>"; + } else { + $ret .= "(not logged in)"; + } + $ret .= "
    Reference FAQ:\n"; + + my %faqcat; + my %faqq; + $sth = $dbr->prepare("SELECT faqcat, faqcatname, catorder FROM faqcat WHERE faqcat<>'int-abuse'"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $faqcat{$_->{'faqcat'}} = $_; + } + + $sth = $dbr->prepare("SELECT faqid, question, sortorder, faqcat, lastmodtime FROM faq WHERE faqcat<>'int-abuse'"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $faqq{$_->{'faqid'}} = $_; + } + + my @faqlist = ('0', "(don't reference FAQ)"); + foreach my $faqcat (sort { $faqcat{$a}->{'catorder'} <=> $faqcat{$b}->{'catorder'} } keys %faqcat) + { + push @faqlist, ('0', "[ $faqcat{$faqcat}->{'faqcatname'} ]"); + foreach my $faqid (sort { $faqq{$a}->{'sortorder'} <=> $faqq{$b}->{'sortorder'} } + grep { $faqq{$_}->{'faqcat'} eq $faqcat } keys %faqq) + { + next unless ($faqq{$faqid}->{'question'}); + my $q = "... $faqq{$faqid}->{'question'}"; + $q =~ s/^\s+//; + $q =~ s/\s+$//; + $q =~ s/\n/ /g; + if (length($q) > 50) { + $q = substr($q, 0, 50) . "..."; + } + push @faqlist, ($faqid, $q); + } + } + $ret .= LJ::html_select({ 'name' => 'faqid', 'onchange' => 'updateFaqLink()' }, @faqlist) . "\n"; + $ret .= qq(); + $ret .= "
    Reply Type:"; + + # if less than 2, remote is the person filing the request + # so all they can do is add more info + if (@ans_type > 2) { + $ret .= LJ::html_select({ 'name' => 'replytype', + 'onchange' => "check_replytype()" }, + @ans_type) . "\n"; + $ret .= ""; + } else { + $ret .= LJ::html_hidden('replytype', $ans_type[0]) . "\n"; + $ret .= "$ans_type[1]"; + } + $ret .= "
    \n"; + + $ret .= ""; + + $ret .= ""; + + if (@screened && $helper_mode) { + $ret .= ""; + } + $ret .= "
    Change Category:
    "; + $ret .= LJ::html_select({ 'name' => 'changecat' }, + ('', $sp->{'_cat'}->{'catname'}), + map { $_->{'spcatid'}, "---> $_->{'catname'}" } + LJ::Support::sorted_cats($cats)); + $ret .= "
    Approve Screened Response:
    "; + $ret .= LJ::html_select({ 'name' => 'approveans' }, + ('', ''), + map { $_->{'splid'}, "\#$_->{'splid'} (" . LJ::get_username($_->{'userid'}) . ")" } + @screened); + $ret .= LJ::html_select({ 'name' => 'approveas' }, + ("answer" => "as answer", "comment" => "as comment",)); + $ret .= "
    \n"; + + $ret .= "
    Put in Queue:"; + $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'touch' }); + $ret .= "\n"; + $ret .= "
    Take out of Queue:"; + $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'untouch' }); + $ret .= "\n"; + $ret .= "
    Change summary:"; + $ret .= LJ::html_check({ 'type' => 'checkbox', 'name' => 'changesum' }); + $ret .= LJ::html_text({ 'type' => 'text', 'name' => 'summary', 'size' => '50', 'maxlength' => '80', 'value' => $sp->{'subject'} }); + $ret .= "
     "; + $ret .= "\n"; + $ret .= "
    Stock answers:\n"; + $ret .= "\n"; + $ret .= "
    Message:"; + $ret .= LJ::html_textarea({ 'rows' => '12', 'cols' => '80', 'wrap' => 'virtual', 'id' => 'body', 'name' => 'body', 'value' => $validationnag }) . "
    "; + $ret .= "URLs are automatically link-ified, so just reference those. de?>
    "; + $ret .= LJ::html_submit('submitpost', "Post Comment/Solution"); + $ret .= "
    \n"; + + $ret .= "
    \n"; + + return $ret; + +} +_code?> + +previous open request, " . + "next open request" +} +_code?> +
    +Back to the list of open requests.
    +Back to the support area. + +<=body +page?> +link: htdocs/support/faqbrowse.bml, htdocs/styles/browse/styleinfo.bml +link: htdocs/support/help.bml, htdocs/support/act.bml, htdocs/login.bml +link: htdocs/guide/support.bml, htdocs/support/faq.bml, htdocs/support/index.bml +link: htdocs/allpics.bml +img: htdocs/userpic +post: htdocs/support/append_request.bml + _c?> diff --git a/livejournal/htdocs/support/stock_answers.bml b/livejournal/htdocs/support/stock_answers.bml new file mode 100755 index 0000000..5a82f99 --- /dev/null +++ b/livejournal/htdocs/support/stock_answers.bml @@ -0,0 +1,207 @@ +Support Stock Answers +body<= +" unless $remote; + + # most things have a category id + my $spcatid = ($GET{spcatid} || $POST{spcatid} || 0) + 0; + my $cats = LJ::Support::load_cats(); + return "" + unless !$spcatid || $cats->{$spcatid}; + + # editing is based on ability to grant supporthelp. and throw an error if they + # posted but can't edit. + my $canedit = ($spcatid && LJ::check_priv($remote, 'admin', "supporthelp/$cats->{$spcatid}->{catkey}")) || + LJ::check_priv($remote, 'admin', 'supporthelp') || + LJ::check_priv($remote, 'admin', '*'); + return "" + if LJ::did_post() && ! $canedit; + + # viewing is based on having supporthelp over the particular category you're viewing. + my %canview; # spcatid => 0/1 + foreach my $cat (values %$cats) { + $canview{$cat->{spcatid}} = 1 + if LJ::Support::can_help({ _cat => $cat }, $remote); + } + return "" + unless %canview; + return "" + if $spcatid && ! $canview{$spcatid}; + + # filter down the category list + $cats = { map { $_->{spcatid}, $_ } grep { $canview{$_->{spcatid}} } values %$cats }; + + my $ansid = ($GET{ansid} || 0) + 0; + + my $ret = ""; + my $self = "$LJ::SITEROOT/support/stock_answers.bml"; + + if ($POST{'action:delete'}) { + my $dbh = LJ::get_db_writer(); + return "" + unless $dbh; + + my $ct = $dbh->do("DELETE FROM support_answers WHERE ansid = ? AND spcatid = ?", + undef, $ansid, $spcatid); + return "errstr . " p?>" if $dbh->err; + return "" unless $ct; + return BML::redirect("$self?spcatid=$spcatid&deleted=1"); + } + + if ($POST{'action:new'} || $POST{'action:save'}) { + my ($subj, $body) = ($POST{subject}, $POST{body}); + + foreach my $ref (\$subj, \$body) { + $$ref =~ s/^\s+//; + $$ref =~ s/\s+$//; + # FIXME: more stuff to clean it up? + } + + return "" + unless $spcatid && $subj && $body; + + my $dbh = LJ::get_db_writer(); + return "" + unless $dbh; + + if ($POST{'action:new'}) { + my $newid = LJ::alloc_global_counter('A'); + return "" + unless $newid; + + $dbh->do("INSERT INTO support_answers (ansid, spcatid, subject, body, lastmodtime, lastmoduserid) " . + "VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?)", + undef, $newid, $spcatid, $subj, $body, $remote->{userid}); + return "errstr . " p?>" if $dbh->err; + + return BML::redirect("$self?user=$remote->{user}&spcatid=$spcatid&ansid=$newid&added=1"); + } else { + return "" unless $ansid; + + $dbh->do("UPDATE support_answers SET subject = ?, body = ?, lastmodtime = UNIX_TIMESTAMP(), " . + "lastmoduserid = ? WHERE ansid = ?", undef, + $subj, $body, $remote->{userid}, $ansid); + return "errstr . " p?>" if $dbh->err; + + return BML::redirect("$self?user=$remote->{user}&spcatid=$spcatid&ansid=$ansid&saved=1"); + } + } + + if ($GET{new}) { + $ret .= "
    "; + + $ret .= ""; + $ret .= " 'spcatid', selected => $spcatid }, + 0, "( please select )", + map { $_, $cats->{$_}->{catname} } + grep { $canview{$_} } + sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} } + keys %$cats) . "
    "; + $ret .= "Subject: " . LJ::html_text({ name => 'subject', maxlength => 255, size => 40 }) . "
    "; + $ret .= LJ::html_textarea({ name => 'body', rows => 15, cols => 80 }) . "
    "; + $ret .= LJ::html_submit('action:new', "Save Answer"); + $ret .= "
    p?>"; + + return $ret; + } + + my $dbr = LJ::get_db_reader(); + return "" unless $dbr; + + my $cols = "ansid, spcatid, subject, lastmodtime, lastmoduserid"; + $cols .= ", body" if $ansid; + + my $sql = "SELECT $cols FROM support_answers"; + my @bind = (); + + if ($spcatid || $ansid) { + $sql .= " WHERE "; + if ($spcatid) { + $sql .= "spcatid = ?"; + push @bind, $spcatid; + } + if ($ansid) { + $sql .= ($spcatid ? " AND " : "") . "ansid = ?"; + push @bind, $ansid; + } + } + + my $sth = $dbr->prepare($sql); + $sth->execute(@bind); + return "errstr . " p?>" if $sth->err; + + $ret .= "
    "; + $ret .= " 'spcatid', selected => $spcatid }, + 0, "( none )", + map { $_, $cats->{$_}->{catname} } + sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} } keys %$cats); + $ret .= LJ::html_submit(undef, "Show") . "
    p?>"; + + my %answers; + while (my $row = $sth->fetchrow_hashref) { + $answers{$row->{spcatid}}->{$row->{ansid}} = { + subject => $row->{subject}, + body => $row->{body}, + lastmodtime => $row->{lastmodtime}, + lastmoduser => LJ::load_userid($row->{lastmoduserid}), + }; + } + + $ret .= "View All ]"; + $ret .= " [ Add New Answer ]" if $canedit; + $ret .= " p?>"; + + if ($GET{added}) { + $ret .= "Answer added! p?>"; + } elsif ($GET{saved}) { + $ret .= "Changes saved! p?>"; + } elsif ($GET{deleted}) { + $ret .= "Answer deleted! p?>"; + } + + # bilevel sort, fun and messy + foreach my $spcatid (sort { $cats->{$a}->{catname} cmp $cats->{$b}->{catname} } keys %$cats) { + next unless %{$answers{$spcatid} || {}}; + + $ret .= "$cats->{$spcatid}->{catname} h2?>"; + $ret .= "
      "; + foreach my $ansid (sort { + $answers{$spcatid}->{$a}->{subject} cmp $answers{$spcatid}->{$b}->{subject} + } keys %{$answers{$spcatid}}) { + my ($subj, $body, $lmu, $lmt) = + map { $answers{$spcatid}->{$ansid}->{$_} } qw(subject body lastmoduser lastmodtime); + if ($body) { + $ret .= "
    • "; + $ret .= "
      "; + $ret .= LJ::html_text({ name => 'subject', value => $subj, size => 40, maxlength => 255 }); + $ret .= "
      "; + $ret .= LJ::html_textarea({ name => 'body', value => $body, rows => 15, cols => 80 }); + $ret .= "
      "; + $ret .= "Last modified by " . LJ::ljuser($lmu) . " on " . LJ::mysql_time($lmt) . ".
      "; + if ($canedit) { + $ret .= LJ::html_submit('action:save', "Save Changes"); + $ret .= LJ::html_submit('action:delete', "Delete Answer", + { onClick => 'return confirm("Are you sure you want to delete this stock answer?");' }); + } + $ret .= "
    • "; + } else { + $ret .= "
    • $subj
    • "; + } + } + $ret .= "
    "; + } + + + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/support/submit.bml b/livejournal/htdocs/support/submit.bml new file mode 100755 index 0000000..18db2a5 --- /dev/null +++ b/livejournal/htdocs/support/submit.bml @@ -0,0 +1,96 @@ +Submit Support Request +body<= + +1 +code=>0 +file=>support-currentproblems +_include?> + +

    From here you can ask a question about . Make sure you've already checked the Frequently Asked Questions.

    + +
    + +{'userid'}+0; + $u = LJ::load_userid($userid); + + foreach (qw(user name)) { + $eh{$_} = LJ::ehtml($u->{$_}); + } + + $eh{'password'} = "_REMOTE"; + } + + $ret .= <<"END"; +

    Your name:
    +

    +

    Are you a $LJ::SITENAMESHORT user?
    + + + + + + + +
    Yes.
    Username: Password:
    +
    No.
    Your email address: (not shown to the public)
    +END + + return $ret; + +_code?> + +

    Problem Area
    +Select what in particular you're having a problem with: +

    + +

    Problem summary
    +Enter a descriptive one-line summary of the problem you're having. A good example would be "Client crashes in friends dialog". A bad example would be "URGENT! plz hlp me!!!! THX!!!". +

    + +

    + +

    Problem
    +And finally, enter your support request. If you want an intelligent fast answer, please provide as much detail as possible. The only rule is do NOT GIVE OUT YOUR PASSWORD because many people could read this request, not just staff. +

    + +

    + +

    Done?
    When done, press .

    + + +

    Back to the support area.

    + +<=body +page?> +link: htdocs/support/faq.bml, htdocs/support/index.bml +post: htdocs/support/submit_do.bml + _c?> diff --git a/livejournal/htdocs/support/submit_do.bml b/livejournal/htdocs/support/submit_do.bml new file mode 100755 index 0000000..0af3855 --- /dev/null +++ b/livejournal/htdocs/support/submit_do.bml @@ -0,0 +1,81 @@ +Submit Request +body<= + +{'r'}; + + my @errors = (); + + unless (LJ::did_post() && LJ::check_referer('/support/submit.bml')) { push @errors, ""; } + + my $u; + my $user; + my $remote; + + my %req; # the request we're building to submit + + if ($POST{'reqtype'} eq "user") + { + $req{'reqtype'} = "user"; + $user = LJ::canonical_username($POST{'user'}); + if ($POST{'password'} eq "_REMOTE") { + $remote = LJ::get_remote(); + if ($remote && $remote->{'user'} eq $user) { + $u = LJ::load_user($remote->{'user'}); + $req{'requserid'} = $remote->{'userid'}; + } + } + unless ($req{'requserid'}) { + $u = LJ::load_user($user); + push @errors, "Invalid username" unless $u; + if (LJ::auth_okay($u, $POST{'password'}, $POST{'hpassword'})) { + $req{'requserid'} = $u->{'userid'}; + } else { + push @errors, "Invalid password"; + } + } + $req{'reqemail'} = $u->{'email'}; + } + elsif ($POST{'reqtype'} eq "email") + { + $req{'reqtype'} = "email"; + $req{'reqemail'} = $POST{'email'}; + + LJ::check_email($POST{'email'}, \@errors); + } + + $req{'reqname'} = $POST{'reqname'}; + $req{'body'} = $POST{'message'}; + $req{'subject'} = $POST{'subject'}; + $req{'spcatid'} = $POST{'spcatid'}; + $req{'uniq'} = $r->notes('uniq'); + + # insert diagnostic information + $req{useragent} = BML::get_client_header('User-Agent') + if $LJ::SUPPORT_DIAGNOSTICS{track_useragent}; + + return LJ::bad_input(@errors) if @errors; + my $spid = LJ::Support::file_request(\@errors, \%req); + return LJ::bad_input(@errors) if @errors; + + my $url = "$LJ::SITEROOT/support/see_request.bml?id=$spid"; + + return "Your $LJ::SITENAMESHORT support request has been filed and will be answered as soon as possible. Your request tracking number is $spid. You can track its progress here: "; +} +_code?> + + +

    Back to the support area.

    + +<=body +page?> +link: htdocs/support/see_request.bml, htdocs/support/index.bml + _c?> diff --git a/livejournal/htdocs/syn/index.bml b/livejournal/htdocs/syn/index.bml new file mode 100755 index 0000000..bad31b7 --- /dev/null +++ b/livejournal/htdocs/syn/index.bml @@ -0,0 +1,241 @@ + +body<= + +"; + } + return "" if $u->{'statusvis'} eq "S"; + + if (LJ::did_post() && $POST{'userid'} != $u->{'userid'}) { + return ""; + } + + my $error = sub { + return " '/syn/', 'text' => $ML{'.back'}}) . " p?>"; + }; + + # add custom feed + if ($POST{'action:addcustom'} || $GET{'url'}) { + my $acct = LJ::trim($POST{'acct'}); + my $url = LJ::trim($POST{'synurl'} || $GET{'url'}); + + if ($acct ne "") { + return $error->($ML{'.invalid.accountname'}) + if $acct && $acct !~ /^\w{3,15}$/; + foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) { + next unless ($acct =~ /$re/); + return $error->($ML{'.invalid.reserved'}); + } + } + if ($url ne "") { + return $error->($ML{'.invalid.url'}) + unless $url =~ m!^http://(.+?)(?::(\d+))?/!; + my $hostname = $1; + my $port = $2; + return $error->($ML{'.invalid.cantadd'}) + if $hostname =~ /\Q$LJ::DOMAIN\E/i; + + return $error->($ML{'.invalid.port'}) + if defined $port && $port != 80 && $port < 1024; + $url =~ s/:80// if $port == 80; + } + + my $su; # account to add + if ($url) { + $su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE s.synurl=? AND s.userid=u.userid", + undef, $url); + + unless ($su) { + # check cap to create new feeds + return $error->($ML{'.error.nocreate'}) + unless LJ::get_cap($u, 'synd_create'); + + # if no account name, give them a proper entry form to pick one, but don't reprompt + # for the url, just pass that through (we'll recheck it anyway, though) + unless ($acct) { + my $ret .= ""; + $ret .= "
    "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}, 'synurl', $url); + $ret .= "
    "; + $ret .= "

    $ML{'.account'} "; + $ret .= "

    "; + $ret .= "

    "; + return $ret; + } + + return "" + unless $acct; + + # create a safeagent to fetch the feed for validation purposes + require LWPx::ParanoidAgent; + my $ua = LWPx::ParanoidAgent->new( + timeout => 7, + max_size => (1024 * 300), + ); + $ua->agent("$LJ::SITENAME ($LJ::ADMIN_EMAIL; Initial check)"); + + my $res = $ua->get($url); + my $content = $res && $res->is_success ? $res->content : undef; + return "" + unless $content; + + my $syn_url; + # analyze link/meta tags + while ($content =~ m!<(link|meta)\b([^>]+)>!g) { + my ($type, $val) = ($1, $2); + # RSS/Atom + # + if ($type eq "link" && + $val =~ m!rel=.alternate.!i && + $val =~ m!type=.application/(?:rss|atom)\+xml.!i && + $val =~ m!href=[\"\']([^\"\']+)[\"\']!i) { + $syn_url = $1; + } + } + + $res = $ua->get($syn_url); + $content = $res && $res->is_success ? $res->content : ""; + + # check whatever we did get for validity (or pseudo-validity) + return "" + unless $content =~ m/<(\w+:)?(?:rss|feed|RDF)/; # Must have a <[?:]rss <[?:]feed (for Atom support) <[?:]RDF + + # create the feed account + my $id = LJ::create_account({ + 'user' => $acct, + 'name' => $acct, + 'password' => '', + 'caps' => $LJ::SYND_CAPS, + 'cluster' => $LJ::SYND_CLUSTER, + }); + return "" + unless $id; + + LJ::update_user($id, { journaltype => 'Y' }); + $dbh->do("INSERT INTO syndicated (userid, synurl, checknext) VALUES (?,?,NOW())", + undef, $id, $url); + + LJ::statushistory_add($u->{'userid'}, $id, "synd_create", "acct: $acct"); + + $su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE s.userid=? AND s.userid=u.userid", + undef, $id); + } + } elsif ($acct) { + # account but no URL, we can add this in any case + $su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ". + "WHERE u.userid=s.userid AND u.user=?", + undef, $acct); + unless ($su) { + return $error->($ML{'.invalid.notexist'}); + } + } else { + # need at least a URL + return $error->($ML{'.invalid.needurl'}); + } + + return $error->($ML{'.error.unknown'}) unless $su; + + # at this point, we have a new account, or an old account, but we have an account, so + # let's redirect them to the add page + return BML::redirect("$LJ::SITEROOT/friends/add.bml?user=$su->{user}"); + + # TAG:FR:bml_syn:count_friendofs + my $count = $dbh->selectrow_array("SELECT COUNT(*) FROM friends WHERE friendid=?", undef, + $su->{'userid'}); + LJ::add_friend($u->{'userid'}, $su->{'userid'}, { 'defaultview' => 1 }); + } + + # get most popular feeds from memcache + my $popsyn = LJ::Syn::get_popular_feeds(); + + # load user's friends so we can strip feeds they already watch + my $friends = LJ::get_friends($u) || {}; + + # populate @pop and add users they've chosen to add + my @pop; + my %urls; + my %names; + for (0 .. 99) { + next if not defined $popsyn->[$_]; + my ($user, $name, $suserid, $url, $count) = @{ $popsyn->[$_] }; + $names{$user} = $name; + + my $suser = LJ::load_userid($suserid); + LJ::load_user_props($suser, 'url'); + $urls{$user} = $suser->{url}; + + # skip suspended/deleted accounts, already watched feeds + next if $friends->{$suserid} || $suser->{'statusvis'} ne "V"; + + if ($POST{'action:add'} && $POST{"add_$user"}) { + LJ::add_friend($u->{'userid'}, $suserid, { 'defaultview' => 1 }); + } else { + push @pop, [ $user, $url, $count ]; + last if @pop >= 20; + } + } + + # intro paragraph + my $title = BML::ml('.using.title', {'sitename' => $LJ::SITENAME}); + my $ret = ""; + + $ret .= "
    "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}); + + if (@pop) { + $ret .= ""; + $ret .= "

    "; + $ret .= ""; + $ret .= ""; + foreach (@pop) { + my ($user, $url, $count) = @$_; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } else { + $ret .= "$names{$user}"; + } + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= ""; + $ret .= "
    $ML{'.table.account'}$ML{'.table.feed'}$ML{'.table.watchers'}
    "; + $ret .= LJ::ljuser($user, { 'type' => 'Y' }) . ""; + if ($urls{$user}) { + my $displayurl = $urls{$user}; + $displayurl = substr($urls{$user}, 0, 50) . "..." if length $displayurl > 60; + $ret .= "$names{$user}
    $displayurl
    " . LJ::img('xml', '', { border => 0 }) . "$count
    "; + $ret .= ""; + $ret .= "
    "; + } + + $ret .= "

    "; + $ret .= LJ::html_hidden("userid", $u->{'userid'}); + + $ret .= ""; + $ret .= "
    "; + $ret .= "

    $ML{'.feed.url'} "; + $ret .= "

    "; + $ret .= "

    "; + + $ret .= "
    "; + + return $ret; +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/syn/list.bml b/livejournal/htdocs/syn/list.bml new file mode 100755 index 0000000..f9be51e --- /dev/null +++ b/livejournal/htdocs/syn/list.bml @@ -0,0 +1,60 @@ + +body<= + $user, 'name' => $name, 'numreaders' => $count, 'synurl' => $url }; + } + + # Query already defaults to "numreaders" sort + if ($GET{'sort'} eq "username") { + @data = sort { $a->{'user'} cmp $b->{'user'} } @data; + } + if ($GET{'sort'} eq "feeddesc") { + @data = sort { $a->{'name'} cmp $b->{'name'} } @data; + } + + return "" unless @data; + + my %items = BML::paging(\@data, $GET{'page'}, 100); + my $navbar = LJ::paging_bar($items{'page'}, $items{'pages'}); + @data = @{$items{'items'}}; + + $ret .= $navbar . ""; + $ret .= $GET{'sort'} eq "username" ? "": + "": + "": + ""; + foreach (@data) { + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + $ret .= ""; + } + $ret .= "
    " . $ML{'.username'} . " "username"}) . "'>" . $ML{'.username'} . ""; + $ret .= $GET{'sort'} eq "feeddesc" ? "" . $ML{'.feeddesc'} . " "feeddesc"}) . "'>" . $ML{'.feeddesc'} . ""; + $ret .= $GET{'sort'} eq "numreaders" ? "" . $ML{'.numreaders'} . " "numreaders"}) . "'>" . $ML{'.numreaders'} . ""; + $ret .= " 
    " . LJ::ljuser($_->{'user'}, { 'type' => 'Y' }) . "" . LJ::ehtml($_->{'name'}) . "" . $_->{'numreaders'} . "". + "$ML{
    " . $navbar; + return $ret; + +_code?> +<=body +head<= + +<=head +page?> diff --git a/livejournal/htdocs/syn/raw.bml b/livejournal/htdocs/syn/raw.bml new file mode 100755 index 0000000..fd696b6 --- /dev/null +++ b/livejournal/htdocs/syn/raw.bml @@ -0,0 +1,17 @@ + diff --git a/livejournal/htdocs/talkmulti.bml b/livejournal/htdocs/talkmulti.bml new file mode 100755 index 0000000..424601e --- /dev/null +++ b/livejournal/htdocs/talkmulti.bml @@ -0,0 +1,101 @@ +"; + return; + }; + + my $mode = $POST{'mode'}; + if ($mode eq 'screen') { + $title = $ML{'.title.screen'}; + } elsif ($mode eq 'unscreen') { + $title = $ML{'.title.unscreen'}; + } elsif ($mode eq 'delete') { + $title = $ML{'.title.delete'}; + } else { + $title = $ML{'Error'}; + return $err->($ML{'.error.invalid_mode'}); + } + + my $sth; + + my $remote = LJ::get_remote(); + return $err->($ML{'.error.login'}) unless $remote; + return $err->("") unless LJ::did_post(); + + my @talkids; + foreach (keys %POST) { + push @talkids, $1 if /^selected_(\d+)$/; + } + return $err->($ML{'.error.none_selected'}) unless @talkids; + + my $u = LJ::load_user($POST{'journal'}); + return $err->($ML{'talk.error.bogusargs'}) unless $u && $u->{'clusterid'}; + return $err->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + + my $jid = $u->{'userid'}; + my $ditemid = $POST{'ditemid'}+0; + my $commentlink = LJ::journal_base($u) . "/$ditemid.html"; + my $itemid = $ditemid >> 8; + my $log = $dbcr->selectrow_hashref("SELECT * FROM log2 WHERE journalid=? AND jitemid=?", + undef, $jid, $itemid); + return $err->($ML{'.error.inconsistent_data'}) unless $log && $log->{'anum'} == ($ditemid & 255); + my $up = LJ::load_userid($log->{'posterid'}); + + # check permissions + return $err->($ML{'.error.privs.screen'}) + if $mode eq "screen" && ! LJ::Talk::can_screen($remote, $u, $up); + return $err->($ML{'.error.privs.unscreen'}) + if $mode eq "unscreen" && ! LJ::Talk::can_unscreen($remote, $u, $up); + return $err->($ML{'.error.privs.delete'}) + if $mode eq "delete" && ! LJ::Talk::can_delete($remote, $u, $up); + + # filter our talkids down to those that are actually attached to the log2 + # specified. also, learn the state of all the items. + my $in = join (',', @talkids); + $sth = $dbcr->prepare("SELECT jtalkid, state FROM talk2 ". + "WHERE journalid=? AND jtalkid IN ($in) ". + "AND nodetype='L' AND nodeid=?"); + $sth->execute($jid, $itemid); + my %state; + while (my ($id, $state) = $sth->fetchrow_array) { + $state{$id} = $state; + } + @talkids = keys %state; + + # do the work: + if ($mode eq "delete") { + # first, unscreen everything for replycount and hasscreened to adjust + my @unscreen = grep { $state{$_} eq "S" } @talkids; + LJ::Talk::unscreen_comment($u, $itemid, @unscreen); + # FIXME: race condition here... somebody could get lucky and view items while unscreened. + # then delete, updating the log2 replycount as necessary + my $num = LJ::delete_comments($u, "L", $itemid, @talkids); + LJ::replycount_do($u, $itemid, "decr", $num); + LJ::Talk::update_commentalter($u, $itemid); + $body = "$commentlink}) . " p?>"; + return; + + } elsif ($mode eq "unscreen") { + LJ::Talk::unscreen_comment($u, $itemid, @talkids); + $body = "$commentlink}) . " p?>"; + return; + + } elsif ($mode eq "screen") { + LJ::Talk::screen_comment($u, $itemid, @talkids); + $body = "$commentlink}) . " p?>"; + return; + } +} +_code?> + +body=> +page?> + _c?> diff --git a/livejournal/htdocs/talkpost.bml b/livejournal/htdocs/talkpost.bml new file mode 100755 index 0000000..aeb8e9b --- /dev/null +++ b/livejournal/htdocs/talkpost.bml @@ -0,0 +1,319 @@ + tags + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + my $errtxt; + + my $pics = LJ::Talk::get_subjecticons(); + + my $r = Apache->request; + $r->notes("codepath" => "bml.talkpost"); + + my $uri = BML::get_uri(); + + if ($uri =~ m!/(\d+)\.html$!) { + $FORM{'itemid'} = $1 unless $FORM{'replyto'} > 0; + $FORM{'journal'} = $r->notes("_journal"); + BML::set_language_scope("/talkpost.bml"); + } + + my $init = LJ::Talk::init(\%FORM); + return "{'error'} p?>" if $init->{'error'}; + + my $u = $init->{'journalu'}; + return $ML{'talk.error.nojournal'} unless $u; + + $r->notes("journalid" => $u->{'userid'}); + return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly"); + + my $dbcr = LJ::get_cluster_def_reader($u); + + return $LJ::MSG_READONLY_USER if $LJ::CLUSTER_DOWN{0} || ! $dbcr; + + # redirect if account was renamed + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + if ($u->{'renamedto'} ne "") { + my $id = $FORM{'itemid'}+0; + return BML::redirect(LJ::journal_base($u->{'renamedto'}) . "/$id.html?mode=reply"); + } + } + + my $ret = ""; + + my $parpost; + my $reply; + + if ($init->{'replyto'}) + { + my $qparentid = $init->{'replyto'}; + + my $sql = "SELECT t.posterid, t.nodetype, t.nodeid AS 'itemid', ". + "UNIX_TIMESTAMP()-UNIX_TIMESTAMP(t.datepost) AS 'secondsold', ". + "t.state, l.anum FROM talk2 t, log2 l WHERE l.journalid=$u->{'userid'} AND ". + "l.jitemid=t.nodeid AND t.journalid=$u->{'userid'} AND t.jtalkid=$qparentid"; + foreach my $pass (1, 2) { + my $db = $pass == 1 ? LJ::get_cluster_reader($u) : $dbcr; + $parpost = $db->selectrow_hashref($sql); + last if $parpost; + } + return $ML{'.error.noreplypost'} unless $parpost; + + unless ($parpost->{'nodetype'} eq "L" && $parpost->{'itemid'}) { + return ""; + } + + ## load its text + { + my $tt = LJ::get_talktext2($u, $init->{'replyto'}); + $parpost->{'subject'} = $tt->{$init->{'replyto'}}->[0]; + $parpost->{'body'} = $tt->{$init->{'replyto'}}->[1]; + } + + ### load the talk properties + + LJ::load_talk_props2($u->{'userid'}, [ $init->{'replyto'} ], {$init->{'replyto'} => $parpost}); + + if($LJ::UNICODE && $parpost->{'unknown8bit'}) { + LJ::item_toutf8($u, \$parpost->{'subject'}, \$parpost->{'body'}, {}); + } + + $init->{'itemid'} = $parpost->{'itemid'}; + $init->{'ditemid'} = $parpost->{'itemid'}*256 + $parpost->{'anum'}; + } + + my $itemid = $init->{'itemid'}; + + my $stylemine = $init->{'style'} eq "mine" ? "style=mine" : ""; + + ## load the journal item + my $item = LJ::Talk::get_journal_item($u, $itemid); + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + return ""; + } + + my $props = $item->{'props'}; + + my $ditemid = $init->{'ditemid'}; + my $talkurl = LJ::journal_base($u) . "/$ditemid.html"; + + $parpost ||= $item; # if there's no parent post, remote is reply to top-level item + + my ($up, $ur); # $up = user posted journal item; $ur = user remote is replying to + LJ::load_userids_multiple([ $item->{'posterid'} => \$up, + $parpost->{'posterid'} => \$ur, ], + [ $u ]); + + my $remote = LJ::get_remote(); + + my @user_props = ("opt_logcommentips", "opt_whoscreened"); + push @user_props, "opt_blockrobots" if $u->{'statusvis'} eq 'V'; + LJ::load_user_props($u, @user_props); + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head = LJ::robot_meta_tags(); + } + + # check suspended + return "" + if $u->{'statusvis'} eq "S" || $up->{'statusvis'} eq "S" || + $ur && $ur->{'statusvis'} eq "S"; + + # check deleted + return "" + if ($u->{'statusvis'} eq "D"); + + # checked screened post + return "" + if $parpost->{'state'} eq "S" + && ! LJ::Talk::can_unscreen($remote, $u, $up, ($ur ? $ur->{'user'} : undef)); + + return "" + if $parpost->{'state'} eq "D"; + + # check if frozen + return "" + if $parpost->{'state'} eq "F"; + + # don't allow anonymous comments on syndicated items + if ($u->{'journaltype'} eq "Y" && $u->{'opt_whocanreply'} eq "all") { + $u->{'opt_whocanreply'} = "reg"; + } + + #### Check security before viewing this post + return $errtxt unless LJ::Talk::check_viewable($remote, $item, \%FORM, \$errtxt); + + my $event = $FORM{'replyto'} eq "" ? $item->{'event'} : $parpost->{'body'}; + my $preformatted = $FORM{'replyto'} eq "" ? $props->{'opt_preformatted'} : $parpost->{'opt_preformatted'}; + + LJ::expand_embedded($u, $ditemid, $remote, \$event); + LJ::CleanHTML::clean_event(\$event, $preformatted); + BML::ebml(\$event); + + $ret .= ""; + my $pickw = $init->{'replyto'} ? $parpost->{'picture_keyword'} : $props->{'picture_keyword'}; + my $picid = LJ::get_picid_from_keyword($ur, $pickw); + + my %userpics; + if ($picid) { + LJ::load_userpics(\%userpics, [ $u, $picid ]); + + # not auto-vivifying $ur here because $picid is based + # on $ur existing in the first place + my $alt = $ur->{'name'}; + $alt .= ": $pickw" if $pickw; + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
    "; + + # who-wrote-where + { + my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; + my $suffix = $is_shared ? "_comm" : ""; + + # user logged in + if ($ur) { + $ret .= BML::ml("talk.somebodywrote$suffix", + { 'realname' => LJ::ehtml($ur->{'name'}), + 'userlink' => LJ::ljuser($ur), + 'commlink' => LJ::ljuser($u) }); + + # user anonymous + } else { + $ret .= BML::ml("talk.anonwrote$suffix", + { 'commlink' => LJ::ljuser($u) }); + } + } + + unless ($init->{'replyto'}) { + my $etime = $item->{'eventtime'}; + $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($u, $&)!e; + $ret .= "
    @ $etime"; + } + + $ret .= "
    "; + + unless ($init->{'replyto'}) { + $ret .= LJ::Talk::link_bar({ 'u' => $u, 'up' => $up, 'headref' => \$head, + 'remote' => $remote, 'itemid' => $ditemid, }); + } + + my %current; + if ($props->{'current_mood'} || $props->{'current_moodid'}) { + $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, + $props->{'current_moodid'}, + $props->{'current_mood'}); + } + if ($props->{'current_music'}) { + $current{'Music'} = LJ::current_music_str($props->{'current_music'}); + } + + $ret .= "
    "; + + ### currents + if (! $init->{'replyto'} && %current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
    $curname$current{$_}

    \n"; + } + + ### security indicator + my $sec = ""; + if ($parpost->{'security'} eq "private") { + $sec = BML::fill_template("securityprivate"); + } elsif ($parpost->{'security'} eq "usemask") { + $sec = BML::fill_template("securityprotected"); + } + + $sec .= "
    \n" unless $sec eq "" or $parpost->{'subject'}; + $ret .= $sec; + + ### + if ($parpost->{'subject'}) { + my $cleansubject = $parpost->{'subject'}; + if ($init->{'replyto'}) { + # comments can't have HTML in subjects at all + $cleansubject = LJ::ehtml($cleansubject); + } else { + # but journal entries can have some + LJ::CleanHTML::clean_subject(\$cleansubject); + BML::ebml(\$cleansubject); + } + $ret .= "$cleansubject
    \n"; + } + + $ret .= $event; + $ret .= "

    "; + + $ret .= "

    "; + + my $jarg = "journal=$u->{'user'}&"; + my $readurl = LJ::Talk::talkargs($talkurl, $stylemine); + + $ret .= "

    ($ML{'talk.commentsread'})

    "; + + # can a comment even be made? + if ($props->{'opt_nocomments'}) { + $ret .= ""; + return $ret; + } + if ($u->{'opt_showtalklinks'} eq "N") { + $ret .= ""; + return $ret; + } + unless (LJ::get_cap($u, "get_comments") || + ($remote && LJ::get_cap($remote, "leave_comments"))) { + $ret .= ""; + return $ret; + } + + $ret .= BML::fill_template("H1", { DATA => $ML{'.postresponse'} }); + + $FORM{'body'} = LJ::ehtml($FORM{'body'}) if $FORM{'qr'}; + + $ret .= LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $u, + 'parpost' => $parpost, + 'replyto' => $init->{replyto}, + 'ditemid' => $ditemid, + 'form' => \%FORM }); + BML::noparse(); + return $ret; +} +_code?> + +<=body +head<= + + +<=head +windowtitle=> +page?> +post: htdocs/talkpost_do.bml +link: htdocs/talkread.bml, htdocs/allpics.bml, htdocs/create.bml + _c?> + diff --git a/livejournal/htdocs/talkpost_do.bml b/livejournal/htdocs/talkpost_do.bml new file mode 100755 index 0000000..ed397fb --- /dev/null +++ b/livejournal/htdocs/talkpost_do.bml @@ -0,0 +1,232 @@ + POST escalation) + # since talklib.pl's LJ::Talk::Post::init checks for $POST{'ecphash'} + # and requires it to be correct. if it's not, the page fails. + %POST = %GET if $GET{'ecphash'}; + + return "" if $LJ::TALK_ABORT_REGEXP && $POST{'body'} =~ /$LJ::TALK_ABORT_REGEXP/; + + my $req = shift; + my $r = $req->{'r'}; + + foreach my $re (@LJ::TALKSPAM) { + return if ($POST{'body'} =~ /$re/); + } + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + # Set the title to be for an error, it will be changed later + # upon sucess + $title = $ML{'Error'}; + + # OpenID support + # openid is a bit of hackery but we'll check to make sure they're + # coming back from the identity server and then recreate their + # POST hash as if they never left. Watch and see + if ($GET{'openid.mode'} eq 'id_res' && $GET{'jid'} && $GET{'pendcid'}) { + + return LJ::bad_input("OpenID support not enabled") + unless LJ::OpenID::consumer_enabled(); + + my $csr = LJ::OpenID::consumer(\%GET); + + my $vident = $csr->verified_identity; + return LJ::bad_input("Can't verify identity: ".$csr->err) unless $vident; + + my $url = $vident->url; + return LJ::bad_input("Invalid characters in identity URL.") if $url =~ /[\<\>\s]/; + + my $uo = LJ::User::load_identity_user("O", $url, $vident); + return LJ::bad_input("Couldn't vivify your account (but we verified that you're " . LJ::ehtml($url) . ")") unless $uo; + + LJ::set_remote($uo); + + my $pendcid = $GET{'pendcid'} + 0; + + my $journalu = LJ::load_userid($GET{'jid'}); + return LJ::bad_input("Unable to load user or get database handle") unless $journalu && $journalu->writer; + + my $pending = $journalu->selectrow_array("SELECT data FROM pendcomments WHERE jid=? AND pendcid=?", + undef, $journalu->{'userid'}, $pendcid); + + return LJ::bad_input("Unable to load pending comment, maybe you took too long") unless $pending; + + my $penddata = eval { Storable::thaw($pending) }; + + %POST = %$penddata; + } + # normally require POST. if an ecphash is specified, we'll let + # them through since they're coming from a comment page and + # validate the hash later. + elsif (! LJ::did_post() && !$POST{'ecphash'}) { + return LJ::bad_input("Comment not posted: POST required, or missing parameter."); + } + + + # as an exception, we do NOT call LJ::text_in() to check for bad + # input, since it may be not in UTF-8 in replies coming from mail + # clients. We call it later. + + my $remote_ip = LJ::get_remote_ip(); + if (($POST{'usertype'} eq "anonymous" || $POST{'usertype'} eq "openid") && LJ::is_open_proxy($remote_ip)) { + return LJ::bad_input("Your IP address ($remote_ip) is detected as an open proxy (a common source of spam) so comment access is denied. If you do not believe you're accessing the net through an open proxy, please contact your ISP or this site's tech support to help resolve the problem."); + } + + my $remote = LJ::get_remote(); + my $journalu = LJ::load_user($POST{journal}); + return LJ::bad_input('Unknown journal. Please go back and try again.') unless $journalu; + + ## preview + # ignore errors for previewing + if ($POST{'submitpreview'} || ($POST{'qr'} && $POST{'do_spellcheck'})) { + my $cookie_auth; + $cookie_auth = 1 if $POST{usertype} eq "cookieuser"; + my $talkurl = LJ::journal_base($journalu) . "/$POST{itemid}.html"; + $title = $ML{'.title.preview'}; + return LJ::Talk::Post::make_preview($talkurl, $cookie_auth, \%POST); + } + + ## init. this handles all the error-checking, as well. + my @errors; + my $need_captcha = 0; + my $init = LJ::Talk::Post::init(\%POST, $remote, \$need_captcha, \@errors); + + # Report errors in a friendly manner by regenerating the field. + # Required for challenge/response login, since we also need to regenerate an auth token. + # We repopulate what we can via hidden fields - however the objects (journalu & parpost) must be recreated here. + + # if the user leaving the comment hasn't agreed to the current TOS, and they + # didn't click the agreement checkbox, return the form back to them + my $require_tos = 0; + my $commentu = $init ? $init->{comment}->{u} : undef; + if ($init && ! $POST{agree_tos} && $commentu && ! $commentu->tosagree_verify) { + $require_tos = 1; + } + + if (! $init || $require_tos) { + my ($sth, $parpost); + my $dbcr = LJ::get_cluster_def_reader($journalu); + return LJ::bad_input('No database connection present. Please go back and try again.') unless $dbcr; + + $sth = $dbcr->prepare("SELECT posterid, state FROM talk2 ". + "WHERE journalid=? AND jtalkid=?"); + $sth->execute($journalu->{userid}, $POST{itemid}+0); + $parpost = $sth->fetchrow_hashref; + + $title = $ML{'.title.error'} unless $need_captcha; + + return LJ::Talk::talkform({ 'remote' => $remote, + 'journalu' => $journalu, + 'parpost' => $parpost, + 'replyto' => $POST{replyto}, + 'ditemid' => $POST{itemid}, + 'require_tos' => $require_tos, + 'do_captcha' => $need_captcha, + 'errors' => \@errors, + 'form' => \%POST }); + } + + # checked $POST{agree_tos} was checked above if it was necessary, + # now we just need to save the userprop + if ($commentu && ! $commentu->tosagree_verify && $POST{agree_tos}) { + my $err = ""; + return LJ::bad_input($err) + unless $commentu->tosagree_set(\$err); + } + + + my $talkurl = $init->{talkurl}; + + my $entryu = $init->{entryu}; + my $journalu = $init->{journalu}; + my $parent = $init->{parent}; + my $comment = $init->{comment}; + my $item = $init->{item}; + + # check max comments + return LJ::bad_input("Sorry, this entry already has the maximum number of comments allowed.") + if LJ::Talk::Post::over_maxcomments($journalu, $item->{'jitemid'}); + + # no replying to frozen comments + return LJ::bad_input($ML{'/talkpost.bml.error.noreply_frozen'}) + if $parent->{state} eq 'F'; + + ## insertion + my $wasscreened = ($parent->{state} eq 'S'); + my $err; + unless (LJ::Talk::Post::post_comment($entryu, $journalu, + $comment, $parent, $item, \$err)) { + return LJ::bad_input($err); + } + + # Yeah, we're done. + my $dtalkid = $comment->{talkid}*256 + $item->{anum}; + + # Allow style=mine for QR redirects + my $stylemine = $POST{'stylemine'} ? 'style=mine' : ''; + + my $commentlink; + if ($POST{'viewing_thread'} eq '') { + $commentlink = LJ::Talk::talkargs($talkurl, "view=$dtalkid", $stylemine) . "#t$dtalkid"; + } else { + $commentlink = LJ::Talk::talkargs($talkurl, "thread=$POST{viewing_thread}", $stylemine) . "#t$dtalkid"; + } + + my $ret = ""; + $ret .= ""; + + my $mlcode; + if ($comment->{state} eq 'A') { + # Redirect the user back to their post as long as it didn't unscreen its parent, + # is screened itself, or they logged in + if (!($wasscreened and $parent->{state} ne 'S') && !$init->{didlogin}) { + LJ::set_lastcomment($journalu->{'userid'}, $remote, $dtalkid); + return BML::redirect($commentlink); + } + + $mlcode = '.success.message'; + } else { + # otherwise, it's a screened comment. + if ($journalu->{'journaltype'} eq 'C') { + $mlcode = $POST{'usertype'} eq 'anonymous' ? '.success.screened.comm.anon' + : '.success.screened.comm'; + } else { + $mlcode = $POST{'usertype'} eq 'anonymous' ? '.success.screened.user.anon' + : '.success.screened.user'; + } + } + + $ret .= " $commentlink }) . " p?>"; + + # did this comment unscreen its parent? + if ($wasscreened and $parent->{state} ne 'S') { + $ret .= ""; + } + + if ($init->{didlogin}) { + $ret .= ""; + } + + # Sucessful! + $title = $ML{'.title'}; + return $ret; +} +_code?> + +<=body +title=> +head<= + +<=head +page?> +lib: LJ::SpellCheck +link: htdocs/lostinfo.bml, htdocs/userinfo.bml, htdocs/talkread.bml, htdocs/editinfo.bml +post: htdocs/talkpost_do.bml + _c?> diff --git a/livejournal/htdocs/talkread.bml b/livejournal/htdocs/talkread.bml new file mode 100755 index 0000000..90e344b --- /dev/null +++ b/livejournal/htdocs/talkread.bml @@ -0,0 +1,608 @@ +{'head'} : \$r_head; + my $title = $_[1] ? \$_[1]->{'title'} : \$r_title; + my $bodyopts = $_[1] ? \$_[1]->{'bodyopts'} : \$r_bodyopts; + + return LJ::server_down_html() if $LJ::SERVER_DOWN; + + + + my $pics = LJ::Talk::get_subjecticons(); + + ## workaround mail client bug when don't understand quoted-printable. + ## Only correct 'journal' if 'itemid' was also broken, to avoid the + ## unlikely clash with a journal name. + if ($GET{'itemid'} =~ s/^3D//) { + $GET{'journal'} =~ s/^3D//; + $GET{'thread'} =~ s/^3D//; + } + + my $r = Apache->request; + $r->notes("codepath" => "bml.talkread"); + + my $uri = BML::get_uri(); + my $itemid; + + if ($uri =~ m!/(\d+)\.html$!) { + $itemid = $1; + $GET{'itemid'} = $itemid; + $GET{'journal'} = $r->notes("_journal"); + BML::set_language_scope("/talkread.bml"); + } + + # pre-load common strings for little speed and less typing later + # (we're doing this *after* set_language_scope is called, because + # two below are relative strings) + my %T = qw(postcomments talk.commentpost + readcomments talk.commentsread + parent talk.parentlink + thread talk.threadlink + replythis talk.replytothis + frozen talk.frozen + link talk.commentpermlink + deleted .subjectdeleted + nosubject .nosubject + ); + foreach (keys %T) { $T{$_} = $ML{$T{$_}}; } + + my $init = LJ::Talk::init(\%GET); + + my $u = $init->{'journalu'}; + return $ML{'talk.error.nojournal'} unless $u; + + my $ditemid = $init->{'ditemid'}+0; + + # redirect if account was renamed + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + if ($u->{'renamedto'} ne "") { + return BML::redirect(LJ::journal_base($u->{'renamedto'}) . "/$ditemid.html"); + } + } + + # now check for init->error, since we know the account wasn't renamed + return "{'error'} p?>" if $init->{'error'}; + + LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $$head .= LJ::robot_meta_tags(); + } + + $r->notes("journalid" => $u->{'userid'}); + + my $thread = $init->{'thread'}; + my $dthread = $init->{'dthread'}; + $itemid = $init->{'itemid'}+0; + + my $stylemine = $init->{'style'} eq "mine" ? "style=mine" : ""; + + my $item = LJ::Talk::get_journal_item($u, $itemid); + + if ($init->{'oldurl'} && $item) { + $init->{'anum'} = $item->{'anum'}; + $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'}; + $ditemid = $init->{'ditemid'} + 0; + } + + unless ($item && $item->{'anum'} == $init->{'anum'}) { + return ""; + } + + my $jarg = "journal=$u->{'user'}&"; + my $jargent ="journal=$u->{'user'}&"; + my $talkurl = LJ::journal_base($u) . "/$ditemid.html"; + + my $ret = ""; + + my $props = $item->{'props'}; + my $nocomments = $u->{'opt_showtalklinks'} eq "N" ? 1 : $props->{'opt_nocomments'}; + + ### load users + my ($up); # $up = user posted journal item + LJ::load_userids_multiple([ $item->{'posterid'} => \$up, ], [ $u ]); + + LJ::text_out(\$u->{'name'}); + + my $remote = LJ::get_remote(); + + # set viewall/viewsome + my $viewall = 0; + my $viewsome = 0; + if ($GET{viewall} && LJ::check_priv($remote, 'canview')) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "entry: $u->{'user'}, itemid: $item->{'itemid'}, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + } + + # check for deleted/suspended/security + unless ($viewsome) { + # check suspended + return "" + if ($u->{'statusvis'} eq "S" || $up->{'statusvis'} eq "S"); + + # check deleted + return "" + if ($u->{'statusvis'} eq "D"); + } + + unless ($viewall) { + #### Check security before viewing this post + my $errtxt; + return $errtxt unless LJ::Talk::check_viewable($remote, $item, \%GET, \$errtxt); + } + + # See if we should inject QuickReply javascript + LJ::load_user_props($remote, "opt_no_quickreply"); + + if (($remote && !$remote->{'opt_no_quickreply'}) && !$nocomments) { + $$head .= $LJ::COMMON_CODE{'quickreply'}; + $$bodyopts .= 'onload="restore_entry();" onunload="save_entry();"'; + } + + my $showmultiform = $remote && + ($remote->{'user'} eq $u->{'user'} || + $remote->{'user'} eq $up->{'user'} || + LJ::can_manage($remote, $u)); + my $multiform_selects = 0; # are there select boxes? don't show form if not. + + my $event = $item->{'event'}; + + LJ::expand_embedded($u, $ditemid, $remote, \$event); + LJ::CleanHTML::clean_event(\$event, $props->{'opt_preformatted'}); + BML::ebml(\$event); + + # make the title +{ + my $subject = $item->{'subject'} || $event; + LJ::CleanHTML::clean_subject_all(\$subject); + $subject =~ s/\n.*//s; + # yes, the 3 param to text_trim is chars, and length returns bytes, but + # it works, as bytes >= chars: + $subject = LJ::text_trim($subject, 0, length($item->{'subject'}) || 40); + $$title = "$u->{'user'}: $subject"; +} + + $ret .= "

    "; + $ret .= ""; + + my $picid = LJ::get_picid_from_keyword($up, $props->{'picture_keyword'}); + + my %userpics; + if ($picid) { + LJ::load_userpics(\%userpics, [ $u, $picid ]); + my $alt = $up->{'name'}; + if ($props->{'picture_keyword'}) { + $alt .= ": $props->{'picture_keyword'}"; + } + LJ::text_out(\$alt); + $alt = LJ::ehtml($alt); + $ret .= ""; + } + + $ret .= "
    "; + my $is_shared = $u->{'journaltype'} eq 'C' || $u->{'journaltype'} eq 'S'; + if ($is_shared) { + $ret .= BML::ml("talk.somebodywrote_comm", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up), + 'commlink' => LJ::ljuser($u) }); + } else { + $ret .= BML::ml("talk.somebodywrote", { 'realname' => LJ::ehtml($up->{'name'}), + 'userlink' => LJ::ljuser($up) }); + } + + my $etime = $item->{'eventtime'}; + $etime =~ s!(\d\d\d\d)-(\d\d)-(\d\d)!LJ::date_to_view_links($u, $&)!e; + $ret .= "
    @ $etime"; + $ret .= "
    "; + + ## standout bar + $ret .= LJ::Talk::link_bar({ 'u' => $u, 'up' => $up, 'headref' => $head, + 'remote' => $remote, 'itemid' => $ditemid, }); + + ## dump the log entry, unless we're browsing a thread. + my %current; + if ($props->{'current_mood'} || $props->{'current_moodid'}) { + $current{'Mood'} = LJ::current_mood_str($up->{'moodthemeid'}, + $props->{'current_moodid'}, + $props->{'current_mood'}); + } + if ($props->{'current_music'}) { + $current{'Music'} = LJ::current_music_str($props->{'current_music'}); + } + + my $logtags = LJ::Tags::get_logtags($u, $itemid); + if ($logtags->{$itemid} && %{$logtags->{$itemid}}) { + my $base = LJ::journal_base($u); + $current{'Tags'} = join(', ', + map { "" . LJ::ehtml($_) . "" } + sort values %{$logtags->{$itemid}} + ); + } + + $ret .= "

    "; + + if (%current) + { + $ret .= "\n"; + foreach (sort keys %current) { + my $curkey = "talk.curname_" . $_; + my $curname = BML::ml($curkey); + $curname = "Current $_:" unless $curname; + $ret .= "\n"; + } + $ret .= "
    $curname$current{$_}

    \n"; + } + + ### security indicator + my $sec = ""; + if ($item->{'security'} eq "private") { + $sec = BML::fill_template("securityprivate"); + } elsif ($item->{'security'} eq "usemask") { + $sec = BML::fill_template("securityprotected"); + } + + $sec .= "
    \n" unless $sec eq "" or $item->{'subject'}; + $ret .= $sec; + + ### + if ($item->{'subject'}) { + my $subject = $item->{'subject'}; + LJ::CleanHTML::clean_subject(\$subject); + BML::ebml(\$subject); + $ret .= "$subject
    \n"; + } + + $ret .= $event; + $ret .= "

    "; + + $ret .= "

    "; + + my %user; + my $opts = { + 'thread' => $thread, + 'page' => $GET{'page'}, + 'view' => $GET{'view'}, + 'userpicref' => \%userpics, + 'userref' => \%user, + 'up' => $up, + 'viewall' => $viewall, + }; + + my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $opts); + return $ML{'error.nodbmaintenance'} if $opts->{'out_error'} eq "nodb"; + + my $page = $opts->{'out_page'}; + my $pages = $opts->{'out_pages'}; + + ########## make the navcrap + my $navcrap; + $navcrap .= ""; + if ($pages > 1) { + $navcrap .= ""; + $navcrap .= ""; + my $left = "<<"; + if ($page > 1) { $left = " $page-1 }) . "#comments'>$left"; } + + my $right = ">>"; + if ($page < $pages) { $right = " $page+1 }) . "#comments'>$right"; } + + $navcrap .= ""; + $navcrap .= "
    "; + $navcrap .= BML::ml('ljlib.pageofpages',{'page'=>$page, 'total'=>$pages}); + $navcrap .= "
    $left"; + + for (my $i=1; $i<=$pages; $i++) { + my $link = "[$i]"; + if ($i != $page) { $link = " $i }) . "#comments'>$link"; } + else { $link = "$link"; } + $navcrap .= "$link "; + if ($i == 11) { $navcrap .= "
    "; } + elsif ($i > 10 && $i % 10 == 0) { $navcrap .= "
    "; } + } + + $navcrap .= "
    $right
    \n"; + $navcrap = BML::fill_template("standout", { 'DATA' => $navcrap }); + } + ####### end navcrap + + # Quick reply variables. Not always set. + my ($last_talkid, $last_jid) = LJ::get_lastcomment(); + my %LJ_cmtinfo; # data structure to give to javascript for commentmanage + $LJ_cmtinfo{'journal'} = $u->{user}; + $LJ_cmtinfo{'canAdmin'} = LJ::can_manage($remote, $u) ? 1 : 0; + $LJ_cmtinfo{'remote'} = $remote ? $remote->{user} : ""; + + my $recurse_post = sub + { + my ($self_sub, $post, $opts) = @_; + + $opts ||= { 'depth' => 0 }; + + my $tid = $post->{'talkid'}; + my $dtid = $tid * 256 + $init->{'anum'}; + my $LJci = $LJ_cmtinfo{$dtid} = { rc => [], u => '' }; + + my $datepost = "" . substr($post->{'datepost'}, 0, 16) . ""; + + my $bgcolor = ($opts->{'depth'} % 2) ? "emcolorlite" : "emcolor"; + $bgcolor = BML::get_template_def($bgcolor); + if ($post->{'state'} eq "S") { + $bgcolor = BML::get_template_def("screenedbarcolor") || $bgcolor; + } elsif ($last_talkid == $dtid && $last_jid == $u->{'userid'}) { + $bgcolor = BML::get_template_def("altcolor1"); + } + + my $pu = $post->{'posterid'} ? $user{$post->{'posterid'}} : undef; + $LJci->{u} = $pu->{user} if $pu; + + my $userpost = $post->{'userpost'}; + my $upost = $post->{'upost'}; + + my $user; + if ($post->{'props'}->{'deleted_poster'}) { + $user = BML::ml('.deleteduser', {'username'=>$post->{'deleted_poster'}}); + } + else { + $user = $ML{'.anonuser'}; + } + + if ($post->{'state'} eq "D") { + $ret .= "

    "; + $ret .= ""; + $ret .= "
    $ML{'.deletedpost'}
    \n"; + } elsif ($post->{'state'} eq "S" && !$post->{'_loaded'} && !$post->{'_show'}) { + $ret .= "

    "; + $ret .= ""; + my $screenedtext = $ML{'.screenedpost'}; + $ret .= "
    $screenedtext
    \n"; + } elsif ($pu && $pu->{'statusvis'} eq "S" && !$viewsome) { + $ret .= "

    "; + $ret .= ""; + $ret .= "
    $ML{'.replysuspended'}"; + if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { + $ret .= " " . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + if ($post->{state} ne 'F' && LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + if ($post->{state} eq 'F' && LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + $ret .= "
    \n"; + } else { + if ($upost) { + $user = LJ::ljuser($upost); + } + my $icon = LJ::Talk::show_image($pics, $post->{'props'}->{'subjecticon'}); + + if ($post->{'_loaded'}) { + $ret .= ""; + $ret .= ""; + $ret .= "
    "; + if (my $picid = $post->{'picid'}) { + my $alt = $pu->{'name'}; + if ($post->{'props'}->{'picture_keyword'}) { + $alt .= ": $post->{'props'}->{'picture_keyword'}"; + } + $alt = LJ::ehtml($alt); + my ($w, $h) = ($userpics{$picid}->{'width'}, $userpics{$picid}->{'height'}); + $ret .= "{'subject'}); + $ret .= "$cleansubject $icon"; + $ret .= "
    $user\n"; + $ret .= "
    $datepost\n"; + if ($post->{'props'}->{'poster_ip'} && $remote && + ($remote->{'user'} eq $up->{'user'} || + LJ::can_manage($remote, $u) || $viewall)) + { + $ret .= BML::ml('.fromip', {'ip'=>$post->{'props'}->{'poster_ip'}}); + } + + $ret .= " ($T{'link'}) "; + + if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($post->{'state'} ne 'F' && + LJ::Talk::can_freeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($post->{'state'} eq 'F' && + LJ::Talk::can_unfreeze($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($post->{'state'} ne 'S' && + LJ::Talk::can_screen($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_scr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($post->{'state'} eq 'S' && + LJ::Talk::can_unscreen($remote, $u, $up, $userpost)) { + $ret .= "" . LJ::img("btn_unscr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($showmultiform) { + $ret .= " "; + $ret .= " "; + $multiform_selects = 1; + } + + # Comment Posted Notice + $ret .= "
    $ML{'.posted'}" + if $last_talkid == $dtid && $last_jid == $u->{'userid'}; + + $ret .= "
    "; + + LJ::CleanHTML::clean_comment(\$post->{'body'}, { 'preformatted' => $post->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$pu }); + BML::ebml(\$post->{'body'}); + $ret .= $post->{'body'}; + + $ret .= "

    "; + + my $replyurl = LJ::Talk::talkargs($talkurl, "replyto=$dtid", $stylemine); + if ($post->{'state'} eq 'F') { + $ret .= "($T{'frozen'}) "; + } elsif ($remote) { + $ret .= "(" . LJ::make_qr_link($dtid, $post->{'subject'}, $T{'replythis'}, $replyurl) . ")"; + } else { + $ret .= "($T{'replythis'}) "; + } + + if ($post->{'parenttalkid'} != 0) { + my $dpid = $post->{'parenttalkid'} * 256 + $init->{'anum'}; + $ret .= "($T{'parent'}) "; + } + if ($post->{'children'} && @{$post->{'children'}}) { + my $url = LJ::Talk::talkargs($talkurl, "thread=$dtid", $stylemine) . "#t$dtid"; + $ret .= "($T{'thread'})"; + } + $ret .= "

    "; + + $ret .= LJ::make_qr_target($dtid) if $remote; + + $ret .= "
    \n"; # close colored table + } else { + # link to message + + $ret .= ""; + $ret .= ""; + $ret .= "
    " . LJ::ehtml($post->{'subject'} || $T{'nosubject'}) . " - $user, $post->{'datepost'}"; + + # Comment Posted Notice + $ret .= " - $ML{'.posted'}" + if $last_talkid == $dtid && $last_jid == $u->{'userid'}; + $ret .= "
    \n"; + } + } + + if ($post->{'children'}) { + foreach my $childpost (@{$post->{'children'}}) { + push @{$LJci->{rc}}, $childpost->{talkid} * 256 + $init->{'anum'}; + $self_sub->($self_sub, $childpost, { "depth" => $opts->{'depth'} + 1}); + } + } + }; + + unless ($nocomments) + { + $ret .= "

    "; + $ret .= "$navcrap" if $navcrap; + my $readlink; + if ($dthread && $pages == 1) { + my $readurl = LJ::Talk::talkargs($talkurl, $stylemine); + $readlink = "($T{'readcomments'}) - "; + } + + my $posturl = LJ::Talk::talkargs($talkurl, "mode=reply", $stylemine); + + $ret .= "
    "; + + # Quick Reply when posting a new top level comment + # requires setup when logged in. + $ret .= "

    $readlink"; + if ($remote) { + $ret .= "(" . LJ::make_qr_link('top', '', $T{'postcomments'}, $posturl) . ")"; + } else { + $ret .= "($T{'postcomments'})"; + } + + $ret .= "

    "; + + $ret .= "
    " . LJ::make_qr_target('top') . "
    " if $remote; + + my $stylemine = $GET{'style'} eq 'mine' ? 1 : 0; + + my $viewing_thread; + if (defined $GET{'thread'}) { + $viewing_thread = $GET{'thread'}; + } + $ret .= LJ::create_qr_div($u, $ditemid, $stylemine, $GET{'prop_picture_keyword'}, $viewing_thread); + + $ret .= LJ::html_hidden("ditemid", $ditemid); + $ret .= LJ::html_hidden("journal", $u->{'user'}); + + # Print out each comment + if (@comments > 0) + { + $recurse_post->($recurse_post, $_, { "depth" => 0 }) foreach (@comments); + + my $do_commentmanage_js = 1; + if ($LJ::DISABLED{'commentmanage'}) { + if (ref $LJ::DISABLED{'commentmanage'} eq "CODE") { + $do_commentmanage_js = $LJ::DISABLED{'commentmanage'}->($remote); + } else { + $do_commentmanage_js = 0; + } + } + + if ($do_commentmanage_js) { + $$head .= "\n"; + my $js_screen_color = "\"" . LJ::ejs(BML::get_template_def("screenedbarcolor") || BML::get_template_def("emcolor")) . "\""; + my $js_normal_color = "\"" . LJ::ejs(BML::get_template_def("emcolor")) . "\""; + $$head .= "\n"; + } + + $ret .= "

    $readlink"; + $ret .= "(" . LJ::make_qr_link('bottom', '', $T{'postcomments'}, $posturl) . ")" if $remote; + $ret .= "

    "; + $ret .= "
    " . LJ::make_qr_target('bottom') . "
    " if $remote; + + if ($showmultiform && $multiform_selects) { + $ret .= "

    $ML{'.talkmulti.des'} "; + $ret .= LJ::html_select({'name' => 'mode' }, + "" => "", + "unscreen" => $ML{'.talkmulti.unscreen'}, + "screen" => $ML{'.talkmulti.screen'}, + "delete" => $ML{'.talkmulti.delete'}); + $ret .= " " . LJ::html_submit('', $ML{'.talkmulti.submit'}, + { "onclick" => "return (document.multiform.mode.value != \"delete\") " . + "|| confirm(\"" . LJ::ejs($ML{'.confirm.action'}) . "\");" }); + $ret .= "

    "; + } + } + + $ret .= "
    "; + + if ($navcrap) { + $ret .= "

    $navcrap

    "; + } + + $ret .= "
    "; + } + + BML::noparse(); + return $ret; + +_code?> +<=body +windowtitle=>{'title'} : $r_title _code?> +head=>{'head'} : $r_head _code?> +bodyopts=>{'bodyopts'}; _code?> +page?> +link: htdocs/talkpost.bml, htdocs/talkread.bml, htdocs/delcomment.bml +img: htdocs/img/dot.gif, htdocs/img/delcomment.gif + _c?> diff --git a/livejournal/htdocs/talkscreen.bml b/livejournal/htdocs/talkscreen.bml new file mode 100755 index 0000000..60f06bc --- /dev/null +++ b/livejournal/htdocs/talkscreen.bml @@ -0,0 +1,199 @@ +1 +_info?>"; + return; + }; + my $bad_input = sub { + return $error->("Bad input: $_[0]") if $jsmode; + $body = LJ::bad_input($_[0]); + return; + }; + + my $mode = $POST{'mode'} || $GET{'mode'}; + my $talkid = $POST{'talkid'} || $GET{'talkid'}; + my $journal = $POST{'journal'} || $GET{'journal'}; + my $qtalkid = $talkid+0; + my $dtalkid = $qtalkid; # display talkid, for use in URL later + + my $jsres = sub { + my $mode = shift; + + # flip case of 'un' + my $newmode = "un$mode"; + $newmode =~ s/^unun//; + my $stockimg = { + 'screen' => "btn_scr.gif", + 'unscreen' => "btn_unscr.gif", + 'freeze' => "btn_freeze.gif", + 'unfreeze' => "btn_unfreeze.gif", + }; + + my $res = "rpcRes = {\n mode: \"$mode\", id: $dtalkid, \n" . + " oldimage: \"$LJ::IMGPREFIX/$stockimg->{$mode}\",\n " . + " newimage: '$LJ::IMGPREFIX/$stockimg->{$newmode}',\n " . + " newurl: '$LJ::SITEROOT/talkscreen.bml?mode=$newmode&journal=$journal&talkid=$dtalkid' \n" . + "};\n"; + BML::finish(); + return $res; + }; + + my $remote = LJ::get_remote(); + + return $error->($ML{'.error.login'}) unless $remote; + + # we need to find out: $u, $up (poster of the entry this is a comment to), + # userpost (username of this comment's author). Then we can check permissions. + + my $u = LJ::load_user($journal); + return $error->($ML{'.talk.error.bogusargs'}) unless $u; + my $dbcr = LJ::get_cluster_def_reader($u); + return $error->($ML{'error.nodb'}) unless $dbcr; + + my $post; + $qtalkid = int($qtalkid / 256); # get rid of anum + $post = $dbcr->selectrow_hashref("SELECT jtalkid AS 'talkid', nodetype, state, nodeid AS 'itemid', ". + "parenttalkid, journalid, posterid FROM talk2 ". + "WHERE journalid=$u->{'userid'} AND jtalkid=$qtalkid"); + + return $error->($ML{'talk.error.nocomment'}) unless $post; + return $error->($ML{'talk.error.comm_deleted'}) if $post->{'state'} eq "D"; + + my $state = $post->{'state'}; + + $u ||= LJ::load_userid($post->{'journalid'}); + return $error->($LJ::MSG_READONLY_USER) if LJ::get_cap($u, "readonly"); + + if ($post->{'posterid'}) { + $post->{'userpost'} = LJ::get_username($post->{'posterid'}); + } + + my $qitemid = $post->{'itemid'}+0; + + # $posterid is the userid of the author of the entry, not the comment + my ($posterid, $anum) = + $dbcr->selectrow_array("SELECT posterid, anum FROM log2 WHERE ". + "journalid=$u->{'userid'} AND jitemid=$qitemid"); + my $up = LJ::load_userid($posterid); + + my $ditemid = $qitemid*256 + $anum; + + my $itemlink = LJ::journal_base($u) . "/$ditemid.html"; + my $commentlink = "$itemlink?view=$dtalkid#t$dtalkid"; + + if ($mode eq 'screen') { + my $can_screen = LJ::Talk::can_screen($remote, $u, $up, $post->{'userpost'}); + return $error->($ML{'.error.privs.screen'}) unless $can_screen; + unless ($POST{'confirm'} eq 'Y') { + $body .= ""; + $body .= "

    \n"; + $body .= LJ::html_hidden(mode => 'screen', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.screen.doit'}); + $body .= "
    "; + $body .= "
    \n"; + return; + } + if ($state ne 'S') { + LJ::Talk::screen_comment($u, $qitemid, $qtalkid); + } + # FIXME: no error checking? + return $jsres->($mode) if $jsmode; + $body = "$commentlink}) . " p?>"; + return; + } + + if ($mode eq 'unscreen') { + my $can_unscreen = LJ::Talk::can_unscreen($remote, $u, $up, $post->{'userpost'}); + return $error->($ML{'.error.privs.unscreen'}) unless $can_unscreen; + unless ($POST{'confirm'} eq 'Y') { + $body .= ""; + $body .= "

    \n"; + $body .= LJ::html_hidden(mode => 'unscreen', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.unscreen.doit'}); + $body .= "
    "; + $body .= "
    \n"; + return; + } + if ($state ne 'A') { + LJ::Talk::unscreen_comment($u, $qitemid, $qtalkid); + } + # FIXME: no error checking? + return $jsres->($mode) if $jsmode; + $body = "$commentlink}) . " p?>"; + return; + } + + if ($mode eq 'freeze') { + my $can_freeze = LJ::Talk::can_freeze($remote, $u, $up, $post->{userpost}); + unless ($can_freeze) { + $body = ""; + return; + } + + unless ($POST{confirm} eq 'Y') { + $body .= ""; + $body .= "

    \n"; + $body .= LJ::html_hidden(mode => 'freeze', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.freeze.doit'}); + $body .= "
    "; + $body .= "
    \n"; + return; + } + if ($state ne 'F') { + LJ::Talk::freeze_thread($u, $qitemid, $qtalkid); + } + return $jsres->($mode) if $jsmode; + my $linktext = BML::ml('.link', { aopts => "href='$itemlink'" }); + $body = ""; + return; + } + + if ($mode eq 'unfreeze') { + my $can_unfreeze = LJ::Talk::can_unfreeze($remote, $u, $up, $post->{userpost}); + unless ($can_unfreeze) { + $body = ""; + return; + } + unless ($POST{confirm} eq 'Y') { + $body .= ""; + $body .= "

    \n"; + $body .= LJ::html_hidden(mode => 'unfreeze', 'talkid' => $talkid, + journal => $u->{user}, confirm => 'Y'); + $body .= LJ::html_submit(undef, $ML{'.unfreeze.doit'}); + $body .= "
    "; + $body .= "
    \n"; + return; + } + if ($state eq 'F') { + LJ::Talk::unfreeze_thread($u, $qitemid, $qtalkid); + } + return $jsres->($mode) if $jsmode; + my $linktext = BML::ml('.link', { aopts => "href='$itemlink'" }); + $body = ""; + return; + } + + $body = ""; + return; + +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/todo/index.bml b/livejournal/htdocs/todo/index.bml new file mode 100755 index 0000000..49e9176 --- /dev/null +++ b/livejournal/htdocs/todo/index.bml @@ -0,0 +1,293 @@ +{'user'}; } + my $u = undef; + + if ($user && $FORM{'mode'} ne "pickuser") { + $u = LJ::load_user($user); + unless ($u) { + $body .= "Unknown user: " . LJ::ehtml($user) . " p?>\n"; + } + } + + unless ($u) { + $title = "To-Do List"; + $body .= "
    "; + $body .= "Enter the username of the user whose to-do list you would like to view:
    \n"; + return; + } + + LJ::Todo::get_permissions($dbh, \%permission, { 'user' => $u, 'remote' => $remote }); + + $title = "To-Do List: $user"; + $body .= "go here. de?>"; + + #### + ### security stuff + ## + + my $where; + unless ($remote && $remote->{'userid'} == $u->{'userid'}) { + my $friendclause; + if ($remote) { + # check to see if this user's a friend + $sth = $dbh->prepare("SELECT COUNT(*) AS 'isfriend' FROM friends WHERE userid=$u->{'userid'} AND friendid=$remote->{'userid'}"); + $sth->execute; + my ($isfriend) = $sth->fetchrow_array; + if ($isfriend) { $friendclause = ", 'friends'"; } + } + $where .= "AND t.security IN ('public' $friendclause)"; + } + + #### + ### load the todo items + ## + + my %keyword; + my %itemkws; + my @tdids; + my @delete; + my $total; + $sth = $dbh->prepare("SELECT t.todoid, tk.kwid, k.keyword FROM todo t LEFT JOIN todokeyword tk ON t.todoid=tk.todoid LEFT JOIN keywords k ON tk.kwid=k.kwid WHERE t.journalid=$u->{'userid'} $where"); + $sth->execute; + while (my ($id, $kwid, $keyword) = $sth->fetchrow_array) { + if ($kwid) { + $keyword{$kwid}->{'count'}++; + $keyword{$kwid}->{'keyword'} = $keyword; + push @{$itemkws{$id}}, $kwid; + } + $total++; + if (! $FORM{'cat'} || ($kwid && $keyword eq $FORM{'cat'})) { + push @tdids, $id; + if ($FORM{"delete_$id"}) { + push @delete, $id; + } + } + } + + ### deleting? + if (@delete) { + unless ($permission{'delete'}) { + $title = "Error"; + $body = ""; + return; + } + + my $in = join(",", @delete); + $dbh->do("DELETE FROM todo WHERE todoid IN ($in)"); + $dbh->do("DELETE FROM tododep WHERE todoid IN ($in)"); + $dbh->do("DELETE FROM tododep WHERE depid IN ($in)"); + $dbh->do("DELETE FROM todokeyword WHERE todoid IN ($in)"); + + $title = "Deleted"; + $body = ""; + $body .= "{'user'}\"><< To-Do List"; + $body .= ""; + return; + } + + $body .= "
    "; + $body .= "\n" if ($FORM{'user'}); + $body .= "{'keyword'}) cmp lc($keyword{$b}->{'keyword'}) } + keys %keyword) + { + my $cat = $keyword{$kwid}->{'keyword'}; + if ($FORM{'cat'} eq $cat) { + $body .= "" . LJ::ehtml($cat) . " ($keyword{$kwid}->{'count'}), "; + } else { + $body .= " $u->{'user'}, 'cat' => $cat }) . "\">" . LJ::ehtml($cat) . " ($keyword{$kwid}->{'count'}), "; + } + } + if ($FORM{'cat'}) { + $body .= " $u->{'user'}, 'cat' => '' }) . "\">(Show All), " + } + + if (keys %keyword) { + chop $body; chop $body; # remove final ", " + } else { + $body .= "No categories to filter on."; + } + $body .= " p?>"; + + unless (@tdids) { + $body .= ""; + } + + ### + ## links + # + { + my @actions = (); + if ($permission{'add'}) { + push @actions, [ "item.bml?user=$u->{'user'}&mode=add&cat=" . LJ::eurl($FORM{'cat'}), "Add Item" ]; + } + + if (@actions) + { + $body .= "[0]\">$_->[1] ]"; + } + $body .= " p?>"; + } + } + + unless (@tdids) { + $body .= "
    "; + return; + } + + $sth = $dbh->prepare("SELECT todoid, posterid, ownerid, statusline, security, subject, des, priority, UNIX_TIMESTAMP(datecreate) AS 'datecreate_unix', dateupdate, datedue, dateclosed, progress FROM todo WHERE todoid IN (" . join(",", @tdids) . ")"); + $sth->execute; + + my @items; + push @items, $_ while ($_ = $sth->fetchrow_hashref); + + foreach my $it (@items) { + $it->{'_duesort'} = $it->{'datedue'}; + if ($it->{'_duesort'} =~ s/^0000-/9999-/) { + $it->{'datedue'} = ""; + } elsif (length($it->{'datedue'})==0) { + $it->{'_duesort'} = "9999"; + } + } + + ### + ## sort + # + + $FORM{'sort'} ||= "due"; + + if ($FORM{'sort'} eq "due") { + @items = sort { $b->{'priority'} <=> $a->{'priority'} } @items; + @items = sort { $a->{'_duesort'} cmp $b->{'_duesort'} } @items; + } + + if ($FORM{'sort'} eq "priority") { + @items = sort { $a->{'_duesort'} cmp $b->{'_duesort'} } @items; + @items = sort { $b->{'priority'} <=> $a->{'priority'} } @items; + } + + if ($FORM{'sort'} eq "status") { + @items = sort { $b->{'progress'} <=> $a->{'progress'} } @items; + } + + if ($FORM{'sort'} eq "item") { + @items = sort { lc($a->{'subject'}) cmp lc($b->{'subject'}) } @items; + } + + + $body .= "

    \n"; + $body .= " ALIGN=LEFT VALIGN=BOTTOM>\n"; + $body .= "\n" if ($permission{'delete'}); + { + my @cols = (["Status", "status"], + ["P", "priority"], + ["Item", "item"], + ["Date Due", "due"], + ["Category", ""]); + foreach my $col (@cols) { + if ($col->[1] eq "") { + $body .= ""; + } elsif ($col->[1] eq $FORM{'sort'}) { + $body .= ""; + } else { + $body .= ""; + } + } + } + + $body .= "\n"; + + foreach my $it (@items) + { + my $val; + my @vals; + + ## status + $val = $it->{'progress'} . "%
    " . LJ::ehtml($it->{'statusline'}); + push @vals, $val; + + ## priority + { + my $color; + if ($it->{'priority'} < 3) { $val = "-"; $color = "#0000C0"; } + if ($it->{'priority'} == 1) { $val = "--"; } + if ($it->{'priority'} > 3) { $val = "!"; $color = "#FF0000"; } + if ($it->{'priority'} == 5) { $val = "!!"; } + $val = $color ? "$val" : " "; + } + push @vals, $val; + + ## item & description + { + my $des = LJ::auto_linkify(LJ::ehtml($it->{'des'})); + $val = "{'todoid'}\">" . LJ::ehtml($it->{'subject'}) . "
    $des"; + push @vals, $val; + } + + ## due + { + $val = " "; + my $due = $it->{'datedue'}; + $due =~ s/:00$//; + $due =~ s/00:00$//; + if ($due) { + $val = "$due"; + } + push @vals, $val; + } + + ## categories + { + $val = ""; + foreach my $kwid (@{$itemkws{$it->{'todoid'}}}) { + if ($val) { $val .= ", "; } + $val .= $keyword{$kwid}->{'keyword'}; + } + $val = $val ? "$val" : " "; + push @vals, $val; + } + + ## print the row + + $body .= "\n"; + $body .= "\n" if ($permission{'delete'}); + foreach $val (@vals) { + $body .= ""; + } + $body .= "\n"; + } + + $body .= "
     $col->[0]>$col->[0] $u->{'user'}, 'sort' => $col->[1] }) . "\">$col->[0]
    {'todoid'}\">$val
    \n"; + + $body .= "

    " if ($permission{'delete'}); + $body .= "

    "; + + return; + +_code?> +body=>

    Note: The to-do list system is in beta. We're well aware it has a lot of work needed, and it definitely needs to be documented-- especially the security related things. standout?> +page?> +form: htdocs/todo/index.bml +post: htdocs/todo/index.bml +link: htdocs/todo/index.bml, htdocs/todo/item.bml + _c?> diff --git a/livejournal/htdocs/todo/item.bml b/livejournal/htdocs/todo/item.bml new file mode 100755 index 0000000..6d137a2 --- /dev/null +++ b/livejournal/htdocs/todo/item.bml @@ -0,0 +1,298 @@ +prepare("SELECT t.*, up.user AS 'posteruser' FROM todo t, useridmap up WHERE t.posterid=up.userid AND t.todoid=$id"); + $sth->execute; + $it = $sth->fetchrow_hashref; + unless ($it) { + $title = "Not found"; + $body = ""; + return; + } + + $u = LJ::load_userid($it->{'journalid'}); + + if ($it->{'security'} eq "private") { + unless ($remote && $remote->{'userid'} == $it->{'journalid'}) { + $title = "Sorry..."; + $body = ""; + return; + } + } + if ($it->{'security'} eq "friends") { + unless (LJ::is_friend($u, $remote)) { + $title = "Sorry..."; + $body = ""; + return; + } + } + + $sth = $dbh->prepare("SELECT k.keyword FROM todokeyword tk, keywords k WHERE tk.todoid=$id AND tk.kwid=k.kwid ORDER BY k.keyword"); + $sth->execute; + my @kws; + push @kws, $_ while ($_ = $sth->fetchrow_array); + $it->{'_cats'} = join(", ", @kws); + } + + $sth = $dbh->prepare("SELECT COUNT(*) FROM todo WHERE journalid=$u->{'userid'}"); + $sth->execute; + my ($todo_count) = $sth->fetchrow_array; + + LJ::Todo::get_permissions($dbh, \%permission, { 'user' => $u, + 'remote' => $remote, + 'item' => $it }); + + if ($FORM{'mode'} eq "save") { + + unless ($FORM{'subject'} =~ /\S+/) { + $title = "Error"; + $body = ""; + return; + } + + my $todoid = $FORM{'id'}+0; + my %q; + foreach my $key (qw(statusline security subject des priority datedue progress)) { + $q{$key} = $dbh->quote($FORM{$key}); + } + $q{'datedue'} = $dbh->quote(LJ::html_datetime_decode({ 'name' => 'datedue' }, \%FORM)); + + if ($todoid) { + unless ($permission{'edit'}) { + $title = "Error"; + $body = ""; + return; + } + + $sth = $dbh->prepare("UPDATE todo SET statusline=$q{'statusline'}, subject=$q{'subject'}, security=$q{'security'}, des=$q{'des'}, priority=$q{'priority'}, datedue=$q{'datedue'}, progress=$q{'progress'}, dateupdate=NOW() WHERE todoid=$todoid"); + $sth->execute; + if ($dbh->err) { $title = "Error"; $body = $dbh->errstr; return; } + + $title = "Modified"; + $body = "here or view the {'user'}\">updated list. p?>"; + + } else { + unless ($permission{'add'}) { + $title = "Error"; + $body .= ""; + return; + } + + ## check to see if user's todo list is full + my $max_items = LJ::get_cap($u, "todomax"); + if (defined $max_items && $todo_count >= $max_items) { + $title = "Sorry..."; + my $atype = "account type"; + if ($LJ::HELPURL{'accounttype'}) { + $atype = "$atype"; + } + $body .= ""; + return; + } + + $sth = $dbh->prepare("INSERT INTO todo (todoid, journalid, posterid, ownerid, statusline, security, subject, des, priority, datecreate, dateupdate, datedue, dateclosed, progress) VALUES (NULL, $u->{'userid'}, $remote->{'userid'}, $u->{'userid'}, $q{'statusline'}, $q{'security'}, $q{'subject'}, $q{'des'}, $q{'priority'}, NOW(), NULL, $q{'datedue'}, NULL, $q{'progress'})"); + $sth->execute; + if ($dbh->err) { return "db error: " . $dbh->errstr; } + $todoid = $sth->{'mysql_insertid'}; + + $title = "Added"; + $body = "here or view the {'user'}\">updated list. p?>"; + } + + if ($it->{'_cats'} ne $FORM{'categories'}) + { + #### we're inserting/replacing now into memories + my @keywords = split(/\s*,\s*/, $FORM{'categories'}); + if (scalar(@keywords) > 10) { + $title = "Error"; + $body = ""; + return; + } + @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords; + my @kwid; + + foreach my $kw (@keywords) { + if (length($kw) > 20) { + $title = "Error"; + $body = ""; + return; + } + + my $kwid = LJ::get_keyword_id($kw); + push @kwid, $kwid; + } + + $dbh->do("DELETE FROM todokeyword WHERE todoid=$todoid"); + if (@kwid) { + my $sql = "INSERT IGNORE INTO todokeyword (todoid, kwid) VALUES "; + # why IGNORE above? with mysql 3.23.x replication, a + # partial insert (some in, some dup -> fail) causes all + # slaves _not_ replicating that table to stop. fucked + # up, huh? so with IGNORE no error is generated. + $sql .= join(",", map { "($todoid,$_)" } @kwid); + $dbh->do($sql); + } + + } + return; + } + + if ($FORM{'mode'} eq "add") { + $title = "Add To-Do Item"; + $it = { 'todoid' => 0, + 'security' => 'public', + 'priority' => 3, + 'progress' => 0, + 'datedue' => '0000-00-00 00:00:00', + '_cats' => $FORM{'cat'}, + }; + + unless ($permission{'add'}) { + $disabled = "DISABLED"; + } + + my $max_items = LJ::get_cap($u, "todomax"); + if (defined $max_items && $todo_count >= $max_items) { + $title = "Sorry..."; + my $atype = "account type"; + if ($LJ::HELPURL{'accounttype'}) { + $atype = "$atype"; + } + $body .= ""; + return; + } + + } else { + unless ($permission{'edit'}) { + $disabled = "DISABLED"; + } + } + + $body .= "

    \n"; + $body .= "\n"; + $body .= "{'user'}\">\n"; + $body .= "{'todoid'}\">\n"; + + $body .= "{'user'}\"><< Back to To-Do List"; + if ($FORM{'mode'} eq "add") { + $body .= ""; + } else { + $body .= "
    {'todoid'} h1?>
    "; + if ($permission{'edit'}) { + $title = "Edit To-Do Item"; + } else { + $title = "View To-Do Item"; + } + } + + $body .= ""; + + ## subject + $hval = LJ::ehtml($it->{'subject'}); + $body .= "\n"; + + ## des + $hval = LJ::ehtml($it->{'des'}); + $body .= "\n"; + + ## statusline + $hval = LJ::ehtml($it->{'statusline'}); + $body .= "\n"; + + ## date due + $body .= ""; + + ## categories + $body .= ""; + + ## categories + $body .= ""; + + ## poster + if (($u->{'journaltype'} eq "C" || $it->{'posteruser'} != $u->{'user'}) && $it->{'posteruser'}) { + $body .= "\n"; + } + + ## submit buttton + { + my $permission = 0; + my $action = ""; + if ($it->{'todoid'}) { $action = "edit"; } else { + $action = "add"; + $title = "Add To-Do Item"; + } + $permission = $permission{$action}; + if ($permission) { + $body .= "\n"; + } + } + + $body .= "
    Subject:"; + $body .= " Priority: "; + $body .= LJ::html_select({ 'name' => 'priority', 'selected' => $it->{'priority'}, 'disabled' => $disabled }, + 5, "++ High", 4, "+", 3, "Normal", 2, "-", 1, "-- Low"); + $body .= "
    Details:
    Status:"; + $body .= ""; + + ## progress (percent complete) + $hval = LJ::ehtml($it->{'progress'}); + $body .= " Percent Done: %"; + $body .= "
    Due Date:"; + $body .= LJ::html_datetime({ 'name' => 'datedue', 'default' => $it->{'datedue'}, 'disabled' => $disabled }), + $body .= "
    Categories:"; + $hval = LJ::ehtml($it->{'_cats'}); + $body .= "
    "; + $body .= "
    Security:"; + { + my $todosec = LJ::get_cap($u, "todosec"); + if ($todosec) { + $body .= LJ::html_select({ 'name' => 'security', + 'selected' => $it->{'security'}, + 'disabled' => $disabled }, + "public" => "Public", + "private" => "Private", + "friends" => $u->{'journaltype'} eq "C" ? "Community Members" : "Friends"); + } else { + $body .= "Your account type doesn't permit non-public to-do items."; + } + } + $body .= "
    Poster:{'posteruser'} ljuser?>
    Done?"; + $body .= "\n"; + $body .= "
    "; + + + $body .= "
    \n"; + + return; + +_code?> +body=>

    Note: The to-do list system is in beta. We're well aware it has a lot of work needed, and it definitely needs to be documented-- especially the security related things. standout?> +page?> +link: htdocs/todo/index.bml, htdocs/todo/item.bml +post: htdocs/todo/item.bml + _c?> diff --git a/livejournal/htdocs/tools/emailmanage.bml b/livejournal/htdocs/tools/emailmanage.bml new file mode 100755 index 0000000..145ad70 --- /dev/null +++ b/livejournal/htdocs/tools/emailmanage.bml @@ -0,0 +1,116 @@ + +body<= + +{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my $firstdate = $dbh->selectrow_array(qq{ + SELECT MIN(timechange) FROM infohistory + WHERE userid=? AND what='email' + AND oldvalue=? + }, undef, $u->{'userid'}, $u->{'email'}); + + my @deleted; + if (LJ::did_post() && $u->{'status'} eq 'A') { + my $sth = $dbh->prepare("SELECT timechange, oldvalue " . + "FROM infohistory WHERE userid=? " . + "AND what='email' ORDER BY timechange"); + $sth->execute($u->{'userid'}); + while (my ($time, $email) = $sth->fetchrow_array) + { + my $can_del = defined $firstdate && $time gt $firstdate; + if ($can_del && $POST{"$email-$time"}) { + push @deleted, BML::ml('.log.deleted', + { 'email' => $email, + 'time' => $time }); + + $dbh->do("UPDATE infohistory SET what='emaildeleted' WHERE what='email' " . + "AND userid=? AND timechange=? AND oldvalue=?", + undef, $u->{'userid'}, $time, $email); + } + } + } + + my $ret; + + # authas switcher form + $ret .= "

    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "
    \n\n"; + + # some explanatory text + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + + $ret .= "\n"; + + unless ($u->{'status'} eq "A") { + $ret .= "\n"; + $ret .= " $u->{'email'} }) . " p?>"; + return $ret; + } + + # current address + $ret .= "\n"; + $ret .= "
    "; + $ret .= "$u->{'email'}
    \n"; + + # old addresses + $ret .= "\n"; + $ret .= ""; + + my $sth = $dbh->prepare("SELECT timechange, oldvalue FROM infohistory " . + "WHERE userid=? AND what='email' " . + "ORDER BY timechange"); + $sth->execute($u->{'userid'}); + my $rows; + while (my ($time, $email) = $sth->fetchrow_array) + { + my $can_del = defined $firstdate && $time gt $firstdate; + $rows .= "" . LJ::html_check({ 'type' => 'check', 'name' => "$email-$time", + 'disabled' => ! $can_del } ) . ""; + $rows .= "$email$time\n"; + } + + if ($rows) { + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + $ret .= "
    "; + $ret .= "\n"; + $ret .= $rows; + $ret .= "
    \n"; + $ret .= LJ::html_submit(undef, $ML{'.delete_selected'}); + $ret .= "
    "; + } else { + $ret .= "
    $ML{'.address.old.none'}
    \n"; + } + + if (@deleted) { + $ret .= "\n"; + $ret .= "
      "; + $ret .= "
    • $_
    • \n" foreach @deleted; + $ret .= "
    "; + } + + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/tools/index.bml b/livejournal/htdocs/tools/index.bml new file mode 100755 index 0000000..e69de29 diff --git a/livejournal/htdocs/tools/memadd.bml b/livejournal/htdocs/tools/memadd.bml new file mode 100755 index 0000000..3f18c18 --- /dev/null +++ b/livejournal/htdocs/tools/memadd.bml @@ -0,0 +1,335 @@ +("Invalid UTF-8 Input"); + } + + my $remote = LJ::get_remote(); + return $err->($ML{'error.noremote'}) + unless $remote; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $memoryu = LJ::get_authas_user($authas); + return $err->($ML{'error.invalidauth'}) + unless $memoryu; + + my %secopts = ( 'public' => $ML{'label.security.public'}, + 'friends' => $ML{'label.security.friends'}, + 'private' => $ML{'label.security.private'}, ); + + if ($memoryu->{'journaltype'} eq "C") { + $secopts{'private'} = $ML{'label.security.maintainers'}; + $secopts{'friends'} = $ML{'label.security.members'}; + } + + my $sth; + my $journal = $GET{'journal'}; + my $ditemid = $GET{'itemid'}+0; + + # OK. the memories schema is weird and stores *display* itemids in the database. + # additionally, we distinguish precluster itemids because they're stored without a userid. + # it's too late to fix it in the db, so we just work around it-- + # all new memories still get userid+ditemid because we can't change the ditemid/itemid problem, + # but old-style itemids get fixed up to userid+ditemid. + + # *however*, when editing old itemids we need to keep around + # the old-style ditemid so we can still edit it. + + # to keep this all sorted out, we fixup variables like this: + # - itemid -- real, new-style itemid + # - ditemid -- display itemid (with anum) + # - dbitemid -- itemid that is in the database; + # usually same as ditemid, but different for old-style itemids. + + my $dbitemid = $ditemid; + my $itemid; + my $oldstyle = 0; + my $ju; + my $jid; + + my $anum; + + if ($journal) { + $ju = LJ::load_user($journal); + $jid = $ju->{'userid'}; + $anum = $ditemid % 256; + $itemid = int($ditemid / 256); + } else { + # old-style item url? + my $newids = LJ::get_newids('L', $ditemid); + if ($newids) { + ($jid, $itemid) = @$newids; + $ju = LJ::load_userid($jid); + $oldstyle = 1; + } + } + + unless ($ju && $itemid) { + $title = $ML{'Error'}; + $body = $ML{'error.nojournal'}; + return; + } + + my $dbcr = LJ::get_cluster_reader($ju); + + my $log = LJ::get_log2_row($ju, $itemid); + unless ($log) { + $title = $ML{'Error'}; + $body = "Error retrieving data to add a memory."; + return; + } + my $subject = LJ::get_logtext2($ju, $itemid)->{$log->{jitemid}}[0]; + + # if the entry is pre-UTF-8 conversion, the + # subject may need conversion into UTF-8 + if ($LJ::UNICODE) { + my %props = (); + LJ::load_log_props2($dbcr, $log->{'journalid'}, [ $itemid ], \%props); + if ($props{$itemid}->{'unknown8bit'}) { + my $u = LJ::load_userid($log->{'journalid'}); + my ($error, $subj); + $subj = LJ::text_convert($subject, $u, \$error); + $subject = $subj unless $error; + } + LJ::text_out(\$subject); + } + + # check to see if it already is memorable (thus we're editing, not adding); + my $memory = LJ::Memories::get_by_ditemid($memoryu, $oldstyle ? 0 : $jid, $ditemid); + + if ($oldstyle) { + # ditemid was an old-style itemid, so we update it to the new style. + $anum = $log->{anum}; + $ditemid = $itemid<<8 + $anum; + } + + # get keywords user has used + my $exist_kw = LJ::Memories::get_keywords($memoryu); + unless ($exist_kw) { + $title = $ML{'Error'}; + $body = "Error fetching existing keywords."; + return; + } + + if ($POST{'mode'} eq "") + { + my ($des, $keywords); + + my @all_keywords; + my %selected_keyword; + @all_keywords = sort values %$exist_kw; + + if (defined $memory) { + $title = $ML{'.title.edit_memory'}; + $des = $memory->{'des'}; + my $kwids = LJ::Memories::get_keywordids($memoryu, $memory->{memid}) || []; + foreach my $kwid (@$kwids) { + my $kw = $exist_kw->{$kwid}; + next if ($kw eq "*"); + if ($keywords) { $keywords .= ", "; } + $keywords .= $kw; + $selected_keyword{$kw} = 1; + } + if (!$log || ($jid && $log->{'anum'} != $anum)) + { + LJ::Memories::delete_by_id($memoryu, $memory->{memid}); + LJ::Memories::updated_keywords($memoryu); + $title = $ML{'Error'}; + $body = $ML{'.error.entry_deleted'}; + return; + } + + } + elsif (!$log || ($jid && $log->{'anum'} != $anum)) + { + $title = $ML{'Error'}; + $body = $ML{'error.noentry'}; + return; + } + else + { + $title = $ML{'.title.add_memory'}; + + # this is a new memory. + my $user = LJ::get_username($log->{'journalid'}); + my $dt = substr($log->{'eventtime'}, 0, 10); + $des = "$dt: $user: $subject"; + } + + # it'd be nice to only show the authas form when adding an entry and not + # when editing one, but if user u is logged in and has post p as a memory + # already then wants to add it to community c, when u clicks the "add memory" + # link on p, u gets the "edit entry" page and they need to be able to switch + # to c. + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= LJ::html_hidden(journal => $GET{journal}) if $GET{journal}; + $body .= LJ::html_hidden(itemid => $GET{itemid}); + $body .= "
    \n\n"; + + LJ::text_out(\$des); + LJ::text_out(\$keywords); + + $body .= $ML{'.add_previous'}; + + my $getextra = "?itemid=$dbitemid"; + $getextra .= "&authas=$authas" if $authas ne $remote->{'user'}; + # we still need to pass the dbitemid and not the itemid to ourself. + $getextra .= "&journal=$journal" unless $oldstyle; + + $body .= "
    "; + $body .= LJ::html_hidden(mode => "save"); + + $body .= ""; + $body .= ""; + + $body .= "\n"; + $body .= "
    $ML{'.description'}"; + $body .= LJ::html_text({name => 'des', value => $des, maxlength => LJ::CMAX_MEMORY, size => 40}); + $body .= "
    $ML{'.description.text'}
    $ML{'.keywords'}"; + $body .= LJ::html_text({name => 'keywords', maxlength => LJ::CMAX_KEYWORD, size => 40, value => $keywords}); + $body .= "
    $ML{'.keywords.text'}
    "; + + if (@all_keywords) { + my $size = scalar(@all_keywords); + $size = 15 if $size > 15; + $body .= "$ML{'.keywords.select'}
    "; + $body .= LJ::html_select( { name => 'oldkeywords', size => $size, multiple => 1, + selected => [ keys %selected_keyword ], noescape => 1 }, + map { (LJ::ehtml($_), LJ::ehtml($_)) } @all_keywords); + $body .= "
    $ML{'.multiple_selections'}"; + } else { + $body .= "$ML{'.keywords.example'}"; + } + + $body .= "
    $ML{'.security'}"; + $body .= LJ::html_select({name => 'security', selected => defined $memory ? $memory->{'security'} : undef}, + map { ($_, $secopts{$_}) } qw(public friends private)); + if ($memoryu->{'journaltype'} eq "C") { + $body .= "
    $ML{'.whocansee.comm'}
    \n"; + } else { + $body .= "
    $ML{'.whocansee'}
    \n"; + } + $body .= LJ::html_submit(undef, $ML{'.form.submit'}); + $body .= LJ::html_submit(undef, $ML{'.form.reset'}, {type => 'reset'}) if defined $memory; + $body .= "
    "; + + return; + } + + if ($POST{'mode'} eq "save") + { + my $dbh = LJ::get_db_writer(); + + if (! $POST{'des'}) { + # then we're deleting. + if (defined $memory) { + LJ::Memories::delete_by_id($memoryu, $memory->{memid}); + LJ::Memories::updated_keywords($memoryu); + $title = $ML{'.title.deleted'}; + $body = " $memory->{'des'} }) . + "p?>"; + return; + } else { + $title = $ML{'Error'}; + $body = ""; + return; + } + } + + #### we're inserting/replacing now into memories + my @keywords; + { + my %kws; + foreach (split(/\s*,\s*/, $POST{'keywords'})) { $kws{$_} = 1; } + # oldkeywords were split at the beginning + foreach (@{$POST{'oldkeywords'}}) { $kws{$_} = 1; } + @keywords = keys %kws; + } + if (scalar(@keywords) > 5) { + $title = $ML{'Error'}; + $body = ""; + return; + } + @keywords = grep { $_ } map { s/\s\s+/ /g; LJ::trim($_); } @keywords; + push @keywords, "*" unless (@keywords); + my @kwid; + + my $needflush = 0; + foreach my $kw (@keywords) { + if (length($kw) > 40) { + $title = $ML{'Error'}; + $body = " LJ::ehtml($kw) }) . "p?>"; + return; + } + + my $kwid = LJ::get_keyword_id($memoryu, $kw); + $needflush = 1 unless defined $exist_kw->{$kwid}; + push @kwid, $kwid; + } + + unless (exists $secopts{$POST{'security'}}) { + $title = $ML{'Error'}; + $body = $ML{'.error.invalid_security'}; + return; + } + + my $des = LJ::text_trim($POST{'des'}, LJ::BMAX_MEMORY, LJ::CMAX_MEMORY); + my $sec = $POST{'security'}; + + # handle edits by deleting the old memory and recreating + LJ::Memories::delete_by_id($memoryu, $memory->{memid}) + if defined $memory; + LJ::Memories::create($memoryu, { + journalid => $jid, + ditemid => $ditemid, + des => $des, + security => $sec, + }, \@kwid); + LJ::Memories::updated_keywords($memoryu) if $needflush; + + $title = $ML{'.title.added'}; + $body = "{user}, $itemid, $anum); + $body .= BML::ml('.body.added.body2', {'aopts' => "href='$backlink'"}); + $body .= " p?>"; + + return; + } + + $title = $ML{'Error'}; + $body = $ML{'error.unknownmode'}; + + return; +_code?> + + +body=> +page?> + + +link: htdocs/login.bml +post: htdocs/tools/memadd.bml + _c?> diff --git a/livejournal/htdocs/tools/memories.bml b/livejournal/htdocs/tools/memories.bml new file mode 100755 index 0000000..2abd043 --- /dev/null +++ b/livejournal/htdocs/tools/memories.bml @@ -0,0 +1,291 @@ +\n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $authasu->{user} }) . "\n"; + $body .= LJ::html_hidden(keyword => $GET{keyword}) if $GET{keyword}; + $body .= "\n\n"; + + $user ||= $authasu->{user}; + $authasarg = "&authas=$authasu->{user}"; + $authasarge = "&authas=$authasu->{user}"; + } else { + $authasu = $remote; + } + } + + # Now, whose memories page do we actually want to see? + # - if 'user' is specified, we want to see theirs + # (in this case, $user has already been set to that) + # - if no 'user', but 'authas' is specified, we want to see authas's + # (in this case, $user has been set to $authasu->{user} above + # - if neither is specified, we want to see remote's: + + if ($user eq "" && defined $remote) { + $user = $remote->{'user'}; + } + + my $u = LJ::load_user($user); + unless ($u) { + # There is no 'authas' OR $remote. + # If there's a 'user', that user doesn't exist. + # Otherwise, complain about the absence of 'user' / suggest logging in. + $title = $ML{'Error'}; + $body = $user eq "" ? BML::ml('.login', { 'aopts' => 'href="/login.bml?ret=1"' }) + : $ML{'error.username_notfound'}; + return; + } + + # owner if you've authed as them or you administrate them + my $is_owner = $authasu && $user eq $authasu->{user} || + LJ::can_manage_other($remote, $u); + + my $userid = $u->{'userid'}; + + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + return BML::redirect("/tools/memories.bml?user=$u->{'renamedto'}$authasarg"); + } + + LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; + unless ($u->{'statusvis'} eq 'V' && ! $u->{'opt_blockrobots'}) { + $head = LJ::robot_meta_tags(); + } + + if ($u->{'statusvis'} eq "S") { + $title = $ML{'error.suspended.title'}; + $body = "$LJ::SITENAME,'user'=>$user}) . " p?>"; + return; + } + + if ($u->{'statusvis'} eq "D") { + $title = $ML{'error.deleted.title'}; + $body = "$user}) . " p?>"; + return; + } + + if ($u->{'statusvis'} eq "X") { + $title = $ML{'error.purged.title'}; + $body = ""; + return; + } + + if (LJ::did_post()) { + unless ($is_owner) { + $title = $ML{'Error'}; + $body = "\n"; + return; + } + + my @to_delete = (); + foreach (keys %POST) { + push @to_delete, $1 if /^select_mem_(\d+)$/; + } + + unless (@to_delete) { + $title = $ML{'Error'}; + $body = ""; + return; + } + + # delete them! + LJ::Memories::delete_by_id($authasu, \@to_delete); + $title = $ML{'.delete.deleted.title'}; + $body = " "href='./memories.bml?user=$authasu->{user}'" }) . " p?>"; + return; + } + + my %filters = ("all" => $ML{'.filter.all'}, + "own" => BML::ml(".filter.own", { 'user' => $user }), + "other" => $ML{'.filter.other'}); + my $filter = $GET{'filter'} || "all"; + unless (defined $filters{$filter}) { $filter = "all"; } + + my %sorts = ('memid' => $ML{'.sort.orderadded'}, + 'des' => $ML{'.sort.description'}, + 'user' => $ML{'.sort.journal'}); + my $sort = ($GET{'sortby'} || 'memid'); + unless (defined $sorts{$sort}) { $sort = 'memid'; } + + # keys must be the same as those of %sorts + my %sortfunc = ('memid' => sub { + sort { $a->{'memid'} <=> $b->{'memid'} } @_; + }, + 'des' => sub { + sort { $a->{'des'} cmp $b->{'des'} } @_; + }, + 'user' => sub { + sort { $a->{'user'} cmp $b->{'user'} || + $a->{'des'} cmp $b->{'des'} } @_; + }); + + my $securities = ['public']; + if ($authasu) { + if ($is_owner) { + $securities = []; + } elsif ($authasu->{'journaltype'} eq 'P' and LJ::is_friend($userid, $authasu->{'userid'})) { + $securities = ['public', 'friends']; + } + } + + my $kwmap = LJ::Memories::get_keywords($u); + return $dberr->() unless defined $kwmap; + + if ($GET{'keyword'}) + { + if ($GET{'keyword'} eq "*") { + $title = $ML{'.title.memorable'}; + $body .= " $user }) . " p?>"; + } else { + my $ekw = LJ::ehtml($GET{'keyword'}); + $title = BML::ml(".title.keyword", { 'keyword' => $ekw, 'user' => $user }); + $body .= BML::ml(".body.keyword", { 'keyword' => $ekw, 'user' => $user }); + } + + $body .= "
    "; + $body .= LJ::html_hidden(keyword => $GET{keyword}) if $GET{keyword}; + $body .= LJ::html_hidden(user => $GET{user}) if $GET{user}; + $body .= LJ::html_hidden(authas => $GET{user}) if $GET{authas}; + $body .= "$ML{'.form.sort'} "; + $body .= "
    \n"; + $body .= "<< $ML{'.back'}"; + + my $key_id; + foreach (keys %$kwmap) { + $key_id = $_ if $kwmap->{$_} eq $GET{keyword}; + } + my $memoryhash = LJ::Memories::get_by_keyword($u, $key_id, + { security => $securities, filter => $filter }); + return $dberr->() unless defined $memoryhash; + my @jids = map { $_->{journalid} } values %$memoryhash; + my $us = LJ::load_userids(@jids); + my @memories = $sortfunc{$sort}->( values %$memoryhash ); + + $body .= "
    \n" + if $is_owner && $GET{multidelete}; + $body .= "
      \n"; + foreach my $mem (@memories) { + my $user = $us->{$mem->{journalid}}{user}; + my $eh_des = LJ::ehtml($mem->{'des'}); + LJ::text_out(\$eh_des); + + my ($entrylink, $editlink); + if ($user) { + my $itemid = int($mem->{'ditemid'} / 256); + my $anum = $mem->{'ditemid'} % 256; + $entrylink = LJ::item_link($user, $itemid, $anum); + $editlink = "/tools/memadd.bml?journal=$user&itemid=$mem->{ditemid}$authasarge"; + } else { + $entrylink = "/talkread.bml?itemid=$mem->{ditemid}"; + $editlink = "/tools/memadd.bml?itemid=$mem->{ditemid}$authasarge"; + } + + my $edit = ""; + my $delete = ""; + if ($is_owner) { + $edit = " [$ML{'.edit'}]"; + $delete = LJ::html_check({ type => 'check', name => "select_mem_$mem->{memid}", value => 1 }) + if $GET{multidelete}; + } + + my %icons = ( + 'friends' => "", + 'private' => "", + ); + $body .= "

    • $delete $eh_des $edit $icons{$mem->{security}}
      $user
    • "; + } + $body .= "
    "; + if ($is_owner && $GET{multidelete}) { + $body .= LJ::html_submit(undef, $ML{'.delete'}, + { onclick => "return confirm('" . LJ::ejs($ML{'.delete.confirm'}) . "')" }); + $body .= "
    \n"; + } + return; + } + + $title = $ML{'.title.memorable'}; + $body .= BML::ml(".body.list_categories", { 'user' => $user }); + + my $rows = LJ::Memories::get_keyword_counts($u, { security => $securities, filter => $filter }); + return $dberr->() unless defined $rows; + my @sortedrows; + push @sortedrows, { keyword => $kwmap->{$_}, count => $rows->{$_} } + foreach keys %{$rows || {}}; + @sortedrows = sort { $a->{'keyword'} cmp $b->{'keyword'} } @sortedrows; + + $body .= "
    "; + $body .= ""; + $body .= "$ML{'.form.filter'} "; + $body .= "
    "; + + unless (@sortedrows) { + $body .= ""; + } else { + $body .= "
      "; + foreach my $row (@sortedrows) { + my $noun = BML::ml(".plur_entry", {'num' => $row->{'count'}}); + my $ue_keyword = LJ::eurl($row->{'keyword'}); + my $keyword = $row->{'keyword'}; + LJ::text_out(\$keyword); + if ($keyword eq "*") { $keyword = $ML{'.uncategorized'}; } + else { $keyword = LJ::ehtml($keyword); } + $body .= "
    • $keyword: $noun\n
    • "; + } + $body .= "
    "; + } + return; + +_code?> +head=> +body<= + +<=body +page?> +link: htdocs/tools/memories.bml, htdocs/tools/memadd.bml, htdocs/talkread.bml +form: htdocs/tools/memories.bml + _c?> diff --git a/livejournal/htdocs/tools/recent_comments.bml b/livejournal/htdocs/tools/recent_comments.bml new file mode 100755 index 0000000..1719cc8 --- /dev/null +++ b/livejournal/htdocs/tools/recent_comments.bml @@ -0,0 +1,266 @@ +Recent Comments +head<= + +<=head +body<= +{user}; + $LJ_cmtinfo{'journal'} = $remote->{user}; + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + return LJ::bad_input($ML{'error.invalidauth'}) + unless $u; + + my $user = $u->{'user'}; + + my $dbcr = LJ::get_cluster_reader($u); + return "Error: can't get DB for user" unless $dbcr; + + my $count = LJ::get_cap($u, "tools_recent_comments_display"); + + # authas switcher form + $ret .= "
    \n"; + $ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $ret .= "
    \n\n"; + + my (@recv, @posted, %talkids); + my %need_userid; + my %logrow; # "jid nodeid" -> $logrow + my %need_logids; # hash of "journalid jitemid" => [journalid, jitemid] + + my $now = time(); + my $sth; + + my $jargent ="journal=$u->{'user'}&"; + + # Retrieve received + { + my $max = $dbcr->selectrow_array("SELECT MAX(jtalkid) FROM talk2 WHERE journalid=?", + undef, $u->{userid}); + $sth = $dbcr->prepare("SELECT jtalkid, nodetype, nodeid, parenttalkid, ". + " posterid, UNIX_TIMESTAMP(datepost) as 'datepostunix', state ". + "FROM talk2 ". + "WHERE journalid=? AND jtalkid > ?"); + $sth->execute($u->{userid}, $max - $count); + die $dbcr->errstr if $dbcr->err; + while (my $r = $sth->fetchrow_hashref) { + $need_userid{$r->{posterid}} = 1 if $r->{posterid}; + push @recv, $r; + $talkids{$r->{jtalkid}} = 1; + $need_logids{"$u->{userid} $r->{nodeid}"} = [$u->{userid}, $r->{nodeid}] + if $r->{nodetype} eq "L"; + } + } + + # Retrieve posted + if ($u->{journaltype} eq "P") { + $sth = $dbcr->prepare("SELECT posttime, journalid, nodetype, nodeid, jtalkid, publicitem ". + "FROM talkleft ". + "WHERE userid=? ORDER BY posttime DESC LIMIT $count"); + $sth->execute($u->{'userid'}); + my %jcount; # jid -> ct + $ret .= ""; + while (my $r = $sth->fetchrow_hashref) { + push @posted, $r; + $need_logids{"$r->{journalid} $r->{nodeid}"} = [$r->{journalid}, $r->{nodeid}] + if $r->{nodetype} eq "L"; + $need_userid{$r->{journalid}} = 1; + } + } + + $ret .= "
    " . + BML::ml('ActionLink', { 'link' => "Latest Received"}) . " " . + BML::ml('Actionlink', { 'link'=>"Latest Posted"}) . "
    " if $u->{journaltype} eq "P"; + + $ret .= ""; + $ret .= ""; + + @recv = sort { $b->{datepostunix} <=> $a->{datepostunix} } @recv; + my @recv_talkids = map { $_->{'jtalkid'} } @recv; + + my %props; + LJ::load_talk_props2($u->{'userid'}, \@recv_talkids, \%props); + + my $us = LJ::load_userids(keys %need_userid); + + # setup the parameter to get_logtext2multi + my $need_logtext = {}; + foreach my $need (values %need_logids) { + my $ju = $us->{$need->[0]}; + next unless $ju; + push @{$need_logtext->{$ju->{clusterid}} ||= []}, $need; + } + + my $comment_text = LJ::get_talktext2($u, keys %talkids); + my $log_text = LJ::get_logtext2multi($need_logtext); + my $root = LJ::journal_base($u); + + $ret .= "
    "; + foreach my $r ( @recv) { + next unless $r->{nodetype} eq "L"; + next if $r->{state} eq "D"; + + my $pu = $us->{$r->{posterid}}; + next if $pu->{statusvis} =~ /[XS]/; + + $r->{'props'} = $props{$r->{'jtalkid'}}; + + my $lrow = $logrow{"$u->{userid} $r->{nodeid}"} ||= LJ::get_log2_row($u, $r->{'nodeid'}); + my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'}; + + my $ditemid = "$root/$lrow->{ditemid}.html"; + my $talkurl = "$root/$lrow->{ditemid}.html?thread=$talkid\#t$talkid"; + + my $bgcolor = "transparent"; + my $state = ""; + if ($r->{state} eq "S") { + $bgcolor = BML::fill_template("screenedbarcolor"); + $state = "Screened"; + } elsif ($r->{state} eq "D") { + $state = "Deleted"; + } elsif ($r->{state} eq "F") { + $state = "Frozen"; + } + + my $ljcmt = $LJ_cmtinfo{$talkid} = {}; + $ljcmt->{u} = $pu ? $pu->{user} : ""; + + $ret .= ""; + + } + $ret .= "
    "; + $ret .= ($pu ? LJ::ljuser($pu) : "Anonymous") . "
    "; + + $ret .= LJ::ago_text($now - $r->{datepostunix}) . "
    "; + $ret .= "
    $state
    " if $r->{state} ne "D"; + + unless ($r->{state} eq "D") + { + $ret .= "" . LJ::img("btn_del", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + if ($r->{'state'} ne 'F') { + $ret .= "" . LJ::img("btn_freeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($r->{'state'} eq 'F') { + $ret .= "" . LJ::img("btn_unfreeze", "", { align => 'absmiddle', hspace => 2, vspace => }) . ""; + } + + if ($r->{'state'} ne 'S') { + $ret .= "" . LJ::img("btn_scr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + + if ($r->{'state'} eq 'S') { + $ret .= "" . LJ::img("btn_unscr", "", { 'align' => 'absmiddle', 'hspace' => 2, 'vspace' => }) . ""; + } + } + + # FIXME: (David?) We'll have to make talk_multi.bml understand jtalkids in multiple posts + #$ret .= " "; + #$ret .= " "; + + $ret .= "
    "; + + my $subject = $log_text->{"$u->{userid} $r->{nodeid}"}[0]; + LJ::CleanHTML::clean_subject(\$subject) if $subject ne ""; + + $ret .= "$subject " if $subject ne ""; + $ret .= "(Entry Link)" unless $lrow->{ditemid} == undef; + $ret .= "

    "; + my $subject = $comment_text->{$r->{jtalkid}}[0]; + LJ::CleanHTML::clean_subject(\$subject); + + if ($subject && $subject !~ /^Re:\s*$/) { + $ret .= "$subject
    "; + } + + my $comment = $comment_text->{$r->{jtalkid}}[1]; + LJ::CleanHTML::clean_comment(\$comment, { 'preformatted' => $r->{'props'}->{'opt_preformatted'}, + 'anon_comment' => !$pu }); + $ret .= "$comment

    "; + + $ret .= "(Comment Link) " unless $r->{state} eq "D" || $lrow->{ditemid} == undef; + + my $stylemine = 0; + my $replyurl = LJ::Talk::talkargs($ditemid, "replyto=$talkid", $stylemine); + if ($lrow->{ditemid} == undef) { + $ret .= "(Post Deleted)"; + } elsif ($r->{'state'} eq 'F') { + $ret .= "($ML{'talk.frozen'}) "; + } elsif ($r->{'state'} eq "D") { + $ret .= "(Comment Deleted)"; + } else { + $ret .= "($ML{'talk.replytothis'}) "; + } + + $ret .= "
    "; + + $ret .= " $count, 'max' => $LJ::TOOLS_RECENT_COMMENTS_MAX }). + " p?>" unless $count == $LJ::TOOLS_RECENT_COMMENTS_MAX; + + + if ($u->{journaltype} eq "P") { + $ret .= "
    " . + BML::ml('Actionlink', { 'link'=>"Latest Received"}) . + BML::ml('ActionLink', { 'link' => "Latest Posted"}) . " " . + "
    "; + $ret .= ""; + my %jcount; # jid -> ct + $ret .= ""; + $ret .= ""; + + foreach my $r (@posted) { + $jcount{$r->{'journalid'}}++; + next unless $r->{'nodetype'} eq "L"; # log2 comment + + my $ju = $us->{$r->{journalid}}; + my $lrow = $logrow{"$ju->{userid} $r->{nodeid}"} ||= LJ::get_log2_row($ju, $r->{'nodeid'}); + my $talkid = ($r->{'jtalkid'} << 8) + $lrow->{'anum'}; + + my $logurl = "$LJ::SITEROOT/users/$ju->{user}/$lrow->{ditemid}.html"; + my $talkurl = "$logurl?thread=$talkid\#t$talkid"; + + my $hr_ago = LJ::ago_text($now - $r->{'posttime'}); + my $subject; + if (defined $lrow->{ditemid}) { + $hr_ago = "$hr_ago"; + $subject = $log_text->{"$r->{journalid} $r->{nodeid}"}[0] || "$lrow->{ditemid}.html"; + LJ::CleanHTML::clean_subject(\$subject); + $subject = "$subject"; + } else { + $subject = "Post Deleted"; + } + + my $links = "[Comment] [Entry]\n"; + $ret .= ""; + } + $ret .= "
    TimeLocation
    $hr_ago" . LJ::ljuser($ju->{user}) . ": $subject
    "; + } + + my $js_screen_color = "\"" . LJ::ejs(BML::get_template_def("screenedbarcolor")) . "\""; + $ret .= ""; + + return $@ || $ret; + +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/tools/search.bml b/livejournal/htdocs/tools/search.bml new file mode 100755 index 0000000..70237e4 --- /dev/null +++ b/livejournal/htdocs/tools/search.bml @@ -0,0 +1,67 @@ +Search a Journal +body<= + +Note: This search is provided by an independent company, Feedster.com, and is provided solely as a convenience. We are not responsible for the resulting content or search results. +p?> + + +}; + + my $rss_feed = LJ::journal_base($u) . '/data/rss'; + $ret .= LJ::html_hidden('hl' => 'en', 'ie' => 'UTF-8', 'inrss' => $rss_feed); + + $ret .= qq{ + + + + + + + + + + + + + + + + + +
    Searching in:$ljuser
    Search for:
    Sort by: +
    + + +
    +
    +
     
    + +standout?> +}; + + return $ret; +} +_code?> +<=body +page?> diff --git a/livejournal/htdocs/tools/sixdegrees.bml b/livejournal/htdocs/tools/sixdegrees.bml new file mode 100755 index 0000000..0b205cc --- /dev/null +++ b/livejournal/htdocs/tools/sixdegrees.bml @@ -0,0 +1,45 @@ +Six Degrees +body<= + + + + +{user} : "")); + my $to_user = LJ::canonical_username($GET{'to'}); + + my $ret; + $ret .= qq{
    +From user: +To user: + +
    }; + + if ($from_user ne "" && $to_user ne "") { + my $fu = LJ::load_user($from_user); + my $tu = LJ::load_user($to_user); + my @path = LJ::SixDegrees::find_path($fu, $tu, 3); + $ret .= "Path:"; + if (@path) { + $ret .= join(" > ", map { LJ::ljuser($_) } @path); + } else { + $ret .= "(none found)"; + } + } + + return $ret; + +} +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/tools/tellafriend.bml b/livejournal/htdocs/tools/tellafriend.bml new file mode 100755 index 0000000..ade1e4e --- /dev/null +++ b/livejournal/htdocs/tools/tellafriend.bml @@ -0,0 +1,157 @@ +login. p?>"; + return; + } + + my $u = LJ::load_userid($remote->{'userid'}); + $u->{'emailpref'} = $u->{'email'}; + if ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail")) { + $u->{'emailpref'} = $u->{'user'} . '@' . $LJ::USER_DOMAIN; + } + + unless ($u->{'status'} eq "A") { + $body .= "{'email'}) isn't validated, so we can't let you use the \"Tell a Friend\" feature. To validate your email address, have the confirmation email resent at the lost information page, and then follow the instructions in it when you get it. p?>"; + return; + } + + my $err = sub { + $title = "Error"; + $body = ""; + return; + }; + + if ($FORM{'mode'} eq "mail") + { + my $email = $FORM{'toemail'}; + my @errors; + LJ::check_email($email, \@errors); + push @errors, "" unless LJ::did_post(); + if (@errors) { + $title = "Error"; + $body = LJ::bad_input(@errors); + return; + } + + LJ::send_mail({ + 'to' => $FORM{'toemail'}, + 'toname' => $FORM{'toname'}, + 'from' => $u->{'emailpref'}, + 'fromname' => $FORM{'fromname'}, + 'charset' => 'utf-8', + 'subject' => $FORM{'subject'}, + 'body' => $FORM{'body'}, + }); + + $body .= ""; + return; + } + + $body .= "
    "; + $body .= ""; + + $body .= "\n"; + $body .= "\n"; + + $body .= "\n"; + $body .= "\n"; + + my ($subject, $msg); + $subject = "Check this out..."; + if ($FORM{'itemid'} =~ /^\d+$/) + { + my $journal = $FORM{'journal'}; + my $itemid = $FORM{'itemid'}+0; + my $ditemid = $itemid; + my $uj; + + $itemid = int($itemid / 256); + + $uj = LJ::load_user($journal); + return $err->("Unknown journal") unless $uj; + + my $dbcr = LJ::get_cluster_reader($uj); + my ($posterid, $subject) = $dbcr->selectrow_array("SELECT l.posterid, ls.subject ". + "FROM log2 l, logtext2 ls ". + "WHERE l.journalid=? AND ls.journalid=l.journalid ". + "AND l.jitemid=? AND ls.jitemid=l.jitemid", + undef, $uj->{'userid'}, $itemid); + my $up; + LJ::load_userids_multiple([ $posterid => \$up ], [ $uj, $u ]); + + my $base = LJ::journal_base($uj); + my $url = "$base/$ditemid.html"; + + if ($up->{'user'} eq $u->{'user'}) { + $msg .= "Hey,\n\nCheck out this journal entry of mine:\n\n"; + } else { + $msg .= "Hey,\n\nCheck this out... I saw this journal entry while reading " . $up->{'user'} . "'s journal:\n\n"; + } + $msg .= " $subject\n" if $subject; + $msg .= " $url\n\n"; + $msg .= "I thought you might be interested.\n\n"; + } + + if ($FORM{'user'} =~ /^\w{1,15}$/) { + my $user = $FORM{'user'}; + my $uj = LJ::load_user($user); + my $url; + if (LJ::get_cap($uj, "userdomain")) { + my $sub = $user; + $sub =~ s/_/-/g; + $url .= "http://$sub.$LJ::USER_DOMAIN/"; + } else { + $url .= "$LJ::SITEROOT/users/$user/"; + } + + if ($user eq $u->{'user'}) { + $msg .= "Hey,\n\nCheck out my journal that I'm keeping online:\n\n"; + $msg .= " $url\n\n"; + my $name = $u->{'name'}; + $name =~ s/\s.+//; + $msg .= "- $name\n"; + } else { + $msg .= "Hey,\n\nCheck out my friend's journal online:\n\n"; + $msg .= " $url\n\n"; + my $name = $u->{'name'}; + $name =~ s/\s.+//; + $msg .= "- $name\n"; + } + } + + my $subject = "Check it out..."; + $body .= "\n"; + + $body .= "\n"; + + $body .= "\n"; + $body .= "
    From:{'name'} || "$LJ::SITENAME User") . "\">
     $u->{'emailpref'}
    To (Name):
    To (Email):
    Subject:
    Body:
     
    "; + $body .= "
    "; + + return; + +_code?> +body=> +page?> +lib: cgi-bin/emailcheck.pl +link: htdocs/login.bml, htdocs/lostinfo.bml, htdocs/users, htdocs/talkread.bml +form: htdocs/tools/tellafriend.bml + _c?> diff --git a/livejournal/htdocs/tools/textmessage.bml b/livejournal/htdocs/tools/textmessage.bml new file mode 100755 index 0000000..b9fff84 --- /dev/null +++ b/livejournal/htdocs/tools/textmessage.bml @@ -0,0 +1,143 @@ +Send a Text Message +body<= +"; + $ret .= "
      "; + foreach my $p (LJ::TextMessage::providers()) { + my $info = LJ::TextMessage::provider_info($p); + $ret .= "

      $info->{'name'} (from: $info->{'fromlimit'}, msg: $info->{'msglimit'}, total: $info->{'totlimit'})
      $info->{'notes'}"; + } + $ret .= "

    "; + &add_footer(); + return $ret; + } + + unless ($user) { + $ret .= "
    Username:
  • p?>"; + &add_footer(); + return $ret; + } + + my $u = LJ::load_user($user); + my $tminfo; + + if ($u->{'txtmsg_status'} eq "on") { + my $dbr = LJ::get_db_reader(); + $tminfo = $dbr->selectrow_hashref("SELECT provider, number, security ". + "FROM txtmsg WHERE userid=$u->{'userid'}") + } + + unless (LJ::get_cap($u, "textmessaging")) { + $ret .= ""; + &add_footer(); + return $ret; + } + + unless ($tminfo) { + $ret .= ""; + &add_footer(); + return $ret; + } + + my $remote; + if ($tminfo->{'security'} ne "all") { + $remote = LJ::get_remote(); + my $andbefriend; + if ($tminfo->{'security'} eq "friends") { + $andbefriend = " and be listed as their friend"; + } + unless ($remote) { + $ret .= "logged in$andbefriend. p?>"; + &add_footer(); + return $ret; + } + + if ($tminfo->{'security'} eq "friends" && $u->{'userid'} != $remote->{'userid'}) { + unless (LJ::is_friend($u->{'userid'}, $remote->{'userid'})) { + $ret .= "$u->{'user'} has selected \"friends only\" as the security level required to send text messages to them. p?>"; + &add_footer(); + return $ret; + } + } + } + + ###### authorized. + + if ($FORM{'message'}) { + my $message = $FORM{'message'}; + my $from = $tminfo->{'security'} eq "all" ? $FORM{'from'} : $remote->{'user'}; + + my $phone = new LJ::TextMessage { 'provider' => $tminfo->{'provider'}, + 'number' => $tminfo->{'number'}, + 'mailcommand' => $LJ::SENDMAIL, + 'smtp' => $LJ::SMTP_SERVER, + }; + my @errors; + $phone->send({ 'from' => $from, + 'message' => $message, }, + \@errors); + + # strip numbers from error messages + s/(\d{3,})/'x'x length $1/eg foreach @errors; + + return LJ::bad_input(@errors) if @errors; + + $ret .= ""; + &add_footer(); + return $ret; + } + + my $pinfo = LJ::TextMessage::provider_info($tminfo->{'provider'}); + + $ret .= "$u->{'user'}. p?>"; + $ret .= "
      "; + $ret .= "
      {'user'}\" />"; + $ret .= "From: "; + my $maxlen = $pinfo->{'totlimit'}; + if ($tminfo->{'security'} eq "all") { + $ret .= "{'user'}\">\n"; + $maxlen -= 15; + } else { + $ret .= "{'user'}\">\n"; + $ret .= "$remote->{'user'}"; + $maxlen -= length($remote->{'user'}); + } + if ($pinfo->{'msglimit'} < $maxlen) { $maxlen = $pinfo->{'msglimit'}; } + $ret .= "

      Message: (max $maxlen characters ... type until it stops you)
      "; + + $ret .= "\n"; + $ret .= "

      "; + $ret .= "
    "; + + &add_footer(); + return $ret; + + sub add_footer + { + my $howwork = $LJ::HELP_URL{'textmessaging_about'} ? "How does this feature work? Read this.
    " : ""; + $ret .= "


    $howworkDisclaimer: The reliability of text messaging should not be trusted in dealing with emergencies."; + } + +} +_code?> +<=body +page?> +lib: LJ::TextMessage +link: htdocs/login.bml, htdocs/support/faqbrowse.bml +form: htdocs/tools/textmessage.bml +post: htdocs/tools/textmessage.bml + _c?> diff --git a/livejournal/htdocs/translate/diff.bml b/livejournal/htdocs/translate/diff.bml new file mode 100755 index 0000000..0c05a5f --- /dev/null +++ b/livejournal/htdocs/translate/diff.bml @@ -0,0 +1,156 @@ + + + + + + +Invalid language" unless $l; + + return "Invalid item" unless $GET{'it'} =~ /^(\d+):(\d+)$/; + my ($dmid, $itid) = ($1, $2); + + my @lnids = $l->{'lnid'}; + { + my $il = $l; + while ($il && $il->{'parentlnid'}) { + push @lnids, $il->{'parentlnid'}; + $il = LJ::Lang::get_lang_id($il->{'parentlnid'}); + } + } + my $lnids = join(",", @lnids); + + my $dbr = LJ::get_db_reader(); + my ($sth, $ret); + + my $sth = $dbr->prepare("select * from ml_text where dmid=$dmid and itid=$itid and lnid in ($lnids) ORDER BY txtid"); + $sth->execute; + my @tlist; + while (my $t = $sth->fetchrow_hashref) { + next if @tlist && $t->{'text'} eq $tlist[-1]->{'text'}; + push @tlist, $t; + } + + my $changes = scalar @tlist - 1; + return "No changes" unless $changes; + + my $view_change = $GET{'change'} || $changes; + return "bogus change" if $view_change < 1 || $view_change > $changes; + for (1..$changes) { + if ($_ eq $view_change) { + $ret .= "[Change $_]\n"; + } else { + $ret .= "[Change $_]\n"; + } + } + $ret .= "
    "; + my $was = $tlist[$view_change-1]->{'text'}; + my $then = $tlist[$view_change]->{'text'}; + + my ($was_alt, $then_alt) = ($was, $then); + foreach (\$was_alt, \$then_alt) { + $$_ =~ s/\n/*NEWLINE*/g; + $$_ =~ s/\s+/\1\n/g; + $$_ .= "\n"; + } + + my ($was_file, $then_file, $fh); + my $tries = 0; + + ($fh, $was_file) = tempfile(); + print $fh $was_alt; close $fh; + ($fh, $then_file) = tempfile(); + print $fh $then_alt; close $fh; + + my @words = split(/\n/, $was_alt); + my $diff = `diff -u $was_file $then_file`; + + my $pos = 0; + my $mode; + my $setmode = sub { + my $newmode = shift; + return " " if $newmode eq $mode; + my $ret; + $ret .= "" if $mode; + $ret .= " "; + $ret .= "<$newmode>" if $newmode; + $mode = $newmode; + return $ret; + }; + + foreach my $dl (split(/\n/, $diff)) { + next if $dl =~ /^(\+\+\+|\-\-\-)/; + if ($dl =~ /^\@\@ \-(\d+),(\d+)/) { + my $newpos = $1; + $ret .= $setmode->(""); + for (my $i=$pos+1; $i<$newpos; $i++) { + my $word = LJ::ehtml($words[$i-1]); + $word =~ s/\*NEWLINE\*/
    \n/g; + $ret .= "$word "; + $pos++; + } + next; + } + if ($dl =~ /^ /) { + $pos++; + my $word = LJ::ehtml($words[$pos-1]); + $word =~ s/\*NEWLINE\*/
    \n/g; + $ret .= $setmode->("") . $word; + } + if ($dl =~ /^\-/) { + $pos++; + my $word = LJ::ehtml($words[$pos-1]); + $word =~ s/\*NEWLINE\*/
    \n/g; + $ret .= $setmode->("del") . $word; + } + if ($dl =~ /^\+(.*)/) { + my $word = LJ::ehtml($1); + $word =~ s/\*NEWLINE\*/
    \n/g; + $ret .= $setmode->("ins") . $word; + } + } + + $ret .= $setmode->(""); + while ($pos < @words) { + my $word = LJ::ehtml($words[$pos]); + $word =~ s/\*NEWLINE\*/
    \n/g; + $ret .= "$word "; + $pos++; + } + + $was = LJ::eall($was); + $was =~ s/\n( *)/"
    " . " "x length($1)/eg; + $then = LJ::eall($then); + $then =~ s/\n( *)/"
    " . " "x length($1)/eg; + + $ret .= "

    "; + $ret .= "
    Before:
    $was
    After:
    $then
    "; + + unlink($was_file, $then_file); + + return $ret; + +} +_code?> + + diff --git a/livejournal/htdocs/translate/edit.bml b/livejournal/htdocs/translate/edit.bml new file mode 100755 index 0000000..985d186 --- /dev/null +++ b/livejournal/htdocs/translate/edit.bml @@ -0,0 +1,16 @@ + + + Language Editor + + + + + + + + + + + diff --git a/livejournal/htdocs/translate/editpage.bml b/livejournal/htdocs/translate/editpage.bml new file mode 100755 index 0000000..6975bc3 --- /dev/null +++ b/livejournal/htdocs/translate/editpage.bml @@ -0,0 +1,318 @@ + + + + + +Invalid language" unless $l; + my $lp = $l->{'parentlnid'} ? LJ::Lang::get_lang_id($l->{'parentlnid'}) : undef; + + my $dbr = LJ::get_db_reader(); + my $dbh; + my ($sth, $ret); + + my $remote = LJ::get_remote(); + my $can_edit = (LJ::check_priv($remote, "translate", "*") || + LJ::check_priv($remote, "translate", $l->{'lncode'})); + my $can_delete = LJ::check_priv($remote, "translate", "[itemdelete]"); + my $can_rename = LJ::check_priv($remote, "translate", "[itemrename]"); + + my $mode = { + '' => 'view', + 'save' => 'save', + }->{$FORM{'mode'}}; + return "bogus mode" unless $mode; + + my $MAX_EDIT = 100; + + if ($mode eq "view") + { + my @load; + foreach (split /,/, $FORM{'items'}) + { + next unless /^(\d+):(\d+)$/; + last if @load >= $MAX_EDIT; + push @load, { 'dmid' => $1, 'itid'=> $2 }; + } + + return "Nothing to show." unless @load; + + $ret .= "

    "; + $ret .= LJ::html_hidden('lang', $lang, + 'mode', 'save'); + + # load item info + my %ml_items; + my $itwhere = join(" OR ", map { "(dmid=$_->{'dmid'} AND itid=$_->{'itid'})" } @load); + $sth = $dbr->prepare("SELECT dmid, itid, itcode, notes FROM ml_items WHERE $itwhere"); + $sth->execute; + while (my ($dmid, $itid, $itcode, $notes) = $sth->fetchrow_array) { + $ml_items{"$dmid-$itid"} = { 'itcode' => $itcode, 'notes' => $notes }; + } + + # getting latest mappings for this lang and parent + my %ml_text; + my %ml_latest; + $sth = $dbr->prepare("SELECT lnid, dmid, itid, txtid, chgtime, staleness FROM ml_latest ". + "WHERE ($itwhere) AND lnid IN ($l->{'lnid'}, $l->{'parentlnid'})"); + $sth->execute; + return $dbr->errstr if $dbr->err; + while ($_ = $sth->fetchrow_hashref) { + $ml_latest{"$_->{'dmid'}-$_->{'itid'}"}->{$_->{'lnid'}} = $_; + $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = undef; # mark to load later + } + + # load text + $sth = $dbr->prepare("SELECT dmid, txtid, lnid, itid, text FROM ml_text ". + "WHERE " . join(" OR ", + map { "(dmid=$_->[0] AND txtid=$_->[1])" } + map { [ split(/-/, $_) ] } keys %ml_text)); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + $ml_text{"$_->{'dmid'}-$_->{'txtid'}"} = $_; + } + + if ($can_delete) { + $ret .= "

    To delete an item: edit text to be \"XXDELXX\"

    "; + } + + # show all editing items + my $ict = 0; + foreach my $i (@load) + { + my ($dmid, $itid) = ($i->{'dmid'}, $i->{'itid'}); + my $ituq = "$dmid-$itid"; + my $it = $ml_items{$ituq}; + my $lat = $ml_latest{$ituq}->{$l->{'lnid'}}; + next unless $it and $lat; + $ict++; + + my $plat; + if ($lp && defined $ml_latest{$ituq}->{$lp->{'lnid'}}) { + $plat = $ml_latest{$ituq}->{$lp->{'lnid'}}; + } + + $ret .= LJ::html_hidden("dom_$ict", $dmid, + "itid_$ict", $itid, + "oldtxtid_$ict", $lat->{'txtid'}, + "oldptxtid_$ict", $plat ? $plat->{'txtid'} : 0, + ); + + # top bar + $ret .= ""; + $ret .= ""; + $ret .= "
    Code: "; + if ($dmid != 1) { + my $d = LJ::Lang::get_dom_id($dmid); + $ret .= "[$d->{'uniq'}] "; + } + + my $difflink; + if ($lat->{'staleness'}) { + $difflink = "($plat->{'chgtime'}, {'itid'}&lang=$lp->{'lncode'}'>diff)"; + } + + $ret .= "$it->{'itcode'} $difflinkSev: $lat->{'staleness'}
    "; + + $ret .= "
    "; + if ($it->{'notes'}) { + my $notes = $it->{'notes'}; + $notes =~ s!\n!
    !g; + $ret .= "
    Notes:
    $notes
    "; + } + + my $show_edit = 0; + my $use_textarea = 0; + + if ($plat) { + $ret .= "
    $lp->{'lnname'}:
    "; + my $t = $ml_text{"$plat->{'dmid'}-$plat->{'txtid'}"}->{'text'}; + if ($t =~ /\n/) { $use_textarea = 1; } + if (length($t) > 255) { $use_textarea = 1; } + $t = LJ::eall($t); + $t =~ s/\n( *)/"
    " . " "x length($1)/eg; + $ret .= "
    $t
    "; + } + + my $curtext = LJ::eall($ml_text{"$lat->{'dmid'}-$lat->{'txtid'}"}->{'text'}); + if ($curtext =~ /\n/) { $use_textarea = 1; } + if (length($curtext) > 255) { $use_textarea = 1; } + if ($lat->{'staleness'} >= 3) { + # if wrong language, why populate it with stuff they'll just have to delete? + $curtext = ""; + } + + $ret .= "
    $l->{'lnname'}:
    "; + my $disabled = "disabled='disabled'"; + if ($lat->{'staleness'} >= 3) { + $disabled = ""; + # when something's this stale, assume both it's being + # edited and that the severity is major (going from wrong + # language to right language is a major change, afterall) + $ret .= LJ::html_hidden("ed_$ict", "1", + "sev_$ict", "2", + ); + } else { + $ret .= ""; + if ($l->{'children'} && @{$l->{'children'}}) { + $ret .= " Severity: "; + $ret .= LJ::html_select({ 'name' => "sev_$ict", "selected" => 1 }, + 0 => "Typo/etc (no notify)", + 1 => "Minor (notify translators)", + 2 => "Major (require translation updates)"); + } + $ret .= "
    "; + } + if ($use_textarea) { + $ret .= ""; + } else { + $ret .= ""; + } + $ret .= "
    \n"; + $ret .= "
    "; + } + + if ($ict) { + $ret .= LJ::html_hidden("ict", $ict); + my $disabled = $can_edit ? "" : "disabled='disabled'"; + $ret .= "
    "; + } else { + $ret .= "No items to show. (since been deleted, perhaps?)"; + } + $ret .= "
    "; + + return $ret; + } + + if ($mode eq "save") + { + my $num = $FORM{'ict'}+0; + $num = $MAX_EDIT if $num > $MAX_EDIT; + + my (@errors, @info); + unless ($can_edit) { + push @errors, "You don't have access to edit text for this language."; + $num = 0; + } + + unless (LJ::text_in(\%FORM)) { + push @errors, "You seem to have changed your browser's encoding to something other than UTF-8. It needs to be in UTF-8."; + push @errors, "Nothing saved."; + $num = 0; + } + + my $saved = 0; # do any saves? + + for (my $i=1; $i<=$num; $i++) + { + next unless $FORM{"ed_$i"}; + my ($dom, $itid, $oldtxtid, $oldptxtid, $sev) = + map { int($FORM{"${_}_$i"}+0) } qw(dom itid oldtxtid oldptxtid sev); + + my $itcode = $dbr->selectrow_array("SELECT itcode FROM ml_items WHERE dmid=$dom AND itid=$itid"); + unless (defined $itcode) { + push @errors, "Bogus dmid/itid: $dom/$itid"; + next; + } + + $dbh ||= LJ::get_db_writer(); + my $lat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$l->{'lnid'} AND dmid=$dom AND itid=$itid"); + unless ($lat) { + push @errors, "No existing mapping for $itcode"; + next; + } + unless ($lat->{'txtid'} == $oldtxtid) { + push @errors, "Another translator updated '$itcode' before you saved, so your edit has been ignored."; + next; + } + + my $plat; + if ($lp) { + $plat = $dbh->selectrow_hashref("SELECT * FROM ml_latest WHERE lnid=$lp->{'lnid'} ". + "AND dmid=$dom AND itid=$itid"); + my $ptid = $plat ? $plat->{'txtid'} : 0; + unless ($ptid == $oldptxtid) { + push @errors, "The source text of item '$itcode' changed while you were editing, so your edit has been ignored."; + next; + } + } + + # did they type anything? + my $text = $FORM{"newtext_$i"}; + next unless $text =~ /\S/; + + # delete + if ($text eq "XXDELXX") { + if ($can_delete) { + $dbh->do("DELETE FROM ml_latest WHERE dmid=$dom AND itid=$itid"); + push @info, "Deleted: '$itcode'"; + } else { + push @errors, "You don't have access to delete items."; + } + next; + } + + # did anything even change, though? + my $oldtext = $dbr->selectrow_array("SELECT text FROM ml_text WHERE dmid=$dom AND txtid=$lat->{'txtid'}"); + if ($oldtext eq $text && $lat->{'staleness'} == 2) { + push @errors, "Severity of source language change requires change in text for item '$itcode'"; + next; + } + + # keep old txtid if text didn't change. + my $opts = {}; + if ($oldtext eq $text) { + $opts->{'txtid'} = $lat->{'txtid'}; + $text = undef; + $sev = 0; + } + + # if setting text for first time, push down to children langs + if ($lat->{'staleness'} == 4) { + $opts->{'childrenlatest'} = 1; + } + + # severity of change: + $opts->{'changeseverity'} = $sev; + + # set userid of writer + $opts->{'userid'} = $remote->{'userid'}; + + my $res = LJ::Lang::set_text($dom, $l->{'lncode'}, $itcode, $text, $opts); + unless ($res) { + push @errors, LJ::Lang::last_error(); + } else { + push @info, "Saved: $itcode"; + $saved = 1; + } + } + + $dbh ||= LJ::get_db_writer(); + $dbh->do("UPDATE ml_langs SET lastupdate=NOW() WHERE lnid=$l->{'lnid'}") if $saved; + + if (@errors) { + $ret .= "ERRORS:
      "; + foreach (@errors) { $ret .= "
    • $_
    • "; } + $ret .= "
    "; + } + if (@info) { + $ret .= "Results:
      "; + foreach (@info) { $ret .= "
    • $_
    • "; } + $ret .= "
    "; + } + if (! @errors && ! @info) { + $ret .= "No errors & nothing saved."; + } + return $ret; + } + +_code?> + + diff --git a/livejournal/htdocs/translate/help-severity.bml b/livejournal/htdocs/translate/help-severity.bml new file mode 100755 index 0000000..45955a8 --- /dev/null +++ b/livejournal/htdocs/translate/help-severity.bml @@ -0,0 +1,12 @@ +

    Description of severity levels:

    + + + + + + + +
    0Translate is up-to-date
    1Parent language has changed a little. Your translation might need updating.
    2Parent language has changed. Your translation probably needs updating.
    3New text was added in parent language which you haven't yet translated.
    4Item code in use but no text exists yet for any language.
    + +

    Searching

    +When searching, you can search for a certain severity level (0, 1, 2, 3, 4) or search for everything at or above a certain severity level (0+, 1+, 2+, 3+). diff --git a/livejournal/htdocs/translate/index.bml b/livejournal/htdocs/translate/index.bml new file mode 100755 index 0000000..5831c04 --- /dev/null +++ b/livejournal/htdocs/translate/index.bml @@ -0,0 +1,70 @@ +Translation Area +body<= + +prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs"); + $sth->execute; + my %lang; + $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref; + + $sth = $dbr->prepare("SELECT lnid, staleness > 1, COUNT(*) FROM ml_latest GROUP by 1, 2"); + $sth->execute; + while (my ($lnid, $stale, $ct) = $sth->fetchrow_array) { + next unless exists $lang{$lnid}; + $lang{$lnid}->{'_total'} += $ct; + $lang{$lnid}->{'_good'} += (1-$stale) * $ct; + $lang{$lnid}->{'percent'} = 100 * $lang{$lnid}->{'_good'} / ($lang{$lnid}->{'_total'}||1); + } + + my $sortcol = exists $lang{'1'}->{$FORM{'s'}} ? $FORM{'s'} : "lnname"; + my @cols = (['lncode','Code'], + ['lnname','Language Name', sub { + my $r = shift; + "$r->{'lnname'}"; + }], + ['percent','% Done', sub { + my $r = shift; + "" . + sprintf("%.02f%%", $r->{'percent'}) . "
    " . + "$r->{'_good'}/$r->{'_total'}" . + ""; + }, sub { $b->{'percent'} <=> $a->{'percent'} || + $b->{'_total'} <=> $a->{'_total'} }], + ['lastupdate','Last Update',undef, + sub { $b->{'lastupdate'} cmp $a->{'lastupdate'} }]); + my $ret; + my $sorter = sub { $a->{$sortcol} cmp $b->{$sortcol} }; + + $ret .= "The following table lists the progress by each of the different translation teams."; + + $ret .= "

    "; + foreach (@cols) { + if ($sortcol eq $_->[0]) { + $ret .= ""; + } else { + $ret .= ""; + } + if ($_->[0] eq $sortcol && $_->[3]) { $sorter = $_->[3]; } + } + $ret .= "\n"; + + foreach my $r (sort $sorter values %lang) { + $ret .= ""; + foreach (@cols) { + $ret .= $_->[2] ? $_->[2]->($r) : ""; + } + $ret .= "\n"; + } + + $ret .= "
    $_->[1][0]\">$_->[1]
    $r->{$_->[0]}
    \n"; + return $ret; + +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/translate/search.bml b/livejournal/htdocs/translate/search.bml new file mode 100755 index 0000000..d4dbc9f --- /dev/null +++ b/livejournal/htdocs/translate/search.bml @@ -0,0 +1,77 @@ +Invalid language" unless $l; + + my $dbr = LJ::get_db_reader(); + my $sth; + + my $sql; + + if ($FORM{'search'} eq 'sev') + { + my $what = ">= 1"; + if ($FORM{'stale'} =~ /^(\d+)(\+?)$/) { + $what = ($2 ? ">=" : "=") . $1; + } + $sql = "SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l WHERE l.lnid=$l->{'lnid'} AND l.staleness $what AND l.dmid=i.dmid AND l.itid=i.itid ORDER BY i.dmid, i.itcode"; + } + + if ($FORM{'search'} eq 'txt') + { + my $remote = LJ::get_remote(); + return "This search type is restricted to $l->{'lnname'} translators." unless + (LJ::check_priv($remote, "translate", "*") || + LJ::check_priv($remote, "translate", $l->{'lncode'}) || + LJ::check_priv($remote, "faqedit", "*")); # FAQ admins can search too + + my $qtext = $dbr->quote($FORM{'searchtext'}); + my $dmid = $FORM{'searchdomain'}+0; + my $dmidwhere = $dmid ? "AND i.dmid=$dmid" : ""; + if ($FORM{'searchwhat'} eq "code") { + $sql = qq{ + SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l + WHERE l.lnid=$l->{'lnid'} AND l.dmid=i.dmid AND i.itid=l.itid + $dmidwhere AND LOCATE($qtext, i.itcode) + }; + } else { + my $lnid = $l->{'lnid'}; + if ($FORM{'searchwhat'} eq "parent") { $lnid = $l->{'parentlnid'}; } + $sql = qq{ + SELECT i.dmid, i.itid, i.itcode FROM ml_items i, ml_latest l, ml_text t + WHERE l.lnid=$lnid AND l.dmid=i.dmid AND i.itid=l.itid + $dmidwhere AND t.dmid=l.dmid AND t.txtid=l.txtid AND LOCATE($qtext, t.text) + ORDER BY i.itcode + }; + } + } + + return "Bogus or unimplemented query type." unless $sql; + + my $ret; + $sth = $dbr->prepare($sql); + $sth->execute; + my $page = 0; + my @page = (); + my $addlink = sub { + return unless @page; + $page++; + my $link = "editpage.bml?lang=$lang&items=" . LJ::eurl(join(",",map{"$_->[0]:$_->[1]"}@page)); + $ret .= "Page $page
    \n"; + $ret .= "$page[0]->[2]
    \n"; + $ret .= "$page[-1]->[2]
    \n"; + @page = (); + }; + while (my ($dmid, $itid, $itcode) = $sth->fetchrow_array) { + push @page, [ $dmid, $itid, $itcode ]; + $addlink->() if @page >= 10; + } + $addlink->(); + + if ($page == 0) { $ret .= "(No matches)"; } + + return $ret; + +} +_code?> diff --git a/livejournal/htdocs/translate/searchform.bml b/livejournal/htdocs/translate/searchform.bml new file mode 100755 index 0000000..d7e35b9 --- /dev/null +++ b/livejournal/htdocs/translate/searchform.bml @@ -0,0 +1,61 @@ + +Search Form + + + +

    +'> + + +[<-- Back] +" . ($l ? $l->{'lnname'} : "Invalid language") . ""; +_code?> + +

    By Severity: (help)
    +

    +
    + +
    +'> + + +

    Search +{'parentlnid'}); + my @opt = ("src" => $l->{'lnname'}); + if ($pl) { push @opt, "parent", $pl->{'lnname'} }; + push @opt, "code", "Item Code"; + $ret .= LJ::html_select({ 'name' => 'searchwhat' }, + @opt); + $ret .= "
    Area: "; + $ret .= LJ::html_select({ 'name' => 'searchdomain' }, + 0, "(all)", + map { $_->{'dmid'}, $_->{'uniq'} } + sort { $a->{'dmid'} <=> $b->{'dmid'} } LJ::Lang::get_domains()); + return $ret; +_code?> +
    Text: +

    + + +
    + + + + diff --git a/livejournal/htdocs/translate/teams.bml b/livejournal/htdocs/translate/teams.bml new file mode 100755 index 0000000..b345d2c --- /dev/null +++ b/livejournal/htdocs/translate/teams.bml @@ -0,0 +1,65 @@ +Translation Teams +body<= + + << Back to progress page. + + + + +prepare("SELECT lnid, lncode, lnname, lastupdate FROM ml_langs"); + $sth->execute; + my %lang; + $lang{$_->{'lnid'}} = $_ while $_ = $sth->fetchrow_hashref; + + # get each lang's community + $sth = $dbr->prepare("SELECT l.lnid, t.text ". + "FROM ml_latest l, ml_items i, ml_text t ". + "WHERE l.dmid=1 AND t.dmid=1 AND i.dmid=1 AND i.itcode='thislang.community' ". + "AND l.itid=i.itid AND t.txtid=l.txtid AND t.lnid=l.lnid"); + $sth->execute; + while ($_ = $sth->fetchrow_hashref) { + next unless exists $lang{$_->{'lnid'}}; + $lang{$_->{'lnid'}}->{'community'} = $_->{'text'}; + } + + # get people with privs + $sth = $dbr->prepare("SELECT pm.arg, u.user FROM useridmap u, priv_list pl, priv_map pm ". + "WHERE pm.userid=u.userid AND pm.prlid=pl.prlid AND pl.privcode='translate'"); + $sth->execute; + my %team; + while (my ($arg, $user) = $sth->fetchrow_array) { + push @{$team{$arg}}, $user; + } + + $ret .= "

    "; + $ret .= ""; + + foreach my $l (sort { $a->{'lncode'} cmp $b->{'lncode'} } values %lang) + { + $ret .= ""; + $ret .= "\n"; + } + + $ret .= "
    LanguageCommunityUsers with privs
    $l->{'lnname'}"; + $ret .= "{'community'} ljcomm?>" if $l->{'community'}; + $ret .= ""; + if ($team{$l->{'lncode'}}) { + $ret .= join(", ", map { LJ::ljuser($_) } + sort @{$team{$l->{'lncode'}}}); + } + $ret .= "
    "; + return $ret; + +_code?> + +<=body +page?> diff --git a/livejournal/htdocs/translate/welcome.bml b/livejournal/htdocs/translate/welcome.bml new file mode 100755 index 0000000..3b6c672 --- /dev/null +++ b/livejournal/htdocs/translate/welcome.bml @@ -0,0 +1,7 @@ +Welcome to the translation area. + +

    In the top-left frame you search for phrases to translate. + +

    The lower-left frame shows your search result links, paginated. + +

    This large frame is the work area, in which text is edited. diff --git a/livejournal/htdocs/unsubscribe.bml b/livejournal/htdocs/unsubscribe.bml new file mode 100755 index 0000000..4473051 --- /dev/null +++ b/livejournal/htdocs/unsubscribe.bml @@ -0,0 +1,58 @@ +Unsubscribe +body<= + +edit info page and change the setting there. p?>"; + } + + if (($aa = LJ::is_valid_authaction($aaid, $auth)) + && $aa->{'action'} eq "nonews" + ) + { + if ($confirm) + { + my $quid = $aa->{'userid'}+0; + LJ::update_user($quid, { allow_getljnews => 'N' }); + return ""; + } + else + { + my $ret = ""; + $ret .= ""; + $ret .= "

    \n"; + my $eaaid = LJ::ehtml($aaid); + my $eauth = LJ::ehtml($auth); + $ret .= "\n"; + $ret .= "\n"; + $ret .= "\n"; + $ret .= "
    \n"; + return $ret; + + } + my $blah = join(", ", %$aa); + return $blah; + } + else + { + my $blah = join(", ", %$aa); + return ""; + } + + + +_code?> + +<=body +page?> +post: htdocs/unsubscribe.bml +link: htdocs/editinfo.bml + _c?> diff --git a/livejournal/htdocs/update.bml b/livejournal/htdocs/update.bml new file mode 100755 index 0000000..e08d378 --- /dev/null +++ b/livejournal/htdocs/update.bml @@ -0,0 +1,402 @@ +{'title'}; + my $head = \$_[1]->{'head'}; + my $body = \$_[1]->{'body'}; + my $bodyopts = \$_[1]->{'bodyopts'}; + + $$title = $ML{'.title'}; + + # server down? + if ($LJ::SERVER_DOWN) { + $$body = LJ::server_down_html(); + return; + } + + LJ::set_active_crumb("update"); + + # invalid text input? + unless (LJ::text_in(\%POST)) { + $$body = ""; + return; + } + + # get remote and see if they can post right now + my $remote = LJ::get_remote(); + + # Errors that are unlikely to change between starting + # to compose an entry and submitting it. + if ($remote) { + if ($remote->underage) { + return BML::redirect("$LJ::SITEROOT/agecheck/?s=1"); + } + + if ($remote->identity) { + $$title = "Sorry"; + $$body = "Non-$LJ::SITENAME users can't post, as they don't actually have journals here. You can leave comments in other journals, though."; + return; + } + + if (! LJ::get_cap($remote, "can_post")) { + $$title = "Can't Post"; + $$body = $LJ::MSG_NO_POST || $ML{'.error.cantpost'}; + return; + } + + if (LJ::get_cap($remote, "disable_can_post")) { + unless (LJ::run_hook("update.bml_disable_can_post", { + title => $title, body => $body, + })) { + $$title = $ML{'.error.disabled.title'}; + $$body = $ML{'.error.disabled'}; + } + return; + } + } + + my %res = (); + + # see if we need to do any transformations + LJ::run_hooks("transform_update_$POST{transform}", \%GET, \%POST) if $POST{transform}; + + # Set up form default values: + my @time = localtime(time); + my ($year, $mon, $mday, $hour, $min) = ($time[5] + 1900, + sprintf("%02d", $time[4] + 1), + sprintf("%02d", $time[3]), + $time[2], + sprintf("%02d", $time[1])); + my $subject = $POST{'subject'} || $GET{'subject'}; + my $event = $POST{'event'} || $GET{'event'}; + + ### define some bools with common logic ### + my $did_post = LJ::did_post() && !$POST{transform}; # transforms aren't posts + my $user_is_remote = $remote && $remote->{'user'} eq $POST{'user'}; # user is remote + my $auth_as_remote = $remote && (! $GET{'altlogin'} || $user_is_remote); # auth as remote + my $auth_missing = $POST{'user'} && + ! $POST{'password'} && + ! $user_is_remote && + ! $POST{'response'}; # user w/o password + + # which authentication option do we display by default? + my $altlogin_display = 'none'; + my $remotelogin_display = 'none'; + if ($auth_as_remote) { + $remotelogin_display = 'table-row'; + } else { + $altlogin_display = 'table-row'; + } + + # Check for errors, store in hash to render later + my $errors; my $onload = "shift_contents(); "; + my $showform = $POST{'showform'} || $auth_missing; # show entry form + my $preview = $POST{'action:preview'}; + + # are we spellchecking before we post? + my $did_spellcheck; my $spellcheck_html; + if ($LJ::SPELLER && $POST{'action:spellcheck'}) { + $did_spellcheck++; + my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, + 'color' => '', }; + my $event = LJ::ehtml($event); + $spellcheck_html = $s->check_html(\$event); + $spellcheck_html = "" unless $spellcheck_html ne ""; + $onload .= "pageload(0); "; # js fill-in off + + my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, \%POST); + ($year, $mon, $mday) = split( /\D/, $date); + $hour = $POST{'hour'}; + $min = $POST{'min'}; + } else { + $onload .= "pageload(1); "; # js fill-in on + + my @time = localtime(time); + $year = $time[5] + 1900; + $mon = sprintf("%02d", $time[4] + 1); + $mday = sprintf("%02d", $time[3]); + $hour = $time[2]; + $min = sprintf("%02d", $time[1]); + } + + # richtext + # 'switched_rte_on' is only set when the user first enables rte. We do this in a POST + # so any pre-existing text in the event and subject fields aren't lost when going to RTE. + # 'rich' is used to keep RTE mode enabled between pages, such as spellchecks. + # The $GET{'rich'} is simply for user bookmarking / faq linking convenience. + my $enabled_rte = $POST{'switched_rte_on'}; + my $richtext = 1 if $GET{rich} || $POST{rich} || + ($enabled_rte && ! $spellcheck_html && ! $preview); + $$bodyopts .= "onunload=\"save_entry();\" " if $richtext; + + my $print_entry_form = sub { + my $opts = shift; + + # authentication box + my $auth = ''; + + if ($remote) { # so lynx won't show this + $auth .= "$ML{'.auth.poster'}"; + $auth .= BML::ml(".loggedinas", {'user' => $remote->{'user'}, 'altget' => "?altlogin=1" }); + $auth .= "\n"; + } + + # table with username/password fields + $auth .= "\n"; + $auth .= "" . BML::ml('Username') . ":"; + $auth .= "" . LJ::html_text({ 'name' => 'user', 'size' => '15', 'maxlength' => '15', + 'value' => $POST{'user'} || $GET{'user'} }); + $auth .= "\n"; + $auth .= ""; + $auth .= "" . BML::ml('Password') . ":"; + $auth .= "" . LJ::html_text({ 'type' => 'password', 'name' => 'password', + 'size' => '15', 'maxlength' => '30' }); + # posted with a user, but no password + if ($did_post && $auth_missing) { + $auth .= "
    "; + } + $auth .= ""; + + # if they submit the form and are spellchecking, remember + # their settings from the GET requests + my $getextra; + $getextra .= "altlogin=1&" if $GET{'altlogin'}; + $getextra .= "rich=1&" if $richtext; + chop $getextra; + $getextra = "?$getextra" if $getextra; + + my $entry = { + 'mode' => "update", + 'auth_as_remote' => $auth_as_remote, + 'subject' => $subject, + 'event' => $event, + 'datetime' => "$year-$mon-$mday $hour:$min", + 'usejournal' => $POST{'usejournal'} || $GET{'usejournal'}, + 'auth' => $auth, + 'remote' => $remote, + 'spellcheck_html' => $spellcheck_html, + 'clientversion' => "WebUpdate/2.0.0", + 'richtext' => 1, + 'richtext_on' => $richtext, + }; + + if ($did_post) { + $entry->{$_} = $POST{$_} foreach keys %POST; + } + + if (LJ::isu($remote) && (!$did_post || $did_spellcheck) && $remote->readonly) { + $$body .= "
    "", + 'a_close' => ""} + ); + } else { + $$body .= BML::ml('.rowarn', { + 'a_open' => '', + 'a_close' => ''} + ); + } + + $$body .= " warningbar?>
    "; + } + + $$body .= "
    "; + + if ($opts->{require_tos}){ + $$body .= LJ::tosagree_html('update', $POST{agree_tos}, $errors->{require_tos}); + } + + $$body .= LJ::entry_form($entry, \$$head, \$onload, $errors); + $$body .= "
    "; + + $$bodyopts .= "onload=\"$onload\" onresize=\"shift_contents();\" "; + + return; + }; + + if ($did_post && !$did_spellcheck && !$showform && !$enabled_rte && !$preview ) { + + # what's our authentication scheme for subsequent protocol actions? + my $flags = {}; + my ($u, $user); + + if ($POST{'user'} && # user argument given + ! $user_is_remote && # user != remote + (!$remote || $GET{'altlogin'})) { # user has clicked alt auth + + $user = $POST{'user'}; + $u = LJ::load_user($user); + + # Verify entered password, if it is present. + my $ok; + if ($POST{response}) { + $ok = LJ::challenge_check_login($u, $POST{chal}, $POST{response}); + } else { # js disabled, fallback to plaintext + $ok = LJ::auth_okay($u, $POST{password}); + } + $flags = { 'noauth' => 1, 'u' => $u } if $ok; + + } elsif ($remote && LJ::check_referer()) { # assume remote if we have it + $flags = { 'noauth' => 1, 'u' => $remote }; + $user = $remote->{'user'}; + $u = $remote; + } + + if ($u && ! $u->tosagree_verify) { + if ($POST{agree_tos}) { + my $err = ""; + unless ($u->tosagree_set(\$err)) { + # error + $errors->{require_tos} = $err; + $print_entry_form->({ require_tos => 1 }); + return; + } + # successfully set + } else { + $errors->{require_tos} = $ML{'tos.error'}; + $print_entry_form->({ require_tos => 1 }); + return; + } + } + + # Check if the account they're posting to is read-only + my $uj = $POST{'usejournal'} ? LJ::load_user($POST{'usejournal'}) : $u; + if ($uj && $uj->readonly) { + # Tell the user they can't post since read only + $$body .= "$ML{'.error.update'} "; + $$body .= $LJ::MSG_READONLY_USER; + $$body .= " errorbar?>
    "; + + $print_entry_form->(); + return + } + + # do a login action + my $login_message; + { + # build a clientversion string + my $clientversion = "Web/2.0.0"; + $clientversion .= 's' if $did_spellcheck; + + # build a request object + my %req = ( 'mode' => 'login', + 'ver' => $LJ::PROTOCOL_VER, + 'clientversion' => $clientversion, + 'user' => $user, + ); + + my %res; + LJ::do_request(\%req, \%res, $flags); + + # error logging in ? + unless ($res{'success'} eq 'OK') { + $errors->{'auth'} = $ML{'.error.login'} . " " . LJ::ehtml($res{'errmsg'}); + } + + # server login message for user? + $login_message = LJ::auto_linkify(LJ::ehtml($res{'message'})) + if $res{'message'}; + } + # any messages from the server? + if ($login_message) { + $$body .= "$ML{'.loggingin'} $ML{'.servermsg'} p?>
    $login_message
    "; + } + + my %req = ( 'mode' => 'postevent', + 'ver' => $LJ::PROTOCOL_VER, + 'user' => $user, + 'password' => $POST{'password'}, + 'usejournal' => $POST{'usejournal'}, + ); + + LJ::entry_form_decode(\%req, \%POST); + if ($req{'event'} eq "") { + $errors->{'entry'} = "Must provide entry text"; + } + + my %res; + LJ::do_request(\%req, \%res, $flags); + + if (!$errors) { + # examine response + my $update_message; + if ($res{'success'} eq "OK" && $res{'message'}) { + $update_message = LJ::auto_linkify(LJ::ehtml($res{'message'})); + } + + # report results + $$body .= "$ML{'.updating'} "; + + if ($res{'success'} ne 'OK') { + # update failed? + $$body .= "
    $ML{'.error.update'} "; + $$body .= LJ::ehtml($res{'errmsg'}) . " errorbar?>"; + $$body .= "
    p?>"; + } else { + # short bail if this was posted moderated or some other special case (no itemid but a message) + if (!defined $res{itemid} && $res{message}) { + $$body .= "
    $res{message} p?>"; + return; + } + + # update success + my $ju; + if ($POST{'usejournal'}) { + $ju = LJ::load_user($POST{'usejournal'}); # posting as community + } elsif ($user) { + $ju = LJ::load_user($user); # posting not as user from form + } else { + $ju = $remote; # posting as remote + }; + $$body .= BML::ml(".update.success", { 'uri' => LJ::journal_base($ju) . "/" }); + my $juser = $ju->{'user'}; + my ($itemid, $anum) = ($res{'itemid'}, $res{'anum'}); + my $itemlink = LJ::item_link($ju, $itemid, $anum); + $itemid = $itemid * 256 + $anum; + $$body .= " p?>"; + return; + } + } + } + + $print_entry_form->(); + return; +} + +_code?> {'title'}; _code?> +body=> {'body'}; _code?> +bodyopts=>{'bodyopts'}; _code?> +head<= + + +{'head'}; + $ret .= ""; + $ret .= (! $LJ::REQ_HEAD_HAS{'chalresp_js'}++) ? $LJ::COMMON_CODE{'chalresp_js'} : ""; + return $ret; +} +_code?> + +<=head +page?> +lib: LJ::SpellCheck +link: htdocs/users, htdocs/download/index.bml, htdocs/moodlist.bml +link: htdocs/update.bml, htdocs/lostinfo.bml, htdocs/support/faqbrowse.bml +link: htdocs/allpics.bml +post: htdocs/update.bml + _c?> diff --git a/livejournal/htdocs/userinfo.bml b/livejournal/htdocs/userinfo.bml new file mode 100755 index 0000000..6d669a8 --- /dev/null +++ b/livejournal/htdocs/userinfo.bml @@ -0,0 +1,1059 @@ +"; + $body .= LJ::run_hook("bot_director", $pre, $post); + + if ($LJ::SERVER_DOWN) { + $title = $ML{'Sorry'}; + $body = LJ::server_down_html(); + return; + } + + my $MAX_FRIENDS_SHOW = 500; + my $MAX_FRIENDOF_SHOW = 150; + + my $remote = LJ::get_remote(); + if ($GET{'user'} eq "" && !$remote) { + $body = ""; + return; + } + + my $sth; + my %countries = (); + my %states = (); + LJ::load_codes({ "country" => \%countries, "state" => \%states }); + + my $error = sub { + my $e = shift; + $body = ""; + return; + }; + + my $user = LJ::canonical_username($GET{'user'}); + if ($GET{'user'} && ! $user) { + $body = $ML{'.error.malfname'}; + return; + } + if ($user eq "" && $remote) { + $user = $remote->{'user'}; + } + + my $dbr = LJ::get_db_reader(); + return $error->($ML{'error.nodb'}) unless $dbr; + + my $userid = $GET{'userid'}; + my $u; + $userid += 0; + + { + if ($userid) { + $u = LJ::load_userid($userid); + } else { + $u = LJ::load_user($user); + } + + return $error->($ML{'.label.reqfinduser'}) + if $userid && ! LJ::check_priv($remote, "finduser") && ! ($GET{t} eq "I" && $u && $u->{journaltype} eq "I"); + + # fix accidentally broken ext_nnnn URLs for identity users + if ($u->{journaltype} eq "I" && ! $userid) { + return BML::redirect("$LJ::SITEROOT/userinfo.bml?userid=$u->{'userid'}&t=I"); + } + + $user = $u->{'user'} if $u; + $userid = $u->{'userid'}+0 if $u; + + LJ::text_out(\$u->{'name'}) if $u; + if ($u && ($GET{'mode'} eq "full" || $u->{'journaltype'} eq "Y")) { + $sth = $dbr->prepare("SELECT timeupdate, timecreate, ". + "UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ". + "AS 'secondsold' FROM userusage ". + "WHERE userid=$userid"); + $sth->execute; + ($u->{'timeupdate'}, + $u->{'timecreate'}, + $u->{'secondsold'}) = $sth->fetchrow_array; + } + } + + unless ($u) { + $title = $ML{'Error'}; + $body = "$user}) . " p?>"; + return; + } + + # account purged? + if ($u->{'statusvis'} eq "X") { + $title = $ML{'error.purged.title'}; + $body = ""; + BML::set_status(410); # 410 Gone + return; + } + + my $dbcr = LJ::get_cluster_reader($u); + return $error->($ML{'error.nodb'}) unless $dbcr; + + # option + my %hide_fo; # userid -> 1 + if ($LJ::HIDE_FRIENDOF_VIA_BAN) { + if (my $list = LJ::load_rel_user($u, 'B')) { + $hide_fo{$_} = 1 foreach @$list; + } + } + + my $remote_isowner = $remote && $remote->{'user'} eq $u->{'user'}; + my $remote_isfriend = LJ::is_friend($u, $remote); + my $com = $u->{'journaltype'} eq "C" ? 1 : 0; + my $extid = $u->{'journaltype'} eq "I" ? $u->identity : undef; + + my $synd; + if ($u->{'journaltype'} eq "Y") { + $synd = $dbr->selectrow_hashref("SELECT * FROM syndicated WHERE userid=$u->{'userid'}"); + } + my $dir = "users"; + + ### load user props. some don't apply to communities + { + my @props = qw(opt_whatemailshow country state city zip renamedto + journaltitle journalsubtitle public_key + url urlname opt_hidefriendofs dont_load_members + opt_showmutualfriends fb_num_pubpics); + unless ($com || $synd) { push @props, qw(aolim icq yahoo msn gender jabber); } + if ($synd) { push @props, qw(rssparseerror); } + if ($u->{'statusvis'} eq 'V') { push @props, qw(opt_blockrobots); } + LJ::run_hooks('userinfo_local_props', { + 'props' => \@props + }); + LJ::load_user_props($u, @props); + } + + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head .= LJ::robot_meta_tags(); + } + + if ($u->{'journaltype'} eq "R" && $u->{'renamedto'}) { + my $extra = $GET{'mode'} eq 'full' ? "&mode=full" : ''; + return BML::redirect("$LJ::SITEROOT/userinfo.bml?user=$u->{'renamedto'}$extra"); + } + + my %friends = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); + my %friendsof = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); + + if ($com) { + $title = $ML{'.title.communityinfo'}; + $dir = "community"; + } elsif ($synd) { + $title = $ML{'.title.syndicated'}; + $u->{'opt_whatemailshow'} = "N"; # don't show email + $friends{'load'} = $friends{'display'} = 0; + } + + if ($extid) { + $windowtitle = "External identity profile"; + } else { + $windowtitle = "$u->{'user'} - $title"; + } + + $friends{'load'} = $friendsof{'load'} = 0 if $com && $u->{'dont_load_members'}; + + # do they have the viewall priv? + # there are no entries on this page, so we just check if they have any viewall, so viewsome + # applies here too. we can't see info they've hidden anyway, but we can see the page. + my $viewall = 0; + if ($GET{'viewall'} && LJ::check_priv($remote, "canview")) { + $viewall = LJ::check_priv($remote, 'canview', '*'); + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "userinfo: $u->{'user'}, statusvis: $u->{'statusvis'}"); + } else { + + if ($u->{'statusvis'} eq "S") { + $title = $ML{'error.suspended.title'}; + $body = " LJ::ljuser($user), + 'sitename' => $LJ::SITENAME }) . " p?>"; + BML::set_status(403); # 403 Forbidden + return; + } + if ($u->{'statusvis'} eq "D") { + $title = $ML{'error.deleted.title'}; + $body = "$user}) . " p?>"; + BML::set_status(404); # 404 Not Found + return; + } + } + + $user = $u->{'user'}; + $userid = $u->{'userid'}; + + $u->{'bio'} = LJ::get_bio($u); + LJ::text_out(\$u->{'bio'}); + + # arrayref of interests rows: [ intid, intname, intcount ] + my $intu = LJ::get_interests($u); + + my %remote_interest; + if ($remote && $remote->{'userid'} != $userid) { + if (my $rint = LJ::get_interests($remote, { justids => 1 })) { + $remote_interest{$_} = 1 foreach @$rint; + } + } + + if ($u->{'opt_hidefriendofs'} && ! $remote_isowner) { + # at this point, load should be on if viewall is on or if the user + # wants to show their mutual friends + $friendsof{'load'} = $u->{'opt_showmutualfriends'} || $viewall; + $friendsof{'display'} = $viewall; + } + + # Add metadata links to + my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{'email'}); + $head .= "\n"; + $head .= "\n"; + $head .= "\n"; + $head .= "\n"; + + my @friends; + my $fr_res; + my %fr; + # TAG:FR:userinfo:loadfriends + if ($friends{'load'}) { + $fr_res = LJ::get_friends($u); + my @ids = keys %$fr_res; + $friends{'count'} = @ids; + if (@ids > $MAX_FRIENDS_SHOW) { + @ids = splice(@ids, 0, $MAX_FRIENDS_SHOW); + } + LJ::load_userids_multiple([ map { $_ => \$fr{$_} } @ids ]); + push @friends, sort { $a->{user} cmp $b->{user} } values %fr; + $friends{'loaded'} = 1; + } + + my (@friend_of, @member_of, @mutual); + + # TAG:FR:userinfo:loadfriendofs + if ($friendsof{'load'}) { + # figure at most 50 people are not statusvis='V' *shrug* (this is lame pending the friend changes) + my @ids = grep { ! $hide_fo{$_} } LJ::get_friendofs($u); + $friendsof{'load_clipped'} = @ids > $LJ::MAX_FRIENDOF_LOAD; + + my %fro; + LJ::load_userids_multiple([ map { $_ => \$fro{$_} } @ids ]); + + foreach my $ulocal (sort { $a->{'user'} cmp $b->{'user'} } values %fro) { + next unless $ulocal->{'statusvis'} eq 'V'; + if ($ulocal->{'journaltype'} eq 'P' || $ulocal->{'journaltype'} eq "I") { + if (!$com && $u->{'opt_showmutualfriends'} && $fr{$ulocal->{userid}}) { + push @mutual, $ulocal; + } else { + push @friend_of, $ulocal; + } + } else { + push @member_of, $ulocal; # 'S' or 'C' (shared or community) + } + } + + $friendsof{'count'} = scalar @friend_of; + $friendsof{'count_m'} = scalar @member_of; + $friendsof{'count_b'} = scalar @mutual; + $friendsof{'loaded'} = 1; + } + + $u->{'name'} = LJ::ehtml($u->{'name'}); + + # TAG:FR:userinfo:remotefriends + # who does the remote user list as a friend? + my %remote_friendid; + if ($remote && $friends{'loaded'}) { + if ($remote->{'userid'} == $u->{'userid'}) { + foreach (@friends) { $remote_friendid{$_->{'userid'}} = 1; } + } else { + my $frs = LJ::get_friends($remote) || {}; + $remote_friendid{$_} = 1 while $_ = each %$frs; + } + } + + # BML helpers. we do BML by hand in this page, so we don't force BML + # to evaluate this huge page looking for non-existent BML. this + # makes it quicker, and prevents us from having to clean out BML in + # the HTML cleaner too. + my $h1 = sub { + return BML::fill_template("h1", { DATA => $_[0] }); + }; + my $p = sub { + return BML::fill_template("p", { DATA => $_[0] }); + }; + + if ($com) { + $body .= $h1->($ML{'.comminfo.name'}); + my $pt = BML::ml('.comminfo.body',{'commname'=>$u->{'name'}}) . " "; + my $userinfo_join_community; + LJ::run_hooks("userinfo_join_community", { + 'u' => $u, + 'ret' => \$userinfo_join_community, + }); + $pt .= $userinfo_join_community ? $userinfo_join_community : BML::ml('.membership.body',{'commname'=>$u->{'user'}}); + $pt .= BML::ml('.body.leave',{'commname'=>$u->{'user'}}); + $body .= $p->($pt); + } elsif ($synd) { + $body .= $h1->($ML{'.syndinfo.name'}) . $p->(BML::ml('.syndinfo.body', { + 'addtofriends' => "$LJ::SITEROOT/friends/add.bml?user=$u->{'user'}", + })); + } elsif ($extid) { + if ($extid->[0] eq "O") { + $body .= $h1->("OpenID user"); + $body .= $p->("This is a non-$LJ::SITENAME user that's using their external identity to log in to $LJ::SITENAME using OpenID in order to leave authenticated comments and read friends-only entries."); + } + + + } else { + $body .= $h1->($ML{'.userinfo.name'}) . $p->(BML::ml('.userinfo.body', { + 'username' => $u->{'name'}, 'siteroot'=>$LJ::SITEROOT, + })); + } + + ## standout bar + { + my @linkele; + + my $label = $com ? $ML{'.monitor.comm'} : $ML{'.monitor.user'}; + push @linkele, "$label"; + + if (LJ::can_use_journal($remote->{'userid'}, $user) && !$extid) { + if($remote_isowner) { + $label = $ML{'.label.postalt'}; + } else { + $label = BML::ml('.label.post', {'journal' => $user}); + } + + $label = LJ::ehtml("$label"); + + push @linkele, "$label"; + } + + $label = $ML{'.label.todo'}; + push @linkele, "$label" unless $extid; + + $label = $ML{'.label.memories'}; + push @linkele, "$label" unless $extid; + + unless ($LJ::DISABLED{'tellafriend'} || $extid) { + push @linkele, "$ML{"; + } + + unless ($LJ::DISABLED{'feedster_search'} || $extid) { + push @linkele, "$ML{"; + } + + if (@linkele) { + $body .= BML::fill_template("standout", { + DATA => join("  ", @linkele), + }); + } + } + + $body .= ""; + { + my $hook_extra; + LJ::run_hooks("userinfo_html_by_user", { + 'u' => $u, + 'ret' => \$hook_extra, + }); + if ($u->{journaltype} eq "I") { + $body .= ""; + } else { + $body .= "\n"; + } + } + +### picture + + my $narrow_left = 2; ## rows with smaller colspan to 2 + $body .= ""; +### /picture + + $body .= "\n"; + + ## journal title +if ($u->{'journaltitle'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "\n"; +} + + + ### name or 'syndicated from' + unless ($synd) { + unless ($u->underage || $u->{'name'} eq $u->{'journaltitle'}) { + $narrow_left--; + $body .= "\n"; + } + } else { + $narrow_left--; + my $link; + if (my $url = $u->{'url'}) { + $link="$u->{'name'}"; + } else { + $link=$u->{'name'}; + } + my $icon="". + ""; + $body .= "\n". + "\n"; + + # syndication status + $body .= "\n"; + + } + + ## text message + if ($u->{'txtmsg_status'} eq "on" && LJ::get_cap($u, "textmessaging")) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= ""; + } + + if ( ! $synd && $u->{'url'}) { + my $url = LJ::ehtml($u->{'url'}); + my $span = ($narrow_left-- >= 0) ? 1 : 2; + unless ($url =~ /^https?:\/\//) { + $url =~ s/^http\W*//; + $url = "http://$url"; + } + my $urlname = LJ::ehtml($u->{'urlname'} || $url); + $url = "$urlname"; + $body .= "\n" if ($u->{'url'}); + } + + + if ( ! $synd && ($u->{'allow_infoshow'} eq "Y" || $viewall)) { + if ($u->{'city'} || $u->{'state'} || $u->{'country'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= ""; + } + + if ($u->{'bdate'} && !$com && $u->{'bdate'} ne "0000-00-00" && !$u->underage) { + my $bdate = $u->{'bdate'}; + $bdate =~ s/^0000-//; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "\n"; + } + } + + if ( ! $synd && ! $u->underage && ($u->{'allow_contactshow'} eq "Y" || + ($u->{'allow_contactshow'} eq "F" && $remote_isfriend) || $viewall)) + { + my $mangleaddress = sub { + my $email = shift; + my $mret = "
    OpenID:" . LJ::ljuser($u) . "
    $ML{'.label.user'}$user ($u->{'userid'}) $hook_extra "; + if ($u->{public_key}) { + $body .= ""; + $body .= "View public key"; + } + $body .= ""; + if ($u->{'defaultpicid'}) { + my $picid = $u->{'defaultpicid'}; + my %pic; + LJ::load_userpics(\%pic, [ $u, $picid ]); + $body .= "$user"; + } else { + $body .= " "; + } + $body .= "
    "; + $body .= "" . LJ::ehtml($u->{'journaltitle'}) . ""; + if ($u->{'journalsubtitle'}) { + $body .= "
    " . LJ::ehtml($u->{'journalsubtitle'}) . ""; + } + $body .= "
    $ML{'.label.name'}$u->{'name'}
    $ML{'.label.syndicatedfrom'}$link $icon
    $ML{'.label.syndicatedstatus'}\n"; + $body .= "$ML{'.syn.lastcheck'} "; + $body .= $synd->{'lastcheck'} || $ML{'.syn.last.never'}; + my $status = { + 'parseerror' => "Parse error", + 'notmodified' => "Not Modified", + 'toobig' => "Too big", + 'posterror' => "Posting error", + 'ok' => "", # no status line necessary + 'nonew' => "", # no status line necessary + }->{$synd->{'laststatus'}}; + $body .= " ($status)" if $status; + + if ($synd->{'laststatus'} eq "parseerror") { + $body .= "
    $ML{'.syn.parseerror'} " . LJ::ehtml($u->{'rssparseerror'}); + } + + $body .= "
    $ML{'.syn.nextcheck'} $synd->{'checknext'}"; + $body .= "
    $ML{'.label.textmessage'}" . BML::ml('.sendmessage.body',{'user'=>$u->{'user'}, 'link'=>"/tools/textmessage.bml?user=$u->{'user'}"}) . "
    $ML{'.label.website'}$url
    $ML{'.label.location'}"; + my $estate = LJ::eurl($u->{'state'}); + my $ecity = LJ::eurl($u->{'city'}); + my $ecountry = LJ::eurl($u->{'country'}); + + my ($state, $city, $country); + + if ($u->{'country'}) { + $country = $LJ::DISABLED{'directory'} ? $countries{$u->{'country'}} : + "". + $countries{$u->{'country'}} . ""; + + my $estate; + if ($u->{'state'}) { + $state = $u->{'state'}; + if ($u->{'country'} eq "US") { $state = $states{$state}; } + $estate = LJ::eurl($state); + $state = $LJ::DISABLED{'directory'} ? $state : + "$state"; + } + + if ($u->{'city'}) { + my $ecity = LJ::eurl($u->{'city'}); + $city = LJ::ehtml($u->{'city'}); + unless ($LJ::DISABLED{'directory'}) { + $city = "$city"; + } + } + } + + $body .= join(", ", grep { $_ } ($city, $state, $country)); + $body .= "
    $ML{'.label.birthdate'}$bdate
    "; + for (my $i = 0; $i < length($email); $i++) { + my $letter = substr($email, $i, 1); + if ($letter eq "\@") { $letter = "\@"; } + $mret .= $letter; + } + $mret .= "
    "; + return $mret; + }; + + # some classes of users we want to have their contact info hidden + # after so much time of activity, to prevent people from bugging + # them for their account or trying to brute force it. + my $hide_contactinfo = sub { + my $hide_after = LJ::get_cap($u, "hide_email_after"); + return 0 unless $hide_after; + my $memkey = [$u->{userid}, "timeactive:$u->{userid}"]; + my $active; + unless (defined($active = LJ::MemCache::get($memkey))) { + $active = $dbcr->selectrow_array("SELECT timeactive FROM clustertrack2 ". + "WHERE userid=?", undef, $u->{userid}); + LJ::MemCache::set($memkey, $active, 86400); + } + return $active && (time() - $active) > $hide_after * 86400; + }; + + my $useremail_cap = LJ::get_cap($u, 'useremail'); + unless ($u->{'opt_whatemailshow'} eq "N" || + $u->{'journaltype'} eq "I" || + $u->{'opt_whatemailshow'} eq "L" && ($u->{'no_mail_alias'} || ! $useremail_cap || ! $LJ::USER_EMAIL) || + $hide_contactinfo->()) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.email'}"; + my @emails = ($u->{'email'}); + if ($u->{'opt_whatemailshow'} eq "L") { + @emails = (); + } + if ($LJ::USER_EMAIL && $useremail_cap) { + + unless ($u->{'opt_whatemailshow'} eq "A" || $u->{'no_mail_alias'}) { + push @emails, "$u->{'user'}\@$LJ::USER_DOMAIN"; + } + } + foreach my $email (@emails) { + $body .= ($u->{'opt_mangleemail'} eq "Y" || $email =~ /\@livejournal\.com$/) + ? $mangleaddress->($email) + : "$email
    "; + } + $body .= ""; + } + + foreach my $k (qw(aolim icq yahoo msn jabber)) { + $u->{$k} = LJ::ehtml($u->{$k}); + } + + if ($u->{'aolim'}) { + my $qim = $u->{'aolim'}; + $qim =~ s/ //g; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.aolim'}AIM status $u->{'aolim'} ($ML{'.label.addbuddy'}, $ML{'.label.sendmessage'})\n"; + } + if ($u->{'icq'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.icquin'}"; + $body .= "ICQ status "; + $body .= "$u->{'icq'} ("; + $body .= "$ML{'.label.userprofile'})"; + $body .= "\n"; + } + if ($u->{'yahoo'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$ML{'.label.yahooid'}Yahoo status $u->{'yahoo'} ($ML{'.label.adduser'}, $ML{'.label.sendmessage'}) \n"; + } + if ($u->{'msn'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + my $msnname = ($u->{'opt_mangleemail'} eq "Y") ? $mangleaddress->($u->{'msn'}) : $u->{'msn'}; + $body .= "$ML{'.label.msnusername'}$msnname\n"; + } + if ($u->{'jabber'}) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + my $jabber = $mangleaddress->($u->{'jabber'}); + $body .= "$ML{'.label.jabber'}$jabber\n"; + } + } + + + if ($u->{'has_bio'} eq "Y") { + my $span = ($narrow_left-- > 0) ? 1 : 2; + my $label = $com ? $ML{'.about.comm'} : $ML{'.about.user'}; + + LJ::CleanHTML::clean_userbio(\$u->{'bio'}); + + $body .= "$label$u->{'bio'}\n"; + } + + ### memories + { + my $memcount = LJ::Memories::count($userid); + if ($memcount) { + my $span = ($narrow_left-- > 0) ? 1 : 2; + my $noun_name = $memcount == 1 ? '.memories.entry' : '.memories.entries'; + my $count = BML::ml($noun_name, {'count'=>$memcount}); + $body .= "$ML{'.label.memories'}$count\n"; + } + } + + ### Fotobilder gallery count + { + if (LJ::get_cap($u, 'fb_account') && LJ::get_cap($u, 'fb_can_upload') && $u->{'fb_num_pubpics'}+0 > 0) { + my $span = ($narrow_left-- >= 0) ? 1 : 2; + + # what we display is an estimate. to eliminate confusion on the user end, we'll display the + # estimate in a way that makes it clear it's not an exact number. rules are: + # + # * < 10 == "under 10" + # * 10..999 == "at least 150" (rounded down to nearest 10) + # * 1000+ == "at least 1500" (rounded down to nearest 100) + # + my $ct = $u->{fb_num_pubpics}; + my $ct_str; + if ($ct < 10) { + $ct_str = BML::ml('.fbpictures.lessthan', { count => 10 }); + } else { + my $order = $ct < 100 ? 10 : 100; + my $base = POSIX::floor($ct / $order); + $ct_str = BML::ml('.fbpictures.over', { count => $base * $order }); + } + + $body .= "$ML{'.label.fbpictures'}$ct_str\n"; + } + } + + if (@$intu) { + my $span = ($narrow_left-- > 0) ? 1 : 2; + $body .= "$ML{'.label.interests'}:"; + my $intcount = 0; + my $intlist = ""; + foreach my $int (@$intu) { + next if $intcount++ > 150; + LJ::text_out(\$int->[1]); # 1==interest + my $eint = LJ::eurl($int->[1]); + if ($int->[2] > 1) { # 2==intcount + if ($remote_interest{$int->[0]}) { # 0==intid + $intlist .= "$int->[1], "; + } else { + $intlist .= "$int->[1], "; + } + } else { + $intlist .= "$int->[1], "; + } + } + chop $intlist; chop $intlist; # remove trailing ", " + if ($intcount > 150) { + my $notshown = $intcount - 150; + $intlist .= BML::ml('.label.intsnotshown',{'intnotshown'=>$notshown}); + } + + $body .= "$intcount: " . $intlist; + if ($remote) { + my $link = "/interests.bml?mode=enmasse"; + $link .= "&fromuser=$user" unless ($remote->{'userid'} == $userid); + $body .= ". "; + my $mlcode = ($remote->{'userid'} == $userid) ? '.label.interests.removesome' + : '.label.interests.modifyyours'; + $body .= BML::ml('Actionlink', { 'link' => "$ML{$mlcode}" }); + $body .= ""; + } + $body .= ""; + } + + ## + ## friends + ## + unless ($synd || $LJ::FORCE_EMPTY_FRIENDS{$userid}) { + my $label = $com ? $ML{'.friends.comm'} : $ML{'.friends.user'}; + my $span = ($narrow_left-- >= 0) ? 1 : 2; + $body .= "$label:"; + + $friends{'display'} = 0 if $friends{'count'} > $MAX_FRIENDS_SHOW; + if ($friends{'count'}) { + if (!$friends{'loaded'} || !$friends{'display'}) { + $body .= "" . $friends{'count'} . ": "; + $body .= " " . ($com ? $ML{'.label.viewmembers'} : $ML{'.label.viewfriends'}) . " ."; + } elsif ($u->{'journaltype'} eq 'P' or $u->{'journaltype'} eq 'S') { + # personal/shared journals have a special way of showing their friends list, it breaks it down into + # three sublists: personal/shared, community/news, syndication + my (@pfriends, @cfriends, @yfriends); + my $friend_link = sub { + my $f = shift; + my $status = $f->{'statusvis'}; + my $frlink = "$f->{'user'}"; + $frlink = "$frlink" if $status =~ /[DXS]/; + $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; + return $frlink; + }; + foreach my $f (@friends) { + push @pfriends, $friend_link->($f) if $f->{'journaltype'} eq 'P' or $f->{'journaltype'} eq 'S'; + push @cfriends, $friend_link->($f) if $f->{'journaltype'} eq 'C' or $f->{'journaltype'} eq 'N'; + push @yfriends, $friend_link->($f) if $f->{'journaltype'} eq 'Y'; + } + my ($pcount, $ccount, $ycount) = (scalar @pfriends, scalar @cfriends, scalar @yfriends); + my $pfriends = join ', ', @pfriends; + my $yfriends = join ', ', @yfriends; + my $cfriends = join ', ', @cfriends; + + # now spit out the HTML + $body .= ""; + if ($pfriends) { + my $text = LJ::ehtml($ML{'.label.frpeople'}); + $body .= "" . + "". + ""; + } + if ($cfriends) { + my $text = LJ::ehtml($ML{'.label.frcommunity'}); + $body .= "" . + "" . + ""; + } + if ($yfriends) { + my $text = LJ::ehtml($ML{'.label.frsyndication2'}); + $body .= "" . + "" . + ""; + } + $body .= "
    " . + "$text$pcount:$pfriends
    " . + "$text$ccount:$cfriends
    " . + "$text$ycount:$yfriends
    "; + } else { + $body .= "" . $friends{'count'} . ": "; + foreach my $f (@friends) { + my $status = $f->{'statusvis'}; + my $frlink = "$f->{'user'}"; + $frlink = "$frlink" if $status =~ /[DXS]/; + $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; + $body .= $frlink; + $body .= ", "; + } + chop $body; chop $body; + } + } else { + $body .= $ML{'.label.nofriends'}; + } + $body .= "\n"; + } + + # friend of and mutual friends display + # there are two options that will affect what gets shown below: opt_hidefriendofs, opt_showmutualfriends + # if the option to show mutual friends is on, then what was known as the friend of list is broken down + # into two lists: mutual friends (people you list and who also list you back) and 'also friend of', which + # lists the people you don't also list as friends. you can hide your friend of list, and leave just + # your mutual friends list showing, or you can not split them and have both be hidden. + unless ($synd) { + if ($friendsof{'loaded'}) { + my $label; + if ($u->{'opt_showmutualfriends'} && @mutual) { + $label = $ML{'.label.mutual'}; + $body .= "$label"; + $body .= ""; + + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count_b'} . "$plus: "; + my $count = 0; + my $bold_mutual = ! LJ::u_equals($remote, $u); + foreach (@mutual) { + my $frlink = "{'user'}\">$_->{'user'}"; + $frlink = "$frlink" if $bold_mutual && $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { + $friendsof{'clipped'} = 1; + last; + } + } + chop $body; chop $body; + $body .= ", ..." + if $friendsof{'clipped'} || $friendsof{'load_clipped'}; + $friendsof{'clipped'} = 0; # reset for @friend_of display + $body .= "\n"; + } + if ($friendsof{'display'} && @friend_of) { + $label = $com ? $ML{'.friendof.comm'} : + ($u->{'opt_showmutualfriends'} ? $ML{'.label.alsofriendof'} : $ML{'.friendof.user'}); + $body .= "$label"; + if ($u->{'opt_hidefriendofs'}) { + $body .= "
    $ML{'.friendof.hidden'}"; + } + $body .= ""; + + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count'} . "$plus: "; + my $count = 0; + foreach (@friend_of) { + my $frlink; + if ($_->{'journaltype'} eq "P") { + $frlink = "{'user'}\">$_->{'user'}"; + } elsif ($_->{'journaltype'} eq "I") { + $frlink = "{'userid'}&t=I\">" . LJ::ehtml($_->{'name'}) . ""; + } + $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { + $friendsof{'clipped'} = 1; + last; + } + } + chop $body; chop $body; + $body .= ", ..." + if $friendsof{'clipped'} || $friendsof{'load_clipped'}; + $body .= "\n"; + }; + if ($friendsof{'display'} && @member_of) { + $label = $ML{'.label.memberof'}; + $body .= "$label:"; + my $plus = $friendsof{'load_clipped'} ? "+" : ""; + $body .= "" . $friendsof{'count_m'} . "$plus: "; + foreach (@member_of) { + my $frlink = "$_->{'user'}"; + $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; + $body .= "$frlink, "; + } + chop $body; chop $body; + $body .= "\n"; + }; + } + } else { # Syndication journals are special + $body .= "$ML{'.friendof.syndreadcount'}:"; + $body .= "$friendsof{'count'}\n"; + } + + ## extra rows generated by hooks + foreach my $row (LJ::run_hooks("userinfo_rows", { + 'dbr' => $dbr, + 'u' => $u, + 'remote' => $remote, + })) { + next unless $row->[0]; + $body .= ""; + $body .= $row->[0]; + $body .=":"; + $body .= $row->[1]; + $body .= "\n"; + } + + unless ($synd || $GET{'mode'} eq "full") { # Synd accts are always full, but their full ends early (see below) + $body .= "\n"; + $body .= "

    $ML{'.label.moredetails'}

    "; + $bml_okay = 0; + return; + } + + + ## + ## interesting times + ## + $body .= "$ML{'.label.datecreated'}$u->{'timecreate'}"; + $body .= "$ML{'.label.dateupdated'}"; + if ($u->{'timeupdate'}) { + $body .= "$u->{'timeupdate'}, "; + my $secondsold = $u->{'secondsold'}; + my $num; + if ($secondsold > 60*60*24*7) { + $num = int($secondsold / (60*60*24*7)); + $body .= $num == 1 ? $ML{'.timeupdate.weekago'} + : BML::ml('.timeupdate.weeksago',{'num'=>$num}); + } elsif ($secondsold > 60*60*24) { + $num = int($secondsold / (60*60*24)); + $body .= $num == 1 ? $ML{'.timeupdate.dayago'} + : BML::ml('.timeupdate.daysago',{'num'=>$num}); + } elsif ($secondsold > 60*60) { + $num = int($secondsold / (60*60)); + $body .= $num == 1 ? $ML{'.timeupdate.hourago'} + : BML::ml('.timeupdate.hoursago',{'num'=>$num}); + } elsif ($secondsold > 60) { + $num = int($secondsold / (60)); + $body .= $num == 1 ? $ML{'.timeupdate.minuteago'} + : BML::ml('.timeupdate.minutesago',{'num'=>$num}); + } else { + $num = $secondsold; + $body .= $num == 1 ? $ML{'.timeupdate.secondago'} + : BML::ml('.timeupdate.secondsago',{'num'=>$num}); + } + $body .= ""; + } else { + $body .= $ML{'.date.never'}; + } + $body .= ""; + + if ($synd) { # The rest of the rows are not useful to synd accts + $body .= "\n"; + $bml_okay = 0; + return ""; + } + + unless ($LJ::DISABLED{'userinfo_clientusage'}) { + $body .= "" . BML::ml('.label.clientsused',{'siteroot'=>$LJ::SITEROOT}) . ""; + $sth = $dbr->prepare("SELECT DISTINCT c.client FROM clients c, clientusage cu ". + "WHERE cu.userid=$userid AND cu.clientid=c.clientid ORDER BY c.client"); + $sth->execute; + my $lastclient = ""; + while ($_ = $sth->fetchrow_hashref) { + next unless ($_->{'client'} =~ m!(.+)/(.+)!); + my ($client, $ver) = ($1, $2); + if ($lastclient ne $client) + { + if ($lastclient) { chop $body; chop $body; $body .= "
    "; } + else { 1; } + $body .= "" . LJ::ehtml($client) .": "; + $lastclient = $client; + } + $body .= LJ::ehtml($ver) . ", "; + } + if ($lastclient) { chop $body; chop $body; } + $body .= ""; + } + + # count journal entries + { + my $memkey = [$userid, "log2ct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 3600*24*2; # 2 days + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=?", + undef, $userid); + LJ::MemCache::set($memkey, $count, $expire); + } + + $body .= "$ML{'.label.journalentrs'}" . + "" . &comma($count) . ""; + } + + my $points = $dbr->selectrow_array("SELECT SUM(points) AS 'points' FROM supportpoints WHERE userid=$userid"); + if ($points) { + $body .= "$ML{'.label.supportpoints'}:" . &comma($points) . ""; + } + + sub comma { + my $num = shift; + if ($num =~ s/(\d)(\d\d\d)$/$1,$2/) { + $num =~ s/(\d)(\d\d\d),/$1,$2/g; + } + return $num; + } + +## +## journal comments + { + my ($com_post, $com_got); + unless ($LJ::DISABLED{'show-talkleft'}) { + my $memkey = [$userid, "talkleftct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 3600*24*2; # 2 days + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talkleft " . + "WHERE userid=?", undef, $userid); + LJ::MemCache::set($memkey, $count, $expire) if defined $count; + } + $com_post = comma($count); + $com_post = BML::ml('.label.composted', {'num'=>$com_post}); + } + + my $memkey = [$userid, "talk2ct:$userid"]; + my $count = LJ::MemCache::get($memkey); + unless ($count) { + my $expire = time() + 3600*24*2; # 2 days; + $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talk2 ". + "WHERE journalid=?", undef, $userid); + LJ::MemCache::set($memkey, $count, $expire) if defined $count; + } + + $com_got = comma($count); + $com_got = BML::ml('.label.comreceived', {'num'=>$com_got}); + $body .= "$ML{'.label.comments'}$com_post" . + $com_got . ""; + } + +### +### shared journal access +### +{ + my $list; + if ($com || $u->{'journaltype'} eq 'S') { + # load user who can post to this community + $list = LJ::load_rel_user($u, 'P'); + } else { + # load communities/accounts this user can post to + $list = LJ::load_rel_target($u, 'P'); + } + my %u; + my @ids = @$list; + my $count = @ids; + my $chopped = 0; + my $CHOP_POINT = 500; + if (@ids > $CHOP_POINT) { + @ids = splice(@ids, 0, $CHOP_POINT); + $chopped = 1; + } + LJ::load_userids_multiple([ map { $_ => \$u{$_} } @ids ]); + my @accesslist = sort { $a->{user} cmp $b->{user} } grep { $_->{statusvis} eq 'V' } values %u; + + if (my $vcount = @accesslist) { + $count = $vcount if $count < $CHOP_POINT; + $body .= "$ML{'.label.shared'}$count: "; + $body .= join(", ", map { "$_->{user}" } @accesslist); + $body .= ", ..." if $chopped; + $body .= ""; + } +} + +$body .= "\n"; + +# removed until we run graphviz locally +# $body .= "

    Graph of friends

    "; + +$bml_okay = 0; +return; + +_code?> +title=> +body=> +head=> +page?> +lib: cgi-bin/ljlib.pl, cgi-bin/cleanhtml.pl +link: htdocs/editinfo.bml, htdocs/userinfo.bml, htdocs/users +link: htdocs/community/join.bml, htdocs/community/leave.bml, htdocs/friends/add.bml, htdocs/todo/index.bml +link: htdocs/tools/memories.bml, htdocs/tools/tellafriend.bml, htdocs/allpics.bml +link: htdocs/tools/textmessage.bml, htdocs/interests.bml, htdocs/support/faqbrowse.bml, htdocs/download/index.bml +link: htdocs/support/index.bml +img: img/btn_addfriend.gif, img/btn_todo.gif, img/btn_memories.gif, img/btn_tellfriend.gif, img/talk/md10_thumbup.gif, img/xml.gif +hook: userinfo_html_by_user, userinfo_rows + _c?> diff --git a/livejournal/htdocs/utf8convert.bml b/livejournal/htdocs/utf8convert.bml new file mode 100755 index 0000000..c9c8a0b --- /dev/null +++ b/livejournal/htdocs/utf8convert.bml @@ -0,0 +1,731 @@ +{ + 'des'=>'Personal Information: name, biography, friend groups\' names', + 'browse'=>\&browse_personals, + 'save'=>\&save_personals, + }, + + 'interests'=>{ + 'des'=>'Personal information: interests', + 'browse'=>\&browse_interests, + 'save'=>\&save_interests, + }, + + 'keywords'=>{ + 'des'=>'Picture keywords', + 'browse'=>\&browse_pickwd, + 'save'=>\&save_pickwd, + }, + + 'memories'=>{ + 'des'=>'Text of memory descriptions', + 'browse'=>\&browse_memories, + 'save'=>\&save_memories, + }, + + 'polls'=>{ + 'des'=>'Text of questions/answers for polls you created', + 'browse'=>\&browse_polls, + 'save'=>\&save_polls, + }, + + 'styles'=>{ + 'des'=>'Text of styles and overrides belonging to you', + 'browse'=>\&browse_styles, + 'save'=>\&save_styles, + }, + ); + + + unless ($LJ::UNICODE) { + $body .= ""; + return; + } + + my $remote = LJ::get_remote(); + unless ($remote) { + $body .= "login. p?>"; + return; + } + + my $authas = $GET{'authas'} || $remote->{'user'}; + my $u = LJ::get_authas_user($authas); + unless ($u) { + $body .= LJ::bad_input($ML{'error.invalidauth'}); + return; + } + + # extra arguments for get requests + my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + my $getextra_amp = $getextra ? "&authas=$authas" : ''; + + my $dbcm = LJ::get_cluster_master($u); + my $dbh = LJ::get_db_writer(); + my $sth; + + # avva, kinda improper usage of load_codes, but works i guess -brad + LJ::load_codes({ "encname" => \%LJ::CACHE_ENCNAMES } ) + unless %LJ::CACHE_ENCNAMES; + LJ::load_codes({ "encoding" => \%LJ::CACHE_ENCODINGS } ) + unless %LJ::CACHE_ENCODINGS; + + # check arguments. There are three: mode, area, encid + my $mode = $POST{'mode'} || $GET{'mode'}; + my $area = $POST{'area'} || $GET{'area'}; + my $encid = ($POST{'encid'} || $GET{'encid'}) + 0; + + # authas switcher form + $body .= "
    \n"; + $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n"; + $body .= "
    \n\n"; + + $mode = 'overview' unless defined $mode; + if ( ($mode =~ m/^save.*/) && !$encid) { + $body .= ""; + return; + } + + if ($mode eq 'overview') { + $body .= ""; + $body .= ""; + $body .= "Personal Info page. However, various types of miscellaneous information, such as picture keywords, your name, names of your friend groups, your interests, etc. must be explicitly converted. And this is the purpose of this page. p?>"; + $body .= "If your journal is written in English, you always use English for communication in LiveJournal and never use even accent symbols of other West European languages, you do not need to use this page. p?>"; + + $body .= ""; + if ($u->{'oldenc'}) { + $body .= "$LJ::CACHE_ENCNAMES{$u->{'oldenc'}} on your personal info page. You can choose to mass-convert all your miscellaneous information to UTF-8 under the assumption that it is all stored in this encoding. Do not choose this option if you might have used some other encoding in the past (anywhere besides your entries and comments) while using LiveJournal. If you are not sure, use the Conversion by Area option below. p?>"; + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= " p?>"; + } + + $body .= ""; + $body .= ""; + + unless ($encid) { + $encid = ($u->{'oldenc'} ? $u->{'oldenc'} : '1'); + }; + + foreach (@areanames) { + $body .= "$areas{$_}->{'des'} p?>"; + } + + } + + if ($mode eq 'browse') { + # need to display the data in given encoding, if it is not UTF-8 + $body .= "$areas{$area}->{'des'}: p?>"; + my $browse = $areas{$area}->{'browse'}; + my ($valid, $disp) = $browse->($u, $encid); + if ($valid && !defined($GET{'forceview'})) { + $body .= ""; + $body .= "return to the area list or force the information to be shown anyway. p?>"; + } else { + $body .= ""; + $body .= "$LJ::CACHE_ENCNAMES{$encid}. If it appears correct, press Save to convert and store it in the database. If some or all characters are displayed corrupted, you probably should choose another encoding from the list below and press Browse to see it displayed in that encoding. p?>"; + $body .= ""; + $body .= $disp; + $body .= ""; + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= " p?>"; + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= LJ::html_select({'name'=>'encid', 'selected'=>$encid}, %LJ::CACHE_ENCNAMES); + $body .= ""; + $body .= " p?>"; + + $body .= "go back to the area list. p?>"; + }; + } + + if ($mode eq 'save') { + $body .= "

    $areas{$area}->{'des'}

    $LJ::CACHE_ENCNAMES{$encid}. p?>"; + $body .= "$LJ::CACHE_ENCNAMES{$encid} (the technical name of which is $LJ::CACHE_ENCODINGS{$encid}). If you chose a wrong encoding, the text will display incorrectly after the conversion. p?>"; + $body .= ""; + + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= ""; + $body .= "
    \n"; + $body .= ""; + $body .= "
    p?>"; + } + + if ($mode eq 'saveall') { + $body .= "$LJ::CACHE_ENCNAMES{$encid}. p?>"; + $body .= "$LJ::CACHE_ENCNAMES{$encid} (the technical name of which is $LJ::CACHE_ENCODINGS{$encid}). If you chose a wrong encoding, the text will display incorrectly after the conversion. p?>"; + $body .= ""; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= "\n"; + $body .= ""; + $body .= ""; + $body .= "
    \n"; + $body .= ""; + $body .= "
    p?>"; + } + + if ($mode eq 'save_do') { + $body .= "$areas{$area}->{'des'}... p?>"; + my $save = $areas{$area}->{'save'}; + my ($success, $message) = $save->($u, $encid); + if ($success) { + $body .= ""; + $body .= $message; + } else { + $body .= ""; + } + } + + if ($mode eq 'saveall_do') { + $body .= ""; + foreach (@areanames) { + $body .= "$areas{$_}->{'des'}... p?>"; + my $save = $areas{$_}->{'save'}; + my ($success, $message) = $save->($u, $encid); + if ($success) { + $body .= ""; + $body .= $message; + } else { + $body .= ""; + } + } + } + + return; + + sub browse_personals { + my ($u, $encid) = @_; + + my $ret = ""; + my ($name, $bio, $groups); + + LJ::load_user_props($u, qw(url urlname)); + $name = $u->{'name'}; + if ($u->{'has_bio'} eq "Y") { + $bio = $dbcm->selectrow_array("SELECT bio FROM userbio WHERE userid=$u->{'userid'}"); + }; + $groups = ""; + $sth = $dbh->prepare("SELECT groupname FROM friendgroup WHERE userid=$u->{'userid'}"); + $sth->execute; + while (($_) = $sth->fetchrow_array) { + $groups .= $_ . ' '; + }; + + my $valid = LJ::is_utf8($name . ' ' . $u->{'url'} . ' ' . $u->{'urlname'} . ' ' . $bio . ' ' . $groups); + + convert(\$name, $encid); + convert(\$u->{'url'}, $encid); + convert(\$u->{'urlname'}, $encid); + convert(\$bio, $encid) if $bio; + convert(\$groups, $encid); + + $ret = "Name: $name
    "; + $ret .= "Website URL: $u->{'url'}
    "; + $ret .= "URL name: $u->{'urlname'}
    "; + $ret .= "Bio: $bio
    " if $bio; + $ret .= "Names of friend groups: $groups
    "; + return $valid, $ret; + } + + sub browse_interests { + my ($u, $encid) = @_; + my $ret = ""; + my $interests = ""; + my $sth = $dbh->prepare("SELECT i.interest FROM interests i, userinterests ui WHERE i.intid=ui.intid AND ui.userid=$u->{'userid'}"); + $sth->execute; + while($_ = $sth->fetchrow_array) { + $interests .= $_ . ' '; + } + + my $valid = LJ::is_utf8($interests); + + convert(\$interests, $encid); + + $ret = "Interests: $interests
    "; + return $valid, $ret; + } + + sub browse_pickwd { + my ($u, $encid) = @_; + my $ret = ""; + my $kwds = ""; + my $sth = $dbh->prepare("SELECT k.keyword FROM keywords k, userpicmap up WHERE k.kwid=up.kwid AND up.userid=$u->{'userid'}"); + $sth->execute; + while($_ = $sth->fetchrow_array) { + $kwds .= $_ . ' '; + } + + my $valid = LJ::is_utf8($kwds); + + convert(\$kwds, $encid); + + $ret = "Picture keywords: $kwds
    "; + return $valid, $ret; + } + + sub browse_polls { + my ($u, $encid) = @_; + my $sth; + my $ret = ""; + my $valid = 1; + + # first get some of the pollids of this user + my @pollids; + $sth = $dbh->prepare("SELECT pollid FROM poll WHERE posterid=$u->{'userid'} ". + "LIMIT 50"); + $sth->execute; + while (my ($pid) = $sth->fetchrow_array) { + push @pollids, $pid; + } + unless (@pollids) { + $ret .= "You have no polls defined."; + return 1, $ret; + } + my $pids = join(',', @pollids); + + my @strings; my $limit = 5; my $nlimit = 10; + $sth = $dbh->prepare("SELECT name FROM poll WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($name) = $sth->fetchrow_array) { + push @strings, $name if LJ::is_utf8($name) and --$limit >=0; + push @strings, $name if !LJ::is_utf8($name) and --$nlimit >=0; + $valid = 0 unless LJ::is_utf8($name); + } + $ret .= "Sample poll names: p?>"; } + $ret .= "p?>"; + + $limit = 5; $nlimit = 10; @strings = (); + $sth = $dbh->prepare("SELECT qtext FROM pollquestion WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($question) = $sth->fetchrow_array) { + push @strings, $question if LJ::is_utf8($question) and --$limit >=0; + push @strings, $question if !LJ::is_utf8($question) and --$nlimit >=0; + $valid = 0 unless LJ::is_utf8($question); + } + $ret .= "Sample poll questions: p?>"; } + $ret .= "p?>"; + + $limit = 5; $nlimit = 10; @strings = (); + $sth = $dbh->prepare("SELECT item FROM pollitem WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($item) = $sth->fetchrow_array) { + push @strings, $item if LJ::is_utf8($item) and --$limit >=0; + push @strings, $item if !LJ::is_utf8($item) and --$nlimit >=0; + $valid = 0 unless LJ::is_utf8($item); + } + $ret .= "Sample poll answer choices: p?>"; } + $ret .= "p?>"; + + $limit = 5; $nlimit = 10; @strings = (); + $sth = $dbh->prepare("SELECT value FROM pollresult WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($res) = $sth->fetchrow_array) { + push @strings, $res if LJ::is_utf8($res) and --$limit >=0; + push @strings, $res if !LJ::is_utf8($res) and --$nlimit >=0; + $valid = 0 unless LJ::is_utf8($res); + } + $ret .= "Sample poll answers: p?>"; } + $ret .= "p?>"; + + return $valid, $ret; + } + + sub browse_styles { + my ($u, $encid) = @_; + my $ret = ""; + my $anystyles = 0; + my $valid = 1; + + my $sth = $dbh->prepare("SELECT styleid, styledes, formatdata FROM style WHERE user=?"); + $sth->execute($u->{'user'}); + while (my ($styleid, $styledes, $fdata) = $sth->fetchrow_array) { + $anystyles = 1; + $valid = 0 unless LJ::is_utf8($styledes) && LJ::is_utf8($fdata); + my $utfdata = LJ::is_utf8($fdata); + convert(\$styledes, $encid); + convert(\$fdata, $encid); + + $ret .= "Style number: $styleid
    "; + $ret .= "Description: $styledes
    "; + if ($utfdata) { + $ret .= "Format data: valid UTF-8
    "; + } else { + $ret .= "Format data: contains non-Unicode characters (too large to display)
    "; + } + $ret .= "p?>"; + } + unless ($anystyles) { $ret .= ""; } + + my ($overrides) = $dbh->selectrow_array("SELECT override FROM overrides WHERE user=?", undef, $u->{'user'}); + if ($overrides) { + $valid = 0 unless LJ::is_utf8($overrides); + convert(\$overrides, $encid); + $ret .= ""; + $ret .= ""; + } else { $ret .= ""; } + + return $valid, $ret; + } + + sub browse_memories { + my ($u, $encid) = @_; + my $ret = ""; + my $valid = 1; + + $ret .= ""; + $ret .= "{des}; + $valid = 0 unless LJ::is_utf8($des); + convert(\$des, $encid); + $ret .= $des . "
    " if --$limit >= 0; + } + $ret .= " p?>"; + + return $valid, $ret; + } + + sub save_personals { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $sth; + + my ($name, $bio, $groups); + my $userid = $u->{'userid'}; + + # convert name + $name = $u->{'name'}; + unless (LJ::is_utf8($name)) { + convert(\$name, $encid); + LJ::update_user($userid, { name => $name }); + $message .= ""; + } + + # convert url/urlname + LJ::load_user_props($u, qw(url urlname)); + foreach my $prop (qw(url urlname)) { + unless(LJ::is_utf8($u->{$prop})) { + convert(\$u->{$prop}, $encid); + LJ::set_userprop($u->{'userid'}, $prop, $u->{$prop}); + $message .= ""; + } + } + + # convert bio + if ($u->{'has_bio'} eq "Y") { + $bio = $dbcm->selectrow_array("SELECT bio FROM userbio WHERE userid=$userid"); + unless (LJ::is_utf8($bio)) { + convert(\$bio, $encid); + $u->do("UPDATE userbio SET bio=? WHERE userid=$userid", undef, $bio); + if ($u->err) { + return 0, "Database error: " . $u->errstr; + } + LJ::MemCache::delete([$userid, "bio:$userid"]); + $message .= ""; + } + } + + # convert groups + $groups = {}; + $sth = $dbh->prepare("SELECT groupnum, groupname FROM friendgroup WHERE userid=$userid ORDER BY sortorder"); + $sth->execute; + if ($dbh->err) { + return 0, ("Database error: " . $dbh->errstr); + } + + while ($_ = $sth->fetchrow_hashref) { + $groups->{$_->{'groupnum'}} = $_->{'groupname'}; + } + + my $converted_groups = 0; + + foreach (keys %$groups) { + unless(LJ::is_utf8($groups->{$_})) { + my $name = $groups->{$_}; + convert(\$name, $encid); + $dbh->do("UPDATE friendgroup SET groupname=? WHERE userid=$userid AND groupnum=$_", undef, $name); + if ($dbh->err) { + return 0, "Database error: $dbh->errstr"; + } + $converted_groups = 1; + } + } + if ($converted_groups) { + $message .= ""; + } + + return $success, $message; + } + + sub save_interests { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $sth; + + $sth = $dbh->prepare("SELECT i.interest, i.intid FROM interests i, userinterests ui ". + "WHERE i.intid=ui.intid AND ui.userid=$u->{'userid'}"); + $sth->execute; + my %interests = (); + while ($_ = $sth->fetchrow_hashref) { + $interests{$_->{'interest'}} = $_->{'intid'}; + } + my @ints; + my $changed = 0; + foreach(keys %interests) { + unless (LJ::is_utf8($_)) { + convert(\$_, $encid); + $changed = 1; + } + push @ints, $_; + } + if ($changed) { + LJ::set_interests($u, \%interests, \@ints); + } + + $message = "Converted interests" if $changed; + + return 1, $message; + } + + sub save_pickwd { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $sth; + my $userid = $u->{'userid'}; + + my %kwds; + + my $sth = $dbh->prepare("SELECT k.keyword, k.kwid FROM keywords k, userpicmap up ". + "WHERE k.kwid=up.kwid AND up.userid=$userid"); + $sth->execute; + while($_ = $sth->fetchrow_hashref) { + $kwds{$_->{'keyword'}} = $_->{'kwid'}; + } + my $changed = 0; + foreach my $keyword (keys %kwds) { + next if LJ::is_utf8($keyword); + $changed = 1; + my $kw = $keyword; + convert(\$kw, $encid); + my $newid = LJ::get_keyword_id($kw); + $dbh->do("UPDATE userpicmap SET kwid=$newid WHERE userid=$userid AND kwid=$kwds{$keyword}"); + } + if ($changed) { + $message = ""; + } + return 1, $message; + } + + sub save_polls { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $sth; + my $changed = 0; + + # convert poll names + my @pollids; + $sth = $dbh->prepare("SELECT pollid, name FROM poll WHERE posterid=$u->{'userid'}"); + $sth->execute; + while (my ($pid,$name) = $sth->fetchrow_array) { + push @pollids, $pid; + next if LJ::is_utf8($name); + convert(\$name, $encid); + my $qname = $dbh->quote($name); + $dbh->do("UPDATE poll SET name=$qname WHERE pollid=$pid"); + $changed = 1; + } + if ($changed) { + $message .= ""; + } + + my $pids = join(',', @pollids); + + # convert poll questions + $changed = 0; + $sth = $dbh->prepare("SELECT pollid, pollqid, qtext FROM pollquestion WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($pid, $pqid, $text) = $sth->fetchrow_array) { + next if LJ::is_utf8($text); + convert(\$text, $encid); + my $qtext = $dbh->quote($text); + $dbh->do("UPDATE pollquestion SET qtext=$qtext WHERE pollid=$pid AND pollqid=$pqid"); + $changed = 1; + } + if ($changed) { + $message .= ""; + } + + # convert poll items + $changed = 0; + $sth = $dbh->prepare("SELECT pollid, pollqid, pollitid, item FROM pollitem WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($pid, $pqid, $pitid, $item) = $sth->fetchrow_array) { + next if LJ::is_utf8($item); + convert(\$item, $encid); + my $qitem = $dbh->quote($item); + $dbh->do("UPDATE pollitem SET item=$qitem WHERE pollid=$pid AND pollqid=$pqid AND pollitid=$pitid"); + $changed = 1; + } + if ($changed) { + $message .= ""; + } + + # convert poll results + $changed = 0; + $sth = $dbh->prepare("SELECT pollid, pollqid, userid, value FROM pollresult WHERE pollid IN ($pids)"); + $sth->execute; + while (my ($pid, $pqid, $userid, $res) = $sth->fetchrow_array) { + next if LJ::is_utf8($res); + convert(\$res, $encid); + my $qres = $dbh->quote($res); + $dbh->do("UPDATE pollresult SET value=$qres WHERE pollid=$pid AND pollqid=$pqid AND userid=$userid"); + $changed = 1; + } + if ($changed) { + $message .= ""; + } + + return 1, $message; + + } + + sub save_styles { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $sth; + my $changed = 0; + + my $quser = $dbh->quote($u->{'user'}); + + my $sth = $dbh->prepare("SELECT styleid, styledes, formatdata FROM style WHERE user=$quser"); + $sth->execute; + while (my ($styleid, $styledes, $fdata) = $sth->fetchrow_array) { + next if LJ::is_utf8($styledes) && LJ::is_utf8($fdata); + convert(\$styledes, $encid); + convert(\$fdata, $encid); + my $newdes = $dbh->quote($styledes); + my $newdata = $dbh->quote($fdata); + $dbh->do("UPDATE style SET styledes=$newdes, formatdata=$newdata WHERE styleid=$styleid"); + $changed =1; + } + if ($changed) { + $message .= ""; + } + + my ($overrides) = $dbh->selectrow_array("SELECT override FROM overrides WHERE user=$quser"); + if ($overrides && !LJ::is_utf8($overrides)) { + convert(\$overrides, $encid); + my $qoverrides = $dbh->quote($overrides); + $dbh->do("UPDATE overrides SET override=$qoverrides WHERE user=$quser"); + $message .= ""; + } + + return 1, $message; + } + + sub save_memories { + my ($u, $encid) = @_; + my $success = 1; + my $message = ""; + my $changed = 0; + my $userid = $u->{'userid'}; + + my $keywords = LJ::Memories::get_keywords($u); + my %kwds = ( map { $keywords->{$_} => $_ } keys %{$keywords || {}} ); + foreach my $keyword (keys %kwds) { + next if LJ::is_utf8($keyword); + $changed = 1; + my $kw = $keyword; + convert(\$kw, $encid); + my $newid = LJ::get_keyword_id($u, $kw); + + # not an API because this is the only place this happens, and it's very rare + if ($u->{dversion} > 5) { + $u->do("UPDATE memkeyword2 SET kwid = ? WHERE userid = ? kwid = ?", + undef, $newid, $u->{userid}, $kwds{$keyword}); + } else { + $dbh->do("UPDATE memkeyword SET kwid=$newid WHERE kwid=$kwds{$keyword}"); + } + } + if ($changed) { + $message .= ""; + } + + # now the memory descriptions + $changed = 0; + my $memories = LJ::Memories::get_by_user($u); + foreach my $memory (values %{$memories || {}}) { + my $des = $memory->{des}; + next if LJ::is_utf8($des); + $changed = 1; + convert(\$des, $encid); + LJ::Memories::update_memory($u, $memory->{memid}, { des => $des }); + } + if ($changed) { + $message .= ""; + } + + return 1, $message; + } + + sub convert { + my ($rtext, $encid) = @_; + if ($encid && !LJ::is_utf8($$rtext)) { + my $enc = $LJ::CACHE_ENCODINGS{$encid}; + unless (lc($enc) eq "utf-8") { + $$rtext = Unicode::MapUTF8::to_utf8({-string=>$$rtext, -charset=>$enc}); + } + LJ::text_out($rtext); + } + } + +} +_code?> +body=> +page?> diff --git a/livejournal/htdocs/view/index.bml b/livejournal/htdocs/view/index.bml new file mode 100755 index 0000000..8fd54b4 --- /dev/null +++ b/livejournal/htdocs/view/index.bml @@ -0,0 +1,235 @@ +request; +if ($uri =~ m!/(\d\d\d\d)/(\d\d)/?$!) { + $FORM{'user'} = $r->notes('_journal'); + $FORM{'type'} = "month"; + $FORM{'y'} = $1; + $FORM{'m'} = $2 + 0; +} +$r->notes("codepath" => "bml.view.index"); + + my $view = $FORM{'type'}; + my $user = $FORM{'user'}; + + if ($view ne "month") { + $title = "Error"; + $body .= "Unknown view."; + return; + } + unless ($user) { + $title = "Error"; + $body .= "No user given."; + return; + } + + my $u = LJ::load_user($user); + unless ($u) { + $title = "Error"; + $body .= "User doesn't exist."; + return; + } + + # check for purged + if ($u->{'statusvis'} eq "X") { + $body = ""; + return; + } + + if ($u->{'journaltype'} eq "R") { + LJ::load_user_props($u, "renamedto"); + if ($u->{'renamedto'}) { + return BML::redirect(sprintf(LJ::journal_base($u->{'renamedto'}) . "/%04d/%02d/", $FORM{'y'}, $FORM{'m'})); + } + } + + my $remote = LJ::get_remote(); + + # do they have the viewall priv? + my $viewall = 0; + my $viewsome = 0; + if ($GET{'viewall'} && LJ::check_priv($remote, "canview")) { + LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, + "viewall", "month: $u->{'user'}, statusvis: $u->{'statusvis'}"); + $viewall = LJ::check_priv($remote, 'canview', '*'); + $viewsome = $viewall || LJ::check_priv($remote, 'canview', 'suspended'); + + # check for deleted/suspended + } else { + + # check suspended + if ($u->{'statusvis'} eq "S") { + $body = ""; + return; + } + + # check deleted + if ($u->{'statusvis'} eq "D") { + $body = ""; + return; + } + } + + LJ::load_user_props($u, "opt_blockrobots") if $u->{'statusvis'} eq 'V'; + if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { + $head .= LJ::robot_meta_tags(); + } + + my $base = LJ::journal_base($u); + + if (LJ::did_post()) { + my $newuri = sprintf("$base/%04d/%02d/", $POST{'y'}, $POST{'m'}); + return BML::redirect($newuri); + } + + my $secwhere = "AND l.security='public'"; + if ($remote) { + if ($remote->{'userid'} == $u->{'userid'} || $viewall) { + $secwhere = ""; # see everything + } elsif ($remote->{'journaltype'} eq 'P') { + my $gmask = LJ::get_groupmask($u, $remote); + $secwhere = "AND (l.security='public' OR (l.security='usemask' AND l.allowmask & $gmask))" + if $gmask; + } + } + + my $year = $FORM{'y'}+0; + my $month = $FORM{'m'}+0; + unless ($year =~ /^\d\d\d\d$/ && ($month >= 1 && $month <= 12)) { + my @now = localtime(); + $year = $now[5] + 1900; + $month = $now[4] + 1; + } + + my $monlang = LJ::Lang::month_long($month); + $title = $monlang; + $title .= ", $year - $u->{'user'}"; + + my $is_person = $u->{'journaltype'} eq "P"; + if ($is_person) { + $body .= "{'user'}) . " in $monlang, $year. p?>"; + } else { + $body .= "{'user'}) . " journal in $monlang, $year. p?>"; + } + + ### make standout box + { + my @next = ($year, $month+1); + if ($next[1] > 12) { @next = ($year+1, 1); } + my @prev = ($year, $month-1); + if ($prev[1] < 1) { @prev = ($year-1, 12); } + + my $next = ""; + my $prev = ""; + + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= ""; + $body .= "
    $prev $next
    "; + $body .= " standout?>\n"; + } + + $body .= "
    \n"; + + my $db = LJ::get_cluster_reader($u); + my $sth = $db->prepare("SELECT l.jitemid, l.anum, l.day, l.eventtime, l.posterid, ". + "l.replycount, l.security ". + "FROM log2 l ". + "WHERE l.journalid=$u->{'userid'} AND l.year=$year AND l.month=$month ". + "$secwhere LIMIT 2000"); + my $items = $db->selectall_arrayref($sth); + + # figure out what we need to load + my @itemids; + my %need_userid; # userid -> 1 + foreach my $it (@$items) { + push @itemids, $it->[0]; + $need_userid{$it->[4]} = 1; + } + my $lt = LJ::get_logtext2($u, @itemids); + my %u; + LJ::load_userids_multiple([map { $_ => \$u{$_} } keys %need_userid], []); + + # sort on event time + my $lday = 0; # last day shown + foreach my $it (sort { $a->[3] cmp $b->[3] } @$items) + { + my ($itemid, $anum, $day, $eventtime, $posterid, $replycount, $security) = @$it; + next if $u{$posterid}->{statusvis} eq 'S' && !$viewsome; + + my $subject = $lt->{$itemid}->[0]; + my $poster = $u{$posterid}->{user}; + + if ($day != $lday) { + if ($lday) { $body .= ""; } + $lday = $day; + my $ord = LJ::Lang::day_ord($day); + my $dayview_url = sprintf("$LJ::SITEROOT/users/$u->{'user'}/%04d/%02d/%02d/", + $year, $month, $day); + $body .= "
    $day$ord
    "; + $body .= "
    "; + } + + # we need to convert the subject to UTF-8 if it's a pre-Unicode entry + # loading all the props for all the posts and checking 'unknown8bit' + # is too long. The heuristic "if it's not UTF-8, convert it" works + # well here. + if ($LJ::UNICODE && !LJ::is_utf8($subject)) { + my $error; + my $subj = LJ::text_convert($subject, $u, \$error); + $subject = $subj unless $error; + LJ::text_out(\$subject); + } + + unless ($subject ne "") { $subject = "(no subject)"; } + my $h = substr($eventtime, 11, 2); + my $m = substr($eventtime, 14, 2); + my ($rep, $sec); + if ($security eq "private") { + $sec = " "; + } elsif ($security eq "usemask") { + $sec = " "; + } + if ($replycount) { + if ($replycount == 1) { $rep .= " - $replycount reply"; } + else { $rep .= " - $replycount replies"; } + } + $body .= ""; + if (! $is_person) { + $body .= ""; + } + + LJ::CleanHTML::clean_subject_all(\$subject); + + $body .= "\n"; + } + if ($lday) { $body .= "
    " . LJ::Lang::time_format(12, $h, $m, "short") . "" . LJ::ljuser($poster) . "$subject$sec$rep
    \n"; } + $body .= "
    "; + + return; + +_code?> +head=> +body=> +page?> +img: htdocs/img/btn_next.gif, htdocs/img/btn_prev.gif +form: htdocs/view/index.bml +link: htdocs/users, htdocs/talkread.bml + _c?> diff --git a/livejournal/logs/.placeholder b/livejournal/logs/.placeholder new file mode 100755 index 0000000..2895e7a --- /dev/null +++ b/livejournal/logs/.placeholder @@ -0,0 +1 @@ +This file exists to make sure the directory is created. diff --git a/livejournal/sites/README b/livejournal/sites/README new file mode 100755 index 0000000..abb2df3 --- /dev/null +++ b/livejournal/sites/README @@ -0,0 +1,3 @@ +This is where you'd make directories for other document roots.... for +example, mrtg.happyjournal.com, or whatever. + diff --git a/livejournal/src/historic/README b/livejournal/src/historic/README new file mode 100755 index 0000000..882f653 --- /dev/null +++ b/livejournal/src/historic/README @@ -0,0 +1,4 @@ +This was the first version of the LiveJournal server code, written sometime +in 1998, newly discovered in January of 2002. + +Amusing, eh? diff --git a/livejournal/src/historic/brad-log.cgi b/livejournal/src/historic/brad-log.cgi new file mode 100755 index 0000000..f013597 --- /dev/null +++ b/livejournal/src/historic/brad-log.cgi @@ -0,0 +1,64 @@ +#!/usr/bin/perl + +use DBI; +$dbh = DBI->connect("DBI:mysql:bradfitz", "bradfi2", ""); + +&get_form_data; + +print "Content-type: text/plain\n\n"; + +unless ($dbh) +{ + print "ERROR: cannot connect to database."; + exit; +} + +unless ($FORM{'event'}) +{ + print "ERROR: no event."; + exit; +} + +unless ($FORM{'password'} eq "mylog") +{ + print "ERROR: incorrect password"; + exit; +} + +$qevent = $dbh->quote($FORM{'event'}); + +$dbh->do("INSERT INTO bradlog (eventtime, type, event) VALUES (UNIX_TIMESTAMP(), 'event', $qevent)"); + +if ($dbh->err) +{ + print "ERROR: dbh->errstr = ", $dbh->errstr; + exit; +} + +print "Success."; + + +sub get_form_data +{ + my $buffer; + if ($ENV{'REQUEST_METHOD'} eq 'POST') { + read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); + } else { + $buffer = $ENV{'QUERY_STRING'}; + } + + # Split the name-value pairs + my $pair; + my @pairs = split(/&/, $buffer); + my ($name, $value); + foreach $pair (@pairs) + { + ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $name =~ tr/+/ /; + $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $FORM{$name} .= $FORM{$name} ? "\0$value" : $value; + } +} + diff --git a/livejournal/src/jbackup/jbackup.pl b/livejournal/src/jbackup/jbackup.pl new file mode 100755 index 0000000..c7eee65 --- /dev/null +++ b/livejournal/src/jbackup/jbackup.pl @@ -0,0 +1,1029 @@ +#!/usr/bin/perl + +# jbackup.pl +# Journal Backup Utility +# This tool downloads a copy of your journal (all entries and all comments) in a nice-to-the-server +# fashion and lets you export them in an easy to access XML format or an easy to read HTML format. + +### DATABASE DOCUMENTATION ######################################################################## +# There are a bunch of keys in the database. They're (hopefully) named in an easy to follow and +# understand manner, but I'm documenting them here for quick reference. +# +# event:lastsync +# The most recent item returned by the syncitems mode. This is just passed back to the +# server to instruct it when to pick up again and start sending us more data. +# +# event:ids +# Comma separated list of all valid jitemids. This is maintained so we don't have to +# iterate through every key in the database to find event jitemids. +# +# event:lastgrab +# The real date of the most recently downloaded event. This is set when we actually +# get an event from the getevents mode. This date will match up with one of the dates +# returned by syncitems. +# +# event:realtime: Time the server got this post (YYYY-MM-DD HH:MM:SS format). +# event:subject: Subject of the event, may not be present. +# event:anum: Arbitrary number for this event. +# event:event: Text of the event. +# event:eventtime: Time the user specified (YYYY-MM-DD HH:MM:SS format). +# event:security: Present if not public. Values are 'private', 'usemask'. +# event:allowmask: Present for security == usemask. Allowmask == 1 means Friends Only. +# event:poster: If present, may be any username. Else, it's the user's journal. +# These all contain various bits of data about the event. +# +# event:proplist: +# List of all properties that are defined for this event. Comma separated. +# +# event:prop:: +# Stores the values of the properties. is taken from the proplist. +# +# usermap: +# For , contains the username. +# +# usermap:userids +# All the valid userids. Same logic as event:ids. +# +# comment:ids +# Should be familiar. All the valid jtalkids. Comma separated. +# +# comment:lastid +# The most recently downloaded jtalkid as retrieved by the comment_body mode. +# +# comment:state: +# Formatted string: ::: +# This contains state information about a comment. Most of this information is subject to +# change, and hence it's separate. +# +# comment:subject: Subject of the comment. May not be present. +# comment:body: Text of the comment. May not be present for deleted comments. +# comment:date: Date of the comment. In W3C date format. +# As with events. Contains various bits of information about the comments. +################################################################################################### + +## the program ## +use strict; +use Getopt::Long; +use GDBM_File; +use Data::Dumper; +use XMLRPC::Lite; +use XML::Parser; +use Digest::MD5 qw(md5_hex); +use Term::ReadKey; + +# get options +my %opts; +exit 1 unless + GetOptions("dump=s" => \$opts{dumptype}, + "sync" => \$opts{sync}, + "user=s" => \$opts{user}, + "help" => \$opts{help}, + "server=s" => \$opts{server}, + "port=i" => \$opts{port}, + "quiet" => \$opts{quiet}, + "publiconly" => \$opts{public}, + "journal=s" => \$opts{usejournal}, + "clean" => \$opts{clean}, + "file=s" => \$opts{file}, + "password=s" => \$opts{password}, + "md5pass=s" => \$opts{md5password}, + "alter-security=s" => \$opts{alter_security}, + "confirm-alter" => \$opts{confirm_alter}, + "no-comments" => \$opts{no_comments},); + +# hit up .jbackup for other options +if (-e "$ENV{HOME}/.jbackup") { + # read in the options + open FILE, "<$ENV{HOME}/.jbackup"; + foreach () { + $opts{$1} = $2 + if /^(.+)=(.+)[\r\n]*$/; + } + close FILE; +} + +# setup some nice, sane defaults +$opts{server} ||= 'www.livejournal.com'; +$opts{port} += 0; +$opts{verbose} = $opts{quiet} ? 0 : 1; +$opts{server} = "$opts{server}:$opts{port}" + if $opts{port} && $opts{port} != 80; + +# now figure out what we're doing +if ($opts{help} || !($opts{sync} || $opts{dumptype} || $opts{alter_security})) { + print <; + chomp $user; + $opts{user} = $user; + die "Need a username" unless $opts{user}; +} +if (!$opts{password} && !$opts{md5password} && $opts{sync}) { + print "Password: "; + ReadMode('noecho'); + my $pass = ReadLine(0); + ReadMode('normal'); + chomp $pass; + $opts{password} = $pass; + print "\n"; + die "Need a password" unless $opts{password}; +} +$opts{linkuser} = $opts{usejournal} || $opts{user}; + +# setup some global variables +my %bak; +my $filename = "$ENV{HOME}/$opts{user}." . ($opts{usejournal} ? "$opts{usejournal}." : '') . "jbak"; + +# setup database +my $tied = do_tie(); + +# do something +do_alter_security($opts{alter_security}, $opts{confirm_alter}) if $opts{alter_security}; +do_sync() if $opts{sync}; +do_dump($opts{dumptype}) if $opts{dumptype}; + +# clean up before we exit +do_untie(); + +#### helper functions below here ############################################ + +sub d { + # just dump a message to stderr if we're in verbose mode + return unless $opts{verbose}; + print STDERR shift(@_) . "\n"; +} + +sub do_sync { +### ENTRY DOWNLOADING ### + # see if we have any sync data saved + my %sync; + my $lastsync = $bak{"event:lastsync"}; + my $synccount = 0; + + # get sync data + my @usejournal = $opts{usejournal} ? ('usejournal', $opts{usejournal}) : (); + while (1) { + # contact server for list of items + d("do_sync: calling syncitems with lastsync = " . ($lastsync || 'none yet')); + my $hash = call_xmlrpc('syncitems', { lastsync => $lastsync, @usejournal }); + + # push this info, set lastsync + foreach my $item (@{$hash->{syncitems} || []}) { + next unless $item->{item} =~ /L-(\d+)/; + $synccount++; + $sync{$1} = [ $item->{action}, $item->{'time'} ]; + $lastsync = $item->{'time'} + if $item->{'time'} gt $lastsync; + $bak{"event:realtime:$1"} = $item->{'time'}; + } + $bak{'event:lastsync'} = $lastsync; + do_flush(); + + # last if necessary + d("do_sync: got $hash->{count} of $hash->{total} syncitems."); + last if $hash->{count} == $hash->{total}; + } + print "$synccount total new and/or updated entries.\n"; + $bak{'event:lastsync'} = $lastsync; + + # helper sub + my $realtime = sub { + my $id = shift; + return $sync{$id}->[1] if @{$sync{$id} || []}; + return $bak{"event:realtime:$id"}; + }; + + # get list of ids so far + my %eventids = ( map { $_, 1 } split(',', $bak{"event:ids"}) ); + + # setup our download hash + my $lastgrab = $bak{"event:lastgrab"}; + my %data; + while (1) { + # shortcut to maybe not have to hit getvents + last if $lastgrab eq $lastsync; + + # get newest item we have cached + my $count = 0; + d("do_sync: calling getevents with lastgrab = " . ($lastgrab || 'none yet')); + my $hash = call_xmlrpc('getevents', { selecttype => 'syncitems', + lastsync => $lastgrab, + ver => 1, + lineendings => 'unix', + @usejournal, }); + + # parse incoming data one event at a time + foreach my $evt (@{$hash->{events} || []}) { + # got an event + $count++; + $eventids{$evt->{itemid}} = 1; + $evt->{realtime} = $realtime->($evt->{itemid}); + $lastgrab = $evt->{realtime} + if $evt->{realtime} gt $lastgrab; + save_event($evt); + } + $bak{"event:lastgrab"} = $lastgrab; + $bak{"event:ids"} = join ',', keys %eventids; + do_flush(); + + # do we all be done here? + d("do_sync: got $count items."); + last unless $count && $lastgrab; + } + +### COMMENT DOWNLOADING ### + # see if we shouldn't be doing this + return if $opts{no_comments}; + + # first we hit up the server to get a session + my $hash = call_xmlrpc('sessiongenerate', { expiration => 'short' }); + my $ljsession = $hash->{ljsession}; + + # downloaded meta data information + my %meta; + my @userids; + + # setup our parsing function + my $maxid = 0; + my $server_max_id = 0; + my $lasttag = ''; + my $meta_handler = sub { + # this sub actually processes incoming meta information + $lasttag = $_[1]; + shift; shift; # remove the Expat object and tag name + my %temp = ( @_ ); # take the rest into our humble hash + if ($lasttag eq 'comment') { + # get some data on a comment + $maxid = $temp{id} if $temp{id} > $maxid; + $meta{$temp{id}} = { + id => $temp{id}, + posterid => $temp{posterid}+0, + state => $temp{state} || 'A', + }; + update_comment($meta{$temp{id}}); + } elsif ($lasttag eq 'usermap') { + # put this data in our usermap + $bak{"usermap:$temp{id}"} = $temp{user}; + push @userids, $temp{id}; + } + }; + my $meta_closer = sub { + # we hit a closing tag so we're not in a tag anymore + $lasttag = ''; + }; + my $meta_content = sub { + # if we're in a maxid tag, we want to save that value so we know how much further + # we have to go in downloading meta info + return unless $lasttag eq 'maxid'; + $server_max_id = $_[1] + 0; + }; + + # hit up the server for metadata + while (1) { + my $content = do_authed_fetch('comment_meta', $maxid+1, $ljsession); + die "Some sort of error fetching metadata from server" unless $content; + + # now we want to XML parse this + my $parser = new XML::Parser(Handlers => { Start => $meta_handler, Char => $meta_content, End => $meta_closer }); + $parser->parse($content); + + # now at this point what we have to decide whether we should loop again for more metadata + last unless $maxid < $server_max_id; + } + $bak{"comment:ids"} = join ',', keys %meta; + $bak{"usermap:userids"} = join ',', @userids; + + # setup our handlers for body XML info + my $lastid = $bak{"comment:lastid"}+0; + my $curid = 0; + my @tags; + my $body_handler = sub { + # this sub actually processes incoming body information + $lasttag = $_[1]; + push @tags, $lasttag; + shift; shift; # remove the Expat object and tag name + my %temp = ( @_ ); # take the rest into our humble hash + if ($lasttag eq 'comment') { + # get some data on a comment + $curid = $temp{id}; + $meta{$curid}{parentid} = $temp{parentid}+0; + $meta{$curid}{jitemid} = $temp{jitemid}+0; + $lastid = $curid if $curid > $lastid; + } + }; + my $body_closer = sub { + # we hit a closing tag so we're not in a tag anymore + my $tag = pop @tags; + $lasttag = $tags[0]; + }; + my $body_content = sub { + # this grabs data inside of comments: body, subject, date + return unless $curid; + return unless $lasttag =~ /(?:body|subject|date)/; + $meta{$curid}{$lasttag} .= $_[1]; + # have to .= it, because the parser will split on punctuation such as an apostrophe + # that may or may not be in the data stream, and we won't know until we've already + # gotten some data + }; + + # at this point we have a fully regenerated metadata cache and we want to grab a block of comments + while (1) { + my $content = do_authed_fetch('comment_body', $lastid+1, $ljsession); + die "Some sort of error fetching body data from server" unless $content; + + # now we want to XML parse this + my $parser = new XML::Parser(Handlers => { Start => $body_handler, Char => $body_content, End => $body_closer }); + $parser->parse($content); + + # now at this point what we have to decide whether we should loop again for more metadata + last unless $lastid < $maxid; + } + + # at this point we should have a set of fully formed comments, so let's save everything + my $count = 0; + foreach my $id (keys %meta) { + next unless $meta{$id}{jitemid}; # jitemid == 0 means we didn't get body info on this comment + $count++; + save_comment($meta{$id}); + } + print "$count new comments downloaded.\n"; + + # update our lastid. we want this to always point to the last comment we downloaded, because + # comment ids will never go backwards, and we can always count on the next one being > lastid + $bak{"comment:lastid"} = $lastid if $count; +} + +# save an event that we get +sub save_event { + my $data = shift; + my $id = $data->{itemid}; # convenience + # DO NOT SET REALTIME HERE. It is set by syncitems. + foreach (qw(subject anum event eventtime security allowmask poster)) { + next unless $data->{$_}; + my $tmp = pack('C*', unpack('C*', $data->{$_})); + $bak{"event:$_:$id"} = $tmp; + } + my @props; + while (my ($p, $v) = each %{$data->{props} || {}}) { + $bak{"event:prop:$id:$p"} = $v; + push @props, $p; + } + $bak{"event:proplist:$id"} = join ',', @props; # so we don't have to sort through the whole database +} + +# load up an event given an id +sub load_event { + my $id = shift; + my %hash = ( props => {} ); + foreach (qw(subject anum event eventtime security allowmask poster realtime)) { + $hash{$_} = $bak{"event:$_:$id"}; + } + my $proplist = $bak{"event:proplist:$id"}; + my @props = split ',', $proplist; + foreach (@props) { + $hash{props}->{$_} = $bak{"event:prop:$id:$_"}; + } + $hash{itemid} = $id; + return \%hash; +} + +# updates a comment (state and posterid) +sub update_comment { + my $new = shift; + my $old = load_comment($new->{id}); + return unless $old && $old->{id}; + $old->{$_} = $new->{$_} foreach qw(state posterid); + save_comment($old); +} + +# takes in a comment hashref and saves it to the database +sub save_comment { + my $data = shift; + $bak{"comment:state:$data->{id}"} = "$data->{state}:$data->{posterid}:$data->{jitemid}:$data->{parentid}"; + foreach (qw(subject body date)) { + next unless $data->{$_}; + # GDBM doesn't deal with UTF-8, it only wants a string of bytes, so let's do that + # by clearing the UTF-8 flag on our input scalars. + my $tmp = pack('C*', unpack('C*', $data->{$_})); + $bak{"comment:$_:$data->{id}"} = $tmp; + } +} + +# load a comment up into a hash and return the hash +sub load_comment { + my $id = shift; + my $state = $bak{"comment:state:$id"}; + return {} unless $state; + my @data = ($1, $2, $3, $4) + if $state =~ /^(\w):(\d+):(\d+):(\d+)$/; + my %hash = ( + id => $id, + subject => $bak{"comment:subject:$id"}, + body => $bak{"comment:body:$id"}, + date => $bak{"comment:date:$id"}, + state => $data[0] || 'D', + posterid => $data[1]+0, + jitemid => $data[2]+0, + parentid => $data[3]+0, + ); + return \%hash; +} + +sub do_authed_fetch { + my ($mode, $maxid, $sess) = @_; + d("do_authed_fetch: mode = $mode, maxid = $maxid, sess = $sess"); + + # hit up the server with the specified information and return the raw content + my $ua = LWP::UserAgent->new; + $ua->agent('JBackup/1.0'); + my $authas = $opts{usejournal} ? "&authas=$opts{usejournal}" : ''; + my $request = HTTP::Request->new(GET => "http://$opts{server}/export_comments.bml?get=$mode&startid=$maxid$authas"); + $request->push_header(Cookie => "ljsession=$sess"); + my $response = $ua->request($request); + return if $response->is_error(); + my $xml = $response->content(); + return $xml if $xml; + + # blah + d("do_authed_fetch: failure! retrying"); + return do_authed_fetch($mode, $maxid, $sess); +} + +sub do_dump { + # raw handler preemption + my $dt = shift; + return raw_dump() if $dt eq 'raw'; + + # put our data into a format usable by the dumpers + d("do_dump: loading comments"); + my %data; + my @ids = split ',', $bak{"comment:ids"}; + foreach my $id (@ids) { + $data{$id} = load_comment($id); + } + + # get the usermap loaded + d("do_dump: loading users"); + my %usermap; + my @userids = split ',', $bak{"usermap:userids"}; + foreach my $id (@userids) { + $usermap{$id} = $bak{"usermap:$id"}; + } + + # now let's hit up the events + d("do_dump: loading events"); + my %events; + @ids = split ',', $bak{"event:ids"}; + foreach my $id (@ids) { + $events{$id} = load_event($id); + delete $events{$id} if $opts{publiconly} && + $events{$id}->{security} && $events{$id}->{security} ne 'public'; + } + + # and now, the wild and crazy 'dump this' handler ... in case you can't tell, it just + # dispatches to the appropriate dumper, and if an invalid dump type is specified, it + # tells the user they can't do that + my $content = ({html => \&dump_html, xml => \&dump_xml}->{$dt} || \&dump_invalid)->(\%data, \%usermap, \%events); + if ($opts{file}) { + # open file and print + open FILE, ">$opts{file}" + or die "do_dump: unable to open file: $!\n"; + print FILE $content; + close FILE; + } else { + # just throw it out, oh well + print $content; + } +} + +sub do_alter_security { + # raw handler preemption + my ($newsec, $confirmed) = @_; + + # verify new security + my ($security, $allowmask); + if ($newsec eq 'friends') { + ($security, $allowmask) = ('usemask', 1); + } elsif ($newsec eq 'private') { + ($security, $allowmask) = ('private', 0); + } else { + # probably a group? load their groups + my $groups = call_xmlrpc('getfriendgroups', { ver => 1 }); + foreach my $group (@{$groups->{friendgroups} || []}) { + if ($group->{name} eq $newsec) { + # it's this group, set it up + ($security, $allowmask) = ('usemask', 1 << $group->{id}); + } + } + } + die "New security must be one of: friends, private, or the name of a group you have.\n" + unless defined $security && defined $allowmask; + d("do_alter_security: new security = $security ($allowmask)"); + + # load up the user's events + d("do_alter_security: loading events"); + my %events; + my @ids = split ',', $bak{"event:ids"}; + foreach my $id (@ids) { + $events{$id} = load_event($id); + + # delete events that are not public + delete $events{$id} if $events{$id}->{security} && + $events{$id}->{security} ne 'public'; + } + + # now spit out to the user what we're going to change + unless ($confirmed) { + foreach my $evt (sort { $a->{eventtime} cmp $b->{eventtime} } values %events) { + my ($subj, $time) = ($evt->{subject} || '(no subject)', $evt->{eventtime}); + my $ditemid = $evt->{itemid} * 256 + $evt->{anum}; + $subj = substr($subj, 0, 40); + printf "\%-45s\%s\n", $subj, "http://$opts{server}/users/$opts{linkuser}/$ditemid.html"; + } + return; + } + + # if we're confirmed we get here and we should handle uploading the changed entries + foreach my $evt (sort { $a->{eventtime} cmp $b->{eventtime} } values %events) { + # make SURE we have event text (otherwise we delete their entry) + die "FATAL: no event text for event itemid $evt->{itemid}!\n" + unless $evt->{event}; + + # break up the event time + my ($year, $mon, $day, $hour, $min); + if ($evt->{eventtime} =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):\d\d$/) { + ($year, $mon, $day, $hour, $min) = ($1, $2, $3, $4, $5); + } else { + # if we have no time, this is also fatal + die "FATAL: $evt->{eventtime} does not match expected eventtime format.\n"; + } + + # now call for the update + my $hash = call_xmlrpc('editevent', { + ver => 1, + itemid => $evt->{itemid}, + event => $evt->{event}, + subject => $evt->{subject}, + security => $security, + allowmask => $allowmask, + props => $evt->{props}, # hashref + usejournal => $evt->{linkuser}, + year => $year, + mon => $mon, + day => $day, + hour => $hour, + min => $min, + }); + + # see what we got back and make sure it's kosher + die "FATAL: Server sent back ($hash->{itemid}, $hash->{anum}) but expected ($evt->{itemid}, $evt->{anum}).\n" + if $hash->{itemid} != $evt->{itemid} || $hash->{anum} != $evt->{anum}; + + # print success + my $ditemid = $hash->{itemid} * 256 + $hash->{anum}; + printf "\%s\n%-35s\%s\n\n", ($evt->{subject} || "(no subject)"), "public -> $security ($allowmask)", + "http://$opts{server}/users/$opts{linkuser}/$ditemid.html"; + } + + # tell user to run --sync + print "WARNING: you should now run jbackup.pl again with the --sync\n" . + "option, AFTER making a backup copy of your current jbak GDBM\n" . + "file. That way, if anything got messed up, you still have your journal.\n"; +} + +sub dump_invalid { + d("dump_invalid: invalid dump type"); + return "Invalid dump type specified. Valid values are xml, html, and raw.\n"; +} + +# makes an array of trees of comments so they can easily be parsed in dumpers +sub make_tree { + d("make_tree: calculating"); + my $comments = shift; + + my %jitems; + my %children; + while (my ($id, $data) = each %$comments) { + if ($data->{parentid}) { + # not a top level comment + push @{$children{$data->{parentid}}}, $id; + } else { + # top level comment, so add it to the list + push @{$jitems{$data->{jitemid}}}, $id; + } + } + + # now we want to sort all the comments by date + while (my ($id, $list) = each %children) { + $children{$id} = [ sort { $comments->{$a}{date} cmp $comments->{$b}{date} } @$list ]; + } + while (my ($id, $list) = each %jitems) { + $jitems{$id} = [ sort { $comments->{$a}{date} cmp $comments->{$b}{date} } @$list ]; + } + + # now we have all the location information necessary to construct our array + my $creator; + $creator = sub { + my ($jitemid, $jtalkid) = @_; + + # two modes: first creates hashref for an entry, second an arrayref of comments + if ($jitemid) { + my @temp; + foreach my $id (@{$jitems{$jitemid}}) { + # we get comment ids here + push @temp, $creator->(0, $id); + } + return \@temp; + } elsif ($jtalkid) { + my $hash = $comments->{$jtalkid}; + push @{$hash->{children}}, $creator->(0, $_) + foreach @{$children{$jtalkid} || []}; + return $hash; + } + }; + + # create the result array to send back + my %res; + $res{$_} = $creator->($_, 0) foreach keys %jitems; + + # all done + return \%res; +} + +sub prune_nonvisible { + # prunes out nonvisible trunks of the passed comment tree. a nonvisible trunk is defined + # as a part of the comment tree that has no visible children. this could mean they're all + # deleted, or perhaps they're all screened and we're hiding private data. however, note + # that we show normally hidden things if a visible comment is further down the trunk, but + # we want to show as little as possible, so we prune out most things. + my $stem = shift; + my $anyvis = 0; # any visible? + + # hit up each child + my @list; + foreach my $data (@{$stem->{children} || []}) { + $data = prune_nonvisible($data); + if ($data && %$data) { + $anyvis = 1; + push @list, $data; + } + } + $stem->{children} = \@list; + + # now hop back and undefine this stem if necessary. we undefine if we have no visible + # children and we are also not visible. + $stem = undef if !$anyvis && $stem->{state} ne 'A'; + return $stem; +} + +sub dump_html { + my ($comments, $users, $events) = @_; + d("dump_html: dumping."); + + # dumper + my $ret = ""; + my $cdumper; + $cdumper = sub { + my ($ary, $link, $anum, $level) = @_; + foreach my $data (@{$ary || []}) { + # prune out paths that we shouldn't see + $data = prune_nonvisible($data); + next unless $data; + + # we have something to dump, so let's get to it + $ret .= "
    \n"; + my $col = ($level % 2) ? '#bbb' : '#ddd'; + $ret .= "
    \n"; + if ($data->{state} eq 'D') { + $ret .= "(deleted comment)"; + } elsif ($data->{state} eq 'S' && $opts{publiconly}) { + $ret .= "(screened comment)"; + } else { + my $ditemid = $data->{id} * 256 + $anum; + my $commentlink = "$link?thread=$ditemid#t$ditemid"; + $ret .= $data->{posterid} ? + "Comment by $users->{$data->{posterid}} " : + "Anonymous comment "; + $ret .= "on $data->{date}
    \n"; + $data->{subject} = $opts{clean} ? clean_subject($data->{subject}) : ehtml($data->{subject}); + $ret .= "Subject: $data->{subject}
    \n" if $data->{subject}; + $data->{body} = $opts{clean} ? clean_comment($data->{body}) : ehtml($data->{body}); + $ret .= $data->{body} . "\n
    "; + my $replylink = "$link?replyto=$ditemid"; + $ret .= "(reply)\n"; + } + $ret .= "
    \n"; + + # now hit up their children + $cdumper->($data->{children}, $link, $anum, $level+1); + + $ret .= "
    \n"; + } + }; + + # iterate through all entries, sorted by date + my $tree = make_tree($comments); + my $maxcount = scalar keys %$events; + my $count = 0; + foreach my $evt (sort { $a->{eventtime} cmp $b->{eventtime} } values %{$events || {}}) { + $ret .= "
    \n"; + my $itemid = $evt->{itemid} * 256 + $evt->{anum}; + my $link = "http://$opts{server}/users/$opts{linkuser}/$itemid.html"; + $evt->{subject} = $opts{clean} ? clean_subject($evt->{subject}) : ehtml($evt->{subject}); + $ret .= "$evt->{subject}" if $evt->{subject}; + my $altposter = $evt->{poster} ? " (posted by $evt->{poster})" : ""; + $ret .= "$altposter
    \n"; + $ret .= "$evt->{eventtime}

    \n"; + $evt->{event} = $opts{clean} ? clean_event($evt->{event}) : ehtml($evt->{event}); + $ret .= "$evt->{event}
    "; + $ret .= "(reply)
    \n"; + $cdumper->($tree->{$evt->{itemid}}, $link, $evt->{anum}); # dump comments + $ret .= "
    \n"; + + $count++; + unless ($count % 100) { + my $str = sprintf "%.2f%% ...", ($count / $maxcount * 100); + d($str); + } + } + $ret .= ""; + d("100.00% ..."); # just to make it look polished + d("dump_html: done."); + return $ret; +} + +sub dump_xml { + my ($comments, $users, $events) = @_; + d("dump_xml: dumping."); + + # comment dumper + my $ret; + my $cdumper; + $cdumper = sub { + my ($ary, $level) = @_; + my $res; + foreach my $data (@{$ary || []}) { + # prune out paths that we shouldn't see + $data = prune_nonvisible($data); + next unless $data; + + # we have something to dump, so let's get to it + $res .= "\t\t\t\t{posterid}; + $res .= " parentid='$data->{parentid}'" if $data->{parentid}; + $res .= " state='$data->{state}'" if $data->{state} ne 'A'; + $res .= ">\n"; + $res .= "\t\t\t\t\t$data->{date}\n"; + + unless ($data->{state} eq 'D' || + $data->{state} eq 'S' && $opts{publiconly}) { + # spit out subject/body info + foreach (qw(subject body)) { + $data->{$_} = exml($data->{$_}); + $res .= "\t\t\t\t\t<$_>$data->{$_}\n" if $data->{$_}; + } + } + + # now hit up their children + my $sc = $cdumper->($data->{children}, $level+1); + $res .= "\t\t\t\t\t\n$sc\t\t\t\t\t\n" if $sc; + $res .= "\t\t\t\t\n"; + } + return $res; + }; + + # dump xml formatted comments + $ret .= "\n"; + $ret .= "\n\t\n"; + + # now start iterating + my $tree = make_tree($comments); + my $maxcount = scalar keys %$events; + my $count = 0; + foreach my $evt (sort { $a->{eventtime} cmp $b->{eventtime} } values %{$events || {}}) { + my $ditemid = $evt->{itemid} * 256 + $evt->{anum}; + $ret .= "\t\t{security} && $evt->{security} ne 'public'; + $ret .= " allowmask='$evt->{allowmask}'" if $evt->{allowmask}; + $ret .= " poster='$evt->{poster}'" if $evt->{poster}; + $ret .= ">\n"; + foreach (qw(subject event)) { + $evt->{$_} = exml($evt->{$_}); + $ret .= "\t\t\t<$_>$evt->{$_}\n" if $evt->{$_}; + } + $ret .= "\t\t\t$evt->{eventtime}\n"; + $ret .= "\t\t\t$evt->{realtime}\n"; + my $p; + while (my ($k, $v) = each %{$evt->{props} || {}}) { + $k = exml($k); + $v = exml($v); + $p .= "\t\t\t\t\n"; + } + $ret .= "\t\t\t\n$p\t\t\t\n" if $p; + my $c = $cdumper->($tree->{$evt->{itemid}}); # dump comments + $ret .= "\t\t\t\n$c\t\t\t\n" if $c; + $ret .= "\t\t\n"; + + $count++; + unless ($count % 100) { + my $str = sprintf "%.2f%% ...", ($count / $maxcount * 100); + d($str); + } + } + d("100.00% ..."); # spit and polish + + # close out, we're done + $ret .= "\t\n\n"; + d("dump_xml: done."); + return $ret; +} + +sub xmlrpc_call_helper { + # helper function that makes life easier on folks that call xmlrpc stuff. this handles + # running the actual request and checking for errors, as well as handling the cases where + # we hit a problem and need to do something about it. (abort or retry.) + my ($xmlrpc, $method, $req, $mode, $hash) = @_; + d("\t\txmlrpc_call_helper: $method"); + my $res; + eval { $res = $xmlrpc->call($method, $req); }; + if ($res && $res->fault) { + # fatal error, so don't use d() as we want to print even in case of non-verbosity + print STDERR "xmlrpc_call_helper error:\n\tString: " . $res->faultstring . "\n\tCode: " . $res->faultcode . "\n"; + do_abort(); + exit 1; + } + unless ($res) { + # when server times out + d("\t\txmlrpc_call_helper: timeout... retrying."); + return call_xmlrpc($mode, $hash); + } + return $res->result; +} + +sub call_xmlrpc { + # also a way to help people do xmlrpc stuff easily. this method actually does the + # challenge response stuff so we never send the user's password or md5 digest over + # the intarweb. of course, we say nothing about the user's password security anyway... + my ($mode, $hash) = @_; + $hash ||= {}; + + my $xmlrpc = new XMLRPC::Lite; + $xmlrpc->proxy("http://$opts{server}/interface/xmlrpc"); + my $chal; + while (!$chal) { + my $get_chal = xmlrpc_call_helper($xmlrpc, 'LJ.XMLRPC.getchallenge'); + $chal = $get_chal->{'challenge'}; + } + #d("\tcall_xmlrpc: challenge obtained: $chal"); + + my $response = md5_hex($chal . ($opts{md5password} ? $opts{md5password} : md5_hex($opts{password}))); + #d("\tcall_xmlrpc: calling LJ.XMLRPC.$mode"); + my $res = xmlrpc_call_helper($xmlrpc, "LJ.XMLRPC.$mode", { + 'username' => $opts{user}, + 'auth_method' => 'challenge', + 'auth_challenge' => $chal, + 'auth_response' => $response, + %$hash, # interpolate $hash into our hash here...isn't Perl great? + }, $mode, $hash); + return $res; +} + +sub do_flush { + # simply flush ourselves + d('do_flush: flushing database'); + $tied->sync(); +} + +sub do_tie { + # try to open the database for access + d("do_tie: tying database"); + my $x = tie %bak, 'GDBM_File', $filename, &GDBM_WRCREAT, 0600 + or die "Could not open/tie $filename: $!\n"; + return $x; +}; + +sub do_untie { + # close our database. + d("do_untie: untying database"); + return untie %bak; +}; + +sub do_abort { + # hard abort. save our database and just exit right back to the OS. + print STDERR "Aborted.\n"; + do_untie(); + exit 1; +}; + +sub raw_dump { + # dump out the raw GDBM data + while (my ($k, $v) = each %bak) { + print "$k = $v\n"; + } +} + +sub exml { + # stolen from ljlib.pl, LJ::exml + + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[&\"\'<>\x00-\x08\x0B\x0C\x0E-\x1F]/; + # what are those character ranges? XML 1.0 allows: + # #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + + my $a = shift; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/'/g; + $a =~ s//>/g; + $a =~ s/[\x00-\x08\x0B\x0C\x0E-\x1F]//g; + return $a; +} + +sub ehtml { + # also stolen from ljlib.pl, LJ::ehtml + + # fast path for the commmon case: + return $_[0] unless $_[0] =~ /[&\"\'<>]/; + + # this is faster than doing one substitution with a map: + my $a = $_[0]; + $a =~ s/\&/&/g; + $a =~ s/\"/"/g; + $a =~ s/\'/&\#39;/g; + $a =~ s//>/g; + return $a; +} + +# yeah, the cleaners are pretty sad right now. the idea is that perhaps the LJ HTML cleaner can +# be invoked if the user typed the --clean option, it just hasn't been coded in yet. for now, if +# they specify --clean, we will just replace poll tags with links to the poll, and not do much else. +sub clean_event { + my $input = shift; + $input =~ s!!View poll.!g; + return $input; +} + +sub clean_comment { + my $input = shift; + return $input; +} + +sub clean_subject { + my $input = shift; + return $input; +} diff --git a/livejournal/src/utf8.pl b/livejournal/src/utf8.pl new file mode 100755 index 0000000..d50fff8 --- /dev/null +++ b/livejournal/src/utf8.pl @@ -0,0 +1,142 @@ +#!/usr/bin/perl +# +# Validate UTF-8 in Perl, using C. +# +# Brad Fitzpatrick, +# +# UTF-8 character validation code copyright by Unicode, Inc. +# See below. +# + +use Inline C; +use strict; + +sub check_utf8 +{ + my $t = shift; + return 0 if $t =~ /\0/; # no embedded nulls + return isLegalUTF8String($t); +} + + +my @tests = ( + # these are okay: + "1) a" => 1, + "2) Some string!\n" => 1, + "3) Stra\xc3\x9fe" => 1, # StraBe (B = German 'ss') + + # these should fail: + "4) Stra\xc3" => 0, # Strasse, with B cut in middle + "5) \0" => 0, # don't allow nulls in middle + "6) \xFF", => 0, # out of range + + # these overlongs should fail: (all for ASCII "/") + "7) \xc0\xaf" => 0, + "8) \xe0\x80\xaf" => 0, + "9) \xf0\x80\x80\xaf" => 0, + "10) \xf8\x80\x80\x80\xaf" => 0, + + ); + +while (@tests) { + my ($t, $ev) = splice(@tests, 0, 2); + my $av = check_utf8($t); + unless ($av == $ev) { die "FAIL on $t\n"; } +} + +print "All tests pass.\n"; + +__END__ +__C__ + +/* + * Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +typedef unsigned char UTF8; +typedef unsigned char Boolean; + +#define false 0 +#define true 1 + +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static Boolean isLegalUTF8(UTF8 *source, int length) { + UTF8 a; + UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + if (*source > 0xF4) return false; + } + return true; +} + +/********************* End code from Unicode, Inc. ***************/ + +/* + * Author: Brad Fitzpatrick + * + */ + +Boolean isLegalUTF8String(char *str) +{ + UTF8 *cp = str; + int i; + while (*cp) { + /* how many bytes follow this character? */ + int length = trailingBytesForUTF8[*cp]+1; + + /* check for early termination of string: */ + for (i=1; i +# + +use strict; +use Fcntl; +use POSIX qw(tmpnam); +use XMLRPC::Lite; +use Data::Dumper; +my $CONFFILE = "$ENV{'HOME'}/.journalconf"; + +unless (-s $CONFFILE) { + open (C, ">>$CONFFILE"); close C; chmod 0700, $CONFFILE; + print "\nNo ~/.journalconf config file found.\nFormat: one journal account per line.\n"; + print "Example config for posting to both LiveJournal and Slashdot:\n\n"; + print "servertype=lj username=test password=test host=www.livejournal.com\n"; + print "servertype=slash username=\"some username\" password=linux host=slashdot.org\n"; + print "\n"; + exit 1; +} + +my %dispatch; + +# LiveJournal support +$dispatch{'lj'} = sub +{ + my ($acct, $post) = @_; + my $xmlrpc = new XMLRPC::Lite; + $xmlrpc->proxy("http://$acct->{'host'}/interface/xmlrpc"); + my @now = localtime(); + my $req = { + 'username' => $acct->{'username'}, + 'password' => $acct->{'password'}, + 'subject' => $post->{'subject'}, + 'event' => $post->{'body'}, + 'mode' => 'postevent', + 'security' => $post->{'security'} || "public", + 'year' => $now[5]+1900, + 'mon' => $now[4]+1, + 'day' => $now[3], + 'hour' => $now[2], + 'min' => $now[1], + }; + foreach (qw(music mood)) { + next unless $post->{$_}; + $req->{"props"}->{"current_$_"} = $post->{$_}; + } + my $res = $xmlrpc->call('LJ.XMLRPC.postevent', $req); + if ($res->fault) { + print STDERR "Error posting to LJ server:\n". + " String: " . $res->faultstring . "\n" . + " Code: " . $res->faultcode . "\n"; + return 0; + } + return 1; +}; + +$dispatch{'slash'} = sub +{ + print STDERR "Unimplemented.\n"; + return 0; +}; + +my $editor = $ENV{'EDITOR'} || "vi"; +my $tmpname; +do { $tmpname = tmpnam() } +until sysopen(FH, $tmpname, O_RDWR|O_CREAT|O_EXCL); +END { unlink($tmpname); } + +print FH "Subject: \n"; +print FH "----\n"; +close FH; +chmod $tmpname, 0700; + +if (system($editor, $tmpname)) { + die "Failed to run \$EDITOR\n"; +} + +my %jdata; +open (J, $tmpname) or die "Can't reopen temp file?"; +$jdata{lc($1)} = $2 + while (scalar() =~ /^\s*(\S+)\s*:\s*(.+?)\s*\n/); +$jdata{'body'} .= join('',); +$jdata{'body'} =~ s/\s+$//; + +open (C, $CONFFILE); +while () { + next unless /\S/; + chomp; + my %params; + while (s/(\w+)=(?:([^\"\s]+)|(\"(.+?)\"))//) { + $params{$1} = $2 || $4; + + } + my $stype = $params{'servertype'}; + die "Unknown server type \"$stype\"\n" + unless defined $dispatch{$stype}; + die "Error posting to $stype\n" + unless ($dispatch{$stype}->(\%params, \%jdata)); +} +close C; +print "Done.\n"; + diff --git a/livejournal/temp/.placeholder b/livejournal/temp/.placeholder new file mode 100755 index 0000000..2895e7a --- /dev/null +++ b/livejournal/temp/.placeholder @@ -0,0 +1 @@ +This file exists to make sure the directory is created. diff --git a/livejournal/test/MANIFEST b/livejournal/test/MANIFEST new file mode 100755 index 0000000..fa36640 --- /dev/null +++ b/livejournal/test/MANIFEST @@ -0,0 +1,9 @@ +bin/ipl +examples/example.test.pl +examples/moveuclusterd_tests.pl +lib/LJ/Object.pm +lib/LJ/Test/Assertions.pm +lib/LJ/Test/Result.pm +lib/LJ/Test/Unit.pm +Makefile.PL +MANIFEST diff --git a/livejournal/test/MANIFEST.SKIP b/livejournal/test/MANIFEST.SKIP new file mode 100755 index 0000000..ede9cda --- /dev/null +++ b/livejournal/test/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^# +\bCVS\b +^MANIFEST\. +^Makefile$ +~$ +\.html$ +\.old$ +^blib/ +_blib$ +^MakeMaker-\d +^\.exists diff --git a/livejournal/test/Makefile.PL b/livejournal/test/Makefile.PL new file mode 100755 index 0000000..9d7a0ac --- /dev/null +++ b/livejournal/test/Makefile.PL @@ -0,0 +1,37 @@ +#!/usr/bin/perl +# +# Perl Makefile for LJ-Test +# $Id: Makefile.PL,v 1.1 2004/10/30 01:10:20 deveiant Exp $ +# +# Invoke with 'perl Makefile.PL' +# +# See ExtUtils::MakeMaker (3) for more information on how to influence +# the contents of the Makefile that is written +# + +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'LJ-Test', + VERSION_FROM => 'lib/LJ/Test/Unit.pm', # finds $VERSION + AUTHOR => 'Michael Granger ', + ABSTRACT => 'Unit testing for LiveJournal code', + PREREQ_PM => { + Scalar::Util => 0, + Time::HiRes => 0, + Carp => 0, + Data::Compare => 0, + Danga::Exceptions => 1.03, + overload => 0, + Class::Translucent => 0, + }, + dist => { + CI => "cvs commit", + RCS_LABEL => 'cvs tag RELEASE_$(VERSION_SYM)', + SUFFIX => ".gz", + DIST_DEFAULT => 'all tardist', + COMPRESS => "gzip", + }, + +); + diff --git a/livejournal/test/bin/ipl b/livejournal/test/bin/ipl new file mode 100755 index 0000000..f3af76f --- /dev/null +++ b/livejournal/test/bin/ipl @@ -0,0 +1,404 @@ +#!/usr/bin/perl +package IPL::Shell; +use strict; + +BEGIN { + use vars qw{$VERSION $RCSID}; + + $VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: ipl,v 1.3 2004/11/11 00:51:38 deveiant Exp $; + + use base qw{Shell::Base}; + + use Carp qw{carp croak confess}; + use Data::Dumper qw{}; + use Term::ANSIColor qw{color}; + use Cwd qw{cwd}; + use File::Basename qw(basename); + use Net::Domain qw(hostfqdn); + use String::Format qw(stringf); + use Sys::Hostname qw(hostname); + use Devel::Symdump qw{}; + + $Shell::Base::RE_QUIT = '(?i)^\s*(exit|q(uit)?|logout)'; +} + + + +##################################################################### +### C L A S S G L O B A L S +##################################################################### + +# Default configuration values +our %Defaults = ( + prompt_fmt => '%{bold cyan}C%p%{white}C %!> ', +); + + + +##################################################################### +### I N S T A N C E M E T H O D S +##################################################################### + +### Shell initialization +sub init { + my ( $self, $args ) = @_; + + # Merge defaults + %$args = ( %Defaults, %$args ); + + # Add instance vars + $self->{result_history} = []; + $self->{package} = 'main'; + $self->{prompt_fmt} = $args->{prompt_fmt}; +} + + +### METHOD: init_completions() +### Initialize the internal COMPLETIONS list. +sub init_completions { + my $self = shift; + $self->SUPER::init_completions; + $self->completions( map { ":$_" } $self->completions ); +} + + +### Intro/outro message +sub intro { return qq{IPL: Interactive Perl Shell $VERSION} } +sub outro { "" } + + +### Prompt callback +sub prompt { + my $self = shift; + my $fmt = $self->{prompt_fmt}; + + my $prompt = stringf $fmt => { + '!' => $self->term->{history_length}, + '$' => $$, + '0' => $self->progname, + 'C' => sub { color($_[0]) }, + 'H' => hostfqdn, + 'W' => basename(cwd), + 'c' => ref($self), + 'g' => scalar getgrgid($(), + 'h' => hostname, + 'p' => $self->{package}, + 'u' => scalar getpwuid($<), + 'w' => cwd, + }; + + # Append a reset to clean up if there are color escapes in the prompt + $prompt .= color( 'reset' ) if $prompt =~ m{\e\[}; + + return "\n$prompt"; +} + + +### METHOD: print( $output ) +### Output method. +sub print { + my $self = shift; + my $output = join( "", @_ ); + + my $nlcount = $output =~ tr/\n/\n/; + + if ( $nlcount >= $self->{ROWS} - 3 ) { + my $pager = $self->pager; + open my $P, "|$pager" or carp "Can't open $pager: $!"; + CORE::print $P $output; + close $P; + } else { + CORE::print $output; + } + +} + + +### METHOD: parseline( $input ) +### Command-parsing method: parse the specified I, run the specified +### command, and output the result. +sub parseline { + my ( $self, $input ) = @_; + + if ( $input =~ m{^:(\S+.*)} ) { + return $self->SUPER::parseline( $1 ); + } + + else { + return ( "eval", {}, $input ); + } +} + + +### METHOD: prettyPrint( $value ) +### Return the given I as a pretty-printed string. +sub prettyPrint { + my ( $self, $val ) = @_; + + local $Data::Dumper::Terse = 1; + local $Data::Dumper::Indent = 1; + local $Data::Dumper::Pad = " "; + + my $rval = Data::Dumper->Dumpxs( [$val] ); + $rval =~ s{^\s+}{}; + $rval = " => $rval "; + + return $rval; +} + + + +##################################################################### +### C O M M A N D M E T H O D S +##################################################################### + +### METHOD: do_shellobj( undef ) +### Implementation of the 'shellobj' command +sub do_shellobj { + my $self = shift; + return Data::Dumper->Dumpxs( [$self], [qw{self}] ); +} + + +### METHOD: help_shellobj( undef ) +### Callback for help on the 'shellobj' command. +sub help_shellobj { + return q{Show a dump of the IPL shell object itself.}; +} + + +### METHOD: do_eval( @args ) +### Implementation of the 'eval' command. +sub do_eval { + my ( $self, @args ) = @_; + + my ( + $input, + $res, + $rval, + ); + + $input = join( ' ', @args ); + #$self->print( "[Evaluating '$input']\n" ); + $res = eval qq{ + package $self->{package}; + no strict; + $input ; + }; + + # Show error message for errors + if ( $@ ) { + ( $rval = $@ ) =~ s{at \S+ line \d+\..*}{}; + } + + # Dump everything else + else { + $rval = $self->prettyPrint( $res ); + } + + return $rval; +} + +### METHOD: help_eval( undef ) +### Provide help text for the 'eval' command. +sub help_eval { + return q{Evaluate the input as Perl and display the result.}; +} + + +### METHOD: do_rl( $subcmd, @args ) +### Implementation of the 'readline' command. +sub do_rl { + my ( $self, $subcmd, @args ) = @_; + + my $rval = ''; + + if ( $subcmd =~ m{features} ) { + $rval = $self->prettyPrint( $self->term->Features ); + } + + elsif ( $subcmd =~ m{module} ) { + $rval = "Readline features provided by: " . + $self->term->ReadLine; + } + + elsif ( $subcmd =~ m{completions} ) { + $rval = "Tab-completions: \n" . + $self->prettyPrint( [sort $self->completions] ); + } + + else { + $rval = $self->prettyPrint( $self->term ); + } + + return $rval; +} + + +### METHOD: help_rl( undef ) +### Return help text for the 'rl' (readline) command. +sub help_rl {q{ +rl [] + +Provide information about the readline implementation used by the shell. The + can be one of: + +features Dump the hash of features understood by the implementation. +module Show the name of the actual module that is providing readline + features. +completions Dump the list of tab-completions. + +}} + + +### METHOD: do_perldoc( @args ) +### Implementation of the 'perldoc' command. +sub do_perldoc { + my ( $self, @args ) = @_; + + if ( @args ) { + system 'perldoc', @args; + return undef; + } else { + return "'perldoc' requires at least one argument."; + } +} + + +### METHOD: help_perldoc() +### Help method for the 'perldoc' command. +sub help_perldoc {q{ +Run the 'perldoc' program. +}} + + +### METHOD: do_package( $newpkg ) +### Change the package future evals will take place in. +sub do_package { + my ( $self, $package ) = @_; + + if ( $package ) { + return "Invalid package name '$package'" + unless $package =~ m{^[a-z]\w+(?:::[a-z]\w+)*$}i; + $self->{package} = $package; + return "Set eval package to: '$package'."; + } else { + return "Current package is: '$self->{package}'."; + } +} + + +### METHOD: help_package() +### Help method for the 'package' command. +sub help_package {q{ + package [] + +Set the package future evaluations will occur in to 'newpackage' if the optional +argument is given, else just print the name of the current package. +}} + + + + +### METHOD: do_reload() +### Implementation of the 'reload' command. +sub do_reload { + my $self = shift; + + if ( my $h = $self->histfile ) { + $self->term->WriteHistory( $h ); + } + + $self->print( "Re-execing shell...\n" ); + local $ENV{IPL_RELOAD} = 1; + exec $0; + return "Hmmm... something funky happened."; +} + +sub help_reload {q{ + reload + +Reload the shell. +}} + + +### METHOD: do_inspect( [$package] ) +### Implementation of the 'inspect' command. +sub do_inspect { + my $self = shift; + my $package = shift || $self->{package}; + + my $inspector = new Devel::Symdump $package; + + no strict; + my @out = ( "Symbol table for $package" ); + my ( %scalars, %arrays, %hashes, %functions, %packages, %filehandles ); + + # Grab entries for each type from the symbol table for the inspected + # package. + %scalars = map { $_ => ${*{$_}{SCALAR}} } $inspector->scalars; + %arrays = map { $_ => *{$_}{ARRAY} } $inspector->arrays; + %hashes = map { $_ => *{$_}{HASH} } $inspector->hashes; + %functions = map { $_ => *{$_}{CODE} } $inspector->functions; + %packages = map { $_ => undef } $inspector->packages; + %filehandles = map { $_ => *{$_}{IO} } $inspector->filehandles; + + # Build displays for each entry in the symbol table, sorted by type, + # prepending the sigil for each one. In part stolen from Matthew Simon + # Cavalletto's Term::ShellKit::Dev + foreach my $output ( + [ 'Scalars', \%scalars, '$', ], + [ 'Arrays', \%arrays, '@'], + [ 'Hashes', \%hashes, '%'], + [ 'Subs', \%functions, 'sub '], + [ 'Packages', \%packages, '::'], + [ 'Filehandles', \%filehandles, '*'], + ) { + next unless scalar keys %{$output->[1]}; + push @out, "$output->[0]:", '-' x length($output->[0]); + foreach ( sort keys %{$output->[1]} ) { + if ( defined $output->[1]{$_} ) { + push @out, qq{ $output->[2]$_ = "$output->[1]{$_}"}; + } else { + push @out, qq{ $output->[2]$_}; + } + } + } + + return join "\n", @out; + + +} + +sub help_inspect {q{ + inspect [] + +Inspect the contents of the specified package, or the current package if no +package is given. +}} + + + +##################################################################### +### R U N T I M E P A C K A G E +##################################################################### +package ipl; +use strict; + +BEGIN { + use Getopt::Long qw{GetOptions}; + $GetOpt::Long::Bundling = 1; +} + + +if ( $0 eq __FILE__ ) { + my %opts = ( + HISTFILE => glob("~/.ipl_history"), + RCFILES => [glob("~/.iplrc"), ".iplrc"], + ); + + IPL::Shell->new( %opts )->run; +} + + diff --git a/livejournal/test/examples/example.test.pl b/livejournal/test/examples/example.test.pl new file mode 100755 index 0000000..67fbe0f --- /dev/null +++ b/livejournal/test/examples/example.test.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl -w +########################################################################### + +=head1 Example test script + +This is a minimal test suite to demo LJ::Test::Unit. + +=head1 CVS + + $Id: example.test.pl,v 1.1 2004/10/30 01:10:21 deveiant Exp $ + +=cut + +########################################################################### +package moveuclusterd_tests; +use strict; + +use lib qw{lib}; + +use LJ::Test::Unit qw{+autorun}; +use LJ::Test::Assertions qw{:all}; + +sub test_00_packages { + assert( 1 ); + assert_undef( undef ); + assert_defined( 1 ); + assert_no_exception { my $foo = 1; }; +} + +sub test_01_fail { + fail( "Intentional failure." ); +} + +sub test_02_fail2 { + assert_no_exception { blargllglg() } "Demo of failing assertion."; +} + +sub test_05_error { + plop(); +} diff --git a/livejournal/test/examples/moveuclusterd_tests.pl b/livejournal/test/examples/moveuclusterd_tests.pl new file mode 100755 index 0000000..dab7b4b --- /dev/null +++ b/livejournal/test/examples/moveuclusterd_tests.pl @@ -0,0 +1,130 @@ +#!/usr/bin/perl -w +########################################################################### + +=head1 Tests For moveuclusterd + +This is the test suite for 'moveuclusterd', the jobserver half of the +LiveJournal user-mover. + +=cut + +########################################################################### +package moveuclusterd_tests; +use strict; + +use lib ( "$ENV{LJHOME}/bin", "lib" ); + +use LJ::Test::Unit qw{+autorun}; +use LJ::Test::Assertions qw{:all}; + +BEGIN { + require 'moveuclusterd.pl'; +} + + +my @test_goodjobspecs = ( + q{67645:23:30}, + q{3932342:117:62 prelock=1}, + q{1103617:85:88 giddy=whippingcream bollocks=queen prelock=1}, +); +my @test_badjobspecs = ( + q{}, + q{14}, + q{12:22}, +); + + +### General tests +sub test_packages { + foreach my $package (qw{JobServer JobServer::Job JobServer::Client}) { + assert_no_exception { $package->isa('UNIVERSAL') }; + } +} + +### JobServer::Job class tests +sub test_jobserverjob_new { + my ( $obj, $rval ); + my $server = new JobServer; + + # Requires a server as first argument + assert_exception { + new JobServer::Job; + }; + + # Valid jobspecs + foreach my $spec ( @test_goodjobspecs ) { + assert_no_exception { + $obj = new JobServer::Job $server, $spec + }; + assert_instance_of 'JobServer::Job', $obj; + + my ( $userid, $scid, $dcid, $rest ) = split /[:\s]/, $spec, 4; + $rest ||= ''; + + assert_no_exception { $rval = $obj->userid }; + assert_equal $userid, $rval; + + assert_no_exception { $rval = $obj->srcclusterid }; + assert_equal $scid, $rval; + + assert_no_exception { $rval = $obj->dstclusterid }; + assert_equal $dcid, $rval; + + assert_no_exception { $rval = $obj->stringify }; + $rest = sprintf '(%s)', join( '|', split(/\s+/, $rest) ); + assert_matches qr{$userid:$scid:$dcid \d+.\d+ $rest}, $rval; + } + + # Invalid jobspecs + foreach my $spec ( @test_badjobspecs ) { + assert_exception { + new JobServer::Job $server, $spec + } "Didn't expect to be able to create job '$spec'"; + } +} + + +### JobServer class tests +sub test_jobserver_new { + my $rval; + + assert_no_exception { $rval = new JobServer }; + assert_instance_of 'JobServer', $rval; +} + + +sub test_jobserver_addjobs { + my $rval; + my $js = new JobServer; + + # Should be able to call addJobs() with no jobs. + assert_no_exception { + local $^W = 0; # Quell LJ::start_request()'s warnings + $js->addJobs; + }; + + # Server should have 0 jobs queued + assert_no_exception { + $rval = $js->getJobList; + }; + assert_matches qr{0 queued jobs, 0 assigned jobs for 0 clusters}, $rval->{footer}[0]; + assert_matches qr{0 of 0 total jobs assigned since}, $rval->{footer}[1]; + + # Load up some job objects and add those + my @jobs = map { new JobServer::Job $js, $_ } @test_goodjobspecs; + my $jobcount = scalar @jobs; + assert_no_exception { + local $^W = 0; # Quell LJ::start_request()'s warnings + $js->addJobs( @jobs ); + }; + + # Now server should have the test jobs queued + assert_no_exception { + $rval = $js->getJobList; + }; + assert_matches qr{$jobcount queued jobs, 0 assigned jobs for \d+ clusters}, $rval->{footer}[0]; + assert_matches qr{0 of $jobcount total jobs assigned since}, $rval->{footer}[1]; + +} + + diff --git a/livejournal/test/lib/LJ/Object.pm b/livejournal/test/lib/LJ/Object.pm new file mode 100755 index 0000000..5afa8b9 --- /dev/null +++ b/livejournal/test/lib/LJ/Object.pm @@ -0,0 +1,232 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +LJ::Object - Base object class for LiveJournal object classes. + +=head1 SYNOPSIS + + use base qw{LJ::Object}; + + sub new { + my $prot = shift; + my $class = ref $proto || $proto; + + return $self->SUPER::new( @_ ); + } + +=head1 REQUIRES + +C, C, C, C, +C + +=head1 DESCRIPTION + +This is a base object class for LiveJournal object classes that provides some +basic useful functionality that would otherwise have to be repeated throughout +various object classes. + +It currently provides methods for debugging and logging facilities, translucent +attributes, etc. + +=head1 AUTHOR + +Michael Granger Eged@danga.comE + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package LJ::Object; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + ### Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Object.pm,v 1.2 2004/10/30 02:07:22 deveiant Exp $; + + # Human-readable constants + use constant TRUE => 1; + use constant FALSE => 0; + + # Modules + use Carp qw{carp croak confess}; + use Scalar::Util qw{blessed}; + use Danga::Exceptions qw{:syntax}; + + # Superclass + class template + use Class::Translucent ({ + debugFunction => undef, + logFunction => undef, + + debugLevel => 0, + }); + + + # Inheritance + use base qw{Class::Translucent}; +} + + +##################################################################### +### C L A S S V A R I A B L E S +##################################################################### + +our ( $AUTOLOAD ); + + + +############################################################################### +### P U B L I C M E T H O D S +############################################################################### + +### (CLASS) METHOD: DebugMsg( $level, $format, @args ) +### If the debug level is C<$level> or above, and the debugFunction is defined, +### call it at the specified level with the given printf C<$format> and +### C<@args>. If the debug level would allow the message, but no debugFunction +### is defined, the LogMsg() method is called instead at the 'debug' priority. +sub DebugMsg { + my $self = shift or throw Danga::MethodError; + my $level = shift; + my $debugLevel = $self->debugLevel; + return unless $level && $debugLevel >= abs $level; + + my $message = shift; + + if ( $debugLevel > 1 ) { + my $caller = caller; + $message = "<$caller> $message"; + } + + if (( my $debugFunction = $self->debugFunction )) { + $debugFunction->( $message, @_ ); + } else { + $self->LogMsg( 'debug', $message, @_ ); + } +} + + +### (CLASS) METHOD: LogMsg( $level, $format, @args ) +### Call the log function (if defined) at the specified level with the given +### printf C<$format> and C<@args>. +sub LogMsg { + my $self = shift or throw Danga::MethodError; + my $logFunction = $self->logFunction or return (); + + my ( + @args, + $level, + $objectName, + $format, + ); + + ### Massage the format a bit to include the object it's coming from. + $level = shift; + ( $objectName = ref $self ) =~ s{(Danga|LJ|FotoBilder)::}{}g; + $format = sprintf( '%s: %s', $objectName, shift() ); + + # Turn any references or undefined values in the arglist into dumped strings + @args = map { defined $_ ? (ref $_ ? Data::Dumper->Dumpxs([$_], [ref $_]) : $_) : '(undef)' } @_; + + # Call the logging callback + $logFunction->( $level, $format, @args ); +} + + +### (PROXY) METHOD: AUTOLOAD( @args ) +### Proxy method to build (non-translucent) object accessors. +sub AUTOLOAD { + my $self = shift or throw Danga::MethodError; + ( my $name = $AUTOLOAD ) =~ s{.*::}{}; + + ### Build an accessor for extant attributes + if ( blessed $self && exists $self->{$name} ) { + $self->DebugMsg( 5, "AUTOLOADing '%s'", $name ); + + ### Define an accessor for this attribute + my $method = sub : lvalue { + my $closureSelf = shift or throw Danga::MethodError; + + $closureSelf->{$name} = shift if @_; + return $closureSelf->{$name}; + }; + + ### Install the new method in the symbol table + NO_STRICT_REFS: { + no strict 'refs'; + *{$AUTOLOAD} = $method; + } + + ### Now jump to the new method after sticking the self-ref back onto the + ### stack + unshift @_, $self; + goto &$AUTOLOAD; + } + + ### Try to delegate to our parent's version of the method + my $parentMethod = "SUPER::$name"; + return $self->$parentMethod( @_ ); +} + + +### Destructors +END {} + +### The package return value (required) +1; + + +############################################################################### +### D O C U M E N T A T I O N +############################################################################### + +### AUTOGENERATED DOCUMENTATION FOLLOWS + +=head1 METHODS + +=head2 Class Methods + +=over 4 + +=item I + +If the debug level is C<$level> or above, and the debugFunction is defined, +call it at the specified level with the given printf C<$format> and +C<@args>. If the debug level would allow the message, but no debugFunction +is defined, the LogMsg() method is called instead at the 'debug' priority. + +=item I + +Call the log function (if defined) at the specified level with the given +printf C<$format> and C<@args>. + +=back + +=head2 Proxy Methods + +=over 4 + +=item I + +Proxy method to build (non-translucent) object accessors. + +=back + +=cut + diff --git a/livejournal/test/lib/LJ/Test/Assertions.pm b/livejournal/test/lib/LJ/Test/Assertions.pm new file mode 100755 index 0000000..88d1aaa --- /dev/null +++ b/livejournal/test/lib/LJ/Test/Assertions.pm @@ -0,0 +1,676 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +LJ::Test::Assertions - Assertion-function library + +=head1 SYNOPSIS + + use LJ::Test::Assertions qw{:all}; + +=head1 REQUIRES + +C, C, C, C, +C + +=head1 DESCRIPTION + +None yet. + +=head1 EXPORTS + +Nothing by default. + +This module exports several useful assertion functions for the following tags: + +=over 4 + +=item B<:assertions> + +A collection of assertion functions for testing. You can define your own +assertion functions by implementing them in terms of L. + +L, L, +L, L, +L, L, L, +L, L, L, L, L, +L, L, L + +=item B<:skip> + +L, L + +=back + +=head1 TO DO + +=over 4 + +=item Skip Functions + +The skip functions are functional, but the backend isn't set up to handle them +yet. + +=item Test::Harness Integration + +I ripped out the L code when I ported over the +L code for the sake of simplicity. I plan to move that over at +some point. + +=item Docs + +The docs for most of this stuff is still sketchy. + +=back + +=head1 AUTHOR + +Michael Granger Eged@danga.comE + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package LJ::Test::Assertions; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + ### Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Assertions.pm,v 1.2 2004/10/30 02:07:22 deveiant Exp $; + + # Export functions + use base qw{Exporter}; + use vars qw{@EXPORT @EXPORT_OK %EXPORT_TAGS}; + + @EXPORT = qw{}; + %EXPORT_TAGS = ( + assertions => [qw{ + &assert + &assert_not + &assert_defined + &assert_undef + &assert_no_exception + &assert_exception + &assert_exception_type + &assert_exception_matches + &assert_equal + &assert_equals + &assert_matches + &assert_ref + &assert_not_ref + &assert_instance_of + &assert_kind_of + + &fail + }], + + skip => [qw{ + &skip_one + &skip_all + }], + ); + + # Create an 'all' Exporter class which is the union of all the others and + # then add the symbols it contains to @EXPORT_OK + { + my %seen; + push @{$EXPORT_TAGS{all}}, + grep {!$seen{$_}++} @{$EXPORT_TAGS{$_}} foreach keys %EXPORT_TAGS; + } + Exporter::export_ok_tags('all'); + + # Require modules + use Data::Compare qw{Compare}; + use Scalar::Util qw{blessed dualvar}; + use Data::Dumper qw{}; + use Carp qw{croak confess}; + + # Observer pattern + use vars qw{@Observers}; + @Observers = qw{}; +} + + +##################################################################### +### A S S E R T I O N F A I L U R E C L A S S +##################################################################### +{ + package LJ::Test::AssertionFailure; + use Danga::Exceptions qw{}; + use Carp qw{croak confess}; + use base qw{Danga::Exception}; + + our $ErrorType = "assertion failure"; + + ### Overridden to unwrap frames from the stacktrace. + sub new { + my $proto = shift; + local $Danga::Exception::Depth = $Danga::Exception::Depth + 2; + return $proto->SUPER::new( @_ ); + } + + ### Override the base class's error message to make sense as an exception + ### failure. + sub error { + my $self = shift; + + my ( $priorframe, $testframe ); + my @frames = $self->stacktrace; + + for ( my $i = 0; $i <= $#frames; $i++ ) { + next unless $frames[$i]->{package} eq 'LJ::Test::Result'; + ( $priorframe, $testframe ) = @frames[ $i-1, $i ]; + last; + } + + unless ( $priorframe ) { + ( $priorframe, $testframe ) = @frames[ 0, 1 ]; + } + + return sprintf( "%s\n\tin %s (%s) line %d\n\t(%s).\n", + $self->message, + $testframe->{subroutine}, + $priorframe->{filename}, + $priorframe->{line}, + scalar localtime($self->timestamp) ); + } + +} + + + +##################################################################### +### F O R W A R D D E C L A R A T I O N S +##################################################################### + +sub assert ($;$); +sub assert_not ($;$); +sub assert_defined ($;$); +sub assert_undef ($;$); +sub assert_no_exception (&;$); +sub assert_exception (&;$); +sub assert_exception_type (&$;$); +sub assert_exception_matches (&$;$); +sub assert_equals ($$;$); +sub assert_matches ($$;$); +sub assert_ref ($$;$); +sub assert_not_ref ($;$); +sub assert_instance_of ($$;$); +sub assert_kind_of ($$;$); + +sub fail (;$); + +sub skip_one (;$); +sub skip_all (;$); + + + +##################################################################### +### O B S E R V E R F U N C T I O N S +##################################################################### + +### METHOD: add_observer( $observer ) +### Add the given object, package, or coderef (I) to the list of +### observers. When an assertion is called, a notification will be sent to the +### registrant. If the specified I is an object or a package, the +### C method will be called on it. If the observer is a coderef, the +### coderef itself will be called. +sub add_observer { + shift if $_[0] eq __PACKAGE__; # Allow this to be called as a method, too. + my $observer = shift or return; + push @Observers, $observer; +} + + +### METHOD: remove_observer( $observer ) +### Remove the given I from the list of observers. +sub remove_observer { + shift if $_[0] eq __PACKAGE__; # Allow calling as a method + my $observer = shift or return; + @Observers = grep { "$observer" ne "$_" } @Observers; +} + + +### METHOD: notify_observers( $type ) +### Notify any registered observers that an assertion has been made. The +### I will be passed to each observer. +sub notify_observers { + shift if $_[0] eq __PACKAGE__; # Allow calling as a method + + foreach my $observer ( @Observers ) { + if ( ref $observer eq 'CODE' ) { + $observer->( __PACKAGE__, @_ ); + } + + else { + $observer->update( __PACKAGE__, @_ ); + } + } +} + +### (PRIVATE) FUNCTION: makeMessage( $failureInfo, $format, @args ) +### Do sprintf-style formatting on I and I and catenate it with +### the given I if it's defined and not empty. +sub makeMessage { + my ( $failureInfo, $fmt, @rawargs ) = @_; + local $Data::Dumper::Terse = 1; + my @args = map { + ref $_ + ? Data::Dumper->Dumpxs([$_], ['_']) + : (defined $_ ? "$_" : "(undef)") + } @rawargs; + my $failureMessage = sprintf( $fmt, @args ); + + return $failureInfo + ? "$failureInfo\n\t$failureMessage" + : $failureMessage; +} + + + +##################################################################### +### A S S E R T I O N F U N C T I O N S +##################################################################### + +### (ASSERTION) FUNCTION: assert( $value[, $failureInfo] ) +### Die with a failure message if the specified I is not true. If the +### optional I is given, It will precede the failure message. +sub assert ($;$) { + my ( $assert, $message ) = @_; + + __PACKAGE__->notify_observers( 'assert' ); + $message ||= "Assertion failed: " . (defined $assert ? "'$assert'" : "(undef)"); + throw LJ::Test::AssertionFailure $message unless $assert; + __PACKAGE__->notify_observers( 'success' ); + + return 1; +} + +### (ASSERTION) FUNCTION: assert_not( $value[, $failureInfo] ) +### Die with a failure message if the specified I B true. If the +### optional I is given, it will precede the failure message. +sub assert_not ($;$) { + my ( $assert, $info ) = @_; + my $message = makeMessage( $info, "Expected a false value, got '%s'", $assert ); + assert( !$assert, $message ); +} + +### (ASSERTION) FUNCTION: assert_defined( $value[, $failureInfo] ) +### Die with a failure message if the specified I is undefined. If the +### optional I is given, it will precede the failure message. +sub assert_defined ($;$) { + my ( $assert, $info ) = @_; + my $message = makeMessage( $info, "Expected a defined value, got: %s", $assert ); + assert( defined($assert), $message ); +} + +### (ASSERTION) FUNCTION: assert_undef( $value[, $failureInfo] ) +### Die with a failure message if the specified I is B. If the +### optional I is given, it will precede the failure message. +sub assert_undef ($;$) { + my ( $assert, $info ) = @_; + my $message = makeMessage( $info, "Expected an undefined value, got %s", + $assert ); + assert( !defined($assert), $message ); +} + +### (ASSERTION) FUNCTION: assert_no_exception( \&coderef[, $failureInfo] ) +### Evaluate the specified I, and die with a failure message if it +### generates an exception. If the optional I is given, it will +### precede the failure message. +sub assert_no_exception (&;$) { + my ( $code, $info ) = @_; + + eval { $code->() }; + ( my $errmsg = $@ ) =~ s{ at .* line \d+\.?\s*$}{}; + my $message = makeMessage( $info, "Exception raised when none expected:\n\t<$errmsg>" ); + + assert( ! $@, $message ); +} + +### (ASSERTION) FUNCTION: assert_exception( \&coderef[, $failureInfo] ) +### Evaluate the specified I, and die with a failure message if it does +### not generate an exception. If the optional I is given, it will +### precede the failure message. +sub assert_exception (&;$) { + my ( $code, $info ) = @_; + + eval { $code->() }; + assert( $@, makeMessage($info, "No exception raised.") ); +} + +### (ASSERTION) FUNCTION: assert_exception_type( \&coderef, $type[, $failureInfo] ) +### Evaluate the specified I, and die with a failure message if it does +### not generate an exception which is an object blessed into the specified +### I or one of its subclasses (ie., the exception must return true to +### C<$exception->isa($type)>. If the optional I is given, it will +### precede the failure message. +sub assert_exception_type (&$;$) { + my ( $code, $type, $info ) = @_; + + eval { $code->() }; + assert $@, makeMessage($info, "Expected an exception of type '$type', but none was raised."); + + my $message = makeMessage( $info, "Exception thrown, but was wrong type" ); + assert_kind_of( $type, $@, $message ); +} + +### (ASSERTION) FUNCTION: assert_exception_matches( \&code, $regex[, $failureInfo] ) +### Evaluate the specified I, and die with a failure message if it does +### not generate an exception which matches the specified I. If the +### optional I is given, it will precede the failure message. +sub assert_exception_matches (&$;$) { + my ( $code, $regex, $info ) = @_; + + eval { $code->() }; + assert $@, makeMessage($info, "Expected an exception which matched <$regex>, but none was raised."); + my $err = "$@"; + + my $message = makeMessage( $info, "Exception thrown, but message didn't match" ); + assert_matches( $regex, $err, $message ); +} + + +### (ASSERTION) FUNCTION: assert_equal( $wanted, $tested[, $failureInfo] ) +### Die with a failure message if the specified I value doesn't equal the +### specified I value. The comparison is done with L, so +### arbitrarily complex data structures may be compared, as long as they contain +### no C, C, or C references. If the optional I is +### given, it will precede the failure message. +sub assert_equal ($$;$) { + my ( $wanted, $tested, $info ) = @_; + + my $message = makeMessage( $info, "Values not equal: wanted '%s', got '%s' instead", + $wanted, $tested ); + assert( Compare($wanted, $tested), $message ); +} +*assert_equals = *assert_equal; + + +### (ASSERTION) FUNCTION: assert_matches( $wantedRegexp, $testedValue[, $failureInfo] ) +### Die with a failure message if the specified I doesn't match the +### specified I. If the optional I is given, it will +### precede the failure message. +sub assert_matches ($$;$) { + my ( $wanted, $tested, $info ) = @_; + + if ( ! blessed $wanted || ! $wanted->isa('Regexp') ) { + $wanted = qr{$wanted}; + } + + my $message = makeMessage( $info, "Tested value '%s' did not match wanted regex '%s'", + $tested, $wanted ); + assert( ($tested =~ $wanted), $message ); +} + +### (ASSERTION) FUNCTION: assert_ref( $wantedType, $testedValue[, $failureInfo] ) +### Die with a failure message if the specified I is not of the +### specified I. The I can either be a ref-type like 'ARRAY' +### or 'GLOB' or a package name for testing object classes. If the optional +### I is given, it will precede the failure message. +sub assert_ref ($$;$) { + my ( $wantedType, $testValue, $info ) = @_; + + my $message = makeMessage( $info, "Expected a %s reference, got <%s>", + $wantedType, $testValue ); + + assert( ref $testValue && + (ref $testValue eq $wantedType || UNIVERSAL::isa($wantedType, $testValue)), + $message ); +} + + +### (ASSERTION) FUNCTION: assert_not_ref( $testedValue[, $failureInfo] ) +### Die with a failure message if the specified I is a reference of +### any kind. If the optional I is given, it will precede the +### failure message. +sub assert_not_ref ($;$) { + my ( $testValue, $info ) = @_; + + my $message = makeMessage( $info, "Expected a simple scalar, got <%s>", $testValue ); + assert( !ref $testValue, $message ); +} + + +### (ASSERTION) FUNCTION: assert_instance_of( $wantedClass, $testedValue[, $failureInfo] ) +### Die with a failure message if the specified I is not an instance +### of the specified I. If the optional I is given, it will +### precede the failure message. +sub assert_instance_of ($$;$) { + my ( $wantedClass, $testValue, $info ) = @_; + + my $message = makeMessage( $info, "Expected an instance of '%s', got a non-object <%s>", + $wantedClass, $testValue ); + assert( blessed $testValue, $message ); + + $message = makeMessage( $info, "Expected an instance of '%s'", $wantedClass ); + assert_equals( $wantedClass, ref $testValue, $message ); +} + + +### (ASSERTION) FUNCTION: assert_kind_of( $wantedClass, $testedValue[, $failureInfo] ) +### Die with a failure message if the specified I is not an instance +### of the specified I B one of its derivatives. If the optional +### I is given, it will precede the failure message. +sub assert_kind_of ($$;$) { + my ( $wantedClass, $testValue, $info ) = @_; + + my $message = makeMessage( $info, "Expected an instance of '%s' or a subclass, got <%s>", + $wantedClass, $testValue ); + assert( blessed $testValue, $message ); + assert( $testValue->isa($wantedClass), $message ); +} + + +### (ASSERTION) FUNCTION: fail( [$message] ) +### Die with a failure message unconditionally. If the optional I is +### not given, the failure message will be C. +sub fail (;$) { + my $message = shift || "Failed (no reason given)"; + __PACKAGE__->notify_observers( 'assert' ); + throw LJ::Test::AssertionFailure $message; +} + + +### (SKIP) FUNCTION: skip_one( [$message] ) +### Skip the rest of this test, optionally outputting a message as to why the +### rest of the test was skipped. +sub skip_one (;$) { + my $message = shift || ''; + die bless \$message, 'SKIPONE'; +} + + +### (SKIP) FUNCTION: skip_all( [$message] ) +### Skip all the remaining tests, optionally outputting a message as to why the +### they were skipped. +sub skip_all (;$) { + my $message = shift || ''; + die bless \$message, 'SKIPALL'; +} + + + + +### Destructors +DESTROY {} +END {} + + +1; + + +### AUTOGENERATED DOCUMENTATION FOLLOWS + +=head1 FUNCTIONS + +=head2 Assertion Functions + +=over 4 + +=item I + +Die with a failure message if the specified I is not true. If the +optional I is given, It will precede the failure message. + +=item I + +Die with a failure message if the specified I is undefined. If the +optional I is given, it will precede the failure message. + +=item I + +Die with a failure message if the specified I value doesn't equal the +specified I value. The comparison is done with L, so +arbitrarily complex data structures may be compared, as long as they contain +no C, C, or C references. If the optional I is +given, it will precede the failure message. + +=item I + +Evaluate the specified I, and die with a failure message if it does +not generate an exception. If the optional I is given, it will +precede the failure message. + +=item I + +Evaluate the specified I, and die with a failure message if it does +not generate an exception which matches the specified I. If the +optional I is given, it will precede the failure message. + +=item I + +Evaluate the specified I, and die with a failure message if it does +not generate an exception which is an object blessed into the specified +I or one of its subclasses (ie., the exception must return true to +C<$exception->isa($type)>. If the optional I is given, it will +precede the failure message. + +=item I + +Die with a failure message if the specified I is not an instance +of the specified I. If the optional I is given, it will +precede the failure message. + +=item I + +Die with a failure message if the specified I is not an instance +of the specified I B one of its derivatives. If the optional +I is given, it will precede the failure message. + +=item I + +Die with a failure message if the specified I doesn't match the +specified I. If the optional I is given, it will +precede the failure message. + +=item I + +Evaluate the specified I, and die with a failure message if it +generates an exception. If the optional I is given, it will +precede the failure message. + +=item I + +Die with a failure message if the specified I B true. If the +optional I is given, it will precede the failure message. + +=item I + +Die with a failure message if the specified I is a reference of +any kind. If the optional I is given, it will precede the +failure message. + +=item I + +Die with a failure message if the specified I is not of the +specified I. The I can either be a ref-type like 'ARRAY' +or 'GLOB' or a package name for testing object classes. If the optional +I is given, it will precede the failure message. + +=item I + +Die with a failure message if the specified I is B. If the +optional I is given, it will precede the failure message. + +=item I + +Die with a failure message unconditionally. If the optional I is +not given, the failure message will be C. + +=back + +=head2 Private Functions + +=over 4 + +=item I + +Do sprintf-style formatting on I and I and catenate it with +the given I if it's defined and not empty. + +=back + +=head2 Skip Functions + +=over 4 + +=item I + +Skip all the remaining tests, optionally outputting a message as to why the +they were skipped. + +=item I + +Skip the rest of this test, optionally outputting a message as to why the +rest of the test was skipped. + +=back + +=head1 METHODS + +=over 4 + +=item I + +Add the given object, package, or coderef (I) to the list of +observers. When an assertion is called, a notification will be sent to the +registrant. If the specified I is an object or a package, the +C method will be called on it. If the observer is a coderef, the +coderef itself will be called. + +=item I + +Notify any registered observers that an assertion has been made. The +I will be passed to each observer. + +=item I + +Remove the given I from the list of observers. + +=back + +=cut + diff --git a/livejournal/test/lib/LJ/Test/Result.pm b/livejournal/test/lib/LJ/Test/Result.pm new file mode 100755 index 0000000..762863b --- /dev/null +++ b/livejournal/test/lib/LJ/Test/Result.pm @@ -0,0 +1,207 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +LJ::Test::Result - Unit-test result class for LiveJournal testing + +=head1 SYNOPSIS + + use LJ::Test::Result qw{}; + use LJ::Test::Assertions qw{:all}; + + my $res = new LJ::Test::Result; + $res->run( sub {assert(1)} ); + + print "Results: ", $res->stringify, "\n\n"; + +=head1 REQUIRES + +C, C, C, C + +=head1 DESCRIPTION + +None yet. + +=head1 AUTHOR + +Michael Granger Eged@danga.comE + +Copyright (c) 2004 Danga Interactive. All rights reserved. + +This module is free software. You may use, modify, and/or redistribute this +software under the terms of the Perl Artistic License. (See +http://language.perl.com/misc/Artistic.html) + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +FITNESS FOR A PARTICULAR PURPOSE. + +=cut + +############################################################################## +package LJ::Test::Result; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + ### Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: Result.pm,v 1.2 2004/10/30 02:07:22 deveiant Exp $; + + use LJ::Test::Unit qw{}; + use LJ::Test::Assertions qw{}; + use Danga::Exceptions qw{:syntax}; + + use LJ::Object ({ + assertions => 0, + passed => 0, + runs => [], + failures => [], + errors => [], + }); + + use base qw{LJ::Object}; +} + + + + +############################################################################### +### C O N S T R U C T O R +############################################################################### + + +sub new { + my $class = shift; + + my $self = $class->SUPER::new( @_ ); + + $self->assertions( 0 ); + $self->passed( 0 ); + $self->runs( [] ); + $self->failures( [] ); + $self->errors( [] ); + + return $self; +} + + + +### METHOD: run( \&coderef ) +### Run a test I, counting assertions, errors, and failures towards the +### result. +sub run ($&) { + my ( $self, $testcode ) = @_; + my $rchar = '.'; + + try { + $self->pushRuns( "$testcode" ); + LJ::Test::Assertions->add_observer( $self ); + $testcode->(); + } catch LJ::Test::AssertionFailure with { + my ( $failure, $keeptrying ) = @_; + $self->pushFailures( $failure ); + $$keeptrying = 0; + $rchar = 'F'; + } catch Danga::Exception with { + my $error = shift; + $self->pushErrors( $error ); + $rchar = 'E'; + } finally { + LJ::Test::Assertions->remove_observer( $self ); + }; + + return $rchar; +} + + +### METHOD: update( $package, $type ) +### Observable callback: Called from LJ::Test::Assertion when an assertion is +### made or passes. +sub update { + my $self = shift or throw Danga::MethodError; + my ( $package, $type ) = @_; + + if ( $type eq 'assert' ) { + $self->{assertions}++; + } + + elsif ( $type eq 'success' ) { + $self->{passed}++; + } + + else { + warn "Unhandled update type '$type' from '$package'"; + } +} + + +### METHOD: stringify() +### Return a string representation of the test results as a scalar. +sub stringify { + my $self = shift or throw Danga::MethodError; + + my @rval = (""); + my @exceptions; + + # Add any error traces that occurred + if (( @exceptions = $self->errors )) { + push @rval, "Errors:"; + foreach my $exception ( @exceptions ) { + push @rval, $exception->stringify; + } + } + + # Add any assertion failure messages + if (( @exceptions = $self->failures )) { + push @rval, "Failures:"; + foreach my $failure ( @exceptions ) { + push @rval, $failure->error; + } + } + + # Now append the totals + push @rval, sprintf( "%d tests, %d assertions, %d failures, %d errors", + scalar @{$self->{runs}}, + $self->{assertions}, + scalar @{$self->{failures}}, + scalar @{$self->{errors}} ); + + return join( "\n", @rval ); +} + + + +1; + + +### AUTOGENERATED DOCUMENTATION FOLLOWS + +=head1 METHODS + +=over 4 + +=item I + +Run a test I, counting assertions, errors, and failures towards the +result. + +=item I + +Return a string representation of the test results as a scalar. + +=item I + +Observable callback: Called from LJ::Test::Assertion when an assertion is +made or passes. + +=back + +=cut + diff --git a/livejournal/test/lib/LJ/Test/Unit.pm b/livejournal/test/lib/LJ/Test/Unit.pm new file mode 100755 index 0000000..d9156fa --- /dev/null +++ b/livejournal/test/lib/LJ/Test/Unit.pm @@ -0,0 +1,295 @@ +#!/usr/bin/perl +############################################################################## + +=head1 NAME + +LJ::Test::Unit - unit-testing framework for LiveJournal + +=head1 SYNOPSIS + + use LJ::Test::Unit qw{+autorun}; + use My::FooModule (); + + sub test_foo { assert My::FooModule::foo() } + +=head1 EXAMPLE + + use LJ::Test::Unit qw{+autorun}; + use LJ::Test::Assertions qw{:all}; + + # Require the module + sub test_require { + + # Make sure we can load the module to be tested. + assert_no_exception { require MyClass }; + + # Try to import some functions, generating a custom error message if it + # fails. + assert_no_exception { MyClass->import(':myfuncs') } "Failed to import :myfuncs"; + + # Make sure calling 'import()' actually imported the functions + assert_ref 'CODE', *::myfunc{CODE}; + assert_ref 'CODE', *::myotherfunc{CODE}; + } + +=head1 DESCRIPTION + +This is a simplified Perl unit-testing framework for creating unit tests to be +run either standalone or under Test::Harness. + +=head2 Testing + +Testing in LJ::Test::Unit is done by running a test suite, either via 'make +test', which uses the L 'test' target written by +L, or as a standalone script. + +If errors occur while running tests via the 'make test' method, you can get more +verbose output about the test run by adding C to the end of the +C invocation: + + $ make test TEST_VERBOSE=1 + +If you want to display only the messages caused by failing assertions, you can +add a C to the end of the C invocation instead: + + $ make test VERBOSE=1 + +=head2 Test Suites + +A test suite is one or more test cases, each of which tests a specific unit of +functionality. + +=head2 Test Cases + +A test case is a unit of testing which consists of one or more tests, combined +with setup and teardown functions that make the necessary preparations for +testing. + +You may wish to split test cases up into separate files under a C directory +so they will run under a L-style C. + +=head2 Tests + +You can run tests in one of two ways: either by calling L with a list +of function names or CODErefs to test, or by using this module with the +':autorun' tag, in which case any subs whose name begins with C<'test_'> will +automatically run at the end of the script. + +=head1 REQUIRES + +C, C, C, C, +C, C + +=head1 LICENSE + +This module borrows liberally from the Test::SimpleUnit CPAN module, the license +of which is as follows: + + Michael Granger Eged@danga.comE + + Copyright (c) 1999-2003 The FaerieMUD Consortium. All rights reserved. + + This module is free software. You may use, modify, and/or redistribute this + software under the terms of the Perl Artistic License. (See + http://language.perl.com/misc/Artistic.html) + +LiveJournal-specific code is also licensed under the the same terms as Perl +itself: + + Copyright (c) 2004 Danga Interactive. All rights reserved. + +=cut + +############################################################################## +package LJ::Test::Unit; +use strict; +use warnings qw{all}; + + +############################################################################### +### I N I T I A L I Z A T I O N +############################################################################### +BEGIN { + + # Versioning + use vars qw{$VERSION $RCSID}; + $VERSION = 1.21; + $RCSID = q$Id: Unit.pm,v 1.2 2004/10/30 02:07:22 deveiant Exp $; + + # More readable constants + use constant TRUE => 1; + use constant FALSE => 0; + + # Main unit-testing modules + use LJ::Test::Assertions qw{:all}; + use LJ::Test::Result qw{}; + + # Load other modules + use Carp qw{croak confess}; + use Time::HiRes qw{gettimeofday tv_interval}; + use Data::Dumper qw{}; + + # Export the 'runTests' function + use vars qw{@EXPORT @EXPORT_OK %EXPORT_TAGS}; + @EXPORT_OK = qw{&runTests}; + + use base qw{Exporter}; +} + + +our @AutorunPackages = (); + +### Exporter callback -- support :autorun tag +sub import { + my $package = shift; + my @args = @_; + my @pureargs = grep { !/\+autorun/ } @args; + + if ( @args != @pureargs ) { + push @AutorunPackages, scalar caller; + } + + __PACKAGE__->export_to_level( 1, $package, @pureargs ); +} + + +### FUNCTION: extractTestFunctions( @packages ) +### Iterate over the specified I' symbol tables and return a list of +### coderefs that point to functions contained in those packages that are named +### 'test_*'. +sub extractTestFunctions { + my @packages = @_ or croak "No package given."; + + my ( + $glob, # Iterated glob for symbol table traversal + $coderef, # Extracted coderef from symtable glob + @tests, # Collected coderefs for test functions + ); + + @tests = (); + + # Iterate over the package's symbol table, extracting coderefs to functions + # that are named 'test_*'. + PACKAGE: foreach my $package ( @packages ) { + no strict 'refs'; + + SYMBOL: foreach my $sym ( sort keys %{"${package}::"} ) { + next SYMBOL unless $sym =~ m{test_}; + $coderef = extractFunction( $package, $sym ); + + push @tests, $coderef; + } + } + + return @tests; +} + + +### FUNCTION: extractFunction( $package, $funcname ) +### Given a I and a function name I, extract its coderef from +### the symbol table and return it. +sub extractFunction { + my $package = shift or croak "No package name given."; + my $sym = shift or croak "No function name given"; + + no strict 'refs'; + my $glob = ${"${package}::"}{ $sym } or return undef; + return *$glob{CODE}; +} + + +### FUNCTION: prepTests( $package[, @rawTests] ) +### Normalize the given I (which can be coderefs or function names) +### and return them as coderefs. If I is empty, extract functions from +### the given I and return those. +sub prepTests { + my $package = shift or croak "No calling package specified."; + my @rawtests = @_; + my @tests = (); + + @rawtests = extractTestFunctions( $package ) if !@rawtests; + + my $coderef; + + foreach my $test ( @rawtests ) { + push( @tests, $test), next if ref $test eq 'CODE'; + $coderef = extractFunction( $package, $test ) + or croak "No such test '$test' in $package"; + push @tests, $coderef; + } + + return @tests; +} + + +### FUNCTION: runTests( [@tests] ) +### Run the specified I and report the result. The I can be +### coderefs or names of functions in the current package. If no I are +### specified, functions that are named 'test_*' in the current package are +### assumed to be the test functions. +sub runTests { + my @tests = prepTests( scalar caller, @_ ); + my $result = new LJ::Test::Result; + + print "Started.\n"; + my $starttime = [gettimeofday]; + $|++; + + foreach my $test ( @tests ) { + print $result->run( $test ); + } + + printf "\nFinished in %0.5fs\n", tv_interval( $starttime ); + print $result->stringify, "\n\n"; + + return; +} + + + +### Extract tests from packages that were registered for 'autorun' and run them. +END { + return unless @AutorunPackages; + + # Extract coderefs from autorun packages. + my @tests = extractTestFunctions( @AutorunPackages ); + runTests( @tests ); +} + + +1; + +### AUTOGENERATED DOCUMENTATION FOLLOWS + +=head1 FUNCTIONS + +=over 4 + +=item I + +Given a I and a function name I, extract its coderef from +the symbol table and return it. + +=item I + +Iterate over the specified I' symbol tables and return a list of +coderefs that point to functions contained in those packages that are named +'test_*'. + +=item I + +Normalize the given I (which can be coderefs or function names) +and return them as coderefs. If I is empty, extract functions from +the given I and return those. + +=item I + +Run the specified I and report the result. The I can be +coderefs or names of functions in the current package. If no I are +specified, functions that are named 'test_*' in the current package are +assumed to be the test functions. + +=back + +=cut + diff --git a/livejournal/var/.placeholder b/livejournal/var/.placeholder new file mode 100755 index 0000000..2895e7a --- /dev/null +++ b/livejournal/var/.placeholder @@ -0,0 +1 @@ +This file exists to make sure the directory is created. diff --git a/ljcom/.forward b/ljcom/.forward new file mode 100644 index 0000000..229feb0 --- /dev/null +++ b/ljcom/.forward @@ -0,0 +1 @@ +/home/lj/mail/ diff --git a/ljcom/README-ljcom.txt b/ljcom/README-ljcom.txt new file mode 100644 index 0000000..5869b5d --- /dev/null +++ b/ljcom/README-ljcom.txt @@ -0,0 +1,22 @@ +======== + NOTICE +======== + +The files in the "ljcom" CVS repository are not licensed under the GPL. + +These are site-local modifications which differentiate LiveJournal.com +from other livejournal(the code)-based sites. Everything here should +be pretty trivial and/or non-essential, but critical in making +LiveJournal "feel" different. + +We provide the source to these files so developers/integrators know +the proper ways to extend LiveJournal. (generally via hooks and extra +styles and *-local.* files) + +While we encourage you to learn from these files, you do not have +permission to use them in production sites. You may use them on +development servers such as goathack.livejournal.org. + +Any questions or comments may be sent to: + + Brad Fitzpatrick diff --git a/ljcom/bin/checkconfig-local.pl b/ljcom/bin/checkconfig-local.pl new file mode 100644 index 0000000..f048c74 --- /dev/null +++ b/ljcom/bin/checkconfig-local.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# + +my @errors; +my $err = sub { + return unless @_; + print STDERR "Problem:\n" . join('', map { " * $_\n" } @_) . "\n"; + exit 1; +}; + +############################################################################ +print "[Checking site-local config....]\n"; +############################################################################ + +my %modules = ( + "Crypt::Cracklib" => { 'deb' => 'libcrypt-cracklib-perl', + 'opt' => 'Provides checking of strong password.' }, + "GnuPG::Interface" => { 'deb' => 'libgnupg-interface-perl', + 'opt' => 'Crypto and signed message authentication.' }, + "Inline" => { 'deb' => 'libinline-perl', }, + "Crypt::SSLeay" => {'deb' => "libcrypt-ssleay-perl", }, + "Geo::IP::PurePerl" => { 'opt' => "Provides IP to country mapping for stopping some CC fraud.", }, + ); + +my @debs; + +foreach my $mod (sort keys %modules) { + my $rv = eval "use $mod;"; + if ($@) { + my $dt = $modules{$mod}; + if ($dt->{'opt'}) { + print STDERR "Missing optional module $mod: $dt->{'opt'}\n"; + } else { + push @errors, "Missing perl module: $mod"; + } + push @debs, $dt->{'deb'} if $dt->{'deb'}; + next; + } + my $ver_want = $modules{$mod}{ver}; + my $ver_got = $mod->VERSION; + if ($ver_want && $ver_got && $ver_got < $ver_want) { + push @errors, "Out of date module: $mod (need $ver_want, $ver_got installed)"; + } +} + +unless (-e "/usr/share/doc/aspell-en" || -e "/usr/local/share/aspell") { + push @errors, "Spell check dictionary not installed?"; + push @debs, "aspell-en"; +} + +unless (-d "$ENV{'LJHOME'}/temp") { + push @errors, "\$LJHOME/temp dir doesn't exist"; +} +unless (-d "$ENV{'LJHOME'}/var") { + push @errors, "\$LJHOME/var dir doesn't exist"; +} + +if (@debs && -e '/etc/debian_version') { + print STDERR "\n# apt-get install ", join(' ', @debs), "\n\n"; +} + +$err->(@errors); + +1; diff --git a/ljcom/bin/db b/ljcom/bin/db new file mode 100755 index 0000000..82f5e02 --- /dev/null +++ b/ljcom/bin/db @@ -0,0 +1,8 @@ +#!/bin/sh +# +# No dependencies. +# + +mysql -A livejournal + + diff --git a/ljcom/bin/fixtime b/ljcom/bin/fixtime new file mode 100755 index 0000000..f8078fc --- /dev/null +++ b/ljcom/bin/fixtime @@ -0,0 +1,10 @@ +#!/bin/sh +# +# +# prog: ntpdate +# + +/usr/sbin/ntpdate -s tick.nyc.pnap.net tock.pnap.net + + + diff --git a/ljcom/bin/hkill b/ljcom/bin/hkill new file mode 100755 index 0000000..8d0ed48 --- /dev/null +++ b/ljcom/bin/hkill @@ -0,0 +1,21 @@ +#!/usr/bin/perl +# +# +# prog: ps, grep +# + +use strict; + +my $prog = shift @ARGV; +exit unless ($prog =~ /^[\w\.\/]+$/); + +my @procs = `ps awx | grep $prog | grep -v grep | grep -v hkill`; +foreach (@procs) +{ + next unless (/^\s*(\d+)\s/); + my $pid = $1; + print $pid, "\n"; + kill 1, $pid; +} + + diff --git a/ljcom/bin/jmk.jar b/ljcom/bin/jmk.jar new file mode 100755 index 0000000000000000000000000000000000000000..8d8dbceb77741308ba9511e30ea73551d258e632 GIT binary patch literal 231020 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

    7*iSp0LDl^BjQQ<# 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

    ~GF%nHR_0BkgRrDGcjlzt`=* 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 literal 0 HcmV?d00001 diff --git a/ljcom/bin/ljcontrib.pl b/ljcom/bin/ljcontrib.pl new file mode 100755 index 0000000..718f2ad --- /dev/null +++ b/ljcom/bin/ljcontrib.pl @@ -0,0 +1,114 @@ +#!/usr/bin/perl +# -*-perl-*- +# vim:ts=4:sw=4:et +# +# Tool to add/ack contributions on a livejournal server +# +# Gavin Mogan +# +use strict; +use LWP::UserAgent; +use Digest::MD5 qw(md5_hex); +use Getopt::Long; +use URI::Escape; + +my $CONFFILE = "$ENV{'HOME'}/.ljcontrib.conf"; + +my ($opt_help, $opt_type, $opt_zilla, $opt_url, $opt_ack ); + +exit 1 unless GetOptions('help' => \$opt_help, + 'zilla|z=s' => \$opt_zilla, + 'url|u=s' => \$opt_url, + 'type|t=s' => \$opt_type, + 'ack|a' => \$opt_ack, + ); + +if ($opt_help || (@ARGV == 0)) { + print STDERR "Usage: ljcontrib.pl [opts] \n\n"; + print STDERR "Options:\n"; + print STDERR " --ack Ack a contribution\n"; + print STDERR " --zilla= [optional] What zilla bug is it for?\n"; + print STDERR " --url= [optional] Supply a url for contribution\n"; + print STDERR " --type= contrib type: code/doc/creative/biz/other\n"; + exit 1; +} + +unless (-s $CONFFILE) { + open (C, ">>$CONFFILE"); close C; chmod 0700, $CONFFILE; + print "\nNo ~/.ljcontrib.conf config file found.\nFormat:\n\n"; + print "server: www.livejournal.com\n"; + print "username: test\n"; + print "password: test\n"; + exit 1; +} + +my %conf; +open (C, $CONFFILE); +while () { + next if /^\#/; + next unless /\S/; + chomp; + next unless /^(\w+)\s*:\s*(.+)/; + $conf{$1} = $2; +} +close C; +my $commands; + +if ($opt_ack) { + die "No ack #\n" unless @ARGV; + my $ackno = $ARGV[0]; + $commands = "command=" . uri_escape("contrib ack $ackno"); +} else { + die "URL and Zilla are mutually exclusive\n" if ($opt_url && $opt_zilla); + + if ($opt_type ne "code" && $opt_type ne "doc" && $opt_type ne "creative" && + $opt_type ne "biz" && $opt_type ne "other") + { + $opt_type = "other"; # default to other + } + + die "No user for ack\n" unless @ARGV; + my $user = $ARGV[0]; + + die "No description given\n" unless @ARGV == 2; + my $desc = $ARGV[1]; + + my $url = " "; + + $url .= $opt_url if ($opt_url); + $url .= " http://zilla.livejournal.org/show_bug.cgi?id=$opt_zilla" if ($opt_zilla); + + $commands = "command=" . uri_escape("contrib add $user $opt_type \"$desc\"$url"); +} + + +# Create a request +my $ua = LWP::UserAgent->new; +$ua->agent("Gavin_Contrib/0.1"); +my $req = HTTP::Request->new('POST',"http://$conf{'server'}/interface/flat"); +$req->content_type('application/x-www-form-urlencoded'); +my $user = "user=" . uri_escape($conf{'username'}); +my $pass = "hpassword=" . uri_escape(md5_hex($conf{'password'})); +my $mode = "mode=consolecommand"; +my $clientversion = "clientversion=moocow/0.1"; +my $data = join('&', $user,$pass,$mode,$commands, $clientversion); + +$req->content($data); + +my $res = $ua->request($req); + +if ($res->is_error) { + die "Error posting to LJ server: " . $res->message . "\n"; +} +my %ljres = split(/\n/, $res->content); + +if ($ljres{'success'} ne "OK") { + die "Error: " . $ljres{'errmsg'} . "\n"; +} + +if ($ljres{'cmd_line_1_type'} eq "error") { + die "Error: " . $ljres{'cmd_line_1'} . "\n"; +} + +print "SUCCESS: contribution added.\n" unless ($opt_ack); +print "SUCCESS: contribution acked.\n" if ($opt_ack); diff --git a/ljcom/bin/ljrpc b/ljcom/bin/ljrpc new file mode 100755 index 0000000..cc7c99b --- /dev/null +++ b/ljcom/bin/ljrpc @@ -0,0 +1,164 @@ +#!/usr/bin/perl -w +# +# LiveJournal Remote Procedure Call Client (ljrpc) +# Copyright 2001 Dormando (dormando@rydia.net) +# Going to add a license (GPL?) later. +# +# +# This client runs commands you give it at the prompt through the RPC +# system. By default, first it sends out a 'ping', then sends the +# command to any machine that replies to it. Prints out replies it +# gets, too. It can also be invoked with --now, in which case it +# broadcasts the command and exits immediately. +# +# +# lib: IO::Socket, Getopt::Long +# + +use strict; +use IO::Socket; +use Getopt::Long; +use constant SEC_SLAVE_WAIT => 4; +use lib "$ENV{'LJHOME'}/cgi-bin"; +require "ljconfig.pl"; + +$SIG{CHLD} = 'IGNORE'; + +my $MAXLEN = 512; +my $PORTNO = 6100; + +if ($LJ::BCAST_ADDR) { } # shutup warning +my $bcastaddr = $LJ::BCAST_ADDR || '10.0.0.255'; + +my ($cmdmsg, $remhost, @hosts); + +### option processing +my $timeout = 0; +my $quick = 0; +my $server = "web"; +my $ping = 0; +my $delay = 0; +my $serialized = 0; + +exit 1 unless +GetOptions('timeout=i' => \$timeout, + 'now' => \$quick, + 'server=s' => \$server, + 'ping' => \$ping, + 'serialized|s' => \$serialized, + 'dest=s' => \$bcastaddr, + 'delay|d=i' => \$delay, + ); + +my $msg = "@ARGV"; +$msg = "cmd: " . $msg; + +# Creat socket. Shoot the broadcast off. +my $sock = IO::Socket::INET->new(Proto => 'udp') or die "Creating socket: $!\n"; +$sock->sockopt(SO_BROADCAST, 1); + +my $ipaddr = inet_aton($bcastaddr); +my $portaddr = sockaddr_in($PORTNO, $ipaddr); +print STDERR "Broadcasting.\n"; +if ($quick) { + $sock->send($msg, 0, $portaddr) or die "send: $!\n"; + exit 0; +} else { + $sock->send("marco $server", 0, $portaddr) or die "send: $!\n"; +} + +my $count = 0; +$| = 1; + +# First loop, grabs machines that are up. + +my %mark; +if ($server eq "web") { + open (O, "$ENV{LJHOME}/cgi-bin/pool_int_web.txt"); + while () { + chomp; + $mark{$_} = 1; + } + close O; +} + +eval { + local $SIG{ALRM} = sub { die "timeout" }; + alarm(SEC_SLAVE_WAIT); + while ($sock->recv($cmdmsg, $MAXLEN)) { + my ($port, $ipaddr) = sockaddr_in($sock->peername); + $remhost = gethostbyaddr($ipaddr, AF_INET) || ""; + my $remip = inet_ntoa($ipaddr); + if ($cmdmsg eq "pollo") { + alarm(SEC_SLAVE_WAIT); + $count++; + print "$count: $remhost [$remip]\n"; + delete $mark{$remip}; + push(@hosts, $remhost); + } + } + alarm(0); +}; + +print "\n"; + +if ($ping) { + print "Unreported int_web nodes:\n" if %mark; + foreach (keys %mark) { + print " $_\n"; + } + exit; +} + +if ($serialized) { + foreach my $host (@hosts) { + printf "Sending: %-30s", "$host ..."; + my $ipaddr = inet_aton($host); + my $portaddr = sockaddr_in($PORTNO, $ipaddr); + if ($sock->send($msg, 0, $portaddr)) { + print "sent.\n"; + } else { + print "failed.\n"; + } + + if ($delay) { + sleep $delay; + } else { + $sock->recv($cmdmsg, $MAXLEN); + my ($port, $remipaddr) = sockaddr_in($sock->peername); + $remhost = gethostbyaddr($remipaddr, AF_INET); + + print "Server $remhost:\n===============================\n"; + print $cmdmsg; + print "\n\n"; + } + } + + exit; +} + +foreach my $host (@hosts) { + printf "Sending: %-30s", "$host ..."; + my $ipaddr = inet_aton($host); + my $portaddr = sockaddr_in($PORTNO, $ipaddr); + if ($sock->send($msg, 0, $portaddr)) { + print "sent.\n"; + } else { + print "failed.\n"; + } + sleep $timeout; +} + +print "\n\n"; + +# Loop receiving command stuffs. +for (my $i = 0; $i < @hosts; $i++) { + $sock->recv($cmdmsg, $MAXLEN); + my ($port, $ipaddr) = sockaddr_in($sock->peername); + $remhost = gethostbyaddr($ipaddr, AF_INET); + + # Parse thing. + print "Server $remhost:\n===============================\n"; + print $cmdmsg; + print "\n\n"; +} diff --git a/ljcom/bin/ljrpcd b/ljcom/bin/ljrpcd new file mode 100755 index 0000000..905acae --- /dev/null +++ b/ljcom/bin/ljrpcd @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w +# LiveJournal Remote Procedure Call Daemon (ljrpcd) +# Copyright 2001 Dormando (dormando@rydia.net) +# Going add a license (GPL?) later. +# This daemon forks off into the background, logs if told to +# waits for UDP messages on the given port, and executes +# commands sent to it. +# +# +# lib: IO::Socket +# prog: bin/ljmaint.pl +# + +use strict; +use IO::Socket; + +# Max message length and port to bind. +my $MAXLEN = 512; +my $PORTNO = 6100; +my $PIDFILE = '/var/run/ljrpcd.pid'; +my $LOGFILE = '/var/log/ljrpcd.log'; +my $TYPE = shift @ARGV; + +unless ($TYPE eq "web" || $TYPE eq "db") { + print "Unknown/unspecified machine type, quitting.\n"; + exit 1; +} + +# Pid and pidfile. +my $pid; +my $is_parent = 1; +# Socket. Needs to be here for the HUP stuff. +my $sock; + +# In case we're shot, unlink the pidfile. +$SIG{TERM} = sub { + unlink($PIDFILE); + exit 1; +}; + +if (-e $PIDFILE) { + open (PID, $PIDFILE); + my $tpid; + chomp ($tpid = ); + close PID; + + if ($tpid) { + # so Linux-specific, but Proc::ProcessTable + #iterates over /dev forever, which sucks on a NetApp + if (open (CMD, "/proc/$tpid/cmdline")) { + my $cmdline = ; + close CMD; + if ($cmdline =~ /ljrpcd/) { + print "Process exists already, quitting.\n"; + exit 1; + } + } + } +} + +# Print a banner. +print "LiveJournal RPC Daemon starting up into the background...\n"; + +# Perhaps I should give it a command to not do this in the future. +if ($pid = fork) { + # Parent, log pid and exit. + open(PID, ">$PIDFILE") or die "Couldn't open $PIDFILE for writing: $!\n"; + print PID $pid; + close(PID); + print "Closing ($pid) wrote to $PIDFILE\n"; + $is_parent = 1; + exit; +} else { + # This is the child, main loop-de-doo. + my($cmdmsg, $remaddr, $remhost); + + # HUP signal handler. + $SIG{HUP} = \&restart_request; + + open(LOG, ">>$LOGFILE") or die "Couldn't open log file for appending: $!\n"; + flock(LOG, 2) or die "Couldn't flock log file for writing: $!\n"; + select(LOG); # Why the hell not, eh? + $| = 1; + + $sock = IO::Socket::INET->new(LocalPort => "$PORTNO", Proto => 'udp') or die "socket: $@"; + $sock->sockopt(SO_BROADCAST, 1); + print "Bound, awaiting UDP commands on port $PORTNO\n"; + + # Main loop, simple parser. + while ($sock->recv($cmdmsg, $MAXLEN)) { + my ($port, $ipaddr) = sockaddr_in($sock->peername); + my $ip_addy = inet_ntoa($ipaddr); + + $remhost = gethostbyaddr($ipaddr, AF_INET); + print "Client $remhost sent command: $cmdmsg\n"; + + # If the command is 'marco' return 'pollo' + if ($cmdmsg =~ /^marco(\s+($TYPE|all))?$/) { + print "Returning 'pollo' to client $remhost\n"; + $sock->send("pollo") or print "Couldn't scream pollo at $remhost\n"; + next; + } elsif ($cmdmsg =~ s/^cmd:\s//) { + # Handle the command. + if ($cmdmsg eq "restart") { + print "Restarting ljrpcd\n"; + $sock->send("Restarting ljrpcd...\n"); + restart_request(); + } + my $return = handle_request($cmdmsg); + print "Returning $return to client $remhost\n"; + $sock->send($return) or print "Couldn't return $return to $remhost\n"; + next; + } + } + die "recv: $!\n"; +} #if + +# Sub to restart the daemon. +sub restart_request { + $sock->close; + unlink($PIDFILE); + exec($0, $TYPE); +} + + +# Handle a request... Do further parsing, pass it appropriately. +# Should return a discernable ok. Usually 'done' 'ok' or an +# informative reply no longer than 500 characters. +sub handle_request { + my $cmd = shift; + my $su = ""; + if ($cmd =~ s/^(\w+?)://) { + my $user = $1; + my ($login,$pass,$uid,$gid) = getpwnam($user) + or return "$user not in passwd file."; + $su = "su $user -c"; + } + unless ($cmd =~ /[\|\>\<]/) { + my $home = $ENV{'LJHOME'} || "/home/lj"; + $cmd =~ s/[;]/\\$&/; + if ($su) { + return `$su \'$home/bin/ljmaint.pl $cmd\'`; + } else { + return `$home/bin/ljmaint.pl $cmd`; + } + } + + return 'bad command'; +} diff --git a/ljcom/bin/ljstatscasterd b/ljcom/bin/ljstatscasterd new file mode 100755 index 0000000..f0136ec --- /dev/null +++ b/ljcom/bin/ljstatscasterd @@ -0,0 +1,167 @@ +#!/usr/bin/perl + +use strict; +use Getopt::Long; +use IO::Socket::INET; +use IO::Select; +use Time::HiRes qw(time ualarm); +use POSIX (); + +my $opt_pidfile; +my $opt_stop; +my $opt_foreground; + +exit 1 unless GetOptions('pidfile=s' => \$opt_pidfile, + 'stop' => \$opt_stop, + 'foreground' => \$opt_foreground, + ); + +$opt_pidfile ||= "/var/run/ljstatscasterd.pid"; + +$SIG{TERM} = sub { + unlink($opt_pidfile); + exit 1; +}; + +my $pid; +if (-e $opt_pidfile) { + open (PID, $opt_pidfile); + chomp ($pid = ); + close PID; + if ($pid) { + if ($opt_stop) { + kill 15, $pid; + print "Stopped.\n"; + exit; + } + if (kill(0,$pid)) { + die "Already running as pid: $pid\n"; + } + } +} + +if ($opt_stop) { + print "already stopped.\n"; + exit; +} + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my ($host, $port, $ipaddr, $portaddr, $sock); +my $TIMEOUT = 1.0; # transmit at least every 1 sec. + +if ($LJ::FREECHILDREN_BCAST && + $LJ::FREECHILDREN_BCAST =~ /^(\S+):(\d+)$/) { + ($host, $port) = ($1, $2); +} else { + die "\$LJ::FREECHILDREN_BCAST not defined, nowhere to send"; +} + +die "Can't write to $opt_pidfile" unless open(PID, ">>$opt_pidfile"); +close PID; + +unless ($opt_foreground) { + fork && exit 0; + POSIX::setsid() or die "Couldn't become session leader: $!"; + fork && exit 0; +} + +# Parent, log pid and exit. +unless (open(PID, ">$opt_pidfile")) { + die "Couldn't open $opt_pidfile for writing: $!\n"; +} +print PID $$; +close(PID); +print "Started with pid $$\n"; + +unless ($opt_foreground) { + # Change working dir to the filesystem root, clear the umask + chdir "/"; + umask 0; + + # Close standard file descriptors and reopen them to /dev/null + close STDIN && open STDIN, "&STDIN"; + close STDERR && open STDERR, "+>&STDIN"; +} + +$sock = IO::Socket::INET->new(Proto => 'udp'); +$sock->sockopt(SO_BROADCAST, 1); +$ipaddr = inet_aton($host); +$portaddr = sockaddr_in($port, $ipaddr); + +my $insock = IO::Socket::INET->new(Proto=>'udp', + LocalAddr=>"127.0.0.1:$port"); + or die "couldn't create socket\n"; +$insock->blocking(0); + +my $sel = IO::Select->new(); +$sel->add($insock); + +my ($buf, $last_message); +my $no_servers = 1; # true if there are no servers available +my $last_send; +my $last_free; + + +my ($type, $message); + +sub transmit { + #print "transmitting...\n"; + $sock->send($last_message, 0, $portaddr) + if $last_message; +} + +my $MAXLEN = 512; +SEL: +while(1) { + my @ready = $sel->can_read($TIMEOUT); + unless (@ready) { + # we got here via a timeout. check to make sure apache-perl + # is still running before actually deciding to transmit more + open (PID, "/var/run/apache-perl.pid") or next; # debian-specific + my $pid = ; + chomp $pid; + close PID; + if (readlink("/proc/$pid/exe") =~ /apache/) { + transmit(); + } + next SEL; + } + + # assume we shouldn't transmit, until we've decided we should + my $transmit = 0; + + # only one handle selected, so we know it's the incoming UDP + my $message; + while ($sock->recv($message, $MAXLEN)) { + $last_message = $message if $message; + } + $message = $last_message; + + $message =~ m!free=(\d+)\n!; + my $free = $1; + next SEL if $free == $last_free; + + $now = time(); + + if (defined $free && $now > $last_send + 0.2) { + $transmit = 1; + } elsif (defined $free) { + my $new_no_servers = ($free == 0); + if ($no_servers != $new_no_servers) { + $transmit = 1; + $no_servers = $new_no_servers; + } + } elsif ($message =~ m!shutdown=1!) { + $transmit = 1; + } + + if ($transmit) { + $last_send = $now; + $last_free = $free; + transmit(); + } + +} + diff --git a/ljcom/bin/machine_config.pl b/ljcom/bin/machine_config.pl new file mode 100755 index 0000000..2b8d80b --- /dev/null +++ b/ljcom/bin/machine_config.pl @@ -0,0 +1,662 @@ +#!/usr/bin/perl +# +# +# lib: Sys::Hostname, Getopt::Long, Fcntl::, POSIX:: +# + +use strict; +use Sys::Hostname; +use Getopt::Long; +use Fcntl; +use POSIX qw(tmpnam); + +my %DEFAULT = ( + 'search' => 'lj', + 'ns1' => '10.2.0.1', + ); + +my %MACHINE = ( + "stan" => { + 'ipco' => '10.0.0.3', + 'do_web' => 1, + 'web_slave' => 1, + 'paid_web_slave' => 1, + }, + "kyle" => { + 'ipco' => '10.0.0.4', + 'do_web' => 1, + 'web_slave' => 1, + 'web_master' => 1, + }, + "wendy" => { + 'ipco' => '10.0.0.5', + 'do_web' => 1, + 'web_slave' => 1, + }, + "bebe" => { + 'ipco' => '10.0.0.6', + 'do_web' => 1, + 'web_slave' => 1, + }, + "terrance" => { + 'ipco' => '10.0.0.7', + 'do_web' => 1, + 'web_slave' => 1, + }, + "phillip" => { + 'ipco' => '10.0.0.8', + 'do_web' => 1, + 'web_slave' => 1, + 'paid_web_slave' => 1, + }, + "ike" => { + 'ipco' => '10.0.0.11', + 'do_web' => 1, + 'web_slave' => 1, + }, + "pip" => { + 'ipco' => '10.0.0.12', + 'do_web' => 1, + 'web_slave' => 1, + }, + "kenny" => { + 'ipco' => '10.0.0.1', + 'db_slave' => 1, + }, + "cartman" => { + 'ipco' => '10.0.0.2', + 'db_master' => 1, + }, + "mackey" => { + 'ipco' => '10.0.0.9', + 'db_slave' => 1, + }, + "hat" => { + 'ipco' => '10.0.0.10', + 'db_slave' => 1, + }, + "marklar" => { + 'ip' => '216.231.32.128', + 'ipco' => '10.0.0.15', + 'db_slave' => 1, + }, + ); + +my $machine = hostname(); +unless ($machine =~ /^lj-(\w+)(\.livejournal\.com)?$/) { + die "Weird hostname.\n"; +} +$machine = $1; + +my $DRY = 0; +my $HELP = 0; +exit 1 unless GetOptions( + 'dryrun|n' => \$DRY, + 'help' => \$HELP, + ); + +if ($HELP || ! defined $MACHINE{$machine}) { + die("Usage: machine_config.pl [opts]\n\nWhere opts can be:\n". + "--dryrun -n Don't change any config files; just show changes.\n". + "--help -h This message.\n"); +} + +my $host = { %DEFAULT }; +$host->{'name'} = $machine; +foreach (keys %{$MACHINE{$machine}}) { + $host->{$_} = $MACHINE{$machine}->{$_}; +} + +print "Host information: ($host->{'name'})\n"; +foreach (sort keys %{$host}) { + printf " %10s : %s\n", $_, $host->{$_}; +} + +setup_resolve_conf($host); +setup_hosts($host); +setup_httpd($host) if ($host->{'do_web'}); + +##################### + +sub write_file +{ + my $file = shift; + my $new = shift; + my $old; + + open (IN, $file); + while () { + $old .= $_; + } + close IN; + + if ($new ne $old) { + if ($DRY) { + my $tmp = tmpnam(); + die "temp file exists!\n" if (-e $tmp); + print "$file needs updating!\n"; + open (OUT, ">$tmp"); + print OUT $new; + close OUT; + print `diff -u $file $tmp`; + unlink $tmp; + } else { + print "Updating: $file\n"; + open (OUT, ">$file"); + print OUT $new; + close OUT; + } + } +} + +sub setup_resolve_conf +{ + my $host = shift; + my $file = "/etc/resolv.conf"; + my $new; + + if (exists($host->{'search'})) { + $new .= "search\t$host->{'search'}\n"; + } + + foreach my $ns (qw(ns1)) { + next unless ($host->{$ns}); + $new .= "nameserver\t$host->{$ns}\n"; + } + + write_file($file, $new); +} + +# NOTE: this used to do a lot more, before we had DNS running +# internally. +sub setup_hosts +{ + my $host = shift; + my $file = "/etc/hosts"; + my $new; + + $new .= "127.0.0.1\tlocalhost\n"; + write_file($file, $new); +} + +sub setup_httpd +{ + my $host = shift; + my $file = "/usr/local/apache/conf/httpd.conf"; + my $new; + + $new .= <<"END_CONF"; +ServerType standalone +ServerRoot "/usr/local/apache" +PidFile /usr/local/apache/logs/httpd.pid +ScoreBoardFile /usr/local/apache/logs/httpd.scoreboard +Timeout 30 + +## keep-alive +KeepAlive Off +MaxKeepAliveRequests 200 +KeepAliveTimeout 50 + +MinSpareServers 15 +MaxSpareServers 40 +StartServers 170 +MaxClients 255 +MaxRequestsPerChild 0 + + +# Dynamic Shared Object (DSO) Support +# Note: The order is which modules are loaded is important. Don't change +# the order below without expert advice. + +LoadModule vhost_alias_module libexec/mod_vhost_alias.so +LoadModule env_module libexec/mod_env.so +LoadModule config_log_module libexec/mod_log_config.so +#LoadModule mime_magic_module libexec/mod_mime_magic.so +LoadModule mime_module libexec/mod_mime.so +#LoadModule negotiation_module libexec/mod_negotiation.so +LoadModule status_module libexec/mod_status.so +LoadModule info_module libexec/mod_info.so +LoadModule includes_module libexec/mod_include.so +LoadModule autoindex_module libexec/mod_autoindex.so +LoadModule dir_module libexec/mod_dir.so +LoadModule cgi_module libexec/mod_cgi.so +#LoadModule asis_module libexec/mod_asis.so +#LoadModule imap_module libexec/mod_imap.so +LoadModule action_module libexec/mod_actions.so +#LoadModule speling_module libexec/mod_speling.so +#LoadModule userdir_module libexec/mod_userdir.so +LoadModule alias_module libexec/mod_alias.so +LoadModule rewrite_module libexec/mod_rewrite.so +LoadModule access_module libexec/mod_access.so +LoadModule auth_module libexec/mod_auth.so +#LoadModule anon_auth_module libexec/mod_auth_anon.so +#LoadModule dbm_auth_module libexec/mod_auth_dbm.so +#LoadModule digest_module libexec/mod_digest.so +#LoadModule proxy_module libexec/libproxy.so +#LoadModule cern_meta_module libexec/mod_cern_meta.so +LoadModule expires_module libexec/mod_expires.so +#LoadModule headers_module libexec/mod_headers.so +LoadModule usertrack_module libexec/mod_usertrack.so +LoadModule unique_id_module libexec/mod_unique_id.so +LoadModule setenvif_module libexec/mod_setenvif.so +LoadModule fastcgi_module libexec/mod_fastcgi.so +#LoadModule php4_module libexec/libphp4.so + +# Reconstruction of the complete module list from all available modules +# (static and shared ones) to achieve correct module execution order. +# [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO] +ClearModuleList +AddModule mod_vhost_alias.c +AddModule mod_env.c +AddModule mod_log_config.c +#AddModule mod_mime_magic.c +AddModule mod_mime.c +#AddModule mod_negotiation.c +AddModule mod_status.c +AddModule mod_info.c +AddModule mod_include.c +AddModule mod_autoindex.c +AddModule mod_dir.c +AddModule mod_cgi.c +#AddModule mod_asis.c +#AddModule mod_imap.c +AddModule mod_actions.c +#AddModule mod_speling.c +#AddModule mod_userdir.c +AddModule mod_alias.c +AddModule mod_rewrite.c +AddModule mod_access.c +AddModule mod_auth.c +#AddModule mod_auth_anon.c +#AddModule mod_auth_dbm.c +#AddModule mod_digest.c +#AddModule mod_proxy.c +#AddModule mod_cern_meta.c +AddModule mod_expires.c +#AddModule mod_headers.c +AddModule mod_usertrack.c +AddModule mod_unique_id.c +AddModule mod_so.c +AddModule mod_setenvif.c +AddModule mod_fastcgi.c +#AddModule mod_php4.c + +ExtendedStatus On +Port 80 +END_CONF + + if ($host->{'ip'} && ! $host->{'web_slave'}) { + $new .= "Listen $host->{'ip'}:80\n"; + } + + $new .= <<"END_CONF"; +Listen $host->{'ipco'}:80 + +User lj +Group lj + +ServerAdmin webmaster\@livejournal.com +ServerName lj-$host->{'name'}.livejournal.com + +DocumentRoot "/usr/local/apache/htdocs" + + + SetHandler server-status + Order deny,allow + Deny from all + Allow from 10.0 66.31.142.7 + + + + DirectoryIndex index.html index.bml + + + Options Indexes FollowSymLinks ExecCGI +#for speed, instead of "All" + AllowOverride None + + Order allow,deny + Allow from all + + +SendBufferSize 131072 + +####################################### +END_CONF + if ($host->{'ip'} && ! $host->{'web_slave'}) { + $new .= "NameVirtualHost $host->{'ip'}:80\n"; + } + + $new .= <<"END_CONF"; +NameVirtualHost $host->{'ipco'}:80 + +FastCgiSuexec Off +FastCgiConfig -maxClassProcesses 10 -startDelay 1 -idle-timeout 20 + +END_CONF + + if ($host->{'web_master'}) { + $new .= <<"END_CONF"; + +# site's down message. +Listen 10.0.0.4:81 +NameVirtualHost 10.0.0.4:81 + + SetEnv LJHOME /home/lj + FastCgiServer /home/lj/sites/sitedown/index.cgi -processes 1 + ServerName livejournal.com + ServerAlias *.livejournal.com + DocumentRoot /home/lj/sites/sitedown/ + DirectoryIndex index.cgi + ErrorDocument 404 /index.cgi + + SetHandler fastcgi-script + + + +### mrtg.livejournal.com +Listen 10.0.0.4:88 +NameVirtualHost 10.0.0.4:88 + + SetEnv LJHOME /home/lj + ServerName mrtg.livejournal.com + ServerAlias mrtg.livejournal.com + + ServerAdmin webmaster\@livejournal.com + DocumentRoot /home/lj/sites/mrtg/ + DirectoryIndex index.cgi + AddHandler cgi-script .cgi + Options -Indexes +ExecCGI + + # Putting netsaint's aliases here for now. + Alias /netsaint/ /usr/local/netsaint/share/ + ScriptAlias /cgi-bin/netsaint/ /usr/local/netsaint/sbin/ + + ErrorLog /dev/null + TransferLog /dev/null + + +END_CONF + + } + + $new .= " {'ip'} && $host->{'web_master'}) { + $new .= " $host->{'ip'}:80"; + } + $new .= " $host->{'ipco'}:80>\n"; + $new .=" SetEnv LJHOME /home/lj\n"; + { + my %fcgi = ('/home/lj/htdocs/users' => 10, + '/home/lj/cgi-bin/log.cgi' => 4, + '/home/lj/cgi-bin/404notfound.cgi' => 1, + '/home/lj/htdocs/customview.cgi' => 4, + '/home/lj/cgi-bin/bmlp.pl' => 7, + '/home/lj/cgi-bin/sbmlp.pl' => 3, + '/home/lj/htdocs/userpic' => 1); + + if ($host->{'name'} eq "kenny") { + $fcgi{'/home/lj/htdocs/users'} = 5; + $fcgi{'/home/lj/htdocs/customview.cgi'} = 2; + $fcgi{'/home/lj/cgi-bin/bmlp.pl'} = 4; + $fcgi{'/home/lj/cgi-bin/sbmlp.pl'} = 2; + $fcgi{'/home/lj/cgi-bin/log.cgi'} = 2; + } + foreach my $app (sort keys %fcgi) + { + $new .= " FastCgiServer $app -processes $fcgi{$app} -initial-env LJHOME=/home/lj\n"; + } + } + + ########## rewrite stuff. no interpolation. + $new .= <<'END_CONF'; + RewriteEngine on + RewriteLog /home/lj/logs/rewrite.log + RewriteLogLevel 0 + + RewriteCond %{HTTP_HOST} ^(www\.)?livejournal\.com$ [NC] + RewriteRule ^/~([a-z0-9_]+)(/?.*)$ /users/$1$2 [L,PT,NS] + + RewriteCond %{REQUEST_URI} !\.bml + RewriteRule ^/community/([a-z0-9_]+)(/?.*)$ /users/$1$2 [L,PT,NS] + + RewriteCond %{HTTP_HOST} ^([a-z0-9_\-]+)\.livejournal\.com$ [NC] + RewriteCond %1 !^www$ [NC] + RewriteRule ^(.+) %{HTTP_HOST}$1 [C] + RewriteRule ^([a-z0-9_\-]+)\.livejournal\.com(.+) /users/$1$2 [L,PT,NS] + + RewriteCond %{HTTP_HOST} ^(www\.)?livejournal\.com$ [NC] + RewriteRule ^/confirm/([a-z0-9]+\.[a-z0-9]+) http://www.livejournal.com/register.bml?$1 [L,R] + + # if they send any Host header with letters (an IP address or blank + # is okay) then it has to be www.livejournal.com or livejournal.com + # (optional port, too) + RewriteCond %{HTTP_HOST} [a-z] [NC] + RewriteCond %{HTTP_HOST} !^(www\.)?livejournal\.com(:[0-9]+)?$ [NC] + RewriteRule . . [F] + +END_CONF + + $new .= <<"END_CONF"; + + AddType text/rdf rdf + AddType text/plain TCL + AddType application/x-httpd-cgi CGI + + Options +ExecCGI + + ServerName lj-$host->{'name'}.livejournal.com + ServerAlias livejournal.com *.livejournal.com + ServerAdmin webmaster\@livejournal.com + DocumentRoot /home/lj/htdocs/ + ScriptAlias /cgi-bin/ /home/lj/cgi-bin/ + + ErrorDocument 403 /403.html +END_CONF + + if ($host->{'paid_web_slave'}) { + $new .= " ErrorDocument 500 /500-paid.html\n"; + } else { + $new .= " ErrorDocument 500 /500.html\n"; + } + + $new .= <<"END_CONF"; + ErrorDocument 404 /cgi-bin/404notfound.cgi +# RedirectMatch 301 ^/users/?\$ http://www.livejournal.com/directory.bml + + AddType text/bml BML + Action text/bml /cgi-bin/bmlp.pl + AddType text/sbml SBML + Action text/sbml /cgi-bin/sbmlp.pl + DirectoryIndex index.html index.bml + + SetEnvIf Request_URI "^/img/" no-log + SetEnvIf Request_URI "^/userpic/" no-log + SetEnvIf Request_URI "^/status" no-log + LogFormat "%h %l %u %t \\"%r\\" %s %b \\"%{Referer}i\\" \\"%{User-Agent}i\\" \\"%{Host}i\\"" ljlog + ErrorLog "|/usr/local/apache/bin/rotatelogs /home/lj/logs/error-$host->{'name'} 3600" + CustomLog "|/usr/local/apache/bin/rotatelogs /home/lj/logs/access-$host->{'name'} 3600" ljlog env=!no-log + + + SetHandler fastcgi-script + + + SetHandler fastcgi-script + + + SetHandler fastcgi-script + + + ErrorDocument 500 /500-log.html + SetHandler fastcgi-script + + + SetHandler fastcgi-script + + + SetHandler fastcgi-script + + + SetHandler fastcgi-script + + + AllowOverride None + Options None + ExpiresActive on + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + + + + Deny from all + + + + Deny from all + + + + AuthUserFile /home/lj/pass-gen.txt + AuthName "Brad only area" + AuthType Basic + require user bradfitz + Options +Indexes + + + + Options -ExecCGI + + + + +# backup image server (load balancer will prefer thttpd/tux/etc first) +Listen $host->{'ipco'}:8081 +NameVirtualHost $host->{'ipco'}:8081 +{'ipco'}:8081> + ServerName img.livejournal.com + DocumentRoot /home/lj/htdocs/img + DirectoryIndex index.html + Options -ExecCGI + + +# AccessFileName: The name of the file to look for in each directory +# for access control information. +# +AccessFileName .htaccess + + + Order allow,deny + Deny from all + + + Order allow,deny + Deny from all + + + Order allow,deny + Deny from all + + +UseCanonicalName Off + + + TypesConfig /usr/local/apache/conf/mime.types + + +## MIME +DefaultType text/plain + + MIMEMagicFile /usr/local/apache/conf/magic + + +HostnameLookups Off + +ErrorLog "|/usr/local/apache/bin/rotatelogs /usr/local/apache/logs/error_log 86400" +LogLevel error +CustomLog /dev/null common + +ServerSignature On + + + Alias /icons/ "/usr/local/apache/icons/" + + Options Indexes + AllowOverride None + Order allow,deny + Allow from all + + + + + + # + # FancyIndexing is whether you want fancy directory indexing or standard + # + IndexOptions FancyIndexing SuppressDescription SuppressColumnSorting FoldersFirst NameWidth=* + + # + # AddIcon* directives tell the server which icon to show for different + # files or filename extensions. These are only displayed for + # FancyIndexed directories. + # + AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + + AddIconByType (TXT,/icons/text.gif) text/* + AddIconByType (IMG,/icons/image2.gif) image/* + AddIconByType (SND,/icons/sound2.gif) audio/* + AddIconByType (VID,/icons/movie.gif) video/* + + AddIcon /icons/rpm.gif .rpm + AddIcon /icons/debian.gif .deb + AddIcon /icons/binary.gif .bin .exe + AddIcon /icons/binhex.gif .hqx + AddIcon /icons/tar.gif .tar + AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv + AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip + AddIcon /icons/a.gif .ps .ai .eps + AddIcon /icons/layout.gif .html .shtml .htm .pdf + AddIcon /icons/text.gif .txt + AddIcon /icons/c.gif .c + AddIcon /icons/p.gif .pl .py + AddIcon /icons/f.gif .for + AddIcon /icons/dvi.gif .dvi + AddIcon /icons/uuencoded.gif .uu + AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl + AddIcon /icons/tex.gif .tex + AddIcon /icons/bomb.gif core + + AddIcon /icons/back.gif .. + AddIcon /icons/hand.right.gif README + AddIcon /icons/folder.gif ^^DIRECTORY^^ + AddIcon /icons/blank.gif ^^BLANKICON^^ + + # + # DefaultIcon is which icon to show for files which do not have an icon + # explicitly set. + # + DefaultIcon /icons/unknown.gif + ReadmeName README + HeaderName HEADER + IndexIgnore .??* *~ *# HEADER* RCS CVS *,v *,t + + + + AddEncoding x-compress Z + AddEncoding x-gzip gz tgz + AddType application/x-httpd-php .php + AddType application/x-httpd-php-source .phps + AddType application/x-tar .tgz + + + + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 + + +END_CONF + + write_file($file, $new); +} diff --git a/ljcom/bin/maint/aliases.pl b/ljcom/bin/maint/aliases.pl new file mode 100644 index 0000000..f2755d3 --- /dev/null +++ b/ljcom/bin/maint/aliases.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl +# + +$maint{'makealiases'} = sub +{ + my $dbh = LJ::get_dbh("master"); + foreach (keys %LJ::FIXED_ALIAS) { + $dbh->do("REPLACE INTO email_aliases (alias, rcpt) VALUES (?,?)", + undef, "$_\@$LJ::USER_DOMAIN", $LJ::FIXED_ALIAS{$_}); + } +}; + +1; diff --git a/ljcom/bin/maint/clean_caches-local.pl b/ljcom/bin/maint/clean_caches-local.pl new file mode 100644 index 0000000..e485952 --- /dev/null +++ b/ljcom/bin/maint/clean_caches-local.pl @@ -0,0 +1,14 @@ +#!/usr/bin/perl +# + +$maint{'clean_caches_local'} = sub +{ + my $dbh = LJ::get_db_writer(); + + my $verbose = $LJ::LJMAINT_VERBOSE; + + print "-I- Cleaning authactions.\n"; + $dbh->do("DELETE FROM authactions WHERE datecreate < DATE_SUB(NOW(), INTERVAL 30 DAY)"); +}; + +1; diff --git a/ljcom/bin/maint/dirsync.pl b/ljcom/bin/maint/dirsync.pl new file mode 100644 index 0000000..1bc00c4 --- /dev/null +++ b/ljcom/bin/maint/dirsync.pl @@ -0,0 +1,80 @@ +#!/usr/bin/perl +# + +$maint{'dirsync'} = sub +{ + use File::Copy; + + my $FROMBASE = "/home/devftp"; + my $TOBASE = "/home/lj/htdocs"; + my $REWRITE_PERIOD = 3600*2; # for 2 hours, ftp area files can overwrite masters + my $VERBOSE = 0; + + print "-I- Connecting to db.\n" if ($VERBOSE); + + my $dbr = LJ::get_db_reader(); + + print "-I- Fetching users with devftp privs.\n" if ($VERBOSE); + my $sth = $dbr->prepare("SELECT u.user, u.userid, pm.arg FROM priv_map pm, priv_list pl, user u WHERE pl.prlid=pm.prlid AND pl.privcode='dirsync' AND pm.userid=u.userid ORDER BY u.user"); + $sth->execute; + while (my ($user, $userid, $arg) = $sth->fetchrow_array) + { + print "-I- $user: $arg\n" if ($VERBOSE); + if ($arg =~ /\.\./) { print "-E- ($user) arg contains '..', skipping!\n"; next; } + if ($arg =~ /~/) { print "-E- ($user) arg contains '~', skipping!\n"; next; } + my $opts; + if ($arg =~ s/\s*\[(.+)?\]\s*$//) { + $opts = $1; + } + unless ($arg =~ /^(\S+)=(\S+)$/) { print "-E- arg doesn't match \S+=\S+, skipping!\n"; next; } + my ($from, $to) = ($1, $2); + + $to =~ s/\0//; # fuck perl, seriously. why's a NULL in this string? + if ($from =~ /\0/) { die "from has null (0)!\n"; } + if ($to =~ /\0/) { die "to has null (0)!\n"; } + + $from = "$FROMBASE/$user/$from"; + $to = "$TOBASE/$to"; + unless (-d $from) { print "-E- ($user) From directory doesn't exist: $from, skipping!\n"; next; } + unless (-d $to) { print "-E- ($user) To directory doesn't exist: $to, skipping!\n"; next; } + + opendir (DIR, $from); + while (my $file = readdir DIR) + { + if ($file eq "." || $file eq ".." || $file =~ /~/ || length($file) > 40) { next; } + + my $tofile = "$to/$file"; + if ($tofile =~ /\0/) { die "tofile has null (1)!\n"; } + + my $fromfile = "$from/$file"; + if (-d $fromfile) { next; } + unless (-f $fromfile) { next; } + + my $fromtime = (stat($fromfile))[9]; + my $totime = (-e $tofile) ? (stat($tofile))[9] : 0; + my $existtime = $totime - $fromtime; + + my $allow = 0; + if ($totime == 0) { $allow = 1; } + elsif ($fromtime > $totime) { + if ($existtime < $REWRITE_PERIOD) { $allow = 1; } + elsif ($file =~ /^changelog(\.txt)?$/i || + $file =~ /^readme(\.txt)?$/i) { $allow = 1; } + elsif ($opts =~ /u/) { $allow = 1; } + } + + if ($allow) { + if ($fromfile =~ /\0/) { die "from has null!\n"; } + if ($tofile =~ /\0/) { die "to has null!\n"; } + print "-I- ($user) Copying $file ($fromfile to $tofile)\n"; + unless (copy($fromfile, $tofile)) { + print "-E- ($user) Didn't copy! error: $!\n"; + } + } + } + + } + +}; + +1; diff --git a/ljcom/bin/maint/expiring.pl b/ljcom/bin/maint/expiring.pl new file mode 100644 index 0000000..34c0424 --- /dev/null +++ b/ljcom/bin/maint/expiring.pl @@ -0,0 +1,259 @@ +#!/usr/bin/perl +# + +use strict; +use vars qw(%maint); + +$maint{'expiring'} = sub +{ + require "$ENV{'LJHOME'}/cgi-bin/paylib.pl"; + my $dbh = LJ::get_db_writer(); + my $sth; + + # NOTES: + # We mail people about 10 days before, 3 days before, + # and when their account expires. But because we have + # to plan for this script not running all the time, here + # are the rules/ranges we play by: + # + # + # 10 8 3 2 0 + # ------------------------+-----------+..... + # ^-----------^ ^------^ ^>>>> + # "Expiring..." "Soon!" "Expired" + # + # First, expire all accounts t>=0, and email them. + # + # Second, mail all accounts expiring in 2-3 days, + # provided they haven't been mailed in the past 5 days. + # (less than 2 days would be considered too rude, + # considering we'll be mailing them again in a day + # or so to say it expired.) + # + # Third, mail all accounts expiring 8-10 days, again + # if they haven't been mailed in past 5 days. + + # what time is it on the database? + my $nowu = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()"); + + if (abs($nowu - time()) > 30*60) { + die "Database and host clock differ too much. Something might be wrong.\n"; + } + + # do expirations + print "-I- Doing expirations.\n"; + + # paid accounts + $sth = $dbh->prepare("SELECT userid FROM paiduser ". + "WHERE paiduntil < NOW() AND paiduntil > '0000-00-00'"); + $sth->execute; + die $dbh->errstr if $dbh->err; + while (my ($userid) = $sth->fetchrow_array) + { + + # about to modify account, get a lock on the user, + # try again later if we fail to get a lock + next unless LJ::Pay::get_lock($userid); + + # re-verify $u object and skip if the expiration data no longer matches + my $u = $dbh->selectrow_hashref("SELECT u.* FROM user u, paiduser pu ". + "WHERE pu.userid=? AND u.userid=pu.userid AND u.caps&16=0 AND ". + " pu.paiduntil < NOW() AND pu.paiduntil > '0000-00-00'", + undef, $userid); + unless ($u) { + LJ::Pay::release_lock($userid); + next; + } + + # expire the account + print "Expiring $u->{'user'}...\n"; + + # remove paid time, this %res is coming from LJ::Pay::freeze_bonus + my $bonus_ref = []; + my $res = LJ::Pay::remove_paid_account($u, $bonus_ref); + + # release lock on this account + LJ::Pay::release_lock($userid); + + # did an error occur above? + unless ($res) { + LJ::statushistory_add($userid, undef, "pay_modify", + "error trying to expire paid account"); + next; + } + + # and send them an email, if they're not self-deleted/suspended + if ($u->{'statusvis'} eq "V") { + my $bonus_msg; + if (@$bonus_ref) { + $bonus_msg = "Additionally, the following bonus features have been deactivated " . + "from your account. Any remaining time has been saved and will " . + "be reapplied if you later decide to renew your paid account.\n\n" . + join("\n", map { " - " . LJ::Pay::product_name($_->{'item'}, $_->{'size'}, undef, "short") . + ": $_->{'daysleft'} days saved" } + sort { $a->{'item'} cmp $b->{'item'} } @$bonus_ref) . "\n\n"; + } + + # email the user + LJ::send_mail({ 'to' => $u->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => 'Paid Account Expired', + 'body' => ("Your $LJ::SITENAMESHORT paid account for user \"$u->{'user'}\" has expired.\n\n". + $bonus_msg . + "You can continue to use the site, but without all the paid features. If ". + "you'd like to renew your subscription, visit:\n\n". + " $LJ::SITEROOT/pay/\n\n". + "And if you have any questions or requests, feel free to ask. We want ". + "to keep you happy. :)\n\n". + "Thanks,\n". + "$LJ::SITENAMESHORT Team\n"), + }); + } + } + + # bonus features + $sth = $dbh->prepare("SELECT userid, item, size FROM paidexp " . + "WHERE (daysleft=0 OR daysleft IS NULL) AND ". + " expdate < NOW() AND expdate > '0000-00-00'"); + $sth->execute; + die $dbh->errstr if $dbh->err; + while (my ($userid, $item, $size) = $sth->fetchrow_array) + { + + # get a u object + my $u = LJ::load_userid($userid, "force"); + + # going to modify this account, get a lock. + # but try again later if we can't get one + next unless LJ::Pay::get_lock($userid); + + # expire the feature + print "Expiring $u->{'user'} bonus feature: $item..\n"; + + # expire this bonus feature + my $res = LJ::Pay::expire_bonus($userid, $item); + + # finished doing account modifications + LJ::Pay::release_lock($userid); + + # an error occurred above, log to statushistory + unless ($res) { + LJ::statushistory_add($userid, undef, "pay_modify", + "error trying to expire bonus feature: $item"); + next; + } + + # and send them an email, if they're not self-deleted/suspended + if ($u->{'statusvis'} eq "V") { + my $name = LJ::Pay::product_name($item, $size, undef, "short"); + LJ::send_mail({ 'to' => $u->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => 'Bonus Feature Expired', + 'body' => ("$u->{'name'},\n\n". + "The following bonus feature of your $LJ::SITENAMESHORT paid " . + "account for user \"$u->{'user'}\" has expired.\n\n" . + " - $name\n\n" . + "If you'd like this feature reactivated, you can " . + "renew your subscription. To do so, visit:\n\n" . + " $LJ::SITEROOT/pay/\n\n". + "Thanks,\n". + "$LJ::SITENAMESHORT Team\n"), + }); + } + } + + + # do reminders + foreach my $range ([2,3,"warn"], [8,10,"soon"]) { + my $rlo = $range->[0]; + my $rhi = $range->[1]; + my $level = $range->[2]; + + # expiring paid accounts + my $subject = $level eq "soon" ? "Account Expiring Soon" : "Account Expiration Warning"; + print "-I- Do $rlo-$rhi day reminders...\n"; + $sth = $dbh->prepare("SELECT u.*, pu.paiduntil, pu.paidreminder ". + "FROM user u, paiduser pu ". + "WHERE u.userid=pu.userid AND u.caps&16=0 AND u.caps&8 ". + "AND u.statusvis='V' ". + "AND pu.paiduntil BETWEEN DATE_ADD(NOW(), INTERVAL $rlo DAY) ". + "AND DATE_ADD(NOW(), INTERVAL $rhi DAY) ". + "AND (pu.paidreminder IS NULL ". + "OR pu.paidreminder < DATE_SUB(NOW(), INTERVAL 5 DAY))"); + $sth->execute; + die $dbh->errstr if $dbh->err; + while (my $u = $sth->fetchrow_hashref) + { + my $uexp = LJ::mysqldate_to_time($u->{'paiduntil'}); + my $days = int(($uexp - $nowu) / 86400 + 0.5); + print "Mailing user $u->{'user'} about $days days...\n"; + $dbh->do("UPDATE paiduser SET paidreminder=NOW() WHERE userid=?", undef, $u->{'userid'}); + LJ::send_mail({ 'to' => $u->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => $subject, + 'body' => ("$u->{'name'},\n\n". + "Your $LJ::SITENAMESHORT paid account for user \"$u->{'user'}\" is expiring ". + "in $days days, at which time it'll revert to free account status.\n\n". + "If you're still using and enjoying the site, please renew your ". + "subscription before it runs out and help support the project. ". + "(Servers and bandwidth don't come free, unfortunately...)\n\n". + " $LJ::SITEROOT/pay/\n\n". + "And if you have any questions or requests, feel free to ask. We want ". + "to keep you happy. :)\n\n". + "Thanks,\n". + "$LJ::SITENAMESHORT Team\n"), + }); + } + + # expiring bonus feature reminders + my $subject = $level eq "soon" ? "Subscription Expiring Soon" : "Subscription Expiration Warning"; + $sth = $dbh->prepare("SELECT u.*, px.item, px.size, px.expdate FROM user u, paidexp px ". + "WHERE u.userid=px.userid AND u.statusvis='V' AND ". + " px.expdate BETWEEN DATE_ADD(NOW(), INTERVAL $rlo DAY) AND ". + " DATE_ADD(NOW(), INTERVAL $rhi DAY)". + " AND (px.lastmailed IS NULL ". + " OR px.lastmailed < DATE_SUB(NOW(), INTERVAL 5 DAY))"); + $sth->execute; + die $dbh->errstr if $dbh->err; + while (my $u = $sth->fetchrow_hashref) + { + my $expdate = LJ::mysqldate_to_time($u->{'expdate'}); + my $days = int(($expdate - $nowu) / 86400 + 0.5); + print "Mailing user $u->{'user'} about $days days...\n"; + $dbh->do("UPDATE paidexp SET lastmailed=NOW() WHERE userid=? AND item=?", + undef, $u->{'userid'}, $u->{'item'}); + my $bonus_name = LJ::Pay::product_name($u->{'item'}, $u->{'size'}, undef, "short"); + LJ::send_mail({ 'to' => $u->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => $subject, + 'body' => ("$u->{'name'},\n\n". + "Your $LJ::SITENAMESHORT paid account for user \"$u->{'user'}\" has ". + "bonus features expiring soon. In $days days, your ". + "$bonus_name will expire and you will be reverted to the standard ". + "set of features included with your paid account.\n\n". + "If you're still using and enjoying your $bonus_name, please ". + "renew your subscription at the $LJ::SITENAMESHORT store:\n\n". + " $LJ::SITEROOT/pay/\n\n". + "If you have any further questions, feel free to ask. We'll do our ". + "best to help.\n\n". + "Thanks,\n". + "$LJ::SITENAMESHORT Team\n"), + }); + } + } + + print "-I- Done.\n"; +}; + +1; diff --git a/ljcom/bin/maint/interests.pl b/ljcom/bin/maint/interests.pl new file mode 100644 index 0000000..61ebffd --- /dev/null +++ b/ljcom/bin/maint/interests.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl +# + +$maint{'clean_intdups'} = sub +{ + my $dbh = LJ::get_dbh("master"); + my ($sth); + my @dups; + + print "-I- Cleaning duplicates.\n"; + foreach my $let ('a'..'z', '0'..'9') + { + print "-I- Letter $let\n"; + $sth = $dbh->prepare("SELECT interest, COUNT(*) AS 'count' FROM interests WHERE interest LIKE '$let%' GROUP BY 1 HAVING count > 1"); + $sth->execute; + while (($interest, $count) = $sth->fetchrow_array) + { + print " $interest has $count\n"; + push @dups, $interest; + } + } + + foreach my $dup (@dups) { + print "Fixing: $dup\n"; + my $min = 0; + my @fix = (); + my $qdup = $dbh->quote($dup); + $sth = $dbh->prepare("SELECT intid FROM interests WHERE interest=$qdup ORDER BY intid"); + $sth->execute; + while (my ($id) = $sth->fetchrow_array) { + if ($min) { push @fix, $id; } + else { $min = $id; } + } + if (@fix) { + my $in = join(",", @fix); + + # change duplicate interests to the minimum, ignoring duplicates. + $sth = $dbh->prepare("UPDATE IGNORE userinterest SET intid=$min WHERE intid IN ($in)"); + $sth->execute; + + # delete ones that had duplicate key conflicts and didn't change + $sth = $dbh->prepare("DELETE FROM userinterest WHERE intid IN ($in)"); + $sth->execute; + + # update the intcount column + $sth = $dbh->prepare("REPLACE INTO interests (intid, interest, intcount) SELECT intid, $qdup, COUNT(*) FROM userinterests WHERE intid=$min GROUP BY 1, 2"); + $sth->execute; + + # delete from interests table + $sth = $dbh->prepare("DELETE FROM interests WHERE intid IN ($in)"); + $sth->execute; + } + print " @fix --> $min\n"; + + } + +}; + +$maint{'clean_intcounts'} = sub +{ + my $dbh = LJ::get_dbh("master"); + my ($sth); + + $sth = $dbh->prepare("SELECT MAX(intid) FROM userinterests"); + $sth->execute; + my ($max) = $sth->fetchrow_array; + + print "Fixing intcounts, up to intid=$max\n"; + for (my $i=1; $i < $max; $i += 5000) + { + my $low = $i; + my $high = $i+4999; + print "$low..$high:\n"; + $sth = $dbh->prepare("SELECT ui.intid, i.intcount, COUNT(*) AS 'count' FROM userinterests ui, interests i WHERE i.intid=ui.intid AND ui.intid BETWEEN $low AND $high GROUP BY 1, 2 HAVING i.intcount<>COUNT(*)"); + $sth->execute; + while (my ($intid, $wrong, $count) = $sth->fetchrow_array) { + print " $intid: $count, not $wrong\n"; + $dbh->do("UPDATE interests SET intcount=$count WHERE intid=$intid"); + } + } + +}; + +1; diff --git a/ljcom/bin/maint/ljadmin.pl b/ljcom/bin/maint/ljadmin.pl new file mode 100644 index 0000000..72dfc70 --- /dev/null +++ b/ljcom/bin/maint/ljadmin.pl @@ -0,0 +1,215 @@ +#!/usr/bin/perl +# + +use SOAP::Lite; + +sub SOAP::Transport::HTTP::Client::get_basic_credentials +{ + return $LJ::BIGIP_USER => $LJ::BIGIP_PASS; +} + +$maint{'echo'} = sub +{ + my (@args) = @_; + print "echo: @args\n"; +}; + +$maint{'echosleep'} = sub +{ + my ($sleep, @args) = @_; + print "echosleep: @args\n"; + sleep $sleep; +}; + +$maint{'debug'} = sub +{ + my (@args) = @_; + print "debug: @args\n"; + print "\$LJ::HOME = $LJ::HOME\n"; + print "whoami? ", `whoami`; + print "\$< = $<, \$> = $>\n"; + print "ENV:\n"; + foreach (keys %ENV) { + print " $_ = $ENV{$_}\n"; + } +}; + +$maint{'apgrace'} = sub +{ + unless ($> == 0) { + print "Only root can restart apache\n"; + return 0; + } + + print "Gracefully restarting apache...\n"; + system("/usr/sbin/apachectl", "graceful"); + print "Done.\n"; +}; + +$maint{'appgrace'} = sub +{ + unless ($> == 0) { + print "Only root can restart apache-perl\n"; + return 0; + } + + print "Gracefully restarting apache-perl...\n"; + system("/usr/sbin/apache-perl-ctl", "graceful"); + print "Done.\n"; +}; + +$maint{'appss'} = sub +{ + unless ($> == 0) { + print "Only root can stop/start apache-perl\n"; + return 0; + } + + open (BC, "$ENV{'LJHOME'}/.bigip_soap.conf"); + my $line = ; + chomp $line; + ($LJ::BIGIP_HOST, $LJ::BIGIP_PORT, $LJ::BIGIP_USER, $LJ::BIGIP_PASS) + = split(/\s+/, $line); + close BC; + my $soap; + if ($LJ::BIGIP_HOST) { + $soap = SOAP::Lite + -> uri('urn:iControl:ITCMLocalLB/Node') + -> readable(1) + -> proxy("https://${LJ::BIGIP_HOST}:${LJ::BIGIP_PORT}/iControl/iControlPortal.cgi"); + } + + my $ifconfig = `/sbin/ifconfig -a`; + my $ip; + if ($ifconfig =~ /addr:(10\.0\.\S+)/) { + $ip = $1; + } + + my $node_config = sub { + return 0 unless $soap && $ip; + my $state = shift; + $state = $state ? 1 : 0; + + my $node_definition = { address => $ip, port => 80 }; + my $soap_response = $soap->set_state(SOAP::Data->name(node_defs => ( [$node_definition] )), + SOAP::Data->name(state => $state)); + if ($soap_response->fault) { + print $soap_response->faultcode, " ", $soap_response->faultstring, "\n"; + return 0; + } + return 1; + }; + + print "Stopping & starting apache-perl...\n"; + if ($node_config->(0)) { + print "Node disabled on BIG-IP.\n"; + } + system("/usr/sbin/apache-perl-ctl", "stop"); + while (-e "/var/run/apache-perl.pid") { + sleep 1; + } + system("/usr/sbin/apache-perl-ctl", "start"); + if ($node_config->(1)) { + print "Node enabled on BIG-IP.\n"; + } + print "Done.\n"; +}; + +$maint{'sshkick'} = sub +{ + unless ($> == 0) { + print "Only root can stop/start ssh\n"; + return 0; + } + + print "Stopping & starting ssh...\n"; + system("/etc/init.d/ssh", "restart"); + print "Done.\n"; +}; + +$maint{'statscaster_restart'} = sub +{ + unless ($> == 0) { + print "Only root can stop/start statscaster\n"; + return 0; + } + + print "Stopping & starting statscaster...\n"; + system("cp", "$ENV{LJHOME}/bin/lj-init.d/ljstatscasterd", "/etc/init.d/ljstatscasterd"); + system("chmod", "+x", "/etc/init.d/ljstatscasterd"); + system("/etc/init.d/ljstatscasterd", "restart"); + print "Done.\n"; +}; + +$maint{'aprestart'} = sub +{ + unless ($> == 0) { + print "Only root can restart apache\n"; + return 0; + } + + print "Restarting apache...\n"; + system("/usr/sbin/apachectl", "restart"); + print "Done.\n"; +}; + +$maint{'hupcaches'} = sub +{ + if ($> == 0) { + print "Don't run this as root.\n"; + return 0; + } + foreach my $proc (qw(404notfound.cgi users customview.cgi bmlp.pl interface)) + { + print "$proc..."; + print `$LJ::BIN/hkill $proc | wc -l`; + } +}; + +$maint{'restartapps'} = sub +{ + if ($> == 0) { + print "Don't run this as root.\n"; + return 0; + } + my $pid; + if ($pid = fork) + { + print "Started.\n"; + return 1; + } + + foreach my $proc (qw(404notfound.cgi users customview.cgi interface)) { + system("$LJ::BIN/pkill", $proc); + } +}; + +$maint{'load'} = sub +{ + print ((`w`)[0]); + +}; + +$maint{'date'} = sub +{ + print ((`date`)[0]); + +}; + +$maint{'exposeconf'} = sub +{ + print "-I- Copying configuration files to /misc/conf\n"; + my @files = qw( + /usr/src/sys/i386/conf/KENNYSMP kernel-config.txt + /etc/postfix/main.cf postfix-main.cf.txt + /etc/postfix/master.cf postfix-master.cf.txt + ); + + while (@files) { + my $src = shift @files; + my $dest = shift @files; + print "$src -> $dest\n"; + system("cp", $src, "$LJ::HTDOCS/misc/conf/$dest"); + } + print "done.\n"; +}; diff --git a/ljcom/bin/maint/moods.pl b/ljcom/bin/maint/moods.pl new file mode 100644 index 0000000..a8dff36 --- /dev/null +++ b/ljcom/bin/maint/moods.pl @@ -0,0 +1,10 @@ +#!/usr/bin/perl +# + +$maint{'makemoodindexes'} = sub +{ + print "-I- Making mood index files.\n" if $VERBOSE; + system("find $LJ::HTDOCS/img/mood/ -type d -exec makemoodindex.pl {} \\;"); +}; + +1; diff --git a/ljcom/bin/maint/pay.pl b/ljcom/bin/maint/pay.pl new file mode 100644 index 0000000..94e5ca9 --- /dev/null +++ b/ljcom/bin/maint/pay.pl @@ -0,0 +1,713 @@ +#!/usr/bin/perl +# + +use strict; +use vars qw(%maint); + +$maint{'pay_mail'} = sub +{ + require "$ENV{'LJHOME'}/cgi-bin/paylib.pl"; + + my $dbh = LJ::get_db_writer(); + + my $sth; + my $now = time(); + + # we don't mail receipts (yet?) to non-users paying, or carts w/ no price (eg coppa verifications) + $dbh->do("UPDATE payments SET mailed='X' WHERE mailed='N' AND forwhat='cart' AND (userid=0 OR amount=0)"); + + $sth = $dbh->prepare("SELECT u.user, u.email, u.name, p.* FROM payments p, user u ". + "WHERE p.userid=u.userid AND p.mailed='N' ". + "AND (IFNULL(p.giveafter,0) = 0 OR $now >= p.giveafter)"); + $sth->execute; + die $dbh->errstr if $dbh->err; + while (my $p = $sth->fetchrow_hashref) + { + + my $note_msg = sub { + return "" unless $p->{'notes'}; + + # this will get run through Text::Wrap when it's emailed + my $notes = $p->{'notes'}; + $notes =~ s/\n/\n /g; + + return "Here are some notes associated with this payment:\n\n" . + " $notes\n\n"; + }; + + if ($p->{'forwhat'} eq "cart") { + my $cart = "$p->{'payid'}-$p->{'anum'}"; + LJ::send_mail({ + 'to' => $p->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Payment received (Order $cart)", + 'body' => ("Your payment of \$$p->{'amount'} for order $cart was received and the order is now being processed.\n\n". + "For your reference, you can view the order here:\n\n". + " $LJ::SITEROOT/pay/?c=$cart\n\n". + $note_msg->() . + "We thank you for supporting the site,\n\n". + "$LJ::SITENAMESHORT Team" + )}); + $dbh->do("UPDATE payments SET mailed='Y' WHERE payid=$p->{'payid'}"); + next; + } + + if ($p->{'forwhat'} eq "rename") { + my $token = LJ::Pay::new_rename_token($dbh, $p->{'payid'}) + or next; + + LJ::send_mail({ + 'to' => $p->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Rename Token", + 'body' => ("Here is the username rename token you purchased:\n\n". + " $token\n\n". + "You can use it here:\n\n". + " $LJ::SITEROOT/rename/use.bml?token=$token\n\n". + "For more information regarding account renames, read:\n\n". + " $LJ::SITEROOT/rename/\n\n". + $note_msg->() . + "$LJ::SITENAMESHORT Team" + ), + }); + + $dbh->do("UPDATE payments SET mailed='Y', used='Y' WHERE payid=$p->{'payid'}"); + next; + } + + my $howmany = $p->{'months'} == 99 ? "UNLIMITED" : $p->{'months'}; + print "$p->{'payid'}: Mailing $p->{'email'} ($howmany) ...\n"; + $p->{'notes'} =~ s/\r//g; + + my $msg; + $msg .= "$p->{'name'} ...\n\n"; + $msg .= "Your $LJ::SITENAMESHORT payment of \$$p->{'amount'} was received $p->{'daterecv'}"; + if ($p->{'forwhat'} eq "account") { + $msg .= " and your account has been credited with $howmany more months"; + } + $msg .= ".\n\n"; + + $msg .= $note_msg->(); + + $msg .= "We thank you for supporting the site,\n\n$LJ::SITENAMESHORT Team"; + + LJ::send_mail({ + 'to' => $p->{'email'}, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "$LJ::SITENAMESHORT Payment Received -- \#$p->{'payid'}", + 'body' => $msg, + }); + + $dbh->do("UPDATE payments SET mailed='Y' WHERE payid=$p->{'payid'}"); + } + +}; + +$maint{'pay_updateaccounts'} = sub +{ + require "$ENV{'LJHOME'}/cgi-bin/paylib.pl"; + + my $dbh = LJ::get_db_writer() + or die "Could not contact global database master"; + + # for some reason, use of purchased codes doesn't always apply payment + # to account when it's created. some code path involved when paypal + # servers are being lame isn't as robust, or something. in any case, + # this query fixes it: + my $sth = $dbh->prepare + ("SELECT ac.rcptid, p.payid ". + "FROM acctcode ac, acctpay ap, payments p ". + "WHERE p.userid=0 AND p.used='N' AND p.payid=ap.payid AND ". + " ap.acid=ac.acid AND ac.rcptid <> 0"); + $sth->execute; + while (my ($userid, $payid) = $sth->fetchrow_array) { + $dbh->do("UPDATE payments SET userid=$userid WHERE payid=$payid AND userid=0"); + print "Fix payid=$payid to userid=$userid.\n"; + } + + # and now, back to what this maint task is supposed to do: + my $now = time(); + $sth = $dbh->prepare("SELECT payid, userid, months, forwhat, amount, method, datesent ". + "FROM payments WHERE used='N' ". + "AND (IFNULL(giveafter,0) = 0 OR $now >= giveafter)"); + $sth->execute; + die $dbh->errstr if $dbh->err; + my @used = (); + while (my $p = $sth->fetchrow_hashref) + { + my $userid = $p->{'userid'}; + + # check userids of all the affected clusterids before deciding whether to process this payment + my %userids = $userid ? ($userid => 1) : (); + if ($p->{'forwhat'} eq 'cart') { + my $s = $dbh->prepare("SELECT rcptid FROM payitems WHERE payid=? AND rcptid>0"); + $s->execute($p->{'payid'}); + die $dbh->errstr if $dbh->err; + while (my $uid = $s->fetchrow_array) { + $userids{$uid} = 1; + } + } + + if (%userids) { + # call into LJ::load_userids_multi() to get clusterids for these users + # -- cheap because we load all payment userids later during processing + + my $users = LJ::load_userids(keys %userids); + + # verify we can get all of the handles necessary to complete this request + my $dirty = 0; + foreach (values %$users) { + $dirty = $_->{clusterid}, last unless $_->writer; + } + + if ($dirty) { + print "Cluster $dirty unreachable, skipping payment: $p->{payid}\n"; + next; + } + } + + print "Payment: $p->{'payid'} ($p->{'forwhat'})\n"; + + # mail notification of large orders... but only if it was automatically processed + if ($LJ::ACCOUNTS_EMAIL && $LJ::LARGE_ORDER_NOTIFY && + ($p->{'method'} eq "cc" || $p->{'method'} eq "paypal") && + $p->{'amount'} > $LJ::LARGE_ORDER_NOTIFY) { + + my $dollars = sub { sprintf("\$%.02f", shift()) }; + print "Sending large order notification: " . $dollars->($p->{'amount'}) . "\n"; + + LJ::send_mail({ + 'to' => $LJ::ACCOUNTS_EMAIL, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Large order processed: " . $dollars->($p->{'amount'}) . + " [payid: $p->{'payid'}]", + 'body' => "This warning has been sent because the following order of over " . + $dollars->($LJ::LARGE_ORDER_NOTIFY) . + " has been processed on $LJ::SITENAMESHORT.\n\n" . + + " Amount: " . $dollars->($p->{'amount'}) . "\n" . + " Payid: $p->{'payid'}\n" . + " Method: $p->{'method'}\n" . + " Date Sent: $p->{'datesent'}\n\n" + }); + } + + # park this payment as used + push @used, $p->{'payid'}; + + # if a cart, mark each item in the cart as ready to be processed, + # then we'll do that below. + if ($p->{'forwhat'} eq "cart") { + $dbh->do("UPDATE payitems SET status='pend' WHERE ". + "payid=? AND status='cart'", undef, $p->{'payid'}); + + next; + } + + ### legacy support from here on. + + # needs to be for a user + next unless $userid; + + # if permanent account, ignore this legacy (non-cart) payment + my $u = LJ::load_userid($userid); + next if $u->{'caps'} & (1 << $LJ::Pay::capinf{'perm'}->{'bit'}); + + # if there is an error adding paid months, remove from used list + # so we'll try again later + unless (LJ::Pay::add_paid_months($userid, $p->{'months'})) { + pop @used; + } + } + + # @used is only populated in legacy (non-cart) case + if (@used) { + my $usedin = join(", ", @used); + $dbh->do("UPDATE payments SET used='Y' WHERE payid IN ($usedin)"); + } + + my %pay; + my $get_payment = sub { + my $id = shift; + return $pay{$id} if $pay{$id}; + return $pay{$id} = + $dbh->selectrow_hashref("SELECT * FROM payments WHERE payid=?", + undef, $id); + }; + + # get pending cart items + my %payitems = ( 'paidacct' => [], 'other' => [] ); + $sth = $dbh->prepare("SELECT * FROM payitems WHERE status='pend'"); + $sth->execute; + while (my $pi = $sth->fetchrow_hashref) { + my $key = $pi->{'item'} eq 'perm' ? 'perm' : + $pi->{'item'} eq 'paidacct' ? 'paidacct' : 'other'; + push @{$payitems{$key}}, $pi; + } + my %bonus_failure = (); + + # paid accounts are special because they have to apply before bonus features + foreach my $pi (@{$payitems{'perm'}}, @{$payitems{'paidacct'}}, @{$payitems{'other'}}) { + next if $pi->{'giveafter'} > $now; # delayed payment + + my $pp = $get_payment->($pi->{'payid'}); + my $bu = LJ::load_userid($pp->{'userid'}); # buying user, no force needed + + my $email = $pi->{'rcptemail'}; + my $ru; # rcpt user + if ($pi->{'rcptid'}) { + $ru = LJ::load_userid($pi->{'rcptid'}, "force"); + $email = $ru->{'email'}; + } + + # optional gift header + my $msg; + if ($bu && $bu->{'userid'} != $pi->{'rcptid'}) { + if ($pi->{'anon'}) { + $msg .= "(the following is an anonymous gift)\n\n" + } else { + $msg .= "(the following is a gift from $LJ::SITENAMESHORT user \"$bu->{'user'}\")\n\n"; + } + } + + my ($token, $tokenid); + my $close = sub { + $dbh->do("UPDATE payitems SET status='done', token=?, tokenid=? ". + "WHERE piid=? AND status='pend'", undef, $token, + $tokenid, $pi->{'piid'}); + }; + + # paid/perm accounts + if ($pi->{'item'} eq "paidacct" || $pi->{'item'} eq "perm") { + my $isacct = $pi->{'item'} eq "paidacct"; + + my $has_perm = $ru && $ru->{'caps'} & (1 << $LJ::Pay::capinf{'perm'}->{'bit'}); + + # send 'em a token + if ($pi->{'rcptid'} == 0 || $has_perm) { # rcpt is an email address, or perm acct + $token = LJ::acct_code_generate($bu ? $bu->{userid} : 0); + my ($acid, $auth) = LJ::acct_code_decode($token); + $dbh->do("INSERT INTO acctpayitem (piid, acid) VALUES (?,?)", + undef, $pi->{'piid'}, $acid); + + $tokenid = $acid; + + my $what; + if ($isacct) { + $what = "$pi->{'qty'} month(s) of paid account time"; + } else { + $what = "a permanent account"; + } + + $msg .= "The following code will give $what to any $LJ::SITENAMESHORT account:\n\n"; + $msg .= " $token\n\n"; + $msg .= "To apply it to an existing account, visit:\n\n"; + $msg .= " $LJ::SITEROOT/paidaccounts/apply.bml?code=$token\n\n"; + $msg .= "To create a new account using it, visit:\n\n"; + $msg .= " $LJ::SITEROOT/create.bml?code=$token\n\n"; + + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => $isacct ? "Paid account" : "Permanent account", + 'body' => $msg, + }); + $close->(); + # don't need to release lock, no rcptid + next; + } + + # just set it up now, and tell them it's done. + # no need to release lock since no $ru anyway + next unless $ru; + + my $mo; + $mo = $pi->{'qty'} if $isacct; + $mo = 99 if $pi->{'item'} eq "perm"; + my $bonus_ref = []; + + # modifying paid account status, need to get a lock on the account, + # try again later if we fail to get a lock + next unless LJ::Pay::get_lock($ru); + + my $res = LJ::Pay::add_paid_months($ru->{'userid'}, $mo, $bonus_ref); + + # finished modifying account, can unconditionally release lock and finish payitem now + LJ::Pay::release_lock($ru); + + # some sort of error occurred, log to payvars and try again later + unless ($res) { + LJ::Pay::payvar_append($pi->{'payid'}, "error", + "[" . LJ::mysql_time() . "] unable to apply: item=$pi->{'item'}, qty=$pi->{'qty'}."); + next; + } + + # account changes were successful: close transaction, only need to send email now + $close->(); + + # finish composing email to send to user + my $bonus_added; + if (@$bonus_ref) { + $bonus_added = "Additionally, the following previously deactivated bonus features\n" . + "have been reactivated so you can use the time remaining on them:\n\n" . + join("\n", map { " - " . LJ::Pay::product_name($_->{'item'}, $_->{'size'}, undef, "short") . + ": $_->{'daysleft'} days applied" } + sort { $a->{'item'} cmp $b->{'item'} } @$bonus_ref) . + "\n\n"; + } + + if ($isacct) { + $msg .= "$mo months of paid account time have been added to your $LJ::SITENAMESHORT account for user \"$ru->{'user'}\".\n\n$bonus_added$LJ::SITENAMESHORT Team"; + } else { + $msg .= "Your $LJ::SITENAMESHORT account \"$ru->{'user'}\" has been upgraded to a permanent account.\n\n$bonus_added$LJ::SITENAMESHORT Team"; + } + + # send notification email + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => $isacct ? "Paid Account" : "Permanent Account", + 'body' => $msg, + }); + + next; + } + + # rename tokens + elsif ($pi->{'item'} eq "rename") { + next unless ($token, $tokenid) = LJ::Pay::new_rename_token($dbh, $pp->{'payid'}); + + # send email notification + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Rename Token", + 'body' => "${msg}$LJ::SITENAMESHORT username rename token:\n\n". + " $token\n\n". + "You can use it here:\n\n". + " $LJ::SITEROOT/rename/use.bml?token=$token\n\n". + "For more information regarding account renames, read:\n\n". + " $LJ::SITEROOT/rename/\n\n". + "$LJ::SITENAMESHORT Team", + }); + + $close->(); + next; + } + + # clothing items + elsif ($pi->{'item'} eq "clothes") { + $dbh->do("INSERT IGNORE INTO shipping (payid, status, dateready) VALUES (?, 'needs', NOW())", + undef, $pp->{'payid'}) and $close->(); + next; + } + + # coupons + elsif ($pi->{'item'} eq "coupon") { + + # subitem used to be type-dollaramount, but that was redundant + my ($type) = split('-', $pi->{'subitem'}); + + # If amt < 0, this item is a previously purchased coupon being applied + # to this cart. So we shouldn't generate a new tokenid for it, especially + # since it will have rcptid=0, so we wouldn't know where to mail it anyway. + if ($type eq 'dollaroff' && $pi->{'amt'} > 0) { + + ($tokenid, $token) = + LJ::Pay::new_coupon("dollaroff", $pi->{'amt'}, $pi->{'rcptid'}, $pp->{'payid'}); + + # if there was an error, try again later + next unless $tokenid; + + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "Coupon Purchase", + 'body' => "${msg}$LJ::SITENAMESHORT coupon code:\n\n". + " $token\n\n". + "You can redeem it for \$$pi->{amt} USD in $LJ::SITENAMESHORT merchandise and/or services:\n\n". + "$LJ::SITENAMESHORT store:\n" . + " - $LJ::SITEROOT/store/\n\n" . + "$LJ::SITENAMESHORT services:\n" . + " - $LJ::SITEROOT/pay/\n\n" . + + "NOTE: Your coupon is only valid for one use, so be sure that your order's " . + "value is greater than or equal to \$$pi->{amt} USD.\n\n" . + + "$LJ::SITENAMESHORT Team", + }); + + # close, but preserve token info + } else { + ($token, $tokenid) = ($pi->{'token'}, $pi->{'tokenid'}); + } + $close->(); + next; + } + + # bonus features + elsif (LJ::Pay::is_bonus($pi)) { + + # if a bonus item of this type failed to apply, don't try to apply any more + next if exists $bonus_failure{"$pi->{'payid'}-$pi->{'item'}-$pi->{'subitem'}"}; + + # get a lock since we're about to modify their account, + # try again later if we can't get a lock + next unless LJ::Pay::get_lock($ru); + + # apply the bonus item to the recipient user's account + my $res = LJ::Pay::apply_bonus_item($ru, $pi); + + # release lock and close regardless of results of operation + LJ::Pay::release_lock($ru); + + # if an error, log to payvars (call above also logged to statushistory) and skip the email + unless ($res) { + LJ::Pay::payvar_append($pi->{'payid'}, "error", + "[" . LJ::mysql_time() . "] unable to apply: item=$pi->{'item'}, size=" . + (split("-", $pi->{'subitem'}))[0] . ", qty=$pi->{'qty'}. invalid cart?"); + + # if there was a failure, all bonus items of this type were marked + # as failed, so we shouldn't try to process any more of them + $bonus_failure{"$pi->{'payid'}-$pi->{'item'}-$pi->{'subitem'}"}++; + + next; + } + + # at this point time is applied, just need to send mail. so close. + $close->(); + + # send notification email to user + my $name = LJ::Pay::product_name($pi); + LJ::send_mail({ + 'to' => $email, + 'from' => $LJ::ACCOUNTS_EMAIL, + 'fromname' => $LJ::SITENAMESHORT, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => $name, + 'body' => "${msg}Your $LJ::SITENAMESHORT account for user \"$ru->{'user'}\" has been " . + "credited with the following bonus feature:\n\n" . + " - $name\n\n" . + "Your account has been updated so you can use your new feature immediately.\n\n" . + "$LJ::SITENAMESHORT Team" + }); + + next; + + # just close -- shipping, coppa, etc + } else { + $close->(); + next; + } + } +}; + +$maint{'pay_lookupstates'} = sub +{ + require "$ENV{'LJHOME'}/cgi-bin/paylib.pl"; + require "$ENV{'LJHOME'}/cgi-bin/statslib.pl"; + + my $get_dbr = sub { + my @roles = ('slow'); + push @roles, ('slave', 'master') unless $LJ::STATS_FORCE_SLOW; + return LJ::get_dbh({raw=>1}, @roles) + or die "couldn't connect to database"; + }; + + my $dbr = $get_dbr->(); + + # see where we got to on our last run + my $min_payid = $dbr->selectrow_array("SELECT value FROM blobcache WHERE bckey='pay_lookupstates_pos'")+0; + my $max_payid = $dbr->selectrow_array("SELECT MAX(payid) FROM payments")+0; + my $to_do = $max_payid - $min_payid; + + print " -I- $to_do rows to process... "; + unless ($to_do) { + print "done\n\n"; + return; + } + print "\n"; + + # we'll call into LJ::Stats since it has handy functions + my $blocks = LJ::Stats::num_blocks($to_do); + + # get some userprop ids + my $propid = LJ::get_prop("user", "sidx_loc")->{id}; + + foreach my $block (1..$blocks) { + my ($low, $high) = LJ::Stats::get_block_bounds($block, $min_payid); + print LJ::Stats::block_status_line($block, $blocks); + + # make sure our database handles aren't stale + $LJ::DBIRole->clear_req_cache(); + $dbr = $get_dbr->() + or die "Couldn't connect to global db reader"; + + # find all payids that don't have a corresponding paystate row + my $rows = $dbr->selectall_arrayref + ("SELECT p.payid, p.userid FROM payments p " . + "LEFT JOIN paystates s ON s.payid=p.payid " . + "WHERE s.payid IS NULL AND p.userid > 0 " . + "AND p.payid BETWEEN $low AND $high"); + + next unless @$rows; # probably won't happen + + my %payids_of_userid = (); # userid => [ payids ] + foreach (@$rows) { + my ($payid, $userid) = @$_; + push @{$payids_of_userid{$userid}}, $payid; + } + my @userids = keys %payids_of_userid; + + my $userid_bind = join(",", map { "?" } @userids); + my $st_data = $dbr->selectall_arrayref + ("SELECT userid, value FROM userprop " . + "WHERE upropid=? AND userid IN ($userid_bind)", + undef, $propid, @userids); + + # save userprop data for setting later + my %state_of_userid = map { $_ => "??" } @userids; + foreach (@$st_data) { + my ($userid, $value) = @$_; + + my ($ctry, $st) = LJ::Pay::check_country_state((split("-", $value))[0,1]); + + # only care about states of 'US' + $state_of_userid{$userid} = $ctry || '??'; + $state_of_userid{$userid} .= "-" . ($st || '??') if $ctry eq 'US'; + } + + # save results in DB + my @vals = (); + my $bind = ""; + while (my ($userid, $state) = each %state_of_userid) { + foreach (@{$payids_of_userid{$userid}}) { + push @vals, $_ => $state; + $bind .= "(?,?),"; + } + } + chop $bind; + + my $dbh = LJ::get_db_writer(); + $dbh->do("REPLACE INTO paystates VALUES $bind", undef, @vals); + die "ERROR: " . $dbh->errstr if $dbh->err; + + # now save where we got to for subsequent runs + $dbh->do("REPLACE INTO blobcache (bckey, dateupdate, value) " . + "VALUES ('pay_lookupstates_pos', NOW(), ?)", + undef, $max_payid); + die "ERROR: " . $dbh->errstr if $dbh->err; + } + + # we're all done + print " -I- Processed $to_do rows... done\n\n"; +}; + +$maint{'pay_unreserve'} = sub +{ + use strict; + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + + print "Unreserving inventory...\n"; + + my $dbh = LJ::get_db_writer() + or die "couldn't get master db handle"; + + my $sth = $dbh->prepare(qq{ + SELECT pi.* FROM payitems pi, payments p + WHERE pi.payid=p.payid + AND pi.qty_res > 0 AND pi.status='cart' AND p.mailed='C' + AND ( + (p.method='cc' and p.datesent < DATE_SUB(NOW(), INTERVAL 3 DAY)) + OR + (p.datesent < DATE_SUB(NOW(), INTERVAL 12 DAY)) + ) + }); + die $dbh->errstr if $dbh->err; + $sth->execute; + + while (my $it = $sth->fetchrow_hashref) { + print "$it->{'piid'}: $it->{'item'} $it->{'subitem'} $it->{'qty_res'}\n"; + + $dbh->do("UPDATE inventory SET avail=avail+? WHERE item=? AND subitem=?", + undef, $it->{'qty_res'}, $it->{'item'}, $it->{'subitem'}); + die $dbh->errstr if $dbh->err; + + $dbh->do("UPDATE payitems SET qty_res=0 WHERE piid=?", undef, $it->{'piid'}); + die $dbh->errstr if $dbh->err; + } +}; + +$maint{'pay_shipping_notify'} = sub +{ + use strict; + require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + + die "no shipping email" + unless $LJ::SHIPPING_EMAIL; + die "no shipping contact email" + unless $LJ::SHIPPING_CONTACT_EMAIL; + + my $dbh = LJ::get_db_writer() + or die "couldn't get master db handle"; + + my ($ct, $min_date) = + $dbh->selectrow_array("SELECT COUNT(*), MIN(dateready) " . + "FROM shipping WHERE status='needs'"); + + LJ::send_mail({ + 'to' => $LJ::SHIPPING_EMAIL, + 'from' => $LJ::ADMIN_EMAIL, + 'fromname' => $LJ::SITENAME, + 'wrap' => 1, + 'charset' => 'utf-8', + 'subject' => "$ct Outstanding $LJ::SITENAME Merchandise Orders", + 'body' => + "There are currently $ct outstanding $LJ::SITENAME merchandise orders in need of shipping. " . + "The oldest of which became ready at $min_date.\n\n" . + + "Visit the following URL for details about currently outstanding orders. Please print all " . + "invoices and include a copy of each order's invoice with its shipment, which should be " . + "the cheaper of UPS Ground or FedEx Ground.\n\n" . + + " $LJ::SITEROOT/admin/accounts/shipping_labels.bml\n\n" . + + "As orders are shipped, please enter their order numbers at the following URL so that " . + "$LJ::SITENAME\'s cart system will be able to stop selling merchandise as supplies run out.\n\n" . + + " $LJ::SITEROOT/admin/accounts/shipping_finish.bml\n\n" . + + "Please contact $LJ::SHIPPING_CONTACT_EMAIL directly with any questions or problems.\n\n" . + + "Regards,\n" . + "$LJ::SITENAME Team\n", + }); + + print " -I- Emailed $LJ::SHIPPING_EMAIL\n\n"; +}; + +1; diff --git a/ljcom/bin/maint/stats-local.pl b/ljcom/bin/maint/stats-local.pl new file mode 100644 index 0000000..14097ab --- /dev/null +++ b/ljcom/bin/maint/stats-local.pl @@ -0,0 +1,45 @@ +#!/usr/bin/perl +# + +use strict; +use vars qw(%maint); + +$maint{'genstatslocal'} = sub +{ + my @which = @_; + + unless (@which) { @which = qw(singles); } + my %do = map { $_, 1, } @which; + + my %to_pop; + + LJ::load_props("user"); + + if ($do{'singles'}) { + my $dbr = LJ::get_db_reader(); + my $propid = $dbr->selectrow_array("SELECT upropid FROM userproplist WHERE name='single_status'"); + my $ct = $dbr->selectrow_array("SELECT COUNT(*) FROM userprop WHERE upropid=$propid"); + $to_pop{'singles'}->{'total'} = $ct; + } + + # copied from stats.pl: + my $dbh = LJ::get_db_writer(); + foreach my $cat (keys %to_pop) + { + print " dumping $cat stats\n"; + my $qcat = $dbh->quote($cat); + $dbh->do("DELETE FROM stats WHERE statcat=$qcat"); + if ($dbh->err) { die $dbh->errstr; } + foreach (sort keys %{$to_pop{$cat}}) { + my $qkey = $dbh->quote($_); + my $qval = $to_pop{$cat}->{$_}+0; + $dbh->do("REPLACE INTO stats (statcat, statkey, statval) VALUES ($qcat, $qkey, $qval)"); + if ($dbh->err) { die $dbh->errstr; } + } + } + + print "-I- Done.\n"; + +}; + +1; diff --git a/ljcom/bin/maint/syncweb.pl b/ljcom/bin/maint/syncweb.pl new file mode 100644 index 0000000..f838733 --- /dev/null +++ b/ljcom/bin/maint/syncweb.pl @@ -0,0 +1,247 @@ +#!/usr/bin/perl +# + +use Sys::Hostname; +use Digest::MD5; +use File::Copy; + +$maint{'syncsoon'} = sub +{ + if ($> == 0) { + print "Don't run this as root.\n"; + return 0; + } + open (F, ">/home/lj/var/do-syncweb"); + print F "this file flags to syncweb to sync later.\n"; + close F; + + print "Flag set.\n"; + return 1; +}; + +$maint{'syncweb'} = sub +{ + my $arg = shift; + + # update inc files on disk if necessary + if ($LJ::FILEEDIT_VIA_DB) { + my $syncfile = "$LJ::HOME/temp/last-fileedit-sync"; + open (F, $syncfile); + my $lasttime = ; + close F; + $lasttime += 0; + my $dbh = LJ::get_dbh("master"); + my $sth = $dbh->prepare("SELECT incname, inctext, updatetime FROM includetext ". + "WHERE updatetime > $lasttime"); + $sth->execute; + + my $newmax = 0; + while (my ($name, $text, $time) = $sth->fetchrow_array) { + if (open (F, ">$LJ::HOME/htdocs/inc/$name")) { + print F $text; + close F; + $newmax = $time if ($time > $newmax); + } + } + + if ($newmax) { + open (F, ">$syncfile"); + print F $newmax; + close F; + } + } + + return 1 if ($arg eq "norsync"); + + unless ($arg eq "now" || -e "/home/lj/var/do-syncweb") { + return 1; + } + + my $host = hostname(); + + if ($> == 0) { + print "Don't run this as root.\n"; + return 0; + } + if (`grep '/home nfs' /proc/mounts`) { + print "Don't run this on an NFS client.\n"; + return 0; + } + unless (chdir("/home/lj")) + { + print "Could not chdir to /home/lj\n"; + return 0; + } + + my @exclude = qw(/logs/ + /mail/ + /var/ + /backup/ + /cvs/ + /temp/ + /.ssh/ + /.ssh2/ + /.procmailrc + /htdocs/userpics + ); + my $excludes = join(" ", map { "--exclude='$_'"} @exclude); + + print "Syncing...\n"; + print `/usr/bin/rsync -avz --delete $excludes masterweb::ljhome/ .`; + + unlink "/home/lj/var/do-syncweb"; + print "Done.\n"; + return 1; +}; + +$maint{'syncmodules'} = sub +{ + my $host = hostname(); + + unless ($> == 0 || $< == 0) { + print "Must run this as root.\n"; + return 0; + } + + my %state; + my $STATE_FILE = "/home/lj/var/modstate.dat"; + my $LINK_DIR = "/home/lj/modules"; + my $BUILD_DIR = "/usr/build"; + my $changed = 0; # did state change? + + unless (-d $BUILD_DIR) { + print "Build directory ($BUILD_DIR) doesn't exist!\n"; + return 0; + } + + ### + ## load everything about what we did last + # + open (ST, $STATE_FILE); + while () { + chomp; + my ($file, $target, $status, $digest) = split(/\t/, $_); + $state{$file} = {'target' => $target, + 'status' => $status, + 'digest' => $digest, }; + } + close ST; + + ## look for all symlinks in the link dir. for each + ## try to install it if, 1) it points to someplace + ## that it didn't before, or 2) it failed before and + ## the md5 sum changed from last time. + + unless (chdir ($LINK_DIR)) { + print "Can't chdir to link directory: $LINK_DIR\n"; + return 0; + } + + unless (opendir (DIR, $LINK_DIR)) { + print "Can't open link directory: $LINK_DIR\n"; + return 0; + } + + LINKWHILE: + while (my $file = readdir(DIR)) + { + chdir $LINK_DIR; + next if (-d $file); + next unless (-l $file); + my $target = readlink($file); + + # FIXME: and check for weird characters? + # could be a problem if user lj is hacked, could be used to get + # root, if symlink goes somewhere odd. + next unless (-f $file); + + my $install = 0; + my $digest = ""; + + if ($target ne $state{$file}->{'target'}) { + $install = 1; + } elsif ($state{$file}->{'status'} eq "FAIL") { + $digest = Digest::MD5::md5_hex($target); + if ($digest ne $state{$file}->{'digest'}) { + $install = 1; + } + } + next unless ($install); + + # + # install it! + # + + print "Installing $file ($target)...\n"; + $digest ||= Digest::MD5::md5_hex($target); + $state{$file}->{'digest'} = $digest; + $state{$file}->{'target'} = $target; + $changed = 1; + + my $subdir; + open (CON, "tar ztf $target |"); + while () { + chomp; + unless (/^(\S+?)\//) { + warn "Target has no subdirectories it extracts from?\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + my $dir = $1; + $subdir ||= $dir; + if ($subdir ne $dir) { + warn "Target has multiple sub-directories.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + } + close CON; + + print "Sub-directory = $subdir\n"; + + if (system("tar zxvf $target -C $BUILD_DIR")) { + warn "Extraction failed.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + chdir "$BUILD_DIR/$subdir"; + if (system("perl Makefile.PL")) { + warn "makefile creation failed.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + if (system("make")) { + warn "make failed.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + if (system("make test")) { + warn "make test failed.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + if (system("make install")) { + warn "make install failed.\n"; + $state{$file}->{'status'} = "FAIL"; + next LINKWHILE; + } + + $state{$file}->{'status'} = "OK"; + + } + closedir (DIR); + + if ($changed) { + print "Writing state.\n"; + open (ST, ">$STATE_FILE"); + foreach (sort keys %state) { + print ST join("\t", + $_, + $state{$_}->{'target'}, + $state{$_}->{'status'}, + $state{$_}->{'digest'}), "\n"; + } + close ST; + } + +}; diff --git a/ljcom/bin/maint/taskinfo-local.txt b/ljcom/bin/maint/taskinfo-local.txt new file mode 100644 index 0000000..f16103b --- /dev/null +++ b/ljcom/bin/maint/taskinfo-local.txt @@ -0,0 +1,56 @@ +ljadmin.pl: + apgrace - gracefully restart apache + appss - stops apache-perl, waits, and starts again + sshkick - restarts ssh + appgrace - gracefully restart apache-perl + aprestart - restart apache + exposeconf - OLD: shows server's configuration to public + hupcaches - sends HUP signals to fastcgi processes so they clear their caches + load - prints load (the output of 'w') + date - prints date/time (the output of 'date') + restartapps - slowly restarts fastcgi processes + echo - echo arguments back + echosleep - sleeps for first arg seconds after echoing rest arguments back + debug - prints debug info + statscaster_restart - restart the ljstatscasterd + +expiring.pl: + expiring - Expire un-renewed paid accounts, and remind users with accounts soon to expire. + +interests.pl: + clean_intcounts - OLD: Migration tool. Used to define intcount when it was null. + clean_intdups - OLD: Remove duplicate interests (fixed. shouldn't happen anymore) + +dirsync.pl: + dirsync - Copies files from FTP area to web root + +aliases.pl: + makealiases - Adds the fixed aliases to the email_aliases table + +moods.pl: + makemoodindexes - Generate the index.html files in all the mood directories. + +pay.pl: + pay_mail - Sends out the email thanking people for their payment + pay_updateaccounts - Sets people's accounts to 'paid' if it's not already. + pay_lookupstates - Looks up and sets country/state info based on userprops + pay_unreserve - Unreserve inventory items that are over 3 days old and unclaimed + pay_shipping_notify - Notify third party shipping agent of new orders + +xplanet.pl: + stats_makemarkers - Make the markers.txt file to feed to xplanet + +syncweb.pl: + syncmodules - Install new local perl modules if needed, on master or slaves + syncweb - rsync files from master server (if given arg of "now", does it immediately) + syncsoon - set a flag so that the next syncweb actually syncs + +xfers.pl: + xfers_do - FTPs/SCPs people's journals to their webservers. + +stats-local.pl: + genstatslocal - Daily stats for ljcom code + +clean_caches-local.pl: + clean_caches_local - cleans old caches + diff --git a/ljcom/bin/maint/xfers.pl b/ljcom/bin/maint/xfers.pl new file mode 100644 index 0000000..f9e7b4d --- /dev/null +++ b/ljcom/bin/maint/xfers.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +# + +use Net::FTP; + +# FIXME: low priority. bitrot. never made public. + +$maint{'xfers_do'} = sub +{ + + my $dbh = LJ::get_db_writer(); + + print "-I- Loading users that need transfers...\n"; + $sth = $dbh->prepare("SELECT t.*, u.user, u.lastn_style FROM transferinfo t, user u WHERE t.userid=u.userid AND t.lastxfer < u.timeupdate AND t.state='on'"); + $sth->execute; + if ($dbh->err) { die $dbh->errstr; } + while ($ti = $sth->fetchrow_hashref) + { + print " ==> $ti->{'user'} ($ti->{'userid'})\n"; + my $styleid = $ti->{'styleid'} || $ti->{'lastn_style'}; + + my $localfile = "$LJ::TEMP/$ti->{'userid'}.xfer"; + open (TEMP, ">$localfile") or die ($!); + my $data = &make_journal_by_style($ti->{'user'}, $styleid, "", ""); + $data ||= "[LiveJournal: Bad username, styleid, or style definition]"; + print TEMP $data; + close TEMP; + + if ($ti->{'method'} eq "ftp") { + my $ftp = Net::FTP->new($ti->{'host'}); + $ftp->login($username, $ti->{'password'}); + $ftp->cwd($ti->{'directory'}); + $ftp->put($localfile, ($ti->{'filename'} || "livejournal.html")); + $ftp->quit; + } + elsif ($ti->{'method'} eq "scp") + { + my $username = $ti->{'username'}; + $username =~ s/[^a-zA-Z0-9\-\_]//g; + my $host = $ti->{'host'}; + $host =~ s/[^a-zA-Z0-9\-\.]//g; + my $directory = $ti->{'directory'}; + $directory =~ s/[^a-zA-Z0-9\_\-\. \/]//g; + my $filename = $ti->{'filename'}; + $filename =~ s/[^a-zA-Z0-9\_\-\. ]//g; + my $rc = system("scp $localfile \"$username\@$host:$directory/$filename\""); + print "Return: $rc\n"; + } + + } + +}; + +1; diff --git a/ljcom/bin/maint/xplanet.pl b/ljcom/bin/maint/xplanet.pl new file mode 100644 index 0000000..63078c0 --- /dev/null +++ b/ljcom/bin/maint/xplanet.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +# + +$maint{'stats_makemarkers'} = sub +{ + my $dbr = LJ::get_db_reader(); + + my ($sth); + + open (MARK, ">${STATSDIR}/markers.txt"); + + # FIXME: this is broken. zip is a userprop now. + $sth = $dbr->prepare("CREATE TEMPORARY TABLE tmpmarkzip SELECT DISTINCT zip FROM user WHERE country='US' and zip<>''"); + $sth->execute; + $sth = $dbr->prepare("SELECT z.lon, z.lat FROM zips z, tmpmarkzip t WHERE t.zip=z.zip"); + $sth->execute; + while (my ($lon, $lat) = $sth->fetchrow_array) { + print MARK "$lat -$lon \"\" color=white # \n"; + } + $sth->finish; + close (MARK); +}; + +1; diff --git a/ljcom/bin/makemoodindex.pl b/ljcom/bin/makemoodindex.pl new file mode 100755 index 0000000..a45b370 --- /dev/null +++ b/ljcom/bin/makemoodindex.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# + +my $dir = shift @ARGV; +unless ($dir || -d $dir) { + die "Usage:\n makemoodindex.pl

    \n"; +} + +print "Making mood index for $dir\n"; + +@colors = qw(ffffff 333333 663300 ff9900 ffff33 00ff00 006600 009999 0066cc 9900cc ff3399 ff0000 + cccccc 000000 cccc99 ffcc99 ffffcc ccffcc 339933 99ffff 99ccff cc99ff ff99cc ffcccc); + +opendir (DIR, $dir); +@files = readdir DIR; +closedir DIR; + +if (-e "$dir/index.html") { + open (HTML, "$dir/index.html"); + my $line = ; + chomp $line; + unless ($line eq "") { die "Won't overwrite index.html in this directory!\n"; } +} + +open (HTML, ">$dir/index.html"); +print HTML "\n"; +print HTML "\n"; + +print HTML <<"CHOOSER_HEADER"; +
    + +•• click for background color •• + +
    +
    + + +CHOOSER_HEADER + + my $count = 0; + foreach my $col (@colors) { + if (++$count == 13) { print HTML "\n\n"; } + print HTML "\n"; + + } +print HTML "
    \n\n"; + +foreach my $file (sort @files) +{ + next unless (-d "$dir/$file" && $file ne "."); + print HTML "
    $file/
    \n"; +} + +print HTML "\n"; +foreach my $file (sort @files) +{ + next unless ($file =~ /\.gif$/); + + print HTML ""; + print HTML ""; + print HTML "\n"; +} + +print HTML "
    $file
    \n"; diff --git a/ljcom/bin/mcvsui.pl b/ljcom/bin/mcvsui.pl new file mode 100755 index 0000000..53a23a1 --- /dev/null +++ b/ljcom/bin/mcvsui.pl @@ -0,0 +1,803 @@ +#!/usr/bin/perl -w + +# * Diff selected files. +# +# * Push selected files live. +# +# * Invoke $EDITOR and parse the resulting output, selecting all files which +# match. +# +# * Deselect all files. +# +# + +package MultiCvsUI; +use strict; + +BEGIN { + # Versioning stuff and custom includes + use vars qw{$VERSION $RCSID}; + + $VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + $RCSID = q$Id: mcvsui.pl,v 1.3 2004/04/21 00:19:14 deveiant Exp $; + + if ( ! $ENV{HOME} || ! -d $ENV{HOME} ) { + die "LJHOME not set or invalid"; + } + use lib ("$ENV{LJHOME}/cgi-bin", "$ENV{LJHOME}/cvs/wcmtools/lib"); + + use Carp qw{confess croak}; + use Curses::UI qw{}; + use Cwd qw{getcwd}; + use Data::Dumper qw{}; + use IO::File qw{}; + use IO::Handle qw{}; + use List::Util qw{max min}; + use File::Temp qw{tempfile tempdir}; + use File::Spec qw{}; + use Fcntl qw{SEEK_SET}; + + use MultiCVS qw{}; + + $Data::Dumper::Indent = 1; + $Data::Dumper::Terse = 1; +} + + +our ( $MultiCvsConf, $GoLive, %Keynames, %WindowOptions, %KeyBindings ); + +# The path to the multicvs config +$MultiCvsConf = $ENV{LJHOME} . "/cvs/multicvs.conf"; + +# The path to the golive program +$GoLive = $ENV{LJHOME} . "/bin/golive"; + +# Map of keys to human-readable names for onscreen keybinding documentation +%Keynames = ( + "\t" => "", + "\n" => "", + "\e" => "", +); + + +%WindowOptions = ( + mainWindow => [ + mainWindow => 'Window', + -title => "MultiCVS UI $VERSION", + -titlereverse => 0, + -border => 1, + #-padbottom => 5, + ], + + selectionList => [ + selList => 'Listbox', + -multi => 1, + -values => [], + -labels => {}, + -border => 1, + -vscrollbar => 1, + -htmltext => 1, + -ipadleft => 2, + -ipadright => 2, + -ipadtop => 1, + -ipadbottom => 1, + -padbottom => 5, + ], + + helpPane => [ + '' => 'Label', + -border => 0, + -width => -1, + #-height => -1, + -y => -1, + -ipad => 1, + -paddingspaces => 1, + ], + + logWindow => [ + logWindow => 'Window', + -title => 'Log', + -border => 1, + -titlereverse => 0, + -padtop => 2, + -padleft => 1, + -padright => 1, + -padbottom => 6, + -ipad => 1, + ], + + logViewer => [ + logViewer => 'TextViewer', + title => "Log", + -text => "", + -wrapping => 1, + ], + + pagerWindow => [ + pagerWindow => 'Window', + -title => "Pager", + -border => 1, + -titlereverse => 0, + -padtop => 2, + -padleft => 1, + -padright => 1, + -padbottom => 6, + -ipad => 1, + ], + + pager => [ + pager => 'TextViewer', + -text => "", + -wrapping => 0, + -showoverflow => 1, + ], + + applyDialog => [ + applyDialog => "Dialog::Basic", + -title => "Apply", + -message => "Command? (d)iff, (g)olive, (u)nmark", + -buttons => ['cancel'], + ], +); + +# App keybindings +%KeyBindings = ( + + # 'l': Switch focus to the log viewer + "l" => { + desc => "Show/hide the log", + handler => "showLog", + applyable => 0, + }, + + # 'a': Apply (aggregate) next command + a => { + desc => "Apply", + handler => "applyCommand", + applyable => 0, + }, + + # 'd': Show diffs for current selection + d => { + desc => "Diff", + handler => "showDiff", + applyable => 1, + }, + + # 'g': Push files up to the live site + g => { + desc => "Golive", + handler => "pushFilesLive", + applyable => 1, + }, + + # 'e': Edit the list of selected files + e => { + desc => "Edit Selection", + handler => "editSelection", + applyable => 0, + }, + + # 'u': Unmark all selected files + u => { + desc => "Unmark All", + handler => "unmarkAll", + applyable => 1, + }, + +); + + + +##################################################################### +### M A I N B O D Y +##################################################################### + +### (CLASS) METHOD: new( undef ) +### Instantiate and return a new CvsReportShell. +sub new { + my $proto = shift; + my $class = ref $proto || $proto; + + my $self = bless { + mainWindow => undef, # Main enclosing window + selList => undef, # Selection list (holds files) + logWindow => undef, # Logging window + logViewer => undef, # Log viewer window + pagerWindow => undef, # Pager top-level window + pager => undef, # Pager scrolling container + + display => 'cvs', # Display 'cvs', 'live', or 'both' updates? + + _log => undef, + }, $class; + + # Open the logfile and append to it. + open $self->{_log}, ">>mcvsui.log" or die "Failed to open log: $!"; + $self->logmsg( "\n\n>>> Starting shell at %s\n\n", scalar localtime ); + + # Get the interface object to the multicvs layout + die "Cannot find multicvs.conf: Is your \$LJHOME set correctly?\n" + unless -e $MultiCvsConf; + $self->{multicvs} = new MultiCVS ($MultiCvsConf) + or die "Failed to create multicvs interface"; + + # Create the UI object + $self->{ui} = new Curses::UI( -color_support => 0 ); + $self->setupWindows; + + # Circular reference: Be sure to break this association if the object needs + # to be destroyed. + $self->{ui}->userdata( $self ); + + return $self; +} + + +### METHOD: run( undef ) +### Run the shell. +sub run { + my $self = shift or confess "Cannot be used as a function"; + + my ( + %bindings, + @keydocs, + ); + + $self->logmsg( "Running the shell." ); + + # Global keybindings + $self->{ui}->set_binding( sub {$self->exitDialog}, "\cq" ); + $self->{ui}->set_binding( sub {$self->exitDialog}, "\cc" ); + + # Log viewer keybindings + $self->{logViewer}->set_binding( sub {$self->{selList}->focus}, "\t" ); + + # Add a binding and documentation for each key + foreach my $key ( keys %KeyBindings ) { + my $code; + + # Either build a callback to invoke the handler by name or use an + # explicit CODE ref if present + if ( ! exists $KeyBindings{$key}{code} ) { + my $method = $KeyBindings{$key}{handler}; + $code = sub { $self->$method() }; + } else { + $code = $KeyBindings{$key}{code}; + } + + $self->{selList}->set_binding( $code, $key ); + } + + # List the keybindings in the help window + $self->makeHelpPane( \%KeyBindings ); + + # Read cvsreport's output and put it in the selectlist + $self->populateSelectionList; + + # Start the main event loop + $self->{selList}->focus; + $self->{ui}->mainloop; +} + + +### METHOD: showLog( undef ) +### Show the log viewer window. +sub showLog { + my $self = shift or confess "Cannot be used as a function"; + $self->{logViewer}->focus; +} + + +### METHOD: applyCommand( undef ) +### Apply a command to all selected files. +sub applyCommand { + my $self = shift or confess "Cannot be used as a function"; + my $list = $self->{selList}; + my @selections = $list->get; + + my $dialog = $self->{ui}->add( @{$WindowOptions{applyDialog}} ); + + # Add a binding and documentation for each key + foreach my $key ( keys %KeyBindings ) { + next unless $KeyBindings{$key}{applyable}; + my $code; + + # Either build a callback to invoke the handler by name or use an + # explicit CODE ref if present + if ( ! exists $KeyBindings{$key}{code} ) { + # Call the handler with a true value to set 'apply mode' + my $method = $KeyBindings{$key}{handler}; + $code = sub { + $dialog->lose_focus; + $self->$method(1); + }; + } else { + $code = sub { + $dialog->lose_focus; + $KeyBindings{$key}{code}->(1); + }; + } + + $dialog->set_binding( $code, $key ); + } + + $dialog->set_binding( sub {}, "\e" ); + + $dialog->modalfocus; + $dialog->lose_focus; + $self->{ui}->delete( $WindowOptions{applyDialog}[0] ); +} + + +### METHOD: makeHelpPane( \%KeyBindings ) +### Given a hashref of keybindings, write the list of documentation for them to +### the help window. +sub makeHelpPane { + my $self = shift or throw Exception::MethodError; + my $bindings = shift or return (); + + my ( + @keydocs, + $keyhelp, + $cols, + $colwidth, + $colpat, + $rows, + $helptext, + $curcol, + ); + + $self->logmsg( "Building keyhelp" ); + + $colwidth = 0; + foreach my $key ( keys %$bindings ) { + #$self->logmsg( "Generating key help for %s: %s", $key, $bindings->{$key} ); + if ( exists $Keynames{$key} ) { + $keyhelp = sprintf( '%5s %s', $Keynames{$key}, $bindings->{$key}{desc} ); + } else { + $keyhelp = sprintf( ' <%s> %s', $key, $bindings->{$key}{desc} ); + } + + push @keydocs, $keyhelp; + $colwidth = length $keyhelp if length $keyhelp > $colwidth; + } + + # Make all the column widths the same by padding with spaces. + $colpat = "\%${colwidth}s"; + @keydocs = map { sprintf $colpat, $_ } @keydocs; + + # Calculate columns and rows + $cols = int( $self->{helpPane}->canvaswidth / $colwidth + 2 ); + $rows = min( (int(scalar @keydocs / $cols) || 1), $self->{helpPane}->canvasheight ); + return () if $cols < 1 || $rows < 1; + + # Build the actual text rows + $helptext = ''; + foreach my $row ( 0 .. ($rows - 1) ) { + $curcol = $cols * $row; + $helptext .= " " . join(' ', @keydocs[$curcol .. $curcol + $cols]) . " \n"; + } + + $self->{helpPane}->text( $helptext ); +} + + + +### METHOD: editSelection( @items ) +### Edit the list of the selected items as text, making any changes necessary to +### reflect the changes made in the file. +sub editSelection { + my $self = shift or confess "Cannot be used as a function"; + my $list = $self->{selList}; + my @items = $list->get; + my @newItems = $self->forkEditor( join("\n", @items) . "\n" ); + + # Explode space-separated lines into multiple entries, discarding null + # entries. + @newItems = grep { defined } map { split /(?!<\\)\s+/, $_ } @newItems; + #$self->logmsg( "Got modified selection list: %s", \@newItems ); + + $self->populateSelectionList( @newItems ); +} + + +### METHOD: pushFilesLive( @files ) +### Ask the golive script to publish the specified I. +sub pushFilesLive { + my $self = shift or confess "Cannot be used as a function"; + my $applyMode = shift || 0; + + my $list = $self->{selList}; + my @files = (); + + if ( $applyMode ) { + @files = $list->get; + } else { + @files = ( $list->get_active_value ); + } + + $self->{ui}->status( sprintf("Pushing %d files live.", scalar @files) ); + my @output = $self->forkRead( $GoLive, @files ); + $self->logmsg( "Output from golive:\n%s", join('', @output) ); + $self->{ui}->nostatus; + + $self->populateSelectionList; +} + + +### METHOD: unmarkAll( undef ) +### Unmark all marked files. +sub unmarkAll { + my $self = shift or confess "Cannot be used as a function"; + + $self->{selList}->clear_selection; + $self->populateSelectionList; +} + + +### METHOD: showDiff( @files ) +### Ask cvsreport for a diff and display it in the pager window. +sub showDiff { + my $self = shift or confess "Cannot be used as a function"; + my $applyMode = shift || 0; + + my $list = $self->{selList}; + my @files = (); + + if ( $applyMode ) { + @files = $list->get; + } else { + @files = ( $list->get_active_value ); + } + + $self->logmsg( "Got list of files to diff: %s", \@files ); + + # Slice out just the tuples that are needed for the diff + my @tuples = @{$self->{changes}}{ @files }; + $self->logmsg( "Got list of tuples for files to diff: %s", \@tuples ); + + # Get unified diffs + #$self->{multicvs}{_debug} = 1; + my @diffs = $self->{multicvs}->get_diffs( ['-u'], @tuples ); + #$self->{multicvs}{_debug} = 0; + $self->logmsg( "Got diffs: %s", \@diffs ); + + my $title = sprintf( "Differences (%d files)", scalar @files ); + $self->showPager( $title, @diffs ); +} + + +### METHOD: showPager( $text ) +### Fork an instance of the user's pager as defined by C<$PAGER> and pipe the +### given I to it after temporarily leaving curses mode. +sub showPager { + my $self = shift or confess "Cannot be used as a function"; + my $title = shift; + my $text = join '', @_; + + # If they have a pager configured, use that to display the output + if ( ($ENV{PAGER} || $ENV{MCVSUI_PAGER}) && $ENV{MCVSUI_PAGER} ne 'builtin' ) { + $self->forkWrite( $text, $ENV{MCVSUI_PAGER}||$ENV{PAGER} ); + } + + # Otherwise use the built-in page + else { + $self->{pagerWindow}->title( $title || 'Pager' ); + $self->{pager}->text( $text ); + $self->{pager}->focus; + } +} + + + + +# 'htdocs/site/free.bml' => { +# 'cvs_time' => 1075506514, +# 'to' => '/Library/LiveJournal/cvs/local/htdocs/site/free.bml', +# 'type' => 'l', +# 'from' => '/Library/LiveJournal/htdocs/site/free.bml', +# 'module' => 'local', +# 'live_time' => 1075935006 +# }, + + +### METHOD: populateSelectionList( @selected ) +### Run cvsreport and populate the selectlist with the files which are reported +### as actionable. Files in I will be pre-selected. +sub populateSelectionList { + my $self = shift or confess "Cannot be used as a function"; + my @selected = @_; + + my ( + $maxlength, + $changes, + @displayKeys, + @values, + %labels, + %selectPositions, + $count, + ); + + $changes = $self->{multicvs}->find_changed_files; + + # Get the list of relpaths to display based on the current view mask + @displayKeys = grep { + $self->{display} eq 'both' + or + ( $self->{display} eq 'cvs' && $changes->{$_}{type} eq 'c' ) + or + $self->{display} eq 'live' + } sort keys %$changes; + + $self->logmsg( "Selected %d '%s' changes of %d total", + scalar @displayKeys, + $self->{display}, + scalar keys %$changes ); + + # If there were changes to list, list 'em + if ( @displayKeys ) { + $maxlength = max map { length $_ } @displayKeys; + + $self->logmsg( "Got %d items to set in the select list.", scalar @displayKeys ); + $count = 0; + + # For each file cvsreport says needs moving, add the filename to the + # list of raw items, make a label for display purposes, and note the + # item's position so it can be highlighted later. + foreach my $relpath ( @displayKeys ) { + $labels{ $relpath } = + sprintf( "%-*s [%s]", $maxlength, $relpath, + $changes->{$relpath}{module} ); + $selectPositions{ $relpath } = $count; + $count++; + } + + # Stuff the items into the select list. Merge the selected item + # filenames with the map of their indexes. + $self->logmsg( "Setting the select list to: %s", \@displayKeys ); + $self->{changes} = $changes; + $self->{selList}->values( \@displayKeys ); + $self->{selList}->labels( \%labels ); + $self->{selList}->set_selection( @selectPositions{@selected} ); + $self->{selList}->title( scalar @displayKeys . " Pending Files" ); + } else { + $self->{changes} = undef; + $self->{selList}->values(); + $self->{selList}->labels( {} ); + $self->{selList}->set_selection(); + $self->{selList}->title( "No Pending Files" ); + } +} + + +### METHOD: logmsg( $fmt, @args ) +### Write a message to a logfile and to the log window if it's been created +### already. The I is a C-style output format, and I is a +### list of arguments to the C call, with the additional functionality +### of dumping references instead of just stringifying them as-is for C<%s>. +sub logmsg { + my $self = shift or confess "Can't be used as a function"; + my ( $format, @args ) = @_; + + chomp( $format ); + $format .= "\n"; + + for ( my $i = 0; $i <= $#args; $i++ ) { + next unless ref $args[$i]; + $args[$i] = Data::Dumper->Dumpxs( [$args[$i]], [qw{$i}] ); + } + + $self->{_log}->printf( $format, @args ) if $self->{_log}; + $self->appendToLogWindow( sprintf($format, @args) ); +} + + +### METHOD: appendToLogWindow( $text ) +### Append the specified I to the log window if it's been created already. +sub appendToLogWindow { + my $self = shift or confess "Cannot be used as a function"; + my $text = shift; + + my $lv = $self->{logViewer} or return (); + $lv->text( $lv->get . $text ); + $lv->cursor_to_end; +} + + +### METHOD: forkRead( $cmd, @args ) +### Fork and exec the specified I, giving it the specified I, and +### return the output of the command as a list of lines. +sub forkRead { + my $self = shift or confess "Cannot be used as a function"; + my ( $cmd, @args ) = @_; + + my ( + $fh, + @lines, + $pid, + ); + + #$self->logmsg( "Reading from a forked child." ); + + # Fork-open and read the child's output as the parent + if (( $pid = open($fh, "-|") )) { + @lines = <$fh>; + $fh->close; + } + + # Child - capture output for diagnostics and progress display stuff. + else { + die "Couldn't fork: $!" unless defined $pid; + $self->{ui}->clear_on_exit( 0 ); + + open STDERR, ">&STDOUT" or die "Can't dup stdout: $!"; + { exec $cmd, @args }; + + # Only reached if the exec() fails. + close STDERR; + close STDOUT; + exit 1; + } + + #$self->logmsg( "Read %d lines from '%s'", scalar @lines, $cmd ); + return @lines; +} + + +### METHOD: forkWrite( $output, $cmd, @args ) +### Fork and exec the specified I with the specified I and +### print the given I to it. +sub forkWrite { + my $self = shift or confess "Cannot be used as a function"; + my ( $output, $cmd, @args ) = @_; + + my ( + $fh, + $pid, + ); + + $self->logmsg( "Leaving curses..." ); + $self->{ui}->leave_curses; + + # Fork-open and read the child's output as the parent + if (( $pid = open($fh, "|-") )) { + print $fh $output; + $fh->close; + } + + # Child - capture output for diagnostics and progress display stuff. + else { + die "Couldn't fork: $!" unless defined $pid; + + { exec $cmd, @args }; + + # Only reached if the exec() fails. + exit 1; + } + + $self->{ui}->reset_curses; + $self->logmsg( "Curses restored." ); +} + + +### METHOD: forkEditor( $content ) +### Write the given I to a tempfile and invoke $ENV{EDITOR} on it, +### returning whatever was left in it after the editor returns. +sub forkEditor { + my $self = shift or confess "Cannot be used as a function"; + my $content = shift || ''; + + my ( + $editor, + $tempdir, + $tempfile, + $fname, + $fh, + $pid, + @rlines, + ); + + # Pick the editor based on the environment or a sensible default + $editor = $ENV{EDITOR} || $ENV{VISUAL} || 'vi'; + + # Pick a temporary directory on this platform + $tempdir = File::Spec->tmpdir; + + # Open a tempfile and write the conte to it + ( $tempfile, $fname ) = tempfile( "mcvsui.XXXXX", DIR => $tempdir ); + $self->logmsg( "Writing %d bytes to '%s'", length $content, $fname ); + $tempfile->print( $content ); + $tempfile->close; + + # Switch off curses + $self->logmsg( "Leaving curses..." ); + $self->{ui}->leave_curses; + + # Invoke the editor on the tempfile + unless ( system($editor, $fname) == 0 ) { + die "Could not invoke '$editor': Error $?\n\n"; + } + + # Restore the curses ui + $self->{ui}->reset_curses; + $self->logmsg( "Curses restored." ); + + # Rewind and re-read the tempfile back in + $tempfile = new IO::File( $fname, "r" ) + or die "open: $fname: $!"; + @rlines = <$tempfile>; + $tempfile->close; + unlink $fname if -e $fname; + + chomp( @rlines ); + $self->logmsg( "Read in:\n%s", \@rlines ); + + return @rlines; +} + + +### METHOD: setupWindows( undef ) +### Set up all the initial windows. +sub setupWindows { + my $self = shift or confess "Cannot be used as a function"; + + # Create the main window + $self->{mainWindow} = $self->{ui}->add( @{$WindowOptions{mainWindow}} ); + $self->{selList} = $self->{mainWindow}->add( @{$WindowOptions{selectionList}} ); + $self->{helpPane} = $self->{mainWindow}->add( @{$WindowOptions{helpPane}} ); + $self->logmsg( "Created main window." ); + + # Create the log window at the bottom of the screen and put a text viewer in + # it. + $self->{logWindow} = $self->{ui}->add( @{$WindowOptions{logWindow}} ); + $self->{logViewer} = $self->{logWindow}->add( @{$WindowOptions{logViewer}} ); + $self->{logViewer}->set_binding( sub {$self->{mainWindow}->focus} => 'q' ); + $self->logmsg( "Created log window." ); + + # Create the pager window and widget + $self->{pagerWindow} = $self->{ui}->add( @{$WindowOptions{pagerWindow}} ); + $self->{pager} = $self->{pagerWindow}->add( @{$WindowOptions{pager}} ); + $self->{pager}->set_binding( sub {$self->{mainWindow}->focus} => "q" ); + $self->logmsg( "Create the pager window." ); + +} + + +### METHOD: exitDialog( undef ) +### Display an confirmation dialog and quit if the user confirms. +sub exitDialog { + my $self = shift or confess "Cannot be used as a function"; + + exit( 0 ); + #my $return = $self->{ui}->dialog( + # -message => "Really quit?", + # -title => "Confirm", + # -buttons => ['yes', 'no'], + # ); + # + #exit(0) if $return; +} + + + + + + + +##################################################################### +### C L E A N U P +##################################################################### +END { + #Cdk::end(); +} + + + +package mcvsui; +use strict; + +open STDERR, ">err.out" or die "open: STDERR: $!"; + +my $sh = new MultiCvsUI; +$sh->run; diff --git a/ljcom/bin/misc/fixuu.pl b/ljcom/bin/misc/fixuu.pl new file mode 100755 index 0000000..3264b15 --- /dev/null +++ b/ljcom/bin/misc/fixuu.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +my $dbh = LJ::get_db_writer(); +my $dbslo = LJ::get_dbh("slow"); +die "no slow" unless $dbslo; + +my $sth = $dbslo->prepare("select u.userid from user u left join userusage uu on u.userid=uu.userid where uu.userid is null"); +$sth->execute; +while (my $userid = $sth->fetchrow_array) +{ + print "$userid...\n"; + my $u = LJ::load_userid($userid); + die unless $u; + + print "Find timeupdate...\n"; + my $timeupdate; + my $dbcr = LJ::get_cluster_reader($u); + $timeupdate = $dbcr->selectrow_array("SELECT logtime FROM log2 WHERE journalid=$u->{'userid'} AND rlogtime>0 ORDER BY journalid, rlogtime"); + die $dbcr->errstr if $dbcr->err; + $timeupdate = $dbh->quote($timeupdate); + + print "BS a time create...\n"; + my $timecreate; + my $puserid = $u->{'userid'}; + while (not defined $timecreate) { + $puserid--; + print " trying $puserid\n"; + $timecreate = $dbslo->selectrow_array("SELECT DATE_ADD(timecreate, INTERVAL 10 MINUTE) FROM userusage WHERE userid=$puserid"); + } + $timecreate = $dbh->quote($timecreate); + + my $sql = "INSERT INTO userusage VALUES ($u->{'userid'}, $timecreate, $timeupdate, NULL, 0)"; + print "$sql\n"; + $dbh->do($sql); +} diff --git a/ljcom/bin/multideb b/ljcom/bin/multideb new file mode 100755 index 0000000..a36041c --- /dev/null +++ b/ljcom/bin/multideb @@ -0,0 +1,250 @@ +#!/usr/bin/perl +# +# multideb - compare package installation differences over +# many machines remotely. +# +# example ~/.multideb.conf file: +# +# servera port=2210 user=bob classes=web,db +# serverb user=root classes=web +# serverc user=root classes=web +# serverd user=mysql classes=db +# localhost classes=web +# +# Port 22 is the default. User required unless servername is localhost. +# + +use strict; +use Getopt::Long; +use Data::Dumper; + +my $MD_DIR = ensure_dir("$ENV{'HOME'}/.multideb"); + +my %host; # hostname -> {..., classes => { classname => 1 } } +my %classes; # classname -> { hostname => 1 } +my %core; # classname -> [ packagename, ... ] + +my $opt_full = 0; +my $opt_core = 0; +help() unless GetOptions( + "full" => \$opt_full, + "core" => \$opt_core, + ); + +my $mode = shift @ARGV; + +if ($mode eq "check") +{ + load_conf(); + my @pkgs = @ARGV; + my @hosts = sort keys %host; + + foreach my $host (@hosts) { + my $h = $host{$host}; + parse_status($h); + } + + foreach my $pkg (@pkgs) + { + my %whowhat; + foreach my $host (@hosts) { + my $h = $host{$host}; + my $p = $h->{'pkg'}->{$pkg}; + + my $status = status_of_package($p); + push @{$whowhat{$status}}, $host; + } + + print "$pkg\n"; + foreach my $stat (sort keys %whowhat) { + print " $stat: @{$whowhat{$stat}}\n"; + } + } + + exit 0; +} + +if ($mode eq "compare") +{ + load_conf(); + my $class = shift @ARGV; + my @hosts = sort keys %{$classes{$class}}; + + unless (@hosts) { + die "No matching '$class' hosts.\n"; + } + + my @comp_list; + + my %epkg; # existing packages: { name => 1 } + foreach my $host (@hosts) + { + my $h = $host{$host}; + parse_status($h); + foreach (keys %{$h->{'pkg'}}) { + $epkg{$_} = 1; + } + } + + if ($opt_core) { + unless (defined $core{$class}) { + die "No core packages defined for class '$class'\n"; + } + @comp_list = @{$core{$class}}; + } else { + @comp_list = sort keys %epkg; + } + + # iterate through all packages, showing differences: + foreach my $pkg (@comp_list) + { + my %whowhat; + my $installed = 0; + foreach my $host (@hosts) { + my $h = $host{$host}; + my $p = $h->{'pkg'}->{$pkg}; + + my $status = status_of_package($p); + push @{$whowhat{$status}}, $host; + + my ($sa, $sb, $sc) = split(/ /, $p->{'Status'}); + if ($sc eq "installed") { $installed = 1; } + } + if ($installed && + ($opt_full || scalar(keys %whowhat) > 1)) + { + print "$pkg\n"; + foreach my $stat (sort keys %whowhat) { + print " $stat: @{$whowhat{$stat}}\n"; + } + } + } + + exit 0; +} + +if ($mode eq "update") +{ + load_conf(); + foreach my $host (sort keys %host) + { + my $h = $host{$host}; + my $user = $h->{'user'}; + my $port = $h->{'port'}; + + print "$host...\n"; + if ($host eq "localhost") { + system("rsync", "/var/lib/dpkg/status", + "$MD_DIR/$host.status"); + } else { + system("rsync", "-e", "ssh -p $port", "-az", + "$user\@$host:/var/lib/dpkg/status", + "$MD_DIR/$host.status"); + } + } + + print "Done.\n"; + exit 0; +} + +help(); + +sub status_of_package +{ + my $p = shift; + + my $status = $p->{'Version'}; + if ($p->{'Status'} ne "install ok installed") { + $status .= "/" if $status; + $status .= "$p->{'Status'}"; + } + $status ||= "(unknown)"; + + return $status; +} + +sub parse_status +{ + my $h = shift; + my $fname = "$MD_DIR/$h->{'host'}.status"; + unless (-e $fname) { + die "$fname doesn't exist. Run update.\n"; + } + open (F, $fname); + while () { + unless (/^Package: (.+)/) { + die "Corrupt $h->{'host'} status file?\n"; + } + my $pkg = $1; + my $p = $h->{'pkg'}->{$pkg} = { + 'Package' => $pkg, + }; + my $lastkey = 'Package'; + while () { + chomp; + unless ($_) { last; } + if (/^(\w+):\s*(.+)/i) { + $p->{$1} = $2; + } + } + } + close F; +} + +sub help +{ + die("Usage:\n". + " multideb update\n". + " multideb compare \n". + " multideb check ...\n"); +} + +sub load_conf { + open (C, "$ENV{'HOME'}/.multideb.conf"); + while () + { + s/^\s+//; s/\s+$//; + next if (/^\#/); + next unless $_; + chomp; + my ($p1, @opts) = split(/\s+/, $_); + + if ($p1 =~ /^core:(\w+)/) { + $core{$1} = [ @opts ]; + next; + } + + my $host = $p1; + my $h = $host{$host} = { + 'host' => $host, + 'port' => 22, + }; + foreach (@opts) { + my ($k, $v) = split(/=/, $_); + if ($k eq "classes") { + foreach (split(/,/, $v)) { + $h->{'classes'}->{$_} = 1; + $classes{$_}->{$host} = 1; + } + } else { + $h->{$k} = $v; + } + } + } + close C; +} + +sub ensure_dir { + my $dir = shift; + unless (-e $dir) { + if (mkdir $dir) { + return $dir; + } else { + die "Can't create $dir directory\n"; + } + } + unless (-w $dir) { + die "Can't write to $dir directory\n"; + } + return $dir; +} diff --git a/ljcom/bin/mytop.pl b/ljcom/bin/mytop.pl new file mode 100755 index 0000000..bf209af --- /dev/null +++ b/ljcom/bin/mytop.pl @@ -0,0 +1,1019 @@ +#!/usr/bin/perl -w +# +# $Id: mytop.pl,v 1.2 2002/02/11 05:48:56 bradfitz Exp $ + +=pod + +=head1 NAME + +mytop - display MySQL server performance info like `top' + +=cut + +use 5.004; +use strict; +use DBI; +use Getopt::Long; +use Term::ReadKey; + +$|++; + +## Test for color support. + +eval { require Term::ANSIColor; }; + +my $HAS_COLOR = $@ ? 0 : 1; + +## Try to lower our priority (which, who, pri) + +setpriority(0,0,10); + +## Default Config Values + +my %config = ( + delay => 5, + host => 'localhost', + db => 'test', + user => 'root', + pass => '', + port => 3306, + socket => '', + batchmode => 0, + header => 1, + color => 1, + ); + +my $CLEAR = `clear`; + +my $VERSION = "0.3"; + +## Term::ReadKey values + +my $RM_RESET = 0; +my $RM_NOBLKRD = 3; ## using 4 traps Ctrl-C :-( + +## Read the user's config file, if it exists. + +my $config = "$ENV{HOME}/.mytop"; + +if (-e $config) +{ + if (open CFG, "<$config") + { + while () + { + next if /^\s*$/; ## skip blanks + next if /^\s*#/; ## skip comments + + chomp; + + if (/(\S+)\s*=\s*(\S+)/) + { + $config{lc $1} = $2 if exists $config{lc $1}; + } + } + + close CFG; + } +} + +## Command-line args. + +use vars qw($opt_foo); + +GetOptions( "color!" => \$config{color}, + "user|u=s" => \$config{user}, + "pass|p=s" => \$config{pass}, + "database|db|d=s" => \$config{db}, + "host|h=s" => \$config{host}, + "port=i" => \$config{port}, + "socket|S=s" => \$config{socket}, + "delay|s=i" => \$config{delay}, + "batch|batchmode|b!" => \$config{batchmode}, + "header!" => \$config{header}, + ); + +## User may have put the port with the host. + +if ($config{host} =~ s/:(\d+)$//) +{ + $config{port} = $1; +} + +## User may want to disable color. + +if ($HAS_COLOR and not $config{color}) +{ + $HAS_COLOR = 0; +} + +if ($HAS_COLOR) +{ + import Term::ANSIColor ':constants'; +} +else +{ + *RESET = sub { }; + *YELLOW = sub { }; + *RED = sub { }; + *GREEN = sub { }; + *BLUE = sub { }; + *WHITE = sub { }; + *BOLD = sub { }; +} + +my $RESET = RESET() || ''; +my $YELLOW = YELLOW() || ''; +my $RED = RED() || ''; +my $GREEN = GREEN() || ''; +my $BLUE = BLUE() || ''; +my $WHITE = WHITE() || ''; +my $BOLD = BOLD() || ''; + +## Connect + +my $dsn; + +## Socket takes precedence. + +$dsn ="DBI:mysql:database=$config{db};"; + +if ($config{socket} and -S $config{socket}) +{ + $dsn .= "mysql_socket=$config{socket}"; +} +else +{ + $dsn .= "host=$config{host};port=$config{port}"; +} + + +my $dbh = DBI->connect($dsn, $config{user}, $config{pass}, + { PrintError => 0 }); + +if (not ref $dbh) +{ + my $Error = <{Variable_name} eq "version"; + $db_version = $_->{Value}; + last; +} + +## The main loop + +ReadMode($RM_NOBLKRD); + +while (1) +{ + Clear() unless $config{batchmode}; + GetData(); + last if $config{batchmode}; + my $key = ReadKey $config{delay}; + + next unless $key; + + ## quit + + if ($key =~ /q/i) + { + ReadMode($RM_RESET); + print "\n"; + exit; + } + + ## seconds of delay + + if ($key =~ /s/) + { + ReadMode($RM_RESET); + + print RED(), "Seconds of Delay: ", RESET(); + my $secs = ReadLine(0); + + if ($secs =~ /^\s*(\d+)/) + { + $config{delay} = $1; + + if ($config{delay} < 1) + { + $config{delay} = 1; + } + + } + + ReadMode($RM_NOBLKRD); + next; + } + + ## pause + + if ($key =~ /p/i) + { + print RED(), "-- paused. press any key to resume --", RESET(); + ReadKey(0); + next; + } + + ## help (?) + + if ($key eq '?') + { + Clear(); + PrintHelp(); + ReadKey(0); + next; + } + + ## kill + + if ($key =~ /k/i) + { + ReadMode($RM_RESET); + + print RED(), "Thread id to kill: ", RESET(); + my $id = ReadLine(0); + + $id =~ s/\s//g; + + if ($id =~ /^\d+$/) + { + Execute("KILL $id"); + } + else + { + print RED(), "-- invalid thread id --", RESET(); + sleep 2; + } + + ReadMode($RM_NOBLKRD); + next; + } + + ## full info + + if ($key =~ /f/i) + { + print RED(), "Full query info not yet implemented.", RESET(); + sleep 2; + next; + } + + ## reset status counters + + if ($key =~ /r/i) + { + Execute("FLUSH STATUS"); + print RED(), "-- counters reset --", RESET(); + sleep 2; + next; + } + + ## header toggle + + if ($key =~ /h/i) + { + if ($config{header}) + { + $config{header} = 0; + } + else + { + $config{header}++; + } + } + +} + +ReadMode($RM_RESET); + +exit; + +####################################################################### + +sub Clear() +{ + print "$CLEAR"; +} + +sub GetData() +{ + ## Get terminal info + + my ($width, $height, $wpx, $hpx) = GetTerminalSize(); + + my $lines_left = $height - 2; + + if ($config{batchmode}) + { + $height = 999_999; ## I hope you don't have more than that! + } + + ## + ## Header stuff. + ## + + if ($config{header}) + { + my @recs = Hashes("show status"); + + my %S; + + foreach my $ref (@recs) + { + my $key = $ref->{Variable_name}; + my $val = $ref->{Value}; + + $S{$key} = $val; + } + + ## Compute Key Cache Hit Stats + + $S{Key_read_requests} ||= 1; ## can't divide by zero next + + my $cache_hits_percent = (100-($S{Key_reads}/$S{Key_read_requests}) * 100); + $cache_hits_percent = sprintf("%2.2f",$cache_hits_percent); + + ## Server Uptime in meaningful terms... + + my $time = $S{Uptime}; + my ($d,$h,$m,$s) = (0, 0, 0, 0); + + $d += int($time / (60*60*24)); $time -= $d * (60*60*24); + $h += int($time / (60*60)); $time -= $h * (60*60); + $m += int($time / (60)); $time -= $m * (60); + $s += int($time); + + my $uptime = sprintf("%d+%02d:%02d:%02d", $d, $h, $m, $s); + + ## Queries per second... + + my $avg_queries_per_sec = sprintf("%.2f", $S{Questions} / $S{Uptime}); + my $num_queries = $S{Questions}; + + my @t = localtime(time); + + my $current_time = sprintf "[%02d:%02d:%02d]", $t[2], $t[1], $t[0]; + + my $host_width = 55; + my $up_width = $width - $host_width; + + print RESET(); + + printf "%-${host_width}s%${up_width}s\n", + "MySQL on $config{host} ($db_version)", "up $uptime $current_time"; + + $lines_left--; + + printf " Queries Total: %-13s ", commify($num_queries); + printf "Avg/Sec: %-4.2f ", $avg_queries_per_sec; + printf "Slow: %s\n", commify($S{Slow_queries}); + + $lines_left--; + + printf " Threads Total: %-5s Active: %-5s Cached: %-5s\n", + commify($S{Threads_connected}), commify($S{Threads_running}), + commify($S{Threads_cached}); + + $lines_left--; + + printf " Key Efficiency: %2.2f%% Bytes in: %s Bytes out: %s\n\n", + $cache_hits_percent, commify($S{Bytes_received}), + commify($S{Bytes_sent}); + + $lines_left--; + + } + + + ## + ## Threads + ## + + #my $sz = $width - 52; + my @sz = (6, 8, 10, 10, 6, 8); + my $used = scalar(@sz) + Sum(@sz); + my $free = $width - $used; + + print BOLD(); + + printf "%6s %8s %10s %10s %6s %8s %-${free}s\n", + 'Id','User','Host','Dbase','Idle', 'Command', 'Query Info'; + + print RESET(); + + printf "%6s %8s %10s %10s %6s %8s %-${free}s\n", + '--','----','----','-----','----', '-------', '----------'; + + $lines_left -= 2; + + my @data = Hashes("show processlist"); + + foreach my $thread (@data) + { + last if not $lines_left; + + ## Drop Domain Name + + $thread->{Host} =~ s/^([^.]+).*/$1/; + + ## Fix possible undefs + + $thread->{db} ||= ''; + $thread->{Info} ||= ''; + $thread->{Time} ||= 0 ; + $thread->{Id} ||= 0 ; + $thread->{User} ||= 0 ; + $thread->{Command} ||= ''; + $thread->{Host} ||= ''; + + ## Normalize spaces + + $thread->{Info} =~ s/[\n\r]//g; + $thread->{Info} =~ s/\s+/ /g; + $thread->{Info} =~ s/^\s*//; + } + + ## Sort by idle time (closest thing to CPU usage I can think of). + + ## unauthenticated user + + foreach my $thread (sort { $a->{Time} <=> $b->{Time} } @data) + { + + my $smInfo = substr $thread->{Info}, 0, $free; + + if ($HAS_COLOR) + { + print YELLOW() if $thread->{Command} eq 'Query'; + print WHITE() if $thread->{Command} eq 'Sleep'; + print GREEN() if $thread->{Command} eq 'Connect'; + } + + printf "%6d %8.8s %10.10s %10.10s %6d %8.8s %-${free}.${free}s\n", + $thread->{Id}, $thread->{User}, $thread->{Host}, $thread->{db}, + $thread->{Time}, $thread->{Command}, $smInfo; + + + print RESET() if $HAS_COLOR; + + $lines_left--; + + last if $lines_left == 0; + + } + +} + +########################################################################### +########################################################################### +########################################################################### + +sub PrintHelp() +{ + print< + + ? - display this screen + s - change the delay between screen updates + k - kill a thread + h - toggle the mytop header + p - pause the display + r - reset the status counters (via FLUSH STATUS on your server) + f - full query info (NOT IMPLEMENTED) + q - quit + +mytop man page is available via `${RED}perldoc mytop${RESET}' + + database: $config{db} + username: $config{user} + hostname: $config{host} + port: $config{port} + socket: $config{socket} + delay: $config{delay} seconds + +${GREEN}http://public.yahoo.com/~jzawodn/mytop/${RESET} + +(press any key to return) +EOHELP +} + +sub Sum(@) +{ + my $sum; + + while (my $val = shift @_) + { + $sum += $val; + } + + return $sum; +} + +## A useful routine from perlfaq + +sub commify($) +{ + local $_ = shift; + return 0 unless defined $_; + 1 while s/^([-+]?\d+)(\d{3})/$1,$2/; + return $_; +} + +## Run a query and return the records has an array of hashes. + +sub Hashes($) +{ + my $sql = shift; + + my @records; + + if (my $sth = Execute($sql)) + { + while (my $ref = $sth->fetchrow_hashref) + { + push @records, $ref; + } + + } + return @records; +} + +## Execute an SQL query and return the statement handle. + +sub Execute($) +{ + my $sql = shift; + + ## + ## Prepare the statement + ## + my $sth = $dbh->prepare($sql); + + if (not $sth) + { + die $DBI::errstr; + } + + ## + ## Execute the statement. + ## + + my $ReturnCode = $sth->execute; + + if (not $ReturnCode) + { + return undef; + } + + return $sth; +} + +=pod + +=head1 SYNOPSIS + +B [options] + +=head1 AVAILABILITY + +The latest version of B is available from +http://public.yahoo.com/~jzawodn/mytop/ + +=head1 REQUIREMENTS + +In order for B to function properly, you must have the +following: + + * Perl 5.005 or newer + * Getopt::Long + * DBI and DBD::mysql + * Term::ReadKey from CPAN + +Most systems are likely to have all of those installed--except for +Term::ReadKey. You will need to pick that up from the CPAN. You can +pick up Term::ReadKey here: + + http://search.cpan.org/search?dist=TermReadKey + +And you obviously need access to a MySQL server (version 3.22.x or +3.23.x) with the necessary security to run the I and +I commands. + +=head2 Optional Color Support + +In additon, if you want a color B (recommended), install +Term::ANSIColor from the CPAN: + + http://search.cpan.org/search?dist=ANSIColor + +Once you do, B will automatically use it. + +=head2 Platforms + +B is known to work on: + + * Linux (2.2.x) + * FreeBSD (2.2, 3.x, 4.x) + * BSDI 4.x + * Solaris 2.x + +If you find that it works on another platform, please let me +know. Given that it is all Perl code, I expect it to be rather +portable to Unix and Unix-like systems. Heck, it I even work on +Win32 systems. + +=head1 DESCRIPTION + +This software is subject to change. It is currently I quality +software with known problems and incompatibilities, so please keep +that in mind. + +It is, however, stable. There's little damage you can do by running +B. + +Help is always welcome in improving this software. Feel free to +contact the author (see L<"AUTHOR"> below) with bug reports, fixes, +suggestions, and comments. Additionally L<"BUGS"> will provide a list +of things this software is not able to do yet. + +Having said that, here are the details on how it works and what you can +do with it. + +=head2 Basics + +B was inspired by the system monitoring tool B. I +routinely use B on Linux, FreeBSD, and Solaris. You are likely to +notice features from each of them here. + +B will connect to a MySQL server and periodically run the +I and I commands and attempt to +summarize the information from them in a useful format. + +=head2 The Display + +The B display screen is really broken into two parts. The top 4 +lines (header) contain summary information about your MySQL +server. For example, you might see something like: + + MySQL on localhost (3.22.32) up 3+23:14:20 [23:54:52] + Queries Total: 617 Avg/Sec: 0.00 Slow: 0 + Threads Total: 1 Active: 1 Cached: 0 + Key Efficiency: 88.38% Bytes in: 0 Bytes out: 0 + +The first line identified the hostname of the server (localhost) and +the version of MySQL it is running. The right had side shows the +uptime of the MySQL server process in days+hours:minutes:seconds +format (much like FreeBSD's top) as well as the current time. + +The second line displays the total number of queries the server has +processed, the average number of queries per second, and the number of +slow queries. + +The third line deals with threads. Versions of MySQL before 3.23.x +didn't give out this information, so you'll see all zeros. + +And the fourth line displays key buffer efficiency (how often keys are +read from the buffer rather than disk) and the number of bytes that +MySQL has sent and received. + +You can toggle the header by hitting B when running B. + +The second part of the display lists as many threads as can fit on +screen. By default they are sorted according to their idle time (least +idle first). The display looks like: + + Id User Host Dbase Idle Command Query Info + -- ---- ---- ----- ---- ------- ---------- + 61 jzawodn localhost music 0 Query show processlist + +As you can see, the thread id, username, host from which the user is +connecting, database to which the user is connected, number of seconds +of idle time, the command the thread is executing, and the query info +are all displayed. + +Often times the query info is what you are really interested in, so it +is good to run B in an xterm that is wider than the normal 80 +columns if possible. + +The thread display color-codes the threads if you have installed color +support. The current color scheme only works well in a window with a +dark (like black) background. The colors are selected according to the +C column of the display: + + Query Yellow + Sleep White + Connect Green + +Those are purely arbitrary and will be customizable in a future +release. If they annoy you just start B with the B<-nocolor> +flag or adjust your config file appropriately. + +=head2 Arguments + +B handles long and short command-line arguments. Not all +options have both long and short formats, however. The long arguments +can start with one or two dashes `-' or `--'. They are shown here with +just one. + +=over + +=item B<-u> or B<-user> username + +Username to use when logging in to the MySQL server. Default: ``root''. + +=item B<-p> or B<-password> password + +Password to use when logging in to the MySQL server. Default: none. + +=item B<-h> or B<-host> hostname[:port] + +Hostname of the MySQL server. The hostname may be followed by an +option port number. Note that the port is specified separate from the +host when using a config file. Default: ``localhost''. + +=item B<-port> port + +If you're running MySQL on a non-standard port, use this to specify +the port number. Default: 3306. + +=item B<-s> or B<-delay> seconds + +How long between display refreshes. Default: 5 + +=item B<-d> or B<-db> or B<-database> database + +Use if you'd like B to connect to a specific database by +default. Default: ``test''. + +=item B<-b> or B<-batch> or B<-batchmode> + +In batch mode, mytop runs only once, does not clear the screen, and +places no limit on the number of lines it will print. This is suitable +for running periodically (perhaps from cron) to capture the +information into a file for later viewing. You might use batch mode in +a CGI script to occasionally display your MySQL server status on the +web. + +Default: unset. + +=item B<-S> or B<-socket> /path/to/socket + +If you're running B on the same host as MySQL, you may wish to +have it use the MySQL socket directly rather than a standard TCP/IP +connection. If you do,just specify one. + +Note that specifying a socket will make B ignore any host +and/or port that you might have specified. If the socket does not +exist (or the file specified is not a socket), this option will be +ignored and B will use the hostname and port number instead. + +Default: none. + +=item B<-header> or B<-noheader> + +Sepcify if you want the header to display or not. You can toggle this +with the B key while B is running. + +Default: header. + +=item B<-color> or B<-nocolor> + +Specify if you want a color display. This has no effect if you don't +have color support available. + +Default: If you have color support, B will try color unless you +tell it not to. + +=back + +Command-line arguments will always take precedence over config file +options. That happens because the config file is read I the +command-line arguments are applied. + +=head2 Config File + +Instead of always using bulky command-line parameters, you can also +use a config file in your home directory (C<~/.mytop>). If present, +B will read it automatically. It is read I any of your +command-line arguments are processed, so your command-line arguments +will override directives in the config file. + +Here is a sample config file C<~/.mytop> which implements the defaults +described above. + + user=root + pass= + host=localhost + db=test + delay=5 + port=3306 + socket= + batchmode=0 + header=1 + color=1 + +Using a config file will help to ensure that your database password +isn't visible to users on the command-line. Just make sure that the +permissions on C<~/.mytop> are such that others cannot read it (unless +you want them to, of course). + +You may have white space on either side of the C<=> in lines of the +config file. + +=head2 Shortcut Keys + +The following keys perform various actions while B is +running. Those which have not been implemented are listed as +such. They are included to give the user idea of what is coming. + +=over + +=item B + +Change the sleep time (number of seconds between display refreshes). + +=item B + +Quit B + +=item B + +Kill a thread. + +=item B + +Reset the server's status counters via a I command. + +=item B + +Full query info. (Not Implemented) + +=item B

    + +Pause display. + +=item B + +Toggle the header display. You can also specify either C or +C in your config file to set the default behavior. + +=item B + +Display help. + +=back + +The B key has a command-line counterpart: B<-s>. + +The B key has two command-line counterparts: B<-header> and +B<-noheader>. + +=head1 BUGS + +This is more of a BUGS + WishList. + +Some performance information is not available when talking to a +version 3.22.x MySQL server. Additional information (about threads +mostly) was added to the output of I in MySQL 3.23.x and +B makes use of it. If the information is not available, you +will simply see zeros where the real numbers should be. + +Simply running this program will increase your overall counters. But +you may or may not view that as a bug. + +B consumes too much CPU time when running (verified on Linux +and FreeBSD). It's likely a problem related to Term::ReadKey. I +haven't had time to investigate yet, so B now automatically +lowers its priority when you run it. You may also think about running +B on another workstation instead of your database server. + +You can't easily toggle the sorting order of the threads or filter the +information (yet). Ideally you should be able to view only threads +belonging to a particular user or those which are using a particular +database, and so on. That functionality is on the TODO list that I +haven't committed to disk yet. + +You can't specify the maximum number of threads to list. If you have +many threads and a tall xterm, B will always try to display as +many as it can fit. + +The size of most of the columns in the display has a small maximum +width. If you have fairly long database/user/host names the display +may appear odd. I have no good idea as to how best to deal with that +yet. Suggestions are welcome. + +Full query info is not implemented. I'd like to be able to show the +whole query for a given thread. This will be especially useful in +tracking slow queries. + +It'd be cool if you could just add B configuration directives +in your C file instead of having a separate config file. + +=head1 AUTHOR + +mytop was developed and is maintained by Jeremy D. Zawodny +(jzawodn@yahoo-inc.com). + +If you wish to e-mail me regarding this software, B prefix the +Subject line of your message with ``mytop'' so that my mail filter +will notice it. I will be able to respond more quickly and it will +show that you bothered to read the documentation first. + +=head1 DISCLAIMER + +While I use this software in my job at Yahoo!, I am solely responsible +for it. Yahoo! does not support this software in any way. It is merely +a personal idea which happened to be very useful in my job. + +=head1 RECRUITING + +If you hack Perl and grok MySQL, come work at Yahoo! Contact me for +details. Or just send me your resume. + +=head1 SEE ALSO + +Please check the MySQL manual if you're not sure where some of the +output of B is coming from. + +=head1 COPYRIGHT + +Copyright (C) 2000, Jeremy D. Zawodny. + +=head1 CREDITS + +Fix a bug. Add a feature. See your name here! + +Many thanks go to these fine folks: + +=over + +=item Jan Willamowius (jan@janhh.shnet.org) + +Mirnor bug report. Documentation fixes. + +=item Alex Osipov (alex@acky.net) + +Long command-line options, Unix socket support. + +=item Stephane Enten (tuf@grolier.fr) + +Suggested batch mode. + +=item Richard Ellerbrock (richarde@eskom.co.za) + +Bug reports and usability suggestions. + +=item William R. Mattil (wrm@newton.irngtx.tel.gte.com) + +Bug report about empty passwords not working. + +=back + +See the Changes file on the B distribution page for more +details on what has changed. + +=head1 LICENSE + +B is licensed under the GNU General Public License version +2. For the full license information, please visit +http://www.gnu.org/copyleft/gpl.html + +=cut + +__END__ + + + diff --git a/ljcom/bin/no-emacs.sh b/ljcom/bin/no-emacs.sh new file mode 100755 index 0000000..891d649 --- /dev/null +++ b/ljcom/bin/no-emacs.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# +# +# prog: find, rm +# + +find . \( -name '.*~' -or -name '*~' -or -name '#*#' -or -name '.#*' \) -print -exec rm -f {} \; diff --git a/ljcom/bin/pay-batch b/ljcom/bin/pay-batch new file mode 100755 index 0000000..64ac15b --- /dev/null +++ b/ljcom/bin/pay-batch @@ -0,0 +1,9 @@ +#!/bin/sh +# +# +# prog: bin/ljmaint.pl +# + +~lj/bin/ljmaint.pl pay_mail pay_updateaccounts + + diff --git a/ljcom/bin/pkill b/ljcom/bin/pkill new file mode 100755 index 0000000..8a1bb1b --- /dev/null +++ b/ljcom/bin/pkill @@ -0,0 +1,20 @@ +#!/usr/bin/perl +# +# +# prog: ps, grep +# + +use strict; + +my $prog = shift @ARGV; +exit unless ($prog =~ /^[\w\.\/]+$/); + +my @procs = `ps awx | grep $prog | grep -v grep | grep -v pkill`; +foreach (@procs) +{ + next unless (/^\s*(\d+)\s/); + my $pid = $1; + print $pid, "\n"; + kill 15, $pid; +} + diff --git a/ljcom/bin/qkill b/ljcom/bin/qkill new file mode 100755 index 0000000..f401fec --- /dev/null +++ b/ljcom/bin/qkill @@ -0,0 +1,18 @@ +#!/usr/bin/perl +# + +use strict; + +my $prog = shift @ARGV; +exit unless ($prog =~ /^[\w\.\/]+$/); + +my @procs = `ps awx | grep $prog | grep -v grep | grep -v hkill`; +foreach (@procs) +{ + next unless (/^\s*(\d+)\s/); + my $pid = $1; + print $pid, "\n"; + kill 15, $pid; +} + + diff --git a/ljcom/bin/release.pl b/ljcom/bin/release.pl new file mode 100755 index 0000000..21b52ee --- /dev/null +++ b/ljcom/bin/release.pl @@ -0,0 +1,76 @@ +#!/usr/bin/perl +# + +my $mode = shift @ARGV; + +if ($< == 0 || $> ==0) { die "Don't run as root.\n"; } +chdir("/home/lj") || die "Can't cd to /home/lj"; + +chdir("/home/ljcode") || die "Can't cd to /home/ljcode"; +unless (-d "LiveJournal") { + die "directory 'LiveJournal' doesn't exist.\n"; +} + +print "Dumping SQL...\n"; +system("dumpsql.pl init > LiveJournal/livejournal.sql"); +system("dumpsql.pl data > LiveJournal/livejournal-data.sql"); +system("dumpsql.pl datareplace > LiveJournal/livejournal-datareplace.sql"); + +mkdir "LiveJournal/bin/", 0755; +mkdir "LiveJournal/cgi-bin/", 0755; +mkdir "LiveJournal/htdocs/", 0755; +foreach my $dir (qw(htdocs/files htdocs/temp htdocs/misc htdocs/img + htdocs/stats htdocs/download htdocs/clients + logs var)) +{ + mkdir "LiveJournal/htdocs/$dir", 0755; + open (T, ">LiveJournal/htdocs/$dir/.touch"); + print T "placeholder\n"; + close T; +} + +print "Syncing cgi-bin...\n"; +system("rsync -rl --delete --exclude='archive' --exclude='clients' --exclude='ljconfig.pl' /home/lj/cgi-bin/ LiveJournal/cgi-bin/"); + +print "Syncing htdocs...\n"; +system("rsync -rl --delete --exclude='htdocs/dev/' --exclude='img' --exclude='files' --exclude='download' --exclude='temp' --exclude='misc' --exclude='stats' /home/lj/htdocs/ LiveJournal/htdocs/"); + +print "Syncing bin...\n"; +system("rsync -rl --delete --exclude='old' /home/lj/bin/ LiveJournal/bin/"); + +my @now = localtime(); +my $date = sprintf("%04d%02d%02d", $now[5]+1900, $now[4]+1, $now[3]); +my $append = $date; +print "Date is: $date\n"; +my $count = 1; +while (-e "LiveJournal-$append" || -e "LiveJournal-$append.tar.gz") { + $count++; + $append = "$date-$count"; +} + +chdir("LiveJournal"); + +print "Cleaning emacs files.\n"; +system("no-emacs.sh"); +print "Cleaning other files.\n"; +system("rm cgi-bin/pod2html-* cgi-bin/perl.core"); + +chdir(".."); + +unless ($mode eq "lite") +{ + print "Renaming to LiveJournal-$append...\n"; + rename "LiveJournal", "LiveJournal-$append"; + + print "Tarring...\n"; + system("tar -zcvf LiveJournal-$append.tar.gz LiveJournal-$append"); + + print "Renaming back...\n"; + rename "LiveJournal-$append", "LiveJournal"; +} +else +{ + print "Skipping tarball.\n"; +} +print "Done\n"; + diff --git a/ljcom/bin/renameuser.pl b/ljcom/bin/renameuser.pl new file mode 100755 index 0000000..5658793 --- /dev/null +++ b/ljcom/bin/renameuser.pl @@ -0,0 +1,159 @@ +#!/usr/bin/perl +# +# +# lib: cgi-bin/ljlib.pl +# + +use strict; +use Getopt::Long; + +require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; + +sub usage { + die "Usage: [--swap --force] \n"; +} + +my %args = ( swap => 0, force => 0 ); +usage() unless + GetOptions('swap' => \$args{swap}, + 'force' => \$args{force}, + ); + +my $error; + +my $from = shift @ARGV; +my $to = shift @ARGV; +usage() unless $from =~ /^\w{1,15}$/ && $to =~ /^\w{1,15}$/; + +my $dbh = LJ::get_db_writer(); + +unless ($args{swap}) { + if (rename_user($from, $to)) { + print "Success. Renamed $from -> $to.\n"; + } else { + print "Failed: $error\n"; + } + exit; +} + +### check that emails/passwords match, and that at least one is verified +my $qfrom = $dbh->quote(lc($from)); +my $qto = $dbh->quote(lc($to)); + +unless ($args{force}) { + my $sth = $dbh->prepare("SELECT user, email, password, status FROM user WHERE user IN ($qfrom, $qto)"); + $sth->execute; + { + my @acct; + while (my $l = $sth->fetchrow_hashref) { + push @acct, $l; + } + unless (@acct == 2) { + print "Both accounts aren't valid.\n"; + exit 1; + } + unless (lc($acct[0]->{'email'}) eq lc($acct[1]->{'email'})) { + print "Email addresses don't match.\n"; + print " $acct[0]->{'email'}\n"; + print " $acct[1]->{'email'}\n"; + exit 1; + } + unless ($acct[0]->{'password'} eq $acct[1]->{'password'}) { + print "Passwords don't match.\n"; + exit 1; + } + unless ($acct[0]->{'status'} eq "A" || $acct[1]->{'status'} eq "A") { + print "At least one account isn't verified.\n"; + exit 1; + } + } +} + +my $swapnum = 0; +print "Swapping 1/3...\n"; +until ($swapnum == 10 || rename_user($from, "lj_swap_$swapnum")) { + $swapnum++; +} +if ($swapnum == 10) { + print "Couldn't find a swap position?\n"; + exit 1; +} + +print "Swapping 2/3...\n"; +unless (rename_user($to, $from)) { + print "Swap failed in the middle, from $to -> $from failed.\n"; + exit 1; +} + +print "Swapping 3/3...\n"; +unless (rename_user("lj_swap_$swapnum", $to)) { + print "Swap failed in the middle, from lj_swap_$swapnum -> $to failed.\n"; + exit 1; +} + +# check for circular 'renamedto' references +{ + + # if the fromuser had redirection on, make sure it points to the new $to user + my $fromu = LJ::load_user($from, 'force'); + LJ::load_user_props($fromu, 'renamedto'); + if ($fromu->{renamedto} && $fromu->{renamedto} ne $to) { + print "Setting redirection: $from => $to\n"; + unless (LJ::set_userprop($fromu, 'renamedto' => $to)) { + print "Error setting 'renamedto' userprop for $from\n"; + exit 1; + } + } + + # if the $to user had redirection, they shouldn't anymore + my $tou = LJ::load_user($to, 'force'); + LJ::load_user_props($tou, 'renamedto'); + if ($tou->{renamedto}) { + print "Removing redirection for user: $to\n"; + unless (LJ::set_userprop($tou, 'renamedto' => undef)) { + print "Error setting 'renamedto' userprop for $to\n"; + exit 1; + } + } +} + +print "Swapped.\n"; +exit 0; + +sub rename_user +{ + my $from = shift; + my $to = shift; + + my $qfrom = $dbh->quote(LJ::canonical_username($from)); + my $qto = $dbh->quote(LJ::canonical_username($to)); + + print "Renaming $from -> $to\n"; + + my $u = LJ::load_user($from, 'force'); + unless ($u) { + $error = "Invalid source user: $from"; + return 0; + } + + foreach my $table (qw(user useridmap overrides style)) + { + $dbh->do("UPDATE $table SET user=$qto WHERE user=$qfrom"); + if ($dbh->err) { + $error = $dbh->errstr; + return 0; + } + } + + # from user is now invalidated + LJ::memcache_kill($u->{userid}, "userid"); + LJ::MemCache::delete("uidof:$from"); + LJ::MemCache::delete("uidof:$to"); + + LJ::procnotify_add("rename_user", { 'user' => $u->{'user'}, + 'userid' => $u->{'userid'} }); + + $dbh->do("INSERT INTO renames (renid, token, payid, userid, fromuser, touser, rendate) ". + "VALUES (NULL,'[manual]',0,$u->{userid},$qfrom,$qto,NOW())"); + return 1; +} diff --git a/ljcom/bin/rewrite-balancer.pl b/ljcom/bin/rewrite-balancer.pl new file mode 100755 index 0000000..569d485 --- /dev/null +++ b/ljcom/bin/rewrite-balancer.pl @@ -0,0 +1,131 @@ +#!/usr/bin/perl + +# This tool is to be run from apache's mod_rewrite, +# not from command line. +# If there's an argument, it's taken to be a key +# in the $LJ::WEB_POOLS hash specifying the hosts which +# this balancer is to work with. + +use strict; +use IO::Socket::INET; +use IO::Select; + +my $port = 4446; +my $MAXLEN = 512; +my $BCAST_VER = 1; +my %allowed; # ip_text -> 1 (if broadcasting server is in our watched pool) + +eval { require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; }; + +if ($LJ::FREECHILDREN_BCAST && + $LJ::FREECHILDREN_BCAST =~ /^(\S+):(\d+)$/) { + $port = $2; +} + +if ($ARGV[0] && $LJ::WEB_POOLS{$ARGV[0]}) { + foreach (@{$LJ::WEB_POOLS{$ARGV[0]}}) { + $allowed{$_} = 1; + } +} + +my $sock = IO::Socket::INET->new(Proto=>'udp', + LocalPort=>$port) + or die "couldn't create socket\n"; +$sock->sockopt(SO_BROADCAST, 1); +$sock->blocking(0); +$|=1; + +my $sel = IO::Select->new(); +$sel->add(\*STDIN); +$sel->add($sock); + +my %servers; # ip_text -> { bcast_ver => 1 , free => \d+, active => \d+, _time => unix } +my %free; # ip_text -> num_free +my $total_free = 0; + +sub get_server { + return "" unless $total_free; + + # delete servers that haven't reported back in a while + my $now = time(); + my @del; + while (my ($k, $v) = each %servers) { + push @del, $k if $v->{_time} < $now - 20; + } + foreach (@del) { delete_server($_); } + + return "" unless $total_free; + + my $choice = rand($total_free); + my $count = 0; + while ($_ = each %free) { + $count += $free{$_}; + if ($count >= $choice) { # can only happen if $free{$_}>0 + $total_free--; + $free{$_}--; + return $_; + } + } + return ""; +} + +sub delete_server { + my $key = shift; # key = ip_text + $total_free -= $free{$key} if $free{$key}; + delete $servers{$key}; + delete $free{$key}; +} + +sub parse_message { + my ($sock, $message) = @_; + my ($port, $ipaddr) = sockaddr_in($sock->peername); + my $ip_text = inet_ntoa($ipaddr); + return if %allowed and not $allowed{$ip_text}; + + delete_server($ip_text); + + my $host; + foreach my $pair (split /\n/, $message) { + $host->{$1} = $2 if $pair =~ /^(\S+)=(\S*)$/; + } + $host->{_time} = time(); + + return unless $host->{bcast_ver} eq $BCAST_VER; + + if ($host->{free}) { + $servers{$ip_text} = $host; + $free{$ip_text} = $host->{free}; + $total_free += $host->{free}; + } + return; +} + +my @backlog; # unserviced uris, with trailing newlines + +sub process_requests +{ + my $server; + while (@backlog && ($server = get_server())) { + my $uri = shift @backlog; + print "http://$server/$uri"; + } +} + +while(1) { + my @ready = $sel->can_read(); + foreach my $fh (@ready) { + if ($fh == $sock) { + my $message; + while($sock->recv($message, $MAXLEN)) { + parse_message($sock, $message); + } + process_requests(); + } + if ($fh == \*STDIN) { + $_ = ; + push @backlog, $_; + exit 1 if @backlog > 2000; # something's horribly wrong + process_requests(); + } + } +} diff --git a/ljcom/bin/rotate b/ljcom/bin/rotate new file mode 100755 index 0000000..901f9ab --- /dev/null +++ b/ljcom/bin/rotate @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# + +@files = @ARGV; +$base = $0; +$base =~ s/^.+\///; +if (@files==0 || $files[0] =~ /^-/) +{ + die "Usage: $base logfiles\n"; +} +@files = grep { -e } @files; + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +$mon++; $year+=1900; + +$num = 0; +$ext = sprintf("%04d.%02d.%02d.%02d.rotlog", $year, $mon, $mday, $num); + +$dirty=1; +while ($dirty) +{ + $dirty=0; + foreach $file (@files) + { + $dirty =1 if (-e "$file.$ext.gz" || -e "$file.$ext"); + } + + if ($dirty) + { + $num++; + $ext = sprintf("%04d.%02d.%02d.%02d.rotlog", $year, $mon, $mday, $num); + } +} + +foreach $file (@files) +{ + rename $file, "$file.$ext"; +} diff --git a/ljcom/bin/screenshots.pl b/ljcom/bin/screenshots.pl new file mode 100755 index 0000000..90c7c9e --- /dev/null +++ b/ljcom/bin/screenshots.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +# + +use Image::Size; + +my $dir = shift @ARGV; +unless ($dir) { + die "Usage:\n $0 \n"; +} +unless (-d $dir) { + die "$dir isn't a directory!\n"; +} + +unless (open (PICS, "pics.dat")) { + die "No pics.dat found in that directory, or unreadable.\n"; +} + +print "Screenshots\nbody<=\n"; + +while ($line = ) { + chomp $line; + my ($file, $des) = split(/\t/, $line); + if (-e $file) { + my ($w, $h) = imgsize($file); + + print "

    $des

    \n"; + + } else { + print STDERR "$file not found!\n"; + } + +} + +print "<=body\npage?>\n"; diff --git a/ljcom/bin/sourceclean.pl b/ljcom/bin/sourceclean.pl new file mode 100755 index 0000000..0b13cc2 --- /dev/null +++ b/ljcom/bin/sourceclean.pl @@ -0,0 +1,37 @@ +#!/usr/bin/perl +# + +use strict; +use File::Find (); +use Getopt::Long; +die "\$LJHOME not set or invalid\n" unless -d $ENV{'LJHOME'}; + +my $opt_check = 0; +exit 1 unless GetOptions('check' => \$opt_check); + +File::Find::find({ + wanted => \&wanted, + no_chdir => 1, +}, map { "$ENV{'LJHOME'}/$_"} qw(bin cgi-bin htdocs)); + +sub wanted { + return 0 unless m/\.(pl|bml|html)$/; + + open (F, $_); + my $lnum = 0; + my $contents; + my $dirty = 0; + while (my $line = ) { + $lnum++; + if ($line =~ s/\t/ /g) { + print "$_:$lnum: tab\n"; + $dirty = 1; + } + if ($line =~ s/\s+\n$/\n/) { + print "$_:$lnum: trailing space\n"; + $dirty = 1; + } + $contents .= $line; + } + close F; +} diff --git a/ljcom/bin/splitlog.pl b/ljcom/bin/splitlog.pl new file mode 100755 index 0000000..db8c7cd --- /dev/null +++ b/ljcom/bin/splitlog.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl +# + +my $file = shift @ARGV; +my $newfile = shift @ARGV; + +my $locfile = "$file.loc"; +my $loc = 0; +my $lines = 0; + +my %monthtonum = qw(Jan 01 Feb 02 Mar 03 Apr 04 May 05 Jun 06 + Jul 07 Aug 08 Sep 09 Oct 10 Nov 10 Dec 12); + +$SIG{'INT'} = \&write_loc; + +sub write_loc { + close OUT; + print "Writing location $loc\n"; + open (LOC, ">$locfile") || die "Can't write location file!\n"; + print LOC "$loc\n$lines\n"; + close LOC; + print "Ending."; + exit; +}; + +unless ($file && $newfile) { + die "Usage:\n $0 \n"; +} +unless (-r $file) { + die "File \"$file\" does not exist.\n"; +} + +unless (-d "split") { + die "No split directory underneith the current directory.\n"; +} + +if (-e $locfile) { + open (LOC, $locfile) || die "Can't read location file!\n";; + chomp ($loc = ); + $loc += 0; + chomp ($lines = ); + $lines += 0; + close LOC; + print "Location: $loc (did $lines lines)\n"; +} + +open (LOG, $file) || die "Can't read log file\n";; +seek(LOG, $loc, 0); + +#my $line = ; +#$line = ; +#print $line; +#exit; + +my $count = 0; +my $lastdate = ""; +while (my $line = ) { + $loc += length($line); + $lines++; + + if ($line =~ /\[(\d\d)\/(...)\/(\d\d\d\d)/) { + my ($year, $month, $day) = ($3, $monthtonum{$2}, $1); + + my $date = "$year-$month-$day"; + + if ($date ne $lastdate) { +# if ($year==2001 && $month==3 && $day > 2) { + close OUT; + open (OUT, ">>split/$date-$newfile.log") || die "Can't open file we're supposed to append to.\n"; +# } + $lastdate = $date; + } + +# if ($year==2001 && $month==3 && $day > 2) { + print OUT $line; +# } + } + + if ($lines % 10000 == 0) { print "line: $lines ($lastdate).\n"; } +} + +close LOG; +close OUT; + +print "End of file!\n"; +unlink $locfile, $file; + + diff --git a/ljcom/bin/upgrading/base-data-local.sql b/ljcom/bin/upgrading/base-data-local.sql new file mode 100644 index 0000000..4013d74 --- /dev/null +++ b/ljcom/bin/upgrading/base-data-local.sql @@ -0,0 +1,31 @@ +# This file is automatically generated from MySQL by $LJHOME/bin/dumpsql.pl +# Don't submit a diff against a hand-modified file - dump and diff instead. + +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to delete contributions from idiots.', '1', 'contrib_delete', 'Delete Contributions', 'local'); +UPDATE priv_list SET des='Allows a user to delete contributions from idiots.',is_public='1',privname='Delete Contributions',scope='local' WHERE privcode='contrib_delete'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to edit contributions.', '1', 'contrib_edit', 'Edit Contributions', 'local'); +UPDATE priv_list SET des='Allows a user to edit contributions.',is_public='1',privname='Edit Contributions',scope='local' WHERE privcode='contrib_edit'; +INSERT IGNORE INTO priv_list (des, is_public, privcode, privname, scope) VALUES ('Allows a user to access shipping tools.', '1', 'shipping', 'Shipping Access', 'local'); +UPDATE priv_list SET des='Allows a user to access shipping tools.',is_public='1',privname='Shipping Access',scope='local' WHERE privcode='shipping'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Override some payment checks to allow a user to pay. Values are Y to allow payment, N to deny payment.', '0', '0', 'allow_pay', 'Allow/deny a user to pay', 'local'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Override some payment checks to allow a user to pay. Values are Y to allow payment, N to deny payment.',indexed='0',multihomed='0',prettyname='Allow/deny a user to pay',scope='local' WHERE name='allow_pay'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Initial create.bml account type selection', '', '0', 'create_accttype', 'Created account type', 'local'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Initial create.bml account type selection',indexed='',multihomed='0',prettyname='Created account type',scope='local' WHERE name='create_accttype'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Boolean: 1 means mail Accounts about any payment activity for monitoring', '', '', 'fraud_watch', 'Fraud Watch', 'local'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Boolean: 1 means mail Accounts about any payment activity for monitoring',indexed='',multihomed='',prettyname='Fraud Watch',scope='local' WHERE name='fraud_watch'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Opt out of latest.bml, latest-rss.bml, and latest-img.bml if on.', '0', '0', 'latest_optout', 'Latest Updates Opt Out', 'local'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Opt out of latest.bml, latest-rss.bml, and latest-img.bml if on.',indexed='0',multihomed='0',prettyname='Latest Updates Opt Out',scope='local' WHERE name='latest_optout'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'bool', 'Assignment agreement necessary for bazaar payouts', '0', '0', 'legal_assignagree', 'Assignment Agreement Received', 'local'); +UPDATE userproplist SET cldversion='4',datatype='bool',des='Assignment agreement necessary for bazaar payouts',indexed='0',multihomed='0',prettyname='Assignment Agreement Received',scope='local' WHERE name='legal_assignagree'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Email address of parent provided during age verification.', '0', '0', 'parent_email', 'Parent\'s Email Address', 'local'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Email address of parent provided during age verification.',indexed='0',multihomed='0',prettyname='Parent\'s Email Address',scope='local' WHERE name='parent_email'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'blobchar', 'Packed POP3 deleted message id list', '0', '0', 'pop3_deletelist', 'POP3 Deletion List', 'local'); +UPDATE userproplist SET cldversion='4',datatype='blobchar',des='Packed POP3 deleted message id list',indexed='0',multihomed='0',prettyname='POP3 Deletion List',scope='local' WHERE name='pop3_deletelist'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'char', 'Post by phone stored blob format', '0', '0', 'pp_format', 'PhonePost File Format', 'local'); +UPDATE userproplist SET cldversion='4',datatype='char',des='Post by phone stored blob format',indexed='0',multihomed='0',prettyname='PhonePost File Format',scope='local' WHERE name='pp_format'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('4', 'num', 'The friendgroup id for friends that may transcribe audio postings.', '0', '0', 'pp_transallow', 'Allowed phonepost transcribers', 'local'); +UPDATE userproplist SET cldversion='4',datatype='num',des='The friendgroup id for friends that may transcribe audio postings.',indexed='0',multihomed='0',prettyname='Allowed phonepost transcribers',scope='local' WHERE name='pp_transallow'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Keyword to show in singles search', '0', '0', 'single_pickw', 'Single Picture Keyword', 'local'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Keyword to show in singles search',indexed='0',multihomed='0',prettyname='Single Picture Keyword',scope='local' WHERE name='single_pickw'; +INSERT IGNORE INTO userproplist (cldversion, datatype, des, indexed, multihomed, name, prettyname, scope) VALUES ('0', 'char', 'Delimited by pipes: MF/MM/FF/FM, country, state, city, age', '1', '0', 'single_status', 'Single Status', 'local'); +UPDATE userproplist SET cldversion='0',datatype='char',des='Delimited by pipes: MF/MM/FF/FM, country, state, city, age',indexed='1',multihomed='0',prettyname='Single Status',scope='local' WHERE name='single_status'; diff --git a/ljcom/bin/upgrading/be.dat b/ljcom/bin/upgrading/be.dat new file mode 100644 index 0000000..b05f310 --- /dev/null +++ b/ljcom/bin/upgrading/be.dat @@ -0,0 +1,5132 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=ЗьмÑніць Ñтан + +/accountstatus.bml.error.db=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° базы зьвеÑтак пры апрацоўцы вашага запыту. + +/accountstatus.bml.error.invalid=ÐÑÑлушны тып Ñтану + +/accountstatus.bml.error.nochange.expunged=Рахунак быў зьнішчаны з ÑÑ‹ÑÑ‚Ñмы. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Ðемагчыма зьмÑніць Ñтан журналу з прыпыненага. + +/accountstatus.bml.header.success=ПоÑьпех + +/accountstatus.bml.journalstatus.about=Калі вы хочаце выдаліць ці аднавіць Ñвой журнал, то гÑта меÑца, каб зрабіць гÑта. У выпадку Ð²Ñ‹Ð´Ð°Ð»ÐµÐ½ÑŒÐ½Ñ Ñвайго журналу вы маеце 30 дзён, каб аднавіць Ñго, калі вы перадумаеце. Праз 30 дзён ваш журнал будзе выдалены назаўÑёды, Ñ– магчымаÑьці аднавіць Ñго Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ. + +/accountstatus.bml.journalstatus.head=Стан актывацыі журналу + +/accountstatus.bml.journalstatus.select.activated=Ðктыўны + +/accountstatus.bml.journalstatus.select.deleted=Выдалены + +/accountstatus.bml.journalstatus.select.head=Стан: + +/accountstatus.bml.journalstatus.select.suspended=Прыпынены + +/accountstatus.bml.message.nochange=Стан вашага журналу быў пакінуты Ñк [[statusvis]]. + +/accountstatus.bml.message.success=Стан вашага журналу быў паÑьпÑхова зьменены на [[statusvis]]. + +/accountstatus.bml.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/allpics.bml.current=БÑÐ³ÑƒÑ‡Ñ‹Ñ Ð²Ñ‹Ñвы + +/allpics.bml.default=Па змоўчаньні + +/allpics.bml.edit2=Ð’Ñ‹ можаце быць зацікаўлены Ñž Ñ€Ñдагаваньні ключавых Ñловаў вашага малюнку ці Ñž загрузцы новага малюнку. + +/allpics.bml.error.noparam=Ð’Ñ‹ павінны ÑžÑтанавіць парамÑÑ‚Ñ€ карыÑтальніка. + +/allpics.bml.keywords=ÐšÐ»ÑŽÑ‡Ð°Ð²Ñ‹Ñ Ñловы: + +/allpics.bml.nopics.text.other=ГÑÑ‚Ñ‹ карыÑтальнік не загрузіў ніводнага малюнку. + +/allpics.bml.nopics.text2=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ загружаных малюнкаў. Каб загрузіць Ñкі, ідзіце Ñюды. + +/allpics.bml.nopics.title=ÐÑма малюнкаў + +/allpics.bml.pics=Тут знаходзÑцца выÑвы карыÑтальніка [[user]]. + +/allpics.bml.title=Ð’Ñ‹Ñвы карыÑтальніка + +/approve.bml.comm.success=ПоÑьпех + +/approve.bml.comm.text<< +Ð’Ñ‹ былі дададзены да [[comm]]. +ÐаціÑьніце тут, каб дадаць Ñуполку да вашага ÑьпіÑу ÑÑброў. +. + +/approve.bml.commjoin.text<< +Ð’Ñ‹ зацьвердзілі запыт пра ўдзел [[user]] у [[comm]]. +ÐаціÑьніце тут, каб наведаць ÑÑŒÐ¿Ñ–Ñ ÑƒÐ´Ð·ÐµÐ»ÑŒÐ½Ñ–ÐºÐ°Ñž гÑтай Ñуполкі Ñ– ÑžÑтанавіць Ñ–Ð½ÑˆÑ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– Ð´Ð»Ñ Ð³Ñтага карыÑтальніка. +. + +/approve.bml.error.actionperformed=ГÑтае дзеÑньне ўжо было выканана + +/approve.bml.error.approving=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры зацьверджаньні запыта на далучÑньне. + +/approve.bml.error.internerr.invalidaction=Ð£Ð½ÑƒÑ‚Ñ€Ð°Ð½Ð°Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ°: нÑÑлушнае дзеÑньне + +/approve.bml.error.invalidargument=Пададзены нÑÑлушны аргумÑнт + +/approve.bml.error.unknownactiontype=ÐевÑдомы тып дзеÑÐ½ÑŒÐ½Ñ + +/approve.bml.shared.success=ПоÑьпех + +/approve.bml.shared.text<< +Ð’Ñ‹ атрымалі доÑтуп да запіÑу Ñž [[shared]]. +ÐаціÑьніце тут, каб дадаць ÑумеÑны журнал да вашага ÑьпіÑу ÑÑброў. +. + +/approve.bml.title=Зацьверджаньне дзеÑÐ½ÑŒÐ½Ñ + +/birthdays.bml.description=ÐіжÑй пазначаны дні нараджÑÐ½ÑŒÐ½Ñ ÑžÑÑ–Ñ…, каго вы пазначылі Ñк ÑÑброў. + +/birthdays.bml.title=Дні нараджÑÐ½ÑŒÐ½Ñ + +/changepassword.bml.btn.proceed=ПрацÑг + +/changepassword.bml.changepassword.header=Зьмена паролю + +/changepassword.bml.changepassword.instructions=Запоўніце форму ніжÑй, каб зьмÑніць ваш пароль. Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð¿Ð°Ð¼Ð¾Ð³Ñ– Ñž выбары добрага паролю Ñ– Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½ÑŒÐ½Ñ Ð±ÑÑьпечным вашага рахунку, глÑдзіце гÑÑ‚Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы. + +/changepassword.bml.email.body<< +Ваш пароль на [[sitename]] быў зьменены. + +Каб атрымаць Ñго Ñž будучыні, наведайце: + +  [[siteroot]]/lostinfo.bml + +З павагай, +Каманда [[sitename]] + +[[siteroot]] + +. + +/changepassword.bml.email.subject=Зьмена паролю + +/changepassword.bml.error.badcheck=КепÑкі новы пароль: [[error]] + +/changepassword.bml.error.badnewpassword=Вашае пацьверджаньне новага паролю не Ñупадае з вашым новым паролем. Магчыма вы зрабілі памылку пры ўводзе. Калі лаÑка, увÑдзіце Ñ– пацьвердзіце ваш новы пароль ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/changepassword.bml.error.badoldpassword=Ваш Ñтары пароль нÑÑлушны. + +/changepassword.bml.error.blankpassword=Ваш новы пароль Ð½Ñ Ð¼Ð¾Ð¶Ð° быць пуÑтым. + +/changepassword.bml.error.changetestaccount=Ðемагчыма зьмÑніць пароль Ñ‚ÑÑтавага рахунку. + +/changepassword.bml.error.characterlimit=Пароль абмежаваны па даўжыні 30 ÑымбалÑмі. + +/changepassword.bml.error.invaliduser=ÐÑÑлушны карыÑтальнік [[user]]. КарыÑтальнік не Ñ–Ñнуе. Праверце, ці Ñлушна вы напіÑалі? + +/changepassword.bml.error.mustenterusername=Ð’Ñ‹ павінны ўвеÑьці Ñваё Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/changepassword.bml.error.nonascii=У паролÑÑ… можна выкарыÑтоўваць толькі ASCII Ñымбалі. Калі лаÑка ўвÑдзіце пароль толькі з ASCII ÑымбалÑÑž. + +/changepassword.bml.error.notvalidated=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ зьмÑніць ваш пароль, калі ваш бÑгучы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð½Ñ Ð±Ñ‹Ñž пацьверджаны. Калі лаÑка, глÑдзіце Пытаньні Ñ– адказы Ð´Ð·ÐµÐ»Ñ Ñ–Ð½ÑтрукцыÑÑž, Ñк зрабіць гÑта. + +/changepassword.bml.newpassword=Ðовы пароль: + +/changepassword.bml.newpasswordagain=Ðовы пароль (ÑÑˆÑ‡Ñ Ñ€Ð°Ð·): + +/changepassword.bml.oldpassword=Стары пароль: + +/changepassword.bml.proceed.instructions=ÐаціÑьніце кнопку ўнізе Ñ– ваш пароль будзе зьменены. Ð’Ñ‹ такÑама атрымаеце ліÑÑ‚ праз Ñл.пошту, што пароль быў зьменены. + +/changepassword.bml.relogin=У дадатак, уÑе Ð²Ð°ÑˆÑ‹Ñ Ñ–ÑÐ½ÑƒÑŽÑ‡Ñ‹Ñ ÑÑÑÑ–Ñ– былі Ñкончаны. Ð’Ñ‹ павінны ўвайÑьці наноў Ð´Ð·ÐµÐ»Ñ Ð¿Ñ€Ð°Ñ†Ñгу. + +/changepassword.bml.success.text=Ваш пароль быў зьменены Ñ– вам быў адаÑланы ліÑÑ‚ з нагадваньнем пра гÑта. + +/changepassword.bml.title=Зьмена паролю + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge, дзе знойдзеце адказы на большаÑьць вашых пытаньнÑÑž. Ðаведайце , павывучайце крыху, Ñ– вы зробіцеÑÑ Ð¿Ñ€Ð¾Ñ„Ñ– амаль адразу! +p?> + + +
    +Дадайце да вашага ÑьпіÑу ÑÑброў, каб ведаць пра ÑžÑе падзеі Ñ– зьмены, што тычацца ÑžÑёй грамады Жывога Журналу.
    +Дадайце да вашага ÑьпіÑу ÑÑброў, каб ведаць пра Ñ‡Ð°Ñ Ð·Ð°Ð¿Ð»Ñнаванага Ð¿Ñ€Ñ‹Ð¿Ñ‹Ð½ÐµÐ½ÑŒÐ½Ñ Ð´Ð·ÐµÐ¹Ð½Ñ–Ñ‡Ð°Ð½ÑŒÐ½Ñ ÑÑрверу, Ñ– Ñправаздачы пра Ñ€Ð°Ð¿Ñ‚Ð¾ÑžÐ½Ñ‹Ñ Ð¿Ñ€Ð°Ð±Ð»ÐµÐ¼Ñ‹ з ÑÑрверам. +p?> + + +AIM, ICQ, Yahoo!, MSN, ці Jabber праграмы абмену паведамленьнÑмі. Калі Ñ– вы імі карыÑтаецеÑÑ, пазначце гÑта Ñž вашайпÑÑ€Ñанальнай інфармацыі. Калі вы маеце Платны рахунак, вы можаце дазволіць атрыманьне Ñ‚ÑкÑтавых паведамленьнÑÑž на ваш мабільны Ñ‚Ñлефон ці пÑйджар. +p?> + + +Платнага рахунку. Ðле такÑама Ñ‘Ñьць Ñ– Ñ–Ð½ÑˆÑ‹Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьці, Ñк дапамагчы. +

    +Жывы Журнал - гÑта праект з Ðдкрытым кодам. Калі вы маеце вопыт Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñ†Ñ– ÑтварÑÐ½ÑŒÐ½Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼ ÑÑрвернай чаÑткі, наведайце Суполку раÑпрацоўцкі Жывога Журналу, . Калі Ñž Ð²Ð°Ñ Ñ‘Ñьць ідÑÑ–, Ñк зрабіць Жывы Журнал лепшым, наведайце Зону прапановаў Жывога Журналу, . Калі вы хочаце дапамагчы хоць у чым-небудзь, наведайце БізнÑÑÐ¾Ð²Ð°Ñ Ñуполка Жывога Журналу, . Калі вам падабаецца дапамагаць людзÑм, наведайце наш цÑнтр Ñ‚Ñхнічнай падтрымкі Ñ– дапамажыце каму-небудзь. Калі вы разьбіраецеÑÑ Ñž графічным дызайне, наведайце МаÑтацкую Ñуполку Жывога Журналу, . +p?> + + +Anime да Zen Buddhism, ад Astronomy да Zim. Ð’Ñ‹ такÑама знойдзеце Ñ€ÑгіÑÐ½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ñуполкі розных меÑцаў Ñьвету. ÐапÑўна Ñ‘Ñьць такÑама Ñ– Ñуполка таго меÑца, дзе вы жывеце! +p?> + + +Пытаньні Ñ– адказы, ÑÐºÑ–Ñ Ñ‚Ð»ÑƒÐ¼Ð°Ñ‡Ð°Ñ†ÑŒ, Ñк Ñтварыць вашую ўлаÑную Ñуполку. ТакÑама Ñ‘Ñьць дзьве катÑгорыі ПытаньнÑÑž Ñ– адказаў (ÐÐ³ÑƒÐ»ÑŒÐ½Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы пра Суполкі Ñ– Пытаньні Ñ– адказы пра кіраваньне Ñуполкай) раÑÐºÐ°Ð·Ð²Ð°ÑŽÑ‡Ñ‹Ñ Ð¿Ñ€Ð° ÑžÑÑ‘, што вам Ñ‚Ñ€Ñба ведаць пра Ñуполкі. Калі вам патрÑбна ÑÑˆÑ‡Ñ Ð½ÐµÐ¹ÐºÐ°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ, пачувайцеÑÑ Ð²Ð¾Ð»ÑŒÐ½Ð°, каб даÑлаць запыт падтымкі. +p?> + + + + +
      +
    • Пошук Ñуполак
    • +
    • Ðаведайце Суполку прамоцыÑÑž ()
    • +
    • Ðаведайце Суполку пошуку ()
    • +
    + + +Пішыце Jesse Proulx, () Кіраўнік Ñуполак. +p?> + +. + +/community/index.bml.title=ЦÑнтр Ñуполак + +/community/join.bml.button.join=Далучыцца да Ñуполкі + +/community/join.bml.error.already.member=Ð’Ñ‹ ўжо ўдзельнік гÑтай Ñуполкі. + +/community/join.bml.error.closed=ГÑта Ñуполка Ð·Ð°Ð¼ÐºÐ½Ñ‘Ð½Ð°Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… удзельнікаў. Калі вы жадаеце далучыцца да Ñе, калі лаÑка, кантактуйце з адны з наÑтупных ÑтаршынÑÑž: [[admins]] + +/community/join.bml.error.statusvis.body=Рахунак, у Ñкі вы ўвайшлі, не зьÑўлÑецца актыўным рахункам. + +/community/join.bml.error.statusvis.title=Ðемагчыма далучыцца да Ñуполак + +/community/join.bml.label.addtofriends=Дадаць "[[maintainer]]" да ÑьпіÑу ÑÑброў.
    + +/community/join.bml.label.allowposting=ГÑÑ‚Ð°Ñ Ñуполка дазвалÑе рабіць запіÑÑ‹ ÑžÑім Ñе ўдзельнікам, такім чынам вы маеце доÑтуп, каб рабіць запіÑÑ‹ Ñž Ñе. Калі вы маеце адчыненай праграму-кліент да Жывога Журналу на вашым кампутары, вы павінны выйÑьці Ñ– ўвайÑьці наноў, каб гÑÑ‚Ñ‹ журнал адлюÑтраваўÑÑ Ñž ÑьпіÑе Ñ‚Ñ‹Ñ…, у ÑÐºÑ–Ñ Ð²Ñ‹ можаце рабіць запіÑÑ‹. + +/community/join.bml.label.auth=Ð¥Ð°Ñ†Ñ Ð²Ñ‹ цÑпер пазначаны Ñк удзельнік, у гÑтай Ñуполцы дазволена рабіць запіÑÑ‹ толькі аўтарызаваным удзельнікам. Кантактуйце з адным Ñа Ñтаршынь Ñуполкі, калі вы хочаце атрымаць доÑтуп Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñаў. ÐіжÑй знаходзіцца ÑÑŒÐ¿Ñ–Ñ Ñтаршынь гÑтай Ñуполкі: [[admins]] + +/community/join.bml.label.banned=СтаршынÑ/Ñ– Ñуполкі забаранілі вам далучацца да Ñе. + +/community/join.bml.label.closed=ГÑÑ‚Ð°Ñ Ñуполка замкнёнаÑ. Калі вы зацікаўлены Ñž далучÑньні да Ñе, калі лаÑка, кантактуйце з адным Ñа Ñтаршынь. ÐіжÑй знаходзіцца ÑÑŒÐ¿Ñ–Ñ Ñтаршынь гÑтай Ñуполкі: [[admins]] + +/community/join.bml.label.commlogged=Ð’Ñ‹ ўвайшлі на ÑумеÑны рахунак (рахунак Ñуполкі), а не на ваш аÑабіÑÑ‚Ñ‹ рахунак. + +/community/join.bml.label.errorcomminfo=Ð’Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку не ÑапраўднаÑ. + +/community/join.bml.label.expls=ÐаціÑьніце кнопку ніжÑй, каб далучыцца да Ñуполкі "[[maintainer]]". Ðе вызначайце пункт ніжÑй, калі вы жадаеце далучыцца да Ñуполкі без адлюÑÑ‚Ñ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð·Ð°Ð¿Ñ–Ñаў зь Ñе на вашай Ñтаронцы ÑÑброў. + +/community/join.bml.label.loginfirst=Каб далучыцца да Ñуполкі, вы павінны Ñпачатку ўвайÑьці. + +/community/join.bml.label.membernow=ЦÑпер вы ўдзельнік Ñуполкі [[commname]] + +/community/join.bml.label.sure=Ð’Ñ‹ ўпÑўнены? + +/community/join.bml.reqsubmitted.body=Ваш запыт на далучÑньне быў пададзены ÑтаршынÑм: + +/community/join.bml.reqsubmitted.title=Запыт на далучÑньне пададзены + +/community/join.bml.request.body=Суполка [[comm]] Ð½Ñ Ð¼Ð°Ðµ адкрытага ўдзелу. Калі лаÑка, пацьвердзіце, што вы жадаеце далучыцца да гÑтай Ñуполкі, націÑнуўшы ніжÑй. + +/community/join.bml.request.reason=Ðе абавÑзкова, увÑдзіце прычыну, чаму вы жадаеце далучыцца да гÑтай Ñуполкі: + +/community/join.bml.request.title=Запыт на далучÑньне + +/community/join.bml.success=ПоÑьпех + +/community/join.bml.title=Далучыцца да Ñуполкі + +/community/leave.bml.button.leave=Пакінуць Ñуполку + +/community/leave.bml.label.buttontoleave=ÐаціÑьніце на кнопку ніжÑй, каб пакінуць Ñуполку "[[commname]]". + +/community/leave.bml.label.infoerror=Ð’Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку не ÑапраўднаÑ. + +/community/leave.bml.label.logoutfirst=Каб пакінуць Ñуполку, вы павінны Ñпачатку ўвайÑьці. + +/community/leave.bml.label.removed=ЦÑпер вы выдалены з Ñуполкі [[commname]] + +/community/leave.bml.label.removefromfriends=ТакÑама выдаліць "[[user]]" Ñа ÑьпіÑу ÑÑброў. + +/community/leave.bml.success=ПоÑьпех + +/community/leave.bml.sure=Ð’Ñ‹ ўпÑўнены? + +/community/leave.bml.title=Пакінуць Ñуполку + +/community/manage.bml.commlist.actinfo=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/community/manage.bml.commlist.actions=ДзеÑньні + +/community/manage.bml.commlist.actmembers=[Удзельнікі] + +/community/manage.bml.commlist.actmembers2=Удзельнікі + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] разглÑдаецца + +/community/manage.bml.commlist.actsettings=[УÑтаноўкі] + +/community/manage.bml.commlist.actsettings2=УÑтаноўкі + +/community/manage.bml.commlist.header=Ð’Ð°ÑˆÑ‹Ñ Ñуполкі + +/community/manage.bml.commlist.moderation=Чакае мадÑрацыі + +/community/manage.bml.commlist.moderation.num=[[[num]] у чарзе] + +/community/manage.bml.commlist.none=Ð’Ñ‹ не кіруеце ніводнай Ñуполкай. + +/community/manage.bml.commlist.text=Суполкі, Ñкімі вы кіруеце ці дапамагаеце кіраваць: + +/community/manage.bml.commlist.title=Ðазва + +/community/manage.bml.commlist.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальнiка + +/community/manage.bml.create.header=Стварыць Ñуполку + +/community/manage.bml.create.text=Ð’Ñ‹ такÑама можаце Ñтварыць новую Ñуполку. + +/community/manage.bml.joinmail.body=Ð”Ð»Ñ Ñуполак з закрытым удзелам, вы маеце некалькі опцыÑÑž Ñл.пошты: + +/community/manage.bml.joinmail.email.all=ДаÑылаць ліÑÑ‚ Ñл.пошты кожны раз, калі нехта робіць запыт на далучÑньне + +/community/manage.bml.joinmail.email.digest=ДаÑылаць ліÑÑ‚ Ñл.пошты кожны дзень Ñа ÑьпіÑам уÑÑ–Ñ… разглÑдаемых запытаў + +/community/manage.bml.joinmail.email.none=ÐÑ Ñ‚Ñ€Ñба ліÑтоў Ñл.пошты, Ñ Ð±ÑƒÐ´Ñƒ ўжываць гÑтую Ñтаронку Ð´Ð»Ñ Ð¿Ñ€Ð°Ð³Ð»Ñду новых запытаў + +/community/manage.bml.joinmail.save=Захаваць уÑтаноўкі + +/community/manage.bml.joinmail.title=ÐдмініÑÑ‚Ñ€Ð°Ñ‚Ñ‹ÑžÐ½Ñ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– + +/community/manage.bml.title=Кіраваньне Ñуполкай + +/community/members.bml.error.alreadyadded=[[user]] Ð½Ñ Ð±Ñ‹Ñž дададзены, таму што ён ужо мае доÑтуп да гÑтай Ñуполкі. + +/community/members.bml.error.alreadysent=[[user]] Ð½Ñ Ð¼Ð¾Ð¶Ð° быць дададзены, таму што Ñму ўжо адаÑланы ліÑÑ‚ Ð´Ð»Ñ Ð¿Ð°Ñ†ÑŒÐ²ÐµÑ€Ð´Ð¶Ð°Ð½ÑŒÐ½Ñ: [[datetime]]. Чакайце адказу. + +/community/members.bml.error.invaliduser=Ðемагчыма дадаць Ñуполку ці аб'Ñднаны рахунак: [[user]] + +/community/members.bml.error.noaccess=Толькі Ñтаршыні Ñуполкі маюць магчымаÑьць Ñ€Ñдагаваць ÑьпіÑÑ‹ ўдзельнікаў. Ð’Ñ‹ не ÑÑ‚Ð°Ñ€ÑˆÑ‹Ð½Ñ Ñуполкі [[comm]]. + +/community/members.bml.error.noattr=Ðе выбраны атрыбуты Ð´Ð»Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: [[user]] + +/community/members.bml.error.nocomm=Суполка Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð°. + +/community/members.bml.error.nouser=КарыÑтальнік не Ñ–Ñнуе: [[user]] + +/community/members.bml.key.admin=Ð¡Ñ‚Ð°Ñ€ÑˆÑ‹Ð½Ñ + +/community/members.bml.key.member=Удзельнік + +/community/members.bml.key.moderate=МадÑратар + +/community/members.bml.key.post=ДоÑтуп Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñаў + +/community/members.bml.key.preapprove=Ðе мадÑруецца + +/community/members.bml.key.user=КарыÑтальнік + +/community/members.bml.manage2=Кіраваць Ñуполкамі + +/community/members.bml.name=Ðазва Ñуполкі: [[name]] + +/community/members.bml.nextlink=(ÐаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ñтаронка...) + +/community/members.bml.prevlink=(ПапÑÑ€ÑднÑÑ Ñтаронка...) + +/community/members.bml.success.header=ПоÑьпех + +/community/members.bml.success.message=Ð’Ð°ÑˆÑ‹Ñ Ð·ÑŒÐ¼ÐµÐ½Ñ‹ былі паÑьпÑхова захаваны. + +/community/members.bml.success.return=Ð’Ñрнуцца да ÑьпіÑу + +/community/members.bml.title=Удзельнікі Ñуполкі + +/community/members.bml.update=Ðбнавіць уÑтаноўкі + +/community/moderate.bml.approve.button=Так, ухваліць + +/community/moderate.bml.approve.header=Ухваліць гÑÑ‚Ñ‹ запіÑ? + +/community/moderate.bml.approve.preapprove=ТакÑама дадаць карыÑтальніка [[user]] да ÑьпіÑу папÑÑ€Ñдне-ўхваленых Ð´Ð»Ñ Ð³Ñтай Ñуполкі. + +/community/moderate.bml.approve.text=Ð’Ñ‹ ўпÑўнены, што хочаце ўхваліць гÑÑ‚Ñ‹ запіÑ? + +/community/moderate.bml.brlist.actions=ДзеÑньні + +/community/moderate.bml.brlist.poster=Зрабіў Ð·Ð°Ð¿Ñ–Ñ + +/community/moderate.bml.brlist.subject=Пачатак Ñ‚Ñмы + +/community/moderate.bml.brlist.time=Ð§Ð°Ñ + +/community/moderate.bml.brlist.view=ÐглÑд + +/community/moderate.bml.browse.empty=Чарга мадÑÑ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð¿ÑƒÑтаÑ. + +/community/moderate.bml.browse.header=МадÑраваць Ñуполку + +/community/moderate.bml.browse.text=Тут знаходзіцца чарга мадÑÑ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð´Ð»Ñ Ñуполкі [[link]] + +/community/moderate.bml.choice.approve=Ухваліць + +/community/moderate.bml.choice.reject=Ðдмовіць + +/community/moderate.bml.error.noaccess=Ð’Ñ‹ не мадÑратар Ñуполкі [[comm]]. + +/community/moderate.bml.error.noentry=Ð—Ð°Ð¿Ñ–Ñ Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹ (верагодна ўжо апрацаваны іншым мадÑратарам). + +/community/moderate.bml.error.nolist=Ð’Ñ‹ не мадÑруеце ніводную Ñуполку. + +/community/moderate.bml.error.notfound=Рахунак Ñуполкі Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹. + +/community/moderate.bml.manage=Кіраваць Ñуполкамі + +/community/moderate.bml.moderate=МадÑраваць гÑтую Ñуполку + +/community/moderate.bml.modlist.actions=ДзеÑньні + +/community/moderate.bml.modlist.actmoderate=МадÑраваць + +/community/moderate.bml.modlist.count=Памер чаргі + +/community/moderate.bml.modlist.header=МадÑраваць Ñуполкі + +/community/moderate.bml.modlist.title=Ðазва + +/community/moderate.bml.modlist.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/community/moderate.bml.posted.appheader=ПапÑÑ€Ñдне-ўхвалены + +/community/moderate.bml.posted.apptext=Ðпроч таго, карыÑтальнік [[user]] дададзены да ÑьпіÑу папÑÑ€Ñдне-ўхваленых карыÑтальнікаў Ð´Ð»Ñ Ð³Ñтай Ñуполкі. + +/community/moderate.bml.posted.header=ПоÑьпех + +/community/moderate.bml.posted.proterror=Ð—Ð°Ð¿Ñ–Ñ Ð½Ñ Ð±Ñ‹Ñž дададзены з-за памылкі з пратаколам: [[err]] + +/community/moderate.bml.posted.text=Ð—Ð°Ð¿Ñ–Ñ Ð±Ñ‹Ñž паÑьпÑхова дададзены. + +/community/moderate.bml.reject.button=Так, адхіліць + +/community/moderate.bml.reject.header=Ðдхіліць гÑÑ‚Ñ‹ запіÑ? + +/community/moderate.bml.reject.reason=Ð’Ñ‹ такÑама можаце патлумачыць таму, хто зрабіў гÑÑ‚Ñ‹ запіÑ, Ñвае прычыны Ð´Ð»Ñ Ð°Ð´Ñ…Ñ–Ð»ÐµÐ½ÑŒÐ½Ñ Ð³Ñтага запіÑу. Прычыны будуць адаÑланы гÑтаму карыÑтальніку праз Ñл.пошту. + +/community/moderate.bml.reject.text=Ð’Ñ‹ ўпÑўнены, што хочаце адхіліць гÑÑ‚Ñ‹ запіÑ? + +/community/moderate.bml.rejected.header=Ðдхілены + +/community/moderate.bml.rejected.text=Ð—Ð°Ð¿Ñ–Ñ Ð±Ñ‹Ñž адхілены. + +/community/moderate.bml.title=МадÑраваньне Ñуполкі + +/community/pending.bml.approve.title=Зацьвердзіць удзел? + +/community/pending.bml.no=Ðе + +/community/pending.bml.nopending.body=ÐÑма разглÑдаемых запытаў на ўдзел у гÑтай Ñуполцы + +/community/pending.bml.nopending.title=Ðіхто не разглÑдаецца + +/community/pending.bml.success.added=Ð’Ñ‹ дадалі [[num]] [[?num|аÑобу|аÑобаў]] да гÑтай Ñуполкі. + +/community/pending.bml.success.ignored=[[num]] [[?num|запыт|запыты]] чакаюць разглÑду. + +/community/pending.bml.success.previous=[[num]] [[?num|запыт Ð½Ñ Ð±Ñ‹Ñž|запытаў Ð½Ñ Ð±Ñ‹Ð»Ð¾]] апрацавана, таму што Ñны больш не чакаюць разглÑду. Іншы ÑÑ‚Ð°Ñ€ÑˆÑ‹Ð½Ñ Ð¼Ð°Ð³Ñ‡Ñ‹Ð¼Ð° ўжо апрацаваў [[?num|Ñго|Ñ–Ñ…]]. + +/community/pending.bml.success.rejected=Ð’Ñ‹ адхілілі [[num]] [[?num|запыт|запытаў]] на ўдзел у гÑтай Ñуполцы. + +/community/pending.bml.title=РазглÑд запытаў на ўдзел + +/community/pending.bml.yes=Так + +/community/search.bml.button.clear=ÐчыÑьціць форму + +/community/search.bml.button.search=Шукаць! + +/community/search.bml.checkbox.onlywithpics=Толькі Ñуполкі з малюнкамі + +/community/search.bml.label.byinterest=Па зацікаўленаÑьці + +/community/search.bml.label.bylocation=Па меÑцазнаходжаньні + +/community/search.bml.label.bytime=Па чаÑе Ð°Ð´Ð½Ð°ÑžÐ»ÐµÐ½ÑŒÐ½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ + +/community/search.bml.label.city=Горад: + +/community/search.bml.label.country=Краіна: + +/community/search.bml.label.displayoptions=Паказаць опцыі + +/community/search.bml.label.hasmember=Мае ўдзельнікам + +/community/search.bml.label.othercriteria=Іншы крытÑÑ€ + +/community/search.bml.label.outputformat=Фармат вываду: + +/community/search.bml.label.records=ЗапіÑаў на Ñтаронку: + +/community/search.bml.label.searchcomm=Шукаць па Ñуполкам + +/community/search.bml.label.selecriteria=Выберыце ніжÑй крытÑÑ€, па Ñкому вы хочаце адшукаць Ñуполку. Вынікі вÑртаюцца Ñк перакрыжаваньне ÑžÑÑ–Ñ… крытÑраў пошуку. Іншымі Ñловамі, кожны пункт, на Ñкі вы націÑкаеце, значыць "І", не "ÐБО". + +/community/search.bml.label.sortmethod=ÐœÑтад ÑартаваньнÑ: + +/community/search.bml.label.stateprovince=Штат/ПравінцыÑ: + +/community/search.bml.label.updated=Ðбноўлены за Ð°Ð¿Ð¾ÑˆÐ½Ñ–Ñ + +/community/search.bml.sel.bypicture=Па малюнку + +/community/search.bml.sel.communityname=Ðазва Ñуполкі + +/community/search.bml.sel.commview=ÐглÑд Ñуполкі + +/community/search.bml.sel.day=дзень + +/community/search.bml.sel.month=меÑÑц + +/community/search.bml.sel.simple=ПроÑÑ‚Ñ‹ + +/community/search.bml.sel.updatetime=Ð§Ð°Ñ Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½ÑŒÐ½Ñ + +/community/search.bml.sel.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/community/search.bml.sel.week=тыдзень + +/community/search.bml.title=Пошук па Ñуполках + +/community/settings.bml.button.changecommunity=Ðбнавіць уÑтаноўкі + +/community/settings.bml.button.createcommunity=Стварыць Ñуполку + +/community/settings.bml.error.badpassword=ÐÑÑлушны пароль да Ñуполкі + +/community/settings.bml.error.hasentries=ГÑÑ‚Ñ‹ рахунак ужо мае допіÑÑ‹ Ñ– Ð½Ñ Ð¼Ð¾Ð¶Ð° быць пераўтвораны. + +/community/settings.bml.error.maintainertype=Старшынёй павінен быць чалавек, а Ð½Ñ Ñ–Ð½ÑˆÑ‹ ÑумеÑны рахунак. + +/community/settings.bml.error.noaccess=Толькі Ñтаршыні Ñуполкі могуць Ñ€Ñдагаваць уÑтаноўкі Ñуполкі. Ð’Ñ‹ не ÑÑ‚Ð°Ñ€ÑˆÑ‹Ð½Ñ Ñуполкі [[comm]]. + +/community/settings.bml.error.notcomm=ГÑта не рахунак Ñуполкі. + +/community/settings.bml.error.notfound=Рахунак Ñуполкі Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹. + +/community/settings.bml.error.samenames=Рахунак Ñтаршыні Ñ– рахунак Ñуполкі Ð½Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ быць аднолькавымі. + +/community/settings.bml.label.anybodycan=УÑе ўдзельнікі
    Кожны можа імгненна рабіць запіÑÑ‹, Ñк толькі робіцца ўдзельнікам. + +/community/settings.bml.label.changeheader=ЗьмÑніць уÑтаноўкі Ñуполкі + +/community/settings.bml.label.changetext=Тут вы можаце зьмÑнÑць уÑтаноўкі Ñуполкі, Ñкой валодаеце ці кіруеце. + +/community/settings.bml.label.closedmemb2=Замкнёны ўдзел
    Ðіхто Ð½Ñ Ð¼Ð¾Ð¶Ð° далучыцца да Ñуполкі. + +/community/settings.bml.label.commchanged=УÑтаноўкі Ñуполкі былі зьменены. + +/community/settings.bml.label.commcreate=ГÑта рахунак, Ñкі вы хочаце пераўтварыць у Ñуполку. Ðн павінен быў быць Ñтвораны, але не павінен быў ужывацца Ñк індывідуальны, таму што з-за гÑтага патÑнцыйна шмат людзей змогуць рабіць запіÑÑ‹ Ñž Ñго. + +/community/settings.bml.label.commcreated=Ð’Ð°ÑˆÐ°Ñ Ñуполка цÑпер утворана. + +/community/settings.bml.label.commheader=Рахунак Ñуполкі + +/community/settings.bml.label.comminfo=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку + +/community/settings.bml.label.commopts=Опцыі Ñуполкі + +/community/settings.bml.label.commsite=Сайт Ñуполкі + +/community/settings.bml.label.community=Суполка: + +/community/settings.bml.label.createheader=Стварыць Ñуполку + +/community/settings.bml.label.createtext=ÐдÑюль вы можаце Ñтварыць рахунак Ñуполкі. Суполка - гÑта ÑпÑцыÑльны тып рахунку, да Ñкога могуць далучыцца Ñ–Ð½ÑˆÑ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі Ñ– рабіць запіÑÑ‹. Ð”Ð»Ñ Ð¿Ñ€Ñ‹ÐºÐ»Ð°Ð´Ñƒ Ñуполкі наведайце Seattle Party Community. + +/community/settings.bml.label.howoperates=Выберыце, Ñк будзе працаваць Ð²Ð°ÑˆÐ°Ñ Ñуполка. Ð’Ñ‹ можаце пазьней гÑта зьмÑніць. + +/community/settings.bml.label.maintainer=СтаршынÑ: + +/community/settings.bml.label.maintainer.login=ГÑта не рахунак Ñтаршыні, увайдзіце Ñк нехта іншы. + +/community/settings.bml.label.managepage=Кіраваньне Ñуполкай - дадаваньне ўдзельнікаў, выдаваньне доÑтупу Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñу, прызначÑньне мадÑратараў Ñ– г.д. + +/community/settings.bml.label.membership=Удзел + +/community/settings.bml.label.moderatedmemb=МадÑруемы ўдзел
    Запыты на далучÑньне даÑылаюцца вам Ð´Ð·ÐµÐ»Ñ Ð·Ð°Ñ†ÑŒÐ²ÐµÑ€Ð´Ð¶Ð°Ð½ÑŒÐ½Ñ. + +/community/settings.bml.label.modheader=МадÑраваньне + +/community/settings.bml.label.modis=МадÑруецца
    ÐÐ¾Ð²Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ павінны быць ухвалены мадÑратарам. + +/community/settings.bml.label.modisnt=Ðе мадÑруецца
    ÐÐ¾Ð²Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ зьÑўлÑюцца імгненна. + +/community/settings.bml.label.modtext=Ці мадÑруюцца запіÑÑ‹ Ñž дадзенай Ñуполцы? + +/community/settings.bml.label.nmcan=ÐÑўдзельнікі могуць рабіць запіÑÑ‹
    КарыÑтальнікі могуць рабіць запіÑÑ‹ Ñž Ñуполку без далучÑÐ½ÑŒÐ½Ñ Ð´Ð° Ñе. + +/community/settings.bml.label.nmcant=ÐÑўдзельнікі Ð½Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ рабіць запіÑÑ‹
    КарыÑтальнікі павінны далучыцца да Ñуполкі, каб рабіць запіÑÑ‹ Ñž Ñе. + +/community/settings.bml.label.nmheader=ЗапіÑÑ‹ нÑўдзельнікаў + +/community/settings.bml.label.nmtext=Ці могуць карыÑтальнікі рабіць запіÑÑ‹ Ñž Ñуполку без далучÑÐ½ÑŒÐ½Ñ Ð´Ð° Ñе? + +/community/settings.bml.label.openmemb=Ðдкрыты ўдзел
    Кожны можа далучыцца без ухваленьнÑ. + +/community/settings.bml.label.password=Пароль: + +/community/settings.bml.label.postaccess=ДоÑтуп Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñаў + +/community/settings.bml.label.rellinks=ЗьвÑÐ·Ð°Ð½Ñ‹Ñ ÑпаÑылкі: + +/community/settings.bml.label.selcan=Выберыце ўдзельнікаў
    Толькі Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ ÑžÐ´Ð·ÐµÐ»ÑŒÐ½Ñ–ÐºÑ– змогуць рабіць запіÑÑ‹, паÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾ Ñк ім будзе нададзены доÑтуп праз рахунак Ñтаршыні. + +/community/settings.bml.label.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/community/settings.bml.label.whocanjoin=Хто можа далучыцца да вашай Ñуполкі? + +/community/settings.bml.label.whocanpost=Хто можа рабіць запіÑÑ‹ Ñž вашую Ñуполку? + +/community/settings.bml.manage2=Кіраваць Ñуполкамі + +/community/settings.bml.name=Ðазва Ñуполкі: [[name]] + +/community/settings.bml.success=ПоÑьпех + +/community/settings.bml.title.create=Стварыць Ñуполку + +/community/settings.bml.title.modify=УÑтаноўкі Ñуполкі + +/create.bml.age.check.question=Вам менш за 13 гадоў? + +/create.bml.age.check.yes=Так, мне менш за 13 год. + +/create.bml.age.check2.question=Вам ужо Ñ‘Ñьць 13 гадоў? + +/create.bml.age.check2.yes=Так, мне ўжо Ñ‘Ñьць 13 гадоў. + +/create.bml.age.head=УзроÑÑ‚ + +/create.bml.btn.create=Стварыць журнал + +/create.bml.btn.proceed=ПрацÑг... + +/create.bml.captcha.answer=Ðдказ: + +/create.bml.captcha.audiodesc=Ðапішыце лічбы, што вы чуеце, каб даказаць, што вы Ð½Ñ Ñпам-робат: + +/create.bml.captcha.desc=Ðапішыце літары Ñ– лічбы, што вы бачыце ніжÑй, каб даказаць, што вы Ð½Ñ Ñпам-робат. Калі вы Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ прачытаць Ñ‚ÑкÑÑ‚ ніжÑй, напішыце "AUDIO" Ñ– прайдзіце гукавы Ñ‚ÑÑÑ‚ замеÑÑ‚ гÑтага. + +/create.bml.captcha.invalid=ÐÑÑлушны адказ на папÑÑ€ÑднÑе пытаньне. Спрабуйце ÑшчÑ. + +/create.bml.captcha.play=Прайграць гук + +/create.bml.captcha.prove=Дакажыце, што вы чалавек + +/create.bml.clusterselect.cluster=КлÑÑтар: + +/create.bml.clusterselect.clusternum=КлÑÑтар [[number]] + +/create.bml.clusterselect.head=Выбар клÑÑтара + +/create.bml.clusterselect.nocluster=ÐÑма клÑÑтара + +/create.bml.clusterselect.text=Калі лаÑка, выберыце клÑÑтар, у Ñкім вы хочаце Ñтварыць рахунак. Заўвага: ГÑта Ð¾Ð¿Ñ†Ñ‹Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– наладкі/Ñ‚ÑÑтаваньнÑ. У працоўным варыÑнце карыÑтальнікі не выбіраюць гÑтага, Ñ– нават нічога пра гÑта Ð½Ñ Ð²ÐµÐ´Ð°ÑŽÑ†ÑŒ. + +/create.bml.create.head=СтварÑньне новага журналу + +/create.bml.create.text=Стварыць новы журнал проÑта, кіруйцеÑÑ Ð½Ñ–Ð¶Ñйшымі інÑтрукцыÑмі! + +/create.bml.email.head=Ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/create.bml.email.input.head=ÐÐ´Ñ€Ð°Ñ Ñл.пошты + +/create.bml.email.text2=Ð”Ð»Ñ Ð¿Ð°Ñ†ÑŒÐ²ÐµÑ€Ð´Ð¶Ð°Ð½ÑŒÐ½Ñ Ñ– з прычын бÑÑьпекі, нам патрÑбны ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. Ðн ніколі, ні пры Ñкіх абÑтавінах Ð½Ñ Ñ‚Ñ€Ð°Ð¿Ñ–Ñ†ÑŒ у рукі да ÑпамÑраў. Мы гÑта ненавідзім больш за ÑžÑÑ‘. Прачытайце нашую палітыку прыватнаÑьці Ð´Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі. + +/create.bml.error.coppa.under13=Выбачайце, але з-за абмежаваньнÑÑž COPPA, вы не можаце карыÑтацца Жывым Журналам да даÑÑÐ³Ð½ÐµÐ½ÑŒÐ½Ñ 13 гадоў. Калі лаÑка, вÑртайцеÑÑ Ð½Ð° ваш 13-Ñ‚Ñ‹ дзень нараджÑньнÑ. + +/create.bml.error.email.blank=Ð’Ñ‹ павінны ўвеÑьці Ñвой Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/create.bml.error.email.lj_domain=Ð’Ñ‹ не можаце выкарыÑтоўваць Ð°Ð´Ñ€Ð°Ñ Ð· дамÑну [[domain]], калі Ñтвараеце рахунак. Калі лаÑка, увÑдзіце іншы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/create.bml.error.email.nospaces=У адраÑе Ñл.пошты прабелы не дазволены. Калі вы карыÑтаецеÑÑ AOL, памÑтайце, што ваш ІнтÑрнÑтавы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты - гÑта вашае адлюÑтраванае Ñ–Ð¼Ñ Ð· выдаленымі прабеламі Ñ– дададзеным у канцы @aol.com + +/create.bml.error.password.asciionly=Ð’Ñ‹ можаце выкарыÑтоўваць толькі Ñымбалі ASCII у паролі. + +/create.bml.error.password.blank=Ð’Ñ‹ павінны ўвеÑьці пароль. + +/create.bml.error.password.nomatch=Паролі не Ñупадаюць. + +/create.bml.error.postrequired=Патрабуецца POST + +/create.bml.error.username.blank=Калі лаÑка, увÑдзіце Ñ–Ð¼Ñ Ñ†Ñ– мÑнушку/назву. + +/create.bml.error.username.inuse=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ўжо занÑта; калі лаÑка, увÑдзіце іншае. + +/create.bml.error.username.iscode=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка падобна на запрашальны код, а не на Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/create.bml.error.username.mustenter=Ð’Ñ‹ павінны ўвеÑьці Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/create.bml.error.username.reserved=Выбачайце, але гÑтае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка зарÑзÑрвавана. + +/create.bml.errors.label=Калі лаÑка, выправіце наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð¿Ñ€Ð°Ð±Ð»ÐµÐ¼Ñ‹ Ñ– перадашліце: + +/create.bml.initial.friend.lj_maintenance=Паведамленьні пра плÑÐ½Ð°Ð²Ñ‹Ñ Ñ– незаплÑÐ½Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð¿Ñ‹Ð½ÐºÑ– Ñž працы ÑÑрверу Ñ– Ñго абÑлугоўваньне + +/create.bml.initial.friend.news=Ðавіны Ñ– падзеі Жывога Журналу + +/create.bml.initialfriends=Дадайце гÑÑ‚Ñ‹Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñ‹ да ÑьпіÑу вашых ÑÑброў, каб ведаць уÑе Ð°Ð¿Ð¾ÑˆÐ½Ñ–Ñ Ð½Ð°Ð²Ñ–Ð½Ñ‹ Ñ– інфармацыю пра Ñайт. + +/create.bml.initialfriends.heading=СÑбры пачаткоўца + +/create.bml.name.head=Вашае Ñ–Ð¼Ñ + +/create.bml.name.input.head=ІмÑ: + +/create.bml.name.text=Якое вашае Ñ–Ð¼Ñ Ñ†Ñ– мÑнушка? ГÑÑ‚Ñ‹ будзе зьÑўлÑцца ўверÑе вашага журналу, ды Ñž тым паказальніку карыÑтальнікаў, Ñкі вы выберыце. Вам Ð½Ñ Ñ‚Ñ€Ñба ўжываць ваша поўнае Ñ–Ð¼Ñ Ñ†Ñ– нават Ñапраўднае. + +/create.bml.password.head=Пароль + +/create.bml.password.input.head1=Пароль: + +/create.bml.password.input.head2=Пацьвердзіце пароль: + +/create.bml.password.text=Выберыце пароль. + +/create.bml.proceed.btn.proceed=ПрацÑг... + +/create.bml.proceed.warning=ÐаціÑьніце ПрацÑг адзін раз!! + +/create.bml.success.btn.enterinfo=УвÑдзіце аÑабіÑтую інфармацыю + +/create.bml.success.head=ПоÑьпех! + +/create.bml.success.text1=Ваш журнал быў Ñтвораны. Ð’Ð°Ð¶Ð½Ð°Ñ Ñ€ÑгіÑÑ‚Ñ€Ð°Ñ†Ñ‹Ð¹Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð· далейшымі інÑтукцыÑмі была адаÑлана на [[email]]. УпÑўніцеÑÑ, што вы пацьвердзілі ÑтварÑньне вашага журналу націÑкам на ÑпаÑылку даÑланую на ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/create.bml.success.text2=Ваш Жывы Журнал будзе даÑтупны тут: + +/create.bml.success.text3=ЦÑпер, калі лаÑка, удзÑліце крыху чаÑу, каб увеÑьці некаторую інфармацыю пра ÑÑбе. У аÑноўным гÑта неабавÑзкова, але гÑта даÑьць нам магчымаÑьць больш ведаць пра Ñ‚Ñ‹Ñ…, хто карыÑтаецца Жывым Журналам. + +/create.bml.title=СтварÑньне новага журналу + +/create.bml.tos.error=Ð’Ñ‹ павінны прачытаць Ñ– згадзіцца з правіламі абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ Ð¿ÐµÑ€Ð°Ð´ тым, Ñк Ñтварыць рахунак. + +/create.bml.tos.haveread=Я прачытаў Ñ– згодны з Правіламі абÑлугоўваньнÑ. + +/create.bml.tos.heading=Правілы абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ + +/create.bml.tos.p1.2=Перад працÑгам вы павінны прачытаць Ñ– згадзіцца з Правіламі абÑлугоўваньнÑ. + +/create.bml.useacctcodes.entercode=Каб Ñтварыць новы рахунак, увÑдзіце код Ð´Ð»Ñ ÑтварÑÐ½ÑŒÐ½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ°. Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі, глÑдзіце Як мне Ñтварыць рахунак? + +/create.bml.useacctcodes.welcome=Запрашаем + +/create.bml.username.box.head=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/create.bml.username.charsallowed=Вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка можа ўтрымліваць толькі Ð¼Ð°Ð»Ñ‹Ñ Ð»Ñ–Ñ‚Ð°Ñ€Ñ‹ (a-z), лічбы (0-9) Ñ– знак падкрÑÑÑŒÐ»ÐµÐ½ÑŒÐ½Ñ (_).
    Дадаткова, Ñно не павінна быць даўжÑй за 15 ÑымбалÑÑž + +/create.bml.username.forpaidaccts=Ці, Ð´Ð»Ñ Ð°Ð¿Ð»Ð°Ñ‡Ð°Ð½Ñ‹Ñ… рахунакаў: + +/create.bml.username.head=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/create.bml.username.ljaddress=Ваш журнал будзе па гÑÑ‚Ñ‹Ñ… адраÑах: + +/create.bml.username.text=Кожны карыÑтальнік [[sitename]] павінен мець непаўторнае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. Вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка - гÑта тое, што зьÑўлÑцца Ñž адраÑе вашага журналу Ñ– тое, што вы ўжываеце Ð´Ð»Ñ ÑžÐ²Ð°Ñ…Ð¾Ð´Ñƒ на наш ÑÑрвер [[sitename]]. Яно такÑама адлюÑтроўваецца, калі вы пакідаеце камÑнтары Ñž журналах іншых людзей. + +/create.bml.username.username=Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/customize/index.bml.change=ЗьмÑніць + +/customize/index.bml.choose=Ð’Ñ‹ хочаце ўжываць Ñтарую ÑÑ‹ÑÑ‚Ñму ÑтылÑ, ці новую? + +/customize/index.bml.choose.header=Выберыце ÑÑ‹ÑÑ‚Ñму ÑÑ‚Ñ‹Ð»Ñ + +/customize/index.bml.choose.s1=Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÑÑ‹ÑÑ‚Ñма (S1) + +/customize/index.bml.choose.s2=ÐÐ¾Ð²Ð°Ñ ÑÑ‹ÑÑ‚Ñма (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ðемагчыма згенÑраваць Ñхему карыÑтальніка + +/customize/index.bml.error.fail_create_style=Памылка пры ÑтварÑньні новага Ñтылю. + +/customize/index.bml.error.not_your_layout=ÐÑ Ð²Ð°ÑˆÐ°Ñ Ñхема. + +/customize/index.bml.error.not_your_theme=ÐÑ Ð²Ð°ÑˆÐ°Ñ Ñ‚Ñма + +/customize/index.bml.error.no_core_parent=ÐÑма бацькоўÑкага Ñдра? + +/customize/index.bml.previews=(ПерадпраглÑды) + +/customize/index.bml.s1=Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÑÑ‹ÑÑ‚Ñма Ñтылю наладжваецца праз Ñтаронку Мадыфікаваць журнал. + +/customize/index.bml.s1.header=Ужываньне S1 + +/customize/index.bml.s2.advanced.denied=Толькі ўладальнікі платных, Ñталых ці рахункаў раньніх удзельнікаў могуць ужываць зону пашыранай наладкі. Даведацца пра перавагі платнага рахунку. + +/customize/index.bml.s2.advanced.header=ÐŸÐ°ÑˆÑ‹Ñ€Ð°Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´ÐºÑ– + +/customize/index.bml.s2.advanced.permitted=Каб Ñтварыць новую Ñхему ці Ñтыль з чарнавіка, наведайце цÑнтр пашыранай наладкі. + +/customize/index.bml.s2.customize=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÑžÑтаноўкі залежаць ад Ñхемы. + +/customize/index.bml.s2.customize.header=Крок 2: Ðаладка Ñхемы + +/customize/index.bml.s2.customize.language=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð¼Ð¾Ð²Ñ‹ поўнаÑьцю ці чаÑткова падтрымліваюцца гÑтай Ñхемай. + +/customize/index.bml.s2.customize.language.custom=(УлаÑны) + +/customize/index.bml.s2.customize.language.header=Мова + +/customize/index.bml.s2.customize.settings=Калі вы жадаеце ÑÑˆÑ‡Ñ Ð±Ð¾Ð»ÑŒÑˆ наладзіць ваш журнал, можаце зрабіць гÑта з дапамогай індывідуальных уÑтановак. + +/customize/index.bml.s2.customize.settings.delete=Прыбраць наладкі + +/customize/index.bml.s2.customize.settings.delete.confirm=Ð’Ñ‹ ўпÑўнены, што хочаце выдаліць гÑÑ‚Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´ÐºÑ–? + +/customize/index.bml.s2.customize.settings.edit=РÑдагаваньне наладак + +/customize/index.bml.s2.customize.settings.header=ЗьмÑніць Ñ–Ð½Ð´Ñ‹Ð²Ñ–Ð´ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ñ ÑžÑтаноўкі + +/customize/index.bml.s2.customize.settings.new=Ðаладка + +/customize/index.bml.s2.customize.themes=Выберыце з наÑтупных неабавÑзковых Ñ‚Ñм Ð´Ð»Ñ Ð³Ñтай Ñхемы. + +/customize/index.bml.s2.customize.themes.default=(Схема па змоўчаньні) + +/customize/index.bml.s2.customize.themes.header=ТÑмы + +/customize/index.bml.s2.layout=Выберыце вашую Ñхему. З-за таго, што выбар Ñ‚Ñмы Ñ– ўлаÑÐ½Ñ‹Ñ Ð¼Ð°Ð´Ñ‹Ñ„Ñ–ÐºÐ°Ñ†Ñ‹Ñ– залежаць ад вашай Ñхемы, зьмена гÑтай уÑтаноўкі адменіць уÑе папÑÑ€ÑÐ´Ð½Ñ–Ñ Ñ€Ñдагаваньні, што вы маглі зрабіць. + +/customize/index.bml.s2.layout.header=Крок 1: Схема + +/customize/index.bml.s2.related.editinfo.about=УÑтанавіце назвы вашага журналу Ñ– ÑžÑÑлÑÐºÑ–Ñ Ð¾Ð¿Ñ†Ñ‹Ñ–. + +/customize/index.bml.s2.related.header=ЗьвÑÐ·Ð°Ð½Ñ‹Ñ Ñтаронкі + +/customize/index.bml.s2.related.links.about=ÐÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ñтылі могуць уключаць ваш ÑÑŒÐ¿Ñ–Ñ ÑпаÑылак. + +/customize/index.bml.s2.related.modify.about=Выберыце набор выÑваў наÑтрою Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° журналу. + +/customize/index.bml.title=Ðаладка журналу + +/delcomment.bml.changeoptions=Заўвага: Са Ñтаронкі [[link]], вы можаце выбраць каму дазволіць піÑаць камÑнтары: уÑім, зарÑгіÑтраваным карыÑтальнікам, ці толькі ÑÑбрам. + +/delcomment.bml.confirm.banuser=Забраніць карыÑтальніку [[user]] рабіць камÑнтары Ñž вашым журнале + +/delcomment.bml.confirm.body=Ð’Ñ‹ ўпÑўнены, што хочаце выдаліць гÑÑ‚Ñ‹ камÑнтар? + +/delcomment.bml.confirm.head=Выдаліць гÑÑ‚Ñ‹ камÑнтар? + +/delcomment.bml.confirm.spam=Пазначыць гÑÑ‚Ñ‹ камÑнтар Ñк Ñпам + +/delcomment.bml.confirm.submit=Выдаліць камÑнтар + +/delcomment.bml.error.alreadydeleted=Пазначаны камÑнтар ужо быў выдалены. + +/delcomment.bml.error.cantdelete=КамÑнтар можа быць выдалены толькі Ñго аўтарам ці ўладальнікам журналу. + +/delcomment.bml.error.cantdelete.comm=КамÑнтар можа быць выдалены толькі Ñго аўтарам, аўтарам журнальнага запіÑу, ці Ñтаршынёй Ñуполкі. + +/delcomment.bml.error.invalidtype=ÐÑÑлушны тып камÑнтару. ГÑÑ‚Ð°Ñ Ñтаронка падтрымлівае толькі камÑнтары да журнальных запіÑаў. + +/delcomment.bml.error.nocomment=Пазначаны камÑнтар не Ñ–Ñнуе. + +/delcomment.bml.success.andban=КамÑнтар быў выдалены, а карыÑтальніку [[user]] было забаронена рабіць камÑнтары Ñž вашым журнале. + +/delcomment.bml.success.head=Выдалены + +/delcomment.bml.success.noban=КамÑнтар быў выдалены. + +/delcomment.bml.success.spam=Дадаткова, адмініÑтратарам гÑтага Ñайту было паведамлена, што гÑÑ‚Ñ‹ камÑнтар быў Ñпамам. ДзÑкуй за вашую Ñправаздачу. + +/delcomment.bml.title=Выдаленьне камÑнтару + +/developer/index.bml.clients<< +Такім чынам, вы жадаеце Ñтварыць ці палепшыць праграму-кліент Жывога Журналу Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð¹ плÑтформы? Цудоўна! +ÐіжÑй знаходзÑцца Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð½ÐµÐ°Ð±Ñ…Ð¾Ð´Ð½Ñ‹Ñ ÐºÑ€Ñ‹Ð½Ñ–Ñ†Ñ‹, ÑÐºÑ–Ñ Ñ€Ð°Ñказваюць, Ñк працуе Жывы Журнал. +. + +/developer/index.bml.clients.header=СтварÑньне праграмаў-кліентаў да Жывога Журналу + +/developer/index.bml.clients.links<< +
    +  
    Пратакол Жывога Журналу СÑрвер<->Кліент
    +  
    ДаведайцеÑÑ Ñк праграма-кліент на вашым кампутары кантактуе з ÑÑрверам Жывога Журналу Ñ– наадварот. +  Разуменьне гÑтага - першы крок перад тым, Ñк вы будзеце раÑпрацоўваць ці ўдаÑканальваць праграму-кліент Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð¹ плÑтформы.
    +  
    ÐŸÐ¾ÑžÐ½Ð°Ñ Ð´Ð°ÐºÑƒÐ¼ÑÐ½Ñ‚Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° пратакол
    +  
    УÑÑлÑÐºÑ–Ñ Ñ€Ñжымы Ñ– мÑтады пратаколу.
    +  
    Ð¡ÑŒÐ¿Ñ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ð°Ñž-кліентаў
    +  
    Ð¡ÑŒÐ¿Ñ–Ñ Ð±Ð°Ð»ÑŒÑˆÑ‹Ð½Ñ– праграмаў-кліентаў ужываемых Ð´Ð»Ñ ÑувÑзі з Жывым Журналам. БольшаÑьць гÑÑ‚Ñ‹Ñ… праграмаў маюць адкрыты код, Ñ– ÑžÑе Ñны бÑÑплатныÑ. ГÑта тое меÑца, дзе можна знайÑьці добры прыклад Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð¹ праграмы-кліента.
    +
    +. + +/developer/index.bml.code=Каб убачыць, што прымушае працаваць Жывы Журнал, а такÑама коды некаторых з даÑтупных праграмаў-кліентаў, глÑдзіце Ñтаронку Коду. + +/developer/index.bml.code.header=Сховішча коду Жывога Журналу + +/developer/index.bml.dbschema<< +Хаціце даведацца пра Ñхему базы зьвеÑтак? +SQL Ð´Ð»Ñ ÑтаврÑÐ½ÑŒÐ½Ñ ÑžÑÑ–Ñ… табліц Ñ– памнажÑÐ½ÑŒÐ½Ñ Ñ–Ñ… знаходзіцца разам з кодам ÑÑрвера. +. + +/developer/index.bml.dbschema.header=Схема базы зьвеÑтак + +/developer/index.bml.embedding=Хочаце ўклаÑьці ваш журнал у вашую хатнюю Ñтаронку? ÐÑьць некалькі шлÑхоў каб зрабіць гÑта, залежыць ад таго Ñкі від кантролю над вашым ÑÑрверам вы маеце. Ð’Ñ‹ павінны непакоіцца пра гÑта толькі калі не жадаеце, каб www.livejournal.com было Ñž адраÑе вашага журналу. + +/developer/index.bml.embedding.header=Укладаньне Жывога Журнала Ñž іншы Ñайт + +/developer/index.bml.notice.header=Заўвага + +/developer/index.bml.notice1=ÐаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð´Ð°Ñ‚Ñ‹Ñ‡Ñ‹Ñ†ÑŒ толькі праграміÑтаў Ñ– праÑунутых карыÑтальнікаў. Калі вы хочаце ўжываць Жывы Журнал, каб трымаць ваш журнал, выдатна! Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі не павінны клапаціцца пра гÑта. + +/developer/index.bml.notice2=ÐіжÑйшы зьмеÑÑ‚ падзелены на дзьве чаÑткі: інфармацыÑ, Ñк наладзіць выглÑд Ñтаронак Жывога Журналу, Ñ– Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° ÑтварÑньне праграмаў-кліентаў да ÑÑрверу Жывога Журналу. + +/developer/index.bml.styles=Ðе падабаецца выглÑд Ñтаронак вашага журналу? Ðе хвалюйцеÑÑ... уÑÑ‘ падлÑгае зьменам, Ñ– калі вы прачытаеце наÑтупную дакумÑнтацыю, вы будзеце ведаць уÑÑ‘ што Ñ‚Ñ€Ñба, каб прымуÑіць Ñтаронкі вашага журналу выглÑдаць так, Ñк вам захочацца. + +/developer/index.bml.styles.header=Ðаладка выглÑду Жывога Журналу + +/developer/index.bml.styles.s1.header=СыÑÑ‚Ñма Ñтылю 1 + +/developer/index.bml.styles.s1.system=СыÑÑ‚Ñма Ñтылю + +/developer/index.bml.styles.s1.system.about=Ðгульны аглÑд наладкі першай ÑÑ‹ÑÑ‚Ñмы Ñтылю. + +/developer/index.bml.styles.s1.varlist=Ð¡ÑŒÐ¿Ñ–Ñ Ð·ÑŒÐ¼ÐµÐ½Ð½Ñ‹Ñ… + +/developer/index.bml.styles.s1.varlist.about=ПроÑÑ‚Ñ‹ альфабÑтны ÑÑŒÐ¿Ñ–Ñ ÑƒÑÑ–Ñ… зьменных, што вы можаце наладжваць. + +/developer/index.bml.styles.s1.views=ÐглÑд тыпаў + +/developer/index.bml.styles.s1.views.about=Ð¡ÑŒÐ¿Ñ–Ñ Ñ€Ð¾Ð·Ð½Ñ‹Ñ… тыпаў шлÑхоў, Ñк вы можаце праглÑдаць ваш журнал, Ñ– дÑтальна пра кожны. + +/developer/index.bml.styles.s2.header=СыÑÑ‚Ñма Ñтылю 2 + +/developer/index.bml.styles.s2.layerbrowse=ПраглÑдач Ñхемы S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Поўны ÑÑŒÐ¿Ñ–Ñ Ð³Ñ€Ð°Ð¼Ð°Ð´Ð·ÐºÑ–Ñ… Ñхемаў S2, ÑÐºÑ–Ñ ÑžÐ²Ð°Ñ…Ð¾Ð´Ð·Ñць у ÑÑ‹ÑÑ‚Ñму ÑтылÑÑž S2. Тут знаходзÑцца Ñхемы Ñдра, ÑÐºÑ–Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ð°ÑŽÑ†ÑŒ Ð±Ð°Ð·Ð°Ð²Ñ‹Ñ Ð·ÑŒÐ¼ÐµÐ½Ð½Ñ‹Ñ, функцыі Ñ– клÑÑÑ‹, ÑÐºÑ–Ñ Ñ€Ð¾Ð±Ñць S2 моцнай мовай, Ñкой Ñна ўжо зьÑўлÑецца. + +/developer/index.bml.styles.s2.manual=Даведнік па S2 + +/developer/index.bml.styles.s2.manual.about=ÐŸÐ¾ÑžÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° ўжываньне S2 на Жывым Журнале. + +/developer/index.bml.title=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð´Ð»Ñ Ñ€Ð°Ñпрацоўшчыкаў + +/directory.bml.browse.country.desc=Выберыце краіну, каб чытаць журналы з гÑтай краіны... + +/directory.bml.browse.country.title=ПраглÑд журналаў па краіне + +/directory.bml.browse.usa.desc=ÐаціÑьніце ніжÑй на амÑрыканÑкі штат, каб чытаць журналы з гÑтага штату, ці націÑьніце на назву краіны ніжÑй мапы, каб чытаць журналы з гÑтай краіны. + +/directory.bml.browse.usa.title=ПраглÑд журналаў па амÑрыканÑкіх штатах + +/directory.bml.error.accounttype=Выбачайце, тып вашага рахунку не дазвалÑе вам карыÑтацца паказальнікам карыÑтальнікаў, ці вы не ўвайшлі. Калі тып вашага рахунку дазвалÑе выкарыÑтаньне паказальніка карыÑтальнікаў, упÑўніцеÑÑ, што вы ўвайшлі Ñ– паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/directory.bml.navcrap.matches=СупадзеньнÑÑž: [[count]] + +/directory.bml.navcrap.xofy=Паказана Ñтаронка [[curpage]] з [[totpages]] (запіÑÑ‹ [[reca]]-[[recb]]) + +/directory.bml.open=Ðдчыніць + +/directory.bml.post=ЗапіÑаць + +/directory.bml.search.monkey=Сотні навучаных малпаў цÑпер бегаюць, шукаючы вынікі вашага запыту. Пачакайце. + +/directory.bml.search.new=Ðовы запыт + +/directory.bml.search.overflow=Вынікі пошуку абмежаваны да [[count]]. Калі лаÑка, пераглÑдзіце Ñвой запыт. + +/directory.bml.search.title=У пошуках + +/directory.bml.update=Ðбнова: + +/directory.bml.user=КарыÑтальнік + +/doc/index.bml.about=Запрашаем у Ñховішча дакумÑнтацыі Жывога Журналу, дзе вы можаце знайÑьці інфармацыю па большаÑьці пытаньнÑÑž пра працу Жывога Журналу ці праграмнага забÑÑÑŒÐ¿ÐµÑ‡Ð°Ð½ÑŒÐ½Ñ ÑÑрверу. Калі лаÑка, выберыце Ñ‚Ñму ніжÑй: + +/doc/index.bml.about.header=Запрашаем + +/doc/index.bml.docs.faq.about=Пытаньні Ñ– адказы пра LiveJournal.com + +/doc/index.bml.docs.faq.title=Пытаньні Ñ– адказы + +/doc/index.bml.docs.guides.about=Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ð° ПытаньнÑÑ… Ñ– адказах + +/doc/index.bml.docs.guides.title=Даведнікі + +/doc/index.bml.docs.header=ДакумÑнты + +/doc/index.bml.docs.howto.about=Падказкі, каб дапамагчы вам перарабіць ваш рахунак Жывога Журналу + +/doc/index.bml.docs.server.about=УÑÑ‘ што вам Ñ‚Ñ€Ñба ведаць, каб уÑталÑваць, адмініÑтраваць, Ñ– ўжываць наладку Жывога Журналу + +/doc/index.bml.docs.server.title=Даведнік ÑÑрверу Жывога Журналу + +/doc/index.bml.docs.tour.about=РаÑпрацаваны Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… наведвальнікаў, каб пазнаёміць Ñ–Ñ… з Ñайтам + +/doc/index.bml.docs.tour.title=Падарожжа + +/doc/index.bml.title=ДакумÑÐ½Ñ‚Ð°Ñ†Ñ‹Ñ + +/doc/index.bml.volunteering.about=Калі вы хочаце дапамагчы з дакумÑнтацыÑй па Жывому Журналу, паглÑдзіце наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñ„Ð¾Ñ€ÑƒÐ¼Ñ‹: + +/doc/index.bml.volunteering.header=Добраахвотніцтва + +/doc/index.bml.volunteering.ljsysdoc=ДыÑкуÑÑ–Ñ– пра ÑÑ‹ÑÑ‚Ñму дакумÑнтацыі па Жывому Журналу + +/doc/index.bml.volunteering.ljuserdoc=Скончыць дыÑкуÑÑ–Ñ– пра дакумÑнтацыі + +/doc/tour/index.bml.clients.caption=Праграмы-кліенты да Жывога Журналу - гÑта невÑÐ»Ñ–ÐºÑ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹, ÑÐºÑ–Ñ Ð¿Ñ€Ð°Ñ†ÑƒÑŽÑ†ÑŒ на вашым кампутары, дазвалÑючы вам рабіць Ð½Ð¾Ð²Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ Ñž журнал не адчынÑючы вакно праглÑдача, калі вы знаходзіцеÑÑ Ð°Ð½Ð»Ñйн. Праграмы-кліенты прадÑтаўлены амаль Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð¹ платформы, Ñ– лёгка наладжваюцца. + +/doc/tour/index.bml.clients.title=Праграмы-кліенты + +/doc/tour/index.bml.comms.caption=Жывы Журнал - гÑта вÑÐ»Ñ–ÐºÐ°Ñ Ñ–Ð½Ñ‚ÑÑ€Ð°ÐºÑ‚Ñ‹ÑžÐ½Ð°Ñ Ñуполка, Ð´Ð»Ñ Ð²Ð°Ñ Ð½Ðµ павінны быць Ñюрпрызам, што Ñ–Ñнуе шмат карыÑтальнікаў з падобнымі зацікаўленаÑьцÑмі. У такіх выпадках, мы даем магчымаÑьць Ñтвараць Ñуполкі, ці журналы, у ÑÐºÑ–Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ рабіць запіÑÑ‹ шмат карыÑтальнікаў. + +/doc/tour/index.bml.comms.title=Суполкі + +/doc/tour/index.bml.create.caption=Жывы Журнал - гÑта Ñуполка журналаў Ð¿Ð°Ð±ÑƒÐ´Ð°Ð²Ð°Ð½Ð°Ñ Ð½Ð° ўдзелу карыÑтальнікаў. ГÑÑ‚Ð°Ñ Ñтаронка тлумачыць, што ўдзел цÑгне за Ñабой, чаму важны ўдзел, Ñ– Ñž чым Ñго карыÑьць. Яна такÑама ўключае форму ÑтварÑÐ½ÑŒÐ½Ñ Ð½Ð¾Ð²Ð°Ð³Ð° рахунку. + +/doc/tour/index.bml.create.title=СтварÑньне рахунку + +/doc/tour/index.bml.friends.caption=Ð’Ñ‹ такÑама маеце магчымаÑьць Ñачыць за Жывымі Журналамі Ñваіх ÑÑброў, дзÑкуючы ўбудаванай мажліваÑьці "ÑÑброўÑтва". Калі вы знойдзеце цікавы Ð´Ð»Ñ ÑÑбе журнал, дадайце Ñго да ÑьпіÑу ÑÑброў, што дазволіць вам чытаць допіÑÑ‹ вашых ÑÑброў на адной Ñтаронцы. + +/doc/tour/index.bml.friends.title=СÑбры + +/doc/tour/index.bml.intro.caption=ГÑтае падарожжа раÑпрацавана Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… наведвальнікаў, каб пазнаёміць з бачынай. Яно пакажа, дзе знаходзÑцца найбольш Ð²Ð°Ð¶Ð½Ñ‹Ñ Ñ‡Ð°Ñткі, а такÑама раÑкажа пра Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ñ†Ñ–ÐºÐ°Ð²Ñ‹Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьці. + +/doc/tour/index.bml.intro.title=Запрашаем + +/doc/tour/index.bml.modify.caption=ТакÑама магчыма перарабіць ваш журнал у некалькіх розных напрамках, выкарыÑтоўваючы Ð·Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ Ñтылі Ñ– Ñхемы колераў. Зрабіце Ñвой журнал наÑтолькі непаўторым, наколькі захочаце! + +/doc/tour/index.bml.modify.title=ПÑÑ€ÑÐ°Ð½Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ‹Ñ + +/doc/tour/index.bml.nav.next=ÐаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ --> + +/doc/tour/index.bml.nav.prev=<-- ПапÑÑ€ÑднÑÑ + +/doc/tour/index.bml.profile.caption=Удзельнікам Жывога Журналу нададзена магчымаÑьць дадаваць інфармацыю пра ÑÑбе Ñž Ñвае профілі, гÑта даÑьць нам магчымаÑьць даведацца, хто карыÑтаецца нашым Ñайтам, Ñ– Ñк Ñ–Ñ… лепш абÑлугоўваць. Ðднак, нічога з гÑтага не зьÑўлÑецца абавÑзковым, Ð°Ð´Ð·Ñ–Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ð°Ñ‚Ñ€ÑбнаÑ, каб пачаць карыÑтацца Жывым Журналам - гÑта імÑ, Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ñ– пароль. + +/doc/tour/index.bml.profile.title=Профілі + +/doc/tour/index.bml.sitemap.caption=СпадзÑемÑÑ, гÑтае падарожжа дало вам карыÑную пачатковую інфармацыю пра Ñайт Ñ– абÑлугоўваньне Жывога Журналу. Калі вам патрабуецца дапамога зьвÑÐ·Ð°Ð½Ð°Ñ Ð· Жывым Журналам, вольна кантакуйце з нашым аддзелам падтрымкі. Калі вы хочаце паблукаць далей, глÑдзіце мапу Ñайту, там вы ўбачыце уÑе Ñтаронкі нашага Ñайту. + +/doc/tour/index.bml.sitemap.title=Мапа Ñайту + +/doc/tour/index.bml.support.caption=Старонкі падтрымкі - гÑта меÑца, дзе тлумачыцца, што такое Жывы Журнал, там знаходзÑцца пытаньні Ñ– адказы пра Ñайт, Ñ– Ñ–Ð½ÑˆÐ°Ñ ÐºÐ°Ñ€Ñ‹ÑÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° паÑлугі, кампанію, Ñ– ўвогуле Ñуполку. + +/doc/tour/index.bml.support.title=Ðтрыманьне дапамогі + +/doc/tour/index.bml.title=Падарожжа - [[title]] + +/doc/tour/index.bml.update.caption=Ðбнаўленьне Журналу - гÑта Ñамае ÑÑрца паÑлугаў Жывога Журналу. ГÑта меÑца, дзе мы даем магчымаÑьць удзельнікам раÑкрываць Ñвае душы Ñ– казаць тое, што Ñны думаюць. Ðбнаўленьне Журналу - гÑта проÑта. Ðапішыце Ñвае думкі Ñž адпаведную форму, а потым націÑьніце на кнопку "Зрабіць запіÑ". ТакÑама мы дазвалÑем Ð¿Ð°Ð»ÐµÐ¿ÑˆÐ°Ð½Ñ‹Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьці на Ñтаронцы Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½ÑŒÐ½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ, напрыклад магчымаÑьць праверкі Ñ‚ÑкÑту на наÑўнаÑьць памылак (толькі ангельÑÐºÐ°Ñ Ð¼Ð¾Ð²Ð°), ці магчымаÑьць даць больш разнаÑтайную інфармацыю пра ваш запіÑ, Ñк бÑÐ³ÑƒÑ‡Ð°Ñ Ð¼ÑƒÐ·Ñ‹ÐºÐ° ці наÑтрой. + +/doc/tour/index.bml.update.title=Ðбнаўленьне + +/editinfo.bml.advanced.about=Ðе зьвÑртайце ўвагі на гÑта, калі вы Ð½Ñ Ð²ÐµÐ´Ð°ÐµÑ†Ðµ, што гÑта такое. + +/editinfo.bml.advanced.title=ÐŸÐ°ÑˆÑ‹Ñ€Ð°Ð½Ñ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– + +/editinfo.bml.allowshowcontact.about=Ð’Ñ‹ можаце трымаць гÑту опцыю ўключанай. ГÑта даÑьць магчымаÑьць людзÑм канактаваць з вамі праз ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, нумар ICQ, ці адлюÑтраванае Ñ–Ð¼Ñ Ð²Ð°ÑˆÐ°Ð¹ праграмы абмену паведамленьнÑмі AOL, уÑÑ‘ на вашым Жывым Журнале. + +/editinfo.bml.allowshowcontact.email=Калі бачны, то Ð°Ð´Ñ€Ð°Ñ Ñл.пошты будзе паказаны Ñк: + +/editinfo.bml.allowshowcontact.email.actual_only=Толькі дзейны Ð°Ð´Ñ€Ð°Ñ + +/editinfo.bml.allowshowcontact.email.both=Ðбодва (дзейны + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Толькі Ð°Ð´Ñ€Ð°Ñ Ð–Ñ‹Ð²Ð¾Ð³Ð° Журналу + +/editinfo.bml.allowshowcontact.email.neither=Ðіводны. Ðе паказваць ні адзін Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/editinfo.bml.allowshowcontact.email.no_show=Ðе паказваць Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.allowshowcontact.email.show=Паказваць Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.allowshowcontact.email.withdomainaddr=З дапамогай опцыі вышÑй, вы можаце выбраць ці Ñхаваць ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты (пры гÑтым паказваючы іншую кантактную інфармацыю), ці паказваць Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Жывога Журналу (толькі Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ–), ці Ñапраўдны Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, ці абодва з Ñ–Ñ…. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=З дапамогай опцыі вышÑй, вы можаце выбраць ці Ñхаваць ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты (пры гÑтым паказваючы іншую кантактную інфармацыю). + +/editinfo.bml.allowshowcontact.title=Паказваць вашую кантактную інфармацыю Ñž вашым Жывым Журнале? + +/editinfo.bml.allowshowinfo.about=Ðдзначце тут, калі вы хочаце, каб вашы горад/штат/краіны Ñ– дзень нараджÑÐ½ÑŒÐ½Ñ Ð±Ñ‹Ð»Ñ– бачны Ð´Ð»Ñ Ñ–Ð½ÑˆÑ‹Ñ… карыÑтальнікаў. + +/editinfo.bml.allowshowinfo.title=Паказваць меÑцазнаходжаньне Ñ– дзень нараджÑньнÑ? + +/editinfo.bml.autotranslate.about=ВыкарыÑтоўвайце гÑтую опцыю, каб паведаміць Жывому Журналу Ñž Ñкім кадаваньні зроблены Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ перад тым, Ñк Ñайт пераробіць Ñ–Ñ… у Юнікод. Калі вы пішыце па-беларуÑку, выберыце "Cyrillic (Windows)". + +/editinfo.bml.autotranslate.header=Ðўтаматычна перарабіць Ñ€Ð°Ð½ÐµÐ¹ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ Ñž: + +/editinfo.bml.bday.title=Дзень нараджÑÐ½ÑŒÐ½Ñ + +/editinfo.bml.bday.year.opt=год не абавÑзковы + +/editinfo.bml.bdayreminders.about=Калі вы хочаце атрымліваць напаміны пра дні нараджÑÐ½ÑŒÐ½Ñ Ð²Ð°ÑˆÑ‹Ñ… ÑÑброў з Жывога Журналу, адзначце тут. + +/editinfo.bml.bdayreminders.header=ДаÑылаць мне напаміны пра дні нараджÑÐ½ÑŒÐ½Ñ (цÑпер не магчыма) + +/editinfo.bml.bio.about=Тут вы можаце напіÑаць невÑлічкую аўтабіÑграфію. Яна будзе адлюÑтравана на Ñтаронцы Пра карыÑтальніка. + +/editinfo.bml.bio.header=Пра Ð²Ð°Ñ + +/editinfo.bml.blockrobots.about=Калі вы адзначыце тут, робаты зьнікнуць. ÐÑ ÑžÑе робаты паважаюць правілы. + +/editinfo.bml.blockrobots.header=ЗаблÑкаваць Робатаў/Павукоў ад індÑкÑацыі вашага журналу + +/editinfo.bml.chat.icquin.title=Ðумар ICQ + +/editinfo.bml.chat.msnusername.title=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка MSN + +/editinfo.bml.city.title=Горад + +/editinfo.bml.country.choose=Вызначы краіну + +/editinfo.bml.country.title=Краіна + +/editinfo.bml.donotlog=Ðе + +/editinfo.bml.email.title=Эл.пошта + +/editinfo.bml.enableboards.about=Ðдзначце тут, каб людзі маглі камÑнтаваць запіÑÑ‹ Ñž вашым журнале. + +/editinfo.bml.enableboards.header=Дазволіць дошкі камÑнтараў + +/editinfo.bml.encoding.about=Ðе хвалюйцеÑÑ Ð½Ð°ÐºÐ¾Ð½Ñ‚ гÑÑ‚Ñ‹Ñ… опцый. Звычайна толькі міжнародным карыÑтальнікам, што пішуць на некалькіх мовах, Ñ‚Ñ€Ñба тут нешта зьмÑнÑць. + +/editinfo.bml.encoding.header=Опцыі ÐºÐ°Ð´Ð°Ð²Ð°Ð½ÑŒÐ½Ñ + +/editinfo.bml.error.day.notinmonth=ÐÑÑлушны дзень Ð´Ð»Ñ Ð´Ð°Ð´Ð·ÐµÐ½Ð°Ð³Ð° меÑÑца. + +/editinfo.bml.error.day.outofrange=ÐÑÑлушны дзень нараджÑньнÑ. УвÑдзіце дзень паміж 1-31. + +/editinfo.bml.error.email.lj_domain=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ ўвеÑьці Ð°Ð´Ñ€Ð°Ñ Ñл.пошты @[[domain]]. УвÑдзіце ваш Ñапраўдны Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ñž гÑтае поле. Калі вы платны карыÑтальнік, пошта з адраÑу [[user]]@[[domain]] будзе пераÑылацца на ваш Ñапраўдны адраÑ. Каб выбраць, Ñкі адраÑ(Ñ‹) Ñл.пошты паказваць уÑім, глÑдзіце опцыю ніжÑй опцыі "Паказваць вашую кантактную інфармацыю". + +/editinfo.bml.error.email.none=Ð’Ñ‹ павінны ўвеÑьці Ñвой Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.error.email.no_space=У адраÑе Ñл.пошты прабелы не дазволены. Калі вы карыÑтаецеÑÑ AOL, памÑтайце, што ваш ІнтÑрнÑтавы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты - гÑта вашае адлюÑтраванае Ñ–Ð¼Ñ Ð· выдаленымі прабеламі Ñ– дададзеным у канцы @aol.com + +/editinfo.bml.error.excessive_int=Выбачайце, але вы ўвÑлі зашмат зацікаўленаÑьцей. Ліміт роўны 150, а вы ўвÑлі [[intcount]]. УÑе Ð·Ñ€Ð¾Ð±Ð»ÐµÐ½Ñ‹Ñ Ð·ÑŒÐ¼ÐµÐ½Ñ‹ Ð½Ñ Ð±Ñ‹Ð»Ñ– захаваны. Ð’ÑрніцеÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– паменшыце Ñвой ÑьпіÑ, потым захавайце наноў. + +/editinfo.bml.error.invalidbio=Ð’Ð°ÑˆÐ°Ñ Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ð°Ñ Ð±Ñ–ÑÐ³Ñ€Ð°Ñ„Ñ–Ñ ÑžÑ‚Ñ€Ñ‹Ð¼Ð»Ñ–Ð²Ð°Ðµ нÑÑÐ»ÑƒÑˆÐ½Ñ‹Ñ Ñымбалі. Ð’Ñ‹ павінны наведаць Ñтаронку пераробкі, каб перарабіць Ñ–Ñ… у Юнікод. + +/editinfo.bml.error.invalidints=Ваш захаваны ÑÑŒÐ¿Ñ–Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьцей ўтрымлівае нÑÑÐ»ÑƒÑˆÐ½Ñ‹Ñ Ñымбалі. Ð’Ñ‹ павінны наведаць Ñтаронку пераробкі, каб перарабіць Ñ–Ñ… у Юнікод. + +/editinfo.bml.error.invalidname=Вашае Ñ–Ð¼Ñ ÑžÑ‚Ñ€Ñ‹Ð¼Ð»Ñ–Ð²Ð°Ðµ нÑÑÐ»ÑƒÑˆÐ½Ñ‹Ñ Ñымбалі. Ð’Ñ‹ павінны наведаць Ñтаронку пераробкі, каб перарабіць Ñ–Ñ… у Юнікод. + +/editinfo.bml.error.locale.country_ne_state=Ð’Ñ‹ выбралі Ð—Ð»ÑƒÑ‡Ð°Ð½Ñ‹Ñ Ð¨Ñ‚Ð°Ñ‚Ñ‹ ÐмÑрыкі Ñк вашую краіну, але вы пазначылі неамÑрыканÑкі штат у полі "іншы штат". + +/editinfo.bml.error.locale.invalid_country=Ðейкім чынам вы выбралі нÑÑлушную краіну. + +/editinfo.bml.error.locale.state_ne_country=Ð’Ñ‹ выбралі не ЗШРÑваёй краінай, але выбралі амÑрыканÑкі штат. + +/editinfo.bml.error.locale.zip_ne_state=Ваш паштовы індÑÐºÑ Ð½Ðµ Ñупадае з указаным штатам. Ці ÑкарÑктуйце інфармацыю, ці выдаліце адно з ўведзеных, ці штат, ці паштовы індÑкÑ. + +/editinfo.bml.error.locale.zip_requires_us=Ð’Ñ‹ ўвÑлі паштовы індÑкÑ, але не пазначылі Ð—Ð»ÑƒÑ‡Ð°Ð½Ñ‹Ñ Ð¨Ñ‚Ð°Ñ‚Ñ‹ ÐмÑрыкі, Ñк Ñваю краіну. Мы зьбіраем Ð¿Ð°ÑˆÑ‚Ð¾Ð²Ñ‹Ñ Ñ–Ð½Ð´ÑкÑÑ‹ толькі жыхароў ЗШÐ. Калі лаÑка, вÑрніцеÑÑ Ñ– ці выдаліце паштовы індÑкÑ, ці выберыце Ñваёй краінай Ð—Ð»ÑƒÑ‡Ð°Ð½Ñ‹Ñ Ð¨Ñ‚Ð°Ñ‚Ñ‹ ÐмÑрыкі. + +/editinfo.bml.error.month.outofrange=ÐÑÑлушны меÑÑц нараджÑньнÑ. УвÑдзіце меÑÑц паміж 1-12. (Студз-Снеж) + +/editinfo.bml.error.noname=Вашае Ñ–Ð¼Ñ - абавÑзковае поле. Ð¥Ð°Ñ†Ñ Ð± увÑдзіце вашую мÑнушку. + +/editinfo.bml.error.tm.require.number=Калі вы зьбіраецеÑÑ ÑžÐ¶Ñ‹Ð²Ð°Ñ†ÑŒ пераÑылку Ñ‚ÑкÑтавых паведамленьнÑÑž, увÑдзіце Ñвой Ñ‚Ñлефонны нумар. + +/editinfo.bml.error.tm.require_provider=Калі вы зьбіраецеÑÑ ÑžÐ¶Ñ‹Ð²Ð°Ñ†ÑŒ пераÑылку Ñ‚ÑкÑтавых паведамленьнÑÑž, увÑдзіце вашую Ñ‚Ñлефонную кампанію. Калі вашай кампаніі нÑма Ñž ÑьпіÑе, калі лаÑка кантактуйце з намі, з інфармацыÑй, Ñк працуе Ð²Ð°ÑˆÐ°Ñ Ð¿ÐµÑ€Ð°Ñылка Ñ‚ÑкÑтавых паведамленьнÑÑž, каб мы змаглі зрабіць да Ñе падтрымку. + +/editinfo.bml.error.year.notenoughdigits=ÐÑÑлушны год нараджÑньнÑ. УвÑдзіце 4-лічбавы год. + +/editinfo.bml.error.year.outofrange=ÐÑÑлушны год нараджÑньнÑ. + +/editinfo.bml.finished.about=Калі ÑžÑÑ‘ зроблена, націÑьніце кнопку "Захаваць зьмены" ніжÑй: + +/editinfo.bml.finished.header=Зроблена? + +/editinfo.bml.finished.save_button=Захаваць зьмены + +/editinfo.bml.foafurl.about=Калі вы не жадаеце ўжываць Ñтаронку FOAF па змоўчаньні, пададзеную намі, любы URL, што вы ўвÑдзеце вышÑй будзе ўжывацца замеÑÑ‚ вашай Ñтаронкі FOAF. Мы будзем перанакіроўваць запыты да FOAF на пазначаны URL. + +/editinfo.bml.foafurl.title=Зьнешні FOAF URL: + +/editinfo.bml.gender.title=Пол + +/editinfo.bml.getreplies.about=Ðдзначце тут, калі вы жадаеце атрымліваць адказы на Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹, ÑÐºÑ–Ñ Ñ€Ð¾Ð±Ñць Ñ–Ð½ÑˆÑ‹Ñ Ð»ÑŽÐ´Ð·Ñ– на дошках паведамленьнÑÑž (камÑнтары), на ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/editinfo.bml.getreplies.header=Ðтрымліваць адказы з дошак камÑнтараў + +/editinfo.bml.getselfemails.about=Ðдзначце тут, калі вы жадаеце атрымліваць ліÑÑ‚ Ñл.пошты кожны раз, калі вы робіце камÑнтар у журнале ці Ñуполцы. Ð’Ñ‹ Ð½Ñ Ð±ÑƒÐ´Ð·ÐµÑ†Ðµ атрымліваць ліÑÑ‚ Ñл.пошты паÑÑŒÐ»Ñ Ð°Ð½Ð°Ð½Ñ–Ð¼Ð½Ñ‹Ñ… камÑнтараў. + +/editinfo.bml.getselfemails.header=Ðтрымліваць Ð·Ñ€Ð¾Ð±Ð»ÐµÐ½Ñ‹Ñ ÐºÐ°Ð¼Ñнтары на Ñвой Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.hidefriendof.about=Калі вы адзначыце тут, то ÑÑŒÐ¿Ñ–Ñ Ð»ÑŽÐ´Ð·ÐµÐ¹, што пазначылі Ð²Ð°Ñ Ñк ÑÑбра, будзе Ñхаваны на Ñтаронцы вашага профілю. + +/editinfo.bml.hidefriendof.header=Схаваць ÑÑŒÐ¿Ñ–Ñ "Чый ÑÑбра" + +/editinfo.bml.howhear.about=ПроÑта цікава, адкуль вы даведаліÑÑ Ð¿Ñ€Ð° [[sitename]]? Калі гÑта быў аÑобны чалавек, увÑдзіце Ñгонае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка; калі гÑта была Ñ–Ð½ÑˆÐ°Ñ ÐºÑ€Ñ‹Ð½Ñ–Ñ†Ð°/артыкул/ÑпаÑылка/бачына ўвÑдзіце патрÑбную інфармацыю. + +/editinfo.bml.howhear.header=ЦікаваÑьць + +/editinfo.bml.htmlemail.about=Ðдзначце тут, калі Ð²Ð°ÑˆÐ°Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ð° Ñл.пошты поўнаÑьцю падтрымлівае HTML у вашай пошце. ÐÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹-кліенты Ñпрабуюць падтрымліваць Ñе, але Ñž Ñ–Ñ… не атрымліваецца паказваць Ñе Ñлушна. Калі вы не адзначыце тут, то Жывы Журнал будзе даÑылаць толькі Ñ‚ÑкÑÑ‚Ð°Ð²Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½ÑŒÐ½Ñ– на Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/editinfo.bml.htmlemail.header=ДаÑылаць ліÑÑ‚Ñ‹ Ñž HTML на Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.imagelinks.about=ЗамÑнÑльнікі карыÑныÑ, калі вы праглÑдаеце Ñайт з работы ці праз маруднае падлучÑньне, Ñны замÑнÑюць карцінкі Ñž Ñ‚ÑкÑьце на ÑпаÑылкі. Якога памеру павінны быць карцінкі, каб ужываць замÑнÑльнікі? + +/editinfo.bml.imagelinks.header=Ужываць замÑнÑльнікі карцінак на вашай Ñтаронцы ÑÑброў + +/editinfo.bml.imagelinks.size.all=Ужываць замÑнÑльнікі Ð´Ð»Ñ ÑžÑÑ–Ñ… карцінак + +/editinfo.bml.imagelinks.size.custom=УлаÑнае: ужываць замÑнÑльнікі Ð´Ð»Ñ ÐºÐ°Ñ€Ñ†Ñ–Ð½Ð°Ðº памерам больш за [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=Ужываць замÑнÑльнікі Ð´Ð»Ñ Ð²Ñлікіх карцінак (больш за [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Ужываць замÑнÑльнікі Ð´Ð»Ñ ÑÑÑ€Ñдніх карцінак (больш за [[width]]x[[height]]) + +/editinfo.bml.int.about=Калі вы хочаце, каб Ñ–Ð½ÑˆÑ‹Ñ Ð»ÑŽÐ´Ð·Ñ– шукалі Ñž паказальніку Ñ– маглі знайÑьці Ð²Ð°Ñ Ð¿Ð° зацікаўленаÑьці, пазначце ніжÑй уÑе Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці, Ð¿Ð°Ð´Ð·ÐµÐ»ÐµÐ½Ñ‹Ñ ÐºÐ¾Ñкамі. ÐšÐ°Ñ€Ð¾Ñ‚ÐºÑ–Ñ Ð°Ð´Ð½Ð°ÑÐ»Ð¾ÑžÐ½Ñ‹Ñ Ð²Ñ‹Ñ€Ð°Ð·Ñ‹ будуць лепш за ÑžÑÑ‘. Галоўнае правіла: Ð’Ñ‹ павінны мець магчымаÑьць падÑтавіць вашую зацікаўленаÑьць у ÑловазлучÑньне "Мне падабае(ÑŽ)цца ________". + +/editinfo.bml.int.ex.bad=КЕПСКРПрыклад: Мне падабаюцца ÑˆÐ¼Ð°Ñ‚Ð»Ñ–ÐºÑ–Ñ Ð³ÑƒÑ€Ñ‚Ñ‹, фільмы, размовы з ÑÑбрамі, туÑоўкі Ñž клюбах. ГÑта ÑžÑÑ‘ павінна быць у вашай біÑграфіі. + +/editinfo.bml.int.ex.good=ДОБРРПрыклад: футбол, кампутары, кружÑлкі, мп3, ÑÑ‹Ñ€, жанчыны + +/editinfo.bml.int.header=ЗацікаўленаÑьці + +/editinfo.bml.login.enterinfo=УвÑдзіце вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль, каб зьмÑніць вашую аÑабіÑтую інфармацыю. + +/editinfo.bml.login.forgot.header=Забылі нешта? + +/editinfo.bml.login.forgot.recover=Калі вы забылі вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ці пароль, узнавіце Ñ–Ñ… тут!. + +/editinfo.bml.logip.always=ЗаўÑёды + +/editinfo.bml.logip.anon_only=Толькі Ñž Ñ‚Ñ‹Ñ…, хто піша ананімна + +/editinfo.bml.logip.header=ЗапіÑваць IP-адраÑÑ‹ Ñ‚Ñ‹Ñ…, хто піша камÑнтары? + +/editinfo.bml.mangleaddress.about=Калі вы баіцеÑÑ, што робаты-ÑпамÑры знойдуць ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты на Жывым Журнале, выберыце гÑтую опцыю. Ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты будзе зьменены такім чынам, каб робаты, што зьбіраюць адраÑÑ‹, не знайшлі Ñго. + +/editinfo.bml.mangleaddress.header=Падправіць ваш бачны Ð°Ð´Ñ€Ð°Ñ Ñл.пошты + +/editinfo.bml.mutualfriends.about=ГÑÑ‚Ð°Ñ Ð¾Ð¿Ñ†Ñ‹Ñ Ð´Ð°Ð´Ð°Ðµ новы ÑÑŒÐ¿Ñ–Ñ Ð½Ð° вашую Ñтронку профілÑ: ÑÑŒÐ¿Ñ–Ñ ÑƒÐ·Ð°ÐµÐ¼Ð½Ñ‹Ñ… ÑÑброў. Людзі, хто дадаў Ð²Ð°Ñ Ñƒ ÑÑбры, Ñ– каго вы такÑама дадалі да ÑÑброў, будуць у гÑтым ÑьпіÑе. + +/editinfo.bml.mutualfriends.header=Паказваць узаемных ÑÑброў на Ñтаронцы профілю + +/editinfo.bml.name.title=Ð†Ð¼Ñ + +/editinfo.bml.newemail.body2<< +Ð’Ñ‹ толькі што зьмÑнілі Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° [[sitename]] рахунку "[[username]]". Каб пацьвердзіць зьмену, калі лаÑка, наведайце гÑÑ‚Ñ‹ адраÑ: + +[[conflink]] + +З павагай, +Каманда [[sitename]] +[[sitelink]] +. + +/editinfo.bml.newemail.subject=ÐÐ´Ñ€Ð°Ñ Ñл.пошты быў зьменены + +/editinfo.bml.numcomments.about=Ðдзначце тут, калі вы хочаце, каб лічыльнік камÑнтараў дадаваўÑÑ Ð´Ð° адраÑоў URL, каб ваш праглÑдач магчыма адлюÑтроўваў ÑпаÑылкі іншым колерам. + +/editinfo.bml.numcomments.header=Дадаваць &nc=xx да адраÑоў URL камÑнтараў + +/editinfo.bml.optional=Ðе абавÑзкова + +/editinfo.bml.opt_in.about=Калі вы хочаце ведаць, калі мы ўводзім Ð½ÐµÐ¹ÐºÑ–Ñ Ð½Ð¾Ð²Ñ‹Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьці Ñž Жывым Журнале, адзначце тут. У дадзены момант мы не ўжываем гÑтую опцыю, але магчыма будзем у будучыні. Ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ бачны іншым карыÑтальнікам, Ñ– вы можаце адключыць гÑта Ñž любы момант. + +/editinfo.bml.opt_in.header=ДаÑылаць мне навіны Жывога Журналу. + +/editinfo.bml.persinfo.disclaimer=Ðапішыце крыху інфармацыі пра ÑÑбе, Ð´Ð»Ñ Ð½Ð°ÑˆÐ°Ð¹ цікаваÑьці Ñ– ÑтатыÑтычных мÑтаў. Мы не зьбіраемÑÑ Ñ€Ð°Ð±Ñ–Ñ†ÑŒ нічога кепÑкага з гÑтай інфармацыÑй, мы толькі хочам ведаць, хто Ñ– адкуль Ð½Ð°ÑˆÑ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі. Калі лаÑка, падавайце дакладную інфармацыю. Калі вам цікава, прачытайце нашую палітыку прыватнаÑьці. + +/editinfo.bml.persinfo.header=ÐÑабіÑÑ‚Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/editinfo.bml.screen.all=УÑе + +/editinfo.bml.screen.anon=ÐÐ½Ð°Ð½Ñ–Ð¼Ð½Ñ‹Ñ + +/editinfo.bml.screen.header=Ð¯ÐºÑ–Ñ ÐºÐ°Ð¼Ñнтары вы хочаце, каб былі заÑлонены па змоўчаньні? + +/editinfo.bml.screen.none=ÐÑ–ÑÐºÑ–Ñ + +/editinfo.bml.screen.nonfriends=Ðе ÑÑброўÑÐºÑ–Ñ + +/editinfo.bml.screen.nonmembers=Ðе ўдзельнікаў + +/editinfo.bml.security.header=Хто можа праглÑдаць вашую кантактную інфармацыю? + +/editinfo.bml.security.visibility.anybody=УÑÑкі + +/editinfo.bml.security.visibility.everybody=Кожны + +/editinfo.bml.security.visibility.friends=Толькі ÑÑбры + +/editinfo.bml.security.visibility.regusers=ЗарÑгіÑÑ‚Ñ€Ð°Ð²Ð°Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі + +/editinfo.bml.settings.friendspage.title=Ðазва Ñтаронкі ÑÑброў: + +/editinfo.bml.settings.friendspage.title.optional=Ðе абавÑзкова, увÑдзіце назву Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð¹ Ñтаронкі ÑÑброў. (HTML нельга) + +/editinfo.bml.settings.header=Опцыі Жывога Журналу + +/editinfo.bml.settings.journal.subtitle=Падзагаловак журналу + +/editinfo.bml.settings.journal.subtitle.optional=Ðе абавÑзкова, увÑдзіце назву Ñ– падзагаловак Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° журналу. (HTML нельга). + +/editinfo.bml.settings.journal.title=Ðазва журналу: + +/editinfo.bml.settings.privacy.about=Выберыце ніжÑй Ð²Ð°ÑˆÑ‹Ñ Ð¿Ñ€Ñ‹Ð²Ð°Ñ‚Ð½Ñ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– Ñ– ÑžÑтаноўкі. + +/editinfo.bml.settings.privacy.header=ÐŸÑ€Ñ‹Ð²Ð°Ñ‚Ð½Ñ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– + +/editinfo.bml.state.other=Ці, напішыце іншы штат/правінцыю/Ñ‚Ñрыторыю + +/editinfo.bml.state.title=Штат + +/editinfo.bml.state.us=ÐмÑрыканÑÐºÑ–Ñ ÑˆÑ‚Ð°Ñ‚Ñ‹ + +/editinfo.bml.stylemine.about=Ðдзначце гÑтую опцыю, каб праглÑдаць Ñтаронкі камÑнтараў у Ñтылі вашага журналу, калі заходзіце па ÑпаÑылках з вашай Ñтаронкі ÑÑброў. + +/editinfo.bml.stylemine.header=ПраглÑдаць камÑнтары Ñž Ñтылі вашага журналу? + +/editinfo.bml.success.header=ПоÑьпех! + +/editinfo.bml.success.message=Ð’Ð°ÑˆÐ°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ, уÑтаноўкі журналу Ñ– профіль былі зьменены. + +/editinfo.bml.switch.button=Пераключыць + +/editinfo.bml.switch.header=Пераключыць журнал + +/editinfo.bml.switch.workwith=Праца з журналам: + +/editinfo.bml.title=РÑдагаваць аÑабіÑтую інфармацыю + +/editinfo.bml.tm.details=дÑталі + +/editinfo.bml.tm.phonenum=Поўны нумар Ñ‚Ñлефону: + +/editinfo.bml.tm.sec.about=Даць магчымаÑьць іншым карыÑтальнікам выкарыÑтоўваць пераÑылку Ñ‚ÑкÑтавых паведамленьнÑÑž + +/editinfo.bml.tm.sec.title=Узровень бÑÑьпекі + +/editinfo.bml.tm.servprov=ПрадÑтаўнік паÑлугаў + +/editinfo.bml.tm.title=ПераÑылка Ñ‚ÑкÑтавых паведамленьнÑÑž + +/editinfo.bml.translatemailto.about=У выпадку, калі вы пажадалі атрымліваць адказы з дошак камÑнтараў на Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, Ñ– Ð²Ð°ÑˆÐ°Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ð°-кліент не падтрымлівае паведамленьні Ñž Юнікод (UTF-8), выкарыÑтайце гÑтую опцыю, каб вызначыць іншае кадаваньне, у Ñкім Жывы Журнал будзе даÑылаць вам Ñ‚ÑкÑÑ‚ камÑнтараў. + +/editinfo.bml.translatemailto.header=Пераводзіць паведамленьні на Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ñž: + +/editinfo.bml.unbanusers.about=Ð’Ñ‹ забаранілі наÑтупным карыÑтальнікам рабіць запіÑÑ‹ Ñž ваш журнал. Ðдзначце "птушкай" ÐºÐ°Ð»Ñ Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, каб зьнÑць забарону. + +/editinfo.bml.unbanusers.header=ÐдмÑніць забарону карыÑтальнікам + +/editinfo.bml.userpic.about=ÐіжÑй знаходзіцца выÑўка, Ñкую вы загрузілі, каб Ñ€ÑпрÑзентаваць Ð²Ð°Ñ Ð½Ð° Ñайце Жывога Журналу, у вашым журнале, Ñ– Ñž журналах вашых ÑÑброў: + +/editinfo.bml.userpic.edit=Каб выдаліць гÑтую выÑву, ці загрузіць новую, ідзіце Ñюды. + +/editinfo.bml.userpic.header=Ð’Ð°ÑˆÐ°Ñ Ð²Ñ‹Ñва + +/editinfo.bml.userpic.none=ні адзін малюнак не загружаны + +/editinfo.bml.weblogscom.about=Выберыце гÑтую опцыю, калі вы хочаце, каб Weblogs.com трымаў Ð²Ð°Ñ Ñž Ñваім ÑьпіÑе, калі вы робіце Ð½Ð¾Ð²Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹. + +/editinfo.bml.weblogscom.header=ПаведамлÑць Weblogs.com пра абновы + +/editinfo.bml.webpagename.title=Ðазва бачыны + +/editinfo.bml.webpageurl.title=URL бачыны + +/editinfo.bml.whoreply.header=Хто можа адказваць на Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹? + +/editinfo.bml.zip.title=Паштовы індÑÐºÑ + +/editinfo.bml.zip.usonly=5-лічбавы паштовы індÑкÑ; толькі Ð´Ð»Ñ Ð¶Ñ‹Ñ…Ð°Ñ€Ð¾Ñž ЗШР+ +/editjournal.bml.btn.proceed=ПрацÑг... + +/editjournal.bml.certainday=ПÑўны дзень: + +/editjournal.bml.desc=Калі лаÑка, ужывайце форму ніжÑй, каб знайÑьці запіÑ, Ñкі вы хочаце Ñ€Ñдагаваць. + +/editjournal.bml.in=У Ñуполцы: + +/editjournal.bml.recententries=Ñамых апошніх запіÑаў + +/editjournal.bml.recententry=Самы апошні Ð·Ð°Ð¿Ñ–Ñ + +/editjournal.bml.title=РÑдагаваньне журнальных запіÑаў + +/editjournal.bml.viewwhat=ПраглÑдзець: + +/editjournal_do.bml.body=ÐдрÑдагуйце ÑžÑе палі вашага журнальнага запіÑу, Ñкі вы хочаце мадыфікаваць Ñ– націÑьніце кнопку Ð·Ð°Ñ…Ð°Ð²Ð°Ð½ÑŒÐ½Ñ ÑžÐ½Ñ–Ð·Ðµ Ñтаронкі. Інакш вы можаце націÑнуць кнопку выдаленьнÑ, каб выдаліць запіÑ. + +/editjournal_do.bml.btn.delete=Выдаліць журнальны Ð·Ð°Ð¿Ñ–Ñ + +/editjournal_do.bml.btn.edit=РÑдагаваць вызначаны Ð·Ð°Ð¿Ñ–Ñ + +/editjournal_do.bml.btn.preview=ПерадпраглÑд запіÑу + +/editjournal_do.bml.btn.save=Захаваць журнальны Ð·Ð°Ð¿Ñ–Ñ + +/editjournal_do.bml.continue.head=ÐаціÑьніце Ð´Ð»Ñ Ð¿Ñ€Ð°Ñ†Ñгу... + +/editjournal_do.bml.continue.text=ПаÑÑŒÐ»Ñ Ð²Ñ‹Ð±Ð°Ñ€Ñƒ пункту Ð´Ð»Ñ Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñ†Ñ– выдаленьнÑ, націÑьніце кнопку РÑдагаваць ніжÑй. + +/editjournal_do.bml.currmood=БÑгучы наÑтрой: + +/editjournal_do.bml.currmusic=БÑÐ³ÑƒÑ‡Ð°Ñ Ð¼ÑƒÐ·Ñ‹ÐºÐ°: + +/editjournal_do.bml.date=Дата: + +/editjournal_do.bml.default=па змоўчаньні + +/editjournal_do.bml.delete.confirm=Ð’Ñ‹ ўпÑўнены, што хочаце выдаліць гÑÑ‚Ñ‹ запіÑ? + +/editjournal_do.bml.edit.text=ГÑÑ‚Ñ‹ Ð·Ð°Ð¿Ñ–Ñ Ñƒ журнал вы выбралі, каб Ñ€Ñдагаваць. ЗьмÑніце ÑžÑÑ‘, што вы жадаеце, а потым націÑьніце кнопку "Захаваць журнальны запіÑ" унізе.

    Каб выдаліць запіÑ, выдаліце ўвеÑÑŒ Ñ‚ÑкÑÑ‚ запіÑу, а потым націÑьніце кнопку "Захаваць журнальны запіÑ" унізе. + +/editjournal_do.bml.error.getting=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры атрыманьні журнальных запіÑаў Ð´Ð»Ñ Ñ€ÑдагаваньнÑ: + +/editjournal_do.bml.error.modify=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры абнаўленьні вашага журналу: + +/editjournal_do.bml.error.nofind=ÐÑ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹ выбраны журнальны запіÑ. + +/editjournal_do.bml.event=ПадзеÑ: + +/editjournal_do.bml.localtime=ÐœÑÑцовы чаÑ: + +/editjournal_do.bml.noneother=ÐÑ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ñ‹, ці іншы: + +/editjournal_do.bml.opt.backdate=Ð—Ð°Ð¿Ñ–Ñ Ð·Ð° мінулую дату: + +/editjournal_do.bml.opt.backdate.about=Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ паказаны Ñž Ñтужках ÑÑброў + +/editjournal_do.bml.opt.nocomments=Забараніць камÑнтары: + +/editjournal_do.bml.opt.noemail=Ðе даÑылаць камÑнтары на Ñ-мÑйл: + +/editjournal_do.bml.opt.noformat=Ðе аўта-фарматаваць: + +/editjournal_do.bml.other=Іншы: + +/editjournal_do.bml.pickentry.head=Выберыце Ð·Ð°Ð¿Ñ–Ñ Ð´Ð»Ñ Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ + +/editjournal_do.bml.pickentry.text=Выберыце пункт, Ñкі вы хочаце Ñ€Ñдагаваць Ñ– націÑьніце кнопку Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ ÑžÐ½Ñ–Ð·Ðµ Ñтаронкі. + +/editjournal_do.bml.picture=Ужыць выÑву: + +/editjournal_do.bml.preview.header=ПерадпраглÑд запіÑу + +/editjournal_do.bml.preview.text=Так будзе выглÑдаць Ð·Ð°Ð¿Ñ–Ñ Ñƒ журнале. Ужываючы форму ніжÑй, вы можаце Ñ€Ñдагаваць Ð·Ð°Ð¿Ñ–Ñ Ð´Ð°Ð»ÐµÐ¹, ці запіÑаць Ñго Ñк ён Ñ‘Ñьць. + +/editjournal_do.bml.save.head=ÐаціÑьніце, каб захаваць... + +/editjournal_do.bml.save.text=Калі Ñкончыце Ñ€Ñдагаваць Ð²Ð°ÑˆÑ‹Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹, націÑьніце Захаваць. + +/editjournal_do.bml.subject=ТÑма: (не абавÑзкова) + +/editjournal_do.bml.success.delete=Журнальны Ð·Ð°Ð¿Ñ–Ñ Ð±Ñ‹Ñž выдалены. + +/editjournal_do.bml.success.edit=Журнальны Ð·Ð°Ð¿Ñ–Ñ Ð±Ñ‹Ñž зьменены. Ð’Ñ‹ можаце ўбачыць Ñго тут. + +/editjournal_do.bml.success.head=ПоÑьпех + +/editjournal_do.bml.timeformat=24-гадзінавы Ñ‡Ð°Ñ + +/editjournal_do.bml.title=РÑдагаваньне журнальных запіÑаў + +/editpics.bml.btn.proceed=ПрацÑг + +/editpics.bml.btn.save=Захаваць уÑтаноўкі + +/editpics.bml.curpics=БÑÐ³ÑƒÑ‡Ñ‹Ñ Ð²Ñ‹Ñвы + +/editpics.bml.curpics.desc=Тут знаходзÑцца выÑвы, што вы загрузілі Ñž мінулым. Ð’Ñ‹ можаце прызначыць ім ÐºÐ»ÑŽÑ‡Ð°Ð²Ñ‹Ñ Ñловы, каб потым выбіраць Ñ–Ñ… па ключавых Ñловах, вы можаце прызначыць адну з Ñ–Ñ… выÑвай па змоўчаньні, ці выдаліць ÑтарыÑ. Каб загрузіць новую, карыÑтайцеÑÑ Ñ„Ð¾Ñ€Ð¼Ð°Ð¹ унізе Ñтаронкі. + +/editpics.bml.error.badurl=ÐÐ´Ñ€Ð°Ñ Ð¼Ð°Ð»ÑŽÐ½ÐºÑƒ Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÑ– выглÑдае нÑÑлушна. Ðн павінен пачынацца з http:// + +/editpics.bml.error.filetoolarge=Загружаемы малюнак завÑлікі. Файл Ð½Ñ Ð¼Ð¾Ð¶Ð° быць большы за [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Памеры вашай выÑвы ([[imagesize]]) перавышаюць дазволеныÑ. Ð’Ð°ÑˆÐ°Ñ Ð²Ñ‹Ñва Ð½Ñ Ð¼Ð¾Ð¶Ð° быць больш, чым 100x100 пікÑÑлаў. ВыкарыÑтайце праграму Ð´Ð»Ñ Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð¼Ð°Ð»ÑŽÐ½ÐºÐ°Ñž/фотаздымкаў, каб зьменшыць памеры выÑвы. + +/editpics.bml.error.invalidimage=ÐÑÑлушны файл малюнку. + +/editpics.bml.error.keywords=Ð’Ñ‹ ўжылі ключавое Ñлова "[[ekw]]" Ð´Ð»Ñ Ð½ÐµÐºÐ°Ð»ÑŒÐºÑ–Ñ… выÑваў. Ðдна зь Ñ–Ñ… была выпадкова выбрана, але падобна Ð½Ñ Ñ‚Ð°Ñ, што вы хацелі. Ð’Ñ‹ можаце вÑрнуцца назад Ñ– выправіць гÑта. + +/editpics.bml.error.toomanypics2=Ð’Ñ‹ даÑÑгнулі ліміту з [[maxpics]] малюнакаў. Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ загрузіць гÑÑ‚Ñ‹ малюнак, пакуль Ð½Ñ Ð²Ñ‹Ð´Ð°Ð»Ñ–Ñ†Ðµ адзін з Ñ–Ñнуючых. + +/editpics.bml.error.toomanypics3=ЦÑпер вы даÑÑгнулі вашага ліміту [[max]] [[?max|выÑвы|выÑваў]. Ð’Ñ‹ Ð½Ñ Ð·Ð¼Ð¾Ð¶Ð°Ñ†Ðµ загрузіць Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð²Ñ‹Ñвы, пакуль Ð½Ñ Ð²Ñ‹Ð´Ð°Ð»Ñ–Ñ†Ðµ адну ці болей зь бÑгучых выÑваў. + +/editpics.bml.error.unsupportedtype=Файлы тыпу [[filetype]] не падтрымліваюцца. Ð’Ñ‹ можаце загружаць толькі файлы GIF, PNG ці JPG. Ðмаль ÑžÑе праграмы Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð¼Ð°Ð»ÑŽÐ½ÐºÐ°Ñž/фотаздымкаў могуць зрабіць такое пераўтварÑньне. + +/editpics.bml.error.urlerror=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры Ñпробе даÑÑгнуць вашага малюнку. + +/editpics.bml.fromfile=З Файлу: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=Ñ„ + +/editpics.bml.fromurl=З URL: + +/editpics.bml.kilobytes=КБ + +/editpics.bml.label.default=Па змоўчаньні: + +/editpics.bml.label.delete=Выдаліць: + +/editpics.bml.label.keywords=ÐšÐ»ÑŽÑ‡Ð°Ð²Ñ‹Ñ Ñловы: + +/editpics.bml.makedefault=Зрабіць выÑвай па змоўчаньні + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=п + +/editpics.bml.nodefault=ÐÑма выÑвы па змоўчаньні + +/editpics.bml.noneupload=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ загружаных выÑваў. Калі лаÑка, загрузіце Ñкую ўжываючы форму ніжÑй. + +/editpics.bml.nopics=ÐÑма выÑваў + +/editpics.bml.piclimitstatus=Загружана на дадзены момант: [[current]] з магчымых [[max]]. + +/editpics.bml.restriction.fileformat=Фармат файлу павінен быць PNG, GIF ці JPG + +/editpics.bml.restriction.filesize=Памер файлу павінен быць менш за 40кб + +/editpics.bml.restriction.imagesize=Памеры выÑвы не могуць быць больш за 100x100 пікÑÑлаў + +/editpics.bml.title=РÑдагаваньне выÑваў карыÑтальніка + +/editpics.bml.uploaddesc=Ужывайце форму ніжÑй, каб загрузіць новую выÑву + +/editpics.bml.uploadheader=Загрузіць новую выÑву + +/export.bml.btn.proceed=ПрацÑг... + +/export.bml.description=ГÑÑ‚Ð°Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьць дазвалÑе вам ÑьцÑгнуць увеÑÑŒ ваш журнал Ð´Ð»Ñ Ñ€Ñзервовай копіі. Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі пра Ñ€Ñзерваваньне вашага журналу, глÑдзіце гÑÑ‚Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы. + +/export.bml.fields=Палі: + +/export.bml.format.csv=КПВ (КоÑкай Ð¿Ð°Ð´Ð·ÐµÐ»ÐµÐ½Ñ‹Ñ Ð²ÐµÐ»Ñ–Ñ‡Ñ‹Ð½Ñ–) + +/export.bml.label.encoding=Кадаваньне: + +/export.bml.label.field.allowmask=Дазволіць маÑку + +/export.bml.label.field.currents=БÑгучы наÑтрой Ñ– музыка + +/export.bml.label.field.event=ÐŸÐ°Ð´Ð·ÐµÑ + +/export.bml.label.field.eventtime=Ð§Ð°Ñ Ð¿Ð°Ð´Ð·ÐµÑ– (з гадзіньніка карыÑтальніка) + +/export.bml.label.field.itemid=Ðумар ID + +/export.bml.label.field.logtime=Ð§Ð°Ñ Ð·Ð°Ð¿Ñ–Ñу (з ÑÑ‹ÑÑ‚Ñмнага гадзіньніку) + +/export.bml.label.field.security=Узровень бÑÑьпекі + +/export.bml.label.field.subject=ТÑма + +/export.bml.label.format=Фармат: + +/export.bml.label.header=Загаловак + +/export.bml.label.month=Выберыце меÑÑц: + +/export.bml.label.month.month=мм: + +/export.bml.label.month.year=гггг: + +/export.bml.label.notranslation=Ðе перакладаць паміж кадаваньнÑмі + +/export.bml.label.what=Што ÑкÑпартаваць: + +/export.bml.title=ЭкÑпарт журналу + +/export.bml.what.entries=Ð–ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +/export_do.bml.error.encoding=Выбрана нÑÑлушнае кадаваньне + +/friends/add.bml.add.header=ПоÑьпех + +/friends/add.bml.add.text=КарыÑтальнік [[ljuser]] быў дададзены да вашага ÑьпіÑу ÑÑброў. Ð’Ñ‹ можаце ўбачыць Ñтаронку вашых ÑÑброў тут. + +/friends/add.bml.add.title=СÑбра дададзены! + +/friends/add.bml.btn.add=Дадаць [[user]] + +/friends/add.bml.btn.modify=ЗьмÑніць + +/friends/add.bml.btn.remove=Выдаліць + +/friends/add.bml.colors.bg=Фон + +/friends/add.bml.colors.fg=ПÑÑ€Ñдні плÑн + +/friends/add.bml.colors.header=Колеры + +/friends/add.bml.colors.hover=(ÐавÑдзіце мышку на колер, каб убачыць Ñгоную назву) + +/friends/add.bml.colors.text=Ð’Ñ‹ такÑама можаце па жаданьні выбраць колер, Ñкі будзе Ñ€ÑпрÑзентаваць [[user]] у вашай Ñтужцы ÑÑброў. + +/friends/add.bml.confirm.header=Дадаць [[user]] у ÑÑбры? + +/friends/add.bml.confirm.syn.header=Дадаць Ñындыкаваную Ñтужку [[user]] у ÑÑбры? + +/friends/add.bml.confirm.syn.title=Дадаваньне Ñындыкаванай Ñтужкі + +/friends/add.bml.confirm.text=Каб дадаць [[user]] да ÑьпіÑу ÑÑброў, націÑьніце кнопку ўнізе. + +/friends/add.bml.confirm.title=Дадаць ÑÑбра + +/friends/add.bml.error1.header=Увайдзіце Ñпачатку + +/friends/add.bml.error1.text=Каб дадаць карыÑтальніка да ÑьпіÑу вашых ÑÑброў Ñпачатку ўвайдзіце. Калі Ñž Ð²Ð°Ñ Ð½Ñма рахунку, вы можаце Ñтварыць Ñго, каб Ñачыць за журналамі вашых ÑÑброў. + +/friends/add.bml.error1.title=Дадаць ÑÑбра + +/friends/add.bml.error2.text=ÐÑÑлушае ці нÑÑ–Ñнуючае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. Каб дадаць ÑÑбра, ідзіце на Ñтаронку Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ ÑьпіÑу ÑÑброў + +/friends/add.bml.error3.text=КарыÑтальнік [[user]] ужо знаходзіцца Ñž вашым ÑьпіÑе ÑÑброў. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, вы можаце зьмÑніць Ñ€ÑпрÑÐ·ÐµÐ½Ñ‚ÑƒÑŽÑ‡Ñ‹Ñ Ñго/Ñе колеры. + +/friends/add.bml.error3.title=Мадыфікаваць ÑÑбра + +/friends/add.bml.groups.header=Групы ÑÑброў + +/friends/add.bml.groups.nogroup=Групы ÑÑброў не наладжаны + +/friends/add.bml.groups.text=У Ñкую групу вы хочаце дадаць гÑтага карыÑтальніка? Групы ÑÑброў Ñтвораны Ð´Ð»Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñтужкі ÑÑброў, ды каб надаваць узроўні бÑÑьпекі заÑÐ½Ð°Ð²Ð°Ð½Ñ‹Ñ Ð½Ð° групах. + +/friends/add.bml.remove.header=ПоÑьпех + +/friends/add.bml.remove.text=КарыÑтальнік быў выдалены з вашага ÑьпіÑу ÑÑброў. Ð’Ñ‹ можаце ўбачыць Ñтужку вашых ÑÑброў тут. + +/friends/add.bml.remove.title=Выдалены Ñа ÑьпіÑу ÑÑброў! + +/friends/edit.bml.title=РÑдагаваньне ÑьпіÑу ÑÑброў + +/friends/editgroups.bml.btn.ge.del=Выдаліць + +/friends/editgroups.bml.btn.ge.new=ÐÐ¾Ð²Ð°Ñ + +/friends/editgroups.bml.btn.ge.ren=Перайменаваць + +/friends/editgroups.bml.btn.gs.private=ÐŸÑ€Ñ‹Ð²Ð°Ñ‚Ð½Ð°Ñ + +/friends/editgroups.bml.btn.gs.public=Ð“Ñ€Ð°Ð¼Ð°Ð´Ð·ÐºÐ°Ñ + +/friends/editgroups.bml.btn.mv.down=ПераÑунуць уніз + +/friends/editgroups.bml.btn.mv.up=ПераÑунуць уверх + +/friends/editgroups.bml.confirm.delete=Ð’Ñ‹ ўпÑўнены, што хочаце выдаліць гÑтую ўлаÑную групу ÑÑброў? + +/friends/editgroups.bml.done.btn=Захаваць зьмены + +/friends/editgroups.bml.done.header=Зроблена? + +/friends/editgroups.bml.done.text=Калі ÑžÑÑ‘ зроблена, націÑьніце кнопку ўнізе, каб захаваць зьмены. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Ð’Ñ‹ даÑÑгнулі ліміту Ñž 30 улаÑных груп ÑÑброў. Калі вы выдалілі адну ці больш груп, але ÑÑˆÑ‡Ñ Ð½Ðµ захавалі зьмены, зрабіце гÑта цÑпер, потым вÑрніцеÑÑ Ñ– перазагрузіце Ñтаронку. Тады Ñž Ð²Ð°Ñ Ð±ÑƒÐ´Ð·Ðµ магчымаÑьць Ñтварыць новую ўлаÑную групу ÑÑброў. + +/friends/editgroups.bml.error.text=СÑрвер вÑрнуў наÑтупнае паведамленьне: + +/friends/editgroups.bml.group.public=(грамадзкаÑ) + +/friends/editgroups.bml.ingroup=У групе: + +/friends/editgroups.bml.ingroup.not=ÐÑ Ñž групе: + +/friends/editgroups.bml.prompt.newname=УвÑдзіце Ñ–Ð¼Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð°Ð¹ улаÑнай групы ÑÑброў: + +/friends/editgroups.bml.prompt.rename=Перайменаваць улаÑную групу ÑÑброў у: + +/friends/editgroups.bml.saved.header=Захавана + +/friends/editgroups.bml.saved.text=Ð’Ð°ÑˆÑ‹Ñ ÑžÐ»Ð°ÑÐ½Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў захаваны. + +/friends/editgroups.bml.text<< +ГÑÑ‚Ð°Ñ Ñтаронка дазвалÑе вам Ñ€Ñдагаваць улаÑÐ½Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў. УлаÑÐ½Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў выкарыÑтоўваюцца Ð´Ð»Ñ ÑžÑтаноўкі ўзроўнÑÑž бÑÑьпекі Ñ– Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñтужкі ÑÑброў. Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð¿Ð°Ð¼Ð¾Ð³Ñ–, глÑдзіце Што такое ўлаÑÐ½Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў? Як імі карыÑтацца? + +ГÑÑ‚Ð°Ñ Ñтаронка патрабуе JavaScript Ð´Ð»Ñ Ñлушнай працы. +. + +/friends/editgroups.bml.text.sec=Заўвага па бÑÑьпецы: Калі вы хочаце выдаліць адну групу, а потым Ñтварыць новую, не рабіце гÑта перайменаваньнем адной групы, а потым Ñ€Ñдагаваньнем Ñе. Калі вы зробіце так, то ÑžÑе Ð²Ð°ÑˆÑ‹Ñ ÑÑ‚Ð°Ñ€Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹, што былі Ð±Ð°Ñ‡Ð½Ñ‹Ñ Ñтарой групе ÑÑброў, будуць Ð±Ð°Ñ‡Ð½Ñ‹Ñ Ñ– новай групе. + +/friends/editgroups.bml.title=РÑдагаваньне ўлаÑных груп ÑÑброў + +/friends/editgroups.bml.yourgroups=Ð’Ð°ÑˆÑ‹Ñ ÑžÐ»Ð°ÑÐ½Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў: + +/friends/edit_do.bml.addfriends.head=Дадаць ÑÑброў + +/friends/edit_do.bml.addfriends.text=УвÑдзіце імёны карыÑтальнікаў Жывога Журналу вашых ÑÑброў у палі ніжÑй, Ñ– выберыце колеры фону Ñ– пÑÑ€ÑднÑга плÑну, каб надаць ім.... + +/friends/edit_do.bml.background=Фон + +/friends/edit_do.bml.bgcolor=Колер фону: + +/friends/edit_do.bml.btn.close=Зачыніць + +/friends/edit_do.bml.btn.save=Захаваць зьмены + +/friends/edit_do.bml.btn.toggle=Уключыць вакно перадпраглÑду + +/friends/edit_do.bml.done.head=Зроблена? + +/friends/edit_do.bml.done.text=Калі ÑžÑÑ‘ зроблена, націÑьніце кнопку "Захаваць зьмены" ўнізе... + +/friends/edit_do.bml.error.updating=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° Ð°Ð´Ð½Ð°ÑžÐ»ÐµÐ½ÑŒÐ½Ñ ÑьпіÑу вашых ÑÑброў: + +/friends/edit_do.bml.fellowfriends.head=Ð’Ñ‹ ÑÑбра + +/friends/edit_do.bml.fellowfriends.text=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð»ÑŽÐ´Ð·Ñ– пазначылі Ð²Ð°Ñ Ñк Ñвайго ÑÑбра. Магчыма вы такÑама захочаце ўнеÑьці Ñ–Ñ… у ÑÑŒÐ¿Ñ–Ñ Ð²Ð°ÑˆÑ‹Ñ… ÑÑброў. ГÑта пададзена Ñк ÑпаÑылкі, такім чынам вы ведаеце Ñ–Ñ… імёны карыÑтальнікаў Жывога Журналу. Ð’Ñ‹ не абавÑзаны дадаваць Ñ–Ñ… у Ñвой ÑÑŒÐ¿Ñ–Ñ ÑÑброў. + +/friends/edit_do.bml.foreground=ПÑÑ€Ñдні плÑн + +/friends/edit_do.bml.friend=СÑбра + +/friends/edit_do.bml.hover=ÐавÑдзіце мышку на колер, каб убачыць Ñгоную назву + +/friends/edit_do.bml.mrcolor=ПраглÑдальнік колераў + +/friends/edit_do.bml.name=Ð†Ð¼Ñ + +/friends/edit_do.bml.needmore=Калі вам Ñ‚Ñ€Ñба дадаць больш ÑÑброў, чым Ñ‘Ñьць меÑца на гÑтай форме, захавайце зьмены ўнізе, а потым вÑрніцеÑÑ Ñ– дадайце ÑшчÑ. + +/friends/edit_do.bml.nofriends.head=ÐÑма ÑÑброў? + +/friends/edit_do.bml.nofriends.text=ЦÑпер вы Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ вызначаных ÑÑброў. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, вы ўпÑўнены, што Ñž Ð²Ð°Ñ Ð¿Ð°Ð²Ñ–Ð½Ð½Ñ‹ быць ÑÑбры! :) ПроÑта ўвÑдзіце Ñ–Ñ…Ð½Ñ–Ñ Ñ–Ð¼Ñ‘Ð½Ñ‹ з Жывога Журналу ніжÑй.... + +/friends/edit_do.bml.opt.addtolist=Дадаць ÑÑбра + +/friends/edit_do.bml.opt.delete=Выдаліць? + +/friends/edit_do.bml.success.head=ПоÑьпех + +/friends/edit_do.bml.success.text=Ð’Ð°ÑˆÑ‹Ñ ÑÑбры былі абноўлены. Ð’Ñ‹ можаце ўбачыць абноўленую Ñтужку ÑÑброў тут. + +/friends/edit_do.bml.textcolor=Колер Ñ‚ÑкÑту: + +/friends/edit_do.bml.title=РÑдагаваньне ÑÑброў + +/friends/edit_do.bml.user=КарыÑтальнік + +/friends/edit_do.bml.viewer=ПраглÑдальнік колераў + +/friends/edit_do.bml.yourfriends.head=Ð’Ð°ÑˆÑ‹Ñ ÑÑбры + +/friends/edit_do.bml.yourfriends.text=ЦÑпер вы маеце вызначанымі наÑтупных ÑÑброў: + +/friends/filter.bml.editgroups=Калі вы хочаце Ñ€Ñдагаваць Ð²Ð°ÑˆÑ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў, ідзіце на Ñтаронку [[link]]. + +/friends/filter.bml.error.nogroups=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ фільтраваць ваш ÑÑŒÐ¿Ñ–Ñ ÑÑброў, таму што Ñпачатку вам Ñ‚Ñ€Ñба наладзіць Ð²Ð°ÑˆÑ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў. + +/friends/filter.bml.error.nogroups.header=Групы Ð½Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹ + +/friends/filter.bml.reset=ÐчыÑьціць + +/friends/filter.bml.select=Ðдзначце групу ці групы ÑÑброў, ÑÐºÑ–Ñ Ð²Ñ‹ хочаце бачыць у Ñваім ÑьпіÑе ÑÑброў. + +/friends/filter.bml.select.header=Выберыце групы + +/friends/filter.bml.submit=ГлÑдзець! + +/friends/filter.bml.title=Фільтр ÑÑброў + +/friends/index.bml.about<< +ГÑÑ‚Ð°Ñ Ñтаронка дазвалÑе вам кіраваць вашым ÑьпіÑам ÑÑброў. +Дадаваньнем іншых карыÑтальнікаў да вашага ÑьпіÑу ÑÑброў, вы можаце лёгка Ñачыць за Ñ–Ñ… запіÑамі на Ñтаронцы вашых ÑÑброў. Ð’Ñ‹ такÑама можаце дадаваць у ÑÑŒÐ¿Ñ–Ñ ÑÑброў Ñуполкі Ñ– Ñындыкаты, каб бачыць запіÑÑ‹ зь Ñ–Ñ… на Ñтаронцы вашых ÑÑброў. +. + +/friends/index.bml.edit.about=Дадаваньне ці выдаленьне карыÑтальнікаў Ñа ÑьпіÑу вашых ÑÑброў, ці Ñ€Ñдагаваньне Ñ€ÑпрÑзентуючых Ñ–Ñ… колераў. + +/friends/index.bml.editgroups.about=СтварÑньне, Ñ€Ñдагаваньне ці выдаленьне падгрупаў вашых ÑÑброў. + +/friends/index.bml.filter=ГÑÑ‚Ñ‹Ñ Ð³Ñ€ÑƒÐ¿Ñ‹ ÑÑброў могуць быць выкарыÑтаны Ð´Ð»Ñ Ñ„Ñ–Ð»ÑŒÑ‚Ñ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð²Ð°ÑˆÐ°Ð¹ Ñтаронкі ÑÑброў: вы можаце праглÑдаць запіÑÑ‹ аÑобнай групы. Яны такÑама могуць ужывацца Ð´Ð»Ñ Ð±ÑÑьпекі, заÑнаванай на групах (глÑдзіце ніжÑй). + +/friends/index.bml.filter.about=Фільтраваньне вашага ÑьпіÑу ÑÑброў адпаведна вызначаным падгрупам. + +/friends/index.bml.groups=Дадаткова, могуць быць вызначаны падгрупы ÑÑброў. + +/friends/index.bml.security=Ваш ÑÑŒÐ¿Ñ–Ñ ÑÑброў такÑама ўжываецца Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñаў з абмежаваным доÑтупам. Ð’Ñ‹ можаце даведацца больш пра бÑÑьпеку ÑьпіÑу ÑÑброў у СÑбры Ñ– ўзроўні бÑÑьпекі. + +/friends/index.bml.security.custom="УлаÑнымі" запіÑамі, вы можаце вызначыць ÑÐºÐ°Ñ Ð· груп ÑÑброў зможа ўбачыць гÑÑ‚Ñ‹ запіÑ. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, Ð½Ñ ÑžÑе праграмы-кліеніты на дадзены момант падтрымліваюць улаÑную бÑÑьпеку. + +/friends/index.bml.security.header=БÑÑьпека + +/friends/index.bml.security.only=ЗапіÑÑ‹ "Толькі Ð´Ð»Ñ ÑÑброў" змогуць праглÑдаць уÑе карыÑтальнікі з вашага ÑьпіÑу ÑÑброў. + +/friends/index.bml.title=Прылады ÑÑброў + +/friends/index.bml.tools=Ðаладкі + +/friends/popwithfriends.bml.account_type=Выбачайце, але тып вашага рахунку не дазвалÑе ўжываць гÑтую ÑžÑтаноўку. + +/friends/popwithfriends.bml.count=Падлік + +/friends/popwithfriends.bml.exclude_own=Па жаданьні, вы можаце выключыць вашых ÑÑброў. + +/friends/popwithfriends.bml.include_own=Па жаданьні, вы можаце далучыць вашых ÑÑброў. + +/friends/popwithfriends.bml.intro=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÑÑбры чаÑта ÑуÑтракаюцца Ñž ÑьпіÑах ÑÑброў вашых ÑÑброў, але Ð½Ñ Ñž вашым. + +/friends/popwithfriends.bml.intro_own=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÑÑбры чаÑта ÑуÑтракаюцца Ñž ÑьпіÑах ÑÑброў вашых ÑÑброў. Ð¡ÑŒÐ¿Ñ–Ñ ÑƒÐºÐ»ÑŽÑ‡Ð°Ðµ Ñ– вашых ÑÑброў такÑама. + +/friends/popwithfriends.bml.no_users=ÐÑма карыÑтальнікаў + +/friends/popwithfriends.bml.title=ПапулÑÑ€Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі ÑÑрод вашых ÑÑброў + +/friends/popwithfriends.bml.user=КарыÑтальнік + +/go.bml.defaultbody=Ðе пададзены парамÑтры. + +/go.bml.defaulttitle=Памылка + +/go.bml.error.noentry.next=ПаÑÑŒÐ»Ñ Ð³Ñтага запіÑу нÑма ніводнага запіÑу. + +/go.bml.error.noentry.prev=Перад гÑтым запіÑам нÑма ніводнага запіÑу. + +/go.bml.error.noentrytitle=ÐÑма запіÑу + +/go.bml.error.redirkey=Падроблены redir_key. + +/go.bml.error.usernotfound=КарыÑтальнік Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹. + +/index.bml.about.header=Пра Жывы Журнал + +/index.bml.about.joining=ДалучÑньне да Ñайту бÑÑплатнае. КарыÑтальнікі могуць палÑпшаць Ñвае рахункі Ð´Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ… мажліваÑьцей. + +/index.bml.about.us=Жывы Журнал - гÑта проÑÑ‚Ð°Ñ Ñž карыÑтаньні (але вельмі Ð¼Ð°Ð³ÑƒÑ‚Ð½Ð°Ñ Ñ– наладжваемаÑ) пÑÑ€ÑÐ°Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ð° Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–ÐºÐ°Ð²Ð°Ð½ÑŒÐ½Ñ ("блог"), Ð¿Ð°Ð±ÑƒÐ´Ð°Ð²Ð°Ð½Ð°Ñ Ð½Ð° праграмным забÑÑьпечаньні з адкрытым кодам. + +/index.bml.boldcreate=Стварыць Ñвой улаÑны Жывы Журнал! + +/index.bml.frank.image.alt=Казёл ФрÑнк, таліÑман Жывога Журналу. + +/index.bml.frank.logo="Меееее", кажа ФрÑнк. + +/index.bml.learnmore.header=Хочаце даведацца больш? + +/index.bml.learnmore.text=Калі лаÑка, прачытайце наш аглÑд мажліваÑьцей. ПеракананыÑ? Стварыце ваш улаÑны Жывы Журнал! + +/index.bml.meta.desc=LiveJournal.com - гÑта меÑца, дзе вы можаце дзÑліцца Ñваімі думкамі з Ñьветам. + +/index.bml.meta.keywords=дзёньнік, журнал, анлÑйн журнал, дзёньнікі, анлÑйн дзёньнікі, ÑÐµÑ†ÐµÐ²Ñ‹Ñ Ð´Ð·Ñ‘Ð½ÑŒÐ½Ñ–ÐºÑ– + +/index.bml.news.text=ÐÐ¿Ð¾ÑˆÐ½Ñ–Ñ Ð½Ð°Ð²Ñ–Ð½Ñ‹ Ñайту: + +/index.bml.news.title=ÐÐ¿Ð¾ÑˆÐ½Ñ–Ñ Ð½Ð°Ð²Ñ–Ð½Ñ‹ + +/index.bml.post=СтатыÑтыка жывых запіÑаў + +/index.bml.post.hour=За гадзіну: + +/index.bml.post.latest=ÐÐ¿Ð¾ÑˆÐ½Ñ–Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +/index.bml.post.min=За хвіліну: + +/interests.bml.add.added.head=Дададзена! + +/interests.bml.add.added.text=ЗацікаўленаÑьць была дададзена да вашага ÑьпіÑу. + +/interests.bml.add.btn.text=Дадаць [[interest]] + +/interests.bml.add.confirm.head=Пацьвердзіць + +/interests.bml.add.confirm.text=Каб дадаць [[interest]] Ñк зацікаўленаÑьць, націÑьніце кнопку ніжÑй. + +/interests.bml.add.toomany.head=Выбачайце... + +/interests.bml.add.toomany.text=Ð’Ñ‹ ўжо вызначылі [[maxinterests]] зацікаўленаÑьцей. + +/interests.bml.addint=Калі вы такÑама гÑтым цікавіцеÑÑ Ñ– жадаеце дадаць гÑта да Ñвайго ÑьпіÑу, націÑьніце тут. + +/interests.bml.btn.switch=Пераключыць + +/interests.bml.communities.head=ÐŸÐ°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ñуполкі + +/interests.bml.communities.text=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñуполкі такÑама цікавÑцца "[[interest]]". + +/interests.bml.count=Падлік + +/interests.bml.enmasse.body.other=ÐіжÑй знаходзÑцца зацікаўленаÑьці [[user]]. Ðдзначце ÐºÐ°Ð»Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьцей, калі вы хочаце дадаць Ñ–Ñ… да вашых, Ñ– не адзначайце, ÐºÐ°Ð»Ñ Ñ‚Ñ‹Ñ…, ÑÐºÑ–Ñ Ð²Ñ‹ хочаце выдаліць. Калі ÑžÑÑ‘ зроблена, націÑьніце "Захаваць зьмены". + +/interests.bml.enmasse.body.other_authas=ÐіжÑй знаходзÑцца зацікаўленаÑьці [[user]]. Ðдзначце ÐºÐ°Ð»Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьцей, калі вы хочаце дадаць Ñ–Ñ… да Ñваіх зацікаўленаÑьцей [[target]], Ñ– не адзначайце, ÐºÐ°Ð»Ñ Ñ‚Ñ‹Ñ…, ÑÐºÑ–Ñ Ð²Ñ‹ хочаце выдаліць. Калі ÑžÑÑ‘ зроблена, націÑьніце "Захаваць зьмены". + +/interests.bml.enmasse.body.you=Ðе адзначайце Ñ‚Ñ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці, ÑÐºÑ–Ñ Ð²Ñ‹ хочаце выдаліць. Калі ÑžÑÑ‘ зроблена, націÑьніце "Захаваць зьмены". + +/interests.bml.enmasse.btn=Паказаць ÑÑŒÐ¿Ñ–Ñ + +/interests.bml.enmasse.header=Дадаць/выдаліць зацікаўленаÑьці + +/interests.bml.enmasse.intro=Мадыфікаваць Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці грунтуючыÑÑ Ð½Ð°: + +/interests.bml.error.add.mustlogin=Ð’Ñ‹ павінны ўвайÑьці, каб дадаць зацікаўленаÑьць такім чынам. + +/interests.bml.error.enmasse.mustlogin=Ð’Ñ‹ павінны ўвайÑьці, каб карыÑтацца гÑтай мажліваÑьцю. + +/interests.bml.error.enmasse.noaccess=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ доÑтупу да журналу [[user]]. + +/interests.bml.error.findsim_do.intnotfound=ЗацікаўленаÑьць Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð°. + +/interests.bml.error.nointerests=Выбраны карыÑтальнік не Ñ–Ñнуе, ці не пазначыў ніводнай зацікаўленаÑьці. + +/interests.bml.findsim.searchwait=Заўважце: Пошук зойме некалькі Ñекунд. Пачакайце. + +/interests.bml.findsim_do.account.notallowed=Выбачайце, але тып вашага рахунку не дазвалÑе карыÑтацца гÑтай прыладай. + +/interests.bml.findsim_do.magic=Магічны
    індÑÐºÑ + +/interests.bml.findsim_do.magic.head=Магічны індÑкÑ? + +/interests.bml.findsim_do.magic.text=Кожны падыходзÑчы карыÑтальнік атрымлівае магічны індÑкÑ, Ñкі Ñкладаецца з двух фактараў: агульнай колькаÑьці падобных зацікаўленаÑьцей Ñ– дадатковых пунктаў за вызначÑньне незвычайных зацікаўленаÑьцей. + +/interests.bml.findsim_do.nomatch.head=ÐÑма ÑупадзеньнÑÑž + +/interests.bml.findsim_do.nomatch.text=ÐÑма карыÑтальнікаў падобных да [[user]]. + +/interests.bml.findsim_do.notdefined=КарыÑтальнік [[user]] Ð½Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ñ‹Ñž зацікаўленаÑьцей. + +/interests.bml.findsim_do.similar.head=ÐŸÐ°Ð´Ð¾Ð±Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі + +/interests.bml.findsim_do.similar.text=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð½Ð°Ð¹Ð±Ð¾Ð»ÑŒÑˆ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð´Ð° карыÑтальніка [[user]] + +/interests.bml.finished.about=Калі ÑžÑÑ‘ зроблена, націÑьніце кнопку "Захаваць зьмены" ўнізе: + +/interests.bml.finished.header=Зроблена? + +/interests.bml.finished.save_button=Захаваць зьмены + +/interests.bml.interest=ЗацікаўленаÑьць + +/interests.bml.interested.btn.find=Шукаць + +/interests.bml.interested.in=Шукаць людзей Ñ– Ñуполкі, ÑÐºÑ–Ñ Ñ†Ñ–ÐºÐ°Ð²Ñцца: + +/interests.bml.interests.findsim=Шукаць карыÑтальнікаў падобных да: + +/interests.bml.interests.head=ЗацікаўленаÑьці + +/interests.bml.interests.text=Тут знаходзÑцца Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ñ†Ñ–ÐºÐ°Ð²Ñ‹Ñ Ñ€Ñчы, ÑÐºÑ–Ñ Ð²Ñ‹ можаце зрабіць з зацікаўленаÑьцÑмі. + +/interests.bml.interests.viewpop=ПраглÑд папулÑрных зацікаўленаÑьцей + +/interests.bml.login.enterinfo=УвÑдзіце вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль, каб мадыфікаваць Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці. + +/interests.bml.login.proceed=ПрацÑг... + +/interests.bml.match=[[count]] Ñупадзеньне: + +/interests.bml.matches=[[count]] ÑупадзеньнÑÑž: + +/interests.bml.morestuff=Ð¯ÑˆÑ‡Ñ Ð±Ð¾Ð»ÑŒÑˆ цікавага можа быць знойдзена на Ñтаронцы зацікаўленаÑьцей. + +/interests.bml.nointerests.text=Ð’Ñ‹ Ð½Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ñ‹Ð»Ñ– ніводнай зацікаўленаÑьці? Дадайце некалькі, зайшоўшы на Ñтаронку РÑдагаваць аÑабіÑтую інфармацыю Ñ– ÑžÑтаноўкі + +/interests.bml.popular.disabled=Выбачайце, мажліваÑьць папулÑÑ€Ð½Ñ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці недаÑтупнаÑ. + +/interests.bml.popular.head=ПапулÑÑ€Ð½Ñ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці + +/interests.bml.popular.text=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ð°Ñьці найбольш папулÑрныÑ. + +/interests.bml.results.added=ЗацікаўленаÑьці, што вы вызначылі, былі паÑьпÑхова дададзены да вашага ÑьпіÑу зацікаўленаÑьцей. + +/interests.bml.results.both=ЗацікаўленаÑьці, што вы вызначылі, былі паÑьпÑхова дададзены да вашага ÑьпіÑу зацікаўленаÑьцей, аÑÑ‚Ð°Ñ‚Ð½Ñ–Ñ Ð±Ñ‹Ð»Ñ– выдалены. + +/interests.bml.results.deleted=ЗацікаўленаÑьці, што вы не вызначылі, былі паÑьпÑхова выбалены з вашага ÑьпіÑу зацікаўленаÑьцей. + +/interests.bml.results.del_and_toomany=ЗацікаўленаÑьці, што вы не вызначылі, былі паÑьпÑхова выбалены з вашага ÑьпіÑу зацікаўленаÑьцей. Ðднак вы выбралі зашмат зацікаўленаÑьцей, каб дадаць. Ð’Ñ‹ можаце вызначыць Ð½Ñ Ð±Ð¾Ð»ÑŒÑˆ за [[intcount]] зацікаўленаÑьцей. ÐÑ–Ð²Ð¾Ð´Ð½Ð°Ñ Ð· выбраных зацікаўленаÑьцей не была дададзена. Ð’Ñ‹ можаце вÑрнуцца назад, Ñ– выбраць менш зацікаўленаÑьцей, каб дадаць. + +/interests.bml.results.goback=Ð’Ñ‹ можаце вÑрнуцца да профілю [[user]], Ñкі вы глÑдзелі раней. + +/interests.bml.results.header=Вынікі + +/interests.bml.results.message=ПаглÑдзець Ñваю абноўленую Ñтаронку профілю. + +/interests.bml.results.nothing=Ð’Ñ‹ не зрабілі ніÑкіх зьменаў. + +/interests.bml.results.toomany=Ð’Ñ‹ выбралі зашмат зацікаўленаÑьцей, каб дадаць. Ð’Ñ‹ можаце вызначыць Ð½Ñ Ð±Ð¾Ð»ÑŒÑˆ за [[intcount]] зацікаўленаÑьцей. ÐÑ–Ð²Ð¾Ð´Ð½Ð°Ñ Ð· выбраных зацікаўленаÑьцей не была дададзена. Ð’Ñ‹ можаце вÑрнуцца назад, Ñ– выбраць менш зацікаўленаÑьцей, каб дадаць. + +/interests.bml.title=ЗацікаўленаÑьці + +/interests.bml.toomany.body=[[intcount]] людзей Ñ–/ці Ñуполак маюць у ÑьпіÑе гÑтую зацікаўленаÑьць. Ð¡ÑŒÐ¿Ñ–Ñ Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ паказаны. + +/interests.bml.toomany.head=Шмат ÑупадзеньнÑÑž + +/interests.bml.users.head=Ð—Ð°Ñ†Ñ–ÐºÐ°ÑžÐ»ÐµÐ½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі + +/interests.bml.users.text=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі цікавÑцца [[interest]]. + +/invite/index.bml.code=Код + +/invite/index.bml.error=Памылка + +/invite/index.bml.genmore=ЗгенÑраваць ÑÑˆÑ‡Ñ ÐºÐ¾Ð´Ð°Ñž + +/invite/index.bml.how_detail=У залежнаÑьці ад некалькіх фактараў, Ñ–ÑÐ½ÑƒÑŽÑ‡Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі могуць запраÑіць некаторую колькаÑьць іншых карыÑтальнікаў на гÑÑ‚Ñ‹ Ñайт. Каб запраÑіць некага, вам Ñ‚Ñ€Ñба згенÑраваць запрашальны код Ñ– перадаць код Ñму. + +/invite/index.bml.how_header=Як гÑта працуе? + +/invite/index.bml.invite_header=ЗапрашÑньні? + +/invite/index.bml.none=ÐÑма + +/invite/index.bml.redeemed=Кім выкарыÑтаны + +/invite/index.bml.title=ЗапраÑіце іншых у Жывы Журнал... + +/invite/index.bml.unused=ÐÑўжыты + +/invite/index.bml.use=ужыць + +/invite/index.bml.why_codes=Каб утрымліваць Ñуполку, кантралÑваць роÑÑ‚ Ñ– прадухілÑць абразы, ÑтварÑньне рахунку цÑпер патрабуе Ð½Ð°Ð±Ñ‹Ñ†ÑŒÑ†Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð°Ð³Ð° рахунку ці запрашÑньне ад Ñ–Ñнуючага карыÑтальніка. ÐœÑта гÑтага зрабіць Ñуполку лепшай Ð´Ð»Ñ Ð»ÑŽÐ´Ð·ÐµÐ¹, ÑÐºÑ–Ñ Ñ‘Ð¹ карыÑтаюцца, за кошт невÑлікіх нÑзручнаÑьцей Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… карыÑтальнікаў. + +/legal/index.bml.about<< +Жывы Журнал Ñтвораны, каб даваць Ð°Ð´Ð½Ð¾Ð»ÑŒÐºÐ°Ð²Ñ‹Ñ Ð²Ñ‹Ð³Ð¾Ð´Ñ‹ ÑžÑім удзельнікам, незалежна ад Ð¿Ð°Ñ…Ð¾Ð´Ð¶Ð°Ð½ÑŒÐ½Ñ Ñ– нацыÑнальнаÑьці, Ð´Ð·ÐµÐ»Ñ Ð³Ñтага мы маем некалькі правілаў. ÐÐ°ÑˆÑ‹Ñ Ð´Ð°ÐºÑƒÐ¼Ñнты ўтрымліваюць паÑтановы Ñ– інфармацыю, пра тое, Ñк мы робім уÑÑ‘ магчымае, каб найлепш абÑлугоўваць ваÑ, Ñ– ÑÐºÑ–Ñ Ð¿Ð°Ð²Ð¾Ð´Ð·Ñ–Ð½Ñ‹ мы чакаем ад нашых удзельнікаў у дачыненьні да Ð½Ð°Ñ Ñ– іншых. Жывы Журнал працуе лепш з тымі, хто прытрымліваецца правілаў. ВоÑÑŒ ÑÐ°Ð¼Ñ‹Ñ Ð²Ð°Ð¶Ð½Ñ‹Ñ Ð· Ñ–Ñ…: +
      +
    • ÐÑ–Ñкіх дамаганьнÑÑž, абразаў, пагрозаў.
    • +
    • ÐÑ–Ñкіх ушчамленьнÑÑž меншаÑьцей.
    • +
    • ÐÑ–Ñкага Ñпаму Ñž дачыненьні да гÑтага Ñайту, ці Ñгоных рахункаў.
    • +
    • Ðе разьмÑшчайце аўтарÑкай інфармацыі без папÑÑ€ÑднÑга дазволу.
    • +
    • Ðе парушайце прыватнаÑьці іншых.
    • +
    • Ðе парушайце законаў ЗШРці вашых мÑÑцовых законаў.
    • +
    +Поўны ÑÑŒÐ¿Ñ–Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»Ð°Ñž шукайце ніжÑй: +. + +/legal/index.bml.about.header=ÐглÑд + +/legal/index.bml.docs.coppa.about=Ðкт абароны правоў дзіцÑці Ñž анлÑйн (COPPA) Ñ€Ñгулюе збор Ñ– выкарыÑтаньне аÑабіÑтай інфармацыі, ÑÐºÐ°Ñ Ð¿Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ð° Ñ– датычыцца дзÑцей да трынаццацігадовага ўзроÑту. ÐÐ°ÑˆÐ°Ñ Ñтаронка COPPA тлумачыць нашае Ñтаўленьне да гÑтага закону Ñ– раÑказвае, Ñк трымацца гÑтага закону. + +/legal/index.bml.docs.header=ДакумÑнты + +/legal/index.bml.docs.privacy.about=Палітыка прыватнаÑьці раÑказвае, Ñкую інфармацыю мы зьбіраем пра нашых ўдзельнікаў, Ñ– тлумачыць, Ñк мы Ñе выкарыÑтоўваем. + +/legal/index.bml.docs.tos.about=Правілы абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ Ð°ÐºÑ€ÑÑьліваюць Ð½Ð°ÑˆÑ‹Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»Ñ‹ карыÑтаньнÑ, а такÑама паÑтановы Ñ– ўмовы ўдзелу. Удзел Ñ–/ці выкарыÑтаньне ÑÑ–ÑÑ‚Ñмы падразумÑвае згоду з гÑтымі Ñ– вышÑйазначанымі правіламі. + +/legal/index.bml.title=Ð®Ñ€Ñ‹Ð´Ñ‹Ñ‡Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/legal/privacy.bml.title=Палітыка прыватнаÑьці + +/legal/tos.bml.title=Правілы абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ + +/login.bml.bindip.label=ПрывÑзвацца да IP адраÑу: + +/login.bml.bindip.no=Ðе (працуе з уÑімі правайдÑрамі) + +/login.bml.bindip.yes=Так (бÑÑьпечней) + +/login.bml.error.mustenterusername=Ð’Ñ‹ павінны ўвеÑьці Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/login.bml.expire.btn.neverexpire=ЗьмÑніць Ñ‡Ð°Ñ Ð·Ð°ÐºÐ°Ð½Ñ‡ÑÐ½ÑŒÐ½Ñ ÑÑÑÑ–Ñ– на ÐІКОЛІ + +/login.bml.expire.btn.sessiononly=ЗьмÑніць Ñ‡Ð°Ñ Ð·Ð°ÐºÐ°Ð½Ñ‡ÑÐ½ÑŒÐ½Ñ ÑÑÑÑ–Ñ– на ТОЛЬКІ СЭÐÐС + +/login.bml.expire.neverexpire.text=Ð§Ð°Ñ Ð²Ð°ÑˆÐ°Ð³Ð° ўваходу ніколі Ð½Ñ Ñкончыцца, таму, калі вы карыÑтаецеÑÑ Ð†Ð½Ñ‚ÑрнÑтам у грамадзкім меÑцы, школе, бібліÑÑ‚Ñцы, ці там, дзе людзі могуць выкарыÑтоўваць кампутар непрацÑглы чаÑ, упÑўніцеÑÑ, што вы выйшлі, калі ÑžÑÑ‘ зрабілі! Ці, зьмÑніце опцыі ўваходу, каб Ñ‡Ð°Ñ Ð´Ð·ÐµÑÐ½ÑŒÐ½Ñ ÑканчаўÑÑ, калі вы зачынÑеце праглÑдач: + +/login.bml.expire.sessiononly.text=Ваш уваход Ñкончыцца, калі вы зачыніце ваш праглÑдач. Калі гÑта ваш улаÑны кампутар Ñ– вы адзіны карыÑтальнік на ім, то вы можаце зрабіць так, каб Ð²Ð°ÑˆÐ°Ñ ÑÑÑÑ–Ñ Ð½Ñ–ÐºÐ¾Ð»Ñ– не ÑканчвалаÑÑ: + +/login.bml.links.head=СпаÑылкі + +/login.bml.links.link1=Ð’Ð°ÑˆÐ°Ñ Ñтужка ÑÑброў. + +/login.bml.links.link2=Ваш ÑÑŒÐ¿Ñ–Ñ "што зрабіць". + +/login.bml.links.text=У далейшым гÑта Ñтаронка будзе ўтрымліваць Ð»ÑŽÐ±Ñ‹Ñ Ð¿Ð°Ñ‚Ñ€ÑÐ±Ð½Ñ‹Ñ ÑпаÑылкі Ñ– інфармацыю, а зараз тут пазначаны Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¼ÐµÑцы, на ÑÐºÑ–Ñ Ð²Ñ‹ можаце паглÑдзець: + +/login.bml.loggedin.head=Увайшлі! + +/login.bml.loggedin.text=ЦÑпер вы ўвайшлі. + +/login.bml.login.btn.changeopts=ЗьмÑніць опцыі + +/login.bml.login.btn.login=Уваход... + +/login.bml.login.expiration=ТÑрмін дзеÑÐ½ÑŒÐ½Ñ Ñканчваецца: + +/login.bml.login.forget=ЗабыліÑÑ? + +/login.bml.login.head=Уваход + +/login.bml.login.never=Ðіколі + +/login.bml.login.otheropts=Ð†Ð½ÑˆÑ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ– + +/login.bml.login.password=Пароль: + +/login.bml.login.text1=Каб увайÑьці на [[sitename]], увÑдзіце вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль ніжÑй. ÐÐ¾Ð²Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі: Каб Ñтварыць рахунак, ідзіце Ñюды. + +/login.bml.login.text2=Ð’Ñ‹ такÑама можаце пазначыць, калі будзе Ñканчвацца ваш уваход. Па змоўчаньні ваш уваход будзе Ñканчвацца, калі вы зачыніце ваш праглÑдач, што лепш Ð´Ð»Ñ Ð³Ñ€Ð°Ð¼Ð°Ð´Ð·ÐºÑ–Ñ… кампутараў. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, калі вы адзіны карыÑтальнік кампутару, Ñ– ніхто іншы Ð½Ñ Ð¼Ð°Ðµ да Ñго доÑтупу, вы можаце выбраць опцыю, каб заÑтавацца ўвайшоўшым заўÑёды. Ð”Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі Ñ– іншых опцыÑÑž, глÑдзіце Ð¯ÐºÑ–Ñ Ñ‘Ñьць опцыі паÑÑŒÐ»Ñ Ð¼Ð°Ð¹Ð³Ð¾ ўваходу? + +/login.bml.login.text3=[[username]], цÑпер вы ўвайшлі на [[sitename]]. ПачувайцеÑÑ Ð²Ð¾Ð»ÑŒÐ½Ð° праглÑдаючы Ñайт, ужываючы нашую Мапу Ñайту. + +/login.bml.login.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/login.bml.login.whenbrowsercloses=Калі праглÑдач зачынÑецца + +/login.bml.logout.btn=ВыйÑьце + +/login.bml.title=Уваход + +/login.bml.whylogin.benefit1=Вам цÑпер Ð½Ñ Ñ‚Ñ€Ñба больш нідзе на гÑтым Ñайце ўводзіць Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль. + +/login.bml.whylogin.benefit2=ЦÑпер вы можаце чытаць "абароненыÑ" Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ вашых ÑÑброў, да Ñкіх Ñны далі вам доÑтуп. + +/login.bml.whylogin.benefit3=Шмат мажліваÑьцей Ð±Ð°Ñ‡Ð½Ñ‹Ñ Ñ†Ñ– даÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– тады, калі вы ўвайшлі. + +/login.bml.whylogin.head=Ðавошта ўваходзіць? + +/login.bml.whylogin.text=ВоÑÑŒ Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð²Ð°Ð³Ñ– ўваходу: + +/logout.bml.already.head=Ужо выйшлі + +/logout.bml.already.text=Ð’Ñ‹ ўжо выйшлі. + +/logout.bml.killall.btn=Скончыць уÑе мае ÑÑÑÑ–Ñ– + +/logout.bml.killall.head=Ð†Ð½ÑˆÑ‹Ñ ÑÑÑÑ–Ñ– + +/logout.bml.killall.text=У Ð²Ð°Ñ Ñ‘Ñьць Ñ–Ð½ÑˆÑ‹Ñ Ð°ÐºÑ‚Ñ‹ÑžÐ½Ñ‹Ñ ÑÑÑÑ–Ñ–. Ð’Ñ‹ хочаце Ñкончыць уÑе ÑÑÑÑ–Ñ–, а Ð½Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– гÑтую? (ГлÑдзіце гÑÑ‚Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі.) + +/logout.bml.loggedout.already=Ужо выйшлі. + +/logout.bml.loggedout.head=Выйшлі + +/logout.bml.loggedout.killedall=УÑе Ð²Ð°ÑˆÑ‹Ñ ÑÑÑÑ–Ñ– Ñкончаны. + +/logout.bml.loggedout.success=Выйшлі. + +/logout.bml.loggedout.text=ЦÑпер вы выйшлі. + +/logout.bml.logout.btn=ВыйÑьце + +/logout.bml.logout.head=ВыйÑьці? + +/logout.bml.logout.text=ÐаціÑьніце кнопку ўнізе, каб выйÑьці. + +/logout.bml.title=Выхад + +/lostinfo.bml.btn.proceed=ПрацÑг + +/lostinfo.bml.enter_email=УвÑдзіце ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты: + +/lostinfo.bml.enter_email_optional=ÐÐ´Ñ€Ð°Ñ Ñл.пошты: (не абавÑзкова) + +/lostinfo.bml.enter_username=УвÑдзіце вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/lostinfo.bml.error.no_email=Ð’Ñ‹ паінны ўвеÑьці ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, каб даведацца вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/lostinfo.bml.error.purged=Ðемагчыма вызначыць пароль да выдаленнага рахунку, бо ён быў зьнішчаны. + +/lostinfo.bml.error.renamed=Ðемагчыма вызначыць пароль да перайменаванага рахунку. + +/lostinfo.bml.error.syndicated=Рахунак, Ð´Ð»Ñ Ñкога вы Ñпрабуеце атрымаць пароль, зьÑўлÑецца Ñындыкаваным. Ð¢Ð°ÐºÑ–Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– Ð½Ñ Ð¼Ð°ÑŽÑ†ÑŒ паролю Ð´Ð»Ñ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½ÑŒÐ½Ñ. + +/lostinfo.bml.error.sysbanned=Ваш рахунак не дазвалÑе даÑылаць паролі праз Ñл.пошту. + +/lostinfo.bml.lostpassword.text=Калі вы згубілі ваш пароль, увÑдзіце вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– магчыма, Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, на Ñкі вы хочаце атрымаць пароль. Каб атрымаць ваш пароль на адзін з папÑÑ€Ñдне пазначаных адраÑоў Ñл.пошты, гÑÑ‚Ñ‹ Ð°Ð´Ñ€Ð°Ñ Ð¿Ð°Ð²Ñ–Ð½ÐµÐ½ быў быць пацьверджаны. Калі вы пакініце поле Ñл.пошты пуÑтым, пароль будзе даÑланы на ваш бÑгучы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/lostinfo.bml.lostpassword.title=Згубілі Ñвой пароль? + +/lostinfo.bml.lostusername.text=Калі вы забылі Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, увÑдзіце ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ñ– мы дашлем вам Ñго. + +/lostinfo.bml.lostusername.title=Забылі Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка? + +/lostinfo.bml.title=Ð—Ð³ÑƒÐ±Ð»ÐµÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/lostinfo_do.bml.error.no_usernames_for_email=Ðе Ñ–Ñнуе Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ð´Ð»Ñ Ð³Ñтага адраÑу Ñл.пошты: [[address]] . + +/lostinfo_do.bml.error1.text=Ð’Ñ‹ ніколі не ўжывалі гÑÑ‚Ñ‹ Ð°Ð´Ñ€Ð°Ñ Ñл.пошты з гÑтым рахункам, ці ён ніколі Ð½Ñ Ð±Ñ‹Ñž пацьверджаны. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** ГÑта аўтаматычны ліÑÑ‚. Вам Ð½Ñ Ñ‚Ñ€Ñба адказваць на Ñго. *** +ГÑта напамінальнік вашага паролю з [[sitename]]. +ÐіжÑй знаходзÑцца Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, пароль Ñ– Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, на ÑÐºÑ–Ñ Ð·Ð°Ñ€ÑгіÑтраваны ваш журнал. +Â Â Â Â Â Â Â Â Â Â Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: [[username]] +          Пароль: [[password]] +     ÐÐ´Ñ€Ð°Ñ Ñл.пошты: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Каб пацьвердзіць ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, ідзіце Ñюды: + +/lostinfo_do.bml.lostpasswordmail.part3<< +ГÑÑ‚Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð½Ð° нашым Ñайце была запытана з [[remoteip]]. +Калі вы не рабілі запыту, каб атрымаць пароль на Ñл.пошту, не хвалюйцеÑÑ. +У любым выпадку, вы адзіны, хто бачыць гÑÑ‚Ñ‹ ліÑÑ‚. +Магчыма, што той карыÑтальнік, што рабіў запыт упÑўнены, што гÑта Ñгонае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. +ТакÑама магчыма, што нехта памыліўÑÑ ÑžÐ²Ð¾Ð´Ð·Ñчы Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ці Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Калі вы думаеце, што ваш рахунак знаходзіцца Ñž небÑÑьпецы, прачытайце http://www.livejournal.com/support/faqbrowse.bml?faqid=117 Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі, Ñк зрабіць Ñго ізноў бÑÑьпечным. + +/lostinfo_do.bml.lostpasswordmail.part5<< +КарыÑÐ½Ñ‹Ñ ÑпаÑылкі: + +  Ваш Жывы Журнал: +    [[journalurl]] +  + Зрабіць Ð·Ð°Ð¿Ñ–Ñ Ñƒ ваш журнал: +    [[updateurl]] + +З найлепшымі пажаданьнÑмі, +Каманда Жывога Журналу + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Згублены пароль + +/lostinfo_do.bml.password_mailed.text=ПоÑьпех. Ваш пароль быў адаÑланы. + +/lostinfo_do.bml.password_mailed.title=Пароль адаÑланы! + +/lostinfo_do.bml.title=Ð—Ð³ÑƒÐ±Ð»ÐµÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/lostinfo_do.bml.username_mailed.text=ПоÑьпех. Вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка было адаÑлана. + +/lostinfo_do.bml.username_mailed.title=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка адаÑлана. + +/manage/index.bml.about=Кіраваньне вашым рахункам - гÑта проÑта. ПроÑта выбірайце з наÑтупнага: + +/manage/index.bml.communities=Стварыце Ñ– кіруйце вашымі ўлаÑнымі Ñуполкамі: + +/manage/index.bml.communities.create.about=СтварÑньне новай Ñуполкі + +/manage/index.bml.communities.header=Суполкі + +/manage/index.bml.communities.manage.about=Кіраваньне ÑžÑтаноўкамі Ñ– ўдзельнікамі вашых Ñуполак + +/manage/index.bml.customization=Ðаладка выглÑду Ñтаронак вашага журналу: + +/manage/index.bml.customization.advanced=ÐŸÐ°ÑˆÑ‹Ñ€Ð°Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´ÐºÑ– + +/manage/index.bml.customization.advanced.about=ПраглÑд, ÑтварÑньне Ñ– Ñ€Ñдагаваньне вашай Ñхемы Ñ– Ñтылю S2 + +/manage/index.bml.customization.customize=Ðаладка журналу + +/manage/index.bml.customization.customize.about=ЗьмÑненьне выглÑду вашага журналу + +/manage/index.bml.customization.header=Ðаладка + +/manage/index.bml.customization.links=Ð¡ÑŒÐ¿Ñ–Ñ ÑпаÑылак + +/manage/index.bml.customization.links.about=СтварÑньне ÑьпіÑу ÑпаÑылак Ð´Ð»Ñ Ð°Ð´Ð»ÑŽÑÑ‚Ñ€Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñž вашым журнале + +/manage/index.bml.customization.modify.about=Мадыфікаваць наладкі выглÑду вашага журналу + +/manage/index.bml.customization.s1.header=СыÑÑ‚Ñма Ñтылю S1 + +/manage/index.bml.customization.s2.header=СыÑÑ‚Ñма Ñтылю S2 + +/manage/index.bml.entries=Праца з запіÑамі, што вы зрабілі Ñž журнале вашага рахунку: + +/manage/index.bml.entries.edit.about=РÑдагаваньне Ñ– выдаленьне запіÑаў у вашым журнале + +/manage/index.bml.entries.header=Ð–ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +/manage/index.bml.entries.memories.about=ПраглÑдайце Ñ– працуйце з вашымі запамінальнымі запіÑамі + +/manage/index.bml.friends=Кіруйце ÑьпіÑам Ñваіх ÑÑброў Ñ– групамі ÑÑброў, ці фільтруйце вашую Ñтаронку ÑÑброў згодна Ñа Ñтворанымі групамі ÑÑброў: + +/manage/index.bml.friends.edit.about=Дадаваньне ці выдаленьне карыÑтальнікаў Ñа ÑьпіÑу ÑÑброў, альбо зьмена Ñ€ÑпрÑзентуючых Ñ–Ñ… колераў. + +/manage/index.bml.friends.filter=Фільтраваньне Ñтаронкі ÑÑброў + +/manage/index.bml.friends.filter.about=Фільтраваньне вашага ÑьпіÑу ÑÑброў, каб паказаць аÑобную групу ÑÑброў + +/manage/index.bml.friends.groups.about=СтварÑньне, Ñ€Ñдагаваньне, ці выдаленьне падгруп вашага ÑьпіÑу ÑÑброў + +/manage/index.bml.friends.header=СÑбры + +/manage/index.bml.information=Выберыце, ÑÐºÐ°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ð°Ð²Ñ–Ð½Ð½Ð° паказвацца на вашым рахунку: + +/manage/index.bml.information.changepass=ЗьмÑніць пароль рахунку + +/manage/index.bml.information.changepass.about=ЗьмÑненьне паролю да вашага рахунку + +/manage/index.bml.information.editinfo.about=РÑдагаваньне вашай інфармацыі пра рахунак Ñ– розных опцыÑÑž. + +/manage/index.bml.information.emailpost=УÑтаноўкі шлюзу Ñл.пошты + +/manage/index.bml.information.emailpost.about=Кіраваньне вашымі адраÑамі Ñл.пошты Ñ– PIN Ð´Ð»Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÑ– запіÑаў праз Ñл.пошту + +/manage/index.bml.information.header=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° рахунак + +/manage/index.bml.information.siteopts.about=Выберыце вашую Ñхему Ñайту Ñ– мову + +/manage/index.bml.information.status=Стан рахунку + +/manage/index.bml.information.status.about=ВызначÑньне Ñтану актывацыі вашага рахунку (выдаленьне ці ўзнаўленьне вашага рахунку) + +/manage/index.bml.login=ÐаÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ ÑпаÑылкі правÑдуць Ð²Ð°Ñ Ð¿Ð° Ñтаронках, дзе ÑпатрÑбіцца Ð²Ð°ÑˆÐ°Ñ ÑžÐ²Ð°Ñ…Ð¾Ð´Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ. Каб захаваць Ñабе крыху чаÑу, вы можаце ўвайÑьці раней. + +/manage/index.bml.title=Кіраваньне рахункам + +/manage/index.bml.userpictures=Загружайце Ñ– кіруйце выÑвамі карыÑтальніка Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° рахунку: + +/manage/index.bml.userpictures.edit.about=Загрузка Ñ– кіраваньне вашымі выÑвамі карыÑтальніка + +/manage/index.bml.userpictures.header=Ð’Ñ‹Ñвы карыÑтальніка + +/manage/links.bml.about=Ужывайце форму ніжÑй, каб Ñтварыць ÑÑŒÐ¿Ñ–Ñ ÑпаÑылак, Ñкі б зьÑвіўÑÑ Ñž вашым журнале. СпÑылкі зьÑвÑцца толькі калі гÑÑ‚Ð°Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьць падтрымліваецца вашым Ñтылем S2. + +/manage/links.bml.about.blank=Каб Ñтварыць пуÑÑ‚Ñ‹ радок, увÑдзіце "-" замеÑÑ‚ назвы. + +/manage/links.bml.about.heading=Каб Ñтварыць загаловак, увÑдзіце назву бÑз адраÑу URL. + +/manage/links.bml.about.reorder=Каб пераўпарадкаваць ÑпаÑылкі Ñž ÑьпіÑе, зьмÑніце лікі зьлева (дзеÑÑÑ‚ÐºÐ¾Ð²Ñ‹Ñ Ð»Ñ–ÐºÑ– прымаюцца). + +/manage/links.bml.error.s2required=СьпіÑÑ‹ ÑпаÑылак наÑÑžÐ½Ñ‹Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– Ñž падтрымліваемых ÑтылÑÑ… S2. Каб пераключыцца на S2, глÑдзіце Ñтаронку [[link]]. + +/manage/links.bml.error.s2required.header=Патрабуецца S2 + +/manage/links.bml.success=ПоÑьпех! Ð’Ð°ÑˆÑ‹Ñ ÑпаÑылкі захаваны. + +/manage/links.bml.title=Ð¡ÑŒÐ¿Ñ–Ñ ÑпаÑылак + +/manage/phonepost.bml.delete=Выдаліць уÑтаноўкі + +/manage/phonepost.bml.deleted=Ð’Ð°ÑˆÑ‹Ñ ÑžÑтаноўкі запіÑу па Ñ‚Ñлефоне былі выдалены. + +/manage/phonepost.bml.deleted.header=Выдалены + +/manage/phonepost.bml.error.inuse=ÐÑÑлушны PIN, паÑпрабуйце іншы + +/manage/phonepost.bml.error.phone.length=У вашым нумары Ñ‚Ñлефону павінна быць Ð½Ñ Ð¼ÐµÐ½Ñˆ за 10 лічбаў. + +/manage/phonepost.bml.error.pin=Ваш PIN павінен быць лічбавым. + +/manage/phonepost.bml.error.transcription=ÐÑÑÐ»ÑƒÑˆÐ½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð° ÑÑброў Ð´Ð»Ñ Ð¿Ñ€Ð°ÑÐ»ÑƒÑ…Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ + +/manage/phonepost.bml.intro.loggedin<< +ЗапіÑÑ‹ па Ñ‚Ñлефоне, увÑдзіце нумар Ñ‚Ñлефону Ñ– PIN ніжÑй. p?> +Палітыку прыватнаÑьці Ð´Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі). +Званкі, Ð·Ñ€Ð¾Ð±Ð»ÐµÐ½Ñ‹Ñ Ð· нумароў адрозных ад вашага аўтарызванага нумару ÑžÑÑ‘ роўна будуць прымацца, але вы павінны будзеце ўвеÑьці ваш аўтарызаваны Ñ‚Ñлефонны нумар перад тым, Ñк рабіць запіÑ. p?> + +. + +/manage/phonepost.bml.intro.loggedout=Удзельнікі могуць увайÑьці Ñ– зьмÑніць Ñвае ÑžÑтаноўкі ЗапіÑу па Ñ‚Ñлефоне тут: + +/manage/phonepost.bml.phone=Ðўтарызаваны нумар Ñ‚Ñлефону: + +/manage/phonepost.bml.pin=ПÑÑ€Ñанальны ІдÑнтыфікацыйны Ðумар: + +/manage/phonepost.bml.pin.help=Ñ€Ñкамендавана 4-6 лічбаў + +/manage/phonepost.bml.save=Захаваць уÑтаноўкі + +/manage/phonepost.bml.saved=Захавана + +/manage/phonepost.bml.success.moreinfo=Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі, Ñк зрабіць Ð—Ð°Ð¿Ñ–Ñ Ð¿Ð° Ñ‚Ñлефоне, глÑдзіце Як мне зрабіць аўдыё-Ð·Ð°Ð¿Ñ–Ñ Ñƒ Ñвой журнал?. + +/manage/phonepost.bml.success.text=Ð’Ð°ÑˆÑ‹Ñ Ñ‚ÑÐ»ÐµÑ„Ð¾Ð½Ð½Ñ‹Ñ ÑžÑтаноўкі былі захаваныÑ. + +/manage/phonepost.bml.title=УÑтаноўкі запіÑу па Ñ‚Ñлефоне + +/manage/phonepost.bml.transcribers=Дазволіць праÑлухоўваньне: + +/manage/phonepost.bml.transcribers.help=РÑдагаваньне груп ÑÑброў + +/manage/pubkey.bml.error.invalidkey=ГÑта не зьÑўлÑецца Ñапраўдным ключом PGP/GPG. + +/manage/pubkey.bml.error.notconfigured=ГÑÑ‚Ñ‹ Ñайт не Ñканфігураваны Ð´Ð»Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÑ– PGP. + +/manage/pubkey.bml.header=PGP/GPG ключ + +/manage/pubkey.bml.info=Публікаваньне вашага адкрытага ключа дазволіць іншым праглÑдаць Ñго праз вашую Ñтаронку інфармацыі пра карыÑтальніка, Ñ– вы зможаце рабіць запіÑÑ‹ праз шлюз Ñл.пошты з дапамогай падпіÑаных паведамленьнÑÑž. ГлÑдзіце інÑтрукцыі тут/a>. + +/manage/pubkey.bml.pastekey=УÑтаўце ваш ключ поўнаÑьцю (у фармаце ascii) Ñž поле ніжÑй: + +/manage/pubkey.bml.save=Захаваць + +/manage/pubkey.bml.successhead=ПоÑьпех + +/manage/pubkey.bml.successtext=Ваш адкрыты ключ захаваны. Ð’Ñ‹ можаце ўбачыць Ñго тут. + +/manage/pubkey.bml.title=УÑтаноўка адкрытага ключа + +/manage/pubkey.bml.whatis=ÐÑ Ð²ÐµÐ´Ð°ÐµÑ†Ðµ, што такое адкрыты ключ? ПатрÑбна дапамога Ñž ÑкÑпартаваньні вашага ключа? ДаведайцеÑÑ Ð±Ð¾Ð»ÐµÐ¹ пра PGP ды GPG. + +/manage/siteopts.bml.btn.lang=Пераключыць мову + +/manage/siteopts.bml.btn.scheme=Пераключыць Ñхему + +/manage/siteopts.bml.head.lang=Выберыце вашую мову + +/manage/siteopts.bml.head.scheme=Выберыце вашую Ñхему + +/manage/siteopts.bml.scheme.preview=[ПерадпраглÑд Ñхемы [[title]]] + +/manage/siteopts.bml.title=Опцыі праглÑду + +/meme.bml.meme.disabled=ÐдмініÑтратар Ñайту заблÑкаваў гÑтую мажліваÑьць. + +/modify.bml.title=Мадыфікаваць журнал + +/modify_do.bml.availablestyles.head=ÐаÑÑžÐ½Ñ‹Ñ Ñтылі + +/modify_do.bml.availablestyles.userstyles=Стылі карыÑтальніка: + +/modify_do.bml.colortheme.about=Тут вы можаце выбраць Ñхему колераў, ÑÐºÐ°Ñ Ð±ÑƒÐ´Ð·Ðµ дапаÑавана да опцыÑÑž, што вы выбралі вышÑй. Ці, калі вам непадабаюцца Ð¿Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ ÐºÐ¾Ð»ÐµÑ€Ñ‹, вызначыце Ñвае! + +/modify_do.bml.colortheme.area.head=Зона карыÑтальніка + +/modify_do.bml.colortheme.color.head1=Колер + +/modify_do.bml.colortheme.color.head2=(#rrggbb ці імÑ) + +/modify_do.bml.colortheme.customcolors=УлаÑÐ½Ñ‹Ñ ÐºÐ¾Ð»ÐµÑ€Ñ‹ + +/modify_do.bml.colortheme.defaulttheme=ТÑма па змоўчаньні + +/modify_do.bml.colortheme.head=ТÑма колераў + +/modify_do.bml.domainalias.about=Калі вы ўжо маеце зарÑгіÑтраваны дамÑн (ці плÑнуеце зарÑгіÑтраваць) Ñ– жадаеце, каб пры ўваходзе на Ñго загружаўÑÑ Ð²Ð°Ñˆ Жывы Журнал, увÑдзіце Ñго тут: + +/modify_do.bml.domainalias.domainname=Ð†Ð¼Ñ Ð´Ð°Ð¼Ñну: + +/modify_do.bml.domainalias.example=Прыклад: my-journal.com + +/modify_do.bml.domainalias.head=ПÑÑўданім дамÑну + +/modify_do.bml.domainalias.helptext=Каб гÑта працавала, вы павінны зрабіць, каб DNS вашага дамÑннага Ñ–Ð¼Ñ ÑžÐºÐ°Ð·Ð²Ð°Ð»Ð° на аднолькавы IP з [[sitename]]. Ð”Ð·ÐµÐ»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі, глÑдзіце гÑÑ‚Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы. + +/modify_do.bml.done.btn.savechanges=Захаваць зьмены + +/modify_do.bml.done.head=Зроблена? + +/modify_do.bml.done.text=Калі зроблена, націÑьніце кнопку "Захаваць зьмены" ніжÑй... + +/modify_do.bml.error.dupdomainalias=Іншы карыÑтальнік ужо зарÑгіÑтраваў Ð´Ð»Ñ ÐºÐ°Ñ€Ñ‹ÑÑ‚Ð°Ð½ÑŒÐ½Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ñ‹ вамі пÑÑўданім дамÑну. + +/modify_do.bml.error.stylenotavailable=Ðдзін з выбраных вамі Ñтылей не даÑтупны. ГÑта можа быць вынікам таго, што нехта выдаліў гÑÑ‚Ñ‹ Ñтыль, ці вы Ñпрабуеце выбраць Ñтыль, да Ñкога Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ доÑтупу. + +/modify_do.bml.friends.about=ГÑта опцыі, каб наладзіць выглÑд вашай Ñтужкі ÑÑброў. + +/modify_do.bml.friends.head=Стужка ÑÑброў + +/modify_do.bml.friends.opt.usesharedpic.about=ГÑÑ‚Ð°Ñ Ð¾Ð¿Ñ†Ñ‹Ñ ÐºÐ°Ð½Ñ‚Ñ€Ð°Ð»ÑŽÐµ, Ñкі малюнак вы ўбачыце Ñž вашай Ñтужцы ÑÑброў, калі карыÑтальнік робіць Ð·Ð°Ð¿Ñ–Ñ Ñž ÑумеÑны журнал, ці Ñуполку. Калі вы адзначыце тут, тады вы будзеце бачыць малюнак Ñуполкі. Калі вы не адзначыце тут, то будзеце бачыць малюнак карыÑтальніка, Ñкі зрабіў гÑÑ‚Ñ‹ запіÑ. + +/modify_do.bml.friends.opt.usesharedpic.head=ВыкарыÑтоўваць малюнак ÑумеÑнага журналу замеÑÑ‚ малюнку карыÑтальніка, што зрабіў Ð·Ð°Ð¿Ñ–Ñ + +/modify_do.bml.journaloptions.about=ÐдÑюль вы можаце перарабіць зьнешні выглÑд Ñтаронак вашага Жывога Журналу. Калі вам Ñапраўды цікава, Ñк гÑта ÑžÑÑ‘ працуе, чытайце інфармацыю Ð´Ð»Ñ Ñ€Ð°Ñпрацоўшчыкаў. Інакш, мы думаем, што вам хопіць базавых опцый ніжÑй: + +/modify_do.bml.journaloptions.head=Опцыі журналу + +/modify_do.bml.journalstatus.about=Калі вы хочаце выдаліць ці ўзнавіць Ñвой журнал, то гÑта меÑца, каб зрабіць гÑта. У выпадку Ð²Ñ‹Ð´Ð°Ð»ÐµÐ½ÑŒÐ½Ñ Ñвайго журналу вы маеце 30 дзён, каб узнавіць Ñго, калі вы перадумаеце. Праз 30 дзён ваш журнал будзе выдалены назаўÑёды, Ñ– магчымаÑьці ўзнавіць Ñго Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ. + +/modify_do.bml.journalstatus.head=Стан актывацыі журналу + +/modify_do.bml.journalstatus.select.activated=Ðктыўны + +/modify_do.bml.journalstatus.select.deleted=Выдалены + +/modify_do.bml.journalstatus.select.head=Стан: + +/modify_do.bml.journalstatus.select.suspended=Прыпынены + +/modify_do.bml.moodicons.about=Калі вы робіце Ð·Ð°Ð¿Ñ–Ñ Ñž журнал, вы такÑама можаце пазначаць ваш бÑгучы наÑтрой. Ð Ð¾Ð·Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі даÑлалі нам Ñ€Ð¾Ð·Ð½Ñ‹Ñ Ð½Ð°Ð±Ð¾Ñ€Ñ‹ малюнкаў наÑтрою, ÑÐºÑ–Ñ Ð²Ñ‹ можаце ўжываць. Ці, выберыце "Ðе ўжываць", каб ÐºÐ°Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° наÑтрою не было ніÑкіх малюнкаў. (вы нават можаце не ўжываць опцыю БÑгучага наÑтрою ўвогуле.) + +/modify_do.bml.moodicons.head=Малюнкі наÑтрою + +/modify_do.bml.moodicons.opt.forcefriends.about=РаÑпаўÑюдзіць ужываньне гÑтай Ñ‚Ñмы наÑтроÑÑž на ÑžÑÑ–Ñ… вашых ÑÑброў у Ñтужцы. + +/modify_do.bml.moodicons.personal=ÐÑабіÑÑ‚Ñ‹Ñ Ñ‚Ñмы: + +/modify_do.bml.moodicons.preview=перадпраглÑд + +/modify_do.bml.moodicons.select=Выберыце набор малюнкаў наÑтрою: + +/modify_do.bml.overrides.about=Калі вам падабаецца опцыі Ñхемы вашага журналу, то вы можаце праігнараваць гÑÑ‚Ñ‹ разьдзел. Ðн Ñ–Ñнуе Ð´Ð»Ñ Ð²ÐµÐ»ÑŒÐ¼Ñ– тонкай наладкі выглÑду вашых Ñтаронак. Ð”Ð»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑьцей чытайце Што такое перапрацоўкі? Як Ñны працуюць? Ñ– наведайце разьдзел раÑпрацоўшчыкаў. Заўважце, што перапрацоўкі ўжываюцца толькі Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ñ€Ð¾Ð±ÐºÑ– адной ці двух Ñ€Ñчаў Ñа Ñтылю. Калі вы хочаце перарабіць уÑÑ‘, вам Ñ‚Ñ€Ñба Ñтварыць ваш улаÑны Ñтыль. Ð”Ð·ÐµÐ»Ñ Ð°Ð³Ð»Ñду пра ÑтварÑньне Ñтылю, глÑдзіце Як мне Ñтварыць улаÑны Ñтыль? + +/modify_do.bml.overrides.box.head=Перапрацоўкі: + +/modify_do.bml.overrides.head=Перапрацоўкі Ñтылю + +/modify_do.bml.overrides.note=Заўважце, што Ð½Ñ ÑžÑе Ð·ÑŒÐ¼ÐµÐ½Ð½Ñ‹Ñ Ñтылю могуць быць перапрацаваны. ГлÑдзіце дакумÑнтацыю Ð´Ð»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑьцей.
    ТакÑама памÑтайце, што калі пры Ñпробе Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð¿ÐµÑ€Ð°Ð¿Ñ€Ð°Ñ†Ð¾Ð²Ð°Ðº вы выкарыÑтаеце Ñ‚Ñг, Ñкі не дазволены Ñž пачатку дакумÑнта, напрыклад <DIV>, <SPAN>, <IMG>, Ñ– шмат іншых, то Ñ‚Ð°ÐºÑ–Ñ Ñ‚Ñгі будуць прыбраны. ÐÐ´Ð·Ñ–Ð½Ñ‹Ñ Ñлементы HTML, ÑÐºÑ–Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ быць выкарыÑтаны у перапрацоўках *_HEAD, гÑта Ñ‚Ñ‹Ñ, ÑÐºÑ–Ñ Ð¼Ð¾Ð¶Ð½Ð° выкарыÑтоўваць у пачатку дакумÑнту HTML. ГÑта <title>, <base>, <style>, <link>, and <meta>. + +/modify_do.bml.overrides.warning=ГЭТРÐЯ МЕСЦÐ, ДЗЕ ВЫ ПІШЫЦЕ ÐŽ СВОЙ ЖУРÐÐЛ!! + +/modify_do.bml.pagelayoutstyle.about=УÑтаноўка гÑÑ‚Ñ‹Ñ… опцыÑÑž гÑта тое, Ñк будзе выглÑдаць ваш журнал на Ñкране. + +/modify_do.bml.pagelayoutstyle.head=Стыль выглÑду Ñтаронкі + +/modify_do.bml.pagelayoutstyle.warning=Ваш тып рахунку дазвалÑе вам выбіраць толькі паміж абмежаванай колькаÑьцю ÑтылÑÑž па змоўчаньні. + +/modify_do.bml.success.head=ПоÑьпех + +/modify_do.bml.success.text=УÑтаноўкі вашага журналу былі абноўлены. Ð’Ñ‹ можаце паглÑдзець на Ñвой журнал тут. + +/multisearch.bml.formaterror=Памылка фармату + +/multisearch.bml.noaddress.text=Ð’Ñ‹ не ўвÑлі Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/multisearch.bml.noaddress.title=ÐÑма адраÑу + +/multisearch.bml.nointerest.text=Ð’Ñ‹ не ўвÑлі зацікаўленаÑьць. + +/multisearch.bml.nointerest.title=ÐÑма зацікаўленаÑьці + +/multisearch.bml.nomatch.text=Згодна з пазначаным вамі крытÑрам вынікаў не атрымана. + +/multisearch.bml.nomatch.title=ÐÑма ÑупадзеньнÑÑž + +/multisearch.bml.region.bodytext<< +Ð’Ñ‹ можаце шукаць па Ñ€Ñгіёне Ñž адным з наÑтупных фарматаў: +
      +
    • Краіна
    • +
    • Горад *
    • +
    • Горад, Штат *
    • +
    • Штат, Краіна
    • +
    • Горад, Штат, Краіна
    • +
    +Заўвагі: +
      +
    • * пры пошуке толькі па горадзе ці па горадзе Ñ– штату па змоўчаньні мÑркуецца, што краіна - гÑта Ð—Ð»ÑƒÑ‡Ð°Ð½Ñ‹Ñ Ð¨Ñ‚Ð°Ñ‚Ñ‹ ÐмÑрыкі.
    • +
    • Там, дзе краіна, можа быць уведзена Ð¿Ð¾ÑžÐ½Ð°Ñ Ð½Ð°Ð·Ð²Ð° краіны, ці дзьвюхлітарны код краіны
    • +
    +Калі вы хочаце зрабіць пошук іншага тыпу, глÑдзіце пошук па паказальніку. +. + +/multisearch.bml.region.head=Пошук па Ñ€Ñгіёне + +/paidaccounts/index.bml.costs.header=Добра, Ñ– колькі гÑта каштуе? + +/paidaccounts/index.bml.costs.rates=Кошты наÑтупныÑ: + +/paidaccounts/index.bml.costs.rates.amount.header=Сума + +/paidaccounts/index.bml.costs.rates.inexpensive<< +ГÑта атрымліваецца крышку больш за $2 у меÑÑц пры гадавым плÑне. +ГÑта наўрад ці ўдарыць па вашай кішÑні. +Самае цÑжкае гÑта даÑтаць кашалёк, знайÑьці Ñž ім крÑдытную картку, Ñ– ўвеÑьці Ð²Ð°ÑˆÑ‹Ñ Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ. +. + +/paidaccounts/index.bml.costs.rates.time.header=Ð§Ð°Ñ + +/paidaccounts/index.bml.features<< +
    Каб паказаць, што мы цÑнім карыÑтальнікаў, што ўкладаюць у наш Ñайт, колькі мажліваÑьцÑÑž даÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– ўладальнікам платных рахункаў. ГÑÑ‚Ñ‹Ñ Ð¼Ð°Ð¶Ð»Ñ–Ð²Ð°Ñьці ўключаюць, але не абмежаваны наÑтупнымі:
    + +
    Ðовае! ЗапіÑÑ‹ праз Ñл.пошту
    +
    Уладальнікі платных рахункаў могуць рабіць запіÑÑ‹ Ñž Ñвае журналы Ñ– Ñуполкі хутка Ñ– бÑÑьпечна праз наш шлюз Ñл.пошты.
    + +
    Ðаладка вашага журналу
    +
    У дадатак да таго, што вы можаце выбраць любы Ñтыль Ñ– колеры, вы можаце Ñтварыць ваш улаÑны Ñтыль карыÑтаючыÑÑ Ð»ÑŽÐ±Ñ‹Ð¼ HTML. Ð’Ñ‹ такÑама можаце зрабіць Ñтыль Ñкі будзе нагадваць ваш аÑабіÑÑ‚Ñ‹ Ñайт, у Ñкі вы можаце ўклаÑьці гÑÑ‚Ñ‹ Ñтыль, нідзе не паказваючы, што вы выкарыÑтоўваеце LiveJournal.com Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° журналу.
    + +
    Ðпытаньні
    +
    Уладальнікі платных рахункаў могуць Ñтвараць апытаньні Ñž Ñваіх журналах, Ñ– Ñž Ñуполках, у ÑÐºÑ–Ñ Ð¼Ð°ÑŽÑ†ÑŒ права запіÑу.
    + +
    Больш выÑваў карыÑтальніка
    +
    Уладальнікі платных рахункаў могуць мець да 15 выÑваў, у паразнаньні з 3, што маюць уладальнікі бÑÑплатных рахункаў.
    + +
    ÐÐ´Ñ€Ð°Ñ Ñл.пошты на LiveJournal.com
    +
    Уладальнікам платных рахункаў даецца Ð°Ð´Ñ€Ð°Ñ Ñл.пошты на LiveJournal.com ([[username]]@livejournal.com), Ñкі Ñны могуць уключыць ці выключыць.
    + +
    Пошукі ў паказальніку
    +
    Уладальнкі платных рахункаў могуць шукаць у паказальніку іншых карыÑтальнікаў.
    + +
    СубдамÑн LiveJournal.com
    +
    ЗамеÑÑ‚ журналу http://www.livejournal.com/users/[[username]]/, вы будзеце мець Ñго па адраÑе http://[[username]].livejournal.com/, што значна карацей Ñ– больш аÑабіÑта.
    + +
    СындыкацыÑ
    +
    Уладальнікі платных рахункаў маюць мажліваÑьць Ñтвараць Ñтужкі RSS, ÑÐºÑ–Ñ Ñ–Ñнуюць у Жывым Журнале Ñž ÑкаÑьці Ñындыкаваных рахункаў.
    + +
    ІнтÑрфÑÐ¹Ñ Ñ‚ÑкÑтавых паведамленьнÑÑž
    +
    Уладальнікі платных рахункаў валодаюць мажліваÑьцю Ñ‚ÑкÑтавых паведамленьнÑÑž, ÑÐºÑ–Ñ Ð´Ð°Ð·Ð²Ð¾Ð»Ñць ім атрымліваць Ñ‚ÑкÑÑ‚Ð°Ð²Ñ‹Ñ Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½ÑŒÐ½Ñ– на іхні Ñ‚Ñлефон ці пÑйджар праз улаÑны інтÑрфÑÐ¹Ñ Ð–Ñ‹Ð²Ð¾Ð³Ð° Журналу.
    + +
    Больш Ñлементаў у ÑьпіÑе "Што зрабіць"
    +
    Уладальнікі платных рахункаў могуць дадаць да 150 Ñлементаў да Ñвайго ÑьпіÑу "Што зрабіць", Ñ– могуць пазначаць розны ўзровень бÑÑьпекі Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð°Ð³Ð° зь Ñ–Ñ….
    + +
    Укладаньне Ñž іншы Ñайт
    +
    Уладальнікі платных рахункаў маюць доÑтуп да поўнага набору опцыÑÑž Ð´Ð»Ñ ÑƒÐºÐ»Ð°Ð´Ð°Ð½ÑŒÐ½Ñ Ñвайго журналу Ñž іхнюю хатнюю Ñтаронку, Ñк тлумачыцца на Ñтаронцы "Укладаньне Ñž іншы Ñайт".
    + +
    Перанакіроўваньне дамÑну
    +
    Уладальнікі платных рахункаў могуць наладзіць перанакіроўваньне дамÑну, каб іхні інтÑрнÑтавы дамÑн накіроўваў на іхні Жывы Журнал.
    + +
    ЯшчÑ...
    +
    Ð”Ð·ÐµÐ»Ñ Ð¿Ð¾ÑžÐ½Ð°Ð³Ð° ÑьпіÑу перавагаў платнага рахунку прачытайце Ð¯ÐºÑ–Ñ Ð¿ÐµÑ€Ð°Ð²Ð°Ð³Ñ– мае платны рахунак?
    + +. + +/paidaccounts/index.bml.features.header=Ð¯ÐºÑ–Ñ Ð¿ÐµÑ€Ð°Ð²Ð°Ð³Ñ– Ñ Ð· гÑтага атрымаю? + +/paidaccounts/index.bml.title=Пра Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– + +/paidaccounts/index.bml.whypay.argument<< +Ðе, вÑдома не. Мы згодныÑ, што плата за ÑÑрвіÑÑ‹ Ñž Ñеціве даволі раздражнÑе. +Таму амаль уÑе функцыі Жывога Журналу прадаÑтаўлÑюцца бÑÑплатна. +Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, калі вы задаволены ÑкаÑьцю паÑлуг, выкажыце Ñваю падтрымку Ñ– зрабіце Ñабе платны рахунак. +. + +/paidaccounts/index.bml.whypay.header=Ці павінен Ñ Ð¿Ð»Ð°Ñ†Ñ–Ñ†ÑŒ за Жывы Журнал? + +/paidaccounts/index.bml.whypay.no_ads=Трыманьне Ñайту каштуе грошай (за ÑÑрверы, разьмÑшчÑньне Ñ– шырыню каналу), Ñ– нам падаецца лепшым плаціць за гÑта, чым раздражнÑць Ð²Ð°Ñ Ð²Ñ‹Ñкокваючымі банÑрамі, ці Ñ€ÑклÑмным Ñпамам. + +/paidaccounts/index.bml.your_username=вашае_імÑ_карыÑтальніка + +/paidaccounts/usepaypal.bml.delivery.badformat=ÐÑÑлушны фармат даты. Павінна быць гггг-мм-дд ці гггг-мм-дд гг:Ñ…Ñ…. + +/paidaccounts/usepaypal.bml.delivery.past=Дата даÑтаўкі Ð½Ñ Ð¼Ð¾Ð¶Ð° быць у мінулым. Каб даÑлаць зараз, пакіньце поле пуÑтым. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Дата даÑтаўкі Ð½Ñ Ð¼Ð¾Ð¶Ð° быць больш за меÑÑц наперад. + +/pay/index.bml.deliverydate.details=Фармат: гггг-мм-дд гг:Ñ…Ñ… (Ñ‡Ð°Ñ Ð¿Ð° Грынвічу)
    (не ўвадзіце нічога Ð´Ð»Ñ Ñ‚Ñрміновай даÑтаўкі) + +/pay/index.bml.deliverydate.label=Дата даÑтаўкі: + +/pay/index.bml.gift.anonymous=Ðнанімны падарунак + +/poll/create.bml.button.editpoll=РÑдагаваць апытаньне + +/poll/create.bml.button.insert=УÑтавіць + +/poll/create.bml.button.postpoll=ЗапіÑаць апытаньне + +/poll/create.bml.button.preview=ПерадпраглÑд Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/poll/create.bml.button.seecode=Убачыць код + +/poll/create.bml.button.startover=РаÑпачаць + +/poll/create.bml.elements.limitreached=ДаÑÑгнуты ліміт Ñлементаў + +/poll/create.bml.error.accttype=Тып вашага рахунку не дазвалÑе вам карыÑтацца мажліваÑьцю ÑтварÑÐ½ÑŒÐ½Ñ Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½ÑÑž. + +/poll/create.bml.error.allitemsblank=УÑе пункты Ð½Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ быць пуÑтымі. + +/poll/create.bml.error.notext=ПатрÑбны Ñ‚ÑкÑÑ‚, Ñкі тлумачыць вашае пытаньне + +/poll/create.bml.error.parsing=Памылка аналізу апытаньнÑ: + +/poll/create.bml.error.pqmaxlengthinvalid=Ðтрыбут maxlength у Ñ‚ÑкÑтавых Ñ‚Ñгах на lj-pq павінен быць цÑлы лік ад [[min]] да [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Ðтрыбут size у Ñ‚ÑкÑтавых Ñ‚Ñгах на lj-pq павінен быць цÑлы лік ад [[min]] да [[max]]. + +/poll/create.bml.error.scalemaxlessmin=ЗначÑньне Ð¿Ð¾Ð»Ñ 'ад' павінна быць менш, чым значÑньне Ð¿Ð¾Ð»Ñ 'да'. + +/poll/create.bml.error.scalemininvalid=УзраÑтаньне значÑÐ½ÑŒÐ½Ñ Ð¿Ð°Ð²Ñ–Ð½Ð½Ð° быць Ð½Ñ Ð¼ÐµÐ½Ñˆ за [[min]]. + +/poll/create.bml.error.scaletoobig=Ліміт з [[max]] выбрараў (ад-да)/па > 20 + +/poll/create.bml.error.texttoolong=ТÑкÑÑ‚ вашай опцыі апынуўÑÑ Ð·Ð°Ð´Ð¾ÑžÐ³Ñ–Ð¼ Ñ– быў уÑечаны. + +/poll/create.bml.haserrors=У вашым апытаньні Ñ‘Ñьць адна ці некалькі памылак. Калі лаÑка, глÑдзіце Ñкрутак ніжÑй Ð´Ð·ÐµÐ»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑьцей. + +/poll/create.bml.insertquestion=УÑтаўце пытаньне Ñюды: + +/poll/create.bml.options=Опцыі: + +/poll/create.bml.options.limitreached=ДаÑÑгнуты ліміт опцыÑÑž + +/poll/create.bml.pollname=Ðазва апытаньнÑ: (не абавÑзкова) + +/poll/create.bml.preview.desc=ÐіжÑй знаходзіцца перадпраглÑд вашага апытаньнÑ. Рыхтык так ён будзе выглÑдаць паÑÑŒÐ»Ñ Ñ€Ð°Ð·ÑŒÐ¼ÑшчÑÐ½ÑŒÐ½Ñ Ñž вашым журнале. Ужывайце кнопкі ніжÑй, каб вÑрнуцца Ñ– зрабіць зьмены ці запіÑаць гÑтае апытаньне Ñž ваш журнал. + +/poll/create.bml.preview.options=Опцыі + +/poll/create.bml.properties=УлаÑьціваÑьці Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/poll/create.bml.question=Пытаньне: + +/poll/create.bml.questionnum=Пытаньне #[[num]] + +/poll/create.bml.questions=Пытаньні + +/poll/create.bml.title=Стваральнік Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/poll/create.bml.type.check=ÐÐ´Ð·Ð½Ð°ÐºÐ°Ð²Ñ‹Ñ Ð¿ÑƒÐ½ÐºÑ‚Ñ‹ + +/poll/create.bml.type.drop=Выпадны ÑÑŒÐ¿Ñ–Ñ + +/poll/create.bml.type.radio=ÐÐ±Ñ–Ñ€Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð¿ÑƒÐ½ÐºÑ‚Ñ‹ + +/poll/create.bml.type.scale=Шкала + +/poll/create.bml.type.text=ТÑкÑтавы Ð·Ð°Ð¿Ñ–Ñ + +/poll/create.bml.whoview=Хто можа праглÑдаць гÑтае апытаньне? + +/poll/create.bml.whovote=Хто можа ўдзельнічаць у гÑтым апытаньні? + +/poll/index.bml.discuss=Ðбмеркаваньне вынікаў + +/poll/index.bml.error.cantview=Выбачайце, вам не дазволена бачыць гÑтае апытаньне. + +/poll/index.bml.error.postdeleted=Ð—Ð°Ð¿Ñ–Ñ Ð±Ñ‹Ñž выдалены, таму цÑпер апытаньне не даÑтупнае. + +/poll/index.bml.filloutpoll=Запаўненьне Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/poll/index.bml.gotocreate=ГÑта Ð°Ð´Ñ€Ð°Ñ Ð´Ð»Ñ ÑžÐ´Ð·ÐµÐ»Ñƒ Ñž апытаньні. Ð’Ñ‹ наторкнуліÑÑ Ð½Ð° адраÑ, Ñкі нічога цÑпер Ð½Ñ Ñ€Ð¾Ð±Ñ–Ñ†ÑŒ. Калі вы жадаеце, вы можаце Ñтварыць новае апытаньне. + +/poll/index.bml.pollnotfound=Ðпытаньне Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð°. + +/poll/index.bml.submitted.head=ДзÑкуй + +/poll/index.bml.submitted.text=Ð’Ð°ÑˆÑ‹Ñ Ð°Ð´ÐºÐ°Ð·Ñ‹ на апытаньне былі пададзены. + +/poll/index.bml.submitted.title=Пададзена! + +/poll/index.bml.title=Ðпытаньне + +/poll/index.bml.viewresults=ПраглÑд вынікаў Ð°Ð¿Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/press/staff.bml.accountserv=ÐбÑлугоўваньне рахункаў + +/press/staff.bml.administration=ÐдмініÑÑ‚Ñ€Ð°Ñ†Ñ‹Ñ + +/press/staff.bml.administration.about=LiveJournal.com Ñтвораны Ñž 1999, Ñк праект БрÑда Фіцпатрыка, Ñ– цÑгам першых двух гадоў Ñвайго Ñ–ÑÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼Ð»Ñ–Ð²Ð°ÑžÑÑ Ð²Ñлікай групай добраахвотнікаў. Ды Ñ– цÑпер вÑÐ»Ñ–ÐºÐ°Ñ Ñ‡Ð°Ñтка LiveJournal.com падтрымліваецца групамі добраахвотнікаў, але мы маем Ñ– Ñталы пÑÑ€Ñанал, Ñкі наглÑдае за ÑžÑімі дзеÑньнÑмі: + +/press/staff.bml.avva.title=Сталы раÑпрацоўшчык + +/press/staff.bml.back2=Ðазад у зону прÑÑÑ‹ + +/press/staff.bml.bradfitz.quip=СфакуÑуйцеÑÑ Ð½Ð° Ñваім праекце, а Ð½Ñ Ñ‚Ð¾Ð»ÑŒÐºÑ– на грошах. + +/press/staff.bml.bradfitz.title=ПрÑзідÑнт / Галоўны раÑпрацоўшчык + +/press/staff.bml.contact=Калі вам Ñ‚Ñ€Ñба зьвÑзацца з намі, пішыце webmaster@livejournal.com. + +/press/staff.bml.custserv=ÐбÑлугоўваньне кліентаў / ДаÑьледваньне юзабіліці + +/press/staff.bml.david.title=ІнтÑрн + +/press/staff.bml.denisep.quip=ГÑта будзе Ñž Ð²Ð°Ñ Ñƒ наÑтупны чацьвер + +/press/staff.bml.denisep.title=Кантакты з добраахвотнікамі / СпÑцыÑліÑÑ‚ па юзабіліці + +/press/staff.bml.deveiant.title=Ðддалены раÑпрацоўшчык + +/press/staff.bml.developers=РаÑпрацоўшчыкі + +/press/staff.bml.evan.title=ЗаÑлужаны хакÑÑ€ + +/press/staff.bml.ferrell.title=ÐœÑнÑджÑÑ€ па абÑлугоўваньні кліентаў + +/press/staff.bml.jproulx.quip=ПераключыцеÑÑ Ð½Ð° ÑувÑзі з карыÑтальнікамі + +/press/staff.bml.jproulx.title=СупÑрвайзÑÑ€ Ñупольнага Ñайту / Кантакты з прÑÑай + +/press/staff.bml.kevin.title=Графічны Ñ– Ñеткавы дызайнер + +/press/staff.bml.lisa.title=СыÑÑ‚Ñмны адмініÑтратар + +/press/staff.bml.mahlon.quip=Eek eek! + +/press/staff.bml.mahlon.title=Code Monkey + +/press/staff.bml.nick.title=СыÑÑ‚Ñмны адмініÑтратар + +/press/staff.bml.ryanfitz.title=ÐŸÐ»Ð°Ñ‚Ð½Ñ‹Ñ ÑÑрвіÑÑ‹ + +/press/staff.bml.sandy.title=Рахункі Ñ– адмініÑÑ‚Ñ€Ð°Ñ†Ñ‹Ñ + +/press/staff.bml.smithy.title=Пачынаючы хакÑÑ€ + +/press/staff.bml.sysadmin=СыÑÑ‚ÑÐ¼Ð½Ñ‹Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтратары + +/press/staff.bml.title=Сталы пÑÑ€Ñанал + +/press/staff.bml.whitaker.quip=Што далей? + +/press/staff.bml.whitaker.title=Ðддалены раÑпрацоўшчык + +/pubkey.bml.error.notconfigured=ГÑÑ‚Ñ‹ Ñайт не Ñканфігураваны Ð´Ð»Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÑ– PGP. + +/pubkey.bml.error.nousername=Ðе пазначана Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/pubkey.bml.info.desc=ÐÑ Ð²ÐµÐ´Ð°ÐµÑ†Ðµ, што такое адкрыты ключ? Прачытайце болей пра PGP ды GPG. + +/pubkey.bml.info.head=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/pubkey.bml.info.upload=Жадаеце загрузіць ваш ключ? ЦіÑьніце Ñюды. + +/pubkey.bml.label=Ðдкрыты ключ Ð´Ð»Ñ [[user]]: + +/pubkey.bml.nokey=[[user]] ÑÑˆÑ‡Ñ Ð½Ðµ загрузіў(-ла) адкрыты ключ. + +/pubkey.bml.title=ПраглÑд адкрытага ключа + +/register.bml.ask.body=ÐаціÑьніце кнопку ніжÑй, каб даÑлаў пацьвÑрджальны ліÑÑ‚ Ñл.пошты на [[email]]. + +/register.bml.ask.button=ДаÑлаць + +/register.bml.ask.header=Пацьверджаньне адраÑу Ñл.пошты + +/register.bml.asterisk.comment=(Калі лаÑка, заўважце, што рахункі Ð¿Ð°Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ * ÑÑˆÑ‡Ñ Ð½Ðµ былі пацьверджаны) + +/register.bml.asterisk.name=* [[journal]] + +/register.bml.email.body<< +ГÑта пацьвÑрджальны ліÑÑ‚ Ñл.пошты па вашым запыце. +Каб завершыць пацьверджаньне вашага рахунку, калі лаÑка, наведайце наÑтупную бачыну: + + [[conflink]] + +Вам можа ÑпатрÑбіцца ÑкапіÑваць Ñ– ÑžÑтавіць гÑтую ÑпаÑылку Ñž вакно вашага праглÑдача. + +З павагай, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Пацьверджаньне адраÑу Ñл.пошты + +/register.bml.error.invalidcode=ÐÑÑлушны пацьвÑрджальны код. + +/register.bml.error.useralreadyvalidated=ÐÐ´Ñ€Ð°Ñ Ñл.пошты Ð´Ð»Ñ [[user]] ужо быў пацьверджаны. + +/register.bml.error.usernotfound=КарыÑтальнік Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹. + +/register.bml.new.body=ДзÑкуй! ЦÑпер ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты быў пацьверджаны. ÐдÑюль вы можаце быць зацікаўлены Ñž наÑтупным: + +/register.bml.new.editinfo=РÑдагаваньне інфармацыі -- Запоўніце ваш профіль карыÑтальніка Ñ– ÑžÑтанавіце Ñ€Ð¾Ð·Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´ÐºÑ–. + +/register.bml.new.header=ПоÑьпех + +/register.bml.new.login=Уваход -- Так вам Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ патрÑбы ўводзіць паўÑюль вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль. + +/register.bml.new.modify=Мадыфікаваньне журналу -- ЗьмÑніце выглÑд вашага журналу. + +/register.bml.new.update=Ð—Ð°Ð¿Ñ–Ñ Ñƒ журнал -- Пішыце Ñž ваш журнал. + +/register.bml.sent.body=ПацьвÑрджальны ліÑÑ‚ Ñл.пошты быў даÑланы на [[email]]. Каб завершыць пацьверджаньне, вам Ñ‚Ñ€Ñба націÑнуць на ÑпаÑылку Ñž гÑтым ліÑьце. + +/register.bml.sent.header=ПоÑьпех + +/register.bml.title=Пацьверджаньне адраÑу Ñл.пошты + +/register.bml.trans.body=Ваш новы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты быў пацьверджаны. + +/register.bml.trans.header=ПоÑьпех + +/rename/index.bml.does=Перайменаваньне рахунку зьмÑнÑе толькі Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. УÑÑ‘ аÑтатнÑе - платны ці Ñталы ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ, прывілеі карыÑтальніка, пÑÑ€ÑÐ°Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ–, ÑÑбры, Ñ– Ñ–Ð½ÑˆÑ‹Ñ Ð·ÑŒÐ²ÐµÑткі, зьвÑÐ·Ð°Ð½Ñ‹Ñ Ð· рахункам - заÑтануцца на Ñваім меÑцы, Ñ– будуць аÑацыÑÐ²Ð°Ð½Ñ‹Ñ Ð· новым імем карыÑтальніка. УÑе Ñ–ÑÐ½ÑƒÑŽÑ‡Ñ‹Ñ ÐºÐ°Ð¼Ñнтары Ñž іншых журналах Ñ– запіÑÑ‹ Ñž Ñуполках будуць паказваць новае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/rename/index.bml.faqurl=Ð”Ð·ÐµÐ»Ñ Ð¿Ð°Ð´Ñ€Ð°Ð±ÑзнаÑьцей пра працÑÑ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ, глÑдзіце Пытаньні Ñ– адказы па перайменаваньні. + +/rename/index.bml.fee=Ðплата Ð´Ð»Ñ Ð·ÑŒÐ¼ÐµÐ½Ñ‹ вашага Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Жывога Журналу Ñкладае [[fee]]. + +/rename/index.bml.heading.cost=Кошт + +/rename/index.bml.heading.details=ПадрабÑзнаÑьці + +/rename/index.bml.heading.how=Як набыць + +/rename/index.bml.option=Ð’Ñ‹ маеце магчымаÑьць, ці каб Ñтарое Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка накіроўвала на новае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, ці пазначыць Ñго выдаленым. Ð’Ñ‹ такÑама можаце выбраць, каб вы заÑталіÑÑ Ñž ÑьпіÑах ÑÑброў, ÑÐºÑ–Ñ Ð¼ÐµÐ»Ñ– Ð²Ð°Ñ Ñƒ Ñваім ÑьпіÑе раней, але з новым імем карыÑтальніка, ці каб вы былі выдалены Ñа ÑьпіÑаў ÑÑброў іншых карыÑтальнікаў. + +/rename/index.bml.options.buy=Ðабыць жÑтон + +/rename/index.bml.options.buy.desc=Ðабыцьцё жÑтону Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ. + +/rename/index.bml.options.use=Ужыць жÑтон + +/rename/index.bml.options.use.desc=Ужываньне жÑтону Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ. + +/rename/index.bml.redeem=Ð’Ñ‹ Ñпачатку павінны набыць перайменавальны жÑтон, Ñкі будзе даÑланы на ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, калі атрымаеце Ñго, выкарыÑтайце гÑÑ‚Ñ‹ жÑтон, каб зрабіць перайменаваньне. ÐŸÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð¶Ñтоны не прымаюцца назад, але Ñ–Ñ… можна перадаваць. ГÑта значыць, што вы можаце набыць перайменавальны жÑтон Ð´Ð»Ñ Ñ–Ð½ÑˆÐ°Ð³Ð° карыÑтальніка. + +/rename/index.bml.reserve=Вам Ð½Ñ Ñ‚Ñ€Ñба Ñтвараць рахунак з вашым новым імем карыÑтальніка, каб быць перайменаваным у Ñго. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, калі вы хвалюецеÑÑ, што нехта можа занÑць Ñ–Ð¼Ñ Ð¿ÐµÑ€Ð°Ð´ тым, Ñк вы набудзеце Ñ– выкарыÑтаеце ваш жÑтон, вы можаце Ñтварыць рахунак з новым імем карыÑтальніка. УпÑўніцеÑÑ, што вы ўжываеце той жа Ñамы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ñ– пароль, Ñкі вы маеце Ð½Ñ Ð±Ñгучым рахунку, Ð´Ð»Ñ Ð½Ð¾Ð²Ð°Ð³Ð° рахунку. + +/rename/index.bml.title=Служба Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/rename/index.bml.whatrename=Ð’Ñ‹ можаце перайменаваць толькі ваш пÑÑ€Ñанальны рахунак, а не Ñуполку, што вы трымаеце. + +/rename/use.bml.changes=Ðдбудуцца наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð·ÑŒÐ¼ÐµÐ½Ñ‹, калі перайменаваньне будзе Ñкончанае: + +/rename/use.bml.changes.move="[[newuser]]" будзе прыбраны Ñа шлÑху Ð´Ð»Ñ "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" будзе перайменаваны Ñž "[[newuser]]" + +/rename/use.bml.confirm=ПаÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾, Ñк вы націÑьніце 'Перайменаваць' унізе, Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ шлÑху вернуць назад зьмены. Як Ñродак пацьверджаньнÑ, увÑдзіце "[[confirmword]]" у поле ніжÑй. + +/rename/use.bml.confirm.click=Рпотым, націÑьніце 'Перайменаваць': + +/rename/use.bml.error.allocating=Памылка Ñž вызначÑньні імÑ, каб пермÑÑьціць прызначаны рахунак. + +/rename/use.bml.error.badpass=Паролі Ð´Ð»Ñ Ñтарага Ñ– новага імёнаў карыÑтальніка не Ñупадаюць. + +/rename/use.bml.error.differentusername=ГÑта Ð½Ñ Ñ‚Ð¾Ðµ Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, пад Ñкім вы зайшлі, калі загрузілі гÑтую форму. + +/rename/use.bml.error.login=Ðле Ñпачатку, вы павінны ўвайÑьці. + +/rename/use.bml.error.readit=Прачытайце абзац вышÑй. + +/rename/use.bml.error.reserved=Памылка Ð¿Ñ€Ñ‹Ð±Ñ–Ñ€Ð°Ð½ÑŒÐ½Ñ Ð·Ð°Ñ€Ñзерваванага Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/rename/use.bml.error.same=Яно тое ж Ñамае, што Ñ– вашае Ñтарое Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/rename/use.bml.error.token=ÐÑÑлушны жÑтон Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ. + +/rename/use.bml.error.type=Толькі Ð·Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– могуць быць перайменаваныÑ, а не рахункі Ñуполак. + +/rename/use.bml.error.unknown=ÐевÑÐ´Ð¾Ð¼Ð°Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° перайменаваньнÑ. + +/rename/use.bml.error.usedtoken=ГÑÑ‚Ñ‹ жÑтон ужо быў выкарыÑтаны. + +/rename/use.bml.error.username=ÐÑÑлушнае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/rename/use.bml.error.usernametaken=ГÑта Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ўжо ва ўжываньні. + +/rename/use.bml.heading.changes=Зьмены + +/rename/use.bml.heading.success=ПоÑьпех + +/rename/use.bml.heading.sure=Ð’Ñ‹ ўпÑўнены? + +/rename/use.bml.intent=ГÑÑ‚Ð°Ñ Ñтаронка Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ паÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾, Ñк вы прачытаеце ўводзіны Ñ– набудзеце перайменавальны жÑтон. + +/rename/use.bml.label.desired=Жаданае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/rename/use.bml.label.proceed=ПрацÑг ... + +/rename/use.bml.label.rename=Перайменаваньне + +/rename/use.bml.label.token=ЖÑтон Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ: + +/rename/use.bml.label.username=БÑгучае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/rename/use.bml.options=Опцыі перайменаваньнÑ: + +/rename/use.bml.options.delfriends=Выдаліць уÑÑ–Ñ… карыÑтальнікаў з вашага ÑьпіÑу ÑÑброў Ñ– выйÑьці з уÑÑ–Ñ… Ñуполак. + +/rename/use.bml.options.forward=Ðўтаматычна перанакіроўваць карыÑтальнікаў з [[oldname]] на новае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +/rename/use.bml.options.keepfriends=Захаваць уÑÑ–Ñ… карыÑтальнікаў Ñ– Ñуполкі Ñž вашым ÑьпіÑе ÑÑброў. + +/rename/use.bml.options.keepself=Захаваць уÑÑ–Ñ… у вашым ÑьпіÑе Чый ÑÑбра. + +/rename/use.bml.options.removeself=Выдаліць уÑÑ–Ñ… Ñа ÑьпіÑу Чый ÑÑбра. + +/rename/use.bml.options.unlink=Ðе пакідаць ÑувÑзі паміж [[oldname]] Ñ– новым журналам. + +/rename/use.bml.success.login=Вам Ñ‚Ñ€Ñба ізноў цÑпер увайÑьці. + +/rename/use.bml.success.moved="[[newuser]]" быў прыбраны Ñа шлÑху Ð´Ð»Ñ "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" быў перайменаваны Ñž "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка перайменаванае. + +/rename/use.bml.title=Ужываньне жÑтону Ð´Ð»Ñ Ð¿ÐµÑ€Ð°Ð¹Ð¼ÐµÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ + +/site/contract.bml.promise=Мы трымаем Ñлова, калі кажам што: + +/site/contract.bml.promise.account=Шануем ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð¶Ð½Ð°Ð³Ð° рахунку + +/site/contract.bml.promise.account.about=Ð¡Ñ‚Ð°Ð»Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– будуць шанавацца на працÑгу Ð¶Ñ‹Ñ†ÑŒÑ†Ñ Ñайту. ÐŸÐ»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– будуць заÑтавацца такімі, Ñк Ñны Ñ‘Ñьць, пакуль на Ñкончыцца Ñ‚Ñрмін Ñ–Ñ… Ñ–ÑнаваньнÑ, ці Ñны будуць узноўлены. Раньнім ўдзельнікам будзе дадзены доÑтуп да платных мажліваÑьцей, што былі бÑÑплатнымі на пачатку Ñ–ÑÐ½Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñайту. (рахункі будуць працаваць, за вынÑткам выпадкаў парушÑÐ½ÑŒÐ½Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»Ð°Ñž абÑлугоўваньнÑ) + +/site/contract.bml.promise.ads=ЗаÑтаемÑÑ Ð±ÐµÐ· Ñ€ÑклÑмы + +/site/contract.bml.promise.ads.about=ГÑта адна з нашых значных перавагаў, Ñ– мы абÑцаем, што на нашых Ñтаронках Ñ– Ñž нашых ÑÑрвіÑах ніколі Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ Ñ€ÑклÑмы. + +/site/contract.bml.promise.community=Працуем з Ñуполкамі Ð´Ð·ÐµÐ»Ñ Ñуполак + +/site/contract.bml.promise.community.about=Мы абÑцаем неназойліва інфармаваць Ð²Ð°Ñ Ð°Ð± зьменах. Ð’Ñ‹ абÑцаем працаваць, кіруючыÑÑ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñй атрыманай намі ад ÑупольнаÑьці Жывога Журналу, Ñ– памÑтаць пра інтарÑÑÑ‹ ÑупольнаÑьці Жывога Журналу. + +/site/contract.bml.promise.opensource=Падтрымка руху Вольнага праграмнага забÑÑÑŒÐ¿ÐµÑ‡Ð°Ð½ÑŒÐ½Ñ + +/site/contract.bml.promise.opensource.about=УвеÑÑŒ код, выкарыÑтаны Ð´Ð»Ñ ÑžÑталÑÐ²Ð°Ð½ÑŒÐ½Ñ Ð–Ñ‹Ð²Ð¾Ð³Ð° Журналу даÑтупны грамадзтву. Мы абÑцаем трымаць крыніцы адкрытамі, Ñ– так падтрымліваць ÑупольнаÑьць Вольнага праграмнага забÑÑьпечаньнÑ. + +/site/contract.bml.promise.spam=Ðіколі не дашлем незапатрабаваны ліÑÑ‚ Ñл.пошты + +/site/contract.bml.promise.spam.about=Мы ўпÑўнены, што Ñпаму Ð½Ñ Ð¼ÐµÑца Ñž ІнтÑрнÑце, Ñ– мы абÑцаем ніколі не даÑылаць вам ліÑÑ‚Ñ‹ Ñл.пошты бÑз вашай папÑÑ€ÑднÑй згоды ці патрабаваньнÑ. Мы абÑцаем ніколі не прадаваць ÑьпіÑÑ‹ адраÑоў Ñл.пошты нашых карыÑтальнікаў, ці нейкую аÑабіÑтую інфармацыю, Ñ– мы абÑцаем ніколі не займацца Ñпамам у інтарÑÑах Ñ‚Ñ€Ñціх груповак. + +/site/contract.bml.promise.uptime=Падтрымліваць надзейную працаздольнаÑьць Ñž межах Ñ‚Ñхнічных магчымаÑьцей + +/site/contract.bml.promise.uptime.about=Мы імкнемÑÑ, каб ÑžÑÑ‘ йшло добра Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð°Ð³Ð°, ÑÑˆÑ‡Ñ Ñ– таму, што Ñамі карыÑтаемÑÑ Ð³Ñтай ÑÑ‹ÑÑ‚Ñмай. Ðа жаль чаÑам узьнікаюць праблемы з ÑÑрверам. але мы робім уÑÑ‘ магчымае, каб пазьбегнуць Ñ–Ñ…. + +/site/contract.bml.promisetoyou=Мы Ñž Жывым Журнале робім уÑÑ‘, каб запÑўніць, што Ð½Ð°ÑˆÑ‹Ñ ÑÑрвіÑÑ‹ наÑтолькі зручныÑ, наколькі гÑта магчыма, таму мы Ñ– прыводзім ÑÑŒÐ¿Ñ–Ñ Ð°Ð±ÑцаньнÑÑž, Ñкіх будзем трымацца. + +/site/contract.bml.promisetoyou.header=Ðашае абÑцаньне вам + +/site/contract.bml.title=Грамадзкі кантракт + +/site/goat.bml.image.alt=Казёл ФрÑнк, Ñымбаль Жывога Журналу. + +/site/goat.bml.image.caption="Мееее," кажа ФрÑнк. + +/site/goat.bml.meet.body=ГÑта ФрÑнк. ФрÑнк - Ñымбаль Жывога Журналу. Ðн дапамагае нам з розным праграмаваньнем, калі Ñž Ð½Ð°Ñ Ð½Ðµ атрымліваецца, а чаÑам адказвае на пытаньні Ñ‚Ñхпадтрымкі. ФрÑнк Ñапраўды рознабаковы.... ён нават чаÑам працуе Ñž двары. Калі трава на газоне робіцца занадта выÑокай, мы кажам: "ФрÑнк! Ð§Ð°Ñ Ð°Ð±ÐµÐ´Ñƒ.... Ñхадзі, паеш травы!". ГÑта бÑÑÐ¿Ñ€Ð¾Ð¹Ð³Ñ€Ñ‹ÑˆÐ½Ð°Ñ ÑытуацыÑ. + +/site/goat.bml.meet.header=СуÑÑ‚Ñ€Ñць ФрÑнка + +/site/goat.bml.title=Казёл ФрÑнк + +/styles/create.bml.choosebase=Выберыце базавы Ñтыль Ð´Ð»Ñ Ð¿Ð°Ñ‡Ð°Ñ‚ÐºÑƒ Ñ– Ñ€ÑдагаваньнÑ: + +/styles/create.bml.createstyle.head=СтварÑньне Ñтылю + +/styles/create.bml.createstyle.text=ÐдÑюль вы можаце Ñтварыць новы пÑÑ€Ñанальны Ñтыль, што карыÑна, калі зьбіраецеÑÑ ÑžÐºÐ»Ð°Ñьці ваш журнал у вашую хатнюю Ñтаронку ці жадаеце Ñтварыць грамадзкі Ñтыль, каб уÑе маглі ўжываць Ñго, тады вы павінны папрацаваць Ñпачатку тут над ім, а Ð½Ñ Ñž ÑÑкцыі перапрацовак. Заўважце, што толькі карыÑтальнікі платных рахункаў могуць Ñтвараць Ñвае ўлаÑÐ½Ñ‹Ñ Ñтылі. + +/styles/create.bml.enterstyleid=Ці, увÑдзіце неÑÑ‹ÑÑ‚Ñмны грамадзкі ID# Ñтылю: + +/styles/create.bml.noneorother=(ÐÑ–Ñкі, ці адзін з ніжÑйшых:) + +/styles/create.bml.selecttype.head=Выбар тыпу Ñтылю + +/styles/create.bml.selecttype.text=Стыль уплывае толькі на адзін тып праглÑду. Калі вы жадаеце Ñтварыць набор адпаведных ÑтылÑÑž Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° журналу, вы муÑіце Ñтвараць ваш Ñтыль Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð°Ð³Ð° тыпу праглÑду. + +/styles/create.bml.submit=Стварыць Ñтыль + +/styles/create.bml.title=СтварÑньне Ñтылю + +/styles/create_do.bml.editstyle=РÑдагаваньне Ñтылю + +/styles/create_do.bml.error.accounttype=Тып вашага рахунку не дазвалÑе вам рабіць Ñтылі. + +/styles/create_do.bml.error.invalidview=Ð’Ñ‹ Ð½Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð»Ñ– дзейны тып Ñтылю. + +/styles/create_do.bml.error.styleexists=Ð’Ñ‹ ўжо маеце Ñтыль гÑтага тыпу з назвай [[des]]. Калі вы ÑžÑÑ‘ ж жадаеце Ñтварыць новы Ñтыль тыпу [[view]], тады мадыфікуйце ваш Ñтары Ñтыль [[view]], зьмÑніце Ñгоную назву, а потым вÑртайцеÑÑ Ñюлы, каб Ñтварыць новы Ñтыль гÑтага тыпу. + +/styles/create_do.bml.error.stylenotfound=Падобна на тое, што Ñтыль ([[baseid]]), зь Ñкога вы Ñпрабуеце ўтварыць новы Ñтыль не Ñ–Ñнуе. + +/styles/create_do.bml.error.stylenotpublic=Стыль ([[baseid]]), зь Ñкога вы Ñпрабуеце ўтварыць новы Ñтыль не зьÑўлÑецца грамадзкім, таму вы Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ ÑкапіÑваць Ñго. + +/styles/create_do.bml.success.head=ПоÑьпех + +/styles/create_do.bml.success.text=Ваш Ñтыль быў Ñтвораны Ñ– чаÑова названы [[des]]. Ð’Ñ‹ можаце пачаць Ñгонае Ñ€Ñдагаваньне, націÑнуўшы кнопку ніжÑй. + +/styles/create_do.bml.title=СтварÑньне Ñтылю + +/styles/index.bml.about<< +

    ГÑÑ‚Ñ‹ разьдзел Ñайту дазваоліць вам Ñтвараць, Ñ€Ñдагаваць Ñ– выдалÑць улаÑÐ½Ñ‹Ñ Ñтылі S1. ГÑта дазволіць вам у вÑлікай Ñтупені кантралÑваць выглÑд вашага рахунку, калі вы захочаце, каб ён выглÑдаў Ñк ваш Ñайт, ці проÑта адрозьніваўÑÑ Ð°Ð´ аÑтатніх.

    + +

    Ð’Ñ‹ такÑама можаце Ñтварыць укладаючыеÑÑ Ñтылі, замеÑÑ‚ ÑтварÑÐ½ÑŒÐ½Ñ Ñ†Ñлай Ñтаронкі, ÑÐºÑ–Ñ Ð±ÑƒÐ´ÑƒÑ†ÑŒ уключаць толькі Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ Ñ– дазволіць вам уклаÑьці ваш журнал у іншы Ñайт.

    + +

    Ð’Ñ‹ можаце прачытаць болей пра ÑÑ‹ÑÑ‚Ñму ÑтылÑÑž на Ñтаронцы дакумÑнтацыі пра Ñтылі Ñž зоне раÑпрацоўкі.

    + +

    Заўважце, што толькі ўладальнікі платных рахункаў могуць Ñтвараць Ñ– ўжываць улаÑÐ½Ñ‹Ñ Ñтылі. Уладальнікі бÑÑплатных рахункаў маюць выбар з ужо Ñтвораных ÑтылÑÑž Жывога Журналу, выбраць з Ñкіх можна на Ñтаронцы ÐœÐ°Ð´Ñ‹Ñ„Ñ–ÐºÐ°Ð²Ð°Ð½ÑŒÐ½Ñ Ð²Ð°ÑˆÐ°Ð³Ð° журналу.

    +. + +/styles/index.bml.about.header=СтварÑньне Ñ– ўжываньне ўлаÑных ÑтылÑÑž + +/styles/index.bml.nav.browse=ПраглÑдач Ñтылю + +/styles/index.bml.nav.browse.about=ПраглÑдач Ñтылю дазвалÑе вам праглÑдаць Ð³Ñ€Ð°Ð¼Ð°Ð´Ð·ÐºÑ–Ñ Ñтылі, ÑÑ‚Ð²Ð¾Ñ€Ð°Ð½Ñ‹Ñ Ñ–Ð½ÑˆÑ‹Ð¼Ñ– карыÑтальнікамі. + +/styles/index.bml.nav.create=СтварÑньне новага Ñтылю + +/styles/index.bml.nav.create.about=Стварыце новы Ñтыль з накіду, ці на аÑнове ўжо Ñ–Ñнуючага грамадзкага Ñтылю. + +/styles/index.bml.nav.edit=РÑдагаваньне ці выдаленьне Ñ–Ñнуючага Ñтылю + +/styles/index.bml.nav.edit.about=Ð’Ñ‹ можаце Ñ€Ñдагаваць толькі Ñтылі, Ñкімі “валодае” ваш рахунак. Каб наладзіць ÑÑ‹ÑÑ‚Ñму Ñтылю, вам Ñ‚Ñ€Ñба Ñпачатку Ñтварыць новы Ñтыль заÑнаваны на гÑтай ÑÑ‹ÑÑ‚Ñме Ñтылю. + +/styles/index.bml.nav.modify=Мадыфікаваньне вашага рахунку + +/styles/index.bml.nav.modify.about=ЗмÑніце Ñтыль па змоўчаньні вашага рахунку на адзін Ñа ÑтылÑÑž пададзены ÑÑ‹ÑÑ‚Ñмай + +/styles/index.bml.title=УлаÑÐ½Ñ‹Ñ Ñтылі + +/suggestions/index.bml.howto.text<< +
    +
    ПаглÑдзець аÑÐ½Ð¾ÑžÐ½Ñ‹Ñ Ð¿Ñ€Ð°Ð¿Ð°Ð½Ð¾Ð²Ñ‹
    +Спачатку прачытайце папÑÑ€ÑÐ´Ð½Ñ–Ñ Ð¿Ñ€Ð°Ð¿Ð°Ð½Ð¾Ð²Ñ‹, каб ўпÑўніцца, што падобнае не закраналаÑÑ Ñ€Ð°Ð½ÐµÐ¹. Калі ўжо закраналаÑÑ, вы можаце прачытаць каментары да прапановы. ЧаÑам выгÑдае, што прапанова праігнараванаÑ, але проÑта Ñна можа быць у раÑпрацоўцы. ЧаÑам ідÑÑ– адхілÑюцца з іншых прычын. +
    +
    Couldn't find your idea? ПадзÑліцеÑÑ Ð· намі!
    +Ð”Ð»Ñ ÑžÑÑ–Ñ… прапановаў павінен ужывацца шаблон. Запоўніце ÑžÑе палі шаблону Ñ– перад тым, Ñк адправіць, праверце, што ÑžÑÑ‘ Ñлушна Ñ– ÑžÑÑ‘ запоўнена. ГенÑратар прапаноў не дадае канца радка, таму вы можаце ўжываць Ñ‚Ñг <br>, каб зрабіць пераход на новы радок. Так вашую прапанову будзе лÑгчÑй чытаць. +
    +
    ЗапіÑаць Ñе!
    +Ð’Ñ‹ можаце дадаць Ñуполку да вашага ÑьпіÑу ÑÑброў тут. Калі прапанова запіÑана, людзі могуць абмÑркоўваць Ñе. Калі мы думаем, што ідÑÑ Ð²Ð°Ñ€Ñ‚Ð°Ñ, то мы дадаем Ñе да ÑьпіÑу праектаў раÑпрацоўшчыкаў, Ñ– будзем працаваць над ёй, Ñк толькі дазволіць чаÑ. ÐÑ ÑžÑе прапановы могуць быць уведзены імгненна, таму будзьце цÑрплівымі. +
    + +. + +/suggestions/index.bml.howto.title=Як зрабіць прапанову? + +/suggestions/index.bml.info.text<< +Ðдчуваеце, што можаце дапамагчы з раÑпрацоўкай вашых прапановаў? ПачувайцеÑÑ Ð²Ð¾Ð»ÑŒÐ½Ð°, каб 'назіраць' ці далучацца да наÑтупных Ñуполак: +
    +
    Форум раÑпрацоўшчыкаў Жывога Журналу -- размовы пра Ñ‚ÑÑ…Ð½Ñ–Ñ‡Ð½Ñ‹Ñ Ñ€Ñчы.
    +
    +
    БізнÑÑовы форум Жывога Журналу -- размовы пра Ð°Ð³ÑƒÐ»ÑŒÐ½Ñ‹Ñ Ð±Ñ–Ð·Ð½ÑÑÐ¾Ð²Ñ‹Ñ Ð¼Ð°Ð³Ñ‡Ñ‹Ð¼Ð°Ñьці Жывога Журналу Ñ– ўмё, што з гÑтым зьвÑзана.
    +
    +
    Форум дакумÑнтацыі карыÑтальнікаў Жывога Журналу -- абмеркаваньне Ñ– Ñ€Ñдагаваньне аÑноўных форм карыÑтальніцкай дакумÑнтацыі
    +
    +
    МаÑтацкі форум Жывога Журналу -- абмеркаваньне выÑвак, Ñ‚Ñм наÑтрою, Ñхем колераў Ñ– малюнкаў карыÑтальнікаў.
    +
    +
    +Калі лаÑка, памÑтайце, што людзі ÑÐºÑ–Ñ Ð¿Ñ€Ð°Ñ†ÑƒÑŽÑ†ÑŒ над Жывым Журналам, Ñ‚Ð°ÐºÑ–Ñ Ð¶ карыÑтальнікі Ñк Ñ– вы. Таму гÑта ÑžÑÑ‘ патрабуе чаÑу, Ñ– чым больш вы дапамагаеце, тым больш у Ð½Ð°Ñ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð»Ñ–Ð²Ð°ÐµÑ†Ñ†Ð°. + +. + +/suggestions/index.bml.info.title=Ð†Ð½ÑˆÐ°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +/suggestions/index.bml.rules<< +ÐÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ñ€Ñчы, ÑÐºÑ–Ñ Ñ‚Ñ€Ñба помніць: +
      +
    • Шмат што ўжо было прапанавана Ñ– абмеркавана раней, проÑта ÑÑˆÑ‡Ñ Ð½Ñ ÑžÐ²ÐµÐ´Ð·ÐµÐ½Ð° Ñž карыÑтаньне. УпÑўніцеÑÑ, што вы не прапаноўваеце тое ж Ñамае.
    • +
    • ФлÑйм не вітаецца. Кожны мае Ñваё меркаваньне на конт таго, Ñк павінен разьвівацца Жывы Журнал. Помніце, выказаць Ñваю думку - гÑта добра, а Ð³Ñ€ÑƒÐ±Ñ‹Ñ "наезды" на Ñ‡ÑƒÐ¶Ñ‹Ñ Ð¿Ñ€Ð°Ð¿Ð°Ð½Ð¾Ð²Ñ‹ - не.
    • +
    • Пішыце наÑтолькі поўна, Ñк магчыма. ДÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð°Ð¿Ð°Ð½Ð¾Ð²Ð° мае больш шанцаў быць прынÑтай. Вам не абавÑзкова ведаць праграмаваньне, проÑта падумайце, Ñк паўлывае Ð²Ð°ÑˆÐ°Ñ Ñ–Ð´ÑÑ, Ñ– ÑÐºÑ–Ñ Ð¿Ñ€Ð°Ð±Ð»ÐµÐ¼Ñ‹ могуць узьнікнуць.
    • +
    • Спачатку прачытайце Пытаньні Ñ– адказы, можа быць, што Ð²Ð°ÑˆÐ°Ñ Ñ–Ð´ÑÑ ÑžÐ¶Ð¾ Ñ–Ñнуе, ці можна выкарыÑтаць нешта з ужо Ñ–Ñнуючага
    • +
    • Калі у Ð²Ð°Ñ Ñ‘Ñьць пытаньне пра тое, Ñк працуе Жывы Журнал, ці вы не ўпÑўнены ці Ñ–Ñнуе што вам Ñ‚Ñ€Ñба, ці маеце праблему, не рабіце прапанову. Спытайце Ñпачатку Ñž Падтрымцы.
    • +
    + +. + +/suggestions/index.bml.title=Зона прапановаў + +/suggestions/index.bml.welcome.text=Прапановы карыÑтальнікаў - Ð²Ð°Ð¶Ð½Ð°Ñ Ñ‡Ð°Ñтка Жывога Журналу. Калі Ñž Ð²Ð°Ñ Ð½Ð° вашую думку Ñ‘Ñьць добра ідÑÑ, вы можаце кіравацца гÑтымі парадамі, каб прыцÑгнуць увагу людзей, што робÑць гÑÑ‚Ñ‹ Ñайт. + +/suggestions/index.bml.welcome.title=Запрашаем! + +/support/append_request.bml.back.requests=Ðазад да ÑьпіÑу адкрытых запытаў. + +/support/append_request.bml.back.support=Ðазад у зону падтрымкі. + +/support/append_request.bml.bounce.noemail=Ðе пазначаны Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð´Ð»Ñ Ð¿ÐµÑ€Ð°ÐºÑ–Ð´Ð²Ð°Ð½ÑŒÐ½Ñ. + +/support/append_request.bml.bounce.notauth=Ð’Ñ‹ не аўтарызаваныÑ, каб перакінуць гÑÑ‚Ñ‹ запыт. + +/support/append_request.bml.bounce.toomany=Ð’Ñ‹ можаце даÑылаць на Ð½Ñ Ð±Ð¾Ð»ÑŒÑˆ, чым 5 адраÑоў Ñл.пошты. Ð’Ñ‹ пазначылі больш, чым 5. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=ГÑÑ‚Ñ‹ запыт з таго чаÑу ўжо быў зачынены. + +/support/append_request.bml.closed.title=Зачынены + +/support/append_request.bml.internal.approve=Каб зацьвердзіць адказ, вы павінны выбраць "Унутраны камÑнтар / ДзеÑньне" Ñ– па магчымаÑьці раÑтлумачыць, чаму вы зацьвÑрджаеце Ñго. + +/support/append_request.bml.internal.changecat=Каб зьмÑніць катÑгорыю запыту, вы павінны выбраць "Унутраны камÑнтар / ДзеÑньне" Ñ– па магчымаÑьці раÑтлумачыць, чаму вы зьмÑнÑеце Ñе. + +/support/append_request.bml.internal.changesum=Каб зьмÑніць кароткі зьмеÑÑ‚ запыту, вы павінны выбраць "Унутраны камÑнтар / ДзеÑньне" Ñ– ўвеÑьці новы кароткі зьмеÑÑ‚. + +/support/append_request.bml.internal.touch=Каб зьмÑніць ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ð¿Ñ‹Ñ‚Ñƒ, вы павінны выбраць "Унутраны камÑнтар / ДзеÑньне" Ñ– раÑтлумачыць, чаму вы зьмÑнÑеце Ñго. + +/support/append_request.bml.invalid.blank=Вашае паведамленьне было пуÑтым. Калі лаÑка, напішыце хоць нешта Ñž полі паведамленьнÑ. + +/support/append_request.bml.invalid.noanswer=ÐÑÑлушны заÑлонены адказ Ð´Ð»Ñ Ð·Ð°Ñ†ÑŒÐ²ÑрджÑньнÑ. + +/support/append_request.bml.invalid.nocat=Падобна, што гÑÑ‚Ð°Ñ ÐºÐ°Ñ‚ÑÐ³Ð¾Ñ€Ñ‹Ñ Ð½Ðµ Ñ–Ñнуе. + +/support/append_request.bml.invalid.noid=ГÑтае дзеÑньне патрабуе нумару ID запыту патрымкі. + +/support/append_request.bml.invalid.type=ÐÑÑлушны тып адказу. + +/support/append_request.bml.logged.text=Вашае дзеÑньне/камÑнтар/адказ было запіÑана. ДзÑкуй. + +/support/append_request.bml.logged.title=ПоÑьпех + +/support/append_request.bml.login.required=Ð’Ñ‹ павінны ўвайÑьці, каб дапамагаць людзÑм. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Дадаць камÑнтар/адказ + +/support/append_request.bml.unknown.request=ÐевÑдомы запыт падтрымкі. + +/support/encodings.bml.edit.header=Я не магу Ñ€Ñдагаваць Ñвае запіÑÑ‹ праз вÑб-інтÑрфÑйÑ! + +/support/encodings.bml.edit.text<< +Кароткі адказ:
    (калі вы пішыце кірыліцай): Ідзіце на вашую Ñтаронку +аÑабіÑÑ‚Ñ‹Ñ… уÑтановак. Знайдзіце опцыю ўнізе Ñтаронкі +ÑÐºÐ°Ñ Ð·Ð°Ð²ÐµÑ†Ñ†Ð° Ðўта-ÐºÐ°Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ñ‹Ñ Ñтарых запіÑаў з:. Выберыце +"Cyrillic (Windows)" з выпадаючага мÑню Ñ– захавайце зьмены. ЦÑпер Ð²Ð°ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ можна Ñ€Ñдагаваць. p?> + +Доўгі адказ: Каб дазволіць вам Ñ€Ñдагаваць нÑ-ЮнікодаўÑкі запіÑ, Жывы Журнал павінен ведаць +у Ñкім кадаваньні быў зроблены запіÑ. Ð”Ð»Ñ Ð±ÐµÐ»Ð°Ñ€ÑƒÑкіх карыÑтальнікаў гÑта звычайна "Cyrillic (Windows)". +КарыÑтальнікі, ÑÐºÑ–Ñ Ð¿Ñ–ÑˆÑƒÑ†ÑŒ на іншых мовах павінны Ñамі абраць кадаваньне; калі Ñго нÑма Ñž ÑьпіÑе, +кантактуйце Падтрымку Ñ– патлумачце праблему. p?> + + +. + +/support/encodings.bml.editcl.header=Я не магу Ñ€Ñдагаваць Ñвае запіÑÑ‹ праз праграму-кліент! + +/support/encodings.bml.editcl.text<< + +. + +/support/encodings.bml.groups.header=Я не магу Ñ€Ñдагаваць ÑÑŒÐ¿Ñ–Ñ Ð¼Ð°Ñ–Ñ… ÑÑброў праз праграму-кліента! + +/support/encodings.bml.groups.text<< +Ñтаронцы Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ð³Ñ€ÑƒÐ¿, потым карыÑтацца праграмай-кліентам. p?> +. + +/support/encodings.bml.overview.header=Ð”Ð·ÐµÐ»Ñ Ñ‡Ð°Ð³Ð¾ гÑта ÑžÑÑ‘? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=УÑÑ‘ ÑÑˆÑ‡Ñ Ñž замÑшаньні? + +/support/encodings.bml.still.text=Падтрымцы. p?> + +/support/encodings.bml.title=Кадаваньні + +/support/faqbrowse.bml.backfaq=Ð’Ñрнуцца да пытаньнÑÑž Ñ– адказаў. + +/support/faqbrowse.bml.backfaqcat=Ðазад у бацькоўÑкую катÑгорыю ПытаньнÑÑž Ñ– адказаў. + +/support/faqbrowse.bml.backsupport=Ð’Ñрнуцца да Ñтаронкі дапамогі. + +/support/faqbrowse.bml.edit.faq=РÑдагаваць гÑÑ‚Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ðµ Ñ– адказ + +/support/faqbrowse.bml.error.nofaq=ÐÐ·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы Ð½Ñ Ð¹Ñнуюць. + +/support/faqbrowse.bml.lastupdated=ÐпошнÑе абнаўленьне: + +/support/faqbrowse.bml.title_cat=Пытаньні Ñ– адказы - [[catname]] + +/support/faqbrowse.bml.title_num=Пытаньні Ñ– адказы. Пытаньне #[[num]] + +/support/help.bml.interim<< + + + + +Пачатак ва уÑпамінах HelpScreening аÑабліва добрае меÑца Ð´Ð»Ñ Ð·Ð´Ð°Ð±Ñ‹Ñ‡Ñ‹ інфармацыі Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… добраахвотнікаў. p?> + + + +
    • Быць прафеÑійным Ñ– ветлівым.
    • +
    • Ðе кантактаваць з людзьмі, што робÑць запыт, па-за межамі Дошкі падтрымкі, каб абмерхаваць іхні запыт ці даць ім нейкую інфармацыю.
    • +
    • Захоўваць прыватнаÑьць інфармацыі Ñž Запытах падтрымкі.
    • +
    • Ðе капіÑваць адказы іншых людзей.
    + + + +, чаму адказы не былі зацьверджаны, але пачакайце пакуль у запыце зьÑвіцца зацьверджаны адказ. p?> + + + + + +Дошцы падтрымкі. p?> + +. + +/support/see_overrides.bml.error.noprivs=Толькі карыÑтальнікі з правамі supportviewscreened ці supporthelp могуць праглÑдаць перапрацоўкі іншых карыÑтальнікаў. + +/support/see_overrides.bml.error.nos1=ГÑÑ‚Ñ‹ карыÑтальнік не ўжывае S1. + +/support/see_overrides.bml.header=Перапрацоўкі Ð´Ð»Ñ : + +/support/see_overrides.bml.nooverrides=Перапрацоўкі Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹ Ð´Ð»Ñ . + +/support/see_overrides.bml.title=Перапрацоўкі карыÑтальніка + +/syn/index.bml.account=Рахунак: + +/syn/index.bml.add=Дадаць Ñтужку + +/syn/index.bml.add.byurl.text=Дадайце Ñтужку да вашага ÑьпіÑу ÑÑброў, увёўшы URL Ñтужкі ніжÑй. + +/syn/index.bml.add.byurl.title=Дадаваньне Ñтужкі па URL + +/syn/index.bml.add.pop.text=Далей ідуць Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¿Ð°Ð¿ÑƒÐ»ÑÑ€Ð½Ñ‹Ñ Ñтужкі, ÑÐºÑ–Ñ Ð²Ñ‹ не праглÑдаеце: + +/syn/index.bml.add.pop.title=Дадаваньне папулÑрных Ñтужак + +/syn/index.bml.add.selected=Дадаць выбранае + +/syn/index.bml.back=Ðазад + +/syn/index.bml.create=СтварÑньне Ñтужкі + +/syn/index.bml.create.name=URL, што вы ўвÑлі, не Ñындыкавана на гÑтым Ñайце. Калі лаÑка, увÑдзіце назву рахунку, каб Ñындыкаваць гÑтую Ñтужку. + +/syn/index.bml.error.nocreate=URL, што вы ўвÑлі, не Ñындыкавана на гÑтым Ñайце. Тып вашага рахунку не дазвалÑе Ñтвараць Ð½Ð¾Ð²Ñ‹Ñ ÑÑ‹Ð½Ð´Ñ‹ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ñтужкі. + +/syn/index.bml.error.unknown=ÐевÑÐ´Ð¾Ð¼Ð°Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° + +/syn/index.bml.feed.url=URL Ñтужкі: + +/syn/index.bml.invalid.accountname=ÐÑÑлушнае Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/syn/index.bml.invalid.cantadd=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ дадаваць Ñтужкі RSS з гÑтага Ñайту. + +/syn/index.bml.invalid.http.text=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° пры атрыманьні гÑтага URL. Магчыма ÑÑрвер не працуе ці Ñгоны зьмеÑÑ‚ цÑпер недаÑтупны. Калі лаÑка, удакладніце ваш URL Ñ– паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/syn/index.bml.invalid.http.title=Памылка Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ð½ÑŒÐ½Ñ Ð·ÑŒÐ¼ÐµÑту + +/syn/index.bml.invalid.inuse.text=ГÑтае Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ ўжо занÑтае. + +/syn/index.bml.invalid.inuse.title=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ва ўжываньні + +/syn/index.bml.invalid.needname.text=Каб дадаць Ñындыкаваны рахунак, Ñкі не Ñ–Ñнуе, вÑрніцеÑÑ Ñ– дайце Ñму Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/syn/index.bml.invalid.needname.title=Патрабуецца Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +/syn/index.bml.invalid.needurl=Ð’Ñ‹ павінны ўвеÑьці Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñындыкаванага рахунку ці URL, каб дадаць новую Ñтужку. + +/syn/index.bml.invalid.notexist=Ðе Ñ–Ñнуе Ñындыкаванага рахунку з такім імем карыÑтальніка. + +/syn/index.bml.invalid.notrss.text=Падобна, што пададзены URL не ўтрымлівае зьвеÑтак адфарматаваных у XML. + +/syn/index.bml.invalid.notrss.title=ЗьвеÑткі не Ð°Ð´Ñ„Ð°Ñ€Ð¼Ð°Ñ‚Ð°Ð²Ð°Ð½Ñ‹Ñ Ñž XML + +/syn/index.bml.invalid.port=ÐеÑтандартны нумар парта не дазволены + +/syn/index.bml.invalid.reserved=ГÑтае Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ зарÑзерваванае. Калі лаÑка, выберыце іншае Ñ–Ð¼Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ. + +/syn/index.bml.invalid.submission=ÐÑÑÐ»ÑƒÑˆÐ½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° падачы + +/syn/index.bml.invalid.url=URL, што вы ўвÑлі, нÑÑлушны. Калі лаÑка, праверце ўведзены URL Ñ– паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/syn/index.bml.loginrequired.text=Каб кіраваць вашымі Ñындыкаванымі рахункамі, Ñпачатку ўвайдзіце. + +/syn/index.bml.loginrequired.title=ПатрÑбна ўвайÑьці + +/syn/index.bml.promo.text=Калі вы хочаце пабачыць ÑÑŒÐ¿Ñ–Ñ Ñындыкаваных Ñтужак, што карыÑтальнікі Ñ€ÑклÑмавалі Ñž мінулым, вы можаце наведаць , дзе карыÑтальнікі паведамлÑюць пра Ñтужкі, што Ñны Ñтвараюць Ñ– праглÑдаюць. + +/syn/index.bml.remove=Выдаліць выбранае + +/syn/index.bml.table.account=Рахунак + +/syn/index.bml.table.feed=Стужка + +/syn/index.bml.table.watchers=Гледачы + +/syn/index.bml.title=Ð¡Ñ‹Ð½Ð´Ñ‹ÐºÐ°Ñ†Ñ‹Ñ + +/syn/index.bml.user.nomatch=Ð—Ð°Ð¿Ñ–Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка не адпавÑдае карыÑтальніку, Ñкі запоўніў форму. + +/syn/index.bml.using.text=Тут вы можаце дадаваць ÑÑ‹Ð½Ð´Ñ‹ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ñтужкі (RSS) з іншых Ñайтаў да вашага ÑьпіÑу ÑÑброў, пазьбÑгаючы патрÑбы праглÑдаць тузін Ñайтаў штодзень. + +/syn/index.bml.using.title=Ужываньне [[sitename]] Ð´Ð»Ñ Ñындыкацыі + +/syn/list.bml.error.nofeeds=Памылка: ÐÑ–Ð²Ð¾Ð´Ð½Ð°Ñ ÑÑ‹Ð½Ð´Ñ‹ÐºÐ°Ð²Ð°Ð½Ð°Ñ Ñтужка не абнаўлÑлаÑÑ Ñ†Ñгам апошніх 24 гадзін. + +/syn/list.bml.feeddesc=ÐпіÑаньне Ñтужкі + +/syn/list.bml.feedurl=URL Ñтужкі + +/syn/list.bml.numreaders=КолькаÑьць чытачоў + +/syn/list.bml.title=Ð¡Ñ‹Ð½Ð´Ñ‹ÐºÐ°Ð²Ð°Ð½Ñ‹Ñ Ñтужкі + +/syn/list.bml.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +/syn/list.bml.xml_icon.alt=[ПраглÑд неапрацаванай Ñтужкі] + +/talkmulti.bml.deleted.body=КамÑнтары былі выдалены. Ð’Ñ‹ можаце праглÑдзець заÑтаўшуюÑÑ Ð³Ð°Ð»Ñ–Ð½Ñƒ тут. + +/talkmulti.bml.deleted.title=КамÑнтары выдалены + +/talkmulti.bml.error.comms_deleted=Ðдзін з камÑнтараў быў выдалены паÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾, Ñк вы выбралі Ñго. З прычын бÑÑьпекі вÑрніцеÑÑ Ð½Ð°Ð·Ð°Ð´ Ñ– паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/talkmulti.bml.error.inconsistent_data=Ð£Ð²ÐµÐ´Ð·ÐµÐ½Ñ‹Ñ Ð´Ð°Ð´Ð·ÐµÐ½Ñ‹Ñ ÑупÑÑ€ÑчлівыÑ. + +/talkmulti.bml.error.invalid=ÐÑÑлушна вызначаны парамÑтры. + +/talkmulti.bml.error.invalid_mode=Ð’Ñ‹ Ð½Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð»Ñ– дзеÑньне. Ð’ÑрніцеÑÑ Ñ– выберыце, ці заÑланіць, ці адÑланіць, ці выдаліць камÑнтары. + +/talkmulti.bml.error.login=Ð’Ñ‹ не ўвайшлі + +/talkmulti.bml.error.none_selected=Ð’Ñ‹ не выбралі камÑнтары. + +/talkmulti.bml.error.privs.delete=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб выдаліць гÑÑ‚Ñ‹Ñ ÐºÐ°Ð¼Ñнтары. + +/talkmulti.bml.error.privs.screen=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб заÑланіць гÑÑ‚Ñ‹Ñ ÐºÐ°Ð¼Ñнтары. + +/talkmulti.bml.error.privs.unscreen=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб адÑланіць гÑÑ‚Ñ‹Ñ ÐºÐ°Ð¼Ñнтары. + +/talkmulti.bml.screened.body=КамÑнтары былі заÑлонены. Ð’Ñ‹ можаце паглÑдзець на Ñ–Ñ… тут. + +/talkmulti.bml.screened.title=КамÑнтары заÑлонены + +/talkmulti.bml.title.delete=Выдаліць некалькі камÑнтараў + +/talkmulti.bml.title.screen=ЗаÑланіць некалькі камÑнтараў + +/talkmulti.bml.title.unscreen=ÐдÑланіць некалькі камÑнтараў + +/talkmulti.bml.unscreened.body=КамÑнтары былі адÑлонены. Ð’Ñ‹ можаце паглÑдзець на Ñ–Ñ… тут. + +/talkmulti.bml.unscreened.title=КамÑнтары адÑлонены + +/talkpost.bml.allowedhtml=Дазволены HTML + +/talkpost.bml.error.cannotreplynopost=Ð’Ñ‹ не можаце адказаць на неіÑнуючы Ð·Ð°Ð¿Ñ–Ñ + +/talkpost.bml.error.nocommentsjournal=КарыÑтальнік забараніў камÑнтары Ñž Ñваім журнале. + +/talkpost.bml.error.nocommentspost=КарыÑтальнік забараніў камÑнтары Ð´Ð»Ñ Ð³Ñтага запіÑу. + +/talkpost.bml.error.noreplypost=Ð—Ð°Ð¿Ñ–Ñ Ñƒ адказ Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹ (выдалены?) + +/talkpost.bml.error.noreply_deleted=КамÑнтар быў выдалены. Ð’Ñ‹ не можаце адказаць на Ñго. + +/talkpost.bml.error.noreply_screened=ГÑÑ‚Ñ‹ камÑнтар заÑлонены Ñ– вы не можаце Ñго ўбачыць ці адказаць на Ñго. + +/talkpost.bml.label.picturetouse=Ужыць выÑву: + +/talkpost.bml.loganonip=Увага! ГÑÑ‚Ñ‹ карыÑтальнік актывізаваў опцыю, ÑÐºÐ°Ñ Ð·Ð°Ð¿Ñ–Ñвае IP адраÑÑ‹ ÑžÑÑ–Ñ…, хто піша адказы ананімна. + +/talkpost.bml.loginq=УвайÑьці? + +/talkpost.bml.logyourip=Увага! ГÑÑ‚Ñ‹ карыÑтальнік актывізаваў опцыю, ÑÐºÐ°Ñ Ð·Ð°Ð¿Ñ–Ñвае IP адраÑÑ‹ ÑžÑÑ–Ñ…, хто піша адказы. + +/talkpost.bml.nosubjecthtml=У Ñ‚Ñме HTML не дазволены + +/talkpost.bml.opt.anonymous=Ðнанімна + +/talkpost.bml.opt.defpic=(па змоўчаньні) + +/talkpost.bml.opt.friendsonly=- гÑÑ‚Ñ‹ карыÑтальнік забараніў піÑаць адказы ананімам Ñ– не-ÑÑбрам. Ð’Ñ‹ можаце тут піÑаць, калі [[username]] пазначыў Ð²Ð°Ñ Ñк ÑÑбра. + +/talkpost.bml.opt.from=Ðд: + +/talkpost.bml.opt.ljuser=КарыÑтальнік Жывога Журналу: + +/talkpost.bml.opt.loggedin=КарыÑтальнік па ўваходзе: [[username]] + +/talkpost.bml.opt.message=Паведамленьне: + +/talkpost.bml.opt.noanonpost=- гÑÑ‚Ñ‹ карыÑтальнік забараніў Ð°Ð½Ð°Ð½Ñ–Ð¼Ð½Ñ‹Ñ Ð°Ð´ÐºÐ°Ð·Ñ‹. + +/talkpost.bml.opt.noautoformat=Ðе аўта-фарматаваць: + +/talkpost.bml.opt.noimage=Без малюнку + +/talkpost.bml.opt.preview=ПерадпраглÑд + +/talkpost.bml.opt.spellcheck=Праверка арфаграфіі перад запіÑам + +/talkpost.bml.opt.subject=ТÑма: + +/talkpost.bml.opt.submit=ÐапіÑаць камÑнтар + +/talkpost.bml.opt.willscreen=(будзе заÑлонены) + +/talkpost.bml.opt.willscreenfriend=(будзе заÑлонены, калі вы Ð½Ñ ÑÑбра) + +/talkpost.bml.paraformat=Ðбзацы будуць фарматавацца аўтаматычна. + +/talkpost.bml.postresponse=ÐапіÑаць камÑнтар у адказ: + +/talkpost.bml.title=ÐапіÑаць камÑнтар + +/talkpost.bml.usermismatch<< +Ð’Ñ‹ ўвÑлі Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, але не адзначылі опцыю 'карыÑтальнік Жывога Журналу'. +Калі лаÑка, ці ачыÑьціце Ñ‚ÑкÑтавае поле, ці выберыце Ñлушны Ñ€Ñжым уводу Ñ– паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. +. + +/talkpost.bml.warnscreened=Заўвага: ГÑÑ‚Ñ‹ камÑнтар заÑлонены. Ðдказ Ð½Ñ Ñго аўтаматычна адÑлоніць Ñго Ñ– зробіць бачным. + +/talkpost_do.bml.error.badpassword=ÐÑÑлушны пароль Ð´Ð»Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ð°Ð³Ð° Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. Ð’Ñ‹ можаце ўзнавіць пароль тут, калі забылі Ñго. + +/talkpost_do.bml.error.badusername=Вызначанае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Жывога Журналу не Ñ–Ñнуе. Ð’Ñ‹ можаце ўзнавіць вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка тут, калі забылі Ñго, ці можаце зрабіць Ð·Ð°Ð¿Ñ–Ñ Ñк "Ðнанім". + +/talkpost_do.bml.error.banned=Вам не дазволена піÑаць у журнал гÑтага карыÑтальніка. + +/talkpost_do.bml.error.blankmessage=Вашае паведамленьне пуÑтое. Ðапішіце нешта Ñž полі паведамленьнÑ. + +/talkpost_do.bml.error.confused_identity=Ð’Ñ‹ ўвÑлі Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка, але выбралі рабіць Ð·Ð°Ð¿Ñ–Ñ Ð°Ð½Ð°Ð½Ñ–Ð¼Ð½Ð°, ці ўжо зайшоўшым карыÑтальнікам. Ð’ÑрніцеÑÑ Ñ– вырашыце, што вы хочаце рабіць. + +/talkpost_do.bml.error.deleted=Ваш журнал быў выдалены. Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ рабіць запіÑÑ‹. + +/talkpost_do.bml.error.friendsonly=Толькі ÑÑбры [[user]] могуць рабіць запіÑÑ‹ Ñž гÑÑ‚Ñ‹ журнал. + +/talkpost_do.bml.error.lostcookie=Файл-кукі вашага ўваходу зьнік? + +/talkpost_do.bml.error.manybytes=Выбачайце, але ваш камÑнтар [[current]] перавышае макÑымальную даўжыню [[limit]] байт. Ð’ÑрніцеÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкараціце Ñго Ñ– паÑпрабуйце запіÑаць ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/talkpost_do.bml.error.manychars=Выбачайце, але ваш камÑнтар з [[current]] ÑымбалÑÑž перавышае макÑымальна магчымую даўжыню [[limit]]. Ð’ÑрніцеÑÑ Ð½Ð°Ð·Ð°Ð´, Ñкараціце Ñго, Ñ– паÑпрабуйце запіÑаць ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/talkpost_do.bml.error.mustlogin=Ð’Ñ‹ павінны ўвайÑьці ці ўжыць Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль каб адказаць на гÑÑ‚Ñ‹ абаронены запіÑ. + +/talkpost_do.bml.error.noanon=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ піÑаць ананімна Ñž журнале гÑтага чалавека. + +/talkpost_do.bml.error.noauth=Ð’Ñ‹ не аўтарызаваны, каб адказаць на гÑÑ‚Ñ‹ абаронены запіÑ. + +/talkpost_do.bml.error.nocomments=КарыÑтальнік забараніў камÑнтары гÑтага журнальнага запіÑу. + +/talkpost_do.bml.error.noparent=Ðемагчыма адказаць на неіÑнуючы камÑнтар. + +/talkpost_do.bml.error.notafriend=Выбачайце, карыÑтальнік [[user]] Ð½Ñ Ð¼Ð°Ðµ Ð²Ð°Ñ Ñƒ ÑьпіÑе ÑÑброў, а ён выбраў опцыю "толькі ÑÑбры" Ð´Ð»Ñ Ñ‚Ñ‹Ñ…, хто можа адказваць на Ñго Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹. + +/talkpost_do.bml.error.nousername=Ð’Ñ‹ Ð½Ñ ÑžÐ²Ñлі вашае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Жывога Журналу. Ð’Ñ‹ можаце зрабіць Ð·Ð°Ð¿Ñ–Ñ Ñк "Ðнанім", калі вы Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ рахунку Жывога Журналу. + +/talkpost_do.bml.error.noverify=Выбачайце, вам не дазволена рабіць камÑнтары Ñž журналах іншых людзей пакуль ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ пацьверджаны. Калі вы згубілі пацьвÑрджальны ліÑÑ‚, вы можаце атрымаць Ñго ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/talkpost_do.bml.error.postshared=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ рабіць Ð·Ð°Ð¿Ñ–Ñ Ñк з ÑумеÑнага рахунку ці Ñуполкі. СумеÑÐ½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– Ñ€ÑпрÑзентуюць групы людзей, а не аÑобнага чалавека. + +/talkpost_do.bml.error.screened=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб адказаць на гÑÑ‚Ñ‹ заÑлонены камÑнтар. + +/talkpost_do.bml.error.suspended=Ваш журнал быў прыпынены. Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ рабіць запіÑÑ‹. + +/talkpost_do.bml.error.testacct=ТÑÑÑ‚Ð°Ð²Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– могуць ужывацца толькі Ñž журналах Ñ‚ÑÑтавых рахункаў. + +/talkpost_do.bml.opt.preview=ПерадпраглÑд + +/talkpost_do.bml.preview=Так будзе выглÑдаць ваш камÑнтар паÑÑŒÐ»Ñ Ð·Ð°Ð¿Ñ–Ñу. Ужываючы форму ніжÑй, вы можаце Ñ€Ñдагаваць далей, ці можаце запіÑаць Ñго, Ñк ён Ñ‘Ñьць. + +/talkpost_do.bml.preview.subject=ТÑма: + +/talkpost_do.bml.preview.submit=ЗапіÑаць + +/talkpost_do.bml.preview.title=ПерадпраглÑд + +/talkpost_do.bml.success.loggedin=ЦÑпер вы ўвайшлі. + +/talkpost_do.bml.success.message=Ваш камÑнтар быў дададзены. Ð’Ñ‹ можаце праглÑдзець Ñго тут. + +/talkpost_do.bml.success.screened.comm=Ваш камÑнтар быў дададзены. КіруючыÑÑ ÑžÑтаноўкамі Ñуполкі, ён быў пазначаны Ñк заÑлонены, ён будзе бачны толькі вам Ñ– ÑтаршынÑм Ñуполкі, пакуль Ñны не адÑлонÑць Ñго. Ð’Ñ‹ можаце праглÑдзець ваш камÑнтар тут. + +/talkpost_do.bml.success.screened.comm.anon=Ваш ананімны камÑнтар быў дададзены. КіруючыÑÑ ÑžÑтаноўкамі Ñуполкі, ён быў пазначаны Ñк заÑлонены, ён будзе бачны толькі вам Ñ– ÑтаршынÑм Ñуполкі, пакуль Ñны не адÑлонÑць Ñго. Ð’Ñ‹ можаце вÑрнуцца да галіны камÑнтараў тут. + +/talkpost_do.bml.success.screened.user=Ваш камÑнтар быў дададзены. КіруючыÑÑ ÑžÑтаноўкамі гÑтага журналу, ён быў пазначаны Ñк заÑлонены, ён будзе бачны толькі вам Ñ– ўладальніку журнала, пакуль уладальнік не адÑлоніць Ñго. Ð’Ñ‹ можаце праглÑдзець ваш камÑнтар тут. + +/talkpost_do.bml.success.screened.user.anon=Ваш ананімны камÑнтар быў дададзены. КіруючыÑÑ ÑžÑтаноўкамі гÑтага журналу, ён быў пазначаны Ñк заÑлонены, ён будзе бачны толькі вам Ñ– ўладальніку журналу, пакуль уладальнік не адÑлоніць Ñго. Ð’Ñ‹ можаце вÑрнуцца да галіны камÑнтараў тут. + +/talkpost_do.bml.success.title=ПоÑьпех + +/talkpost_do.bml.success.unscreened=Дадаткова, заÑлонены камÑнтар, на Ñкі вы адказалі, быў адÑлонены Ñ– цÑпер бачны. + +/talkpost_do.bml.title=КамÑнтар запіÑаны + +/talkpost_do.bml.title.error=КамÑнтар не запіÑаны + +/talkpost_do.bml.title.preview=ПерадпраглÑд камÑнтару + +/talkread.bml.anonuser=(Ðнанімна) + +/talkread.bml.confirm.action=Ð’Ñ‹ ўпÑўнены, што хочаце выдаліць Ð²Ñ‹Ð±Ñ€Ð°Ð½Ñ‹Ñ ÐºÐ°Ð¼Ñнтары? + +/talkread.bml.deletedpost=(Выдалены запіÑ) + +/talkread.bml.deleteduser=(Выдалены карыÑтальнік: [[username]]) + +/talkread.bml.fromip=(з [[ip]]) + +/talkread.bml.noreplies=ÐÑма адказаў + +/talkread.bml.nosubject=(бÑз Ñ‚Ñмы) + +/talkread.bml.replysuspended=(Ðдказ ад прыпыненага карыÑтальніка) + +/talkread.bml.screenedpost=(ЗаÑлонены запіÑ) + +/talkread.bml.select=Выбраць + +/talkread.bml.talkmulti.delete=Выдаліць + +/talkread.bml.talkmulti.des=МаÑавае дзеÑньне над выбранымі камÑнтарамі: + +/talkread.bml.talkmulti.screen=ЗаÑланіць + +/talkread.bml.talkmulti.submit=Выканаць дзеÑньне + +/talkread.bml.talkmulti.unscreen=ÐдÑланіць + +/talkread.bml.title=Прачытаць камÑнтары + +/talkscreen.bml.error.login=Ð’Ñ‹ павінны ўвайÑьці, каб працаваць з заÑлоненымі камÑнтарамі. + +/talkscreen.bml.error.privs.screen=У Ð²Ð°Ñ Ð½Ñма правоў, каб заÑланіць гÑÑ‚Ñ‹ камÑнтар. + +/talkscreen.bml.error.privs.unscreen=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб адÑланіць гÑÑ‚Ñ‹ камÑнтар. + +/talkscreen.bml.screen.doit=Так, заÑланіць гÑÑ‚Ñ‹ камÑнтар + +/talkscreen.bml.screen.sure.body=Ð’Ñ‹ ўпÑўнены, што хочаце заÑланіць гÑÑ‚Ñ‹ камÑнтар? + +/talkscreen.bml.screen.sure.title=ЗаÑланіць гÑÑ‚Ñ‹ камÑнтар? + +/talkscreen.bml.screened.body=КамÑнтар быў заÑлонены.Ð’Ñ‹ можаце праглÑдзець Ñго тут. + +/talkscreen.bml.screened.title=ПоÑьпех + +/talkscreen.bml.title=ЗаÑлонены камÑнтар + +/talkscreen.bml.unscreen.doit=Так, адÑланіць гÑÑ‚Ñ‹ камÑнтар + +/talkscreen.bml.unscreen.sure.body=Ð’Ñ‹ ўпÑўнены, што хочаце адÑланіць гÑÑ‚Ñ‹ камÑнтар? + +/talkscreen.bml.unscreen.sure.title=ÐдÑланіць гÑÑ‚Ñ‹ камÑнтар? + +/talkscreen.bml.unscreened.body=КамÑнтар быў адÑлонены. Ð’Ñ‹ можаце праглÑдзець Ñго тут. + +/talkscreen.bml.unscreened.title=ПоÑьпех + +/tools/emailmanage.bml.address.current.title=БÑгучы Ð°Ð´Ñ€Ð°Ñ + +/tools/emailmanage.bml.address.old.none=ÐÑма + +/tools/emailmanage.bml.address.old.text=ÐіжÑй - гÑта ÑÑŒÐ¿Ñ–Ñ Ð°Ð´Ñ€Ð°Ñоў Ñл.пошты, ÑÐºÑ–Ñ ÑžÐ¶Ñ‹Ð²Ð°Ð»Ñ–ÑÑ Ð· вашым рахункам, Ñ– Ñ‡Ð°Ñ ÐºÐ°Ð»Ñ– Ñны пераÑтавалі быць вашым аÑноўным адраÑам Ñл.пошты. Ðдзначце Ñ‚Ñ‹Ñ, ÑÐºÑ–Ñ Ð²Ñ‹ хочаце выдаліць. + +/tools/emailmanage.bml.address.old.title=ПапÑÑ€ÑÐ´Ð½Ñ–Ñ Ð°Ð´Ñ€Ð°ÑÑ‹ + +/tools/emailmanage.bml.delete_selected=Выдаліць Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ + +/tools/emailmanage.bml.desc.notfirst=ГÑÑ‚Ð°Ñ Ñтаронка толькі дазвалÑе вам выдаліць адраÑÑ‹ Ñл.пошты, ÑÐºÑ–Ñ ÑžÐ¶Ñ‹Ð²Ð°Ð»Ñ–ÑÑ Ð¿Ð°ÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾, Ñк вы актывізавалі ваш рахунак праз ваш бÑгучы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. У прыватнаÑьці, гÑта значыць, што нападаючы Ð½Ñ Ð·Ð¼Ð¾Ð¶Ð° выдаліць ваш Ñапраўдны Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +/tools/emailmanage.bml.desc.text=ГÑÑ‚Ð°Ñ Ñтаронка дазвалÑе вам выдаліць адраÑÑ‹ Ñл.пошты, ÑÐºÑ–Ñ ÑžÐ¶Ñ‹Ð²Ð°Ð»Ñ–ÑÑ Ð· вашым рахункам. Калі вы выдаліце адраÑ, вы больш Ð½Ñ Ð·Ð¼Ð¾Ð¶Ð°Ñ†Ðµ атрымаць на Ñго Ñвой пароль. ГÑта зручна, калі нехта даведаўÑÑ Ð¿Ñ€Ð° ваш пароль Ñ– захапіў ваш журнал. ПроÑта атрымайце пароль на ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, зьмÑніце пароль, Ñ– выдаліце Ð°Ð´Ñ€Ð°Ñ Ñл.пошты захопніка. + +/tools/emailmanage.bml.desc.title=ÐпіÑаньне + +/tools/emailmanage.bml.log.deleted=Выдалены: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Зьмены захаваны + +/tools/emailmanage.bml.notvalidated.text=Каб ужыць гÑтую прыладу, ваш бÑгучы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты [[email]] павінен быць пацьверджаны. Калі вы згубілі пацьвÑрджальны ліÑÑ‚ Ñл.пошты Ð´Ð»Ñ Ð³Ñтага, вы можаце атрымаць Ñго ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. ПаÑÑŒÐ»Ñ Ð¿Ð°Ñ†ÑŒÐ²ÐµÑ€Ð´Ð¶Ð°Ð½ÑŒÐ½Ñ Ð²Ð°ÑˆÐ°Ð³Ð° адраÑу Ñл.пошты, вÑртайцеÑÑ Ñюды. + +/tools/emailmanage.bml.notvalidated.title=ÐÐ´Ñ€Ð°Ñ Ñл.пошты не пацьверджаны + +/tools/emailmanage.bml.title=Кіраваньне адраÑам Ñл.пошты + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Ваш ÑÑŒÐ¿Ñ–Ñ Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ… запіÑаў быў абноўлены. + +/tools/memadd.bml.body.added.header=ПоÑьпех + +/tools/memadd.bml.description=ÐпіÑаньне: + +/tools/memadd.bml.description.text<< +Ðпішыце гÑÑ‚Ñ‹ журнальны Ð·Ð°Ð¿Ñ–Ñ Ñ‚Ð°Ðº, Ñк вы Ñго будзеце ўзгадваць. +  Каб выдаліць гÑÑ‚Ñ‹ запіÑ, пакіньце поле апіÑÐ°Ð½ÑŒÐ½Ñ Ð¿ÑƒÑтым. +. + +/tools/memadd.bml.error.deleted.body=Журнальны Ð·Ð°Ð¿Ñ–Ñ Ñ€Ð°Ð½ÐµÐ¹ апіÑаны Ñк "[[desc]]" быў выдалены Ñа ÑьпіÑу вашых запамінальных запіÑаў. + +/tools/memadd.bml.error.deleted.title=УÑпамін выдалены + +/tools/memadd.bml.error.entry_deleted=Журнальны Ð·Ð°Ð¿Ñ–Ñ Ð±Ð¾Ð»ÑŒÑˆ не Ñ–Ñнуе. УÑпамін выдалены. + +/tools/memadd.bml.error.fivekeywords=Толькі 5 ключавых Ñловаў ці катÑÐ³Ð¾Ñ€Ñ‹Ñ Ð´Ð°Ð·Ð²Ð¾Ð»ÐµÐ½Ð° Ð´Ð»Ñ Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ð°Ð³Ð° запіÑу. + +/tools/memadd.bml.error.invalid_security=ÐÑÑÐ»ÑƒÑˆÐ½Ð°Ñ Ñ†Ñ– Ð¿Ñ€Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð½Ð°Ñ Ð¾Ð¿Ñ†Ñ‹Ñ Ð±ÑÑьпекі. + +/tools/memadd.bml.error.login=Ð’Ñ‹ павінны ўвайÑьці, каб ужываць гÑтую мажліваÑьць. Увайдзіце Ñ– вы потым вернецеÑÑ Ñюды. + +/tools/memadd.bml.error.maxsize=ГÑтае ключавое Ñлова перавыÑіла макÑымальна дазволеную даўжыню: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Каб дадаваць журнальны Ð·Ð°Ð¿Ñ–Ñ Ð´Ð° ÑьпіÑу вашых уÑпамінаў, вам Ñ‚Ñ€Ñба апіÑаць Ñго. +Каб выдаліць уÑпамін, вам Ñ‚Ñ€Ñба Ñ€Ñдагаваць Ñго Ñ– выдаліць апіÑаньне, але вы ÑÑˆÑ‡Ñ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ гÑÑ‚Ñ‹ Ð·Ð°Ð¿Ñ–Ñ Ñƒ ліку вашых уÑпамінаў. +. + +/tools/memadd.bml.error.nodescription.title=ÐÑма апіÑÐ°Ð½ÑŒÐ½Ñ + +/tools/memadd.bml.form.reset=Скінуць + +/tools/memadd.bml.form.submit=ЗапіÑаць + +/tools/memadd.bml.keywords=ÐšÐ»ÑŽÑ‡Ð°Ð²Ñ‹Ñ Ñловы: + +/tools/memadd.bml.keywords.example=Прыклад: вÑÑёлы, дурны, рамантычны + +/tools/memadd.bml.keywords.select=Ці вы можаце выбраць з ключавых Ñловаў, ÑÐºÑ–Ñ Ð²Ñ‹ ўжывалі раней: + +/tools/memadd.bml.keywords.text=Чаму гÑÑ‚Ñ‹ Ð·Ð°Ð¿Ñ–Ñ Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹? УвÑдзіце да пÑці, падзеленых коÑкай, ключавых Ñловаў ці катÑгорыÑÑž, каб вы маглі Ñго потым знайÑьці. + +/tools/memadd.bml.login.enterinfo=УвÑдзіце Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль рахунку, у Ñкі вы хочаце захаваць запіÑ. + +/tools/memadd.bml.login.forgot.header=Забылі нешта? + +/tools/memadd.bml.login.forgot.recover=Калі вы забылі Ñвае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ці пароль, узнавіце Ñ–Ñ… тут!. + +/tools/memadd.bml.multiple_selections=Трымайце клÑвішу 'Control' націÑкаючы на ÐºÐ»ÑŽÑ‡Ð°Ð²Ñ‹Ñ Ñловы, каб выбраць некалькі з Ñ–Ñ…. + +/tools/memadd.bml.security=БÑÑьпека: + +/tools/memadd.bml.security.friendsonly=Толькі ÑÑбры + +/tools/memadd.bml.security.private=Прыватны + +/tools/memadd.bml.security.public=Грамадзкі + +/tools/memadd.bml.title=Дадаць да ÑžÑпамінаў + +/tools/memadd.bml.title.added=Дададзена + +/tools/memadd.bml.title.add_memory=Дадаць запамінальны Ð·Ð°Ð¿Ñ–Ñ + +/tools/memadd.bml.title.deleted=Выдаленьне + +/tools/memadd.bml.title.edit_memory=РÑдагаваць запамінальны Ð·Ð°Ð¿Ñ–Ñ + +/tools/memadd.bml.whocansee<< +Хто можа бачыць запіÑÑ‹, ÑÐºÑ–Ñ Ð²Ñ‹ пазначылі, Ñк запамінальныÑ? + Кожны, толькі Ð²Ð°ÑˆÑ‹Ñ ÑÑбры, ці толькі вы? +. + +/tools/memadd.bml.whocansee.comm=Хто можа бачыць, што вы пазначылі гÑÑ‚Ñ‹ запіÑ, Ñк запамінальны? Кожны, толькі ўдзельнікі Ñуполкі, ці толькі Ñтаршыні Ñуполкі? + +/tools/memories.bml.back=Ðазад + +/tools/memories.bml.body.keyword<< + +[[user]]. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] падзÑліў Ñвае Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹. p?> +. + +/tools/memories.bml.body.memorable=ÐіжÑй ÑÑŒÐ¿Ñ–Ñ Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ… запіÑаў, ÑÐºÑ–Ñ ÐºÐ°Ñ€Ñ‹Ñтальнік [[user]] Ð½Ñ ÑžÐ½Ñ‘Ñ Ð½Ñ– Ñž адну з катÑгорыÑÑž. + +/tools/memories.bml.delete=Выдаліць вызначанае + +/tools/memories.bml.delete.confirm=Ð’Ñ‹ зьбіраецеÑÑ Ð²Ñ‹Ð´Ð°Ð»Ñ–Ñ†ÑŒ адзін ці болей уÑпамінаў. Ð’Ñ‹ ўпÑўнены, што хочаце зрабіць гÑта? + +/tools/memories.bml.delete.deleted.head=ПоÑьпех + +/tools/memories.bml.delete.deleted.text=Ð’Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹Ñ ÑžÑпаміны былі выдалены. Ð’Ñ‹ можаце вернуцца да вашага ÑьпіÑу запамінальных запіÑаў. + +/tools/memories.bml.delete.deleted.title=УÑпаміны выдалены + +/tools/memories.bml.delete.error.dberror=ÐдбылаÑÑ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÐ° Ñž базе зьвеÑтак пад Ñ‡Ð°Ñ Ð²Ñ‹Ð´Ð°Ð»ÐµÐ½ÑŒÐ½Ñ Ð²Ð°ÑˆÑ‹Ñ… уÑпамінаў. Памылка: [[error]]. Калі лаÑка, паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +/tools/memories.bml.delete.error.noneselected=Ð’Ñ‹ Ð½Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ñ‹Ð»Ñ– ÑžÑпаміны Ð´Ð»Ñ Ð²Ñ‹Ð´Ð°Ð»ÐµÐ½ÑŒÐ½Ñ. + +/tools/memories.bml.edit=Ñ€Ñдагаваць + +/tools/memories.bml.error.noentries.body<< +ГÑта можа быць з-за таго, што:
      +
    1. карыÑтальнік Ð½Ñ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ñ‹Ñž запамінальных запіÑаў,
    2. +
    3. Ð·Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ карыÑтальніка абаронены, Ñ– вы Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб праглÑдаць Ñ–Ñ…
    4. +
    5. карыÑтальнік Ð½Ñ Ð¼Ð°Ðµ ÑžÑпамінаў, ÑÐºÑ–Ñ Ð°Ð´Ð¿Ð°Ð²Ñдаюць вашаму крытÑру фільтра.
    +. + +/tools/memories.bml.error.noentries.title=УÑпаміны Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ñ‹. + +/tools/memories.bml.filter.all=УÑе ÑžÑпаміны + +/tools/memories.bml.filter.other=Толькі Ñ–Ð½ÑˆÑ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +/tools/memories.bml.filter.own=Толькі запіÑÑ‹ '[[user]]' + +/tools/memories.bml.form.filter=Фільтраваць запіÑÑ‹ па: + +/tools/memories.bml.form.sort=Сартаваць запіÑÑ‹ па: + +/tools/memories.bml.form.switch=Пераключыць + +/tools/memories.bml.login=Каб праглÑдзець Ð²Ð°ÑˆÑ‹Ñ ÑžÐ»Ð°ÑÐ½Ñ‹Ñ ÑžÑпаміны, калі лаÑка, увайдзіце. + +/tools/memories.bml.plur_entry=[[num]] [[?num|запіÑ|запіÑаў]] + +/tools/memories.bml.sort.description=апіÑаньню + +/tools/memories.bml.sort.journal=журналу + +/tools/memories.bml.sort.orderadded=парадку Ð´Ð°Ð´Ð°Ð²Ð°Ð½ÑŒÐ½Ñ + +/tools/memories.bml.title.keyword=Ð—Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ [[keyword]] запіÑÑ‹ + +/tools/memories.bml.title.memorable=Ð—Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +/tools/memories.bml.uncategorized=ÐекатÑÐ³Ð°Ñ€Ñ‹Ð·Ð°Ð²Ð°Ð½Ñ‹Ñ + +/update.bml.altpost=Журнал, каб рабіць запіÑ: + +/update.bml.btn.preview=ПерадпраглÑд + +/update.bml.btn.update=Зрабіць Ð·Ð°Ð¿Ñ–Ñ + +/update.bml.currmood=БÑгучы наÑтрой: + +/update.bml.currmusic=БÑÐ³ÑƒÑ‡Ð°Ñ Ð¼ÑƒÐ·Ñ‹ÐºÐ°: + +/update.bml.date=Дата: + +/update.bml.default=па змоўчаньні + +/update.bml.defaultjournal=([[user]]) -- па змоўчаньні + +/update.bml.error.cantpost=Выбачайце, вы Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ зрабціь Ð·Ð°Ð¿Ñ–Ñ Ñƒ гÑÑ‚Ñ‹ чаÑ. + +/update.bml.error.disabled=Тып вашага рахунку не дазвалÑе вам рабіць запіÑÑ‹. + +/update.bml.error.disabled.title=ДоÑтуп, каб рабіць запіÑÑ‹, закрыты + +/update.bml.error.login=Памылка ўваходу: + +/update.bml.error.nopass=УвÑдзіце пароль + +/update.bml.error.update=Памылка пры запіÑу Ñž журнал: + +/update.bml.event=ПадзеÑ: + +/update.bml.full=ÐŸÐ¾ÑžÐ½Ð°Ñ Ñтаронка запіÑу + +/update.bml.htmlokay.norich=(HTML дазволены; па змоўчаньні, Ð½Ð¾Ð²Ñ‹Ñ Ñ€Ð°Ð´ÐºÑ– будуць аўтаматычна фарматавацца Ñž <br>) + +/update.bml.htmlokay.rich=(HTML дазволены; па змоўчаньні, Ð½Ð¾Ð²Ñ‹Ñ Ñ€Ð°Ð´ÐºÑ– будуць аўтаматычна фарматавацца Ñž <br> - ці выкарыÑтайце Ñ€Ñжым узбагачанага Ñ‚ÑкÑту.) + +/update.bml.htmlokay.rte_nosupport=(Выбачайце, ваш праглÑдач не падтрымлівае аÑÑродзьдзе ўзбагачанага Ñ‚ÑкÑту.) + +/update.bml.localtime=ÐœÑÑцовы чаÑ: + +/update.bml.loggedinas=ЦÑпер вы ўвайшлі Ñк [[user]].
    Каб зрабіць Ð·Ð°Ð¿Ñ–Ñ Ñк іншы карыÑтальнік, націÑьніце тут. + +/update.bml.loggingin=Уваход на ÑÑрвер... + +/update.bml.noneother=ÐÑ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ñ‹, ці іншы: + +/update.bml.note=Заўвага: Ð§Ð°Ñ Ñ– дата вышÑй узÑÑ‚Ñ‹Ñ Ð· нашага ÑÑрверу. ПадкарÑктуйце Ñ–Ñ… Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° гадзіннага поÑÑу перад запіÑам. + +/update.bml.opt.backdate=Ð—Ð°Ð¿Ñ–Ñ Ð·Ð° мінулую дату: + +/update.bml.opt.backdate.about=Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ бачны Ñž Ñтужках ÑÑброў + +/update.bml.opt.defpic=(па змоўчаньні) + +/update.bml.opt.nocomments=Забараніць камÑнтары: + +/update.bml.opt.noemail=Ðе даÑылаць камÑнтары на Ð°Ð´Ñ€Ð°Ñ Ñл.пошты: + +/update.bml.opt.noformat=Ðе аўта-фарматаваць: + +/update.bml.opt.spellcheck=Праверыць артаграфію перад запіÑам (толькі ангельÑÐºÐ°Ñ Ð¼Ð¾Ð²Ð°) + +/update.bml.options=ÐеабавÑÐ·ÐºÐ¾Ð²Ñ‹Ñ ÑžÑтаноўкі + +/update.bml.other=Іншы: + +/update.bml.password=Пароль: + +/update.bml.picture=Ужыць выÑву: + +/update.bml.preview.header=ПерадпраглÑд + +/update.bml.preview.text=Так будзе выглÑдаць Ð·Ð°Ð¿Ñ–Ñ Ñƒ вашым журнале. Ужываючы форму ніжÑй, вы можаце далей Ñ€Ñдагаваць запіÑ, ці падаць Ñго Ñк ён Ñ‘Ñьць. + +/update.bml.security.custom=УлаÑны... + +/update.bml.security.friends=СÑбры + +/update.bml.security.head=Узровень бÑÑьпекі + +/update.bml.security.private=Прыватны + +/update.bml.security.public=Грамадзкі + +/update.bml.servermsg=ТакÑама, ÑÑрвер мае вам паведамленьне: + +/update.bml.simple=Ð’Ñ‹ глÑдзіце на звычайную Ñтаронку. Ð”Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ°Ð¹ колькаÑьці опцыÑÑž, націÑьніце тут. + +/update.bml.spellchecked=Ваш Ð·Ð°Ð¿Ñ–Ñ Ð¿Ð°ÑÑŒÐ»Ñ Ð¿Ñ€Ð°Ð²ÐµÑ€ÐºÑ– арфаграфіі: + +/update.bml.subject=ТÑма: (не абавÑзкова) + +/update.bml.timeformat=24-гадзінавы Ñ‡Ð°Ñ + +/update.bml.title=Ð—Ð°Ð¿Ñ–Ñ Ñƒ журнал + +/update.bml.title.readonly=РÑжым толькі-Ñ‡Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ + +/update.bml.update.alternate=Калі вы не жадаеце ÑьцÑгваць праграму-кліент Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° кампутару, ці такой нÑма Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° кампутару, вы можаце ўжываць гÑтую Ñтаронку, каб рабіць запіÑÑ‹ Ñž ваш Жывы Журнал. Яна такÑама карыÑнаÑ, калі вы знаходзіцеÑÑ Ð½Ð° вакацыÑÑ… ці далёка ад вашага аÑноўнага кампутару. Калі вы валодаеце платным рахункам, вы можаце рабіць запіÑÑ‹ Ñž ваш журнал праз Ñл.пошту, ці па Ñ‚Ñлефоне, калі вы знаходзіцеÑÑ Ð´Ð°Ð»Ñ‘ÐºÐ° ад кампутару, ці Ñтвараць апытаньні Ñž вашых запіÑах. + +/update.bml.update.head=Зрабіць запіÑ... + +/update.bml.update.success=Ð—Ð°Ð¿Ñ–Ñ Ð¿Ð°ÑьпÑхова зроблены. Ð’Ñ‹ можаце паглÑдзець на ваш абноўлены журнал тут. + +/update.bml.updating=Ðбнаўленьне журналу... + +/update.bml.username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: + +/uploadpic.bml.error.unsupportedtype=Файлы тыпу [[filetype]] не падтрымліваюцца. Ð’Ñ‹ можаце загружаць толькі файлы тыпу GIF, PNG ці JPG. Ðмаль уÑе праграмы працы з малюнкамі ці фотаздымкамі могуць зрабіць Ð´Ð»Ñ Ð²Ð°Ñ Ñ‚Ð°ÐºÑƒÑŽ канвертацыю. + +/userinfo.bml.about.comm=Пра: + +/userinfo.bml.about.user=БіÑграфіÑ: + +/userinfo.bml.body.leave= Ð’Ñ‹ можаце пакінуць Ñуполку Ñž любы момант. + +/userinfo.bml.comminfo.body=ÐіжÑй знаходзіцца Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку "[[commname]]" Жывога Журналу. + +/userinfo.bml.comminfo.name=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку + +/userinfo.bml.date.never=Ðіколі. + +/userinfo.bml.error.malfname=ДÑфармаванае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: задоўгае, ці ўтрымлівае нÑÑÐ»ÑƒÑˆÐ½Ñ‹Ñ Ñымбалі. + +/userinfo.bml.error.notloggedin=Калі вы хочаце паглÑдзець Ñвой улаÑны профіль, вам Ñ‚Ñ€Ñба ўвайÑьці. + +/userinfo.bml.friendof.comm=ПраглÑдаецца: + +/userinfo.bml.friendof.hidden=(Ñхавана) + +/userinfo.bml.friendof.syndreadcount=КолькаÑьць чытачоў + +/userinfo.bml.friendof.user=Чый ÑÑбра: + +/userinfo.bml.friends.comm=Удзельнікі + +/userinfo.bml.friends.user=СÑбры + +/userinfo.bml.label.addbuddy=Дадаць таварыша + +/userinfo.bml.label.adduser=Дадаць карыÑтальніка + +/userinfo.bml.label.alsofriendof=ТакÑама чый ÑÑбра: + +/userinfo.bml.label.birthdate=Дзень нараджÑньнÑ: + +/userinfo.bml.label.clientsused=Ð£Ð¶Ñ‹Ñ‚Ñ‹Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹-кліенты: + +/userinfo.bml.label.comments=КамÑнтары: + +/userinfo.bml.label.composted=ЗробленыÑ: [[num]] - + +/userinfo.bml.label.comreceived=ÐтрыманыÑ: [[num]] + +/userinfo.bml.label.datecreated=Дата ÑтварÑньнÑ: + +/userinfo.bml.label.dateupdated=Дата абнаўленьнÑ: + +/userinfo.bml.label.email=Эл.пошта: + +/userinfo.bml.label.frcommunity=Суполкі + +/userinfo.bml.label.frpeople=Людзі + +/userinfo.bml.label.frsyndication2=Стужкі + +/userinfo.bml.label.icquin=Ðумар ICQ: + +/userinfo.bml.label.interests=ЗацікаўленаÑьці + +/userinfo.bml.label.interests.modifyyours=Мадыфікаваць Ñвае + +/userinfo.bml.label.interests.removesome=Выдаліць Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] зацікаўленаÑьцей не паказана + +/userinfo.bml.label.journalentrs=Ð–ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹: + +/userinfo.bml.label.location=МеÑцажыхарÑтва: + +/userinfo.bml.label.memberof=Удзельнік + +/userinfo.bml.label.memories=УÑпаміны: + +/userinfo.bml.label.moredetails=(больш дÑталёва...) + +/userinfo.bml.label.msnusername=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка MSN: + +/userinfo.bml.label.mutual=Ð£Ð·Ð°ÐµÐ¼Ð½Ñ‹Ñ ÑÑбры: + +/userinfo.bml.label.name=ІмÑ: + +/userinfo.bml.label.nofriends=ÐÑ Ð²Ñ‹Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹. + +/userinfo.bml.label.post=Зрабіць Ð·Ð°Ð¿Ñ–Ñ Ñƒ "[[journal]]" + +/userinfo.bml.label.postalt=Зрабіць Ð·Ð°Ð¿Ñ–Ñ + +/userinfo.bml.label.reqfinduser=Толькі карыÑтальнікі з прывілеем 'пошук карыÑтальнікаў' могуць праглÑдаць ідÑÐ½Ñ‚Ñ‹Ñ„Ñ–ÐºÐ°Ñ†Ñ‹Ð¹Ð½Ñ‹Ñ Ð½ÑƒÐ¼Ð°Ñ€Ñ‹. + +/userinfo.bml.label.searchjournal=Пошук у гÑтым журнале + +/userinfo.bml.label.sendmessage=ДаÑлаць паведамленьне + +/userinfo.bml.label.shared=ДоÑтуп Ð´Ð»Ñ Ð·Ð°Ð¿Ñ–Ñу: + +/userinfo.bml.label.supportpoints=Пункты падтрымкі + +/userinfo.bml.label.syndicatedfrom=Сындыкат з: + +/userinfo.bml.label.syndicatedstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñындыкату: + +/userinfo.bml.label.textmessage=
    ТÑкÑтавае
    паведамленьне
    : + +/userinfo.bml.label.todo=Ð¡ÑŒÐ¿Ñ–Ñ "што зрабіць" + +/userinfo.bml.label.user=КарыÑтальнік: + +/userinfo.bml.label.viewfriends=ПраглÑд ÑÑброў + +/userinfo.bml.label.viewmembers=ПраглÑд удзельнікаў + +/userinfo.bml.label.website=Сайт: + +/userinfo.bml.membership.body=Каб далучыцца да гÑтай Ñуполкі, націÑьніце тут. + +/userinfo.bml.membership.paidmembers=ПаÑÑŒÐ»Ñ Ñ‚Ð°Ð³Ð¾ Ñк вы наладзілі ваш платны рахунак, вы можаце далучыцца да Ñуполкі платных удзельнікаў. + +/userinfo.bml.memories.entries=ЗапіÑаў: [[count]] + +/userinfo.bml.memories.entry=[[count]] Ð·Ð°Ð¿Ñ–Ñ + +/userinfo.bml.monitor.comm=Сачыць за Ñуполкай + +/userinfo.bml.monitor.user=Дадаць гÑтага карыÑтальніка да ÑьпіÑу ÑÑброў + +/userinfo.bml.nonexist.body=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка [[user]] ÑÑˆÑ‡Ñ Ð½Ðµ зарÑгіÑтравана. + +/userinfo.bml.nonexist.name=ÐевÑдомы карыÑтальнік + +/userinfo.bml.sendmessage.body=ДаÑлаць [[user]] Ñ‚ÑкÑтавае паведамленьне
    на мабільны ці пÑйджар. + +/userinfo.bml.syn.last.never=Ðіколі + +/userinfo.bml.syn.lastcheck=ÐпошнÑÑ Ð¿Ñ€Ð°Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.nextcheck=ÐаÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð¿Ñ€Ð°Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.parseerror=Паведамленьне пра памылку: + +/userinfo.bml.syndinfo.body=Калі вы хочаце, каб артыкулы з Ñындыкаванага Ñайту траплÑлі Ñž вашу Ñтужку ÑÑброў, вы можаце дадаць гÑÑ‚Ñ‹ журнал да ÑьпіÑу вашых ÑÑброў. + +/userinfo.bml.syndinfo.name=Сындыкаваны журнал + +/userinfo.bml.tellafriend=РаÑкажыце ÑÑбру! + +/userinfo.bml.timeupdate.dayago=1 дзень таму + +/userinfo.bml.timeupdate.daysago=прайшло дзён: [[num]] + +/userinfo.bml.timeupdate.hourago=1 гадзіну таму + +/userinfo.bml.timeupdate.hoursago=прайшло гадзін: [[num]] + +/userinfo.bml.timeupdate.minuteago=1 хвіліну таму + +/userinfo.bml.timeupdate.minutesago=прайшло хвілін: [[num]] + +/userinfo.bml.timeupdate.secondago=1 Ñекунду таму + +/userinfo.bml.timeupdate.secondsago=Секунд прайшло [[num]] + +/userinfo.bml.timeupdate.weekago=1 тыдзень таму + +/userinfo.bml.timeupdate.weeksago=прайшло тыднÑÑž: [[num]] + +/userinfo.bml.title=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° карыÑтальніка + +/userinfo.bml.title.communityinfo=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° Ñуполку + +/userinfo.bml.title.syndicated=Сындыкаваны рахунак + +/userinfo.bml.userinfo.body=ÐіжÑй знаходзіцца Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° карыÑтальніка [[username]]. Калі вы гÑÑ‚Ñ‹ карыÑтальнік, вы можаце зьмÑніць інфармацыю пра ÑÑбе на Ñтаронцы Ñ€ÑÐ´Ð°Ð³Ð°Ð²Ð°Ð½ÑŒÐ½Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ–. + +/userinfo.bml.userinfo.name=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° карыÑтальніка + +bml.badcontent.body=Ðдна ці некалькі памылак адбылоÑÑ Ñž чаÑе апрацоўкі вашага запыту. Калі лаÑка, вÑрніцеÑÑ, ÑкарÑктуйце неабходную інфармацыю, Ñ– падайце зьвеÑткі ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +bml.badinput.body=Ваш праглÑдач даÑлаў некаторы Ñ‚ÑкÑÑ‚, Ñкі не зьÑўлÑецца Ñлушным Ñ‚ÑкÑтам у кадаваньні UTF-8, Ñк ён павінен быць. ГÑта можа быць з-за таго, што вы прымуÑілі ваш праглÑдач адчыніць папÑÑ€Ñднюю Ñтаронку Ñž кадаваньні адрозным ад UTF-8. ГÑта такÑама можа паказваць на памылку Ñž вашым праглÑдачы. Калі вы Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ абыйÑьці гÑтую памылку, кантактуйце з намі. + +bml.badinput.head=КепÑкі юнікодавы ўвод + +bml.needlogin.body2=Каб праглÑдзець гÑтую Ñтаронку, вы муÑіце ўвайÑьці. + +bml.needlogin.head=ПатрÑбны ўваход + +BML.parse_multipart.parse=Памылка аналізу загрузкі + +BML.parse_multipart.toolarge=Ðбнова завÑÐ»Ñ–ÐºÐ°Ñ + +BML.parse_multipart.unknowntype=ÐевÑдомы тып зьмеÑту + +bml.requirepost=Як пераÑьцÑрога бÑÑьпекі, гÑÑ‚Ð°Ñ Ñтаронка патрабуе запыту тыпу POST, а Ð½Ñ GET. Калі вы Ñпрабуеце Ñлушна падаць гÑтую форму, калі лаÑка, кантактуйце з намі. + +btn.search=Пошук + +crumb.about=Пра Жывы Журнал + +crumb.abusereport=Скарга пра абразу + +crumb.acctfeatures=МажліваÑьці па тыпу рахунку + +crumb.acctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑƒ + +crumb.addfriend=Дадаваньне ÑÑбра + +crumb.addtodo=Дадаваньне пункту ÑьпіÑу "што зрабіць" + +crumb.advcustomize=Ðаладка пашыраных уÑтановак S2 + +crumb.advsearch=Пашыраны + +crumb.banners=РÑклÑÐ¼Ð½Ñ‹Ñ Ð±Ð°Ð½Ñры + +crumb.birthdays=Дні нараджÑньнÑÑž + +crumb.changepass=Зьмена паролю + +crumb.code=Код Жывога Журналу + +crumb.commmembers=Удзел у Ñуполцы + +crumb.commpending=РазглÑд удзелу + +crumb.commsearch=Пошук Ñуполак + +crumb.community=ЦÑнтр Ñуполак + +crumb.contract=Ðаш грамадзкі кантракт + +crumb.contributors=Супрацоўнікі + +crumb.coppa=COPPA + +crumb.createcommunity=СтварÑньне Ñуполкі + +crumb.createjournal=СтварÑньне журналу + +crumb.createstyle=СтварÑньне Ñтылю + +crumb.customize=Ðаладка ÑžÑтановак S2 + +crumb.delcomment=Выдаленьне камÑнтару + +crumb.download=СьцÑгваньне праграмы-кліента + +crumb.editentries=РÑдагаваньне запіÑаў + +crumb.editentries_do=РÑдагаваньне запіÑу + +crumb.editfriendgrps=РÑдагаваньне груп ÑÑброў + +crumb.editfriends=РÑдагаваньне ÑÑброў + +crumb.editinfo=ÐÑабіÑÑ‚Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +crumb.editpics=Ð’Ñ‹Ñвы карыÑтальніка + +crumb.editstyle=РÑдагаваньне Ñтылю + +crumb.emailgateway=Шлюз Ñл.пошты + +crumb.emailmanage=Кіраваньне Ñл.поштай + +crumb.encodings=Пра кадаваньні + +crumb.export=ЭкÑпартаваньне журналу + +crumb.faq=Пытаньні Ñ– адказы + +crumb.feedstersearch=Пошук у журнале + +crumb.filemanager=Кіраваньне файламі + +crumb.friends=Прылады ÑÑброў + +crumb.friendsfilter=Фільтр ÑÑброў + +crumb.goat=Пра ФрÑнка + +crumb.home=Пачатак + +crumb.itsfree=ГÑта бÑÑплатна? + +crumb.joincomm=ДадучÑньне да Ñуполкі + +crumb.latestposts=ÐÐ¿Ð¾ÑˆÐ½Ñ–Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +crumb.layerbrowse=ПраглÑдач грамадзкіх ÑлоÑÑž + +crumb.leavecomm=Пакіданьне Ñуполкі + +crumb.legal=Ð®Ñ€Ñ‹Ð´Ñ‹Ñ‡Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +crumb.linkslist=Ð’Ð°ÑˆÑ‹Ñ ÑпаÑылкі + +crumb.login=Уваход + +crumb.logout=Выхад + +crumb.lostinfo=Ð—Ð³ÑƒÐ±Ð»ÐµÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +crumb.manage=Кіраваньне рахункамі + +crumb.managecommunity=Кіраваньне Ñуполкай + +crumb.meme=ÐдÑочваньне папулÑрнага + +crumb.memories=Ð—Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +crumb.moderate=МадÑÑ€Ð°Ñ†Ñ‹Ñ Ñуполкі + +crumb.modify=УÑтаноўкі журналу + +crumb.moodlist=ПраглÑд наÑтроÑÑž + +crumb.news=Ðавіны + +crumb.paidaccounts=ÐŸÐ»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– + +crumb.paidacctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð°Ð³Ð° рахунку + +crumb.phonepostsettings=Ð—Ð°Ð¿Ñ–Ñ Ð¿Ð° Ñ‚Ñлефоне + +crumb.popfaq=ПапулÑÑ€Ð½Ñ‹Ñ ÐŸÑ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ– Ñ– адказы + +crumb.press=Зона прÑÑÑ‹ Жывога Журналу + +crumb.pressarticles=Жывы Журнал у прÑÑе + +crumb.preview=ПерадпраглÑды Ñхем + +crumb.privacy=Палітыка прыватнаÑьці + +crumb.register=Пацьверджаньне адраÑу Ñл.пошты + +crumb.search=Пошук + +crumb.searchinterests=Па зацікаўленаÑьці + +crumb.searchregion=Па Ñ€Ñгіёне + +crumb.seeoverrides=ПраглÑд перапрацовак карыÑтальніка + +crumb.setpgpkey=Ðдкрыты ключ + +crumb.singles=ÐÐ´Ð·Ñ–Ð½Ð¾ÐºÑ–Ñ Ð–Ñ‹Ð²Ð¾Ð³Ð° Журналу + +crumb.singlesopts=Мадыфікаваньне даÑтупнаÑьці + +crumb.singlessearch=Пошук адзінокіх + +crumb.sitemap=Мапа Ñайту + +crumb.siteopts=Опцыі праглÑду + +crumb.sizechart=ДыÑграма + +crumb.staff=Сталы пÑÑ€Ñанал + +crumb.stats=СтатыÑтыка + +crumb.store=Крама Жывога Журналу + +crumb.storeitem=ПраглÑд дÑталÑÑž аÑобніку + +crumb.styles=Стылі + +crumb.suggestions=ГенÑратар прапановаў + +crumb.suggview=Прапановы + +crumb.support=Падтрымка + +crumb.supportact=ДзеÑньне па запыце + +crumb.supportappend=Дадаць да запыту + +crumb.supporthelp=Дошка падтрымкі + +crumb.supportnotify=УÑтаноўкі паведамленьнÑÑž + +crumb.supportscores=Ð›ÐµÐ¿ÑˆÑ‹Ñ Ð²Ñ‹Ð½Ñ–ÐºÑ– + +crumb.supportsubmit=Зрабіць запыт + +crumb.textmessage=ДаÑылка Ñ‚ÑкÑтавага Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½ÑŒÐ½Ñ + +crumb.themes=ПерадпраглÑд Ñ‚Ñмаў + +crumb.todo=Ð¡ÑŒÐ¿Ñ–Ñ "што зрабіць" + +crumb.tos=Правілы абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ + +crumb.unsubscribe=ÐдпіÑацца + +crumb.update=Ð—Ð°Ð¿Ñ–Ñ Ñƒ журнал + +crumb.utf8convert=КанвÑртар UTF-8 + +crumb.yourlayers=Ð’Ð°ÑˆÑ‹Ñ Ñхемы + +crumb.yourstyles=Ð’Ð°ÑˆÑ‹Ñ Ñтылі + +date.day.friday.long=ПÑтніца + +date.day.friday.short=ПÑтн + +date.day.monday.long=ПанÑдзелак + +date.day.monday.short=Пан + +date.day.saturday.long=Субота + +date.day.saturday.short=Суб + +date.day.sunday.long=ÐÑÐ´Ð·ÐµÐ»Ñ + +date.day.sunday.short=ÐÑдз + +date.day.thursday.long=Чацьвер + +date.day.thursday.short=Чацьв + +date.day.tuesday.long=Ðўторак + +date.day.tuesday.short=Ðўт + +date.day.wednesday.long=Серада + +date.day.wednesday.short=Сер + +date.month.april.long=КраÑавік + +date.month.april.short=ÐšÑ€Ð°Ñ + +date.month.august.long=Жнівень + +date.month.august.short=Жнів + +date.month.december.long=Сьнежань + +date.month.december.short=Сьнеж + +date.month.february.long=Люты + +date.month.february.short=Лют + +date.month.january.long=Студзень + +date.month.january.short=Студз + +date.month.july.long=Ліпень + +date.month.july.short=Ліп + +date.month.june.long=ЧÑрвень + +date.month.june.short=ЧÑрв + +date.month.march.long=Сакавік + +date.month.march.short=Сак + +date.month.may.long=Травень + +date.month.may.short=Трав + +date.month.november.long=ЛіÑтапад + +date.month.november.short=ЛіÑÑ‚ + +date.month.october.long=КаÑтрычнік + +date.month.october.short=КаÑÑ‚Ñ€ + +date.month.september.long=ВераÑень + +date.month.september.short=Вер + +dystopia.btn.login=Уваход + +dystopia.hello_anonymous=Вітаем у LiveJournal! + +dystopia.hello_loggedin=Вітаю, [[username]]! + +dystopia.nav.contact=ÐšÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +dystopia.nav.createjournal=Стварыць журнал + +dystopia.nav.developer=Зона раÑпрацоўкі + +dystopia.nav.download=СьцÑгнуць + +dystopia.nav.editentries=РÑдагаваць запіÑÑ‹ + +dystopia.nav.editfriends=Ð’Ð°ÑˆÑ‹Ñ ÑÑбры + +dystopia.nav.editpassword=Ваш пароль + +dystopia.nav.editpics=Ð’Ð°ÑˆÑ‹Ñ Ð²Ñ‹Ñвы + +dystopia.nav.editstyle=РÑдагаваць Ñтыль + +dystopia.nav.faq=Пытаньні Ñ– адказы + +dystopia.nav.findcomm=Па Ñуполках + +dystopia.nav.finddir=Пошук + +dystopia.nav.findint=Па зацікаўленаÑьці + +dystopia.nav.findrandom=Выпадковы + +dystopia.nav.findregion=Па Ñ€Ñгіёне + +dystopia.nav.home=Дадому + +dystopia.nav.journalcalendar=КалÑндар + +dystopia.nav.journalfriends=СÑбры + +dystopia.nav.journalinfo=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° карыÑтальніка + +dystopia.nav.journalrecent=ÐпошнÑе + +dystopia.nav.legalprivacy=ПрыватнаÑьць + +dystopia.nav.legaltos=Правілы абÑÐ»ÑƒÐ³Ð¾ÑžÐ²Ð°Ð½ÑŒÐ½Ñ + +dystopia.nav.login=Уваход + +dystopia.nav.logout=Выхад + +dystopia.nav.lostinfo=Згублены пароль + +dystopia.nav.memories=УÑпаміны + +dystopia.nav.modifyjournal=Мадыфікаваць журнал + +dystopia.nav.news=Ðавіны + +dystopia.nav.paidaccts=ÐŸÐ»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– + +dystopia.nav.paymentarea=Зона аплаты + +dystopia.nav.personalinfo=ПÑÑ€ÑÐ°Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +dystopia.nav.sitemap=Мапа Ñайту + +dystopia.nav.siteopts=Опцыі праглÑду + +dystopia.nav.support=ÐÑьць пытаньне? + +dystopia.nav.updatejournal=Зрабіць Ð·Ð°Ð¿Ñ–Ñ + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=140 + +dystopia.navhead.findusers=Пошук карыÑтальнікаў + +dystopia.navhead.help=Дапамога Ñ– падтрымка + +dystopia.navhead.journal=Ваш журнал + +dystopia.navhead.legal=ЗаконнаÑьць + +dystopia.navhead.settings=Ð’Ð°ÑˆÑ‹Ñ ÑžÑтаноўкі + +dystopia.navhead.welcome=Запрашаем! + +dystopia.search.icq=Ðумар ICQ + +dystopia.search.int=ЗацікаўленаÑьць + +dystopia.search.msn=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка MSN + +dystopia.search.region=РÑгіён + +dystopia.searchlj=Пошук па Жывым Журнале: + +Email=Эл.пошта + +email.newacct.body<< +Віншуем, цÑпер вы маеце рахунак у Жывым Журнале! + +Каб завершыць ÑтварÑньне журналу Ñ– пацьвердзіць ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, ідзіце Ñюды: + +   [[regurl]] + +ÐÐ´Ñ€Ð°Ñ Ð¿Ð° Ñкому знаходзіцца ваш новы журнал: + +   [[siteroot]]/users/[[username]]/ + +а такÑама: + +   [[siteroot]]/~[[username]]/ + +ÐіжÑй Ð²Ð°ÑˆÑ‹Ñ Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль да Жывога Журналу: + +Â Â Â Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка: [[username]] +   Пароль: [[password]] + +Ð’Ñ‹ можаце пайÑьці Ñюды: [[siteroot]]/ Ð´Ð»Ñ Ð´Ð¾Ñтупу да вашага рахунку, ÑтварÑÐ½ÑŒÐ½Ñ Ð½Ð¾Ð²Ñ‹Ñ… журнальных запіÑаў, +зьмÑÐ½ÐµÐ½ÑŒÐ½Ñ Ð²Ð°ÑˆÑ‹Ñ… журнальных опцый, але мы Ñ€Ñкамендуем ÑьцÑгнуць праграму-кліент да Жывога Журналу. +ГÑта Ñамы проÑÑ‚Ñ‹ шлÑÑ…, каб рабіць запіÑÑ‹ Ñž журнал, Ñ–Ñнуе шмат праграм-кліентаў Ð´Ð»Ñ Ñ€Ð¾Ð·Ð½Ñ‹Ñ… плÑтформ! +Іх можна знайÑьці тут: +  +  [[siteroot]]/download/ + +Спачатку, калі вы ÑÑˆÑ‡Ñ Ð½Ñ Ð²ÐµÐ´Ð°ÐµÑ†Ðµ нікога на Жывым Журнале, вам можа быць Ñкладана. +Ðаведайце http://newbies.livejournal.com каб атрымаць добрую параду... +калі вам крышку пашанцуе, вы хутка зробіцеÑÑ Ð¿Ñ€Ð¾Ñ„Ñ– Ñž Жывым Журнале! + +Мы ÑпадзÑемÑÑ, што вы цÑніце Жывы Журнал так, Ñк мы цÑнім тое, што можам зрабіць Ð´Ð»Ñ Ð²Ð°Ñ. +Калі вы маеце пытаньні, Ñк карыÑтацца Жывым Журналам, наведайце зону падтрымкі: + +   [[siteroot]]/support/ + +Там вы зможаце знайÑьці адказы амаль на ÑžÑе пытаньні пра Жывы Журнал. + +Ðаша мÑта зрабіць Жывы Журнал абÑалютна лепшым... калі мы можам нешта зрабіць, каб палепшыць Ñго... паведаміце нам. +Мы не трымаем гÑÑ‚Ñ‹ Ñайт Ð´Ð·ÐµÐ»Ñ Ð³Ñ€Ð¾ÑˆÐ°Ð¹. Мы не ÐºÐ°Ð¼ÐµÑ€Ñ†Ñ‹Ð¹Ð½Ð°Ñ ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ... гÑÑ‚Ñ‹ Ñайт трымаецца на Ñ‚Ñ‹Ñ…, хто ім карыÑтаецца. +РаÑкажыце нам, што вы хочаце бачыць на ім. + +Калі вы маеце пытаньне, наша каманда падтрымкі адкажа на Ñ–Ñ…, звычайна менш, чым за 24 гадзіны. + +Ðтрымлівайце аÑалоду! + +Каманда [[sitename]] +[[siteroot]]/ +. + +email.newacct.subject=Запрашаем у Жывы Журнал + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Памылка + +error.badpassword=ÐÑÑлушны пароль + +error.code.comm_not_comm=Рахунак не зьÑўлÑецца Ñуполкай + +error.code.comm_not_found=Суполка Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð° + +error.code.comm_not_member=КарыÑтальнік не зьÑўлÑецца ўдзельнікам гÑтай Ñуполкі + +error.dberror=Памылка базы зьвеÑтак: + +error.deleted.name=Выдалены + +error.deleted.text=Журнал быў выдалены. Калі вы [[user]], то вы маеце 30 дзён ад моманту выдаленьнÑ, каб аднавіць Ñвой журнал. Праз 30 дзён мы выдалім журнал з нашых ÑÑрвераў. + +error.deleted.title=Выдалены рахунак + +error.expiredchal=ТÑрмін дзеÑÐ½ÑŒÐ½Ñ Ð²Ð°ÐºÐ½Ð° ўваходу ÑкончыўÑÑ. Калі лаÑка, паÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð·. + +error.invalidauth=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ быць аўтÑнтыфікаваны, Ñк вызначаны карыÑтальнік. + +error.ipbanned=Ваш IP-Ð°Ð´Ñ€Ð°Ñ Ð±Ñ‹Ñž чаÑова забаронены, з-за перавышÑÐ½ÑŒÐ½Ñ ÑžÐ·Ñ€Ð¾ÑžÐ½ÑŽ ўваходу. + +error.malformeduser=ДÑфармаванае Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка. + +error.nobutton=ÐÑ–Ð²Ð¾Ð´Ð½Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° не націÑнута? + +error.nodb=База зьвеÑтак чаÑова недаÑтупнаÑ. + +error.nodbmaintenance=ГÑÑ‚Ð°Ñ Ñ‡Ð°Ñтка базы зьвеÑтак знаходзіцца на абÑлугоўваньні. ПаÑпрабуйце ÑÑˆÑ‡Ñ Ñ€Ð°Ð· праз некалькі хвілін. + +error.noentry=ÐÑма такога журнальнага запіÑу. + +error.nojournal=ÐевÑдомы журнал + +error.noremote=Вам Ñ‚Ñ€Ñба ўвайÑьці, каб карыÑтацца гÑтай Ñтаронкай. + +error.procrequest=Па вашаму запыту ўзьнікла памылка: + +error.purged.name=Выдалены + +error.purged.text=ГÑÑ‚Ñ‹ журнал быў выдалены Ñ– зьнішчаны. + +error.purged.title=Зьнішчаны рахунак + +error.suspended.name=Прыпынены + +error.suspended.text=ГÑÑ‚Ñ‹ рахунак быў чаÑова ці назаўжды прыпынены. Калі вы [[user]], паглÑдзіце Пытаньні Ñ– адказы з назвай Мой рахунак быў прыпынены! Як атрымаць Ñго назад?, каб атрымаць больш інфармацыі. Заўважце, што па правілах прыватнаÑьці карыÑтальнікаў, [[sitename]] н можа абмÑркоўваць любое прыпыненьне з некім, Ð°ÐºÑ€Ð°Ð¼Ñ ÑžÐ»Ð°Ð´Ð°Ð»ÑŒÐ½Ñ–ÐºÐ° рахунку. + +error.suspended.title=Прыпынены рахунак + +error.tempdisabled=ГÑта чаÑова забаронена. + +error.unknownmode=ÐевÑдомы Ñ€Ñжым. + +error.usernameinvalid=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ўтрымлівае нÑÑÐ»ÑƒÑˆÐ½Ñ‹Ñ Ñымбалі. + +error.usernamelong=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка занадта доўгае, макÑымум - 15 ÑымбалÑÑž. + +error.username_notfound=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð°. + +Help=Дапамога + +label.screening.all=УÑе камÑнтары + +label.screening.anonymous=Толькі Ð°Ð½Ð°Ð½Ñ–Ð¼Ð½Ñ‹Ñ + +label.screening.default=Па змоўчаньні + +label.screening.header=ЗаÑланÑць камÑнтары: + +label.screening.none=ÐÑ–ÑÐºÑ–Ñ + +label.screening.nonfriends=Ðе-ÑÑброўÑÐºÑ–Ñ + +label.security.custom=Групы ÑÑброў... + +label.security.friends=СÑбры + +label.security.head=Узровень бÑÑьпекі: + +label.security.maintainers=Старшыні + +label.security.members=Удзельнікі + +label.security.private=Прыватны + +label.security.public=Грамадзкі + +label.switch.button=Пераключыць + +label.switch.header=Пераключыць журнал + +label.switch.workwith=Працаваць з журналам: + +langname.be=БеларуÑÐºÐ°Ñ + +langname.da=Ð”Ð°Ñ†ÐºÐ°Ñ + +langname.de=ÐÑÐ¼ÐµÑ†ÐºÐ°Ñ + +langname.en=ÐнгельÑÐºÐ°Ñ + +langname.en_GB=ÐнгельÑÐºÐ°Ñ (ВБр) + +langname.en_LJ=ÐнгельÑÐºÐ°Ñ + +langname.eo=ЭÑпÑранта + +langname.es=ГішпанÑÐºÐ°Ñ + +langname.et=ЭÑтонÑÐºÐ°Ñ + +langname.fi=ФінÑÐºÐ°Ñ + +langname.fr=ФранцуÑÐºÐ°Ñ + +langname.ga=ІрлÑÐ½Ð´Ð·ÐºÐ°Ñ + +langname.gd=ГаÑльÑÐºÐ°Ñ + +langname.he=Іўрыт + +langname.hi=Хіндзі + +langname.hu=ВугорÑÐºÐ°Ñ + +langname.is=ІÑлÑÐ½Ð´Ð·ÐºÐ°Ñ + +langname.it=ІтальÑнÑÐºÐ°Ñ + +langname.ja=ЯпонÑÐºÐ°Ñ + +langname.la=ЛацінÑÐºÐ°Ñ + +langname.lv=ЛатыÑÐºÐ°Ñ + +langname.ms=МалайÑÐºÐ°Ñ + +langname.nb=ÐарвÑÑÐºÐ°Ñ BokmÃ¥l + +langname.nl=ÐідÑрлÑÐ½Ð´Ð·ÐºÐ°Ñ + +langname.nn=ÐарвÑÑÐºÐ°Ñ Nynorsk + +langname.pl=ПольÑÐºÐ°Ñ + +langname.pt=ПартугальÑÐºÐ°Ñ + +langname.ru=РаÑейÑÐºÐ°Ñ + +langname.sv=ШвÑÐ´Ð·ÐºÐ°Ñ + +langname.tr=ТурÑÑ†ÐºÐ°Ñ + +langname.uk=УкраінÑÐºÐ°Ñ + +langname.zh=КітайÑÐºÐ°Ñ ÑÐ¿Ñ€Ð¾ÑˆÑ‡Ð°Ð½Ð°Ñ + +ljcom.account.feature=МажліваÑьць + +ljcom.account.feature.email=ÐÐ´Ñ€Ð°Ñ Ñл.пошты на LiveJournal + +ljcom.account.feature.full2=Ð”Ð·ÐµÐ»Ñ Ð¿Ð¾ÑžÐ½Ð°Ð¹ табліцы, глÑдзіце гÑтую Ñтаронку. + +ljcom.account.feature.limit=абмежавана + +ljcom.account.feature.ownblog=Ваш улаÑны журнал/вÑблог + +ljcom.account.feature.search=Пошук у Паказальніку + +ljcom.account.feature.styles=СтварÑньне/наладка ÑтылÑÑž + +ljcom.account.feature.syn=Зьбіральнік ÑÑброў Ñ– Ñындыкаваных Ñтужак + +ljcom.account.free=БÑÑплатны рахунак + +ljcom.account.paid=Платны рахунак + +ljcom.account.paid12=Платны на 12 меÑÑцаў ($25 USD) + +ljcom.account.paid2=Платны на 2 меÑÑцы ($5 USD) + +ljcom.account.paid6=Платны на 6 меÑÑцаў ($15 USD) + +ljcom.accounttype=Тып рахунку + +ljcom.badpass.email=Ваш пароль Ð½Ñ Ð¼Ð¾Ð¶Ð° быць заÑнаваны на вашым адраÑе Ñл.пошты. + +ljcom.badpass.realname=Ваш пароль Ð½Ñ Ð¼Ð¾Ð¶Ð° быць заÑнаваны на вашым Ñ€Ñальным іме. + +ljcom.badpass.username=Ваш пароль Ð½Ñ Ð¼Ð¾Ð¶Ð° быць заÑнаваны на вашым іме карыÑтальніка. + +ljcom.meetup.head=СуÑтракайцеÑÑŒ! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Міжнародны Дзень СуÑÑ‚Ñ€Ñч [[name]] + +ljcom.meetup.moreinfo=(Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Хочаце ÑуÑÑ‚Ñ€Ñць людзей у Ñ€Ñальным жыцьці з вашай мÑÑцоваÑьці, каб абмеркаваць гÑтую зацікаўленаÑьць? ГлÑдзіце [[link]]! + +ljcom.menu.upgrade=Палпшыце Ñвой рахунак + +ljcom.userinfo.accounttype=Тып рахунку + +ljcom.userinfo.paiduser=Платны карыÑтальнік + +ljcom.userinfo.types.early=Раньні ўдзельнік + +ljcom.userinfo.types.free=БÑÑплатны рахунак + +ljcom.userinfo.types.paid=Платны рахунак + +ljcom.userinfo.types.paid_early=Платны рахунак, да таго Раньні ўдзельнік + +ljcom.userinfo.types.paid_early_expiring=Платны рахунак, Ñкончыцца [[paiduntil]], да таго Раньні ўдзельнік + +ljcom.userinfo.types.paid_expiring=Платны рахунак, Ñкончыцца [[paiduntil]] + +ljcom.userinfo.types.permanent=Сталы рахунак + +ljcom.userinfo.types.permanent_early=Сталы рахунак, да таго Раньні ўдзельнік + +ljlib.pageofpages=Старонка [[page]] з [[total]] + +lostinfo.head=Забылі нешта? + +lostinfo.text=Калі вы забылі Ñваё Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка ці пароль, узнавіце Ñ–Ñ… тут. + +lynx.nav.friends=СÑбры + +lynx.nav.help=ТÑÑ…Ð½Ñ–Ñ‡Ð½Ð°Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÐ° + +lynx.nav.home=Дадому + +lynx.nav.login=Уваход + +lynx.nav.logout=Выхад + +lynx.nav.recent=ÐÐ¿Ð¾ÑˆÐ½Ñ–Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +lynx.nav.sitemap=Мапа Ñайту + +lynx.nav.siteopts=Опцыі праглÑду + +lynx.nav.update=Зрабіць Ð·Ð°Ð¿Ñ–Ñ + +Password=Пароль + +password.max30=Паролі Ð½Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ быць даўжÑй за 30 ÑымбалÑÑž. + +poll.dberror=Памылкі базы зьвеÑтак: [[errmsg]] + +poll.dberror.items=Памылка базы зьвеÑтак пры ÑžÑтаўленьні пунктаў: [[errmsg]] + +poll.dberror.questions=Памылка базы зьвеÑтак пры ÑžÑтаўленьні пытаньнÑÑž: [[errmsg]] + +poll.error.badmaxlength=Ðтрыбут maxlength у Ñ‚ÑкÑтвых Ñ‚Ñгах на lj-pq павінен быць цÑлы лік паміж 1-255. + +poll.error.badsize=Ðтрыбут size у Ñ‚ÑкÑтвых Ñ‚Ñгах на lj-pq павінен быць цÑлы лік паміж 1-255. + +poll.error.cantview=Памылка: вы Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ доÑтупу, каб праглÑдзець вынікі гÑтага апытаньнÑÑž. + +poll.error.cantvote=Выбачайце, вы Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў Ð´Ð»Ñ ÑžÐ´Ð·ÐµÐ»Ñƒ Ñž гÑтым аÑобным апытаньні. + +poll.error.missingljpoll=УÑе Ñ‚Ñгі lj-pq павінны меÑьціцца паміж Ñ‚Ñгам lj-poll. + +poll.error.missingljpq=УÑе Ñ‚Ñгі lj-pi павінны меÑьціцца паміж Ñ‚Ñгам lj-pq. + +poll.error.nested=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ разьмеÑьціць Ñ‚Ñг [[tag]]. Ð’Ñ‹ забылі закрыць нейкі Ñ‚Ñг? + +poll.error.noentry=Памылка: гÑтае апытаньне не дапаÑавана да гÑтага журнальнага запіÑу + +poll.error.noitems=Ð’Ñ‹ павінны мець Ñ…Ð°Ñ†Ñ Ð±Ñ‹ адзін пункт у нÑÑ‚ÑкÑтавым пытаньні апытаньнÑ. + +poll.error.noitemstext=Ñ‚Ñгі lj-pq тыпу 'Ñ‚ÑкÑÑ‚' Ð½Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ утрымліваць пункты апытаньнÑ. + +poll.error.nopollid=адÑутнічае парамÑÑ‚Ñ€ pollid + +poll.error.noquestions=У вашым апытаньне павінна быць Ñ…Ð°Ñ†Ñ Ð±Ñ‹ адно пытаньне. + +poll.error.notext=ПатрÑбны Ñ‚ÑкÑÑ‚ у Ñ‚Ñгу lj-pq, каб Ñказаць пра што пытаньне. + +poll.error.pitoolong=ТÑкÑÑ‚ у Ñ‚Ñгу lj-pi павінен быць даўжынёй ад 1 да 255 ÑымбалÑÑž. Ð’Ð°ÑˆÐ°Ñ - [[len]]. + +poll.error.pollnotfound=Памылка: апытаньне #[[num]] Ð½Ñ Ð·Ð½Ð¾Ð¹Ð´Ð·ÐµÐ½Ð° + +poll.error.questionnotfound=Памылка: гÑтае пытаньне не Ñ–Ñнуе Ñž апытаньні. + +poll.error.scalefromlessto=ЗначÑньне 'ад' павінна быць меней, чым значÑньне 'да'. + +poll.error.scaleincrement=Крок шкалы павінен быць Ñ…Ð°Ñ†Ñ Ð±Ñ‹ 1. + +poll.error.scaletoobig=Ð’Ð°ÑˆÐ°Ñ ÑˆÐºÐ°Ð»Ð° перавышае ліміт 20 выбараў (да-ад)/на > 20. + +poll.error.tagnotopen=Ð’Ñ‹ Ð½Ñ Ð¼Ð¾Ð¶Ð°Ñ†Ðµ закрыць неадкрыты Ñ‚Ñг [[tag]] + +poll.error.truncated=... абрÑзана + +poll.error.unknownpqtype=ÐевÑдомы тып Ñ‚Ñгу lj-pq + +poll.error.unlockedtag=Ðезачынены Ñ‚Ñг [[tag]]. + +poll.error.whoview=whoview павінен быць 'уÑе', 'ÑÑбры' ці 'ніхто'. + +poll.error.whovote=whovote павінен быць 'уÑе' ці 'ÑÑбры'. + +poll.pollnum=Ðпытаньне #[[num]] + +poll.scaleanswers=СÑÑ€ÑднÑе: [[mean]] МедыÑна: [[median]] СÑÑ€ÑднÑе квадратовае адхіленьне [[stddev]] + +poll.security=Ðдкрыты длÑ: [[whovote]], вынікі Ð±Ð°Ñ‡Ð½Ñ‹Ñ Ð´Ð»Ñ: [[whoview]] + +poll.security.all=УÑе + +poll.security.friends=СÑбры + +poll.security.none=Ðіхто + +poll.submit=Падаць апытаньне + +poll.viewanswers=ПраглÑд адказаў + +portal.bdays.count.des=Па змоўчаньні, паказваюцца 5 ÑÑброў з найбліжÑйшымі днÑмі нараджÑньнÑ. + +portal.bdays.count.name=Паказваць дні нараджÑÐ½ÑŒÐ½Ñ + +portal.bdays.portalname=Дні нараджÑÐ½ÑŒÐ½Ñ + +portal.bdays.portaltitle=Дні нараджÑÐ½ÑŒÐ½Ñ + +portal.goat.name=Сымбаль Ñайту + +portal.goattext.des=Што вы хочаце, каб казаў ваш казёл? Казёл можа казаць толькі адну Ñ€Ñч 'Мееее', але вы можаце ÑžÑвіць, што ваш казёл можа казаць нешта іншае. + +portal.goattext.name=ТÑкÑÑ‚ казла + +portal.login.portalname=Поле ўваходу + +portal.memories.entriesnoun=запіÑÑ‹ + +portal.memories.entrynoun=Ð·Ð°Ð¿Ñ–Ñ + +portal.memories.portalname=Ð—Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +portal.memories.portaltitle=Ð—Ð°Ð¿Ð°Ð¼Ñ–Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +portal.ministats.active=ÐктыўныÑ: + +portal.ministats.title=СтатыÑтыка карыÑтальнікаў + +portal.ministats.total=УÑÑго: + +portal.misbehaved.des=Ð’Ñ‹ Ñапраўды хочаце пакінуць гÑта неадзначаным. Казлы, ÑÐºÑ–Ñ Ð½Ðµ натрÑніраваныÑ, Ð½Ñ Ð±Ð¾Ð»ÑŒÑˆ, чым праблема. + +portal.misbehaved.name=ДрÑнны казёл + +portal.newtolj.name=СпаÑылкі Ñайту + +portal.popfaq.portalname=10 Ñамых папулÑрных ПытаньнÑÑž Ñ– адказаў + +portal.popfaq.portaltitle=10 Ñамых папулÑрных ПытаньнÑÑž Ñ– адказаў + +portal.randuser.count.des=Па змоўчаньні, паказваецца толькі 1 карыÑтальнік, але вы можаце мець да 10 у вузкіх калёнках, ці да 5 у шырокай + +portal.randuser.count.name=Паказваць выпадковых карыÑтальнікаў + +portal.randuser.error.tableempty=ÐÑма выпадковых карыÑтальнікаў. ЗьвÑртайцеÑÑ Ð´Ð° адмініÑтратара. + +portal.randuser.hidename.des=Па змоўчаньні паказваецца Ñ–Ð¼Ñ Ð²Ñ‹Ð¿Ð°Ð´ÐºÐ¾Ð²Ð°Ð³Ð° карыÑтальніка. Ðдзначце тут, каб не паказваць. + +portal.randuser.hidename.name=Схаваць Ñ–Ð¼Ñ + +portal.randuser.hidepic.des=Па змоўчаньні паказваецца малюнак выпадковага карыÑтальніка, калі ён Ñ–Ñнуе. Ðдзначце тут, каб не паказваць. + +portal.randuser.hidepic.name=Схаваць малюнак карыÑтальніка + +portal.randuser.portalname=Выпадковы карыÑтальнік + +portal.randuser.portaltitle=Выпадковы карыÑтальнік + +portal.randuser.portaltitleplural=Ð’Ñ‹Ð¿Ð°Ð´ÐºÐ¾Ð²Ñ‹Ñ ÐºÐ°Ñ€Ñ‹Ñтальнікі + +portal.recent.error.noentries=Выбачайце. ÐÑма запіÑаў. + +portal.recent.error.notsetup=Ð’Ñ‹ Ñ‚Ñ€Ñба наладзіць гÑтае поле. ÐаціÑьніце Ñымбаль плюÑу, каб наладзіць журнал, Ñкі вы хочаце тут бачыць. + +portal.recent.error.userstatus=КарыÑтальнік выдаліў ці прыпыніў Ñвой рахунак. + +portal.recent.items.description=Па змоўчаньні паказваецца толькі Ñамы апошні запіÑ. + +portal.recent.items.name=Паказваць пункты + +portal.recent.journal.description=З Ñкога журналу вы хочаце бачыць Ð°Ð¿Ð¾ÑˆÐ½Ñ–Ñ Ð¿ÑƒÐ½ÐºÑ‚Ñ‹? + +portal.recent.journal.name=Журнал + +portal.recent.nosubject=(ÐÑма Ñ‚Ñмы) + +portal.recent.permlink=СпаÑылка + +portal.recent.portalname=ПраглÑд апошнÑга запіÑу + +portal.recent.portaltitle=Поле апошнÑга запіÑу + +portal.recent.showtext.description=Па змоўчаньні будуць паказаны толькі Ñ‚Ñмы. + +portal.recent.showtext.name=Уключаць Ñ‚ÑкÑÑ‚ + +portal.stats.journalentyest=Ð£Ñ‡Ð¾Ñ€Ð°ÑˆÐ½Ñ–Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ + +portal.stats.portalname=СтатыÑтыка Ñайту + +portal.stats.portaltitle=СтатыÑтыка + +portal.stats.totalusers=УÑÑго карыÑтальнікаў + +portal.update.mode.des=Поўны Ñ€Ñжым дае Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð¾Ð¿Ñ†Ñ‹Ñ Ð·Ð°Ð¿Ñ–Ñу... уключае запіÑÑ‹ Ñž Ñуполкі, бÑгучы наÑтрой, музыку Ñ– малюнак. Звычайны Ñ€Ñжым праÑьцей, але вы Ð½Ñ Ð·Ð¼Ð¾Ð¶Ð°Ñ†Ðµ карыÑтацца ÑžÑімі мажліваÑьцÑмі Ñ– нават Ð½Ñ ÑžÐ±Ð°Ñ‡Ñ‹Ñ†Ðµ Ñ–Ñ…. + +portal.update.mode.full=Поўны + +portal.update.mode.name=РÑжым + +portal.update.mode.simple=Звычайны + +portal.update.portalname=Ðбнаўленьне журналу + +portal.update.portaltitle=Ðбнавіць ваш журнал + +protocol.bad_password=Ваш пароль можна лёгка вызначыць. Мы Ñ€Ñкамендуем вам зьмÑніць Ñго, бо вы рызыкуеце, што ваш журнал будзе захоплены. Ðаведайце [[siteroot]]/changepassword.bml , каб зьмÑніць пароль. + +protocol.hello_test=Прывітаньне, Ñ‚ÑÑтавы рахунак! + +protocol.mail_bouncing=У Ð²Ð°Ñ Ð¿Ð°Ð·Ð½Ð°Ñ‡Ð°Ð½Ñ‹ неіÑнуючы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. УÑе ліÑÑ‚Ñ‹, што мы вам даÑылаем, не даходзÑць. [[sitename]] патрабуе Ñапраўдага адраÑу Ñл.пошты Ð´Ð»Ñ Ñталага карыÑтаньнÑ. Ðаведайце [[siteroot]]/support/faqbrowse.bml?faqid=19 , каб даведацца, Ñк зьмÑніць Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. + +protocol.modpost=Ваш Ð·Ð°Ð¿Ñ–Ñ Ð´Ð°Ð±Ð°ÑžÐ»ÐµÐ½Ñ‹ Ñž чаргу мадÑраваньнÑ. Ðн будзе прынÑÑ‚Ñ‹ ці адмоўлены адным Ñа ÑтаршынÑÑž Ñуполкі. + +protocol.must_revalidate<< +Ð’Ñ‹ павінны пацьвердзіць ваш новы Ð°Ð´Ñ€Ð°Ñ Ñл.пошты. Ваш Ñтары Ð°Ð´Ñ€Ð°Ñ Ð±Ñ‹Ñž добры, але вы Ñго зьмÑнілі, таму Ñ‚Ñ€Ñба пацьвердзіць новы адраÑ. Калі вы не пацьвердзіце ваш адраÑ, вы Ð½Ñ Ð±ÑƒÐ´Ð·ÐµÑ†Ðµ мець доÑтуп да ÑžÑÑ–Ñ… функцыÑÑž [[sitename]]. ГлÑдзіце [[siteroot]]/support/faqbrowse.bml?faqid=11 Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі. + +. + +protocol.not_validated<< +Ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты Ð½Ñ Ð±Ñ‹Ñž пацьверджаны. Ð’Ñ‹ можаце працÑгнуць карыÑтацца [[sitename]], але калі вы не пацьвердзіце ваш Ð°Ð´Ñ€Ð°Ñ Ñл.пошты, вы Ð½Ñ Ð±ÑƒÐ´Ð·ÐµÑ†Ðµ мець доÑтуп да ÑžÑÑ–Ñ… функцыÑÑž Ñайту. ГлÑдзіце інÑтрукцыі, што мы даÑлалі вам, калі вы Ñтварылі ваш журнал, ці наведайце [[siteroot]]/support/faqbrowse.bml?faqid=11 Ð´Ð»Ñ Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ð¹ інфармацыі. + +. + +protocol.old_win32_client=ЦÑпер даÑтупны значна Ð½Ð°Ð²ÐµÐ¹ÑˆÑ‹Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹-кліенты Жывога Журнала пад Windows, Ñ– мы Ñ€Ñкамендуем вам абнавіць вашую. Ðаведайце [[siteroot]]/download/ , каб ÑьцÑгнуць новую праграму-кліент. + +protocol.readonly=Ваш рахунак чаÑова даÑтупны толькі Ð´Ð»Ñ Ñ‡Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ. УÑе дзеÑньні Ð½ÐµÐ¼Ð°Ð³Ñ‡Ñ‹Ð¼Ñ‹Ñ Ð½Ð° працÑгу некалькіх хвілін. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Выбачайце + +talk.anonwrote=Ðехта напіÑаў, + +talk.anonwrote_comm=Ðехта напіÑаў у [[commlink]], + +talk.btn.preview=ПерадпраглÑд + +talk.commentpermlink=ÑпаÑылка + +talk.commentpost=Зрабіць новы камÑнтар + +talk.commentsread=Чытаць камÑнтары + +talk.curname_Mood=БÑгучы наÑтрой: + +talk.curname_Music=БÑÐ³ÑƒÑ‡Ð°Ñ Ð¼ÑƒÐ·Ñ‹ÐºÐ°: + +talk.error.bogusargs=ÐеÑÐ°Ð¿Ñ€Ð°ÑžÐ´Ð½Ñ‹Ñ Ð°Ñ€Ð³ÑƒÐ¼Ñнты + +talk.error.comm_deleted=ГÑÑ‚Ñ‹ камÑнтар быў выдалены. + +talk.error.deleted=ГÑÑ‚Ñ‹ журнал выдалены. + +talk.error.deleted.title=Выдалены + +talk.error.mustlogin=Ð’Ñ‹ павінны ўвайÑьці, каб праглÑдзець гÑÑ‚Ñ‹ абаронены запіÑ. + +talk.error.nocomment=КамÑнтар не Ñ–Ñнуе. + +talk.error.noentry=ÐÑма такога запіÑу. + +talk.error.nojournal=Памылка: немагчыма вызначыць журнал па аргумÑнтах. + +talk.error.nosuchjournal=ÐÑма такога журналу + +talk.error.notauthorised=Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб праглÑдзець гÑÑ‚Ñ‹ абаронены запіÑ. + +talk.error.suspended=ГÑÑ‚Ñ‹ журнал ці карыÑтальнік прыпынены. + +talk.error.suspended.title=Прыпынены + +talk.parentlink=БацькоўÑкі + +talk.readsimilar=Чытаць Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹: + +talk.replytothis=Ðдказаць на гÑта + +talk.somebodywrote=[[realname]] ([[userlink]]) напіÑаў(-ла), + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) напіÑаў(-ла) у [[commlink]], + +talk.spellcheck=Праверыць артаграфію Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿ÐµÑ€Ð°Ð´Ð¿Ñ€Ð°Ð³Ð»Ñду (толькі ангельÑÐºÐ°Ñ Ð¼Ð¾Ð²Ð°). + +talk.threadlink=Галіна + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_belarusian + +Username=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка + +userpic.inactive=Ðе актыўна + +xcolibur.greeting.anon=Запрашаем у Жывы Журнал! + +xcolibur.greeting.logged_in=Вітаем, [[name]]! [[logout]] + +xcolibur.login=УвайÑьці? + +xcolibur.logout=ВыйÑьці? + +xcolibur.nav.about=Пра + +xcolibur.nav.about.download=СьцÑгнуць + +xcolibur.nav.about.general=ÐÐ³ÑƒÐ»ÑŒÐ½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +xcolibur.nav.about.paidaccounts=ÐŸÐ»Ð°Ñ‚Ð½Ñ‹Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÑ– + +xcolibur.nav.about.press=ПрÑÑа + +xcolibur.nav.about.sitenews=Ðавіны Ñайту + +xcolibur.nav.about.stats=СтатыÑтыка + +xcolibur.nav.footer.sitemap=Мапа Ñайту + +xcolibur.nav.help=Дапамога + +xcolibur.nav.help.ask=Спытай + +xcolibur.nav.help.contact=Кантакты + +xcolibur.nav.help.faq=Пытаньні Ñ– адказы + +xcolibur.nav.help.lostpassword=Згублены пароль + +xcolibur.nav.home=Дадому + +xcolibur.nav.journal=Журнал + +xcolibur.nav.journal.archive=Ðрхіў + +xcolibur.nav.journal.edit.entries=РÑдагаваць запіÑÑ‹ + +xcolibur.nav.journal.friends=СÑбры + +xcolibur.nav.journal.info=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +xcolibur.nav.journal.memories=УÑпаміны + +xcolibur.nav.journal.recent=ÐпошнÑе + +xcolibur.nav.journal.update=Зрабіць Ð·Ð°Ð¿Ñ–Ñ + +xcolibur.nav.manage=РÑдагаваньне + +xcolibur.nav.manage.community=Суполкі + +xcolibur.nav.manage.customize=Ðаладкі + +xcolibur.nav.manage.entries=ЗапіÑÑ‹ + +xcolibur.nav.manage.friends=СÑбры + +xcolibur.nav.manage.info=Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ + +xcolibur.nav.manage.password=Пароль + +xcolibur.nav.manage.pics=Ð’Ñ‹Ñвы + +xcolibur.nav.manage.styles=Стылі + +xcolibur.nav.search=Пошук + +xcolibur.nav.search.directory=РÑгіён + +xcolibur.nav.search.directory.search=Пашыраны + +xcolibur.nav.search.interests=ЗацікаўленаÑьці + +xcolibur.nav.search.random=Выпадковы + +xcolibur.nav.siteopts=Опцыі праглÑду + +xcolibur.nav.title=ÐавігацыÑ: + +xcolibur.nav.welcome=Запрашаем + +xcolibur.nav.welcome.create=Стварыць рахунак + +xcolibur.nav.welcome.login=УвайÑьці + +xcolibur.nav.welcome.update=Ðбнавіць ваш журнал + +xcolibur.search=Пошук: + +xcolibur.search.category=КатÑгорыÑ: + +xcolibur.search.icq=Ðумар ICQ + +xcolibur.search.int=ЗацікаўленаÑьць + +xcolibur.search.msn=Ð†Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка MSN + +xcolibur.search.region=РÑгіён + +xcolibur.upgrade=Палепшыць Ñвой рахунак + diff --git a/ljcom/bin/upgrading/da.dat b/ljcom/bin/upgrading/da.dat new file mode 100644 index 0000000..89fe93a --- /dev/null +++ b/ljcom/bin/upgrading/da.dat @@ -0,0 +1,2906 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Hvis du vil slette eller genskabe din journal, sÃ¥ er det her du gør det. Fra du har slettet din journal har du 30 dage til at genskabe den, hvis nu du skulle skifte mening. NÃ¥r de 30 dage er gÃ¥et vil din journal blive slettet permanent, uden nogen mÃ¥de hvormed den kan blive genskabt. + +/accountstatus.bml.journalstatus.head=Journal aktiverings status + +/accountstatus.bml.journalstatus.select.activated=Aktiveret + +/accountstatus.bml.journalstatus.select.deleted=Slettet + +/accountstatus.bml.journalstatus.select.suspended=Suspenderet + +/accountstatus.bml.title=Kontostatus + +/allpics.bml.current=Nuværende billeder + +/allpics.bml.default=Standard + +/allpics.bml.edit2=Du kan være interesseret i at redigere nøgleordene til dine billeder eller i at uploade et nyt billede. + +/allpics.bml.error.noparam=Du skal angive en brugerparameter. + +/allpics.bml.keywords=Nøgleord: + +/allpics.bml.nopics.text.other=Denne bruger har ikke uploadet nogen brugerbilleder. + +/allpics.bml.nopics.text2=Du har ikke uploadet nogen billeder. Klik her for at uploade et. + +/allpics.bml.nopics.title=Ingen billeder + +/allpics.bml.pics=Her er de brugerbilleder der tilhører [[user]]. + +/allpics.bml.title=Brugerbilleder + +/approve.bml.comm.success=Succes + +/approve.bml.comm.text<< +Du er blevet tilføjet til [[comm]]. +Klike her for at tilføje gruppen til din venneliste. +. + +/approve.bml.error.actionperformed=Denne handling er allerede blevet udført. + +/approve.bml.error.internerr.invalidaction=Intern fejl: Ugyldig handling + +/approve.bml.error.invalidargument=Ugyldigt argument angivet + +/approve.bml.error.unknownactiontype=Ukendt handlingstype + +/approve.bml.shared.success=Succes + +/approve.bml.shared.text<< +Du har fÃ¥et posteadgang til [[shared]]. +Klik her for at tilføje den delte journal til din venneliste. +. + +/approve.bml.title=Godkend handling + +/changepassword.bml.btn.proceed=Fortsæt + +/changepassword.bml.changepassword.header=Skift kodeord + +/changepassword.bml.changepassword.instructions=Udfyld formlen nedenfor for at ændre dit kodeord. Se eventuelt dette OSS for hjælp til at vælge et godt kodeord og til at holde din konto sikker. + +/changepassword.bml.email.body<< +Dit kodeord pÃ¥ [[sitename]] er blevet ændret. + +GÃ¥ til nedenstÃ¥ende side for at genfinde det i fremtiden: + + [[siteroot]]/lostinfo.bml + +Med venlig hilsen, +[[sitename]] Holdet + +[[siteroot]] +. + +/changepassword.bml.email.subject=Ændring af kodeord + +/changepassword.bml.error.badcheck=DÃ¥rligt nyt kodeord: [[error]] + +/changepassword.bml.error.badnewpassword=Bekræftelsen af dit nye kodeord passer ikke til det du skrev som dit nye kodeord. Du kan have lavet en fejl i skrivningen af det. Prøv venligst at skrive og bekræfte dit nye kodeord igen. + +/changepassword.bml.error.badoldpassword=Dit gamle kodeord er ikke rigtigt. + +/changepassword.bml.error.blankpassword=Dit nye kodeord kan ikke være tomt. + +/changepassword.bml.error.changetestaccount=Testkontoens kodeord kan ikke blive ændret. + +/changepassword.bml.error.characterlimit=Kodeord er begrænset til et maksimum pÃ¥ 30 tegn. + +/changepassword.bml.error.invaliduser=Ugyldig bruger [[user]]. Denne bruger eksisterer ikke. Er du sikker pÃ¥ det er skrevet rigtigt? + +/changepassword.bml.error.mustenterusername=Du skal skrive dit brugernavn. + +/changepassword.bml.error.nonascii=Kodeord er begrænset til ASCII-tegn. Vælg venligst et kodeord der ikke bruger ikke-ASCII-tegn. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Du kan ikke ændre dit kodeord hvis din nuværende emailadresse ikke er blevet bekræftet. + +/changepassword.bml.newpassword=Nyt kodeord: + +/changepassword.bml.newpasswordagain=Nyt kodeord (igen): + +/changepassword.bml.oldpassword=Gammelt kodeord: + +/changepassword.bml.proceed.instructions=Klik pÃ¥ knappen nedenfor for at ændre dit kodeord. Du vil modtage en email der fortæller om ændringen. + +/changepassword.bml.success.text=Dit kodeord er blevet ændret og en email med en pÃ¥mindelse herom er blevet sendt til dig. + +/changepassword.bml.title=Skift kodeord + +/community/index.bml.title=Gruppe Center + +/community/join.bml.button.join=Tilmeld gruppe + +/community/join.bml.label.addtofriends=Tilføj "[[maintainer]]" til venneliste.
    + +/community/join.bml.label.allowposting=Denne gruppe tillader postning fra samtlige medlemmer, så du har nu adgang til at poste til det. Hvis du allerede har en LiveJournal klient åben på din computer bliver du nødt til at logge ud og logge ind igen for at denne gruppe vil blive vist på din liste over journaler du kan poste i. + +/community/join.bml.label.auth=Selvom du nu er listet som medlem, tillader dette samfund kun autoriserede brugere at poste i det. Kontakt en af vedligeholderne hvis du ønsker adgang til at poste. Listen over vedligholdere for dette samfund er vist nedenfor: [[admins]] + +/community/join.bml.label.banned=Vedligeholderen(-erne) af samfundet har bandlyst dig fra at blive medlem. + +/community/join.bml.label.closed=Dette samfund er lukket. Kontakt en af dets vedligeholdere hvis du er interesseret i at blive medlem af det. Listen over vedligholdere for dette samfund er vist nedenfor: [[admins]] + +/community/join.bml.label.commlogged=Du er logget ind som en delt/gruppekonto, ikke din personlige konto. + +/community/join.bml.label.errorcomminfo=Den angivne gruppeinformation er ikke gyldig. + +/community/join.bml.label.expls=Klik på knappen nedenfor for at blive medlem af "[[maintainer]]" gruppen. Afkryds boksen forneden hvis du vil være medlem af gruppen uden at se gruppens poster på din venneside. + +/community/join.bml.label.loginfirst=Du skal først logge ind før du kan blive medlem af en gruppe. + +/community/join.bml.label.membernow=Du er nu medlem af [[commname]] Gruppen + +/community/join.bml.label.sure=Er du sikker? + +/community/join.bml.success=Succes + +/community/join.bml.title=Tilmeld gruppe + +/community/leave.bml.button.leave=Forlad gruppe + +/community/leave.bml.label.buttontoleave=Klik på knappen nedenfor for at forlade "[[commname]]" gruppen. + +/community/leave.bml.label.infoerror=Den angivne gruppeinformation er ikke gyldig. + +/community/leave.bml.label.logoutfirst=Du skal først logge ind før du kan forlade en gruppe. + +/community/leave.bml.label.removed=Du er nu fjernet fra [[commname]] Gruppen + +/community/leave.bml.label.removefromfriends=Fjern også "[[user]]" fra vennelisten. + +/community/leave.bml.success=Succes + +/community/leave.bml.sure=Er du sikker? + +/community/leave.bml.title=Forlad gruppe + +/community/manage.bml.commlist.actions=Funktioner + +/community/manage.bml.commlist.actmembers=[Medlemmer] + +/community/manage.bml.commlist.actmembers2=Medlemmer + +/community/manage.bml.commlist.actsettings=[Indstillinger] + +/community/manage.bml.commlist.actsettings2=Indstillinger + +/community/manage.bml.commlist.header=Dine grupper + +/community/manage.bml.commlist.none=Du administrerer ikke nogle grupper. + +/community/manage.bml.commlist.text=Her er de grupper du administrerer eller med-administrerer: + +/community/manage.bml.commlist.title=Titel + +/community/manage.bml.commlist.username=Brugernavn + +/community/manage.bml.create.header=Lav en gruppe + +/community/manage.bml.create.text=Du kan også lave en ny gruppe. + +/community/manage.bml.title=Gruppeadministration + +/community/members.bml.error.noaccess=Kun samfundsvedligeholdere kan redigere medlemsskabslister. Du er ikke vedligeholder af samfundet [[comm]]. + +/community/members.bml.error.nocomm=Gruppe ikke fundet. + +/community/members.bml.key.admin=Vedligeholder + +/community/members.bml.key.member=Medlem + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post|staleness=2 +/community/members.bml.key.post=Kan poste + +/community/members.bml.key.preapprove=Umodereret + +/community/members.bml.manage2=Administrer grupper + +/community/members.bml.name=Gruppenavn: [[name]] + +/community/members.bml.nextlink=(Næste side...) + +/community/members.bml.prevlink=(Forrige side...) + +/community/members.bml.settings=[Indstillinger] + +/community/members.bml.success.header=Succes + +/community/members.bml.success.message=Dine ændringer er blevet succesfuldt gemt. + +/community/members.bml.success.return=Tilbage til listen + +/community/members.bml.title=Gruppemedlemmer + +/community/members.bml.update=Opdater indstillinger + +/community/moderate.bml.approve.button=Ja, godkend den + +/community/moderate.bml.approve.header=Godkend denne post? + +/community/moderate.bml.approve.preapprove=Tilføj iøvrigt brugeren [[user]] til listen over forhåndsgodkendte brugere i denne gruppe. + +/community/moderate.bml.approve.text=Er du sikker på du vil godkende denne post? + +/community/moderate.bml.browse.empty=Modereringskøen er tom. + +/community/moderate.bml.browse.header=Moderer gruppe + +/community/moderate.bml.browse.text=Her er de poster der mangler at blive modereret i gruppen [[link]] + +/community/moderate.bml.choice.approve=Godkend + +/community/moderate.bml.choice.reject=Afvis + +/community/moderate.bml.error.noaccess=Du er ikke moderator for gruppen [[comm]]. + +/community/moderate.bml.error.noentry=Post ikke fundet (kan allerede være håndteret af en anden moderator). + +/community/moderate.bml.error.nolist=Du er ikke moderator for nogle grupper. + +/community/moderate.bml.error.notfound=Gruppekonto ikke fundet. + +/community/moderate.bml.manage=Administrer grupper + +/community/moderate.bml.moderate=Moderer denne gruppe + +/community/moderate.bml.modlist.actions=Handlinger + +/community/moderate.bml.modlist.actmodempty=[Moderer] + +/community/moderate.bml.modlist.actmoderate=Moderer + +/community/moderate.bml.modlist.count=Kø størrelse + +/community/moderate.bml.modlist.header=Moderer grupper + +/community/moderate.bml.modlist.title=Titel + +/community/moderate.bml.modlist.username=Brugernavn + +/community/moderate.bml.posted.header=Succes + +/community/search.bml.button.clear=Ryd Formular + +/community/search.bml.button.search=Søg! + +/community/search.bml.checkbox.onlywithpics=Kun grupper med billeder + +/community/search.bml.label.byinterest=Efter Interesse + +/community/search.bml.label.bylocation=Efter Sted + +/community/search.bml.label.bytime=Efter Journal Opdaterings Tid + +/community/search.bml.label.city=By: + +/community/search.bml.label.country=Land: + +/community/search.bml.label.displayoptions=Visnings Indstillinger + +/community/search.bml.label.hasmember=Har Medlem + +/community/search.bml.label.othercriteria=Andre Kriterier + +/community/search.bml.label.outputformat=Uddata Format: + +/community/search.bml.label.sortmethod=Sorteringsmetode: + +/community/search.bml.label.stateprovince=Stat/Provins: + +/community/search.bml.label.updated=Opdateret indenfor den seneste + +/community/search.bml.sel.bypicture=Efter Billede + +/community/search.bml.sel.communityname=Gruppenavn + +/community/search.bml.sel.day=dag + +/community/search.bml.sel.month=måned + +/community/search.bml.sel.simple=Simpel + +/community/search.bml.sel.updatetime=Opdaterings Tid + +/community/search.bml.sel.username=Brugernavn + +/community/search.bml.sel.week=uge + +/community/search.bml.title=Gruppesøgning + +/community/settings.bml.button.changecommunity=Opdater Indstillinger + +/community/settings.bml.button.createcommunity=Lav gruppe + +/community/settings.bml.error.badpassword=Ugyldigt gruppekodeord + +/community/settings.bml.error.maintainertype=Vedligeholderkonto skal være en person, ikke en anden delt konto. + +/community/settings.bml.error.noaccess=Kun samfundsvedligeholdere kan redigere samfundsindstillinger. Du er ikke vedligeholder af samfundet [[comm]]. + +/community/settings.bml.error.notcomm=Ikke en gruppekonto. + +/community/settings.bml.error.notfound=Gruppekonto ikke fundet. + +/community/settings.bml.error.samenames=Vedligeholderkonto og samfundskonto kan ikke være den samme. + +/community/settings.bml.label.anybodycan=Alle Medlemmer
    Alle kan poste så snart de er blevet medlem. + +/community/settings.bml.label.changeheader=Skift gruppeindstillinger + +/community/settings.bml.label.changetext=Her kan du ændre på indstillingerne for de samfund som du ejer eller vedligeholder. + +/community/settings.bml.label.commchanged=Dine gruppeindstillinger er ændret. + +/community/settings.bml.label.commcreate=Dette er kontoen som du vil lave om til en gruppe. Den skal allerede være lavet, men bør ikke være brugt af en enkeltperson da der vil være masser af forskellige folk der muligvis vil være i stand til at poste i den efter dette. + +/community/settings.bml.label.commcreated=Din gruppe er nu sat op. + +/community/settings.bml.label.commheader=Gruppekonto + +/community/settings.bml.label.comminfo=Gruppeinfo + +/community/settings.bml.label.commopts=Gruppeindstillinger + +/community/settings.bml.label.commsite=Gruppens websted + +/community/settings.bml.label.createheader=Lav gruppe + +/community/settings.bml.label.createtext=Herfra kan du lave en samfundskonto. Et samfund er en speciel kontotype som andre bruger kan blive medlem af og poste i. Et eksempel på et smafund kunne være Seattle Fest Samfundet. + +/community/settings.bml.label.howoperates=Bestem hvordan din gruppe skal fungere. Du kan ændre dette senere. + +/community/settings.bml.label.membership=Medlemskab + +/community/settings.bml.label.nmcan=Ikke-Medlemmer Kan Poste
    Brugere kan poste til dette samfund uden at skulle være medlem. + +/community/settings.bml.label.nmcant=Ikke-Medlemmer Kan Ikke Poste
    Brugere skal være medlem før de kan poste til samfundet. + +/community/settings.bml.label.nmheader|staleness=1 +/community/settings.bml.label.nmheader=Ikke-Medlems Postning + +/community/settings.bml.label.nmtext=Kan brugere poste til denne gruppe uden at være medlem? + +/community/settings.bml.label.openmemb=Åbent Medlemskab
    Alle kan tilmelde sig uden at skulle godkendes. + +/community/settings.bml.label.password=Kodeord: + +/community/settings.bml.label.rellinks=Relevante links: + +/community/settings.bml.label.selcan=Udvalgte Medlemmer
    Kun nogle medlemmer kan poste, efter de har fået adgang af vedligeholderkontoen.. + +/community/settings.bml.label.username=Brugernavn: + +/community/settings.bml.label.whocanjoin=Hvem kan blive medlem af din gruppe? + +/community/settings.bml.label.whocanpost=Hvem kan poste til denne gruppe? + +/community/settings.bml.members=[Medlemmer] + +/community/settings.bml.name=Gruppenavn: [[name]] + +/community/settings.bml.success=Succes + +/community/settings.bml.title.create=Lav gruppe + +/community/settings.bml.title.modify=Gruppeindstillinger + +/create.bml.age.check.question=Er du under 13 år gammel? + +/create.bml.age.check.yes=Ja, jeg er under 13 år. + +/create.bml.age.check2.question=Er du over 13 år gammel? + +/create.bml.age.check2.yes=Ja, jeg er over 13 år gammel. + +/create.bml.age.head=Alder + +/create.bml.btn.create=Opret journal + +/create.bml.btn.proceed=Fortsæt... + +/create.bml.captcha.answer=Svar: + +/create.bml.captcha.audiodesc=Skriv numrene du hører for at bevise du ikke er en spamrobot: + +/create.bml.captcha.desc=Skriv bogstaverne og tallene du ser nedenfor for at bevise du ikke er en spamrobot. Hvis du ikke kan læse teksten, kan du skrive "AUDIO" og tage en lydtest i stedet. + +/create.bml.captcha.invalid=Ugyldigt svar til forrige prøve. Prøv en ny. + +/create.bml.captcha.play=Afspil lyden + +/create.bml.captcha.prove=Bevis du er et menneske + +/create.bml.clusterselect.cluster=Klynge: + +/create.bml.clusterselect.clusternum=Klynge [[number]] + +/create.bml.clusterselect.head=Klyngevalg + +/create.bml.clusterselect.nocluster=Ingen klynge + +/create.bml.clusterselect.text=Vælg venligt den klynge du vil lave denne konto på. Note: Dette er kun en fejlsøgnings/test indstilling. I normalt virke vil brugere ikke kunne vælge dette, eller kende noget som helst til det. + +/create.bml.create.head=At oprette en ny journal + +/create.bml.create.text=At oprette en ny LiveJournal er nemt, bare følg instruktionerne nedenunder! + +/create.bml.email.head=Din emailadresse + +/create.bml.email.input.head=Emailadresse: + +/create.bml.email.text2=Af bekræftigelses- og sikkerhedsmæssige grunde har vi brug for din email adresse. Den vil aldrig nogensinde, under nogle omstændigheder, blive solgt eller givet væk til spammere. Det hader vi selv mere end noget andet. Læs vores fortrolighedspolitik for mere information. + +/create.bml.error.coppa.under13=Desværre, på grund af COPPA restriktioner kan du ikke bruge LiveJournal tjenesten indtil du er 13 år gammel. Kom endelig tilbage på din 13 års fødseldag. + +/create.bml.error.email.blank=Du skal angive en emailadresse. + +/create.bml.error.email.lj_domain=Du kan ikke bruge et [[domain]] alias når du opretter en konto. Indtast venlig en anden email adresse. + +/create.bml.error.email.nospaces=Mellemrum er ikke tilladt i email adresser. Hvis du er på AOL så husk at din Internet Email adresse er dit skærmnavn, med alle mellemrum fjernet, efterfulgt af @aol.com + +/create.bml.error.password.asciionly=Du kan kun bruge ASCII-tegn i kodeordet. + +/create.bml.error.password.blank=Du skal angive et kodeord. + +/create.bml.error.password.nomatch=Kodeordene er ikke ens. + +/create.bml.error.postrequired=POST krævet. + +/create.bml.error.username.blank=Angiv venligst et navn eller kaldenavn/alias. + +/create.bml.error.username.inuse=Brugernavn er allerede i brug, vælg venligst et andet. + +/create.bml.error.username.iscode=Brugernavn ser ud til at være en invitationskode, ikke et brugernavn. + +/create.bml.error.username.mustenter=Du skal angive et brugernavn. + +/create.bml.error.username.reserved=Desværre, det er et reserveret brugernavn. + +/create.bml.initial.friend.lj_maintenance=Rapporter for både planlagt & uplanlagt nedetid og vedligeholdelse + +/create.bml.initial.friend.news=LiveJournal nyheder og begivenheder + +/create.bml.initialfriends=Tilføj disse journaler til din venneliste for at blive holdt opdateret med sidenyheder og -information. + +/create.bml.initialfriends.heading=Begyndervenner + +/create.bml.name.head=Dit navn + +/create.bml.name.input.head=Navn: + +/create.bml.name.text=Hvad er dit navn eller kaldenavn? Dette vil stå øverst på din journal og i brugerkataloget, hvis du vælger at blive listet i den. Du behøver ikke at opgive dit fulde navn, eller for den sags skyld dit rigtige navn. + +/create.bml.password.head=Kodeord + +/create.bml.password.input.head1=Kodeord: + +/create.bml.password.input.head2=Bekræft kodeord: + +/create.bml.password.text=Vælg et kodeord + +/create.bml.proceed.btn.proceed=Fortsæt... + +/create.bml.proceed.warning=Klik kun en gang på Fortsæt!! + +/create.bml.success.btn.enterinfo=Angiv personlig information + +/create.bml.success.head=Succes! + +/create.bml.success.text1=Din journal er oprettet. Vigtige registreringsinformationer er blevet emailet til [[email]] med yderligere instruktioner. Sørg for at bekræfte at du har lavet din journal ved at klikke på linket, der er sendt til dig i emailen. + +/create.bml.success.text2=Din LiveJournal vil være tilgængelig på: + +/create.bml.success.text3=Nu bedes du venligst tage dig tid til at skrive noget information om dig selv. Det meste er frivilligt, men lader os få en ide om hvem, der bruger LiveJournal. + +/create.bml.title=Opret ny journal + +/create.bml.tos.error=Du skal læse og godkende brugsbetingelserne inden oprettelse af en konto. + +/create.bml.tos.haveread=Jeg har læst og godkender brugsbetingelserne. + +/create.bml.tos.heading=Brugsbetingelser + +/create.bml.tos.p1.2=Før du fortsætter skal du læse og godkende brugsbetingelserne. + +/create.bml.useacctcodes.entercode=Skriv en kontooptrettelseskode for at lave en ny konto. Se Hvordan opretter jeg en konto? for at få mere at vide. + +/create.bml.useacctcodes.welcome=Velkommen + +/create.bml.username.box.head=Brugernavn: + +/create.bml.username.charsallowed=Dit brugernavn må kun indeholde små bogstaver (a-z), tal (0-9) og understregningstegnet (_).
    Derudover må det ikke være længere end 15 tegn. + +/create.bml.username.forpaidaccts=Eller, til betalte konti: + +/create.bml.username.head=Brugernavn + +/create.bml.username.ljaddress=Din journal vil være på disse adresser: + +/create.bml.username.text=Enhver [[sitename]] bruger skal have sit eget unikke brugernavn. Dit brugernavn er det, der bliver brugt i adressen til din journal, og det du skal bruge til at logge ind på [[sitename]] serveren. Det er også det, der bliver vist, når du skriver kommentarer i en andens journal. + +/create.bml.username.username=brugernavn + +/customize/index.bml.change=Skift + +/customize/index.bml.choose=Vil du bruge det gamle stilsystem eller det nye? + +/customize/index.bml.choose.s1=Gammelt system (S1) + +/customize/index.bml.choose.s2=Nyt system (S2) + +/customize/index.bml.title=Tilpas journal + +/delcomment.bml.changeoptions=Bemærk: Fra [[link]]-siden kan du vælge, om du vil tillade alle, registrede bruger eller kun venner at skrive kommentarer. + +/delcomment.bml.confirm.banuser=Forbyd [[user]] at kommentere i din journal + +/delcomment.bml.confirm.body=Er du sikker på du vil slette denne kommentar? + +/delcomment.bml.confirm.head=Slet kommentaren? + +/delcomment.bml.confirm.submit=Slet kommentar + +/delcomment.bml.error.alreadydeleted=Den angivne kommentar er allerede blevet slettet. + +/delcomment.bml.error.cantdelete=En kommentar må kun slettes af den har skrevet den eller den der ejer journalen. + +/delcomment.bml.error.cantdelete.comm=En kommentar må kun slettes af dens forfatter, journalpostens forfatter eller en gruppevedligeholder. + +/delcomment.bml.error.invalidtype=Ugyldig kommentartype. Denne side kan kun bruges til kommentarer til journalposter. + +/delcomment.bml.error.nocomment=Den angivne kommentar eksisterer ikke. + +/delcomment.bml.success.andban=Kommentaren er blevet slettet, og brugeren [[user]] har fået forbud mod at kommentere i din journal. + +/delcomment.bml.success.head=Slettet + +/delcomment.bml.success.noban=Kommentaren er blevet slettet. + +/delcomment.bml.title=Slet kommentar + +/developer/index.bml.clients<< +Så du vil skabe eller forbedre en LiveJournal klient til din platform? Herligt! +Nedenfor er nogle nødvendige ressourcer til at give dig viden om hvordan LiveJournal fungerer. +. + +/developer/index.bml.clients.header=Skrive LiveJournal klienter + +/developer/index.bml.clients.links<< +
    +
    LiveJournal server<->klientprotokol
    +
    Lær hvordan LiveJournal klienten på din computer taler med LiveJournal serveren og omvendt. + Forståelse for dette er det vigtigste du har brug for når du skal udvikle eller forbedre en klient til din platform.
    +
    Komplet protokoldokumentation
    +
    Alle de forskellige protokol tilstande & metoder.
    +
    Liste over klienter
    +
    En liste over de fleste klienter brugt til at forbinde sig til LiveJournal. Størstedelen af disse klienter er open source, og de er alle gratis at bruge. Dette er et godt sted at finde eksempler til din klient.
    +
    +. + +/developer/index.bml.code=For at se bagenden der fÃ¥r LiveJournal til at virke og for at se indmaden af et par af de tilgængelige klienter, kan du gÃ¥ til kodesiden. + +/developer/index.bml.code.header=LiveJournal kodearkiv + +/developer/index.bml.dbschema<< +Nysgerrig angÃ¥ende databaseskemaet? +SQL'en til at oprette alle tabellerne og udfylde dem er inkluderet i serverkoden. +. + +/developer/index.bml.dbschema.header=Databaseskema + +/developer/index.bml.embedding=Kunne du tænke dig at indlejre din journal i din hjemmeside? Der er flere mÃ¥der at gøre det pÃ¥, afhængig af hvilken form for kontrol du har over din server. Du behøver kun at bekymre dig om dette, hvis du ikke kan lide at have www.livejournal.com til at stÃ¥ i din journals URL. + +/developer/index.bml.embedding.header=Indlejre LiveJournal + +/developer/index.bml.notice.header=Bemærk + +/developer/index.bml.notice1<< +Den følgende information er kun beregnet for programmører og avancerede brugere. +Hvis du blot ønsker at bruge LiveJournal til at føre din journal, herligt! +Almindelige brugere behøver ikke at bekymre sig om disse ting. +. + +/developer/index.bml.notice2=NÃ¥r det er sagt, det nedenstÃ¥ende indhold er delt op i to sektioner: Information om hvordan udseendet af LiveJournal sider ændres og information om at skrive LiveJournal klienter til LiveJournal serveren. + +/developer/index.bml.styles<< +Ikke tilfreds med hvordan dine journalsider ser ud? +Frygt ej... alt er fleksibelt, og hvis du læser dokumentationen nedenfor, vil du vide alt, du behøver for at fÃ¥ dine sider til at se ud, som du ønsker det. +. + +/developer/index.bml.styles.header=Tilpasse udseendet af en LiveJournal + +/developer/index.bml.styles.s1.header=Stilsystem 1 + +/developer/index.bml.styles.s1.system=Stilsystem + +/developer/index.bml.styles.s1.system.about=Generelt overblik over hvordan det første stilsystem er opbygget. + +/developer/index.bml.styles.s1.varlist=Variabelliste + +/developer/index.bml.styles.s1.varlist.about=Enkel alfabetisk liste med alle de variabler du kan tilpasse. + +/developer/index.bml.styles.s1.views=VisningsmÃ¥der + +/developer/index.bml.styles.s1.views.about=En liste over de forskellige mÃ¥der du kan se din journal pÃ¥ og oplysninger om hver enkelt. + +/developer/index.bml.styles.s2.header=Stilsystem 2 + +/developer/index.bml.styles.s2.layerbrowse=S2 lagbrowser + +/developer/index.bml.styles.s2.layerbrowse.about=En komplet liste af offentlige S2 lag som udgør S2 systemstilene. Af vigtighed er her kernelagene, som definerer grundvariablerne, -funktionerne og -klasserne, som gør S2 til det kraftfulde designsprog, det er. + +/developer/index.bml.styles.s2.manual=S2 manualen + +/developer/index.bml.styles.s2.manual.about=Omfattende information om brug af S2 pÃ¥ LiveJournal. + +/developer/index.bml.title=Udviklerinformation + +/doc/index.bml.about=Velkommen til LiveJournals dokumentationsopbevaringssted hvor du kan finde information om de fleste emner angÃ¥ende LiveJournals service eller serversoftware. Vælg venligst et af nedenstÃ¥ende emner: + +/doc/index.bml.about.header=Velkommen + +/doc/index.bml.docs.faq.about=Ofte Stillede SpørgsmÃ¥l om LiveJournal.com + +/doc/index.bml.docs.faq.title=OSS + +/doc/index.bml.docs.header=Dokumenter + +/doc/index.bml.docs.howto.about=Tips og tricks til at hjælpe med at tilpasse din LiveJournal konto + +/doc/index.bml.docs.server.about=Alt du behøver at vide for at installere, administrere og hacke en LiveJournal opsætning + +/doc/index.bml.docs.server.title=LiveJournal servermanual + +/doc/index.bml.docs.tour.about=Designet til at nye besøgende kan blive fortrolige med siden + +/doc/index.bml.docs.tour.title=Rundvisning + +/doc/index.bml.title=Dokumentation + +/doc/index.bml.volunteering.about=Hvis du kunne tænke dig at hjælpe med LiveJournals dokumentation, check følgende fora: + +/doc/index.bml.volunteering.header=Hjælpe til + +/doc/index.bml.volunteering.ljsysdoc=Diskussioner angÃ¥ende LiveJournals dokumentationssystem + +/doc/index.bml.volunteering.ljuserdoc=Slutbrugerdokumentation diskussioner + +/doc/tour/index.bml.clients.caption<< +LiveJournal klienter er smÃ¥ programmer der kører pÃ¥ din computer og lader dig opdatere din journal nÃ¥r du er online, uden at du behøver Ã¥bne et browser vindue. +Klienter er tilgængelige til stort set alle platforme og mange er lette at tilpasse. +. + +/doc/tour/index.bml.clients.title=Klienter + +/doc/tour/index.bml.comms.caption=LiveJournal er et stort, interaktivt samfund, sÃ¥ det burde ikke være en overraskelse at der er mange medlemmer med ens interesser. For at imødekomme dette tilbyder vi muligheden for at lave grupper, eller journaler som mange personer kan poste til. + +/doc/tour/index.bml.comms.title=Grupper + +/doc/tour/index.bml.create.caption=LiveJournal er et medlemsbaseret journal/dagbogssamfund. Denne side forklarer hvad medlemskab medfører, hvorfor medlemskab er vigtigt og fordelene ved medlemskab. Den indeholder ogsÃ¥ en formular til at oprette din egen konto. + +/doc/tour/index.bml.create.title=Oprette en konto + +/doc/tour/index.bml.friends.caption<< +Du ogsÃ¥ kan holde styr pÃ¥ dine venner gennem LiveJournal ved at bruge den indbyggede "vennefunktion". +Hvis du finder en journal som du synes er interessant sÃ¥ tilføj den til din venneliste, som vil lade dig læse alle dine venners poster pÃ¥ den samme side. +. + +/doc/tour/index.bml.friends.title=Venner + +/doc/tour/index.bml.intro.caption<< +Denne rundvisning er designet til at nye besøgende kan blive fortrolige med siden. +Den vil vise dig hvor de vigtigste sektioner er placeret ligesom den ogsÃ¥ vil vise nogle af de mere interessante egenskaber. +. + +/doc/tour/index.bml.intro.title=Velkommen + +/doc/tour/index.bml.modify.caption=Det er ogsÃ¥ muligt at formatere din journal pÃ¥ en del forskellige mÃ¥der, ved at bruge foruddefinerede stile og farveskemaer. Lav din journal sÃ¥ unik som du ønsker! + +/doc/tour/index.bml.modify.title=Personalisere + +/doc/tour/index.bml.nav.next=Næste --> + +/doc/tour/index.bml.nav.prev=<-- Forrige + +/doc/tour/index.bml.profile.caption=LiveJournal medlemmer opmuntres til at tilføje information om dem selv i deres profiler, sÃ¥ vi kan fÃ¥ en ide om hvem der bruger siden og hvordan vi bedst kan tjene dem. Der er dog intet af dette der er nødvendigt — de eneste informationer der er krævet for at kunne begynde med at bruge LiveJournal er et navn, en emailadresse og et kodeord. + +/doc/tour/index.bml.profile.title=Profiler + +/doc/tour/index.bml.sitemap.caption<< +ForhÃ¥bentlig gav denne rundvisning dig noget hjælpende startinformation om LiveJournal siden og servicen. +Hvis du behøver hjælp med noget som helst LiveJournal relateret skal du være velkommen til at kontakte vores supportafdeling. Hvis du vil udforske videre kan du kigge pÃ¥ sideoversigten for at se en liste over alle sider her pÃ¥ siden. +. + +/doc/tour/index.bml.sitemap.title=Sideoversigt + +/doc/tour/index.bml.support.caption=Supportsiden viser omrÃ¥der som hjælper med at forklare hvad LiveJournal er, ofte stillede spørgsmÃ¥l om siden og andre hjælpende informationer om servicen, firmaet og samfundet generelt. + +/doc/tour/index.bml.support.title=FÃ¥ hjælp + +/doc/tour/index.bml.title=Rundvisning - [[title]] + +/doc/tour/index.bml.update.caption=At opdatere en LiveJournal er kernen af LiveJournal servicen; det er her vi tilbyder medlemmerne en chance for at dele deres liv og sige hvad de har pÃ¥ hjerte. At opdatere en journal er simpelt. Du skriver simpelthen bare en post i den angivne boks og trykker pÃ¥ "Opdater journal"-knappen. Vi tilbyder selvfølgelig ogsÃ¥ avancerede muligheder pÃ¥ vores opdateringsside, som muligheden for at kontrollere for stavefejl, og muligheden for at angive ekstra information omkring dine poster, sÃ¥som dit nuværende humør eller din nuværende musik. + +/doc/tour/index.bml.update.title=Opdatere + +/editinfo.bml.allowshowcontact.about=Du bør have denne indstilling slÃ¥et til. Dette lader andre folk kontakte dig ved at vise din emailadresse, dit ICQ nummer og dit AOL Instant Messenger skærmnavn pÃ¥ din LiveJournal. + +/editinfo.bml.allowshowcontact.email=Hvis synlig, hvilken email adresse skal vises: + +/editinfo.bml.allowshowcontact.email.actual_only=Kun aktuel adresse + +/editinfo.bml.allowshowcontact.email.both=Begge (aktuel + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Kun LiveJournal adresse + +/editinfo.bml.allowshowcontact.email.neither=Ingen. Lad være med at vise nogen email adresse. + +/editinfo.bml.allowshowcontact.email.no_show=Vis ikke email adresse + +/editinfo.bml.allowshowcontact.email.show=Vis email adresse + +/editinfo.bml.allowshowcontact.title=Vis din kontaktinformation i din LiveJournal? + +/editinfo.bml.allowshowinfo.about=SlÃ¥ dette til hvis du vil have at dit din by, din stat, dit land, og din fødselsdag skal være synligt for andre brugere. + +/editinfo.bml.allowshowinfo.title=Vis sted & fødselsdag? + +/editinfo.bml.bday.title=Fødselsdag + +/editinfo.bml.bday.year.opt=Ã¥r er valgfrit + +/editinfo.bml.bio.about=Her kan du skrive en lille minibiografi om dig selv. Den vil blive vist pÃ¥ din brugerinfo side. + +/editinfo.bml.bio.header=Om Dig + +/editinfo.bml.blockrobots.about<< +Hvis du vælger denne indstilling vil robotter blive bedt om at holde sig væk. +Ikke alle robotter respekterer reglerne. +. + +/editinfo.bml.chat.msnusername.title=MSN brugernavn + +/editinfo.bml.chat.yahooid.title=Yahoo! Id + +/editinfo.bml.city.title=By + +/editinfo.bml.country.choose=Vælg et land + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Nej + +/editinfo.bml.error.email.lj_domain<< +Du kan ikke angive en @[[domain]] e-mailadresse. +Skriv din rigtige adresse i feltet. +Hvis du er en betalt bruger vil din [[user]]@[[domain]]-adresse videresende til din rigtige adresse. +Se indstillingen under "Vis din kontaktinformation" for at vælge hvilken adresse der vil blive vist offentligt, eller om begge adresser skal vises. +. + +/editinfo.bml.error.email.none=Du skal skrive din email adresse + +/editinfo.bml.error.email.no_space<< +Mellemrum er ikke tilladt i emailadresser. +Husk pÃ¥ at hvis du er pÃ¥ AOL, er din internet emailadresse det samme som dit skærmnavn uden mellemrum, efterfulgt af @aol.com +. + +/editinfo.bml.error.excessive_int<< +Desværre, du angav for mange interesser. Begrænsningen er 150, men du har angivet [[intcount]]. +De ændringer du havde lavet i dine interesser blev ikke gemt. GÃ¥ tilbage og skær ned pÃ¥ dine liste og gem igen. +. + +/editinfo.bml.error.locale.invalid_country=Det lykkedes dig at vælge et ugyldigt land. + +/editinfo.bml.error.locale.state_ne_country=Du angav et ikke-US land, men valgt en US stat. + +/editinfo.bml.error.locale.zip_ne_state<< +Dette postnummer passer ikke med den stat du angav. +Enten ret informationen, eller slet bÃ¥de stat og postnummer feltet eller et af dem. +. + +/editinfo.bml.error.tm.require.number=Hvis du vil bruge tekstbeskeder skal du indtaste et telefonnummer. + +/editinfo.bml.finished.about=Tryk pÃ¥ "Gem ændringer"-knappen nedenfor nÃ¥r du er færdig: + +/editinfo.bml.finished.header=Færdig? + +/editinfo.bml.finished.save_button=Gem ændringer + +/editinfo.bml.gender.title=Køn + +/editinfo.bml.hidefriendof.header=Skjul "Ven af" liste + +/editinfo.bml.howhear.header=Nysgerrighed + +/editinfo.bml.int.header=Interesser + +/editinfo.bml.login.enterinfo=Angiv dit brugernavn og kodeord for at ændre din personlige information. + +/editinfo.bml.login.forgot.header=Glemt noget? + +/editinfo.bml.login.forgot.recover=Hvis du har glemt dit brugernavn eller kodeord, fÃ¥ det tilbage her!. + +/editinfo.bml.logip.always=Altid + +/editinfo.bml.name.title=Navn + +/editinfo.bml.numcomments.header=Tilføj &nc=xx til kommentar URL'er. + +/editinfo.bml.optional=Valgfrit + +/editinfo.bml.opt_in.header=Send mig nyheder om LiveJournal. + +/editinfo.bml.persinfo.header=Personlig Information + +/editinfo.bml.screen.all=Alle + +/editinfo.bml.screen.anon=Anonyme + +/editinfo.bml.screen.none=Ingen + +/editinfo.bml.screen.nonfriends=Af ikke-venner + +/editinfo.bml.screen.nonmembers=Af ikke-medlemmer + +/editinfo.bml.security.header=Hvem kan se din kontaktinfo? + +/editinfo.bml.security.visibility.friends=Kun venner + +/editinfo.bml.security.visibility.regusers=Registrede Brugere + +/editinfo.bml.settings.header=LiveJournal Indstillinger + +/editinfo.bml.state.title=Stat + +/editinfo.bml.state.us=Stater i USA + +/editinfo.bml.success.header=Succes! + +/editinfo.bml.success.message=Dine informationer og journal indstillinger og din profil er blevet opdateret. + +/editinfo.bml.switch.button=Skift + +/editinfo.bml.switch.header=Skift Journal + +/editinfo.bml.switch.workwith=Arbejd med journal: + +/editinfo.bml.title=Rediger Personlig Information + +/editinfo.bml.tm.details=detaljer + +/editinfo.bml.tm.sec.title=Sikkerheds Niveau: + +/editinfo.bml.userpic.edit=Klik her for at slette dette billede eller uploade et nyt. + +/editinfo.bml.userpic.header=Dit Billede + +/editinfo.bml.userpic.none=intet billede uploadet + +/editinfo.bml.webpagename.title=Webside Navn + +/editinfo.bml.webpageurl.title=Webside URL + +/editinfo.bml.whoreply.header=Hvem kan svare pÃ¥ dine poster? + +/editinfo.bml.zip.title=Postnummer + +/editjournal.bml.btn.proceed=Fortsæt... + +/editjournal.bml.certainday=Bestemt dag: + +/editjournal.bml.desc=Brug venligst formularen nedenfor til at finde den post du vil redigere. + +/editjournal.bml.in=I gruppe: + +/editjournal.bml.recententries=seneste poster + +/editjournal.bml.recententry=Seneste post + +/editjournal.bml.title=Rediger journalposter + +/editjournal.bml.viewwhat=Vis hvilke poster: + +/editjournal_do.bml.body=Rediger de felter af din journalpost du vil ændre og tryk pÃ¥ gem-knappen i bunden af siden. Alternativt kan du trykke pÃ¥ slet-knappen for at slette posten. + +/editjournal_do.bml.btn.delete=Slet journalpost + +/editjournal_do.bml.btn.edit=Rediger valgt post + +/editjournal_do.bml.btn.save=Gem journalpost + +/editjournal_do.bml.continue.head=Klik for at fortsætte... + +/editjournal_do.bml.continue.text=Efter du har valgt en post til at redigere eller slette, tryk pÃ¥ rediger-knappen nedenfor. + +/editjournal_do.bml.currmood=Nuværende humør: + +/editjournal_do.bml.currmusic=Nuværende musik: + +/editjournal_do.bml.date=Dato: + +/editjournal_do.bml.default=standard + +/editjournal_do.bml.delete.confirm=Er du sikker pÃ¥ du vil slette denne post? + +/editjournal_do.bml.edit.text=Dette er den journalpost du valgte at redigere. Ret alle de informationer du vil ændre, og tryk sÃ¥ pÃ¥ "Gem journalpost"-knappen nederst.

    For at slette posten, slet al tekst i tekstboksen og tryk på "Gem journalpost"-knappen nederst. + +/editjournal_do.bml.error.getting=Der var en fejl under hentningen af journalposterne til redigering: + +/editjournal_do.bml.error.modify=Der skete en fejl under redigeringen af din journal: + +/editjournal_do.bml.error.nofind=Kunne ikke finde den valgte journalpost. + +/editjournal_do.bml.localtime=Lokal tid: + +/editjournal_do.bml.noneother=Intet, eller andet: + +/editjournal_do.bml.opt.backdate=Tilbagedatér post: + +/editjournal_do.bml.opt.backdate.about=vil ikke blive vist i vennevisning + +/editjournal_do.bml.opt.nocomments=Tillad ikke kommentarer: + +/editjournal_do.bml.opt.noemail=E-mail ikke kommentarer: + +/editjournal_do.bml.opt.noformat=Ingen autoformatering: + +/editjournal_do.bml.other=Andet: + +/editjournal_do.bml.pickentry.text=Vælg hvilken post du vil redigere og tryk på rediger-knappen i bunden af siden. + +/editjournal_do.bml.picture=Brug billede: + +/editjournal_do.bml.save.head=Tryk for at gemme... + +/editjournal_do.bml.save.text=Når du er færdig med at redigere din journalpost, tryk på gem. + +/editjournal_do.bml.subject=Emne: (valgfrit) + +/editjournal_do.bml.success.delete=Journalpost blev slettet. + +/editjournal_do.bml.success.edit=Journalpost blev ændret. Du kan se den her. + +/editjournal_do.bml.success.head=Succes + +/editjournal_do.bml.timeformat=24-timers tid + +/editjournal_do.bml.title=Rediger journalposter + +/editpics.bml.btn.proceed=Fortsæt + +/editpics.bml.btn.save=Gem indstillinger + +/editpics.bml.curpics=Nuværende billeder + +/editpics.bml.curpics.desc=Her er de billeder du tidligere har uploadet. Du kan tildele dem nøgleord, så du senere kan bruge billederne ud fra disse, vælge hvilket du vil bruge som standard, eller slette gamle billeder. For at uploade nye billeder skal du bruge formularen i bunden af siden. + +/editpics.bml.error.badurl=Adressen til det billede der skal uploades ser ikke rigtigt ud. Det burde starte med http:// + +/editpics.bml.error.filetoolarge=Det uploadede billede er for stort. Filstørrelsen må ikke være mere end [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Dimensionerne på dit billede ([[imagesize]]) overskrider maksimum størrelsen. Dit billede må højst være 100x100 piksler stort. Brug et billedbehandlingsprogram for at formindske billedet til miniaturestørrelse. + +/editpics.bml.error.invalidimage=Ugyldig billedfil. + +/editpics.bml.error.keywords=Du har brugt nøgleordet "[[ekw]]" til flere billeder. Et blev tilfældigt valgt, men nok ikke det du ville have. Du kan gå tilbage og rette dette. + +/editpics.bml.error.toomanypics2=Du har allerede nået din begrænsning på [[maxpics]] billeder. Du kan ikke uploade billedet før du har slettet et af dine nuværende. + +/editpics.bml.error.unsupportedtype=Filer af typen [[filetype]] er ikke understøttede. Du kan kun uploade GIF, PNG og JPG filer. Næsten alle billed-/fotoprogrammer kan lave denne omdannelse for dig. + +/editpics.bml.error.urlerror=Der skete en fejl under forsøget på at hente dit billede. + +/editpics.bml.fromfile=Fra fil: + +/editpics.bml.fromurl=Fra URL: + +/editpics.bml.label.default=Standard: + +/editpics.bml.label.delete=Slet: + +/editpics.bml.label.keywords=Nøgleord: + +/editpics.bml.makedefault=Gør dette til dit standard billede + +/editpics.bml.nodefault=Intet standardbillede + +/editpics.bml.noneupload=Du har ikke uploadet nogen billeder. Upload venligst et ved at bruge formularen forneden. + +/editpics.bml.nopics=Ingen billeder + +/editpics.bml.restriction.fileformat=Filformatet skal være enten PNG, GIF eller JPG + +/editpics.bml.restriction.filesize=Filstørrelsen skal være mindre end 40k + +/editpics.bml.restriction.imagesize=Billeddimensionerne må ikke være større end 100x100 piksler + +/editpics.bml.title=Rediger brugerbilleder + +/editpics.bml.uploaddesc=Brug formularen nedenfor til at uploade et nyt billede. + +/editpics.bml.uploadheader=Upload et nyt billede + +/export.bml.btn.proceed=Fortsæt... + +/export.bml.fields=Felter: + +/export.bml.label.field.currents=Nuværende humør & musik + +/export.bml.label.field.subject=Emne + +/export.bml.label.month=Vælg måned: + +/friends/add.bml.add.header=Succes + +/friends/add.bml.add.text=Brugeren [[ljuser]] er tilføjet til din venneliste. Du kan se din venneside her. + +/friends/add.bml.add.title=Ven tilføjet! + +/friends/add.bml.btn.add=Tilføj [[user]]. + +/friends/add.bml.btn.modify=Rediger + +/friends/add.bml.btn.remove=Fjern + +/friends/add.bml.colors.bg=Baggrund + +/friends/add.bml.colors.fg=Forgrund + +/friends/add.bml.colors.header=Farver + +/friends/add.bml.colors.hover=(Hold din mus over en farve hvor at se dens navn) + +/friends/add.bml.colors.text=Du kan eventuelt vælge farverne der vil repræsentere [[user]] i din venneliste. + +/friends/add.bml.confirm.header=Tilføj [[user]] som ven? + +/friends/add.bml.confirm.text=For at tilføje [[user]] til din venneliste, klik på knappen nedenfor. + +/friends/add.bml.confirm.title=Tilføj Ven + +/friends/add.bml.error1.header=Log ind først + +/friends/add.bml.error1.text<< +For at tilføje en bruger til din venneliste skal du først logge ind. +Hvis du ikke allerede har en konto kan du lave en for at følge dine venners journaler. +. + +/friends/add.bml.error1.title=Tilføj Ven + +/friends/add.bml.error2.text=Ugyldigt eller intet brugernavn angivet. Gå til rediger venner siden for at tilføje en ven. + +/friends/add.bml.error3.text=Du har allerede angivet [[user]] som ven. Du kan dog redigere de farver du har valgt til at repræsentere ham/hende. + +/friends/add.bml.error3.title=Rediger ven + +/friends/add.bml.groups.header=Vennegrupper + +/friends/add.bml.groups.nogroup=Ingen vennegrupper sat op. + +/friends/add.bml.remove.header=Succes + +/friends/add.bml.remove.text=Brugeren er fjernet fra din venneliste. Du kan se din venneside her. + +/friends/add.bml.remove.title=Ven Fjernet! + +/friends/edit.bml.title=Rediger venner + +/friends/editgroups.bml.btn.ge.del=Slet + +/friends/editgroups.bml.btn.ge.new=Ny + +/friends/editgroups.bml.btn.ge.ren=Omdøb + +/friends/editgroups.bml.btn.gs.private=Privat + +/friends/editgroups.bml.btn.gs.public=Offentlig + +/friends/editgroups.bml.btn.mv.down=Flyt ned + +/friends/editgroups.bml.btn.mv.up=Flyt op + +/friends/editgroups.bml.done.btn=Gem ændringer + +/friends/editgroups.bml.done.header=Færdig? + +/friends/editgroups.bml.done.text=Tryk på knappen nedenfor når du er færdig for at gemme dine ændringer. + +/friends/editgroups.bml.error.text=Serveren returnerede følgende fejlbesked: + +/friends/editgroups.bml.group.public=(offentlig) + +/friends/editgroups.bml.ingroup=I gruppe: + +/friends/editgroups.bml.ingroup.not=Ikke i gruppe: + +/friends/editgroups.bml.saved.header=Gemt + +/friends/edit_do.bml.addfriends.head=Tilføj venner + +/friends/edit_do.bml.addfriends.text=Angiv dine venners LiveJournal brugernavne i boksene nedenfor og vælg hvilke baggrunds og forgrundsfarver du vil forbinde med dem.... + +/friends/edit_do.bml.background=Baggrund + +/friends/edit_do.bml.bgcolor=Baggrundsfarve: + +/friends/edit_do.bml.btn.close=Luk + +/friends/edit_do.bml.btn.save=Gem ændringer + +/friends/edit_do.bml.done.head=Færdig? + +/friends/edit_do.bml.done.text=Tryk på "Gem ændringer"-knappen nedenfor når du er færdig... + +/friends/edit_do.bml.foreground=Forgrund + +/friends/edit_do.bml.friend=Ven + +/friends/edit_do.bml.hover=Hold din mus over en farve for at se dens navn + +/friends/edit_do.bml.mrcolor=Hr. Farveviser + +/friends/edit_do.bml.name=Navn + +/friends/edit_do.bml.nofriends.head=Ingen venner? + +/friends/edit_do.bml.opt.delete=Slet? + +/friends/edit_do.bml.success.head=Succes + +/friends/edit_do.bml.textcolor=Tekstfarve: + +/friends/edit_do.bml.title=Rediger venner + +/friends/edit_do.bml.user=Bruger + +/friends/edit_do.bml.viewer=Farveviser + +/friends/edit_do.bml.yourfriends.head=Dine venner + +/friends/edit_do.bml.yourfriends.text=Du har ligenu følgende angivet som venner: + +/friends/index.bml.title=Venne værktøjer + +/index.bml.about.header=Om LiveJournal + +/index.bml.about.joining=At blive medlem af siden er gratis. Brugere kan vælge at opgradere deres konti for flere funktioner. + +/index.bml.about.us=LiveJournal er et nemt-at-bruge (men ekstremt kraftfuldt og tilpasseligt) personligt udgivelses ("blogging") værktøj, bygget på open source software. + +/index.bml.boldcreate=Opret din egen LiveJournal! + +/index.bml.frank.image.alt=Frank, LiveJournals maskot ged. + +/index.bml.frank.logo="Baaaaah", siger Frank. + +/index.bml.learnmore.header=Vil du vide mere? + +/index.bml.learnmore.text=Læs venligst vores funktionsoversigt.
    Overbevist? Opret din egen LiveJournal! + +/index.bml.meta.desc=LiveJournal.com er et sted hvor du kan dele dine tanker med verden. + +/index.bml.meta.keywords=dagbog, journal, online journal, dagbøger, skrivning, online dagbog, web dagbog + +/index.bml.news.text=De seneste sidenyheder: + +/index.bml.news.title=Seneste nyheder + +/index.bml.post=Live poststatistik + +/index.bml.post.hour=Per time: + +/index.bml.post.latest=Seneste poster + +/index.bml.post.min=Per minut: + +/interests.bml.add.added.head=Tilføjet! + +/interests.bml.add.added.text=Interessen er blevet tilføjet til din liste. + +/interests.bml.add.btn.text=Tilføj [[interest]] + +/interests.bml.add.confirm.head=Bekræft + +/interests.bml.add.confirm.text=Tryk på knappen nedenfor for at tilføje [[interest]] til dine interesser. + +/interests.bml.add.toomany.head=Desværre... + +/interests.bml.add.toomany.text=Du har allerede valgt [[maxinterests]] interesser. + +/interests.bml.communities.head=Relevante grupper + +/interests.bml.communities.text=Følgende grupper er også interesseret i "[[interest]]". + +/interests.bml.count=Optælling + +/interests.bml.error.add.mustlogin=Du skal være logget ind for at kunne tilføje en interesse på denne måde. + +/interests.bml.error.findsim_do.intnotfound=Interesse blev ikke fundet. + +/interests.bml.findsim_do.account.notallowed=Desværre, din kontotype lader dig ikke bruge denne funktion. + +/interests.bml.finished.about=Tryk på "Gem ændringer"-knappen nedenfor når du er færdig: + +/interests.bml.finished.save_button=Gem ændringer + +/interests.bml.interests.viewpop=Vis populære interesser + +/interests.bml.popular.head=Populære Interesser + +/interests.bml.popular.text=Følgende er de mest populære interesser. + +/interests.bml.title=Interesser + +/interests.bml.toomany.body=Der er [[intcount]] folk og/eller grupper som har angivet dette som en interesse. Der vil ikke blive vist en liste. + +/interests.bml.users.head=Interesserede brugere + +/interests.bml.users.text=Følgende brugere er interesseret i [[interest]]. + +/invite/index.bml.code=Kode + +/invite/index.bml.error=Fejl + +/invite/index.bml.genmore=Lav flere koder + +/invite/index.bml.how_detail=Eksisterende brugere har, afhængig af visse faktorer, lov til at invitere et vist antal af andre folk til at tilmelde sig siden. For at invitere nogen skal du lave en invitationskode og så give den til dem. + +/invite/index.bml.how_header=Hvordan virker det? + +/invite/index.bml.invite_header=Invitationer? + +/invite/index.bml.none=Ingen + +/invite/index.bml.redeemed=Brugt af + +/invite/index.bml.title=Inviter andre til LiveJournal... + +/invite/index.bml.unused=Ubrugt + +/invite/index.bml.use=brug + +/legal/index.bml.about.header=Oversigt + +/legal/index.bml.docs.header=Dokumenter + +/legal/privacy.bml.title=Fortrolighedspolitik + +/legal/tos.bml.title=Brugsbetingelser + +/login.bml.bindip.label=Knyt til IP adresse: + +/login.bml.bindip.no=Nej (virker med alle ISP'er) + +/login.bml.bindip.yes=Ja (mere sikkert) + +/login.bml.error.mustenterusername=Du skal skrive et brugernavn. + +/login.bml.expire.btn.neverexpire=Sæt udløbstilstand til ALDRIG + +/login.bml.expire.neverexpire.text=Dit logind vil aldrig løbe ud, så hvis du sidder ved en offentlig terminal, på en skole, et bibliotek eller andetsteds hvor andre folk frit kan benytte computeren skal du huske at logge af når du er færdig! Eller du kan ændre dit logind til at løbe ud når du lukker din browser: + +/login.bml.expire.sessiononly.text=Dit logind udløber efter du lukker din browser. Hvis dette er din egen computer og du er den eneste bruger, kunne du muligvis ønske at sætte dit logind til adrig at udløbe. + +/login.bml.links.link1=Din venneside. + +/login.bml.links.link2=Din to-do liste. + +/login.bml.links.text=I fremtiden vil denne side indeholde alle mulige slags links og relevante informationer, men indtil videre er der en liste over et par steder der måske er et besøg værd: + +/login.bml.loggedin.head=Logget ind! + +/login.bml.loggedin.text=Du er nu logget ind. + +/login.bml.login.btn.changeopts=Skift indstillinger + +/login.bml.login.btn.login=Log ind... + +/login.bml.login.expiration=Udløb: + +/login.bml.login.forget=Glemt? + +/login.bml.login.head=Log ind + +/login.bml.login.never=Aldrig + +/login.bml.login.otheropts=Andre indstillinger: + +/login.bml.login.password=Kodeord: + +/login.bml.login.text1=Skriv dit brugernavn og kodeord nedenfor, for at logge ind på [[sitename]]. Nye Brugere: Klik her for at oprette en konto. + +/login.bml.login.text2=Du kan også angive hvornår dit logind skal udløbe. Som standard vil dit logind løbe ud når du lukker din browser, hvilket er det smarteste på offentlige computere. På den anden side, hvis du er den eneste bruger af en computer og der ikke er andre der har adgang til den, kan du vælge at forblive logget på for altid. For flere informationer om denne og andre indstillinger, kig på Hvad er mulighederne når jeg logger ind? + +/login.bml.login.text3=[[username]], du er nu logget ind på [[sitename]]. Vær velkommen til at kigge vores sideoversigt igennem. + +/login.bml.login.username=Brugernavn: + +/login.bml.login.whenbrowsercloses=Når browseren lukkes + +/login.bml.logout.btn=Log ud + +/login.bml.title=Log ind + +/login.bml.whylogin.benefit1=Du behøver ikke længere at skrive dit brugernavn/kodeord nogle steder på siden. + +/login.bml.whylogin.benefit2=Du vil være i stand til at læse "beskyttede" journalposter af de venner der giver dig lov til at læse dem. + +/login.bml.whylogin.benefit3=Mange funktioner er kun synlige eller tilgængelige mens du er logget ind. + +/login.bml.whylogin.head=Hvorfor logge ind? + +/login.bml.whylogin.text=Her er nogle af hovedfordelene af at logge ind: + +/logout.bml.already.head=Allerede logget ud + +/logout.bml.already.text=Du har allerede logget ud. + +/logout.bml.loggedout.already=Allerede logget ud. + +/logout.bml.loggedout.head=Logget ud + +/logout.bml.loggedout.success=Logget ud. + +/logout.bml.loggedout.text=Du er nu logget ud. + +/logout.bml.logout.btn=Log ud + +/logout.bml.logout.head=Log ud? + +/logout.bml.logout.text=Klik på knappen nedenfor for at logge ud. + +/logout.bml.title=Log ud + +/lostinfo.bml.btn.proceed=Fortsæt + +/lostinfo.bml.enter_email=Skriv din email adresse: + +/lostinfo.bml.enter_email_optional=Email adresse: (valgfri) + +/lostinfo.bml.enter_username=Skriv dit brugernavn: + +/lostinfo.bml.lostpassword.title=Mistet dit kodeord? + +/lostinfo.bml.lostusername.text=Hvis du har mistet dit brugernavn, angiv din email adresse og vi sender det til dig. + +/lostinfo.bml.lostusername.title=Mistet dit brugernavn? + +/lostinfo.bml.title=Mistet Information + +/lostinfo_do.bml.error.no_usernames_for_email=Intet brugernavn til denne email adresse: [[address]] . + +/lostinfo_do.bml.error1.text=Du har aldrig brugt den email adresse med den konto, eller du fik den aldrig godkendt. + +/lostinfo_do.bml.password_mailed.text=Succes. Dit kodeord er blevet sendt. + +/lostinfo_do.bml.password_mailed.title=Koderord sendt! + +/lostinfo_do.bml.title=Mistet Information + +/lostinfo_do.bml.username_mailed.text=Succes. Dit brugernavn er blevet sendt. + +/lostinfo_do.bml.username_mailed.title=Brugernavn sendt. + +/manage/siteopts.bml.btn.lang=Skift sprog + +/manage/siteopts.bml.head.lang=Vælg dit sprog + +/manage/siteopts.bml.title=Visningsindstillinger + +/modify_do.bml.availablestyles.head=Tilgængelige Stile + +/modify_do.bml.availablestyles.userstyles=Bruger Stile: + +/modify_do.bml.colortheme.color.head1=Farve + +/modify_do.bml.colortheme.color.head2=(#rrggbb eller navn) + +/modify_do.bml.domainalias.about=Hvis du allerede har registreret et domænenavn (eller der er et du har planlagt at registrere) og du kunne tænke dig at det automatisk hentede din LiveJournal, så angiv det her: + +/modify_do.bml.domainalias.domainname=Domæne navn: + +/modify_do.bml.domainalias.example=Eksempel: min-journal.dk + +/modify_do.bml.domainalias.helptext=For at dette skal virke skal du sørge for at dit domænenavns DNS peger på den samme IP-adresse som [[sitename]]. Læs dette OSS for mere information. + +/modify_do.bml.done.btn.savechanges=Gem ændringer + +/modify_do.bml.done.head=Færdig? + +/modify_do.bml.done.text=Klik på "Gem ændringer"-knappen nedenfor når du er færdig... + +/modify_do.bml.journaloptions.head=Journal indstillinger + +/modify_do.bml.overrides.warning=DETTE ER IKKE HER DU SKRIVER I DIN JOURNAL! + +/modify_do.bml.pagelayoutstyle.warning=Din kontotype tillader dig kun at vælge imellem et lille antal af standard stile. + +/modify_do.bml.success.head=Succes + +/modify_do.bml.success.text=Dine journalindstillinger er blevet opdateret. Du kan se din journal her. + +/paidaccounts/index.bml.costs.header=Nå, hvor meget koster det så? + +/paidaccounts/index.bml.costs.rates=Priserne er som følger: + +/paidaccounts/index.bml.costs.rates.amount.header=Pris + +/paidaccounts/index.bml.costs.rates.time.header=Tid + +/paidaccounts/index.bml.title=Om Betalte Konti + +/paidaccounts/index.bml.your_username=dit_brugernavn + +/press/staff.bml.administration.about=LiveJournal.com blev startet af Brad Fitzpatrick i 1999 som et projekt, og blev gennem de første to år af dets liv opretholdt af en stor og loyal gruppe af frivillige. Selvom en stor del af LiveJournal.com stadig bliver kørt af frivillige hold, har vi nu en lille gruppe ansat personale, som tilser alle funktioner: + +/press/staff.bml.avva.title=Overudvikler + +/press/staff.bml.back2=Tilbage til presseområdet + +/press/staff.bml.bradfitz.quip=Fokuser på dit produkt, ikke kun på at tjene penge. + +/press/staff.bml.bradfitz.title=Formand / Hovedudvikler + +/press/staff.bml.contact=E-mail venligst til webmaster@livejournal.com hvis du skal i kontakt med nogen af os. + +/press/staff.bml.david.title=Praktikanten + +/press/staff.bml.denisep.quip=Jeg har det til dig på næste torsdag + +/press/staff.bml.denisep.title=Forhold til frivillige / Specialist i brugbarhed + +/press/staff.bml.deveiant.title=Fjernudvikler + +/press/staff.bml.developers=Udviklere + +/press/staff.bml.evan.title=Hacker emeritus + +/press/staff.bml.jproulx.quip=Nørd til bruger kommunikation + +/press/staff.bml.jproulx.title=Gruppesidetilsynsførende / Pressetalsmand + +/press/staff.bml.kevin.title=Grafiker og webdesigner + +/press/staff.bml.lisa.title=Systemadministrator + +/press/staff.bml.nick.title=Systemadministrator + +/press/staff.bml.ryanfitz.title=Betalingstjenester + +/press/staff.bml.sandy.title=Bogholderi og administration + +/press/staff.bml.smithy.title=Hacker lærling + +/press/staff.bml.sysadmin=Systemadministratorer + +/press/staff.bml.title=Ansat personale + +/press/staff.bml.whitaker.quip=Hvad er det næste? + +/press/staff.bml.whitaker.title=Fjernudvikler + +/site/goat.bml.image.alt=Frank, LiveJournals maskot ged. + +/site/goat.bml.image.caption="Baaaah," siger Frank. + +/site/goat.bml.meet.header=Mød Frank + +/site/goat.bml.title=Geden Frank + +/suggestions/index.bml.howto.text<< +
    +
    Check tidligere forslag
    +Start med at læse igennem tidligere forslag for at være sikker på at noget lignende ikke allerede er blevet foreslået. Hvis det har kan du læse kommentarene til posten. Nogle gange kan ting se ud om de er blevet ignoreret, men det kan være de er under udvikling. Nogle gang er ideer blevet afvist eller udsat på grund af andre anliggender eller bekymringer. +
    +
    Kunne du ikke finde din ide? Del den med os!
    +Skabelonen skal bruges til alle forslag. Vær sikker på at udfylde alle dele af skabelonen, og vær sikker på at dit forslag er rigtig og komplet før du poster den. Forslagsgeneratoren laver heller ikke linieskift, men du kan bruge <br>-tagget til at lave disse. Dette gør dit forslag lettere at læse. +
    +
    Indsend det!
    +Du kan tilføje gruppen til din venneliste her. Når et forslag er blevet indsendt vil folk diskutere det. Hvis vi synes det er en god ide, vil den blive tilføjet til listen over udviklerprojekter, og vil blive arbejdet som tiden tillader det. Ikke alle forslag kan blive implementeret øjeblikkeligt, så vær venligst tålmodig med processen. +
    +. + +/suggestions/index.bml.howto.title=Hvordan laver jeg et forslag? + +/suggestions/index.bml.info.text<< +Føler du at du kan bidrage til implementeringen af dine forslag? Du skal være velkommen til at 'overvåge' eller tilmelde dig grupperne nedenfor: +
    +
    LiveJournal udviklernes forum -- snak om tekniske ting.
    +
    +
    LiveJournal forretnings forum -- snak om generelle LiveJournal forretningsmuligheder og beslægtede områder.
    +
    +
    LiveJournal brugerdokumentations forum -- diskussion og redigering af de fleste former for slutbrugerdokumentation.
    +
    +
    LiveJournal kunstforum -- diskussion og deling af ikonger, humørtemaer, farvetemaer og brugerbilleder.
    +
    +
    +Vær venlig at huske på at folkene der implementerer LiveJournal ændringer og tilføjelser er medbrugere, ligesom dig selv. Disse ting kan tage tid og jo mere du hjælper med implementeringen, jo mere kan der blive opnået. +. + +/suggestions/index.bml.info.title=Anden information + +/suggestions/index.bml.rules<< +Der er nogle få ting du skal huske på: +
      +
    • Mange forslag er allerede blevet fremsat og diskuteret, men er ganske enkelt ikke blevet implementeret endnu. Vær sikker pÃ¥ du ikke indsender noget der allerede er blevet foreslÃ¥et.
    • +
    • Mudderkastning vil ikke blive tolereret. Alle har forskellige ideer om hvordan LiveJournal bør virker; husk pÃ¥ at reklamere for din mening er i orden, men at kaste mudder efter en andens meninger er ikke.
    • +
    • Vær sÃ¥ grundig som muligt med dit forslag. Der er større mulighed for at et forslag der indeholder detaljerede implementeringsnoter bliver accepteret end der er for et der ikke gør. Du behøver ikke vide hvordan man programmerer; bare tænk pÃ¥ hvad din ide ellers vil pÃ¥virke og nævn alle problemer du kan se med den.
    • +
    • Vær sikker pÃ¥ at læse OSS'erne først for at se om din ide allerede eksisterer, eller om der er eksisterende del af siden der kan bruges til hvad du ønsker. +
    • Hvis du vil stille et spørgsmÃ¥l angÃ¥ende hvordan LiveJournal virker, ikke er sikker pÃ¥ om noget eksisterer eller ej eller hvis du har et problem sÃ¥ lad være med at komme med et forslag. Spørg Support i stedet.
    • +
    +. + +/suggestions/index.bml.title=Forslagsområde + +/suggestions/index.bml.welcome.text=Forslag fra brugerne er en vigtig del af LiveJournal. Hvis du har noget du tror kunne være en fed ide, kan du følge denne fremgangsmåde for at bringe det til dem kører sidens opmærksomhed. + +/suggestions/index.bml.welcome.title=Velkommen! + +/support/append_request.bml.back.requests=Tilbage til listen over åbne forespørgsler. + +/support/append_request.bml.back.support=Tilbage til supportområdet. + +/support/append_request.bml.bounce.noemail=Du har ikke angivet en e-mailadresse til tilbagesendelse. + +/support/append_request.bml.bounce.notauth=Du er ikke autoriseret til at tilbagesende denne forespørgsel. + +/support/append_request.bml.bounce.toomany=Du kan kun sende til op til fem e-mailadresser. Du har angivet mere end fem. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Denne supportforespørgsel er sidenhen blevet lukket. + +/support/append_request.bml.closed.title=Lukket + +/support/append_request.bml.internal.approve=For at godkende et svar skal du vælge "Intern kommentar / handling" og eventuelt forklare hvorfor du godkender det. + +/support/append_request.bml.internal.changecat=For at ændre en forespørgsels kategori skal du vælge "Intern kommentar / handling" og eventuelt forklare hvorfor du ændrer den. + +/support/append_request.bml.internal.changesum=For at ændre en forespørgsels opsummering skal du vælge "Intern kommentar / handling" og skrive den nye opsummering. + +/support/append_request.bml.internal.touch=For at ændre en forespørgsels status skal du vælge "Intern kommentar / handling" og forklare hvorfor du ændrer den. + +/support/append_request.bml.invalid.blank=Din besked var tom. Vær venlig bare at skrive noget i beskedfeltet. + +/support/append_request.bml.invalid.noanswer=<Screened> svar kan ikke godkendes. + +/support/append_request.bml.invalid.nocat=Denne kategori eksisterer tilsyneladende ikke. + +/support/append_request.bml.invalid.noid=Denne handling kræver et supportforespørgselsid. + +/support/append_request.bml.invalid.type=Ugyldig svartype. + +/support/append_request.bml.logged.text=Din handling/kommentar/dit svar er blevet gemt. Tak. + +/support/append_request.bml.logged.title=Succes + +/support/append_request.bml.login.required=Du skal logge ind for at hjælpe folk. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Tilføj kommentar/svar + +/support/append_request.bml.unknown.request=Ukendt supportforespørgsel. + +/support/encodings.bml.edit.header=Jeg kan ikke redigere mine poster i webbrugerfladen! + +/support/encodings.bml.edit.text<< +Kort svar: (anvendeligt hvis du skriver din journal på engelsk): +Gå til din side for personlige indstillinger. +Find indstillingen nær bunden af siden kaldet Autokoverter gamle poster fra:. +Vælg "Western European (Windows)" fra pull-down menuen og gem dine indstillinger. +Du skulle nu kunne redigere dine poster. p?> + +Langt svar: For at du kan redigere en ikke-unicode post, skal LiveJournals kode vide, hvilken kodning posten er blevet oprettet i. +For brugere af engelsk og andre vesteuropæiske sprog vil dette normalt være "Western European (Windows)", hvis dette dog ikke fungerer godt med citationstegn og andre lignende metategn, så prøv "Western European (ISO)". +Brugere der skriver på andre sprog bør vælge deres kodning. +Hvis denne ikke er på den opgivne liste, så kontakt supporten og forklar problemet. p?> + + +. + +/support/encodings.bml.editcl.header=Jeg kan ikke redigere mine poster i klientprogrammet! + +/support/encodings.bml.editcl.text<< + +. + +/support/encodings.bml.groups.header=Jeg kan ikke redigere min venneliste med mit klientprogram! + +/support/encodings.bml.groups.text<< +vennegrupperedigeringssiden og så bruge dit klientprogram. p?> +. + +/support/encodings.bml.overview.header=Hvad handler alt det her om? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Stadig forvirret? + +/support/encodings.bml.still.text=supportområdet. p?> + +/support/encodings.bml.title=Kodninger + +/support/faqbrowse.bml.backfaq=Tilbage til OSS'en. + +/support/faqbrowse.bml.backfaqcat=Tilbage til forælder OSS kategorien. + +/support/faqbrowse.bml.backsupport=Tilbage til supportområdet. + +/support/faqbrowse.bml.edit.faq=Rediger dette OSS + +/support/faqbrowse.bml.error.nofaq=Det angivne OSS eksisterer ikke. + +/support/faqbrowse.bml.lastupdated=Sidst opdateret: + +/support/faqbrowse.bml.title_cat=OSS - [[catname]] + +/support/faqbrowse.bml.title_num=OSS Spørgsmål #[[num]] + +/support/see_overrides.bml.error.noprivs=Kun brugere med supportviewscreened eller supporthelp privilegiet kan se en anden brugers overskrivninger. + +/support/see_overrides.bml.error.nos1=Denne bruger bruger ikke S1. + +/support/see_overrides.bml.header=Overskrivninger til : + +/support/see_overrides.bml.nooverrides=Der blev ikke fundet nogen overskrivninger til . + +/support/see_overrides.bml.title=Brugeroverskrivninger + +/talkmulti.bml.deleted.body=Kommentarerne er blevet slettet. Du kan se resten af tråden her. + +/talkmulti.bml.deleted.title=Kommentarer slettet + +/talkmulti.bml.error.comms_deleted=En af kommentarerne er blevet slettet siden du valgte den. Af sikkerhedsgrunde vil vi bede dig om at gå tilbage og prøve igen. + +/talkmulti.bml.error.invalid=Ugyldige parametre angivet. + +/talkmulti.bml.error.login=Du er ikke logget ind. + +/talkmulti.bml.error.none_selected=Du har ikke valgt nogen kommentarer. + +/talkmulti.bml.error.privs.delete=Du har ikke rettigheder til at slette disse kommentarer. + +/talkmulti.bml.title.delete=Slet flere kommentarer + +/talkpost.bml.allowedhtml=Tilladt HTML + +/talkpost.bml.error.cannotreplynopost=Du kan ikke svare på en ikke-eksisterende post + +/talkpost.bml.error.nocommentsjournal=Bruger har slået kommentarer fra i sin journal. + +/talkpost.bml.error.nocommentspost=Bruger har slået kommentarer til denne post fra. + +/talkpost.bml.error.noreplypost=Svarpå ("replyto") post ikke fundet (slettet?) + +/talkpost.bml.error.noreply_deleted=Kommentaren er blevet slettet. Du kan ikke svare på den. + +/talkpost.bml.label.picturetouse=Brug billede: + +/talkpost.bml.loganonip=Bemærk! Denne bruger har slået muligheden for at logge anonyme posteres IP-adresser til. + +/talkpost.bml.loginq=Log ind? + +/talkpost.bml.logyourip=Bemærk! Denne bruger har slået muligheden for at logge din IP-adresse når du poster til. + +/talkpost.bml.nosubjecthtml=HTML er ikke tilladt i emnet + +/talkpost.bml.opt.anonymous=Anonym + +/talkpost.bml.opt.defpic=(standard) + +/talkpost.bml.opt.friendsonly=- denne bruger har slået kommentarer fra anonyme og ikke-venner fra. Du kan poste her hvis [[username]] lister dig som en ven. + +/talkpost.bml.opt.from=Fra: + +/talkpost.bml.opt.ljuser=LiveJournal bruger: + +/talkpost.bml.opt.loggedin=Indlogget bruger: [[username]] + +/talkpost.bml.opt.message=Besked: + +/talkpost.bml.opt.noanonpost=- denne bruger tillader ikke postning fra anonyme + +/talkpost.bml.opt.noautoformat=Ingen autoformatering: + +/talkpost.bml.opt.noimage=Intet billede + +/talkpost.bml.opt.preview=Forhåndsvisning + +/talkpost.bml.opt.spellcheck=Stavekontroller post før afsendelse + +/talkpost.bml.opt.subject=Emne: + +/talkpost.bml.opt.submit=Send kommentar + +/talkpost.bml.paraformat=Afsnit vil som standard blive formateret automatisk. + +/talkpost.bml.postresponse=Skriv en kommentar som svar: + +/talkpost.bml.title=Skriv kommentar + +/talkpost.bml.usermismatch<< +Du har angivet et brugernavn, men du har fravalgt 'LiveJournal bruger' muligheden. + +Vær venlig enten at rydde tekstboksen eller at vælge den relevante sendetilstand og så prøve igen. +. + +/talkpost_do.bml.error.badpassword=Forkert kodeord for det angivne brugernavn. Du kan få dit kodeord tilbage her, hvis du har glemt det. + +/talkpost_do.bml.error.badusername=Det LiveJournal brugernavn som du har angivet eksisterer ikke. Du kan få dit brugernavn her hvis du har glemt det, eller du kan poste some "Anonym" istedet. + +/talkpost_do.bml.error.banned=Du har ikke tilladelse til at poste i denne brugers journal. + +/talkpost_do.bml.error.blankmessage=Din besked var tom. Skriv i det mindste noget i beskedfeltet. + +/talkpost_do.bml.error.confused_identity=Du skrev et brugernavn, men valgte at poste anonymt, eller som den bruger der er logget ind. Gå tilbage og vælg hvad du egentlig ønsker at gøre. + +/talkpost_do.bml.error.deleted=Din journal er blevet slettet. Du kan ikke poste beskeder. + +/talkpost_do.bml.error.friendsonly=Kun venner af [[user]] kan poste i denne journal. + +/talkpost_do.bml.error.lostcookie=Din logind cookie ser ud til at være forsvundet? + +/talkpost_do.bml.error.manybytes=Desværre, din kommentar på [[current]] overskrider den maksimale bytelængde på [[limit]]. Vær venlig at gå tilbage, forkorte den og prøv at poste igen. + +/talkpost_do.bml.error.manychars=Desværre, din kommentar på [[current]] tegn overskrider maksimum tegnlængden på [[limit]]. Vær venlig at gå tilbage, forkorte den og prøv at poste igen. + +/talkpost_do.bml.error.mustlogin=Du skal være logget ind eller bruge et brugernavn/kodeord for at svare på denne beskyttede post. + +/talkpost_do.bml.error.noanon=Du kan ikke kommentere anonymt i denne brugers journal. + +/talkpost_do.bml.error.noauth=Du har ikke rettigheder til at svare på denne beskyttede post. + +/talkpost_do.bml.error.nocomments=Bruger har slået kommentering af denne journal post fra. + +/talkpost_do.bml.error.noparent=Kan ikke svare på en ikke-eksisterende kommentar. + +/talkpost_do.bml.error.notafriend=Desværre, brugeren [[user]] har dig ikke på sin venneliste, og de har sat indstillingen om hvem der kan svare i deres journal til "kun venner". + +/talkpost_do.bml.error.nousername=Du angav ikke dit LiveJournal brugernavn. Du kan vælge at kommentere som "Anonym" hvis du ikke har en LiveJournal bruger konto. + +/talkpost_do.bml.error.noverify=Det er ikke tilladt at poste kommentarer i andre folks journaler før din e-mailadresse er blevet godkendt. Hvis du har mistet din godkendelses-e-mail hvor du kunne gøre dette, kan du få den sendt igen. + +/talkpost_do.bml.error.postshared=Du kan ikke poste som en delt konto eller som en gruppekonto. Delte konti repræsenterer grupper af folk, ikke individuelle personer. + +/talkpost_do.bml.error.suspended=Din journal er blevet suspenderet. Du kan ikke poste beskeder. + +/talkpost_do.bml.error.testacct=Testkonti kan kun blive brugt i testkonto journaler. + +/talkpost_do.bml.opt.preview=Forhåndsvisning + +/talkpost_do.bml.preview=Dette er hvordan din kommentar vil se ud når du har sendt den. Brug feltet nedenfor for at redigere yderligere i din kommentar, eller send den som den er. + +/talkpost_do.bml.preview.subject=Emne: + +/talkpost_do.bml.preview.submit=Send + +/talkpost_do.bml.preview.title=Forhåndsvisning + +/talkpost_do.bml.success.loggedin=Du er nu logget ind. + +/talkpost_do.bml.success.message=Din kommentar er blevet tilføjet. Du kan se den her. + +/talkpost_do.bml.success.title=Succes + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Kommentar sendt + +/talkpost_do.bml.title.preview=Kommentar forhåndsvisning + +/talkread.bml.anonuser=(Anonym) + +/talkread.bml.confirm.action=Er du sikker på, at du ønsker at slette de valgte kommentarer? + +/talkread.bml.deletedpost=(Slettet post) + +/talkread.bml.deleteduser=(Slettet bruger: [[username]]) + +/talkread.bml.fromip=(fra [[ip]]) + +/talkread.bml.noreplies=Ingen svar + +/talkread.bml.nosubject=(intet emne) + +/talkread.bml.replysuspended=(Svar fra suspenderet bruger) + +/talkread.bml.select=Vælg + +/talkread.bml.subjectdeleted=[slettet] + +/talkread.bml.talkmulti.delete=Slet + +/talkread.bml.title=Læs Kommentarer + +/talkscreen.bml.screened.title=Succes + +/talkscreen.bml.unscreened.title=Succes + +/tools/emailmanage.bml.address.current.title=Nuværende adresse + +/tools/emailmanage.bml.address.old.none=Ingen + +/tools/emailmanage.bml.address.old.text=Følgende er en liste over emailadresser som tidligere har været brugt med din konto, samt tiden hvor de blev deaktiveret som den primære emailadresse. Afkryds dem du ønsker at slette. + +/tools/emailmanage.bml.address.old.title=Tidligere adresser + +/tools/emailmanage.bml.delete_selected=Slet valgte + +/tools/emailmanage.bml.desc.notfirst=Denne side lader dig kun slette emailadresser som er blevet brugt siden den første gang du brugte den emailadresse som din konto er godkendt med nu. Dette betyder at en angriber ikke er i stand til at fjerne din originale emailadresse. + +/tools/emailmanage.bml.desc.text<< +Denne side lader dig fjerne tidligere e-mailadresser der blev brugt til din konto. +Hvis du fjerner en adresse vil det ikke længere være muligt at få dit kodeord sendt til den adresse. +Dette er brugbart hvis nogen opdager dit kodeord og overtager din journal. +Du får ganske enkelt bare sendt det nye kodeord til din gamle adresse, ændrer kodeordet og fjerner angriberens emailadresse. +. + +/tools/emailmanage.bml.desc.title=Beskrivelse + +/tools/emailmanage.bml.log.deleted=Slettet: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Ændringer gemt + +/tools/emailmanage.bml.notvalidated.text=Din nuværende e-mailadresse, [[email]], skal være godkendt før du kan bruge dette værktøj. Hvis du har mistet bekræftelsesemailen til at gøre dette, kan du få den gensendt. Kom tilbage hertil efter du har godkendt din email. + +/tools/emailmanage.bml.notvalidated.title=Email ikke godkendt + +/tools/emailmanage.bml.title=Email administration + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Din liste over mindeværdige poster er blevet opdateret. + +/tools/memadd.bml.body.added.header=Succes + +/tools/memadd.bml.description=Beskrivelse: + +/tools/memadd.bml.description.text<< +Giv journalposten en beskrivelse som du kan huske den på. + For at slette posten fra din liste over minderværdige poster skal du lade være med at skrive noget i beskrivelsen. +. + +/tools/memadd.bml.error.deleted.body=Journalposten tidligere beskrevet som "[[desc]]" er blevet fjernet fra din liste over mindeværdige poster. + +/tools/memadd.bml.error.deleted.title=Minde slettet + +/tools/memadd.bml.error.entry_deleted=Journalpost eksisterer ikke længere. Minde slettet. + +/tools/memadd.bml.error.fivekeywords=Kun 5 nøgleord/kategorier er tilladt per mindeværdig post. + +/tools/memadd.bml.error.invalid_security=Ugyldig eller manglende sikkerhedsindstilling. + +/tools/memadd.bml.error.login=Du skal være logget ind for at kunne bruge denne funktion. Log ind og du vil blive bragt tilbage hertil. + +/tools/memadd.bml.error.maxsize=Dette nøgleord overskrider den maksimalt tilladte størrelse: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +For at tilføje en journal post til din liste over minder skal du angive en beskrivelse. +For at slette et minde skal du redigere det og fjerne dets beskrivelse, men du havde i forvejen ikke denne post blandt dine minder. +. + +/tools/memadd.bml.error.nodescription.title=Ingen beskrivelse + +/tools/memadd.bml.form.reset=Nulstil + +/tools/memadd.bml.form.submit=Send + +/tools/memadd.bml.keywords=Nøgleord: + +/tools/memadd.bml.keywords.example=Eksempel: Sjovt, Nørdet, Romantisk + +/tools/memadd.bml.keywords.select=Eller du kan vælge nogle nøgleord du tidligere har brugt: + +/tools/memadd.bml.keywords.text=Hvorfor er denne post mindeværdig? Skriv op til fem kommaopdelte nøgleord eller kategorier så du kan finde den senere. + +/tools/memadd.bml.login.enterinfo=Angiv brugernavn og kodeord for kontoen du ønsker at gemme mindet under. + +/tools/memadd.bml.login.forgot.header=Glemt noget? + +/tools/memadd.bml.login.forgot.recover=Hvis du har glemt dit brugernavn eller kodeord, kan du genfinde det her! + +/tools/memadd.bml.multiple_selections=Hold 'kontrol'-tasten nede mens du vælger nøgleord for at vælge mere end et. + +/tools/memadd.bml.security=Sikkerhed: + +/tools/memadd.bml.security.friendsonly=Kun venner + +/tools/memadd.bml.security.private=Privat + +/tools/memadd.bml.security.public=Offentlig + +/tools/memadd.bml.title=Tilføj til minder + +/tools/memadd.bml.title.added=Tilføjet + +/tools/memadd.bml.title.add_memory=Tilføj mindeværdig post + +/tools/memadd.bml.title.deleted=Slettet + +/tools/memadd.bml.title.edit_memory=Rediger mindeværdig post + +/tools/memadd.bml.whocansee<< +Hvem kan se at du har markeret denne post som mindeværdig? + Alle, kun folk som du har på din venneliste eller kun dig selv? +. + +/tools/memories.bml.back=Tilbage + +/tools/memories.bml.body.keyword<< + +[[user]] fandt mindeværdige. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] har placeret mindeværdige journalposter i. p?> +. + +/tools/memories.bml.body.memorable=Følgende er en liste over ukategoriserede journalposter som bruger [[user]] fandt mindeværdige. + +/tools/memories.bml.edit=rediger + +/tools/memories.bml.error.noentries.body<< +Dette kan skyldes:
      +
    1. brugeren har ikke angivet nogen mindeværdige poster,
    2. +
    3. brugerens minderværdige poster er beskyttede, og du ikke har adgang til at se dem, eller
    4. +
    5. brugeren har ikke nogen minder der passer til dine filterkriterier.
    +. + +/tools/memories.bml.error.noentries.title=Ingen minder fundet. + +/tools/memories.bml.filter.all=Alle minder + +/tools/memories.bml.filter.other=Kun andre poster + +/tools/memories.bml.filter.own=Kun '[[user]]' poster + +/tools/memories.bml.form.filter=Filtrer poster efter: + +/tools/memories.bml.form.sort=Sorter poster efter: + +/tools/memories.bml.form.switch=Skift + +/tools/memories.bml.login=For at se dine egne minder, log venligst ind. + +/tools/memories.bml.plur_entry=[[num]] [[?num|post|poster]] + +/tools/memories.bml.sort.description=Beskrivelse + +/tools/memories.bml.sort.orderadded=Rækkefølge tilføjet + +/tools/memories.bml.title.keyword=Mindeværdige [[keyword]] poster + +/tools/memories.bml.title.memorable=Mindeværdige poster + +/tools/memories.bml.uncategorized=Ukategoriserede + +/update.bml.altpost=Post i journal: + +/update.bml.btn.update=Opdater journal + +/update.bml.currmood=Nuværende humør: + +/update.bml.currmusic=Nuværende musik: + +/update.bml.date=Dato: + +/update.bml.default=standard + +/update.bml.defaultjournal=([[user]]) -- standard + +/update.bml.error.cantpost=Desværre, du kan ikke poste lige nu. + +/update.bml.error.disabled=Din kontotype tillader ikke at du poster. + +/update.bml.error.disabled.title=Posteadgang slået fra + +/update.bml.error.nopass=Skriv kodeord + +/update.bml.error.update=Fejl ved opdatering af journal: + +/update.bml.full=Fuld opdaterings side + +/update.bml.htmlokay.norich=(HTML okay; som standard vil nye linier blive autoformateret til <br>) + +/update.bml.localtime=Lokal tid: + +/update.bml.loggedinas=Du er logget ind som [[user]].
    Klik her for at poste som en anden bruger. + +/update.bml.loggingin=Logger pÃ¥ serveren... + +/update.bml.noneother=Intet, eller andet: + +/update.bml.note=Bemærk: Tiden og datoen er fra vores server. Ret det til sÃ¥ det passer med din tidszone før du poster. + +/update.bml.opt.backdate=Tilbagedatér post: + +/update.bml.opt.backdate.about=vil ikke blive vist i vennevisning + +/update.bml.opt.defpic=(standard) + +/update.bml.opt.nocomments=Tillad ikke kommentarer: + +/update.bml.opt.noemail=E-mail ikke kommentarer: + +/update.bml.opt.noformat=Ingen autoformatering: + +/update.bml.opt.spellcheck=Kontroller stavning før postning + +/update.bml.options=Valgfri indstillinger + +/update.bml.other=Andet: + +/update.bml.password=Kodeord: + +/update.bml.picture=Brug billede: + +/update.bml.security.custom=Tilpas... + +/update.bml.security.friends=Venner + +/update.bml.security.head=Sikkerhedsniveau: + +/update.bml.security.private=Privat + +/update.bml.security.public=Offentlig + +/update.bml.servermsg=Serveren har ogsÃ¥ en besked til dig: + +/update.bml.simple=Du ser pÃ¥ den simple side. Klik her for flere indstillinger. + +/update.bml.spellchecked=Din stavekontrollerede post: + +/update.bml.subject=Emne: (valgfrit) + +/update.bml.timeformat=24-timers tid + +/update.bml.title=Opdater journal + +/update.bml.title.readonly=Skrivebeskyttet tilstand + +/update.bml.update.head=Opdater din journal... + +/update.bml.update.success=Succesfuld opdatering. Du kan se din opdaterede journal her. + +/update.bml.updating=Opdaterer journal... + +/update.bml.username=Brugernavn: + +/uploadpic.bml.error.unsupportedtype=Filer af typen [[filetype]] er ikke understøttede. Du kan kun uploade GIF, PNG og JPG filer. Næsten alle billed-/fotoprogrammer kan lave denne omdannelse for dig. + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.body.leave=Du kan forlade gruppen nÃ¥r som helst. + +/userinfo.bml.comminfo.body=Der er information om "[[commname]]" gruppen pÃ¥ LiveJournal nedenfor. + +/userinfo.bml.comminfo.name=Gruppeinformation + +/userinfo.bml.date.never=Aldrig. + +/userinfo.bml.error.notloggedin=Hvis du vil se din egen brugerprofil skal du logge ind. + +/userinfo.bml.friendof.hidden=(skjult) + +/userinfo.bml.friendof.syndreadcount=Antal af læsere + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Ven af: + +/userinfo.bml.friends.comm=Medlemmer + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Venner + +/userinfo.bml.label.adduser=Tilføj bruger + +/userinfo.bml.label.birthdate=Fødselsdag: + +/userinfo.bml.label.clientsused=Brugte klienter: + +/userinfo.bml.label.comments=Kommentarer + +/userinfo.bml.label.composted=Postet: [[num]] - + +/userinfo.bml.label.comreceived= Modtaget: [[num]] + +/userinfo.bml.label.datecreated=Oprettelsesdato: + +/userinfo.bml.label.dateupdated=Opdateringsdato: + +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.interests=Interesser + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] interesser ikke vist + +/userinfo.bml.label.journalentrs=Journal poster: + +/userinfo.bml.label.location=Placering: + +/userinfo.bml.label.memberof=Medlem af + +/userinfo.bml.label.memories=Minder: + +/userinfo.bml.label.moredetails=(flere detaljer...) + +/userinfo.bml.label.msnusername=MSN Brugernavn: + +/userinfo.bml.label.name=Navn: + +/userinfo.bml.label.sendmessage=Send Besked + +/userinfo.bml.label.shared|staleness=2 +/userinfo.bml.label.shared=Delt Journal Adgang: + +/userinfo.bml.label.supportpoints=Support point + +/userinfo.bml.label.user=Bruger: + +/userinfo.bml.label.viewfriends=Vis venner + +/userinfo.bml.label.viewmembers=Vis medlemmer + +/userinfo.bml.label.website=Websted: + +/userinfo.bml.memories.entries=[[count]] poster + +/userinfo.bml.memories.entry=[[count]] post + +/userinfo.bml.monitor.user=Tilføj denne bruger til din venneliste + +/userinfo.bml.nonexist.body=Brugernavnet [[user]] er ikke registreret i øjeblikket. + +/userinfo.bml.nonexist.name=Ukendt bruger + +/userinfo.bml.syn.last.never=Aldrig + +/userinfo.bml.syn.parseerror=Fejlbesked: + +/userinfo.bml.timeupdate.dayago=1 dag siden + +/userinfo.bml.timeupdate.daysago=[[num]] dage siden + +/userinfo.bml.timeupdate.hourago=1 time siden + +/userinfo.bml.timeupdate.hoursago=[[num]] timer siden + +/userinfo.bml.timeupdate.minuteago=1 minut siden + +/userinfo.bml.timeupdate.minutesago=[[num]] minutter siden + +/userinfo.bml.timeupdate.secondago=1 sekund siden + +/userinfo.bml.timeupdate.secondsago=[[num]] sekunder siden + +/userinfo.bml.timeupdate.weekago=1 uge siden + +/userinfo.bml.timeupdate.weeksago=[[num]] uger siden + +/userinfo.bml.title=Brugerinfo + +/userinfo.bml.title.communityinfo=Gruppeinfo + +/userinfo.bml.userinfo.body=Brugerinformation om [[username]] er vist nedenfor. Hvis du er denne bruger kan du redigere denne information (eller vælge hvilken information der bliver betragtet som offentlig) pÃ¥ Rediger Info siden. + +/userinfo.bml.userinfo.name=Brugerinformation + +BML.parse_multipart.toolarge=Upload for stor + +btn.search=Søg + +crumb.about=Om LiveJournal + +crumb.acctstatus=Kontostatus + +crumb.addfriend=Tilføj ven + +crumb.addtodo=Tilføj to-do punkt + +crumb.advcustomize=Tilpas avancerede S2 indstillinger + +crumb.advsearch=Avanceret + +crumb.birthdays=Fødselsdage + +crumb.changepass=Skift kodeord + +crumb.code=LiveJournal kode + +crumb.commmembers=Gruppemedlemskab + +crumb.commsearch=Gruppesøgning + +crumb.community=Gruppecenter + +crumb.contributors=Bidragydere + +crumb.createcommunity=Opret gruppe + +crumb.createjournal=Opret journal + +crumb.customize=Tilpas S2 indstillinger + +crumb.delcomment=Slet kommentar + +crumb.download=Download en klient + +crumb.editentries=Rediger poster + +crumb.editentries_do=Rediger post + +crumb.editfriendgrps=Rediger vennegrupper + +crumb.editfriends=Rediger venner + +crumb.editinfo=Personlig info + +crumb.editpics=Brugerbilleder + +crumb.editstyle=Rediger stil + +crumb.emailgateway=Email adgangspunkt + +crumb.emailmanage=Emailadministration + +crumb.encodings=Om kodninger + +crumb.faq=Ofte Stillede SpørgsmÃ¥l + +crumb.friends=Venneværktøj + +crumb.friendsfilter=Vennefilter + +crumb.goat=Om Frank + +crumb.home=Hjem + +crumb.itsfree=Det er gratis? + +crumb.joincomm=Tilmeld gruppe + +crumb.latestposts=Seneste poster + +crumb.leavecomm=Forlad gruppe + +crumb.linkslist=Dine links + +crumb.login=Log ind + +crumb.logout=Log ud + +crumb.manage=Administrer konti + +crumb.managecommunity=Gruppeadministration + +crumb.memories=Mindeværdige poster + +crumb.moderate=Gruppemoderering + +crumb.modify=Journalindstillinger + +crumb.moodlist=Humørviser + +crumb.news=Nyheder + +crumb.paidaccounts=Betalte konti + +crumb.popfaq=Populære OSS'er + +crumb.press=LiveJournal presseomrÃ¥de + +crumb.pressarticles=LiveJournal i pressen + +crumb.privacy=Fortrolighedspolitik + +crumb.register=Godkend e-mail + +crumb.search=Søg + +crumb.searchinterests=Efter interesse + +crumb.searchregion=Efter omrÃ¥de + +crumb.seeoverrides=Vis brugeroverskrivninger + +crumb.setpgpkey=Offentlig PGP-nøgle + +crumb.sitemap=Sideoversigt + +crumb.siteopts=Visningsindstillinger + +crumb.staff=Ansat personale + +crumb.stats=Statistikker + +crumb.store=LiveJournal butik + +crumb.suggview=Forslag + +crumb.todo=Todo liste + +crumb.tos=Brugsbetingelser + +crumb.update=Opdater journal + +crumb.yourlayers=Dine lag + +crumb.yourstyles=Dine stile + +date.day.friday.long=Fredag + +date.day.friday.short=Fre + +date.day.monday.long=Mandag + +date.day.monday.short=Man + +date.day.saturday.long=Lørdag + +date.day.saturday.short=Lør + +date.day.sunday.long=Søndag + +date.day.sunday.short=Søn + +date.day.thursday.long=Torsdag + +date.day.thursday.short=Tors + +date.day.tuesday.long=Tirsdag + +date.day.tuesday.short=Tirs + +date.day.wednesday.long=Onsdag + +date.day.wednesday.short=Ons + +date.month.february.long=Februar + +date.month.january.long=Januar + +date.month.july.long=Juli + +date.month.june.long=Juni + +date.month.march.long=Marts + +date.month.may.long=Maj + +date.month.may.short=Maj + +date.month.october.long=Oktober + +date.month.october.short=Okt + +dystopia.btn.login=LOG IND + +dystopia.hello_anonymous=Velkommen til LiveJournal + +dystopia.hello_loggedin=Hej [[username]]! + +dystopia.nav.contact=Kontaktinfo + +dystopia.nav.createjournal=Lav en journal + +dystopia.nav.developer=UdvikleromrÃ¥de + +dystopia.nav.editentries=Rediger poster + +dystopia.nav.editfriends=Dine venner + +dystopia.nav.editpassword=Dit kodeord + +dystopia.nav.editpics=Dine billeder + +dystopia.nav.editstyle=Rediger stil + +dystopia.nav.faq=LiveJournal OSS + +dystopia.nav.findcomm=Efter gruppe + +dystopia.nav.finddir=Katalogsøgning + +dystopia.nav.findint=Efter interesse + +dystopia.nav.findrandom=Tilfældig + +dystopia.nav.findregion=Efter omrÃ¥de + +dystopia.nav.home=Hjem + +dystopia.nav.journalcalendar=Kalender + +dystopia.nav.journalfriends=Venner + +dystopia.nav.journalinfo=Brugerinfo + +dystopia.nav.journalrecent=Seneste + +dystopia.nav.legalprivacy=Fortrolighed + +dystopia.nav.legaltos=Brugsbetingelser + +dystopia.nav.login=Log ind + +dystopia.nav.logout=Log ud + +dystopia.nav.lostinfo=Mistet kodeord + +dystopia.nav.memories=Minder + +dystopia.nav.modifyjournal=Tilpas journal + +dystopia.nav.news=Nyheder + +dystopia.nav.paidaccts=Betalte konti + +dystopia.nav.paymentarea=BetalingsomrÃ¥de + +dystopia.nav.personalinfo=Personlig info + +dystopia.nav.sitemap=Sideoversigt + +dystopia.nav.siteopts=Visningsindstillinger + +dystopia.nav.support=Har du et spørgsmÃ¥l? + +dystopia.nav.updatejournal=Opdater journal + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=127 + +dystopia.navhead.findusers=Find brugere + +dystopia.navhead.help=Hjælp & support + +dystopia.navhead.journal=Din journal + +dystopia.navhead.legal=<Legal> + +dystopia.navhead.settings=Dine indstillinger + +dystopia.navhead.welcome=Velkommen! + +dystopia.search.icq=ICQ Nummer + +dystopia.search.int=Interesse + +dystopia.search.msn=MSN Brugernavn + +dystopia.search.region=OmrÃ¥de + +dystopia.searchlj=Søg pÃ¥ LiveJournal: + +Email=Email + +email.newacct.subject=Velkommen til LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Fejl + +error.badpassword=Forkert kodeord. + +error.dberror=Der skete en database fejl: + +error.deleted.name=Slettet + +error.deleted.text=Denne journal er blevet slettet. Hvis du er [[user]] har du en periode pÃ¥ 30 dage fra tidspunktet journalen blev slettet til at gendanne den. Efter 30 dage vil alt indhold i journalen blive permanent slettet fra vores servere. + +error.deleted.title=Slettet konto + +error.nodb=Database midlertidigt utilgængelig + +error.nodbmaintenance=Denne del af databasen er midlertidigt nede pga. vedligeholdelse. Prøv igen om et par minutter. + +error.nojournal=Ukendt Journal + +error.noremote=Du skal logge ind for at kunne bruge denne side. + +error.procrequest=Der skete en fejl under behandlingen af din forespørgsel: + +error.purged.name=Slettet + +error.suspended.name=Suspenderet + +error.suspended.text=Denne konto er blevet enten midlertidigt eller permanent suspenderet. Hvis du er [[user]], bedes du venligst se pÃ¥ OSS'en med titlen Min konto er blevet suspenderet! Hvordan kan jeg fÃ¥ den tilbage? for flere oplysninger. Vær venligst opmærksom pÃ¥ at [[sitename]], for at beskytte vores brugeres privatliv, ikke kan diskutere grundene for suspenderingen med nogen anden end kontoens ejer. + +error.suspended.title=Suspenderet konto + +error.tempdisabled=Dette er midlertidigt slÃ¥et fra. + +error.unknownmode=Ukendt tilstand. + +error.usernameinvalid=Brugernavn indeholder ugyldige tegn. + +error.usernamelong=Brugernavn er for langt, højst 15 tegn. + +error.username_notfound=Brugernavn ikke fundet. + +Help=Hjælp + +label.security.custom=Tilpasset... + +label.security.friends=Venner + +label.security.head=Sikkerhedsniveau: + +label.security.private=Privat + +label.security.public=Offentlig + +label.switch.button=Skift + +label.switch.header=Skift Journal + +label.switch.workwith=Arbejd med journal: + +langname.be=Hviderussisk + +langname.da=Dansk + +langname.de=Tysk + +langname.en=Engelsk + +langname.en_GB=Engelsk (UK) + +langname.en_LJ=Engelsk + +langname.es=Spansk + +langname.et=Estisk + +langname.fi=Finsk + +langname.fr=Fransk + +langname.ga=Irsk + +langname.gd=Gælisk + +langname.he=Hebraisk + +langname.hu=Ungarsk + +langname.is=Islandsk + +langname.it=Italiensk + +langname.ja=Japansk + +langname.lv=Lettisk + +langname.ms=Malajisk + +langname.nb=Norsk BokmÃ¥l + +langname.nl=Hollandsk + +langname.nn=Nynorsk + +langname.pl=Polsk + +langname.pt=Portugisisk + +langname.ru=Russisk + +langname.sv=Svensk + +langname.tr=Tyrkisk + +langname.uk=Ukrainsk + +langname.zh=Forenklet Kinesisk + +ljcom.account.free=Gratis konto + +ljcom.account.paid=Betalt konto + +ljcom.account.paid12=Betalt for 12 mÃ¥neder ($25 USD) + +ljcom.account.paid2=Betalt for 2 mÃ¥neder ($5 USD) + +ljcom.account.paid6=Betalt for 6 mÃ¥neder ($15 USD) + +ljcom.accounttype=Kontotype + +ljcom.badpass.email=Dit kodeord mÃ¥ ikke være baseret pÃ¥ din emailadresse. + +ljcom.badpass.realname=Dit kodeord mÃ¥ ikke være baseret pÃ¥ dit rigtige navn. + +ljcom.badpass.username=Dit kodeord mÃ¥ ikke være baseret pÃ¥ dit brugernavn. + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=International [[name]] Meetup Dag + +ljcom.meetup.moreinfo=(mere info) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Vil du møde folk i den virkelige verden fra dit omrÃ¥de til at tale om denne interesse? Check [[link]] ud! + +ljcom.menu.upgrade=Opgrader din konto + +ljcom.userinfo.accounttype=Kontotype + +ljcom.userinfo.paiduser=Betalt bruger + +ljcom.userinfo.types.early=Opstartsmedlem + +ljcom.userinfo.types.free=Gratis konto + +ljcom.userinfo.types.paid=Betalt konto + +ljcom.userinfo.types.paid_early=Betalt konto, tidligere opstartsmedlem + +ljcom.userinfo.types.paid_early_expiring=Betalt konto, udløber [[paiduntil]], tidligere opstartsmedlem + +ljcom.userinfo.types.paid_expiring=Betalt konto, udløber [[paiduntil]] + +ljcom.userinfo.types.permanent=Permanent konto + +ljcom.userinfo.types.permanent_early=Permanent konto, tidligere opstartsmedlem + +ljlib.pageofpages=Side [[page]] af [[total]] + +lostinfo.head=Glemt noget? + +lostinfo.text=Hvis du har glemt dit brugernavn eller kodeord, genfind det her. + +lynx.nav.friends=Venner + +lynx.nav.help=Teknisk support + +lynx.nav.home=Hjem + +lynx.nav.login=Log ind + +lynx.nav.logout=Log ud + +lynx.nav.recent=Seneste poster + +lynx.nav.sitemap=Sideoversigt + +lynx.nav.siteopts=Visningsindstillinger + +lynx.nav.update=Opdater journal + +Password=Kodeord + +password.max30=Kodeord mÃ¥ ikke indeholde mere end 30 tegn. + +portal.memories.entriesnoun=poster + +portal.memories.entrynoun=post + +portal.memories.portalname=Minderværdige poster + +portal.memories.portaltitle=Mindeværdige poster + +portal.ministats.active=Aktive: + +portal.ministats.title=Brugerstats + +portal.ministats.total=Ialt: + +portal.popfaq.portalname=10 mest viste OSS'er + +portal.popfaq.portaltitle=10 mest viste OSS'er + +protocol.bad_password=Dit kodeord er for let at gætte. Det er anbefalet at du ændrer det, da du ellers risikerer at nogen overtager din journal. Besøg [[siteroot]]/changepassword.bml for at ændre dit kodeord. + +protocol.hello_test=Hej Testkonto! + +protocol.mail_bouncing=Du bruger for tiden en dÃ¥rlig emailadresse. Al mail vi prøver at sende til dig bliver afvist. [[sitename]] kræver en gyldig emailadresse for fortsat brug. Besøg [[siteroot]]/support/faqbrowse.bml?faqid=19 for at se hvordan du ændrer din emailadresse. + +protocol.modpost=Din post er blevet placeret i modereringskøen. Den vil blive godkendt eller afvist af en af gruppemoderatorene. + +protocol.must_revalidate=Du skal godkende din nye emailadresse. Din gamle var god, men siden du har ændret den, skal du godkende den nye. Hvis du ikke godkender din adresse vil du ikke have adgang til alle funktionerne pÃ¥ [[sitename]]. Besøg [[siteroot]]/support/faqbrowse.bml?faqid=11 for mere information. + +protocol.not_validated=Din emailadresse er ikke blevet godkendt. Du kan fortsætte med at bruge [[sitename]], men hvis du ikke godkender din adresse vil du ikke have adgang til alle sidens funktioner. Se instruktionerne der blev sendt til dig da du oprettede din journal eller besøg [[siteroot]]/support/faqbrowse.bml?faqid=11 for mere information. + +protocol.old_win32_client=Der er betydeligt nyere Windows LiveJournal klienter tilgængelige og vi anbefaler at du opgraderer. Besøg [[siteroot]]/download/ for at downloade en nyere klient. + +protocol.readonly=Din konto er midlertidigt i skrivebeskyttet tilstand. Nogle funktioner vil ikke fungere i et par minutter. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Desværre + +talk.anonwrote=Nogen skrev, + +talk.anonwrote_comm=Nogen skrev i [[commlink]], + +talk.btn.preview=ForhÃ¥ndsvisning + +talk.commentpermlink=link + +talk.commentpost=Skriv ny kommentar + +talk.commentsread=Læs kommentarer + +talk.curname_Mood=Nuværende humør: + +talk.curname_Music=Nuværende musik: + +talk.error.bogusargs=Falske argumenter + +talk.error.comm_deleted=Denne kommentar er blevet slettet. + +talk.error.deleted=Denne journal er slettet. + +talk.error.deleted.title=Slettet + +talk.error.mustlogin=Du skal være logget ind for at kunne se denne beskyttede post. + +talk.error.nocomment=Kommentaren eksisterer ikke. + +talk.error.nojournal=Fejl: kunne ikke bestemme journal ud fra argumenter. + +talk.error.notauthorised=Du er ikke autoriseret til at se denne beskyttede post. + +talk.error.suspended=Denne journal/bruger er blevet suspenderet. + +talk.error.suspended.title=Suspenderet + +talk.parentlink=Forælder + +talk.readsimilar=Læs lignende journal poster: + +talk.replytothis=Svar pÃ¥ dette + +talk.somebodywrote=[[realname]] ([[userlink]]) skrev, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) skrev i [[commlink]], + +talk.spellcheck=Kontrollér stavning under forhÃ¥ndsvisning + +talk.threadlink=TrÃ¥d + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_dansk + +Username=Brugernavn + +userpic.inactive=Inaktiv + +xcolibur.greeting.anon=Velkommen til LiveJournal! + +xcolibur.greeting.logged_in=Velkommen [[name]]! [[logout]] + +xcolibur.login=Log ind? + +xcolibur.logout=Log ud? + +xcolibur.nav.about=Om siden + +xcolibur.nav.about.general=Generel info + +xcolibur.nav.about.paidaccounts=Betalte konti + +xcolibur.nav.about.press=Presse + +xcolibur.nav.about.sitenews=Sidenyheder + +xcolibur.nav.about.stats=Statistikker + +xcolibur.nav.footer.sitemap=Sideoversigt + +xcolibur.nav.help=Hjælp + +xcolibur.nav.help.ask=Stil et spørgsmÃ¥l + +xcolibur.nav.help.contact=Kontaktinfo + +xcolibur.nav.help.faq=OSS + +xcolibur.nav.help.lostpassword=Mistet kodeord + +xcolibur.nav.home=Hjem + +xcolibur.nav.journal.archive=Arkiv + +xcolibur.nav.journal.edit.entries=Rediger poster + +xcolibur.nav.journal.friends=Venner + +xcolibur.nav.journal.memories=Minder + +xcolibur.nav.journal.recent=Nyeste + +xcolibur.nav.journal.update=Opdater + +xcolibur.nav.manage=Administrer + +xcolibur.nav.manage.community=Grupper + +xcolibur.nav.manage.customize=Tilpas + +xcolibur.nav.manage.entries=Poster + +xcolibur.nav.manage.friends=Venner + +xcolibur.nav.manage.password=Kodeord + +xcolibur.nav.manage.pics=Brugerbilleder + +xcolibur.nav.manage.styles=Stile + +xcolibur.nav.search=Søg + +xcolibur.nav.search.directory=OmrÃ¥de + +xcolibur.nav.search.directory.search=Avanceret + +xcolibur.nav.search.interests=Interesser + +xcolibur.nav.search.random=Tilfældig + +xcolibur.nav.siteopts=Visningsindstillinger + +xcolibur.nav.title=Naviger: + +xcolibur.nav.welcome=Velkommen + +xcolibur.nav.welcome.create=Lav en konto + +xcolibur.nav.welcome.login=Log ind + +xcolibur.nav.welcome.update=Opdater din journal + +xcolibur.search=Søg: + +xcolibur.search.category=Kategori: + +xcolibur.search.icq=ICQ Nummer + +xcolibur.search.int=Interesse + +xcolibur.search.msn=MSN Brugernavn + +xcolibur.search.region=OmrÃ¥de + +xcolibur.upgrade=Opgrader din konto + diff --git a/ljcom/bin/upgrading/de.dat b/ljcom/bin/upgrading/de.dat new file mode 100644 index 0000000..9fcbdc6 --- /dev/null +++ b/ljcom/bin/upgrading/de.dat @@ -0,0 +1,5145 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Status ändern + +/accountstatus.bml.error.db=Beim Bearbeiten der Anfrage ist ein Datenbank-Fehler aufgetreten. + +/accountstatus.bml.error.invalid=Ungültiger Status-Typ + +/accountstatus.bml.error.nochange.expunged=Dieser Account wurde komplett aus dem System gelöscht. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Der Status eines gesperrten Journals kann nicht verändert werden. + +/accountstatus.bml.header.success=Aktion erfolgreich + +/accountstatus.bml.journalstatus.about=Wenn du dein Journal löschen oder wieder aktivieren möchtest, dann kannst du dies hier tun. Hast du erst einmal dein Journal gelöscht, dann hast du 30 Tage Zeit, es wieder zu aktivieren, falls du dich umentscheiden sollest. Nach 30 Tagen wird das Journal permanent gelöscht werden und es wird dann keine Möglichkeit geben, es wieder zu bekommen. + +/accountstatus.bml.journalstatus.head=Aktivierungsstatus des Journals + +/accountstatus.bml.journalstatus.select.activated=Aktiviert + +/accountstatus.bml.journalstatus.select.deleted=Gelöscht + +/accountstatus.bml.journalstatus.select.suspended=Suspendiert + +/accountstatus.bml.message.nochange=Der Journal-Status bleibt bei [[statusvis]]. + +/accountstatus.bml.message.success=Der Journal-Status wurde erfolgreich zu [[statusvis]] geändert. + +/accountstatus.bml.title=Account-Status + +/allpics.bml.current=Aktuelle Benutzerbilder + +/allpics.bml.default=Standard + +/allpics.bml.edit2=Du kannst auch die Schlüsselwörter der Bilder bearbeiten oder ein neues Bild hochladen. + +/allpics.bml.error.noparam=Du musst einen Benutzernamen als Parameter angeben. + +/allpics.bml.keywords=Schlüsselwörter: + +/allpics.bml.nopics.text.other=Dieser Benutzer hat keine Benutzerbilder hochgeladen. + +/allpics.bml.nopics.text2=Du hast keine Bilder hochgeladen. Um dies zu tun, gehe hierhin. + +/allpics.bml.nopics.title=Keine Bilder + +/allpics.bml.pics=Dies sind die Benutzerbilder für [[user]]. + +/allpics.bml.title=Benutzerbilder + +/approve.bml.comm.success=Aktion erfolgreich. + +/approve.bml.comm.text<< +Du wurdest zu [[comm]] hinzugefügt. +Klicke hier, um die Community zu beobachten. +. + +/approve.bml.commjoin.text<< +Du hast die Anfrage auf Mitgliedschaft von [[user]] in [[]] bestätigt. +Die Mitgliederliste für diese Community kannst du hier abrufen, um andere Einstellungen für diesen Benutzer zu treffen. +. + +/approve.bml.error.actionperformed=Dieser Vorgang wurde bereits durchgeführt. + +/approve.bml.error.approving=Bei der Bestätigung der Mitgliedschaft ist ein Fehler aufgetreten. + +/approve.bml.error.internerr.invalidaction=Interner Fehler: ungültiger Vorgang + +/approve.bml.error.invalidargument=Ungültiger Parameter + +/approve.bml.error.unknownactiontype=Ungültiger Vorgang + +/approve.bml.shared.success=Aktion erfolgreich + +/approve.bml.shared.text<< +Dir wurde Schreibzugriff auf [[shared]] erteilt. +Klicke hier, um das Journal deiner Freundesliste hinzuzufügen. +. + +/approve.bml.title=Bestätigung des Vorgangs + +/birthdays.bml.description=Unten sind die Geburtstage aller Personen auf deiner Freundesliste angegeben. + +/birthdays.bml.title=Geburtstage + +/changepassword.bml.btn.proceed=Weiter + +/changepassword.bml.changepassword.header=Passwort ändern + +/changepassword.bml.changepassword.instructions=Fülle das unten stehende Formular aus, um dein Passwort zu ändern. Weitere Informationen für die Erstellung eines sicheren Passworts und die Sicherung deines Accounts findest du hier. + +/changepassword.bml.email.body<< +Dein Passwort bei [[sitename]] wurde geändert. + +Um es abzurufen, gehe auf die Seite + +[[siteroot]]/lostinfo.bml + +Mit freundlichen Grüßen +Das [[sitename]]-Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Passwortänderung + +/changepassword.bml.error.badcheck=Ungültiges neues Passwort: [[error]] + +/changepassword.bml.error.badnewpassword=Die Bestätigung deines Passwortes stimmt nicht mit dem neuen Passwort überein. Gib bitte beide erneut ein, da vielleicht eines falsch geschrieben wurde. + +/changepassword.bml.error.badoldpassword=Das alte Passwort stimmt nicht. + +/changepassword.bml.error.blankpassword=Das Feld "neues Passwort" muss ausgefüllt werden. + +/changepassword.bml.error.changetestaccount=Kann die Passwörter des Test-Accounts nicht ändern. + +/changepassword.bml.error.characterlimit=Passwörter können nicht länger als 30 Zeichen sein. + +/changepassword.bml.error.invaliduser=Der Benutzer [[user]] ist ungültig. Dieser Benutzer existiert nicht. Bitte überprüfe die Schreibweise des Benutzernamens. + +/changepassword.bml.error.mustenterusername=Du musst deinen Benutzernamen eingeben. + +/changepassword.bml.error.nonascii=Passwörter können nur aus ASCII-Symbolen bestehen. Bitte wähle ein Passwort, das nur ASCII-Symbole enthält. + +/changepassword.bml.error.notvalidated=Du kannst dein Passwort nicht ändern, solange deine aktuelle E-Mail-Adresse nicht bestätigt worden ist. Mehr Informationen darüber sind in der FAQ zu finden. + +/changepassword.bml.newpassword=Neues Passwort: + +/changepassword.bml.newpasswordagain=Neues Passwort (noch einmal): + +/changepassword.bml.oldpassword=Altes Passwort: + +/changepassword.bml.proceed.instructions=Klicke den nachstehenden Button, um dein Passwort zu ändern. Du wirst per E-Mail eine Bestätigung über die Passwortänderung erhalten. + +/changepassword.bml.relogin=Zusätzlich wurdest du aus sämtlichen existierenden LiveJournal-Sitzungen ausgeloggt. Du solltest dich vor dem Fortfahren wieder einloggen. + +/changepassword.bml.success.text=Dein Passwort ist geändert worden und eine E-Mail-Bestätigung wurde dir zugeschickt. + +/changepassword.bml.title=Passwort ändern + +/community/index.bml.main<< + + + + +'Newbies' anschauen, wo du viele Antworten auf brennende Fragen finden kannst. Gehe zu , schau dich ein bißchen um und in kürzester Zeit bist du dann ein Profi! +p?> + + +
    +Füge das englischsprachige Journal deiner Freundesliste hinzu, wenn du mehr über Ereignisse und aktuelle Angelegenheiten erfahren möchtest, die die ganze LiveJournal-Community etwas angehen.
    +Füge die englischsprachige Community (englisch) deiner Freundesliste hinzu, wenn du über geplante Auszeiten der Website und Berichte über ungeplante Unterbrechungen informiert werden möchtest. +Oder füge deiner Freundesliste hinzu, um eine deutsche Übersetzung der Einträge aus "News" und "LJ_Maintenance" lesen zu können.
    +p?> + + +AIM, ICQ, Yahoo!, MSN oder Jabber. Wenn du über Instant Messenger erreichbar bist, dann kannst du ihn in deinem Benutzerprofil angeben. Wenn du einen bezahlten Account hast, dann kannst du auch dein Handy oder deinen Beeper so einstellen, dass du über LiveJournal SMS erhalten kannst. +p?> + + +bezahlten Accounts. Es gibt natürlich auch eine Menge andere Arten, mitzumachen. +

    +LiveJournal ist ein Open-Source-Projekt; falls du Erfahrung mit Programmiersprachen oder Server-Anwendungen hast, dann komm in LiveJournals Entwicklungs-Community, , vorbei. Hast du Ideen zur Verbesserung von LiveJournal, dann gehe in LiveJournals Bereich für Vorschläge, . Möchtest du einfach allgemein mitmachen, dann schau mal in LiveJournals Business-Community, , nach. Hilfst du gerne Leuten, dann kannst du dies im Bereich für technischen Support tun. Wenn du dich mit Grafikdesign auskennst, dann kannst du in LiveJournals Kunst-Community, , mithelfen. +p?> + + +Anime bis Zen-Buddhismus, von Astronomie bis Invader Zim. Du kannst auch regionale Communities finden, die für Mitglieder aus bestimmten Orten auf dieser Welt sind. Es gibt wahrscheinlich auch eine LiveJournal-Community für deinen Wohnort! +p?> + + +FAQ, die dir genau erklärt, wie du deine eigene Community erstellst. Es gibt auch zwei FAQ-Kategorien (Allgemeine Fragen zu Communities und FAQs zur Community-Verwaltung), die eigentlich alles abdecken, was du jemals über Communities wissen möchtest. Brauchst du trotzdem noch Hilfe, dann kannst du auch eine Support-Anfrage schreiben. +p?> + + + + +
      +
    • Ankündigungen für neue Communities ()
    • +
    • Finde eine spezielle Community ()
    • +
    + + +Dann schreibe eine E-Mail an Jesse Proulx, () der für den Community-Bereich verantwortlich ist. +p?> +. + +/community/index.bml.title=Community-Zentrum + +/community/join.bml.button.join=Der Community beitreten + +/community/join.bml.error.already.member=Du bist bereits Mitglied dieser Community. + +/community/join.bml.error.closed=Dieser Community dürfen keine neuen Mitglieder beitreten. Wenn du gerne Mitglied sein möchtest, kontaktiere bitte einen der folgenden Maintainer: [[admins]] + +/community/join.bml.error.statusvis.body=Der zur Zeit eingeloggte Account ist kein aktiver Account. + +/community/join.bml.error.statusvis.title=Kein Community-Beitritt möglich + +/community/join.bml.label.addtofriends="[[maintainer]]" der Freundesliste hinzufügen.
    + +/community/join.bml.label.allowposting=Diese Community erlaubt es allen Mitgliedern, Beiträge zu schreiben, also kannst du ab sofort Beiträge darin schreiben. Hast du auf deinem Computer gerade einen LiveJournal-Client offen, musst du dich aus ihm ausloggen und wieder einloggen, damit dieses Journal auf der Liste der Journale angezeigt wird, in denen du Beiträge schreiben kannst. + +/community/join.bml.label.auth=Du bist zwar jetzt Mitglied dieser Community, doch dürfen in dieser Community nur autorisierte Benutzer Einträge schreiben. Kontaktiere einen der Betreiber der Community, wenn du gerne Einträge schreiben möchtest. Es folgt die Liste der Betreiber für diese Community: [[admins]] + +/community/join.bml.label.banned=Du wurdest vom/von den Betreiber/n dieser Community vom Beitritt ausgeschlossen. + +/community/join.bml.label.closed=Diese Community ist geschlossen. Würdest du ihr gerne beitreten, bitte kontaktiere einen ihrer Betreiber. Es folgt die Liste der Betreiber für diese Community: [[admins]] + +/community/join.bml.label.commlogged=Du bist als Account einer Community/eines geteilten Journals eingeloggt und nicht als dein eigener Account. + +/community/join.bml.label.errorcomminfo=Die angegebene Information für die Community ist nicht gültig. + +/community/join.bml.label.expls=Klicke den Button unten, um der "[[maintainer]]"-Community beizutreten. Entferne das Häkchen aus der Box, wenn du der Community beitreten möchtest, ohne ihre Beiträge auf deiner Freundesseite zu sehen. + +/community/join.bml.label.loginfirst=Um einer Community beizutreten, musst du dich zuerst einloggen. + +/community/join.bml.label.membernow=Du bist jetzt ein Mitglied der Community [[commname]]. + +/community/join.bml.label.sure=Bist du dir sicher? + +/community/join.bml.reqsubmitted.body=Die Beitrittsanfrage wurde an die Betreiber weitergeleitet. + +/community/join.bml.reqsubmitted.title=Beitrittsanfrage abgeschickt + +/community/join.bml.request.body=Die Community [[comm]] hat keine offene Mitgliedschaft. Bitte bestätige deinen Beitrittswunsch durch Klicken auf den unten stehenden Button. + +/community/join.bml.request.reason=Wahlweise kannst du einen Beitrittsgrund angeben: + +/community/join.bml.request.title=Beitrittswunsch + +/community/join.bml.success=Aktion erfolgreich + +/community/join.bml.title=Community beitreten + +/community/leave.bml.button.leave=Community verlassen + +/community/leave.bml.label.buttontoleave=Klicke den Button unten, um die Community "[[commname]]" zu verlassen. + +/community/leave.bml.label.infoerror=Die angegebenen Community-Informationen sind nicht gültig. + +/community/leave.bml.label.logoutfirst=Um eine Community zu verlassen, musst du dich zuerst einloggen. + +/community/leave.bml.label.removed=Du bist jetzt kein Mitglied der Community [[commname]] mehr. + +/community/leave.bml.label.removefromfriends=Entferne "[[user]]" auch von der Freundesliste. + +/community/leave.bml.success=Aktion erfolgreich + +/community/leave.bml.sure=Bist du dir sicher? + +/community/leave.bml.title=Community verlassen + +/community/manage.bml.commlist.actions=Bearbeiten + +/community/manage.bml.commlist.actmembers=[Mitglieder] + +/community/manage.bml.commlist.actmembers2=Mitglieder + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] Bewerber + +/community/manage.bml.commlist.actsettings=[Einstellungen] + +/community/manage.bml.commlist.actsettings2=Einstellungen + +/community/manage.bml.commlist.header=Deine Communities + +/community/manage.bml.commlist.moderation=Warteschlange + +/community/manage.bml.commlist.moderation.num=[[[num]] in der Schlange] + +/community/manage.bml.commlist.none=Du betreibst keine Communities. + +/community/manage.bml.commlist.text=Hier sind die Communities, die du allein oder mit anderen betreibst: + +/community/manage.bml.commlist.title=Titel + +/community/manage.bml.commlist.username=Benutzername + +/community/manage.bml.create.header=Eine Community erstellen + +/community/manage.bml.create.text=Du kannst auch eine neue Community erstellen. + +/community/manage.bml.joinmail.body=Es gibt für Communities mit beschränkter Mitgliedschaft mehrere E-Mail-Einstellungen + +/community/manage.bml.joinmail.email.all=E-Mail bei jeder Beitrittsanfrage + +/community/manage.bml.joinmail.email.digest=Eine E-Mail pro Tag mit einer Liste aller Bewerber-Einträge + +/community/manage.bml.joinmail.email.none=Keine E-Mails, statt dessen Verwendung dieser Seite + +/community/manage.bml.joinmail.save=Einstellungen speichern + +/community/manage.bml.joinmail.title=Einstellungen zur Adminstration + +/community/manage.bml.title=Community-Verwaltung + +/community/members.bml.error.alreadyadded=Der Benutzer [[user]] wurde nicht hinzugefügt, da er schon Zugriff auf diese Community hat. + +/community/members.bml.error.alreadysent=Der Benutzer [[user]] konnte nicht hinzugefügt werden, da ihm am [[datetime]] schon eine Bestätigungs-E-Mail geschickt wurde. Bitte warte auf seine Bestätigung. + +/community/members.bml.error.invaliduser=Kann keine Community oder externe Artikelquelle hinzufügen: [[user]] + +/community/members.bml.error.noaccess=Nur die Betreiber von Communities dürfen die Mitgliederlisten bearbeiten. Du bist kein Betreiber der Community [[comm]]. + +/community/members.bml.error.noattr=Keine Attribute ausgewählt für Benutzer: [[user]] + +/community/members.bml.error.nocomm=Community wurde nicht gefunden. + +/community/members.bml.error.nouser=Benutzer existiert nicht: [[user]] + +/community/members.bml.key.admin=Betreiber + +/community/members.bml.key.member=Mitglied + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Schreibzugriff + +/community/members.bml.key.preapprove=Nicht Moderieren + +/community/members.bml.key.user=Benutzer + +/community/members.bml.manage2=Communities verwalten + +/community/members.bml.name=Name der Community: [[name]] + +/community/members.bml.nextlink=(Nächste Seite...) + +/community/members.bml.prevlink=(Vorherige Seite...) + +/community/members.bml.settings=[Einstellungen] + +/community/members.bml.success.header=Aktion erfolgreich + +/community/members.bml.success.message=Deine Änderungen wurden erfolgreich gespeichert. + +/community/members.bml.success.return=Zurück zur Liste + +/community/members.bml.title=Community-Mitglieder + +/community/members.bml.update=Einstellungen aktualisieren + +/community/moderate.bml.approve.button=Ja, Eintrag akzeptieren + +/community/moderate.bml.approve.header=Diesen Eintrag akzeptieren? + +/community/moderate.bml.approve.preapprove=Den Benutzer [[user]] auch zu der Liste vorher akzeptierter Benutzer für diese Community hinzufügen. + +/community/moderate.bml.approve.text=Bist du dir sicher, dass du diesen Eintrag akzeptieren möchtest? + +/community/moderate.bml.brlist.actions=Aktionen + +/community/moderate.bml.brlist.poster=Autor des Eintrags + +/community/moderate.bml.brlist.subject=Betreff fängt an: + +/community/moderate.bml.brlist.time=Zeit + +/community/moderate.bml.brlist.view=Anschauen + +/community/moderate.bml.browse.empty=Die Moderations-Warteschlange ist leer. + +/community/moderate.bml.browse.header=Community moderieren + +/community/moderate.bml.browse.text=Hier ist die Moderations-Warteschlange für die Community [[link]] + +/community/moderate.bml.choice.approve=Akzeptieren + +/community/moderate.bml.choice.reject=Ablehnen + +/community/moderate.bml.error.noaccess=Du bist kein Moderator der Community [[comm]]. + +/community/moderate.bml.error.noentry=Eintrag wurde nicht gefunden (möglicherweise von einem anderen Moderator bearbeitet). + +/community/moderate.bml.error.nolist=Du moderierst keine Communities. + +/community/moderate.bml.error.notfound=Community-Account wurde nicht gefunden. + +/community/moderate.bml.manage=Communities verwalten + +/community/moderate.bml.moderate=Diese Community moderieren + +/community/moderate.bml.modlist.actions=Aktionen + +/community/moderate.bml.modlist.actmodempty=[Moderieren] + +/community/moderate.bml.modlist.actmoderate=Moderieren + +/community/moderate.bml.modlist.count=Größe der Warteschlange + +/community/moderate.bml.modlist.header=Communities moderieren + +/community/moderate.bml.modlist.title=Titel + +/community/moderate.bml.modlist.username=Benutzername + +/community/moderate.bml.posted.appheader=Vorher akzeptiert + +/community/moderate.bml.posted.apptext=Zusätzlich wurde Benutzer [[user]] der Liste der vorher akzeptierten Benutzer für diese Community hinzugefügt. + +/community/moderate.bml.posted.header=Aktion erfolgreich + +/community/moderate.bml.posted.proterror=Wegen des folgenden Protokollfehlers wurde der Eintrag nicht in das Journal übernommen: [[err]] + +/community/moderate.bml.posted.text=Der Eintrag wurde erfolgreich in das Journal übernommen. + +/community/moderate.bml.reject.button=Ja, Eintrag ablehnen. + +/community/moderate.bml.reject.header=Diesen Eintrag ablehnen? + +/community/moderate.bml.reject.reason=Du kannst dem Autor des Eintrags auch Gründe angeben, warum sein Eintrag abgelehnt wurde. Die Erklärung wird ihm per E-Mail zugeschickt. + +/community/moderate.bml.reject.text=Möchtest du diesen Eintrag gewiss ablehnen? + +/community/moderate.bml.rejected.header=Abgelehnt + +/community/moderate.bml.rejected.text=Dieser Eintrag wurde abgelehnt. + +/community/moderate.bml.title=Community-Moderation + +/community/pending.bml.approve.title=Mitgliedschaft bestätigen? + +/community/pending.bml.no=Nein + +/community/pending.bml.nopending.body=Es gibt keine Bewerbungen auf Mitgliedschaft für diese Community. + +/community/pending.bml.nopending.title=Keine Bewerbungen auf Mitgliedschaft + +/community/pending.bml.success.added=[[num]] [[?num|Person|Personen]] wurden dieser Community hinzugefügt. + +/community/pending.bml.success.ignored=[[num]] [[?num|Anfrage wartet|Anfragen warten]] weiterhin auf Beitritt zur Community. + +/community/pending.bml.success.previous=[[num]] [[?num|Anfrage wurde|Anfragen wurden]] nicht bearbeitet, da sie nicht mehr in der Bewerberschlange sind. Ein weiterer Betreiber könnte sie bearbeitet haben. + +/community/pending.bml.success.rejected=[[num]] [[?num|Anfrage|Anfragen]] auf Beitritt wurden abgelehnt. + +/community/pending.bml.title=Beitrittsanträge + +/community/pending.bml.yes=Ja + +/community/search.bml.button.clear=Formular löschen + +/community/search.bml.button.search=Suchen + +/community/search.bml.checkbox.onlywithpics=Nur Communities mit Bildern + +/community/search.bml.label.byinterest=Nach Interessen + +/community/search.bml.label.bylocation=Nach Ort + +/community/search.bml.label.bytime=Nach letzter Aktualisierung des Journals + +/community/search.bml.label.city=Stadt + +/community/search.bml.label.country=Land + +/community/search.bml.label.displayoptions=Darstellungsoptionen + +/community/search.bml.label.hasmember=Hat Mitglied + +/community/search.bml.label.othercriteria=Andere Kriterien + +/community/search.bml.label.outputformat=Ausgabeformat: + +/community/search.bml.label.records=Ergebnisse pro Seite + +/community/search.bml.label.searchcomm=Communities durchsuchen + +/community/search.bml.label.selecriteria=Wähle unten die Kriterien aus, nach denen du Communities finden möchtest. Die Resultate sind dann die Übereinstimmungen aller Suchkriterien. Das heißt, jedes angekreuzte Kästchen ist mit "UND" verbunden und nicht "ODER". + +/community/search.bml.label.sortmethod=Sortiermethode + +/community/search.bml.label.stateprovince=Staat/Provinz + +/community/search.bml.label.updated=Aktualisiert in den letzten + +/community/search.bml.sel.bypicture=Nach Bild + +/community/search.bml.sel.communityname=Name der Community + +/community/search.bml.sel.commview=Community-Ansicht + +/community/search.bml.sel.day=Tag + +/community/search.bml.sel.month=Monat + +/community/search.bml.sel.simple=Einfach + +/community/search.bml.sel.updatetime=Aktualisierungszeit + +/community/search.bml.sel.username=Benutzername + +/community/search.bml.sel.week=Woche + +/community/search.bml.title=Suche nach Communities + +/community/settings.bml.button.changecommunity=Einstellungen aktualisieren + +/community/settings.bml.button.createcommunity=Community erstellen + +/community/settings.bml.error.badpassword=Ungültiges Community-Passwort + +/community/settings.bml.error.hasentries=Dieser Account enthält bereits Einträge und kann nicht konvertiert werden. + +/community/settings.bml.error.maintainertype=Der Betreiber-Account muss der einer Person sein, kein anderer Community-Account. + +/community/settings.bml.error.noaccess=Nur Betreiber von Communities dürfen die Community-Einstellungen bearbeiten. Du bist kein Betreiber der Community [[comm]]. + +/community/settings.bml.error.notcomm=Kein Community-Account. + +/community/settings.bml.error.notfound=Der Community-Account wurde nicht gefunden. + +/community/settings.bml.error.samenames=Der Betreiber-Account und der Community-Account dürfen nicht identisch sein. + +/community/settings.bml.label.anybodycan=Alle Mitglieder
    Jeder darf sofort Einträge schreiben, sobald er Mitglied ist. + +/community/settings.bml.label.changeheader=Community-Einstellungen verändern + +/community/settings.bml.label.changetext=Hier kannst du die Einstellungen für die Community, die du betreibst oder besitzt, bearbeiten. + +/community/settings.bml.label.closedmemb2=Geschlossene Mitgliedschaft
    Niemand kann der Community beitreten. + +/community/settings.bml.label.commchanged=Deine Community-Einstellungen wurden verändert. + +/community/settings.bml.label.commcreate=Dies ist der Account, den du in eine Community umwandeln möchtest. Er muss bereits erstellt worden sein, aber sollte noch nicht von einer Person in Benutzung sein, da nach der Umstellung viele verschiedene Leute Einträge schreiben werden dürfen. + +/community/settings.bml.label.commcreated=Deine Community ist nun erstellt. + +/community/settings.bml.label.commheader=Community-Account + +/community/settings.bml.label.comminfo=Community-Informationen + +/community/settings.bml.label.commopts=Community-Optionen + +/community/settings.bml.label.commsite=Webseite der Community + +/community/settings.bml.label.createheader=Community erstellen + +/community/settings.bml.label.createtext=Hier kannst du einen Community-Account erstellen. Eine Community ist eine besondere Art von Account, dem andere Benutzer beitreten und dann dort Beiträge schreiben können. Um einen Eindruck zu gewinnen, schaue dir die Community "Um die Ecke" an, in der sich deutschsprachige Benutzer treffen können. + +/community/settings.bml.label.howoperates=Wähle aus, wie deine Community verwaltet wird. Du kannst sie später noch verändern. + +/community/settings.bml.label.maintainer=Betreiber: + +/community/settings.bml.label.maintainer.login=Falls dies nicht der Account des Betreibers ist, bitte logge dich mit dem richten Account ein. + +/community/settings.bml.label.managepage=Community-Verwaltung - um Mitglieder hinzuzufügen, Schreibzugriff zu erteilen, Moderatoren zu ernennen etc. + +/community/settings.bml.label.membership=Mitgliedschaft + +/community/settings.bml.label.moderatedmemb=Moderierte Mitgliedschaft
    Beitrittswünsche werden dir per E-Mail zugeschickt. + +/community/settings.bml.label.modis=Moderiert
    Neue Einträge müssen von einem Moderator akzeptiert werden. + +/community/settings.bml.label.modisnt=Nicht Moderiert
    Neue Einträge werden sofort angezeigt. + +/community/settings.bml.label.modtext=Werden Einträge in diese Community moderiert? + +/community/settings.bml.label.nmcan=Nicht-Mitglieder dürfen Einträge schreiben
    Benutzer müssen dieser Community nicht beitreten, um in ihr Einträge zu schreiben. + +/community/settings.bml.label.nmcant=Nicht-Mitglieder dürfen keine Einträge schreiben
    Benutzer müssen dieser Community beitreten, um in ihr Einträge zu schreiben. + +/community/settings.bml.label.nmheader=Einträge von Nicht-Mitgliedern + +/community/settings.bml.label.nmtext=Dürfen Benutzer in dieser Community Einträge schreiben, ohne ihr vorher beitreten zu müssen? + +/community/settings.bml.label.openmemb=Offene Mitgliedschaft
    Jeder darf ohne Bestätigung durch den Betreiber beitreten. + +/community/settings.bml.label.password=Passwort: + +/community/settings.bml.label.postaccess=Schreibzugriff + +/community/settings.bml.label.rellinks=Weiterführende Links: + +/community/settings.bml.label.selcan=Ausgewählte Mitglieder
    Nur bestimmte Mitglieder dürfen Einträge schreiben, sobald ihnen vom Betreiber Schreibzugriff erteilt wurde. + +/community/settings.bml.label.username=Benutzername: + +/community/settings.bml.label.whocanjoin=Wer darf deiner Community beitreten? + +/community/settings.bml.label.whocanpost=Der darf in dieser Community Einträge schreiben? + +/community/settings.bml.manage2=Communities verwalten + +/community/settings.bml.members=[Mitglieder] + +/community/settings.bml.name=Name der Community: [[name]] + +/community/settings.bml.success=Aktion erfolgreich + +/community/settings.bml.title.create=Community erstellen + +/community/settings.bml.title.modify=Community-Einstellungen + +/create.bml.age.check.question=Bist Du jünger als 13 Jahre? + +/create.bml.age.check.yes=Ja, ich bin jünger als 13 Jahre. + +/create.bml.age.check2.question=Bist du älter als 13 Jahre? + +/create.bml.age.check2.yes=Ja, ich bin älter als 13 Jahre. + +/create.bml.age.head=Alter + +/create.bml.btn.create=Journal erstellen + +/create.bml.btn.proceed=Weiter... + +/create.bml.captcha.answer=Antwort: + +/create.bml.captcha.audiodesc=Gib die gehörten Nummern ein, um zu beweisen, dass du kein Spam-Roboter bist. + +/create.bml.captcha.desc=Gib die unten angegebenen Buchstaben und Nummern ein um zu beweisen, dass du kein Spam-Roboter bist. Wenn du den Text nicht lesen kannst, gib bitte "AUDIO" ein, um statt dessen einen Audio-Test zu machen. + +/create.bml.captcha.invalid=Ungültige Antwort auf vorherige Frage. Versuche es noch einmal. + +/create.bml.captcha.play=Sound abspielen + +/create.bml.captcha.prove=Beweise, dass du wirklich ein Mensch bist. + +/create.bml.clusterselect.head=Cluster-Auswahl + +/create.bml.clusterselect.nocluster=Kein Cluster + +/create.bml.clusterselect.text=Bitte wähle den Cluster aus, in dem dieser Account angelegt werden soll. Anmerkung: Dies ist nur eine Option fürs Testen bzw. Debuggen. Benutzer werden in der Praxis keine solche Auswahloption haben, noch etwas darüber wissen. + +/create.bml.create.head=Ein neues Journal anlegen + +/create.bml.create.text=Es ist einfach, ein neues Journal anzulegen. Folge einfach den nachfolgenden Anweisungen. + +/create.bml.email.head=Deine E-Mail-Adresse + +/create.bml.email.input.head=E-Mail-Adresse: + +/create.bml.email.text2=Zur Bestätigung deines Accounts und aus Sicherheitsgründen benötigen wir deine E-Mail-Adresse. Sie wird niemals an Spammer vergeben oder verkauft werden. Wir hassen das mehr als alles andere. Weitere Informationen darüber gibt es in unserer Datenschutzerklärung. + +/create.bml.error.coppa.under13=Aufgrund der Jugendschutzbestimmungen kannst du LiveJournal nicht benutzen, sofern du nicht mindestens 13 Jahre alt bist. Bitte komm an deinem 13. Geburtstag wieder. + +/create.bml.error.email.blank=Du musst deine E-Mail-Adresse angeben. + +/create.bml.error.email.lj_domain=Bei der Erstellung von Accounts kann kein [[domain]]-Alias verwendet werden. Bitte gib eine andere E-Mail-Adresse ein. + +/create.bml.error.email.nospaces=In der E-Mail-Adresse sind keine Leerzeichen erlaubt. Falls du AOL benutzt, besteht deine E-Mail-Adresse aus deinem Screennamen ohne Leerzeichen, gefolgt von @aol.com + +/create.bml.error.password.asciionly=Im Passwort sind nur ASCII-Zeichen erlaubt. + +/create.bml.error.password.blank=Du musst ein Passwort angeben. + +/create.bml.error.password.nomatch=Die Passwörter stimmen nicht überein. + +/create.bml.error.postrequired=POST erforderlich. + +/create.bml.error.username.blank=Bitte gib einen Benutzernamen an. + +/create.bml.error.username.inuse=Dieser Benutzername ist bereits vergeben; bitte wähle einen anderen. + +/create.bml.error.username.iscode=Der Benutzername scheint ein Einladungscode zu sein und nicht ein Benutzername. + +/create.bml.error.username.mustenter=Du musst einen Benutzernamen eingeben. + +/create.bml.error.username.reserved=Das ist leider ein reservierter Benutzername. + +/create.bml.errors.label=Bitte beachte die folgenden Probleme und schicke die Anfrage erneut ab. + +/create.bml.initial.friend.lj_maintenance=Berichte über geplante und ungeplante Wartungsarbeiten und Ausfallzeiten + +/create.bml.initial.friend.news=Nachrichten und Ereignisse bei LiveJournal + +/create.bml.initialfriends=Füge diese beiden Journale deiner Freundesliste hinzu, um immer über LiveJournal auf dem Laufenden zu sein. + +/create.bml.initialfriends.heading=Erste Freunde + +/create.bml.name.head=Dein Name + +/create.bml.name.text=Wie heisst du oder wie möchtest du dich nennen? Dieser Name erscheint über deinem Journal und im Benutzerverzeichnis, sofern du dort erscheinen möchtest. Du musst nicht deinen vollständigen oder wirklichen Namen angeben. + +/create.bml.password.head=Passwort + +/create.bml.password.input.head1=Passwort: + +/create.bml.password.input.head2=Passwort bestätigen + +/create.bml.password.text=Wähle ein Passwort. + +/create.bml.proceed.btn.proceed=Weiter... + +/create.bml.proceed.warning=Drücke Weiter nur einmal!! + +/create.bml.success.btn.enterinfo=Persönliche Informationen eingeben + +/create.bml.success.head=Aktion erfolgreich + +/create.bml.success.text1=Dein Journal wurde erstellt. Wichtige Registrierungsinformationen mit weiteren Anweisungen wurden per E-Mail an [[email]] gesandt. Vergewissere dich, die Erstellung deines Journals auch wirklich zu bestätigen, indem du auf den Link in der E-Mail klickst. + +/create.bml.success.text2=Du findest dein LiveJournal unter: + +/create.bml.success.text3=Bitte nimm dir die Zeit, einige Informationen über dich einzugeben. Die meisten Eingaben sind freiwillig, aber gib uns ein paar Anhaltspunkte, wer LiveJournal benutzt. + +/create.bml.title=Neues Journal anlegen + +/create.bml.tos.error=Du musst die Nutzungsbedingungen lesen und ihnen zustimmen, bevor du einen Account erstellst. + +/create.bml.tos.haveread=Ich habe die Nutzungsbedingungen gelesen und ihnen zugestimmt. + +/create.bml.tos.heading=Nutzungsbedingungen + +/create.bml.tos.p1.2=Bevor du weiter machst, musst du unsere Allgemeine Geschäftsbedingungen lesen und ihnen zustimmen. + +/create.bml.useacctcodes.entercode=Um einen neuen Account zu erstellen, gib einen Einladungscode ein. Weitere Informationen dazu findest du in der FAQ "Wie erstelle ich einen Account?" + +/create.bml.useacctcodes.welcome=Willkommen + +/create.bml.username.box.head=Benutzername: + +/create.bml.username.charsallowed=Dein Benutzername darf nur klein geschriebene Buchstaben (a-z), Ziffern (0-9) und den Unterstrich (_) enthalten. Außerdem darf er 15 Zeichen nicht überschreiten. + +/create.bml.username.forpaidaccts=Oder für bezahlte Accounts: + +/create.bml.username.head=Benutzername + +/create.bml.username.ljaddress=Dein Journal ist unter folgenden Adressen zu finden: + +/create.bml.username.text=Jeder [[sitename]]-Benutzer muss einen eindeutigen Benutzernamen haben. Dein Benutzername erscheint in der Adresse deines Journals und wird beim Einloggen verwendet. Er erscheint auch, wenn du Kommentare in anderen Journalen schreibst. + +/create.bml.username.username=Benutzername + +/customize/index.bml.change=Wechseln + +/customize/index.bml.choose=Möchtest du das alte oder das neue Stilsystem verwenden? + +/customize/index.bml.choose.header=Stilsystem auswählen + +/customize/index.bml.choose.s1=Altes System (S1) + +/customize/index.bml.choose.s2=Neues System (S2) + +/customize/index.bml.error.cant_generate_user_layer=Konnte Benutzer-Layer nicht erstellen + +/customize/index.bml.error.fail_create_style=Konnte neuen Stil nicht erstellen. + +/customize/index.bml.error.not_your_layout=Nicht dein Layout. + +/customize/index.bml.error.not_your_theme=Nicht dein Farbschema + +/customize/index.bml.error.no_core_parent=Kein übergeordnetes Core-Layer? + +/customize/index.bml.previews=(Vorschau) + +/customize/index.bml.s1=Das alte Stilsystem wird auf der Seite Design verändern bearbeitet. + +/customize/index.bml.s1.header=S1 wird verwendet + +/customize/index.bml.s2.advanced.denied=Nur die Inhaber bezahlter, permanenter und Früheinsteiger-Accounts können die erweiterte Anpassung verwenden. Finde mehr über die Vorzüge eines bezahlten Accounts heraus. + +/customize/index.bml.s2.advanced.header=Erweiterte Anpassung + +/customize/index.bml.s2.advanced.permitted=Um komplett neue Layer und Stile zu erstellen, gehe auf die Seite der erweiterten Anpassung. + +/customize/index.bml.s2.customize=Die folgenden Einstellungen sind vom jeweiligen Layout abhängig. + +/customize/index.bml.s2.customize.header=Schritt 2: Layout bearbeiten + +/customize/index.bml.s2.customize.language=Die folgenden Sprachen werden vollständig oder teilweise von diesem Layout unterstützt. + +/customize/index.bml.s2.customize.language.custom=(Benutzerdefiniert) + +/customize/index.bml.s2.customize.language.header=Sprache + +/customize/index.bml.s2.customize.settings=Möchtest du dein Journal noch weiter bearbeiten, dann kannst du hier persönliche Einstellungen verändern, damit es genau so aussieht, wie du es möchtest. + +/customize/index.bml.s2.customize.settings.delete=Einstellungen entfernen + +/customize/index.bml.s2.customize.settings.delete.confirm=Sollen diese Anpassungen ganz sicher entfernt werden? + +/customize/index.bml.s2.customize.settings.edit=Einstellungen bearbeiten + +/customize/index.bml.s2.customize.settings.header=Persönliche Einstellungen verändern + +/customize/index.bml.s2.customize.settings.new=Bearbeiten + +/customize/index.bml.s2.customize.themes=Du kannst hier eines der folgenden Farbschemen für dein Layout auswählen. + +/customize/index.bml.s2.customize.themes.default=(Standard) + +/customize/index.bml.s2.customize.themes.header=Farbschemen + +/customize/index.bml.s2.layout=Wähle dein Layout aus. Da die Auswahl von Farbschemen und die persönlichen Einstellungen vom jeweiligen Layout abhängen, wird eine Änderung der Layout-Einstellung alle anderen von dir getroffenen Einstellungen verwerfen. + +/customize/index.bml.s2.layout.header=Schritt 1: Layout + +/customize/index.bml.s2.related.editinfo.about=Stelle die Überschriften für dein Journal ein und weitere Optionen. + +/customize/index.bml.s2.related.header=Ähnliche Seiten + +/customize/index.bml.s2.related.links.about=Einige Stile beinhalten die von dir erstellte Link-Liste. + +/customize/index.bml.s2.related.modify.about=Stelle das Stimmungsmotiv für dein Journal ein. + +/customize/index.bml.title=Journal bearbeiten + +/delcomment.bml.changeoptions=Beachte: Auf der Seite [[link]] kannst du auswählen, ob jeder, nur registrierte Benutzer oder nur Freunde Kommentare hinterlassen dürfen. + +/delcomment.bml.confirm.banuser=Benutzer [[user]] vom Kommentieren in deinem Journal ausschließen. + +/delcomment.bml.confirm.body=Bist du sicher, dass du diesen Kommentar löschen möchtest? + +/delcomment.bml.confirm.head=Diesen Kommentar löschen? + +/delcomment.bml.confirm.spam=Diesen Kommentar als Spam markieren + +/delcomment.bml.confirm.submit=Kommentar löschen + +/delcomment.bml.error.alreadydeleted=Der angegebene Kommentar wurde bereits gelöscht. + +/delcomment.bml.error.cantdelete=Ein Kommentar kann nur von seinem Autor oder dem Besitzer des Journals gelöscht werden. + +/delcomment.bml.error.cantdelete.comm=Ein Kommentar kann nur von seinem Autor, dem Autor des Journal-Eintrags oder einem Betreiber der Community gelöscht werden. + +/delcomment.bml.error.invalidtype=Ungültiger Kommentartyp. Diese Seite kann nur Kommentare auf Journal-Einträge verarbeiten. + +/delcomment.bml.error.nocomment=Der angegebene Kommentar existiert nicht. + +/delcomment.bml.success.andban=Der Kommentar ist gelöscht worden und Benutzer [[user]] ist aus deinem Journal ausgeschlossen worden. + +/delcomment.bml.success.head=Gelöscht + +/delcomment.bml.success.noban=Der Kommentar ist gelöscht worden. + +/delcomment.bml.success.spam=Außerdem wurden die Administratoren benachrichtigt, dass es sich bei diesem Kommentar um Spam handelte. Danke für deine Meldung. + +/delcomment.bml.title=Kommentar löschen + +/developer/index.bml.clients<< +Du möchtest also auf deinem Betriebssystem einen LiveJournal-Client erstellen oder verbessern? Wunderbar! +Unten kannst du ein paar wichtige Informationen über die Funktionsweise von LiveJournal finden. +. + +/developer/index.bml.clients.header=LiveJournal-Clienten erstellen + +/developer/index.bml.clients.links<< +
    +
    Das LiveJournal Server<->Client Protokoll
    +
    Finde heraus, wie der LiveJournal-Client auf deinem Desktop mit dem LiveJournal-Server kommuniziert und anders herum. Dieses Wissen ist grundlegend für das Entwickeln oder Verbessern eines Clients für dein Betriebssystem.
    +
    Vollständige Protokoll-Dokumentation
    +
    Alle verschiedenen Protokoll-Arten und -Methoden.
    +
    Liste der Clients
    +
    Eine Liste der meisten Clients, die zur Verbindung zu LiveJournal verwendet werden. Die Mehrheit dieser Clients unterliegt der Open-Source-Lizenz und alle der Clients können kostenlos benutzt werden. Du kannst hier hervorragend Beispiele für deinen Client finden.
    +
    +. + +/developer/index.bml.code=Um den Code zu sehen, der LiveJournal am Laufen hält oder um ein paar der verfügbaren Clients ganz genau unter die Lupe zu nehmen, gehe auf die Seite Quelltext. + +/developer/index.bml.code.header=LiveJournal-Quelltext + +/developer/index.bml.dbschema=Bist du neugierig auf das Datenbankschema? Das SQL zur Erstellung aller Tabellen und wie man sie ausfüllt ist beim Server-Code inbegriffen. + +/developer/index.bml.dbschema.header=Datenbankschema + +/developer/index.bml.embedding=Möchtest du dein Journal auf deiner Homepage einbetten? Es gibt verschiedene Möglichkeiten, dies zu tun, je nach dem, welche Kontrolle du über deinen Server hast. Darüber musst du dir nur Gedanken machen, wenn www.livejournal.com nicht in dem URL deines Journals stehen soll. + +/developer/index.bml.embedding.header=Einbettung von LiveJournal + +/developer/index.bml.notice.header=Bemerkung + +/developer/index.bml.notice1<< +Die folgenden Informationen sind ausschließlich für Programmierer und fortgeschrittene Benutzer gedacht. +Wenn du LiveJournal lediglich als Tagebuch verwenden möchtest, dann ist das auch super! Dann muss man sich um die Informationen hier keine Gedanken machen. +. + +/developer/index.bml.notice2=Die unten angegebenen Informationen sind in zwei Bereiche geteilt: Informationen, wie man das Aussehen der LiveJournal-Seiten bearbeitet und Informationen, wie man LiveJournal-Clients für den LiveJournal-Server erstellt. + +/developer/index.bml.styles=Magst du die Art, wie dein Journal aussieht, nicht? Keine Sorge - alles kann verändert werden; wenn du die Dokumentation weiter unten liest, wirst du alles erfahren, was zum Verändern des Aussehens deiner Seiten nötig ist. + +/developer/index.bml.styles.header=Das Aussehen eines LiveJournals verändern + +/developer/index.bml.styles.s1.header=Stilsystem 1 + +/developer/index.bml.styles.s1.system=Stilsystem + +/developer/index.bml.styles.s1.system.about=Allgemeiner Ãœberblick über den Aufbau des ersten Stilsystems + +/developer/index.bml.styles.s1.varlist=Liste der Variablen + +/developer/index.bml.styles.s1.varlist.about=Alphabetische Liste aller veränderbaren Variablen + +/developer/index.bml.styles.s1.views=Arten anschauen + +/developer/index.bml.styles.s1.views.about=Eine Liste der unterschiedlichen Arten, dein Journal anzuschauen, inklusive Details über jede Art. + +/developer/index.bml.styles.s2.header=Stilsystem 2 + +/developer/index.bml.styles.s2.layerbrowse=S2-Layer-Browser + +/developer/index.bml.styles.s2.layerbrowse.about=Eine vollständige Liste öffentlicher S2-Layer, aus denen die Stile des S2-Systems bestehen. Hier sind die Kern-Layer wichtig, welche die Grundvariablen, -funktionen und -klassen definieren, die S2 zu der leistungsfähigen Design-Sprache machen, die es ist. + +/developer/index.bml.styles.s2.manual=Das S2-Handbuch + +/developer/index.bml.styles.s2.manual.about=Umfassende Informationen über die Verwendung von S2 bei LiveJournal + +/developer/index.bml.title=Informationen für Entwickler + +/directory.bml.browse.country.desc=Wähle ein Land aus, um Journale aus diesem Land zu lesen. + +/directory.bml.browse.country.title=Journale nach Ländern geordnet anschauen + +/directory.bml.browse.usa.desc=Klicke auf einen US-Staat, um Journale aus diesem Staat zu lesen, oder klicke auf einen Ländernamen unterhalb der Karte, um Journale aus dem jeweiligen Land zu lesen. + +/directory.bml.browse.usa.title=Journale nach US-Staaten geordnet anschauen + +/directory.bml.error.accounttype=Dein Accounttyp erlaubt leider nicht die Benutzung des Verzeichnisses oder du bist gerade nicht eingeloggt. Falls dein Accounttyp doch die Benutzung des Verzeichnisses erlaubt, überprüfe bitte, ob du eingeloggt ist und versuche es noch einmal. + +/directory.bml.navcrap.matches=[[count]] Treffer + +/directory.bml.navcrap.xofy=Seite [[curpage]] of [[totpages]] angezeigt (zeigt an: [[reca]]-[[recb]]) + +/directory.bml.open=Öffnen + +/directory.bml.post=Eintrag schreiben + +/directory.bml.search.monkey=Eine Horde dressierter Affen wurde gerade losgelassen, um deine Suchergebnisse zu finden. Einen Moment Geduld bitte. + +/directory.bml.search.new=Neue Suche + +/directory.bml.search.overflow=Suchergebnisse sind auf [[count]] Ergebnisse begrenzt. Bitte verfeinere deine Suche. + +/directory.bml.search.title=Suche + +/directory.bml.user=Benutzer + +/doc/index.bml.about=Willkommen im Bereich der LiveJournal-Dokumentation, wo du Informationen über die meisten Themen finden kannst, die die Server-Software und den Service von LiveJournal betreffen. Bitte wähle eines der unten angegebenen Themen aus: + +/doc/index.bml.about.header=Willkommen + +/doc/index.bml.docs.faq.about=Häufige Fragen über LiveJournal.com + +/doc/index.bml.docs.guides.about=Hilfreiche FAQ-Informationen + +/doc/index.bml.docs.guides.title=Anleitungen + +/doc/index.bml.docs.header=Dokumente + +/doc/index.bml.docs.howto.about=Tipps und Tricks zum Verändern deines LiveJournal-Layouts + +/doc/index.bml.docs.server.about=Alles, was du über das Installieren, Verwalten und Verändern eines LiveJournal-Setups wissen solltest. + +/doc/index.bml.docs.server.title=LiveJournal Server-Handbuch + +/doc/index.bml.docs.tour.about=Entworfen für Besucher, die sich mit LiveJournal vertraut machen wollen + +/doc/index.bml.title=Dokumentation + +/doc/index.bml.volunteering.about=Möchtest du mit der Dokumentation bei LiveJournal aushelfen, schau dir die folgenden Foren an: + +/doc/index.bml.volunteering.header=Freiwillige Arbeit + +/doc/index.bml.volunteering.ljsysdoc=Diskussionen über das System der LiveJournal-Dokumentation + +/doc/index.bml.volunteering.ljuserdoc=Diskussionen der Benutzer über die Dokumenation + +/doc/tour/index.bml.clients.caption<< +LiveJournal-Clients sind kleine Programme für deinen Computer, die es dir erlauben, dein LiveJournal zu aktualisieren, wann immer du online bist, ohne dass du erst ein Browserfenster dazu öffnen musst. +Clients sind für die meisten Betriebssysteme verfügbar und viele von ihnen verfügen über benutzerdefinierbare Einstellungen. +. + +/doc/tour/index.bml.comms.caption=LiveJournal ist eine große interaktive Gemeinschaft. Es sollte dich daher nicht überraschen, viele Mitglieder mit ähnlichen Interessen zu finden. Deswegen bietet LiveJournal die Möglichkeit, Communities zu erstellen, bzw. Journale, in denen viele Benutzer Einträge schreiben können. + +/doc/tour/index.bml.create.caption=LiveJournal ist eine Online-Gemeinschaft, in der viele Mitglieder Journale führen können. Diese Seite erklärt, was diese Mitgliedschaft umfasst, warum eine Mitgliedschaft wichtig ist und gibt einen Ãœberblick über ihre Vorzüge. Weiterhin gibt es auf dieser Seite ein Formular zum Erstellen eines Accounts. + +/doc/tour/index.bml.create.title=Einen Account erstellen + +/doc/tour/index.bml.friends.caption<< +Du kannst über LiveJournal auch mit der Situation deiner Freunde auf dem Laufenden bleiben, indem du das LiveJournal-"Freunde"-Feature verwendest. +Findest du ein interessantes Journal, kannst du es deiner Freundesliste hinzufügen, die dich alle aktuellen Einträge deiner Freunde auf einer Seite lesen lässt. +. + +/doc/tour/index.bml.friends.title=Freunde + +/doc/tour/index.bml.intro.caption<< +Diese Tour wurde für Besucher eingerichtet, die LiveJournal kennenlernen möchten. +Sie wird euch einge der interessantesten Features zeigen und wo sich die wichtigsten Bereiche befinden. +. + +/doc/tour/index.bml.intro.title=Willkommen + +/doc/tour/index.bml.modify.caption=Du kannst das Design deines Journals auch auf verschiedene Arten verändern, indem du vordefinierte Stile und Farbthemen verwendest. Gestalte dein Journal so, wie du gerne möchtest! + +/doc/tour/index.bml.modify.title=Personalisieren + +/doc/tour/index.bml.nav.next=Weiter --> + +/doc/tour/index.bml.nav.prev=<-- Zurück + +/doc/tour/index.bml.profile.caption=Die Mitglieder von LiveJournal werden gebeten, Informationen über sich in ihre Profile einzutragen, so dass man einen Eindruck davon gewinnen kann, wer diese Webseite verwendet und mit Hilfe dieser Informationen den Bedürfnissen der Benutzer am besten nachkommen kann. Diese Informationen sind jedoch nicht obligatorisch — die einzigen Informationen, die zum Erstellen eines LiveJournals benötigt werden, sind ein Name, eine E-Mail-Adresse und ein Passwort. + +/doc/tour/index.bml.profile.title=Benutzerprofile + +/doc/tour/index.bml.sitemap.caption<< +Hoffentlich hat dir diese Tour einige hilfreiche Startpunkte gegeben, um dich auf der LiveJournal-Seite zurechtzufinden und dir einen Ãœberblick über ihre Dienste zu bieten. +Brauchst du Hilfe, was LiveJournal betrifft, tritt ruhig in Kontakt mit dem unserem Support Team. Möchtest du LiveJournal weiter erkunden, kannst du in der Sitemap alle Seiten von LiveJournal einsehen. +. + +/doc/tour/index.bml.sitemap.title=Sitemap + +/doc/tour/index.bml.support.caption=Auf den Support-Seiten gibt es Erklärungen zu LiveJournal, häufige Fragen über die Seite und weitere hilfreiche Informationen über die Features, die Firma und die LiveJournal-Community im Allgemeinen. + +/doc/tour/index.bml.support.title=Brauchst du Hilfe? + +/doc/tour/index.bml.update.caption=Das Aktualisieren eines LiveJournals ist der Kern von LiveJournal. Hier können Mitglieder Einblick in ihr Leben geben und ihre Gedanken mit anderen teilen. Es ist einfach, seinem Journal einen neuen Eintrag hinzuzufügen: Man schreibt einfach einen Eintrag in das entsprechende Textfeld und klickt auf "Eintrag speichern". Natürlich werden auf der Seite zum Aktualisieren auch erweiterte Funktionen angeboten, wie die Möglichkeit einer Rechtschreibkontrolle (im Moment ist diese Funktion nur für amerikanisches Englisch verfügbar) oder die Option, den Eintrag mit zusätzlichen Informationen zu versehen, wie die aktuelle Stimmung oder die aktuelle Musik. + +/doc/tour/index.bml.update.title=Einträge schreiben + +/editinfo.bml.advanced.about=Falls du nicht weißt, wofür diese Optionen stehen, dann kümmere dich nicht weiter um sie. + +/editinfo.bml.advanced.title=Erweiterte Optionen + +/editinfo.bml.allowshowcontact.about=Diese Option solltest du aktiviert lassen. Andere Leute können dich dadurch kontaktieren, da in deinem LiveJournal deine E-Mail-Adresse, die ICQ-Nummer und der Benutzername des AOL Instant Messengers zu sehen sind. + +/editinfo.bml.allowshowcontact.email=Anzuzeigende E-Mail-Adresse (wenn die Adressen sichtbar sind): + +/editinfo.bml.allowshowcontact.email.actual_only=Nur die eigentliche Adresse + +/editinfo.bml.allowshowcontact.email.both=Beide (die eigentliche + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Nur die LiveJournal-Adresse. + +/editinfo.bml.allowshowcontact.email.neither=Keine von beiden Adressen anzeigen. + +/editinfo.bml.allowshowcontact.email.no_show=E-Mail-Adresse nicht anzeigen. + +/editinfo.bml.allowshowcontact.email.show=E-Mail-Adresse anzeigen + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Mit dieser Option kannst du auswählen, ob deine E-Mail-Adresse nicht angezeigt werden soll (während andere Informationen weiterhin angezeigt werden), oder ob nur deine LiveJournal-E-Mail-Adresse (nur bei bezahlten Accounts), nur deine eigentliche E-Mail-Adresse oder beide angezeigt werden sollen. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Mit dieser Option kannst du auswählen, ob deine E-Mail-Adresse nicht angezeigt werden soll (während andere Informationen weiterhin angezeigt werden). + +/editinfo.bml.allowshowcontact.title=In deinem LiveJournal deine Kontaktinformationen anzeigen? + +/editinfo.bml.allowshowinfo.about=Schalte diese Option an, wenn anderen Benutzern dein Ort, dein Bundesland/Kanton und dein Geburtstag sichtbar sein sollen. + +/editinfo.bml.allowshowinfo.title=Ort & Geburtstag anzeigen? + +/editinfo.bml.autotranslate.about<< +Verwende diese Option dazu, LiveJournal mitzuteilen, welche Codierung es für deine Einträge und Kommentare verwenden soll, die geschrieben wurden, bevor LiveJournal zu Unicode konvertiert wurde. + +Wenn du auf Deutsch schreibst, wähle hier "Westeuropäisch" (Western European). +. + +/editinfo.bml.autotranslate.header=Ältere Einträge automatisch konvertieren von: + +/editinfo.bml.bday.title=Geburtstag + +/editinfo.bml.bday.year.opt=Jahr ist optional + +/editinfo.bml.bdayreminders.about=Möchtest du E-Mails bekommen, die dich an die Geburtstage deiner Freunde in LiveJournal erinnern, setze ein Häkchen in diesem Kästchen. + +/editinfo.bml.bdayreminders.header=Geburtstagsbenachrichtigungen schicken (zur Zeit nicht möglich) + +/editinfo.bml.bio.about=Hier kannst du eine kleine Biographie über dich eingeben. Diese wird in deinem Benutzerprofil angezeigt. + +/editinfo.bml.bio.header=Ãœber dich + +/editinfo.bml.blockrobots.about=Wenn du diese Option aktivierst, wird den Robots gesagt, dass sie weggehen sollen. Nicht alle Robots halten sich an diese Regel. + +/editinfo.bml.blockrobots.header=Robots/Spiders von der Indizierung deines Journals abhalten. + +/editinfo.bml.chat.msnusername.title=MSN Benutzername + +/editinfo.bml.city.title=Ort + +/editinfo.bml.country.choose=Wähle ein Land aus + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Nein + +/editinfo.bml.email.title=E-Mail + +/editinfo.bml.enableboards.about=Aktiviere diese Option, um es Leuten zu erlauben, auf deine Journaleinträge antworten zu können. + +/editinfo.bml.enableboards.header=Kommentare erlauben + +/editinfo.bml.encoding.about=Die folgenden Optionen betreffen normalerweise nur internationale Benutzer, die verschiedene Sprachen in ihren Journalen benutzen. + +/editinfo.bml.encoding.header=Codierungsoptionen + +/editinfo.bml.error.day.notinmonth=Ungültiger Tag für diesen Monat + +/editinfo.bml.error.day.outofrange=Ungültiger Geburtstag. Gib eine Zahl zwischen 1 und 31 ein. + +/editinfo.bml.error.email.lj_domain<< +Du darfst keine @[[domain]] E-Mail-Adresse eingeben. +Gib deine wirkliche E-Mail-Adresse in das Feld ein. +Wenn du ein zahlender Benutzer bist, wird deine [[user]]@[[domain]]-Adresse die E-Mails an deine eigentliche Adresse weiterleiten. +Um auszuwählen, welche der Adressen öffentlich angezeigt werden, gehe zu der Option "Kontaktinformation anzeigen". +. + +/editinfo.bml.error.email.none=Du mußt deine E-Mail-Adresse angeben. + +/editinfo.bml.error.email.no_space<< +In einer E-Mail-Adresse dürfen keine Leerzeichen enthalten sein. +Benutzt du AOL, ist deine Internet-E-Mail-Adresse dein Webname, aus dem alle Leerzeichen entfernt sind, und dann @aol.com +. + +/editinfo.bml.error.excessive_int=Du hast leider zu viele Interessen angegeben. Sie sind auf 150 beschränkt, du hast aber [[intcount]] angegeben. Jegliche Änderungen, die du an den Interessen vorgenommen hattest, wurden nicht gespeichert. Gehe zurück, verringere die Anzahl der Interessen auf höchstens 150 und speichere erneut. + +/editinfo.bml.error.invalidbio=Die abgespeicherte Biographie enthält ungültige Zeichen. Du musst auf die Konvertierungsseite gehen, um sie dort in Unicode zu konvertieren. + +/editinfo.bml.error.invalidints=Die abgespeicherte Interessenliste enthält ungültige Zeichen. Du musst auf die Konvertierungsseite gehen, um sie dort in Unicode zu konvertieren. + +/editinfo.bml.error.invalidname=Dein Name enthält ungültige Zeichen. Du musst auf die Konvertierungsseite gehen, um ihn dort in Unicode zu konvertieren. + +/editinfo.bml.error.locale.country_ne_state=Du hast USA als dein Land angegeben, aber einen Staat, der nicht in den USA ist, im Feld "anderer Staat" angegeben. + +/editinfo.bml.error.locale.invalid_country=Irgendwie hast du ein ungültiges Land ausgewählt. + +/editinfo.bml.error.locale.state_ne_country=Du hast ein anderes Land als die USA angegeben, aber einen Staat in den USA gewählt. + +/editinfo.bml.error.locale.zip_ne_state<< +Die Postleitzahl stimmt nicht dem ausgewählten Staat überein. +Gib entweder die richtigen Informationen ein oder lösche eines oder beide der Felder "Staat" und "Postleitzahl". +. + +/editinfo.bml.error.locale.zip_requires_us<< +Du hast eine Postleitzahl angegeben, aber nicht die USA als dein Land angegeben. +Wir registrieren nur die Postleitzahlen von Benutzern in den USA. +Bitte gehe zurück und entferne die Postleitzahl oder wähle die USA als dein Land. +. + +/editinfo.bml.error.month.outofrange=Ungültiges Geburstdatum. Gib einen Monat von 1 bis 12 an. + +/editinfo.bml.error.noname=Dein Name wird benötigt. Gib zumindest deinen Vornamen oder einen Spitznamen/Nick an. + +/editinfo.bml.error.tm.require.number=Wenn du die SMS-Funktion verwenden möchtest, musst du deine Telefonnummer eingeben. + +/editinfo.bml.error.tm.require_provider<< +Wenn du die SMS-Funktion verwenden möchtest, musst du deinen Anbieter auswählen. + +Ist dein Anbieter nicht angegeben, kontaktiere uns bitte mit Informationen, wie dein Anbieter mit Kurznachrichten umgeht, sodass wir ihn auch unterstützen können. +. + +/editinfo.bml.error.year.notenoughdigits=Ungültiges Geburtsjahr. Bitte vierstellig eingeben. + +/editinfo.bml.error.year.outofrange=Ungültiges Geburtsjahr. + +/editinfo.bml.finished.about=Wenn du fertig bist, klicke auf "Änderungen speichern" weiter unten. + +/editinfo.bml.finished.header=Fertig? + +/editinfo.bml.finished.save_button=Änderungen speichern + +/editinfo.bml.foafurl.about=Falls du die von uns zur Verfügung gestellte FOAF-Seite nicht verwenden möchtest, wird der oben eingetragene URL anstelle dieser FOAF-Quelle verwendet werden. Wir werden FOAF-Anfragen an den angegebenen URL weiterleiten. + +/editinfo.bml.foafurl.title=Externer FOAF-URL: + +/editinfo.bml.gender.title=Geschlecht + +/editinfo.bml.getreplies.about=Aktiviere diese Option, wenn du E-Mail-Benachrichtungen bekommen möchtest, sobald jemand mit einem Kommentar auf deine Journaleinträge antwortet. + +/editinfo.bml.getreplies.header=E-Mail-Benachrichtigungen zuschicken + +/editinfo.bml.getselfemails.about=Aktiviere diese Option, wenn du bei jedem Kommentar, den du selbst in einem Journal oder einer Community schreibst, eine Mailbenachrichtigung bekommen möchtest. Du wirst keine E-Mails für anonyme Kommentare erhalten. + +/editinfo.bml.getselfemails.header=Mailbenachrichtigungen von selbst geschriebenen Kommentaren + +/editinfo.bml.hidefriendof.about=Wenn du diese Option aktivierst, wird die Liste der Leute, die dich auf ihrer Freundesliste haben, auf deiner Infoseite versteckt. + +/editinfo.bml.hidefriendof.header="Freund von"-Liste verstecken + +/editinfo.bml.howhear.about<< +Aus reiner Neugier, woher kennst du [[sitename]]? +Wenn es eine Person war, gib ihren Benutzernamen ein, wenn es eine andere Quelle/Artikel/Link/Webseite war, gib die entsprechende Information ein. +. + +/editinfo.bml.howhear.header=Aus Neugier + +/editinfo.bml.htmlemail.about<< +Aktiviere diese Option, wenn dein E-Mail-Programm HTML-E-Mails vollständig unterstützt. In vielen Programmen wird das versucht, aber mit schrecklichen Resultaten. +Wenn du die Option ausschaltest, wird LiveJournal nur Text-E-Mails verschicken. +. + +/editinfo.bml.htmlemail.header=HTML-E-Mails verschicken + +/editinfo.bml.imagelinks.about=Platzhalter sind beim Browsen auf Arbeit oder über eine langsame Verbindung nützlich - sie ersetzen Bilder mit Links. Ab welcher Bildgröße sollten Platzhalter verwendet werden? + +/editinfo.bml.imagelinks.header=Platzhalter für Bilder auf der Freundesansicht verwenden + +/editinfo.bml.imagelinks.size.all=Platzhalter für alle Bilder verwenden + +/editinfo.bml.imagelinks.size.custom=Benutzerdefiniert: Platzhalter für Bilder größer als [[width]]x[[height]] verwenden + +/editinfo.bml.imagelinks.size.medium=Platzhalter für große Bilder verwenden (über [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Platzhalter für mittelgroße Bilder verwenden (über [[width]]x[[height]]) + +/editinfo.bml.int.about<< +Möchtest du, dass andere Leute dich über die Interessensuche im Verzeichnis finden können, dann gib unten alles an, wofür du dich interessierst, durch Kommas getrennt. +Wörter und kurze Wortgruppen sind am besten. Immer bedenken: Du solltest deine Interessen alle in den Satz "Ich mag ________" einfügen konnen. Wenn du Substantive verwendest, benutze die Mehrzahl des Wortes. "Ich mag DVDs" und nicht "Ich mag DVD" +. + +/editinfo.bml.int.ex.bad=SCHLECHTES Beispiel: Ich mag viele Bands und ins Kino gehen und mit Freunden reden und in Clubs gehen. So etwas gehört in die Biographie oben hinein. + +/editinfo.bml.int.ex.good=GUTES Beispiel: fahrrad fahren, ski fahren, computer, dvds, mp3s, käse, frauen + +/editinfo.bml.int.header=Interessen + +/editinfo.bml.login.enterinfo=Gib deinen Benutzernamen und dein Passwort ein, um deine persönlichen Informationen zu verändern. + +/editinfo.bml.login.forgot.header=Etwas vergessen? + +/editinfo.bml.login.forgot.recover=Hast du deinen Benutzernamen oder dein Passwort vergessen, hole sie dir hier zurück!. + +/editinfo.bml.logip.always=Immer + +/editinfo.bml.logip.anon_only=Nur anonym Kommentierende + +/editinfo.bml.logip.header=IP-Adressen von antwortenden Leuten aufzeichnen? + +/editinfo.bml.mangleaddress.about=Wenn du befürchtest, dass Spam-Roboter deine E-Mail-Adresse bei LiveJournal finden könnten, dann aktiviere diese Option. Deine E-Mail-Adresse wird daraufhin so verändert, dass sie von Robotern, die E-Mail-Adressen sammeln, nicht gefunden werden kann. + +/editinfo.bml.mangleaddress.header=Angezeigte E-Mail-Adresse verunstalten + +/editinfo.bml.mutualfriends.about=Diese Option erstellt eine neue Liste auf deiner Profilseite: Die Liste der beidseitigen Freunde. Diejenigen, die dich als Freund angeben und die du als Freund angibst, werden auf dieser Liste angezeigt. + +/editinfo.bml.mutualfriends.header=Liste der beidseitigen Freunde auf der Profilseite anzeigen + +/editinfo.bml.newemail.body2<< +Soeben wurde die E-Mail-Adresse für den [[sitename]]-Account "[[username]]" geändert. Gehe auf die folgende Seite, um diese Änderung zu bestätigen: + +[[conflink]] + +Viele Grüße, +das [[sitename]]-Team +[[sitelink]] + +. + +/editinfo.bml.newemail.subject=E-Mail-Adresse geändert + +/editinfo.bml.numcomments.about=Aktiviere diese Option, wenn den URLs der Kommentarzähler hinzugefügt werden soll, sodass dein Browser die Links womöglich in einer anderen Farbe darstellen wird. + +/editinfo.bml.numcomments.header=&nc=xx an die Kommentar-URLs anfügen. + +/editinfo.bml.optional=Freiwillig + +/editinfo.bml.opt_in.about<< +Möchtest du wissen, wann wir LiveJournal interessante neue Optionen hinzufügen, setze ein Häkchen in diese Box. +Du wirst von uns relativ selten E-Mails bekommen, normalerweise nicht mehr als ein- bis zweimal pro Monat. +Deine E-Mail-Adresse wird anderen Benutzern nicht angezeigt und die Option kann jederzeit abgeschaltet werden. +. + +/editinfo.bml.opt_in.header=Schickt mir aktuelle Neuigkeiten über LiveJournal zu. + +/editinfo.bml.persinfo.disclaimer<< +Gib hier bitte ein paar Informationen zu dir selber an, aus statistischen Gründen und da es uns interessiert, wer unseren Service verwendet. +Wir werden mit diesen Informationen nichts Teuflisches oder Gemeines anstellen; wir würden einfach gerne sehen, wer und wo unsere Benutzer sind. Fülle die Informationen bitte korrekt aus. Zu deiner Beruhigung ist hier unsere Datenschutzregelung. +. + +/editinfo.bml.persinfo.header=Persönliche Informationen + +/editinfo.bml.screen.all=Alle + +/editinfo.bml.screen.anon=Anonym + +/editinfo.bml.screen.header=Welche Antworten sollen standardmäßig verdeckt sein? + +/editinfo.bml.screen.none=Keine + +/editinfo.bml.screen.nonfriends=von Nicht-Freunden + +/editinfo.bml.screen.nonmembers=von Nicht-Mitgliedern + +/editinfo.bml.security.header=Wer darf deine Kontaktinformationen sehen? + +/editinfo.bml.security.visibility.anybody=Jeder + +/editinfo.bml.security.visibility.everybody=Alle + +/editinfo.bml.security.visibility.friends=Nur Freunde + +/editinfo.bml.security.visibility.regusers=Registrierte Benutzer + +/editinfo.bml.settings.friendspage.title=Titel der Freundesseite: + +/editinfo.bml.settings.friendspage.title.optional=(optional) Gib eine Ãœberschrift für deine Freundesseite an (kein HTML). + +/editinfo.bml.settings.header=LiveJournal-Optionen + +/editinfo.bml.settings.journal.subtitle=Untertitel: + +/editinfo.bml.settings.journal.subtitle.optional=(optional) Gib eine Ãœberschrift und einen Untertitel für dein Journal an (kein HTML). + +/editinfo.bml.settings.journal.title=Titel deines Journals: + +/editinfo.bml.settings.privacy.about=Im folgenden kannst du Optionen zum Schutz deiner Privätsphäre einstellen. + +/editinfo.bml.settings.privacy.header=Privatsphäre + +/editinfo.bml.state.other=Oder gib ein anderes Bundesland/Kanton an + +/editinfo.bml.state.title=Bundesland + +/editinfo.bml.state.us=US-Staaten + +/editinfo.bml.stylemine.about=Aktiviere diese Option, wenn du Kommentarseiten von Einträgen auf deiner Freundesseite in dem Stil deines Journal sehen möchtest. + +/editinfo.bml.stylemine.header=Kommentarseiten in dem Stil deines Journal anzeigen? + +/editinfo.bml.success.header=Aktion erfolgreich + +/editinfo.bml.success.message=Die Einstellungen für dein Journal und deine Benutzerinfo wurden aktualisiert. + +/editinfo.bml.switch.button=Wechseln + +/editinfo.bml.switch.header=Journal wechseln + +/editinfo.bml.switch.workwith=Mit Journal arbeiten: + +/editinfo.bml.title=Persönliche Informationen bearbeiten + +/editinfo.bml.tm.details=Details + +/editinfo.bml.tm.phonenum=Vollständige Telefonnummer: + +/editinfo.bml.tm.sec.about=Einschalten der SMS-Funktion + +/editinfo.bml.tm.sec.title=Sicherheitsniveau + +/editinfo.bml.tm.servprov=Service-Anbieter + +/editinfo.bml.tm.title=SMS-Funktion + +/editinfo.bml.translatemailto.about=Falls du dich dazu entschieden hast, Kommentare per E-Mail zu erhalten, aber dein E-Mail-Programm unterstützt Unicode (UTF-8) nicht vollständig, dann verwende diese Option, um eine andere Codierung für die E-Mail-Benachrichtigungen auszuwählen, in welche LiveJournal sie dann automatisch konvertieren wird. + +/editinfo.bml.translatemailto.header=E-Mail-Benachrichtigungen übersetzen in: + +/editinfo.bml.unbanusers.about=Die folgenden Benutzer sind vom Kommentieren in deinem Journal ausgeschlossen. Um den Ausschluss eines Benutzers aufzuheben, setze ein Häkchen in das Kästchen neben ihrem Benutzernamen. + +/editinfo.bml.unbanusers.header=Ausschluss von Benutzern aufheben + +/editinfo.bml.userpic.about=Unten ist das Bild angezeigt, das du hochgeladen hast, damit es dich überall in LiveJournal, in deinem eigenen Journal und in den Journalen deiner Freunde repräsentiert: + +/editinfo.bml.userpic.edit=Um dieses Bild zu löschen oder ein neues hochzuladen, gehe hierhin. + +/editinfo.bml.userpic.header=Dein Bild + +/editinfo.bml.userpic.none=kein Bild hochgeladen + +/editinfo.bml.weblogscom.about=Wähle diese Option aus, damit dein Journal auf Weblogs.com angezeigt wird, wenn du neue öffentliche Einträge machst. + +/editinfo.bml.weblogscom.header=Benachrichtige Weblogs.com bei Updates + +/editinfo.bml.webpagename.title=Name der Website + +/editinfo.bml.webpageurl.title=URL der Website + +/editinfo.bml.whoreply.header=Wer darf auf deine Einträge antworten? + +/editinfo.bml.zip.title=Postleitzahl + +/editinfo.bml.zip.usonly=Fünfstellige PLZ, nur für Anwohner in den USA + +/editjournal.bml.btn.proceed=Weiter... + +/editjournal.bml.certainday=Datum (jjjj-mm-tt): + +/editjournal.bml.desc=Bitte verwende das Formular um dein Eintrag zu finden, den du bearbeiten möchtest. + +/editjournal.bml.in=In Community: + +/editjournal.bml.recententries=jüngste Einträge + +/editjournal.bml.recententry=Jüngster Eintrag + +/editjournal.bml.title=Journaleinträge bearbeiten + +/editjournal.bml.viewwhat=Auswahl: + +/editjournal_do.bml.body=Bearbeite die Textfelder des Journaleintrags, die verändert werden sollen und klicke dann auf "Speichern" unten auf der Seite. Wenn du den Eintrag löschen möchtest, dann klicke auf "Löschen". + +/editjournal_do.bml.btn.delete=Journaleintrag löschen + +/editjournal_do.bml.btn.edit=Ausgewählten Eintrag bearbeiten + +/editjournal_do.bml.btn.preview=Vorschau + +/editjournal_do.bml.btn.save=Journaleintrag speichern + +/editjournal_do.bml.continue.head=Drücke zum Fortfahren... + +/editjournal_do.bml.continue.text=Nachdem du einen Eintrag zum Bearbeiten oder Löschen ausgewählt hast, drücke den folgende Button. + +/editjournal_do.bml.currmood=Aktuelle Stimmung: + +/editjournal_do.bml.currmusic=Aktuelle Musik: + +/editjournal_do.bml.date=Datum: + +/editjournal_do.bml.default=Standard + +/editjournal_do.bml.delete.confirm=Möchtest du diesen Eintrag wirklich löschen? + +/editjournal_do.bml.edit.text=Das ist der Journal-Eintrag, den du zur Bearbeitung ausgewählt hast. Bearbeite die Felder deines Eintrags, die du ändern möchtest und drücke den Button zum Speichern ganz unten auf der Seite.

    Um einen Eintrag zu löschen, entferne den gesamten Text und speichere ab - der Eintrag wird dann gelöscht. + +/editjournal_do.bml.error.getting=Beim Zugriff auf die zu bearbeitenden Einträge ist ein Fehler aufgetreten: + +/editjournal_do.bml.error.modify=Beim Bearbeiten deines Journals ist ein Fehler aufgetreten: + +/editjournal_do.bml.error.nofind=Der ausgewählte Journaleintrag wurde nicht gefunden. + +/editjournal_do.bml.event=Ereignis: + +/editjournal_do.bml.localtime=Ortszeit: + +/editjournal_do.bml.noneother=Keine, oder: + +/editjournal_do.bml.opt.backdate=Eintrag zurückdatieren: + +/editjournal_do.bml.opt.backdate.about=erscheint nicht in der Freunde-Ansicht + +/editjournal_do.bml.opt.nocomments=Keine Kommentare: + +/editjournal_do.bml.opt.noemail=Keine Kommentar-E-Mails: + +/editjournal_do.bml.opt.noformat=Keine automatische Formatierung: + +/editjournal_do.bml.other=andere Stimmung: + +/editjournal_do.bml.pickentry.head=Wähle einen Eintrag zur Bearbeitung aus + +/editjournal_do.bml.pickentry.text=Wähle aus, welchen Eintrag du ändern möchtest und drücke dann den Bearbeiten-Button am Ende der Seite. + +/editjournal_do.bml.picture=Benutzerbild auswählen: + +/editjournal_do.bml.preview.header=Vorschau + +/editjournal_do.bml.preview.text=So wird der Eintrag aussehen, wenn er abgeschickt wird. Du kannst den Eintrag mithilfe des Formulars unten weiter bearbeiten oder ihn so abschicken. + +/editjournal_do.bml.save.head=Speichern... + +/editjournal_do.bml.save.text=Wenn du deinen Eintrag geändert hast, drücke auf "Journaleintrag speichern". + +/editjournal_do.bml.subject=Betreff: (optional) + +/editjournal_do.bml.success.delete=Der Eintrag wurde gelöscht. + +/editjournal_do.bml.success.edit=Der Eintrag wurde geändert. Du kannst ihn hier ansehen. + +/editjournal_do.bml.success.head=Aktion erfolgreich + +/editjournal_do.bml.timeformat=24-Stunden-Zeitformat + +/editjournal_do.bml.title=Journaleinträge bearbeiten + +/editpics.bml.btn.proceed=Weiter + +/editpics.bml.btn.save=Einstellungen speichern + +/editpics.bml.curpics=Aktuelle Bilder + +/editpics.bml.curpics.desc=Hier sind die bereits hochgeladenen Bilder. Ihnen können Schlüsselworte zugewiesen werden, so dass sie später mit Hilfe der Schlüsselworte verwendet werden können. Du kannst auch ein Standardbild auswählen oder alte Bilder löschen. Verwende das Formular im unteren Seitenteil, um ein neues hochzuladen. + +/editpics.bml.error.badurl=Die Adresse für das hochzuladende Bild sieht nicht korrekt aus. Sie sollte mit http:// beginnen. + +/editpics.bml.error.filetoolarge=Das hochgeladene Bild ist zu groß. Die Dateigröße darf [[maxsize]] nicht überschreiten. + +/editpics.bml.error.imagetoolarge=Die Größe deines Bildes ([[imagesize]]) überschreitet die Maximalgröße. Dein Bild darf nur 100x100 Pixel groß sein. Verwende ein Bildbearbeitungsprogramm, um dieses Bild auf eine Miniaturansicht zu verkleinern. + +/editpics.bml.error.invalidimage=Ungültige Bilddatei. + +/editpics.bml.error.keywords=Das Schlüsselwort "[[ekw]]" wurde für mehrere Bilder verwendet. Eines der beiden wurde zufällig ausgewählt, aber höchstwahrscheinlich genau das, welches du nicht haben wolltest. Vielleicht möchtest du zurückgehen und das überarbeiten. + +/editpics.bml.error.toomanypics2=Du hast bereits die maximale Anzahl von [[maxpics]] Bildern. Du kannst dieses Bild nicht hochladen, bis du nicht eines deiner aktuellen Bilder gelöscht hast. + +/editpics.bml.error.toomanypics3=Im Moment ist die maximale Anzahl von [[max]] [[?max|Bild|Bilder]] erreicht. Keine weiteren Bilder werden hinzugefügt, solange nicht eines oder mehrere der aktuellen gelöscht wurden. + +/editpics.bml.error.unsupportedtype=Dateien des Typs [[filetype]] wreden nicht unterstützt. Du kannst nur GIF, PNG oder JPG-Dateien hochladen. Fast alle Bildbearbeitungsprogramme können den Dateityp in einen der oben genannten konvertieren. + +/editpics.bml.error.urlerror=Beim Hochladen deines Bildes ist ein Fehler aufgetreten. + +/editpics.bml.fromfile=Aus Datei: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=d + +/editpics.bml.fromurl=Aus URL: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=u + +/editpics.bml.label.default=Standard: + +/editpics.bml.label.delete=Löschen: + +/editpics.bml.label.keywords=Schlüsselworte: + +/editpics.bml.makedefault=Zum Standard-Bild machen. + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=s + +/editpics.bml.nodefault=Kein Standardbild + +/editpics.bml.noneupload=Du hast keine Bilder hochgeladen. Bitte lade eines mit Hilfe des Formulars unten hoch. + +/editpics.bml.nopics=Keine Bilder + +/editpics.bml.piclimitstatus=Momentan hochgeladen: [[current]] von [[max]]. + +/editpics.bml.restriction.fileformat=Das Dateiformat muss entweder PNG, GIF oder JPG sein. + +/editpics.bml.restriction.filesize=Dateigröße muss weniger als 40k betragen. + +/editpics.bml.restriction.imagesize=Die Größe des Bildes darf 100x100 Pixel nicht überschreiten. + +/editpics.bml.title=Benutzerbilder bearbeiten + +/editpics.bml.uploaddesc=Verwende das Formular unten, um ein neues Bild hochzuladen. + +/editpics.bml.uploadheader=Ein neues Bild hochladen + +/export.bml.btn.proceed=Weiter... + +/export.bml.description=Mit diesem Feature kannst du dein gesamtes Journal zu Sicherungszwecken in ein benutzerdefiniertes Format runterladen. Weitere Informationen hierzu findest du hier. + +/export.bml.fields=Felder: + +/export.bml.format.csv=CSV (durch Komma getrennte Werte) + +/export.bml.label.encoding=Kodierung: + +/export.bml.label.field.allowmask=Maske erlauben + +/export.bml.label.field.currents=Aktuelle Stimmung & Musik + +/export.bml.label.field.event=Ereignis + +/export.bml.label.field.eventtime=Zeit des Ereignisses (nach Uhr des Benutzers) + +/export.bml.label.field.itemid=ID-Nummer + +/export.bml.label.field.logtime=Registrierte Zeit (von der Systemuhr) + +/export.bml.label.field.security=Sicherheitsniveau + +/export.bml.label.field.subject=Betreff + +/export.bml.label.header=Kopfzeilen + +/export.bml.label.month=Monat auswählen: + +/export.bml.label.month.year=jjjj: + +/export.bml.label.notranslation=Nicht zwischen Kodierungen konvertieren + +/export.bml.label.what=Was exportieren: + +/export.bml.title=Journal exportieren + +/export.bml.what.entries=Journaleinträge + +/export_do.bml.error.encoding=Ungültige Kodierung wurde ausgewählt + +/friends/add.bml.add.header=Aktion erfolgreich + +/friends/add.bml.add.text=Der Benutzer [[ljuser]] wurde deiner Freundesliste hinzugefügt. Du kannst dir die aktuellsten Einträge deiner Freunde hier anschauen. + +/friends/add.bml.add.title=Freund hinzugefügt! + +/friends/add.bml.btn.add=[[user]] hinzufügen + +/friends/add.bml.btn.modify=Ändern + +/friends/add.bml.btn.remove=Entfernen + +/friends/add.bml.colors.bg=Hintergrund + +/friends/add.bml.colors.fg=Vordergrund + +/friends/add.bml.colors.header=Farben + +/friends/add.bml.colors.hover=(Der Name der Farbe wird angezeigt, wenn du mit der Maus über sie gehst) + +/friends/add.bml.colors.text=Du kannst, wenn gewünscht, auch die Farben auswählen, die [[user]] auf deiner Freundeliste repräsentieren werden. + +/friends/add.bml.confirm.header=[[user]] deiner Freundesliste hinzufügen? + +/friends/add.bml.confirm.syn.header=Externe Artikelquelle [[user]] abonnieren? + +/friends/add.bml.confirm.syn.title=Externe Artikelquelle abonnieren + +/friends/add.bml.confirm.text=Um [[user]] deiner Freundesliste hinzuzufügen, klicke auf die Taste unten. + +/friends/add.bml.confirm.title=Freund hinzufügen + +/friends/add.bml.error1.header=Zuerst einloggen + +/friends/add.bml.error1.text=Um deiner Freundesliste einen Benutzer hinzuzufügen, musst du dich zuerst einloggen. Hast du noch keinen Account, kannst du einen erstellen, um mit den Journalen deiner Freunde auf dem Laufenden zu bleiben. + +/friends/add.bml.error1.title=Freund hinzufügen + +/friends/add.bml.error2.text=Ungültiger oder fehlender Benutzername. Um einen Freund hinzuzufügen, gehe auf die Seite Freunde bearbeiten + +/friends/add.bml.error3.text=Der Benutzer [[user]] ist schon auf deiner Freundesliste. Du kannst aber die Farben verändern, die ihn auf deiner Freundesseite repräsentieren. + +/friends/add.bml.error3.title=Freundeseinstellung bearbeiten + +/friends/add.bml.groups.header=Freundesgruppen + +/friends/add.bml.groups.nogroup=Es sind keine Freundesgruppen definiert. + +/friends/add.bml.groups.text=In welchen Freundesgruppen soll dieser Benutzer sein? Freundesgruppen werden dazu verwendet, deine Ansicht der Freundesseite zu filtern und auch für eine auf bestimmte Gruppen beschränkte Sicherheit eines Eintrags. + +/friends/add.bml.remove.header=Aktion erfolgreich + +/friends/add.bml.remove.text=Der Benutzer wurde von deiner Freundesliste entfernt. Du kannst die aktuellsten Einträge deiner Freunde hier anschauen. + +/friends/add.bml.remove.title=Freund entfernt! + +/friends/edit.bml.title=Liste der Freunde bearbeiten + +/friends/editgroups.bml.btn.ge.del=Löschen + +/friends/editgroups.bml.btn.ge.new=Neu + +/friends/editgroups.bml.btn.ge.ren=Umbenennen + +/friends/editgroups.bml.btn.gs.private=Privat + +/friends/editgroups.bml.btn.gs.public=Öffentlich + +/friends/editgroups.bml.btn.mv.down=Nach unten + +/friends/editgroups.bml.btn.mv.up=Nach oben + +/friends/editgroups.bml.confirm.delete=Bist du sicher, das du diese Freundesgruppe löschen willst? + +/friends/editgroups.bml.done.btn=Änderungen speichern + +/friends/editgroups.bml.done.header=Fertig? + +/friends/editgroups.bml.done.text=Wenn du fertig bist, klicke unten auf "Änderungen speichern". + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Du hast die Obergrenze von 30 Freundesgruppen erreicht. Falls du eine oder mehrere Gruppen gelöscht hast, diese Änderung aber noch nicht gespeichert hast, dann tue dies jetzt und lade diese Seite dann erneut. Dann kannst du neue Gruppen erstellen. + +/friends/editgroups.bml.error.text=Der Server hat folgenden Fehler gemeldet: + +/friends/editgroups.bml.group.public=(öffentlich) + +/friends/editgroups.bml.ingroup=In der Gruppe: + +/friends/editgroups.bml.ingroup.not=Nicht in der Gruppe: + +/friends/editgroups.bml.prompt.newname=Den Namen für die neue Freundesgruppe eingeben: + +/friends/editgroups.bml.prompt.rename=Diese Freundesgruppe umbenennen in: + +/friends/editgroups.bml.saved.header=Gespeichert + +/friends/editgroups.bml.saved.text=Deine benutzerdefinierten Freundesgruppen wurden gespeichert. + +/friends/editgroups.bml.text<< +Diese Seite ermöglicht es dir, deine benutzerdefinierten Freundesgruppen zu bearbeiten. Benutzerdefinierte Freundesgruppen dienen dazu, das Sicherheitsniveau von Einträgen anzupassen und deine Freundesseite zu filtern. +Ausführliche Informationen findest du in der FAQ Wie werden benutzerdefinierte Freundesgruppen verwendet?" + +Diese Seite benötigt JavaScript, um korrekt zu funktionieren. +. + +/friends/editgroups.bml.text.sec=Sicherheitshinweis: Falls du eine neue Gruppe erstellen und gleichzeitig eine alte löschen willst, dann tue dies nicht, indem du eine vorhandene Gruppe umbenennst und dann veränderst. Wenn du dies tust, werden alle Einträge, die du für die alte Gruppe sichtbar gemacht hast, auch für die neue Gruppe sichtbar sein. + +/friends/editgroups.bml.title=Benutzerdefinierte Freundesgruppen bearbeiten + +/friends/editgroups.bml.yourgroups=Deine Freundesgruppen: + +/friends/edit_do.bml.addfriends.head=Freunde hinzufügen + +/friends/edit_do.bml.addfriends.text=Gib die Benutzernamen deiner LiveJournal-Freunde in die folgenden Textfelder ein, und wähle die Farben für Hintergrund und Vordergrund aus, mit denen sie angezeigt werden sollen.... + +/friends/edit_do.bml.background=Hintergrund + +/friends/edit_do.bml.bgcolor=Hintergrundfarbe: + +/friends/edit_do.bml.btn.close=Schließen + +/friends/edit_do.bml.btn.save=Änderungen speichern + +/friends/edit_do.bml.btn.toggle=Farbvorschaufenster ein/ausblenden + +/friends/edit_do.bml.done.head=Fertig? + +/friends/edit_do.bml.done.text=Wenn du fertig bist, drücke die folgende Taste "Änderungen speichern"... + +/friends/edit_do.bml.error.updating=Beim Speichern der Liste deiner Freunde ist ein Fehler aufgetreten: + +/friends/edit_do.bml.fellowfriends.head=Freund von + +/friends/edit_do.bml.fellowfriends.text=Folgende Leute haben dich als Freund auf ihrer Liste... Vielleicht möchtest du sie auch in deine Liste der Freunde aufnehmen. Diese Liste soll dir lediglich deren Benutzernamen zeigen. Du bist keineswegs verpflichtet, sie auch in deine Liste der Freunde aufzunehmen. + +/friends/edit_do.bml.foreground=Vordergrund + +/friends/edit_do.bml.friend=Freund + +/friends/edit_do.bml.hover=Bewege den Mauscursor über eine Farbe, um ihren Namen zu sehen + +/friends/edit_do.bml.mrcolor=Farbanzeige + +/friends/edit_do.bml.needmore=Wenn du mehr Freunde hinzufügen möchtest als auf diese Seite passen, speichere die Änderungen ab und gehe erneut auf diese Seite. + +/friends/edit_do.bml.nofriends.head=Keine Freunde? + +/friends/edit_do.bml.nofriends.text=Du hast zur Zeit keine Freunde auf deiner Liste. Wir sind aber sicher, dass du ein paar Freunde hast! :) Gib einfach ihre LiveJournal-Benutzernamen hier ein.... + +/friends/edit_do.bml.opt.addtolist=Freund hinzufügen + +/friends/edit_do.bml.opt.delete=Löschen? + +/friends/edit_do.bml.success.head=Aktion erfolgreich + +/friends/edit_do.bml.success.text=Die Liste deiner Freunde wurde aktualisiert. Du kannst dir die aktualisierte Freundes-Ansicht hier ansehen. + +/friends/edit_do.bml.textcolor=Textfarbe: + +/friends/edit_do.bml.title=Liste der Freunde bearbeiten + +/friends/edit_do.bml.user=Benutzer + +/friends/edit_do.bml.viewer=Farbansicht + +/friends/edit_do.bml.yourfriends.head=Deine Freunde + +/friends/edit_do.bml.yourfriends.text=Du hast zurzeit folgende Freunde auf deiner Liste: + +/friends/filter.bml.editgroups=Wenn du deine Freundesgruppen bearbeiten möchtest, gehe auf die Seite [[link]]. + +/friends/filter.bml.error.nogroups=Du kannst deine Freundesansicht nicht filtern, weil du zuerst deine Freundesgruppen erstellen musst. + +/friends/filter.bml.error.nogroups.header=Keine Gruppen erstellt + +/friends/filter.bml.reset=Auswahl aufheben + +/friends/filter.bml.select=Kreuze die Freundesgruppe(n) an, die du gern auf deiner Freundesansicht sehen möchtest. + +/friends/filter.bml.select.header=Gruppen auswählen + +/friends/filter.bml.submit=Anschauen! + +/friends/filter.bml.title=Freundesansicht filtern + +/friends/index.bml.about<< +Auf dieser Seite kannst du deine Freundesliste verwalten. + +Indem du andere Benutzer auf deine Freundesliste setzt, kannst du ihre Einträge einfach auf deiner Freundesseite lesen. Du kannst auch Communities und externe Artikelquellen auf deine Freundesliste setzen, so dass du auch deren Einträge auf deiner Freundesseite siehst. +. + +/friends/index.bml.edit.about=Benutzer auf die Freundesliste setzen oder entfernen bzw. ihre zugeordnete Farbe verändern. + +/friends/index.bml.editgroups.about=Untergruppen auf deiner Freundesliste erstellen, bearbeiten oder löschen. + +/friends/index.bml.filter=Diese Freundesgruppen können verwendet werden, um deine Freundesliste zu filtern: du kannst hier eine spezielle Freundesgruppe zum Anschauen auswählen, um nur die Einträge dieser Benutzergruppe zu sehen. Du kannst damit auch einen Eintrag auf bestimmte Gruppen beschränken (siehe unten). + +/friends/index.bml.filter.about=Filtere deine Freundesliste nach Untergruppen. + +/friends/index.bml.groups=Zusätzlich kannst du Untergruppen von deinen Freunden einstellen. + +/friends/index.bml.security=Du kannst auch Einträge mit beschränktem Sicherheitsniveau für bestimmte Benutzer auf deiner Freundesliste schreiben. Mehr darüber kannst du unter Freunde & Sicherheitsniveaus herausfinden. + +/friends/index.bml.security.custom=Mit "benutzerdefinierten" Einträgen kannst du einstellen, welche Freundesgruppen deinen Eintrag anschauen können. Momentan unterstützen jedoch nicht alle Clients benutzerdefinierte Sicherheitsniveaus. + +/friends/index.bml.security.header=Sicherheit + +/friends/index.bml.security.only=Einträge, die "nur für Freunde" sind, können von allen Benutzern auf deiner Freundesliste gesehen werden. + +/friends/index.bml.title=Freunde verwalten + +/friends/index.bml.tools=Extras + +/friends/popwithfriends.bml.account_type=Sorry, dein Accounttyp erlaubt leider nicht die Benutzung dieses Services. + +/friends/popwithfriends.bml.count=Zähler + +/friends/popwithfriends.bml.exclude_own=Wenn du möchtest, kannst du auch deine Freunde ausschließen. + +/friends/popwithfriends.bml.include_own=Wenn du möchtest, kannst du auch deine Freunde einschließen. + +/friends/popwithfriends.bml.intro=Die folgenden Freunde werden oft von deinen Freunden geführt, aber nicht von dir. + +/friends/popwithfriends.bml.intro_own=Die folgenden Freunde werden oft von deinen Freunden geführt. Diese Liste beinhaltet auch deine eigenen Freunde. + +/friends/popwithfriends.bml.no_users=Keine Benutzer + +/friends/popwithfriends.bml.title=Beliebte Benutzer bei deinen Freunden + +/friends/popwithfriends.bml.user=Benutzer + +/go.bml.defaultbody=Keine Argumente wurden angegeben + +/go.bml.defaulttitle=Fehler + +/go.bml.error.noentry.next=Es gibt keinen Eintrag nach diesem. + +/go.bml.error.noentry.prev=Es gibt keinen Eintrag vor diesem. + +/go.bml.error.noentrytitle=Kein Eintrag + +/go.bml.error.redirkey=falscher redir_key + +/go.bml.error.usernotfound=Benutzer wurde nicht gefunden. + +/index.bml.about.header=Über LiveJournal + +/index.bml.about.joining=Der Beitritt zur Webseite ist kostenlos. Benutzer können einen bezahlten Account erwerben, um Extra-Features zu erhalten. + +/index.bml.about.us=LiveJournal ist ein einfach zu verwendendes, aber sehr vielseitiges Hilfsmittel zur Veröffentlichung persönlicher Inhalte ("Weblog"), welches auf Open-Source-Software basiert. + +/index.bml.boldcreate=Erstelle dein eigenes LiveJournal! + +/index.bml.frank.image.alt=Die Ziege Frank, das LiveJournal-Maskottchen. + +/index.bml.frank.logo="Bäääääh", sagt Frank. + +/index.bml.learnmore.header=Möchtest du mehr wissen? + +/index.bml.learnmore.text=Bitte lies den Überblick über unsere Features. Überzeugt? Erstelle dein eigenes LiveJournal! + +/index.bml.meta.desc=Bei LiveJournal.com kannst du mit dem Rest der Welt deine Gedanken austauschen. + +/index.bml.meta.keywords=Tagebuch, Journal, Online-Journal, Tagebücher, schreiben, Internettagebuch, Internet Tagebuch, Online Tagebuch + +/index.bml.news.text=Die aktuellsten Neuigkeiten über die Site: + +/index.bml.news.title=Aktuellste Neuigkeiten + +/index.bml.post=Live-Eintragsstatistik + +/index.bml.post.hour=Pro Stunde + +/index.bml.post.latest=Aktuellste Einträge + +/index.bml.post.min=Pro Minute + +/interests.bml.add.added.head=Hinzugefügt! + +/interests.bml.add.added.text=Das Interesse wurde zu deiner Liste hinzugefügt! + +/interests.bml.add.btn.text=[[interest]] hinzufügen + +/interests.bml.add.confirm.head=Bestätigen + +/interests.bml.add.confirm.text=Um [[interest]] als Interesse hinzuzufügen, drücke den folgenden Button. + +/interests.bml.add.toomany.head=Entschuldigung... + +/interests.bml.add.toomany.text=Du hast schon [[maxinterests]] Interessen angegeben. + +/interests.bml.addint=Wenn du auch daran interessiert bist und dies zu deiner Liste hinzufügen möchtest, klicke hier. + +/interests.bml.btn.switch=Wechseln + +/interests.bml.communities.head=Entsprechende Communities + +/interests.bml.communities.text=Die folgenden Communities sind ebenfalls an "[[interest]]" interessiert. + +/interests.bml.count=Anzahl + +/interests.bml.enmasse.body.other=Unten sind die Interessen des Benutzers [[user]]. Setze Häkchen in die Kästchen neben den Interessen, die du gerne als eigene Interessen hinzufügen würdest und entferne die Häkchen neben den Interessen, die du gerne aus deiner Liste entfernen würdest. Klicke dann auf "Änderungen speichern". + +/interests.bml.enmasse.body.other_authas=Unten sind die Interessen des Benutzers [[user]]. Setze Häkchen in die Kästchen neben den Interessen, die du gerne der Liste von [[target]] hinzufügen würdest und entferne die Häkchen neben den Interessen, die du gerne aus der Liste von [[target]] entfernen würdest. Klicke dann auf "Änderungen speichern". + +/interests.bml.enmasse.body.you=Entferne die Häkchen neben den Interessen, die du gern entfernen würdest. Klicke dann auf "Änderungen speichern". + +/interests.bml.enmasse.btn=Liste anzeigen + +/interests.bml.enmasse.header=Interessen hinzufügen/entfernen + +/interests.bml.enmasse.intro=Verändere deine Interessen, basierend auf den Interessen von: + +/interests.bml.error.add.mustlogin=Du musst eingeloggt sein, um auf diesem Weg ein Interesse hinzuzufügen. + +/interests.bml.error.enmasse.mustlogin=Um dieses Extra zu verwenden, musst du eingeloggt sein. + +/interests.bml.error.enmasse.noaccess=Du hast anscheinend keinen Zugriff auf das Journal [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Interesse nicht gefunden. + +/interests.bml.error.nointerests=Der gewählte Benutzer existiert nicht oder hat keine Interessen angegeben. + +/interests.bml.findsim.searchwait=Bitte beachten: Die Suche dauert einige Sekunden. Sei geduldig. + +/interests.bml.findsim_do.account.notallowed=Entschuldigung, aber dein Account Typ erlaubt die Verwendung dieses Werkzeugs nicht. + +/interests.bml.findsim_do.magic=Magischer
    Index + +/interests.bml.findsim_do.magic.head=Magischer Index? + +/interests.bml.findsim_do.magic.text=Für jeden übereinstimmenden Benutzer wird ein magischer Index berechnet, der aus zwei Faktoren besteht: der Anzahl der gleichen Interessen, sowie einige Extra Punkte für gemeinsame ungewöhnliche Interessen. + +/interests.bml.findsim_do.nomatch.head=Keine Übereinstimmungen + +/interests.bml.findsim_do.nomatch.text=Keine Benutzer ähneln [[user]]. + +/interests.bml.findsim_do.notdefined=Benutzer [[user]] hat keine Interessen angegeben. + +/interests.bml.findsim_do.similar.head=Ähnliche Benutzer + +/interests.bml.findsim_do.similar.text=Die folgenden Benutzer haben die meisten gemeinsamen Interessen mit [[user]] + +/interests.bml.finished.about=Wenn du fertig bist, klicke auf "Änderungen speichern". + +/interests.bml.finished.header=Fertig? + +/interests.bml.finished.save_button=Änderungen speichern + +/interests.bml.interest=Interesse + +/interests.bml.interested.btn.find=Suchen + +/interests.bml.interested.in=Benutzer und Communities mit folgendem Interesse suchen: + +/interests.bml.interests.findsim=Finde Benutzer mit ähnlichen Interessen wie denen von + +/interests.bml.interests.head=Interessen + +/interests.bml.interests.text=Hier sind ein paar nette Sachen, die du mit Interessen machen kannst... + +/interests.bml.interests.viewpop=Beliebte Interessen anzeigen + +/interests.bml.login.enterinfo=Gib deinen Benutzernamen und Passwort ein, um deine Interessen zu verändern. + +/interests.bml.login.proceed=Weiter... + +/interests.bml.match=[[count]] Übereinstimmung: + +/interests.bml.matches=[[count]] Übereinstimmungen: + +/interests.bml.morestuff=Weitere interessante Funktionen finden sich auf der Interessenseite. + +/interests.bml.nointerests.text=Noch keine Interessen eingegeben? Auf der Seite Info bearbeiten können Interessen hinzugefügt werden. + +/interests.bml.popular.disabled=Sorry, das Feature, das populäre Interessen anzeigt, ist nicht verfügbar. + +/interests.bml.popular.head=Beliebte Interessen + +/interests.bml.popular.text=Es folgen die beliebtesten Interessen. + +/interests.bml.results.added=Die ausgewählten Interessen wurden erfolgreich deinen Interessen hinzugefügt. + +/interests.bml.results.both=Die ausgewählten Interessen wurden erfolgreich deinen Interessen hinzugefügt und die abgewählten wurden entfernt. + +/interests.bml.results.deleted=Die abgewählten Interessen wurden erfolgreich von deinen Interessen entfernt. + +/interests.bml.results.del_and_toomany=Die abgewählten Interessen wurden erfolgreich von deinen Interessen entfernt. Du hast jedoch zu viele Interessen zum Hinzufügen ausgewählt. Du kannst insgesamt nur [[intcount]] Interessen haben. Keines der ausgewählten Interessen wurde deiner Liste hinzugefügt. Du kannst zurückgehen und es noch einmal mit weniger Interessen versuchen. + +/interests.bml.results.goback=Du kannst zurück zum Profil von [[user]] gehen, welches du dir vorher angeschaut hast. + +/interests.bml.results.header=Ergebnis + +/interests.bml.results.message=Schaue dir dein aktualisiertes Profil an. + +/interests.bml.results.nothing=Du hast keine Veränderungen vorgenommen. + +/interests.bml.results.toomany=Du hast zu viele Interessen zum Hinzufügen ausgewählt. Du darfst insgesamt nur [[intcount]] Interessen haben. Keines der ausgewählten Interessen wurde deiner Liste hinzugefügt. Du kannst zurückgehen und es noch einmal mit weniger Interessen versuchen. + +/interests.bml.title=Interessen + +/interests.bml.toomany.body=[[intcount]] Benutzer und/oder Communities haben dies als Interesse aufgeführt. Eine Liste wird nicht angezeigt. + +/interests.bml.toomany.head=Viele Übereinstimmungen + +/interests.bml.users.head=Interessierte Benutzer + +/interests.bml.users.text=Die folgenden Benutzer interessieren sich für [[interest]]. + +/invite/index.bml.code=Code + +/invite/index.bml.error=Fehler + +/invite/index.bml.genmore=Weitere Codes erzeugen + +/invite/index.bml.how_detail=Abhängig von einer Reihe von Faktoren können existierende Benutzer eine bestimmte Anzahl anderer Benutzer zu dieser Webseite einladen. Um jemand anderen einzuladen, musst du einen Einladungscode erzeugen und ihn der anderen Person geben. + +/invite/index.bml.how_header=Wie funktioniert's? + +/invite/index.bml.invite_header=Einladungen? + +/invite/index.bml.none=Keine + +/invite/index.bml.redeemed=Eingelöst von + +/invite/index.bml.title=Andere zu LiveJournal einladen... + +/invite/index.bml.unused=Nicht verwendet + +/invite/index.bml.use=Verwenden + +/invite/index.bml.why_codes=Um die Community beeinander zu halten, ihr Wachstum zu kontrollieren und Missbrauch vorzubeugen, benötigt man für die Erstellung eines Accounts nun entweder die Einladungs eines existierenden Benutzers oder man muss ihn bei der Erstellung bezahlen. Diese Maßnahme, die neuen Benutzern kompliziert erscheinen mag, dient dazu, den bereits registrierten Benutzern eine angenehmere Atmosphäre zu schaffen. + +/legal/index.bml.about<< +Da LiveJournal dazu dient, eine stabile und sinnvolle Gemeinschaft von Mitgliedern aller Hintergründe und Nationen anzubieten, haben wir ein paar Regeln aufgestellt, um das zu erreichen. + +Diese Dokumente enthalten angemessene Bedingungen und Informationen darüber, wie wir diesen Dienst bestmöglich anbieten, und welches Mitgliederverhalten wir uns und anderen gegenüber erwarten. LiveJournal funktioniert am besten, wenn diese Regeln beachtet werden. Die wichtigsten sind hier zusammengefasst: +
      +
    • Andere Benutzer nicht zu belästigen, zu missbrauchen, oder ihnen zu drohen.
    • +
    • Minderjährigen nicht zu schaden.
    • +
    • Keinen Spam auf der Website oder in irgendwelchen Accounts zu hinterlassen.
    • +
    • Urheberrechtlich geschütztes Material nicht ohne Erlaubnis zu veröffentlichen.
    • +
    • Die Privatsphäre Anderer nicht zu verletzen.
    • +
    • Weder die U.S.-amerikanischen noch die heimischen Gesetze in irgend einer Weise zu verletzen.
    • +
    +Hier ist die vollständige Liste der Regeln und Grundsätze: +. + +/legal/index.bml.about.header=Übersicht + +/legal/index.bml.docs.coppa.about=Das amerikanische Kinder-Online-Datenschutzabkommen (COPPA, Children's Online Privacy Protection Act) reguliert die Anhäufung und Verwendung von personenbezogener Information, die von Kindern unter 13 Jahren bereitgestellt wurde oder sie betrifft. Unsere COPPA-Seite erklärt unseren Standpunkt zu diesem Gesetz und fasst zusammen, wie mit COPPA-bezogenen Situationen umzugehen ist. + +/legal/index.bml.docs.header=Dokumente + +/legal/index.bml.docs.privacy.about=Die Datenschutzerklärung fasst zusammen, welche Informationen wir von Mitgliedern sammeln und erklärt, wie wir diese Information verwenden. + +/legal/index.bml.docs.tos.about=Die Nutzungsbedingungen legen fest, welche Art von Nutzung akzeptabel ist, und welche Bedingungen für die Mitgliedschaft gelten. Die Mitgliedschaft und/oder Verwendung des Systems setzt Zustimmung zur Befolgung dieser und anderer vereinbarter Bedingungen voraus. + +/legal/index.bml.title=Rechtliche Information + +/legal/privacy.bml.title=Datenschutzerklärung + +/legal/tos.bml.title=Nutzungsbedingungen + +/login.bml.bindip.label=An feste IP-Adresse binden: + +/login.bml.bindip.no=Nein (funktioniert mit allen ISPs) + +/login.bml.bindip.yes=Ja (sicherer) + +/login.bml.error.mustenterusername=Du musst einen Benutzernamen eingeben. + +/login.bml.expire.btn.neverexpire=Login auf DAUERHAFT GÜLTIG umstellen + +/login.bml.expire.btn.sessiononly=Login auf NUR FÜR DIESE SITZUNG GÜLTIG umstellen + +/login.bml.expire.neverexpire.text=Dein Login bleibt dauerhaft gültig. Befindest du dich an einem öffentlichen Internet-Terminal, in einer Schule, Bibliothek oder einem anderen Ort, an dem andere Leute diesen Computer demnächst benutzen könnten, dann vergiss nicht, dich auszuloggen, wenn du fertig bist! Oder stelle deinen Login-Modus um, sodass er beim Beenden des Browsers ungültig wird: + +/login.bml.expire.sessiononly.text=Dein Login wird ungültig, wenn du deinen Browser schließt. Falls dies dein eigener Computer ist und du der einzige Benutzer bist, kannst du deinen Login so umstellen, dass er dauerhaft gültig bleibt: + +/login.bml.links.link1=Deine Freunde. + +/login.bml.links.link2=Deine To-Do Liste. + +/login.bml.links.text=Zukünftig wird diese Seite alle möglichen Links und Informationen enthalten, aber bis dahin sind hier ein paar Stellen, die dich vielleicht interessieren: + +/login.bml.loggedin.head=Eingeloggt! + +/login.bml.loggedin.text=Du bist jetzt eingeloggt. + +/login.bml.login.btn.changeopts=Optionen ändern + +/login.bml.login.btn.login=Einloggen... + +/login.bml.login.expiration=Gültigkeitsdauer des Logins läuft ab: + +/login.bml.login.forget=Vergessen? + +/login.bml.login.head=Einloggen + +/login.bml.login.never=Niemals + +/login.bml.login.otheropts=Andere Optionen: + +/login.bml.login.password=Passwort: + +/login.bml.login.text1=Um sich bei [[sitename]] einzuloggen, gib unten deinen Benutzernamen und Passwort ein. Neue Benutzer: Um einen neuen Account anzulegen, gehe hier hin. + +/login.bml.login.text2<< +Du kannst auch angeben, wann dein Login ungültig wird. Normalerweise wird dein Login ungültig, wenn du deinen Browser schließt (das ist am besten für öffentlich zugängliche Computer). Falls du der einzige Benutzer deines Computers bist und niemand sonst Zugang dazu hat, kannst du auch einstellen, dauerhaft eingeloggt zu bleiben. Mehr Informationen über diese und andere Optionen findest du in der FAQ Welche Optionen kann ich während des Einloggens einstellen? + +. + +/login.bml.login.text3=[[username]], du bist nun bei [[sitename]] eingeloggt. Mit der Site Map kannst du die Webseite erkunden. + +/login.bml.login.username=Benutzername: + +/login.bml.login.whenbrowsercloses=Beim Schließen des Browsers + +/login.bml.logout.btn=Ausloggen + +/login.bml.title=Einloggen + +/login.bml.whylogin.benefit1=Du brauchst deinen Benutzernamen und dein Passwort nicht mehr eingeben. + +/login.bml.whylogin.benefit2=Du kannst "geschützte" Journaleinträge deiner Freunde lesen, falls sie dir den Zugang gestattet haben. + +/login.bml.whylogin.benefit3=Vieles ist nur sichtbar bzw. zugänglich, wenn du eingeloggt bist. + +/login.bml.whylogin.head=Warum einloggen? + +/login.bml.whylogin.text=Dies sind einige der wesentlichen Vorteile des Einloggens: + +/logout.bml.already.head=Bereits ausgeloggt + +/logout.bml.already.text=Du bist bereits ausgeloggt. + +/logout.bml.killall.btn=Alle Sitzungen beenden + +/logout.bml.killall.head=Andere Sitzungen + +/logout.bml.killall.text=Andere Sitzungen sind noch aktiv. Möchtest du alle Sitzungen beenden statt nur dieser hier? (Mehr Informationen findest du in diesem FAQ.) + +/logout.bml.loggedout.already=Bereits ausgeloggt. + +/logout.bml.loggedout.head=Ausgeloggt + +/logout.bml.loggedout.killedall=Alle deine Sitzungen wurden beendet. + +/logout.bml.loggedout.success=Ausgeloggt. + +/logout.bml.loggedout.text=Du bist jetzt ausgeloggt. + +/logout.bml.logout.btn=Ausloggen. + +/logout.bml.logout.head=Ausloggen? + +/logout.bml.logout.text=Klicke auf den nachstehenden Button um dich auszuloggen. + +/logout.bml.title=Ausloggen + +/lostinfo.bml.btn.proceed=Weiter + +/lostinfo.bml.enter_email=Gib deine E-Mail-Adresse ein: + +/lostinfo.bml.enter_email_optional=E-Mail-Adresse: (optional) + +/lostinfo.bml.enter_username=Gib deinen Benutzernamen ein: + +/lostinfo.bml.error.no_email=Du musst eine E-Mail-Adresse eingeben, um deinen Benutzernamen abzufragen. + +/lostinfo.bml.error.purged=Du kannst nicht das Passwort eines permanent gelöschten Accounts wiedererlangen. + +/lostinfo.bml.error.renamed=Du kannst nicht das Passwort eines Accounts wiedererlangen, dessen Benutzername geändert wurde. + +/lostinfo.bml.error.syndicated=Das Account, dessen Passwort abgerufen werden soll, ist eine externe Artikelquelle. Solche Accounts verfügen über kein Passwort, das man abrufen kann. + +/lostinfo.bml.error.sysbanned=Deinem Account dürfen keine Passwörter zugeschickt werden. + +/lostinfo.bml.lostpassword.text=Wenn du dein Passwort verloren hast, dann gib deinen Benutzernamen und gegebenenfalls auch die E-Mail-Adresse ein, an die das Passwort verschickt werden soll. Möchtest du, dass das Passwort an eine E-Mail-Adresse verschickt wird, die du zu einem früheren Zeitpunkt verwendet hast, dann muss diese Adresse vorher schon einmal bei LiveJournal bestätigt gewesen sein. Lässt du das Feld für die E-Mail-Adresse frei, dann wird dir das Passwort an die aktuelle Adresse geschickt. + +/lostinfo.bml.lostpassword.title=Hast du dein Passwort verloren? + +/lostinfo.bml.lostusername.text=Wenn du deinen Benutzernamen vergessen hast, gib deine E-Mail-Adresse ein und wir schicken dir deinen Benutzernamen zu. + +/lostinfo.bml.lostusername.title=Hast du deinen Benutzernamen vergessen? + +/lostinfo.bml.title=Verlorene Informationen + +/lostinfo_do.bml.error.no_usernames_for_email=Kein(e) Benutzername(n) für diese E-Mail-Adresse: [[address]] . + +/lostinfo_do.bml.error1.text=Diese E-Mail-Adresse wurde nie mit diesem Account verwendet oder sie wurde nie bestätigt. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Dies ist eine automatisch generierte Nachricht. *** +*** Eine Antwort ist nicht erforderlich. *** + + +Dies ist die angeforderte E-Mail mit der Passwort- +Erinnerung von [[sitename]]. +Der Benutzername, das Passwort und die E-Mail-Adresse, +unter denen dein Account +registriert ist, sind im folgenden angegeben: + + Benutzername: [[username]] + Passwort: [[password]] + E-Mail-Adresse: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Um deine E-Mail-Adresse bestätigen zu lassen, folge diesem Link: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Diese Information wurde auf der Webseite von [[remoteip]] +angefordert. + +Wenn du das Passwort nicht angefordert hast, brauchst du dich nicht +zu sorgen. Schließlich bist du der- oder diejenige, der diese E-Mail +sieht, und nicht die andere Person. Es ist möglich, dass der Benutzer, +der die Anforderung gemacht hat, fälschlicherweise glaubt, er habe +Kontrolle über deinen Account erlangt. Es kann auch sein, dass sich +jemand im Benutzernamen oder der E-Mail-Adresse vertippt hat. + +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Wenn du Grund zu der Annahme hast, dass die Sicherheit +deines Accounts gefährdet ist, liefert die folgende FAQ +Informationen darüber, wie Accounts gesichert werden können: + "Jemand ist in meinen LiveJournal-Account eingebrochen!" + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Weiterführende Links: + +Dein LiveJournal: + [[journalurl]] + +Einen neuen Eintrag in dein Journal schreiben: + [[updateurl]] + + +Mit freundlichen Grüßen +Das LiveJournal-Team + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Angeforderte Passwort-Erinnerung + +/lostinfo_do.bml.password_mailed.text=Dein Passwort wurde erfolgreich verschickt. + +/lostinfo_do.bml.password_mailed.title=Passwort verschickt! + +/lostinfo_do.bml.title=Verlorene Informationen + +/lostinfo_do.bml.username_mailed.text=Dein Benutzername wurde dir erfolgreich zugestellt. + +/lostinfo_do.bml.username_mailed.title=Benutzername zugestellt! + +/manage/index.bml.about=Die Verwaltung deines Accounts ist einfach. Wähle einfach einen der folgenden Bereiche aus. + +/manage/index.bml.communities=Erstelle und verwalte deine eigenen Communities: + +/manage/index.bml.communities.create.about=Erstelle eine neue Community + +/manage/index.bml.communities.manage.about=Verwalte die Einstellungen und Mitgliederlisten deiner Communities + +/manage/index.bml.customization=Bearbeite das Aussehen deiner Journal-Seiten: + +/manage/index.bml.customization.advanced=Erweiterte Anpassung + +/manage/index.bml.customization.advanced.about=Durchsuche, erstelle und bearbeite deine S2-Layouts und Stile + +/manage/index.bml.customization.customize=Journal anpassen + +/manage/index.bml.customization.customize.about=Verändere das Aussehen deines Journals + +/manage/index.bml.customization.header=Anpassung + +/manage/index.bml.customization.links=Links-Liste + +/manage/index.bml.customization.links.about=Erstelle eine Liste von Links, die in deinem Journal angezeigt werden + +/manage/index.bml.customization.modify.about=Bearbeite die Darstellung deines Journals + +/manage/index.bml.customization.s1.header=Stilsystem S1 + +/manage/index.bml.customization.s2.header=Stilsystem S2 + +/manage/index.bml.entries=Arbeite mit Einträgen, die in deinem Journal stehen: + +/manage/index.bml.entries.edit.about=Bearbeite und lösche Einträge in deinem Journal + +/manage/index.bml.entries.header=Journal-Einträge + +/manage/index.bml.entries.memories.about=Schaue dir deine erinnerungswürdigen Einträge an und arbeite mit ihnen + +/manage/index.bml.friends=Bearbeite deine Freundesliste und Freundesgruppen, oder schaue dir eine nach Freundesgruppen gefilterte Freundesseite an: + +/manage/index.bml.friends.edit.about=Hinzufügen und Entfernen von Benutzern auf deiner Freundesliste bzw. Verändern der ihnen zugeordneten Farbe. + +/manage/index.bml.friends.filter=Freundesseite filtern + +/manage/index.bml.friends.filter.about=Filtere deine Freundesseite, um nur eine bestimmte Freundesgruppe anzuzeigen + +/manage/index.bml.friends.groups.about=Erstelle, bearbeite oder lösche Untergruppen deiner Freundesliste + +/manage/index.bml.friends.header=Freunde + +/manage/index.bml.information=Wähle aus, welche Informationen bei deinem Account dargestellt werden: + +/manage/index.bml.information.changepass=Passwort des Accounts ändern + +/manage/index.bml.information.changepass.about=Verändere das Passwort deines Accounts + +/manage/index.bml.information.editinfo.about=Bearbeite die Informationen und weitere Optionen zu deinem Account + +/manage/index.bml.information.emailpost=Einstellungen des E-Mail-Gateways + +/manage/index.bml.information.emailpost.about=Verwalte deine E-Mail-Adressen und die PIN für das Schreiben von Einträgen per E-Mail + +/manage/index.bml.information.header=Account-Informationen + +/manage/index.bml.information.siteopts.about=Wähle dein bevorzugtes LiveJournal-Layout & die Sprache aus + +/manage/index.bml.information.status=Account-Status + +/manage/index.bml.information.status.about=Stelle den Aktivierungsstatus deines Accounts ein (Account löschen bzw. wieder aktivieren) + +/manage/index.bml.login=Die folgenden Links werden dich auf Seiten leiten, auf denen deine Login-Informationen benötigt werden. Um dir etwas Zeit zu sparen, kannst du dich vorher einloggen. + +/manage/index.bml.title=Accounts verwalten + +/manage/index.bml.userpictures=Lade Benutzerbilder für deinen Account hoch und verwalte sie: + +/manage/index.bml.userpictures.edit.about=Hochladen und Verwalten deiner Benutzerbilder + +/manage/index.bml.userpictures.header=Benutzerbilder + +/manage/links.bml.about=Verwende das Formular unten, um eine Liste von Links zu erstellen, die in deinem Journal angezeigt werden. Links werden nur dann angezeigt, wenn das Feature von deinem S2-Stil unterstützt wird. + +/manage/links.bml.about.blank=Um eine leere Zeile einzufügen, gib "-" als Titel ein. + +/manage/links.bml.about.heading=Um eine Überschrift zu erstellen, gib einen Titel ohne URL ein. + +/manage/links.bml.about.reorder=Um die Reihenfolge von Links in der Liste zu verändern, verändere die Zahlen auf der linken Seite (Dezimalzahlen sind ok). + +/manage/links.bml.error.s2required=Die Link-Liste ist nur für S2-Stile verfügbar, die diese unterstützen. Auf der Seite [[link]] kannst du auf das S2-System umstellen. + +/manage/links.bml.error.s2required.header=Benötigt S2 + +/manage/links.bml.success=Änderung erfolgreich! Deine Links wurden gespeichert. + +/manage/links.bml.title=Link-Liste + +/manage/phonepost.bml.delete=Einstellungen löschen + +/manage/phonepost.bml.deleted=Deine Einstellungen für Telefoneinträge wurden gelöscht. + +/manage/phonepost.bml.deleted.header=Gelöscht + +/manage/phonepost.bml.error.inuse=Ungültige PIN, bitte versuche eine andere + +/manage/phonepost.bml.error.phone.length=Deine Telefonnummer muss mindestens aus 10 Ziffern bestehen. + +/manage/phonepost.bml.error.pin=Deine PIN muss aus Ziffern bestehen. + +/manage/phonepost.bml.error.transcription=Ungültige Freundesgruppe oder Transkription + +/manage/phonepost.bml.intro.loggedin<< +Telefoneintrag machen möchtest, dann gib unten deine Telefonnummer und deine PIN ein. p?> +Datenschutzerklärung) +Anrufe von anderen Nummern als von deiner authorisierten Telefonnummer werden auch akzeptiert, du musst aber vor der Aufnahme des Telefoneintrags deine authorisierte Telefonnummer eingeben. p?> + +. + +/manage/phonepost.bml.intro.loggedout=Mitglieder von können sich einloggen und ihre Einstellungen für Telefoneinträge hier ändern: + +/manage/phonepost.bml.phone=Freigeschaltete Telefonnummer: + +/manage/phonepost.bml.phone.help=001 (515) 555-5555 + +/manage/phonepost.bml.pin=Persönliche Identifikationsnummer: + +/manage/phonepost.bml.pin.help=4-6 Ziffern empfohlen + +/manage/phonepost.bml.save=Einstellungen speichern + +/manage/phonepost.bml.saved=Gespeichert + +/manage/phonepost.bml.success.moreinfo=Mehr Informationen, wie du einen Telefoneintrag aufnehmen kannst, findest du in der FAQ "Wie kann ich einen Telefoneintrag für mein Journal aufnehmen?". + +/manage/phonepost.bml.success.text=Die Telefon-Einstellungen wurden gespeichert. + +/manage/phonepost.bml.title=Einstellungen für Einträge per Telefon + +/manage/phonepost.bml.transcribers=Die folgenden Benutzer dürfen transkribieren: + +/manage/phonepost.bml.transcribers.help=Freundesgruppen bearbeiten + +/manage/pubkey.bml.error.invalidkey=Das scheint kein gültiger PGP/GPG-Key zu sein. + +/manage/pubkey.bml.error.notconfigured=Diese Seite ist nicht für PGP-Support konfiguriert. + +/manage/pubkey.bml.header=PGP/GPG-Key + +/manage/pubkey.bml.info=Das Veröffentlichen deiner Public Keys lässt andere Benutzer diese in deinem Benutzerprofil sehen und du kannst signierte Messages über den E-Mail-Gateway schicken. Weitere Informationen gibt es hier. + +/manage/pubkey.bml.pastekey=Füge deinen Key im ASCII-Format komplett in das Feld unten ein: + +/manage/pubkey.bml.save=Speichern + +/manage/pubkey.bml.successhead=Aktion erfolgreich + +/manage/pubkey.bml.successtext=Dein Public Key wurde gespeichert. Du kannst ihn hier anschauen. + +/manage/pubkey.bml.title=Public Key einstellen + +/manage/pubkey.bml.whatis=Du weißt nicht, was ein Public Key ist? Brauchst Hilfe beim Exportieren deines Keys? Erfahre mehr über PGP und GPG. + +/manage/siteopts.bml.btn.lang=Sprache wechseln + +/manage/siteopts.bml.btn.scheme=LiveJournal-Layout wechseln + +/manage/siteopts.bml.head.lang=Wähle deine Sprache aus + +/manage/siteopts.bml.head.scheme=Wähle dein bevorzugtes LiveJournal-Layout aus + +/manage/siteopts.bml.scheme.preview=[Vorschau des Schemas [[title]]] + +/manage/siteopts.bml.title=Grundeinstellungen + +/meme.bml.meme.disabled=Der Adminstrator der Site hat dieses Feature deaktiviert. + +/modify.bml.title=Design ändern + +/modify_do.bml.availablestyles.head=Verfügbare Stile + +/modify_do.bml.availablestyles.userstyles=Benutzer Stile: + +/modify_do.bml.colortheme.about=Hier kannst du auswählen, welches Farbmotiv auf die von dir gewählten Journaloptionen angewendet werden soll oder du kannst, falls dir die vorgegebenen Farben nicht gefallen, deine eigenen aussuchen! + +/modify_do.bml.colortheme.area.head=Verwendung für + +/modify_do.bml.colortheme.color.head1=Farbe + +/modify_do.bml.colortheme.color.head2=(#rrggbb oder Name) + +/modify_do.bml.colortheme.customcolors=Benutzerdefinierte Farben + +/modify_do.bml.colortheme.defaulttheme=Standardmotiv + +/modify_do.bml.colortheme.head=Farbmotiv + +/modify_do.bml.domainalias.about=Falls du einen Domain-Namen registriert hast (oder planst einen zu registrieren), der zu deinem LiveJournal führen soll, gib den Namen hier ein: + +/modify_do.bml.domainalias.domainname=Domain Name: + +/modify_do.bml.domainalias.example=Beispiel: mein-journal.de + +/modify_do.bml.domainalias.head=Domainweiterleitung + +/modify_do.bml.domainalias.helptext=Damit dies funktioniert, musst du den DNS (domain name server) deiner Domain so einstellen, dass er auf die IP-Adresse von [[sitename]] verweist. Weitere Informationen dazu findest du hier. + +/modify_do.bml.done.btn.savechanges=Änderungen speichern + +/modify_do.bml.done.head=Fertig? + +/modify_do.bml.done.text=Wenn du fertig bist, drücke den folgenden Button "Änderungen speichern". + +/modify_do.bml.error.dupdomainalias=Ein anderer Benutzer hat sich bereits für den von dir gewählten Domain Alias registriert. + +/modify_do.bml.error.stylenotavailable=Einer der von dir ausgewählten Stile ist nicht verfügbar. Entweder hat jemand den Stil gelöscht, oder du versucht einen Stil auszuwählen, auf den du keinen Zugriff hast. + +/modify_do.bml.friends.about=Dies sind die Optionen, die festlegen, wie deine Freundesseite aussieht. + +/modify_do.bml.friends.head=Freundesseite + +/modify_do.bml.friends.opt.usesharedpic.about=Diese Option legt fest, welche Benutzerbilder du auf deiner Freundesliste siehst, wenn jemand in einer Community oder einem gemeinsamen Journal schreibt.. Wenn aktiviert, wird das Benutzerbild der Community angezeigt. Wenn nicht angekreuzt, wird das Benutzerbild des Autors angezeigt. + +/modify_do.bml.friends.opt.usesharedpic.head=Die Benutzerbilder gemeinsamer Journale an Stelle der Benutzerbilder des Autors anzeigen + +/modify_do.bml.journaloptions.about=Hier kannst du das Aussehen deiner Journalseiten anpassen. Wenn du genau wissen möchtest, wie das alles funktioniert, lies die Informationen im Entwicklerbereich. Andernfalls nehmen wir an, dass du mit den folgenden einfachen Optionen auskommst: + +/modify_do.bml.journaloptions.head=Journaleinstellungen + +/modify_do.bml.journalstatus.about=Wenn du dein Tagebuch löschen möchtest oder den Löschvorgang wieder rückgängig machen möchtest, ist dies die richtige Stelle. Sobald du dein Journal gelöscht hast, hast du 30 Tage Zeit, um den Löschvorgang rückgängig zu machen, falls du es dir anders überlegst. Nach 30 Tagen wird das Journal endgültig gelöscht und kann nicht mehr wiederhergestellt werden. + +/modify_do.bml.journalstatus.head=Journal Status + +/modify_do.bml.journalstatus.select.activated=Aktiv + +/modify_do.bml.journalstatus.select.deleted=Gelöscht + +/modify_do.bml.journalstatus.select.suspended=Gesperrt + +/modify_do.bml.moodicons.about=Wenn du einen Eintrag schreibst, kannst du auch deine aktuelle Stimmung angeben. Verschiedene Benutzer haben diverse Stimmungssymbole erstellt, die du benutzen kannst. Oder wähle "Keine" aus, wenn du keine Symbole zu deiner Stimmung angezeigt werden sollen. Du kannst auch ganz darauf verzichten, Stimmungen anzuzeigen. + +/modify_do.bml.moodicons.head=Stimmungssymbole + +/modify_do.bml.moodicons.opt.forcefriends.about=Dieses Stimmungsmotiv auf alle Freunde deiner Freundesliste anwenden + +/modify_do.bml.moodicons.personal=Persönliche Themen: + +/modify_do.bml.moodicons.preview=Vorschau + +/modify_do.bml.moodicons.select=Stimmungsmotiv auswählen: + +/modify_do.bml.overrides.about=Wenn du zufrieden mit den oben angegebenen Anpassungsmöglichkeiten für dein Journal bist, kannst du diesen Abschnitt getrost ignorieren. Hier können sehr spezielle Aspekte deines Layouts verändert werden. Einen Überblick kannst du in der FAQ "Was sind Stilanpassungen? Wie funktionieren sie?" finden; Details findest du im Entwicklerbereich. Bitte beachte auch, dass du mit Hilfe von Stilanpassungen nur ein oder zwei Aspekte deines Stils verändern solltest. Wenn du alles ändern willst, musst du einen eigenen Stil erstellen. Weiterführende Informationen zur Erstellung eines Stils findest du hier. + +/modify_do.bml.overrides.box.head=Stilanpassungen: + +/modify_do.bml.overrides.head=Stilanpassungen: + +/modify_do.bml.overrides.note=Bitte beachte, dass nicht alle Stil-Variablen durch Overrides angepasst werden können. Die Dokumentation enthält mehr Details zu diesem Thema.
    Bitte beachte auch, dass die Elemente <DIV>, <SPAN> und <IMG> sowie viele andere HTML-Tags aus den *_HEAD-Overrides entfernt werden, da diese Tags nicht im Kopfteil des Dokumentes erlaubt sind. Die einzigen HTML-Elemente, die in den *_HEAD-Overrides verwendet werden dürfen, sind jene Elemente, die auch im Kopfteil eines HTML-Dokumentes gültig sind. Diese Tags beschränken sich auf <title>, <base>, <style>, <link> und <meta>. + +/modify_do.bml.overrides.warning=HIER KÖNNEN KEINE JOURNAL-EINTRÄGE GESCHRIEBEN WERDEN!! + +/modify_do.bml.pagelayoutstyle.about=Hier kannst du einstellen, wie dein Journal angezeigt werden soll. + +/modify_do.bml.pagelayoutstyle.head=Stil des Seiten-Layouts + +/modify_do.bml.pagelayoutstyle.warning=Dein Account-Typ gestattet nur die Auswahl einiger weniger Standard-Stile. + +/modify_do.bml.success.head=Aktion erfolgreich + +/modify_do.bml.success.text=Deine Journaleinstellungen wurden übernommen. Du kannst dein Journal hier ansehen. + +/multisearch.bml.formaterror=Format-Fehler + +/multisearch.bml.noaddress.text=Es wurde keine Mailadresse eingegeben. + +/multisearch.bml.noaddress.title=Keine Adresse + +/multisearch.bml.nointerest.text=Es wurde kein Interesse eingegeben. + +/multisearch.bml.nointerest.title=Kein eingegebenes Interesse + +/multisearch.bml.nomatch.text=Für die angegebenen Suchkriterien liegen keine Resultate vor. + +/multisearch.bml.nomatch.title=Keine Resultate + +/multisearch.bml.region.bodytext<< +Du kannst in einem der folgenden Formate nach Regionen suchen: +
      +
    • Land
    • +
    • Stadt *
    • +
    • Stadt, Bundesstaat *
    • +
    • Bundesstaat, Land
    • +
    • Stadt, Bundesstaat, Land
    • +
    +Anmerkungen: +
      +
    • * die Suche nach einer Stadt oder einem Bundesstaat ohne Länderangabe nimmt automatisch die USA als gesuchtes Land an
    • +
    • die Länderangabe kann entweder der volle Ländername oder der zweibuchstabige Ländercode sein
    • +
    +Andere Suchmöglichkeiten gibt es in der Verzeichnissuche. +. + +/multisearch.bml.region.head=Nach Region suchen + +/paidaccounts/index.bml.costs.header=Also, wieviel kostet es? + +/paidaccounts/index.bml.costs.rates=Die Preise sind wie folgt: + +/paidaccounts/index.bml.costs.rates.amount.header=Betrag + +/paidaccounts/index.bml.costs.rates.inexpensive<< +Das ist ein bisschen mehr als $2/Monat und wird kaum dein Portemonnaie sprengen. +Der ärgerlichste Teil wird wahrscheinlich das Herausholen deiner Brieftasche, das Finden der Kreditkarte und das Eintippen der Informationen sein. +. + +/paidaccounts/index.bml.costs.rates.time.header=Dauer + +/paidaccounts/index.bml.features|staleness=1 +/paidaccounts/index.bml.features<< +
    Um die Benutzer, die zu LiveJournal beigetragen haben, anzuerkennen, gibt es einige Features, die nur mit bezahlten Accounts verwendet werden können. Diese Features beinhalten zum Beispiel:
    + +
    Neu! Einträge per E-Mail
    +
    Bezahlte Accounts können durch unseren E-Mail-Zugang schnell und sicher Einträge in ihre Journale und Communities schreiben.
    + +
    Dein Journal anpassen
    +
    Zusätzlich zu der Möglichkeit, nur einen Stil für dein Journal und Farben auszuwählen, kannst du mit HTML auch deinen eigenen Stil erstellen. So kannst du auch neue Stile erstellen, die zu deiner Webseite passen, die du dann leicht dort einbetten kannst. So fällt nicht auf, dass du LiveJournal.com als Grundlage für dein Journal verwendest.
    + +
    Umfragen
    +
    Mit einem bezahlten Account kannst du Umfragen in deinem eigenen Journal und in sämtlichen Communities erstellen, zu denen zu Schreibzugriff hast.
    + +
    Mehr Benutzerbilder
    +
    Mit einem bezahlten Account kannst du 15 Benutzerbilder verwenden, statt der üblichen 3 für kostenlose Accounts.
    + +
    LiveJournal.com E-Mail-Adresse
    +
    Mit einem bezahlten Account erhältst du eine LiveJournal.com E-Mail-Adresse ([[username]]@livejournal.com), die an- oder ausgeschaltet werden kann.
    + +
    Verzeichnissuche
    +
    Mit einem bezahlten Account hast du Zugriff auf das Verzeichnis, um nach anderen Benutzern zu suchen.
    + +
    LiveJournal.com-Subdomain
    +
    Nicht nur unter http://www.livejournal.com/users/[[username]]/ wird dein Journal verfügbar sein, sondern auch unter http://[[username]].livejournal.com/, was viel kürzer und persönlicher ist.
    + +
    Externe Artikelquellen
    +
    Mit einem bezahlten Account kannst du externe Artikelquellen erstellen, die im RSS-Format bei LiveJournal eingespeist werden.
    + +
    Textnachrichten
    +
    Mit einem bezahlten Account erhältst du Zugriff auf das SMS-Feature, mit dem du über LiveJournals Benutzeroberfläche Textnachrichten auf deinem Handy oder Beeper erhalten kannst.
    + +
    Erweiterte Aufgabenliste
    +
    Mit einem bezahlten Account kannst du bis zu 150 Aufgaben auf deiner Aufgabenliste definieren und jeder Aufgabe unterschiedliche Sicherheitslevel zuweisen.
    + +
    RSS-Ansicht
    +
    Die RSS-Ansicht für Inhaber bezahlter Accounts beinhaltet den vollen Eintragstext von externen Artikelquellen an Stelle von einfachen Zusammenfassungen.
    + +
    Einbetten
    +
    Mit einem bezahlten Account hast du Zugriff auf die volle Palette der Optionen für das Einbetten deines Journals in deine Homepage, wie auf der Seite "Journal einbetten" näher erklärt.
    + +
    Domainweiterleitung
    +
    Bezahlte Benutzer können eine Domainweiterleitung aktivieren, so dass ihre Internet-Domain zu ihrem LiveJournal verweist.
    + +
    Mehr...
    +
    Eine vollständige Liste von den Vorzügen eines bezahlten Accounts kann in der FAQ Was sind die Vorzüge eines bezahlten Accounts? gefunden werden
    +. + +/paidaccounts/index.bml.features.header=Was für Funktionen kann ich dann verwenden? + +/paidaccounts/index.bml.title=Über bezahlte Accounts + +/paidaccounts/index.bml.whypay.argument<< +Natürlich nicht. Es ist ärgerlich, für Internetdienstleistungen zu bezahlen, das finden wir auch. +Deswegen ist ein großer Teil der LiveJournal-Funktionen auch kostenlos verfügbar. +Bist du allerdings zufrieden mit dem Service, der dir geboten wird, kannst du uns unterstützen, indem du einen bezahlten Account erwirbst. +. + +/paidaccounts/index.bml.whypay.header=Ich muss bezahlen, um LiveJournal zu benutzen? + +/paidaccounts/index.bml.whypay.no_ads=Zum Betreiben von Websites benötigt man Geld (für die Server, die Unterbringung und die Bandbreite) und diese Zahlungsweise scheint uns sinnvoller, als dich mit Pop-Up-Bannerwerbungen zu belästigen und dich mit Werbung zu überfluten. + +/paidaccounts/index.bml.your_username=dein_benutzername + +/paidaccounts/usepaypal.bml.delivery.badformat=Ungültiges Datumsformat. Bitte entweder in der Form jjjj-mm-tt oder jjjj-mm-tt hh:mm eingeben. + +/paidaccounts/usepaypal.bml.delivery.past=Zustellungsdatum kann nicht in der Vergangenheit liegen. Für sofortige Zustellung bitte das Feld freilassen. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Zustellungsdatum darf nicht weiter als einen Monat in der Zukunft liegen. + +/pay/index.bml.deliverydate.details=Format: jjjj-mm-tt hh:mm (GMT)
    (freilassen, falls Lieferung nicht verzögert werden soll) + +/pay/index.bml.deliverydate.label=Lieferdatum: + +/pay/index.bml.gift.anonymous=Anonymes Geschenk + +/poll/create.bml.button.editpoll=Umfrage bearbeiten + +/poll/create.bml.button.insert=Einfügen + +/poll/create.bml.button.postpoll=Umfrage abschicken + +/poll/create.bml.button.preview=Vorschau der Umfrage + +/poll/create.bml.button.seecode=Code anschauen + +/poll/create.bml.button.startover=Neu anfangen + +/poll/create.bml.elements.limitreached=Keine weiteren Elemente möglich + +/poll/create.bml.error.accttype=Dein Account-Typ erlaubt es dir nicht, Umfragen zu erstellen. + +/poll/create.bml.error.allitemsblank=Wenigstens ein Element muss ausgefüllt sein. + +/poll/create.bml.error.notext=Du benötigst Text, der die Frage erklärt. + +/poll/create.bml.error.parsing=Fehler beim Erstellen der Umfrage + +/poll/create.bml.error.pqmaxlengthinvalid=Das Maxlength-Attribut (Maximallänge) bei lj-pq-Tags muss eine ganze Zahl zwischen [[min]] und [[max]] sein. + +/poll/create.bml.error.pqsizeinvalid=Das Size-Attribut (Größe) bei lj-pq-Tags muss eine ganze Zahl zwischen [[min]] und [[max]] sein. + +/poll/create.bml.error.scalemaxlessmin=Der Wert 'from' in der Skala muss kleiner sein als der Wert 'to'. + +/poll/create.bml.error.scalemininvalid=Skala muss sich mindestens um [[min]] erhöhen. + +/poll/create.bml.error.scaletoobig=Maximale Auswahlmöglichkeit [[max]] (von-bis)/Schritte > 20 + +/poll/create.bml.error.texttoolong=Der Text deiner Option ist zu lang und wurde abgeschnitten. + +/poll/create.bml.haserrors=Ein oder mehr Fehler liegen in der Umfrage vor. Unten stehen die genauen Details. + +/poll/create.bml.insertquestion=Frage hier eingeben: + +/poll/create.bml.options=Optionen: + +/poll/create.bml.options.limitreached=Mehr Optionen sind nicht möglich + +/poll/create.bml.pollname=Name der Umfrage: (opt.) + +/poll/create.bml.preview.desc=Unten ist eine Vorschau der Umfrage. Genau so wird die Umfrage aussehen, sobald sie abgeschickt ist. Die Buttons unten können verwendet werden, um zurückzugehen und die Umfrage zu verändern, oder sie abzuschicken. + +/poll/create.bml.preview.options=Optionen + +/poll/create.bml.properties=Eigenschaften der Umfrage + +/poll/create.bml.question=Frage: + +/poll/create.bml.questionnum=Frage #[[num]] + +/poll/create.bml.questions=Fragen + +/poll/create.bml.title=Umfragen-Generator + +/poll/create.bml.type.check=Kästchen + +/poll/create.bml.type.drop=Dropdown-Box + +/poll/create.bml.type.radio=Radio-Buttons + +/poll/create.bml.type.scale=Skala + +/poll/create.bml.type.text=Textfeld + +/poll/create.bml.whoview=Wer kann die Umfragenergebnisse ansehen? + +/poll/create.bml.whovote=Wer kann in der Umfrage abstimmen? + +/poll/index.bml.discuss=Kommentarseite + +/poll/index.bml.error.cantview=Sorry, du kannst dir die Umfrageergebnisse nicht anschauen. + +/poll/index.bml.error.postdeleted=Da der Eintrag gelöscht wurde, kann auf die Umfrage nicht länger zugegriffen werden. + +/poll/index.bml.filloutpoll=Umfrage ausfüllen + +/poll/index.bml.gotocreate=Dies ist der URL, über den man an einer Umfrage teilnehmen kann. Dieser spezielle URL ist im Moment nicht funktionell. Wenn du möchtest, kannst du eine neue Umfrage erstellen. + +/poll/index.bml.pollnotfound=Umfrage nicht gefunden + +/poll/index.bml.submitted.head=Danke + +/poll/index.bml.submitted.text=Die Antworten der Umfrage wurden abgeschickt. + +/poll/index.bml.submitted.title=Antworten abgeschickt! + +/poll/index.bml.title=Umfrage + +/poll/index.bml.viewresults=Antworten anschauen + +/press/staff.bml.accountserv=Account-Service + +/press/staff.bml.administration=Verwaltung + +/press/staff.bml.administration.about=LiveJournal.com begann 1999 als ein Projekt von Brad Fitzpatrick. Es wurde während seiner ersten zwei "Lebensjahre" von einer großen und loyalen Gruppe von Freiwilligen aufrechterhalten. Während ein großer Teil von LiveJournal.com immer noch von Freiwilligenteams betrieben wird, gibt es nun auch eine kleine Gruppe Angestellter, welche den Überblick über alle Vorgänge behalten: + +/press/staff.bml.avva.title=Erfahrener Programmierer + +/press/staff.bml.back2=Zurück zur Presseseite + +/press/staff.bml.bradfitz.quip=Konzentriere dich auf dein Produkt und nicht darauf, Geld zu machen. + +/press/staff.bml.bradfitz.title=Vorsitzender / Hauptprogrammierer + +/press/staff.bml.contact=Möchtest du dich mit einem von uns in Verbindung setzen, schicke bitte eine E-Mail an webmaster@livejournal.com. + +/press/staff.bml.custserv=Kundenservice / Benutzerfreundlichkeit + +/press/staff.bml.david.title=Der Praktikant + +/press/staff.bml.denisep.quip=Bis nächsten Donnerstag krieg ich das hin. + +/press/staff.bml.denisep.title=Kontakt zu Freiwilligen / Profi in Sachen Benutzerfreundlichkeit + +/press/staff.bml.deveiant.title=Entwickler außer Landes + +/press/staff.bml.developers=Entwickler + +/press/staff.bml.evan.title=Hacker im Ruhestand + +/press/staff.bml.ferrell.title=Verwaltung des Kundenservice + +/press/staff.bml.jproulx.quip=Verbindungsglied zwischen Hackern und Benutzern. + +/press/staff.bml.jproulx.title=Datenverwalter der Website / Pressesprecher + +/press/staff.bml.kevin.title=Grafik- und Web-Designer + +/press/staff.bml.lisa.title=Systemadministrator + +/press/staff.bml.mahlon.quip=Iiik! Iiik! + +/press/staff.bml.mahlon.title=eifriger Programmierer + +/press/staff.bml.nick.title=System-Administrator + +/press/staff.bml.ryanfitz.title=Zahlungsabwicklung + +/press/staff.bml.sandy.title=Buchhaltung und Verwaltung + +/press/staff.bml.smithy.title=Hacker-Azubi + +/press/staff.bml.sysadmin=System-Administratoren + +/press/staff.bml.title=Angestellte + +/press/staff.bml.whitaker.quip=Und als nächstes? + +/press/staff.bml.whitaker.title=Entwickler auf Entfernung + +/pubkey.bml.error.notconfigured=Diese Seite wurde nicht für PGP-Support konfiguriert. + +/pubkey.bml.error.nousername=Kein Benutzername angegeben. + +/pubkey.bml.info.desc=Du weißt nicht, was ein Public Key ist? Erfahre mehr über PGP und GPG. + +/pubkey.bml.info.head=Informationen + +/pubkey.bml.info.upload=Du möchtest deinen Key hochladen? Dann klicke hier. + +/pubkey.bml.label=Public Key von [[user]]: + +/pubkey.bml.nokey=[[user]] hat noch keinen Public Key hochgeladen. + +/pubkey.bml.title=Public Key anschauen + +/register.bml.ask.body=Klicke den untenstehenden Button, damit eine Bestätigungs-Mail an [[email]] sendet. + +/register.bml.ask.button=Abschicken + +/register.bml.ask.header=E-Mail bestätigen + +/register.bml.asterisk.comment=(Achtung: mit * markierte Accounts sind noch nicht bestätigt worden) + +/register.bml.email.body<< +Dies ist die angeforderte Bestätigungs-E-Mail. +Die Bestätigung dieses Accounts wird beim Klicken des folgenden +URLs vervollständigt. + + [[conflink]] + +Unter Umständen muss der Link kopiert und per Hand in die Adresszeile +deines Browsers eingegeben werden. + +Viele Grüße, +[[sitename]] +[[siteroot]] +. + +/register.bml.email.subject=E-Mail bestätigen + +/register.bml.error.invalidcode=Ungültiger Bestätigungscode. + +/register.bml.error.useralreadyvalidated=Die Mailadresse für [[user]] wurde bereits bestätigt. + +/register.bml.error.usernotfound=Benutzer wurde nicht gefunden. + +/register.bml.new.body=Danke! Deine E-Mail-Adresse ist nun bestätigt worden. Von hier aus kannst du die folgenden Dinge tun: + +/register.bml.new.editinfo=Persönliche Informationen bearbeiten -- Fülle dein Benutzerprofil aus und kontrolliere verschiedene Einstellungen. + +/register.bml.new.header=Aktion erfolgreich + +/register.bml.new.login=Einloggen -- So musst du Benutzernamen und Passwort nicht überall eingeben. + +/register.bml.new.modify=Design ändern -- Verändere das Aussehen deines Journals. + +/register.bml.new.update=Eintrag schreiben -- Schreibe Einträge in dein Journal. + +/register.bml.sent.body=Eine Bestätiguns-E-Mai ist an [[email]] gesendet worden. Um die Bestätigung zu vervollständigen, musst du auf den Link in der E-Mail klicken. + +/register.bml.sent.header=Aktion erfolgreich + +/register.bml.title=E-Mail-Adresse bestätigen + +/register.bml.trans.body=Deine neue E-Mail-Adresse ist nun bestätigt worden. + +/register.bml.trans.header=Aktion erfolgreich + +/rename/index.bml.does=Das Umbenennen eines Accounts verändert lediglich den Benutzernamen. Alles andere - der Status des Accounts (bezahlt, kostenlos oder permanent), Benutzerprivilegien, das Benutzerprofil, die Freunde und weitere mit dem Account verbundene Informationen - bleiben gleich und werden weiterhin mit dem neuen Benutzernamen verbunden. Sämtliche existierenden Kommentare in anderen Journalen oder Communities werden nach der Umbenennung den neuen Benutzernamen anzeigen. + +/rename/index.bml.faqurl=Diese FAQ bietet weitere Informationen über das Umbenennen eines Accounts. + +/rename/index.bml.fee=Zum Umbenennen eines LiveJournal-Accounts wird eine Gebühr von [[fee]] berechnet. + +/rename/index.bml.heading.cost=Kosten + +/rename/index.bml.heading.how=Coupon kaufen + +/rename/index.bml.option=Der alte Benutzername kann entweder zu dem neuen weiterleiten oder als gelöscht markiert werden. Du kannst auswählen, ob der neue Benutzername von allen Freundeslisten gelöscht wird oder ob auf den Listen der Leute, die den alten Benutzernamen auf ihrer Freundesliste haben, nun der neue Name angezeigt wird. + +/rename/index.bml.options.buy=Coupon kaufen + +/rename/index.bml.options.buy.desc=Einen Umbenennungs-Coupon kaufen. + +/rename/index.bml.options.use=Coupon verwenden + +/rename/index.bml.options.use.desc=Einen Umbenennungs-Coupon verwenden. + +/rename/index.bml.redeem=Zuerst muss ein Umbenennungs-Coupon gekauft werden, der dann per E-Mail verschickt wird. Dieser Coupon wird zum Umbenennen des Accounts verwendet. Solche Umbenennungs-Coupons können nicht zurückgegeben werden, sind aber übertragbar. Es ist also möglich, einen Coupon für einen anderen Benutzer zu kaufen. + +/rename/index.bml.reserve=Der neue Accountname muss vorm Umbenennen nicht erst erstellt werden. Falls jedoch Sorge besteht, dass jemand anders diesen Benutzernamen in Anspruch nehmen könnte, bevor du deinen Umbenennungs-Coupon kaufen und verwenden kannst, dann solltest du einen Account mit dem neuen Benutzernamen erstellen. Das Passwort und die Mailadresse sollten dieselben sein wie bei dem aktuellen (alten) Account. + +/rename/index.bml.title=Account-Umbenennung + +/rename/index.bml.whatrename=Es können nur persönliche Accounts umbenannt werden, keine Communities + +/rename/use.bml.changes=Die folgenden Änderungen werden vollzogen, sobald die Umbenennung vollendet ist: + +/rename/use.bml.changes.move="[[newuser]]" wird zu "[[exname]]" bewegt + +/rename/use.bml.changes.rename="[[oldname]]" wird zu "[[newuser]]" umbenannt + +/rename/use.bml.confirm=Nachdem einmal auf 'Umbenennen' geklickt worden ist, ist dieser Prozess nicht mehr rückgängig zu machen. Um den Vorgang zu bestätigen, muss das Wort "[[confirmword]]" in das Textfeld unten eingegeben werden. + +/rename/use.bml.confirm.click=Klicke nun 'Umbenennen': + +/rename/use.bml.error.allocating=Fehler beim Zuordnen des Zielaccounts. + +/rename/use.bml.error.badpass=Die Passwörter für den alten und neuen Benutzernamen stimmen nicht überein. + +/rename/use.bml.error.differentusername=Dies ist nicht der Benutzername, der beim Laden dieses Formulars eingeloggt war. + +/rename/use.bml.error.login=Erst musst du dich aber einloggen. + +/rename/use.bml.error.readit=Lies den obenstehenden Absatz. + +/rename/use.bml.error.reserved=Fehler beim Umbenennen: Reservierter Account-Name. + +/rename/use.bml.error.same=Dies ist der gleiche Benutzername wie dein alter. + +/rename/use.bml.error.token=Ungültiger Umbenennungs-Coupon. + +/rename/use.bml.error.type=Nur normale Accounts dürfen umbenannt werden, keine Community accounts. + +/rename/use.bml.error.unknown=Unbekannter Fehler während des Umbenennens + +/rename/use.bml.error.usedtoken=Dieser Coupon wurde bereits verwendet. + +/rename/use.bml.error.username=Ungültiger Benutzername + +/rename/use.bml.error.usernametaken=Dieser Benutzername ist bereits in Verwendung + +/rename/use.bml.heading.changes=Veränderungen + +/rename/use.bml.heading.success=Aktion erfolgreich + +/rename/use.bml.heading.sure=Sicher? + +/rename/use.bml.intent=Auf dieser Seite kann ein Account umbenannt werden, nachdem die Anweisung gelesen und a [[aopts1]]>Umbenennungs-Coupon gekauft wurde. + +/rename/use.bml.label.desired=Gewünschter Benutzername: + +/rename/use.bml.label.proceed=Weiter... + +/rename/use.bml.label.rename=Umbenennen + +/rename/use.bml.label.token=Umbenennungs-Coupon: + +/rename/use.bml.label.username=Derzeitiger Benutzername: + +/rename/use.bml.options=Umbenennungs-Einstellungen: + +/rename/use.bml.options.delfriends=Alle Benutzer von der Freundesliste entfernen und alle Communities verlassen. + +/rename/use.bml.options.forward=Automatisch von [[oldname]] zum neuen Benutzernamen weiterleiten. + +/rename/use.bml.options.keepfriends=Alle Benutzer und Communities auf Freundesliste lassen. + +/rename/use.bml.options.keepself=Alle auf der Freundesliste behalten. + +/rename/use.bml.options.removeself=Alten Benutzernamen von allen Freundeslisten entfernen. + +/rename/use.bml.options.unlink=Die Verbindung zwischen [[oldname]] und dem neuen Journal nicht aufrecht erhalten. + +/rename/use.bml.success.login=Ein erneutes Einloggen ist nun nötig. + +/rename/use.bml.success.moved="[[newuser]]" wurde zu "[[bewegt]]" + +/rename/use.bml.success.renamed="[[olduser]]" wurde zu "[[newuser]]" umbenannt + +/rename/use.bml.success.usernamerenamed=Benutzername wurde umbenannt + +/rename/use.bml.title=Umbenennungs-Coupon verwenden + +/site/contract.bml.promise=Wir werden fest dazu stehen: + +/site/contract.bml.promise.account=Den Status jeden Accounts zu achten + +/site/contract.bml.promise.account.about=Permanente Accounts werden für die Lebenszeit der Webseite ihren Status beibehalten. Bezahlte Accounts werden bis zu ihrem Ablauf als solche verbleiben, es sei denn, sie werden rechtzeitig erneuert. Früheinsteiger werden Zugriff zu den bezahlten Features haben, die in der Anfangszeit der Webseite frei verfügbar waren. (Account-Status ist gültig mit der Ausnahme der Kündigung des Accounts im Falle von Verletzung der Nutzungsbedingungen) + +/site/contract.bml.promise.ads=Werbefrei zu bleiben + +/site/contract.bml.promise.ads.about=Vielleicht, weil Werbung uns ein so großes Ärgernis ist oder vielleicht, weil man damit nicht allzuviel Geld verdient: Wir versprechen auf jeden Fall, niemals Werbeplatz auf unseren Seiten oder bei unserem Service anzubieten. + +/site/contract.bml.promise.community=Mit und für die Community zu arbeiten + +/site/contract.bml.promise.community.about=Wir versprechen, Euch so gut wie möglich über Änderungen auf dem Laufenden zu halten, ohne dabei aufdringlich zu werden. Wir versprechen, unser Geschäft basierend auf dem Feedback der LiveJournal-Community zu betreiben und die Interessen der LiveJournal-Community immer im Kopf zu behalten. + +/site/contract.bml.promise.opensource=Die Bewegung für freie Software zu unterstützen + +/site/contract.bml.promise.opensource.about=Der gesamte Code, der benötigt wird, um eine vollständige, hoch-individualisierbare LiveJournal-Installation zu betreiben, ist der Öffentlichkeit verfügbar. Wir versprechen, diesen Quellcode frei und offen zu lassen, so dass wir der Gemeinschaft für freie Software etwas zurückgeben können. + +/site/contract.bml.promise.spam=Euch niemals unaufgeforderte E-Mails zu schicken + +/site/contract.bml.promise.spam.about=Wir glauben fest, dass Spam im Internet keinen Platz hat. Daher versprechen wir, Euch niemals ohne Eure implizite oder ausdrückliche Zusage E-Mails zu schicken. Wir versprechen, niemals Listen mit E-Mail-Adressen oder persönlichen Angaben von Benutzern zu verkaufen und wir versprechen, niemals Spam für eine dritte Partei zu verbreiten. + +/site/contract.bml.promise.uptime=Innerhalb der technischen Möglichkeiten verlässlichen Zugriff auf die Website zu bieten + +/site/contract.bml.promise.uptime.about=Wir versuchen, die Site für jeden reibungslos verfügbar zu machen, besonders da wir das System genau so verwenden, wie alle anderen. Leider treten Serverprobleme manchmal auf, doch wir versuchen, so gut wie möglich vorauszuplanen, um sie zu vermeiden. + +/site/contract.bml.promisetoyou=Wir bei LiveJournal versuchen, unsere Dienstleistung so angenehm wie möglich für jeden Benutzer zu gestalten. So haben wir eine Liste von Versprechen zusammengestellt, die wir halten werden. + +/site/contract.bml.promisetoyou.header=Unser Versprechen an Euch + +/site/contract.bml.title=Absichtserklärung + +/site/goat.bml.image.alt=Frank, das LiveJournal-Maskottchen. + +/site/goat.bml.image.caption=Bääääh," sagt Frank. + +/site/goat.bml.meet.body<< +Das ist Frank. Frank ist das Maskottchen von LiveJournal. Er steht uns beim Programmieren +zur Seite und beantwortet auch einmal die eine oder andere Support-Anfrage. Frank ist ziemlich vielseitig - manchmal erledigt er sogar die Gartenarbeit. Wenn der Rasen zu lang wird, sagen wir einfach "Hey Frank! Mittagszeit, der Rasen ist fertig!" Das hat Vorteile für alle Beteiligten. +. + +/site/goat.bml.meet.header=Triff Frank + +/site/goat.bml.title=Frank, die Ziege + +/styles/create.bml.choosebase=Basisstil auswählen, mit dem du anfangen und den du bearbeiten kannst: + +/styles/create.bml.createstyle.head=Stil erstellen + +/styles/create.bml.createstyle.text=Hier kannst du einen neuen persönlichen Stil erstellen, was sehr nützlich ist, wenn du dein Journal in deine Website einbetten möchtest oder du einen öffentlichen Stil erstellen möchtest, den jeder verwenden kannst. Der Stil muss zuerst hier bearbeitet werden, bevor er in den Stilanpassungen genauer eingestellt werden kann. Bitte beachte, dass nur Benutzer mit bezahlten Accounts ihre eigenen Stile erstellen können. + +/styles/create.bml.enterstyleid=Oder gib eine andere öffentliche ID-Nummer eines Stils ein: + +/styles/create.bml.noneorother=(Keine, oder andere:) + +/styles/create.bml.selecttype.head=Stil-Typ auswählen + +/styles/create.bml.selecttype.text=Ein Stil beeinflusst nur jeweils eine der Ansichten. Wenn ein gesamtes Stilset für dein Journal erstellt werden soll, muss für jede einzelne Ansicht ein Stil erstellt werden. + +/styles/create.bml.submit=Stil erstellen + +/styles/create.bml.title=Stil erstellen + +/styles/create_do.bml.editstyle=Stil bearbeiten + +/styles/create_do.bml.error.accounttype=Dein Account-Typ erlaubt es nicht, Stile zu erstellen. + +/styles/create_do.bml.error.invalidview=Kein gültiger Stil-Typ wurde ausgewählt. + +/styles/create_do.bml.error.styleexists=Ein Stil dieses Typs mit dem Namen [[des]] existiert bereits. Wenn wirklich ein neuer Stil des Typs [[view]] erstellt werden soll, dann muss zuerst der Name des alten [[view]]-Stils verändert werden, indem er dementsprechend bearbeitet wird. Komme danach auf diese Seite zurück und erstelle einen neuen Stil dieses Typs. + +/styles/create_do.bml.error.stylenotfound=Der Stil, der basierend auf ([[baseid]]) erstellt werden soll, scheint nicht zu existieren. + +/styles/create_do.bml.error.stylenotpublic=Der Stil, der basierend auf ([[baseid]]) erstellt werden soll, ist nicht öffentlich und kann somit nicht kopiert werden. + +/styles/create_do.bml.success.head=Aktion erfolgreich + +/styles/create_do.bml.success.text=Der Stil wurde erstellt und hat vorerst den Namen [[des]] erhalten. Durch Klicken des unten stehenden Buttons kann er bearbeitet werden. + +/styles/create_do.bml.title=Stil erstellen + +/styles/index.bml.about<< +

    In diesem Bereich der Webseite kannst du benutzerdefinierte S1-Stile erstellen, bearbeiten +und löschen. So kannst du zu einem Großteil das Aussehen deines Accounts kontrollieren und entscheiden, ob du +es nun wie deine Webseite aussehen lassen möchtest oder einfach nur einen persönlichen Stil entwickeln möchtest.

    + +

    Du kannst auch eingebettete Stile erstellen, die nicht die volle Seite enthalten, +sondern nur die eigentlichen Journaleinträge, und kannst dann dein Journal in eine andere Seite +einbetten.

    + +

    Mehr über das S1-Stilsystem kannst du in der +Stil-Dokumentation im +Entwicklerbereich erfahren.

    + +

    Bitte beachte, dass nur bezahlte Accounts benutzerdefinierte Stile erstellen und verwenden +dürfen. Für Inhaber kostenloser Accounts steht eine Auswahl vordefinierter Stile zur Verfügung, +die du auf der Seite "Design verändern" auswählen kannst. +. + +/styles/index.bml.about.header=Benutzerdefinierte Stile erstellen und benutzen + +/styles/index.bml.nav.browse=Stil-Browser + +/styles/index.bml.nav.browse.about=Mit dem Stil-Browser kannst du öffentliche Stile, die von anderen Benutzern erstellt worden sind, anschauen. + +/styles/index.bml.nav.create=Neuen Stil erstellen + +/styles/index.bml.nav.create.about=Erstelle einen neuen Stil von Grundauf, oder erstelle deinen Stil basierend auf einem existierenden öffentlichen Stil. + +/styles/index.bml.nav.edit=Existierenden Stil bearbeiten oder löschen + +/styles/index.bml.nav.edit.about<< +Du kannst nur die Stile bearbeiten, die “Eigentum” von deinem Account sind. +Um einen Systemstil zu bearbeiten, musst du zuerst einen neuen Stil erstellen, der auf +diesem Systemstil basiert. +. + +/styles/index.bml.nav.modify=Passe deinen Account an + +/styles/index.bml.nav.modify.about=Verändere den Standard-Stil deines Accounts zu einem der angebotenen Stile + +/styles/index.bml.title=Eigene Stile + +/suggestions/index.bml.howto.text<< +

    +
    Schaue dir frühere Vorschläge an
    +Lies dir zuerst vorangegangene Vorschläge durch, um sicher zu gehen, dass eine ähnliche Idee nicht schon vorgeschlagen worden ist. Falls dies der Fall ist, dann kannst du dir die Kommentare zu dem entsprechenden Eintrag durchlesen. Manchmal sieht es so aus, als wäre ein Vorschlag ignoriert worden; er könnte jedoch gleichzeitig schon in Vorbereitung sein. Manchmal werden Ideen aus verschiedenen Gründen abgelehnt oder verzögert. +
    +
    Hast du deine Idee nicht gefunden? Teile sie mit uns!
    +Die Vorlage muss für alle Vorschläge verwendet werden. Stelle sicher, dass du alle Teilbereiche der Vorlage ausgefüllt hast und dass dein Vorschlag korrekt und vollständig ist, bevor du ihn abschickst. Außerdem fügt die Vorlage nicht automatisch Leerzeilen ein; du kannst das HTML-Tag <br> verwenden, um Leerzeilen einzufügen. Dadurch kann dein Vorschlag leichter gelesen werden. Bedenke bitte auch, dass der Vorschlag in englischer Sprache formuliert sein sollte. +
    +
    Schicke den Vorschlag ab!
    +Du kannst die Community hier deiner Freundesliste hinzufügen. Wurde ein Vorschlag erst einmal abgeschickt, kann er diskutiert werden. Falls wir finden, dass der Vorschlag gut ist, wird er auf die Liste der wichtigen Projekte für die Programmierer gesetzt und bearbeitet, sobald es die Zeit erlaubt. Nicht alle Vorschläge können sofort umgesetzt werden, also sei bitte geduldig. +
    +. + +/suggestions/index.bml.howto.title=Wie mache ich einen Vorschlag? + +/suggestions/index.bml.info.text|staleness=1 +/suggestions/index.bml.info.text<< +Denkst du, dass du zu der Umsetzung deines Vorschlages beitragen kannst? Du kannst gerne den unten angegebenen Communities beitreten oder sie "beobachten": +
    +
    LiveJournals Entwicklerforum -- Gespräche über technische Angelegenheiten
    +
    +
    LiveJournals Businessforum -- Gespräche über allgemeine geschäftliche Angelegenheiten und ähnliches
    +
    +
    Das Forum für LiveJournals Benutzerdokumentation -- Gespräche über und Überarbeitung von den meisten Formen der Dokumentation für Benutzer
    +
    +
    LiveJournals Kunstforum -- Gespräche über und gemeinsame Nutzung von Benutzerbildern, Stimmungsschemen, Farbschemen und andere Grafiken.
    +
    +
    +Bitte beachte, dass die Leute, die LiveJournal mit verändern und verbessern, ebenso Benutzer sind wie du selber. Diese Veränderungen können Zeit brauchen; je mehr du bei der Umsetzung helfen kannst, desto mehr kann auch erreicht werden. +. + +/suggestions/index.bml.info.title=Andere Informationen + +/suggestions/index.bml.rules|staleness=1 +/suggestions/index.bml.rules<< +Es gibt noch andere Dinge, die du beachten solltest: +
      +
    • Viele Ideen sind schon vorgeschlagen und besprochen worden, sind jedoch noch nicht umgesetzt worden. Stelle sicher, dass du nicht eine Idee zum zweiten Mal vorschlägst. +
    • "Flaming" wird nicht toleriert werden. Jeder hat verschiedene Ideen darüber, wie LiveJournal funktionieren sollte. Bitte bedenke, dass du deine Meinung gerne vertreten kannst, aber du solltest nicht andere wegen ihrer Meinung belästigen. +
    • Stelle deine Idee so detailliert wie möglich vor. Eine Idee mit detaillierten Ideen zur Umsetzung wird wahrscheinlich eher akzeptiert als eine weniger detaillierte. Du musst dafür nicht wissen, wie man programmiert; denke einfach darüber nach, was deine Idee alles beeinflussen könnte und erwähne alle Probleme, die du vielleicht damit assoziierst. +
    • Lies auf jeden Fall zuerst die FAQs um dort zu sehen, ob deine Idee schon existiert oder ob ein bereits existierender Teil der Site dazu verwendet werden kann, deine Idee besser umzusetzen.. +
    • Möchtest du wissen, wie LiveJournal funktioniert, bist du dir nicht sicher, ob es etwas Bestimmtes gibt oder hast du ein Problem, dann mache keinen Vorschlag, sondern stelle statt dessen eine Anfrage im Support-Bereich. +
    +. + +/suggestions/index.bml.title=Vorschläge + +/suggestions/index.bml.welcome.text=Die Vorschläge von Benutzern sind ein wichtiger Teil von LiveJournal. Ist dir etwas eingefallen, was vielleicht eine interessante Idee wäre, dann folge bitte den nachstehenden Anweisungen, um diese Idee den Leuten vorzuschlagen, die die Website betreiben. + +/suggestions/index.bml.welcome.title=Willkommen! + +/support/append_request.bml.back.requests=Zurück zur Liste der offenen Anfragen. + +/support/append_request.bml.back.support=Zurück zum Support-Bereich. + +/support/append_request.bml.bounce.noemail=Es wurde keine E-Mail-Adresse zum Weiterleiten angegeben. + +/support/append_request.bml.bounce.notauth=Du bist nicht berechtigt, diese Anfrage weiterzuleiten. + +/support/append_request.bml.bounce.toomany=Du darfst nur bis zu fünf E-Mail-Adressen angeben. Du hast mehr als fünf angegeben. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Diese Support-Anfrage ist in der Zwischenzeit geschlossen worden. + +/support/append_request.bml.closed.title=Geschlossen + +/support/append_request.bml.internal.approve=Um eine Antwort zu genehmigen, musst du "Internal Comment / Action" wählen und eventuell noch erklären, wieso du diese Antwort genehmigst. + +/support/append_request.bml.internal.changecat=Um die Kategorie einer Anfrage zu verändern, musst du "Internal Comment / Action" wählen und eventuell erklären, wieso du die Kategorie änderst. + +/support/append_request.bml.internal.changesum=Um die Überschrift einer Anfrage zu verändern, musst du "Internal Comment / Action" wählen und die neue Überschrift eingeben. + +/support/append_request.bml.internal.touch=Um den Status einer Anfrage zu verändern, musst du "Internal Comment / Action" wählen und erklären, wieso du den Status veränderst. + +/support/append_request.bml.invalid.blank=Du hattest keinen Text angegeben. Bitte schreibe etwas in das Textfeld. + +/support/append_request.bml.invalid.noanswer=Ungültige verdeckte Antwort zum Genehmigen. + +/support/append_request.bml.invalid.nocat=Diese Kategorie scheint nicht zu existieren. + +/support/append_request.bml.invalid.noid=Für diesen Vorgang benötigst du eine Anfrage-ID. + +/support/append_request.bml.invalid.type=Ungültiger Antwort-Typ. + +/support/append_request.bml.logged.text=Dein/e Vorgang/Kommentar/Antwort wurde aufgenommen. Danke. + +/support/append_request.bml.logged.title=Aktion erfolgreich + +/support/append_request.bml.login.required=Du musst dich einloggen, bevor du Leuten helfen kannst. + +/support/append_request.bml.successlinks<< +
      +
    • Zurück zu Anfrage #[[number]]
    • +
    • Zurück zu den offenen Support-Anfragen
    • +
    • Zurück zu den offenen Support-Anfragen in der gleichen Kategorie
    • +
    • Gehe zur letzten / + nächsten offenen Anfrage
    • +
    • Gehe zur letzten / + nächsten offenen Support-Anfrage in der gleichen Kategorie
    • +. + +/support/append_request.bml.title=Kommentar/Anwort abschicken + +/support/append_request.bml.unknown.request=Unbekannte Support-Anfrage + +/support/encodings.bml.edit.header=Ich kann meiner Einträge nicht unter der Web-Benutzeroberfläche bearbeiten! + +/support/encodings.bml.edit.text<< +Kurze Antwort: (trifft zu, wenn du deine Einträge in Englisch oder Deutsch schreibt): Gehe auf die Seite "Persönliche Einstellungen. Im unteren Bereich der Seite ist eine Option namens Ältere Einträge automatisch konvertieren von. Wähle dort "Western European (Windows)" aus dem Dropdown-Menü und speichere deine Einstellungen. Jetzt kannst du deine Einträge bearbeiten. p?> + +Lange Antwort: Um einen Eintrag zu bearbeiten, der nicht im Unicode-Format ist, muss der LiveJournal-Code wissen, in welcher Codierung dieser Eintrag geschrieben wurde. Normalerweise ist diese Codierung "Western European (Windows)" für Sprecher von Englisch, Deutsch und anderen westeuropäischen Sprachen; wenn diese Einstellung jedoch die Anführungszeichen und ähnliche Zeichen nicht ordentlich darstellt, nimm "Western European (ISO)". Benutzer, die in anderen Sprachen schreiben, sollten eine entsprechende andere Einstellung wählen; befindet sich diese nicht in der Dropdown-Liste, kontaktiere Support und erkläre das Problem. p?> + + +. + +/support/encodings.bml.editcl.header=Ich kann meine Einträge nicht in dem Client-Programm bearbeiten! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Ich kann die Liste meiner Freunde nicht mit dem Client-Programm bearbeiten! + +/support/encodings.bml.groups.text="Freundesgruppen bearbeiten" deine Freundesgruppen auch umbenennen, sodass sie nur ASCII-Zeichen enthalten, dann kannst du auch dein Client-Programm für die Freundesgruppen verwenden. p?> + +/support/encodings.bml.overview.header=Worum geht es hier eigentlich? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Immer noch verwirrt? + +/support/encodings.bml.still.text=Support-Bereich stellen. p?> + +/support/encodings.bml.title=Codierungen + +/support/faqbrowse.bml.backfaq=Zurück zu den FAQ. + +/support/faqbrowse.bml.backfaqcat=Zurück zu der übergeordneten FAQ-Kategorie. + +/support/faqbrowse.bml.backsupport=Zurück zu den Support-Seiten. + +/support/faqbrowse.bml.edit.faq=Diese FAQ bearbeiten + +/support/faqbrowse.bml.error.nofaq=Die angegebene FAQ-Frage gibt es nicht. + +/support/faqbrowse.bml.lastupdated=Zuletzt aktualisiert: + +/support/faqbrowse.bml.title_num=FAQ-Frage #[[num]] + +/support/help.bml.interim|staleness=1 +/support/help.bml.interim<< + + + + +Getting +Started +in den Erinnerungen von "Helpscreening" sind ein sehr guter Ort für neue +Freiwillige, um Informationen zu finden. p?> + + + +
      • Verhalte dich professionell und höflich.
      • +
      • Kontaktiere keine Benutzer, die Support-Anfragen öffnen, +außerhalb des Support-Bereiches, um ihre Anfrage zu besprechen +oder ihnen etwas mitzuteilen.
      • +
      • Behandele Informationen aus Support-Anfragen vertraulich.
      • +
      • Kopiere nicht die Antworten anderer Leute.
      + + + + fragst. +Warte aber bitte, bis bei der entsprechenden Anfrage eine aufgedeckte Antwort +vorhanden ist. p?> + + + + + +hier im Support-Bereich gefunden werden. p?> +. + +/support/see_overrides.bml.error.noprivs=Nur Benutzer mit dem Privileg supportviewscreened oder supporthelp können die Stilanpassungen eines anderen Benutzers sehen. + +/support/see_overrides.bml.error.nos1=Dieser User benutzt nicht S1. + +/support/see_overrides.bml.header=Stilanpassungen für : + +/support/see_overrides.bml.nooverrides=Keine Stilanpassungen für gefunden. + +/support/see_overrides.bml.title=Stilanpassungen + +/syn/index.bml.add=Quelle hinzufügen + +/syn/index.bml.add.byurl.text=Abonniere eine Artikelquelle, indem du den URL der RSS-Quelle hier eingibst. + +/syn/index.bml.add.byurl.title=Artikelquelle per URL abonnieren + +/syn/index.bml.add.pop.text=Im folgenden sind beliebte Artikelquellen aufgeführt, die du im Moment nicht abonniert hast + +/syn/index.bml.add.pop.title=Verbreitete Quelle hinzufügen + +/syn/index.bml.add.selected=Ausgewählte Quelle(n) hinzufügen + +/syn/index.bml.back=Zurück + +/syn/index.bml.create=Artikelquelle erstellen + +/syn/index.bml.create.name=Der eingegebene URL existiert momenten auf dieser Site nicht als Artikelquelle. Bitte gib einen Account-Namen ein, damit eine Artikelquelle erstellt werden kann. + +/syn/index.bml.error.nocreate=Der eingegebene URL existiert momenten auf dieser Site nicht als Artikelquelle. Mit deinem Account-Typ können keine neuen Artikelquellen erstellt werden. + +/syn/index.bml.error.unknown=Unbekannter Fehler + +/syn/index.bml.feed.url=URL der Quelle + +/syn/index.bml.invalid.accountname=Ungültiger Account-Name + +/syn/index.bml.invalid.cantadd=Du kannst von dieser Webseite keine Artikelquellen abonnieren. + +/syn/index.bml.invalid.http.text=Beim Abrufen dieses URLs ist ein Fehler aufgetreten. Möglicherweise sind der Server oder der Inhalt zur Zeit nicht verfügbar. Bitte überprüfe den eingegebenen URL und versuche es erneut. + +/syn/index.bml.invalid.http.title=Fehler beim Abrufen des Inhalts + +/syn/index.bml.invalid.inuse.text=Dieser Account-Name wird bereits verwendet. + +/syn/index.bml.invalid.inuse.title=Benutzername in Verwendung + +/syn/index.bml.invalid.needname.text=Um eine Artikelquelle zu abonnieren, die noch nicht existiert, gehe bitte zurück und gib ihr einen Account-Namen. + +/syn/index.bml.invalid.needname.title=Account-Name benötigt + +/syn/index.bml.invalid.needurl=Du musst entweder den Benutzernamen einer Artikelquelle oder einen URL eingeben, um eine neue Quelle zu erstellen. + +/syn/index.bml.invalid.notexist=Es gibt keine Artikelquelle mit diesem Benutzernamen. + +/syn/index.bml.invalid.notrss.text=Der eingegebene URL scheint keine Daten im XML-Format zu enthalten. + +/syn/index.bml.invalid.notrss.title=Die Daten sind nicht im XML-Format + +/syn/index.bml.invalid.port=Nur Nummern von Standard-Ports sind erlaubt. + +/syn/index.bml.invalid.reserved=Dieser Account-Name ist reserviert. Bitte wähle einen anderen Account-Namen aus. + +/syn/index.bml.invalid.submission=Formular falsch ausgefüllt + +/syn/index.bml.invalid.url=Der von dir eingegebene URL ist ungültig. Bitte stelle sicher, dass du den URL richtig eingegeben hast und versuche es erneut. + +/syn/index.bml.loginrequired.text=Um die von dir abonnierten Artikelquellen zu verwalten, musst du dich erst einloggen. + +/syn/index.bml.loginrequired.title=Bitte einloggen + +/syn/index.bml.promo.text=Wenn du gerne eine Liste von Artikelquellen sehen möchtest, die Benutzer von bereits abonniert haben, dann kannst du in nachschauen, wo Benutzer Artikelquellen ankündigen, die sie erstellen und abonnieren. + +/syn/index.bml.remove=Ausgewählte entfernen + +/syn/index.bml.table.feed=Quelle + +/syn/index.bml.table.watchers=Abonnenten + +/syn/index.bml.title=Externe Artikelquellen + +/syn/index.bml.user.nomatch=Benutzer stimmt nicht mit dem Benutzer überein, der das Formular ausgefüllt hat. + +/syn/index.bml.using.text=Hier kannst du externe Artikelquellen (RSS-Quellen) von anderen Seiten abonnieren, so dass du nicht jeden Tag mehrere Webseiten auf Aktualität überprüfen musst. + +/syn/index.bml.using.title=Über [[sitename]] Artikelquellen abonnieren + +/syn/list.bml.error.nofeeds=Fehler: In den letzten 24 Stunden wurden keine Artikelquellen auf den neuesten Stand gebracht. + +/syn/list.bml.feeddesc=Beschreibung der Artikelquelle + +/syn/list.bml.feedurl=URL der Artikelquelle + +/syn/list.bml.numreaders=Anzahl der Leser + +/syn/list.bml.title=Externe Artikelquellen + +/syn/list.bml.username=Benutzername + +/syn/list.bml.xml_icon.alt=[Unbearbeitete Artikelquelle anschauen] + +/talkmulti.bml.deleted.body=Die Kommentare wurden gelöscht. Du kannst dir die restlichen Kommentare hier anschauen. + +/talkmulti.bml.deleted.title=Kommentare gelöscht + +/talkmulti.bml.error.comms_deleted=Einer der Kommentare ist gelöscht worden, nachdem du ihn ausgewählt hast. Bitte gehe aus Sicherheitsgründen zurück und wiederhole deine Aktion. + +/talkmulti.bml.error.inconsistent_data=Die angegebenen Informationen sind nicht schlüssig. + +/talkmulti.bml.error.invalid=Ungültige Parameterangabe. + +/talkmulti.bml.error.invalid_mode=Du hast keine der Aktionen gewählt. Bitte gehe zurück und wähle aus, ob du die Kommentare verdecken, aufdecken oder löschen möchtest. + +/talkmulti.bml.error.login=Du bist nicht eingeloggt. + +/talkmulti.bml.error.none_selected=Du hast keine Kommentare ausgewählt. + +/talkmulti.bml.error.privs.delete=Du hast keine Berechtigung, diese Kommentare zu löschen. + +/talkmulti.bml.error.privs.screen=Du hast keine Berechtigung, diese Kommentare zu verdecken. + +/talkmulti.bml.error.privs.unscreen=Du hast keine Berechtigung, diese Kommentare aufzudecken. + +/talkmulti.bml.screened.body=Die Kommentare wurden verdeckt. Du kannst sie dir hier anschauen. + +/talkmulti.bml.screened.title=Kommentare verdeckt + +/talkmulti.bml.title.delete=Mehrere Kommentare löschen + +/talkmulti.bml.title.screen=Mehrere Kommentare verdecken + +/talkmulti.bml.title.unscreen=Mehrere Kommentare aufdecken + +/talkmulti.bml.unscreened.body=Die Kommentare wurden aufgedeckt. Du kannst sie dir hier anschauen. + +/talkmulti.bml.unscreened.title=Kommentare aufgedeckt + +/talkpost.bml.allowedhtml=Erlaubte HTML-Tags + +/talkpost.bml.error.cannotreplynopost=Du kannst nicht auf einen nicht vorhandenen Eintrag antworten + +/talkpost.bml.error.nocommentsjournal=Der Benutzer lässt keine Kommentare in seinem Journal zu. + +/talkpost.bml.error.nocommentspost=Der Benutzer lässt keine Kommentare für diesen Eintrag zu. + +/talkpost.bml.error.noreplypost=Der Eintrag wurde nicht gefunden und möglicherweise gelöscht. + +/talkpost.bml.error.noreply_deleted=Dieser Kommentar wurde gelöscht. Du kannst darauf nicht antworten. + +/talkpost.bml.error.noreply_screened=Dieser Kommentar ist verdeckt und es ist dir nicht gestattet, ihn zu sehen oder darauf zu antworten. + +/talkpost.bml.label.picturetouse=Benutzerbild auswählen: + +/talkpost.bml.loganonip=Achtung! Dieser Benutzer hat die Option aktiviert, welche IP-Adressen anonymer Personen aufzeichnet. + +/talkpost.bml.loginq=Einloggen? + +/talkpost.bml.logyourip=Achtung! Dieser Benutzer hat die Option aktiviert, die deine IP-Adresse aufzeichnet. + +/talkpost.bml.nosubjecthtml=HTML ist in der Betreffzeile nicht erlaubt. + +/talkpost.bml.opt.anonymous=Anonym + +/talkpost.bml.opt.defpic=(Standard) + +/talkpost.bml.opt.friendsonly=- Dieser Benutzer lässt keine anonymen Kommentare zu. Du kannst hier nur einen Kommentar hinterlassen, wenn du auf der Freundesliste von [[username]] stehst. + +/talkpost.bml.opt.from=Von: + +/talkpost.bml.opt.ljuser=LiveJournal-Benutzer: + +/talkpost.bml.opt.loggedin=Eingeloggter Benutzer: [[username]] + +/talkpost.bml.opt.message=Nachricht: + +/talkpost.bml.opt.noanonpost=- Dieser Benutzer lässt keine anonymen Kommentare zu. + +/talkpost.bml.opt.noautoformat=Keine automatische Formatierung: + +/talkpost.bml.opt.noimage=Ohne Bild + +/talkpost.bml.opt.preview=Vorschau + +/talkpost.bml.opt.spellcheck=Vorherige Rechtschreibprüfung (nur U.S.-Englisch) + +/talkpost.bml.opt.subject=Betreff: + +/talkpost.bml.opt.submit=Kommentar abschicken + +/talkpost.bml.opt.willscreen=(wird verdeckt werden) + +/talkpost.bml.opt.willscreenfriend=(wird verdeckt werden falls nicht auf Freundesliste) + +/talkpost.bml.paraformat=Absätze werden automatisch formatiert. + +/talkpost.bml.postresponse=Hierauf antworten: + +/talkpost.bml.title=Kommentar hinterlassen + +/talkpost.bml.usermismatch<< +Du hast einen Benutzernamen eingegeben, aber die Option "LiveJournal-Benutzer" nicht gewählt. + +Lösche entweder den Benutzernamen aus dem Textfeld oder ändere die getroffene Auswahl und versuche es erneut. +. + +/talkpost.bml.warnscreened=Beachte: Dieser Kommentar ist verdeckt. Wenn du darauf antwortest, wird er automatisch aufgedeckt und sichtbar. + +/talkpost_do.bml.error.badpassword=Das Passwort für den angegebenen Benutzernamen ist falsch. Du kannst dein Passwort hier abrufen, solltest du es vergessen haben + +/talkpost_do.bml.error.badusername=Der angegebene Benutzername existiert nicht. Du kannst deinen Benutzernamen hier herausfinden solltest du ihn vergessen haben, oder du kannst einen anonymen Kommentar hinterlassen. + +/talkpost_do.bml.error.banned=Dir fehlt die Berechtigung zum Hinterlassen von Kommentaren in dem Journal dieses Benutzers. + +/talkpost_do.bml.error.blankmessage=Dein Kommentar enthielt keinen Text. Bitte schreibe zumindest etwas in die Titelzeile. + +/talkpost_do.bml.error.confused_identity=Du hast einen Benutzernamen eingegeben, jedoch die Option gewählt, einen Kommentar anonym oder als momentan eingeloggter Benutzer zu hinterlassen. Bitte gehe zurück und entscheide dich, was du wirklich tun möchtest. + +/talkpost_do.bml.error.deleted=Dein Journal wurde gelöscht. Du kannst keine Kommentare hinterlassen. + +/talkpost_do.bml.error.friendsonly=Nur Freunde von [[user]] dürfen in diesem Journal Kommentare hinterlassen. + +/talkpost_do.bml.error.lostcookie=Dein Login-Cookie scheint verschwunden zu sein? + +/talkpost_do.bml.error.manybytes=Dein Kommentar von [[current]] überschreitet die maximale Byte-Länge von [[limit]]. Bitte gehe zurück, kürze deinen Kommentar, und versuche, ihn dann erneut abzuschicken. + +/talkpost_do.bml.error.manychars=Dein Kommentar von [[current]] Zeichen überschreitet die maximale Zeichen-Länge von [[limit]]. Bitte gehe zurück, kürze deinen Kommentar, und versuche, ihn dann erneut abzuschicken + +/talkpost_do.bml.error.mustlogin=Du musst eingeloggt sein oder einen Benutzernamen und ein Passwort eingeben, um auf diesen geschützten Eintrag antworten zu können. + +/talkpost_do.bml.error.noanon=Du kannst keine anonymen Kommentare in diesem Journal hinterlassen. + +/talkpost_do.bml.error.noauth=Du bist nicht authorisiert, auf diesen geschützten Eintrag zu kommentieren. + +/talkpost_do.bml.error.nocomments=Der Benutzer lässt keine Kommentare zu diesem Eintrag zu. + +/talkpost_do.bml.error.noparent=Du kannst nicht auf einen nicht vorhandenen Kommentar antworten. + +/talkpost_do.bml.error.notafriend=Leider führt dich Benutzer [[user]] nicht als Freund, und es dürfen nur seine Freunde in seinem Journal antworten. + +/talkpost_do.bml.error.nousername=Du hast nicht deinen LiveJournal-Benutzernamen eingegeben. Du kannst als "Anonym" antworten falls Du kein LiveJournal-Benutzer bist. + +/talkpost_do.bml.error.noverify=Leider darfst du keine Kommentare in anderen Journalen schreiben, bis deine E-Mail-Adresse bestätigt wurde. Falls du deine Bestätigungs-E-Mail verloren hast, kannst du eine neue anfordern. + +/talkpost_do.bml.error.postshared=Du darfst nicht als Account einer Community oder eines geteilten Journals antworten. Geteilte Accounts repräsentieren Gruppen, keine Individuen. + +/talkpost_do.bml.error.screened=Dir fehlt die Berechtigung, auf diesen verdeckten Kommentar zu antworten. + +/talkpost_do.bml.error.suspended=Dein Journal ist suspendiert worden. Du kannst keine Nachrichten schreiben. + +/talkpost_do.bml.error.testacct=Test-Accounts können nur in Testjournalen verwendet werden. + +/talkpost_do.bml.opt.preview=Vorschau + +/talkpost_do.bml.preview=Hier siehst du, wie dein Eintrag aussehen wird. Mit den Eingabefeldern unten kannst Du noch Änderungen daran vornehmen oder ihn einfach abschicken. + +/talkpost_do.bml.preview.subject=Betreff: + +/talkpost_do.bml.preview.submit=Abschicken + +/talkpost_do.bml.preview.title=Vorschau + +/talkpost_do.bml.success.loggedin=Du bist jetzt eingeloggt. + +/talkpost_do.bml.success.message=Dein Kommentar wurde hinzugefügt. Du kannst ihn hier lesen. + +/talkpost_do.bml.success.screened.comm=Dein Kommentar wurde gespeichert. Gemäß den Einstellungen dieser Community ist er vorläufig verdeckt und nur für dich und die Betreiber der Community sichtbar, bis diese ihn aufdecken. Du kannst deinen Kommentar hier lesen. + +/talkpost_do.bml.success.screened.comm.anon=Dein anonymer Kommentar wurde hinzugefügt. Gemäß den Community-Einstellungen ist er verdeckt worden, so dass nur die Verwalter der Community ihn sehen können, bis sie sich dazu entschließen, ihn aufzudecken. Du kannst hier zu den Kommentaren zurückkehren. + +/talkpost_do.bml.success.screened.user=Dein Kommentar wurde gespeichert. Gemäß den Einstellungen dieses Journals ist er vorläufig verdeckt und nur für dich und den Inhaber des Journals sichtbar, bis dieser ihn aufdeckt. Du kannst deinen Kommentar hier lesen. + +/talkpost_do.bml.success.screened.user.anon=Dein anonymer Kommentar wurde hinzugefügt. Gemäß den Einstellungen in diesem Journal ist er verdeckt worden, so dass nur der Besitzer dieses Journals ihn sehen kann, bis er sich dazu entschließt, ihn aufzudecken. Du kannst hier zu den Kommentaren zurückkehren. + +/talkpost_do.bml.success.title=Aktion erfolgreich + +/talkpost_do.bml.success.unscreened=Der Kommentar, auf den du geantwortet hast, wurde aufgedeckt und ist nun sichtbar. + +/talkpost_do.bml.title=Kommentar hinterlassen + +/talkpost_do.bml.title.error=Kommentar nicht abgeschickt + +/talkpost_do.bml.title.preview=Kommentar-Vorschau + +/talkread.bml.anonuser=(Anonym) + +/talkread.bml.confirm.action=Bist du dir sicher, dass du die ausgewählten Kommentare löschen möchtest? + +/talkread.bml.deletedpost=(gelöschter Kommentar) + +/talkread.bml.deleteduser=(Gelöschter Benutzer: [[username]]) + +/talkread.bml.fromip=(von [[ip]]) + +/talkread.bml.noreplies=Keine Antworten + +/talkread.bml.nosubject=(kein Betreff) + +/talkread.bml.replysuspended=(Antwort von suspendiertem Benutzer) + +/talkread.bml.screenedpost=(Verdeckter Kommentar) + +/talkread.bml.select=Auswählen + +/talkread.bml.subjectdeleted=[gelöscht] + +/talkread.bml.talkmulti.delete=Löschen + +/talkread.bml.talkmulti.des=Alle ausgewählten Kommentare: + +/talkread.bml.talkmulti.screen=Verdecken + +/talkread.bml.talkmulti.submit=Ausführen + +/talkread.bml.talkmulti.unscreen=Aufdecken + +/talkread.bml.title=Kommentare lesen + +/talkscreen.bml.error.login=Du musst eingeloggt sein, um mit verdeckten Kommentaren zu arbeiten. + +/talkscreen.bml.error.privs.screen=Es ist dir nicht gestattet, diesen Kommentar zu verdecken. + +/talkscreen.bml.error.privs.unscreen=Es ist dir nicht gestattet, diesen Kommentar aufzudecken. + +/talkscreen.bml.screen.doit=Ja, diesen Kommentar verdecken + +/talkscreen.bml.screen.sure.body=Bist du sicher, dass du diesen Kommentar verdecken möchtest? + +/talkscreen.bml.screen.sure.title=Diesen Kommentar verdecken? + +/talkscreen.bml.screened.body=Dieser Kommentar wurde verdeckt. Du kannst ihn betrachten. + +/talkscreen.bml.screened.title=Aktion erfolgreich + +/talkscreen.bml.title=Verdeckter Kommentar + +/talkscreen.bml.unscreen.doit=Ja, diesen Kommentar aufdecken + +/talkscreen.bml.unscreen.sure.body=Bist du sicher, dass du diesen Kommentar aufdecken möchtest? + +/talkscreen.bml.unscreen.sure.title=Diesen Kommentar aufdecken? + +/talkscreen.bml.unscreened.body=Dieser Kommentar wurde aufgedeckt. Du kannst ihn betrachten. + +/talkscreen.bml.unscreened.title=Aktion erfolgreich + +/tools/emailmanage.bml.address.current.title=Aktuelle Adresse + +/tools/emailmanage.bml.address.old.none=Keine + +/tools/emailmanage.bml.address.old.text=Im Folgenden ist eine Liste mit E-Mail-Adressen, die du in der Vergangenheit mit deinem Account verwendet hast und der Zeitpunkt, an dem sie als primäre E-Mail-Adresse deaktiviert wurden. Wähle die Adressen aus, die du gerne löschen möchtest. + +/tools/emailmanage.bml.address.old.title=Vorherige Adressen + +/tools/emailmanage.bml.delete_selected=Ausgewählte Adressen löschen + +/tools/emailmanage.bml.desc.notfirst=Die Seite lässt dich nur die E-Mail-Adressen entfernen, die verwendet wurden, nachdem du zum ersten Mal die Adresse verwendet hast, die momentan für deinen Account bestätigt ist. Das bedeutet, dass der Angreifer nicht deine Originaladresse entfernen kann. + +/tools/emailmanage.bml.desc.text|staleness=1 +/tools/emailmanage.bml.desc.text=Auf dieser Seite kannst du E-Mail-Adressen entfernen, die du in der Vergangenheit mit deinem Account verwendet hast. Wenn du sie entfernst, kannst du dir nicht länger dein Passwort zu diesen Adressen schicken lassen. Dies ist nützlich, wenn jemand dein Passwort herausgefunden hat und Kontrolle über dein Journal bekommen hat. Lasse dir einfach dein Passwort zu deiner alten Adresse schicken, verändere das Passwort und entferne die E-Mail-Adresse des Angreifers. + +/tools/emailmanage.bml.desc.title=Beschreibung + +/tools/emailmanage.bml.log.deleted=Gelöscht: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Änderungen gespeichert + +/tools/emailmanage.bml.notvalidated.text|staleness=1 +/tools/emailmanage.bml.notvalidated.text=Um dieses Tool zu verwenden, muss deine aktuelle E-Mail-Adresse [[email]] bestätigt sein. Wenn du die Bestätigungs-E-Mail dafür verloren hast, kannst du sie dir erneut zusenden lassen. Nachdem du diesen URL besucht hast, komme wieder hierher zurück. + +/tools/emailmanage.bml.notvalidated.title=E-Mail-Adresse ist nicht bestätigt + +/tools/emailmanage.bml.title=E-Mail-Verwaltung + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Deine Liste denkwürdiger Einträge wurde aktualisiert. + +/tools/memadd.bml.body.added.header=Aktion erfolgreich + +/tools/memadd.bml.description=Beschreibung: + +/tools/memadd.bml.description.text<< +Gib diesem Journaleintrag eine Beschreibung, durch die du ihn dir merken kannst. +Um diesen Eintrag von deiner Liste der denkwürdigen Einträge zu löschen, lösche den Inhalt dieses Feldes. +. + +/tools/memadd.bml.error.deleted.body=Der Journaleintrag, der vorher "[[desc]]" hieß, wurde von deiner Liste denkwürdiger Einträge gelöscht. + +/tools/memadd.bml.error.deleted.title=Erinnerung gelöscht + +/tools/memadd.bml.error.entry_deleted=Den Journaleintrag gibt es nicht mehr. Die "Erinnerung" wurde gelöscht. + +/tools/memadd.bml.error.fivekeywords=Nur 5 Schlüsselworte/Kategorien sind für einen denkwürdigen Eintrag erlaubt. + +/tools/memadd.bml.error.invalid_security=Ungültige oder fehlende Sicherheitsoption. + +/tools/memadd.bml.error.login=Um dieses Feature zu verwenden, musst du eingeloggt sein. Logge dich ein, dann wirst du hierher zurückgebracht. + +/tools/memadd.bml.error.maxsize=Dieses Schlüsselwort überschreitet die erlaubte Maximallänge: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Um deiner Liste denkwürdiger Einträge einen Journaleintrag hinzuzufügen, musst du eine Beschreibung angeben. + +Du kannst einen denkwürdigen Eintrag löschen, indem du ihn bearbeitest und die Beschreibung entfernst; allerdings war dieser Eintrag noch nicht in deinen denkwürdigen Erinnerungen eingetragen. +. + +/tools/memadd.bml.error.nodescription.title=Keine Beschreibung + +/tools/memadd.bml.form.reset=Löschen + +/tools/memadd.bml.form.submit=Absenden + +/tools/memadd.bml.keywords=Schlüsselwörter: + +/tools/memadd.bml.keywords.example=Beispiel: Witzig, Streberhaft, Romantisch + +/tools/memadd.bml.keywords.select=Du kannst auch Schlüsselwörter wählen, die du bereits verwendet hast: + +/tools/memadd.bml.keywords.text=Warum ist dieser Eintrag denkwürdig? Gib bis zu fünf Kategorien oder durch Komma getrennte Schlüsselwörter an, um ihn später wiederzufinden. + +/tools/memadd.bml.login.enterinfo=Gib den Benutzernamen und Passwort des Accounts ein, in dessen Erinnerungen du speichern möchtest. + +/tools/memadd.bml.login.forgot.header=Etwas vergessen? + +/tools/memadd.bml.login.forgot.recover=Falls du deinen Benutzernamen oder dein Passwort vergessen hast, klicke hier!. + +/tools/memadd.bml.multiple_selections=Um mehrere auszuwählen, halte 'Steuerung' gedrückt, um dann mehrere Schlüsselwörter auszuwählen. + +/tools/memadd.bml.security=Sicherheit: + +/tools/memadd.bml.security.friendsonly=Nur für Freunde + +/tools/memadd.bml.security.private=Privat + +/tools/memadd.bml.security.public=Öffentlich + +/tools/memadd.bml.title=Den Erinnerungen hinzufügen + +/tools/memadd.bml.title.added=Hinzugefügt + +/tools/memadd.bml.title.add_memory=Erinnerung hinzufügen + +/tools/memadd.bml.title.deleted=Gelöscht + +/tools/memadd.bml.title.edit_memory=Denkwürdigen Eintrag bearbeiten + +/tools/memadd.bml.whocansee<< +Wer darf sehen, dass du diesen Eintrag als denkwürdig definiert hast? +Jeder, deine LiveJournal-Freunde oder nur du? +. + +/tools/memadd.bml.whocansee.comm<< +Wer kann sehen, dass dieser Eintrag als Erinnerung gespeichert wurde? + Alle, nur Mitglieder der Community oder nur Maintainer der Community? +. + +/tools/memories.bml.back=Zurück + +/tools/memories.bml.body.keyword<< + + +[[user]] als erinnerungswürdig empfand. p?> +. + +/tools/memories.bml.body.list_categories<< + + +[[user]] erinnerungswürdige Journaleinträge eingetragen hat. p?> +. + +/tools/memories.bml.body.memorable=Im Folgenden eine Liste unkategorisierter Journaleinträge, die der Benutzer [[user]] als erinnerungswürdig empfand. + +/tools/memories.bml.delete=Ausgewählte Erinnerungen löschen + +/tools/memories.bml.delete.confirm=Möchtest du wirklich die ausgewählten erinnerungswürdigen Einträge löschen? + +/tools/memories.bml.delete.deleted.head=Aktion erfolgreich + +/tools/memories.bml.delete.deleted.text=Die ausgewählten erinnerungswürdigen Einträge wurden gelöscht. Hier kannst du zur Liste der erinnerungswürdigen Einträge zurückkehren. + +/tools/memories.bml.delete.deleted.title=Erinnerungen gelöscht + +/tools/memories.bml.delete.error.dberror=Beim Löschen der Erinnerungen ist der folgende Datenbankfehler aufgetreten: [[error]]. Bitte versuche es erneut. + +/tools/memories.bml.delete.error.noneselected=Keine Erinnerungen wurden zum Löschen ausgewählt. + +/tools/memories.bml.edit=bearbeiten + +/tools/memories.bml.error.noentries.body<< +Das könnte sein, weil
        +
      1. der Benutzer keine Erinnerungen definiert hat
      2. +
      3. die Erinnerungen des Benutzers geschützt sind und du keine Berechtigung hast, sie zu lesen oder
      4. +
      5. der Benutzer keine Erinnerungen definiert hat, die auf deine Suchkriterien passen.
      +. + +/tools/memories.bml.error.noentries.title=Keine Erinnerungen gefunden. + +/tools/memories.bml.filter.all=Alle Erinnerungen + +/tools/memories.bml.filter.other=Nur Einträge von anderen + +/tools/memories.bml.filter.own=Nur Einträge von "[[user]]" + +/tools/memories.bml.form.filter=Erinnerungen filtern: + +/tools/memories.bml.form.sort=Erinnerungen sortieren nach: + +/tools/memories.bml.form.switch=Wechseln + +/tools/memories.bml.login=Um dir deine Erinnerungen anzuschauen, logge dich bitte ein. + +/tools/memories.bml.plur_entry=[[num]] [[?num|Eintrag|Einträge]] + +/tools/memories.bml.sort.description=Beschreibung + +/tools/memories.bml.sort.orderadded=Datum des Hinzufügens + +/tools/memories.bml.title.keyword=Erinnerungswürdige Einträge zum Thema "[[keyword]]" + +/tools/memories.bml.title.memorable=Erinnerungswürdige Einträge + +/tools/memories.bml.uncategorized=Nicht kategorisiert + +/update.bml.altpost=Journal auswählen: + +/update.bml.btn.preview=Vorschau + +/update.bml.btn.update=Eintrag speichern + +/update.bml.currmood=Aktuelle Stimmung: + +/update.bml.currmusic=Aktuelle Musik: + +/update.bml.date=Datum: + +/update.bml.default=Standard + +/update.bml.defaultjournal=([[user]]) -- Standard + +/update.bml.error.cantpost=Sorry, du kannst zur Zeit keine Einträge schreiben. + +/update.bml.error.disabled=Deine Account-Art erlaubt nicht das Schreiben von Einträgen. + +/update.bml.error.disabled.title=Schreibzugriff deaktiviert + +/update.bml.error.login=Fehler beim Einloggen: + +/update.bml.error.nopass=Passwort eingeben + +/update.bml.error.update=Fehler beim Speichern: + +/update.bml.event=Ereignis: + +/update.bml.full=Vollständige Seite + +/update.bml.htmlokay.norich=(HTML erlaubt; Leerzeilen werden standardmäßig als <br> formattiert) + +/update.bml.htmlokay.rich=(HTML erlaubt; Leerzeilen werden standardmäßig als <br> formattiert - oder verwende das "Rich Text"-Format) + +/update.bml.htmlokay.rte_nosupport=(Dein aktueller Browser unterstützt leider nicht die Rich-Text-Oberfläche.) + +/update.bml.localtime=Ortszeit: + +/update.bml.loggedinas=Im Moment ist [[user]] eingeloggt.
      Um mit einem anderen Account einen Eintrag zu schreiben, klicke hier. + +/update.bml.loggingin=Einloggen beim Server... + +/update.bml.noneother=Keine, oder: + +/update.bml.note=Bitte beachte: Datum und Uhrzeit stammen von unserem Server. Bitte passe sie vor dem Abschicken deines Eintrages an deine Zeitzone an. + +/update.bml.opt.backdate=Eintrag zurückdatieren: + +/update.bml.opt.backdate.about=erscheint nicht in der Freunde-Ansicht + +/update.bml.opt.defpic=(Standard) + +/update.bml.opt.nocomments=Keine Kommentare: + +/update.bml.opt.noemail=Keine Kommentar-E-Mails: + +/update.bml.opt.noformat=Keine automatische Formatierung: + +/update.bml.opt.spellcheck=Vor dem Speichern Rechtschreibung prüfen (nur U.S.-Englisch) + +/update.bml.options=Optionale Einstellungen + +/update.bml.other=andere Stimmung: + +/update.bml.password=Passwort: + +/update.bml.picture=Benutzerbild auswählen: + +/update.bml.preview.header=Vorschau + +/update.bml.preview.text=So wird der Eintrag aussehen, sobald er abgeschickt worden ist. Mit dem Formular unten kann er weiter verändert werden, oder so abgeschickt werden. + +/update.bml.security.custom=Freundesgruppen... + +/update.bml.security.friends=Freunde + +/update.bml.security.head=Sichtbarkeit: + +/update.bml.security.private=Privat + +/update.bml.security.public=Öffentlich + +/update.bml.servermsg=Der Server hat eine Meldung für dich: + +/update.bml.simple=Dies ist die einfache Version. Weitere Optionen gibt es hier. + +/update.bml.spellchecked=Dein Eintrag nach der Rechtschreibprüfung: + +/update.bml.subject=Betreff: (optional) + +/update.bml.timeformat=24-Stunden-Zeitformat + +/update.bml.title=Neuer Eintrag + +/update.bml.title.readonly=Nur Lesezugriff + +/update.bml.update.alternate=Wenn für deinen Computer kein Client heruntergeladen werden soll oder wenn es keinen für deine Plattform gibt, dann kannst du auf dieser Seite einen neuen Eintrag für dein Journal schreiben. Dies ist auch dann nützlich, wenn du im Urlaub oder nicht an deinem eigenen Computer bist. Mit einem bezahlten Account kannst du einen Eintrag per E-Mail schreiben, einen Telefoneintrag machen, wenn du gar nicht in der Nähe eines Computers bist, oder Umfragen erstellen. + +/update.bml.update.head=Neuen Journaleintrag schreiben... + +/update.bml.update.success=Dein neuer Eintrag wurde gespeichert. Du kannst dir dein aktualisiertes Journal hier ansehen. + +/update.bml.updating=Neuer Journaleintrag wird gespeichert... + +/update.bml.username=Benutzername: + +/uploadpic.bml.error.unsupportedtype=Dateien des Typs [[filetype]] werden nicht unterstützt. Du kannst nur Dateien der Typen GIF, PNG oder JPG hochladen. Fast alle Graphikprogramme können Bilddateien in diese Formate konvertieren. + +/userinfo.bml.about.comm=Info: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.body.leave= Du kannst die Community jederzeit verlassen. + +/userinfo.bml.comminfo.body=Dies ist die Information über die "[[commname]]"-Community auf LiveJournal. + +/userinfo.bml.comminfo.name=Community-Informationen + +/userinfo.bml.date.never=Niemals. + +/userinfo.bml.error.malfname=Ungültiger Benutzername, oder er enthält ungültige Zeichen. + +/userinfo.bml.error.notloggedin=Möchtest du dein eigenes Benutzerprofil sehen, musst du dich einloggen. + +/userinfo.bml.friendof.comm=Gelesen von: + +/userinfo.bml.friendof.hidden=(ausgeblendet) + +/userinfo.bml.friendof.syndreadcount=Anzahl der Leser + +/userinfo.bml.friendof.user=Freund von: + +/userinfo.bml.friends.comm=Mitglieder + +/userinfo.bml.friends.user=Freunde + +/userinfo.bml.label.addbuddy=Buddy hinzufügen + +/userinfo.bml.label.adduser=Benutzer hinzufügen + +/userinfo.bml.label.alsofriendof=Außerdem Freund von: + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=Geburtsdatum: + +/userinfo.bml.label.clientsused=Verwendete Clients: + +/userinfo.bml.label.comments=Kommentare: + +/userinfo.bml.label.composted=geschrieben: [[num]] - + +/userinfo.bml.label.comreceived=erhalten: [[num]] + +/userinfo.bml.label.datecreated=Angelegt am: + +/userinfo.bml.label.dateupdated=Letzter Eintrag: + +/userinfo.bml.label.email=E-Mail: + +/userinfo.bml.label.frpeople=Leute + +/userinfo.bml.label.frsyndication2=RSS-Quellen + +/userinfo.bml.label.icquin=ICQ-Nummer: + +/userinfo.bml.label.interests=Interessen + +/userinfo.bml.label.interests.modifyyours=Deine verändern + +/userinfo.bml.label.interests.removesome=Einige entfernen + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] Interessen nicht angezeigt + +/userinfo.bml.label.journalentrs=Journaleinträge: + +/userinfo.bml.label.location=Ort: + +/userinfo.bml.label.memberof=Mitglied von + +/userinfo.bml.label.memories=Erinnerungen: + +/userinfo.bml.label.moredetails=(weitere Details...) + +/userinfo.bml.label.msnusername=MSN-Benutzername: + +/userinfo.bml.label.mutual=Beidseitige Freunde: + +/userinfo.bml.label.nofriends=Niemand. + +/userinfo.bml.label.post=Ausgewähltes Journal: "[[journal]]" + +/userinfo.bml.label.postalt=Neuen Eintrag schreiben + +/userinfo.bml.label.reqfinduser=Nur Benutzer mit dem 'finduser'-Privileg können Benutzer über ihre Benutzer-ID suchen. + +/userinfo.bml.label.searchjournal=Dieses Journal durchsuchen + +/userinfo.bml.label.sendmessage=Mitteilung senden + +/userinfo.bml.label.shared=Schreibzugriff: + +/userinfo.bml.label.supportpoints=Supportpunkte + +/userinfo.bml.label.syndicatedfrom=Ãœbernahme von: + +/userinfo.bml.label.syndicatedstatus=Status der Aktualisierung: + +/userinfo.bml.label.textmessage=Textmeldung
      (SMS)
      : + +/userinfo.bml.label.todo=To-Do Liste + +/userinfo.bml.label.user=Benutzer: + +/userinfo.bml.label.viewfriends=Freunde anzeigen + +/userinfo.bml.label.viewmembers=Mitglieder anzeigen + +/userinfo.bml.label.yahooid=Yahoo!-Benutzername: + +/userinfo.bml.membership.body=Klicke hier, um dieser Community beizutreten. + +/userinfo.bml.membership.paidmembers=Sobald du einen bezahlten Account hast, kannst du der Paidmembers-Community beitreten. + +/userinfo.bml.memories.entries=[[count]] Einträge + +/userinfo.bml.memories.entry=[[count]] Eintrag + +/userinfo.bml.monitor.comm=Community beobachten + +/userinfo.bml.monitor.user=Diesen Benutzer zur Liste deiner Freunde hinzufügen + +/userinfo.bml.nonexist.body=Der Benutzername [[user]] ist momentan nicht registriert. + +/userinfo.bml.nonexist.name=Unbekannter Benutzer + +/userinfo.bml.sendmessage.body=Verschicke eine Textnachricht (SMS) an [[user]]
      zum Mobiltelefon oder Pager. + +/userinfo.bml.syn.last.never=Noch nie + +/userinfo.bml.syn.lastcheck=Letzte Überprüfung: + +/userinfo.bml.syn.nextcheck=Nächste Überprüfung: + +/userinfo.bml.syn.parseerror=Fehlermeldung: + +/userinfo.bml.syndinfo.body=Wenn du Artikel von der externen Website in deiner Freundesseite lesen möchtest, kannst du dieses Journal deiner Freundesliste hinzufügen. + +/userinfo.bml.syndinfo.name=Externe Artikelquelle + +/userinfo.bml.tellafriend=Einem Freund mitteilen! + +/userinfo.bml.timeupdate.dayago=vor einem Tag + +/userinfo.bml.timeupdate.daysago=vor [[num]] Tagen + +/userinfo.bml.timeupdate.hourago=vor einer Stunde + +/userinfo.bml.timeupdate.hoursago=vor [[num]] Stunden + +/userinfo.bml.timeupdate.minuteago=vor einer Minute + +/userinfo.bml.timeupdate.minutesago=vor [[num]] Minuten + +/userinfo.bml.timeupdate.secondago=vor einer Sekunde + +/userinfo.bml.timeupdate.secondsago=vor [[num]] Sekunden + +/userinfo.bml.timeupdate.weekago=vor einer Woche + +/userinfo.bml.timeupdate.weeksago=vor [[num]] Wochen + +/userinfo.bml.title=Benutzerprofil + +/userinfo.bml.title.communityinfo=Community-Informationen + +/userinfo.bml.title.syndicated=Externe Artikelquelle + +/userinfo.bml.userinfo.body=Dies sind die Informationen über den Benutzer [[username]]. Falls du dieser Benutzer bist, kannst du diese Informationen auf der Seite Info bearbeiten ändern (und auswählen, welche Informationen öffentlich zugänglich sind). + +/userinfo.bml.userinfo.name=Benutzerprofil + +bml.badcontent.body=Einer oder mehrere Fehler sind beim Bearbeiten der Anfrage aufgetreten. Bitte gehe zurück, korrigiere die entsprechenden Informationen und schicke die Daten erneut ab. + +bml.badinput.body=Dein Browser hat Text abgeschickt, der nicht als gültiger Text in UTF-Kodierung erkannt werden kann, was aber zur Verarbeitung des Texts notwendig ist. Dies könnte passiert sein, falls dein Browser die letzte Seite in einer anderen Kodierung anzeigte. Es könnte auch auf einen Fehler im Browser hinweisen. Falls der Fehler nicht umgangen werden kann, kontaktiere uns bitte. + +bml.badinput.head=Fehlerhafte Unicode-Eingabe + +bml.needlogin.body2=Um diese Seite zu sehen, musst du dich einloggen. + +bml.needlogin.head=Bitte einloggen + +BML.parse_multipart.parse=Fehler beim Analysieren der hochgeladenen Datei + +BML.parse_multipart.toolarge=Die hochgeladene Datei ist zu groß + +BML.parse_multipart.unknowntype=Unbekannter Inhaltstyp + +bml.requirepost=Als Sicherheitsmaßnahme benötigt diese Seite eine POST-Anfrage, keine GET-Anfrage. Falls du dieses Formular mit Berechtigung abschicken möchtest, kontaktiere uns bitte. + +btn.search=Suche + +crumb.about=Über LiveJournal + +crumb.abusereport=Mißbrauch melden + +crumb.acctfeatures=Features der Accountarten + +crumb.acctstatus=Account-Status + +crumb.addfriend=Freund hinzufügen + +crumb.addtodo=Aufgabe hinzufügen + +crumb.advcustomize=Erweiterte S2-Einstellungen anpassen + +crumb.advsearch=Erweitert + +crumb.banners=Werbebanner + +crumb.birthdays=Geburtstage + +crumb.changepass=Passwort ändern + +crumb.commmembers=Community-Mitgliedschaft + +crumb.commpending=Zu bestätigende Mitgliedschaften + +crumb.commsearch=Community-Suche + +crumb.community=Community-Zentrum + +crumb.contract=Unser Versprechen an die Benutzer + +crumb.contributors=Mitwirkende + +crumb.createcommunity=Community erstellen + +crumb.createjournal=Journal erstellen + +crumb.createstyle=Layout erstellen + +crumb.customize=S2-Anpassungen bearbeiten + +crumb.delcomment=Kommentar löschen + +crumb.download=Client herunterladen + +crumb.editentries=Einträge bearbeiten + +crumb.editentries_do=Eintrag bearbeiten + +crumb.editfriendgrps=Freundesgruppen bearbeiten + +crumb.editfriends=Freundesliste bearbeiten + +crumb.editinfo=Persönliche Informationen + +crumb.editpics=Benutzerbilder + +crumb.editstyle=Layout bearbeiten + +crumb.emailgateway=E-Mail-Zugang + +crumb.emailmanage=E-Mail-Verwaltung + +crumb.encodings=Über Kodierungen + +crumb.export=Journal exportieren + +crumb.faq=Häufige Fragen + +crumb.feedstersearch=Nach einem Journal suchen + +crumb.filemanager=Datei-Manager + +crumb.friendsfilter=Freundes-Filter + +crumb.goat=Über Frank + +crumb.home=Startseite + +crumb.itsfree=Es ist kostenlos? + +crumb.joincomm=Community beitreten + +crumb.latestposts=Aktuellste Einträge + +crumb.layerbrowse=Browser der öffentlichen Layer + +crumb.leavecomm=Community verlassen + +crumb.legal=Rechtliche Informationen + +crumb.linkslist=Deine Links + +crumb.login=Einloggen + +crumb.logout=Ausloggen + +crumb.lostinfo=Verlorene Informationen + +crumb.manage=Accounts verwalten + +crumb.managecommunity=Community-Verwaltung + +crumb.meme=Liste der 'Memes' + +crumb.memories=Erinnerungswürdige Einträge + +crumb.moderate=Community-Warteschlange + +crumb.modify=Journal-Einstellungen + +crumb.moodlist=Stimmungs-Liste + +crumb.news=Neuigkeiten + +crumb.paidaccounts=Bezahlte Accounts + +crumb.paidacctstatus=Bezahlter Account + +crumb.phonepostsettings=Telefoneintrag + +crumb.popfaq=Oft verwendete FAQs + +crumb.press=LiveJournal-Pressebereich + +crumb.pressarticles=LiveJournal in der Presse + +crumb.preview=Layout-Vorschau + +crumb.privacy=Datenschutzerklärung + +crumb.register=E-Mail bestätigen + +crumb.search=Suchen + +crumb.searchinterests=Nach Interesse + +crumb.searchregion=Nach Region + +crumb.seeoverrides=Benutzer-Anpassungen anschauen + +crumb.singles=LiveJournal-Singles + +crumb.singlesopts=Verfügbarkeit bearbeiten + +crumb.singlessearch=Suche nach Singles + +crumb.siteopts=Web-Einstellungen + +crumb.sizechart=Größentabelle + +crumb.staff=Angestelltenteam + +crumb.stats=Statistiken + +crumb.store=LiveJournal-Laden + +crumb.storeitem=Details anschauen + +crumb.styles=Layouts + +crumb.suggestions=Formular für Vorschläge + +crumb.suggview=Vorschläge + +crumb.supportappend=Antwort vorschlagen + +crumb.supporthelp=Anfragen + +crumb.supportnotify=Benachrichtigungs-Einstellungen + +crumb.supportscores=High-Scores + +crumb.supportsubmit=Anfrage abschicken + +crumb.textmessage=SMS verschicken + +crumb.themes=Farbschemen-Vorschau + +crumb.todo=Aufgabenliste + +crumb.tos=Allgemeine Nutzungsbedingungen + +crumb.unsubscribe=Abbestellen + +crumb.update=Neuer Eintrag + +crumb.utf8convert=UFT-8-Konvertierer + +crumb.yourlayers=Deine Layer + +crumb.yourstyles=Deine Layouts + +date.day.friday.long=Freitag + +date.day.friday.short=Fr + +date.day.monday.long=Montag + +date.day.monday.short=Mo + +date.day.saturday.long=Samstag + +date.day.saturday.short=Sa + +date.day.sunday.long=Sonntag + +date.day.sunday.short=So + +date.day.thursday.long=Donnerstag + +date.day.thursday.short=Do + +date.day.tuesday.long=Dienstag + +date.day.tuesday.short=Di + +date.day.wednesday.long=Mittwoch + +date.day.wednesday.short=Mi + +date.month.december.long=Dezember + +date.month.december.short=Dez + +date.month.february.long=Februar + +date.month.january.long=Januar + +date.month.july.long=Juli + +date.month.june.long=Juni + +date.month.march.long=März + +date.month.march.short=Mär + +date.month.may.long=Mai + +date.month.may.short=Mai + +date.month.october.long=Oktober + +date.month.october.short=Okt + +dystopia.btn.login=EINLOGGEN + +dystopia.hello_anonymous=Willkommen bei LiveJournal! + +dystopia.hello_loggedin=Hallo, [[username]]! + +dystopia.nav.contact=Kontaktinformationen + +dystopia.nav.createjournal=Journal erstellen + +dystopia.nav.developer=Entwicklerbereich + +dystopia.nav.download=Download + +dystopia.nav.editentries=Einträge ändern + +dystopia.nav.editfriends=Deine Freunde + +dystopia.nav.editpassword=Dein Passwort + +dystopia.nav.editpics=Deine Bilder + +dystopia.nav.editstyle=Stil bearbeiten + +dystopia.nav.faq=LiveJournal FAQ + +dystopia.nav.findcomm=Nach Community + +dystopia.nav.finddir=Verzeichnissuche + +dystopia.nav.findint=Nach Interessen + +dystopia.nav.findrandom=Zufälliges Journal + +dystopia.nav.findregion=Nach Region + +dystopia.nav.home=Startseite + +dystopia.nav.journalcalendar=Kalender + +dystopia.nav.journalfriends=Freunde + +dystopia.nav.journalinfo=Über dich + +dystopia.nav.journalrecent=Aktuelle Einträge + +dystopia.nav.legalcoppa=COPPA + +dystopia.nav.legalprivacy=Datenschutz + +dystopia.nav.legaltos=AGB + +dystopia.nav.login=Einloggen + +dystopia.nav.logout=Ausloggen + +dystopia.nav.lostinfo=Passwort weg? + +dystopia.nav.memories=Erinnerungen + +dystopia.nav.modifyjournal=Design ändern + +dystopia.nav.news=Aktuelles + +dystopia.nav.paidaccts=Bezahlter Zugang + +dystopia.nav.paymentarea=Bezahlen + +dystopia.nav.personalinfo=Info bearbeiten + +dystopia.nav.sitemap=Sitemap + +dystopia.nav.siteopts=Grundeinstellungen + +dystopia.nav.support=Hast du Fragen? + +dystopia.nav.updatejournal=Neuer Eintrag + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=122 + +dystopia.navhead.findusers=Nach Benutzern suchen + +dystopia.navhead.help=Hilfe & Support + +dystopia.navhead.journal=Dein Journal + +dystopia.navhead.legal=Rechtliches + +dystopia.navhead.settings=Deine Einstellungen + +dystopia.navhead.welcome=Willkommen! + +dystopia.search.icq=ICQ-Nummer + +dystopia.search.int=Interessen + +dystopia.search.msn=MSN-Benutzername + +dystopia.search.region=Region + +dystopia.search.yahoo=Yahoo!-Benutzername + +dystopia.searchlj=LiveJournal durchsuchen: + +Email=E-Mail-Adresse + +email.newacct.body<< +Herzlichen Glückwunsch zu deinem neuen LiveJournal-Account! + +Um die Erstellung deines Account zu vollenden und deine E-Mail-Adresse +zu bestätigen, folge diesem Link: + + [[regurl]] + +Dein neues Journal kannst du unter den folgenden URLs abrufen: + + [[siteroot]]/users/[[username]]/ + +und + + [[siteroot]]/~[[username]]/ + +Dein LiveJournal-Benutzername und -Passwort lauten: + + Benutzername: [[username]] + Passwort: [[password]] + +Auf [[siteroot]]/ kannst du auf deinen Account zugreifen, +Einträge erstellen und die Einstellungen deines Journals verändern. +Es ist empfehlenswert, einen LiveJournal-Client herunterzuladen. +Das ist der einfachste Weg, dein Journal auf den neuesten Stand +zu bringen. Clients werden für viele Betriebssysteme angeboten! +Hier kannst du einen Client downloaden: + + [[siteroot]]/download/ + +Bei LiveJournal anzufangen kann manchmal schwierig senn, wenn man +niemanden kennt. Die Seite http://newbies.livejournal.com/ bietet +cleveren und hilfreichen Rat... Mit etwas Glück bist du in null +Komma nichts ein LiveJournal-Profi! + +Wir hoffen, dass dir LiveJournal genauso viel bedeuten wird, wie es +uns bedeutet, es zur Verfügung zu stellen. Hast du Fragen, die die +Benutzung von LiveJournal betreffen, kannst du sie im Support-Bereich +stellen: + + [[siteroot]]/support/ + +Dort findest du Antworten auf beinahe alle Fragen, die dir zu LiveJournal +einfallen. Support-Anfragen können natürlich auch in deutscher Sprache +gestellt werden. + +Unser Ziel ist es, dass LiveJournal richtig cool wird. Findest du, dass +wir etwas benutzerfreundlicher machen können oder mehr Funktionen und +Optionen zur Verfügung stellen könnten, dann lass es uns wissen. +Wir betreiben diese Webseite nicht, um Geld zu verdienen. Wir sind +keine Dot-Com-Firma, die von Risikokapitalen unterstützt wird und hofft, +an die Börse zu gehen... Diese Webseite wird von den Leuten in Stand +gehalten, die sie auch benutzen. Teile uns mit, was du von der Webseite +erwartest. + +Das Support-Team beantwortet Fragen im Allgemeinen innerhalb von +weniger als 24 Stunden. + +Viel Spaß! + +Das [[sitename]]-Team +[[siteroot]]/ + +. + +email.newacct.subject=Willkommen bei LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Fehler + +error.badpassword=Falsches Passwort. + +error.code.comm_not_comm=Account ist keine Community + +error.code.comm_not_found=Community wurde nicht gefunden + +error.code.comm_not_member=Benutzer ist kein Mitglied dieser Community + +error.dberror=Ein Datenbankfehler ist aufgetreten: + +error.deleted.name=Gelöscht + +error.deleted.text=Dieses Journal wurde gelöscht. Falls du [[user]] bist, hast du 30 Tage Zeit, um den Löschvorgang rückgängig zu machen. Nach 30 Tagen wird der ganze Inhalt permanent von unseren Servern gelöscht. + +error.deleted.title=Gelöschter Account + +error.expiredchal=Das Login-Fenster ist abgelaufen. Bitte versuche es erneut. + +error.invalidauth=Du konntest nicht als der angegebene Benutzer identifiziert werden. + +error.ipbanned=Deine IP-Adresse ist aufgrund zu vieler fehlgeschlagener Login-Versuche vorübergehend gesperrt. + +error.malformeduser=Ungültiger Benutzername + +error.nobutton=Keinen Button gedrückt? + +error.nodb=Datenbank derzeit nicht erreichbar. + +error.nodbmaintenance=Dieser Teil der Datenbank ist momentan wegen Wartungsarbeiten nicht verfügbar. Versuche es in einigen Minuten noch einmal. + +error.noentry=Solch ein Journaleintrag existiert nicht. + +error.nojournal=Unbekanntes Journal + +error.noremote=Um diese Seite zu verwenden, musst du eingeloggt sein. + +error.procrequest=Bei der Bearbeitung deiner Anfrage ist ein Fehler aufgetreten: + +error.purged.name=Gelöscht + +error.purged.text=Dieses Journal wurde endgültig gelöscht. + +error.purged.title=Endgültig gelöschter Account + +error.suspended.name=Gesperrt + +error.suspended.text=Dieser Account wurde entweder zeitweise oder dauerhaft suspendiert. Wenn du [[user]] bist, ist die FAQ Mein Account wurde suspendiert! Wie bekomme ich ihn zurück? für dich von Nutzen. Zum Schutz der Privatsphäre der Benutzer kann [[sitename]] die Gründe für eine Suspension mit niemand anderem als dem Besitzer des Accounts diskutieren. + +error.suspended.title=Gesperrter Account + +error.tempdisabled=Dies ist vorübergehend abgeschaltet. + +error.unknownmode=Unbekannter Modus. + +error.usernameinvalid=Der Benutzername enthält unzulässige Zeichen. + +error.usernamelong=Der Benutzername ist zu lang, maximal 15 Zeichen. + +error.username_notfound=Der Benutzername wurde nicht gefunden. + +Help=Hilfe + +label.screening.all=Alle Kommentare + +label.screening.anonymous=Nur anonyme Kommentare + +label.screening.default=Standard + +label.screening.header=Verdeckte Kommentare: + +label.screening.none=Keine + +label.screening.nonfriends=außer LiveJournal-Freunde + +label.security.custom=Freundesgruppen... + +label.security.friends=Freunde + +label.security.head=Sichtbarkeit: + +label.security.maintainers=Maintainer + +label.security.members=Mitglieder + +label.security.private=Privat + +label.security.public=Öffentlich + +label.switch.button=Wechseln + +label.switch.header=Zu einem anderen Journal wechseln + +label.switch.workwith=Arbeite mit Journal: + +langname.be=Belarusisch + +langname.da=Dänisch + +langname.de=Deutsch + +langname.en=Englisch (USA) + +langname.en_GB=Englisch (Großbritannien) + +langname.en_LJ=Englisch (USA) + +langname.es=Spanisch + +langname.et=Estnisch + +langname.fi=Finnisch + +langname.fr=Französisch + +langname.ga=Irisch + +langname.gd=Gälisch + +langname.he=Hebräisch + +langname.hu=Ungarisch + +langname.is=Isländisch + +langname.it=Italienisch + +langname.ja=Japanisch + +langname.la=Lateinisch + +langname.lv=Lettisch + +langname.ms=Malaysisch + +langname.nb=Norwegisch (Bokmål) + +langname.nl=Holländisch + +langname.nn=Norwegisch (Nynorsk) + +langname.pl=Polnisch + +langname.pt=Portugiesisch + +langname.ru=Russisch + +langname.sv=Schwedisch + +langname.tr=Türkisch + +langname.uk=Ukrainisch + +langname.zh=Chinesisch (Vereinfacht) + +ljcom.account.feature.email=LiveJournal- Mailadresse + +ljcom.account.feature.full2=Die vollständige Tabelle befindet sich auf dieser Seite. + +ljcom.account.feature.limit=begrenzt + +ljcom.account.feature.ownblog=Dein eigenes Journal/Weblog + +ljcom.account.feature.search=Verzeichnissuche + +ljcom.account.feature.styles=Designs erstellen/bearbeiten + +ljcom.account.feature.syn=Zeigt Einträge von Freunden und externen Artikelquellen an + +ljcom.account.free=Kostenloser Account + +ljcom.account.paid=Bezahlter Zugang + +ljcom.account.paid12=Für 12 Monate bezahlt ($25 US) + +ljcom.account.paid2=Für 2 Monate bezahlt ($5 US) + +ljcom.account.paid6=Für 6 Monate bezahlt ($15 US) + +ljcom.accounttype=Account-Art + +ljcom.badpass.email=Dein Passwort darf nicht deiner E-Mail-Adresse ähnlich sein. + +ljcom.badpass.realname=Dein Passwort darf nicht deinem echten Namen ähnlich sein. + +ljcom.badpass.username=Dein Passwort darf nicht deinem Benutzernamen ähnlich sein. + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Internationalen [[name]] "Meetup"-Tag + +ljcom.meetup.moreinfo=(Details) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Möchtest du offline Leute aus deiner Gegend treffen, um euch über dieses Interesse zu unterhalten? Mehr darüber erfahrt ihr beim [[link]]! + +ljcom.menu.upgrade=Account bezahlen + +ljcom.userinfo.accounttype=Account-Art + +ljcom.userinfo.paiduser=Zahlender Benutzer + +ljcom.userinfo.types.early=Früheinsteiger + +ljcom.userinfo.types.free=Kostenloser Account + +ljcom.userinfo.types.paid=Bezahlter Account + +ljcom.userinfo.types.paid_early=Bezahlter Account, vorher Früheinsteiger + +ljcom.userinfo.types.paid_early_expiring=Bezahlter Account, läuft [[paiduntil]] aus, vorher Früheinsteiger + +ljcom.userinfo.types.paid_expiring=Bezahlter Account, läuft [[paiduntil]] aus + +ljcom.userinfo.types.permanent=Permanenter Account + +ljcom.userinfo.types.permanent_early=Permanenter Account, vorher Früheinsteiger + +ljlib.pageofpages=Seite [[page]] von [[total]] + +lostinfo.head=Etwas vergessen? + +lostinfo.text=Falls du deinen Benutzernamen oder dein Passwort vergessen hast, klicke hier. + +lynx.nav.friends=Freunde + +lynx.nav.help=Technischer Support + +lynx.nav.home=Startseite + +lynx.nav.login=Einloggen + +lynx.nav.logout=Ausloggen + +lynx.nav.recent=Aktuelle Einträge + +lynx.nav.siteopts=Browsereinstellungen + +lynx.nav.update=Neuer Eintrag + +Password=Passwort + +password.max30=Passwörter dürfen nicht mehr als 30 Zeichen enthalten. + +poll.dberror=Datenbank-Fehler: [[errmsg]] + +poll.dberror.items=Datenbank-Fehler beim Einfügen der Elemente: [[errmsg]] + +poll.dberror.questions=Datenbank-Fehler beim Einfügen der Fragen: [[errmsg]] + +poll.error.badmaxlength=Das Maxlength-Attribut (Maximallänge) bei lj-pq-Tags muss eine ganze Zahl zwischen 1 und 255 sein. + +poll.error.badsize=Das Size-Attribut (Größe) bei lj-pq-Tags muss eine ganze Zahl zwischen 1 und 100 sein. + +poll.error.cantview=Fehler: Du hast keinen Zugriff auf die Umfrageergebnisse + +poll.error.cantvote=Sorry, du darfst in dieser Umfrage nicht abstimmen. + +poll.error.missingljpoll=Alle lj-pq-Tags müssen sich innerhalb eines lj-poll-Tags befinden. + +poll.error.missingljpq=Alle lj-pi-Tags müssen sich innerhalb eines lj-pq-Tags befinden. + +poll.error.nested=[[tag]]-Tags können nicht verschachtelt werden. Wurde eines möglicherweise nicht korrekt geschlossen? + +poll.error.noentry=Fehler: diese Umfrage ist diesem Journal-Eintrag nicht zugehörig + +poll.error.noitems=Wenigstens ein Element muss sich in einer nicht-textbasierten Frage befinden. + +poll.error.noitemstext=lj-pq-Tags des Typs 'text' können keine Umfragenelemente beinhalten. + +poll.error.nopollid=Parameter pollid fehlt. + +poll.error.noquestions=Wenigstens eine Frage sollte sich in der Umfrage befinden. + +poll.error.notext=Innerhalb eines lj-pq-Tags muss sich Text befinden, der die Frage erklärt. + +poll.error.pitoolong=Der Text innerhalb eines lj-pi-Tags muss zwischen 1 und 255 Zeichen lang sein. Deiner ist [[len]] lang. + +poll.error.pollnotfound=Fehler: Umfrage #[[num]] wurde nicht gefunden. + +poll.error.questionnotfound=Fehler: Diese Frage existiert nicht. + +poll.error.scalefromlessto=Der Wert 'von' in einer Skala muss kleiner als der 'bis'-Wert sein. + +poll.error.scaleincrement=Die Skala muss sich um wenigstens 1 erhöhen. + +poll.error.scaletoobig=Die Skala überschreitet die Grenze von 20 Auswahlmöglichkeiten (von-bis)/Schritte > 20 + +poll.error.tagnotopen=Ein [[tag]]-Tag, das nicht geöffnet wurde, kann nicht geschlossen werden. + +poll.error.truncated=... abgeschnitten + +poll.error.unknownpqtype=Unbekannter Typ im lj-pq-Tag + +poll.error.whoview=whoview muss 'alle', 'Freunde' oder 'niemand' sein. + +poll.error.whovote=whovote muss 'alle' oder 'Freunde' sein. + +poll.pollnum=Umfrage #[[num]] + +poll.security=Offen für: [[whovote]], Ergebnisse sichtbar für: [[whoview]] + +poll.security.all=Alle + +poll.security.friends=Freunde + +poll.security.none=Niemand + +poll.submit=Antworten abschicken + +poll.viewanswers=Antworten anschauen + +portal.bdays.count.des=Standardmäßig werden die 5 Freunde gezeigt, die als nächstes Geburtstag haben. + +portal.bdays.count.name=Angezeigte Geburtstage + +portal.bdays.portalname=Geburtstage + +portal.bdays.portaltitle=Geburtstage + +portal.goat.name=Website-Maskottchen + +portal.goattext.des=Was soll deine Ziege sagen? Eigentlich können Ziegen nur "Bääääh" sagen, aber wenn du wirklich willst, kannst du auch so tun, als könne deine Ziege etwas anderes sagen. + +portal.goattext.name=Frank sagt + +portal.login.portalname=Login-Box + +portal.memories.entriesnoun=Einträge + +portal.memories.entrynoun=Eintrag + +portal.memories.portalname=Erinnerungswürdige Einträge + +portal.memories.portaltitle=Erinnerungswürdige Einträge + +portal.ministats.active=Aktiv: + +portal.ministats.title=Anzahl der Benutzer: + +portal.misbehaved.des=Diese Option hättest du wirklich auslassen sollen. Ziegen, die nicht stubenrein sind, bringen nur Ärger. + +portal.misbehaved.name=Ungezogene Ziege + +portal.newtolj.name=Nützliche Links + +portal.popfaq.portalname=Die 10 am häufigsten angeschauten FAQs + +portal.popfaq.portaltitle=Die 10 am häufigsten angeschauten FAQs + +portal.randuser.count.des=Standardmäßig wird ein zufällig gewählter Benutzer angezeigt, aber du kannst dir vertikal bis zu 10 in der schmalen Spalte anzeigen lassen oder 5 horizontal in einer breiten Spalte. + +portal.randuser.count.name=Anzahl der zufällig angezeigten Benutzer + +portal.randuser.error.tableempty=Es gibt keine zufällig angezeigten Benutzer. Bitte Administrator informieren. + +portal.randuser.hidename.des=Standardmäßig wird der zufällige Benutzername angezeigt. Um ihn zu entfernen, aktiviere diese Option. + +portal.randuser.hidename.name=Namen verstecken + +portal.randuser.hidepic.des=Standardmäßig wird das Benutzerbild des zufälligen Journals angezeigt, falls verfügbar. Aktiviere diese Option, um es zu entfernen. + +portal.randuser.hidepic.name=Benutzerbild entfernen + +portal.randuser.portalname=Zufälliger Benutzer + +portal.randuser.portaltitle=Zufälliger Benutzer + +portal.randuser.portaltitleplural=Zufällige Benutzer + +portal.recent.error.noentries=Sorry. Keine Einträge. + +portal.recent.error.notsetup=Diese Box muss konfiguriert werden. Klicke auf das "Plus"-Symbol, um das Journal einzustellen, welches du hier gerne beobachten möchtest. + +portal.recent.error.userstatus=Account des Benutzers wurde gelöscht oder suspendiert. + +portal.recent.items.description=Standardmäßig wird hier nur der aktuellste Eintrag angezeigt. + +portal.recent.items.name=Dargestellte Elemente + +portal.recent.journal.description=Von welchem Journal würdest du gerne die aktuellsten Einträge sehen? + +portal.recent.nosubject=(Kein Betreff) + +portal.recent.portalname=Aktuelle Einträge + +portal.recent.portaltitle=Box "Aktuellste Einträge" + +portal.recent.showtext.description=Standardmäßig werden nur die Titelzeilen angezeigt. + +portal.recent.showtext.name=Text einfügen + +portal.stats.journalentyest=gestrige Journaleinträge + +portal.stats.portalname=LiveJournal-Statistik + +portal.stats.portaltitle=Statistik + +portal.stats.totalusers=Anzahl aller Benutzer + +portal.update.mode.des=Der Vollmodus verfügt über eine Menge Extras zum Schreiben von Einträgen, zum Beispiel Einträge in Communities schreiben. die aktuelle Stimmung oder Musik einstellen oder ein anderes Benutzerbild verwenden. Der einfache Modus ist besser, wenn du jene Features kaum verwendest oder die Einstellungsmöglichkeiten lieber nicht sehen möchtest. + +portal.update.mode.full=Voll + +portal.update.mode.name=Modus + +portal.update.mode.simple=Einfach + +portal.update.portalname=Neuer Eintrag + +portal.update.portaltitle=Neuen Eintrag schreiben + +protocol.bad_password=Dein Passwort ist zu leicht zu erraten. Bitte ändere dein Passwort, wenn du nicht Gefahr laufen möchtest, dass in dein Journal eingebrochen wird. Um dein Passwort zu ändern, gehe auf die Seite [[siteroot]]/changepassword.bml + +protocol.hello_test=Hallo, Test-Account! + +protocol.mail_bouncing=Zur Zeit verwendest du eine ungültige E-Mail-Adresse. Jede E-Mail, die wir dir schicken wollen, wird an uns zurückgeschickt. [[sitename]] benötigt eine gültige E-Mail-Adresse. Gehe zu [[siteroot]]/support/faqbrowse.bml?faqid=19 für Informationen, wie du deine E-Mail-Adresse veränderst. + +protocol.modpost=Dein Eintrag wurde in die Moderations-Warteschlange eingereiht. Er wird von einem der Community-Moderatoren akzeptiert oder abgelehnt werden. + +protocol.must_revalidate=Du musst deine neue E-Mail-Adresse bestätigen lassen. Deine vorherige war bestätigt, aber da du die Adresse geändert hast, musst du die neue erneut bestätigen lassen. Wenn du die Adresse nicht bestätigen lässt, wirst du nicht Zugang zu allen Funktionen von [[sitename]] haben. Die FAQ "Wie lasse ich meine E-Mail-Adresse bestätigen? Mir wird gesagt, meine E-Mail-Adresse sei nicht bestätigt!" ([[siteroot]]/support/faqbrowse.bml?faqid=11) enthält mehr Informationen. + +protocol.not_validated=Deine E-Mail-Adresse wurde noch nicht bestätigt. Du kannst [[sitename]] weiterhin benutzen, aber ohne die Bestätigung deiner Mail-Adresse erhältst du keinen Zugang zu bestimmten Funktionen der Site. Lies die Anleitung, die dir beim Erstellen des Journals zugeschickt wurden oder gehe zu [[siteroot]]/support/faqbrowse.bml?faqid=11 für mehr Informationen. + +protocol.old_win32_client=Wir empfehlen dir ein Upgrade des Windows LiveJournal-Clients, da eine um vieles neuere Version verfügbar ist. Um einen neuen Client runterzuladen, gehe zu [[siteroot]]/download/ + +protocol.readonly=Momentan befindet sich dein Account im "Nur Lesen"-Modus. Einige Vorgänge werden für einige Minuten nicht funktionieren. + +talk.anonwrote=Jemand schrieb, + +talk.anonwrote_comm=Jemand schrieb in [[commlink]], + +talk.btn.preview=Vorschau + +talk.commentpermlink=Link + +talk.commentpost=Neuen Kommentar hinterlassen + +talk.commentsread=Kommentare lesen + +talk.curname_Mood=Stimmung: + +talk.curname_Music=Musik: + +talk.error.bogusargs=Falsche Eingaben + +talk.error.comm_deleted=Dieser Kommentar wurde gelöscht. + +talk.error.deleted=Dieses Journal wurde gelöscht. + +talk.error.deleted.title=Gelöscht + +talk.error.mustlogin=Du musst eingeloggt sein um diesen geschützten Eintrag zu lesen. + +talk.error.nocomment=Kein Kommentar vorhanden. + +talk.error.noentry=Diesen Eintrag gibt es nicht. + +talk.error.nojournal=Fehler: Journal ließ sich nicht aus den Eingaben bestimmen. + +talk.error.nosuchjournal=Dieses Journal gibt es nicht. + +talk.error.notauthorised=Es ist dir nicht gestattet, diesen geschützten Eintrag zu lesen. + +talk.error.suspended=Dieses Journal/Dieser Benutzer ist gesperrt. + +talk.error.suspended.title=Gesperrt. + +talk.parentlink=Kommentar davor + +talk.readsimilar=Ähnliche Journaleinträge lesen: + +talk.replytothis=Darauf antworten + +talk.somebodywrote=[[realname]] ([[userlink]]) schrieb: + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) schrieb in [[commlink]]: + +talk.spellcheck=Rechtschreibprüfung während der Vorschau (nur U.S.-Englisch) + +talk.threadlink=Nachfolgende Kommentare + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_deutsch + +Username=Benutzername + +userpic.inactive=inaktiv + +xcolibur.greeting.anon=Willkommen bei LiveJournal! + +xcolibur.greeting.logged_in=Hallo, [[name]]! [[logout]] + +xcolibur.login=Einloggen? + +xcolibur.logout=Ausloggen? + +xcolibur.nav.about=Über LiveJournal + +xcolibur.nav.about.general=Allgemeine Informationen + +xcolibur.nav.about.paidaccounts=Bezahlte Accounts + +xcolibur.nav.about.press=Presse + +xcolibur.nav.about.sitenews=Aktuelles + +xcolibur.nav.about.stats=Statistiken + +xcolibur.nav.footer.sitemap=Sitemap + +xcolibur.nav.help=Hilfe + +xcolibur.nav.help.ask=Hast du Fragen? + +xcolibur.nav.help.contact=Kontakt-Informationen + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Passwort verloren? + +xcolibur.nav.home=Startseite + +xcolibur.nav.journal.archive=Archiv + +xcolibur.nav.journal.edit.entries=Einträge bearbeiten + +xcolibur.nav.journal.friends=Freunde + +xcolibur.nav.journal.info=Profil + +xcolibur.nav.journal.memories=Erinnerungen + +xcolibur.nav.journal.recent=Aktuelle Einträge + +xcolibur.nav.journal.update=Neuer Eintrag + +xcolibur.nav.manage=Verwalten + +xcolibur.nav.manage.customize=Design verändern + +xcolibur.nav.manage.entries=Einträge + +xcolibur.nav.manage.friends=Freunde + +xcolibur.nav.manage.info=Profil + +xcolibur.nav.manage.password=Passwort + +xcolibur.nav.manage.pics=Benutzerbilder + +xcolibur.nav.manage.styles=Stile + +xcolibur.nav.search=Suchen + +xcolibur.nav.search.directory=Ort + +xcolibur.nav.search.directory.search=Erweiterte Suche + +xcolibur.nav.search.interests=Interessen + +xcolibur.nav.search.random=Zufälliges Journal + +xcolibur.nav.siteopts=Grundeinstellungen + +xcolibur.nav.title=Navigation + +xcolibur.nav.welcome=Willkommen + +xcolibur.nav.welcome.create=Account erstellen + +xcolibur.nav.welcome.login=Einloggen + +xcolibur.nav.welcome.update=Neuen Eintrag schreiben + +xcolibur.search=Suchen: + +xcolibur.search.aolim=AOL-Benutzername + +xcolibur.search.category=Kategorie: + +xcolibur.search.icq=ICQ-Nummer + +xcolibur.search.int=Interesse + +xcolibur.search.msn=MSN-Benutzername + +xcolibur.search.region=Ort + +xcolibur.search.yahoo=Yahoo!-Benutzername + +xcolibur.upgrade=Bezahlten Account kaufen + diff --git a/ljcom/bin/upgrading/deadphrases-local.dat b/ljcom/bin/upgrading/deadphrases-local.dat new file mode 100644 index 0000000..48d6aa0 --- /dev/null +++ b/ljcom/bin/upgrading/deadphrases-local.dat @@ -0,0 +1,137 @@ +# ljcom version of deadphrases.dat +# + +general dystopia.nav.setscheme + +general /index.bml.getstarted.create.caption +general /index.bml.getstarted.create.title +general /index.bml.getstarted.download.caption +general /index.bml.getstarted.download.title +general /index.bml.getstarted.header +general /index.bml.getstarted.modify.caption +general /index.bml.getstarted.modify.title +general /index.bml.getstarted.update.caption +general /index.bml.getstarted.update.title +general /index.bml.howuse.create +general /index.bml.howuse.exp +general /index.bml.howuse.header +general /index.bml.otheropts.editfriends.caption +general /index.bml.otheropts.editfriends.title +general /index.bml.otheropts.editinfo.caption +general /index.bml.otheropts.editinfo.title +general /index.bml.otheropts.editjournal.caption +general /index.bml.otheropts.editjournal.title +general /index.bml.otheropts.header +general /index.bml.support.contrib.caption +general /index.bml.support.contrib.title +general /index.bml.support.dev.caption +general /index.bml.support.dev.title +general /index.bml.support.faq.caption +general /index.bml.support.faq.title +general /index.bml.support.header +general /index.bml.support.web.caption +general /index.bml.support.web.title +general /index.bml.text.1 +general /index.bml.text.2 +general /index.bml.text.3 +general /index.bml.text.4 +general /index.bml.text.5 +general /index.bml.whatis.def +general /index.bml.whatis.dev +general /index.bml.whatis.header +general /index.bml.whatis.uses + +general ljcom.login.fastservers + +general /code/index.bml.title +general /code/index.bml.opensource.header +general /code/index.bml.opensource +general /code/index.bml.servercode.header +general /code/index.bml.servercode +general /code/index.bml.libraries.header +general /code/index.bml.libraries +general /code/index.bml.name +general /code/index.bml.description +general /code/index.bml.LJCache.name +general /code/index.bml.LJCache.description +general /code/index.bml.LJTextMessage.name +general /code/index.bml.LJTextMessage.description +general /code/index.bml.LJSpellCheck.name +general /code/index.bml.LJSpellCheck.description +general /code/index.bml.HTMLCleaner.name +general /code/index.bml.HTMLCleaner.description +general /code/index.bml.BML.name +general /code/index.bml.BML.description + +general /manage/phonepost.bml.introduction +general /manage/phonepost.bml.phone.explanation + +general /paidaccounts/index.bml.deliverydate.details +general /paidaccounts/index.bml.deliverydate.label +general /paidaccounts/index.bml.existingpaidaccount.choose_one +general /paidaccounts/index.bml.existingpaidaccount.header +general /paidaccounts/index.bml.existingpaidaccount.months +general /paidaccounts/index.bml.existingpaidaccount.use_this_form +general /paidaccounts/index.bml.existingpaidaccount.your_password +general /paidaccounts/index.bml.existingpaidaccount.your_username +general /paidaccounts/index.bml.features.available +general /paidaccounts/index.bml.features.available.domain_email.about +general /paidaccounts/index.bml.features.available.domain_email.header +general /paidaccounts/index.bml.features.available.domain_name.about +general /paidaccounts/index.bml.features.available.domain_name.header +general /paidaccounts/index.bml.features.available.fast_servers.about +general /paidaccounts/index.bml.features.available.fast_servers.header +general /paidaccounts/index.bml.features.available.polls.about +general /paidaccounts/index.bml.features.available.polls.header +general /paidaccounts/index.bml.features.available.styles.about +general /paidaccounts/index.bml.features.available.styles.header +general /paidaccounts/index.bml.features.available.text_messaging.about +general /paidaccounts/index.bml.features.available.text_messaging.header +general /paidaccounts/index.bml.features.available.userpics.about +general /paidaccounts/index.bml.features.available.userpics.header +general /paidaccounts/index.bml.features.planned.about +general /paidaccounts/index.bml.features.planned.counters.about +general /paidaccounts/index.bml.features.planned.counters.header +general /paidaccounts/index.bml.features.planned.custom_comment_style.about +general /paidaccounts/index.bml.features.planned.custom_comment_style.header +general /paidaccounts/index.bml.gift.anonymous +general /paidaccounts/index.bml.gift.proceed +general /paidaccounts/index.bml.gift.question +general /paidaccounts/index.bml.gift.recipient +general /paidaccounts/index.bml.newpaidaccount.about +general /paidaccounts/index.bml.newpaidaccount.header +general /paidaccounts/index.bml.otherpay.alsopayby +general /paidaccounts/index.bml.otherpay.check_or_mo +general /paidaccounts/index.bml.otherpay.header +general /paidaccounts/index.bml.otherpay.phone_num +general /paidaccounts/index.bml.otherthings.header +general /paidaccounts/index.bml.otherthings.howtogive +general /paidaccounts/index.bml.paypal.about +general /paidaccounts/index.bml.paypal.header + +general /press/staff.bml.back +general /press/staff.bml.deviant +general /press/staff.bml.evan.title +general /press/staff.bml.evan.quip +general /press/staff.bml.kevin.title +general /press/staff.bml.nick.title +general /press/staff.bml.brett.title + +general /rename/index.bml.cost + +general /rename/use.bml.confirm +general /rename/use.bml.error.usedtoke +general /rename/use.bml.error.color + +general xcolibur.nav.setscheme + +general ljcom.account.feature.full + +general xcolibur.nav.about.invite +general dystopia.nav.invite + +general /legal/coppa.bml.title +general /legal/index.bml.docs.coppa.about +general /legal/index.bml.docs.privacy.about + +general dystopia.nav.legalcoppa diff --git a/ljcom/bin/upgrading/en_GB.dat b/ljcom/bin/upgrading/en_GB.dat new file mode 100644 index 0000000..2772ac5 --- /dev/null +++ b/ljcom/bin/upgrading/en_GB.dat @@ -0,0 +1,691 @@ +;; -*- coding: utf-8 -*- +/changepassword.bml.changepassword.instructions=Fill out the form below to change your password. For help with choosing a good password and keeping your account secure, see this FAQ. + +/changepassword.bml.error.badnewpassword=Your new password confirmation does not match your new password. You may have made a mistake in typing. Please type and confirm your new password again. + +/changepassword.bml.error.notvalidated=You cannot change your password if your current email address has not been validated. Please see the FAQ for instructions on doing this. + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge, where you'll find answers to many of the questions you may have. Visit , explore a bit, and you'll be a pro in no time at all! +p?> + + +
      +Add to your friends page to keep up with events and issues that are relevant to the entire LiveJournal community.
      +Add to your friends page to be informed when downtime is planned, and reports on unplanned interruptions of service. +p?> + + +AIM, ICQ, Yahoo!, MSN, or Jabber instant messengers. If you do, be sure to list it in your personal info settings. If you have a Paid Account, you can also enable your mobile phone or pager to receive text messages. +p?> + + +Paid Account. There are, of course, loads of other ways you help out. +

      +LiveJournal is an Open Source project; if you have experience with programming languages or server side applications you can check out the LiveJournal Development Community, . If you have ideas about how LiveJournal could be better, check out the LiveJournal Suggestions Area, . If you would like to help with just about anything, visit the LiveJournal Business Community, . If you like helping people, visit our technical support centre and help someone out. If you are savy with graphic design, check out the LiveJournal Art Community, . +p?> + + +Anime to Zen Buddhism, from Astronomy to Zim. You'll also find regional communities for places all around the world. There's probably a LiveJournal community for where you live too! +p?> + + +FAQ that will explain how to create your very own community. There are also two FAQ Categories (General Community FAQs and Community Management FAQs) covering just about everything you'll ever need to know about communities. If you still need more information, feel free to submit a support request. +p?> + + + + +
        +
      • Community Search
      • +
      • Check out the Promotions Community ()
      • +
      • Check out the Search Community ()
      • +
      + + +Email Jesse Proulx, () the Community Director. +p?> +. + +/community/index.bml.title=Community Centre + +/community/join.bml.label.banned=The maintainer(s) of this community has/have banned you from joining. + +/community/join.bml.label.sure=Are you sure? + +/community/leave.bml.sure=Are you sure? + +/community/members.bml.key.admin=Maintainer + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Posting Access + +/community/moderate.bml.reject.reason=You can also explain to the poster your reasons for rejecting their entry. The reasons will be sent to the poster by email. + +/community/settings.bml.label.maintainer.login=If this is not the maintainer account, log in as somebody else. + +/community/settings.bml.label.nmheader=Non-Member Posting + +/create.bml.create.text=Creating a new LiveJournal is easy — just follow the instructions below! + +/create.bml.error.coppa.under13=Sorry, but due to COPPA restrictions, you cannot use the LiveJournal service until you + +/create.bml.error.email.nospaces=No spaces are allowed in an email address. If you're on AOL, remember that your Internet Email address is your screen name with all spaces removed, followed by @aol.com + +/create.bml.password.input.head2=Confirm password: + +/create.bml.success.text1=Your journal has been created. Important registration information has been emailed to [[email]] containing further instructions. Be sure to confirm your journal creation by clicking on the link sent to you in email. + +/create.bml.useacctcodes.entercode=To create a new account, enter an account creation code. For more information, see How do I create an account? + +/create.bml.username.charsallowed=Your username may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_). Additionally, it must not be longer than 15 characters. + +/customize/index.bml.s2.advanced.denied=Only paid, permanent, and early adopter account holders may use the advanced customisation area. Find out the benefits of getting a paid account. + +/customize/index.bml.s2.advanced.header=Advanced Customisations + +/customize/index.bml.s2.advanced.permitted=To create new layers and styles from scratch, visit the advanced customisation area. + +/customize/index.bml.s2.customize.header=Step 2: Customise Layout + +/customize/index.bml.s2.customize.settings=If you want to customise your journal further, here you can tweak individual settings to get it looking exactly how you want. + +/customize/index.bml.s2.customize.settings.delete=Remove Customisations + +/customize/index.bml.s2.customize.settings.edit=Edit Customisations + +/customize/index.bml.s2.customize.settings.new=Customise + +/customize/index.bml.title=Customise Journal + +/doc/tour/index.bml.modify.caption<< +It is also possible to format your journal in a number of different ways, by making use +of predefined styles and colour schemes. Make your journal as unique as you want! +. + +/editinfo.bml.allowshowcontact.about=You should keep this option enabled. This allows people to contact you by showing your email address, ICQ number, and AOL Instant Messenger screenname on your profile page. + +/editinfo.bml.autotranslate.header=Auto-convert older entries from: + +/editinfo.bml.bdayreminders.header=Send me birthday reminders (currently disabled) + +/editinfo.bml.bio.about=Here you can enter a little mini-biography about yourself. This will show up on your User Info page. + +/editinfo.bml.blockrobots.about<< +If you check this option, robots will be told to go away. +Not all robots respect the rules. + +. + +/editinfo.bml.enableboards.about=Check this if you want people to be able to reply to journal entries you post. + +/editinfo.bml.error.email.lj_domain<< +You cannot enter an @[[domain]] email address. +Enter your real address in that field. +If you're a paid user, your [[user]]@[[domain]] address will forward to your real address. +To choose which email address(es) are displayed publicly, see the option below the "Show your contact information" option. + +. + +/editinfo.bml.error.excessive_int<< +Sorry, you've listed too many interests. The limit is 150, but you've listed [[intcount]]. +Any changes you made to your interests were not saved. Go back and cut down your list, then save again. +. + +/editinfo.bml.error.locale.zip_requires_us<< +You entered a zip code but you did not select United States as your country. +We only collect zip code information about people in the US. +Please go back and remove the zip code or select United States as your country. + +. + +/editinfo.bml.error.tm.require_provider<< +If you're going to use text messaging, you must select your service provider. +If yours is not listed, please contact us with information about how your service's text messaging feature so we can add support for it. +. + +/editinfo.bml.getreplies.about=Check this if you want to get email updates when people reply to your journal entries using the message boards (comments). + +/editinfo.bml.howhear.about<< +Just for curiosity's sake, where did you hear about [[sitename]] from? +If it was a specific person, enter their username; if it +was from another source/article/link/website, enter the appropriate information. + +. + +/editinfo.bml.htmlemail.about<< +Check this if your email program fully supports HTML in your email. Some clients try to support it, but fail to display it properly. If you uncheck it, LiveJournal will only send text emails. + +. + +/editinfo.bml.mangleaddress.about<< +If you are afraid spam-robots will find your email +address on LiveJournal, select this option. Your email address will be modified so it won't be found by address-collecting robots. + +. + +/editinfo.bml.numcomments.about=Check this if you want to append the comment count to URLs, which may make your browser display the visited links in a different colour. + +/editinfo.bml.security.header=Who can view your contact info? + +/editinfo.bml.userpic.about=Below is the miniature picture you have uploaded to represent you throughout the LiveJournal site, in your journal, and in your friends' journals: + +/editinfo.bml.userpic.edit=To delete this picture, or upload a new one, go here. + +/editjournal.bml.btn.proceed=Proceed + +/editjournal.bml.viewwhat=View Which Entries?: + +/editjournal_do.bml.btn.delete=Delete Journal Entry + +/editjournal_do.bml.continue.head=Press to continue… + +/editjournal_do.bml.edit.text<< +This is the journal entry you selected to be edited. Change all the information you would like to modify, then click the "Save Journal Entry" button at the bottom.

      To delete the entry, delete all the text in the text box and click the "Save Journal Entry" button at the bottom. + +. + +/editjournal_do.bml.subject=Subject: (optional) + +/editjournal_do.bml.success.edit=Journal entry was modified. You can view it here. + +/export.bml.description=This feature lets you download your entire journal to a custom format for backup purposes. For more information about backing up your journal, see this FAQ. + +/friends/add.bml.add.text=User [[ljuser]] was added to your friend list. View your friends page. + +/friends/add.bml.colors.header=Colours + +/friends/add.bml.colors.hover=(Hover your mouse over a colour to see its name) + +/friends/add.bml.colors.text=You may also optionally select the colours that will represent [[user]] in your friends list. + +/friends/add.bml.error1.header=Log In First + +/friends/add.bml.error1.text<< +To add a user to your friends list you must first go and log in. If you don't +already have an account you can create one to track your friends' journals. +. + +/friends/add.bml.error2.text=Invalid or missing username given. To add a friend, go to the edit friends page. + +/friends/add.bml.error3.text=You already have [[user]] listed as a friend. However, you can modify the colours you've chosen to represent him/her. + +/friends/add.bml.groups.nogroup=No friend groups set up. + +/friends/add.bml.remove.text=User was removed from your friend list. You can view your friends page here. + +/friends/editgroups.bml.text=This page allows you to edit your custom friends groups. Custom friends groups are used for setting security on items and for filtering your friends page. For help, see What are custom friends groups? How do I use them? + +/friends/edit_do.bml.addfriends.text=Enter your friends' LiveJournal user names in the boxes below, and pick what background and foreground colours you want to associate with them.... + +/friends/edit_do.bml.bgcolor=Background Colour: + +/friends/edit_do.bml.hover=Hover your mouse over a colour to see its name + +/friends/edit_do.bml.mrcolor=Mr. Colour Viewer + +/friends/edit_do.bml.success.text=Your friends have been updated. You can view your newly updated friends page here. + +/friends/edit_do.bml.textcolor=Text Colour: + +/friends/edit_do.bml.viewer=Colour Viewer + +/friends/filter.bml.error.nogroups=You cannot filter your friends list because you must first set up your friend groups. + +/friends/index.bml.about<< +This page allows you to manage your friends list. +By adding other users to your friends list, you can easily see their entries from your friends page. You can also add communities and syndicated feeds to your friends list so that you see their entries on your friends page. +. + +/friends/index.bml.edit.about=Add or remove users from your friends list, or edit the colours used to represent them. + +/friends/index.bml.filter=These friend groups can be used to filter your friends view: you can view only the entries of a certain group. They can also be used for group-based security (see below). + +/friends/index.bml.filter.about=Filter your friends list according to specific subgroups. + +/friends/index.bml.security.only=With "Friends-Only" posts, any user on your friends list can view your post. + +/index.bml.frank.logo="Baaaaa", says Frank. + +/interests.bml.add.btn.text=Add [[interest]] + +/interests.bml.add.toomany.head=Sorry… + +/interests.bml.interested.in=Find people and communities interested in: + +/interests.bml.interests.text=Here are some fun things you can do with interests. + +/interests.bml.users.text=The following users are interested in [[interest]]. + +/legal/index.bml.about<< +LiveJournal is dedicated to offering a stable and meaningful experience for members from all +backgrounds and nations, so we have a few rules we've laid out to provide this. +Our documents here contain reasonable terms and information regarding how we will do our best to serve you, +and how we expect members to behave to us and others. LiveJournal works best when people +follow these rules. Here are some important ones to remember: +
        +
      • Do not harass, abuse, or threaten others.
      • +
      • Do not harm minors in any way.
      • +
      • Do not spam the site or any account on the site.
      • +
      • Do not post copyrighted content without permission.
      • +
      • Do not invade the privacy of others.
      • +
      • Do not violate U.S. law or your local laws in any way.
      • +
      +The complete list of rules and policies can be found below: +. + +/login.bml.expire.sessiononly.text=Your login will expire after you close your browser. If this is your own computer and you're the only user, you may want to set your login expiration such that it never expires: + +/login.bml.login.btn.login=Log in... + +/login.bml.login.head=Log in + +/login.bml.login.text1=To log in to [[sitename]], enter your username and password below. New Users: To create an account, go here. + +/login.bml.login.text2=You may also specify when your login expires. By default your login will expire when you close your browser, which is best on public computers. However, if you're the only user of your computer and nobody else has access to it, you may choose to remain logged in forever. For more information on this and other options, see What are the options when I log in? + +/login.bml.title=Log in + +/login.bml.whylogin.head=Why Log in? + +/logout.bml.killall.text=You have other active sessions. Do you want to expire all your sessions, and not just this one? (See this FAQ for more information.) + +/logout.bml.logout.btn=Log out + +/lostinfo.bml.lostpassword.text=If you've lost your password, enter your username and optionally, the email address you'd like the password sent to. In order to have your password sent to a previously listed email address, that address must have been validated. If you leave the email field blank, it will be mailed to your current address. + +/lostinfo.bml.lostpassword.title=Lost your password? + +/lostinfo.bml.lostusername.title=Lost your username? + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** This is an automated email. You do not need to respond to it. *** + +This is your requested password reminder from [[sitename]]. +Below are the username, password, and email address your journal is registered under. + + Username: [[username]] + Password: [[password]] + Email Address: [[emailadr]] +. + +/manage/index.bml.customization.customize.about=Change the appearance of your journal + +/manage/index.bml.friends.edit.about=Add or remove users from your friends list, or change the colours used to represent them. + +/manage/index.bml.information.status.about=Set your account's activation status (delete or undelete your account) + +/manage/phonepost.bml.phone=Authorised Phone Number: + +/manage/phonepost.bml.pin=Personal Identification Number: + +/manage/phonepost.bml.save=Save Settings + +/manage/phonepost.bml.title=Post by Phone Settings + +/modify_do.bml.colortheme.about=Here you can select what colour theme will be applied to the layout options you pick above. Or, if you don't like the provided colours, specify your own! + +/modify_do.bml.colortheme.color.head1=Colour + +/modify_do.bml.colortheme.customcolors=Custom Colours + +/modify_do.bml.colortheme.head=Colour Theme + +/modify_do.bml.domainalias.helptext=For this to work, you'll need to arrange to have your domain name's DNS point to the same IP address as [[sitename]]. For more information, see this FAQ. + +/modify_do.bml.journaloptions.about<< +From here you can customise the look of your LiveJournal pages. If you're really curious how everything works, read the developer information. Otherwise, we'll assume you're satisifed with the basic options below: + +. + +/modify_do.bml.moodicons.about=When posting journal entries you can also specify your current mood. Users have submitted different sets of mood icons that you can use, or you can select "None" if you don't want any pictures beside your moods. (of course, you don't even have to use the Current Mood feature at all.) + +/modify_do.bml.overrides.about=If you are happy with the journal layout options above, you can ignore this section. This is for tweaking very specific things about your page layout. See What are overrides? How do they work? for an overview, and visit the developer section for details. Also note that overrides are for overriding only one or two things about a style. If you'd like to override everything, you need to create your own style. For an overview of how to create a style, see How do I make a custom style? + +/modify_do.bml.overrides.note=Please note that not all style variables can be overridden. See the documentation for more details.
      Also, be aware that if you attempt to edit your overrides and you have used a tag that is not allowed in the head of the document -- such as <DIV>, <SPAN>, <IMG>, and many other tags -- that tag will be stripped. The only HTML elements that can be used in the *_HEAD overrides are those elements that are valid in the head of a HTML document. This is limited to <title>, <base>, <style>, <link>, and <meta>. + +/modify_do.bml.overrides.warning=THIS IS NOT WHERE YOU TYPE YOUR JOURNAL‼ + +/paidaccounts/index.bml.costs.rates.inexpensive<< +That works out to a little over $2/month (roughly £1.30) for the year plan. +That'll hardly break the bank. +The most annoying part will likely be pulling out your wallet, finding your credit card, and typing in your information. +. + +/paidaccounts/index.bml.features<< +
      To show appreciation for users who have made contributions, there are a number of features that are only available to paid accounts. These features include, but aren't limited to:
      + +
      New! Post by Email
      +
      Paid accounts can post to their journals and communities quickly and securely through our email gateway.
      + +
      Customising your Journal
      +
      In addition to just being able to pick the style of your journal and the colours, you'll also be able to create your own style using whatever HTML you like. This will also let you be able to make new styles that match your website that you can then easily embed, never revealing that you're using LiveJournal.com as your journal mechanism.
      + +
      Polls
      +
      Paid accounts have the ability to create polls in their own journals and in any communities they are a part of and can post to.
      + +
      More User Picture Icons
      +
      Paid accounts are allowed 15 user picture icons, rather than the 3 allotted to free users.
      + +
      LiveJournal.com Email Alias
      +
      Paid accounts are given a LiveJournal.com email address ([[username]]@livejournal.com) that can be turned on or off.
      + +
      Directory Searches
      +
      Paid accounts are given access to use the directory to search for other users.
      + +
      LiveJournal.com Subdomain
      +
      Instead of having your journal at +http://www.livejournal.com/users/[[username]]/, it'll also be available at http://[[username]].livejournal.com/, much shorter and more personal.
      + +
      Syndication
      +
      Paid accounts have the ability to create new syndicated accounts, which are RSS feeds that are incarnated on LiveJournal.
      + +
      Text Messaging Interface
      +
      Paid accounts are given access to the text messaging feature, which will allow them to receive text messages on their mobile phone or pager through LiveJournal's custom interface.
      + +
      More To-Do Items
      +
      Paid accounts can set up to 150 to-do list items in their to-do lists, and can set differing security levels on each item.
      + +
      Embedding
      +
      Paid accounts have access to the complete range of options for embedding your journal into your home page, as explained on the "Embedding" page.
      + +
      Domain Forwarding
      +
      Paid users can set up domain forwarding, so that their internet domain points to their LiveJournal.
      + +
      More...
      +
      For a complete list of Paid Account benefits, please read What are the Paid Account benefits?
      +. + +/paidaccounts/index.bml.whypay.header=I have to pay to use LiveJournal? + +/press/staff.bml.jproulx.quip=Geek to User Liaison + +/press/staff.bml.whitaker.title=Remote Developer + +/register.bml.email.body<< +This is the validation email you have requested. +To complete validation of your account, please visit this URL: + + [[conflink]] + +You may have to copy and paste this link into your browser's window. + +Regards, +[[sitename]] +[[sitelink]] +. + +/site/contract.bml.promise.account.about<< +Permanent accounts will be honored for the life of the site. Paid accounts will remain as +such until they expire or are renewed. Early adopters will be granted access to the paid +features that were freely available in the early history of the site. (This is with the exception of account termination due to Terms of Service +violation) +. + +/site/contract.bml.promise.spam.about<< +We strongly believe that spam has no place on the internet, and we promise to never send you any email without implied or implicit consent. We promise to never sell lists of users' email addresses or personal information, and we promise to never spam on the behalf of an interested +third party. +. + +/suggestions/index.bml.howto.text<< +
      +
      Check prior suggestions
      +First, read over past suggestions to make sure that something similar hasn't already been brought up. If it has, you can read the comments on the entry. Sometimes, things might look as though they've been ignored, but they might be in development. Sometimes, ideas are rejected or delayed due to other concerns. +
      +
      Couldn't find your idea? Share it with us!
      +The template must be used for all suggestions. Be sure to fill out all areas of the template, and make sure your suggestion is correct and complete before you post it. Also, the suggestion generator does not add in line breaks, so you can use the <br> tag to produce whitespace. This makes your suggestion easier to read. +
      +
      Submit It!
      +You can add the community to your Friends list here. Once a suggestion is posted, people will discuss it. If we think it's a good idea, it will be added to the list of developer projects, and will be worked on as time permits. Not all suggestions can be implemented immediately, so please be patient with the process. +
      +. + +/suggestions/index.bml.info.text<< +Feel that you can contribute to the implementation of your suggestions? Feel free to 'watch' or join the communities below: +
      +
      LiveJournal Developer's Forum -- talking about technical things.
      +
      +
      LiveJournal Business Forum -- talking about general LiveJournal business opportunities and related areas.
      +
      +
      LiveJournal User Documentation Forum -- discussing and editing most forms of end user documentation.
      +
      +
      LiveJournal Art Forum -- discussing and sharing icons, mood themes, colour themes and userpics.
      +
      +
      +Please remember that the people who implement LiveJournal changes and additions are fellow users like yourself. These things can take time and the more you can help with implementing, the more that can be achieved. +. + +/suggestions/index.bml.rules<< +There are a few things to keep in mind: +
        +
      • Many suggestions have already been proposed and discussed, but simply not implemented yet. Be sure that you're not submitting a duplicate.
      • +
      • Flaming will not be tolerated. Everyone has different ideas about how LiveJournal should work; remember that promoting your opinion is all right, but flaming someone else's opinion is not.
      • +
      • Be as thorough as possible with your suggestion. A suggestion that contains detailed implementation notes is more likely to be accepted than one that doesn't. You don't need to know how to program; just try to think about what else your idea would affect, and bring up any problems you can see with it.
      • +
      • Be sure to read the FAQs first, to see if your idea already exists, or if an existing aspect of the site can be used to do what you want.
      • +
      • If you want to ask a question about how LiveJournal works, aren't certain if something exists or not, or are having a problem, don't submit a suggestion. Ask Support instead.
      • +
      +. + +/support/append_request.bml.bounce.toomany=You can only send to up to five email addresses. You have specified more than five. + +/support/append_request.bml.internal.touch=To change a request's status, you must select "Internal Comment / Action" and explain why you're changing it. + +/support/append_request.bml.successlinks<< + +. + +/support/help.bml.interim<< + + + + +Getting +Started category in HelpScreening's memories +is an especially good place for new +volunteers to get information. p?> + + + +
      • Be professional and courteous.
      • +
      • Don't contact people submitting requests outside the Support +board to discuss their request or give them information.
      • +
      • Keep information in Support requests private.
      • +
      • Don't copy other people's answers.
      + + + +, but +please wait until there is an approved answer in the request. p?> + + + + + +Support +board. p?> +. + +/support/see_overrides.bml.error.noprivs=Only users with the supportviewscreened or supporthelp privilege can view another user's overrides. + +/syn/index.bml.loginrequired.text=To manage your syndicated accounts, first log in. + +/talkmulti.bml.error.comms_deleted=One of the comments has been deleted since you selected it. For security reasons, please go back and try again. + +/talkpost.bml.loginq=Log in? + +/talkpost.bml.opt.friendsonly=- this user has disabled anonymous and non-friend posting. You may post here if [[username]] lists you as a friend. + +/talkpost.bml.title=Post a Comment + +/talkpost_do.bml.error.badpassword=Incorrect password given for the username specified. If you've forgotten your password, you can recover it. + +/talkpost_do.bml.error.badusername=The LiveJournal username you specified does not exist. If you've forgotten your username, you can recover it, or you may post as "Anonymous" instead. + +/talkpost_do.bml.error.blankmessage=Your message was blank. Please type something in the message field. + +/talkpost_do.bml.error.noauth=You are not allowed to reply to this protected entry. + +/talkpost_do.bml.error.noverify=Sorry, you aren't allowed to post comments in other people's journals until your email address has been verified. If you've lost the confirmation email to do this, you can have it re-sent. + +/talkpost_do.bml.preview=This is how your comment will look when posted. Using the form below, you can edit your comment further, or you can submit it as-is. + +/talkpost_do.bml.success.message=Your comment has been added. You can view it here. + +/talkpost_do.bml.title=Comment Posted + +/talkscreen.bml.screened.body=The comment has been screened. You can view it here. + +/talkscreen.bml.unscreened.body=The comment has been unscreened. You can view it here. + +/tools/emailmanage.bml.desc.text=This page lets you remove past email addresses that were used with your account. If you remove an address, it will no longer be possible to have your password mailed to that address. This is useful if somebody discovered your password and hijacked your journal. Simply have the new password mailed to your old address, change the password, and remove the attacker's email address. + +/tools/emailmanage.bml.notvalidated.text=To use this tool, your current email address, [[email]] , must be validated. If you've lost the confirmation email to do this, you can have it re-sent. After you validate your email, come back here. + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.error.login=You must be logged in to use this feature. Go and log in and you'll be brought back here. + +/tools/memadd.bml.error.maxsize=The keyword "[[keyword]]" exceeds the maximum allowed size. + +/tools/memadd.bml.keywords.text=Why is this post memorable? Enter up to five comma separated keywords or categories so you can find it later. + +/tools/memories.bml.body.keyword<< + +[[user]] found memorable. p?> + +. + +/tools/memories.bml.body.list_categories<< + +[[user]] has placed memorable journal entries in. p?> + +. + +/tools/memories.bml.body.memorable=The following is a list of uncategorised journal entries that user [[user]] found memorable. + +/tools/memories.bml.error.noentries.body<< +This could be because:
        +
      1. the user hasn't defined any memorable events,
      2. +
      3. the user's memorable events are protected and you don't have access to view them, or
      4. +
      5. the user doesn't have any memories that match your filter criteria.
      + +. + +/tools/memories.bml.uncategorized=Uncategorised + +/update.bml.note=Note: The time and date above are from our server. Correct them for your timezone before posting. + +/update.bml.opt.spellcheck=Spell-check entry before posting (checker only supports US English) + +/update.bml.subject=Subject: (optional) + +/update.bml.update.success=Update successful. You can view your updated journal here. + +/userinfo.bml.about.comm=About: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.error.malfname=Malformed username: too long, or contains invalid characters. + +/userinfo.bml.error.notloggedin=If you wish to view your own user profile, you need to log in. + +/userinfo.bml.friendof.comm=Watched by: + +/userinfo.bml.friendof.user=Friend of: + +/userinfo.bml.friends.user=Friends + +/userinfo.bml.label.interests.modifyyours=Modify yours + +/userinfo.bml.label.interests.removesome=Remove some + +/userinfo.bml.label.shared=Posting Access: + +/userinfo.bml.nonexist.body=The username [[user]] is not currently registered. + +/userinfo.bml.syn.parseerror=Error Message: + +error.noremote=You have to log in in order to use this page. + +error.purged.text=This journal has been deleted and purged. + +error.suspended.text=This account has been either temporarily or permanently suspended. If you are [[user]], please refer to the FAQ entitled My account has been suspended! How can I get it back? for more information. Please note that in order to maintain our users' privacy, [[sitename]] cannot discuss the reasons for any suspension with anyone except the account's owner. + +error.usernamelong=Username is too long — usernames may not be longer than 15 characters. + +portal.recent.items.description=By default, only the most recent entry is shown. + +talk.error.bogusargs=Invalid parameters + +talk.error.notauthorised=You are not allowed to view this protected entry. + +talk.spellcheck=Check spelling during preview + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_english + +xcolibur.nav.manage=Manage + +xcolibur.nav.manage.customize=Customise + diff --git a/ljcom/bin/upgrading/en_LJ.dat b/ljcom/bin/upgrading/en_LJ.dat new file mode 100644 index 0000000..7b0fc0f --- /dev/null +++ b/ljcom/bin/upgrading/en_LJ.dat @@ -0,0 +1,2103 @@ +;; -*- coding: utf-8 -*- +/changepassword.bml.changepassword.instructions=Fill out the form below to change your password. For help with choosing a good password and keeping your account secure, see this FAQ. + +/changepassword.bml.email.body<< +Your password has been changed at [[sitename]]. + +To retrieve it in the future, visit: + + [[siteroot]]/lostinfo.bml + +Regards, +[[sitename]] Team +[[siteroot]] +. + +/changepassword.bml.error.badnewpassword=Your new password confirmation does not match your new password. You may have made a mistake in typing. Please type and confirm your new password again. + +/changepassword.bml.error.notvalidated=You cannot change your password if your current e-mail address has not been validated. Please see the FAQ for instructions on doing this. + +/changepassword.bml.proceed.instructions=Press the button below and your password will be changed. You will receive an e-mail noting the password change. + +/changepassword.bml.success.text=Your password has been changed and an e-mail has been sent to you with a reminder message. + +/community/index.bml.main<< + + + + +The 'Newbies' Lounge, where you'll find answers to many of the questions you may have. Visit , explore a bit, and you'll be a pro in no time at all! +p?> + + +
      +Add to your friends page to keep up with events and issues that are relevant to the entire LiveJournal community.
      +Add to your friends page to be informed when downtime is planned, and reports on unplanned interruptions of service. +p?> + + +AIM, ICQ, Yahoo!, MSN, or Jabber instant messengers. If you do, be sure to list it in your personal info settings. If you have a Paid Account, you can also enable your cell phone or pager to receive text messages. +p?> + + +Paid Account. There are, of course, loads of other ways you help out. +

      +LiveJournal is an Open Source project; if you have experience with programming languages or server side applications you can check out the LiveJournal Development Community, . If you have ideas about how LiveJournal could be better, check out the LiveJournal Suggestions Area, . If you would like to help with just about anything, visit the LiveJournal Business Community, . If you like helping people, visit our technical support center and help someone out. If you are savy with graphic design, check out the LiveJournal Art Community, . +p?> + + +Anime to Zen Buddhism, from Astronomy to Zim. You'll also find regional communities for places all around the world. There's probably a LiveJournal community for where you live too! +p?> + + +FAQ that will explain how to create your very own community. There are also two FAQ Categories (General Community FAQs and Community Management FAQs) covering just about everything you'll ever need to know about communities. If you still need more information, feel free to submit a support request. +p?> + + + + +
        +
      • Community Search
      • +
      • Check out the Promotions Community ()
      • +
      • Check out the Search Community ()
      • +
      + + +E-mail Jesse Proulx, () the Community Director. +p?> +. + +/community/join.bml.label.allowposting=This community allows posting by all members, so you now have access to post in it. If you already have a LiveJournal client open on your computer, you'll have to log out and log back in for this journal to show up in your list of journals you can post to. + +/community/members.bml.error.alreadysent=[[user]] could not be added because they were already sent a confirmation e-mail on [[datetime]]. Please wait for them to respond. + +/community/members.bml.key.admin=Maintainer + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Posting Access + +/community/moderate.bml.reject.reason=You can also explain to the poster your reasons for rejecting their entry. The reasons will be sent to the poster by e-mail. + +/community/search.bml.label.city=City: + +/community/settings.bml.label.anybodycan=All Members
      Anybody can post immediately once a member. + +/community/settings.bml.label.commcreate=This is the account that you want to turn into a community. It must already be created, but should not already be in use by an individual, because after this, many different people will potentially be able to post in it. + +/community/settings.bml.label.createtext=From here you can create a community account. A community is a special type of account that other users can join and post in. For an example of a community, check out the Seattle Party Community. + +/community/settings.bml.label.maintainer.login=If this is not the maintainer account, log in as somebody else. + +/community/settings.bml.label.nmheader=Non-Member Posting + +/community/settings.bml.label.selcan=Select Members
      Only some members are able to post, once they've been given access by the maintainer account. + +/create.bml.email.head=Your e-mail address + +/create.bml.email.input.head=E-mail Address: + +/create.bml.email.text2=For verification and security purposes, we need your e-mail address. It will never ever, under any circumstances, be sold or given away to spammers. We hate that more than anything. Read our privacy policy for more information. + +/create.bml.error.email.blank=You must provide your e-mail address. + +/create.bml.error.email.lj_domain=You cannot use a [[domain]] alias when creating an account. Please enter a different e-mail address. + +/create.bml.error.email.nospaces=No spaces allowed in e-mail address. If you're on AOL, remember that your Internet E-mail address is your screen name with all spaces removed, followed by @aol.com. + +/create.bml.error.username.purged=The username you entered is that of an account which has been deleted and purged. If you wish to use this username you must first purchase a rename token for an existing account. + +/create.bml.initial.friend.lj_maintenance=Reports of both planned & unplanned downtimes and maintenance + +/create.bml.initial.friend.news=LiveJournal news and events + +/create.bml.password.input.head2=Confirm password: + +/create.bml.password.secure=You must choose a secure password that is not based on a dictionary word, your username, or your email address. + +/create.bml.success.text1=Your journal has been created. Important registration information has been e-mailed to [[email]] containing further instructions. Be sure to confirm your journal creation by clicking on the link sent to you in e-mail. + +/create.bml.useacctcodes.entercode=To create a new account, enter an account creation code. For more information, see How do I create an account? + +/create.bml.username.charsallowed=Your username may contain only lower-case letters (a-z), digits (0-9) and the underscore character (_).
      Additionally, it must not be longer than 15 characters. + +/customize/index.bml.s2.advanced.denied=Only paid, permanent, and early adopter account holders may use the advanced customization area. Find out the benefits of getting a paid account. + +/customize/index.bml.s2.customize.language=The following languages are fully or partially supported by this layout. + +/developer/index.bml.clients<< +So you want to create or improve a LiveJournal client on your platform? Wonderful! +Below are some necessary resources to let you know how LiveJournal works. +. + +/developer/index.bml.clients.header=Writing LiveJournal Clients + +/developer/index.bml.clients.links<< +
      +
      LiveJournal Server<->Client Protocol
      +
      Learn how the LiveJournal client on your desktop talks to the LiveJournal server and vice versa. + Understanding this is the primary thing you need to understand before developing or improving + a client for your platform.
      +
      Complete Protocol Docs
      +
      All the different protocol modes & methods.
      +
      List of Clients
      +
      A list of most clients used to connect to LiveJournal. The majority of these clients are + open source, and all of them are free to use. This is a great place to get examples for your + client.
      +
      +. + +/developer/index.bml.code<< +To see the backend that makes LiveJournal tick, and to see the innards of a few +of the available clients, go to the Code page. +. + +/developer/index.bml.code.header=LiveJournal Code Repository + +/developer/index.bml.dbschema<< +Curious about the database schema? +The SQL to create all the tables and populate them is included with the server code. +. + +/developer/index.bml.dbschema.header=Database Schema + +/developer/index.bml.embedding<< +Want to embed your journal right into your homepage? There are +several ways to do it, depending on what sort of control +you have over your server. You only have to worry about this if you don't like having +www.livejournal.com appear in your journal URL. +. + +/developer/index.bml.embedding.header=Embedding LiveJournal + +/developer/index.bml.notice.header=Notice + +/developer/index.bml.notice1<< +The following information is intended for programmers and advanced users only. +If you just want to use LiveJournal to keep your journal, great! Normal users +do not have to worry about this stuff. +. + +/developer/index.bml.notice2<< +That said, the content below is split up into two sections: information on how +to customize the look of LiveJournal pages, and information on writing +LiveJournal clients to the LiveJournal server. +. + +/developer/index.bml.styles<< +Don't like the way your journal pages look? Never you fear... everything is +flexible and if you read the documentation below you'll know all you need to make +your pages look any which way you want. +. + +/developer/index.bml.styles.header=Customizing the look of a LiveJournal + +/developer/index.bml.styles.s1.header=Style System 1 + +/developer/index.bml.styles.s1.system=Style System + +/developer/index.bml.styles.s1.system.about=General overview of how the first style system is setup. + +/developer/index.bml.styles.s1.varlist=Variable List + +/developer/index.bml.styles.s1.varlist.about=Straight alphabetical list of all variables that you can customize. + +/developer/index.bml.styles.s1.views=View Types + +/developer/index.bml.styles.s1.views.about=A list of the different types of ways you can view your journal, and details on each. + +/developer/index.bml.styles.s2.header=Style System 2 + +/developer/index.bml.styles.s2.layerbrowse=S2 Layer Browser + +/developer/index.bml.styles.s2.layerbrowse.about<< +A full list of public S2 layers that comprise the S2 system styles. Of importance here +are the core layers, that define the base variables, functions, and classes that make +S2 the powerful design language that it is. +. + +/developer/index.bml.styles.s2.manual=The S2 Manual + +/developer/index.bml.styles.s2.manual.about=Comprehensive information about using S2 on LiveJournal. + +/developer/index.bml.title=Developer Information + +/doc/index.bml.about<< +Welcome to LiveJournal's documentation repository, where you can find information +on most topics regarding LiveJournal's service or server software. Please select +a topic from below: +. + +/doc/index.bml.about.header=Welcome + +/doc/index.bml.docs.faq.about=Frequently Asked Questions about LiveJournal.com + +/doc/index.bml.docs.faq.title=FAQ + +/doc/index.bml.docs.guides.about=Supplemental FAQ information + +/doc/index.bml.docs.guides.title=Guides + +/doc/index.bml.docs.header=Documents + +/doc/index.bml.docs.howto.about=Tips and tricks to help customize your LiveJournal account + +/doc/index.bml.docs.server.about=All you need to know to install, administrate, and hack a LiveJournal setup + +/doc/index.bml.docs.server.title=LiveJournal Server Manual + +/doc/index.bml.docs.tour.about=Designed for new visitors to become familiar with the site + +/doc/index.bml.docs.tour.title=Tour + +/doc/index.bml.title=Documentation + +/doc/index.bml.volunteering.about=If you'd like to help out with LiveJournal's documentation, check out the following forums: + +/doc/index.bml.volunteering.header=Volunteering + +/doc/index.bml.volunteering.ljsysdoc=Discussions regarding the LiveJournal documentation system + +/doc/index.bml.volunteering.ljuserdoc=End user documentation discussions + +/doc/tour/index.bml.clients.caption<< +LiveJournal clients are small programs that run on your computer, allowing you to update your journal +whenever you're online, without having to open a browser window. +Clients are available for just about any platform, and many are easily customizable. +. + +/doc/tour/index.bml.clients.title=Clients + +/doc/tour/index.bml.comms.caption<< +LiveJournal is a large interactive community, so it shouldn't be a surprise that there are many members +with similar interests. To this end, we offer the ability to create communities, or journals that many +people can post to. +. + +/doc/tour/index.bml.comms.title=Communities + +/doc/tour/index.bml.create.caption<< +LiveJournal is a membership-based journaling community. This page explains what membership entails, +why membership is important, and the benefits of membership. It also includes a form to create +your own account. +. + +/doc/tour/index.bml.create.title=Creating an Account + +/doc/tour/index.bml.friends.caption<< +You can keep track of your friends through LiveJournal as well, by using the built–in "friends" feature. +If you find a journal you think is interesting, add it to your friends list, which will let you read all of +your friends' entries from the same page. +. + +/doc/tour/index.bml.friends.title=Friends + +/doc/tour/index.bml.intro.caption<< +This tour is designed for new visitors to become familiar with the site. +It will show you where the most important sections are located, as well +as some of the more interesting features. +. + +/doc/tour/index.bml.intro.title=Welcome + +/doc/tour/index.bml.modify.caption<< +It is also possible to format your journal in a number of different ways, by making use +of predefined styles and color schemes. Make your journal as unique as you want! +. + +/doc/tour/index.bml.modify.title=Personalizing + +/doc/tour/index.bml.nav.next=Next --> + +/doc/tour/index.bml.nav.prev=<-- Prev + +/doc/tour/index.bml.profile.caption<< +LiveJournal members are encouraged to add information about themselves into their profiles, so that +we can get an idea of who uses the site and how we can best serve them. However, none of this is required +— the only information that is required to start using LiveJournal is a name, an e-mail address, and a password. +. + +/doc/tour/index.bml.profile.title=Profiles + +/doc/tour/index.bml.sitemap.caption<< +Hopefully this tour gave you some helpful starting information about the LiveJournal site and service. +If you need help with anything LiveJournal related, feel free to contact +our support department. If you want to explore further, please +refer to the site map to see a list of all the pages on this site. +. + +/doc/tour/index.bml.sitemap.title=Site Map + +/doc/tour/index.bml.support.caption<< +The support page lists areas that help explain what LiveJournal is, +frequently asked questions about the site, and other helpful information +about the service, the company, and the community at large. +. + +/doc/tour/index.bml.support.title=Getting Help + +/doc/tour/index.bml.title=Tour - [[title]] + +/doc/tour/index.bml.update.caption<< +Updating a LiveJournal is the core of the LiveJournal service; here is where we offer members a chance to share their +lives and say what's on their minds. Updating a journal is simple. Simply write an entry in the supplied +box and press the "Update Journal" button. Of course, we also offer advanced features on our update page, like +the ability to check for spelling mistakes, and the ability to supply extra information about your +entries, such as your current music or current mood. +. + +/doc/tour/index.bml.update.title=Updating + +/editinfo.bml.allowshowcontact.about<< +You should keep this option enabled. This lets other people be able to contact +you by showing your e-mail address, ICQ number, and AOL Instant Messenger screenname +all on your LiveJournal. +. + +/editinfo.bml.allowshowcontact.email=If visible, e-mail address to be displayed: + +/editinfo.bml.allowshowcontact.email.neither=Neither. Don't show any e-mail address. + +/editinfo.bml.allowshowcontact.email.no_show=Don't show e-mail address + +/editinfo.bml.allowshowcontact.email.show=Show e-mail address + +/editinfo.bml.allowshowcontact.email.withdomainaddr<< +With the option above, you may also choose to hide your e-mail address +(while still showing other contact information), only show your +LiveJournal e-mail address (paid accounts +only), only show your real address, or show them both. +. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr<< +With the option above, you may also choose to hide your e-mail address +(while still showing other contact information). +. + +/editinfo.bml.autotranslate.header=Auto-convert older entries from: + +/editinfo.bml.bdayreminders.about=If you want to get e-mail reminding you of birthdays for your friends on LiveJournal, click this box. + +/editinfo.bml.bdayreminders.header=Send me birthday reminders (currently disabled) + +/editinfo.bml.bio.about=Here you can enter a little mini-biography about yourself. This will show up on your User Info page. + +/editinfo.bml.blockrobots.about<< +If you check this option, robots will be told to go away. +Not all robots respect the rules. +. + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=Check this if you want people to be able to reply to journal entries you post. + +/editinfo.bml.error.email.lj_domain<< +You cannot enter an @[[domain]] e-mail address. +Enter your real address in that field. +If you're a paid user, your [[user]]@[[domain]] address will forward to your real address. +To choose which e-mail address(es) are displayed publicly, see the option below the "Show your contact information" option. +. + +/editinfo.bml.error.email.none=You must provide your e-mail address. + +/editinfo.bml.error.email.no_space<< +No spaces are allowed in an e-mail address. +If you're on AOL, remember that your Internet E-mail address is your screen name with all spaces removed, followed by @aol.com +. + +/editinfo.bml.error.locale.zip_requires_us<< +You entered a zip code but you did not select United States as your country. +We only collect zip code information about people in the US. +Please go back and remove the zip code or select United States as your country. +. + +/editinfo.bml.error.tm.require_provider<< +If you're going to use text messaging, you must select your service provider. + +If yours is not listed, please contact us with information about how your service's text messaging feature so we can add support for it. +. + +/editinfo.bml.getreplies.about=Check this if you want to get e-mail updates when people reply to your journal entries using the message boards (comments). + +/editinfo.bml.getselfemails.about=Check this if you wish to get an e-mail every time you post a comment in a journal or community. You will not get e-mail for anonymous comments. + +/editinfo.bml.getselfemails.header=Get comments you post e-mailed to you + +/editinfo.bml.howhear.about<< +Just for curiosity's sake, where did you hear about [[sitename]] from? +If it was a specific person, enter their username; if it +was from another source/article/link/website, enter the appropriate information. +. + +/editinfo.bml.htmlemail.about<< +Check this if your e-mail program fully supports HTML in your e-mail. +Some clients try to support it, but fail to display it properly. +If you uncheck it, LiveJournal will only send text e-mails. +. + +/editinfo.bml.htmlemail.header=Send HTML E-mails + +/editinfo.bml.mangleaddress.about<< +If you are afraid spam-robots will find your e-mail +address on LiveJournal, select this option. Your e-mail address will be modified +so it won't be found by address-collecting robots. +. + +/editinfo.bml.mangleaddress.header=Mangle your displayed e-mail address + +/editinfo.bml.newemail.body2<< +You have just changed the e-mail address for your [[sitename]] account "[[username]]". To validate the change, please go to this address: + +[[conflink]] + +Regards, +[[sitename]] Team +[[sitelink]] +. + +/editinfo.bml.newemail.subject=E-mail Address Changed + +/editinfo.bml.opt_in.about<< +If you want to know when we add some cool new feature to LiveJournal, check this box. +We aren't currently using this feature, but we might in the future. +Your e-mail address will not be visible to other users, and you can turn this off at anytime. +. + +/editinfo.bml.security.header=Who can view your contact info? + +/editinfo.bml.translatemailto.about<< +In case you chose to receive message board replies by e-mail, and your e-mail client doesn't handle Unicode (UTF-8) +messages very well, use this option to specify a different encoding into which LiveJournal will automatically translate the text of comments sent to you. +. + +/editinfo.bml.translatemailto.header=Translate e-mail notifications into: + +/editinfo.bml.userpic.about<< +Below is the miniature picture you have uploaded to represent you +throughout the LiveJournal site, in your journal, and in your friends' journals: +. + +/editinfo.bml.userpic.edit=To delete this picture, or upload a new one, go here. + +/editjournal_do.bml.btn.delete=Delete Journal Entry + +/editjournal_do.bml.currmood=Current Mood: + +/editjournal_do.bml.edit.text=This is the journal entry you selected to be edited. Change all the information you would like to modify, then click the "Save Journal Entry" button at the bottom.

      To delete the entry, delete all the text in the text box and click the "Save Journal Entry" button at the bottom. + +/editjournal_do.bml.error.modify=An error occurred modifying your journal: + +/editjournal_do.bml.opt.noemail=Don't e-mail comments: + +/editjournal_do.bml.subject=Subject: (optional) + +/export.bml.description=This feature lets you download your entire journal to a custom format for backup purposes. For more information about backing up your journal, see this FAQ. + +/friends/add.bml.add.text=User [[ljuser]] was added to your friend list. You can view your friends page here. + +/friends/add.bml.error1.header=Log In First + +/friends/add.bml.error1.text<< +To add a user to your friends list you must first go and log in. If you don't +already have an account you can create one to track your friend's journals. +. + +/friends/add.bml.error2.text=Invalid or missing username given. To add a friend, go to the edit friends page. + +/friends/add.bml.groups.nogroup=No friend groups set up. + +/friends/add.bml.remove.text=User was removed from your friend list. You can view your friends page here. + +/friends/editgroups.bml.text<< +This page allows you to edit your custom friends groups. Custom friends groups are used for setting security on items and for filtering your friends page. For help, see What are custom friends groups? How do I use them? + +This page requires JavaScript to work. +. + +/friends/edit_do.bml.fellowfriends.text=The following people have listed you as a friend. You may want to list them as your friend too. This is provided as a reference, so that you know their LiveJournal usernames. You are under no obligation to add them to your list. + +/friends/edit_do.bml.success.text=Your friends have been updated. You can view your newly updated friends page here. + +/friends/filter.bml.error.nogroups=You cannot filter your friends list because you must first set up your friend groups. + +/friends/index.bml.about<< +This page allows you to manage your friends list. +By adding other users to your friends list, you can easily see their entries from your friends page. You can also add communities and syndicated feeds to your friends list so that you see their entries on your friends page. +. + +/friends/index.bml.edit.about=Add or remove users from your friends list, or edit the colors used to represent them. + +/friends/index.bml.editgroups.about=Create, edit, or delete subgroups of your friends. + +/friends/index.bml.filter=These friend groups can be used to filter your friends view: you can view only the entries of a certain group. They can also be used for group-based security (see below). + +/friends/index.bml.filter.about=Filter your friends list according to specific subgroups. + +/friends/index.bml.security=Your friends list is also used for entries with restricted access. You can find out more about friends list security at Friends & Security Levels. + +/friends/index.bml.security.custom=With "Custom" entries, you can specify which friend groups can view your entry. However, not all clients currently support custom security. + +/friends/index.bml.security.only=With "Friends-Only" entries, any user on your friends list can view your entries. + +/friends/popwithfriends.bml.account_type=Sorry, your account type doesn't permit you to use this tool. + +/friends/popwithfriends.bml.count=Count + +/friends/popwithfriends.bml.exclude_own=Optionally, you may exclude your friends. + +/friends/popwithfriends.bml.include_own=Optionally, you may include your friends. + +/friends/popwithfriends.bml.intro=The following friends are listed often by your friends, but not by you. + +/friends/popwithfriends.bml.intro_own=The following friends are listed often by your friends. The list also includes your own friends. + +/friends/popwithfriends.bml.no_users=No users + +/friends/popwithfriends.bml.title=Popular Users Amongst Your Friends + +/friends/popwithfriends.bml.user=User + +/index.bml.about.header=About LiveJournal + +/index.bml.about.joining=Joining the site is free. Users can choose to upgrade their accounts for extra features. + +/index.bml.about.us=LiveJournal is a simple-to-use (but extremely powerful and customizable) personal publishing ("blogging") tool, built on open source software. + +/index.bml.boldcreate=Create your own LiveJournal! + +/index.bml.frank.image.alt=Frank, the LiveJournal mascot goat. + +/index.bml.frank.logo="Baaaaah", says Frank. + +/index.bml.learnmore.header= Want to learn more? + +/index.bml.learnmore.text=Please read our feature overview. Convinced? Create your own LiveJournal! + +/index.bml.meta.desc=LiveJournal.com is a place where you can share your thoughts with the world. + +/index.bml.meta.keywords=diary, journal, online journal, diaries, writing, online diary, web diary + +/index.bml.news.text=The latest site news: + +/index.bml.news.title=Latest News + +/index.bml.post=Live Post Stats + +/index.bml.post.hour=Per Hour: + +/index.bml.post.latest=Latest Posts + +/index.bml.post.min=Per Minute: + +/interests.bml.add.btn.text=Add [[interest]] + +/interests.bml.interested.in=Find people and communities interested in: + +/interests.bml.interests.text=Here are some fun things you can do with interests. + +/interests.bml.morestuff=More fun stuff can be found on the interests page. + +/interests.bml.users.text=The following users are interested in [[interest]]. + +/invite/index.bml.code=Code + +/invite/index.bml.error=Error + +/invite/index.bml.genmore=Generate more codes + +/invite/index.bml.how_detail=Depending on a number of factors, existing users are allowed to invite a certain number of other users to join the site. To invite somebody you need to generate an invitation code and then give it to them. + +/invite/index.bml.how_header=How does it work? + +/invite/index.bml.invite_header=Invitations? + +/invite/index.bml.none=None + +/invite/index.bml.redeemed=Redeemed by + +/invite/index.bml.title=Invite others to LiveJournal... + +/invite/index.bml.unused=Unused + +/invite/index.bml.use=use + +/invite/index.bml.why_codes=As a means to keep the community tight, control growth, and prevent abuse, creating an account now requires either buying an account or getting invited by an existing user. The point of this is to make this community a better place for the people that use it, at the added cost of a little inconvenience for new users. + +/legal/dmca.bml.title=Copyright Information (DMCA) + +/legal/index.bml.about<< +LiveJournal is dedicated to offering a stable and meaningful experience for members from all +backgrounds and nations, so we have a few rules we've laid out to provide this. +Our documents here contain reasonable terms and information regarding how we will do our best to serve you, +and how we expect members to behave to us and others. LiveJournal works best when people +follow these rules. Here are some important ones to remember: +
        +
      • Do not harass, abuse, or threaten others.
      • +
      • Do not harm minors in any way.
      • +
      • Do not spam the site or any account on the site.
      • +
      • Do not post copyrighted content without permission.
      • +
      • Do not invade the privacy of others.
      • +
      • Do not violate U.S. law or your local laws in any way.
      • +
      +The complete list of rules and policies can be found below: +. + +/legal/index.bml.about.header=Overview + +/legal/index.bml.docs.dmca.about<< +The Digital Millenium Copyright Act (DMCA) describes the manner in which +service providers must react to copyright infringement. Our DMCA page +describes how you may notify us that a user on our service is infringing +upon your copyright. +. + +/legal/index.bml.docs.header=Documents + +/legal/index.bml.docs.privacy.about2<< +The Privacy Policy outlines what information we gather from our members +and explains how we use that information. This page also describes how +we handle the Children's Online Privacy Protection Act (COPPA) and our +policies about children on our site. +. + +/legal/index.bml.docs.tos.about<< +The Terms of Service outlines our usage policies, as well as the general terms and conditions +of membership. Membership and/or use of the system constitutes an agreement to abide by these +and all other agreed-upon terms. +. + +/legal/index.bml.title=Legal Information + +/legal/privacy.bml.title=Privacy Policy + +/legal/tos.bml.title=Terms of Service + +/login.bml.expire.sessiononly.text=Your login will expire after you close your browser. If this is your own computer and you're the only user, you may want to set your login expiration such that it never expires: + +/login.bml.login.btn.login=Log in... + +/login.bml.login.head=Log in + +/login.bml.login.text1=To log in to [[sitename]], enter your username and password below. New Users: To create an account, go here. + +/login.bml.login.text2=You may also specify when your login expires. By default your login will expire when you close your browser, which is best on public computers. However, if you're the only user of your computer and nobody else has access to it, you may choose to remain logged in forever. For more information on this and other options, see What are the options when I log in? + +/login.bml.login.text3=[[username]], you are now logged in to [[sitename]]. Feel free to browse the site by using our Site Map. + +/login.bml.title=Log in + +/login.bml.whylogin.head=Why log in? + +/logout.bml.killall.text=You have other active sessions. Do you want to expire all your sessions, and not just this one? (See this FAQ for more information.) + +/logout.bml.logout.btn=Log out + +/lostinfo.bml.enter_email=Enter your e-mail address: + +/lostinfo.bml.enter_email_optional=E-mail address: (optional) + +/lostinfo.bml.error.no_email=You must enter an e-mail address in order to recover your username. + +/lostinfo.bml.lostpassword.text=If you've lost your password, enter your username and optionally the e-mail address you'd like the password sent to. In order to have your password sent to a previously listed e-mail address, that address must have been validated. If you leave the e-mail field blank, it will be mailed to your current address. + +/lostinfo.bml.lostpassword.title=Lost your password? + +/lostinfo.bml.lostusername.text=If you've lost your username, enter your e-mail address and we'll send you your username. + +/lostinfo.bml.lostusername.title=Lost your username? + +/lostinfo_do.bml.error.no_usernames_for_email=No username(s) for this e-mail address: [[address]] . + +/lostinfo_do.bml.error1.text=You never used that e-mail address with this account or it was never validated. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** This is an automated e-mail. You do not need to respond to it. *** + +This is your requested password reminder from [[sitename]]. +Below are the username, password, and e-mail address your journal is registered under. + + Username: [[username]] + Password: [[password]] + E-mail Address: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=To validate your e-mail address, go here: + +/lostinfo_do.bml.lostpasswordmail.part3<< +This information was requested on the website from [[remoteip]]. + +If you didn't request to have this password e-mailed to you, don't panic. +After all, you're the one who's seeing this e-mail, and not the other person. +It's possible that the user who made the request is mistaken and +believes that he or she controls this username. It's also possible that +someone made a typo in a username or e-mail address. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +If you truly believe that your account isn't secure, read + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +for some information on how to re-secure it. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Useful links: + + Your LiveJournal: + [[journalurl]] + + Update your journal online: + [[updateurl]] + +Regards, +LiveJournal Team + +[[rooturl]] +. + +/manage/index.bml.customization.customize.about=Change the appearance of your journal and switch between S1 and S2 style systems + +/manage/index.bml.customization.moodtheme.editor=Create and edit your custom mood themes + +/manage/index.bml.customization.moodtheme.editor.header=Mood Theme Editor + +/manage/index.bml.customization.moodtheme.header=Mood Themes + +/manage/index.bml.customization.moodtheme.set=Select which mood theme set your journal will use + +/manage/index.bml.customization.moodtheme.set.header=Set Your Mood Theme + +/manage/index.bml.entries.memories.about=View and work with your memorable entries + +/manage/index.bml.entries.tags.about=Organize your journal entry categories + +/manage/index.bml.entries.tags.header=Manage Entry Tags + +/manage/index.bml.friends.edit.about=Add or remove users from your friends list, or change the colors used to represent them. + +/manage/index.bml.information.emailpost=E-mail Gateway Settings + +/manage/index.bml.information.emailpost.about=Manage your e-mail addresses and PIN for post-by-email support + +/manage/index.bml.information.phonepost=Phonepost Settings + +/manage/index.bml.information.phonepost.about=Manage your post-by-phone phone number and PIN. + +/manage/index.bml.information.siteopts.about=Select your preferred site layout and language + +/manage/index.bml.information.status.about=Set your account's activation status (delete or undelete your account) + +/manage/phonepost.bml.delete=Delete Settings + +/manage/phonepost.bml.deleted=Your phone post settings have been deleted. + +/manage/phonepost.bml.deleted.header=Deleted + +/manage/phonepost.bml.error.inuse=Invalid PIN, please try another + +/manage/phonepost.bml.error.phone.length=Your phone number must be at least ten digits long. + +/manage/phonepost.bml.error.pin=Your PIN must be numeric. + +/manage/phonepost.bml.error.transcription=Invalid friend group for transcription + +/manage/phonepost.bml.format=Recorded Post Format: + +/manage/phonepost.bml.format.help='Ogg Vorbis' is less supported, but creates a higher quality file. 'Wav' is smaller and doesn't sound as nice, but plays natively nearly everywhere. + +/manage/phonepost.bml.intro.loggedin<< +Post by Phone, fill out your phone number and PIN below. p?> +Privacy Policy for more information) +Calls made from numbers other than your authorized phone number will still be accepted, but you'll have to enter your authorized phone number before you can record your post. p?> + +. + +/manage/phonepost.bml.intro.loggedout=Members of can log in and change their Post by Phone settings here: + +/manage/phonepost.bml.phone=Authorized Phone Number: + +/manage/phonepost.bml.phone.help=(515) 555-5555 + +/manage/phonepost.bml.pin=Personal Identification Number: + +/manage/phonepost.bml.pin.help=4-6 digits recommended + +/manage/phonepost.bml.save=Save Settings + +/manage/phonepost.bml.saved=Saved + +/manage/phonepost.bml.success.moreinfo=For more information on recording a Post by Phone entry, see How do I record an audio post to my journal?. + +/manage/phonepost.bml.success.text=Your phone settings have been saved. + +/manage/phonepost.bml.title=Post by Phone Settings + +/manage/phonepost.bml.transcribers=Allowed Transcribers: + +/manage/phonepost.bml.transcribers.help=Edit Friend Groups + +/manage/pubkey.bml.info=Publishing your public key allows others to view it via your userinfo page, and you can post to the e-mail gateway with signed messages. See instructions here. + +/modify_do.bml.colortheme.about=Here you can select what color theme will be applied to the layout options you pick above. Or, if you don't like the provided colors, specify your own! + +/modify_do.bml.domainalias.helptext=For this to work, you'll need to arrange to have your domain name's DNS point to the same IP address as [[sitename]]. For more information, see this FAQ. + +/modify_do.bml.friends.opt.usesharedpic.about=This option controls what picture you see on your friends page when a user posts in a shared or community journal. If you check it, then you'll see the community's icon. If you leave it unchecked, then you'll see the user icon of the person who's actually posting. + +/modify_do.bml.journaloptions.about=From here you can customize the look of your LiveJournal pages. If you're really curious how everything works, read the developer information. Otherwise, we'll assume you're satisfied with the basic options below: + +/modify_do.bml.moodicons.about=When posting journal entries you can also specify your current mood. Different users have submitted different sets of mood icons that you can use. Or, select "None" if you don't want any pictures beside your moods. (or, you don't even have to use the Current Mood feature at all.) + +/modify_do.bml.overrides.about=If you are happy with the journal layout options above, you can ignore this section. This is for tweaking very specific things about your page layout. See What are overrides? How do they work? for an overview, and visit the developer section for details. Also note that overrides are for overriding only one or two things about a style. If you'd like to override everything, you need to create your own style. For an overview of how to create a style, see How do I make a custom style? + +/modify_do.bml.overrides.note=Please note that not all style variables can be overridden. See the documentation for more details.
      Also, be aware that if you attempt to edit your overrides and you have used a tag that is not allowed in the head of the document – such as <DIV>, <SPAN>, <IMG>, and many other tags – that tag will be stripped. The only HTML elements that can be used in the *_HEAD overrides are those elements that are valid in the head of a HTML document. This is limited to <title>, <base>, <style>, <link>, and <meta>. + +/multisearch.bml.noaddress.text=You did not enter an e-mail address. + +/paidaccounts/index.bml.costs.header=Well, how much does it cost? + +/paidaccounts/index.bml.costs.rates=The rates are as follows: + +/paidaccounts/index.bml.costs.rates.amount.header=Amount + +/paidaccounts/index.bml.costs.rates.inexpensive<< +That works out to a little over $2/month for the year plan. +That'll hardly break your pocketbook. +The most annoying part will likely be pulling out your wallet, finding your credit card, and typing in your information. +. + +/paidaccounts/index.bml.costs.rates.time.header=Time + +/paidaccounts/index.bml.features<< +
      To show appreciation for users who have made contributions, there are a number of features that are only available to paid accounts. These features include, but aren't limited to:
      + +
      New! Post by E-mail
      +
      Paid accounts can post to their journals and communities quickly and securely through our e-mail gateway.
      + +
      Customizing your Journal
      +
      In addition to just being able to pick the style of your journal and the colors, you'll also be able to create your own style using whatever HTML you like. This will also let you be able to make new styles that match your website that you can then easily embed, never revealing that you're using LiveJournal.com as your journal mechanism.
      + +
      Polls
      +
      Paid accounts have the ability to create polls in their own journals and in any communities they are a part of and can post to.
      + +
      More User Picture Icons
      +
      Paid accounts are allowed 15 user picture icons, rather than the 3 allotted to free users.
      + +
      LiveJournal.com E-mail Alias
      +
      Paid accounts are given a LiveJournal.com e-mail address ([[username]]@livejournal.com) that can be turned on or off.
      + +
      Directory Searches
      +
      Paid accounts are given access to use the directory to search for other users.
      + +
      LiveJournal.com Subdomain
      +
      Instead of having your journal at +http://www.livejournal.com/users/[[username]]/, it'll also be available at http://[[username]].livejournal.com/, much shorter and more personal.
      + +
      Syndication
      +
      Paid accounts have the ability to create new syndicated accounts, which are RSS feeds that are incarnated on LiveJournal.
      + +
      Text Messaging Interface
      +
      Paid accounts are given access to the text messaging feature, which will allow them to receive text messages on their phone or pager through LiveJournal's custom interface.
      + +
      More To-Do Items
      +
      Paid accounts can set up to 150 to-do list items in their to-do lists, and can set differing security levels on each item.
      + +
      Embedding
      +
      Paid accounts have access to the complete range of options for embedding your journal into your home page, as explained on the "Embedding" page.
      + +
      Domain Forwarding
      +
      Paid users can set up domain forwarding, so that their internet domain points to their LiveJournal.
      + +
      More...
      +
      For a complete list of Paid Account benefits, please read What are the Paid Account benefits?
      +. + +/paidaccounts/index.bml.features.header=So what cool features will I get? + +/paidaccounts/index.bml.title=About Paid Accounts + +/paidaccounts/index.bml.whypay.argument<< +No, of course not. Paying for web services is annoying, we agree. +That's why nearly all of LiveJournal's functionality is available free of charge. +However, if you're happy with the service you're being provided, show your support and get a paid account. +. + +/paidaccounts/index.bml.whypay.header=I have to pay to use LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads<< +It takes money to run websites (for servers, colocation, and bandwidth), and this seems like a +better way to pay for it than blasting you with pop-up banner ads and spamming you with advertisements. +. + +/paidaccounts/index.bml.your_username=your_username + +/paidaccounts/usepaypal.bml.delivery.badformat=Invalid delivery date format. Must be of form yyyy-mm-dd or yyyy-mm-dd hh:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Delivery date cannot be in the past. To send immediately, leave the delivery date box blank. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Delivery date cannot be more than a month in the future. + +/pay/index.bml.deliverydate.details=Format: yyyy-mm-dd hh:mm (GMT time)
      (enter nothing for no delayed delivery) + +/pay/index.bml.deliverydate.label=Delivery Date: + +/pay/index.bml.gift.anonymous=Anonymous gift + +/press/staff.bml.accountserv=Account Services + +/press/staff.bml.administration=Administration + +/press/staff.bml.administration.about<< +LiveJournal.com started in 1999 as a project of Brad Fitzpatrick, and during the first two years of its life, +was sustained by a large and loyal group of volunteers. While a lot of +LiveJournal.com is still run by teams of volunteers, we now have a small senior staff who oversee all +operations: +. + +/press/staff.bml.avva.title=Senior Developer + +/press/staff.bml.back2=Back to the Press area + +/press/staff.bml.bleything.title=Senior Support Monkey + +/press/staff.bml.bradfitz.quip=Focus on your product and not just on making money. + +/press/staff.bml.bradfitz.title=President / Lead Developer + +/press/staff.bml.contact=If you need to get in touch with any of us, please e-mail webmaster@livejournal.com. + +/press/staff.bml.custserv=Customer Service / Usability Research + +/press/staff.bml.david.title=The Intern + +/press/staff.bml.denisep.quip=I'll have that to you next Thursday + +/press/staff.bml.denisep.title=Volunteer Relations / Usability Specialist + +/press/staff.bml.deveiant.title=Remote Developer + +/press/staff.bml.developers=Developers + +/press/staff.bml.ferrell.title=Customer Service Manager + +/press/staff.bml.jproulx.quip=Geek to User Liaison + +/press/staff.bml.jproulx.title=Community Site Supervisor / Press Relations + +/press/staff.bml.lisa.title=Lead Systems Administrator + +/press/staff.bml.mahlon.quip=Eek eek! + +/press/staff.bml.mahlon.title=Code Monkey + +/press/staff.bml.matthew.title=Systems Administrator + +/press/staff.bml.ryanfitz.title=Payment Services + +/press/staff.bml.sandy.title=Accounting and Administration + +/press/staff.bml.smithy.title=Apprentice Hacker + +/press/staff.bml.sysadmin=Systems Administrators + +/press/staff.bml.title=Senior Staff + +/press/staff.bml.whitaker.quip=What next? + +/press/staff.bml.whitaker.title=Remote Developer + +/register.bml.ask.body=Click the button below to have send a validation e-mail to [[email]]. + +/register.bml.ask.header=Validate E-mail + +/register.bml.email.body<< +This is the validation e-mail you have requested. +To complete validation of your account, please visit this URL: + + [[conflink]] + +You may have to copy and paste this link into your browser's window. + +Regards, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Validate E-mail + +/register.bml.error.useralreadyvalidated=The e-mail address for [[user]] has already been validated. + +/register.bml.sent.body=A validation e-mail has been sent to [[email]]. In order to complete validation, you need to click the link in that e-mail. + +/register.bml.title=Validate E-mail + +/register.bml.trans.body=Your new e-mail address has been validated. + +/rename/index.bml.does=Renaming the account only changes the username. Everything else - paid or permanent account status, user privileges, personal info, friends, and other account-related data - remains the same, and will be associated with the new username. All existing comments in other journals and entries in communities will display the new username. + +/rename/index.bml.faqurl=For more details on the rename process, see the rename FAQ. + +/rename/index.bml.fee=There is a fee of [[fee]] to change your LiveJournal username. + +/rename/index.bml.heading.cost=Cost + +/rename/index.bml.heading.details=Details + +/rename/index.bml.heading.how=How To Buy + +/rename/index.bml.option=You have the option to either redirect the old username to the new username or mark it as deleted. You may also choose to either have people who list you as a friend continue to list your new username as a friend, or be removed from the friends lists of all other users. + +/rename/index.bml.options.buy=Buy Token + +/rename/index.bml.options.buy.desc=Buy a rename token. + +/rename/index.bml.options.use=Use Token + +/rename/index.bml.options.use.desc=Use a rename token. + +/rename/index.bml.redeem=You first buy a rename token, which is e-mailed to you, then use that token to do the actual rename when you receive it. Rename tokens are non-refundable, but are transferrable. That is, you can buy a rename token for another user. + +/rename/index.bml.reserve=You do not have to create an account with your new username in order to be renamed to it. However, if you are worried that someone might take the name before you have a chance to buy and use your token, you should create an account with the new username. Be sure to use the same e-mail address and password that you use for your current account for the new one. + +/rename/index.bml.title=Account Renaming Service + +/rename/index.bml.whatrename=You may only rename your personal account, not a community you run. + +/rename/use.bml.changes=The following changes will be made once the rename is completed: + +/rename/use.bml.changes.move="[[newuser]]" will be moved out of the way to "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" will be renamed to "[[newuser]]" + +/rename/use.bml.confirm2=After you click 'Rename' below, there is no way to undo the change. As a means of confirmation, type the word "[[confirmword]]" in the box below in uppercase. + +/rename/use.bml.confirm.click=And then, click 'Rename': + +/rename/use.bml.error.allocating=Error allocating name to move away destination account. + +/rename/use.bml.error.badpass=The passwords for the old and new usernames do not match. + +/rename/use.bml.error.differentusername=This isn't the username you were logged in as when you loaded this form. + +/rename/use.bml.error.login=But first, you have to login. + +/rename/use.bml.error.notvalidated=The email address on one or more of the accounts involved has not been validated. Before you rename your journal, you must first validate your email address. Please see How do I validate my email address? for information on how to validate your email address. + +/rename/use.bml.error.readit=Read the paragraph above. + +/rename/use.bml.error.reserved=Error moving away reserved account name. + +/rename/use.bml.error.same=This is the same as your old username. + +/rename/use.bml.error.token=Invalid rename token. + +/rename/use.bml.error.type=Only normal accounts can be renamed, not community accounts. + +/rename/use.bml.error.unknown=Unknown error renaming. + +/rename/use.bml.error.usedtoken=This token has already been used. + +/rename/use.bml.error.username=Invalid username. + +/rename/use.bml.error.usernametaken=That username is already taken. + +/rename/use.bml.heading.changes=Changes + +/rename/use.bml.heading.success=Success + +/rename/use.bml.heading.sure=Are you sure? + +/rename/use.bml.intent=This page is for renaming an account after you've read the introduction and bought a rename token. + +/rename/use.bml.label.desired=Desired username: + +/rename/use.bml.label.proceed=Proceed ... + +/rename/use.bml.label.rename=Rename + +/rename/use.bml.label.token=Rename token: + +/rename/use.bml.label.username=Current username: + +/rename/use.bml.options=Rename options: + +/rename/use.bml.options.delfriends=Remove all users from your Friends list and leave all communities. + +/rename/use.bml.options.forward=Automatically forward users from [[oldname]] to new username. + +/rename/use.bml.options.keepfriends=Keep all users and communities on your Friends list. + +/rename/use.bml.options.keepself=Keep everyone on your Friend Of list. + +/rename/use.bml.options.removeself=Remove everyone from your Friend Of list. + +/rename/use.bml.options.unlink=Do not keep a connection between [[oldname]] and the new journal. + +/rename/use.bml.success.login=You'll need to login again now. + +/rename/use.bml.success.moved="[[newuser]]" has been moved out of the way to "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" has been renamed to "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Username renamed. + +/rename/use.bml.title=Use A Rename Token + +/site/contract.bml.promise=We stand firm in saying that we will: + +/site/contract.bml.promise.account=Honor the status of every account + +/site/contract.bml.promise.account.about<< +Permanent accounts will be honored for the life of the site. Paid accounts will remain as +paid accounts until they expire, unless they are renewed in advance. Early adopters will be granted access to the paid +features that were freely available in the early history of the site. (Account status valid +with the exception of account termination by means of Terms of Service +violation.) +. + +/site/contract.bml.promise.ads=Stay advertisement free + +/site/contract.bml.promise.ads.about<< +It may be because it's one of our biggest pet peeves, or it may be because they don't +garner a lot of money, but nonetheless, we promise to never offer advertising space in our +service or on our pages. +. + +/site/contract.bml.promise.community=Work with the community, for the community + +/site/contract.bml.promise.community.about<< +We promise to keep you informed of changes to the best of our abilities without being intrusive. +We promise to run our business based on feedback from the LiveJournal community, and with the +LiveJournal community's best interests in mind. +. + +/site/contract.bml.promise.opensource=Support the Free Software movement + +/site/contract.bml.promise.opensource.about<< +All of the code that is used to run a complete, highly-customizable LiveJournal installation +is available to the public. We promise to keep this source free and open so that we can give +something back to the Free Software community. +. + +/site/contract.bml.promise.spam=Never send you unsolicited e-mail + +/site/contract.bml.promise.spam.about<< +We strongly believe that spam has no place on the internet, and we promise never to send you +any e-mail without your implied or explicit consent. We promise to never sell lists of users' e-mail +addresses or personal information, and we promise never to spam on the behalf of an interested +third party. +. + +/site/contract.bml.promise.uptime=Maintain reliable uptime within the limits of technical considerations + +/site/contract.bml.promise.uptime.about<< +We try to keep things running smoothly for everyone, especially since we use the system just +as much as anyone else. Unfortunately server hangups do occur, but we will plan ahead as best +as possible to avoid them. +. + +/site/contract.bml.promisetoyou<< +We at LiveJournal try to ensure that our service is as pleasant as possible for each user, +so we've assembled a list of promises we will keep. +. + +/site/contract.bml.promisetoyou.header=Our Promise to You + +/site/contract.bml.title=Social Contract + +/site/goat.bml.image.alt=Frank, the LiveJournal mascot goat. + +/site/goat.bml.image.caption="Baaaah," says Frank. + +/site/goat.bml.meet.body<< +This is Frank. Frank is the LiveJournal.com mascot. He helps us with random programming +when we get behind, and occasionally he answers tech support requests. Frank's really quite versatile.... he even does the yardwork sometimes. When the lawn gets overgrown we go, "Hey Frank! It's lunch time.... go eat the lawn!". It's really a win-win situation. +. + +/site/goat.bml.meet.header=Meet Frank + +/site/goat.bml.title=Frank the Goat + +/styles/create.bml.createstyle.text=From here you can create a new personal-style, useful if you're going to either embed your journal in your homepage or you want to make a public style that everybody can use and you need to work on it here first, rather than in your overrides section. Note that only users with paid accounts can create their own styles. + +/styles/index.bml.about<< +

      This section of the site allows you to create, edit, and delete customized S1 styles. This +allows you to control the look of your account to a great extent, whether you want to make it look +like your website, or just feel like being different.

      + +

      You can also create embedded styles which, rather than +creating a full page, include only the Journal entries and leave +you to embed your journal in another site.

      + +

      You can read more about the style system in the +style +documentation in the +developer area.

      + +

      Please note that only paid accounts +may create and use custom styles. Free Accounts have a selection of predefined +LiveJournal styles which you can select from the +Modify Your Journal page.

      +. + +/styles/index.bml.nav.edit=Edit or delete an existing style + +/suggestions/index.bml.howto.text<< +
      +
      Check prior suggestions
      +First, read over past suggestions to make sure that something similar hasn't already been brought up. If it has, you can read the comments on the entry. Sometimes, things might look as though they've been ignored, but they might be in development. Sometimes, ideas are rejected or delayed due to other concerns. +
      +
      Couldn't find your idea? Share it with us!
      +The template must be used for all suggestions. Be sure to fill out all areas of the template, and make sure your suggestion is correct and complete before you post it. Also, the suggestion generator does not add in line breaks, so you can use the <br> tag to produce whitespace. This makes your suggestion easier to read. +
      +
      Submit It!
      +You can add the community to your Friends list here. Once a suggestion is posted, people will discuss it. If we think it's a good idea, it will be added to the list of developer projects, and will be worked on as time permits. Not all suggestions can be implemented immediately, so please be patient with the process. +
      +. + +/suggestions/index.bml.howto.title=How do I make a suggestion? + +/suggestions/index.bml.info.text<< +Feel that you can contribute to the implementation of your suggestions? Feel free to 'watch' or join the communities below: +
      +
      LiveJournal Developer's Forum -- talking about technical things.
      +
      +
      LiveJournal Business Forum -- talking about general LiveJournal business opportunities and related areas.
      +
      +
      LiveJournal User Documentation Forum -- discussing and editing most forms of end user documentation.
      +
      +
      LiveJournal Art Forum -- discussing and sharing icons, mood themes, color themes and userpics.
      +
      +
      +Please remember that the people who implement LiveJournal changes and additions are fellow users like yourself. These things can take time and the more you can help with implementing, the more that can be achieved. +. + +/suggestions/index.bml.info.title=Other Information + +/suggestions/index.bml.rules<< +There are a few things to keep in mind: +
        +
      • Many suggestions have already been proposed and discussed, but simply not implemented yet. Be sure that you're not submitting a duplicate.
      • +
      • Flaming will not be tolerated. Everyone has different ideas about how LiveJournal should work; remember that promoting your opinion is all right, but flaming someone else's opinion is not.
      • +
      • Be as thorough as possible with your suggestion. A suggestion that contains detailed implementation notes is more likely to be accepted than one that doesn't. You don't need to know how to program; just try to think about what else your idea would affect, and bring up any problems you can see with it.
      • +
      • Be sure to read the FAQs first, to see if your idea already exists, or if an existing aspect of the site can be used to do what you want.
      • +
      • If you want to ask a question about how LiveJournal works, aren't certain if something exists or not, or are having a problem, don't submit a suggestion. Ask Support instead.
      • +
      +. + +/suggestions/index.bml.title=Suggestion Area + +/suggestions/index.bml.welcome.text=User suggestions are an important part of LiveJournal. If you have something that you think would be a cool idea, you can follow these procedures to bring it to the attention of the people who run the site. + +/suggestions/index.bml.welcome.title=Welcome! + +/support/append_request.bml.bounce.noemail=No e-mail address specified for bounce. + +/support/append_request.bml.bounce.toomany=You can only send to up to five e-mail addresses. You have specified more than five. + +/support/append_request.bml.internal.touch=To change a request's status, you must select "Internal Comment / Action" and explain why you're changing it. + +/support/append_request.bml.successlinks<< + +. + +/support/encodings.bml.edit.text<< +Short answer: (applicable if you write your journal in English): Go to your +personal settings page. Find an option +near the bottom of the page that is called Auto-convert older entries from:. Choose +"Western European (Windows)" from the pull-down menu and save your settings. Your entries should +now be editable. p?> + +Long answer: In order to allow you to edit a non-Unicode entry, LiveJournal code needs to +know which encoding that entry has been posted in. For users of English and other West European +languages, this will normally be "Western European (Windows)", although if that doesn't work well +for quote characters and other similar meta-characters, try "Western European (ISO)". Users +writing in other languages should select their encoding; if it isn't in the supplied list, +contact Support and explain the problem. p?> + + +. + +/support/encodings.bml.overview.text<< + + + +. + +/support/help.bml.interim<< + + + + +Getting +Started category in HelpScreening's memories +is an especially good place for new +volunteers to get information. p?> + + + +
      • Be professional and courteous.
      • +
      • Don't contact people submitting requests outside the Support +board to discuss their request or give them information.
      • +
      • Keep information in Support requests private.
      • +
      • Don't copy other people's answers.
      + + + +, but +please wait until there is an approved answer in the request. p?> + + + + + +Support +board. p?> +. + +/support/see_overrides.bml.error.noprivs=Only users with the supportviewscreened or supporthelp privilege can view another user's overrides. + +/syn/index.bml.loginrequired.text=To manage your syndicated accounts, first log in. + +/syn/index.bml.promo.text=If you would like to see a list of the syndicated feeds that users have advertised in the past, you may wish to visit , where users post announcements of feeds they create and watch. + +/talkmulti.bml.error.comms_deleted=One of the comments has been deleted since you selected it. For security reasons, please go back and try again. + +/talkpost.bml.error.noreply_deleted=This comment has been deleted. You cannot reply to it. + +/talkpost.bml.loginq=Log in? + +/talkpost.bml.opt.friendsonly=- this user has disabled anonymous and non-friend posting. You may post here if [[username]] lists you as a friend. + +/talkpost_do.bml.error.noverify=Sorry, you aren't allowed to post comments in other people's journals until your e-mail address has been verified. If you've lost the confirmation e-mail to do this, you can have it re-sent. + +/talkpost_do.bml.preview=This is how your comment will look when posted. Using the form below, you can edit your comment further, or you can submit it as is. + +/talkpost_do.bml.title=Comment Posted + +/talkscreen.bml.screened.body=The comment has been screened. You can view it here. + +/talkscreen.bml.unscreened.body=The comment has been unscreened. You can view it here. + +/tools/emailmanage.bml.address.old.text<< +The following is a list of e-mail addresses that were used with your account, +and the time they were deactivated as the primary e-mail address. Check the ones +you wish to delete. +. + +/tools/emailmanage.bml.desc.notfirst<< +This page only lets you remove e-mail addresses that were used after the first time +you used the e-mail address your account is currently validated with. In particular, +this means an attacker isn't able to remove your original e-mail address. +. + +/tools/emailmanage.bml.desc.text<< +This page lets you remove past e-mail addresses that were used with your account. +If you remove an address, it will no longer be possible to have your password mailed to that address. +This is useful if somebody discovered your password and hijacked your journal. Simply +have the new password mailed to your old address, change the password, and remove the +attacker's e-mail address. +. + +/tools/emailmanage.bml.notvalidated.text=To use this tool, your current e-mail address, [[email]] , must be validated. If you've lost the confirmation e-mail to do this, you can have it re-sent. After you validate your email, come back here. + +/tools/emailmanage.bml.notvalidated.title=E-mail not validated + +/tools/emailmanage.bml.title=E-mail Management + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.description.text<< + Give this journal entry a description that you can remember it by. + To delete this entry from your list of memorable entries, enter a blank description. +. + +/tools/memadd.bml.error.deleted.body=The journal entry previously described as "[[desc]]" has been removed from your list of memorable entries. + +/tools/memadd.bml.error.fivekeywords=Only 5 keywords/categories are allowed per memorable entry. + +/tools/memadd.bml.error.login=You must be logged in to use this feature. Go log in and you'll be brought back here. + +/tools/memadd.bml.keywords.select=You can also select keywords you've used in the past: + +/tools/memadd.bml.keywords.text=Why is this entry memorable? Enter up to five comma-separated keywords or categories so you can find it later. + +/tools/memadd.bml.whocansee<< + Who can see that you've marked this entry as memorable? + Everybody, only people you list as a friend, or just you? +. + +/tools/memories.bml.body.keyword<< + +[[user]] found memorable. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] has placed memorable journal entries in. p?> +. + +/tools/memories.bml.error.noentries.body<< +This could be because:
        +
      1. the user hasn't defined any memorable events,
      2. +
      3. the user's memorable events are protected and you don't have access to view them, or
      4. +
      5. the user doesn't have any memories that match your filter criteria.
      +. + +/tools/memories.bml.title.keyword=Memorable [[keyword]] Entries + +/tools/memories.bml.title.memorable=Memorable Entries + +/tools/recent_comments.bml.maxnotshown=Upgrade to a Paid Account to see [[max]] recent comments, instead of [[current]]. + +/update.bml.note=Note: The time and date above are from our server. Correct them for your timezone before posting. + +/update.bml.opt.noemail=Don't e-mail comments: + +/update.bml.subject=Subject: (optional) + +/update.bml.update.alternate=If you don't want to download a client for your computer, or if one doesn't exist for your computer, you may use this page to update your LiveJournal. This is also useful if you're on vacation or away from your primary computer. If you have a paid account, you may update your journal via e-mail, record phone posts when away from a computer, or create polls for your entries. + +/update.bml.update.success=Update successful. You can view your updated journal here. + +/userinfo.bml.about.comm=About: + +/userinfo.bml.about.user=Bio: + +/userinfo.bml.error.malfname=Malformed username: too long, or contains invalid characters. + +/userinfo.bml.error.notloggedin=If you wish to view your own user profile, you need to log in. + +/userinfo.bml.friendof.comm=Watched by: + +/userinfo.bml.friendof.user=Friend of: + +/userinfo.bml.friends.user=Friends + +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.interests.modifyyours=Modify yours + +/userinfo.bml.label.interests.removesome=Remove some + +/userinfo.bml.label.shared= Posting Access: + +/userinfo.bml.membership.paidmembers=After your paid account is set up, you may join the paidmembers community. + +/userinfo.bml.nonexist.body=The username [[user]] is not currently registered. + +/userinfo.bml.syn.parseerror=Error Message: + +crumb.about=About LiveJournal + +crumb.abusereport=Report Abuse + +crumb.acctfeatures=Features By Account Type + +crumb.advsearch=Advanced + +crumb.banners=Advertising Banners + +crumb.code=LiveJournal Code + +crumb.contract=Our Social Contract + +crumb.contributors=Contributors + +crumb.coppa=COPPA + +crumb.dmca=DMCA Information + +crumb.download=Download a Client + +crumb.emailgateway=E-mail Gateway + +crumb.emailmanage=E-mail Management + +crumb.filemanager=File Manager + +crumb.goat=About Frank + +crumb.guidingprinciples=Our Guiding Principles + +crumb.itsfree=It's Free? + +crumb.legal=Legal Information + +crumb.ljhome=Home + +crumb.memories=Memorable Entries + +crumb.paidaccounts=Paid Accounts + +crumb.paidacctstatus=Paid Account Status + +crumb.press=LiveJournal Press Area + +crumb.pressarticles=LiveJournal in the Press + +crumb.privacy=Privacy Policy + +crumb.register=Validate E-mail + +crumb.search=Search + +crumb.searchinterests=By Interest + +crumb.searchregion=By Region + +crumb.securechangepass=Change Password + +crumb.securecreatejournal=Create Journal + +crumb.securelogin=Login + +crumb.securemanage=Manage Accounts + +crumb.singles=LiveJournal Singles + +crumb.singlesopts=Modify Availability + +crumb.singlessearch=Search for Singles + +crumb.sitemap=Site Map + +crumb.sizechart=Sizing Chart + +crumb.staff=Senior Staff + +crumb.stats=Statistics + +crumb.store=LiveJournal Store + +crumb.storeitem=View Item Detail + +crumb.suggestions=Suggestions Generator + +crumb.suggview=Suggestions + +crumb.tos=Terms of Service + +dystopia.btn.login=LOGIN + +dystopia.hello_anonymous=Welcome to LiveJournal! + +dystopia.hello_loggedin=Hello, [[username]]! + +dystopia.nav.contact=Contact Info + +dystopia.nav.createjournal=Create a Journal + +dystopia.nav.developer=Developer Area + +dystopia.nav.download=Download + +dystopia.nav.editentries=Edit Entries + +dystopia.nav.editfriends=Your Friends + +dystopia.nav.editpassword=Your Password + +dystopia.nav.editpics=Your Pictures + +dystopia.nav.editstyle=Edit Style + +dystopia.nav.faq=LiveJournal FAQ + +dystopia.nav.findcomm=By Community + +dystopia.nav.finddir=Directory Search + +dystopia.nav.findint=By Interest + +dystopia.nav.findrandom=Random + +dystopia.nav.findregion=By Region + +dystopia.nav.home=Home + +dystopia.nav.journalcalendar=Calendar + +dystopia.nav.journalfriends=Friends + +dystopia.nav.journalinfo=User Info + +dystopia.nav.journalrecent=Recent + +dystopia.nav.legaldmca=DMCA + +dystopia.nav.legalprivacy=Privacy + +dystopia.nav.legaltos=Terms of Service + +dystopia.nav.login=Login + +dystopia.nav.logout=Logout + +dystopia.nav.lostinfo=Lost Password + +dystopia.nav.manage=Manage Accounts + +dystopia.nav.memories=Memories + +dystopia.nav.modifyjournal=Modify Journal + +dystopia.nav.news=News + +dystopia.nav.paidaccts=Paid Accounts + +dystopia.nav.paymentarea=Payment Area + +dystopia.nav.personalinfo=Personal Info + +dystopia.nav.sitemap=Site Map + +dystopia.nav.siteopts=Browse Options + +dystopia.nav.support=Have a question? + +dystopia.nav.updatejournal=Update Journal + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=122 + +dystopia.navhead.findusers=Find Users + +dystopia.navhead.help=Help & Support + +dystopia.navhead.journal=Your Journal + +dystopia.navhead.legal=Legal + +dystopia.navhead.settings=Your Settings + +dystopia.navhead.welcome=Welcome! + +dystopia.search.aolim=AOL IM + +dystopia.search.icq=ICQ Number + +dystopia.search.int=Interest + +dystopia.search.jabber=Jabber + +dystopia.search.msn=MSN Username + +dystopia.search.region=Region + +dystopia.search.yahoo=Yahoo! ID + +dystopia.searchlj=Search LiveJournal: + +Email=E-mail + +email.newacct.body<< +Congratulations, you have a new LiveJournal account! + +To complete your journal creation and verify your e-mail address, go +here: + + [[regurl]] + +The URL that your new journal is located at is: + + [[siteroot]]/users/[[username]]/ + +and also: + + [[siteroot]]/~[[username]]/ + +Below is your LiveJournal username and password: + + Username: [[username]] + Password: [[password]] + +You can go to [[siteroot]]/ to access your account, create +new journal entries, and modify your journal options, but we recommend +downloading a LiveJournal client. It's the easiest way to update your +journal, and there are clients available for many platforms! Get one at: + + [[siteroot]]/download/ + +Getting started on LiveJournal can be difficult when you don't know +anyone. Visit http://newbies.livejournal.com for smart, helpful advice... +with a little luck, you'll be a LiveJournal pro in no time! + +We hope you appreciate LiveJournal as much as we appreciate bringing it to +you. If you have any questions regarding how to use LiveJournal, please +visit the support area at: + + [[siteroot]]/support/ + +There you'll find answers to almost any question you could ask about +LiveJournal. + +Our goal is to make LiveJournal totally rock... if we can do anything to +make it easier, more powerful, more customizable, whatever... let us know. +We're not running the site to make money. We're not a dot-com company +funded by venture-capital hoping to go IPO ... this site is run by all the +people that use it. Let us know what you want out of it. + +If you have questions, the support team will get you an answer usually +in less than 24 hours. + +Enjoy! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Welcome to LiveJournal + +error.nodb=Database temporarily unavailable. + +error.noremote=You have to log in in order to use this page. + +error.purged.text=This journal has been deleted and purged. + +error.suspended.text=This account has been either temporarily or permanently suspended. If you are [[user]], please refer to the FAQ entitled My account has been suspended! How can I get it back? for more information. Please note that in order to maintain our users' privacy, [[sitename]] cannot discuss the reasons for any suspension with anyone except the account's owner. + +langname.be=Belarusian + +langname.da=Danish + +langname.de=German + +langname.en_GB=English (UK) + +langname.en_LJ=English + +langname.eo=Esperanto + +langname.es=Spanish + +langname.et=Estonian + +langname.fi=Finnish + +langname.fr=French + +langname.ga=Irish + +langname.gd=Gaelic + +langname.gr=Greek + +langname.he=Hebrew + +langname.hi=Hindi + +langname.hu=Hungarian + +langname.is=Icelandic + +langname.it=Italian + +langname.ja=Japanese + +langname.la=Latin + +langname.lv=Latvian + +langname.ms=Malay + +langname.nb=Norwegian BokmÃ¥l + +langname.nl=Dutch + +langname.nn=Norwegian Nynorsk + +langname.pl=Polish + +langname.pt=Portuguese + +langname.ru=Russian + +langname.sv=Swedish + +langname.tr=Turkish + +langname.uk=Ukrainian + +langname.zh=Chinese Simplified + +ljcom.account.feature=Feature + +ljcom.account.feature.email=LiveJournal e-mail address + +ljcom.account.feature.full2=For the full table, see this page. + +ljcom.account.feature.limit=limited + +ljcom.account.feature.ownblog=Your own journal/weblog + +ljcom.account.feature.photo=100MiB Integrated photo hosting + +ljcom.account.feature.pp=Phone Posting + +ljcom.account.feature.search=Directory search + +ljcom.account.feature.styles=Create/customize styles + +ljcom.account.feature.syn=Friends and syndicated feeds aggregator + +ljcom.account.free=Free Account + +ljcom.account.paid=Paid Account + +ljcom.account.paid12=Paid for 12 Months ($25 USD) + +ljcom.account.paid2=Paid for 2 Months ($5 USD) + +ljcom.account.paid6=Paid for 6 Months ($15 USD) + +ljcom.accounttype=Account Type + +ljcom.badpass.email=Your password cannot be based on your e-mail address. + +ljcom.badpass.realname=Your password cannot be based on your real name. + +ljcom.badpass.username=Your password cannot be based on your username. + +ljcom.meetup.head=Meetup! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=International [[name]] Meetup Day + +ljcom.meetup.moreinfo=(more info) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Want to meet people in real life from around your area to discuss this interest? Check out the [[link]]! + +ljcom.menu.upgrade=Upgrade your account + +ljcom.userinfo.accounttype=Account type + +ljcom.userinfo.paiduser=Paid User + +ljcom.userinfo.types.early=Early Adopter + +ljcom.userinfo.types.free=Free Account + +ljcom.userinfo.types.paid=Paid Account + +ljcom.userinfo.types.paid_early=Paid Account, previously an Early Adopter + +ljcom.userinfo.types.paid_early_expiring=Paid Account, expiring [[paiduntil]], previously an Early Adopter + +ljcom.userinfo.types.paid_expiring=Paid Account, expiring [[paiduntil]] + +ljcom.userinfo.types.permanent=Permanent Account + +ljcom.userinfo.types.permanent_early=Permanent Account, previously an Early Adopter + +portal.goat.name=Site Mascot + +portal.goattext.des=What do you want your goat to say? The only true thing goats can say is 'Baaaaah', but you can pretend your goat can say something else if you really want. + +portal.goattext.name=Goat Text + +portal.memories.portalname=Memorable Entries + +portal.memories.portaltitle=Memorable Entries + +portal.misbehaved.des=You really wanted to leave this unchecked. Goats that aren't housetrained are nothing but trouble. + +portal.misbehaved.name=Mishaved Goat + +portal.newtolj.name=Site Links + +portal.recent.items.description=By default, only the most recent entry is shown. + +portal.recent.showtext.description=By default only subjects will be shown. + +protocol.mail_bouncing=You are currently using a bad e-mail address. All mail we try to send you is bouncing. [[sitename]] requires a valid e-mail address for continued use. Visit [[siteroot]]/support/faqbrowse.bml?faqid=19 for how to change your e-mail address. + +protocol.must_revalidate=You need to validate your new e-mail address. Your old one was good, but since you've changed it, you need to revalidate the new one. If you don't validate your address, you will not have access to all of the functions of [[sitename]]. Visit [[siteroot]]/support/faqbrowse.bml?faqid=11 for more information. + +protocol.not_validated=Your e-mail address has not been validated. You may continue to use [[sitename]], but if you do not validate your address, you will not have access to all functions of the site. See the instructions that were mailed to you when you created your journal, or visit [[siteroot]]/support/faqbrowse.bml?faqid=11 for more information. + +talk.spellcheck=Check spelling during preview + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_english + +xcolibur.greeting.anon=Welcome to LiveJournal! + +xcolibur.greeting.logged_in=Welcome, [[name]]! [[logout]] + +xcolibur.login=Login? + +xcolibur.logout=Log out? + +xcolibur.nav.about=About + +xcolibur.nav.about.download=Download + +xcolibur.nav.about.general=General Info + +xcolibur.nav.about.paidaccounts=Paid Accounts + +xcolibur.nav.about.press=Press + +xcolibur.nav.about.sitenews=Site News + +xcolibur.nav.about.stats=Statistics + +xcolibur.nav.footer.sitemap=Site Map + +xcolibur.nav.help=Help + +xcolibur.nav.help.ask=Ask a Question + +xcolibur.nav.help.contact=Contact Info + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Lost Password + +xcolibur.nav.home=Home + +xcolibur.nav.journal=Journal + +xcolibur.nav.journal.archive=Archive + +xcolibur.nav.journal.edit.entries=Edit Entries + +xcolibur.nav.journal.friends=Friends + +xcolibur.nav.journal.info=Info + +xcolibur.nav.journal.memories=Memories + +xcolibur.nav.journal.recent=Recent + +xcolibur.nav.journal.update=Update + +xcolibur.nav.manage=Manage + +xcolibur.nav.manage.community=Communities + +xcolibur.nav.manage.customize=Customize + +xcolibur.nav.manage.entries=Entries + +xcolibur.nav.manage.friends=Friends + +xcolibur.nav.manage.info=Info + +xcolibur.nav.manage.password=Password + +xcolibur.nav.manage.pics=User Pictures + +xcolibur.nav.manage.styles=Styles + +xcolibur.nav.manage.tags=Tags + +xcolibur.nav.search=Search + +xcolibur.nav.search.directory=Region + +xcolibur.nav.search.directory.search=Advanced + +xcolibur.nav.search.interests=Interests + +xcolibur.nav.search.random=Random + +xcolibur.nav.siteopts=Browse Options + +xcolibur.nav.title=Navigate: + +xcolibur.nav.welcome=Welcome + +xcolibur.nav.welcome.create=Create an Account + +xcolibur.nav.welcome.login=Login + +xcolibur.nav.welcome.update=Update Your Journal + +xcolibur.search=Search: + +xcolibur.search.aolim=AOL IM + +xcolibur.search.category=Category: + +xcolibur.search.icq=ICQ Number + +xcolibur.search.int=Interest + +xcolibur.search.jabber=Jabber + +xcolibur.search.msn=MSN Username + +xcolibur.search.region=Region + +xcolibur.search.yahoo=Yahoo! ID + +xcolibur.upgrade=Upgrade Your Account + diff --git a/ljcom/bin/upgrading/eo.dat b/ljcom/bin/upgrading/eo.dat new file mode 100644 index 0000000..17fe591 --- /dev/null +++ b/ljcom/bin/upgrading/eo.dat @@ -0,0 +1,3580 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=ÅœanÄu Statuson + +/accountstatus.bml.error.db=Estis datumbaza eraro dum prilaboro de via peto. + +/accountstatus.bml.error.invalid=Nevalida statuso tipo + +/accountstatus.bml.error.nochange.expunged=Ĉi tiu konto estas senrubigita de sistemo. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Ne povas ÅanÄi taglibron statuson de suspendita. + +/accountstatus.bml.header.success=Sukceso + +/accountstatus.bml.journalstatus.about=Se vi volas forigi vian taglibron aÅ­ rehavi Äin, vi estas en la Äusta paÄo. Vi havos 30 tagojn post forigo de via taglibro, dum kiuj vi povos ÅanÄi vian intencon kaj rehavi vian taglibron. Post 30 tagoj taglibro estos forigita tute, sen ebleco reakiri Äin. + +/accountstatus.bml.journalstatus.head=Stato de taglibro + +/accountstatus.bml.journalstatus.select.activated=Aktivita + +/accountstatus.bml.journalstatus.select.deleted=Forigita + +/accountstatus.bml.journalstatus.select.head=Stato: + +/accountstatus.bml.journalstatus.select.suspended=Provizore Forigita + +/accountstatus.bml.message.nochange=Vian taglibron statuson lasis kiel [[statusvis]]. + +/accountstatus.bml.message.success=Vian taglibron statuson ÅanÄis sukcese al [[statusvis]]. + +/accountstatus.bml.title=Konta Stato + +/allpics.bml.current=Nunaj Bildoj + +/allpics.bml.default=DefaÅ­lto + +/allpics.bml.edit2=Vi povas redakti Ålosilvortojn por la bildoj aÅ­ alÅuti novan bildon. + +/allpics.bml.error.noparam=Vi devas specifi parametron. + +/allpics.bml.keywords=Åœlosilvortoj: + +/allpics.bml.nopics.text.other=Ĉi tiu uzanto ne alÅutis iujn ajn uzantobildojn. + +/allpics.bml.nopics.text2=Vi ne havas alÅutitajn bildojn. AlÅutu iun. + +/allpics.bml.nopics.title=Neniuj Bildoj + +/allpics.bml.pics=Jen la uzant-bildoj de [[user]]. + +/allpics.bml.title=Uzant-Bildoj + +/approve.bml.comm.success=Sukceso + +/approve.bml.comm.text<< +Vi nun estas ano de [[comm]]. +Klaku ĉi tie por aldoni la komunumon al via amikolisto. +. + +/approve.bml.commjoin.text<< +Vi aprobis la membreca peto de [[user]] en [[comm]]. +Klaku ĉi tie por viziti la membra listo de ĉi tiu komunumo, por agordi aliajn elektojn por ĉi tiu uzanto. +. + +/approve.bml.error.actionperformed=Ĉi tiu ago jam estas farita + +/approve.bml.error.approving=Estis eraro dum aprobo de ĉi tiu peto aliÄi. + +/approve.bml.error.internerr.invalidaction=Interna eraro: malvalida ago + +/approve.bml.error.invalidargument=Malvalida argumento donita + +/approve.bml.error.unknownactiontype=Nekonata agotipo + +/approve.bml.shared.success=Sukceso + +/approve.bml.shared.text<< +Vi nun havas afiÅa rajto ĉe [[shared]]. +Klaku ĉi tie por aldoni la partoprenitan taglibran al via amikolisto. +. + +/approve.bml.title=Ago Aprobo + +/birthdays.bml.description=Sube estas naskiÄtagoj por c^iuj, kiuj vi listas kiel amiko. + +/birthdays.bml.title=NaskiÄtagoj + +/changepassword.bml.btn.proceed=DaÅ­rigu + +/changepassword.bml.changepassword.header=ÅœanÄu Pasvorton + +/changepassword.bml.changepassword.instructions=Plenigu la formularon malsupre, por ÅanÄi vian pasvorton. Ricevu helpon pri elekto de bona kaj sekura pasvorto en tiu ĉi sekcio de Oftaj Demandoj (ODo). + +/changepassword.bml.email.body<< +Via pasvorto estas ÅanÄita ĉe [[sitename]]. + +Por reakiri Äin estontece, vizitu: + +[[siteroot]]/lostinfo.bml + +Sincere, +La Teamo [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=ÅœanÄo de Pasvorto + +/changepassword.bml.error.badcheck=Malbona nova pasvorto: [[error]] + +/changepassword.bml.error.badnewpassword<< +Via pasvorta konfirmo ne egalas vian novan pasvorton. Eble vi mistajpis. +Bonvolu retajpi kaj rekonfirmi vian novan pasvorton. +. + +/changepassword.bml.error.badoldpassword=Via malnova pasvorto ne estas Äusta. + +/changepassword.bml.error.blankpassword=Via nova pasvorto ne rajtas esti nenio. + +/changepassword.bml.error.changetestaccount=Ne eblas Åangi testkontan pasvorton. + +/changepassword.bml.error.characterlimit=Pasvortoj ne povas havi pli ol 30 signoj. + +/changepassword.bml.error.invaliduser=Malvalida uzanto [[user]]. Ĉi tiu uzanto ne ekzistas. Ĉu vi certas ke vi ne mistajpis Äin? + +/changepassword.bml.error.mustenterusername=Vi devas enmeti vian uzantnomon. + +/changepassword.bml.error.nonascii=Pasvortoj devas uzi sole ASCII-ajn signojn. Bonvolu elekti pasvorton, kiu ne uzas ekster-ASCII-ajn signojn. + +/changepassword.bml.error.notvalidated=Vi ne povas ÅanÄi vian pasvorton, se la valido de via nuna retpoÅtadreso ankoraÅ­ ne estas kontrolita. Bonvolu rigardi la OD-n por instruo pri ĉi tiu. + +/changepassword.bml.newpassword=Nova Pasvorto: + +/changepassword.bml.newpasswordagain=Nova Pasvorto (denove): + +/changepassword.bml.oldpassword=Malnova Pasvorto: + +/changepassword.bml.proceed.instructions=Premu la butonon suban, kaj via pasvorto estos ÅanÄita. Vi ankaÅ­ ricevos retpoÅton, kiu notas la pasvortan ÅanÄon. + +/changepassword.bml.relogin=AnkaÅ­, vi estas elsalutita de ĉiuj el viaj ekzistaj sesioj. Vi devus resaluti, antaÅ­ vi kontinuas. + +/changepassword.bml.success.text=Via pasvorto estas ÅanÄita, kaj retpoÅto estas sendita al vi kun memoriga mesaÄo. + +/changepassword.bml.title=ÅœanÄu Pasvorton + +/community/index.bml.main<< + + + + +Komunumo "Esperanto", kie oni povos helpi vin en komprenebla lingvo. Se vi regas la anglan lingvon, vizitu ankaÅ­ komunumon , iom esploru tie kaj tre baldaÅ­ vi mem povos ĉiujn instrui pri la ecoj kaj agordoj de VivÄ´urnalo. +p?> + + +
      +Por scii pri novaj eventoj kaj pri la problemoj, kiujn renkontas la tuta VÄ´-komunumo, aldonu al viaj amikoj .
      +Por Äustatempe ricevi informon pri planataj problemoj aÅ­ forÅaltoj de la servilo, aldonu al via amiko-bendo komunumon . +

      +Se vi ne komprenas la anglan, ĉiam eblas ekscii novaĵojn en Esperanto ĉe komunumo . +p?> + + +AIM, ICQ, Yahoo!, MSN aÅ­ Jabber. Se ankaÅ­ vi tujumas foje, aldonu tiun informon al via privata informo. Se vi havas pagatan konton, vi povas agordi ricevon de tekstaj mesaÄoj al via poÅtelefono. +p?> + + +aĉeti pagatan konton. Sed, certe, ekzistas aliaj manieroj partopreni nian agadon. +

      +VivÄ´urnalo estas projekto kun malferma kodo de programoj. Se vi havas bonan sperton en programado de servilaj programoj, turnu vin al Komunumo de VivÄ´urnalaj programistoj, . Se vi havas ideojn pri plibonigo de VivÄ´urnalo, skribu ilin en la Libro de Proponoj, . Se vi volas helpi per io ajn, iru al . Se vi Åatas solvi problemojn de aliaj homoj, ni proponas al vi partoprenon en Centro de Subteno. Se vi estas sperta pri aspektigo, vizitu nian Artistan Komunumon, . +p?> + + + + + +ĉi tiu teksto vi povas ekscii, kiel fari novan komunumon. Krom tio ekzistas du pliaj tekstoj, kiuj kovras preskaÅ­ ĉiujn demandojn, kiuj povas aperi pri komunumoj: Äœenerala helpo pri komunumoj kaj Mastrumado de komunumoj. Se vi tamen ne trovis respondon al via demando, uzu help-paÄaron. +p?> + + + + +
        +
      • Serĉu komunumon
      • +
      • Vidu taglibron kun reklamo de novaj komunumoj ()
      • +
      • Vidu taglibron, kie oni serĉas komunumojn ()
      • +
      • Se tio ne funkcias, demandu en la ĉefa E-lingva komunumo ()
      • +
      + + +Skribu Jesse Proulx, () mesaÄon al direktoro pri komunumoj. +p?> +. + +/community/index.bml.title=Komunumejo + +/community/join.bml.button.join=AliÄu al la komunumo + +/community/join.bml.error.already.member=Vi jam estas membro de ĉi tiu komunumo. + +/community/join.bml.error.closed=Ĉi tiu komunumo estas fermita al novaj membroj. Se vi deziras aliÄi, bonvolu kontakti iun el la sekvantaj prizorgantoj: [[admins]] + +/community/join.bml.error.statusvis.body=La konto, per kiu vi salutis, ne estas aktiva konto. + +/community/join.bml.error.statusvis.title=Ne Povas AliÄi Komunumojn + +/community/join.bml.label.addtofriends=Aldonu al la listo de geamikoj: "[[maintainer]]".
      + +/community/join.bml.label.allowposting=Ĉi tiu komunumo permesas afiÅi al ĉiuj membroj, do vi nun rajtas afiÅi al Äi. Se vi jam uzas VivÄ´urnalan klient-programon en via komputilo, vi devos elsaluti kaj reensaluti por ke ĉi tiu taglibro aperu en via listo de taglibroj al kiuj vi rajtas afiÅi. + +/community/join.bml.label.auth=Kvankam vi nun estas registrita kiel membro, ĉi tiu komunumo nur permesas afiÅojn de aÅ­toritataj uzantoj. Kontaktu unun de la prizorgantoj, se vi deziras afiÅan atingon. Jen la listo de prizorgantoj de ĉi tiu komunumo: [[admins]] + +/community/join.bml.label.banned=La prizorganto(j) de ĉi tiu komunumo malpermesis ke vi membriÄu. + +/community/join.bml.label.closed=Ĉi tiu komunumo estas fermita. Se vi interesiÄas pri aliÄo al Äi, bonvolu kontakti unun de ties prizorgantoj. Jen la listo de prizorgantoj de ĉi tiu komunumo: [[admins]] + +/community/join.bml.label.commlogged=Vi estas ensalutita kiel komunuma konto, ne la propra konto. + +/community/join.bml.label.errorcomminfo=La indikitaj informoj pri komunumo ne validas. + +/community/join.bml.label.expls=Premu la malsupran butonon por aliÄi al la komunumo "[[maintainer]]". Malmarki la malsupran kvadraton se vi volas aniÄi la komunumon sen vidi komunumaj enskriboj ĉe via amikara paÄo. + +/community/join.bml.label.loginfirst=Por aliÄi al komunumo, unue vi devas ensaluti. + +/community/join.bml.label.membernow=Vi nun estas membro de la komunumo [[commname]] + +/community/join.bml.label.sure=Ĉu vi certas? + +/community/join.bml.reqsubmitted.body=Via peto por aliÄi estis konservita al la prizorgantoj: + +/community/join.bml.reqsubmitted.title=AliÄa Peto Konservita + +/community/join.bml.request.body=La [[comm]] konumumo ne havas malferman membriÄon. Bonvolu klaki sube, kontroli ke vi deziras aliÄi ĉi tiun komunumon. + +/community/join.bml.request.reason=Nedevige, enmeti kialon ke vi deziras aliÄi ĉi tiun komunumon: + +/community/join.bml.request.title=Peto AliÄi + +/community/join.bml.success=Pasis sukcese + +/community/join.bml.title=AliÄu al la Komunumo + +/community/leave.bml.button.leave=Forlasu la Komunumon + +/community/leave.bml.label.buttontoleave=Premu la malsupran butonon por forlasi la komunumon "[[commname]]". + +/community/leave.bml.label.infoerror=La indikita informo pri komunumo ne validas. + +/community/leave.bml.label.logoutfirst=Por forlasi komunumon, unue vi devas ensaluti. + +/community/leave.bml.label.removed=Vi nun estas forigita el la komunumo [[commname]] + +/community/leave.bml.label.removefromfriends=AnkaÅ­ forigu "[[user]]" de amikolisto. + +/community/leave.bml.success=Sukcese pasis + +/community/leave.bml.sure=Ĉu vi certas? + +/community/leave.bml.title=Forlasu Komunumon + +/community/manage.bml.commlist.actinfo=Informoj + +/community/manage.bml.commlist.actions=Agoj + +/community/manage.bml.commlist.actmembers=[Membroj] + +/community/manage.bml.commlist.actmembers2=Membroj + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] pritraktataj + +/community/manage.bml.commlist.actsettings=[Agordoj] + +/community/manage.bml.commlist.actsettings2=Agordoj + +/community/manage.bml.commlist.header=Viaj komunumoj + +/community/manage.bml.commlist.moderation=Atendanta Moderigo + +/community/manage.bml.commlist.moderation.num=[[[num]] en atendovico] + +/community/manage.bml.commlist.none=Vi ne administras komunumojn. + +/community/manage.bml.commlist.text=Jen la komunumoj, kiujn vi administras aÅ­ kun-administras: + +/community/manage.bml.commlist.title=Titolo + +/community/manage.bml.commlist.username=Uzantnomo + +/community/manage.bml.create.header=Krei novan komunumon + +/community/manage.bml.create.text=Vi ankaÅ­ povas krei novan komunumon. + +/community/manage.bml.joinmail.body=Por komunumoj kun fermitaj membriÄoj, vi havas kelkajn retpoÅtajn elektojn: + +/community/manage.bml.joinmail.save=Konservu Agordojn + +/community/manage.bml.title=Komunuma Administrado + +/community/members.bml.error.alreadyadded=[[user]] ne estas aldonita, ĉar li jam povas atingi ĉi tiun komunumon. + +/community/members.bml.error.alreadysent=[[user]] ne estas aldonita, ĉar jam retpoÅto konfirma estas sendita al li je: [[datetime]]. Bonvolu atendi Äis la respondo. + +/community/members.bml.error.invaliduser=Ne povas aldoni komunuman aÅ­ resendatan konton: [[user]] + +/community/members.bml.error.noaccess=Nur komunumo-prizorgantoj eblas redakti membriÄajn listojn. Vi ne estas prizorganto de la komunumo [[comm]]. + +/community/members.bml.error.noattr=Neniam da atributoj elektita por uzanto: [[user]] + +/community/members.bml.error.nocomm=Komunumo ne estas trovebla. + +/community/members.bml.error.nouser=Uzanto ne ekzistas: [[user]] + +/community/members.bml.key.admin=Prizorganto + +/community/members.bml.key.member=Membro + +/community/members.bml.key.moderate=Moderiganto + +/community/members.bml.key.post=AfiÅa Atingo + +/community/members.bml.key.preapprove=Ne-moderigita + +/community/members.bml.key.user=Uzanto + +/community/members.bml.manage2=Administru komunumojn + +/community/members.bml.name=Komunuma nomo: [[name]] + +/community/members.bml.nextlink=(Sekvonta paÄo...) + +/community/members.bml.prevlink=(AntaÅ­a paÄo...) + +/community/members.bml.settings=[Preferigoj] + +/community/members.bml.success.header=Sukceso + +/community/members.bml.success.message=Viaj ÅanÄoj estas sukcese konservitaj. + +/community/members.bml.success.return=Revenu al la listo + +/community/members.bml.title=Komunumaj Membroj + +/community/members.bml.update=Äœisdatigaj agordoj + +/community/moderate.bml.approve.button=Jes, mi permesas Äin + +/community/moderate.bml.approve.header=Ĉu vi permesas ĉi tiun enskribon? + +/community/moderate.bml.approve.preapprove=Cetere, aldonu uzanton [[user]] al la listo de antaÅ­-permesitaj uzantoj por ĉi tiu komunumo. + +/community/moderate.bml.approve.text=Ĉu vi certas pri la deziro permesi ĉi tiun enskribon? + +/community/moderate.bml.brlist.actions=Agoj + +/community/moderate.bml.brlist.poster=AfiÅanto + +/community/moderate.bml.brlist.subject=Komenco de titolo + +/community/moderate.bml.brlist.time=Tempo + +/community/moderate.bml.brlist.view=Rigardu + +/community/moderate.bml.browse.empty=La vico por moderigo estas malplena. + +/community/moderate.bml.browse.header=Moderigu Komunumon + +/community/moderate.bml.browse.text=Jen la vico por moderigi en la komunumo [[link]] + +/community/moderate.bml.choice.approve=Permesu + +/community/moderate.bml.choice.reject=Malpermesu + +/community/moderate.bml.error.noaccess=Vi ne moderigas la komunumon [[comm]]. + +/community/moderate.bml.error.noentry=Enskribo ne trovita (eble jam prizorgita de alia moderiganto). + +/community/moderate.bml.error.nolist=Vi ne moderigas iujn ajn komunumojn. + +/community/moderate.bml.error.notfound=Komunuma konto ne trovita. + +/community/moderate.bml.manage=Administru komunumojn + +/community/moderate.bml.moderate=Moderigi ĉi tiun komunumon + +/community/moderate.bml.modlist.actions=Agadoj + +/community/moderate.bml.modlist.actmodempty=[Moderigu] + +/community/moderate.bml.modlist.actmoderate=Moderigu + +/community/moderate.bml.modlist.count=Vica grandeco + +/community/moderate.bml.modlist.header=Moderigu Komunumojn + +/community/moderate.bml.modlist.title=Titolo + +/community/moderate.bml.modlist.username=Uzantnomo + +/community/moderate.bml.posted.appheader=AntaÅ­-permesita + +/community/moderate.bml.posted.apptext=Krome, la uzanto [[user]] estas nun en la listo de antaÅ­-permesita uzantoj por ĉi tiu komunumo. + +/community/moderate.bml.posted.header=Sukceso + +/community/moderate.bml.posted.proterror=La enskribo ne estas afiÅita, laÅ­ jena protokola eraro: [[err]] + +/community/moderate.bml.posted.text=La enskribo estas afiÅita sukcese. + +/community/moderate.bml.reject.button=Jes, malpermesu Äin + +/community/moderate.bml.reject.header=Ĉu malpermesu ĉi tiun enskribon? + +/community/moderate.bml.reject.reason=Vi ankaÅ­ povas klarigi al la afiÅanto viajn kialoj por malpermesi ties enskribon. La kialoj estas sendota al la afiÅanto retpoÅte. + +/community/moderate.bml.reject.text=Ĉu vi certas pri malpermesi ĉi tiun enskribon? + +/community/moderate.bml.rejected.header=Malpermesita + +/community/moderate.bml.rejected.text=La enskribon estas malpermesita. + +/community/moderate.bml.title=Komunuma Administrado + +/community/pending.bml.approve.title=Ĉu Aprobu MembriÄon? + +/community/pending.bml.no=Ne + +/community/pending.bml.nopending.title=Neniu pritraktata + +/community/pending.bml.yes=Jes + +/community/search.bml.button.clear=Malplenigu la Demandaron + +/community/search.bml.button.search=Serĉu! + +/community/search.bml.checkbox.onlywithpics=Nur komunumoj, kiuj havas bildojn + +/community/search.bml.label.byinterest=LaÅ­ Intereso + +/community/search.bml.label.bylocation=LaÅ­ Loko + +/community/search.bml.label.bytime=LaÅ­ Taglibra Äœisdatiga Horo + +/community/search.bml.label.city=Urbo: + +/community/search.bml.label.country=Lando: + +/community/search.bml.label.displayoptions=Montradaj Elektoj + +/community/search.bml.label.hasmember=Membras + +/community/search.bml.label.othercriteria=Aliaj Kriterioj + +/community/search.bml.label.outputformat=Eliga Formato: + +/community/search.bml.label.records=Nombro da rekordoj paÄe: + +/community/search.bml.label.searchcomm=Serĉu Komunumojn + +/community/search.bml.label.selecriteria=Elektu la malsuprajn kriteriojn, per tiuj vi volas trovi komunumojn. La rezultoj redonitaj estas la kongruaĵo de la tutaj serĉkriterioj. Alie dire, tuta markobutono, sur kiun vi klakas, signifas "AND" (kaj), ne "OR" (aÅ­). + +/community/search.bml.label.sortmethod=Ordiga Metodo: + +/community/search.bml.label.stateprovince=Åœtato/Provinco: + +/community/search.bml.label.updated=Äœisdatigita dum la lastaj + +/community/search.bml.sel.bypicture=LaÅ­ Bildo + +/community/search.bml.sel.communityname=Nomo de Komunumo + +/community/search.bml.sel.commview=Komunuma Vidaĵo + +/community/search.bml.sel.day=tago + +/community/search.bml.sel.month=monato + +/community/search.bml.sel.simple=Simpla + +/community/search.bml.sel.updatetime=Horo de Äœisdatigo + +/community/search.bml.sel.username=Uzantnomo + +/community/search.bml.sel.week=semajno + +/community/search.bml.title=Komunuma Serĉo + +/community/settings.bml.button.changecommunity=Äœisdatugu Preferigojn + +/community/settings.bml.button.createcommunity=Kreu Komunumon + +/community/settings.bml.error.badpassword=Malvalida komunuma pasvorto + +/community/settings.bml.error.hasentries=Ĉi tiu konto havas afiÅojn kaj ne povas esti konvertota. + +/community/settings.bml.error.maintainertype=Prizorganta konto devas esti homo, ne alia partoprenita konto. + +/community/settings.bml.error.noaccess=Nur komunumaj prizorgantoj eblas editi komunumajn preferigojn. Vi ne estas prizorganto de la komunumo [[comm]]. + +/community/settings.bml.error.notcomm=Ne estas komunuma konto. + +/community/settings.bml.error.notfound=Komunuma konto ne estas trovebla. + +/community/settings.bml.error.samenames=Prizorganta konto kaj komunuma konto ne povas esti la sama. + +/community/settings.bml.label.anybodycan=Ĉiuj Membroj
      Iu ajn povas tuj enskribi, post membriÄo. + +/community/settings.bml.label.changeheader=ÅœanÄi Komunumajn Preferigojn + +/community/settings.bml.label.changetext=Ĉi tie vi povas ÅanÄi la preferigojn por la komunumo propra aÅ­ prizorgata. + +/community/settings.bml.label.commchanged=Viaj komunumaj preferoj estas ÅanÄitaj. + +/community/settings.bml.label.commcreate=Ĉi tiu estas la konto, kiun vi volas komunumigi. Äœi devas jam esti kreita, sed ne devas esti uzata de individuo, ĉar post tiu, multaj diferencaj homoj eblas afiÅi en Äin, laÅ­ la potencioj. + +/community/settings.bml.label.commcreated=Via komunumo nun estas agordita. + +/community/settings.bml.label.commheader=Komunuma Konto + +/community/settings.bml.label.comminfo=Komunumaj informoj + +/community/settings.bml.label.commopts=Komunumaj preferigoj + +/community/settings.bml.label.commsite=TTT-ejo de komunumo + +/community/settings.bml.label.community=Komunumo: + +/community/settings.bml.label.createheader=Kreu Komunumon + +/community/settings.bml.label.createtext=De ĉi tie vi povas krei komunuman konton. Komunumo estas speciala kontotipo kien aliaj uzantoj povas aliÄi kaj enafiÅi. Por ekzemplo de komunumo, vizitu la Seattle-an Festan Komunumon. + +/community/settings.bml.label.howoperates=Elektu, kiel via komunumo funkcios. Vi povos ÅanÄi Äin pli poste. + +/community/settings.bml.label.maintainer=Prizorganto: + +/community/settings.bml.label.maintainer.login=Se tiu ne estas la prizorganta konto, ensalutu kromule. + +/community/settings.bml.label.managepage=Komunuma Administrado - por aldoni anojn, rajtigi afiÅadojn, enoficigi moderigantojn, ktp. + +/community/settings.bml.label.membership=MembriÄo + +/community/settings.bml.label.modheader=Moderigado + +/community/settings.bml.label.modis=Moderigita
      Novaj enskriboj devas esti permesitaj de moderiganto. + +/community/settings.bml.label.modisnt=Ne-moderigita
      Novaj enskriboj aperas tuj. + +/community/settings.bml.label.modtext=Ĉu malprotestoj al ĉi tiu komunumo estas moderigitaj? + +/community/settings.bml.label.nmcan=Ne-Membroj Povas AfiÅi
      Uzantoj povas afiÅi al ĉi tiu komunumo sen membriÄi. + +/community/settings.bml.label.nmcant=Ne-Membroj Ne Povas AfiÅi
      Uzantoj devas membriÄi en ĉi tiu komunumo por afiÅi en Äin.. + +/community/settings.bml.label.nmheader=Ne-Membra AfiÅo + +/community/settings.bml.label.nmtext=Ĉu uzantoj povas afiÅi al ĉi tiu komunumo sen membriÄu? + +/community/settings.bml.label.openmemb=Malfermita MembriÄo
      Iu ajn povas membriÄi sen aprobo. + +/community/settings.bml.label.password=Pasvorto: + +/community/settings.bml.label.postaccess=AfiÅa Atingo + +/community/settings.bml.label.rellinks=Ligiloj laÅ­temaj: + +/community/settings.bml.label.selcan=Elektu Membrojn
      Nur iuj membroj eblas afiÅi post li ricevis atingon de la prizorganta konto. + +/community/settings.bml.label.username=Uzantnomo: + +/community/settings.bml.label.whocanjoin=Kiu povas aliÄi al via komunumo? + +/community/settings.bml.label.whocanpost=Kiu povas afiÅi al ĉi tiu komunumo? + +/community/settings.bml.manage2=Administru komunumojn + +/community/settings.bml.members=[Membroj] + +/community/settings.bml.name=Komunuma nomo: [[name]] + +/community/settings.bml.success=Sukceso + +/community/settings.bml.title.create=Kreu Komunumon + +/community/settings.bml.title.modify=Komunumaj Preferigoj + +/create.bml.age.check.question=Ĉu vi havas malpli ol 13 jarojn? + +/create.bml.age.check.yes=Jes, mi havas malpli ol 13 jarojn. + +/create.bml.age.check2.question=Ĉu vi havas pli ol 13 anojn? + +/create.bml.age.check2.yes=Jes, mi havas pli ol 13 anojn. + +/create.bml.age.head=AÄo + +/create.bml.btn.create=Startu Ä´urnalon + +/create.bml.btn.proceed=DaÅ­rigu... + +/create.bml.captcha.answer=Respondo: + +/create.bml.captcha.audiodesc=Tajpu la numerojn, kiujn vi aÅ­das, por pruvi ke vi ne estas spamroboto: + +/create.bml.captcha.desc=Tajpu la literojn kaj numerojn, kiujn vi vidas sube, por pruvi ke vi ne estas spamroboto. Se vi ne povas legi la tekston, tajpu la vorton "AUDIO" kaj akceptu sonan teston anstataÅ­e. + +/create.bml.captcha.invalid=Malvalida respondo al antaÅ­a kontesto. Provu alian. + +/create.bml.captcha.play=Ludu la sonon. + +/create.bml.captcha.prove=Pruvu ke vi estas homa. + +/create.bml.clusterselect.cluster=Servilaro: + +/create.bml.clusterselect.clusternum=Servilaro [[number]] + +/create.bml.clusterselect.head=Servilara Elekto: + +/create.bml.clusterselect.nocluster=Neniu Servilaro + +/create.bml.clusterselect.text=Bonvolu selekti la servilaron, kien vi volas krei ĉi tiun konton. Komentario: Ĉi tiu nur estas Äustiga/testa elekto. Produkuktante, uzantoj ne elektos tiun aÅ­ scios iojn pri Äi. + +/create.bml.create.head=Krei Novan Taglibron + +/create.bml.create.text=Facilas krei novan Livejournal, nur sekvu la jenajn instrukciojn! + +/create.bml.email.head=Via retpoÅtadreso + +/create.bml.email.input.head=RetpoÅtadreso: + +/create.bml.email.text2=Pro verkontrolaj kaj sekurecaj celoj, ni bezonas vian retpoÅtadreson. Äœi neniam, je ia cirkonstanco, estos vendita au^ donita al spamistoj. Ni malamas tion pli ol io ajn. Legu nia privatecan politikon por pli informo. + +/create.bml.error.coppa.under13=BedaÅ­rinde, pro la Usonaj reguloj COPPA, vi ne rajtas uzi LiveJournal Äis vi havas 13 jarojn. Bonvolu reveni je via 13-a naskiÄtago. + +/create.bml.error.email.blank=Vi devas provizi vian retpoÅtadreson. + +/create.bml.error.email.lj_domain=Kreante konton, ne uzu alinomo de [[domain]]. Bonvolu entajpi alian retpoÅtadreson. + +/create.bml.error.email.nospaces=Ne permesatas spacoj en retpoÅtadreso. Se vi uzas AOL, memoru ke via Interreta RetpoÅtadreso estas via ekrannomo sen iu ajn spacoj, sekvata de @aol.com + +/create.bml.error.password.asciionly=Vi povas uzi nur ASCII-ajn simbolojn en la pasvorto. + +/create.bml.error.password.blank=Vi devas enmeti pasvorton. + +/create.bml.error.password.nomatch=Pasvortoj ne samas. + +/create.bml.error.postrequired=POST estas postulata. + +/create.bml.error.username.blank=Bonvolu doni nomon aÅ­ kaÅnomon. + +/create.bml.error.username.inuse=Uzantnomo jam uzatas; bonvolu elekti alian. + +/create.bml.error.username.iscode=Uzantnomo Åajnas esti invitaĵa kodo, ne uzantnomo. + +/create.bml.error.username.mustenter=Vi devas enmeti uzantnomon. + +/create.bml.error.username.reserved=BedaÅ­rinde, tiu uzantnomo estas reservita. + +/create.bml.errors.label=Bonvolu noti la sekvantajn problemojn, kaj rekonservu: + +/create.bml.initial.friend.lj_maintenance=Raportoj pri ambaÅ­ planitaj kaj neplanitaj senkonektadoj kaj funkcitenoj. + +/create.bml.initial.friend.news=Novaĵoj kaj eventoj de VivÄ´urnalo + +/create.bml.initialfriends=Aldonu tiujn taglibrojn al via listo de amikoj por sekvi novaĵojn de la paÄaro. + +/create.bml.initialfriends.heading=Amikoj de komencanto + +/create.bml.name.head=Via Nomo + +/create.bml.name.input.head=Nomo: + +/create.bml.name.text=Kio estas via nomo aÅ­ kaÅnomo? Äœi aperos je la supro de via taglibro, kaj en la uzanto-listo, se vi elektas aperiÄi tie. Vi ne devas doni vian kompletan nomon aÅ­ eĉ vian veran nomon. + +/create.bml.password.head=Pasvorto + +/create.bml.password.input.head1=Pasvorto: + +/create.bml.password.input.head2=Retajpu pasvorton: + +/create.bml.password.text=Elektu pasvorton. + +/create.bml.proceed.btn.proceed=DaÅ­rigu... + +/create.bml.proceed.warning=Nur unufoje premu DaÅ­rigu!! + +/create.bml.success.btn.enterinfo=Enmetu Personajn Informojn: + +/create.bml.success.head=Sukceso! + +/create.bml.success.text1=Via taglibro estas kreita. Gravaj informoj pri la registro estas enretpoÅtitaj al [[email]], kaj ili enhavas pli da instrukcio. Nepre konfirmu la taglibra kreado per klaki la ligilon en la mesaÄo. + +/create.bml.success.text2=Via LiveJournal haveblos ĉe: + +/create.bml.success.text3=Nun, bonvolu pasigi la tempon por plenskribi informojn pri vi mem. Äœi estas plimalpli nedeviga, sed Äi donas al ni ideon pri kiaj homoj uzas LiveJournal. + +/create.bml.title=Krei Novan Taglibron + +/create.bml.tos.error=Vi devas legi kaj akcepti la Servajn Kondiĉojn antaÅ­ krei konton. + +/create.bml.tos.haveread=Mi legis kaj akceptas la Servajn Kondiĉojn. + +/create.bml.tos.heading=Servaj Kondiĉoj + +/create.bml.tos.p1.2=AntaÅ­ daÅ­rigos, vi devas legi kaj konsenti pri la Servaj Kondiĉoj. + +/create.bml.useacctcodes.entercode=Por krei novan konton, enmetu kontan kreikodon. Por pli da informo, vizitu Kiel mi kreas konton? + +/create.bml.useacctcodes.welcome=Bonvenon + +/create.bml.username.box.head=Uzantnomo: + +/create.bml.username.charsallowed=Via uzantnomo povas konsisti nur el minusklaj literoj (a-z), ciferoj (0-9) kaj substreko-signo (_).
      AnkaÅ­ konsideru, ke la uzantnomo ne povas esti pli ol 15 signojn longa. + +/create.bml.username.forpaidaccts=AÅ­, por pagitaj kontoj: + +/create.bml.username.head=Uzantnomo + +/create.bml.username.ljaddress=Via taglibro estos je la jenaj adresoj: + +/create.bml.username.text=Ĉiu uzanto de [[sitename]] devas havi la propran unikan uzantnomon. Via uzantnomo aperas en la adreso de via taglibro, kaj vi uzos Äin por ensaluti je la servilo [[sitename]]. Äœi aperas ankaÅ­ kiam vi afiÅas komentojn al la taglibroj de aliaj homoj. + +/create.bml.username.username=uzantnomo + +/customize/index.bml.change=ÅœanÄu + +/customize/index.bml.choose=Ĉu vi deziras uzi la malnovan stilsistemon, aÅ­ la novan? + +/customize/index.bml.choose.header=Elektu stilsistemon + +/customize/index.bml.choose.s1=Malnova sistemo (S1) + +/customize/index.bml.choose.s2=Nova sistemo (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ne povis generi uzanta tavolo + +/customize/index.bml.error.fail_create_style=Kreo de nova stilo fiaskis. + +/customize/index.bml.error.not_your_layout=Ne via aranÄo. + +/customize/index.bml.error.not_your_theme=Ne via temo + +/customize/index.bml.error.no_core_parent=Nenia kerna gepatro? + +/customize/index.bml.previews=(AntaÅ­rigardoj) + +/customize/index.bml.s1=Oni konfiguras la malnovan stilsistemon per la Modifu Taglibron paÄo. + +/customize/index.bml.s1.header=Uzi S1 + +/customize/index.bml.s2.advanced.denied=Sole pagitaj, konstantaj, kaj frua-adoptantaj kont-propruloj rajtas uzi la altgrada individuiga areo. Malkovri la avantaÄojn de pagitaj kontoj. + +/customize/index.bml.s2.advanced.header=Altnivelaj Individuigaĵoj + +/customize/index.bml.s2.advanced.permitted=Por krei novajn tavolojn kaj stilojn de nenio, vizitu la altnivelan individuigadan centron. + +/customize/index.bml.s2.customize.language.header=Lingvo + +/customize/index.bml.s2.customize.settings.delete=Forigu Individuigaĵojn + +/customize/index.bml.s2.customize.settings.delete.confirm=Ĉu vi certas ke vi deziras forigi ĉi tiun individuigaĵojn? + +/customize/index.bml.s2.customize.settings.edit=Redaktu Individuigaĵojn + +/customize/index.bml.s2.customize.settings.header=ÅœanÄu individuajn agordojn + +/customize/index.bml.s2.related.header=Rilataj PaÄoj + +/delcomment.bml.confirm.banuser=Malpermesu, ke [[user]] komentu en via taglibro. + +/delcomment.bml.confirm.body=Ĉu vi certas, ke vi deziras forigi ĉi tiun komenton? + +/delcomment.bml.confirm.head=Ĉu forigu ĉi tiun? + +/delcomment.bml.confirm.spam=Marku, ke cxi tiu komento estas spamo + +/delcomment.bml.confirm.submit=Forigu komenton + +/delcomment.bml.error.alreadydeleted=La komento jam estas forigita. + +/delcomment.bml.error.cantdelete=Nur + +/delcomment.bml.error.cantdelete.comm=Komenton rajtas forigi nur Äia aÅ­toro, aÅ­toro de la enskribo aÅ­ komunum-estro. + +/delcomment.bml.error.nocomment=La komento ne ekzistas. + +/delcomment.bml.success.head=Forigita + +/delcomment.bml.success.noban=La komento estas forigita. + +/delcomment.bml.title=Forigu komenton + +/developer/index.bml.dbschema.header=Skemo de datumbazo + +/developer/index.bml.notice.header=Anonco + +/developer/index.bml.styles<< +Ĉu ne plaĉas al vi, kiel aspektas viaj taglibraj paÄoj? +Ne malesperu... ĉio estas fleksebla, kaj se vi legos la jenan instrukcion, vi scios ĉion, +kion vi bezonas por fari, ke viaj paÄoj aspektu kia ajn vi deziras. +. + +/developer/index.bml.styles.s1.header=Stila Sistemo 1 + +/developer/index.bml.styles.s1.system=Stila Sistemo + +/developer/index.bml.styles.s1.varlist=Listo de variabloj + +/developer/index.bml.styles.s1.views=Rigardu Tipojn + +/developer/index.bml.styles.s2.header=Stila Sistemo 2 + +/directory.bml.browse.country.title=Trarigardi Taglibrojn Lande + +/directory.bml.browse.usa.title=Trarigardi Taglibrojn UsonoÅtate + +/directory.bml.error.accounttype=Pardonu, via kontotipo ne permesas uzon de la adresaro, aÅ­ vi ne estas ensalutinta. Se via kontotipo permesas uzon de adresaro, certiÄu ke vi estas ensalutita kaj tiam reprovu. + +/directory.bml.navcrap.matches=[[count]] kongruaĵoj + +/directory.bml.open=Malfermu + +/directory.bml.post=AfiÅu + +/directory.bml.search.monkey=Centoj da dresitaj simioj nune ĉirkaukuras por trovi viajn serĉorezultojn. Bonvolu atendi. + +/directory.bml.search.new=Nova Informmendo + +/directory.bml.search.title=Serĉanta + +/directory.bml.update=Äœisdatu: + +/directory.bml.user=Uzanto + +/doc/index.bml.about=Bonvenon ĉe LiveJournal-a dokumentaro ripozejo, kie vi povas trovi informojn pri plej multe da temoj pri la servo de LiveJournal aÅ­ servila programaro. Bonvolu elekti temon el la subaj: + +/doc/index.bml.about.header=Bonvenon + +/doc/index.bml.docs.faq.about=Oftaj Demandoj pri LiveJournal.com + +/doc/index.bml.docs.faq.title=Oftaj Demandoj + +/doc/index.bml.docs.header=Dokumentoj + +/doc/index.bml.docs.howto.about=Konsiloj kaj konsiletoj por helpi individuigi vian LiveJournal-an konton + +/doc/index.bml.docs.server.about=Tutaj sciindoj kiuj ebligas vin de instali, administri kaj kodumi LiveJournal-an konton + +/doc/index.bml.docs.server.title=LiveJournal-a Servila Manlibro + +/doc/index.bml.docs.tour.about=Designita por novaj vizitantoj por kutimiÄi al la paÄo + +/doc/index.bml.docs.tour.title=Ekskurso + +/doc/index.bml.title=Dokumentaro + +/doc/index.bml.volunteering.about=Se vi Åatus helpi pri la dokumentaro de LiveJournal, vizitu la sekvantajn forumojn: + +/doc/index.bml.volunteering.header=Voluntaĵo + +/doc/index.bml.volunteering.ljsysdoc=Priparoladoj pri la dokumentara sistemo de LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=Fina uzula dokumentara priparoladoj + +/doc/tour/index.bml.clients.caption<< +LiveJournal-aj klientiloj estas malgrandaj programoj kiuj iras sur via komputilo, permesante al vi Äisdatigi vian taglibron kiam ajn vi estas interreta, sen malfermitu foliumilan fenestron. +Klientiloj haveblas por ja iu ajn platformo kaj multaj estas facile individuigeblaj. +. + +/doc/tour/index.bml.clients.title=Klientiloj + +/doc/tour/index.bml.comms.caption=LiveJournal estas granda interaktiva komunumo, do ne-surprezige ekzistas multaj membroj kun similaj interesoj. Por tio, ni ofertas kreeblon de komunumoj aÅ­ taglibroj al kiuj multajn homojn povas afiÅi. + +/doc/tour/index.bml.comms.title=Komunumoj + +/doc/tour/index.bml.create.caption=LiveJournal estas membriÄ-bazata taglibra komunumo. Ĉi tiu paÄo klarigas kion membriÄo sekvigas, kial membriÄo estas grava kaj la avantaÄojn de la membreÄo. Äœi ankaÅ­ enhavas la formularon por krei vian propran konton. + +/doc/tour/index.bml.create.title=Krei Konton + +/doc/tour/index.bml.friends.caption=Vi krome povas esti plej bone informita pri viaj geamikoj per LiveJournal uzante la inkluzivan funkcion "geamikoj". Se vi trovas taglibron kiu Åajnas interesa, aldonu Äin al via listo de geamikoj, kiu lasos vin legi tutajn da enskribojn de via geamikoj sur la sama paÄo. + +/doc/tour/index.bml.friends.title=Geamikoj + +/doc/tour/index.bml.intro.caption=Ĉi tiu turneo estas desegnita por novaj vizitantoj ekkoni pli multe pri la retpaÄo. Äœi montros al vi kie oni trovas la plej gravajn sekciojn, kaj ankaÅ­ iom da pli interesigaj trajtoj. + +/doc/tour/index.bml.intro.title=Bonvenon + +/doc/tour/index.bml.modify.caption=AnkaÅ­ eblas ke vi formatigi vian taglibron kelke diversmaniere, per uzi antaÅ­definitajn stilojn kaj kolorskemojn. Uniku vian taglibron laÅ­ vi volas! + +/doc/tour/index.bml.modify.title=Personigo + +/doc/tour/index.bml.nav.next=Posta --> + +/doc/tour/index.bml.nav.prev=<-- AntaÅ­a + +/doc/tour/index.bml.profile.caption=LiveJournal-aj membroj estas kuraÄigitaj aldoni informojn pri sin mem en siaj profiloj, do Äi donas al ni ideon pri kiaj homoj uzas LiveJournal kaj ni plej povas servi ilin. Tamen, neniuj de ĉi tiuj estas bezonataj — la solaj informoj bezonataj por komenci uzi LiveJournal-on estas nomo, retpoÅtadreso kaj pasvorto. + +/doc/tour/index.bml.profile.title=Profiloj + +/doc/tour/index.bml.sitemap.caption<< +Espereble ĉi tiu tureo donis al vi iom da helpemaj komencaj informoj pri la LiveJournal-a paÄo kaj servo. +Se vi bezonas helpon pri iu ajn LiveJournal-a, nehezitante kontaktu nian subtenan fakon. Se vi volas plu esplori, bonvolu viziti la TTT-eja mapo por vidi liston de la tutaj paÄoj je ĉi tiu TTT-ejo. +. + +/doc/tour/index.bml.sitemap.title=TTT-eja Mapo + +/doc/tour/index.bml.support.caption=La subtena paÄo listas areojn kiuj helpas komprenigi kio LiveJournal estas, oftajn demandojn pri la TTT-ejo, kaj aliajn helpemajn informojn pri la servo, la kompanio kaj la komunumo grande. + +/doc/tour/index.bml.support.title=Ricevas Helpon + +/doc/tour/index.bml.title=Tureo - [[title]] + +/doc/tour/index.bml.update.caption=Äœisdatigi LiveJournal-on estas la kerno de la LiveJournal-a servo; ĉi tie ni ofertas al membroj Åancon de partopreni siajn vivojn kaj diri siajn opinion. Äœisdatigi LiveJournal-on estas facile. Simple skribu afiÅon en la havigitan kestenon kaj klaku la "Äœisdatigu Taglibron" butonon. Kompreneble, ni ankaÅ­ ofertas progresintajn trajtojn je nia Äisdatiga paÄo, kiel la kontroleblo de ortografiaj eraroj kaj la provizeblo de ekstraj informoj pri viaj afiÅoj, kio estas via nuna muziko aÅ­ nuna humoro. + +/doc/tour/index.bml.update.title=Äœisdatigi + +/editinfo.bml.allowshowcontact.about=Vi devus restigi ĉi tiun elekton ebligita. Ĉi tio permesas ke aliaj homoj eblas kontakti vin per montri vian retpoÅtadreson, ICQ-an numeron kaj AOL-an tujmesaÄilan ekrannomon tute en via LiveJournal. + +/editinfo.bml.allowshowcontact.email=Se videbla, retpoÅtadreso por montri: + +/editinfo.bml.allowshowcontact.email.actual_only=Nur vera adreso + +/editinfo.bml.allowshowcontact.email.both=AmbaÅ­ (vera + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Nur LiveJournal-a adreso + +/editinfo.bml.allowshowcontact.email.neither=Neniu. Ne montru iun ajn retpoÅtadreson. + +/editinfo.bml.allowshowcontact.email.no_show=Ne montru retpoÅtadreson + +/editinfo.bml.allowshowcontact.email.show=Montru retpoÅtadreson + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Per la elekto supra, vi ankaÅ­ elekteblas kaÅi vian retpoÅtadreson (ankoraÅ­ montrante aliajn kontaktinformojn), aÅ­ nur montri vian LiveJournal-an retpoÅtadreson (nur Pagitaj Kontoj), aÅ­ nur montri vian veran adreson, aÅ­ montri ambaÅ­ ilin. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Per la elekto supra, vi ankaÅ­ elekteblas kaÅi vian retpoÅtadreson (ankoraÅ­ montrante aliajn kontaktinformojn). + +/editinfo.bml.allowshowcontact.title=Ĉu montru viajn kontaktajn informojn en via LiveJournal? + +/editinfo.bml.allowshowinfo.about=Åœaltu ĉi tion, se vi volas ke aliaj uzantoj vidos vian urbon/Åtaton/landon kaj naskiÄtagon. + +/editinfo.bml.allowshowinfo.title=Ĉu montru lokon & naskiÄtagon? + +/editinfo.bml.autotranslate.about<< +Elektu kiun enkodigon supozi por viaj afiÅoj kaj komentoj enmetitaj antaÅ­ ol la paÄaro unikodiÄis. +Se vi skribas angle, elektu "Western European" ĉi tie. +. + +/editinfo.bml.autotranslate.header=AÅ­tomate traduku malnovajn enskribojn el: + +/editinfo.bml.bday.title=NaskiÄtago + +/editinfo.bml.bday.year.opt=jaro ne devigatas + +/editinfo.bml.bdayreminders.about=Se vi deziras ricevi retpoÅtojn por memorigi vin pri geamikaj naskiÄtagoj, klaku ĉi tiun kvadraton. + +/editinfo.bml.bdayreminders.header=Sendu al mi naskiÄtagajn memorigojn (nuntempe malebligita) + +/editinfo.bml.bio.about=Vi povas enskribi biografieton pri vi mem kiu aperos en via Uzant-Informa paÄo. + +/editinfo.bml.bio.header=Pri Vi + +/editinfo.bml.blockrobots.about=Se vi markos ĉi tiun elekton, la sistemo diros al robotoj, ke ili foriru. Ne ĉiuj robotoj obeas la regulojn. + +/editinfo.bml.blockrobots.header=Malebligu, ke robotoj/araneoj indeksu vian taglibron + +/editinfo.bml.chat.aolim.title=AOL-Nomo + +/editinfo.bml.chat.icquin.title=ICQ-Numero + +/editinfo.bml.chat.msnusername.title=MSN Uzantnomo + +/editinfo.bml.chat.yahooid.title=Yahoo!-ID + +/editinfo.bml.city.title=Urbo + +/editinfo.bml.country.choose=Elektu landon + +/editinfo.bml.country.title=Lando + +/editinfo.bml.donotlog=Ne + +/editinfo.bml.email.title=RetpoÅtadreso + +/editinfo.bml.enableboards.about=Marku tiun, se vi volas ke homoj eblas respondi al viaj taglibraj afiÅoj. + +/editinfo.bml.enableboards.header=Ebligu komentoj + +/editinfo.bml.encoding.about=Ne maltrankviliÄu pri ĉi tiuj umoj. Äœenerale, nur uzantoj kiuj skribas plurlingve devas ÅanÄi ion ĉi tie. + +/editinfo.bml.encoding.header=Kodoprezentaj Elektoj + +/editinfo.bml.error.day.notinmonth=Nevalida tago por tiu monato. + +/editinfo.bml.error.day.outofrange=Nevalida tago por nasktago. Entajpu tagon de 1 Äis 31. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Vi ne entajpu retpoÅtadreson de @[[domain]]. +Entajpu vian veran retpoÅtadreson en tiu kampo. +Se vi estas paginto, via adreso [[user]]@[[domain]] ekspedos al via vera adreso. +Por elekti kiu adreso montriÄos (aÅ­ la ambaÅ­), vidu la elekton sub la elekto "Montru vian Kontaktan Informon". +. + +/editinfo.bml.error.email.none=Vi devas provizi vian retpoÅtadreson + +/editinfo.bml.error.email.no_space<< +Neniuj spacoj permesatas en retpoÅta adreso. +Se vi uzas AOL-n, memoru ke via retpoÅtadreso estas via ekrannomon escepte de ĉiuj spacoj forprenitaj, sekvita de @aol.com + +. + +/editinfo.bml.error.excessive_int=BedaÅ­ron; vi listigis tro multe da interesoj. La limo estas 150, sed vi listigis [[intcount]]. Iuj ajn ÅanÄoj, kiujn vi faris al viaj interesoj, ne konserviÄis. Iru reen kaj malpliigu vian liston, kaj poste konservu denove. + +/editinfo.bml.error.invalidbio=Via konservita historieto enhavas malvalidajn literojn. Vi vizitu la konvertatan paÄon por konverti Äin al Unikodo. + +/editinfo.bml.error.invalidints=Via nuna konservita listo de interesoj enhavas malvalidajn literojn. Vi vizitu la konvertan paÄon por konverti la liston al Unikodo. + +/editinfo.bml.error.invalidname=Via nomo enhavas malvalidajn literojn. Vi vizitu la konvertatan paÄon por konverti Äin al Unikodo. + +/editinfo.bml.error.locale.country_ne_state=Vi specifis Usonon por via lando, sed vi tajpis neusonan Åtaton en la kampon por "alia Åtato". + +/editinfo.bml.error.locale.invalid_country=Iel, vi elektis nevalidan landon. + +/editinfo.bml.error.locale.state_ne_country=Vi specifis neusonan landon sed elektis usonan Åtaton. + +/editinfo.bml.error.locale.zip_ne_state<< +Via poÅtkodo ne akordas kun la Åtato, kiun vi specifis. +AÅ­ Äustigu la informojn, aÅ­ forigu unu aÅ­ ambaÅ­ el la Åtata kaj poÅtkoda kampoj. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Vi enskribis poÅtkodon, sed vi ne elektis Usonon por via lando. +Ni kolektas poÅtkodajn informojn nur pri usonanoj. +Bonvolu iri reen kaj forigu la poÅtkodon aÅ­ elektu Usonon por via lando. + +. + +/editinfo.bml.error.month.outofrange=Nevalida monato por nasktago. Entajpu monaton de 1 Äis 12. (jan-dec) + +/editinfo.bml.error.noname=Vi devas enmeti vian nomon en la formularon. AlmenaÅ­ enmetu vian antaÅ­nomon aÅ­ salutnomon. + +/editinfo.bml.error.tm.require.number=Se vi uzos tekstan mesaÄumon, vi devas enskribi vian telefonnumeron. + +/editinfo.bml.error.tm.require_provider<< +Por tekstmesaÄi, vi devas elekti vian Interret-peranton. + +Se via Interretperanto ne estas en la listo, bonvolu kontakti nin kun informo pri via tekstmesaÄa komplezo, tial ke ni povas kongruigi Äin. +. + +/editinfo.bml.error.year.notenoughdigits=Nevalida jaro por nasktago. Entajpu 4-ciferan jaron. + +/editinfo.bml.error.year.outofrange=Nevalida jaro por nasktago. + +/editinfo.bml.finished.about=Kiam vi finos, premu la malsupran Åaltilon "Konservu ÅœanÄojn": + +/editinfo.bml.finished.header=Ĉu finita? + +/editinfo.bml.finished.save_button=Konservu ÅœanÄojn + +/editinfo.bml.gender.title=Genro + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Marku tiun, se vi volas ricevi retpoÅtajn Äisdatigojn kiam homoj respondas al viaj taglibraj afiÅoj en la mesaÄejoj. + +/editinfo.bml.getreplies.header=Ricevu mesaÄarajn respondojn + +/editinfo.bml.getselfemails.header=EnretpoÅtigu la proprajn komentojn + +/editinfo.bml.hidefriendof.about=Se vi elektas ĉi tion, la listo de personoj, kiuj havas vin en sia listo de geamikoj, kaÅiÄos ĉe via uzant-informa paÄo. + +/editinfo.bml.hidefriendof.header=KaÅu "Amiko de" liston + +/editinfo.bml.howhear.about<< +Nur tial scivolemaj motivoj, de kie vi aÅ­dis pri [[sitename]]? +Se Äi estis specifa persono, enskribu ties uzantnomon; se Äi estis alia fonto/artikolo/ligilo/retpaÄo, aldonu la konvenajn informojn. +. + +/editinfo.bml.howhear.header=Scivolemo + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Marku se via retpoÅta programo plene subtenas HTML en viaj retpoÅto. +Multe da klientiloj provas subteni Äin, sed malsukcesas terure. +Se vi malmarkas Äin, LiveJournal nur sendos tekstajn retpoÅtojn. +. + +/editinfo.bml.htmlemail.header=Sendu HTML-ajn RetpoÅtmesaÄojn + +/editinfo.bml.int.about=Se vi volas, ke aliaj homoj povos serĉi la adresaron kaj trovi vin per intereso, listu malsupre ĉion, kio interesas vin, apartigitaj per komoj. Mallongaj unu-vortaj esprimoj estas plej bonaj. Äœenerala regulo: Eblu uzi la intereson en la frazo "(La) [io] plaĉas al mi". Aludante al substantivoj, uzu la pluralan formon por uniformeco: "La viddiskoj plaĉas al mi" anstataÅ­ "La viddisko plaĉas al mi". + +/editinfo.bml.int.ex.bad=MALBONA Ekzemplo: Plaĉas al mi multaj muzikistaroj kaj iri al kinejoj kaj paroli kun amikoj kaj iri al diskokluboj. Metu tiaj umoj supre en vian biografieton. + +/editinfo.bml.int.ex.good=BONA Ekzemplo: biciklado, neÄoskiado, komputiloj, viddiskoj, MP3oj, kesoj, virinoj + +/editinfo.bml.int.header=Interesoj + +/editinfo.bml.login.enterinfo=Enskribu vian uzantnomon kaj pasvorton por ÅanÄi viajn personajn informojn. + +/editinfo.bml.login.forgot.header=Ĉu vi forgesis ion? + +/editinfo.bml.login.forgot.recover=Se vi forgesis vian uzantnomon au pasvorton, rehavigu Äin ĉi tie! + +/editinfo.bml.logip.always=Ĉiam + +/editinfo.bml.logip.anon_only=Nur anonimaj afiÅantoj + +/editinfo.bml.logip.header=Ĉu registru IP-adresojn de respondantoj? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Se vi timas ke spam-robotoj povus trovi vian retpoÅtadreson ĉe LiveJournal, elektu ĉi tiun elekton. Via retpoÅtadreso estas modifota, do Äi ne estos trovebla de retpoÅtkolektantaj robotoj. + +/editinfo.bml.mangleaddress.header=Malklarigu vian montratan retpoÅtadreson + +/editinfo.bml.name.title=Nomo + +/editinfo.bml.newemail.subject=RetpoÅtadreso ÅœanÄita + +/editinfo.bml.numcomments.about=Marku tiun se vi volas aldoni la komentan nombron al URL-oj por vidigebligi la ligilojn aliakolore. + +/editinfo.bml.numcomments.header=Aldonu &nc=xx al komentaj URL-oj + +/editinfo.bml.optional=nedeviga + +/editinfo.bml.opt_in.about=Se vi volas scii kiam ni estas aldonantaj kelkan bonegan novan eblon al LiveJournal, marku tiun butonon. Ni ne estas nuntempe uzanta ĉi tiun eblon, sed ni eble uzos Äin pli poste. Via retpoÅtadreso ne estos videbla por aliaj uzantoj, kaj vi povas malelekti Äin ĉiam kiam vi volas. + +/editinfo.bml.opt_in.header=Sendu al mi novaĵojn (en la angla) pri LiveJournal. + +/editinfo.bml.persinfo.disclaimer=Enskribu kelkajn mallongajn informojn pri vi mem, por nia propra scivolemo kaj statistikaj celoj. Ni ne estas faronta ian fian aÅ­ enuigantan per tiuj informoj; ni nur volus vidi kiuj kaj kie estas niaj uzantoj. Bonvolu plenigi Äin Äuste. Se vi okupiÄas, legu nian privatecan politikon. + +/editinfo.bml.persinfo.header=Personaj Informoj + +/editinfo.bml.screen.all=Ĉiuj + +/editinfo.bml.screen.anon=Sennomaj + +/editinfo.bml.screen.header=Kiajn respondojn vi volas havi kaÅantajn defaÅ­lte? + +/editinfo.bml.screen.none=Neniuj + +/editinfo.bml.screen.nonfriends=De ne-geamikoj + +/editinfo.bml.screen.nonmembers=De ne-membroj + +/editinfo.bml.security.header=Kiu rajtas vidi viajn kontaktajn informojn? + +/editinfo.bml.security.visibility.anybody=Iu ajn + +/editinfo.bml.security.visibility.everybody=Ĉiu + +/editinfo.bml.security.visibility.friends=Nur geamikoj + +/editinfo.bml.security.visibility.regusers=Registritaj Uzantoj + +/editinfo.bml.settings.friendspage.title=Titolo de Geamikara PaÄo: + +/editinfo.bml.settings.friendspage.title.optional=Se vi deziras, enmetu titolon por viaj geamikaraj paÄoj (sen HTML). + +/editinfo.bml.settings.header=LiveJournal-aj Elektoj + +/editinfo.bml.settings.journal.subtitle=Ä´urnala Subtitolo: + +/editinfo.bml.settings.journal.title=Taglibra Titolo: + +/editinfo.bml.settings.privacy.header=Privatecaj Alternativoj + +/editinfo.bml.state.other=AÅ­ tajpu alian Åtaton/provincon/teritorion + +/editinfo.bml.state.title=Åœtato + +/editinfo.bml.state.us=Usonaj Åœtatoj + +/editinfo.bml.success.header=Sukceso! + +/editinfo.bml.success.message=Viaj informoj kaj taglibraj preferigoj kaj profilo estas Äisdatigitaj. + +/editinfo.bml.switch.button=InterÅanÄu + +/editinfo.bml.switch.header=InterÅanÄu Taglibron + +/editinfo.bml.switch.workwith=Uzu tiun taglibron: + +/editinfo.bml.title=Redaktu Personajn Informojn + +/editinfo.bml.tm.details=detaloj + +/editinfo.bml.tm.phonenum=Plena telefona numero: + +/editinfo.bml.tm.sec.about=Kapabligu tekstan mesaÄadon de aliaj uzantoj. + +/editinfo.bml.tm.sec.title=Sekureca Nivelo: + +/editinfo.bml.tm.servprov=Serva Provizanto + +/editinfo.bml.tm.title=Teksta MesaÄado + +/editinfo.bml.translatemailto.about=En la okazo se vi elektis ricevi mesaÄtabulajn respondojn retpoÅte, kaj via retpoÅta klientilo ne traktas unikodajn (UTF-8) mesaÄojn tre bone, uzu tiun elekton por specifi malsaman kodoprezenton en kiun LiveJournal aÅ­tomate transformos la tekston de la komentoj senditaj al vi. + +/editinfo.bml.translatemailto.header=Traduku retpoÅtajn informiÄojn en: + +/editinfo.bml.unbanusers.about=Vi malpermesis al la sekvantajn uzantojn afiÅi en via taglibron. Marku la markobutonon apud iliaj uzantnomoj por elpreni la malpermeson el ili. + +/editinfo.bml.unbanusers.header=Repermesu Uzantojn + +/editinfo.bml.userpic.about=Jen supre maketa bildo kiun vi alÅutis por reprezenti vin en la tuta LiveJournal-a paÄo, en via taglibro, kaj en la taglibroj de viaj amikoj: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Por forigi ĉi tiun bildon aÅ­ alÅuti novan, iru tien. + +/editinfo.bml.userpic.header=Via Bildo + +/editinfo.bml.userpic.none=bildo ne alÅutiÄis + +/editinfo.bml.webpagename.title=Nomo de TTT-ejo + +/editinfo.bml.webpageurl.title=URL-o de TTT-ejo + +/editinfo.bml.whoreply.header=Kiu rajtas respondi al viaj enskriboj? + +/editinfo.bml.zip.title=PoÅtkodo + +/editinfo.bml.zip.usonly=5-cifera poÅtkodo; nur por usonanoj + +/editjournal.bml.btn.proceed=DaÅ­rigu... + +/editjournal.bml.certainday=Specifa Tago: + +/editjournal.bml.in=En komunumo: + +/editjournal.bml.recententries=plej lastatempaj enskriboj + +/editjournal.bml.recententry=Plej lastatempa enskribo + +/editjournal.bml.title=Redaktu Taglibrajn Enskribojn + +/editjournal.bml.viewwhat=Vidu Kiujn Enskribojn: + +/editjournal_do.bml.btn.delete=Forigu Taglibran Enskribon + +/editjournal_do.bml.btn.edit=Redaktu Elektitan Enskribon + +/editjournal_do.bml.btn.preview=AntaÅ­rigardu Enskribaĵon + +/editjournal_do.bml.btn.save=Konservu Taglibran Enskribon + +/editjournal_do.bml.continue.head=Premu por daÅ­rigi... + +/editjournal_do.bml.continue.text=Post vi elektis eron por redakti aÅ­ forigi, premu la Redaktu butonon malsupre. + +/editjournal_do.bml.currmood=Nuna Humoro: + +/editjournal_do.bml.currmusic=Nuna Muziko: + +/editjournal_do.bml.date=Dato: + +/editjournal_do.bml.default=defaÅ­lto + +/editjournal_do.bml.delete.confirm=Ĉu vi certas, ke vi volus forigi tiun afiÅon? + +/editjournal_do.bml.edit.text=Jen la taglibra enskribo, kiun vi elektis redakti. ÅœanÄu ĉiujn la informojn, kiujn vi volas, kaj poste klaku la butonon "Konservu Taglibra Enskribo" sube.

      Por forigi la enskribon, forigu la tutan tekston en la kamparo kaj poste klaku la butonon "Konservu Taglibra Enskribo" sube. + +/editjournal_do.bml.error.getting=Eraro okzazis dum provi redakti la taglibrajn enskribojn: + +/editjournal_do.bml.error.modify=Eraro okzazis dum modifi vian taglibron: + +/editjournal_do.bml.error.nofind=Ne eblis trovi elektitan taglibran enskribon. + +/editjournal_do.bml.event=Evento: + +/editjournal_do.bml.localtime=Loka horo: + +/editjournal_do.bml.noneother=Neniu, aÅ­ alia: + +/editjournal_do.bml.opt.backdate=Retrodatu Enskribon: + +/editjournal_do.bml.opt.backdate.about=ne aperos sur geamikoj vido + +/editjournal_do.bml.opt.nocomments=Malpermesu Komentojn: + +/editjournal_do.bml.opt.noemail=Ne retpoÅtu Komentojn: + +/editjournal_do.bml.opt.noformat=Ne aÅ­tomate formatu: + +/editjournal_do.bml.other=Aliaj: + +/editjournal_do.bml.pickentry.head=Elektu enskribon por redakti + +/editjournal_do.bml.pickentry.text=Elektu la redaktendan eron kaj premu la redaktu-butonon malsupre sur la paÄo. + +/editjournal_do.bml.picture=Uzu la bildon: + +/editjournal_do.bml.preview.header=AntaÅ­rigardu Enskribaĵon + +/editjournal_do.bml.save.head=Premu por konservi... + +/editjournal_do.bml.save.text=Post vi finis redakti vian taglibran enskribon, premu Konservu. + +/editjournal_do.bml.subject=Subjekto: (nedeviga) + +/editjournal_do.bml.success.delete=La taglibra enskribo estas forigita. + +/editjournal_do.bml.success.edit=Via enskribo nun estas redaktita. Vi povas vidi Äin ĉi tie. + +/editjournal_do.bml.success.head=Sukceso + +/editjournal_do.bml.timeformat=24-hora tempo + +/editjournal_do.bml.title=Redaktu Taglibrajn Enskribojn + +/editpics.bml.btn.save=Konservu Agordojn + +/editpics.bml.curpics=Nunaj Bildoj + +/editpics.bml.error.filetoolarge=La alÅutita bildo estas tro granda. La grandeco de la dosiero ne rajtas preteri [[maxsize]]. + +/editpics.bml.error.invalidimage=Nevalida formato de dosiero. + +/editpics.bml.error.toomanypics2=Vi jam havis la maksimumon el [[maxpics]] bildoj. Vi ne povas alÅuti la novan bildon, se vi ne forigas iun el la nun ekzistantaj. + +/editpics.bml.fromfile=El dosiero: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=d + +/editpics.bml.fromurl=De URL: + +/editpics.bml.imagesize.by|notes=This character is inserted between two numbers to indicate "by" when specifying image dimensions, for example "100x100". +/editpics.bml.imagesize.by=p + +/editpics.bml.kilobytes=Kbajt + +/editpics.bml.restriction.fileformat=Formato de la dosiero devas esti PNG, GIF aÅ­ JPG + +/editpics.bml.restriction.filesize=La dosiero ne povas esti pli granda ol 40 KB + +/editpics.bml.restriction.imagesize=La bildo ne povas esti pli granda ol 100x100 punktoj. + +/editpics.bml.uploadheader=Aldonu novan bildon + +/export.bml.btn.proceed=Progresu... + +/export.bml.description|staleness=1 +/export.bml.description=Ĉi tiu trajto elÅutebligas vian tutan taglibron al kutiman formaton por restaÅ­rkopion. + +/export.bml.fields=Ĉeloj: + +/export.bml.format.csv=CSV (Kome Subdividitaj Valoroj) + +/export.bml.label.encoding=Kodoprezento: + +/export.bml.label.field.allowmask=Permesi Maskon + +/export.bml.label.field.currents=Nuna Humoro & Muziko + +/export.bml.label.field.event=Evento + +/export.bml.label.field.eventtime=Eventa Tempo (de uzanta horloÄo) + +/export.bml.label.field.itemid=ID-Numero + +/export.bml.label.field.logtime=Protokola Tempo (de sistema horloÄo) + +/export.bml.label.field.security=Sekureca Nivelo + +/export.bml.label.field.subject=Subjekto + +/export.bml.label.format=Formato + +/export.bml.label.header=Ĉapo + +/export.bml.label.month=Elektu monaton: + +/export.bml.label.month.year=jjjj: + +/export.bml.label.notranslation=Ne traduku inter kodoprezentoj + +/export.bml.label.what=Eksporti kion: + +/export.bml.title=ElÅutu la Taglibron + +/export.bml.what.entries=Taglibraj enskriboj + +/friends/add.bml.add.header=Sukceso + +/friends/add.bml.add.text=La uzanto [[ljuser]] aldoniÄis al via listo de geamikoj. Vi povas vidi vian geamikan paÄon ĉi tie. + +/friends/add.bml.add.title=Geamiko AldoniÄis! + +/friends/add.bml.btn.add=Aldonu [[user]] + +/friends/add.bml.btn.modify=Modifu + +/friends/add.bml.btn.remove=Forigu + +/friends/add.bml.colors.bg=Fono + +/friends/add.bml.colors.fg=Malfono + +/friends/add.bml.colors.header=Koloro + +/friends/add.bml.colors.hover=(Movu vian muson super koloron por vidi sian nomon) + +/friends/add.bml.colors.text=Vi ankaÅ­ povas elekti la koloron kiu reprezentos [[user]] en via listo de geamikoj. + +/friends/add.bml.confirm.header=Ĉu aldoni [[user]] kiel geamikon? + +/friends/add.bml.confirm.text=Por aldoni [[user]] al via listo de geamikoj, klaku la butonon sube. + +/friends/add.bml.confirm.title=Aldonu Geamikon + +/friends/add.bml.error1.header=Unue Ensalutu + +/friends/add.bml.error1.text=Por aldoni uzanton al via listo de geamikoj, vi unue devas ensaluti. Se vi ne jam havas konton, vi povas krei Äin por traki viajn geamikajn taglibrojn. + +/friends/add.bml.error1.title=Aldonu Geamikon + +/friends/add.bml.error2.text=Malvalida aÅ­ mankanta uzantnomo. Por aldoni geamikon, vizitu la redaktu geamikojn paÄon. + +/friends/add.bml.error3.text=Vi jam havas [[user]] sur via listo de geamikoj. Tamen, vi povas modifi la kolorojn kiuj vi elektis por reprezenti lin/Åin. + +/friends/add.bml.error3.title=Modifu Geamikon + +/friends/add.bml.groups.header=Geamikaj Grupoj + +/friends/add.bml.groups.nogroup=Neniuj geamikaj grupoj starigitas. + +/friends/add.bml.groups.text=En kiu geamikan grupon vi volas meti ĉi tiun uzanton? Geamikaj grupoj estas uzataj por filtri la vidon de via listo de geamikoj kaj ankaÅ­ por grup-bazita vidada sekureco de erojn. + +/friends/add.bml.remove.header=Sukceso + +/friends/add.bml.remove.text=Uzanto estas forigita el via listo de geamikoj. Vi povas vidi vian geamikan paÄon ĉi tie. + +/friends/add.bml.remove.title=Geamiko forigitas! + +/friends/edit.bml.title=Redaktu Geamikojn + +/friends/editgroups.bml.btn.ge.del=Forigu + +/friends/editgroups.bml.btn.ge.new=Nova + +/friends/editgroups.bml.btn.ge.ren=Renomu + +/friends/editgroups.bml.btn.gs.private=Privata + +/friends/editgroups.bml.btn.gs.public=Publika + +/friends/editgroups.bml.btn.mv.down=Movu malsupren + +/friends/editgroups.bml.btn.mv.up=Movu supren + +/friends/editgroups.bml.confirm.delete=Ĉu vi certas ke vi viÅas forigi ĉi tiun kutiman geamikan grupon? + +/friends/editgroups.bml.done.btn=Konservu ÅœanÄojn + +/friends/editgroups.bml.done.header=Ĉu finita? + +/friends/editgroups.bml.done.text=Kiam vi estas finita, premu la malsupran butonon por konsevi viajn ÅanÄojn. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Vi atingis la maksimuman limon de 30 kutimajn geamikajn grupojn. Se vi forigi unu aÅ­ pli multe da grupojn, sed ne ankoraÅ­ konservis la ÅanÄojn, faru Äin nun, tiem returnu al ĉi tiu paÄo kaj reÅarÄu Äin. Vi poste eblas krei novajn kutimajn geamikajn grupojn. + +/friends/editgroups.bml.error.text=La servilo redonis la sekvantan erar-mesaÄon: + +/friends/editgroups.bml.group.public=(publika) + +/friends/editgroups.bml.ingroup=En grupo: + +/friends/editgroups.bml.ingroup.not=Ne en grupo: + +/friends/editgroups.bml.prompt.newname=Enskribu la nomon por la nova kutima geamika grupo: + +/friends/editgroups.bml.prompt.rename=Renomu ĉi tiun kutiman geamikan grupon en: + +/friends/editgroups.bml.saved.header=Konservita + +/friends/editgroups.bml.saved.text=Viaj kutimaj geamikaj grupoj nun konservitaj. + +/friends/editgroups.bml.text<< +Ĉi-paÄo ebligas al vi redakti viajn grupojn de amikoj. La grupoj de amikoj povas esti uzataj por sekurecaj agordoj kaj por filtrado de via paÄo de amikoj. Trovu helpon ĉe Kio estas grupoj de amikoj? Kiel mi uzu ilin? + +La paÄo bezonas JavaSkripton por bone funkcii. +. + +/friends/editgroups.bml.text.sec=Sekurecan noto: Se vi volas forigi grupon kaj krei novas, ne faru Äin renomante unu grupon kaj redakti Äin tiam. Se vi faras tiun, tute da viaj antaÅ­aj enskriboj kiuj estas videblaj por la malnova grupo, tiam videbligos por la nova grupo. + +/friends/editgroups.bml.title=Redaktu Kutimajn Geamikajn Grupojn + +/friends/editgroups.bml.yourgroups=Via kutimaj geamikaj grupoj: + +/friends/edit_do.bml.addfriends.head=Aldonu Geamikojn + +/friends/edit_do.bml.addfriends.text=Enskribu la LiveJournal-an uzantnomon de via geamikoj en la ĉelon malsupran, kaj elektu la kolorojn fonajn kaj malfonajn kiujn vi volas havi por ilin... + +/friends/edit_do.bml.background=Fono + +/friends/edit_do.bml.bgcolor=Fonan Koloro: + +/friends/edit_do.bml.btn.close=Fermu + +/friends/edit_do.bml.btn.save=Konservu ÅœanÄojn + +/friends/edit_do.bml.btn.toggle=Baskulu AntaÅ­rigardan Fenestron + +/friends/edit_do.bml.done.head=Ĉu finita? + +/friends/edit_do.bml.done.text=Kiam vi finitis, premu la "Konservu ÅœanÄojn" butonon malsupre... + +/friends/edit_do.bml.error.updating=Okazis eraro dum Äisdatigi vian listo de geamikoj: + +/friends/edit_do.bml.fellowfriends.head=Kameradoj + +/friends/edit_do.bml.fellowfriends.text=La sekvantaj homoj listigis vin kiel amikon. Vi eblas ankaÅ­ listigi ilin kiel vian amikon. Ĉi tiu estas provizita kiel referecon, do vi konas iliajn LiveJournal-ajn uzantnomojn. Tamen, vi ne devas aldoni ilin al via listo. + +/friends/edit_do.bml.foreground=Malfono + +/friends/edit_do.bml.friend=Geamiko + +/friends/edit_do.bml.hover=Movi vian muson super koloron por vidi sian nomon + +/friends/edit_do.bml.mrcolor=S-ro Kolor-Vidilo + +/friends/edit_do.bml.name=Nomo + +/friends/edit_do.bml.needmore=Se vi bezonas aldoni pli da geamikoj ol vi havas ĉelojn en ĉi tiu formo, konservu la ÅanÄojn malsupre, kaj poste revenu por aldoni pluajn. + +/friends/edit_do.bml.nofriends.head=Neniuj Geamikoj? + +/friends/edit_do.bml.nofriends.text=Vi nun ne havas iujn ajn geamikojn difinitajn. Tamen, ni estas certaj ke vi devas havi kelkajn geamikojn! :) Simple enskribu iliajn VivÄ´urnalajn nomojn malsupre... + +/friends/edit_do.bml.opt.addtolist=Aldonu amikon + +/friends/edit_do.bml.opt.delete=Ĉu Forigu? + +/friends/edit_do.bml.success.head=Sukceso + +/friends/edit_do.bml.success.text|staleness=1 +/friends/edit_do.bml.success.text=Viaj geamikoj estas Äisdatigitaj. Vi povas rigardi vian denove Äisdatigitan geamikan paÄon ĉi tie. + +/friends/edit_do.bml.textcolor=Teksta Koloro: + +/friends/edit_do.bml.title=Redaktu Geamikojn + +/friends/edit_do.bml.user=Uzanto + +/friends/edit_do.bml.viewer=Kolor-Vidigilo + +/friends/edit_do.bml.yourfriends.head=Viaj Geamikoj + +/friends/edit_do.bml.yourfriends.text=Vi estas specifinta la jenaj amikoj: + +/friends/filter.bml.reset=Malelektu + +/friends/filter.bml.select=Elektu grupo(j)n de geamikoj, kiujn vi volus vidi en via listo de amikoj. + +/friends/filter.bml.select.header=Elektu grupojn + +/friends/filter.bml.submit=Vidu! + +/friends/filter.bml.title=Filtro de amikoj + +/friends/index.bml.edit.about=Aldonu aÅ­ forigu uzantojn en via listo de amikoj; aÅ­ redaktu kolorojn, kiuj reprezentas la amikojn. + +/friends/index.bml.editgroups.about=Kreu, redaktu aÅ­ forigu grupojn de viaj amikoj. + +/friends/index.bml.filter.about=Filtru vian liston de amikoj laÅ­ specifaj grupoj. + +/friends/index.bml.title=Iloj por Geamikoj + +/friends/index.bml.tools=Iloj + +/friends/popwithfriends.bml.account_type=Paronu, sed via kontotipo ne permesas uzadon de tiu ĉi ilo. + +/friends/popwithfriends.bml.count=Nombro + +/friends/popwithfriends.bml.intro=Vi ne listigas tiujn ĉi amikojn, sed multaj viaj amikoj listigas. + +/friends/popwithfriends.bml.no_users=Neniom da uzantoj + +/friends/popwithfriends.bml.title=Uzantoj Popularaj Inter Viaj Amikoj + +/index.bml.about.header=Pri LiveJournal + +/index.bml.about.joining=AliÄi la retejon ne kostas. Uzantoj povas promocii iliajn kontojn por pliaj funkcioj. + +/index.bml.about.us=LiveJournal estas simple uzebla (sed tre pova kaj individuigebla) ilo por persona eldonado, konstruita sur libera programaro. + +/index.bml.boldcreate=Kreu la propran LiveJournal-on! + +/index.bml.frank.image.alt=Franĉjo la kapro, bestsimbolo de LiveJournal + +/index.bml.frank.logo="Beeeee", diras Franĉjo. + +/index.bml.learnmore.header=Deziras lerni pli? + +/index.bml.learnmore.text=Bonvolu legi nian funkcion resumon. Ĉu konvinkita? Kreu vian propran LiveJournal! + +/index.bml.meta.desc=LiveJournal.com estas loko, kie oni povas doni siajn pensojn al la mondo. + +/index.bml.meta.keywords=taglibro, rettaglibro, taglibroj, skribo, reta taglibro, interreta taglibro + +/index.bml.news.text=La plej freÅaj retejaj novaĵoj (sole angle, bedaÅ­rinde): + +/index.bml.news.title=Plej FreÅaj Novaĵoj + +/index.bml.post=Aktuala AfiÅa Statistikoj + +/index.bml.post.hour=Hore + +/index.bml.post.latest=Plej FreÅaj AfiÅoj + +/index.bml.post.min=Minute: + +/interests.bml.add.added.head=Aldonita! + +/interests.bml.add.added.text=La intereso estas nun en via listo. + +/interests.bml.add.btn.text=Aldonu [[interest]] + +/interests.bml.add.confirm.head=Konfirmu + +/interests.bml.add.confirm.text=Por aldoni [[interest]] kiel intereston, klaku la butonon malsupre. + +/interests.bml.add.toomany.head=BedaÅ­ron... + +/interests.bml.add.toomany.text=Vi jam difinis [[maxinterests]] interesojn. + +/interests.bml.addint=Se vi ankaÅ­ interesiÄas pri Äi kaj volas esti aldonita al ĉi tiu listo, klaku ĉi tie. + +/interests.bml.communities.head=Rilataj Komunumoj + +/interests.bml.communities.text=La sekvaj komunumoj ankaÅ­ interesiÄas pri "[[interest]]". + +/interests.bml.count=Komptilo + +/interests.bml.error.add.mustlogin=Vi devas esti salutita por aldoni interson tiel. + +/interests.bml.error.enmasse.noaccess=EvidentiÄis, ke vi ne havas rajtojn por ÅanÄi agordojn de [[user]] + +/interests.bml.error.findsim_do.intnotfound=La intereso ne estis trovata. + +/interests.bml.error.nointerests=La elektita uzanto ne ekzistas aÅ­ ne indikis siajn interesojn. + +/interests.bml.findsim.searchwait=Notu bone: La serĉo daÅ­ros plurajn sekundojn. Paciencu. + +/interests.bml.findsim_do.account.notallowed=BedaÅ­rinde via kontotipo ne permesas vin uzi ĉi tiun ilon. + +/interests.bml.findsim_do.magic=Magia
      Indico + +/interests.bml.findsim_do.magic.head=Ĉu Magia Indico...? + +/interests.bml.findsim_do.magic.text=Estas komputata por ĉiu uzanto po magia indico, kiu estas pezigo de du faktoroj: la baza nombro de samaj interesoj, kaj kelkaj kromaj poentoj pro interhavi maloftaj interesoj. + +/interests.bml.findsim_do.nomatch.head=Neniuj Rezultoj + +/interests.bml.findsim_do.nomatch.text=Neniu uzantoj similas al [[user]]. + +/interests.bml.findsim_do.notdefined=La uzanto [[user]] ne difinis iun ajn interesojn. + +/interests.bml.findsim_do.similar.head=Similaj Uzantoj + +/interests.bml.findsim_do.similar.text=La jenaj estas la uzantoj plej rilate al [[user]] + +/interests.bml.finished.about=Kiam vi finos, presu la butonon "Konservu ÅanÄojn" ĉi-sube: + +/interests.bml.finished.header=Ĉu vi finis? + +/interests.bml.finished.save_button=Konservu ÅanÄojn + +/interests.bml.interest=Intereso + +/interests.bml.interested.btn.find=Trovu + +/interests.bml.interested.in=Trovu personojn kaj komunumojn, kiuj interesiÄas pri: + +/interests.bml.interests.findsim=Trovu uzantojn, kies interesoj similas al interesoj de: + +/interests.bml.interests.head=Interesoj + +/interests.bml.interests.text=Jen kelkajn amuzaĵojn kiujn vi povas fari kun la interesoj. + +/interests.bml.interests.viewpop=Vidu popularajn interesojn + +/interests.bml.login.enterinfo=Entajpu vian uzant-nomon kaj pasvorton por redakti viajn interesojn. + +/interests.bml.match=[[count]] konformas: + +/interests.bml.matches=[[count]] havas: + +/interests.bml.morestuff=Pli multe da amuzaĵoj estas trovebla sur la interesoj-paÄo. + +/interests.bml.nointerests.text=Ĉu neniuj interesoj en via listo? Aldonu kelkajn per tio, ke vi vizitas la Redaktu Personajn Informojn & Preferigojn paÄon. + +/interests.bml.popular.head=Popularaj Interesoj + +/interests.bml.popular.text=La jenaj estas la plej popularaj interesoj. + +/interests.bml.results.added=La interesoj, kiujn vi elektis, estas sukcese aldonitaj al via listo de interesoj. + +/interests.bml.results.both=La elektitaj interesoj estas sukcese aldonitaj al via listo de interesoj, la malelektitaj interesoj estas forigitaj. + +/interests.bml.results.deleted=La malelektitaj interesoj estas sukcese forigitaj el via listo de interesoj. + +/interests.bml.results.header=Rezultoj + +/interests.bml.results.nothing=Vi nenion ÅanÄis + +/interests.bml.title=Interesoj + +/interests.bml.toomany.body=Estas [[intcount]] homoj kaj/aÅ­ komunumoj kiuj listas ĉi tion kiel intereso. Listo ne montriÄos. + +/interests.bml.toomany.head=Multegaj egaluloj + +/interests.bml.users.head=Interesataj uzantoj + +/interests.bml.users.text=La jenaj uzantoj interesiÄas pri [[interest]]. + +/invite/index.bml.code=Kodo + +/invite/index.bml.error=Eraro + +/invite/index.bml.none=Neniu + +/invite/index.bml.title=Invitu aliaj al LiveJournal + +/invite/index.bml.unused=Neuzitaj + +/legal/index.bml.about<< +LiveJournal estas dediĉita al oferti stabilan kaj multsignifan sperton por ĉiaj membroj el ĉiaj landoj, do ni starigis kelkajn regulojn por provizi Äin. Niaj dokumentoj enhavas prudentajn kondiĉojn kaj informojn pri kiel ni provos la plej bonan por bonservi vin, kaj kiel membroj devus konduti al ni kaj aliaj, laÅ­ ni. LiveJournal plej bone funkcias kiam homoj agi laÅ­ tiuj reguloj. Jen iom da reguloj gravaj kaj rememorindaj: +
        +
      • Ne atakadu, misuzi aÅ­ minaci aliajn homojn.
      • +
      • Ne ia malutili neplenaÄulojn.
      • +
      • Ne spami la TTT-ejon aÅ­ iu ajn konton sur la TTT-ejo.
      • +
      • Ne afiÅu kopirajtan enhavon senpermese.
      • +
      • Ne entrudiÄu en la privatsfero de aliaj homoj.
      • +
      • Ne malobeu iel la leÄojn de la Usono aÅ­ de via ejo.
      • +
      +La plena listo de reguloj kaj politikoj troveblas malsupre: +. + +/legal/index.bml.about.header=Resumo + +/legal/index.bml.docs.coppa.about=La Interreta Privateca Protektado de la Infantoj (COPPA) regulas la retan kolektadon kaj uzadon de personaj informoj de infantoj sub la aÄo de dek tri. Nia COPPA-paÄo klarigas nian vidpunkton sur tiu leÄo, kaj priskribas kiel oni traktas COPPA-problemojn. + +/legal/index.bml.docs.header=Dokumentoj + +/legal/index.bml.docs.privacy.about=La Privateco priskribas, kiajn informojn de niaj membroj ni kolektas kaj Äi klarigas kiel ni uzas tiujn informojn. + +/legal/index.bml.docs.tos.about=La Servaj Kondiĉoj priskribas nian uzantan politikon, kaj ankaÅ­ la Äeneralajn kondiĉojn de la membreco. Membreco kaj/aÅ­ uzo de la sistemo konsistigas konsenton pri obei la regulojn kaj tute da aliaj akceptitaj kondiĉoj. + +/legal/index.bml.title=LeÄaj Informoj + +/legal/privacy.bml.title=Privateco + +/legal/tos.bml.title=Servaj Kondiĉoj + +/login.bml.bindip.label=Bindu kun IP-adreso: + +/login.bml.bindip.no=Ne (funkcias per ĉiuj ISP-oj) + +/login.bml.bindip.yes=Jes (pli sekura) + +/login.bml.error.mustenterusername=Vi devas entajpi uzantnomon. + +/login.bml.expire.btn.neverexpire=ÅœanÄu finiÄi-modon al NENIAM + +/login.bml.expire.btn.sessiononly=ÅœanÄu finiÄi-modon al NUR SESIO + +/login.bml.expire.neverexpire.text=Via ensaluto neniam finiÄos, do se vi estas ĉe publika terminalo, en lernejo, librejo aÅ­ alia loko kie homoj uzos ĉi tiun komputilon baldaÅ­, ne forgesu elsaluti post vi finlaboris! AÅ­ ÅanÄu vian ensalut-modon por ke Äi finiÄu kiam vi fermos vian retumilon: + +/login.bml.expire.sessiononly.text=Via ensaluto finiÄos post vi fermis vian retumilon. Se Äi estas via propra komputilo kaj vi estas la sola uzanto, vi eble volas ÅanÄi la finiÄon tian, ke Äi neniam finiÄas: + +/login.bml.links.head=Ligiloj + +/login.bml.links.link1=Via amikara paÄo. + +/login.bml.links.link2=Via farendaĵa listo. + +/login.bml.links.text=Ĉi tiu paÄo iam havos ĉiajn ligilojn kaj gravajn informojn, sed por nun, jen kelkaj lokoj kiujn vi volas eble viziti: + +/login.bml.loggedin.head=Ensalutita! + +/login.bml.loggedin.text=Vi nun estas ensalutita. + +/login.bml.login.btn.changeopts=ÅœanÄu Elektojn + +/login.bml.login.btn.login=Ensalutu... + +/login.bml.login.expiration=FiniÄo: + +/login.bml.login.forget=Forgesis? + +/login.bml.login.head=Ensalutu + +/login.bml.login.never=Neniam + +/login.bml.login.otheropts=Aliaj Elektoj: + +/login.bml.login.password=Pasvorto: + +/login.bml.login.text1=Por ensaluti al [[sitename]], entajpi vian uzantnomon kaj pasvorton malsupren. Novaj Uzantoj: Por krei konton, iru ĉi tien. + +/login.bml.login.text2=Vi povas ankaÅ­ specifi kiam via ensaluto finiÄos. DefaÅ­lte, via ensaluto finiÄos kiam vi fermos vian retumilon, kiu estas la plej bona por publikaj komputilaj. Tamen, se vi estas la sola uzanto de via komputilo kaj neniu alia ajn rajtas aliri, vi verÅajne elekti resti ensalutita ĉiame. + +/login.bml.login.username=Uzantnomo: + +/login.bml.login.whenbrowsercloses=Kiam retumilo fermiÄos + +/login.bml.logout.btn=Elsalutu + +/login.bml.title=Ensalutu + +/login.bml.whylogin.benefit1=Vi ne devos enskribi vian uzantnomon/pasvorton ie ajn sur tiu paÄo. + +/login.bml.whylogin.benefit2=Vi rajtos vidi "protektitajn" taglibrajn enskribojn el via geamikoj, kiuj donas al vin la permeson de legi ilin. + +/login.bml.whylogin.benefit3=Multe da trajtoj nur estas videblaj aÅ­ atingeblaj kiam vi estas ensalutita. + +/login.bml.whylogin.head=Kial Ensaluti? + +/login.bml.whylogin.text=Jen iom da la ĉefaj avantaÄoj pri ensaluti: + +/logout.bml.already.head=Jam salutita + +/logout.bml.already.text=Vi jam estas elsalutita. + +/logout.bml.killall.btn=Finigu tute da miajn sesiojn + +/logout.bml.killall.head=Aliaj sesioj + +/logout.bml.killall.text=Vi havas aliajn aktivajn sesiojn. Ĉu vi volas finigi tute da viajn sesiojn, kaj ne nur tiun ĉi? (Vidu ĉi tiun OD-on por pli multaj informoj.) + +/logout.bml.loggedout.already=Jam elsalutita. + +/logout.bml.loggedout.head=Elsalutita + +/logout.bml.loggedout.killedall=Tute da viaj sesioj estas forigitaj. + +/logout.bml.loggedout.success=Elsalutita. + +/logout.bml.loggedout.text=Vi nun estas elsalutita. + +/logout.bml.logout.btn=Elsalutu + +/logout.bml.logout.head=Ĉu elsalutu? + +/logout.bml.logout.text=Klaku la butonon malsupre por elsaluti. + +/logout.bml.title=Elsalutu + +/lostinfo.bml.btn.proceed=DaÅ­rigu + +/lostinfo.bml.enter_email=Enskribu vian retpoÅtadreson: + +/lostinfo.bml.enter_email_optional=RetpoÅtadreso: (nedeviga) + +/lostinfo.bml.enter_username=Enskribu vian uzantnomon: + +/lostinfo.bml.error.no_email=Vi devas entajpi vian retpoÅtan adreson por rericevi vian uzantnomon. + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Se vi forgesis vian pasvorton, enskribu vian uzantnomon kaj, libervole, la retpoÅtadreson al kiu la pasvorto devas esti sendota. Ne forgesu ke la retpoÅtadreso devas esti unu kiun vi jam uzis ĉe LiveJournal kaj devis konfirmi jam. Se vi lasas la retpoÅtan ĉelon blanka, Äi estos sendata retpoÅte al via nuna adreso. + +/lostinfo.bml.lostpassword.title=Ĉu forgesis vian pasvorton? + +/lostinfo.bml.lostusername.text=Se vi forgesis vian uzantnomon, enskribu vian retpoÅtadreson kaj ni sendos al vi vian uzantnomon. + +/lostinfo.bml.lostusername.title=Ĉu forgesis vian uzantnomon? + +/lostinfo.bml.title=Forgesitaj Informoj + +/lostinfo_do.bml.error.no_usernames_for_email=Ne estas uzantnomo(j) por ĉi tiu retpoÅtadreso: [[address]] . + +/lostinfo_do.bml.error1.text=Vi neniam uzis ĉi tiun retpoÅtadreson kun ĉi tiu konto, aÅ­ Äi neniam estis validigita. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Ĉi tiu estas aÅ­tomata retpoÅto. Vi ne bezonas respondi al Äi. *** + +Ĉi tiu estas via demandita pasvort-memorigo de [[sitename]]. +Jen via uzantnomo, pasvorto kaj retpoÅtadreso kun kiuj via taglibro estas registrita. + +Uzantnomo: [[username]] +Pasvorto: [[password]] +RetpoÅtadreso: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Por validigi vian retpoÅtadreson, iru tien: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ĉi tiu informo estas petita el la TTT-ejo de [[remoteip]]. + +Se vi ne petis ke la pasvorto estas sendata al vi, ne paniku. Vi ja kvankam estas la persono kiu vidas la retpoÅton, kaj ne alia persono. Eblas ke la alia uzanto kiu petis, malpravis kaj kredas ke li aÅ­ Åi kontrolas ĉi tiun uzantnomon. AnkaÅ­ estas verÅajne ke iu misskribis la uzantnomon aÅ­ la adreson. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Se vi vere kredas ke via konto ne estas sekura, legu + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +por kelkaj informoj pri kiel oni re-sekurigas Äin. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Utilaj ligiloj: + + Via LiveJournal: + [[journalurl]] + + Äœisdatigu vian taglibron enrete: + [[updateurl]] + +Saluton, +LiveJournal-a Teamo + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Forgesita Pasvorto + +/lostinfo_do.bml.password_mailed.text=Sukceso. Via pasvorto enretpoÅtiÄis. + +/lostinfo_do.bml.password_mailed.title=Pasvorto sendita! + +/lostinfo_do.bml.title=Forgesitaj Informoj + +/lostinfo_do.bml.username_mailed.text=Sukceso. Via uzantnomo estas enretpoÅtigita. + +/lostinfo_do.bml.username_mailed.title=Uzantnomo enretpoÅtigita! + +/manage/index.bml.customization.advanced=Altnivela Individuigado + +/manage/index.bml.customization.header=Individuigado + +/manage/siteopts.bml.btn.lang=InterÅanÄu la lingvon + +/manage/siteopts.bml.head.lang=Elektu Vian Lingvon + +/manage/siteopts.bml.scheme.preview=[AntaÅ­rigardo de [[title]] skemo] + +/modify.bml.title=Modifu Taglibron + +/modify_do.bml.availablestyles.head=Haveblaj Stiloj + +/modify_do.bml.availablestyles.userstyles=Uzantaj Stiloj: + +/modify_do.bml.colortheme.about=Jen vi povas elekti kiu kolorskemo estos apliki al la aranÄaj elektoj kiuj vi elektas supre. AÅ­ se vi ne Åatas la provizitajn kolorojn, specifu viajn proprajn! + +/modify_do.bml.colortheme.area.head=Uzoejo + +/modify_do.bml.colortheme.color.head1=Koloro + +/modify_do.bml.colortheme.color.head2=(#rrvvbb aÅ­ nomo) + +/modify_do.bml.colortheme.customcolors=Kutimaj Koloroj + +/modify_do.bml.colortheme.defaulttheme=DefaÅ­lta Temo + +/modify_do.bml.colortheme.head=Kolor-Temo + +/modify_do.bml.domainalias.about=Se vi jam havas domajnan nomon registritan (aÅ­ registrotan) kaj volas ke Äi aÅ­tomate Åargas vian taglibron, enskribu la domajnan nomon ĉi tie: + +/modify_do.bml.domainalias.domainname=Domajna nomo: + +/modify_do.bml.domainalias.example=Ekzemplo: mia-taglibro.com + +/modify_do.bml.domainalias.head=Domajna Sinonimado + +/modify_do.bml.domainalias.helptext|staleness=1 +/modify_do.bml.domainalias.helptext=Por ke tiu funkcias, vi bezonas ÅanÄi la DNS-on de via domajna nomo tiel, ke Äi montras al la saman IP-adreson de [[sitename]]. + +/modify_do.bml.done.btn.savechanges=Konservu ÅœanÄojn + +/modify_do.bml.done.head=Ĉu finita? + +/modify_do.bml.done.text=Se finita, premu la "Konservu ÅœanÄojn" butonon malsupre... + +/modify_do.bml.error.dupdomainalias=Alia uzanto jam registris sin mem kaj uzas vian elektitan domajnan sinonimadon. + +/modify_do.bml.error.stylenotavailable=Unu de la stiloj, kiujn vi elektis, ne estas havebla. Estas aÅ­ ĉar iu forigis la stilon, aÅ­ vi provas elekti iun al kiu vi ne havas rajton. + +/modify_do.bml.friends.about=Jen la elektoj kiuj kontroli kiel via geamika paÄo aspektas. + +/modify_do.bml.friends.head=Geamika Vido + +/modify_do.bml.friends.opt.usesharedpic.about=Tiu elekto kontrolas kiun bildon vi vidas sur via geamika paÄo kiam uzanto afiÅas en partoprenita taglibro aÅ­ komunumo. Se vi markas Äin, tiam vi vidas la komunuman piktogramon. Se vi lasas Äin nemarkita, tiam vi vidas la personan uzant-piktogramon de la afiÅanto. + +/modify_do.bml.friends.opt.usesharedpic.head=Uzu partoprenitan taglibran bildon anstataÅ­ la uzantan bildon de la afiÅanto. + +/modify_do.bml.journaloptions.about=Ĉi tie vi povas individuigi la aspekton de via LiveJournal-an paÄon. Se vi vere interesiÄas pri ĉiu funkcias, legu la disvolviÄantajn informojn. Krome, ni supozas ke vi kontentas pri la bazaj elektoj malsupraj: + +/modify_do.bml.journaloptions.head=Taglibraj Elektoj + +/modify_do.bml.journalstatus.about=Se vi volas forigi aÅ­ malforigi vian taglibron, vi povas fari Äin tie. Kiam vi forigis vian taglibron, vi havas 30 tagojn por malforigi Äin, por la kazo ke vi redecidi. Post 30 tagoj, la taglibro estos eterne forigita kaj ne ekiston eblo por reakiru Äin. + +/modify_do.bml.journalstatus.head=Taglibra Aktiveca Stato + +/modify_do.bml.journalstatus.select.activated=Aktivita + +/modify_do.bml.journalstatus.select.deleted=Forigita + +/modify_do.bml.journalstatus.select.head=Stato: + +/modify_do.bml.journalstatus.select.suspended=Provizore Forigita + +/modify_do.bml.moodicons.about=Kiam afiÅi taglibrajn enskribojn, vi ankaÅ­ povas specifi vian laÅ­tempan humoron. Diversaj uzantoj sendis al ni diversajn humor-piktogramarojn kiujn vi ankaÅ­ povas uzi. AÅ­ elektu "Neniu" kiam vi ne volas iun ajn bildon apud viaj humoroj. (vi ne eĉ devas uzi la Nuna Humoro trajton ajn.) + +/modify_do.bml.moodicons.head=Humoraj Piktogramoj + +/modify_do.bml.moodicons.opt.forcefriends.about=Fortu ĉi tiun humoran temon por viaj tutaj geamikoj sur via geamikoj paÄo + +/modify_do.bml.moodicons.personal=Personaj Temoj: + +/modify_do.bml.moodicons.preview=antaÅ­rigardu + +/modify_do.bml.moodicons.select=Elektu humor-piktogramaron: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Vi povas ignori tiun sekcion. Äœi estas por optimigi tre specifajn aĵojn pri via paÄa aranÄo. Vizitu la disvolviÄantan sekcion por detaloj. AnkaÅ­ ne forgesu ke malvalidigoj estas por malvalidigi nur unu aÅ­ du aĵojn pri stilon. Se vi viÅas malvalidigi ĉiun, vi bezonas krei vian propran stilon. + +/modify_do.bml.overrides.box.head=Malvalidigoj: + +/modify_do.bml.overrides.head=Stil-Malvalidigoj + +/modify_do.bml.overrides.note=Bonvolu remarki ke ne ĉiuj la stil-variabloj estas malvalidigeblaj. Vizitu la klarigon por pluaj detaloj.
      Sciu ankaÅ­ ke kiam vi klopodas redakti viajn malvalidigojn, kaj vi uzis etikedon kiu ne estas permesita en la ĉapo de la dokumento – kiel <DIV>, <SPAN>, <IMG> kaj multaj aliaj etikedojn – tiu etikedo estos forigata. La solaj HTML-aj elementoj kiuj povas esti uzitaj en la *_HEAD-aj malvalidigoj estas tiuj elementoj kiuj estas validaj en la ĉapo de HTML-dokumentoj. Tiuj ĉi estas limitaj al <title>, <base>, <style>, <link>, kaj <meta>. + +/modify_do.bml.overrides.warning=ĈI TIO NE ESTAS KIE VI TAJPAS VIAN TAGLIBRON!! + +/modify_do.bml.pagelayoutstyle.about=ÅœanÄi Äin kontrolas kiel via taglibro estos montrita sur la ekrano. + +/modify_do.bml.pagelayoutstyle.head=PaÄa AranÄa Stilo + +/modify_do.bml.pagelayoutstyle.warning=Via konto-tipo nur permesas vin elekti inter malmultaj da defaÅ­ltaj stiloj. + +/modify_do.bml.success.head=Sukceso + +/modify_do.bml.success.text=Viaj taglibraj preferigoj estas Äisdatigitaj. Vi povas vidi vian taglibron ĉi tie. + +/paidaccounts/index.bml.costs.header=Nu, kiom Äi kostas? + +/paidaccounts/index.bml.costs.rates=Jen la ratoj: + +/paidaccounts/index.bml.costs.rates.amount.header=Nombro + +/paidaccounts/index.bml.costs.rates.inexpensive=Tiu estas iomete pli ol po $2 por monato por la jara plano. Tiom apenaÅ­ malplenigos vian monujon. La plej enuiga parto verÅajne estos eltiri vian monujon, trovi vian kreditkarton, kaj entajpi viajn informojn. + +/paidaccounts/index.bml.costs.rates.time.header=Tempo + +/paidaccounts/index.bml.features.header=Do, kiajn bonegajn eblojn mi ricevos? + +/paidaccounts/index.bml.title=Pri Pagitaj Kontoj + +/paidaccounts/index.bml.whypay.argument=Ne, kompreneble ne. Ni konsentas, ke estas enuige, pagi por TTT-servoj. Tio estas kial preskaÅ­ la tuta funkciado de LiveJournal estas havebla senkoste. Tamen, se vi estas kontenta pro la provizita servo, montru vian subtenon kaj aĉetu pagitan konton. + +/paidaccounts/index.bml.whypay.header=Ĉu vere mi devas pagi por LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads=Oni bezonas monon por funkciigi TTT-ejojn (por serviloj, aranÄoj kaj kapacito), kaj tiu Åajnas kiel pli bona maniero por pagi ol enuigi vin per Åpruc-reklamiloj kaj spami vin per reklamoj. + +/paidaccounts/index.bml.your_username=via_uzantnomo + +/paidaccounts/usepaypal.bml.delivery.badformat=Malvalida livera data formato. Devas esti en la formato jjjj-mm-tt aÅ­ jjjj-mm-tt hh:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Livera dato ne povas esti en la estinteco. Por sendi Äin tuj, lasu la liveran datan ĉelon blanka. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Livera dato ne povas esti pli ol unu monato en la futuro. + +/pay/index.bml.deliverydate.details=Formato: yyyy-mm-dd hh:mm (GMT-tempo)
      (enskribu nenion por neprokrastita livero) + +/pay/index.bml.deliverydate.label=Livera Dato: + +/pay/index.bml.gift.anonymous=Sennoma donaco + +/poll/create.bml.button.editpoll=Redaktu Baloton + +/poll/create.bml.button.postpoll=AfiÅu Baloton + +/poll/create.bml.button.preview=AntaÅ­rigardu Baloton + +/poll/create.bml.error.accttype=Via kontotipo ne permesas ke vi uzas la balot-krea funkcio. + +/poll/create.bml.error.parsing=Eraro dum analizo de baloto: + +/poll/create.bml.haserrors=Estas unu aÅ­ pli eraroj en via baloto. Bonvolu rulumi malsupren por pluaj detaloj. + +/poll/create.bml.pollname=Balota Nomo: (opt.) + +/poll/create.bml.preview.desc=Sube estas antaÅ­rigardo de via baloto. Ĉi tiu estas precize kiel Äi aspektas, post kiam Äi estas afiÅita en via taglibro. Uzu la butonojn sube por reiri kaj redakti Äin, aÅ­ afiÅi Äin en via taglibro. + +/poll/create.bml.properties=Balotaj Atributoj + +/poll/create.bml.questions=Balotaj Demandoj + +/poll/create.bml.title=Balota Kreinto + +/poll/create.bml.whoview=Kiu rajtas rigardi ĉi tiun baloton? + +/poll/create.bml.whovote=Kiu rajtas baloti en ĉi tiu baloto? + +/poll/index.bml.error.cantview=BedaÅ­rinde, vi ne rajtas rigardi ĉi tiun baloton. + +/poll/index.bml.error.postdeleted=Posedanta afiÅo estas forigita, do baloto ne jam haveblas. + +/poll/index.bml.filloutpoll=Plenigu Baloton + +/poll/index.bml.gotocreate=Ĉi tiu estas adreso por partopreni en baloto. Vi trovis adreson kiu nuntempe ne faris ion ajn. Se vi deziras, vi povas krei novan baloton. + +/poll/index.bml.pollnotfound=Baloto ne trovita. + +/poll/index.bml.submitted.text=Via balotaj respondoj estas konservita. + +/poll/index.bml.title=Baloto + +/poll/index.bml.viewresults=Rigardu Balotajn Rezultojn + +/press/staff.bml.administration=Administrado + +/press/staff.bml.administration.about=LiveJournal.com komencis je 1999 kiel projekto de Brad Fitzpatrick, kaj dum la unuaj du vivjaroj, estis subtenata de granda kaj lojala voluntara. Dum granda parto de LiveJournal.com estas ankoraÅ­ kondukata de voluntaraj, ni nun havas malgrandan estro-stabon kiu superrigardas ĉiujn operaciojn: + +/press/staff.bml.avva.title=Estro-DisvolviÄanto + +/press/staff.bml.back2=Reen al la Gazetara paÄo + +/press/staff.bml.bradfitz.quip=KoncentriÄu pri via produkto kaj ne nur pri la enspezado de mono. + +/press/staff.bml.bradfitz.title=Prezidanto / Ĉef-DisvolviÄanto + +/press/staff.bml.contact=Se vi bezonas kontakti iun da ni, bonvolu skribi retpoÅton al webmaster@livejournal.com. + +/press/staff.bml.denisep.quip=Mi havos tion por vi venontĵaÅ­de + +/press/staff.bml.denisep.title=Voluntarulaj / Uzeblada Fakulo + +/press/staff.bml.jproulx.quip=Geek to User Liaison + +/press/staff.bml.jproulx.title=Komunumaj PaÄa Supervidanto / Gazetaraj + +/press/staff.bml.lisa.title=Sistem-Administranto + +/press/staff.bml.ryanfitz.title=Pago-Servoj + +/press/staff.bml.sandy.title=Konteco kaj Administrado + +/press/staff.bml.title=Estraro + +/press/staff.bml.whitaker.quip=Kio sekvas? + +/press/staff.bml.whitaker.title|staleness=1 +/press/staff.bml.whitaker.title=La Praktikanto + +/register.bml.error.invalidcode=MalÄusta konfirma kodo. + +/register.bml.error.usernotfound=Uzanto ne estis trovita. + +/register.bml.new.header=Sukcese + +/register.bml.new.update=Äœisdatigu la Taglibron -- Skribu en via taglibro. + +/register.bml.sent.body=La konfirmiga mesaÄo estis sendita al la adreso [[email]]. Por fini konfirmon de la adreso vi bezonas alklaki ligon, kiun vi trovos en la mesaÄo. + +/register.bml.sent.header=Sukcese + +/register.bml.title=Konfirmu RetpoÅtan Adreson + +/register.bml.trans.body=Via nova retpoÅta adreso estas sukcese konfirmita. + +/site/contract.bml.promise.account=Estimi statuson de ĉiu konto + +/site/contract.bml.promise.ads=Resti sen reklamo + +/site/contract.bml.promise.community=Labori kun la komunumo kaj por la komunumo + +/site/goat.bml.image.alt=Franĉjo, la bestsimbolo de LiveJournal. + +/site/goat.bml.image.caption="Beeeee", diras Franĉjo. + +/site/goat.bml.meet.body=Ĉi tiu estas Franĉjo. Franĉjo estas la bestsimbolon de LiveJournal.com. Li helpas nin kun hazardan programadon kiam ni postiÄas, kaj kelkfoje li respondas al demandoj el la teknika subteno. Franĉoj vere estas tre multflanka... li eĉ faras la Äardenlaboron, kelkfoje. Kiam la razeno superkreskas, ni vokas: "Hej, Franĉjo! Estas tempo por lunĉi... manÄu la razenon!". Vere estas ambaÅ­flanke profitabla situacio. + +/site/goat.bml.meet.header=RenkontiÄu kun Franĉjo + +/site/goat.bml.title=Franĉjo la Kapro + +/styles/create_do.bml.error.accounttype=Via kontotipo ne permesas ke vi kreas stiloj. + +/suggestions/index.bml.howto.title=Kiel mi submetas sugeston? + +/suggestions/index.bml.info.title=Alia Informo + +/suggestions/index.bml.title=Sugestejo + +/suggestions/index.bml.welcome.title=Bonvenon! + +/support/encodings.bml.edit.header=Mi ne povas redakti miajn enskribojn en la TTT-eja interfaco! + +/support/encodings.bml.edit.text<< +Mallonga respondo: (farebla kiam vi skribas viajn enskribojn angle): Iru al via personaj preferigoj-paÄo. Trovu elekton apud la fundo de la paÄo kun la nomo AÅ­tomate konvertu malnovajn enskribojn de:. Elektu "Western European (Windows)" el la tirmenuo kaj konservu viajn preferigojn. Viaj enskriboj nun devus esti redakteblaj. p?> + +Longa respondo: Por vi povas redakti ne-unikodan enskribon, LiveJournal devas scii en kiu enkodo ĉi tiu enskribo estas afiÅita. Por uzantoj de la angla lingvo aÅ­ aliaj okcidenteÅ­ropaj lingvoj, tiu normale estos "Western European (Windows)", kvankam se Äi ne funkcias bone por citiloj kaj aliaj similaj meta-literoj, provu "Western European (ISO)". Uzantoj skribantaj en aliaj lingvoj devas elekti sian enkodon; se Äi ne estas en la provizita listo, kontaktu la Subtenon kaj klarigu la problemon. p?> + + +. + +/support/encodings.bml.editcl.header=Mi ne povas redakti miajn enskribojn en la klienta programo! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Mi ne povas redakti mian liston de geamikoj kun mia klienta programo! + +/support/encodings.bml.groups.text=grupaj redakti paÄo kaj tiam uzi vian klientilan programon. p?> + +/support/encodings.bml.overview.header=Kial estas la tuta aĵo? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Ĉu ankoraÅ­ perpleksa? + +/support/encodings.bml.still.text=Subtenejo. p?> + +/support/encodings.bml.title=Kodoprezento + +/support/faqbrowse.bml.backfaq=Reen al la OD + +/support/faqbrowse.bml.backsupport=Reen al la helpejo + +/support/faqbrowse.bml.error.nofaq=La specifita OD ne ekzistas. + +/support/faqbrowse.bml.lastupdated=Laste ÄœisdatiÄita: + +/support/faqbrowse.bml.title_cat=OD - [[catname]] + +/support/faqbrowse.bml.title_num=OD Demando #[[num]] + +/support/see_overrides.bml.error.noprivs|staleness=1 +/support/see_overrides.bml.error.noprivs=Nur uzantoj kun la subtenvido-interna aÅ­ subtenhelpa privilegio povas vidi la malvalidigojn de aliaj uzantoj. + +/support/see_overrides.bml.error.nos1=Ĉi tiu uzanto ne uzas S1. + +/support/see_overrides.bml.header=Malvalidigoj por : + +/support/see_overrides.bml.nooverrides=Neniuj malvalidigoj troveblaj por . + +/support/see_overrides.bml.title=Uzantaj Malvalidigoj + +/talkmulti.bml.deleted.body=La komentoj estas forigitaj. Vi povas legi la reston de la fadeno ĉi tie. + +/talkmulti.bml.deleted.title=Komentoj forigitaj + +/talkmulti.bml.error.comms_deleted=Unu de la komentoj estas forigita ekde vi selektis Äin. Por sekurecaj kaÅ­zoj, bonvolu iri reen kaj reprovu. + +/talkmulti.bml.error.inconsistent_data=La provizita datumo estas nekonsekvenca. + +/talkmulti.bml.error.invalid=Malvalidaj parametroj specifitaj. + +/talkmulti.bml.error.invalid_mode=Vi ne elektis unu de la agadoj. Bonvolu iri reen kaj elektu se vi volas kaÅi, malkaÅi aÅ­ forigi la komentojn. + +/talkmulti.bml.error.login=Vi ne estas salutita. + +/talkmulti.bml.error.none_selected=Vi ne selektis iujn ajn komentojn. + +/talkmulti.bml.error.privs.delete=Vi ne estas permesita forigi tiujn komentojn. + +/talkmulti.bml.error.privs.screen=Vi ne estas permesita kaÅi tiujn komentojn. + +/talkmulti.bml.error.privs.unscreen=Vi ne estas permesita malkaÅi tiujn komentojn. + +/talkmulti.bml.screened.body=La komentoj estas kaÅitaj. Vi povas vidi ilin ĉi tie. + +/talkmulti.bml.screened.title=Komentoj kaÅitaj + +/talkmulti.bml.title.delete=Forigu Multoblajn Komentojn + +/talkmulti.bml.title.screen=KaÅu Multoblajn Komentojn + +/talkmulti.bml.title.unscreen=MalkaÅu Multoblajn Komentojn + +/talkmulti.bml.unscreened.body=La komentoj estas malkaÅitaj. Vi povas vidi ilin ĉi tie + +/talkmulti.bml.unscreened.title=Komentoj malkaÅitaj + +/talkpost.bml.allowedhtml=Permesata HTML + +/talkpost.bml.error.cannotreplynopost=Vi ne povas respondi al neekzistanta mesaÄo + +/talkpost.bml.error.nocommentsjournal=La uzanto malebligis komentojn en sia taglibro. + +/talkpost.bml.error.nocommentspost=La uzanto malebligis komentojn por ĉi tiu rakonto. + +/talkpost.bml.error.noreplypost=MesaÄo al kiu vi respondas, ne trovitas (forigita?) + +/talkpost.bml.error.noreply_screened=Ĉi tiu komento estas kaÅita kaj vi ne estas permesita vidi Äin aÅ­ respondi al Äi. + +/talkpost.bml.label.picturetouse=Uzu la bildon: + +/talkpost.bml.loganonip=Notu! Ĉi tiu uzanto Åaltis la opcion kiu registras IP-adresojn de sennomaj respondantoj. + +/talkpost.bml.loginq=Ĉu ensalutu? + +/talkpost.bml.logyourip=Notu! Ĉi tiu uzanto Åaltis la opcion kiu registras vian IP-adreson kiam vi respondas. + +/talkpost.bml.nosubjecthtml=HTML ne permesatas en la subjekto + +/talkpost.bml.opt.anonymous=Sennoma + +/talkpost.bml.opt.defpic=(la defaÅ­lta) + +/talkpost.bml.opt.friendsonly=- ĉi tiu uzanto malebligis la anoniman kaj ne-geamikan afiÅadon. Vi rajtas afiÅi ĉi tie se [[username]] listas vin kiel amik(in)o. + +/talkpost.bml.opt.from=De: + +/talkpost.bml.opt.ljuser=LiveJournal uzanto: + +/talkpost.bml.opt.loggedin=Salutita uzanto: [[username]] + +/talkpost.bml.opt.message=MesaÄo: + +/talkpost.bml.opt.noanonpost=- ĉi tiu uzanto malebligis la sennoman komentadon. + +/talkpost.bml.opt.noautoformat=Ne aÅ­tomate formatu: + +/talkpost.bml.opt.noimage=Neniu Bildo + +/talkpost.bml.opt.preview=AntaÅ­rigardu + +/talkpost.bml.opt.spellcheck=Literumile kontrolu enskribon antaÅ­ afiÅi + +/talkpost.bml.opt.subject=Subjekto: + +/talkpost.bml.opt.submit=AfiÅu Komenton + +/talkpost.bml.opt.willscreen=(estas kaÅota) + +/talkpost.bml.opt.willscreenfriend=(estas kaÅota se ne amika) + +/talkpost.bml.paraformat=Paragrafoj defaÅ­lte estos aÅ­tomate formatita. + +/talkpost.bml.postresponse=AfiÅu komenton responde: + +/talkpost.bml.title=AfiÅu Komenton + +/talkpost.bml.usermismatch<< +Vi enskribis uzantnomon, sed vi malelektis la 'LiveJournal-a uzanto' elekton. + +Bonvolu aÅ­ blanki la uzanto-ĉelon aÅ­ elekti la Äustan afiÅmodon kaj reprovu. +. + +/talkpost.bml.warnscreened=Rimarku: Ĉi tiu komento estas kaÅita. Respondi al Äi aÅ­tomate malkaÅigos kaj videbligos Äin. + +/talkpost_do.bml.error.badpassword=MalÄusta pasvorto por tiu uzantnomo. Vi povas remalkovri vian pasvorton ĉi tie se vi forgesis Äin. + +/talkpost_do.bml.error.badusername=La LiveJournal-an uzantnomon kiun vi elektis ne ekzistas. Vi povas rehavigi vian uzantnomon ĉi tie se vi forgesis Äin, aÅ­ vi simple povas afiÅi kiel "sennoma." + +/talkpost_do.bml.error.banned=Vi ne rajtas afiÅi en la taglibro de ĉi tiu uzanto. + +/talkpost_do.bml.error.blankmessage=Via mesaÄo malplenis. Bonvolu tajpi ion en la mesaÄa kampo. + +/talkpost_do.bml.error.confused_identity=Vi entajpis uzantnomon, sed elektis afiÅi sennome aÅ­ kiel la nuna uzanto. Iru reen kaj elektu kiun vi vere volas fari. + +/talkpost_do.bml.error.deleted=Via taglibro estas forigita. Vi ne povas afiÅi mesaÄojn. + +/talkpost_do.bml.error.friendsonly=Nur geamikoj de [[user]] rajtas afiÅi ĉe tiu ĉi taglibro. + +/talkpost_do.bml.error.lostcookie=Via ensalut-kuketo Åajnas malaperinta, ĉu ne? + +/talkpost_do.bml.error.manybytes=Pardonu, sed via komento de [[current]] superas la maksimuman bajtlongecon de [[limit]]. Bonvolu iri reen, malplilongigi Äin kaj provi reposti Äin ankoraÅ­foje. + +/talkpost_do.bml.error.manychars=Pardonu, sed via komento de [[current]] signoj superas la maksimuman signolongecon de [[limit]]. Bonvolu iri reen, malplilongigi Äin kaj provi reposti Äin ankoraÅ­foje. + +/talkpost_do.bml.error.mustlogin=Vi devas esti ensalutita aÅ­ uzi uzantnomon/pasvorton por respondi al ĉi tiu protektita enskribo. + +/talkpost_do.bml.error.noanon=Vi ne rajtas sennome afiÅi en la taglibro de ĉi tiu homo. + +/talkpost_do.bml.error.noauth=Vi ne estas aÅ­torizatita respondi al ĉi tiu protektita enskribo. + +/talkpost_do.bml.error.nocomments=La uzanto malebligis komentadon pri ĉi tiu taglibra enskribo. + +/talkpost_do.bml.error.noparent=Ne povas respondi al ne-ekzista komento. + +/talkpost_do.bml.error.notafriend=Pardonu, uzanto [[user]] ne listigas vin kiel amikon, kaj li/Åi elektis la "nur geamikoj" elekton por kiu povas respondi al sia taglibro. + +/talkpost_do.bml.error.nousername=Vi ne enskribis vian LiveJournal-an uzantnomon. Vi eblas afiÅi "sennome" se vi ne havas LiveJournal-an uzantkonton. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Pardonu, vi ne estas permesita afiÅi komentojn en la taglibroj de aliaj homoj, Äis via retpoÅtadreso estas kontrolita. Se vi venkiÄis la konfirm-retpoÅtmesaÄon por Äi, vi povas havi Äin resendita de la venkiÄi-informoj-paÄo. + +/talkpost_do.bml.error.postshared=Vi ne rajtas afiÅi kiel partoprenita aÅ­ komunuma konto. Partoprenitaj kontoj reprezentas grupojn, ne individuojn. + +/talkpost_do.bml.error.screened=Vi ne estas permesita respondi al ĉi tiu kaÅita komento. + +/talkpost_do.bml.error.suspended=Via taglibro estis provizore forigita. Vi ne povas afiÅi mesaÄojn. + +/talkpost_do.bml.error.testacct=Oni nur povas uzi provajn kontojn en provaj taglibroj. + +/talkpost_do.bml.opt.preview=AntaÅ­rigardu + +/talkpost_do.bml.preview=Jen kiel via mesaÄo aperos. Per la malsupra formularo, vi povas pluredakti vian komenton, aÅ­ vi povas nun aldoni Äin. + +/talkpost_do.bml.preview.subject=Subjekto: + +/talkpost_do.bml.preview.submit=Konservu + +/talkpost_do.bml.preview.title=AntaÅ­rigardu + +/talkpost_do.bml.success.loggedin=Vi nun estas ensalutita. + +/talkpost_do.bml.success.message=Via komento afiÅiÄis. Vi povas rigardi Äin ĉi tie. + +/talkpost_do.bml.success.screened.comm=Via komento afiÅiÄis. LaÅ­ la preferigoj de ĉi tiu komunumo, Äi estas kaÅita kaj nur estos videbla por vi kaj la prizorgantoj de la komunumo Äis ili volas malkaÅi Äin. Vi povas vidi vian komenton ĉi tie. + +/talkpost_do.bml.success.screened.user=Via komento afiÅiÄis. LaÅ­ la taglibraj preferigoj, Äi estas kaÅita kaj nur estos videbla por vi kaj la proprulo de ĉi tiu taglibro Äis li/Åi volas malkaÅi Äin. Vi povas vidi vian komenton ĉi tie. + +/talkpost_do.bml.success.screened.user.anon=Via komento sennoma estas afiÅita. LaÅ­ la preferigoj de la taglibro, Äi estas kaÅita, kaj aperos nur al la taglibra proprulo, Äis ri malkaÅos Äin. Vi povas reiri al la komenta fadeno ĉi tie. + +/talkpost_do.bml.success.title=Sukceso + +/talkpost_do.bml.success.unscreened=Cetere, la kaÅita komento, al kiu vi respondis, nun estas malkaÅita kaj videbla. + +/talkpost_do.bml.title=Komento AfiÅiÄis + +/talkpost_do.bml.title.preview=Komenta AntaÅ­rigardo + +/talkread.bml.anonuser=(Sennoma) + +/talkread.bml.confirm.action=Ĉu vi certas ke vi viÅas forigi la elektitajn komentojn? + +/talkread.bml.deletedpost=(Forigita mesaÄo) + +/talkread.bml.deleteduser=(Forigita uzanto: [[username]]) + +/talkread.bml.fromip=(el [[ip]]) + +/talkread.bml.noreplies=Neniuj respondoj + +/talkread.bml.nosubject=(neniu subjekto) + +/talkread.bml.replysuspended=(Respondo de provizore forigita uzanto) + +/talkread.bml.screenedpost=(KaÅita AfiÅo) + +/talkread.bml.select=Elektu + +/talkread.bml.subjectdeleted=[forigita] + +/talkread.bml.talkmulti.delete=Forigu + +/talkread.bml.talkmulti.des=Amasagado por elektitaj komentoj: + +/talkread.bml.talkmulti.screen=KaÅu + +/talkread.bml.talkmulti.submit=Agu + +/talkread.bml.talkmulti.unscreen=MalkaÅu + +/talkread.bml.title=Legu Komentojn + +/talkscreen.bml.error.login=Vi devas esti ensalutita por labori kun kaÅitaj komentoj. + +/talkscreen.bml.error.privs.screen=Vi ne rajtas kaÅi ĉi tiun komenton. + +/talkscreen.bml.error.privs.unscreen=Vi ne rajtas malkaÅi ĉi tiun komenton. + +/talkscreen.bml.screen.doit=Jes, kaÅu ĉi tiun komenton + +/talkscreen.bml.screen.sure.body=Ĉu vi certas ke vi volas kaÅi ĉi tiun komenton? + +/talkscreen.bml.screen.sure.title=Ĉu kaÅu ĉi tiun komenton? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=La komento estas kaÅita. + +/talkscreen.bml.screened.title=Sukceso + +/talkscreen.bml.title=KaÅita Komento + +/talkscreen.bml.unscreen.doit=Jes, malkaÅu ĉi tiun komenton + +/talkscreen.bml.unscreen.sure.body=Ĉu vi certas ke vi volas malkaÅi ĉi tiun komenton? + +/talkscreen.bml.unscreen.sure.title=Ĉu kaÅu ĉi tiun komenton? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=La komento estas malkaÅita. + +/talkscreen.bml.unscreened.title=Sukceso + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Via listo de memorindaj afiÅoj estas Äisdatigita. + +/tools/memadd.bml.body.added.header=Sukceso + +/tools/memadd.bml.description=Priskribo: + +/tools/memadd.bml.description.text<< +Donu al ĉi tiu taglibra enskribo priskribon per kiu vi povas rememorigi Äin. +Por forigi ĉi tiun enskribon el la listo de memorindaj afiÅoj, enskribu blankan priskribon. +. + +/tools/memadd.bml.error.deleted.body=La taglibra enskribo antaÅ­e priskribis kiel "[[desc]]" estas elprenita el via listo de memorindaj afiÅoj. + +/tools/memadd.bml.error.deleted.title=Memoro forigita + +/tools/memadd.bml.error.entry_deleted=Taglibra enskribo ne plue ekzistas. Memoro forigita. + +/tools/memadd.bml.error.fivekeywords=Nur 5 kapvortoj/kategorioj estas permesitaj per memorinda afiÅo. + +/tools/memadd.bml.error.invalid_security=Malvalida aÅ­ venka sekureca elekto. + +/tools/memadd.bml.error.login=Vi devas esti ensalutita por uzi ĉi tiun trajton. Ensalutu kaj vi estas reportita ĉi tien. + +/tools/memadd.bml.error.maxsize=Ĉi tiu kapvorto superas la maksimuman permesatan grandecon: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Por aldoni taglibran enskribon al via listo de memorindaj afiÅoj, vi bezonas provizi priskribon. +Por forigi memoron, vi povas redakti Äin kaj elpreni la priskribon, sed vi ne jam havis ĉi tiun enskribon en viaj memoroj. +. + +/tools/memadd.bml.error.nodescription.title=Neniu priskribo + +/tools/memadd.bml.form.reset=ReÅargu + +/tools/memadd.bml.form.submit=Konservu + +/tools/memadd.bml.keywords=Kapvortoj: + +/tools/memadd.bml.keywords.example=Ekzemple: Amuza, Intelekta, Ama + +/tools/memadd.bml.keywords.select=AÅ­, vi povas elekti ankaÅ­ kapvortojn, kiujn vi uzis antaÅ­e: + +/tools/memadd.bml.keywords.text=Kial ĉi tiu afiÅo memorindas? Enskribu Äis kvin kapvortojn aÅ­ kategoriojn, apartigatajn per komoj, por ke vi povos retrovi Äin poste. + +/tools/memadd.bml.login.enterinfo=Enskribu uzantnomon kaj pasvorton de la konto en kiun vi volas konservi la memoron. + +/tools/memadd.bml.login.forgot.header=Ĉu forgesis iun? + +/tools/memadd.bml.login.forgot.recover=Se vi forgesis vian uzantnomon aÅ­ pasvorton, reakiru Äin ĉi tie!. + +/tools/memadd.bml.multiple_selections=Tenu 'Ctrl' dum klaki kapvortojn por elekti multajn. + +/tools/memadd.bml.security.friendsonly=Nur Geamikoj + +/tools/memadd.bml.security.private=Privata + +/tools/memadd.bml.security.public=Publika + +/tools/memadd.bml.title=Aldonu al Memoroj + +/tools/memadd.bml.title.added=Aldonita + +/tools/memadd.bml.title.deleted=Forigita + +/tools/memadd.bml.title.edit_memory=Redaktu Memorindan Enskribon + +/tools/memadd.bml.whocansee<< +Kiu rajtas vidi ke ĉi tiu afiÅo memorindas? +Ĉu ĉiu, ĉu nur homoj kiujn vi listas kiel geamikoj, aÅ­ ĉu nur vi? + +. + +/tools/memories.bml.back=Reen + +/tools/memories.bml.body.keyword<< + +[[user]] trovis memorindaj. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] aldonis memorindajn afiÅojn. p?> +. + +/tools/memories.bml.body.memorable=La sekvanta estas listo de ne-kategoritaj taglibraj enskriboj kiujn la uzanto [[user]] trovis memorindaj. + +/tools/memories.bml.edit=redaktu + +/tools/memories.bml.error.noentries.body<< +Tiu povus esti ĉar: +
    • la uzanto ne definis iun ajn memorindajn afiÅojn,
    • +
    • la memorindaj afiÅoj de la uzanto estas protektitaj kaj vi ne havas permeson vidi ilin, aÅ­
    • +
    • la uzanto ne havas memorindajn afiÅojn kiuj konformas viajn filtrilkriterioj.
    • +. + +/tools/memories.bml.error.noentries.title=Neniuj memoroj trovitas. + +/tools/memories.bml.filter.all=Ĉiuj memoroj + +/tools/memories.bml.filter.other=Nur aliaj enskriboj + +/tools/memories.bml.filter.own=Nur enskriboj de '[[user]]' + +/tools/memories.bml.form.switch=ÅœanÄu + +/tools/memories.bml.title.keyword=Memorindaj [[keyword]]-aj AfiÅoj + +/tools/memories.bml.title.memorable=Memorindaj AfiÅoj + +/tools/memories.bml.uncategorized=Senkategoriaj + +/update.bml.altpost=Taglibro por enskribi: + +/update.bml.btn.preview=AntaÅ­rigardu + +/update.bml.btn.update=Äœisdatigu la Taglibron + +/update.bml.currmood=Nuna Humoro: + +/update.bml.currmusic=Nuna Muziko: + +/update.bml.date=Dato: + +/update.bml.default=defaÅ­lta + +/update.bml.defaultjournal=([[user]]) -- defaÅ­lta + +/update.bml.error.login=Eraro pri ensalutado: + +/update.bml.error.update=Eraro pri Äisdatigado de taglibro: + +/update.bml.event=Evento: + +/update.bml.full=Plena Äœisdatiga PaÄo + +/update.bml.localtime=Loka horo: + +/update.bml.loggingin=Ensalutanta al la servilo... + +/update.bml.noneother=Neniu, aÅ­ alia: + +/update.bml.note|staleness=1 +/update.bml.note=Rimarku: La tempo/dato supre estas de nia servilo. Korektu ilin laÅ­ via horzono antaÅ­ afiÅi. + +/update.bml.opt.backdate=AntaÅ­datigu Enskribo: + +/update.bml.opt.backdate.about=ne montriÄos ĉe geamika vidaĵo + +/update.bml.opt.defpic=(defaÅ­lta) + +/update.bml.opt.nocomments=Malpermesu komentojn: + +/update.bml.opt.noemail=Ne enretpoÅtigu komentojn: + +/update.bml.opt.noformat=Ne aÅ­tomate formatu: + +/update.bml.opt.spellcheck=Kontrolu literumadon de enskribo antaÅ­ ol afiÅi [utila nur kun la angla?] + +/update.bml.options=Nedevigaj Preferigoj + +/update.bml.other=Alia: + +/update.bml.picture=Uzu la bildon: + +/update.bml.preview.header=AntaÅ­rigardo + +/update.bml.security.custom=Aparta... + +/update.bml.security.friends=Geamikoj + +/update.bml.security.head=Sekureca Nivelo: + +/update.bml.security.private=Privata + +/update.bml.security.public=Publika + +/update.bml.servermsg=AnkaÅ­, la servilo havas mesaÄon por vi: + +/update.bml.simple=Vi rigardas la simplan paÄon. Por pli da elektoj, iru ĉi tien. + +/update.bml.spellchecked=Via literuma-kontrolita afiÅo: + +/update.bml.subject=Subjekto: (nedeviga) + +/update.bml.timeformat=24-hora tempo + +/update.bml.title=Äœisdatigu la Taglibron + +/update.bml.title.readonly=Nur-lega modalo + +/update.bml.update.head=Äœisdatigu Vian Taglibron... + +/update.bml.update.success=La Äisdatigo sukcesis. Vi povas vidi vian Äisdatigitan taglibron ĉi tie. + +/update.bml.updating=Äœisdatigata la taglibro... + +/uploadpic.bml.error.unsupportedtype=Dosieroj de la tipo [[filetype]] ne estas subtenata. Vi povas alÅuti sole GIF-ajn, PNG-ajn, aÅ­ JPG-ajn dosierojn. PreskaÅ­ ĉiuj el bildaj/fotaj programoj povas konverti al tiuj formatoj. + +/userinfo.bml.about.comm=Pri + +/userinfo.bml.about.user=Historieto: + +/userinfo.bml.body.leave=Vi eblas forlasi la komunumon iam kiam vi volas. + +/userinfo.bml.comminfo.body=Ĉi-sube estas informoj pri la "[[commname]]" -komunumo en LiveJournal. + +/userinfo.bml.comminfo.name=Komunuminformoj + +/userinfo.bml.date.never=Neniam. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=La uzantnomo misformiÄis. + +/userinfo.bml.error.notloggedin=Se vi deziras vidi vian uzantprofilon, vi devas ensalutiÄi. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Observata de: + +/userinfo.bml.friendof.hidden=(kaÅata(j)) + +/userinfo.bml.friendof.syndreadcount=Numero de Legantoj + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Amik(in)o de: + +/userinfo.bml.friends.comm=Membroj + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Amikoj + +/userinfo.bml.label.addbuddy=Aldonu Uzanton + +/userinfo.bml.label.adduser=Aldonu Uzanton + +/userinfo.bml.label.aolim=AOL-Nomo: + +/userinfo.bml.label.birthdate=NaskiÄtago: + +/userinfo.bml.label.clientsused=Uzataj klientiloj: + +/userinfo.bml.label.comments=Komentoj: + +/userinfo.bml.label.composted=AfiÅita: [[num]] - + +/userinfo.bml.label.comreceived=Ricevita: [[num]] + +/userinfo.bml.label.datecreated=Kiam kreita: + +/userinfo.bml.label.dateupdated=Kiam Äisdatigita: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=RetpoÅtadreso: + +/userinfo.bml.label.icquin=ICQ-Numero: + +/userinfo.bml.label.interests=Interesoj + +/userinfo.bml.label.interests.modifyyours=ÅœanÄu la via + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] interesoj ne montrataj + +/userinfo.bml.label.journalentrs=Taglibraj enskriboj: + +/userinfo.bml.label.location=Loko: + +/userinfo.bml.label.memberof=Membro de + +/userinfo.bml.label.memories=Memoroj + +/userinfo.bml.label.moredetails=(pli da detaloj...) + +/userinfo.bml.label.msnusername=MSN-Uzantnomo: + +/userinfo.bml.label.name=Nomo: + +/userinfo.bml.label.nofriends=Neniuj listigitaj. + +/userinfo.bml.label.reqfinduser=Nur uzantoj kun 'finduser'-privilegio rajtas serĉi uzantojn per uzanta ID. + +/userinfo.bml.label.sendmessage=Sendu MesaÄon + +/userinfo.bml.label.shared=AfiÅi-Rajto: + +/userinfo.bml.label.supportpoints=Subteni-Punktoj + +/userinfo.bml.label.syndicatedfrom=Sindikatita de: + +/userinfo.bml.label.syndicatedstatus=Sindikateca Stato: + +/userinfo.bml.label.textmessage=Teksta
      MesaÄo
      : + +/userinfo.bml.label.todo=Farendaĵa Listo + +/userinfo.bml.label.user=Uzanto: + +/userinfo.bml.label.viewfriends=Vidu Geamikojn + +/userinfo.bml.label.viewmembers=Vidu Membrojn + +/userinfo.bml.label.website=TTT-ejo: + +/userinfo.bml.label.yahooid=Yahoo!-ID: + +/userinfo.bml.membership.body=Por kuniÄi en ĉi tiun komunumon, klaku ĉi tien. + +/userinfo.bml.memories.entries=[[count]] enskriboj + +/userinfo.bml.memories.entry=[[count]] enskribo + +/userinfo.bml.monitor.comm=Observu Komunumon + +/userinfo.bml.monitor.user=Aldonu ĉi tiun uzanton al via listo de geamikoj + +/userinfo.bml.nonexist.body=La uzantnomo [[user]] ne troveblas inter la registritaj. + +/userinfo.bml.nonexist.name=Nekonata uzanto + +/userinfo.bml.sendmessage.body=Sendu [[user]] tekstan mesaÄon
      al lia/Åia kunportebla telefono/tekstmesaÄilo. + +/userinfo.bml.syn.last.never=Neniam + +/userinfo.bml.syn.lastcheck=Lastatempe kontrolita: + +/userinfo.bml.syn.nextcheck=Sekvanta kontrolota: + +/userinfo.bml.syn.parseerror=ErarmesaÄo: + +/userinfo.bml.syndinfo.body=Se vi volas ke artikuloj de la sindikatita TTT-ejo aperas sur via geamika paÄo, vi povas aldoni tiun taglibron al via geamika paÄo. + +/userinfo.bml.syndinfo.name=Sindikata Taglibro + +/userinfo.bml.tellafriend=Informu Amikon! + +/userinfo.bml.timeupdate.dayago=antaÅ­ 1 tago + +/userinfo.bml.timeupdate.daysago=antaÅ­ [[num]] tagoj + +/userinfo.bml.timeupdate.hourago=antaÅ­ 1 horo + +/userinfo.bml.timeupdate.hoursago=antaÅ­ [[num]] horoj + +/userinfo.bml.timeupdate.minuteago=antaÅ­ 1 minuto + +/userinfo.bml.timeupdate.minutesago=antaÅ­ [[num]] minutoj + +/userinfo.bml.timeupdate.secondago=antaÅ­ 1 sekundo + +/userinfo.bml.timeupdate.secondsago=antaÅ­ [[num]] sekundoj + +/userinfo.bml.timeupdate.weekago=antaÅ­ 1 semajno + +/userinfo.bml.timeupdate.weeksago=antaÅ­ [[num]] semajnoj + +/userinfo.bml.title=Uzantinformoj + +/userinfo.bml.title.communityinfo=Komunuminformoj + +/userinfo.bml.title.syndicated=Sindikatita Konto + +/userinfo.bml.userinfo.body=Jen malsupre la uzantinformojn por [[username]]. Se vi estas tiu uzanto, vi povas redakti viajn informojn (aÅ­ elekti kiuj informoj estu publikaj) sur la Redaktu Informojn paÄo. + +/userinfo.bml.userinfo.name=Uzantinformoj + +BML.parse_multipart.parse=Eraro kun sintakse analizi Äisdatigon + +BML.parse_multipart.toolarge=Tro granda alÅuto + +BML.parse_multipart.unknowntype=Nekonata enhavotipo + +btn.search=Serĉu + +crumb.acctfeatures=Funkcioj LaÅ­ Kontotipo + +crumb.latestposts=Plej FreÅaj AfiÅoj + +date.day.friday.long=vendredon + +date.day.friday.short=ven + +date.day.monday.long=lundon + +date.day.monday.short=lun + +date.day.saturday.long=sabaton + +date.day.saturday.short=sab + +date.day.sunday.long=dimanĉon + +date.day.sunday.short=dim + +date.day.thursday.long=ĵaÅ­don + +date.day.thursday.short=ĵaÅ­ + +date.day.tuesday.long=mardon + +date.day.tuesday.short=mar + +date.day.wednesday.long=merkredon + +date.day.wednesday.short=mer + +date.month.april.long=aprilo + +date.month.april.short=apr + +date.month.august.long=aÅ­gusto + +date.month.august.short=aÅ­g + +date.month.december.long=decembro + +date.month.december.short=dec + +date.month.february.long=februaro + +date.month.february.short=feb + +date.month.january.long=januaro + +date.month.january.short=jan + +date.month.july.long=julio + +date.month.july.short=jul + +date.month.june.long=junio + +date.month.june.short=jun + +date.month.march.long=marto + +date.month.march.short=mar + +date.month.may.long=majo + +date.month.may.short=maj + +date.month.november.long=novembro + +date.month.november.short=nov + +date.month.october.long=oktobro + +date.month.october.short=okt + +date.month.september.long=septembro + +date.month.september.short=sep + +dystopia.btn.login=ENSALUTU + +dystopia.hello_anonymous=Bonvenon al LiveJournal! + +dystopia.hello_loggedin=Saluton, [[username]]! + +dystopia.nav.createjournal=Kreu Taglibron + +dystopia.nav.developer=Programistejo + +dystopia.nav.download=ElÅutu + +dystopia.nav.editentries=Redaktu Enskribojn + +dystopia.nav.editfriends=Viaj Geamikoj + +dystopia.nav.editpassword=Via Pasvorto + +dystopia.nav.editpics=Viaj Bildoj + +dystopia.nav.editstyle=Redaktu Stilon + +dystopia.nav.faq=LiveJournal OD + +dystopia.nav.findcomm=LaÅ­ Komunumo + +dystopia.nav.finddir=Adresara Serĉo + +dystopia.nav.findint=LaÅ­ Intereso + +dystopia.nav.findrandom=Hazarde + +dystopia.nav.findregion=LaÅ­ Regiono + +dystopia.nav.home=Hejmo + +dystopia.nav.journalcalendar=Kalendaro + +dystopia.nav.journalfriends=Geamikoj + +dystopia.nav.journalinfo=Uzantinformoj + +dystopia.nav.journalrecent=Lastatempaj + +dystopia.nav.legalprivacy=Privateco + +dystopia.nav.legaltos=Servaj Kondiĉoj + +dystopia.nav.login=Ensalutu + +dystopia.nav.logout=Elsalutu + +dystopia.nav.lostinfo=Perdita Pasvorto + +dystopia.nav.memories=Memoroj + +dystopia.nav.modifyjournal=ÅœanÄu Taglibron + +dystopia.nav.news=Novaĵoj + +dystopia.nav.paidaccts=Pagitaj Kontoj + +dystopia.nav.paymentarea=Pagejo + +dystopia.nav.personalinfo=Personaj Informoj + +dystopia.nav.sitemap=TTT-eja Mapo + +dystopia.nav.siteopts=Retumaj opcioj + +dystopia.nav.support=Ĉu Demando? + +dystopia.nav.updatejournal=Äœisdatigu la Taglibron + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=146 + +dystopia.navhead.findusers=Trovu Uzantojn + +dystopia.navhead.help=Helpo & Subteno + +dystopia.navhead.journal=Via Taglibro + +dystopia.navhead.legal=LeÄaj Informoj + +dystopia.navhead.settings=Viaj Preferigoj + +dystopia.navhead.welcome=Bonvenon! + +dystopia.search.aolim=AOL-tujmesaÄilo + +dystopia.search.icq=ICQ-numero + +dystopia.search.int=Intereso + +dystopia.search.msn=MSN-Uzantnomo + +dystopia.search.region=Regiono + +dystopia.search.yahoo=Yahoo!-ID + +dystopia.searchlj=Serĉu interne de LiveJournal + +Email=RetpoÅtadreso + +email.newacct.body<< +Gratulon, vi havas novas LiveJournal-an konton! + +Por kompletigi vian taglibran kreadon kaj kontroli vian retpoÅtadreson, iru tien: + + [[regurl]] + +La URL, kie via nova taglibro estas trovebla, estas: + + [[siteroot]]/users/[[username]]/ + +kaj ankaÅ­: + + [[siteroot]]/~[[username]]/ + +Jen malsupre via LiveJournal-a uzantnomo kaj pasvorto: +Below is your LiveJournal username and password: + + Uzantnomo: [[username]] + Pasvorto: [[password]] + +Vi povas viziti [[siteroot]]/ por viziti vian konton, krei novajn taglibrajn enskribojn kaj modifi viajn taglibrajn elektojn, sed ni rekomendas ke vi elÅutas LiveJournal-an klientilon. Äœi estas la plej facila metodo Äisdatigi vian taglibron, kaj estas tre multaj klientiloj haveblaj por multaj platformoj! ElÅutu unu ĉe: + + [[siteroot]]/download/ + +Komenci kun LiveJournal povas esti kelke malfacila kiam vi ne konas iun. Vizitu http://newbies.livejournal.com por ruzaj, helpemaj konsiloj... +Kun iom da bonÅanco, vi estos LiveJournal-a profesiulo en nultempo! + +Ni esperas ke vi Åatas LiveJournal-on kiom multe, kiel ni Åatas alporti Äin al vi. Se vi havas iun ajn demandon pri la uzado de LiveJournal, bonvolu viziti la subtenejon ĉe: + + [[siteroot]]/support/ + +Tie vi trovos respondojn por preskaÅ­ iu ajn demando vi povus demandi pri LiveJournal. + +Nia venko estas tute frenezegigi LiveJournal-on... se vi povas fari iun por plifaciligi, plifortegigi, plikutimebligi Äin, ion ajn... rakontu Äin al ni. +Ni ne havas la TTT-ejon por fari monon. Ni ne estas dot-com-firmo, salajratata per riskkapital-esperantan aÄiotisto... ĉi tiu paÄo funkcias per tute da homoj kiuj uzas Äin. Rakontu al ni kion vi volas el Äi. + +Se vi havas demandon, la subtenanta teamo havos respondon por vi dum malpli ol 24 horoj. + +Äœoju! + +[[sitename]] Teamo +[[siteroot]]/ +. + +email.newacct.subject=Bonvenon al LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Eraro + +error.badpassword=Malkorekta Pasvorto. + +error.dberror=Datumbaza eraro okazis: + +error.deleted.name=Forigita + +error.deleted.text=Ĉi tiu taglibro estas forigita. Se vi estas [[user]], estas periodo da 30 tagoj post la horo de forigo por malforigi la taglibron. Post 30 tagoj ni persiste forigos ĉiuj enhavoj el niaj serviloj. + +error.deleted.title=Forigita Konto + +error.ipbanned=Via IP-adreso portempe malpermesita por ke superi la enslauti-malsukcesega rato. + +error.malformeduser=Malformata uzantnomo. + +error.nobutton=Ĉu neniu butono premita? + +error.nodb=Datumbazo portempe nehavebla. + +error.nodbmaintenance=Ĉi tiu parto de la datumbazo estas portempe nefunkciebla ĉar konservado. Reprovu ankoraÅ­foje post kelkaj minutoj. + +error.noentry=Neniu tia taglibra enskribo. + +error.nojournal=Nekonata Taglibro + +error.noremote=Vi devas ensaluti por uzi ĉi tiun paÄon. + +error.procrequest=Okazis eraro dum procesi vian demandon: + +error.purged.name=Forigita + +error.purged.text=Ĉi tiu taglibro estas forigita kaj senrubigita. + +error.purged.title=Senrubigita Konto + +error.suspended.name=Provizore Forigita + +error.suspended.text=Ĉi tiu konto estas aÅ­ portempe aÅ­ ĉiame forigita. Se vi estas [[user]], bonvolu legi la OD-on Mia konto estas provizore forigita! Kiel mi rehavigas Äin? por pli da informoj. Bonvolu rimarki, ke por konservi la privatecon de niaj uzantoj, [[sitename]] ne povas priparoli la kaÅ­zojn de la provizora forigo kun iu ajn escepte de la posedanto de la konto. + +error.suspended.title=Provizore Forigita Konto + +error.tempdisabled=Ĉi tiu estas portempe malebligita. + +error.unknownmode=Nekonata reÄimo. + +error.usernameinvalid=Uzantnomo enhavas nevalidajn signojn. + +error.usernamelong=Uzantnomo estas tro longa; 15 signoj maksimume. + +error.username_notfound=Uzantnomo ne troviÄis. + +Help=Helpo + +label.screening.all=Ĉiuj komentoj + +label.screening.header=KaÅantaj Komentoj: + +label.security.custom=Individuiga... + +label.security.friends=Geamikoj + +label.security.head=Sekureca Nivelo: + +label.security.private=Privata + +label.security.public=Publika + +label.switch.button=InterÅanÄu + +label.switch.header=InterÅanÄu la Taglibron + +label.switch.workwith=Prilabori la taglibron: + +langname.be=la belarusa + +langname.da=la dana + +langname.de=la germana + +langname.en=la angla + +langname.en_GB=la angla (brita) + +langname.en_LJ=la angla + +langname.eo=Esperanto + +langname.es=la hispana + +langname.et=la estona + +langname.fi=la finna + +langname.fr=la franca + +langname.ga=la irlanda + +langname.gd=la gaela + +langname.he=la hebrea + +langname.hu=la hungara + +langname.is=la islanda + +langname.it=la itala + +langname.ja=la japana + +langname.la=la latina + +langname.lv=la latva + +langname.ms=la malaja + +langname.nb=la norvega (bokmÃ¥l) + +langname.nl=la nederlanda + +langname.nn=la norvega (nynorsk) + +langname.pl=la pola + +langname.pt=la portugala + +langname.ru=la rusa + +langname.sv=la sveda + +langname.tr=la turka + +langname.uk=la ukrajna + +langname.zh=la ĉina (simpligata) + +ljcom.accounttype=Kontotipo + +ljcom.userinfo.accounttype=Kontotipo + +ljcom.userinfo.types.early=Frua Adoptanto + +ljcom.userinfo.types.paid_early=Pagita Konto, antaÅ­e Frua Adoptanto + +ljcom.userinfo.types.paid_early_expiring=Pagita Konto, finiÄota [[paiduntil]], antaÅ­e Frua Adoptanto + +ljcom.userinfo.types.permanent_early=Konstanta Konto, antaÅ­e Frua Adoptanto + +ljlib.pageofpages=PaÄo [[page]] el [[total]] + +lostinfo.head=Ĉu vi forgesis ion? + +lostinfo.text=Se vi forgesis vian uzantnomon aÅ­ pasvorton, reakiru Äin ĉi tie. + +Password=Pasvorto + +password.max30=Pasvortoj ne rajtas esti pli longaj ol 30 signoj. + +poll.error.cantview=Eraro: vi ne rajtas rigardi ĉi tiujn balotajn rezultojn. + +poll.error.cantvote=BedaÅ­rinde, vi ne estas permesita baloti en ĉi tiu baloto. + +poll.error.missingljpoll=Ĉiuj lj-pq etikedoj devas esti ingita interne de lj-poll etikedo. + +poll.error.noentry=Eraro: ĉi tiu baloto ne estas fiksita al ĉi tiu taglibra enskribo + +poll.error.noitems=Vi devas havi almenaÅ­ unu ero en ne-teksta balota demando. + +poll.error.noitemstext=lj-pq etikedoj de tipo 'teksto' ne povas enhavi balotajn erojn. + +poll.error.nopollid=pollid parametro mankas. + +poll.error.noquestions=Vi devas have almenaÅ­ unu demando en baloto. + +poll.error.pollnotfound=Eraro: baloto #[[num]] ne trovita + +poll.error.questionnotfound=Eraro: ĉi tiu balota demando ne ekzistas. + +poll.pollnum=Baloto #[[num]] + +poll.submit=Konservu Baloton + +portal.bdays.count.des=DefaÅ­lte, la 5 geamikoj kun la plej baldaÅ­aj naskiÄtagoj estas montrataj. + +portal.bdays.count.name=Montrotaj NaskiÄtagoj + +portal.bdays.portalname=NaskiÄtagoj + +portal.bdays.portaltitle=NaskiÄtagoj + +portal.goat.name=PaÄa Bestsimbolo + +portal.goattext.des=Kion vi volas ke via kapro diras? La sola kion kaproj povas diri, estas 'Beeeee', sed vi povas Åajnigi ke via kapro povas diri iun alian, se vi vere volas. + +portal.goattext.name=Kapra Teksto + +portal.login.portalname=Ensalutada Kesto + +portal.memories.entriesnoun=enskriboj + +portal.memories.entrynoun=enskribo + +portal.memories.portalname=Memorindaj AfiÅoj + +portal.memories.portaltitle=Memorindaj AfiÅoj + +portal.ministats.active=Aktivaj: + +portal.ministats.title=Uzantaj Statistikoj + +portal.ministats.total=Tutaj: + +portal.misbehaved.des=Vi vere volis lasi Äin nekontrolita. Kaproj kiuj ne estas edukitaj, nur estas Äenaj. + +portal.misbehaved.name=Miskondutanta Kapro + +portal.newtolj.name=TTT-ejaj Ligiloj + +portal.popfaq.portalname=10 Plej Ofte Vizititaj OD-oj + +portal.popfaq.portaltitle=10 Plej Ofte Vizititaj OD-oj + +portal.randuser.count.des=DefaÅ­lte, 1 hazarda uzanto estas montrita, sed vi povas havi Äis 10 uzantojn vertikale en la malvastaj kolonoj, aÅ­ 5 horizontale en vasta kolono + +portal.randuser.count.name=Nombro de montrotaj hazardaj uzantoj + +portal.randuser.error.tableempty=Ne ekzistas hazardaj uzantoj. Kontaktu la administriston. + +portal.randuser.hidename.des=DefaÅ­lte, la hazarda uzantnomo estas montrata. Kontrolu tion por elpreni Äin. + +portal.randuser.hidename.name=KaÅu Nomon + +portal.randuser.hidepic.des=DefaÅ­lte, la hazarda uzantbildo estas montrata, se havebla. Kontrolu tion por elpreni Äin. + +portal.randuser.hidepic.name=KaÅu Uzantbildon + +portal.randuser.portalname=Hazarda Uzanto + +portal.randuser.portaltitle=Hazarda Uzanto + +portal.randuser.portaltitleplural=Hazardaj Uzantoj + +portal.recent.error.noentries=Pardonu. Neniuj enskriboj. + +portal.recent.error.notsetup=Vi devas konfiguri ĉi tiun keston. Klaku sur la plus-simbolon por agordi la taglibron kiun vi volas vidi ĉi tie. + +portal.recent.error.userstatus=Uzanto forigis aÅ­ provizore forigis sian konton. + +portal.recent.items.description=DefaÅ­lte, nur la plej nova enskribo estas montrata. + +portal.recent.items.name=Anoj por vidigi + +portal.recent.journal.description=De kiu taglibro vi volas vidi la novajn anojn? + +portal.recent.journal.name=Taglibro + +portal.recent.nosubject=(Neniu Temo) + +portal.recent.permlink=Ligilo + +portal.recent.portalname=Novaj Enskriboj Vido + +portal.recent.portaltitle=Novaj Enskriboj Kesto + +portal.recent.showtext.description=DefaÅ­lte, nur subjektoj estas montrata. + +portal.recent.showtext.name=Inkluzivu Tekston + +portal.stats.journalentyest=Taglibraj enskriboj hieraÅ­ + +portal.stats.portalname=TTT-ejaj Statistikoj + +portal.stats.portaltitle=Statistikoj + +portal.stats.totalusers=Tutaj uzantoj + +portal.update.mode.des=Plena modo ofertas al vi tre multe da ekstra-afiÅaj elektoj... inkluzive de afiÅi en komunumojn kaj preferigi vian nunan humoron, muzikon kaj bildon. Simpla modo estas pli afabla se vi apenaÅ­ uzas tiujn trajtojn kaj preferus neniam vidi Äin. + +portal.update.mode.full=Plena + +portal.update.mode.name=Modo + +portal.update.mode.simple=Simpla + +portal.update.portalname=Taglibra Äœisdatigilo + +portal.update.portaltitle=Äœisdatigu Vian Taglibron + +protocol.bad_password=Via pasvorto estas tro facile supozebla. Rekomendate, ÅanÄu Äin, kontraÅ­e vi riskas ke via taglibro estas forkaptota. Vizitu [[siteroot]]/changepassword.bml por ÅanÄi vian pasvorton. + +protocol.hello_test=Saluton al Prova Konto! + +protocol.mail_bouncing=Vi nuntempe estas uzanta malÄustan retpoÅtadreson. Tute da retpoÅto, kiun ni provas sendi, estas resendata. [[sitename]] bezonas validan retpoÅtadreson por kontinui uzon. Vizitu [[siteroot]]/support/faqbrowse.bml?faqid=19 por scii pri kiel oni ÅanÄas sian retpoÅtadreson. + +protocol.modpost=Via enskribo estas metita en la modero-vicon. Äœi estas akceptota aÅ­ rifuzita de unu de la komunumaj moderantoj. + +protocol.must_revalidate=Vi devas validigi vian novan retpoÅtadreson. Via malnova estis bona, sed ĉar vi ÅanÄis Äin, vi devos revalidigi la novan. Se vi ne validigi vian adreson, vi ne havos rajton por tute da funkcioj de [[sitename]]. Vizitu [[siteroot]]/support/faqbrowse.bml?faqid=11 por pli multe da informoj. + +protocol.not_validated=Via retpoÅtadreso ne estas validigita. Vi povas plue uzi [[sitename]], sed se vi ne validigas vian adreson, vi ne havos rajton por tute da funkcioj de la TTT-ejo. Vidu la instrukciojn kiuj estas sendita al vi kiam vi kreis vian taglibron, aÅ­ vizitu [[siteroot]]/support/faqbrowse.bml?faqid=11 por pli multe da informoj. + +protocol.old_win32_client=Estas grave pli novaj Vindozaj LiveJournal-aj klientiloj haveblaj, kaj ni rekomendas ke vi Äisdatigas. Vizitu [[siteroot]]/download/ por elÅuti pli novan klientilon. + +protocol.readonly=Via konto estas portempe en nur-legata modo. Iom da operacioj ne funkcios por kelkaj minutoj. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=BedaÅ­ron + +talk.anonwrote=Iu skribis, + +talk.anonwrote_comm=Iu skribis ĉe [[commlink]], + +talk.btn.preview=AntaÅ­rigardu + +talk.commentpermlink=ligilo + +talk.commentpost=AfiÅu novan komenton + +talk.commentsread=Legu komentojn + +talk.curname_Mood=Nuna humoro: + +talk.curname_Music=Nuna muziko: + +talk.error.bogusargs=Åœajnaj argumentoj + +talk.error.comm_deleted=Ĉi tiu komento estas forigita. + +talk.error.deleted=Ĉi tiu taglibro estas forigita. + +talk.error.deleted.title=Forigita + +talk.error.mustlogin=Vi devas esti ensalutita por vidi ĉi tiun protektatan enskribon. + +talk.error.nocomment=La komento ne ekzistas. + +talk.error.noentry=La enskribo ne ekzistas. + +talk.error.nojournal=Eraro: ne eblis determini taglibron el argumentoj. + +talk.error.nosuchjournal=La taglibro ne ekzistas + +talk.error.notauthorised=Vi ne rajtas vidi ĉi tiun protektitan enskribon. + +talk.error.suspended=Ĉi tiu taglibro/afiÅanto estas provizore forigita. + +talk.error.suspended.title=Provizore Forigita + +talk.parentlink=Patro + +talk.readsimilar=Legu similajn taglibrajn enskribojn: + +talk.replytothis=Respondu al tiu ĉi + +talk.somebodywrote=[[realname]]([[userlink]]) skribis, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) skribis ĉe [[commlink]], + +talk.spellcheck=Kontrolu ortografie dum antaÅ­rigardi + +talk.threadlink=Fadeno + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_esperanto + +Username=Uzantnomo + +userpic.inactive=Neaktiva + +xcolibur.greeting.anon=Bonvenon al LiveJournal! + +xcolibur.greeting.logged_in=Bonvenon, [[name]]! [[logout]] + +xcolibur.login=Ĉu ensalutu? + +xcolibur.logout=Ĉu elsalutu? + +xcolibur.nav.about=Pri + +xcolibur.nav.about.download=ElÅutu + +xcolibur.nav.about.general=Äœeneralaj Informoj + +xcolibur.nav.about.paidaccounts=Pagitaj Kontoj + +xcolibur.nav.about.press=Gazetaro + +xcolibur.nav.about.sitenews=TTT-ejaj Novaĵoj + +xcolibur.nav.about.stats=Statistikoj + +xcolibur.nav.footer.sitemap=TTT-eja Mapo + +xcolibur.nav.help=Helpo + +xcolibur.nav.help.ask=Demandu Ion + +xcolibur.nav.help.faq=OD + +xcolibur.nav.help.lostpassword=Perdita Pasvorto + +xcolibur.nav.home=Hejmo + +xcolibur.nav.journal=Taglibro + +xcolibur.nav.journal.archive=ArÄ¥ivo + +xcolibur.nav.journal.edit.entries=Redaktu Enskribojn + +xcolibur.nav.journal.friends=Geamikoj + +xcolibur.nav.journal.info=Informoj + +xcolibur.nav.journal.memories=Memoroj + +xcolibur.nav.journal.recent=Lastatempaj + +xcolibur.nav.journal.update=Äœisdatigu + +xcolibur.nav.manage=Administru + +xcolibur.nav.manage.community=Komunumoj + +xcolibur.nav.manage.customize=Kutimigi + +xcolibur.nav.manage.entries=Enskriboj + +xcolibur.nav.manage.friends=Geamikoj + +xcolibur.nav.manage.info=Informoj + +xcolibur.nav.manage.password=Pasvorto + +xcolibur.nav.manage.pics=Uzantaj Bildoj + +xcolibur.nav.manage.styles=Stiloj + +xcolibur.nav.search=Serĉu + +xcolibur.nav.search.directory=LaÅ­ Regiono + +xcolibur.nav.search.directory.search=Altgrada + +xcolibur.nav.search.interests=Interesoj + +xcolibur.nav.search.random=Hazarde + +xcolibur.nav.siteopts=Retumaj opcioj + +xcolibur.nav.title=Navigaciu: + +xcolibur.nav.welcome=Bonvenon + +xcolibur.nav.welcome.create=Kreu konton + +xcolibur.nav.welcome.login=Ensalutu + +xcolibur.nav.welcome.update=Äœisdatigu Vian Taglibron + +xcolibur.search=Serĉu: + +xcolibur.search.category=Kategorio: + +xcolibur.search.icq=ICQ-numero + +xcolibur.search.int=Intereso + +xcolibur.search.msn=MSN-uzantnomo + +xcolibur.search.region=Regiono + +xcolibur.search.yahoo=Yahoo!-ID + +xcolibur.upgrade=Promociu Vian Konton + diff --git a/ljcom/bin/upgrading/es.dat b/ljcom/bin/upgrading/es.dat new file mode 100644 index 0000000..29fbe61 --- /dev/null +++ b/ljcom/bin/upgrading/es.dat @@ -0,0 +1,3313 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Si quieres borrar o reactivar tu diario, lo puedes hacer aquí. Una vez borrado tu diario, tienes 30 días para reactivarlo, por si cambies de idea. Después de los 30 días, se borrará permanentemente el diario y no habrá cómo recuperarlo. + +/accountstatus.bml.journalstatus.head=Estado de Diario + +/accountstatus.bml.journalstatus.select.activated=Activado + +/accountstatus.bml.journalstatus.select.deleted=Borrado + +/accountstatus.bml.journalstatus.select.head=Estado: + +/accountstatus.bml.journalstatus.select.suspended=Suspendido + +/accountstatus.bml.title=Estado de cuenta + +/allpics.bml.current=Imágenes actuales + +/allpics.bml.default=Por defecto + +/allpics.bml.edit2=Tal vez te interese modificar las palabras clave de imagen o cargar una nueva imagen. + +/allpics.bml.error.noparam=Debes especificar un parámetro de nombre de usuario. + +/allpics.bml.keywords=Palabras clave: + +/allpics.bml.nopics.text.other=Este usuario no tiene cargada ninguna imagen de usuario. + +/allpics.bml.nopics.text2=No tienes imágenes cargadas. Para cargar una, pulsa aquí. + +/allpics.bml.nopics.title=Sin imágenes + +/allpics.bml.pics=Estas son las imágenes de [[user]]. + +/allpics.bml.title=Imágenes de usuario + +/changepassword.bml.btn.proceed=Seguir + +/changepassword.bml.changepassword.header=Cambiar contraseña + +/changepassword.bml.changepassword.instructions|staleness=1 +/changepassword.bml.changepassword.instructions=Llene el formulario abajo para cambiar tu contraseña. + +/changepassword.bml.email.body<< +Se ha cambiado tu contraseña en [[sitename]]. + +Para recuperarlo en el futuro, accede a: + +[[siteroot]]/lostinfo.bml + +Atentamente, + +La dirección de [[siteroot]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Cambio de contraseña + +/changepassword.bml.error.badcheck=Nueva contraseña inválida: [[error]] + +/changepassword.bml.error.badnewpassword=Las nuevas contraseñas no son idénticas. Tal vez has cometido un error tipográfico. Escribe las dos de nuevo. + +/changepassword.bml.error.badoldpassword=Tu antigua contraseña no es correcta. + +/changepassword.bml.error.blankpassword=La nueva contraseña no se puede dejar en blanco. + +/changepassword.bml.error.changetestaccount=No se puede cambiar la contraseña de la cuenta de prueba. + +/changepassword.bml.error.characterlimit=Hay un límite de 30 caracteres para las contraseñas. + +/changepassword.bml.error.invaliduser=Usuario inválido [[user]]. Este usuario no existe. ¿Estás seguro de que lo escribiste bien? + +/changepassword.bml.error.mustenterusername=Tienes que introducir tu nombre de usuario. + +/changepassword.bml.error.nonascii=Las contraseñas únicamente pueden formarse con símbolos ASCII. Por favor, elije una contraseña que no utilice símbolos excluidos del código ASCII. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=No puedes cambiar tu contraseña si tu direccón actual de correo electrónico no ha sido validada. + +/changepassword.bml.newpassword=Nueva contraseña: + +/changepassword.bml.newpasswordagain=Nueva contraseña (de nuevo): + +/changepassword.bml.oldpassword=Antigua contraseña: + +/changepassword.bml.proceed.instructions=Pulsa el botón a continuación y se efectuará el cambio de contraseña. Además, recibirás un correo electrónico confirmando el cambio. + +/changepassword.bml.success.text=Tu contraseña ha sido cambiada y el correo electrónico recordatorio se te ha enviado. + +/changepassword.bml.title=Cambiar contraseña + +/community/index.bml.title=Centro de comunidad + +/community/join.bml.button.join=Unirse a la comunidad + +/community/join.bml.label.addtofriends=Añadir "[[maintainer]]" a tu lista de amigos.
      + +/community/join.bml.label.allowposting=Esta comunidad permite poner mensajes a todos sus miembros, así que ahora tienes acceso para poner mensajes en ella. Si ya tienes un cliente de LiveJournal abierto en tu computadora, deberás cerrar sesión e iniciar sesión nuevamente; así este diario aparecerá en la lista de diarios en los que puedes poner mensajes. + +/community/join.bml.label.auth=Aunque estás listado como un miembro, esta comunidad sólo permite la escritura de entradas por usuarios autorizados. Contacta con uno de los administradores si deseas obtener permiso de escritura. A continuación se muestra una lista de los administradores para esta comunidad: [[admins]] + +/community/join.bml.label.banned=El/Los administrador(es) de esta comunidad te han prohibido unirte a ella. + +/community/join.bml.label.closed=Esta comunidad es una comunidad cerrada. Si estás interesado en unirte a ella, por favor contacta con uno de sus administradores. A continuación se muestra una lista de los administradores para esta comunidad: [[admins]] + +/community/join.bml.label.commlogged=Has iniciado sesión en una cuenta compartida/de comunidad, no en tu cuenta personal. + +/community/join.bml.label.errorcomminfo=La información especificada de la comunidad no es válida. + +/community/join.bml.label.expls=Pulsa el botón abajo para unirte a la comunidad de "[[maintainer]]". Borra la casilla abajo si quieres unirte a la comunidad sin ver las entradas de la comunidad en tu página de amigos. + +/community/join.bml.label.loginfirst=Para unirte a una comunidad, primero debes iniciar sesión. + +/community/join.bml.label.membernow=Te has unido a la Comunidad [[commname]] + +/community/join.bml.label.sure=¿Seguro? + +/community/join.bml.success=Hecho + +/community/join.bml.title=Unirte a una comunidad + +/community/leave.bml.button.leave=Dejar la comunidad + +/community/leave.bml.label.buttontoleave=Pulsa el botón abajo para dejar la comunidad "[[commname]]". + +/community/leave.bml.label.infoerror=La información especificada para la comunidad no es válida. + +/community/leave.bml.label.logoutfirst=Para dejar una comunidad, primero debes iniciar sesión. + +/community/leave.bml.label.removed=Has dejado la Comunidad [[commname]] + +/community/leave.bml.label.removefromfriends=También quitar "[[user]]" de tu lista de amigos. + +/community/leave.bml.success=Hecho + +/community/leave.bml.sure=¿Seguro? + +/community/leave.bml.title=Dejar comunidad + +/community/manage.bml.commlist.actions=Acciones + +/community/manage.bml.commlist.actmembers=[Miembros] + +/community/manage.bml.commlist.actmembers2=Miembros + +/community/manage.bml.commlist.actsettings=[Configuración] + +/community/manage.bml.commlist.actsettings2=Configuración + +/community/manage.bml.commlist.header=Tus comunidades + +/community/manage.bml.commlist.none=No administras ninguna comunidad actualmente. + +/community/manage.bml.commlist.text=Aquí se muestran las comunidades que administras o coadministras: + +/community/manage.bml.commlist.title=Título + +/community/manage.bml.commlist.username=Nombre de usuario + +/community/manage.bml.create.header=Crear comunidad + +/community/manage.bml.create.text=También puedes crear una nueva comunidad. + +/community/manage.bml.title=Administración de comunidades + +/community/members.bml.error.alreadyadded=[[user]] no fue añadido porque ya tiene acceso a esta comunidad. + +/community/members.bml.error.alreadysent=No se podía añadir [[user]] porque ya se le envió un email de confirmación el [[datetime]]. Por favor, espera hasta que responda. + +/community/members.bml.error.invaliduser=No se puede añadir la comunidad o cuenta sindicada: [[user]] + +/community/members.bml.error.noaccess=Sólo los administradores de una comunidad pueden modificar su lista de miembros. No eres un administrador de la comunidad [[comm]]. + +/community/members.bml.error.noattr=No se han elegido atributos para el usuario [[user]] + +/community/members.bml.error.nocomm=No se ha encontrado la comunidad. + +/community/members.bml.error.nouser=El usuario no existe: [[user]] + +/community/members.bml.key.admin=Administrador + +/community/members.bml.key.member=Miembro + +/community/members.bml.key.moderate=Moderador + +/community/members.bml.key.post=Permiso de escritura + +/community/members.bml.key.preapprove=Sin moderar + +/community/members.bml.manage2=Administrar comunidades + +/community/members.bml.name=Nombre de comunidad: [[name]] + +/community/members.bml.nextlink=(Página siguiente...) + +/community/members.bml.prevlink=(Página anterior...) + +/community/members.bml.settings=[Configuración] + +/community/members.bml.success.header=Hecho + +/community/members.bml.success.message=Tus cambios se guardaron correctamente. + +/community/members.bml.success.return=Volver a la lista + +/community/members.bml.title=Miembros de la comunidad + +/community/members.bml.update=Actualizar configuración + +/community/moderate.bml.approve.button=Sí, lo apruebo + +/community/moderate.bml.approve.header=¿Aprobar esta entrada? + +/community/moderate.bml.approve.preapprove=Añadir, además, el usuario [[user]] a la lista de usuarios preaprobados para esta comunidad. + +/community/moderate.bml.approve.text=¿Estás seguro de querer aprobar esta entrada? + +/community/moderate.bml.brlist.actions=Acciones + +/community/moderate.bml.brlist.poster=Autor + +/community/moderate.bml.brlist.subject=Asunto comienza por + +/community/moderate.bml.brlist.time=Hora + +/community/moderate.bml.brlist.view=Vista + +/community/moderate.bml.browse.empty=La cola de moderación está vacía. + +/community/moderate.bml.browse.header=Moderar comunidad + +/community/moderate.bml.browse.text=Esta es la cola de moderación para la comunidad [[link]] + +/community/moderate.bml.choice.approve=Aprobar + +/community/moderate.bml.choice.reject=Rechazar + +/community/moderate.bml.error.noaccess=No moderas la comunidad [[comm]]. + +/community/moderate.bml.error.noentry=No se encontró la enrtada (puede que otro moderador haya cerrado el caso). + +/community/moderate.bml.error.nolist=No moderas ninguna comunidad. + +/community/moderate.bml.error.notfound=No se encontró la cuenta de la comunidad. + +/community/moderate.bml.manage=Administrar comunidades + +/community/moderate.bml.moderate=Modera esta comunidad + +/community/moderate.bml.modlist.actions=Acciones + +/community/moderate.bml.modlist.actmodempty=[Modera] + +/community/moderate.bml.modlist.actmoderate=Modera + +/community/moderate.bml.modlist.count=Tamaño de la cola + +/community/moderate.bml.modlist.header=Moderar comunidades + +/community/moderate.bml.modlist.title=Título + +/community/moderate.bml.modlist.username=Nombre de usuario + +/community/moderate.bml.posted.appheader=Preaprobado + +/community/moderate.bml.posted.apptext=Además, el usuario [[user]] ha sido añadido a la lista de usuarios preaprobados para esta comunidad. + +/community/moderate.bml.posted.header=Hecho + +/community/moderate.bml.posted.proterror=La entrada no ha sido enviada a causa de este error de protocolo: [[err]] + +/community/moderate.bml.posted.text=La entrada ha sido enviada con éxito. + +/community/moderate.bml.reject.button=Sí, rechazarlo. + +/community/moderate.bml.reject.header=¿Rechazar esta entrada? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=También puedes explicar al autor los motivos por los cuales has rechazado la entrada. Se enviarán al autor mediante correo electrónico. + +/community/moderate.bml.reject.text=¿Estás seguro de querer rechazar esta entrada? + +/community/moderate.bml.rejected.header=Rechazada + +/community/moderate.bml.rejected.text=La entrada ha sido rechazada. + +/community/moderate.bml.title=Moderación de comunidad + +/community/search.bml.button.clear=Borrar + +/community/search.bml.button.search=¡Buscar! + +/community/search.bml.checkbox.onlywithpics=Sólo las comunidades con imágenes + +/community/search.bml.label.byinterest=Por interés + +/community/search.bml.label.bylocation=Por región + +/community/search.bml.label.bytime=Por la hora de su actualización + +/community/search.bml.label.city=Ciudad: + +/community/search.bml.label.country=País: + +/community/search.bml.label.displayoptions=Opciones de visualización + +/community/search.bml.label.hasmember=Tiene como miembro + +/community/search.bml.label.othercriteria=Otros criterios + +/community/search.bml.label.outputformat=Formato de salida: + +/community/search.bml.label.records=Resultados por página: + +/community/search.bml.label.searchcomm=Buscar comunidades + +/community/search.bml.label.selecriteria=Escoge los criterios según los cuales quieres buscar comunidades. Los resultados que recibes son la intersección de todos los criterios buscados. Es decir que cada casilla que marcas significa "AND" ["y"] y no "OR" ["o"]. + +/community/search.bml.label.sortmethod=Método de clasificación: + +/community/search.bml.label.stateprovince=Estado/Provincia: + +/community/search.bml.label.updated=Actualizada en el último: + +/community/search.bml.sel.bypicture=Por imagen + +/community/search.bml.sel.communityname=Nombre de comunidad + +/community/search.bml.sel.commview=Ver comunidad + +/community/search.bml.sel.day=día + +/community/search.bml.sel.month=mes + +/community/search.bml.sel.updatetime=Hora de actualización + +/community/search.bml.sel.username=Nombre de usuario + +/community/search.bml.sel.week=semana + +/community/search.bml.title=Buscar comunidades + +/community/settings.bml.button.changecommunity=Actualizar configuración + +/community/settings.bml.button.createcommunity=Crear comunidad + +/community/settings.bml.error.badpassword=Contraseña de comunidad no válida + +/community/settings.bml.error.hasentries=Esta cuenta ya tiene entradas y no puede ser convertida. + +/community/settings.bml.error.maintainertype=La cuenta administradora debe ser una persona, no otra cuenta compartida. + +/community/settings.bml.error.noaccess=Sólo los administradores de una comunidad pueden modificar la configuración de la comunidad. No eres un administrador de la comunidad [[comm]]. + +/community/settings.bml.error.notcomm=No es una cuenta de comunidad. + +/community/settings.bml.error.notfound=Cuenta de comunidad no encontrada. + +/community/settings.bml.error.samenames=La cuenta del administrador y la cuenta de la comunidad no pueden la misma. + +/community/settings.bml.label.anybodycan=Todos los miembros
      Cualquiera puede escribir de forma inmediata una vez son miembros. + +/community/settings.bml.label.changeheader=Cambiar configuración de la comunidad + +/community/settings.bml.label.changetext=Aquí puedes cambiar la configuración para tu comunidad o una comunidad que administres. + +/community/settings.bml.label.commchanged=La configuración de tu comunidad ha sido cambiada. + +/community/settings.bml.label.commcreate=Esta cuenta es la que quieres convertir en una comunidad. Debe estar ya creada, pero no debe estar en uso por un individuo, porque tras esta operación muchas otras personas podrían, potencialmente, escribir en el diario. + +/community/settings.bml.label.commcreated=Tu comunidad ha sido creada. + +/community/settings.bml.label.commheader=Cuenta de comunidad + +/community/settings.bml.label.comminfo=Infomación de la comunidad + +/community/settings.bml.label.commopts=Opciones de la comunidad + +/community/settings.bml.label.commsite=Sitio web de la comunidad + +/community/settings.bml.label.community=Comunidad: + +/community/settings.bml.label.createheader=Crear una comunidad + +/community/settings.bml.label.createtext=Desde aquí puedes crear una cuenta de comunidad. Una comunidad es un tipo de cuenta especial a la que pueden unirse otros usuarios y escribir en el diario. Para un ejemplo de una comunidad fíjate en la Comunidad de juergas en Seattle. + +/community/settings.bml.label.howoperates=Elige como funcionará tu comunidad. Puedes cambiar estas opciones más tarde. + +/community/settings.bml.label.maintainer=Administrador: + +/community/settings.bml.label.maintainer.login=Si esta no es la cuenta del administrador, debes iniciar sesión con otra cuenta. + +/community/settings.bml.label.membership=Membresía + +/community/settings.bml.label.modheader=Moderación + +/community/settings.bml.label.modis=Moderada
      Nuevas entradas deben ser aprobadas por un moderador. + +/community/settings.bml.label.modisnt=Sin moderar
      Nuevas entradas aparecen inmediatamente. + +/community/settings.bml.label.modtext=¿Las entradas de esta comunidad son moderadas? + +/community/settings.bml.label.nmcan=Usuarios no miembros pueden escribir
      Usuarios pueden escribir en esta comunidad sin necesidad de unirse a ella. + +/community/settings.bml.label.nmcant=Usuarios no miembros no pueden escribir
      Usuarios deben unirse a la comunidad para poder escribir en ella. + +/community/settings.bml.label.nmheader=Escritura sin membresía + +/community/settings.bml.label.nmtext=¿Pueden usuarios escribir en esta comunidad sin necesidad de unirse a ella? + +/community/settings.bml.label.openmemb=Membresía abierta
      Cualquiera puede unirse sin necesidad de aprobarse su unión. + +/community/settings.bml.label.password=Contraseña: + +/community/settings.bml.label.postaccess=Permiso de escritura + +/community/settings.bml.label.rellinks=Enlaces relacionados: + +/community/settings.bml.label.selcan=Escoge miembros
      Sólo algunos miembros pueden escribir entradas, una vez les hayan recibido permiso por parte de la cuenta administradora. + +/community/settings.bml.label.username=Nombre de usuario: + +/community/settings.bml.label.whocanjoin=¿Quién puede unirse a tu comunidad? + +/community/settings.bml.label.whocanpost=¿Quién puede escribir entradas en esta comunidad? + +/community/settings.bml.manage2=Administrar comunidades + +/community/settings.bml.members=[Miembros] + +/community/settings.bml.name=Nombre de la comunidad: [[name]] + +/community/settings.bml.success=Hecho + +/community/settings.bml.title.create=Crear una comunidad + +/community/settings.bml.title.modify=Configuración de la comunidad + +/create.bml.age.check.question=¿Tienes menos de 13 años de edad? + +/create.bml.age.check.yes=Sí, tengo menos de 13 años. + +/create.bml.age.check2.question=¿Tienes más de 13 años de edad? + +/create.bml.age.check2.yes=Sí, tengo más de 13 años de edad. + +/create.bml.age.head=Edad + +/create.bml.btn.create=Crear diario + +/create.bml.btn.proceed=Adelante + +/create.bml.captcha.answer=Respuesta: + +/create.bml.captcha.audiodesc=Escribe aquí los números que oyes, para comprobar que no eres un «spam robot»: + +/create.bml.captcha.desc=Escribe aquí las letras y los números que ves abajo, para comprobar que no eres un «spam robot». Si no puedes leer el texto, escribe «AUDIO» para comprobarlo auditoriamente + +/create.bml.captcha.play=Escuchar el sonido + +/create.bml.captcha.prove=Comprobar que eres un ser humano + +/create.bml.clusterselect.cluster=Agrupación: + +/create.bml.clusterselect.clusternum=Agrupación [[number]] + +/create.bml.clusterselect.head=Escoger agrupación + +/create.bml.clusterselect.nocluster=Sin agrupación + +/create.bml.clusterselect.text=Por favor, escoge la agrupación en que quieres crear esta cuenta. Fíjate: Esta opción únicamente se aplica a las realizaciones de pruebas y corrección de errores. En realidad, los usuarios no escogerán esto ni tampoco sabrán nada de ello. + +/create.bml.create.head=Crear un diario nuevo + +/create.bml.create.text=Es fácil crear un LiveJournal nuevo, ¡sigue las instrucciones abajo! + +/create.bml.email.head=Tu dirección electrónica + +/create.bml.email.input.head=Dirección electrónica + +/create.bml.error.coppa.under13=Lo sentimos, pero debido a las restricciones de la Ley para la Protección de la Privacidad de Menores de Edad en Línea (COPPA), no puedes usar el servicio de LiveJournal hasta que cumplas 13 años. Por favor, regresa el día que cumplas los 13. + +/create.bml.error.email.blank=Tienes que facilitarnos tu dirección electrónica. + +/create.bml.error.email.lj_domain=No puedes utilizar una cuenta [[domain]] al crear una cuenta. Por favor, escribe una dirección de correo electrónico distinta. + +/create.bml.error.email.nospaces=No se permiten espacios en la dirección electrónica. Si usas AOL, acuérdate de que tu dirección de Correo Electrónico de Internet es tu alias de mensajería sin los espacios, seguido por @aol.com + +/create.bml.error.password.asciionly=Sólo puedes usar caracteres ASCII en la contraseña. + +/create.bml.error.password.blank=Tienes que escribir una contraseña. + +/create.bml.error.password.nomatch=Las contraseñas no son iguales. + +/create.bml.error.postrequired=Se requiere un POST. + +/create.bml.error.username.blank=Por favor, dé un nombre o alias. + +/create.bml.error.username.inuse=Ese nombre de usuario ya está en uso; escoge otro, por favor. + +/create.bml.error.username.iscode=El nombre de usuario parece ser un código de invitación, no un nombre de usuario. + +/create.bml.error.username.mustenter=Tienes que escribir un nombre de usuario. + +/create.bml.error.username.reserved=Lo sentimos, ese nombre de usuario queda reservado. + +/create.bml.initial.friend.news=Noticias y sucesos de LiveJournal + +/create.bml.name.head=Tu nombre: + +/create.bml.name.input.head=Nombre: + +/create.bml.name.text=¿Cuál es tu nombre o alias? Este aparecerá en el título de tu diario, y en el directorio de usuarios si eliges ser incluido. No tienes que dar tu nombre completo ni aun el verdadero. + +/create.bml.password.head=Contraseña + +/create.bml.password.input.head1=Contraseña: + +/create.bml.password.input.head2=Confirmar la contraseña: + +/create.bml.password.text=Escoge una contraseña. + +/create.bml.proceed.btn.proceed=Adelante... + +/create.bml.proceed.warning=Sólo debe pulsar Adelante ¡¡una sola vez!! + +/create.bml.success.btn.enterinfo=Escribir infomación personal + +/create.bml.success.head=¡Hecho! + +/create.bml.success.text1=Se ha creado tu diario. Alguna información importante de registración se ha enviado por correo electrónico a [[email]] con instrucciones adicionales. Asegúrate de confirmar la creación de tu diario pulsando sobre el enlace enviado en el correo electrónico. + +/create.bml.success.text2=Tu LiveJournal estará disponible en: + +/create.bml.success.text3=Ahora, toma el tiempo para llenar alguna información acerca de ti mismo, por favor. La mayoría es opcional, pero nos da una idea de quién está usando LiveJournal. + +/create.bml.title=Crear un diario nuevo + +/create.bml.tos.error=Debes leer y aceptar las condiciones de prestación de servicio antes de crear una cuenta. + +/create.bml.tos.haveread=He leído y aceptado las condiciones de prestación de servicio. + +/create.bml.tos.heading=Condiciones de prestación de servicio + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Para crear una cuenta nueva, escribe un código de creación de cuenta: + +/create.bml.useacctcodes.welcome=Bienvenido + +/create.bml.username.box.head=Nombre de usuario: + +/create.bml.username.forpaidaccts=O, para las cuentas pagadas: + +/create.bml.username.head=Nombre de usuario + +/create.bml.username.ljaddress=Tu diario estará en estas direcciones: + +/create.bml.username.text=Cada usuario de [[sitename]] debe tener su propio nombre de usuario que es único. Tu nombre de usuario es lo que aparece en la dirección de tu diario y lo que utilizas para iniciar sesión en el servidor de [[sitename]]. También aparece cuando escribes comentarios en el diario de otra persona. + +/create.bml.username.username=nombre de usuario + +/customize/index.bml.change=Cambiar + +/customize/index.bml.choose=¿Quieres utilizar el sistema antiguo de estilos o el nuevo? + +/customize/index.bml.choose.header=Elije un sistema de estilos + +/customize/index.bml.choose.s1=Sistema antiguo (S1) + +/customize/index.bml.choose.s2=Sistema nuevo (S2) + +/customize/index.bml.error.cant_generate_user_layer=No se pudo generar la capa de usuario + +/customize/index.bml.error.fail_create_style=Falló la creación del nuevo estilo. + +/customize/index.bml.error.not_your_layout=La distribución no te pertenece + +/customize/index.bml.error.not_your_theme=El tema no te pertenece + +/customize/index.bml.error.no_core_parent=¿Existe la raíz padre? + +/customize/index.bml.previews=(Previsualizaciones) + +/customize/index.bml.s1=El antiguo sistema de estilos se configura mediante la página Modificar Diario. + +/customize/index.bml.s1.header=S1 en uso + +/customize/index.bml.s2.advanced.denied=Sólo cuentas pagadas, permanentes y veteranas pueden usar la personalización avanzada. Descubre los beneficios de tener una cuenta pagada. + +/customize/index.bml.s2.advanced.header=Personalizaciones avanzadas + +/customize/index.bml.s2.advanced.permitted=Para crear nuevas capas y estilos desde cero, visita el centro de personalización avanzada. + +/customize/index.bml.s2.customize=Las siguientes configuraiones dependen de la distribución. + +/customize/index.bml.s2.customize.header=Paso 2: Personalizar Distribución + +/customize/index.bml.s2.customize.language=Los siguientes idiomas son total o parcialmente compatibles con esta distribución. + +/customize/index.bml.s2.customize.language.custom=(Personalizada) + +/customize/index.bml.s2.customize.language.header=Idioma + +/customize/index.bml.s2.customize.settings=Si quieres personalizar más tu diario, aquí puedes modificar las configuraciones individuales para conseguir la presentación exacta que buscas. + +/customize/index.bml.s2.customize.settings.delete=Quitar personalizaciones + +/customize/index.bml.s2.customize.settings.edit=Modificar personalizaciones + +/customize/index.bml.s2.customize.settings.header=Cambiar configuraciones individuales + +/customize/index.bml.s2.customize.settings.new=Personalizar + +/customize/index.bml.s2.customize.themes=Opta por uno de los siguientes temas optativos para esta distribución. + +/customize/index.bml.s2.customize.themes.default=(Distribución por defecto) + +/customize/index.bml.s2.customize.themes.header=Temas + +/customize/index.bml.s2.layout=Escoge tu distribución. Dado que la selección de tema y modificaciones personalizadas dependen de tu distribución, estas podrían descartarse al modificar esta configuración. + +/customize/index.bml.s2.layout.header=Paso 1: Distribución + +/customize/index.bml.s2.related.editinfo.about=Fija el título de tu diario y varias opciones + +/customize/index.bml.s2.related.modify.about=Escoger los iconos de estados de ánimo para tu diario. + +/customize/index.bml.title=Personalizar diario + +/delcomment.bml.confirm.banuser=Prohibir que [[user]] escriba comentarios en tu diario + +/delcomment.bml.confirm.body=¿Estás seguro de que quieres borrar este comentario? + +/delcomment.bml.confirm.head=¿Borrar este comentario? + +/delcomment.bml.confirm.submit=Borrar comentario + +/delcomment.bml.error.alreadydeleted=Ya se ha borrado el comentario especificado. + +/delcomment.bml.error.cantdelete=Un comentario puede ser borrado únicamente por el autor del mismo o por el dueño del diario en que aparece. + +/delcomment.bml.error.cantdelete.comm=Un comentario puede ser borrado únicamente por el autor del mismo, por el autor de la entrada o por un administrador de la comunidad. + +/delcomment.bml.error.nocomment=El comentario especificado no existe. + +/delcomment.bml.success.andban=Se ha borrado el comentario y se le ha prohibido a [[user]] escribir más comentarios en tu diario. + +/delcomment.bml.success.head=Borrado + +/delcomment.bml.success.noban=Se ha borrado el comentario. + +/delcomment.bml.title=Borrar comentario + +/directory.bml.error.accounttype=Lo sentimos, tu tipo de cuenta no permite el uso del directorio, o actualmente no tienes iniciada la sesión. Si tu tipo de cuenta permite el uso del directorio, asegúrate de tener iniciada la sesión. + +/doc/index.bml.about=Bienvenido/a al depósito de documentos de LiveJournal, donde puedes encontrar información sobre la mayoría de los asuntos relacionados con los servicios de LiveJournal o software del servidor. Por favor, elige uno de los asuntos a continuación: + +/doc/index.bml.about.header=Bienvenido/a + +/doc/index.bml.docs.faq.about=Preguntas frecuentes sobre LiveJournal.com + +/doc/index.bml.docs.faq.title=Preguntas frecuentes + +/doc/index.bml.docs.header=Documentos + +/doc/index.bml.docs.howto.about=Trucos y consejos para ayudarte a personalizar tu cuenta de LiveJournal + +/doc/index.bml.docs.server.about=Todo lo que necesitas saber para instalar, administrar y trastear una configuración de LiveJournal + +/doc/index.bml.docs.server.title=Manual del servidor de LiveJournal + +/doc/index.bml.docs.tour.about=Diseñado para que nuevos visitas puedan familiarizarse con el sitio + +/doc/index.bml.docs.tour.title=Guía + +/doc/index.bml.title=Documentación + +/doc/index.bml.volunteering.about=Si te gustaría ayudar con la documentación de LiveJournal, mira los siguientes foros: + +/doc/index.bml.volunteering.header=Prestando ayuda voluntaria + +/doc/index.bml.volunteering.ljsysdoc=Debates acerca del sistema de documentación de LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=Debates sobre documentación para el usuario + +/doc/tour/index.bml.clients.caption<< +Los programas clientes de LiveJournal son pequeños programas que se ejecutan en tu computadora, permitiéndote actualizar tu diario en cualquier momento que te encuentres conectado a internet sin necesidad de abrir tu navegador. +Estos programas están disponibles para practicamente cualquier sistema operativo y mucho se pueden personalizar fácilmente. +. + +/doc/tour/index.bml.clients.title=Programas cliente + +/doc/tour/index.bml.comms.caption=LiveJournal es una gran comunidad interactiva, por lo que no es de sorprender que hayan muchos miembros con intereses similares. En respuesta a esto ofrecemos la posibilidad de crear comunidades, o diarios en los que varias personas pueden escribir. + +/doc/tour/index.bml.comms.title=Comunidades + +/doc/tour/index.bml.create.caption=LiveJournal es una comunidad de diarios basado en membresía. Esta página explica lo que conlleva una membresía, porqué es importante y los beneficios que aporta. También incluye un formulario para crear tu propia cuenta. + +/doc/tour/index.bml.create.title=Creando una cuenta + +/doc/tour/index.bml.friends.caption<< +También puedes hacer un seguimiento de tus amigos mediante LiveJournal usando la función integrada de "amigos". +Si encuentras un diario que consideras interesante, agrégalo a tu lista de amigos, que te permitirá leer todas las entradas de tus amigos en una misma página. +. + +/doc/tour/index.bml.friends.title=Amigos + +/doc/tour/index.bml.intro.caption<< +Esta guía se ha diseñado para que nuevos visitantes puedan familiarizarse con el sitio. +Te mostrará donde se encuentran los apartados más importantes, además de algunas de las funciones más interesantes. +. + +/doc/tour/index.bml.intro.title=Bienvenid@ + +/doc/tour/index.bml.modify.caption=También es posible dar formato a tu diario de varias formas, usando estilos predefinidos y esquemas de colores. ¡Haz que tu diario sea único de la forma que quieras! + +/doc/tour/index.bml.modify.title=Personalización + +/doc/tour/index.bml.nav.next=Siguiente --> + +/doc/tour/index.bml.nav.prev=<-- Anterior + +/doc/tour/index.bml.profile.caption=LiveJournal invita a sus miembros a añadir información sobre ellos en su perfil para que saber un poco más acerca de quien utiliza el sitio y como podemos servirlos mejor. Sin embargo esta información no es un requisito — la única información requerida para empezar a utilizar LiveJournal es un nombre, dirección de correo electrónico y una contraseña. + +/doc/tour/index.bml.profile.title=Perfiles + +/doc/tour/index.bml.sitemap.caption<< +Esperamos que esta guía te haya proporcionado información útil sobre el sitio y servicio de LiveJournal. +Si requieres ayuda sobre cualquier tema relacionado con LiveJournal, no dudes en contactar con nuestro departamento de soporte. Si quieres explorar el sitio con mayor detalle, por favor visita el mapa del sitio para ver un listado de todas las páginas en el sitio. +. + +/doc/tour/index.bml.sitemap.title=Mapa del sitio + +/doc/tour/index.bml.support.caption=La página de soporte lista zonas que ayudan a explicar lo que es LiveJournal, preguntas frecuentes sobre el sitio y más información útil sobre el servicio, la empresa y su gran comunidad. + +/doc/tour/index.bml.support.title=Obteniendo ayuda + +/doc/tour/index.bml.title=Guía - [[title]] + +/doc/tour/index.bml.update.caption=La actualización de diarios es el núcleo del servicio de LiveJournal; aquí ofrecemos la oportunidad a nuestros miembros de compartir sus vidas y lo que pasa por sus mentes. Actualizar un diario es sencillo. Simplemente escribe una entrada en el campo proporcionado y pulsa el botón "Actualizar diario". Por supuesto, ofrecemos opciones más avanzadas en nuestra página de actualización, como la opción de comprobar la ortografía de la entrada (actualmente sólo en inglés) y la de proporcionar información adicional sobre tus entradas, como la música que estás escuchando y tu estado de ánimo actualmente. + +/doc/tour/index.bml.update.title=Actualizando + +/editinfo.bml.allowshowcontact.about=Deberías dejar esta opción activada. Esto mostrará en LiveJournal tu dirección electrónica, número ICQ y alias de mensajería AOL, para que otras personas puedan ponerse en contacto contigo. + +/editinfo.bml.allowshowcontact.email=En caso de ser visible, se mostrará la dirección: + +/editinfo.bml.allowshowcontact.email.actual_only=Sólo dirección real + +/editinfo.bml.allowshowcontact.email.both=Ambas (real + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Sólo dirección LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=No mostrar ninguna dirección. + +/editinfo.bml.allowshowcontact.email.no_show=No mostrar dirección electrónica + +/editinfo.bml.allowshowcontact.email.show=Mostrar dirección electrónica + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Con la opción arriba, puedes también optar por ocultar tu dirección de correo electrónico (aún mostrando el resto de información de contacto), sólo mostrar tu dirección de LiveJournal (sólo cuentas pagadas), sólo mostrar tu dirección real o mostrar ambos. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Con la opción arriba, puedes también optar por ocultar tu dirección de correo electrónico (aún mostrando el resto de información de contacto). + +/editinfo.bml.allowshowcontact.title=¿Mostrar tu información de contacto en tu LiveJournal? + +/editinfo.bml.allowshowinfo.about=Activa esta opción si quieres que tu ciudad/estado/país y cumpleaños estén visibles para los demás usuarios. + +/editinfo.bml.allowshowinfo.title=¿Mostrar localidad y cumpleaños? + +/editinfo.bml.autotranslate.about<< +Esta opción se usa para informar a LiveJournal qué tipo de codificación se debe utilizar para las entradas y comentarios que escribiste antes de que el sitio se convirtió a Unicode. +Si escribes en inglés o español, debes escoger "Western European" [Europa Occidental] aquí. + +. + +/editinfo.bml.autotranslate.header=Convertir las entradas viejas automáticamente de: + +/editinfo.bml.bday.title=Cumpleaños + +/editinfo.bml.bday.year.opt=el año es opcional + +/editinfo.bml.bdayreminders.about=Si quieres recibir recordatorios por correo electrónico de los cumpleaños de tus amigos, marca esta casilla. + +/editinfo.bml.bdayreminders.header=Envíame recordatorios de cumpleaños (actualmente deshabilitado) + +/editinfo.bml.bio.about=Aquí puedes escribir un pequeño perfil de ti mismo. Esto se mostrará en tu página de información de usuario. + +/editinfo.bml.bio.header=Tu perfil + +/editinfo.bml.blockrobots.about<< +Si marcas esta opción, LiveJournal mandará a los robots y arañas que se vayan. +No todos los robots obedecen las reglas. +. + +/editinfo.bml.blockrobots.header=Bloquear robots/arañas para que no añadan tu diario a su base de datos + +/editinfo.bml.chat.aolim.title=Mensajería AOL + +/editinfo.bml.chat.icquin.title=Número ICQ + +/editinfo.bml.chat.msnusername.title=Usuario MSN + +/editinfo.bml.chat.yahooid.title=ID Yahoo! + +/editinfo.bml.city.title=Ciudad + +/editinfo.bml.country.choose=Escoge un país + +/editinfo.bml.country.title=País + +/editinfo.bml.email.title=Correo electrónico + +/editinfo.bml.enableboards.about=Marca esta casilla si quieres que los demás puedan responder a las entradas que escribes. + +/editinfo.bml.enableboards.header=Activar comentarios + +/editinfo.bml.encoding.about=No te preocupes por esto. En general, sólo los usuarios internacionales que escriben en varios idiomas tendrán que cambiar algo aquí. + +/editinfo.bml.encoding.header=Opciones de codificación + +/editinfo.bml.error.day.notinmonth=Ese día no es válido para ese mes. + +/editinfo.bml.error.day.outofrange=Cumpleaños erróneo. Escribe un día del 1 al 31. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +No puedes dar una dirección de @[[domain]]. +Escribe tu dirección real en ese campo. +Si tienes una cuenta pagada, tu dirección de [[username]]@[[domain]] se reenviará a tu dirección real. +Para escoger qué dirección se publicará (o que ambas se mostrarán), véase abajo la opción de "Mostrar tu información de contacto". +. + +/editinfo.bml.error.email.none=Debes proveer una dirección de correo electrónico + +/editinfo.bml.error.email.no_space<< +No se permiten espacios en la dirección electrónica. +Si usas AOL, recuerda que tu dirección electrónica de Internet es tu alias de mensajería sin los espacios, seguido por @aol.com. + +. + +/editinfo.bml.error.excessive_int<< +Lo sentimos, pero tu lista incluye demasiados intereses. El límite es de 150, pero tú incluiste [[intcount]]. Los cambios que hiciste a tu lista de intereses no se guardaron. Vuelve, acorta la lista, y después guárdala de nuevo. + +. + +/editinfo.bml.error.invalidbio<< +Tu perfil almacenado incluye caracteres inválidos. Tienes que visitar a la página de conversión para convertirlo a Unicode. + +. + +/editinfo.bml.error.invalidints=Tu lista de intereses almacenada incluye caracteres inválidos. Tienes que visitar a la página de conversión para convertirlo a Unicode. + +/editinfo.bml.error.invalidname=Tu nombre incluye caracteres inválidos. Tienes que visitar a la página de conversión/b> para convertirlo a Unicode. + +/editinfo.bml.error.locale.country_ne_state=Especificaste "Estados Unidos" como tu país, pero el estado que escribiste en el campo de "Otro estado" no es de EE UU. + +/editinfo.bml.error.locale.invalid_country=De alguna forma has escogido un país no válido. + +/editinfo.bml.error.locale.state_ne_country=El estado que escogiste es de EE UU, pero no especificaste Estados Unidos como país. + +/editinfo.bml.error.locale.zip_ne_state<< +Tu código ZIP no está en el estado que especificaste. +Corrige la información, o borra el campo de estado o de código ZIP (o ambos). +. + +/editinfo.bml.error.locale.zip_requires_us<< +Escribiste un código ZIP pero no escogiste Estados Unidos como país. +Sólo recogemos la información de códigos ZIP de los que viven en EE UU. +Por favor, regresa y borra el código ZIP o escoge Estados Unidos como país. + +. + +/editinfo.bml.error.month.outofrange=El es del cumpleaños no es válido. Escribe un mes del 1 al 12 (ene-dic). + +/editinfo.bml.error.noname=Tu nombre es un campo obligatorio. Debes proveer al menos tu nombre, apodo o algún identificativo. + +/editinfo.bml.error.tm.require.number=Si quieres usar el servicio de mensajes cortos, tienes que dar tu número de teléfono. + +/editinfo.bml.error.tm.require_provider<< +Si quieres usar el servicio de mensajes cortos, tienes que escoger tu servicio. + +Si el tuyo no está en la lista, por favor, comunícanos la información sobre el sistema de mensajes cortos de tu servicio para que podemos crear el soporte para él. +. + +/editinfo.bml.error.year.notenoughdigits=Año de nacimiento no válido. Escribe los cuatro dígitos del año. + +/editinfo.bml.error.year.outofrange=Año de nacimiento no válido. + +/editinfo.bml.finished.about=Después de terminar, pulsa el botón de "Guardar cambios" abajo: + +/editinfo.bml.finished.header=¿Terminaste? + +/editinfo.bml.finished.save_button=Guardar cambios + +/editinfo.bml.gender.title=Sexo + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Marca esta casilla si quieres recibir notificaciones por correo electrónico cuando alguien escribe un comentario en respuesta a una entrada de diaro tuya. + +/editinfo.bml.getreplies.header=Recibir las respuestas por correo electrónico + +/editinfo.bml.hidefriendof.about=Si marcas esta casilla, la lista de los que te incluyen en tu lista de amigos no aparece en tu página de perfil. + +/editinfo.bml.hidefriendof.header=Ocultar la lista de "Amigo de" + +/editinfo.bml.howhear.about<< +Sólo por curiosidad, ¿cómo descubriste [[sitename]]? +Si era de alguien en específico, danos su nombre de usuario; si era de otra fuente/artículo/enlace/sitio Web, danos la información apropiada. +. + +/editinfo.bml.howhear.header=Curiosidad + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Marca esta casilla si tu programa de correo electrónica soporta completamente los emails que contienen el HTML. +Muchos clientes intentan soportarlo, pero fracasan por completo. +Si no la marcas, LiveJournal sólo te enviará emails textuales. +. + +/editinfo.bml.htmlemail.header=Enviar correos en HTML + +/editinfo.bml.int.about<< +Si quieres que los demás puedan buscar en el directorio y encontrarte por tus intereses, haz abajo una lista de todo lo que te interesa, con una coma entre cada término. +Son mejores las frases cortas o de una sola palabra. Regla general: debes poder colocar el interés en la oración "Me gusta(n) ________". Para mantener la uniformidad de los sustantivos, escríbelos en forma plural y sin artículos. "Me gustan DVDs", no "Me gusta DVD". +. + +/editinfo.bml.int.ex.bad=Ejemplo MALO: Me gustan muchos grupos de rock y mirar pelis y hablar con los amigos e ir a las discotecas. Las cosas así se deben escribir arriba en tu perfil. + +/editinfo.bml.int.ex.good=Ejemplo BUENO: ciclismo, esquiar, computadoras, dvds, mp3s, queso, mujeres + +/editinfo.bml.int.header=Intereses + +/editinfo.bml.login.enterinfo=Escribe tu nombre de usuario y contraseña para modificar tu información personal. + +/editinfo.bml.login.forgot.header=¿Has olvidado algo? + +/editinfo.bml.login.forgot.recover=Si has olvidado tu nombre de usuario o contraseña, ¡puedes recuperarlo aquí!. + +/editinfo.bml.logip.always=Siempre + +/editinfo.bml.logip.anon_only=Sólo para comentarios anónimos + +/editinfo.bml.logip.header=¿Grabar la dirección IP de quién responda? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Si temes que los «spam-robots» puedan encontrar tu dirección electrónica en LiveJournal, escoge esta opción y tu dirección se modificará para que no la encuentren los robots que recogen direcciones electrónicas. + +/editinfo.bml.mangleaddress.header=Alterar la dirección electrónica que se muestra + +/editinfo.bml.name.title=Nombre + +/editinfo.bml.newemail.subject=Dirección de correo electrónico cambiado + +/editinfo.bml.numcomments.about=Marca esta casilla si quieres añadir la cantidad de comentarios a los URLs para que tu navegador muestre los enlaces en otro color (si soporta la opción). + +/editinfo.bml.numcomments.header=Añadir &nc=xx a los URL de los comentarios + +/editinfo.bml.optional=Opcional + +/editinfo.bml.opt_in.about=Si quieres ser informado cuando creamos alguna opción nueva e interesante para LiveJournal, marca esta casilla. Los emails que recibirás serán bastante infrecuentes, por lo general una o dos veces por mes como máximo. Tu dirección electrónica no será visible para los demás usuarios, y puedes desactivar esta opción en cualquier momento. + +/editinfo.bml.opt_in.header=Envíame las noticias de LiveJournal + +/editinfo.bml.persinfo.disclaimer=Llena aquí alguna información básica sobre ti, por curiosidad nuestra y para fines estadísticos. No vamos a hacer nada con esta información que sea malicioso ni molestante, sólo nos interesa quiénes son nuestros usuarios y dónde están. Por favor, llénalo con la información correcta. Si esto te preocupa, lee nuestra política sobre la privacidad. + +/editinfo.bml.persinfo.header=Información personal + +/editinfo.bml.screen.all=Todas + +/editinfo.bml.screen.anon=Anónimas + +/editinfo.bml.screen.header=¿Cuáles respuestas quieres filtradas por defecto? + +/editinfo.bml.screen.none=Ninguna + +/editinfo.bml.screen.nonfriends=De no amigos + +/editinfo.bml.screen.nonmembers=De no miembros + +/editinfo.bml.security.header=¿Quién puede ver tu información de contacto? + +/editinfo.bml.security.visibility.anybody=Cualquiera + +/editinfo.bml.security.visibility.everybody=Todo el mundo + +/editinfo.bml.security.visibility.friends=Sólo amigos + +/editinfo.bml.security.visibility.regusers=Usuarios registrados + +/editinfo.bml.settings.friendspage.title=Título de página de amigos + +/editinfo.bml.settings.friendspage.title.optional=Puedes optar por escribir un título para tu página de amigos (no se permite HTML). + +/editinfo.bml.settings.header=Opciones de LiveJournal + +/editinfo.bml.settings.journal.subtitle=Subtítulo de diario: + +/editinfo.bml.settings.journal.subtitle.optional=Puedes optar por escribir un subtítulo para tu diario (no se permite HTML). + +/editinfo.bml.settings.journal.title=Título de diario: + +/editinfo.bml.settings.privacy.about=Elige abajo las opciones de privacidad y preferencias. + +/editinfo.bml.settings.privacy.header=Opciones de privacidad + +/editinfo.bml.state.other=O escribe otro país/provincia/territorio + +/editinfo.bml.state.title=Estado + +/editinfo.bml.state.us=Estados de EE UU + +/editinfo.bml.stylemine.header=¿Ver las páginas de comentario en el mismo estilo utilizado por tu diario? + +/editinfo.bml.success.header=¡Hecho! + +/editinfo.bml.success.message=Se han actualizado tu información y la configuración de tu diario y de tu perfil. + +/editinfo.bml.switch.button=Cambiar + +/editinfo.bml.switch.header=Cambiar diario + +/editinfo.bml.switch.workwith=Modificar diario: + +/editinfo.bml.title=Modificar información personal + +/editinfo.bml.tm.details=detalles + +/editinfo.bml.tm.phonenum=Número completo de teléfono: + +/editinfo.bml.tm.sec.about=Activar el servicio de mensajes cortos de otros usuarios. + +/editinfo.bml.tm.sec.title=Nivel de seguridad: + +/editinfo.bml.tm.servprov=Proveedor de servicio + +/editinfo.bml.tm.title=Servicio de mensajes cortos + +/editinfo.bml.translatemailto.about=Si eliges recibir las respuestas a tus entradas por correo electrónico, y tu cliente de correo electrónico no soporta muy bien los mensajes en Unicode (UTF-8), utiliza esta opción para especificar otro sistema de codificación al cual LiveJournal traducirá automáticamente el texto de los comentarios que te enviamos. + +/editinfo.bml.translatemailto.header=Traducir los emails a: + +/editinfo.bml.unbanusers.about=Has prohibido que los siguientes usuarios escriban comentarios en tu diario. Marca la casilla al lado de su nombre de usuario para retirar esa prohibición. + +/editinfo.bml.unbanusers.header=Retirar prohibición de usuarios + +/editinfo.bml.userpic.about=Abajo está la imagen pequeña que has cargado para representarte en todas partes del sitio de LiveJournal y en tu diario y los de tus amigos. + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Para borrar esta imagen o cargar otra, haz clic aquí. + +/editinfo.bml.userpic.header=Tu imagen + +/editinfo.bml.userpic.none=no se ha cargado ninguna imagen + +/editinfo.bml.weblogscom.about=Marca esta opción si te gustaría que Weblogs.com listase tu diario cuando publiques nuevas entradas. + +/editinfo.bml.weblogscom.header=Notificar a Weblogs.com sobre actualizaciones + +/editinfo.bml.webpagename.title=Nombre de tu página Web + +/editinfo.bml.webpageurl.title=URL de tu página Web + +/editinfo.bml.whoreply.header=¿Quién puede responder a tus entradas? + +/editinfo.bml.zip.title=Código ZIP + +/editinfo.bml.zip.usonly=Código ZIP de 5 números; sólo para residentes de EE UU + +/editjournal.bml.btn.proceed=Adelante... + +/editjournal.bml.certainday=Día concreto: + +/editjournal.bml.recententries=entradas más recientes + +/editjournal.bml.recententry=Entrada más reciente + +/editjournal.bml.title=Modificar entradas de tu diario + +/editjournal.bml.viewwhat=Entradas a ver: + +/editjournal_do.bml.body=Modifica los campos de tu entrada que quieres modificar y pulsa el botón de "Guardar" al pie de la página. Como alternativa, puedes pulsar el botón de "Borrar" para borrar la entrada. + +/editjournal_do.bml.btn.delete=Borrar entrada + +/editjournal_do.bml.btn.edit=Modificar entrada elegida + +/editjournal_do.bml.btn.save=Guardar Entrada + +/editjournal_do.bml.continue.head=Pulsa para continuar... + +/editjournal_do.bml.continue.text=Tras elegir un elemento para modificar o borrar, pulsa el botón "Modificar" abajo. + +/editjournal_do.bml.currmood=Estado de ánimo actual: + +/editjournal_do.bml.currmusic=Música actual: + +/editjournal_do.bml.date=Fecha: + +/editjournal_do.bml.default=por defecto + +/editjournal_do.bml.delete.confirm=¿Estás seguro de que quieres borrar esta entrada? + +/editjournal_do.bml.edit.text=Esta es la entrada de diario que escogiste para modificar. Modifica los campos de tu entrada que quieres cambiar y pulsa el botón de "Guardar entrada" al final de la página.

      Para borrar la entrada, borra todo el texto en el campo de texto y pulsa el botón de "Guardar entrada" al final de la página. + +/editjournal_do.bml.error.getting=Ocurrió un error al llamar las entradas de tu diario para modificarlas: + +/editjournal_do.bml.error.modify=Un error ocurrió modificando tu diario: + +/editjournal_do.bml.error.nofind=No se pudo encontrar la entrada elegida. + +/editjournal_do.bml.event=Evento: + +/editjournal_do.bml.localtime=Hora local: + +/editjournal_do.bml.noneother=Ninguno u otro: + +/editjournal_do.bml.opt.backdate=Guardar con fecha anterior: + +/editjournal_do.bml.opt.backdate.about=no se mostrará en la vista de amigos + +/editjournal_do.bml.opt.nocomments=No permitir comentarios: + +/editjournal_do.bml.opt.noemail=No enviar avisos por correo: + +/editjournal_do.bml.opt.noformat=No dar formato automáticamente: + +/editjournal_do.bml.other=Otro: + +/editjournal_do.bml.pickentry.head=Elige una entrada para modificarla + +/editjournal_do.bml.pickentry.text=Elige el elemento que deseas modificar y pulsa el botón de modificar al final de la página. + +/editjournal_do.bml.picture=Imagen a utilizar: + +/editjournal_do.bml.save.head=Pulsa para guardar... + +/editjournal_do.bml.save.text=Cuando hayas terminado de modificar tu entrada, pulsa Guardar. + +/editjournal_do.bml.subject=Asunto: (opcional) + +/editjournal_do.bml.success.delete=La entrada fue borrada de tu diario. + +/editjournal_do.bml.success.edit=La entrada fue modificada. Puedes verla aquí. + +/editjournal_do.bml.success.head=Hecho + +/editjournal_do.bml.timeformat=Formato 24 horas + +/editjournal_do.bml.title=Modificar entradas de tu diario + +/editpics.bml.btn.proceed=Seguir + +/editpics.bml.btn.save=Guardar opciones + +/editpics.bml.curpics=Imágenes actuales + +/editpics.bml.error.badurl=La dirección para la imagen que quieres cargar no parece correcta. Debe empezar con http:// + +/editpics.bml.error.filetoolarge=La imagen que intentaste cargar es demasiado grande. El archivo no puede sobrepasar un tamaño de [[maxsize]]. + +/editpics.bml.error.invalidimage=Archivo de imagen inválido. + +/editpics.bml.error.toomanypics2=Ya has cargado el máximo de [[maxpics]] imágenes. No puedes cargar esta imagen hasta que borres una de las ya existentes. + +/editpics.bml.fromfile=de Archivo: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=a + +/editpics.bml.fromurl=De URL: + +/editpics.bml.makedefault=Esta imagen debe ser la que se muestra por defecto. + +/editpics.bml.restriction.fileformat=El formato de archivo tiene que ser PNG, GIF o JPG + +/editpics.bml.restriction.filesize=El tamaño máximo del archivo es de 40k + +/editpics.bml.uploadheader=Cargar nueva imagen + +/export.bml.btn.proceed=Adelante... + +/export.bml.description|staleness=1 +/export.bml.description=Esta función te permite descargar tu diario completo a un formato personalizado para propósitos de copia de seguridad. + +/export.bml.fields=Campos: + +/export.bml.format.csv=CSV (Valores Separados por Comas) + +/export.bml.label.encoding=Codificación: + +/export.bml.label.field.allowmask=Permitir máscara + +/export.bml.label.field.currents=Estado de ánimo y música actual + +/export.bml.label.field.event=Evento + +/export.bml.label.field.eventtime=Hora del evento (según hora del usuario) + +/export.bml.label.field.itemid=Número de identificación + +/export.bml.label.field.logtime=Hora de registro (según hora del sistema) + +/export.bml.label.field.security=Nivel de seguridad + +/export.bml.label.field.subject=Asunto + +/export.bml.label.format=Formato: + +/export.bml.label.header=Encabezado + +/export.bml.label.month=Elige un mes: + +/export.bml.label.month.year=aaaa: + +/export.bml.label.notranslation=No traducir entre codificaciones + +/export.bml.label.what=Qué exportar: + +/export.bml.title=Exportar diario + +/export.bml.what.entries=Entradas de diario + +/friends/add.bml.add.header=Hecho + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=El usuario fue añadido a tu lista de amigos. Puedes ver tu página de amigos aquí. + +/friends/add.bml.add.title=¡Amigo añadido! + +/friends/add.bml.btn.add=Añadir [[user]] + +/friends/add.bml.btn.modify=Modificar + +/friends/add.bml.btn.remove=Borrar + +/friends/add.bml.colors.bg=Fondo + +/friends/add.bml.colors.fg=Primer plano + +/friends/add.bml.colors.header=Colores + +/friends/add.bml.colors.hover=(Coloca tu puntero sobre un color para ver su nombre) + +/friends/add.bml.colors.text=También puedes elegir de forma opcional los colores que representarán a [[user]] en tu lista de amigos. + +/friends/add.bml.confirm.header=¿Añadir a [[user]] como amigo? + +/friends/add.bml.confirm.text=Para añadir a [[user]] a tu lista de amigos, pulsa el botón abajo. + +/friends/add.bml.confirm.title=Añadir amigo + +/friends/add.bml.error1.header=Primero inicia la sesión + +/friends/add.bml.error1.text=Para añadir un usuario a tu lista de amigos primero debes iniciar tu sesión. Si no tienes todavía una cuenta puedes crear una para seguir los diarios de tus amigos. + +/friends/add.bml.error1.title=Añadir amigo + +/friends/add.bml.error2.text=El nombre de usuario proporcionado es inválido o no existe. Para añadir un amigo, ve a la página de modificar amigos. + +/friends/add.bml.error3.text=[[user]] ya figura en tu lista de amigos. Sin embargo, puedes modificar los colores que elegiste para representarle. + +/friends/add.bml.error3.title=Modificar amigo + +/friends/add.bml.groups.header=Grupos de amigos + +/friends/add.bml.groups.nogroup=No tienes creado ningún grupo de amigos. + +/friends/add.bml.groups.text=¿En qué grupo de amigos quieres colocar a este usuario? Los grupos de amigos se utilizan para filtrar la vista de tu lista de amigos, y también para la seguridad de visualización de entradas basados en estos grupos. + +/friends/add.bml.remove.header=Hecho + +/friends/add.bml.remove.text=El usuario fue borrado de tu lista de amigos. Puedes ver tu página de amigos aquí. + +/friends/add.bml.remove.title=¡Amigo borrado! + +/friends/edit.bml.title=Modificar amigos + +/friends/editgroups.bml.btn.ge.del=Borrar + +/friends/editgroups.bml.btn.ge.new=Nuevo + +/friends/editgroups.bml.btn.ge.ren=Cambiar nombre + +/friends/editgroups.bml.btn.gs.private=Privado + +/friends/editgroups.bml.btn.gs.public=Público + +/friends/editgroups.bml.btn.mv.down=Desplazar abajo + +/friends/editgroups.bml.btn.mv.up=Desplazar arriba + +/friends/editgroups.bml.confirm.delete=¿Estás seguro de querer borrar este grupo de amigos personalizado? + +/friends/editgroups.bml.done.btn=Guardar cambios + +/friends/editgroups.bml.done.header=¿Terminaste? + +/friends/editgroups.bml.done.text=Cuando hayas terminado, pulsa el botón siguiente para guardar los cambios. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Has llegado al límite máximo de 30 grupos de amigos personalizados. Si has borrado uno o más grupos pero no has guardado todavía los cambios, hazlo ahora, luego vuelve a esta página y refréscalo. Podrás crear entonces nuevos grupos de amigos personalizados. + +/friends/editgroups.bml.error.text=El servidor devolvió el siguiente mensaje de error: + +/friends/editgroups.bml.group.public=(público) + +/friends/editgroups.bml.ingroup=Dentro del grupo: + +/friends/editgroups.bml.ingroup.not=Fuera del grupo: + +/friends/editgroups.bml.prompt.newname=Escribe el nombre para el nuevo grupo de amigos personalizado: + +/friends/editgroups.bml.prompt.rename=Cambiar el nombre de este grupo de amigos personalizado a: + +/friends/editgroups.bml.saved.header=Guardado + +/friends/editgroups.bml.saved.text=Tus grupos de amigos personalizados han sido guardados. + +/friends/editgroups.bml.text|staleness=1 +/friends/editgroups.bml.text<< +Esta página te permite modificar tus grupos de amigos personalizados. Estos grupos se usan para fijar la seguridad de ciertos elementos y filtrar tu página de amigos. +Esta página requiere JavaScript para funcionar. +. + +/friends/editgroups.bml.text.sec=Nota de seguridad: Si deseas borrar un grupo y crear uno nuevo, no lo hagas renombrando un grupo y modificándolo. Si haces esto, todas tus antiguas entradas que eran accesibles a los componentes del antiguo grupo serán accesibles para los nuevos componentes. + +/friends/editgroups.bml.title=Modificar grupos de amigos personalizados + +/friends/editgroups.bml.yourgroups=Tus grupos de amigos personalizados: + +/friends/edit_do.bml.addfriends.head=Añadir amigos + +/friends/edit_do.bml.addfriends.text=Escribe los nombres de usuario de tus amigos de LiveJournal + +/friends/edit_do.bml.background=Fondo + +/friends/edit_do.bml.bgcolor=Color de fondo: + +/friends/edit_do.bml.btn.close=Cerrar + +/friends/edit_do.bml.btn.save=Guardar cambios + +/friends/edit_do.bml.btn.toggle=Activar ventana de vista previa + +/friends/edit_do.bml.done.head=¿Has terminado? + +/friends/edit_do.bml.done.text=Cuando hayas terminado, pulsa el botón "Guardar cambios" abajo... + +/friends/edit_do.bml.error.updating=Ocurrió un error al actualizar tu lista de amigos: + +/friends/edit_do.bml.fellowfriends.head=Coamigos + +/friends/edit_do.bml.fellowfriends.text=Las siguientes personas te han listado como su amigo... Tal vez quieras listarlos como amigos también. Más que nada, esto se proporciona como referencia para que conozcas sus nombres de usuario de LiveJournal también. No estás obligado a añadirlos a tu lista de amigos. + +/friends/edit_do.bml.foreground=Primer plano + +/friends/edit_do.bml.friend=Amigo + +/friends/edit_do.bml.hover=Coloca tu puntero sobre un color para ver su nombre + +/friends/edit_do.bml.mrcolor=El Sr. Vista Previa de Colores + +/friends/edit_do.bml.name=Nombre + +/friends/edit_do.bml.needmore=Si necesitas añadir más amigos que los permitidos por este formulario, guarda abajo los cambios y luego regresa a esta página para añadir más. + +/friends/edit_do.bml.nofriends.head=¿No tienes amigos? + +/friends/edit_do.bml.nofriends.text=Actualmente no tienes definido ningún amigo. Sin embargo, ¡seguro que tienes alguno que otro! :) Simplemente coloca abajo sus nombres de usuario de LiveJournal.... + +/friends/edit_do.bml.opt.addtolist=Añadir amigo + +/friends/edit_do.bml.opt.delete=¿Borrar? + +/friends/edit_do.bml.success.head=Hecho + +/friends/edit_do.bml.success.text=Tu lista de amigos se ha actualizado. Puedes ver tu página de amigos actualizada aquí. + +/friends/edit_do.bml.textcolor=Color de texto: + +/friends/edit_do.bml.title=Modificar amigos + +/friends/edit_do.bml.user=Usuario + +/friends/edit_do.bml.viewer=Vista previa de colores + +/friends/edit_do.bml.yourfriends.head=Tus amigos + +/friends/edit_do.bml.yourfriends.text=Tienes definidos los siguientes amigos actualmente: + +/friends/index.bml.title=Herramientas de amigos + +/friends/popwithfriends.bml.account_type=Lo sentimos, el tipo de cuenta que tienes no te permite utilizar esta herramienta. + +/friends/popwithfriends.bml.count=Recuento + +/friends/popwithfriends.bml.no_users=Ningún usuario + +/friends/popwithfriends.bml.user=Usuario + +/index.bml.boldcreate=¡Crea tu propio LiveJournal! + +/index.bml.frank.image.alt=La Cabra Frank, la mascota de LiveJournal. + +/index.bml.frank.logo=—Beeee —dice Frank. + +/index.bml.meta.desc=LiveJournal.com es un lugar donde puede compartir tus pensamientos con todo el mundo. + +/index.bml.meta.keywords=diary, journal, online journal, diaries, writing, online diary, web diary, diario, diario en Internet, diario de Web, escritura + +/interests.bml.add.added.head=¡Añadido! + +/interests.bml.add.added.text=El interés se ha añadido a tu lista. + +/interests.bml.add.btn.text=Añadir [[interest]] + +/interests.bml.add.confirm.head=Confirmar + +/interests.bml.add.confirm.text=Para añadir [[interest]] a tu lista de intereses, haz clic en el botón abajo. + +/interests.bml.add.toomany.head=Disculpa... + +/interests.bml.add.toomany.text=Ya has definido [[maxinterests]]. + +/interests.bml.addint=Si esto te interesa también a ti y quisieras apuntarte a esta lista, haz clic aquí. + +/interests.bml.btn.switch=Cambiar + +/interests.bml.communities.head=Comunidades pertinentes + +/interests.bml.communities.text=A las siguientes comunidades también les interesa(n) "[[interest]]". + +/interests.bml.count=Cantidad + +/interests.bml.enmasse.body.other=Abajo se muestran los intereses de [[user]]. Marca las casillas de los intereses que quieras añadir a tu lista de intereses y borra las casillas de los intereses que quieras eliminar de tu lista de intereses. Cuando terminas, pulsa "Guardar Cambios". + +/interests.bml.enmasse.body.other_authas=Abajo se muestran los intereses de [[user]]. Marca las casillas de los intereses que quieras añadir a la lista de intereses de [[target]] y borra las casillas de los intereses que quieras eliminar. Cuando terminas, pulsa "Guardar Cambios". + +/interests.bml.enmasse.body.you<< +Borra las casillas de los intereses que quieras eliminar. +Cuando terminas, pulsa "Guardar cambios". +. + +/interests.bml.enmasse.btn=Mostrar lista + +/interests.bml.enmasse.header=Añadir/eliminar intereses + +/interests.bml.enmasse.intro=Modificar tus intereses según los de: + +/interests.bml.error.add.mustlogin=Hay que tener sesión iniciada para añadir un interés de este modo. + +/interests.bml.error.enmasse.mustlogin=Tienes que iniciar sesión para utilizar esta opción. + +/interests.bml.error.enmasse.noaccess=Parece que no tienes acceso al diario [[user]]. + +/interests.bml.error.findsim_do.intnotfound=No se encontró ese interés. + +/interests.bml.error.nointerests=El usuario escogido no existe o no ha especificado ningún interés. + +/interests.bml.findsim.searchwait=Fíjate: La búsqueda demorará varios segundos. Ten paciencia. + +/interests.bml.findsim_do.account.notallowed=Lo sentimos, pero el tipo de cuenta que tienes no te permite utilizar esta herramienta. + +/interests.bml.findsim_do.magic=Ãndice
      Mágico + +/interests.bml.findsim_do.magic.head=¿Ãndice mágico? + +/interests.bml.findsim_do.magic.text=Cada usuario correspondente recibe un "índice mágico" calculado, el cual es una evaluación sujetiva de dos factores: la cantidad bruta de intereses iguales, y algunos puntos extras por compartir intereses poco comunes. + +/interests.bml.findsim_do.nomatch.head=Sin correspondencias + +/interests.bml.findsim_do.nomatch.text=Ningún usuario es semejante a [[user]]. + +/interests.bml.findsim_do.notdefined=El usuario [[user]] no ha definido ningún interés. + +/interests.bml.findsim_do.similar.head=Usuarios semejantes + +/interests.bml.findsim_do.similar.text=Los siguientes son los usuarios que más se parecen a [[user]] + +/interests.bml.finished.about=Después de terminar, pulsa el botón de "Guardar Cambios" abajo: + +/interests.bml.finished.header=¿Terminado? + +/interests.bml.finished.save_button=Guardar cambios + +/interests.bml.interest=Interés + +/interests.bml.interested.btn.find=Buscar + +/interests.bml.interested.in=Buscar personas y comunidades a quienes les interesa(n): + +/interests.bml.interests.head=Intereses + +/interests.bml.interests.text=Aquí tienes algunas cosas entretenidas que puedes hacer con los intereses. + +/interests.bml.interests.viewpop=Ver los intereses populares + +/interests.bml.login.enterinfo=Ingresa tu nombre de usuario y contraseña para modificar tus intereses. + +/interests.bml.login.proceed=Seguir... + +/interests.bml.match=[[count]] corresponden: + +/interests.bml.matches=[[count]] correspondencias: + +/interests.bml.morestuff=Se puede encontrar más cosas entretenidas en la página de intereses. + +/interests.bml.nointerests.text=¿No tienes listado ningún interés? Puedes añadir alguno(s) si vas a la página de Modificar información y configuración personales. + +/interests.bml.popular.head=Intereses populares + +/interests.bml.popular.text=Los siguientes intereses son los más populares. + +/interests.bml.results.goback=Tal vez quieres volver al perfil de [[user]], que estabas viendo anteriormente. + +/interests.bml.title=Intereses + +/interests.bml.toomany.body=Hay [[intcount]] personas y comunidades que listan esto como interés. No se mostrará la lista. + +/interests.bml.toomany.head=Muchas correspondencias + +/interests.bml.users.head=Usuarios con este interés + +/interests.bml.users.text=A los siguientes usuarios les interesa(n) [[interest]]. + +/legal/index.bml.about<< +LiveJournal se compromete a ofrecerles a sus miembros una experiencia estable y significativo, sean cuales sean los antecedentes u orígenes nacionales de esos miembros. Por lo tanto, hemos establecido unas pocas reglas para proporcionársela. +Nuestros documentos contienen provisiones e información razonables con respecto a cómo hacemos todo lo posible para servirte y cómo exigimos que los miembros se porten con nosotros y entre sí. LiveJournal funciona mejor cuando la gente cumple con estas reglas. Aquí tienes las más importantes para recordar: : +
        +
      • No acoses, maltrates ni amenaces a otras personas.
      • +
      • No lastimes de ninguna manera a los menores de edad.
      • +
      • No escribas mensajes repetitivos en el sitio Web ni en ninguna cuenta en él.
      • +
      • No escribas contenid que está protegido por los derechos de autores sin tener el permiso del autor.
      • +
      • No infrinjas la privacidad de otras personas.
      • +
      • No infrinjas de ningún modo las leyes de los EE UU ni las leyes de tu localidad.
      • +
      +La lista completa de las reglas y políticas se encuentra abajo: +. + +/legal/index.bml.about.header=Resumen + +/legal/index.bml.docs.coppa.about=La Ley para la Protección de la Privacidad de los Niños en Internet (COPPA, por sus siglas en inglés) reglamenta el uso y recogida en línea de información personal de o sobre los niños que tienen menos de trece años. Nuestra página de COPPA explica nuestra postura respecto a esta ley y resume la manera en que se tratarán las cuestiones de COPPA. + +/legal/index.bml.docs.header=Documentos + +/legal/index.bml.docs.privacy.about=La Política sobre la Privacidad resume cuál información recogemos de nuestros miembros y explica cómo utilizamos tal información. + +/legal/index.bml.docs.tos.about=La página de Condiciones de servicio resume nuestras políticas de uso y también las condiciones generales para la membresía. La membresía y/o el uso del sistema constituye un acuerdo que vas a cumplir con estas condiciones y cualquier otra sobre que hay un acuerdo. + +/legal/index.bml.title=Información legal + +/legal/privacy.bml.title=Política sobre la privacidad + +/legal/tos.bml.title=Condiciones de servicio + +/login.bml.bindip.label=Vincular a dirección IP: + +/login.bml.bindip.no=No (funciona con todos los ISP) + +/login.bml.bindip.yes=Sí (más seguro) + +/login.bml.error.mustenterusername=Debes escribir un nombre de usuario. + +/login.bml.expire.btn.neverexpire=Cambiar modo de caducidad a NUNCA + +/login.bml.expire.btn.sessiononly=Cambiar modo de caducidad a SESIÓN ÚNICA + +/login.bml.expire.neverexpire.text=Tu sesión nunca caducará, con lo que si estás conectado en un terminal de internet público, una escuela, biblioteca u otro lugar donde otras personas puedan utilizar dentro de poco esta computadora, ¡asegúrate de cerrar tu sesión cuando hayas acabado! O puedes cambiar tu modo de sesión para que caduque en el momento que cierres tu navegador: + +/login.bml.expire.sessiononly.text=Tu sesión caducará tras cerrar tu navegador. Si esta es tu propia computadora y eres el único usuario, puede que prefieras cambiar la caducidad de tu sesión de tal forma que nunca caduque: + +/login.bml.links.head=Enlaces + +/login.bml.links.link1=Tu página de amigos. + +/login.bml.links.link2=Tu lista de quehaceres. + +/login.bml.links.text=Más adelante esta página contendrá todo tipo de enlaces e información de interés, pero por ahora aquí tienes algunos sitios que puedes querer visitar: + +/login.bml.loggedin.head=¡Sesión iniciada! + +/login.bml.loggedin.text=Tu sesión se ha iniciado. + +/login.bml.login.btn.changeopts=Cambiar opciones + +/login.bml.login.btn.login=Iniciar sesión... + +/login.bml.login.expiration=Caducidad: + +/login.bml.login.forget=¿Olvidada? + +/login.bml.login.head=Iniciar sesión + +/login.bml.login.never=Nunca + +/login.bml.login.otheropts=Otras opciones: + +/login.bml.login.password=Contraseña: + +/login.bml.login.text1=Para iniciar tu sesión con [[sitename]], escribe tu nombre de usuario a contraseña abajo. Nuevos usuarios: Para crear una cuenta ve aquí. + +/login.bml.login.text2<< +También puedes especificar cuándo caducará tu sesión. Por defecto caducará cuando cierres tu navegador, que es la mejor opción cuando utilizas computadoras públicas. Sin embargo, si eres la única persona que utiliza tu computadora y nadie más tiene acceso a ella, puedes optar por mantener tu sesión siempre abierta. Para más información acerca de esta opción y otras relacionadas, accede a ¿Cuáles son las opciones cuando inicio sesión? + +. + +/login.bml.login.username=Nombre de usuario: + +/login.bml.login.whenbrowsercloses=Cuando cierra el navegador + +/login.bml.logout.btn=Cerrar Sesión + +/login.bml.title=Iniciar sesión + +/login.bml.whylogin.benefit1=No tendrás que escribir más tu nombre de usuario/contraseña en ninguna parte del sitio web. + +/login.bml.whylogin.benefit2=Podrás ver entradas "protegidas" de los diarios de tus amigos que te den acceso para leerlas. + +/login.bml.whylogin.benefit3=Muchas funciones sólo son visibles o accesibles cuando tienes iniciada tu sesión. + +/login.bml.whylogin.head=¿Por qué querría iniciar sesión? + +/login.bml.whylogin.text=Aquí tienes algunas de las principales ventajas de iniciar tu sesión: + +/logout.bml.already.head=Sesión ya cerrada + +/logout.bml.already.text=Ya has cerrado la sesión. + +/logout.bml.killall.btn=Caducar todas mis sesiones + +/logout.bml.killall.head=Otras sesiones + +/logout.bml.killall.text=Tienes otras sesiones activas desde otros ordenadores. ¿Quieres caducar todas tus sesiones además de esta? + +/logout.bml.loggedout.already=No tienes ninguna sesión abierta. + +/logout.bml.loggedout.head=Sesión cerrada + +/logout.bml.loggedout.killedall=Todas tus sesiones han caducado. + +/logout.bml.loggedout.success=Sesión cerrada. + +/logout.bml.loggedout.text=Tu sesión se ha cerrado. + +/logout.bml.logout.btn=Cerrar sesión + +/logout.bml.logout.head=¿Cerrar sesión? + +/logout.bml.logout.text=Pulsa el siguiente botón para cerrar tu sesión. + +/logout.bml.title=Cerrar sesión + +/lostinfo.bml.btn.proceed=Adelante + +/lostinfo.bml.enter_email=Escribe to dirección de correo electrónico: + +/lostinfo.bml.enter_email_optional=Dirección de correo electrónico: (opcional) + +/lostinfo.bml.enter_username=Escribe tu nombre de usuario: + +/lostinfo.bml.lostpassword.text=Si has perdido tu contraseña, escribe tu nombre de usuario y, opcionalmente, la dirección de correo electrónico donde quieres recibir la contraseña. Para que la contraseña se envíe a una dirección que usabas anteriormente para LiveJournal, es necesario que se haya validado la dirección. Si dejas este campo en blanco, se enviará a tu dirección actual. + +/lostinfo.bml.lostpassword.title=¿Perdiste tu contraseña? + +/lostinfo.bml.lostusername.text=Si has perdido tu nombre de usuario, escribe tu dirección de correo electrónico y te lo enviaremos. + +/lostinfo.bml.lostusername.title=¿Perdiste tu nombre de usuario? + +/lostinfo.bml.title=Información perdida + +/lostinfo_do.bml.error.no_usernames_for_email=No hay nombre(s) de usuario para esta dirección: [[address]] . + +/lostinfo_do.bml.error1.text=Nunca has utilizado esa dirección con esta cuenta o nunca fue validada. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Esto es un correo automatico *** + +Este es el recordatorio de contraseña que solicitaste en [[sitename]]. +A continuación está tu nombre de usuario, contraseña y la dirección de correo electrónico bajo la cual está registrado tu diario. + +Nombre de usuario: [[username]] +Contraseña: [[password]] +Dirección de correo electrónico: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Para validar tu dirección de correo electrónico, entra aquí: + +/lostinfo_do.bml.lostpasswordmail.part3<< +La información fue solicitada en la página web por [[remoteip]]. + +Si no solicitaste el envío de esta contraseña a tu dirección, no te preocupes. Después de todo, eres el único que está leyendo este correo, y no la otra persona. Es posible que el usuario que hizo la petición esté equivocado y crea que él o ella tiene control de este nombre de usuario. También es posible que alguien cometiera un error tipográfico en el nombre de usuario o dirección de correo electrónico. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Si realmente crees que tu cuenta no es segura, lee http://www.livejournal.com/support/faqbrowse.bml?faqid=117 para información sobre como asegurarla. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Enlaces de utilidad: + +Tu LiveJournal: + [[journalurl]] + +Actualiza tu diario desde la página web: + [[updateurl]] + +Recuerdos, +El Equipo de LiveJournal + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Contraseña Perdida + +/lostinfo_do.bml.password_mailed.text=Hecho. Tu contraseña ha sido enviada. + +/lostinfo_do.bml.password_mailed.title=¡Contraseña enviada! + +/lostinfo_do.bml.title=Información perdida + +/lostinfo_do.bml.username_mailed.text=Hecho. Tu nombre de usuario ha sido enviado. + +/lostinfo_do.bml.username_mailed.title=¡Nombre de usuario enviado! + +/manage/index.bml.customization.customize=Personalizar diario + +/manage/index.bml.customization.customize.about=Cambiar la apareciencia de tu diario + +/manage/index.bml.customization.header=Personalización + +/manage/index.bml.customization.links=Lista de enlaces + +/manage/index.bml.customization.links.about=Crear una lista de enlaces que aparecerán en tu diario + +/manage/index.bml.entries.edit.about=Modidicar y borrar entradas de tu diario + +/manage/index.bml.entries.header=Entrades de diario + +/manage/index.bml.friends.header=Amigos + +/manage/index.bml.information.changepass=Cambiar contraseña + +/manage/index.bml.information.changepass.about=Cambiar la contraseña de tu cuenta + +/manage/index.bml.information.editinfo.about=Modificar la información de tu cuenta y varias opciones de la misma + +/manage/index.bml.information.header=Información de cuenta + +/manage/index.bml.information.status=Estado de cuenta + +/manage/index.bml.information.status.about=Escoge el estado de activación de tu cuenta (borrar o reactivar tu cuenta) + +/manage/index.bml.title=Administrar cuentas + +/manage/index.bml.userpictures=Cargar y administrar las imágenes de usuario para tu cuenta + +/manage/index.bml.userpictures.edit.about=Cargar y administrar tus imágenes de usuario + +/manage/index.bml.userpictures.header=Imágenes de usuario + +/manage/siteopts.bml.btn.lang=Cambiar idioma + +/manage/siteopts.bml.head.lang=Escoge tu idioma + +/modify.bml.title=Modificar diario + +/modify_do.bml.availablestyles.head=Estilos disponibles + +/modify_do.bml.availablestyles.userstyles=Estilos propios del usuario: + +/modify_do.bml.colortheme.about=Aquí puedes elegir que esquema de colores se aplicará a las opciones de presentación que elijas arriba. O, si no te gustan los colores proporcionados, ¡especifica tus propios colores! + +/modify_do.bml.colortheme.area.head=Zona de uso + +/modify_do.bml.colortheme.color.head2=(nombre o #rrggbb) + +/modify_do.bml.colortheme.customcolors=Colores personalizados + +/modify_do.bml.colortheme.defaulttheme=Esquema por defecto + +/modify_do.bml.colortheme.head=Esquema de colores + +/modify_do.bml.domainalias.about=Si tienes un dominio registrado (o que tienes pensado registrar) y te gustaría que automáticamente cargase tu LiveJournal, escríbelo aquí: + +/modify_do.bml.domainalias.domainname=Nombre de dominio: + +/modify_do.bml.domainalias.example=Ejemplo: mi-diario.com + +/modify_do.bml.domainalias.head=Solapamiento de dominio + +/modify_do.bml.domainalias.helptext=Para que esto funcione, debes dirigir al DNS de tu dominio para que solape hacia la dirección IP de [[sitename]]. Para más información, ver esta pregunta frecuente. + +/modify_do.bml.done.btn.savechanges=Guardar cambios + +/modify_do.bml.done.head=¿Terminaste? + +/modify_do.bml.done.text=Cuando hayas terminado, pulsa el botón de "Guardar cambios" abajo... + +/modify_do.bml.error.dupdomainalias=Otro usuario ya ha indicado estar utilizando el dominio que has elegido. + +/modify_do.bml.error.stylenotavailable=Uno de los estilos que has elegido no está disponible. Esto puede resultar porque alguien ha borrado el estilo, o estás intentando elegir uno para el cual no tienes acceso. + +/modify_do.bml.friends.about=Aquí están las opciones que controlan la vista de tu página de amigos. + +/modify_do.bml.friends.head=Vista de tu página de amigos + +/modify_do.bml.friends.opt.usesharedpic.about=Esta opción define la imagen que aparecerá en tu página de amigos cuando un usuario escribe en un diario compartido o comunidad. Si lo marcas verás la imagen de la comunidad, y si lo dejas sin marcar, verás la imagen de la persona que escribe la entrada. + +/modify_do.bml.friends.opt.usesharedpic.head=Usar imagen de diario compartido en lugar de imagen del usuario autor + +/modify_do.bml.journaloptions.about=Desde aquí puedes personalizar el aspecto de tus páginas de LiveJournal. Si tienes curiosidad por cómo funciona todo, lee la información de desarrollador. De otro modo, supondremos que estás satisfecho con las opciones básicas a continuación: + +/modify_do.bml.journaloptions.head=Opciones de tu diario + +/modify_do.bml.journalstatus.about=Si quieres borrar o recuperar tu diario, aquí lo puedes hacer. Una vez borrado tu diario, tienes 30 días para recuperarlo, por si cambias de parecer. Tras 30 días, tu diario se borrará de forma permanente y no habrá posibilidad de recuperarlo. + +/modify_do.bml.journalstatus.head=Estado de activación de tu diario + +/modify_do.bml.journalstatus.select.activated=Activo + +/modify_do.bml.journalstatus.select.deleted=Borrado + +/modify_do.bml.journalstatus.select.head=Estado: + +/modify_do.bml.journalstatus.select.suspended=Suspendido + +/modify_do.bml.moodicons.about=Cuando escribes en tu diario también puedes elegir tu estado de ánimo actual. Distintos usuarios han enviado distintos grupos de imagenes de estado de ánimo que puedes utilizar. O escoge "Ninguno" si no quieres ninguna imagen junto a tu estado de ánimo (ni siquiera tienes porque utilizar la función de estado de ánimo actual). + +/modify_do.bml.moodicons.head=Imágenes de estado de ánimo + +/modify_do.bml.moodicons.opt.forcefriends.about=Forzar este grupo de imagenes para todos los amigos en su página de amigos + +/modify_do.bml.moodicons.personal=Temas personales: + +/modify_do.bml.moodicons.preview=vista previa + +/modify_do.bml.moodicons.select=Escoge un grupo de imágenes: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Puedes hacer caso omiso a este apartado. Esto es para ajustar valores específicos de la presentación de tu página. Ver área de desarolladores para detalles. Ten en cuenta que estas sobreescrituras únicamente son para ajustar uno o dos valores de tu estilo. Si quieres sobreescribir todos los valores, tendrás que crear tu propio estilo. + +/modify_do.bml.overrides.box.head=Sobreescritura: + +/modify_do.bml.overrides.head=Sobreescrituras de estilo + +/modify_do.bml.overrides.note=Ten en cuenta que no todos los variables del estilo puedes sobreescribirse. Ver documentación para más detalles.
      También ten en cuenta que si intentas modificar tus sobreescrituras y has utilizado una etiqueta que no está permitida en el encabezado del documento – como <DIV>, <SPAN>, <IMG>, y muchas ortas etiquetas – esa etiqueta se filtrará. Sólo los elementos válidos en el encabezado de un documento HTML pueden usarse en las sobreescrituras de *_HEAD. Esto se limita a <title>, <base>, <style>, <link>, y <meta>. + +/modify_do.bml.overrides.warning=¡¡ESTO NO ES DONDE ESCRIBES TU DIARIO!! + +/modify_do.bml.pagelayoutstyle.about=Este valor controla cómo se presentará tu diario en pantalla. + +/modify_do.bml.pagelayoutstyle.head=Estilo de la presentación de tu página + +/modify_do.bml.pagelayoutstyle.warning=Tu tipo de cuenta únicamente permite elegir entre un pequeño número de estilos por defecto. + +/modify_do.bml.success.head=Hecho + +/modify_do.bml.success.text=La configuración de tu diario ha sido actualizada. Puedes ver tu diario aquí. + +/paidaccounts/index.bml.costs.header=Bueno, ¿cuánto cuesta? + +/paidaccounts/index.bml.costs.rates=Los precios son los siguientes: + +/paidaccounts/index.bml.costs.rates.amount.header=Cantidad + +/paidaccounts/index.bml.costs.rates.inexpensive<< +Eso sale a poco más de $2(EEUU)/mes por la cuota anual. +La parte más molesta seguramente será sacar tu cartera, encontrar tu tarjeta de crédito e ingresar tu información. +. + +/paidaccounts/index.bml.costs.rates.time.header=Duración + +/paidaccounts/index.bml.features.header=Y, ¿qué ventajas especiales recibo a cambio? + +/paidaccounts/index.bml.title=Acerca de las cuentas pagadas + +/paidaccounts/index.bml.whypay.argument<< +Por supuesto que no. Pagar por servicios de web es molesto, estamos de acuerdo. +Por eso casi todas las funciones de LiveJournal están disponibles libres de cargo. +Sin embargo, si estás contento con el servicio que estás recibiendo, muestra tu apoyo y adquiere una cuenta pagada. +. + +/paidaccounts/index.bml.whypay.header=¿Tengo que pagar para utilizar LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads=Hace falta dinero para llevar adelante un sitio web (servidores, alojamiento y ancho de banda), y esta forma nos parece mejor que bombardearte con correos banners publicitarios. + +/paidaccounts/index.bml.your_username=tu_nombre_de_usuario + +/paidaccounts/usepaypal.bml.delivery.badformat=La fecha de entrega no es válida. El formato debe ser aaaa-mm-dd o aaaa-mm-dd hh:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Fecha de entrega no puede ser una fecha pasada. Para entregar de forma inmediata, deja en blanco el campo de fecha. + +/paidaccounts/usepaypal.bml.delivery.toofuture=La fecha de entrega no puede distar de la fecha actual más de un mes. + +/pay/index.bml.deliverydate.details=Formato: aaaa-mm-dd hh:mm (hora Greenwich)
      (deja esto en blanco si no quieres demora de entrega) + +/pay/index.bml.deliverydate.label=Fecha de entrega: + +/pay/index.bml.gift.anonymous=Regalo anónimo + +/press/staff.bml.administration=Administración + +/press/staff.bml.administration.about=LiveJournal.com comenzó en 1999 como un proyecto de Brad Fitzpatrick, y durante los primeros dos años de su vida se mantuvo en pie gracias a un extenso grupo leal de voluntarios. Mientras que muchas operaciones de LiveJournal.com siguen llevándolas a cabo el equipo de voluntarios, ahora tenemos un grupo de empleados que lo supervisa todo: + +/press/staff.bml.avva.title=Desarrollador superior + +/press/staff.bml.back2=Volver al área de prensa + +/press/staff.bml.bradfitz.quip=Enfócate en tu producto, no sólo en sacar dinero. + +/press/staff.bml.bradfitz.title=Presidente / Desarrollador jefe + +/press/staff.bml.contact=Si necesitaras contactar cualquiera de nosotros, por favor envía un correo electrónico a webmaster@livejournal.com. + +/press/staff.bml.denisep.quip=Te lo tendré preparado el jueves que viene. + +/press/staff.bml.denisep.title=Relaciones con voluntarios / Especialista en utilidad + +/press/staff.bml.jproulx.quip=De friki a contacto con usuarios + +/press/staff.bml.jproulx.title=Supervisor de comunidades del sitio / Relaciones de prensa + +/press/staff.bml.lisa.title=Administrador de sistemas + +/press/staff.bml.ryanfitz.title=Servicios de pago + +/press/staff.bml.sandy.title=Contabilidad y administración + +/press/staff.bml.title=Empleados superiores + +/press/staff.bml.whitaker.quip=¿Ahora qué? + +/press/staff.bml.whitaker.title|staleness=1 +/press/staff.bml.whitaker.title=El interno + +/site/goat.bml.image.alt=Frank, la cabra mascota de LiveJournal. + +/site/goat.bml.image.caption=—Beeee —dice Frank. + +/site/goat.bml.meet.body=Este es Frank. Frank es la mascota de LiveJournal.com. Nos ayuda con tareas de programación esporádicas cuando las cosas se demoran, y de vez en cuando responde a preguntas en el área de soporte. Frank es realmente muy versátil... incluso ayuda a veces en el jardín. Cuando dejamos demasiado tiempo el césped sin cortar... "¡Eh, Frank! Es la hora de comer... ¡encárgate del césped!". Realmente es una situación de beneficio mutuo. + +/site/goat.bml.meet.header=Conoce a Frank + +/site/goat.bml.title=La Cabra Frank + +/suggestions/index.bml.howto.title=¿Cómo tramito una sugerencia? + +/suggestions/index.bml.info.title=Más información + +/suggestions/index.bml.title=Ãrea de sugerencias + +/suggestions/index.bml.welcome.text=Las sugerencias de los usuarios son una parte importante de LiveJournal. Si tienes algo que piensas que sería una buena idea, puedes seguir los siguientes procedimientos para atraer la atención de la gente que lleva el sitio. + +/suggestions/index.bml.welcome.title=¡Bienvenid@! + +/support/encodings.bml.edit.header=¡No puedo modificar mis entradas en el interfaz web! + +/support/encodings.bml.edit.text<< +Respuesta corta:
      (se aplica si escribes tu diario en inglés): Ves a tu página de configuración personal. Busca la opción cerca del final titulado Traducir las entradas viejas automáticamente de:. Elige la opción "Western European (Windows)" del menú desplegable y guarda los cambios. Tus entradas ahora deben de poder modificarse correctamente. p?> + +Respuesta larga: Para permitir modificar una entrada sin Unicode, el código LiveJournal necesita saber que codificación fue utilizada al escribir esa entrada. Para los usuarios del Inglés u otros idiomas occidentales, este será normalmente "Western European (Windows)", aunque si eso no funciona correctamente para caracteres de acentuación o similares, prueba con "Western European (ISO)". Usuarios que escriben en otros idiomas deberán seleccionar su codificación. Si no está en la lista, contacta a Soporte y explica el problema. p?> + + +. + +/support/encodings.bml.editcl.header=¡No puedo modificar mis entradas en el programa cliente! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=¡No puedo modificar mi lista de amigos con mi programa cliente! + +/support/encodings.bml.groups.text=modificar grupos y luego utiliza tu programa cliente. p?> + +/support/encodings.bml.overview.header=¿De qué se trata esto? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=¿Sigues perplejo? + +/support/encodings.bml.still.text=Ãrea de soporte. p?> + +/support/encodings.bml.title=Codificaciones + +/support/faqbrowse.bml.backfaq=Volver a preguntas frecuentes. + +/support/faqbrowse.bml.backsupport=Volver al área de soporte. + +/support/faqbrowse.bml.error.nofaq=El documento especificado no existe. + +/support/faqbrowse.bml.lastupdated=Última actualización: + +/support/faqbrowse.bml.title_cat=Preguntas frecuentes: [[catname]] + +/support/faqbrowse.bml.title_num=Pregunta frecuente No. [[num]] + +/support/see_overrides.bml.error.noprivs=Sólo usuarios con el privilegio «supportviewscreened» o «supporthelp» pueden ver las sobreescrituras de otro usuario. + +/support/see_overrides.bml.error.nos1=El usuario no está utilizando S1. + +/support/see_overrides.bml.header=Sobrescrituras para : + +/support/see_overrides.bml.nooverrides=No se han encontrado sobreescrituras para . + +/support/see_overrides.bml.title=Sobreescritras de usuario + +/talkmulti.bml.deleted.body=Los comentarios han sido borrados. Puedes ver el resto de la cadena aquí. + +/talkmulti.bml.deleted.title=Comentarios borrados + +/talkmulti.bml.error.comms_deleted=Uno de los comentarios ha sido borrado desde entonces. Por motivos de seguridad, rogamos vuelvas e intentes de nuevo. + +/talkmulti.bml.error.inconsistent_data=Los datos proporcionados son inconsistentes. + +/talkmulti.bml.error.invalid=Parametros especificados no válidos. + +/talkmulti.bml.error.invalid_mode=No has elegido ninguna de las acciones. Por favor vuelve y elige si quieres filtrar, quitar filtro de, o borrar los comentarios. + +/talkmulti.bml.error.login=No tienes iniciada la sesión. + +/talkmulti.bml.error.none_selected=No has elegido ningún comentario. + +/talkmulti.bml.error.privs.delete=No tienes permiso para borrar estos comentarios. + +/talkmulti.bml.error.privs.screen=No tienes permiso para filtrar estos comentarios. + +/talkmulti.bml.error.privs.unscreen=No tienes permiso para quitar el filtro a estos comentarios. + +/talkmulti.bml.screened.body=Estos comentarios han sido filtrados. Puedes visualizarlos aquí. + +/talkmulti.bml.screened.title=Comentarios filtrados + +/talkmulti.bml.title.delete=Borrar múltiples comentarios + +/talkmulti.bml.title.screen=Filtrar múltiples comentarios + +/talkmulti.bml.title.unscreen=Quitar el filtro a múltiples comentarios + +/talkmulti.bml.unscreened.body=Se ha quitado el filtro de los comentarios. Puedes visualizarlos aquí. + +/talkmulti.bml.unscreened.title=Quitado el filtro de comentarios + +/talkpost.bml.allowedhtml=Códigos HTML permitidos + +/talkpost.bml.error.cannotreplynopost=No se puede responder a un mensaje inexistente + +/talkpost.bml.error.nocommentsjournal= El usuario ha desactivado los comentarios para su diario. + +/talkpost.bml.error.nocommentspost=El usuario ha desactivado los comentarios para este mensaje en específico. + +/talkpost.bml.error.noreplypost=No se encuentra el mensaje al que quieres responder (¿se ha borrado?) + +/talkpost.bml.error.noreply_deleted=Ya se había borrado este comentario. No puedes responder a él. + +/talkpost.bml.error.noreply_screened=Este comentario está filtrado y no tienes permisos para verlo ni responder a él. + +/talkpost.bml.label.picturetouse=Imagen a utilizar: + +/talkpost.bml.loganonip=¡Aviso! Este usuario tiene activada la opción que graba la dirección IP de quiénes escriban de forma anónima. + +/talkpost.bml.loginq=¿Iniciar sesión? + +/talkpost.bml.logyourip=¡Aviso! Este usuario tiene activada la opción que graba tu dirección IP al escribir un comentario. + +/talkpost.bml.nosubjecthtml=No se permite código HTML en el asunto + +/talkpost.bml.opt.anonymous=Anónimo + +/talkpost.bml.opt.defpic=(predeterminada) + +/talkpost.bml.opt.friendsonly=- este usuario no permite comentarios anónimos ni de usuarios que no sean amigos. Puedes comentar aquí si [[username]] te lista como amigo. + +/talkpost.bml.opt.from=De: + +/talkpost.bml.opt.ljuser=Usuario de LiveJournal: + +/talkpost.bml.opt.loggedin=Sesión de usuario: [[username]] + +/talkpost.bml.opt.message=Mensaje: + +/talkpost.bml.opt.noanonpost=- este usuario no permite comentarios anónimos. + +/talkpost.bml.opt.noautoformat=No formatear automáticamente: + +/talkpost.bml.opt.noimage=Sin imagen + +/talkpost.bml.opt.preview=Vista previa + +/talkpost.bml.opt.spellcheck=Comprobar ortografía antes de enviar (sólo entradas en inglés) + +/talkpost.bml.opt.subject=Asunto: + +/talkpost.bml.opt.submit=Enviar comentario + +/talkpost.bml.opt.willscreen=(será filtrado) + +/talkpost.bml.opt.willscreenfriend=(será filtrado si no eres amigo) + +/talkpost.bml.paraformat=Los párrafos se formatearán automáticamente por defecto. + +/talkpost.bml.postresponse=Escribe un comentario en respuesta: + +/talkpost.bml.title=Escribir un comentario + +/talkpost.bml.usermismatch<< +Has escrito un nombre de usuario per has desmarcado la opción "usuario de LiveJournal". + +Por favor, elige entre borrar el campo de texto o elige la modalidad de envío relevante e intenta de nuevo. +. + +/talkpost.bml.warnscreened=Aviso: Este comentario está filtrado. Al responder se quitará el filtro automáticamente y se hará visible. + +/talkpost_do.bml.error.badpassword=La contraseña proporcionada no es correcta para este nombre de usuario. Puedes recuperar tu contraseña aquí si la has olvidado. + +/talkpost_do.bml.error.badusername=El nombre de usuario especificado no existe en LiveJournal. Puedes recuperar tu nombre de usuario aquí si lo has olvidado, o puedes escribir como usuario "Anónimo". + +/talkpost_do.bml.error.banned=No tienes permiso para escribir comentarios en el diario de este usuario. + +/talkpost_do.bml.error.blankmessage=Tu mensaje estaba vacío. Por lo menos escribe algo en el campo de mensaje, por favor. + +/talkpost_do.bml.error.confused_identity=Pusiste un nombre de usuario, pero escogiste escribir de forma anónima o como el usuario actualmente en sesión. Vuelve y decide la opción que realmente quieres utilizar. + +/talkpost_do.bml.error.deleted=Tu diario ha sido borrado. No puedes escribir comentarios. + +/talkpost_do.bml.error.friendsonly= 1. Sólo los amigos de [[username]] pueden escribir mensajes en este diario. + +/talkpost_do.bml.error.lostcookie=Parece que se ha desparecido tu cookie de iniciar sesión. + +/talkpost_do.bml.error.manybytes=* Lo sentimos, pero tu mensaje actual de [[current]] sobrepasa la cantidad máxima de bytes, que es de [[limit]]. Por favor, vuelve, acórtalo e intenta enviarlo de nuevo. + +/talkpost_do.bml.error.manychars=Lo sentimos, pero tu mensaje actual de [[current]] caracteres sobrepasa el límite, que es de [[limit]] carácteres. Por favor, vuelve, acórtalo e intenta enviarlo de nuevo. + +/talkpost_do.bml.error.mustlogin=* Hay que tener una sesión iniciada o usar un nombre de usuario y contraseña para responder a esta entrada protegida. + +/talkpost_do.bml.error.noanon=No se puede escribir comentarios anónimos en este diario. + +/talkpost_do.bml.error.noauth=No estás autorizado para responder a esta entrada protegida. + +/talkpost_do.bml.error.nocomments=El usuario ha desactivado los comentarios para esta entrada. + +/talkpost_do.bml.error.noparent=No puedes responder a un comentario inexistente. + +/talkpost_do.bml.error.notafriend=Lo sentimos, pero [[user]] no te lista como amigo, y ha escogido la opción de "sólo amigos" para quién puede responder a su diario. + +/talkpost_do.bml.error.nousername=No diste tu nombre de usuario de LiveJournal. Puedes escoger "Anónimo" si no tienes una cuenta de LiveJournal. + +/talkpost_do.bml.error.noverify=Lo sentimos, pero no se te permite escribir comentarios en los diarios de otros usuarios hasta que se verifique tu dirección electrónica. Si has perdido el email de confirmación para ello, puedes solicitar el reenvío del mismo. + +/talkpost_do.bml.error.postshared=No puedes enviar comentarios con una cuenta de comunidad o de diario compartido. Estas no representan individuos, sino grupos de personas. + +/talkpost_do.bml.error.screened=No tienes permiso para responder a este comentario filtrado. + +/talkpost_do.bml.error.suspended=Tu diario ha sido suspendido. No puedes escribir mensajes. + +/talkpost_do.bml.error.testacct=Las cuentas de prueba sólo pueden utilizarse en diarios de prueba. + +/talkpost_do.bml.opt.preview=Vista previa + +/talkpost_do.bml.preview=Abajo está como se mostrará tu comentario. Puedes modificar tu comentario mediante el formulario que se encuentra abajo, o lo puedes enviar tal como es. + +/talkpost_do.bml.preview.subject=Asunto: + +/talkpost_do.bml.preview.submit=Enviar + +/talkpost_do.bml.preview.title=Vista previa + +/talkpost_do.bml.success.loggedin=Tu sesión se ha iniciado. + +/talkpost_do.bml.success.message=Se ha añadido tu comentario. Lo puedes ver aquí. + +/talkpost_do.bml.success.screened.comm=Tu comentario ha sido añadido. Según las opciones de esta comunidad, fue filtrado, y sólo será visible para ti y los administradores de la comunidad hasta que quiten el filtro del comentario. Puedes ver tu comentario aquí. + +/talkpost_do.bml.success.screened.user=Tu comentario ha sido añadido. Según las opciones de este diario, fue filtrado, y sólo será visible para ti y el propietario del diario hasta que quite el filtro del comentario. Puedes ver tu comentario aquí. + +/talkpost_do.bml.success.title=Hecho + +/talkpost_do.bml.success.unscreened=Además, el comentario filtrado al que estabas respondiendo carece ahora de filtrado y es visible. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Comentario escrito + +/talkread.bml.anonuser=(Anónimo) + +/talkread.bml.confirm.action=¿Estás seguro de querer borrar los comentarios elegidos? + +/talkread.bml.deletedpost=(Mensaje borrado) + +/talkread.bml.deleteduser=(Usuario borrado: [[username]]) + +/talkread.bml.fromip=(desde [[ip]]) + +/talkread.bml.noreplies=Sin respuestas + +/talkread.bml.nosubject=(sin asunto) + +/talkread.bml.replysuspended=(Respuesta de un usuario suspendido) + +/talkread.bml.screenedpost=(Comentario filtrado) + +/talkread.bml.select=Marcar + +/talkread.bml.subjectdeleted=[borrado] + +/talkread.bml.talkmulti.delete=Borrar + +/talkread.bml.talkmulti.des=Acción en masa sobre los comentarios marcados: + +/talkread.bml.talkmulti.screen=Filtrar + +/talkread.bml.talkmulti.submit=Ejecutar + +/talkread.bml.talkmulti.unscreen=Quitar filtro + +/talkread.bml.title=Leer comentarios + +/talkscreen.bml.error.login=Debes tener iniciada la sesión para trabajar con comentarios filtrados. + +/talkscreen.bml.error.privs.screen=No tienes permiso para filtrar este comentario. + +/talkscreen.bml.error.privs.unscreen=No tienes permiso para quitar el filtro de este comentario. + +/talkscreen.bml.screen.doit=Sí, filtrar este comentario + +/talkscreen.bml.screen.sure.body=¿Estás seguro de que quieres filtrar este comentario? + +/talkscreen.bml.screen.sure.title=¿Filtrar este comentario? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=Este comentario ha sido filtrado. + +/talkscreen.bml.screened.title=Hecho + +/talkscreen.bml.title=Comentario filtrado + +/talkscreen.bml.unscreen.doit=Sí, quitar filtrado + +/talkscreen.bml.unscreen.sure.body=¿Estás seguro de querer quitar el filtrado de este comentario? + +/talkscreen.bml.unscreen.sure.title=¿Quitar filtrado a este comentario? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=Este comentario ya no está filtrado. + +/talkscreen.bml.unscreened.title=Hecho + +/tools/emailmanage.bml.address.current.title=Dirección actual + +/tools/emailmanage.bml.address.old.title=Direcciones previas + +/tools/emailmanage.bml.desc.title=Descripción + +/tools/emailmanage.bml.log.deleted=Borrada: [[email]] a la(s) [[time]] + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Tu lista de entradas para recordar ha sido actualizada. + +/tools/memadd.bml.body.added.header=Hecho + +/tools/memadd.bml.description=Descripción: + +/tools/memadd.bml.description.text<< +Asigna una descripción a esta memoria para recordarla. + Para borrar esta entrada de tu lista de memorias, deja el campo de descripción vacío. +. + +/tools/memadd.bml.error.deleted.body=La entrada descrita anteriormente como "[[desc]]" ha sido borrada de tu lista de memorias. + +/tools/memadd.bml.error.deleted.title=Memoria borrada + +/tools/memadd.bml.error.entry_deleted=La entrada del diario ha dejado de existir. Memoria borrada. + +/tools/memadd.bml.error.fivekeywords=Sólo se permiten 5 palabras clave/categorías por memoria. + +/tools/memadd.bml.error.invalid_security=Falta la opción de seguridad o no es válida. + +/tools/memadd.bml.error.login=Debes tener iniciada tu sesión para utilizar este servicio. Inicia tu sesión y regresarás automáticamente aquí. + +/tools/memadd.bml.error.maxsize=Esta palabra clave sobrepasa el límite de caracteres permitidos: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Para añadir una entrada de diario a tu lista de memorias, debes proporcionar una descripción. +Para borrar una memoria, puedes modificarlo y dejar vacía la descripción, pero esta entrada todavía no estaba en tu lista de memorias. +. + +/tools/memadd.bml.error.nodescription.title=Sin descripción + +/tools/memadd.bml.form.reset=Vaciar campos + +/tools/memadd.bml.form.submit=Enviar + +/tools/memadd.bml.keywords=Palabras clave: + +/tools/memadd.bml.keywords.example=Ejemplos: Gracioso, Geeky, Romántico + +/tools/memadd.bml.keywords.select=O, si lo prefieres, puedes elegir palabras clave que has usado anteriormente: + +/tools/memadd.bml.keywords.text=¿Por qué es memorable esta entrada? Escribe hasta cinco palabras clave o categorías, separadas por comas, para poder encontrarlo más adelante. + +/tools/memadd.bml.login.enterinfo=Escribe el nombre de usuario y contraseña de la cuenta en el que deseas guardar la memoria. + +/tools/memadd.bml.login.forgot.header=¿Olvidaste algo? + +/tools/memadd.bml.login.forgot.recover=Si olvidaste tu nombre de usuario o contraseña, recupéralo aquí. + +/tools/memadd.bml.multiple_selections=Mantén pulsado 'Control' al elegir las palabras clave para poder usar varias. + +/tools/memadd.bml.security=Seguridad: + +/tools/memadd.bml.security.friendsonly=Sólo para amigos + +/tools/memadd.bml.security.private=Privado + +/tools/memadd.bml.security.public=Público + +/tools/memadd.bml.title=Añadir a memorias + +/tools/memadd.bml.title.added=Añadido + +/tools/memadd.bml.title.add_memory=Añadir entrada memorable + +/tools/memadd.bml.title.deleted=Borrado + +/tools/memadd.bml.title.edit_memory=Modificar entrada memorable + +/tools/memadd.bml.whocansee<< +¿Quién puede ver que esta entrada la has marcado como memorable? + ¿Todos los usuarios, sólo aquellos en tu lista de amigos, o sólo tú? +. + +/tools/memories.bml.back=Volver + +/tools/memories.bml.body.keyword<< + + +[[user]] le parecen memorables. P?> +. + +/tools/memories.bml.body.list_categories<< + + +[[user]] ha colocado sus memorias. P?> +. + +/tools/memories.bml.body.memorable=Aquí se muestra una lista de las entradas sin clasificar que [[user]] guarda como memorables. + +/tools/memories.bml.edit=modificar + +/tools/memories.bml.error.noentries.body<< +Esto podría deberse a que:
        +
      1. el usuario no ha definido ningún hecho memorable, +
      2. los hechos memorables del usuario están protegidos y no tienes permiso para verlos, o, +
      3. el usuario no tiene memorias que coincidan con los criterios de filtrado.
      +. + +/tools/memories.bml.error.noentries.title=No se encontró ninguna memoria. + +/tools/memories.bml.filter.all=Todas las memorias + +/tools/memories.bml.filter.other=Sólo otras entradas + +/tools/memories.bml.filter.own=Sólo entradas de '[[user]]' + +/tools/memories.bml.form.switch=Cambiar + +/tools/memories.bml.sort.description=Descripción + +/tools/memories.bml.sort.journal=Diario + +/tools/memories.bml.sort.orderadded=Orden en el que se añadieron + +/tools/memories.bml.title.keyword=Entradas [[keyword]] memorables. + +/tools/memories.bml.title.memorable=Entradas memorables + +/tools/memories.bml.uncategorized=Sin clasificar + +/update.bml.altpost=Escribir entrada en el diario: + +/update.bml.btn.update=Actualizar diario + +/update.bml.currmood=Estado de ánimo actual: + +/update.bml.currmusic=Música actual: + +/update.bml.date=Fecha: + +/update.bml.default=por defecto + +/update.bml.defaultjournal=([[user]]) -- por defecto + +/update.bml.error.login=Fallo al iniciar sesión: + +/update.bml.error.update=Fallo al actualizar diario: + +/update.bml.event=Evento: + +/update.bml.full=Página completa de actualización + +/update.bml.localtime=Hora local: + +/update.bml.loggingin=Iniciando sesión en el servidor... + +/update.bml.noneother=Ninguno u otro: + +/update.bml.note=Aviso: La hora y fecha arriba son las de nuestro servidor. Corrígelos para tu zona antes de enviar la entrada. + +/update.bml.opt.backdate=Guardar con fecha anterior: + +/update.bml.opt.backdate.about=no se mostrará en la vista de amigos + +/update.bml.opt.defpic=(por defecto) + +/update.bml.opt.nocomments=No permitir comentarios: + +/update.bml.opt.noemail=No enviar avisos por correo: + +/update.bml.opt.noformat=No dar formato automáticamente: + +/update.bml.opt.spellcheck=Comprobar ortografía antes de enviar (sólo entradas en inglés) + +/update.bml.options=Opciones adicionales + +/update.bml.other=Otro: + +/update.bml.picture=Imagen a utilizar: + +/update.bml.security.custom=Personalizado... + +/update.bml.security.friends=Sólo amigos + +/update.bml.security.head=Nivel de seguridad: + +/update.bml.security.private=Privado + +/update.bml.security.public=Público + +/update.bml.servermsg=Además, el servidor tiene un mensaje para ti: + +/update.bml.simple=Estás viendo la página sencilla. Para más opciones, pulsa aquí. + +/update.bml.spellchecked=Tu entrada corregida: + +/update.bml.subject=Asunto: (opcional) + +/update.bml.timeformat=Formato 24 horas + +/update.bml.title=Actualizar diario + +/update.bml.title.readonly=Modo sólo lectura + +/update.bml.update.head=Actualiza tu diario... + +/update.bml.update.success=Actualización hecha. Puedes ver tu diario actualizado aquí. + +/update.bml.updating=Actualizando diario... + +/uploadpic.bml.error.unsupportedtype=Los archivos del tipo [[filetype]] no son soportados. Sólo puedes cargar archivos GIF, PNG o JPG. Casi todos los programas editores de imágenes pueden hacer esta conversión. + +/userinfo.bml.about.comm=Acerca de: + +/userinfo.bml.about.user=Perfil: + +/userinfo.bml.body.leave= Puedes abandonar la comunidad en cualquier momento. + +/userinfo.bml.comminfo.body=A continuación se muestra la información acerca de la comunidad "[[commname]]" en LiveJournal. + +/userinfo.bml.comminfo.name=Información de comunidad + +/userinfo.bml.date.never=Nunca. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Nombre de usuario malformado. + +/userinfo.bml.error.notloggedin=Si deseas ver tu propio perfil de usuario, deberás iniciar tu sesión. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Visto por: + +/userinfo.bml.friendof.hidden=(oculto) + +/userinfo.bml.friendof.syndreadcount=Número de lectores + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Amigo de: + +/userinfo.bml.friends.comm=Miembros + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Amigos + +/userinfo.bml.label.addbuddy=Añadir contacto + +/userinfo.bml.label.adduser=Añadir usuario + +/userinfo.bml.label.aolim=Mensajería AOL: + +/userinfo.bml.label.birthdate=Fecha de nacimiento: + +/userinfo.bml.label.clientsused=Clientes utilizados: + +/userinfo.bml.label.comments=Comentarios: + +/userinfo.bml.label.composted=Escritos: [[num]] - + +/userinfo.bml.label.comreceived=Recibidos: [[num]] + +/userinfo.bml.label.datecreated=Fecha de creación: + +/userinfo.bml.label.dateupdated=Última actualización: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=Correo Electrónico: + +/userinfo.bml.label.icquin=Número ICQ: + +/userinfo.bml.label.interests=Intereses + +/userinfo.bml.label.interests.modifyyours=Modificar los tuyos + +/userinfo.bml.label.interests.removesome=Quitar algunos + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] intereses no mostrados + +/userinfo.bml.label.journalentrs=Entradas en diario: + +/userinfo.bml.label.location=Localidad: + +/userinfo.bml.label.memberof=Miembro de + +/userinfo.bml.label.memories=Memorias: + +/userinfo.bml.label.moredetails=(más detalles...) + +/userinfo.bml.label.msnusername=Usuario MSN: + +/userinfo.bml.label.name=Nombre: + +/userinfo.bml.label.nofriends=Ninguno listado. + +/userinfo.bml.label.reqfinduser=Sólo los usuarios con el privilegio 'finduser' pueden buscar usuarios por userid. + +/userinfo.bml.label.sendmessage=Enviar mensaje + +/userinfo.bml.label.shared=Acceso de escritura: + +/userinfo.bml.label.supportpoints=Puntos por soporte + +/userinfo.bml.label.syndicatedfrom=Sindicado de: + +/userinfo.bml.label.syndicatedstatus=Estado de sindicación: + +/userinfo.bml.label.textmessage=Mensaje
      de texto
      : + +/userinfo.bml.label.todo=Lista de quehaceres + +/userinfo.bml.label.user=Usuario: + +/userinfo.bml.label.viewfriends=Ver amigos + +/userinfo.bml.label.viewmembers=Ver miembros + +/userinfo.bml.label.website=Página web: + +/userinfo.bml.label.yahooid=ID Yahoo!: + +/userinfo.bml.membership.body=Para unirte a esta comunidad pulsa aquí. + +/userinfo.bml.memories.entries=[[count]] entradas + +/userinfo.bml.memories.entry=[[count]] entrada + +/userinfo.bml.monitor.comm=Seguir comunidad + +/userinfo.bml.monitor.user=Añadir este usuario a tu lista de amigos + +/userinfo.bml.nonexist.body=El nombre de usuario [[user]] actualmente no está registrado. + +/userinfo.bml.nonexist.name=Usuario desconocido + +/userinfo.bml.sendmessage.body=Envía un mensaje de texto a [[user]]
      a su teléfono celular o buscapersonas. + +/userinfo.bml.syn.last.never=Nunca + +/userinfo.bml.syn.lastcheck=Última comprobación: + +/userinfo.bml.syn.nextcheck=Siguiente comprobación: + +/userinfo.bml.syn.parseerror=Mensaje de error: + +/userinfo.bml.syndinfo.body=Si quieres que los artículos del sitio sindicado aparezcan en tu página de amigos, puedes añadir este diario a tu lista de amigos. + +/userinfo.bml.syndinfo.name=Diario de sindicado + +/userinfo.bml.tellafriend=¡Recomiéndalo/a a un amigo! + +/userinfo.bml.timeupdate.dayago=Hace 1 día + +/userinfo.bml.timeupdate.daysago=Hace [[num]] días + +/userinfo.bml.timeupdate.hourago=Hace 1 hora + +/userinfo.bml.timeupdate.hoursago=Hace [[num]] horas + +/userinfo.bml.timeupdate.minuteago=Hace 1 minuto + +/userinfo.bml.timeupdate.minutesago=Hace [[num]] minutos + +/userinfo.bml.timeupdate.secondago=Hace 1 segundo + +/userinfo.bml.timeupdate.secondsago=Hace [[num]] segundos + +/userinfo.bml.timeupdate.weekago=Hace 1 semana + +/userinfo.bml.timeupdate.weeksago=Hace [[num]] semanas + +/userinfo.bml.title=Información de usuario + +/userinfo.bml.title.communityinfo=Información de comunidad + +/userinfo.bml.title.syndicated=Cuenta sindicada + +/userinfo.bml.userinfo.body=Abajo se muestra la información para [[username]]. Si eres este usuario, puedes modificar tu información (o elegir qué información se considerará pública) en la página para modificar tu información. + +/userinfo.bml.userinfo.name=Información de usuario + +BML.parse_multipart.parse=Error analizando el archivo a cargar + +BML.parse_multipart.toolarge=Archivo demasiado grande para ser cargado + +BML.parse_multipart.unknowntype=Tipo de contenido desconocido + +btn.search=Buscar + +date.day.friday.long=Viernes + +date.day.friday.short=vie + +date.day.monday.long=Lunes + +date.day.monday.short=lun + +date.day.saturday.long=Sábado + +date.day.saturday.short=sab + +date.day.sunday.long=Domingo + +date.day.sunday.short=dom + +date.day.thursday.long=Jueves + +date.day.thursday.short=jue + +date.day.tuesday.long=Martes + +date.day.tuesday.short=mar + +date.day.wednesday.long=Miércoles + +date.day.wednesday.short=xie + +date.month.april.long=Abril + +date.month.april.short=abr + +date.month.august.long=Agosto + +date.month.august.short=ago + +date.month.december.long=Diciembre + +date.month.december.short=dic + +date.month.february.long=Febrero + +date.month.february.short=feb + +date.month.january.long=Enero + +date.month.january.short=ene + +date.month.july.long=Julio + +date.month.july.short=jul + +date.month.june.long=Junio + +date.month.june.short=jun + +date.month.march.long=Marzo + +date.month.march.short=mar + +date.month.may.long=Mayo + +date.month.may.short=may + +date.month.november.long=Noviembre + +date.month.november.short=nov + +date.month.october.long=Octubre + +date.month.october.short=oct + +date.month.september.long=Septiembre + +date.month.september.short=sep + +dystopia.btn.login=INICIAR SESIÓN + +dystopia.hello_anonymous=¡Bienvenido a LiveJournal! + +dystopia.hello_loggedin=¡Hola, [[username]]! + +dystopia.nav.createjournal=Crear un diario + +dystopia.nav.developer=Ãrea de desarolladores + +dystopia.nav.download=Descargar + +dystopia.nav.editentries=Modificar entradas + +dystopia.nav.editfriends=Tus amigos + +dystopia.nav.editpassword=Tu contraseña + +dystopia.nav.editpics=Tus imágenes + +dystopia.nav.editstyle=Modificar estilo + +dystopia.nav.faq=Preguntas frecuentes + +dystopia.nav.findcomm=Por comunidad + +dystopia.nav.finddir=En el directorio + +dystopia.nav.findint=Por intereses + +dystopia.nav.findrandom=Al azar + +dystopia.nav.findregion=Por región + +dystopia.nav.home=Inicio + +dystopia.nav.journalcalendar=Calendario + +dystopia.nav.journalfriends=Amigos + +dystopia.nav.journalinfo=Info de usuario + +dystopia.nav.journalrecent=Recientes + +dystopia.nav.legalprivacy=Privacidad + +dystopia.nav.legaltos=Condiciones de servicio + +dystopia.nav.login=Iniciar sesión + +dystopia.nav.logout=Cerrar sesión + +dystopia.nav.lostinfo=Contraseña perdida + +dystopia.nav.memories=Memorias + +dystopia.nav.modifyjournal=Modificar diario + +dystopia.nav.news=Noticias + +dystopia.nav.paidaccts=Cuentas pagadas + +dystopia.nav.paymentarea=Zona de pago + +dystopia.nav.personalinfo=Info personal + +dystopia.nav.sitemap=Mapa del sitio Web + +dystopia.nav.support=¿Tienes alguna pregunta? + +dystopia.nav.updatejournal=Actualizar + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=135 + +dystopia.navhead.findusers=Buscar usuarios + +dystopia.navhead.help=Ayuda y soporte + +dystopia.navhead.journal=Tu diario + +dystopia.navhead.legal=Asuntos legales + +dystopia.navhead.settings=Tu configuración + +dystopia.navhead.welcome=¡Bienvenido! + +dystopia.search.aolim=Nombre de AOL + +dystopia.search.icq=Número de ICQ + +dystopia.search.int=Interés + +dystopia.search.msn=Usuario MSN + +dystopia.search.region=Región + +dystopia.search.yahoo=Identificador Yahoo! + +dystopia.searchlj=Buscar en LiveJournal + +Email=Dirección electrónica + +email.newacct.body<< +¡Enhorabuena, tienes una nueva cuenta de LiveJournal! + +Para completar la creación de tu diario y verificar tu dirección de correo, +entra aquí: + + [[regurl]] + +La dirección URL de tu nuevo diario se encuentra en: + + [[siteroot]]/users/[[username]]/ + +y también en: + + [[siteroot]]/~[[username]]/ + +A continuación se encuentran tu nombre de usuario y contraseña de +LiveJournal: + + Nombre de usuario: [[username]] + Contraseña: [[password]] + +Puedes acceder a tu cuenta desde [[siteroot]]/, crear nuevas +entradas de diario y modificar tus opciones de diario, pero recomendamos +que descargues un programa cliente de LiveJournal. Es la forma más fácil +de actualizar tu diario, y hay para muchos sistemas operativos. Consigue +uno en: + + [[siteroot]]/download/ + +Empezar a usar LiveJournal puede ser difícil cuando no conoces a nadie. +Visita http://newbies.livejournal.com para consejos prácticos y ayuda... +¡con un poco de suerte serás un profesional en poco tiempo! + +Esperamos que disfrutamos LiveJournal tanto como disfrutamos +proporcionándote el servicio. Si tienes cualquier pregunta acerca de como +usar LiveJournal, por favor visita nuestro área de soporte en: + + [[siteroot]]/support/ + +Allí encontrarás las respuestas a prácticamente cualquier pregunta que +podrías tener acerca de LiveJournal. + +Nuestra meta es hacer que LiveJournal sea la caña... si podemos hacer +cualquier cosa para hacerlo más fácil de usar, más potente, más fácil de +personalizar, lo que sea... háznoslo saber. No mantenemos este sitio por +dinero. No somos una compañía punto com fundada por capital venturado +que espera entrar en el mercado de stock ... este sitio lo mantienen todas +las personas que lo utilizan. Haznos saber que es lo que quieres sacar de +LiveJournal. + +Si tienes preguntas, el equipo de soporte te proporcionará una respuesta +generalmente en menos de 24 horas. + +¡Disfruta! + +El Equipo de [[sitename]] +[[siteroot]]/ +. + +email.newacct.subject=Bienvenid@ a LiveJournal + +error.badpassword=Contraseña incorrecta. + +error.dberror=Surgió un error en la base de datos: + +error.deleted.name=Borrado + +error.deleted.text=Este diario fue borrado. Si eres [[user]], tienes un periodo de 30 días tras haber borrado tu diario para recuperarlo. Después de 30 días borraremos todo el contenido permanentemente de nuestros servidores. + +error.deleted.title=Cuenta borrada + +error.ipbanned=Tu dirección IP tiene prohibido el acceso temporalmente por sobrepasar el limite de fallos de inicio de sesión. + +error.malformeduser=Nombre de usuario malformado. + +error.nobutton=¿No pulsaste ningún botón? + +error.nodb=La base de datos no está disponible por el momento. + +error.nodbmaintenance=Esta parte de la base de datos está temporalmente fuera de servicio por tareas de mantenimiento. Intenta de nuevo en unos minutos. + +error.noentry=No existe tal entrada. + +error.nojournal=Diario desconocido + +error.noremote=Tienes que iniciar tu sesión para poder utilizar esta página. + +error.procrequest=Surgió un error al procesar tu petición: + +error.purged.name=Borrado + +error.purged.text=El diario fue borrado y purgado. + +error.purged.title=Cuenta purgada + +error.suspended.name=Suspendido + +error.suspended.text=Este diario fue suspendido de manera temporal o permanente. Si eres [[user]], lee la pregunta frecuente ¡Mi cuenta ha sido suspendida! ¿Qué puedo hacer para recuperarla? para más información. Fíjate que, para proteger la privacidad de nuestros usuarios, [[sitename]] no puede hablar de las razones para ninguna suspensión con nadie que no sea el dueño de la cuenta. + +error.suspended.title=Cuenta suspendida + +error.tempdisabled=Esto está temporalmente deshabilitado. + +error.unknownmode=Modo desconocido. + +error.usernameinvalid=Nombre de usuario contiene caracteres no válidos. + +error.usernamelong=Nombre de usuario es demasiado largo, máximo de 15 caracteres. + +error.username_notfound=No se encontró el nombre de usuario. + +Help=Ayuda + +label.security.custom=Personalizado... + +label.security.friends=Sólo amigos + +label.security.head=Nivel de seguridad: + +label.security.private=Privado + +label.security.public=Público + +label.switch.button=Cambiar + +label.switch.header=Cambiar de diario + +label.switch.workwith=Trabajar con el diario: + +langname.be=bielorruso + +langname.da=danés + +langname.de=alemán + +langname.en=inglés + +langname.en_GB=inglés (Reino Unido) + +langname.en_LJ=inglés + +langname.eo=Esperanto + +langname.es=Español + +langname.et=estonio + +langname.fi=finlandés + +langname.fr=francés + +langname.ga=irlandés + +langname.gd=gaélico + +langname.he=hebreo + +langname.hu=húngaro + +langname.is=islandés + +langname.it=italiano + +langname.ja=japonés + +langname.la=latín + +langname.lv=letón + +langname.ms=malayo + +langname.nb=noruego bokmÃ¥l + +langname.nl=neerlandés + +langname.nn=noruego nynorsk + +langname.pl=polaco + +langname.pt=portugués + +langname.ru=ruso + +langname.sv=sueco + +langname.tr=turco + +langname.uk=ucraniano + +langname.zh=chino simplificado + +ljcom.userinfo.accounttype=Tipo de cuenta + +ljlib.pageofpages=Página [[page]] de [[total]] + +lostinfo.head=¿Olvidaste algo? + +lostinfo.text=Si olvidaste tu nombre de usuario o contraseña, recupéralo aquí. + +Password=Contraseña + +password.max30=Las contraseñas no pueden ser mayores de 30 caracteres. + +portal.bdays.count.des=Por defecto, se mostrarán los 5 amigos con cumpleaños más próximo. + +portal.bdays.count.name=Cumpleaños a mostrar + +portal.bdays.portalname=Cumpleaños + +portal.bdays.portaltitle=Cumpleaños + +portal.goat.name=Mascota del sitio + +portal.goattext.des=¿Qué quieres que diga tu cabra? Lo único que realmente pueden decir las cabras es "Beeee", pero puedes imaginar que tu cabra dice otra cosa si quieres. + +portal.goattext.name=Texto de cabra + +portal.login.portalname=Campo de inicio de sesión + +portal.memories.entriesnoun=entradas + +portal.memories.entrynoun=entradas + +portal.memories.portalname=Entradas memorables + +portal.memories.portaltitle=Entradas memorables + +portal.ministats.active=Activos: + +portal.ministats.title=Usuarios + +portal.ministats.total=Totales: + +portal.misbehaved.des=En realidad, querrás dejar esto marcado. Cabras sin domesticar son todo problemas. + +portal.misbehaved.name=Cabra mal comportado + +portal.newtolj.name=Enlaces del sitio + +portal.popfaq.portalname=Los 10 documentos más leídos + +portal.popfaq.portaltitle=Los 10 documentos más leídos + +portal.randuser.count.des=Por defecto, se muestra un usuario al azar, pero puedes tener hasta 10 usuarios verticalmente en columnas estrechas, o 5 horizontalmente en una columna ancha. + +portal.randuser.count.name=Número de usuarios al azar a mostrar + +portal.randuser.error.tableempty=No hay usuarios al azar. Contactar con el adminitrador. + +portal.randuser.hidename.des=Por defecto, se muestra el nombre de usuario al azar. Marca esta opción para quitarlo. + +portal.randuser.hidename.name=Ocultar nombre + +portal.randuser.hidepic.des=Por defecto, se muestra la imagen de usuario, si hay uno disponible. Marca esta opción para quitarlo. + +portal.randuser.hidepic.name=Ocultar Imagen de Usuario + +portal.randuser.portalname=Usuario al azar + +portal.randuser.portaltitle=Usuario al azar + +portal.randuser.portaltitleplural=Usuarios al azar + +portal.recent.error.noentries=Lo sentimos. No hay entradas. + +portal.recent.error.notsetup=Debes configurar este campo. Pulsa sobre el símbolo más para fijar el diario que te gustaría ver aquí. + +portal.recent.error.userstatus=El usuario ha borrado o suspendido su cuenta. + +portal.recent.items.description=Por defecto sólo se muestra la entrada más reciente. + +portal.recent.items.name=Elementos a mostrar + +portal.recent.journal.description=¿De qué diario quieres ver las entradas más recientes? + +portal.recent.journal.name=Diario + +portal.recent.nosubject=(sin asunto) + +portal.recent.permlink=Enlace + +portal.recent.portalname=Vista de Entrada Reciente + +portal.recent.portaltitle=Campo de entrada reciente + +portal.recent.showtext.description=Por defecto sólo se mostrarán los asuntos. + +portal.recent.showtext.name=Incluir texto + +portal.stats.journalentyest=Entradas de diario de ayer + +portal.stats.portalname=Estadísticas del sitio + +portal.stats.portaltitle=Estadísticas + +portal.stats.totalusers=Usuarios totales + +portal.update.mode.des=Modo completo te da un motón de opciones de escritura de entrada adicionales ... incluyendo enviar a comunidades y fijar tu estado de ánimo y música actuales, y tu imagen de usuario. El modo sencillo es mejor si apenas utilizas esas funciones y preferirías no verlos siquiera. + +portal.update.mode.full=Completo + +portal.update.mode.name=Modo + +portal.update.mode.simple=Sencillo + +portal.update.portalname=Actualizar diario + +portal.update.portaltitle=Actualizar tu diario + +protocol.bad_password=Tu contraseña es demasiado fácil para adivinar. Se recomienda que lo cambies, de lo contrario hay riesgo de que alguien se apodere de tu diario. Visita [[siteroot]]/changepassword.bml para cambiar tu contraseña. + +protocol.hello_test=¡Hola, cuenta de prueba! + +protocol.mail_bouncing=Actualmente estás utilizando una dirección de correo electrónico errónea. Todo el correo que intentamos enviarte está siendo devuelto. [[sitename]] requiere una dirección válida para su uso continuo. Visita [[siteroot]]/support/faqbrowse.bml?faqid=19 para información sobre como cambiar tu dirección de correo electrónico. + +protocol.modpost=Tu entrada ha sido colocada en la cola de moderación. Será aceptada o rechazada por uno de los moderadores de la comunidad. + +protocol.must_revalidate=Debes validar tu nueva dirección. Tú dirección antigua estaba bien, pero dado que lo has cambiado, necesitas volver a validar la nueva. De lo contrario no podrás acceder a todas las funciones de [[sitename]]. Visita [[siteroot]]/support/faqbrowse.bml?faqid=11 para más información. + +protocol.not_validated=Tu dirección de correo electrónico no ha sido validada. Puedes seguir usando [[sitename]], pero si no tienes una dirección validada no podrás acceder a todas las funciones de la página. Sigue las instrucciones que te fueron enviadas cuando creaste tu diario o visita [[siteroot]]/support/faqbrowse.bml?faqid=11 para más información. + +protocol.old_win32_client=Hay clientes de LiveJournal para Windows más nuevos, y recomendamos que actualices el tuyo. Visita [[siteroot]]/download/ para descargar la última versión. + +protocol.readonly=Tu cuenta está temporalmente en modo de sólo lectura. Algunas operaciones fallarán durante un par de minutos. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Disculpa las molestias + +talk.anonwrote=Alguien escribió: + +talk.anonwrote_comm=Alguien escribió en [[commlink]]: + +talk.btn.preview=Vista previa + +talk.commentpermlink=enlace + +talk.commentpost=Escribir un comentario nuevo + +talk.commentsread=Leer comentarios + +talk.curname_Mood=Estado de ánimo actual: + +talk.curname_Music=Música actual: + +talk.error.bogusargs=Argumentos falsos + +talk.error.comm_deleted=Este comentario ha sido borrado. + +talk.error.deleted=Este diario se ha borrado. + +talk.error.deleted.title=Borrado + +talk.error.mustlogin=Hay que tener sesión iniciada para ver esta entrada protegida. + +talk.error.nocomment=Ese comentario no existe. + +talk.error.noentry=Esa entrada no existe + +talk.error.nojournal=Error: no se podía determinar el diario a partir de los argumentos. + +talk.error.nosuchjournal=Ese diario no existe + +talk.error.notauthorised=No estás autorizado para ver esta entrada protegida. + +talk.error.suspended=Este diario/usuario está suspendido. + +talk.error.suspended.title=Suspendido + +talk.parentlink=Mensaje origen + +talk.readsimilar=Leer entradas similares: + +talk.replytothis=Responder a esto + +talk.somebodywrote=[[realname]] ([[userlink]]) escribió + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) escribió en [[commlink]]: + +talk.spellcheck=Comprobar ortografía durante vista previa + +talk.threadlink=Cadena + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_espanol + +Username=Nombre de usuario + +userpic.inactive=Inactivo + +xcolibur.greeting.anon=¡Bienvenido a LiveJournal! + +xcolibur.greeting.logged_in=¡Bienvenido, [[name]]! [[logout]] + +xcolibur.login=¿Iniciar sesión? + +xcolibur.logout=¿Cerrar sesión? + +xcolibur.nav.about=Información + +xcolibur.nav.about.download=Descargar + +xcolibur.nav.about.general=Información general + +xcolibur.nav.about.paidaccounts=Cuentas pagadas + +xcolibur.nav.about.press=Prensa + +xcolibur.nav.about.sitenews=Noticias del sitio + +xcolibur.nav.about.stats=Estadísticas + +xcolibur.nav.footer.sitemap=Mapa del sitio Web + +xcolibur.nav.help=Ayuda + +xcolibur.nav.help.ask=¿Tienes pregunta? + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Contraseña perdida + +xcolibur.nav.home=Inicio + +xcolibur.nav.journal=Diario + +xcolibur.nav.journal.archive=Archivo + +xcolibur.nav.journal.edit.entries=Modificar entradas + +xcolibur.nav.journal.friends=Amigos + +xcolibur.nav.journal.info=Información + +xcolibur.nav.journal.memories=Memorias + +xcolibur.nav.journal.recent=Recientes + +xcolibur.nav.journal.update=Actualizar + +xcolibur.nav.manage=Administrar + +xcolibur.nav.manage.community=Comunidades + +xcolibur.nav.manage.customize=Personalizar + +xcolibur.nav.manage.entries=Entradas + +xcolibur.nav.manage.friends=Amigos + +xcolibur.nav.manage.info=Información + +xcolibur.nav.manage.password=Contraseña + +xcolibur.nav.manage.pics=Imágenes de usuario + +xcolibur.nav.search=Búsquedas + +xcolibur.nav.search.directory=Por región + +xcolibur.nav.search.directory.search=Avanzada + +xcolibur.nav.search.interests=Por intereses + +xcolibur.nav.search.random=Al azar + +xcolibur.nav.title=Navegar: + +xcolibur.nav.welcome=Bienvenido + +xcolibur.nav.welcome.create=Crear una cuenta + +xcolibur.nav.welcome.login=Iniciar sesión + +xcolibur.nav.welcome.update=Actualizar tu diario + +xcolibur.search=Buscar: + +xcolibur.search.category=Categoría + +xcolibur.search.icq=Número ICQ + +xcolibur.search.int=Interés + +xcolibur.search.msn=Nombre de MSN + +xcolibur.search.region=Región + +xcolibur.search.yahoo=ID Yahoo! + +xcolibur.upgrade=Aumenta tu cuenta + diff --git a/ljcom/bin/upgrading/et.dat b/ljcom/bin/upgrading/et.dat new file mode 100644 index 0000000..1451c1b --- /dev/null +++ b/ljcom/bin/upgrading/et.dat @@ -0,0 +1,13 @@ +;; -*- coding: utf-8 -*- +/allpics.bml.current=Käesolevad Pildid + +/allpics.bml.keywords=Võtmesõnad: + +/allpics.bml.nopics.text.other=See kasitaja ei ole üles laadinud ühtegi kasutaja pilti. + +/allpics.bml.nopics.title=Pildid Puuduvad + +/allpics.bml.pics=Siin on kasutaja pildid [[user]]le. + +/allpics.bml.title=Kasutaja Pildid + diff --git a/ljcom/bin/upgrading/fi.dat b/ljcom/bin/upgrading/fi.dat new file mode 100644 index 0000000..3cb2d60 --- /dev/null +++ b/ljcom/bin/upgrading/fi.dat @@ -0,0 +1,5137 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Muuta tilaa + +/accountstatus.bml.error.db=Pyyntöäsi käsiteltäessä on tapahtunut tietokantavirhe. + +/accountstatus.bml.error.invalid=Virheellinen tilatyyppi + +/accountstatus.bml.error.nochange.expunged=Tämä tili on poistettu tietokannasta. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Et voi vaihtaa päiväkirjan tilaa jäädytetystä. + +/accountstatus.bml.header.success=Onnistui + +/accountstatus.bml.journalstatus.about=Täällä voit poistaa tai palauttaa päiväkirjasi. Kun olet poistanut päiväkirjasi, sinulla on 30 päivää aikaa palauttaa se jos satut muuttamaan mieltäsi. 30 päivän kuluttua päiväkirja poistetaan lopullisesti, eikä sitä voi enää palauttaa. + +/accountstatus.bml.journalstatus.head=Päiväkirjan tila + +/accountstatus.bml.journalstatus.select.activated=Aktiivinen + +/accountstatus.bml.journalstatus.select.deleted=Poistettu + +/accountstatus.bml.journalstatus.select.head=Tila: + +/accountstatus.bml.journalstatus.select.suspended=Jäädytetty + +/accountstatus.bml.message.nochange=Päiväkirjasi on jätetty [[statusvis]]-tilaan. + +/accountstatus.bml.message.success=Päiväkirjasi on onnistuneesti muutettu [[statusvis]]-tilaan. + +/accountstatus.bml.title=Tilin tila + +/allpics.bml.current=Nykyiset kuvat + +/allpics.bml.default=Oletuskuva + +/allpics.bml.edit2=Saatat haluta muokata kuviesi avainsanoja tai ladata uuden kuvan. + +/allpics.bml.error.noparam=Sinun täytyy antaa syöte. (You need to specify a user parameter.) + +/allpics.bml.keywords=Avainsanat: + +/allpics.bml.nopics.text.other=Käyttäjällä ei ole yhtään kuvaa. + +/allpics.bml.nopics.text2=Et ole tallentanut yhtään kuvaa palvelimelle. Kuvia voit ladata täällä. + +/allpics.bml.nopics.title=Ei kuvia + +/allpics.bml.pics=Nämä ovat käyttäjän [[user]] kuvat. + +/allpics.bml.title=Käyttäjäkuvat + +/approve.bml.comm.success=Onnistui + +/approve.bml.comm.text<< +Sinut on lisätty yhteisöön [[comm]]. +Klikkaa tästä lisätäksesi yhteisön kaverilistallesi. +. + +/approve.bml.commjoin.text=Olet hyväksynyt käyttäjän [[user]] pyynnön liittyä yhteisöön [[comm]]. Klikkaa tästä päästäksesi jäsenlistaan määrittämään käyttäjän muut oikeudet. + +/approve.bml.error.actionperformed=Tämä toiminto on jo tehty + +/approve.bml.error.approving=Liittymispyyntöä käsiteltäessä tapahtui virhe. + +/approve.bml.error.internerr.invalidaction=Sisäinen virhe: kelpaamaton toiminto + +/approve.bml.error.invalidargument=Virheellinen argumentti syötetty + +/approve.bml.error.unknownactiontype=Tuntematon toimintotyyppi + +/approve.bml.shared.success=Onnistui + +/approve.bml.shared.text<< +Sinulle on annettu merkintäoikeus päiväkirjaan [[shared]]. +Klikkaa tästä lisätäksesi jaetun päiväkirjan kaverilistallesi. +. + +/approve.bml.title=Toiminnon hyväksyminen + +/birthdays.bml.description=Alla ovat kaverilistallasi olevien käyttäjien syntymäpäivät. + +/birthdays.bml.title=Syntymäpäivät + +/changepassword.bml.btn.proceed=Jatka + +/changepassword.bml.changepassword.header=Muuta salasanaa + +/changepassword.bml.changepassword.instructions=Täytä oheinen lomake muuttaaksesi salasanasi. Jos tarvitset apua keksiäksesi hyvän ja turvallisen salasanan, lue tämä FAQ. + +/changepassword.bml.email.body<< +[[sitename]]-salasanasi on muutettu. + +Tulevaisuudessa saat salasanasi takaisin osoitteesta: + + [[siteroot]]/lostinfo.bml + +Terveisin, +[[sitename]]-tiimi + +[[siteroot]] +. + +/changepassword.bml.email.subject=Salasanasi on vaihdettu + +/changepassword.bml.error.badcheck=Uusi salasana ei kelpaa: [[error]] + +/changepassword.bml.error.badnewpassword=Uudet salasanasi eivät ole samat. Kirjoita kumpikin uudestaan - luultavasti teit jommassa kummassa kirjoitusvirheen. + +/changepassword.bml.error.badoldpassword=Vanha salasanasi oli väärä. + +/changepassword.bml.error.blankpassword=Uusi salasanasi ei voi olla tyhjä. + +/changepassword.bml.error.changetestaccount=Testitilin salasanaa ei voi muuttaa. + +/changepassword.bml.error.characterlimit=Salasanan maksimipituus on 30 merkkiä. + +/changepassword.bml.error.invaliduser=Käyttäjä [[user]] ei kelpaa, sillä häntä ei ole olemassa. Kirjoititko käyttäjätunnuksen oikein? + +/changepassword.bml.error.mustenterusername=Sinun täytyy syöttää käyttäjätunnuksesi. + +/changepassword.bml.error.nonascii=Salasanoissa saa olla vain ASCII-merkkejä. Valitse salasana, jossa ei ole ASCIIhin kuulumattomia merkkejä. + +/changepassword.bml.error.notvalidated=Et voi muuttaa salasanaasi, ellei nykyistä sähköpostiosoitettasi ole varmennettu. Varmennusohjeet löydät täältä. + +/changepassword.bml.newpassword=Uusi salasana: + +/changepassword.bml.newpasswordagain=Uusi salasana (uudestaan): + +/changepassword.bml.oldpassword=Nykyinen salasana: + +/changepassword.bml.proceed.instructions=Paina alla olevaa nappia ja salasanasi vaihtuu. Saat myös salasanan muuttumisesta muistuttavan sähköpostin. + +/changepassword.bml.relogin=Lisäksi sinut on kirjattu ulos kaikista olemassa olevista istunnoistasi. Kirjaudu uudelleen sisään ennen kuin jatkat. + +/changepassword.bml.success.text=Salasanasi on muutettu ja sinulle on lähetty muistutusviestin sisältävä sähköposti. + +/changepassword.bml.title=Salasanan vaihtaminen + +/community/index.bml.main<< + + + + +Uusien käyttäjien tiloihin, josta löytyy vastaus moniin kysymyksiin, joita sinulla ehkä on. Käy yhteisössä , katsele hieman ympärillesi ja olet ammattilainen hetkessä! +p?> + + +
      +Lisää ystäväsivullesi ja pysyt perillä ajankohtaisistatapahtumista ja -aiheista, joilla on merkitystä koko LiveJournal yhteisölle. +Lisää ystäväsivullesi saadaksesi tietoa suunnitelluista palvelun keskeytyksiä ja lukeaksesi raportteja suunnittelemattomista häiriöistä palvelussa. +p?> + + +AIM, ICQ, Yahoo!, MSN tai Jabber. Jos käytät jotakin näistä, kerro se käyttäjätiedoissasi. Jos sinulla on maksettu tili, voit myös vastaanottaa tekstiviestejä kännykkääsi tai hakulaitteeseesi. +p?> + + +maksetun tilin hankkiminen. On tietysti myös lukuisia muita tapoja auttaa. +

      +LiveJournal on avoimen lähdekoodin projekti; jos sinulla on kokemusta ohjelmointikielistä tai server side -sovelluksista voit vilkaista LiveJournalin kehittämisyhteisöäa, . Jos sinulla on ajatuksia LiveJournalin parantamiseksi, vilkaise LiveJournalin ehdotusaluettaa, . Jos haluaisit auttaa melkeinpä missä tahansa, käy LiveJournalin businessyhteisössässä, . Jos pidät ihmisten auttamisesta, käy teknisen tuen keskuksessa ja auta jotakuta. Jos osaat suunnitella grafiikkaa, vilkaise LiveJournalin taideyhteisöäa, . +p?> + + +Animesta Zen-buddhalaisuuteen ja Astronomiasta Zimiin. Löydät myös paikallisia yhteisöjä kaikilta maailmankolkilta. Omalla asuinpaikallasikin on jo luultavasti LiveJournal-yhteisö! +p?> + + +FAQ-kysymyksessä selitetään, kuinka luot aivan oman yhteisön. On olemassa myös kaksi FAQ-luokkaa (Yhteisöt ja Yhteisön hallinta), jotka kattavat lähes kaiken tiedon jota kaipaat yhteisöistä. Jos tarvitset vielä enemmän tietoa, elä epäröi pyytää apua. +p?> + + + + +
        +
      • Katso edistämisyhteisöä()
      • +
      • Katso hakuyhteisöä()
      • +
      + + +Lähetä sähköpostia Jesse Proulxille, (), LiveJournalin yhteisövastaavalle. +p?> +. + +/community/index.bml.title=Yhteisökeskus + +/community/join.bml.button.join=Liity yhteisöön + +/community/join.bml.error.already.member=Olet jo tämän yhteisön jäsen. + +/community/join.bml.error.closed=Tämä yhteisö on suljettu uusilta jäseniltä. Jos haluat liittyä, ota yhteyttä seuraaviin ylläpitäjiin: [[admins]] + +/community/join.bml.error.statusvis.body=Sisäänkirjautunut tilisi ei ole aktiivinen. + +/community/join.bml.error.statusvis.title=Yhteisöön liittyminen mahdotonta + +/community/join.bml.label.addtofriends=Lisää "[[maintainer]]" kaverilistallesi.
      + +/community/join.bml.label.allowposting=Tässä yhteisössä kaikki sen jäsenet voivat lähettää viestejä, joten voit nyt tehdä niin. Jos tietokoneellasi on LiveJournalin päivitysohjelma käynnissä, sinun täytyy sulkea se ja kirjautua uudestaan sisään. Muuten tämä päiväkirja ei näy siinä listassa josta valitaan mihin päiväkirjaan lähetät viestisi. + +/community/join.bml.label.auth=Vaikka oletkin nyt yhteisön jäsen, vain lähettämisoikeuden saaneet käyttäjät voivat lähettää viestejä siihen. Ota yhteyttä yhteisön ylläpitäjiin, jos haluat saada lähetysoikeuden. Yhteisön ylläpitäjät ovat: [[admins]] + +/community/join.bml.label.banned=Tämän yhteisön ylläpitäjä on (tai ylläpitäjät ovat) estäneet sinun liittymisesi yhteisöön. + +/community/join.bml.label.closed=Tämä yhteisö on suljettu. Jos haluat liittyä siihen, ota yhteyttä yhteen sen ylläpitäjistä. Tämän yhteisön ylläpitäjät ovat: [[admins]] + +/community/join.bml.label.commlogged=Olet kirjautunut sisään jaettuun tai yhteisötiliin, et henkilökohtaiseen tiliisi. + +/community/join.bml.label.errorcomminfo=Syötetyt yhteisötiedot eivät kelpaa. + +/community/join.bml.label.expls=Paina oheista nappia liittyäksesi yhteisöön nimeltä "[[maintainer]]". Poista ruksi valinnasta, jos haluat liittyä yhteisöön muttet halua nähdä yhteisön viestejä kaverisivullasi. + +/community/join.bml.label.loginfirst=Liittyäksesi yhteisöön sinun on kirjauduttava sisään. + +/community/join.bml.label.membernow=Nyt olet yhteisön [[commname]] jäsen. + +/community/join.bml.label.sure=Oletko varma? + +/community/join.bml.reqsubmitted.body=Liittymispyyntösi on lähetetty ylläpitäjille: + +/community/join.bml.reqsubmitted.title=Liittymispyyntö lähetetty + +/community/join.bml.request.body=Yhteisössä [[comm]] ei ole vapaata jäsenyyttä. Varmista yhteisöön liittyminen klikkaamalla alta. + +/community/join.bml.request.reason=Valinnaisesti, anna syy liittymisellesi: + +/community/join.bml.request.title=Liittymispyyntö + +/community/join.bml.success=Onnistui + +/community/join.bml.title=Liity yhteisöön + +/community/leave.bml.button.leave=Poistu yhteisöstä + +/community/leave.bml.label.buttontoleave=Paina oheista nappia erotaksesi yhteisöstä "[[commname]]". + +/community/leave.bml.label.infoerror=Syötetyt yhteisötiedot eivät kelpaa. + +/community/leave.bml.label.logoutfirst=Poistuaksesi yhteisöstä sinun on kirjaudattuva sisään. + +/community/leave.bml.label.removed=Et ole enää [[commname]]-yhteisön jäsen. + +/community/leave.bml.label.removefromfriends=Poista käyttäjä "[[user]]" myös kaverilistalta. + +/community/leave.bml.success=Onnistui + +/community/leave.bml.sure=Oletko varma? + +/community/leave.bml.title=Eroa yhteisöstä + +/community/manage.bml.commlist.actinfo=Tietoa + +/community/manage.bml.commlist.actions=Vaihtoehdot + +/community/manage.bml.commlist.actmembers=[Jäsenet] + +/community/manage.bml.commlist.actmembers2=Jäsenet + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] odottaa hyväksyntää + +/community/manage.bml.commlist.actsettings= [Asetukset] + +/community/manage.bml.commlist.actsettings2=Asetukset + +/community/manage.bml.commlist.header=Sinun yhteisösi + +/community/manage.bml.commlist.moderation=Odottaa moderointia + +/community/manage.bml.commlist.moderation.num=[[[num]] jonossa] + +/community/manage.bml.commlist.none=Et ole minkään yhteisön ylläpitäjä. + +/community/manage.bml.commlist.text=Olet näiden yhteisöjen ylläpitäjä - joko yksin tai muiden kanssa: + +/community/manage.bml.commlist.title=Nimi + +/community/manage.bml.commlist.username=Käyttäjätunnus + +/community/manage.bml.create.header=Luo yhteisö + +/community/manage.bml.create.text=Voit myös luoda uuden yhteisön. + +/community/manage.bml.joinmail.body=Yhteisöille, joissa on suljettu jäsenyys, on useita sähköpostivaihtoehtoja: + +/community/manage.bml.joinmail.email.all=Lähetä sähköpostiviesti aina kun joku pyytää liittymislupaa + +/community/manage.bml.joinmail.email.digest=Joka päivä yksi sähköpostiviesti, jossa on odottavien pyyntöjen lista + +/community/manage.bml.joinmail.email.none=Ei sähköpostia, käytän tätä sivua seuratakseni uusia pyyntöjä + +/community/manage.bml.joinmail.save=Tallenna asetukset + +/community/manage.bml.joinmail.title=Hallinta-asetukset + +/community/manage.bml.title=Yhteisöjen hallinta + +/community/members.bml.error.alreadyadded=Käyttäjää [[user]] ei lisätty, koska hänellä on jo oikeudet tähän yhteisöön. + +/community/members.bml.error.alreadysent=Käyttäjää [[user]] ei voitu lisätä koska heille on jo lähetetty vahvistussähköposti [[datetime]]. Ole hyvä ja odota heidän vastaustaan. + +/community/members.bml.error.invaliduser=Et voi lisätä yhteisöä tai syndikoitua tiliä: [[user]] + +/community/members.bml.error.noaccess=Vain yhteisön ylläpitäjät voivat muokata jäsenlistoja. Sinä et ole yhteisön [[comm]] ylläpitäjä. + +/community/members.bml.error.noattr=Käyttäjälle [[user]] ei ole määritelty ominaisuuksia. + +/community/members.bml.error.nocomm=Yhteisöä ei löytynyt. + +/community/members.bml.error.nouser=Käyttäjää [[user]] ei ole olemassa. + +/community/members.bml.key.admin=Ylläpitäjä + +/community/members.bml.key.member=Jäsen + +/community/members.bml.key.moderate=Moderaattori + +/community/members.bml.key.post=Lähetysoikeus + +/community/members.bml.key.preapprove=Moderoimaton + +/community/members.bml.key.user=Käyttäjä + +/community/members.bml.manage2=Yhteisöjen hallinta + +/community/members.bml.name=Yhteisön nimi: [[name]] + +/community/members.bml.nextlink=(Seuraava sivu) + +/community/members.bml.prevlink=(Edellinen sivu...) + +/community/members.bml.settings= [Asetukset] + +/community/members.bml.success.header=Onnistui! + +/community/members.bml.success.message=Muutokset tallennettiin onnistuneesti. + +/community/members.bml.success.return= Palaa listaan + +/community/members.bml.title=Yhteisön jäsenet + +/community/members.bml.update=Päivitä asetukset + +/community/moderate.bml.approve.button=Hyväksy + +/community/moderate.bml.approve.header=Hyväksytkö tämän merkinnän? + +/community/moderate.bml.approve.preapprove=Lisää käyttäjä [[user]] tämän yhteisön automaattisesti hyväksyttävien käyttäjien listalle. + +/community/moderate.bml.approve.text=Haluatko hyväksyä tämän merkinnän? + +/community/moderate.bml.brlist.actions=Toiminnot + +/community/moderate.bml.brlist.poster=Lähettäjä + +/community/moderate.bml.brlist.subject=Aihe alkaa + +/community/moderate.bml.brlist.time=Aika + +/community/moderate.bml.brlist.view=Näytä + +/community/moderate.bml.browse.empty=Moderoimisjono on tyhjä. + +/community/moderate.bml.browse.header=Moderoi yhteisöä + +/community/moderate.bml.browse.text=Tässä on yhteisön [[link]] moderointijono. + +/community/moderate.bml.choice.approve=Hyväksy + +/community/moderate.bml.choice.bkapprove=#82dd88 + +/community/moderate.bml.choice.bkreject=#e08291 + +/community/moderate.bml.choice.reject=Hylkää + +/community/moderate.bml.error.noaccess=Et ole yhteisön [[comm]] moderoija. + +/community/moderate.bml.error.noentry=Merkintää ei löytynyt (ehkäpä sitä käsitteli jo toinen moderaattori). + +/community/moderate.bml.error.nolist=Et ole yhdenkään yhteisön moderoija. + +/community/moderate.bml.error.notfound=Yhteisöä ei löytynyt. + +/community/moderate.bml.manage=Yhteisöjen hallinta + +/community/moderate.bml.moderate=Moderoi tätä yhteisöä + +/community/moderate.bml.modlist.actions=Toiminnot + +/community/moderate.bml.modlist.actmodempty=[Moderoi] + +/community/moderate.bml.modlist.actmoderate=Moderoi + +/community/moderate.bml.modlist.count=Jonon koko + +/community/moderate.bml.modlist.header=Moderoi yhteisöjä + +/community/moderate.bml.modlist.title=Otsikko + +/community/moderate.bml.modlist.username=Käyttäjätunnus + +/community/moderate.bml.posted.appheader=Ennalta hyväksytty + +/community/moderate.bml.posted.apptext=Lisäksi käyttäjä [[user]] on lisätty automaattisesti hyväksyttävien kirjoittajien listaan. + +/community/moderate.bml.posted.header=Onnistui + +/community/moderate.bml.posted.proterror=Merkintää ei lähetetty seuraavan protokollavirheen vuoksi: [[err]] + +/community/moderate.bml.posted.text=Merkintä lähetettiin onnistuneesti. + +/community/moderate.bml.reject.button=Hylkää + +/community/moderate.bml.reject.header=Hylkäätkö tämän merkinnän? + +/community/moderate.bml.reject.reason=Voit myös selittää merkinnän lähettäjälle, miksi hylkäsit sen. Selitys lähetetään merkinnän tekijälle sähköpostitse. + +/community/moderate.bml.reject.text=Haluatko varmasti hylätä tämän merkinnän? + +/community/moderate.bml.rejected.header=Hylätty + +/community/moderate.bml.rejected.text=Merkintä on hylätty. + +/community/moderate.bml.title=Yhteisön moderointi + +/community/pending.bml.approve.title=Hyväksy jäsenyys? + +/community/pending.bml.no=Ei + +/community/pending.bml.nopending.body=Tälle yhteisölle ei ole odottavia jäsenpyyntöjä. + +/community/pending.bml.nopending.title=Ei odottavia pyyntöjä + +/community/pending.bml.success.added=Olet lisännyt [[num]] [[?num|henkilön|henkilöä]] tähän yhteisöön. + +/community/pending.bml.success.ignored=[[num]] [[?num|pyyntö|pyyntöä]] odottaa päätöstä. + +/community/pending.bml.success.previous=[[num]] [[?num|pyyntöä|pyyntöä]] ei käsitelty, koska [[?num|se ei enää ollut|ne eivät enää olleet]] odotustilassa. Toinen ylläpitäjä on ilmeisesti käsitellyt [[?num|sen|ne]] jo. + +/community/pending.bml.success.rejected=Olet kieltänyt [[num]] [[?num|liittymispyynnön|liittymispyyntöä]]. + +/community/pending.bml.title=Odottavat jäsenpyynnöt + +/community/pending.bml.yes=Kyllä + +/community/search.bml.button.clear=Tyhjennä lomake + +/community/search.bml.button.search=Hae! + +/community/search.bml.checkbox.onlywithpics=Vain yhteisöt, joille on määritelty käyttäjäkuva. + +/community/search.bml.label.byinterest=Kiinnostuksenkohde + +/community/search.bml.label.bylocation=Sijainti + +/community/search.bml.label.bytime=Päivittämisajankohta + +/community/search.bml.label.city=Paikkakunta: + +/community/search.bml.label.country=Maa: + +/community/search.bml.label.displayoptions=Esitysasetukset + +/community/search.bml.label.hasmember=Käyttäjä + +/community/search.bml.label.othercriteria=Muut kriteerit + +/community/search.bml.label.outputformat=Tulosten muoto: + +/community/search.bml.label.records=Tuloksia sivua kohti: + +/community/search.bml.label.searchcomm=Yhteisöhaku + +/community/search.bml.label.selecriteria=Valitse ne ehdot, joilla haluat etsiä yhteisöjä. Tulokset täyttävät kaikki antamasi hakuehdot. Toisin sanoen jokainen valinta tarkoittaa "JA" eikä "TAI". + +/community/search.bml.label.sortmethod=Järjestä tulokset tämän mukaisesti: + +/community/search.bml.label.stateprovince=Osavaltio tai maakunta: + +/community/search.bml.label.updated=Päivitetty tämän ajan kuluessa: + +/community/search.bml.sel.bypicture=Kuvien kera + +/community/search.bml.sel.communityname=Yhteisön nimi + +/community/search.bml.sel.commview=Yhteisönäkymä + +/community/search.bml.sel.day=päivä + +/community/search.bml.sel.month=kuukausi + +/community/search.bml.sel.simple=Yksinkertainen + +/community/search.bml.sel.updatetime=Viimeisin päivitys + +/community/search.bml.sel.username=Käyttäjätunnus + +/community/search.bml.sel.week=viikko + +/community/search.bml.title=Yhteisöhaku + +/community/settings.bml.button.changecommunity=Päivitä asetukset + +/community/settings.bml.button.createcommunity=Luo yhteisö + +/community/settings.bml.error.badpassword=Yhteisön salasana ei kelpaa + +/community/settings.bml.error.hasentries=Tilillä on jo merkintöjä, eikä sitä voi siksi muuntaa. + +/community/settings.bml.error.maintainertype=Ylläpitäjän tilin täytyy kuulua henkilölle eikä olla jaettu tili. + +/community/settings.bml.error.noaccess=Vain yhteisön ylläpitäjät voivat muokata yhteisön asetuksia. Sinä et ole yhteisön [[comm]] ylläpitäjä. + +/community/settings.bml.error.notcomm=Tili ei ole yhteisön tili + +/community/settings.bml.error.notfound=Yhteisön tiliä ei löytynyt + +/community/settings.bml.error.samenames=Ylläpitäjän tili ja yhteisön tili eivät voi olla samat + +/community/settings.bml.label.anybodycan=Kaikki jäsenet
      Kuka tahansa voi lähettää viestejä heti kun hän on jäsen. + +/community/settings.bml.label.changeheader=Muuta yhteisön asetuksia + +/community/settings.bml.label.changetext=Tästä voit muuttaa omistamasi tai ylläpitämäsi yhteisön asetuksia. + +/community/settings.bml.label.closedmemb2=Suljettu jäsenyys
      Kukaan ei voi liittyä yhteisöön. + +/community/settings.bml.label.commchanged=Yhteisösi asetuksia on muutettu. + +/community/settings.bml.label.commcreate=Tämä on se tili, jonka haluat muuttaa yhteisöksi. Sen täytyy olla luotu, mutta sen ei pitäisi vielä olla kenenkään käytössä, sillä luomisen jälkeen hyvin monet ihmiset voivat halutessaan lähettää siihen viestejä. + +/community/settings.bml.label.commcreated=Yhteisösi on nyt käyttövalmis. + +/community/settings.bml.label.commheader=Yhteisön tili + +/community/settings.bml.label.comminfo=Yhteisön tiedot + +/community/settings.bml.label.commopts=Yhteisön asetukset + +/community/settings.bml.label.commsite=Yhteisön kotisivu + +/community/settings.bml.label.community=Yhteisö: + +/community/settings.bml.label.createheader=Luo yhteisö + +/community/settings.bml.label.createtext=Täällä voit luoda yhteisön tilin. Yhteisö on erityinen tili, johon muut käyttäjät voivat liittyä ja lähettää viestejä. Esimerkki yhteisöstä on Seattle Party Community. + +/community/settings.bml.label.howoperates=Valitse, kuinka yhteisösi toimii. Voit muuttaa näitä asetuksia myöhemmin. + +/community/settings.bml.label.maintainer=Ylläpitäjä: + +/community/settings.bml.label.maintainer.login=Jos tämä ei ole yhteisön ylläpitäjän tili, kirjaudu sisään jonakuna toisena. + +/community/settings.bml.label.managepage=Yhteisöjen hallinta - lisää jäseniä, myönnä merkinnänteko-oikeudet, valitse moderaattoreita, jne. + +/community/settings.bml.label.membership=Jäsenyys + +/community/settings.bml.label.moderatedmemb=Moderoitu jäsenyys
      Liittymispyynnöt lähetetään sähköpostilla sinulle hyväksyttäviksi. + +/community/settings.bml.label.modheader=Moderointi + +/community/settings.bml.label.modis=Moderoitu
      Moderaattorin täytyy hyväksyä uudet merkinnät. + +/community/settings.bml.label.modisnt=Moderoimaton
      Uudet merkinnät ilmestyvät yhteisöön heti. + +/community/settings.bml.label.modtext=Ovatko kirjoitukset tähän yhteisöön moderoituja? + +/community/settings.bml.label.nmcan=Ei-jäsenet voivat lähettää viestejä
      Käyttäjät voivat lähettää viestejä tähän yhteisöön liittymättä jäseneksi. + +/community/settings.bml.label.nmcant=Ei-jäsenet eivät voi lähettää viestejä
      Käyttäjien täytyy liittyä tähän yhteisöön ennen, kuin he voivat lähettää siihen viestejä. + +/community/settings.bml.label.nmheader=Yhteisöön kuulumattomien oikeudet + +/community/settings.bml.label.nmtext=Voivatko käyttäjät lähettää viestejä yhteisöön liittymättä siihen? + +/community/settings.bml.label.openmemb=Avoin jäsenyys
      Kuka tahansa voi liittyä ilman erillistä hyväksymistä. + +/community/settings.bml.label.password=Salasana: + +/community/settings.bml.label.postaccess=Lähetysoikeudet + +/community/settings.bml.label.rellinks=Linkit: + +/community/settings.bml.label.selcan=Valitut jäsenet
      Vain tietyt jäsenet voivat lähettää viestejä, kunhan ylläpitäjä on antanut heille lähetysoikeuden. + +/community/settings.bml.label.username=Käyttäjätunnus: + +/community/settings.bml.label.whocanjoin=Kuka voi liittyä yhteisöön? + +/community/settings.bml.label.whocanpost=Kuka voi lähettää viestejä yhteisöön? + +/community/settings.bml.manage2=Yhteisöjen hallinta + +/community/settings.bml.members= [Jäsenet] + +/community/settings.bml.name=Yhteisön nimi: [[name]] + +/community/settings.bml.success=Onnistui! + +/community/settings.bml.title.create=Luo yhteisö + +/community/settings.bml.title.modify=Yhteisön asetukset + +/create.bml.age.check.question=Oletko alle 13-vuotias? + +/create.bml.age.check.yes=Kyllä, olen alle 13-vuotias. + +/create.bml.age.check2.question=Oletko yli 13-vuotias? + +/create.bml.age.check2.yes=Kyllä, olen yli 13-vuotias. + +/create.bml.age.head=Ikä + +/create.bml.btn.create=Luo päiväkirja + +/create.bml.btn.proceed=Jatka... + +/create.bml.captcha.answer=Vastaus: + +/create.bml.captcha.audiodesc=Kirjoita kuulemasi numerot todistaaksesi ettet ole roskapostirobotti: + +/create.bml.captcha.desc=Kirjoita alla näkyvät kirjaimet ja numerot todistaaksesi ettet ole roskapostirobotti. Jos et voi lukea tekstiä, kirjoita "AUDIO" ja tee tämän sijaan äänitesti. + +/create.bml.captcha.invalid=Väärä vastaus edelliseen haasteeseen. Yritä uudestaan. + +/create.bml.captcha.play=Toista ääni + +/create.bml.captcha.prove=Todista, että olet ihminen + +/create.bml.clusterselect.cluster=Tiedontallennusryhmä: + +/create.bml.clusterselect.clusternum=Tiedontallennusryhmä [[number]] + +/create.bml.clusterselect.head=Tiedontallennusryhmän valinta + +/create.bml.clusterselect.nocluster=Ei tiedontallennusryhmää + +/create.bml.clusterselect.text=Valitse se tiedontallennusryhmä, johon haluat luoda tämän tilin. Huom: Tämä asetus on vain debuggausta ja testausta varten. Tuotantokäytössä ("in production") käyttäjät eivät valitse tai edes tiedä tästä mitään. + +/create.bml.create.head=Uuden päiväkirjan luonti + +/create.bml.create.text=Uuden päiväkirjan luominen on helppoa - seuraa vain ohjeita! + +/create.bml.email.head=Sähköpostiosoitteesi: + +/create.bml.email.input.head=E-mail: + +/create.bml.email.text2=Tarvitsemme sähköpostiosoitteesi varmistus- ja turvallisuussyistä. Sitä ei missään tilanteessa myydä tai luovuteta roskapostin lähettäjille. Inhoamme sitä yli kaiken. Lue yksityisperiaatteemme saadaksesi lisätietoja. + +/create.bml.error.coppa.under13=Valitettavasti COPPA-rajoitusten vuoksi et voi käyttää LiveJournal-palvelua ennen kuin olet 13-vuotias. Voit tulla takaisin 13. syntymäpäivänäsi. + +/create.bml.error.email.blank=Sinun on annettava sähköpostiosoite. + +/create.bml.error.email.lj_domain=Et voi käyttää [[domain]]-aliasta tiliä luotaessa. Anna toinen sähköpostiosoite. + +/create.bml.error.email.nospaces=Sähköpostiosoitteessa ei saa olla välilyöntejä. Jos käytät AOL:a, muista, että Internet-osoitteesi on "screen name" ilman välilyöntejä plus @aol.com. + +/create.bml.error.password.asciionly=Salasanassa voi olla vain ASCII-merkkejä. + +/create.bml.error.password.blank=Sinun täytyy antaa salasana. + +/create.bml.error.password.nomatch=Salasanat ovat erilaiset. + +/create.bml.error.postrequired=POST-metodi on oltava käytettävissä. (POST required.) + +/create.bml.error.username.blank=Sinun pitää syöttää nimi tai nimimerkki. + +/create.bml.error.username.inuse=Käyttäjätunnus on jo olemassa. Ole hyvä ja valitse toinen käyttäjätunnus. + +/create.bml.error.username.iscode=Käyttäjätunnuksesi näyttää olevan kutsukoodi eikä käyttäjätunnus. + +/create.bml.error.username.mustenter=Sinun on annettava käyttäjätunnus. + +/create.bml.error.username.reserved=Antamasi käyttäjätunnus on jo varattu. + +/create.bml.errors.label=Huomaa seuraavat ongelmat ja lähetä lomake uudestaan: + +/create.bml.initial.friend.lj_maintenance=Ilmoitukset suunnitelluista ja suunnittelemattomista katkoksista ja huoltoajoista + +/create.bml.initial.friend.news=LiveJournalin uutiset ja tapahtumat + +/create.bml.initialfriends=Lisää nämä päiväkirjat kaverilistallesi saadaksesi ajantasaisia tietoja sivuston uutisista. + +/create.bml.initialfriends.heading=Aloituskaverit + +/create.bml.name.head=Nimesi + +/create.bml.name.input.head=Nimi: + +/create.bml.name.text=Mikä on nimesi tai nimimerkkisi? Tämä näkyy päiväkirjasi yläreunassa ja käyttäjälistassa, jos haluat itsesi listattavaksi siihen. Sinun ei tarvitse antaa koko tai edes oikeaa nimeäsi. + +/create.bml.password.head=Salasana + +/create.bml.password.input.head1=Salasana: + +/create.bml.password.input.head2=Anna salasana uudestaan: + +/create.bml.password.text=Valitse salasana. + +/create.bml.proceed.btn.proceed=Jatka... + +/create.bml.proceed.warning=Paina Jatka-nappia vain kerran! + +/create.bml.success.btn.enterinfo=Anna henkilötietosi + +/create.bml.success.head=Onnistui! + +/create.bml.success.text1=Päiväkirjasi on luotu. Tärkeitä rekisteröitymistietoja on lähetetty osoitteeseen [[email]]. Muista varmistaa päiväkirjasi luonti klikkaamalla sinulle sähköpostissa lähetettyä linkkiä. + +/create.bml.success.text2=Päiväkirjasi löytyy osoitteesta: + +/create.bml.success.text3=Jos suinkin ehdit, niin pyydämme sinua antamaan joitain tietoja itsestäsi. Tämä on suurimmalta osalta valinnaista, mutta siten saamme jotain käsitystä siitä, kuka käyttää LiveJournalia. + +/create.bml.title=Luo uusi päiväkirja + +/create.bml.tos.error=Sinun täytyy lukea ja hyväksyä käyttöehdot ennen tilin luomista. + +/create.bml.tos.haveread=Olen lukenut käyttöehdot ja hyväksyn ne. + +/create.bml.tos.heading=Käyttöehdot + +/create.bml.tos.p1.2=Ennen kuin jatkat, lue ja hyväksy käyttöehdot. + +/create.bml.useacctcodes.entercode=Anna tilinluontikoodi luodaksesi uuden tilin. Saadaksesi lisätietoja, ks. Kuinka luon tilin? + +/create.bml.useacctcodes.welcome=Tervetuloa + +/create.bml.username.box.head=Käyttäjätunnus: + +/create.bml.username.charsallowed=Käyttäjänimessäsi saa olla vain pikkukirjaimia (a-z), numeroita (0-9) ja alaviivaa (_).
      Tämän lisäksi se ei saa olla 15 merkkiä pidempi. + +/create.bml.username.forpaidaccts=Tai (vain maksetut tilit): + +/create.bml.username.head=Käyttäjätunnus + +/create.bml.username.ljaddress=Päiväkirjasi sijaitsee näissä osoitteissa: + +/create.bml.username.text=Jokaisella [[sitename]]-käyttäjällä on oltava yksilöllinen käyttäjätunnus. Käyttäjätunnuksesi esiintyy päiväkirjasi osoitteessa, ja käytät sitä myös kirjautuessasi [[sitename]]-palvelimelle. Lisäksi se näkyy muiden käyttäjien päiväkirjoihin jättämissäsi kommenteissa. + +/create.bml.username.username=käyttäjätunnus + +/customize/index.bml.change=Muuta + +/customize/index.bml.choose=Haluatko käyttää vanhaa vai uutta tyylijärjestelmää? + +/customize/index.bml.choose.header=Valitse tyylijärjestelmä + +/customize/index.bml.choose.s1=Vanha järjestelmä (S1) + +/customize/index.bml.choose.s2=Uusi järjestelmä (S2) + +/customize/index.bml.error.cant_generate_user_layer=Käyttäjäkerrosta ei voidu luoda. (Could not generate user layer) + +/customize/index.bml.error.fail_create_style=Uuden tyylin luominen epäonnistui. + +/customize/index.bml.error.not_your_layout=Ei sinun ulkoasusi. + +/customize/index.bml.error.not_your_theme=Ei sinun teemasi + +/customize/index.bml.error.no_core_parent=Ei alkuperäistä lähdettä? (No core parent?) + +/customize/index.bml.previews=(Esikatselut) + +/customize/index.bml.s1=Vanhaa tyylijärjestelmää käytetään Muokkaa päiväkirjaa -sivulla. + +/customize/index.bml.s1.header=S1:n käyttäminen + +/customize/index.bml.s2.advanced.denied=Vain maksetut, pysyvät tai varhaisen mukaantulijan tilit voivat käyttää kehittyneempää tyylinmuokkausta. Ota selvää maksettujen tilien ominaisuuksista. + +/customize/index.bml.s2.advanced.header=Kehittynyt tyylinmuokkaus + +/customize/index.bml.s2.advanced.permitted=Luodaksesi uusia kerroksia ja tyylejä, käy kehittyneen tyylinmuokkauksen järjestelmässä. + +/customize/index.bml.s2.customize=Seuraavat asetukset ovat tyyliriippuvaisia. + +/customize/index.bml.s2.customize.header=Vaihe 2: Muokkaa tyyliä + +/customize/index.bml.s2.customize.language=Seuraavat kielet ovat kokonaan tai osittain tuettuja tässä tyylissä. + +/customize/index.bml.s2.customize.language.custom=(Mukautettu) + +/customize/index.bml.s2.customize.language.header=Kieli + +/customize/index.bml.s2.customize.settings=Jos haluat muokata päiväkirjaasi enemmän, täällä voit muuttaa yksittäisiä asetuksia saadaksesi sen näyttämään juuri sellaiselta kuin haluat. + +/customize/index.bml.s2.customize.settings.delete=Poista muokkaukset + +/customize/index.bml.s2.customize.settings.delete.confirm=Haluatko varmasti poistaa nämä muokkaukset? + +/customize/index.bml.s2.customize.settings.edit=Muuta muokkauksia + +/customize/index.bml.s2.customize.settings.header=Vaihda yksittäisiä asetuksia + +/customize/index.bml.s2.customize.settings.new=Mukauta + +/customize/index.bml.s2.customize.themes=Valitse seuraavista tämän ulkoasun mahdollisista teemoista: + +/customize/index.bml.s2.customize.themes.default=(Oletusulkoasu) + +/customize/index.bml.s2.customize.themes.header=Teemat + +/customize/index.bml.s2.layout=Valitse ulkoasu. Koska teeman valinta ja valinnaiset muokkaukset riippuvat ulkoasusta, poistaa tämän asetuksen vaihtaminen kaikki tekemäsi muokkaukset. + +/customize/index.bml.s2.layout.header=Vaihe 1: Ulkoasu + +/customize/index.bml.s2.related.editinfo.about=Muuta päiväkirjasi otsikoita ja muita asetuksia. + +/customize/index.bml.s2.related.header=Mukaankuuluvat sivut + +/customize/index.bml.s2.related.links.about=Jotkin tyylit voivat sisältää linkkilistasi. + +/customize/index.bml.s2.related.modify.about=Valitse päiväkirjasi mielialakuvakkeet. + +/customize/index.bml.title=Muokkaa päiväkirjaa + +/delcomment.bml.changeoptions<< +Huomaa: [[link]] -sivulla voit valita annatko kaikkien, vain rekisteröityneiden käyttäjien, tai +vain kavereiden jättää kommentteja. +. + +/delcomment.bml.confirm.banuser=Estä käyttäjän [[user]] kommentointi päiväkirjassasi + +/delcomment.bml.confirm.body=Haluatko varmasti poistaa tämän kommentin? + +/delcomment.bml.confirm.head=Poista kommentti? + +/delcomment.bml.confirm.spam=Merkitse tämä kommentti roskapostiksi + +/delcomment.bml.confirm.submit=Poista kommentti + +/delcomment.bml.error.alreadydeleted=Valittu kommentti on jo poistettu. + +/delcomment.bml.error.cantdelete=Kommentin voi poistaa vain sen tekijä tai päiväkirjan omistaja. + +/delcomment.bml.error.cantdelete.comm=Kommentin voi poistaa vain sen tekijä, merkinnän tekijä tai yhteisön ylläpitäjä. + +/delcomment.bml.error.invalidtype=Virheellinen kommenttityyppi. Tämä sivu käsittelee vain päiväkirjamerkintöjen kommentit. + +/delcomment.bml.error.nocomment=Valittua kommenttia ei ole olemassa. + +/delcomment.bml.success.andban=Kommentti on poistettu ja käyttäjän [[user]] kommentointi on estetty päiväkirjassasi. + +/delcomment.bml.success.head=Poistettu + +/delcomment.bml.success.noban=Kommentti on poistettu. + +/delcomment.bml.success.spam=Tämän lisäksi valvojille on lähetetty tieto siitä, että kommentti oli roskapostia. Kiitos ilmoituksestasi. + +/delcomment.bml.title=Poista kommentti + +/developer/index.bml.clients=Haluat siis tehdä LiveJournalin päivitysohjelman käyttöjärjestelmällesi? Hienoa! Alla on muutamia tarpeellisia lähteitä joista saat tietoa LiveJournalin toiminnasta. + +/developer/index.bml.clients.header=LiveJournalin päivitysohjelmien kirjoittaminen + +/developer/index.bml.clients.links<< +
      +
      LiveJournalin Palvelin<->Päivitysohjelma -protokolla
      +
      Opi kuinka tietokoneellasi oleva päivitysohjelma keskustelee palvelimen kanssa ja päinvastoin. Tämän asian ymmärtäminen on ensimmäinen askel kehittäessäsi omalle käyttöjärjestelmällesi päivitysohjelmaa.
      +
      Täydellinen protokolladokumentaatio
      +
      Kaikki erilaiset protokollamallit ja metodit.
      +
      Päivitysohjelmalista
      +
      Lista useimmista LiveJournalin kanssa käytetyistä päivitysohjelmista. Suurimmassa osassa ohjelmista on avoin lähdekoodi ja kaikki ovat ilmaisia käyttää. Tämä on hyvä paikka etsiä esimerkkejä omaan ohjelmaasi.
      +
      + +. + +/developer/index.bml.code=Jos haluat nähdä koneiston, joka pitää LiveJournalin käynnissä ja muutaman suositun päivitysohjelman sisälmykset, mene koodisivulle. + +/developer/index.bml.code.header=LiveJournalin koodivarasto + +/developer/index.bml.dbschema=Oletko kiinnostunut tietokantakaaviosta? SQL, joka luo kaikki taulukot ja asuttaa ne, sisältyy palvelinkoodiin. + +/developer/index.bml.dbschema.header=Tietokantakaavio + +/developer/index.bml.embedding=Haluatko upottaa päiväkirjasi suoraan nettisivuusi? Tämän tekemiseen on useita eri tapoja, riippuen palvelimen asetuksista. Sinun täytyy huolehtia tästä vain, jos et halua päiväkirjasi käyttävän osoitetta www.livejournal.com. + +/developer/index.bml.embedding.header=LiveJournalin upottaminen + +/developer/index.bml.notice.header=Huomautus + +/developer/index.bml.notice1=Nämä ohjeet on tarkoitettu vain ohjelmoijille ja edistyneille käyttäjille. Jos haluat käyttää LiveJournalia vain päiväkirjana, älä huolestu. Tavallisten käyttäjien ei tarvitse kiinnittää huomiota näihin sivuihin. + +/developer/index.bml.notice2=Sisältö on jaettu kahteen osaan: LiveJournalin ulkoasun mukauttamiseen ja ohjeisiin siitä, miten kirjoitetaan päivitysohjelma LiveJournal-palvelimelle. + +/developer/index.bml.styles=Etkä pidä päiväkirjasivujesi ulkoasusta? Ei ole syytä huoleen, sillä kaikki on muokattavissa. Jos vielä luet seuraavan ohjeistuksen, tiedät kaiken tarvittavan siitä, miten saat sivusi näyttämään juuri sellaisilta miltä haluatkin. + +/developer/index.bml.styles.header=LiveJournalin ulkonäön muuttaminen + +/developer/index.bml.styles.s1.header=Tyylijärjestelmä 1 (S1) + +/developer/index.bml.styles.s1.system=Tyylijärjestelmä + +/developer/index.bml.styles.s1.system.about=Yleiskatsaus ensimmäisen tyylijärjestelmä asetuksista ja ominaisuuksista. + +/developer/index.bml.styles.s1.varlist=Muuttujalista + +/developer/index.bml.styles.s1.varlist.about=Aakkostettu lista muuttujista, joita voit mukauttaa. + +/developer/index.bml.styles.s1.views=Tarkastelutapa + +/developer/index.bml.styles.s1.views.about=Tietoa erilaisista tavoista, joilla voit tarkastella päiväkirjaasi + +/developer/index.bml.styles.s2.header=Tyylijärjestelmä 2 (S2) + +/developer/index.bml.styles.s2.layerbrowse=S2-kerrostyyppien tarkastelu + +/developer/index.bml.styles.s2.layerbrowse.about=Täydellinen lista S2-kerroksista, jotka muodostavat S2-tyylit. Tärkeimmät näistä ovat ydinkerrokset, jotka määrittelevät perusmuuttujat, toiminnot ja luokat, jotka tekevät S2-ohjelmointikielestä tehokkaan ulkoasun suunnittelussa. + +/developer/index.bml.styles.s2.manual=S2-ohjeet + +/developer/index.bml.styles.s2.manual.about=Täydelliset ohjeet S2:n käyttämisestä LiveJournalissa. + +/developer/index.bml.title=Kehittäjätietoa + +/directory.bml.browse.country.desc=Valitse maa lukeaksesi päiväkirjoja kyseisestä maasta... + +/directory.bml.browse.country.title=Selaa päiväkirjoja maittain + +/directory.bml.browse.usa.desc=Klikkaa USA:n osavaltiota lukeaksesi päiväkirjoja kyseisestä valtiosta tai klikkaa maan nimeä alempaa lukeaksesi päiväkirjoja kyseisestä maasta. + +/directory.bml.browse.usa.title=Selaa päiväkirjoja USA:n osavaltioiden mukaan + +/directory.bml.error.accounttype=Valitettavasti tilityyppisi ei salli hakemiston käyttöä tai et ole kirjautunut sisään. Jos tilityyppisi sallii hakemiston käytön, kirjaudu sisään ja yritä uudestaan. + +/directory.bml.navcrap.matches=[[count]] tulosta + +/directory.bml.navcrap.xofy=Sivu [[curpage]] [[totpages]] löydetystä (väliltä [[reca]]-[[recb]]) + +/directory.bml.open=Avaa + +/directory.bml.post=Tee merkintä + +/directory.bml.search.monkey=Sadat koulutetut apinat juoksevat tällä hetkellä ympäriinsä etsien hakutuloksiasi. Odota vielä. + +/directory.bml.search.new=Uusi haku + +/directory.bml.search.overflow=Hakutulokset on rajoitettu [[count]] tulokseen. Tarkenna hakusanojasi. + +/directory.bml.search.title=Hakee + +/directory.bml.update=Päivitetty: + +/directory.bml.user=Käyttäjä + +/doc/index.bml.about=Tervetuloa LiveJournalin dokumentaatiovarastoon. Täältä löydät tietoa useimmista LiveJournal-palvelua ja palvelinohjelmistoa koskevista asioista. Valitse haluamasi alla olevista: + +/doc/index.bml.about.header=Tervetuloa + +/doc/index.bml.docs.faq.about=Vastauksia usein kysyttyihin kysymyksiin LiveJournal.comista + +/doc/index.bml.docs.faq.title=UKK (FAQ) + +/doc/index.bml.docs.guides.about=Täydentävää FAQ-tietoa + +/doc/index.bml.docs.guides.title=Oppaat + +/doc/index.bml.docs.header=Tekstit + +/doc/index.bml.docs.howto.about=Neuvoja ja temppuja, joilla voit mukauttaa LiveJournal-tiliäsi + +/doc/index.bml.docs.server.about=Kaikki mitä sinun pitää tietää LiveJournalin asentamisesta, ylläpidosta ja tehokkaasta käytöstä + +/doc/index.bml.docs.server.title=LiveJournalin palvelimen käsikirja + +/doc/index.bml.docs.tour.about=Uusille käyttäjille sivustoon tutustumista varten + +/doc/index.bml.docs.tour.title=Tutustumiskierros + +/doc/index.bml.title=Dokumentaatio + +/doc/index.bml.volunteering.about=Jos haluat auttaa LiveJournalin dokumentaation kokoamisessa, vieraile seuraavissa paikoissa + +/doc/index.bml.volunteering.header=Vapaaehtoistoiminta + +/doc/index.bml.volunteering.ljsysdoc=Keskustelua LiveJournalin dokumentaatiojärjestelmästä + +/doc/index.bml.volunteering.ljuserdoc=Keskustelua loppukäyttäjien dokumentaatiosta + +/doc/tour/index.bml.clients.caption=LiveJournal-päivitysohjelmat ovat pieniä tietokoneellasi ajettavia ohjelmia, joiden avulla voit päivittää päiväkirjaasi aina kun olet netissä ilman, että sinun täytyy avata selainikkunaa. Ohjelmia on olemassa melkein mille tahansa alustalle, ja monia niistä voi mukauttaa helposti. + +/doc/tour/index.bml.clients.title=Päivitysohjelmat + +/doc/tour/index.bml.comms.caption=LiveJournal on suuri vuorovaikutteinen yhteisö, eikä siksi pitäisi olla yllättävää, että täällä on monia, jotka ovat kiinnostuneita samoista asioista. Sen vuoksi tarjoamme mahdollisuuden luoda yhteisöjä eli päiväkirjoja, joihin monet ihmiset voivat kirjoittaa. + +/doc/tour/index.bml.comms.title=Yhteisöt + +/doc/tour/index.bml.create.caption=LiveJournal on jäseniensä muodostama yhteisö, jossa voi kirjoittaa omaa päiväkirjaa. Tämä sivu kertoo, mitä jäsenyys pitää sisällään, miksi se on tärkeä ja mitä etuja jäsenyydestä on. Tällä sivulla on myös lomake, jolla voit luoda oman tilisi. + +/doc/tour/index.bml.create.title=Tilin luominen + +/doc/tour/index.bml.friends.caption=Voit myös seurata kavereittesi tekemisiä LiveJournalin välityksellä käyttämällä siihen kuuluvaa "kaverit"-ominaisuutta. Jos löydät päiväkirjan, joka kiinnostaa sinua, lisää se kaverilistallesi ja voit lukea kaikkien kavereittesi päiväkirjamerkinnät samalla sivulla. + +/doc/tour/index.bml.friends.title=Kaverit + +/doc/tour/index.bml.intro.caption=Tämän opastuksen tarkoitus on saada vierailijat tuntemaan olonsa kotoiseksi LiveJournalissa. Se näyttää, missä kaikkein tärkeimmät osiot sijaitsevat, ja kertoo kiinnostavimmista ominaisuuksista. + +/doc/tour/index.bml.intro.title=Tervetuloa + +/doc/tour/index.bml.modify.caption=Voit muotoilla päiväkirjasi eri tavoin käyttäen valmiiksi määriteltyjä tyylejä ja väriasetuksia. Tee päiväkirjastasi niin ainutlaatuinen kuin haluat! + +/doc/tour/index.bml.modify.title=Mukauttaminen + +/doc/tour/index.bml.nav.next=Seuraava --> + +/doc/tour/index.bml.nav.prev=<-- Edellinen + +/doc/tour/index.bml.profile.caption=LiveJournalin käyttäjiä kehotetaan kirjoittamaan itsestään tietoa profiiliinsa tai käyttäjätietosivulleen, jotta saamme jotain kuvaa siitä, kuka käyttää palvelua ja miten voimme parhaiten palvella heitä. Kuitenkaan mikään tällainen ei ole pakollista — ainoat LiveJournalin käyttöön tarvittavat tiedot ovat nimi, sähköpostiosoite ja salasana. + +/doc/tour/index.bml.profile.title=Profiilit + +/doc/tour/index.bml.sitemap.caption=Toivottavasti tämä opastuskierros antoi sinulle hyödyllistä tietoa LiveJournalista ja sen palveluista. Jos tarvitset apua jossain LiveJournaliin liittyvässä asiassa, ota yhteyttä tukeemme. Jos haluat edelleen tutkia itse, lue sivukarttaamme, jolla on luettelo kaikista tämän palvelun sivuista. + +/doc/tour/index.bml.sitemap.title=Sivukartta + +/doc/tour/index.bml.support.caption=Tukisivu listaa paikat, jotka kertovat, mitä LiveJournal on, joissa on vastauksia usein kysyttyihin kysymyksiin (FAQ, UKK) ja joissa on hyödyllistä tietoa palvelusta, yhtiöstä sekä tästä yhteisöstä yleensä. + +/doc/tour/index.bml.support.title=Avun saaminen + +/doc/tour/index.bml.title=Tutustumiskierros - [[title]] + +/doc/tour/index.bml.update.caption=Päivittäminen on LiveJournal-palvelun ydin: näin annamme jäsenillemme mahdollisuuden kertoa elämästään ja siitä, mitä heillä on mielessään. Päivittäminen on yksinkertaista. Riittää, että kirjoitat merkinnän laatikkoon ja painat "Päivitä"-nappia. Tietysti tarjoamme päivityssivulla myös edistyksellisiä ominaisuuksia, kuten mahdollisuuden tarkistaa englannin oikeinkirjoitus tai liittää lisätietoa merkintöihisi, kuten päivityshetken musiikin tai mielialan. + +/doc/tour/index.bml.update.title=Päivittäminen + +/editinfo.bml.advanced.about=Älä huolehdi tästä mikäli et tiedä sen tarkoitusta. + +/editinfo.bml.advanced.title=Lisävaihtoehdot + +/editinfo.bml.allowshowcontact.about=Tämä valinta tulisi säilyttää valittuna. Se antaa muille mahdollisuuden ottaa yhteyttä sinuun sähköpostin, ICQ:n tai AOL Instant Messengerin välityksellä, kun tarvittavat tiedot ovat näkyvissä. + +/editinfo.bml.allowshowcontact.email=Jos tiedot ovat näkyvissä, näytetäänkö sähköpostiosoite? + +/editinfo.bml.allowshowcontact.email.actual_only=Vain oikea osoite + +/editinfo.bml.allowshowcontact.email.both=Kumpikin (oikea ja [[domain]]-) + +/editinfo.bml.allowshowcontact.email.lj_only=Vain LiveJournal-osoite + +/editinfo.bml.allowshowcontact.email.neither=Ei kumpaakaan + +/editinfo.bml.allowshowcontact.email.no_show=Älä näytä sähköpostiosoitetta + +/editinfo.bml.allowshowcontact.email.show=Näytä sähköpostiosoite + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Yllä oleva asetus määrää, piilotetaanko sähköpostiosoitteesi (vaikka muut yhteystiedot ovatkin näkyvillä). Voit lisäksi valita, onko näkyvillä vain LiveJournal-osoitteesi (vain maksetuilla tileillä), vain oikea osoitteesi vai kumpikin osoite. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Oheisella asetuksella voit valita, piilotetaanko sähköpostiosoitteesi (vaikka muut yhteystiedot ovatkin näkyvillä). + +/editinfo.bml.allowshowcontact.title=Näytetäänkö yhteystietosi LiveJournalissa? + +/editinfo.bml.allowshowinfo.about=Valitse tämä, jos haluat kotipaikkasi, osavaltiosi tai maakuntasi ja asuinmaasi sekä syntymäpäiväsi näkyvän muille käyttäjille. + +/editinfo.bml.allowshowinfo.title=Näytetäänkö asuinpaikka ja syntymäpäivä? + +/editinfo.bml.autotranslate.about=Tämä asetus kertoo LiveJournalille, mitä merkistökoodausta olet käyttänyt päiväkirjamerkinnöissäsi ennen kuin koko LiveJournal muutetiin Unicodeksi. Jos olet kirjoittanut suomea, valitse "Western European (ISO)". + +/editinfo.bml.autotranslate.header=Muunna vanhat merkinnät tästä koodauksesta: + +/editinfo.bml.bday.title=Syntymäpäivä + +/editinfo.bml.bday.year.opt=vuotta ei tarvitse antaa + +/editinfo.bml.bdayreminders.about=Valitse tämä, jos haluat saada muistutuksia LiveJournal-kavereittesi syntymäpäivistä sähköpostilla. + +/editinfo.bml.bdayreminders.header=Haluan saada syntymäpäivämuistutuksia (ei käytössä tällä hetkellä) + +/editinfo.bml.bio.about=Tähän voit kirjoittaa pienen vapaamuotoisen kuvauksen itsestäsi. Se näkyy käyttäjätietosivullasi. + +/editinfo.bml.bio.header=Vapaamuotoinen kuvaus + +/editinfo.bml.blockrobots.about<< +Jos valitset tämän, www-robottien käsketään mennä muualle. +Kaikki robotit eivät noudata näitä sääntöjä. +. + +/editinfo.bml.blockrobots.header=Estä nettirobotteja ja -spidereitä tallentamasta päiväkirjaasi hakemistoihinsa + +/editinfo.bml.chat.icquin.title=ICQ-numero + +/editinfo.bml.chat.msnusername.title=MSN-käyttäjätunnus + +/editinfo.bml.chat.yahooid.title=Yahoo!-ID + +/editinfo.bml.city.title=Paikkakunta + +/editinfo.bml.country.choose=Valitse maa + +/editinfo.bml.country.title=Maa + +/editinfo.bml.donotlog=Ei + +/editinfo.bml.email.title=Sähköposti + +/editinfo.bml.enableboards.about=Valitse tämä, jos haluat muiden voivan kommentoida päiväkirjaan lähettämiäsi merkintöjä. + +/editinfo.bml.enableboards.header=Mahdollista kommentointi + +/editinfo.bml.encoding.about=Jos kirjoitat vain englanniksi, nämä asetukset eivät koske sinua. Suomeksi kirjoittavien on syytä muuttaa oletusasetusta. + +/editinfo.bml.encoding.header=Merkistöasetukset + +/editinfo.bml.error.day.notinmonth=Kyseisessä kuukaudessa ei ole tällaista päivänumeroa. + +/editinfo.bml.error.day.outofrange=Epäkelpo syntymäpäivän päivä. Anna päivä väliltä 1-31. + +/editinfo.bml.error.email.lj_domain<< +Et voi antaa @[[domain]]-päätteistä sähköpostiosoitetta. +Kirjoita oikea osoitteesi kenttään. +Jos olet maksanut käyttäjä, [[user]]@[[domain]]-osoitteesi toimii jatkolähetysosoitteena (forward) oikeaan osoitteeseesi. +Alempana, kohdassa "Näytetäänkö yhteystietosi" voit valita, mitkä osoitteet näytetään muille. +. + +/editinfo.bml.error.email.none=Sinun täytyy antaa sähköpostiosoite. + +/editinfo.bml.error.email.no_space<< +Sähköpostiosoitteessa ei saa olla välilyöntejä. +Jos käytät AOLia, muista, että sähköpostiosoitteesi on käyttäjätunnuksesi plus @aol.com.  +. + +/editinfo.bml.error.excessive_int<< +Sinulla on liikaa kiinnostuksenkohteita. Yläraja on 150, mutta olet syöttänyt niitä [[intcount]] kappaletta. +Kiinnostuksenkohteisiisi tekemäsi muutokset eivät tallentuneet. Palaa takaisin, vähennä niitä ja tallenna uudestaan. +. + +/editinfo.bml.error.invalidbio=Tallennettu kuvauksesi sisältää epäkelpoja merkkejä. Sinun täytyy käydä merkistönmuunnossivulla muuntaaksesi sen Unicodeksi. + +/editinfo.bml.error.invalidints=Tämänhetkinen kiinnostuslistasi sisältää epäkelpoja merkkejä. Sinun täytyy käydä merkistönmuunnossivulla muuntaaksesi sen Unicodeksi. + +/editinfo.bml.error.invalidname=Nimessäsi on epäkelpoja merkkejä. Sinun täytyy käydä merkistönmuunnossivulla muuntaaksesi sen Unicodeksi. + +/editinfo.bml.error.locale.country_ne_state=Annoit asuinmaaksesi Yhdysvallat, mutta syötit muun maan osavaltion "muu osavaltio tai maakunta" -kenttään. + +/editinfo.bml.error.locale.invalid_country=Onnistuit jotenkin valitsemaan epäkelvon maan. + +/editinfo.bml.error.locale.state_ne_country=Valitsit muun valtion kuin Yhdysvallat, mutta valitsit Yhdysvaltain osavaltion. + +/editinfo.bml.error.locale.zip_ne_state=Antamasi postinumero kuuluu eri osavaltioon kuin se, missä sanoit asuvasi. Korjaa tietosi tai tyhjennä joko osavaltio- tai postinumerokenttä tai molemmat. + +/editinfo.bml.error.locale.zip_requires_us<< +Syötit postinumeron, muttet valinnut asuinmaaksesi Yhdysvaltoja. +Keräämme postinumerotiedot vain Yhdysvalloissa asuvilta. +Palaa takaisin ja poista postinumero tai valitse Yhdysvallat asuinmaaksesi. +. + +/editinfo.bml.error.month.outofrange=Epäkelpo syntymäkuukausi. Kuukauden pitää olla välillä 1-12. (tammikuu-joulukuu) + +/editinfo.bml.error.noname=Nimi-kenttä täytyy täyttää. Anna edes etu-, netti- tai lempinimesi. + +/editinfo.bml.error.tm.require.number=Sinun täytyy antaa puhelinnumerosi, jos aiot käyttää tekstiviestipalvelua. + +/editinfo.bml.error.tm.require_provider<< +Jos aiot käyttää tekstiviestipalvelua, sinun täytyy valita palveluntarjoajasi. + +Jos tarjoaja ei ole listalla, ole hyvä ja ota meihin yhteyttä kertoaksesi kuinka palvelusi tekstiviestiominaisuus toimii, jotta voimme lisätä sen. +. + +/editinfo.bml.error.year.notenoughdigits=Virheellinen syntymävuosi. Anna vuosi neljällä numerolla. + +/editinfo.bml.error.year.outofrange=Epäkelpo vuosi syntymäpäiväksi. + +/editinfo.bml.finished.about=Kun lopetat muokkaamisen, paina "Tallenna muutokset" -nappulaa. + +/editinfo.bml.finished.header=Tuliko valmista? + +/editinfo.bml.finished.save_button=Tallenna muutokset + +/editinfo.bml.foafurl.about=Jos et halua käyttää oletuksena tarjoamaamme FOAF-sivua, alle syöttämääsi osoitetta käytetään FOAF-lähteenä. Ohjaamme FOAF-pyynnöt annettuun osoitteeseen. + +/editinfo.bml.foafurl.title=Ulkoinen FOAF-osoite: + +/editinfo.bml.gender.title=Sukupuoli + +/editinfo.bml.getreplies.about=Valitse tämä, jos haluat saada sähköpostiviestejä, kun päiväkirjamerkintöihisi tulee kommentteja. + +/editinfo.bml.getreplies.header=Haluan tiedon kommenteista + +/editinfo.bml.getselfemails.about=Valitse tämä, jos haluat saada sähköpostin aina kun lähetät kommentin päiväkirjaan tai yhteisöön. Et saa sähköpostia nimettömistä kommenteista. + +/editinfo.bml.getselfemails.header=Lähetä tekemäsi kommentit sähköpostilla itsellesi + +/editinfo.bml.hidefriendof.about=Jos valitset tämän, niiden käyttäjien lista, joiden kaveri olet, ei näy käyttäjätietosivullasi. + +/editinfo.bml.hidefriendof.header=Älä näytä "kenen kaveri" -listaa + +/editinfo.bml.howhear.about=Meitä kiinnostaa tietää, mistä kuulit [[sitename]]-palvelusta. Jos lähteesi oli tietty henkilö, syötä hänen käyttäjätunnuksensa; jos lähteesi oli jokin artikkeli, linkki tai internetsivusto, kirjoita se tähän. + +/editinfo.bml.howhear.header=Tiedonhalu + +/editinfo.bml.htmlemail.about=Valitse tämä, jos sähköpostiohjelmasi tukee HTML:ää. Monet ohjelmat yrittävät, mutta epäonnistuvat surkeasti. Jos poistat valinnan, LiveJournal lähettää sähköpostin tekstimuotoisena. + +/editinfo.bml.htmlemail.header=Lähetä HTML-sähköposteja + +/editinfo.bml.imagelinks.about=Paikanvaraajat ovat käteviä jos käytät LiveJournalia töissä tai hitaalla internetyhteydellä, koska ne korvaavat kuvat linkeillä. Minkäkokoiset kuvat haluat paikanvaraajien korvaavan? + +/editinfo.bml.imagelinks.header=Käytä paikanvaraajia kaverisivullasi + +/editinfo.bml.imagelinks.size.all=Käytä paikanvaraajia kaikille kuville + +/editinfo.bml.imagelinks.size.custom=Mukautettu: käytä paikanvaraajia kuville, jotka ovat suurempia kuin [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=Käytä paikanvaraajia suurille kuville (yli [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Käytä paikanvaraajia keskikokoisille kuville (yli [[width]]x[[height]]) + +/editinfo.bml.int.about<< +Jos haluat, että toiset voivat etsiä hakemistosta ja löytää sinut kiinnostuksenkohteen perusteella, voit listata alla kaiken, mistä olet kiinnostunut - pilkuilla erotettuna. Listassa on syytä käyttää englantia. +Lyhyet, yhden sanan sisältävät ilmaukset ovat parhaita. Muistisääntö: kiinnostuksenkohteen pitäisi sopia englanninkieliseen lauseeseen "I like ________." Kun viittaat substantiiveihin, käytä monikkomuotoa johdonmukaisuuden vuoksi. Mieluummin "I like DVDs" kuin "I like DVD". +. + +/editinfo.bml.int.ex.bad=VÄÄRIN Esimerkki: I like lots of bands and watching movies and talking to friends and going to clubs. Tällainen kuuluu vapaaseen kuvaukseesi, jonka löydät ylempää. + +/editinfo.bml.int.ex.good=OIKEIN Esimerkki: biking, snow skiing, computers, dvds, mp3s, cheese, women + +/editinfo.bml.int.header=Kiinnostuksenkohteet + +/editinfo.bml.login.enterinfo=Anna käyttäjätunnuksesi ja salasanasi, jotta pääset muokkaamaan henkilökohtaisia tietojasi. + +/editinfo.bml.login.forgot.header=Unohtuiko jotain? + +/editinfo.bml.login.forgot.recover=Jos unohdit käyttäjätunnuksesi tai salasanasi, voit saada ne selville tästä! + +/editinfo.bml.logip.always=Aina + +/editinfo.bml.logip.anon_only=Vain nimettömiltä kommentoijilta + +/editinfo.bml.logip.header=Tallennetaanko kommentoijien IP-osoite? + +/editinfo.bml.mangleaddress.about=Jos pelkäät että roskapostirobotit löytävät sähköpostiosoitteesi LiveJournalista, valitse tämä vaihtoehto. Osoitteesi sotketaan siten, etteivät osoitteita etsivät nettirobotit löydä sitä. + +/editinfo.bml.mangleaddress.header=Sotke näkyvät sähköpostiosoitteet + +/editinfo.bml.mutualfriends.about=Tämä vaihtoehto lisää uuden listan käyttäjätietosivullesi: molemminpuoleiset kaverit. Kaverit, jotka ovat sekä omalla kaverilistallasi ja ovat lisänneet sinut kaverilistalleen lisätään tähän listaan. + +/editinfo.bml.mutualfriends.header=Näytä molemminpuoleiset kaverit käyttäjätietosivulla. + +/editinfo.bml.name.title=Nimi + +/editinfo.bml.newemail.body2<< +Olet juuri muuttanut käyttäjän "[[username]]" sähköpostiosoitetta [[sitename]]-palvelussa. Varmistaaksesi muutokset, käy osoitteessa: + +[[conflink]] + +Terveisin, +[[sitename]]-tiimi +[[sitelink]] +. + +/editinfo.bml.newemail.subject=Sähköpostiosoite muutettu + +/editinfo.bml.numcomments.about=Valitse tämä, jos haluat lisätä kommenttien määrän URLeihin, jotta selain mahdollisesti näyttäisi linkit eri värillä. + +/editinfo.bml.numcomments.header=Lisää &nc=xx kommenttien URLeihin + +/editinfo.bml.optional=valinnainen + +/editinfo.bml.opt_in.about<< +Valitse tämä, jos haluat tietää, milloin lisäämme hienoja uusia ominaisuuksia LiveJournaliin. +Et saa näitä sähköposteja kovinkaan usein, yleensä vain kerran tai kaksi kuussa. +Muut käyttäjät eivät näe sähköpostiosoitettasi, ja voit lopettaa uutisten vastaanoton milloin tahansa. +. + +/editinfo.bml.opt_in.header=Tahdon saada LiveJournal-uutisia. + +/editinfo.bml.persinfo.disclaimer<< +Tänne voit antaa joitain tietoja itsestästi, sillä olemme uteliaita, ja myös tilastojen takia. +Emme käytä näitä tietoja mihinkään ilkeään tai ärsyttävään toimintaan - haluaisimme vain nähdä, keitä ja missä käyttäjämme ovat. Pyydämme antamaan tiedot oikein. Jos olet huolissasi, lue meidän yksityisyysperiaatteemme. +. + +/editinfo.bml.persinfo.header=Henkilökohtaiset tiedot + +/editinfo.bml.screen.all=Kaikki + +/editinfo.bml.screen.anon=Nimettömät + +/editinfo.bml.screen.header=Mitkä viestit haluat oletuksena peitettävän? + +/editinfo.bml.screen.none=En mitkään + +/editinfo.bml.screen.nonfriends=Muiden kuin kavereiden + +/editinfo.bml.screen.nonmembers=Muiden kuin jäsenten + +/editinfo.bml.security.header=Kuka voi nähdä yhteystietosi? + +/editinfo.bml.security.visibility.anybody=Kuka tahansa + +/editinfo.bml.security.visibility.everybody=Kaikki + +/editinfo.bml.security.visibility.friends=Vain kaverit + +/editinfo.bml.security.visibility.regusers=Rekisteröityneet käyttäjät + +/editinfo.bml.settings.friendspage.title=Kaverisivun otsikko: + +/editinfo.bml.settings.friendspage.title.optional=Valinnainen otsikko kaverinäkymällesi (ei HTML-kieltä). + +/editinfo.bml.settings.header=LiveJournal-asetukset + +/editinfo.bml.settings.journal.subtitle=Päiväkirjan alaotsikko: + +/editinfo.bml.settings.journal.subtitle.optional=Valinnainen otsikko ja alaotsikko päiväkirjallesi (ei HTML-kieltä). + +/editinfo.bml.settings.journal.title=Päiväkirjan otsikko: + +/editinfo.bml.settings.privacy.about=Valitse tästä yksityisyysasetuksesi. + +/editinfo.bml.settings.privacy.header=Yksityisyysasetukset + +/editinfo.bml.state.other=Tai jokin muu osavaltio tai maakunta + +/editinfo.bml.state.title=Osavaltio (USA) + +/editinfo.bml.state.us=Yhdysvaltain osavaltiot + +/editinfo.bml.stylemine.about=Valitse tämä vaihtoehto nähdäksesi kommenttisivut päiväkirjasi tyylisinä kun klikkaat linkkiä kaverisivultasi + +/editinfo.bml.stylemine.header=Näytä kommenttisivut päiväkirjasi tyylisenä? + +/editinfo.bml.success.header=Onnistui! + +/editinfo.bml.success.message=Päiväkirjasi asetukset sekä henkilökohtaiset tietosi on päivitetty. + +/editinfo.bml.switch.button=Vaihda + +/editinfo.bml.switch.header=Valitse päiväkirja + +/editinfo.bml.switch.workwith=Muokkaa tätä päiväkirjaa: + +/editinfo.bml.title=Muokkaa henkilökohtaisia tietoja + +/editinfo.bml.tm.details=lisätietoja + +/editinfo.bml.tm.phonenum=Täydellinen puhelinnumero: + +/editinfo.bml.tm.sec.about=Anna muiden käyttäjien lähettää tekstiviestejä + +/editinfo.bml.tm.sec.title=Turvataso: + +/editinfo.bml.tm.servprov=Matkapuhelinoperaattori + +/editinfo.bml.tm.title=Tekstiviestipalvelu + +/editinfo.bml.translatemailto.about=Jos halusit saada kommentit merkintöihisi sähköpostitse eikä sähköpostiohjelmasi osaa käsitellä Unicode-viestejä (UTF-8) kunnolla, käytä tätä asetusta ja valitse jokin toinen merkistökoodaus. LiveJournal muuntaa sinulle lähetettyjen kommenttien tekstin automaattisesti haluamaasi merkistöön. + +/editinfo.bml.translatemailto.header=Muunna kommenttimuistukset tähän merkistöön: + +/editinfo.bml.unbanusers.about=Olet estänyt seuraavia käyttäjiä kommentoimasta päiväkirjaasi. Valitse käyttäjätunnuksen viereinen laatikko poistaaksesi eston kyseiseltä käyttäjältä. + +/editinfo.bml.unbanusers.header=Poista kommentointiesto + +/editinfo.bml.userpic.about=Ohessa on pieni kuva, jonka olet siirtänyt LiveJournaliin kuvaamaan itseäsi niin omassa kuin kavereidesikin päiväkirjoissa. + +/editinfo.bml.userpic.edit=Jos haluat poistaa tämän kuvan tai ladata uuden, tee se täällä. + +/editinfo.bml.userpic.header=Käyttäjäkuva + +/editinfo.bml.userpic.none=ei kuvaa + +/editinfo.bml.weblogscom.about=Valitse tämä, jos haluat Weblogs.com-palvelun listaavan päiväkirjasi, kun kirjoitat uusia julkisia merkintöjä. + +/editinfo.bml.weblogscom.header=Kerro Weblogs.comille päivityksistä + +/editinfo.bml.webpagename.title=Kotisivun nimi + +/editinfo.bml.webpageurl.title=Kotisivun URL + +/editinfo.bml.whoreply.header=Kuka voi kommentoida merkintöjäsi? + +/editinfo.bml.zip.title=Postinumero + +/editinfo.bml.zip.usonly=5 numeroinen postinumero, vain Yhdysvalloissa asuvat + +/editjournal.bml.btn.proceed=Jatka... + +/editjournal.bml.certainday=Tämän päivän merkinnät: + +/editjournal.bml.desc=Käytä alla olevaa lomaketta etsiäksesi merkintä, jota haluat muokata. + +/editjournal.bml.in=Yhteisössä: + +/editjournal.bml.recententries=viimeisintä merkintää + +/editjournal.bml.recententry=Viimeisin merkintä + +/editjournal.bml.title=Muokkaa päiväkirjamerkintöjä + +/editjournal.bml.viewwhat=Mitkä merkinnät haluat nähdä? + +/editjournal_do.bml.body=Muokkaa haluamiasi kenttiä päiväkirjamerkinnästäsi ja paina Tallenna-nappia sivun alareunassa. Voit myös painaa Poista merkintä -nappia poistaaksesi merkinnän. + +/editjournal_do.bml.btn.delete=Poista merkintä + +/editjournal_do.bml.btn.edit=Muokkaa valittua merkintää + +/editjournal_do.bml.btn.preview=Esikatsele merkintä + +/editjournal_do.bml.btn.save=Tallenna päiväkirjamerkintä + +/editjournal_do.bml.continue.head=Paina jatkaaksesi... + +/editjournal_do.bml.continue.text=Kun olet valinnut sen, mitä haluat muokata tai poistaa, paina Muokkaa-nappia. + +/editjournal_do.bml.currmood=Mieliala: + +/editjournal_do.bml.currmusic=Musiikki: + +/editjournal_do.bml.date=Päivämäärä: + +/editjournal_do.bml.default=oletus + +/editjournal_do.bml.delete.confirm=Oletko varma että haluat poistaa tämän merkinnän? + +/editjournal_do.bml.edit.text=Tässä on muokattavaksi valitsemasi päiväkirjamerkintä. Muuta niitä kenttiä, joita haluat, ja klikkaa sivun alareunan "Tallenna päiväkirjamerkintä"-nappia.

      Jos haluat poistaa merkinnän, poista kaikki teksti isosta laatikosta ja klikkaa alareunan "Tallenna päiväkirjamerkintä"-nappia. + +/editjournal_do.bml.error.getting=Haettaessa päiväkirjamerkintöjä muokattavaksi sattui virhe: + +/editjournal_do.bml.error.modify=Päiväkirjaasi muokattaessa tapahtui virhe: + +/editjournal_do.bml.error.nofind=Valittua päiväkirjamerkintää ei löytynyt. + +/editjournal_do.bml.event=Merkinnän teksti: + +/editjournal_do.bml.localtime=Paikallinen aika + +/editjournal_do.bml.noneother=Ei mitään tai muu: + +/editjournal_do.bml.opt.backdate=Päivää takautuvasti: + +/editjournal_do.bml.opt.backdate.about=ei näy kavereittesi kaverilistoilla + +/editjournal_do.bml.opt.nocomments=Estä kommentointi: + +/editjournal_do.bml.opt.noemail=Ei kommenttimuistutuksia sähköpostilla: + +/editjournal_do.bml.opt.noformat=Ei automaattista muotoilua: + +/editjournal_do.bml.opt.spellcheck=Tarkista merkinnän oikeinkirjoitus ennen tallentamista (englanti) + +/editjournal_do.bml.other=Muu: + +/editjournal_do.bml.pickentry.head=Valitse muokattava merkintä + +/editjournal_do.bml.pickentry.text=Valitse, mitä haluat muokata ja paina muokkaa-nappia sivun alareunassa. + +/editjournal_do.bml.picture=Merkintään liitettävä kuva: + +/editjournal_do.bml.preview.header=Esikatsele merkintä + +/editjournal_do.bml.preview.text=Tältä merkintä näyttää valmiina. Alla olevaa lomaketta käyttäen voit muokata merkintää pidemmälle tai lähettää sen sellaisenaan. + +/editjournal_do.bml.save.head=Paina tallentaaksesi + +/editjournal_do.bml.save.text=Kun olet muokannut merkintää, paina Tallenna-nappia. + +/editjournal_do.bml.spellchecked=Tarkistettu merkintäsi: + +/editjournal_do.bml.subject=Aihe: (valinnainen) + +/editjournal_do.bml.success.delete=Päiväkirjamerkintä on poistettu. + +/editjournal_do.bml.success.edit=Päiväkirjamerkintääsi on muutettu. Voit nähdä sen täällä. + +/editjournal_do.bml.success.head=Onnistui! + +/editjournal_do.bml.timeformat=24-tuntinen aika + +/editjournal_do.bml.title=Muokkaa päiväkirjamerkintöjä + +/editpics.bml.btn.proceed=Jatka + +/editpics.bml.btn.save=Tallenna asetukset + +/editpics.bml.curpics=Tämänhetkiset kuvat + +/editpics.bml.curpics.desc=Tässä ovat aikaisemmin tallentamasi kuvat. Voit antaa niillä avainsanoja, joiden avulla käytät niitä myöhemmin. Voit myös valita oletuskuvasi tai poistaa vanhoja. Tallentaaksesi uuden kuvan käytä sivun alalaidassa olevaa lomaketta. + +/editpics.bml.error.badurl=Tallennettavan kuvan osoite vaikuttaa vääränlaiselta. Sen alussa pitäisi olla http:// + +/editpics.bml.error.filetoolarge=Tallennettava kuva on liian iso. Tiedoston maksimikoko on [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Kuvasi koko ([[imagesize]]) ylittää suurimman sallitun koon. Kuva voi olla enintään 100x100 pikselin kokoinen. Pienennä kuva vaadittavaan kokoon kuvanmuokkausohjelmalla. + +/editpics.bml.error.invalidimage=Virheellinen kuvatiedosto. + +/editpics.bml.error.keywords=Käytit avainsanaa "[[ekw]]" useammalle kuvalle, joten niistä valittiin sattumalta yksi. Et luultavasti tarkoittanut kyseistä kuvaa, joten saatat haluta palata korjaamaan asian. + +/editpics.bml.error.toomanypics2=Sinulla on jo enimmäismäärä eli [[maxpics]] käyttäjäkuvaa. Et voi tallentaa tätä kuvaa ennen kuin poistat jonkin nykyisistä kuvista. + +/editpics.bml.error.toomanypics3=Olet tällä hetkellä maksimirajassasi, joka on [[max]] [[?max|kuva|kuvaa]]. Et voi ladata lisää käyttäjäkuvia ennen kuin poistat yhden tai useamman vanhoista kuvistasi. + +/editpics.bml.error.unsupportedtype=Tiedostotyyppi [[filetype]] ei ole tuettu. Voit tallentaa vain GIF-, PNG- tai JPG-tiedostoja. Lähes kaikki kuvanmuokkausohjelmat osaavat tehdä tarvittavan muunnoksen. + +/editpics.bml.error.urlerror=Haettaessa kuvaasi tapahtui virhe. + +/editpics.bml.fromfile=Tiedostosta: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=t + +/editpics.bml.fromurl=Osoitteesta: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=o + +/editpics.bml.kilobytes=kt + +/editpics.bml.label.default=Oletus: + +/editpics.bml.label.delete=Poista: + +/editpics.bml.label.keywords=Avainsanat: + +/editpics.bml.makedefault=Tee tästä oletuskuvasi + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=l + +/editpics.bml.nodefault=Ei oletuskuvaa + +/editpics.bml.noneupload=Sinulla ei ole kuvia tallennettuna. Tallenna sellainen käyttämällä allaolevaa lomaketta. + +/editpics.bml.nopics=Ei kuvia + +/editpics.bml.piclimitstatus=Kuvia tällä hetkellä ladattuna: [[current]]/[[max]]. + +/editpics.bml.restriction.fileformat=Tiedostotyypin täytyy olla PNG, GIF tai JPG + +/editpics.bml.restriction.filesize=Tiedoston koko täytyy olla pienempi kuin 40 kt + +/editpics.bml.restriction.imagesize=Kuva ei saa olla suurempi kuin 100x100 pikseliä + +/editpics.bml.title=Muokkaa käyttäjäkuvia + +/editpics.bml.uploaddesc=Käytä alla olevaa lomaketta tallentaaksesi uuden kuvan. + +/editpics.bml.uploadheader=Lisää uusi kuva + +/export.bml.btn.proceed=Jatka... + +/export.bml.description=Tällä voit tallentaa koko päiväkirjasi haluamaasi muotoon varmuuskopiointia varten. Saadaksesi varmuuskopioinnista lisää tietoa, lue tämä FAQ. + +/export.bml.fields=Kentät: + +/export.bml.label.encoding=Koodaus: + +/export.bml.label.field.allowmask="Allow Mask" + +/export.bml.label.field.currents=Mieliala & musiikki + +/export.bml.label.field.event=Merkintä + +/export.bml.label.field.eventtime=Merkinnän aika (käyttäjän kellon mukaan) + +/export.bml.label.field.itemid=ID-numero + +/export.bml.label.field.logtime=Kirjausaika (systeemin kellosta) + +/export.bml.label.field.security=Turvataso + +/export.bml.label.field.subject=Otsikko + +/export.bml.label.format=Muoto: + +/export.bml.label.header=Otsikko + +/export.bml.label.month=Kuukausi: + +/export.bml.label.month.month=kk: + +/export.bml.label.month.year=vvvv: + +/export.bml.label.notranslation=Älä muunna koodauksesta toiseen + +/export.bml.label.what=Mitä tallennetaan: + +/export.bml.title=Tallenna päiväkirja + +/export.bml.what.entries=Päiväkirjamerkinnät + +/export_do.bml.error.encoding=Virheellinen koodaus valittu. + +/friends/add.bml.add.header=Onnistui + +/friends/add.bml.add.text=Käyttäjä [[ljuser]] on lisätty kaverilistallesi. Voit lukea kaverisivuasi tästä. + +/friends/add.bml.add.title=Kaveri lisätty! + +/friends/add.bml.btn.add=Lisää käyttäjä [[user]] + +/friends/add.bml.btn.modify=Muokkaa + +/friends/add.bml.btn.remove=Poista + +/friends/add.bml.colors.bg=Tausta + +/friends/add.bml.colors.fg=Teksti + +/friends/add.bml.colors.header=Värit + +/friends/add.bml.colors.hover=(Vie hiiren osoitin värin päälle nähdäksesi sen nimen.) + +/friends/add.bml.colors.text=Voit halutessasi myös muuttaa niitä värejä, joilla [[user]] näkyy kaverilistallasi. + +/friends/add.bml.confirm.header=Lisätäänkö [[user]] kaveriksi? + +/friends/add.bml.confirm.syn.header=Lisää syndikaatiosyöte [[user]] kaverilistalle? + +/friends/add.bml.confirm.syn.title=Lisää syndikaatiosyöte + +/friends/add.bml.confirm.text=Paina oheista nappia lisätäksesi käyttäjän [[user]] kaverilistallesi. + +/friends/add.bml.confirm.title=Lisää kaveri + +/friends/add.bml.error1.header=Kirjaudu ensin sisään + +/friends/add.bml.error1.text=Jotta voit lisätä käyttäjän kaverilistallesi, sinun täytyy ensin kirjautua sisään. Ellei sinulla ole LiveJournal-tiliä, voit luoda omasi ja sitten seurata kaveriesi päiväkirjoja. + +/friends/add.bml.error1.title=Lisää kaveri + +/friends/add.bml.error2.text=Antamasi käyttäjätunnus ei kelpaa tai sitä ei ole olemassa. Voit lisätä kaverin kaverienmuokkaussivulla. + +/friends/add.bml.error3.text=Käyttäjä [[user]] on jo kaverilistallasi. Voit kuitenkin muuttaa häneen jo liittämiäsi värejä. + +/friends/add.bml.error3.title=Muokkaa kavereita + +/friends/add.bml.groups.header=Kaveriryhmät + +/friends/add.bml.groups.nogroup=Ei määritettyjä kaveriryhmiä. + +/friends/add.bml.groups.text=Mihin kaveriryhmään haluat sijoittaa tämän käyttäjän? Kaveriryhmiä käytetään jaottelemaan kaverilista haluttuihin osiin sekä siihen, mihin ryhmiin kuuluvat näkevät viestisi turva-asetusten perusteella. + +/friends/add.bml.remove.header=Onnistui + +/friends/add.bml.remove.text=Käyttäjä on poistettu kaverilistaltasi. Voit katsoa kaverisivuasi tästä. + +/friends/add.bml.remove.title=Kaveri poistettu! + +/friends/edit.bml.title=Muokkaa kavereita + +/friends/editgroups.bml.btn.ge.del=Poista + +/friends/editgroups.bml.btn.ge.new=Uusi + +/friends/editgroups.bml.btn.ge.ren=Nimeä uudestaan + +/friends/editgroups.bml.btn.gs.private=Yksityinen + +/friends/editgroups.bml.btn.gs.public=Julkinen + +/friends/editgroups.bml.btn.mv.down=Alas + +/friends/editgroups.bml.btn.mv.up=Ylös + +/friends/editgroups.bml.confirm.delete=Haluatko varmasti poistaa tämän kaveriryhmän? + +/friends/editgroups.bml.done.btn=Tallenna muutokset + +/friends/editgroups.bml.done.header=Tuliko valmista? + +/friends/editgroups.bml.done.text=Kun olet tehnyt haluamasi muutokset, paina alla olevaa nappia. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Sinulla on nyt 30 kaveriryhmää, joka on suurin sallittu määrä. Jos olet poistanut yhden tai useampia ryhmiä muttet vielä tallentanut muutoksia, tee se nyt. Kun sen jälkeen tulet takaisin tälle sivulle, päivitä se. Sen jälkeen voit luoda uusia kaveriryhmiä. + +/friends/editgroups.bml.error.text=Palvelin antoi seuraavan virheilmoituksen: + +/friends/editgroups.bml.group.public=(julkinen) + +/friends/editgroups.bml.ingroup=Kuuluvat ryhmään: + +/friends/editgroups.bml.ingroup.not=Eivät kuulu ryhmään: + +/friends/editgroups.bml.prompt.newname=Anna uuden kaveriryhmän nimi: + +/friends/editgroups.bml.prompt.rename=Anna tämän kaveriryhmän uusi nimi: + +/friends/editgroups.bml.saved.header=Tallennettu + +/friends/editgroups.bml.saved.text=Kaveriryhmäsi ovat nyt tallentuneet. + +/friends/editgroups.bml.text<< +Tällä sivulla voit muokata kaveriryhmiä. Mukautettuja kaveriryhmiä käytetään merkintöjen turva-asetuksiin ja kaverisivun suodattamiseen. Ks. myös Mitä ovat mukautetut kaveriryhmät? Kuinka käytän niitä?. + +Tämä sivu vaatii JavaScriptin toimiakseen. +. + +/friends/editgroups.bml.text.sec=Turvallisuushuomautus: Jos haluat poistaa ryhmän ja luoda tilalle uuden, älä tee sitä nimeämällä uudelleen jo olemassa olevaa ryhmää ja sitten muokkaamalla tätä. Jos teet näin, kaikki vanhan ryhmän nähtävissä olevat merkinnät näkyvät myös uudelle ryhmälle. + +/friends/editgroups.bml.title=Muokkaa kaveriryhmiä + +/friends/editgroups.bml.yourgroups=Kaveriryhmät: + +/friends/edit_do.bml.addfriends.head=Kavereiden lisääminen + +/friends/edit_do.bml.addfriends.text=Kirjoita kaveriesi LiveJournal-käyttäjätunnukset alla oleviin laatikoihin ja valitse, minkä värisen taustan ja tekstin haluat liittää heihin... + +/friends/edit_do.bml.background=Tausta + +/friends/edit_do.bml.bgcolor=Taustan väri + +/friends/edit_do.bml.btn.close=Sulje + +/friends/edit_do.bml.btn.save=Tallenna muutokset + +/friends/edit_do.bml.btn.toggle=Näytä/poista esikatseluikkuna + +/friends/edit_do.bml.done.head=Tuliko valmista? + +/friends/edit_do.bml.done.text=Kun olet lopettanut muokkaamisen, paina "Tallenna muutokset" -nappia... + +/friends/edit_do.bml.error.updating=Kaverilistan päivittämisessä tapahtui virhe: + +/friends/edit_do.bml.fellowfriends.head=Kanssakaverit + +/friends/edit_do.bml.fellowfriends.text=Olet seuraavien ihmisten kaverilistalla. Saatat haluta lisätä heidät omalle listallesi. Heidät on listattu ennen kaikkea siksi, että tietäisit heidän LiveJournal-käyttäjätunnuksensa. Mikään ei velvoita sinua lisäämään heitä kavereiksesi. + +/friends/edit_do.bml.foreground=Tekstin väri + +/friends/edit_do.bml.friend=Kaveri + +/friends/edit_do.bml.hover=Vie hiiren osoitin värin päälle nähdäksesi sen nimen. + +/friends/edit_do.bml.mrcolor=Herra Värinnäytin + +/friends/edit_do.bml.name=Nimi + +/friends/edit_do.bml.needmore=Jos haluat lisätä enemmän kavereita kuin tälle lomakkeelle mahtuu, tallenna muutokset ja tule uudestaan lisätäksesi puuttuvat käyttäjät. + +/friends/edit_do.bml.nofriends.head=Ei kavereita? + +/friends/edit_do.bml.nofriends.text=Et ole määrittänyt ketään kavereiksesi. Mutta kohta sinulla varmaan on jo on muutama kaveri! :) Sinun pitää vain syöttää heidän LiveJournal-tunnuksensa alle... + +/friends/edit_do.bml.opt.addtolist=Lisää kaveri + +/friends/edit_do.bml.opt.delete=Poista? + +/friends/edit_do.bml.success.head=Onnistui + +/friends/edit_do.bml.success.text=Kaverilistasi on päivitetty. Voit katsoa päivittynyttä kaverisivuasi tästä. + +/friends/edit_do.bml.textcolor=Tekstin väri: + +/friends/edit_do.bml.title=Muokkaa kaverilistaa + +/friends/edit_do.bml.user=Käyttäjä + +/friends/edit_do.bml.viewer=Värien esikatselu + +/friends/edit_do.bml.yourfriends.head=Kaverisi + +/friends/edit_do.bml.yourfriends.text=Seuraavat käyttäjät on merkitty kavereiksesi: + +/friends/filter.bml.editgroups=Kaveriryhmiä voit muokata [[link]] -sivulla. + +/friends/filter.bml.error.nogroups=Et voi suodattaa kaverilistaasi, sillä ensin sinun täytyy määrittää kaveriryhmäsi. + +/friends/filter.bml.error.nogroups.header=Ei määriteltyjä ryhmiä + +/friends/filter.bml.reset=Tyhjennä + +/friends/filter.bml.select=Valitse se ryhmä tai ne ryhmät, jotka haluat nähdä kaverilistallasi. + +/friends/filter.bml.select.header=Valitse ryhmät + +/friends/filter.bml.submit=Näytä + +/friends/filter.bml.title=Kaverisuodatin + +/friends/index.bml.about=Tällä sivulla voit järjestää kaverilistaasi. Lisäämällä muita käyttäjiä omalle kaverilistallesi voit helposti nähdä heidän merkintänsä kaverisivusi avulla. Voit lisätä kaverilistallesi myös yhteisöjä ja syndikoituja sivuja. + +/friends/index.bml.edit.about=Muokkaa kaverilistaasi lisäämällä tai poistamalla siitä käyttäjiä ja muokkaamalla heitä edustavia värejä. + +/friends/index.bml.editgroups.about=Luo, muokkaa tai poista muodostamiasi kaveriryhmiä. + +/friends/index.bml.filter=Ryhmien avulla voi suodattaa kaverilistaasi, kun valitset näytettäväksi tietyn kaveriryhmän. Niitä voi käyttää myös merkintöjen turva-asetuksia tehdessä. (katso alta) + +/friends/index.bml.filter.about=Suodata kaverilistaasi siten, että näet vain valitsemasi ryhmien merkinnät. + +/friends/index.bml.groups=Voit lisäksi järjestellä kavereita alaryhmiksi. + +/friends/index.bml.security=Kaverilistaasi käytetään myös rajoitettujen merkintöjesi kanssa. Saat lisätietoa kaverilistastasi täältä. + +/friends/index.bml.security.custom="Mukautettu" antaa sinun valita mitkä kaveriryhmät näkevät merkintäsi. Huomaa kuitenkin, että kaikki päivitysohjelmat eivät tällä hetkellä tue tätä toimintoa. + +/friends/index.bml.security.header=Turvallisuus + +/friends/index.bml.security.only="Vain kaverit" -viesteissä vain kaverilistalla olevat käyttäjät näkevät merkintäsi. + +/friends/index.bml.title=Kaverityökalut + +/friends/index.bml.tools=Työkalut + +/friends/popwithfriends.bml.account_type=Tilityyppisi ei salli tämän toiminnon käyttöä. + +/friends/popwithfriends.bml.count=Lukumäärä + +/friends/popwithfriends.bml.exclude_own=Voit myös poistaa kavereitasi. + +/friends/popwithfriends.bml.include_own=Voit myös lisätä kavereitasi. + +/friends/popwithfriends.bml.intro=Kavereillasi on listallaan usein seuraavat käyttäjät, jotka eivät vielä kuulu omiin kavereihisi. + +/friends/popwithfriends.bml.intro_own=Kavereillasi on listallaan usein seuraavat käyttäjät. Lista sisältää myös omat kaverisi. + +/friends/popwithfriends.bml.no_users=Ei käyttäjiä + +/friends/popwithfriends.bml.title=Suosittuja käyttäjiä kavereidesi keskuudessa + +/friends/popwithfriends.bml.user=Käyttäjä + +/go.bml.defaultbody=Arvoja ei annettu. + +/go.bml.defaulttitle=Virhe + +/go.bml.error.noentry.next=Tätä merkinnän jälkeen ei ole muita. + +/go.bml.error.noentry.prev=Tätä merkintää ennen ei ole muita. + +/go.bml.error.noentrytitle=Ei merkintää + +/go.bml.error.redirkey=Virheellinen redir_key. + +/go.bml.error.usernotfound=Käyttäjää ei löytynyt. + +/index.bml.about.header=Tietoja LiveJournalista + +/index.bml.about.joining=Liittyminen on ilmaista. Käyttäjät voivat halutessaan ostaa maksetun tilin saadakseen lisätoimintoja. + +/index.bml.about.us=LiveJournal on helppokäyttöinen (mutta erittäin tehokas ja muokattava) henkilökohtainen julkaisu- ja päiväkirjatyökalu, joka perustuu vapaaseen lähdekoodiin. + +/index.bml.boldcreate=Luo oma LiveJournalisi! + +/index.bml.frank.image.alt=Frank, LiveJournalin maskottivuohi. + +/index.bml.frank.logo="Määäää", sanoo Frank. + +/index.bml.learnmore.header=Haluatko tietää lisää? + +/index.bml.learnmore.text=Lue toimintokatsauksemme. Vakuutuitko? Luo oma LiveJournalisi! + +/index.bml.meta.desc=LiveJournal.com on paikka, jossa voit jakaa ajatuksesi maailman kanssa. + +/index.bml.meta.keywords=päiväkirja, online, nettipäiväkirja, päiväkirjat, kirjoittaminen, verkkopäiväkirja + +/index.bml.news.text=Sivuston viimeisimmät uutiset: + +/index.bml.news.title=Viimeisimmät uutiset + +/index.bml.post=Reaaliaikainen seuranta + +/index.bml.post.hour=Merkintöjä tunnissa: + +/index.bml.post.latest=Viimeisimmät merkinnät + +/index.bml.post.min=Merkintöjä minuutissa: + +/interests.bml.add.added.head=Lisätty! + +/interests.bml.add.added.text=Kiinnostuksenkohde on lisätty listaasi. + +/interests.bml.add.btn.text=Lisää [[interest]] + +/interests.bml.add.confirm.head=Vahvistus + +/interests.bml.add.confirm.text=Lisätäksesi kiinnostuksenkohteen [[interest]], klikkaa nappia. + +/interests.bml.add.toomany.head=Valitettavasti... + +/interests.bml.add.toomany.text=Sinulla on jo [[maxinterests]] kiinnostuksenkohdetta. + +/interests.bml.addint=Jos tämä kiinostaa sinua ja haluaisit olla tällä listalla, klikkaa tästä. + +/interests.bml.btn.switch=Vaihda + +/interests.bml.communities.head=Yhteisöt + +/interests.bml.communities.text=Myös seuraavien yhteisöjen kiinnostuksenkohteena on "[[interest]]". + +/interests.bml.count=Lukumäärä + +/interests.bml.enmasse.body.other=Tässä ovat käyttäjän [[user]] kiinnostuksenkohteet. Rastita ruudut niitten kiinnostuksenkohteiden vierestä jotka haluat lisätä omaan listaasi, ja poista rastit niistä jotka haluat poistaa listaltasi. Kun olet valmis, paina "Tallenna muutokset". + +/interests.bml.enmasse.body.other_authas=Tässä ovat käyttäjän [[user]] kiinnostuksenkohteet. Rastita ruudut niitten kiinnostuksenkohteiden vierestä jotka haluat lisätä [[target]]:n listaan, ja poista rastit niistä jotka haluat poistaa listalta. Kun olet valmis, paina "Tallenna muutokset". + +/interests.bml.enmasse.body.you=Poista rastit niistä kiinnostuksenkohteista jotka haluat poistaa listalta. Kun olet valmis, paina "Tallenna muutokset". + +/interests.bml.enmasse.btn=Näytä lista + +/interests.bml.enmasse.header=Lisää/poista kiinnostuksenkohteita + +/interests.bml.enmasse.intro=Muokkaa kiinnostuksenkohteita seuraavan käyttäjän listaan perustuen: + +/interests.bml.error.add.mustlogin=Sinun täytyy olla kirjautuneena sisään, jotta voit lisätä kiinnostuksenkohteen tällä tavoin. + +/interests.bml.error.enmasse.mustlogin=Sinun täytyy olla kirjautunut sisään jotta voit käyttää tätä ominaisuutta. + +/interests.bml.error.enmasse.noaccess=Sinulla ei ole käyttöoikeutta päiväkirjaan nimeltä [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Kiinnostuksenkohdetta ei löytynyt. + +/interests.bml.error.nointerests=Valittua käyttäjää ei ole olemassa tai hän ei ole merkinnyt yhtään kiinnostuksenkohdetta. + +/interests.bml.findsim.searchwait=Huomaa: Haku kestää useita sekunteja. Ole kärsivällinen. + +/interests.bml.findsim_do.account.notallowed=Tilisi tyyppi ei estää sinua käyttämästä tätä työkalua. + +/interests.bml.findsim_do.magic=Maaginen
      luku + +/interests.bml.findsim_do.magic.head=Mikä ihmeen maaginen luku? + +/interests.bml.findsim_do.magic.text=Jokainen hakuehdon täyttävä käyttäjä saa maagisen luvun, joka on koostuu kahdesta tekijästä: samojen kiinnostuksenkohteiden määrästä ja yhteisistä harvinaisista kohteista, joista tulee vähän lisäpisteitä. + +/interests.bml.findsim_do.nomatch.head=Ei osumia + +/interests.bml.findsim_do.nomatch.text=Kukaan käyttäjä ei ole samankaltainen kuin [[user]]. + +/interests.bml.findsim_do.notdefined=Käyttäjällä [[user]] ei ole määriteltynä kiinnostuksenkohteita. + +/interests.bml.findsim_do.similar.head=Samankaltaiset käyttäjät + +/interests.bml.findsim_do.similar.text=Nämä ovat eniten käyttäjän [[user]] kaltaisia + +/interests.bml.finished.about=Kun olet valmis, paina "Tallenna muutokset"-nappia sivun alareunassa: + +/interests.bml.finished.header=Valmista? + +/interests.bml.finished.save_button=Tallenna muutokset + +/interests.bml.interest=Kiinnostuksenkohde + +/interests.bml.interested.btn.find=Etsi + +/interests.bml.interested.in=Etsi tästä kiinnostuneita henkilöitä ja yhteisöjä: + +/interests.bml.interests.findsim=Muokkaa kiinnostuksenkohteita seuraavan käyttäjän listaan perustuen: + +/interests.bml.interests.head=Kiinnostuksenkohteet + +/interests.bml.interests.text=Kiinnostuksenkohteita voi hyödyntää seuraavasti: + +/interests.bml.interests.viewpop=Näytä suosituimmat kiinnostuksenkohteet + +/interests.bml.login.enterinfo=Syötä käyttäjätunnuksesi ja salasanasi muokataksesi kiinnostuksenkohteitasi. + +/interests.bml.login.proceed=Jatka... + +/interests.bml.match=[[count]] tulos: + +/interests.bml.matches=[[count]] tulosta: + +/interests.bml.morestuff=Lisää kiinnostavaa löytyy kiinnostuksenkohdesivulta. + +/interests.bml.nointerests.text=Etkö ole listannut kiinnostuksenkohteitasi? Voit lisätä niitä henkilökohtaisten tietojen ja asetusten muokkaussivulla. + +/interests.bml.popular.disabled=Valitettavasti suositut kiinnostuksenkohteet -toiminto ei ole käytettävissä. + +/interests.bml.popular.head=Suositut kiinnostuksenkohteet + +/interests.bml.popular.text=Nämä ovat kaikkein suosituimmat kiinnostuksenkohteet. + +/interests.bml.results.added=Valitsemasi kiinnostuksenkohteet lisättiin listaasi. + +/interests.bml.results.both=Valitsemasi kiinnostuksenkohteet lisättiin listaasi, ja ne joista otit raksin pois poistettiin. + +/interests.bml.results.deleted=Kiinnostuksenkohteet joista otit raksin pois poistettiin listaltasi. + +/interests.bml.results.del_and_toomany=Kiinnostuksenkohteet, joiden kohdalta poistit valinnan on poistettu kiinnostuksenkohdelistaltasi. Valitsit kuitenkin liian monta uutta kohdetta. Sinulla voi olla vain [[intcount]] kiinnostuksenkohdetta, joten valitsemiasi ei lisätty listallesi. Voit yrittää uudestaan ja lisätä vähemmän uusia kohteita. + +/interests.bml.results.goback=Saatat haluta palata käyttäjän [[user]] profiiliin. + +/interests.bml.results.header=Tulokset + +/interests.bml.results.message=Katso päivitettyä profiilisivuasi. + +/interests.bml.results.nothing=Et tehnyt muutoksia. + +/interests.bml.results.toomany=Valitsit liian monta kiinnostuksenkohdetta lisättäväksi. Sinulla saa olla vain [[intcount]] kohdetta, joten valintojasi ei lisätty listaasi. Voit kuitenkin yrittää uudestaan ja lisätä vähemmän uusia kohteita. + +/interests.bml.title=Kiinnostuksenkohteet + +/interests.bml.toomany.body=[[intcount]] ihmistä ja yhteisöä on listannut tämän kiinnostuksenkohteekseen. Listaa ei näytetä. + +/interests.bml.toomany.head=Paljon osumia + +/interests.bml.users.head=Käyttäjät + +/interests.bml.users.text=Seuraavia käyttäjiä kiinnostaa [[interest]]. + +/invite/index.bml.code=Koodi + +/invite/index.bml.error=Virhe + +/invite/index.bml.genmore=Luo lisää koodeja + +/invite/index.bml.how_detail=Riippuen tietyistä tekijöistä, olemassaolevilla käyttäjillä on oikeus kutsua tietty määrä muita käyttäjiä sivustolle. Kutsuaksesi jonkun täytyy sinun luoda kutsukoodi ja sitten antaa se hänelle. + +/invite/index.bml.how_header=Kuinka se toimii? + +/invite/index.bml.invite_header=Kutsut? + +/invite/index.bml.none=Ei mitään + +/invite/index.bml.redeemed=Lunastanut käyttäjä + +/invite/index.bml.title=Kutsu muita LiveJournaliin... + +/invite/index.bml.unused=Käyttämätön + +/invite/index.bml.use=käytä + +/invite/index.bml.why_codes=Voidaksemme pitää yhteisön tiukkana, kontrolloidaksemme kasvua ja estääksemme väärinkäytöksiä täytyy tiliä luodessa joko ostaa tili tai saada kutsukoodi jo olemassa olevalta käyttäjältä. Tämän tarkoitus on tehdä yhteisöstämme parempi paikka sen käyttäjille, vaikkakin se aiheuttaa pienen harmin uusille käyttäjille. + +/legal/index.bml.about<< +LiveJournal on omistautunut tarjoamaan vakaan ja tarkoituksellisen kokemuksen kaikille jäsenillemme, joten olemme sopineet muutamia sääntöjä tätä varten. Asiakirjamme kertovat kuinka olemme valmistautuneet palvelemaan teitä parhaalla mahdollisella tavalla, ja kuinka oletamme jäsentemme käyttäytyvän. LiveJournal toimii parhaiten kun noudatamme näitä sääntöjä. Tässä on muutamia tärkeimmistä: +
        +
      • Älä kiusaa, häiritse tai uhkaile toisia.
      • +
      • Älä häiritse alaikäisiä käyttäjiämme.
      • +
      • Älä lähetä roskapostia yhdellekään sivuston sivuista tai käyttäjistä.
      • +
      • Älä käytä tekijänoikeudella suojattua materiaalia ilman lupaa.
      • +
      • Älä loukkaa muiden yksityisyyttä.
      • +
      • Älä riko USA:n tai oman maasi lakeja millään tavoin.
      • +
      +Täydellinen lista säännöistä ja käytännöistä löytyy alta. +. + +/legal/index.bml.about.header=Yleiskatsaus + +/legal/index.bml.docs.coppa.about=Children's Online Privacy Protection Act (COPPA) säätelee alle 13-vuotiaiden henkilöiden yhteystietojen keräämista ja niiden käyttöä. COPPA-sivumme selvittää asenteemme tätä lakia kohtaan ja hahmottaa kuinka siihen liittyviä asioita tulisi käsitellä. + +/legal/index.bml.docs.header=Asiakirjat + +/legal/index.bml.docs.privacy.about=Yksityisyysperiaatteemme selvittävät mitä tietoja keräämme jäsenistämme ja kertovat myös tietojen käytöstä. + +/legal/index.bml.docs.tos.about=Käyttöehdot hahmottelevat käyttäjäpolitiikkamme ja jäsenyyden yleiset ehdot. Järjestelmän käyttö ja/tai jäsenyys tarkoitavat sitä, että suostut noudattamaan näitä ja kaikkia muita sovittuja ehtoja. + +/legal/index.bml.title=Lakitietoa + +/legal/privacy.bml.title=Yksityisyysperiaatteet + +/legal/tos.bml.title=Käyttöehdot + +/login.bml.bindip.label=Sido IP-osoitteeseen: + +/login.bml.bindip.no=Älä (toimii kaikilla palveluntarjoajilla) + +/login.bml.bindip.yes=Kyllä (turvallisempi) + +/login.bml.error.mustenterusername=Sinun täytyy syöttää käyttäjätunnus. + +/login.bml.expire.btn.neverexpire=Vaihda kirjautuminen PYSYVÄKSI + +/login.bml.expire.btn.sessiononly=Vaihda kirjautuminen TÄMÄN ISTUNNON PITUISEKSI + +/login.bml.expire.neverexpire.text=Kirjautumisesi pysyy voimassa loputtomiin, joten jos olet julkisella Internet-päätteellä, koulussa, kirjastossa tai muussa sellaisessa paikassa, jossa muut käyttävät tätä tietokonetta, pidä huoli että kirjaudut ulos kun lopetat! Voit myös vaihtaa kirjautumisesi päättyväksi silloin, kun suljet selaimen. + +/login.bml.expire.sessiononly.text=Kirjautumisesi on voimassa siihen asti, kun suljet selaimesi. Jos tämä tietokone on sinun ja olet sen ainoa käyttäjä, voit halutessasi vaihtaa kirjautumisesi pysyväksi. + +/login.bml.links.head=Linkkejä + +/login.bml.links.link1=Kaverisivusi. + +/login.bml.links.link2=täältä. + +/login.bml.login.text3=Käyttäjä [[username]], olet kirjautunut sisään [[sitename]]-palveluun. Selaa sivustoa käyttämällä sivukarttaamme. + +/login.bml.login.username=Käyttäjätunnus: + +/login.bml.login.whenbrowsercloses=Kun selain suljetaan + +/login.bml.logout.btn=Kirjaudu ulos + +/login.bml.title=Kirjaudu sisään + +/login.bml.whylogin.benefit1=Sinun ei tarvitse enää syöttää käyttäjätunnustasi ja salasanaasi millään LiveJournalin sivulla. + +/login.bml.whylogin.benefit2=Näet kavereittesi "suojatut" päiväkirjamerkinnät, jos he ovat suoneet sinulle oikeuden lukea niitä. + +/login.bml.whylogin.benefit3=Monet ominaisuudet ovat näkyvissä tai käytettävissä ainoastaan sisäänkirjautuneena. + +/login.bml.whylogin.head=Miksi kirjautuisin sisään? + +/login.bml.whylogin.text=Tärkeimmät sisäänkirjautumisen edut: + +/logout.bml.already.head=Kirjauduit jo ulos + +/logout.bml.already.text=Olet jo kirjautunut ulos. + +/logout.bml.killall.btn=Päätä kaikki omat istunnot + +/logout.bml.killall.head=Muut istunnot + +/logout.bml.killall.text=Sinulla on muita aktiivisia istuntoja. Haluatko päättää kaikki yhteydet tämänhetkisen sijaan? (Lisätietoja.) + +/logout.bml.loggedout.already=Olet jo kirjautunut ulos. + +/logout.bml.loggedout.head=Kirjauduit ulos + +/logout.bml.loggedout.killedall=Kaikki olemassa olleet istunnot on päätetty. + +/logout.bml.loggedout.success=Sinut kirjattiin ulos. + +/logout.bml.loggedout.text=Olet nyt kirjautunut ulos. + +/logout.bml.logout.btn=Kirjaudu ulos + +/logout.bml.logout.head=Poistutko? + +/logout.bml.logout.text=Klikkaa alla olevaa nappia poistuaksesi. + +/logout.bml.title=Uloskirjautuminen + +/lostinfo.bml.btn.proceed=Jatka + +/lostinfo.bml.enter_email=Anna sähköpostiosoitteesi: + +/lostinfo.bml.enter_email_optional=Sähköposti: (valinnainen) + +/lostinfo.bml.enter_username=Syötä käyttäjätunnuksesi: + +/lostinfo.bml.error.no_email=Sinun täytyy antaa sähköpostiosoite tai et voi saada salasanamuistutusta. + +/lostinfo.bml.error.purged=Poistetulle ja tuhotulle tilille ei voida hakea salasanaa. + +/lostinfo.bml.error.renamed=Uudelleennimetylle tilille ei voi hakea salasanaa. + +/lostinfo.bml.error.syndicated=Tili jonka salasanaa yrität hakea on syndikoitu tili. Tämän tyyppisillä tileillä ei ole haettavaa salasanaa. + +/lostinfo.bml.error.sysbanned=Tilillesi ei sallita salasanojen lähettämistä sähköpostissa. + +/lostinfo.bml.lostpassword.text=Jos olet hukannut salasanasi, syötä käyttäjätunnuksesi ja valinnaisena se sähköpostiosoite, johon haluat saada salasanasi lähetetyksi. Huomaa myös, että osoitteesi täytyy olla sellainen, jonka olet varmentanut. Jos jätät sähköposti-kentän tyhjäksi, salasana lähetetään tämänhetkiseen osoitteeseesi. + +/lostinfo.bml.lostpassword.title=Hukkasitko salasanan? + +/lostinfo.bml.lostusername.text=Jos olet hukannut käyttäjätunnuksesi, syötä sähköpostiosoitteesi, ja lähetämme sinulle tunnuksesi. + +/lostinfo.bml.lostusername.title=Hukkasitko käyttäjätunnuksen? + +/lostinfo.bml.title=Puuttuvat tiedot + +/lostinfo_do.bml.error.no_usernames_for_email=Mikään käyttäjätunnus ei vastaa tätä osoitetta: [[address]] . + +/lostinfo_do.bml.error1.text=Et ole koskaan käyttänyt antamaasi sähköpostia tämän tilin yhteydessä, tai sitä ei koskaan varmennettu. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Tämä on automaattinen sähköpostiviesti. Sinun ei tarvitse vastata siihen. *** + +Tämä sähköposti on peräisin [[sitename]]-palvelusta ja lähetetään pyynnöstä. +Alla on käyttäjätunnuksesi, salasanasi ja se sähköpostiosoite, jolle päiväkirjasi on rekisteröity. + +Käyttäjätunnus: [[username]] + Salasana: [[password]] + Sähköposti: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Sähköpostiosoitteesi voi varmentaa täällä: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Nämä tiedot pyydettiin www:n kautta IP-osoitteesta [[remoteip]]. + +Ellet halunnut saada tätä salasanaa lähetetyksi sinulle, älä hätäänny. Sinähän olet ainoa, joka näkee tämän sähköpostin - ei kukaan muu. On mahdollista, että pyynnön tehnyt käyttäjä erehtyi ja että hän luulee omistavansa tämän käyttäjätunnuksen. On myös mahdollista, että joku teki kirjoitusvirheen käyttäjätunnukseensa tai sähköpostiosoitteeseensa. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Jos todella uskot, ettei tilisi ole turvassa, lue FAQ osoitteesta + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +Siinä kerrotaan, kuinka voit tehdä sen taas turvalliseksi. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Hyödyllisiä linkkejä: + + Päiväkirjasi: + [[journalurl]] + + Päivitä päiväkirjaasi internetissä: + [[updateurl]] + + Terveisin, + LiveJournal-tiimi + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Unohtunut salasana + +/lostinfo_do.bml.password_mailed.text=Onnistui. Salasanasi on lähetetty. + +/lostinfo_do.bml.password_mailed.title=Salasana lähetetty! + +/lostinfo_do.bml.title=Puuttuvat tiedot + +/lostinfo_do.bml.username_mailed.text=Onnistui. Käyttäjätunnuksesi on lähetetty. + +/lostinfo_do.bml.username_mailed.title=Käyttäjätunnus lähetetty! + +/manage/index.bml.about=Tilin hallinta on helppoa. Valitse vain alla olevista vaihtoehdoista: + +/manage/index.bml.communities=Luo ja hallitse omia yhteisöjäsi: + +/manage/index.bml.communities.create.about=Luo uusi yhteisö + +/manage/index.bml.communities.header=Yhteisöt + +/manage/index.bml.communities.manage.about=Hallitse yhteisöjesi asetuksia ja jäsenyyksiä + +/manage/index.bml.customization=Muuta päiväkirjasi ulkoasua: + +/manage/index.bml.customization.advanced=Edistynyt mukauttaminen + +/manage/index.bml.customization.advanced.about=Selaa, luo ja muokkaa S2-tyylejä ja ulkoasuja + +/manage/index.bml.customization.customize=Muokkaa päiväkirjaa + +/manage/index.bml.customization.customize.about=Muuta päiväkirjasi ulkoasua + +/manage/index.bml.customization.header=Räätälöinti + +/manage/index.bml.customization.links=Linkkilista + +/manage/index.bml.customization.links.about=Luo päiväkirjassasi näkyvä linkkilista + +/manage/index.bml.customization.modify.about=Muuta päiväkirjasi ulkoasua + +/manage/index.bml.customization.s1.header=Tyylijärjestelmä S1 + +/manage/index.bml.customization.s2.header=Tyylijärjestelmä S2 + +/manage/index.bml.entries=Työskentele tekemiesi päiväkirjamerkintöjen kanssa: + +/manage/index.bml.entries.edit.about=Muokkaa ja poista päiväkirjamerkintöjäsi + +/manage/index.bml.entries.header=Päiväkirjamerkinnät + +/manage/index.bml.entries.memories.about=Katso ja muokkaa muistettavia merkintöjäsi + +/manage/index.bml.friends=Muokkaa kavereita ja kaveriryhmiäsi tai suodata ystäväsivusi ryhmien mukaan: + +/manage/index.bml.friends.edit.about=Lisää, muokkaa ja poista käyttäjiä kaverilistaltasi tai muuta heitä edustavia värejä. + +/manage/index.bml.friends.filter=Suodata kaverisivu + +/manage/index.bml.friends.filter.about=Suodata kaverilistasi näyttämään tietty ryhmä + +/manage/index.bml.friends.groups.about=Luo, muokkaa tai poista kaverilistasi alaryhmiä + +/manage/index.bml.friends.header=Kaverit + +/manage/index.bml.information=Valitse tilisi asetukset ja tiedot: + +/manage/index.bml.information.changepass=Vaihda tilin salasana + +/manage/index.bml.information.changepass.about=Vaihda tilisi salasana + +/manage/index.bml.information.editinfo.about=Muuta tilin tietoja ja erilaisia asetuksia + +/manage/index.bml.information.emailpost=Sähköpostiasetukset + +/manage/index.bml.information.emailpost.about=Muuta sähköpostiosoitteita ja PIN-koodiasi sähköpostilla tehtävien merkintöjä varten + +/manage/index.bml.information.header=Tilin tiedot + +/manage/index.bml.information.siteopts.about=Valitse sivustolle haluamasi ulkoasu & kieli + +/manage/index.bml.information.status=Tilin tila + +/manage/index.bml.information.status.about=Määritä tilisi aktivointitila (poista tai palauta tilisi) + +/manage/index.bml.login=Seuraavat linkit vievät sinut sivuille joilla tarvitset sisäänkirjautumista. Säästääksesi aikaa, voit kirjautua sisään jo etukäteen. + +/manage/index.bml.title=Muokkaa tiliä + +/manage/index.bml.userpictures=Lisää ja muokkaa tilisi käyttäjäkuvia: + +/manage/index.bml.userpictures.edit.about=Lisää ja muokkaa käyttäjäkuviasi + +/manage/index.bml.userpictures.header=Käyttäjäkuvat + +/manage/links.bml.about=Käytä alla olevaa lomaketta luodaksesi linkkilistan, joka näkyy päiväkirjassasi. Linkit näkyvät vain, jos valitsemasi S2-tyyli tukee tätä toimintoa. + +/manage/links.bml.about.blank=Luodaksesi tyhjän rivin, laita otsikoksi vain viiva (-) + +/manage/links.bml.about.heading=Luodaksesi otsikon syötä otsikko, mutta älä osoitetta. + +/manage/links.bml.about.reorder=Järjestääksesi listaa, muuta vasemmalla olevia numeroita (desimaaliluvut käyvät). + +/manage/links.bml.error.s2required=Linkkilista on käytettävissä vain sitä tukevissa S2-tyyleissä. Vaihtaaksesi S2-tyylijärjestelmään, ks. sivu [[link]]. + +/manage/links.bml.error.s2required.header=S2 pakollinen + +/manage/links.bml.success=Onnistui! Linkkisi on tallennettu. + +/manage/links.bml.title=Linkkilista + +/manage/phonepost.bml.delete=Poista asetukset + +/manage/phonepost.bml.deleted=Puhelumerkintäasetuksesi on poistettu. + +/manage/phonepost.bml.deleted.header=Poistettu + +/manage/phonepost.bml.error.inuse=Väärä PIN-koodi, koeta uudestaan + +/manage/phonepost.bml.error.phone.length=Puhelinnumerossasi täytyy olla vähintään kymmenen numeroa. + +/manage/phonepost.bml.error.pin=PIN-koodisi täytyy olla numeroita. + +/manage/phonepost.bml.error.transcription=Virheellinen kaveriryhmä tekstitykseen + +/manage/phonepost.bml.intro.loggedin<< +puhelumerkintöjä, täytä puhelinnumero ja PIN-koodi alle. p?> +yksityisyysperiaatteemme). +Muista numeroista tehdyt puhelut sallitaan, mutta sinun täytyy syöttää hyväksytty puhelinnumerosi ennen kuin voit nauhoittaa merkintäsi. p?> + +. + +/manage/phonepost.bml.intro.loggedout=-palvelun jäsenet voivat kirjautua sisään ja muuttaa puhelumerkintäasetuksiaan täällä: + +/manage/phonepost.bml.phone=Hyväksytty puhelinnumero: + +/manage/phonepost.bml.phone.help=358 9 1234567 + +/manage/phonepost.bml.pin=Tunnistenumero (PIN): + +/manage/phonepost.bml.pin.help=Suositus 4-6 numeroa + +/manage/phonepost.bml.save=Tallenna asetukset + +/manage/phonepost.bml.saved=Tallennettu + +/manage/phonepost.bml.success.moreinfo=Lisätietoa puhelumerkinnän tekemisestä saat seuraavasta FAQ:sta Kuinka nauhoitan äänimerkinnän päiväkirjaani?. + +/manage/phonepost.bml.success.text=Puhelinasetuksesi on tallennettu + +/manage/phonepost.bml.title=Puhelumerkintäasetukset + +/manage/phonepost.bml.transcribers=Sallitut tekstittäjät: + +/manage/phonepost.bml.transcribers.help=Muokkaa kaveriryhmiä + +/manage/pubkey.bml.error.invalidkey=Tämä ei näytä olevan toimiva PGP/GPG-avain. + +/manage/pubkey.bml.error.notconfigured=Tätä sivustoa ei ole asetettu PGP-tukeen. + +/manage/pubkey.bml.header=PGP/GPG-avain + +/manage/pubkey.bml.info=Julkisen avaimesi julkaiseminen antaa muille mahdollisuuden nähdä sen käyttäjätietosivusi kautta, ja voit tehdä allekirjoitettuja sähköpostimerkintöjä. Ohjeet löydät täältä. + +/manage/pubkey.bml.pastekey=Liitä koko julkinen avaimesi (ascii-muodossa) alla olevaan kenttään: + +/manage/pubkey.bml.save=Tallenna + +/manage/pubkey.bml.successhead=Onnistui + +/manage/pubkey.bml.successtext=Julkinen avaimesi on tallennettu. Voit nähdä sen täällä. + +/manage/pubkey.bml.title=Aseta julkinen avain + +/manage/pubkey.bml.whatis=Etkö tiedä mikä julkinen avain on? Tarvitsetko apua avaimesi käytössä? Lue lisää PGP:stä ja GPG:stä. + +/manage/siteopts.bml.btn.lang=Vaihda kieltä + +/manage/siteopts.bml.btn.scheme=Vaihda teemaa + +/manage/siteopts.bml.head.lang=Valitse kielesi + +/manage/siteopts.bml.head.scheme=Valitse haluamasi teema + +/manage/siteopts.bml.scheme.preview=[Teeman [[title]] esikatselu] + +/manage/siteopts.bml.title=Käyttöasetukset + +/meme.bml.meme.disabled=Sivuston valvoja on estänyt tämän toiminnon käytön. + +/modify.bml.title=Muokkaa päiväkirjaa + +/modify_do.bml.availablestyles.head=Käytettävissä olevat tyylit + +/modify_do.bml.availablestyles.userstyles=Käyttäjien tyylit + +/modify_do.bml.colortheme.about=Tästä voit valita, millaisen värityksen haluat yllä valitsemillesi sivun asettelulle. Ellet pidä tarjotuista väreistä, voit määrittää omat värisi! + +/modify_do.bml.colortheme.area.head=Käyttöalue + +/modify_do.bml.colortheme.color.head1=Väri + +/modify_do.bml.colortheme.color.head2=(#rrggbb tai nimi) + +/modify_do.bml.colortheme.customcolors=Käyttäjän omat värit + +/modify_do.bml.colortheme.defaulttheme=Oletusteema + +/modify_do.bml.colortheme.head=Väriteema + +/modify_do.bml.domainalias.about=Jos sinulla on domain-nimi, jonka olet jo rekisteröinyt (tai jonka aiot rekisteröidä) ja jonka haluat automaattisesti lataavan päiväkirjasi, syötä se tähän: + +/modify_do.bml.domainalias.domainname=Domain-nimi: + +/modify_do.bml.domainalias.example=Esimerkki: my-journal.com + +/modify_do.bml.domainalias.head=Domain-nimen kytkentä + +/modify_do.bml.domainalias.helptext=Jotta tämä toimisi, sinun täytyy järjestää domainnimesi DNS osoittamaan samaan IP-osoitteeseen [[sitename]]:n kanssa. Saadaksesi lisätietoa, lue tämä FAQ. + +/modify_do.bml.done.btn.savechanges=Tallenna muutokset + +/modify_do.bml.done.head=Tuliko valmista? + +/modify_do.bml.done.text=Kun olet tehnyt haluamasi muutokset, paina "Tallenna muutokset" -nappulaa... + +/modify_do.bml.error.dupdomainalias=Toinen käyttäjä on jo rekisteröinyt valitsemasi domainnimen. + +/modify_do.bml.error.stylenotavailable=Yksi valitsemistasi tyyleistä ei ole käytettävissä. Tämä johtuu joko siitä, että tyyli on poistettu, tai siitä, ettei sinulla ole oikeutta käyttää sitä. + +/modify_do.bml.friends.about=Nämä asetukset säätelevät sitä, miltä kaverisivusi näyttää. + +/modify_do.bml.friends.head=Kaverilista + +/modify_do.bml.friends.opt.usesharedpic.about=Tämä asetus määrittää, minkä kuvan näet kaverisivullasi, kun joku kirjoittaa jaettuun päiväkirjaan tai yhteisöön. Jos se on valittuna, näet yhteisön kuvan. Jos se on valitsematta, näet sen henkilön käyttäjäkuvan, joka lähettää viestin. + +/modify_do.bml.friends.opt.usesharedpic.head=Käytä jaetun päiväkirjan kuvaa käyttäjän oman kuvan sijaan + +/modify_do.bml.journaloptions.about=Tästä voit muokata LiveJournal-sivujesi ulkoasua haluamaksesi. Jos todella haluat tietää, miten kaikki tämä toimii, lue kehittäjien sivuja. Muuten oletamme sinun tyytyvän alla oleviin perusasetuksiin: + +/modify_do.bml.journaloptions.head=Päiväkirjan asetukset + +/modify_do.bml.journalstatus.about=Jos haluat poistaa tai palauttaa päiväkirjasi, tee se tästä. Kun olet poistanut päiväkirjasi, sinulla on 30 päivää aikaa palauttaa se, jos muutat mieltäsi. 30 päivän jälkeen päiväkirjasi poistetaan lopullisesti, eikä sitä voi enää palauttaa mitenkään. + +/modify_do.bml.journalstatus.head=Päiväkirjan tila + +/modify_do.bml.journalstatus.select.activated=Käytössä + +/modify_do.bml.journalstatus.select.deleted=Poistettu + +/modify_do.bml.journalstatus.select.head=Tila: + +/modify_do.bml.journalstatus.select.suspended=Jäädytetty + +/modify_do.bml.moodicons.about=Kun kirjoitat päiväkirjamerkintöjä, voit myös sisällyttää senhetkisen mielialasi viestiin. Käyttäjät ovat antaneet kaikkien käyttöön useita "mielialakuvakkeita". Valitse "Ei kuvakkeita", ellet halua pientä kuvaa mielialasi viereen. (Sinun ei tarvitse käyttää tämänhetkinen mieliala -ominaisuutta lainkaan.) + +/modify_do.bml.moodicons.head=Mielialakuvakkeet + +/modify_do.bml.moodicons.opt.forcefriends.about=Käytä näitä mielialakuvakkeita myös kaverisivulla kaikille + +/modify_do.bml.moodicons.personal=Henkilökohtaiset teemat: + +/modify_do.bml.moodicons.preview=esikatselu + +/modify_do.bml.moodicons.select=Valitse käytettävät mielialakuvakkeet: + +/modify_do.bml.overrides.about=Tämän osion voi jättää huomiotta, jos olet tyytyväinen päiväkirjasi ulkoasuun. Se on tarkoitettu erittäin yksityiskohtaiseen sivun asettelun muokkaamiseen. Katso perusasiat täältä ja yksityiskohtia kehittäjien sivuilta. Huomaa myös, että korvaavuudet on tarkoitettu vain parin tyyliseikan korvaamiseen. Jos haluat korvata kaiken, sinun pitää luoda oma tyyli. Saadaksesi lisätietoja tyylien luomisesta, katso tämä FAQ. + +/modify_do.bml.overrides.box.head=Korvaavuudet: + +/modify_do.bml.overrides.head=Tyylien korvaavuudet: + +/modify_do.bml.overrides.note=Huomaa, ettei kaikkia tyylimuuttujia voi korvata. Katso dokumentaatiosta lisätietoja.
      Pidä myös mielessä, että jos yrität muokata korvaavuuksia ja olet käyttänyt sellaista HTML-koodia, joka ei ole sallittu dokumentin head-osiossa (otsikko-osiossa)–kuten <DIV>, <SPAN>, <IMG> ja monia muita–kyseinen koodi leikataan pois. Sallittuja HTML-elementtejä *_HEAD-korvaavuuksissa ovat ainoastaan ne elementit, jotka ovat valideja HTML-dokumentissa. Niitä ovat <title>, <base>, <style>, <link> ja <meta>. + +/modify_do.bml.overrides.warning=TÄHÄN EI PIDÄ KIRJOITTAA PÄIVÄKIRJAMERKINTÖJÄ! + +/modify_do.bml.pagelayoutstyle.about=Tämä asetus määrittää, kuinka päiväkirjasi asetellaan näytölle. + +/modify_do.bml.pagelayoutstyle.head=Sivun asettelutyyli + +/modify_do.bml.pagelayoutstyle.warning=Tilisi tyyppi sallii sinun valita vain yhden muutamista oletustyyleistä. + +/modify_do.bml.success.head=Onnistui + +/modify_do.bml.success.text=Päiväkirjasi asetukset on päivitetty. Voit nähdä päiväkirjasi tästä. + +/multisearch.bml.formaterror=Tiedostomuotovirhe + +/multisearch.bml.noaddress.text=Et syöttänyt sähköpostiosoitetta. + +/multisearch.bml.noaddress.title=Ei osoitetta + +/multisearch.bml.nointerest.text=Et syöttänyt kiinnostuksenkohdetta. + +/multisearch.bml.nointerest.title=Ei kiinnostuksenkohdetta + +/multisearch.bml.nomatch.text=Antamillasi hakuehdoilla ei löytynyt tuloksia. + +/multisearch.bml.nomatch.title=Ei tuloksia + +/multisearch.bml.region.bodytext<< +Voit etsiä sijainnin mukaan seuraavissa muodoissa: +
        +
      • Maa
      • +
      • Kaupunki *
      • +
      • Kaupunki, osavaltio *
      • +
      • Osavaltio, maa
      • +
      • Kaupunki, osavaltio, maa
      • +
      +Huomattavaa: +
        +
      • * vain kaupunkia tai kaupunkia ja osavaltiota etsittäessä oletetaan haun koskevan Yhdysvaltoja.
      • +
      • Maa voi olla joko maan koko nimi tai sen kaksikirjaiminen tunnus
      • +
      +Jos haluat tehdä erilaisen haun, käytä hakemistohakua. +. + +/multisearch.bml.region.head=Etsi alueen perusteella + +/paidaccounts/index.bml.costs.header=No, kuinka paljon tämä maksaa? + +/paidaccounts/index.bml.costs.rates=Hinnat ovat seuraavat: + +/paidaccounts/index.bml.costs.rates.amount.header=Hinta + +/paidaccounts/index.bml.costs.rates.inexpensive<< +Tästä laskemalla saadaan vuoden maksulle hieman yli $2 USD/kk. +Se tuskin käy kohtuuttomaksi pankkitilillesi. +Suurin urakka koostuukin luultavasti lompakon esiin ottamisesta, luottokortin etsimisestä ja tietojesi syöttämisestä. + +. + +/paidaccounts/index.bml.costs.rates.time.header=Kesto + +/paidaccounts/index.bml.features<< +
      Osoittaaksemme kunnioitusta lahjoituksia tehneille käyttäjille, olemme antaneet heille käyttöön muutamia ominaisuuksia jotka toimivat vain maksetuilla tileillä. Näihin ominaisuuksiin kuuluvat:
      + +
      Uutta! Tee merkintöjä sähköpostin kautta
      +
      Maksaneet käyttäjät voivat tehdä merkintöjä päiväkirjoihin ja yhteisöihinsä nopeasti ja turvallisesti sähköpostinsa kautta.
      + +
      Päiväkirjan mukauttaminen
      +
      Sen lisäksi että pystyt valitsemaan päiväkirjasi tyylin ja värit, voit luoda oman tyylisi käyttäen haluamaasi HTML-koodia. Tämän ansiosta voit luoda myös uusia tyylejä jotka sopivat yhteen sivujesi kanssa ja voit myös upottaa päiväkirjasi sivuillesi paljastamatta, että käytät LiveJournalia.
      + +
      Kyselyt
      +
      Maksaneet käyttäjät voivat luoda kyselyitä omiin päiväkirjoihinsa, sekä kaikkiin yhteisöihin joissa ovat jäsenenä.
      + +
      Useampia käyttäjäkuvia
      +
      Maksaneilla käyttäjillä saa olla 15 käyttäjäkuvaa, kun taas ilmaiset käyttäjät joutuvat tyytymään kolmeen.
      + +
      LiveJournal.com-sähköpostialias
      +
      Kaikki osoitteeseen [[username]]@livejournal.com tuleva sähköposti voidaan lähettää edelleen henkilökohtaiseen sähköpostiosoitteeseesi.
      + +
      Hakemistohaut
      +
      Maksaneilla käyttäjillä on mahdollisuus käyttää käyttäjähakemistoa toisten käyttäjien etsimiseen.
      + +
      LiveJournal.com-osoite
      +
      Tavallisen http://www.livejournal.com/users/[[username]]/ -osoitteen sijaan, päiväkirjaasi pääsee myös osoitteesta http://[[username]].livejournal.com/, joka on paljon lyhyempi ja henkilökohtainen.
      + +
      Syndikaatio
      +
      Maksaneet käyttäjät voivat luoda uusia syndikoituja tilejä, jotka ovat RSS-syötteitä.
      + +
      Tekstiviestit
      +
      Maksaneet käyttäjät voivat vastaanottaa tekstiviestejä puhelimeen tai hakulaitteeseensa LiveJournalin kautta.
      + +
      Enemmän tehtävää-merkintöjä
      +
      Maksaneet käyttäjät voivat luoda jopa 150 merkintää ja muuttaa jokaisen turvatasoa.
      + +
      Upottaminen
      +
      Maksaneilla käyttäjillä on täydet mahdollisuudet muokata päiväkirja kotisivuihin sopivaksi. Lisää tästä löytyy FAQ-osiosta "Upottaminen".
      + +
      Domain-nimet
      +
      Maksaneet käyttäjät voivat kytkeä oman domain-nimensä osoittamaan päiväkirjaan.
      + +
      Lisää...
      +
      Täydellinen lista eduista löytyy täältä.
      +. + +/paidaccounts/index.bml.features.header=Mitä hienoja ominaisuuksia sitten saan? + +/paidaccounts/index.bml.title=Maksetut tilit + +/paidaccounts/index.bml.whypay.argument<< +Ei tietenkään. Www-palveluista maksaminen on ärsyttävää meidänkin mielestämme. +Siksi lähes kaikki LiveJournalin ominaisuudet ovat käytettävissä maksutta. +Jos kuitenkin olet tyytyväinen sinulle tarjottuun palveluun, tuo tukesi julki ja hanki maksettu tili. +. + +/paidaccounts/index.bml.whypay.header=Täytyykö minun maksaa LiveJournalin käytöstä? + +/paidaccounts/index.bml.whypay.no_ads=Verkkopalveluiden ylläpito vie rahaa (palvelimia, niiden sijoittamista ja verkkoyhteyksiä varten), ja tämä vaikuttaa paremmalta tavalta kuin hukuttaa käyttäjät ponnahdusikkunamainoksiin tai sähköpostina lähetettäviin kaupallisiin tiedotteihin. + +/paidaccounts/index.bml.your_username=kayttajatunnus + +/paidaccounts/usepaypal.bml.delivery.badformat=Virheellinen toimituspäivämäärän muoto. Sen täytyy olla joko vvvv-kk-pp tai vvvv-kk-pp tt:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Toimistuspäivämäärä ei voi olla menneisyydessä. Jätä toimituspäivämäärälaatikko tyhjäksi, jos haluat sen lähtevän heti. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Toimituspäivämäärä saa olla enintään kuukauden verran tulevaisuudessa. + +/pay/index.bml.deliverydate.details=Muoto: vvvv-kk-pp tt:mm (GMT-aika)
      (jätä tyhjäksi, jos haluat toimituksen heti) + +/pay/index.bml.deliverydate.label=Toimitusajankohta: + +/pay/index.bml.gift.anonymous=Nimetön lahja + +/poll/create.bml.button.editpoll=Muokkaa kyselyä + +/poll/create.bml.button.insert=Syötä + +/poll/create.bml.button.postpoll=Lähetä kysely + +/poll/create.bml.button.preview=Esikatsele kysely + +/poll/create.bml.button.seecode=Näytä koodi + +/poll/create.bml.button.startover=Aloita uudestaan + +/poll/create.bml.elements.limitreached=Elementtiraja saavutettu + +/poll/create.bml.error.accttype=Tilityyppisi ei salli kyselypalvelun käyttöä. + +/poll/create.bml.error.allitemsblank=Kaikki kohdat eivät voi olla tyhjiä. + +/poll/create.bml.error.notext=Tarvitset kysymystä selittävän tekstin + +/poll/create.bml.error.parsing=Virhe luotaessa kyselyä: + +/poll/create.bml.error.pqmaxlengthinvalid=Maxlength-attribuutti lj-pq -tekstikoodeissa täytyy olla kokonaisluku väliltä [[min]]-[[max]]. + +/poll/create.bml.error.pqsizeinvalid=Size-attribuutti lj-pq -tekstikoodeissa täytyy olla kokonaisluku väliltä [[min]]-[[max]]. + +/poll/create.bml.error.scalemaxlessmin=Koon "mistä"-arvon tulee olla pienempi kuin "mihin"-arvon. + +/poll/create.bml.error.scalemininvalid=Koon kasvu täytyy olla vähintään [[min]]. + +/poll/create.bml.error.scaletoobig=[[max]] valinnan maksimiraja (mistä-mihin)/mennessä > 20 + +/poll/create.bml.error.texttoolong=Vaihtoehtosi teksti oli liian pitkä, joten se katkaistiin. + +/poll/create.bml.haserrors=Kyselyssäsi on yksi tai useampi virhe. Alta saat lisätietoja. + +/poll/create.bml.insertquestion=Syötä kysymys tähän: + +/poll/create.bml.options=Vaihtoehdot: + +/poll/create.bml.options.limitreached=Vaihtoehtoraja saavutettu + +/poll/create.bml.pollname=Kyselyn nimi: (vaihtoeht.) + +/poll/create.bml.preview.desc=Alla on kyselysi esikatselu. Kysely näyttää juuri tältä päiväkirjassasi. Käytä alla olevia painikkeita palataksesi tekemään muutoksia tai lähetä kysely päiväkirjaasi. + +/poll/create.bml.preview.options=Vaihtoehdot + +/poll/create.bml.properties=Kyselyn ominaisuudet + +/poll/create.bml.question=Kysymys: + +/poll/create.bml.questionnum=Kysymys #[[num]] + +/poll/create.bml.questions=Kyselyn kysymykset + +/poll/create.bml.title=Kyselyn luonti + +/poll/create.bml.type.check=Valintaruudut + +/poll/create.bml.type.drop=Pudotusvalikko + +/poll/create.bml.type.radio=Radionappulat + +/poll/create.bml.type.scale=Koko + +/poll/create.bml.type.text=Tekstin syöttä + +/poll/create.bml.whoview=Kuka voi nähdä kyselyn? + +/poll/create.bml.whovote=Kuka voi vastata kyselyyn? + +/poll/index.bml.discuss=Keskustelun tulokset + +/poll/index.bml.error.cantview=Et saa valitettavasti nähdä tätä kyselyä. + +/poll/index.bml.error.postdeleted=Alkuperäinen merkintä poistettu, joten kysely ei enää käytössä. + +/poll/index.bml.filloutpoll=Täytä kysely + +/poll/index.bml.gotocreate=Tässä osoitteessa voit osallistua kyselyyn. Olet sattumalta osunut osoitteeseen, joka ei tällä hetkellä tee mitään. Halutessasi voit luoda uuden kyselyn. + +/poll/index.bml.pollnotfound=Kyselyä ei löytynyt. + +/poll/index.bml.submitted.head=Kiitos + +/poll/index.bml.submitted.text=Kyselyvastauksesi on tallennettu. + +/poll/index.bml.submitted.title=Tallennettu! + +/poll/index.bml.title=Kysely + +/poll/index.bml.viewresults=Näytä kyselyn tulokset + +/press/staff.bml.accountserv=Tilipalvelut + +/press/staff.bml.administration=Ylläpito + +/press/staff.bml.administration.about=Livejournal.com alkoi vuonna 1999 Brad Fitzpatrickin projektina ja kahden ensimmäisen elinvuotensa aikana se sai ympärilleen ison ja lojaalin ryhmän vapaaehtoisia. Vaikka suuri osa LiveJournal.comista toimiikin vapaaehtoistyön avulla, meillä on nyt pieni virallinen henkilöstö joka valvoo kaikkia toimintoja: + +/press/staff.bml.avva.title=Vanhempi kehittäjä + +/press/staff.bml.back2=Takaisin lehdistöalueelle + +/press/staff.bml.bradfitz.quip=Keskitä voimavarasi tuotteeseesi äläkä vain rahan ansaitsemiseen. + +/press/staff.bml.bradfitz.title=Johtaja ja pääasiallinen kehittäjä + +/press/staff.bml.contact=Jos haluat saada yhteyden johonkuhun meistä, ole hyvä ja lähetä sähköpostia osoitteeseen webmaster@livejournal.com. + +/press/staff.bml.custserv=Asiakaspalvelu / Käytettävyystutkimus + +/press/staff.bml.david.title=Työharjoittelija + +/press/staff.bml.denisep.quip=Palataan asiaan ensi torstaina + +/press/staff.bml.denisep.title=Vapaaehtoisvastaava ja käytettävyysasiantuntija + +/press/staff.bml.deveiant.title=Ulkoinen kehittäjä + +/press/staff.bml.developers=Kehittäjät + +/press/staff.bml.evan.quip=Fnord + +/press/staff.bml.evan.title=Emeritushakkeri + +/press/staff.bml.ferrell.title=Asiakaspalveluvastaava + +/press/staff.bml.jproulx.quip=Nörtti käyttäjäsuhteissa + +/press/staff.bml.jproulx.title=Yhteisösivuston valvoja ja lehdistövastaava + +/press/staff.bml.kevin.title=Grafiikka- ja webdesignsuunnittelija + +/press/staff.bml.lisa.title=Järjestelmävastaava + +/press/staff.bml.mahlon.quip=Uuk uuk! + +/press/staff.bml.mahlon.title=Koodiapina + +/press/staff.bml.nick.title=Järjestelmävastaava + +/press/staff.bml.ryanfitz.title=Maksupalvelut + +/press/staff.bml.sandy.title=Kirjanpito ja hallinto + +/press/staff.bml.smithy.title=Harjoittelijahakkeri + +/press/staff.bml.sysadmin=Järjestelmävastaavat + +/press/staff.bml.title=Henkilöstö + +/press/staff.bml.whitaker.quip=Mitä seuraavaksi? + +/press/staff.bml.whitaker.title=Ulkoinen kehittäjä + +/pubkey.bml.error.notconfigured=Tätä sivustoa ei ole asetettu PGP-tukeen. + +/pubkey.bml.error.nousername=Käyttäjänimeä ei annettu. + +/pubkey.bml.info.desc=Etkö tiedä mikä julkinen avain on? Lue lisää PGP:stä ja GPG:stä. + +/pubkey.bml.info.head=Tietoja + +/pubkey.bml.info.upload=Haluatko syöttää avaimesi? Klikkaa tästä. + +/pubkey.bml.label=Käyttäjän [[user]] julkinen avain: + +/pubkey.bml.nokey=Käyttäjä [[user]] ei ole vielä syöttänyt julkista avainta. + +/pubkey.bml.title=Näytä julkinen avain + +/register.bml.ask.body=Klikkaa alla olevaa painiketta lähettääksesi -varmistusviestin osoitteeseen [[email]]. + +/register.bml.ask.button=Lähetä + +/register.bml.ask.header=Varmenna sähköpostiosoite + +/register.bml.asterisk.comment=(Huomaa, että tähdellä merkittyjä tilejä ei ole vielä varmennettu) + +/register.bml.email.body<< +Tämä on pyytämäsi varmistusviesti. Saattaaksesi tilin luonti päätökseen käy osoitteessa: + + [[conflink]] + +Voi olla, että sinun täytyy kopioida ja liittää osoite selaimesi osoitekenttään. + +Terveisin, +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Varmenna sähköpostiosoite + +/register.bml.error.invalidcode=Virheellinen varmennuskoodi. + +/register.bml.error.useralreadyvalidated=Käyttäjän [[user]] sähköpostiosoite on jo varmennettu. + +/register.bml.error.usernotfound=Käyttäjää ei löytynyt. + +/register.bml.new.body=Kiitos! Sähköpostiosoiteesi on nyt varmennettu. Tästä eteenpäin saatat olla kiinnostunut seuraavista asioista: + +/register.bml.new.editinfo=Muuta käyttäjätietoja -- Täytä käyttäjätietosi ja muuta erilaisia asetuksia. + +/register.bml.new.header=Onnistui + +/register.bml.new.login=Kirjaudu sisään -- Näin sinun ei tarvitse aina kirjoittaa käyttäjänimeäsi ja salasanaasi. + +/register.bml.new.modify=Muokkaa päiväkirjaa -- Muuta päiväkirjasi ulkoasua. + +/register.bml.new.update=Päivitä päiväkirjaa -- Kirjoita päiväkirjaasi. + +/register.bml.sent.body=Varmennusviesti on lähetetty osoitteeseen [[email]]. Saattaaksesi varmennuksen loppuun klikkaa sähköpostiviestissä olevaa linkkiä. + +/register.bml.sent.header=Onnistui + +/register.bml.title=Varmenna sähköpostiosoite + +/register.bml.trans.body=Uusi sähköpostiosoitteesi on varmennettu. + +/register.bml.trans.header=Onnistui + +/rename/index.bml.does=Päiväkirjan uudelleennimeäminen muuttaa vain käyttäjänimen. Kaikki muu - maksettu tai pysyvä tili, käyttäjäoikeudet, henkilötiedot, kaverit ja muut päiväkirjaan liittyvät tiedot - säilyvät ennallaan ja yhdistetään uuteen käyttäjänimeen. Kaikki olemassa olevat merkinnät ja kommentit muissa päiväkirjoissa ja yhteisöissä näyttävät uuden käyttäjänimen. + +/rename/index.bml.faqurl=Lisätietoja uudelleennimeämisestä saat tästä FAQ-vastauksesta. + +/rename/index.bml.fee=LiveJournal-käyttäjätunnuksesi muuttaminen maksaa [[fee]]. + +/rename/index.bml.heading.cost=Hinta + +/rename/index.bml.heading.details=Yksityiskohdat + +/rename/index.bml.heading.how=Kuinka ostaa + +/rename/index.bml.option=Voit vaihtoehtoisesti ohjata vanhan käyttäjänimesi uuteen tai merkitä sen poistetuksi. Voit myös pitää vanhat kaverisi uuden käyttäjänimesi kanssa tai poistaa itsesi muiden kaverilistoilta. + +/rename/index.bml.options.buy=Osta poletti + +/rename/index.bml.options.buy.desc=Osta uudelleennimeämispoletti. + +/rename/index.bml.options.use=Käytä poletti + +/rename/index.bml.options.use.desc=Käytä uudelleennimeämispoletti. + +/rename/index.bml.redeem=Ensin ostat uudelleennimeämispoletin, joka lähetetään sinulle sähköpostilla. Saatuasi poletin voit käyttää sen tehdäksesi uudelleennimeämisen. Uudelleennimeämispoleteista voi saada rahanpalautusta, mutta ne voi siirtää. Voit siis ostaa poletin toisellekin käyttäjälle. + +/rename/index.bml.reserve=Sinun ei tarvitse luoda tiliä uudella käyttäjänimelläsi voidaksesi käyttää nimeä. Jos olet huolissasi siitä, että joku muu käyttää nimeä ennen kuin voit ostaa poletin, voit luoda tilin kyseisellä nimellä. Käytä luodessasi kuitenkin samaa sähköpostiosoitetta ja salasanaa kuin tämänhetkisessä tilissäsi. + +/rename/index.bml.title=Tilin uudelleennimeämispalvelu + +/rename/index.bml.whatrename=Voit muuttaa vain oman tilisi nimeä, et omistamiesi yhteisöjen. + +/rename/use.bml.changes=Seuraavat muutokset tehdään kun uudelleennimeäminen on valmis: + +/rename/use.bml.changes.move="[[newuser]]" siirretään erilleen käyttäjänimestä "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" uudelleennimetään käyttäjänimeksi "[[newuser]]" + +/rename/use.bml.confirm=Kun klikkaat "Nimeä uudelleen" alta, muutosta ei voida peruuttaa. Varmistuksena kirjoita "[[confirmword]]" alla olevaan laatikkoon. + +/rename/use.bml.confirm.click=Ja sitten, klikkaa "Nimeä uudelleen": + +/rename/use.bml.error.allocating=Virhe varatessa nimeä muutettavalle tilille. + +/rename/use.bml.error.badpass=Uuden ja vanhan käyttäjänimen salasanat eivät ole samanlaiset. + +/rename/use.bml.error.differentusername=Et ollut kirjautunut sisään tällä käyttäjänimellä ladatessasi lomakkeen. + +/rename/use.bml.error.login=Mutta ensin sinun täytyy kirjautua sisään. + +/rename/use.bml.error.readit=Lue yllä oleva kappale. + +/rename/use.bml.error.reserved=Virhe siirrettäessä varattua tilinimeä. + +/rename/use.bml.error.same=Tämä on sama kuin vanha käyttäjänimesi. + +/rename/use.bml.error.token=Virheellinen uudelleennimeämispoletti. + +/rename/use.bml.error.type=Vain tavalliset tilit voi uudelleennimetä, ei yhteisötilit. + +/rename/use.bml.error.unknown=Tuntematon virhe muutettaessa nimeä. + +/rename/use.bml.error.usedtoken=Tämä poletti on jo käytetty. + +/rename/use.bml.error.username=Virheellinen käyttäjänimi. + +/rename/use.bml.error.usernametaken=Kyseinen käyttäjänimi on jo käytössä. + +/rename/use.bml.heading.changes=Muutokset + +/rename/use.bml.heading.success=Onnistui + +/rename/use.bml.heading.sure=Oletko varma? + +/rename/use.bml.intent=Tällä sivulla voit uudelleennimetä tilisi kun olet lukenut esittelyn ja ostanut uudelleennimeämispoletin. + +/rename/use.bml.label.desired=Haluttu käyttäjänimi: + +/rename/use.bml.label.proceed=Jatka... + +/rename/use.bml.label.rename=Nimeä uudelleen + +/rename/use.bml.label.token=Uudelleennimeämispoletti: + +/rename/use.bml.label.username=Tämänhetkinen käyttäjänimi: + +/rename/use.bml.options=Uudelleennimeämisasetukset: + +/rename/use.bml.options.delfriends=Poista kaikki käyttäjät kaverilistaltasi ja eroa kaikista yhteisöistä. + +/rename/use.bml.options.forward=Automaattinen ohjaus käyttäjänimestä [[oldname]] uuteen nimeen. + +/rename/use.bml.options.keepfriends=Säilytä kaikki käyttäjät ja yhteisöt kaverilistallasi. + +/rename/use.bml.options.keepself=Säilytä kaikki Kenen kaveri -listallasi. + +/rename/use.bml.options.removeself=Poista kaikki Kenen kaveri -listaltasi. + +/rename/use.bml.options.unlink=Älä jätä yhteyttä tilin [[oldname]] ja uuden päiväkirjan välille. + +/rename/use.bml.success.login=Sinun täytyy nyt kirjautua sisään uudelleen. + +/rename/use.bml.success.moved="[[newuser]]" siirretään erilleen käyttäjänimestä "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" on uudelleennimetty käyttäjänimeksi "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Käyttäjänimi vaihdettu. + +/rename/use.bml.title=Käytä uudelleennimeämispoletti + +/site/contract.bml.promise=Seisomme seuraavien lupausten takana: + +/site/contract.bml.promise.account=Kunnioitamme jokaisen tilin asemaa + +/site/contract.bml.promise.account.about=Pysyvät tilit ovat pysyviä koko sivuston olemassaolon ajan. Maksetut tilit pysyvät sellaisina koko maksetun käyttöajan. Varhaisilla mukaantulijoilla on pääsy maksullisiin ominaisuuksiin, jotka olivat aikaisemmin ilmaisia. (Poikkeuksen tilin tilan vakauteen tekee käyttöehtojen rikkomisesta seuraava tilin lakkauttaminen.) + +/site/contract.bml.promise.ads=Emme mainosta sivuillamme + +/site/contract.bml.promise.ads.about=Kyse on ehkä siitä, että pidämme mainoksia ärsyttävinä tai siitä, että niillä ei koota suuria rahasummia, mutta jokatapauksessa lupaamme, ettemme koskaan tarjoa mainostilaa LiveJournal-palvelussa tai -sivuilla. + +/site/contract.bml.promise.community=Toimimme yhteisön kanssa ja yhteisön etujen puolesta + +/site/contract.bml.promise.community.about<< +Lupaamme pidää sinut parhaan kykymme mukaan ajantasalla muutoksista, olematta kuitenkaan tunkeilevia. +Lupaamme pohjata toimintamme LiveJournal-yhteisöltä saamaamme palautteeseen ja toimia yhteisön etujen mukaisesti. +. + +/site/contract.bml.promise.opensource=Tuemme Free Software -liikettä + +/site/contract.bml.promise.opensource.about=Kaikki helposti mukautettavissa oleva, LiveJournalissa käytetty koodi on jokaisen nähtävissä. Lupaamme pitää tämän lähdekoodin ilmaisena ja vapaana tukeaksemme Free Software -yhteisöä. + +/site/contract.bml.promise.spam=Emme koskaan lähetä sinulle sähköpostia ilman suostumustasi + +/site/contract.bml.promise.spam.about=Uskomme, että roskapostille ei ole paikkaa internetissä ja lupaamme, ettemme koskaan lähetä sinulle sähköpostia ilman suostumustasi. Lupaamme myös, ettemme koskaan myy käyttäjiemme sähköpostiosoitteita tai henkilökohtaisia tietoja, emmekä lähetä roskapostia kolmannen osapuolen nimissä. + +/site/contract.bml.promise.uptime=Huolehdimme palvelun luotettavasta toiminnasta teknisten mahdollisuuksien rajoissa + +/site/contract.bml.promise.uptime.about=Yritämme ylläpitää sivuston toimintoja ja nopeutta siedettävällä tasolla, sillä mekin käytämme sitä yhtä paljon kuin kuka tahansa muu. Valitettavasti palvelimet jumittuvat välillä, mutta estämme tätä mahdollisuuksiemme mukaisesti. + +/site/contract.bml.promisetoyou=Pyrimme varmistamaan, että LiveJournalin palvelut ovat mahdollisimman miellyttäviä kaikille käyttäjille, joten olemme koonneet listan lupauksista, jotka pidämme. + +/site/contract.bml.promisetoyou.header=Lupauksemme Sinulle + +/site/contract.bml.title=Yhteisösopimus + +/site/goat.bml.image.alt=LiveJournalin maskottivuohi Frank + +/site/goat.bml.image.caption="Määäää", sanoo Frank. + +/site/goat.bml.meet.body=Tämä on Frank. Frank on LiveJournal.comin maskotti. Se auttaa meitä joidenkin asioiden ohjelmoimisessa kun olemme juuttuneet johonkin, ja joskus se vastaa teknisessä tuessa esitettäviin kysymyksiin. Frank on varsin moneen kykenevä... Se jopa tekee pihatöitä. Kun nurmikko kasvaa liian pitkäksi, sille sanotaan: "Frank! On ruoka-aika, menehän syömään ruohoa!" Tämähän on kaikille hyödyksi. + +/site/goat.bml.meet.header=Frank + +/site/goat.bml.title=Frank-vuohi + +/styles/create.bml.choosebase=Valitse tyyli, jota alat muokkaamaan: + +/styles/create.bml.createstyle.head=Luo tyyli + +/styles/create.bml.createstyle.text=Täällä voit luoda oman henkilökohtaisen tyylisi, mikä on kätevää jos aiot upottaa päiväkirjasi kotisivuusi tai tehdä julkisen tyylin, jota kaikki voivat käyttää, ja tarvitset tätä sivua sen työstämiseen. Huomaa, että vain maksettujen tilien omistajat voivat luoda omia tyylejään. + +/styles/create.bml.enterstyleid=Tai, anna ei-julkisen tyylin ID-numero: + +/styles/create.bml.noneorother=(Ei mitään, tai alle annettu:) + +/styles/create.bml.selecttype.head=Valitse tyylin tyyppi + +/styles/create.bml.selecttype.text=Tyyli vaikuttaa vain yhteen näkymään. Jos haluat luoda yhtenäisen tyylisetin päiväkirjaasi, täytyy sinun luoda tyyli joka näkymälle. + +/styles/create.bml.submit=Luo tyyli + +/styles/create.bml.title=Luo tyyli + +/styles/create_do.bml.editstyle=Muokkaa tyyliä + +/styles/create_do.bml.error.accounttype=Tilityyppisi ei salli tyylien luomista. + +/styles/create_do.bml.error.invalidview=Valitsit virheellisen tyylityypin. + +/styles/create_do.bml.error.styleexists=Sinulla on jo tämäntyyppinen tyyli nimeltä [[des]]. Jos haluat luoda uuden [[view]]-tyypin tyylin, muokkaa vanhaa [[view]]-tyyliäsi muuttamalla sen nimeä, ja palaa tänne luodaksesi uuden tämäntyyppisen tyylin. + +/styles/create_do.bml.error.stylenotfound=Tyyli [[baseid]], josta yrität luoda uutta tyyliä ei näytä olevan olemassa. + +/styles/create_do.bml.error.stylenotpublic=Tyyli [[baseid]], josta yrität luoda uutta tyyliä ei ole julkinen, joten et voi kopioida sitä. + +/styles/create_do.bml.success.head=Onnistui + +/styles/create_do.bml.success.text=Tyylisi on luotu ja väliaikaisesti käytössä nimellä [[des]]. Voit alkaa muokata sitä klikkaamalla alla olevaa painiketta. + +/styles/create_do.bml.title=Luo tyyli + +/styles/index.bml.about<< +

      Tällä sivuston osalla voit luoda, muokata ja poistaa mukautettuja S1-tyylejä. Näin voit kontrolloida tilisi ulkoasua tarkasti, halusitpa sen näyttävän omalta sivustoltasi tai muuten erilaiselta.

      + +

      Voit luoda myös upotettuja tyylejä, jotka sisältävät vain päiväkirjamerkinnät (eivät koko sivua) ja antavat sinun upottaa päiväkirjasi toiselle sivustolle.

      + +

      Voit lukea lisää tyyleistä tyylien ohjeista, jotka sijaitsevat kehittäjäalueella.

      + +

      Huomaa, että vain maksetut tilit voivat luoda ja käyttää mukautettuja tyylejä. Ilmaisilla tileillä on käytössään valikoima valmiiksi määriteltyjä LiveJournal-tyylejä, joita voit valita päiväkirjan muokkaussivulla.

      +. + +/styles/index.bml.about.header=Mukautettujen tyylien luominen ja käyttäminen + +/styles/index.bml.nav.browse=Tyyliselain + +/styles/index.bml.nav.browse.about=Tyyliselaimella voit selata muiden käyttäijen luomia julkisia tyylejä. + +/styles/index.bml.nav.create=Luo uusi tyyli + +/styles/index.bml.nav.create.about=Luo uuden tyylin tyhjästä tai olemassa olevan julkisen tyylin pohjalta + +/styles/index.bml.nav.edit=Muuta tai poista jo olemassa oleva tyyli + +/styles/index.bml.nav.edit.about=Voit muokata vain tyylejä, jotka tilisi “omistaa”. Muuttaaksesi järjestelmätyyliä, sinun täytyy ensin luoda siihen perustuva uusi tyyli. + +/styles/index.bml.nav.modify=Muokka tiliäsi + +/styles/index.bml.nav.modify.about=Muuta tilisi oletustyyliä, mitä tahansa järjestelmän tukevista. + +/styles/index.bml.title=Muokatut tyylit + +/suggestions/index.bml.howto.text<< +
      +
      Tarkista aikaisemmat ehdotukset
      +Ensiksi, lue läpi aikaisempia ehdotuksia varmistuaksesi siitä, ettei jotain samanlaista ole jo aiemmin käsitelty. Jos näin on tapahtunut, voit lukea merkinnän kommentit. Joskus saattaa näyttää siltä, että jotakin ei ole otettu huomioon, mutta ne saattavat olla juuri työn alla. Joskus ideat hylätään tai niiden toteutusta siirretään muista syistä. +
      +
      Etkö löytänyt ehdotustasi? Jaa se meidän kanssamme!
      +Kaavakettä täytyy käyttää kaikissa ehdotuksissa. Täytä kaikki kentät ja varmistu siitä, että ehdotuksesi on valmis ja järkevä ennen kuin lähetät sen. Huomaa myös, että ehdotusjärjestelmä ei tee rivinvaihtoja, joten tehdäksesi ehdotuksesi selvemmäksi käytä koodia <br> tehdäksesi tyhjää tilaa. +
      +
      Lähetä se!
      +Voit lisätä -yhteisön kaverilistallesi tästä. Kun joku tekee ehdotuksen, synnyttää se keskustelua. Jos se on meidän mielestämme hyvä, lisätään se kehityskohdelistalle ja sitä työstetään mahdollisuuksien mukaan. Kaikkia ehdotuksia ei voida ottaa käyttöön aivan heti, joten ole kärsivällinen. +
      +. + +/suggestions/index.bml.howto.title=Kuinka teen ehdotuksen? + +/suggestions/index.bml.info.text<< +Voitko auttaa ehdotustesi toteutuksessa? Jos mielestäsi voit, seuraa alla olevia yhteisöjä tai liity niihin: +
      +
      LiveJournalin kehittäjien keskustelualue -- keskustelua teknisistä seikoista.
      +
      +
      LiveJournalin talouskeskustelu -- keskustelua yleisistä LiveJournaliin liittyvistä talousmahdollisuuksista.
      +
      +
      LiveJournalin käyttäjädokumentaatiokeskustelu -- keskustelua ja yleistä dokumentaation muuttamista.
      +
      +
      LiveJournalin taidekeskustelu -- keskustelua ja kuvien, mielialakuvakkeiden, väriteemojen sekä käyttäjäkuvien jakamista.
      +
      +
      +Muista, että ihmiset jotka tekevät LiveJournaliin näitä muutoksia ovat aivan samanlaisia käyttäjiä kuin sinäkin. Asiat vievät aikaa ja mitä enemmän voit auttaa, sitä enemmän saadaan tehtyä. +. + +/suggestions/index.bml.info.title=Muuta tietoa + +/suggestions/index.bml.rules<< +Joitakin muistettavia asioita: +
        +
      • Monia asioita on jo ehdotettu ja niistä on keskusteltu, mutta niitä ei yksinkertaisesti ole vielä toteutettu. Varmistu siitä, että et esitä jotain aikaisempaa ehdotusta uudestaan.
      • +
      • Toisten mielipiteiden haukkumista ei hyväksytä. Kaikilla on erilaisia ajatuksia siitä, millainen LiveJournalin tulisi olla; muista että omien ajatustesi mainostaminen käy, mutta toisen mielipiteen haukkuminen ei.
      • +
      • Varmista, että ehdotuksesi on toteutettavissa. Ehdotus, joka sisältään yksityiskohtaisia tietoja toteutuksesta, hyväksytään todennäköisimmin. Sinun ei tarvitse osata ohjelmointia; yritä ajatella mihin muihin toimintoihin ideasi voisi vaikuttaa ja tuo esiin havaitsemasi ongelmat.
      • +
      • Lue ensin FAQ:t nähdäksesi, onko ideasi jo olemassa tai voidaanko jotain sivun olemassa olevaa ominaisuutta käyttää sen toteuttamiseen.
      • +
      • Jos haluat tietoa siitä, miten LiveJournal toimii, et ole varma onko joku ominaisuus olemassa vai ei, tai jos sinulla on ongelma, elä esitä ehdotusta. Kysy sen sijaan Tukialueelta.
      • +
      +. + +/suggestions/index.bml.title=Ehdotusalue + +/suggestions/index.bml.welcome.text=Käyttäjien tekemät ehdotukset ovat tärkeä osa LiveJournalia. Jos sinulla on mielessä joku hyvä idea, seuraa ohjeita saadaksesi se sivuston hoitajien tietoon. + +/suggestions/index.bml.welcome.title=Tervetuloa! + +/support/append_request.bml.back.requests=Takaisin avointen pyyntöjen listalle. + +/support/append_request.bml.back.support=Takaisin tukialueelle. + +/support/append_request.bml.bounce.noemail=Siirrolle ei määritetty sähköpostiosoitetta. + +/support/append_request.bml.bounce.notauth=Sinulla ei ole oikeuksia siirtää tätä pyyntöä. + +/support/append_request.bml.bounce.toomany=Voit lähettää vain viiteen sähköpostiosoitteeseen. Olet syöttänyt enemmän kuin viisi. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Tämä tukipyyntö on suljettu. + +/support/append_request.bml.closed.title=Suljettu + +/support/append_request.bml.internal.approve=Hyväksyäksesi vastauksen täytyy sinun valita "Internal Comment / Action" ja vaihtoehtoisesti selittää miksi hyväksyt sen. + +/support/append_request.bml.internal.changecat=Muuttaaksesi pyynnön aihepiiriä täytyy sinun valita "Internal Comment / Action" ja vaihtoehtoisesti selittää miksi muutat sitä. + +/support/append_request.bml.internal.changesum=Muuttaaksesi pyynnön yhteenvetoa täytyy sinun valita "Internal Comment / Action" ja syöttää uusi yhteenveto. + +/support/append_request.bml.internal.touch=Muuttaaksesi pyynnön tilaa täytyy sinun valita "Internal Comment / Action" ja selittää miksi muutat sitä. + +/support/append_request.bml.invalid.blank=Viestisi oli tyhjä. Kirjoita jotain ainakin viestikenttään. + +/support/append_request.bml.invalid.noanswer=Virheellinen hyväksyttävä peitetty vastaus. + +/support/append_request.bml.invalid.nocat=Aihepiiriä ei näytä olevan olemassa. + +/support/append_request.bml.invalid.noid=Tämä toiminto vaatii tukipyynnön ID-numeron. + +/support/append_request.bml.invalid.type=Virheellinen vastaustyyppi. + +/support/append_request.bml.logged.text=Toimintosi/kommenttisi/vastauksesi on tallennettu. Kiitos. + +/support/append_request.bml.logged.title=Onnistui + +/support/append_request.bml.login.required=Sinun täytyy kirjautua sisään voidaksesi auttaa ihmisiä. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Liitä kommentti/vastaus + +/support/append_request.bml.unknown.request=Tuntematon tukipyyntö. + +/support/encodings.bml.edit.header=En pysty muokkaamaan merkintöjäni www-käyttöliittymällä! + +/support/encodings.bml.edit.text<< +Lyhyt vastaus: (jos kirjoitat päiväkirjaasi Englanniksi: Mene henkilökohtaisten tietojesi muokkaussivulle. Etsi asetus sivun alareunassa, nimeltään Muunna vanhat merkinnät automaattisesti tästä koodauksesta. Valitse "Western European (Windows)" pudotusvalikosta ja tallenna muutokset. Merkintöjäsi pitäisi nyt pystyä muokkaamaan. p?> + +Pitkä vastaus: Jotta voisit muokata ei-Unicode-merkintää, LiveJournalin koodin pitää tietää, mitä merkistökoodausta käyttäen merkintä on lähetetty. Englannin ja muiden Länsi-Euroopan kielten (myös suomen) käyttäjille tämä on yleensä "Western European (Windows)", mutta jos tämä toimii huonosti lainausmerkeille ja vastaaville välimerkeille, kokeile valita "Western European (ISO)". Muilla kielillä kirjoittavien tulee valita oma merkistökoodauksensa, ellei sitä ole listassa, kannattaa ottaa yhteyttä tukeen ja selittää ongelma. p?> + + + +/support/encodings.bml.groups.header=En voi muokata kaverilistojani päivitysohjelmallani! + +/support/encodings.bml.groups.text=ryhmienmuokkaussivulla ja käyttää sen jälkeen päivitysohjelmaasi. p?> + +/support/encodings.bml.overview.header=Mitä tämä kaikki tarkoittaa? + +/support/encodings.bml.overview.text<< + + +. + +/support/encodings.bml.still.header=Eikö onnistu vieläkään? + +/support/encodings.bml.still.text=tukialueella. p?> + +/support/encodings.bml.title=Merkistökoodaukset + +/support/faqbrowse.bml.backfaq=Takaisin päänäkymään. + +/support/faqbrowse.bml.backfaqcat=Takaisin aihepiirinäkymään. + +/support/faqbrowse.bml.backsupport=Takaisin tukialueelle. + +/support/faqbrowse.bml.edit.faq=Muokkaa tätä FAQ:ta + +/support/faqbrowse.bml.error.nofaq=Annettua FAQ:ta ei ole olemassa. + +/support/faqbrowse.bml.lastupdated=Viimeksi päivitetty: + +/support/faqbrowse.bml.title_num=FAQ-kysymys #[[num]] + +/support/help.bml.interim<< + + + + +HelpScreening-yhteisön muistojen Getting +Started -osiosta löytyy hyödyllistä tietoa uusille vapaaehtoisille. p?> + + + +
      • Ole asiantunteva ja kohtelias.
      • +
      • Älä ota yhteyttä avustuspyyntöjä jättäneisiin ihmisiin avustusalueen ulkopuolella keskustellaksesi heidän pyynnöstään tai antaaksesi heille tietoa.
      • +
      • Älä levitä avustuspyyntöjen henkilökohtaisia tietoja.
      • +
      • Älä kopioi muiden ihmisten vastauksia.
      + + + +-yhteisöstä miksi vastaustasi ei hyväksytty, mutta odota kuitenkin, kunnes avustuspyyntöön on olemassa hyväksytty vastaus. p?> + + + + + +tukipyyntölistalta. p?> +. + +/support/see_overrides.bml.error.noprivs=Vain ne käyttäjät, joilla on supportviewscreened- tai supporthelp-oikeudet, voivat nähdä toisten käyttäjien korvaavuudet. + +/support/see_overrides.bml.error.nos1=Käyttäjä ei käytä S1:tä. + +/support/see_overrides.bml.header=Käyttäjän korvaavuudet: + +/support/see_overrides.bml.nooverrides=Käyttäjältä ei löytynyt korvaavuuksia. + +/support/see_overrides.bml.title=Käyttäjän korvaavuudet + +/syn/index.bml.account=Tili: + +/syn/index.bml.add=Lisää syöte + +/syn/index.bml.add.byurl.text=Lisää syöte kaverilistallesi antamalle sen osoite alle. + +/syn/index.bml.add.byurl.title=Lisää syöte osoitteen perusteella + +/syn/index.bml.add.pop.text=Seuraavat ovat suosittuja syötteitä, joita et tällä hetkellä seuraa: + +/syn/index.bml.add.pop.title=Lisää suosittu syöte + +/syn/index.bml.add.selected=Lisää valitut + +/syn/index.bml.back=Takaisin + +/syn/index.bml.create=Luo syöte + +/syn/index.bml.create.name=Antamaasi osoitetta ei tällä hetkellä syndikoida tälle sivustolle. Anna tilinimi, jonka kautta haluat syndikoinnin tapahtuvan. + +/syn/index.bml.error.nocreate=Antamaasi osoitetta ei syndikoida tälle sivustolle. Tilityyppisi ei salli uusien syndikaatiosyötteiden luontia. + +/syn/index.bml.error.unknown=Tuntematon virhe + +/syn/index.bml.feed.url=Syötteen osoite: + +/syn/index.bml.invalid.accountname=Virheellinen tili. + +/syn/index.bml.invalid.cantadd=Et voi lisätä RSS-syötettä tältä sivustolta. + +/syn/index.bml.invalid.http.text=Osoitetta haettassa tapahtui virhe. Palvelin voi olla kaatunut tai sisältö käyttämättömissä. Tarkista antamasi osoite ja yritä uudelleen. + +/syn/index.bml.invalid.http.title=Virhe haettaessa sisältöä + +/syn/index.bml.invalid.inuse.text=Tilinimi on jo käytössä. + +/syn/index.bml.invalid.inuse.title=Käyttäjänimi käytössä + +/syn/index.bml.invalid.needname.text=Lisätäksesi syndikoidun tilin jota ei ole olemassa, mene takaisin ja anna sille tilinimi. + +/syn/index.bml.invalid.needname.title=Tilinimi tarvitaan + +/syn/index.bml.invalid.needurl=Sinun täytyy syöttää joko syndikoidun tilin käyttäjänimi tai osoite lisätäksesi uuden syötteen. + +/syn/index.bml.invalid.notexist=Käyttäjänimellä ei ole olemassa syndikoituja tilejä. + +/syn/index.bml.invalid.notrss.text=Antamasi osoite ei näytä sisältävän XML-muotoista tietoa. + +/syn/index.bml.invalid.notrss.title=Tieto ei XML-muotoista + +/syn/index.bml.invalid.port=Epästandardinmukainen porttinumero ei sallittu + +/syn/index.bml.invalid.reserved=Tilinimi on jo varattu. Ole hyvä ja valitse uusi. + +/syn/index.bml.invalid.submission=Virheellinen lomakkeenlähetys + +/syn/index.bml.invalid.url=Kirjoittamasi osoite on väärä. Tarkista osoite ja yritä uudelleen. + +/syn/index.bml.loginrequired.text=Muokataksesi syndikoituja tilejäsi, kirjaudu sisään. + +/syn/index.bml.loginrequired.title=Sisäänkirjautuminen vaadittu + +/syn/index.bml.promo.text=Jos haluat nähdä listan syndikaatiosyötteistä joita -käyttäjät ovat mainostaneet viime aikoina, kannattaa sinun käydä sivulla , jossa käyttäjät tekevät ilmoituksia tekemistään syötteistä. + +/syn/index.bml.remove=Poista valitut + +/syn/index.bml.table.account=Tili + +/syn/index.bml.table.feed=Syöte + +/syn/index.bml.table.watchers=Seuraajat + +/syn/index.bml.title=Syndikointi + +/syn/index.bml.user.nomatch=Merkintöjä tekevä käyttäjä ei vastaa lomakkeen täyttänyttä käyttäjää. + +/syn/index.bml.using.text=Täällä voit lisätä syndikaatiosyötteitä (RSS) toisilta sivustoilta ja poistaa tarpeen käydä useilla eri sivustoilla joka päivä. + +/syn/index.bml.using.title=[[sitename]]-palvelun käyttäminen syndikaatiossa + +/syn/list.bml.error.nofeeds=Virhe: Mitään syndikaatiosyötteitä ei ole päivitetty viimeisen 24 tunnin aikana. + +/syn/list.bml.feeddesc=Syötteen kuvaus + +/syn/list.bml.feedurl=Syötteen osoite + +/syn/list.bml.numreaders=Lukijoiden määrä + +/syn/list.bml.title=Syndikaatiosyötteet + +/syn/list.bml.username=Käyttäjänimi + +/syn/list.bml.xml_icon.alt=[Näytä raakasyöte] + +/talkmulti.bml.deleted.body=Kommentit on poistettu. Voit katsoa jäljellä olevan viestiketjun tästä. + +/talkmulti.bml.deleted.title=Kommentit poistettu + +/talkmulti.bml.error.comms_deleted=Yksi kommenteista poistettiin sen jälkeen kun olit valinnut sen. Mene takaisin ja yritä uudestaan turvasyiden takia. + +/talkmulti.bml.error.inconsistent_data=Annettu data on epäyhtenäistä. (The supplied data is inconsistent.) + +/talkmulti.bml.error.invalid=Epäkelvot syötteet. (Invalid parameters specified.) + +/talkmulti.bml.error.invalid_mode=Et valinnut toimintoa. Mene takaisin ja valitse, haluatko peittää kommentin, tuoda sen näkyviin vai poistaa sen. + +/talkmulti.bml.error.login=Et ole kirjautuneena sisään. + +/talkmulti.bml.error.none_selected=Et valinnut yhtään kommenttia. + +/talkmulti.bml.error.privs.delete=Sinulla ei ole oikeuksia poistaa näitä kommentteja. + +/talkmulti.bml.error.privs.screen=Sinulla ei ole oikeuksia peittää näitä kommentteja. + +/talkmulti.bml.error.privs.unscreen=Sinulla ei ole oikeuksia laittaa näitä kommentteja taas näkyviin. + +/talkmulti.bml.screened.body=Kommentit on peitetty. Voit lukea ne tästä. + +/talkmulti.bml.screened.title=Kommentit peitetty + +/talkmulti.bml.title.delete=Poista useita kommentteja + +/talkmulti.bml.title.screen=Peitä useita kommentteja + +/talkmulti.bml.title.unscreen=Poista usean kommentin peitto + +/talkmulti.bml.unscreened.body=Kommentit eivät ole enää peitettyjä. Voit lukea niitä täällä. + +/talkmulti.bml.unscreened.title=Kommenttien peitto poistettu + +/talkpost.bml.allowedhtml=Sallitut HTML-koodit + +/talkpost.bml.error.cannotreplynopost=Et voi vastata viestiin, jota ei ole olemassa. + +/talkpost.bml.error.nocommentsjournal=Käyttäjä on estänyt päiväkirjansa kommentoinnin. + +/talkpost.bml.error.nocommentspost=Käyttäjä on estänyt juuri tämän viestin kommentoinnin. + +/talkpost.bml.error.noreplypost=Viestiä, johon vastasit, ei löydy (se on ehkä poistettu). + +/talkpost.bml.error.noreply_deleted=Tämä kommentti poistettiin. Et voi vastata siihen. + +/talkpost.bml.error.noreply_screened=Tämä kommentti on peitetty, eikä sinulla ole oikeuksia nähdä sitä tai vastata siihen. + +/talkpost.bml.label.picturetouse=Kommenttiin liitettävä kuva: + +/talkpost.bml.loganonip=Huom! Tällä käyttäjällä on käytössä asetus, joka tallentaa anonyymien kommentoijien IP-osoitteet. + +/talkpost.bml.loginq=Kirjaudutko sisään? + +/talkpost.bml.logyourip=Huom! Tällä käyttäjällä on käytössä asetus, joka tallentaa IP-osoitteesi, kun jätät kommenttejä hänelle. + +/talkpost.bml.nosubjecthtml=HTML ei sallittu otsikossa + +/talkpost.bml.opt.anonymous=Nimetön + +/talkpost.bml.opt.defpic=(oletus) + +/talkpost.bml.opt.friendsonly=- tämä käyttäjä on estänyt nimettömät ja muiden kuin kaverilistansa jäsenten kommentit. Voit kommentoida täällä jos [[username]] on merkinnyt sinut ystäväkseen. + +/talkpost.bml.opt.from=Keneltä: + +/talkpost.bml.opt.ljuser=LiveJournal-käyttäjä: + +/talkpost.bml.opt.loggedin=Kirjautunut käyttäjä: [[username]] + +/talkpost.bml.opt.message=Viesti: + +/talkpost.bml.opt.noanonpost=- tämä käyttäjä on estänyt nimettömän kommentoinnin + +/talkpost.bml.opt.noautoformat=Älä muotoile automaattisesti: + +/talkpost.bml.opt.noimage=Ei kuvaa + +/talkpost.bml.opt.preview=Esikatsele + +/talkpost.bml.opt.spellcheck=Tarkista oikeinkirjoitus ennen lähettämistä (englanti) + +/talkpost.bml.opt.subject=Otsikko: + +/talkpost.bml.opt.submit=Lisää kommentti + +/talkpost.bml.opt.willscreen=(peitetään) + +/talkpost.bml.opt.willscreenfriend=(peitetään muilta kuin kavereilta) + +/talkpost.bml.paraformat=Oletuksena kappaleet muotoillaan automaattisesti. + +/talkpost.bml.postresponse=Kommentti viestiin: + +/talkpost.bml.title=Lisää kommentti + +/talkpost.bml.usermismatch<< +Syötit käyttäjätunnuksen muttet valinnut "LiveJournal-käyttäjä" -kohtaa. + +Joko tyhjennä käyttäjätunnuslaatikko tai valitse asiaankuuluva lähetysasetus ja yritä uudestaan. +. + +/talkpost.bml.warnscreened=Huom: Tämä kommentti on peitetty. Siihen vastaaminen poistaa sen peiton automaattisesti, ja kommentti tulee näkyviin. + +/talkpost_do.bml.error.badpassword=Väärä salasana annettu määrätylle käyttäjänimelle. Voit palauttaa salasanasi täällä jos olet unohtanut sen. + +/talkpost_do.bml.error.badusername=Antamaasi käyttäjänimeä ei ole olemassa. Voit palauttaa käyttäjänimesi täällä jos olet unohtanut sen, tai kommentoida "Nimettömänä" sen sijaan. + +/talkpost_do.bml.error.banned=Sinun ei ole sallittua kirjoittaa tämän käyttäjän päiväkirjaan. + +/talkpost_do.bml.error.blankmessage=Viestisi oli tyhjä. Ole hyvä ja kirjoita edes jotain viestikenttään. + +/talkpost_do.bml.error.confused_identity=Syötit käyttäjätunnuksen, mutta halusit lähettää viestin anonyymisti tai sisään kirjautuneena käyttäjänä. Palaa takaisin ja päätä, miten todella haluat toimia. + +/talkpost_do.bml.error.deleted=Päiväkirjasi on poistettu. Et voi lisätä viestejä. + +/talkpost_do.bml.error.friendsonly=Vain käyttäjän [[user]] kaverit voivat lähettää viestejä tähän päiväkirjaan. + +/talkpost_do.bml.error.lostcookie=Sisäänkirjautumisevästeesi näyttää kadonneen? + +/talkpost_do.bml.error.manybytes=[[current]] tavun pituinen kommenttisi ylittää suurimman sallitun pituuden, [[limit]] tavua. Palaa takaisin, lyhennä sitä ja yritä lähettää se uudestaan. + +/talkpost_do.bml.error.manychars=[[current]] merkin pituinen kommenttisi ylittää suurimman sallitun pituuden, [[limit]] tavua. Palaa takaisin, lyhennä sitä ja yritä lähettää se uudestaan. + +/talkpost_do.bml.error.mustlogin=Sinun täytyy olla kirjautuneena sisään tai käyttää käyttäjänimeä/salasanaa vastataksesi tähän suojattuun merkintään. + +/talkpost_do.bml.error.noanon=Et voi kirjoittaa nimettömänä tämän henkilön päiväkirjaan. + +/talkpost_do.bml.error.noauth=Et ole oikeutettu vastaamaan tähän suojattuun merkintään. + +/talkpost_do.bml.error.nocomments=Käyttäjä on estänyt tähän merkintään kommentoimisen. + +/talkpost_do.bml.error.noparent=Olemattomaan viestiin ei voi lähettää kommentteja. + +/talkpost_do.bml.error.notafriend=Käyttäjä [[user]] ei ole listannut sinua kaverikseen mutta on sallinut päiväkirjansa kommentoimisen vain kaverilistaansa kuuluville. + +/talkpost_do.bml.error.nousername=Et syöttänyt LiveJournal käyttäjänimeä. Voit valita kirjoittamisen "Nimettömänä" jos sinulle ei ole LiveJournal-tiliä. + +/talkpost_do.bml.error.noverify=Valitettavasti et voi lisätä kommentteja muiden ihmisten päiväkirjoihin ennen kuin sähköpostiosoitteesi on varmennettu. Jos olet kadottanut tämän tekemiseen tarvittavan sähköpostin, voit lähetyttää sen uudestaan. + +/talkpost_do.bml.error.postshared=Et voi kirjoittaa jaettuna tai yhteisön tilinä. Jaetut tilit edustavat ryhmää ihmisiä, eivät yksilöitä. + +/talkpost_do.bml.error.screened=Sinulla ei ole oikeuksia vastata tähän peitettyyn kommenttiin. + +/talkpost_do.bml.error.suspended=Päiväkirjasi on jäädytetty. Et voi lähettää viestejä. + +/talkpost_do.bml.error.testacct=Testitilejä voi käyttää vain testitilipäiväkirjoissa. + +/talkpost_do.bml.opt.preview=Esikatselu + +/talkpost_do.bml.preview=Alla näet miltä kommenttisi tulee näyttämään. Käytä alla olevaa lomaketta muokataksesi sitä lisää - tai voit lähettää sen sellaisenaan. + +/talkpost_do.bml.preview.subject=Otsikko: + +/talkpost_do.bml.preview.submit=Lähetä + +/talkpost_do.bml.preview.title=Esikatsele + +/talkpost_do.bml.success.loggedin=Olet kirjautunut sisään. + +/talkpost_do.bml.success.message=Kommenttisi on lisätty, voit nähdä sen täällä. + +/talkpost_do.bml.success.screened.comm=Kommenttisi on lisätty. Yhteisön asetusten mukaan se on peitetty ja näkyy vain sinulle ja yhteisön ylläpitäjille, kunnes he päättävät poistaa sen peiton. Voit lukea kommenttisi tästä. + +/talkpost_do.bml.success.screened.comm.anon=Nimetön kommenttisi on lisätty. Yhteisön asetusten mukaan se on peitetty ja näkyy vain sinulle ja yhteisön ylläpitäjille, kunnes he päättävät poistaa sen peiton. Voit lukea kommenttisi tästä. + +/talkpost_do.bml.success.screened.user=Kommenttisi on lisätty. Päiväkirjan asetusten mukaisesti se on peitossa eikä näy kuin sinulle ja päiväkirjan omistajalle niin kauan, kunnes omistaja päättää poistaa peiton. Näet kommenttisi tästä. + +/talkpost_do.bml.success.screened.user.anon=Nimetön kommenttisi on lisätty. Päiväkirjan asetusten mukaisesti se on peitossa eikä näy kuin sinulle ja päiväkirjan omistajalle niin kauan, kunnes omistaja päättää poistaa peiton. Näet kommenttisi tästä. + +/talkpost_do.bml.success.title=Onnistui + +/talkpost_do.bml.success.unscreened=Huomaa, että peitetty kommentti, johon vastasit, ei enää ole peitetty ja on nyt nähtävissä. + +/talkpost_do.bml.title=Kommentti lisätty + +/talkpost_do.bml.title.error=Kommenttia ei lähetetty + +/talkpost_do.bml.title.preview=Kommentin esikatselu + +/talkread.bml.anonuser=(Nimetön) + +/talkread.bml.confirm.action=Haluatko todella poistaa valitut kommentit? + +/talkread.bml.deletedpost=(Poistettu kommentti) + +/talkread.bml.deleteduser=(Poistettu käyttäjä: [[username]]) + +/talkread.bml.fromip=(osoitteesta [[ip]]) + +/talkread.bml.noreplies=Ei vastauksia + +/talkread.bml.nosubject=(ei otsikkoa) + +/talkread.bml.replysuspended=(Kommentti jäädytetyltä käyttäjältä) + +/talkread.bml.screenedpost=(Peitetty kommentti) + +/talkread.bml.select=Valitse + +/talkread.bml.subjectdeleted=[poistettu] + +/talkread.bml.talkmulti.delete=Poista + +/talkread.bml.talkmulti.des=Yhteistoiminto valituille kommenteille: + +/talkread.bml.talkmulti.screen=Peitä + +/talkread.bml.talkmulti.submit=Suorita toiminto + +/talkread.bml.talkmulti.unscreen=Poista peitto + +/talkread.bml.title=Lue kommentteja + +/talkscreen.bml.error.login=Sinun täytyy olla kirjautunut sisään, jotta voit käsitellä peitettyjä kommentteja. + +/talkscreen.bml.error.privs.screen=Sinulla ei ole oikeuksia peittää tätä kommenttia. + +/talkscreen.bml.error.privs.unscreen=Sinulla ei ole oikeuksia poistaa peittoa tältä kommentilta. + +/talkscreen.bml.screen.doit=Peitä tämä kommentti + +/talkscreen.bml.screen.sure.body=Haluatko todella peittää tämän kommentin? + +/talkscreen.bml.screen.sure.title=Peitetäänkö kommentti? + +/talkscreen.bml.screened.body=Kommentti on peitetty. Voit nähdä kommentin täällä. + +/talkscreen.bml.screened.title=Onnistui + +/talkscreen.bml.title=Peitetty kommentti + +/talkscreen.bml.unscreen.doit=Kyllä, poista tämän kommentin peitto. + +/talkscreen.bml.unscreen.sure.body=Haluatko poistaa tämän kommentin peiton? + +/talkscreen.bml.unscreen.sure.title=Poistetaanko kommentin peitto? + +/talkscreen.bml.unscreened.body=Kommentin peitto on poistettu. Voit nähdä kommentin täällä. + +/talkscreen.bml.unscreened.title=Onnistui + +/tools/emailmanage.bml.address.current.title=Tämänhetkinen osoite + +/tools/emailmanage.bml.address.old.none=Ei mitään + +/tools/emailmanage.bml.address.old.text=Alla on lista kaikista sähköpostiosoitteista, joita on käytetty tilisi kanssa sekä ajat jolloin ensisijaista osoitetta vaihdettin. Valitse ne jotka haluat poistaa. + +/tools/emailmanage.bml.address.old.title=Edelliset osoitteet + +/tools/emailmanage.bml.delete_selected=Poista valitut + +/tools/emailmanage.bml.desc.notfirst=Tämä sivu antaa sinun poistaa vain sähköpostiosoitteita, joita olet ensimmäisen osoitteen antamisen jälkeen lisännyt. Toisin sanoen, tämä tarkoittaa että tilin kaappaaja ei voi poistaa alkuperäistä osoitettasi. + +/tools/emailmanage.bml.desc.text=Tämä sivu antaa sinun poistaa sähköpostiosoitteita, joita on aiemmin käytetty tilisi kanssa. Kun ne on poistettu, kyseiseen osoitteeseen ei voida enää lähettää salasanaa. Tämä on kätevää, jos joku sai selville salasanasi ja kaappasi päiväkirjasi. Lähetytä vain uusi salasana vanhaan osoitteeseesi, muuta se takaisin ja poista hyökkääjän sähköpostiosoite. + +/tools/emailmanage.bml.desc.title=Kuvaus + +/tools/emailmanage.bml.log.deleted=Poistettu: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Muutokset tallennettu + +/tools/emailmanage.bml.notvalidated.text=Jotta voisit käyttää tätä työkalua, nykyisen sähköpostiosoitteesi [[email]] täytyy olla varmennettu. Jos olet kadottanut tämän tekemiseen tarvittavan varmistussähköpostin, voit lähetyttää sen uudestaan. Kun olet käynyt sinulle lähetettävässä osoitteessa, tule takaisin tälle sivulle. + +/tools/emailmanage.bml.notvalidated.title=Sähköpostiosoitetta ei ole varmennettu + +/tools/emailmanage.bml.title=Sähköpostin asetukset + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Muistamisen arvoisten viestien lista on päivitetty. + +/tools/memadd.bml.body.added.header=Onnistui + +/tools/memadd.bml.description=Kuvaus + +/tools/memadd.bml.description.text<< +Anna tälle merkinnälle otsikko, josta muistat mikä se on. +Poistaaksesi tämän merkinnän muistamisen arvoisista viesteistä, jätä kuvaus tyhjäksi. +. + +/tools/memadd.bml.error.deleted.body=Merkintä, jolla oli kuvaus "[[desc]]" on poistettu muistolistaltasi. + +/tools/memadd.bml.error.deleted.title=Muisto poistettu + +/tools/memadd.bml.error.entry_deleted=Päiväkirjaa ei enää ole. Muisto on poistettu. + +/tools/memadd.bml.error.fivekeywords=Yhtä muistoa kohti saa olla vain viisi avainsanaa tai kategoriaa. + +/tools/memadd.bml.error.invalid_security=Turva-asetus on epäkelpo tai puuttuu. + +/tools/memadd.bml.error.login=Sinun täytyy kirjautuneena sisään käyttääksesi tätä ominaisuutta. Kirjaudu sisään, niin pääset takaisin tälle sivulle. + +/tools/memadd.bml.error.maxsize=Tämä avainsana on sallittua pitempi: "[[keyword]]". + +/tools/memadd.bml.error.nodescription.body<< +Jotta voit lisätä merkinnän muistolistallesi, sinun pitää antaa sille kuvaus. +Voit poistaa muiston poistamalla kuvauksen kokonaan, mutta tämä merkintä ei vielä ollut muistoissasi. +. + +/tools/memadd.bml.error.nodescription.title=Ei kuvausta + +/tools/memadd.bml.form.reset=Tyhjennä + +/tools/memadd.bml.form.submit=Lähetä + +/tools/memadd.bml.keywords=Avainsanat: + +/tools/memadd.bml.keywords.example=Esimerkki: hauska, romanttinen, sekava + +/tools/memadd.bml.keywords.select=Voit myös valita avainsanoja, joita olet käyttänyt aikaisemmin: + +/tools/memadd.bml.keywords.text=Miksi tämä viesti on muistettava? Anna enintään 5 avainsanaa tai kategoriaa, jotta löydät sen myöhemmin. + +/tools/memadd.bml.login.enterinfo=Anna haluamasi tilin käyttäjätunnus ja salasana; tämä muisto tallentuu sen yhteyteen. + +/tools/memadd.bml.login.forgot.header=Unohtuiko jotain? + +/tools/memadd.bml.login.forgot.recover=Jos unohdit käyttäjätunnuksesi tai salasanasi, palauta se mieleesi täällä! + +/tools/memadd.bml.multiple_selections=Paina control-näppäintä (Ctrl) pohjassa valitaksesi useita eri avainsanoja. + +/tools/memadd.bml.security=Turvallisuus: + +/tools/memadd.bml.security.friendsonly=Vain kaverit + +/tools/memadd.bml.security.private=Yksityinen + +/tools/memadd.bml.security.public=Julkinen + +/tools/memadd.bml.title=Lisää muistoihin + +/tools/memadd.bml.title.added=Muisto lisätty + +/tools/memadd.bml.title.add_memory=Lisää muistettava merkintä + +/tools/memadd.bml.title.deleted=Muisto poistettu + +/tools/memadd.bml.title.edit_memory=Muokkaa muistettavaa merkintää + +/tools/memadd.bml.whocansee<< +Kuka voi nähdä, että olet merkinnyt tämän viestin muistettavaksi? + Kaikki, vain kaverilistasi jäsenet vai ainoastaan sinä? +. + +/tools/memadd.bml.whocansee.comm<< +Kuka voi nähdä, että olet merkinnyt tämän viestin muistettavaksi? +Kaikki, vain yhteisön jäsenet vai vain yhteisön ylläpitäjät? +. + +/tools/memories.bml.back=Takaisin + +/tools/memories.bml.body.keyword<< + +[[user]] muistoista, joihin hän on liittänyt avainsanan "[[keyword]]". p?> + +. + +/tools/memories.bml.body.list_categories<< + +[[user]] on sijoittanut muistonsa. p?> +. + +/tools/memories.bml.body.memorable=Tässä ovat käyttäjän [[user]] luokittelemattomat muistot. + +/tools/memories.bml.delete=Poista valitut + +/tools/memories.bml.delete.confirm=Olet poistamassa yhden tai useampia muistoja. Haluatko varmasti tehdä tämän? + +/tools/memories.bml.delete.deleted.head=Onnistui + +/tools/memories.bml.delete.deleted.text=Valitut muistot on poistettu. Voit palata muistolistaasi. + +/tools/memories.bml.delete.deleted.title=Muistot poistettu + +/tools/memories.bml.delete.error.dberror=Muistoja poistettaessa tapahtui tietokantavirhe. Virhe on [[error]]. Ole hyvä ja yritä uudelleen. + +/tools/memories.bml.delete.error.noneselected=Et valinnut poistettavia muistoja. + +/tools/memories.bml.edit=muokkaa + +/tools/memories.bml.error.noentries.body<< +Syynä tähän saattaa olla se, että
        +
      1. käyttäjä ei ole määrittänyt yhtään muistamisen arvoista merkintää
      2. +
      3. käyttäjän muistamisen arvoiset merkinnät ovat suojattuja eikä sinulla ole oikeutta katsoa niitä tai
      4. +
      5. käyttäjällä ei ole yhtään muistoa, joka vastaisi antamiasi ehtoja.
      +. + +/tools/memories.bml.error.noentries.title=Muistoja ei löytynyt. + +/tools/memories.bml.filter.all=Kaikki muistot + +/tools/memories.bml.filter.other=Vain muut merkinnät + +/tools/memories.bml.filter.own=Vain käyttäjän "[[user]]" viestit + +/tools/memories.bml.form.filter=Suodata merkinnät jonkun näistä mukaan: + +/tools/memories.bml.form.sort=Merkintöjen järjestämisperiaate: + +/tools/memories.bml.form.switch=Vaihda + +/tools/memories.bml.login=Nähdäksesi omat muistosi, ole hyvä ja kirjaudu sisään. + +/tools/memories.bml.plur_entry=[[num]] [[?num|merkintä|merkintää]] + +/tools/memories.bml.sort.description=kuvaus + +/tools/memories.bml.sort.journal=päiväkirja + +/tools/memories.bml.sort.orderadded=lisäysjärjestys + +/tools/memories.bml.title.keyword=Muistettavat viestit, joiden avainsana on [[keyword]] + +/tools/memories.bml.title.memorable=Muistettavat viestit + +/tools/memories.bml.uncategorized=Luokittelemattomat + +/update.bml.altpost=Lähetetään päiväkirjaan: + +/update.bml.btn.preview=Esikatselu + +/update.bml.btn.update=Päivitä + +/update.bml.currmood=Tämänhetkinen mieliala: + +/update.bml.currmusic=Musiikki: + +/update.bml.date=Päivämäärä: + +/update.bml.default=oletus + +/update.bml.defaultjournal=([[user]]) - oletus + +/update.bml.error.cantpost=Valitettavasti et voi tehdä merkintää juuri nyt. + +/update.bml.error.disabled=Tilisi tyyppi ei salli merkintöjen tekemistä. + +/update.bml.error.disabled.title=Merkintöjen tekeminen kielletty + +/update.bml.error.login=Virhe kirjautumisessa: + +/update.bml.error.nopass=Anna salasana + +/update.bml.error.update=Päivitysvirhe: + +/update.bml.event=Merkintä: + +/update.bml.full=Täydellinen päivityssivu + +/update.bml.htmlokay.norich=(HTML sallittu, oletusasetuksena uudet rivit käyttävät <br>-muotoa) + +/update.bml.htmlokay.rich=(HTML sallittu, oletusasetuksena uudet rivit käyttävät <br>-muotoa - käytä monipuolisempaa päivityslomaketta.) + +/update.bml.htmlokay.rte_nosupport=(Valitettavasti selaimesi ei tue tällä hetkellä monipuolisempaa päivityslomaketta.) + +/update.bml.localtime=Paikallinen aika: + +/update.bml.loggedinas=Olet tällä hetkellä kirjautunut sisään käyttäjänä [[user]].
      Tehdäksesi merkinnän toisena käyttäjänä, klikkaa tästä. + +/update.bml.loggingin=Kirjaudutaan palvelimelle... + +/update.bml.noneother=Ei mitään, tai muu: + +/update.bml.note=Huom: Aika ja päivämäärä ovat peräisin palvelimeltamme. Korjaa ne omalle aikavyöhykkeellesi ennen lähettämistä. + +/update.bml.opt.backdate=Päivää takautuvasti: + +/update.bml.opt.backdate.about=ei näy kavereiden kaverisivulla + +/update.bml.opt.defpic=(oletus) + +/update.bml.opt.nocomments=Estä kommentointi: + +/update.bml.opt.noemail=Älä lähetä kommentteja: + +/update.bml.opt.noformat=Ei automaattista muotoilua: + +/update.bml.opt.spellcheck=Tarkista oikeinkirjoitus ennen lähettämistä (englanti) + +/update.bml.options=Valinnaiset asetukset + +/update.bml.other=Muu: + +/update.bml.password=Salasana: + +/update.bml.picture=Merkintään liitettävä kuva: + +/update.bml.preview.header=Esikatselu + +/update.bml.preview.text=Tältä merkintä näyttää, kun se lähetetään. Alla olevaa lomaketta käyttäen voit muokata merkintää pidemmälle tai lähettää sen sellaisenaan. + +/update.bml.security.custom=Mukautettu... + +/update.bml.security.friends=Kaverit + +/update.bml.security.head=Turvataso: + +/update.bml.security.private=Yksityinen + +/update.bml.security.public=Julkinen + +/update.bml.servermsg=Palvelimella on viesti sinulle: + +/update.bml.simple=Tämä on yksinkertainen sivu. Täällä on enemmän valinnanvaraa. + +/update.bml.spellchecked=Merkintäsi oikeinkirjoitustarkistuksen jälkeen: + +/update.bml.subject=Otsikko: (valinnainen) + +/update.bml.timeformat=24-tuntinen aika + +/update.bml.title=Päivitä + +/update.bml.title.readonly=Vain luku -tila (read-only) + +/update.bml.update.alternate=Jos et halua ladata päivitysohjelmaa tietokoneellesi tai sopivaa ei löydy, voit käyttää tätä sivua LiveJournalisi päivittämiseen. Tämä sivu on hyödyllinen myös jos olet matkalla tai et käytä ensisijaista tietokonettasi. Jos sinulla on maksettu tili, voit päivittää päiväkirjaasi sähköpostin kautta, tehdä puhelumerkintöjä kun et ole tietokoneella tai luoda kyselyitä merkintöihisi. + +/update.bml.update.head=Päivitä LiveJournaliasi... + +/update.bml.update.success=Päivitys onnistui. Voit katsoa päivitettyä päiväkirjasi tästä + +/update.bml.updating=Päivitetään päiväkirjaa... + +/update.bml.username=Käyttäjänimi: + +/uploadpic.bml.error.unsupportedtype=Tiedostotyyppi [[filetype]] ei ole tuettu. Voit tallentaa ainoastaan GIF-, PNG- tai JPG-tiedostoja. Muunnoksen voi tehdä lähes kaikilla kuvanmuokkausohjelmilla. + +/userinfo.bml.about.comm=Oma kuvaus: + +/userinfo.bml.about.user=Kuvaus: + +/userinfo.bml.body.leave=Voit erota yhteisöstä milloin tahansa. + +/userinfo.bml.comminfo.body=Alla ovat "[[commname]]"-yhteisön LiveJournal-tiedot. + +/userinfo.bml.comminfo.name=Yhteisön tiedot + +/userinfo.bml.date.never=Ei koskaan. + +/userinfo.bml.error.malfname=Käyttäjätunnus väärän muotoinen: liian pitkä tai sisältää virheellisiä merkkejä. + +/userinfo.bml.error.notloggedin=Jos haluat nähdä oman käyttäjäprofiilisi, sinun pitää kirjautua sisään. + +/userinfo.bml.friendof.comm=Seuraajat: + +/userinfo.bml.friendof.hidden=(ei näytetä) + +/userinfo.bml.friendof.syndreadcount=Lukijoiden määrä + +/userinfo.bml.friendof.user=Kenen kaveri: + +/userinfo.bml.friends.comm=Jäsenet + +/userinfo.bml.friends.user=Kaverit + +/userinfo.bml.label.addbuddy=Lisää käyttäjä + +/userinfo.bml.label.adduser=Lisää käyttäjä + +/userinfo.bml.label.alsofriendof=Myös kenen kaveri: + +/userinfo.bml.label.birthdate=Syntymäaika: + +/userinfo.bml.label.clientsused=Käytetyt päivitysohjelmat: + +/userinfo.bml.label.comments=Kommentteja: + +/userinfo.bml.label.composted=Itse lähetettyjä: [[num]] - + +/userinfo.bml.label.comreceived=Vastaanotettuja: [[num]] + +/userinfo.bml.label.datecreated=Päiväkirja luotu: + +/userinfo.bml.label.dateupdated=Viimeksi päivitetty: + +/userinfo.bml.label.email=Sähköposti: + +/userinfo.bml.label.frcommunity=Yhteisöt + +/userinfo.bml.label.frpeople=Ihmiset + +/userinfo.bml.label.frsyndication2=Syötteet + +/userinfo.bml.label.icquin=ICQ-numero: + +/userinfo.bml.label.interests=Kiinnostuksenkohteet + +/userinfo.bml.label.interests.modifyyours=Muokkaa omiasi + +/userinfo.bml.label.interests.removesome=Poista joitakin + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] kiinnostuksenkohteet piilotettu + +/userinfo.bml.label.journalentrs=Päiväkirjamerkintöjä: + +/userinfo.bml.label.location=Sijainti: + +/userinfo.bml.label.memberof=Kuuluu yhteisöihin + +/userinfo.bml.label.memories=Muistot + +/userinfo.bml.label.moredetails=(lisätietoja...) + +/userinfo.bml.label.msnusername=MSN-käyttäjätunnus: + +/userinfo.bml.label.mutual=Molemminpuoliset kaverit: + +/userinfo.bml.label.name=Nimi: + +/userinfo.bml.label.nofriends=Ei ketään listattuna. + +/userinfo.bml.label.post=Tee merkintä kohteeseen "[[journal]]" + +/userinfo.bml.label.postalt=Päivitä päiväkirjaasi + +/userinfo.bml.label.reqfinduser=Vain ne, joilla on "finduser"-oikeus voivat etsiä käyttäjiä userid-kentän perusteella. + +/userinfo.bml.label.searchjournal=Etsi tästä päiväkirjasta + +/userinfo.bml.label.sendmessage=Lähetä viesti + +/userinfo.bml.label.shared=Lähetysoikeus: + +/userinfo.bml.label.supportpoints=Tukipisteet + +/userinfo.bml.label.syndicatedfrom=Syndikoitu täältä käsin: + +/userinfo.bml.label.syndicatedstatus=Syndikoinnin tila: + +/userinfo.bml.label.textmessage=Tekstiviestit: + +/userinfo.bml.label.todo=Tehtävää-lista + +/userinfo.bml.label.user=Käyttäjätunnus: + +/userinfo.bml.label.viewfriends=Näytä kaverit + +/userinfo.bml.label.viewmembers=Näytä jäsenet + +/userinfo.bml.label.website=Kotisivu: + +/userinfo.bml.membership.body=Klikkaa tästä liittyäksesi tähän yhteisöön. + +/userinfo.bml.membership.paidmembers=Kun maksettu tilisi on käytössä, voit liittyä paidmembers-yhteisöön. + +/userinfo.bml.memories.entries=[[count]] kpl + +/userinfo.bml.memories.entry=[[count]] kpl + +/userinfo.bml.monitor.comm=Seuraa yhteisöä + +/userinfo.bml.monitor.user=Lisää tämä käyttäjä kaverilistallesi + +/userinfo.bml.nonexist.body=Käyttäjätunnus [[user]] ei ole rekisteröity tällä hetkellä. + +/userinfo.bml.nonexist.name=Tuntematon käyttäjä + +/userinfo.bml.sendmessage.body=Lähetä käyttäjälle [[user]] tekstiviesti
      hänen matkapuhelimeensa tai hakulaitteeseensa. + +/userinfo.bml.syn.last.never=Ei koskaan + +/userinfo.bml.syn.lastcheck=Tarkistettu viimeksi: + +/userinfo.bml.syn.nextcheck=Seuraava tarkistus: + +/userinfo.bml.syn.parseerror=Virhe: + +/userinfo.bml.syndinfo.body=Jos haluat syndikoidulta sivustolta tulevien artikkeleiden ilmestyvän kaverisivullesi, voit lisätä tämän päiväkirjan kaverilistaasi. + +/userinfo.bml.syndinfo.name=Syndikoitu päiväkirja + +/userinfo.bml.tellafriend=Kerro kaverille! + +/userinfo.bml.timeupdate.dayago=1 päivä sitten + +/userinfo.bml.timeupdate.daysago=[[num]] päivää sitten + +/userinfo.bml.timeupdate.hourago=1 tunti sitten + +/userinfo.bml.timeupdate.hoursago=[[num]] tuntia sitten + +/userinfo.bml.timeupdate.minuteago=1 minuutti sitten + +/userinfo.bml.timeupdate.minutesago=[[num]] minuuttia sitten + +/userinfo.bml.timeupdate.secondago=1 sekunti sitten + +/userinfo.bml.timeupdate.secondsago=[[num]] sekuntia sitten + +/userinfo.bml.timeupdate.weekago=1 viikko sitten + +/userinfo.bml.timeupdate.weeksago=[[num]] viikkoa sitten + +/userinfo.bml.title=Käyttäjätiedot + +/userinfo.bml.title.communityinfo=Yhteisön tiedot + +/userinfo.bml.title.syndicated=Syndikoitu tili + +/userinfo.bml.userinfo.body=Tässä ovat käyttäjän [[username]] henkilökohtaiset tiedot. Jos itse olet kyseinen käyttäjä, voit muokata tietojasi (tai päättää, mitkä tiedot ovat julkisia) tietojenmuokkaussivulla. + +/userinfo.bml.userinfo.name=Käyttäjätiedot + +bml.badcontent.body=Pyyntöäsi käsiteltäessä tapahtui yksi tai useampia virheitä. Mene takaisin korjaamaan tiedot ja lähetä ne uudelleen. + +bml.badinput.body=Selaimesi lähetti tekstiä, jonka ei tunnistettu olevan UTF-8 -koodattua, vaikka niin tulisi olla. Tämä saattaa tapahtua jos pakotit selaimesi näyttämään edellisen sivun jollain muulla koodauksella. Se saattaa myös olla virhe selaimessasi. Jos et pääse tämän ongelman ohi, ota meihin yhteyttä. + +bml.badinput.head=Virheellinen Unicode-syöttö + +bml.needlogin.body2=Jotta voisit nähdä tämän sivun, täytyy sinun kirjautua sisään. + +bml.needlogin.head=Sisäänkirjautuminen tarvitaan + +BML.parse_multipart.parse=Virhe tallentamisessa (Error parsing upload) + +BML.parse_multipart.toolarge=Liian suuri tallennus (Upload too large) + +BML.parse_multipart.unknowntype=Tuntematon sisältötyyppi (content type) + +bml.requirepost=Turvallisuuden vuoksi lukemasi sivu vaatii POST-pyynnön eikä GET-pyyntöä. Jos yrität lähettää lomakkeen sääntöjen mukaisesti, ota meihin yhteyttä. + +btn.search=Hae + +crumb.about=Tietoja LiveJournalista + +crumb.abusereport=Väärinkäyttöilmoitus + +crumb.acctfeatures=Ominaisuudet tilin tyypin mukaan + +crumb.acctstatus=Tilin tila + +crumb.addfriend=Lisää kaveri + +crumb.addtodo=Lisää tehtävää-listan merkintä + +crumb.advcustomize=Muokkaa edistyneitä S2-asetuksia + +crumb.advsearch=Edistynyt + +crumb.banners=Mainosbannerit + +crumb.birthdays=Syntymäpäivät + +crumb.changepass=Muuta salasanaa + +crumb.code=LiveJournal-koodi + +crumb.commmembers=Yhteisön jäsenyydet + +crumb.commpending=Odottavat jäsenyydet + +crumb.commsearch=Yhteisöhaku + +crumb.community=Yhteisökeskus + +crumb.contract=Yhteisösopimuksemme + +crumb.contributors=Avustajat + +crumb.createcommunity=Luo yhteisö + +crumb.createjournal=Luo päiväkirja + +crumb.createstyle=Luo tyyli + +crumb.customize=Muokkaa S2-asetuksia + +crumb.delcomment=Poista kommentti + +crumb.download=Lataa päivitysohjelma + +crumb.editentries=Muokkaa merkintöjä + +crumb.editentries_do=Muokkaa merkintää + +crumb.editfriendgrps=Muokkaa kaveriryhmiä + +crumb.editfriends=Muokkaa kavereita + +crumb.editinfo=Henkilökohtaiset tiedot + +crumb.editpics=Käyttäjäkuvat + +crumb.editstyle=Muokkaa tyyliä + +crumb.emailgateway=Sähköpostin yhdyskäytävä + +crumb.emailmanage=Sähköpostiasetukset + +crumb.encodings=Tietoa koodauksista + +crumb.export=Tallenna päiväkirja + +crumb.faq=Usein kysytyt kysymykset (FAQ) + +crumb.feedstersearch=Etsi päiväkirjasta + +crumb.filemanager=Tiedostoselain + +crumb.friends=Kaverityökalut + +crumb.friendsfilter=Kaverisuodatin + +crumb.goat=Tietoja Frankista + +crumb.home=Etusivu + +crumb.itsfree=Onko se ilmaista? + +crumb.joincomm=Liity yhteisöön + +crumb.latestposts=Viimeisimmät merkinnät + +crumb.layerbrowse=Julkinen kerrosseltain + +crumb.leavecomm=Eroa yhteisöstä + +crumb.legal=Lakitiedot + +crumb.linkslist=Linkkisi + +crumb.login=Sisäänkirjautuminen + +crumb.logout=Uloskirjautuminen + +crumb.lostinfo=Kadonneet tiedot + +crumb.manage=Muokkaa tiliä + +crumb.managecommunity=Yhteisöjen hallinta + +crumb.meme=Meme-seurain + +crumb.memories=Muistettavat merkinnät + +crumb.moderate=Yhteisön moderointi + +crumb.modify=Päiväkirjan asetukset + +crumb.moodlist=Mielialakatselin + +crumb.news=Uutiset + +crumb.paidaccounts=Maksetut tilit + +crumb.paidacctstatus=Maksetun tilin tila + +crumb.phonepostsettings=Puhelumerkintäasetukset + +crumb.popfaq=Suositut FAQ:t + +crumb.press=LiveJournalin lehdistöalue + +crumb.pressarticles=LiveJournal lehdistössä + +crumb.preview=Ulkoasun esikatselut + +crumb.privacy=Yksityisyysperiaatteet + +crumb.register=Varmenna sähköposti + +crumb.search=Haku + +crumb.searchinterests=Kiinnostuksenkohteen mukaan + +crumb.searchregion=Alueen mukaan + +crumb.seeoverrides=Näytä korvaavuudet + +crumb.setpgpkey=Julkinen avain + +crumb.singles=LiveJournalin sinkut + +crumb.singlesopts=Muuta saatavuutta + +crumb.singlessearch=Etsi sinkkuja + +crumb.sitemap=Sivukartta + +crumb.siteopts=Käyttöasetukset + +crumb.sizechart=Kokokartta + +crumb.staff=Täysipäiväinen henkilöstö + +crumb.stats=Tilastot + +crumb.store=LiveJournal-kauppa + +crumb.storeitem=Näytä tuotteen tiedot + +crumb.styles=Tyylit + +crumb.suggestions=Ehdotusgeneraattori + +crumb.suggview=Ehdotukset + +crumb.support=Tukialue + +crumb.supportact=Pyydä tukea + +crumb.supportappend=Liitä pyyntöön + +crumb.supporthelp=Pyyntölista + +crumb.supportnotify=Huomautusasetukset + +crumb.supportscores=Parhaat pisteet + +crumb.supportsubmit=Lähetä pyyntö + +crumb.textmessage=Lähetä tekstiviesti + +crumb.themes=Teeman esikatselut + +crumb.todo=Tehtävää-lista + +crumb.tos=Käyttöehdot + +crumb.unsubscribe=Poistu listalta + +crumb.update=Päivitä päiväkirjaa + +crumb.utf8convert=UTF-8 -muunnin + +crumb.yourlayers=Kerroksesi + +crumb.yourstyles=Tyylisi + +date.day.friday.long=perjantai + +date.day.friday.short=pe + +date.day.monday.long=maanantai + +date.day.monday.short=ma + +date.day.saturday.long=lauantai + +date.day.saturday.short=la + +date.day.sunday.long=sunnuntai + +date.day.sunday.short=su + +date.day.thursday.long=torstai + +date.day.thursday.short=to + +date.day.tuesday.long=tiistai + +date.day.tuesday.short=ti + +date.day.wednesday.long=keskiviikko + +date.day.wednesday.short=ke + +date.month.april.long=huhtikuu + +date.month.april.short=huhti + +date.month.august.long=elokuu + +date.month.august.short=elo + +date.month.december.long=joulukuu + +date.month.december.short=joulu + +date.month.february.long=helmikuu + +date.month.february.short=helmi + +date.month.january.long=tammikuu + +date.month.january.short=tammi + +date.month.july.long=heinäkuu + +date.month.july.short=heinä + +date.month.june.long=kesäkuu + +date.month.june.short=kesä + +date.month.march.long=maaliskuu + +date.month.march.short=maalis + +date.month.may.long=toukokuu + +date.month.may.short=touko + +date.month.november.long=marraskuu + +date.month.november.short=marras + +date.month.october.long=lokakuu + +date.month.october.short=loka + +date.month.september.long=syyskuu + +date.month.september.short=syys + +dystopia.btn.login=Kirjaudu sisään + +dystopia.hello_anonymous=Tervetuloa LiveJournaliin! + +dystopia.hello_loggedin=Hei, [[username]]! + +dystopia.nav.contact=Yhteystiedot + +dystopia.nav.createjournal=Luo päiväkirja + +dystopia.nav.developer=Kehittäjäalue + +dystopia.nav.download=Lataa + +dystopia.nav.editentries=Muokkaa merkintöjä + +dystopia.nav.editfriends=Kaverit + +dystopia.nav.editpassword=Salasana + +dystopia.nav.editpics=Kuvat + +dystopia.nav.editstyle=Muokkaa tyyliä + +dystopia.nav.findcomm=Yhteisön mukaan + +dystopia.nav.finddir=Hakemistohaku + +dystopia.nav.findint=Kiinnostuksenkohteiden mukaan + +dystopia.nav.findrandom=Satunnaisesti + +dystopia.nav.findregion=Alueen mukaan + +dystopia.nav.home=Koti + +dystopia.nav.journalcalendar=Kalenteri + +dystopia.nav.journalfriends=Kaverit + +dystopia.nav.journalinfo=Käyttäjätiedot + +dystopia.nav.journalrecent=Uusimmat + +dystopia.nav.legalprivacy=Yksityisyys + +dystopia.nav.legaltos=Käyttöehdot + +dystopia.nav.login=Kirjaudu sisään + +dystopia.nav.logout=Kirjaudu ulos + +dystopia.nav.lostinfo=Unohditko salasanasi? + +dystopia.nav.memories=Muistot + +dystopia.nav.modifyjournal=Muokkaa päiväkirjaa + +dystopia.nav.news=Uutiset + +dystopia.nav.paidaccts=Maksaneet käyttäjät + +dystopia.nav.paymentarea=Maksualue + +dystopia.nav.personalinfo=Henkilökohtaiset tiedot + +dystopia.nav.sitemap=Sivukartta + +dystopia.nav.siteopts=Käyttöasetukset + +dystopia.nav.support=Kysymyksiä? + +dystopia.nav.updatejournal=Päivitä + +dystopia.navhead.findusers=Etsi käyttäjiä + +dystopia.navhead.help=Ohjeet & käyttäjätuki + +dystopia.navhead.journal=Oma päiväkirja + +dystopia.navhead.legal=Lakitietoa + +dystopia.navhead.settings=Omat asetukset + +dystopia.navhead.welcome=Tervetuloa! + +dystopia.search.icq=ICQ-numero + +dystopia.search.int=Kiinnostuksenkohde + +dystopia.search.msn=MSN-käyttäjätunnus + +dystopia.search.region=Alue + +dystopia.searchlj=Etsi LiveJournalista: + +Email=Sähköposti + +email.newacct.body<< +Onnittelut - sinulla on nyt uusi [[sitename]]-tili! + +Jotta päiväkirjasi luominen saataisiin valmiiksi ja sähköpostiosoitteesi varmennettaisiin, mene osoitteeseen: + + [[regurl]] + +Uusi päiväkirjasi sijaitsee osoitteessa: + + [[siteroot]]/users/[[username]]/ + +ja tämän lisäksi se löytyy myös osoitteesta: + + [[siteroot]]/~[[username]]/ + +Tässä ovat LiveJournal-käyttäjätunnuksesi ja salasanasi: + + Käyttäjätunnus: [[username]] + Salasana: [[password]] + +Nyt voit mennä osoitteeseen [[siteroot]]/ ja säätää tiliäsi, luoda uusia päiväkirjamerkintöjä ja muokata päiväkirjasi asetuksia, mutta me suosittelemme LiveJournal-päivitysohjelman lataamista omalle koneellesi. Se on helpoin tapa kirjoittaa päiväkirjaasi, ja ohjelmia on saatavilla monille käyttöjärjestelmille! Hae omasi osoitteesta + + [[siteroot]]/download/ + +Alkuun pääseminen LiveJournalissa voi olla vaikeaa, kun et tunne ketään. Hyödyllisiä neuvoja löytyy päiväkirjasta http://newbies.livejournal.com, ja pienellä tuurilla olet tuota pikaa LiveJournal-ekspertti! + +Toivomme, että arvostat LiveJournalia yhtä paljon kuin me arvostamme sen saattamista sinun ulottuvillesi. Jos sinulla on jotain kysyttävää Livejournalin käytöstä, vieraile tukipalvelussamme osoitteessa + + [[siteroot]]/support/ + +Sieltä löydät vastauksen melkeinpä mihin tahansa LiveJournalia koskevaan kysymykseen. + +Tavoitteenamme on tehdä LiveJournalista jotain äärimmäisen hienoa, ja jos voimme tehdä jotain mikä tekisi siitä helpompaa - kerro se meille. Emme ylläpidä tätä sivustoa tehdäksemme rahaa. Emme ole internetpalveluita ylläpitävä yhtiö, joka toimii riskirahalla toivoen tuottavansa voittoa, vaan LiveJournalia pyörittävät sitä käyttävät ihmiset. Kerro meille, mitä haluat. + +Jos sinulla on kysyttävää, tukiosasto yleensä vastaa sinulle 24 tunnin sisällä. + +Ja ei kun nauttimaan! + +[[sitename]]-ylläpito +[[siteroot]]/ +. + +email.newacct.subject=Tervetuloa LiveJournaliin + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Virhe + +error.badpassword=Väärä salasana. + +error.code.comm_not_comm=Tili ei ole yhteisö + +error.code.comm_not_found=Yhteisöä ei löytynyt + +error.code.comm_not_member=Käyttäjä ei ole tämän yhteisön jäsen + +error.dberror=Sattui tietokantavirhe: + +error.deleted.name=Poistettu + +error.deleted.text=Tämä päiväkirja on poistettu. Jos olet [[user]], sinulla on 30 päivää aikaa poistamisen jälkeen palauttaa päiväkirja. 30 päivän jälkeen tuhoamme kaiken sisällön palvelimiltamme. + +error.deleted.title=Poistettu tili + +error.expiredchal=Sisäänkirjautumisikkuna vanhentunut. Yritä uudestaan. + +error.invalidauth=Sinua ei voitu vahvistaa valituksi käyttäjäksi. + +error.ipbanned=IP-osoitteesi on väliaikaisesti estolistalla, koska siitä on tullut liian monta virheellistä kirjautumisyritystä. + +error.malformeduser=Käyttäjätunnus väärän muotoinen. (Malformed username.) + +error.nobutton=Etkö painanut nappia? (No button pressed?) + +error.nodb=Tietokanta väliaikaisesti poissa käytöstä. + +error.nodbmaintenance=Tämä osa tietokannasta on väliaikaisesti alhaalla huoltotöiden takia. Yritä uudestaan muutaman minuutin kuluttua. + +error.noentry=Päiväkirjamerkintää ei ole + +error.nojournal=Tuntematon päiväkirja + +error.noremote=Sinun täytyy kirjautua sisään, jotta voit käyttää kyseistä sivua. + +error.procrequest=Pyyntöäsi käsiteltäessä sattui virhe: + +error.purged.name=Poistettu + +error.purged.text=Tämä päiväkirja on poistettu ja tuhottu. + +error.purged.title=Tuhottu tili + +error.suspended.name=Jäädytetty + +error.suspended.text=Tämä tili on joko tilapäisesti tai pysyvästi jäädytetty. Jos olet [[user]], katso FAQ nimeltään Tilini on jäädytetty! Kuinka saisin sen takaisin? saadaksesi lisää tietoa. Huomioi että säilyttääkseen käyttäjän yksityisyyden, [[sitename]] ei voi keskustella minkään jäädyttämisen syistä kenenkään muun kuin tilin omistajan kanssa. + +error.suspended.title=Jäädytetty tili + +error.tempdisabled=Väliaikaisesti pois käytöstä. + +error.unknownmode=Tuntematon moodi (Unknown mode) + +error.usernameinvalid=Käyttäjätunnuksessa on epäkelpoja merkkejä. + +error.usernamelong=Käyttäjätunnus on liian pitkä, maksimi on 15 merkkiä. + +error.username_notfound=Käyttäjätunnusta ei löytynyt. + +Help=Ohjeet + +label.screening.all=Kaikki kommentit + +label.screening.anonymous=Vain nimettömät + +label.screening.default=Oletus + +label.screening.header=Peitetyt kommentit: + +label.screening.none=Ei mitään + +label.screening.nonfriends=Ei-kavereiden tekemät + +label.security.custom=Mukautettu... + +label.security.friends=Kaverit + +label.security.head=Turvataso: + +label.security.maintainers=Valvojat + +label.security.members=Jäsenet + +label.security.private=Yksityinen + +label.security.public=Julkinen + +label.switch.button=Vaihda + +label.switch.header=Vaihda päiväkirjaa + +label.switch.workwith=Muokkaa päiväkirjaa: + +langname.be=valkovenäjä + +langname.da=tanska + +langname.de=saksa + +langname.en=englanti + +langname.en_GB=englanti, UK + +langname.en_LJ=englanti + +langname.eo=esperanto + +langname.es=espanja + +langname.et=viro + +langname.fi=suomi + +langname.fr=ranska + +langname.ga=iiri + +langname.gd=gaeli + +langname.he=heprea + +langname.hi=hindi + +langname.hu=unkari + +langname.is=islanti + +langname.it=italia + +langname.ja=japani + +langname.la=latina + +langname.lv=latvia + +langname.ms=malesia + +langname.nb=norja, bokmÃ¥l + +langname.nl=hollanti + +langname.nn=norja, nynorsk + +langname.pl=puola + +langname.pt=portugali + +langname.ru=venäjä + +langname.sv=ruotsi + +langname.tr=turkki + +langname.uk=ukraina + +langname.zh=yksinkertaistettu kiina + +ljcom.account.feature=Toiminto + +ljcom.account.feature.email=LiveJournal-sähköpostiosoite + +ljcom.account.feature.full2=Täydellisen taulukon löydät tältä sivulta. + +ljcom.account.feature.limit=rajoitettu + +ljcom.account.feature.ownblog=Oma päiväkirja/weblog + +ljcom.account.feature.search=Hakemistohaku + +ljcom.account.feature.styles=Luo/muokkaa tyylejä + +ljcom.account.feature.syn=Kavereiden ja syndikaatiosyötteiden ryhmittely + +ljcom.account.free=Ilmainen tili + +ljcom.account.paid=Maksettu tili + +ljcom.account.paid12=Maksettu 12 kuukauden ajan ($25 USD) + +ljcom.account.paid2=Maksettu 2 kuukauden ajan ($5 USD) + +ljcom.account.paid6=Maksettu 6 kuukauden ajan ($15 USD) + +ljcom.accounttype=Tilin tyyppi + +ljcom.badpass.email=Salasanasi ei saa perustua sähköpostiosoitteeseesi. + +ljcom.badpass.realname=Salasanasi ei saa perustua oikeaan nimeesi. + +ljcom.badpass.username=Salasanasi ei saa perustua käyttäjänimeesi. + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Kansainvälinen [[name]] Meetup -päivä + +ljcom.meetup.moreinfo=(lisää tietoa) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Haluatko tavata ihmisiä omalla alueellasi keskustellaksesi tästä kiinnostuksenkohteesta? Käy täällä: [[link]] + +ljcom.menu.upgrade=Osta maksettu tili + +ljcom.userinfo.accounttype=Tilin tyyppi + +ljcom.userinfo.paiduser=Maksanut käyttäjä + +ljcom.userinfo.types.early=Varhainen mukaantulija + +ljcom.userinfo.types.free=Ilmainen tili + +ljcom.userinfo.types.paid=Maksettu tili + +ljcom.userinfo.types.paid_early=Maksettu tili, ennen varhainen mukaantulija + +ljcom.userinfo.types.paid_early_expiring=Maksettu tili [[paiduntil]] asti, ennen varhainen mukaantulija + +ljcom.userinfo.types.paid_expiring=Maksettu tili, [[paiduntil]] asti + +ljcom.userinfo.types.permanent=Pysyvä tili + +ljcom.userinfo.types.permanent_early=Pysyvä tili, ennen varhainen mukaantulija + +ljlib.pageofpages=Sivu [[page]]/[[total]] + +lostinfo.head=Unohtuiko jotain? + +lostinfo.text=Jos olet unohtanut käyttäjätunnuksesi tai salasanasi, palauta se mieleesi tästä. + +lynx.nav.friends=Kaverit + +lynx.nav.help=Tekninen tuki + +lynx.nav.home=Kotisivu + +lynx.nav.login=Kirjaudu sisään + +lynx.nav.logout=Kirjaudu ulos + +lynx.nav.recent=Viimeisimmät merkinnät + +lynx.nav.sitemap=Sivukartta + +lynx.nav.siteopts=Käyttöasetukset + +lynx.nav.update=Päivitä päiväkirjaa + +Password=Salasana + +password.max30=Salasana saa olla enintään 30 merkkiä pitkä. + +poll.dberror=Tietokantavirhe: [[errmsg]] + +poll.dberror.items=Tietokantavirhe syötettäessä artikkeleita: [[errmsg]] + +poll.dberror.questions=Tietokantavirhe syötettäessä kysymyksiä: [[errmsg]] + +poll.error.badmaxlength=Maxlength-attribuutti lj-pq -tekstikoodeissa täytyy olla kokonaisluku väliltä 1-255. + +poll.error.badsize=Size-attribuutti lj-pq -tekstikoodeissa täytyy olla kokonaisluku väliltä 1-100. + +poll.error.cantview=Virhe: sinulla ei ole oikeuksia nähdä kyselyn tuloksia. + +poll.error.cantvote=Valitettavasti sinulla ei ole oikeutta vastata tähän kyselyyn. + +poll.error.missingljpoll=Kaikkien lj-pq -koodien täytyy olla sulkevan lj-poll -koodin sisällä. + +poll.error.missingljpq=Kaikkien lj-pi -koodien täytyy olla sulkevan lj-poll -koodin sisällä. + +poll.error.nested=Et voi avata [[tag]] -koodia. Unohditko sulkea jonkun? + +poll.error.noentry=Virhe: tätä kyselyä ei kiinnitetty tähän päiväkirjamerkintään. + +poll.error.noitems=Tarvitset ainakin yhden vaihtoehdon ei-teksti -kysymystä varten. + +poll.error.noitemstext=lj-pq -koodit, joiden tyyppi on "text" eivät voi sisältää vaihtoehtoja. + +poll.error.nopollid=pollid-parametri puuttuu. + +poll.error.noquestions=Tarvitset kyselyysi ainakin yhden kysymyksen. + +poll.error.notext=Tarvitset lj-pq -koodin sisään kysymystä selittävää tekstiä. + +poll.error.pitoolong=lj-pi -koodin sisältämän tekstin täytyy olla 1-255 merkkiä pitkä. Käyttämäsi oli [[len]] merkkiä. + +poll.error.pollnotfound=Virhe: kyselyä [[num]] ei löytynyt + +poll.error.questionnotfound=Virhe: tätä kysymystä ei ole olemassa. + +poll.error.scalefromlessto="Mistä"-arvon täytyy olla suurempi kuin "mihin"-arvon. + +poll.error.scaleincrement=Koon muutoksen täytyy olla vähintään 1. + +poll.error.scaletoobig=Kokosi ylittää 20 yksikön määrän (mistä-mihin)/mennessä > 20. + +poll.error.tagnotopen=Et voi sulkea [[tag]] -koodia, joka ei ole avoinna. + +poll.error.truncated=... katkaistu + +poll.error.unknownpqtype=Tuntematon lj-pq -koodin muoto. + +poll.error.unlockedtag=[[tag]] -koodi avattu + +poll.error.whoview=whoview täytyy olla "kaikki", "kaverit" tai "ei kukaan". + +poll.error.whovote=whovote täytyy olla "kaikki" tai "kaverit". + +poll.pollnum=Kysely #[[num]] + +poll.scaleanswers=Keskiarvo: [[mean]] Mediaani: [[median]] Std. Dev [[stddev + +poll.security=Avoinna: [[whovote]], tulokset nähtävillä: [[whoview]] + +poll.security.all=Kaikki + +poll.security.friends=Kaverit + +poll.security.none=Ei kukaan + +poll.submit=Lähetä kysely + +poll.viewanswers=Näytä vastaukset + +portal.bdays.count.des=Oletuksena näkyvät ne 5 kaveria, joiden syntymäpäivä on seuraavaksi. + +portal.bdays.count.name=Näytettävät syntymäpäivät + +portal.bdays.portalname=Syntymäpäivät + +portal.bdays.portaltitle=Syntymäpäivät + +portal.goat.name=Sivuston maskotti + +portal.goattext.des=Miten haluat vuohesi ääntelevän? Vuohethan sanovat oikeasti vain "määää", mutta voit kuvitella oman vuohesi sanovan jotain muuta. + +portal.goattext.name=Vuohen ääni + +portal.login.portalname=Kirjautuminen + +portal.memories.entriesnoun=merkintää + +portal.memories.entrynoun=merkintä + +portal.memories.portalname=Muistot + +portal.memories.portaltitle=Muistot + +portal.ministats.active=Aktiiviset: + +portal.ministats.title=Käyttäjätilasto + +portal.ministats.total=Kaikki: + +portal.misbehaved.des=Et varmaankaan halua valita tätä. Kouluttamattomat vuohet aiheuttavat vain harmia. + +portal.misbehaved.name=Huonosti käyttäytyvä vuohi + +portal.newtolj.name=Sivuston linkkejä + +portal.popfaq.portalname=10 luetuinta FAQ:ta + +portal.popfaq.portaltitle=10 luetuinta FAQ:ta + +portal.randuser.count.des=Oletuksena näkyy yksi satunnainen käyttäjä, mutta voit nähdä jopa 10 kappaletta allekkain kapeassa sarakkeessa tai 5 vierekkäin leveässä sarakkeessa. + +portal.randuser.count.name=Näytettävien satunnaisten käyttäjien määrä + +portal.randuser.error.tableempty=Satunnaisia käyttäjiä ei ole. Ota yhteyttä ylläpitoon. + +portal.randuser.hidename.des=Oletuksena satunnainen käyttäjätunnus on näkyvissä. Valitse tästä piilottaaksesi sen. + +portal.randuser.hidename.name=Piilota nimi + +portal.randuser.hidepic.des=Oletuksena käyttäjäkuva näkyy, jos sellainen on olemassa. Tämä valinta poistaa sen. + +portal.randuser.hidepic.name=Piilota käyttäjäkuva + +portal.randuser.portalname=Satunnainen käyttäjä + +portal.randuser.portaltitle=Satunnainen käyttäjä + +portal.randuser.portaltitleplural=Satunnaisia käyttäjiä + +portal.recent.error.noentries=Ei merkintöjä. + +portal.recent.error.notsetup=Sinun pitää valita laatikon asetukset. Klikkaamalla plusmerkkiä pääset valitsemaan sen päiväkirjan, jonka haluat näkyvän tässä. + +portal.recent.error.userstatus=Käyttäjä on poistanut tai jäädyttänyt tilinsä. + +portal.recent.items.description=Oletuksena näkyy vain uusin merkintä. + +portal.recent.items.name=Näytettävät kohteet + +portal.recent.journal.description=Minkä päiväkirjan uusimmat merkinnät haluat nähdä? + +portal.recent.journal.name=Päiväkirja + +portal.recent.nosubject=(Ei otsikkoa) + +portal.recent.permlink=Linkki + +portal.recent.portalname=Uusimmat-näkymä + +portal.recent.portaltitle=Uusimmat merkinnät + +portal.recent.showtext.description=Oletuksena vain otsikot näkyvät. + +portal.recent.showtext.name=Näytä teksti + +portal.stats.journalentyest=Merkintöjä eilen + +portal.stats.portalname=Sivuston tilasto + +portal.stats.portaltitle=Tilasto + +portal.stats.totalusers=Käyttäjiä yhteensä + +portal.update.mode.des=Täydellinen päivitysmoodi antaa sinulle runsaasti lisävalintoja. Se mahdollistaa merkintöjen lähettämisen yhteisöihin sekä mielialan, musiikin ja kuvan määrittämisen. Yksinkertainen moodi on parempi, ellet juuri käytä kyseisiä ominaisuuksia etkä halua nähdä kaikkia valintoja. + +portal.update.mode.full=Täydellinen + +portal.update.mode.name=Päivitysmoodi + +portal.update.mode.simple=Yksinkertainen + +portal.update.portalname=Päivitä + +portal.update.portaltitle=Päivitä päiväkirjaasi + +protocol.bad_password=Salasanasi on liian helppo arvata. On suositeltavaa, että vaihdat sen, tai vaarana on päiväkirjasi kaappaaminen. Käy sivulla [[siteroot]]/changepassword.bml vaihtaaksesi salasanasi. + +protocol.hello_test=Hei testitili! + +protocol.mail_bouncing=Nykyinen sähköpostiosoitteesi ei ole toiminnassa. Kaikki osoitteeseen lähettämämme sähköposti palaa takaisin. [[sitename]] vaatii toimivan sähköpostiosoiteen, jotta voit jatkaa käyttöä. Käy sivulla [[siteroot]]/support/faqbrowse.bml?faqid=19 - siellä kerrotaan, miten sähköpostiosoite muutetaan. + +protocol.modpost=Merkintäsi on lähetetty moderointijonoon. Joku yhteisön moderoijista joko hyväksyy tai hylkää sen. + +protocol.must_revalidate=Sinun pitää varmentaa uusi sähköpostiosoitteesi. Aiemmin käyttämäsi oli kelvollinen, mutta koska olet vaihtanut sen sinun täytyy varmentaa uusi osoite. Ellet varmenna sähköpostiosoitettasi, et pääse kaikkiin toimintoihin jotka [[sitename]] tarjoaa. Katso [[siteroot]]/support/faqbrowse.bml?faqid=11 lisätietojen saamiseksi. + +protocol.not_validated=Sähköpostiosoitettasi ei ole varmennettu. Voit jatkaa [[sitename]]-palvelun käyttöä, mutta ellet varmenna osoitettasi et pääse käyttämään kaikkia toimintoja. Katso ohjeita jotka lähetettiin sinulle kun loit päiväkirjasi tai lue [[siteroot]]/support/faqbrowse.bml?faqid=11 saadaksesi lisätietoja. + +protocol.old_win32_client=Windowsille on olemassa merkittävästi uudempia LiveJournal-päivitysohjelmia - suosittelemme päivittämään. Mene sivulle [[siteroot]]/download/ imuroidaksesi uudemman version. + +protocol.readonly=Tilisi on väliaikaisesti vain luku -tilassa. Jotkut operaatiot eivät onnistu muutamaan minuuttiin. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Pahoittelut + +talk.anonwrote=Joku kirjoitti, + +talk.anonwrote_comm=Joku kirjoitti [[commlink]], + +talk.btn.preview=Esikatselu + +talk.commentpermlink=linkki + +talk.commentpost=Lisää uusi kommentti + +talk.commentsread=Lue kommentteja + +talk.curname_Mood=Mieliala, + +talk.curname_Music=Musiikki, + +talk.error.bogusargs=Valeargumentit + +talk.error.comm_deleted=Kommentti on poistettu. + +talk.error.deleted=Päiväkirja on poistettu. + +talk.error.deleted.title=Poistettu + +talk.error.mustlogin=Sinun pitää olla kirjautuneena sisään lukeaksesi tämän suojatun merkinnän. + +talk.error.nocomment=Kommenttia ei ole olemassa. + +talk.error.noentry=Merkintää ei ole olemassa. + +talk.error.nojournal=Virhe: päiväkirjaa ei voitu määrittää syötteestä. (Error: couldn't determine journal from arguments.) + +talk.error.nosuchjournal=Päiväkirjaa ei ole olemassa + +talk.error.notauthorised=Et ole oikeutettu lukemaan tätä suojattua merkintää. + +talk.error.suspended=Tämä päiväkirja/käyttäjä on jäädytetty. + +talk.error.suspended.title=Jäädytetty + +talk.parentlink=Alkuperäinen + +talk.readsimilar=Lue samankaltaisia päiväkirjamerkintöjä: + +talk.replytothis=Jätä vastaus tähän + +talk.somebodywrote=[[realname]] ([[userlink]]) kirjoitti, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) kirjoitti yhteisössä [[commlink]], + +talk.spellcheck=Tarkista englannin oikeinkirjoitus esikatselussa + +talk.threadlink=Viestiketju + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_suomi + +Username=Käyttäjänimi + +userpic.inactive=Ei käytössä + +xcolibur.greeting.anon=Tervetuloa LiveJournaliin! + +xcolibur.greeting.logged_in=Tervetuloa, [[name]]! [[logout]] + +xcolibur.login=Kirjaudu sisään + +xcolibur.logout=Kirjaudu ulos + +xcolibur.nav.about=Tietoja + +xcolibur.nav.about.download=Lataa + +xcolibur.nav.about.general=Yleisinfo + +xcolibur.nav.about.paidaccounts=Maksetut tilit + +xcolibur.nav.about.press=Lehdistöalue + +xcolibur.nav.about.sitenews=Sivuston uutiset + +xcolibur.nav.about.stats=Tilasto + +xcolibur.nav.footer.sitemap=Sivukartta + +xcolibur.nav.help=Ohje + +xcolibur.nav.help.ask=Lähetä kysymys + +xcolibur.nav.help.contact=Yhteystiedot + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Unohtunut salasana + +xcolibur.nav.home=Etusivu + +xcolibur.nav.journal=Päiväkirja + +xcolibur.nav.journal.archive=Arkisto + +xcolibur.nav.journal.edit.entries=Muokkaa + +xcolibur.nav.journal.friends=Kaverit + +xcolibur.nav.journal.info=Käyttäjätiedot + +xcolibur.nav.journal.memories=Muistot + +xcolibur.nav.journal.recent=Uusimmat + +xcolibur.nav.journal.update=Päivitä + +xcolibur.nav.manage=Muokkaa... + +xcolibur.nav.manage.community=Yhteisöjä + +xcolibur.nav.manage.customize=Ulkoasua + +xcolibur.nav.manage.entries=Merkintöjä + +xcolibur.nav.manage.friends=Kavereita + +xcolibur.nav.manage.info=Käyttäjätietoja + +xcolibur.nav.manage.password=Vaihda salasana + +xcolibur.nav.manage.pics=Käyttäjäkuvia + +xcolibur.nav.manage.styles=Tyylit + +xcolibur.nav.search=Hae... + +xcolibur.nav.search.directory=Asuinpaikan mukaan + +xcolibur.nav.search.directory.search=Lisäasetuksin + +xcolibur.nav.search.interests=Kiinnostuksenkohteen mukaan + +xcolibur.nav.search.random=Satunnaisesti + +xcolibur.nav.siteopts=Käyttöasetukset + +xcolibur.nav.title=Navigoi: + +xcolibur.nav.welcome=Tervetuloa + +xcolibur.nav.welcome.create=Luo tili + +xcolibur.nav.welcome.login=Kirjaudu sisään + +xcolibur.nav.welcome.update=Päivitä päiväkirjaasi + +xcolibur.search=Haku: + +xcolibur.search.category=Haun kohde: + +xcolibur.search.icq=ICQ-numero + +xcolibur.search.int=Kiinnostuksenkohde + +xcolibur.search.msn=MSN-käyttäjätunnus + +xcolibur.search.region=Asuinpaikka + +xcolibur.search.yahoo=Yahoo!-ID + +xcolibur.upgrade=Hanki maksettu tili + diff --git a/ljcom/bin/upgrading/fr.dat b/ljcom/bin/upgrading/fr.dat new file mode 100644 index 0000000..e966885 --- /dev/null +++ b/ljcom/bin/upgrading/fr.dat @@ -0,0 +1,3983 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Changez de statut + +/accountstatus.bml.error.db=Il y a eu une erreur dans la base de donnée en effectuant votre requête. + +/accountstatus.bml.error.invalid=Statut inaproprié + +/accountstatus.bml.error.nochange.expunged=Ce compte a été supprimé. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Vous ne pouvez pas changez le statut de votre journal lorsqu'il est suspendu. + +/accountstatus.bml.header.success=Réussi + +/accountstatus.bml.journalstatus.about=Si vous voulez activer ou désactiver votre journal, c'est ici qu'il faut le faire. Lorsque vous aurez désactivé votre journal, vous aurez 30 jours pour le réactiver au cas où vous changeriez d'idée, faute de quoi le contenu de votre journal sera effacé en permanence et il n'y aura aucun moyen de le réactiver. + +/accountstatus.bml.journalstatus.head=Statut d'activation du journal + +/accountstatus.bml.journalstatus.select.activated=Activé + +/accountstatus.bml.journalstatus.select.deleted=Désactivé + +/accountstatus.bml.journalstatus.select.head=Statut : + +/accountstatus.bml.journalstatus.select.suspended=Suspendu + +/accountstatus.bml.message.nochange=Le statut de votre journal est demeuré [[statusvis]]. + +/accountstatus.bml.message.success=Le statut de votre journal à été changé à [[statusvis]] avec succès. + +/accountstatus.bml.title=État du compte + +/allpics.bml.current=Icônes actuelles + +/allpics.bml.default=Par défaut + +/allpics.bml.edit2=Peut être seriez vous interessé à éditer les mots clés de vos icônes ou à télécharger une nouvelle icône. + +/allpics.bml.error.noparam=Vous devez spécifier un paramètre d'utilisateur. + +/allpics.bml.keywords=Mots clés : + +/allpics.bml.nopics.text.other=Cet utilisateur n'a pas téléchargé d'icônes. + +/allpics.bml.nopics.text2=Vous n'avez aucune icône téléchargée. Pour en télécharger une, allez ici. + +/allpics.bml.nopics.title=Pas d'icônes + +/allpics.bml.pics=Voici les icônes de [[user]]. + +/allpics.bml.title=Icônes de l'utilisateur + +/approve.bml.comm.success=Succès + +/approve.bml.comm.text<< +Vous avez été ajouté à [[comm]] +Cliquez ici pour ajouter la communauté à votre liste d'amis. +. + +/approve.bml.commjoin.text<< +Vous avez approuvé la demande d'adhésion à la communauté [[comm]] de [[user]]. +Cliquez ici afin de voir la liste des membres de cette communauté et d'ajouter d'autres options pour cet utilisateur. +. + +/approve.bml.error.actionperformed=Cette action a déjà été éffectuée + +/approve.bml.error.approving=Il y a eu une erreur en approuvant la demande d'adhésion. + +/approve.bml.error.internerr.invalidaction=Erreur interne: action non valide + +/approve.bml.error.invalidargument=L'argument suggéré n'est pas valide + +/approve.bml.error.unknownactiontype=Type d'action inconnu + +/approve.bml.shared.success=Succès + +/approve.bml.shared.text<< +Vous avez reçu la permission de poster sur [[shared]]. +Cliquez ici pour ajouter le journal partagé à votre liste d'amis. +. + +/approve.bml.title=Permission d'agir + +/birthdays.bml.description=Ci-dessous se trouvent les anniversaires de tous ceux que vous listez comme amis. + +/birthdays.bml.title=Anniversaires + +/changepassword.bml.btn.proceed=Procédez + +/changepassword.bml.changepassword.header=Changez votre mot de passe + +/changepassword.bml.changepassword.instructions=Remplissez le formulaire ci-dessous pour changer votre mot de passe. Pour de l'aide à choisir un bon mot de passe pour garder la sécurité de votre compte, allez à cette FAQ. + +/changepassword.bml.email.body<< +Votre mot de passe à été changé chez [[sitename]]. + +À l'avenir, pour le récupérer allez à : + +[[siteroot]]/lostinfo.bml + +Sincèrement, +L'équipe de [[sitename]] +. + +/changepassword.bml.email.subject=Changement du mot de passe + +/changepassword.bml.error.badcheck=Mauvais nouveau mot de passe [[error]] + +/changepassword.bml.error.badnewpassword=Le confirmation de votre nouveau mot de passe n'est pas identique à votre nouveau mot de passe. Peut-être avez vous fait une erreur en l'écrivant. Veuillez recommencer et confirmer votre nouveau mot de passe à nouveau. + +/changepassword.bml.error.badoldpassword=Votre ancien mot de passe est incorrect. + +/changepassword.bml.error.blankpassword=Votre nouveau mot de passe ne peut pas être vide. + +/changepassword.bml.error.changetestaccount=Le mot de passe du compte d'essai ne peut être modifié. + +/changepassword.bml.error.characterlimit=Les mots de passes sont limités à 30 caractères. + +/changepassword.bml.error.invaliduser=Nom d'utilisateur invalide [[user]]. Cet utilisateur n'existe pas. Êtes-vous sûr de l'avoir bien écrit? + +/changepassword.bml.error.mustenterusername=Vous devez enter un nom d'utilisateur. + +/changepassword.bml.error.nonascii=Les mots de passe sont restreints aux symboles ASCII. Veuillez choisir un mot de passe qui n'utilise pas d'autres symboles. + +/changepassword.bml.error.notvalidated=Vous ne pouvez pas changer votre mot de passe si votre courriel actuel n'a pas été validé. Veuillez voir la FAQ pour obtenir des informations supplémentaires. + +/changepassword.bml.newpassword=Nouveau mot de passe : + +/changepassword.bml.newpasswordagain=Nouveau mot de passe (encore) : + +/changepassword.bml.oldpassword=Ancien mot de passe : + +/changepassword.bml.proceed.instructions=Appuyez sur le bouton ci-dessous et votre mot de passe sera changé. Vous recevrez aussi un courriel qui vous avertira du changement de mot de passe. + +/changepassword.bml.relogin=De plus, toutes vos sessions existantes ont été fermées. Vous devriez vous ré-enregistrer avant de continuer. + +/changepassword.bml.success.text=Votre mot de passe à été changé et un courriel vous a été envoyé avec un message de rappel. + +/changepassword.bml.title=Changez votre mot de passe + +/community/index.bml.main<< + + + + +Salon des nouveaux. Vous y trouverez des réponses à plusieurs de vos questions. Visitez , explorez un peu, et vous serez un pro en un rien de temps! +p?> + + +
      +Ajoutez à votre liste d'amis afin de rester au courant des derniers événements concernant tous les utilisateurs de LiveJournal.
      +Ajoutez à votre page d'amis pour avoir accès à tous les développements techniques, incluant les problèmes techniques et des rapports sur les problèmes avec le service. +p?> + + +AIM, ICQ, Yahoo!, MSN, ou Jabber. Si vous utilisez aussi certains de ces programmes, n'oubliez pas de partager comment vous joindre sur votre page de profil, en mettant à jour votre page d'informations personnelles. Si vous avez un compte payant, vous pouvez aussi recevoir de la messagerie texte sur votre téléphone sans-fil ou votre paget. +p?> + + +un compte payant. Il existe, bien sûr, plusieurs autres façons d'aider. +

      +LiveJournal est un projet a source ouverte; si vous avez de l'expérience en programmation ou avec des applications de serveurs vous pouvez allez à la Communauté de dévelopement . Si vous avez des idées pour améliorer LiveJournal, n'hésitez pas à visiter la section des suggestions . Si vous aimeriez aider avec un peu de tout, visitez la communauté affaires . Si vous aimez aider les gens, visitez le support technique. Si vous avez des talents en graphisme, visitez La Communauté d'Art de LiveJournal. +p?> + + +Anime, le Bouddhisme Zen, l'Astronomie ou Invader Zim. Vous trouverez aussi des communautés régionales. Il y a sûrement une communauté pour votre propre région! +p?> + + +question dans la FAQ qui vous expliquera comment créer votre propre communauté. Il y a aussi deux catégories de FAQ (FAQ générales de LiveJournal et des FAQs de gérance des communautés) qui couvrent à peu près tout ce que vous voudrez jamais savoir à propos des communautés. Si vous avez besoin de plus d'informations, n'hésitez pas à soumettre une demande d'aide. +p?> + + + + +
        +
      • La communauté de promotion de communautés ()
      • +
      • La communauté de recherche de communautés ()
      • +
      + + +Envoyez un courriel à Jesse Proulx, () le directeur des communautés. +p?> + +. + +/community/index.bml.title=Centre communautaire + +/community/join.bml.button.join=Joignez la communauté + +/community/join.bml.error.already.member=Vous êtes déjà membre de cette communauté. + +/community/join.bml.error.closed=Cette communauté n'est pas ouverte aux nouveaux membres. Si vous voulez y adhérer, veuillez contacter les administrateurs suivants: [[admins]] + +/community/join.bml.error.statusvis.body=Le compte avec lequel vous êtes connecté n'est pas un compte actif. + +/community/join.bml.error.statusvis.title=Incapable d'adhérer aux communautés. + +/community/join.bml.label.addtofriends=Ajouter '[[maintainer]]' à votre liste d'amis.
      + +/community/join.bml.label.allowposting=Cette communauté permet à tout les membres de faire des entrées, vous pouvez donc faire de même maintenant. Si vous avez déjà un client de Live Journal en marche sur votre ordinateur, vous devrez vous déconnecter et vous reconnecter pour que la communauté apparaisse dans votre liste de journaux dans lesquels vous pouvez écrire. + +/community/join.bml.label.auth=Bien que vous êtes maintenant un membre de cette communauté, celle-ci ne permet qu'aux utilisateurs autorisés à faire des entrées. Contactez un des administrateurs si vous désirez y avoir accès. Voici une liste des administrateurs de cette communauté: [[admins]] + +/community/join.bml.label.banned=Le modérateur de cette communauté vous a banni et vous ne pouvez vous joindre à la communauté. + +/community/join.bml.label.closed=Cette communauté est fermée. Si vous êtes interessé à la joindre, s'il-vous-plaît contactez un des administrateurs. Voici une liste des administrateurs de cette communauté: [[admins]] + +/community/join.bml.label.commlogged=Vous êtes connecté avec un compte partagé ou une communauté, et non avec votre journal personnel. + +/community/join.bml.label.errorcomminfo= L'information spécifié pour la communauté n'est pas valide. + +/community/join.bml.label.expls=Clicker sur le bouton ci-dessous pour joindre la communauté "[[maintainer]]". Enlever le crochet de la boîte ci-dessous si vous voulez joindre la communauté sans l'ajouter à votre page d'amis. + +/community/join.bml.label.loginfirst= Pour joindre une communauté, vous devez d'abord vous connecter. + +/community/join.bml.label.membernow=Vous êtes maintenant membre de la communauté [[commname]]. + +/community/join.bml.label.sure=En êtes-vous certain? + +/community/join.bml.reqsubmitted.body=Votre demande d'adhésion à la communauté à été envoyée aux administrateurs: + +/community/join.bml.reqsubmitted.title=Votre demande d'adhésion à la communauté est envoyée. + +/community/join.bml.request.body=La communauté [[comm]] n'est pas à inscription ouverte. Veuillez vérifier que vous voulez joindre cette communauté en cliquant ci-dessous. + +/community/join.bml.request.reason=Optionellement, entrez une raison pour laquelle vous voulez joindre cette communauté: + +/community/join.bml.request.title=Requête pour joindre la communauté + +/community/join.bml.success=Succès + +/community/join.bml.title=Joignez la communauté + +/community/leave.bml.button.leave=Quittez la communauté + +/community/leave.bml.label.buttontoleave=Cliquer sur le bouton plus bas pour quitter la communauté '[[commname]]". + +/community/leave.bml.label.infoerror=L'information spécifiée pour la communauté n'est pas valable + +/community/leave.bml.label.logoutfirst=Avant de quitter une communauté, vous devez être connecté. + +/community/leave.bml.label.removed=Vous n'êtes plus membre de la communauté [[commname]] + +/community/leave.bml.label.removefromfriends=Retirer aussi "[[user]]" de ma liste d'amis. + +/community/leave.bml.success=Succès + +/community/leave.bml.sure=En êtes vous certain? + +/community/leave.bml.title=Quitter la communauté + +/community/manage.bml.commlist.actinfo=Profil + +/community/manage.bml.commlist.actmembers=[Membres] + +/community/manage.bml.commlist.actmembers2=Membres + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] en attente + +/community/manage.bml.commlist.actsettings=[Options] + +/community/manage.bml.commlist.actsettings2=Paramètres + +/community/manage.bml.commlist.header=Vos communautés + +/community/manage.bml.commlist.moderation=En attente de changements + +/community/manage.bml.commlist.moderation.num=[[[num]] en queue] + +/community/manage.bml.commlist.none=Vous n'administrez aucune communauté. + +/community/manage.bml.commlist.text=Voici une liste des communautés que vous administrez ou co-administrez: + +/community/manage.bml.commlist.title=Titre + +/community/manage.bml.commlist.username=Nom d'utilisateur + +/community/manage.bml.create.header=Créez une communauté + +/community/manage.bml.create.text=Vous pouvez aussi créer une nouvelle communauté. + +/community/manage.bml.joinmail.body=Pour les communautés avec des inscriptions fermés, vous avez plusieurs options de courriel: + +/community/manage.bml.joinmail.email.all=Recevoir un courriel chaque fois que quelqu'un demande à joindre la communauté + +/community/manage.bml.joinmail.email.digest=Recevoir un courriel par jour avec une liste de toutes les requêtes en attente + +/community/manage.bml.joinmail.email.none=Aucun courriel. Vous devrez alors utiliser cette page-ci pour vérifier les requêtes. + +/community/manage.bml.joinmail.save=Sauvegarder les paramètres + +/community/manage.bml.joinmail.title=Options d'administration + +/community/manage.bml.title=Administration des communautés + +/community/members.bml.error.alreadyadded=[[user]] n'a pas été ajouté parce qu'il ou elle a déjà accès à la communauté. + +/community/members.bml.error.alreadysent=[[user]] n'a pu être ajouté parce qu'il ou elle a déjà reçu un courriel de confirmation à la date suivante : [[datetime]]. Veuillez attendre leur réponse. + +/community/members.bml.error.invaliduser=La communauté ou le compte syndiqué [[user]] ne peut être ajouté. + +/community/members.bml.error.noaccess=Il n'est permis qu'aux administrateurs d'éditer la liste de membres de la communauté. Vous n'êtes pas un administrateur de la communauté [[comm]]. + +/community/members.bml.error.noattr=Pas d'attributs sélectionnés pour cet utilisateur : [[user]] + +/community/members.bml.error.nocomm=Communauté non trouvée. + +/community/members.bml.error.nouser=Cet utilisateur n'existe pas : [[user]] + +/community/members.bml.key.admin=Administrateur + +/community/members.bml.key.member=Membre + +/community/members.bml.key.moderate=Modérateur + +/community/members.bml.key.post=Autorisation de l'envoi + +/community/members.bml.key.preapprove=Pas supervisées + +/community/members.bml.key.user=Utilisateur + +/community/members.bml.manage2=S'occuper des communautés + +/community/members.bml.name=Nom de la communauté: [[name]] + +/community/members.bml.nextlink=(Page suivante...) + +/community/members.bml.prevlink=(Page précédente...) + +/community/members.bml.settings=[Options] + +/community/members.bml.success.header=Succès + +/community/members.bml.success.message=Vos modifications ont étés sauvegardées. + +/community/members.bml.success.return=Retournez à la liste + +/community/members.bml.title=Membres de la communauté + +/community/members.bml.update=Sauvegarder + +/community/moderate.bml.approve.button=Oui, je l'accepte + +/community/moderate.bml.approve.header=Accepter cette entrée? + +/community/moderate.bml.approve.preapprove=Ajouter aussi l'utilisateur [[user]] à la liste d'utilisateurs autorisés pour cette communauté. + +/community/moderate.bml.approve.text=Êtes-vous sur de vouloir accepter cette entrée? + +/community/moderate.bml.brlist.poster=Auteur + +/community/moderate.bml.brlist.subject=Le sujet commence + +/community/moderate.bml.brlist.time=Heure + +/community/moderate.bml.brlist.view=Affichage + +/community/moderate.bml.browse.empty=La liste de supervision est vide. + +/community/moderate.bml.browse.header=Superviser la communauté + +/community/moderate.bml.browse.text=Voici la liste de supervision pour la communauté [[links]] + +/community/moderate.bml.choice.approve=Accepter + +/community/moderate.bml.choice.reject=Rejeter + +/community/moderate.bml.error.noaccess=Vous ne supervisez pas la communauté [[comm]]. + +/community/moderate.bml.error.noentry=Entrée introuvable (peut être déjà effacée par un autre modérateur) + +/community/moderate.bml.error.nolist=Vous ne supervisez aucune communauté. + +/community/moderate.bml.error.notfound=Compte de la communauté introuvable. + +/community/moderate.bml.manage=Pour s'occuper des comunautés + +/community/moderate.bml.moderate=Superviser cette commuanuté + +/community/moderate.bml.modlist.actmodempty=[Supervisé(e)] + +/community/moderate.bml.modlist.actmoderate=Superviser + +/community/moderate.bml.modlist.count=Longueur de la file d'attente + +/community/moderate.bml.modlist.header=Superviser les communautés + +/community/moderate.bml.modlist.title=Titre + +/community/moderate.bml.modlist.username=Nom d'utilisateur + +/community/moderate.bml.posted.appheader=Déjà accepté + +/community/moderate.bml.posted.apptext=De plus, l'utilisateur [[user]] a été ajouté à la liste d'utilisateurs déjà acceptés dans cette communauté. + +/community/moderate.bml.posted.header=Succès + +/community/moderate.bml.posted.proterror=L'entrée n'a pas été affichée à cause de cette erreur de protocole : [[err]] + +/community/moderate.bml.posted.text=L'entrée a été affichée avec succès. + +/community/moderate.bml.reject.button=Oui, rejetez-la + +/community/moderate.bml.reject.header=Rejeter cette entrée? + +/community/moderate.bml.reject.reason=Vous pouvez aussi expliquer à l'utilisateur vos raisons de rejeter l'entrée. Elles seront envoyées à l'utilisateur par courriel. + +/community/moderate.bml.reject.text=Êtes-vous sûr de vouloir rejeter cette entrée? + +/community/moderate.bml.rejected.header=Rejetée + +/community/moderate.bml.rejected.text=Cette entrée à été rejetée. + +/community/moderate.bml.title=Administration de la communauté + +/community/pending.bml.approve.title=Accepter l'inscription? + +/community/pending.bml.no=Non + +/community/pending.bml.nopending.body=Il n'y a pas de requête d'inscription en attente pour cette communauté. + +/community/pending.bml.nopending.title=Personne n'est en attente. + +/community/pending.bml.success.added=Vous avez ajouté [[num]] [[?num|personne|personnes]] à cette communauté. + +/community/pending.bml.success.ignored=[[num]] [[?num|requête est|requêtes sont]] encore en attente. + +/community/pending.bml.success.previous=[[num]] [[?num|requête a|requêtes ont]] été [[?num|passée|passées]], puisqu'[[?num|elle n'est|elles ne sont]] plus en attente. Un autre administrateur s'en est peut être occupé. + +/community/pending.bml.success.rejected=Vous avez rejeté [[num]] [[?num|requête|requêtes]] d'adhérer à cette communauté. + +/community/pending.bml.title=Requêtes d'inscription en attente + +/community/pending.bml.yes=Oui + +/community/search.bml.button.clear=Recommencer + +/community/search.bml.button.search=Chercher! + +/community/search.bml.checkbox.onlywithpics=Seulement les communautés avec des images + +/community/search.bml.label.byinterest=Par intérêt + +/community/search.bml.label.bylocation=Par endroit + +/community/search.bml.label.bytime=Selon l'heure de mise à jour du journal + +/community/search.bml.label.city=Ville + +/community/search.bml.label.country=Pays + +/community/search.bml.label.displayoptions=Afficher les options + +/community/search.bml.label.hasmember=A ce membre + +/community/search.bml.label.othercriteria=Autres critères + +/community/search.bml.label.outputformat=Mode d'afffichage + +/community/search.bml.label.records=Entrées par page: + +/community/search.bml.label.searchcomm=Chercher dans les communautés + +/community/search.bml.label.selecriteria=Choisissez un critère avec lequel vous ferez une recherche. Les résultats contiendront tous les critères. En d'autres termes, chaque boîte à cocher veut dire "ET", et non "OU". + +/community/search.bml.label.sortmethod=Méthode d'assemblage + +/community/search.bml.label.stateprovince=État/Province + +/community/search.bml.label.updated=Mis à jour dans les derniers + +/community/search.bml.sel.bypicture=Par icône + +/community/search.bml.sel.communityname=Nom de la communauté + +/community/search.bml.sel.commview=Vue de la communauté + +/community/search.bml.sel.day=jour + +/community/search.bml.sel.month=mois + +/community/search.bml.sel.updatetime=Heure de mise à jour + +/community/search.bml.sel.username=Nom d'usager + +/community/search.bml.sel.week=semaine + +/community/search.bml.title=Recherche par communauté + +/community/settings.bml.button.changecommunity=Sauvegarder + +/community/settings.bml.button.createcommunity=Créez une communauté + +/community/settings.bml.error.badpassword=Mot de passe de la communauté invalide + +/community/settings.bml.error.hasentries=Ce compte a déjà des entrées et ne peut être convertis. + +/community/settings.bml.error.maintainertype=Le compte de l'administrateur doit être un compte individuel, pas un autre compte partagé. + +/community/settings.bml.error.noaccess=Seulement les administrateurs d'une communauté peuvent modifier les options de la communauté. Vous n'êtes pas administrateur de la communauté [[comm]]. + +/community/settings.bml.error.notcomm=Ce compte n'est pas une communauté. + +/community/settings.bml.error.notfound=Compte de la communauté non trouvé. + +/community/settings.bml.error.samenames=Le compte de l'administrateur et le compte de la communauté ne peuvent être les mêmes. + +/community/settings.bml.label.anybodycan=Tous les membres
      N'importe qui peut envoyer des entrées s'il est un membre. + +/community/settings.bml.label.changeheader=Modifier les préférences de la communauté + +/community/settings.bml.label.changetext=Ici vous pouvez modifier les préférences pour la communauté que vous possédez ou administrez. + +/community/settings.bml.label.closedmemb2= Inscription fermée
      Personne ne peut adhérer à la communauté. + +/community/settings.bml.label.commchanged=Vos modifications ont étés sauvegardées. + +/community/settings.bml.label.commcreate=Ceci est le compte que vous voulez changer en communauté. Il faut qu'il est déjà été créé, mais il ne doit pas déjà être utilisé par un individu, parce qu'après ce changement, beaucoup d'utilisateurs pourraient potentiellement faire des entrées dans cette communauté. + +/community/settings.bml.label.commcreated=Votre communauté a été créée. + +/community/settings.bml.label.commheader=Compte de la communauté + +/community/settings.bml.label.comminfo=Profil de la communauté + +/community/settings.bml.label.commopts=Options de la communauté + +/community/settings.bml.label.commsite=Site web de la communauté + +/community/settings.bml.label.community=Communauté: + +/community/settings.bml.label.createheader=Créez une communauté + +/community/settings.bml.label.createtext=Ici il vous sera possible de créer une communauté. Une communauté est un type de compte spécial que d'autres utilisateurs peuvent joindre et auquel ils peuvent faire des entrées. Pour un exemple d'une communauté, visitez la communauté France. + +/community/settings.bml.label.howoperates=Choisissez comment votre communauté doit fonctionner. Il vous sera possible de changer ces options plus tard. + +/community/settings.bml.label.maintainer=Administrateur: + +/community/settings.bml.label.maintainer.login=Si cela n'est pas le compte de l'administrateur, connectez-vous comme quelqu'un d'autre. + +/community/settings.bml.label.managepage=Administration de la communnauté - pour ajouter des membres, permettre de faire des entrées, ajouter des modérateurs, etc. + +/community/settings.bml.label.membership=Inscription + +/community/settings.bml.label.moderatedmemb=Inscriptions Contrôlées>br/> Les requêtes pour adhérer à la communauté vous sont envoyées par courriel pour que vous les acceptiez. + +/community/settings.bml.label.modheader=Supervision + +/community/settings.bml.label.modis=Supervisée
      Les nouvelles entrées doivent être approuvées par un modérateur. + +/community/settings.bml.label.modisnt=Pas supervisée
      Les nouvelles entrées sont affichées immédiatement. + +/community/settings.bml.label.modtext=Est-ce que les soumissions à la communauté sont supervisées? + +/community/settings.bml.label.nmcan=Les non-membres peuvent faire des entrées
      N'importe quel utilisateur peut faire des entrées à la communauté sans la joindre. + +/community/settings.bml.label.nmcant=Les non-membres ne peuvent pas faire d'entrées
      Il faut joindre la communauté pour y faire des entrées. + +/community/settings.bml.label.nmheader=Messages des non-membres + +/community/settings.bml.label.nmtext=Est-ce qu'il faut joindre cette communauté pour faire des entrées? + +/community/settings.bml.label.openmemb=Admission ouverte
      N'importe qui peut joindre sans autorisation. + +/community/settings.bml.label.password=Mot de passe: + +/community/settings.bml.label.postaccess=Autorisation de faire des entrées + +/community/settings.bml.label.rellinks=Liens utiles: + +/community/settings.bml.label.selcan=Membres autorisés
      Seulement certains membres peuvent faire des entrées qui ont étés autorisés par l'administrateur de la communauté. + +/community/settings.bml.label.username=Nom d'utilisateur: + +/community/settings.bml.label.whocanjoin=Qui peut joindre votre communauté? + +/community/settings.bml.label.whocanpost=Qui peut faire des entrées à la communauté? + +/community/settings.bml.manage2=Administrer les communautés + +/community/settings.bml.members=[Membres] + +/community/settings.bml.name=Nom de la communauté: [[name]] + +/community/settings.bml.success=Succès + +/community/settings.bml.title.create=Créez une communauté + +/community/settings.bml.title.modify=Options de la communauté + +/create.bml.age.check.question= Avez-vous moins de 13 ans? + +/create.bml.age.check.yes= Oui, j'ai moins de 13 ans. + +/create.bml.age.check2.question=Avez-vous plus de 13 ans? + +/create.bml.age.check2.yes=Oui, j'ai plus de 13 ans. + +/create.bml.age.head=Âge + +/create.bml.btn.create=Créez un journal + +/create.bml.btn.proceed=Procéder... + +/create.bml.captcha.answer=Réponse: + +/create.bml.captcha.audiodesc=Tapez les chiffres que vous entendez pour prouver que vous n'êtes pas un robot publicitaire: + +/create.bml.captcha.desc=Tapez les lettres et les chiffres que vous voyez ci-dessous pour prouver que vous n'êtes pas un robot publicitaire. Si vous ne pouvez pas lire le texte, écrivez "AUDIO" et faites le test sonore à la place. + +/create.bml.captcha.invalid=Vous avez raté le test précédent. Essayez-en un autre. + +/create.bml.captcha.play=Jouez le son + +/create.bml.captcha.prove=Prouvez que vous êtes humain + +/create.bml.clusterselect.head=Sélection de cluster + +/create.bml.clusterselect.nocluster=Pas de cluster + +/create.bml.clusterselect.text=Veuillez selectionner le cluster que voius voulez pour créer votre compte. + +/create.bml.create.head=Créer un nouveau journal + +/create.bml.create.text=Créer un nouveau LiveJournal est facile, suivez les instructions ci-dessous. + +/create.bml.email.head=Votre adresse courriel. + +/create.bml.email.input.head=Adresse courriel: + +/create.bml.email.text2=Pour des raisons de sécurité, votre adresse courriel nous est nécessaire. En aucun cas celle-ci ne sera divulguée ou distribuée à des services de publicités. Nous avons horreur de cela. Pour plus d'informations, lisez notre charte sur la vie privée. + +/create.bml.error.coppa.under13=Désolé, due à des restrictions de COPPA, vous ne pouvez utiliser LiveJournal avant l'age de 13 ans. Revenez à votre 13e anniversaire! + +/create.bml.error.email.blank=Vous devez soumettre une adresse de courriel. + +/create.bml.error.email.lj_domain=Vous ne pouvez pas utiliser un alias de [[domain]] lorsque vous créez un compte. Veuillez utiliser une autre adresse électronique. + +/create.bml.error.email.nospaces=Aucun espace n'est permit dans une adresse de courriel. Si vous êtes un usager de AOL, souvenez-vous que votre courriel est constitué de votre non d'usager sans les espaces, suivi de @aol.com. + +/create.bml.error.password.asciionly=Vous ne pouvez utiliser que des symboles ASCII dans votre mot de passe. + +/create.bml.error.password.blank=Vous devez entrer un mot de passe. + +/create.bml.error.password.nomatch=Les mots de passe ne correspondent pas. + +/create.bml.error.postrequired=ENTRÉE requise + +/create.bml.error.username.blank=Veuillez soumettre un nom ou un alias + +/create.bml.error.username.inuse=Ce nom d'usager est déjà pris; veuillez en choisir un nouveau. + +/create.bml.error.username.iscode=Ce nom d'usager semble être un code d'invitation, et non un nom d'usager. + +/create.bml.error.username.mustenter=Vous devez soumettre un nom d'usager. + +/create.bml.error.username.reserved=Désolé, ce nom d'usager est réservé. + +/create.bml.errors.label=Veuillez noter les problèmes suivants et réessayer: + +/create.bml.initial.friend.lj_maintenance=Rapports des périodes d'entretien et d'inaccès au site prévues et imprévues + +/create.bml.initial.friend.news=Nouvelles et événements de LiveJournal + +/create.bml.initialfriends=Ajouter ces journaux à votre liste d'amis pour rester à jour des nouvelles et des informations concernant le site. + +/create.bml.initialfriends.heading=Premiers amis + +/create.bml.name.head=Votre nom + +/create.bml.name.input.head=Nom: + +/create.bml.name.text=uel est votre nom ou votre surnom? Ceci apparaîtra en haut de votre journal, et dans le répertoire des utilisateurs si vous décidez d'en faire parti. Vous n'ête pas obligé de donner votre nom au complet, ni votre vrai nom. + +/create.bml.password.head=Mot de passe + +/create.bml.password.input.head1=Mot de passe: + +/create.bml.password.input.head2=Confirmez votre mot de passe. + +/create.bml.password.text=Choississez un mot de passe. + +/create.bml.proceed.btn.proceed=Allez-y... + +/create.bml.proceed.warning=N'appuyez sur Allez-y qu'une seule fois!! + +/create.bml.success.btn.enterinfo=Entrer votre information personelle + +/create.bml.success.head=Succès! + +/create.bml.success.text1=Votre journal à été créé. De l'information importante, contenant des instructions pour continuer l'inscription vous à été envoyée au courriel [[email]]. Confirmez la création de votre journal en cliquant sur le lien qui vous a été envoyé par courriel. + +/create.bml.success.text2=Votre journal sera disponible à: + +/create.bml.success.text3=Prenez le temps de remplir quelques informations à propos de vous. C'est optionel, mais ça nous donne une idée de qui utilise LiveJournal. + +/create.bml.title=Créez un nouveau journal + +/create.bml.tos.error=Vous devez lire et approuver les Conditions du service avant de créer un compte. + +/create.bml.tos.haveread=J'ai lu et j'approuve des Conditions du service + +/create.bml.tos.heading=Conditions du service + +/create.bml.tos.p1.2=Pour continuer, veuillez lire et accepter nos Conditions d'utilisation. + +/create.bml.useacctcodes.entercode=Pour créer un nouveau compte, veuillez entrer votre code de création de compte. Pour plus d'informations, voyez Comment est-ce que je crée un compte? + +/create.bml.useacctcodes.welcome=Bienvenue + +/create.bml.username.box.head=Nom d'utilisateur: + +/create.bml.username.charsallowed=Votre nom d'utilisateur ne peut contenir que des lettres minuscules (a à z), des chiffres (0 à 9) et un trait (_).
      De plus, il ne doit pas dépasser 15 caractères. + +/create.bml.username.forpaidaccts=Ou, pour les comptes payants: + +/create.bml.username.head=Nom d'utilisateur + +/create.bml.username.ljaddress=Votre journal sera aux adresses suivantes: + +/create.bml.username.text=Chaque utilisateur de [[sitename]] doit avoir son propre nom d'utilisateur. Votre nom d'utilisateur apparaît dans l'adresse de votre journal et est utilisé pour se connecter sur le serveur de [[sitename]]. Il est également affiché quand vous postez des commentaires sur le journal de quelqu'un. + +/create.bml.username.username=nom d'utilisateur + +/customize/index.bml.change=Changez + +/customize/index.bml.choose=Voulez-vous utiliser l'ancien système, ou le nouveau? + +/customize/index.bml.choose.header=Choississez un système de style + +/customize/index.bml.choose.s1=Ancien Système (S1) + +/customize/index.bml.choose.s2=Nouveau Système (S2) + +/customize/index.bml.error.cant_generate_user_layer=N'a pu créer une l'interface de l'utilisateur + +/customize/index.bml.error.fail_create_style=La création du nouveau style a échouée. + +/customize/index.bml.error.not_your_layout=Ceci n'est pas votre disposition. + +/customize/index.bml.error.not_your_theme=Ceci n'est pas votre thème. + +/customize/index.bml.error.no_core_parent=Vous n'avez pas de noyau de base? + +/customize/index.bml.previews=(Aperçus) + +/customize/index.bml.s1=L'ancien système de style est configuré en utilisant la page de modification de journal . + +/customize/index.bml.s1.header=Vous utilisez S1 + +/customize/index.bml.s2.advanced.denied=Seul les utilisateurs avec des comptes payants, permanents et précurseurs peuvent utiliser la section de paramètres avancés. Découvrez les bénéfices des comptes payants. + +/customize/index.bml.s2.advanced.header=Paramètres avancés + +/customize/index.bml.s2.advanced.permitted=Pour créer de nouvelles dispostitions et styles du tout début, visitez le centre de paramètres avancés. + +/customize/index.bml.s2.customize=Les paramètres suivants dépendent de la disposition de votre style. + +/customize/index.bml.s2.customize.header=Étape 2: Personnaliser la dispostion + +/customize/index.bml.s2.customize.language=Les langues suivantes sont partiellement ou complètement supportées par cette disposition. + +/customize/index.bml.s2.customize.language.custom=(Personalisation) + +/customize/index.bml.s2.customize.language.header=langue + +/customize/index.bml.s2.customize.settings=Si vous voulez personnaliser votre journal encore plus, ici vous pouvez jouer avec les paramètres individuels pour que votre journal aie l'apparence que vous voulez lui donner. + +/customize/index.bml.s2.customize.settings.delete=Enlevez les personnalisations + +/customize/index.bml.s2.customize.settings.delete.confirm=Êtes-vous sûr de vouloir supprimer ces personalisations? + +/customize/index.bml.s2.customize.settings.edit=Éditer les personnalisations + +/customize/index.bml.s2.customize.settings.header=Changer les paramètres individuels + +/customize/index.bml.s2.customize.settings.new=Personnalisez + +/customize/index.bml.s2.customize.themes=Choississez parmis les thèmes optionnels pour cette disposition. + +/customize/index.bml.s2.customize.themes.default=(Disposition par défaut) + +/customize/index.bml.s2.customize.themes.header=Thèmes + +/customize/index.bml.s2.layout=Choississez votre disposition. Parce que la sélection des thèmes et des modifications personnalisées depend de votre disposition, changer cette option efface toutes les modifications précédentes. + +/customize/index.bml.s2.layout.header=Étape 1: Dispostition + +/customize/index.bml.s2.related.editinfo.about=Fixez le titre de votre journal ainsi que plusieurs options. + +/customize/index.bml.s2.related.header=Pages apparentées + +/customize/index.bml.s2.related.links.about=Certain styles peuvent inclure votre liste de liens. + +/customize/index.bml.s2.related.modify.about=Fixez votre série d'icônes d'humeur. + +/customize/index.bml.title=Personnalisez votre journal + +/delcomment.bml.changeoptions= NB: À partir de la page [[link]], vous pouvez choisir de laisser soit tout le monde, les utilisateurs enregistrés, ou seulement vos amis faire des commentaires dans votre journal. + +/delcomment.bml.confirm.banuser=Empêcher [[user]] de faire des commentaires dans votre journal. + +/delcomment.bml.confirm.body=Êtes-vous sûr de vouloir supprimer ce commentaire? + +/delcomment.bml.confirm.head=Supprimer ce commentaire? + +/delcomment.bml.confirm.spam=Notez ce commentaire comme étant du pourriel + +/delcomment.bml.confirm.submit=Supprimer le commentaire + +/delcomment.bml.error.alreadydeleted=Le commentaire spécifié à déjà été supprimé. + +/delcomment.bml.error.cantdelete=Un commentaire ne peut être supprimé que par l'auteur ou le propriétaire du journal. + +/delcomment.bml.error.cantdelete.comm=Un commentaire ne peut être supprimé que par son auteur, l'auteur de l'entrée, ou le modérateur de la communauté. + +/delcomment.bml.error.invalidtype=Commentaire non valide. Cette page sert seulement à commenter les entrées d'un journal. + +/delcomment.bml.error.nocomment=Le commentaire spécifié n'existe pas. + +/delcomment.bml.success.andban=Le commentaire a été effacé et l'utilisateur ne pourra plus écrire de commentaires dans votre journal. + +/delcomment.bml.success.head=Effacé + +/delcomment.bml.success.noban=Le commentaire a été effacé. + +/delcomment.bml.success.spam=De plus, les administrateurs de ce site ont été prévenus que ce commentaire était du pourriel. Merci de l'avoir rapporté. + +/delcomment.bml.title=Effacer le commentaire + +/developer/index.bml.clients=Vous voulez créer ou améliorer un client de LiveJournal? Merveilleux! Vous trouverez les ressources nécéssaires afin de savoir comment LiveJournal fonctionne plus bas. + +/developer/index.bml.clients.header=Pour écrire des clients de LiveJournal + +/developer/index.bml.clients.links<< +
      +
      Protocole de communication entre le serveur et les clients
      +
      Apprenez comment le client de LiveJournal sur votre ordinateur communique avec le serveur de LiveJournal, et vice-versa. Comprendre ceci est primordial et c'est la première chose que vous devez savoir avant de développer ou d'améliorer un client.
      +
      Documents complet du protocole
      +
      Tout les modes de protocoles & méthodes.
      +
      Liste des clients
      +
      Voici une liste de la plupart des clients utilisés pour se connecter à LiveJournal. La plupart de ceux-ci sont à source ouverte, et ils sont tous gratuits à utiliser. C'est un endroit parfait pour avoir des exemples pour votre client.
      +
      +. + +/developer/index.bml.code=Pour voir ce qui fait sauter LiveJournal, et pour voir le codage de quelques-uns des clients disponibles, allez à la page du code source. + +/developer/index.bml.code.header=Dépôt du code source de LiveJournal + +/developer/index.bml.dbschema=Curieux à propos du schema de la base de données? Le code SQL pour créer toutes les tables et pour les remplir est inclus avec le code source du serveur. + +/developer/index.bml.dbschema.header=Schéma de la base de données + +/developer/index.bml.embedding=Voulez-vous inclure votre journal dans votre page web? Il y a plusieurs façons de faire ceci, en fonction de quel type de contrôle vous avez sur votre serveur. Vous n'avez à vous inquiéter de ceci seulement si vous n'aimez pas voir www.livejournal.com apparaître dans le lien de votre journal. + +/developer/index.bml.embedding.header=Pour inclure votre LiveJournal + +/developer/index.bml.notice.header=Notez + +/developer/index.bml.notice1=L'information qui suit est pour les programmeurs et les utilisateurs avancés seulement. Si vous voulez utiliser LiveJournal simplement pour y garder votre journal, parfait! La plupart des utilisateurs n'ont pas à se préoccuper de ceci. + +/developer/index.bml.notice2=Cela dit, le contenu ci-dessous est divisé en deux sections: les informations sur comment personnaliser l'apparence des pages de LiveJournal, et l'information sur comment écrire des clients pour communiquer avec le serveur de LiveJournal. + +/developer/index.bml.styles=Vous n'aimez pas l'apparence de votre journal? Ne vous inquiétez pas, tout est flexible et si vous lisez la documentation ci-dessous vous saurez tout ce qu'il faut savoir pour tout personaliser. + +/developer/index.bml.styles.header=Personaliser l'apparence d'un LiveJournal + +/developer/index.bml.styles.s1.header=Système de style 1 + +/developer/index.bml.styles.s1.system=Système de style + +/developer/index.bml.styles.s1.system.about=Aperçu général de la façon dont le système de style 1 est configuré. + +/developer/index.bml.styles.s1.varlist=Liste des variables + +/developer/index.bml.styles.s1.varlist.about=Liste alphabétique de toutes les variables qui peuvent être modifiées. + +/developer/index.bml.styles.s1.views=Voir les types + +/developer/index.bml.styles.s1.views.about=Une liste des différents façons dont vous pouvez voir votre journal, et des détails de chacun. + +/developer/index.bml.styles.s2.header=Système de style 2 + +/developer/index.bml.styles.s2.layerbrowse=Navigateur de couche S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Une liste complète des couches publiques S2 incluant le système de style S2. L'important ici sont les couches du noyau qui définissent les variables de base, les fonctions et les classes qui font de S2 un système de style puissant. + +/developer/index.bml.styles.s2.manual=Le manuel de S2 + +/developer/index.bml.styles.s2.manual.about=Information complète sur comment utiliser S2 sur LiveJournal. + +/developer/index.bml.title=Informations pour les développeurs + +/directory.bml.browse.country.desc=Sélectionnez un pays pour en lire les journaux. + +/directory.bml.browse.country.title=Parcourez les journaux par pays + +/directory.bml.browse.usa.desc=Cliquez sur un état des États-Unis ci-dessous pour en lire les journaux, ou cliquez sur un nom de pays sur la carte ci-dessous pour lire les journaux de ce pays. + +/directory.bml.browse.usa.title=Parcourez les journaux par état (É-U.) + +/directory.bml.error.accounttype=Désolé, votre type de compte ne vous permet pas d'utiliser le répertoire, ou vous n'êtes pas présentement connecté. Si votre type de compte vous permet d'utiliser le répertoire, assurez-vous d'être connecté et essayez de nouveau. + +/directory.bml.navcrap.matches=[[count]] résultats + +/directory.bml.navcrap.xofy=Page [[curpage]] de [[totpages]] (archives [[reca]]-[[recb]]) + +/directory.bml.open=Ouvrir + +/directory.bml.post=Envoyez + +/directory.bml.search.monkey=Des centaines de singes malins sont et train de chercher une réponse à votre requête. Soyez patient. + +/directory.bml.search.new=Nouvelle recherche + +/directory.bml.search.overflow=Résultats de la recherche limités à [[count]] résultats. Veuillez affiner votre recherche. + +/directory.bml.search.title=Recherche en cours + +/directory.bml.update=Mise-à-jour: + +/directory.bml.user=Utilisateur + +/doc/index.bml.about=Bienvenue aux archives de documentation de LiveJournal. Vous trouverez ici des informations sur la plupart des sujets concernants les services de LiveJournal ou le logiciel du serveur. Veuillez choisir un sujet ci-dessous: + +/doc/index.bml.about.header=Bienvenue + +/doc/index.bml.docs.faq.about=Foire aux questions de LiveJournal.com + +/doc/index.bml.docs.guides.about=Informations supplémentaires à propos de la FAQ + +/doc/index.bml.docs.howto.about=Conseils et trucs pour vous aider à personaliser votre compte LiveJournal + +/doc/index.bml.docs.server.about=Tout ce que vous devez savoir pour installer, administrer, et programmer une installation de LiveJournal + +/doc/index.bml.docs.server.title=Manuel du serveur de LiveJournal + +/doc/index.bml.docs.tour.about=Créé pour aider les nouveaux visiteurs à se familisariser avec le site + +/doc/index.bml.docs.tour.title=Visite + +/doc/index.bml.volunteering.about=Si vous aimeriez aider avec la documentation de LiveJournal, veuillez visiter les forums qui suivent: + +/doc/index.bml.volunteering.header=Bénévolat + +/doc/index.bml.volunteering.ljsysdoc=Discussions à propos du système de documentation de LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=Finir les discussions de la documentation de l'utilisateur + +/doc/tour/index.bml.clients.caption=Les clients LiveJournal sont des petits programmes qui marchent sur votre ordinateur et qui vous permettent de mettre à jour votre journal quand vous êtes en ligne, sans avoir à ouvrir un navigateur. Des clients sonts disponibles pour presque toutes les plate-formes, et beaucoup d'entre eux peuvent être personalisés. + +/doc/tour/index.bml.comms.caption=LiveJournal est une grande communauté interactive, donc il ne faut pas vous étonner que beaucoup de membres ont des intérêts en communs. Pour leur utilisation, LiveJournal offre l'abilité de créer des « communautés Â», c'est-à-dire des journaux que plusieurs personnes peuvent actualiser. + +/doc/tour/index.bml.comms.title=Communautés + +/doc/tour/index.bml.create.caption=LiveJournal est une communauté de journaux basée sur l'inscription. Cette page explique les implications de l'abonnement : qu'est-ce c'est, pourquoi c'est important, et les bénéfices que cela apporte. Il y a aussi un formulaire pour créer son propre compte. + +/doc/tour/index.bml.create.title=Pour créer un compte + +/doc/tour/index.bml.friends.caption=Vous pouvez aussi suivre les vies de vos amis avec LiveJournal, en utilisant la fonction d'amis. Si vous trouvez un journal que vous trouvez intéressant, ajoutez-le à votre liste d'amis, et il vous sera alors possible de lire toutes les entrées de vos amis sur une seule page. + +/doc/tour/index.bml.friends.title=Amis + +/doc/tour/index.bml.intro.caption=Cette visite a pour but de permettre aux nouveaux visiteurs de devenir familiers avec le site. Elle vous montrera où se trouvent les pages les plus importantes ainsi que certaines des fonctions les plus intéressantes. + +/doc/tour/index.bml.intro.title=Bienvenue + +/doc/tour/index.bml.modify.caption=Il est aussi possible de formater votre journal de plusieurs façons en utilisant les styles et les couleurs prédéfinies. Rendez votre journal aussi unique que vous le voulez! + +/doc/tour/index.bml.modify.title=Personnalisation + +/doc/tour/index.bml.nav.next=Suivant --> + +/doc/tour/index.bml.nav.prev=<-- Précédent + +/doc/tour/index.bml.profile.caption=Les membres de LiveJournal sont encouragés à fournir des informations sur eux-mêmes dans leur profils, afin que nous puissions avoir une idée de qui utilise le site et comment mieux les servir. Il n'est pas nécessaire d'inscrire des informations — les seules informations qui sont requises pour commencer à utiliser LiveJournal sont un nom, un courriel et un mot de passe. + +/doc/tour/index.bml.profile.title=Profils + +/doc/tour/index.bml.sitemap.caption=Nous espèrons bien que cette visite vous a donné quelques informations utiles sur le site et le service LiveJournal. Si vous avez besoin d'aide, sentez vous libres de contacter le départment du support. Explorez LiveJournal d'avantage sur le plan du site qui liste toutes les pages sur ce site. + +/doc/tour/index.bml.sitemap.title=Plan du site + +/doc/tour/index.bml.support.caption=La page du support technique liste les régions du site qui vous expliqueront qu'est-ce que LiveJournal, la foire aux questions (FAQ) du site, et d'autres informations utiles sur le service, la compagnie, et la commaunté en général. + +/doc/tour/index.bml.support.title=Recevoir de l'aide + +/doc/tour/index.bml.title=La visite - [[title]] + +/doc/tour/index.bml.update.caption=Mettre à jour un LiveJournal c'est l'essentiel du service ; c'est ainsi que les membres ont l'opportunité de parler de leur vie et de ce qu'ils pensent. Mettre à jour un journal c'est simple. Écrivez une entrée dans la boîte et appuyez sur le bouton marqué « Mettre à jour votre journal Â». Certes, il y a aussi sur cette page des fonctions plus avancées, telle que la capacité de mettre des renseignements supplémentaires, telles que votre humeur ou votre musique actuelle. + +/doc/tour/index.bml.update.title=Mise à jour d'un journal + +/editinfo.bml.advanced.about=Ne vous inquiétez pas de ces choses là si vous ne savez pas ce que c'est. + +/editinfo.bml.advanced.title=Options avancées + +/editinfo.bml.allowshowcontact.about=Vous devriez garder cette option activée. Elle permet aux autres usagers de vous contacter en leur donnant accès à votre courriel, votre numéro ICQ, et votre nom d'utilisateur pour la Messagerie Instantanée de AOL à partir de votre Livejournal. + +/editinfo.bml.allowshowcontact.email=Si visible, l'adresse courriel sera affichée. + +/editinfo.bml.allowshowcontact.email.actual_only=Adresse actuelle seulement + +/editinfo.bml.allowshowcontact.email.both=Les deux (actuelle + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Adresse de LiveJournal seulement + +/editinfo.bml.allowshowcontact.email.neither=Ni l'une, ni l'autre. Ne pas montrer aucune des adresses courriel. + +/editinfo.bml.allowshowcontact.email.no_show=Ne pas montrer d'adresse courriel + +/editinfo.bml.allowshowcontact.email.show=Montrer l'adresse courriel. + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Avec l'option ci-dessus, vous pouvez choisir de cacher votre adresse courriel (tout en montrant le reste de vos informations), de montrer seulement votre courriel de LiveJournal (comptes payants seulement), de montrer votre vraie adresse ou de montrer les deux. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=L'option ci-dessus vous permet de choisir de cacher votre adresse courriel (tout en montrant le reste de vos informations.) + +/editinfo.bml.allowshowcontact.title=Afficher les informations pour vous contacter sur LiveJournal? + +/editinfo.bml.allowshowinfo.about=Activer ceci pour que votre ville/état ou province/pays et votre anniversaire soient visible pour les autres usagers. + +/editinfo.bml.allowshowinfo.title= Montrer où vous habitez & votre anniversaire? + +/editinfo.bml.autotranslate.about<< +Utilisez cette option pour dire à LiveJournal quelle sorte de format utiliser pour vos entrées et vos commentaires faits avant que le site ne soit modifié en Unicode. +Si vous écrivez en français, choisissez "Western European" ici. +. + +/editinfo.bml.autotranslate.header=Convertir automatiquement les ancienes entrées à partir de: + +/editinfo.bml.bday.title=Anniversaire + +/editinfo.bml.bday.year.opt=l'année est optionelle + +/editinfo.bml.bdayreminders.about=Si vous voulez recevoir des courriels vous rappellant des anniversaires de vos amis sur Livejournal, cocher cette boîte. + +/editinfo.bml.bdayreminders.header=Envoyez-moi les rappels pour les anniversaires (désactivé en ce moment) + +/editinfo.bml.bio.about=Ici vous pouvez entrer une mini-biographie à propos de vous qui sera sur votre page de profil. + +/editinfo.bml.bio.header=À propos de vous + +/editinfo.bml.blockrobots.about=Si vous cocher cette option, les robots seront repoussés. Tous les robots ne respectent pas les règles. + +/editinfo.bml.blockrobots.header=Empêcher l'indexation de votre journal par les robots publicitaires. + +/editinfo.bml.chat.icquin.title=Numéro ICQ + +/editinfo.bml.chat.msnusername.title=Nom d'utilisateur MSN + +/editinfo.bml.chat.yahooid.title=Identification Yahoo! + +/editinfo.bml.city.title=Ville + +/editinfo.bml.country.choose=Choississez un pays + +/editinfo.bml.country.title=Pays + +/editinfo.bml.donotlog=Non + +/editinfo.bml.email.title=Courriel + +/editinfo.bml.enableboards.about=Cocher ceci si vous voulez que les autres usagers puissent répondre aux entrées que vous affichez. + +/editinfo.bml.enableboards.header=Activer les forums. + +/editinfo.bml.encoding.about=Ne vous inquiétez pas pour ce qui suit. En général, seul les utilisateurs internationaux qui écrivent dans plusieurs langues différentes auront à changer quelque chose ici. + +/editinfo.bml.encoding.header=Options de codification. + +/editinfo.bml.error.day.notinmonth=Ce jour n'existe pas pour ce mois. + +/editinfo.bml.error.day.outofrange=Ce n'est pas le bon jour de fête (anniversaire). Entrez un jour entre 1 et 31. + +/editinfo.bml.error.email.lj_domain<< +Vous ne pouvez entrer un courriel @[[domain]]. +Entrez votre vrai courriel ici. +Si vous êtes un membre payant, votre adresse [[user]]@[[domain]] transfèrera tout à votre vraie adresse. +Pour choisir quelle adresse (ou les deux) est affichée publiquement, aller à l'option "Montrer vos information pour vous contacter" plus bas. +. + +/editinfo.bml.error.email.none=Vous devez fournir votre adresse courriel. + +/editinfo.bml.error.email.no_space<< +Aucun espace n'est permit dans une adresse courriel. +Si vous utiliser AOL, souvenez-vous que votre Courriel Internet est votre nom d'usager, sans les espaces, suivi de @aol.com. +. + +/editinfo.bml.error.excessive_int<< +Désolé, vous avez ajouté trop d'intérêts La limite est de 150, mais vous en avez ajouté [[intcount]]. +Tout les changements apportés à vos intérêts n'ont pas été sauvegardés. Retourner pour rapetisser la liste et sauvegarder à nouveau. +. + +/editinfo.bml.error.invalidbio=Votre biographie contient des caractères non valable. Vous devez aller à la page de conversion pour convertir en Unicode. + +/editinfo.bml.error.invalidints=Votre liste d'intérêts contient des caractères non valable. Vous devez aller à la page de conversion pour convertir en Unicode. + +/editinfo.bml.error.invalidname=Votre nom contient des caractères non valable. Vous devez aller à la page de conversion pour convertir en Unicode. + +/editinfo.bml.error.locale.country_ne_state=Vous avez spécifié les États-Unis comme étant votre pays, mais vous avez écrit un état non-américain dans " autre état". + +/editinfo.bml.error.locale.invalid_country=Vous avez sélectionner un pays non-disponible. + +/editinfo.bml.error.locale.state_ne_country=Vous avez spécifié un pays autre que les États-Unis, mais sélectionné un état américain. + +/editinfo.bml.error.locale.zip_ne_state<< +Votre code postal ne correspond pas à l'état que vous avez spécifié. +Corrigez l'information ou effacez soit l'état ou le code postal, ou les deux. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Vous avez entré un code postal, mais vous n'avez pas sélectionné les États-Unis comme pays. +Nous ne collectons que les codes postaux des États-Unis. +Veuillez retourner pour effacer le code postal ou sélectionner les États-Unis comme pays. +. + +/editinfo.bml.error.month.outofrange=Ce n'est pas le bon jour de fête (anniversaire). Veuillez entrer un mois entre 1 et 12. (Jan-Dec) + +/editinfo.bml.error.noname=Votre nom est requis. Veuillez au moins écrire votre prénom, ou un surnom. + +/editinfo.bml.error.tm.require.number=Si vous voulez utiliser la messagerie texte, vous devez donner votre numéro de téléphone. + +/editinfo.bml.error.tm.require_provider<< +Si vous utilisez la messagerie texte, vous devez donner votre fournisseur de service. + +si le vôtre n'est pas listé,informez nous du fonctionnement de votre service de messagerie texte pour que nous l'ajoutions à la liste supportée. +. + +/editinfo.bml.error.year.notenoughdigits=Année de naissance non valable. Veuillez entrer 4 chiffres pour l'année. + +/editinfo.bml.error.year.outofrange=Année de naissance non valable. + +/editinfo.bml.finished.about=Lorsque vous aurez fini, cliquez sur le bouton "Sauvegarder" ci-dessous: + +/editinfo.bml.finished.header=Fini? + +/editinfo.bml.finished.save_button=Sauvegarder + +/editinfo.bml.foafurl.about=Si vous ne voulez pas utiliser la page par défaut de type "FOAF" que nous suggérons, tapez un URL ci-dessus et celui-ci sera utilisé comme source FOAF. Nous redirigerons toutes les demandes FOAF à ce URL. + +/editinfo.bml.foafurl.title=Lien (URL) externe FOAF: + +/editinfo.bml.gender.title=Sexe + +/editinfo.bml.getreplies.about=Cochez ceci si vous voulez recevoir des courriels vous avertissant lorsque d'autres usagers répondent à vos entrées dans les forums. + +/editinfo.bml.getreplies.header=Recevoir les réponses des forums. + +/editinfo.bml.getselfemails.about=Cochez ceci si vous désirez recevoir un courriel chaque fois que vous faites un commentaire dans un journal ou une communauté. Vous ne recevrez pas de courriel pour des commentaires anonymes que vous faites. + +/editinfo.bml.getselfemails.header=Recevez les commentaires que vous faites par courriel + +/editinfo.bml.hidefriendof.about=Si vous cochez ceci, la liste d'utilisateurs qui vous listent comme ami sera cachée sur votre page de profil. + +/editinfo.bml.hidefriendof.header=Cacher la liste d' "Ami de". + +/editinfo.bml.howhear.about=Par curiosité, où avez-vous entendu parler de [[sitename]]? Si c'était quelqu'un en particulier, veuillez entrer son nom d'utilisateur; si c'était d'un(e) autre source/article/lien/site internet, entrez l'information appropriée. + +/editinfo.bml.howhear.header=Curiosité + +/editinfo.bml.htmlemail.about<< +Cochez ceci si votre programe de courriel supporte complètement le HTML. +Plusieurs fournisseurs essaient de le faire, mais échouent horriblement. +Si vous décochez la case, LiveJournal n'enverra que des courriels de texte. +. + +/editinfo.bml.htmlemail.header=Envoyer des courriels en HTML + +/editinfo.bml.imagelinks.about=Les "placeholders" sont utiles si vous visitez le site du travail ou en utilisant une connexion lente car il remplacent les images par des liens. Pour quelle grandeur d'image voulez vous que les "placeholders" soient utilisés? + +/editinfo.bml.imagelinks.header=Utilisez les "placeholders" sur votre page d'amis + +/editinfo.bml.imagelinks.size.all=Utilisez les "placeholders" pour toutes les images + +/editinfo.bml.imagelinks.size.custom=Personalisation: utilisez des "placeholders" pour les images plus grandes que [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=Utiliser les "placeholders" pour les images de grand format( plus de [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=Utiliser les "placeholders" pour les images de format moyen (plus de [[width]]x[[height]]) + +/editinfo.bml.int.about<< +Si vous voulez que d'autres utilisateurs puissent vous trouver dans le répertoire à partir de votre liste d'intérêts, entrer tout ce qui vous interesse ci-dessous, séparé par des virgules. +Le mieux est d'utiliser des mots seuls. La règle d'or: Vouz devriez toujours pouvoir insérer vos intérêts dans la phrase "J'aime le/la/les _______". Lorsque vous faites une référence à un nom commun, utilisez le pluriel pour rester consistant. +. + +/editinfo.bml.int.ex.bad=MAUVAIS exemple: J'aime plusieurs groupes musicaux et regarder des films et parler à mes amis et sortir dans des clubs. Ce genre de chose va dans votre biographie au-dessus. + +/editinfo.bml.int.ex.good=BON exemple: ordinateurs, dvds, mp3s, fromage, femmes, nager, écrire + +/editinfo.bml.int.header=Intérêts + +/editinfo.bml.login.enterinfo=Entrez votre nom d'usager et votre mot de passe pour modifier vos informations personnelles. + +/editinfo.bml.login.forgot.header=Avez-vous oublié quelque chose? + +/editinfo.bml.login.forgot.recover=Si vous avez oublié votre nom d'utilisateur ou votre mot de passe, retrouvez les ici! + +/editinfo.bml.logip.always=Toujours + +/editinfo.bml.logip.anon_only=Commentaires anonymes seulement. + +/editinfo.bml.logip.header=Voulez-vous voir l'adresse IP des personnes qui répondent? + +/editinfo.bml.mangleaddress.about=Si vous avez peur que des robots publicitaires trouvent votre adresse courriel sur LiveJournal, sélectionner cette option. Votre courriel sera modifié pour qu'il ne soit pas trouvé par ces robots. + +/editinfo.bml.mangleaddress.header=Modifier le courriel que vous afficher? + +/editinfo.bml.mutualfriends.about=Cette option ajoute une nouvelle liste à votre page de profil: la liste des amis mutuels. Les utilisateurs qui vous listent comme amis et que vous listez comme ami seront ajoutés à cette liste. + +/editinfo.bml.mutualfriends.header=Affichez la liste d'amis mutuels sur ma page de profil + +/editinfo.bml.name.title=Nom + +/editinfo.bml.newemail.body2<< +Vous venez tout juste de changer votre addresse courriel pour votre compte "[[username]]" sur [[sitename]]. Pour valider ces changements, veuillez aller à cette adresse: + +[[conflink]] + +Sincèrement, +L'équipe de [[sitename]] +[[sitelink]] +. + +/editinfo.bml.newemail.subject=Adresse de courriel modifiée + +/editinfo.bml.numcomments.about=Cochez cette case si vous voulez ajouter le compte de commentaires aux URL pour que votre explorateur puisse afficher les liens d'une couleur différente. + +/editinfo.bml.numcomments.header=Ajouter &nc=xx aux URL de commentaires. + +/editinfo.bml.optional=Optionnel + +/editinfo.bml.opt_in.about<< +Si vous voulez savoir quand nous ajoutons des nouvelles choses à LiveJournal, cochez cette case. +Les courriels que vous recevrez seront rares, soit une ou deux fois par mois, pas plus. +Votre adresse courriel ne sera pas visible aux autres utilisateurs, et vous pouvez désactiver cette fonction n'importe quand. +. + +/editinfo.bml.opt_in.header=Envoyez-moi des nouvelles de LiveJournal. + +/editinfo.bml.persinfo.disclaimer<< +Remplissez quelques informations personelles, pour notre propre curiosité et pour des données statistiques. +Nous ne ferons rien de maléfique ou de déplaisant avec ces informations, nous aimerions seulement voir qui et où sont nos utilisateurs. Veuillez s'il-vous-plaît le remplir correctement. Si vous êtes inquiet, lisez notre police de respect de la vie privée. +. + +/editinfo.bml.persinfo.header=Information personelle + +/editinfo.bml.screen.all=Tout + +/editinfo.bml.screen.anon=Anonyme + +/editinfo.bml.screen.header=Quels commentaires voulez-vous filtrer par défaut? + +/editinfo.bml.screen.none=Aucun + +/editinfo.bml.screen.nonfriends=Ceux qui ne sont pas de mes amis + +/editinfo.bml.screen.nonmembers=Ceux qui ne sont pas membres + +/editinfo.bml.security.header=Qui peut voir vos informations pour vous contacter? + +/editinfo.bml.security.visibility.anybody=N'importe qui + +/editinfo.bml.security.visibility.everybody=Tout le monde + +/editinfo.bml.security.visibility.friends=Mes amis seulement + +/editinfo.bml.security.visibility.regusers=Membres inscrits + +/editinfo.bml.settings.friendspage.title=Titre de la page d'amis : + +/editinfo.bml.settings.friendspage.title.optional=Entrez un titre pour votre page d'amis optionnellement. (pas de HTML) + +/editinfo.bml.settings.header=Options de LiveJournal + +/editinfo.bml.settings.journal.subtitle=Sous-titre de votre journal : + +/editinfo.bml.settings.journal.subtitle.optional=Entrez un titre et un sous-titre pour votre journal optionnellement (pas de HTML) + +/editinfo.bml.settings.journal.title=Titre de votre journal : + +/editinfo.bml.settings.privacy.about=Sélectionnez ci-dessous vos options de vie privée et vos préférences. + +/editinfo.bml.settings.privacy.header=Options de vie privée + +/editinfo.bml.state.other=Ou, tapez un autre état/province/territoire + +/editinfo.bml.state.title=État + +/editinfo.bml.state.us=État américain + +/editinfo.bml.stylemine.about=Sélectionner cette option pour voir les pages de commentaires en utilisant votre style de journal lorsque vous faites des commentaires dans les journaux de vos amis. + +/editinfo.bml.stylemine.header=Voulez-vous voir les pages de commentaires avec votre style de journal? + +/editinfo.bml.success.header=Réussi! + +/editinfo.bml.success.message=Vos informations, vos ajustements de journal ainsi que votre profil ont étés mis à jour. + +/editinfo.bml.switch.button=Changer + +/editinfo.bml.switch.header=Changer de journal + +/editinfo.bml.switch.workwith=Travailler avec le journal: + +/editinfo.bml.title=Éditez vos informations personnelles + +/editinfo.bml.tm.details=détails + +/editinfo.bml.tm.phonenum=Numéro de téléphone complet: + +/editinfo.bml.tm.sec.about=Activer la messagerie texte par les autres utilisateurs. + +/editinfo.bml.tm.sec.title=Niveau de sécurité + +/editinfo.bml.tm.servprov=Fournisseur de service + +/editinfo.bml.tm.title=Messagerie texte + +/editinfo.bml.translatemailto.about=Si vous avez choisi de recevoir les commentaires faits sur le forum par courriel, et que votre fournisseur à quelques difficultés avec les messages en Unicode (UTF-8), utiliser cette option pour spécifier une autre méthode d'encodage que LiveJournal utilisera pour traduire les commentaires qui vous seront envoyés. + +/editinfo.bml.translatemailto.header=Traduire les notifications par courriel en: + +/editinfo.bml.unbanusers.about=Les utilisateurs suivants sont bannis de votre journal et ne peuvent plus y faire de commentaires. Cochez la case à côté de leur nom pour les retirer de la liste d'utilisateurs excluts. + +/editinfo.bml.unbanusers.header=Accepter à nouveau l'utilisateur + +/editinfo.bml.userpic.about=Ci-dessous se trouve l'icône que vous avez chargée pour vous représenter partout sur le site, sur votre journal, et dans le journal de vos amis. + +/editinfo.bml.userpic.edit=Pour effacer cette icône, ou en charger une nouvelle, allez ici. + +/editinfo.bml.userpic.header=Votre icône + +/editinfo.bml.userpic.none=Aucune image n'est chargée + +/editinfo.bml.weblogscom.about=Choississez cette option si vous voulez que Weblogs.com liste votre journal lorsque vous faites de nouvelles entrées publiques. + +/editinfo.bml.weblogscom.header=Notifier Weblogs.com des mises à jour + +/editinfo.bml.webpagename.title=Nom de votre page web + +/editinfo.bml.webpageurl.title=URL de votre page web + +/editinfo.bml.whoreply.header=Qui peut répondre à vos entrées? + +/editinfo.bml.zip.title=Code postal + +/editinfo.bml.zip.usonly=Code postal à 5 unités; pour les résidents des États-Unis seulement + +/editjournal.bml.btn.proceed=Procédez... + +/editjournal.bml.certainday=Jour spécifique: + +/editjournal.bml.desc=Veuillez utiliser le formulaire ci-dessous pour trouver l'entrée que vous voulez éditer. + +/editjournal.bml.in=Dans une communauté: + +/editjournal.bml.recententries=entrées les plus récentes + +/editjournal.bml.recententry=Entrée la plus récente + +/editjournal.bml.title=Éditez vos entrées + +/editjournal.bml.viewwhat=Voir quelles entrées: + +/editjournal_do.bml.body=Éditez les champs de votre journal que vous aimeriez changer et cliquez sur le bouton "sauvegarder les paramètres" au bas de la page. Vous pouvez aussi cliquer sur le bouton "supprimer l'entrée" pour effacer l'entrée. + +/editjournal_do.bml.btn.delete=Supprimer l'entrée + +/editjournal_do.bml.btn.edit=Éditez l'entrée sélectionnée + +/editjournal_do.bml.btn.preview=Aperçu de votre entrée + +/editjournal_do.bml.btn.save=Sauvegarder cette entrée + +/editjournal_do.bml.continue.head=Cliquez pour continuer... + +/editjournal_do.bml.continue.text=Lorsque vous aurez choisi une entrée à éditer ou effacer, cliquez sur le bouton Éditer ci-dessous. + +/editjournal_do.bml.currmood=Humeur actuelle : + +/editjournal_do.bml.currmusic=Musique actuelle: + +/editjournal_do.bml.default=Par défaut + +/editjournal_do.bml.delete.confirm=Êtes-vous sûr de vouloir supprimer cette entrée? + +/editjournal_do.bml.edit.text=Voici l'entrée que vous avez choisi d'éditer. Éditez les parties de votre entrée que vous voulez modifier et cliquez sur le bouton "Sauvegardez" au bas de la page pour sauvegarder. .

      Pour effacer cette entrée, vous n'avez qu'à tout effacer le texte et appuyer sur le bouton "Sauvegardez". + +/editjournal_do.bml.error.getting=Il y a eu une erreur en éditant l'entrée. + +/editjournal_do.bml.error.modify=Il y a eu une erreur lors de la modification de votre journal: + +/editjournal_do.bml.error.nofind=L'entrée sélectionnée n'a pu être trouvée. + +/editjournal_do.bml.event=Entrée : + +/editjournal_do.bml.localtime=Heure locale: + +/editjournal_do.bml.noneother=Aucune, ou une autre: + +/editjournal_do.bml.opt.backdate=Antidater l'entrée : + +/editjournal_do.bml.opt.backdate.about=ne sera pas visible sur les pages d'amis + +/editjournal_do.bml.opt.nocomments=Désactiver les commentaires : + +/editjournal_do.bml.opt.noemail=Ne pas envoyer les commentaires par courriel : + +/editjournal_do.bml.opt.noformat=Ne pas mettre en forme automatiquement : + +/editjournal_do.bml.other=Autre : + +/editjournal_do.bml.pickentry.head=Choisissez une entrée à éditer + +/editjournal_do.bml.pickentry.text=Sélectionnez l'entrée que vous voulez éditer et cliquez sur le bouton pour éditer au bas de la page. + +/editjournal_do.bml.picture=Icôneà utiliser : + +/editjournal_do.bml.preview.header=Aperçu de votre entrée + +/editjournal_do.bml.preview.text=Voici à quoi ressemblera votre entrée lorsqu'elle sera affichée. En utilisant les options ci-dessous vous pouvez continuer à l'éditer, ou vous pouvez l'afficher telle qu'elle. + +/editjournal_do.bml.save.head=Cliquez pour sauvegarder... + +/editjournal_do.bml.save.text=Lorsque vous aurez fini d'éditer votre entrée, cliquez sur Sauvegarder. + +/editjournal_do.bml.subject=Sujet: (facultatif) + +/editjournal_do.bml.success.delete=L'entrée a été effacée. + +/editjournal_do.bml.success.edit=L'entrée a été modifiée. Vous pouvez la voir ici. + +/editjournal_do.bml.success.head=Succès + +/editjournal_do.bml.timeformat=Temps de 24 heures + +/editjournal_do.bml.title=Éditez des entrées + +/editpics.bml.btn.proceed=Procédez + +/editpics.bml.btn.save=Sauvegarder les paramètres + +/editpics.bml.curpics=Icônes actuelles + +/editpics.bml.curpics.desc=Voici les icônes que vous avez déjà téléchargé. Vous pouvez leur assigner des mots clés pour faciliter leur utilisation, sélectionner celle que vous utilisez par défaut, ou effacer celles dont vous ne voulez plus. Pour en télécharger une nouvelle, utilisez le formulaire au bas de la page. + +/editpics.bml.error.badurl=L'adresse pour l'image que vous voulez télécharger ne semble pas correcte. Elle devrait débuter par http:// + +/editpics.bml.error.filetoolarge=L'image téléchargée est trop grande. Le fichier ne peut pas dépasser [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Les dimensions de votre image ([[imagesize]]) dépassent la grandeur maximum. Votre icône ne peut pas dépasser 100x100 pixels. Utilisez un éditeur d'images ou de photos pour en réduire la taille. + +/editpics.bml.error.invalidimage=Fichier image non valable. + +/editpics.bml.error.keywords=Vous avez utilisé le mot clé "[[ekw]]" pour plusieurs icônes. Un mot clé à été choisi au hasard, mais pas celui que vous vouliez.Vous pouvez revenir en arrière et corriger cette erreur. + +/editpics.bml.error.toomanypics2=Vous avez déjà atteint votre limite de [[maxpics]] icônes. Vous ne pouvez pas télécharger cette icône tant que vous n'effacerez pas une icône existante. + +/editpics.bml.error.toomanypics3=Vous avez atteint votre limite d'icônes de [[max]] sur [[?max|picture|pictures]]. Vous ne pourrez ajouter une nouvelle icône tant que vous n'aurez pas effacé une ou plus de vos icônes actuelles. + +/editpics.bml.error.unsupportedtype=Les fichiers de type [[filetype]] ne sont pas supportés. Vous ne pouvez uniquement utiliser des fichiers de types GIF, PNG ou JPG. Presque tous les programmes d'édition d'images ou de photos peuvent faire cette conversion pour vous. + +/editpics.bml.error.urlerror=Une erreur a eu lieu pendant la recherche de votre image. + +/editpics.bml.fromfile=Du Fichier : + +/editpics.bml.fromurl=Du URL : + +/editpics.bml.label.default=Par défaut: + +/editpics.bml.label.delete=Supprimer: + +/editpics.bml.label.keywords=Mots-clés: + +/editpics.bml.makedefault=Faire de cette image votre image par défaut + +/editpics.bml.nodefault=Aucune icône par défaut + +/editpics.bml.noneupload=Vous n'avez pas téléchargé d'icône. Veuillez en télécharger une en utilisant le formulaire ci-dessous. + +/editpics.bml.nopics=Aucune icône + +/editpics.bml.piclimitstatus=Actuellement téléchargé: [[current]] sur un maximum de [[max]]. + +/editpics.bml.restriction.fileformat=Le type de fichier doit être PNG, GIF ou JPG + +/editpics.bml.restriction.filesize=Le fichier doit être inférieur à 40k + +/editpics.bml.restriction.imagesize=Les dimensions de l'image ne peuvent dépasser 100x100 pixels + +/editpics.bml.title=Éditez vos icônes + +/editpics.bml.uploaddesc=Utilisez le formulaire ci-dessous pour télécharger une nouvelle icône. + +/editpics.bml.uploadheader=Télécharger une nouvelle icône + +/export.bml.btn.proceed=Continuez... + +/export.bml.description=Cette option vous permet de télécharger votre journal en entier en un format personnalisé pour des raisons de sécurité. Pour plus d'informations sur comment faire une copie de votre journal, voyez cette FAQ. + +/export.bml.fields=Champs: + +/export.bml.format.csv=CSV (Valeurs Séparées par des Virgules) + +/export.bml.label.encoding=Code: + +/export.bml.label.field.allowmask=Permettre de masquer + +/export.bml.label.field.currents=Humeur & musique actuelles + +/export.bml.label.field.event=Événement + +/export.bml.label.field.eventtime=Heure de l'événement (selon l'heure de l'utilisateur) + +/export.bml.label.field.itemid=Numéro d'identification + +/export.bml.label.field.logtime=Heure de connection (selon l'horloge de l'utilisateur) + +/export.bml.label.field.security=Niveau de sécurité + +/export.bml.label.field.subject=Sujet + +/export.bml.label.format=Format : + +/export.bml.label.header=En-tête + +/export.bml.label.month=Choisissez le mois : + +/export.bml.label.month.month=mm : + +/export.bml.label.month.year=aaaa : + +/export.bml.label.notranslation=Ne pas traduire entre les codes + +/export.bml.label.what=Exporter quoi : + +/export.bml.title=Exporter le journal + +/export.bml.what.entries=Entrées du journal + +/export_do.bml.error.encoding=Code sélectionné non valable + +/friends/add.bml.add.header=Succès + +/friends/add.bml.add.text=L'utilisateur [[user]] a été ajouté à votre liste d'amis. Vous pouvez voir votre page d'amis ici. + +/friends/add.bml.add.title=Ami ajouté! + +/friends/add.bml.btn.add=Ajouter [[user]] + +/friends/add.bml.btn.modify=Modifier + +/friends/add.bml.btn.remove=Enlever + +/friends/add.bml.colors.bg=Arrière-plan + +/friends/add.bml.colors.fg=Avant-plan + +/friends/add.bml.colors.header=Couleurs + +/friends/add.bml.colors.hover=(Passez votre souris sur une couleur pour en voir le nom.) + +/friends/add.bml.colors.text=Vous pouvez aussi sélectionner optionellement les couleurs qui représenteront [[user]] dans votre liste d'amis. + +/friends/add.bml.confirm.header=Ajouter [[user]] comme ami(e)? + +/friends/add.bml.confirm.syn.header=Ajouter la source syndiquée [[user]] comme ami? + +/friends/add.bml.confirm.syn.title=Ajouter la source syndiquée + +/friends/add.bml.confirm.text=Pour ajouter [[user]] à votre liste d'amis, cliquer le bouton ci-dessous. + +/friends/add.bml.confirm.title=Ajouter un ami + +/friends/add.bml.error1.header=Connectez-vous avant + +/friends/add.bml.error1.text=Pour ajouter un ami à votre liste d'amis vous devez d'abord aller vous connecter. Si vous n'avez pas encore de compte vous pouvez en créer un pour suivre les journaux de vos amis. + +/friends/add.bml.error1.title=Ajouter un ami + +/friends/add.bml.error2.text= Nom d'utilisateur non-valable ou manquant. Pour ajouter un ami, allez à la page pour éditez vos amis. + +/friends/add.bml.error3.text=[[user]] est déjà sur votre liste d'amis. Mais, vous pouvez modifier les couleurs que vous avez choisi pour le représenter. + +/friends/add.bml.error3.title=Modifiez vos amis + +/friends/add.bml.groups.header=Groupes d'amis + +/friends/add.bml.groups.nogroup=Aucun groupe d'amis. + +/friends/add.bml.groups.text=Dans quel groupe d'amis voulez vous mettre cet utilisateur? Les groupes d'amis sont utlisés pour filtrer votre page d'amis et la sécurité des entrées. + +/friends/add.bml.remove.header=Succès + +/friends/add.bml.remove.text=L'utilisateur a été retiré de votre liste d'amis. Vous pouvez voir votre page d'amis ici. + +/friends/add.bml.remove.title=Ami retiré! + +/friends/edit.bml.title=Éditez vos amis + +/friends/editgroups.bml.btn.ge.del=Effacez + +/friends/editgroups.bml.btn.ge.new=Nouveau + +/friends/editgroups.bml.btn.ge.ren=Renommez + +/friends/editgroups.bml.btn.gs.private=Privé + +/friends/editgroups.bml.btn.mv.down=Descendre + +/friends/editgroups.bml.btn.mv.up=Monter + +/friends/editgroups.bml.confirm.delete=Êtes-vous sûr(e) de vouloir effacer ce groupe d'amis? + +/friends/editgroups.bml.done.btn=Sauvegardez + +/friends/editgroups.bml.done.header=Fini? + +/friends/editgroups.bml.done.text=Quand vous êtes prêt(e), appuyez sur le bouton ci-dessous pour sauvegarder vos modifications. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Vous êtes arrivé(e) au maximum de 30 groupes d'amis. Si vous avez effacé quelques groupes, mais vous n'avez pas encore sauvegardé cette modification, faites-le maintenant. Retournez ici après et rechargez cette page. Il vous sera alors possible de créer de nouveaux groupes d'amis. + +/friends/editgroups.bml.error.text=Le serveur a retourné l'erreur suivante: + +/friends/editgroups.bml.ingroup=Dans le groupe: + +/friends/editgroups.bml.ingroup.not=Pas dans le groupe: + +/friends/editgroups.bml.prompt.newname=Donnez le nom pour le nouveau groupe d'amis: + +/friends/editgroups.bml.prompt.rename=Renommer le groupe d'amis à: + +/friends/editgroups.bml.saved.header=Sauvegardé + +/friends/editgroups.bml.saved.text=Vos goupes d'amis ont étés sauvegardés. + +/friends/editgroups.bml.text<< +Cette page vous permet d'éditer vos groupes d'amis. Ces groupes d'amis sont utiles pour contrôler la sécurité des entrées et pour filtrer votre page d'amis. Pour plus d'informations voyez Comment est-ce que les groupes d'amis personnalisés fonctionnent? Comment est-ce que je les utilisent? + + +Cette page a besoin de JavaScript pour fonctionner correctement. +. + +/friends/editgroups.bml.text.sec=Note de sécurité: Si vous voulez effacer un groupe et en créer un autre, ne faites pas cela en renommant un groupe et en l'éditant. Si vous faites cela, toutes vos anciennes entrées qui étaient accessibles à l'ancien groupe deviendront accessible aux utilisateurs dans le nouveau groupe. + +/friends/editgroups.bml.title=Modifiez vos groupes d'amis + +/friends/editgroups.bml.yourgroups=Vos groupes d'amis: + +/friends/edit_do.bml.addfriends.head=Ajoutez un ami + +/friends/edit_do.bml.addfriends.text=Entrez le nom d'utilisateur de vos amis dans les boîtes ci-dessous, et choississez quelles couleurs d'arrière-plan et d'avant-plan vous voulez associer avec eux... + +/friends/edit_do.bml.background=Arrière-plan + +/friends/edit_do.bml.bgcolor=Couleur d'arrière-plan + +/friends/edit_do.bml.btn.close=Fermer + +/friends/edit_do.bml.btn.save=Sauvegarder + +/friends/edit_do.bml.btn.toggle=Basculer vers la fenêtre d'aperçu + +/friends/edit_do.bml.done.head=Fini? + +/friends/edit_do.bml.done.text=Lorsque vous aurez fini, cliquer sur le bouton "Sauvegarder" plus bas. + +/friends/edit_do.bml.error.updating=Il y a eu une erreur pendant la mise à jour de votre liste d'amis: + +/friends/edit_do.bml.fellowfriends.head=Compagnons + +/friends/edit_do.bml.fellowfriends.text=Les utilisateurs suivants vous ont ajouté comme ami... Peut être voulez-vous les ajouter aussi. Nous fournissons ceci seulement comme référence pour que vous puissiez savoir leur nom d'utilisateur LiveJournal. Vous n'êtes sous aucune obligation de les ajouter à votre liste d'amis. + +/friends/edit_do.bml.foreground=Avant-plan + +/friends/edit_do.bml.friend=Ami + +/friends/edit_do.bml.hover=Passez votre curseur sur une couleur pour en savoir le nom. + +/friends/edit_do.bml.mrcolor=M. Démonstrateur de Couleurs + +/friends/edit_do.bml.needmore=Si vous avez besoin d'ajouter plus d'amis que vous n'avez de place pour le faire sur cette page, sauvegarder les changements plus bas, et revenez pour en rajouter. + +/friends/edit_do.bml.nofriends.head=Aucun ami? + +/friends/edit_do.bml.nofriends.text=Présentement, vous n'avez aucun ami de défini. Mais nous sommes sûrs que vous devez bien en avoir quelques-uns! :) Vous n'avez qu'à entrer leurs nom d'utilisateurs ci-dessous.... + +/friends/edit_do.bml.opt.addtolist=Ajoutez un ami + +/friends/edit_do.bml.opt.delete=Effacer? + +/friends/edit_do.bml.success.head=Succès + +/friends/edit_do.bml.success.text=Votre liste d'amis à été mise à jour. Vous pouvez voir votre nouvelle page d'amis ici. + +/friends/edit_do.bml.textcolor=Couleur du texte: + +/friends/edit_do.bml.title=Éditez vos amis + +/friends/edit_do.bml.user=Utilisateur + +/friends/edit_do.bml.viewer=Visionneur de couleurs + +/friends/edit_do.bml.yourfriends.head=Vos amis + +/friends/edit_do.bml.yourfriends.text=Voici vos amis actuels: + +/friends/filter.bml.editgroups=Si vous voulez éditer vos groupes d'amis, allez à la page [[link]]. + +/friends/filter.bml.error.nogroups=Vous ne pouvez filter votre liste d'amis parce que vous devez tout d'abord avoir défini des groupes d'amis. + +/friends/filter.bml.error.nogroups.header=Aucun groupe de défini + +/friends/filter.bml.reset=Recommencer + +/friends/filter.bml.select=Sélectionner le(s) groupe(s) d'amis que vous voulez voir sur votre liste d'amis. + +/friends/filter.bml.select.header=Sélectionnez un/des groupe(s) + +/friends/filter.bml.submit=Afficher + +/friends/filter.bml.title=Filtre d'amis + +/friends/index.bml.about<< +Cette page vous permet de gérer votre liste d'amis. +En ajoutant d'autres utilisateurs à votre liste d'amis, vous pouvez facilement lire leur entrées sur votre page d'amis. Vous pouvez aussi ajouter des communautés et des comptes associés à votre liste d'amis afin de voir leur entrées sur votre page d'amis. +. + +/friends/index.bml.edit.about=Ajouter ou retirer des utilisateurs de votre liste d'amis, ou éditez les couleurs utilisées pour ls représenter. + +/friends/index.bml.editgroups.about=Créez, éditez, ou effacez des groupes d'amis. + +/friends/index.bml.filter=Ces groupes d'amis peuvent être utilisés pour filtrer votre page d'amis: si vous le désirez, vous pouvez voir seulement les entrées d'un groupe en particulier. Ils peuvent aussi être utilisés comme moyen de sécurité (voir plus bas). + +/friends/index.bml.filter.about=Filtrez votre liste d'amis selon certain sous-groupes. + +/friends/index.bml.groups=En plus de cela, des sous-groupes d'amis peuvent être spécifiés. + +/friends/index.bml.security=Votre liste d'amis est aussi utilisée pour les entrées avec un accès restreint. Vous pouvez trouver plus d'informations sur la sécurité reliée à votre liste d'amis à Amis & niveaux de sécurité. + +/friends/index.bml.security.custom=Avec des entrées te type "personalisé", vous pouvez spécifiez quel groupe d'amis peut voir votre entrée. Mais ce ne sont pas tout les clients qui utilisent présentement cette fonction. + +/friends/index.bml.security.header=Sécurité + +/friends/index.bml.security.only=Avec les entrées de type "Amis seulement", tout les utilisateur sur votre liste d'amis peuvent voir l'entrée. + +/friends/index.bml.title=Outils pour les amis + +/friends/index.bml.tools=Outils + +/friends/popwithfriends.bml.account_type=Désolé, votre type de compte ne vous permet pas d'utiliser cet outil. + +/friends/popwithfriends.bml.count=Compte + +/friends/popwithfriends.bml.exclude_own=Vous pouvez optionnellement exclure vos amis. + +/friends/popwithfriends.bml.include_own=Vous pouvez optionnellement inclure vos amis. + +/friends/popwithfriends.bml.intro=Les utilisateurs suivants sont souvent listés par vos amis, mais pas par vous. + +/friends/popwithfriends.bml.intro_own=Les utilisateurs suivants sont souvent listés par vos amis. Cette liste contient aussi vos propres amis. + +/friends/popwithfriends.bml.no_users=Pas d'utilisateurs + +/friends/popwithfriends.bml.title=Utilisateurs populaires parmis vos amis + +/friends/popwithfriends.bml.user=Utilisateur + +/go.bml.defaultbody=Aucun paramètre indiqué. + +/go.bml.defaulttitle=Erreur + +/go.bml.error.noentry.next=Il n'y a pas d'entrée après celle-ci. + +/go.bml.error.noentry.prev=Il n'y a pas d'entrée avant celle-ci. + +/go.bml.error.noentrytitle=Aucune entrée + +/go.bml.error.redirkey=Faux redir_key. + +/go.bml.error.usernotfound=Utilisateur introuvable. + +/index.bml.about.header=À propos de LiveJournal + +/index.bml.about.joining=Joidre le site est gratuit. Les utilisateurs peuvent néanmoins choisir d' améliorer leur compte pour avoir plus d'options. + +/index.bml.about.us=LiveJournal est un outil de publication personnelle ("blogging") très simple à utiliser (mais néanmoins très puissant et personnalisable). Il est basé sur un logiciel open source. + +/index.bml.boldcreate=Créez votre propre LiveJournal! + +/index.bml.frank.image.alt=Frank, la chèvre mascotte de LiveJournal. + +/index.bml.frank.logo="Bêhhh", dit Frank. + +/index.bml.learnmore.header=Vous voulez en savoir plus? + +/index.bml.learnmore.text=Veuillez lire notre présentation. Convaincu? Créez votre propre LiveJournal! + +/index.bml.meta.desc=Chez LiveJournal.com, on peut révéler ses pensées au monde. + +/index.bml.meta.keywords=journal intime, journaux, journal en ligne, écriture, journal de web + +/index.bml.news.text=Les dernières nouvelles: + +/index.bml.news.title=Dernières nouvelles + +/index.bml.post=Statistiques en direct + +/index.bml.post.hour=Par heure: + +/index.bml.post.latest=Dernières entrées + +/index.bml.post.min=Par minute: + +/interests.bml.add.added.head=Ajouté! + +/interests.bml.add.added.text=L'intérêt a été ajouté à votre liste + +/interests.bml.add.btn.text=Ajouter [[interest]] + +/interests.bml.add.confirm.head=Confirmez + +/interests.bml.add.confirm.text=Pour ajouter [[interest]] comme un intérêt, cliquez sur le bouton ci-dessous + +/interests.bml.add.toomany.head=Désolé + +/interests.bml.add.toomany.text=Vous avez déjà défini [[maxinterests]] intérêts + +/interests.bml.addint=Si vous êtes aussi intéressé par ceci et que vous souhaitez être ajouté à cette liste, cliquez ici. + +/interests.bml.btn.switch=Changez + +/interests.bml.communities.head=Communautés pertinentes + +/interests.bml.communities.text=Les communautés suivantes sont aussi intéressées par "[[interest]]". + +/interests.bml.count=Compte + +/interests.bml.enmasse.body.other=Ci-dessous se trouvent les intérêts de [[user]]. Cochez les cases à côté des intérêts que vous aimeriez ajouter à votre liste, et décochez celles que vous voudriez enlever de votre liste. Lorsque ce sera fini, cliquez sur "Sauvegarder les changements". + +/interests.bml.enmasse.body.other_authas=Ci-dessous se trouvent les intérêts de [[user]]. Cochez les cases à côté des intérêts que vous aimeriez ajouter à la liste de [[target]], et décochez celles que vous voudriez enlever de votre liste. Lorsque ce sera fini, cliquez sur "Sauvegarder les changements". + +/interests.bml.enmasse.body.you=Décochez les cases près des intérêts que vous aimeriez enlever de votre liste. Lorsque ce sera fini, cliquez sur "Sauvegarder les changements". + +/interests.bml.enmasse.btn=Montrer la liste + +/interests.bml.enmasse.header=Ajouter/enlever des intérêts + +/interests.bml.enmasse.intro=Modifiez vos intérêts selon ceux de : + +/interests.bml.error.add.mustlogin=Vous devez être enregistré pour ajouter un intérêt ainsi + +/interests.bml.error.enmasse.mustlogin=Vous devez être connecté(e) pour utiliser cette fonction. + +/interests.bml.error.enmasse.noaccess=Vous ne semblez pas avoir accès au journal [[user]]. + +/interests.bml.error.findsim_do.intnotfound=L'intérêt n'a pas été trouvé. + +/interests.bml.error.nointerests=L'utilisateur sélectionné n'existe pas ou n'a pas spécifié d'intérêts. + +/interests.bml.findsim.searchwait=Attention: La recherche prendra du temps. Soyez patient. + +/interests.bml.findsim_do.account.notallowed=Désolé, votre type de compte ne vous permet pas d'utiliser cet outil. + +/interests.bml.findsim_do.magic=Index
      Magic + +/interests.bml.findsim_do.magic.head=Index Magique? + +/interests.bml.findsim_do.magic.text=Chaque utilisateur concerné reçoit un index magique calculé, qui est un mélange de deux facteurs: le nombre d'intérêts et des points ajoutés correspondant à des intérêts partagés peu communs. + +/interests.bml.findsim_do.nomatch.head=Aucun résultat + +/interests.bml.findsim_do.nomatch.text=Pas d'utilisateur semblable à [[user]]. + +/interests.bml.findsim_do.notdefined=L'utilisateur [[user]] n'a pas défini d'intérêt. + +/interests.bml.findsim_do.similar.head=Utilisateurs semblables + +/interests.bml.findsim_do.similar.text=Les utilisateurs suivants sont les plus reliés à [[user]] + +/interests.bml.finished.about=Lorsque vous aurez terminé, appuyez sur le bouton "Sauvegarder les changements" ci-dessous : + +/interests.bml.finished.header=Fini? + +/interests.bml.finished.save_button=Sauvegarder les changements + +/interests.bml.interest=Intérêt + +/interests.bml.interested.btn.find=Trouver + +/interests.bml.interested.in=Trouver des personnes et des communautés partageant l'intérêt suivant: + +/interests.bml.interests.findsim=Trouver des utilisateurs avec des intérêts similaires à ceux de : + +/interests.bml.interests.head=Intérêts + +/interests.bml.interests.text=Il y a ici des choses amusantes à faire avec les intérêts. + +/interests.bml.interests.viewpop=Voyez les intérêts populaires + +/interests.bml.login.enterinfo=Entrez votre nom d'utilisateur et votre mot de passe pour modifier vos intérêts. + +/interests.bml.login.proceed=Procédez + +/interests.bml.match=[[count]] résultat + +/interests.bml.matches=[[count]] résultats + +/interests.bml.morestuff=Vous trouverez plus de trucs amusants à la page d'intérêts. + +/interests.bml.nointerests.text=Vous n'avez pas de liste d'intérêts? Ajoutez en à la page Editez vos informations personnelles & réglages + +/interests.bml.popular.disabled=Désolé, les centres d'intérêts populaires ne sont pas disponibles. + +/interests.bml.popular.head=Intérêts populaires + +/interests.bml.popular.text=Les suivants sont les intérêts les plus populaires. + +/interests.bml.results.added=Les intérêts que vous avez sélectionnés ont étés ajoutés à votre liste d'intérêts avec succès. + +/interests.bml.results.both=Les intérêts que vous avez sélectionnés ont étés ajoutés à votre liste d'intérêts avec succès, et ceux que vous avez voulu retirer le furent avec succès. + +/interests.bml.results.deleted=Les intérêts que vous vouliez retirer de votre liste d'intérêts le furent avec succès. + +/interests.bml.results.del_and_toomany=Les intérêts que vous vouliez retirer de votre liste d'intérêts le furent avec succès. Mais vous avez choisi trop d'intérêts à ajouter. Vous ne pouvez avoir que [[intcount]] intérêts en tout. Aucun des intérêts sélectionnés n'ont été ajoutés à votre liste. Vous pouvez retourner à la page précédente et réessayer en ajoutant moins d'intérêts. + +/interests.bml.results.goback=Peut être voulez-vous retourner au profil de [[user]] que vous regardiez précédemment. + +/interests.bml.results.header=Résultats + +/interests.bml.results.message=Voyez votre page de profil mise à jour. + +/interests.bml.results.nothing=Vous n'avez fait aucun changement. + +/interests.bml.results.toomany=Vous avez sélectionné trop d'intérêts à ajouter. Vous ne pouvez avoir que [[intcount]] intérêts en tout. Aucun des intérêts sélectionnés n'a été ajouté à votre liste d'intérêts. Retournez à la page précédente et réessayez, en choisissant moins d'intérêts à ajouter. + +/interests.bml.title=Intérêts + +/interests.bml.toomany.body=Il y a [[intcount]] personnes et/ou communautés qui ont ceci comme intérêt. Il n'y aura pas de liste montrée. + +/interests.bml.toomany.head=Beaucoup de résultats + +/interests.bml.users.head=Utilisateurs intéressés + +/interests.bml.users.text=Les utilisateurs suivants sont aussi intéressés à [[interest]]. + +/invite/index.bml.code=Code + +/invite/index.bml.error=Erreur + +/invite/index.bml.genmore=Générez plus de codes + +/invite/index.bml.how_detail=Dépendamment de certains facteurs, les utilisateurs actuels ont la possibilité d'inviter un certain nombre de nouveaux utilisateurs. Pour inviter quelqu'un, vous devez générer de nouveau codes d'invitation et le leur donner. + +/invite/index.bml.how_header=Comment ça marche ? + +/invite/index.bml.invite_header=Invitations? + +/invite/index.bml.none=Aucune + +/invite/index.bml.redeemed=Utilisé par + +/invite/index.bml.title=Invitez d'autres personnes à LiveJournal... + +/invite/index.bml.unused=Inutilisés + +/invite/index.bml.use=utilisez + +/invite/index.bml.why_codes=Il est maintenant requis d'acheter un compte payant ou d'être invité par un utilisateur existant pour créer un nouveau compte de communauté, en contrôler la croissance et prévenir les abus. Notre motivation pour faire ceci est d'améliorer la communauté pour les gens qui l'utilisent déjà, bien que ce soit un léger inconvénient pour les nouveaux utilisateurs. + +/legal/index.bml.about<< +LiveJournal se voue à offrir une expérience stable et significative aux membres de toutes les origines et de toutes les nations. Nous devons donc avoir quelques règles pour procurer ceci. +Les documents trouvés ici contiennent des termes raisonnables et de l'information sur les manières que nous utiliserons pour vous servir le mieux possible, et sur comment nous nous attendons que les membres agissent envers nous et envers les autres membres. LiveJournal fonctionne mieux lorsque ces règles sont respectées. +En voici quelques-unes importantes à retenir : +
        +
      • N'abusez pas, ni n'agressez, ni ne menacez les autres.
      • +
      • Ne blessez les mineurs en aucune façon.
      • +
      • N'utilisez pas le site ou un compte pour faire de la publicité.
      • +
      • n'utilisez pas de matériel protégé par les droits d'auteurs sans permission.
      • +
      • N'envahisez pas la vie privée des autres.
      • +
      • Ne violez pas les lois des États-Unis, ni celles de votre région.
      • +
      +La liste complète des règles peut être trouvée plus bas : +. + +/legal/index.bml.about.header=Vue d'ensemble + +/legal/index.bml.docs.coppa.about<< +La " Children's Online Privacy Protection Act " (COPPA) filtre les documents et l'utilisation des informations personnelles fournie par et concernant des enfants de moins de treize ans. Notre page sur COPPA explique notre position face à cette loi, et définit comment s'y prendre avec les complications face à COPPA. + +. + +/legal/index.bml.docs.privacy.about<< +La Politique de la Vie Privée définit quelles informations nous amassons de nos membres et explique à quelles fins nous utilisons ces informations. + +. + +/legal/index.bml.docs.tos.about<< +Les Termes du Service définissent nos politiques d'utilisation, ainsi que les termes généraux et les conditions pour être membre. Le fait d'être membre et/ou l'utilisation du système constitue un accord à respecter et se conformer à ces termes, ainsi qu'à tous les autres. + +. + +/legal/index.bml.title=Information Légale + +/legal/privacy.bml.title=Vie Privée + +/legal/tos.bml.title=Conditions du service + +/login.bml.bindip.label=Lié à l'adresse IP: + +/login.bml.bindip.no=Non (fonctionne avec toutes les ISP) + +/login.bml.bindip.yes=Oui (plus sûr) + +/login.bml.error.mustenterusername=Vous devez entrer un nom d'utilisateur + +/login.bml.expire.btn.neverexpire=Changer le mode d'expiration à JAMAIS + +/login.bml.expire.btn.sessiononly=Changer le mode d'expiration à SESSION SEULEMENT + +/login.bml.expire.neverexpire.text=Votre connection ne prendra jamais fin, alors si vous êtes sur un ordinateur public, où d'autres utilisateurs pourraient utiliser cet ordinateur bientôt, soyez certain de vous déconnecter lorsque vous aurez fini! Ou changez votre mode de connection pour qu'elle expire aussitôt que vous fermer votre explorateur: + +/login.bml.expire.sessiononly.text=Votre connexion expirera quand vous fermerez votre explorateur. Si vous êtes le seul à utiliser votre propre ordinateur, vous pouvez changer votre connexion pour qu'elle ne se périme pas. + +/login.bml.links.head=Liens + +/login.bml.links.link1=Votre page d'amis. + +/login.bml.links.link2=Votre liste des choses à faire. + +/login.bml.links.text=Plus tard cette page contiendra toutes sortes de liens et d'informations pertinentes, mais pour le moment voici les quelques endroits où vous pouvez aller: + +/login.bml.loggedin.head=Connecté! + +/login.bml.loggedin.text=Vous êtes à présent connecté. + +/login.bml.login.btn.changeopts=Modifier + +/login.bml.login.btn.login=Connectez vous... + +/login.bml.login.forget=Oublié? + +/login.bml.login.head=Connectez-vous + +/login.bml.login.never=Jamais + +/login.bml.login.otheropts=Autres options: + +/login.bml.login.password=Mot de passe: + +/login.bml.login.text1=Pour vous connecter à [[sitename]], entrez votre nom d'utilisateur et votre mot de passe ci-dessous. Nouvel utilisateur : Pour créer un compte, c'est ici. + +/login.bml.login.text2<< +Vous devez spécifier quand votre connexion expire. Par défaut elle expire lorsque vous fermez votre explorateur, ce qui est le mieux pour des ordinateurs publics. Cependant si vous êtes l'unique utilistateur de votre ordinateur et que personne d'autre n'y a accès, vous pouvez choisir d'être connecté en permanence. Pour plus d'informations et d'autres options, voyez Quelles sont les options lorsque je me connecte? + +. + +/login.bml.login.text3=[[username]], vous êtes maintenant connecté à [[sitename]]. Vous pouvez naviguer sur le site en utilisant notre plan du site. + +/login.bml.login.username=Nom d'utilisateur: + +/login.bml.login.whenbrowsercloses=Quand l'explorateur se ferme + +/login.bml.logout.btn=Déconnectez-vous + +/login.bml.title=Connectez-vous + +/login.bml.whylogin.benefit1=Vous n'aurez plus besoin d'entrer votre nom d'utilisateur/mot de passe nulle part sur le site. + +/login.bml.whylogin.benefit2=Vous serez capable de voir les entrées "protégées" de vos amis qui vous en donneront la permission. + +/login.bml.whylogin.benefit3=Un tas de choses ne sont visibles ou accessibles que si vous êtes connecté. + +/login.bml.whylogin.head=Pourquoi se connecter? + +/login.bml.whylogin.text=Voici les principaux avantages d'être connecté: + +/logout.bml.already.head=Déjà déconnecté + +/logout.bml.already.text=Vous êtes déjà déconnecté. + +/logout.bml.killall.btn=Terminer toutes mes sessions + +/logout.bml.killall.head=Autres sessions + +/logout.bml.killall.text=Vous avez d'autres sessions actives. Voulez-vous fermer toutes vos sessions plutôt que juste celle-ci ? (Veuillez voir cette question de la FAQ pour plus d'informations.) + +/logout.bml.loggedout.already=Déjà déconnecté. + +/logout.bml.loggedout.head=Déconnecté + +/logout.bml.loggedout.killedall=Toutes vos sessions sont terminées + +/logout.bml.loggedout.success=Déconnecté + +/logout.bml.loggedout.text=Vous êtes maintenant déconnecté. + +/logout.bml.logout.btn=Déconnectez-vous + +/logout.bml.logout.head=Voulez-vous vous déconnecter? + +/logout.bml.logout.text=Cliquer sur le bouton ci-dessous pour vous déconnecter. + +/logout.bml.title=Sortie + +/lostinfo.bml.btn.proceed=Allez-y + +/lostinfo.bml.enter_email=Entrez votre adresse de courriel: + +/lostinfo.bml.enter_email_optional=Adresse de courriel: (facultatif) + +/lostinfo.bml.enter_username=Entrez votre nom d'utilisateur: + +/lostinfo.bml.error.no_email=Vous devez entrez une adresse courriel afin de récupérer votre nom d'utilisateur. + +/lostinfo.bml.error.purged=Nous ne pouvons récupérer le mot de passe d'un compte lorsqu'il a été effacé. + +/lostinfo.bml.error.renamed=Nous ne pouvons récupérer le mot de passe d'un compte qui à été renommé. + +/lostinfo.bml.error.syndicated=Le compte duquel vous essayez de récupérer le mot de passe est un compte syndiqué. Ce type de compte n'a pas de mot de passe. + +/lostinfo.bml.error.sysbanned=Votre compte ne permet pas d'envoyer les mot de passe par courriel. + +/lostinfo.bml.lostpassword.text=Si vous avez perdu votre mot de passe, entrez votre nom d'utilisateur et optionnellement l'adresse de courriel où vous voudriez recevoir votre mot de passe. Afin de recevoir votre mot de passe à votre courriel, celui-ci doit avoir été confirmée. Si vous laissez le champ d'adress vide, il sera envoyé à votre adresse actuelle. + +/lostinfo.bml.lostpassword.title=Avez-vous perdu votre mot de passe? + +/lostinfo.bml.lostusername.text=Si vous avez perdu votre nom d'utilisateur, entrez votre adresse de courriel et nous vous enverrons votre nom d'utilisateur. + +/lostinfo.bml.lostusername.title=Avez-vous perdu votre nom d'utilistateur? + +/lostinfo.bml.title=Information perdue + +/lostinfo_do.bml.error.no_usernames_for_email=Pas de nom(s) d'utilistateur pour cette adresse courriel: [[address]] + +/lostinfo_do.bml.error1.text=Vous n'avez jamais utiilisé cette adresse courriel avec ce compte ou elle n'a jamais été validée. + +/lostinfo_do.bml.lostpasswordmail.part1<< +***Ceci est une réponse automatique. Vous n'avez pas besoin d'y répondre. *** + +Voici le rappel de mot de passe que vous avez demandé de [[sitename]]. +Ci-dessous se trouve votre nom d'utilisateur, votre mot de passe, et le courriel auquel est enregistré votre journal. + +Nom d'utilisateur : [[username]] +Mot de passe : [[password]] +Courriel : [[emailadr]] + +. + +/lostinfo_do.bml.lostpasswordmail.part2=Pour valider votre courriel, allez ici : + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ces informations ont étés demandées sur le site Internet de [[remoteip]]. + +Si vous n'avez pas demandé de recevoir votre mot de passe, ne paniquez pas. Après tout, vous êtes la seule personne qui peut recevoir ce courriel. Il est possible que la personne qui a fait la demande ce soit trompée et croit qu'il ou elle contrôle ce nom d'utilisateur. Il est aussi possible que quelqu'un ait fait une erreur en entrant le nom d'utilisateur ou le courriel. + +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Si vous croyez vraiment que votre compte n'est pas sécure, lisez + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +pour plus d'informations sur comment le rendre plus sécure. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Liens utiles : + +Votre LiveJournal : +[[journalurl]] + +Mettez à jour votre journal en ligne : +[[updateurl]] + +Nos estimes, +L'Équipe de LiveJournal + +[[rooturl]] + +. + +/lostinfo_do.bml.lostpasswordmail.subject=Mot de passe perdu + +/lostinfo_do.bml.password_mailed.text=Réussi. Votre mot de passe a été envoyé. + +/lostinfo_do.bml.password_mailed.title=Mot de passe envoyé! + +/lostinfo_do.bml.title=Information perdue + +/lostinfo_do.bml.username_mailed.text=Réussi. Votre nom d'utlisateur a été envoyé. + +/lostinfo_do.bml.username_mailed.title=Nom d'utilisateur envoyé! + +/manage/index.bml.about=S'occuper des réglages d'un compte est facile. Vous n'avez qu'à choisir une des sections ci-dessous: + +/manage/index.bml.communities=Créez et gérez vos propres communautés: + +/manage/index.bml.communities.create.about=Créez une nouvelle communauté + +/manage/index.bml.communities.header=Communautés + +/manage/index.bml.communities.manage.about=Gérez les options de votre communauté et ses membres + +/manage/index.bml.customization=Personnalisez l'apparence de votre journal: + +/manage/index.bml.customization.advanced=Personnalisation avancée + +/manage/index.bml.customization.advanced.about=Regardez, créez et choississez vos dispositions et vos styles S2 + +/manage/index.bml.customization.customize=Personnalisez votre journal + +/manage/index.bml.customization.customize.about=Changez l'apparence de votre journal et alternez entre les systèmes de style S1 et S2 + +/manage/index.bml.customization.header=Personnalisation + +/manage/index.bml.customization.links=Liste de liens + +/manage/index.bml.customization.links.about=Créez une liste de liens qui apparaîtra dans votre journal + +/manage/index.bml.customization.modify.about=Modifiez les options d'affichage de votre journal + +/manage/index.bml.customization.s1.header=Système de style S1 + +/manage/index.bml.customization.s2.header=Système de style S2 + +/manage/index.bml.entries=Travaillez avec des entrées que vous avez faites dans votre journal: + +/manage/index.bml.entries.edit.about=Éditez et effacez des entrées de votre journal + +/manage/index.bml.entries.header=Entrées journalières + +/manage/index.bml.entries.memories.about=Visionnez et travaillez avec vos entrées mémorables + +/manage/index.bml.friends=Gérez vos amis et vos groupes d'amis, ou filtrez votre page d'amis selon vos groupes d'amis sauvegardés: + +/manage/index.bml.friends.edit.about=Ajoutez ou retirez des utilisateurs de votre liste d'amis, ou changez les couleurs choisies pour les représenter + +/manage/index.bml.friends.filter=Filtrez votre page d'amis + +/manage/index.bml.friends.filter.about=Filtrez votre liste d'amis afin d'afficher un groupe d'amis bien spécifique + +/manage/index.bml.friends.groups.about=Créez, éditez ou effacez des sous-groupes de votre liste d'amis + +/manage/index.bml.friends.header=Amis + +/manage/index.bml.information=Choisissez quelles informations sont affichées sur votre compte: + +/manage/index.bml.information.changepass=Changer le mot de passe du compte + +/manage/index.bml.information.changepass.about=Changer le mot de passe de votre compte + +/manage/index.bml.information.editinfo.about=Éditez les informations de votre compte et d'autres options + +/manage/index.bml.information.emailpost=Réglages du portail courriel + +/manage/index.bml.information.emailpost.about=Gérez vos adresses courriel et votre code confidentiel pour supporter l'affichage par courriel + +/manage/index.bml.information.header=Informations de compte + +/manage/index.bml.information.siteopts.about=Sélectionnez votre mise en page et votre langue préférée + +/manage/index.bml.information.status=État du compte + +/manage/index.bml.information.status.about=Choisissez l'état d'activation de votre compte (effacez ou rétablissez votre compte) + +/manage/index.bml.login=Les liens ci-dessous vous conduiront vers des pages où vos informations d'enregistrement sont nécessaires. Pour économiser du temps, vous pouvez vous enregistrer à l'avance. + +/manage/index.bml.title=Gérez les comptes + +/manage/index.bml.userpictures=Téléchargez et gérez les icônes de votre compte: + +/manage/index.bml.userpictures.edit.about=Téléchargez et gérez vos icônes + +/manage/index.bml.userpictures.header=Icônes + +/manage/links.bml.about=Utilisez le formulaire ci-dessous pour créer une liste de liens qui apparaîtra sur votre journal. Les liens apparaîtront seulement si cette option est supportée par votre style S2. + +/manage/links.bml.about.blank=Afin de créer une ligne vide, tapez un "-" comme titre. + +/manage/links.bml.about.heading=Pour créer une entête, tapez un titre sans URL (adresse web). + +/manage/links.bml.about.reorder=Pour réorganiser les liens dans la liste, modifiez le numéro d'ordre à gauche (nombres décimaux acceptés). + +/manage/links.bml.error.s2required=La liste de liens est disponible seulement pour les styles S2 supportés. Afin de changer pour S2, voyez la page [[link]]. + +/manage/links.bml.error.s2required.header=S2 requis + +/manage/links.bml.success=Réussi ! Vos liens ont été enregistrés. + +/manage/links.bml.title=Liste de liens + +/manage/phonepost.bml.delete=Effacer les réglages + +/manage/phonepost.bml.deleted=Vos données téléphoniques ont été effacées. + +/manage/phonepost.bml.deleted.header=Effacé + +/manage/phonepost.bml.error.inuse=Code confidentiel invalide, essayez-en un autre SVP + +/manage/phonepost.bml.error.phone.length=Votre numéro de téléphone doit être d'au moins 10 chiffres. + +/manage/phonepost.bml.error.pin=Votre NIP doit être numérique. + +/manage/phonepost.bml.error.transcription=Groupe d'amis invalide pour la transcription + +/manage/phonepost.bml.intro.loggedin<< +entrées par téléphone, entrez votre numéro de téléphone ainsi que votre NIP ci-dessous. p?> +politique de la vie privée pour plus d'information). +Les appels venant de numéros de téléphone autres que ceux que vous autorisez seront acceptés, mais vous devrez entrer votre numéro de téléphone pré autorisé avant de pouvoir enregistrer votre entrée. p?> + +. + +/manage/phonepost.bml.intro.loggedout=Les membres de peuvent se connecter et changer leur paramètres pour faire des entrées par téléphone ici: + +/manage/phonepost.bml.phone=Numéro de téléphone autorisé: + +/manage/phonepost.bml.pin=Numéro d'identification personnel: + +/manage/phonepost.bml.pin.help=Il est recommandé d'utiliser 4 à 6 chiffres + +/manage/phonepost.bml.save=Sauvegarder les paramètres + +/manage/phonepost.bml.saved=Sauvegardé + +/manage/phonepost.bml.transcribers=Transcripteurs permis: + +/modify.bml.title=Modifiez votre journal + +/modify_do.bml.availablestyles.head=Styles disponibles + +/modify_do.bml.availablestyles.userstyles=Styles + +/modify_do.bml.colortheme.about=Vous pouvez sélectionner ici le thème de couleur qui sera appliqué à l'ensemble d'options que vous avez choisi ci-dessus. Ou si vous n'aimez pas les couleurs proposées, déterminez la vôtre! + +/modify_do.bml.colortheme.area.head=Espace d'utilisation + +/modify_do.bml.colortheme.color.head1=Couleur + +/modify_do.bml.colortheme.color.head2=(#rrggbb ou le nom) + +/modify_do.bml.colortheme.customcolors=Couleurs personnalisées + +/modify_do.bml.colortheme.defaulttheme=Thème par défaut + +/modify_do.bml.colortheme.head=Thème de couleur + +/modify_do.bml.domainalias.about=Si vous avez un nom de domaine déjà enregistré (ou que vous envisagez d'enregister) et que vous aimiriez qu'il démarre automatiquement votr LiveJournal, entrez le ici: + +/modify_do.bml.domainalias.domainname=Nom de domaine: + +/modify_do.bml.domainalias.example=Exemple: mon-journal.com + +/modify_do.bml.domainalias.head=Pseudo en cours du domaine + +/modify_do.bml.domainalias.helptext=Pour que ça marche, arrangez vous pour que votre DNS de nom de domaine pointe la même adresse IP que [[sitename]]. Pour plus d'informations, voyez cette FAQ. + +/modify_do.bml.done.btn.savechanges=Sauvegarder les changements + +/modify_do.bml.done.head=Fini? + +/modify_do.bml.done.text=Lorsque vous avez fini, cliquez sur le bouton "Sauvegarder les changements" ci-dessous... + +/modify_do.bml.error.dupdomainalias=Un autre utilisateur a déjà enregistré le pseudo de domaine que vous avez choisi. + +/modify_do.bml.error.stylenotavailable=Un des styles que vous avez choisi n'est pas disponible. Soit quelqu'un l'a effacé, ou vous essayez d'en choisir un auquel vous n'avez pas accès. + +/modify_do.bml.friends.about=Vous trouverez ici les options qui contrôlent l'apparence de votre page d'amis. + +/modify_do.bml.friends.head=Voyez vos amis + +/modify_do.bml.friends.opt.usesharedpic.about=Cette option contôle quelle image vous voyez sur votre page d'amis lorsqu'un utilisateur écrit dans un journal partagé ou une communauté. Si vous la cochez, vous verez l'icône de la communauté. Si vous ne la cochez pas, vous verez l'icône personnelle de la personne qui écrit. + +/modify_do.bml.friends.opt.usesharedpic.head=Utiliser les icônes des journaux partagés ou des communautés au lieu de celles des utilisateurs. + +/modify_do.bml.journaloptions.about=D'ici vous pouvez personnaliser l'apparence de vos pages LiveJournal. Si vous voulez savoir comment ça marche, lisez les informations pour les developpeurs. Autrement nous présumerons que vous êtes satisfait des options de base ci-dessous. + +/modify_do.bml.journaloptions.head=Options de votre journal + +/modify_do.bml.journalstatus.about=Si vous voulez désactiver ou réactiver votre journal, c'est ici qu'il faut le faire. Une fois que vous l'aurez désactivé, vous aurez 30 jours pour le réactiver si vous changez d'idée. Après 30 jours, le journal sera effacé de façon permanente et il n'y aura aucun moyen de le retrouver. + +/modify_do.bml.journalstatus.head=Statut de l'activation du journal + +/modify_do.bml.journalstatus.select.activated=Activé + +/modify_do.bml.journalstatus.select.deleted=Effacé + +/modify_do.bml.journalstatus.select.head=Statut : + +/modify_do.bml.journalstatus.select.suspended=Suspendu + +/modify_do.bml.moodicons.about=Quand vous postez des entrées, vous pouvez aussi préciser votre humeur actuelle. Des utilisateurs ont soumis différents ensembles d'icônes que vous pouvez utiliser. Ou bien sélectionnez *aucun* si vous ne voulez pas d'image à côté de votre humeur. (ou bien n'utilisez pas la commande Humeur Actuelle).). + +/modify_do.bml.moodicons.head=Icônes d'humeur + +/modify_do.bml.moodicons.opt.forcefriends.about=Toujours utiliser ce thème pour les entrées de votrte page d'amis. + +/modify_do.bml.moodicons.personal=Thèmes personnels: + +/modify_do.bml.moodicons.preview=Aperçu + +/modify_do.bml.moodicons.select=Choisir un ensemble d'icônes d'humeur : + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Vous pouvez ignorer cette partie. Elle sert à établir des éléments spécifiques à propos de votre mise en page. Voyez la section des développeurs pour plus de détails.Notez aussi que les réécritures ne servent qu'à réécrire un ou deux éléments d'un style. Si vous préférez tout réécrire, vous devez créer votre propre style. + +/modify_do.bml.overrides.box.head=Réécritures: + +/modify_do.bml.overrides.head=Réécritures de style + +/modify_do.bml.overrides.note=Notez, s'il vous plaît qu'on ne peut réécrire toutes les variables de style. Voyez la documentation pour plus de détails. Soyez aussi conscient que si vous essayez d'éditer en utilisant une expression non autorisée en tête du document,comme <DIV>, <SPAN>, <IMG>, cette expression sera omise. Les seuls éléments HTML qui peuvent être utilisés en tête de réécriture sont ceux acceptés dans une en-tête de document HTML. Ils sont limités à: <title>, <base>, <style>, <link>, et <meta>,. + +/modify_do.bml.overrides.warning=CECI N'EST PAS L'ENDROIT OÙ VOUS ÉCRIVEZ VOTRE JOURNAL!! + +/modify_do.bml.pagelayoutstyle.about=Ce réglage contrôle la façon dont votre journal est disposé à l"écran. + +/modify_do.bml.pagelayoutstyle.head=Style de mise en page + +/modify_do.bml.pagelayoutstyle.warning=Votre style de compte ne vous permet de sélectionner qu'un petit nombre de styles par défaut. + +/modify_do.bml.success.head=Réussi + +/modify_do.bml.success.text=Les réglages de votre journal ont été mis à jour. Vous pouvez voir votre journal ici. + +/paidaccounts/index.bml.costs.header=Bon, combien ça coûte? + +/paidaccounts/index.bml.costs.rates=Les tarifs sont les suivants: + +/paidaccounts/index.bml.costs.rates.amount.header=Montant + +/paidaccounts/index.bml.costs.rates.inexpensive<< +Ca fait un peu plus de 2$/mois pour le plan annuel. +C'est pas la ruine. +Le plus ennuyeux c'est que vous devrez trouver votre portefeuille pour en sortir votre carte de crédit, et écrire vos informations. + +. + +/paidaccounts/index.bml.costs.rates.time.header=Heure + +/paidaccounts/index.bml.features.header=Alors, quelles fonctions cool est-ce que j'aurai? + +/paidaccounts/index.bml.title=À propos des comptes payants + +/paidaccounts/index.bml.whypay.argument<< +Bien sûr que non. Payer pour des services sur l'internet est agaçant, nous sommes d'accord. +C'est pourquoi presque toutes les fonctions sur LiveJournal sont accessibles sans frais. +Mais, si vous aimez le service que vous recevez, montrez votre soutien et procurez-vous un compte payant. +. + +/paidaccounts/index.bml.whypay.header=Je dois payer pour utiliser LiveJournal ? + +/paidaccounts/index.bml.whypay.no_ads=Ça prend de l'argent pour faire fonctionner un site web (pour les serveurs, la bande passante, etc), et nous trouvons que c'est mieux de vous donner l'option de payer que de vous bombarder de publicités. + +/paidaccounts/index.bml.your_username=nom_d'utilisateur + +/paidaccounts/usepaypal.bml.delivery.badformat=Format de la date de livraison incorrecte. Elle doit être comme suit : aaaa-mm-jj ou aaaa-mm-jj hh :mm. + +/paidaccounts/usepaypal.bml.delivery.past=La date de livraison ne peut être dans le passé. Pour envoyer immédiatement, laissez l'espace pour la date de livraison vide. + +/paidaccounts/usepaypal.bml.delivery.toofuture=La date de livraison ne peut être dans plus qu'un mois. + +/pay/index.bml.deliverydate.details=Format: aaaa-mm-jj hh:mm (heure GMT)
      (laissez vide pour livraison instantanée) + +/pay/index.bml.deliverydate.label=Date de livraison : + +/pay/index.bml.gift.anonymous=Cadeau anonyme + +/press/staff.bml.administration.about=LiveJournal à fait ses débuts en 1999 en tant que projet de Brad Fitzpatrick. Durant les deux premières années, le projet était entretenu par une équipe de volontaires importante et loyale. Bien que la majorité des tâches sur LiveJournal.com soit encore sous la tutelle de volontaires, nous avons maintenant un petit groupe d'initiés qui supervisent les opérations. + +/press/staff.bml.avva.title=Développeur en chef + +/press/staff.bml.back2=Retournez à la page de la presse + +/press/staff.bml.bradfitz.quip=Concentrez-vous sur votre produit, et non sur l'entrée d'argent. + +/press/staff.bml.bradfitz.title=Président / Développeur principal + +/press/staff.bml.contact=Si vous devez entrer en contact avec un de nous, veuillez envoyer un courriel à webmaster@livejournal.com. + +/press/staff.bml.denisep.quip=J'aurais ça pour vous jeudi prochain + +/press/staff.bml.denisep.title=Volontaire des relations / Spécialiste de l'utilisation + +/press/staff.bml.jproulx.quip=Geek des liaisons d'utilisateur + +/press/staff.bml.jproulx.title=Superviseur du site / Relations publiques + +/press/staff.bml.lisa.title=Administrateur du service + +/press/staff.bml.ryanfitz.title=Service des paiements + +/press/staff.bml.sandy.title=Comptabilité et Administration + +/press/staff.bml.title=Cadres Supérieurs + +/press/staff.bml.whitaker.quip=Quoi d'autre? + +/press/staff.bml.whitaker.title|staleness=1 +/press/staff.bml.whitaker.title=L'interne + +/rename/use.bml.error.username=Nom d'utilisateur non valide. + +/rename/use.bml.error.usernametaken=Ce nom d'utilisateur est déjà pris. + +/rename/use.bml.heading.changes=Changements + +/rename/use.bml.heading.success=Réussi + +/rename/use.bml.heading.sure=Êtes-vous sûr? + +/rename/use.bml.label.desired=Nom d'utilisateur souhaité: + +/rename/use.bml.label.proceed=En cours... + +/rename/use.bml.label.rename=Renommez + +/rename/use.bml.label.username=Nom d'utilisateur actuel : + +/rename/use.bml.options.delfriends=Enlevez tous les utilisateurs de votre page d'amis et quittez toutes les communautés. + +/rename/use.bml.options.forward=Transférer automatiquement tous les utilisateurs de [[oldname]] au nouveau nom d'utilisateur. + +/rename/use.bml.options.keepfriends=Conserver tous les utilisateurs et les communautés sur votre liste d'amis. + +/rename/use.bml.success.login=Vous devez maintenant vous reconnecter. + +/rename/use.bml.success.renamed="[[olduser]]" a été renommé "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Nom d'utilisateur changé. + +/site/contract.bml.promise=Nous tenons ferme à: + +/site/contract.bml.promise.account=Honorer le statut de chaque compte + +/site/contract.bml.promise.account.about=Les comptes permanents seront honorés aussi longtemps que le site existera. Les comptes payants le resteront jusqu'à leur échéance, à moins d'être renouvelés avant cette date. Les comptes précurseurs auront accès aux options qui étaient gratuites au tout début du site lorsqu'ils ont créé leur journaux. (Le statut des comptes demeurent valide à moins d'une violation des termes des Conditions du Service.) + +/site/contract.bml.promise.ads=Rester un site sans publicité + +/site/contract.bml.promise.ads.about=C'est peut être parce que c'est quelque chose qui nous agace beaucoup, ou peut être est-ce parce qu'ils n'en valent pas la peine, mais nous promettons de ne jamais offir de place pour de la publicité dans notre service ou sur nos pages. + +/site/contract.bml.promise.community=Travailler avec la communauté, pour la communauté + +/site/contract.bml.promise.community.about<< +Nous promettons de vous garder informés de tous les changements au mieux de nos capacités sans être envahissants. Nous promettons de nous occuper de notre entreprise en fonction des demandes des membres, et avec +le plus grand souci de leurs intérêts. +. + +/site/contract.bml.promise.opensource=Supporter le mouvement de logiciels gratuit + +/site/contract.bml.promise.opensource.about<< +Tout le code qui est utilisé pour faire marcher le système complet de LiveJournal, tout en laissant place à la personnalisation est disponible au public. Nous promettons de garder cette source gratuite et accessible, ainsi nous +pourrons donner quelque chose en retour à la communauté des +logiciels gratuits. +. + +/site/contract.bml.promise.spam=Ne jamais vous envoyer de courriel non sollicité. + +/site/goat.bml.image.alt=Frank, la mascotte chèvre de LiveJournal. + +/site/goat.bml.image.caption=Bèèèèè dit Frank. + +/site/goat.bml.meet.body=Voici Frank. Frank est la mascotte de LiveJournal. Il nous aide avec de la programmation diverse lorsque nous prenons du retard, et parfois il répond même à des requêtes au support technique. Frank est très polyvalent.... il fait même les tâches jardinières parfois. Quand le gazon devient trop haut nous lui disons: "Hey Frank! C'est l'heure du dîner... va manger le gazon!" C'est une situation où tout le monde est gagnant. + +/site/goat.bml.meet.header=Voici Frank + +/site/goat.bml.title=Frank la chèvre + +/suggestions/index.bml.howto.title=Comment faire une suggestion ? + +/suggestions/index.bml.info.title=D'autres informations + +/suggestions/index.bml.title=Section des suggestions + +/suggestions/index.bml.welcome.text=Les suggestions des utilisateurs sont une partie importante de LiveJournal. S'il vous trouvez une bonne idée, vous pouvez suivre ces instructions pour attirer l'attention de ceux qui dirigent ce site. + +/suggestions/index.bml.welcome.title=Bienvenue ! + +/support/encodings.bml.edit.header=Je suis incapable d'éditer mes entrées sur le web! + +/support/encodings.bml.edit.text<< +Réponse courte:(Seulement si vous écrivez votre journal en Anglais): Aller à la page d'édition de vos informations personnelles. Au bas de la page vous trouverez l'option Traduire automatiquement les anciennes entrées à partir de: . Choisissez "Western European (Windows)" dans le menu et sauvegardez les changements. Vos entrées devraient maintenant être éditable. p?> + +Réponse longue: Pour pouvoir éditer une entrée qui n'est pas en mode Unicode, LiveJournal a besoin de savoir quelle sorte de codage à été utilisé pour l'entrée. Pour les utilisateurs de l'anglais et des autres langues européennes de l'est, c'est généralement "Western European (Windows)", même si ça ne marche pas bien pour certains caractères, "Western European (ISO)" est le plus approprié. Les utilisateurs écrivant dans d'autres langues devraient choisir le type de codage approprié; s'il n'est pas dans la liste fournie, contactez notre support technique et expliquez-nous le problème. p?> + + +. + +/support/encodings.bml.editcl.header=Je suis incapable d'éditez mes entrées dans le client! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Je suis incapable d'éditez ma liste d'amis avec le client! + +/support/encodings.bml.groups.text=page d'édition des groupes d'amis et par la suite utiliser votre client. p?> + +/support/encodings.bml.overview.header=Qu'est-ce que c'est? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Toujours coincé? + +/support/encodings.bml.still.text=. p?> + +/support/encodings.bml.title=Codage + +/support/faqbrowse.bml.backfaq=Retournez à la FAQ. + +/support/faqbrowse.bml.backsupport=Retournez au support technique. + +/support/faqbrowse.bml.error.nofaq=La FAQ demandée n'existe pas. + +/support/faqbrowse.bml.lastupdated=Dernière mise à jour: + +/support/faqbrowse.bml.title_num=Question FAQ #[[num]] + +/support/see_overrides.bml.error.noprivs=Seuls les utilisateurs ayant le privilège "supportviewscreened" ou "supporthelp" peuvent voir les réécritures d'autres utilisateurs. + +/support/see_overrides.bml.error.nos1=Cet utilisateur n'utilise pas S1. + +/support/see_overrides.bml.header=Réécritures de  : + +/support/see_overrides.bml.nooverrides=Aucunes réécritures trouvés pour . + +/support/see_overrides.bml.title=Réécritures d'utilisateur + +/talkmulti.bml.deleted.body=Les commentaires ont étés effacés. Vous pouvez voir le fil restant ici. + +/talkmulti.bml.deleted.title=Commentaires effacés + +/talkmulti.bml.error.comms_deleted=Un des commentaires a été effacé pendant ce temps. Pour des raisons de sécurité, veuillez retourner à la page précedente et réessayer. + +/talkmulti.bml.error.inconsistent_data=Les données fournies sont inconsistantes. + +/talkmulti.bml.error.invalid=Les paramètres specifiés ne sont pas valides. + +/talkmulti.bml.error.invalid_mode=Vous n'avez choisi aucune action. Veuillez retourner et choisir si vous voulez filtrer, rendre public ou effacer les commentaires sélectionnés. + +/talkmulti.bml.error.login=Vous n'êtes pas connecté. + +/talkmulti.bml.error.none_selected=Vous n'avez choisi aucun commentaire. + +/talkmulti.bml.error.privs.delete=Vous n'avez pas la permission d'effacer ces commentaires. + +/talkmulti.bml.error.privs.screen=Vous n'avez pas la permission de filtrer ces commentaires. + +/talkmulti.bml.error.privs.unscreen=Vous n'avez pas la permission de rendre public ces commentaires. + +/talkmulti.bml.screened.body=Les commentaires ont été filtrés. Vous pouvez les voir ici. + +/talkmulti.bml.screened.title=Commentaires filtrés + +/talkmulti.bml.title.delete=Effacez plusieurs commentaires + +/talkmulti.bml.title.screen=Filtrez plusieurs commentaires + +/talkmulti.bml.title.unscreen=Rendez public plusieurs commentaires + +/talkmulti.bml.unscreened.body=Les commentaires ont été rendus publics. Vous pouvez les voir ici. + +/talkmulti.bml.unscreened.title=Commentaires rendus publics + +/talkpost.bml.allowedhtml=HTML permis + +/talkpost.bml.error.cannotreplynopost=Vous ne pouvez pas faire de commentaires à une entrée inexistante + +/talkpost.bml.error.nocommentsjournal= L'utilisateur a désactivé les commentaires dans son journal + +/talkpost.bml.error.nocommentspost=L'utilisateur a désactivé les commentaires pour cette entrée + +/talkpost.bml.error.noreplypost=L'entrée à laquelle vous avez fait un commentaire n'a pas été trouvée (effacée?) + +/talkpost.bml.error.noreply_deleted=Ce commentaire a été effacé. Vous ne pouvez y faire une réponse. + +/talkpost.bml.error.noreply_screened=Ce commentaire est filtré et vous n'avez pas la permission de le voir ou d'y faire des commentaires. + +/talkpost.bml.label.picturetouse=Icône à utiliser : + +/talkpost.bml.loganonip=Notez! Cet utilisateur a activé l'option qui prends en note l'adresse IP des commentaires anonymes. + +/talkpost.bml.loginq=Connectez-vous? + +/talkpost.bml.logyourip=Notez! Cet utilisateur a activé l'option qui prend en note votre adresse IP lorsque vous faites des commentaires. + +/talkpost.bml.nosubjecthtml=Le HTML n'est pas permis dans le sujet. + +/talkpost.bml.opt.anonymous=Anonyme + +/talkpost.bml.opt.defpic=(par défault) + +/talkpost.bml.opt.friendsonly=- Cet utilisateur interdit les commentaires anonymes et ceux des utilisateurs qu'il n'a pas inclus dans sa liste d'amis. Vous pouvez écrire ici si [[username]] vous a inclus dans sa liste d'amis. + +/talkpost.bml.opt.from=De: + +/talkpost.bml.opt.ljuser=Utilisateur de LiveJournal + +/talkpost.bml.opt.loggedin=Utilisateur connecté: [[username]] + +/talkpost.bml.opt.noanonpost=- Cet utilisateur interdit les commentaires anonymes + +/talkpost.bml.opt.noautoformat=Ne pas mettre en forme automatiquement : + +/talkpost.bml.opt.noimage=Pas d'image + +/talkpost.bml.opt.preview=Aperçu + +/talkpost.bml.opt.spellcheck=Vérifier l'orthographe avant d'afficher l'entrée. + +/talkpost.bml.opt.subject=Sujet: + +/talkpost.bml.opt.submit=Envoyer un commentaire + +/talkpost.bml.opt.willscreen=(sera filtré) + +/talkpost.bml.opt.willscreenfriend=(sera filtré si vous n'êtes pas un ami) + +/talkpost.bml.paraformat=Les paragraphes seront automatiquement mis en forme. + +/talkpost.bml.postresponse=Envoyer un commentaire pour répondre: + +/talkpost.bml.title=Faire un commentaire + +/talkpost.bml.usermismatch<< +Vous avez entré un nom d'utilisateur, mais vous avez désélectionné l'option d'"utilisateur de LiveJournal". + +Veuillez soit vider la boîte du nom d'utilisateur, soit sélectionner le bon mode pour faire une entrée et essayer de nouveau. +. + +/talkpost.bml.warnscreened=Notez! Ce commentaire est filtré. Y répondre enlèvera cette option et le rendra visible à tous. + +/talkpost_do.bml.error.badpassword=Mot de passe erroné pour le nom d'utilisateur spécifié. Vous pouvez récupérer votre mot de passe ici si vous l'avez oublié. + +/talkpost_do.bml.error.badusername=Le nom d'utilisateur LiveJournal que vous avez spécifié n'existe pas. Vous pouvez récupérer votre nom d'utilisateur ici si vous l'avez oublié, ou vous pouvez répondre comme " anonyme ". + +/talkpost_do.bml.error.banned=Vous n'êtes pas autorisé à répondre dans ce journal. + +/talkpost_do.bml.error.blankmessage=Vous n'avez rien écrit. S'il vous plaît, tapez au moins quelque chose dans la zone de message. + +/talkpost_do.bml.error.confused_identity=Vous avez entré un nom d'utilisateur, mais avez choisi de faire soit un commentaire anonyme, soit un commentaire avec le nom d'utilisateur déjà connecté. Veuillez retourner et décider ce que vous voulez vraiment faire. + +/talkpost_do.bml.error.deleted=Votre journal à été détruit. Vous ne pouvez pas y faire d'entrées. + +/talkpost_do.bml.error.friendsonly=Seulement les amis de [[user]] peuvent faire des entrées dans ce journal. + +/talkpost_do.bml.error.lostcookie= Votre cookie de connection semble avoir disparu? + +/talkpost_do.bml.error.manybytes=Désolé, votre commentaire de [[current]] dépasse le maximum de bytes alloué de [[limit]]. Veuillez retourner, raccourcir votre commentaire, et essayer de nouveau. + +/talkpost_do.bml.error.manychars=Désolé, votre commentaire de [[current]] caractères dépassela longueur maximum de [[limit]]. Veuillez retourner, raccourcir votre commentaire, et essayer de nouveau. + +/talkpost_do.bml.error.mustlogin=Vous devez soit être connecté, soit utiliser un nom d'utilisateur et un mot de passe pour répondre à cette entrée protégée. + +/talkpost_do.bml.error.noanon=Vous ne pouvez pas laisser un commentaire anonyme sur ce journal. + +/talkpost_do.bml.error.noauth=Vous n'êtes pas autorisé à répondre à cette entrée protégée. + +/talkpost_do.bml.error.nocomments=L'utilisateur interdit les commentaires sur cette entrée. + +/talkpost_do.bml.error.noparent=Vous ne pouvez répondre à un commentaire qui n'existe pas. + +/talkpost_do.bml.error.notafriend=Désolé, l'utilisateur [[user]]ne vous a pas inclus dans sa liste d'amis, et il a coché l'option " amis seulement " pour ceux qui peuvent répondre à son journal. + +/talkpost_do.bml.error.nousername=Vous n'avez pas entré votre nom d'utilisateur LiveJournal. Vous pouvez décider de répondre comme " anonyme " si vous n'avez pas un compte d'utilisateur LiveJournal. + +/talkpost_do.bml.error.noverify=Désolé, vous n'êtes pas autorisé à envoyer des commentaires dans les journaux d'autres utilisateurs jusqu'à ce que votre adresse courriel ne soit vérifiée. Si vous avez perdu le courriel de confirmation pour faire cette opération, vous pouvez vous le faire envoyer de nouveau par la page des information perdue. + +/talkpost_do.bml.error.postshared=Vous ne pouvez pas écrire en tant que compte partagé ou une communauté. Les comptes partagés representent des groupes de personnes, pas un individu. + +/talkpost_do.bml.error.screened=Vous n'avez pas le droit de répondre à ce commentaire filtré. + +/talkpost_do.bml.error.suspended=Votre journal a été suspendu. Vous ne pouvez pas poster de messages. + +/talkpost_do.bml.error.testacct=Les comptes d'essai peuvent seulement être utilisés dans les journaux d'essai. + +/talkpost_do.bml.opt.preview=Aperçu + +/talkpost_do.bml.preview=Vous pouvez voir ici à quoi ressemblera votre commentaire. En utilisant le formulaire ci-dessous, vous pouvez faire une modification ou l'envoyer. + +/talkpost_do.bml.preview.subject=Sujet: + +/talkpost_do.bml.preview.submit=Soumettre + +/talkpost_do.bml.preview.title=Aperçu + +/talkpost_do.bml.success.loggedin=Vous êtes maintenant connecté. + +/talkpost_do.bml.success.message=Votre réponse a été ajoutée. Vous pouvez la voir ici. + +/talkpost_do.bml.success.screened.comm=Votre commentaire à été ajouté. Selon le fonctionnement de cette communauté, il est automatiquement filtré, et seuls vous et le(s) modérateur(s) de la communauté peuvent le voir jusqu'à ce qu'ils choississent de le rendre public. Vous pouvez voir votre commentaire ici. + +/talkpost_do.bml.success.screened.user=Votre commentaire à été ajouté. Selon les options de ce journal, il est filtré et ne sera visible qu'à vous et au propriétaire du journal, jusqu'à ce que ce dernier le rende public. Vous pouvez voir votre commentaire ici. + +/talkpost_do.bml.success.title=Réussi + +/talkpost_do.bml.success.unscreened=Le commentaire filtré auquel vous avez répondu à été défiltré et est maintenant visible. + +/talkpost_do.bml.title=Commentaire affiché + +/talkread.bml.anonuser=Anonyme + +/talkread.bml.confirm.action=Êtes-vous sûr de vouloir supprimer les commentaires sélectionnés? + +/talkread.bml.deletedpost=(Message effacé) + +/talkread.bml.deleteduser=(compte désactivé: [[username]]) + +/talkread.bml.fromip=(de [[ip]]) + +/talkread.bml.noreplies=Pas de réponses + +/talkread.bml.nosubject=(aucun sujet) + +/talkread.bml.replysuspended=(Réponse d'un compte suspendu) + +/talkread.bml.screenedpost=(Entrée filtrée) + +/talkread.bml.select=Sélectionner + +/talkread.bml.subjectdeleted=[effacé] + +/talkread.bml.talkmulti.delete=Effacez + +/talkread.bml.talkmulti.des=Faisez action en masse avec les commentaires selectionés : + +/talkread.bml.talkmulti.screen=Filtrez + +/talkread.bml.talkmulti.submit=Faire l'action + +/talkread.bml.talkmulti.unscreen=Rendre public + +/talkread.bml.title=Lire les commentaires + +/talkscreen.bml.error.login=Vous devez être connecté pour pouvoir utiliser des commentaires filtrés. + +/talkscreen.bml.error.privs.screen=Vous n'avez pas la permission de filtrer ce commentaire. + +/talkscreen.bml.error.privs.unscreen=Vous n'avez pas la permission de rendre public ce commentaire. + +/talkscreen.bml.screen.doit=Oui, filtrer ce commentaire. + +/talkscreen.bml.screen.sure.body=Êtes-vous certain de vouloir filtrer ce commentaire? + +/talkscreen.bml.screen.sure.title=Filtrer ce commentaire? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=Ce commentaire à été filtré. + +/talkscreen.bml.screened.title=Succès + +/talkscreen.bml.title=Commentaire filtré + +/talkscreen.bml.unscreen.doit=Oui, rendre public ce commentaire. + +/talkscreen.bml.unscreen.sure.body=Êtes-vous sur de vouloir rendre public ce commentaire? + +/talkscreen.bml.unscreen.sure.title=Rendre ce commentaire public? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=Le commentaire à été rendu public. + +/talkscreen.bml.unscreened.title=Succès + +/tools/emailmanage.bml.address.current.title=Courriel Actuel + +/tools/emailmanage.bml.address.old.title=Couriel précédent + +/tools/emailmanage.bml.desc.notfirst=Cette page vous permet de supprimer seulement les adresses courriel utilisées pour valider votre compte la première fois. En particulier, cela signifie que quelqu'un attaquant votre compte ne peut pas supprimer votre adresse courriel d'origine. + +/tools/emailmanage.bml.desc.text=Cette page vous permet de supprimer les adresses courriel précédemment utilisées pour votre compte. Si vous supprimez une adresse, il ne sera plus possible d'utiliser votre mot de passe pour cette adresse. C'est utile si quelqu'un découvrait votre mot de passe et piratait votre journal. Envoyez simplement votre nouveau mot de passe à votre adresse précédente. Changez ensuite votre mot de passe et supprimez l'adresse courriel de la personne vous attaquant. + +/tools/emailmanage.bml.log.deleted=Effacé [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Changements sauvegardés + +/tools/emailmanage.bml.notvalidated.text=Pour utiliser cet outil, votre adresse courriel actuelle , [[email]], doit être validée. Si vous avez perdu le message de confirmation pour faire cela, vous pouvez vous le faire envoyer de nouveau. Après avoir validé votre adresse courriel, revenez sur cette page. + +/tools/emailmanage.bml.notvalidated.title=L'adresse courriel n'a pas été validée + +/tools/emailmanage.bml.title=Gestion de courriel + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Votre liste d'entrées mémorables a été mise à jour. + +/tools/memadd.bml.body.added.header=Succès + +/tools/memadd.bml.description.text<< +Donnez à cete entrée une description par laquelle vous pourrez vous en souvenir. + Pour effacer cette entrée de votre liste d'entrées mémorables, ne faites aucune descriptions. +. + +/tools/memadd.bml.error.deleted.body=L'entrée qui était auparavent décrit comme suit: "[[desc]]", à été enlevée de votre liste d'entrées mémorables. + +/tools/memadd.bml.error.deleted.title=Souvenir effacé + +/tools/memadd.bml.error.entry_deleted=L'entrée n'existe plus. Le souvenir a été effacé. + +/tools/memadd.bml.error.fivekeywords=Seulement 5 mot-clés/catégories sont permis par entrée mémorable. + +/tools/memadd.bml.error.invalid_security=Option de sécurité manquante ou non-valide. + +/tools/memadd.bml.error.login=Vous devez être connecté pour utiliser cette fonction. Allez vous connecter et vous reviendrez ici automatiquement par la suite. + +/tools/memadd.bml.error.maxsize=Ce mot clé dépasse la longueur permise: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Pour ajouter une entrée à votre liste d'entrées mémorables, vous devez lui donner une description. +Pour effacer un souvenir, vous pouvez l'éditez et en enlever la description, mais vous n'aviez pas encore cette entrée dans vos souvenirs. +. + +/tools/memadd.bml.error.nodescription.title=Pas de description + +/tools/memadd.bml.form.reset=Recommencer + +/tools/memadd.bml.form.submit=Soumettre + +/tools/memadd.bml.keywords=Mots clés + +/tools/memadd.bml.keywords.example=Exemple: Amusant, débile, romantique + +/tools/memadd.bml.keywords.select=Ou bien, vous pouvez aussi choisir des mots clés que vous avez utilisé antérieurement. + +/tools/memadd.bml.keywords.text<< +Pourquoi cette entrée est-elle mémorable ? +Entrez au plus cinq mots clés ou catégories pour la retrouver plus tard. +. + +/tools/memadd.bml.login.enterinfo=Entrez le nom d'utilisateur et le mot de passe du compte où vous voulez sauvegarder le souvenir. + +/tools/memadd.bml.login.forgot.header=Avez-vous oublié quelque chose ? + +/tools/memadd.bml.login.forgot.recover=Si vous avez perdu votre nom d'utilisateur ou votre mot de passe, retrouvez le ici!. + +/tools/memadd.bml.multiple_selections=Pour choisir plusieurs mot-clés, appuyez sur 'Control' sur votre clavier en clickant sur les mot-clés désirés. + +/tools/memadd.bml.security=Sécurité: + +/tools/memadd.bml.security.friendsonly=Amis seulement + +/tools/memadd.bml.security.private=Privé + +/tools/memadd.bml.security.public=Public + +/tools/memadd.bml.title=Ajouter aux souvenirs + +/tools/memadd.bml.title.added=Ajouté + +/tools/memadd.bml.title.add_memory=Ajouter une entrée mémorable + +/tools/memadd.bml.title.deleted=Effacé + +/tools/memadd.bml.title.edit_memory=Éditez une entrée mémorable + +/tools/memadd.bml.whocansee<< +Qui peut voir que vous avez marqué cette entrée comme mémorable? +Tout le monde, seulement ceux que vous avez sur votre liste d'amis, ou juste vous ? +. + +/tools/memories.bml.back=Retourner + +/tools/memories.bml.body.keyword<< + +[[user]] a trouvé mémorables. p?> +. + +/tools/memories.bml.body.list_categories<< + + +. + +/tools/memories.bml.body.memorable=La liste suivante est une liste d'entrées non classées que l'utilisateur [[user]] a trouvé mémorables. + +/tools/memories.bml.edit=éditer + +/tools/memories.bml.error.noentries.body<< +C'est peut-être parce que
        +
      1. l'utilisateur n'a pas défini d'entrées mémorables,
      2. +
      3. les entrées mémorables de l'utilisateur sont protégées et vous n'y avez pas accès,
      4. +
      5. l'utilisateur n'a pas d'entrées mémorables selon vos critères.
      6. +. + +/tools/memories.bml.error.noentries.title= Aucune entrée mémorable trouvée. + +/tools/memories.bml.filter.all=Toutes les entrées mémorables + +/tools/memories.bml.filter.other=Seulement les autres entrées + +/tools/memories.bml.filter.own=Seulement les entrées de "[[user]]" + +/tools/memories.bml.form.filter=Filtrer les entrées par : + +/tools/memories.bml.form.sort=Trier les entrées : + +/tools/memories.bml.form.switch=Changer + +/tools/memories.bml.login=Afin de voir vos propres entrées mémorables, veuillez vous enregistrer + +/tools/memories.bml.plur_entry=[[num]] [[?num|entrée|entrées]] + +/tools/memories.bml.sort.description=par description + +/tools/memories.bml.sort.journal=par nom de journal + +/tools/memories.bml.sort.orderadded=Ordre ajouté + +/tools/memories.bml.title.keyword=Entrées mémorables "[[keyword]]" + +/tools/memories.bml.title.memorable=Entrées mémorables + +/tools/memories.bml.uncategorized=Sans catégorie + +/update.bml.altpost=Journal où poster: + +/update.bml.btn.update=Mettre à jour votre journal + +/update.bml.currmood=Humeur actuelle: + +/update.bml.currmusic=Musique actuelle: + +/update.bml.default=par défault + +/update.bml.defaultjournal=([[user]]) -- par défaut + +/update.bml.error.cantpost=Désolé, vous ne pouvez pas poster en ce moment. + +/update.bml.error.disabled=Votre type de compte de permet pas de poster + +/update.bml.error.disabled.title=Autorisation de poster désactivée + +/update.bml.error.login=Erreur lors de la connection: + +/update.bml.error.nopass=Entrez votre mot de passe + +/update.bml.error.update=Erreur lors de la mise à jour de votre journal: + +/update.bml.event=Événement: + +/update.bml.full=Page de mise à jour complète + +/update.bml.htmlokay.norich=(HTML autorisé; par défaut, les nouvelles lignes seront formatées automatiquement en <br>) + +/update.bml.htmlokay.rich=(HTML autorisé; par défaut, les nouvelles lignes seront formatées automatiquement en <br> - ou, utilisez le mode texte enrichi.) + +/update.bml.htmlokay.rte_nosupport=(Désolé, votre navigateur ne supporte pas encore l'environnement de texte enrichi) + +/update.bml.localtime=Heure locale: + +/update.bml.loggedinas=Vous êtes actuellement enregistré comme étant l'utilisateur [[user]].
        Pour poster avec un autre nom d'utilisateur, cliquez ici + +/update.bml.loggingin=Connection au serveur... + +/update.bml.noneother=Aucun, ou autre: + +/update.bml.note=Notez: La date et l'heure ci-dessus sont celles de notre serveur. Corrigez les en fonction de votre heure locale avant de faire une entrée. + +/update.bml.opt.backdate=Entrée antidatée. + +/update.bml.opt.backdate.about=ne sera pas sur la page d'amis + +/update.bml.opt.defpic=(par défaut) + +/update.bml.opt.nocomments=Interdire les commentaires: + +/update.bml.opt.noemail=Ne pas envoyer les commentaires par courriel: + +/update.bml.opt.noformat=Ne pas mettre en forme automatiquement: + +/update.bml.opt.spellcheck=Vérifier l'orthographe + +/update.bml.options=Options + +/update.bml.other=Autre: + +/update.bml.password=Mot de passe: + +/update.bml.picture=Icôneà utiliser: + +/update.bml.security.custom=Personnaliser... + +/update.bml.security.friends=Amis + +/update.bml.security.head=Niveau de sécurité: + +/update.bml.security.private=Privé + +/update.bml.servermsg=Le serveur a aussi un message pour vous: + +/update.bml.simple=Vous voyez la page simple. Pour plus d'options, cliquez ici. + +/update.bml.spellchecked=Votre entrée corrigée: + +/update.bml.subject=Sujet (facultatif) + +/update.bml.timeformat=Temps sur 24 heures + +/update.bml.title=Mettez à jour votre journal + +/update.bml.title.readonly=Mode de lecture seulement + +/update.bml.update.head=Mettez à jour votre journal... + +/update.bml.update.success=Mise à jour réussie. Vous pouvez voir votre journal ici. + +/update.bml.updating=Journal mis à jour... + +/update.bml.username=Nom d'utilisateur: + +/uploadpic.bml.error.unsupportedtype=Les fichiers de type [[filetype]] ne sont pas supportés. Vous ne pouvez télécharger que des fichiers GIF, PNG ou JPG. Presque tous les programmes d'édition d'images peuvent faire cette conversion pour vous. + +/userinfo.bml.about.comm=À propos : + +/userinfo.bml.about.user=Bio : + +/userinfo.bml.body.leave=Vous pouvez quitter la communauté quand vous voulez. + +/userinfo.bml.comminfo.body=Ci-dessous se trouve l'information à propos de la communauté "[[commname]]" sur LiveJournal. + +/userinfo.bml.comminfo.name=Profil de la communauté + +/userinfo.bml.date.never=Jamais. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Nom d'utilisateur déformé. + +/userinfo.bml.error.notloggedin=Vous devez être connecté pour regarder votre propre profil. + +/userinfo.bml.friendof.comm=Regardé par: + +/userinfo.bml.friendof.hidden=(caché) + +/userinfo.bml.friendof.syndreadcount=Nombre de lecteurs + +/userinfo.bml.friendof.user=Ami(e) de: + +/userinfo.bml.friends.comm=Membres + +/userinfo.bml.friends.user=Amis + +/userinfo.bml.label.addbuddy=Ajouter un copain + +/userinfo.bml.label.adduser=Ajouter l'utilisateur + +/userinfo.bml.label.aolim=AOL IM : + +/userinfo.bml.label.birthdate=Anniversaire + +/userinfo.bml.label.clientsused= Clients utilisés: + +/userinfo.bml.label.comments=Commentaires: + +/userinfo.bml.label.composted=Envoyé: [[num]] - + +/userinfo.bml.label.comreceived=Reçu: [[num]] + +/userinfo.bml.label.datecreated=Date de création: + +/userinfo.bml.label.dateupdated=Date de mise à jour: + +/userinfo.bml.label.email=Courriel : + +/userinfo.bml.label.icquin=ICQ : + +/userinfo.bml.label.interests=Intérêts + +/userinfo.bml.label.interests.modifyyours=Modifiez les vôtres + +/userinfo.bml.label.interests.removesome=Supprimez en + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] intérêt caché + +/userinfo.bml.label.jabber=Jabber : + +/userinfo.bml.label.journalentrs=Entrées: + +/userinfo.bml.label.location=Endroit: + +/userinfo.bml.label.memberof=Membre de + +/userinfo.bml.label.memories=Souvenirs: + +/userinfo.bml.label.moredetails=(plus de détails...) + +/userinfo.bml.label.msnusername=MSN : + +/userinfo.bml.label.name=Nom: + +/userinfo.bml.label.nofriends=Aucun listé. + +/userinfo.bml.label.post=Postez dans "[[journal]]" + +/userinfo.bml.label.postalt=Mettez à jour votre journal + +/userinfo.bml.label.reqfinduser=Seuls les utilisateurs avec des droits de 'finduser' peuvent chercher des utilisateurs par identification d'utilisateur. + +/userinfo.bml.label.searchjournal=Cherchez dans ce journal + +/userinfo.bml.label.sendmessage=Envoyer un message + +/userinfo.bml.label.shared=Accès au journal: + +/userinfo.bml.label.supportpoints=Points de supports + +/userinfo.bml.label.syndicatedfrom=Associé de: + +/userinfo.bml.label.syndicatedstatus=Etat des associations + +/userinfo.bml.label.textmessage= Message
        texte
        : + +/userinfo.bml.label.todo=Liste des choses à faire + +/userinfo.bml.label.user=Utilisateur: + +/userinfo.bml.label.viewfriends=Voir vos amis + +/userinfo.bml.label.viewmembers=Voir les membres + +/userinfo.bml.label.website=Site web: + +/userinfo.bml.label.yahooid=Yahoo!: + +/userinfo.bml.membership.body=Cliquez ici pour joindre cette communauté. + +/userinfo.bml.membership.paidmembers=Un fois que votre compte payant sera établi, vous pourrez vous joindre à la communauté des membres payants + +/userinfo.bml.memories.entries=[[count]] entrées + +/userinfo.bml.memories.entry=[[count]] entrée + +/userinfo.bml.monitor.comm=Contrôlez la communauté + +/userinfo.bml.monitor.user=Ajoutez cet utilisateur à votre liste d'amis + +/userinfo.bml.nonexist.body=Le nom d'utilisateur [[user]] n'est pas présentement enregistré. + +/userinfo.bml.nonexist.name=Utilisateur inconnu + +/userinfo.bml.sendmessage.body=Envoyez un message texte à [[user]]
        sur son cellullaire ou son téléavertisseur. + +/userinfo.bml.syn.last.never=Jamais + +/userinfo.bml.syn.lastcheck=Dernier appelé + +/userinfo.bml.syn.nextcheck=Prochain appelé + +/userinfo.bml.syn.parseerror=Message d'erreur: + +/userinfo.bml.syndinfo.body<< +Si vous aimeriez voir dans votre liste d'amis des articles du site associé, vous pouvez ajouter ce journal à votre liste d'amis. + +. + +/userinfo.bml.syndinfo.name=Journal associé + +/userinfo.bml.tellafriend=Dites le à un(e) ami(e)! + +/userinfo.bml.timeupdate.dayago=il y a 1 jour + +/userinfo.bml.timeupdate.daysago=il y a [[num]] jours + +/userinfo.bml.timeupdate.hourago=il y a 1 heure + +/userinfo.bml.timeupdate.hoursago=il y a [[num]] heures + +/userinfo.bml.timeupdate.minuteago=il y a 1 minute + +/userinfo.bml.timeupdate.minutesago=il y a [[num]] minutes + +/userinfo.bml.timeupdate.secondago=il y a 1 seconde + +/userinfo.bml.timeupdate.secondsago=il y a [[num]] secondes + +/userinfo.bml.timeupdate.weekago=il y a 1 semaine + +/userinfo.bml.timeupdate.weeksago=il y a [[num]] semaines + +/userinfo.bml.title=Profil + +/userinfo.bml.title.communityinfo=Profil de la communauté + +/userinfo.bml.title.syndicated=Compte associé + +/userinfo.bml.userinfo.body=Ci-dessous se trouve l'information de [[username]]. Si vous êtes cet utilisateur, vous pouvez éditer votre profil (ou choisir les informations qui seront publiques) à votre page de profil. + +/userinfo.bml.userinfo.name=Profil + +BML.parse_multipart.parse=Erreur de syntaxe lors du téléchargement + +BML.parse_multipart.toolarge=Mise à jour trop grande + +BML.parse_multipart.unknowntype=Contenu inconnu + +btn.search=Chercher + +crumb.about=À propos de LiveJournal + +crumb.acctfeatures=Caractéristiques par type de compte + +crumb.acctstatus=État du compte + +crumb.addfriend=Ajoutez un ami + +crumb.addtodo=Ajoutez une chose à faire + +crumb.advcustomize=Personnalisez vos réglages S2 avancés + +crumb.advsearch=Avancés + +crumb.banners=Bannières publicitaires + +crumb.birthdays=Anniversaires + +crumb.changepass=Changez votre mot de passe + +crumb.contract=Notre contrat social + +crumb.contributors=Collaborateurs + +crumb.createcommunity=Créez une communauté + +crumb.createjournal=Créez un journal + +crumb.customize=Personnalisez vos réglages S2 + +crumb.delcomment=Effacez le commentaire + +crumb.download=Téléchargez un client + +crumb.editentries=Éditez les entrées + +crumb.editentries_do=Éditez l'entrée + +crumb.editfriendgrps=Éditez les groupes d'amis + +crumb.editfriends=Éditez les amis + +crumb.editinfo=Informations personnelles + +date.day.friday.long=Vendredi + +date.day.friday.short=Ven + +date.day.monday.long=Lundi + +date.day.monday.short=Lun + +date.day.saturday.long=Samedi + +date.day.saturday.short=Sam + +date.day.sunday.long=Dimanche + +date.day.sunday.short=Dim + +date.day.thursday.long=Jeudi + +date.day.thursday.short=Jeu + +date.day.tuesday.long=Mardi + +date.day.tuesday.short=Mar + +date.day.wednesday.long=Mercredi + +date.day.wednesday.short=Mer + +date.month.april.long=Avril + +date.month.april.short=Avr + +date.month.august.long=Août + +date.month.august.short=Aoû + +date.month.december.long=Décembre + +date.month.december.short=Déc + +date.month.february.long=Février + +date.month.february.short=Fév + +date.month.january.long=Janvier + +date.month.july.long=Juillet + +date.month.july.short=Juil + +date.month.june.long=Juin + +date.month.june.short=Juin + +date.month.march.long=Mars + +date.month.may.long=Mai + +date.month.may.short=Mai + +date.month.november.long=Novembre + +date.month.october.long=Octobre + +date.month.september.long=Septembre + +dystopia.btn.login=CONNECTEZ-VOUS + +dystopia.hello_anonymous=Bienvenue sur LiveJournal! + +dystopia.hello_loggedin=Bonjour, [[username]]! + +dystopia.nav.createjournal=Créer un journal + +dystopia.nav.developer=Section des développeurs + +dystopia.nav.download=Télécharger + +dystopia.nav.editentries=Éditer vos entrées + +dystopia.nav.editfriends=Vos amis + +dystopia.nav.editpassword=Votre mot de passe + +dystopia.nav.editpics=Vos icônes + +dystopia.nav.editstyle=Editez votre style + +dystopia.nav.faq=FAQ de LiveJournal + +dystopia.nav.findcomm=Par communauté + +dystopia.nav.finddir=Recherche par répertoire + +dystopia.nav.findint=Par intérêt + +dystopia.nav.findrandom=Aléatoire + +dystopia.nav.findregion=Par région + +dystopia.nav.home=Accueil + +dystopia.nav.journalcalendar=Calendrier + +dystopia.nav.journalfriends=Amis + +dystopia.nav.journalinfo=Profil + +dystopia.nav.journalrecent=Récent + +dystopia.nav.legalprivacy=Privé + +dystopia.nav.legaltos=Conditions du service + +dystopia.nav.login=Connectez-vous + +dystopia.nav.logout=Déconnectez-vous + +dystopia.nav.lostinfo=Mot de passe perdu + +dystopia.nav.memories=Souvenirs + +dystopia.nav.modifyjournal=Modifiez votre journal + +dystopia.nav.news=Nouvelles + +dystopia.nav.paidaccts=Comptes payants + +dystopia.nav.paymentarea=Endroit pour payer + +dystopia.nav.personalinfo=Profil + +dystopia.nav.sitemap=Plan du site + +dystopia.nav.support=Avez-vous une question? + +dystopia.nav.updatejournal=Mettez à jour votre journal + +dystopia.navhead.findusers=Trouver des utilisateurs + +dystopia.navhead.help=Aide & support + +dystopia.navhead.journal=Votre journal + +dystopia.navhead.legal=Légal + +dystopia.navhead.settings=Vos réglages + +dystopia.navhead.welcome=Bienvenue! + +dystopia.search.icq=Numéro ICQ + +dystopia.search.int=Intérêt + +dystopia.search.msn=Nom MSN + +dystopia.search.region=Région + +dystopia.search.yahoo=ID Yahoo! + +dystopia.searchlj=Chercher sur LiveJournal: + +Email=Courriel + +email.newacct.body<< +Félicitations, vous avez un compte LiveJournal! + +Pour completer la création de votre journal et vérifier votre courriel, allez ici : + + [[regurl]] + +L'adresse virtuelle de votre nouveau journal est la suivante : + + [[siteroot]]/users/[[username]]/ + +et aussi : + + [[siteroot]]/~[[username]]/ + +Ci-dessous se trouvent votre nom d'utilisateur de LiveJournal, et votre mot de passe : + + Nom d'utilisateur: [[username]] + mot de passe: [[password]] + +Vous pouvez aller à [[siteroot]]/ pour avoir accès à votre compte, créer de nouvelles entrées pour votre journal, et modifier vos options, mais nous recommandons que vous téléchargiez un client. C'est la façon la plus facile de mettre à jour votre journal,et il a plusieurs clients disponibles pour plusieurs plateformes! Trouvez-en un à: + + [[siteroot]]/download/ + +Faire ses débuts sur LiveJournal peut être difficile lorsqu'on ne connait personne. Visitez http://newbies.livejournal.com pour de l'aide intelligente et utile. Avec un peu de chance, vous serez un pro de LiveJournal en peu de temps! + +Nous espèrons que vous apprécierez LiveJournal autant que nous apprécions vous le présenter. Si vous avez des questions sur l'utilisation de LiveJournal, veuillez +visiter le support technique à : + + [[siteroot]]/support/ + +Vous y trouverez les réponses à presque toutes les questions que vous pourriez vous poser à propos de LiveJournal. + +Notre but est de rendre LiveJournal génial... si nous pouvons faire n'importe quoi pour le rendre plus facile, plus puissant, plus personnel, peu importe, laissez nous savoir. Notre but n'est pas de faire de l'arget avec le site. Ce site est dirigé par les gens qui l'utilisent. Faites nous savoir ce que vous voulez y trouver. + +Si vous avez des questions, l'équipe du support technique vous répondra généralement dans les 24 heures. + +Amusez-vous! + +L'équipe [[sitename]] +[[siteroot]]/ + +. + +email.newacct.subject=Bienvenue à LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Erreur + +error.badpassword=Mot de passe incorrect. + +error.dberror=Erreur de base de données: + +error.deleted.name=Effacé + +error.deleted.text=Ce journal a été effacé. Si vous êtes [[user]], vous avez 30 jours pour revenir sur votre décision. Après ces 30 jours, nous effacerons son contenu de nos serveurs. + +error.deleted.title=Compte effacé + +error.ipbanned=Votre adresse IP est temporairement exclue pour avoir dépassé le nombre d'erreurs de connexion. + +error.malformeduser=Nom d'utilisateur malformé. + +error.nobutton=Vous n'avez appuyé sur aucun bouton? + +error.nodb=Base de données temporairement indisponible + +error.nodbmaintenance=Cette partie de la base de données est temporairement fermée pour maintenance. Essayez à nouveau dans quelques minutes + +error.noentry=Pas d'entrée de ce genre. + +error.nojournal=Journal inconnu + +error.noremote=Vous devez vous connecter pour utiliser cette page. + +error.procrequest=Une erreur est survenue en traitant votre demande: + +error.purged.name=Effacé + +error.purged.text=Ce journal a été effacé et purgé. + +error.purged.title=Compte purgé + +error.suspended.name=Suspendu + +error.suspended.text=Ce journal a été suspendu temporairement ou définitivement. Si vous êtes [[user]], référez vous s'il vous plaît à la FAQ Mon compte a été suspendu ! Comment le récupérer ?? pour plus d'informations. Notez que pour préserver la vie privée de nos utilisateurs, [[sitename]] ne peut discuter d'aucune suspension de compte avec quelqu'un d'autre que le propriétaire du compte. + +error.suspended.title=Compte suspendu + +error.tempdisabled=Temporairement indisponible. + +error.unknownmode=Mode inconnu. + +error.usernameinvalid=Le nom d'utilisateur contient des caractères non valables. + +error.usernamelong=Le nom d'utilisateur est trop long, 15 caractères au plus. + +error.username_notfound=Nom d'utilisateur non trouvé + +Help=Aide + +label.security.custom=Personnalisé + +label.security.friends=Amis + +label.security.head=Niveau de sécurité: + +label.security.private=Privé + +label.switch.button=Changer + +label.switch.header=Changer de journal + +label.switch.workwith=Travailler avec le journal: + +langname.be=Biélorusse + +langname.da=Danois + +langname.de=Allemand + +langname.en=Anglais + +langname.en_GB=Anglais (RU) + +langname.en_LJ=Anglais + +langname.es=Espagnol + +langname.et=Estonien + +langname.fi=Finnois + +langname.fr=Français + +langname.ga=Irlandais + +langname.gd=Gaélique + +langname.he=Hébreu + +langname.hu=Hongrois + +langname.is=Islandais + +langname.it=Italien + +langname.ja=Japonais + +langname.lv=Letton + +langname.ms=Malais + +langname.nb=Norvégien + +langname.nl=Hollandais + +langname.nn=Norvégien + +langname.pl=Polonais + +langname.pt=Portugais + +langname.ru=Russe + +langname.sv=Suédois + +langname.tr=Turc + +langname.zh=Chinois simplifié + +ljlib.pageofpages=Page [[page]] de [[total]] + +lostinfo.head=Avez-vous oublié quelque chose ? + +lostinfo.text=Si vous avez perdu votre nom d'utilisateur ou votre mot de passe, retrouvez le ici. + +Password=Mot de passe + +password.max30=Les mots de passes ne peuvent avoir plus de 30 caractères. + +portal.bdays.count.des=Par défaut, vous verrez les 5 amis aux anniversaires les plus proches. + +portal.bdays.count.name=Anniversaires à afficher + +portal.bdays.portalname=Anniversaires + +portal.bdays.portaltitle=Anniversaires + +portal.goat.name=Mascotte du site + +portal.goattext.des=Que voulez-vous que votre chèvre dise? La seule chose que les chèvres sachent dire c'est "Bêêêhh", mais vous pouvez faire semblant que la vôtre peut dire autre chose si ça vous fait plaîsir. + +portal.goattext.name=Texte de la chèvre + +portal.login.portalname=Boîte de connection + +portal.memories.entriesnoun=entrées + +portal.memories.entrynoun=entrée + +portal.memories.portalname=Entrées mémorables + +portal.memories.portaltitle=Entrées mémorables + +portal.ministats.active=Actifs : + +portal.ministats.title=Statistiques + +portal.ministats.total=Utilisateurs : + +portal.misbehaved.des=Vous voulez vraiment laisser ceci décoché. Les chèvres non-domestiques sont capricieuses. + +portal.misbehaved.name=Chèvre mal élevée + +portal.newtolj.name=Liens du site + +portal.popfaq.portalname=10 FAQ les plus lues + +portal.popfaq.portaltitle=10 FAQ les plus lues + +portal.randuser.count.des=Par défaut, 1 utilisateur apparaît, mais vous pourriez avoir jusqu'à 10 utilisateurs dans des colonnes minces verticales, ou 5 dans des colonnes plus larges horizontalement. + +portal.randuser.count.name=Nombre aléatoire d'utilisateurs à montrer + +portal.randuser.error.tableempty=Il n'y a pas d'utilisateurs aléatoires. Veuillez contacter les administrateurs. + +portal.randuser.hidename.des=Par défaut, le nom d'utilisateur aléatoire est montré. Cochez ceci pour le cacher. + +portal.randuser.hidename.name=Cacher le nom + +portal.randuser.hidepic.des=Par défaut, l'icône aléatoire de l'utilisateur est montrée, lorsque c'est possible. Cochez ceci pour la cacher. + +portal.randuser.hidepic.name=Cacher l'icône de l'utilisateur + +portal.randuser.portalname=Utilisateur aléatoire + +portal.randuser.portaltitle=Utilisateur aléatoire + +portal.randuser.portaltitleplural=Utilisateurs aléatoires + +portal.recent.error.noentries=Désolé. Pas d'entrées. + +portal.recent.error.notsetup=Vous devez configurer cette boîte. Cochez le symbole "plus" pour déterminer le journal que vous aimeriez regarder ici. + +portal.recent.error.userstatus=L'utilisateur a effacé ou suspendu son compte. + +portal.recent.items.description=Par défaut, seulement les entrées les plus récentes sont montrées. + +portal.recent.items.name=Items à afficher + +portal.recent.journal.description=De quel journal voudriez-vous voir les derniers items? + +portal.recent.nosubject=(Aucun sujet) + +portal.recent.permlink=Lien + +portal.recent.portalname=Affichage des entrées récentes + +portal.recent.portaltitle=Boîte des entrées récentes + +portal.recent.showtext.description=Par défaut, seul les sujets seront affichés. + +portal.recent.showtext.name=Inclure le texte + +portal.stats.journalentyest=Entrées d'hier du journal + +portal.stats.portalname=Statistiques du site + +portal.stats.portaltitle=Statistiques + +portal.stats.totalusers=Nombre total d'utilisateurs + +portal.update.mode.des=Le mode complet vous permet d'avoir une multitude d'options supplémentaires lorsque vous faites vos entrées... y compris l'accès aux communautés et l'affichage de votre humeur et musique actuelles, ainsi que le choix d'une icône. Le mode simple est utile lorsque vous n'utilisez pas ces fonctions et ne voulez pas les voir. + +portal.update.mode.full=Complet + +portal.update.portalname=Mise à jour du journal + +portal.update.portaltitle=Mettez à jour votre journal + +protocol.bad_password=Votre mot de passe est trop facile à deviner. Changez le, autrement votre journal risque d'être piraté. Allez à [[siteroot]]/changepassword.bml pour changer votre mot de passe. + +protocol.hello_test=Hello Compte Test! + +protocol.mail_bouncing=Vous utilisez actuellement une mauvaise adresse courriel. Le courriel que nous essayons de vous envoyer revient. [[sitename]] a besoin d'une adresse valable pour être utilisé. Allez à [[siteroot]]/support/faqbrowse.bml?faquid=19 pour modifier votre adresse de courriel. + +protocol.modpost=Votre entrée a été ajoutée à la liste d'attente de supervision. Elle sera acceptée ou rejetée par un des superviseurs de la communauté. + +protocol.must_revalidate=Vous devez valider votre nouvelle adresse. Votre précédente était valable, mais comme vous l'avez changée, vous devez valider la nouvelle. Si vous ne le faites pas, vous n'aurez pas accès à toutes les fonctions de [[sitename]]. Voyez [[siteroot]]/support/faqbrowse.bml?faqid=11 pour plus d'informations. + +protocol.not_validated=Votre adresse de courriel n'a pas été validée. Vous pouvez continuer à utiliser [[sitename]], mais si vous ne validez pas votre adresse vous n'aurez pa accès à toutes les fonctions du site. Voyez les instructions que vous avez reçu par courriel lorsque vous avez créé votre journal, ou allez à [[siteroot]]/support/faqbrowse.bml?faqid=11 pour en savoir plus. + +protocol.old_win32_client=Il y a des clients Windows pour LiveJournal plus récents, et nous vous recommandons de faire une mise à jour. Allez à [[siteroot]]/download/ pour télécharger un nouveau client. + +protocol.readonly=Votre compte est temporairement en mode lire-seulement. Certaines opérations seront impossibles pendant quelques minutes. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Désolé + +talk.anonwrote=Quelqu'un a écrit, + +talk.anonwrote_comm=Quelqu'un a écrit dans [[commlink]], + +talk.btn.preview=Aperçu + +talk.commentpermlink=lien + +talk.commentpost=Envoyez un nouveau commentaire + +talk.commentsread=Lire les commentaires + +talk.curname_Mood=Humeur actuelle: + +talk.curname_Music=Musique actuelle: + +talk.error.bogusargs=Information incohérente + +talk.error.comm_deleted=Ce commentaire a été effacé. + +talk.error.deleted=Ce journal est effacé. + +talk.error.deleted.title=Effacé + +talk.error.mustlogin=Vous devez être connecté pour voir cette entrée protégée. + +talk.error.nocomment=Le commentaire n'existe pas. + +talk.error.noentry=Pas d'entrée de cette sorte. + +talk.error.nojournal=Erreur: n'a pu déterminer le journal à partir de l'information + +talk.error.nosuchjournal=Pas de journal de ce genre + +talk.error.notauthorised=Vous n'êtes pas autorisé à voir cette entrée protégée. + +talk.error.suspended=Ce journal/auteur est suspendu. + +talk.error.suspended.title=Suspendu + +talk.parentlink=Précédent + +talk.readsimilar=Lire des entrées semblables: + +talk.replytothis=Répondre + +talk.somebodywrote=[[realname]] ([[userlink]]) a écrit, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) a écrit dans [[commlink]], + +talk.spellcheck=Vérifier l'orthographe pendant l'aperçu + +talk.threadlink=Fil + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_francais + +Username=Nom d'utilisateur + +userpic.inactive=Inactif + +xcolibur.greeting.anon=Bienvenue à LiveJournal! + +xcolibur.greeting.logged_in=Bienvenue, [[name]]! [[logout]] + +xcolibur.login=Connectez-vous + +xcolibur.logout=Déconnectez-vous + +xcolibur.nav.about=À propos + +xcolibur.nav.about.download=Télécharger + +xcolibur.nav.about.general=Informations générales + +xcolibur.nav.about.paidaccounts=Compte payants + +xcolibur.nav.about.press=La presse + +xcolibur.nav.about.sitenews=Nouveautés + +xcolibur.nav.about.stats=Statistiques + +xcolibur.nav.footer.sitemap=Plan du site + +xcolibur.nav.help=Aide + +xcolibur.nav.help.ask=Posez une question + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Mot de passe perdu + +xcolibur.nav.home=Accueil + +xcolibur.nav.journal.archive=Archives + +xcolibur.nav.journal.edit.entries=Éditer vos entrées + +xcolibur.nav.journal.friends=Amis + +xcolibur.nav.journal.info=Profil + +xcolibur.nav.journal.memories=Souvenirs + +xcolibur.nav.journal.recent=Entrées récentes + +xcolibur.nav.journal.update=Mettez à jour + +xcolibur.nav.manage=Réglages + +xcolibur.nav.manage.community=Communautés + +xcolibur.nav.manage.customize=Personalisation + +xcolibur.nav.manage.entries=Entrées + +xcolibur.nav.manage.friends=Amis + +xcolibur.nav.manage.info=Profil + +xcolibur.nav.manage.password=Mot de passe + +xcolibur.nav.manage.pics=Icônes + +xcolibur.nav.search=Recherche + +xcolibur.nav.search.directory=Par région + +xcolibur.nav.search.directory.search=Avancée + +xcolibur.nav.search.interests=Par intérêts + +xcolibur.nav.search.random=Aléatoire + +xcolibur.nav.title=Navigation : + +xcolibur.nav.welcome=Bienvenue + +xcolibur.nav.welcome.create=Créez un compte + +xcolibur.nav.welcome.login=Connectez-vous + +xcolibur.nav.welcome.update=Mettez à jour vote journal + +xcolibur.search=Recherche : + +xcolibur.search.category=Catégorie : + +xcolibur.search.icq=Numéro ICQ + +xcolibur.search.int=Intérêts + +xcolibur.search.msn=Nom d'utilisateur MSN + +xcolibur.search.region=Région + +xcolibur.search.yahoo=ID Yahoo! + +xcolibur.upgrade=Améliorez votre compte + diff --git a/ljcom/bin/upgrading/ga.dat b/ljcom/bin/upgrading/ga.dat new file mode 100644 index 0000000..22fd1cd --- /dev/null +++ b/ljcom/bin/upgrading/ga.dat @@ -0,0 +1,2170 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Más mian leat do dhialann a scriosadh nó í a fháil ar ais, seo í an áit. Nuair a scriosann tú do dhialann, bíonn sí ann fós ar feadh 30 lá agus is féidir í a fháil ar ais má thagann malairt intinne ort. Tar éis 30 lá scriosfar an dialann go buan agus ní bheidh caoi ann í a fháil ar ais. + +/accountstatus.bml.journalstatus.head=Stádas do Dhialainne + +/accountstatus.bml.journalstatus.select.activated=Beo + +/accountstatus.bml.journalstatus.select.deleted=Scriosta + +/accountstatus.bml.journalstatus.select.head=Stádas: + +/accountstatus.bml.journalstatus.select.suspended=Ar fionraí + +/allpics.bml.current=Pictiúir Reatha + +/allpics.bml.default=Loicrogha + +/allpics.bml.edit2=Is féidir treoirfhocail do phictiúr a eagrú nó pictiúr nua a uaschóipeáil. + +/allpics.bml.error.noparam=Is riachtanach úsáideoir éigin a lua. + +/allpics.bml.keywords=Treoirfhocail: + +/allpics.bml.nopics.text.other=Níor uaschóipeáil an t-úsáideoir seo pictiúr ar bith. + +/allpics.bml.nopics.text2=Níor uaschóipeáil tú pictiúr ar bith. Más maith leat ceann a uaschóipeáil, téigh anseo. + +/allpics.bml.nopics.title=Pictiúr ar bith + +/allpics.bml.pics=Seo na pictiúir don úsáideoir [[user]]. + +/allpics.bml.title=Pictiúir an Úsáideora + +/community/index.bml.title=Ionad na gCumann + +/community/join.bml.button.join=Cláraigh mar bhall an Chumainn + +/community/join.bml.label.addtofriends=Cuir "[[maintainer]]" le do liosta cairde.
        + +/community/join.bml.label.allowposting=Tá cead ag gach ball teachtaireacht a scríobh sa chumann seo agus mar sin, tá an cead sin agatsa anois. Má tá ríomhchlár cliaint LiveJournal ar oscailt agat ar do ríomhaire faoi láthair, beidh sé ort logáil amach agus logáil isteach arís sula nochtfar an dialann seo sa liosta dialanna gur féidir leat scríobh iontu. + +/community/join.bml.label.auth=Cé go bhfuil tú liostaithe anois mar bhall, níl cead ag gach ball teachtaireachtaí a scríobh sa chumainn seo. Más mian leat cumas scríofa, téigh i dteagmháil le duine de na coimeádaithe. Seo iad coimeádaithe an chumainn seo: [[admins]] + +/community/join.bml.label.banned=Tá cosc curtha ort ag coimeádaí(-aithe) an chumainn seo dul isteach ann. + +/community/join.bml.label.closed=Is cumann dúnta é seo. Más maith leat dul isteach ann, téigh i dteagmháil le duine de na coimeádaithe. Seo iad coimeádaithe an chumainn seo: [[admins]] + +/community/join.bml.label.commlogged=Tá tú logáilte isteach faoi chuntas comhpháirteach (cuntas cumainn), seachas do chuntas pearsanta. + +/community/join.bml.label.errorcomminfo=Níl an fhaisnéis a thug tú faoin gcumann sin bailí. + +/community/join.bml.label.expls=Brúigh ar an gcnaipe thíos chun clárú mar bhall an chumainn "[[maintainer]]". Bain an tic den bhosca más maith leat clárú gan iontrálacha ón gcumann a fheiceáil ar do leathanach cairde. + +/community/join.bml.label.loginfirst=Chun clárú mar bhall cumainn caithfidh tú logáil isteach. + +/community/join.bml.label.membernow=Tá tú i do bhall den chumann [[commname]] anois + +/community/join.bml.label.sure=An bhfuil tú cinnte? + +/community/join.bml.success=D’éirigh leat + +/community/join.bml.title=Cláraigh mar bhall an Chumainn + +/community/leave.bml.button.leave=Fág an Cumann + +/community/leave.bml.label.buttontoleave=Brúigh ar an gcnaipe thíos chun an cumann "[[commname]]" a fhágáil. + +/community/leave.bml.label.infoerror=Níl an fhaisnéis a thug tú faoin gcumann sin bailí. + +/community/leave.bml.label.logoutfirst=Chun cumann a fhágáil caithfidh tú logáil isteach. + +/community/leave.bml.label.removed=Baineadh den Chumann [[commname]] thú + +/community/leave.bml.success=D’éirigh leat + +/community/leave.bml.sure=An bhfuil tú cinnte? + +/community/leave.bml.title=Fág an Cumann + +/community/manage.bml.commlist.actinfo=Faisnéis + +/community/manage.bml.commlist.actions=Gníomhartha + +/community/manage.bml.commlist.actmembers=[Baill] + +/community/manage.bml.commlist.actmembers2=Baill + +/community/manage.bml.commlist.actsettings=[Socruithe] + +/community/manage.bml.commlist.actsettings2=Socruithe + +/community/manage.bml.commlist.header=Do chumainn + +/community/manage.bml.commlist.none=Níl cumann ar bith dá riaradh agat. + +/community/manage.bml.commlist.text=Seo iad na cumainn a bhfuil tú dá riar: + +/community/manage.bml.commlist.title=Teideal + +/community/manage.bml.commlist.username=Ainm Úsáideora + +/community/manage.bml.create.header=Cruthaigh cumann + +/community/manage.bml.create.text=Is féidir cumann a chruthú freisin. + +/community/manage.bml.title=Riarachán Cumann + +/community/members.bml.error.invaliduser=Ní féidir cumann nó cúntas comhfhoilsithe a chur le liosta ball: [[user]] + +/community/members.bml.error.noaccess=Níl cead ach ag coimeádaithe cumann liostaí ball a athrú. Níl tú i do choimeádaí ar an gcumann [[comm]]. + +/community/members.bml.error.noattr=Níor roghnaigh tú tréith ar bith le haghaidh an úsáideora: [[user]] + +/community/members.bml.error.nocomm=Ní bhfuarthas an cumann. + +/community/members.bml.error.nouser=Níl an t-úsáideoir [[user]] ann. + +/community/members.bml.key.admin=Coimeádaí + +/community/members.bml.key.member=Ball + +/community/members.bml.key.moderate=Réiteoir + +/community/members.bml.key.post=Cumas Scríofa + +/community/members.bml.key.preapprove=Muiníneach + +/community/members.bml.manage2=Riar cumainn + +/community/members.bml.name=Ainm an Chumainn: [[name]] + +/community/members.bml.nextlink=(Leathanach ina dhiaidh…) + +/community/members.bml.prevlink=(Leathanach roimhe seo…) + +/community/members.bml.settings=[Socruithe] + +/community/members.bml.success.header=D’éirigh leat + +/community/search.bml.button.clear=Glan an Fhoirm + +/community/search.bml.button.search=Cuardaigh! + +/community/search.bml.checkbox.onlywithpics=Cumainn le pictiúir amhain + +/community/search.bml.label.byinterest=de réir Spéise + +/community/search.bml.label.bylocation=de réir Limistéir + +/community/search.bml.label.bytime=de réir Am Athrú na Dialanne + +/community/search.bml.label.city=Cathair: + +/community/search.bml.label.country=Tír: + +/community/search.bml.label.displayoptions=Roghanna Taispeána + +/community/search.bml.label.hasmember=de réir Baill + +/community/search.bml.label.othercriteria=Critéir Eile + +/community/search.bml.label.outputformat=Formáid na dTorthaí: + +/community/search.bml.label.records=Torthaí ar an leathanach: + +/community/search.bml.label.searchcomm=Cuardaigh Cumainn + +/community/search.bml.label.selecriteria=Roghnaigh na critéir thíos gur mhaith leat cuardach cumainn a dhéanamh dá réir. Braitheann na torthaí ar na critéir cuardaigh uile. Lena rá i chaoi eile, is ionann tic a chur i mbosca agus oibríocht "AND" (AGUS) a úsáid, seachas oibríocht "OR" (NÓ). + +/community/search.bml.label.sortmethod=Modh Sortála: + +/community/search.bml.label.stateprovince=Stát/Cúige: + +/community/search.bml.label.updated=Athraithe + +/community/search.bml.sel.bypicture=de réir Pictiúr + +/community/search.bml.sel.communityname=Ainm an Chumainn + +/community/search.bml.sel.commview=Radharc Cumainn + +/community/search.bml.sel.day=sa lá deireanach + +/community/search.bml.sel.month=sa mhí dheireanach + +/community/search.bml.sel.simple=Simplí + +/community/search.bml.sel.updatetime=Am Athraithe + +/community/search.bml.sel.username=Ainm Úsáideora + +/community/search.bml.sel.week=sa tseachtain dheireanach + +/community/search.bml.title=Cuardaigh Cumainn + +/create.bml.age.check.question=An bhfuil tú níos óige ná 13 bliana d’aois? + +/create.bml.age.check.yes=Tá, tá mé níos óige ná 13 bliana d’aois? + +/create.bml.age.head=Aois + +/create.bml.btn.proceed=Ar aghaidh… + +/create.bml.clusterselect.cluster=Braisle: + +/create.bml.clusterselect.clusternum=Braisle a [[number]] + +/create.bml.clusterselect.head=Rogha na Braisle + +/create.bml.clusterselect.nocluster=Braisle ar bith + +/create.bml.create.head=Cruthú Dialainne Nua + +/create.bml.create.text=Is furasta ar fad LiveJournal nua a chruthú. Níl ort ach an treoir thíos a leanúint! + +/create.bml.email.head=Do sheoladh ríomhphoist + +/create.bml.email.input.head=Seoladh Ríomhphoist: + +/create.bml.error.coppa.under13=Tá brón orainn, ach de réir teorainneacha COPPA, ní féidir an tseirbhís LiveJournal a úsáid go mbeidh tú 13 bliana d’aois. Téigh ar ais, más é do thoil é, ar do 13ú lá breithe. + +/create.bml.error.email.blank=Is riachtanach do sheoladh ríomhphoist a chur isteach. + +/create.bml.error.email.nospaces=Ní féidir spás a chur isteach i seoladh ríomhphoist. Más úsáideoir AOL thú, ná déan dearmad gur riachtanach gach spás i do ‘screen name’ a bhaint de agus @aol.com a chur ina dhiaidh chun do sheoladh Idirlín a chruthú. + +/create.bml.error.password.asciionly=Ní féidir ach carachtair ASCII a úsáid i d’fhocal faire. + +/editinfo.bml.allowshowcontact.about=B'fhiú an rogha seo a choinneáil i bhfeidhm. Ligeann sé do dhaoine bheith i dteagmháil leat trí do sheoladh ríomhphoist, d'uimhir ICQ agus d'ainm scáileáin AOL a thaispeáint ar do dhialann LiveJournal. + +/editinfo.bml.allowshowcontact.email=Seoladh ríomhphoist le taispeáint: + +/editinfo.bml.allowshowcontact.email.actual_only=Seoladh pearsanta amháin + +/editinfo.bml.allowshowcontact.email.both=Iad araon (pearsanta + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Seoladh LiveJournal amháin + +/editinfo.bml.allowshowcontact.email.neither=Ná taispeáin seoladh ar bith + +/editinfo.bml.allowshowcontact.email.no_show=Ná taispeáin seoladh ríomhphoist + +/editinfo.bml.allowshowcontact.email.show=Taispeáin seoladh ríomhphoist + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Leis an rogha thuas, féadann tú do sheoladh ríomhphoist a cheilt (agus d’eolas teagmhála eile a thaispeáint), do sheoladh ríomhphoist LiveJournal amháin (cuntais íoctha amháin) a thaiseáint, do sheoladh pearsanta amháin a thaispeáint, nó iad araon a thaispeáint. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Leis an rogha thuas, féadann tú do sheoladh ríomhphoist a cheilt (agus d’eolas teagmhála eile a thaispeáint). + +/editinfo.bml.allowshowcontact.title=Taispeáin d'eolas teagmhála ar do dhialann + +/editinfo.bml.allowshowinfo.about=Cuir é seo i bhfeidhm más maith leat do chathair/stát/tír agus breithlá a thaispeáint d'úsáideoirí eile. + +/editinfo.bml.allowshowinfo.title=Taispeáin láthair agus breithlá + +/editinfo.bml.autotranslate.about=Leis an rogha seo is féidir cur in iúl do LiveJournal cén t-ionchódú ba cheart a úsáid chun sean-iontrálacha (iontrálacha a scríobh tú roimh tiontú an tsuímh go Unicode) a thaispeáint. Má scríobhann tú i nGaeilge (nó i mBéarla) roghnaigh "Iarthar Eorpa" (Western European) anseo. + +/editinfo.bml.autotranslate.header=Tiontaigh sean-iontrálacha go huathoibríoch ón ionchódú: + +/editinfo.bml.bday.title=Breithlá + +/editinfo.bml.bday.year.opt=tá an bhliain roghnach + +/editinfo.bml.bdayreminders.about=Más maith leat cuimhneacháin ríomhphoist a fháil ar bhreithlaethanta do chairde ar LiveJournal, cliceáil sa bhosca seo. + +/editinfo.bml.bdayreminders.header=Seol cuimhneacháin bhreithlae chugam (díchumasaithe faoi láthair) + +/editinfo.bml.bio.about=Anseo féadann tú beatháisnéisín beag a scríobh le taispeáint ar do leathanach Faisnéis Úsáideora. + +/editinfo.bml.bio.header=Eolas Fútsa + +/editinfo.bml.blockrobots.about<< +Má chuireann tú an rogha seo i bhfeidhm, déarfar le róbónna (ríomhchláir innéacsaithe) do dhialann a fhágáil. +Ní gheilleann gach róbó do na rialacha. +. + +/editinfo.bml.blockrobots.header=Coisc ar Róbónna/Damháin Alla (Ríomhchláir Innéacsaithe) do dhialann a innéacsú. + +/editinfo.bml.chat.aolim.title= AOL IM + +/editinfo.bml.chat.icquin.title= ICQ UIN + +/editinfo.bml.chat.jabber.title= Jabber + +/editinfo.bml.chat.msnusername.title=Ainm Úsáideora MSN + +/editinfo.bml.chat.yahooid.title= Yahoo! ID + +/editinfo.bml.city.title=Cathair + +/editinfo.bml.country.choose=Roghnaigh tír + +/editinfo.bml.country.title=Tír + +/editinfo.bml.donotlog=Ná taifead + +/editinfo.bml.email.title=Ríomhphost + +/editinfo.bml.enableboards.about=Cuir é seo i bhfeidhm más mian leat go mbeidh daoine in ann freagraí a thabhairt ar d'iontrálacha dialainne. + +/editinfo.bml.enableboards.header=Cumasaigh cláir teachtaireachtaí + +/editinfo.bml.encoding.about=Ná bíodh imní ort faoin stuif seo. Go hiondúil, ní bhíonn gá agat rud ar bith a athrú anseo, ach má scríobhann tú in níos mó ná teanga amháin b'fhéidir go mbeadh sé fóinteach duit. + +/editinfo.bml.encoding.header=Roghanna Ionchódaithe + +/editinfo.bml.error.day.notinmonth=Níl an lá sin sa mhí sin. + +/editinfo.bml.error.day.outofrange=Lá bréithe neamhbhailí. Cuir isteach uimhir idir 1 is 31 don lá. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain=Ní féidir seoladh ríomhphoist @[[domain]] a chur isteach anseo.Cuir isteach do sheoladh pearsanta sa réimse sin.Má tá tú i d'úsáídeoir íoctha, seolfar ríomhphost chuig do sheoladh [[user]]@[[domain]] ar aghaidh chuig do sheoladh pearsanta.Chun rogha a dhéanamh ar cén seoladh a thaispeáint go poiblí, féach an rogha "Taispeáin d'eolas teagmhála ar do dhialann". + +/editinfo.bml.error.email.none=Is riachtanach do sheoladh ríomhphoist a thabhairt. + +/editinfo.bml.error.email.no_space<< +Ní cheadaítear spásanna a chur i seoladh ríomhphoist. +Más úsáideoir AOL thú, cuimhnigh gur éard atá ann i do sheoladh ríomhphoist ar an Idirghréasán ná d'ainm scáileáin (agus gach spás bainte de), agus ina dhiaidh sin @aol.com +. + +/editinfo.bml.error.excessive_int<< +Gabh mo leithscéal, ach chuir tú an iomarca spéiseanna isteach. Is í 150 an teorainn atá air, ach chuir tú [[intcount]] isteach. +Má rinne tú athruithe ar bith ar do spéiseanna, níor sábháileadh iad. Téigh ar ais, bain spéiseanna den liosta agus ansin sábháil arís é. +. + +/editinfo.bml.error.invalidbio=Tá carachtair neamhbhailí is do bheatháisnéis. Caithfidh tú dul chuig an leathanach tiontaithe chun í a thiontú go Unicode. + +/editinfo.bml.error.invalidints=Tá carachtair neamhbhailí i do liosta spéiseanna. Caithfidh tú dul chuig an leathanach tiontaithe chun é a thiontú go Unicode. + +/editinfo.bml.error.invalidname=Tá carachtair neamhbhailí i d'ainm. Caithfidh tú dul chuig an leathanach tiontaithe chun é a thiontú go Unicode. + +/editinfo.bml.error.locale.country_ne_state=D'ainmnigh tú na Stáit Aontaithe Mheiriceá mar thír, ach scríobh tú stát nach bhfuil sna Stáit Aontaithe sa réimse "stát/cúige/fearann eile". + +/editinfo.bml.error.locale.invalid_country=Ar chaoi éigin roghnaigh tú tír neamhbhailí. + +/editinfo.bml.error.locale.state_ne_country=D'ainmnigh tú tír eile ach roghnaigh tú stát atá sna Stáit Aontaithe Mheiriceá. + +/editinfo.bml.error.locale.zip_ne_state<< +Ní chomhoiriúnaíonn an zip code (cód poist) don stát a d'aimnigh tú. +Leasaigh an t-eolas, nó scrios an réimse "Stát" nó an réimse "ZIP code" nó iad araon. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Chuir tú zip code (cód poist) isteach, ach níor roghnaigh tú Stáit Aontaithe Mheiriceá mar thír. +Ní bhailíonn muid eolas chód poist ach le haghaidh daoine sna SAM. +Téigh ar ais agus bain an cód poist den réimse nó roghnaigh na Stáit Aontaithe Mheiriceá mar thír. +. + +/editinfo.bml.error.month.outofrange=Mí bhréithe neamhbhailí. Cuir isteach uimhir idir 1 is 12 don mhí. + +/editinfo.bml.error.tm.require.number=Má tá sé ar intinn agat teachtaireachtaí téacs (SMS) a úsáid, caithfidh tú d'uimhir gutháin a chur isteach. + +/editinfo.bml.error.tm.require_provider<< +Má tá sé ar intinn agat teachtaireachtaí téacs (SMS) a úsáid, caithfidh tú do sholáthraí seirbhíse a roghnú. + +Mura bhfuil do sholáthraí sa liosta, téigh i dteagmháil linn más é do thoil é, agus cuir in iúl dúinn cén chaoi a oibríonn teachtaireachtaí téacs ar do sheirbhís sa chaoi gur féidir linn tacaíocht a thabhairt di. +. + +/editinfo.bml.finished.about=Nuair atá tú réidh leis, cliceáil ar an gcnaipe "Sábháil Athruithe" thíos: + +/editinfo.bml.finished.header=Réidh? + +/editinfo.bml.finished.save_button=Sábháil Athruithe + +/editinfo.bml.gender.title=Gnéas + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Cuir tic anseo más maith leat ríomhphost a fháil nuair a thugann daoine freagraí ar d'iontrálacha sna cláir teachtaireachtaí. + +/editinfo.bml.getreplies.header=Faigh freagraí ón gclár teachtaireachtaí + +/editinfo.bml.hidefriendof.about=Má chuireann tú tic anseo ceilfear an liosta (ar do leathanach eolais) de dhaoine a liostaíonns thú mar chara. + +/editinfo.bml.hidefriendof.header=Ceil liosta "Cara le" + +/editinfo.bml.howhear.about<< +Le teann fiosrachta, cár chuala tú iomrá ar [[sitename]]? +Más ó dhuine ar leith a chuala tú é, cuir isteach a (h)ainm úsáideora. Más ó áit/alt/nasc/líonláithreán eile é, cuir isteach an t-eolas freagrach. +. + +/editinfo.bml.howhear.header=Fiosracht + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about=Cuir tic anseo má tá do chlár ríomhphoist in ann ríomhphost HTML a thuiscint. Is iomaí ríomhchlár atá ann a bhaineanns triail as, ach ní éiríonn leo. Má bhaineann tú an tic de, seolfaidh LiveJournal ríomhphost i dtéacs amháin. + +/editinfo.bml.htmlemail.header=Seol ríomhphost HTML + +/editinfo.bml.int.about<< +Más mian leat go mbeadh daoine in ann tusa a aimsiú agus iad ag cuardach an eolaire de réir spéise, liostaigh gach rud a chuireann tú spéis ann agus cuir camóg idir gach ceann. +Is fearr abairtí gearra d'fhocal amháin. Riail ginearálta: Ba cheart gur féidir an spéis a chur in abairt mar seo, "Is maith liom ________". Nuair is ainmfhocail atá i gceist, scríobh an fhoirm iolra ar son comhionnanais. "Is maith liom DVDanna" i leaba "Is maith liom DVD". +. + +/editinfo.bml.int.ex.bad=OLC Sampla: Is maith liom slám maith bannaí agus féachaint ar scannáin agus caint le cairde agus goil chuig na clubanna. Cuir an stuif sin isteach i do bheatháisnéis thuas. + +/editinfo.bml.int.ex.good=MAITH Sampla: rothaíocht, sciáil sneachta, ríomhairí, dvd-anna, mp3-anna, cáis, mná + +/editinfo.bml.int.header=Spéiseanna + +/editinfo.bml.login.enterinfo=Cuir isteach d'ainm úsáideora agus d'fhocal faire chun d'fhaisnéis phearsanta a athrú. + +/editinfo.bml.login.forgot.header=An ndearna tú dearmad ar rud éigin? + +/editinfo.bml.login.forgot.recover=Má rinne tú dearmad ar d'ainm úsáideora nó ar d'fhocal faire, faigh ar ais anseo é!. + +/editinfo.bml.logip.always=I gcónaí + +/editinfo.bml.logip.anon_only=Tráchtairí "Gan Ainm" amháin + +/editinfo.bml.logip.header=Taifeadadh seoltaí IP de dhaoine do do fhreagairt + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Má tá imní ort go bhfaighidh róbónna spaim do sheoladh ríomhphoist ar LiveJournal, roghnaigh an rogha seo agus beidh do sheoladh ríomhphoist athraithe sa chaoi nach bhfaighidh róbónna a bhailíonns seoltaí é. + +/editinfo.bml.mangleaddress.header=Ciorraigh do sheoladh ríomhphoist taispeánta + +/editinfo.bml.name.title=Ainm + +/editinfo.bml.numcomments.about=Cuir tic anseo más maith leat an áireamh tráchtanna a chur le URLanna sa chaoi go dtaispeánfaidh do bhrabhsálaí na naisc i ndath eile más féidir. + +/editinfo.bml.numcomments.header=Cuir &nc=xx le URLanna tráchta + +/editinfo.bml.optional=Roghnach + +/editinfo.bml.opt_in.about<< +Más maith leat eolas a bheith agat nuair a chuireann muid gnéithe nua le LiveJournal, cuir tic sa bhosca seo. +Is annamh a bhfaighidh tú ríomhphost uainn, ceann nó dhó sa mhí go hiondúil. +Ní bheidh do sheoladh infheicthe do na húsáideoirí eile agus is féidir é seo a chur ó fheidhm am ar bith. +. + +/editinfo.bml.opt_in.header=Seol nuacht LiveJournal chugam. + +/editinfo.bml.persinfo.disclaimer=Scríobh isteach beagán eolas fút féin, ar son ar bhfiosrachta agus staitistic. Níl sé ar intinn againn cur isteach ort nó rud dona a dhéanamh leis an eolas seo, níl uainn ach fáisnéis a fháil ar cé hiad ár n-úsáideoirí agus cá bhfuil siad. Más é do thoil é, scríobh isteach go cruinn é. Má tá tú buartha faoi, léigh ár bpolasaí príobháideachta. + +/editinfo.bml.persinfo.header=Faisnéis Phearsanta + +/editinfo.bml.screen.all=Gach uile cheann + +/editinfo.bml.screen.anon=Gan ainm + +/editinfo.bml.screen.header=Cé hiad na freagraí ar maith leat iad a cheilt mar loicrogha? + +/editinfo.bml.screen.none=Ceann ar bith + +/editinfo.bml.screen.nonfriends=Ó daoine nach do chairde iad + +/editinfo.bml.screen.nonmembers=Ó daoine nach baill iad + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=Slándáil + +/editinfo.bml.security.visibility.anybody=Duine ar bith + +/editinfo.bml.security.visibility.everybody=Gach duine + +/editinfo.bml.security.visibility.friends=Cairde amháin + +/editinfo.bml.security.visibility.regusers=Úsáideoirí Cláraithe + +/editinfo.bml.settings.friendspage.title=Teideal do Leathanach Cairde: + +/editinfo.bml.settings.friendspage.title.optional=Más maith leat, cuir isteach teideal le haghaidh do Leathanach Cairde. (HTML ar bith ceadaithe) + +/editinfo.bml.settings.header=Roghanna LiveJournal + +/editinfo.bml.settings.journal.subtitle=Fotheideal Dialainne: + +/editinfo.bml.settings.journal.subtitle.optional=Más maith leat, cuir isteach teideal agus fotheideal le haghaidh do dhialainne. (HTML ar bith ceadaithe) + +/editinfo.bml.settings.journal.title=Teideal Dialainne: + +/editinfo.bml.settings.privacy.about=Roghnaigh do socruithe príobháideachta thíos. + +/editinfo.bml.settings.privacy.header=Roghanna Príobháideachta + +/editinfo.bml.state.other=Nó, scríobh isteach stát/cúige/fearann eile + +/editinfo.bml.state.title=Stát + +/editinfo.bml.state.us=Stáit Aontaithe Mheiriceá + +/editinfo.bml.success.header=D’éirigh leat! + +/editinfo.bml.success.message=D’athraíodh d'fhaisnéis phearsanta agus socruithe do dhialainne. + +/editinfo.bml.switch.button=Tiontaigh + +/editinfo.bml.switch.header=Tiontaigh ar Dhialann eile + +/editinfo.bml.switch.workwith=Oibrigh le dialann: + +/editinfo.bml.title=Athraigh Faisnéis Phearsanta + +/editinfo.bml.tm.details=sonraí + +/editinfo.bml.tm.phonenum=Uimhir gutháin iomlán: + +/editinfo.bml.tm.sec.about=Cumasaigh teachtaireachtaí téacs (SMS) ó úsáideoirí eile. + +/editinfo.bml.tm.sec.title=Leibhéal Slándála: + +/editinfo.bml.tm.servprov=Soláthraí Seirbhíse + +/editinfo.bml.tm.title=Teachtaireachtaí Téacs (SMS) + +/editinfo.bml.translatemailto.about=Má roghnaigh tú freagraí ó na cláir teachtaireachtaí a fháil trí ríomhphost, agus ní thuigeann do chlár ríomhphoist Unicode (UTF-8) i gceart, úsáid an rogha seo chun ionchódú eile a ainmniú. Aistreoidh LiveJournal téacs i dtráchtanna seolta chugat don ionchódú seo go huathoibríoch. + +/editinfo.bml.translatemailto.header=Aistrigh fógraí ríomhphoist go: + +/editinfo.bml.unbanusers.about=Tá cosc curtha agat ar na húsáideoirí seo a leanas trácht a scríobh i do dhialann. Cuir tic sa bhosca in aice leis a n-ainmneacha úsáideora chun an cosc a bhaint díobh. + +/editinfo.bml.unbanusers.header=Bain Cosc d'Úsáideoirí + +/editinfo.bml.userpic.about=Tá an pictiúr beag a d'uaschóipeáil tú le feiceáil thíos. Féicfear an pictiúr seo mar shamhail duit ar fud an tsuímh, i do dhialainn agus i ndialanna do chairde: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Chun an pictiúr seo a scriosadh, nó ceann nua a uaschóipeáil, téigh anseo. + +/editinfo.bml.userpic.header=Do Phictiúr + +/editinfo.bml.userpic.none=íomhá ar bith uaschóipeáilte + +/editinfo.bml.webpagename.title=Ainm do Leathanach Lín + +/editinfo.bml.webpageurl.title=URL do Leathanach Lín + +/editinfo.bml.whoreply.header=Cé a bhfuil cead aige/aici freagra a thabhairt ar d'iontrálacha? + +/editinfo.bml.zip.usonly=cód ZIP (cód poist) de 5 digit; cónaitheoirí na SAM amháin + +/editjournal.bml.btn.proceed=Ar aghaidh… + +/editjournal.bml.certainday=Lá áirithe: + +/editjournal.bml.recententries=iontráil is déanaí + +/editjournal.bml.recententry=An iontráil is déanaí + +/editjournal.bml.title=Athraigh Iontrálacha + +/editjournal.bml.viewwhat=Iontrálacha le feiceáil: + +/editjournal_do.bml.body=Athraigh d’iontráíl dialainne agus brúigh ar an gcnapie sábhála ag bun an leathanaigh. Más maith leat an iontráil a scriosadh, brúigh ar an gcnapie scriosta. + +/editjournal_do.bml.btn.delete=Scrios an Iontráil + +/editjournal_do.bml.btn.edit=Athraigh an Iontráil Roghnaithe + +/editjournal_do.bml.btn.save=Sábháil an Iontráil + +/editjournal_do.bml.continue.head=Brúigh chun dul ar aghaidh… + +/editjournal_do.bml.continue.text=Roghnaigh iontráil le n-athrú no le scriosadh agus brúigh ar an gcnaipe thíos. + +/editjournal_do.bml.currmood=Fonn Reatha: + +/editjournal_do.bml.currmusic=Ceol Reatha: + +/editjournal_do.bml.date=Dáta: + +/editjournal_do.bml.default=loicrogha + +/editjournal_do.bml.delete.confirm=An bhfuil tú cinnte gur maith leat an iontráil seo a scriosadh? + +/editjournal_do.bml.edit.text=Seo í an iontráil dialainne a roghnaigh tú lena athrú.Athraigh an fhaisnéis mar is maith leat agus brúigh ar an gcnaipe "Sábháil an Iontráil" ag bun an leathanaigh.

        Chun an iontráil a scriosadh, scrios an téacs uile agus brúigh ar an gcnaipe "Sábháil an Iontráil" thíos. + +/editjournal_do.bml.error.getting=Tharla earráid ag fáil iontrálacha le n-athrú: + +/editjournal_do.bml.error.modify=Tharla earráid ag athrú do dhialann: + +/editjournal_do.bml.error.nofind=Níorbh’fhéidir an iontráil roghnaithe a aimsiú. + +/editjournal_do.bml.event=Tarlú: + +/editjournal_do.bml.localtime=Am áitiúil: + +/editjournal_do.bml.noneother=Ceann ar bith, nó ceann eile: + +/editjournal_do.bml.opt.backdate=Iontráil Chaite: + +/editjournal_do.bml.opt.backdate.about=ní taispeánfar ar leathanaigh cairde é + +/editjournal_do.bml.opt.nocomments=Ná ceadaigh Tráchtanna: + +/editjournal_do.bml.opt.noemail=Ná seol Tráchtanna: + +/editjournal_do.bml.opt.noformat=Ná formáidigh go huathoibríoch: + +/editjournal_do.bml.other=Fonn eile: + +/editjournal_do.bml.pickentry.head=Roghnaigh iontráil le n-athrú + +/editjournal_do.bml.pickentry.text=Roghnaigh iontráil le n-athrú agus brúigh ar an gcnaipe ag bun an leathanaigh. + +/editjournal_do.bml.picture=Pictiúr le n-úsáid: + +/editjournal_do.bml.save.head=Brúigh chun sábháil… + +/editjournal_do.bml.save.text=Nuair atá an iontráil athraithe agat, brúigh ar an gcnaipe thíos. + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=Ãbhar: (roghnach) + +/editjournal_do.bml.success.delete=Scriosadh an iontráil. + +/editjournal_do.bml.success.edit=Athraíodh an iontráil. Is féidir é a fheiceáil anseo. + +/editjournal_do.bml.success.head=D’éirigh leat + +/editjournal_do.bml.timeformat=Am 24 uair + +/editjournal_do.bml.title=Athraigh Iontrálacha + +/friends/add.bml.add.header=D’éirigh leat + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=Cuireadh le do liosta cairde. Is féidir do leathanach cairde a fheiceáil anseo. + +/friends/add.bml.add.title=Cara curtha leis an liosta! + +/friends/add.bml.btn.add=Cuir [[user]] le do liosta cairde + +/friends/add.bml.btn.modify=Mionathraigh + +/friends/add.bml.btn.remove=Bain den liosta + +/friends/add.bml.colors.bg=Cúlra + +/friends/add.bml.colors.fg=Réamhionad + +/friends/add.bml.colors.header=Dathanna + +/friends/add.bml.colors.hover=(Cuir do chúrsóir os cionn datha chun a ainm a thaispeáint) + +/friends/add.bml.colors.text=Féadann tú rogha a dhéanamh de dhath ar leith do [[user]] ar do liosta cairde. + +/friends/add.bml.confirm.header=Cuir [[user]] le do liosta cairde? + +/friends/add.bml.confirm.text=Chun [[user]] a chur le do liosta cairde, cliceáil ar an gcnaipe thíos. + +/friends/add.bml.confirm.title=Cara Nua + +/friends/add.bml.error1.header=Logáil Isteach + +/friends/add.bml.error1.text=Chun úsáideoir a chur le do liosta cairde, is riachtanach logáil isteach. Mura bhfuil cuntas agat cheana is féidir ceann a chruthú chun dialanna do chairde a fhaire. + +/friends/add.bml.error1.title=Cara Nua + +/friends/add.bml.error2.text=Thug tú ainm úsáideora neamhbhailí nó níor thug tú ainm úsáideora ar bith. Chun cara a chur le do liosta, téigh chuig an leathanach Athraigh Cairde. + +/friends/add.bml.error3.text=Tá [[user]] ar do liosta cairde cheana. Is féidir, áfach, na dathanna a roghnaigh tú dó/di a athrú anseo. + +/friends/add.bml.error3.title=Mionathraigh Cara + +/friends/add.bml.groups.header=Grúpaí Cairde + +/friends/add.bml.groups.nogroup=Níor shocraigh tú grúpa cairde ar bith fós. + +/friends/add.bml.groups.text=Cén grúpa cairde ar maith leat an t‑úsáideoir seo a chur ann? Is féidir grúpa cairde a úsáid chun iontrálacha ó chairde ar leith a fheiceáil, nó chun iontráil a scríobh nach féidir a léamh mura ball thú den ghrúpa ceart. + +/friends/add.bml.remove.header=D’éirigh leat + +/friends/add.bml.remove.text=Baineadh de de liosta cairde. Is féidir do leathanach cairde a fheiceáil anseo. + +/friends/add.bml.remove.title=Baineadh an cara den liosta! + +/friends/edit.bml.title=Athraigh Cairde + +/friends/editgroups.bml.btn.ge.del=Scrios + +/friends/editgroups.bml.btn.ge.new=Nua + +/friends/editgroups.bml.btn.ge.ren=Athainmnigh + +/friends/editgroups.bml.btn.gs.private=Príobháideach + +/friends/editgroups.bml.btn.gs.public=Poiblí + +/friends/editgroups.bml.btn.mv.down=Bog síos + +/friends/editgroups.bml.btn.mv.up=Bog suas + +/friends/editgroups.bml.confirm.delete=An bhfuil tú cinnte gur mhaith leat an grúpa cairde seo a scriosadh? + +/friends/editgroups.bml.done.btn=Sábháil Athruithe + +/friends/editgroups.bml.done.header=Réidh? + +/friends/editgroups.bml.done.text=Nuair atá tú réidh leis, cliceáil ar an gcnaipe thíos chun d’athruithe a shábháil. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Tá an t‑uasluach de 30 grúpa cairde sroicthe agat. Má tá grúpaí scriosta agat gan an athrú a shábháil, déan é anois, tar ar ais don leathanach seo agus athlódáil é. Beidh tú ábalta ansin grúpaí nua a chruthú. + +/friends/editgroups.bml.error.text=D’fhreagair an freastalaí leis an teachtaireacht earráide seo: + +/friends/editgroups.bml.group.public=(poiblí) + +/friends/editgroups.bml.ingroup=Sa ghrúpa: + +/friends/editgroups.bml.ingroup.not=Fágtha amuigh: + +/friends/editgroups.bml.prompt.newname=Cuir isteach an t‑ainm don ghrúpa nua cairde: + +/friends/editgroups.bml.prompt.rename=Athainmnigh an grúpa cairde seo mar: + +/friends/editgroups.bml.saved.header=Sábháilte + +/friends/editgroups.bml.saved.text=Sábháileadh do ghrúpaí cairde. + +/friends/editgroups.bml.text|staleness=1 +/friends/editgroups.bml.text=Ar an leathanach seo féadann tú do ghrúpaí cairde a athrú. Úsáidtear grúpaí cairde chun slándáil d’iontrálacha a shocrú agus scagaireacht a dhéanamh ar do leathanach cairde.Ní oibríonn an leathanach seo i gceart gan JavaScript. + +/friends/editgroups.bml.text.sec=Nóta slándála: Más maith leat grúpa a scriosadh agus grúpa nua a chruthú, ná déan é trí grúpa a athainmniú agus a athrú. Má déanann tú é seo, beidh cead ag an ngrúpa nua feiceáil gach iontráil a raibh cead ag an seanghrúpa í a fheiceáil. + +/friends/editgroups.bml.title=Athraigh Grúpaí Cairde + +/friends/editgroups.bml.yourgroups=Do ghrúpaí cairde: + +/friends/edit_do.bml.addfriends.head=Cairde Nua + +/friends/edit_do.bml.addfriends.text=Cuir isteach ainmneacha úsáideora de do chairde sna boscaí thíos agus roghnaigh na dáthanna le n‑úsáid leo… + +/friends/edit_do.bml.background=Cúlra + +/friends/edit_do.bml.bgcolor=Dath an Chúlra: + +/friends/edit_do.bml.btn.close=Dún + +/friends/edit_do.bml.btn.save=Sábháil Athruithe + +/friends/edit_do.bml.btn.toggle=Taispeáin/Dún an Fhuinneog Réamhamhairc + +/friends/edit_do.bml.done.head=Réidh? + +/friends/edit_do.bml.done.text=Nuair atá tú réidh leis, cliceáil ar an gcnaipe "Sábháil Athruithe" thíos… + +/friends/edit_do.bml.error.updating=Tharla earráid ag athrú do liosta cairde: + +/friends/edit_do.bml.fellowfriends.head=Comhchairde + +/friends/edit_do.bml.fellowfriends.text=Tá tú ar liosta cairde na ndaoine seo a leanas. B’fhéidir go bhfuil fonn ort iad a chur le do liosta cairde freisin. An aon chaoi, liostaítear iad anseo sa chaoi go bhfuil a n‑ainmneacha úsáideora agat. Níl dualgas ar bith ort áfach iad a chur le do liosta cairde. + +/friends/edit_do.bml.foreground=Réamhionad + +/friends/edit_do.bml.friend=Cara + +/friends/edit_do.bml.hover=Cuir do chúrsóir os cionn datha chun a ainm a thaispeáint + +/friends/edit_do.bml.mrcolor=An tUasal Taispeántas Mac Datha + +/friends/edit_do.bml.name=Ainm + +/friends/edit_do.bml.needmore=Má tá níos mó cairde agat ná a bhfuil spás ar an bhfoirm seo, sábháil d’athruithe agus ansin téigh ar ais agus cuir isteach an t‑iarsma. + +/friends/edit_do.bml.nofriends.head=Cara Ar Bith? + +/friends/edit_do.bml.nofriends.text=Níor shonraigh tú cara ar bith fós. Pé scéal é, tá muid cinnte go bhfuil cara nó dhó ’ad! :) Cuir isteach a n‑ainmneacha LiveJournal thíos… + +/friends/edit_do.bml.opt.delete=Scrios? + +/friends/edit_do.bml.success.head=D’éirígh leat + +/friends/edit_do.bml.success.text=Athraíodh do liosta cairde. Is féidir an liosta nua a fheiceáil anseo. + +/friends/edit_do.bml.textcolor=Dath Téacs: + +/friends/edit_do.bml.title=Athraigh Cairde + +/friends/edit_do.bml.user=Úsáideoir + +/friends/edit_do.bml.viewer=Taispeántas Dathanna + +/friends/edit_do.bml.yourfriends.head=Do Chairde + +/friends/edit_do.bml.yourfriends.text=Tá na cairde a leanas sonraithe agat faoi láthair: + +/friends/index.bml.title=Uirlisí Cairde + +/friends/popwithfriends.bml.account_type=Tá brón orainn ach ní cheadaítear don saghas cuntais atá agat an uirlis seo a úsáid. + +/index.bml.boldcreate=Cruthaigh do dhialann féin! + +/index.bml.frank.image.alt=Frank, an gadhar sonóga LiveJournal + +/index.bml.frank.logo="Máááááá", arsa Frank. + +/index.bml.meta.desc=Le LiveJournal.com is féidir do smaointe a roinnt leis an domhan. + +/index.bml.meta.keywords=dialann, dialann lín, dialanna, scríbhneoireacht, dialann ghréasáin + +/interests.bml.add.added.head=Spéis curtha leis an liosta! + +/interests.bml.add.added.text=Cuireadh an spéis le do liosta. + +/interests.bml.add.btn.text=Cuir [[interest]] le do liosta + +/interests.bml.add.confirm.head=Dearbhaigh + +/interests.bml.add.confirm.text=Chun [[interest]] a chur le do liosta spéiseanna, cliceáil ar an gcnaipe thíos. + +/interests.bml.add.toomany.head=Tá brón orainn… + +/interests.bml.add.toomany.text=Tá [[maxinterests]] sonraithe agat cheana. + +/interests.bml.addint=Má chuireann tú spéis san ábhar seo agus más maith leat bheith ar an liosta seo, cliceáil anseo. + +/interests.bml.btn.switch=Tiontaigh + +/interests.bml.communities.head=Cumainn Ãbhartha + +/interests.bml.communities.text=Cuireann na cumainn seo a leanas spéis in “[[interest]]â€. + +/interests.bml.count=Ãireamh + +/interests.bml.enmasse.body.other=Tá spéiseanna an úsáideora [[user]] thíos. Cuir tic sna boscaí in aice leis na spéiseanna gur mhaith leat a chur le do liosta féin, agus bain an tic de na boscaí in aice leis na speiseanna gur maith leat a bhaint de do liosta féin. Nuair atá tú réidh leis, cliceáil ar “Sábháil Athruitheâ€. + +/interests.bml.enmasse.body.other_authas=Tá spéiseanna an úsáideora [[user]] thíos. Cuir tic sna boscaí in aice leis na spéiseanna gur mhaith leat a chur le liosta [[target]], agus bain an tic de na boscaí in aice leis na speiseanna gur maith leat a bhaint den a liosta. Nuair atá tú réidh leis, cliceáil ar “Sábháil Athruitheâ€. + +/interests.bml.enmasse.body.you=Bain an tic de na boscaí in aice leis na spéiseanna gur mhaith leat a bhaint de do liosta. Nuair atá tú réidh leis, cliceáil ar “Sábháil Athruitheâ€. + +/interests.bml.enmasse.btn=Taispeáin liosta + +/interests.bml.enmasse.header=Cuir le/Bain de liosta spéiseanna + +/interests.bml.enmasse.intro=Athraigh do liosta spéiseanna de réir liosta: + +/interests.bml.error.add.mustlogin=Is riachtanach logáil isteach chun spéis a chur le do liosta. + +/interests.bml.error.findsim_do.intnotfound=Ní bhfuarthas an spéis. + +/interests.bml.findsim.searchwait=Tabhair faoi deara: Tógfaidh an cuardach cúpla soicind. Bíodh foighid agat. + +/interests.bml.findsim_do.account.notallowed=Tá brón orainn, ní cheadaítear don saghas cuntais atá agat an uirlis seo a úsáid. + +/interests.bml.findsim_do.magic=Innéacs
        Draíochtach + +/interests.bml.findsim_do.magic.head=Innéacs Draíochtach? + +/interests.bml.findsim_do.magic.text=Ríomhtar innéacs draíochtach do gach úsáideoir comhoiriúnach. Séard atá ann ná an t-áireamh spéiseanna cosúla agus tuilleadh pointí le haghaidh spéiseanna neamhchoitianta a pháirtíonn na húsáideoirí. + +/interests.bml.findsim_do.nomatch.head=Ní bhfuarthas dada + +/interests.bml.findsim_do.nomatch.text=Níl úsáideoir ann atá cosúil le [[user]]. + +/interests.bml.findsim_do.notdefined=Níor sonraigh [[user]] spéis ar bith. + +/interests.bml.findsim_do.similar.head=Úsáideoirí Cosúla + +/interests.bml.findsim_do.similar.text=Seo iad na húsáideoirí is cosúla le [[user]] + +/interests.bml.interest=Spéis + +/interests.bml.interested.btn.find=Cuardaigh + +/interests.bml.interested.in|staleness=1 +/interests.bml.interested.in=Cuardaigh daoine a chuireann spéis in: + +/interests.bml.interests.head=Spéiseanna + +/interests.bml.interests.text=Seo duit cúpla rud spórtúil le déanamh le spéiseanna. + +/interests.bml.interests.viewpop=Féach spéiseanna coitianta + +/interests.bml.match=ceann amháin: + +/interests.bml.matches=[[count]] cinn: + +/interests.bml.morestuff=Tá níos mó stuif spraoi le fáil ar leathanach na spéiseanna. + +/interests.bml.nointerests.text=An bhfuil spéis ar bith liostaithe agat? Cuir spéiseanna le do liosta ag an leathanach Faisnéis Phearsanta . + +/interests.bml.popular.head=Spéiseanna Coitianta + +/interests.bml.popular.text=Seo iad na speiseanna is coitianta. + +/interests.bml.title=Spéiseanna + +/interests.bml.toomany.body=Tá [[intcount]] daoine/cumainn a chuireann spéis san ábhar seo. Ní taispeánfar liosta. + +/interests.bml.toomany.head=An iomarca torthaí + +/interests.bml.users.head=Úsáideoirí a chuireann spéis ann + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=Cuireann na húsáideoirí seo a leanas spéis in [[interest]] freisin. + +/legal/index.bml.about<< +Caitheann LiveJournal a dhúthracht le taithí seasmhach éifeachtach a thairscint do bhaill ó gach cúlra agus gach tír, agus mar sin tá cúpla riail leagtha amach againn chun é seo a chinntiú. +Tá téarmaí réasúnta agus faisnéis faoin gcaoi a ndéanann muid ár ndícheall ag freastail ort, agus faoin iompar is béasaíocht a bhfuil muid ag braith orthu dúinne agus d’úsáideoirí eile le fáil inár gcáipéisí anseo. Bíonn LiveJournal ag oibriú sa chaoi is fearr nuair a leanann daoine na rialacha seo. Seo iad na cinn is tábhachtaí: +
          +
        • Ná ciap, ná maslaigh is ná bagraigh daoine eile.
        • +
        • Ná déan dóchar ar bith do mhionaoisigh.
        • +
        • Ná seol spam chuig an suíomh nó chuig cuntas ar bith ar an suíomh.
        • +
        • Ná cuir ábhar a bhfuil coipcheart air ar an suíomh gan cead a fháil.
        • +
        • Ná cuir isteach ar phríobháideacht duine eile.
        • +
        • Ná bris dlíonna na S.A.M. nó do dhlíonna áitiúla ar chaoi ar bith.
        • +
        +Tá an liosta iomlán rialacha agus polasaithe le fáil thíos: +. + +/legal/index.bml.about.header=Achoimre + +/legal/index.bml.docs.coppa.about=Rialaíonn The Children's Online Privacy Protection Act (COPPA) (an tAcht um Chosaint Phríobháideacht na Leanaí ar an Líon) bailiú agus úsáid fhaisnéis phearsanta ó nó faoi leanaí níos óige ná trí bliana déag d’aois. Tá míniúchán ár ndearcaidh ar an ndlí seo le fáil ar ár leathanach COPPA agus tá achoimre ann freisin ar láimhseáil ceistanna COPPA. + +/legal/index.bml.docs.header=Cáipéisí + +/legal/index.bml.docs.privacy.about=Míníonn an Polasaí Príobháideachta cén fhaisnéis a bhailíonn muid ónár mbaill agus cén chaoi a n‑úsáideann muid an fhaiséis sin. + +/legal/index.bml.docs.tos.about=Míníonn na Téarmaí Seirbhíse ár bpolasaí úsáide, chomh maith le téarmaí agus coinníollacha ginearálta na ballraíochta. Comhdhéanann ballraíocht agus/nó úsáid an chórais comhaontú leis na téarmaí seo agus le gach téarmaí socraithe eile. + +/legal/index.bml.title=Faisnéis faoin nDleachtanas + +/legal/privacy.bml.title=Polasaí Príobháideachta + +/legal/tos.bml.title=Téarmaí Seirbhíse + +/login.bml.bindip.label=Ceangail den sheoladh IP: + +/login.bml.bindip.no=Ná ceangail (oibríonn sé le gach ISP) + +/login.bml.bindip.yes=Ceangail (níos sláine) + +/login.bml.error.mustenterusername=Caithfidh tú ainm úsáideora a chur isteach. + +/login.bml.expire.btn.neverexpire=Athraigh an mód éaga go BUAN + +/login.bml.expire.btn.sessiononly=Athraigh an mód éaga go SEISIÚN AMHÃIN + +/login.bml.expire.neverexpire.text=Ní éagfaidh do chónasc choíche agus mar sin má tá tú ar inneall idirlín poiblí, i scoil, i leabharlann, nó in áit poiblí eile a mbeidh daoine eile ann ag úsáid an ríomhaire seo go tapaidh, féach chuige go logálann tú amach nuair atá tú déanta! Nó athraigh an mód éaga sa chaoi go n‑éagann do chónasc nuair a dhúnann tú do bhrabhsálaí: + +/login.bml.expire.sessiononly.text=Éagfaidh do chónasc tar éis dúnadh do bhrabhsálaí. Más é seo do ríomhaire féin agus más tusa an t‑aon duine dhá úsáid, b’fhéidir gur maith leat an mód éaga a athrú sa chaoi nach n‑éagfaidh do chónasc choíche: + +/login.bml.links.head=Naisc + +/login.bml.links.link1=Do leathanach cairde. + +/login.bml.links.link2=Do liosta ‘le déanamh’. + +/login.bml.links.text=Lá éigin beidh ’chuile shórt de nasc agus faisnéis ábhartha le fáil ar an leathanach seo, ach anois seo duit cúpla áit gurbh’fhearr cuairt a thabhairt orthu: + +/login.bml.loggedin.head=Logáilte isteach! + +/login.bml.loggedin.text=Logáil tú isteach. + +/login.bml.login.btn.changeopts=Athraigh Roghanna + +/login.bml.login.btn.login=Logáil isteach… + +/login.bml.login.expiration=Éag: + +/login.bml.login.forget=Dearmadta? + +/login.bml.login.head=Logáil isteach + +/login.bml.login.never=Ná héag choíche + +/login.bml.login.otheropts=Roghanna Eile: + +/login.bml.login.password=Focal Faire: + +/login.bml.login.text1=Chun logáil isteach i [[sitename]], cuir isteach d’ainm úsáideora agus d’fhocal faire thíos. Úsáideoirí Nua: Chun cuntas nua a chruthú, téigh anseo. + +/login.bml.login.text2|staleness=1 +/login.bml.login.text2=Is féidir sonrú cén uair a n‑éagfaidh do chónasc. De loicrogha, éagann do chónasc nuair a dhúnann tú do bhrabhsálaí; an rogha is fearr ar ríomhairí poiblí. Ach más tusa an t‑aon úsáideoir amháin ar an ríomhaire seo agus mura bhfuil teacht ag aon duine eile air, tá rogha eile agat—cónasc buan nach n‑éagfaidh choíche. + +/login.bml.login.username=Ainm Úsáideora: + +/login.bml.login.whenbrowsercloses=Nuair a dhúnann an brabhsálaí + +/login.bml.logout.btn=Logáil Amach + +/login.bml.title=Logáil isteach + +/login.bml.whylogin.benefit1=Ní bheidh ort d’ainm úsáideora/d’fhocal faire a chur isteach áit ar bith eile ar an suíomh. + +/login.bml.whylogin.benefit2=Féadfaidh tú iontrálacha “cosanta†do chairde a fheiceáil má thug siad cead duit iad a léamh. + +/login.bml.whylogin.benefit3=Is iomaí feidhmeanna nach bhfuil le feiceáil nó le n‑úsáid gan logáil isteach. + +/login.bml.whylogin.head=Logáil isteach? Cén fáth? + +/login.bml.whylogin.text=Seo iad na príomhbhuntáistí: + +/logout.bml.already.head=Logáilte amach cheana + +/logout.bml.already.text=Tá tú logáilte amach cheana + +/logout.bml.loggedout.head=Logáilte amach + +/logout.bml.loggedout.text=Logáil tú amach. + +/logout.bml.title=Logáil amach + +/lostinfo.bml.btn.proceed=Ar aghaidh + +/lostinfo.bml.enter_email=Cuir isteach do sheoladh ríomhphoist: + +/lostinfo.bml.enter_email_optional=Seoladh ríomhphoist: (roghnach) + +/lostinfo.bml.enter_username=Cuir isteach d'ainm úsáideora: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Má chaill tú d’fhocal faire, cuir isteach d’ainm úsáideora agus, más maith leat, an seoladh ríomhphoist ar maith leat go seolfaí an focal faire chuige. Tabhair faoi deara gur riachtanach gur seoladh ríomhphoist é a bhí (nó atá) in úsáid agat do LiveJournal agus gur dheimhnigh LiveJournal é cheana. Mura chuireann tú seoladh isteach, seolfar d’fhocal faire chuig do sheoladh reatha. + +/lostinfo.bml.lostpassword.title=Ar chaill tú d’fhocal faire? + +/lostinfo.bml.lostusername.text=Má chaill tú d’ainm úsáideora, cuir isteach do sheoladh ríomhphoist agus seolfaidh muid d'ainm úsáideora chugat. + +/lostinfo.bml.lostusername.title=Ar chaill tú d’ainm úsáideora? + +/lostinfo.bml.title=Eolas Caillte + +/lostinfo_do.bml.error.no_usernames_for_email=Ní bhfuarthas ainm úsáideora ar bith don seoladh ríomhphoist seo: [[address]]. + +/lostinfo_do.bml.error1.text=Ní raibh an seoladh ríomhphoist in úsáid agat leis an gcuntas seo riamh nó níor dheimhníodh é riamh. + +/lostinfo_do.bml.password_mailed.text=D’éirigh leat. Seoladh d’fhocal faire chugat. + +/lostinfo_do.bml.password_mailed.title=Focal Faire seolta! + +/lostinfo_do.bml.title=Eolas Caillte + +/lostinfo_do.bml.username_mailed.text=D’éirigh leat. Seoladh d’ainm úsáideora chugat. + +/lostinfo_do.bml.username_mailed.title=Ainm Úsáideora seolta! + +/manage/siteopts.bml.btn.lang=Athraigh Teanga + +/manage/siteopts.bml.btn.scheme=Athraigh Scéim + +/modify_do.bml.journalstatus.select.deleted=Scriosta + +/paidaccounts/index.bml.costs.header=Bhuel anois, cé mhéad atá air? + +/paidaccounts/index.bml.costs.rates=Tá na rátaí mar a leanas: + +/paidaccounts/index.bml.costs.rates.amount.header=Méid + +/paidaccounts/index.bml.costs.rates.inexpensive=Sin beagán níos mó ná $2 sa mhí thar bliain. Níl dócha go scriosfadh sé do bhuiséad. Is é an crá is mó a mbeadh ort ná do vallait a thabhairt amach, do chárta creidmheasa a fháil agus do chuid eolais a chlóscríobh isteach. + +/paidaccounts/index.bml.costs.rates.time.header=Tréimhse + +/site/goat.bml.image.alt=Frank, an gadhar sonóga LiveJournal + +/site/goat.bml.image.caption="Máááááá", arsa Frank. + +/site/goat.bml.title=Frank an Gadhar + +/suggestions/index.bml.info.title=Eolas Eile + +/support/faqbrowse.bml.backfaq=Ar ais do na Ceisteanna Coitianta (FAQ). + +/support/faqbrowse.bml.backsupport=Ar ais do na leathanaigh thacaíochta. + +/support/faqbrowse.bml.lastupdated=Athrú Deireannach: + +/talkpost.bml.allowedhtml=HTML ceadaithe + +/talkpost.bml.error.cannotreplynopost=Ní féidir freagra a thabhairt ar theachtaireacht nach bhfuil ar fáil + +/talkpost.bml.error.nocommentsjournal=Díchumasaigh an t‑úsáideoir tráchtanna ina d(h)ialann + +/talkpost.bml.error.nocommentspost=Díchumasaigh an t‑úsáideoir tráchtanna ar an iontráil seo. + +/talkpost.bml.error.noreplypost=Ní bhfuarthas an bhunteachtaireacht (scriosta?) + +/talkpost.bml.error.noreply_screened=Tá an trácht seo ceilte agus níl cead agat é a fheiceáil ná é a freagairt. + +/talkpost.bml.label.picturetouse=  Pictiúr le n‑úsáid:  + +/talkpost.bml.loganonip=Fógra! Chuir an t‑úsáideoir seo an rogha ann a thaifeadanns an seoladh IP de thráctairí "Gan Ainm". + +/talkpost.bml.loginq=Logáil isteach? + +/talkpost.bml.logyourip=Fógra! Chuir an t‑úsáideoir seo an rogha ann a thaifeadanns do sheoladh IP nuair a scríobhann tú trácht. + +/talkpost.bml.nosubjecthtml=Ní féidir HTML a scríobh san ábhar + +/talkpost.bml.opt.anonymous=Gan Ainm + +/talkpost.bml.opt.defpic=(loicrogha) + +/talkpost.bml.opt.friendsonly=- díchumasaigh an t‑úsáideoir seo tráchtanna "Gan Ainm" nó tráchtanna ó dhaoine nach cairde iad. Féadann tú trácht a scríobh anseo má tá tú ar liosta cairde [[username]]. + +/talkpost.bml.opt.from=Ó: + +/talkpost.bml.opt.ljuser=Úsáideoir eile LiveJournal: + +/talkpost.bml.opt.loggedin=Úsáideoir reatha: [[username]] + +/talkpost.bml.opt.message=Teachtaireacht: + +/talkpost.bml.opt.noanonpost=- díchumasaigh an t‑úsáideoir seo tráchtanna "Gan Ainm". + +/talkpost.bml.opt.noautoformat=Ná formáidigh go huathoibríoch: + +/talkpost.bml.opt.noimage=Gan Ãomhá + +/talkpost.bml.opt.preview=Réamhamharc + +/talkpost.bml.opt.spellcheck=Deimhnigh litriú (Béarla) na hiontrála roimh a seoladh + +/talkpost.bml.opt.subject=Ãbhar: + +/talkpost.bml.opt.submit=Seol Trácht + +/talkpost.bml.paraformat=Is é an loicrogha go bhformáideofar paragraif go huathoibríoch. + +/talkpost.bml.postresponse=Scríobh trácht mar fhreagra: + +/talkpost.bml.title=Scríobh Trácht + +/talkpost.bml.warnscreened=Fógra: Tá an trácht seo ceilte. Má scríobhann tú freagra air, ní bheidh sé ceilte níos mó. + +/talkpost_do.bml.error.badpassword=Níor thug tú an focal faire ceart don ainm úsáideora seo. Is féidir d'fhocal faire a fháil ar ais anseo má rinne tú dearmad air. + +/talkpost_do.bml.error.badusername=Níl an t‑ainm úsáideora a chuir tú isteach ar fáil i LiveJournal. Is féidir d'ainm úsáideora a fháil ar ais anseo má rinne tú dearmad air, nó is féidir teachtaireacht "Gan Ainm" a scríobh. + +/talkpost_do.bml.error.banned=Níl cead agat trácht a scríobh i ndialann an úsáideora seo. + +/talkpost_do.bml.error.blankmessage=Bhí do theactaireacht folamh. Le do thoil, clóscríobh rud éigin sa bhosca teachtaireachta. + +/talkpost_do.bml.error.confused_identity=Chuir tú ainm úsáideora isteach, ach roghnaigh tú teachtaireacht "Gan Ainm" nó teachtaireacht ón úsáideoir reatha a scríobh. Téigh ar ais agus déan an rogha is fearr leat. + +/talkpost_do.bml.error.deleted=Scriosadh do dhialann. Ní féidir leat teachtaireachtaí a scríobh. + +/talkpost_do.bml.error.friendsonly=Tá cead ag cairde [[user]] amháin scríobh sa dialann seo. + +/talkpost_do.bml.error.lostcookie=Níl do chuach logála le fáil! + +/talkpost_do.bml.error.manybytes=Gabh mo leithscéal, ach tá do thrácht de [[current]] beart níos faide ná an fad uasluacha de [[limit]] beart. Le do thoil, téigh ar ais, giorraigh é agus bain triail as arís. + +/talkpost_do.bml.error.manychars=Gabh mo leithscéal, ach tá do thrácht de [[current]] carachtar níos faide ná an fad uasluacha de [[limit]] carachtar. Le do thoil, téigh ar ais, giorraigh é agus bain triail as arís. + +/talkpost_do.bml.error.mustlogin=Is riachtanach go bhfuil tú logáilte isteach chun freagra a scríobh don iontráil chosanta seo. + +/talkpost_do.bml.error.noanon=Ní féidir leat tráchtanna "Gan Ainm" a scríobh i ndialann an duine seo. + +/talkpost_do.bml.error.noauth=Níl cead agat freagra a thabhairt ar an iontráil chosanta seo. + +/talkpost_do.bml.error.nocomments=Díchumasaigh an t‑úsáideoir tráchtanna ar an iontráil seo. + +/talkpost_do.bml.error.noparent=Ní féidir freagra a scríobh ar trácht nach bhfuil ann. + +/talkpost_do.bml.error.notafriend=Gabh mo leithscéal, níl tú ar liosta cairde [[user]] agus rinne an t‑úsáideoir sin rogha gur féidir lena c(h)airde amháin freagraí a thabhairt ar iontrálacha ina d(h)ialann. + +/talkpost_do.bml.error.nousername=Níor chuir tú d'ainm úsáideora isteach. Is féidir leat tráchtanna "Gan Ainm" a scríobh mura bhfuil cuntas LiveJournal agat. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Gabh mo leithscéal, níl cead agat tráchtanna a scríobh i ndialanna daoine eile sula ndeimhnítear do sheoladh ríomhphoist. Má chaill tú an ríomhphost deimhnithe, is féidir é a athsheoladh trí cuairt a thabhairt ar an leathanach eolais chaillte. + +/talkpost_do.bml.error.postshared=Ní féidir teachtaireachtaí a scríobh le cuntas comhpháirteach nó cuntas cumainn. Feidhmíonn cuntais chomhpháirteacha ar son dreamanna, in aonad daoine ar leith. + +/talkpost_do.bml.error.screened=Níl cead agat freagra a scríobh ar an trácht ceilte seo. + +/talkpost_do.bml.error.suspended=Chuir do dhialann ar fionraí. Ní féidir leat tráchtanna a scríobh. + +/talkpost_do.bml.error.testacct=Ní féidir cuntas teiste a úsáid ach i ndialanna teiste. + +/talkpost_do.bml.opt.preview=Réamhamharc + +/talkpost_do.bml.preview=Seo an cuma a mbeidh ar do thrácht. Is féidir é a athrú san fhoirm thíos nó é a sheoladh mar atá. + +/talkpost_do.bml.preview.subject=Ãbhar: + +/talkpost_do.bml.preview.submit=Seol + +/talkpost_do.bml.preview.title=Réamhamharc + +/talkpost_do.bml.success.loggedin=Tá tú logáilte isteach anois. + +/talkpost_do.bml.success.message=Taifeadadh do thrácht. Is féidir é a fheiceáil anseo. + +/talkpost_do.bml.success.screened.comm=Sábháileadh do thrácht. De réir socruithe an chumainn seo, ceileadh é agus ní fheicfidh duine é ach tú féin agus coimeádaithe an chumainn sula socróidh siad é a nochtú. Féadann tú do thrácht a fheiceáil anseo. + +/talkpost_do.bml.success.screened.user=Sábháileadh do thrácht. De réir socruithe na dialainne seo, ceileadh é agus ní fheicfidh duine é ach tú féin agus úinéir na dialainne sula socróidh an t‑úinéir é a nochtú. Féadann tú do thrácht a fheiceáil anseo. + +/talkpost_do.bml.success.title=D'éirígh leat + +/talkpost_do.bml.success.unscreened=Nochtadh an trácht ceilte a fhreagair tú agus tá sé le feiceáil anois. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Scríobh Trácht + +/talkread.bml.anonuser=(Gan Ainm) + +/talkread.bml.deletedpost=(Teachtaireacht scriosta) + +/talkread.bml.deleteduser=(Úsáideoir scriosta: [[username]]) + +/talkread.bml.fromip=(ó [[ip]]) + +/talkread.bml.noreplies=Gan freagra + +/talkread.bml.nosubject=(gan ábhar) + +/talkread.bml.replysuspended=(Freagra ó úsáideoir ar fionraí) + +/talkread.bml.screenedpost=(Teachtaireacht Cheilte) + +/talkread.bml.select=Roghnaigh + +/talkread.bml.subjectdeleted=[scriosta] + +/talkread.bml.talkmulti.delete=Scrios + +/talkread.bml.talkmulti.des=Gníomh le déanamh ar tráchtanna roghnaithe: + +/talkread.bml.talkmulti.screen=Ceil + +/talkread.bml.talkmulti.submit=Déan + +/talkread.bml.talkmulti.unscreen=Taispeáin + +/talkread.bml.title=Léigh Tráchtanna + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=D’athraíodh do liosta iontrálacha le cuimhneamh. + +/tools/memadd.bml.body.added.header=D’éirigh leat + +/tools/memadd.bml.description=Cur síos: + +/tools/memadd.bml.description.text<< +Déan cur síos ar an iontráil seo go gcuimhnóidh tú í. +Chun an iontráil seo a bhaint de do liosta iontrálacha le cuimhneamh, fág an cur síos folamh. +. + +/tools/memadd.bml.error.deleted.body=Baineadh an iontráil “[[desc]]†de do liosta iontrálacha le cuimhneamh. + +/tools/memadd.bml.error.deleted.title=Scriosadh an Cuimhne. + +/tools/memadd.bml.error.entry_deleted=Níl an iontráil ann fós. Scriosadh an Cuimhne. + +/tools/memadd.bml.error.fivekeywords=Ní féidir ach 5 threoirfhocal/chatagóir a úsáid i gcur síos ar iontráil le cuimhneamh. + +/tools/memadd.bml.error.invalid_security=Níor chuir tú isteach rogha slándála bhailí. + +/tools/memadd.bml.error.login=Caithfidh tú logáil isteach chun an gné seo a úsáid. Logáil isteach agus tabharfar ar ais anseo thú. + +/tools/memadd.bml.error.maxsize=Tá an treoirfhocal seo níos faide ná an fad ceadaithe: “[[keyword]]†+ +/tools/memadd.bml.error.nodescription.body<< +Chun iontráil a chur le do liosta cuimhní, caithfidh tú cur síos a dhéanamh uirthi. +Chun cuimhne a scriosadh, níl ort ach an cur síos a bhaint de, ach ní raibh an iontráil seo ar do liosta cuimhní cheana. +. + +/tools/memadd.bml.error.nodescription.title=Gan Chur Síos + +/tools/memadd.bml.form.submit=Seol + +/tools/memadd.bml.keywords=Treoirfhocail: + +/tools/memadd.bml.keywords.example=Sampla: Greannmhar, Cabaireacht, Rómánsach + +/tools/memadd.bml.keywords.select=Is féidir roghnú treoirfhocail a d’úsáid tú roimhe seo freisin: + +/tools/memadd.bml.keywords.text=Cén fáth gur fiú an iontráil seo a chuimhneamh? Cuir isteach suas le cúig threoirfhocail nó chatagóir (le camóga eatartha) go n‑aimseoidh tú í amach anseo. + +/tools/memadd.bml.login.enterinfo=Cuir isteach an t‑ainm úsáideora agus an focal faire den chuntas gur maith leat an chuimhne a shábháil ann. + +/tools/memadd.bml.login.forgot.header=An ndearna tú dearmad ar rud éigin? + +/tools/memadd.bml.login.forgot.recover=Má rinne tú dearmad ar d’ainm úsáideora nó ar d’fhocal faire, faigh ar ais anseo é!. + +/tools/memadd.bml.multiple_selections=Brúigh an cnaipe ‘Control’ agus cliceáil ar treoirfhocail chun níos mó ná ceann amháin a roghnú. + +/tools/memadd.bml.security=Slándáil: + +/tools/memadd.bml.security.friendsonly=Cairde Amháin + +/tools/memadd.bml.security.private=Príobháideach + +/tools/memadd.bml.security.public=Poiblí + +/tools/memadd.bml.title=Cuir le Cuimhní + +/tools/memadd.bml.title.added=Iontráil curtha le do chuimhní + +/tools/memadd.bml.title.add_memory=Iontráil le Cuimhneamh + +/tools/memadd.bml.title.deleted=Scriosta + +/tools/memadd.bml.title.edit_memory=Athraigh Iontráil le Cuimhneamh + +/tools/memadd.bml.whocansee<< +Cé a fheicfidh gur iontráil le cuimhneamh í seo? +Gach uile dhuine, daoine a bhfuil ar do liosta cairde, nó tú féin amháin? +. + +/tools/memories.bml.back=Ar Ais + +/tools/memories.bml.body.keyword<< + +[[user]] gur fiú a gcuimhneamh. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] iontrálacha le cuimhneamh iontu. p?> +. + +/tools/memories.bml.body.memorable=Seo é liosta d’iontralacha gan treoirfhocal a shíleann an t‑úsáideoir [[user]] gur fiú a gcuimhneamh. + +/tools/memories.bml.edit=athraigh + +/tools/memories.bml.error.noentries.body<< +Seans go bhfuil ceann de na cúiseanna seo taobh thiar de:
          +
        1. níor shonraigh an t‑úsáideoir cuimhne ar bith,
        2. +
        3. tá cuimhní an úsáideora cosanta agus níl cead agat iad a fheiceáil, nó
        4. +
        5. níl cuimhní le fáil faoi na critéir scagaireachta a thug tú.
        +. + +/tools/memories.bml.error.noentries.title=Ní bhfuarthas cuimhne ar bith. + +/tools/memories.bml.filter.all=Gach cuimhne + +/tools/memories.bml.filter.other=Iontrálacha eile + +/tools/memories.bml.filter.own=Iontrálacha ‘[[user]]’ + +/tools/memories.bml.form.filter=Scagaireacht: + +/tools/memories.bml.form.sort=Sórtáil: + +/tools/memories.bml.form.switch=Tiontaigh + +/tools/memories.bml.sort.description=Cur Síos + +/tools/memories.bml.sort.journal=Dialann + +/tools/memories.bml.sort.orderadded=Ord Curtha Isteach + +/tools/memories.bml.title.keyword=Iontráil le Cuimhneamh: [[keyword]] + +/tools/memories.bml.title.memorable=Iontráil le Cuimhneamh + +/tools/memories.bml.uncategorized=Gan treoirfhocal + +/update.bml.altpost=Dialann le n‑úsáid: + +/update.bml.btn.update=Sábháil Iontráil + +/update.bml.currmood=Fonn Reatha:  + +/update.bml.currmusic=Ceol Reatha: + +/update.bml.date=Dáta: + +/update.bml.default=loicrogha + +/update.bml.defaultjournal=([[user]]) — loicrogha + +/update.bml.error.login=Earráid ag logáil isteach: + +/update.bml.error.update=Earráid ag sábháil iontráil: + +/update.bml.event=Tarlú: + +/update.bml.full=Leathanach de Lán-Roghanna + +/update.bml.localtime=Am áitiúil: + +/update.bml.loggingin=Ag logáil isteach don fhreastalaí… + +/update.bml.noneother=Ceann ar bith, nó ceann eile: + +/update.bml.note|staleness=1 +/update.bml.note=Tabhair faoi deara: Tagann an t‑am/dáta thuas ón ár bhfreastalaí. Ceartaigh iad de réir do chrios ama roimh shábháil do theachtaireachta. + +/update.bml.opt.backdate=Iontráil Chaite: + +/update.bml.opt.backdate.about=ní taispeánfar ar leathanaigh cairde é + +/update.bml.opt.defpic=(loicrogha) + +/update.bml.opt.nocomments=Ná ceadaigh Tráchtanna: + +/update.bml.opt.noemail=Ná seol Tráchtanna: + +/update.bml.opt.noformat=Ná formáidigh go huathoibríoch: + +/update.bml.opt.spellcheck=Deimhnigh litriú (Béarla) na hiontrála roimh a seoladh + +/update.bml.options=Socruithe Roghnach + +/update.bml.other=Fonn eile: + +/update.bml.picture=Pictiúr le n-úsáid: + +/update.bml.security.custom=Speisialta… + +/update.bml.security.friends=Cairde + +/update.bml.security.head=Leibhéal Slándála: + +/update.bml.security.private=Príobháideach + +/update.bml.security.public=Poiblí + +/update.bml.servermsg=Seo teachtaireacht duit ón bhfreastalaí: + +/update.bml.simple=Seo an leathanach simplí. Má tá níos mó roghanna uait cliceáil anseo. + +/update.bml.spellchecked=Do theactaireacht i ndiaidh a deimhniú: + +/update.bml.subject|staleness=1 +/update.bml.subject=Ãbhar: (roghnach) + +/update.bml.timeformat=Am 24 uair + +/update.bml.title=Iontráil Nua + +/update.bml.title.readonly=Mód léamh amháin + +/update.bml.update.head=Scríobh Iontráil Nua… + +/update.bml.update.success=D’éirigh leat. Is féidir do dhialann athraithe le feiceáil anseo. + +/update.bml.updating=Ag athrú na dialainne… + +/userinfo.bml.about.comm=Faisnéis: + +/userinfo.bml.about.user=Beathaisnéis: + +/userinfo.bml.body.leave=Is féidir an cumann a fhágáil am ar bith. + +/userinfo.bml.comminfo.body=Tá faisnéis thíos faoin gcumann “[[commname]]†ar LiveJournal. + +/userinfo.bml.comminfo.name=Faisnéis faoin gCumann + +/userinfo.bml.date.never=Riamh. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Ainm úsáideora mícheart. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Ag féachaint air: + +/userinfo.bml.friendof.hidden=(ceilte) + +/userinfo.bml.friendof.syndreadcount=Léitheoirí + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Cara le: + +/userinfo.bml.friends.comm=Baill + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Cairde + +/userinfo.bml.label.addbuddy=Cuir Buddy le liosta AIM + +/userinfo.bml.label.adduser=Cuir Úsáideoir le liosta ICQ + +/userinfo.bml.label.aolim= AOL IM: + +/userinfo.bml.label.birthdate=Dáta Breithe: + +/userinfo.bml.label.clientsused=Úsáideadh na cliaint seo: + +/userinfo.bml.label.comments=Tráchtanna: + +/userinfo.bml.label.composted=Scríofa: [[num]] — + +/userinfo.bml.label.comreceived=Faighte: [[num]] + +/userinfo.bml.label.datecreated=Cruthaíodh: + +/userinfo.bml.label.dateupdated=Athraíodh: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=Ríomhphost: + +/userinfo.bml.label.icquin= ICQ UIN: + +/userinfo.bml.label.interests=Spéiseanna + +/userinfo.bml.label.interests.modifyyours=Athraigh do chinnsa + +/userinfo.bml.label.interests.removesome=Bain cinn de + +/userinfo.bml.label.intsnotshown=… [[intnotshown]] spéis nach taispeántar + +/userinfo.bml.label.jabber= Jabber: + +/userinfo.bml.label.journalentrs=Iontrálacha: + +/userinfo.bml.label.location=Láthair: + +/userinfo.bml.label.memberof=Ball de + +/userinfo.bml.label.memories=Cuimhní: + +/userinfo.bml.label.moredetails=(níos mó…) + +/userinfo.bml.label.msnusername=Ainm Úsáideora MSN: + +/userinfo.bml.label.name=Ainm: + +/userinfo.bml.label.nofriends=Ní liostaítear cara ar bith. + +/userinfo.bml.label.reqfinduser=Ní féidir úsáideoirí a aimsiú ar userid gan an cead (priv) 'finduser' a bheith agat. + +/userinfo.bml.label.sendmessage=Seol Teachtaireacht + +/userinfo.bml.label.shared|staleness=2 +/userinfo.bml.label.shared=Ceadanna i nDialanna Comhpháirteacha: + +/userinfo.bml.label.supportpoints=Pointí tacaíochta + +/userinfo.bml.label.syndicatedfrom=Comhfhoilsithe ó: + +/userinfo.bml.label.syndicatedstatus=Stádas Comhfhoilsithe: + +/userinfo.bml.label.textmessage=Teachtaireacht
        Téacs
        : + +/userinfo.bml.label.todo=Liosta ‘Le Déanamh’ + +/userinfo.bml.label.user=Úsáideoir: + +/userinfo.bml.label.viewfriends=Féach Cairde + +/userinfo.bml.label.viewmembers=Féach Baill + +/userinfo.bml.label.website=Leathanach Lín: + +/userinfo.bml.label.yahooid= Yahoo! ID: + +/userinfo.bml.membership.body=Chun clárú mar bhall an chumainn seo, cliceáil anseo. + +/userinfo.bml.memories.entries=[[count]] iontráil + +/userinfo.bml.memories.entry=iontráil amháin + +/userinfo.bml.monitor.comm=Fair Cumann + +/userinfo.bml.monitor.user=Cuir an t-úsáideoir seo le do liosta cairde + +/userinfo.bml.nonexist.body=Níl an t-ainm úsáideora [[user]] cláraithe faoi láthair. + +/userinfo.bml.nonexist.name=Úsáideoir anaithnid + +/userinfo.bml.sendmessage.body=Seol teachtaireacht téacs chuig [[user]]
        ar a g(h)uthán póca/g(h)laoire. + +/userinfo.bml.syn.last.never=Riamh + +/userinfo.bml.syn.lastcheck=Seiceáil dheireannach: + +/userinfo.bml.syn.nextcheck=An chéad sheiceáil eile: + +/userinfo.bml.syn.parseerror=Earráid: + +/userinfo.bml.syndinfo.body=Más maith leat go dtaispeánfar ailt ón suíomh comhfhoilsithe ar do leathanach cairde, is féidir an dialann seo a chur le do liosta cairde. + +/userinfo.bml.syndinfo.name=Dialann Comhfhoilsithe + +/userinfo.bml.tellafriend=Cuir scéala faoi chuig cara! + +/userinfo.bml.timeupdate.dayago=lá ó shin + +/userinfo.bml.timeupdate.daysago=[[num]] lá ó shin + +/userinfo.bml.timeupdate.hourago=uair ó shin + +/userinfo.bml.timeupdate.hoursago=[[num]] uair ó shin + +/userinfo.bml.timeupdate.minuteago=nóiméad ó shin + +/userinfo.bml.timeupdate.minutesago=[[num]] nóiméad ó shin + +/userinfo.bml.timeupdate.secondago=soicind ó shin + +/userinfo.bml.timeupdate.secondsago=[[num]] soicind ó shin + +/userinfo.bml.timeupdate.weekago=seachtain ó shin + +/userinfo.bml.timeupdate.weeksago=[[num]] seachtain ó shin + +/userinfo.bml.title=Faisnéis Úsáideora + +/userinfo.bml.title.communityinfo=Faisnéis faoin gCumann + +/userinfo.bml.title.syndicated=Cuntas Comhfhoilsithe + +/userinfo.bml.userinfo.body=Tá faisnéis an úsáideora [[username]] thíos. Más tusa an t‑úsáideoir seo, féadann tú d’fhaisnéis a athrú (nó príobháideacht d’fhaisnéise a shocrú) ar an leathanach Athraigh Faisnéis. + +/userinfo.bml.userinfo.name=Faisnéis faoin Úsáideoir + +btn.search=Cuardaigh + +date.day.friday.long=Dé hAoine + +date.day.friday.short=Aoi + +date.day.monday.long=Dé Luain + +date.day.monday.short=Lua + +date.day.saturday.long=Dé Sathairn + +date.day.sunday.long=Dé Domhnaigh + +date.day.sunday.short=Dom + +date.day.thursday.long=Déardaoin + +date.day.thursday.short=Déa + +date.day.tuesday.long=Dé Máirt + +date.day.tuesday.short=Mái + +date.day.wednesday.long=Dé Céadaoin + +date.day.wednesday.short=Céa + +date.month.april.long=Aibreán + +date.month.april.short=Aib + +date.month.august.long=Lúnasa + +date.month.august.short=Lún + +date.month.december.long=Nollaig + +date.month.december.short=Nol + +date.month.february.long=Feabhra + +date.month.february.short=Fea + +date.month.january.long=Eanáir + +date.month.january.short=Ean + +date.month.july.long=Iúil + +date.month.july.short=Iúi + +date.month.june.long=Meitheamh + +date.month.june.short=Mei + +date.month.march.long=Márta + +date.month.march.short=Már + +date.month.may.long=Bealtaine + +date.month.may.short=Bea + +date.month.november.long=Samhain + +date.month.november.short=Sam + +date.month.october.long=Deireadh Fómhair + +date.month.october.short=DFó + +date.month.september.long=Meán Fómhair + +date.month.september.short=MFó + +dystopia.btn.login=LOGÃIL ISTEACH + +dystopia.hello_anonymous=Fáilte isteach chuig LiveJournal! + +dystopia.hello_loggedin=Dia dhuit, a [[username]]! + +dystopia.nav.createjournal=Cruthaigh Dialann + +dystopia.nav.developer=Lucht Forbartha + +dystopia.nav.download=Ãoschóipeáil + +dystopia.nav.editentries=Athraigh Iontrálacha + +dystopia.nav.editfriends=Do Chairde + +dystopia.nav.editpassword=D'Fhocal Faire + +dystopia.nav.editpics=Do Phictiúir + +dystopia.nav.editstyle=Athraigh Stíl + +dystopia.nav.faq=Ceisteanna Coitianta + +dystopia.nav.findcomm=de réir Cumainn + +dystopia.nav.finddir=Cuardaigh san Eolaire + +dystopia.nav.findint=de réir Spéise + +dystopia.nav.findrandom=Gan Aird + +dystopia.nav.findregion=de réir Limistéir + +dystopia.nav.home=Baile + +dystopia.nav.journalcalendar=Féilire + +dystopia.nav.journalfriends=Cairde + +dystopia.nav.journalinfo=Faisnéis Úsáideora + +dystopia.nav.journalrecent=Le Déanaí + +dystopia.nav.legalprivacy=Príobháideacht + +dystopia.nav.legaltos=Téarmaí Seirbhíse + +dystopia.nav.login=Lógáil isteach + +dystopia.nav.logout=Logáil amach + +dystopia.nav.lostinfo=Focal Faire Caillte? + +dystopia.nav.memories=Cuimhní + +dystopia.nav.modifyjournal=Mionathraigh Dialann + +dystopia.nav.news=Nuacht + +dystopia.nav.paidaccts=Cuntais Ãoctha + +dystopia.nav.personalinfo=Faisnéis Phearsanta + +dystopia.nav.sitemap=Mapa an tSuímh + +dystopia.nav.siteopts=Roghanna Brabhsála + +dystopia.nav.support=An bhfuil ceist ‘ad? + +dystopia.nav.updatejournal=Iontráil Nua + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=170 + +dystopia.navhead.findusers=Aimsigh Úsáideoirí + +dystopia.navhead.help=Cabhair & Tacaíocht + +dystopia.navhead.journal=Do Dhialann + +dystopia.navhead.legal=Dleachtanas + +dystopia.navhead.settings=Do Shocruithe + +dystopia.navhead.welcome=Fáilte romhat! + +dystopia.search.aolim=AOL IM  + +dystopia.search.icq=Uimhir ICQ + +dystopia.search.int=Spéis + +dystopia.search.jabber=Jabber  + +dystopia.search.msn=Ainm Úsáideora MSN + +dystopia.search.region=Limistéar + +dystopia.search.yahoo=Yahoo! ID  + +dystopia.searchlj=Cuardaigh LiveJournal: + +Email=R-phost + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Earráid + +error.nodb=Níl an bunachar sonraí le fáil faoi láithair. + +error.nodbmaintenance=Tá an chuid seo den bhunachar sonraí dúnta faoi láthair chun coinneáil a dhéanamh uirthi. Bain triail as arís i gcúpla nóiméad. + +error.unknownmode=Mód anaithnid. + +error.usernameinvalid=Tá carachtair neamhbhailí i d’ainm úsáideora. + +error.usernamelong=Tá d’ainm úsáideora rófhada—níos mó ná 15 charactar. + +error.username_notfound=Ní bhfuarthas an t‑ainm úsáideora. + +Help=Cabhair + +label.security.custom=Speisialta… + +label.security.friends=Cairde + +label.security.head=Leibhéal Slándála: + +label.security.private=Príobháideach + +label.security.public=Poiblí + +label.switch.button=Tiontaigh + +label.switch.header=Tiontaigh ar Dhialann eile + +label.switch.workwith=Oibrigh le dialann: + +langname.be=Bealarúisis + +langname.da=Danmhairgis + +langname.de=Gearmáinis + +langname.en=Béarla + +langname.en_GB=Béarla - RA + +langname.en_LJ=Béarla - SAM + +langname.es=Spáinnis + +langname.et=Eastóinis + +langname.fi=Fionlainnis + +langname.fr=Fraincis + +langname.ga=Gaeilge + +langname.gd=Gàidhlig + +langname.he=Eabhrais + +langname.hi=Hindí + +langname.hu=Ungáiris + +langname.is=Ãoslainnis + +langname.it=Iodáilis + +langname.ja=Seapáinis + +langname.la=Laidin + +langname.lv=Laitvis + +langname.ms=Malaeis + +langname.nb=Ioruais - BokmÃ¥l + +langname.nl=Ollannais + +langname.nn=Ioruais - Nynorsk + +langname.pl=Polainnis + +langname.pt=Portaingéilis + +langname.ru=Rúisis + +langname.sv=Sualainnis + +langname.tr=Tuircis + +langname.uk=Úcráinis + +langname.zh=Sínis Shimplithe + +ljcom.menu.upgrade=Ceannaigh Cuntas Ãoctha + +ljcom.userinfo.accounttype=Saghas Cuntais + +ljcom.userinfo.types.early=Úsáideoir Tosaigh + +ljcom.userinfo.types.free=Cuntas Saor + +ljcom.userinfo.types.paid=Cuntas Ãoctha + +ljcom.userinfo.types.paid_early=Cuntas Ãoctha, Úsáideoir Tosaigh roimhe seo + +ljcom.userinfo.types.paid_early_expiring=Cuntas Ãoctha, éag [[paiduntil]], Úsáideoir Tosaigh roimhe seo + +ljcom.userinfo.types.paid_expiring=Cuntas Ãoctha, éag [[paiduntil]] + +ljcom.userinfo.types.permanent=Cuntas Buan + +ljcom.userinfo.types.permanent_early=Cuntas Buan, Bunúsáideoir roimhe seo + +ljlib.pageofpages=Leathanach a [[page]] de [[total]] + +lostinfo.head=An ndearna tú dearmad ar rud éigin? + +lostinfo.text=Má rinne tú dearmad ar d'ainm úsáideora nó ar d'fhocal faire, faigh ar ais anseo é!. + +Password=Focal Faire + +password.max30=Ní féidir focal faire a úsáid atá níos faide ná 30 carachtar. + +portal.bdays.count.des=Mar loicrogha, taispeántar an cúigear carad gur luaithe a mbreithlaethanta. + +portal.bdays.count.name=Breithlaethanta le Taispéaint + +portal.bdays.portalname=Breithlaethanta + +portal.bdays.portaltitle=Breithlaethanta + +portal.goat.name=Sonóg an tSuímh + +portal.goattext.des=Céard a deireann do ghadharsa? Ní féidir le fíor-ghadhar ach 'Mááááá' a rá, ach féadann tú ligean ort gur féidir le do ghadharsa rud éigin eile a rá más maith leat. + +portal.goattext.name=Téacs Gadhair + +portal.login.portalname=Bosca Logáil Isteach + +portal.memories.entriesnoun=iontráil + +portal.memories.entrynoun=iontráil amháin + +portal.memories.portalname=Iontrálacha le Cuimhneamh + +portal.memories.portaltitle=Iontrálacha le Cuimhneamh + +portal.ministats.active=Gníomhach: + +portal.ministats.title=Staitisticí Úsáideoirí + +portal.ministats.total=Uile: + +portal.misbehaved.des=B’fhiú dhuit gan an bosca seo a sheiceáil. Níl ann ach trioblóid i ngadhar gan taithí ar tithe. + +portal.misbehaved.name=Gadhar Mí-iomprach + +portal.newtolj.name=Naisc an tSuímh + +portal.popfaq.portalname=10 CC (FAQanna)is Mó a Léamh + +portal.popfaq.portaltitle=10 CC (FAQanna)is Mó a Léamh + +portal.randuser.count.des=Mar loicrogha, taispeántar úsáideoir randamach amháin, ach is féidir deichniúr a chur isteach go hingearach sna colúin caola, nó cúigear a chur isteach go cothrománach i gcolún leathan + +portal.randuser.count.name=Méid úsáideoirí randamacha le taispeáint + +portal.randuser.error.tableempty=Níl úsáideoirí randamacha ann. Téigh i dteagmháil leis an lucht riaracháin. + +portal.randuser.hidename.des=Mar loicrogha, taispeántar ainm an úsáideora randamaigh. Seiceáil an bosca seo chun an ainm a bhaint amach. + +portal.randuser.hidename.name=Ceil Ainm + +portal.randuser.hidepic.des=Mar loicrogha, taispeántar pictiúr an úsáideora randamaigh, má tá sé ar fáil. Seiceáil an bosca seo chun an pictiúr a bhaint amach. + +portal.randuser.hidepic.name=Ceil Pictiúr Úsáideora + +portal.randuser.portalname=Úsáideoir Randamach + +portal.randuser.portaltitle=Úsáideoir Randamach + +portal.randuser.portaltitleplural=Úsáideoirí Randamacha + +portal.recent.error.noentries=Tá brón orainn. Iontráil ar bith. + +portal.recent.error.notsetup=Caithfidh an bosca seo a oiriúnú. Brúigh ar an comhartha plus chun rogha a dhéanamh de dhialann le faire. + +portal.recent.error.userstatus=Scrios an t-úsáideoir a chuntas nó chuir sé ar fionraí é. + +portal.recent.items.description=Mar loicrogha, ní taispeántar ach an iontráil is déanaí. + +portal.recent.items.name=Míreanna le taispeáint + +portal.recent.journal.description=Cén dialann ar mhaith leat a iontrálacha is déanaí a fheiceáil? + +portal.recent.journal.name=Dialann + +portal.recent.nosubject=(Gan Ãbhar) + +portal.recent.permlink=Nasc + +portal.recent.portalname=Radharc na nIontrálacha Déanacha + +portal.recent.portaltitle=Bosca na nIontrálacha Déanacha + +portal.recent.showtext.description=Mar loicrogha, ní taispeántar ach na hábhair. + +portal.recent.showtext.name=Cuir Téacs san Ãireamh + +portal.stats.journalentyest=Iontrálacha inné + +portal.stats.portalname=Staitisticí an tSuímh + +portal.stats.portaltitle=Staitisticí + +portal.stats.totalusers=Suim úsáideoirí + +portal.update.mode.full=Lán + +portal.update.mode.name=Mód + +portal.update.mode.simple=Simplí + +portal.update.portalname=Iontráil Nua + +portal.update.portaltitle=Scríobh Iontráil Nua + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Gabh mo leithscéal + +talk.anonwrote=Scríobh duine éigin, + +talk.anonwrote_comm=Scríobh duine éigin sa chumann [[commlink]], + +talk.btn.preview=Réamhamharc + +talk.commentpermlink=nasc + +talk.commentpost=Scríobh trácht nua + +talk.commentsread=Léigh tráchtanna + +talk.curname_Mood=Fonn reatha: + +talk.curname_Music=Ceol reatha: + +talk.error.bogusargs=Argóintí bréagacha + +talk.error.comm_deleted=Scriosadh an trácht seo. + +talk.error.deleted=Scriosadh an dialann seo. + +talk.error.deleted.title=Scriosta + +talk.error.mustlogin=Caithfidh tú bheith logáilte isteach chun an iontráil chosanta seo a fheiceáil. + +talk.error.nocomment=Níl an trácht ann. + +talk.error.noentry=Níl a leithéid d'iontráil ann. + +talk.error.nojournal=Earráid: níorbh'fhéidir an dialann a dhéanamh amach ó na hargóintí. + +talk.error.nosuchjournal=Níl a leithéid de dhialann ann. + +talk.error.notauthorised=Níl cead agat an iontráil chosanta seo a fheiceáil. + +talk.error.suspended=Tá an dialann/úsáideoir seo ar fionraí. + +talk.error.suspended.title=Ar fionraí + +talk.parentlink=Tuismitheoir + +talk.readsimilar=Léigh iontrálacha atá cosúil léis an gceann seo: + +talk.replytothis=Freagair é seo + +talk.somebodywrote=Scríobh [[realname]] ([[userlink]]), + +talk.somebodywrote_comm=Scríobh [[realname]] ([[userlink]]) sa chumann [[commlink]], + +talk.spellcheck=Deimhnigh an litriú (Béarla) sa réamhamharc + +talk.threadlink=Snáithe + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_gaeilge + +Username=Ainm Úsáideora + +xcolibur.greeting.anon=Fáilte isteach chuig LiveJournal! + +xcolibur.greeting.logged_in=Fáilte romhat, a [[name]]! [[logout]] + +xcolibur.login=Logáil isteach? + +xcolibur.logout=Logáil amach? + +xcolibur.nav.about=Eolas + +xcolibur.nav.about.download=Ãoschóipeáil + +xcolibur.nav.about.general=Eolas Ginearálta + +xcolibur.nav.about.paidaccounts=Cuntais Ãoctha + +xcolibur.nav.about.press=Meáin Cumarsáide + +xcolibur.nav.about.sitenews=Nuacht an tSuímh + +xcolibur.nav.about.stats=Staitisticí + +xcolibur.nav.footer.sitemap=Mapa an tSuímh + +xcolibur.nav.help=Cabhair + +xcolibur.nav.help.ask=Cuir Ceist + +xcolibur.nav.help.faq=Ceisteanna Coitianta + +xcolibur.nav.help.lostpassword=Focal Faire Caillte + +xcolibur.nav.home=Baile + +xcolibur.nav.journal=Dialann + +xcolibur.nav.journal.archive=Cartlann + +xcolibur.nav.journal.edit.entries=Athraigh Iontrálacha + +xcolibur.nav.journal.friends=Cairde + +xcolibur.nav.journal.info=Faisnéis + +xcolibur.nav.journal.memories=Cuimhní + +xcolibur.nav.journal.recent=Le Déanaí + +xcolibur.nav.journal.update=Iontráil Nua + +xcolibur.nav.manage=Riar + +xcolibur.nav.manage.community=Cumainn + +xcolibur.nav.manage.customize=Oiriúnaigh + +xcolibur.nav.manage.entries=Iontrálacha + +xcolibur.nav.manage.friends=Cairde + +xcolibur.nav.manage.info=Faisnéis + +xcolibur.nav.manage.password=Focal Faire + +xcolibur.nav.manage.pics=Pictiúir Úsáideora + +xcolibur.nav.search=Cuardaigh + +xcolibur.nav.search.directory=Limistéar + +xcolibur.nav.search.directory.search=Casta + +xcolibur.nav.search.interests=Spéiseanna + +xcolibur.nav.search.random=Gan Aird + +xcolibur.nav.siteopts=Roghanna Brabhsála + +xcolibur.nav.title=Stiúradh: + +xcolibur.nav.welcome=Fáilte romhat + +xcolibur.nav.welcome.create=Cruthaigh Cuntas + +xcolibur.nav.welcome.login=Logáil isteach + +xcolibur.nav.welcome.update=Scríobh Iontráil Nua + +xcolibur.search=Cuardaigh: + +xcolibur.search.aolim=AOL IM  + +xcolibur.search.category=Sonra: + +xcolibur.search.icq=Uimhir ICQ + +xcolibur.search.int=Spéis + +xcolibur.search.jabber=Jabber  + +xcolibur.search.msn=Ainm Úsáideora MSN + +xcolibur.search.region=Limistéar + +xcolibur.search.yahoo=Yahoo! ID  + +xcolibur.upgrade=Ceannaigh Cuntas Ãoctha + diff --git a/ljcom/bin/upgrading/gd.dat b/ljcom/bin/upgrading/gd.dat new file mode 100644 index 0000000..06c718e --- /dev/null +++ b/ljcom/bin/upgrading/gd.dat @@ -0,0 +1 @@ +;; -*- coding: utf-8 -*- diff --git a/ljcom/bin/upgrading/gr.dat b/ljcom/bin/upgrading/gr.dat new file mode 100644 index 0000000..1b97780 --- /dev/null +++ b/ljcom/bin/upgrading/gr.dat @@ -0,0 +1,2850 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Αν θέλεις να σβήσεις ή να επαναφέÏεις το ημεÏολόγιο σου, μποÏείς να το κάνεις εδώ. Όταν σβήσεις το ημεÏολόγιο σου έχεις 30 ημέÏες διοÏία για να το επαναφέÏεις, για την πεÏίπτωση που αλλάξεις γνώμη. Μετά απο 30 ημέÏες το ημεÏολόγιο αυτό θα σβηστεί μόνιμα και δεν θα υπάÏχει Ï„Ïόπος επαναφοÏάς του. + +/accountstatus.bml.journalstatus.head=Κατάσταση ΕνεÏγοποίησης ΗμεÏολογίου + +/accountstatus.bml.journalstatus.select.activated=ΕνεÏγοποιημένο + +/accountstatus.bml.journalstatus.select.deleted=Σβησμένο + +/accountstatus.bml.journalstatus.select.head=Κατάσταση + +/accountstatus.bml.journalstatus.select.suspended=Σε διαθεσιμότητα + +/accountstatus.bml.title=Κατάσταση ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +/allpics.bml.current=ΤÏέχουσες ΦωτογÏαφίες + +/allpics.bml.default=ΠÏοεπιλεγμένο + +/allpics.bml.edit2=Ίσως θέλεις να αλλάξεις τις λέξεις-κλειδιά σου ή να αναφοÏτώσεις νέα ικόνα. + +/allpics.bml.error.noparam=ΧÏειάζεται να οÏίσεις μια παÏάμετÏο χÏήστη. + +/allpics.bml.keywords=Λέξεις-κλειδιά: + +/allpics.bml.nopics.text.other=Αυτός ο χÏήστης δεν έχει αναφοÏτώσει καμία εικόνα. + +/allpics.bml.nopics.text2=Δεν έχεις καμία αναφοÏτωμένη εικόνα. Για να αναφοÏτώσεις εικόνα, πήγαινε εδώ. + +/allpics.bml.nopics.title=Καμία εικόνα + +/allpics.bml.pics=ΟÏίστε οι εικόνες του χÏήστη [[user]]. + +/allpics.bml.title=Εικόνες ΧÏήστη + +/changepassword.bml.btn.proceed=Συνέχεια + +/changepassword.bml.changepassword.header=Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης + +/changepassword.bml.changepassword.instructions=ΣυμπλήÏωσε την παÏακάτω φόÏμα για να αλλάξεις τον κωδικό σου. Για βοήθεια με την επιλογή ενός ÎºÎ±Î»Î¿Ï ÎºÏ‰Î´Î¹ÎºÎ¿Ï ÎºÎ±Î¹ την διατήÏηση της ασφάλειας του λογαÏιασμόυ σου, βλέπε αυτό το FAQ. + +/changepassword.bml.email.body<< +Ο κωδικός Ï€Ïόσβασής έχει αλλάξει στο [[sitename]]. + +Για να τον ανακτήσεις μελλοντικά, επισκεψου το: + +[[siteroot]]/lostinfo.bml + +Με φιλικοÏÏ‚ χαιÏετισμοÏÏ‚, +Ομάδα του [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï + +/changepassword.bml.error.badcheck=Λανθασμένος καινοÏÏιος κωδικός Ï€Ïόσβασης [[error]] + +/changepassword.bml.error.badnewpassword=Η επιβεβαίωση του νέου ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης δεν ταυτίζεται με το νέο κωδικό. ΜποÏεί να έχει γίνει κάποιο λάθος στη δακτυλογÏάφηση. ΠαÏακαλώ ξαναγÏάψε κι επιβεβαίωσε το νέο σου κωδικό. + +/changepassword.bml.error.badoldpassword=Ο παλιός σου κωδικός Ï€Ïόσβασης είναι λανθασμένος + +/changepassword.bml.error.blankpassword=Ο καινοÏÏιος κωδικός Ï€Ïόσβασης δεν μποÏεί να είναι κενός. + +/changepassword.bml.error.changetestaccount=Δεν μποÏείς να αλλάξεις τον κωδικό Ï€Ïόσβασης Î´Î¿ÎºÎ¹Î¼Î±ÏƒÏ„Î¹ÎºÎ¿Ï Î»Î¿Î³Î±ÏιασμοÏ. + +/changepassword.bml.error.characterlimit=Οι κωδικοί Ï€Ïόσβασης έχουν μέγιστο ÏŒÏιο 30 χαÏακτήÏες. + +/changepassword.bml.error.invaliduser=ΆκυÏος χÏήστης [[user]]. Αυτός ο χÏήστης δεν υπάÏχει. ΣίγουÏα το έγÏαψες σωστά; + +/changepassword.bml.error.mustenterusername=ΠÏέπει να εισάγετε το όνομα του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚. + +/changepassword.bml.error.nonascii=Οι κωδικοί πεÏιοÏίζονται σε χαÏακτήÏες ASCII. ΠαÏακαλώ διάλεξε έναν κωδικό Ï€Ïόσβασης που να πεÏιλαμβάνει αποκλειστικά χαÏακτήÏες ASCII + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Δεν μποÏείς να αλλάξεις τον κωδικό σου Ï€Ïόσβασης αν η Ï„Ïέχουσα διεÏθυνση email σου δεν έχει πιστοποιηθεί. + +/changepassword.bml.newpassword=Îέος Κωδικός ΠÏόσβασης: + +/changepassword.bml.newpasswordagain=Îέος Κωδικός ΠÏόσβασης (ξανά΅): + +/changepassword.bml.oldpassword=Παλιός Κωδικός ΠÏόσβασης: + +/changepassword.bml.proceed.instructions=Πάτα το παÏακάτω κουμπί και ο κωδικός Ï€Ïόσβασής σου θα αλλάξει. Θα λάβεις ένα email που θα πληÏοφοÏεί για την αλλαγή κωδικοÏ. + +/changepassword.bml.success.text=Ο κωδικός Ï€Ïόσβασής σου έχει αλλάξει και σου απεστάλη ένα email με μήνυμα υπενθÏμισης. + +/changepassword.bml.title=Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης + +/community/index.bml.main<< + + + +/community/join.bml.label.allowposting=Αυτή η κοινότητα επιτÏέπει καταχωÏήσεις από όλα τα μέλη, οπότε Ï„ÏŽÏα έχεις Ï€Ïόσβαση να γÏάψεις σ' αυτή. Άν έχεις ένα Ï€ÏόγÏαμμα καταχώÏησης LiveJournal στον υπολογιστή σου, θα Ï€Ïέπει να αποσυνδεθείς και να επανασυνδεθείς ώστε να εμφανιστεί στη λίστα με τα ημεÏολόγια που έχει τη δυνατότητα να ενημεÏώνεις. + +/community/join.bml.label.auth=ΠαÏ' όλο που Ï„ÏŽÏα συμπεÏιλαμβάνεσαι στον κατάλογο μελών, αυτή η κοινότητα επιτÏέπει μόνο σε εξουσιοδοτημένους χÏήστες να γÏάψουν σε αυτή. Άν επιθυμείς Ï€Ïόσβαση για ανανέωση του ημεÏολογίου της κοινότητας, έλα σε επαφή με κάποιον απο τους διαχειÏιστές της. ΠαÏακάτω υπάÏχει μια λίστα με τους διαχειÏιστές αυτής της κοινότητας: [[admins]] + +/community/join.bml.label.banned=Οι διαχειÏιστές της κοινότητας αυτής σου έχουν απαγοÏεÏεσει τη συμμετοχή. + +/community/join.bml.label.closed=Η κοινότητα αυτή είναι κλειστή. Αν ενδιαφέÏεσαι να γίνεις μέλος, έλα σε επαφή με έναν απ΄ τους μεσολαβητές της. ΠαÏακάτω υπάÏχει μια λίστα με τους μεσολαβητές αυτής της κοινότητας: [[admins]] + +/community/join.bml.label.commlogged=Είσαι συνδεδεμένος στο LiveJournal με κοινό/κοινοτικό λογαÏιασμό, όχι με τον Ï€Ïοσωπικό σου λογαÏιασμό. + +/community/join.bml.label.errorcomminfo=Οι πληÏοφοÏίες για τη συγκεκÏιμένη κοινότητα είναι άκυÏες. + +/community/join.bml.label.expls=Πάτα το παÏακάτω κουμπί για να γίνεις μέλος της κοινότητας "[[maintainer]]". Βγάλε την επιλογή από το παÏακάτω κουτί αν θέλεις να γίνεις μέλος της κοινότητας χωÏίς να βλέπεις τις καταχωÏήσεις της στη σελίδα φίλων σου. + +/community/join.bml.label.loginfirst=Για να γίνεις μέλος μιας κοινότητας Ï€Ïέπει Ï€Ïώτα να συνδεθείς. + +/community/join.bml.label.membernow=Είσαι πλέον μέλος της Κοινότητας [[commname]] + +/community/join.bml.label.sure=ΣίγουÏα; + +/community/join.bml.success=Επιτυχία + +/community/join.bml.title=Γίνε Μέλος + +/community/leave.bml.button.leave=Έξοδος απ' την Κοινότητα + +/community/leave.bml.label.buttontoleave=Πάτα το παÏακάτω κουμπί για να φÏγεις απ' την κοινότητα "[[commname]]". + +/community/leave.bml.label.infoerror=Οι πληÏοφοÏίες για τη συγκεκÏιμένη κοινότητα είναι άκυÏες. + +/community/leave.bml.label.logoutfirst=Για να φÏγεις απο μία κοινότητα Ï€Ïέπει Ï€Ïώτα να συνδεθείς. + +/community/leave.bml.label.removed=Έχεις πλέον φÏγει απ' την . + +/community/leave.bml.label.removefromfriends=Σβήσιμο του "[[user]]" απ' τη λίστα φίλων. + +/community/leave.bml.success=Επιτυχία + +/community/leave.bml.sure=ΣίγουÏα; + +/community/leave.bml.title='Εξοδος απ' την Κοινότητα. + +/community/manage.bml.commlist.actinfo=ΠληÏοφοÏίες + +/community/manage.bml.commlist.actions=ΕνέÏγειες + +/community/manage.bml.commlist.actmembers=[Μέλη] + +/community/manage.bml.commlist.actmembers2=Μέλη + +/community/manage.bml.commlist.actsettings=[Ρυθμίσεις] + +/community/manage.bml.commlist.actsettings2=Ρυθμίσεις + +/community/manage.bml.commlist.header=Οι κοινότητές σου + +/community/manage.bml.commlist.none=Δε διαχειÏίζεσαι καμία κοινότητα. + +/community/manage.bml.commlist.text=Αυτές είναι οι κοινότητες που διαχειÏίζεσαι μόνος ή με άλλους. + +/community/manage.bml.commlist.title=Τίτλος + +/community/manage.bml.commlist.username=Όνομα ΧÏήστη + +/community/manage.bml.create.header=ΔημιουÏγία κοινότητας + +/community/manage.bml.create.text=ΜποÏείς επίσης να δημιουÏγήσεις καινοÏÏια κοινότητα. + +/community/manage.bml.title=ΔιαχείÏιση Κοινότητας. + +/community/members.bml.error.alreadyadded=O [[user]] δεν Ï€Ïοστέθηκε επειδή έχει ήδη Ï€Ïόσβαση σ'αυτή την κοινότητα. + +/community/members.bml.error.alreadysent=Ο [[user]] δεν μποÏεί να Ï€Ïοστεθεί γιατί έχει ήδη λάβει ένα email επιβεβαίωσης στις [[datetime]]. ΠαÏακαλώ πεÏίμενε να απαντήσει. + +/community/members.bml.error.invaliduser=Δεν μποÏείς να Ï€Ïοσθέσεις την κοινότητα ή το Ï€ÏακτοÏείο: [[user]] + +/community/members.bml.error.noaccess=Μόνο οι διαχειÏιστές των κοινοτήτων έχουν το δικάιωμα να αλλάξουν τις λίστες μελών. Δεν είσαι διαχειÏιστής της κοινότητας [[comm]]. + +/community/members.bml.error.noattr=Δεν έχουν επιλεγεί παÏάμετÏοι για τον χÏήστη: [[user]] + +/community/members.bml.error.nocomm=Δε βÏέθηκε κοινότητα. + +/community/members.bml.error.nouser=Ο χÏήστης [[user]] δεν υπάÏχει + +/community/members.bml.key.admin=ΔιαχειÏιστής + +/community/members.bml.key.member=Μέλος + +/community/members.bml.key.moderate=Επιβλέπων + +/community/members.bml.key.post=ΠÏόσβαση σε Ανανέωση + +/community/members.bml.key.preapprove=ΧωÏίς επιβλέποντα. + +/community/members.bml.manage2=ΔιαχείÏιση κοινοτήτων + +/community/members.bml.name=Όνομα κοινότητας: [[name]] + +/community/members.bml.nextlink=(Επόμενη σελίδα...) + +/community/members.bml.prevlink=(ΠÏοηγοÏμενη σελίδα...) + +/community/members.bml.settings=[Ρυθμίσεις] + +/community/members.bml.success.header=Επιτυχία + +/community/members.bml.success.message=Οι αλλαγές αποθηκεÏτηκαν επιτυχώς. + +/community/members.bml.success.return=ΕπιστÏοφή στη λίστα + +/community/members.bml.title=Μέλη Κοινότητας + +/community/members.bml.update=ΕνημέÏωση Ïυθμίσεων + +/community/moderate.bml.approve.button=Nαι, έγκÏιση + +/community/moderate.bml.approve.header=ΕγκÏίνεις την καταχώÏηση αυτή; + +/community/moderate.bml.approve.preapprove=Επίσης Ï€Ïόσθεση του χÏήστη [[user]] στην λίστα των Ï€ÏοεγκÏιμένων χÏηστών της κοινότητας αυτής. + +/community/moderate.bml.approve.text=Είσαι σίγουÏος πως θέλεις να εγκÏίνεις τη συγκεκÏιμένη καταχώÏηση; + +/community/moderate.bml.brlist.actions=ΕνέÏγειες + +/community/moderate.bml.brlist.poster=ΣυγγÏαφέας + +/community/moderate.bml.brlist.subject=Το θέμα αÏχίζει + +/community/moderate.bml.brlist.time=ÎÏα + +/community/moderate.bml.brlist.view=Εμφάνιση + +/community/moderate.bml.browse.empty=Η ουÏά διαχείÏισης είναι κενή. + +/community/moderate.bml.browse.header=ΔιαχείÏιση Κοινότητας + +/community/moderate.bml.browse.text=Αυτή είναι η λίστα αναμονής διαχείÏισης για την κοινότητα [[link]] + +/community/moderate.bml.choice.approve=ΈγκÏιση + +/community/moderate.bml.choice.reject=ΑπόÏÏιψη + +/community/moderate.bml.error.noaccess=Δεν επιβλέπεις την κοινότητα [[comm]]. + +/community/moderate.bml.error.noentry=Δεν βÏέθηκε η καταχώÏηση (πιθανόν να έχει ήδη διαχειÏιστεί από άλλον επιβλέποντα). + +/community/moderate.bml.error.nolist=Δεν επιβλέπεις καμία κοινότητα. + +/community/moderate.bml.error.notfound=Δεν έχει βÏεθεί ο λογαÏιασμός αυτής της κοινότητας. + +/community/moderate.bml.manage=ΔιαχείÏιση Κοινοτήτων. + +/community/moderate.bml.moderate=ΔιαχείÏιση αυτής της κοινότητας + +/community/moderate.bml.modlist.actions=ΕνέÏγειες + +/community/moderate.bml.modlist.actmoderate=ΔιαχείÏιση + +/community/moderate.bml.modlist.count=Μέγεθος λίστας αναμονής + +/community/moderate.bml.modlist.header=ΔιαχέιÏιση Κοινοτήτων + +/community/moderate.bml.modlist.title=Τίτλος + +/community/moderate.bml.modlist.username=Όνομα ΧÏήστη + +/community/moderate.bml.posted.appheader=ΠÏοεγκεκÏιμένος + +/community/moderate.bml.posted.apptext=Επίσης ο χÏήστης [[user]] έχει Ï€Ïοστεθεί στη λίστα των Ï€ÏοεγκεκÏιμένων χÏηστών αυτήςτης κοινότητας. + +/community/moderate.bml.posted.header=Επιτυχία + +/community/moderate.bml.posted.proterror=Η καταχώÏηση δεν έχει υποβληθεί λόγω του συγκεκÏιμένου σφάλματος Ï€Ïωτοκόλλου [[err]]. + +/community/moderate.bml.posted.text=Η καταχώÏηση έχει υποβληθεί επιτυχημένα. + +/community/moderate.bml.reject.button=Îαι, απόÏÏιψη. + +/community/moderate.bml.reject.header=ΑπόÏÏιψη αυτής της καταχώÏησης; + +/community/moderate.bml.reject.reason=ΜποÏείς επίσης να εξηγήσεις στο συγγÏαφέα τους λόγους για τους οποίους απέÏÏιψες την καταχώÏησή του. Θα αποσταλοÏν στο συγγÏαφέα με email. + +/community/moderate.bml.reject.text=ΣίγουÏα θέλεις να αποÏÏίψεις αυτήν την καταχώÏηση; + +/community/moderate.bml.rejected.header=ΑποÏÏίφθηκε + +/community/moderate.bml.rejected.text=Η καταχώÏηση έχει αποÏÏιφθεί. + +/community/moderate.bml.title=ΔιαχείÏιση Κοινότητας + +/community/search.bml.button.clear=ΚαθαÏισμός φόÏμας + +/community/search.bml.button.search=Αναζήτηση! + +/community/search.bml.checkbox.onlywithpics=Μόνο κοινότητες με εικόνες + +/community/search.bml.label.byinterest=Κατά ΕνδιαφέÏοντα + +/community/search.bml.label.bylocation=Κατά Τοποθεσία + +/community/search.bml.label.bytime=Κατά ÎÏα Ανανέωσης ΗμεÏολογίου + +/community/search.bml.label.city=Πόλη: + +/community/search.bml.label.country=ΧώÏα: + +/community/search.bml.label.displayoptions=Επιλογές Εμφάνισης + +/community/search.bml.label.hasmember=Έχει Μέλος + +/community/search.bml.label.othercriteria=Άλλα ΚÏιτήÏια + +/community/search.bml.label.outputformat=ΤÏπος Οutput + +/community/search.bml.label.records=ΕγγÏαφές ανά σελίδα: + +/community/search.bml.label.searchcomm=ΈÏευνα Κοινοτήτων + +/community/search.bml.label.selecriteria=Διάλεξε τα παÏακάτω κÏιτήÏια με τα οποία θα ήθελες να βÏεις κοινότητες. Τα αποτελέσματα που θα εμφανιστοÏν είναι συνδυασμός όλων των κÏιτήÏιων αναζήτησης. Με άλλα λόγια, κάθε κουτάκι που επιλέγεις σημαίνει "ΚΑΙ", όχι "Ή". + +/community/search.bml.label.sortmethod=Μέθοδος Ταξινόμησης: + +/community/search.bml.label.stateprovince=Îομός: + +/community/search.bml.label.updated=Τελευταία ενημέÏωση + +/community/search.bml.sel.bypicture=Κατά εικόνα + +/community/search.bml.sel.communityname=Όνομα κοινότητας + +/community/search.bml.sel.commview=Εμφάνιση Κοινότητας + +/community/search.bml.sel.day=ημέÏα + +/community/search.bml.sel.month=μήνας + +/community/search.bml.sel.simple=Απλή + +/community/search.bml.sel.updatetime=ÎÏα ΕνημέÏωσης + +/community/search.bml.sel.username=Όνομα χÏήστη + +/community/search.bml.sel.week=εβδομάδα + +/community/search.bml.title=Αναζήτηση κοινοτήτων + +/community/settings.bml.button.changecommunity=ΕνημέÏωση Ρυθμίσεων + +/community/settings.bml.button.createcommunity=ΔημιουÏγία Κοινότητας + +/community/settings.bml.error.badpassword=ΆκυÏος κωδικός κοινότητας. + +/community/settings.bml.error.hasentries=Αυτός ο λογαÏιασμός έχει ήδη καταχωÏήσεις και δεν μποÏεί να μετατÏαπεί. + +/community/settings.bml.error.maintainertype=Ο λογαÏιασμός του μεσολαβητή Ï€Ïέπει να είναι Ï€Ïοσωπικός, όχι κάποιος άλλος κοινός λογαÏιασμός. + +/community/settings.bml.error.noaccess=Μόνο οι διαχειÏιστές της κοινότητας έχουν το δικαίωμα να αλλάξουν τις επιλογές της κοινότητας. Δεν είσαι διαχειÏιστής της κοινότητας [[comm]] + +/community/settings.bml.error.notcomm=Δεν είναι κοινοτικός λογαÏιασμός. + +/community/settings.bml.error.notfound=Δεν βÏέθηκε ο λογαÏιασμός κοινότητας. + +/community/settings.bml.error.samenames=Ο λογαÏιασμός του διαχειÏιστή και της κοινότητας δεν μποÏεί να είναι ο ίδιος. + +/community/settings.bml.label.anybodycan=Όλα τα Μέλη
        Οποιοσδήποτε μποÏεί να Ï€Ïοσθέσει καταχώÏηση αυτόματα αν είναι μέλος. + +/community/settings.bml.label.changeheader=Αλλαγή Ρυμίσεων Κοινότητας + +/community/settings.bml.label.changetext=Εδώ μποÏείς να αλλάξεις τις Ïυθμίσεις της κοινότητας που σου ανήκει ή διαχειÏίζεσαι. + +/community/settings.bml.label.commchanged=Οι Ïυθμίσεις κοινότητας έχουν αλλάξει. + +/community/settings.bml.label.commcreate=Αυτός είναι ο λογαÏιασμός που θέλεις να μετατÏέψεις σε κοινότητα. ΠÏέπει να έχει ήδη δημιουÏγηθεί, αλλά να μη χÏησιμοποιείται από κανέναν, επειδή μετά απ' αυτό πολλά διαφοÏετικά άτομα θα μποÏοÏν να ανανεώνουν το ημεÏολόγιο της. + +/community/settings.bml.label.commcreated=Η κοινότητά σου είναι πλέον εγκατεστημένη. + +/community/settings.bml.label.commheader=Κοινοτικός ΛογαÏιασμός + +/community/settings.bml.label.comminfo=ΠληÏοφοÏίες Κοινότητας + +/community/settings.bml.label.commopts=Επιλογές Κοινότητας + +/community/settings.bml.label.commsite=Ιστοσελίδα Κοινότητας + +/community/settings.bml.label.community=Κοινότητα: + +/community/settings.bml.label.createheader=ΔημιουÏγία Κοινότητας + +/community/settings.bml.label.createtext<< +Εδώ μποÏείς να δημιουÏγήσεις ένα λογαÏιασμό κοινόητας. Η κοινότητα είναι ένας ειδικός Ï„Ïπος λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Ï€Î¿Ï… άλλοι χÏήστες μποÏοÏν να γίνουν μέλη και να καταχωÏήσουν. Για παÏάδειγμα μιας κοινότητας, κοίτα το Seattle Party Community. + +. + +/community/settings.bml.label.howoperates=Διάλεξε πώς λειτουÏγεί η κοινότητά σου. ΜποÏείς να αλλάξεις αυτές τις επιλογές αÏγότεÏα. + +/community/settings.bml.label.maintainer=ΔιαχειÏιστής: + +/community/settings.bml.label.maintainer.login=Άν αυτός ο λογαÏιασμός δεν είναι διαχειÏιστή, a href='/login.bml?ret=1'>μπες ως κάποιος άλλος. + +/community/settings.bml.label.membership=ΣυνδÏομή + +/community/settings.bml.label.modheader=ΤÏοποποίηση + +/community/settings.bml.label.modis=Επιβλεπόμενη
        Οι νέες καταχωÏήσεις Ï€Ïέπει να εγκÏιθοÏν από έναν Επιβλέποντα. + +/community/settings.bml.label.modisnt=
        Οι νέες καταχωÏήσεις εμφανίζονται αμέσως. + +/community/settings.bml.label.modtext=Είναι οι καταχωÏήσεις σ'αυτή την κοινότητα ελεγχόμενες; + +/community/settings.bml.label.nmcan=Τα Μη Μέλη ΜποÏοÏν να Ανανεώσουν
        Οι χÏήστες μποÏοÏν να γÏάφουν σε αυτή την κοινότητα χωÏίς να έιναι μέλη της. + +/community/settings.bml.label.nmcant=Τα Μη Μέλη Δεν ΜποÏοÏν να Ανανεώσουν
        Οι χÏήστες Ï€Ïέπει να γίνουν μέλη αυτής της κοινότητας για να γÏάφουν σε αυτή. + +/community/settings.bml.label.nmheader=Ανανέωση απο Μη Μέλη + +/community/settings.bml.label.nmtext=ΜποÏοÏν οι χÏήστες να γÏάφουν σε αυτή την κοινότητα χωÏίς να είναι μέλη; + +/community/settings.bml.label.openmemb=Ανοιχτή ΣυνδÏομή
        Οποιοσδήποτε μποÏεί να γίνει μέλος χωÏίς να εγκÏιθεί. + +/community/settings.bml.label.password=Κωδικός: + +/community/settings.bml.label.postaccess=ΠÏόσβαση σε Ανανέωση + +/community/settings.bml.label.rellinks=Σχετικά links: + +/community/settings.bml.label.selcan=Επιλεγμένα Μέλη
        Μόνο μεÏικά μέλη μποÏοÏν να ανανεώνουν, Î±Ï†Î¿Ï Ï„Î¿Ï…Ï‚ δοθεί το δικαίωμα από τον λογαÏιασμό του επιβλέποντα. + +/community/settings.bml.label.username=Όνομα ΧÏήστη: + +/community/settings.bml.label.whocanjoin=Ποιός μποÏεί να γίνει μέλος της κοινότητάς σου; + +/community/settings.bml.label.whocanpost=Ποιός μποÏεί να ενημεÏώνει την κοινότητα αυτή; + +/community/settings.bml.manage2=ΔιαχείÏιση κοινοτήτων + +/community/settings.bml.members=[Μέλη] + +/community/settings.bml.name=Όνομα Κοινότητας: [[name]] + +/community/settings.bml.success=Επιτυχία + +/community/settings.bml.title.create=ΔημιουÏγία Κοινότητας + +/community/settings.bml.title.modify=Επιλογές Κοινότητας + +/create.bml.age.check.question=Είσαι κάτω των 13 ετών; + +/create.bml.age.check.yes=Îαι, είμαι κάτω των 13 ετών + +/create.bml.age.check2.question=Είσαι πάνω απο 13 ετών; + +/create.bml.age.check2.yes=Îαί, είμαι πάνω απο 13 ετών. + +/create.bml.age.head=Ηλικία + +/create.bml.btn.create=ΔημιουÏγία ΗμεÏολογίου + +/create.bml.btn.proceed=Συνέχεια.. + +/create.bml.captcha.answer=Απάντηση: + +/create.bml.captcha.audiodesc=ΓÏάψε τα νοÏμεÏα που ακοÏÏ‚ για να αποδείξεις οτι δεν είσαι spam robot (μχαηχαμ) + +/create.bml.captcha.desc=ΓÏάψε τα γÏάμματα και τους αÏιθμοÏÏ‚ που βλέπεις παÏακάτω, για να αποδείξεις οτι δεν είσαι spam robot. Αν δε μποÏείς να διαβάσεις το κείμενο, γÏάψε "AUDIO" και κάνε το τεστ ήχου. + +/create.bml.captcha.invalid=Λάθος απάντηση στο Ï€ÏοηγοÏμενο τεστ. Δοκίμασε άλλη. + +/create.bml.captcha.play=Πάιξε τον ήχο + +/create.bml.captcha.prove=Απόδειξε πως είσαι άνθÏωπος + +/create.bml.clusterselect.cluster=Τομέας: + +/create.bml.clusterselect.clusternum=Τομέας [[number]] + +/create.bml.clusterselect.head=Επιλογή Τομέα + +/create.bml.clusterselect.nocluster=ΑνÏπαÏκτος Τομέας + +/create.bml.clusterselect.text=ΠαÏακαλώ διάλεξε τον τομέα που θέλεις να δημιουÏγήσεις το λογαÏιασμό αυτόν. Σημείωση: Αυτή είναι επιλογή εκσφαλμάτωσης μόνο. Κατά την παÏαγωγή οι χÏήστες δεν θα διαλέγουν οÏτε θα γνωÏίζουν σχετικά. + +/create.bml.create.head=ΔημιουÏγία νέου ημεÏολογίου + +/create.bml.create.text=Είναι απλό να δημιουÏγείς καινοÏÏγιο LiveJournal, απλώς ακολοÏθησε τις κάτω οδηγίες! + +/create.bml.email.head=ΔιεÏθυνση e-mail σου + +/create.bml.email.input.head=ΔιεÏθυνση e-mail + +/create.bml.email.text2=Για λόγους ασφάλειας και επιβεβαίωσης, χÏειαζόμαστε το email σου. Ποτέ μα ποτέ, κάτω από οποιεσδήποτε συνθήκες, δεν θα πουληθεί η δοθεί σε spammers. Το μισοÏμε αυτό πεÏισσότεÏο από οτιδήποτε. Για πεÏισσότεÏες πληÏοφοÏίες, διάβασε την πολιτική μυστικότητάς μας. + +/create.bml.error.coppa.under13=Λυπάμαι, λόγω πεÏιοÏισμών της COPPA, δεν μποÏείς να χÏησιμοποιήσεις την υπηÏεσία LiveJournal γιατί είσαι κάτω απο 13 ετών. ΠαÏακαλώ επέστÏεψε στα 13α γενέθλιά σου. + +/create.bml.error.email.blank=ΠÏέπει να γÏάψεις την διεÏθυνση email σου. + +/create.bml.error.email.lj_domain=Δεν μποÏείς να χÏησιμοποιήσεις ψευδώνυμο [[domain]] όταν δημιουÏγείς ένα λογαÏιασμό. ΠαÏακαλώ βάλε διαφοÏετικό email. + +/create.bml.error.email.nospaces=Δεν επιτÏέπονται τα κενά στις διευθÏνσεις email. + +/create.bml.error.password.asciionly=ΜποÏείς να χÏησιμοποιήσεις μόνο σÏμβολα ASCII στον κωδικό. + +/create.bml.error.password.blank=ΠÏέπει να εισάγεις κωδικό. + +/create.bml.error.password.nomatch=Οι κωδικοί Ï€Ïόσβασης δεν είναι ίδιοι. + +/create.bml.error.postrequired=Απαιτείται ΚΑΤΑΧΩΡΗΣΗ + +/create.bml.error.username.blank=ΠαÏακαλώ δώσε όνομα η ψευδώνυμο. + +/create.bml.error.username.inuse=Αυτό το όνομα χÏήστη είναι κιόλας εν χÏήσει. ΠαÏακαλώ, διάλεξε άλλο. + +/create.bml.error.username.iscode=Αυτό το όνομα χÏήστη φαίνεται να είναι κώδικας Ï€Ïόσκλησης και όχι όνομα χÏήστη. + +/create.bml.error.username.mustenter=ΠÏέπει να γÏάψεις όνομα χÏήστη. + +/create.bml.error.username.reserved=Λυπάμαι, το όνομα χÏήστη είναι κÏατημένο. + +/create.bml.initial.friend.lj_maintenance=ΕνημεÏώσεις καθοÏισμένων και εκτάκτων downtimes και συντήÏησης + +/create.bml.initial.friend.news=Îέα και δÏαστηÏιότητες του LiveJournal + +/create.bml.initialfriends=ΠÏόσθεσε αυτά τα ημεÏολόγια στην λίστα φίλων σου για να ενημεÏώνεσαι για τα νέα και τις πληÏοφοÏίες της ιστοσελίδας. + +/create.bml.initialfriends.heading=ΑÏχικοί Φίλοι + +/create.bml.name.head=Το όνομά σου + +/create.bml.name.input.head=Όνομα: + +/create.bml.name.text=Ποιό είναι το όνομα ή το ψευδώνυμο σου; Θα εμφανίζεται στην κοÏυφή του ημεÏολογίου σου, και στο ευÏετήÏιο χÏηστών αν επιλέξεις να βÏίσκεσαι σε αυτή. Δεν χÏειάζεται να δώσεις το πλήÏες ονοματεπώνυμό σου ή το Ï€Ïαγματικό σου όνομα. + +/create.bml.password.head=Κωδικός + +/create.bml.password.input.head1=Κωδικός: + +/create.bml.password.input.head2=Επιβεβαίωση κωδικοÏ: + +/create.bml.password.text=Διάλεξε έναν κωδικό Ï€Ïόσβασης. + +/create.bml.proceed.btn.proceed=Συνέχεια... + +/create.bml.proceed.warning=Πάτα το Συνέχεια μόνο μια φοÏά!! + +/create.bml.success.btn.enterinfo=Εισαγωγή ΠÏοσωπικών Δεδομένων + +/create.bml.success.head=Επιτυχία! + +/create.bml.success.text1=Το ημεÏολόγιό σου δημιουÏγήθηκε. Έχουμε στείλει σημαντικές πληÏοφοÏίες εγγÏαφής στο [[email]], που πεÏιέχουν πεÏαιτέÏω οδηγίες. ΣιγουÏέψου πως επιβεβαίωσες την δημιουÏγία ημεÏολογίου σου πατώντας το link που σου απεστάλη στο email. + +/create.bml.success.text2=Το LiveJournal σου θα βÏίσκεται στο: + +/create.bml.success.text3=ΤώÏα ξόδεψε μεÏικά λεπτά για να συμπληÏώσεις μεÏικές πληÏοφοÏίες για τον εαυτό σου. Είναι κυÏίως Ï€ÏοαιÏετικές, αλλά δώσε μας μια ιδέα του ποιοί χÏησιμοποιοÏν το LiveJournal. + +/create.bml.title=ΔημιουÏγία νέου ημεÏολογίου + +/create.bml.tos.error=ΠÏέπει να διαβάσεις και να συμφωνήσεις στους ÏŒÏους εξυπηÏέτησης Ï€Ïιν δημιουÏγήσεις εναν λογαÏιασμό. + +/create.bml.tos.haveread=Έχω διαβάσει τους ÎŒÏους ΕξυπηÏέτησης και συμφωνώ. + +/create.bml.tos.heading=ÎŒÏοι ΕξυπηÏέτησης + +/create.bml.tos.p1.2=ΠÏιν συνεχίσεις Ï€Ïέπει να έχεις διαβάσει τους a [[aopts]]>ÎŒÏους ΕξυπηÏέτησης και να συμφωνείς με αυτοÏÏ‚. + +/create.bml.useacctcodes.entercode=Για τη δημιουÏγία νέου λογαÏιασμοÏ, απαιτείται η εισαγωγή ενός ÎºÏ‰Î´Î¹ÎºÎ¿Ï Î´Î·Î¼Î¹Î¿Ï…Ïγίας λογαÏιασμοÏ. ΠεÏισσότεÏες πληÏοφοÏίες εδώ: Πώς να δημιουÏγήσω ένα λογαÏιασμό; + +/create.bml.useacctcodes.welcome=Καλώς ÏŒÏισες + +/create.bml.username.box.head=Όνομα χÏήστη: + +/create.bml.username.charsallowed=Το όνομα χÏήστη σου μποÏεί να πεÏιέχει μόνο μικÏά αγγλικά γÏάμματα (a-z), ψηφία (0-9) και το underscore (__)
        Επίσης δεν Ï€Ïέπει να είναι μεγαλÏτεÏο απο 15 χαÏακτήÏες. + +/create.bml.username.forpaidaccts=Ή, για αγοÏασμένους λογαÏιασμοÏÏ‚: + +/create.bml.username.head=Όνομα χÏήστη + +/create.bml.username.ljaddress=Το ημεÏολόγιό σου θα βÏεθεί σ' αυτές τις διευθÏνσεις: + +/create.bml.username.text=Κάθε χÏήστης του [[sitename]] Ï€Ïέπει να έχει το δικό του ξεχωÏιστό όνομα. Το όνομα χÏήστη σου είναι αυτό που εμφανίζεται στη διεÏθυνση του ημεÏολογίου σου και χÏησιμοποιείς για να συνδεθείς στον server του [[sitename]]. Επίσης εμφανίζεται όταν γÏάφεις σχόλια στα ημεÏολόγια άλλων. + +/create.bml.username.username=όνομα χÏήστη + +/customize/index.bml.change=Αλλαγή + +/customize/index.bml.choose=Θέλεις να χÏησιμοποιήσεις το παλιό σÏστημα στυλ ή το καινοÏÏιο; + +/customize/index.bml.choose.header=Επιλογή συστήματος στυλ. + +/customize/index.bml.choose.s1=Παλιό σÏστημα (S1) + +/customize/index.bml.choose.s2=Îέο σÏστημα (S2) + +/customize/index.bml.error.cant_generate_user_layer=Δεν ήταν δυνατή η δημιουÏγία layer χÏήστη. + +/customize/index.bml.error.fail_create_style=Σφάλμα στην δημιουÏγία νέου στυλ. + +/customize/index.bml.error.not_your_layout=Δεν είναι δικό σου σχέδιο. + +/customize/index.bml.error.not_your_theme=Δεν είναι δικό σου theme + +/customize/index.bml.error.no_core_parent=Δεν υπάÏχει πατÏικός πυÏήνας; + +/customize/index.bml.previews=(ΠÏοεπισκοπήσεις) + +/customize/index.bml.s1=Το παλιό σÏστημα στυλ μποÏεί να Ï„Ïοποποιηθεί στη σελίδα ΤÏοποποίση ΗμεÏολογίου + +/customize/index.bml.s1.header=ΧÏήση του S1 + +/customize/index.bml.s2.advanced.denied=Μόνο οι χÏήστες αγοÏασμένων, μόνιμων και early adopter λογαÏιασμών μποÏοÏν να χÏησιμοποιήσουν την πεÏιοχή Ï€ÏοχωÏημένης Ï„Ïοποποίησης. Ανακάλυψε τα οφέλη της αγοÏάς λογαÏιασμοÏ.. + +/customize/index.bml.s2.advanced.header=ΠÏοχωÏημένες ΤÏοποποιήσεις + +/customize/index.bml.s2.advanced.permitted=Για να δημιουÏγήσεις εντελώς καινοÏÏια layers και στυλ, επισκέψου το κέντÏο Ï€ÏοχωÏημένης Ï„Ïοποποίησης. + +/customize/index.bml.s2.customize=Οι παÏακάτω επιλογές εξαÏτώνται απ' το Ï€Ïοσχέδιο. + +/customize/index.bml.s2.customize.header=ΤÏοποποίηση ΠÏοσχεδίου + +/customize/index.bml.s2.customize.language=Οι παÏακάτω γλώσσες υποστηÏίζονται πλήÏως ή μεÏικώς από αυτό το Ï€Ïοσχέδιο. + +/customize/index.bml.s2.customize.language.custom=(Ειδικής ÏÏθμισης) + +/customize/index.bml.s2.customize.language.header=Γλώσσα + +/customize/index.bml.s2.customize.settings=Άν θέλεις να Ï„Ïοποποιήσειες κι άλλο το ημεÏολόγιό σου, εδώ μποÏείς να Ïυθμίσεις επι μέÏους επιλογές για να το κάνεις να φαίνεται ακÏιβώς όσο θέλεις. + +/customize/index.bml.s2.customize.settings.delete=ΑφαίÏεση ΤÏοποποιήσεων + +/customize/index.bml.s2.customize.settings.edit=ΜετατÏοπή ΤÏοποποιήσεων + +/customize/index.bml.s2.customize.settings.header=Αλλαγή Επι ΜέÏους Επιλογών + +/customize/index.bml.s2.customize.settings.new=ΤÏοποποιήση + +/customize/index.bml.s2.customize.themes=Διάλεξε απο τα παÏακάτω Ï€ÏοαιÏετικά themes για αυτό το Ï€Ïοσχέδιο. + +/customize/index.bml.s2.customize.themes.default=(ΠÏοεπιλεγμένο ΠÏοσχέδιο) + +/customize/index.bml.s2.layout=Διάλεξε το Ï€Ïοσχέδιό σου. Επειδή η επιλογή themes και οι custom Ï„Ïοποποιήσεις εξαÏτώνται από το Ï€Ïοσχέδιο, η αλλαγή αυτής της επιλογής εξαλείφει όλες τις άλλες Ï„Ïοποποιήσεις που μποÏεί να έκανες. + +/customize/index.bml.s2.layout.header=ΠÏώτο Βήμα: ΠÏοσχέδιο + +/customize/index.bml.s2.related.editinfo.about=Θέσε τους τίτλους του ημεÏολογίου σου και διάφοÏες επιλογές. + +/customize/index.bml.s2.related.header=Σχετικές Σελίδες + +/customize/index.bml.s2.related.links.about=ΜεÏικά στυλ μποÏοÏν να πεÏιλαμβάνουν την λίστα link σου που ÎµÏƒÏ Î´Î¹Î±Ï‡ÎµÎ¹Ïίζεσαι. + +/customize/index.bml.s2.related.modify.about=Διάλεξε το σετ εικονιδίων διάθεσης του ημεÏολογίου σου. + +/customize/index.bml.title=ΤÏοποποίηση ΗμεÏολογίου + +/delcomment.bml.changeoptions<< +Σημείωση: Απο τη σελίδα [[link]], μποÏείς να επιλέξεις αν θα επιτÏέπεις σεόλους, γÏαμμένους χÏήστες, ή μόνο φίλους να γÏάφουν σχόλια. + +. + +/delcomment.bml.confirm.banuser=Αποκλεισμός του [[user]] από το σχολιασμό του ημεÏολογίου σου. + +/delcomment.bml.confirm.body=ΣίγουÏα θέλεις να σβήσεις το σχόλιο αυτό; + +/delcomment.bml.confirm.head=ΔιαγÏαφή σχολίου; + +/delcomment.bml.confirm.submit=ΔιαγÏαφή Σχολίου + +/delcomment.bml.error.alreadydeleted=Το συγεκÏιμένο σχόλιο έχει ήδη διαγÏαφεί. + +/delcomment.bml.error.cantdelete=Ένα σχόλιο μποÏεί να διαγÏαφεί μόνο από τον συγγÏαφέα του ή τον ιδιοκτήτη του ημεÏολογίου. + +/delcomment.bml.error.cantdelete.comm=Ένα σχόλιο μποÏεί να διαγÏαφεί μόνο από τον συγγÏαφέα του, τον συγγÏαφέα της καταχώÏησης αυτής ή έναν διαχειÏιστή της κοινότητας. + +/delcomment.bml.error.invalidtype=Εσφαλμένος Ï„Ïπος σχολίου. Αυτή η σελίδα ασχολείται μόνο με τα σχόλια σε καταχωÏήσεις ημεÏολογίου. + +/delcomment.bml.error.nocomment=Το επιλεγμένο σχόλιο δεν υπάÏχει. + +/delcomment.bml.success.andban=Το σχόλιο έχει διαγÏαφεί, και ο χÏήστης [[user]] έχει αποκλειστεί από τον σχολιασμό του ημεÏολογίου σου. + +/delcomment.bml.success.head=ΔιαγÏαμμένο. + +/delcomment.bml.success.noban=Το σχόλιο έχει διαγÏαφεί. + +/delcomment.bml.title=ΔιαγÏαφή Σχολίου + +/developer/index.bml.clients=Θέλεις να δημιουÏγήσεις ή να βελτιώσεις έναν LiveJournal client για το σÏστημά σου; ΥπέÏοχα! ΠαÏακάτω υπάÏχουν μεÏικές απαÏαίτητες πηγές πληÏοφοÏιών για να μάθεις πώς δουλεÏει το LiveJournal. + +/developer/index.bml.clients.header=ΣυγγÏαφή LiveJournal Clients + +/developer/index.bml.clients.links<< +
        +
        Διακομιστής LiveJournal <->ΠÏωτόκολο ΕξυπηÏετητή
        +
        Μάθε πώς το Ï€ÏόγÏαμμα LiveJournal στον υπολογιστή σου επικοινωνεί με το διακομιστή του LiveJournal και αντίστÏοφα. + Κατανοώντας το είναι Ï€ÏωταÏχικό Ï€Ïάγμα Ï€Ïάγμα που Ï€Ïέπει να κατανοήσεις Ï€Ïιν αναπτÏξεις ή βελτιώσεις το Ï€ÏόγÏαμμα LiveJournal στο λειτουÏγικό σου σÏστημα.
        +
        Complete Protocol Docs
        +
        All the different protocol modes & methods.
        +
        List of Clients
        +
        A list of most clients used to connect to LiveJournal. The majority of these clients are + open source, and all of them are free to use. This is a great place to get examples for your + client.
        +
        +. + +/developer/index.bml.code<< +Για να δεις τον κοÏμό ο οποίος κινεί το LiveJournal και για να δεις την εσωτεÏική δομή μεÏικών από τους διαθέσιμους εξυπηÏετητές, πήγαινε στη σελίδα του a href="/code/">Κώδικα. + +. + +/developer/index.bml.code.header=Αποθεματικό Κώδικα του LiveJournal + +/developer/index.bml.dbschema<< +Είσαι πεÏίεÏγος να μάθεις για τη μοÏφολογία της βάσης δεδομένων; Η SQL για τη δημιουÏγία όλων των πινάκων και των στοιχείων τους πεÏιλαμβάνεται στον κώδικα του διακομιστή. + +. + +/developer/index.bml.dbschema.header=ΜοÏφολογία Βάσης Δεδομένων + +/developer/index.bml.embedding=Θέλεις να ενσωματώσεις το LiveJournal στην ιστοσελίδα σου; ΥπάÏχουν διάφοÏοι Ï„Ïόποι για να γίνει αυτό, ανάλογα με το είδος του ελέγχου που έχεις στον server σου. Αυτό θα Ï€Ïέπει να σε απασχολεί μόνο αν δεν σου αÏέσει να εμφανίζεται το www.livejournal.com στο URL του ημεÏολογίου σου. + +/developer/index.bml.embedding.header=Ενσωμάτωση LiveJournal + +/developer/index.bml.notice.header=Σημείωση + +/developer/index.bml.notice1=Οι επόμενες πληÏοφοÏίες αφοÏοÏν μόνο Ï€ÏογÏαμματιστές και Ï€ÏοχωÏημένους χÏήστες. Αν απλά θέλεις να γÏάφεις το ημεÏολόγιό σου με το LiveJournal, τότε όλα είναι μια χαÏά! Δε χÏειάζεται να ενδιαφεÏθοÏν οι απλοί χÏήστες. + +/developer/index.bml.notice2=Λέγοντας το Ï€ÏοηγοÏμενο, το παÏακάτω πεÏιεχόμενο είναι μοιÏασμένο σε δÏο τομείς: πληÏοφοÏίες σχετικά με το πώς θα Ïυθμίσεις την όψη των σελίδων στο LiveJournal και πληÏοφοÏίες σχετικά με το πώς θα εγγÏάψεις Ï€ÏογÏάμματα LiveJournal στο διακομιστή του LiveJournal. + +/developer/index.bml.styles=Δε σου αÏέσει η όψη των σελίδων του ημεÏολογίου σου; Μη φοβάσαι καθόλου...Τα πάντα είναι ευέλικτα και αν διαβάσεις την τεκμηÏίωση παÏακάτω, θα μάθεις όλα όσα χÏειάζονται για να κάνεις τις σελίδες σου να μοιάζουν με αυτό που σου αÏέσει. + +/developer/index.bml.styles.header=Ρυθμίζοντας την όψη του LiveJournal + +/developer/index.bml.styles.s1.header=ΣÏστημα στυλ 1 + +/developer/index.bml.styles.s1.system=ΣÏστημα Στυλ + +/developer/index.bml.styles.s1.system.about=Γενική επισκόπηση του πώς θα Ïυθμιστεί το Ï€Ïώτο σου σÏστημα στυλ. + +/developer/index.bml.styles.s1.varlist=Κατάλογος μεταβλητών + +/developer/index.bml.styles.s1.varlist.about=Άμεσος αλφαβητικός κατάλογος με όλες τις μεταβλητές που μποÏείς να Ïυθμίσεις. + +/developer/index.bml.styles.s1.views=Εμφάνιση ΤÏπων + +/developer/index.bml.styles.s1.views.about=Λίστα των διαφοÏετικών Ï„Ïπων των Ï„Ïόπων που μποÏείς να βλέπεις το ημεÏολόγιό σου και λεπτομέÏειες για τον καθένα. + +/developer/index.bml.styles.s2.header=ΣÏστημα Στυλ 2 + +/developer/index.bml.styles.s2.layerbrowse=Πλοήγηση επιπέδου S2 + +/developer/index.bml.styles.s2.layerbrowse.about=ΠλήÏης κατάλογος με επίπεδα S2, τα οποία αποτελοÏν τις Ï€ÏοδιαγÏαφές του συστήματος S2. Σημαντικά εδώ είναι τα επίπέδα κοÏμοÏ, τα οποία οÏίζουν τις βασικές μεταβλητές, λειτουÏγίες και υποÏουτίνες που κάνουν το S2 να είναι μια ισχυÏή γλώσσα σχεδιασμοÏ. + +/developer/index.bml.styles.s2.manual=Το ΕγχειÏίδιο του S2 + +/developer/index.bml.styles.s2.manual.about=ΠληÏοφοÏίες κατανόησης του πώς να χÏησιμοποιείς S2 στο LiveJournal. + +/developer/index.bml.title=ΠληÏοφοÏίες Ï€ÏογÏαμματιστή + +/directory.bml.browse.country.desc=Διάλεξε μια χώÏα για να διαβάσεις ημεÏολόγια απ΄ αυτήν. + +/directory.bml.browse.country.title=Αναζήτηση ΗμεÏολογίων σÏμφωνα με ΧώÏα + +/directory.bml.browse.usa.desc=Κάνε κλικ σε μια πολιτεία των ΗΠΑ παÏακάτω για να διαβάσεις ημεÏολόγια απ΄ αυτή, ή σε μια χώÏα κάτω απ' το χάÏτη για να διαβάσεις ημεÏολόγια από τη χώÏα αυτή. + +/directory.bml.browse.usa.title=Εμφάνιση ΗμεÏολογίων κατά ΑμεÏικανική Πολιτεία + +/directory.bml.error.accounttype=Λυπάμαι, ο Ï„Ïπος λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… δεν επιτÏέπει χÏήση του καταλόγου, ή δεν είσαι συνδεδεμένος αυτή τη στιγμή. Αν ο Ï„Ïπος λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… επιτÏέπει την χÏήση καταλόγου, σιγουÏέψου οτι είσαι συνδεδεμένος και ξαναπÏοσπάθησε. + +/directory.bml.navcrap.matches=[[count]] αντιστοιχίες + +/directory.bml.navcrap.xofy=Σελίδα [[curpage]] από [[totpages]] που εμφανίζονται (records [[reca]]-[[recb]]) + +/directory.bml.open=Άνοιγμα + +/directory.bml.post=ΚαταχώÏηση + +/directory.bml.search.monkey=Αυτή τη στιγμή χιλιάδες εκπαιδευμένα πιθηκάκια Ï„Ïέχουν γÏÏω γÏÏω ψάχνοντας τα αποτελέσματα της αναζήτησης σου. ΠαÏακαλώ πεÏίμενε. + +/directory.bml.search.new=Îέα ΕÏώτηση + +/directory.bml.search.overflow=Ψάξε τα αποτελέσματα με πεÏιοÏισμό σε [[count]] αποτελέσματα. ΚαθόÏισε με ακÏίβεια το εÏώτημά σου. + +/directory.bml.search.title=Αναζήτηση + +/directory.bml.update=ΕνημέÏωση: + +/directory.bml.user=ΧÏήστης + +/doc/index.bml.about=Καλώς ήÏθες στο αÏχείο ενημέÏωσης του LiveJournal, οπου μποÏείς να βÏεις πληÏοφοÏίες για τα πεÏισσότεÏα θέματα που σχετίζονται με την υπηÏεσία του LiveJournal και το λογισμικό του server. ΠαÏακαλώ διάλεξε ένα θέμα από τα παÏακάτω: + +/doc/index.bml.about.header=Καλώς ήÏθες + +/doc/index.bml.docs.faq.about=Συχνές ΑποÏίες (FAQ) για το LiveJournal.com + +/doc/index.bml.docs.guides.about=ΣυμπληÏωματικές πληÏοφοÏίες FAQ + +/doc/index.bml.docs.guides.title=Οδηγοί + +/doc/index.bml.docs.header=ΈγγÏαφα + +/doc/index.bml.docs.howto.about=Κόλπα και Ï€Ïοτάσειες για να σε βοηθήσουν να Ï„Ïοποποιήσεις τον λογαÏιασμό σου στο LiveJournal + +/doc/index.bml.docs.server.about=ΧÏειάζεται να ξέÏεις να εγκαθιστάς, να διαχειÏίζεσαι και να μετατÏέπεις ένα στήσιμο του LiveJournal. + +/doc/index.bml.docs.server.title=ΧειÏιστήÏιο του server του LiveJournal + +/doc/index.bml.docs.tour.about=Κατασκευάστηκε για να γνωÏίσουν το site οι νέοι επισκέπτες + +/doc/index.bml.docs.tour.title=ΠεÏιήγηση + +/doc/index.bml.title=ΈγγÏαφα + +/doc/index.bml.volunteering.about=Αν θέλεις να βοηθήσεις με τα έγγÏαφα του LiveJournal, κοίτα τα παÏακάτω forums + +/doc/index.bml.volunteering.header=Εθελοντισμός + +/doc/index.bml.volunteering.ljsysdoc=Συζητήσεις σχετικές με το σÏστημα εγγÏάφων του LiveJournal. + +/doc/index.bml.volunteering.ljuserdoc=Συζητήσεις για τα έγγÏαφα end user. + +/doc/tour/index.bml.clients.caption=Οι LiveJournal clients είναι μικÏά Ï€ÏογÏάμματα που Ï„Ïέχουν στον υπολογιστή σου και σου επιτÏέπουν να ενημεÏώνεις το ημεÏολόγιό σου οποτεδήποτε είσαι στο δίκτυο, χωÏίς να χÏειάζεται να ανοίξεις παÏάθυÏο browser. Τα clients υπάÏχουν για κάθε λειτουÏγικό, και αÏκετά αλλάζουν επιλογές Ï€Î¿Î»Ï ÎµÏκολα. + +/doc/tour/index.bml.comms.caption=Το LiveJournal είναι μια μεγάλη κοινότητα αλληλεπίδÏασης, οπότε δεν θα Ï€Ïέπει να σε εκπλήσσει το οτι υπάÏχουν πολλά μέλη με παÏόμοια ενδιαφέÏοντα. Για αυτό το λόγο, Ï€ÏοσφέÏουμε τη δυνατότητα δημιουÏγίας κοινοτήτων, ημεÏολογίων δηλαδή που μποÏοÏν να ανανεώνουν πολλά άτομα συγχÏόνως. + +/doc/tour/index.bml.comms.title=Κοινότητες + +/doc/tour/index.bml.create.caption=Το LiveJournal είναι μια κοινότητα ημεÏολογίων που βασίζεται στη συνδÏομή. Αυτή η σελίδα εξηγεί τι συνεπάγεται η συνδÏομή, γιατί είναι σημαντική, και τα Ï€Ïονόμιά της. Επίσης πεÏιλαμβάνει μια φόÏμα δημιουÏγίας του Î´Î¹ÎºÎ¿Ï ÏƒÎ¿Ï… λογαÏιασμοÏ. + +/doc/tour/index.bml.create.title=ΔημιουÏγία ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +/doc/tour/index.bml.friends.caption=ΜποÏείς επίσης να είσαι ενημεÏωμένος για τους φίλους σου μέσω του LiveJournal, χÏησιμοποιώντας την Ï€ÏουπάÏχουσα επιλογή "φίλοι". Άν βÏεις ένα ημεÏολόγιο που θεωÏείς ενδιαφέÏον, Ï€Ïόσθεσέ το στην λίστα φίλων σου, η οποία σου επιτÏέπει να διαβάζεις όλες τις ενημεÏώσεις των φίλων σου απ' την ίδια σελίδα. + +/doc/tour/index.bml.friends.title=Φίλοι + +/doc/tour/index.bml.intro.caption=Αυτή η πεÏιήγηση σχεδιάστηκε για να εξοικειώσει νέους επισκέπτες με το site. Θα σου δείξει που βÏίσκονται οι πιο σημαντικές ενότητες, όπως επίσης και μεÏικές απο τις πιο ενδιαφέÏουσες επιλογές. + +/doc/tour/index.bml.intro.title=Καλώς ήÏθες + +/doc/tour/index.bml.modify.caption=Είναι επίσης δυνατό να Ï„Ïοποποιήσεις το ημεÏολόγιό σου με έναν απο πολλοÏÏ‚ διαφοÏετικοÏÏ‚ Ï„Ïόπους, χÏησιμοποιώντας Ï€ÏοκαθοÏισμένα στυλ και χÏωματικοÏÏ‚ συνδιασμοÏÏ‚. Κάνε το ημεÏολόγιό σου όσο ξεχωÏιστό θέλεις! + +/doc/tour/index.bml.modify.title=ΠÏοσωποποίηση + +/doc/tour/index.bml.nav.next=Επόμενο --> + +/doc/tour/index.bml.nav.prev=<-- ΠÏοηγοÏμενο + +/doc/tour/index.bml.profile.caption=ΕνθαÏÏÏνουμε τα μέλη του LiveJournal να Ï€Ïοσθέσουν πληÏοφοÏίες για τον εαυτό τους στο Ï€Ïοφίλ τους, έτσι ωστε να έχουμε μια ιδέα για το ποιοί χÏησιμοποιοÏν το site μας και πώς να τους εξυπηÏετοÏμε καλÏτεÏα. ΠαÏ'όλα αυτά, τίποτα απ'αυτά δεν απαιτείται. Οι μόνες πληÏοφοÏίες που απαιτοÏνται για να αÏχίσεις να χÏησιμοποιείς το LiveJournal είναι ένα όνομα, μια διεÏθυνση email και ένας κωδικός Ï€Ïόσβασης. + +/doc/tour/index.bml.profile.title=ΠÏοφίλ + +/doc/tour/index.bml.sitemap.caption=Ελπίζουμε πως αυτή η πεÏιήγηση σου έδωσε κάποιες χÏήσιμες αÏχικές πληÏοφοÏίες για το site και την υπηÏεσία του LiveJournal. Άν χÏειάζεσαι βοήθεια με οτιδήποτε σχετικό με το LiveJournal, παÏακαλώ έλα σε επαφή με την ομάδα υποστήÏιξης μας. Άν θες να εξεÏευνήσεις πεÏισσότεÏο, απευθÏνσου στο χάÏτη πλοήγησης για να δεις μια λίστα όλων των σελίδων σ'αυτό το site. + +/doc/tour/index.bml.sitemap.title=ΧάÏτης Πλοήγησης + +/doc/tour/index.bml.support.caption=Η σελίδα υποστήÏιξης πεÏιέχει τομείς που βοηθοÏν στην κατανόηση του τι είναι το LiveJournal, συχνές εÏωτήσεις για το site, και άλλες χÏήσιμες γενικές πληÏοφοÏίες για την υπηÏεσία, την εταιÏεία και την κοινότητα. + +/doc/tour/index.bml.support.title=Βοήθεια + +/doc/tour/index.bml.title=ΠεÏιήγηση - [[title]] + +/doc/tour/index.bml.update.caption=Η ανανέωση ενός ημεÏολογίου είναι ο πυÏήνας της υπηÏεσίας LiveJournal. Εδώ Ï€ÏοσφέÏουμε στα μέλη μια ευκαιÏία να μοιÏαστοÏν τις ζωές τους και να εκφÏάζουν τις σκέψεις τους. Η ανανέωση ημεÏολογίου είναι απλή. Απλά γÏάψε μια καταχώÏηση στο κουτί και πάτα το κουμπί "ΕνημέÏωση ΗμεÏολογίου". Φυσικά Ï€ÏοσφέÏουμε επίσης Ï€ÏοχωÏημένες επιλογές στην σελίδα ανανέωσής μας, όπως την δυνατότητα να ελέγξεις για οÏθογÏαφικά λάθη (στ' αγγλικά κείμενα), και να δώσεις επιπλέον πληÏοφοÏίες για τις καταχωÏήσεις σου, όπως την Ï„Ïέχουσα μουσική και την Ï„Ïέχουσα διάθεση σου. + +/doc/tour/index.bml.update.title=ΕνημέÏωση + +/editinfo.bml.allowshowcontact.about=ΚαλÏτεÏα να αφήσεις αυτή την επιλογή ενεÏγοποιημένη. ΕπιτÏέπει στους άλλους να έÏχονται σε επαφή μαζί σου αφήνοντας εμφανή την διεÏθυνση email σου, τον αÏιθμό ICQ και το όνομα χÏήστη AOL στο ημεÏολόγιό σου. + +/editinfo.bml.allowshowcontact.email=Άν οÏατή, διεÏνθυνση email για εμφάνιση: + +/editinfo.bml.allowshowcontact.email.actual_only=Μόνο Ï€Ïαγματικές διευθÏνσεις + +/editinfo.bml.allowshowcontact.email.both=Και τα δÏο (Ï€Ïαγματικό + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Μόνο η διεÏθυνση στο LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=Καμία. Îα μην εμφανιστεί καμία διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου + +/editinfo.bml.allowshowcontact.email.no_show=Μη εμφάνιση διεÏθυνσης ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου + +/editinfo.bml.allowshowcontact.email.show=Εμφάνιση διεÏθυνσης ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Με την παÏαπάνω επιλογή, μποÏείς επίσης να επιλέξεις την απόκÏυψη του email σου (ενώ θα εμφανίζονται ακόμα τα υπόλοιπα στοιχεία επικοινωνίας), να εμφανίζεται μόνο η διεÏθυνση email σου στο LiveJournal ((μόνο για αγοÏασμένους λογαÏιασμοÏÏ‚), να εμφανίζεται μόνο το Ï€Ïαγματικό σου email, ή να εμφανίζονται και τα δÏο. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Με την παÏαπάνω επιλογή μποÏείς να διαλέξεις επίσης την απόκÏυψη του email σου (ενώ οι υπόλοιπες πληÏοφοÏίες επικοινωνίας μαζί σου θα φαίνονται). + +/editinfo.bml.allowshowcontact.title=Εμφάνιση Ï€Ïοσωπικών δεδομένων επικοινωνίας στο LiveJournal σου; + +/editinfo.bml.allowshowinfo.about=ΕνεÏγοποίησε αυτή την επιλογή αν θέλεις να εμφανίζονται η πόλη/πολιτεία/χώÏα και η ημεÏομηνία γέννησής σου στους άλλους χÏήστες + +/editinfo.bml.allowshowinfo.title=Εμφάνιση τοποθεσίας και γενεθλίων; + +/editinfo.bml.autotranslate.about<< +ΧÏησιμοποίησε αυτή την επιλογή για να πεις στο LiveJournal σε ποιά γλώσσα να υποθέσει οτι είναι οι καταχωÏήσεις σου και τα σχόλια που εισήχθησαν Ï€Ïιν το site μεταφεÏθεί σε μοÏφή Unicode. +Άν γÏάφεις στα ελληνικά, διάλεξε το "Ελληνικά". +Άν γÏάφεις μόνο στα αγγλικά, διάλεξε το "Δυτικής ΕυÏώπης". + +. + +/editinfo.bml.autotranslate.header=Αυτόματη μετατÏοπή παλαιότεÏων καταχωÏήσεων από τα: + +/editinfo.bml.bday.title=Γενέθλια + +/editinfo.bml.bday.year.opt=η χÏονιά είναι Ï€ÏοαιÏετική + +/editinfo.bml.bdayreminders.about=Άν θέλεις να λαβαίνεις υπενθυμιστικά email για τα γενέθλια των φίλων σου στο LiveJournal, επέλεξε αυτό το κουτί. + +/editinfo.bml.bdayreminders.header=Στέλνετέ μου υπενθυμίσεις γενεθλίων (μη ενεÏγό για την ÏŽÏα) + +/editinfo.bml.bio.about=Εδώ μποÏείς να βάλεις μια μικÏή βιογÏαφία σου. Θα εμφανίζεται στην σελίδα ΠληÏοφοÏίες ΧÏήστη σου. + +/editinfo.bml.bio.header=Σχετικά με σένα + +/editinfo.bml.blockrobots.about<< +Αν επιλέξεις αυτό, θα λέμε στα Ïομπότ να φÏγουν. +Βασικά δεν σέβονται τους κανόνες όλα τα Ïομπότ. +. + +/editinfo.bml.blockrobots.header=ΠαÏεμπόδιση Robots/Spiders από το να συμπεÏιλαμβάνουν το ημεÏολόγιό σου στους καταλόγους τους. + +/editinfo.bml.chat.msnusername.title=Όνομα χÏήστη στο MSN + +/editinfo.bml.chat.yahooid.title=Ταυτότητα Yahoo! + +/editinfo.bml.city.title=Πόλη + +/editinfo.bml.country.choose=Διάλεξε χώÏα + +/editinfo.bml.country.title=ΧώÏα + +/editinfo.bml.donotlog=Όχι + +/editinfo.bml.email.title=ΔιεÏθυνση e-mail + +/editinfo.bml.enableboards.about=ΕνεÏγοποίησε αυτή την επιλογή εάν θέλεις να μποÏοÏν άλλοι να απαντήσουν σ' αυτό που γÏάφÏεις + +/editinfo.bml.enableboards.header=ΕνεÏγοποίησε τους πίνακες μηνυμάτων + +/editinfo.bml.encoding.about=Γενικά μόνο χÏήστες που γÏάφουν σε διάφοÏες γλώσσες θα χÏειαστεί να αλλάξουν κάτι εδώ. + +/editinfo.bml.encoding.header=Επιλογές Encoding + +/editinfo.bml.error.day.notinmonth=Εσφαλμένη μέÏα για αυτόν τον μήνα. + +/editinfo.bml.error.day.outofrange=ΆκυÏη μέÏα γενεθλίων. Βάλε μια μέÏα απο 1-31. + +/editinfo.bml.error.email.lj_domain<< +Δεν μποÏείς να εισάγεις email @[[domain]]. +Βάλε την Ï€Ïαγματική σου διεÏθυνση email σε αυτό το πεδίο. Αν είσαι χÏήστης επί πληÏωμή, η διεÏθυνση [[user]]@[[domain]] θα Ï€Ïοωθηθεί στην Ï€Ïαγματική σου διεÏθυνση. +Για να επιλέξεις ποια(ες) διεÏθυνση(εις) email θα εμγανίζονται δημόσια, δες τις επιλογές κάτω από την επιλογή "Εμφάνισε τις πληÏοφοÏίες επικοινωνίας" +. + +/editinfo.bml.error.email.none=ΠÏέπει να δώσεις το email σου. + +/editinfo.bml.error.email.no_space<< +Δεν επιτÏέπονται κενά μέσα σε διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου. +Εάν χÏησιμοποιείς AOL, θυμήσου ότι η διεÏθυνση σου ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου στο ΊντεÏνετ είναι το όνομα οθόνης σου χωÏίς τυχόν κενά, ακολουθημένο από @aol.com +. + +/editinfo.bml.error.excessive_int=Λυπάμαι, έβαλες υπεÏβολικά πολλά ενδιαφέÏοντα. Το ÏŒÏιο είναι 150, αλλά ÎµÏƒÏ Î­Î²Î±Î»ÎµÏ‚ [[intcount]]. Οι αλλαγές που έκανες στα ενδιαφέÏοντά σου δεν αποθηκεÏτηκαν. Πάνε πίσω και πεÏιόÏισε την λίστα σου, και ξανααποθήκευσέ την. + +/editinfo.bml.error.invalidbio=Το αποθηκευμένο σου βιογÏαφικό πεÏιέχει εσφαλμένους χαÏακτήÏες. ΠÏέπει να επισκεφτείς την σελίδα μετατÏοπής για να το μετατÏέψεις σε Unicode. + +/editinfo.bml.error.invalidints=Η + +/editinfo.bml.error.invalidname=Το όνομά σου πεÏιέχει άκυÏους χαÏακτήÏες. ΠÏέπει να επισκεφτείς τη σελίδα Ï„Ïοποποίησης για να το μετατÏέψεις σε χαÏακτήÏες Unicode. + +/editinfo.bml.error.locale.country_ne_state=Διάλεξες τις ΗΠΑ ως χώÏα σου, αλλά έγÏαψες πολιτεία που δεν είναι στις ΗΠΑ στον κάμπο "άλλη πολιτεία" + +/editinfo.bml.error.locale.invalid_country=ΚατάφεÏες να διαλέξεις άκυÏη χώÏα. + +/editinfo.bml.error.locale.state_ne_country=Διάλεξες διαφοÏετική χώÏα από τις ΗΠΑ αλλά διάλεξες πολιτεία των ΗΠΑ. + +/editinfo.bml.error.locale.zip_ne_state=Ο ταχυδÏομικός σου τομέας δεν ταιÏιάζει με την πολιτεία που έδωσες. ΔιόÏθωσε τις πληÏοφοÏίες, ή σβήσε μία ή και τις δÏο επιλογές πολιτείας και ταχυδÏÎ¿Î¼Î¹ÎºÎ¿Ï ÎºÏŽÎ´Î¹ÎºÎ±. + +/editinfo.bml.error.locale.zip_requires_us=Εισήγαγες ταχυδÏομικό κώδικα αλλά δεν επέλεξες τις ΗΠΑ ως χώÏα σου. Συλλέγουμε πληÏοφοÏίες Ï„.κ. μόνο για τους κατοίκους των ΗΠΑ. ΠαÏακαλοÏμε επέστÏεψε και διέγÏαψε τον ταχυδÏομικό κώδικα ή επέλεξε τις Ηνωμένες Πολιτείες ως χώÏα σου. + +/editinfo.bml.error.month.outofrange=ΆκυÏος μήνας γέννησης. Διάλεξε μήνα από 1 έως 12 (Ιαν-Δεκ). + +/editinfo.bml.error.noname=Το όνομα σου είναι απαÏαίτητο πεδίο. Τουλάχιστον δώσε το μικÏÏŒ σου όνομα ή ψευδώνυμο. + +/editinfo.bml.error.tm.require.number=Αν σκοπεÏεις να χÏησιμοποιείς αποστολή κειμένου μέσω sms, Ï€Ïέπει να εισάγεις τον τηλεφωνικό σου αÏιθμό. + +/editinfo.bml.error.tm.require_provider<< +Αν σκοπεÏεις να χÏησιμοποιείς γÏαπτά μηνÏματα, Ï€Ïέπει να Ï€ÏοσδιοÏίσεις την εταιÏεία παÏοχής των υπηÏεσιών. + +Αν η δική σου εταιÏεία δεν πεÏιέχεται στον κατάλογο, παÏακαλοÏμε να μας ενημεÏώσεις σχετικά με τον Ï„Ïόπο λειτουÏγίας της υπηÏεσίας γÏαπτών μηνυμάτων, ώστε να Ï€Ïοσθέσουμε την ανάλογη υποστήÏιξη. +. + +/editinfo.bml.error.year.notenoughdigits=ΆκυÏος χÏόνος γέννησης. Διάλεξε χÏόνο με 4 ψηφία. + +/editinfo.bml.error.year.outofrange=ΆκυÏος χÏόνος γέννησης + +/editinfo.bml.finished.about=Μόλις τελειώσεις, πάτα το κουμπί "Αποθήκευση Αλλαγών" παÏακάτω: + +/editinfo.bml.finished.header=Τελείωσες; + +/editinfo.bml.finished.save_button=Αποθήκευση Αλλαγών + +/editinfo.bml.gender.title=ΦÏλο + +/editinfo.bml.getreplies.about=Επέλεξέ το αν θέλεις να λαμβάνεις ενημέÏωση μέσω email όταν ο κόσμος απαντάει στις καταχωÏήσεις σου χÏησιμοποιώντας τον πίνακα ανακοινώσεων (σχόλια). + +/editinfo.bml.getreplies.header=Λήψη σχολίων + +/editinfo.bml.hidefriendof.about=Αν το επιλέξεις, η λίστα των ατόμων που σε έχουν φίλο δεν εμφανίζεται στην σελίδα Ï€Ïοφίλ σου. + +/editinfo.bml.hidefriendof.header=ΑπόκÏυψη λίστας "Φιλος των" + +/editinfo.bml.howhear.about<< +Μόνο απο πεÏιέÏγεια, από Ï€Î¿Ï Î¬ÎºÎ¿Ï…ÏƒÎµÏ‚ για το [[sitename]]; +Αν ήταν συγκεκÏιμένο άτομο, βάλε το όνομα χÏήστη του. Αν ήταν από άλλη πηγή/άÏθÏο/site, βάλε τις κατάλληλες πληÏοφοÏίες. +. + +/editinfo.bml.howhear.header=ΠεÏιέÏγεια + +/editinfo.bml.htmlemail.about<< +Επέλεξέ το αν το Ï€ÏόγÏαμμα email σου υποστηÏίζει HTML στα μηνÏματα. Πολλά Ï€ÏογÏάμματα Ï€ÏοσπαθοÏν να το υποστηÏίξουν κανονικά, αλλά αποτυχαίνουν. +Αν δεν είναι επιλεγμένο, το LiveJournal θα σου στέλνει email με απλό κείμενο μόνο. +. + +/editinfo.bml.htmlemail.header=Αποστολή Email σε HTML + +/editinfo.bml.imagelinks.about=Οι αντικαταστάτες είναι χÏήσιμοι αν βÏίσκεσαι στη δουλειά ή χÏησιμοποιείς αÏγή σÏνδεση, με το να αντικαθιστοÏν τις εικόνες με συνδέσμους. Για τι μέγεθος εικόνων θέλεις να χÏησιμοποιήσεις τους αντικαταστάτες; + +/editinfo.bml.imagelinks.header=ΧÏησιμοποίησε τους αντικαταστάτες στη σελίδα με τους φίλους σου. + +/editinfo.bml.imagelinks.size.all=ΧÏησιμοποίησε αντικαταστάτες για όλες τις εικόνες. + +/editinfo.bml.imagelinks.size.medium=ΧÏησιμοποιήσε αντικαταστάτες για μεγάλες εικόνες (άνω των [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=ΧÏησιμοποίησε αντικαταστάτες για μεσαίες εικόνες (άνω των [[width]]x[[height]]) + +/editinfo.bml.int.about=Αν θέλεις οι άλλοι να μποÏοÏν να ψάχνουν τον κατάλογο και να σε βÏίσκουν σÏμφωνα με τα ενδιαφέÏοντά σου, γÏάψε όλα όσα σε ενδιαφέÏουν παÏακάτω, χωÏισμένα Î¼ÎµÏ„Î±Î¾Ï Ï„Î¿Ï…Ï‚ με κόμματα. Οι μικÏές μονολεκτικές φÏάσεις είναι καλÏτεÏες. Βασικός Κανόνας: Θα Ï€Ïέπει να μποÏείς να βάλεις το ενδιαφέÏον στην Ï€Ïόταση "Îœ'αÏεσει ο/η/το______". Όταν αναφέÏεσαι σε ουσιαστικά, χÏησιμοποίησε τον πληθυντικό για συνέπεια. "Μου αÏέσουν οι δίσκοι" αντί για "Μου αÏέσει ο δίσκος". + +/editinfo.bml.int.ex.bad=ΛΑΘΟΣ ΠαÏάδειγμα: Îœ'αÏεσουν πολλά συγκÏοτήματα και να βλέπω ταινίες και να μιλάω με φίλους και να βγαίνω σε μπαÏάκια.Τέτοιου είδους πεÏιγÏαφές Ï€Ïέπει να βάζεις στο βιογÏαφικό παÏαπάνω. + +/editinfo.bml.int.ex.good=ΣΩΣΤΟ ΠαÏάδειγμα: ποδήλατο, σκι στο χιόνι, κοκόÏια, υπολογιστές, dvd, mp3, Ï„Ï…Ïί, γκόμενες + +/editinfo.bml.int.header=ΕνδιαφέÏοντα + +/editinfo.bml.login.enterinfo=Εισήγαγε το όνομα χÏήστη και τον κωδικό σου για να Ï„Ïοποποιήσεις τις Ï€Ïοσωπικές σου πληÏοφοÏίες. + +/editinfo.bml.login.forgot.header=Ξέχασες κάτι; + +/editinfo.bml.login.forgot.recover=Αν ξέχασες το όνομα χÏήστη ή τον κωδικό σου, επανάκτησέ τα εδώ!. + +/editinfo.bml.logip.always=Πάντα + +/editinfo.bml.logip.anon_only=Μόνο ανώνυμοι σχολιαστές + +/editinfo.bml.logip.header=Σημείωση των IP όσων απαντοÏν; + +/editinfo.bml.mangleaddress.about=Αν φοβάσαι πως μηχανές αναζήτησεις διευθÏνσεων για spam θα βÏουν το email σου στο LiveJournal, επέλεξε αυτό. Το email σου θα Ï„Ïοποποιηθεί ώστε να μη βÏεθεί από μηχανές συλλογής mails. + +/editinfo.bml.mangleaddress.header=ΔιαστÏέβλωσε την απεικονιζόμενη διεÏθυνση email σου + +/editinfo.bml.name.title=Όνομα + +/editinfo.bml.newemail.subject=Η διέυθυνση email άλλαξε + +/editinfo.bml.numcomments.about=Επέλεξε αυτό αν θέλεις να Ï€ÏοσαÏτήσεις τον αÏιθμό σχολίων στις URL για να κάνεις τον πλοηγό σου να εμφανίζει πιθανότατα τα links με διαφοÏετικό χÏώμα. + +/editinfo.bml.numcomments.header=ΠÏόσθεση &nc=xx στους συνδέσμους σχολίων. + +/editinfo.bml.optional=ΠÏοαιÏετικό + +/editinfo.bml.opt_in.about<< +Άν θέλεις να μάθεις πότε Ï€Ïοσθέτουμε νέα χαÏακτηÏιστικά στο LiveJournal, επέλεξε αυτό το κουτί. +Για την ÏŽÏα δεν χÏησιμοποιείται αυτή η υπηÏεσία, αλλά μποÏεί να χÏησιμοποιηθεί στο μέλλον. +Η διεÏθυνση email σου δεν θα είναι οÏατή στους υπόλοιπους χÏήστες, και μποÏείς να απενεÏγοποιήσεις την επιλογή ανα πάσα στιγμή. +. + +/editinfo.bml.opt_in.header=Στέλνετέ μου νέα του LiveJournal. + +/editinfo.bml.persinfo.disclaimer<< +ΣυμπλήÏωσε μεÏικές σÏντομες πληÏοφοÏίες για σένα, για την ικανοποίηση της δικής μας πεÏιέÏγειας και στατιστικοÏÏ‚ λόγους. Δεν θα κάνουμε τίποτα σατανικό ή ενοχλητικό με αυτές τις πληÏοφοÏίες, απλά μας αÏέσει να γνωÏίζουμε ποιοι και από που είναι οι χÏήστες μας. ΠαÏακαλοÏμε συμπλήÏωσε το σωστά. Αν ανησυχείς, διάβασε την +πολιτική μας για τα Ï€Ïοσωπικά δεδομένα. +. + +/editinfo.bml.persinfo.header=ΠÏοσωπικές ΠληÏοφοÏίες + +/editinfo.bml.screen.all=Όλα + +/editinfo.bml.screen.anon=Ανώνυμο + +/editinfo.bml.screen.header=Ποιά σχόλια θέλετε να είναι κατα κανόνα κÏυμμένα; + +/editinfo.bml.screen.none=Κανένα + +/editinfo.bml.screen.nonfriends=Από μη φίλους + +/editinfo.bml.screen.nonmembers=Από μη μέλη + +/editinfo.bml.security.header=Ποιοί μποÏοÏν να δουν τα δεδομένα επικοινωνίας σου; + +/editinfo.bml.security.visibility.anybody=Οποιοσδήποτε + +/editinfo.bml.security.visibility.everybody=Όλοι + +/editinfo.bml.security.visibility.friends=Μόνο οι φίλοι + +/editinfo.bml.security.visibility.regusers=ΕγγεγÏαμμένοι χÏήστες + +/editinfo.bml.settings.friendspage.title=Τίτλος Σελίδας Φίλων: + +/editinfo.bml.settings.friendspage.title.optional=ΠÏοαιÏετικά, διάλεξε έναν τίτλο για τη σελίδα φίλων σου. (χωÏίς HTML) + +/editinfo.bml.settings.header=Επιλογές ΗμεÏολογίου + +/editinfo.bml.settings.journal.subtitle=Υπότιτλος ΗμεÏολογίου: + +/editinfo.bml.settings.journal.subtitle.optional=ΠÏοαιÏετικά, διάλεξε έναν τίτλο και υπότιτλο για το ημεÏολόγιό σου (χωÏίς HTML). + +/editinfo.bml.settings.journal.title=Τίτλος ΗμεÏολογίου: + +/editinfo.bml.settings.privacy.about=Διάλεξε παÏακάτω τις Ï€Ïοσωπικές σου επιλογές και Ï€Ïοτιμήσεις ?????? + +/editinfo.bml.settings.privacy.header=Επιλογές ιδιωτικών στιγμών + +/editinfo.bml.state.other=Ή βάλε άλλη πολιτέια/νομό/πεÏιοχή. + +/editinfo.bml.state.title=Πολιτεία + +/editinfo.bml.state.us=Πολιτείες των ΗΠΑ + +/editinfo.bml.stylemine.about=Διάλεξε αυτή την επιλογή για να βλέπεις τις σελίδες σχολίων στο στυλ του Î´Î¹ÎºÎ¿Ï ÏƒÎ¿Ï… ημεÏολογίου όταν ακολουθείς links από τη σελίδα φίλων σου. + +/editinfo.bml.stylemine.header=Θέλεις να βλέπεις τις σελίδες σχολίων στο στυλ του ημεÏολογίου σου; + +/editinfo.bml.success.header=Επιτυχία! + +/editinfo.bml.success.message=Οι πληÏοφοÏίες και οι Ïυθμίσεις του ημεÏολόγιου σου και το Ï€Ïοφίλ σου έχουν ενημεÏωθεί. + +/editinfo.bml.switch.button=Αλλαγή + +/editinfo.bml.switch.header=Αλλαγή ΗμεÏολογίου + +/editinfo.bml.switch.workwith=ΕÏγασία με το ημεÏολόγιο: + +/editinfo.bml.title=ΤÏοποποίηση ΠÏοσωπικών Στοιχείων + +/editinfo.bml.tm.details=λεπτομέÏειες + +/editinfo.bml.tm.phonenum=ΠλήÏης αÏιθμός τηλεφώνου: + +/editinfo.bml.tm.sec.about=Εξουσιοδότηση sms από άλλους χÏήστες. + +/editinfo.bml.tm.sec.title=Επίπεδο Ασφαλείας: + +/editinfo.bml.tm.servprov=ΕταιÏεία παÏοχής υπηÏεσιών + +/editinfo.bml.tm.title=ΓÏαπτά μηνÏματα + +/editinfo.bml.translatemailto.about=Σε πεÏίπτωση που επέλεξες να λαμβάνεις απαντήσεις από τον πίνακα ανακοινώσεων μέσω email και το Ï€ÏόγÏαμμα διαχείÏισης του email σου δεν υποστηÏίζει μηνÏματα σε Unicode (UTF-8) επιτυχημένα, επέλεξε αυτή τη ÏÏθμιση για να οÏίσεις ένα διαφοÏετικό σÏστημα κωδικοποίησης στο οποίο τα γÏαπτά κείμενα τα οποία σου αποστέλλονται θα μεταφÏάζονται αυτόματα από το LiveJournal. + +/editinfo.bml.translatemailto.header=ΜετέφÏασε τις ειδοποιήσης email σε: + +/editinfo.bml.unbanusers.about=Έχει απαγοÏεÏεσει καταχωÏήσεις στο ημεÏολόγιό σου από τους παÏακάτω χÏήστες. Επέλεξε τα αντίστοιχα τετÏαγωνάκια κατά όνομα χÏήστη για να αφαιÏέσεις την απαγόÏευσή σου. + +/editinfo.bml.unbanusers.header=ΚατήÏγησε την απαγόÏευση των χÏηστών + +/editinfo.bml.userpic.about=Εδώ βλέπεις την μικÏοσκοπική εικόνα που έχεις υποβάλλει στο LiveJournal για να σε αντιπÏοσωπεÏει στο site ολόκληÏο, στο ημεÏολόγιο σου και στα ημεÏολόγια των φίλων σου: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Για να διαγÏάψεις την εικόνα αυτή ή να υποβάλλεις μια νέα, πήγαινε εδώ. + +/editinfo.bml.userpic.header=Η εικόνα σου + +/editinfo.bml.userpic.none=καμία εικόνα + +/editinfo.bml.weblogscom.about=Επέλεξε την επόμενη ÏÏθμιση για να επιτÏέψεις στο Weblogs.com να πεÏιέχει το ημεÏολόγιό σου όταν κάνεις νέες καταχωÏήσεις. + +/editinfo.bml.weblogscom.header=ΕνημέÏωσε το Weblogs.com για νέες καταχωÏήσεις. + +/editinfo.bml.webpagename.title=Όνομα Ιστοσελίδας + +/editinfo.bml.webpageurl.title=ΔιεÏθυνση Ιστοσελίδας + +/editinfo.bml.whoreply.header=Ποιοί μποÏοÏν να απαντοÏν στις καταχωÏήσεις σου; + +/editinfo.bml.zip.title=ΤαχυδÏομικός κώδικας + +/editinfo.bml.zip.usonly=Τ.Κ. με 5 ψηφία (μόνο για κάτοικους των ΗΠΑ) + +/editjournal.bml.btn.proceed=Συνέχεια... + +/editjournal.bml.certainday=ΣυγεκÏιμένη ΗμέÏα: + +/editjournal.bml.desc=ΠαÏακαλώ χÏησιμοποίησε την παÏακάτω φόÏμα για να βÏεις την καταχώÏηση που θέλεις να Ï„Ïοποποιήσεις. + +/editjournal.bml.in=Στην κοινότητα: + +/editjournal.bml.recententries=πιο Ï€Ïόσφατες καταχωÏήσεις + +/editjournal.bml.recententry=Πιο Ï€Ïόσφατη καταχώÏηση + +/editjournal.bml.title=ΤÏοποποίηση ΚαταχωÏήσεων + +/editjournal.bml.viewwhat=Ποιές ΚαταχωÏήσεις να ΕμφανιστοÏν: + +/editjournal_do.bml.body=Άλλαξε τις παÏαμέτÏους της καταχώÏησης που θέλεις να Ï„Ïοποποιήσεις και πάτα το κουμπί αποθήκευσης στο τέλος της σελίδας. Εναλλακτικά, μποÏείς να πατήσεις το κουμπί διαγÏαφής για να διαγÏάψεις την καταχώÏηση. + +/editjournal_do.bml.btn.delete=ΔιαγÏαφή ΚαταχώÏησης + +/editjournal_do.bml.btn.edit=ΤÏοποποίηση Επιλεγμένης ΚαταχώÏησης + +/editjournal_do.bml.btn.save=Αποθήκευση ΚαταχώÏησης + +/editjournal_do.bml.continue.head=Πάτα για συνέχεια... + +/editjournal_do.bml.continue.text=Î‘Ï†Î¿Ï ÎµÏ€Î¹Î»Î­Î¾ÎµÎ¹Ï‚ αντικείμενο για να Ï„Ïοποποιήσεις, πάτα το παÏακάτω κουμπί Ï„Ïοποποίησης. + +/editjournal_do.bml.currmood=ΤÏέχουσα Διάθεση: + +/editjournal_do.bml.currmusic=ΤÏέχουσα Μουσική: + +/editjournal_do.bml.date=ΗμεÏομηνία: + +/editjournal_do.bml.default=Ï€Ïοεπιλεγμένο + +/editjournal_do.bml.delete.confirm=ΣίγουÏα θέλεις να διαγÏάψεις αυτή την καταχώÏηση; + +/editjournal_do.bml.edit.text=Αυτή είναι η καταχώÏηση που θα Ï„Ïοποποιήσεις. Άλλαξε όσα θέλεις και μετά πάτα το κουμπί "Αποθήκευση ΚαταχώÏησης" παÏακάτω.

        Για να διαγÏάψεις την καταχώÏηση, σβήσε όλο το κείμενο στο κουτί κειμένου και πάτα το κουμπί "Αποθήκευση ΚαταχώÏησης" στο τέλος. + +/editjournal_do.bml.error.getting=Σφάλμα ανάκλησης της καταχώÏησης που θέλεις να Ï„Ïοποποιήσεις: + +/editjournal_do.bml.error.modify=Σφάλμα κατα την Ï„Ïοποποίηση του ημεÏολογίου: + +/editjournal_do.bml.error.nofind=Δεν βÏέθηκε η επιλεγμένη καταχώÏηση. + +/editjournal_do.bml.event=Γεγονός: + +/editjournal_do.bml.localtime=Τοπική ÏŽÏα: + +/editjournal_do.bml.noneother=Καμία, η άλλη: + +/editjournal_do.bml.opt.backdate=ΕτεÏοχÏονισμένη ΚαταχώÏηση: + +/editjournal_do.bml.opt.backdate.about=δεν θα εμφανιστεί στην σελίδα των φίλων σου + +/editjournal_do.bml.opt.nocomments=ΑπαγόÏευση Σχολίων: + +/editjournal_do.bml.opt.noemail=ΧωÏίς email Σχολίων + +/editjournal_do.bml.opt.noformat=ΧωÏίς αυτόματη Ï„Ïοποποίηση: + +/editjournal_do.bml.other=Άλλο: + +/editjournal_do.bml.pickentry.head=Διάλεξε μια καταχώÏηση για Ï„Ïοποποίηση + +/editjournal_do.bml.pickentry.text=Διάλεξε ποιό αντικείμενο θέλεις να Ï„Ïοποποίησεις και πάτα το κουμπί Ï„Ïοποποίησης στο τέλος της σελίδας. + +/editjournal_do.bml.picture=Εικόνα για χÏήση: + +/editjournal_do.bml.save.head=Πάτα για αποθήκευση.. + +/editjournal_do.bml.save.text=Î‘Ï†Î¿Ï Ï„ÎµÎ»ÎµÎ¹ÏŽÏƒÎµÎ¹Ï‚ την Ï„Ïοποποίηση της καταχώÏησής σου, πάτα Αποθήκευση. + +/editjournal_do.bml.subject=Θέμα: (Ï€ÏοαιÏετικό) + +/editjournal_do.bml.success.delete=Η καταχώÏηση διεγÏάφη. + +/editjournal_do.bml.success.edit=Η καταχώÏηση Ï„Ïοποποιήθηκε. ΜποÏείς να την δεις εδώ. + +/editjournal_do.bml.success.head=Επιτυχία + +/editjournal_do.bml.timeformat=ÏŽÏα με 24ωÏη μοÏφή + +/editjournal_do.bml.title=ΤÏοποποίηση ΚαταχωÏήσεων + +/editpics.bml.btn.proceed=Συνέχεια + +/editpics.bml.btn.save=Αποθήκευση Επιλογών + +/editpics.bml.curpics=ΤÏέχουσες Εικόνες + +/editpics.bml.curpics.desc=Εδώ βÏίσκονται οι εικόνες που υπέβαλλες στο παÏελθόν. ΜποÏείς να τους αναθέσεις λέξεις-κλειδιά για να τις χÏησιμοποιείς με αυτά αÏγότεÏα, να διαλέξεις ποιά να θεωÏηθει ?? ή να σβησεις παλιές. Για να υποβάλλεις νέα εικόνα, χÏησιμοποίησε τη φόÏμα στο τέλος της σελίδας. + +/editpics.bml.error.badurl=Η διεÏνθυνση για την εικόνα που θέλεις να υποβάλλεις δεν μου φαίνεται σωστή. Θα έπÏεπε να αÏχίζει με http:// + +/editpics.bml.error.filetoolarge=Η εικόνα που υπέβαλλες είναι υπεÏβολικά μεγάλη. Το μέγεθος του αÏχείου δεν Ï€Ïέπει να ξεπεÏνάει τα [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Οι διαστάσεις της εικόνας σου ([[imagesize]]) ξεπεÏνοÏν το ανώτατο ÏŒÏιο. Η εικόνα σου μποÏεί να είναι το Ï€Î¿Î»Ï 100x100 pixel. ΧÏησιμοποίησε ένα Ï€ÏόγÏαμμα επεξεÏγασίας εικόνας για να την μικÏÏνεις σε μέγεθος. + +/editpics.bml.error.invalidimage=Εσφαλμένο αÏχείο εικόνας. + +/editpics.bml.error.keywords=ΧÏησιμοποίησες την λέξη-κλειδί "[[ekw]]" για πολλές φωτογÏαφίες. Μία απ' αυτές επιλέχθη τυχαία, αλλά πιθανότατα όχι αυτή που ήθελες. ΜποÏείς να επιστÏέψεις και να το διοÏθώσεις. + +/editpics.bml.error.toomanypics2=Î’Ïίσκεσαι ήδη στο ÏŒÏιο των [[maxpics]] εικόνων. Δε μποÏείς να υποβάλλεις αυτή την εικόνα μέχÏι να διαγÏάψεις μία απ' τις ήδη υπάÏχουσες. + +/editpics.bml.error.unsupportedtype=Δεν υποστηÏίζονται αÏχεία Ï„Ïπου [[filetype]]. ΜποÏείς να υποβάλλεις μόνο αÏχεία GIF, PNG και JPG. Σχεδόν όλα τα Ï€ÏογÏάμματα εικόνων/φωτογÏαφιών μποÏοÏν να κάνουν αυτή την μετατÏοπή για σένα. + +/editpics.bml.error.urlerror=ΠÏοέκυψε σφάλμα στην ανάκτηση της εικόνας σου. + +/editpics.bml.fromfile=Απο ΑÏχείο: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=α + +/editpics.bml.fromurl=Από URL: + +/editpics.bml.imagesize.by|notes=This character is inserted between two numbers to indicate "by" when specifying image dimensions, for example "100x100". +/editpics.bml.imagesize.by=επί + +/editpics.bml.label.default=ΠÏοεπιλεγμένο: + +/editpics.bml.label.delete=ΔιαγÏαφή: + +/editpics.bml.label.keywords=Λέξεις-Κλειδιά: + +/editpics.bml.makedefault=ΧÏησιμοποίησε τη συγκεκÏιμένη φωτογÏαφία ως Ï€Ïοεπιλογή. + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=Ï€ + +/editpics.bml.nodefault=Δεν υπάÏχει Ï€Ïοεπιλεγμένη εικόνα + +/editpics.bml.noneupload=Δεν έχεις υποβάλλει εικόνες. ΠαÏακαλώ υπόβαλλε μία χÏησιμοποιώντας την παÏακάτω φόÏμα. + +/editpics.bml.nopics=Καμία Εικόνα + +/editpics.bml.restriction.fileformat=Το αÏχείο Ï€Ïέπει να είναι Ï„Ïπου PNG, GIF ή JPG + +/editpics.bml.restriction.filesize=Το αÏχείο Ï€Ïέπει να είναι μικÏότεÏο απο 40k σε μέγεθος + +/editpics.bml.restriction.imagesize=Οι διαστάσεις της εικόνας δεν Ï€Ïέπει να υπεÏβαίνουν τα 100 επί 100 pixel. + +/editpics.bml.title=ΤÏοποποίηση Εικόνων ΧÏήστη + +/editpics.bml.uploaddesc=ΧÏησιμοποίησε την παÏακάτω φόÏμα για να ανεβάσεις μια νέα εικόνα. + +/editpics.bml.uploadheader=Υποβολή Îέας Εικόνας + +/export.bml.btn.proceed=Συνέχεια... + +/export.bml.description=Το παÏακάτω χαÏακτηÏιστικό σου επιτÏέπει να καταφοÏτώσεις ολόκληÏο το ημεÏολόγιό σου σε διαμόÏφωση του γοÏστου σου για λόγους εφεδÏικής αποθήκευσης. Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με την εφεδÏική αποθήκευση του ημεÏολογίου, δες αυτό το FAQ. + +/export.bml.fields=Τομεις: + +/export.bml.label.encoding=Κωδικοποίηση: + +/export.bml.label.field.allowmask=ΕπέτÏεψε την επικάλυψη + +/export.bml.label.field.currents=ΤÏέχουσα Διάθεση & Μουσική + +/export.bml.label.field.event=Γεγονός + +/export.bml.label.field.eventtime=ΧÏονολόγησε το γεγονός (από το Ïολόι του χÏήστη) + +/export.bml.label.field.itemid=ΑÏιθμός ταυτότητας + +/export.bml.label.field.logtime=ΧÏονολόγησε το μητÏώο (από το Ïολόι του συστήματος) + +/export.bml.label.field.security=Επίπεδο Ασφαλείας + +/export.bml.label.field.subject=Θέμα + +/export.bml.label.format=ΜοÏφή: + +/export.bml.label.header=Επικεφαλίδα + +/export.bml.label.month=Επέλεξε μήνα: + +/export.bml.label.month.month=μμ: + +/export.bml.label.month.year=χχχχ: + +/export.bml.label.notranslation=Μη μεταφÏάζεις Î¼ÎµÏ„Î±Î¾Ï ÎºÏυπτογÏαφήσεων. + +/export.bml.label.what=Τι να εξάγεις: + +/export.bml.title=Îα εξάγεις το ΗμεÏολόγιο + +/export.bml.what.entries=ΚαταχωÏήσεις ΗμεÏολογίου + +/friends/add.bml.add.header=Επιτυχία + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=Ο χÏήστης Ï€Ïοστέθηκε στον κατάλογο φίλων σου. ΜποÏείς να διαβάσεις τη σελίδα των φίλων σου εδώ. + +/friends/add.bml.add.title=Ο φίλος Ï€Ïοστέθηκε! + +/friends/add.bml.btn.add=ΠÏόσθεση [[user]] + +/friends/add.bml.btn.modify=ΤÏοποποίηση + +/friends/add.bml.btn.remove=ΑφαίÏεση + +/friends/add.bml.colors.bg=Φόντο + +/friends/add.bml.colors.fg=ΠÏώτο πλάνο + +/friends/add.bml.colors.header=ΧÏώματα + +/friends/add.bml.colors.hover=(Κίνησε το ποντίκι σου πάνω σ' ένα χÏώμα για να δεις το όνομά του) + +/friends/add.bml.colors.text=ΜποÏείς επίσης, αν θέλεις, να διαλέξεις τα χÏώματα που θα αντιπÏοσοπεÏουν [[user]] στον κατάλαγο των φίλων σου. + +/friends/add.bml.confirm.header=ΠÏόσθεση του [[user]] στους φίλους σου; + +/friends/add.bml.confirm.text=Για να Ï€Ïοσθέσεις τον [[user]]στον λίστα φίλων σου, κάνα κλικ στο κάτω κουμπί. + +/friends/add.bml.confirm.title=ΠÏόσθεση φίλου + +/friends/add.bml.error1.header=Συνδέσου ΠÏώτα + +/friends/add.bml.error1.text=Για να Ï€Ïοσθέσεις έναν χÏήστη στη λίστα φίλων σου Ï€Ïέπει Ï€Ïώτα να κάνεις log in. Αν δεν έχεις λογαÏιασμό ήδη, μποÏείς να δημιουÏγήσεις για να παÏακολουθείς τα ημεÏολόγια των φίλων σου. + +/friends/add.bml.error1.title=ΠÏόσθεση φίλου + +/friends/add.bml.error2.text=Δόθηκε άκυÏο ή ανÏπαÏκτο όνομα χÏήστη, Για να Ï€Ïοσθέσεις έναν φίλο, πήγαινε στη σελίδα Ï„Ïοποποίησης φίλων. + +/friends/add.bml.error3.text=Ο [[user]] είναι ήδη στον κατάλογο των φίλων σου. ΜποÏείς, όμως, να αλλάξεις τα χÏώματα που επέλεξες για να τον/την αντιπÏοσωπεÏουν + +/friends/add.bml.error3.title=ΤÏοποποίηση Φίλου + +/friends/add.bml.groups.header=Ομάδες Φίλων + +/friends/add.bml.groups.nogroup=Δεν έχουν εγκατασταθεί ομάδες με φίλους + +/friends/add.bml.remove.header=Επιτυχία + +/friends/add.bml.remove.text=Ο χÏήστης διεγÏάφηκε από τον κατάλογο των φίλων σου. ΜποÏείς να διαβάσεις τη σελίδα των φίλων σου εδώ. + +/friends/add.bml.remove.title=Φίλος διεγÏάφηκε! + +/friends/editgroups.bml.btn.ge.del=ΔιαγÏαφή + +/friends/editgroups.bml.confirm.delete=Είσαι σίγουÏος(η) ότι θέλεις να διαγÏάψεις αυτή την ομάδα φίλων; + +/friends/editgroups.bml.ingroup=Στην ομάδα: + +/friends/editgroups.bml.ingroup.not=Όχι στην ομάδα: + +/friends/edit_do.bml.addfriends.head=ΠÏόσθεση Φίλων + +/friends/edit_do.bml.addfriends.text=Εισήγαγε τα ονόματα χÏήστη στο LiveJournal των φίλων σου στα παÏακάτω κουτιά και διάλεξε τι χÏώματα φόντου και ?? θέλεις να σχετίσεις μαζί τους. + +/friends/edit_do.bml.background=Φόντο + +/friends/edit_do.bml.bgcolor=ΧÏώμα Φόντου: + +/friends/edit_do.bml.btn.close=Κλείσιμο + +/friends/edit_do.bml.btn.save=Αποθήκευση Αλλαγών + +/friends/edit_do.bml.done.head=Τελείωσες; + +/friends/edit_do.bml.done.text=Μόλις τελειώσεις, πάτα το κουμπί "Αποθήκευση Αλλαγών" πιο κάτω... + +/friends/edit_do.bml.error.updating=ΠÏοέκυψε σφάλμα στην ανανέωση της λίστας φίλων σου: + +/friends/edit_do.bml.fellowfriends.head=Κοινοί Φίλοι + +/friends/edit_do.bml.fellowfriends.text=Τα παÏακάτω άτομα σε έχουν καταχωÏημένο ως φίλο. ΜποÏεί να θέλεις να τους καταχωÏήσεις επίσης σαν φίλους. Αυτό σου δίδεται ως αναφοÏά, ωστε να ξέÏεις τα ονόματα χÏήστη τους στο LiveJournal. Δεν έχεις καμία υποχÏέωση να τους Ï€Ïοσθέσεις στη λίστα σου. + +/friends/edit_do.bml.friend=Φίλος + +/friends/edit_do.bml.hover=Κίνησε το ποντίκι σου πάνω σ' ένα χÏώμα για να δεις το όνομά του + +/friends/edit_do.bml.name=Όνομα + +/friends/edit_do.bml.needmore=Αν θέλεις να Ï€Ïοσθέσεις πεÏισσότεÏους φίλους απ' όσους χωÏάνε σε αυτή τη φόÏμα, αποθήκευσε τις παÏακάτω αλλαγές και επίστÏεψε για να Ï€Ïοσθέσεις και άλλους. + +/friends/edit_do.bml.nofriends.head=Κανένας φίλος; + +/friends/edit_do.bml.nofriends.text=Δε διάλεξες κανένα φίλο ÏŽÏ‚ Ï„ÏŽÏα. Αλλά σίγουÏα έχεις φίλους! :) Απλώς γÏάψε τα ονόματα LJ τους εδώ κάτω... + +/friends/edit_do.bml.opt.delete=ΑπογÏαφή; + +/friends/edit_do.bml.success.head=Επιτυχία + +/friends/edit_do.bml.user=ΧÏήστης + +/friends/edit_do.bml.yourfriends.head=Οι φίλοι σου + +/friends/edit_do.bml.yourfriends.text=Αυτή τη στιγμή έχεις καθοÏισμένους τους παÏακάτω ως φίλους: + +/friends/filter.bml.editgroups='Αν θέλεις να Ï„Ïοποποιήσεις τις ομάδες φίλων σου, πήγαινε στην σελίδα [[link]]. + +/friends/filter.bml.error.nogroups=Δεν μποÏείς να φιλτÏάÏεις την λίστα φίλων σου γιατί Ï€Ïέπει Ï€Ïώτα να δημιουÏγήσεις τις ομάδες φίλων. + +/friends/filter.bml.error.nogroups.header=Καμία ΟÏισμένη Ομάδα + +/friends/filter.bml.select=Επίλεξε τις ομάδες φίλων που θέλεις να εμφανίσεις στη λίστα φίλων σου. + +/friends/filter.bml.select.header=Επιλογή Ομάδων + +/friends/filter.bml.submit=Εμφάνιση! + +/friends/filter.bml.title=ΦίλτÏο Φίλων + +/friends/index.bml.about<< +Αυτή η σελίδα σου επιτÏέπει να διαχειÏίζεσαι τη λίστα φίλων σου. +ΠÏοσθέτοντας άλλους χÏήστες στην λίστα φίλων σου, μποÏείς να δεις εÏκολα τις καταχωÏήσεις τους στην σελίδα φίλων σου. ΜποÏείς επίσης να Ï€Ïοσθέσεις κοινότητες και Ï€ÏακτοÏεία στην λίστα φίλων σου ώστε να βλέπεις τις καταχωÏήσεις τους στην σελίδα φίλων. +. + +/friends/index.bml.edit.about=ΠÏόσθεσε ή διέγÏαψε χÏήστες απ΄τη λίστα φίλων, ή Ï„Ïοποποίησε τα χÏώματα που τους αντιπÏοσωπεÏουν. + +/friends/index.bml.editgroups.about=ΔημιοÏÏγησε, Ï„Ïοποποίησε ή διάγÏαψε υποομάδες των φίλων σου. + +/friends/index.bml.filter=Αυτές οι ομάδες φίλων μποÏοÏν να χÏησιμοποιηθοÏν για να φιλτÏάÏεις την επισκόπηση φίλων σου: μποÏείς να εμφανίσεις μόνο τις καταχωÏήσεις μιας συγκεκÏιμένης ομάδας. ΜποÏοÏν επίσης να χÏησιμοποιηθοÏν για ασφάλεια βασισμένη σε ομάδες (βλέπε παÏακάτω). + +/friends/index.bml.filter.about=ΦίλτÏαÏε την λίστα φίλων σου σÏμφωνα με συγκεκÏιμένες υποομάδες. + +/friends/index.bml.groups=ΕπιπÏόσθετα, μποÏοÏν να καθοÏιστοÏν υποομάδες ή φίλοι. + +/friends/index.bml.security=Η λίστα φίλων σου χÏησιμοποιείται επίσης για καταχωÏήσεις με πεÏιοÏισμένη Ï€Ïόσβαση. ΜποÏείς να μάθεις πεÏισσότεÏα για την ασφάλεια της λίστας φίλων στο Φίλοι & Επίπεδα Ασφαλείας. + +/friends/index.bml.security.custom=Με τις καταχωÏήσεις "custom", μποÏείς να οÏίσεις ποιές ομάδες φίλων μποÏοÏν να δουν την καταχώÏησή σου. ΠαÏ' όλα αυτά όλοι οι clients δεν υποστηÏίζουν την custom ασφάλεια για την ÏŽÏα. + +/friends/index.bml.security.header=Ασφάλεια + +/friends/index.bml.security.only=Με τις καταχωÏήσεις "Μόνο για Φίλους", οποιοσδήποτε χÏήστης στην λίστα φίλων σου μποÏεί να δει την καταχώÏησή σου. + +/friends/index.bml.title=ΕÏγαλεία Φίλων + +/friends/index.bml.tools=ΕÏγαλεία + +/friends/popwithfriends.bml.account_type=Λυπάμαι, ο Ï„Ïπος του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… δεν σου επιτÏέπει + +/friends/popwithfriends.bml.count=ΜέτÏημα + +/friends/popwithfriends.bml.exclude_own=ΜποÏείς, Ï€ÏοαιÏετικά, να παÏαλείψεις τους φίλους σου. + +/friends/popwithfriends.bml.include_own=ΜποÏείς, Ï€ÏοαιÏετικά, να συμπεÏιλάβεις τους φίλους σου. + +/friends/popwithfriends.bml.intro=Οι παÏακάτω φίλοι εμφανίζονται συχνά από τους φίλους σου, αλλά όχι από εσένα. + +/friends/popwithfriends.bml.intro_own=Οι παÏακάτω φίλοι εμφανίζονται συχνά απο τους φίλους σου. Η λίστα πεÏιλαμβάνει επίσης και τους φίλους σου. + +/friends/popwithfriends.bml.no_users=Κανένας χÏήστης + +/friends/popwithfriends.bml.title=Δημοφιλείς ΧÏήστες Στους Φίλους Σου + +/friends/popwithfriends.bml.user=ΧÏήστης + +/index.bml.boldcreate=ΔημιοÏÏγησε δικό σου LiveJournal! + +/index.bml.frank.image.alt=Ο ΦÏανκ, ο Ï„Ïάγος-μάσκοτ του LiveJournal. + +/index.bml.frank.logo=Ο ΦÏάνκ λέει "Μπεεεεεεεεεεεε". + +/index.bml.meta.desc=Το LiveJournal.com είναι ενα μέÏος οπου μποÏείς να μοιÏαστείς τις σκέψεις σου με τον κόσμο. + +/interests.bml.add.added.head=ΠÏοστέθηκε! + +/interests.bml.add.added.text=Αυτό το ενδιαφέÏον έχει Ï€Ïοστεθεί στη λίστα σου. + +/interests.bml.add.btn.text=ΠÏόσθεση του [[interest]] + +/interests.bml.add.confirm.head=Επιβεβάιωση + +/interests.bml.add.confirm.text=Για να Ï€Ïοσθέσεις το [[interest]] σαν ενδιαφέÏον, πάτα το παÏακάτω κουμπί. + +/interests.bml.add.toomany.head=Λυπάμαι... + +/interests.bml.add.toomany.text=Επίλεξες κιόλας [[maxinterests]] ενδιαφέÏοντα. + +/interests.bml.addint=Αν ενδιαφέÏεσαι επίσης για αυτό και θα ήθελες να Ï€Ïοστεθείς σ' αυτή τη λίστα, πάτα εδώ. + +/interests.bml.communities.head=Σχετικές Κοινότητες + +/interests.bml.communities.text=Οι παÏακάτω κοινότητες ενδιαφέÏονται επίσης για "[[interest]]". + +/interests.bml.count=ΑÏιθμός + +/interests.bml.enmasse.body.other=ΠαÏακάτω βÏίσκονται τα ενδιαφέÏοντα του [[user]]. Επίλεξε τα κουτάκια δίπλα στα ενδιαφέÏοντα που θα ήθελες να Ï€ÏοστεθοÏν στα δικά σου, και βγάλε την επιλογή απ΄τα κουτάκια δίπλα στα ενδιαφέÏοντα που θέλεις να αφαιÏέσεις απ' τα δικά σου. Όταν τελειώσεις, πάτα το "Αποθήκευση Αλλαγών". + +/interests.bml.enmasse.body.other_authas=ΠαÏακάτω βÏίσκονται τα ενδιαφέÏοντα του [[user]]. Επίλεξε τα κουτάκια δίπλα στα ενδιαφέÏοντα που θα ήθελες να Ï€ÏοστεθοÏν σ'αυτά του [[target]] , και βγάλε την επιλογή απ΄τα κουτάκια δίπλα στα ενδιαφέÏοντα που θέλεις να αφαιÏέσεις. Όταν τελειώσεις, πάτα το "Αποθήκευση Αλλαγών". + +/interests.bml.enmasse.body.you=Βγάλε την επιλογή από τα κουτάκια δίπλα στα ενδιαφέÏοντα που θέλεις να αφαιÏέσεις. Όταν τελειώσεις, πάτα το "Αποθήκευση Αλλαγών". + +/interests.bml.enmasse.btn=Εμφάνιση λίστας + +/interests.bml.enmasse.header=ΠÏόσθεση/ΑφαίÏεση ενδιαφεÏόντων + +/interests.bml.enmasse.intro=ΤÏοποποίηση των ενδιαφεÏόντων σου βασισμένη στα ενδιαφέÏοντα του: + +/interests.bml.error.enmasse.noaccess=Φαίνεται πως δεν έχεις Ï€Ïόσβαση στο ημεÏολόγιο [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Αυτό το ενδιαφέÏον δε βÏέθηκε. + +/interests.bml.error.nointerests=Ο επιλεγμένος χÏήστης δεν υπάÏχει ή δεν έχει οÏίσει ενδιαφέÏοντα. + +/interests.bml.findsim_do.account.notallowed=Λυπόμαστε, ο Ï„Ïπος του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… δε σου επιτÏέπει να χÏησιμοποιήσεις αυτό το εÏγαλείο. + +/interests.bml.findsim_do.magic=Μαγικός
        Κατάλογος + +/interests.bml.findsim_do.nomatch.text=Κανένας χÏήστης δεν ειναι παÏόμοιος με τον [[user]]. + +/interests.bml.findsim_do.notdefined=Ο [[user]] δεν επέλεξε ενδιαφέÏοντα. + +/interests.bml.findsim_do.similar.head=ΠαÏόμοιοι ΧÏήστες + +/interests.bml.findsim_do.similar.text=ΠαÏακάτω είναι οι πιο όμοιο με τον [[user]] χÏήστες. + +/interests.bml.finished.about=Όταν τελειώσεις, πάτα το κουμπί "Αποθήκευση Αλλαγών" πιο κάτω. + +/interests.bml.finished.header=Τελείωσες; + +/interests.bml.finished.save_button=Αποθήκευση Αλλαγών + +/interests.bml.interest=ΕνδιαφέÏον + +/interests.bml.interested.btn.find=ΈÏευνα + +/interests.bml.interested.in=Ψάξε για άτομα και κοινότητες που τους ενδιαφέÏει: + +/interests.bml.interests.findsim=Ψάξε για άτομα με παÏόμοια ενδιαφέÏοντα με τον: + +/interests.bml.interests.head=ΕνδιαφέÏοντα + +/interests.bml.interests.text=ΟÏίστε μεÏικά διασκεδαστικά Ï€Ïάγματα που μποÏείς να κάνεις με τα ενδιαφέÏοντα. + +/interests.bml.interests.viewpop=Εμφάνιση δημοφιλών ενδιαφεÏόντων + +/interests.bml.login.enterinfo=Εισήγαγε το όνομα χÏήστη και τον κωδικό σου για να Ï„Ïοποποιήσεις τα ενδιαφέÏοντά σου. + +/interests.bml.login.proceed=Συνέχεια... + +/interests.bml.results.del_and_toomany=Τα ενδιαφέÏοντα που επέλεξες να διαγÏάψεις διαγÏάφηκαν επιτυχώς από τη λίστα ενδιαφεÏόντων σου. ΠαÏ'όλα αυτά επέλεξες υπεÏβολικά πολλά ενδιαφέÏοντα για Ï€Ïόσθεση. ΜποÏείς να έχεις μόνο [[intcount]] ενδιαφέÏοντα συνολικά. Κανένα απ' τα επιλεγμένα ενδιαφέÏοντα δεν Ï€Ïοστέθηκαν στη λίστα ενδιαφεÏόντων σου. ΜποÏεί να θέλεις να επιστÏέψεις και να ξαναδοκιμάσεις, διαλέγοντας λιγότεÏα ενδιαφέÏοντα για Ï€Ïόσθεση. + +/interests.bml.results.goback=ΜποÏεί να θέλεις να επιστÏέψεις στο < href='[[url]]'>Ï€Ïοφίλ του [[user]] το οποίο έβλεπες Ï€Ïοηγουμένως. + +/interests.bml.results.header=Αποτελέσματα + +/interests.bml.results.message=Εμφάνιση της ενημεÏωμένης σελίδασ Ï€Ïοφίλ σου. + +/interests.bml.results.nothing=Δεν έκανες καμία αλλαγή. + +/interests.bml.results.toomany=Επέλεξες υπεÏβολικά πολλά ενδιαφέÏοντα για Ï€Ïόσθεση. ΜποÏείς να έχεις μόνο [[intcount]] ενδιαφέÏοντα συνολικά. Κανένα απ' τα επιλεγμένα ενδιαφέÏοντα δεν Ï€Ïοστέθηκαν στη λίστα ενδιαφεÏόντων σου. ΜποÏεί να θέλεις να επιστÏέψεις και να ξαναδοκιμάσεις, διαλέγοντας λιγότεÏα ενδιαφέÏοντα για Ï€Ïόσθεση. + +/interests.bml.title=ΕνδιαφέÏοντα + +/interests.bml.toomany.body=ΥπάÏχουν [[intcount]] άτομα ή/και κοινότητες με καταχωÏημένο αυτό το ενδιαφέÏον. Δεν θα εμφανιστεί λίστα. + +/interests.bml.toomany.head=Πολλές αντιστοιχίες + +/interests.bml.users.head=ΕνδιαφεÏόμενοι χÏήστες + +/interests.bml.users.text=Τους ακόλουθους χÏήστες τους ενδιαφέÏει επίσης το [[interest]]. + +/invite/index.bml.code=Κώδικας + +/invite/index.bml.error=Λάθος + +/invite/index.bml.genmore=ΔημιουÏγία πεÏισσότεÏων κωδικών. + +/invite/index.bml.how_detail=ΣÏμφωνα με έναν αÏιθμό παÏαγόντων, οι ήδη χÏήστες επιτÏέπεται να Ï€Ïοσκαλέσουν έναν συγκεκÏιμένο αÏιθμό άλλων χÏηστών για να μπουν στο LiveJournal. Για να Ï€Ïοσκαλέσεις κάποιον Ï€Ïέπει να δημιουÏγήσεις έναν κώδικα Ï€Ïόσκλησης και να του τον δώσεις. + +/invite/index.bml.how_header=Πώς λειτουÏγεί; + +/invite/index.bml.invite_header=ΠÏοσκλήσεις; + +/invite/index.bml.none=Καμία + +/invite/index.bml.redeemed=ΕξαÏγυÏώθηκε από + +/invite/index.bml.title=ΠÏοσκάλεσε άλλους στο LiveJournal... + +/invite/index.bml.unused=ΑχÏησιμοποίητος + +/invite/index.bml.use=χÏήση + +/legal/index.bml.about<< +Το LiveJournal είναι αφοσιωμένο στην Ï€ÏοσφοÏά μιας σταθεÏής και ουσιώδους εμπειÏίας για μέλη από όλους τους πολιτισμοÏÏ‚ και τα έθνη, οπότε για να το καταφέÏουμε αυτό έχουμε ετοιμάσει μεÏικοÏÏ‚ κανόνες. +Αυτά τα επίσημα έγγÏαφα πεÏιλαμβάνουν λογικοÏÏ‚ ÏŒÏους και πληÏοφοÏίες σχετικές με τον καλÏτεÏο Ï„Ïόπο που θα ενεÏγήσουμε για να σε εξυπηÏετήσουμε, και τον Ï„Ïόπο που πεÏιμένουμε να συμπεÏιφέÏονται τα μέλη σε εμάς και τους άλλους. Το LiveJournal δουλέυει καλÏτεÏα όταν τα άτομα ακολουθοÏν αυτοÏÏ‚ τους κανόνες. ΟÏίστε μεÏικοί απ' τους σημαντικότεÏους για να θυμάσαι: +
          +
        • Μην παÏενοχλείς, κακομεταχειÏίζεσαι ή απειλείς τους άλλους.
        • +
        • Μην βλάπτεις με οποιονδήποτε Ï„Ïόπο ανηλίκους.
        • +
        • Μην γεμίζεις με διαφημίσεις το site ή οποιονδήποτε λογαÏιασμό στο site.
        • +
        • Μην καταχωÏείς πεÏιεχόμενο χωÏίς να έχεις τα δικαιώματά του ή την άδεια του συγγÏαφέα του.
        • +
        • Μην εισβάλλεις στην ???μυστικότητα?? των άλλων.
        • +
        • Μην παÏαβαίνεις τον νόμο των ΗΠΑ ή τους τοπικοÏÏ‚ σου νόμους με οποιονδήποτε Ï„Ïόπο.
        • +
        +Η πλήÏης λίστα κανόνων και πολιτικής βÏίσκεται παÏακάτω: +. + +/legal/index.bml.docs.coppa.about=Η ΔÏάση ΠÏοστασίας της Παιδικής Μυστικότητας στο Διαδίκτυο (COPPA) πεÏιοÏίζει την συλλογή στο διαδίκτυο των Ï€Ïοσωπικών δεδομένων που υποβάλλονται από και αφοÏοÏν τα παιδιά ηλικίας κατώτεÏης των δεκατÏιών. Η σελίδα μας που αναφέÏεται στην COPPA εξηγεί την στάση μας απέναντι σ'αυτόν τον νόμο και σκιαγÏαφεί τον Ï„Ïόπο αντιμετώπισης των θεμάτων της COPPA. + +/legal/index.bml.docs.header=Κείμενα + +/legal/index.bml.docs.privacy.about=Η ΑÏχή ΠÏοστασίας ΠÏοσωπικών Δεδομένων μας σκιαγÏαφεί ποιά δεδομένα συλλέγουμε από τα μέλη μας και εξηγεί πώς χÏησιμοποιοÏμε αυτές τις πληÏοφοÏίες. + +/legal/index.bml.docs.tos.about=Οι ÎŒÏοι ΧÏήσης σκιαγÏαφοÏν τις πολιτικές χÏήσης μας, όπως και τους γενικοÏÏ‚ κανόνες και ÏŒÏους συνδÏομής. Η συνδÏομή ή και η χÏήση του συστήματος αποτελεί συμφωνία για συμμόÏφωση με αυτοÏÏ‚ και όλους τους άλλους ÏŒÏους που σε βÏήκαν σÏμφωνο. + +/legal/index.bml.title=Îομικές ΠληÏοφοÏίες + +/legal/privacy.bml.title=ΑÏχή ΠÏοστασίας ΠÏοσωπικών Δεδομένων + +/legal/tos.bml.title=ÎŒÏοι ΧÏήσης + +/login.bml.bindip.label=Δέσμευση σε διέυθυνση IP: + +/login.bml.bindip.no=Όχι (δουλεÏει με όλους τους ISP) + +/login.bml.bindip.yes=Îαι (ασφαλέστεÏο) + +/login.bml.error.mustenterusername=ΠÏέπει να εισάγεις ένα όνομα χÏήστη. + +/login.bml.expire.btn.neverexpire=Αλλαγή μεθόδου λήξης σε ΠΟΤΕ. + +/login.bml.expire.btn.sessiononly=Αλλαγή μεθόδου λήξης σε ΜΟÎΟ Σ'ΑΥΤΗ ΤΗ ΣΥÎΔΕΣΗ. + +/login.bml.expire.neverexpire.text=H είσοδος σου δεν θα λήξει ποτέ, οπότε αν βÏίσκεσαι σε δημόσιο παÏοχέα διαδικτÏου, σε σχολείο, βιβλιοθήκη, ή άλλο μέÏος οπου άλλοι μποÏεί να χÏησιμοποιήσουν σÏντομα αυτόν τον υπολογιστή, σιγουÏέψου την έξοδο όταν τελειώσεις! Ή άλλαξε τον Ï„Ïόπο εισόδου σου ώστε να λήγει όταν κλείνεις τον πλοηγό σου. + +/login.bml.links.link1=Η σελίδα των φίλων σου. + +/login.bml.links.text=Μελλοντικά αυτή η σελίδα θα έχει διαφόÏων ειδών συνδέσμους και σχετικές πληÏοφοÏίες, αλλά για την ÏŽÏα οÏίστε μεÏικά μέÏη που μποÏεί να θέλεις να πας: + +/login.bml.loggedin.head=Συνδεδεμένος! + +/login.bml.loggedin.text=ΤώÏα είσαι συνδεδεμένος. + +/login.bml.login.btn.changeopts=Αλλαγή Επιλογών + +/login.bml.login.btn.login=Είσοδος... + +/login.bml.login.expiration=Λήξη: + +/login.bml.login.forget=Λησμόνηση; + +/login.bml.login.head=Είσοδος + +/login.bml.login.never=Ποτέ + +/login.bml.login.otheropts=Άλλες Επιλογές: + +/login.bml.login.password=Κωδικός: + +/login.bml.login.text1=Για να μπεις στο [[sitename]], βάλε το όνομα χÏήστη και τον κωδικό σου παÏακάτω. ΚαινοÏÏγιοι ΧÏήστες: Για να δημιουÏγήσετε λογαÏιασμό, πηγαίνετε εδώ. + +/login.bml.login.username=Όνομα χÏήστη + +/login.bml.login.whenbrowsercloses=Όταν κλείνει ο πλοηγός + +/login.bml.logout.btn=Έξοδος + +/login.bml.title=Είσοδος + +/login.bml.whylogin.benefit1=Δεν θα αναγκάζεσαι πλέον να εισάγεις το όνομα και τον κωδικό σου οπουδήποτε στο site. + +/login.bml.whylogin.benefit2=Θα μποÏείς να βλέπεις τις "Ï€Ïοστατευμένες" καταχωÏήσεις από τους φίλους σου που σου δίνουν Ï€Ïόσβαση να τις διαβάσεις. + +/login.bml.whylogin.benefit3=Πολλές επιλογές είναι οÏατές ή Ï€Ïοσβάσιμες μόνο όταν είσαι συνδεδεμένος. + +/login.bml.whylogin.head=Γιατί να κάνω είσοδο; + +/login.bml.whylogin.text=ΟÏίστε μεÏικά από τα κÏÏια οφέλη της εισόδου: + +/logout.bml.already.head=Ήδη αποσυνδεδεμένος + +/logout.bml.already.text=Είσαι ήδη αποσυνδεδεμένος. + +/logout.bml.killall.btn=Λήξη όλων των συνδέσεών μου + +/logout.bml.killall.head=Άλλες συνδέσεις + +/logout.bml.killall.text=Έχεις άλλες ενεÏγές συνδέσεις. Θέλεις να λήξεις όλες τις συνδέσεις σου, και όχι μόνο αυτή; (Βλέπε αυτό το FAQ για πεÏισσότεÏες πληÏοφοÏίες.) + +/logout.bml.loggedout.already=Ήδη αποσυνδεδεμένος. + +/logout.bml.loggedout.head=Αποσυνδεδεμένος + +/logout.bml.loggedout.killedall=Όλες σου οι συνδέσεις έχουν λήξει. + +/logout.bml.loggedout.success=Αποσυνδεδεμένος. + +/logout.bml.loggedout.text=Είσαι Ï„ÏŽÏα αποσυνδεδεμένος. + +/logout.bml.logout.btn=ΑποσÏνδεση + +/logout.bml.logout.head=ΑποσÏνδεση; + +/logout.bml.logout.text=Πάτα το παÏακάτω κουμπί για να αποσυνδεθείς. + +/logout.bml.title=ΑποσÏνδεση + +/lostinfo.bml.btn.proceed=Συνέχεια + +/lostinfo.bml.enter_email=ΓÏάψε τη διεÏθυνσή σου ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου: + +/lostinfo.bml.enter_email_optional=Διέυθυνση email: (Ï€ÏοαιÏετική) + +/lostinfo.bml.enter_username=ΓÏάψε το όνομα χÏήστη σου: + +/lostinfo.bml.error.no_email=ΠÏέπει να εισάγεις μια διεÏθυνση email για να επανακτήσεις το όνομα χÏήστη σου. + +/lostinfo.bml.error.purged=Δεν γίνεται ανάκτηση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Î³Î¹Î± έναν διεγÏαμμένο λογαÏιασμό Î±Ï†Î¿Ï ÎµÎºÎºÎ±Î¸Î±Ïιστεί. + +/lostinfo.bml.error.renamed=Δεν γίνεται ανάκτηση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Î³Î¹Î± μετονομασμένο λογαÏιασμό. + +/lostinfo.bml.error.sysbanned=Ο λογαÏιασμός σου δεν επιτÏέπεται να αποστέλλει κωδικοÏÏ‚ μέσω email. + +/lostinfo.bml.lostpassword.text=Άν έχεις χάσει τον κωδικό σου, βάλε το όνομα χÏήστη σου και, Ï€ÏοαιÏετικά, το email οπου θέλεις να αποσταλλεί ο κωδικός σου. Για να αποσταλλεί ο κωδικός σου σε μια διεÏθυνση email που βÏισκόταν παλιότεÏα καταχωÏημένη, η διεÏθυνση αυτή Ï€Ïέπει να είχε επιβεβαιωθεί. Αν αφήσεις το πεδίο email κενό, θα σταλεί στην Ï„Ïέχουσά σου διεÏθυνση. + +/lostinfo.bml.lostpassword.title=Ξέχασες τον κωδικό σου; + +/lostinfo.bml.lostusername.text=Αν ξέχασες το όνομα χÏήστη σου, γÏάψε τη διεÏθυνσή email σου και θα σου στείλουμε το όνομα χÏήστη σου. + +/lostinfo.bml.lostusername.title=Ξέχασες το όνομα χÏήστη σου; + +/lostinfo.bml.title=Χαμένα δεδομένα + +/lostinfo_do.bml.error.no_usernames_for_email=Κανένα όνομα χÏήστη για αυτήν τη διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου: [[address]] . + +/lostinfo_do.bml.error1.text=Δεν χÏησιμοποίησες ποτέ αυτήν τη διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου με αυτόν το λογαÏιασμό ή δεν εγκυÏώθηκε ποτέ. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Αυτό είναι ένα αυτοματοποιημένο μήνυμα. Δεν χÏειάζεται να απαντήσεις *** + +Αυτή είναι η αιτοÏμενη υπενθÏμιση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Î±Ï€' το [[sitename]]. +ΠαÏακάτω βÏίσκεται το όνομα χÏήστη σου, ο κωδικός και η διεÏθυνση email στην οποία είναι καταχωÏημένος ο λογαÏιασμός σου. + + Όνομα χÏήστη: [[username]] + Κωδικός: [[password]] + ΔιεÏθυνση email: [[emailadr]] + +. + +/lostinfo_do.bml.lostpasswordmail.part2=Για να επικυÏώσεις τη διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου, πήγαινε εδώ: + +/lostinfo_do.bml.lostpasswordmail.part5<< +ΧÏήσιμοι σÏνδεσμοι: + + Το LiveJournal σου: + [[journalurl]] + + ΕνημέÏωση του ημεÏολογίου σου: + [[updateurl]] + + +ΧαιÏετισμοÏÏ‚, +Η Oμάδα του LiveJournal + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Χαμένος Κωδικός + +/lostinfo_do.bml.password_mailed.text=Επιτυχία. Ο κωδικός σου έχει αποσταλλεί. + +/lostinfo_do.bml.password_mailed.title=Κωδικός απεστάλλη! + +/lostinfo_do.bml.title=Ξεχασμένες πληÏοφοÏίες + +/lostinfo_do.bml.username_mailed.text=Επιτυχία. Το όνομα χÏήστη σου έχει αποσταλλεί. + +/lostinfo_do.bml.username_mailed.title=Όνομα χÏήστη απεστάλλη! + +/manage/index.bml.about=Ο χειÏισμός του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… είναι εÏκολος. Απλά διάλεξε από τα παÏακάτω πεδία. + +/manage/index.bml.communities=ΔημιουÏγία και διαχείÏιση δικών σου κοινοτήτων: + +/manage/index.bml.communities.create.about=ΔημιουÏγία νέας κοινότητας + +/manage/index.bml.communities.header=Κοινότητες + +/manage/index.bml.communities.manage.about=ΔιαχείÏιση των επιλογών και μελών της κοινότητάς σου + +/manage/index.bml.customization=ΠÏοσαÏμογή της εμφάνισης των σελίδων του ημεÏολογίων σου: + +/manage/index.bml.customization.advanced=ΠÏοχωÏημένες ΠÏοσαÏμογές + +/manage/index.bml.customization.customize=ΠÏοσαÏμογή ΗμεÏολογίου + +/manage/index.bml.customization.customize.about=Άλλαγή της εμφάνισης του ημεÏολογίου σου και εναλλαγή Î¼ÎµÏ„Î±Î¾Ï Ï„Ï‰Î½ συστημάτων στυλ S1 και S2. + +/manage/index.bml.customization.header=ΠÏοσαÏμογή + +/manage/index.bml.customization.links=Λίστα Συνδέσμων + +/manage/index.bml.customization.links.about=ΔημιουÏγία λίστας συνδέσμων για να εμφανίζονται στο ημεÏολόγιό σου + +/manage/index.bml.customization.modify.about=ΤÏοποποίηση των συνισταμένων εμφάνισης του ημεÏολογίου σου + +/manage/index.bml.customization.s1.header=ΣÏστημα Στυλ S1 + +/manage/index.bml.customization.s2.header=ΣÏστημα Στυλ S2 + +/manage/index.bml.entries=ΕÏγασία με καταχωÏήσεις που έχεις κάνει στο ημεÏολόγιο του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï…: + +/manage/index.bml.entries.edit.about=ΤÏοποποίηση και διαγÏαφή καταχωÏήσεων στο ημεÏολόγιό σου + +/manage/index.bml.entries.header=ΚαταχωÏήσεις ΗμεÏολογίου + +/manage/index.bml.entries.memories.about=Εμφάνιση και εÏγασία με τις αξιομνημόνευτες καταχωÏήσεις σου + +/manage/index.bml.friends=ΔιαχείÏιση των φίλων και ομάδων φίλων σου, ή φιλτÏάÏισμα της σελίδας φίλων σÏμφωνα με τις αποθηκευμένες ομάδες φίλων σου: + +/manage/index.bml.friends.edit.about=ΠÏόσθεση ή αφαίÏεση χÏηστών από τη λίστα φίλων σου, ή αλλαγή των χÏωμάτων που τους αντιπÏοσωπεÏουν. + +/manage/index.bml.friends.filter=ΦιλτÏάÏισμα Σελίδας Φίλων + +/manage/index.bml.friends.filter.about=ΦιλτÏάÏισμα της σελίδας φίλων σου ωστε να εμφανίζει μία συγκεκÏιμένη ομάδα φίλων + +/manage/index.bml.friends.groups.about=ΔημιουÏγία, Ï„Ïοποποίηση ή διαγÏαφή υποομάδων από τη λίστα φίλων σου + +/manage/index.bml.friends.header=Φίλοι + +/manage/index.bml.information=Διάλεξε ποια δεδομένα εμφανίζονται στο λογαÏιασμό σου: + +/manage/index.bml.information.changepass=Αλλαγή ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î›Î¿Î³Î±Ïιασμόυ + +/manage/index.bml.information.changepass.about=Αλλαγή του ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï„Î¿Ï… λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… + +/manage/index.bml.information.editinfo.about=ΤÏοποποίηση των δεδομένων του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… και διαφόÏων επιλογών + +/manage/index.bml.information.emailpost=Αποστολή Ρυθμίσεων ΠÏλης με email. + +/manage/index.bml.information.emailpost.about=ΔιαχείÏιση της διεÏθυνσης email και του PIN σου για υποστήÏιξη της καταχώÏησης με email. + +/manage/index.bml.information.header=Δεδομένα ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +/manage/index.bml.information.status=Κατάσταση ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +/manage/index.bml.information.status.about=Θέσε την κατάσταση του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… (σβήσε ή επανάφεÏε τον λογαÏιασμό σου) + +/manage/index.bml.login=Οι παÏακάτω σÏνδεσμοι θα σε οδηγήσουν σε σελίδες οπου χÏειάζονται οι πληÏοφοÏίες εισόδου σου. Για να γλιτώσεις χÏόνο, μποÏείς να έχεις συνδεθεί στο site Ï€Ïοηγουμένως. + +/manage/index.bml.title=ΔιαχείÏιση ΛογαÏιασμών + +/manage/index.bml.userpictures=Υποβολή και διαχείÏιση των εικόνων χÏήστη για τον λογαÏιασμό σου: + +/manage/index.bml.userpictures.edit.about=Υποβολή και ΔιαχείÏιση των Εικόνων ΧÏήστη σου + +/manage/index.bml.userpictures.header=Εικόνες ΧÏήστη + +/manage/links.bml.about=ΧÏησιμοποίησε την παÏακάτω αίτηση για να δημιουÏγήσεις μια λίστα με συνδέσμους που να εμφανίζονται στο ημεÏολόγιό σου. Οι σÏνδεσμοι θα εμφανίζονται μόνο αν αυτή η επιλογή υποστηÏίζεται απ' το στυλ S2 σου. + +/manage/links.bml.about.blank=Για να δημιουÏγήσεις μια κενή γÏαμμή, βάλε ένα "-" για τον τίτλο. + +/manage/links.bml.about.heading=Για να δημιουÏγήσεις μια επικεφαλίδα, βάλε έναν τίτλο χωÏίς URL. + +/manage/links.bml.about.reorder=Για να αναδιατάξεις τους συνδέσμους της λίστας, Ï„Ïοποποίησε την αÏιθμητική σειÏά στα αÏιστεÏά (οι δεκαδικοί είναι δεκτοί). + +/manage/links.bml.error.s2required=Η λίστα συνδέσμων είναι διαθέσιμη μόνο σε στυλ S2 που υποστηÏίζονται. Για να αλλάξεις σε S2, βλέπε την σελίδα [[link]]. + +/manage/links.bml.error.s2required.header=ΑπαιτοÏμενο S2 + +/manage/links.bml.success=Επιτυχία! Η λίστα συνδέσμων σου έχει αποθηκευθεί. + +/manage/links.bml.title=Λίστα Συνδέσμων + +/manage/phonepost.bml.delete=ΔιαγÏαφή ΤÏοποποιήσεων + +/manage/phonepost.bml.deleted.header=ΔιεγÏάφη + +/manage/phonepost.bml.error.inuse=ΆκυÏο PIN, παÏακαλώ δοκίμασε διαφοÏετικό + +/manage/phonepost.bml.error.phone.length=Ο τηλεφωνικός σου αÏιθμός Ï€Ïέπει να είναι τουλάχιστον δέκα ψηφία. + +/manage/phonepost.bml.error.pin=Το PIN σου Ï€Ïέπει να αποτελείται από νοÏμεÏα. + +/manage/phonepost.bml.phone=Εξουσιοδοτημένος ΑÏιθμός Τηλεφώνου: + +/manage/phonepost.bml.pin=ΠÏοσωπικός ΑÏιθμός ΑναγνώÏισης: + +/manage/phonepost.bml.pin.help=Ï€Ïοτείνονται 4-6 ψηφία + +/manage/phonepost.bml.save=Αποθήκευση Ρυθμίσεων + +/modify_do.bml.colortheme.color.head1=ΧÏώμα + +/modify_do.bml.colortheme.color.head2=(#rrggbb ή όνομα) + +/modify_do.bml.success.head=Επιτυχία + +/paidaccounts/index.bml.costs.header=Πόσο κάνει; + +/paidaccounts/index.bml.costs.rates=Οι τιμές είναι ως εξής: + +/paidaccounts/index.bml.costs.rates.amount.header=ΣÏνολο + +/paidaccounts/index.bml.costs.rates.time.header=ÎÏα + +/paidaccounts/index.bml.whypay.header=ΠÏέπει να πληÏώσω για να χÏησιμοποιήσω LiveJournal; + +/paidaccounts/index.bml.your_username=όνομα_χÏήστη_σου + +/pay/index.bml.gift.anonymous=Ανώνυμο δώÏο + +/site/goat.bml.image.alt=Ο ΦÏανκ, το κατσίκι μάσκοτ του LiveJournal. + +/site/goat.bml.title=Ο ΦÏανκ, το κατσίκι + +/suggestions/index.bml.welcome.title=Καλώς ήÏθες! + +/support/see_overrides.bml.error.nos1=Αυτός ο χÏήστης δεν χÏησιμοποιεί το σÏστημα S1. + +/talkpost.bml.opt.from=Από: + +/talkpost.bml.opt.ljuser=ΧÏήστης LiveJournal: + +/talkpost.bml.opt.message=Μήνυμα: + +/talkpost.bml.opt.noimage=Καμία Εικόνα + +/talkpost_do.bml.error.banned=Δεν σου επιτÏέπεται να γÏάψεισ στο ημεÏολόγιο Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… χÏήστη + +/talkpost_do.bml.error.blankmessage=Το μήνυμά σου ήταν κενό. ΠαÏακαλώ, γÏάψε κάτι στο πεδίο μηνÏματος. + +/talkpost_do.bml.error.friendsonly=ΕπιτÏέπεται μόνο σε φίλους του/της [[user]] να γÏάφουν σ' αυτό το ημεÏολόγιο. + +/talkpost_do.bml.success.title=Επιτυχία + +/talkread.bml.anonuser=(Ανώνυμο) + +/talkread.bml.talkmulti.delete=ΔιαγÏαφή + +/talkscreen.bml.screened.title=Επιτυχία + +/talkscreen.bml.unscreened.title=Επιτυχία + +/tools/memadd.bml.body.added.header=Επιτυχία + +/tools/memadd.bml.description=ΠεÏιγÏαφή + +/tools/memadd.bml.error.nodescription.title=Καμία πεÏιγÏαφή + +/tools/memadd.bml.keywords=Λέξεις-κλειδία + +/tools/memadd.bml.keywords.select=Ή μποÏείς να διαλέξεις από λέξεις-κλειδιά που έχεις χÏησιμοποιήσει Ï€Ïοηγουμένως: + +/tools/memadd.bml.login.forgot.header=Ξέχασες κάτι; + +/tools/memadd.bml.security.friendsonly=Μόνο για Φίλους + +/tools/memadd.bml.security.private=Ιδιωτικό + +/tools/memadd.bml.security.public=Κοινό + +/tools/memadd.bml.title.added=ΠÏοστέθηκε + +/tools/memadd.bml.title.deleted=ΔιαγÏάφηκε + +/update.bml.date=ΗμεÏομηνία: + +/update.bml.security.friends=Φίλοι + +/update.bml.security.private=Ιδιωτικό + +/update.bml.security.public=Κοινό + +/userinfo.bml.comminfo.body=Το εξής είναι δεδομένα πεÏί της κοινότητας «[[commname]]» στο LiveJournal. + +/userinfo.bml.comminfo.name=Δεδομένα κοινότητας + +/userinfo.bml.date.never=Ποτέ. + +/userinfo.bml.friendof.syndreadcount=ΑÏιθμός αναγνωστών + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Φίλος των: + +/userinfo.bml.friends.comm=Μέλη + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Φίλοι + +/userinfo.bml.label.adduser=ΠÏόσθεση χÏήστη + +/userinfo.bml.label.birthdate=ΗμεÏομηνία γέννησης: + +/userinfo.bml.label.clientsused=ΧÏησιμοποιημένα Ï€ÏογÏάμματα client: + +/userinfo.bml.label.comments=Σχόλια: + +/userinfo.bml.label.composted=ΓÏαμμένα: [[num]] - + +/userinfo.bml.label.comreceived=Λημμένα: [[num]] + +/userinfo.bml.label.datecreated=ΗμεÏομηνία δημιουÏγίας: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=ΔιεÏθυνση e-mail: + +/userinfo.bml.label.icquin=UIN στο ICQ: + +/userinfo.bml.label.interests=ΕνδιαφέÏοντα + +/userinfo.bml.label.journalentrs=ΕγγÏαφές: + +/userinfo.bml.label.memberof=Μέλος των + +/userinfo.bml.label.moredetails=(πεÏισσότεÏες πληÏοφοÏίες...) + +/userinfo.bml.label.msnusername=Όνομα χÏήστη στο MSN: + +/userinfo.bml.label.name=Όνομα: + +/userinfo.bml.label.shared=ΠÏόσβαση: + +/userinfo.bml.label.supportpoints=Πόντοι υποστήÏιξης + +/userinfo.bml.label.syndicatedstatus=Κατάσταση ΚοινοπÏαξίας + +/userinfo.bml.label.textmessage=ΓÏαπτό
        Μήνυμα
        : + +/userinfo.bml.label.user=ΧÏήστης: + +/userinfo.bml.label.viewfriends=Επισκόπηση Φίλων + +/userinfo.bml.label.viewmembers=Επισκόπηση Μελών + +/userinfo.bml.label.website=Ιστοσελίδα: + +/userinfo.bml.label.yahooid=Ταυτότητα Yahoo!: + +/userinfo.bml.membership.body=Για να Ï€ÏοσχωÏήσεις σε αυτήν την κοινότητα, a href="/community/join.bml?comm=[[commname]]">πάτησε εδώ. + +/userinfo.bml.membership.paidmembers=Î‘Ï†Î¿Ï Î­Ï‡ÎµÎ¹ εγκατασταθεί ο πληÏωμένος λογαÏιασμός σου, μποÏείς να a href="/paidaccounts/joincommunity.bml">να Ï€ÏοσχωÏήσεις στην κοινότητα μελών επί πληÏωμή. + +/userinfo.bml.memories.entries=[[count]] καταχωÏήσεις + +/userinfo.bml.memories.entry=[[count]] καταχώÏηση + +/userinfo.bml.monitor.comm=ΠαÏακόλοÏθηση Κοινότητας + +/userinfo.bml.monitor.user=ΠÏόσθεσε αυτόν το χÏήστη στον κατάλογο των φίλων σου + +/userinfo.bml.nonexist.body=Το όνομα χÏήστη [[user]] δεν είναι εγγεγÏαμμένο αυτή τη στιγμή. + +/userinfo.bml.nonexist.name=Άγνωστος χÏήστης + +/userinfo.bml.sendmessage.body=Στείλε στον [[user]] ένα γÏαπτό μήνυμα
        στο κινητό του τηλέφωνο/βομβητή. + +/userinfo.bml.syn.last.never=Ποτέ + +/userinfo.bml.syn.lastcheck=Τελευταίος έλεγχος: + +/userinfo.bml.syn.nextcheck=Επόμενος έλεγχος: + +/userinfo.bml.syn.parseerror=Μήνυμα σφάλματος: + +/userinfo.bml.syndinfo.body=Αν θέλεις να εμφανίζονται άÏθÏα από τη σελίδα της κοινοπÏαξίας στις σελίδες των φίλων σου, μποÏείς να Ï€Ïοσθέσεις αυτό το ημεÏόλογιο στον κατάλογο των φίλων σου. + +/userinfo.bml.syndinfo.name=ΗμεÏόλογιο ΚοινοπÏαξίας + +/userinfo.bml.tellafriend=Πες το σε ένα φίλο! + +/userinfo.bml.timeupdate.dayago=ΠÏιν από μία ημέÏα + +/userinfo.bml.timeupdate.daysago=ΠÏιν από [[num]] ημέÏες + +/userinfo.bml.timeupdate.hourago=ΠÏιν από μία ÏŽÏα + +/userinfo.bml.timeupdate.hoursago=ΠÏιν από [[num]] ÏŽÏες + +/userinfo.bml.timeupdate.minuteago=ΠÏιν από ένα λεπτό + +/userinfo.bml.timeupdate.minutesago=ΠÏιν από [[num]] λεπτά + +/userinfo.bml.timeupdate.secondago=ΠÏιν από ένα δευτεÏόλεπτο + +/userinfo.bml.timeupdate.secondsago=ΠÏιν από [[num]] δευτεÏόλεπτα + +/userinfo.bml.timeupdate.weekago=ΠÏιν από μία εβδομάδα + +/userinfo.bml.timeupdate.weeksago=ΠÏιν από [[num]] εβδομάδες + +/userinfo.bml.title=Στοιχεία ΧÏήστη + +/userinfo.bml.title.communityinfo=Στοιχεία Κοινότητας + +/userinfo.bml.title.syndicated=ΛογαÏιασμός ΚοινοπÏαξίας + +/userinfo.bml.userinfo.body=ΠαÏακάτω βÏίσκονται τα στοιχεία χÏήστη για τον [[username]]. Αν είσαι αυτός ο χÏήστης, μποÏείς να Ï„Ïοποποιήσεις τα στοιχεία σου (ή να επιλέξεις τις πληÏοφοÏίες που θα θεωÏοÏνται δημόσιες) στη σελίδα ΤÏοποποίησης Στοιχείων. + +/userinfo.bml.userinfo.name=Στοιχεία ΧÏήστη + +BML.parse_multipart.parse=Σφάλμα ανάγνωσης κατά την Ï€ÏοσφόÏτωση + +BML.parse_multipart.toolarge=Πολλή μεγάλη Ï€ÏοσφόÏτωση + +BML.parse_multipart.unknowntype=Άγνωστος Ï„Ïπος πεÏιεχομένου + +btn.search=Αναζήτηση + +date.day.friday.long=ΠαÏασκευή + +date.day.friday.short=Î Î±Ï + +date.day.monday.long=ΔευτέÏα + +date.day.monday.short=Δευ + +date.day.saturday.long=Σάββατο + +date.day.saturday.short=Σαβ + +date.day.sunday.long=ΚυÏιακή + +date.day.sunday.short=ÎšÏ…Ï + +date.day.thursday.long=Πέμπτη + +date.day.thursday.short=Πεμ + +date.day.tuesday.long=ΤÏίτη + +date.day.tuesday.short=ΤÏι + +date.day.wednesday.long=ΤετάÏτη + +date.day.wednesday.short=Τετ + +date.month.april.long=ΑπÏίλιος + +date.month.april.short=Î‘Ï€Ï + +date.month.august.long=ΑÏγουστος + +date.month.august.short=Αυγ + +date.month.december.long=ΔεκέμβÏιος + +date.month.december.short=Δεκ + +date.month.february.long=ΦεβÏουάÏιος + +date.month.february.short=Φεβ + +date.month.january.long=ΙανουάÏιος + +date.month.january.short=Ιαν + +date.month.july.long=ΙοÏλιος + +date.month.july.short=Ιουλ + +date.month.june.long=ΙοÏνιος + +date.month.june.short=Ιουν + +date.month.march.long=ΜάÏτιος + +date.month.march.short=ÎœÎ±Ï + +date.month.may.long=Μάιος + +date.month.may.short=Μαϊ + +date.month.november.long=ÎοέμβÏιος + +date.month.november.short=Îοε + +date.month.october.long=ΟκτώβÏιος + +date.month.october.short=Οκτ + +date.month.september.long=ΣεπτέμβÏιος + +date.month.september.short=Σεπ + +dystopia.btn.login=ΣΥÎΔΕΣΗ + +dystopia.hello_anonymous=Καλώς ήÏθες στο LiveJournal! + +dystopia.hello_loggedin=Γεια σου, [[username]]! + +dystopia.nav.createjournal=ΔημιουÏγία ΗμεÏολογίου + +dystopia.nav.developer=ΠεÏιοχή ΠÏογÏαμματιστή + +dystopia.nav.download=ΚαταφόÏτωση + +dystopia.nav.editentries=Αλλαγή ΚαταχωÏήσεων + +dystopia.nav.editfriends=Οι Φίλοι σου + +dystopia.nav.editpassword=Ο Κωδικός σου + +dystopia.nav.editpics=Οι Εικόνες σου + +dystopia.nav.editstyle=ΜετατÏοπή Στυλ + +dystopia.nav.findcomm=Κατα Κοινότητα + +dystopia.nav.finddir=Αναζήτηση σε ΕυÏετήÏιο + +dystopia.nav.findint=Κατα ΕνδιαφέÏον + +dystopia.nav.findrandom=Τυχαίος + +dystopia.nav.findregion=Κατά πεÏιοχή + +dystopia.nav.home=ΑÏχική Σελίδα + +dystopia.nav.journalcalendar=ΗμεÏόλογιο + +dystopia.nav.journalfriends=Φίλοι + +dystopia.nav.journalinfo=Στοιχεία ΧÏήστη + +dystopia.nav.journalrecent=ΠÏόσφατα + +dystopia.nav.legalprivacy=Μυστικότητα + +dystopia.nav.legaltos=ÎŒÏοι ΥπηÏεσιών + +dystopia.nav.login=ΣÏνδεση + +dystopia.nav.logout=ΑποσÏνδεση + +dystopia.nav.lostinfo=Απώλεια ÎšÏ‰Î´Î¹ÎºÎ¿Ï Î Ïόσβασης + +dystopia.nav.memories=Αναμνήσεις + +dystopia.nav.modifyjournal=ΤÏοποποίηση ΗμεÏολογίου + +dystopia.nav.news=Îέα + +dystopia.nav.paidaccts=ΠληÏωμένοι ΛογαÏιασμοί + +dystopia.nav.paymentarea=ΠεÏιοχής ΠληÏωμής + +dystopia.nav.personalinfo=ΠÏοσωπικά Στοιχεία + +dystopia.nav.sitemap=ΧάÏτης Σελίδας + +dystopia.nav.siteopts=Επιλογές Ξενάγησης + +dystopia.nav.support=Έχεις εÏώτηση; + +dystopia.nav.updatejournal=ΕνημέÏωση ΗμεÏολογίου + +dystopia.navhead.findusers=Î’Ïες ΧÏήστες + +dystopia.navhead.help=Βοήθεια & ΥποστήÏιξη + +dystopia.navhead.journal=Το ΗμεÏολόγιό σου + +dystopia.navhead.legal=Îομικά + +dystopia.navhead.settings=Οι Ρυθμίσεις σου + +dystopia.navhead.welcome=Καλώς ÏŒÏισες! + +dystopia.search.icq=ΑÏιθμός ICQ + +dystopia.search.int=ΕνδιαφέÏον + +dystopia.search.msn=Όνομα χÏήστη στο MSN + +dystopia.search.region=ΠεÏιοχή + +dystopia.search.yahoo=Ταυτότητα Yahoo! + +dystopia.searchlj=ΈÏευνα στο LiveJournal: + +Email=ΔιεÏθυνση e-mail + +email.newacct.body<< +ΣυγχαÏητήÏια, έχεις ένα νέο λογαÏιασμό Livejournal! + +Για να ολοκληÏώσεις τη δημιουÏγία του ημεÏολογίου σου και να επιβεβαιώσεις τη διεÏθυνση email σου, πήγαινε εδώ: + + [[regurl]] + +Η διεÏθυνση στην οποία βÏίσκεται το ημεÏολόγιό σου είναι + + [[siteroot]]/users/[[username]]/ + +και επίσης: + + [[siteroot]]/~[[username]]/ + +ΠαÏακάτω είναι το όνομα χÏήστη και ο κωδικός Ï€Ïόσβασης LiveJournal: + + Όνομα χÏήστη: [[username]] + Κωδικός Ï€Ïόσβασης: [[password]] + +ΜποÏείς να πας στο [[siteroot]]/ για να αποκτήσεις Ï€Ïόσβαση στο ημεÏολόγιο, να δημιουÏγήσεις νέες καταχωÏήσεις και να Ï„Ïοποποιήσεις τις Ïυθμίσεις σου, αλλά συνιστοÏμε να καταφοÏτώσεις ένα Ï€ÏόγÏαμμα LiveJournal. Είναι ο πιο εÏκολος Ï„Ïόπος να ενημεÏώνεις το ημεÏολόγιό σου και υπάÏχουν διαθέσιμα Ï€ÏογÏάμματα για πολλά λειτουÏγικά συστήματα! Απόκτησε ένα εδώ: + + [[siteroot]]/download/ + +Ξεκινώντας στο LiveJournal μποÏεί να είναι δÏσκολο όταν δεν ξέÏεις κανένα. Επισκέψου το http://newbies.livejournal.com για έξυπνες και βοηθητικές συμβουλές... Με λίγη Ï„Ïχη, θα γίνεις ειδικός του LiveJournal σε μηδέν χÏόνο! + +Ελπίζουμε να σου αÏέσει το LiveJournal όσο μας αÏέσει να το παÏέχουμε σε σένα. Αν έχεις εÏωτήσεις για το πώς να χÏησιμοποιείς το LiveJournal, παÏακαλοÏμε επισκέψου την πεÏιοχή υποστήÏιξης: + + [[siteroot]]/support/ + +Εκεί θα βÏεις απαντήσεις για σχεδόν όλες τις εÏωτήσεις που μποÏείς να Ïωτήσεις σχετικά με το LiveJournal. + +Ο στόχος μας είναι να κάνουμε το LiveJournal να πετάει... Αν μποÏοÏμε να κάνουμε ο,τιδήποτε για να το ευκολÏνουμε, να το κάνουμε πιο ισχυÏÏŒ, πιο Ïυθμίσιμο... ενημέÏωσέ μας. +Δε λειτουÏγοÏμε τη σελίδα για να βγάλουμε λεφτά. Δεν είμαστε μια εταιÏεία dot-com, η οποία χÏηματοδοτείται από εξωτεÏικοÏÏ‚ χοÏηγοÏÏ‚, ελπίζοντας να μποÏμε στο χÏηματιστήÏιο... αυτή η σελίδα διατηÏείται από όλους τους ανθÏώπους που την χÏησιμοποιοÏν. Πες μας τι θέλεις από αυτή. + +Αν έχεις εÏωτήσεις, η ομάδα υποστήÏιξης θα σου βÏει μια απάντηση, συνήθως σε λιγότεÏο από 24 ÏŽÏες. + +Καλώς ήλθες! + +Ομάδα [[sitename]] +[[siteroot]]/ + +. + +email.newacct.subject=Καλώς ήÏθες στο LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Σφάλμα + +error.badpassword=Λανθασμένος Κωδικός ΠÏόσβασης + +error.dberror=Συνέβη ένα σφάλμα με τη βάση δεδομένων + +error.deleted.name=Σβήστηκε + +error.deleted.text=Το ημεÏολόγιο έχει σβηστεί. Αν είσαι [[user]], έχεις μμία πεÏίδοο 30 ημεÏών από το χÏόνο διαγÏαφής για να ανακαλέσεις τη διαγÏαφή του ημεÏολογίου. Μετά από 30 ημέÏες θα σβήσουμε όλα τα πεÏιεχόμενα από τους διακομιστές μας μόνιμα. + +error.deleted.title=Σβησμένος ΛογαÏιασμός + +error.invalidauth=Δεν μποÏείς να εξουσιοδοτηθείς ως ο συγκεκÏιμένος χÏήστης + +error.ipbanned=Η διεÏθυνση IP σου έχει Ï€ÏοσωÏινά απαγοÏευτεί επειδή έχει ξεπεÏαστεί ο Ïυθμός αποτυχίας σÏνδεσης. + +error.malformeduser=ΠαÏαποιημένο όνομα χÏήστη. + +error.nobutton=Δεν πάτησες κανένα κουμπί; + +error.nodb=Η βάση δεδωμένων δεν είναι διαθέσιμη Ï€ÏοσωÏινά. + +error.nodbmaintenance=Αυτό το μέÏος της βάσης δεδομένων είναι Ï€ÏοσωÏινά κλειστό για επισκευή. ΞαναπÏοσπάθησε σε μεÏικά λεπτά. + +error.noentry=Δεν υπάÏχει τέτοια καταχώÏηση + +error.nojournal=Άγνωστο ημεÏολόγιο + +error.noremote=ΠÏέπει να συνδεθείς για να μποÏέσεις να χÏησιμοποιήσεις αυτλη τη σελίδα + +error.procrequest=ΥπήÏξε σφάλμα κατά την επεξεÏγασία της + +error.purged.name=Σβήστηκε + +error.purged.text=Το ημεÏολόγιο αυτό έχει σβηστεί και διαγÏαφεί + +error.purged.title=ΔιεγÏαμμένος ΛογαÏιασμός + +error.suspended.name=Αναστάλθηκε + +Help=Βοήθεια + +label.security.friends=Φίλοι + +label.security.head=Επίπεδο ΠÏοστασίας + +label.security.private=Ιδιωτικό + +label.security.public=Δημόσιο + +label.switch.button=Αλλαγή + +label.switch.header=Αλλαγή ΗμεÏολογίου + +label.switch.workwith=ΕÏγασία με το ημεÏολόγιο: + +langname.be=ΛευκοÏώσικα + +langname.da=Δανέζικα + +langname.de=ΓεÏμανικά + +langname.en=Αγγλικά + +langname.en_GB=Αγγλικά (ΗΒ) + +langname.en_LJ=Αγγλικά + +langname.eo=ΕσπεÏάντο + +langname.es=Ισπανικά + +langname.et=Εσθονιακά + +langname.fi=Φινλανδέζικα + +langname.fr=Γαλλικά + +langname.ga=ΙÏλανδικά + +langname.gd=Κέλτικα + +langname.he=ΕβÏαϊκά + +langname.hi=Ινδικά + +langname.hu=ΟυγγÏικά + +langname.is=Ισλανδικά + +langname.it=Ιταλικά + +langname.ja=Γιαπωνέζικα + +langname.la=Λατινικά + +langname.lv=Λεττονικά + +langname.ms=Μαλαισικά + +langname.nb=ÎοÏβηγικά (BokmÃ¥l) + +langname.nl=Ολλανδέζικα + +langname.nn=ÎοÏβηγικά (Nynorsk) + +langname.pl=Πολωνικά + +langname.pt=ΠοÏτογαλικά + +langname.ru=Ρωσικά + +langname.sv=Σουηδικά + +langname.tr=ΤοÏÏκικα + +langname.uk=ΟυκÏανικά + +langname.zh=Κινέζικα (Απλοποιημένα) + +ljcom.account.feature=ΧαÏακτηÏιστικό + +ljcom.account.feature.email=ΔιεÏθυνση email του ΗμεÏολογίου + +ljcom.account.paid6=ΠληÏωμένος για 6 μήνες ($15 USD) + +ljcom.accounttype=ΤÏπος ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +ljcom.badpass.email=Ο κωδικός σου Ï€Ïόσβασης δεν μποÏεί να βασίζεται στη διεÏθυνση email σου + +ljcom.badpass.realname=Ο κωδικός σου Ï€Ïόσβασης δεν μποÏεί να βασίζεται στο Ï€Ïαγματικό σου όνομα + +ljcom.badpass.username=Ο κωδικός σου Ï€Ïόσβασης δεν μποÏεί να βασίζεται στον κωδικό σου χÏήστη + +ljcom.meetup.head=Συνάντηση! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Διεθνής [[name]] ΜέÏα Συνάντησης + +ljcom.meetup.moreinfo=(πεÏισσότεÏες πληÏοφοÏίες) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Θέλεις να συναντήσεις άτομα από κοντά που να βÏίσκονται γÏÏω από την πεÏιοχή σου; Ρίξε μια ματιά στο [[link]]! + +ljcom.menu.upgrade=Αναβάθμισε το λογαÏιασμό σου + +ljcom.userinfo.accounttype=ΤÏπος λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +ljcom.userinfo.paiduser=ΧÏήστης επί πληÏωμή + +ljcom.userinfo.types.early=Παλαιός ΧÏήστης + +ljcom.userinfo.types.free=ΔωÏεάν λογαÏιασμός + +ljcom.userinfo.types.paid=ΠληÏωμένος λογαÏιασμός + +ljcom.userinfo.types.paid_early=ΠληÏωμένος λογαÏιασμός, Παλαιός ΧÏήστης Ï€ÏωτÏτεÏα + +ljcom.userinfo.types.paid_early_expiring=ΠληÏωμένος ΛογαÏιασμός, ο οποίος λήγει [[paiduntil]], Παλαιός ΧÏήστης Ï€ÏωτÏτεÏα + +ljcom.userinfo.types.paid_expiring=ΠληÏωμένος ΛογαÏιασμός, ο οποίος λήγει [[paiduntil]], + +ljcom.userinfo.types.permanent=Μόνιμος ΛογαÏιασμός + +ljcom.userinfo.types.permanent_early=Μόνιμος ΛογαÏιασμός, Παλαιός ΧÏήστης Ï€ÏωτÏτεÏα + +ljlib.pageofpages=Σελίδα [[page]] από [[total]] + +lostinfo.head=Ξέχασες κάτι; + +lostinfo.text=Αν ξέχασες τον κωδικό ή τον κωδικό Ï€Ïόσβασης, βÏες τα εδώ. + +Password=Κωδικός Ï€Ïόσβασης + +password.max30=ΟΙ κωδιοί Ï€Ïόσβασης δεν μποÏοÏν να είναι άνω των 30 χαÏακτήÏων. + +portal.bdays.count.des=Λόγω Ï€Ïοεπιλογής, Ï€Ïαουσιάζονται οι 5 φίλοι με τα πιο κοντινά γενέθλια. + +portal.bdays.count.name=Γενέθλια Ï€Ïος απεικόνιση + +portal.bdays.portalname=Γενέθλια + +portal.bdays.portaltitle=Γενέθλια + +portal.goat.name=Μασκότ της σελίδας + +portal.goattext.des=Τι ακÏιβώς θέλεις να λέει η κατσίκα σου; Το μόνο που λένε οι κατσίκες είναι "Μπεεεεε", αλλά μποÏείς να κάνεις οτι η δική σου κατσίκα λέει κάτι άλλο αν το θέλεις Ï€Ïαγματικά. + +portal.goattext.name=Κέιμενο Κατσίκας + +portal.login.portalname=Κουτί Εισόδου + +portal.memories.entriesnoun=καταχωÏήσεις + +portal.memories.entrynoun=καταχώÏηση + +portal.memories.portalname=Αξιομνημόνευτες καταχωÏήσεις + +portal.memories.portaltitle=Αξιομνημόνευτες καταχωÏήσεις + +portal.ministats.active=ΕνεÏγός: + +portal.ministats.title=Στατιστικά ΧÏηστών + +portal.ministats.total=ΣÏνολο: + +portal.misbehaved.des=Βασικά ήθελες να μην το επιλέξεις. Οι μη εκπαιδευμένες κατσίκες είναι τζαναμπέτικες. + +portal.misbehaved.name=Κακοποιημένη Κατσίκα + +portal.newtolj.name=ΣÏνδεσμοι Ιστοσελίδας + +portal.popfaq.portalname=Τα 10 πιο δημοφιλή FAQ + +portal.popfaq.portaltitle=Τα 10 πιο δημοφιλή FAQ + +portal.randuser.count.des=όγω Ï€Ïοεπιλογής, εμφανίζεται 1 τυχαίος χÏήστης, αλλά μποÏείς να έχεις ως 10 κάθετα στις στενές στήλες, ή 5 οÏιζόντια σε μία πλατιά στήλη + +portal.randuser.count.name=ΑÏιθμός τυχαίων χÏηστών που θα εμφανιστοÏν + +portal.randuser.error.tableempty=Δεν υπάÏχουν τυχαίοι χÏήστες. Έλα σε επαφή με τον διαχειÏιστή. + +portal.randuser.hidename.des=όγω Ï€Ïοεπιλογής, εμφανίζεται η εικόνα τυχαίου χÏήστη εμφανίζεται. Διάλεξε αυτό για να την αφαιÏέσεις + +portal.randuser.hidename.name=ΑπόκÏυψη Ονίοματος + +portal.randuser.hidepic.des=Λόγω Ï€Ïοεπιλογής, εμφανίζεται η εικόνα τυχαίου χÏήστη εμφανίζεται, αν είναι διαθέσιμη. Διάλεξε αυτό για να την αφαιÏέσεις. + +portal.randuser.hidepic.name=ΑπόκÏυψη Εικόνας ΧÏήστη + +portal.randuser.portalname=Τυχαίος ΧÏήστης + +portal.randuser.portaltitle=Τυχαίος ΧÏήστης + +portal.randuser.portaltitleplural=Τυχαίοι ΧÏήστες + +portal.recent.error.noentries=Λυπάμαι, καμία καταχώÏηση. + +portal.recent.error.notsetup=ΠÏέπει να διαμοÏφώσες αυτό το κιβώτιο. Κάνε κλικ στο σÏμβολο "συν" για να εγκαταστήσεις εδώ το ημεÏολόγιο που θέλεις να παÏακολουθείς. + +portal.recent.error.userstatus=Ο χÏήστης έχει σβήσει ή αναστείλει το λογαÏιασμό τους + +portal.recent.items.description=όγω Ï€Ïοεπιλογής, εμφανίζεται μόνο η πιο Ï€Ïόσφατη καταχώÏηση. + +portal.recent.items.name=Αντικείμενα Ï€Ïος εμφάνιση + +portal.recent.journal.description=Από ποιο ημεÏολόγιο θέλεις να δεις τα Ï€Ïόσφατά του αντικείμενα + +portal.recent.journal.name=ΗμεÏολόγιο + +portal.recent.nosubject=(ΧωÏίς Θέμα) + +portal.recent.permlink=ΣÏνδεσμος + +portal.recent.portalname=Άποψη ΠÏόσφατης ΚαταχώÏησης + +portal.recent.portaltitle=Κιβώτιο ΠÏόσφατης ΚαταχώÏησης + +portal.recent.showtext.description=Θα εμφανίζονται μόνο θέματα λόγω Ï€Ïοεπιλογής + +portal.recent.showtext.name=ΣυμπεÏίλαβε το κείμενο + +portal.stats.journalentyest=Οι χθεσινές καταχωÏήσεις του ΗμεÏολογίου + +portal.stats.portalname=Στατιστικά σελίδας + +protocol.hello_test=Γεια σου, λογαÏισμέ δοκιμής! + +protocol.mail_bouncing=Αυτή τη στιγμή χÏησιμοποιείς μία εσφαλμένη διεÏθυνση email. Όλα τα μηνλυματα που Ï€ÏοσπαθοÏμε να σου στείλουμε επιστÏέφουν. Η ιστοσελίδα [[sitename]] απαιτεί μία ισχÏουσα διεÏθυνση email για συνεχή χÏήση. Πήγαινε στο [[siteroot]]/support/faqbrowse.bml?faqid=19 για να δεις πώς μποÏείς να αλλάξεις το email σου. + +protocol.modpost=Η καταχώÏησή σου έχει τοποθετηθεί στη λίστα αναμονής του διαχειÏιστή. Θα εγκÏιθεί ή θα αποÏÏιφθεί από έναν από τους διαχειÏιστές της κοινότητας + +protocol.must_revalidate=ΠÏέπει να επιβεβαιώσεις το νέο σου email. Το παλιό σου ήταν εντάξει, αλλά από τη στιγμή που το έχεις αλλάξει, χÏειάζεται να επιβεβαιώσεις το νέο. Αν δεν επιβεβαιώσεις το νέο email, δε θα έχεις Ï€Ïόσβαση σε όλες τις λειτουÏγίες της ιστοσελίδας [[sitename]]. Πήγαινε στη σελίδα [[siteroot]]/support/faqbrowse.bml?faqid=11 για πεÏισσότεÏες πληÏοφοÏίες. + +protocol.not_validated=Το email σου δεν έχει επιβεβαιωθεί. ΜποÏείς να εξακολουθήσεις να χÏησιμοποιείς τη σελίδα [[sitename]], αλλά αν δεν επιβεβαιώσεις το email σου, δε θα έχεις Ï€Ïόσβαση σε όλες τις λειτουÏγίες της ιστοσελίδας. Δες τις οδηγίες οι οποίες σου έχουν σταλεί όταν δημιοÏÏγησες το ημεÏολόγιό σου, η πήγαινε στη σελίδα [[siteroot]]/support/faqbrowse.bml?faqid=11 για πεÏισσότεÏες πληÏοφοÏίες. + +protocol.old_win32_client=ΥπάÏχουν σημαντικά νεώτεÏα Ï€ÏογÏάμματα LiveJournal για Windows διαθέσιμα και συστήνουμε να τα αναβαθμίσεις. Πήγαινε στο [[siteroot]]/download/ για να καταφοÏτώσεις ένα καινοÏÏιο Ï€ÏόγÏαμμα. + +protocol.readonly=Ο λογαÏιασμός σου είναι Ï€ÏοσωÏινά σε κατάστασης ανάγνωσης μόνο. ΜεÏικές λειτουÏγίες θα απότÏχουν για μεÏικά λεπτά. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Λυπόμαστε + +talk.anonwrote=Κάποιος έγÏαψε, + +talk.anonwrote_comm=Κάποιος έγÏαψε στη [[commlink]], + +talk.btn.preview=ΠÏοεπισκόπηση + +talk.commentpermlink=σÏνδεσμος + +talk.commentpost=ΓÏάψε νέο σχόλιο + +talk.commentsread=Διάβασε τα σχόλια + +talk.curname_Mood=ΤÏέχουσα διάθεση: + +talk.curname_Music=ΤÏέχουσα μουσική: + +talk.error.bogusargs=Ψευδά επιχειÏήματα + +talk.error.comm_deleted=Αυτό το σχόλιο έχει σβηστεί + +talk.error.deleted=Αυτό το ημεÏολόγιο έχει σβηστεί + +talk.error.deleted.title=Σβησμένο + +talk.error.mustlogin=ΠÏέπει να έχετε συνδεθεί για να δείτε αυτή την Ï€Ïοστατευμένη καταχώÏηση + +talk.error.nocomment=Το σχόλιο δεν υπάÏχει + +talk.error.noentry=Δεν υπάÏχει τέτοια καταχώÏηση + +talk.error.nojournal=Σφάλμα: το ημεÏολόγιο δεν μπόÏεσε να διευκÏινστεί από τα στοιχεία + +talk.error.nosuchjournal=Δεν υπάÏχει τέτοιο ημεÏολόγιο + +talk.error.notauthorised=Δεν είσαι εξουσιοδοτημένος να διάβάσεις την Ï€Ïοστατευμένη καταχώÏηση + +talk.error.suspended=Αυτό το ημεÏολόγιο/συγγÏαφέας έχει ανασταλεί + +talk.error.suspended.title=Σε αναστολή + +talk.parentlink=ΠÏογονικό + +talk.readsimilar=Ανάγνωση παÏόμοιων καταχωÏήσεων: + +talk.replytothis=Απάντησε σε αυτό + +talk.somebodywrote=[[realname]] ([[userlink]]) έγÏαψε, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) έγÏαψε στη [[commlink]], + +talk.spellcheck=Έλεγχος οÏθογÏαφίας Ï€Ïιν την Ï€Ïοεπισκόπηση + +talk.threadlink=Îήμα + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_ellinika + +Username=Όνομα χÏήστη + +userpic.inactive=ΑνενεÏγός + +xcolibur.greeting.anon=Καλώς ήÏθες στο LiveJournal! + +xcolibur.greeting.logged_in=Καλώς ήÏθες, [[name]]! [[logout]] + +xcolibur.login=ΣÏνδεση; + +xcolibur.logout=ΑποσÏνδεση; + +xcolibur.nav.about=Σχετικά + +xcolibur.nav.about.download=ΚαταφόÏτωση + +xcolibur.nav.about.general=Γενικές πληÏοφοÏίες + +xcolibur.nav.about.paidaccounts=ΠληÏωμένοι λογαÏιασμοί + +xcolibur.nav.about.press=ΤÏπος + +xcolibur.nav.about.sitenews=Îέα ιστοσελίδας + +xcolibur.nav.about.stats=Στατιστικά + +xcolibur.nav.footer.sitemap=ΧάÏτης ιστοσελίδας + +xcolibur.nav.help=Βοήθεια + +xcolibur.nav.help.ask=Θέσε εÏώτηση + +xcolibur.nav.help.contact=ΠληÏοφοÏίες ÎµÏ€Î¹ÎºÎ¿Î¹Î½Ï‰Î½Î¯Î±Ï‚ + +xcolibur.nav.help.faq=abbr title="Frequently Asked Questions">FAQ + +xcolibur.nav.help.lostpassword=Απώλεια ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης + +xcolibur.nav.home=ΑÏχική σελίδα + +xcolibur.nav.journal=ΗμεÏολόγιο + +xcolibur.nav.journal.archive=ΑÏχείο + +xcolibur.nav.journal.edit.entries=ΔιόÏθωση καταχωÏήσεων + +xcolibur.nav.journal.friends=Φίλοι + +xcolibur.nav.journal.info=ΠληÏοφοÏίες + +xcolibur.nav.journal.memories=Αναμνήσεις + +xcolibur.nav.journal.recent=ΠÏόσφατο + +xcolibur.nav.journal.update=ΕνημέÏωση + +xcolibur.nav.manage=ΔιαχείÏιση + +xcolibur.nav.manage.community=Κοινότητες + +xcolibur.nav.manage.customize=ΠÏοσωπικές Ρυθμίσεις + +xcolibur.nav.manage.entries=ΚαταχωÏήσεις + +xcolibur.nav.manage.friends=Φίλοι + +xcolibur.nav.manage.info=ΠληÏοφοÏίες + +xcolibur.nav.manage.password=Κωδικός Ï€Ïόσβασης + +xcolibur.nav.manage.pics=Εικόνες ΧÏήστη + +xcolibur.nav.manage.styles=ΠÏότυπα + +xcolibur.nav.search=ΈÏευνα + +xcolibur.nav.search.directory=ΠεÏιοχή + +xcolibur.nav.search.directory.search=ΠÏοχωÏημένοι + +xcolibur.nav.search.interests=ΕνδιαφέÏοντα + +xcolibur.nav.search.random=Τυχαίοι + +xcolibur.nav.siteopts=Δες τις επιλογές + +xcolibur.nav.title=Πλοήγηση: + +xcolibur.nav.welcome=Καλώς ήÏθες + +xcolibur.nav.welcome.create=ΔημιουÏγία λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï + +xcolibur.nav.welcome.login=ΣÏνδεση + +xcolibur.nav.welcome.update=ΕνημέÏωση του ΗμεÏολογίου σου. + +xcolibur.search=ΈÏευνα: + +xcolibur.search.category=ΚατηγοÏία: + +xcolibur.search.icq=ΑÏιθμός ICQ + +xcolibur.search.int=ΕνδιαφέÏον + +xcolibur.search.msn=Όνομα χÏήστη στο MSN + +xcolibur.search.region=ΠεÏιοχή + +xcolibur.search.yahoo=Ταυτότητα Yahoo! + +xcolibur.upgrade=Αναβάθμιση του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ¿Ï… + diff --git a/ljcom/bin/upgrading/he.dat b/ljcom/bin/upgrading/he.dat new file mode 100644 index 0000000..47c9b84 --- /dev/null +++ b/ljcom/bin/upgrading/he.dat @@ -0,0 +1,1853 @@ +;; -*- coding: utf-8 -*- +/allpics.bml.current=תמונות נוכחות + +/allpics.bml.default=ברירת מחדל + +/allpics.bml.error.noparam=עליך לציין ×©× ×ž×©×ª×ž×© + +/allpics.bml.keywords=מילות מפתח: + +/allpics.bml.nopics.text.other=משתמש ×–×” ×œ× ×”×¢×œ×” ××£ תמונת משתמש. + +/allpics.bml.nopics.title=×ין תמונות + +/allpics.bml.pics=להלן התמונות עבור המשתמש [[user]]. + +/allpics.bml.title=תמונות משתמש + +/community/index.bml.title=מרכז קהילה + +/community/join.bml.button.join=הצטרפות לקהילה + +/community/join.bml.label.addtofriends=הוסף\×™ "[[maintainer]]" לרשימת חברי×.
        + +/community/join.bml.label.allowposting=קהילה זו מ×פשרת לכל משתמשיה ×œ×¤×¨×¡× ×‘×”, על כן, כעת יש לך הרש××” ×œ×¤×¨×¡× ×‘×”. ×× ×ª×•×›× ×ª העדכון של LiveJournal פתוחה כעת במחשב שלך, ×™×”×™×” עליך לצ×ת מהתוכנה ולהתחבר מחדש לחשבון ×–×” כדי שיומן ×–×” יופיע ברשימת ×”×™×•×ž× ×™× ×‘×”× ×‘×פשרותך ×œ×¤×¨×¡× ×¨×™×©×•×ž×™×. + +/community/join.bml.label.auth=על ××£ שהצטרפת עתה לקהילה, הקהילה מ×פשרת הוספת ×¨×™×©×•×ž×™× ×¨×§ ×œ×ž×©×ª×ž×©×™× ×ž×¡×•×™×ž×™×. יש ליצור קשר ×¢× ×חד ממתחזקי הקהילה ×× ×‘×¨×¦×•× ×š לקבל הרש×ת הוספת רישומי×. להלן רשימת מתחזקי הקהילה: [[admins]] + +/community/join.bml.label.banned=מנהל(×™) קהילה זו חסמו ×ותך מלהצטרף לקהילה. + +/community/join.bml.label.closed=זו קהילה סגורה. ×× ×‘×¨×¦×•× ×š להצטרף ×ליה, עליך ליצור קשר ×¢× ×חד ממתחזקיה. להלן רשימת ×”×ž×ª×—×–×§×™× ×©×œ קהילה זו: [[admins]] + +/community/join.bml.label.commlogged=הנך מחובר כעת למערכת בחשבון משותף/קהילתי, ×•×œ× ×‘×מצעות החשבון ×”×ישי שלך. + +/community/join.bml.label.errorcomminfo=פרטי הקהילה שצוינו ××™× × ×—×•×§×™×™×. + +/community/join.bml.label.expls=לחץ על הכפתור למטה ×œ×©× ×”×¦×˜×¨×¤×•×ª לקהילה "[[maintainer]]". ×ל תסמן ×ת התיבה שלמטה ×× ×ינך רוצה לר×ות ×ת ×”×¨×™×©×•×ž×™× ×‘×§×”×™×œ×” זו בדף ×”×—×‘×¨×™× ×©×œ×š. + +/community/join.bml.label.loginfirst=על מנת להצטרף לקהילה עליך להתחבר למערכת תחילה. + +/community/join.bml.label.membernow=כעת הנך חבר בקהילה [[commname]]. + +/community/join.bml.label.sure=×”×× ×תה בטוח? + +/community/join.bml.success=הצלחה + +/community/join.bml.title=הצטרף לקהילה + +/community/leave.bml.button.leave=עזוב קהילה + +/community/leave.bml.label.buttontoleave=לחץ על הכפתור למטה ×œ×©× ×¢×–×™×‘×ª הקהילה "[[commname]]". + +/community/leave.bml.label.infoerror=פרטי הקהילה שצויינו ××™× × ×—×•×§×™×™×. + +/community/leave.bml.label.logoutfirst=×œ×©× ×¢×–×™×‘×ª קהילה, תחילה עליךלהתחבר למערכת. + +/community/leave.bml.label.removed=×ינך עוד חבר בקהילה [[commname]] + +/community/leave.bml.success=הצלחה + +/community/leave.bml.sure=×”×× ×תה בטוח? + +/community/leave.bml.title=עזיבת קהילה + +/community/manage.bml.commlist.actions=פעולות + +/community/manage.bml.commlist.header=הקהילות שלך + +/community/manage.bml.commlist.none=×ין קהילות בניהולך. + +/community/manage.bml.commlist.text=להלן הקהילות שבניהולן ×ת/×” משתתפ/ת: + +/community/manage.bml.commlist.title=כותרת + +/community/manage.bml.commlist.username=×©× ×ž×©×ª×ž×©: + +/community/manage.bml.create.header=יצירת קהילה + +/community/manage.bml.title=ניהול קהילה + +/community/members.bml.error.nocomm=הקהילה ×œ× × ×ž×¦××”. + +/community/members.bml.key.admin=מתחזק/ת + +/community/search.bml.button.clear=נקה טופס + +/community/search.bml.button.search=חיפוש! + +/community/search.bml.checkbox.onlywithpics=קהילות ×¢× ×ª×ž×•× ×•×ª בלבד + +/community/search.bml.label.byinterest=לפי תחומי עניין + +/community/search.bml.label.bylocation=לפי ×ž×™×§×•× + +/community/search.bml.label.bytime=לפי מועד עדכון היומן + +/community/search.bml.label.city=עיר: + +/community/search.bml.label.country=×רץ: + +/community/search.bml.label.displayoptions=×פשרויות תצוגה + +/community/search.bml.label.hasmember=כולל ×ת המשתמש + +/community/search.bml.label.othercriteria=×§×¨×™×˜×¨×™×•× ×™× × ×•×¡×¤×™× + +/community/search.bml.label.outputformat=צורת פלט + +/community/search.bml.label.records=×¤×¨×™×˜×™× ×‘×“×£: + +/community/search.bml.label.searchcomm=חיפוש בקהילות + +/community/search.bml.label.selecriteria=בחר ×ת ×”×§×¨×™×˜×¨×™×•× ×™× ×œ×¤×™×”× ×‘×¨×¦×•× ×š לחפש קהילות. התוצ×ות שיתקבלו הנן חיתך של ×”×§×¨×™×˜×¨×™×•× ×™× ×”× ×‘×—×¨×™×. כלומר, משמעותה של כל תיבה שתסמן ×”×™× "ו", ×•×œ× "×ו". + +/community/search.bml.label.sortmethod=צורת מיון: + +/community/search.bml.label.stateprovince=מדינה/מחוז: + +/community/search.bml.label.updated=עודכן ב- + +/community/search.bml.sel.bypicture=לפי תמונות + +/community/search.bml.sel.communityname=×©× ×”×§×”×™×œ×” + +/community/search.bml.sel.commview=תצוגת קהילה + +/community/search.bml.sel.day=×™×•× + +/community/search.bml.sel.month=חודש + +/community/search.bml.sel.simple=פשוט + +/community/search.bml.sel.updatetime=מועד עדכון + +/community/search.bml.sel.username=×©× ×ž×©×ª×ž×© + +/community/search.bml.sel.week=שבוע + +/community/search.bml.title=חיפוש קהילות + +/create.bml.age.check.question=×”×× ×תה מתחת לגיל 13? + +/create.bml.age.check.yes=כן, גילי ×”×•× ×¤×—×•×ª מ-13 . + +/create.bml.age.head=גיל + +/create.bml.btn.proceed=המשך... + +/create.bml.clusterselect.cluster=גוש: + +/create.bml.clusterselect.clusternum=גוש [[number]] + +/create.bml.clusterselect.head=בחירת גוש + +/create.bml.clusterselect.nocluster=×œ×œ× ×’×•×© + +/create.bml.clusterselect.text=× × ×œ×‘×—×•×¨ ×ת הגוש בו ברצונך ליצור חשבון. הערה: זו ×פשרות לבדיקות וניפוי שגי×ות בלבד. במערכת פעילה ×ž×©×ª×ž×©×™× ×œ× ×™×‘×—×¨×• בזה ×•×œ× ×™×“×¢×• על ×–×” דבר. + +/create.bml.create.head=יצירת יומן חדש + +/create.bml.create.text=קל ליצור LiveJournal חדש, פשוט ×¢×•×§×‘×™× ×חרי ההור×ות להלן! + +/create.bml.email.head=כתובת הדו×ל שלך + +/create.bml.email.input.head=כתובת דו×ל: + +/create.bml.error.coppa.under13=מצטערי×, ×ך עקב מגבלות החוק ×”×מריקני (COPPA), ×œ× × ×™×ª×Ÿ לספק לך שירותי LiveJournal לפני הגיעך לגיל 13. נשמח לר×ותך ×‘×™×•× ×”×•×œ×“×ª 13 שלך. + +/create.bml.error.email.blank=עלייך לספק ×ת כתובת הדו×ל שלך. + +/create.bml.error.email.lj_domain=×ין להשתמש בכינוי מהדומיין [[domain]] בעת יצירת חשבון. × × ×œ×”×–×™×Ÿ כתובת דו×ל ×חרת. + +/create.bml.error.email.nospaces=×¨×•×•×—×™× ××™× × ×ž×•×ª×¨×™× ×‘×›×ª×•×‘×ª דו×ל. ×× ×—×©×‘×•× ×š ×צל AOL, יש לזכור שכתובת הדו×ל שלך ×”×™× ×©× ×”×ž×¡×š שלך (screen name) ×œ×œ× ×¨×•×•×—×™×, ול×חריו @aol.com + +/create.bml.error.password.asciionly=עליך להשתמש רק בסימני ASCII ×¨×’×™×œ×™× ×‘×¡×™×¡×ž×ª×š. + +/create.bml.error.password.blank=עלייך לספק סיסמ×. + +/create.bml.error.password.nomatch=הסיסמ×ות ×ינן תו×מות. + +/create.bml.error.postrequired=דרוש רישו×. + +/create.bml.error.username.blank=× × ×œ×¦×™×™×Ÿ ×©× ×ו כינוי. + +/create.bml.error.username.inuse=×©× ×”×ž×©×ª×ž×© כבר תפוס; × × ×œ×‘×—×•×¨ ×©× ×חר. + +/create.bml.error.username.iscode=×©× ×”×ž×©×ª×ž×© נר××” כקוד הזמנה ×‘×ž×§×•× ×©× ×ž×©×ª×ž×©. + +/create.bml.error.username.mustenter=עלייך לספק ×©× ×ž×©×ª×ž×©. + +/create.bml.error.username.reserved=למרבה הצער, ×©× ×ž×©×ª×ž×© ×–×” שמור. + +/create.bml.name.head=שמך + +/create.bml.name.input.head=ש×: + +/create.bml.name.text=מה שמך, ×ו כינויך? ×©× ×–×” יופיע בר×ש היומן שלך, ×•×’× ×‘×¡×¤×¨ המשתמשי×, ×× ×‘×—×¨×ª להופיע בו. ×ין חובה לציין ×ת שמך ×”×ž×œ× ×ו ×ו ×פילו להשתמש בשמך ×”×מיתי. + +/create.bml.password.head=×¡×™×¡×ž× + +/create.bml.password.input.head1=סיסמ×: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=× × ×œ×”×§×œ×™×“ ×¡×™×¡×ž× ×©×•×‘: + +/create.bml.password.text=× × ×œ×‘×—×•×¨ סיסמ×. + +/create.bml.proceed.btn.proceed=המשך... + +/create.bml.proceed.warning=× × ×œ×œ×—×•×¥ על המשך רק ×¤×¢× ×חת!! + +/create.bml.success.btn.enterinfo=הכנסת ×¤×¨×˜×™× ××™×©×™×™× + +/create.bml.success.head=הצלחה! + +/create.bml.success.text1|staleness=1 +/create.bml.success.text1=יומנך נוצר בהצלחה. מידע ×¨×™×©×•× ×—×©×•×‘ נשלח לכתובת [[email]] ובו הור×ות נוספות. הערה: לרשותך בדיוק שבעה ×™×ž×™× ×œ×שר ×ת יצירת יומנך. ×× ×›×¢×‘×•×¨ שבעה ×™×ž×™× ×œ× × ×™×’×©×ª ליומנך, יימחק ×©× ×”×ž×©×ª×ž×© [[username]] ×וטומטית, ומישהו ×חר עשוי להשתמש בו. + +/create.bml.success.text2=×”- LiveJournal שלך יופיע ב: + +/create.bml.success.text3=עכשיו, בבקשה מל×/×™ מספר ×¤×¨×˜×™× ×ישיי×. ×ין חובה ×œ×ž×œ× ×ת רוב הפרטי×, ×בל ×”× × ×•×ª× ×™× ×œ× ×• מושג על ×ילו ×× ×©×™× ×ž×©×ª×ž×©×™× ×‘- LiveJournal. + +/create.bml.title=יצירת יומן חדש + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=כדי ליצור חשבון חדש, × × ×œ×”×›× ×™×¡ קוד יצירת חשבון: + +/create.bml.useacctcodes.welcome=×‘×¨×•×›×™× ×”×‘××™× + +/create.bml.username.box.head=×©× ×ž×©×ª×ž×©: + +/create.bml.username.forpaidaccts=×ו, לחשבונות בתשלו×: + +/create.bml.username.head=×©× ×ž×©×ª×ž×© + +/create.bml.username.ljaddress=יומנך ×™×”×™×” בכתובות ×לו: + +/create.bml.username.text=כל משתמש [[sitename]] חייב ל×מץ ×©× ×ž×©×ª×ž×© ייחודי. ×©× ×”×ž×©×ª×ž×© שלך מופיע בכתובת היומן שלך, ו×יתו ניתן להזדהות מול שרת [[sitename]]. ×”×•× ××£ מופיע בהערות פרי עטך ×‘×™×•×ž× ×™× ×©×œ ×חרי×. + +/create.bml.username.username=×©× ×ž×©×ª×ž×© + +/editinfo.bml.allowshowcontact.about=עליך להש×יר ×פשרות זו. כך ת×פשר ל×× ×©×™× ××—×¨×™× ×œ×™×¦×•×¨ ×יתך קשר על ידי הצגת כתובת הדו×ר ×”×לקטרוני, מספר ×”- ICQ ×•×©× ×”×ž×©×ª×ž×© שלך ב- AOL Instant Messenger בדף ×”×¤×¨×˜×™× ×”××™×©×™×™× ×©×œ×š ב- LiveJournal. + +/editinfo.bml.allowshowcontact.email=×× ×ž×•×¦×’, זו כתובת הדו×"ל שתוצג. + +/editinfo.bml.allowshowcontact.email.actual_only=כתובת ×מיתית בלבד + +/editinfo.bml.allowshowcontact.email.both=×©× ×™×”× (×מיתי + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=כתובת LiveJournal בלבד + +/editinfo.bml.allowshowcontact.email.neither=××£ ×חד משניה×. ×ל תציג כתובת דו×"ל כלשהי. + +/editinfo.bml.allowshowcontact.email.no_show=×ל תציג כתובת דו×"ל + +/editinfo.bml.allowshowcontact.email.show=הצג כתובת דו×"ל + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=בתיבה לעיל תוכל לבחור להסתיר ×ת כתובת הדו×ל שלך (ועדיין להציג × ×ª×•× ×™× ××™×©×™×™× ×חרי×). + +/editinfo.bml.allowshowcontact.title=×”×× ×œ×”×¦×™×’ ×ת פרטי ההתקשרות שלך ב- LiveJournal שלך? + +/editinfo.bml.allowshowinfo.about=בחר ב×פשרות זו ×× ×‘×¨×¦×•× ×š להציג ×ת העיר/מדינה/×רץ ות×ריך הלידה שלך בפני ×ž×©×ª×ž×©×™× ×חרי×. + +/editinfo.bml.allowshowinfo.title=הצג ×ž×™×§×•× ×•×ª×ריך לידה + +/editinfo.bml.autotranslate.about<< +השתמש ב×פשרות זו כדי לקבוע ב×יזו צורת קידוד תניח מערכת LiveJournal שהשתמשת ×‘×¨×™×©×•×ž×™× ×•×”×”×¢×¨×•×ª שפרסמת לפני המרת ×”×תר לפורמט Unicode. +×× ×תה כותב ב×נגלית, בחר ב×פשרות "Western European". +. + +/editinfo.bml.autotranslate.header|staleness=1 +/editinfo.bml.autotranslate.header=בצע ×ª×¨×’×•× ×וטומטי של ×¨×™×©×•×ž×™× ×™×©× ×™× ×ž×©×¤×”: + +/editinfo.bml.bday.title=ת×ריך לידה + +/editinfo.bml.bday.year.opt=×ינך חייב לציין שנה + +/editinfo.bml.bdayreminders.about=×× ×‘×¨×¦×•× ×š לקבל תזכורות בדו×"ל ×ודות ימי הולדת של חבריך ב - LiveJournal, סמן תיבה זו. + +/editinfo.bml.bdayreminders.header|staleness=1 +/editinfo.bml.bdayreminders.header=שלח לי תזכורות ימי הולדת. + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=×›×ן ב×פשרותך להזין תי×ור ביוגרפי קצר של עצמך ×שר יופיע בדף פרטי המשתמש שלך. + +/editinfo.bml.bio.header=על ×ודותיך + +/editinfo.bml.blockrobots.about|staleness=1 +/editinfo.bml.blockrobots.about<< +×× ×ª×™×‘×—×¨ ×”×פשרות הזו, נגיד ×œ×¨×•×‘×•×˜×™× ×œ×”×¡×ª×œ×§. +×œ× ×›×œ ×”×¨×•×‘×•×˜×™× ×™×›×‘×“×• ×ת בקשתנו בהכרח, ×בל ×”×¨×•×‘×•×˜×™× ×©×œ ×תרי החיפוש ×”×ž×‘×•×§×©×™× ×™×¦×™×™×ª×•. +. + +/editinfo.bml.blockrobots.header=חסימת ×¨×•×‘×•×˜×™× ×•×¢×›×‘×™×©×™× ×ž×”×•×¡×¤×ª יומנך ל×ינדקס ×©×œ×”× + +/editinfo.bml.city.title=יישוב + +/editinfo.bml.country.choose=בחר/×™ מדינה + +/editinfo.bml.country.title=מדינה + +/editinfo.bml.donotlog=×œ× + +/editinfo.bml.email.title=דו×ל + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=סמן ×פשרות זו ×× ×‘×¨×¦×•× ×š ל×פשר ×œ×ž×©×ª×ž×©×™× ××—×¨×™× ×œ×”×’×™×‘ ×œ×¨×™×©×•×ž×™× ×‘×™×•×ž× ×š (על סגנון היומן בו הנך משתמש לתמוך ב×פשרות זו) + +/editinfo.bml.enableboards.header=×פשר שימוש בלוחות תגובות + +/editinfo.bml.encoding.about=×ל תד××’ לגבי ×”×¢× ×™×™× ×™× ×”×לה. ככלל, רק ×ž×©×ª×ž×©×™× ×‘×™× ×œ××•×ž×™×™× ×”×›×•×ª×‘×™× ×‘×©×¤×•×ª שונות יצטרכו לשנות פה משהו. + +/editinfo.bml.encoding.header=×פשרויות קידוד + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +×ינך יכול להזין כתובת דו×"ל @[[domain]]. +הזן ×ת כתובתך ×”×מיתית בשדה ×–×”.. +×× ×”× ×š משתמש בתשלו×, כתובתך [[user]]@[[domain]] תבצע העברה ×וטומטית ×ל כתובתך ×”×מיתית. +×œ×©× ×‘×—×™×¨×” ×יזו כתובת דו×"ל (×ו שתיהן) תוצג בציבור, ר××” ×ת ×”×פשרות המופיעה מתחת ל"הצג ×¤×¨×˜×™× ×œ×™×¦×™×¨×ª קשר". +. + +/editinfo.bml.error.email.no_space<< +×œ× × ×™×ª×Ÿ להשתמש ×‘×¨×•×•×—×™× ×‘×›×ª×•×‘×ª דו×"ל. +×× ×”× ×š משתמש AOL, זכור ×›×™ כתובת הדו×"ל שלך ×”×™× ×©× ×”×ž×©×ª×ž×© שלך, ×œ×œ× ×¨×•×•×—×™× ×›×œ×©×”× ×•×חריו @aol.com +. + +/editinfo.bml.error.excessive_int<< +מצטערי×, ציינת יותר מדי תחומי עניין. קיימת מגבלה של 150 תחומי×, ×ך ×תה ציינת [[intcount]]. +×”×©×™× ×•×™×™× ×©×‘×™×¦×¢×ª ברשימת תחומי העניין שלך ×œ× × ×©×ž×¨×•. חזור ×חורה ×•×¦×ž×¦× ×ת הרשימה שלך ול×חר מכן שמור שנית ×ת הרשימה. + +. + +/editinfo.bml.error.invalidbio=הביוגרפיה שלך כוללת ×ª×•×•×™× ×œ× ×—×•×§×™×™×. עליך לגשת ×ל דף ההמרה ולהמירו לפורמט Unicode. + +/editinfo.bml.error.invalidints=רשימת תחומי העניין שלך כוללת ×ª×•×•×™× ×œ× ×—×•×§×™×™×. עליך לגשת ×ל דף ההמרה ולהמירו לפורמט Unicode. + +/editinfo.bml.error.invalidname=שמך כולל ×ª×•×•×™× ×œ× ×—×•×§×™×™×. עליך לגשת ×ל דף ההמרה ולהמירו לפורמט Unicode. + +/editinfo.bml.error.locale.country_ne_state=ציינת ×ת ×רה"ב ×›×רץ בה ×תה גר, ×ך הקלדת מדינה ש××™× ×” חלק מ×רה"ב בשדה "מדינה ×חרת". + +/editinfo.bml.error.locale.invalid_country=בחרת במדינה ש××™× ×” קיימת. + +/editinfo.bml.error.locale.state_ne_country=ציינת ×רץ ש××™× ×” ×רה"ב, ×ך בחרת במדינה ×©×”×—×™× ×—×œ×§ מ×רה"ב. + +/editinfo.bml.error.locale.zip_ne_state<< +המיקוד שציינת ×ינו תו×× ×œ×ž×“×™× ×” שציינת. +תקן × ×ª×•× ×™× ×לה, ×ו מחק ×ת תוכן שדות המדינה ו/×ו המיקוד. +. + +/editinfo.bml.error.locale.zip_requires_us|staleness=1 +/editinfo.bml.error.locale.zip_requires_us<< +הזנת מיקוד, ×ך ×œ× ×‘×—×¨×ª ב×רה"ב ×›×רץ בה ×תה גר. +×נו ××•×¡×¤×™× ×ת פרטי המיקוד ×ž×ž×©×ª×ž×©×™× ×”×—×™×™× ×‘×רה"ב בלבד. +× × ×—×–×•×¨ לדף ×”×§×•×“× ×•×ž×—×§ ×ת המיקוד שציינת, ×ו בחר ב×רה"ב ×›×רץ בה ×תה ×—×™. + +. + +/editinfo.bml.error.tm.require.number=×× ×‘×›×•×•× ×ª×š להשתמש בתכונת שליחת הודעות טקסט, עליך להזין ×ת מספר הטלפון שלך. + +/editinfo.bml.error.tm.require_provider<< +×× ×‘×›×•×•× ×ª×š להשתמש בתכונת שליחת הודעות טקסט, עליך לבחור בספק השירות שלך. +במידה והספק שלך ×ינו מופיע ברשימה, צור עימנו קשר ומסור לנו ×ת המידע הדרוש ×ודות ×ופן שליחת הודעות טקסט ×צל ספק השירות שלך, כדי שנוכל להוסיף תמיכה בספק ×–×”. + +. + +/editinfo.bml.finished.about=ל×חר שסיימת, לחץ על כפתור "שמור שינויי×" שלמטה. + +/editinfo.bml.finished.header=סיימת? + +/editinfo.bml.finished.save_button=שמור ×©×™× ×•×™×™× + +/editinfo.bml.gender.title=מין + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=סמן ×›×ן ×× ×‘×¨×¦×•× ×š לקבל ×¢×“×›×•× ×™× ×‘×“×•×"ל ×›×שר ×ž×©×ª×ž×©×™× ××—×¨×™× ×™×’×™×‘×• ×œ×¨×™×©×•×ž×™× ×‘×™×•×ž× ×š. + +/editinfo.bml.getreplies.header=×פשר קבלת תגובות + +/editinfo.bml.hidefriendof.about=סמן ×›×ן ×× ×‘×¨×¦×•× ×š להסתיר ×ת רשימת ×”×ž×©×ª×ž×©×™× ×”×ž×’×“×™×¨×™× ×ותך כחבר בדף פרטי המשתמש שלך. + +/editinfo.bml.hidefriendof.header=הסתר רשימת "חבר של" + +/editinfo.bml.howhear.about|staleness=1 +/editinfo.bml.howhear.about<< +מתוך סקרנות, היכן שמעת ×ודות [[sitename]]? +×× ×”×™×” ×–×” ××“× ×ž×¡×•×™×™×, ×× × ×¦×™×™×Ÿ ×ת ×©× ×”×ž×©×ª×ž×© שלו. במידה והגעת ×לינו ממקור ×חר/כתבה/קישור/×תר, ×× × ×”×–×Ÿ ×ת המידע הרלוונטי. +. + +/editinfo.bml.howhear.header=סקרנות + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +סמן ×›×ן ×× ×ª×•×›× ×ª הדו×ר ×”×לקטרוני שלך תומכת היטב בדו×ר בפורמט HTML. +תוכנות רבות מנסות לתמוך ב- HTML ×ך נכשלות בכך בצורה מביכה. +×× ×œ× ×ª×¡×ž×Ÿ תיבה זו, הודעות הדו×"ל שיישלחו ×ליך מ- LiveJournal יהיו בפורמט טקסט בלבד. +. + +/editinfo.bml.htmlemail.header=שלח הודעות דו×"ל בפורמט HTML + +/editinfo.bml.int.about<< +×× ×‘×¨×¦×•× ×š ×©×ž×©×ª×ž×©×™× ××—×¨×™× ×™×•×›×œ×• לבצע חיפוש במדריך ×•×œ×ž×¦×•× ×ותך על פי תחומי העניין שלך, פרט ×ת ×”×ª×—×•×ž×™× ×‘×”× ×תה מתעניין, ×›×©×”× ×ž×•×¤×¨×“×™× ×–×” מזה בפסיקי×. +מומלץ להשתמש ×‘×‘×™×˜×•×™×™× ×§×¦×¨×™×, בני מילה ×חת. ×©×™× ×œ×‘: ×תה ×מור להיות מסוגל להשתמש במילה במשפט כגון "×× ×™ ×והב ________". ×›×שר הנך מתייחס למושג ×©×”×•× ×‘×œ×©×•×Ÿ ×¨×‘×™× ×”×©×ª×ž×© בלשון יחיד, מסיבות של עקביות. לדוגמה: "I like DVDs" ×‘×ž×§×•× "I like DVD". +. + +/editinfo.bml.int.ex.bad=רע לדוגמה: I like lots of bands and watching movies and talking to friends and going to clubs. תוכן ×›×–×” יופיע בביוגרפיה שלך המופיעה למעלה. + +/editinfo.bml.int.ex.good=טוב לדוגמה: biking, snow skiing, computers, dvds, mp3s, cheese, women + +/editinfo.bml.int.header=תחומי עניין + +/editinfo.bml.login.enterinfo=הזן ×ת ×©× ×”×ž×©×ª×ž×© והסיסמה שלך ×œ×©× ×¢×¨×™×›×ª ×”×¤×¨×˜×™× ×”××™×©×™×™× ×©×œ×š. + +/editinfo.bml.login.forgot.header=שכחת משהו? + +/editinfo.bml.login.forgot.recover=×× ×©×›×—×ª ×ת ×©× ×”×ž×©×ª×ž×© ×ו הסיסמה שלך, שחזר ××•×ª× ×›×ן!. + +/editinfo.bml.logip.always=תמיד + +/editinfo.bml.logip.anon_only=×ž×©×ª×ž×©×™× ××œ×ž×•× ×™× ×‘×œ×‘×“ + +/editinfo.bml.logip.header=×¨×©×•× ×ž×¡×¤×¨×™ IP של כותבי התגובות? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=במידה ובחרת ב×פשרות של ציון כתובת הדו×"ל שלך, ו×תה חושש שתוכנות ×”×וספות כתובת דו×"ל ב×ינטרנט ימצ×ו ×ת כתובתך ב- LiveJournal, סמן ×פשרות זו וכתובתך תשונה כך ×©×”×™× ×œ× ×ª×ותר על ידי מנועי חיפוש כתובות דו×"ל. + +/editinfo.bml.mangleaddress.header=בלגן ×ת כתובת הדו×"ל המוצגת + +/editinfo.bml.name.title=×©× + +/editinfo.bml.numcomments.about=סמן ×פשרות זו ×× ×‘×¨×¦×•× ×š להחיל ×ת ספירת כתובת ×”- URL כדי שתהיה לדפדפן שלך ×פשרות להציג ×ת ×”×§×™×©×•×¨×™× ×‘×¦×‘×¢ שונה. + +/editinfo.bml.numcomments.header=×”×× ×œ×”×•×¡×™×£ &nc=xx לכתובות של תגובות? + +/editinfo.bml.optional=×œ× ×—×•×‘×” + +/editinfo.bml.opt_in.about<< +×× ×‘×¨×¦×•× ×š לקבל עדכון בכל ×¤×¢× ×©× ×•×¡×™×£ תכונה חדשה ומדליקה ל- LiveJournal, סמן תיבה זו. +הודעות העדכון שיישלחו ×ליך יהיו נדירות למדי, ×¤×¢× ×ו ×¤×¢×ž×™×™× ×‘×—×•×“×© לכל היותר. +כתובת הדו×"ל שלך ×œ× ×ª×•×¦×’ בפני ×ž×©×ª×ž×©×™× ××—×¨×™× ×•×פשרותך לבטל הגדרה זו בכל עת. +. + +/editinfo.bml.opt_in.header=שלחו לי חדשות על LiveJournal + +/editinfo.bml.persinfo.disclaimer<< +×× × ×”×–×Ÿ מעט מידע על עצמך, כדי לספק ×ת הסקרנות שלנו ×•×œ×©×™×ž×•×©×™× ×”×¡×˜×˜×™×¡×˜×™×™× ×©×œ× ×•. +×ין בכוונתנו לעשות שימוש מרושע ×ו מעצבן במידע ×–×”, ×נו פשוט ×ž×¢×•× ×™×™× ×™× ×œ×“×¢×ª מי ומה ×”× ×”×ž×©×ª×ž×©×™× ×©×œ× ×•. בבקשה, ד×גו ×œ×ž×œ× ×ž×™×“×¢ נכון. ×× ×תה מוד××’, +×§×¨× ×ת הצהרת הפרטיות שלנו. +. + +/editinfo.bml.persinfo.header=×¤×¨×˜×™× ××™×©×™×™× + +/editinfo.bml.screen.all=כולן + +/editinfo.bml.screen.anon=×נונימיות + +/editinfo.bml.screen.header=×ילו תגובות ברצונך לסנן כברירת מחדל? + +/editinfo.bml.screen.none=×œ× ×œ×¡× ×Ÿ + +/editinfo.bml.screen.nonfriends=מ×ת ×ž×©×ª×ž×©×™× ×©××™× × ×—×‘×¨×™× ×©×œ×™ + +/editinfo.bml.screen.nonmembers=מ×ת ל×-×ž×©×ª×ž×©×™× + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=×בטחה + +/editinfo.bml.security.visibility.anybody=כל ×חד + +/editinfo.bml.security.visibility.everybody=×›×•×œ× + +/editinfo.bml.security.visibility.friends=×—×‘×¨×™× ×‘×œ×‘×“ + +/editinfo.bml.security.visibility.regusers=×ž×©×ª×ž×©×™× ×¨×©×•×ž×™× + +/editinfo.bml.settings.header=×פשרויות LiveJournal + +/editinfo.bml.state.other=×ו, רשו×\×™ מדינה\מחוז\שטח שונה + +/editinfo.bml.state.title=מדינה + +/editinfo.bml.state.us=מדינות ×רה"ב + +/editinfo.bml.success.header=הצלחה! + +/editinfo.bml.success.message=המידע שלך ויומנך ופרופילך התעדכנו. + +/editinfo.bml.switch.button=החלפה + +/editinfo.bml.switch.header=החלף\×™ יומן + +/editinfo.bml.switch.workwith=עבוד ×¢× ×™×•×ž×Ÿ: + +/editinfo.bml.title=עריכת ×¤×¨×˜×™× ××™×©×™×™× + +/editinfo.bml.tm.details=פירוט + +/editinfo.bml.tm.phonenum=מספר טלפון: + +/editinfo.bml.tm.sec.about=×פשר הודעות טקסט ×ž×ž×©×ª×ž×©×™× ×חרי×. + +/editinfo.bml.tm.sec.title=רמת בטיחות + +/editinfo.bml.tm.servprov=חברה מספקת + +/editinfo.bml.tm.title=הודעות טקסט + +/editinfo.bml.translatemailto.about=במידה ובחרת לקבל ×ת התגובות ×œ×¨×™×©×•×ž×™× ×‘×מצעות דו×"ל, ותוכנת הדו×"ל שלך ×ינך תומכת כהלכה בפורמט Unicode (UTF-8), השתמש ב×פשרות זו ×œ×©× ×¦×™×•×Ÿ צורת קידוד שונה ×ליה תמיר מערכת LiveJournal ×ת טקסט ההודעות הנשלחות ×ליך. + +/editinfo.bml.translatemailto.header=×ª×¨×’× ×”×•×“×¢×•×ª דו×ר ×לקטרוני ל: + +/editinfo.bml.unbanusers.about=חסמת ×ת ×”×ž×©×ª×ž×©×™× ×œ×”×œ×Ÿ ×ž×¤×¨×¡×•× ×‘×™×•×ž× ×š. סמן ×ת תיבת הסימון המופיעה לצד ×©×ž× ×¢×œ מנת להסיר ×ת החסימה. + +/editinfo.bml.unbanusers.header=ביטול חסימת ×ž×©×ª×ž×©×™× + +/editinfo.bml.userpic.about=להלן התמונה שהעלית על מנת לייצג ×ותך ב×תר LiveJournal, ביומנך ×•×‘×™×•×ž× ×™×”× ×©×œ חבריך: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=למחיקת תמונה זו, ×ו העל×ת תמונה חדשה, , לחץ ×›×ן. + +/editinfo.bml.userpic.header=תמונתך + +/editinfo.bml.userpic.none=תמונה ×œ× ×”×•×¢×œ×ª×” + +/editinfo.bml.webpagename.title=×©× ×תר + +/editinfo.bml.webpageurl.title=כתובת ×תר + +/editinfo.bml.whoreply.header=מי רש××™ להגיב לרשימותיך? + +/editinfo.bml.zip.title=מיקוד + +/editinfo.bml.zip.usonly=מיקוד בעל 5 ספרות; תושבי ×רה"ב בלבד + +/editjournal.bml.btn.proceed=המשך... + +/editjournal.bml.certainday=×™×•× ×ž×¡×•×™×: + +/editjournal.bml.recententries=×¨×™×©×•×ž×™× ××—×¨×•× ×™× + +/editjournal.bml.recententry=×¨×™×©×•× ×חרון + +/editjournal.bml.title=עריכת רישומי יומן + +/editjournal.bml.viewwhat=ב×ילו ×¨×™×©×•×ž×™× ×‘×¨×¦×•× ×š לעיין: + +/editjournal_do.bml.btn.edit=עריכת ×”×¨×™×©×•× ×”× ×‘×—×¨ + +/editjournal_do.bml.btn.save=שמירת ×¨×™×©×•× ×–×” + +/editjournal_do.bml.continue.head=× × ×œ×œ×—×•×¥ להמשך... + +/editjournal_do.bml.continue.text=ל×חר הבחירה בפריט לעריכה ×ו מחיקה, × × ×œ×œ×—×•×¥ על לחצן העריכה שלמטה. + +/editjournal_do.bml.currmood|staleness=1 +/editjournal_do.bml.currmood=מצב-רוח נוכחי: + +/editjournal_do.bml.currmusic=מוסיקה נוכחית: + +/editjournal_do.bml.date=ת×ריך: + +/editjournal_do.bml.default=ברירת מחדל + +/editjournal_do.bml.edit.text|staleness=2 +/editjournal_do.bml.edit.text=ערוך ×ת השדות ברשימתך ש×תה מעוניין לשנות, ולחץ על הלחצן "שמירה" שבתחתית העמוד. כדי למחוק רשימה, יש למחוק ×ת כל הטקסט וללחוץ על "שמירה"... הרשימה תמחק. + +/editjournal_do.bml.error.getting=×ירעה שגי××” בגישה לרישומי היומן לצורך עריכה: + +/editjournal_do.bml.error.modify=×ירעה שגי××” בעת שינוי יומנך: + +/editjournal_do.bml.error.nofind=×¨×™×©×•× ×”×™×•×ž×Ÿ הנבחר ×œ× × ×ž×¦×. + +/editjournal_do.bml.event=×ירוע: + +/editjournal_do.bml.localtime=זמן מקומי: + +/editjournal_do.bml.noneother=כלו×, ×ו ×חר. + +/editjournal_do.bml.opt.backdate=תי×רוך-ל×חור של הרישו×: + +/editjournal_do.bml.opt.backdate.about=×œ× ×™×•×¦×’ בתצוגת ×—×‘×¨×™× + +/editjournal_do.bml.opt.nocomments=×יסור על תגובות: + +/editjournal_do.bml.opt.noemail=×œ× ×œ×©×œ×•×— תגובות בדו×ל: + +/editjournal_do.bml.opt.noformat=×œ× ×œ×¢×¦×‘ ×וטומטית: + +/editjournal_do.bml.other=×חר: + +/editjournal_do.bml.pickentry.head=× × ×œ×‘×—×•×¨ ×¨×™×©×•× ×œ×¢×¨×™×›×” + +/editjournal_do.bml.pickentry.text=× × ×œ×‘×—×•×¨ בפריט שברצונך לערוך וללחוץ על לחצן העריכה בתחתית הדף. + +/editjournal_do.bml.picture=להשתמש בתמונה: + +/editjournal_do.bml.save.head=× × ×œ×œ×—×•×¥ כדי לשמור... + +/editjournal_do.bml.save.text=בסיימך לערוך ×ת הרישו×, × × ×œ×œ×—×•×¥ על "שמירה". + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=נוש×: (×œ× ×—×•×‘×”, ×בל כד××™ ×‘×¨×™×©×•×ž×™× ×רוכי×) + +/editjournal_do.bml.success.delete=×¨×™×©×•× ×”×™×•×ž×Ÿ נמחק. + +/editjournal_do.bml.success.edit|staleness=1 +/editjournal_do.bml.success.edit=×¨×™×©×•× ×”×™×•×ž×Ÿ עודכן. ניתן לר×ותו ×›×ן. + +/editjournal_do.bml.success.head=הצלחה + +/editjournal_do.bml.timeformat=זמן בפורמט 24 שעות + +/editjournal_do.bml.title=עריכת רישומי יומן + +/friends/add.bml.add.header=הצלחה + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=המשתמש נוסף לדף ×”×—×‘×¨×™× ×©×œ×š. ב×פשרותך להציג ×ת דף ×”×—×‘×¨×™× ×©×œ×š ×›×ן. + +/friends/add.bml.add.title=התווסף חבר! + +/friends/add.bml.btn.add=הוסף ×ת [[user]] + +/friends/add.bml.btn.modify=שינוי + +/friends/add.bml.btn.remove=הסרה + +/friends/add.bml.colors.bg=רקע + +/friends/add.bml.colors.fg=קדמה + +/friends/add.bml.colors.header=×¦×‘×¢×™× + +/friends/add.bml.colors.hover=(העבר ×ת סמן העכבר מעל לצבע על מנת להציג ×ת ×©× ×”×¦×‘×¢) + +/friends/add.bml.colors.text=ב×פשרותך ×’× ×œ×‘×—×•×¨ ×ת ×”×¦×‘×¢×™× ×שר ייצגו ×ת [[user]] ברשימת ×”×—×‘×¨×™× ×©×œ×š. + +/friends/add.bml.confirm.header=×”×× ×œ×”×•×¡×™×£ ×ת [[user]] לרשימת החברי×? + +/friends/add.bml.confirm.text=×œ×©× ×”×•×¡×¤×ª [[user]] לרשימת ×”×—×‘×¨×™× ×©×œ×š, לחץ על הכפתור להלן. + +/friends/add.bml.confirm.title=הוסף חבר + +/friends/add.bml.error1.header|staleness=1 +/friends/add.bml.error1.header=התחבר תחילה + +/friends/add.bml.error1.text<< + ×œ×©× ×”×•×¡×¤×ª משתמש לרשימת חבריך, תחילה עליך + להתחבר למערכת. +×× ×¢×“×™×™×Ÿ ×ין ברשותך חשבון, ב×פשרותך ליצור חשבון על מנת לעקוב ×חרי ×™×•×ž× ×™×”× ×©×œ חבריך. + +. + +/friends/add.bml.error1.title=הוספת חבר + +/friends/add.bml.error2.text|staleness=1 +/friends/add.bml.error2.text=צויין ×©× ×ž×©×ª×ž×© חסר ×ו בלתי חוקי. להוספת חבר, גש לדף עריכת חברי×. + +/friends/add.bml.error3.text=המשתמש [[user]] כבר מופיע ברשימת ×”×—×‘×¨×™× ×©×œ×š. ×ול×, ב×פשרותך לשנות ×ת ×”×¦×‘×¢×™× ×‘××ž×¦×¢×•×ª× ×‘×—×¨ לייצג ×ותה/×ותו. + +/friends/add.bml.error3.title=עריכת חבר + +/friends/add.bml.groups.header=קבוצות ×—×‘×¨×™× + +/friends/add.bml.groups.nogroup|staleness=1 +/friends/add.bml.groups.nogroup=×œ× ×”×•×’×“×¨×• קבוצות ×—×‘×¨×™× + +/friends/add.bml.groups.text=ל×לו קבוצות ×—×‘×¨×™× ×‘×¨×¦×•× ×š לשייך משתמש ×–×”? קבוצות ×—×‘×¨×™× ×ž×©×ž×©×•×ª לסינון תצוגת רשימת ×”×—×‘×¨×™× ×©×œ×š ולקביעת רמות ×בטחה קבוצתיות להצגת רישומי×. + +/friends/add.bml.remove.header=הצלחה + +/friends/add.bml.remove.text=המשתמש הוסר מרשימת ×”×—×‘×¨×™× ×©×œ×š. ב×פשרותך להציג ×ת דף ×”×—×‘×¨×™× ×©×œ×š ×›×ן. + +/friends/add.bml.remove.title=הוסר חבר! + +/friends/edit.bml.title=עריכת ×—×‘×¨×™× + +/friends/edit_do.bml.addfriends.head=הוספת ×—×‘×¨×™× + +/friends/edit_do.bml.addfriends.text=הכנס ×ת שמות ×”×ž×©×ª×ž×©×™× ×©×œ חבריך בתיבה למטה, ובחר ×ילו צבעי רקע וחזית ברצונך לקשר ×ית×... + +/friends/edit_do.bml.background=רקע + +/friends/edit_do.bml.bgcolor=צבע רקע. + +/friends/edit_do.bml.btn.close=סגירה + +/friends/edit_do.bml.btn.save=שמירת ×©×™× ×•×™×™× + +/friends/edit_do.bml.btn.toggle=הפעלת/ביטול חלון תצוגה מקדימה + +/friends/edit_do.bml.done.head=גמרת? + +/friends/edit_do.bml.done.text=כשגמרת, לחץ על "שמירת שינויי×" למטה... + +/friends/edit_do.bml.error.updating=היתה טעות בעדכון רשימת ×”×—×‘×¨×™× ×©×œ×š: + +/friends/edit_do.bml.fellowfriends.text=×”×× ×©×™× ×”×‘××™× ×¨×©×ž×• ×ותך כחבר/×” שלה×... ייתכן שברצונך ×œ×¨×©×•× ××•×ª× ×›×—×‘×¨×™× ×©×œ×š. מידע ×–×” מסופק בעיקר כדי ×œ×”×‘×™× ×œ×™×“×™×¢×ª×š ×ת שמות המשתמש ×©×œ×”× ×‘-LiveJournal. ×ין עליך כל חובה להוסיף ××•×ª× ×œ×¨×©×™×ž×ª×š. + +/friends/edit_do.bml.foreground=חזית + +/friends/edit_do.bml.friend=חבר + +/friends/edit_do.bml.hover=ניתן לרחף מעל צבע בעזרת העכבר על-מנת לר×ות ×ת שמו + +/friends/edit_do.bml.mrcolor=×דון צבעון + +/friends/edit_do.bml.name=×©× + +/friends/edit_do.bml.needmore=×× ×“×¨×•×© לך ×ž×§×•× ×œ×¢×•×“ ×—×‘×¨×™× ×‘×˜×•×¤×¡ ×–×”, יש לשמור ×ת ×”×©×™× ×•×™×™× ×œ×”×œ×Ÿ, ולשוב לכ×ן ולהוסיף עוד חברי×. + +/friends/edit_do.bml.nofriends.head=×ין חברי×? + +/friends/edit_do.bml.nofriends.text=×œ× ×ž×•×’×“×¨×™× ×œ×š כרגע חברי×. ×בל ×נחנו ×‘×˜×•×—×™× ×©×™×© לך כמה חברי×! :) ניתן להקליד ×ת שמות ×”×ž×©×ª×ž×©×™× ×©×œ×”× ×œ×”×œ×Ÿ... + +/friends/edit_do.bml.opt.delete=למחוק? + +/friends/edit_do.bml.success.head=הצלחה + +/friends/edit_do.bml.success.text|staleness=1 +/friends/edit_do.bml.success.text=רשימת חבריך עודכנה. תוכל לר×ות ×ת דף ×”×—×‘×¨×™× ×”×ž×¢×•×“×›×Ÿ שלך ×›×ן. + +/friends/edit_do.bml.textcolor=צבע הטקסט: + +/friends/edit_do.bml.title=עריכת ×—×‘×¨×™× + +/friends/edit_do.bml.user=משתמש + +/friends/edit_do.bml.viewer=תצוגת ×”×¦×‘×¢×™× + +/friends/edit_do.bml.yourfriends.head=חבריך + +/friends/edit_do.bml.yourfriends.text=×”×ž×©×ª×ž×©×™× ×”×‘××™× ×¨×©×•×ž×™× ×›×—×‘×¨×™× ×©×œ×š כרגע: + +/friends/index.bml.title=כלי עריכת רשימת ×”×—×‘×¨×™× + +/index.bml.boldcreate=צרו ×ת ×”- LiveJournal ×”×ישי שלכ×! + +/index.bml.frank.image.alt=פרנק התיש, הקמיע של LiveJournal. + +/index.bml.frank.logo="בעעעעע", ×ומרפרנק. + +/index.bml.meta.desc=Livejournal.com ×”×•× ×ž×§×•× ×‘×• ב×פשרותך לחלוק ×ת מחשבותיך ×¢× ×”×¢×•×œ×. + +/index.bml.meta.keywords=יומן, יומן מקוון, יומני×, כתיבה, ×™×•×ž× ×™× ×ž×§×•×•× ×™× + +/interests.bml.add.added.head=הוסף! + +/interests.bml.add.added.text=×ª×—×•× ×¢× ×™×Ÿ ×–×” נוסף לרשימתך. + +/interests.bml.add.btn.text=הוספת [[interest]] + +/interests.bml.add.confirm.head=×שר/×™ + +/interests.bml.add.confirm.text=על-מנת להוסיף ×ת ×ª×—×•× ×”×¢× ×™×Ÿ [[interest]], לחץ על הלחצן להלן. + +/interests.bml.add.toomany.head=סליחה... + +/interests.bml.add.toomany.text=יש לך כבר [[maxinterests]] תחומי ענין. + +/interests.bml.addint=×× ×ª×—×•× ×–×” מענין ×’× ×ותך וברצונך להתווסף לרשימה, לחץ ×›×ן. + +/interests.bml.communities.head=קהילות רלבנטיות + +/interests.bml.communities.text=הקהילות הב×ות מתעניינות ××£ הן ×‘×ª×—×•× "[[interest]]". + +/interests.bml.count=כמות + +/interests.bml.error.add.mustlogin=עליך להזדהות מול המערכת על-מנת להוסיף ×ª×—×•× ×¢× ×™×Ÿ. + +/interests.bml.error.findsim_do.intnotfound=×ª×—×•× ×”×¢× ×™×Ÿ ×œ× × ×ž×¦×. + +/interests.bml.findsim.searchwait=לתשומת לבך: החיפוש ×™×רך כמה שניות. × × ×œ×”×ª×זר בסבלנות. + +/interests.bml.findsim_do.account.notallowed=למרבה הצער, סוג החשבון שלך ×ינו מ×פשר שימוש ב×פשרות זו. + +/interests.bml.findsim_do.nomatch.head=×ין הת×מות + +/interests.bml.findsim_do.nomatch.text=×ין ×ž×©×ª×ž×©×™× ×“×•×ž×™× ×œ×ž×©×ª×ž×©/ת [[user]]. + +/interests.bml.findsim_do.notdefined=המשתמש/ת [[user]] ×œ× ×”×’×“×™×¨/×” תחומי ענין. + +/interests.bml.findsim_do.similar.head=×ž×©×ª×ž×©×™× ×“×•×ž×™× + +/interests.bml.findsim_do.similar.text=להלן ×”×ž×©×ª×ž×©×™× ×”×“×•×ž×™× ×‘×™×•×ª×¨ בתחומי הענין ×©×œ×”× ×œ×ž×©×ª×ž×©/ת [[user]]: + +/interests.bml.interest=×ª×—×•× ×¢× ×™×Ÿ + +/interests.bml.interested.btn.find=חיפוש + +/interests.bml.interested.in|staleness=1 +/interests.bml.interested.in=חיפוש ×× ×©×™× ×”×ž×ª×¢× ×™×™× ×™× ×‘: + +/interests.bml.interests.head=תחומי ענין + +/interests.bml.interests.text|staleness=1 +/interests.bml.interests.text=להלן כמה ×“×‘×¨×™× ×›×™×¤×™×™× ×©× ×™×ª×Ÿ לעשות ×¢× ×ª×—×•×ž×™ ענין... + +/interests.bml.interests.viewpop=הצג תחומי ענין × ×¤×•×¦×™× + +/interests.bml.match=הת×מה [[count]]: + +/interests.bml.matches=[[count]] תוצ×ות: + +/interests.bml.morestuff|staleness=1 +/interests.bml.morestuff=עוד ×“×‘×¨×™× ×ž×“×œ×™×§×™× ×פשר ×œ×ž×¦×•× ×‘×“×£ תחומי הענין. + +/interests.bml.nointerests.text=×ין לך תחומי ענין רשומי×? כד××™ להוסיף, בדף עריכת פרטי משתמש. + +/interests.bml.popular.head=תחומי ענין × ×¤×•×¦×™× + +/interests.bml.popular.text=להלן תחומי הענין ×”× ×¤×•×¦×™× ×‘×™×•×ª×¨. + +/interests.bml.title=תחומי ענין + +/interests.bml.toomany.body=×™×©× × [[intcount]] ×× ×©×™× ×•/×ו קהילות ×”×ž×ª×¢× ×™× ×™× ×‘×ª×—×•× ×¢× ×™×Ÿ ×–×”. ×œ× ×ª×•×¦×’ רשימה. + +/interests.bml.toomany.head=תוצ×ות רבות + +/interests.bml.users.head=×ž×©×ª×ž×©×™× ×ž×ª×¢× ×™× ×™× + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=×”×ž×©×ª×ž×©×™× ×”×‘××™× ×ž×ª×¢× ×™× ×™× ×‘-[[interest]] ××£ ×”×: + +/legal/coppa.bml.title=חוק "קופ×" ×”×מריקני + +/login.bml.bindip.label=קשור לכתובת IP: + +/login.bml.bindip.no=×œ× (עובד ×¢× ×›×œ ספק שרות) + +/login.bml.bindip.yes=כן (יותר בטוח) + +/login.bml.error.mustenterusername=עליך להקליד ×©× ×ž×©×ª×ž×©. + +/login.bml.expire.btn.neverexpire=שינוי מצב תפוגה ל"×œ×¢×•×œ× ×œ×". + +/login.bml.expire.btn.sessiononly=שינוי מצב תפוגה ל"עד סגירת הדפדפן" + +/login.bml.expire.neverexpire.text=הכניסה למערבת ××£ ×¤×¢× ×œ× ×ª×¤×•×’, כך ש×× ×תה במסוף ציבורי, ×וניברסיטה, ספריה, ×ו ×ž×§×•× ×חר שבו ×× ×©×™× ××—×¨×™× ×¢×©×•×™×™× ×œ×”×©×ª×ž×© במחשב, ×•×“× ×©×™×¦×ת מהמערכת כשסיימת! ×ו לחילופין, ניתן לקבוע שהיצי××” מהמערכת תעשה ×וטומטית כשתסגור ×ת הדפדפן. + +/login.bml.expire.sessiononly.text=הכניסה למערכת תפוג כשהדפדפן ייסגר. ×× ×–×” מחשב שלך, ו×תה המשתמש היחיד, ייתכן שתרצה לקבוע שהכניסה למערכת ××£ ×¤×¢× ×œ× ×ª×¤×•×’: + +/login.bml.links.head=קישוריות + +/login.bml.links.link1=×ל דף ×”×—×‘×¨×™× ×©×œ×š. + +/login.bml.links.link2=×ל רשימת המטלות שלך. + +/login.bml.links.text=בעתיד יהיו בדף ×”×–×” כל מיני ×§×™×©×•×¨×™× ×•×¤×¨×˜×™× ×¨×œ×‘× ×˜×™×™×, ×בל ×‘×™× ×ª×™×™× ×”× ×” כמה מקומות ש×ולי יענינו ×ותך: + +/login.bml.loggedin.head=זוהית על-ידי המערכת! + +/login.bml.loggedin.text=זוהית על-ידי המערכת. + +/login.bml.login.btn.changeopts=שנוי ×פשרויות + +/login.bml.login.btn.login=הזדהות... + +/login.bml.login.expiration=תפוגה: + +/login.bml.login.forget=שכחת? + +/login.bml.login.head=הזדהות מול המערכת + +/login.bml.login.never=×œ×¢×•×œ× ×œ× + +/login.bml.login.otheropts=×פשרויות נוספות: + +/login.bml.login.password=סיסמה: + +/login.bml.login.text1=על-מנת להזדהות מול ×תר [[sitename]], × × ×œ×”×§×œ×™×“ ×ת ×©× ×”×ž×©×ª×ž×© ו×ת הסיסמה להלן. ×ž×©×ª×ž×©×™× ×—×“×©×™×: על-מנת ליצור חשבון, גשו לכ×ן. + +/login.bml.login.username=×©× ×ž×©×ª×ž×©: + +/login.bml.login.whenbrowsercloses=כשהדפדפן נסגר + +/login.bml.title=הזדהות מול המערכת + +/login.bml.whylogin.benefit1=×œ× ×™×”× ×¢×œ×™×š להקליד ×ת ×©× ×”×ž×©×ª×ž×© ו×ת הסיסמה שלך ×‘×©×•× ×ž×§×•× ×‘×תר מעתה. + +/login.bml.whylogin.benefit3=תכונות רבות זמינות ×ך ורק ל×חר שהזדהית מול המערכת. + +/login.bml.whylogin.head=למה להזדהות מול המערכת? + +/login.bml.whylogin.text=×”× ×” כמה יתרונות ×¢×™×§×¨×™×™× ×œ×”×–×“×”×•×ª מול המערכת: + +/logout.bml.already.head=כבר יצ×ת מהמערכת + +/logout.bml.already.text=כבר יצ×ת מהמערכת + +/logout.bml.loggedout.head=בוצעה יצי××” מהמערכת + +/logout.bml.loggedout.text=יצ×ת עתה מהמערכת + +/logout.bml.title=יצי××” מהמערכת + +/lostinfo.bml.btn.proceed=המשך + +/lostinfo.bml.enter_email=הכנס כתובת דו×ר ×”×לקטרוני: + +/lostinfo.bml.enter_email_optional=כתובת דו×ר ×לקטרוני: (רשות) + +/lostinfo.bml.enter_username=× × ×œ×”×§×œ×™×“ ×ת ×©× ×”×ž×©×ª×ž×© שלך: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=×× ×¡×™×¡×ž×ª×š ×בדה, רשו×\×™ ×ת ×©× ×”×ž×©×ª×ž×© שלך וכ×ופציה, ×ת כתובת הדו×ר ×”×לקטרוני הינך מעוניין\ת שסיסמתך תישלח ×ליה. יש לציין שכתובת הדו×ר ×”×לקטרוני חייבת להיות ×ותה הכתובת שהשתמשת ב-LiveJournal בעבר ו×שר ×ושרה. ×× ×ª×©×יר\×™ ×ת שטח הדו×ר ×”×לקטרוני ריק, סיסמתך תישלח לכתובת הדו×ר ×”×לקטרוני הנוכחית. + +/lostinfo.bml.lostpassword.title|staleness=1 +/lostinfo.bml.lostpassword.title=×יבדת ×ת סיסמתך? + +/lostinfo.bml.lostusername.text=×× ×יבדת ×ת ×©× ×”×ž×©×ª×ž×© שלך, × × ×œ×”×§×œ×™×“ ×ת כתובת הדו×ל שלך ונשלח לך ×ותו. + +/lostinfo.bml.lostusername.title|staleness=1 +/lostinfo.bml.lostusername.title=×יבדת ×ת ×©× ×”×ž×©×ª×ž×© שלך? + +/lostinfo.bml.title=×¤×¨×˜×™× ×©×בדו + +/lostinfo_do.bml.error.no_usernames_for_email=×ין משתמש(×™×) לכתובת דור ×לקטרוני ×–×”: [[address]]. + +/lostinfo_do.bml.error1.text=×œ× ×”×©×ª×ž×©×ª בכתובת דו×ר ×לקטרוני זו ×¢× ×—×©×‘×•×Ÿ ×–×” ×ו שכתובת זו ×œ× × ×›× ×¡×” לתוקף. + +/lostinfo_do.bml.password_mailed.text=בוצע בהצלחה. סיסמתך נשלחה ×ליך בדו×ל. + +/lostinfo_do.bml.password_mailed.title=סיסמתך נשלחה! + +/lostinfo_do.bml.title=×¤×¨×˜×™× ×©×בדו + +/lostinfo_do.bml.username_mailed.text=בוצע בהצלחה. ×©× ×”×ž×©×ª×ž×© נשלח ×ליך בדו×ל. + +/lostinfo_do.bml.username_mailed.title=×©× ×”×ž×©×ª×ž×© נשלח בדו×ל! + +/modify.bml.title=עיצוב יומן + +/modify_do.bml.availablestyles.head=סגנונות ×–×ž×™× ×™× + +/modify_do.bml.colortheme.area.head=×זור שימוש + +/modify_do.bml.colortheme.color.head1=צבע + +/modify_do.bml.done.btn.savechanges=שמירת ×©×™× ×•×™×™× + +/modify_do.bml.done.head=סיימת? + +/modify_do.bml.done.text=כסיימת, לחץ על לחצן "שמירת שינויי×" למטה... + +/modify_do.bml.error.stylenotavailable=×חד מהסגנונות שבחרת ×יננו נגיש. ייתכן שזה בגלל מישהו מחק ×ת הסגנון המבוקש, ×ו שבחרת סגנון ש×ין לך רשות להשתמש בו. + +/modify_do.bml.friends.about=×לו ×”×פשרויות הקובעות כיצד ייר××” עמוד ×”×—×‘×¨×™× ×©×œ×š. + +/modify_do.bml.friends.opt.usesharedpic.about=×פשרות זו קובעת ×יזו תמונה תר××” בעמוד ×”×—×‘×¨×™× ×©×œ×š, כשמשתמש ×¨×•×©× ×‘×™×•×ž×Ÿ משותף ×ו בקהילה. ×× ×ª×¡×ž×Ÿ ×פשרות זו, תר××” ×ת סמל הקהילה. ×× ×ª×©×יר ×פשרות זו בלתי מסומנת, תר××” ×ת הסמל ×”×ישי של המשתמש שכתב ×ת הרשימה. + +/modify_do.bml.journaloptions.head=×פשרויות יומן + +/modify_do.bml.journalstatus.about=×× ×‘×¨×¦×•× ×š למחוק ×ו לשחזר ×ת היומן שלך, ×›×ן ×–×” נעשה. ×חרי שמחקת ×ת יומנך, יש לך 30 ×™×•× ×œ×©×—×–×¨ ×ותו, במקרה ששינית ×ת דעתך. ×חרי 30 יו×, יומנך יימחק ב×ופן סופי, ×•×œ× ×ª×”×™×™×” ×פשרות לשחזר ×ותו. + +/modify_do.bml.moodicons.preview=תצוגה מקדימה + +/modify_do.bml.overrides.box.head=עקיפות: + +/modify_do.bml.overrides.head=עקיפות סגנון: + +/modify_do.bml.overrides.warning=×›×ן ×œ× ×”×ž×§×•× ×œ×”×§×œ×™×“ ×ת רישומי היומן! + +/modify_do.bml.pagelayoutstyle.about=ההגדרות הללו קובעות ×ת פריסת היומן שלך על המסך. + +/modify_do.bml.pagelayoutstyle.warning=סוג החשבון שלך מ×פשר לך רק בחירה בין מספר ×ž×¦×•×ž×¦× ×©×œ סגנונות ×ª×§× ×™×™× + +/modify_do.bml.success.head=הצלחה + +/modify_do.bml.success.text=הגדרות יומנך עודכנו. ניתן לעיין ביומנך ×›×ן. + +/paidaccounts/index.bml.costs.header=ובכן, כמה ×–×” עולה? + +/paidaccounts/index.bml.costs.rates=להלן המחירי×: + +/paidaccounts/index.bml.costs.rates.amount.header=×¡×›×•× + +/paidaccounts/index.bml.costs.rates.inexpensive<< +המחיר ×”×•× ×ž×¢×˜ יותר מ- $2 לחודש בתוכנית השנתית. +×¡×›×•× ×שר בהחלט ×œ× ×™×¨×•×©×© ×ותך. +סביר להניח ×›×™ החלק המעצבן היחידי בתהליך ×”×¨×™×©×•× ×™×”×™×” שליפת ×רנקך מהכיס, חיפוש כרטיס ×”×שר××™ שלך והקלדת פרטיך. +. + +/paidaccounts/index.bml.costs.rates.time.header=משך זמן + +/paidaccounts/index.bml.features.header=×לו תכונות מדליקות ×קבל? + +/paidaccounts/index.bml.title=×ודות חשבונות ×‘×ª×©×œ×•× + +/paidaccounts/index.bml.whypay.argument<< +כמובן של×! כולנו ×ž×¡×›×™×ž×™× ×©×ž×¨×’×™×– ×œ×©×œ× ×¢×‘×•×¨ ×©×™×¨×•×ª×™× ×‘×ינטרנט. +לכן רוב תכונות LiveJournal ניתנות בחינ×. +×ול×, ×× ×תה מרוצה מן השירות ש×תה מקבל מ×יתנו, הר××” ×ת הערכתך לנו ורכוש חשבון בתשלו×. +. + +/paidaccounts/index.bml.whypay.header|staleness=2 +/paidaccounts/index.bml.whypay.header=עליי ×œ×©×œ× ×¢×œ השימוש ב- LiveJournal? ×–×” טיפשי! + +/paidaccounts/index.bml.whypay.no_ads=ניהול ×תרי ×ינטרנט עולה כסף (עבור שרתי×, ×חסון ורוחב פס) ונר××” לנו שזוהי דרך טובה יותר ×œ×©×œ× ×¢×‘×•×¨ ×–×” מ×שר להפציץ ×ותך בב×× ×¨×™× ×§×•×¤×¦×™× ×•×‘×“×•×ר זבל פרסומי. + +/paidaccounts/index.bml.your_username=ש×_המשתמש_שלך + +/support/encodings.bml.edit.header=×œ× ×”×¦×œ×—×ª×™ לערוך ×ת רישומי דרך ממשק ×”×תר! + +/support/encodings.bml.editcl.header=×œ× ×”×¦×œ×—×ª×™ לערוך ×ת רישומיי בעזרת תוכנת המשתמש! + +/support/encodings.bml.groups.header=×œ× ×”×¦×œ×—×ª×™ לערוך ×ת רשימת ×”×—×‘×¨×™× ×©×œ×™ בעזרת תוכנת המשתמש! + +/support/encodings.bml.overview.header=במה מדובר, בעצ×? + +/support/encodings.bml.still.header=עדיין מבולבל/ת? + +/support/faqbrowse.bml.backfaq=בחזרה ל- ש×לות נפוצות. + +/support/faqbrowse.bml.backsupport=בחזרה ל- תמיכה. + +/support/faqbrowse.bml.lastupdated=עודכן ל×חרונה + +/talkpost.bml.allowedhtml=HTML מותר + +/talkpost.bml.error.cannotreplynopost=×œ× × ×™×ª×Ÿ להשיב ×œ×¨×™×©×•× ×©×ינו ×§×™×™× + +/talkpost.bml.error.nocommentsjournal=בוטלה ×פשרות התגובה ליומן ×–×” + +/talkpost.bml.error.nocommentspost=בוטלה ×פשרות התגובה ×œ×¨×™×©×•× ×–×” + +/talkpost.bml.error.noreplypost=×œ× × ×ž×¦××” התגובה לה השבת (×ולי נמחקה?) + +/talkpost.bml.error.noreply_screened=תגובה זו מסוננת ו×ין לך הרש××” לצפות בה ×ו להשיב לה. + +/talkpost.bml.label.picturetouse=תמונה ×œ×¨×™×©×•× ×–×”: + +/talkpost.bml.loganonip=חשוב! עבור יומן ×–×” מנוהל ×¨×™×©×•× ×›×ª×•×‘×•×ª IP של ×ž×’×™×‘×™× ×× ×•× ×™×ž×™×™× + +/talkpost.bml.loginq=להזדהות מול המערכת? + +/talkpost.bml.logyourip=חשוב! עבור יומן ×–×” מנוהל ×¨×™×©×•× ×›×ª×•×‘×•×ª IP של כל ×”×ž×’×™×‘×™× + +/talkpost.bml.nosubjecthtml=×סור לשלב קוד HTML בשורת ×”× ×•×©× + +/talkpost.bml.opt.anonymous=×למוני/ת + +/talkpost.bml.opt.defpic=(ברירת מחדל) + +/talkpost.bml.opt.friendsonly=משתמש ×–×” ביטל ×פשרות תגובה ל××œ×ž×•× ×™× ×•×œ×-חברי×. הינך רש××™\ת להגיב ×›×ן ×× [[משתמש]] מגדיר ×ותך כחבר. + +/talkpost.bml.opt.from=מ×ת: + +/talkpost.bml.opt.ljuser=משתמש/ת LiveJournal: + +/talkpost.bml.opt.loggedin=×©× ×ž×©×ª×ž×© מזוהה: [[username]] + +/talkpost.bml.opt.message=הודעה: + +/talkpost.bml.opt.noanonpost=- ביומן ×–×” בוטלה ×פשרות התגובה ×”×למונית + +/talkpost.bml.opt.noautoformat=ביטול עיצוב ×וטומטי: + +/talkpost.bml.opt.noimage=×ין תמונה + +/talkpost.bml.opt.preview=תצוגה מקדימה + +/talkpost.bml.opt.subject=נוש×: + +/talkpost.bml.opt.submit=הוספת תגובה + +/talkpost.bml.paraformat=ברירת המחדל ×”×™× ×¢×™×¦×•×‘ ×וטומטי של פסק×ות + +/talkpost.bml.postresponse=הוספת תגובה לתגובה + +/talkpost.bml.title=הוספת תגובה + +/talkpost.bml.warnscreened=לתשומת לבך: תגובה זו סוננה. השבה לתגובה זו תבטל ×ת הסינון ×וטומטית, ותהפוך ×ותה לנר×ית. + +/talkpost_do.bml.error.badpassword=נמסרה ×¡×¡×ž× ×©×’×•×™×” למשתמש ×–×”. ×× ×©×›×—×ª ×ת ססמתך, הינך יכול\×” להשיג ×ת ססמתך מחדש ×›×ן + +/talkpost_do.bml.error.badusername=×©× ×”×ž×©×ª×ž×© ×©×¦×™×™× ×ª× ×ינו ×§×™×™× ×‘- LiveJournal. ב××¤×©×¨×•×ª×›× ×œ×©×—×–×¨ ×ת ×©× ×”×ž×©×ª×ž×© ×©×œ×›× ×›×ן ×× ×©×›×—×ª× ×ותו. לחלופין, ב××¤×©×¨×•×ª×›× ×œ×”×’×™×‘ ×›"×למוני". + +/talkpost_do.bml.error.banned=×ין לך הרש×ת תגובה ביומן ×–×” + +/talkpost_do.bml.error.blankmessage=הודעתך ריקה. × × ×œ×”×§×œ×™×“ לפחות דבר-מה בשדה ההודעה + +/talkpost_do.bml.error.confused_identity=הזנת ×©× ×ž×©×ª×ž×©, ×ך בחרת להגיב ×‘×¢×™×œ×•× ×©× ×ו כמשתמש/ת המזוהה כרגע. × × ×œ×—×–×•×¨ לדף ×”×§×•×“× ×•×œ×”×—×œ×™×˜ מה ×‘×¢×¦× ×”×ª×›×•×•× ×ª לעשות מכל ×לה. + +/talkpost_do.bml.error.deleted=יומנך נמחק. ×œ× × ×™×ª×Ÿ להוסיף רישומי×. + +/talkpost_do.bml.error.friendsonly=רק ×—×‘×¨×™× ×©×œ [[user]] רש××™× ×œ×”×’×™×‘ ביומן ×–×”. + +/talkpost_do.bml.error.lostcookie=נר××” שעוגיית הזיהוי שלך נעלמה. + +/talkpost_do.bml.error.manybytes=מצטערי×, ×ך גודל התגובה שכתבת להודעה [[current]] עולה על מספר ×”×‘×ª×™× ×”×ž×•×ª×¨ לתגובות שנקבע ל- [[limit]]. ×× × ×—×–×•×¨ לתגובה שכתבת, קצר ×ותה, ונסה לשלוח ×ת התגובה שנית. + +/talkpost_do.bml.error.manychars=מצטערי×, ×ך גודל התגובה שכתבת להודעה [[current]] עולה על מספר ×”×ª×•×•×™× ×”×ž×•×ª×¨ לתגובות שנקבע ל- [[limit]]. ×× × ×—×–×•×¨ לתגובה שכתבת×, קצר ×ותה, ונסה לשלוח ×ת התגובה שנית. + +/talkpost_do.bml.error.mustlogin=עליך להיות מזוהה ×ו להזין ×©× ×ž×©×ª×ž×© וסיסמה כדי להשיב ×œ×¨×™×©×•× ×—×¡×•×™ ×–×”. + +/talkpost_do.bml.error.noanon=×œ× × ×™×ª×Ÿ להש×יר תגובות ×למוניות ביומן ×–×” + +/talkpost_do.bml.error.noauth=×ין לך הרש××” להגיב ×œ×¨×™×©×•× ×—×¡×•×™ ×–×”. + +/talkpost_do.bml.error.nocomments=×‘×¨×™×©×•× ×™×•×ž×Ÿ ×–×” בוטלה ×פשרות התגובה. + +/talkpost_do.bml.error.noparent=×œ× × ×™×ª×Ÿ להשיב לתגובה ש××™× ×” קיימת. + +/talkpost_do.bml.error.notafriend=מצטערי×, ×ך המשתמש [[user]] ×œ× ×›×•×œ×œ ×ותך ברשימת ×”×—×‘×¨×™× ×©×œ×•, ×•×”×•× ×§×‘×¢ ש"×—×‘×¨×™× ×‘×œ×‘×“" ×™×›×•×œ×™× ×œ×”×’×™×‘ ×œ×¨×™×©×•×ž×™× ×‘×™×•×ž× ×•. + +/talkpost_do.bml.error.nousername=×œ× ×”×–× ×ª ×ת ×©× ×”×ž×©×ª×ž×© שלך ב- LiveJournal. ב×פשרותך להגיב ×›"×למוני" ×× ×ין ברשותך חשבון ב- LiveJournal. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=×ž×¦×˜×¢×¨×™× ×ך ×œ× ×ª×•×›×œ להוסיף תגובות ×‘×™×•×ž× ×™× ×©×œ ×ž×©×ª×ž×©×™× ××—×¨×™× ×¢×“ ל×ימות כתובת הדו×ר ×”×לקטרוני שלך. ×× ×יבדת ×ת הודעת הדו×"ל ב×מצעותה תוכל לבצע פעולה זו, תוכל לבקש שההודעה תישלח ×ליך שוב מדף ×”×¤×¨×˜×™× ×”×בודי×. + +/talkpost_do.bml.error.postshared=×ין ×פשרות לכתוב תגובה ב×מצעות חשבון משותף ×ו קהילתי. חשבונות ×ž×©×•×ª×¤×™× ×ž×™×™×¦×’×™× ×§×‘×•×¦×•×ª של ×ž×©×ª×ž×©×™× ×•×œ× ×× ×©×™× ×‘×•×“×“×™×. + +/talkpost_do.bml.error.screened=×ין לך הרש××” להשיב לתגובה מסוננת זו. + +/talkpost_do.bml.error.suspended=יומנך הושעה. ×œ× × ×™×ª×Ÿ להוסיף רישומי×. + +/talkpost_do.bml.error.testacct=חשבונות בדיקות ×™×›×•×œ×™× ×œ×©×ž×© רק ביומני בדיקות + +/talkpost_do.bml.preview|staleness=1 +/talkpost_do.bml.preview=כך ייר××” רישומך. יש ללחוץ על הלחצן back בדפדפן על-מנת לערוך שינויי×, ×ו ל×שר ×ת הפרסו×. + +/talkpost_do.bml.preview.subject=נוש×: + +/talkpost_do.bml.preview.submit=×¤×¨×¡×•× + +/talkpost_do.bml.preview.title=תצוגה מקדימה + +/talkpost_do.bml.success.loggedin=זוהית בהצלחה. + +/talkpost_do.bml.success.message=תגובתך נרשמה. ניתן לר×ותה ×›×ן. + +/talkpost_do.bml.success.title=הצלחה + +/talkpost_do.bml.success.unscreened=בנוסף, התגובה המסוננת לה השבת הפכה בלתי-מסוננת, וניתן לצפות בה כעת. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=הוספת תגובה + +/talkread.bml.anonuser=(×למוני/ת) + +/talkread.bml.deletedpost=(הודעה שנמחקה) + +/talkread.bml.deleteduser=(משתמש שנמחק: [[username]]) + +/talkread.bml.fromip=(מהכתובת [[ip]]) + +/talkread.bml.noreplies=×ין תגובות + +/talkread.bml.nosubject=(×ין נוש×) + +/talkread.bml.replysuspended=(תשובה ממשתמש/ת מושעה/ית) + +/talkread.bml.screenedpost=(הודעה מסוננת) + +/talkread.bml.subjectdeleted=[נמחק] + +/talkread.bml.title=קרי×ת תגובות + +/talkscreen.bml.error.login=עליך להזדהות מול המערכת ×‘×˜×¨× ×™×”× ×‘×פשרותך לעבוד ×¢× ×ª×’×•×‘×•×ª מסוננות. + +/talkscreen.bml.error.privs.screen=×ין לך הרש××” לסנן תגובה זו. + +/talkscreen.bml.error.privs.unscreen=×ין לך הרש××” לבטל סינון תגובה זו. + +/talkscreen.bml.screen.doit=כן, סנן תגובה זו + +/talkscreen.bml.screen.sure.body=×”×× ×ת/×” בטוח/×” שברצונך לסנן תגובה זו? + +/talkscreen.bml.screen.sure.title=לסנן תגובה זו? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=התגובה סוננה. + +/talkscreen.bml.screened.title=הצלחה + +/talkscreen.bml.title=תגובה מסוננת + +/talkscreen.bml.unscreen.doit=כן, בטל סינון תגובה זו + +/talkscreen.bml.unscreen.sure.body=×”×× ×ת/×” בטוח/×” שברצונך לבטל סינון תגובה זו? + +/talkscreen.bml.unscreen.sure.title=לבטל סינון תגובה זו? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=התגובה בלתי-מסוננת עתה. + +/talkscreen.bml.unscreened.title=הצלחה + +/tools/memadd.bml.add_previous<< + + + + +. + +/tools/memadd.bml.body.added.body=רשימת הזכרונות שלך עודכנה + +/tools/memadd.bml.body.added.header=הצלחה + +/tools/memadd.bml.description=תי×ור: + +/tools/memadd.bml.description.text<< +× × ×œ×ª×ª ×œ×¨×™×©×•× ×™×•×ž×Ÿ ×–×” תי×ור שיסייע לך לזכור ×ותו. +על-מנת למחוק ×ת ×”×¨×™×©×•× ×”×–×” מרשימת זכרונותיך, × × ×œ×”×–×™×Ÿ תי×ור ריק. +. + +/tools/memadd.bml.error.deleted.body=×¨×™×©×•× ×”×™×•×ž×Ÿ שתו×ר עד עכשיו ×›-"[[desc]]" הוסר מרשימת זכרונותיך. + +/tools/memadd.bml.error.deleted.title=הזכרון נמחק + +/tools/memadd.bml.error.entry_deleted=×¨×™×©×•× ×™×•×ž×Ÿ ×–×” ×œ× ×§×™×™×. זיכרון נמחק. + +/tools/memadd.bml.error.fivekeywords=ניתן לציין עד 5 מילות מפתח/קטגוריות בלבד עבור כל ×¨×™×©×•× ×©×‘×¨×¦×•× ×š להוסיף לזכרונות. + +/tools/memadd.bml.error.invalid_security=×פשרות ביטחון חסרה ×ו פסולה. + +/tools/memadd.bml.error.login=הינך מוכרח\ת להיכנס כדי להשתמש ב×פשרות זו. היכנס\×™ ותוחזר\×™ לכ×ן. + +/tools/memadd.bml.error.maxsize=מילת מפתח זו עלתה על גודל ×”×ž×§×¡×™×ž×•× ×”×ž×•×¨×©×”: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +כדי להוסיף ×¨×™×©×•× ×™×•×ž×Ÿ לרשימת הזכרונות שלך, הינך זקוק\×” לספק תי×ור. +כדי למחוק זיכרון, הינך רש××™\ת לערוך ×ותו ולמחוק ×ת התי×ור, ×ך ×œ× ×”×™×” לך ×¨×™×©×•× ×–×” בזיכרונותיך. +. + +/tools/memadd.bml.error.nodescription.title=×ין תי×ור + +/tools/memadd.bml.form.reset=×יפוס + +/tools/memadd.bml.form.submit=שלח + +/tools/memadd.bml.keywords=מילות מפתח: + +/tools/memadd.bml.keywords.example=דוגמ×: מצחיק, חנוני, רומנטי + +/tools/memadd.bml.keywords.select=×ו, ניתן לבחור מילות מפתח שהשתמשת בהן בעבר: + +/tools/memadd.bml.keywords.text|staleness=2 +/tools/memadd.bml.keywords.text<< +מדוע ×¨×™×©×•× ×–×” ר×וי לזוכרו? +×¨×©×•× ×פס עד חמש מילות מפתח ×ו קטגוריות כדי שתוכל ×œ×ž×¦×•× ×–×ת ×©×•× ×ž×וחר יותר. +. + +/tools/memadd.bml.login.enterinfo=הקלד ×©× ×ž×©×ª×ž×© וסיסמה עבור החשבון בו ברצונך לשמור ×ת הזכרון. + +/tools/memadd.bml.login.forgot.header=שכחת משהו? + +/tools/memadd.bml.login.forgot.recover=×× ×©×›×—×ª ×ת ×©× ×”×ž×©×ª×ž×© שלך ×ו ×ת סיסמתך, ×”× ×ž×—×›×™× ×œ×š ×›×ן! + +/tools/memadd.bml.multiple_selections=לחץ על 'Control' ×›×שר הינך לוחץ על מילות המפתח כדי לבחור יותר ממלת מפתח ×חת. + +/tools/memadd.bml.security.friendsonly=×—×‘×¨×™× ×‘×œ×‘×“ + +/tools/memadd.bml.security.private=פרטי + +/tools/memadd.bml.security.public=ציבורי + +/tools/memadd.bml.title=הוסף לזיכרונות + +/tools/memadd.bml.title.added=נוסף + +/tools/memadd.bml.title.deleted=מחוק + +/tools/memadd.bml.title.edit_memory=עריכת ×¨×™×©×•× ×—×©×•×‘ + +/tools/memadd.bml.whocansee<< +מי רש××™ לר×ות שסימנת ×¨×™×©×•× ×–×” כחשוב? +כל ×חד, רק מי שברשימת ×”×—×‘×¨×™× ×©×œ×š, ×ו רק ×ת\×”? +. + +/tools/memories.bml.back=חזרה + +/tools/memories.bml.body.keyword<< + +[[user]] כלל כחשובי×.. p?> +. + +/tools/memories.bml.body.list_categories<< + + +[[user]] הכניס ×‘×ª×•×›× ×¨×™×©×•×ž×™ יומן חשובי×.p?> +. + +/tools/memories.bml.body.memorable=להלן רשימת רישומי יומן ×œ× ×‘×ª×•×š קטגוריה שמשתמש [[user]] מצ×\×” חשובי×. + +/tools/memories.bml.edit=עריכה + +/tools/memories.bml.error.noentries.body|staleness=2 +/tools/memories.bml.error.noentries.body<< +ייתכן שזה בגלל + 1) המשתמש ×ינו הגדיר ×©×•× ×ž×ורע חשוב, + 2) ×¨×™×©×•×ž×™× ×—×©×•×‘×™× ×©×œ המשתמש ×ž×•×’× ×™× ×•×ין לך גישה לר×ות×, ×ו + 3) ×ין למשתמש ×¨×™×©×•×ž×™× ×—×©×•×‘×™× ×©×ž×ª××™×ž×™× ×œ×§×¨×™×˜×¨×™×•× ×™× ×©×œ×š. +. + +/tools/memories.bml.error.noentries.title=×œ× × ×ž×¦×ו זכרונות + +/tools/memories.bml.filter.all=כל הזכרונות + +/tools/memories.bml.filter.other=רק ×¨×™×©×•×ž×™× ××—×¨×™× + +/tools/memories.bml.filter.own=רק ×¨×™×©×•×ž×™× ×©×œ '[[user]]'. + +/tools/memories.bml.form.switch=החלפה + +/tools/memories.bml.title.keyword=×¨×™×©×•×ž×™× [[keyword]] ×—×©×•×‘×™× + +/tools/memories.bml.title.memorable=×¨×™×©×•×ž×™× ×—×©×•×‘×™× + +/tools/memories.bml.uncategorized=בלתי-מסווג + +/update.bml.altpost=להוסיף ביומן: + +/update.bml.btn.update=עדכון היומן + +/update.bml.currmood=מצב-רוח נוכחי: + +/update.bml.currmusic=מוסיקה נוכחית: + +/update.bml.date=ת×ריך: + +/update.bml.default=ברירת מחדל + +/update.bml.defaultjournal=([[user]]) -- ברירת מחדל + +/update.bml.error.login=שגי××” בהזדהות מול המערכת: + +/update.bml.error.update=שגי××” בעת עדכון היומן: + +/update.bml.event=×ירוע: + +/update.bml.full=דף עדכון ×ž×œ× + +/update.bml.localtime=זמן מקומי: + +/update.bml.loggingin=מזדהה מול המערכת... + +/update.bml.noneother=×ין, ×ו ×חר: + +/update.bml.opt.backdate=תי×רוך ×”×¨×™×©×•× ×œ×חור: + +/update.bml.opt.backdate.about=×œ× ×™×•×¦×’ בדף תצוגת ×—×‘×¨×™× + +/update.bml.opt.nocomments=בטל ×פשרות לתגובות: + +/update.bml.opt.noemail=×ל תשלח תגובות בדו×ל: + +/update.bml.opt.noformat=×ל תעצב ×וטומטית: + +/update.bml.opt.spellcheck=בדוק ×יות ×‘×¨×™×©×•× ×œ×¤× ×™ פרסומו + +/update.bml.other=×חר: + +/update.bml.picture=תמונה ×œ×¨×™×©×•× ×–×”: + +/update.bml.security.custom=מות×× ×ישית... + +/update.bml.security.friends=×—×‘×¨×™× + +/update.bml.security.head=רמת ×בטחה: + +/update.bml.security.private=פרטי + +/update.bml.security.public=ציבורי + +/update.bml.servermsg=בנוסף, יש לשרת הודעה עבורך: + +/update.bml.simple=לפניך הדף הפשוט. ×פשרויות נוספות ניתן ×œ×ž×¦×•× ×›×ן. + +/update.bml.spellchecked=רישומך ל×חר בדיקת ×יות: + +/update.bml.subject|staleness=1 +/update.bml.subject=נוש×: (×œ× ×—×•×‘×”; לשימוש ×‘×¨×™×©×•×ž×™× ×רוכי×) + +/update.bml.timeformat=זמן בפורמט 24 שעות + +/update.bml.title=עדכון היומן + +/update.bml.title.readonly=מצב קרי××” בלבד + +/update.bml.update.head=עדכון היומן שלך... + +/update.bml.update.success|staleness=1 +/update.bml.update.success=העדכון ×”×•×©×œ× ×‘×”×¦×œ×—×”. ניתן לעיין ביומנך המעודכן ×›×ן. + +/update.bml.updating=מעדכן ×ת היומן... + +/userinfo.bml.about.comm|staleness=1 +/userinfo.bml.about.comm=על ×ודות + +/userinfo.bml.about.user|staleness=1 +/userinfo.bml.about.user=ביוגרפיה + +/userinfo.bml.body.leave=ב×פשרותך לעזוב ×ת הקהילה בכל עת. + +/userinfo.bml.comminfo.body=להלן ×¤×¨×˜×™× ×¢×œ ×ודות הקהילה "[[commname]]". + +/userinfo.bml.comminfo.name=פרטי קהילה + +/userinfo.bml.date.never=××£ ×¤×¢× + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=×©× ×ž×©×ª×ž×© ×œ× ×ª×§×™×Ÿ + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=×¦×•×¤×™× ×‘×§×”×™×œ×”: + +/userinfo.bml.friendof.hidden=(מוסתר) + +/userinfo.bml.friendof.syndreadcount=מספר קור××™× + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=חבר/×” של: + +/userinfo.bml.friends.comm=חברי הקהילה + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=×—×‘×¨×™× + +/userinfo.bml.label.addbuddy=הוספת חבר + +/userinfo.bml.label.adduser=הוספת משתמש + +/userinfo.bml.label.birthdate=ת×ריך לידה: + +/userinfo.bml.label.clientsused=תוכנות משתמש שהופעלו ××™-פע×: + +/userinfo.bml.label.comments=תגובות: + +/userinfo.bml.label.composted=נכתבו: [[num]] - + +/userinfo.bml.label.comreceived=נתקבלו: [[num]] + +/userinfo.bml.label.datecreated=ת×ריך יצירה: + +/userinfo.bml.label.dateupdated=ת×ריך עדכון: + +/userinfo.bml.label.interests=תחומי ענין + +/userinfo.bml.label.intsnotshown=...[[intnotshown]] תחומי ענין ×œ× ×ž×•×¦×’×™× + +/userinfo.bml.label.journalentrs=רישומי יומן: + +/userinfo.bml.label.location=מיקו×: + +/userinfo.bml.label.memberof=חבר/×” בקהילות: + +/userinfo.bml.label.memories=זכרונות: + +/userinfo.bml.label.moredetails=(×¤×¨×˜×™× × ×•×¡×¤×™×...) + +/userinfo.bml.label.msnusername=×©× ×ž×©×ª×ž×© ב-MSN + +/userinfo.bml.label.name=ש×: + +/userinfo.bml.label.nofriends=×ין ×—×‘×¨×™× ×¨×©×•×ž×™× + +/userinfo.bml.label.reqfinduser=רק ×ž×©×ª×ž×©×™× ×‘×¢×œ×™ ההרש××” 'finduser' רש××™× ×œ×תר ×ž×©×ª×ž×©×™× ×œ×¤×™ userid. + +/userinfo.bml.label.sendmessage=שליחת הודעה + +/userinfo.bml.label.shared=רש××™× ×œ×”×•×¡×™×£ רישומי×: + +/userinfo.bml.label.supportpoints=נקודות תמיכה: + +/userinfo.bml.label.syndicatedfrom=בסינדיקציה מ: + +/userinfo.bml.label.syndicatedstatus=מצב סינדיקציה: + +/userinfo.bml.label.textmessage=הודעת
        טקסט
        : + +/userinfo.bml.label.todo=רשימת מטלות: + +/userinfo.bml.label.user=×©× ×ž×©×ª×ž×©: + +/userinfo.bml.label.viewfriends=הצגת ×—×‘×¨×™× + +/userinfo.bml.label.viewmembers=הצגת חברי קהילה + +/userinfo.bml.label.website=×תר ×ו דף בית: + +/userinfo.bml.label.yahooid=זהות Yahoo! + +/userinfo.bml.membership.body=על-מנת להצטרף לקהילה זו, יש ללחוץ ×›×ן. + +/userinfo.bml.memories.entries=[[count]] ×¨×™×©×•×ž×™× + +/userinfo.bml.memories.entry=[[count]] ×¨×™×©×•× + +/userinfo.bml.monitor.comm=צפייה בקהילה + +/userinfo.bml.monitor.user=הוספת משתמש ×–×” לרשימת חבריך + +/userinfo.bml.nonexist.body=×ין משתמש ×‘×©× [[user]] במערכת. + +/userinfo.bml.nonexist.name=משתמש ×œ× ×ž×•×›×¨ + +/userinfo.bml.tellafriend=ספר/×™ לחבר/×”! + +/userinfo.bml.title=פרטי משתמש + +/userinfo.bml.title.communityinfo=פרטי קהילה + +/userinfo.bml.userinfo.name=פרטי משתמש + +BML.parse_multipart.parse=שגי××” בטיפול בקובץ שהעלית + +BML.parse_multipart.toolarge=הקובץ שהועלה גדול מדי + +BML.parse_multipart.unknowntype=סוג ×œ× ×ž×•×›×¨ של תוכן + +btn.search=חיפוש + +date.day.thursday.short=×” + +date.day.tuesday.long=שלישי + +date.day.tuesday.short=×’ + +date.day.wednesday.long=רביעי + +date.day.wednesday.short=ד + +date.month.april.long=×פריל + +date.month.april.short=×פר + +date.month.august.long=×וגוסט + +date.month.august.short=×וג + +date.month.december.long=דצמבר + +date.month.december.short=דצמ + +date.month.february.long=פברו×ר + +date.month.february.short=פבר + +date.month.january.long=ינו×ר + +date.month.january.short=ינו + +date.month.july.long=יולי + +date.month.july.short=יול + +date.month.june.long=יוני + +date.month.june.short=יונ + +date.month.march.long=מרץ + +date.month.march.short=מרץ + +date.month.may.long=מ××™ + +date.month.may.short=מ××™ + +date.month.november.long=נובמבר + +date.month.november.short=נוב + +date.month.october.long=×וקטובר + +date.month.october.short=×וק + +date.month.september.long=ספטמבר + +date.month.september.short=ספט + +dystopia.btn.login=כניסה + +dystopia.hello_anonymous=×‘×¨×•×›×™× ×”×‘××™× ×œ- LiveJournal + +dystopia.hello_loggedin=שלו×, [[username]]! + +dystopia.nav.createjournal=יצירת יומן + +dystopia.nav.developer=×זור ×œ×ž×ª×›× ×ª×™× + +dystopia.nav.download=הורדה + +dystopia.nav.editentries=עריכת ×¨×™×©×•×ž×™× + +dystopia.nav.editfriends=חבריך + +dystopia.nav.editpassword=סיסמתך + +dystopia.nav.editpics=תמונותיך + +dystopia.nav.editstyle=עריכת סגנון + +dystopia.nav.faq=ש×לות נפוצות + +dystopia.nav.findcomm=לפי קהילה + +dystopia.nav.finddir=חיפוש במדריך + +dystopia.nav.findint=לפי ×ª×—×•× ×¢× ×™×Ÿ + +dystopia.nav.findrandom=ב×קר××™ + +dystopia.nav.findregion=לפי ×יזור + +dystopia.nav.home=דף הבית + +dystopia.nav.journalcalendar=לוח שנה + +dystopia.nav.journalfriends=×—×‘×¨×™× + +dystopia.nav.journalinfo=פרטי משתמש + +dystopia.nav.journalrecent=×¨×™×©×•×ž×™× ××—×¨×•× ×™× + +dystopia.nav.legalcoppa=חוק COPPA ×”×מריקני + +dystopia.nav.legalprivacy=פרטיות + +dystopia.nav.legaltos=תנ××™ שימוש + +dystopia.nav.login=כניסה + +dystopia.nav.logout=יצי××” + +dystopia.nav.lostinfo=סיסמתי ×בדה + +dystopia.nav.memories=זכרונות + +dystopia.nav.modifyjournal=עיצוב יומן + +dystopia.nav.news=חדשות + +dystopia.nav.paidaccts=חשבונות ×‘×ª×©×œ×•× + +dystopia.nav.paymentarea=×יזור ×ª×©×œ×•× + +dystopia.nav.personalinfo=×¤×¨×˜×™× ××™×©×™×™× + +dystopia.nav.support=יש לך ש×לה? + +dystopia.nav.updatejournal=עדכון היומן + +dystopia.navhead.findusers=מצי×ת ×ž×©×ª×ž×©×™× + +dystopia.navhead.help=עזרה ותמיכה + +dystopia.navhead.journal=יומנך + +dystopia.navhead.legal=×”×ª×—×•× ×”×ž×©×¤×˜×™ + +dystopia.navhead.settings=הגדרותיך + +dystopia.navhead.welcome=ברוכ/×” הב×/×”! + +dystopia.search.icq=מספר ICQ + +dystopia.search.int=×ª×—×•× ×¢× ×™×™×Ÿ + +dystopia.search.region=×יזור + +dystopia.searchlj=חיפוש ב- LiveJournal + +Email=דו×ר ×לקטרוני + +Error|notes=typically used inside an H1 tag to announce an error. +Error=שגי××” + +error.badpassword=סיסמה שגויה + +error.dberror=×ירעה שגי××” במסד הנתוני×: + +error.deleted.name=מחוק + +error.deleted.text=יומן ×–×” נמחק. ×× ×ת/×” [[user]], לרשותך 30 ×™×ž×™× ×ž×ž×—×™×§×ª היומן לחזור בך ממחיקתו. ל×חר 30 ×™×ž×™× × ×ž×—×•×§ לצמיתות ×ת כל תוכן היומן מהשרת שלנו. + +error.deleted.title=חשבון מחוק + +error.nobutton=×œ× × ×œ×—×¥ כפתור? + +error.nodb=מסד ×”× ×ª×•× ×™× ×ינו נגיש ב×ופן זמני + +error.nodbmaintenance=חלק ×–×” במסד ×”× ×ª×•× ×™× ×¢×•×‘×¨ טיפול כרגע, ו×ינו זמין. × × ×œ× ×¡×•×ª שוב בעוד מספר דקות. + +error.noentry=×¨×™×©×•× ×–×” ×ינו קיי×. + +error.nojournal=LiveJournal ×œ× ×™×“×•×¢ + +error.procrequest=×ירעה שגי××” תוך כדי טיפול בבקשתך: + +error.purged.name=מחוק + +error.purged.text=יומן ×–×” בוטל ונמחק. + +error.purged.title=חשבון מחוק + +error.suspended.name=מושעה + +error.suspended.text|staleness=2 +error.suspended.text=יומן ×–×” הושעה זמנית ×ו תמידית ×¢"×™ צוות [[sitename]] בגין עבירה על מדיניות המערכת. ×× ×”× ×š [[user]], × × ×œ×™×¦×•×¨ עמנו קשר לקבלת ×¤×¨×˜×™× × ×•×¡×¤×™×. + +error.suspended.title=חשבון מושעה + +error.tempdisabled=יומן ×–×” ×œ× ×¤×¢×™×œ זמנית + +error.unknownmode=מצב ×œ× ×™×“×•×¢. + +error.usernameinvalid=×©× ×”×ž×©×ª×ž×© מכיל ×ª×•×™× ×œ× ×§×‘×™×œ×™× + +error.usernamelong=×©× ×”×ž×©×ª×ž×© ×רוך מדי. 15 ×ª×•×™× ×œ×›×œ היותר. + +error.username_notfound=×©× ×ž×©×ª×ž×© ×œ× × ×ž×¦× + +Help=עזרה + +label.security.friends=×—×‘×¨×™× + +label.security.head=רמת ×בטחה: + +label.security.private=פרטי + +label.security.public=ציבורי + +label.switch.button=החלפה + +label.switch.header=החלפת יומן פעיל + +label.switch.workwith=עבודה ×¢× ×™×•×ž×Ÿ: + +langname.be=בלרוסית + +langname.da=דנית + +langname.de=גרמנית + +langname.en=×נגלית + +langname.en_GB=×נגלית בריטית + +langname.en_LJ=×נגלית + +langname.eo=×ספרנטו + +langname.es=ספרדית + +langname.et=×סטונית + +langname.fi=פינית + +langname.fr=צרפתית + +langname.ga=×ירית + +langname.gd=גיילית + +langname.he=עברית + +langname.hu=הונגרית + +langname.is=×יסלנדית + +langname.it=×יטלקית + +langname.ja=יפנית + +langname.la=לטינית + +langname.lv=ל×טבית + +langname.ms=מל×ית + +langname.nb=נורבגית בוקמול + +langname.nl=הולנדית + +langname.nn=נורבגית נונורסק + +langname.pl=פולנית + +langname.pt=פורטוגזית + +langname.ru=רוסית + +langname.sv=שוודית + +langname.tr=טורקית + +langname.zh=סינית מפושטת + +lostinfo.head=שכחת משהו? + +lostinfo.text=×× ×©×›×—×ª ×ת ×©× ×”×ž×©×ª×ž×© שלך ×ו ×ת סיסמתך, ×”× ×ž×—×›×™× ×œ×š ×›×ן. + +Password=סיסמה + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=סליחה + +talk.anonwrote=×למוני/ת כתב/×”, + +talk.anonwrote_comm=×למוני/ת כתב/×” ב-[[commlink]], + +talk.commentpermlink=קישור + +talk.commentpost=הוספת תגובה + +talk.commentsread=קרי×ת תגובות + +talk.curname_Mood=מצב-רוח נוכחי: + +talk.curname_Music=מוסיקה נוכחית: + +talk.error.bogusargs=××¨×’×•×ž× ×˜×™× ×‘×“×•×™×™× + +talk.error.comm_deleted=תגובה זו נמחקה. + +talk.error.deleted=יומן ×–×” נמחק. + +talk.error.deleted.title=מחוק + +talk.error.mustlogin=עליך להזדהות מול המערכת כדי ×œ×§×¨×•× ×¨×™×©×•× ×—×¡×•×™ ×–×”. + +talk.error.nocomment=תגובה זו ××™× ×” קיימת. + +talk.error.noentry=×ין ×¨×™×©×•× ×›×–×”. + +talk.error.nojournal=שגי××”: ×œ× × ×™×ª×Ÿ לזהות ×ת היומן מתוך ×”××¨×’×•×ž× ×˜×™× + +talk.error.nosuchjournal=×ין יומן ×›×–×” + +talk.error.notauthorised=×ין לך הרש××” ×œ×§×¨×•× ×¨×™×©×•× ×—×¡×•×™ ×–×”. + +talk.error.suspended=יומן ×–×”, ×ו מחבר/ת התגובה, ×ž×•×©×¢×™× + +talk.error.suspended.title=מושעה + +talk.parentlink=הורה + +talk.readsimilar=קרי×ת רישומי יומן דומי×: + +talk.replytothis=השבה לטקסט ×–×” + +talk.somebodywrote=[[realname]] ([[userlink]]) כתב/×”, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) כתב/×” ב- [[commlink]], + +talk.threadlink=פתיל ×–×” + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_hebrew + +Username=×©× ×ž×©×ª×ž×© + diff --git a/ljcom/bin/upgrading/hi.dat b/ljcom/bin/upgrading/hi.dat new file mode 100644 index 0000000..4d8ac51 --- /dev/null +++ b/ljcom/bin/upgrading/hi.dat @@ -0,0 +1,1107 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=यही वह जगह है जहाठपर आप लेखा रदà¥à¤¦ कर सकते हैं या रदà¥à¤¦ लेखा वापिस ला सकते हैं। किसी लेखा रदà¥à¤¦ करने के बाद 30 दिन के अनà¥à¤¦à¤° अनà¥à¤¦à¤° ही आप उसे वापस ला सकते हैं। 30 दिन के बाद लेखा पà¥à¤°à¤£à¤¾à¤²à¥€ से पूरी तरह गायब हो जाà¤à¤—ा, और किसी भी तरीके से वापिस न आ पाà¤à¤—ा। + +/accountstatus.bml.journalstatus.head=लेखा सकà¥à¤°à¤¿à¤¯à¤¨ सà¥à¤¥à¤¿à¤¤à¤¿ + +/accountstatus.bml.journalstatus.select.activated=सकà¥à¤°à¤¿à¤¯ + +/accountstatus.bml.journalstatus.select.deleted=रदà¥à¤¦ + +/accountstatus.bml.journalstatus.select.head=सà¥à¤¥à¤¿à¤¤à¤¿: + +/accountstatus.bml.journalstatus.select.suspended=लमà¥à¤¬à¤¿à¤¤ + +/accountstatus.bml.title=खाते की सà¥à¤¥à¤¿à¤¤à¤¿ + +/allpics.bml.current=मौजूदा छवियाठ+ +/allpics.bml.default=मूल + +/allpics.bml.edit2=आप अपने चितà¥à¤° के कà¥à¤žà¥à¤œà¥€à¤¶à¤¬à¥à¤¦ समà¥à¤ªà¤¾à¤¦à¤¿à¤¤ कर सकते हैं या नया चितà¥à¤° चढ़ा सकते हैं। + +/allpics.bml.error.noparam=आपको पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ का कोई मान पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करना होगा। + +/allpics.bml.keywords=कà¥à¤žà¥à¤œà¥€à¤¶à¤¬à¥à¤¦: + +/allpics.bml.nopics.text.other=इस पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ ने कोई छवियाठनहीं चढ़ाई हैं। + +/allpics.bml.nopics.text2=आपने कोई छवियाठनहीं चढ़ाई हैं। चढ़ाने के लिठयहाठजाà¤à¤à¥¤ + +/allpics.bml.nopics.title=कोई छवियाठनहीं + +/allpics.bml.pics=[[user]] की पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ छवियाठयहाठहैं। + +/allpics.bml.title=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ छवियाठ+ +/changepassword.bml.btn.proceed=आगे बढ़ें + +/changepassword.bml.changepassword.header=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ बदलें + +/changepassword.bml.changepassword.instructions=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ बदलने के लिठनिमà¥à¤¨à¥‹à¤•à¥à¤¤ परà¥à¤šà¤¾ भरें। अचà¥à¤›à¤¾ पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ चà¥à¤¨à¤¨à¥‡ और अपने खाते को सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ रखेन के बारे में जानकारी के लिठइस सवाल जवाब को देखें। + +/changepassword.bml.email.body<< +[[sitename]] में आपका पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ परिवरà¥à¤¤à¤¿à¤¤ कर दिया गया है। + +भविषà¥à¤¯ में गà¥à¤® हो जाने पर इसे पà¥à¤°à¤¾à¤ªà¥à¤¤ करने के लिठ+ +[[siteroot]]/lostinfo.bml + +पर जाà¤à¤ + +सविनय, + +[[sitename]] दल + +[[siteroot]] +. + +/changepassword.bml.email.subject=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ परिवरà¥à¤¤à¤¨ + +/changepassword.bml.error.badcheck=नया पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ अनà¥à¤šà¤¿à¤¤: [[error]] + +/changepassword.bml.error.badnewpassword=नठपà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ की पà¥à¤·à¥à¤Ÿà¤¿ के लिठपà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿, पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ से मेल नहीं खाती। समà¥à¤­à¤µ है टङà¥à¤•à¤¨ में कोई तà¥à¤°à¥à¤Ÿà¤¿ हो। कृपया नठपà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ को पà¥à¤¨à¤ƒ टङà¥à¤•à¤¿à¤• करें और पà¥à¤¨à¤ƒ पà¥à¤·à¥à¤Ÿà¤¿ करें। + +/changepassword.bml.error.badoldpassword=आपका पà¥à¤°à¤¾à¤¨à¤¾ पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ सही नहीं है। + +/changepassword.bml.error.blankpassword=आपका नया पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ खाली नहीं हो सकता। + +/changepassword.bml.error.changetestaccount=परीकà¥à¤·à¤£ खाते का पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ परिवरà¥à¤¤à¤¨ निषिदà¥à¤§ है। + +/changepassword.bml.error.characterlimit=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ 30 अकà¥à¤·à¤° से कम के ही हो सकते हैं। + +/changepassword.bml.error.invaliduser=अवैध पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ [[user]]। यह पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ मौजूद नहीं है। कà¥à¤¯à¤¾ आपने सही टङà¥à¤•à¤¨ किया है? + +/changepassword.bml.error.mustenterusername=अपना पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/changepassword.bml.error.nonascii=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ में केवल à¤à¤¸à¥à¤•à¥€ अकà¥à¤·à¤° हो सकते हैं। कृपया à¤à¤¸à¤¾ पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ चà¥à¤¨à¥‡à¤‚ जिसमें à¤à¤¸à¥à¤•à¥€ के अलावा अनà¥à¤¯ अकà¥à¤·à¤° न हों। + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=अपने मौजूदा वैपतà¥à¤°à¤¿à¤• पते की पà¥à¤·à¥à¤Ÿà¤¿ होने के बाद ही आप अपना पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ बदल पाà¤à¤à¤—े। + +/changepassword.bml.newpassword=नया पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦: + +/changepassword.bml.newpasswordagain=नया पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ (पà¥à¤¨à¤ƒ): + +/changepassword.bml.oldpassword=पà¥à¤°à¤¾à¤¨à¤¾ पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦: + +/changepassword.bml.proceed.instructions=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ बदलने के लिठनीचे दी कà¥à¤žà¥à¤œà¥€ दबाà¤à¤à¥¤ आपको पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ परिवरà¥à¤¤à¤¨ समà¥à¤¬à¤¨à¥à¤§à¥€ डाक मिलेगी। + +/changepassword.bml.success.text=आपका पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ परिवरà¥à¤¤à¤¿à¤¤ हो चà¥à¤•à¤¾ है, तथा आपको इससे समà¥à¤¬à¤¨à¥à¤§à¤¿à¤¤ डाक भी भेजी जा चà¥à¤•à¥€ है। + +/changepassword.bml.title=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ बदलें + +/community/index.bml.main<< + + + + +'नौसिखियों' की बैठक में जाà¤à¤, जहाठआपको अपने कई सवालों के जवाब मिलेंगे। , में जाà¤à¤, थोड़ी खोज करें, और कà¥à¤› ही समय में आप अभà¥à¤¯à¤¸à¥à¤¤ हो जाà¤à¤à¤—े! +p?> + + +
        + को अपने मितà¥à¤° पृषà¥à¤ à¥‹à¤‚ में जोड़ें, ताकि पूरà¥à¤£ लाइवà¥à¤œà¤°à¥à¤¨à¤² समà¥à¤¦à¤¾à¤¯ से समà¥à¤¬à¤¦à¥à¤§ मà¥à¤¦à¥à¤¦à¥‹à¤‚ और समारोहों की आपको पूरी जानकारी रहे।
        + को अपने मितà¥à¤° पृषà¥à¤ à¥‹à¤‚ में जोड़ें, ताकि आपको पता रहे कि यह सेवा मरमà¥à¤®à¤¤ आदि के लिठबनà¥à¤¦ रहेगी, साथ ही आपको इस सेवा की अपà¥à¤¨à¤°à¥à¤¨à¤¿à¤¯à¥‹à¤œà¤¿à¤¤ रà¥à¤•à¤¾à¤µà¤Ÿà¥‹à¤‚ का लेखा जोखा भी मिलता रहेगा। +p?> + + +à¤à¤®, आईसीकà¥à¤¯à¥‚, याहू!, à¤à¤® à¤à¤¸ à¤à¤¨, या जॅबर जैसे लोकपà¥à¤°à¤¿à¤¯ दà¥à¤°à¥à¤¤ सनà¥à¤¦à¥‡à¤¶à¤µà¤¾à¤¹à¤•à¥‹à¤‚ का पà¥à¤°à¤¯à¥‹à¤— करते हैं। यदि आप भी करते हों, तो अपनी + वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त जानकारी जमाव इसे उलà¥à¤²à¤¿à¤–ित करना न भूलें। यदि आपका शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ खाता है, तो आप अपने सॅल फ़ोन या पेजर पर पाठà¥à¤¯ सनà¥à¤¦à¥‡à¤¶ पà¥à¤°à¤¾à¤ªà¥à¤¤ करने की सà¥à¤µà¤¿à¤§à¤¾ भी लागू कर सकते हैं। +p?> + + +शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ खाता लेना। हाठइसके अलावा, और भी कई तरीके हैं सहायता करने के। +

        +लाइवà¥à¤œà¤°à¥à¤¨à¤² मà¥à¤•à¥à¤¤ सà¥à¤°à¥‹à¤¤ परियोजना है; यदि आपको पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤®à¤¿à¤™à¥à¤— भाषाओं या सेवक à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨à¥‹à¤‚ का अनà¥à¤­à¤µ है तो लाइवà¥à¤œà¤°à¥à¤¨à¤² निरà¥à¤®à¤¾à¤£ समà¥à¤¦à¤¾à¤¯, पर à¤à¤• नज़र डालें। यदि आपके पास कोई सà¥à¤à¤¾à¤µ है, लाइवà¥à¤œà¤°à¥à¤¨à¤² को सà¥à¤§à¤¾à¤°à¤¨à¥‡ के लिà¤, तो लाइवà¥à¤œà¤°à¥à¤¨à¤² सà¥à¤à¤¾à¤µ कà¥à¤·à¥‡à¤¤à¥à¤° को देखें। यदि आप किसी भी चीज़ के बारे में मदद करना चाहते हैं, तो लाइवà¥à¤œà¤°à¥à¤¨à¤² वà¥à¤¯à¤µà¤¸à¤¾à¤¯ सà¥à¤®à¤¦à¤¾à¤¯, को देखें। +यदि आपको लोगों की मदद करना अचà¥à¤›à¤¾ लगता है, तो हमारे तकनीकी सहायता केनà¥à¤¦à¥à¤° में जा कर किसी की मदद करें। यदि आपकी चैतà¥à¤°à¤¿à¤• कला में अभिरà¥à¤šà¤¿ है, तो लाइवà¥à¤œà¤°à¥à¤¨à¤² कला समà¥à¤¦à¤¾à¤¯, पर à¤à¤• नज़र डालें। +p?> + + +à¤à¤¨à¤¿à¤® से ले के ज़ॅन बौदà¥à¤§à¥‹à¤‚ , तक, खगोलशासà¥à¤¤à¥à¤° से ज़िम तक फैले हà¥à¤ हैं। +आपको दà¥à¤¨à¤¿à¤¯à¤¾ भर के हर कà¥à¤·à¥‡à¤¤à¥à¤° के कà¥à¤·à¥‡à¤¤à¥à¤°à¥€à¤¯ समà¥à¤¦à¤¾à¤¯ भी मिलेंगे। समà¥à¤­à¤µ है कि आपके निवास सà¥à¤¥à¤¾à¤¨ से समà¥à¤¬à¤¨à¥à¤§à¤¿à¤¤ समà¥à¤¦à¤¾à¤¯ भी यहाठमौजूद हो! +p?> + + +सवाल जवाब +आपको इस काम में मदद करेगा। साथ ही दो और तरह के सवाल जवाब हैं, (आम समà¥à¤¦à¤¾à¤¯ समà¥à¤¬à¤¨à¥à¤§à¥€ सवाल जवाब व समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ समà¥à¤¬à¤¨à¥à¤§à¥€ सवाल जवाब) जिनमें सभी जानकारी उपलबà¥à¤§ है। यदि आपको फिर भी और जानकारी की ज़रूरत महसूस होती है, तो सहायता अनà¥à¤°à¥‹à¤§ जमा करने से न हिचकें। +p?> + + + + +
          +
        • समà¥à¤¦à¤¾à¤¯ खोज
        • +
        • विजà¥à¤žà¤¾à¤ªà¤¨ समà¥à¤¦à¤¾à¤¯ को देखें()
        • +
        • खोज समà¥à¤¦à¤¾à¤¯ में खोजें ()
        • +
        + + +समà¥à¤¦à¤¾à¤¯ निरà¥à¤¦à¥‡à¤¶à¤•, जॅसी पà¥à¤°à¥‰à¤²à¥à¤•à¥à¤¸, () को लिखें। +p?> +. + +/community/index.bml.title=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• केनà¥à¤¦à¥à¤° + +/community/join.bml.button.join=समà¥à¤¦à¤¾à¤¯ के सदसà¥à¤¯ बनें + +/community/join.bml.label.addtofriends="[[maintainer]]" को मितà¥à¤° सूची में जोड़ें + +/community/join.bml.label.allowposting=यह समà¥à¤¦à¤¾à¤¯ सभी सदसà¥à¤¯à¥‹à¤‚ को लिखने की अनà¥à¤®à¤¤à¤¿ देता है, अतः अब आप यहाठपर लिख सकते हैं। यदि आपके सङà¥à¤—णक पर पहले से ही लाइवà¥à¤œà¤°à¥à¤¨à¤² गà¥à¤°à¤¾à¤¹à¤• खà¥à¤²à¤¾ हà¥à¤† है, तो आपको बहिरà¥à¤—मन करके पà¥à¤¨à¤ƒ पà¥à¤°à¤µà¥‡à¤¶ करना होगा, तभी यह लेखा आपके लेखनीय लेखों की सूची में पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ होगा। + +/community/join.bml.label.auth=हालाà¤à¤•à¤¿ आप अब इस समà¥à¤¦à¤¾à¤¯ के सदसà¥à¤¯ हैं, केवल अधिकृत पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ ही यहाठपर लेख लिख सकते हैं। यदि आप लेखन की अनà¥à¤®à¤¤à¤¿ चाहते हैं तो किसी भी पà¥à¤°à¤¶à¤¾à¤¸à¤• को लिखें। इस समà¥à¤¦à¤¾à¤¯ के पà¥à¤°à¤¶à¤¾à¤¸à¤•à¥‹à¤‚ की सूची निमà¥à¤¨à¥‹à¤•à¥à¤¤ है: [[admins]] + +/community/join.bml.label.banned=इस समà¥à¤¦à¤¾à¤¯ के पà¥à¤°à¤¶à¤¾à¤¸à¤•à¥‹à¤‚ नें आपको सदसà¥à¤¯ बनने से अवरोधित किया हà¥à¤† है। + +/community/join.bml.label.closed=यह समà¥à¤¦à¤¾à¤¯ बनà¥à¤¦ है। यदि आप इसके सदसà¥à¤¯ बनना चाहते हैं तो कृपया इसके किसी पà¥à¤°à¤¶à¤¾à¤¸à¤• से समà¥à¤ªà¤°à¥à¤• करें। पà¥à¤°à¤¶à¤¾à¤¸à¤•à¥‹à¤‚ की सूची निमà¥à¤¨à¥‹à¤•à¥à¤¤ है: [[admins]] + +/community/join.bml.label.commlogged=आपका मौजूदा पà¥à¤°à¤µà¥‡à¤¶ साà¤à¤à¤¾/सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाते के तौर पर है, वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त खाते के तौर पर नहीं। + +/community/join.bml.label.errorcomminfo=पà¥à¤°à¤¦à¤¤à¥à¤¤ सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जानकारी अवैध है। + +/community/join.bml.label.expls="[[maintainer]]" समà¥à¤¦à¤¾à¤¯ में शामिल होने के लिठनिमà¥à¤¨à¥‹à¤•à¥à¤¤ कà¥à¤žà¥à¤œà¥€ दबाà¤à¤à¥¤ यदि आप शामिल होने के बाद समà¥à¤¦à¤¾à¤¯ की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ अपने मितà¥à¤° पृषà¥à¤  पर नहीं देखना चाहते तो नीचे दिठबकà¥à¤¸à¥‡ से सही का निशान हटा दें। + +/community/join.bml.label.loginfirst=किसी समà¥à¤¦à¤¾à¤¯ में शामिल होने के पहले आपको पà¥à¤°à¤µà¥‡à¤¶ करना होगा। + +/community/join.bml.label.membernow=अब आप [[commname]] समà¥à¤¦à¤¾à¤¯ के सदसà¥à¤¯ हैं + +/community/join.bml.label.sure=पकà¥à¤•à¤¾? + +/community/join.bml.success=सफल + +/community/join.bml.title=समà¥à¤¦à¤¾à¤¯ में शामिल हों + +/community/leave.bml.button.leave=समà¥à¤¦à¤¾à¤¯ छोड़ें + +/community/leave.bml.label.buttontoleave="[[commname]]" को छोड़ने के लिठनिमà¥à¤¨à¥‹à¤•à¥à¤¤ कà¥à¤žà¥à¤œà¥€ दबाà¤à¤à¥¤ + +/community/leave.bml.label.infoerror=पà¥à¤°à¤¦à¤¤à¥à¤¤ सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जानकारी अवैध है। + +/community/leave.bml.label.logoutfirst=समà¥à¤¦à¤¾à¤¯ छोड़ने के लिठआपको पहले पà¥à¤°à¤µà¥‡à¤¶ करना होगा। + +/community/leave.bml.label.removed=अब आपको [[commname]] समà¥à¤¦à¤¾à¤¯ से हटा दिया गया है + +/community/leave.bml.label.removefromfriends="[[user]]" को मितà¥à¤° सूची से भी हटाà¤à¤à¥¤ + +/community/leave.bml.success=सफल + +/community/leave.bml.sure=पकà¥à¤•à¤¾? + +/community/leave.bml.title=समà¥à¤¦à¤¾à¤¯ छोड़ें + +/community/manage.bml.commlist.actinfo=जानकारी + +/community/manage.bml.commlist.actions=कà¥à¤°à¤¿à¤¯à¤¾à¤à¤ + +/community/manage.bml.commlist.actmembers=[सदसà¥à¤¯] + +/community/manage.bml.commlist.actmembers2=सदसà¥à¤¯ + +/community/manage.bml.commlist.actsettings=[जमाव] + +/community/manage.bml.commlist.actsettings2=जमाव + +/community/manage.bml.commlist.header=आपके समà¥à¤¦à¤¾à¤¯ + +/community/manage.bml.commlist.none=आप किसी समà¥à¤¦à¤¾à¤¯ का पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ नहीं कर रहे हैं। + +/community/manage.bml.commlist.text=आप इन समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ का पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ या सह पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ कर रहे हैं: + +/community/manage.bml.commlist.title=शीरà¥à¤·à¤• + +/community/manage.bml.commlist.username=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम + +/community/manage.bml.create.header=समà¥à¤¦à¤¾à¤¯ बनाà¤à¤ + +/community/manage.bml.create.text=आप नवीन समà¥à¤¦à¤¾à¤¯ निरà¥à¤®à¤¾à¤£ भी कर सकते हैं। + +/community/manage.bml.title=समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ + +/community/members.bml.error.alreadyadded=[[user]] को शामिल नहीं किया गया कà¥à¤¯à¥‹à¤‚कि वे पहले ही इस समà¥à¤¦à¤¾à¤¯ में हैं। + +/community/members.bml.error.alreadysent=[[user]] को शामिल नहीं किया जा सका कà¥à¤¯à¥‹à¤‚कि उनà¥à¤¹à¥‡à¤‚ पहले ही [[datetime]] को पà¥à¤·à¥à¤Ÿà¤¿ समà¥à¤¬à¤¨à¥à¤§à¥€ डाक भेजी जा चà¥à¤•à¥€ है। कृपया उनकी पà¥à¤°à¤¤à¤¿à¤•à¥à¤°à¤¿à¤¯à¤¾ की पà¥à¤°à¤¤à¥€à¤•à¥à¤·à¤¾ करें। + +/community/members.bml.error.invaliduser=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• या सिणà¥à¤¡à¤¿à¤•à¥‡à¤Ÿà¥…ड खाता नहीं जोड़ा जा सकता है: [[user]] + +/community/members.bml.error.noaccess=केवल समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¶à¤¾à¤¸à¤• ही सदसà¥à¤¯à¤¤à¤¾ सूची समà¥à¤ªà¤¾à¤¦à¤¿à¤¤ कर सकते हैं। आप [[comm]] समà¥à¤¦à¤¾à¤¯ के पà¥à¤°à¤¶à¤¾à¤¸à¤• नहीं हैं। + +/community/members.bml.error.noattr=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾: [[user]] की कोई विशेषताà¤à¤ नहीं चà¥à¤¨à¥€ गईं। + +/community/members.bml.error.nocomm=समà¥à¤¦à¤¾à¤¯ अपà¥à¤°à¤¾à¤ªà¥à¤¯à¥¤ + +/community/members.bml.error.nouser=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ मौजूद नहीं है: [[user]] + +/community/members.bml.key.admin=पà¥à¤°à¤¶à¤¾à¤¸à¤• + +/community/members.bml.key.member=सदसà¥à¤¯ + +/community/members.bml.key.moderate=मधà¥à¤¯à¤¸à¥à¤¥ + +/community/members.bml.key.post=लेखन सà¥à¤µà¤¿à¤§à¤¾ + +/community/members.bml.key.preapprove=मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾à¤¹à¥€à¤¨ + +/community/members.bml.manage2=समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ करें + +/community/members.bml.name=समà¥à¤¦à¤¾à¤¯ का नाम: [[name]] + +/community/members.bml.nextlink=(अगला पनà¥à¤¨à¤¾...) + +/community/members.bml.prevlink=(पिछला पनà¥à¤¨à¤¾...) + +/community/members.bml.settings=[जमाव] + +/community/members.bml.success.header=सफल + +/community/members.bml.success.message=आपके परिवरà¥à¤¤à¤¨ सफलतापूरà¥à¤µà¤• सà¤à¤œà¥‹ लिठगठहै। + +/community/members.bml.success.return=वापस सूची पर जाà¤à¤ + +/community/members.bml.title=समà¥à¤¦à¤¾à¤¯ के सदसà¥à¤¯ + +/community/members.bml.update=जमाव बदलें + +/community/moderate.bml.approve.button=जी हाà¤, सà¥à¤µà¥€à¤•à¥ƒà¤¤à¤¿ दें + +/community/moderate.bml.approve.header=इस पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ को सà¥à¤µà¥€à¤•à¥ƒà¤¤à¤¿ दें? + +/community/moderate.bml.approve.preapprove=साथ ही, पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ [[user]] को इस समà¥à¤¦à¤¾à¤¯ के पूरà¥à¤µ सà¥à¤µà¥€à¤•à¥ƒà¤¤ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं की सूची में शामिल करें। + +/community/moderate.bml.approve.text=कà¥à¤¯à¤¾ आप निशà¥à¤šà¤¯ ही इस पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ को सà¥à¤µà¥€à¤•à¥ƒà¤¤ करना चाहते हैं? + +/community/moderate.bml.brlist.actions=कà¥à¤°à¤¿à¤¯à¤¾à¤à¤ + +/community/moderate.bml.brlist.poster=पà¥à¤°à¥‡à¤·à¤• + +/community/moderate.bml.brlist.subject=विषय का आरमà¥à¤­ + +/community/moderate.bml.brlist.time=समय + +/community/moderate.bml.brlist.view=दृषà¥à¤¯ + +/community/moderate.bml.browse.empty=मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ पङà¥à¤•à¥à¤¤à¤¿ रिकà¥à¤¤ है। + +/community/moderate.bml.browse.header=समà¥à¤¦à¤¾à¤¯ की मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ करें + +/community/moderate.bml.browse.text=यह है [[link]] समà¥à¤¦à¤¾à¤¯ की मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ पङà¥à¤•à¥à¤¤à¤¿ + +/community/moderate.bml.choice.approve=सà¥à¤µà¥€à¤•à¥ƒà¤¤à¤¿ दें + +/community/moderate.bml.choice.reject=असà¥à¤µà¥€à¤•à¤¾à¤° करें + +/community/moderate.bml.error.noaccess=आप [[comm]] समà¥à¤¦à¤¾à¤¯ के मधà¥à¤¯à¤¸à¥à¤¥ नहीं हैं। + +/community/moderate.bml.error.noentry=पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ अपà¥à¤°à¤¾à¤ªà¥à¤¯ (समà¥à¤­à¤µà¤¤à¤ƒ किसी अनà¥à¤¯ मधà¥à¤¯à¤¸à¥à¤¥ दà¥à¤µà¤¾à¤°à¤¾ सà¤à¤­à¤¾à¤²à¥€ जा चà¥à¤•à¥€ है) + +/community/moderate.bml.error.nolist=आप किसी समà¥à¤¦à¤¾à¤¯ के मधà¥à¤¯à¤¸à¥à¤¥ नहीं हैं। + +/community/moderate.bml.error.notfound=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता अपà¥à¤°à¤¾à¤ªà¥à¤¯à¥¤ + +/community/moderate.bml.manage=समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ का पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ करें + +/community/moderate.bml.moderate=इस समà¥à¤¦à¤¾à¤¯ की मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ करें + +/community/moderate.bml.modlist.actions=कृयाà¤à¤ + +/community/moderate.bml.modlist.actmodempty=[मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ करें] + +/community/moderate.bml.modlist.actmoderate=मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ करें + +/community/moderate.bml.modlist.count=पङà¥à¤•à¥à¤¤à¤¿ आकार + +/community/moderate.bml.modlist.header=समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ की मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ करें + +/community/moderate.bml.modlist.title=शीरà¥à¤·à¤• + +/community/moderate.bml.modlist.username=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम + +/community/moderate.bml.posted.appheader=पूरà¥à¤µ सà¥à¤µà¥€à¤•à¥ƒà¤¤ + +/community/moderate.bml.posted.apptext=इस के अलावा, पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ [[user]] को इस समà¥à¤¦à¤¾à¤¯ के पूरà¥à¤µ सà¥à¤µà¥€à¤•à¥ƒà¤¤ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं की सूची में शामिल किया जा चà¥à¤•à¤¾ है। + +/community/moderate.bml.posted.header=सफल + +/community/moderate.bml.posted.proterror=इस पà¥à¤°à¥‹à¤Ÿà¥‹à¤•à¥‰à¤² तà¥à¤°à¥à¤Ÿà¤¿ के कारण यह पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ छापी नहीं गई है: [[err]] + +/community/moderate.bml.posted.text=पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ सफलता पूरà¥à¤µà¤• छाप दी गई। + +/community/moderate.bml.reject.button=जी हाà¤, असà¥à¤µà¥€à¤•à¤¾à¤° करें + +/community/moderate.bml.reject.header=पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ को असà¥à¤µà¥€à¤•à¤¾à¤° करें? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=आप पà¥à¤°à¥‡à¤·à¤• को पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ असà¥à¤µà¥€à¤•à¥ƒà¤¤ करने का कारण भी बता सकते हैं। यह पà¥à¤°à¥‡à¤·à¤• को डाक दà¥à¤µà¤¾à¤°à¤¾ भेजी जाà¤à¤à¤—ी। + +/community/moderate.bml.reject.text=कà¥à¤¯à¤¾ आप निशà¥à¤šà¤¯ ही इस पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ को असà¥à¤µà¥€à¤•à¥ƒà¤¤ करना चाहते हैं? + +/community/moderate.bml.rejected.header=असà¥à¤µà¥€à¤•à¥ƒà¤¤ + +/community/moderate.bml.rejected.text=इस पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ को असà¥à¤µà¥€à¤•à¤¾à¤° किया जा चà¥à¤•à¤¾ है। + +/community/moderate.bml.title=समà¥à¤¦à¤¾à¤¯ की मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾ + +/community/search.bml.button.clear=परà¥à¤šà¥‡ की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ हटाà¤à¤ + +/community/search.bml.button.search=खोजें! + +/community/search.bml.checkbox.onlywithpics=केवल छवियों वाले समà¥à¤¦à¤¾à¤¯ + +/community/search.bml.label.byinterest=रà¥à¤šà¤¿ के अनà¥à¤¸à¤¾à¤° + +/community/search.bml.label.bylocation=सà¥à¤¥à¤¾à¤¨ के अनà¥à¤¸à¤¾à¤° + +/community/search.bml.label.bytime=लेखा परिवरà¥à¤¤à¤¨ समय के अनà¥à¤¸à¤¾à¤° + +/community/search.bml.label.city=शहर: + +/community/search.bml.label.country=देश: + +/community/search.bml.label.displayoptions=पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨ विकलà¥à¤ª + +/community/search.bml.label.hasmember=जिसमें यह सदसà¥à¤¯ हो + +/community/search.bml.label.othercriteria=खोज के अनà¥à¤¯ आधार + +/community/search.bml.label.outputformat=परिणामों का पà¥à¤°à¤¾à¤°à¥‚प + +/community/search.bml.label.records=हर पनà¥à¤¨à¥‡ पर कितने परिणाम चाहिà¤: + +/community/search.bml.label.searchcomm=समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ को खोजें + +/community/search.bml.label.selecriteria=नीचे से चà¥à¤¨à¤¿à¤, कि आप किस आधार पर समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ को खोजना चाहते हैं। खोज के सभी आधारों से मेल खाने वाले परिणाम पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ किठजाà¤à¤à¤—े। दूसरे शबà¥à¤¦à¥‹à¤‚ में सही के निशान लगाने का मतलब है "और", "या" नहीं। + +/community/search.bml.label.sortmethod=छà¤à¤Ÿà¤¨à¥€ की विधि: + +/community/search.bml.label.stateprovince=राजà¥à¤¯/पà¥à¤°à¤¾à¤¨à¥à¤¤: + +/community/search.bml.label.updated=इतने समय पहले परिवरà¥à¤¤à¤¿à¤¤ + +/community/search.bml.sel.bypicture=छवि के अनà¥à¤¸à¤¾à¤° + +/community/search.bml.sel.communityname=समà¥à¤¦à¤¾à¤¯ का नाम + +/community/search.bml.sel.commview=समà¥à¤¦à¤¾à¤¯ का दृषà¥à¤¯ + +/community/search.bml.sel.day=दिवस + +/community/search.bml.sel.month=मास + +/community/search.bml.sel.simple=सादा + +/community/search.bml.sel.updatetime=परिवरà¥à¤¤à¤¨ समय + +/community/search.bml.sel.username=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम + +/community/search.bml.sel.week=सपà¥à¤¤à¤¾à¤¹ + +/community/search.bml.title=समà¥à¤¦à¤¾à¤¯ खोज + +/community/settings.bml.button.changecommunity=जमाव बदलें + +/community/settings.bml.button.createcommunity=समà¥à¤¦à¤¾à¤¯ बनाà¤à¤ + +/community/settings.bml.error.badpassword=अवैध समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ + +/community/settings.bml.error.hasentries=इस खाते में पहले ही पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ है, इसका परिवरà¥à¤¤à¤¨ नहीं किया जा सकता। + +/community/settings.bml.error.maintainertype=पà¥à¤°à¤¬à¤¨à¥à¤§à¤• खाता वà¥à¤¯à¤•à¥à¤¤à¤¿ विशेष का हो, à¤à¤• अनà¥à¤¯ साà¤à¤à¤¾ खाता नहीं। + +/community/settings.bml.error.noaccess=केवल समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¬à¤¨à¥à¤§à¤• ही सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जमाव बदल सकते हैं। आप [[comm]] समà¥à¤¦à¤¾à¤¯ के पà¥à¤°à¤¬à¤¨à¥à¤§à¤• नहीं हैं। + +/community/settings.bml.error.notcomm=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता नहीं। + +/community/settings.bml.error.notfound=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता अपà¥à¤°à¤¾à¤ªà¥à¤¯à¥¤ + +/community/settings.bml.error.samenames=पà¥à¤°à¤¬à¤¨à¥à¤§à¤• खाता व सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता अलग अलग होने चाहिà¤à¥¤ + +/community/settings.bml.label.anybodycan=सभी सदसà¥à¤¯
        सदसà¥à¤¯ गà¥à¤°à¤¹à¤£ करते ही कोई भी लेख लिख सकता है। + +/community/settings.bml.label.changeheader=समà¥à¤¦à¤¾à¤¯ जमाव बदलें + +/community/settings.bml.label.changetext=यहाठपर आप अपने व अपने दà¥à¤µà¤¾à¤°à¤¾ पà¥à¤°à¤¬à¤¨à¥à¤§à¤¿à¤¤ समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ के जमाव में परिवरà¥à¤¤à¤¨ ला सकते हैं। + +/community/settings.bml.label.commchanged=आपकी सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जमाव बदल दिठगठहैं। + +/community/settings.bml.label.commcreate=यही है वह खाता जिसे आप समà¥à¤¦à¤¾à¤¯ में बदलना चाहते हैं। यह पहले ही निरà¥à¤®à¤¿à¤¤, होना चाहिà¤, लेकिन किसी वà¥à¤¯à¤•à¥à¤¤à¤¿à¤µà¤¿à¤¶à¥‡à¤· दà¥à¤µà¤¾à¤°à¤¾ पहले से ही पà¥à¤°à¤¯à¥à¤•à¥à¤¤ नहीं होना चाहिठकà¥à¤¯à¥‹à¤‚कि अब इस पर कई लोगों को लेख लिखने की अनà¥à¤®à¤¤à¤¿ होनी चाहिà¤à¥¤ + +/community/settings.bml.label.commcreated=आपके समà¥à¤¦à¤¾à¤¯ का जमाव किया जा चà¥à¤•à¤¾ है। + +/community/settings.bml.label.commheader=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता + +/community/settings.bml.label.comminfo=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जानकारी + +/community/settings.bml.label.commopts=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• विकलà¥à¤ª + +/community/settings.bml.label.commsite=सामà¥à¤¦à¤¾à¤¯à¤¿à¤• जालसà¥à¤¥à¤² + +/community/settings.bml.label.community=समà¥à¤¦à¤¾à¤¯: + +/community/settings.bml.label.createheader=समà¥à¤¦à¤¾à¤¯ बनाà¤à¤ + +/community/settings.bml.label.createtext=यहाठपर आप सामà¥à¤¦à¤¾à¤¯à¤¿à¤• खाता चालू कर सकते हैं। समà¥à¤¦à¤¾à¤¯ à¤à¤• विशेष खाता है जिसमें अनà¥à¤¯ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ भी शामिल हो सकते हैं और लेख लिख सकते हैं। उदाहरणारà¥à¤¥ सियेटल पारà¥à¤Ÿà¥€ समà¥à¤¦à¤¾à¤¯ को देखें। + +/community/settings.bml.label.howoperates=अपने समà¥à¤¦à¤¾à¤¯ के पà¥à¤°à¤šà¤¾à¤²à¤¨ की विधि चà¥à¤¨à¥‡à¤‚। आप इस बाद में बदल सकते हैं। + +/community/settings.bml.label.maintainer=पà¥à¤°à¤¬à¤¨à¥à¤§à¤•: + +/community/settings.bml.label.maintainer.login=यदि यह पà¥à¤°à¤¬à¤¨à¥à¤§à¤• खाता नहीं है, तो किसी और के तौर पर पà¥à¤°à¤µà¥‡à¤¶ करें। + +/community/settings.bml.label.membership=सदसà¥à¤¯à¤¤à¤¾ + +/community/settings.bml.label.modheader=मधà¥à¤¯à¤¸à¥à¤¥à¤¿à¤¤ + +/community/settings.bml.label.modis=मधà¥à¤¯à¤¸à¥à¤¥à¤¿à¤¤
        नई पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ मधà¥à¤¯à¤¸à¥à¤¥ दà¥à¤µà¤¾à¤°à¤¾ सà¥à¤µà¥€à¤•à¥ƒà¤¤ होनी चाहिà¤à¥¤ + +/community/settings.bml.label.modisnt=मधà¥à¤¯à¤¸à¥à¤¥à¤¤à¤¾à¤¹à¥€à¤¨
        नई पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ तà¥à¤°à¤¨à¥à¤¤ छप जाती हैं। + +/community/settings.bml.label.modtext=कà¥à¤¯ इस समà¥à¤¦à¤¾à¤¯ की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ मधà¥à¤¯à¤¸à¥à¤¥à¤¿à¤¤ हैं? + +/community/settings.bml.label.nmcan=सदसà¥à¤¯à¤¤à¤¾ के बगैर लिख सकते हैं
        इस समà¥à¤¦à¤¾à¤¯ में शामिल हà¥à¤ बिना पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ इसमें लेख लिख सकते हैं। + +/community/settings.bml.label.nmcant=सदसà¥à¤¯à¤¤à¤¾ के बगैर नहीं लिख सकते
        इस समà¥à¤¦à¤¾à¤¯ में शामिल होने पर ही पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ इसमें लेख लिख सकते हैं। + +/community/settings.bml.label.nmheader=बिना सदसà¥à¤¯à¤¤à¤¾ के लेखन + +/community/settings.bml.label.nmtext=कà¥à¤¯à¤¾ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ इस समà¥à¤¦à¤¾à¤¯ में शामिल हà¥à¤ बिना लेख लिख सकते हैं? + +/community/settings.bml.label.openmemb=खà¥à¤²à¥€ सदसà¥à¤¯à¤¤à¤¾
        बिना सà¥à¤µà¥€à¤•à¥ƒà¤¤à¤¿ के कोई भी शामिल हो सकता है। + +/community/settings.bml.label.password=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦: + +/community/settings.bml.label.postaccess=लेखन की अनà¥à¤®à¤¤à¤¿ + +/community/settings.bml.label.rellinks=समà¥à¤¬à¤¦à¥à¤§ कड़ियाठ+ +/community/settings.bml.label.selcan=चà¥à¤¨à¥‡ हà¥à¤ सदसà¥à¤¯
        केवल कà¥à¤› सदसà¥à¤¯ लिख सकते हैं, वह भी पà¥à¤°à¤¬à¤¨à¥à¤§à¤• खाते दà¥à¤µà¤¾à¤°à¤¾ अनà¥à¤®à¤¤à¤¿ मिलने के पशà¥à¤šà¤¾à¤¤à¥¤ + +/community/settings.bml.label.username=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम: + +/community/settings.bml.label.whocanjoin=आपके समà¥à¤¦à¤¾à¤¯ में कौन शामिल हो सकता है? + +/community/settings.bml.label.whocanpost=इस समà¥à¤¦à¤¾à¤¯ में कौन लिख सकता है? + +/community/settings.bml.manage2=समà¥à¤¦à¤¾à¤¯à¥‹à¤‚ का पà¥à¤°à¤¬à¤¨à¥à¤§à¤¨ करें + +/community/settings.bml.members=[सदसà¥à¤¯] + +/community/settings.bml.name=समà¥à¤¦à¤¾à¤¯ का नाम: [[name]] + +/community/settings.bml.success=सफल + +/community/settings.bml.title.create=समà¥à¤¦à¤¾à¤¯ बनाà¤à¤ + +/community/settings.bml.title.modify=समà¥à¤¦à¤¾à¤¯ का जमाव + +/create.bml.age.check.question=कà¥à¤¯à¤¾ आपकी आयॠ13 वरà¥à¤· से कम है? + +/create.bml.age.check.yes=जी हाठ, मेरी आयॠतेरह वरà¥à¤· से कम है। + +/create.bml.age.check2.question=कà¥à¤¯à¤¾ आपकी आयॠ13 वरà¥à¤· से अधिक है? + +/create.bml.age.check2.yes=जी हाà¤, मेरी आयॠ13 वरà¥à¤· से अधिक है। + +/create.bml.age.head=आयॠ+ +/create.bml.btn.create=लेखा निरà¥à¤®à¤¿à¤¤ करें + +/create.bml.btn.proceed=आगे बढ़ें... + +/create.bml.captcha.answer=उतà¥à¤¤à¤°: + +/create.bml.captcha.audiodesc=आप सà¥à¤ªà¥…म रोबोट नहीं हैं, यह सिदà¥à¤§ करने के लिà¤, जो सङà¥à¤–à¥à¤¯à¤¾à¤à¤ आप को सà¥à¤¨à¤¾à¤ˆ दे रही हैं, उनà¥à¤¹à¥‡à¤‚ टङà¥à¤•à¤¿à¤¤ करें: + +/create.bml.captcha.desc=आप सà¥à¤ªà¥…म रोबोट नहीं हैं, यह सिदà¥à¤§ करने के लिà¤, नीचे दिख रहे अकà¥à¤·à¤°à¥‹à¤‚ और सङà¥à¤–à¥à¤¯à¤¾à¤“ं को टङà¥à¤•à¤¿à¤¤ करें। यदि आप पढ़ नहीं पा रहे हैं, तो "AUDIO" टङà¥à¤•à¤¿à¤¤ करें और शà¥à¤°à¤¾à¤µà¥à¤¯ परीकà¥à¤·à¤£ करवाà¤à¤à¥¤ + +/create.bml.captcha.invalid=पिछली चà¥à¤¨à¥Œà¤¤à¥€ का उतà¥à¤¤à¤° अवैध था। à¤à¤• और बार कोशिश करें। + +/create.bml.captcha.play=धà¥à¤µà¤¨à¤¿ चलाà¤à¤ + +/create.bml.captcha.prove=सिदà¥à¤§ करें कि आप मानव हैं + +/create.bml.clusterselect.cluster=à¤à¥à¤£à¥à¤¡: + +/create.bml.clusterselect.clusternum=à¤à¥à¤£à¥à¤¡ [[number]] + +/create.bml.clusterselect.head=à¤à¥à¤£à¥à¤¡ का चà¥à¤¨à¤¾à¤µ + +/create.bml.clusterselect.nocluster=कोई à¤à¥à¤£à¥à¤¡ नहीं + +/create.bml.clusterselect.text=कृपया चà¥à¤¨à¥‡à¤‚ कि आप किस à¤à¥à¤£à¥à¤¡ में खाता बनाना चाहते हैं। धà¥à¤¯à¤¾à¤¨ दें: यह विकलà¥à¤ª केवल परीकà¥à¤·à¤£ के लिठहै। वासà¥à¤¤à¤µ में पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ इसे न तो इसे चà¥à¤¨à¥‡à¤‚गे, न ही इसके बारे में कà¥à¤› जानते होंगे। + +/create.bml.create.head=नया लेखा बनाना + +/create.bml.create.text=नया लाइवà¥à¤œà¤°à¥à¤¨à¤² बनाना सरल है, निमà¥à¤¨à¥‹à¤•à¥à¤¤ निरà¥à¤¦à¥‡à¤¶à¥‹à¤‚ की मदद से! + +/create.bml.email.head=आपका डाक पता + +/create.bml.email.input.head=डाक पता: + +/create.bml.email.text2=पà¥à¤·à¥à¤Ÿà¤¿ व सà¥à¤°à¤•à¥à¤·à¤¾ की दृषà¥à¤Ÿà¤¿ से हमें आपका डाक पता चाहिठहोगा। किसी भी हालत में यह सà¥à¤ªà¥…मरों को बेचा या दिया नहीं जाà¤à¤—ा। इस चीज़ से हमें खà¥à¤¦ सबसे ज़à¥à¤¯à¤¾à¤¦à¤¾ नफ़रत है। और जानकारी के लिठहमारी निजी सà¥à¤°à¤•à¥à¤·à¤¾ नीति पढ़ें। + +/create.bml.error.coppa.under13=कà¥à¤·à¤®à¤¾ करें, कॉपà¥à¤ªà¤¾ पà¥à¤°à¤¤à¤¿à¤¬à¤¨à¥à¤§à¥‹à¤‚ की वजह से आप 13 वरà¥à¤· को होने तक लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवा का पà¥à¤°à¤¯à¥‹à¤— नहीं कर सकते। कृपया अपने 13वें जनà¥à¤®à¤¦à¤¿à¤¨ पर वापिस आà¤à¤à¥¤ + +/create.bml.error.email.blank=आपको अपना डाक पता पà¥à¤°à¤¦à¤¾à¤¨ करना होगा। + +/create.bml.error.email.lj_domain=खाता खोलते समय [[domain]] छदà¥à¤®à¤¨à¤¾à¤® का पà¥à¤°à¤¯à¥‹à¤— निषिदà¥à¤§ है। कःपया कोई अनà¥à¤¯ डाक पता पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/create.bml.error.email.nospaces=डाक पते के बीच में खाली सà¥à¤¥à¤¾à¤¨ निषिदà¥à¤§ हैं। यदि आप ठओ à¤à¤² पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ हैं, तो आपका अनà¥à¤¤à¤°à¥à¤œà¤¾à¤² डाक पता है आपका पट नाम, सारे खाले सà¥à¤¥à¤¾à¤¨ हटा कर, और अनà¥à¤¤ में@aol.com लगा कर। + +/create.bml.error.password.asciionly=आप पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ में केवल à¤à¤¸à¥à¤•à¥€ चिनà¥à¤¹à¥‹à¤‚ का पà¥à¤°à¤¯à¥‹à¤— कर सकते हैं। + +/create.bml.error.password.blank=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ अनिवारà¥à¤¯ है। + +/create.bml.error.password.nomatch=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ मेल नहीं खाते। + +/create.bml.error.postrequired=पोसà¥à¤Ÿ अनिवारà¥à¤¯à¥¤ + +/create.bml.error.username.blank=कृपया à¤à¤• नाम या छदà¥à¤®à¤¨à¤¾à¤® पà¥à¤°à¤¦à¤¾à¤¨ करें। + +/create.bml.error.username.inuse=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम पहले ही इसà¥à¤¤à¥‡à¤®à¤¾à¤² में है, कृपया कोई और चà¥à¤¨à¥‡à¤‚। + +/create.bml.error.username.iscode=यह पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम आमनà¥à¤¤à¥à¤°à¤£ कूट पà¥à¤°à¤¤à¥€à¤¤ होता है, पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम नहीं। + +/create.bml.error.username.mustenter=कृपया पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/create.bml.error.username.reserved=खेद है कि यह पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम आरकà¥à¤·à¤¿à¤¤ है। + +/create.bml.initial.friend.lj_maintenance=पूरà¥à¤µà¤¨à¤¿à¤¯à¥‹à¤œà¤¿à¤¤ व अनियोजित मरमà¥à¤®à¤¤à¥‹à¤‚ व सà¥à¤¥à¤² बनà¥à¤¦ होने की रपटें। + +/create.bml.initial.friend.news=लाइवà¥à¤œà¤°à¥à¤¨à¤² समाचार व घटनाà¤à¤ + +/create.bml.initialfriends=सà¥à¤¥à¤² समà¥à¤¬à¤¨à¥à¤§à¥€ समाचार व जानकारी पà¥à¤°à¤¾à¤ªà¥à¤¤ करने हेतॠयह लेखे अपनी मितà¥à¤° सूची में जोड़ें। + +/create.bml.initialfriends.heading=शà¥à¤°à¥à¤†à¤¤à¥€ मितà¥à¤° + +/create.bml.name.head=आपका नाम + +/create.bml.name.input.head=नाम: + +/create.bml.name.text=आपका नाम या छदà¥à¤®à¤¨à¤¾à¤® कà¥à¤¯à¤¾ है? यह आपके लेखे के ऊपर पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ होगा, और पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ निरà¥à¤¦à¥‡à¤¶à¤¿à¤•à¤¾ में भी, यदि आप चाहें तो। आपको पूरी नाम देने की ज़रूरत नहीं है, बलà¥à¤•à¤¿ असली नाम देने की भी ज़रूरत नहीं है। + +/create.bml.password.head=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ + +/create.bml.password.input.head1=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦: + +/create.bml.password.input.head2=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ पà¥à¤·à¥à¤Ÿà¤¿: + +/create.bml.password.text=पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ चà¥à¤¨à¥‡à¤‚। + +/create.bml.proceed.btn.proceed=आगे बढ़ें... + +/create.bml.proceed.warning=केवल à¤à¤• बार ही आगे बढ़ें दबाà¤à¤!! + +/create.bml.success.btn.enterinfo=वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त जानकारी पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें + +/create.bml.success.head=सफल! + +/create.bml.success.text1=आपका चिटà¥à¤ à¤¾ तैयार है। महतà¥à¤µà¤ªà¥‚रà¥à¤£ पञà¥à¤œà¥€à¤•à¤°à¤£ समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी [[email]] पर भेज दी गई है, अनà¥à¤¯ निरà¥à¤¦à¥‡à¤¶à¥‹à¤‚ के साथ। डाक में पà¥à¤°à¤¦à¤¤à¥à¤¤ कड़ी पर चटका लगा कर चिटà¥à¤ à¥‡ के निरà¥à¤®à¤¾à¤£ की पà¥à¤·à¥à¤Ÿà¤¿ करना न भूलें। + +/create.bml.success.text2=आपका लाइवà¥à¤œà¤°à¥à¤¨à¤² यहाठपà¥à¤°à¤¾à¤ªà¥à¤¯ है: + +/create.bml.success.text3=अब, थोड़ा समय दे, और अपने बारे में कà¥à¤› बताà¤à¤à¥¤ अधिकतर जानकारी वैकलà¥à¤ªà¤¿à¤• है, लेकिन इससे हमें पता चलता है कि लाइवà¥à¤œà¤°à¥à¤¨à¤² के पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ कैसे हैं। + +/create.bml.title=नया चिटà¥à¤ à¤¾ बनाà¤à¤ + +/create.bml.tos.error=खाता खोलने से पहले आपको सेवा की शरà¥à¤¤à¥‹à¤‚ को पढ़ना होगा व उनको मञà¥à¤œà¥‚री देनी होगी। + +/create.bml.tos.haveread=हमने सेवा की शरà¥à¤¤à¥‡à¤‚ पढ़ ली हैं, और वे हमें मञà¥à¤œà¥‚र हैं। + +/create.bml.tos.heading=सेवा की शरà¥à¤¤à¥‡à¤‚ + +/create.bml.tos.p1.2=आगे बढ़ने से पहले आपको सेवा की शरà¥à¤¤à¥‡à¤‚ पढ़नी होंगी और उनà¥à¤¹à¥‡à¤‚ मञà¥à¤œà¥‚र करना होगा। + +/create.bml.useacctcodes.entercode=नया खाता खोलने के लिठखाता खोलने का कूट पà¥à¤°à¤¦à¤¾à¤¨ करें। और जानकारी के लिठखाता कैसे खोलें? देखें। + +/create.bml.useacctcodes.welcome=सà¥à¤µà¤¾à¤—तमॠ+ +/create.bml.username.box.head=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम: + +/create.bml.username.charsallowed=आपके पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम में केवल छोटे अकà¥à¤·à¤° (a-z), सङà¥à¤–à¥à¤¯à¤¾à¤à¤, (0-9) व अणà¥à¤¡à¤°à¥à¤•à¥‹à¤° (_) हो सकते हैं।
        साथ ही इसमें १५ से अधिक अकà¥à¤·à¤° न हों। + +/create.bml.username.forpaidaccts=या, शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ खातों के लिà¤: + +/create.bml.username.head=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम: + +/create.bml.username.ljaddress=आपका खाता इन पतों पर रहेगा: + +/create.bml.username.text=हरेक [[sitename]] पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ का अनोखा पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम होता है। यह नाम आपके लेखे के पते में दिखलाई देगा, और [[sitename]] सेवक में पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ होने के लिठभी यह पà¥à¤°à¤¯à¥à¤•à¥à¤¤ होगा। दूसरों के लेखों पर टिपà¥à¤ªà¤£à¥€ लिखने पर भी यह नाम पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ होगा। + +/create.bml.username.username=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम + +/customize/index.bml.change=बदलें + +/customize/index.bml.choose=आप पà¥à¤°à¤¾à¤¨à¥€ शैली पà¥à¤°à¤£à¤¾à¤²à¥€ चाहते हैं या नई वाली? + +/customize/index.bml.choose.header=शैली पà¥à¤°à¤£à¤¾à¤²à¥€ चà¥à¤¨à¥‡à¤‚ + +/customize/index.bml.choose.s1=पà¥à¤°à¤¾à¤¨à¥€ पà¥à¤°à¤£à¤¾à¤²à¥€ (S1) + +/customize/index.bml.choose.s2=नई पà¥à¤°à¤£à¤¾à¤²à¥€ (S2) + +/customize/index.bml.error.cant_generate_user_layer=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ आवरण उतà¥à¤ªà¤¨à¥à¤¨ करने में असफल + +/customize/index.bml.error.fail_create_style=नई शैली बनाने में असफल। + +/customize/index.bml.error.not_your_layout=यह आपका जमाव नहीं है। + +/customize/index.bml.error.not_your_theme=यह आपकी थीम नहीं है + +/customize/index.bml.error.no_core_parent=कोई कोर पितर नहीं हैं? + +/customize/index.bml.previews=(पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨) + +/customize/index.bml.s1=पà¥à¤°à¤¾à¤¨à¥€ शैली पà¥à¤°à¤£à¤¾à¤²à¥€ का जमावचिटà¥à¤ à¤¾ परिवरà¥à¤¤à¤¨ पृषà¥à¤  से होता है। + +/customize/index.bml.s1.header=S1 की मदद से + +/customize/index.bml.s2.advanced.denied=केवल शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤, सà¥à¤¥à¤¾à¤¯à¥€ व पà¥à¤°à¤¾à¤ªà¥à¤°à¤¯à¥‹à¤—ी खाताधारी ही विकसित परिवरà¥à¤¤à¤¨ कà¥à¤·à¥‡à¤¤à¥à¤° का पà¥à¤°à¤¯à¥‹à¤— कर सकते हैं। शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ खाते के फ़ायदों के बारे में और जानें। + +/customize/index.bml.s2.advanced.header=विकसित परिवरà¥à¤¤à¤¨ + +/customize/index.bml.s2.advanced.permitted=नठआवरण व शैलियाठबनाने के लिठविकसित परिवरà¥à¤¤à¤¨ केनà¥à¤¦à¥à¤° पर जाà¤à¤à¥¤ + +/customize/index.bml.s2.customize=निमà¥à¤¨à¥‹à¤•à¥à¤¤ जमाव आवरण पर निरà¥à¤­à¤° हैं। + +/customize/index.bml.s2.customize.header=कà¥à¤°. 2: जमाव बदलें + +/customize/index.bml.s2.customize.language=इस जमाव में निमà¥à¤¨à¥‹à¤•à¥à¤¤ भाषाà¤à¤ पूरà¥à¤£à¤¤à¤ƒ या आंशिक रूप से उपलबà¥à¤§ हैं। + +/customize/index.bml.s2.customize.language.custom=(बदला हà¥à¤†) + +/customize/index.bml.s2.customize.language.header=भाषा + +/customize/index.bml.s2.customize.settings=यदि आप अपने लेखे को और भी बदलना चाहते हैं, तो आप यहाठपर हरेक चीज़ का जमाव बदल कर जैसा चाहें वैसा कर सकते हैं। + +/customize/index.bml.s2.customize.settings.delete=बदलाव हटा दें + +/customize/index.bml.s2.customize.settings.edit=बदलावों को समà¥à¤ªà¤¾à¤¦à¤¿à¤¤ करें + +/customize/index.bml.s2.customize.settings.header=वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त जमाव बदलें + +/customize/index.bml.s2.customize.settings.new=बदलें + +/customize/index.bml.s2.customize.themes=इस जमाव के लिठइन वैकलà¥à¤ªà¤¿à¤• थीमों में से चà¥à¤¨à¥‡à¤‚। + +/customize/index.bml.s2.customize.themes.default=(जमाव के लिठमूल सà¥à¤¥à¤¿à¤¤à¤¿) + +/customize/index.bml.s2.customize.themes.header=थीमें + +/customize/index.bml.s2.layout=अपना जमाव चà¥à¤¨à¥‡à¤‚। थीम का चà¥à¤¨à¤¾à¤µ व बदलाव, जमाव पर निरà¥à¤­à¤° हैं। अतः इसको बदलने से आपके अभी तक के सभी परिवरà¥à¤¤à¤¨ रदà¥à¤¦ हो जाà¤à¤à¤—े। + +/customize/index.bml.s2.layout.header=कà¥à¤°. 1: जमाव + +/customize/index.bml.s2.related.editinfo.about=अपने लेखे के शीरà¥à¤·à¤• व अनà¥à¤¯ विकलà¥à¤ª निरà¥à¤§à¤¾à¤°à¤¿à¤¤ करें। + +/customize/index.bml.s2.related.header=समान पनà¥à¤¨à¥‡ + +/customize/index.bml.s2.related.links.about=कà¥à¤› शैलियों में सà¥à¤µà¤ªà¥à¤°à¤¬à¤¨à¥à¤§à¤¿à¤¤ कड़ी सूची भी शामिल की जा सकती है। + +/customize/index.bml.s2.related.modify.about=लेखे की मूड छवियाठचà¥à¤¨à¥‡à¤‚ + +/customize/index.bml.title=लेखे को बदलें + +/delcomment.bml.changeoptions<< +धà¥à¤¯à¤¾à¤¨ दें: [[link]] पृषà¥à¤Ÿ से आप यह निरà¥à¤§à¤¾à¤°à¤¿à¤¤ कर सकते हैं कि कौन टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤ छाप सकता है, सभी, पञà¥à¤œà¥€à¤•à¥ƒà¤¤ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾, या +केवल मितà¥à¤°à¥¤ +. + +/delcomment.bml.confirm.banuser=[[user]] को अपने लेखे में टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤ लिखने से पà¥à¤°à¤¤à¤¿à¤¬à¤¨à¥à¤§à¤¿à¤¤ करें + +/delcomment.bml.confirm.body=कà¥à¤¯à¤¾ आप निशà¥à¤šà¤¯ ही इस टिपà¥à¤ªà¤£à¥€ को हटाना चाहते हैं? + +/delcomment.bml.confirm.head=टिपà¥à¤ªà¤£à¥€ हटाà¤à¤? + +/delcomment.bml.confirm.submit=टिपà¥à¤ªà¤£à¥€ हटाà¤à¤ + +/delcomment.bml.error.alreadydeleted=यह टिपà¥à¤ªà¤£à¥€ पहले ही हटा दी जा चà¥à¤•à¥€ है। + +/delcomment.bml.error.cantdelete=टिपà¥à¤ªà¤£à¥€ हटाने का अधिकार केवल उसके लेखक को और लेखे के सà¥à¤µà¤¾à¤®à¥€ को है। + +/delcomment.bml.error.cantdelete.comm=टिपà¥à¤ªà¤£à¥€ केवल उसके लेखक, लेखा पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ के लेखक, या समà¥à¤¦à¤¾à¤¯ पà¥à¤°à¤¬à¤¨à¥à¤§à¤• ही हटा सकते हैं। + +/delcomment.bml.error.invalidtype=अवैध टिपà¥à¤ªà¤£à¥€ पà¥à¤°à¤•à¤¾à¤°à¥¤ यह पनà¥à¤¨à¤¾ केवल लेखा पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¥‹à¤‚ पर की टिपà¥à¤ªà¤£à¤¿à¤¯à¥‹à¤‚ के लिठहै। + +/delcomment.bml.error.nocomment=पà¥à¤°à¤¦à¤¤à¥à¤¤ टिपà¥à¤ªà¤£à¥€ अनà¥à¤ªà¤²à¤¬à¥à¤§à¥¤ + +/delcomment.bml.success.andban=यह टिपà¥à¤ªà¤£à¥€ हटा दी गई है, और पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ [[user]] को आपके लेखे में टिपà¥à¤ªà¤£à¥€ लिखने की मनाही कर दी गई है। + +/delcomment.bml.success.head=हटा दी गई + +/delcomment.bml.success.noban=टिपà¥à¤ªà¤£à¥€ हटा दी गई है। + +/delcomment.bml.title=टिपà¥à¤ªà¤£à¥€ हटाà¤à¤ + +/developer/index.bml.clients<< +तो, आप अपने पà¥à¤²à¥…टà¥à¤«à¤¼à¥‰à¤°à¥à¤® के लिठलाइवà¥à¤œà¤°à¥à¤¨à¤² सेवक बनाना या सà¥à¤§à¤¾à¤°à¤¨à¤¾ चाहते हैं? +बढ़िया है! +निमà¥à¤¨à¥‹à¤•à¥à¤¤ हैं कà¥à¤› आवशà¥à¤¯à¤• संसाधन, जिनसे आपको पता चलेगा कि लाइवà¥à¤œà¤°à¥à¤¨à¤² काम कैसे करता है। +. + +/developer/index.bml.clients.header=लाइवà¥à¤œà¤°à¥à¤¨à¤² गà¥à¤°à¤¾à¤¹à¤• लेखन + +/developer/index.bml.clients.links<< +
        +
        लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवक<->गà¥à¤°à¤¾à¤¹à¤• पà¥à¤°à¥‹à¤Ÿà¥‹à¤•à¥‰à¤²
        +
        पता करें कि डॅसà¥à¤•à¥à¤Ÿà¥‰à¤ª पर मौजूद गà¥à¤°à¤¾à¤¹à¤•, व लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवक आपस में कैसे बात करते हैं। + अपने पà¥à¤²à¥…टà¥à¤«à¤¼à¥‰à¤°à¥à¤® के लिठगà¥à¤°à¤¾à¤¹à¤• बनाने या सà¥à¤§à¤¾à¤°à¤¨à¥‡ के नज़रिये से यह समà¤à¤¨à¤¾ à¤à¤• पहला कदम है।
        +
        समà¥à¤ªà¥‚रà¥à¤£ पà¥à¤°à¥‹à¤Ÿà¥‹à¤•à¥‰à¤² पà¥à¤°à¤²à¥‡à¤–
        +
        सभी पà¥à¤°à¥‹à¤Ÿà¥‹à¤•à¥‰à¤² रीतियाठव विधियाà¤à¥¤
        +
        गà¥à¤°à¤¾à¤¹à¤•à¥‹à¤‚ की सूची
        +
        लाइवà¥à¤œà¤°à¥à¤¨à¤² से जà¥à¤¡à¤¼à¤¨à¥‡ के लिठपà¥à¤°à¤¯à¥à¤•à¥à¤¤ गà¥à¤°à¤¾à¤¹à¤•à¥‹à¤‚ की सूची। अधिकतर गà¥à¤°à¤¾à¤¹à¤• मà¥à¤•à¥à¤¤ सà¥à¤°à¥‹à¤¤ हैं, और सभी निःशà¥à¤²à¥à¤• पà¥à¤°à¤¯à¥à¤•à¥à¤¤ किठजा सकते हैं। आप अपने गà¥à¤°à¤¾à¤¹à¤• के लिठयहाठसे उदाहरण पà¥à¤°à¤¾à¤ªà¥à¤¤ कर सकते हैं।
        +
        +. + +/developer/index.bml.code=लाइवà¥à¤œà¤°à¥à¤¨à¤² की बॅकेणà¥à¤¡ कैसे चलता है, व कà¥à¤› उपलबà¥à¤§ गà¥à¤°à¤¾à¤¹à¤•à¥‹à¤‚ के अनà¥à¤¦à¤°à¥‚नी मसले को देखने के लिठकूट पनà¥à¤¨à¥‡ पर जाà¤à¤à¥¤ + +/developer/index.bml.code.header=लाइवà¥à¤œà¤°à¥à¤¨à¤² कूट भणà¥à¤¡à¤¾à¤° + +/developer/index.bml.dbschema<< +डाटाबेस सà¥à¤•à¥€à¤®à¤¾ के बारे में जानना चाहते हैं? +सभी तालिकाओं के निरà¥à¤®à¤¾à¤£ व उनमें सामगà¥à¤°à¥€ भरने वाले à¤à¤¸ कà¥à¤¯à¥‚ à¤à¤² भी सेवक कूट में शामिल हैं। +. + +/developer/index.bml.dbschema.header=डाटाबेस सà¥à¤•à¥€à¤®à¤¾ + +/developer/index.bml.embedding=अपना लेखा, अपने गृहपृषà¥à¤  पर शामिल करना चाहते हैं? यह करने के कई तरीके हैं, और यह इस पर निरà¥à¤­à¤° है कि आपका अपने सेवक के ऊपर कैसा नियनà¥à¤¤à¥à¤°à¤£ है। इस सबकी चिनà¥à¤¤à¤¾ आपको तभी करने की ज़रूरत है यदि आपको अपने लेखे के पते में www.livejournal.com पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ होना पसनà¥à¤¦ न हो। + +/developer/index.bml.embedding.header=लाइवà¥à¤œà¤°à¥à¤¨à¤² को शामिल करना + +/developer/index.bml.notice.header=सूचना + +/developer/index.bml.notice1=यह जानकारी केवल पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤®à¤°à¥‹à¤‚ व विकसित पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं के लिठहै। यदि आप लाइवà¥à¤œà¤°à¥à¤¨à¤² पर ही अपना लेखा रखना चाहते हैं, तो बढ़िया है! आम पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं को इस सब की चिनà¥à¤¤à¤¾ करने की आवशà¥à¤¯à¤•à¤¤à¤¾ नहीं है। + +/developer/index.bml.notice2=तो अब काम की बात: नीचे दिया मसला दो हिसà¥à¤¸à¥‹à¤‚ में बà¤à¤Ÿà¤¾ है: लाइवà¥à¤œà¤°à¥à¤¨à¤² पनà¥à¤¨à¥‹à¤‚ को बदलने के बारे में जानकारी, और लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवक के लिठलाइवà¥à¤œà¤°à¥à¤¨à¤² गà¥à¤°à¤¾à¤¹à¤• लिखने समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी। + +/developer/index.bml.styles=लेखा पृषà¥à¤ à¥‹à¤‚ की शकà¥à¤²à¥‹à¤¸à¥‚रत पसनà¥à¤¦ नहीं है? कोई गल नहीं, सब कà¥à¤› बदला जा सकता है, नीचे दिया पà¥à¤°à¤²à¥‡à¤–न पढ़ें व अपने पनà¥à¤¨à¥‹à¤‚ को अपने मन मà¥à¤†à¤«à¤¼à¤¿à¤• बनाà¤à¤à¥¤ + +/developer/index.bml.styles.header=लाइवà¥à¤œà¤°à¥à¤¨à¤² की शकà¥à¤²à¥‹à¤¸à¥‚रत बदलना + +/developer/index.bml.styles.s1.header=शैली पà¥à¤°à¤£à¤¾à¤²à¥€ 1 + +/developer/index.bml.styles.s1.system=शैली पà¥à¤°à¤£à¤¾à¤²à¥€ + +/developer/index.bml.styles.s1.system.about=पà¥à¤°à¤¥à¤® शैली पà¥à¤°à¤£à¤¾à¤²à¥€ के जमाव के बारे में आम जानकारी + +/developer/index.bml.styles.s1.varlist=परिवरà¥à¤¤à¤¨à¥€à¤¯à¥‹à¤‚ की सूची + +/developer/index.bml.styles.s1.varlist.about=जिन परिवरà¥à¤¤à¤¨à¥€à¤¯à¥‹à¤‚ को आप बदल सकते हैं, उनकी अकारादिकà¥à¤°à¤® में सूची। + +/developer/index.bml.styles.s1.views=दृषà¥à¤¯ के पà¥à¤°à¤•à¤¾à¤° + +/developer/index.bml.styles.s1.views.about=जिस जिस पà¥à¤°à¤•à¤¾à¤° से आप अपना लेखा देख सकते हैं, उनकी सूची, विसà¥à¤¤à¥ƒà¤¤ जानकारी सहित। + +/developer/index.bml.styles.s2.header=शैली पà¥à¤°à¤£à¤¾à¤²à¥€ 2 + +/developer/index.bml.styles.s2.layerbrowse=S2 आवरण पà¥à¤°à¤¦à¤°à¥à¤¶à¤• + +/developer/index.bml.styles.s2.layerbrowse.about=S2 के सारà¥à¤µà¤œà¤¨à¤¿à¤• आवरणों की पूरी सूची, जिसमें कि S2 पà¥à¤°à¤£à¤¾à¤²à¥€ की शैलियाठनिहित हैं। इनमें महतà¥à¤µà¤ªà¥‚रà¥à¤£ हैं, कोर आवरण, जिनमें कि मूल परिवरà¥à¤¤à¤¨à¥€à¤¯, फ़ङà¥à¤•à¤¶à¤¨ व कà¥à¤²à¤¾à¤¸ परिभाषित हैं। यही S2 को इतनी सशकà¥à¤¤ डिज़ाइन भाषा बनाते हैं। + +/developer/index.bml.styles.s2.manual=S2 पà¥à¤°à¤²à¥‡à¤–न + +/developer/index.bml.styles.s2.manual.about=लाइवà¥à¤œà¤°à¥à¤¨à¤² पर S2 के पà¥à¤°à¤¯à¥‹à¤— के बारे में समà¥à¤ªà¥‚रà¥à¤£ जानकारी + +/developer/index.bml.title=निरà¥à¤®à¤¾à¤¤à¤¾ समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी + +/directory.bml.browse.country.desc=किसी देश विशेष के चिटà¥à¤ à¥‡ पढ़ने के लिà¤, कोई देश चà¥à¤¨à¥‡à¤‚... + +/directory.bml.browse.country.title=देशानà¥à¤¸à¤¾à¤° लेखे देखें + +/directory.bml.browse.usa.desc=किसी अमरीकी राजà¥à¤¯ विशेष के चिटà¥à¤ à¥‡ पढ़ने के लिठराजà¥à¤¯ पर चटका लगाà¤à¤, या नकà¥à¤¶à¥‡ के नीचे पà¥à¤°à¤¦à¤¤à¥à¤¤ देशों के नाम में से अक पर चटका लगाà¤à¤, उस देश के लेखों को पढ़ने के लिà¤à¥¤ + +/directory.bml.browse.usa.title=अमरीकी राजà¥à¤¯à¥‹à¤‚ के अनà¥à¤¸à¤¾à¤° लेखा देखें + +/directory.bml.error.accounttype=मà¥à¤†à¤«à¤¼à¥€, या तो जिस पà¥à¤°à¤•à¤¾à¤° का आपका खाता है, उसमें निरà¥à¤¦à¥‡à¤¶à¤¿à¤•à¤¾ का पà¥à¤°à¤¯à¥‹à¤— वरà¥à¤œà¤¿à¤¤ है, अनà¥à¤¯à¤¥à¤¾ आप पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ नहीं हैं। यदि आपके खाते में निरà¥à¤¦à¥‡à¤¶à¤¿à¤•à¤¾ का पà¥à¤°à¤¯à¥‹à¤— उपलबà¥à¤§ है, तो कृपया पà¥à¤°à¤µà¥‡à¤¶ करके फिर से कोशिश करें। + +/directory.bml.navcrap.matches=[[count]] मेल + +/directory.bml.navcrap.xofy=कà¥à¤² [[totpages]] पनà¥à¤¨à¥‹à¤‚ में से पृषà¥à¤  [[curpage]] पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ किया गया (कà¥à¤°. [[reca]]-[[recb]]) + +/directory.bml.open=खोलें + +/directory.bml.post=छापें + +/directory.bml.search.monkey=सैकड़ों पà¥à¤°à¤¶à¤¿à¤•à¥à¤·à¤¿à¤¤ वानर कूद फ़ाà¤à¤¦ कर आपके खोज परिणाम निकाल रहे हैं। कृपया पà¥à¤°à¤¤à¥€à¤•à¥à¤·à¤¾ करें। + +/directory.bml.search.new=नई खोज + +/directory.bml.search.overflow=खोज परिणाम [[count]] से अधिक नहीं हो सकते। कृपया खोज को छोटा करें। + +/directory.bml.search.title=खोज जारी + +/directory.bml.update=बदलें: + +/directory.bml.user=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ + +/doc/index.bml.about=लाइवà¥à¤œà¤°à¥à¤¨à¤² के पà¥à¤°à¤²à¥‡à¤–न भणà¥à¤¡à¤¾à¤° में आपका सà¥à¤µà¤¾à¤—त है। यहाठआपको लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवा से ले के सेवक तनà¥à¤¤à¥à¤°à¤¾à¤‚श तक के बारे में जानकारी मिलेगी। कृपया निमà¥à¤¨à¥‹à¤•à¥à¤¤ सूची से विषय चà¥à¤¨à¥‡à¤‚: + +/doc/index.bml.about.header=सà¥à¤µà¤¾à¤—तमॠ+ +/doc/index.bml.docs.faq.about=लाइवà¥à¤œà¤°à¥à¤¨à¤² के बारे में सवाल जवाब + +/doc/index.bml.docs.faq.title=सवाल जवाब + +/doc/index.bml.docs.guides.about=सवाल जवाब समà¥à¤¬à¤¨à¥à¤§à¥€ अनà¥à¤¯ जानकारी + +/doc/index.bml.docs.guides.title=सहायिकाà¤à¤ + +/doc/index.bml.docs.header=पà¥à¤°à¤²à¥‡à¤– + +/doc/index.bml.docs.howto.about=लाइवà¥à¤œà¤°à¥à¤¨à¤² खाते की शकà¥à¤²à¥‹à¤¸à¥‚रत बदलने समà¥à¤¬à¤¨à¥à¤§à¥€ नà¥à¤¸à¥à¤–े + +/doc/index.bml.docs.server.about=लाइवà¥à¤œà¤°à¥à¤¨à¤² जमाव को सà¥à¤¥à¤¾à¤ªà¤¿à¤¤, पà¥à¤°à¤¬à¤¨à¥à¤§à¤¿à¤¤ व जà¥à¤—ाड़ने से समà¥à¤¬à¤¨à¥à¤§à¤¿à¤¤ जानकारी + +/doc/index.bml.docs.server.title=लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवक पà¥à¤°à¤²à¥‡à¤–न + +/doc/index.bml.docs.tour.about=नठदरà¥à¤¶à¤•à¥‹à¤‚ की सà¥à¤¥à¤² से जानपहचान बढ़ाने के लिठनिरà¥à¤®à¤¿à¤¤ + +/doc/index.bml.docs.tour.title=यातà¥à¤°à¤¾ + +/doc/index.bml.title=पà¥à¤°à¤²à¥‡à¤–न + +/doc/index.bml.volunteering.about=यदि आप लाइवà¥à¤œà¤°à¥à¤¨à¤² के पà¥à¤°à¤²à¥‡à¤–न में सहायता करना चाहते हैं, तो इन मञà¥à¤šà¥‹à¤‚ को देखें: + +/doc/index.bml.volunteering.header=सà¥à¤µà¤¯à¤‚सेवा + +/doc/index.bml.volunteering.ljsysdoc=लाइवà¥à¤œà¤°à¥à¤¨à¤² पà¥à¤°à¤²à¥‡à¤–न पà¥à¤°à¤£à¤¾à¤²à¥€ पर चरà¥à¤šà¤¾ + +/doc/index.bml.volunteering.ljuserdoc=पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं की पà¥à¤°à¤²à¥‡à¤–न समà¥à¤¬à¤¨à¥à¤§à¥€ चरà¥à¤šà¤¾ + +/doc/tour/index.bml.clients.caption=लाइवà¥à¤œà¤°à¥à¤¨à¤² गà¥à¤°à¤¾à¤¹à¤• आपके सङà¥à¤—णक पर चलने वाले छोटे कारà¥à¤¯à¤•à¥à¤°à¤® होते हैं, जिनकी मदद से जाल से जà¥à¤¡à¤¼à¥‡ होने पर आप बिना बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤° खोले अपना लेखा बदल सकते हैं। गà¥à¤°à¤¾à¤¹à¤• लगभक सभी पà¥à¤²à¥…टà¥à¤«à¤¼à¥‰à¤°à¥à¤®à¥‹à¤‚ के लिठउपलबà¥à¤§ हैं, और आसानी से परिवरà¥à¤¤à¤¨à¥€à¤¯ भी हैं। + +/doc/tour/index.bml.clients.title=गà¥à¤°à¤¾à¤¹à¤• + +/doc/tour/index.bml.comms.caption=लाइवà¥à¤œà¤°à¥à¤¨à¤² à¤à¤• बहà¥à¤¤ बड़ा समà¥à¤¦à¤¾à¤¯ है, चà¥à¤¨à¤¾à¤à¤šà¥‡ यह ताजà¥à¤œà¥à¤¬ की बात नहीं है कि कई सदसà¥à¤¯à¥‹à¤‚ की दिलà¥à¤šà¤¸à¥à¤ªà¤¿à¤¯à¤¾à¤ आपस में मेल खाती हैं। इसको मदà¥à¤¦à¥‡à¤¨à¤œà¤¼à¤° रखते हà¥à¤, हमने समà¥à¤¦à¤¾à¤¯, यानी à¤à¤¸à¥‡ लेखे जिनमें कई लोग लेख लिख सकते हैं, बनाने की सà¥à¤µà¤¿à¤§à¤¾ पेश की है। + +/doc/tour/index.bml.comms.title=समà¥à¤¦à¤¾à¤¯ + +/doc/tour/index.bml.create.caption=लाइवà¥à¤œà¤°à¥à¤¨à¤² सदसà¥à¤¯à¤¤à¤¾ आधारित लेखन समà¥à¤¦à¤¾à¤¯ है। इस पनà¥à¤¨à¥‡ से आपको पता चलेगा कि सदसà¥à¤¯à¤¤à¤¾ कà¥à¤¯à¤¾ है, यह कà¥à¤¯à¥‹à¤‚ आवशà¥à¤¯à¤• है, और सदसà¥à¤¯à¤¤à¤¾ के लाभ। इसमें अपना खाता खोलने का à¤à¤• परà¥à¤šà¤¾ भी है। + +/doc/tour/index.bml.create.title=खाता खोलना + +/doc/tour/index.bml.friends.caption="मितà¥à¤°à¤—ण" सà¥à¤µà¤¿à¤§ से, आप अपने मितà¥à¤°à¥‹à¤‚ के हालचाल पता करते रह सकते हैं। यदि आपको कोई लेखा दिलचसà¥à¤ª लगता है, तो उसे अपने मितà¥à¤°à¥‹à¤‚ की सूची में शामिल कर दें। इससे आप à¤à¤• ही पनà¥à¤¨à¥‡ पर अपने सभी मितà¥à¤°à¥‹à¤‚ की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ पढ़ सकेंगे। + +/doc/tour/index.bml.friends.title=मितà¥à¤°à¤—ण + +/doc/tour/index.bml.intro.caption=यह यातà¥à¤°à¤¾ नठदरà¥à¤¶à¤•à¥‹à¤‚ के लिठहै, ताकि वे इस सà¥à¤¥à¤² से और परिचित हों। इसमें आपको पता चलेगा कि सबसे महतà¥à¤µà¤ªà¥‚रà¥à¤£ विभाग कौन से हैं, और साथ ही कà¥à¤› और दिलचसà¥à¤ª सà¥à¤µà¤¿à¤§à¤¾à¤“ं के बारे में भी। + +/doc/tour/index.bml.intro.title=सà¥à¤µà¤¾à¤—तमॠ+ +/doc/tour/index.bml.modify.caption=आप अपने लेखे को कई तरह से पà¥à¤°à¤¾à¤°à¥‚पित कर सकते हैं, पूरà¥à¤µà¤¨à¤¿à¤°à¥à¤§à¤¾à¤°à¤¿à¤¤ शैलियों व रङà¥à¤— योजनाओं की मदद से। अपना लेखा अनोखा बनाà¤à¤! + +/doc/tour/index.bml.modify.title=वैयकà¥à¤¤à¥€à¤•à¤°à¤£ + +/doc/tour/index.bml.nav.next=अगला --> + +/doc/tour/index.bml.nav.prev=<-- पिछला + +/doc/tour/index.bml.profile.caption=लाइवà¥à¤œà¤°à¥à¤¨à¤² सदसà¥à¤¯à¥‹à¤‚ को हम पà¥à¤°à¥‡à¤°à¤¿à¤¤ करते हैं कि वे अपने बारे में और जानकारी दें, ताकि हमें पता चले कि सà¥à¤¥à¤² के पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ कौन हैं और इसका पà¥à¤°à¤¯à¥‹à¤— कौन करता है। लेकिन, इसमें से कोई भी जानकारी लाज़िमी नहीं है, लाइवà¥à¤œà¤°à¥à¤¨à¤² का पà¥à¤°à¤¯à¥‹à¤— शà¥à¤°à¥‚ करने के लिठकेवल à¤à¤• नाम, डाक पता व पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ की ज़रूरत है। + +/doc/tour/index.bml.profile.title=पारà¥à¤¶à¥à¤µ चितà¥à¤° + +/doc/tour/index.bml.sitemap.caption=आशा है कि इस यातà¥à¤°à¤¾ से आपको लाइवà¥à¤œà¤°à¥à¤¨à¤² सà¥à¤¥à¤² व सेवा के बारे में काम की जानकारी दी होगी। यदि आपको लाइवà¥à¤œà¤°à¥à¤¨à¤² से समà¥à¤¬à¤¨à¥à¤§à¤¿à¤¤ कोई भी सहायता चाहिठहो तो कृपया हमारे सहायता विभाग से समà¥à¤ªà¤°à¥à¤• करें। यदि आप और खोजबीन करना चाहते हैं, तो कृपया सà¥à¤¥à¤² मानचितà¥à¤° पर उपलबà¥à¤§ इस सà¥à¤¥à¤² के सभी पनà¥à¤¨à¥‹à¤‚ की सूची देखें। + +/doc/tour/index.bml.sitemap.title=सà¥à¤¥à¤² मानचितà¥à¤° + +/doc/tour/index.bml.support.caption=सहायता पृषà¥à¤  में उन कà¥à¤·à¥‡à¤¤à¥à¤°à¥‹à¤‚ की सूची है जिनसे पता चलता है कि लाइवà¥à¤œà¤°à¥à¤¨à¤² के बारे में अकà¥à¤¸à¤° पूछे गठसवाल जवाब कà¥à¤¯à¤¾ हैं, और साथ ही, इस सेवा, कमà¥à¤ªà¤¨à¥€ व समà¥à¤¦à¤¾à¤¯ के बारे में जानकारी भी। + +/doc/tour/index.bml.support.title=मदद माà¤à¤—ें + +/doc/tour/index.bml.title=यातà¥à¤°à¤¾ - [[title]] + +/doc/tour/index.bml.update.caption=लाइवà¥à¤œà¤°à¥à¤¨à¤² को बदलना ही लाइवà¥à¤œà¤°à¥à¤¨à¤² सेवा का मूल मनà¥à¤¤à¥à¤° है, यहीं पर तो हमारे पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं को अपने मन की बात कहने की व अपने जीवन के कà¥à¤› कà¥à¤·à¤£ हमारे साथ बिताने का मौका मिलता है। लेखा बदलना सरल है। पà¥à¤°à¤¦à¤¤à¥à¤¤ बकà¥à¤¸à¥‡ में à¤à¤• पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ लिखे, और "लेखा बदलें" वाली कà¥à¤žà¥à¤œà¥€ दबाà¤à¤à¥¤ हाà¤, हम और विकसित सà¥à¤µà¤¿à¤§à¤¾à¤à¤ भी इस पनà¥à¤¨à¥‡ पर देते हैं, जैसे वरà¥à¤¤à¤¨à¥€ की जाà¤à¤š, या अनà¥à¤¯ जानकारी, जैसे कि मौजूदा सङà¥à¤—ीत या आपका फ़िलहाल का मूड। + +/doc/tour/index.bml.update.title=बदलना + +/editinfo.bml.allowshowcontact.about=आपको यह विकलà¥à¤ª लागू करना चाहिà¤à¥¤ इसकी मदद से अनà¥à¤¯ लोग आपसे समà¥à¤ªà¤°à¥à¤• साध सकते है, लाइवà¥à¤œà¤°à¥à¤¨à¤² पर उपलबà¥à¤§ डाक पते, आई सी कà¥à¤¯à¥‚ कà¥à¤°à¤®à¤¾à¤™à¥à¤•, व ठओ à¤à¤² इंसà¥à¤Ÿà¥…णà¥à¤Ÿ मॅसॅञà¥à¤œà¤° पटनाम की मदद से + +/editinfo.bml.allowshowcontact.email=पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨à¥€à¤¯ डाक पता (यदि पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ हो तो): + +/editinfo.bml.allowshowcontact.email.actual_only=केवल असली पता + +/editinfo.bml.allowshowcontact.email.both=दोनो (असली + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=केवल लाइवà¥à¤œà¤°à¥à¤¨à¤² पता + +/editinfo.bml.allowshowcontact.email.neither=कोई भी नहीं। मेरा डाक पता पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ न करें। + +/editinfo.bml.allowshowcontact.email.no_show=डाक पता न दिखाà¤à¤ + +/editinfo.bml.allowshowcontact.email.show=डाक पता दिखाà¤à¤ + +/editinfo.bml.allowshowcontact.email.withdomainaddr<< +उपरोकà¥à¤¤ विकलà¥à¤ª की मदद से आप अपना डाक पता छिपा सकते हैं, (अनà¥à¤¯ समà¥à¤ªà¤°à¥à¤• जानकारी का पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨ बरकरार रखते हà¥à¤), या केवल लाइवà¥à¤œà¤°à¥à¤¨à¤² डाक पता पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ कर सकते हैं( केवल शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ खातों +के लिà¤), केवल असली पता दिखा सकते हैं, या दोनो दिखा सकते हैं। +. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=उपरोकà¥à¤¤ विकलà¥à¤ª की मदद से आप अपना डाक पता छिपा सकते हैं (अनà¥à¤¯ समà¥à¤ªà¤°à¥à¤• जानकारी का पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨ बरकरार रखते हà¥à¤) + +/editinfo.bml.allowshowcontact.title=अपने लाइवà¥à¤œà¤°à¥à¤¨à¤² पर समà¥à¤ªà¤°à¥à¤• जानकारी पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ करें? + +/editinfo.bml.allowshowinfo.about=यदि आप चाहते हैं कि आपका शहर/राजà¥à¤¯/देश व जनà¥à¤®à¤¦à¤¿à¤µà¤¸ सब पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾à¤“ं को पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ हो तो इसे चालू कर दें। + +/editinfo.bml.allowshowinfo.title=सà¥à¤¥à¤¾à¤¨ व जनà¥à¤®à¤¦à¤¿à¤µà¤¸ पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ करें? + +/editinfo.bml.autotranslate.about=इस विकलà¥à¤ª की मदद से आप लाइवà¥à¤œà¤°à¥à¤¨à¤² को यह बता सकते हैं कि सà¥à¤¥à¤² को यूनीकोड में परिवरà¥à¤¤à¤¿à¤¤ करने के पहले की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¥‹à¤‚ के लिठकौन सा कूटबनà¥à¤§à¤¨ मान कर चला जाà¤à¥¤ यदि आप अङà¥à¤—à¥à¤°à¥‡à¤œà¤¼à¥€ में लिखते हैं, तो यहाठपर "Western European" चà¥à¤¨à¥‡à¤‚। + +/editinfo.bml.autotranslate.header=पà¥à¤°à¤¾à¤¨à¥€ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¥‹à¤‚ को यहाठसे सà¥à¤µà¤¤à¤ƒ परिवरà¥à¤¤à¤¿à¤¤ करें: + +/editinfo.bml.bday.title=जनà¥à¤®à¤¦à¤¿à¤µà¤¸ + +/editinfo.bml.bday.year.opt=वरà¥à¤· वैकलà¥à¤ªà¤¿à¤• है + +/editinfo.bml.bdayreminders.about=यदि आप लाइवà¥à¤œà¤°à¥à¤¨à¤² मितà¥à¤°à¥‹à¤‚ के जनà¥à¤®à¤¦à¤¿à¤µà¤¸à¥‹à¤‚ की याद दिलाने वाली डाक पाना चाहते हैं, तो इस बकà¥à¤¸à¥‡ पर सही का निशान लगाà¤à¤à¥¤ + +/editinfo.bml.bdayreminders.header=जनà¥à¤®à¤¦à¤¿à¤µà¤¸à¥‹à¤‚ की याद दिलाà¤à¤ (फ़िलहाल अनà¥à¤ªà¤²à¤¬à¥à¤§) + +/editinfo.bml.bio.about=यहाठपर आप अपनी à¤à¤• छोटी सी आतà¥à¤®à¤•à¤¥à¤¾ लिख सकते हैं। यद आपके पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ जानकारी पृषà¥à¤  पर पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ होगी। + +/editinfo.bml.bio.header=आपके बारे में + +/editinfo.bml.blockrobots.about=यदि आप इस विकलà¥à¤ª पर सही का निशान लगाते हैं, तो रोबोटों को कहा जाà¤à¤—ा कि वे यहाठन आà¤à¤à¥¤ लेकिन सभी रोबोट नियमों का पालन नहीं करते हैं। + +/editinfo.bml.blockrobots.header=आपके लेखे को रोबोटों/सà¥à¤ªà¤¾à¤‡à¤¡à¤°à¥‹à¤‚ दà¥à¤µà¤¾à¤°à¤¾ अपने सूचकाङà¥à¤• में डालने की अनà¥à¤®à¤¤à¤¿ न दें। + +/editinfo.bml.chat.aolim.title=ठओ à¤à¤² आई à¤à¤® + +/editinfo.bml.chat.icquin.title=आई सी कà¥à¤¯à¥‚ यू आई à¤à¤¨ + +/editinfo.bml.chat.jabber.title=जॅबर + +/editinfo.bml.chat.msnusername.title=à¤à¤® à¤à¤¸ à¤à¤¨ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम + +/editinfo.bml.chat.yahooid.title=याहू! आई डी + +/editinfo.bml.city.title=शहर + +/editinfo.bml.country.choose=देश चà¥à¤¨à¥‡à¤‚ + +/editinfo.bml.country.title=देश + +/editinfo.bml.donotlog=नहीं + +/editinfo.bml.email.title=डाक पता + +/editinfo.bml.enableboards.about=यदि आप चाहते हैं कि आपके दà¥à¤µà¤¾à¤°à¤¾ छापे गठलेखों पर लोग टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤ लिख सकें, तो इस पर सही का निशान लगाà¤à¤à¥¤ + +/editinfo.bml.enableboards.header=सनà¥à¤¦à¥‡à¤¶ पट लागू करें + +/editinfo.bml.encoding.about=इसकी चिनà¥à¤¤à¤¾ न करें। यहाठकेवल उनà¥à¤¹à¥€à¤‚ अनà¥à¤¤à¤°à¥à¤°à¤¾à¤·à¥à¤Ÿà¥à¤°à¥€à¤¯ लेखकों को कà¥à¤› बदलना होगा, जो कई भाषाओं में लिखते हैं। + +/editinfo.bml.encoding.header=कूटबनà¥à¤§à¤¨ विकलà¥à¤ª + +/editinfo.bml.error.day.notinmonth=इस मास के लिठयह दिन अवैध है। + +/editinfo.bml.error.day.outofrange=जनà¥à¤®à¤¦à¤¿à¤µà¤¸ अवैध। 1-31 के बीच का दिन पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain=आप @[[domain]] डाक पता पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ नहीं कर सकते। इस खाने में अपना असली पता पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। यदि आप शà¥à¤²à¥à¤•à¤¦à¤¤à¥à¤¤ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ हैं, तो [[user]]@[[domaon]] पते पर पà¥à¤°à¤¾à¤ªà¥à¤¤ डाक असली पते पर अगà¥à¤°à¥‡à¤·à¤¿à¤¤ कर दी जाà¤à¤—ी। कौन सा पता (या दोनो) सारà¥à¤µà¤œà¤¨à¤¿à¤• रूप से पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ किठजाà¤à¤, यह चà¥à¤¨à¤¨à¥‡ के लिठ"समà¥à¤ªà¤°à¥à¤• सूचना दरà¥à¤¶à¤¾à¤à¤" के नीचे वाला विकलà¥à¤ª देखें। + +/editinfo.bml.error.email.none=डाक पता पà¥à¤°à¤¦à¤¾à¤¨ करना अनिवारà¥à¤¯ है + +/editinfo.bml.error.email.no_space=डाक पते में खाली सà¥à¤¥à¤¾à¤¨ वरà¥à¤œà¤¿à¤¤ हैं। यदि आप ठओ à¤à¤² पर हैं, तो याद रखें कि आपका अनà¥à¤¤à¤°à¥à¤œà¤¾à¤² डाक पता है, सभी खाली सà¥à¤¥à¤¾à¤¨ हटाने के बाद आपका पटनाम, अनà¥à¤¤ में @aol.com ठओ à¤à¤² लगा कर। + +/editinfo.bml.error.excessive_int=मà¥à¤†à¤«à¤¼à¥€, आपने बहà¥à¤¤ अदिक रà¥à¤šà¤¿à¤¯à¤¾à¤ सूचित की हैं। इसकी सीमा है 150, पर आपने [[intcount]] सूचित की हैं। यदि आपने रà¥à¤šà¤¿à¤¯à¥‹à¤‚ में परिवरà¥à¤¤à¤¨ किठथे, तो वे सà¤à¤œà¥‹à¤ नहीं गठहैं। वापस जा के सूची की पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¤¾à¤ कम करें, और फिर सà¤à¤œà¥‹à¤à¤à¥¤ + +/editinfo.bml.error.invalidbio=आपके सà¤à¤œà¥‹à¤ˆ गई आतà¥à¤®à¤•à¤¥à¤¾ में अवैध अकà¥à¤·à¤° है। आपको परिवरà¥à¤¤à¤• पृषà¥à¤  पर जा कर इनà¥à¤¹à¥‡à¤‚ यूनिकोड में परिवरà¥à¤¤à¤¿à¤¤ करना होगा। + +/editinfo.bml.error.invalidints=आपकी फ़िलहाल सà¤à¤œà¥‹à¤ˆ हà¥à¤ˆ रà¥à¤šà¤¿à¤¯à¥‹à¤‚ की सूची में अवैध अकà¥à¤·à¤° हैं। कृपया यूनिकोड में परिवरà¥à¤¤à¤¿à¤¤ करने के लिठपरिवरà¥à¤¤à¤¨ पृषà¥à¤  पर जाà¤à¤à¥¤ + +/editinfo.bml.error.invalidname=आपके नाम में अवैध अकà¥à¤·à¤° हैं। कृपया यूनिकोड में परिवरà¥à¤¤à¤¿à¤¤ करने के लिठपरिवरà¥à¤¤à¤¨ पृषà¥à¤  पर जाà¤à¤à¥¤ + +/editinfo.bml.error.locale.country_ne_state=आपने देश का नाम संयà¥à¤•à¥à¤¤ राजà¥à¤¯ पà¥à¤°à¤¦à¤¾à¤¨ किया है, किनà¥à¤¤à¥ "अनà¥à¤¯ राजà¥à¤¯" खाने में à¤à¤¸à¤¾ राजà¥à¤¯ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ किया है जो संयà¥à¤•à¥à¤¤ राजà¥à¤¯ में नहीं है। + +/editinfo.bml.error.locale.invalid_country=देश का नाम अवैध है। + +/editinfo.bml.error.locale.state_ne_country=आपने देश तो संयà¥à¤•à¥à¤¤ राजà¥à¤¯ नहीं चà¥à¤¨à¤¾ है, किनà¥à¤¤à¥ राजà¥à¤¯ संयà¥à¤•à¥à¤¤ राजà¥à¤¯ का चà¥à¤¨à¤¾ है। + +/editinfo.bml.error.locale.zip_ne_state=पà¥à¤°à¤¦à¤¤à¥à¤¤ ज़िप कोड राजà¥à¤¯ के साथ मेल नहीं खाता। या तो जानकारी को सही करें, अथवा, राजà¥à¤¯, ज़िप कोड या दोनों की ही पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ हटा दें। + +/editinfo.bml.error.locale.zip_requires_us=आपने ज़िप कोड पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ किया है किनà¥à¤¤à¥ देश संयà¥à¤•à¥à¤¤ राजà¥à¤¯ नहीं चà¥à¤¨à¤¾ है। हम केवल संयà¥à¤•à¥à¤¤ राजà¥à¤¯ के पà¥à¤°à¤µà¤¾à¤¸à¤¿à¤¯à¥‹à¤‚ के ज़िप कोड à¤à¤•à¤¤à¥à¤°à¤¿à¤¤ करते हैं। कृपया वापस जा के ज़िप कोड का कोषà¥à¤ à¤• रिकà¥à¤¤ करें अथवा संयà¥à¤•à¥à¤¤ राजà¥à¤¯ को अपना देश चà¥à¤¨à¥‡à¤‚। + +/editinfo.bml.error.month.outofrange=जनà¥à¤®à¤¦à¤¿à¤µà¤¸ मास अवैध। 1-12 (जन.-दिस) के बीच का मास चà¥à¤¨à¥‡à¤‚। + +/editinfo.bml.error.noname=नाम पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करना अनिवारà¥à¤¯ है। कम से कम à¤à¤• नाम, या छदà¥à¤®à¤¨à¤¾à¤® ही पà¥à¤°à¤¦à¤¾à¤¨ करें। + +/editinfo.bml.error.tm.require.number=यदि आप पाठà¥à¤¯ सनà¥à¤¦à¥‡à¤¶à¥‹à¤‚ का पà¥à¤°à¤¯à¥‹à¤— करेंगे तो, दूरभाष सङà¥à¤–à¥à¤¯à¤¾ भी पà¥à¤°à¤¦à¤¾à¤¨ करें। + +/editinfo.bml.error.tm.require_provider=यदि आप पाठà¥à¤¯ सनà¥à¤¦à¥‡à¤¶à¥‹à¤‚ का पà¥à¤°à¤¯à¥‹à¤— करेंगे, तो आपको सेवा पà¥à¤°à¤¦à¤¾à¤¤à¤¾ भी चनना होगा। यदि आपका सेवा पà¥à¤°à¤¦à¤¾à¤¤à¤¾ सूची में नहीं है, तो कृपया इसकी जानकारी हमें पà¥à¤°à¤¦à¤¾à¤¨ करें ताकि हम यह सà¥à¤µà¤¿à¤§à¤¾ इसके लिठभी पà¥à¤°à¤¦à¤¾à¤¨ कर सकें। + +/editinfo.bml.error.year.notenoughdigits=अवैध जनà¥à¤®à¤¦à¤¿à¤µà¤¸ वरà¥à¤·à¥¤ 4 सङà¥à¤–à¥à¤¯à¤¾à¤“ं का वरà¥à¤· पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/editinfo.bml.error.year.outofrange=अवैध जनà¥à¤®à¤¦à¤¿à¤µà¤¸ वरà¥à¤·à¥¤ + +/editinfo.bml.finished.about=समà¥à¤ªà¥‚रà¥à¤£ होने के उपरानà¥à¤¤ निमà¥à¤¨à¥‹à¤•à¥à¤¤ "परिवरà¥à¤¤à¤¨ सà¤à¤œà¥‹à¤à¤" वाली कà¥à¤žà¥à¤œà¥€ दबाà¤à¤à¥¤ + +/editinfo.bml.finished.header=समà¥à¤ªà¥‚रà¥à¤£? + +/editinfo.bml.finished.save_button=परिवरà¥à¤¤à¤¨ सà¤à¤œà¥‹à¤à¤ + +/editinfo.bml.gender.title=लिङà¥à¤— + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=सूचना पटों पर आपकी लेखा पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¯à¥‹à¤‚ के ऊपर टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤ मिलने पर यदि आप डाक से सूचना चाहते हैं तो इस पर सही का निशान लगाà¤à¤à¥¤ + +/editinfo.bml.getreplies.header=सूचना पट से टिपà¥à¤ªà¤£à¤¿à¤¯à¤¾à¤ पà¥à¤°à¤¾à¤ªà¥à¤¤ करें + +/editinfo.bml.hidefriendof.about=यदि आप इस पर सही का निशान लगाते हैं आपको मितà¥à¤° घोषित करने वाले वà¥à¤¯à¤•à¥à¤¤à¤¿à¤¯à¥‹à¤‚ की सूची आपके जानकारी पृषà¥à¤  पर पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ नहीं होगी। + +/editinfo.bml.hidefriendof.header="इनका मितà¥à¤°" सूची छिपाà¤à¤ + +/editinfo.bml.howhear.about<< +हम यह जानने के लिठउतà¥à¤¸à¥à¤• हैं कि आपने [[sitename]] के बारे में कहाठसे सà¥à¤¨à¤¾? +यदि किसी वà¥à¤¯à¤•à¥à¤¤à¤¿à¤µà¤¿à¤¶à¥‡à¤· न बताया तो उनका पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें; यदि किसी और सà¥à¤°à¥‹à¤¤/लेख/कड़ी/सà¥à¤¥à¤² से पता चला, तो उपयà¥à¤•à¥à¤¤ जानकारी पà¥à¤°à¤¦à¤¾à¤¨ करें। +. + +/editinfo.bml.howhear.header=कौतूहल + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about=जाà¤à¤šà¥‡, आपका डाक कारà¥à¤¯à¤•à¥à¤°à¤® डाक में पूरà¥à¤£à¤¤à¤ƒ à¤à¤š टी à¤à¤® à¤à¤² पà¥à¤°à¤¦à¤¾à¤¨ करता है या नहीं। अधिकतर गà¥à¤°à¤¾à¤¹à¤• कोशिश करते हैं, लेकिन असफल रहते हैं। यदि आप इस पर सही का निशान नहीं लगाते हैं तो लाइवà¥à¤œà¤°à¥à¤¨à¤² केवल पाठà¥à¤¯ सनà¥à¤¦à¥‡à¤¶ भेजेगा। + +/editinfo.bml.htmlemail.header=à¤à¤š टी à¤à¤® à¤à¤² डाक भेजें + +/editinfo.bml.int.header=रà¥à¤šà¤¿à¤¯à¤¾à¤ + +/editinfo.bml.login.enterinfo=वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त जानकारी परिवरà¥à¤¤à¤¿à¤¤ करने के लिठपà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम व पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ करें। + +/editinfo.bml.login.forgot.header=कà¥à¤› भूल गà¤? + +/editinfo.bml.login.forgot.recover=यदि आप अपना पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ नाम या पà¥à¤°à¤µà¥‡à¤¶ शबà¥à¤¦ भूल गठहैं, तो यहाठसे पà¥à¤°à¤¾à¤ªà¥à¤¤ करें!। + +/editinfo.bml.logip.always=हमेशा + +/editinfo.bml.newemail.subject=डाक पता परिवरà¥à¤¤à¤¿à¤¤à¥¤ + +/editinfo.bml.optional=वैकलà¥à¤ªà¤¿à¤• + +/editinfo.bml.opt_in.header=मà¥à¤à¥‡ लाइवà¥à¤œà¤°à¥à¤¨à¤² समाचार भेजें + +/editinfo.bml.persinfo.header=वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त जानकारी + +/editinfo.bml.screen.all=सभी + +/editinfo.bml.screen.anon=अजà¥à¤žà¤¾à¤¤ + +/editinfo.bml.security.visibility.everybody=सभी + +/editinfo.bml.security.visibility.friends=केवल मितà¥à¤° + +/editinfo.bml.security.visibility.regusers=पञà¥à¤œà¥€à¤•à¥ƒà¤¤ पà¥à¤°à¤¯à¥‹à¤•à¥à¤¤à¤¾ + +/editinfo.bml.state.us=अमरीकी राजà¥à¤¯ + +/editinfo.bml.success.header=सफल! + diff --git a/ljcom/bin/upgrading/hu.dat b/ljcom/bin/upgrading/hu.dat new file mode 100644 index 0000000..040a754 --- /dev/null +++ b/ljcom/bin/upgrading/hu.dat @@ -0,0 +1,3473 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Ha törölni szeretnéd a naplódat, vagy éppen visszavonni a napló törlését, itt teheted meg. Ha törölted a naplódat és meggondoltad magad, 30 nap áll rendelkezésedre a törlés visszavonásához. A 30 nap elteltével a naplót véglegesen töröljük, ezután a törlés visszavonása már nem lehetséges. + +/accountstatus.bml.journalstatus.head=A napló aktiválási állapota + +/accountstatus.bml.journalstatus.select.activated=Aktiválva + +/accountstatus.bml.journalstatus.select.deleted=Törölve + +/accountstatus.bml.journalstatus.select.head=Ãllapot: + +/accountstatus.bml.journalstatus.select.suspended=Felfüggesztve + +/accountstatus.bml.title=Fiók állapota + +/allpics.bml.current=Jelenlegi képek + +/allpics.bml.default=Alapértelmezett + +/allpics.bml.edit2=Ha kedved van hozzá, akkor ezeken az oldalakon átírhatod a képeid kulcsszavait, vagy feltölthetsz egy új képet. + +/allpics.bml.error.noparam=Meg kell adnod egy felhasználót paraméterként. + +/allpics.bml.keywords=Kulcsszavak: + +/allpics.bml.nopics.text.other=A felhasználónak nincsenek képei feltöltve. + +/allpics.bml.nopics.text2=Nincs még képed feltöltve. Képeket itt lehet feltölteni. + +/allpics.bml.nopics.title=Nincs kép + +/allpics.bml.pics=Itt látható [[user]] összes feltöltött képe: + +/allpics.bml.title=Felhasználó képei + +/approve.bml.comm.success=Siker + +/approve.bml.comm.text<< +Mostantól fel vagy véve [[comm]] közösségbe. +Kattints ide, ha ezt a közösséget fel szeretnéd venni barátaid listájára. + +. + +/approve.bml.error.internerr.invalidaction=BelsÅ‘ hiba történt: érvénytelen művelet + +/approve.bml.shared.success=Siker + +/approve.bml.shared.text<< +Bejegyzési jogot kaptál [[shared]] naplóba. +Kattints ide, ha fel akarod venni ezt a közös naplót barátaid listájára. + +. + +/birthdays.bml.description=Lent láthatod barátaid szülinapját. + +/birthdays.bml.title=Születésnapok + +/changepassword.bml.btn.proceed=Tovább + +/changepassword.bml.changepassword.header=Jelszó módosítása + +/changepassword.bml.changepassword.instructions=Töltsd ki az alant látható mezÅ‘ket a jelszavad megváltoztatásához. Hogy milyen a jó jelszó, arról bÅ‘vebben itt olvashatsz. + +/changepassword.bml.email.body<< +[[sitename]] helyhez tartozó jelszavad megváltozott. + +Ha a jövÅ‘ben szükséged lenne rá, látogasd meg a következÅ‘ helyet: + + [[siteroot]]/lostinfo.bml + +Ãœdvözlettel: +[[sitename]] Csapat +[[siteroot]] + +. + +/changepassword.bml.error.badcheck=Hibás új jelszó: [[error]] + +/changepassword.bml.error.badoldpassword=A régi jelszavad nem egyezik. + +/changepassword.bml.error.blankpassword=Új jelszavad nem lehet üres. + +/changepassword.bml.error.changetestaccount=A teszt fiók jelszavát nem lehet megváltoztatni. + +/changepassword.bml.error.characterlimit=A jelszavak maximum 30 karakteresek lehetnek. + +/changepassword.bml.error.invaliduser=[[user]] nem létezÅ‘ felhasználó. Biztos jól gépelted be? + +/changepassword.bml.error.mustenterusername=Be kell írnod a felhasználói nevedet. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Nem változtathatod meg a jelszavad, ha az e-mail címedet még nem érvényesítetted. + +/changepassword.bml.newpassword=Új jelszó: + +/changepassword.bml.newpasswordagain=Új jelszó (ismét): + +/changepassword.bml.oldpassword=Régi jelszó: + +/changepassword.bml.proceed.instructions=A jelszavad megváltoztatásához nyomd meg az alábbi gombot. A módosításról küldeni fogunk egy nyugtázó e-mailt. + +/changepassword.bml.success.text=A jelszavad megváltoztattuk, és küldtünk egy emlékeztetÅ‘ e-mailt a címedre. + +/changepassword.bml.title=Jelszó módosítása + +/community/index.bml.title=Közösségközpont + +/community/join.bml.button.join=Belépés a közösségbe + +/community/join.bml.label.addtofriends=[[maintainer]] felvétele a barátlistára.
        + +/community/join.bml.label.allowposting=Ez a közösség megengedi, hogy minden tagja írhasson a naplóba, tehát most már neked is van hozzáférésed. Amennyiben már futtatsz egy LiveJournal kliensprogramot a számítógépeden, ahhoz, hogy ez a napló is megjelenjen a kliens listáján, ki, majd újra be kell jelentkezned vele. + +/community/join.bml.label.auth=Bár most már tagja vagy a közösségnek, az itteni szabályok alapján csak akkor lesz írási jogod a naplóba, amikor ezt a közösségnapló karbantartója engedélyezi. E felÅ‘li igényedrÅ‘l értesítsd az következÅ‘ felhasználók valamelyikét: [[admins]] + +/community/join.bml.label.banned=A közösségnapló karbantartója eltiltott a csatlakozástól. + +/community/join.bml.label.closed=Ez egy zárt közösség. A csatlakozással kapcsolatban vedd fel a kapcsolatot a közösség vezetÅ‘ivel, itt vannak a neveik: [[admins]] + +/community/join.bml.label.commlogged=Közösségi fiókba vagy bejelentkezve, nem a személyes fiókodba. + +/community/join.bml.label.errorcomminfo=A megadott közösséginformáció hibás. + +/community/join.bml.label.expls=Kattints az alábbi gombra a [[maintainer]] közösségbe való belépéshez. Hagyd üresen a következÅ‘ rublikát, ha nem akarod, hogy a közösségbe való belépés után a közösségi bejegyzések megjelenjenek naplód barát-nézetében! + +/community/join.bml.label.loginfirst=Ahhoz, hogy belépj egy közösségbe, elÅ‘ször be kell jelentkezned. + +/community/join.bml.label.membernow=Mostantól tagja vagy a [[commname]] közösségnek. + +/community/join.bml.label.sure=Biztos? + +/community/join.bml.success=Sikerült + +/community/join.bml.title=Belépés a közösségbe + +/community/leave.bml.button.leave=Közösség elhagyása + +/community/leave.bml.label.buttontoleave=Kattints az alábbi gombra, hogy elhagyd a „[[commname]]†közösséget! + +/community/leave.bml.label.infoerror=A megadott közösséginformáció hibás. + +/community/leave.bml.label.logoutfirst=Ahhoz, hogy elhagyj egy közösséget, elÅ‘ször be kell jelentkezned. + +/community/leave.bml.label.removed=Mostantól törölve vagy a [[commname]] közösségbÅ‘l. + +/community/leave.bml.label.removefromfriends=Töröld "[[user]]"-t a barátok listájáról. + +/community/leave.bml.success=Siker + +/community/leave.bml.sure=Biztos? + +/community/leave.bml.title=Kilépés a közösségbÅ‘l + +/community/manage.bml.commlist.actinfo=Információ + +/community/manage.bml.commlist.actions=Intézkedések + +/community/manage.bml.commlist.actmembers=[Tagok] + +/community/manage.bml.commlist.actmembers2=Tagok + +/community/manage.bml.commlist.actsettings=[Beállítások] + +/community/manage.bml.commlist.actsettings2=Beállítások + +/community/manage.bml.commlist.header=Közösségeid + +/community/manage.bml.commlist.none=Jelenleg nem vezetsz egy közösséget sem. + +/community/manage.bml.commlist.text=Ezeknek a közösségeknek te vagy a vezetÅ‘je vagy társvezetÅ‘je: + +/community/manage.bml.commlist.title=Cím + +/community/manage.bml.commlist.username=Felhasználó név + +/community/manage.bml.create.header=Közösség létrehozása + +/community/manage.bml.create.text=Itt létrehozhatsz egy új közösséget is. + +/community/manage.bml.title=Közösség Vezetés + +/community/members.bml.error.noaccess=Csak a közösség vezetÅ‘i tudják megváltoztatni a tagsági listát. Mivel te nem vagy a [[comm]] közösség vezetÅ‘je, neked nincs ilyen jogod. + +/community/members.bml.error.nocomm=Közösség nem lézezik. + +/community/members.bml.error.nouser=Nincs ilyen felhasználó: [[user]] + +/community/members.bml.key.admin=VezetÅ‘ + +/community/members.bml.key.member=Tag + +/community/members.bml.key.moderate=FelügyelÅ‘ + +/community/members.bml.key.post=Ãrási jog + +/community/members.bml.key.preapprove=Nincs felügyelve + +/community/members.bml.manage2=Közösségek vezetése + +/community/members.bml.name=Közösség neve: [[name]] + +/community/members.bml.nextlink=(KövetkezÅ‘ oldal...) + +/community/members.bml.prevlink=(ElÅ‘zÅ‘ oldal...) + +/community/members.bml.settings=[Beállítások] + +/community/members.bml.success.header=Siker + +/community/members.bml.success.message=A változtatásaid sikeresen el lettek mentve. + +/community/members.bml.success.return=Visszatérés a listához + +/community/members.bml.title=Közösség Tagjai + +/community/members.bml.update=Beállítások frissítése + +/community/moderate.bml.approve.button=Igen, jóváhagyom + +/community/moderate.bml.approve.header=Jóváhagyod ezt a bejegyzést? + +/community/moderate.bml.approve.preapprove=[[user]] nevű felhasználó hozzáadása ennek a közösségnek az "elÅ‘re-jóváhagyott felhasználók" listájához. + +/community/moderate.bml.approve.text=Biztos, hogy jóvá akarod hagyni ezt a bejegyzést? + +/community/moderate.bml.brlist.actions=Intézkedések + +/community/moderate.bml.brlist.poster=Hozzászóló + +/community/moderate.bml.brlist.subject=Téma kezdÅ‘dik + +/community/moderate.bml.brlist.time=IdÅ‘ + +/community/moderate.bml.brlist.view=Nézet + +/community/moderate.bml.browse.empty=A felügyelési sor üres. + +/community/moderate.bml.browse.header=Közösség Felügyelése + +/community/moderate.bml.browse.text=Itt található a közösség felügyelési sora [[link]] + +/community/moderate.bml.choice.approve=Jóváhagy + +/community/moderate.bml.choice.reject=Visszautasít + +/community/moderate.bml.error.noaccess=Te nem felügyeled a [[comm]] nevű közösséget. + +/community/moderate.bml.error.noentry=Ilyen bejegyzés nem található (lehet, hogy egy másik felügyelÅ‘ már gondoskodik/gondoskodott róla). + +/community/moderate.bml.error.nolist=Nem felügyelsz egy közösséget sem. + +/community/moderate.bml.error.notfound=Közösségi fiók nem található. + +/community/moderate.bml.manage=Közösségek vezetése + +/community/moderate.bml.moderate=Ennek a közösségnek a felügyelése + +/community/moderate.bml.modlist.actions=Intézkedések + +/community/moderate.bml.modlist.actmodempty=[Felügyelés] + +/community/moderate.bml.modlist.actmoderate=Felügyelés + +/community/moderate.bml.modlist.count=A várósor mérete + +/community/moderate.bml.modlist.header=Közösségek Felügyelése + +/community/moderate.bml.modlist.title=Cím + +/community/moderate.bml.modlist.username=Felhasználó név + +/community/moderate.bml.posted.appheader=ElÅ‘re-Jóváhagyva + +/community/moderate.bml.posted.apptext=Továbbá, a [[user]] nevű felhasználó hozzá lett adva ennek a közösségnek az "elÅ‘re-jóváhagyott felhasználók" listájához. + +/community/moderate.bml.posted.header=Siker + +/community/moderate.bml.posted.proterror=Ezt a bejegyzést nem sikerült elküldeni a következÅ‘ protokoll hiba miatt: [[err]] + +/community/moderate.bml.posted.text=A bejegyzés sikeresen ki lett függesztve. + +/community/moderate.bml.reject.button=Igen, visszautasítom + +/community/moderate.bml.reject.header=Visszautasítod ezt a bejegyzést? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=Amennyiben szükséget érzel rá, meg is magyarázhatod a hozzászólónak, hogy mért utasítottad vissza a bejegyzését. Ezt az üzeneteded a szerver ezután emailben továbbítja neki. + +/community/moderate.bml.reject.text=Biztos, hogy vissza akarod utasítani ezt a bejegyzést? + +/community/moderate.bml.rejected.header=Visszautasítva + +/community/moderate.bml.rejected.text=A bejegyzés vissza lett utasítva. + +/community/moderate.bml.title=Közösség Felügyelés + +/community/search.bml.button.clear=Az űrlap kitörlése + +/community/search.bml.button.search=Keress! + +/community/search.bml.checkbox.onlywithpics=Csak képekkel rendelkezÅ‘ közösségek + +/community/search.bml.label.byinterest=ÉrdeklÅ‘dés szerint + +/community/search.bml.label.bylocation=Földrajzi hely szerint + +/community/search.bml.label.bytime=Napló utolsó frissítése szerint + +/community/search.bml.label.city=Város: + +/community/search.bml.label.country=Ország: + +/community/search.bml.label.displayoptions=Megjelenítési beállítások + +/community/search.bml.label.hasmember=Tagok + +/community/search.bml.label.othercriteria=Egyéb kritérium + +/community/search.bml.label.outputformat=Kimeneti formátum: + +/community/search.bml.label.records=Oldalanként megjelenített találatok száma: + +/community/search.bml.label.searchcomm=Közösségek keresése + +/community/search.bml.label.selecriteria=Az alábbi űrlapon állítsd be azokat a kritériumokat, amelyek alapján közösségeket szeretnél találni. A keresÅ‘ ezután olyan közösségeket fog keresni és listázni, melyek minden általad beállított kritériumnak megfelelnek. Más szóval, minden általad kitöltött mezÅ‘ közötti kapcsolat a keresés során „ÉSâ€, nem pedig „VAGYâ€. + +/community/search.bml.label.sortmethod=Rendezési módszer: + +/community/search.bml.label.stateprovince=Ãllam, tartomány: + +/community/search.bml.label.updated=Frissítették az elÅ‘zÅ‘ + +/community/search.bml.sel.bypicture=Kép szerint + +/community/search.bml.sel.communityname=Közösség neve + +/community/search.bml.sel.commview=Közösségi nézet + +/community/search.bml.sel.day=napon + +/community/search.bml.sel.month=hónapban + +/community/search.bml.sel.simple=Egyszerű + +/community/search.bml.sel.updatetime=Frissítés ideje + +/community/search.bml.sel.username=Felhasználónév + +/community/search.bml.sel.week=héten + +/community/search.bml.title=Közösségkeresés + +/community/settings.bml.button.changecommunity=Beállítások Frissítése + +/community/settings.bml.button.createcommunity=Közösség Létrehozása + +/community/settings.bml.error.badpassword=Érvénytelen közösségi jelszó + +/community/settings.bml.error.hasentries=Ennek a fióknak már van bejegyzései és ezért nem változtathatsz közösséggé. + +/community/settings.bml.error.maintainertype=A vezetÅ‘ fiók nem jöhet létre megosztott fiókból, csak egy személy saját fiókja lehet. + +/community/settings.bml.error.noaccess=Csak a közösség vezetÅ‘i változtathatják meg a közösségi beállításokat. Neked nincs ilyen jogod, mert nem vagy a [[comm]] közösség vezetÅ‘je. + +/community/settings.bml.error.notcomm=Nem egy közösségi fiók. + +/community/settings.bml.error.notfound=Közösségi fiók nem található. + +/community/settings.bml.error.samenames=A vezetÅ‘ fiók és a közösségi fiók neve nem lehet ugyanaz. + +/community/settings.bml.label.anybodycan=Az Összes Tag
        Bárki írhat ide új bejegyzést, amint taggá válik. + +/community/settings.bml.label.changeheader=Közösségi beállítások módosítása + +/community/settings.bml.label.changetext=Itt megváltoztathatod a te közösséged vagy az általad vezetett közösség beállításait. + +/community/settings.bml.label.commchanged=A közösségi beállításaid megváltoztak. + +/community/settings.bml.label.commcreate=Ez az a fiók, amelyet egy közösséggé akarsz változtatni. Szükséges, hogy ez a fiók már létre legyen hozva, de még senki által nem lehet használva, mert miután közösséggé alakul, már sok különböző embernek lesz benne lehetősége bejegyzéseket írni. + +/community/settings.bml.label.commcreated=A közösséged most már be van állítva. + +/community/settings.bml.label.commheader=Közösségi Fiók + +/community/settings.bml.label.comminfo=Közösségi információ + +/community/settings.bml.label.commopts=Közösségi Opciók + +/community/settings.bml.label.commsite=Közösségi weboldal + +/community/settings.bml.label.community=Közösség: + +/community/settings.bml.label.createheader=Közösség Létrehozása + +/community/settings.bml.label.createtext=Innen lehetőséged nyílik egy közösségi fiók létrehozására. A "közösség" egy speciális fiók-fajta, amelybe más felhasználók is beléphetnek és bejegyzéseket írhatnak. Ha látni akarsz egy példát arra, hogy milyen egy közösség, akkor látogasd meg például a Seattle Party Közösséget. + +/community/settings.bml.label.howoperates=Válaszd ki, hogyan működjön a közösséged. Ezeket később bármikor megváltoztathatod: + +/community/settings.bml.label.maintainer=Vezető: + +/community/settings.bml.label.maintainer.login=Ha ez nem a vezető fiókja, jelentkezz be valami más név alatt. + +/community/settings.bml.label.membership=Tagság + +/community/settings.bml.label.modheader=Felügyelés + +/community/settings.bml.label.modis=Felügyelve
        Az új bejegyzéseket egy felügyelőnek jóvá kell hagynia. + +/community/settings.bml.label.modisnt=Nincs felügyelve
        Az új bejegyzések azonnal megjelennek. + +/community/settings.bml.label.modtext=Felügyeli valaki az ebbe a közösségbe küldött bejegyzéseket/hozzászólásokat? + +/community/settings.bml.label.nmcan=Nem-Tagok is Ãrhatnak Bejegyzést
        A felhasználók írhatnak ide bejegyzéseket, anélkül, hogy beléptek volna ebbe a közösségbe. + +/community/settings.bml.label.nmcant=Nem-Tagok Nem Ãrhatnak Bejegyzéseket
        A felhasználóknak be kell lépniük ebbe a közösségbe, ahhoz, hogy bejegyzéseket írhassanak bele. + +/community/settings.bml.label.nmheader|staleness=1 +/community/settings.bml.label.nmheader=Tagság nélküli bejegyzés-írás + +/community/settings.bml.label.nmtext=A felhasználók a közösségbe való belépés nélkül is írhatnak bele bejegyzéseket? + +/community/settings.bml.label.openmemb=Nyílt Tagság
        Bárki beléphet, anélkül, hogy ezt jóvá kellene hagyni. + +/community/settings.bml.label.password=Jelszó + +/community/settings.bml.label.postaccess=Ãrási Jog + +/community/settings.bml.label.rellinks=Ide kapcsolódó fontosabb linkek: + +/community/settings.bml.label.selcan=Kiválasztott Tagok
        Csak néhány tagnak van bejegyzés-író joga, miután a vezetÅ‘ fiók biztosította számukra a hozzáférést. + +/community/settings.bml.label.username=Felhasználó név + +/community/settings.bml.label.whocanjoin=Ki csatlakozhat a közösségedbe? + +/community/settings.bml.label.whocanpost=Ki írhat bejegyzéseket ebbe a közösségbe? + +/community/settings.bml.manage2=Közösségek vezetése + +/community/settings.bml.members=Tagok] + +/community/settings.bml.name=Közösség neve: [[name]] + +/community/settings.bml.success=Siker + +/community/settings.bml.title.create=Közösség Létrehozása + +/community/settings.bml.title.modify=Közösségi Beállítások + +/create.bml.age.check.question=Elmúltál már 13 éves? + +/create.bml.age.check.yes=Nem, még nem múltam el 13. + +/create.bml.age.check2.question=Elmúltál már 13 éves? + +/create.bml.age.check2.yes=Igen, idÅ‘sebb vagyok mint 13 éves. + +/create.bml.age.head=Kor + +/create.bml.btn.create=Napló létrehozása + +/create.bml.btn.proceed=Tovább... + +/create.bml.captcha.answer=Válasz: + +/create.bml.captcha.audiodesc=Gépeld be a számokat, amiket hallasz, így bizonyítod, hogy nem egy spam robot vagy. + +/create.bml.captcha.desc=Gépeld be az alábbi betűket és számokat, ezzel bizonyítod, hogy nem egy spam robot vagy. Ha nem tudod elolvasni a szöveget, és inkább a hang tesztet választanád, írd be, hogy "AUDIO". + +/create.bml.captcha.invalid=Helytelen válasz. Próbáld újra. + +/create.bml.captcha.play=Hang lejátszása + +/create.bml.captcha.prove=Bizonyítsd be, hogy nem gép vagy + +/create.bml.clusterselect.cluster=Csoport + +/create.bml.clusterselect.clusternum=Csoport [[number]] + +/create.bml.clusterselect.head=Csoport Kiválasztása + +/create.bml.clusterselect.nocluster=Nincs Csoport + +/create.bml.clusterselect.text=Kérlek válaszd ki azt a csoportot, amelyen létre akarod hozni ezt a fiókot. Megjegyzés: Ez csupán egy hibakeresÅ‘/teszt opció. EbbÅ‘l kifolyólag a felhasználók errÅ‘l semmit nem fognak tudni, vagy érzékelni belÅ‘le. + +/create.bml.create.head=Új napló készítése + +/create.bml.create.text=Egy új napló elkészítése nem egy bonyolult dolog; elég csak az instrukciókat követned! + +/create.bml.email.head=E-mail címed + +/create.bml.email.input.head=E-mail cím: + +/create.bml.email.text2=Biztonsági és egyeztetési okokból szükségünk van az e-mail címedre. Soha, semmilyen körülmények között nem fogjuk odaadni spammelÅ‘knek, jobban utáljuk azt, mint bármi mást. További információkért kérjük, olvasd el adatvédelmi nyilatkozatunkat. + +/create.bml.error.coppa.under13=Sajnáljuk, de a COPPA megkötései értelmében a LiveJournal szolgáltatását nem használhatod amíg be nem töltötted tizenharmadik életévedet. Gyere vissza a tizenharmadik születésnapodon! + +/create.bml.error.email.blank=Meg kell, hogy add az e-mail címedet. + +/create.bml.error.email.lj_domain=Nem használhatsz egy [[domain]] fedÅ‘nevet, ha fiókot hozol létre. Kérlek írj be egy másik emailcímet. + +/create.bml.error.email.nospaces=Az e-mail címben nem szerepelhetnek szóközök. Ha AOL felhasználó vagy, nem szabad elfelejtened, hogy e-mail címed a Screen Name, minden szóköztÅ‘l megfosztva, a végén egy „@aol.comâ€-mal. + +/create.bml.error.password.asciionly=A jelszóban csak ASCII karakterek szerepelhetnek. + +/create.bml.error.password.blank=Be kell írnod egy jelszót. + +/create.bml.error.password.nomatch=A két beírt jelszó nem egyezik. + +/create.bml.error.postrequired=POST paraméterek hiányzanak. + +/create.bml.error.username.blank=Kérjük, adj meg egy nevet, becenevet vagy valami hasonlót. + +/create.bml.error.username.inuse=A felhasználónév már foglalt, válassz másikat! + +/create.bml.error.username.iscode=A felhasználónév, amit megadtál, inkább tűnik meghívókódnak, mint felhasználónévnek. + +/create.bml.error.username.mustenter=Be kell írnod egy felhasználónevet! + +/create.bml.error.username.reserved=Bocs, de ez foglalt név. + +/create.bml.initial.friend.news=LiveJournal hírek, események + +/create.bml.initialfriends.heading=KezdÅ‘ barátok + +/create.bml.name.head=Neved + +/create.bml.name.input.head=Név: + +/create.bml.name.text=Mi legyen a neved, amin a többiek azonosítanak? Ez fog megjelenni a naplód tetején és a felhasználói keresésben. Lehet becenév, vagy akármi, ami tetszik — nem szükséges, hogy pl. a teljes nevedet add meg. + +/create.bml.password.head=Jelszó + +/create.bml.password.input.head1=Jelszó: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Jelszó újra: + +/create.bml.password.text=Találj ki egy jelszót! + +/create.bml.proceed.btn.proceed=Tovább… + +/create.bml.proceed.warning=A Tovább gombot csak egyszer nyomd meg! + +/create.bml.success.btn.enterinfo=Személyes adatok megadása + +/create.bml.success.head=Siker! + +/create.bml.success.text1=Naplódat létrehoztuk. E-mailben elküldtünk néhány fontos regisztrációs információt a Te [[email]] e-mail címedre. Jelezz vissza a leírtaknak megfelelÅ‘en az e-mailben található linkre való kattintással! + +/create.bml.success.text2=A LiveJournalod a következÅ‘ címen lesz elérhetÅ‘: + +/create.bml.success.text3=Most kérünk, tölts ki egy kis kérdőívet magadról. Javarészt nem kötelezÅ‘, de ad nekünk egy képet arról, kik is használják a LiveJournalt. + +/create.bml.title=Új napló létrehozása + +/create.bml.tos.error=MielÅ‘tt létrehoznál egy fiókot, végig kell olvasnod és el kell fogadnod a Szolgáltatás Feltételeit. + +/create.bml.tos.haveread=Végigolvastam és elfogadom a Szolgáltatás Feltételeit. + +/create.bml.tos.heading=Szolgáltatás Feltételei + +/create.bml.useacctcodes.entercode=Új felhasználói fiók létrehozásához írd be a meghívókódod! További információhoz olvasd el a Hogyan készítek felhasználói fiókot? c. gyakran ismételt kérdést. + +/create.bml.useacctcodes.welcome=Ãœdvözlünk! + +/create.bml.username.box.head=Felhasználói név: + +/create.bml.username.charsallowed=A felhasználó neveden csak kisbetűk (a-z ékezet nélkül), és számok (0-9) és az aláhúzó jel (_).
        Ezen kivül, 15 karakter a maximum. + +/create.bml.username.forpaidaccts=vagy, fizetÅ‘s fiókok esetén: + +/create.bml.username.head=Felhasználói név + +/create.bml.username.ljaddress=A naplódra a következÅ‘ címek mutatnak majd: + +/create.bml.username.text=Minden [[sitename]] felhasználónak egyedi azonosítója kell legyen. Az azonosító az, ami megjelenik a naplód címében, az, amit a [[sitename]] szerverére való bejelentkezésre használsz, stb. Többek között a mások naplójába írt hozzászólásoknál is megjelenik. + +/create.bml.username.username=felhasználói név + +/customize/index.bml.change=Váltás + +/customize/index.bml.choose=Szeretnéd a régi stílusrendszert használni, vagy az újat? + +/customize/index.bml.choose.header=Válassz stílusrendszert + +/customize/index.bml.choose.s1=Régi stílusrendszer (S1) + +/customize/index.bml.choose.s2=Új rendszer (S2) + +/customize/index.bml.error.fail_create_style=Nem sikerült új stílust készíteni. + +/customize/index.bml.previews=(ElÅ‘nézetek) + +/customize/index.bml.s1=A régi stílusú rendszert a Napló módosítása oldalon állíthatod be. + +/customize/index.bml.s1.header=Használatban: S1 + +/customize/index.bml.s2.advanced.header=Egyedi felépítések haladóknak + +/customize/index.bml.s2.advanced.permitted=Ha teljesen egyéni rétegeket (layers) és stílusokat szeretnél alkotni, látogass el az Advanced Customization központba. + +/customize/index.bml.s2.customize=A következÅ‘ beállítások elrendezés-függÅ‘ek. + +/customize/index.bml.s2.customize.header=2. lépés: Elrendezés testreszabása + +/customize/index.bml.s2.customize.language=Az aktuális elrendezés a következÅ‘ nyelveket támogatja: + +/customize/index.bml.s2.customize.language.custom=(Egyéni) + +/customize/index.bml.s2.customize.language.header=Nyelv + +/customize/index.bml.s2.customize.settings=Ha még jobban szeretnéd testreszabni a naplódat, ezekkel a speciális beállításokkal teheted meg. + +/customize/index.bml.s2.customize.settings.delete=Testreszabások eltávolítása + +/customize/index.bml.s2.customize.settings.delete.confirm=Biztosan megválsz az egyéni módosításaidtól? + +/customize/index.bml.s2.customize.settings.edit=Testreszabások szerkesztése + +/customize/index.bml.s2.customize.settings.header=Még részletesebb beállítások + +/customize/index.bml.s2.customize.settings.new=Testreszabás + +/customize/index.bml.s2.customize.themes.default=(Alapértelmezett) + +/customize/index.bml.s2.customize.themes.header=Sémák + +/customize/index.bml.s2.layout=Válassz elrendezést. Figyelj arra, hogy ha ezt megváltoztatod, akkor minden további, erre vonatkozó finomításod elvész. + +/customize/index.bml.s2.layout.header=1. lépés: Elrendezés + +/customize/index.bml.s2.related.editinfo.about=Naplód címe és más beállítások. + +/customize/index.bml.s2.related.header=Kapcsolódó oldalak + +/customize/index.bml.s2.related.links.about=Bizonyos stílusok tartalmazhatják saját linkjeid listáját. + +/customize/index.bml.s2.related.modify.about=Naplód hangulatikonjainak beállítása. + +/customize/index.bml.title=Napló testreszabása + +/delcomment.bml.confirm.body=Biztosan törölni szeretnéd ezt a hozzászólást? + +/delcomment.bml.confirm.head=Töröljük ezt a hozzászólást? + +/delcomment.bml.confirm.spam=Ez a hozzászólás spam! + +/delcomment.bml.confirm.submit=Hozzászólás törlése + +/delcomment.bml.error.alreadydeleted=A megadott hozzászólás már törölve van. + +/delcomment.bml.error.cantdelete=Hozzászólást csak a készítÅ‘je, vagy a napló tulajdonosa törölhet. + +/delcomment.bml.error.cantdelete.comm=Hozzászólást csak a hozzászólás készítÅ‘je, a naplóbejegyzés készítÅ‘je, vagy a közösség karbantartója törölhet. + +/delcomment.bml.success.andban=A hozzászólás törölve, [[user]] felhasználó pedig eltiltva a további bejegyzésektÅ‘l a naplódban. + +/delcomment.bml.success.head=Törölve + +/delcomment.bml.success.noban=A hozzászólás törölve. + +/delcomment.bml.title=Hozzászólás törlése + +/developer/index.bml.embedding<< +Be szeretnéd illeszteni naplódat saját honlapodba? Többféleképpen lehetséges, attól függÅ‘en, hogy milyen jogaid vannak a honlapodat tároló szerveren. De ez miatt csak akkor kell aggódnod, ha nem szeretnéd, hogy a +www.livejournal.com cím megjelenjen a címsorodban. + +. + +/developer/index.bml.styles.s1.header=Stílusrendszer 1 + +/developer/index.bml.styles.s1.system=Stílusrendszer + +/developer/index.bml.styles.s2.header=Stílusrendszer 2 + +/directory.bml.browse.country.desc=Válassz egy országot, ahonnan olvasni szeretnél + +/directory.bml.browse.country.title=Naplók böngészése országok szerint + +/directory.bml.browse.usa.desc=Válassz egy államot, vagy kattints egy ország nevére a térkép alatti listán. + +/directory.bml.browse.usa.title=Naplók böngészése államok szerint + +/directory.bml.error.accounttype=Sajnos a fiókod olyan típusú, amely számára nem engedélyezett a címjegyzék használata, vagy jelenleg nem vagy bejelentkezve. Ha olyan típusú fiókkal rendelkezel, amely számára engedélyezett a címjegyzék használata, akkor gyÅ‘zÅ‘dj meg róla, hogy be vagy jelentkezve, és utána próbálkozz újra. + +/directory.bml.navcrap.matches=[[count]] találat + +/directory.bml.navcrap.xofy=Lap [[curpage]] / [[totpages]] ([[reca]]-[[recb]]) + +/directory.bml.search.monkey=Betanított majmok százai dolgoznak éppen a kereséseden. Kérjük, várj. + +/directory.bml.search.new=Új keresés + +/directory.bml.search.overflow=Túl sok találat (max. [[count]] lehet). Kérjük, finomítsd a keresést. + +/directory.bml.search.title=Keresés + +/directory.bml.user=Felhasználó + +/doc/index.bml.about=Ãœdvözlünk a LiveJournal dokumentációs tárházában, ahol információkat találhatsz a legtöbb, LiveJournal szolgáltatással vagy kiszolgáló programokkal kapcsolatos témákról. Kérlek válassz egy témát az alábbiak közül: + +/doc/index.bml.about.header=Ãœdvözöljük + +/doc/index.bml.docs.faq.about=Gyakran Ismételt Kérdések a LiveJournal.com-ról + +/doc/index.bml.docs.faq.title=Gyakran feltett kérdések (GyIK) + +/doc/index.bml.docs.header=Dokumentumok + +/doc/index.bml.docs.howto.about=Tippek és trükkök, amik segítenek a LiveJournal fiókod testreszabásában + +/doc/index.bml.docs.server.title=LiveJournal Szerver Kézikönyv + +/doc/index.bml.docs.tour.about=Új látogatók számára tervezték, hogy minél könnyebben kiismerjék magukat az oldalon. + +/doc/index.bml.docs.tour.title=Túra + +/doc/index.bml.title=Dokumentáció + +/doc/index.bml.volunteering.about=Ha szeretnél segíteni a LiveJournal dokumentációjával, látogasd meg a következÅ‘ fórumokat: + +/doc/index.bml.volunteering.header=Jelentkezés + +/doc/index.bml.volunteering.ljsysdoc=A LiveJournal dokumentációjáról folyó eszmecsere + +/doc/tour/index.bml.clients.caption<< +A LiveJournal kliensek kis programok, amik a számítógépeden futva, lehetÅ‘vé teszik, hogy bármikor (ha csatlakozva vagy az internethez) frissítsd a naplódat, anélkül, hogy akár egy böngészÅ‘ alblakot is meg kelljen nyitnod. +Szinte az összes operációs rendszerhez van elérhetÅ‘ kliens, amelyek közül sok igen könnyen testreszabható. +. + +/doc/tour/index.bml.clients.title=Kliensek + +/doc/tour/index.bml.comms.caption=A LiveJournal egy nagy interaktív közösség, így hát nem meglepÅ‘, hogy sok olyan tagja van, akiknek hasonló az érdeklÅ‘dési körük. Éppen ezért mi felkínáljuk számotokra a lehetÅ‘séget, hogy közösségeket, vagy olyan naplókat hozzatok létre, melyekbe sokan mások is írhatnak. + +/doc/tour/index.bml.comms.title=Közösségek + +/doc/tour/index.bml.create.caption=A LiveJournal egy tagság-alapú naplóíró közösség. Ez az oldal részletesen taglalja a tagság velejáróit, azt, hogy mért fontos a tagság, és, hogy mik az elÅ‘nyei. Továbbá tartalmaz egy űrlapot is, mellyel létrehozhatod a saját LiveJournal fiókodat. + +/doc/tour/index.bml.create.title=Egy Fiók Létrehozása + +/doc/tour/index.bml.friends.caption=A LiveJournalon keresztül barátaid naplóit is nyomon követheted a be–épített "barátok" oldalon. Ha valakinek a naplóját érdekesnek találod, add hozzá a "barátok" listádhoz, amely így lehetÅ‘vé fogja tenni, hogy barátaid összes bejegyzését ugyanazon az oldalon olvashasd. + +/doc/tour/index.bml.friends.title=Barátok + +/doc/tour/index.bml.intro.title=Ãœdvözöljük + +/doc/tour/index.bml.modify.caption=LehetÅ‘séged van arra is, hogy naplódat különféle módokon átalakítsd, felhasználva az elÅ‘re elkészített stílusokat és színösszeállításokat. Varázsold a naplódat olyan egyedülállóvá, amennyire csak akarod! + +/doc/tour/index.bml.modify.title=Személyreszabás + +/doc/tour/index.bml.nav.next=KövetkezÅ‘ --> + +/doc/tour/index.bml.nav.prev=<-- ElÅ‘zÅ‘ + +/doc/tour/index.bml.sitemap.title=Honlaptérkép + +/doc/tour/index.bml.support.caption=A tanácsadó oldalon listázva vannak a helyek, amik segítenek megmagyarázni, hogy mi maga a LiveJournal, vagy, amik az oldallal kapcsolatos gyakran ismételt kérdéseket tartalmaznak vagy akár egyéb hasznos információt nyújtanak a szolgáltatásról, a cégrÅ‘l és a közösségrÅ‘l úgy általában. + +/doc/tour/index.bml.support.title=Segítség kérése + +/doc/tour/index.bml.title=Túra - [[title]] + +/doc/tour/index.bml.update.caption=A naplóírás a LiveJournal alapvetÅ‘ szolgáltatása. Ezzel lehetÅ‘séged nyílik kifejezni önmagad, megosztani gondolatvilágodat. Csak írj bele a téglalapba, és nyomd meg a "Bejegyzés" gombot. Ha akarod, akár pillanatnyi hangulatodat is megadhatod, vagy leírhatod, hogy éppen milyen zenét hallgatsz. + +/doc/tour/index.bml.update.title=Frissités + +/editinfo.bml.allowshowcontact.about=Ajánlott, hogy ezt a funkciót bekapcsolva hagyd. Ez azt szabályozza, hogy mások láthatják-e elérési adataidat (e-mail, ICQ szám, stb.). + +/editinfo.bml.allowshowcontact.email=Amennyiben engedélyezett, az e-mail amit mások láthatnak: + +/editinfo.bml.allowshowcontact.email.actual_only=Csak a valós címet + +/editinfo.bml.allowshowcontact.email.both=MindkettÅ‘t (valódi + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=csak LiveJournal címet + +/editinfo.bml.allowshowcontact.email.neither=Egyiket sem. + +/editinfo.bml.allowshowcontact.email.no_show=Ne mutasson e-mail címet + +/editinfo.bml.allowshowcontact.email.show=Mutassa az e-mail címet + +/editinfo.bml.allowshowcontact.email.withdomainaddr=A fentiek lehetÅ‘séget adnak arra, hogy e-mail címedet mások elÅ‘l elrejtsd (míg egyéb elérhetÅ‘ségeidet közzéteszed) vagy csupán LiveJournalos e-mailedet (ehhez persze fizetÅ‘s fiók kell), csak a valódit, netán mindkettÅ‘t mutasd. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=A fenti lehetÅ‘séggel elrejtheted e-mail címedet, míg más elérhetÅ‘ségi információkat közzéteszel. + +/editinfo.bml.allowshowcontact.title=Közzé kívánod tenni elérhetÅ‘ségi adataidat a LiveJournalon? + +/editinfo.bml.allowshowinfo.about=Kapcsold ezt be, ha szeretnéd, hogy mások tudják, merre laksz és mikor van a szülinapod. + +/editinfo.bml.allowshowinfo.title=Mutassa a helyet és a szülinapot? + +/editinfo.bml.autotranslate.about<< +Mondd meg nekünk, hogyan kódoljuk azokat a bejegyzéseket, amiket még a Unicode-ra való átállásunk elÅ‘tt írtál! +Amennyiben angolul írsz, válaszd a "Western European" beállítást, ha magyarul, akkor pedig a "Central European" lesz megfelelÅ‘, valószínűleg. +. + +/editinfo.bml.autotranslate.header=Régi bejegyzések automatikus konvertálása a következÅ‘ kódlap alapján: + +/editinfo.bml.bday.title=Születésnap + +/editinfo.bml.bday.year.opt=az év elhagyható + +/editinfo.bml.bdayreminders.about=Ha szeretnél e-mailes értesítést kapni barátaid születésnapjáról, jelöld be ezt! + +/editinfo.bml.bdayreminders.header=Kérek szülinapi értesítést (jelenleg üzemen kívül) + +/editinfo.bml.bio.about=Ide írhatsz egy mini-életrajzot vagy akármit; ez meg fog jelenni az adatlapodon. + +/editinfo.bml.bio.header=Magadról + +/editinfo.bml.blockrobots.about=Ha ezt kipipálod, a keresÅ‘robotok nem fogják regisztrálni a naplódat. Nem minden keresÅ‘robot tartja magát a szabályokhoz. + +/editinfo.bml.blockrobots.header=Robotok és pókok megakadályozása naplód indexelésében + +/editinfo.bml.chat.msnusername.title=MSN felhasználónév + +/editinfo.bml.city.title=Város + +/editinfo.bml.country.choose=Válassz országot! + +/editinfo.bml.country.title=Ország + +/editinfo.bml.donotlog=Ne + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=Válaszd ki ezt, ha szeretnéd, hogy mások tudjanak válaszolni bejegyzéseidre! + +/editinfo.bml.enableboards.header=Hozzászólások engedélyezése + +/editinfo.bml.encoding.about=Csak akkor foglalkozz ezzel, ha több nyelven írsz egyszerre; itt választhatod ki a kódolást. + +/editinfo.bml.encoding.header=Kódolási beállítások + +/editinfo.bml.error.day.notinmonth=Abban a hónapban nincs ilyen nap. + +/editinfo.bml.error.day.outofrange=Hibás nap. A születésnapod csak 1 és 31 között lehet. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Ide nem írhatsz @[[domain]] e-mail címet. Ãrd be a valódi címedet! +Ha fizetsz a szolgáltatásért, a [[user]]@[[domain]] címed a valódi e-mail címedre fog átirányítani. +Azt, hogy ezek közül melyik legyen látható, lejjebb állíthatod be. +. + +/editinfo.bml.error.email.none=Be kell írnod az e-mail címedet + +/editinfo.bml.error.email.no_space<< +E-mail címben nem lehetnek szóközök. +Amennyiben AOL-t használsz, ne feledd, e-mail címed a képneved szóközök nélkül, @aol.com-mal kiegészítve. +. + +/editinfo.bml.error.excessive_int=Sajnáljuk, de túl sok érdeklÅ‘dési kört adtál meg. Legfeljebb 150-et írhatsz be, [[intcount]] egy kicsit sok lesz. A változtatásaidat nem mentettük el. Menj vissza, készíts egy rövidebb listát, és azt próbáld elmenteni! + +/editinfo.bml.error.invalidbio=Az általad elmentett életrajz mezÅ‘ nem megengedett karaktereket tartalmaz. Menj a konverziós lapra, és alakítsd át Unicode formátumba! + +/editinfo.bml.error.invalidints=Az általad elmentett érdeklÅ‘dési lista nem megengedett karaktereket tartalmaz. Menj a konverziós lapra, és alakítsd át Unicode formátumba! + +/editinfo.bml.error.invalidname=A neved nem megengedett karaktereket tartalmaz. Menj a konverziós lapra, és alakítsd át Unicode formátumba! + +/editinfo.bml.error.locale.country_ne_state=Az USÃ-t adtad meg országodnak, de "egyéb államnak" egy nem USA-beli államot választottál... + +/editinfo.bml.error.locale.invalid_country=Valahogy egy nem létezÅ‘ országot sikerült kiválasztanod. + +/editinfo.bml.error.locale.state_ne_country=Országodnak nem az USÃ-t választottad, mégis megadtál egy USA-beli államot. + +/editinfo.bml.error.locale.zip_ne_state<< +Olyan irányítószámot adtál meg, ami nem az általad megadott államból való. +Helyesbítsd a megadott adatokat, vagy töröld ki valamelyiket, esetleg mindkettÅ‘t. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Beírtál ugyan egy irányítószámot, de nem az USÃ-t adtad meg országodnak. +Csak USA-beli irányítószámot veszünk figyelembe. +Menj vissza és töröld a beírt számot vagy add meg országodnak az Egyesült Ãllamokat! +. + +/editinfo.bml.error.month.outofrange=Hibás hónap. Ãrj be egy hónapot 1 és 12 között (Jan—Dec.) + +/editinfo.bml.error.noname=A név mezÅ‘ kitöltése kötelezÅ‘. Ãrd be legalább a keresztneved, beceneved vagy az azonosítódat. + +/editinfo.bml.error.tm.require.number=Ahhoz, hogy hasznélni tudjad az SMS szolgáltatást, a telefonszámodra lesz szükségünk. + +/editinfo.bml.error.tm.require_provider<< +Amennyiben használni szeretnéd a rövid szöveges üzenetes szolgáltatást, ki kell választanod a szolgáltatód. + +Ha a tied nem szerepel, vedd fel velünk a kapcsolatot, és mondd el, hogyan működik az SMS a te szolgáltatódnál. +. + +/editinfo.bml.error.year.notenoughdigits=Hibás születési év. Négyjegyű évet kell beírnod. + +/editinfo.bml.error.year.outofrange=Érvénytelen születési év. + +/editinfo.bml.finished.about=Amikor elkészültél, nyomd meg az alább látható Változások mentése című gombot! + +/editinfo.bml.finished.header=Kész? + +/editinfo.bml.finished.save_button=Változások mentése + +/editinfo.bml.gender.title=Nem + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Ezt akkor pipáld ki, ha szeretnél naplódba írt válaszokról e-mailben értesülni. + +/editinfo.bml.getreplies.header=E-mailes értesítÅ‘ a hozzászólásokról + +/editinfo.bml.hidefriendof.about=Ha ezt kiválasztod, mások nem láthatják a profillapodon, kik írtak fel téged a barátlistájukra. + +/editinfo.bml.hidefriendof.header="Barátja vagyok" lista rejtése + +/editinfo.bml.howhear.about<< +Kíváncsiságunkat kielégítendÅ‘ megkérdeznénk, honnét hallottál a [[sitename]] szolgáltatásáról? +Ha ez egy felhasználónk volt, írd be felhasználói nevét; ha valami más, pl. cikk, weblap, link stb., írd be azt! +. + +/editinfo.bml.howhear.header=Kíváncsiskodás + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Válaszd ki ezt, ha szeretnéd hogy a neked küldött e-mailek HTML formátumban érkezzenek. +Sok kliens megpróbálja támogatni a HTML leveleket, de szörnyű módon meghiúsul próbálkozásuk. +Ha üresen hagyod, nem pipálod ki, a LiveJournal tisztán szöveges e-maileket fog csak küldeni. +. + +/editinfo.bml.htmlemail.header=HTML e-mailek küldése + +/editinfo.bml.imagelinks.about=A helyÅ‘rzÅ‘k a megjelenítendÅ‘ képeket linkekkel helyettesítik, ezért hasznos lehet, ha munkahelyen, vagy lassú kapcsolaton keresztül böngészve bekapcsolod Å‘ket. Mekkora képekhez szeretnéd Å‘ket használni? + +/editinfo.bml.imagelinks.header=HelyÅ‘rzÅ‘k megjelenítése a "barátok" oldalon + +/editinfo.bml.imagelinks.size.all=HelyÅ‘rzÅ‘k megjelenítése minden képhez + +/editinfo.bml.imagelinks.size.custom=Egyéni: helyÅ‘rzÅ‘k megjelenítése [[width]]x[[height]]-nál nagyobb képekhez + +/editinfo.bml.imagelinks.size.medium=HelyÅ‘rzÅ‘k megjelenítése nagy képekhez ([[width]]x[[height]]-nál nagyobb) + +/editinfo.bml.imagelinks.size.small=HelyÅ‘rzÅ‘k megjelenítése közepes képekhez ([[width]]x[[height]]-nál nagyobb) + +/editinfo.bml.int.about<< +Ha szeretnéd, hogy mások érdeklÅ‘dési köröd alapján rád találhassanak, írd le, mi érdekel, egy-egy szóval, rövid kifejezéssel! +Ökölszabály: amit ide írsz, be kell tudnod helyezni valami olyan mondatba, hogy „Szeretem a ______-t†vagy „Szeretek ______â€.  Egyszerű fÅ‘neveknél ajánlott a többes szám, rövidítéseknél egyes szám is elég. +. + +/editinfo.bml.int.ex.bad=ROSSZ példa: Szeretek egy csomó zenekart, meg filmet nézni, meg barátaimmal beszélgetni; de nagyon szeretek még diszkóba járni is! Az ilyesmi az tökéletesen jó lesz az életrajzodba/önleírásodba odafenn. + +/editinfo.bml.int.ex.good=JÓ példa: biciklizni, síelni, számítógépek, dvd, mp3, sajtok, csajok + +/editinfo.bml.int.header=ÉrdeklÅ‘dés + +/editinfo.bml.login.enterinfo=Ãrd be a felhasználói neved és jelszavad a személyes adataid megváltoztatásához! + +/editinfo.bml.login.forgot.header=Elfelejtettél valamit? + +/editinfo.bml.login.forgot.recover=Ha elfelejtetted az azonosítód vagy jelszavad, kattints ide! + +/editinfo.bml.logip.always=Mindig + +/editinfo.bml.logip.anon_only=Csak anonim hozzászólók + +/editinfo.bml.logip.header=Naplózzuk a válaszolók IP címét? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Ha nem szeretnéd, hogy reklámpostázó robotok megtalálják az emailcímedet a LiveJournalon, válaszd ki ezt az opciót. Az email címedet megváltoztatva fogjuk feltűntetni, így az email-gyűjtÅ‘ robotok nem fognak rátalálni. + +/editinfo.bml.mangleaddress.header=Email cím felismerhetetlenné tétele + +/editinfo.bml.name.title=Név + +/editinfo.bml.newemail.subject=Email cím megváltoztatva + +/editinfo.bml.numcomments.about=Válaszd ki ezt, ha szeretnéd, hogy a hozzászólások számát az URL végére odarakjuk, így a böngészÅ‘d talán más színnel mutatja, írtak-e a bejegyzéshez mióta utoljára olvastad. + +/editinfo.bml.numcomments.header=&nc=xx hozzáfűzése a kommentek URL-jéhez. + +/editinfo.bml.optional=Nem kötelezÅ‘ + +/editinfo.bml.opt_in.header=Küldj LiveJournal híreket e-mailen. + +/editinfo.bml.persinfo.disclaimer=Kérjük, adj meg pár adatot magadról. Semmi rosszat nem fogunk velük csinálni, mindössze statisztikai célul szolgálnak, hogy jobban megismerhessük felhasználóinkat. Kérjük, ügyelj az adatok pontosságára. Adatvédelmi nyilatkozat. + +/editinfo.bml.persinfo.header=Személyes adatok + +/editinfo.bml.screen.all=Mindet + +/editinfo.bml.screen.anon=Anonímokat + +/editinfo.bml.screen.header=Mely hozzászólásokat szeretnéd alapból elrejteni? + +/editinfo.bml.screen.none=Semelyiket + +/editinfo.bml.screen.nonfriends=Nem barátokéit + +/editinfo.bml.screen.nonmembers=Nem tagokéit + +/editinfo.bml.security.header=Ki nézheti meg elérhetÅ‘ségi adataidat? + +/editinfo.bml.security.visibility.anybody=Bárki + +/editinfo.bml.security.visibility.everybody=Mindenki + +/editinfo.bml.security.visibility.friends=Csak barátok + +/editinfo.bml.security.visibility.regusers=Csak felhasználók + +/editinfo.bml.settings.friendspage.title=Barátok oldal címe: + +/editinfo.bml.settings.friendspage.title.optional=Tetszés szerint, beírhatod, hogy mi legyen a címe a "barátok" oldaladnak. (Nem HTML) + +/editinfo.bml.settings.header=A LiveJournal beállításai + +/editinfo.bml.settings.journal.subtitle=Napló alcíme: + +/editinfo.bml.settings.journal.subtitle.optional=Tetszés szerint, beírhatod, hogy mi legyen a címe és az alcíme a naplódnak. (Nem HTML). + +/editinfo.bml.settings.journal.title=Napló címe: + +/editinfo.bml.settings.privacy.header=Magánjogi Opciók + +/editinfo.bml.state.other=egyéb állam/terület/megye/stb. + +/editinfo.bml.state.title=Ãllam + +/editinfo.bml.state.us=USA államok + +/editinfo.bml.success.header=Siker! + +/editinfo.bml.success.message=Az információid, a naplód beállításai és a profilod fel lett frissítve. + +/editinfo.bml.switch.button=Váltás + +/editinfo.bml.switch.header=Napló váltás + +/editinfo.bml.switch.workwith=Dolgozni ezzel a naplóval: + +/editinfo.bml.title=Személyes információk módosítása + +/editinfo.bml.tm.details=részletek + +/editinfo.bml.tm.phonenum=Teljes telefonszám: + +/editinfo.bml.tm.sec.about=Más felhasználók általi szöveges üzenés lehetÅ‘ségének engedélyezése. + +/editinfo.bml.tm.sec.title=Biztonsági szint: + +/editinfo.bml.tm.servprov=Szolgáltató + +/editinfo.bml.tm.title=Szöveges üzenés + +/editinfo.bml.translatemailto.about=Abban az esetben, ha kiválasztottad a "válaszüzenetekrÅ‘l érkezÅ‘ emailes értesítés" opciót és az email programod nem tudja igazán jól kezelni a Unicode (UTF-8) üzeneteket, használd ezt az opciót egy másfajta kódolási típus kiválasztására, amire aztán a LiveJournal autómatikusan le fogja fordítani a neked küldött hozzászólásokat. + +/editinfo.bml.translatemailto.header=Emailes értesítések lefordítása: + +/editinfo.bml.unbanusers.about=A következÅ‘ felhasználóknak megtiltottad, hogy írjanak a naplódba. X-eld be a felhasználónevük melletti rublikát, ha meg akarod szüntetni a kitiltásukat. + +/editinfo.bml.unbanusers.header=Felhasználó kitiltásának megszüntetése + +/editinfo.bml.userpic.about=Itt látható az a miniatűr képecske, amit feltöltöttél, hogy "reprezentáljon" téged a LiveJournal-on, a naplódban és a barátaid naplóiban: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=A kép letörléséhez, vagy egy új kép föltöltéséhez, kattints ide. + +/editinfo.bml.userpic.header=Képed + +/editinfo.bml.userpic.none=még nincs kép feltöltve + +/editinfo.bml.weblogscom.about=Amennyiben szeretnéd, hogy a Weblogs.com listázza a naplódat, ha egy új nyilvános bejegyzést írsz bele, válaszd ki ezt az opciót. + +/editinfo.bml.weblogscom.header=Weblogs.com értesítése a frissítésekrÅ‘l. + +/editinfo.bml.webpagename.title=Honlap neve + +/editinfo.bml.webpageurl.title=Honlap címe + +/editinfo.bml.whoreply.header=Ki válaszolhat bejegyzéseidre? + +/editinfo.bml.zip.title=Irányítószám + +/editinfo.bml.zip.usonly=Ötjegyű irányítószám, csak USA + +/editjournal.bml.btn.proceed=Tovább... + +/editjournal.bml.certainday=Bizonyos nap: + +/editjournal.bml.recententries=legutóbbi bejegyzések + +/editjournal.bml.recententry=Legutolsó bejegyzés + +/editjournal.bml.title=Naplóbejegyzések szerkesztése + +/editjournal.bml.viewwhat=Mely bejegyzéseket nézzük meg? + +/editjournal_do.bml.body=Ãrd át azokat a mezÅ‘ket, amiket a bejegyzéseden módosítani szeretnél, aztán nyomd meg a mentés gombot az oldal alján. Ha inkább ki szeretnéd törölni az egészet, nyomd meg lent a törlés gombot. + +/editjournal_do.bml.btn.delete=Bejegyzés törlése + +/editjournal_do.bml.btn.edit=Szerkesztés + +/editjournal_do.bml.btn.preview=Bejegyzés elÅ‘nézete + +/editjournal_do.bml.btn.save=Naplóbejegyzés mentése + +/editjournal_do.bml.continue.head=Nyomd meg a folytatáshoz... + +/editjournal_do.bml.continue.text=Mitán a megváltoztatni vagy törölni kívánt részt kiválasztottad, kattints az alábbi Megváltoztatás gombra. + +/editjournal_do.bml.currmood=Jelenlegi hangulat: + +/editjournal_do.bml.currmusic=Jelenlegi Zene: + +/editjournal_do.bml.date=Dátum: + +/editjournal_do.bml.default=alapértelmezet + +/editjournal_do.bml.edit.text=Ez az a naplóbejegyzés amit megváltoztatásra jelöltél ki. Végezd el rajta a kívánt változtatásokat és, ha úgy érzed kész vagy, klikkelj a lap alján lévÅ‘ "Naplóbejegyzés Mentése" gombra.

        A bejegyzés teljes törléséhez, törölj ki minden szöveget a szövegdobozban, majd klikkelj a lap alján található "Naplóbejegyzés mentése" gombra. + +/editjournal_do.bml.error.getting=Hiba történt a bejegyzés módosításra beolvasásakor: + +/editjournal_do.bml.error.modify=Hiba történt naplót módosítása közben: + +/editjournal_do.bml.error.nofind=A kiválasztott naplóbejegyzés nem található. + +/editjournal_do.bml.event=Esemény: + +/editjournal_do.bml.localtime=Helyi idÅ‘: + +/editjournal_do.bml.noneother=Nincs, vagy más: + +/editjournal_do.bml.opt.backdate=Bejegyzés visszadátumozása: + +/editjournal_do.bml.opt.backdate.about=nem fog megjelenni a barátlapon + +/editjournal_do.bml.opt.nocomments=Hozzászólások tiltása: + +/editjournal_do.bml.opt.noemail=Ne küldjön e-mailt: + +/editjournal_do.bml.opt.noformat=Ne formázzon automatikusan: + +/editjournal_do.bml.other=Egyéb: + +/editjournal_do.bml.pickentry.head=Válaszd ki a megváltoztatni kívánt bejegyzést + +/editjournal_do.bml.pickentry.text=Válaszd ki a megváltoztatni kívánt részt, és kattints a lap alján található Megváltoztatás gombra. + +/editjournal_do.bml.picture=Használandó Kép: + +/editjournal_do.bml.preview.header=Bejegyzés elÅ‘nézete + +/editjournal_do.bml.save.head=Ezt nyomd meg a mentéshez... + +/editjournal_do.bml.save.text=Ha elvégezted a naplóbejegyzéseden történÅ‘ kívánt változtatásokat, kattints a Mentés gombra. + +/editjournal_do.bml.subject=Téma: (nem kötelezÅ‘) + +/editjournal_do.bml.success.delete=Bejegyzés törölve. + +/editjournal_do.bml.success.edit=Bejegyzés modósítva. Itt tekintheted meg. + +/editjournal_do.bml.success.head=Siker + +/editjournal_do.bml.timeformat=24 órás idÅ‘ + +/editjournal_do.bml.title=Naplóbejegyzések módosítása + +/editpics.bml.btn.proceed=Mehet + +/editpics.bml.btn.save=Beállítások mentése + +/editpics.bml.curpics=Jelenlegi képek + +/editpics.bml.curpics.desc=Alább láthatod feltöltött képeidet. Ãrhatsz kulcsszavakat hozzájuk, hogy késÅ‘bb hivatkozhass rájuk, beállíthatod, hogy melyik legyen az alapértelmezett, vagy törölheted a régieket. Ha új képet akarsz feltölteni, használd az oldal alján lévÅ‘ űrlapot. + +/editpics.bml.error.badurl=A feltöltendÅ‘ kép címének http://-vel kell kezdÅ‘dnie. + +/editpics.bml.error.filetoolarge=A feltöltött kép túl nagy. A fájlméret max. [[maxsize]] lehet. + +/editpics.bml.error.invalidimage=Érvénytelen képfájl. + +/editpics.bml.error.urlerror=Hiba történt képed beolvasása közben. + +/editpics.bml.fromfile=Fájlból: + +/editpics.bml.fromurl=URL (internet cím): + +/editpics.bml.imagesize.by|notes=This character is inserted between two numbers to indicate "by" when specifying image dimensions, for example "100x100". +/editpics.bml.imagesize.by=× + +/editpics.bml.label.default=Alapértelmezett: + +/editpics.bml.label.delete=Törlés: + +/editpics.bml.label.keywords=Kulcsszavak: + +/editpics.bml.makedefault=Legyen ez az alapértelmezett kép + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=a + +/editpics.bml.nodefault=Ne legyen alapértelmezett kép + +/editpics.bml.noneupload=Még nincsenek képeid. Tölts fel egyet az alábbi űrlap segítségével. + +/editpics.bml.nopics=Nincsenek képek + +/editpics.bml.restriction.fileformat=A kép formátuma PNG, GIF, vagy JPG legyen + +/editpics.bml.restriction.filesize=A kép mérete kisebb legyen, mint 40k + +/editpics.bml.restriction.imagesize=A kép kiterjedése nem lehet nagyobb 100x100 képpontnál + +/editpics.bml.title=Feltöltött képek szerkesztése + +/editpics.bml.uploaddesc=Használd az alábbi űrlapot kép feltöltésére. + +/editpics.bml.uploadheader=Új kép feltöltése + +/export.bml.btn.proceed=Folytatás... + +/export.bml.description|staleness=1 +/export.bml.description=Ez az opció lehetÅ‘vé tesz a teljes naplód letöltését egy egyéni formátumban, biztonsági másolás céljából. + +/export.bml.fields=MezÅ‘k: + +/export.bml.format.csv=CSV (VesszÅ‘k által Elválasztott Értékek) + +/export.bml.label.encoding=Kódolás: + +/export.bml.label.field.allowmask=Maszkolás Engedélyezése + +/export.bml.label.field.currents=Jelenlegi hanulat & zene + +/export.bml.label.field.event=Esemény + +/export.bml.label.field.eventtime=Esemény Ideje (a felhasználó órája szerint) + +/export.bml.label.field.itemid=Azonosító Szám + +/export.bml.label.field.logtime=Feljegyzés Ideje (a rendszer órája szerint) + +/export.bml.label.field.security=Biztonsági szint + +/export.bml.label.field.subject=Téma + +/export.bml.label.format=Formátum: + +/export.bml.label.header=Fejléc + +/export.bml.label.month=Hónap kiválasztása: + +/export.bml.label.month.month=hh + +/export.bml.label.month.year=éééé + +/export.bml.label.notranslation=Egymás között ne fordítsa le a kódolásokat + +/export.bml.label.what=Mit Exportáljon: + +/export.bml.title=Napló Exportálása + +/export.bml.what.entries=Bejegyzéseket + +/friends/add.bml.add.header=Siker + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text= felkerült a barátlistádra. Itt megtekintheted a barátok bejegyzéseit tartalmazó lapodat. + +/friends/add.bml.add.title=Barát hozzáadva! + +/friends/add.bml.btn.add=[[user]] felvétele + +/friends/add.bml.btn.modify=Megváltoztat + +/friends/add.bml.btn.remove=Levesz + +/friends/add.bml.colors.bg=Háttér + +/friends/add.bml.colors.fg=ElÅ‘tér + +/friends/add.bml.colors.header=Színek + +/friends/add.bml.colors.hover=(Vidd az egered egy szín fölé, hogy láthasd annak nevét) + +/friends/add.bml.colors.text=Ha kívánod, akár színekkel is megkülönböztetheted [[user]] barátodat listádon. + +/friends/add.bml.confirm.header=Felvegyük barátaid közé [[user]] felhasználót? + +/friends/add.bml.confirm.text=[[user]] felvételéhez nyomd meg a lenti gombot! + +/friends/add.bml.confirm.title=Barát felvétele + +/friends/add.bml.error1.header=ElÅ‘bb jelentkezz be! + +/friends/add.bml.error1.text=Ahhoz, hogy egy barátot felvehess a listádra, elÅ‘bb be kell jelentkezned. Ha még nincs naplód nálunk, itt készíthetsz egyet, hogy figyelhesd barátaidéit. + +/friends/add.bml.error1.title=Barát felvétele + +/friends/add.bml.error2.text=Hibás felhasználónév. Barát hozzáadásához menj a barátlista szerkesztése lapra! + +/friends/add.bml.error3.text=[[user]] már a barátlistádon van. EttÅ‘l függetlenül, persze, megváltoztathatod színeit. + +/friends/add.bml.error3.title=Barát szerkesztése + +/friends/add.bml.groups.header=Egyéni "barát" csoportok + +/friends/add.bml.groups.nogroup=Nincsenek "barát" csoportok beállítva. + +/friends/add.bml.groups.text=Melyik "barát" csoportba szeretnéd helyezni ezt a felhasználót? Ezeket a csoportokat arra lehet használni, hogy csak az Å‘ naplóikat jelenítsd meg, vagy csak egy adott baráti körödnek tedd láthatóvá egy bejegyzésedet. + +/friends/add.bml.remove.header=Siker + +/friends/add.bml.remove.text= sikeresen eltávolíttatott barátlistádról. Itt megnézheted barátaid naplóbejegyzéseit. + +/friends/add.bml.remove.title=Barát törölve! + +/friends/edit.bml.title=Barátok szerkesztése + +/friends/editgroups.bml.btn.ge.del=Törlés + +/friends/editgroups.bml.btn.ge.new=Új + +/friends/editgroups.bml.btn.ge.ren=Ãtnevezés + +/friends/editgroups.bml.btn.gs.private=Privát + +/friends/editgroups.bml.btn.gs.public=Publikus + +/friends/editgroups.bml.btn.mv.down=Ãthelyezés Lefelé + +/friends/editgroups.bml.btn.mv.up=Ãthelyezés Felfelé + +/friends/editgroups.bml.confirm.delete=Biztos, hogy le akarod törölni ezt az egyéni "barátok" csoportot? + +/friends/editgroups.bml.done.btn=Változtatások mentése + +/friends/editgroups.bml.done.header=Kész? + +/friends/editgroups.bml.done.text=Ha elkészültél, kattints az alábbi gombra a változtatásaid mentéséhez. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Elérted a maximálisan elérhetÅ‘ 30 egyéni barátok csoportot. Ha idÅ‘közben letöröltél egy vagy több csoportot de még nem mentetted el a változtatásaidat akkor ezt tedd meg most, majd gyere vissza erre az oldalra és töltsd be újra. Ezután ismét lehetÅ‘séged lesz új egyéni barátok csoport létrehozására. + +/friends/editgroups.bml.error.text=A szerver a következÅ‘ hibaüzenetet küldte: + +/friends/editgroups.bml.group.public=(publikus) + +/friends/editgroups.bml.ingroup=Csoportban van: + +/friends/editgroups.bml.ingroup.not=Nincs Csoportban: + +/friends/editgroups.bml.prompt.newname=Ãrd be az új egyéni "barátok" csoport nevét: + +/friends/editgroups.bml.prompt.rename=Ennek az egyéni "barátok" csoportnak az átnevezése a következÅ‘ névre: + +/friends/editgroups.bml.saved.header=Elmentve + +/friends/editgroups.bml.saved.text=Az egyéni "barátok" csoportjaid el lettek mentve. + +/friends/editgroups.bml.text.sec=Biztonsági Figyelmeztetés: Ha le akarsz törölni egy csoportot és helyette egy újat akarsz létrehozni, akkor ezt ne úgy csináld, hogy átnevezel egy csoportot és aztán azt megváltoztatod. Ilyenkor ugyanis az összes régi bejegyzésed, amelyhez a régi csoport hozzáfért, az új csoport számára is hozzáférhetÅ‘ lesz. + +/friends/editgroups.bml.title=Barátcsoportok szerkesztése + +/friends/editgroups.bml.yourgroups=Az egyéni "barátok" csoportjaid: + +/friends/edit_do.bml.addfriends.head=Barátok hozzáadása + +/friends/edit_do.bml.addfriends.text=Ãrd be a barátaid LiveJournal felhasználóneveit az alábbi rubrikákba, és válaszd ki, milyen elÅ‘- és háttérszíneket akarsz hozzájuk rendelni. + +/friends/edit_do.bml.background=Háttér + +/friends/edit_do.bml.bgcolor=Háttérszín: + +/friends/edit_do.bml.btn.close=Bezárás + +/friends/edit_do.bml.btn.save=Változtatások mentése + +/friends/edit_do.bml.btn.toggle=ElÅ‘nézeti ablak + +/friends/edit_do.bml.done.head=Kész? + +/friends/edit_do.bml.done.text=Ha kész vagy, kattints az alábbi "Változtatások mentése" gombra. + +/friends/edit_do.bml.error.updating=Hiba lépett fel a "barátok" listád frissítése közben. + +/friends/edit_do.bml.fellowfriends.head=Barátok + +/friends/edit_do.bml.fellowfriends.text=Az alábbi felhasználóknál barátként szerepelsz. Ha gondolod, viszonozhatod ezt azzal, hogy te is felveszed Å‘ket a saját listádra. Ez nem kötelezÅ‘, de így tudni fogod LiveJournal felhasználói nevüket. + +/friends/edit_do.bml.foreground=ElÅ‘tér + +/friends/edit_do.bml.friend=Barát + +/friends/edit_do.bml.hover=Mozgasd az egered egy szín fölé, hogy a nevét megnézhesd. + +/friends/edit_do.bml.mrcolor=Mr. Szín NézegetÅ‘ + +/friends/edit_do.bml.name=Név + +/friends/edit_do.bml.needmore=Ha több barátot szeretnél hozzáadni listádhoz, mint amennyi ezen az űrlapon elfér, csak mentsd el a változtatásokat a lap alján, majd gyere vissza ide. + +/friends/edit_do.bml.nofriends.head=Nincsenek barátaid? + +/friends/edit_do.bml.nofriends.text=Jelenleg senki sincs a "barátok" listádon. Ãm mi biztosra vesszük, hogy kell lennie egy-kettÅ‘nek! :) Csak írd be a LiveJournal azonosítójukat ide: + +/friends/edit_do.bml.opt.addtolist=Barát hozzáadása + +/friends/edit_do.bml.opt.delete=Törölni akarod? + +/friends/edit_do.bml.success.head=Siker + +/friends/edit_do.bml.success.text=A barátlistád fel lett frissítve. Itt tekintheted meg. + +/friends/edit_do.bml.textcolor=Szövegszín: + +/friends/edit_do.bml.title=Barátok szerkesztése + +/friends/edit_do.bml.user=Felhasználó + +/friends/edit_do.bml.viewer=Szín NézegetÅ‘ + +/friends/edit_do.bml.yourfriends.head=Barátaid + +/friends/edit_do.bml.yourfriends.text=Jelenleg a következÅ‘ felhasználókat nevezted meg barátaidként: + +/friends/filter.bml.error.nogroups.header=Nincsenek barát csoportjaid + +/friends/filter.bml.title=Barát lista szűrése + +/friends/index.bml.about<< +Ezen a lapon vezetheted barátaid listáját. +További felhasználókat adva barátaid listájához könnyen követheted naplójuk alakulását. Felvehetsz ide teljes közösségeket vagy csoportokat is. +. + +/friends/index.bml.edit.about=Barátok hozzáadása és elvétele, színek szerkesztése + +/friends/index.bml.editgroups.about=Csoportok létrehozása, szerkesztése, törlése + +/friends/index.bml.filter=Ezek a csoportok arra is jók, hogy szűréssel csak azokat a barátaidat lásd, akik bizonyos csoportba tartoznak. Használhatsz még csoportra vonatkozó biztonsági beállításokat is (lásd lejjebb). + +/friends/index.bml.filter.about=Szűrd barátaid listáját csoporthoz tartozás szerint. + +/friends/index.bml.groups=Barátaidat csoportokba is szervezheted: + +/friends/index.bml.security.header=Biztonság + +/friends/index.bml.title=Barátok lista vezetése + +/friends/index.bml.tools=Eszközök + +/friends/popwithfriends.bml.account_type=Sajnáljuk, de jelenlegi fióktípusoddal ezt az eszközt nem használhatod. + +/friends/popwithfriends.bml.no_users=Nincs ilyen felhasználó + +/friends/popwithfriends.bml.user=Felhasználó + +/go.bml.defaulttitle=Hiba + +/index.bml.about.header=A LiveJournalról + +/index.bml.about.joining=A csatlakozás ingyenes, azonban lehetÅ‘ség van felfejleszteni a felhasználói fiókot, így extra lehetÅ‘ségekhez juthatsz. + +/index.bml.about.us=A LiveJournal egy egyszerűen használható (ugyanakkor hatékony és testreszabható) webnapló (blog) közzétevÅ‘ eszköz, ami nyílt forráskódú szoftver felhasználásával készült. + +/index.bml.boldcreate=Készítsd el saját LiveJournalod! + +/index.bml.frank.image.alt=Frank, a LiveJournal kabala kecskéje. + +/index.bml.frank.logo="Meeeee", szól Frank. + +/index.bml.learnmore.header=Akarsz többet tudni? + +/index.bml.learnmore.text=Kérjük, olvasd el az áttekintÅ‘t a lehetÅ‘ségekrÅ‘l. MeggyÅ‘ztünk? Indítsd el saját LiveJournal-odat! + +/index.bml.meta.desc=A LiveJournal.com egy hely, ahol megoszthatod gondolataidat a világgal. + +/index.bml.meta.keywords=napló, online napló, naplók, naplóírás, webes napló, webnapló, blog, blogírás + +/index.bml.post=Bejegyzések + +/index.bml.post.hour=Óránként: + +/index.bml.post.latest=Friss írások + +/index.bml.post.min=Percenként: + +/interests.bml.add.added.head=Hozzáadva! + +/interests.bml.add.added.text=Az új érdeklÅ‘dési kör hozzá lett adva a listádhoz. + +/interests.bml.add.btn.text=[[interest]] Hozzáadása + +/interests.bml.add.confirm.head=MegerÅ‘sítés + +/interests.bml.add.confirm.text=[[interest]], mint új érdeklÅ‘dési kör hozzáadásához kattints az alábbi gombra. + +/interests.bml.add.toomany.head=Bocs... + +/interests.bml.add.toomany.text=Elérted a maximálisan meghatározható [[maxinterests]] érdeklÅ‘dési kört. + +/interests.bml.addint=Ha téged ez érdekel, és szeretnéd a listádhoz hozzáadni, klikkelj ide. + +/interests.bml.communities.head=A Témához kapcsolódó Közösségek + +/interests.bml.communities.text="[[interest]]" a következÅ‘ közösségeket is érdekli. + +/interests.bml.count=Száma + +/interests.bml.enmasse.body.other=Alant láthatod [[user]] érdeklÅ‘dési köreit. Jelöld be azokat, amelyeket a sajátodéhoz hozzá szeretnél adni, és töröld azokat, amelyek nem kellenek. Ha kész vagy, nyomd meg a "Változtatások mentése" gombot. + +/interests.bml.enmasse.body.other_authas=Alant láthatod [[user]] érdeklÅ‘dési köreit. Jelöld be azokat, amelyeket [[target]] listájához hozzá szeretnél adni, és töröld azokat, amelyeket el akarsz venni. Ha kész vagy, nyomd meg a "Változtatások mentése" gombot. + +/interests.bml.enmasse.body.you=Töröld azokat az érdeklÅ‘dési köröket, amelyek nem kellenek. Ha kész vagy, nyomd meg a "Változtatások mentése" gombot. + +/interests.bml.enmasse.btn=Listázás + +/interests.bml.enmasse.header=ÉrdeklÅ‘dési körök hozzáadása/elvétele + +/interests.bml.enmasse.intro=ÉrdeklÅ‘dési köreid módosítása felhasználó alapján: + +/interests.bml.error.add.mustlogin=Új érdeklÅ‘dési körök ilyen úton történÅ‘ hozzáadásához be kell jelentkezned. + +/interests.bml.error.findsim_do.intnotfound=Az érdeklÅ‘dési kör nem található. + +/interests.bml.findsim.searchwait=Megjegyzés: A keresés eltarthat néhány másodpercig. Kérlek, légy türelmes. + +/interests.bml.findsim_do.account.notallowed=Sajnos a fiókod típusa nem teszi lehetÅ‘vé ennek az eszköznek a használatát. + +/interests.bml.findsim_do.nomatch.head=Nincs Találat + +/interests.bml.findsim_do.nomatch.text=Nincsenek a [[user]] nevű felhasználóhoz hasonlító felhasználók. + +/interests.bml.findsim_do.notdefined=A [[user]] nevű felhasználó nem határozott meg érdeklÅ‘dési köröket. + +/interests.bml.findsim_do.similar.head=Hasonló Felhasználók + +/interests.bml.findsim_do.similar.text=A következÅ‘ felhasználók állnak a legközelebb a [[user]] nevű felhasználóhoz. + +/interests.bml.finished.about=Ha kész vagy, nyomd meg a "Változtatások mentése" gombot. + +/interests.bml.finished.header=Készen van? + +/interests.bml.finished.save_button=Változtatások mentése + +/interests.bml.interest=ÉrdeklÅ‘dés + +/interests.bml.interested.btn.find=Keresés + +/interests.bml.interested.in=Személyek/közösségek keresése érdeklÅ‘dési kör szerint: + +/interests.bml.interests.head=ÉrdeklÅ‘dés + +/interests.bml.interests.text=Itt találhatsz néhány mókás dolgot, amit az érdeklÅ‘dési körök segítségével csinálhatsz. + +/interests.bml.interests.viewpop=Népszerű érdeklÅ‘dési körök megtekintése + +/interests.bml.login.enterinfo=Add meg felhasználói nevedet és jelszavadat érdeklÅ‘dési köreid módosításához. + +/interests.bml.login.proceed=Végrehajtás... + +/interests.bml.match=[[count]] találat: + +/interests.bml.matches=[[count]] találat: + +/interests.bml.morestuff=Még több szórakoztató lehetÅ‘ség található az "érdeklÅ‘dési körök" oldalon. + +/interests.bml.nointerests.text=Még nem határoztad meg az érdeklÅ‘dési köreidet? A "Személyes Információk és Beállítások Megváltoztatása" oldalon ezt is megteheted. + +/interests.bml.popular.head=Népszerű ÉrdeklÅ‘dési körök + +/interests.bml.popular.text=A következÅ‘ érdeklÅ‘dési körök a legnépszerűbbek: + +/interests.bml.results.added=A kiválasztott érdeklÅ‘dések hozzáadódtak az érdeklÅ‘dési listádhoz. + +/interests.bml.results.both=Az érdeklÅ‘dések módosítása megtörtént. + +/interests.bml.results.del_and_toomany=A törölt érdeklÅ‘dési köröket levettük a listádról. Viszont túl sokat akartál hozzáadni, max. [[intcount]] lehet rajta. Az újonnan bejelöltek közül egyet se adtunk hozzá. Javasoljuk, menj vissza, és próbálj kevesebbet kiválasztani. + +/interests.bml.results.goback=Kattints ide, ha vissza akarsz menni [[user]] felhasználó profiljához. + +/interests.bml.results.header=Eredmények + +/interests.bml.results.message=Nézd meg a módosított profillapodat. + +/interests.bml.results.nothing=Nem változtattál semmit. + +/interests.bml.results.toomany=Túl sok érdeklÅ‘dési kört jelöltél ki hozzáadásra, max. [[intcount]] lehet a listádon összesen. Az újonnan bejelöltek közül egyet se adtunk hozzá. Javasoljuk, menj vissza, és próbálj kevesebbet kiválasztani. + +/interests.bml.title=ÉrdeklÅ‘dés + +/interests.bml.toomany.body=[[intcount]] ember és/vagy közösség határozta meg ezt érdeklÅ‘dési köreként. A lista nem lesz megjelenítve. + +/interests.bml.toomany.head=Nagyon sok találat + +/interests.bml.users.head=Ebben érdekelt felhasználók + +/interests.bml.users.text=[[interest]] az alábbi felhasználókat érdekli. + +/invite/index.bml.error=Hiba + +/legal/index.bml.about.header=Ãttekintés + +/legal/index.bml.docs.header=Dokumentumok + +/legal/index.bml.title=Legális Információ + +/legal/privacy.bml.title=Adatvédelmi nyilatkozat + +/legal/tos.bml.title=A Szolgáltatás Feltételei + +/login.bml.bindip.label=Rögzítés az IP-címhez + +/login.bml.bindip.no=Ne rögzítsen (minden szolgáltatóval működik) + +/login.bml.bindip.yes=Rögzítsen (biztonságosabb) + +/login.bml.error.mustenterusername=Ãrj be egy felhasználónevet! + +/login.bml.expire.btn.neverexpire=SOHA ne járjon le + +/login.bml.expire.btn.sessiononly=Lejárat BÖNGÉSZÉS VÉGÉN + +/login.bml.expire.neverexpire.text=A bejelentkezésed soha nem évül el; Ha olyan helyen vagy, ahol a számítógépet mások is használhatják, pl. iskolában, könyvtárban stb., akkor gondoskodj arról, hogy kijelentkezel, amikor kész vagy! Vagy pedig változtasd meg beállításaidat úgy, hogy a bejelentkezés a böngészés végén elévüljön! + +/login.bml.expire.sessiononly.text=Bejelentkezésed a böngészÅ‘ bezárásakor érvényét veszíti. Amennyiben ezt a gépet csak te használod, lehet, hogy jobb ha beállítod, hogy a bejelentkezés sosem évüljön el. + +/login.bml.links.head=Linkek + +/login.bml.links.link1=Barátaid bejegyzései. + +/login.bml.links.link2=Tennivalóid listája. + +/login.bml.links.text=A jövÅ‘ben ez a lap mindenféle linkeket és egyéb információt is fog tartalmazni, de egyelÅ‘re csak együkét linket adunk: + +/login.bml.loggedin.head=Sikeres bejelentkezés! + +/login.bml.loggedin.text=Most már be vagy jelentkezve. + +/login.bml.login.btn.changeopts=Beállítások mentése + +/login.bml.login.btn.login=Bejelentkezés… + +/login.bml.login.expiration=Elévülés: + +/login.bml.login.forget=Elfelejtetted? + +/login.bml.login.head=Bejelentkezés + +/login.bml.login.never=Soha + +/login.bml.login.otheropts=Egyéb beállítások: + +/login.bml.login.password=Jelszó: + +/login.bml.login.text1=Ãrd be felhasználóneved és jelszavad a bejelentkezéshez. Új felhasználók: Új fiók létrehozásához látogasd meg a megfelelÅ‘ lapot! + +/login.bml.login.text2=Megadhatod még, hogyan évüljön el a bejelentkezésed. Alapból akkor, ha bezárod a böngészÅ‘t; ez például akkor jó, ha publikus számítógépet használsz. Beállíthatod viszont, hogy a bejelentkezés ne évüljön el: ha egyedül használod a számítógépet, ez jó ötlet lehet. Többet olvashatsz errÅ‘l a Mik ezek a beállítások bejelentkezés után? c. gyakran idézett kérdés alatt. + +/login.bml.login.text3=[[username]], sikeresen bejelentkeztél [[sitename]] szerverre. A navigáláshoz kedved szerint használhatod a Honlaptérképet. + +/login.bml.login.username=Azonosító: + +/login.bml.login.whenbrowsercloses=Amikor a böngészÅ‘t bezárom + +/login.bml.logout.btn=Kijelentkezés + +/login.bml.title=Bejelentkezés + +/login.bml.whylogin.benefit1=Nem kell majd a site többi részén beírkálnod az azonosítód és jelszavad (pl. válaszüzenet írása, stb.). + +/login.bml.whylogin.benefit2=Láthatod barátaid „védett†naplóbejegyzéseit (persze csak akkor, ha Å‘k azt megengedték). + +/login.bml.whylogin.benefit3=Egy csomó szolgáltatás csak akkor érhetÅ‘ el, ha be vagy jelentkezve. + +/login.bml.whylogin.head=Miért kell bejelentkezni? + +/login.bml.whylogin.text=Ãlljon itt néhány példa, miért is: + +/logout.bml.already.head=Már ki vagy jelentkezve + +/logout.bml.already.text=Már egyszer kijelentkeztél, nem kell még egyszer. + +/logout.bml.loggedout.already=Már kiléptél. + +/logout.bml.loggedout.head=Kijelentkezve + +/logout.bml.loggedout.success=Kijelentkezve. + +/logout.bml.loggedout.text=Sikeresen kijelentkeztél. + +/logout.bml.logout.btn=Kijelentkezés + +/logout.bml.logout.head=Kijelentkezél? + +/logout.bml.logout.text=A kijelentkezéshez klikkelj az alábbi gombra. + +/logout.bml.title=Kijelentkezés + +/lostinfo.bml.btn.proceed=Tovább + +/lostinfo.bml.enter_email=Ãrd be e-mail címed: + +/lostinfo.bml.enter_email_optional=E-mail cím (elhagyható): + +/lostinfo.bml.enter_username=Ãrd be az azonosítódat: + +/lostinfo.bml.error.no_email=Meg kell adnod egy e-mail címet, ha a felhasználói nevedet meg szeretnéd tudni. + +/lostinfo.bml.error.purged=Nem lehet egy törölt fiók jelszavát visszaszerezni, ha már végérvényesen el lett távolítva. + +/lostinfo.bml.lostpassword.text=Ha elfelejtetted a jelszavadat, írd be ide a felhasználói nevedet és, ha akarod, az e-mail címedet is. Az e-mail címnek olyannak kell lennie, amit már egyszer visszaigazoltál a LiveJournal szerverén. Ha üresen hagyod, a jelenleg beállított e-mail címedre fog menni a levél, akkor is ha nincs visszaigazolva a jelenleg beállított e-mail címed. + +/lostinfo.bml.lostpassword.title=Elfelejtetted a jelszavad? + +/lostinfo.bml.lostusername.text=Ha elfelejtetted az azonosítódat, írd be az e-mail címedet és mi elküldjük neked! + +/lostinfo.bml.lostusername.title=Netán az azonosítódat? + +/lostinfo.bml.title=Elfelejtett adatok + +/lostinfo_do.bml.error.no_usernames_for_email=Nincs felhasználó regisztrálva a [[address]] címen. + +/lostinfo_do.bml.error1.text=Ezt az e-mail címet te sosem használtad itt vagy sosem hagyattad jóvá. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Ez egy automatikusan generált e-mail. Ne válaszolj rá *** + +Ez egy emlékeztetÅ‘ e-mail jelszavadról, a(z) [[sitename]] adatbázisából. +Alább látható az azonosítód, jelszavad és a regisztrált e-mail címed. + + Azonosító: [[username]] + Jelszó: [[password]] + E-mail cím: [[emailadr]] + +. + +/lostinfo_do.bml.lostpasswordmail.part2=E-mail címed jóváhagyatásához menj az alábbi címre: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ezt az információt a website-on a [[remoteip]] címrÅ‘l kérték. + +Ha nem te kérvényezted, ne ijedj meg. Végül is te kaptad meg az e-mailt és nem a másik ember. Lehetséges, hogy a másik azt hiszi, az övé ez az azonosító, de az is megtörténhetett, hogy valaki elgépelt valamit, míg a saját jelszavát akarta megtudni. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Ha valóban úgy véled, naplód nincs biztonságban, olvasd el a http://www.livejournal.com/support/faqbrowse.bml?faqid=117 lapot! + +/lostinfo_do.bml.lostpasswordmail.part5<< +Hasznos linkek: + + A naplód: + [[journalurl]] + + Napló online frissítése: + [[updateurl]] + +Ãœdvözlettel, +A LiveJournal Csapat. + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Elfelejtett jelszó + +/lostinfo_do.bml.password_mailed.text=Jelszavadat sikeresen kipostáztuk. + +/lostinfo_do.bml.password_mailed.title=Jelszó kipostázva! + +/lostinfo_do.bml.title=Elfelejtett adatok + +/lostinfo_do.bml.username_mailed.text=Azonosítódat sikeresen kipostáztuk. + +/lostinfo_do.bml.username_mailed.title=Azonosító postázva! + +/manage/index.bml.about=Válassz az alábbi menükbÅ‘l: + +/manage/index.bml.communities=Saját közösségek létrehozása és vezetése + +/manage/index.bml.communities.create.about=Új közösség létrehozása + +/manage/index.bml.communities.header=Közösségek + +/manage/index.bml.communities.manage.about=Saját közösségeid beállításai és tagjai + +/manage/index.bml.customization=Naplód kinézetének testreszabása + +/manage/index.bml.customization.advanced=Speciális testreszabás + +/manage/index.bml.customization.customize=Napló testreszabása + +/manage/index.bml.customization.header=Testreszabás + +/manage/index.bml.customization.links=Linkek listája + +/manage/index.bml.customization.links.about=Naplódban megjelenÅ‘ linkek létrehozása + +/manage/index.bml.customization.modify.about=Naplód megjelenési beállításai + +/manage/index.bml.customization.s1.header=S1 stílusú rendszer + +/manage/index.bml.customization.s2.header=S2 stílusú rendszer + +/manage/index.bml.entries=Bejegyzések szerkesztése a naplódban + +/manage/index.bml.entries.edit.about=Bejegyzések szerkesztése és törlése + +/manage/index.bml.entries.header=Naplóbejegyzések + +/manage/index.bml.entries.memories.about=Emlékezetes eseményeid megtekintése és szerkesztése + +/manage/index.bml.friends=Barátok és "barát" csoportok szerkesztése, vagy barátok szűrése elmentett csoportok alapján: + +/manage/index.bml.friends.edit.about=Barátok hozzáadása és elvétele, színek szerkesztése + +/manage/index.bml.friends.filter=Barátok szűrése + +/manage/index.bml.friends.filter.about=Barátaid egy csoportjának megjelenítése szűrés alapján + +/manage/index.bml.friends.groups.about=Csoportos hozzáadás, szerkesztés, vagy törlés a barátaid listáján + +/manage/index.bml.friends.header=Barátok + +/manage/index.bml.information=Itt állíthatod be, hogy milyen információkat szeretnél látni fiókodban: + +/manage/index.bml.information.changepass=Fiók jelszavának módosítása + +/manage/index.bml.information.changepass.about=Fiókod jelszavának módosítása + +/manage/index.bml.information.editinfo.about=Fiókod tulajdonságainak szerkesztése és egyéb beállítások + +/manage/index.bml.information.emailpost=E-mail átjáró (gateway) beállítások + +/manage/index.bml.information.header=Fiók tulajdonságai + +/manage/index.bml.information.siteopts.about=Oldalad elrendezése és nyelve + +/manage/index.bml.information.status=Fiók állapota + +/manage/index.bml.information.status.about=Fiókod állapota (törlés, vagy visszahozás) + +/manage/index.bml.title=Fiókok kezelése + +/manage/index.bml.userpictures=A felhasználó képeidet feltöltése és igazgatása: + +/manage/index.bml.userpictures.edit.about=Töltsd fel és igazgasd a felhasználó képeidet. + +/manage/index.bml.userpictures.header=Felhasználó Képek + +/manage/links.bml.about=Az alábbi űrlappal megszerkesztheted linkjeid listáját. Vigyázz, ezek csak akkor jelennek meg a naplódban, ha a kiválasztott S2 stílusod támogatja Å‘ket. + +/manage/links.bml.about.blank=Ãœres sor létrehozásához írj egy kötÅ‘jelet (-) címnek. + +/manage/links.bml.about.heading=Ha egy sorba nem linket, csak feliratot szeretnél, hagyd üresen az URL-t. + +/manage/links.bml.about.reorder=Ha meg akarod változtatni a linkek sorrendjét, írd át a sorszámukat baloldalt (mindegy, milyen számot írsz, növekvÅ‘ sorrendben lesznek a linkek listázva). + +/manage/links.bml.error.s2required=Linklista csak bizonyos S2-es stílusrendszerekben lehet. Ha át akarsz váltani S2-re, kattints ide: [[link]]. + +/manage/links.bml.error.s2required.header=Ehhez az S2-es stílusrendszer kell. + +/manage/links.bml.success=Linkjeidet sikeresen elmentettük. + +/manage/links.bml.title=Linkek listája + +/manage/phonepost.bml.delete=Beállítások törlése + +/manage/phonepost.bml.deleted.header=Törölve + +/manage/phonepost.bml.error.inuse=Érvénytelen PIN, próbáld újra + +/manage/phonepost.bml.error.phone.length=Telefonszámodnak legalább 10 számjegyűnek kell lennie. + +/manage/phonepost.bml.error.pin=A PIN csak számjegyekbÅ‘l állhat. + +/manage/phonepost.bml.pin=Személyi Azonosító Kód (PIN): + +/manage/phonepost.bml.pin.help=4-6 számjegy ajánlott + +/manage/phonepost.bml.save=Beállítások mentése + +/manage/phonepost.bml.saved=Elmentve + +/manage/phonepost.bml.success.text=Telefonbeállításaidat elmentettük. + +/manage/phonepost.bml.transcribers.help=Egyéni "barát" csoportok szerkesztése + +/manage/siteopts.bml.btn.lang=Nyelv váltása + +/manage/siteopts.bml.btn.scheme=Séma váltása + +/manage/siteopts.bml.head.lang=Nyelv kiválasztása + +/manage/siteopts.bml.head.scheme=Kedvenc sémád kiválasztása + +/manage/siteopts.bml.scheme.preview=[[[title]] séma elÅ‘nézete] + +/modify.bml.title=Napló testreszabása + +/modify_do.bml.availablestyles.head=Rendelkezésre álló stílusok + +/modify_do.bml.availablestyles.userstyles=Felhasználói stílusok: + +/modify_do.bml.colortheme.about=Itt tudod kiválasztani, milyen séma szerint legyen színezve a fent kiválasztott elrendezésed. Ha az elÅ‘re definiált sémák nem tetszenek neked, alább magad is beállíthatod egyenként a színeket. + +/modify_do.bml.colortheme.area.head=Használati terület + +/modify_do.bml.colortheme.color.head1=Szín + +/modify_do.bml.colortheme.color.head2=(#rrggbb vagy szabványos színnév [angol]) + +/modify_do.bml.colortheme.customcolors=Egyéni színek + +/modify_do.bml.colortheme.defaulttheme=Alap színséma + +/modify_do.bml.colortheme.head=Színséma + +/modify_do.bml.domainalias.about=Ha van már bejegyzett domained vagy tervezel bejegyezni egyet, és szeretnéd, hogy az automatikusan a LiveJournalodat töltse be, írd be a domain nevet ide! + +/modify_do.bml.domainalias.domainname=Domain név: + +/modify_do.bml.domainalias.example=Például: my-journal.com + +/modify_do.bml.domainalias.head=Domain aliasing + +/modify_do.bml.domainalias.helptext=Ahhoz, hogy ez működjön, be kell állíttatnod a DNS szerveren, hogy a domain neved a [[sitename]] IP címre mutasson. További információk + +/modify_do.bml.done.btn.savechanges=Változtatások mentése + +/modify_do.bml.done.head=Kész? + +/modify_do.bml.done.text=Ha elkészültél, kattints a lenti „Változtatások mentése†gombra! + +/modify_do.bml.error.dupdomainalias=Valaki más már megadta ugyanezt a domain aliast. + +/modify_do.bml.error.stylenotavailable=Az általad választott stílusok egyike nem elérhetÅ‘. Ez lehet annak az eredménye, hogy valaki letörölte a stílust, vagy olyat választottál, amihez nem férhetsz hozzá. + +/modify_do.bml.friends.about=Itt találhatók olyan beállítások, melyekkel a naplód barát nézetén tudsz állítani. + +/modify_do.bml.friends.head=Barát nézet + +/modify_do.bml.friends.opt.usesharedpic.about=Ezzel a beállítással azt tudod kiválasztani, hogy milyen kép jelenjen meg akkor, ha egy felhasználó egy megosztott vagy egy közösségi naplóba ír. Ha bejelölöd, a közösség ikonját fogod látni, ha nem, akkor pedig a felhasználóét. + +/modify_do.bml.friends.opt.usesharedpic.head=Mutassa a megosztott elérésű napló ikonjait a felhasználókéi helyett + +/modify_do.bml.journaloptions.about=InnentÅ‘l lefele a naplód kinézetén tudsz finomítani. Ha igazán kíváncsi vagy, hogyan működnek a dolgok, vess egy pillantást a fejlesztÅ‘i oldalakra! Különben reméljük, hogy az alábbi alapvetÅ‘ beállításokkal elégedett leszel. + +/modify_do.bml.journaloptions.head=Naplóbeállítások + +/modify_do.bml.journalstatus.about=Amennyiben törölni szeretnéd a naplódat, vagy éppenséggel meggondoltad magad és egy korábbi törlÅ‘ utasítást visszavonni szeretnél, azt itt teheted meg. Miután törölted, vagyis törlésre jelölted a naplódat, 30 napod van, hogy ezt visszavond. A 30 nap elteltével a naplót visszavonhatatlanul kitöröljük a rendszerbÅ‘l, és visszaszerzésére nem lesz mód. + +/modify_do.bml.journalstatus.head=Napló aktiválásának állapota + +/modify_do.bml.journalstatus.select.activated=Aktiválva + +/modify_do.bml.journalstatus.select.deleted=Törölve + +/modify_do.bml.journalstatus.select.head=Ãllapot: + +/modify_do.bml.journalstatus.select.suspended=Felfüggesztve + +/modify_do.bml.moodicons.about=Amikor egy bejegyzést írsz, meghatározhatod a jelenlegi hangulatodat. Több felhasználó különbözÅ‘ hangulatot kifejezÅ‘ ikont készített, amelyeket te is használhatsz. Ha nem akarsz képet használni, választhatod a "nincs ikon" funkciót is. (De ha nem akarod, nem is fontos jelezned a jelenlegi hangulatodat.) + +/modify_do.bml.moodicons.head=Hangulat-ikonok + +/modify_do.bml.moodicons.personal=Személyes sémák: + +/modify_do.bml.moodicons.preview=elÅ‘nézet + +/modify_do.bml.moodicons.select=Válaszd ki a hangulat-ikon készletet: + +/modify_do.bml.overrides.box.head=Ãtgázolások: + +/modify_do.bml.overrides.head=Stílusi átgázolások: + +/modify_do.bml.overrides.warning=IDE NE GÉPELJ BE A BEJEGYZÉSEIDET! + +/modify_do.bml.pagelayoutstyle.about=Ennek a beállítása adja meg, hogy miként legyen a naplód a képernyÅ‘n elhelyezve. + +/modify_do.bml.pagelayoutstyle.head=Lap elrendezési stílusa + +/modify_do.bml.pagelayoutstyle.warning=A fiókod típusa csak néhány alapértelmezett stílus kiválasztását teszi lehetÅ‘vé. + +/modify_do.bml.success.head=Siker + +/modify_do.bml.success.text=A naplód beállításai frissítve lettek. Itt megtekintheted a (frissített) naplódat. + +/multisearch.bml.nomatch.text=Nem volt találat a megadott feltételek alapján. + +/multisearch.bml.region.head=Régiók szerinti keresés + +/paidaccounts/index.bml.costs.header=Mennyibe kerül? + +/paidaccounts/index.bml.costs.rates=Az árak a következÅ‘k: + +/paidaccounts/index.bml.costs.rates.amount.header=Mennyiség + +/paidaccounts/index.bml.costs.rates.time.header=IdÅ‘ + +/paidaccounts/index.bml.title=FizetÅ‘s Fiókokról + +/paidaccounts/index.bml.whypay.header=Kell-e fizetnem a LiveJournalért? + +/paidaccounts/index.bml.your_username=felhasználó_neved + +/paidaccounts/usepaypal.bml.delivery.badformat=A küldés megadott dátumának formátuma érvénytelen. Ãgy éééé-hh-nn vagy így éééé-hh-nn óó:pp kell kinéznie. + +/paidaccounts/usepaypal.bml.delivery.past=A küldés dátuma nem lehet egy múltbéli idÅ‘pont. Az azonnali küldéshez hagyd üresen a "küldés dátuma" rublikát. + +/paidaccounts/usepaypal.bml.delivery.toofuture=A küldés dátuma nem lehet a mai dátumhoz képest egy hónapnál késÅ‘bbi idÅ‘pont. + +/pay/index.bml.deliverydate.details=Formátum: éééé-hh-nn óó:pp (GMT IdÅ‘)
        (ha a késleltetés nélküli küldést szeretnéd, ne írj be semmit) + +/pay/index.bml.deliverydate.label=A küldés dátuma: + +/pay/index.bml.gift.anonymous=Névtelen ajándék + +/poll/create.bml.button.editpoll=Szavazás módosítása + +/poll/create.bml.button.insert=Beillesztés + +/poll/create.bml.button.postpoll=Szavazás készítése + +/poll/create.bml.button.preview=Szavazás elÅ‘nézete + +/poll/create.bml.button.seecode=Kódolás megtekintése + +/poll/create.bml.button.startover=Újra kezdés + +/poll/create.bml.pollname=Szavazás címe: (nem kötelezÅ‘) + +/poll/create.bml.question=Kérdés: + +/poll/create.bml.questionnum=Kérdés #[[num]] + +/poll/create.bml.questions=Szavazás kérdései + +/poll/create.bml.whoview=Ki láthatja ezt a szavazást? + +/poll/create.bml.whovote=Ki szavazhat ebben a szavazásban? + +/poll/index.bml.discuss=Vissza a bejegyzésbe + +/poll/index.bml.error.cantview=Sajnáljuk, de nincs jogod ezt a szavazást megtekinteni. + +/poll/index.bml.filloutpoll=Szavazás (kitöltés) + +/poll/index.bml.pollnotfound=A szavazás nem található. + +/poll/index.bml.submitted.head=Köszi + +/poll/index.bml.submitted.text=A szavazatodat hozzáfűztük a többihez. + +/poll/index.bml.submitted.title=Siker! + +/poll/index.bml.title=Szavazás + +/poll/index.bml.viewresults=Szavazás eredményeinek megtekintése + +/press/staff.bml.administration=Adminisztráció + +/register.bml.new.update=Új bejegyzés a naplóba + +/register.bml.sent.body=Egy megerÅ‘sítÅ‘ levelet küldtünk [[email]] címre. Az abban található linkre kell kattintanod, hogy érvényesítsd regisztrációdat. + +/rename/use.bml.error.unknown=Ismeretlen hiba történt átnevezés közben. + +/site/goat.bml.title=Kecske Frank + +/suggestions/index.bml.howto.title=Hogyan tehetek javaslatokat? + +/suggestions/index.bml.info.title=Egyéb Információ + +/suggestions/index.bml.title=Javaslatok Helye + +/suggestions/index.bml.welcome.text=A felhasználói javaslatok a LiveJournal fontos részét képezik. Ha úgy gondolod, hogy van egy klassz ötleted, amit az oldal üzemeltetÅ‘inek is meg szeretnél mutatni, kövesd az alábbi instrukciókat. + +/suggestions/index.bml.welcome.title=Ãœdvözöljük! + +/support/append_request.bml.back.requests=Vissza a nyított támogatás kérésekre. + +/support/append_request.bml.back.support=Vissza a támogatás fÅ‘lapra. + +/support/append_request.bml.closed.text=A támogatási kérés már be van csukva. + +/support/append_request.bml.closed.title=Becsukva. + +/support/append_request.bml.invalid.blank=Az üzeneted üres volt. Be kell valamit gépelned az üzenet-mezÅ‘be. + +/support/append_request.bml.invalid.nocat=Ez a kategória nem létezik. + +/support/append_request.bml.logged.title=Siker + +/support/append_request.bml.login.required=Be kell jelentkezned ahhoz, hogy segítesz a támogatásban. + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.unknown.request=Ismeretlen támogatási kérés. + +/support/encodings.bml.edit.header=Nem tudom módosítani a bejegyzéseimet a webes kezelÅ‘felületen! + +/support/encodings.bml.editcl.header=Nem tudom módosítani a bejegyzéseimet a kliens programmal! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.still.header=Még mindig van problémád? + +/support/encodings.bml.still.text=Támogatási részen.p?> + +/support/encodings.bml.title=Kódolások + +/support/faqbrowse.bml.backfaq=Vissza a GyIK fÅ‘lapjára + +/support/faqbrowse.bml.backfaqcat=Vissza a GyIK fÅ‘menüjébe. + +/support/faqbrowse.bml.backsupport=Vissza a tanácsadás fÅ‘lapjára. + +/support/faqbrowse.bml.edit.faq=Javítani ezen a GyÃK-on + +/support/faqbrowse.bml.error.nofaq=A kért GyÃK nem létezik + +/support/faqbrowse.bml.lastupdated=Utoljára frissítve: + +/support/faqbrowse.bml.title_cat=GYIK - [[catname]] + +/support/faqbrowse.bml.title_num=Gyakran ismételt kérdés #[[num]] + +/support/see_overrides.bml.error.noprivs=Csak olyan felhasználok nézhet a másik felhasználó átgázolását, amelynek van a supportviewscreened vagy supporthelp joga. + +/support/see_overrides.bml.error.nos1=Ez a felhasználó nem használja S1-t. + +/support/see_overrides.bml.header= átgázolásai: + +/support/see_overrides.bml.nooverrides=-nek nincsen átgázolása + +/support/see_overrides.bml.title=Felhasználó átgázolásai + +/syn/index.bml.account=Fiók: + +/syn/index.bml.error.unknown=Ismeretlen hiba + +/syn/index.bml.invalid.http.text=Hiba történt az URL megnyitása közben. A szerver foglalt lehet, vagy nem érhetÅ‘ el. EllenÅ‘rizd, hogy jó címet adtál-e meg, és próbálkozz újra. + +/syn/index.bml.invalid.http.title=Hiba történt letöltés közben. + +/talkmulti.bml.deleted.body=A hozzászólásokat töröltük. A vitafonált itt tekintheted meg. + +/talkmulti.bml.deleted.title=Hozzászólások törölve + +/talkmulti.bml.error.comms_deleted=A hozzászólások egyike már törölve lett, amióta kijelölted törlésre. Kérjük, hogy - biztonsági okokból - próbáld újra. + +/talkmulti.bml.error.login=Nem vagy bejelentkezve. + +/talkmulti.bml.error.none_selected=Nem jelöltél ki semmilyen hozzászólást. + +/talkmulti.bml.error.privs.delete=Nincsen jogod arra, hogy ezeket a hozzászólásokat letörölhessed. + +/talkmulti.bml.error.privs.screen=Nincsen jogod arra, hogy ezeket a hozzászólásokat elrejthessed. + +/talkmulti.bml.screened.body=A hozzászólásokat elrejtettük. Itt megtekintheted Å‘ket. + +/talkmulti.bml.screened.title=Hozzászólásokat elrejtettük + +/talkmulti.bml.title.delete=Több hozzászólás törlése + +/talkmulti.bml.title.screen=Több hozzászólás elrejtése + +/talkpost.bml.allowedhtml=Megengedett HTML + +/talkpost.bml.error.cannotreplynopost=Nem válaszolhatsz nem létezÅ‘ bejegyzésre + +/talkpost.bml.error.nocommentsjournal=A felhasználó nem engedélyezte a hozzászólást + +/talkpost.bml.error.nocommentspost=A felhasználó nem kíván ennél a bejegyzésnél megjegyzéseket + +/talkpost.bml.error.noreplypost=Nem találjuk a bejegyzést, amihez a választ írtad (kitörölték?) + +/talkpost.bml.error.noreply_deleted=Ez a hozzászólás már törölve van, nem tudsz rá választ írni. + +/talkpost.bml.error.noreply_screened=Ez a hozzászólás rejtett, és nincsen jogod arra, hogy láthassad, vagy válaszolhass rá. + +/talkpost.bml.label.picturetouse=Használandó kép: + +/talkpost.bml.loganonip=Figyelem! A felhasználó beállította az anonim hozzászólások IP-naplózását! + +/talkpost.bml.loginq=Bejelentkezel? + +/talkpost.bml.logyourip=Figyelem! A felhasználó beállította a hozzászólók IP-inek naplózását! + +/talkpost.bml.nosubjecthtml=A téma nem tartalmazhat HTML kódokat + +/talkpost.bml.opt.anonymous=Névtelen + +/talkpost.bml.opt.defpic=(alapértelmezett) + +/talkpost.bml.opt.friendsonly=- a felhasználó letiltotta a nem-barát és a névtelen hozzászólásokat. Ide csak akkor írhatsz, ha fenn vagy [[username]] barátlistáján. + +/talkpost.bml.opt.from=Ãrta: + +/talkpost.bml.opt.ljuser=LiveJournal felhasználó: + +/talkpost.bml.opt.loggedin=Bejelentkezett felhasználó: [[username]] + +/talkpost.bml.opt.message=Ãœzenet: + +/talkpost.bml.opt.noanonpost=- a felhasználó letiltotta a névtelen üzeneteket. + +/talkpost.bml.opt.noautoformat=Ne formázzon automatikusan: + +/talkpost.bml.opt.noimage=Nincs kép + +/talkpost.bml.opt.preview=ElÅ‘nézet + +/talkpost.bml.opt.spellcheck=Helyesírás-ellenÅ‘rzés a bejegyzés elküldése elÅ‘tt + +/talkpost.bml.opt.subject=Téma: + +/talkpost.bml.opt.submit=Hozzászólás elküldése + +/talkpost.bml.opt.willscreen=(el lesz rejtve) + +/talkpost.bml.opt.willscreenfriend=(el lesz rejtve ha nem barát írta) + +/talkpost.bml.paraformat=Az alapbeállítások szerint a bekezdéseket automatikusan formázzuk. + +/talkpost.bml.postresponse=Válaszüzenet küldése + +/talkpost.bml.title=Ãœzenet küldése + +/talkpost_do.bml.error.badpassword=Hibás jelszót adtál meg a felhasználónév mellé. Amennyiben elfelejtetted a jelszavadat, innen újra megszerezheted. + +/talkpost_do.bml.error.badusername=A LiveJournal felhasználónév, amit megadtál, nem létezik. Amennyiben elfelejtetted felhasználói azonosítódat, hozzájuthatsz itt, vagy írhatsz mint névtelen felhasználó. + +/talkpost_do.bml.error.banned=Nincs engedélyed arra, hogy ennek a felhasználónak a naplójába írjál. + +/talkpost_do.bml.error.blankmessage=Ãœzeneted üres volt. Ãrjál valamit abba a mezÅ‘be is. + +/talkpost_do.bml.error.confused_identity=Beírtál egy felhasználói nevet, de azt választottad, hogy névtelenül vagy az aktuálisan bejelentkezett felhasználóként üzensz. Menj vissza és döntsd el, mit szeretnél. + +/talkpost_do.bml.error.deleted=A naplódat kitörölted; így nem tudsz a neveden üzeneteket írni. + +/talkpost_do.bml.error.friendsonly=Csak [[user]] barátai írhatnak ebbe a naplóba. + +/talkpost_do.bml.error.lostcookie=Eltűnt a bejelentkezési cookie-d? + +/talkpost_do.bml.error.manybytes=Sajnáljuk, de a [[current]] byte-os üzeneted túllépi a megengedett méretet, ami [[limit]] byte. Menj vissza és kurtítsd meg az üzenetet, majd próbálkozz újra. + +/talkpost_do.bml.error.manychars=Sajnáljuk, de a [[current]] karakteres üzeneted túllépi a megengedett karaktermennyiséget, ami [[limit]] karakter. Menj vissza és rövidítsd meg az üzenetet, majd próbálkozz újra. + +/talkpost_do.bml.error.mustlogin=Be kell legyél jelentkezve, vagy be kell írnod egy azonosítót és egy jelszót, hogy válaszolhass erre a védett bejegyzésre. + +/talkpost_do.bml.error.noanon=Ebbe a naplóba névtelenül nem írhatsz. + +/talkpost_do.bml.error.noauth=Nincs engedélyed arra, hogy erre a védett bejegyzésre válaszolj. + +/talkpost_do.bml.error.nocomments=A felhasználó letiltotta a válaszlehetÅ‘séget erre a bejegyzésre. + +/talkpost_do.bml.error.notafriend=Sajnáljuk, de [[user]] nem helyezett téged a barátlistájára, és beállította, hogy csak barátai válaszolhatnak naplóbejegyzéseire. + +/talkpost_do.bml.error.nousername=Nem írtad be a LiveJournal nevedet. Ha nincs még felhasználói fiókod, postázhatsz névtelenül is. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Sajnáljuk, de addig nem írhatsz mások naplóiba, amíg e-mail címedet nem ellenÅ‘riztük. Amennyiben elvesztetted a visszaigazoló e-mailt, újraküldetheted az elveszett adatok lapról. + +/talkpost_do.bml.error.postshared=Nem postázhatsz megosztott ill. közösségi fiókként. Ezek több embert reprezentálnak, nem egyet. + +/talkpost_do.bml.error.screened=Nincsen jogod arra, hogy válaszolhass erre a rejtett hozzászólásra. + +/talkpost_do.bml.error.suspended=Naplódat felfüggesztették, nem írhatsz üzeneteket ezen a néven. + +/talkpost_do.bml.error.testacct=TesztelÅ‘ fiókok csak tesztelÅ‘ naplókban használhatók. + +/talkpost_do.bml.opt.preview=ElÅ‘nézet + +/talkpost_do.bml.preview=Alább látszik, hogyan fog kinézni a hozzászólásod. A szövegmezÅ‘ben tovább szerkesztheted vagy a megfelelÅ‘ gombbal véglegesen elküldheted. + +/talkpost_do.bml.preview.subject=Téma: + +/talkpost_do.bml.preview.submit=Elküld + +/talkpost_do.bml.preview.title=ElÅ‘nézet + +/talkpost_do.bml.success.loggedin=Most be vagy jelentkezve. + +/talkpost_do.bml.success.message=Megjegyzésedet hozzáfűztük a többihez. Itt megnézheted. + +/talkpost_do.bml.success.title=Siker + +/talkpost_do.bml.success.unscreened=Továbbá, a rejtett üzenet amire válaszoltál mostantól nincs elrejtve. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Hozzászólás elküldve + +/talkpost_do.bml.title.preview=Hozzászólás elÅ‘nézete + +/talkread.bml.anonuser=(Névtelen) + +/talkread.bml.confirm.action=Biztos, hogy le akarsz törölni a kijelölt hozzászólásokat? + +/talkread.bml.deletedpost=(Törölt üzenet) + +/talkread.bml.deleteduser=(Törölt felhasználó: [[username]]) + +/talkread.bml.fromip=([[ip]] címrÅ‘l) + +/talkread.bml.noreplies=Nincs válasz + +/talkread.bml.nosubject=(nincs téma) + +/talkread.bml.replysuspended=(Válasz egy felfüggesztett felhasználótól) + +/talkread.bml.screenedpost=(Elrejtett hozzászólás) + +/talkread.bml.select=Kijelölés + +/talkread.bml.subjectdeleted=[törölve] + +/talkread.bml.talkmulti.delete=Törlés + +/talkread.bml.talkmulti.des=Minden kijelölt hozzászólásra: + +/talkread.bml.talkmulti.screen=Elrejtés + +/talkread.bml.talkmulti.submit=Végrehajtás + +/talkread.bml.talkmulti.unscreen=Felfedés + +/talkread.bml.title=Hozzászólások olvasása + +/talkscreen.bml.error.login=Be kell jelentkezned, hogy a rejtett hozzászólásokon állíthass. + +/talkscreen.bml.error.privs.screen=Nincsen jogod arra, hogy ezt a hozzászólást elrejthesd. + +/talkscreen.bml.error.privs.unscreen=Nincsen jogod a rejtés megszűntetéséhez. + +/talkscreen.bml.screen.doit=Igen, rejtse el ezt a hozzászólást. + +/talkscreen.bml.screen.sure.body=Biztos, hogy el akarod rejteni ezt a hozzászólást? + +/talkscreen.bml.screen.sure.title=Elrejted ezt a hozzászólást? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=A hozzászolás elrejtve. + +/talkscreen.bml.screened.title=Siker + +/talkscreen.bml.title=Hozzászólás elrejtve + +/talkscreen.bml.unscreen.doit=Ne legyen többé rejtve ez a hozzászólás + +/talkscreen.bml.unscreen.sure.body=Biztos, hogy többé nem akarod rejteni ezt a hozzászólást? + +/talkscreen.bml.unscreen.sure.title=Ne rejtsük többé? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=A hozzászólás nincs többé elrejtve. + +/talkscreen.bml.unscreened.title=Siker + +/tools/emailmanage.bml.address.current.title=Jelenlegi cím + +/tools/emailmanage.bml.address.old.title=ElÅ‘zÅ‘ cím + +/tools/emailmanage.bml.log.deleted=Törölve: [[email]] @ [[time]] + +/tools/emailmanage.bml.notvalidated.title=E-mail nincs visszaigazolva + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Emlékezetes bejegyzéseid listája módosítva. + +/tools/memadd.bml.body.added.header=Siker + +/tools/memadd.bml.description=Leírás: + +/tools/memadd.bml.description.text<< +Fűzz egy rövid leírást ehhez a bejegyzéshez, amirÅ‘l meg tudod jegyezni. +Ha ki akarod törölni az emlékezetes bejegyzéseid listájáról, töröld ki a leírását. +. + +/tools/memadd.bml.error.deleted.body="[[desc]]" nevű bejegyzésed törölve lett az emlékezetes bejegyzések listájából. + +/tools/memadd.bml.error.deleted.title=Emlék törölve + +/tools/memadd.bml.error.entry_deleted=A bejegyzés már nem létezik. Emlék törölve. + +/tools/memadd.bml.error.fivekeywords=Egy emlékhez max. 5 kulcsszót írhatsz. + +/tools/memadd.bml.error.login=Ennek a funkciónak a használatához be kell jelentkezned. Utána visszakerülsz erre a lapra. + +/tools/memadd.bml.error.maxsize="[[keyword]]" kulcsszó túl hosszú. + +/tools/memadd.bml.form.submit=Küldés + +/tools/memadd.bml.keywords=Kulcsszavak: + +/tools/memadd.bml.login.enterinfo=Ãrd be annak a felhasználónak a nevét és jelszavát, akihez menteni akarod ezt az emléket. + +/tools/memadd.bml.login.forgot.header=Elfelejtettél valamit? + +/tools/memadd.bml.login.forgot.recover=Ha elfelejtetted a neved vagy jelszavad, itt hozzájuthatsz azokhoz! + +/tools/memadd.bml.security.friendsonly=Csak barátok + +/tools/memadd.bml.security.private=Privát + +/tools/memadd.bml.security.public=Publikus + +/tools/memadd.bml.title=Emlék hozzáadása + +/tools/memadd.bml.title.added=Hozzáadva + +/tools/memadd.bml.title.add_memory=Emlék hozzáadása + +/tools/memadd.bml.title.deleted=Törölve + +/tools/memadd.bml.title.edit_memory=Emlék Módosítása + +/tools/memadd.bml.whocansee=Ki láthatja ezt a bejegyzést? Mindenki, vagy csak akiket barátként jelöltél meg, vagy csak te magad? + +/tools/memadd.bml.whocansee.comm=Ki láthatja ezt a bejegyzést? Mindenki, vagy csak a közösség tagjai, vagy csak a közösség karbantartói? + +/tools/memories.bml.back=Vissza + +/tools/memories.bml.body.keyword<< + +[[user]] emlékezetesnek talált. p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] emlékezetes írásokat helyezett. p?> +. + +/tools/memories.bml.body.memorable=Az alábbi lista azokat a kategorizálatlan bejegyzéseket mutatja, amiket [[user]] emlékezetesnek talált. + +/tools/memories.bml.edit=módosítás + +/tools/memories.bml.error.noentries.body<< +Ennek az oka az lehet, hogy
          +
        1. a felhasználó nem állított be egyetlen bejegyzést se emlékezetesnek, vagy
        2. +
        3. az emlékezetes eseményei védettek, és nincs hozzájuk jogod, vagy
        4. +
        5. a szűrés feltételeinek egy sem felel meg.
        +. + +/tools/memories.bml.error.noentries.title=Nincsenek bejegyzések. + +/tools/memories.bml.filter.all=Összes bejegyzés + +/tools/memories.bml.filter.other=Csak mások bejegyzései + +/tools/memories.bml.filter.own=Csak '[[user]]' bejegyzései + +/tools/memories.bml.form.filter=Bejegyzések szűrése: + +/tools/memories.bml.form.sort=Bejegyzések rendezése: + +/tools/memories.bml.form.switch=Váltás + +/tools/memories.bml.login=Hogy megnézhesd saját bejegyzéseidet, kérjük, jelentkezz be. + +/tools/memories.bml.sort.description=Leírás + +/tools/memories.bml.sort.journal=Napló + +/tools/memories.bml.sort.orderadded=Szempont hozzáadva + +/tools/memories.bml.title.keyword=[[keyword]] bejegyzések + +/tools/memories.bml.title.memorable=Emlékezetes bejegyzések + +/tools/memories.bml.uncategorized=Nincs osztályozva + +/update.bml.altpost=FrissítendÅ‘ napló: + +/update.bml.btn.update=Bejegyzés ! + +/update.bml.currmood=Jelenlegi hangulat: + +/update.bml.currmusic=Jelenlegi zene: + +/update.bml.date=Dátum: + +/update.bml.default=alapértelmezett + +/update.bml.defaultjournal=([[user]]) -- alapértelmezett + +/update.bml.error.cantpost=Sajnáljuk, pillanatnyilag nem írhatsz ide. + +/update.bml.error.disabled=A fióktípusod nem engedi meg a bejegyzést. + +/update.bml.error.disabled.title=Bejegyzés letiltva + +/update.bml.error.login=Hiba történt bejelentkezés közben: + +/update.bml.error.nopass=Ãrd be a jelszót + +/update.bml.error.update=Hiba történt a napló frissítése közben: + +/update.bml.event=Esemény: + +/update.bml.full=Teljes frissítÅ‘ lap + +/update.bml.htmlokay.norich=(HTML kód mehet; alapértelmezésként az enterek átformázódnak <br>-ré) + +/update.bml.htmlokay.rich=(HTML kód mehet; alapértelmezésként az enterek átformázódnak <br>-ré. Másik lehetÅ‘ségként használhatod a rich text módot.) + +/update.bml.htmlokay.rte_nosupport=(Sajnáljuk, de a böngészÅ‘d nem támogatja a rich text környezetet.) + +/update.bml.localtime=Helyi idÅ‘: + +/update.bml.loggedinas=Pillanatnyilag [[user]]-ként vagy bejelentkezve.
        Ha más néven akarsz írni, kattints ide. + +/update.bml.loggingin=Bejelentkezés a kiszolgálóhoz… + +/update.bml.noneother=Nincsen, vagy más: + +/update.bml.note|staleness=1 +/update.bml.note=Figyelem! A fenti idÅ‘ a szerverünktÅ‘l származik. Szükség esetén illeszd az értékeked a saját idÅ‘zónádhoz! + +/update.bml.opt.backdate=Bejegyzés visszadátumozása: + +/update.bml.opt.backdate.about=nem fog megjelenni a barátlapon + +/update.bml.opt.defpic=(alapértelmezett) + +/update.bml.opt.nocomments=Hozzászólások tiltása: + +/update.bml.opt.noemail=Ne küldjön e-mailt: + +/update.bml.opt.noformat=Ne formázzon automatikusan: + +/update.bml.opt.spellcheck=(Amerikai angol) helyesírás ellenÅ‘rzése elküldés elÅ‘tt + +/update.bml.options=Egyéb beállítások + +/update.bml.other=Egyéb: + +/update.bml.password=Jelszó: + +/update.bml.picture=Használandó kép: + +/update.bml.security.custom=Egyéni… + +/update.bml.security.friends=Barátok + +/update.bml.security.head=Biztonsági szint: + +/update.bml.security.private=Privát + +/update.bml.security.public=Publikus + +/update.bml.servermsg=Továbbá, a kiszolgáló a következÅ‘ üzenetet küldte: + +/update.bml.simple=Az egyszerű lapot látod. Több beállítási lehetÅ‘séghez kattints ide! + +/update.bml.spellchecked=Helyesírás-ellenÅ‘rzött bejegyzésed: + +/update.bml.subject=Téma: (nem kötelezÅ‘) + +/update.bml.timeformat=24 órás idÅ‘forma + +/update.bml.title=Új naplóbejegyzés + +/update.bml.title.readonly=Csak olvasható mód + +/update.bml.update.head=Ãrj a naplódba + +/update.bml.update.success=A naplóba írás sikeresen megtörtént. A frissített naplódat itt megtekintheted. + +/update.bml.updating=Naplód frissítés alatt… + +/update.bml.username=Felhasználói név: + +/userinfo.bml.about.comm=Rólunk: + +/userinfo.bml.about.user=Életrajz/Leírás: + +/userinfo.bml.body.leave=A közösséget bármikor elhagyhatod. + +/userinfo.bml.comminfo.body=Alább egy keveset olvashatsz a LiveJournal „[[commname]]†közösségérÅ‘l. + +/userinfo.bml.comminfo.name=Közösség adatai + +/userinfo.bml.date.never=Soha. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Hibás azonosító. + +/userinfo.bml.error.notloggedin=Ha meg szeretnéd tekinteni a saját adataidat, be kell jelentkezned. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Figyelik: + +/userinfo.bml.friendof.hidden=(rejtve) + +/userinfo.bml.friendof.syndreadcount=Olvasók száma + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Barátja: + +/userinfo.bml.friends.comm=Tagok + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Barátai + +/userinfo.bml.label.addbuddy=Haver hozzáadása + +/userinfo.bml.label.adduser=Felhasználó hozzáadása + +/userinfo.bml.label.birthdate=Születésnap: + +/userinfo.bml.label.clientsused=Használt kliensek: + +/userinfo.bml.label.comments=Hozzászólások: + +/userinfo.bml.label.composted=Ãrt: [[num]] — + +/userinfo.bml.label.comreceived=Kapott: [[num]] + +/userinfo.bml.label.datecreated=Létrehozva: + +/userinfo.bml.label.dateupdated=Utolsó frissítés: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.interests=ÉrdeklÅ‘dés + +/userinfo.bml.label.interests.modifyyours=ÉrdeklÅ‘déseid módosítása ez alapján + +/userinfo.bml.label.interests.removesome=ÉrdeklÅ‘dések elvétele + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] egyéb dolog iránt érdeklÅ‘dik még + +/userinfo.bml.label.journalentrs=Bejegyzések: + +/userinfo.bml.label.location=Hely: + +/userinfo.bml.label.memberof=Tagja + +/userinfo.bml.label.memories=Emlékezetes bejegyzések: + +/userinfo.bml.label.moredetails=(további részletek...) + +/userinfo.bml.label.msnusername=MSN azonosító: + +/userinfo.bml.label.name=Név: + +/userinfo.bml.label.nofriends=Nincsenek. + +/userinfo.bml.label.postalt=Ãrj a naplódba + +/userinfo.bml.label.reqfinduser=Csak a finduser privilégiummal rendelkezÅ‘ felhasználók kereshetnek azonosító szerint. + +/userinfo.bml.label.searchjournal=Keresés ebben a naplóban + +/userinfo.bml.label.sendmessage=Ãœzenet küldése + +/userinfo.bml.label.shared=Ãrási jog: + +/userinfo.bml.label.supportpoints=Támogatási pontok + +/userinfo.bml.label.syndicatedfrom=HírközlÅ‘ forrás: + +/userinfo.bml.label.syndicatedstatus=Hírközlés állapota: + +/userinfo.bml.label.textmessage=Szöveges
        üzenet
        : + +/userinfo.bml.label.todo=Tennivalók listája + +/userinfo.bml.label.user=Felhasználó: + +/userinfo.bml.label.viewfriends=Barátok megtekintése + +/userinfo.bml.label.viewmembers=Tagok megtekinése + +/userinfo.bml.label.website=Honlap: + +/userinfo.bml.membership.body=A közösségbe való belépéshez kattints ide! + +/userinfo.bml.memories.entries=[[count]] bejegyzés + +/userinfo.bml.memories.entry=[[count]] bejegyzés + +/userinfo.bml.monitor.comm=Közösség figyelése + +/userinfo.bml.monitor.user=Felhasználó felvétele a barátok közé + +/userinfo.bml.nonexist.body=Nincs felhasználó regisztrálva [[user]] azonosítóval. + +/userinfo.bml.nonexist.name=Ismeretlen felhasználó + +/userinfo.bml.sendmessage.body=Küldj [[user]] mobiljára egy szöveges üzenetet! + +/userinfo.bml.syn.last.never=Soha + +/userinfo.bml.syn.lastcheck=Utoljára ellenÅ‘rizve: + +/userinfo.bml.syn.nextcheck=KövetkezÅ‘ ellenÅ‘rzés: + +/userinfo.bml.syn.parseerror=Hibaüzenet: + +/userinfo.bml.syndinfo.body=Ha szeretnéd, hogy a hírforrás által közzétett („syndicatedâ€) cikkek megjelenjenek a barátlapodon, vedd fel ezt a naplót a barátlistádra! + +/userinfo.bml.syndinfo.name=HírközlÅ‘ napló + +/userinfo.bml.tellafriend=Mondd el egy barátodnak! + +/userinfo.bml.timeupdate.dayago=1 napja + +/userinfo.bml.timeupdate.daysago=[[num]] napja + +/userinfo.bml.timeupdate.hourago=1 órája + +/userinfo.bml.timeupdate.hoursago=[[num]] órája + +/userinfo.bml.timeupdate.minuteago=1 perce + +/userinfo.bml.timeupdate.minutesago=[[num]] perce + +/userinfo.bml.timeupdate.secondago=1 másodperccel ez elÅ‘tt + +/userinfo.bml.timeupdate.secondsago=[[num]] másodperccel ez elÅ‘tt + +/userinfo.bml.timeupdate.weekago=1 hete + +/userinfo.bml.timeupdate.weeksago=[[num]] hete + +/userinfo.bml.title=Felhasználó adatai + +/userinfo.bml.title.communityinfo=Közösség adatai + +/userinfo.bml.title.syndicated=HírközlÅ‘ fiók + +/userinfo.bml.userinfo.body=Alább látható egy kis információ [[username]] felhasználóról. Ha te vagy az, ezeket bármikor megváltoztathatod. + +/userinfo.bml.userinfo.name=Felhasználó adatai + +bml.needlogin.body2=Ennek a lapnak a megtekintéséhez be kell jelentkezned. + +BML.parse_multipart.parse=A feltöltött adat nem elemezhetÅ‘ + +BML.parse_multipart.toolarge=A feltöltött adat túl nagy + +BML.parse_multipart.unknowntype=Hibás MIME type. + +btn.search=Keres + +crumb.about=A LiveJournalról + +crumb.birthdays=Születésnapok + +crumb.changepass=Jelszó megváltoztatása + +crumb.contributors=Munkatársok + +crumb.createcommunity=Közösség létrehozása + +crumb.createjournal=Napló létrehozása + +crumb.createstyle=Stílus létrehozása + +crumb.customize=S2 beállítások testreszabása + +crumb.delcomment=Hozzászólás törlése + +crumb.download=Kliens program letöltése + +crumb.editentries=Bejegyzések módosítása + +crumb.editentries_do=Bejegyzés módosítása + +crumb.editfriendgrps=Barátcsoportok szerkesztése + +crumb.editfriends=Barátok szerkesztése + +crumb.editinfo=Szemelyes adatai + +crumb.editpics=Felhasználói képek + +crumb.editstyle=Stilus módosítása + +crumb.faq=Gyakrani Idézett Kérdések + +crumb.friends=Barátok lista vezetése + +crumb.friendsfilter=Barát lista szűrése + +crumb.goat=Frank, a kecskérÅ‘l + +crumb.home=FÅ‘lap + +crumb.itsfree=Ingyenes? + +crumb.leavecomm=Közösség elhagyása + +crumb.linkslist=Linkjeid listája + +crumb.login=Bejelentkezés + +crumb.logout=Kijelentkezés + +crumb.manage=Fiókok kezelése + +crumb.managecommunity=Közösség vezetés + +crumb.memories=Emlékezetes bejegyzések + +crumb.moodlist=Hangulat-nézegetÅ‘ + +crumb.news=Újság + +crumb.paidaccounts=FizetÅ‘s fiókok + +crumb.paidacctstatus=FizetÅ‘s fiók állapota + +crumb.preview=Elrendezés elÅ‘nézete + +crumb.privacy=Adatvédelmi nyilatkozat + +crumb.register=E-mail cím visszaigazolása + +crumb.search=Keresés + +crumb.searchinterests=ÉrdeklÅ‘dés szerint + +crumb.searchregion=Régiók szerint + +crumb.seeoverrides=Felhasználó átgázolásai megtekintése + +crumb.sitemap=Honlaptérkép + +crumb.themes=Séma elÅ‘nézetek + +crumb.todo=Tennivalók listája + +crumb.update=Új bejegyzés + +date.day.friday.long=Péntek + +date.day.friday.short=Péntek + +date.day.monday.long=HétfÅ‘ + +date.day.saturday.long=Szombat + +date.day.sunday.long=Vasárnap + +date.day.thursday.long=Csütörtök + +date.day.tuesday.long=Kedd + +date.day.wednesday.long=Szerda + +date.month.april.long=április + +date.month.april.short=ápr + +date.month.august.long=augusztus + +date.month.august.short=aug + +date.month.december.long=december + +date.month.december.short=dec + +date.month.february.long=február + +date.month.february.short=feb + +date.month.january.long=január + +date.month.january.short=jan + +date.month.july.long=július + +date.month.july.short=júl + +date.month.june.long=június + +date.month.june.short=jún + +date.month.march.long=március + +date.month.march.short=márc + +date.month.may.long=május + +date.month.may.short=máj + +date.month.november.long=november + +date.month.november.short=nov + +date.month.october.long=október + +date.month.october.short=okt + +date.month.september.long=szeptember + +date.month.september.short=szept + +dystopia.btn.login=BEJELENTKEZÉS + +dystopia.hello_anonymous=Ãœdvözlünk a LiveJournalon! + +dystopia.hello_loggedin=Szia, [[username]]! + +dystopia.nav.createjournal=Napló készítése + +dystopia.nav.developer=FejlesztÅ‘i oldalak + +dystopia.nav.download=Letöltés + +dystopia.nav.editentries=Szerkesztés + +dystopia.nav.editfriends=Barátaid + +dystopia.nav.editpassword=Jelszavad + +dystopia.nav.editpics=Képeid + +dystopia.nav.editstyle=Stílus szerkesztése + +dystopia.nav.faq=LiveJournal GyIK + +dystopia.nav.findcomm=Közösségközpont + +dystopia.nav.finddir=Keresés + +dystopia.nav.findint=ÉrdeklÅ‘dés szerint + +dystopia.nav.findrandom=Véletlenszerűen + +dystopia.nav.findregion=Régiók szerint + +dystopia.nav.home=FÅ‘lap + +dystopia.nav.journalcalendar=Naptár + +dystopia.nav.journalfriends=Barátok + +dystopia.nav.journalinfo=Felhasználó adatai + +dystopia.nav.journalrecent=Legfrissebb + +dystopia.nav.legalprivacy=Titoktartás + +dystopia.nav.legaltos=Szolgáltatási Szabályzat + +dystopia.nav.login=Bejelentkezés + +dystopia.nav.logout=Kilépés + +dystopia.nav.lostinfo=Elfelejtett jelszó + +dystopia.nav.memories=Emlékek + +dystopia.nav.modifyjournal=Napló testreszabása + +dystopia.nav.news=Hírek + +dystopia.nav.paidaccts=FizetÅ‘s fiókok + +dystopia.nav.paymentarea=Befizetés + +dystopia.nav.personalinfo=Személyes adatok + +dystopia.nav.sitemap=Honlaptérkép + +dystopia.nav.support=Kérdésed van? + +dystopia.nav.updatejournal=Új naplóbejegyzés + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=148 + +dystopia.navhead.findusers=Keresés + +dystopia.navhead.help=Segítség + +dystopia.navhead.journal=A Te Naplód + +dystopia.navhead.legal=Jogi dolgok + +dystopia.navhead.settings=Beállításaid + +dystopia.navhead.welcome=Ãœdvözlünk! + +dystopia.search.icq=ICQ azonosító + +dystopia.search.int=ÉrdeklÅ‘dési témák + +dystopia.search.msn=MSN azonosító + +dystopia.search.region=Terület/régió + +dystopia.searchlj=Keresés a LiveJournalon: + +Email=E-mail + +email.newacct.subject=Ãœdvözlünk a LiveJournalon! + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Hiba + +error.badpassword=Hibás jelszó + +error.dberror=Adatbázishiba: + +error.deleted.name=Törölve + +error.deleted.text=Ezt a naplót törölték. Ha te vagy [[user]], a törléstÅ‘l számítva 30 napod van arra, hogy visszavond a napló törlését. A 30 nap eltelte után minden adatot törölni fogunk a szervereinkrÅ‘l. + +error.deleted.title=Törölt fiók + +error.ipbanned=IP címed a belépési hibák mennyiségének túllépése miatt ideiglenesen tiltólistára került. + +error.malformeduser=Hibás felhasználónév. + +error.nobutton=Nem ütöttek le gombot? + +error.nodb=Az adatbázis pillanatnyilag nem elérhetÅ‘. + +error.nodbmaintenance=Az adatbázis ezen része karbantartás miatt nem elérhetÅ‘. Pár perc múlva próbálkozz újra. + +error.noentry=Nincs ilyen naplóbejegyzés. + +error.nojournal=Ismeretlen napló + +error.noremote=Be kell jelentkezned ahhoz, hogy ezt a lapot használhasd. + +error.procrequest=Hiba történt a kérés feldolgozása közben: + +error.purged.name=Törölve + +error.purged.text=Ez a napló már végérvényesen el lett távolítva. + +error.purged.title=Végérvényesen eltávolított fiók + +error.suspended.name=Felfüggesztve + +error.suspended.title=Felfüggesztett Fiók + +error.usernamelong=Felhasználó név túl hosszú, 15 karakter maximum. + +error.username_notfound=Felhasználó név nem létezik. + +Help=Súgó + +label.screening.all=Mindet + +label.screening.anonymous=Csak a névteleneket + +label.screening.default=Alapértelmezett + +label.screening.header=Hozzászólások elrejtése: + +label.screening.none=Egyiket sem + +label.screening.nonfriends=Csak a nem barátokét + +label.security.friends=Barátok + +label.security.head=Biztonsági szint: + +label.security.private=Privát + +label.security.public=Publikus + +label.switch.button=Ãtvált + +label.switch.header=Naplóváltás + +label.switch.workwith=Melyik naplóval dolgozzunk? + +langname.be=belarusz + +langname.da=dán + +langname.de=német + +langname.en=amerikai angol + +langname.en_GB=angol + +langname.en_LJ=angol + +langname.eo=eszperantó + +langname.es=spanyol + +langname.et=észt + +langname.fi=finn + +langname.fr=francia + +langname.ga=ír + +langname.gd=skót + +langname.he=héber + +langname.hu=Magyar + +langname.is=izlandi + +langname.it=olasz + +langname.ja=japán + +langname.la=latin + +langname.lv=lett + +langname.ms=maláj + +langname.nb=norvég (BokmÃ¥l) + +langname.nl=holland + +langname.nn=norvég (Nynorsk) + +langname.pl=lengyel + +langname.pt=portugál + +langname.ru=orosz + +langname.sv=svéd + +langname.tr=török + +langname.uk=ukrán + +langname.zh=egyszerűsített kínai + +ljcom.account.feature.email=LiveJournal e-mail cím + +ljcom.account.free=Ingyenes Fiók + +ljcom.account.paid=FizetÅ‘s fiók + +ljcom.accounttype=Fiók típusa + +ljcom.menu.upgrade=Osztályozd fel a felhasználó fiokodat! + +ljcom.userinfo.accounttype=Fiók típusa + +ljcom.userinfo.paiduser=FizetÅ‘s fiók + +ljcom.userinfo.types.free=Ingyenes Fiók + +ljcom.userinfo.types.paid=FizetÅ‘s fiók + +ljcom.userinfo.types.paid_expiring=FizetÅ‘s fiók, lejárat dátuma: [[paiduntil]] + +ljcom.userinfo.types.permanent=Permanens Fiók + +ljlib.pageofpages=[[page]]. az összesen [[total]] lapból + +lostinfo.head=Elfelejtettél valamit? + +lostinfo.text=Ha elfelejtetted azonosítódat vagy jelszavadat, itt hozzájuk juthatsz. + +lynx.nav.friends=Barátok + +lynx.nav.help=Teknikai támogatás + +lynx.nav.home=FÅ‘lap + +lynx.nav.login=Bejelentkezés + +lynx.nav.logout=Kijelentkezés + +lynx.nav.recent=Legutóbbi bejegyzések + +lynx.nav.sitemap=Honlaptérkép + +lynx.nav.update=Napló frissítése + +Password=Jelszó + +password.max30=A jelszó nem lehet hosszabb 30 karakternél. + +poll.dberror=Adatbázis hiba: [[errmsg]] + +poll.dberror.items=Adatbázis hiba beillesztése során: [[errmsg]] + +poll.dberror.questions=Adatbázis hiba kérdések beillesztése során: [[errmsg] + +poll.error.cantview=Hiba: nincs jogod ennek a szavazásnak az eredményeinek megtekintéséhez. + +poll.error.cantvote=Sajnos, nincs jogod ebben a szavazásban részt venni. + +poll.error.noquestions=Kell legalább egy kérdést beírni a szavatodba. + +poll.error.pollnotfound=Hiba: Szavazás #[[num]] nem található. + +poll.error.questionnotfound=Hiba: ez a kérdés nem létezik. + +poll.error.whoview=whoview (ki káthatja) kell 'all' (bárki), 'friends' (barátok), vagy 'none' (senki) lenni. + +poll.error.whovote=whovote (ki szavazhat) kell 'all' (bárki) vagy 'friends' (barátok) lenni. + +poll.pollnum=Szavazás #[[num]] + +poll.security=Ki szavazhat: [[whovote]], ki tekintheti meg az eredményeket: [[whoview]] + +poll.security.all=Bárki + +poll.security.friends=Barátok + +poll.security.none=Senki + +poll.submit=Szavazz! + +poll.viewanswers=Eredmény megtekintése + +portal.bdays.portalname=Születésnapok + +portal.bdays.portaltitle=Születésnapok + +portal.memories.entriesnoun=bejegyzések + +portal.memories.entrynoun=bejegyzés + +portal.memories.portalname=Emlékezetes bejegyzések + +portal.memories.portaltitle=Emlékezetes bejegyzések + +portal.ministats.active=Aktív: + +portal.ministats.title=Felhasználóink + +portal.ministats.total=Összes: + +portal.popfaq.portalname=10 Leggyakranabb tekintve GyÃKot + +portal.popfaq.portaltitle=10 Leggyakranabb tekintve GyÃKot + +portal.randuser.hidename.des=Alapértelmezettenként, egy véletlenül talált felhasználó nevet mutatja. Kattints ide az eltávolításához. + +portal.randuser.hidename.name=Név elrejtése + +portal.randuser.hidepic.des=Alapértelmezettenként, egy véletlenül talált felhasználó kép mutatja, ha lehet. Kattints ide az eltávolításához. + +portal.randuser.hidepic.name=Felhasználó kép elrejtése + +portal.randuser.portalname=Véletlenül talált felhasználó + +portal.randuser.portaltitle=Véletlenül talált felhasználó + +portal.randuser.portaltitleplural=Véletlenül talált felhasználók + +portal.recent.error.noentries=Bocs. Nincsen bejegyzés. + +portal.recent.error.userstatus=Felhasználó letörölte vagy felfüggeszték a fiókját. + +portal.recent.journal.name=Napló + +portal.recent.nosubject=(Nincsen Téma) + +portal.recent.permlink=Vitafonál + +portal.recent.showtext.description=Alapértelmezetként, csak a témák láthatóak. + +portal.stats.journalentyest=Tegnapi bejegyzések + +portal.stats.portalname=Honlap statisztika + +portal.stats.portaltitle=Statisztika + +portal.update.mode.simple=Egyszerűbbített + +portal.update.portalname=Új naplóbejegyzés + +portal.update.portaltitle=Új naplóbejegyzés + +protocol.bad_password=Jelszavad túl könnyen kitalálható.  Ajánlott, hogy megváltoztasd, különben naplód ki van téve a veszélynek, hogy ellopják.  Látogasd meg a [[siteroot]]/changepassword.bml lapot a jelszó megváltoztatásához. + +protocol.hello_test=Szia teszt! + +protocol.must_revalidate=Vissza kell igazolnod az új e-mail címedet. A régi jó volt, de, mivel megváltoztattad, az új címedet is vissza kell igazolnod. Ha ezt nem teszed meg, akkor nem lesz hozzáférésed a(z) [[sitename]] mindegyik funkciójához. Több információt errÅ‘l a témáról, itt olvashatsz: [[siteroot]]/support/faqbrowse.bml?faqid=11 + +protocol.not_validated=Az e-mail címed nincs visszaigazolva. LehetÅ‘ségedben áll a [[sitename]] további használata, de, ha nem igazolod vissza a címedet, akkor nem lesz hozzáférésed az oldal összes funkciójához. Olvasd el a tájékoztatót a felhasználó fiókod készítésekor a részedre elküldött e-mailben, vagy bÅ‘vebb információért errÅ‘l a témáról, látogasd meg a következÅ‘ oldalt: [[siteroot]]/support/faqbrowse.bml?faqid=11 + +protocol.old_win32_client=Már sok, újabb Windows alatt futó LiveJournal kliens program is elérhetÅ‘, ezért azt ajánljuk, hogy tölts le egy újabb verziót. Látogasd meg a [[siteroot]]/download/ lapot egy újabb kliens program letötltéséhez. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Bocs + +talk.anonwrote=Valaki írta: + +talk.anonwrote_comm=Valaki írta [[commlink]] lapon: + +talk.btn.preview=ElÅ‘nézet + +talk.commentpermlink=link + +talk.commentpost=Új hozzászólás + +talk.commentsread=Hozzászólások olvasása + +talk.curname_Mood=Jelenlegi hangulat: + +talk.curname_Music=Jelenlegi zene: + +talk.error.bogusargs=Hablaty argumentumok + +talk.error.comm_deleted=Ezt a hozzászólást törölték. + +talk.error.deleted=Ezt a naplót törölték. + +talk.error.deleted.title=Törölve + +talk.error.mustlogin=Be kell, hogy jelentkezve legyél, hogy elolvasd ezt a védett üzenetet. + +talk.error.nocomment=Ez a hozzászólás nem létezik. + +talk.error.noentry=Nincs ilyen bejegyzés. + +talk.error.nojournal=Hiba: az argumentumok alapján nem lehetett meghatározni a naplót. + +talk.error.nosuchjournal=Nincs ilyen napló + +talk.error.notauthorised=Nincs engedélyed arra, hogy ezt a védett bejegyzést megnézd + +talk.error.suspended=Ez a napló/felhasználó fel van függesztve. + +talk.error.suspended.title=Felfüggesztve + +talk.parentlink=Párbeszéd eleje + +talk.readsimilar=Olvass hasonló neplóbejegyzéseket: + +talk.replytothis=Válasz erre + +talk.somebodywrote=[[realname]] ([[userlink]]) írta: + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) írta a [[commlink]] hozzászólásban: + +talk.spellcheck=(Amerikai angol) helyesírás ellenÅ‘rzése elÅ‘nézetkor + +talk.threadlink=Párbeszéd kibontása + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_magyar + +Username=Felhasználói név + +userpic.inactive=Használaton kívüli + +xcolibur.greeting.anon=Ãœdvözlünk a LiveJournalon! + +xcolibur.greeting.logged_in=Szia, [[name]]! [[logout]] + +xcolibur.login=Bejelentkezel? + +xcolibur.logout=Kilépsz? + +xcolibur.nav.about=A lapról + +xcolibur.nav.about.download=Letöltés + +xcolibur.nav.about.general=Információk + +xcolibur.nav.about.paidaccounts=FizetÅ‘s fiókok + +xcolibur.nav.about.press=Sajtó + +xcolibur.nav.about.sitenews=Újdonságok + +xcolibur.nav.about.stats=Felmérések + +xcolibur.nav.footer.sitemap=Honlaptérkép + +xcolibur.nav.help=Segítség + +xcolibur.nav.help.ask=Kérdésed van? + +xcolibur.nav.help.contact=Kapcsolatfelvétel + +xcolibur.nav.help.faq=GyIK + +xcolibur.nav.help.lostpassword=Elfelejtett jelszó + +xcolibur.nav.home=FÅ‘lap + +xcolibur.nav.journal=Napló + +xcolibur.nav.journal.archive=Archívum + +xcolibur.nav.journal.edit.entries=Szerkesztés + +xcolibur.nav.journal.friends=Barátok + +xcolibur.nav.journal.info=Adatok + +xcolibur.nav.journal.memories=Emlékek + +xcolibur.nav.journal.recent=Legfrissebb + +xcolibur.nav.journal.update=Új bejegyzés + +xcolibur.nav.manage=Változtatás + +xcolibur.nav.manage.community=Közösségek + +xcolibur.nav.manage.customize=Testreszabás + +xcolibur.nav.manage.entries=Bejegyzések + +xcolibur.nav.manage.friends=Barátok + +xcolibur.nav.manage.info=Adatok + +xcolibur.nav.manage.password=Jelszó + +xcolibur.nav.manage.pics=Felhasználói képek + +xcolibur.nav.manage.styles=Stílusok + +xcolibur.nav.search=Keresés + +xcolibur.nav.search.directory=Régió + +xcolibur.nav.search.directory.search=Speciális + +xcolibur.nav.search.interests=ÉrdeklÅ‘dés + +xcolibur.nav.search.random=Véletlen + +xcolibur.nav.siteopts=Böngészési beállítások + +xcolibur.nav.title=Vezérlés: + +xcolibur.nav.welcome=Ãœdvözlünk + +xcolibur.nav.welcome.create=Fiók létrehozása + +xcolibur.nav.welcome.login=Bejelentkezés + +xcolibur.nav.welcome.update=Új naplóbejegyzés + +xcolibur.search=Keresés: + +xcolibur.search.category=Kategória: + +xcolibur.search.icq=ICQ azonosító + +xcolibur.search.int=ÉrdeklÅ‘dés + +xcolibur.search.msn=MSN azonosító + +xcolibur.search.region=Régió + +xcolibur.upgrade=Fiók továbbfejlesztése + diff --git a/ljcom/bin/upgrading/is.dat b/ljcom/bin/upgrading/is.dat new file mode 100644 index 0000000..f93ea9e --- /dev/null +++ b/ljcom/bin/upgrading/is.dat @@ -0,0 +1,2382 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Hér eyðir þú eða afturkallar dagbókina þína - eftir að þú eyðir henni hefurðu 30 daga til að afturkalla hana, ef þú skiptir um skoðun. Eftir það er henni endanlega eytt og engin leið er þá að fá hana aftur. + +/accountstatus.bml.journalstatus.head=Virkni dagbókar + +/accountstatus.bml.journalstatus.select.activated=í notkun + +/accountstatus.bml.journalstatus.select.deleted=hefur verið eytt + +/accountstatus.bml.journalstatus.select.head=Staða: + +/accountstatus.bml.journalstatus.select.suspended=Tekin úr notkun + +/accountstatus.bml.title=Staða skriftu + +/allpics.bml.current=Myndir í notkun + +/allpics.bml.default=Grunnmynd + +/allpics.bml.edit2=Kannski viltu breyta kenniorðum myndanna þinna eða hlaða upp nýja. + +/allpics.bml.error.noparam=Þú þarft að skilgreina notanda. + +/allpics.bml.keywords=Flýtiorð: + +/allpics.bml.nopics.text.other=Þessi notandi hefur ekki sent neinar myndir hingað. + +/allpics.bml.nopics.text2=Þú hefur ekki hlaðið neinni mynd á netþjóninn enn. Farðu hingað til að gera það. + +/allpics.bml.nopics.title=Engar myndir! + +/allpics.bml.pics=Hér eru myndirnar sem [[user]] notar. + +/allpics.bml.title=Notendamyndir + +/approve.bml.comm.success=Meðbyr og brautargengi! + +/approve.bml.comm.text<< +Þú ert núna meðlimur [[comm]] samfélagsins. +Smelltu hér til að bæta því á vinalistann þinn. +. + +/approve.bml.error.actionperformed=Þessi aðgerð hefur þegar verið framkvæmd. + +/approve.bml.error.internerr.invalidaction=Innvortis blæðingar kerfis: óleyfileg aðgerð. + +/approve.bml.error.invalidargument=Óleyfileg tillaga. + +/approve.bml.error.unknownactiontype=Óþekkt tegund aðgerðar + +/approve.bml.shared.success=Meðbyr og brautargengi! + +/approve.bml.shared.text<< +Þú hefur nú færsluréttindi í [[shared]]. +Smelltu hér til að bæta þessari sameiginlegu dagbók á vinalistann þinn. +. + +/approve.bml.title=Samþykki aðgerðar + +/birthdays.bml.description=Hér að neðan eru afmælisdagar fólksins á vinalistanum þínum. + +/birthdays.bml.title=Afmælisdagar + +/changepassword.bml.btn.proceed=Halda áfram + +/changepassword.bml.changepassword.header=Breyta lykilorði + +/changepassword.bml.changepassword.instructions|staleness=1 +/changepassword.bml.changepassword.instructions=Fylltu út eyðublaðið að neðan til að breyta lykilorðinu þínu. + +/changepassword.bml.email.body<< +Lykilorðið þitt á [[sitename]] hefur verið breytt. + +Til að nálgast það í framtíðini, opnaðu síðuna: + + [[siteroot]]/lostinfo.bml + +Kveðja, +[[sitename]] gengið + +[[siteroot]] +. + +/changepassword.bml.email.subject=Breyting á lykilorði + +/changepassword.bml.error.badcheck=Nýja lykilorðið ónothæft: [[error]] + +/changepassword.bml.error.badnewpassword|staleness=1 +/changepassword.bml.error.badnewpassword=Nýja lykilorðið þitt var ekki eins í bæði skiptin sem þú ritaðir það - vinsamlegast sláðu það inn aftur. + +/changepassword.bml.error.badoldpassword=Gamla lykilorðið þitt var ekki rétt. + +/changepassword.bml.error.blankpassword=Nýja lykilorðið verður að vera eitthvað;) + +/changepassword.bml.error.changetestaccount=Það er ekki hægt að breyta lykilorði tilraunarskriftu. + +/changepassword.bml.error.characterlimit=Lykilorð mega ekki vera lengri en 30 stafir. + +/changepassword.bml.error.invaliduser=Því miður, notandinn [[user]] er ekki til. Stafsettirðu nafnið örugglega rétt? + +/changepassword.bml.error.mustenterusername=Þú verður að slá inn notandanafn. + +/changepassword.bml.error.nonascii=Lykilorð mega aðeins standa saman af ASCII stöfum, og engum öðrum. Öruggast er því að nota ekki séríslenska stafi í lykiloðinu. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Þú getur ekki skipt um lykilorð ef þú hefur ekki staðfest netfangið þitt - en það gerirðu með því að svara staðfestestingarbréfinu sem barst til þín þegar þú skráðir þig. + +/changepassword.bml.newpassword=Nýtt lykilorð: + +/changepassword.bml.newpasswordagain=Endurtaktu nýja lykilorðið + +/changepassword.bml.oldpassword=Gamla lykilorðið: + +/changepassword.bml.proceed.instructions=Smelltu á takkann að neðan til að lykilorðinu þínu verði breytt. Þá færðu um leið bréf sem tilkynnir breytinguna. + +/changepassword.bml.success.text=Lykilorðinu þínu hefur verið breytt og bréf sent til þín til áminningar. + +/changepassword.bml.title=Breyta lykilorði + +/community/index.bml.title=Miðstöð samfélags + +/community/join.bml.button.join=Ganga í samfélag + +/community/join.bml.label.addtofriends=Bæta "[[maintainer]]" á vinalistann.
        + +/community/join.bml.label.allowposting=Þetta samfélag leyfir öllum meðlimum að skrifa færslur, þannig að þú getur gert svo. Ef þú ert þegar með færsluvél í gangi í tölvunni þinni verður þú að skrá þig út og inn aftur til að þessi dagbók komi fram með þeim sem þú getur venjulega skrifað í. + +/community/join.bml.label.auth=Þó þú sért núna meðlimur í samfélaginu, þá geta aðeins þeir sem hafa fengið leyfi skrifað færslur. Hafðu samband við einn af stjórnendum ef þú vilt geta það - hér er listi yfir þá: [[admins]] + +/community/join.bml.label.banned=Stjórnandi þessa samfélags hefur bannað þér að skrá þig. + +/community/join.bml.label.closed=Þetta er einkasamfélag. Hafðu samband við einn af stjórnendunum ef þú hefur áhuga á að ganga í það. Þeir eru: [[admins]] + +/community/join.bml.label.commlogged=Þú ert skráður inn sem deili- eða skamfélagsskrifta, ekki sem persónuleg skrifta. + +/community/join.bml.label.membernow=Þú ert nú meðlimur í [[commname]] Samfélaginu + +/community/join.bml.label.sure=Ertu viss? + +/community/join.bml.success=Meðbyr og brautargengi! + +/community/join.bml.title=Ganga í samfélag + +/community/leave.bml.button.leave=Ganga úr samfélagi + +/community/leave.bml.label.buttontoleave=Smelltu á takkann hér að neðan til að yfirgefa "[[commname]]" samfélagið. + +/community/leave.bml.label.infoerror=Þessar tilteknu upplýsingar um samfélagið eru ekki leyfilegar. + +/community/leave.bml.label.logoutfirst=Til að yfirgefa samfélag þarftu fyrst að skrá þig inn. + +/community/leave.bml.label.removed=Þú hefur nú verið fjarlægður úr [[commname]] samfélaginu + +/community/leave.bml.label.removefromfriends=Fjarlæga líka "[[user]]" af vinalistanum. + +/community/leave.bml.success=Meðbyr og brautargengi! + +/community/leave.bml.sure=Ertu viss? + +/community/leave.bml.title=Yfirgefa samfélag + +/community/manage.bml.commlist.actinfo=Upplýsingar + +/community/manage.bml.commlist.actions=Aðgerðir + +/community/manage.bml.commlist.actmembers=[Meðlimir] + +/community/manage.bml.commlist.actmembers2=Meðlimir + +/community/manage.bml.commlist.actsettings=[Stillingar] + +/community/manage.bml.commlist.actsettings2=Stillingar + +/community/manage.bml.commlist.header=Samfélögin þín + +/community/manage.bml.commlist.none=Þú ert ekki að sjá um nein samfélög. + +/community/manage.bml.commlist.text=Hér eru samfélögin sem þú sérð um: + +/community/manage.bml.commlist.title=Titill + +/community/manage.bml.commlist.username=Notandanafn + +/community/manage.bml.create.header=Skapa samfélag + +/community/manage.bml.create.text=Þú getur líka skapað nýtt samfélag. + +/community/manage.bml.title=Sýslun samfélaga + +/community/members.bml.error.alreadyadded=[[user]] var nú þegar með aðgang að samfélaginu, og var því ekki bætt aftur við listann. + +/community/members.bml.error.nocomm=Samfélag fannst ekki + +/community/members.bml.error.nouser=Notandinn [[user]] er ekki til. + +/community/members.bml.success.header=Meðbyr og brautargengi! + +/community/members.bml.update=Uppfærslustillingar + +/community/search.bml.button.clear=Hreinsa eyðublað + +/community/search.bml.button.search=Hefja leit! + +/community/search.bml.checkbox.onlywithpics=Aðeins samfélög með myndum + +/community/search.bml.label.byinterest=Eftir áhugamáli + +/community/search.bml.label.city=Borg: + +/community/search.bml.label.country=Land: + +/community/search.bml.label.displayoptions=Skjásýn + +/community/search.bml.label.hasmember=Hefur meðlim + +/community/search.bml.label.othercriteria=Önnur málefni + +/community/search.bml.label.sortmethod=Röðunaraðferð: + +/community/search.bml.label.updated=Uppfært síðastliðinn + +/community/search.bml.sel.updatetime=Tími uppfærslu + +/community/settings.bml.label.changeheader=Breyta sérstillingingum samfélags + +/community/settings.bml.label.commheader=Samfélagsskrifta + +/community/settings.bml.label.nmtext=Geta notendur skrifað færslur í samfélagið án þess að vera meðlimir? + +/community/settings.bml.label.openmemb=Frjáls skráning
        Hver sem er getur skráð sig án þess að þurfi að samþykkja skráninguna sérstaklega. + +/community/settings.bml.label.password=Lykilorð: + +/community/settings.bml.label.postaccess=Færsluaðgangur + +/community/settings.bml.label.rellinks=Tenglar að viðeigandi efni: + +/community/settings.bml.label.selcan=Valdir meðlimir
        Aðeins þeir meðlimir sem stjórnandinn hefur gefið leyfi til geta skrifað færslur. + +/community/settings.bml.label.username=Notendanafn: + +/community/settings.bml.label.whocanjoin=Hverjir geta gengið í samfélagið? + +/community/settings.bml.label.whocanpost=Hverjir geta skrifað færslur í samfélagið? + +/community/settings.bml.name=Titill samfélags: [[name]] + +/community/settings.bml.success=Meðbyr og brautargengi! + +/community/settings.bml.title.create=Skapa samfélag + +/community/settings.bml.title.modify=Samfélagsstillingar + +/create.bml.age.check.question=Ertu yngri en 13? + +/create.bml.age.check.yes=Já, ég er yngri en 13. + +/create.bml.age.check2.question=Ertu eldri en 13? + +/create.bml.age.check2.yes=Já, ég er eldri en 13 - alveg satt. + +/create.bml.age.head=Aldur + +/create.bml.create.head=Að gera nýja dagbók + +/create.bml.create.text=Það er auðvelt að gera nýja dagbók, fylgdu bara leiðbeiningunum! + +/create.bml.email.head=Netfang þitt + +/create.bml.email.input.head=Netfang: + +/create.bml.error.coppa.under13=Vegna COPPA reglna geturðu því miður ekki notað LiveJournal fyrr en þú verður 13 ára. Komdu aftur þá. + +/create.bml.error.email.nospaces=Engin bil eru leyfð í netfangi. Ef þú ert í AOL mundu þá að netfangið þitt er skjánafnið þitt með öllum bilum fjarlægðum og klesst framan við @aol.com. + +/create.bml.error.password.asciionly=Þú mátt bara nota ASCII stafi í lykilorði þínu. Einfalt að halda sig bara við enska stafi. + +/create.bml.error.password.blank=Þú verður að slá inn lykilorð. + +/create.bml.error.password.nomatch=Lykilorðin eru ekki eins. + +/create.bml.error.username.blank=Vinsamlegast gefðu upp (gælu)nafn eða dulnefni. + +/create.bml.error.username.inuse=Þetta notandanafn er nú þegar í notkun - vinsamlegast veldu annað. + +/create.bml.error.username.iscode=Notandanafnið sem þú gafs upp virðist vera boðskóði en ekki notandanafn. + +/create.bml.error.username.mustenter=Þú verður að stimpla inn notandanafn. + +/create.bml.error.username.reserved=Því miður, þetta notandanafn er frátekið. + +/create.bml.name.head=Nafn þitt + +/create.bml.name.input.head=Nafn: + +/create.bml.name.text=Hvað heitirðu eða kallar þig? Þetta er nafnið sem mun birtast efst í dagbókinni þinni og í notendaskránn (ef þú kýst að vera skráður í hana) Þú þarft ekki að nota fullt nafn eða einu sinni þitt rétta nafn. + +/create.bml.password.head=Lykilorð + +/create.bml.password.input.head1=Lykilorð: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Sláðu lykilorð inn aftur: + +/create.bml.password.text=Veldu lykilorð. + +/create.bml.proceed.btn.proceed=Halda áfram... + +/create.bml.proceed.warning=Smelltu bara einu sinni á Halda áfram!! + +/create.bml.success.btn.enterinfo=Breyta persónuupplýsingum + +/create.bml.success.head=Meðbyr og brautargengi! + +/create.bml.success.text1|staleness=1 +/create.bml.success.text1=Dagbókin þín er tilbúin. Mikilvæg staðfestingargögn hafa verið sent á [[email]] þar sem þú finnur frekari leiðbeiningar. ATH: Þú hefur nákvæmlega viku til þess að staðfesta dagbókina þína. Ef þú hefur ekki gert það innan viku mun notandanafnið [[username]] sjálfkrafa eyðast svo einhver annar geti notað það. + +/create.bml.success.text2=Dagbókin þín mun vera á slóðinni: + +/create.bml.success.text3=Vinsamlegast gefðu þér tíma til að skrifa eitthvað um sjálfan þig hér. Það er frjálst hvort þú skrifar nokkuð, en það gefur okkur hugmynd um það hverjir eru að nota LiveJournal. + +/create.bml.title=Skapa nýja dagbók + +/create.bml.tos.error=Þú verður að samþykkja notkunarskilmálana áður en þú getur skapað skriftu. + +/create.bml.tos.haveread=Ég hef lesið yfir og geng að notkunarskilmálum. + +/create.bml.tos.heading=Notkunarskilmálar + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Settu skrifturununa hér til að skapa nýja skriftu: + +/create.bml.useacctcodes.welcome=Velkomin/n + +/create.bml.username.box.head=Notandanafn: + +/create.bml.username.forpaidaccts=Eða fyrir þá með áskrift: + +/create.bml.username.head=Notandanafn + +/create.bml.username.ljaddress=Dagbókin þín verður á þessu veffangi: + +/create.bml.username.text=Hver [[sitename]] notandi verður að hafa hans eigin einstaka notandanafn. Notandanafnið þitt er það sem birtist í slóðinni að dagbókinni þinni og það sem þú notar til að tengjast [[sitname]] netþjónunum. Það birtist einnig þegar þú skrifar eitthvað í annarra dagbækur. + +/create.bml.username.username=Notandanafn + +/customize/index.bml.change=Breyta + +/customize/index.bml.choose=Hvort viltu nota nýja útlitskerfið eða það gamla? + +/customize/index.bml.choose.header=Veldu útlitskerfi + +/customize/index.bml.choose.s1=Gamla kerfið (S1) + +/customize/index.bml.choose.s2=Nýja kerfið (S2) + +/customize/index.bml.error.cant_generate_user_layer=Gat ekki smíðað notandalag + +/customize/index.bml.error.fail_create_style=Náði ekki að skapa nýjan stíl. + +/customize/index.bml.error.not_your_layout=Ekki þín sviðsetning. + +/customize/index.bml.error.not_your_theme=Ekki þitt þema + +/customize/index.bml.previews=(Skoðun) + +/customize/index.bml.s1.header=S1 nú í notkun + +/customize/index.bml.s2.advanced.header=Þróaðar sérstillingar + +/customize/index.bml.s2.customize.language.header=Tungumál + +/customize/index.bml.title=Sérsníða dagbók + +/directory.bml.open=Opna + +/directory.bml.post=Senda inn + +/directory.bml.search.monkey=Þrjátíu milljónir vel þjálfaðra gaupa eru nú að nota persónutöfra sína til að finna niðurstöður við leitinni þinni - bíddu bara róleg/ur, hallaðu þér upp að vegg og raulaðu lag úr uppáhaldsdraumnum þínum. + +/directory.bml.search.new=Ný fyrirspurn + +/directory.bml.search.title=Er að leita... + +/directory.bml.update=Uppfæra: + +/directory.bml.user=Notandi + +/doc/tour/index.bml.clients.caption<< +LiveJournal færsluvélarnar eru lítil forrit sem þú keyrir á tölvunni þinni sem leyfa þér að uppfæra dagbókina þína þegar þú ert nettengdur án þess að þurfa að opna glugga í vafra. +Þeir eru til fyrir flest stýrikerfi og er auðvelt að sníða eftir þörfum. +. + +/doc/tour/index.bml.clients.title=Færsluvélar + +/doc/tour/index.bml.comms.title=Samfélög + +/doc/tour/index.bml.create.title=Að skapa skriftu + +/doc/tour/index.bml.title=Kynning - [[title]] + +/doc/tour/index.bml.update.caption<< +Mjög einfalt er að halda utan um og uppfæra LiveJournal dagbók. Færslan er einfaldlega skrifuð í þar til gerðan ramma, og svo smellt á hnapp merktan „Uppfæra dagbók“. +Að auki erum við með sérstaka reiti sem hannaðir hafa verið til að geyma upplýsingar um hvaða tónlist var hlustað á meðan færslan var gerð sem og lýsingu á skapi höfundar - og ef þú skrifar á ensku, þá erum við með ágætan stafsetningarprófun sem bendir þér á villur sem þú kannt að hafa gert (miðast við bandaríska ensku). +. + +/doc/tour/index.bml.update.title=Að uppfæra + +/editinfo.bml.allowshowcontact.about=Þú ættir að hafa þennan valkost á þar sem hann gerir öðru fólki kleyft að hafa samband við þig með því að sýna netfangið þitt, ICQ númer og AOL instant messenger skjánafn allt í dagbókinni þinni. + +/editinfo.bml.allowshowcontact.email=Ef þú kýst að birta netfang þitt verður það þetta: + +/editinfo.bml.allowshowcontact.email.actual_only=Aðeins heimilisfang + +/editinfo.bml.allowshowcontact.email.both=Bæði (Heimilisfang + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Aðeins fyrir LiveJournal netfang + +/editinfo.bml.allowshowcontact.email.neither=Hvorugt. Sýnið ekkert netfang. + +/editinfo.bml.allowshowcontact.email.no_show=Sýna ekki netfang + +/editinfo.bml.allowshowcontact.email.show=Sýna netfang + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Með takkanum að ofan geturðu valið að fela netfangið þitt (en þó birta ennþá aðrar upplýsingar), aðeins sýnt LiveJournal netfangið þitt (aðeins þeir í Ã-skrift), aðeins sýnt venjulega netfangið eða sýna bæði. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Með takkanum að ofan geturðu falið netfangið þitt (án þess að fela allar upplýsingar) + +/editinfo.bml.allowshowcontact.title=Sýna tengi-upplýsingar á LiveJournal? + +/editinfo.bml.allowshowinfo.about=Kveiktu hér ef þú vilt að aðrir sjái hvaða borg, fylki og ríki þú býrð í eða til að sýna afmælisdaginn. + +/editinfo.bml.allowshowinfo.title=Sýna staðsetningu & afmælisdag? + +/editinfo.bml.autotranslate.about=Notaðu þetta til að segja LiveJournal hvaða kóðun á að nota á færslurnar þínar og athugasemdir áður en því er breytt í Unicode. Ef þú skrifar á ensku, veldu þá „Western European“. + +/editinfo.bml.autotranslate.header|staleness=1 +/editinfo.bml.autotranslate.header=Kóða sjálfkrafa gamlar færlsur frá: + +/editinfo.bml.bday.title=Afmælisdagur + +/editinfo.bml.bday.year.opt=Óþarft en gagnlegt + +/editinfo.bml.bdayreminders.about=Ef þú vilt að LiveJournal minni þig á afmæli vina þinna í pósti, merktu þá þennan kassa. + +/editinfo.bml.bdayreminders.header|staleness=1 +/editinfo.bml.bdayreminders.header=Minna mig á afmæli með pósti. + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=Hér skrifarðu stutt æviágrip til að sýna á notendaupplýsingasíðunni. + +/editinfo.bml.bio.header=Um þig + +/editinfo.bml.blockrobots.about|staleness=1 +/editinfo.bml.blockrobots.about=Ef þú merkir hér munu allar leitarvélar þræða annað. Þær hlýða þessu ekki allar, en flestar vinsælustu gera það. + +/editinfo.bml.blockrobots.header=Stöðva leitarvélar í að skrá vefdagbókina þína. + +/editinfo.bml.chat.aolim.title=Aim kenninafn + +/editinfo.bml.chat.icquin.title=ICQ númer + +/editinfo.bml.chat.msnusername.title=MSN netfang + +/editinfo.bml.chat.yahooid.title=Yahoo! kenninafn + +/editinfo.bml.city.title=Borg + +/editinfo.bml.country.choose=Veldu land. + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Nei + +/editinfo.bml.email.title=Netfang + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=Merktu hér ef þú vilt að fólk geti svarað eða gert athugasemdir við færslur þínar (stíll sagbókarinnar verður líka að styðja þetta). + +/editinfo.bml.enableboards.header=Leyfa spjallþræði + +/editinfo.bml.encoding.about=Hér er hægt að velja „Western European (ISO)“ í báðum reitunum til að fá alla íslenska stafi til að virka. + +/editinfo.bml.encoding.header=Kóðunarmöguleikar + +/editinfo.bml.error.day.notinmonth=Þessi dagur er ekki til staðar í þessum tiltekna mánuði. + +/editinfo.bml.error.day.outofrange=Afmælisdagur ógildur - vinsamlegast settu dag frá 1-31. + +/editinfo.bml.error.email.lj_domain<< +Þú átt ekki að setja netfang hér, bara þitt raunverulega heimilisfang. +Ef þú ert með ákrift verða bréfin sem berast [[user]]@[[domain]] sent áfram heim til þín. +Til að velja hvort netfangið þitt (eða bæði) verða birt opinberlega skoðaðu þá „Sýna tengi-upplýsinga“-valið hér að neðan. +. + +/editinfo.bml.error.email.none=Þú verður að gefa upp netfangið þitt + +/editinfo.bml.error.email.no_space<< +Engin bil leyfð í netfangi. +Mundu að ef þú ert í AOL, þá er netfangið þitt skjánafnið með öllum bilum fjarlægðum og skeytt framan við @aol.com. +. + +/editinfo.bml.error.excessive_int<< +Því miður lítur út fyrir að þú hafir skilgreint allt of mörg áhugamál. Hámarkið er 150, en þú skráðir [[intcount]]. +Þær breytingar sem þú gerðir á áhugamálalistanum voru ekki vistaðar. Farðu til baka og styttu listann og vistaðu svo aftur. +. + +/editinfo.bml.error.invalidbio=Æviágripið þitt inniheldur óleyfilega stafi - faðru á umbreytisíðuna til að breyta yfir í Unicode. + +/editinfo.bml.error.invalidints=Ãhugamálalistinn þinn inniheldur óleyfilega stafi - faðru á umbreytisíðuna til að breyta yfir í Unicode. + +/editinfo.bml.error.invalidname=Óleyfilegir stafir eru í nafninu þínu. Þú verður að fara á umbreytisíðuna til að breyta því sem þú skrifaðir í leyfilega stafi. + +/editinfo.bml.error.locale.country_ne_state=Þú stilltir Bandaríkin sem landið þitt en skráðir fylki sem er ekki þar í „annað fylki“ liðinn. + +/editinfo.bml.error.locale.invalid_country=Einhvernvegin valdirðu vitlaust land. + +/editinfo.bml.error.locale.state_ne_country=Þú valdir ekki Bandaríkin sem land þitt en valdir þó ríki sem er í BNA. + +/editinfo.bml.error.locale.zip_ne_state=Póstnúmerið passar ekki við fylkið sem þú valdir. Leiðréttu annaðhvort upplýsingarnar eða eyddu öðrum eða báðum liðum. + +/editinfo.bml.error.locale.zip_requires_us=Þú hefur sláð inn póstnúmer en ekki valið Bandaríkin sem föðurland. Við söfnum bara póstnúmerum innan Bandaríkjanna, þannig að vinsamlegast fjarlægðu póstnúmerið eða veldu Bandaríkin sem ríki. + +/editinfo.bml.error.month.outofrange=Afmælismánuður ógildur - veldu mánuð frá 1 uppí 12 (jan-des) + +/editinfo.bml.error.noname=Til að halda áfram verður þú að gefa upp nafn - í það minnsta fornafn, gælunafn eða annað. + +/editinfo.bml.error.tm.require.number=Ef þú ætlar að nota sms-þjóðnustuna verðurðu að skrá símanúmer. + +/editinfo.bml.error.tm.require_provider<< +Ef þú ætlar að nota sms-þjónustuna verðurðu að stilla hvað símafyrirtækið þitt er. + +Ef það er ekki á listanum, sentu okkur þá upplýsingar um símafyrirtækið þitt og hvernig sms-þjónustan þeirra virkar svo við getum bætt því á listann. +. + +/editinfo.bml.error.year.notenoughdigits=Óleyfilegt fæðingarár, skrifaðu árið í fjórum tölustöfum. + +/editinfo.bml.error.year.outofrange=Óleyfilegt fæðingarár. + +/editinfo.bml.finished.about=Smelltu á „Vista breytingar“ takkann þegar þú ert búinn. + +/editinfo.bml.finished.header=Ertu búinn? + +/editinfo.bml.finished.save_button=Vista breytingar + +/editinfo.bml.gender.title=Kyn + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Merktu hér er þú vilt fá vitkun í pósti þegar fólk svarar færlsum þínum. + +/editinfo.bml.getreplies.header=Fá svör frá spjallborði. + +/editinfo.bml.hidefriendof.about=Ef þú merkir hér mun listinn yfir fólkið sem hefur þig á vinalistanum sínum vera falinn í mannlýsingunni þinni. + +/editinfo.bml.hidefriendof.header=Fela listann sem sýnir hver á þig sem vin. + +/editinfo.bml.howhear.about|staleness=1 +/editinfo.bml.howhear.about<< +Ég spyr nú bara í einskærri forvitni, en hvar heyrðirðu um [[sitename]]? +Ef það var ákveðin manneskja settu þá notendanafn hennar hér, og ef það var annarstaðar frá, grein, tengli eða netsíðu skrifaðu það þá hér. +. + +/editinfo.bml.howhear.header=Forvitni + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about=Merktu hér ef póstforritið þitt styður HTML fullkomlega. Mörg slík forrit reyna en mistekst herfilega. Ef þú strokar úr því sendir LiveJournal aðeins bréf sem eru bara texti. + +/editinfo.bml.htmlemail.header=Senda HTML bréf + +/editinfo.bml.int.about<< +Ef þú vilt leyfa öðrum að finna þig í skránni eftir áhugamálum, skrifaðu þá hér fyrir neðan allt sem þú hefur áhuga á og aðskildu með kommum. +Stutt hnit-miðuð orðasambönd henta best.
        Þumalputtaregla Þú ættir að geta sett áhugamál í fram sem svo: "Ég fíla ______". Notaðu rétta málbeitingu, eins og með fleirtölu; "I like DVDs" í staðinn fyrir "I like DVD". + +Athugið Ãslendingar: Þetta kerfi er hannað með ensku í huga, þannig að það gegnur eflaust betur ef þið notið ensku útgáfurnar af orðum og hugtökum;) +. + +/editinfo.bml.int.ex.bad=RANGT Dæmi: Ég fíla margar hljómsveitir og að horfa á vídjó og spjalla við vini og fara á klúbbarölt. Svona fer í æviágripið þitt að ofan. + +/editinfo.bml.int.ex.good=RÉTT Dæmi:biking, snow skiing, computers, dvds, mp3s, cheese, women Ef þið hafið áhugamálin á íslensku fara þau ekki í skrána hjá LiveJournal og koma því ekki að jafn miklu gagni og gætu. + +/editinfo.bml.int.header=Ãhugamál + +/editinfo.bml.login.enterinfo=Sláðu inn notandanafn og lykilorð til að stilla persónuupplýsingarnar þínar. + +/editinfo.bml.login.forgot.header=Gleymdist eitthvað? + +/editinfo.bml.login.forgot.recover=Ef þú ert búinn að gleyma notandanafni eða lykilorði geturðu fengið það hérna!. + +/editinfo.bml.logip.always=Alltaf + +/editinfo.bml.logip.anon_only=Aðeins ókráða notendur + +/editinfo.bml.logip.header=Skrá IP tölu þeirra sem svara skeytum? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Ef þú er heldur að ruslpóstsvélar finni netfangið þitt á LiveJournal merktu þá við hér og því verður breytt þannig að vélarnar finna það ekki. + +/editinfo.bml.mangleaddress.header=Rugla birta netfangið þitt + +/editinfo.bml.name.title=Nafn + +/editinfo.bml.newemail.subject=Netfangi hefur verið breytt + +/editinfo.bml.numcomments.about=Merktu hér ef þú vilt að vafrinn þinn geti sýnt "fjölda svara" tengilinn í mismunandi litum. + +/editinfo.bml.numcomments.header=Bæta &nc=xx í slóðir svara + +/editinfo.bml.optional=Valfrjálst + +/editinfo.bml.opt_in.about<< +Hakaðu hér ef þú vilt fá að vita þegar nýjungar eru kynntar í LiveJournal kerfinu. +Þessi þjónusta er ekki fullkomlega komin í gang, en verður líklega notuð í náinni framtíð. +Netfangið þitt verður ekki aðgengilegt almenningi, og þú getur sagt upp þessari þjónustu hvenær sem er. +. + +/editinfo.bml.opt_in.header=Senda mér LiveJournal fréttir. + +/editinfo.bml.persinfo.disclaimer=Settu örlitlitlar upplýsingar um þig, bara vegna okkar forvitni og tölfræðirannsókna. Við ætlum okkur ekkert illt með þessa vitneskju - við viljum bara sjá hverjir og hvar þeir eru sem nota kerfin okkar. Vinsamlegast settu rétt inn. Lestu persónuverndarreglur okkar ef þú er eitthvað efins. + +/editinfo.bml.persinfo.header=Persónuupplýsingar + +/editinfo.bml.screen.all=Allt + +/editinfo.bml.screen.anon=Ónafngreindur + +/editinfo.bml.screen.header=Hvers konar svör viltu að verði stöðvuð sjálfkrafa? + +/editinfo.bml.screen.none=Engin + +/editinfo.bml.screen.nonfriends=Öll sem ekki eru frá fókli á vinalista + +/editinfo.bml.screen.nonmembers=Öll sem eru frá notendum sem ekki eru á LiveJournal + +/editinfo.bml.security.header=Hver getur skoðað tengiupplýsingar þínar? + +/editinfo.bml.security.visibility.anybody=Opið hverjum sem er + +/editinfo.bml.security.visibility.everybody=Opið öllum + +/editinfo.bml.security.visibility.friends=Aðeins fyrir vini + +/editinfo.bml.security.visibility.regusers=Aðeins fyrir skráða notendur + +/editinfo.bml.settings.friendspage.title=Titill vinasíðu: + +/editinfo.bml.settings.friendspage.title.optional=Ef þú vilt geturðu sett titil á vinasíðuna þína. (HTML virkar ekki) + +/editinfo.bml.settings.header=LiveJournal Val + +/editinfo.bml.settings.journal.subtitle=Undirtitill dagbókar: + +/editinfo.bml.settings.journal.subtitle.optional=Einnig geturðu gefið dagbókinni þinni undirtitil (án HTML þó). + +/editinfo.bml.settings.journal.title=Dagbókartitill: + +/editinfo.bml.settings.privacy.about=Að neðan eru stillingar sem varða almenningsaðgang og almennt val. + +/editinfo.bml.settings.privacy.header=Almenningsaðgangur + +/editinfo.bml.state.other=Eða sláðu inn annað fylki/hérað/sýslu + +/editinfo.bml.state.title=Fylki + +/editinfo.bml.state.us=Bandaríkin + +/editinfo.bml.stylemine.about=Merktu hér við ef þú vilt hafa athugasemdasíður í sama stíl og aðalsíða dagbókarinnar þinnar. + +/editinfo.bml.stylemine.header=Viltu sjá athugasemdasíður í sama stíl og aðalsíða dagbókarinnar þinnar? + +/editinfo.bml.success.header=Meðbyr og brautargengi! + +/editinfo.bml.success.message=Upplýsingarnar þínar og vefdagbókar stillingar og mannlýsing hafa verið uppfærð. + +/editinfo.bml.switch.button=Skipta + +/editinfo.bml.switch.header=Skipta um dagbók + +/editinfo.bml.switch.workwith=Vinna í dagbók + +/editinfo.bml.title=Breyta persónulegum upplýsingum + +/editinfo.bml.tm.details=smáatriði + +/editinfo.bml.tm.phonenum=Fullt símanúmer + +/editinfo.bml.tm.sec.about=Leyfa textaskilaboð frá öðrum notendum. + +/editinfo.bml.tm.sec.title=Öryggisstig: + +/editinfo.bml.tm.servprov=þjónustuveita: + +/editinfo.bml.tm.title=Textaskilaboð + +/editinfo.bml.translatemailto.about=Ef þú hefur valið að fá að vita af svörum við einhverju frá þér og póstþjónninn þinn styður ekki Unicode (UTF-8) skilaboð mjög vel - veldu þá þetta til að stilla á annað kóðunarkerfi svo LiveJournal geti breytt textanum í það áður enn hann fer í póstkassann þinn. + +/editinfo.bml.translatemailto.header=Þýða póstvitkanir í: + +/editinfo.bml.unbanusers.about=Eftirfarandi notendum er bannað að setja skilaboð í dagbókina þína. Merktu kassan við notendanafn þeirra til að fjarlæga bannið á þeim. + +/editinfo.bml.unbanusers.header=Leyfa notendur + +/editinfo.bml.userpic.about=Hér fyrir neðan er myndin sem þú hefur valið til þess að standa fyrir þig á öllu LiveJournal vefsvæðinu, þ.á.m. vefbókinni þinni og vina þinna: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Smelltu hér til að eyða þessari mynd eða hlaða nýja inn. + +/editinfo.bml.userpic.header=Myndin þín + +/editinfo.bml.userpic.none=engar myndir í notkun + +/editinfo.bml.weblogscom.about=Merktu hér ef þú vilt að Weblogs.com hafi dagbókina þína á lista sem sýnir nýjustu opinberu færslurnar þínar. + +/editinfo.bml.weblogscom.header=Láta Weblogs.com vita þegar þú uppfærir. + +/editinfo.bml.webpagename.title=Nafn vefsíðu + +/editinfo.bml.webpageurl.title=Slóð verfsíðu + +/editinfo.bml.whoreply.header=Hver á að geta svarað þínum færslum? + +/editinfo.bml.zip.title=Póstnúmer + +/editinfo.bml.zip.usonly=5 stafa póstnúmer - á aðeins við Kana;) + +/editjournal.bml.btn.proceed=Halda áfram... + +/editjournal.bml.certainday=Ãkveðinn dagur: + +/editjournal.bml.desc=Notaðu kerfið að neðan til að finna færsluna sem þú vilt breyta. + +/editjournal.bml.in=à samfélagi: + +/editjournal.bml.recententries=síðustu færslur + +/editjournal.bml.recententry=Allra nýjustu færsluna + +/editjournal.bml.title=Laga dagbókarfærslur + +/editjournal.bml.viewwhat=Skoða hvaða færslur: + +/editjournal_do.bml.body=Til að vista breytingarnar smellirðu einfaldlega á vistunartakkann að neðan. Þú getur líka eytt færslunni með eyðslutakkanum neðst. + +/editjournal_do.bml.btn.delete=Eyða færslu + +/editjournal_do.bml.btn.edit=Laga valda færslu + +/editjournal_do.bml.btn.save=Vista færslu + +/editjournal_do.bml.continue.head=Smelltu til að halda áfram... + +/editjournal_do.bml.continue.text=Ãttu á Edit-takkann hér fyrir neðan þegar þú hefur valið hlut til að laga eða eyða. + +/editjournal_do.bml.currmood|staleness=1 +/editjournal_do.bml.currmood=Skap. + +/editjournal_do.bml.currmusic=Ég er að hlusta á: + +/editjournal_do.bml.date=Dagsetning: + +/editjournal_do.bml.default=grunnstilling + +/editjournal_do.bml.delete.confirm=Ertu viss um að þú viljir eyða þessari færslu? + +/editjournal_do.bml.edit.text|staleness=2 +/editjournal_do.bml.edit.text=Breyttu því sem þú vilt í færslunni og smelltu á vistunartakkann neðst á síðunni. Til að eyða færslunni þarftu bara að stroka allan textann út og vista - og þá kemur ekkert. + +/editjournal_do.bml.error.getting=Það kom upp villa við að ná í færslur til að laga: + +/editjournal_do.bml.error.modify=Villumelding átti sér stað er reynt var að breyta dagbókinni þinni. + +/editjournal_do.bml.error.nofind=Fann ekki valda dagbókarfærslu. + +/editjournal_do.bml.event=Atburður: + +/editjournal_do.bml.localtime=Staðartími: + +/editjournal_do.bml.noneother=Engin, eða eitthvað aaaaaallt annað: + +/editjournal_do.bml.opt.backdate=Gömul færsla + +/editjournal_do.bml.opt.backdate.about=kemur ekki fram á vinasíðu + +/editjournal_do.bml.opt.nocomments=Banna athugasemdir: + +/editjournal_do.bml.opt.noemail=Senda ekki tilkynningu um athugasemd: + +/editjournal_do.bml.opt.noformat=Ekki sníða sjálfkrafa: + +/editjournal_do.bml.other=Aðra + +/editjournal_do.bml.pickentry.head=Veldu færslu til að laga + +/editjournal_do.bml.pickentry.text=Veldu það sem þú vilt laga og smelltu svo á „Laga“ takkann neðst á síðunni. + +/editjournal_do.bml.picture=Mynd til að nota: + +/editjournal_do.bml.save.head=Smelltu til að vista... + +/editjournal_do.bml.save.text=Ãttu á „Vista“ þegar þú ert búinn að laga færsluna. + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=Titill: (Óþarft, en nothæft við langar færslur) + +/editjournal_do.bml.success.delete=Færlsu hefur verið eytt. + +/editjournal_do.bml.success.edit|staleness=1 +/editjournal_do.bml.success.edit=Færslu hefur verið breytt. Þú getur séð hvernig hún er núna hér. + +/editjournal_do.bml.success.head=Meðbyr og brautargengi! + +/editjournal_do.bml.timeformat=24 stunda sólarhringur + +/editjournal_do.bml.title=Laga færslur + +/editpics.bml.btn.proceed=Halda áfram + +/editpics.bml.btn.save=Vista stillingar + +/editpics.bml.curpics=Myndir í notkun + +/editpics.bml.curpics.desc=Hér eru myndirnar sem þú hefur vistað á LJ-netþjóninn. Þú getur gefið þeim heiti til að nota þau án þess að þurfa að sjá myndina í hvert skipti sem þú velur hverja þú vilt nota, valið hverja þú vilt hafa sem grunnmynd og eytt myndum. Notaðu takkann neðst til að uppfæra nýja mynd. + +/editpics.bml.error.badurl=Vefslóð myndarinnar sem á að hala á netþjóninn virðist ekki vera rétt - hún ætti að hefjast á http:// + +/editpics.bml.error.filetoolarge=Myndin var of stór - stærð skjalsins má ekki vera meiri en [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Víddir myndarinnar þinnar ([[imagesize]]) eru of stórar - hún má ekki vera meiri en 100x100 dílar. Notaðu myndvinnsluforrit til að minnka stærðina í þumalputtamyndarstærð. + +/editpics.bml.error.invalidimage=Óvirkt myndarskjal + +/editpics.bml.error.keywords=Þú nefndir tvær myndir „[[ekw]]“ - önnur þeirra fékk nýtt slembivalið nafn, en líklega ekki eitt að þínu skapi. Farðu aftur á myndasíðuna til að breyta því. + +/editpics.bml.error.toomanypics2=Þú ert nú þegar með eins margar myndir og þú getur haft - [[maxpics]]. Þú getur ekki halað þessari mynd upp fyrr en þú eyðir einni af þínum gömlu. + +/editpics.bml.error.unsupportedtype=Því miður styðjum við ekki myndir á [[filetype]]-sniði. Þú verður að nota mynd á GIF, PNG eða JPG-sniði. Næstum öll myndvinnsluforrit geta breytt myndum á eitthvert þessara sniða fyrir þig. + +/editpics.bml.error.urlerror=Smá vesen olli því að ekki tókst að hala inn myndinni þinni. + +/editpics.bml.fromfile=Frá skjali: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=s + +/editpics.bml.fromurl=Af slóð: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=l + +/editpics.bml.label.default=Grunnmynd: + +/editpics.bml.label.delete=Eyða: + +/editpics.bml.label.keywords=Heiti: + +/editpics.bml.makedefault=Gera þessa mynd að grunnmynd + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=g + +/editpics.bml.restriction.imagesize=Vídd myndar má ekki vera meiri en 100x100 dílar + +/editpics.bml.title=Breyta notandamyndum + +/editpics.bml.uploaddesc=Notaðu kerfið að neðan til að senda inn nýja mynd + +/editpics.bml.uploadheader=Hlaða inn nýrri mynd + +/export.bml.btn.proceed=Halda áfram... + +/export.bml.label.field.currents=Skap og tónlist + +/export.bml.label.field.event=Atburður + +/export.bml.label.field.eventtime=Tími atburðar, miðað við klukku notanda + +/export.bml.label.field.itemid=Kenninúmer + +/export.bml.label.field.logtime=Skráartími, miðað við klukku kerfis + +/export.bml.label.field.security=Öryggisstig + +/export.bml.label.field.subject=Viðfangsefni + +/export.bml.label.format=Snið: + +/export.bml.label.header=Haus + +/export.bml.label.month=Veldu mánuð: + +/export.bml.label.month.year=áááá: + +/export.bml.label.notranslation=Til að þýða ekki milli umkóðana + +/export.bml.label.what=Hvad skal millifæra: + +/export.bml.title=Millifæra dagbók + +/export.bml.what.entries=Dagbókarfærslur + +/friends/add.bml.add.header=Meðbyr og brautargengi! + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text= hefur verið bætt á vinalistann. Þú getur skoðað vinasíðuna hér. + +/friends/add.bml.add.title=Nýr vinur! + +/friends/add.bml.btn.add=Bæta [[user]] + +/friends/add.bml.btn.modify=Breyta + +/friends/add.bml.btn.remove=Fjarlæga + +/friends/add.bml.colors.bg=Bakgrunnur + +/friends/add.bml.colors.fg=Forgrunnur + +/friends/add.bml.colors.header=Litir + +/friends/add.bml.colors.hover=(Færðu músina yfir einhvern tiltekinn lit til að sjá nafn hans) + +/friends/add.bml.colors.text=Þú getur líka valið liti til að einkenna frekar [[user]] á vinalistanum þínum. + +/friends/add.bml.confirm.header=Setja [[user]] á vinalistann? + +/friends/add.bml.confirm.text=Smelltu á takkann að neðan til að setja [[user]] á vinalistann þinn. + +/friends/add.bml.confirm.title=Vingast við + +/friends/add.bml.error1.header|staleness=1 +/friends/add.bml.error1.header=Innskrá fyrst + +/friends/add.bml.error1.text=Til að setja einhvern á vinalistann þinn þarftu fyrst að skrá þig inn. Ef þú ert ekki nú þegar með skriftu getur þú skapað eina til að fylgjast með dagbókum vina þinna. + +/friends/add.bml.error1.title=Vingast við + +/friends/add.bml.error2.text|staleness=1 +/friends/add.bml.error2.text=Annaðhvort vantar notandanafnið eða það er ekki til. Til að bæta við vin farðu á stilla vini síðuna. + +/friends/add.bml.error3.text=[[user]] er nú þegar á vinalistanum þínum - þú gætir þó viljað breyta litunum sem þú valdir fyrir hana á vinasíðunni þinni. + +/friends/add.bml.error3.title=Breyta stillingum vinar + +/friends/add.bml.groups.header=Vinahópar + +/friends/add.bml.groups.nogroup=Engir vinahópar settir upp enn + +/friends/add.bml.groups.text=à hvaða vinahóp viltu setja þennan notanda? Vinahópar eru oft notaðir til að flokka niður vinalistann og til að leyfa aðeins ákveðnum aðilum að skoða sumar færslur. + +/friends/add.bml.remove.header=Meðbyr og brautargengi! + +/friends/editgroups.bml.done.header=Allt tilbúið? + +/friends/editgroups.bml.saved.header=Vistað + +/friends/edit_do.bml.addfriends.text=Sláðu inn notendanöfn vina þinna í kassana að neðan og veldu bak- og forgrunnslit sem þér finnst hæfa þeim... + +/friends/edit_do.bml.friend=Vinur + +/friends/edit_do.bml.hover=Tylltu músinni á einhverjum lit til að sjá nafn hans + +/friends/edit_do.bml.mrcolor=Herra Litaskanni + +/friends/edit_do.bml.name=Nafn + +/friends/edit_do.bml.needmore=Ef þú vilt bæta fleiri vinum en komast fyrir að ofan, vistaðu breytingarnar með takkanum neðst á síðunni og hladdu síðuna aftur. + +/friends/edit_do.bml.nofriends.head=Engir vinir? + +/friends/edit_do.bml.nofriends.text=Þú ert ekki með neina vina skilgreinda eins og er. Ég er samt viss um að þú átt einhverja! :) Skrifaðu bara LiveJournal-notendanöfnin þeirra hér að neðan... + +/friends/edit_do.bml.opt.delete=Eyða? + +/friends/edit_do.bml.success.head=Meðbyr og brautargengi! + +/friends/edit_do.bml.success.text=Vinalisti þinn hefur verið uppfærður - hér er vinasíðan þín með færslum nýju vinanna. + +/friends/edit_do.bml.textcolor=Litur texta: + +/friends/edit_do.bml.title=Breyta vinalista + +/friends/edit_do.bml.user=Notandi + +/friends/edit_do.bml.viewer=Litakanni + +/friends/edit_do.bml.yourfriends.head=Vinir þínir + +/friends/edit_do.bml.yourfriends.text=Eftirfarandi eru skilgreindir sem vinir þínir: + +/friends/index.bml.security.header=Öryggi + +/friends/index.bml.security.only=Þegar þú merkir færslur þínar sem „aðeins fyrir vini“, þá á það við fólkið á vinalistanum þínum. + +/friends/index.bml.title=Vinaverkfæri + +/friends/index.bml.tools=Verkfæri + +/friends/popwithfriends.bml.account_type=Því miður geturðu ekki notað þetta tól með þinni tegund af skriftu. + +/friends/popwithfriends.bml.count=Telja + +/friends/popwithfriends.bml.exclude_own=Þú getur líka skoðað listann án vina. + +/friends/popwithfriends.bml.include_own=Þú getur líka skoðað listann með vinum. + +/friends/popwithfriends.bml.intro=Hér er listi yfir fólk sem er oftar en einu sinni á vinalista einhverra af vinum þínum en ekki skráð sem vinur þinn. + +/friends/popwithfriends.bml.intro_own=Hér er listi yfir fólk sem er oftar en einu sinni á vinalista einhverra af vinum þínum en ekki skráð sem vinur þinn. Þeir sem er skráðir vinir þínir eru einnig á listanum. + +/friends/popwithfriends.bml.no_users=Engir notendur + +/friends/popwithfriends.bml.title=Vinsælir notendur meðal vina þinna + +/friends/popwithfriends.bml.user=Notandi + +/index.bml.boldcreate=Búðu til þína eigin vefdagbók! + +/index.bml.frank.image.alt=Farandrekur, lukkugeit LiveJournal. + +/index.bml.frank.logo="Hvur rækallinn, ég get talað", segir Farandrekur. + +/index.bml.meta.desc=LiveJournal.com er staður þar sem þú getur deilt þínum pælingum með restinni af heiminum. + +/index.bml.meta.keywords=dagbók, vefdagbók, blogg, bloggarar, dagbækur, lífskrá, netblogg, netdagbók + +/interests.bml.add.added.head=Komið á listann! + +/interests.bml.add.added.text=Þessu áhugamáli hefur verið bætt á listann. + +/interests.bml.add.btn.text=Bæta við [[interest]] + +/interests.bml.add.confirm.head=Staðfesta + +/interests.bml.add.confirm.text=Smelltu á takkan að neðan til að setja [[interest]] á áhugamálalistann þinn. + +/interests.bml.add.toomany.head=Því miður... + +/interests.bml.add.toomany.text=Þú ert með [[maxinterests]] áhugamál skráð. + +/interests.bml.addint=Smelltu hér ef þú hefur áhuga á þessu, og vilt vera með á listanum. + +/interests.bml.btn.switch=Skipta + +/interests.bml.communities.text=Eftirfarandi samfélög hafa einnig áhuga á "[[interest]]". + +/interests.bml.count=Talin + +/interests.bml.enmasse.header=Sýsla með áhugamál + +/interests.bml.enmasse.intro=Breyta áhugamálum þínum í samanburði við áhugamál: + +/interests.bml.error.add.mustlogin=Þú verður að vera skráður inn til að bæta við áhugamáli á þennan hátt. + +/interests.bml.error.findsim_do.intnotfound=Ãhugamál fannst ekki. + +/interests.bml.findsim.searchwait=Vinsamlegast athugið: Leitin getur tekið fáeinar sekúndur. Verið þolinmóð. + +/interests.bml.finished.header=Tilbúið? + +/interests.bml.interests.viewpop=Skoða vinsæl áhugamál + +/interests.bml.match=[[count]] fundinn: + +/interests.bml.matches=[[count]] fundnir: + +/interests.bml.morestuff|staleness=1 +/interests.bml.morestuff=Fleira skemmtilegt er hægt að finna á áhugamálasíðunni. + +/legal/index.bml.about.header=Yfirlit + +/legal/index.bml.docs.header=Skjöl + +/login.bml.bindip.label=Binda við eina IP tölu: + +/login.bml.bindip.no=Nei (virkar með öllum nettengingum) + +/login.bml.bindip.yes=Já (öruggara, en virkar bara á einni tengingu) + +/login.bml.error.mustenterusername=Þú verður að slá inn notandanafn. + +/login.bml.expire.btn.neverexpire=Innskráning fellur aldrei úr gildi. + +/login.bml.expire.btn.sessiononly=Innskráning gildir aðeins í þetta skipti. + +/login.bml.expire.neverexpire.text=Innskráningin rennur aldrei úr gildi, þannig vertu viss um að útskrá þig alltaf ef þú ert í almenningstölvu, skóla, bókasafni eða hvar sem fleiri en þú nota tölvuna. Þú getur líka látið innskráninguna falla úr gildi þegar vafrinn lokast. + +/login.bml.expire.sessiononly.text=Innskráningin fellur úr gildi þegar þú lokar vafranum þínum. Ef þetta er þín tölva og þú ert eini notandinn gætir þú viljað stilla innkráninguna þannig að hún gildi alltaf. + +/login.bml.links.head=Tenglar + +/login.bml.links.link1=Vinasíðan þín. + +/login.bml.links.link2=Verkefnalistinn þinn. + +/login.bml.links.text=à náinni framtíð verða á þessari síðu alls konar tenglar og viðeigandi upplýsingar, en í millitíðinni gætirðu viljað kíkja á þetta: + +/login.bml.loggedin.head=Skráður inn! + +/login.bml.loggedin.text=Þú ert núna skráður inn. + +/login.bml.login.btn.changeopts=Breyta stillingum + +/login.bml.login.btn.login=Innskrá... + +/login.bml.login.expiration=Rennur út: + +/login.bml.login.forget=Manstu ekki lykilorðið..? + +/login.bml.login.head=Innskrá + +/login.bml.login.never=Aldrei + +/login.bml.login.otheropts=Aðrir möguleikar: + +/login.bml.login.password=Lykilorð: + +/login.bml.login.text1=Til að skrá inná [[sitename]], sláðu þá inn notandanafn og lykilorð að neðan. Nýir notendur: Farið hingað til að búa til nýja skriftu. + +/login.bml.login.text2|staleness=1 +/login.bml.login.text2=Þú gætir viljað stilla hvenær innskráningin fellur úr gildi. Venjulega gildir hún þar til þú lokar vafranum - sem er óneitanlega best á almenningstölvum. Ef þú ert hins vegar sá eini sem notar (og getur notað) þessa tölvu getur þú latið hana gilda alltaf. + +/login.bml.login.username=Notandanafn: + +/login.bml.login.whenbrowsercloses=Þegar vafri lokast + +/login.bml.title=Innskrá + +/login.bml.whylogin.benefit1=Þú þarft þá ekki lengur að slá inn notandanafn og lykilorð nokkurstaðar á síðunni. + +/login.bml.whylogin.benefit2=Þú munt geta lesið „læstar“ dagbækur semvinir þínir hafa gefið þér aðgang að. + +/login.bml.whylogin.benefit3=Ãmislegt er aðeins hægt að nota ef maður er skráður inn. + +/login.bml.whylogin.head=Til hvers að skrá sig inn? + +/login.bml.whylogin.text=Hér eru helstu kostir þess að skrá sig inn. + +/logout.bml.already.head=Þegar skráður út + +/logout.bml.already.text=Þú hefur þegar skráð þig út. + +/logout.bml.loggedout.head=Útskráður + +/logout.bml.loggedout.text=Þú ert nú útskráður. + +/logout.bml.title=Útskrá + +/lostinfo.bml.btn.proceed=Halda áfram + +/lostinfo.bml.enter_email=Sláðu inn notandanafn: + +/lostinfo.bml.enter_email_optional=Netfang: (valfrjálst) + +/lostinfo.bml.enter_username=Sláðu inn notandanafn þitt: + +/lostinfo_do.bml.lostpasswordmail.part2=Smelltu á tengilinn að neðan til að staðfesta að þetta er netfangið þitt: + +/lostinfo_do.bml.lostpasswordmail.part5<< +Nytsamlegir tenglar: + +LiveJournal dagbókin þín: +[[journalurl]] + +Uppfæra dagbókina í gegnum vafra: +[[updateurl]] + +Kveðja, +Livejournal-dróttnar +. + +/lostinfo_do.bml.lostpasswordmail.subject=Glatað lykilorð + +/lostinfo_do.bml.password_mailed.text=Meðbyr og brautargengi! Lykilorðið þitt hefur verið sent í pósthólfið þitt! + +/lostinfo_do.bml.password_mailed.title=Lykilorð hefur verið sent! + +/lostinfo_do.bml.title=Glataðar upplýsingar + +/lostinfo_do.bml.username_mailed.text=Meðbyr og brautargengi! Notandanafnið þitt hefur verið sent í pósthólfið þitt. + +/lostinfo_do.bml.username_mailed.title=Notandanafn sent á viðeigandi netfang! + +/manage/index.bml.about=Auðvelt er að stjórna skriftunni þinni og sérstilla - veldu bara eitt af svæðunum að neðan til að byrja: + +/manage/index.bml.communities=Skapaðu og sjáðu um eigin samfélög: + +/manage/index.bml.communities.create.about=Skapa nýtt samfélag + +/manage/index.bml.communities.header=Samfélög + +/manage/index.bml.communities.manage.about=Breyttu stillingum samfélagsins og hagi meðlima þess + +/manage/index.bml.customization=Láttu útlit dagbókarsíða þinna vera eftir þínu höfði: + +/manage/index.bml.customization.advanced=Sérstilling á hærra stigi + +/manage/index.bml.customization.advanced.about=Skoða, skapa og/eða laga þína eigin S2 uppsetningu eða stíl + +/manage/index.bml.customization.customize=Sérstilla dagbók + +/manage/index.bml.customization.customize.about=Breyttu útliti dagbókarinnar þinnar eða skiptu milli stílkerfa S1 og S2 + +/manage/index.bml.customization.header=Sérstillingar + +/manage/index.bml.customization.links=Tenglalisti + +/manage/index.bml.customization.links.about=Gerðu lista af tenglum sem birtast eiga í dagbókinni þinni + +/manage/index.bml.customization.modify.about=Breyttu útliti dagbókarinnar + +/manage/index.bml.customization.s1.header=Stílkerfi S1 + +/manage/index.bml.customization.s2.header=Stílkerfi S2 + +/manage/index.bml.entries=Sýsla með færslur sem þú hefur þegar gert í dagbók skriftunnar þinna: + +/manage/index.bml.entries.edit.about=Breyta eða eyða gömlum færslum + +/manage/index.bml.entries.header=Dagbókarfærslur + +/manage/index.bml.entries.memories.about=Skoða, sýsla með minnisstæðar færslur + +/manage/index.bml.friends=Sýsla með vini og vinahópa, eða sía vinasíðuna með ákveðnum vinahópum + +/manage/index.bml.friends.edit.about|staleness=1 +/manage/index.bml.friends.edit.about=Bæta notendum við, breyta miðlun þeirra eða fjarlæga þá af vinalistanum þínum + +/manage/index.bml.friends.filter=Sía vinasíðuna + +/manage/index.bml.friends.filter.about=Sía vinalistann til að sýna aðeins færslur ákveðins vinahópar + +/manage/index.bml.friends.groups.about=Skapa undirhópa, breyta miðlun þeirra eða fjarlæga undirhópa úr vinalistanum + +/manage/index.bml.friends.header=Vinir + +/manage/index.bml.information=Veldu hvaða upplýsingar þú vilt birta í skriftunni þinni. + +/manage/index.bml.information.changepass=Breyta lykilorði skriftu + +/manage/index.bml.information.changepass.about=Breyttu lykilorði skriftunnar þinnar + +/modify_do.bml.journalstatus.select.deleted=Hefur verið eytt + +/modify_do.bml.journalstatus.select.head=Staða: + +/modify_do.bml.journalstatus.select.suspended=Rekinn (ekki drekinn) + +/modify_do.bml.moodicons.head=Skapmerki + +/modify_do.bml.moodicons.select=Veldu sett skapmerkja: + +/modify_do.bml.overrides.warning=ÞÚ SKRIFAR EKKI DAGBÓKINA ÞÃNA HÉRNA!!! + +/modify_do.bml.success.head=Meðbyr og brautargengi! + +/modify_do.bml.success.text=Dagbókarstillingum þínum hefur verið breytt. Þú getur skoðað nýju útkomuna hér! + +/paidaccounts/index.bml.costs.header=Jæja, hvað kostar þetta mikið? + +/paidaccounts/index.bml.costs.rates.amount.header=Gjald + +/paidaccounts/index.bml.costs.rates.time.header=Lengd áskriftar + +/paidaccounts/index.bml.features.header=Hvaða svölu eiginleikum verð ég þá gædd/ur? + +/paidaccounts/index.bml.whypay.header=Verð ég að borga til að nota LiveJournal? + +/styles/index.bml.title=Eigin stílar + +/suggestions/index.bml.info.title=Aðrar upplýsingar + +/suggestions/index.bml.title=Hugmyndakassi + +/suggestions/index.bml.welcome.title=Heil/l þér! + +/support/encodings.bml.edit.header=Ég get ekki lagað færslurnar mínar með netviðmótinu! + +/support/encodings.bml.editcl.header=Mér tekst ekki að laga færslur í færsluvélinni! + +/support/encodings.bml.groups.header=Mér tekst ekki að sýsla með vinalistann minn í færsluvélinni minni! + +/support/encodings.bml.overview.header=Hvað á þetta allt að þýða? + +/support/encodings.bml.still.header=Enn í vanda? + +/support/faqbrowse.bml.lastupdated=Síðast uppfært: + +/talkmulti.bml.error.login=Þú ert ekki skráður inn. + +/talkmulti.bml.error.none_selected=Þú hefur ekki valið neinar athugasemdir. + +/talkmulti.bml.error.privs.delete=Þú hefur ekki leyfi til að eyða þessum athugasemdum. + +/talkmulti.bml.error.privs.screen=Þú hefur ekki leyfi til að hylja þessar athugasemdir. + +/talkmulti.bml.error.privs.unscreen=Þú hefur ekki leyfi til að opinbera þessar athugasemdir. + +/talkmulti.bml.screened.body=Athugasemdir hafa verið huldar. Þú getur skoðað þær hér. + +/talkmulti.bml.screened.title=Athugasemdir huldar + +/talkmulti.bml.title.delete=Eyða mörgum athugasemdum + +/talkmulti.bml.title.screen=Fela margar athugasemdir + +/talkmulti.bml.title.unscreen=Opinbera margar athugasemdir + +/talkmulti.bml.unscreened.body=Athugasemdirnar hafa verið opinberaðar. Þú getur skoðað þær hér. + +/talkmulti.bml.unscreened.title=Athugasemdir hafa verið opinberaðar + +/talkpost.bml.allowedhtml=Leyft HTML + +/talkpost.bml.error.cannotreplynopost=ÞÞú getur ekki svarað færslu sem ekki er til. + +/talkpost.bml.error.nocommentsjournal=Notandi hefur lokað á svör í dagbókinni sinni. + +/talkpost.bml.error.nocommentspost=Notandi hefur lokað á svör við þessari tilteknu færslu. + +/talkpost.bml.error.noreplypost=Svar fannst ekki (hefur kannski verið eytt?) + +/talkpost.bml.error.noreply_deleted=Þessari athugasemd hefur verið eytt - þú getur ekki svarað henni. + +/talkpost.bml.error.noreply_screened=Þetta svar er falið því þú hefur ekki leyfi til að lesa það né svara því. + +/talkpost.bml.label.picturetouse=Mynd sem á að nota: + +/talkpost.bml.loganonip=ATH Þessi notandi skráir allar IP tölur óskráðra notenda. + +/talkpost.bml.loginq=Innskrá? + +/talkpost.bml.logyourip=ATH Þessi notandi skráir IP töluna þína þegar þú svarar einhverju. + +/talkpost.bml.nosubjecthtml=Ekkert HTML virkar í viðfangslínu + +/talkpost.bml.opt.anonymous=Ónafngreindur + +/talkpost.bml.opt.defpic=(grunnstillingar) + +/talkpost.bml.opt.friendsonly=- þessi notandi hefur bannað athugasemdir frá öllum sem ekki eru á vinalista hans. Ef [[username]] bætir þér á listann sinn getur þú skrifað athugasemdir í dagbókina hans. + +/talkpost.bml.opt.from=Frá: + +/talkpost.bml.opt.ljuser=LiveJournal notandi: + +/talkpost.bml.opt.loggedin=Innskráður sem: [[username]] + +/talkpost.bml.opt.message=Skilaboð: + +/talkpost.bml.opt.noanonpost=- þessi notandi hefur bannað athugasemdir frá ónafngreindum. + +/talkpost.bml.opt.noautoformat=Ekki sníða sjálfkrafa: + +/talkpost.bml.opt.noimage=Note ekkert tákn + +/talkpost.bml.opt.preview=Prufuskoða + +/talkpost.bml.opt.spellcheck=Leita að enskum villum áður en skráð er + +/talkpost.bml.opt.subject=Titill: + +/talkpost.bml.opt.submit=Skrifa athugasemd + +/talkpost.bml.opt.willscreen=(mun vera hulið) + +/talkpost.bml.opt.willscreenfriend=(mun verða hulið ef þú ert ekki vinur) + +/talkpost.bml.paraformat=Greinaskil eru sjálfkrafa sniðin. + +/talkpost.bml.postresponse=Svara með athugasemd: + +/talkpost.bml.title=Skrifa athugasemd + +/talkpost.bml.usermismatch<< +Þú skráðir inn notendanafn en afhakaðir „Livejournal notandi“ valmöguleikann. + +Vinsamlegast hreinsaðu annaðhvort notendanafnið eða veldu réttan skrifham og reyndu á ný. +. + +/talkpost.bml.warnscreened=Athugið: Þessi athugasemd verður hulin. Svar við henni mun opinbera hana og gera hana þannig sjáanlega. + +/talkpost_do.bml.error.badpassword=Rangt lykilorð var gefið fyrir notandanafnið sem var áður skilgreint. Þú getur endurheimtad lykilorðið þitt hér, hafir þú gleymt því eða glatað. + +/talkpost_do.bml.error.badusername=Livejournal notandanafnið sem þú notaðir er ekki til staðar. Þú getur endurheimtað notandanafnið þitt hér, hafir þú gleymt því eða glatað - annars geturðu skrifað eitthvað „ónafngreindur“. + +/talkpost_do.bml.error.banned=Þú hefur ekki leyfi til að skrifa í dagbók þessa notanda. + +/talkpost_do.bml.error.confused_identity=Þú sláðir inn notendanafn, en valdir svo að svara án nafns eða sem sá sem er innskráður. Farðu aftur og ákveddu hvað þú ætlaðir að gera. + +/talkpost_do.bml.error.friendsonly=Aðeins vinir [[user]] mega skrifa í þessa dagbók. + +/talkpost_do.bml.error.lostcookie=Innskráningarsmákakan þín virðist hafa horfið...? + +/talkpost_do.bml.error.manybytes=Því miður er athugasemdin þín [[current]] of stór í bætum talið, þar sem hámarkið er [[limit]]. Vinsamlegast styttu hana og reyndu að skrá hana aftur. + +/talkpost_do.bml.error.manychars=Því miður er athugasemdin þín [[current]] of stór í bókstöfum talið, þar sem hámarkið er [[limit]]. Vinsamlegast styttu hana og reyndu að skrá hana aftur. + +/talkpost_do.bml.error.mustlogin=Þú verður að vera skráður inn eða nota notandanafn og lykilorð til að svara þessari læstu færslu. + +/talkpost_do.bml.error.noanon=Þú getur ekki skrifað óinnskráður í dagbók þessarar manneskju. + +/talkpost_do.bml.preview.subject=titill: + +/talkpost_do.bml.success.loggedin=Þú ert núna skráður inn. + +/talkpost_do.bml.success.message=Svar þitt hefur verið skráð. Þú getur skoðað það hér. + +/talkpost_do.bml.success.title=Meðbyr og brautargengi! + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Skrifa athugasemd + +/talkread.bml.anonuser=(Ónafngreindur) + +/talkread.bml.select=Velja + +/talkread.bml.subjectdeleted=[eytt] + +/talkread.bml.talkmulti.delete=Eyða + +/talkread.bml.talkmulti.des=Hópaðgerðir á valdar athugasemdir: + +/talkread.bml.talkmulti.screen=Hylja + +/talkread.bml.talkmulti.submit=Setja í framkvæmd + +/talkread.bml.talkmulti.unscreen=Opinbera + +/talkread.bml.title=Lesa athugasemdir + +/talkscreen.bml.error.login=Þú verður að vera skráður inn til að vinna með lokuð svör. + +/talkscreen.bml.error.privs.screen=Þú hefur ekki leyfi til að hylja þessa athugasemd. + +/talkscreen.bml.error.privs.unscreen=Þú hefur ekki leyfi til að opinbera þessa athugasemd. + +/talkscreen.bml.screen.doit=Já, hylja þessa athugasemd. + +/talkscreen.bml.screened.title=Meðbyr og brautargengi! + +/talkscreen.bml.unscreened.title=Meðbyr og brautargengi! + +/tools/memadd.bml.body.added.body=Listinn þinn yfir minningarverðar færslur hefur verið uppfærður. + +/tools/memadd.bml.body.added.header=Meðbyr og brautargengi! + +/tools/memadd.bml.form.reset=Endurræsa + +/tools/memadd.bml.form.submit=Senda inn + +/tools/memadd.bml.keywords=Kenniorð: + +/tools/memadd.bml.keywords.example=Dæmi: fyndið, aulalegt, rómantík + +/tools/memadd.bml.keywords.select=Þú getur líka notað kenniorð sem þú hefur notað á aðrar færslur: + +/tools/memadd.bml.login.forgot.header=Gleymdirðu einhverju? + +/tools/memadd.bml.security.friendsonly=Aðeins fyrir vini + +/tools/memadd.bml.security.private=Einkamál + +/tools/memadd.bml.security.public=Opinbert + +/tools/memadd.bml.title=Bæta í minningasafn + +/tools/memadd.bml.title.added=Komið inn + +/tools/memadd.bml.title.deleted=Hefur verið eytt + +/tools/memadd.bml.title.edit_memory=Laga minnisverða færslu + +/tools/memadd.bml.whocansee=Hver getur séð að maður hafi merkt færslu sem minnisverða? Allir, aðeins fólk á vinalista eða bara maður sjálfur? + +/tools/memories.bml.back=Til baka + +/tools/memories.bml.body.keyword<< + +[[user]] fannst minnisverðar. p?> +. + +/tools/memories.bml.error.noentries.body|staleness=2 +/tools/memories.bml.error.noentries.body<< +Þetta gæti stafað af því að: +1) Notandinn hefur ekki hefur ekki skilgreint neinar minnisverar færslur +2) Minnisverðu færslur notandans eru læstar og þú ekki með leyfi til að skoða þær +3) eða að eingar minnisverðu færslanna passa við síuna þína +. + +/tools/memories.bml.error.noentries.title=Engar minnisverðar færslur fundust + +/tools/memories.bml.filter.all=Allt minnisvert + +/tools/memories.bml.filter.other=Aðeins aðrar færslur + +/tools/memories.bml.filter.own=Aðeins færsur eftir '[[user]]' + +/tools/memories.bml.form.switch=Skipta + +/tools/memories.bml.sort.journal=Dagbók + +/tools/memories.bml.sort.orderadded=Pöntun bætt við + +/tools/memories.bml.title.keyword=Minnisverðar [[keyword]] færslur + +/tools/memories.bml.title.memorable=Minnisverðar færslur + +/tools/memories.bml.uncategorized=Óflokkað + +/update.bml.altpost=Dagbók til að skrá í: + +/update.bml.btn.update=Uppfæra dagbók + +/update.bml.currmood=Skap: + +/update.bml.currmusic=Er að hlusta á: + +/update.bml.date=Dagsetning: + +/update.bml.default=Það venjulega + +/update.bml.defaultjournal=([[user]]) -- þetta venjulega + +/update.bml.error.login=Villumelding við innskráningu: + +/update.bml.error.nopass=Sláðu inn lykilorð + +/update.bml.error.update=Villumelding átti sér stað við að uppfæra dagbók: + +/update.bml.event=Atburður: + +/update.bml.full=Upfærslusíða með aukavalmöguleikum + +/update.bml.localtime=Staðartími: + +/update.bml.loggedinas=Þú ert sem stendur skráð/ur inn sem [[user]].
        Smelltu hér til að uppfæra sem annar notandi. + +/update.bml.loggingin=Skrái inn á netþjón.... + +/update.bml.noneother=Ekkert, eða eitthvað annað: + +/update.bml.note|staleness=1 +/update.bml.note=ATH: Tíminn að ofan er á tímabelti netþjónsins - breytið til ef þið eruð á öðru. + +/update.bml.opt.backdate=Gömul færsla: + +/update.bml.opt.backdate.about=Kemur ekki fram á vinasíðu + +/update.bml.opt.defpic=( + +/update.bml.opt.nocomments=Loka á svör: + +/update.bml.opt.noemail=Ekki senda mér svör eða athugasemdir: + +/update.bml.opt.noformat=Ekki sníða sjálfkrafa: + +/update.bml.opt.spellcheck=Fara yfir stafsetningarvillur áður en skráð er + +/update.bml.options=Aukastillingar + +/update.bml.other=Annað + +/update.bml.password=Lykilorð: + +/update.bml.picture=ynd sem á að nota: + +/update.bml.security.custom=Sníða betur eftir vexti? + +/update.bml.security.friends=Vinir + +/update.bml.security.head=Öryggisstig: + +/update.bml.security.private=Einkaefni + +/update.bml.security.public=Opinbert + +/update.bml.servermsg=Heyrðu, netþjónnin þarf eitthvað að tjá sig: + +/update.bml.simple=Þú ert á einföldu síðunni - fleiri möguleikar eru hérna. + +/update.bml.spellchecked=Eftir stafsetningarprófun: + +/update.bml.subject|staleness=1 +/update.bml.subject=Titill:(óþarfi, en nothæft við langar færslur) + +/update.bml.timeformat=24 stunda sólarhringur + +/update.bml.title=Uppfærsla á dagbók + +/update.bml.title.readonly=Aðeins til lestrar + +/update.bml.update.head=Uppfæra dagbókina þína... + +/update.bml.update.success|staleness=1 +/update.bml.update.success=Uppfærsla tókst. Þú getur skoðað færsluna hér. + +/update.bml.updating=Uppfæri dagbók... + +/update.bml.username=Notandanafn: + +/userinfo.bml.about.comm|staleness=1 +/userinfo.bml.about.comm=Upplýsingar + +/userinfo.bml.about.user|staleness=1 +/userinfo.bml.about.user=Æviágrip + +/userinfo.bml.body.leave=Þú getur sagt þig úr samfélaginu hvenær sem er. + +/userinfo.bml.comminfo.body=Að neðan eru upplýsingar um LiveJournal samfélagið "[[commname]]". + +/userinfo.bml.comminfo.name=Upplýsingar um samfélag + +/userinfo.bml.date.never=Aldrei + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Gallað notandanafn. + +/userinfo.bml.error.notloggedin=Skráðu þig inn, ef þú vilt sjá þína eigin upplýsingasíðu. Þú getur líka farið á www.livejournal.com/~notandanafn_þitt/userinfo. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Skoðað af + +/userinfo.bml.friendof.hidden=(falið) + +/userinfo.bml.friendof.syndreadcount=Tala lesenda + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Vinur + +/userinfo.bml.friends.comm=Meðlimir + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Vinir + +/userinfo.bml.label.addbuddy=Bæta við Félaga + +/userinfo.bml.label.adduser=Bæta við notanda + +/userinfo.bml.label.birthdate=Fæðingardagur + +/userinfo.bml.label.clientsused=Forritnotuð: + +/userinfo.bml.label.comments=Athugasemdir: + +/userinfo.bml.label.composted=Skrifað: [[num]] - + +/userinfo.bml.label.comreceived=Fengið: [[num]] + +/userinfo.bml.label.datecreated=Skapað þann: + +/userinfo.bml.label.dateupdated=Síðast uppfært: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=Netfang: + +/userinfo.bml.label.icquin=ICQ númer: + +/userinfo.bml.label.interests=Ãhugamál + +/userinfo.bml.label.interests.modifyyours|staleness=1 +/userinfo.bml.label.interests.modifyyours=Breyta þínum áhugamálum + +/userinfo.bml.label.interests.removesome|staleness=1 +/userinfo.bml.label.interests.removesome=Fjarlægja nokkur áhugamál + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] áhugamál ekki birt + +/userinfo.bml.label.journalentrs=Dagbókarfærslur: + +/userinfo.bml.label.location=Staður: + +/userinfo.bml.label.memberof=Meðlimur: + +/userinfo.bml.label.memories=Minningar: + +/userinfo.bml.label.moredetails=(frekari upplýsingar...) + +/userinfo.bml.label.msnusername=MSN notendanafn: + +/userinfo.bml.label.name=Nafn: + +/userinfo.bml.label.nofriends=Ekki til í skrá. + +/userinfo.bml.label.reqfinduser=Aðeins notendur með 'finduser' réttindi geta leitað að notendum eftir notendanafni. + +/userinfo.bml.label.sendmessage=Senda skilaboð + +/userinfo.bml.label.shared|staleness=2 +/userinfo.bml.label.shared=Deild dagbók: + +/userinfo.bml.label.supportpoints=Aðstoðarstig + +/userinfo.bml.label.syndicatedfrom=Sent frá: + +/userinfo.bml.label.syndicatedstatus=Staða samsteypunar: + +/userinfo.bml.label.textmessage=Texti
        Skilaboð
        : + +/userinfo.bml.label.todo=Verkefnalisti + +/userinfo.bml.label.user=Notandi: + +/userinfo.bml.label.viewfriends=Skoða vini + +/userinfo.bml.label.viewmembers=Skoða meðlimi + +/userinfo.bml.label.website=Vefsíða: + +/userinfo.bml.label.yahooid=Yahoo! nafn: + +/userinfo.bml.memories.entries=[[count]] færslur + +/userinfo.bml.memories.entry=[[count]] færsla + +/userinfo.bml.monitor.comm=Umsjónarsamfélag + +/userinfo.bml.monitor.user=Bæta þessum notenda á vinalistann þinn + +/userinfo.bml.nonexist.body|staleness=1 +/userinfo.bml.nonexist.body=Það er ekki neinn notandi sem gengur undir nafninu [[user]], því miður. + +/userinfo.bml.nonexist.name=Óþekktur notandi + +/userinfo.bml.sendmessage.body=Senda[[user]]textaboð
        í farsíma/friðþjóf hans/hennar + +/userinfo.bml.syn.last.never=Aldrei + +/userinfo.bml.syn.lastcheck=Síðast gáð: + +/userinfo.bml.syn.nextcheck=Næst gáð: + +/userinfo.bml.syn.parseerror=Villumelding: + +/userinfo.bml.syndinfo.body=Ef þú vilt að greinar af þessari sameiginlegu skriftu að birtast á vinablaðsíðunni þinni getur þú bætt þessari dagbók á vinalistann. + +/userinfo.bml.syndinfo.name=Sameiginleg dagbók + +/userinfo.bml.tellafriend=Segðu vini frá þessu! + +/userinfo.bml.timeupdate.dayago=à gær + +/userinfo.bml.timeupdate.daysago=Fyrir [[num]] dögum + +/userinfo.bml.timeupdate.hourago=fyrir klukkutíma + +/userinfo.bml.timeupdate.hoursago=fyrir [[num]] klukkutímum + +/userinfo.bml.timeupdate.minuteago=fyrir mínútu + +/userinfo.bml.timeupdate.minutesago=fyrir [[num]] mínútum + +/userinfo.bml.timeupdate.secondago=fyrir einni sekúndu síðan! + +/userinfo.bml.timeupdate.secondsago=Fyrir [[num]] sekúndum + +/userinfo.bml.timeupdate.weekago=Fyrir einni viku + +/userinfo.bml.timeupdate.weeksago=Fyrir [[num]] vikum + +/userinfo.bml.title=Upplýsingar um notanda + +/userinfo.bml.title.communityinfo=Samfélagsupplýsingar + +/userinfo.bml.title.syndicated=Sameiginleg skrifta + +/userinfo.bml.userinfo.body=Hér fyrir neðan eru upplýsingarum [[username]]. Ef þú ert þessi notandi getur þú breytt upplýsingunum um þig (eða valið hvað á að vera opinbert) á upplýsingastillingasíðunni. + +/userinfo.bml.userinfo.name=Upplýsingar um notanda + +BML.parse_multipart.parse=Villa við að greina upphal. + +BML.parse_multipart.toolarge=Upphal of stórt + +BML.parse_multipart.unknowntype=Óþekkt tegund innihalds + +btn.search=Leita + +date.day.friday.long=föstudagur + +date.day.friday.short=fös + +date.day.monday.long=mánudagur + +date.day.monday.short=mán + +date.day.saturday.long=laugardagur + +date.day.saturday.short=lau + +date.day.sunday.long=sunnudagur + +date.day.thursday.long=Fimmtudagur + +date.day.thursday.short=Fim + +date.day.tuesday.long=Þriðjudagur + +date.day.tuesday.short=Þri + +date.day.wednesday.long=Miðvikudagur + +date.day.wednesday.short=Mið + +date.month.april.long=Apríl + +date.month.august.long=Ãgúst + +date.month.august.short=Ãgú + +date.month.december.long=Desember + +date.month.december.short=Des + +date.month.february.long=Febrúar + +date.month.january.long=Janúar + +date.month.july.long=Júlí + +date.month.july.short=Júl + +date.month.june.long=Júní + +date.month.june.short=Jún + +date.month.march.long=Mars + +date.month.may.long=Maí + +date.month.may.short=Maí + +date.month.november.long=Nóvember + +date.month.november.short=Nóv + +date.month.october.long=Október + +date.month.october.short=Okt + +dystopia.btn.login=INNSKRà + +dystopia.hello_anonymous=Velkominn í LiveJournal! + +dystopia.hello_loggedin=Góðan daginn, [[username]]! + +dystopia.nav.createjournal=Búa til dagbók + +dystopia.nav.developer=Hönnuðasvæðið + +dystopia.nav.download=Niðurhlaða + +dystopia.nav.editentries=Laga færslur + +dystopia.nav.editfriends=Vinahagur + +dystopia.nav.editpassword=Lykilorðið þitt + +dystopia.nav.editpics=Myndirnar þínar + +dystopia.nav.editstyle=Breyta stíl + +dystopia.nav.faq=Spurt og svarað + +dystopia.nav.findcomm=Eftir samfélögum + +dystopia.nav.finddir=Skráarleit + +dystopia.nav.findint=Eftir áhugamáli + +dystopia.nav.findrandom=Handahófskennt + +dystopia.nav.findregion=Eftir svæði + +dystopia.nav.home=Heim + +dystopia.nav.journalcalendar=Dagatal + +dystopia.nav.journalfriends=Vinir + +dystopia.nav.journalinfo=Um notanda + +dystopia.nav.journalrecent=Nýjustu færslur + +dystopia.nav.legalprivacy=Trúnaður + +dystopia.nav.legaltos=Reglur um notkun + +dystopia.nav.login=Innskrá + +dystopia.nav.logout=Útskrá + +dystopia.nav.lostinfo=Týndi lykilorði... + +dystopia.nav.memories=Minnisvert + +dystopia.nav.modifyjournal=Breyta dagbók + +dystopia.nav.news=Fréttir + +dystopia.nav.paidaccts=Ã-skriftur + +dystopia.nav.paymentarea=Borgunarsvæði + +dystopia.nav.personalinfo=Persónuupplýsingar + +dystopia.nav.sitemap=Kort af vefsíðu + +dystopia.nav.siteopts=Skoða val + +dystopia.nav.support=Liggur þér eitthvað á hjarta? + +dystopia.nav.updatejournal=Uppfæra dagbók + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=122 + +dystopia.navhead.findusers=Finna notendur + +dystopia.navhead.help=Hjálp & aðstoð + +dystopia.navhead.journal=Dagbókin þín + +dystopia.navhead.legal=Löglegt + +dystopia.navhead.settings=Stillingarnar þínar + +dystopia.navhead.welcome=Velkominn! + +dystopia.search.aolim=AIM nafn + +dystopia.search.icq=ICQ númer + +dystopia.search.int=Ãhugamál + +dystopia.search.msn=MSN notendanafn + +dystopia.search.region=Svæði + +dystopia.search.yahoo=Yahoo! kenninafn + +dystopia.searchlj=Leita í LiveJournal: + +Email=Netfang + +email.newacct.subject=Velkomin/n í LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Villumelding + +error.badpassword=Rangt lykilorð. + +error.dberror=Villa í gagnagrunni: + +error.deleted.name=Hefur verið eytt + +error.deleted.text=Þessari dagbók hefur verið eytt. Ef þú ert [[user]] hefur þú einn mánuð til að endurheimta dagbókina. Eftir mánuð verður öllu efni eytt fyrir fullt og allt af netþjónum okkar. + +error.deleted.title=Eydd skrifta + +error.invalidauth=Ekki var hægt að staðfesta að þú værir þessi notandi. + +error.ipbanned=Þessi IP tala hefur verið bönnuð þar sem of oft misheppnaðist að skrá inn úr henni. + +error.malformeduser=Misheppnað notendanafn. + +error.nobutton=Var ekki þrýst á neinn hnapp? + +error.nodb=Gagnagrunnur tímabundið ekki til staðar. + +error.nodbmaintenance=Þessi hluti gagnasafnsins er niðri eins og er vegna bilunar. Reyndu aftur eftir nokkrar mínútur. + +error.noentry=Engin slík færsla til. + +error.nojournal=Óþekkt dagbók + +error.noremote=Þú verður að vera skráð/ur inn til að nota þessa síðu. + +error.procrequest=Villumelding átti sér stað við úrvinnslu beiðni þinnar: + +error.purged.name=Hefur verið eytt + +error.purged.text=Þessari dagbók hefur verið eytt. + +error.purged.title=Tæmd skrifta + +error.suspended.name=Rekinn + +error.suspended.text=Þessi skrifta hefur annaðhvort verið tímabundið eða endanlega eytt. Ef þú ert [[user]], kíktu þá í Skriftunni minni hefur verið eytt! Hvernig fæ ég hana til baka? hlutann af hjálparbókinni til að fá frekari upplýsingar.Athugaður að til að halda trúnaðarleynd getur [[sitename]] ekki rætt ástæður eyðingarinnar við neinn nema eiganda skriftunnar sem eytt var. + +error.suspended.title=Eydd skrifta + +error.tempdisabled=Þetta hefur verið aftengt tímabundið. + +error.unknownmode=Óþekktur hamur. + +error.usernameinvalid=Óleyfilegir stafir eru í notandanafni. + +error.usernamelong=Notandanafn er of langt - hámarkið er 15 stafir. + +error.username_notfound=Notandanafn fannst ekki. + +Help=Hjálp + +label.security.custom=Sjálfsníða... + +label.security.friends=Vinir + +label.security.head=Öryggisstig: + +label.security.private=Trúnó + +label.security.public=Opinbert + +label.switch.button=Skipta + +label.switch.header=Skipta um dagbók + +label.switch.workwith=Vinna í dagbók: + +langname.be=Belrúsíska + +langname.da=Danska + +langname.de=Þýska + +langname.en=Enska + +langname.en_GB=Breska + +langname.en_LJ=Enska + +langname.es=Spænska + +langname.et=Eistneska + +langname.fi=Finnska + +langname.fr=Franska + +langname.ga=Ãrska + +langname.gd=Gelíska + +langname.he=Hebreska + +langname.hu=Ungverska + +langname.is=Ãslenska + +langname.it=Ãtalska + +langname.ja=Japanska + +langname.la=Latína + +langname.lv=Latverska + +langname.ms=Malaíska + +langname.nb=Norskt bókmál + +langname.nl=Hollenska + +langname.nn=Nýnorska + +langname.pl=Pólska + +langname.pt=Portúgalska + +langname.ru=Rússneska + +langname.sv=Sænska + +langname.tr=Tyrkneska + +langname.uk=Úkraíska + +langname.zh=Einfölduð kínverska + +ljcom.account.feature.email=LiveJournal netfang + +ljcom.account.feature.full2=Sjá alla samanburðartöfluna. + +ljlib.pageofpages=Síða [[page]] af [[total]] + +lostinfo.head=Gleymdirðu einhverju? + +lostinfo.text=Ef þú gleymdir notandanafninu eða lykilorðinu þínu geturðu fengið það hér. + +lynx.nav.friends=Vinir + +lynx.nav.help=Tæknileg hjálp + +lynx.nav.home=Heim + +lynx.nav.login=Innskráning + +lynx.nav.logout=Útskrá + +lynx.nav.recent=Nýlegar færslur + +lynx.nav.sitemap=Vefsíðukort + +lynx.nav.siteopts=Vöfrunarstillingar + +lynx.nav.update=Uppfæra dagbók + +Password=Lykilorð + +password.max30=Lykilorð mega ekki vera lengri en 30 stafir. + +portal.bdays.count.des=Venjulega eru 5 nærstu afmælisdagar vina birtir. + +portal.bdays.count.name=Hve marga afmælisdaga á að sýna + +portal.bdays.portalname=Afmælisdagar + +portal.bdays.portaltitle=Afmælisdagar + +portal.goat.name=Geitin attarna + +portal.goattext.des=Hvað viltu að geitin þín segi? Það eina sem geitur geta í raun sagt er „ble-e-e-e-a“, en þar sem það er frekar einhæft og leiðinlegt getur þú látið sem þín sé í raun að segja eitthvað annað. + +portal.goattext.name=Línur geitarinnar + +portal.login.portalname=Innskráningarkassi + +portal.memories.entriesnoun=færstlur + +portal.popfaq.portalname=10 mest lesnu „Spurt og svarað“ færslur + +portal.popfaq.portaltitle=10 mest lesnu „Spurt og svarað“ færslur + +portal.randuser.count.des=Venjulega er aðeins einn notandi valinn af handahófi, en þú getur haft allt að 10 lóðrétt í mjóum dálki eða 5 lárétt í breiðum dálki. + +portal.randuser.count.name=Fjöldi handahófsvaldra notenda til að sýna + +portal.randuser.error.tableempty=Það eru engir handahófsvaldir notendur. Hafðu samband við kerfisstjóra. + +portal.randuser.hidename.des=Venjulega sýnir viðmótið nafn handahófsvalda notandans - hakaðu hér til að sýna það ekki. + +portal.randuser.hidename.name=Fela nafn + +portal.randuser.hidepic.des=Venjulega er mynd handahófsvalda notandans sýnd, ef hún er til staðar. Hakaðu hér til að sýna hana ekki. + +portal.randuser.hidepic.name=Fela mynd notanda + +portal.randuser.portalname=Handahófsvalinn notandi + +portal.randuser.portaltitle=Handahófsvalinn notandi + +portal.randuser.portaltitleplural=Handahófsvaldir notendur + +portal.recent.error.noentries=Því miður, engar færslur. + +portal.recent.error.notsetup=Þú verður að stilla þennan kassa. Smelltu á plús merkið til að velja hvaða dagbókum þú vilt fylgjast með héðan. + +portal.recent.error.userstatus=Þessi notandi hefur annaðhvort eytt eða tekið skriftu sína úr notkun. + +portal.recent.items.description=Venjulega er aðeins nýjasta færslan sýnd. + +portal.recent.items.name=Hlutir sem á að sýna + +portal.recent.journal.description=Hvaða dagbók viltu fylgjast með? + +portal.recent.journal.name=Dagbók + +portal.recent.nosubject=(Ekkert viðfangsefni) + +portal.recent.permlink=Tengill + +portal.recent.portalname=Nýjustu færslur + +portal.recent.portaltitle=Kassi nýjustu færslna + +portal.recent.showtext.description=Venjulega er aðeins viðfangsefni færslna sýnd. + +portal.recent.showtext.name=Sýna færsluna sjálfa líka + +portal.stats.journalentyest=Færslur dagsins í gær + +portal.stats.portaltitle=Tölfræði + +portal.stats.totalusers=Heildarnotendur + +portal.update.mode.full=Fullnýtt + +portal.update.mode.name=viðmót + +portal.update.mode.simple=Einfalt + +portal.update.portalname=Dagbókaruppfærsla + +portal.update.portaltitle=Uppfæra dagbók + +protocol.bad_password=Lykilorðið þitt er svo einfalt að auðvelt yrði að geta upp á því. Ég mæli með því að þú breytir því, því annars hefurðu á hættu að dagbókinni þinni verði rænt. Farðu á [[siteroot]]/changepassword.bml til að breyta lykilorðinu. + +protocol.hello_test=Halló fröken prufuskrifta! + +protocol.mail_bouncing=Þú notar lélegt eða óvirkt netfang. Allur póstur sem við sendum þér endursendist til bara. [[sitename]] krefst netfangs sem virkar ef á að nota það meira. Farðu á [[siteroot]]/ support/faqbrowse.bml?faqid=19 til að fá upplýsingar um hvernig á að breyta netfangi þínu. + +protocol.modpost=Færslan þín hefur verið send til stjórnanda/enda. Þær eru skoðaðar í röðinni sem þær berast, og stjórnandinn sem fer yfir hana ákveður hvort hún verður sett upp eður ei. + +protocol.must_revalidate=Þú þarft að staðfesta netfangið þitt þar sem þú hefur skipt um það. Ef þú staðfestir það ekki geturðu ekki notað alla möguleika [[sitename]]. Frekari upplýsingar er að finna á [[siteroot]]/support/faqbrowse.bml?faqid=11. + +protocol.not_validated=Netfangið þitt hefur ekki verið staðfest. Þú getur þó notað [[sitename]], en hefur ekki aðgang að öllum möguleikum síðunnar þar til þú staðfestir netfangið. Líttu á leiðbeiningarnar sem þú fékkst í pósti þegar þú skapaðir dagbókina þína eða farðu á [[siteroot]]/support/faqbrowse.bml?faqid=11 til að fá frekari upplýsingar. + +protocol.old_win32_client=Það eru komnir nokkuð mikið nýrri Windows LiveJournal færsluvélar og því mælum við með því að þú uppfærir þína. Farðu á [[siteroot]/download/ til að ná í nýja vél. + +protocol.readonly=Skriftuna þína er tímabundið aðeins hægt að lesa. Sumar aðgerðir munu ekki virka í nokkrar mínútur + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Aðgerð mistókst + +talk.anonwrote=Einhver út í bæ skrifaði: + +talk.anonwrote_comm=Einhver ritaði í [[commlink]]: + +talk.btn.preview=Prufuskoða + +talk.commentpermlink=staður í gagnasafni + +talk.commentpost=Skrifa athugasemd + +talk.commentsread=Skoða athugasemdir + +talk.curname_Mood=skap: + +talk.curname_Music=Er að hlusta á: + +talk.error.bogusargs=Einhver galli + +talk.error.comm_deleted=Þessari færslu hefur nú verið eytt. + +talk.error.deleted=Þessari dagbók hefur verið hent. + +talk.error.deleted.title=Eytt + +talk.error.mustlogin=Þú verður að vera skráður inn til að lesa þessa læstu færslu. + +talk.error.nocomment=Þetta svar er ekki til. + +talk.error.noentry=Engin slík færsla. + +talk.error.nojournal=Bilun átti sér stað: tókst ekki að tilgreina dagbók. + +talk.error.nosuchjournal=Engin slík dagbók til + +talk.error.notauthorised=Þú ert ekki með leyfi til að skoða þessa læstu færslu. + +talk.error.suspended=Þessi dagbók/notande hefur verið rekinn. Nei, hann er ekki drekinn, hann var REKINN! + +talk.error.suspended.title=(D)Rekinn. + +talk.parentlink=Skoða yfirfærslu + +talk.readsimilar=Lesa svipaðar færslur: + +talk.replytothis=Svara þessu + +talk.somebodywrote=[[realname]] ([[userlink]]) ritaði eftirfarandi, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) ritaði eftirfarandi í [[commlink]], + +talk.spellcheck=Gá að enskum stafsetningarvillum í prufuskoðun + +talk.threadlink=Skoða þráð + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_islensku + +Username=Notandanafn + +userpic.inactive=Óvirkt + +xcolibur.greeting.anon=Velkomin í LiveJournal! + +xcolibur.greeting.logged_in=Heill þér, [[name]]! [[logout]] + +xcolibur.login=Innskrá? + +xcolibur.logout=Útskrá? + +xcolibur.nav.about=Um + +xcolibur.nav.about.download=Niðurhala + +xcolibur.nav.about.general=Almennar upplýsingar + +xcolibur.nav.about.paidaccounts=Ã-skriftur + +xcolibur.nav.about.press=Fréttasíða + +xcolibur.nav.about.sitenews=Fréttir á síðunni + +xcolibur.nav.about.stats=Ãmis hlutföll + +xcolibur.nav.footer.sitemap=Kort af síðu + +xcolibur.nav.help=Hjálp + +xcolibur.nav.help.ask=Spurðu spurningar + +xcolibur.nav.help.faq=SOS + +xcolibur.nav.help.lostpassword=Glatað lykilorð + +xcolibur.nav.home=Heim + +xcolibur.nav.journal=Dagbók + +xcolibur.nav.journal.archive=Safn + +xcolibur.nav.journal.edit.entries=Breyta færslum + +xcolibur.nav.journal.friends=Vinir + +xcolibur.nav.journal.info=Upplýsingar + +xcolibur.nav.journal.memories=Minnisvert + +xcolibur.nav.journal.recent=Síðustu færslur þinar + +xcolibur.nav.journal.update=Uppfæra + +xcolibur.nav.manage=Breyta + +xcolibur.nav.manage.community=Samfélög + +xcolibur.nav.manage.customize=Sérsníða dabók + +xcolibur.nav.manage.entries=Færslur + +xcolibur.nav.manage.friends=Vinir + +xcolibur.nav.manage.info=Upplýsingar + +xcolibur.nav.manage.password=Lykilorð + +xcolibur.nav.manage.pics=Notandamyndir + +xcolibur.nav.manage.styles=Hönnun + +xcolibur.nav.search=Leit + +xcolibur.nav.search.directory=Svæði + +xcolibur.nav.search.directory.search=Nákvæmari leit + +xcolibur.nav.search.interests=Ãhugamál + +xcolibur.nav.search.random=Slembileit + +xcolibur.nav.siteopts=Vafrunarval + +xcolibur.nav.title=Hvert viltu fara? + +xcolibur.nav.welcome=Velkomin/n + +xcolibur.nav.welcome.create=Skapa skriftu + +xcolibur.nav.welcome.login=Innskrá + +xcolibur.nav.welcome.update=Uppfærsla dagbókina þína + +xcolibur.search=Leita + +xcolibur.search.aolim=AOL notandanafn + +xcolibur.search.category=Flokkur: + +xcolibur.search.icq=ICQ númer + +xcolibur.search.int=Ãhugamál + +xcolibur.search.msn=MSN netfang + +xcolibur.search.region=Svæði + +xcolibur.search.yahoo=Yahoo! kenni + +xcolibur.upgrade=Uppfæra skriftu + diff --git a/ljcom/bin/upgrading/it.dat b/ljcom/bin/upgrading/it.dat new file mode 100644 index 0000000..19532f0 --- /dev/null +++ b/ljcom/bin/upgrading/it.dat @@ -0,0 +1,1047 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Se vuoi cancellare o ripristinare il tuo journal, qui e' dove puoi farlo. Una volta che l'hai cancellato hai 30 giorni per ripristinarlo, nel caso dovessi cambiare idea. Dopo 30 giorni, il journal sara' cancellato in modo permanente e non ci sara' piu' modo di recuperarlo. + +/accountstatus.bml.journalstatus.head=Stato di Attivazione del Journal + +/accountstatus.bml.journalstatus.select.activated=Attivato + +/accountstatus.bml.journalstatus.select.deleted=Cancellato + +/accountstatus.bml.journalstatus.select.head=Stato: + +/accountstatus.bml.journalstatus.select.suspended=Sospeso + +/allpics.bml.current=Immagini Attuali + +/allpics.bml.edit2=Potresti voler modificare le parole chiave delle tue foto o caricare una nuova foto. + +/allpics.bml.error.noparam=Devi specificare il parametro utente + +/allpics.bml.keywords=Parole-chiave: + +/allpics.bml.nopics.text.other=Questo utente non ha caricato nessuna foto. + +/allpics.bml.nopics.text2=Non hai foto caricate. Per caricarne una, vai qui. + +/allpics.bml.nopics.title=Nessuna Immagine + +/allpics.bml.pics=Ecco le immagini di [[user]]. + +/allpics.bml.title=Immagini Utente + +/changepassword.bml.btn.proceed=Procedi + +/changepassword.bml.changepassword.header=Cambia Password + +/changepassword.bml.changepassword.instructions|staleness=1 +/changepassword.bml.changepassword.instructions=Riempi il modulo qui sotto per cambiare la password. + +/changepassword.bml.email.body<< +La tua password e' stata cambiata a [[sitename]]. + +Per recuperarla in futuro, visita: + +[[siteroot]]/lostinfo.bml + +[[sitename]] Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Cambio di Password + +/changepassword.bml.error.badcheck=Errore nella nuova password: [[error]] + +/changepassword.bml.error.badnewpassword|staleness=1 +/changepassword.bml.error.badnewpassword=Le due password nuove non coincidono. Riscrivile entrambe... hai fatto un errore in una di esse. + +/changepassword.bml.error.badoldpassword=La vecchia password non e' corretta. + +/changepassword.bml.error.blankpassword=La nuova password non puo' essere vuota. + +/changepassword.bml.error.changetestaccount=Non posso cambiare la password dell acount test + +/changepassword.bml.error.characterlimit=Le password sono limitate a un massimo di 30 caratteri. + +/changepassword.bml.error.invaliduser=Utente non valido [[user]]. Questo utente non esiste. Sei sicuro di averlo scritto in modo corretto? + +/changepassword.bml.error.mustenterusername=Devi inserire il tuo username. + +/changepassword.bml.error.nonascii=Le password sono limitate ai soli simboli ASCII. Per piacere scegli una password che non usa simboli non-ASCII. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Non puoi cambiare la password se il tuo indirizzo di email non e' stato verificato. + +/changepassword.bml.newpassword=Nuova password: + +/changepassword.bml.newpasswordagain=Nuova password (di nuovo): + +/changepassword.bml.oldpassword=Vecchia password: + +/changepassword.bml.proceed.instructions=Premi il bottone sotto e la tua password sarà cambiata. Riceverai anche un'email, che ti notifica il cambio di password. + +/changepassword.bml.success.text=La tua password e' stata cambiata e un email ti e' stata inviata + +/changepassword.bml.title=Cambia Password + +/community/index.bml.title=Centro della Comunita' + +/community/join.bml.button.join=Entra nella Comunita' + +/community/join.bml.label.addtofriends=Aggiungi "[[maintainer]]" alla lista amici
        + +/community/join.bml.label.allowposting=Questa comunita' permette a tutti i membri di postare, quindi ora hai anche tu la possibilita' di scriverci dentro. Se hai gia' un client livejournal aperto sul tuo computer dovrai uscire e rientrare di nuovo con la tua password, perche' questo journal venga mostrato nella lista di journals in cui puoi postare. + +/community/join.bml.label.banned=Il maintainer/I maintainers di questa comunita' ti hanno precluso l'iscrizione. + +/community/join.bml.label.commlogged=Stai usando un account condiviso/comunita', non il tuo account personale. + +/community/join.bml.label.errorcomminfo=Le informazioni della comunita' specificate non sono valide. + +/community/join.bml.label.expls=Premi il bottone qui in basso per entrare nella comunita' di "[[maintainer]]". De-seleziona la casella qui sotto se vuoi entrare nella comunita' senza vedere le sue entries nella tua pagina amici. + +/community/join.bml.label.loginfirst=Per entrare in una comunita' devi prima entrare nel tuo account. + +/community/join.bml.label.membernow=Ora sei membro della Comunita' [[commname]] + +/community/join.bml.label.sure=Sicuro? + +/community/join.bml.success=Successo + +/community/join.bml.title=Entra nella Comunita' + +/community/leave.bml.button.leave=Abbandona la Comunita' + +/community/leave.bml.label.buttontoleave=Premi il bottone qui in basso per lasciare la comunita' "[[commname]]". + +/community/leave.bml.label.infoerror=Le informazioni della comunita' specificate non sono valide. + +/community/leave.bml.label.logoutfirst=Per lasciare una comunita' devi prima entrare nel tuo account + +/community/leave.bml.label.removed=Ora sei fuori dalla Comunita' [[commname]] + +/community/leave.bml.success=Successo + +/community/leave.bml.sure=Sicuro? + +/community/leave.bml.title=Abbandona Comunita' + +/community/search.bml.button.clear=Ripulisci Modulo + +/community/search.bml.button.search=Cerca! + +/community/search.bml.checkbox.onlywithpics=Solo comunita' con immagini + +/community/search.bml.label.byinterest=Per Interesse + +/community/search.bml.label.bylocation=Per Localita' + +/community/search.bml.label.bytime=Per Tempo di aggiornamento del Journal + +/community/search.bml.label.city=Citta': + +/community/search.bml.label.country=Nazione: + +/community/search.bml.label.displayoptions=Mostra Opzioni + +/community/search.bml.label.hasmember=Ha come Membro + +/community/search.bml.label.othercriteria=Altri Criteri + +/community/search.bml.label.outputformat=Formato di Output: + +/community/search.bml.label.records=Records per pagina: + +/community/search.bml.label.searchcomm=Cerca Comunita' + +/community/search.bml.label.selecriteria=Scegli i criteri secondo i quali vorresti trovare le comunita'. I risultati saranno dati dall'intersezione di tutti i criteri di ricerca. In altre parole, ogni casella che barri vuol dire "E", non "O". + +/community/search.bml.label.sortmethod=Metodo di Ordinamento: + +/community/search.bml.label.stateprovince=Stato/Provincia: + +/community/search.bml.label.updated=Aggiornato nell'ultimo + +/community/search.bml.sel.bypicture=Per Immagine + +/community/search.bml.sel.communityname=Nome della Comunita' + +/community/search.bml.sel.commview=Vista della Comunita' + +/community/search.bml.sel.day=giorno + +/community/search.bml.sel.month=mese + +/community/search.bml.sel.simple=Semplice + +/community/search.bml.sel.updatetime=Data di Aggiornamento + +/community/search.bml.sel.username=Nome Utente + +/community/search.bml.sel.week=settimana + +/community/search.bml.title=Ricerca Comunita' + +/create.bml.age.check.question=Hai meno di 13 anni? + +/create.bml.age.check.yes=Si, ho meno di 13 anni + +/create.bml.age.head=Eta' + +/create.bml.btn.proceed=Procedi... + +/create.bml.clusterselect.head=Selezione Cluster + +/create.bml.clusterselect.nocluster=Nessun Cluster + +/create.bml.clusterselect.text=Scegli il cluster sul quale vuoi creare questo account. Nota: Questa e' un'opzione solo per il debugging/test. Nella produzione, gli utenti non la sceglieranno, e non ne sapranno niente. + +/create.bml.create.head=Creare un Nuovo Journal + +/create.bml.create.text=Creare un nuovo LiveJournal e' facile, devi solo seguire le istruzioni qui sotto! + +/create.bml.email.head=Il tuo indirizzo email + +/create.bml.email.input.head=Indirizzo Email: + +/create.bml.error.coppa.under13=Spiacente, a causa delle restrizioni COPPA, non puoi usare il servizio offerto da LiveJournal finche' non hai 13 anni. Torna dopo il tuo tredicesimo compleanno. + +/create.bml.error.email.blank=Devi fornire il tuo indirizzo email. + +/create.bml.error.email.lj_domain=Non puoi usare un alias di [[domain]] quando crei un account. Per piacere inserisci un altro indirizzo email. + +/create.bml.error.email.nospaces=Non sono permessi spazi nell'indirizzo email. Se sei su AOL, ricorda che il tuo indirizzo email e' il tuo screen-name privato degli spazi, seguito da @aol.com + +/create.bml.error.password.asciionly=Puoi usare solo simboli ASCII nella password. + +/create.bml.error.password.blank=Devi inserire una password. + +/create.bml.error.password.nomatch=Le password non coincidono. + +/create.bml.error.postrequired=POST richiesto. + +/create.bml.error.username.blank=Fornisci un nome o un soprannome. + +/create.bml.error.username.inuse=Username gia' in uso; ti preghiamo di sceglierne un altro. + +/create.bml.error.username.iscode=Questo username sembra essere un codice di invito, non un username. + +/create.bml.error.username.mustenter=Devi inserire un username. + +/create.bml.error.username.reserved=Spiacente, questo username e' riservato. + +/create.bml.name.head=Il Tuo Nome + +/create.bml.name.input.head=Nome: + +/create.bml.name.text=Qual'e' il tuo nome o soprannome? Questo apparira' nella parte superiore del tuo journal, e nella directory utente, se sceglierai di essere elencato. Non devi necessariamente fornire il tuo nome completo, e neanche il tuo vero nome. + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Re-inserisci la password: + +/create.bml.password.text=Scegli una password. + +/create.bml.proceed.btn.proceed=Procedi... + +/create.bml.proceed.warning=Premi Procedi solo una volta!! + +/create.bml.success.btn.enterinfo=Inserisci le Informazioni Personali + +/create.bml.success.head=Successo! + +/create.bml.success.text1|staleness=1 +/create.bml.success.text1=Il tuo journal e' stato creato. Ti sono state inviate importanti informazioni di registrazioni a [[email]] contenenti altre istruzioni. Nota: Hai esattamente sette giorni per confermare la creazione del tuo journal. Se dopo sette giorni non l'avrai ancora fatto l'username [[username]] sara' cancellato automaticamente e qualcun altro potra' usarlo. + +/create.bml.success.text2=Il tuo LiveJournal sara' disponibile a: + +/create.bml.success.text3=Ora inserisci qualche informazione su di te. E' opzionale, ma ci da' la possibilita' di farci un'idea su chi usa LiveJournal. + +/create.bml.title=Crea Nuovo Journal + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Per creare un nuovo account, inserisci un codice di creazione account: + +/create.bml.useacctcodes.welcome=Benvenuto + +/create.bml.username.forpaidaccts=O, per account a pagamento: + +/create.bml.username.ljaddress=Il tuo journal sara' a questi indirizzi: + +/create.bml.username.text=Ogni utente [[sitename]] deve avere il proprio username. Il tuo username e' quello che appare nell'indirizzo del tuo journal, e che usi per entrare nel server [[sitename]]. Inoltre viene mostrato quando scrivi commenti nei journal di altre persone. + +/editinfo.bml.allowshowcontact.about=Dovresti lasciare selezionata questa opzione. Questo permette ad altre persone di contattarti, mostrando il tuo indirizzo email, codice ICQ, e lo screen-name di AOL Instant Messenger, tutto sul tuo LiveJournal. + +/editinfo.bml.allowshowcontact.email=Se visibile, indirizzo email da mostrare: + +/editinfo.bml.allowshowcontact.email.actual_only=Solo indirizzo effettivo + +/editinfo.bml.allowshowcontact.email.both=Entrambi (effettivo + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Solo indirizzo LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=Nessuno. Non mostrare nessun indirizzo email. + +/editinfo.bml.allowshowcontact.email.no_show=Non mostrare l'indirizzo email + +/editinfo.bml.allowshowcontact.email.show=Mostra indirizzo email + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Con l'opzione sopra, puoi anche scegliere se nascondere il tuo indirizzo email (mostrando tuttavia le altre informazioni per contattarti), mostrare solo il tuo indirizzo email di LiveJournal (solo per account a pagamento), mostrare solo il tuo vero indirizzo, o mostrarli entrambi. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Con l'opzione sopra, puoi anche scegliere di nascondere il tuo indirizzo email (mostrando tuttavia le altre informazioni per contattarti). + +/editinfo.bml.allowshowcontact.title=Vuoi mostrare le informazioni per contattarti sul tuo LiveJournal? + +/editinfo.bml.allowshowinfo.about=Abilitalo se vuoi che la tua citta'/il tuo stato/la tua nazione siano visibili agli altri utenti. + +/editinfo.bml.allowshowinfo.title=Vuoi mostrare localita' & compleanno? + +/editinfo.bml.autotranslate.about<< +Usa questa opzione per dire al LiveJournal che codifica usare per entries e commenti inseriti prima che il sito fosse convertito in Unicode. +Se scrivi in Inglese, scegli "Western European". +. + +/editinfo.bml.autotranslate.header|staleness=1 +/editinfo.bml.autotranslate.header=Traduci automaticamente le vecchie entries da: + +/editinfo.bml.bday.title=Compleanno + +/editinfo.bml.bday.year.opt=l'anno e' opzionale + +/editinfo.bml.bdayreminders.about=Se vuoi ricevere email che ti ricordi i compleanni dei tuoi amici su LiveJournal, barra questa casella. + +/editinfo.bml.bdayreminders.header|staleness=1 +/editinfo.bml.bdayreminders.header=Ricordami i compleanni + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=Qui puoi inserire una mini-biografia su di te che verra' mostrata nella tua pagina user-info. + +/editinfo.bml.bio.header=Su di Te + +/editinfo.bml.blockrobots.about|staleness=1 +/editinfo.bml.blockrobots.about=Se selezioni questa opzione, ai robot sara' detto di andare via. Non tutti i robot rispettano le regole, ma quelli dei motori di ricerca famosi lo fanno. + +/editinfo.bml.blockrobots.header=Non permettere ai Robot/Ragni di inserire il tuo journal nei loro database + +/editinfo.bml.city.title=Citta' + +/editinfo.bml.country.choose=Scegli una nazione + +/editinfo.bml.country.title=Nazione + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=Scegli questo se vuoi che la gente possa rispondere alle entries che metti nel tuo journal. (lo stile di journal che scegli deve supportare questa opzione) + +/editinfo.bml.enableboards.header=Abilita' message boards + +/editinfo.bml.encoding.about=Non ti preoccupare di questa roba. Di solito solo gli utenti internazionali che scrivono in diverse lingue hanno bisogno di cambiare qualcosa qui. + +/editinfo.bml.encoding.header=Opzioni di Codifica + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Non puoi inserire un indirizzo email @[[domain]] . +Inserisci il tuo vero indirizzo in questo campo. +Se sei un utente a pagamento, l'indirizzo [[user]]@[[domain]] rispedisce le email ricevute al tuo indirizzo effettivo. +Per scegliere quale indirizzo email (o entrambi) viene mostrato publicamente, guarda l'opzione sotto a "Mostra le Informazioni per Contattarti" +. + +/editinfo.bml.error.email.no_space<< +Non sono permessi spazi in un indirizzo email. +Se sei su AOL, ricorda che il tuo indirizzo email e' il tuo screen-name privato degli spazi, seguito da @aol.com +. + +/editinfo.bml.error.excessive_int=Spiacente, hai elencato troppi interessi. Il limite e' 150, mentre tu ne hai inseriti [[intcount]]. Nessun cambiamento fatto alla tua lista di interessi e' stato salvato. Torna indietro e riduci la lista, poi salva di nuovo. + +/editinfo.bml.error.invalidbio=La tua biografia contiene caratteri non validi. Devi visitare la pagina di conversione per convertirlo in Unicode. + +/editinfo.bml.error.invalidints=La tua attuale lista di interessi contiene caratteri non validi. Devi visitare la pagina di conversione per convertirla in Unicode. + +/editinfo.bml.error.invalidname=Il tuo nome contiene caratteri non vlaidi. Devi visitare la pagina di conversione per convertirlo in Unicode. + +/editinfo.bml.error.locale.country_ne_state=Hai specificato Stati Uniti come nazione, ma hai inserito uno stato non appartenente agli Stati Uniti nel campo "altro stato". + +/editinfo.bml.error.locale.invalid_country=In qualche modo hai selezionato una nazione non valida. + +/editinfo.bml.error.locale.state_ne_country=Hai specificato una nazione diversa dagli Stati Uniti ma hai scelto uno stato appartenente agli Stati Uniti. + +/editinfo.bml.error.locale.zip_ne_state=Il tuo codice di avviamento postale non corrisponde allo stato specificato. Correggi le informazioni, o cancella il campo stato o codice postale, o entrambi. + +/editinfo.bml.error.locale.zip_requires_us|staleness=1 +/editinfo.bml.error.locale.zip_requires_us=Hai inserito un codice di avviamento postale ma non hai scelto Stati Uniti come nazione. Raccogliamo informazioni sul codice postale solo di persone negli Stati Uniti. Torna indietro e cancella il codice postale o scegli Stati Uniti come nazione. + +/editinfo.bml.error.tm.require.number=Se vuoi usare il text-messaging devi inserire il tuo numero di telefono. + +/editinfo.bml.error.tm.require_provider<< +Se vuoi usare il text-messaging, devi selezionare il tuo gestore. + +Se non e' nella lista, contattaci con le informazioni riguardanti il servizio di text-messaging del tuo gestore, cosi' possiamo aggiungerlo. +. + +/editinfo.bml.finished.about=Quando hai finito, premi il bottone "Salva Modifiche" qui in basso: + +/editinfo.bml.finished.header=Fatto? + +/editinfo.bml.finished.save_button=Salva Modifiche + +/editinfo.bml.gender.title=Sesso + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Scegli questo se vuoi ricevere avvisi via email quando qualcuno risponde alle entries del tuo journal. + +/editinfo.bml.getreplies.header=Ricevi risposte della message-board + +/editinfo.bml.hidefriendof.about=Se scegli questo, la lista di persone che ti elencano tra i propri amici non sara' visibile sulla tua pagina di informazioni. + +/editinfo.bml.hidefriendof.header=Nascondi lista "Amico di" + +/editinfo.bml.howhear.about|staleness=1 +/editinfo.bml.howhear.about<< +Solo per curiosita', dove hai sentito di [[sitename]]? +Se da una persona specifica inserisci il suo username, se da un'altra fonte/articolo/link/sito, inserisci le informazioni appropriate. +. + +/editinfo.bml.howhear.header=Curiosita' + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about=Scegli questo se il tuo programma di email supporta l'HTML completamente. Molti client provano a supportarlo ma falliscono orribilmente. Se non lo scegli LiveJournal mandera' solo email di testo. + +/editinfo.bml.htmlemail.header=Invia Email HTML + +/editinfo.bml.int.about=Se vuoi che altra gente possa cercare nella directory e trovarti cercando i tuoi interessi, elenca qui sotto tutto cio' in cui sei interessato, separato da virgole. Frasi corte o di una sola parola sono la cosa migliore. Regola pratica: Dovresti poter inserire l'interesse nella frase "Mi piace _______". Quando ti riferisci ad un sostantivo usa la forma plurale: "Mi piacciono i DVDs" invece di "Mi piace il DVD". + +/editinfo.bml.int.ex.bad=CATTIVO Esempio: Mi piacciono tanti gruppi e guardare film e parlare con gli amici ed andare ai club. Questo genere di cose va messa nella mini-biografia. + +/editinfo.bml.int.ex.good=BUON Esempio: andare in bici, computers, dvds, mp3s, formaggio, donne + +/editinfo.bml.int.header=Interessi + +/editinfo.bml.login.enterinfo=Inserisci il tuo username e la tua password per modificare le tue informazioni personali. + +/editinfo.bml.login.forgot.header=Dimenticato qualcosa? + +/editinfo.bml.login.forgot.recover=Se hai dimenticato il tuo username o la tua password, recuperali qui! + +/editinfo.bml.logip.always=Sempre + +/editinfo.bml.logip.anon_only=Solo gli anonimi + +/editinfo.bml.logip.header=Segna l'indirizzo IP delle persone che rispondono? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Se scegli l'opzione sopra e hai paura che spam-robots trovino il tuo indirizzo email su LiveJournal, scegli questa opzione ed il tuo indirizzo sara' modificato in modo da non essere riconosciuto dai bot che raccolgono indirizzi email. + +/editinfo.bml.mangleaddress.header=Altera il tuo indirizzo email quando viene visualizzato + +/editinfo.bml.name.title=Nome + +/editinfo.bml.numcomments.about=Scegli questo se vuoi aggiungere il conteggio del commento agli URL per far mostrare al tuo browser i links in un colore differente + +/editinfo.bml.numcomments.header=Aggiungi &nc=xx agli URL del commento + +/editinfo.bml.optional=Opzionale + +/editinfo.bml.opt_in.about<< +Se vuoi sapere quando aggiungiamo qualche nuova caratteristica figa a LiveJournal, barra questa casella. +Le email che riceverai saranno abbastanza rare, non piu' di una o due al mese, di solito. Il tuo indirizzo email non sara' visibile ad altri utenti, e puoi disabilitare questa opzione in qualsiasi momento. +. + +/editinfo.bml.opt_in.header=Inviatemi le novita' del Livejournal. + +/editinfo.bml.persinfo.disclaimer=Inserisci qualche informazione su di te, per la nostra curiosita' e per motivi statistici. Non faremo niente di malvagio o di seccante con queste informazioni, ci piacerebbe solo vedere chi sono e dove sono i nostri utenti. Perpiacere, riempila con informazioni corrette. Se ti interessa leggi la nostra politica per la privacy + +/editinfo.bml.persinfo.header=Informazioni Personali + +/editinfo.bml.screen.all=Tutto + +/editinfo.bml.screen.anon=Anonimo + +/editinfo.bml.screen.header=Quali risposte vuoi visualizzare di default? + +/editinfo.bml.screen.none=Nessuno + +/editinfo.bml.screen.nonfriends=Da non-amici + +/editinfo.bml.screen.nonmembers=Da non-membri + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=Sicurezza + +/editinfo.bml.security.visibility.anybody=Chiunque + +/editinfo.bml.security.visibility.everybody=Tutti + +/editinfo.bml.security.visibility.friends=Solo gli amici + +/editinfo.bml.security.visibility.regusers=Utenti Registrati + +/editinfo.bml.settings.header=Opzioni LiveJournal + +/editinfo.bml.state.other=Oppure, inserisci un'altro stato/provincia/territorio + +/editinfo.bml.state.title=Stato + +/editinfo.bml.state.us=Stati US + +/editinfo.bml.success.header=Successo! + +/editinfo.bml.success.message=Le tue informazioni e la configurazione del tuo journal e profilo sono stati aggiornati. + +/editinfo.bml.switch.button=Cambia + +/editinfo.bml.switch.header=Cambia Journal + +/editinfo.bml.switch.workwith=Lavora sul journal: + +/editinfo.bml.title=Modifica Informazioni Personali + +/editinfo.bml.tm.details=dettagli + +/editinfo.bml.tm.phonenum=Numero di telefono: + +/editinfo.bml.tm.sec.about=Abilita messaggi di testo dagli altri utenti. + +/editinfo.bml.tm.sec.title=Livello di Sicurezza: + +/editinfo.bml.tm.servprov=Gestore del Servizio: + +/editinfo.bml.translatemailto.about=Nel caso avessi scelto di ricevere via email le risposte della message-board, e il tuo client email non gestisce molto bene i messaggi Unicode (UTF-8), usa questa opzione per specificare una codifica differente, nella quale LiveJournal tradurra' automaticamente il testo dei commenti che ti vengono inviati. + +/editinfo.bml.translatemailto.header=Traduci avvisi email in: + +/editinfo.bml.unbanusers.about=Hai precluso ai seguenti utenti la possibilita' di postare nel tuo journal. Barra la casella vicino al loro username per rimuovere il divieto. + +/editinfo.bml.unbanusers.header=Leva il Ban + +/editinfo.bml.userpic.about=Qui sotto c'e' l'immagine che hai inviato per rappresentarti nel sito LiveJournal, nel tuo journal ed in quello dei tuoi amici. + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Per cancellare questa immagine, o inviarne un'altra, vai qui + +/editinfo.bml.userpic.header=La tua Immagine + +/editinfo.bml.userpic.none=nessuna immagine inviata + +/editinfo.bml.webpagename.title=Nome della Pagina Web + +/editinfo.bml.webpageurl.title=Indirizzo della Pagina Web + +/editinfo.bml.whoreply.header=Chi puo' rispondere alle tue entries? + +/editinfo.bml.zip.title=Codice Postale + +/editinfo.bml.zip.usonly=Codice Postale di 5 cifre; Solo per i residenti in USA + +/editjournal.bml.btn.proceed=Procedi... + +/editjournal.bml.certainday=Un Certo Giorno: + +/editjournal.bml.recententries=entries piu' recenti + +/editjournal.bml.recententry=Entry piu' recente + +/editjournal.bml.title=Modifica le Entries del tuo Journal + +/editjournal.bml.viewwhat=Visualizza Quale Entry: + +/editjournal_do.bml.btn.edit=Modifica la Entry Selezionata + +/editjournal_do.bml.btn.save=Salva Entry + +/editjournal_do.bml.continue.head=Premi per continuare... + +/editjournal_do.bml.continue.text=Dopo aver scelto una entry da cancellare o modificare, premi il pulsante Edit qui sotto. + +/editjournal_do.bml.currmood|staleness=1 +/editjournal_do.bml.currmood=Stato d'Animo: + +/editjournal_do.bml.currmusic=Musica: + +/editjournal_do.bml.date=Data: + +/editjournal_do.bml.edit.text|staleness=2 +/editjournal_do.bml.edit.text=Modifica i campi della entry che vuoi cambiare e premi il pulsante salva in fondo alla pagina. Per cancellare la entry, semplicemente cancella tutto il testo e premi salva... la entry sara' cancellata. + +/editjournal_do.bml.error.getting=C'e' stato un errore nel recuperare la entry da modificare: + +/editjournal_do.bml.error.modify=C'e' stato un errore nel modificare il tuo journal: + +/editjournal_do.bml.error.nofind=Non ho trovato la entry selezionata. + +/editjournal_do.bml.event=Evento: + +/editjournal_do.bml.localtime=Ora locale: + +/editjournal_do.bml.noneother=Niente, o altro: + +/editjournal_do.bml.opt.backdate.about=non verra' mostrato nella visualizzazione amici + +/editjournal_do.bml.opt.nocomments=Disabilita Commenti: + +/editjournal_do.bml.opt.noemail=Non inviare i Commenti in email: + +/editjournal_do.bml.opt.noformat=Non formattare automaticamente: + +/editjournal_do.bml.other=Altro: + +/editjournal_do.bml.pickentry.head=Scegli un entry da modificare + +/editjournal_do.bml.pickentry.text=Scegli cosa vuoi modificare e premi il pulsante modifica in fondo alla pagina. + +/editjournal_do.bml.picture=Immagine da usare: + +/editjournal_do.bml.save.head=Premi per salvare... + +/editjournal_do.bml.save.text=Quando hai finito di modificare la entry premi Salva. + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=Soggetto: (facoltativo, da usare su entries piu' lunghe) + +/editjournal_do.bml.success.delete=Entry cancellata. + +/editjournal_do.bml.success.edit|staleness=1 +/editjournal_do.bml.success.edit=La entry e' stata modificata. Puoi vederla qui. + +/editjournal_do.bml.success.head=Successo + +/editjournal_do.bml.timeformat=Ora (formato 24 ore) + +/editjournal_do.bml.title=Modifica Entries + +/friends/add.bml.add.header=Successo + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=L'utente e' stato aggiunto alla tua lista di amici. Puoi vedere la pagina dei tuoi amici qui + +/friends/add.bml.add.title=Amico Aggiunto! + +/friends/add.bml.btn.add=Aggiungi [[user]] + +/friends/add.bml.btn.modify=Modifica + +/friends/add.bml.btn.remove=Rimuovi + +/friends/add.bml.colors.bg=Sfondo + +/friends/add.bml.colors.fg=Testo + +/friends/add.bml.colors.header=Colori + +/friends/add.bml.colors.hover=(Passa con il mouse sopra un colore per vedere il suo nome) + +/friends/add.bml.colors.text=Se vuoi puoi anche selezionare i colori che rappresenteranno [[user]] nella tua lista di amici. + +/friends/add.bml.confirm.header=Aggiungere [[user]] agli amici? + +/friends/add.bml.confirm.text=Per aggiungere [[user]] alla tua lista di amici, premi sul bottone qui in basso. + +/friends/add.bml.confirm.title=Aggiungi Amico + +/friends/add.bml.error1.header|staleness=1 +/friends/add.bml.error1.header=Devi prima entrare nel tuo account + +/friends/add.bml.error1.text=Per aggiungere un utente alla tua lista di amici devi prima entrare nel tuo account. Se non hai ancora un account puoi crearne uno per seguire il journal del tuo amico. + +/friends/add.bml.error1.title=Aggiungi Amico + +/friends/add.bml.error2.text|staleness=1 +/friends/add.bml.error2.text=L'username inserito non e' valido. Per aggiungere un amico vai alla pagina modifica amici + +/friends/add.bml.error3.text=Hai gia' [[user]] elencato come amico. Ad ogni modo, puoi modificare i colori che hai scelto per rappresentarlo/a. + +/friends/add.bml.error3.title=Modifica Amico + +/friends/add.bml.groups.header=Gruppi Amici + +/friends/add.bml.groups.nogroup|staleness=1 +/friends/add.bml.groups.nogroup=Nessuna configurazione per i gruppi amici + +/friends/add.bml.groups.text=In quali gruppi di amici vuoi mettere questo utente? I gruppi di amici sono usati per filtrare la visualizzazione della tua lista di amici, ed anche per le opzioni di sicurezza basate sui gruppi. + +/friends/add.bml.remove.header=Successo + +/friends/add.bml.remove.text=L'utente e' stato cancellato dalla tua lista di amici. Puoi vedere la tua pagina degli amici qui. + +/friends/add.bml.remove.title=Amico Cancellato! + +/friends/edit.bml.title=Modifica Amici + +/friends/edit_do.bml.addfriends.head=Aggiungi Amici + +/friends/edit_do.bml.addfriends.text=Inserisci i nomi dei tuoi amici di LiveJournal nelle caselle qui sotto, e scegli quali colori di sfondo e di primo piano vuoi associare ad essi... + +/friends/edit_do.bml.background=Sfondo + +/friends/edit_do.bml.bgcolor=Colore di Sfondo: + +/friends/edit_do.bml.btn.close=Chiudi + +/friends/edit_do.bml.btn.save=Salva Modifiche + +/friends/edit_do.bml.btn.toggle=Mostra Finestra di Preview + +/friends/edit_do.bml.done.head=Fatto? + +/friends/edit_do.bml.done.text=Quando hai finito, premi il pulsante "Salva Modifiche" sotto... + +/friends/edit_do.bml.error.updating=C'e' stato un errore nell'aggiornamento della tua lista amici: + +/friends/edit_do.bml.fellowfriends.head=Amici: + +/friends/edit_do.bml.fellowfriends.text=Le seguenti persone ti hanno classificato come loro amico... Potresti voler anche tu elencare loro tra i tuoi amici. Piu' che altro questo serve come riferimento cosi' sai i loro usernames su LiveJournal. Non sei obbligato ad aggiungerli alla tua lista. + +/friends/edit_do.bml.foreground=Primo piano + +/friends/edit_do.bml.friend=Amico + +/friends/edit_do.bml.hover=Passa con il mouse su un colore per vederne il nome + +/friends/edit_do.bml.mrcolor=Mister Visualizza-Colori + +/friends/edit_do.bml.name=Nome + +/friends/edit_do.bml.needmore=Se hai bisogno di aggiungere piu' amici di quelli per cui c'e' spazio su questo modulo, salva le modifiche qui sotto, poi torna indietro e aggiungine altri. + +/friends/edit_do.bml.nofriends.head=Niente amici? + +/friends/edit_do.bml.nofriends.text=Al momento non hai nessun amico elencato. Ad ogni modo, siamo certi che tu debba avere qualche amico! :) Inserisci qui sotto i loro nomi su LiveJournal... + +/friends/edit_do.bml.opt.delete=Cancellare? + +/friends/edit_do.bml.success.head=Successo + +/friends/edit_do.bml.success.text|staleness=1 +/friends/edit_do.bml.success.text=I tuoi amici sono stati aggiornati. Puoi vedere la tua nuova pagina-amici qui. + +/friends/edit_do.bml.textcolor=Colore del Testo: + +/friends/edit_do.bml.title=Modifica Amici + +/friends/edit_do.bml.user=Utente + +/friends/edit_do.bml.viewer=Visualizzatore Colori + +/friends/edit_do.bml.yourfriends.head=I Tuoi Amici + +/friends/edit_do.bml.yourfriends.text=Hai nella lista i seguenti amici: + +/friends/index.bml.title=Strumenti Amici + +/index.bml.boldcreate=Crea il tuo LiveJournal personale! + +/index.bml.frank.image.alt=Frank, la capra-mascotte del LiveJournal. + +/index.bml.frank.logo="Baaaaah",dice Frank. + +/index.bml.meta.desc=LiveJournal.com e' un posto dove condividere i tuoi pensieri con il mondo. + +/index.bml.meta.keywords=diario, journnal, journal online, diari, scrivere, diario online, diario web + +/interests.bml.add.added.head=Aggiunto! + +/interests.bml.add.added.text=L'interesse e' stato aggiunto alla tua lista. + +/interests.bml.add.btn.text=Aggiungi [[interest]] + +/interests.bml.add.confirm.head=Conferma + +/interests.bml.add.confirm.text=Per aggiungere [[interest]] agli interessi, clicca sul bottone qui sotto. + +/interests.bml.add.toomany.head=Spiacente... + +/interests.bml.add.toomany.text=Hai gia' [[maxinterests]] interessi. + +/interests.bml.addint=Se anche tu sei interessato a questo e vorresti essere aggiunto a questa lista clicca qui. + +/interests.bml.communities.head=Comunita' Rilevanti + +/interests.bml.communities.text=Anche le seguenti comunita' sono interessate in "[[interest]]". + +/interests.bml.count=Conteggio + +/interests.bml.error.add.mustlogin=Devi entrare nel tuo account per poter aggiungere un interesse. + +/interests.bml.error.findsim_do.intnotfound=L'interesse non e' stato trovato. + +/interests.bml.findsim.searchwait=Nota: La ricerca durera' diversi secondi. Abbi pazienza. + +/interests.bml.findsim_do.account.notallowed=Spiacente, il tuo tipo di account non ti permette di usare questa funzione. + +/interests.bml.findsim_do.magic=Indice
        Magico + +/interests.bml.findsim_do.magic.head=Indice Magico? + +/interests.bml.findsim_do.magic.text=Per ogni utente che corrisponde viene calcolato un indice magico, che dipende da due fattori: il numero di interessi in comune, e qualche punto extra per interessi in comune che sono poco diffusi. + +/interests.bml.findsim_do.nomatch.head=Nessuna Corrispondenza + +/interests.bml.findsim_do.nomatch.text=Nessun utente e' simile a [[user]]. + +/interests.bml.findsim_do.notdefined=L'utente [[user]] non ha definito nessun interesse. + +/interests.bml.findsim_do.similar.head=Utenti Simili + +/interests.bml.findsim_do.similar.text=I seguenti sono gli utenti piu' correlati a [[user]] + +/interests.bml.interest=Interesse + +/interests.bml.interested.btn.find=Trova + +/interests.bml.interested.in|staleness=1 +/interests.bml.interested.in=Trova persone interessate a: + +/interests.bml.interests.head=Interessi + +/interests.bml.interests.text|staleness=1 +/interests.bml.interests.text=Ecco qualche cosa divertente che puoi fare con gli interessi... + +/interests.bml.interests.viewpop=Guarda interessi diffusi + +/interests.bml.match=[[count]] corrispondono: + +/interests.bml.matches=[[count]] corrisponde: + +/interests.bml.morestuff|staleness=1 +/interests.bml.morestuff=Altre cose divertenti sono sulla pagina degli interessi. + +/interests.bml.nointerests.text=Non hai nessun interesse elencato? Aggiungine qualcuno andando alla pagina Modifica Informazioni Personali ed Opzioni + +/interests.bml.popular.head=Interessi Diffusi + +/interests.bml.popular.text=I seguenti sono gli interessi piu' diffusi. + +/interests.bml.title=Interessi + +/interests.bml.toomany.body=Ci sono [[intcount]] persone e/o comunita' che elencano questo tra gli interessi. Non sara' mostrata una lista. + +/interests.bml.toomany.head=Molte corrispondenze. + +/interests.bml.users.head=Utenti interessati + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=Anche i seguenti utenti sono interessati a [[interest]] + +/legal/index.bml.about<< +Lo scopo di LiveJournal e' di offrire un'esperienza significativa per membri di qualsiasi nazione e con qualsiasi background, percio' abbiamo qualche regola necessaria a garantire questo. I nostri documenti qui contengono molte informazioni su come faremo del nostro meglio per servirvi, e come ci aspettiamo che i membri si comportino verso di noi e verso gli altri. LiveJournal funziona al meglio quando le persone seguono queste regole. Eccone alcune importanti da ricordare: +
          +Non disturbare, abusare, o minacciare gli altri. +
        • Non danneggiare i minorenni in nessun modo.
        • +
        • Non spammare il sito o un account sul sito.
        • +
        • Non postare materiale protetto dal copyright senza permesso.
        • +
        • Non invadere la privacy degli altri.
        • +
        • Non violare le leggi degli USA o le leggi del tuo paese in nessun modo.
        • +
          +La lista completa di regole puo' essere letta qui sotto: +. + +/legal/index.bml.about.header=Visione generale + +/legal/index.bml.docs.coppa.about=Il "Children's Online Privacy Protection Act" (COPPA) decide le regole per la raccolta online e l'uso delle informazioni personali, fornite da e riguardanti i bambini al di sotto dei tredici anni. La nostra pagina COPPA spiega la nostra posizione a riguardo di questa legge, e delinea il modo di gestire gli argomenti del COPPA. + +/legal/index.bml.docs.header=Documenti + +/legal/index.bml.docs.privacy.about=La Politica di Privacy spiega quali informazioni acquisiamo dai nostri membri e come usiamo quelle informazioni. + +/legal/index.bml.docs.tos.about=I Termini del Servizio spiegano le nostre regole d'uso, cosi' come le condizioni generali riguardanti i membri. Essere membri e/o usare il sistema significa accettare questi e gli altri termini. + +/login.bml.error.mustenterusername=Devi inserire un username + +/login.bml.expire.btn.neverexpire=Cambia modalita' di scadenza a MAI + +/login.bml.expire.btn.sessiononly=Cambia modalita' di scadenza a SOLO SESSIONE + +/login.bml.expire.neverexpire.text=Il tuo login non scadra' mai, quindi se sei ad un terminale internet publico, a scuola, in biblioteca, o in qualsiasi altro posto dove altre persone potrebbero usare questo computer tra breve tempo, assicurati di uscire dal tuo account quando hai finito! Oppure, cambia la modalita' di scadenza a "solo sessione" + +/login.bml.expire.sessiononly.text|staleness=1 +/login.bml.expire.sessiononly.text=Il tuo login scadra' quando chiuderai il tuo browser. Se questo e' il tuo computer personale e sei l'unico che lo usa, potresti voler cambiare la modalita' di scadenza a "mai" + +/login.bml.links.link1=La tua pagina amici. + +/login.bml.links.link2=La tua lista di cose da fare + +/login.bml.links.text=In futuro questa pagina conterra' ogni tipo di link e informazione rilevante, ma per ora ci sono un paio di posti dove potresti voler andare: + +/login.bml.loggedin.head=Entrato nell'Account! + +/login.bml.loggedin.text=Ora sei nel tuo account. + +/login.bml.login.expiration=Scadenza: + +/login.bml.login.forget=Dimenticato? + +/login.bml.login.never=Mai + +/login.bml.login.otheropts=Altre Opzioni: + +/login.bml.login.text1=Per fare il login in [[sitename]], inserisci il tuo username e la password. Per i Nuovi Utenti: Per creare un account andate qui. + +/login.bml.login.text2|staleness=1 +/login.bml.login.text2=Puoi anche specificare quando scade il tuo login. Di default scade quando chiudi il tuo browser, che e' l'opzione migliore per computer publici. Ad ogni modo, se sei l'unico utente del tuo computer e nessun altro ha accesso, puoi scegliere di non far scadere mai il login. + +/login.bml.login.whenbrowsercloses=Quando il browser viene chiuso + +/login.bml.whylogin.benefit1=Non dovrai inserire di nuovo username e password in nessun altro posto di questo sito. + +/login.bml.whylogin.benefit2=Ti sara' possibile vedere entries "protette" dei tuoi amici che ti hanno dato il permesso di accedervi. + +/login.bml.whylogin.benefit3=Molte funzioni sono visibili o accessibili solo dopo che sei entrato nel tuo account. + +/login.bml.whylogin.head=Perche' fare il Login? + +/login.bml.whylogin.text=Ecco alcuni dei vantaggi principali di entrare nel proprio account: + +/logout.bml.already.head=Gia' uscito dall'account + +/logout.bml.already.text=Sei gia' uscito dall'account + +/logout.bml.loggedout.head=Uscito dall'account + +/logout.bml.loggedout.text=Ora sei fuori dall'account. + +/logout.bml.title=Esci dall'account + +/lostinfo.bml.btn.proceed=Procedi + +/lostinfo.bml.enter_email=Inserisci il tuo indirizzo email: + +/lostinfo.bml.enter_email_optional=Indirizzo Email: (opzionale) + +/lostinfo.bml.enter_username=Inserisci il tuo username: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Se hai perso la password, inserisci il tuo usernale e l'indirizzo email al quale vuoi che la password venga spedita. Nota che l'indirizzo email deve essere uno che hai gia' usato su LiveJournal, ed hai gia' confermato in passato. Se lasci vuoto il campo dell'email, la password sara' spedita al tuo indirizzo attuale. + +/lostinfo.bml.lostpassword.title|staleness=1 +/lostinfo.bml.lostpassword.title=Hai perso la password? + +/lostinfo.bml.lostusername.text=Se hai perso il tuo username, inserisci il tuo indirizzo email e te lo spediremo via email. + +/lostinfo.bml.lostusername.title|staleness=1 +/lostinfo.bml.lostusername.title=Hai perso l'username? + +/lostinfo.bml.title=Informazioni Perse + +/lostinfo_do.bml.error.no_usernames_for_email=Nessun username per questo indirizzo email: [[address]]. + +/lostinfo_do.bml.error1.text=Non hai mai usato questo indirizzo email con questo account o non l'hai mai confermato. + +/lostinfo_do.bml.password_mailed.text=Successo. La tua password e' stata inviata. + +/lostinfo_do.bml.password_mailed.title=Password inviata! + +/lostinfo_do.bml.title=Informazioni Perse + +/lostinfo_do.bml.username_mailed.text=Successo. Il tuo username e' stato inviato. + +/lostinfo_do.bml.username_mailed.title=Username inviato! + +/modify.bml.title=Modifica Journal + +/modify_do.bml.availablestyles.head=Stili Disponibili + +/modify_do.bml.availablestyles.userstyles=Stili Utente: + +/modify_do.bml.colortheme.about|staleness=2 +/modify_do.bml.colortheme.about=Qui puoi scegliere quale set di colori applicare alle opzioni di layout che hai scelto sopra. Oppure, se non ti piacciono i colori disponibili, crea i tuoi colori personali! Se te ne esci con qualcosa di davvero sexy, faccelo sapere e daremo il tuo nome al set. + +/modify_do.bml.colortheme.area.head=Area Utilizzo + +/modify_do.bml.colortheme.color.head1=Colore + +/modify_do.bml.colortheme.color.head2=(#rrggbb oppure nome) + +/modify_do.bml.colortheme.customcolors=Colori Personalizzati + +/modify_do.bml.colortheme.defaulttheme=Set Standard + +/modify_do.bml.colortheme.head=Set di Colori + +/modify_do.bml.domainalias.about=Se hai gia' un dominio registrato (o che stai pensando di registrare) e ti piacerebbe che caricasse direttamente il tuo LiveJournal, inseriscilo qui: + +/modify_do.bml.domainalias.domainname=Nome dominio: + +/modify_do.bml.domainalias.example=Esempio: mio-journal.com + +/modify_do.bml.domainalias.head=Aliasing Dominio + +/modify_do.bml.domainalias.helptext|staleness=1 +/modify_do.bml.domainalias.helptext=Per fare questo dovrai far puntare il DNS del tuo dominio allo stesso indirizzo IP di [[sitename]]. + +/modify_do.bml.done.btn.savechanges=Salva Modifiche + +/modify_do.bml.done.head=Fatto? + +/modify_do.bml.done.text=Quando hai fatto, premi il bottone "Salva Modifiche" qui sotto... + +/modify_do.bml.error.dupdomainalias=Un altro utente si e' gia' registrato per usare questo alias + +/modify_do.bml.error.stylenotavailable=Uno degli stili che hai scelto non e' disponibile. Questo potrebbe essere dovuto sia a qualcuno che ha cancellato lo stile, sia ad aver scelto uno stile al quale non hai accesso. + +/modify_do.bml.friends.about=Ecco le opzioni che controllano l'aspetto della tua pagina amici. + +/modify_do.bml.friends.head=Vista Amici + +/modify_do.bml.friends.opt.usesharedpic.about=Questa opzione decide quale immagine vedi sulla tua pagina amici quando un utente posta su una comunita' o su un journal condiviso. Se la selezioni, allora vedrai l'icona della comunita'. In caso contrario, vedrai l'icona della persona che ha postato il messaggio. + +/modify_do.bml.friends.opt.usesharedpic.head=Usa le immagini del giornale condiviso al posto dell'imagine dell'utente + +/modify_do.bml.journaloptions.about|staleness=2 +/modify_do.bml.journaloptions.about=Da qui puoi personalizzare l'aspetto delle pagine del tuo LiveJournal. Se sei davvero curioso di sapere come funziona il tutto, leggi le informazioni per gli sviluppatori. Altrimenti daremo per scontato che ti vanno bene le opzioni di base qui sotto. + +/modify_do.bml.journaloptions.head=Opzioni Journal + +/modify_do.bml.journalstatus.about=Se vuoi cancellare o recuperare il tuo journal, e' questo il posto dove farlo. Una volta che hai cancellato il journal hai 30 giorni per recuperarlo, nel caso dovessi cambiare idea. Dopo 30 giorni il journal sara' cancellato per sempre e non ci sara' piu' modo di recuperarlo. + +/modify_do.bml.journalstatus.head=Stato di Attivazione del Journal + +/modify_do.bml.journalstatus.select.activated=Attivato + +/modify_do.bml.journalstatus.select.deleted=Cancellato + +/modify_do.bml.journalstatus.select.head=Stato: + +/modify_do.bml.journalstatus.select.suspended=Sospeso + +/modify_do.bml.moodicons.about=Quando scrivi delle entries nel journal puoi anche specificare il tuo stato d'animo del momento. Diversi utenti hanno inviato vari set di icone che puoi usare per rappresentare lo stato d'animo. Altrimenti scegli "Nessuno" se non vuoi nessuna immagine vicino allo stato d'animo (o se non vuoi proprio usare questo campo) + +/modify_do.bml.moodicons.head=Icone Stato d'Animo + +/modify_do.bml.moodicons.opt.forcefriends.about=Imponi questo set per tutti gli amici sulla tua pagina amici + +/modify_do.bml.moodicons.personal=Set Personali: + +/modify_do.bml.moodicons.preview=anteprima + +/modify_do.bml.moodicons.select=Scegli il set di icone stato-d'animo: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Puoi tralasciare questa sezione. Questa serve a modificare cose molto specifiche dell'aspetto della tua pagina. Guarda la sezione sviluppatori per dettagli. Nota anche che gli ovverrides sono per cambiare solo una o due cose di uno stile. Se vuoi cambiare tutto devi creare il tuo stile + +/modify_do.bml.overrides.head=Overrides dello Stile + +/modify_do.bml.overrides.note|staleness=2 +/modify_do.bml.overrides.note=Nota che non si puo' usare l'ovveride su tutte le variabili di stile. Leggi la documentazione per ulteriori dettagli. + +/modify_do.bml.overrides.warning=NON E' QUI CHE SCRIVI IL TUO JOURNAL!! + +/modify_do.bml.pagelayoutstyle.about=Questa configurazione controlla il modo in cui il tuo journal viene rappresentato sullo schermo. + +/modify_do.bml.pagelayoutstyle.head=Stile della Pagina + +/modify_do.bml.pagelayoutstyle.warning=Il tuo tipo di account ti permette di scegliere solo tra un numero ristretto di stili default. + +/modify_do.bml.success.head=Successo + +/modify_do.bml.success.text=La configurazione del tuo journal e' stata aggiornata. Puoi vedere il tuo journal qui. + +/paidaccounts/index.bml.costs.header=Bene, quanto costa? + +/paidaccounts/index.bml.costs.rates=I prezzi sono i seguenti: + +/paidaccounts/index.bml.costs.rates.amount.header=Quantita' + +/paidaccounts/index.bml.costs.rates.inexpensive=Si riduce a poco piu' di 2$ al mese per l'abbonamento annuale. Difficilmente questo ti mandera' in rovina. L'unica seccatura sara' cacciare fuori il portafogli, trovare la carta di credito ed inserire le tue informazioni. + +/paidaccounts/index.bml.costs.rates.time.header=Tempo + +/paidaccounts/index.bml.features.header=Dunque, che funzione figa potro' usare? + diff --git a/ljcom/bin/upgrading/ja.dat b/ljcom/bin/upgrading/ja.dat new file mode 100644 index 0000000..db21a7e --- /dev/null +++ b/ljcom/bin/upgrading/ja.dat @@ -0,0 +1,1181 @@ +;; -*- coding: utf-8 -*- +/allpics.bml.current=ç¾åœ¨è¨­å®šã•ã‚Œã¦ã„るユーザーアイコン + +/allpics.bml.default=デフォールト + +/allpics.bml.error.noparam=ユーザーã®ãƒ‘ラメータã¯æ­£ã—ãã‚ã‚Šã¾ã›ã‚“。 + +/allpics.bml.keywords=キーワード + +/allpics.bml.nopics.text.other=アイコンãŒã‚¢ãƒƒãƒ—ロードã•ã‚Œã¦ã„ã¾ã›ã‚“。 + +/allpics.bml.nopics.title=ユーザーアイコンãªã— + +/allpics.bml.pics=[[user]]ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¢ã‚¤ã‚³ãƒ³ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚ + +/allpics.bml.title=ユーザーアイコン + +/changepassword.bml.error.mustenterusername=ユーザーåを入力ã—ã¦ãã ã•ã„。 + +/changepassword.bml.error.nonascii=パスワードã«ã¯ ASCII 文字 (英数字) 以外使用ã§ãã¾ã›ã‚“。ASCII 文字ã ã‘ã§ãƒ‘スワードを設定ã—ã¦ãã ã•ã„。 + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=ç¾åœ¨ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç¢ºèªã•ã‚Œã¦ã„ãªã„ãŸã‚ã€ãƒ‘スワードを変更ã§ãã¾ã›ã‚“。 + +/changepassword.bml.newpassword=æ–°ã—ã„パスワード: + +/changepassword.bml.newpasswordagain=æ–°ã—ã„パスワード (確èª): + +/changepassword.bml.oldpassword=ç¾åœ¨ã®ãƒ‘スワード: + +/changepassword.bml.success.text=パスワードãŒå¤‰æ›´ã•ã‚Œã€ç¢ºèªã‚’通知ã™ã‚‹ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ + +/changepassword.bml.title=パスワードã®å¤‰æ›´ + +/community/index.bml.title=コミュニティ センター + +/community/join.bml.button.join=コミュニティã«åŠ å…¥ + +/community/join.bml.label.addtofriends=“[[maintainer]]â€ã‚’コミュニティーã®å‹é”ã¨ã—ã¦è¨­å®šã™ã‚‹ã€‚
          + +/community/join.bml.label.allowposting=ã“ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã§ã¯ã€ã™ã¹ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ãŒè¨˜äº‹ã‚’投稿ã§ãã¾ã™ã€‚LiveJournal 書ãè¾¼ã¿/編集用ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆ プログラムãŒé–‹ã„ã¦ã„ã‚‹å ´åˆã€ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ãªãŠã™ã¨ã€æŠ•ç¨¿å…ˆã®æ—¥è¨˜ã¨ã—ã¦ã“ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®åå‰ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/community/join.bml.label.banned=コミュニティーã®ç®¡ç†äººã«ã‚ˆã£ã¦ã€åŠ å…¥ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚ + +/community/join.bml.label.commlogged=ãŸã ä»Šã€å€‹äººã˜ã‚ƒãªãã¦ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¨ã—ã¦ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã¾ã™ã€‚ + +/community/join.bml.label.errorcomminfo=指定ã•ã‚ŒãŸã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®æƒ…å ±ã¯ç„¡åŠ¹ã§ã™ã€‚ + +/community/join.bml.label.expls=下ã®ãƒœã‚¿ãƒ³ã‚’クリックã—ãŸã‚‰ã€Œ[[maintainer]]ã€ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã«å…¥ã‚Šã¾ã™ã€‚コミュニティーを自分ã®å‹é”ã¨ã—ã¦è¨­å®šã—ãªã„ã§å…¥ã‚‹å ´åˆã€ä¸‹ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ãŒé¸æŠžã—ã¦ã„ãªã„よã†ã«ã—ã¦ä¸‹ã•ã„。 + +/community/join.bml.label.loginfirst=コミュニティーã«å…¥ã‚‹å‰ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。 + +/community/join.bml.label.membernow=今ã¯ã€Œ[[commname]]ã€ã¨ã„ã†ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚ + +/community/join.bml.label.sure=確ã‹ã‚ã¦ãã ã•ã„ + +/community/join.bml.success=加入ã®å®Œäº† + +/community/join.bml.title=コミュニティã«åŠ å…¥ã™ã‚‹ + +/community/leave.bml.button.leave=コミュニティを辞ã‚ã‚‹ + +/community/leave.bml.label.buttontoleave=下ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚Œã°ã€ã€Œ[[commname]]ã€ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã‚’去りã¾ã™ã€‚ + +/community/leave.bml.label.infoerror=指定ã•ã‚ŒãŸã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®æƒ…å ±ã¯ç„¡åŠ¹ã§ã™ã€‚ + +/community/leave.bml.label.logoutfirst=コミュニティーを去る時ã«ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ãªãã¦ã¯ã„ã‘ã¾ã›ã‚“。 + +/community/leave.bml.label.removed=今ã¯ã€[[commname]]ã¨ã„ã†ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã¯ãªããªã‚Šã¾ã—ãŸã€‚ + +/community/leave.bml.success=完了 + +/community/leave.bml.sure=確ã‹ã‚ã¦ä¸‹ã•ã„ + +/community/leave.bml.title=コミュニティを辞ã‚ã‚‹ + +/community/manage.bml.commlist.actmembers=[メンãƒãƒ¼] + +/community/manage.bml.commlist.actsettings=[設定] + +/community/manage.bml.commlist.header=管ç†ã—ã¦ã„るコミュニティー + +/community/manage.bml.commlist.none=管ç†ã—ã¦ã„るコミュニティーã¯ã‚ã‚Šã¾ã›ã‚“。 + +/community/manage.bml.commlist.text=管ç†ã¾ãŸã¯å…±åŒç®¡ç†ã—ã¦ã„るコミュニティーã®ãƒªã‚¹ãƒˆã§ã™ã€‚ + +/community/manage.bml.commlist.title=タイトル + +/community/manage.bml.commlist.username=ユーザーå + +/community/manage.bml.create.header=コミュニティーã®ä½œæˆ + +/community/manage.bml.create.text=コミュニティーを新ã—ã作æˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ + +/community/manage.bml.title=ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ç®¡ç† + +/community/members.bml.error.nocomm=コミュニティーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + +/community/members.bml.key.admin=管ç†äºº + +/community/members.bml.key.member=メンãƒãƒ¼ + +/community/members.bml.success.header=完了 + +/community/search.bml.button.clear=リセット + +/community/search.bml.button.search=検索開始! + +/community/search.bml.checkbox.onlywithpics=アイコンã®ãªã„コミュニティーã¯æ¤œç´¢ã—ãªã„ + +/community/search.bml.label.byinterest=興味 + +/community/search.bml.label.bylocation=本拠地 + +/community/search.bml.label.bytime=日記ã®æ›´æ–°æ—¥æ™‚ + +/community/search.bml.label.city=市町æ‘: + +/community/search.bml.label.country=国: + +/community/search.bml.label.displayoptions=表示オプション + +/community/search.bml.label.hasmember=メンãƒãƒ¼ + +/community/search.bml.label.othercriteria=ãã®ä»– + +/community/search.bml.label.outputformat=çµæžœã®è¡¨ç¤ºæ–¹æ³•: + +/community/search.bml.label.records=ページã‚ãŸã‚Šã®è¡¨ç¤ºä»¶æ•°: + +/community/search.bml.label.searchcomm=コミュニティーã®æ¤œç´¢ + +/community/search.bml.label.selecriteria=コミュニティーを検索ã™ã‚‹ãŸã‚ã®æ¡ä»¶ã‚’指定ã—ã¦ãã ã•ã„。指定ã•ã‚ŒãŸæ¡ä»¶ã®å…¨ã¦ã«åˆã†ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/community/search.bml.label.sortmethod=çµæžœã®è¡¨ç¤ºé †åº: + +/community/search.bml.label.stateprovince=å·žã€çœŒã€åœ°æ–¹: + +/community/search.bml.label.updated=最終更新日時 + +/community/search.bml.sel.bypicture=ユーザーアイコン + +/community/search.bml.sel.communityname=コミュニティーå + +/community/search.bml.sel.commview=コミュニティー ページ + +/community/search.bml.sel.day=24 時間以内 + +/community/search.bml.sel.month=1 ヶ月以内 + +/community/search.bml.sel.simple=ç°¡å˜ + +/community/search.bml.sel.updatetime=更新日時 + +/community/search.bml.sel.username=ユーザーå + +/community/search.bml.sel.week=1 週間以内 + +/community/search.bml.title=コミュニティーã®æ¤œç´¢ + +/community/settings.bml.label.commheader=コミュニティーã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ + +/community/settings.bml.label.username=ユーザーå: + +/community/settings.bml.success=æ›´æ–°ã®å®Œäº† + +/create.bml.age.check.question=13歳以下ã§ã™ã‹ï¼Ÿ + +/create.bml.age.check.yes=ã¯ã„ã€ã¾ã ï¼‘3歳ã«ãªã£ã¦ã„ãªã„。 + +/create.bml.age.head=å¹´é½¢ + +/create.bml.btn.proceed=次ã¸... + +/create.bml.clusterselect.cluster=クラスタ + +/create.bml.name.head=å称 + +/create.bml.name.input.head=å称 + +/create.bml.password.head=パスワード + +/create.bml.password.input.head1=パスワード + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=パスワードを書ãç›´ã—ã¦ä¸‹ã•ã„ + +/create.bml.password.text=パスワードをé¸ã‚“ã§ä¸‹ã•ã„ + +/create.bml.proceed.btn.proceed=次ã¸... + +/create.bml.success.head=作æˆã®å®Œäº† + +/doc/tour/index.bml.create.title=アカウントã®ä½œæˆ + +/editinfo.bml.allowshowcontact.about=メール アドレスã€ICQ番å·ã€AOL IM ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åãŒãƒ—ロフィールã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/editinfo.bml.allowshowcontact.email=連絡先ã¨ã—ã¦è¡¨ç¤ºã™ã‚‹ãƒ¡ãƒ¼ãƒ« アドレス: + +/editinfo.bml.allowshowcontact.email.actual_only=実際ã®ãƒ¡ãƒ¼ãƒ« アドレスã®ã¿è¡¨ç¤ºã™ã‚‹ + +/editinfo.bml.allowshowcontact.email.both=実際ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ [[domain]] ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’両方表示ã™ã‚‹ + +/editinfo.bml.allowshowcontact.email.lj_only=LiveJournal ã®ãƒ¡ãƒ¼ãƒ« アドレスã®ã¿è¡¨ç¤ºã™ã‚‹ + +/editinfo.bml.allowshowcontact.email.neither=ã„ãšã‚Œã‚‚表示ã—ãªã„ + +/editinfo.bml.allowshowcontact.email.no_show=メール アドレスを表示ã—ãªã„ + +/editinfo.bml.allowshowcontact.email.show=メール アドレスを表示ã™ã‚‹ + +/editinfo.bml.allowshowcontact.title=連絡先を表示ã™ã‚‹ + +/editinfo.bml.allowshowinfo.about=ä½æ‰€ (国ã€çœŒã€å¸‚町æ‘) ã¨ç”Ÿå¹´æœˆæ—¥ãŒãƒ—ロフィールã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/editinfo.bml.allowshowinfo.title=地域ã¨ç”Ÿå¹´æœˆæ—¥ã‚’表示ã™ã‚‹ + +/editinfo.bml.autotranslate.about<< +LiveJournal ã® Unicode 化以å‰ã«æŠ•ç¨¿ã•ã‚ŒãŸè¨˜äº‹ã‚„コメントã«é©ç”¨ã•ã‚Œã‚‹ã€ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã®ç¨®é¡žã‚’指定ã—ã¾ã™ã€‚
          +英語ã§æ›¸ã‹ã‚Œã¦ã„ã‚‹å ´åˆã€ã€ŒWestern Europeanã€ã‚’é¸æŠžã—ã¦ãã ã•ã„。 +. + +/editinfo.bml.bday.title=生年月日 + +/editinfo.bml.bday.year.opt=å¹´ã®å…¥åŠ›ã¯å¿…è¦ã§ã¯ã‚ã‚Šã¾ã›ã‚“ + +/editinfo.bml.bdayreminders.about=LiveJournal ã®å‹é”ã®èª•ç”Ÿæ—¥ã‚’通知ã™ã‚‹ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã•ã‚Œã¾ã™ã€‚ + +/editinfo.bml.bdayreminders.header=誕生日ã®é€šçŸ¥ã‚’å—ã‘å–ã‚‹ + +/editinfo.bml.bio.about=自己紹介ã®æ–‡ã‚’入力ã—ã¦ãã ã•ã„。入力ã•ã‚ŒãŸå†…容ã¯ã€ãƒ—ロフィールã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/editinfo.bml.bio.header=自己紹介 + +/editinfo.bml.blockrobots.about=検索エンジンã®ãƒ­ãƒœãƒƒãƒˆã®å·¡å›žã‚’防ãŽã¾ã™ã€‚ã“ã®é˜²æ­¢ç­–ãŒæœ‰åŠ¹ã§ãªã„ロボットもã‚ã‚Šã¾ã™ã€‚ + +/editinfo.bml.blockrobots.header=検索エンジンã®ã‚¯ãƒ­ãƒ¼ãƒ©ãƒ¼/ロボット/スパイダーã«ã‚ˆã‚‹ã€è¨˜äº‹ã®ç´¢å¼•åŒ–を防止ã™ã‚‹ + +/editinfo.bml.city.title=åŒºå¸‚ç”ºæ‘ + +/editinfo.bml.country.choose=国をé¸æŠž + +/editinfo.bml.country.title=国 + +/editinfo.bml.donotlog=ã—ãªã„ + +/editinfo.bml.email.title=メール アドレス + +/editinfo.bml.enableboards.about=記事ã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆæŠ•ç¨¿ã‚’許å¯ã—ã¾ã™ã€‚ + +/editinfo.bml.enableboards.header=コメント + +/editinfo.bml.encoding.header=エンコードã®è¨­å®š + +/editinfo.bml.error.excessive_int=入力ã—ãŸèˆˆå‘³ã¯å¤šã™ãŽã¾ã™ã€‚最多é™ç•Œã¯150ã ã‘ã©ã€[[intcount]]を入力ã—ã¾ã—ãŸã€‚ã§ã™ã‹ã‚‰ã€èˆˆå‘³ã®å¤‰æ›´ã¯è¨˜æ†¶ã•ã‚Œã¦ã„ã¾ã›ã‚“。150以下ã®èˆˆå‘³ã«ã—ã¦ã€å¤‰æ›´ã‚’ã—ç›´ã—ã¦ä¸‹ã•ã„。 + +/editinfo.bml.error.locale.country_ne_state=「国ã€æ¬„ã§ã¯ã‚¢ãƒ¡ãƒªã‚« ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ãŒã€ã‚¢ãƒ¡ãƒªã‚«ã«ãªã„å·ž (県) ã®åå‰ãŒå…¥åŠ›ã•ã‚Œã¦ã„ã¾ã™ã€‚ + +/editinfo.bml.error.locale.invalid_country=無効ãªå›½ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚ + +/editinfo.bml.error.locale.state_ne_country=「国ã€æ¬„ã§ã¯ã‚¢ãƒ¡ãƒªã‚«ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒã€ã‚¢ãƒ¡ãƒªã‚«ã®å·žãŒæŒ‡å®šã•ã‚Œã¾ã—ãŸã€‚ + +/editinfo.bml.error.locale.zip_ne_state=郵便番å·ãŒã€æŒ‡å®šã•ã‚ŒãŸçœŒ/å·žã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。
          æ­£ã—ã„情報をå†å…¥åŠ›ã™ã‚‹ã‹ã€ä¸å¿…è¦ãªæƒ…報を削除ã—ã¦ãã ã•ã„。 + +/editinfo.bml.finished.about=オプション設定ãŒå®Œäº†ã—ãŸã‚‰ã€ä¸‹ã®ã€Œé©ç”¨ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。 + +/editinfo.bml.finished.header=完了 + +/editinfo.bml.finished.save_button=é©ç”¨ + +/editinfo.bml.gender.title=性 + +/editinfo.bml.int.header=興味 + +/editinfo.bml.login.enterinfo=ユーザーåã¨ãƒ‘スワードを入力ã—ã¦ãã ã•ã„。 + +/editinfo.bml.login.forgot.header=ログイン情報ã®å…¥æ‰‹ + +/editinfo.bml.login.forgot.recover=ユーザーåã¾ãŸã¯ãƒ‘スワードを忘れãŸå ´åˆã€ã“ã“をクリックã—ã¦ãã ã•ã„。 + +/editinfo.bml.logip.always=å¿…ãšã™ã‚‹ + +/editinfo.bml.logip.anon_only=匿åã®æŠ•ç¨¿ã®ã¿ + +/editinfo.bml.logip.header=コメントã®é€ä¿¡å…ƒã® IP アドレスを記録ã—ã¾ã™ã‹? + +/editinfo.bml.name.title=æ°å + +/editinfo.bml.optional=オプション + +/editinfo.bml.opt_in.header=LiveJournal ã®ãƒ‹ãƒ¥ãƒ¼ã‚¹ã‚’å—ã‘å–ã‚‹ + +/editinfo.bml.persinfo.disclaimer=ã‚ãªãŸã«ã¤ã„ã¦ç°¡å˜ã«æ•™ãˆã¦ãã ã•ã„。ã“ã®æƒ…å ±ã¯ã€LiveJournal ユーザーã«é–¢ã—ã¦ã‚ˆã‚Šè‰¯ã„ç†è§£ã‚’å¾—ã‚‹ãŸã‚ã«é›†è¨ˆã•ã‚Œã¾ã™ã€‚正確ãªæƒ…報を入力ã™ã‚‹ã‚ˆã†ã«ã—ã¦ãã ã•ã„。当サイトã«ã‚ˆã‚‹å€‹äººæƒ…å ±ã®å–り扱ã„ã«ã¤ã„ã¦ã¯ã€ã“ã¡ã‚‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 + +/editinfo.bml.persinfo.header=ユーザー情報 + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=セキュリティー + +/editinfo.bml.security.visibility.anybody=制é™ãªã— + +/editinfo.bml.security.visibility.friends=å‹é”ã®ã¿ + +/editinfo.bml.security.visibility.regusers=登録済ã¿ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿ + +/editinfo.bml.settings.header=LiveJournal オプション + +/editinfo.bml.state.other=ãã®ä»–ã®å·ž/県/地方/領土 + +/editinfo.bml.state.title=å·ž/県 + +/editinfo.bml.state.us=アメリカåˆè¡†å›½ã®å·ž + +/editinfo.bml.success.header=æ›´æ–°ã®å®Œäº† + +/editinfo.bml.success.message=ユーザー情報ã€æ—¥è¨˜ã®è¨­å®šã€ãŠã‚ˆã³ãƒ—ロフィールãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚ + +/editinfo.bml.switch.button=切り替㈠+ +/editinfo.bml.switch.header=日記ã®åˆ‡ã‚Šæ›¿ãˆ + +/editinfo.bml.title=アカウントã¨ãƒ—ロフィールã®è¨­å®š + +/editinfo.bml.tm.phonenum=é›»è©±ç•ªå· + +/editinfo.bml.whoreply.header=コメントを許å¯ã™ã‚‹å¯¾è±¡ã‚’制é™ã—ã¾ã™ã‹ï¼Ÿ + +/editinfo.bml.zip.title=éƒµä¾¿ç•ªå· + +/editinfo.bml.zip.usonly=5æ¡ã®éƒµä¾¿ç•ªå· - アメリカåˆè¡†å›½ä½æ°‘ã®ã¿ + +/editjournal.bml.btn.proceed=次ã¸... + +/editjournal.bml.certainday=日付ã®æŒ‡å®š + +/editjournal.bml.recententries=ã¤ã¾ã§ã®æœ€è¿‘ã®è¨˜äº‹ + +/editjournal.bml.recententry=最も新ã—ã„記事 + +/editjournal.bml.title=éŽåŽ»ã®è¨˜äº‹ã®ç·¨é›† + +/editjournal.bml.viewwhat=編集ã®å¯¾è±¡: + +/editjournal_do.bml.date=年月日 + +/editjournal_do.bml.default=デイファルト + +/editjournal_do.bml.event=エベント + +/editjournal_do.bml.success.head=完了 + +/friends/add.bml.add.header=追加ã®å®Œäº† + +/friends/add.bml.colors.bg=背景 + +/friends/add.bml.colors.fg=å‰é¢ + +/friends/add.bml.colors.header=色 + +/friends/add.bml.remove.header=削除ã®å®Œäº† + +/friends/edit.bml.title=å‹é”ã®è¨­å®š + +/friends/edit_do.bml.addfriends.head=å‹é”ã®è¿½åŠ  + +/friends/edit_do.bml.addfriends.text=追加ã™ã‚‹ãƒ¡ãƒ³ãƒãƒ¼ã® LiveJournal ユーザーåを入力ã—ã¾ã™ã€‚å„ユーザーã«å¯¾ã—ã¦èƒŒæ™¯ã¨æ–‡å­—ã®è‰²ã‚’設定ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ + +/friends/edit_do.bml.background=背景ã®è‰² + +/friends/edit_do.bml.bgcolor=背景ã®è‰²: + +/friends/edit_do.bml.btn.close=é–‰ã˜ã‚‹ + +/friends/edit_do.bml.btn.save=変更ã®é©ç”¨ + +/friends/edit_do.bml.btn.toggle=プレビュー ウィンドウã®è¡¨ç¤º + +/friends/edit_do.bml.done.head=完了 + +/friends/edit_do.bml.done.text=設定ãŒå®Œäº†ã—ãŸã‚‰ã€ä¸‹ã®ã€Œå¤‰æ›´ã®é©ç”¨ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。 + +/friends/edit_do.bml.error.updating=å‹é”リストを更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ + +/friends/edit_do.bml.foreground=文字ã®è‰² + +/friends/edit_do.bml.friend=å‹é” + +/friends/edit_do.bml.hover=色ã®ä¸Šã«ãƒžã‚¦ã‚¹ ãƒã‚¤ãƒ³ã‚¿ã‚’移動ã™ã‚‹ã¨ã€è‰²ã®åå‰ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ + +/friends/edit_do.bml.mrcolor=色ã®ãƒ—レビュー + +/friends/edit_do.bml.name=æ°å + +/friends/edit_do.bml.needmore=入力欄ãŒè¿½åŠ ã™ã‚‹å‹é”ã®æ•°ã‚ˆã‚Šå°‘ãªã„å ´åˆã€å¤‰æ›´ã‚’é©ç”¨ã—ã¦ã‹ã‚‰ã“ã®ãƒšãƒ¼ã‚¸ã‚’å†ã³è¡¨ç¤ºã—ã¦ã€å‹é”ã®è¿½åŠ ã‚’続ã‘ã¦ãã ã•ã„。 + +/friends/edit_do.bml.nofriends.head=å‹é”ãªã— + +/friends/edit_do.bml.nofriends.text=å‹é”ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。å‹é”を作ã£ã¦ã€ä¸‹ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼åを入力ã—ã¦ãã ã•ã„。 :) + +/friends/edit_do.bml.opt.delete=削除 + +/friends/edit_do.bml.success.head=完了 + +/friends/edit_do.bml.success.text|staleness=1 +/friends/edit_do.bml.success.text=å‹é”リストãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚ã“ã“をクリックã—ã¦ç¢ºèªã—ã¦ãã ã•ã„。 + +/friends/edit_do.bml.textcolor=文字ã®è‰²: + +/friends/edit_do.bml.title=å‹é”ã®è¨­å®š + +/friends/edit_do.bml.user=ユーザー + +/friends/edit_do.bml.viewer=色ã®ãƒ—レビュー + +/friends/edit_do.bml.yourfriends.head=ç¾åœ¨ã®å‹é”リスト + +/friends/edit_do.bml.yourfriends.text=以下ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå‹é”ã¨ã—ã¦æŒ‡å®šã•ã‚Œã¦ã„ã¾ã™ã€‚ + +/friends/index.bml.title=å‹é”ツール + +/index.bml.boldcreate=LiveJournal ã§æ—¥è¨˜ã‚’作ã‚ã†ï¼ + +/index.bml.frank.image.alt=LiveJournal ã®ãƒžã‚¹ã‚³ãƒƒãƒˆã€å±±ç¾Šã® Frank ã§ã™ + +/index.bml.frank.logo=Frank ã¯ãƒ¡ãƒ¼ã¨é³´ã + +/index.bml.meta.desc=LiveJournal.com ã¯ä¸–界中ã®äººã€…ã¨æ„見を交æ›ã§ãã‚‹å ´ã§ã™ã€‚ + +/index.bml.meta.keywords=日記, 日誌, ジャーナル, ダイアリー, 日記サイト, journal, online journal, diaries, writing, online diary, web diary + +/interests.bml.add.added.head=追加ã®å®Œäº† + +/interests.bml.add.added.text=æ–°ã—ã„é …ç›®ãŒèˆˆå‘³ã¨ã—ã¦è¿½åŠ ã•ã‚Œã¾ã—ãŸã€‚ + +/interests.bml.add.toomany.head=ã™ã¿ã¾ã›ã‚“ + +/interests.bml.communities.head=関係ã‚るコミュニティー + +/interests.bml.count=ç·æ•° + +/interests.bml.interests.head=興味 + +/interests.bml.title=興味 + +/login.bml.login.otheropts=ä»–ã®ã‚ªãƒ—ション + +/login.bml.login.password=パスワード + +/login.bml.login.username=ユーザーå: + +/login.bml.title=ログイン + +/lostinfo.bml.btn.proceed=次ã¸... + +/lostinfo.bml.enter_username=ユーザーå: + +/lostinfo.bml.lostpassword.title=パスワードを忘れãŸå ´åˆ + +/lostinfo.bml.lostusername.text=ユーザーåãŒã‚ã‹ã‚‰ãªã„å ´åˆã€ç™»éŒ²ã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ« アドレスを入力ã—ã¦ãã ã•ã„。ユーザーåãŒé€ä¿¡ã•ã‚Œã¾ã™ã€‚ + +/lostinfo.bml.lostusername.title=ユーザーåを忘れãŸå ´åˆ + +/lostinfo.bml.title=ログイン情報ã®å…¥æ‰‹ + +/lostinfo_do.bml.password_mailed.text=パスワードãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ + +/lostinfo_do.bml.title=ログイン情報ã®å…¥æ‰‹ + +/lostinfo_do.bml.username_mailed.text=ユーザーåãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ + +/modify_do.bml.journalstatus.select.deleted=削除ã•ã‚ŒãŸ + +/modify_do.bml.journalstatus.select.suspended=åœæ­¢å‡¦åˆ† + +/modify_do.bml.success.head=完了 + +/paidaccounts/index.bml.costs.header=費用ã¯ã„ãらã§ã™ã‹? + +/paidaccounts/index.bml.costs.rates.amount.header=åˆè¨ˆ + +/paidaccounts/index.bml.costs.rates.time.header=時間 + +/paidaccounts/index.bml.title=有料アカウントã«ã¤ã„㦠+ +/support/faqbrowse.bml.backfaq=FAQ ã®ç›®æ¬¡ã«æˆ»ã‚‹ + +/support/faqbrowse.bml.backsupport=サãƒãƒ¼ãƒˆã«æˆ»ã‚‹ + +/support/faqbrowse.bml.lastupdated=最終更新日時 : + +/talkpost.bml.allowedhtml=使用ã§ãã‚‹ HTML コード + +/talkpost.bml.error.cannotreplynopost=存在ã—ãªã„記事ã«ã¯ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã›ã‚“。 + +/talkpost.bml.error.nocommentsjournal=ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æ—¥è¨˜ã§ã¯ã€ã‚³ãƒ¡ãƒ³ãƒˆãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。 + +/talkpost.bml.error.nocommentspost=ã“ã®è¨˜äº‹ã§ã¯ã€ã‚³ãƒ¡ãƒ³ãƒˆãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。 + +/talkpost.bml.error.noreplypost=返信コメントãŒã‚ã‚Šã¾ã›ã‚“。削除ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ + +/talkpost.bml.label.picturetouse=使用ã™ã‚‹ã‚¢ã‚¤ã‚³ãƒ³: + +/talkpost.bml.loganonip=注æ„: 匿åã«ã‚ˆã‚‹ã‚³ãƒ¡ãƒ³ãƒˆã¯ã€é€ä¿¡å…ƒã® IP アドレスãŒè¨˜éŒ²ã•ã‚Œã¾ã™ã€‚ + +/talkpost.bml.loginq=ログインã—ã¾ã™ã‹? + +/talkpost.bml.logyourip=注æ„: ã™ã¹ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã®é€ä¿¡å…ƒã® IP アドレスãŒè¨˜éŒ²ã•ã‚Œã¾ã™ã€‚ + +/talkpost.bml.nosubjecthtml=ã“ã®æ¬„ã§ã¯ã€HTML コードãŒä½¿ç”¨ã§ãã¾ã›ã‚“。 + +/talkpost.bml.opt.anonymous=匿å + +/talkpost.bml.opt.defpic=(デフォルト) + +/talkpost.bml.opt.friendsonly=ã“ã®æ—¥è¨˜ã«ã¯ã€[[username]] ã®å‹é”ã®ã¿ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚ + +/talkpost.bml.opt.from=é€ä¿¡è€…: + +/talkpost.bml.opt.ljuser=LiveJournal メンãƒãƒ¼ + +/talkpost.bml.opt.loggedin=ログインã—ã¦ã„るユーザー: [[username]] + +/talkpost.bml.opt.message=コメント: + +/talkpost.bml.opt.noanonpost=ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯åŒ¿åã«ã‚ˆã‚‹ã‚³ãƒ¡ãƒ³ãƒˆã®æŠ•ç¨¿ã‚’許å¯ã—ã¦ã„ã¾ã›ã‚“。 + +/talkpost.bml.opt.noautoformat=自動HTMLフォーマットã—ãªã„ + +/talkpost.bml.opt.noimage=ç”»åƒãªã— + +/talkpost.bml.opt.preview=プレビュー + +/talkpost.bml.opt.spellcheck=é€ä¿¡ã™ã‚‹å‰ã«ã‚¹ãƒšãƒ«ãƒã‚§ãƒƒã‚¯ã‚’実行ã™ã‚‹ + +/talkpost.bml.opt.subject=タイトル: + +/talkpost.bml.opt.submit=コメントé€ä¿¡ + +/talkpost.bml.paraformat=デフォルト設定ã§ã¯ã€å…¥åŠ›ã•ã‚ŒãŸæ–‡ç« ã®æ›¸å¼ãŒè‡ªå‹•çš„ã«è¨­å®šã•ã‚Œã¾ã™ã€‚ + +/talkpost.bml.postresponse=コメントã®é€ä¿¡ + +/talkpost.bml.title=コメントã®é€ä¿¡ + +/talkpost_do.bml.error.badpassword=ä¸æ­£ãªãƒ‘スワードãŒå…¥åŠ›ã•ã‚Œã¾ã—ãŸã€‚パスワードを忘れãŸå ´åˆã€ã“ã“をクリックã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.error.badusername=指定ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼åã¯å­˜åœ¨ã—ã¾ã›ã‚“。ユーザーåãŒã‚ã‹ã‚‰ãªã„å ´åˆã€ã“ã“をクリックã—ã¦ãã ã•ã„。ã¾ãŸã€åŒ¿åã§ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ + +/talkpost_do.bml.error.banned=ã“ã®æ—¥è¨˜ã§ã¯ã€ã‚³ãƒ¡ãƒ³ãƒˆã‚’é€ä¿¡ã§ãã¾ã›ã‚“。 + +/talkpost_do.bml.error.blankmessage=何も入力ã•ã‚Œã¦ã„ã¾ã›ã‚“。「コメントã€æ¬„ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’書ã込んã§ãã ã•ã„。 + +/talkpost_do.bml.error.confused_identity=匿åユーザーã¨ã—ã¦ã€ã¾ãŸã¯ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„るユーザーã¨ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã™ã‚‹ã‚ªãƒ—ションãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ãŒã€æ–°ã—ãユーザーåãŒå…¥åŠ›ã•ã‚Œã¾ã—ãŸã€‚オプションをé¸æŠžã—ç›´ã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.error.deleted=日記ã¯å‰Šé™¤ã•ã‚ŒãŸã®ã§ã€æ›¸ãè¾¼ã‚ã¾ã›ã‚“。 + +/talkpost_do.bml.error.friendsonly=ã“ã®æ—¥è¨˜ã«ã¯ã€[[user]] ã®å‹é”ã®ã¿ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚ + +/talkpost_do.bml.error.lostcookie=å‰å›žã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’記録ã—㟠Cookie ãŒå‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™ã€‚ + +/talkpost_do.bml.error.manybytes=コメントã®ã‚µã‚¤ã‚º ([[current]] ) ã¯ã€ä¸Šé™ã® [[limit]] ãƒã‚¤ãƒˆã‚’超ãˆã¦ã„ã¾ã™ã€‚コメントを短ãã—ã€é€ä¿¡ã—ç›´ã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.error.manychars=コメントã®å­—æ•° ([[current]]) ã¯ã€ä¸Šé™ã® [[limit]] 字を超ãˆã¦ã„ã¾ã™ã€‚コメントを短ãã—ã€é€ä¿¡ã—ç›´ã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.error.mustlogin=アクセス制é™ã®ã‚る記事ã«ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã«ã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + +/talkpost_do.bml.error.noanon=ã“ã®æ—¥è¨˜ã«ã¯ã€åŒ¿åã®ã‚³ãƒ¡ãƒ³ãƒˆã¯é€ä¿¡ã§ãã¾ã›ã‚“。 + +/talkpost_do.bml.error.noauth=èªè¨¼ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿ãŒã€ã“ã®è¨˜äº‹ã«ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚ + +/talkpost_do.bml.error.nocomments=ã“ã®è¨˜äº‹ã§ã¯ã€ã‚³ãƒ¡ãƒ³ãƒˆãŒè¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。 + +/talkpost_do.bml.error.notafriend=[[user]] ã¯ã‚ãªãŸã‚’å‹é”ã¨ã—ã¦è¨­å®šã—ã¦ã„ã¾ã›ã‚“。ã“ã®æ—¥è¨˜ã«ã‚³ãƒ¡ãƒ³ãƒˆã‚’é€ä¿¡ã™ã‚‹ã«ã¯ã€[[user]] ã®å‹é”ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + +/talkpost_do.bml.error.nousername=LiveJournal ユーザーåãŒå…¥åŠ›ã•ã‚Œã¦ã„ã¾ã›ã‚“。LiveJournal アカウントãŒãªã„å ´åˆã€åŒ¿åユーザーã¨ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=メール アドレスã®ç¢ºèªãŒå®Œäº†ã™ã‚‹ã¾ã§ã€ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã§ãã¾ã›ã‚“。アドレス確èªã«å¿…è¦ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’ãªãã—ãŸå ´åˆã€ã€Œãƒ­ã‚°ã‚¤ãƒ³æƒ…å ±ã®å…¥æ‰‹ã€ãƒšãƒ¼ã‚¸ã§å†é€ä¿¡ã‚’リクエストã§ãã¾ã™ã€‚ + +/talkpost_do.bml.error.postshared=共有アカウントã€ã¾ãŸã¯ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„る状態ã§ã¯ã€ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã§ãã¾ã›ã‚“。ã“れらã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ã€å€‹äººãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã¯ãªãã€è¤‡æ•°ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’代表ã—ã¦ã„ã‚‹ãŸã‚ã§ã™ã€‚ + +/talkpost_do.bml.error.suspended=ã“ã®æ—¥è¨˜ã¯åœæ­¢å‡¦åˆ†ã•ã‚Œã¦ã„ã¾ã™ã€‚ç¾åœ¨ã‚³ãƒ¡ãƒ³ãƒˆã‚’投稿ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 + +/talkpost_do.bml.error.testacct=テスト用アカウントã¯ã€ãƒ†ã‚¹ãƒˆç”¨ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®æ—¥è¨˜ã§ã®ã¿ä½¿ç”¨ã§ãã¾ã™ã€‚ + +/talkpost_do.bml.opt.preview=プレビュー + +/talkpost_do.bml.preview=コメントã¯ã“ã®ã‚ˆã†ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚編集ã™ã‚‹å ´åˆã€ä¸‹ã®ãƒ•ã‚©ãƒ¼ãƒ ã‚’使ã£ã¦ãã ã•ã„。編集ã—ãªã„å ´åˆã¯ã€ã“ã®ã¾ã¾é€ä¿¡ã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.preview.subject=タイトル: + +/talkpost_do.bml.preview.submit=é€ä¿¡ + +/talkpost_do.bml.preview.title=プレビュー + +/talkpost_do.bml.success.loggedin=ログインã—ã¾ã—ãŸã€‚ + +/talkpost_do.bml.success.message=コメントãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ã“ã“ã§ç¢ºèªã—ã¦ãã ã•ã„。 + +/talkpost_do.bml.success.title=完了 + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=コメントã®é€ä¿¡ + +/talkread.bml.anonuser=(匿å) + +/talkread.bml.deletedpost=(削除ã•ã‚ŒãŸã‚³ãƒ¡ãƒ³ãƒˆï¼‰ + +/talkread.bml.fromip=(é€ä¿¡å…ƒ: [[ip]]) + +/talkread.bml.noreplies=返信ãªã— + +/talkread.bml.nosubject=(タイトルãªã—) + +/talkread.bml.replysuspended=(åœæ­¢å‡¦åˆ†ã•ã‚ŒãŸãƒ¡ãƒ³ãƒãƒ¼ã‹ã‚‰ã®è¿”信) + +/talkread.bml.subjectdeleted=<削除済ã¿ï¼ž + +/talkread.bml.title=コメントã®è¡¨ç¤º + +/talkscreen.bml.screened.title=完了 + +/talkscreen.bml.unscreened.title=完了 + +/tools/memadd.bml.body.added.header=完了 + +/tools/memadd.bml.description=説明: + +/tools/memadd.bml.form.reset=リセット + +/tools/memadd.bml.form.submit=ç¢ºèª + +/tools/memadd.bml.keywords=キーワード + +/tools/memadd.bml.login.forgot.header=ログイン情報ã®å…¥æ‰‹ + +/tools/memadd.bml.login.forgot.recover=ユーザーåã¾ãŸã¯ãƒ‘スワードを忘れãŸå ´åˆã€ã“ã“をクリックã—ã¦ãã ã•ã„。 + +/tools/memadd.bml.security.friendsonly=å‹é”ã ã‘ + +/tools/memadd.bml.security.private=プライベート + +/tools/memadd.bml.title=æ€ã„出ã«è¿½åŠ ã™ã‚‹ + +/tools/memadd.bml.title.added=加ãˆã¾ã—㟠+ +/tools/memadd.bml.title.deleted=デリートã—ã¾ã—㟠+ +/tools/memories.bml.back=戻る + +/tools/memories.bml.edit=編集ã™ã‚‹ + +/tools/memories.bml.form.switch=切り替㈠+ +/userinfo.bml.about.comm=紹介: + +/userinfo.bml.about.user=自己紹介: + +/userinfo.bml.comminfo.name=コミュニティー情報 + +/userinfo.bml.friendof.hidden=(éžè¡¨ç¤º) + +/userinfo.bml.friends.comm=メンãƒãƒ¼ + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=å‹é” + +/userinfo.bml.label.birthdate=生年月日: + +/userinfo.bml.label.clientsused=ダウンロードã—ãŸ
          クライアント: + +/userinfo.bml.label.comments=コメント: + +/userinfo.bml.label.composted=é€: [[num]] - + +/userinfo.bml.label.comreceived=å—: [[num]] + +/userinfo.bml.label.datecreated=作æˆæ—¥: + +/userinfo.bml.label.dateupdated=æ›´æ–°æ—¥: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=メール: + +/userinfo.bml.label.interests=興味 + +/userinfo.bml.label.journalentrs=記事ã®æ•°: + +/userinfo.bml.label.location=ä½æ‰€: + +/userinfo.bml.label.memberof=メンãƒãƒ¼ã§ã‚るコミュニティー + +/userinfo.bml.label.memories=æ€ã„出: + +/userinfo.bml.label.moredetails=(詳細表示...) + +/userinfo.bml.label.name=æ°å: + +/userinfo.bml.label.sendmessage=メッセージをé€ã‚‹ + +/userinfo.bml.label.textmessage=テキスト
          メッセージ
          + +/userinfo.bml.label.todo=To-Do リスト + +/userinfo.bml.label.user=ユーザーå: + +/userinfo.bml.label.viewfriends=å‹é”ã®è¡¨ç¤º + +/userinfo.bml.label.viewmembers=メンãƒãƒ¼ã®è¡¨ç¤º + +/userinfo.bml.label.website=ホームページ: + +/userinfo.bml.membership.body=ã“ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã«åŠ å…¥ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¦ãã ã•ã„。 + +/userinfo.bml.monitor.comm=コミュニティーを追加 + +/userinfo.bml.nonexist.body|staleness=1 +/userinfo.bml.nonexist.body=「[[user]]ã€ã¨ã„ã†ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯å­˜åœ¨ã—ã¾ã›ã‚“。 + +/userinfo.bml.nonexist.name=ä¸æ˜Žãªãƒ¦ãƒ¼ã‚¶ãƒ¼ + +/userinfo.bml.syn.parseerror=エラー メッセージ: + +/userinfo.bml.timeupdate.dayago=1 æ—¥å‰ + +/userinfo.bml.timeupdate.daysago=[[num]] æ—¥å‰ + +/userinfo.bml.timeupdate.hourago=1 æ™‚é–“å‰ + +/userinfo.bml.timeupdate.hoursago=[[num]] æ™‚é–“å‰ + +/userinfo.bml.timeupdate.minuteago=1 åˆ†å‰ + +/userinfo.bml.timeupdate.minutesago=[[num]] åˆ†å‰ + +/userinfo.bml.timeupdate.secondago=1 ç§’å‰ + +/userinfo.bml.timeupdate.secondsago=[[num]] ç§’å‰ + +/userinfo.bml.timeupdate.weekago=1 é€±é–“å‰ + +/userinfo.bml.timeupdate.weeksago=[[num]] é€±é–“å‰ + +/userinfo.bml.title=ユーザー プロフィール + +/userinfo.bml.title.communityinfo=コミュニティー プロフィール + +/userinfo.bml.userinfo.name=ユーザー情報 + +btn.search=検索 + +date.day.friday.long=金曜日 + +date.day.friday.short=金 + +date.day.monday.long=月曜日 + +date.day.monday.short=月 + +date.day.saturday.long=土曜日 + +date.day.saturday.short=土 + +date.day.sunday.long=日曜日 + +date.day.sunday.short=æ—¥ + +date.day.thursday.long=木曜日 + +date.day.thursday.short=木 + +date.day.tuesday.long=ç«æ›œæ—¥ + +date.day.tuesday.short=ç« + +date.day.wednesday.long=水曜日 + +date.day.wednesday.short=æ°´ + +date.month.april.long=四月 + +date.month.april.short=四月 + +date.month.august.long=八月 + +date.month.august.short=八月 + +date.month.december.long=å二月 + +date.month.december.short=å二月 + +date.month.february.long=二月 + +date.month.february.short=二月 + +date.month.january.long=一月 + +date.month.january.short=一月 + +date.month.july.long=七月 + +date.month.july.short=七月 + +date.month.june.long=六月 + +date.month.june.short=六月 + +date.month.march.long=三月 + +date.month.march.short=三月 + +date.month.may.long=五月 + +date.month.may.short=五月 + +date.month.november.long=å一月 + +date.month.november.short=å一月 + +date.month.october.long=å月 + +date.month.october.short=å月 + +date.month.september.long=ä¹æœˆ + +date.month.september.short=ä¹æœˆ + +dystopia.btn.login=ログイン + +dystopia.hello_anonymous=LiveJournal ã¸ã‚ˆã†ã“ãï¼ + +dystopia.hello_loggedin=ã“ã‚“ã«ã¡ã¯ã€[[username]] ã•ã‚“ï¼ + +dystopia.nav.createjournal=日記ã®æ–°è¦ä½œæˆ + +dystopia.nav.developer=デベロッパー エリア + +dystopia.nav.download=ダウンロード + +dystopia.nav.editentries=記事ã®ç·¨é›† + +dystopia.nav.editfriends=å‹é”ã®è¨­å®š + +dystopia.nav.editpassword=パスワードã®å¤‰æ›´ + +dystopia.nav.editpics=ユーザーアイコン + +dystopia.nav.editstyle=スタイルã®ç·¨é›† + +dystopia.nav.faq=よãã‚る質å•ï¼ˆï¼¦ï¼¡ï¼±ï¼‰ + +dystopia.nav.findcomm=コミュニティã«ã‚ˆã£ã¦ + +dystopia.nav.finddir=ディレクトリã‹ã‚‰ + +dystopia.nav.findint=興味ã«ã‚ˆã£ã¦ + +dystopia.nav.findrandom=ランダム + +dystopia.nav.findregion=地域ã«ã‚ˆã£ã¦ + +dystopia.nav.home=ホーム + +dystopia.nav.journalcalendar=カレンダー + +dystopia.nav.journalfriends=å‹é”ページ + +dystopia.nav.journalinfo=プロフィール + +dystopia.nav.journalrecent=最近ã®æ—¥è¨˜ + +dystopia.nav.legalprivacy=プライãƒã‚·ãƒ¼ã«ã¤ã„㦠+ +dystopia.nav.legaltos=使用ã®æ¡ä»¶ + +dystopia.nav.login=ログイン + +dystopia.nav.logout=ログアウト + +dystopia.nav.lostinfo=パスワードを忘れãŸå ´åˆ + +dystopia.nav.memories=æ€ã„出 + +dystopia.nav.modifyjournal=日記ã®ã‚¹ã‚¿ã‚¤ãƒ« + +dystopia.nav.news=ニュース + +dystopia.nav.paidaccts=有料アカウント + +dystopia.nav.paymentarea=アカウントã®æ”¯æ‰• + +dystopia.nav.personalinfo=プロフィールã®ç·¨é›† + +dystopia.nav.sitemap=サイトマップ + +dystopia.nav.support=ãŠå•ã„åˆã‚ã› + +dystopia.nav.updatejournal=書ã込む + +dystopia.navhead.findusers=メンãƒãƒ¼æ¤œç´¢ + +dystopia.navhead.help=ヘルプã¨ã‚µãƒãƒ¼ãƒˆ + +dystopia.navhead.journal=日記 + +dystopia.navhead.legal=ãƒãƒªã‚·ãƒ¼ + +dystopia.navhead.settings=アカウント
          オプション + +dystopia.navhead.welcome=よã†ã“ãï¼ + +dystopia.search.icq=ICQç•ªå· + +dystopia.search.int=興味 + +dystopia.search.msn=MSN ユーザーå + +dystopia.search.region=地域 + +dystopia.searchlj=LiveJournal メンãƒãƒ¼æ¤œç´¢ + +Email=メール + +Error|notes=typically used inside an H1 tag to announce an error. +Error=エラー + +error.badpassword=パスワードã¯æ­£ã—ããªã„ã§ã™ã€‚ + +error.dberror=データベースãŒç•°å¸¸çŠ¶æ…‹ã«ãªã‚Šã¾ã—ãŸï¼š + +error.deleted.name=削除ã•ã‚ŒãŸ + +error.deleted.title=削除ã•ã‚ŒãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆ + +error.ipbanned=連続ログイン失敗ã®ãŸã‚ã€ä½¿ã£ã¦ã‚‹IPアドレスã¯ä¸€æ™‚çš„ã«ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚ + +error.malformeduser=ユーザーåã¯æ­£ã—ããªã„ã§ã™ã€‚ + +error.nodb=データベースã¯ä¸€æ™‚çš„ã«ä½¿ç”¨ã§ãã¾ã›ã‚“ + +error.nodbmaintenance=ãŸã ä»Šã€ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ä¿®ç†ã®ãŸã‚ã«ãƒ€ã‚¦ãƒ³ã•ã‚Œã¦ã„ã¾ã™ã€‚å°‘ã—å¾…ã£ã¦ã„ã¦ä¸‹ã•ã„。 + +error.noentry=アクセスã—よã†ã¨ã—ãŸè¨˜äº‹ã¯å­˜åœ¨ã—ã¾ã›ã‚“。 + +error.nojournal=アクセスã—よã†ã¨ã—ãŸæ—¥è¨˜ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + +error.noremote=ã“ã®ãƒšãƒ¼ã‚¸ã‚’見るã®ã«ã€ã¾ãšãƒ­ã‚°ã‚¤ãƒ³ã—ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“。 + +error.purged.name=削除ã•ã‚Œã¾ã—㟠+ +error.purged.text=アクセスã—よã†ã¨ã—ãŸæ—¥è¨˜ã¯ã‚‚ã†å®Œå…¨ã«å‰Šé™¤ã•ã‚Œã¦ã„ã¾ã™ã€‚ + +error.purged.title=削除ã•ã‚ŒãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆ + +error.suspended.name=åœæ­¢å‡¦åˆ† + +error.suspended.title=åœæ­¢å‡¦åˆ†ã•ã‚ŒãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆ + +Help=ヘルプ + +label.switch.button=切り替㈠+ +label.switch.header=日記ã®åˆ‡ã‚Šæ›¿ãˆ + +langname.be=ベラルーシ語 + +langname.da=デンマーク語 + +langname.de=ドイツ語 + +langname.en=英語 + +langname.en_GB=英語(イギリス) + +langname.en_LJ=英語 + +langname.eo=エスペラント + +langname.es=スペイン語 + +langname.fi=フィンランド語 + +langname.fr=フランス語 + +langname.ga=アイランド語 + +langname.gd=ゲール語 + +langname.he=イスラエル語 + +langname.hu=ãƒãƒ³ã‚¬ãƒªãƒ¼èªž + +langname.is=アイスランド語 + +langname.it=イタリア語 + +langname.ja=日本語 + +langname.la=ラテン語 + +langname.lv=ラトビア語 + +langname.ms=マレー語 + +langname.nb=ノルウェー語(BokmÃ¥l) + +langname.nl=オランダ語 + +langname.nn=ノルウェー語(Nynorsk) + +langname.pl=ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž + +langname.pt=ãƒãƒ«ãƒˆã‚¬ãƒ«èªž + +langname.ru=ロシア語 + +langname.sv=スウェーデン語 + +langname.tr=トルコ語 + +langname.zh=簡体中国語 + +lostinfo.head=ログイン情報ã®å…¥æ‰‹ + +lostinfo.text=ユーザーåã¾ãŸã¯ãƒ‘スワードを忘れãŸå ´åˆã€ã“ã“をクリックã—ã¦ãã ã•ã„。 + +Password=パスワード + +password.max30=パスワードã¯30字以下ã«é™ã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ + +talk.anonwrote=匿åã®æ›¸ãè¾¼ã¿: + +talk.anonwrote_comm=[[commlink]] ã¸ã®åŒ¿åã®æ›¸ãè¾¼ã¿: + +talk.btn.preview=プレビュー + +talk.commentpermlink=リンク + +talk.commentpost=コメントをé€ä¿¡ã™ã‚‹ + +talk.commentsread=ã™ã¹ã¦ã®ã‚³ãƒ¡ãƒ³ãƒˆã‚’表示ã™ã‚‹ + +talk.curname_Mood=気分 + +talk.curname_Music=音楽 + +talk.error.comm_deleted=ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ + +talk.error.deleted=ã“ã®æ—¥è¨˜ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚ + +talk.error.deleted.title=削除済㿠+ +talk.error.mustlogin=ã“ã®è¨˜äº‹ã‚’表示ã™ã‚‹ã«ã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ + +talk.error.nocomment=コメントãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + +talk.error.noentry=記事ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + +talk.error.nosuchjournal=日記ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + +talk.error.notauthorised=èªè¨¼ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿ãŒã€ã“ã®è¨˜äº‹ã‚’表示ã§ãã¾ã™ã€‚ + +talk.error.suspended=ã“ã®æ—¥è¨˜ã¯åœæ­¢å‡¦åˆ†ã•ã‚Œã¦ã„ã¾ã™ã€‚ + +talk.error.suspended.title=åœæ­¢å‡¦åˆ† + +talk.parentlink=ç›´å‰ã®ã‚³ãƒ¡ãƒ³ãƒˆ + +talk.replytothis=返信ã™ã‚‹ + +talk.somebodywrote=[[realname]] ([[userlink]]) ã®æ›¸ãè¾¼ã¿: + +talk.somebodywrote_comm=[[commlink]] ã¸ã® [[realname]] ([[userlink]]) ã®æ›¸ãè¾¼ã¿: + +talk.spellcheck=プレビューã¨åŒæ™‚ã«ã‚¹ãƒšãƒ«ãƒã‚§ãƒƒã‚¯ã‚’実行ã™ã‚‹ + +talk.threadlink=ツリー一覧 + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_nihongo + +Username=ユーザーå + +xcolibur.greeting.anon=Livejournalã¸ã‚ˆã†ã“ãï¼ + +xcolibur.greeting.logged_in=ã“ã‚“ã«ã¡ã¯ã€[[name]]ã•ã‚“ï¼ [[logout]] + +xcolibur.login=ログイン + +xcolibur.logout=ログアウト + +xcolibur.nav.about.download=ダウンロード + +xcolibur.nav.about.general=LiveJournalã«ã¤ã„㦠+ +xcolibur.nav.about.paidaccounts=有料アカウント + +xcolibur.nav.about.press=マスコミ㸠+ +xcolibur.nav.about.sitenews=ニュース + +xcolibur.nav.about.stats=サイト統計 + +xcolibur.nav.footer.sitemap=サイトマップ + +xcolibur.nav.help=ヘルプ + +xcolibur.nav.help.ask=ãŠå•ã„åˆã‚ã› + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=パスワードを忘れãŸå ´åˆ + +xcolibur.nav.home=ホーム + +xcolibur.nav.journal=日記 + +xcolibur.nav.journal.archive=カレンダー + +xcolibur.nav.journal.edit.entries=記事ã®ç·¨é›† + +xcolibur.nav.journal.friends=å‹é”ページ + +xcolibur.nav.journal.info=プロフィール + +xcolibur.nav.journal.memories=æ€ã„出 + +xcolibur.nav.journal.recent=最近ã®æ—¥è¨˜ + +xcolibur.nav.journal.update=書ã込む + +xcolibur.nav.manage=編集 + +xcolibur.nav.manage.community=コミュニティー + +xcolibur.nav.manage.customize=スタイルã®è¨­å®š + +xcolibur.nav.manage.entries=記事ã®ç·¨é›† + +xcolibur.nav.manage.friends=å‹é” + +xcolibur.nav.manage.info=プロフィール + +xcolibur.nav.manage.password=パスワードã®å¤‰æ›´ + +xcolibur.nav.manage.pics=ユーザーアイコン + +xcolibur.nav.manage.styles=スタイルã®ç·¨é›† + +xcolibur.nav.search=検索 + +xcolibur.nav.search.directory=地域 + +xcolibur.nav.search.directory.search=ディレクトリ + +xcolibur.nav.search.interests=興味 + +xcolibur.nav.search.random=ランドム + +xcolibur.nav.siteopts=サイトオプション + +xcolibur.nav.welcome=よã†ã“ã + +xcolibur.nav.welcome.create=日記をã¤ãã‚‹ + +xcolibur.nav.welcome.login=ログイン + +xcolibur.nav.welcome.update=日記ã«æ›¸ã込む + +xcolibur.search=検索: + +xcolibur.search.category=対象: + +xcolibur.search.icq=ICQ ç•ªå· + +xcolibur.search.int=興味 + +xcolibur.search.msn=MSN ユーザーå + +xcolibur.search.region=地域 + diff --git a/ljcom/bin/upgrading/la.dat b/ljcom/bin/upgrading/la.dat new file mode 100644 index 0000000..0150a07 --- /dev/null +++ b/ljcom/bin/upgrading/la.dat @@ -0,0 +1,31 @@ +;; -*- coding: utf-8 -*- +/allpics.bml.current=Imagines Recentes + +/allpics.bml.default=Normalis + +/allpics.bml.error.noparam=Necesse est usuarii parametrum indicare. + +/allpics.bml.keywords=Verba Clavis + +/allpics.bml.nopics.title=Nullae Imagines + +/allpics.bml.pics=Hic sunt usuarii imagines usuario [[user]] + +/allpics.bml.title=Usuarii Imagines + +/community/index.bml.title=Caput Communitatis + +/community/join.bml.button.join=Adiungere ad Communitatem + +/community/join.bml.label.addtofriends=Adde "[[maintainer]]" ad elenchum amicorum.
          + +/community/join.bml.label.allowposting=Haec communitas permittet mittendum omnibus sodalibus; licet igitur illic scribere. Si iam cliens adest LiveJournal apertus in computrato, exire et iterum inire necesse est, ut haec ephemris appareat in elencho ephemeridum in quibus potes scriber. + +/community/join.bml.label.banned=Executor(es) huius communitatis interdixit tibi adiungendum. + +/community/join.bml.label.commlogged=Initus est quam computus communis, non quam computus proprius. + +/community/join.bml.label.errorcomminfo=Indicium indicatae communitatis inritum est. + +/community/join.bml.label.expls=Opprime butonem subtus ad adiungendum ad communitatem "[[maintainer]]". Decarpe botonem subtus si vis adiungere ad communitatem, sed non vis scripta comuntatis videre in pagina amicorum. + diff --git a/ljcom/bin/upgrading/lt.dat b/ljcom/bin/upgrading/lt.dat new file mode 100644 index 0000000..c07ea72 --- /dev/null +++ b/ljcom/bin/upgrading/lt.dat @@ -0,0 +1,1564 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Jei norite iÅ¡trinti žurnalÄ… arba atÅ¡aukti jo trynimÄ…, galite padaryti tai Äia. IÅ¡trynus žurnalÄ… jÅ«s turÄ—site 30 dienų atÅ¡aukti trynimÄ…, jei apsigalvotumÄ—te. Po 30-ties dienų žurnalas bus visiÅ¡kai iÅ¡trintas be galimybÄ—s jį susigražinti. + +/accountstatus.bml.journalstatus.head=Žurnalo Aktyvavimo BÅ«sena + +/accountstatus.bml.journalstatus.select.activated=Aktyvuotas + +/accountstatus.bml.journalstatus.select.deleted=IÅ¡trintas + +/accountstatus.bml.journalstatus.select.head=BÅ«sena: + +/accountstatus.bml.journalstatus.select.suspended=Sustabdytas + +/allpics.bml.current=Dabartiniai PaveikslÄ—liai + +/allpics.bml.default=Pagrindinis + +/allpics.bml.edit2=JÅ«s galite norÄ—ti redaguoti paveikslÄ—lių raktinius žodžius arba įkelti naujÄ… paveikslÄ—lį. + +/allpics.bml.error.noparam=Reikia nurodyti vartotojo parametrÄ…. + +/allpics.bml.keywords=Raktiniai žodžiai: + +/allpics.bml.nopics.text.other=Vartotojas nÄ—ra įkÄ—lÄ™s jokių paveikslÄ—lių. + +/allpics.bml.nopics.text2=JÅ«s nesate įkÄ—lÄ™s jokių paveikslÄ—lių. Tai padaryti galite Äia. + +/allpics.bml.nopics.title=PaveikslÄ—lių nÄ—ra + +/allpics.bml.pics=Å tai Äia yra [[user]] paveikslÄ—liai. + +/allpics.bml.title=PaveikslÄ—liai + +/changepassword.bml.btn.proceed=Vykdyti + +/changepassword.bml.changepassword.header=Pakeisti Slaptažodį + +/changepassword.bml.changepassword.instructions=Slaptažodžiui pakeisti, užpildykite Å¡iÄ… formÄ…. Jei reikia pagalbos iÅ¡sirenkant gerÄ… slaptažodį ir prižiÅ«rint savo prisijungimo parametrų saugumÄ…, siÅ«lome paskaityti Å¡iuos DUK. + +/changepassword.bml.email.body<< +JÅ«sų slaptažodis [[sitename]] puslapyje pakeistas. + +Ateityje, pamirÅ¡us jį, apsilankykite Äia: + + [[siteroot]]/lostinfo.bml + +Su pagarba, +[[sitename]] Komanda + +[[siteroot]] + +. + +/changepassword.bml.email.subject=Slaptažodžio Keitimas + +/changepassword.bml.error.badcheck=Naujasis slaptažodis blogas: [[error]] + +/changepassword.bml.error.badnewpassword=PakartojÄ™ naujajį slaptažodį įvedÄ—te jį ne tokį patį, kaip pirmÄ… kartÄ… - greiÄiausiai tai buvo teksto rinkimo klaida. PraÅ¡ome įvesti ir patvirtinti jÅ«sų naujÄ… slaptažodį dar kartÄ…. + +/changepassword.bml.error.badoldpassword=Nurodytas negeras senasis slaptažodis. + +/changepassword.bml.error.blankpassword=JÅ«sų naujas slaptažodis negali bÅ«ti tuÅ¡Äias. + +/changepassword.bml.error.changetestaccount=Negalima pakeisti testinio vartotojo slaptažodžio. + +/changepassword.bml.error.characterlimit=Slaptažodžiai negali bÅ«ti ilgesni nei simbolių. + +/changepassword.bml.error.invaliduser=Vartotojas [[user]] neegzistuoja. JÅ«s tikri, kad vardÄ… įvedÄ—te teisingai? + +/changepassword.bml.error.mustenterusername=Privalote įvesti vartotojo vardÄ…. + +/changepassword.bml.error.nonascii=Slaptažodžiuose leidžiama naudoti tik ASCII simbolius. PraÅ¡ome nurodyti slaptažodį, kuris sudarytas tik iÅ¡ ASCII simbolių. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Negalite pakeisti savo slaptažodžio, kol jÅ«sų dabartinis paÅ¡to adresas nÄ—ra patikrintas. + +/changepassword.bml.newpassword=Naujas Slaptažodis: + +/changepassword.bml.newpasswordagain=Naujas Slaptažodis (dar kartÄ…): + +/changepassword.bml.oldpassword=Senasis Slaptažodis: + +/changepassword.bml.proceed.instructions=Spauskite mygtukÄ… apaÄioje ir jÅ«sų slaptaždis bus pakeistas. Apie tai jums taip pat bus praneÅ¡ta el. paÅ¡tu. + +/changepassword.bml.success.text=Slaptažodis pakeistas ir el.paÅ¡tu nusiųsta apie tai primenanti žinutÄ—. + +/changepassword.bml.title=Slaptažodžio Keitimas + +/community/index.bml.title=Bendruomenių Centras + +/community/join.bml.button.join=Prisijungti prie bendruomenÄ—s + +/community/join.bml.label.addtofriends=Ä®traukti "[[maintainer]]" į draugų sÄ…raÅ¡Ä….
          + +/community/join.bml.label.allowposting=Å ioje bendruomenÄ—je raÅ¡yti gali visi nariai, taigi Å¡iÄ… teisÄ™ dabar turite ir jÅ«s. Jei jÅ«s jau esate atsidarÄ™s LiveJournal programinÄ™ įrangÄ… savo kompiuteryje, jums gali tekti atsijungti ir vÄ—l prisijungti, kad Å¡is žurnalas atsirastų žurnalų, į kuriuos galite raÅ¡yti, sÄ…raÅ¡e. + +/community/join.bml.label.banned=BendruomenÄ—s prižiÅ«rÄ—tojas uždraudÄ— jÅ«sų prisijungimÄ…. + +/community/join.bml.label.commlogged=JÅ«s prisijungÄ—te su dalinamuoju/bendruomenÄ—s vartotoju, o ne su asmeniniu vardu ir slaptažodžiu. + +/community/join.bml.label.errorcomminfo=Nurodyta bendruomenÄ—s informacija yra neteisinga. + +/community/join.bml.label.expls=PaspaudÄ™ mygtukÄ… apaÄioje prisijungsite prie "[[maintainer]]" bendruomenÄ—s. NužymÄ—kite nustatymÄ… apaÄioje jei norite prisijungti prie bendruomenÄ—s, bet nenorite matyti bendruomenÄ—s įrašų savo draugų sÄ…raÅ¡o puslapyje. + +/community/join.bml.label.loginfirst=Tam, kad tapti bendruomenÄ—s nariu, visų pirma reikia prisijungti su vardu ir slaptažodžiu. + +/community/join.bml.label.membernow=Dabar jÅ«s esate [[commname]] bendruomenÄ—s narys. + +/community/join.bml.label.sure=JÅ«s įsitikinÄ™s? + +/community/join.bml.success=Pavyko + +/community/join.bml.title=Prisijungti prie BendruomenÄ—s + +/community/leave.bml.button.leave=Palikti BendruomenÄ™ + +/community/leave.bml.label.buttontoleave=Tam, kad palikti "[[commname]]" bendruomenÄ™, spauskite mygtukÄ… apaÄioje. + +/community/leave.bml.label.infoerror=Nurodyta bendruomenÄ—s informacija yra neteisinga. + +/community/leave.bml.label.logoutfirst=Tam, kad palikti bendruomenÄ™, visų pirma reikia prisijungti su savo vartotojo vardu ir slaptažodžiu. + +/community/leave.bml.label.removed=JÅ«s kÄ… tik palikote [[commname]] bendruomenÄ™ + +/community/leave.bml.success=Pavyko + +/community/leave.bml.sure=JÅ«s įsitikinÄ™s? + +/community/search.bml.button.clear=IÅ¡valyti + +/community/search.bml.button.search=IeÅ¡koti! + +/community/search.bml.checkbox.onlywithpics=Tik tar bendruomenių su paveikslÄ—liais + +/community/search.bml.label.byinterest=Pagal PomÄ—gius + +/community/search.bml.label.bylocation=Pagal VietÄ… + +/community/search.bml.sel.username=Vartotojo Vardas + +/community/search.bml.sel.week=savaitÄ— + +/community/search.bml.title=Bendruomenių paieÅ¡ka + +/create.bml.age.check.question=Ar Jums mažiau nei 13 metų? + +/create.bml.age.check.yes=Taip, man dar nÄ—ra 13 metų + +/create.bml.age.check2.question=Ar Jums daugiau nei 13 metų? + +/create.bml.age.check2.yes=Taip, man daugiau nei 13 metų. + +/create.bml.age.head=Amžius + +/create.bml.btn.proceed=TÄ™sti + +/create.bml.clusterselect.cluster=Klasteris + +/create.bml.clusterselect.clusternum=Klasteris [[number]] + +/create.bml.clusterselect.head=Klasterio pasirinkimas + +/create.bml.clusterselect.nocluster=Be klasterio + +/create.bml.clusterselect.text=PraÅ¡au pasirinkti klasterį, kurį norite sukurti Å¡ioje paskyroje. Pastaba: Tai skirta klaidų taisymo/testavimo tikslams. Galutiniame rezultate, vartotojas negalÄ—s pasirinkti, arba iÅ¡vis nežinos apie tai. + +/create.bml.create.head=Kuriamas naujas žurnalas + +/create.bml.create.text=NorÄ—dami sukurti naujÄ… žurnalÄ… yra paprasta, tiesiog sekite instrukcijÄ…! + +/create.bml.email.head=JÅ«sų el. paÅ¡to adresas + +/create.bml.email.input.head=El. paÅ¡to adresas + +/create.bml.error.coppa.under13=AtsipraÅ¡ome, taÄiau dÄ—l galiojanÄių įstatymų, jÅ«s neturite teisÄ—s naudotis LiveJournal'o paslaugomis, kol Jums nesukako 13 metų. PraÅ¡ome grįžti savo 13-to gimtadienio proga. + +/create.bml.error.email.blank=Turite įvesti JÅ«sų el. paÅ¡to adresÄ…. + +/create.bml.error.email.lj_domain=Negalite naudoti [[domain]] pavadinimo kuriant vartotojÄ…. PraÅ¡ome įvesti kitÄ… e. paÅ¡to adresÄ…. + +/create.bml.error.email.nospaces=Tarpai neleidžiami el. paÅ¡to adrese. Jei naudojate AOL, prisiminkite, kad JÅ«sų internetinis el. paÅ¡to adresas yra JÅ«sų vardas be tarpų, esantis prieÅ¡ @aol.com + +/create.bml.error.password.asciionly=Galite naudoti tik ASCII simbolius slaptažodyje. + +/create.bml.error.password.blank=Turite įvesti slaptažodį. + +/create.bml.error.password.nomatch=Slaptažodis netinka. + +/create.bml.error.postrequired=Reikalingas įraÅ¡as. + +/create.bml.error.username.blank=PraÅ¡au įvesti vardÄ… arba slapyvardį. + +/create.bml.error.username.inuse=Vartotojo vardas jau naudojamas; praÅ¡ome pasirinkti kitÄ…. + +/create.bml.error.username.iscode=Vartotojo vardas panaÅ¡us į kvietimo kodÄ…, o ne vartotojo vardÄ…. + +/create.bml.error.username.mustenter=Privalote įvesti vartotojo vardÄ…. + +/create.bml.error.username.reserved=AtsipraÅ¡ome, Å¡is vartotojo vardas rezervuotas. + +/create.bml.initial.friend.lj_maintenance=Ataskaitos apie planuotus & neplanuotus neveikimus ir techninius darbus. + +/create.bml.initial.friend.news=LiveJournal'o naujienos ir įvykiai + +/create.bml.initialfriends=Ä®traukite Å¡iuos žurnalus į JÅ«sų draugų sÄ…raÅ¡Ä…, norÄ—dami bÅ«ti laiku informuoti apie puslapio naujienas ir įvykius. + +/create.bml.initialfriends.heading=Draugų pradžia + +/create.bml.name.head=JÅ«sų vardas + +/create.bml.name.input.head=Vardas/pavadinimas: + +/create.bml.name.text=JÅ«sų vardas arba slapyvardis? Jis bus pateiktas JÅ«sų žurnalo virÅ¡uje, ir vartotojų direktorijoje turite pasirinkti, kad bÅ«tumete sÄ…raÅ¡e. Neprivalote įvesti viso arba tikro vardo. + +/create.bml.password.head=Slaptažodis + +/create.bml.password.input.head1=Slaptažodis: + +/create.bml.password.input.head2=Patvirtinti slaptažodį: + +/create.bml.password.text=Pasirinkti slaptažodį. + +/create.bml.proceed.btn.proceed=TÄ™sti... + +/create.bml.proceed.warning=Paspauskite TÄ™sti tik vienÄ…kart!! + +/create.bml.success.btn.enterinfo=Ä®veskite asmeninÄ™ informacijÄ… + +/create.bml.success.head=Pavyko! + +/create.bml.success.text1=JÅ«sų žurnalas sukurtas. Svarbi registracijos informacija iÅ¡siųsta elektroniniu laiÅ¡ku į [[email]], kuriame yra tolesnÄ—s instrukcijos. Ä®sitikinkite ar JÅ«sų žurnalas sukurtas, spausdami nuorodÄ…, esanÄiÄ… laiÅ¡ke. + +/create.bml.success.text2=JÅ«sų LiveJournal bus pasiekiamas: + +/create.bml.success.text3=Dabar, praÅ¡ome surasti laiko pateikti Å¡iek tiek asmeninÄ—s informacijos. Tai nÄ—ra bÅ«tina, taÄiau tai padÄ—tų mums suprasti kas naudojasi LiveJournal'u. + +/create.bml.title=Sukurti naujÄ… žurnalÄ… + +/create.bml.tos.error=Privalote susipažinti ir sutikti su vartotojo taisyklÄ—mis prieÅ¡ sukurdami vartotojÄ…. + +/create.bml.tos.haveread=Susipažinau ir sutinku su Vartotojo taisyklÄ—mis. + +/create.bml.tos.heading=Vartotojo taisyklÄ—s + +/create.bml.useacctcodes.entercode=Norint sukurti naujÄ… vartotojÄ…, įveskite aktyvavimo kodÄ…. NorÄ—dami sužinoti daugiau, žiÅ«rÄ—kite Kaip sukurti vartotojÄ…? + +/create.bml.useacctcodes.welcome=Sveiki atvykÄ™ + +/create.bml.username.box.head=Vartotojo vardas: + +/create.bml.username.charsallowed=Vartotojo vardas gali bÅ«ti sudarytas tik iÅ¡ mažųjų lotyniÅ¡kos abÄ—cÄ—lÄ—s raidžių (a-z), skaiÄių (0-9) ir pabraktų simbolių (_).
          Taip pat neturi bÅ«ti ilgesnis nei 16 simbolių. + +/create.bml.username.forpaidaccts=Arba, mokamiems vartotojams: + +/create.bml.username.head=Vartotojo vardas + +/create.bml.username.ljaddress=JÅ«sų žurnalas bus pasiekiamas Å¡iais adresais: + +/create.bml.username.text=Kiekvienas [[sitename]] vartotojas privalo turÄ—ti savo unikalų vartotojo vardÄ…. JÅ«sų vartotojo vardas bus rodomas adrese į JÅ«sų žurnalÄ… ir kurį Jųs naudosite prisijungiant prie [[sitename]] serverio. Taip pat jis bus rodomas, jei komentuosite kitų žmonių žurnaluose. + +/create.bml.username.username=vartotojo vardas + +/editinfo.bml.allowshowcontact.about=Patartina įjungti Å¡itÄ… galimybÄ™, nes ji leidžia kitiems žmonÄ—ms matyti jÅ«sų elektroninio paÅ¡to adresÄ…, ICQ numerį ar AOL Instant Messenger vardÄ… jÅ«sų LiveJournal, ir esant reikalui susisiekti su jumis. + +/editinfo.bml.allowshowcontact.email=Elektroninio paÅ¡to adreso rodymas: + +/editinfo.bml.allowshowcontact.email.actual_only=Tik tikrasis adresas + +/editinfo.bml.allowshowcontact.email.both=Abu (tikrasis ir [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Tik LiveJournal adresas + +/editinfo.bml.allowshowcontact.email.neither=Nerodomas joks el.paÅ¡to adresas + +/editinfo.bml.allowshowcontact.email.no_show=Nerodyti elektroninio paÅ¡to adreso + +/editinfo.bml.allowshowcontact.email.show=Rodyti elektroninio paÅ¡to adresÄ… + +/editinfo.bml.allowshowcontact.title=Rodyti kontaktinÄ™ informacijÄ… jÅ«sų LiveJournal? + +/editinfo.bml.allowshowinfo.about=Ä®junkite Å¡itÄ… galimybÄ™, jeigu norite, kad kiti vartotojai matytų jÅ«sų gimimo datÄ… ir gyvenamÄ…jÄ… vietÄ… (miestÄ…, regionÄ… ir Å¡alį) + +/editinfo.bml.allowshowinfo.title=Rodyti gyvenamÄ…jÄ… vietÄ… ir gimimo datÄ…? + +/editinfo.bml.autotranslate.about<< +Naudokite šį nustatymÄ… tam, kad nurodyti LiveJournal, kurį kodavimÄ… priskirti jÅ«sų įraÅ¡ams ir jų komentarams prieÅ¡ tai, kai tinklapis buvo konvertuotas į Unicode. +Jeigu raÅ¡ote lietuviÅ¡kai, pasirinkite "none". +. + +/editinfo.bml.autotranslate.header=AutomatiÅ¡kai konvertuoti senus įraÅ¡us iÅ¡ kodavimo: + +/editinfo.bml.bday.title=Gimimo data + +/editinfo.bml.bday.year.opt=metų nurodyti nebÅ«tina + +/editinfo.bml.bdayreminders.about=Ä®junkite nustatymÄ…, jeigu norite gauti priminimÄ… elektroniniu paÅ¡tu apie jÅ«sų LiveJournal draugų gimtadienius. + +/editinfo.bml.bdayreminders.header=Siųsti gimtadienių priminimus (Å¡iuo metu iÅ¡jungta) + +/editinfo.bml.bio.about=ÄŒia galite paraÅ¡yti savo trumpÄ… biografijÄ…. Ji bus rodoma jųsų Vartotojo Informacijos puslapyje. + +/editinfo.bml.bio.header=Apie Jus + +/editinfo.bml.blockrobots.about=Ä®jungus Å¡itÄ… galimybÄ™, paieÅ¡kos robotams bus nurodyta nesikiÅ¡ti į jÅ«sų LiveJournal. Ne visi robotai laikosi Å¡ių taisyklių. + +/editinfo.bml.blockrobots.header=Neleisti paieÅ¡kos sistemoms indeksuoti jÅ«sų LiveJournal + +/editinfo.bml.city.title=Miestas + +/editinfo.bml.country.choose=Pasirinkite Å¡alį + +/editinfo.bml.country.title=Å alis + +/editinfo.bml.donotlog=Ne + +/editinfo.bml.email.title=El. paÅ¡tas + +/editinfo.bml.enableboards.about=PažymÄ—kite, jeigu norite, kad žmonÄ—s galÄ—tų komentuoti jÅ«sų įraÅ¡us. + +/editinfo.bml.enableboards.header=Ä®jungti komentarus + +/editinfo.bml.encoding.about=NÄ—ra bÅ«tina keisti Å¡ituos nustatymus. Tik vartotojams, raÅ¡antiems skirtingomis kalbomis gali jų prireikti. + +/editinfo.bml.encoding.header=Kodavimo nustatymai + +/friends/add.bml.add.header=Pavyko + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=Vartotojas buvo pridÄ—tas į jÅ«sų draugų sÄ…raÅ¡Ä…. Galite peržiÅ«rÄ—ti atnaujintÄ… savo draugų puslapį. + +/friends/add.bml.add.title=Draugas PridÄ—tas! + +/friends/add.bml.btn.add=PridÄ—ti [[user]] + +/friends/add.bml.btn.modify=Redaguoti + +/friends/add.bml.btn.remove=IÅ¡mesti + +/friends/add.bml.colors.bg=Fonas + +/friends/add.bml.colors.fg=Teksto spalva + +/friends/add.bml.colors.header=Spalvos + +/friends/add.bml.colors.hover=(Nutaikykite su pele į spalvÄ…, jei norite pamatyti jos pavadinimÄ…) + +/friends/add.bml.colors.text=JÅ«s taip pat, jei norite, galite pasirinkti spalvÄ…, kuri atstovaus [[user]] jÅ«sų draugų sÄ…raÅ¡e. + +/friends/add.bml.confirm.header=PridÄ—ti [[user]] prie draugų? + +/friends/add.bml.confirm.text=Tam, kad pridÄ—ti [[user]] į draugų sÄ…raÅ¡Ä…, spauskite mygtukÄ… žemiau. + +/friends/add.bml.confirm.title=PridÄ—ti DraugÄ… + +/friends/add.bml.error1.header=IÅ¡ pradžių prisijunkite + +/friends/add.bml.error1.text=Tam, kad pridÄ—ti vartotojÄ… į draugų sÄ…raÅ¡Ä…, visų pirma turite prisijungti. Jei jÅ«s dar neturite livejournal vartotojo, jÅ«s galite jį susikurti, kad galÄ—tumÄ—te sekti draugų žurnalus. + +/friends/add.bml.error1.title=PridÄ—ti DraugÄ… + +/friends/add.bml.error2.text=Buvo pateiktas neteisingas arba trÅ«kstamas vartotojo vardas. Kad pridÄ—ti draugÄ…, eikite į draugų sÄ…raÅ¡o redagavimo puslapį. + +/friends/add.bml.error3.text=Vartotojas [[user]] jau yra jÅ«sų draugų sÄ…raÅ¡e. TaÄiau, galite redaguoti spalvas, kurias esate priskyrÄ™ Å¡iam vartotojui. + +/friends/editgroups.bml.btn.ge.del=Trinti + +/friends/editgroups.bml.btn.ge.new=Nauja + +/friends/editgroups.bml.btn.ge.ren=Pervadinti + +/friends/editgroups.bml.btn.gs.private=Privati + +/friends/editgroups.bml.btn.gs.public=VieÅ¡a + +/friends/editgroups.bml.btn.mv.down=Žemyn + +/friends/editgroups.bml.btn.mv.up=AukÅ¡tyn + +/friends/editgroups.bml.confirm.delete=Ar esate tikri, kad norite iÅ¡trinti Å¡iÄ… draugų grupÄ™? + +/friends/editgroups.bml.done.btn=IÅ¡saugoti Pakeitimus + +/friends/editgroups.bml.done.header=BaigÄ—te? + +/friends/editgroups.bml.done.text=Kai baigsite, iÅ¡saugokite pakeitimus spausdami mygtukÄ… apaÄioje. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=JÅ«s pasiekÄ—te leistinÄ… 30-ties draugų grupių limitÄ…. Jei jau iÅ¡trynÄ—te vienÄ… ar daugiau grupių bet dar neiÅ¡saugojote pakeitimų, padarykite taip dabar, grįžkite į šį puslapį ir perkraukite jį. Taip vÄ—l galÄ—site kurti naujas draugų grupes. + +/friends/editgroups.bml.error.text=Serverio gražintas klaidos praneÅ¡imas: + +/friends/editgroups.bml.group.public=(vieÅ¡as) + +/friends/editgroups.bml.ingroup=GrupÄ—je: + +/friends/editgroups.bml.ingroup.not=Ne grupÄ—je: + +/friends/editgroups.bml.prompt.newname=Ä®veskite naujos grupÄ—s pavadinimÄ…: + +/friends/editgroups.bml.prompt.rename=Pervadinti grupÄ™ į: + +/friends/editgroups.bml.saved.header=IÅ¡saugota + +/friends/editgroups.bml.saved.text=JÅ«sų draugų grupÄ—s iÅ¡saugotos. + +/friends/editgroups.bml.text<< +Å is puslapis leidžia redaguoti draugų grupes. Draugų grupÄ—s naudojamos nustatant įrašų saugumo lygį ar filtruojant draugų puslapio įraÅ¡us. DÄ—l daugiau pagalbos, žvilgtelkite į Kas yra draugų grupÄ—s? Kaip jas naudoti? + +JavaScript turi bÅ«ti įjungtas, kad bÅ«tų galima naudotis Å¡iuo puslapiu. +. + +/friends/editgroups.bml.text.sec=Pastaba dÄ—l saugumo: jei norite iÅ¡trinti grupÄ™ ir sukurti naujÄ…, nedarykite to pervadindami kokiÄ… nors grupÄ™ ir tada jÄ… redaguodami. Jei taip elgsitÄ—s, visi jÅ«sų senesni įraÅ¡ai, kurie buvo prieinami senÄ…jai grupei, tada bus matomi naujÄ…jai grupei. + +/friends/editgroups.bml.title=Draugų Grupių Redagavimas + +/friends/editgroups.bml.yourgroups=JÅ«sų draugų grupÄ—s: + +/friends/edit_do.bml.background=Fonas + +/friends/edit_do.bml.bgcolor=Fono spalva: + +/friends/edit_do.bml.btn.close=Uždaryti + +/friends/edit_do.bml.btn.save=IÅ¡saugoti Pakeitimus + +/friends/edit_do.bml.btn.toggle=Ä®jungti/IÅ¡jungti PeržiÅ«ros LangÄ… + +/friends/edit_do.bml.done.head=BaigÄ—te? + +/friends/edit_do.bml.done.text=BaigÄ™ spauskite "IÅ¡saugoti Pakeitimus" mygtukÄ… apaÄioje... + +/friends/edit_do.bml.error.updating=Atnaujinant draugų sÄ…raÅ¡Ä… įvyko klaida: + +/friends/edit_do.bml.fellowfriends.head=Draugaujantys + +/friends/edit_do.bml.fellowfriends.text=JÅ«s esate Å¡ių žmonių draugų sÄ…raÅ¡e. JÅ«s taip pat galite įtraukti juos į savo draugų sÄ…raÅ¡Ä…, taÄiau nesate įpareigoti tai padaryti - Å¡i informacija pateikta tik tam, kad žinotumÄ—t jų LiveJournal vardus. + +/friends/edit_do.bml.foreground=Tekstas + +/friends/edit_do.bml.friend=Draugas + +/friends/edit_do.bml.hover=Kad pamatyti spalvos pavadinimÄ…, nutaikykite virÅ¡ jos pelÄ—s kursorių + +/friends/edit_do.bml.mrcolor=Spalvų PeržiÅ«ra + +/friends/edit_do.bml.name=Vardas + +/friends/edit_do.bml.needmore=Jei norite pridÄ—ti daugiau draugų nei yra vietos Å¡ioje formoje, iÅ¡saugokite pakeitimus ir grįžkite Äia ir vÄ—l, kad pridÄ—ti likusius. + +/friends/edit_do.bml.nofriends.head=Jokių Draugų? + +/friends/edit_do.bml.nofriends.text=Å iuo metu jÅ«s neturite pridÄ—jÄ™ jokių draugų. Å iaip ar taip, mes esame tikri kad jÅ«s privalote turÄ—ti Å¡iek tiek draugų! :) Tiesiog įveskite jų LiveJournal vardus žemiau... + +/friends/edit_do.bml.opt.delete=IÅ¡trinti? + +/friends/edit_do.bml.success.head=Ä®vykdyta SÄ—kmingai + +/friends/edit_do.bml.success.text=JÅ«sų draugų sÄ…raÅ¡as pasikeitÄ—, atnaujintÄ… jų įrašų puslapį galite pamatyti Äia. + +/friends/edit_do.bml.textcolor=Teksto Spalva + +/friends/edit_do.bml.title=Draugų SÄ…raÅ¡o Redagavimas + +/friends/edit_do.bml.user=Vartotojas + +/friends/edit_do.bml.viewer=Spalvų PeržiÅ«ra + +/friends/edit_do.bml.yourfriends.head=JÅ«sų Draugai + +/friends/edit_do.bml.yourfriends.text=JÅ«sų draugų sÄ…raÅ¡as Å¡iuo metu atrodo taip: + +/friends/filter.bml.editgroups=Jei norite redaguoti draugų grupes, eikite į [[link]] puslapį. + +/friends/filter.bml.error.nogroups|staleness=1 +/friends/filter.bml.error.nogroups=JÅ«s negalite filtruoti draugų sÄ…raÅ¡o, nes visų pirma turite sukurti draugų grupes. + +/friends/filter.bml.error.nogroups.header=Neapibrėžtos GrupÄ—s + +/friends/filter.bml.reset=IÅ¡valyti + +/friends/filter.bml.select=PažymÄ—kite draugų grupÄ™(-es), kuriÄ… (-iais) norite matyti draugų sÄ…raÅ¡e. + +/friends/filter.bml.select.header=Pasirinkite Grupes + +/friends/filter.bml.submit=Rodyti! + +/friends/filter.bml.title=Draugų Filtras + +/friends/index.bml.about|staleness=1 +/friends/index.bml.about<< +"Draugų sÄ…raÅ¡o" sÄ…vokos trumpas apraÅ¡ymas bÅ«tų toks. +PridÄ—dami kitus vartotojus į jÅ«sų draugų sÄ…raÅ¡Ä…, jÅ«s galite lengvai sekti, kas vyksta jų gyvenimuose, tiesiai iÅ¡ savo draugų puslapio. +Draugai Å¡iame puslapyje gali bÅ«ti ne vien individualÅ«s žmonÄ—s, bet taip pat ir bendruomenÄ—s bei "syndicated feeds". +. + +/friends/index.bml.edit.about|staleness=1 +/friends/index.bml.edit.about=PridÄ—ti, redaguoti ar iÅ¡mesti vartotojus iÅ¡ draugų sÄ…raÅ¡o. + +/friends/index.bml.editgroups.about=Sukurti, redaguoti ar trinti draugų sub-grupes. + +/friends/index.bml.filter|staleness=1 +/friends/index.bml.filter=Å ios draugų grupÄ—s gali bÅ«ti naudojamos filtruoti draugų sÄ…raÅ¡Ä…: jÅ«s galite pasirinkti bÅ«tent norimÄ… žiÅ«rÄ—ti grupÄ™. + +/friends/index.bml.filter.about|staleness=1 +/friends/index.bml.filter.about=Filtruoti draugų sÄ…raÅ¡Ä… pagal tam tikras draugų grupes. + +/friends/index.bml.groups=Taip pat galite apibrėžti naujas draugų sub-grupes. + +/friends/index.bml.security=JÅ«sų draugų sÄ…raÅ¡as taip pat naudojamas įraÅ¡ams su apribota skaitymo galimybe. Daugiau apie draugų sÄ…raÅ¡u apribotÄ… privatumÄ… galite paskaityti straipsnyje Draugai & Saugumo Lygiai. + +/friends/index.bml.security.header=Privatumas + +/friends/index.bml.security.only|staleness=1 +/friends/index.bml.security.only="Tik Draugams" įraÅ¡us gali matyti tik jÅ«sų draugų sÄ…raÅ¡e esantys vartotojai. + +/friends/index.bml.title=Ä®rankiai + +/friends/index.bml.tools=Ä®rankiai + +/friends/popwithfriends.bml.account_type=AtsipraÅ¡ome, bet jÅ«sų profilio tipas neleidžia naudotis Å¡iuo įrankiu. + +/friends/popwithfriends.bml.count=Kiekis + +/friends/popwithfriends.bml.exclude_own=Pasirinktinai, galite iÅ¡skirti draugus iÅ¡ grupÄ—s. + +/friends/popwithfriends.bml.include_own=Pasirinktinai, galite įtraukti draugus į grupÄ™. + +/friends/popwithfriends.bml.intro=JÅ«sų draugų, bet ne jÅ«sų, draugų sÄ…raÅ¡uose dažni Å¡ie vartotojai. + +/friends/popwithfriends.bml.intro_own=Å ie vartotojai dažni jÅ«sų draugų draugų sÄ…raÅ¡uose. Å iame sÄ…raÅ¡e taip pat įtraukti ir JÅ«sų draugai. + +/friends/popwithfriends.bml.no_users=Vartotojų nÄ—ra. + +/friends/popwithfriends.bml.title=PopuliarÅ«s Vartotojai Tarp JÅ«sų Draugų + +/friends/popwithfriends.bml.user=Vartotojas + +/interests.bml.findsim.searchwait=Atkreipkite dÄ—mesį: paieÅ¡ka užims kelias sekundes. KantrybÄ—s. + +/legal/index.bml.title=JuridinÄ— Informacija + +/legal/privacy.bml.title=Privatumas + +/legal/tos.bml.title=Paslaugos Nuostatos + +/login.bml.bindip.label=Susieti su IP adresu: + +/login.bml.bindip.no=Ne (tinka visi IPT) + +/login.bml.bindip.yes=Taip (saugiau) + +/login.bml.error.mustenterusername=Turite įvesti vartotojo vardÄ… + +/login.bml.expire.btn.neverexpire=Pakeisti galiojimo laikÄ… į NIEKADA + +/login.bml.expire.btn.sessiononly=Pakeisti galiojimo laikÄ… į VIENAM PRISIJUNGIMUI + +/login.bml.expire.neverexpire.text=JÅ«sų prisijungimas niekada nesibaigs, taigi jei esate prie vieÅ¡o interneto terminalo, mokykloje, bibliotekoje, ar kitoje vietoje kur žmonÄ—s naudojasi kompiuteriu trumpÄ… laikÄ…, įsitikinkite, kad pabaigÄ™s darbÄ… atsijungÄ—te! Arba, nustatykite, kad atsijungtumÄ—te, kai uždarote narÅ¡yklÄ—s langÄ…. + +/login.bml.expire.sessiononly.text=JÅ«s atsijungsite po to, kai uždarysite narÅ¡yklÄ—s langÄ…. Jei tai yra JÅ«sų kompiuteris ir JÅ«s esate vienintelis vartotojas, galite nustatyti neribotÄ… prisijungimo laikÄ…. + +/login.bml.links.head=Nuorodos + +/login.bml.links.link1=JÅ«sų draugų puslapis. + +/login.bml.links.link2=JÅ«sų reikalų sÄ…raÅ¡as. + +/login.bml.links.text=Ateityje Å¡iame puslapyje bus įvairių rÅ«Å¡ių nuorodų, bet Å¡iuo metu yra keletas vietų, kurias norÄ—tumÄ—te aplankyti: + +/login.bml.loggedin.head=PrisijungÄ™s! + +/login.bml.loggedin.text=Dabar JÅ«s prisijungÄ™s. + +/login.bml.login.btn.changeopts=Pakeisti pasirinkimus + +/login.bml.login.btn.login=Prisijungti... + +/login.bml.login.expiration=Galiojimas: + +/login.bml.login.forget=PamirÅ¡ote? + +/login.bml.login.head=Prisijungti + +/login.bml.login.never=Niekada + +/login.bml.login.otheropts=Kitos galimybÄ—s: + +/login.bml.login.password=Slaptažodis: + +/login.bml.login.text1=Norint prisijungti prie [[sitename]], įveskite apaÄioje savo vartotojo vardÄ… ir slaptažodį. Naujiems vartotojams: Norint sukurti naujÄ… vartotojÄ…, eikite Äia. + +/login.bml.login.text2<< +Galite nustatyti kada baigsis JÅ«sų prisijungimas. Pagal nutylÄ—jimÄ…, JÅ«s atsijungiate kai uždarote narÅ¡yklÄ™, kas geriausiai tinka vieÅ¡o naudojimo kompiuteriams. TaÄiau, jei esate vienintelis kompiuterio savininkas ir daugiau niekas juo nesinaudoja, galite pasirinkti, kad prisijungimas niekada nesibaigtų. NorÄ—dami sužinoti daugiau, o taip pat ir kitus pasirinkimus, apsilankykite Kokie yra pasirinkimai man prisijungus? + +. + +/login.bml.login.username=Vartotojo vardas: + +/login.bml.login.whenbrowsercloses=Užsidarius narÅ¡yklei + +/login.bml.logout.btn=Atsijungti + +/login.bml.title=Prisijungti + +/login.bml.whylogin.benefit1=NereikÄ—s daugiau niekada įvesti vartotojo vardo/slaptažodžio bet kurioje Å¡io puslapio vietoje. + +/login.bml.whylogin.benefit2=GalÄ—site matyti JÅ«sų draugų "apsaugotas" žinutes, kurie suteikÄ— Jums teisÄ™ jas skaityti. + +/login.bml.whylogin.benefit3=Dauguma funkcijų yra matomos arba aktyvios tik Jums prisijungus. + +/login.bml.whylogin.head=KodÄ—l prisijungti? + +/login.bml.whylogin.text=Å tai Äia yra keletas naudingų dalykų Jums prisijungus: + +/logout.bml.already.head=Jau atsijungÄ™s + +/logout.bml.already.text=JÅ«s jau atsijungÄ—te. + +/logout.bml.killall.btn=Užbaigti visus mano prisijungimus + +/logout.bml.killall.head=Kiti prisijungimai + +/logout.bml.killall.text=Turite kitÄ… aktyvų prisijungimÄ…. Norite užbaigti visus aktyvius prisijungimus, ir ne tik šį? (ŽiÅ«rÄ—kite this FAQ daugiau informacijos.) + +/logout.bml.loggedout.already=Jau atsijungÄ™s. + +/logout.bml.loggedout.head=AtsijungÄ™s + +/logout.bml.loggedout.killedall=Visi JÅ«sų prisijungimai baigti. + +/logout.bml.loggedout.success=AtsijungÄ™s. + +/logout.bml.loggedout.text=Dabar JÅ«s atsijungÄ™s. + +/logout.bml.logout.btn=Atsijungti + +/logout.bml.logout.head=Atsijungti? + +/logout.bml.logout.text=Paspauskite mygtukÄ… apaÄioje norÄ—dami atsijungti. + +/logout.bml.title=Atsijungti + +/lostinfo.bml.btn.proceed=TÄ™sti + +/lostinfo.bml.enter_email=Ä®veskite savo el. paÅ¡to adresÄ…: + +/lostinfo.bml.enter_email_optional=El. paÅ¡to adresas: (pasirinktinai) + +/lostinfo.bml.enter_username=Ä®veskite vartotojo vardÄ…: + +/lostinfo.bml.error.no_email=Norint atstatyti vartotojÄ…, turite įvesti el. paÅ¡to adresÄ…. + +/lostinfo.bml.error.purged=Nepavyksta gauti slaptažodžio iÅ¡trintam vartotojui po to, kai jis buvo sunaikintas. + +/lostinfo.bml.error.renamed=Nepavyksta gauti slaptažodžio pervardintam vartotojui. + +/lostinfo.bml.error.sysbanned=Neturite teisų siųsti slaptažodžio el. paÅ¡tu. + +/lostinfo.bml.lostpassword.text=Jei praradote slaptažodį, įveskite savo vartotojo vardÄ… ir pasirinktinai, el. paÅ¡to adresÄ…, kuriuo norÄ—tumÄ—te gauti slaptažodį. Norint gauti slaptažodį prieÅ¡ tai nurodytu el. paÅ¡to adresu, pastarasis turi bÅ«ti veikiantis. Jei paliksite el. paÅ¡to laukelį tuÅ¡ÄiÄ…, slaptažodis bus nusiųstas dbartiniu adresu. + +/lostinfo.bml.lostpassword.title=Praradote savo slaptažodį? + +/lostinfo.bml.lostusername.text=Jei praradote savo vartotojo vardÄ…, įveskite savo el. paÅ¡to adresÄ… ir mes iÅ¡siųsime Jums jÅ«sų vartotojo vardÄ…. + +/lostinfo.bml.lostusername.title=Praradote savo vartotojo vardÄ…? + +/lostinfo.bml.title=Prarasta informacija + +/lostinfo_do.bml.error.no_usernames_for_email=NÄ—ra vartotjo vardo Å¡iam el. paÅ¡to adresui: [[address]] + +/lostinfo_do.bml.error1.text=Niekada nenaudojote Å¡io el. paÅ¡to adreso Å¡iam varotojui arba jis nebuvo veikiantis. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +***Tai automatizuotas laiÅ¡kas. Neprivalote į jį atsakyti.*** + +Tai yra užklaustas slaptažodžio priminimas iÅ¡ [[sitename]]. +ApaÄioje yra jÅ«sų žurnalo registruotas vartotojo vardas, slaptažodis, ir el. paÅ¡to adresas. + +Vartotojo vardas: [[username]] +Slaptažodis: [[password]] +El. paÅ¡to adresas: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=El. paÅ¡to patikrinimui, eikite Äia: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Å i informacija buvo užklausta interneto puslapyje iÅ¡ [[remoteip]]. + +Jei neužklausÄ—te Å¡io slaptažodžio, atsiųsto Jums, nepanikuokite. Jųs esate vienintelis, kuris skaito šį laiÅ¡kÄ…, o ne kitas asmuo. GabÅ«t, kad vartotojas, kuris atliko Å¡iÄ… užklausÄ…, suklydo ir mano, kad jis kontroliuoja šį varotojo vardÄ…. Arba galbÅ«t, kažkas suklydo spaudinant vartotojo vardÄ… ar el. paÅ¡to adresÄ…. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Jei niekaip negalite patikÄ—ti, kad JÅ«sų paskyra yra saugi, skaitykite http://www.livejournal.com/support/faqbrowse.bml?faqid=117 noredami suzinoti kaip dar labiau ji apsaugoti. + +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Naudingos nuorodos: + +JÅ«sų LiveJournal: +[[journal]] + +Pakeisti žurnalÄ… online režimu: +[[updateurl]] + +LinkÄ—jimai, +LiveJournal komanda +. + +/lostinfo_do.bml.lostpasswordmail.subject=Prarastas slaptažodis + +/lostinfo_do.bml.password_mailed.text=Pavyko. JÅ«sų slaptažodis iÅ¡siųstas. + +/lostinfo_do.bml.password_mailed.title=Slaptaždis iÅ¡siųstas! + +/lostinfo_do.bml.title=Prarasta informacija + +/lostinfo_do.bml.username_mailed.text=Pavyko. JÅ«sų vartotojo vardas iÅ¡siųstas. + +/lostinfo_do.bml.username_mailed.title=Varotojo vardas iÅ¡siųstas! + +/manage/index.bml.information.siteopts.about=Pasirinkite savo norimÄ… svietainÄ—s iÅ¡vaizdÄ… ir kalbÄ… + +/manage/siteopts.bml.btn.lang=Pakeisti KalbÄ… + +/manage/siteopts.bml.btn.scheme=Pakeisti SchemÄ… + +/manage/siteopts.bml.head.lang=IÅ¡sirinkite kalbÄ… + +/manage/siteopts.bml.head.scheme=IÅ¡sirinkite norimÄ… schemÄ… + +/manage/siteopts.bml.title=NarÅ¡ymo Nustatymai + +/modify_do.bml.availablestyles.head=Galimi stiliai + +/modify_do.bml.availablestyles.userstyles=Vartotojo stiliai + +/modify_do.bml.colortheme.about=ÄŒia galite pasirinkti spalvų paletÄ™ iÅ¡dÄ—stymo pasirinkimams, pateiktÄ… virÅ¡uje. Arba, jei jums nepatinka pateiktos spalvos, nurodykite savo! + +/modify_do.bml.colortheme.area.head=Veiklos sritis + +/modify_do.bml.colortheme.color.head1=Spalva + +/modify_do.bml.colortheme.color.head2=(#rrggbb arba pavadinimas) + +/modify_do.bml.colortheme.customcolors=Pasirenkamos spalvos + +/modify_do.bml.colortheme.defaulttheme=PagrindinÄ— tema + +/modify_do.bml.colortheme.head=Spalvos tema + +/modify_do.bml.domainalias.about=Jei esate jau užregistravÄ™s domeino pavadinimÄ… (arba planuojate tai atlikti) ir pageidaujate automatiÅ¡kai patalpinti savo LiveJournal'Ä…, eikite Äia: + +/modify_do.bml.domainalias.domainname=Domeino pavadinimas + +/modify_do.bml.domainalias.example=Pavyzdys: mano-zurnalas.com + +/modify_do.bml.domainalias.head=Domeino sritys + +/modify_do.bml.domainalias.helptext<< +Å iam darbui Jums reikia užtikrinti, kad domeino pavadinimo DNS atitinka tÄ… patį IP adresÄ… kaip ir [[sitename]]. Daugiau informacijos žiÅ«rÄ—kite this FAQ. + +. + +/modify_do.bml.done.btn.savechanges=IÅ¡saugoti pakeitimus + +/modify_do.bml.done.head=Atlikta? + +/modify_do.bml.done.text=Pabaigus, paspauskite "IÅ¡saugoti pakeitimus" mygtukÄ… apaÄioje... + +/modify_do.bml.error.dupdomainalias=Kitas vartotojas jau užsiregistravÄ™s pasirinktÄ… domeino sritį. + +/modify_do.bml.error.stylenotavailable=Vienas iÅ¡ stilių, kurį pasirinkote, yra nepasiekiamas. Taip yra todÄ—l, kad kažkas iÅ¡trynÄ— stilių arba bandote pasirinkti stilių, kuriam neturite teisių. + +/modify_do.bml.friends.about=ÄŒia yra pasirinkimai, leidžiantys kontroliuoti kaip atrodo JÅ«sų draugų puslapis. + +/modify_do.bml.friends.head=Draugų peržiÅ«ra + +/modify_do.bml.friends.opt.usesharedpic.about=Å is pasirinkimas kontroliuoja kokį paveikslÄ—lį matote draugų puslapyje, kai vartotojas raÅ¡o bendrame arba bendruomenÄ—s žurnale. Jei pažymÄ—site jį, matysite bendruomenÄ—s paveikslÄ—lį. Jei paliksite nepažymÄ—tÄ…, matysite to asmens, kuris paraÅ¡Ä—, paveikslÄ—lį. + +/modify_do.bml.friends.opt.usesharedpic.head=Naudoti bendrus žurnalo paveikslÄ—lius vietoj vartotojo paveikslÄ—lių + +/modify_do.bml.journaloptions.about=IÅ¡ Äia galite tinkinti savo LiveJournal'o puslapių iÅ¡vaizdÄ….Jei Jums iÅ¡ tikrųjų smalsu, kaip viskas veikia, skaitykite informacija kÅ«rÄ—jams. Kitu atveju, mes užtikriname, kad liksite patenkinti baziniais pasirinkimais, pateiktais žemiau. + +/modify_do.bml.journaloptions.head=Žurnalo pasirinkimai + +/modify_do.bml.journalstatus.about=Jei norite iÅ¡trinti ar atstatyti savo žurnalÄ…, tai galite atlikti Äia. Jei iÅ¡trynÄ—te savo žurnalÄ…, turite 30 dienų atstatyti jį, jei apsigalvotumÄ—te. Po 30 dienų, žurnalas bus iÅ¡trintas viesiems laikams ir neturÄ—site galimybÄ—s jį atstatyti. + +/modify_do.bml.journalstatus.head=Žurnalo aktyvavimo bÅ«sena + +/modify_do.bml.journalstatus.select.activated=Aktyvuotas + +/modify_do.bml.journalstatus.select.deleted=IÅ¡trintas + +/modify_do.bml.journalstatus.select.head=BÅ«sena + +/modify_do.bml.journalstatus.select.suspended=Sustabdytas + +/modify_do.bml.moodicons.about=RaÅ¡ydami į žurnalÄ…, galite nurodyti dabartinÄ™ nuotaikÄ…. Skirtingi vartotojai yra nustatÄ™ skirtingus nuotaikų pieÅ¡inių rinkinius, kuriuos galite naudoti. Arba, pasirinkite "NÄ—ra", jei nenorite jokio pieÅ¡inÄ—lio Å¡alia savo nuotaikos. (arba galite iÅ¡vis nenaudoti DabartinÄ—s Nuotaikos funkcijos.) + +/modify_do.bml.moodicons.head=Nuotaikos pieÅ¡inÄ—liai + +/modify_do.bml.moodicons.opt.forcefriends.about=Primesti Å¡ia nuotaikos temÄ… visiems vartotojams JÅ«sų draugų puslapyje + +/modify_do.bml.moodicons.personal=AsmeninÄ—s temos: + +/modify_do.bml.moodicons.preview=peržiÅ«ra + +/modify_do.bml.moodicons.select=Pasirinkite nuotaikos pieÅ¡inÄ—lių rinkinį: + +/modify_do.bml.overrides.about<< +Jei esate patenkintas žurnalo schemos pasirinkimu virÅ¡uje, galite praleisti šį skirsnį. Jis skirtas patobulinti specifinius žurnalo schemos dalykus. ŽiÅ«rÄ—kite apžvalgÄ… Kas yra rankinis reguliavimas? Kaip jis veikia?a>, ir aplankykite kÅ«rÄ—jų skirsnis. Taip pat, įsidÄ—mÄ—kite, kad rankiniu reguliavimu galima valdyti tik vienÄ… ar dvi stiliaus funkcijas. Jei norite pakeisti viskÄ…, eikite sukurti savo stilių. Norint sukurti savo stilių, žiÅ«rÄ—kite Kaip sukurti savo nuosavÄ… stilių? + +. + +/modify_do.bml.overrides.box.head=Rankiniai reguliavimai: + +/modify_do.bml.overrides.head=Stiliaus rankiniai reguliavimai + +/modify_do.bml.overrides.note=PraÅ¡ome įsidÄ—mÄ—ti, kad ne visi stiliai gali bÅ«ti reguliuojami rankiniu bÅ«du. Daugiau informacijos žiÅ«rÄ—kite dokumentacija. .
          Taip pat, žinokite, kad jei naudosite žymas, keiÄiant rankinius nustatymus, kurių negalima naudoti dokumento antraÅ¡tÄ—je – tokias kaip <DIV>, <SPAN>, <IMG>, ir daugelį kitų žymų – Å¡ios žymos bus paÅ¡alintos. Tik tie HTML elementai, kuriuos galima naudoti *_HEAD rankiniame reguliavime yra veikiantys HTML dokumento antraÅ¡tÄ—je. Tai yra apribota <title>, <base>, <style>, <link>, and <meta> žymoms. + +/modify_do.bml.overrides.warning=TAI NE TA VIETA KUR RAÅ OTE SAVO ŽURNALÄ„!! + +/modify_do.bml.pagelayoutstyle.about=PasirinkÄ™ Å¡iÄ… funkcijÄ…, matysite kaip atrodo JÅ«sų žurnalas ekrane. + +/modify_do.bml.pagelayoutstyle.head=Puslapio Schemos Stilius + +/modify_do.bml.pagelayoutstyle.warning=Jums suteiktos teisÄ—s pasirinkti tik keletÄ… pagrindinių stilių. + +/modify_do.bml.success.head=Pavyko + +/modify_do.bml.success.text=JÅ«sų žurnalo nustatymai pakeisti. Galite peržiÅ«rÄ—ti savo žurnalÄ… Äia. + +/register.bml.new.update=Pakeisti žurnalÄ… -- RaÅ¡yti į JÅ«sų žurnalÄ… + +/styles/index.bml.nav.browse=Stilių PeržiÅ«ra + +/talkmulti.bml.deleted.body=Kometarai iÅ¡trinti. Likusį pokalbį galite skaityti Äia. + +/talkmulti.bml.deleted.title=Komentarai iÅ¡trinti + +/talkmulti.bml.error.comms_deleted=Vienas iÅ¡ komentarų buvo iÅ¡trintas po to, kai jį pasirinkote. Atsargumo sumetimais, praÅ¡ome sugrįžti atgal ir pabandyti dar kartÄ…. + +/talkmulti.bml.error.inconsistent_data=Pateikti duomenis yra nepilni. + +/talkmulti.bml.error.invalid=Nurodytas blogas parametras. + +/talkmulti.bml.error.invalid_mode=Jus nepasirinkote jokios operacijos. PraÅ¡ome sugrįžti ir pasirinkti - ar norite paslÄ—pti, rodyti, ar iÅ¡trinti komentarus. + +/talkmulti.bml.error.login=JÅ«s nesate prisijungÄ™s. + +/talkmulti.bml.error.none_selected=JÅ«s nepasirinkote jokių komentarų. + +/talkmulti.bml.error.privs.delete=JÅ«s neturite teisių iÅ¡trinti Å¡iuos komentarus. + +/talkmulti.bml.error.privs.screen=JÅ«s neturite teisių paslÄ—pti Å¡iuos komentarus. + +/talkmulti.bml.error.privs.unscreen=JÅ«s neturite teisių parodyti Å¡iuos komentarus. + +/talkmulti.bml.screened.body=Komentarai paslÄ—pti. Galite juos peržiÅ«rÄ—ti Äia. + +/talkmulti.bml.screened.title=Komentarai paslÄ—pti. + +/talkmulti.bml.title.delete=IÅ¡trinti komentarų grupÄ™ + +/talkmulti.bml.title.screen=PaslÄ—pti komentarų grupÄ™ + +/talkmulti.bml.title.unscreen=Rodyti komenratų grupÄ™ + +/talkmulti.bml.unscreened.body=Komentarai bus rodomi. PažiÅ«rÄ—ti juos galite Äia. + +/talkmulti.bml.unscreened.title=Komentarai bus rodomi + +/talkpost.bml.allowedhtml=Leistini HTML kodai + +/talkpost.bml.error.cannotreplynopost=JÅ«s negalite atsakyti į neegzistuojantį praneÅ¡imÄ… + +/talkpost.bml.error.nocommentsjournal=Vartotojas iÅ¡jungÄ— galimybÄ™ komentuotį savo įraÅ¡us. + +/talkpost.bml.error.nocommentspost=Vartotojas iÅ¡jungÄ— galimybÄ™ komentuotį šį įraÅ¡Ä…. + +/talkpost.bml.error.noreplypost=PraneÅ¡imas, į kurį atsakote, nerastas (iÅ¡trintas?) + +/talkpost.bml.error.noreply_deleted=Å is komentaras iÅ¡trintas. JÅ«s negalite į jį atsakyti. + +/talkpost.bml.error.noreply_screened=Å is komentaras yra paslÄ—ptas, ir JÅ«s neturite teisių jį matyti arba į jį atsakyti. + +/talkpost.bml.label.picturetouse=Naudoti paveikslÄ—lį: + +/talkpost.bml.loganonip=Atkreipkite dÄ—mesį! Å is vartotojas įjungÄ— nustatymÄ…, kuris iÅ¡saugoja anoniminių atsakovų IP adresus. + +/talkpost.bml.loginq=Prisijungti? + +/talkpost.bml.logyourip=Atkreipkite dÄ—mesį! Å is vartotojas įjungÄ— nustatymÄ…, kuris iÅ¡saugoja IP adresÄ… iÅ¡ kurio atsakote. + +/talkpost.bml.nosubjecthtml=Negalima naudoti HTML praneÅ¡imo temoje + +/talkpost.bml.opt.anonymous=Anonimas + +/talkpost.bml.opt.defpic=(pagal nutylÄ—jimÄ…) + +/talkpost.bml.opt.friendsonly=- Å¡is vartotojas iÅ¡jungÄ— galimybÄ™ atsakinÄ—ti anonimams ir ne-draugams. JÅ«s galÄ—tumÄ—t raÅ¡yti Äia, jei [[username]] įtrauktų Jus į draugų sÄ…raÅ¡Ä…. + +/talkpost.bml.opt.from=Nuo: + +/talkpost.bml.opt.ljuser=LiveJournal vartotojas: + +/talkpost.bml.opt.loggedin=PrisijungÄ™s vartotojas: [[username]] + +/talkpost.bml.opt.message=PraneÅ¡imas: + +/talkpost.bml.opt.noanonpost=- Å¡is vartotojas iÅ¡jungÄ— galimybÄ™ atsakinÄ—ti anonimiÅ¡kai. + +/talkpost.bml.opt.noautoformat=Neformatuoti automatiÅ¡kai: + +/talkpost.bml.opt.noimage=Be paveiksliuko + +/talkpost.bml.opt.preview=PeržiÅ«ra + +/talkpost.bml.opt.spellcheck=PrieÅ¡ iÅ¡saugant patikrinti raÅ¡ybÄ… + +/talkpost.bml.opt.subject=Tema: + +/talkpost.bml.opt.submit=IÅ¡saugoti komentarÄ… + +/talkpost.bml.opt.willscreen=(bus paslÄ—ptas) + +/talkpost.bml.opt.willscreenfriend=(bus pasleptas, jei nesate draugas) + +/talkpost.bml.paraformat=Pagal nutylÄ—jimÄ… paragrafai bus formatuojami automatiÅ¡kai + +/talkpost.bml.title=Palikti komentarÄ… + +/talkpost.bml.usermismatch<< +JÅ«s įvedÄ—te vartotojo vardÄ…, bet nepasirinkote "LJ vartotojas" atsakymo bÅ«do. + +PraÅ¡ome arba iÅ¡valyti laukÄ… su vartotojo vardu, arba pasirinkti kitÄ… iÅ¡saugojimo bÅ«dÄ…. +. + +/talkpost.bml.warnscreened=Atkreipkite dÄ—mesį! Å is komentaras yra paslÄ—ptas. AtsakinÄ—dami į jį, JÅ«s automatiÅ¡kai darote jį matomu. + +/talkpost_do.bml.error.badpassword=Neteisingas slaptažodis nurodytam vartotojo vardui. Jei JÅ«s pamirÅ¡ote savo slaptažodį, galite atstatyti jį Äia. + +/talkpost_do.bml.error.badusername=JÅ«sų nurodytas LJ vartotojo vardas neegzistuoja.Jei JÅ«s pamirÅ¡ote savo vartotojo vardÄ…, galite atstatyti jį Äia, arba galite raÅ¡yti kaip "Anonimas". + +/talkpost_do.bml.error.banned=JÅ«s negalite raÅ¡yti į Å¡io vartotojo žurnalÄ…. + +/talkpost_do.bml.error.blankmessage=JÅ«sų praneÅ¡imas buvo tuÅ¡Äias. ParaÅ¡ykite kÄ… nors bent jau temos lauke. + +/talkpost_do.bml.error.confused_identity=JÅ«s įvedÄ—te vartotojo vardÄ…, bet pasirinkote paraÅ¡yti anonimiÅ¡kai arba kaip Å¡iuo metu įsijungÄ™s vartotojas. Sugrįžkite ir apsisprÄ™skite, kÄ… iÅ¡ tikrųjų norite padaryti. + +/talkpost_do.bml.error.deleted=JÅ«sų žurnalas iÅ¡trintas. JÅ«s negalite raÅ¡yti praneÅ¡imų. + +/talkpost_do.bml.error.friendsonly=Tik vartotojo [[user]] draugai gali raÅ¡yti į šį žurnalÄ…. + +/talkpost_do.bml.error.lostcookie=Atrodo, kad JÅ«sų prisijungimo slapukas dingo? + +/talkpost_do.bml.error.manybytes=AtsipraÅ¡ome, bet JÅ«sų komentaras yra [[current]] ilgio ir virÅ¡yja maksimalų leistinÄ… ilgį ( [[limit]] baitų). PraÅ¡ome sugrįžti, sutrumpinti jį, ir pabandyti iÅ¡saugoti dar kartÄ…. + +/talkpost_do.bml.error.manychars=AtsipraÅ¡ome, bet JÅ«sų komentaras yra [[current]] simbolių ilgio ir virÅ¡yja maksimalų leistinÄ… ilgi - [[limit]] simbolių. PraÅ¡ome sugrįžkti , sutrumpinti jį, ir pabandyti iÅ¡saugoti dar kartÄ…. + +/talkpost_do.bml.error.mustlogin=JÅ«s turite bÅ«ti prisijungÄ™s arba naudoti vartotojo vardÄ…/slaptažodį tam, kad atsakyti į šį uždarytÄ… praneÅ¡imÄ…. + +/talkpost_do.bml.error.noanon=JÅ«s negalite raÅ¡yti anonimiÅ¡kai į Å¡io asmens žurnalÄ…. + +/talkpost_do.bml.error.noauth=Jus neturite teisių atsakinÄ—ti į šį uždarytÄ… praneÅ¡imÄ…. + +/talkpost_do.bml.error.nocomments=Vartotojas iÅ¡jungÄ— galimybÄ™ komentuoti šį įraÅ¡Ä… + +/talkpost_do.bml.error.noparent=Negalite atsakyti į neegzistuojantį komentarÄ…. + +/talkpost_do.bml.error.notafriend=AtsipraÅ¡ome, vartotojas [[user]] neįtraukÄ— JÅ«sų į draugų sÄ…raÅ¡Ä…, ir įjungÄ— nustatymÄ…, leidžiantį tik draugams atsakinÄ—ti savo žurnale. + +/talkpost_do.bml.error.nousername=JÅ«s neįvedÄ—te savo LJ vartotojo vardo. JÅ«s galite paraÅ¡yti kaip "Anonimas", jei neturite savo žurnalo. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=AtsipraÅ¡ome, JÅ«s negalite raÅ¡yti į kitų žmonių žurnalus, kol JÅ«sų elektroninio paÅ¡to adresas nebus patikrintas. Jei JÅ«s praradote patvirtinimo laiÅ¡kÄ…, JÅ«s galite atsisiųsti jį iÅ¡ prarastos informacijos puslapio. + +/talkpost_do.bml.error.screened=JÅ«s neturite teisių atsakyti į šį paslÄ—ptÄ… komentarÄ…. + +/talkpost_do.bml.error.suspended=JÅ«sų žurnalas laikinai sustabdytas. JÅ«s negalite raÅ¡yti praneÅ¡imų. + +/talkpost_do.bml.error.testacct=Testiniai profiliai gali bÅ«ti naudojami tik testinių profilių žurnaluose. + +/talkpost_do.bml.opt.preview=PeržiÅ«ra + +/talkpost_do.bml.preview=Å tai kaip JÅ«sų komentaras atrodys, kai bus iÅ¡saugotas. Naudojant formÄ… žemiau, JÅ«s galite toliau redaguoti savo komentarÄ…, arba nusiųsti jį kaip yra. + +/talkpost_do.bml.preview.subject=Tema: + +/talkpost_do.bml.preview.submit=Siųsti + +/talkpost_do.bml.preview.title=PeržiÅ«ra + +/talkpost_do.bml.success.loggedin=Dabar JÅ«s esate prisijungÄ™s. + +/talkpost_do.bml.success.message=JÅ«su komentaras iÅ¡saugotas. Galite peržiÅ«rÄ—ti jį Äia. + +/talkpost_do.bml.success.screened.comm=JÅ«sų komentaras buvo iÅ¡saugotas. Pagal Å¡ios benduomenÄ—s nustatymus, jis buvo pažymÄ—tas kaip paslÄ—ptas, ir bus matomas tik Jums ir žmonÄ—ms, palaikantiems bendruomenÄ™, kol jie nenutars jo parodyti. Savo komentarÄ… galite pažiÅ«rÄ—ti Äia. + +/talkpost_do.bml.success.screened.comm.anon=JÅ«sų anonimiÅ¡kas komentaras buvo iÅ¡saugotas. Pagal Å¡ios benduomenÄ—s nustatymus jis buvo pažymÄ—tas kaip paslÄ—ptas, ir bus matomas tik žmonÄ—ms, palaikantiems bendruomenÄ™, kol jie nenutars jo parodyti. Prie kitų komentarų galite sugrįžti Äia. + +/talkpost_do.bml.success.screened.user=JÅ«sų komentaras buvo iÅ¡saugotas. Pagal Å¡io žurnalo nustatymus jis buvo pažymÄ—tas kaip paslÄ—ptas, ir bus matomas tik Jums ir žurnalo savininkui, kol jis nenutars jo parodyti. Savo komentarÄ… galite pažiÅ«rÄ—ti Äia. + +/talkpost_do.bml.success.screened.user.anon=JÅ«sų anonimiÅ¡kas komentaras buvo iÅ¡saugotas. Pagal Å¡io žurnalo nustatymus jis buvo pažymÄ—tas kaip paslÄ—ptas, ir bus matomas tik žurnalo savininkui, kol jis nenutars jo parodyti. Prie kitų komentarų galite sugrįžti Äia. + +/talkpost_do.bml.success.title=Pavyko + +/talkpost_do.bml.success.unscreened=Taip pat, paslÄ—ptas komentaras, į kurį JÅ«s atsakinÄ—jote, buvo atidengtas, ir tapo matomu. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Komentaras iÅ¡saugotas + +/talkpost_do.bml.title.preview=Komentaro peržiÅ«ra + +/talkread.bml.anonuser=(Anonimas) + +/talkread.bml.confirm.action=Ar tikrai norite iÅ¡trinti pasirinktus komentarus? + +/talkread.bml.deletedpost=(IÅ¡trintas įraÅ¡as) + +/talkread.bml.deleteduser=(IÅ¡trintas vartotojas: [[username]]) + +/talkread.bml.fromip=(iÅ¡ [[ip]]) + +/talkread.bml.noreplies=NÄ—ra atsakymų + +/talkread.bml.nosubject=(be temos) + +/talkread.bml.replysuspended=(Atsakymas nuo laikinai atjungto vartotojo) + +/talkread.bml.screenedpost=(PaslÄ—ptas įraÅ¡as) + +/talkread.bml.select=Pasirinkti + +/talkread.bml.subjectdeleted=[iÅ¡trinta] + +/talkread.bml.talkmulti.delete=IÅ¡trinti + +/talkread.bml.talkmulti.des=GrupinÄ— operacija su visais pasirintais komentarais: + +/talkread.bml.talkmulti.screen=PaslÄ—pti + +/talkread.bml.talkmulti.submit=Atlikti operacijÄ… + +/talkread.bml.talkmulti.unscreen=Rodyti + +/talkread.bml.title=Skaityti komentarus + +/talkscreen.bml.error.login=JÅ«s turite įsijungti tam kad dirbti su pasleptais komentarais. + +/talkscreen.bml.error.privs.screen=JÅ«s neturite teisių paslÄ—pti šį komentarÄ…. + +/talkscreen.bml.error.privs.unscreen=JÅ«s neturite teisių parodyti šį komentarÄ…. + +/talkscreen.bml.screen.doit=Taip, paslÄ—pti šį komentarÄ… + +/talkscreen.bml.screen.sure.body=Ar tikrai norite paslÄ—pti šį komentarÄ…? + +/talkscreen.bml.screen.sure.title=PaslÄ—pti šį komentarÄ…? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=Komentaras paslÄ—ptas. + +/talkscreen.bml.screened.title=SÄ—kmÄ— + +/talkscreen.bml.title=PaslÄ—ptas komentaras + +/talkscreen.bml.unscreen.doit=Taip, rodyti šį komentarÄ… + +/talkscreen.bml.unscreen.sure.body=Ar tikrai norite rodyti šį komentarÄ…? + +/talkscreen.bml.unscreen.sure.title=Rodyti šį komentarÄ…? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=Komentaras bus rodomas. + +/talkscreen.bml.unscreened.title=SÄ—kmÄ— + +/update.bml.altpost=Ä®raÅ¡yti į žurnalÄ… + +/update.bml.btn.update=Pakeisti žurnalÄ… + +/update.bml.currmood=Mano Nuotaika: + +/update.bml.currmusic=Dabar klausau + +/update.bml.date=Data + +/update.bml.default=Pagal nutylÄ—jimÄ… + +/update.bml.defaultjournal=([[user]]) -- pagal nutylÄ—jimÄ… + +/update.bml.error.login=Klaida įsijungiant + +/update.bml.error.update=Klaida keiÄiant žurnalÄ… + +/update.bml.event=Ä®vykis + +/update.bml.full=VisiÅ¡kai pakeisti puslapį + +/update.bml.localtime=Vietos laikas + +/update.bml.loggingin=Prisijungimas prie serverio + +/update.bml.noneother=Nieko, arba kita + +/update.bml.note=Pastaba. VirÅ¡uje nurodytas laikas ir data yra iÅ¡ mÅ«sų serverio. Pataisykite pagal JÅ«sų laiko juosta prieÅ¡ iÅ¡siunÄiant + +/update.bml.opt.backdate=AtgalinÄ—s datos įraÅ¡as: + +/update.bml.opt.backdate.about=nebus rodoma draugų puslapyje + +/update.bml.opt.defpic=Pagal nutylÄ—jimÄ… + +/update.bml.opt.nocomments=Neleisti komentuoti: + +/update.bml.opt.noemail=Nesiųsti komentarų el. paÅ¡tu: + +/update.bml.opt.noformat=AutomatiÅ¡kai neformatuoti: + +/update.bml.opt.spellcheck=Patikrinti raÅ¡ybÄ… prieÅ¡ iÅ¡siunÄiant + +/update.bml.options=Neprivalomi nustatymai + +/update.bml.other=Kita + +/update.bml.picture=Naudoti paveikslÄ—lį: + +/update.bml.security.custom=Pasirinktinai + +/update.bml.security.friends=Draugai + +/update.bml.security.head=Apsaugos lygis + +/update.bml.security.private=Privatus + +/update.bml.security.public=VieÅ¡as + +/update.bml.servermsg=Taigi, serverio žinutÄ— Jums: + +/update.bml.simple=JÅ«s žiÅ«rite paprastÄ… puslapį. Didesniam pasirinkimui, spauskite Äia. + +/update.bml.spellchecked=Patikrintas JÅ«sų įraÅ¡as: + +/update.bml.subject=Tema: (nebÅ«tina) + +/update.bml.timeformat=24 valandų laikas + +/update.bml.title=Pakeisti žurnalÄ… + +/update.bml.title.readonly=Tik skaitymui + +/update.bml.update.head=Pakeisti žurnalÄ… + +/update.bml.update.success=Pakeitimai sÄ—kmingi. Galite pamatyti savo žurnalo pakeitimus Äia. + +/update.bml.updating=Žurnalas keiÄiamas... + +/userinfo.bml.about.comm=Apie: + +/userinfo.bml.about.user=Biografija: + +/userinfo.bml.body.leave=Galite palikti bendruomenÄ™ bet kuriuo metu. + +/userinfo.bml.comminfo.body=Žemiau yra pateikta informacija apie "[[commname]]" LiveJournal'o bendruomenÄ™ . + +/userinfo.bml.comminfo.name=BendruomenÄ—s informacija + +/userinfo.bml.date.never=Niekada. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=IÅ¡kraipytas vartotojo vardas. + +/userinfo.bml.error.notloggedin=Jei norite peržiÅ«rÄ—ti savo vartotojo profilį, turite prisijungti. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Stebi: + +/userinfo.bml.friendof.hidden=(paslÄ—pta) + +/userinfo.bml.friendof.syndreadcount=Skaitytojų skaiÄius + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Draugaujantys: + +/userinfo.bml.friends.comm=Nariai + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Draugai + +/userinfo.bml.label.addbuddy=Ä®kelti biÄiulį + +/userinfo.bml.label.adduser=Ä®kelti vartotojÄ… + +/userinfo.bml.label.birthdate=Gimimo data: + +/userinfo.bml.label.clientsused=Klientas naudojamas: + +/userinfo.bml.label.comments=Komentarai: + +/userinfo.bml.label.composted=IÅ¡siųsta: [[num]] - + +/userinfo.bml.label.comreceived=Gauta: [[num]] + +/userinfo.bml.label.datecreated=SukÅ«rimo data: + +/userinfo.bml.label.dateupdated=Pakeitimo data: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=El. paÅ¡tas: + +/userinfo.bml.label.interests=PomÄ—giai + +/userinfo.bml.label.interests.modifyyours=Pakeisti jÅ«sų + +/userinfo.bml.label.interests.removesome=PaÅ¡alinti kai kÄ… + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] nerodyti pomÄ—gių + +/userinfo.bml.label.journalentrs=Žurnalo įraÅ¡ai: + +/userinfo.bml.label.location=Vieta: + +/userinfo.bml.label.memberof=Narys + +/userinfo.bml.label.memories=AtmintinÄ—s: + +/userinfo.bml.label.moredetails=(plaÄiau...) + +/userinfo.bml.label.msnusername=MSN vartotojas: + +/userinfo.bml.label.name=Vardas: + +/userinfo.bml.label.nofriends=TuÅ¡Äias sÄ…raÅ¡as. + +/userinfo.bml.label.post=IÅ¡siųsti į "[[journal]]" + +/userinfo.bml.label.postalt=Pakeisti JÅ«sų žurnalÄ… + +/userinfo.bml.label.reqfinduser=Tik vartotojai su 'rasti vartotojÄ…' privilegija gali ieÅ¡koti vartotojų pagal varotojo id. + +/userinfo.bml.label.sendmessage=Siųsti žinutÄ™ + +/userinfo.bml.label.shared=Siuntimo galimybÄ—: + +/userinfo.bml.label.supportpoints=Palaikymo klausimai + +/userinfo.bml.label.syndicatedfrom=Sindikuotas nuo: + +/userinfo.bml.label.syndicatedstatus=Sindikato bÅ«sena: + +/userinfo.bml.label.textmessage=Tekstas
          Žinutė
          : + +/userinfo.bml.label.todo=Reikalų sÄ…raÅ¡as + +/userinfo.bml.label.user=Vartotojas: + +/userinfo.bml.label.viewfriends=ŽiÅ«rÄ—ti draugus + +/userinfo.bml.label.viewmembers=ŽiÅ«rÄ—ti narius + +/userinfo.bml.label.website=Puslapis internete: + +/userinfo.bml.membership.body=Norint prisijungti prie Å¡ios bendruomenÄ—s, spauskite Äia. + +/userinfo.bml.memories.entries=[[count]] įraÅ¡ai + +/userinfo.bml.memories.entry=[[count]] įraÅ¡as + +/userinfo.bml.monitor.comm=StebÄ—ti bendruomenÄ™ + +/userinfo.bml.monitor.user=Ä®traukti šį vartotojÄ… į draugų sÄ…raÅ¡Ä… + +/userinfo.bml.nonexist.body=Vartotojo vardas [[user]] Å¡iuo metu neregistruotas. + +/userinfo.bml.nonexist.name=Nežinomas vartotojas + +/userinfo.bml.sendmessage.body=Siųsti [[user]] tekstinÄ™ žinutÄ™
          į jo/jos mobilų telefonÄ…/praneÅ¡imų gaviklį. + +/userinfo.bml.syn.last.never=Niekada + +/userinfo.bml.syn.lastcheck=Paskutinįkart tikrinta: + +/userinfo.bml.syn.nextcheck=Kitas patikrinimas: + +/userinfo.bml.syn.parseerror=Klaidos praneÅ¡imas: + +/userinfo.bml.syndinfo.body=Jei pageidaujate, kad straipsniai iÅ¡ sindikuoto varotojo bÅ«tų matomi draugų puslapyje, JÅ«s galite įkelti šį žurnalÄ… į jÅ«sų draugų sÄ…raÅ¡Ä…. + +/userinfo.bml.syndinfo.name=Sindikuotas žurnalas + +/userinfo.bml.tellafriend=Pasakyk draugui! + +/userinfo.bml.timeupdate.dayago=PrieÅ¡ 1 dienÄ… + +/userinfo.bml.timeupdate.daysago=PrieÅ¡ [[num]] dienų + +/userinfo.bml.timeupdate.hourago=Prięš 1 valandÄ… + +/userinfo.bml.timeupdate.hoursago=PrieÅ¡ [[num]] valandų + +/userinfo.bml.timeupdate.minuteago=PrieÅ¡ 1 minutÄ™ + +/userinfo.bml.timeupdate.minutesago=PrieÅ¡ [[num]] minuÄių + +/userinfo.bml.timeupdate.secondago=PrieÅ¡ 1 sekundÄ™ + +/userinfo.bml.timeupdate.secondsago=PrieÅ¡ [[num]] sekundžių + +/userinfo.bml.timeupdate.weekago=PrieÅ¡ 1 savaitÄ™ + +/userinfo.bml.timeupdate.weeksago=PrieÅ¡ [[num]] savaites + +/userinfo.bml.title=Informacija apie vartotojÄ… + +/userinfo.bml.title.communityinfo=Informacija apie bendruomenÄ™ + +/userinfo.bml.title.syndicated=Sindikuotas vartotojas + +/userinfo.bml.userinfo.body=Žemiau yra vartotojo informacija skirta [[username]]. Jei esate Å¡is vartotojas, galite pakeisti informacijÄ… (arba pasirinkti kokia informacija yra vieÅ¡a) Pakeisti informacijÄ…. + +/userinfo.bml.userinfo.name=Vartotojo informacija + +btn.search=IeÅ¡koti + +dystopia.nav.logout=Atsijungti + +dystopia.nav.siteopts=NarÅ¡ymo Nustatymai + +dystopia.search.icq=ICQ Numeris + +dystopia.search.int=PomÄ—gis + +dystopia.search.msn=MSN Vartotojas + +dystopia.search.region=Regionas + +error.noremote=Kad nautotis puslapiu, visų pirma reikia prisijungti. + +langname.be=Baltarusų + +langname.da=Danų + +langname.de=VokieÄių + +langname.en=Anglų + +langname.en_GB=Anglų (UK) + +langname.en_LJ=Anglų (LJ) + +langname.eo=esperanto + +langname.es=Ispanų + +langname.et=Estų + +langname.fi=Suomių + +langname.fr=PrancÅ«zų + +langname.ga=Airių + +langname.gd=GÄ—lų + +langname.he=Hebrajų + +langname.hu=Vengrų + +langname.is=Islandų + +langname.it=Italų + +langname.ja=Japonų + +langname.la=Lotynų + +langname.lv=Latvių + +langname.ms=Malajų + +langname.nb=Norvegų BokmÃ¥l + +langname.nl=Olandų + +langname.nn=Norvegų, Nynorsk + +langname.pl=Lenkų + +langname.pt=Portugalų + +langname.ru=Rusų + +langname.sv=Å vedų + +langname.tr=Turkų + +langname.uk=UkrainieÄių + +langname.zh=KinieÄių Supaprastinta + +portal.login.portalname=Prisijungimas + +talk.anonwrote=Kažkas paraÅ¡Ä—, + +talk.anonwrote_comm=Kažkas paraÅ¡Ä— bendruomenÄ—je [[commlink]], + +talk.btn.preview=PeržiÅ«ra + +talk.commentpermlink=nuoroda + +talk.commentpost=RaÅ¡yti naujÄ… komentarÄ… + +talk.commentsread=Skaityti komentarus + +talk.curname_Mood=Nuotaika: + +talk.curname_Music=Dabar groja: + +talk.error.bogusargs=Neteisingi parametrai + +talk.error.comm_deleted=Å is komentaras iÅ¡trintas. + +talk.error.deleted=Å is žurnalas iÅ¡trintas. + +talk.error.deleted.title=IÅ¡trinta + +talk.error.mustlogin=JÅ«s turite bÅ«ti prisijungÄ™s tam, kad skaityti šį uždarÄ… praneÅ¡imÄ…. + +talk.error.nocomment=Å is komentaras neegzistuoja. + +talk.error.noentry=NÄ—ra tokio praneÅ¡imo. + +talk.error.nojournal=Klaida: neįmanoma nustatyti žurnalÄ… pagal parametrus. + +talk.error.nosuchjournal=NÄ—ra tokio žurnalo + +talk.error.notauthorised=Jums neleidžiama skaityti Å¡io uždaro įraÅ¡o. + +talk.error.suspended=Å is žurnalas laikinai sustabdytas. + +talk.parentlink=Vienu lygių aukÅ¡Äiau + +talk.readsimilar=Skaityti panaÅ¡ius įraÅ¡us: + +talk.replytothis=Atsakyti į šį komentarÄ… + +talk.somebodywrote=[[realname]] ([[userlink]]) paraÅ¡Ä—, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) paraÅ¡Ä— bendruomenÄ—je [[commlink]], + +talk.spellcheck=Tikrinti raÅ¡ybÄ… peržiÅ«rint praneÅ¡imÄ… + +talk.threadlink=Pokalbis pradÄ—dant Å¡iuo komentaru + +xcolibur.greeting.anon=Sveiki atvykÄ™ į LiveJournal! + +xcolibur.greeting.logged_in=Labas, [[name]]! [[logout]] + +xcolibur.login=Prisijungti? + +xcolibur.logout=Atsijungti? + +xcolibur.nav.about=Apie + +xcolibur.nav.about.download=Parsisiųsti + +xcolibur.nav.about.general=Bendra Informacija + +xcolibur.nav.about.paidaccounts=Mokami Vartotojai + +xcolibur.nav.about.press=Spauda + +xcolibur.nav.about.sitenews=SvietainÄ—s Naujienos + +xcolibur.nav.about.stats=Statistika + +xcolibur.nav.footer.sitemap=SvietainÄ—s ŽemÄ—lapis + +xcolibur.nav.help=Pagalba + +xcolibur.nav.help.ask=Užduoti KlausimÄ… + +xcolibur.nav.help.contact=Kontaktai + +xcolibur.nav.help.faq=DUK + +xcolibur.nav.help.lostpassword=PamirÅ¡tas Slaptažodis + +xcolibur.nav.home=Pradinis + +xcolibur.nav.journal=Žurnalas + +xcolibur.nav.journal.archive=Archyvas + +xcolibur.nav.journal.edit.entries=Redaguoti Ä®raÅ¡us + +xcolibur.nav.journal.friends=Draugai + +xcolibur.nav.journal.info=Informacija + +xcolibur.nav.journal.memories=Atmintini Ä®raÅ¡ai + +xcolibur.nav.journal.recent=Naujausi + +xcolibur.nav.journal.update=Atnaujinti + +xcolibur.nav.manage=Redaguoti + +xcolibur.nav.manage.community=BendruomenÄ—s + +xcolibur.nav.manage.customize=Nustatymus + +xcolibur.nav.manage.entries=Ä®raÅ¡us + +xcolibur.nav.manage.friends=Draugus + +xcolibur.nav.manage.info=InformacijÄ… + +xcolibur.nav.manage.password=Slaptažodį + +xcolibur.nav.manage.pics=PaveikslÄ—lius + +xcolibur.nav.manage.styles=Stiliai + +xcolibur.nav.search=PaieÅ¡ka + +xcolibur.nav.search.directory=Pagal RegionÄ… + +xcolibur.nav.search.directory.search=IÅ¡plÄ—stinÄ— + +xcolibur.nav.search.interests=Pagal PomÄ—gius + +xcolibur.nav.search.random=Atsitiktinis + +xcolibur.nav.siteopts=NarÅ¡ymo Nustatymai + +xcolibur.nav.title=Navigacija: + +xcolibur.nav.welcome=Sveiki AtvykÄ™ + +xcolibur.nav.welcome.create=Sukurti VartotojÄ… + +xcolibur.nav.welcome.login=Prisijungti + +xcolibur.nav.welcome.update=Atnaujinti Savo ŽurnalÄ… + +xcolibur.search=PaieÅ¡ka: + +xcolibur.search.category=Kategorija: + +xcolibur.search.icq=ICQ Numeris + +xcolibur.search.int=PomÄ—gis + +xcolibur.search.msn=MSN Vartotojas + +xcolibur.search.region=Regionas + +xcolibur.upgrade=Tapti Mokamu Vartotoju + diff --git a/ljcom/bin/upgrading/lv.dat b/ljcom/bin/upgrading/lv.dat new file mode 100644 index 0000000..a9dd09b --- /dev/null +++ b/ljcom/bin/upgrading/lv.dat @@ -0,0 +1,865 @@ +;; -*- coding: utf-8 -*- +/allpics.bml.current=EsoÅ¡Äs bildes + +/allpics.bml.default=Pamatbilde + +/allpics.bml.error.noparam=LÅ«dzu precizÄ“ lietotÄja parametru. + +/allpics.bml.keywords=AtslÄ“gas vÄrdi: + +/allpics.bml.nopics.title=Nav bilžu + +/allpics.bml.pics=Å Ä«s ir [[user]] bildes. + +/allpics.bml.title=LietotÄjbildes + +/community/index.bml.title=Kopienas centrs + +/community/join.bml.button.join=Pievienoties kopienai + +/community/join.bml.label.addtofriends=Pievieno "[[maintainer]]" draugu sarakstam.
          + +/community/join.bml.label.allowposting=Å Ä« kopiena atļauj rakstÄ«t visiem tÄs biedriem, tÄtad tagad arÄ« tev ir dota atļauja. Ja uz tava datora jau ir atvÄ“rta LJ programma, tev vajadzÄ“s no tÄs iziet un vÄ“lreiz iereÄ£istrÄ“ties, lai Å¡is žurnÄls parÄdÄ«tos to žurnÄlu sarakstÄ, kuros tu vari rakstÄ«t. + +/community/join.bml.label.banned=Å Ä«s kopienas uzturÄ“tÄjs nav atļÄvis tev pievienoties kopienai. + +/community/join.bml.label.commlogged=Tu esi piereÄ£istrÄ“jies ar kopienas kontu, nevis ar savu personÄ«go kontu. + +/community/join.bml.label.errorcomminfo=DotÄ kopienas informÄcija nav derÄ«ga. + +/community/join.bml.label.expls=Spied sekojoÅ¡o pogu, lai pievienotos "[[maintainer]]" kopienai. NeatzÄ«mÄ“ lodziņu, ja gribi pievienoties kopienai bet neredzÄ“t kopienas žurnÄla ierakstus savÄ draugu lapÄ. + +/community/join.bml.label.loginfirst=Lai pievienotos kopienai, tev vispirms ir jÄreÄ£istrÄ“jas. + +/community/join.bml.label.membernow=Tu tagad esi [[commname]] kopienas biedrs + +/community/join.bml.label.sure=Vai esi pÄrliecinÄts? + +/community/join.bml.success=IzdoÅ¡anÄs + +/community/join.bml.title=Pievienojies kopienai + +/community/leave.bml.button.leave=IzstÄjies no kopienas + +/community/leave.bml.label.buttontoleave=Spied sekojoÅ¡o pogu, lai izstÄtos no "[[commname]]" kopienas. + +/community/leave.bml.label.infoerror=DotÄ kopienas informÄcija nav derÄ«ga. + +/community/leave.bml.label.logoutfirst=Lai izstÄtos no kopienas, tev vispirms ir jÄpiereÄ£istrÄ“jas. + +/community/leave.bml.label.removed=Tu tagad esi izstÄjies no [[commname]] kopienas + +/community/leave.bml.success=IzdoÅ¡anÄs + +/community/leave.bml.sure=Vai esi pÄrliecinÄts? + +/community/leave.bml.title=IzstÄjies no kopienas + +/community/search.bml.button.clear=NodzÄ“st + +/community/search.bml.button.search=MeklÄ“! + +/community/search.bml.checkbox.onlywithpics=Tikai kopienas ar bildÄ“m + +/community/search.bml.label.byinterest=PÄ“c interesÄ“m + +/community/search.bml.label.bylocation=PÄ“c atraÅ¡anÄs vietas + +/community/search.bml.label.bytime=PÄ“c žurnÄla pÄ“dÄ“jÄ ieraksta izdarÄ«Å¡anas laika + +/community/search.bml.label.city=PilsÄ“ta: + +/community/search.bml.label.country=Valsts: + +/community/search.bml.label.displayoptions= Tavas iespÄ“jas + +/community/search.bml.label.hasmember=Ir biedrs + +/community/search.bml.label.othercriteria=Citi kritÄ“riji + +/community/search.bml.label.outputformat=Izvades formÄts: + +/community/search.bml.label.records=Ieraksti uz vienas lapas: + +/community/search.bml.label.searchcomm=MeklÄ“t kopienas + +/community/search.bml.label.selecriteria=IzvÄ“lies sekojoÅ¡os kritÄ“rijus, pÄ“c kuriem tu vÄ“lies atrast kopienas. RezultÄti bÅ«s visu meklÄ“Å¡anas kritÄ“riju kopsumma. Citiem vÄrdiem sakot, katrs iezÄ«mÄ“tais lodziņš nozÄ«mÄ“ "AND" vai "OR". + +/community/search.bml.label.sortmethod=KÄrtoÅ¡anas metode: + +/community/search.bml.label.stateprovince=Pavalsts/province: + +/community/search.bml.label.updated=IzdarÄ«ts ieraksts pÄ“dÄ“jÄs + +/community/search.bml.sel.bypicture=PÄ“c bildes + +/community/search.bml.sel.communityname=Kopienas nosaukums + +/community/search.bml.sel.commview=Kopienas skats + +/community/search.bml.sel.day=diena + +/community/search.bml.sel.month=mÄ“nesis + +/community/search.bml.sel.simple=VienkÄrÅ¡i + +/community/search.bml.sel.updatetime=PÄ“dÄ“jÄ ieraksta laiks + +/community/search.bml.sel.username=LietotÄja vÄrds + +/community/search.bml.sel.week=nedēļa + +/community/search.bml.title=Kopienas meklÄ“Å¡ana + +/create.bml.age.check.question=Vai tev ir mazÄk nekÄ 13 gadi? + +/create.bml.age.check.yes=JÄ, man vÄ“l nav 13 gadu. + +/create.bml.age.head=Vecums + +/create.bml.btn.proceed=TurpinÄt... + +/create.bml.clusterselect.cluster=Klasteris: + +/create.bml.clusterselect.clusternum=Klasteris [[number]] + +/create.bml.clusterselect.head=Klastera izvÄ“le + +/create.bml.clusterselect.nocluster=Nav klastera + +/create.bml.clusterselect.text=LÅ«dzu izvÄ“lies to klasteri, uz kura tu vÄ“lies izveidot Å¡o kontu. PiezÄ«me: Å Ä« ir tikai testa opcija. LietotÄji to neredzÄ“s un neko par to nezinÄs. + +/create.bml.create.head=Jauna žurnÄla izveidoÅ¡ana + +/create.bml.create.text=Izveidot jaunu LiveJournal ir viegli, tikai seko instrukcijÄm! + +/create.bml.email.head=Tava e-pasta adrese + +/create.bml.email.input.head=E-pasta adrese: + +/create.bml.error.coppa.under13=Atvaino, sakarÄ ar COPPA ierobežojumiem, tu nevari lietot LiveJournal pirms tev paliek 13 gadi. LÅ«dzu atgriezies savÄ 13. dzimÅ¡anas dienÄ. + +/create.bml.error.email.blank=Tev jÄnorÄda sava e-pasta adrese. + +/create.bml.error.email.nospaces=E-pasta adresÄ“ nav atļautas atstarpes. Ja tu esi AOL biedrs, atceries, ka tava interneta e-pasta adrese ir tavs screen name bez atstarpÄ“m, kam seko @aol.com + +/create.bml.error.password.asciionly=ParolÄ“ tu vari lietot tikai ASCII simbolus. + +/create.bml.error.password.blank=Tev jÄievada parole. + +/create.bml.error.password.nomatch=Paroles nesakrÄ«t. + +/create.bml.error.postrequired=NepiecieÅ¡ams POST. + +/create.bml.error.username.blank=LÅ«dzu norÄdi vÄrdu vai pieņemtu vÄrdu. + +/create.bml.error.username.inuse=LietotÄja vÄrds jau ir aizņemts; lÅ«dzu izvÄ“lies citu. + +/create.bml.error.username.iscode=LietotÄja vÄrds izskatÄs pÄ“c ielÅ«guma koda, nevis lietotÄja vÄrda. + +/create.bml.error.username.mustenter=Tev jÄievada lietotÄja vÄrds. + +/create.bml.error.username.reserved=Atvaino, Å¡is lietotÄja vÄrds ir rezervÄ“ts. + +/create.bml.name.head=Tavs vÄrds + +/create.bml.name.input.head=VÄrds: + +/create.bml.name.text=KÄds ir tavs vÄrds vai pieņemtais vÄrds? Tas parÄdÄ«sies tava žurnÄla augÅ¡daÄ¼Ä un lietotÄju reÄ£istrÄ, ja tu izvÄ“lÄ“sies bÅ«t tajÄ ierakstÄ«ts. Tev nav jÄdod savs pilns vÄrds vai Ä«stais vÄrds. + +/create.bml.password.head=Parole + +/create.bml.password.input.head1=Parole: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=AtkÄrto paroli: + +/create.bml.password.text=IzvÄ“lies paroli. + +/create.bml.proceed.btn.proceed=TurpinÄt... + +/create.bml.proceed.warning=Spied TurpinÄt tikai vienu reizi!! + +/create.bml.success.btn.enterinfo=Ievadi informÄciju par sevi + +/create.bml.success.head=IzdoÅ¡anÄs! + +/create.bml.success.text1|staleness=1 +/create.bml.success.text1=Tavs žurnÄls ir izveidots. SvarÄ«ga reÄ£istrÄcijas informÄcija ir aizsÅ«tÄ«ta uz [[email]] ar turpmÄkÄm instrukcijÄm. PiezÄ«me: Tev ir tieÅ¡i septiņas dienas laika, lai apstiprinÄtu tava žurnÄla izveidoÅ¡anu. Ja pÄ“c septiņÄm dienÄm tu vÄ“l neesi to apstiprinÄjis, lietotÄja vÄrds [[username]] tiks izdzÄ“sts un to varÄ“s lietot kÄds cits. + +/create.bml.success.text2=Tavs LiveJournal bÅ«s atrodams: + +/create.bml.success.text3=Tagad, lÅ«dzu, ievadi informÄciju par sevi. TÄ lielÄkoties nav obligÄta, bet dod mums ieskatu par to, kas ir LiveJournal lietotÄji. + +/create.bml.title=Izveido jaunu žurnÄlu + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Lai izveidotu jaunu kontu, ievadi konta izveidoÅ¡anas kodu: + +/create.bml.useacctcodes.welcome=Laipni lÅ«dzam + +/create.bml.username.box.head=LietotÄja vÄrds: + +/create.bml.username.forpaidaccts=Vai, apmaksÄtiem kontiem: + +/create.bml.username.head=LietotÄja vÄrds + +/create.bml.username.ljaddress=Tavam žurnÄlam bÅ«s Å¡Ädas adreses: + +/create.bml.username.text=Katram [[sitename]] lietotÄjam jÄbÅ«t savam unikÄlam lietotÄja vÄrdam. Tavs lietotÄja vÄrds ir redzams tava žurnÄla adresÄ“ un ar to tu piereÄ£istrÄ“jies [[sitename]] serverÄ«. Tas arÄ« parÄdÄs, kad tu raksti komentÄrus citu cilvÄ“ku žurnÄlos. + +/create.bml.username.username=lietotÄja vÄrds + +/editinfo.bml.allowshowcontact.about=Å o opciju vÄ“lams iezÄ«mÄ“t. TÄ Ä¼auj citiem cilvÄ“kiem kontaktÄ“ties ar tevi, parÄdot tavu e-pasta adresi, ICQ numuru un AOL lietotÄjvÄrdu tavÄ LiveJournal. + +/editinfo.bml.allowshowcontact.email=PublicÄ“jamÄ e-pasta adrese: + +/editinfo.bml.allowshowcontact.email.actual_only=Tikai Ä«stÄ adrese + +/editinfo.bml.allowshowcontact.email.both=Abas (Ä«stÄ + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Tikai LiveJournal adrese + +/editinfo.bml.allowshowcontact.email.neither=Neviena. NerÄdÄ«t nevienu e-pasta adresi. + +/editinfo.bml.allowshowcontact.email.no_show=NerÄdÄ«t e-pasta adresi + +/editinfo.bml.allowshowcontact.email.show=RÄdÄ«t e-pasta adresi + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Ar augÅ¡minÄ“to opciju tu vari arÄ« izvÄ“lÄ“ties slÄ“pt savu e-pasta adresi (tomÄ“r parÄdot citu kontaktinformÄciju), tikai rÄdÄ«t savu LiveJournal e-pasta adresi (tikai apmaksÄtiem kontiem), tikai rÄdÄ«t savu Ä«sto e-pasta adresi, vai rÄdÄ«t abas. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Ar augÅ¡minÄ“to opciju tu vari arÄ« izvÄ“lÄ“ties slÄ“pt savu e-pasta adresi (tomÄ“r parÄdot citu kontaktinformÄciju) + +/editinfo.bml.allowshowcontact.title=ParÄdÄ«t tavu kontaktinformÄciju LiveJournal? + +/editinfo.bml.allowshowinfo.about=IzvÄ“lies Å¡o, ja gribi lai tava pilsÄ“ta/pavalsts/valsts un dzimÅ¡anas diena bÅ«tu redzama citiem lietotÄjiem. + +/editinfo.bml.allowshowinfo.title=ParÄdÄ«t vietu & dzimÅ¡anas dienu? + +/editinfo.bml.autotranslate.about<< +Lieto Å¡o opciju, lai norÄdÄ«tu LiveJournal, kuru kodÄ“Å¡anas sistÄ“mu (encoding) lietot taviem ierakstiem un komentÄriem, kas izdarÄ«ti pirms Å¡Ä« tÄ«kla lapa tika pÄrlikta uz Unicode. +Ja tu raksti angliski, izvÄ“lies "Western European". +. + +/editinfo.bml.autotranslate.header|staleness=1 +/editinfo.bml.autotranslate.header=AutomÄtiski tulkot vecÄkus ierakstus no: + +/editinfo.bml.bday.title=DzimÅ¡anas diena + +/editinfo.bml.bday.year.opt=gadu var nenorÄdÄ«t + +/editinfo.bml.bdayreminders.about=Ja tu vÄ“lies saņemt e-pasta atgÄdinÄjumus par tavu LiveJournal draugu dzimÅ¡anas dienÄm, iezÄ«mÄ“ Å¡o lodziņu. + +/editinfo.bml.bdayreminders.header|staleness=1 +/editinfo.bml.bdayreminders.header=SÅ«tiet man dzimÅ¡anas dienu atgÄdinÄjumus + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=Å eit tu vari ierakstÄ«t mini biogrÄfiju par sevi, kas parÄdÄ«sies tavÄ info lapÄ. + +/editinfo.bml.bio.header=Par tevi + +/editinfo.bml.blockrobots.about|staleness=1 +/editinfo.bml.blockrobots.about<< +Ja tu atzÄ«mÄ“ Å¡o opciju, roboti tiks sÅ«tÄ«ti prom. +Ne visi roboti respektÄ“ noteikumus, bet populÄro meklÄ“Å¡anas portÄlu roboti to dara. +. + +/editinfo.bml.blockrobots.header=Neatļauj robotiem skatÄ«t tavu žurnÄlu + +/editinfo.bml.city.title=PilsÄ“ta + +/editinfo.bml.country.choose=IzvÄ“lies valsti + +/editinfo.bml.country.title=Valsts + +/editinfo.bml.donotlog=NÄ“ + +/editinfo.bml.email.title=E-pasts + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=IezÄ«mÄ“ Å¡o, ja gribi lai citi var atbildÄ“t uz taviem žurnÄla ierakstiem. (nepiecieÅ¡ams atbilstoÅ¡s žurnÄla stils) + +/editinfo.bml.enableboards.header=Atļaut komentÄrus + +/editinfo.bml.encoding.about=PamatÄ tikai lietotÄjiem, kas raksta vairÄkÄs valodÄs, vajadzÄ“s izdarÄ«t Å¡eit izmaiņas. + +/editinfo.bml.encoding.header=KodÄ“Å¡anas izvÄ“lne + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Tu nevari norÄdÄ«t @[[domain]] e-pasta adresi. +Å ajÄ lauciÅ†Ä ieraksti savu Ä«sto adresi. +Ja tu esi maksÄjoÅ¡s lietotÄjs, tava [[user]]@[[domain]] adrese pÄrsÅ«tÄ«s pastu uz tavu Ä«sto adresi. +Lai izvÄ“lÄ“tos, kura e-pasta adrese (vai abas) tiks parÄdÄ«ta publiski, skaties opciju zem "ParÄdÄ«t kontaktinformÄciju". +. + +/editinfo.bml.error.email.no_space<< +E-pasta adresÄ“ nav atļautas atstarpes. +Ja tu lieto AOL, atceries, ka tava interneta e-pasta adrese ir tavs lietotÄjvÄrds bez atstarpÄ“m, kam seko @aol.com +. + +/editinfo.bml.error.excessive_int=Atvaino, tu esi minÄ“jis pÄrÄk daudz intereses. Limits ir 150, bet tu esi minÄ“jis [[intcount]]. Izmaiņas intereÅ¡u sarakstÄ netika izdarÄ«tas. Ej atpakaļ un saÄ«sini savu sarakstu, tad vÄ“lreiz saglabÄ to. + +/editinfo.bml.error.invalidbio=Tava ierakstÄ«tÄ biogrÄfija satur nederÄ«gus simbolus. Tev jÄiet uz konvertÄ“Å¡anas lapu, lai pÄrliktu to uz Unicode. + +/editinfo.bml.error.invalidints=Tavs paÅ¡reizÄ“jais intereÅ¡u saraksts satur nederÄ«gus simbolus. Tev jÄiet uz konvertÄ“Å¡anas lapu, lai pÄrliktu to uz Unicode. + +/editinfo.bml.error.invalidname=Tavs vÄrds satur nederÄ«gus simbolus. Tev jÄiet uz konvertÄ“Å¡anas lapu, lai pÄrliktu to uz Unicode. + +/editinfo.bml.error.locale.country_ne_state=Tu esi izvÄ“lÄ“jies Amerikas SavienotÄs Valstis kÄ savu valsti, bet esi ierakstÄ«jis neesoÅ¡u ASV pavalsti "cita pavalsts" ailÄ“. + +/editinfo.bml.error.locale.invalid_country=Kaut kÄ ir gadÄ«jies, ka tu esi izvÄ“lÄ“jies nederÄ«gu valsti. + +/editinfo.bml.error.locale.state_ne_country=Tu esi norÄdÄ«jis valsti kas nav ASV, bet izvÄ“lÄ“jies ASV pavalsti. + +/editinfo.bml.error.locale.zip_ne_state<< +Tavs pasta indekss neatbilst izvÄ“lÄ“tajai pavalstij. +Vai nu izlabo informÄciju, vai arÄ« izdzÄ“s vienu vai abas ailes. +. + +/editinfo.bml.error.locale.zip_requires_us|staleness=1 +/editinfo.bml.error.locale.zip_requires_us<< +Tu esi norÄdÄ«jis pasta indeksu bet neesi izvÄ“lÄ“jies ASV kÄ savu valsti. +MÄ“s prasÄm pasta indeksu tikai no ASV iedzÄ«votÄjiem. +LÅ«dzu ej atpakaļ un izdzÄ“s pasta indeksu, vai arÄ« izvÄ“lies ASV kÄ savu valsti. +. + +/editinfo.bml.error.tm.require.number=Ja tu vÄ“lies lietot Ä«sziņu sÅ«tÄ«Å¡anu, tev jÄnorÄda savs tÄlruņa numurs. + +/editinfo.bml.error.tm.require_provider<< +Ja tu vÄ“lies izmantot SMS sÅ«tÄ«Å¡anu, tev jÄizvÄ“las savs mobilo sakaru tÄ«kls. + +Ja tas nav minÄ“ts, lÅ«dzu atraksti mums informÄciju par sava tÄ«kla SMS iespÄ“jÄm, lai mÄ“s to varam pievienot sarakstam. +. + +/editinfo.bml.finished.about=Kad esi pabeidzis, spied "SaglabÄt izmaiņas" pogu: + +/editinfo.bml.finished.header=Pabeigts? + +/editinfo.bml.finished.save_button=SaglabÄt izmaiņas + +/editinfo.bml.gender.title=Dzimums + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=IezÄ«mÄ“ Å¡o, ja gribi saņemt e-pastus, kad kÄds atbild uz taviem žurnÄla ierakstiem ziņu dÄ“lÄ«. + +/editinfo.bml.getreplies.header=Saņem ziņu dēļa atbildes + +/editinfo.bml.hidefriendof.about=Ja atzÄ«mÄ“si Å¡o, to cilvÄ“ku saraksts, kas ir pievienojuÅ¡i tevi kÄ draugu, netiks parÄdÄ«ts tavÄ profila lapÄ. + +/editinfo.bml.howhear.about|staleness=1 +/editinfo.bml.howhear.about<< +TÄ«ri aiz ziņkÄrÄ«bas, kur tu uzzinÄji par [[sitename]? +Ja no kÄda cilvÄ“ka, norÄdi viņa lietotÄjvÄrdu, bet ja +no cita avota/raksta/saites/tÄ«kla lapas, sniedz attiecÄ«go informÄciju. +. + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +IezÄ«mÄ“ Å¡o, ja tava e-pasta programma pilnÄ«bÄ atbalsta HTML. +Daudzas programmas cenÅ¡as to atbalstÄ«t, bet smagi izgÄžas. +Ja neiezÄ«mÄ“si, LiveJournal sÅ«tÄ«s tev tikai teksta e-pastus. +. + +/editinfo.bml.htmlemail.header=SÅ«tÄ«t HTML e-pastus + +/editinfo.bml.int.about<< +Ja vÄ“lies lai citi var meklÄ“t reÄ£istrÄ un atrast tevi pÄ“c tavÄm interesÄ“m, norÄdi visu, par ko tu interesÄ“jies, atdalot ar komatiem. +VislabÄkÄs ir Ä«sas viena vÄrda frÄzes. KÄ likums, tavÄm interesÄ“m bÅ«tu jÄiekļaujas teikumÄ "Man patÄ«k ________". Minot lietvÄrdus, lieto daudzskaitli. +. + +/editinfo.bml.int.ex.bad=SLIKTS piemÄ“rs: Man patÄ«k visÄdas grupas un skatÄ«ties filmas un pļÄpÄt ar draugiem un iet uz klubiņiem. TÄdÄ stilÄ tu vari rakstÄ«t savÄ biogrÄfijÄ, bet ne Å¡eit. + +/editinfo.bml.int.ex.good=LABS piemÄ“rs: slÄ“poÅ¡ana, datori, mp3s, siers, sievietes + +/editinfo.bml.int.header=Intereses + +/editinfo.bml.login.enterinfo=Ievadi savu lietotÄjvÄrdu un paroli, lai izmainÄ«tu personÄ«go informÄciju. + +/editinfo.bml.login.forgot.header=Vai esi ko aizmirsis? + +/editinfo.bml.login.forgot.recover=Ja esi aizmirsis savu lietotÄja vÄrdu vai paroli, meklÄ“ to Å¡eit!. + +/editinfo.bml.logip.always=VienmÄ“r + +/editinfo.bml.logip.anon_only=Tikai anonÄ«mus rakstÄ«tÄjus + +/editinfo.bml.logip.header=ReÄ£istrÄ“t atbilžu rakstÄ«tÄju IP adreses? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Ja tu baidies, ka spam-roboti atradÄ«s tavu e-pasta adresi LiveJournal, izvÄ“lies Å¡o opciju, un tava e-pasta adrese tiks izmainÄ«ta tÄ, ka to nevarÄ“s atrast e-pasta meklÄ“tÄji roboti. + +/editinfo.bml.mangleaddress.header=IzmainÄ«t parÄdÄ«to e-pasta adresi + +/editinfo.bml.name.title=VÄrds + +/editinfo.bml.numcomments.about=IezÄ«mÄ“ Å¡o, ja vÄ“lies pielÄ«dzinÄt komentÄru skaitu URL, lai liktu tavai pÄrlÅ«kprogrammai rÄdÄ«t saites citÄ krÄsÄ. + +/editinfo.bml.numcomments.header=Pievienot &nc=xx komentÄru URL + +/editinfo.bml.optional=NeobligÄti + +/editinfo.bml.opt_in.header=SÅ«tiet man LiveJournal jaunumus. + +/editinfo.bml.persinfo.disclaimer=Ieraksti kÄdu informÄciju par sevi, mÅ«su ziņkÄrÄ«bas apmierinÄÅ¡anai un statistikai. MÄ“s ar Å¡o informÄciju nedarÄ«sim neko ļaunu, mÄ“s tikai vÄ“lÄ“tos redzÄ“t, kas un kur ir mÅ«su lietotÄji. LÅ«dzu aizpildi to precÄ«zi. Ja tevi mÄc raizes, izlasi mÅ«su slepenÄ«bas politiku. + +/editinfo.bml.persinfo.header=PersonÄ«gÄ informÄcija + +/editinfo.bml.screen.all=Visi + +/editinfo.bml.screen.anon=AnonÄ«mi + +/editinfo.bml.screen.none=Neviens + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=DroÅ¡Ä«ba + +/editinfo.bml.security.visibility.anybody=JebkurÅ¡ + +/editinfo.bml.security.visibility.everybody=Visi + +/editinfo.bml.security.visibility.friends=Tikai draugi + +/editinfo.bml.security.visibility.regusers=ReÄ£istrÄ“ti lietotÄji + +/editinfo.bml.settings.header=LiveJournal izvÄ“lne + +/editinfo.bml.state.other=Vai ieraksti citu pavalsti/provinci/teritoriju + +/editinfo.bml.state.title=Pavalsts + +/editinfo.bml.state.us=ASV pavalstis + +/editinfo.bml.success.header=IzdoÅ¡anÄs! + +/editinfo.bml.success.message=Tava informÄcija un žurnÄls un profils ir izmainÄ«ti. + +/editinfo.bml.switch.button=PÄrslÄ“gt + +/editinfo.bml.switch.header=PÄrslÄ“gt žurnÄlu + +/editinfo.bml.switch.workwith=StrÄdÄt ar žurnÄlu: + +/editinfo.bml.title=IzmainÄ«t personÄ«go informÄciju + +/editinfo.bml.tm.details=detaļas + +/editinfo.bml.tm.phonenum=Pilns tÄlruņa numurs: + +/editinfo.bml.tm.sec.about=Atļaut Ä«sziņas no citiem lietotÄjiem. + +/editinfo.bml.tm.sec.title=DroÅ¡Ä«bas lÄ«menis: + +/editinfo.bml.tm.servprov=MobÄ«lo sakaru tÄ«kls + +/editinfo.bml.tm.title=Īsziņas + +/editinfo.bml.whoreply.header=Kas var atbildÄ“t uz taviem ierakstiem? + +/editinfo.bml.zip.title=Pasta indekss + +/editinfo.bml.zip.usonly=5 ciparu pasta indekss; tikai ASV iedzÄ«votÄjiem + +/editjournal.bml.btn.proceed=TurpinÄt... + +/editjournal.bml.certainday=Noteikta diena: + +/editjournal.bml.recententries=paÅ¡i pÄ“dÄ“jie ieraksti + +/editjournal.bml.recententry=PÄ“dÄ“jais ieraksts + +/editjournal.bml.title=Rediģēt žurnÄla ierakstus + +/editjournal.bml.viewwhat=Kurus ierakstus skatÄ«t: + +/editjournal_do.bml.btn.edit=Rediģēt izvÄ“lÄ“to ierakstu + +/editjournal_do.bml.btn.save=SaglabÄt žurnÄla ierakstu + +/editjournal_do.bml.continue.head=Spied, lai turpinÄtu... + +/editjournal_do.bml.continue.text=PÄ“c tam kad esi izvÄ“lÄ“jies ierakstu, ko rediģēt vai izdzÄ“st, spied Rediģēt pogu. + +/editjournal_do.bml.currmood|staleness=1 +/editjournal_do.bml.currmood=GarastÄvoklis: + +/editjournal_do.bml.currmusic=MÅ«zika: + +/editjournal_do.bml.date=Datums: + +/editjournal_do.bml.default=pamata + +/editjournal_do.bml.edit.text|staleness=2 +/editjournal_do.bml.edit.text=Rediģē tÄs žurnÄla ieraksta ailes, kuras tu vÄ“lies izmainÄ«t, un nospied SaglabÄt pogu lapas apakÅ¡Ä. Lai izdzÄ“stu ierakstu, vienkÄrÅ¡i izdzÄ“s visu tekstu un spied SaglabÄt... viss ieraksts tiks izdzÄ“sts. + +/editjournal_do.bml.error.getting=ŽurnÄla ieraksta izvÄ“lÄ“ radusies kļūda: + +/editjournal_do.bml.error.modify=Izdarot izmaiņas žurnÄlÄ, radusies kļūda: + +/editjournal_do.bml.error.nofind=IzvÄ“lÄ“tais žurnÄla ieraksts nav atrodams. + +/editjournal_do.bml.event=Notikums: + +/editjournal_do.bml.localtime=VietÄ“jais laiks: + +/editjournal_do.bml.noneother=Neviens, vai cits: + +/editjournal_do.bml.opt.backdate=AtpakaļejoÅ¡s datums/laiks: + +/editjournal_do.bml.opt.backdate.about=neparÄdÄ«sies draugu lapÄ + +/editjournal_do.bml.opt.nocomments=Neatļaut komentÄrus: + +/editjournal_do.bml.opt.noemail=NesÅ«tÄ«t komentÄrus pa e-pastu: + +/editjournal_do.bml.opt.noformat=AutomÄtiski neformatÄ“t: + +/editjournal_do.bml.other=Cits: + +/editjournal_do.bml.pickentry.head=IzvÄ“lies ierakstu rediģēšanai + +/editjournal_do.bml.pickentry.text=IzvÄ“lies, ko tu gribi rediģēt, un nospied Rediģēt pogu lapas apakÅ¡Ä. + +/editjournal_do.bml.picture=LietojamÄ bilde: + +/editjournal_do.bml.save.head=Nospied, lai saglabÄtu... + +/editjournal_do.bml.save.text=PÄ“c tam, kad esi pabeidzis izdarÄ«t izmaiņas savÄ Å¾urnÄla ierakstÄ, nospied SaglabÄt. + +/editjournal_do.bml.subject|staleness=1 +/editjournal_do.bml.subject=Temats: (nav obligÄts, var lietot garÄkiem ierakstiem) + +/editjournal_do.bml.success.delete=ŽurnÄla ieraksts ir izdzÄ“sts. + +/editjournal_do.bml.success.edit|staleness=1 +/editjournal_do.bml.success.edit=ŽurnÄla ieraksts ir mainÄ«ts. Tu vari to skatÄ«t Å¡eit. + +/editjournal_do.bml.success.head=IzdoÅ¡anÄs + +/editjournal_do.bml.timeformat=24 stundu laiks + +/editjournal_do.bml.title=Rediģēt žurnÄla ierakstus + +/friends/add.bml.add.header=IzdoÅ¡anÄs + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=LietotÄjs ir pievienots tavam draugu sarakstam. Tu vari skatÄ«t savu draugu lapu Å¡eit. + +/friends/add.bml.add.title=Draugs pievienots! + +/friends/add.bml.btn.add=Pievieno [[user]] + +/friends/add.bml.btn.modify=IzmainÄ«t + +/friends/add.bml.btn.remove=NodzÄ“st + +/friends/add.bml.colors.bg=PamatkrÄsa + +/friends/add.bml.colors.fg=Teksta krÄsa + +/friends/add.bml.colors.header=KrÄsas + +/friends/add.bml.colors.hover=(Paturi peles kursoru virs krÄsas, lai redzÄ“tu tÄs nosaukumu) + +/friends/add.bml.colors.text=Tu vari arÄ« izvÄ“lÄ“ties krÄsas, kas apzÄ«mÄ“s [[user]] tavÄ draugu sarakstÄ. + +/friends/add.bml.confirm.header=Pievienot [[user]] kÄ draugu? + +/friends/add.bml.confirm.text=Lai pievienotu [[user]] savam draugu sarakstam, nospied pogu. + +/friends/add.bml.confirm.title=Pievieno draugu + +/friends/add.bml.error1.header|staleness=1 +/friends/add.bml.error1.header=Vispirms piereÄ£istrÄ“jies + +/friends/add.bml.error1.text=Lai pievienotu lietotÄju savam draugu sarakstam, tev vispirms jÄreÄ£istrÄ“jas. Ja tev vÄ“l nav sava konta, tu vari to izveidot, lai sekotu lÄ«dzi savu draugu žurnÄliem. + +/friends/add.bml.error1.title=Pievieno draugu + +/friends/add.bml.error2.text|staleness=1 +/friends/add.bml.error2.text=Nepareizs vai neesoÅ¡s lietotÄjvÄrds. :ai pievienotu draugu, ej uz rediģēt draugus lapu. + +/friends/add.bml.error3.text=[[user]] jau ir tavÄ draugu sarakstÄ. Papildus tu vari mainÄ«t viņam pieÅ¡Ä·irtÄs krÄsas. + +/friends/add.bml.error3.title=Rediģēt draugus + +/friends/add.bml.groups.header=Draugu grupas + +/friends/add.bml.groups.nogroup|staleness=1 +/friends/add.bml.groups.nogroup=Draugu grupas nav uzstÄdÄ«tas. + +/friends/add.bml.groups.text=KurÄs draugu grupÄs tu vÄ“lies Å¡o lietotÄju iekļaut? Draugu grupas tiek lietotas tavas draugu lapas filtrÄ“Å¡anai un ierakstu droÅ¡Ä«bai. + +/friends/add.bml.remove.header=IzdoÅ¡anÄs + +/friends/add.bml.remove.text=LietotÄjs ir izņemts no tava draugu saraksta. Tu vari skatÄ«t savu draugu lapu Å¡eit. + +/friends/add.bml.remove.title=Draugs nodzÄ“sts! + +/friends/edit.bml.title=Rediģēt draugus + +/friends/edit_do.bml.addfriends.head=Pievienot draugus + +/friends/edit_do.bml.addfriends.text=Ievadi savu draugu LiveJournal lietotÄjvÄrdus sekojoÅ¡ajÄs ailÄ“s un izvÄ“lies pamata un teksta krÄsas, kuras ar viņiem asociÄ“t.... + +/friends/edit_do.bml.background=PamatkrÄsa + +/friends/edit_do.bml.bgcolor=PamatkrÄsa: + +/friends/edit_do.bml.btn.close=AizvÄ“rt + +/friends/edit_do.bml.btn.save=SaglabÄt izmaiņas + +/friends/edit_do.bml.done.head=DarÄ«ts? + +/friends/edit_do.bml.done.text=Kad esi pabeidzis, spied sekojoÅ¡o "SaglabÄt izmaiņas" pogu... + +/friends/edit_do.bml.error.updating=Tava draugu saraksta papildinÄÅ¡anÄ atgadÄ«jusies kļūda: + +/friends/edit_do.bml.foreground=Teksta krÄsa + +/friends/edit_do.bml.friend=Draugs + +/friends/edit_do.bml.hover=Paturi peles kursoru virs krÄsas, lai redzÄ“tu tÄs nosaukumu + +/friends/edit_do.bml.name=VÄrds + +/friends/edit_do.bml.nofriends.head=Nav draugu? + +/friends/edit_do.bml.opt.delete=IzdzÄ“st? + +/friends/edit_do.bml.success.head=IzdoÅ¡anÄs + +/friends/edit_do.bml.textcolor=Teksta krÄsa: + +/friends/edit_do.bml.title=Rediģēt draugus + +/friends/edit_do.bml.user=LietotÄjs + +/friends/edit_do.bml.yourfriends.head=Tavi draugi + +/friends/edit_do.bml.yourfriends.text=Tu esi minÄ“jis sekojoÅ¡os draugus: + +/index.bml.boldcreate=Izveido pats savu LiveJournal! + +/index.bml.frank.image.alt=Ä€zis Franks, LiveJournal talismans. + +/index.bml.frank.logo="BÄ“Ä“Ä“Ä“Ä“", saka Franks. + +/index.bml.meta.desc=LiveJournal.com ir vieta, kur tu vari dalÄ«ties savÄs domÄs ar visu pasauli. + +/index.bml.meta.keywords=dienasgrÄmata, žurnÄls, online žurnÄls, dienasgrÄmatas, rakstÄ«Å¡ana, online dienasgrÄmata, web dienasgrÄmata + +/interests.bml.add.added.head=Pievienots! + +/interests.bml.add.added.text=Interese pievienota tavam sarakstam. + +/interests.bml.add.btn.text=Pievienot [[interest]] + +/interests.bml.add.confirm.head=ApstiprinÄt + +/interests.bml.add.confirm.text=Lai pievienotu [[interest]] interesÄ“m, spied sekojoÅ¡o pogu. + +/interests.bml.add.toomany.head=Atvaino... + +/interests.bml.add.toomany.text=Tu jau esi norÄdÄ«jis [[maxinterests]] intereses. + +/interests.bml.addint=Ja tu arÄ« par Å¡o interesÄ“jies un vÄ“lÄ“tos pievienoties Å¡im sarakstam, ej Å¡eit. + +/interests.bml.communities.head=SaistÄ«tas kopienas + +/interests.bml.communities.text=SekojoÅ¡Äs kopienas arÄ« interesÄ“jas par "[[interest]]". + +/interests.bml.count=Skaits + +/interests.bml.error.add.mustlogin=Lai pievienotu interesi, tev ir jÄiereÄ£istrÄ“jas. + +/interests.bml.error.findsim_do.intnotfound=Interese nav atrasta. + +/interests.bml.findsim.searchwait=LÅ«dzu ievÄ“ro: MeklÄ“jot paies vairÄkas sekundes. Esi pacietÄ«gs. + +/interests.bml.findsim_do.account.notallowed=Atvaino, tava konta veids neatļauj tev izmantot Å¡o iespÄ“ju. + +/interests.bml.findsim_do.magic=MaÄ£iskais
          indekss + +/interests.bml.findsim_do.magic.head=MaÄ£iskais indekss? + +/interests.bml.findsim_do.magic.text=Katrs lÄ«dzÄ«gais lietotÄjs saņem maÄ£isko indeksu, kas tiek aprÄ“Ä·inÄts no diviem faktoriem: sakrÄ«toÅ¡o intereÅ¡u skaita un dažiem papildus punktiem par netipisku intereÅ¡u sakritÄ«bu. + +/interests.bml.findsim_do.nomatch.head=Nav rezultÄtu + +/interests.bml.findsim_do.nomatch.text=Neviens lietotÄjs nav lÄ«dzÄ«gs [[user]]. + +/interests.bml.findsim_do.notdefined=LietotÄjs [[user]] nav minÄ“jis savas intereses. + +/interests.bml.findsim_do.similar.head=LÄ«dzÄ«gi lietotÄji + +/interests.bml.findsim_do.similar.text=SekojoÅ¡ie lietotÄji ir vislÄ«dzÄ«gÄkie [[user]] + +/interests.bml.interest=Interese + +/interests.bml.interested.btn.find=MeklÄ“t + +/interests.bml.interested.in|staleness=1 +/interests.bml.interested.in=MeklÄ“t cilvÄ“kus, kas interesÄ“jas par: + +/interests.bml.interests.head=Intereses + +/interests.bml.interests.text|staleness=1 +/interests.bml.interests.text=Te ir dažas interesantas lietas, ko var darÄ«t ar interesÄ“m... + +/interests.bml.interests.viewpop=SkatÄ«t populÄras intereses + +/interests.bml.match=[[skaits]] atbilst: + +/interests.bml.matches=[[skaits]] atbilst: + +/interests.bml.morestuff|staleness=1 +/interests.bml.morestuff=VairÄkas interesantas lietas atrodamas intereÅ¡u lapÄ. + +/interests.bml.nointerests.text=VÄ“l neesi norÄdÄ«jis savas intereses? Lai pievienotu tÄs, ej Rediģēt personÄ«go informÄciju un uzstÄdÄ«jumus. + +/interests.bml.popular.head=PopulÄras intereses + +/interests.bml.popular.text=SekojoÅ¡Äs intereses ir vispopulÄrÄkÄs. + +/interests.bml.title=Intereses + +/interests.bml.toomany.body=[[intcount]] cilvÄ“ki un/vai kopienas ir minÄ“juÅ¡i Å¡o interesi. Saraksts netiks parÄdÄ«ts. + +/interests.bml.toomany.head=Daudz rezultÄtu + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=SekojoÅ¡ie lietotÄji arÄ« interesÄ“jas par [[interest]]. + +/login.bml.bindip.label=PiesaistÄ«t IP adresei: + +/login.bml.bindip.no=NÄ“ (strÄdÄ ar visiem ISP) + +/login.bml.login.forget=Aizmirsi? + +/login.bml.login.head=ReÄ£istrÄ“ties + +/login.bml.login.never=Nekad + +/login.bml.login.otheropts=Citas iespÄ“jas + +/login.bml.login.password=Parole: + +/login.bml.login.text1=Lai iereÄ£istrÄ“tos [[sitename]], ievadi savu lietotÄjvÄrdu un paroli. Jauniem lietotÄjiem: Lai izveidotu kontu, ej Å¡eit. + +/login.bml.login.username=LietotÄjvÄrds: + +/login.bml.login.whenbrowsercloses=Kad pÄrlÅ«kprogramma aizveras + +/login.bml.title=ReÄ£istrÄ“ties + +/login.bml.whylogin.benefit1=Tev nevajadzÄ“s vÄ“lreiz ievadÄ«t savu lietotÄjvÄrdu/paroli. + +/login.bml.whylogin.head=KÄpÄ“c jÄreÄ£istrÄ“jas? + +/login.bml.whylogin.text=Dažas reÄ£istrÄ“Å¡anÄs priekÅ¡rocÄ«bas: + +/lostinfo.bml.btn.proceed=TurpinÄt + +/lostinfo.bml.enter_email=Ievadi savu e-pasta adresi: + +/lostinfo.bml.enter_email_optional=E-pasta adrese: (neobligÄti) + +/lostinfo.bml.enter_username=Ievadi savu lietotÄjvÄrdu: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Ja esi pazaudÄ“jis savu paroli, ievadi savu lietotÄjvÄrdu un, vÄ“lams, e-pasta adresi, uz kuru tu vÄ“lÄ“tos nosÅ«tÄ«t paroli. IevÄ“ro, ka e-pasta adresei jÄsakrÄ«t ar to, ko tu esi lietojis iepriekÅ¡ un apstiprinÄjis lietoÅ¡anai LiveJournal. Ja atstÄsi e-pasta aili tukÅ¡u, tÄ tiks aizsÅ«tÄ«ta uz tavu esoÅ¡o adresi. + +/lostinfo.bml.lostpassword.title|staleness=1 +/lostinfo.bml.lostpassword.title=PazaudÄ“ji savu paroli? + +/lostinfo.bml.lostusername.text=Ja esi pazaudÄ“jis savu lietotÄjvÄrdu, ievadi savu e-pasta adresi, un mÄ“s aizsÅ«tÄ«sim tev tavu lietotÄjvÄrdu. + +/lostinfo.bml.lostusername.title|staleness=1 +/lostinfo.bml.lostusername.title=PazaudÄ“ji savu lietotÄjvÄrdu? + +/lostinfo.bml.title=PazaudÄ“ta informÄcija + +/lostinfo_do.bml.error.no_usernames_for_email=Neviens lietotÄjvÄrds nav reÄ£istrÄ“ts ar adresi: [[address]]. + +/lostinfo_do.bml.error1.text=Tu neesi lietojis Å¡o e-pasta adresi ar Å¡o kontu, vai tÄ nav bijusi apstiprinÄta. + +/lostinfo_do.bml.password_mailed.text=Tava parole ir nosÅ«tÄ«ta. + +/lostinfo_do.bml.password_mailed.title=Parole nosÅ«tÄ«ta! + +/lostinfo_do.bml.title=PazaudÄ“ta informÄcija + +/lostinfo_do.bml.username_mailed.text=Tavs lietotÄjvÄrds ir nosÅ«tÄ«ts. + +/lostinfo_do.bml.username_mailed.title=LietotÄjvÄrds nosÅ«tÄ«ts! + +/modify.bml.title=IzmainÄ«t žurnÄlu + +/modify_do.bml.availablestyles.head=Pieejamie stili + +/modify_do.bml.availablestyles.userstyles=LietotÄju stili: + +/modify_do.bml.colortheme.about|staleness=2 +/modify_do.bml.colortheme.about=Å eit tu vari izvÄ“lÄ“ties krÄsu motÄ«vu tavam iepriekÅ¡ izvÄ“lÄ“tajam lapas izkÄrtojumam. Vai arÄ«, ja tevi neapmierina dotÄs krÄsas, norÄdi pats savas! Ja tu atrodi kÄdu Ä«paÅ¡i seksÄ«gu salikumu, paziņo mums, un mÄ“s nosauksim motÄ«vu tavÄ vÄrdÄ. + +/modify_do.bml.colortheme.color.head1=KrÄsa + +/modify_do.bml.colortheme.color.head2=(#rrggbb vai vÄrds) + +/modify_do.bml.colortheme.customcolors=Citas krÄsas + +/modify_do.bml.colortheme.defaulttheme=PamatmotÄ«vs + +/modify_do.bml.colortheme.head=KrÄsu motÄ«vs + +/modify_do.bml.domainalias.about=Ja tev ir savs domÄ“na vÄrds (domain name), vai tu plÄno to reÄ£istrÄ“t un vÄ“lÄ“tos, lai tas automÄtiski norÄda uz tavu žurnÄlu, ievadi to Å¡eit: + +/modify_do.bml.domainalias.domainname=DomÄ“na vÄrds: + +/modify_do.bml.domainalias.example=PiemÄ“rs: my-journal.com + +/modify_do.bml.done.btn.savechanges=SaglabÄt izmaiņas + +/modify_do.bml.done.text=Kad esi pabeidzis, spied "SaglabÄt izmaiņas" pogu... + +/modify_do.bml.error.dupdomainalias=Cits lietotÄjs jau reÄ£istrÄ“jis sev tavu izvÄ“lÄ“to domÄ“na vÄrdu. + +/modify_do.bml.error.stylenotavailable=Viens no izvÄ“lÄ“tajiem stiliem nav pieejams. Tas noticis vai nu tÄdēļ, ka kÄds Å¡o stilu ir izdzÄ“sis, vai arÄ« tev nav dota atļauja izvÄ“lÄ“ties Å¡o stilu. + +/modify_do.bml.friends.about=Å eit tu vari izvÄ“lÄ“ties savas draugu lapas izskatu. + +/modify_do.bml.friends.head=Draugu skats + +/modify_do.bml.friends.opt.usesharedpic.about=Å Ä« opcija nosaka, kuru bildi tu redzÄ“si savÄ draugu lapÄ, kad lietotÄjs rakstÄ«jis kopÄ«gÄ vai kopienas žurnÄlÄ. Ja tu to iezÄ«mÄ“, tad tu redzÄ“si kopienas bildi. Ja atstÄsi to neiezÄ«mÄ“tu, tad tu redzÄ“si rakstÄ«tÄja personÄ«go bildi. + +/modify_do.bml.friends.opt.usesharedpic.head=Lietot kopÄ«gÄs žurnÄla bildes, personÄ«go vietÄ + +/modify_do.bml.journaloptions.about|staleness=2 +/modify_do.bml.journaloptions.about=Å eit tu vari pieskaņot savu LiveJournal lapu izskatu. Ja tev ļoti interesÄ“, kÄ viss darbojas, izlasi programmÄ“tÄju informÄciju. PretÄ“jÄ gadÄ«jumÄ, mÄ“s pieņemsim, ka tu esi apmierinÄts ar dotajÄm pamata izvÄ“les iespÄ“jÄm. + +/modify_do.bml.journaloptions.head=ŽurnÄla izvÄ“lne + +/modify_do.bml.journalstatus.about=Ja tu vÄ“lies aizvÄ“rt vai atkal atvÄ“rt savu žurnÄlu, Å¡Ä« ir tÄ vieta, kur to izdarÄ«t. Kad tu aizver savu žurnÄlu, tev tiek dotas 30 dienas laika to atvÄ“rt, gadÄ«jumÄ ja tu pÄrdomÄ. PÄ“c 30 dienÄm žurnÄls tiks neatgriezeniski izdzÄ“sts un nebÅ«s atjaunojams. + +/modify_do.bml.journalstatus.head=ŽurnÄla aktivizÄcijas statuss + +/modify_do.bml.journalstatus.select.activated=AktÄ«vs + +/userinfo.bml.label.memories=Atmiņas + +/userinfo.bml.label.moredetails=(papildus info...) + +/userinfo.bml.label.name=VÄrds: + +/userinfo.bml.label.nofriends=Neviens nav minÄ“ts. + +/userinfo.bml.label.sendmessage=SÅ«tÄ«t ziņu + +talk.commentpermlink=saite + +talk.commentpost=Pievienot jaunu komentÄru + +talk.commentsread=LasÄ«t komentÄrus + diff --git a/ljcom/bin/upgrading/ms.dat b/ljcom/bin/upgrading/ms.dat new file mode 100644 index 0000000..81ebfa8 --- /dev/null +++ b/ljcom/bin/upgrading/ms.dat @@ -0,0 +1,1114 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Jika anda ingin memadam atau mengembalikan semula jurnal anda, inilah tempatnya. Sebaik sahaja anda memadam jurnal, anda hanya ada 30 hari untuk mengembalikannya semula, sekiranya anda mengubah fikiran. Selepas 30 hari, jurnal itu akan dipadam terus dan tidak boleh dikembalikan semula. + +/accountstatus.bml.journalstatus.head=Status Pengaktifan Jurnal + +/accountstatus.bml.journalstatus.select.activated=Telah diaktifkan + +/accountstatus.bml.journalstatus.select.deleted=Telah dipadam + +/accountstatus.bml.journalstatus.select.suspended=Telah digantung + +/allpics.bml.current=Gambar Terkini + +/allpics.bml.default=Asal + +/allpics.bml.edit2=Anda mungkin berminat untuk mengedit kata kunci gambar anda atau memuatnaikkan gambar baru. + +/allpics.bml.error.noparam=Anda perlu menyatakan parameter pengguna. + +/allpics.bml.keywords=Kata kunci: + +/allpics.bml.nopics.text.other=Pengguna belum lagi memuatnaikkan sebarang gambar pengguna. + +/allpics.bml.nopics.text2=Anda tiada sebarang gambar yang telah dimuatnaikkan. Untuk memuatnaikkan gambar, sila pergi ke sini. + +/allpics.bml.nopics.title=Tiada Gambar + +/allpics.bml.pics=Berikut adalah gambar pengguna [[user]]. + +/allpics.bml.title=Gambar Pengguna + +/changepassword.bml.btn.proceed=Teruskan + +/changepassword.bml.changepassword.header=Tukar Kata Laluan + +/changepassword.bml.changepassword.instructions=Isikan borang di bawah untuk menukar kata laluan anda. Untuk pertolongan dalam memilih kata laluan yang bagus dan memastikan akaun anda selamat, sila lawati FAQ ini. + +/changepassword.bml.email.body<< +Kata laluan anda telah ditukar di [[sitename]]. + +Untuk mendapatkannya semula pada masa hadapan, sila lawat: + + [[siteroot]]/lostinfo.bml + +Salam hormat, +Pihak [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Penukaran Kata Laluan + +/changepassword.bml.error.badcheck=Kata Laluan Baru Ralat: [[error]] + +/changepassword.bml.error.badnewpassword=Pengesahan kata laluan baru anda tidak sepadan dengan kata laluan baru anda. Anda mungkin tersalah taip. Sila taip dan sahkan kata laluan baru anda semula. + +/changepassword.bml.error.badoldpassword=Kata laluan lama anda tidak betul. + +/changepassword.bml.error.blankpassword=Kata laluan baru anda tidak boleh kosong. + +/changepassword.bml.error.changetestaccount=Kata laluan akaun cubaan tidak boleh ditukar. + +/changepassword.bml.error.characterlimit=Kata laluan hanya terhad kepada 30 aksara. + +/changepassword.bml.error.invaliduser=Pengguna tidak sahih [[user]]. Pengguna ini tidak wujud. Anda pasti anda telah menaipnya dengan betul? + +/changepassword.bml.error.mustenterusername=Anda mesti menginputkan nama pengguna anda. + +/changepassword.bml.error.nonascii=Kata laluan terhad kepada simbol ASCII. Sila pilih kata laluan yang tidak menggunakan simbol-simbol bukan ASCII. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Anda tidak boleh menukar kata laluan anda jika alamat email semasa anda belum lagi disahihkan. + +/changepassword.bml.newpassword=Kata Laluan Baru: + +/changepassword.bml.newpasswordagain=Kata Laluan Baru (sekali lagi): + +/changepassword.bml.oldpassword=Kata Laluan Lama: + +/changepassword.bml.proceed.instructions=Sila tekan butang di bawah dan kata laluan anda akan ditukar. Anda juga akan menerima emel memaklumkan penukaran kata laluan itu. + +/changepassword.bml.success.text=Kata laluan anda telah pun ditukar dan emel yang membawa mesej peringatan telah pun dihantar kepada anda. + +/changepassword.bml.title=Tukar Kata Laluan + +/community/index.bml.main|staleness=2 +/community/index.bml.main<< + + + + + The 'Newbies' Lounge, di mana segala persoalan anda akan terjawab. Lawati , biasakan diri anda, dan anda akan menjadi pro tanpa membuang masa lagi! +p?> + + +
          +Tambah kepada laman kawan anda untuk sentiasa peka akan peristiwa dan isu yang relevan kepada komuniti Livejournal seluruhnya.
          +Tambah kepada laman kawan anda untuk diberitahu apabila downtime dijangka dan laporan servis tergendala yang tidak dijangka. +p?> + + [nina, note code missing] +seting maklumat peribadi anda. Kalau anda mempunyai Akaun Berbayar, anda juga boleh memastikan telefon bimbit atau pager anda boleh menerima mesej teks. +p?> + + +Akaun Berbayar. Terdapat juga banyak lagi cara lain untuk anda membantu kami. +

          +Livejournal ialah sebuah projek Open Source; jika anda berpengalaman dalam bahasa pengaturcaraan atau aplikasi bahagian server anda boleh melawati Komuniti Pembangunan Livejournal, . Jikalau anda ada sebarang idea untuk memperbaikkan lagi Livejournal, lawati Ruang Cadangan Livejournal. Jikalau anda ingin membantu dalam apa sahaja, lawati Komuniti Perniagaan Livejournal, . Jikalau anda suka membantu orang, lawati pusat bantuan teknikal kami dan bantulah sesiapa yang memerlukan. Jikalau anda pakar dalam graphic design, lawati Komuniti Seni Livejournal, . +p?> + + +Anime kepada Zen Buddhism, dari Astronomi ke Zim. Anda akan juga mendapati komuniti rantauan untuk pelbagai tempat serata dunia. Kemungkinan besar ada sebuah komuniti Livejournal di mana anda berada! +p?> + + +FAQ yang menjelaskan bagaimana cara untuk mencipta komuniti anda tersendiri. Terdapat juga dua kategori FAQ (FAQ Komuniti Am dan FAQ Pengurusan Komuniti) yang merangkumi apa sahaja yang anda ingin tahu tentang komuniti. Jika anda masih lagi memerlukan pertolongan, jangan teragak-agak untuk menghantar permintaan pertolongan. +p?> + + + + +
            +
          • Lawati Komuniti Promosi ()
          • +
          • Lawati Komuniti Carian ()
          • +
          + + +E-mel Jesse Proulx, () Pengarah Komuniti. +p?> +. + +/community/index.bml.title=Pusat Komuniti + +/community/join.bml.button.join=Sertai Komuniti + +/community/join.bml.label.addtofriends=Tambah "[[maintainer]]" ke dalam senarai sahabat.
          + +/community/join.bml.label.allowposting=Komuniti ini membenarkan semua ahlinya mengepos, jadi anda sekarang mempunyai kebenaran untuk mengepos. Jika anda sudah log masuk menerusi perisian LiveJournal di komputer anda, anda harus log keluar dan log masuk kembali supaya jurnal ini muncul di dalam senarai jurnal yang anda boleh pos. + +/community/join.bml.label.auth=Walaupun anda telah disenaraikan sebagai ahli, komuniti ini hanya membenarkan posting oleh pengguna yang telah dibenarkan. Hubungi salah seorang daripada pentadbirnya jika anda ingin kebenaran untuk posting. Berikut adalah senarai para pentadbir untuk komuniti ini: [[admins]] + +/community/join.bml.label.banned=Penyelenggara komuniti ini telah mengharamkan penyertaan anda. + +/community/join.bml.label.closed=Komuniti ini tertutup. Jika anda berminat untuk menyertainya, sila hubungi salah seorang daripada pentadbirnya. Berikut adalah senarai para pentadbir untuk komuniti ini: [[admins]] + +/community/join.bml.label.commlogged=Anda telah mendaftar masuk ke dalam akaun kongsi/komuniti, dan bukan ke akaun peribadi anda. + +/community/join.bml.label.errorcomminfo=Maklumat tertentu mengenai komuniti ini tidak sah. + +/community/join.bml.label.expls=Tekan butang di bawah untuk menyertai "[[penyelenggara]]" komuniti . Kosongkan kotak di bawah jika anda mahu menyertai komuniti tanpa melihat pos komuniti di laman sahabat anda. + +/community/join.bml.label.loginfirst=Untuk menyertai komuniti, anda terlebih dahulu harus log masuk. + +/community/join.bml.label.membernow=Anda telah menjadi ahli [[commname]] Komuniti + +/community/join.bml.label.sure=Anda pasti? + +/community/join.bml.success=Berjaya + +/community/join.bml.title=Sertai Komuniti + +/community/leave.bml.button.leave=Tinggalkan Komuniti + +/community/leave.bml.label.buttontoleave=Tekan butang di bawah untuk meninggalkan "[[commname]]" komuniti. + +/community/leave.bml.label.infoerror=Maklumat tertentu mengenai komuniti tidak sah. + +/community/leave.bml.label.logoutfirst=Untuk meninggalkan komuniti, anda terlebih dahulu harus log masuk. + +/community/leave.bml.label.removed=Anda telah meninggalkan [[commname]] Komuniti + +/community/leave.bml.label.removefromfriends=Keluarkan juga "[[user]]" daripada senarai kawan. + +/community/leave.bml.success=Berjaya + +/community/leave.bml.sure=Anda pasti? + +/community/leave.bml.title=Tinggalkan Komuniti + +/community/manage.bml.commlist.actinfo=Maklumat + +/community/manage.bml.commlist.actions=Gerakan + +/community/manage.bml.commlist.actmembers=[Ahli] + +/community/manage.bml.commlist.actmembers2=Ahli + +/community/manage.bml.commlist.actsettings=[Setings] + +/community/manage.bml.commlist.actsettings2=Seting + +/community/manage.bml.commlist.header=Komuniti Anda + +/community/manage.bml.commlist.none=Anda tidak mengurus sebarang komuniti. + +/community/manage.bml.commlist.text=Berikut adalah komuniti yang anda urus atau urus bersama: + +/community/manage.bml.commlist.title=Tajuk + +/community/manage.bml.commlist.username=Nama Pengguna + +/community/manage.bml.create.header=Cipta sebuah komuniti + +/community/manage.bml.create.text=Anda boleh juga cipta komuniti baru. + +/community/manage.bml.title=Pengurusan Komuniti + +/community/members.bml.error.alreadyadded=[[user]] tidak ditambah kerana sudah ada laluan ke komuniti ini. + +/community/members.bml.error.alreadysent=[[user]] tidak boleh ditambah kerana email pengesahan telah dihantar kepada mereka pada: [[datetime]]. Sila tunggu untuk mereka membalas. + +/community/members.bml.error.invaliduser=Tidak boleh tambah komuniti atau akaun bersindiket: [[user]] + +/community/members.bml.error.noaccess=Hanya pengendali komuniti yang boleh mengedit senarai keahlian. Anda bukan pengendali komuniti [[comm]]. + +/community/members.bml.error.noattr=Tiada ciri yang telah dipilih oleh pengguna: [[user]] + +/community/members.bml.error.nocomm=Komuniti tidak dijumpai. + +/community/members.bml.error.nouser=Pengguna ini tidak wujud: [[user]] + +/community/members.bml.key.admin=Pengendali + +/community/members.bml.key.member=Ahli + +/community/members.bml.key.moderate=Pengawas + +/community/members.bml.key.post=Kebenaran mempos + +/community/members.bml.key.preapprove=Tidak diawasi + +/community/members.bml.manage2=Kendalikan komuniti + +/community/members.bml.name=Nama komuniti: [[name]] + +/community/members.bml.nextlink=(Mukasurat seterusnya...) + +/community/members.bml.prevlink=(Mukasurat sebelumnya...) + +/community/members.bml.settings=[Setings] + +/community/members.bml.success.header=Berjaya + +/community/members.bml.success.message=Penukaran anda telah disimpan dengan jayanya. + +/community/members.bml.success.return=Kembali ke senarai + +/community/members.bml.title=Ahli Komuniti + +/community/members.bml.update=Kemaskinikan seting + +/community/moderate.bml.approve.button=Ya, benarkan + +/community/moderate.bml.approve.header=Benarkan pos ini? + +/community/moderate.bml.approve.preapprove=Tambahkan juga pengguna ini [[user]] ke senarai pengguna pra-dibenarkan ke komuniti ini. + +/community/moderate.bml.approve.text=Anda pasti anda ingin membenarkan pos ini? + +/community/moderate.bml.brlist.actions=Gerakan + +/community/moderate.bml.brlist.poster=Yang membuat pos + +/community/moderate.bml.brlist.subject=Bermula subjek + +/community/moderate.bml.brlist.time=Waktu + +/community/moderate.bml.brlist.view=Ruang pandangan + +/community/moderate.bml.browse.empty=Barisan pengawasan kosong. + +/community/moderate.bml.browse.header=Awasi Komuniti + +/community/moderate.bml.browse.text=Berikut ialah barisan pengawasan untuk komuniti ini [[link]] + +/community/moderate.bml.choice.approve=Benarkan + +/community/moderate.bml.choice.reject=Tolak + +/community/moderate.bml.error.noaccess=Anda tidak mengawasi komuniti [[comm]]. + +/community/moderate.bml.error.noentry=Pos tidak dijumpai (mungkin telah diuruskan oleh pengawas lain). + +/community/moderate.bml.error.nolist=Anda tidak mengawasi sebarang komuniti. + +/community/moderate.bml.error.notfound=Akaun komuniti tidak dijumpai. + +/community/moderate.bml.manage=Uruskan komuniti + +/community/moderate.bml.moderate=Awasi komuniti ini + +/community/moderate.bml.modlist.actions=Gerakan + +/community/moderate.bml.modlist.actmodempty=[Awasi] + +/community/moderate.bml.modlist.actmoderate=Awas + +/community/moderate.bml.modlist.count=Saiz barisan + +/community/moderate.bml.modlist.header=Awasi Komuniti + +/community/moderate.bml.modlist.title=Tajuk + +/community/moderate.bml.modlist.username=Nama Pengguna + +/community/moderate.bml.posted.appheader=Pra-dibenarkan + +/community/moderate.bml.posted.apptext=Juga, pengguna [[user]] telah ditambah ke senarai pengguna pra-dibenarkan untuk komuniti ini. + +/community/moderate.bml.posted.header=Berjaya + +/community/moderate.bml.posted.proterror=Pos ini tidak berjaya diposkan kerana ralat protokol: [[err]] + +/community/moderate.bml.posted.text=Pos telah berjaya diposkan. + +/community/moderate.bml.reject.button=Ya, singkirkannya. + +/community/moderate.bml.reject.header=Singkirkan pos ini? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=Anda boleh juga memberi sebab kepada yang membuat pos kenapa posnya disingkir. Ia akan dihantar melalui emel. + +/community/moderate.bml.reject.text=Anda pasti anda mahu singkirkan pos ini. + +/community/moderate.bml.rejected.header=Disingkirkan. + +/community/moderate.bml.rejected.text=Pos ini telah disingkir. + +/community/moderate.bml.title=Pengawasan Komuniti + +/community/search.bml.button.clear=Kosongkan Borang + +/community/search.bml.button.search=Cari! + +/community/search.bml.checkbox.onlywithpics=Hanya komuniti yang mempunyai gambar + +/community/search.bml.label.byinterest=Berdasarkan Minat + +/community/search.bml.label.bylocation=Berdasarkan Lokasi + +/community/search.bml.label.bytime=Berdasarkan Waktu Kemaskini Jurnal + +/community/search.bml.label.city=Bandar: + +/community/search.bml.label.country=Negara: + +/community/search.bml.label.displayoptions=Tunjuk Pilihan + +/community/search.bml.label.hasmember=Mempunyai Ahli + +/community/search.bml.label.othercriteria=Kriteria Lain + +/community/search.bml.label.outputformat=Format output: + +/community/search.bml.label.records=Rekod setiap muka: + +/community/search.bml.label.searchcomm=Cari Komuniti + +/community/search.bml.label.selecriteria=Pilih komuniti yang anda mahu cari berdasarkan kriteria di bawah. Keputusan adalah berdasarkan hasil gabungan seluruh kriteria yang telah dipilih. Dalam erti kata lain, setiap kotak yang anda tandakan bermaksud "DAN", bukan "ATAU". + +/community/search.bml.label.sortmethod=Susun Mengikut: + +/community/search.bml.label.stateprovince=Negeri/Wilayah: + +/community/search.bml.label.updated=Terakhir dikemaskini + +/community/search.bml.sel.bypicture=Berdasarkan Gambar + +/community/search.bml.sel.communityname=Nama Komuniti + +/community/search.bml.sel.commview=Pandangan Komuniti + +/community/search.bml.sel.day=hari + +/community/search.bml.sel.month=bulan + +/community/search.bml.sel.simple=Mudah + +/community/search.bml.sel.updatetime=Waktu Kemaskini + +/community/search.bml.sel.username=Nama Pengguna + +/community/search.bml.sel.week=minggu + +/community/search.bml.title=Cari Komuniti + +/community/settings.bml.button.changecommunity=Kemaskini Seting + +/community/settings.bml.button.createcommunity=Cipta Komuniti + +/community/settings.bml.error.badpassword=Kata laluan komuniti tidak sah + +/community/settings.bml.error.hasentries=Akaun ini sudah ada pos dan tidak boleh ditukar. + +/community/settings.bml.error.maintainertype=Akaun pengendali mestilah seorang, bukan akaun berkongsi lain. + +/community/settings.bml.error.noaccess=Hanya pengendali komuniti sahaja yang boleh mengubah seting komuniti. Anda bukan pengendali komuniti [[comm]] ini. + +/community/settings.bml.error.notcomm=Bukan akaun komuniti. + +/community/settings.bml.error.notfound=Akaun komuniti tidak dijumpai. + +/community/settings.bml.error.samenames=Akaun pengendali dan akaun komuniti tidak boleh sama. + +/community/settings.bml.label.anybodycan=Semua Ahli
          Sesiapa sahaja boleh membuat pos sebaik sahaja menjadi ahli. + +/community/settings.bml.label.changeheader=Tukar Seting Komuniti + +/community/settings.bml.label.changetext=Di sini anda boleh menukar setting untuk komuniti kepunyaan anda atau yang anda kendalikan. + +/community/settings.bml.label.commchanged=Seting komuniti anda telahpun ditukar. + +/community/settings.bml.label.commcreate=Ini ialah akaun yang anda ingin ubah menjadi sebuah komuniti. Ia mesti sudah dicipta, tapi belum digunakan oleh sebarang individu, kerana selepas ini, ramai orang yang akan menggunakannya. + +/community/settings.bml.label.commcreated=Komuniti anda sudah sedia. + +/community/settings.bml.label.commheader=Akaun Komuniti + +/community/settings.bml.label.comminfo=Maklumat komuniti + +/community/settings.bml.label.commopts=Pilihan Komuniti + +/community/settings.bml.label.commsite=Laman web komuniti + +/community/settings.bml.label.community=Komuniti: + +/community/settings.bml.label.createheader=Cipta Komuniti + +/community/settings.bml.label.createtext<< +Dari sini anda boleh mencipta sebuah akaun komuniti. Sebuah komuniti ialah sejenis akaun istimewa di mana pengguna lain boleh menyertai dan mempos di dalamnya. Sebagai contoh sebuah komuniti, lawati Komuniti Seattle Party. + +. + +/community/settings.bml.label.howoperates=Pilih bagaimana komuniti anda beroperasi. Anda boleh menukarnya nanti. + +/community/settings.bml.label.maintainer=Pengendali: + +/community/settings.bml.label.maintainer.login=Jika ini bukan akaun pengendali, login sebagai pengguna lain. + +/community/settings.bml.label.membership=Keahlian + +/community/settings.bml.label.modheader=Pengawasan + +/community/settings.bml.label.modis=Diawasi
          Pos baru hendaklah dibenarkan oleh pengawas. + +/community/settings.bml.label.modisnt=Tidak diawasi
          Pos baru diterbitkan serta merta. + +/community/settings.bml.label.modtext=Adakah pos ke komuniti ini diawasi? + +/community/settings.bml.label.nmcan=Bukan Ahli Boleh Membuat Pos
          Pengguna boleh mempos ke komuniti ini tanpa menyertainya. + +/community/settings.bml.label.nmcant=Bukan Ahli Tidak Boleh Membuat Pos
          Pengguna perlu menyertai komuniti ini untuk membuat pos. + +/community/settings.bml.label.nmheader|staleness=1 +/community/settings.bml.label.nmheader=Pos oleh Bukan Ahli (sedang digantung) + +/community/settings.bml.label.nmtext=Bolehkah pengguna mempos ke komuniti ini tanpa menyertainya? + +/community/settings.bml.label.openmemb=Keahlian Terbuka
          Sesiapa sahaja boleh menyertai tanpa menunggu kebenaran. + +/community/settings.bml.label.password=Kata Laluan: + +/community/settings.bml.label.postaccess=Kebenaran Mempos + +/community/settings.bml.label.rellinks=Link-link berkaitan: + +/community/settings.bml.label.selcan=Ahli Terpilih
          Hanya sesetengah ahli boleh mempos, setelah diberi kebenaran oleh akaun pengendali. + +/community/settings.bml.label.username=Nama pengguna: + +/community/settings.bml.label.whocanjoin=Siapa boleh menyertai komuniti anda? + +/community/settings.bml.label.whocanpost=Siapa boleh mempos ke komuniti ini? + +/community/settings.bml.manage2=Urus komuniti + +/community/settings.bml.members=[Ahli] + +/community/settings.bml.name=Nama komuniti: [[name]] + +/community/settings.bml.success=Berjaya + +/community/settings.bml.title.create=Cipta Komuniti + +/community/settings.bml.title.modify=Seting Komuniti + +/create.bml.age.check.question=Adakah anda berumur 13 tahun ke bawah? + +/create.bml.age.check.yes=Ya, saya berumur 13 tahun. + +/create.bml.age.check2.question=Adakah umur anda melebihi 13 tahun? + +/create.bml.age.check2.yes=Ya, umur saya melebihi 13 tahun. + +/create.bml.age.head=Umur + +/create.bml.btn.proceed=Teruskan... + +/create.bml.clusterselect.cluster=Kelompok: + +/create.bml.clusterselect.clusternum=Kelompok [[number]] + +/create.bml.clusterselect.head=Seleksi Kelompok + +/create.bml.clusterselect.nocluster=Tiada Kelompok + +/create.bml.clusterselect.text=Sila pilih kelompok yang anda mahu akaun ini dicipta. Perhatian: Ini pilihan cubaan/nyahpijat sahaja. Ketika produksi, pengguna tidak akan memilihnya atau tahu-menahu tentangnya. + +/create.bml.create.head=Membuat Jurnal Baru + +/create.bml.create.text=Membuat LiveJournal yang baru adalah mudah, cuma ikut segala arahan dibawah. + +/create.bml.email.head=Alamat e-mel anda + +/create.bml.email.input.head=Alamat e-mel: + +/create.bml.error.coppa.under13=Harap maaf, disebabkan adanya halangan dari COPPA, anda tidak boleh mengunakan khidmat LifeJournal sehingga sudah berusia 13 tahun. SIla datang kembali selepas hari jadi anda yang ke-13. + +/create.bml.error.email.blank=Masukkan alamat e-mel. + +/create.bml.error.email.lj_domain=Anda tidak boleh menggunakan alias [[domain]] ketika mencipta akaun. Sila guna alamat emel yang lain. + +/create.bml.error.email.nospaces=Ruang kosong tidak dibenarkan di dalam alamat e-mel. Jika anda menggunakan AOL, alamat e-mel anda adalah nama paparan skrin anda setelah dibuang semua ruang kosong, diikuti dengan @aol.com + +/create.bml.error.password.asciionly=Anda hanya boleh menggunakan simbol ASCII di dalam kata laluan. + +/create.bml.error.password.blank=Masukkan kata laluan. + +/create.bml.error.password.nomatch=Kata laluan tidak tepat. + +/create.bml.error.postrequired=POS diperlukan. + +/create.bml.error.username.blank=Masukkan nama atau nama samaran. + +/create.bml.error.username.inuse=Nama pengguna tersebut telah digunakan, sila pilih nama yang lain. + +/create.bml.error.username.iscode=Nama pengguna kelihatan seperti kod jemputan, bukan nama pengguna. + +/create.bml.error.username.mustenter=Masukkan nama pengguna. + +/create.bml.error.username.reserved=Harap maaf, nama pengguna ini telah disimpan. + +/create.bml.name.head=Nama Anda + +/create.bml.name.input.head=Nama: + +/create.bml.name.text=Apakah nama atau nama samaran anda? Nama ini akan kelihatan di atas jurnal anda, dan dalam direktori pengguna jika anda memilih untuk disenaraikan di dalam direktori. Anda tidak perlu memberi nama penuh mahupun nama sebenar anda. + +/create.bml.password.head=Kata Laluan + +/create.bml.password.input.head1=Kata Laluan: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Taip semula kata laluan: + +/create.bml.password.text=Pilih kata laluan. + +/create.bml.proceed.btn.proceed=Teruskan... + +/create.bml.proceed.warning=Cuma tekan Teruskan sekali!! + +/create.bml.success.btn.enterinfo=Masukkan maklumat peribadi + +/create.bml.success.head=Berjaya! + +/create.bml.success.text1=Jurnal anda sudah tercipta. Maklumat pendaftaran penting telahpun diemelkan ke [[email]] dan mengandungi arahan selanjutnya. Pastikan anda mengesahkan terciptanya jurnal anda dengan mengklik link yang dihantar kepada anda dalam emel. + +/create.bml.success.text2=LiveJournal anda boleh didapati di: + +/create.bml.success.text3=Sekarang, sila luangkan sedikit masa untuk mengisi maklumat tentang diri anda. Ia tidak wajib, tetapi membantu kami menggambarkan identiti para pengguna LiveJournal. + +/create.bml.title=Buat Jurnal Baru + +/create.bml.tos.error=Anda harus baca dan setuju kepada syarat-syarat servis sebelum mencipta akaun. + +/create.bml.tos.haveread=Saya sudah membaca dan setuju dengan Syarat-syarat Servis. + +/create.bml.tos.heading=Syarat-syarat Servis + +/create.bml.useacctcodes.entercode=Untuk mencipta akaun baru, sila inputkan kod penciptaan akaun. Untuk maklumat lanjut, sila lawati Bagaimana cara untuk saya mencipta akaun? + +/create.bml.useacctcodes.welcome=Selamat Datang + +/create.bml.username.box.head=Nama Pengguna: + +/create.bml.username.forpaidaccts=Atau, untuk akaun berbayar: + +/create.bml.username.head=Nama Pengguna + +/create.bml.username.ljaddress=Jurnal anda akan berada di alamat tersebut: + +/create.bml.username.text=Setiap pengguna [[sitename]] mesti mempunyai nama pengguna unik. Nama pengguna anda ialah apa yang terlihat di dalam alamat jurnal anda dan apa yang anda guna into login ke pelayan [[pelayan]]. Ia juga muncul apabila anda mempos komen dalam jurnal orang lain. + +/create.bml.username.username=nama pengguna + +/customize/index.bml.change=Tukar + +/customize/index.bml.choose=Anda ingin menggunakan sistem stail lama, atau yang baru? + +/customize/index.bml.choose.header=Pilih sistem stail + +/customize/index.bml.choose.s1=Sistem lama (S1) + +/customize/index.bml.choose.s2=Sistem baru (S2) + +/customize/index.bml.error.cant_generate_user_layer=Tidak dapat membuat lapisan pengguna + +/customize/index.bml.error.fail_create_style=Usaha mencipta stail baru tidak berjaya. + +/customize/index.bml.error.not_your_layout=Bukan susunan kamu. + +/customize/index.bml.error.not_your_theme=Bukan thema kamu. + +/customize/index.bml.error.no_core_parent=Tiada induk teras? + +/customize/index.bml.previews=(Pratonton) + +/customize/index.bml.s1=Sistem stail lama dikonfigurasikan melalui laman Ubah suai Jurnal + +/customize/index.bml.s1.header=Menggunakan S1 + +/customize/index.bml.s2.advanced.denied=Hanya akaun berbayar, tetap dan pengguna awal sahaja boleh menggunakan ruang peribadian lebih taraf. Pelajari tentang manfaat memiliki akaun berbayar. + +/customize/index.bml.s2.advanced.header=Peribadian Lebih Taraf + +/customize/index.bml.s2.advanced.permitted=Untuk mencipta lapisan dan stail baru tanpa acuan, lawati pusat peribadian lebih taraf + +/customize/index.bml.s2.customize=Seting berikut bergantung kepada layout. + +/customize/index.bml.s2.customize.header=Peribadikan Layout + +/customize/index.bml.s2.customize.language=Bahasa-bahasa berikut adalah disokong penuh atau separa oleh layout ini. + +/customize/index.bml.s2.customize.language.custom=(Khas) + +/customize/index.bml.s2.customize.language.header=Bahasa + +/customize/index.bml.s2.customize.settings=Jika anda ingin peribadikan jurnal anda lagi, sini anda boleh mengubah setiap seting tersendiri untuk mendapatkan rupa seperti anda mahu. + +/customize/index.bml.s2.customize.settings.delete=Buang Peribadian. + +/customize/index.bml.s2.customize.settings.edit=Edit Peribadian + +/customize/index.bml.s2.customize.settings.header=Tukar seting tersendiri + +/customize/index.bml.s2.customize.settings.new=Peribadikan + +/customize/index.bml.s2.customize.themes=Pilih daripada tema-tema pilihan berikut untuk layout ini. + +/customize/index.bml.s2.customize.themes.default=(Layout Asal) + +/customize/index.bml.s2.customize.themes.header=Tema-tema + +/customize/index.bml.s2.layout=Pilih layout anda. Kerana pemilihan tema dan modifikasi khas bergantung kepada layout anda, menukar seting ini akan membuang semua edit lain yang telah anda lakukan. + +/customize/index.bml.s2.layout.header=Langkah 1: Layout + +/customize/index.bml.title=Peribadikan Jurnal + +/developer/index.bml.clients=Jadi anda ingin mencipta atau memperbaiki sebuah klien LiveJournal untuk platform anda? Bagus! Di bawah adalah beberapa sumber penting bagi anda pelajari bagaimana LiveJournal berfungsi. + +/developer/index.bml.clients.header=Menulis Klien LiveJournal + +/developer/index.bml.clients.links<< +
          +
          Protokol Klien <->Pelayan LiveJournal
          +
          Pelajari bagaimana klien Livejournal di desktop anda berkomunikasi dengan pelayan LiveJournal dan sebaliknya. Inilah perkara terpenting yang perlu anda fahami sebelum membina atau memperbaiki klien untuk platform anda.
          +
          Dokumen Protokol Lengkap
          +
          Segala mod dan cara protokol yang berlainan.
          +
          Senarai Klien
          +
          Senarai kebanyakan klien yang digunakan untuk berhubung dengan LiveJournal. Kebanyakannya adalah 'open source' dan semua adalah percuma. Tempat yang bagus untuk mendapat contoh untuk klien anda.
          +
          + +. + +/developer/index.bml.code=Untuk melihat kod yang menjadi asas LiveJournal, serta pengaturcaraan klien-klien yang ada, sila ke laman Kod. + +/developer/index.bml.code.header=Tempat Simpanan Kod LiveJournal + +/developer/index.bml.dbschema<< +Ingin tahu tentang skema pangkalan data? +SQL yang digunakan untuk mencipta kesemua table dan kandungannya termasuk dalam kod pelayan. + +. + +/developer/index.bml.dbschema.header=Skema Pangkalan Data + +/developer/index.bml.embedding=Ingin menanam jurnal anda dalam hompej sendiri? Ada beberapa cara untuk melakukannya, bergantung kepada tahap kawalan yang anda ada pada pelayan anda. Anda hanya perlu risau tentang perkara ini jika anda tidak suka www.livejournal.com di dalam URL jurnal anda. + +/developer/index.bml.embedding.header=Menanam LiveJournal + +/developer/index.bml.notice.header=Notis + +/developer/index.bml.notice1=Maklumat berikut hanya untuk ahli program dan pengguna yang arif sahaja. Jika anda hanya mahu menggunakan LiveJournal untuk menyimpan jurnal anda sahaja, baguslah! Pengguna biasa tidak perlu risau mengenai perkara ini. + +/developer/index.bml.notice2=Walaubagaimanapun, kandungan di bawah terbahagi kepada dua bahagian: maklumat untuk memperibadikan rupa laman LiveJournal, dan maklumat untuk menulis klien LiveJournal kepada pelayan LiveJournal. + +/developer/index.bml.styles=Tidak suka rupa jurnal anda? Jangan risau... segalanya fleksibel dan jika anda membaca dokumen di bawah anda akan tahu segala yang anda perlu tahu untuk mengubah laman anda ke apa-apa pun rupa yang anda mahu. + +/developer/index.bml.styles.header=Memperibadikan rupa sebuah LiveJournal + +/developer/index.bml.styles.s1.header=Sistem Stail 1 + +/developer/index.bml.styles.s1.system=Sistem Stail + +/developer/index.bml.styles.s1.system.about=Gambaran keseluruhan am cara sistem stail pertama disusun. + +/developer/index.bml.styles.s1.varlist=Senarai Pembolehubah + +/developer/index.bml.styles.s1.varlist.about=Senarai kesemua pembolehubah yang anda boleh peribadikan mengikut susuna abjad. + +/developer/index.bml.styles.s1.views=Lihat Jenis + +/developer/index.bml.styles.s1.views.about=Senarai pelbagai jenis cara anda boleh melihat jurnal anda, dan butirannya. + +/developer/index.bml.styles.s2.header=Sistem Stail 2 + +/developer/index.bml.styles.s2.layerbrowse=Lapisan Browser S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Senarai penuh lapisan S2 awam yang meliputi stail sistem S2. Yang penting di sini ialah lapisan teras, yang mendefinisikan pembolehubah asas, fungsi, dan kelas yang menjadikan S2 sebuah bahasa gubahan yang berkuasa. + +/developer/index.bml.styles.s2.manual=Manual S2 + +/developer/index.bml.styles.s2.manual.about=Maklumat lengkap tentang cara menggunakan S2 dalam LiveJournal. + +/developer/index.bml.title=Maklumat Pembina + +/directory.bml.error.accounttype=Maaf, jenis akaun anda tidak membenarkan penggunaan direktori, atau anda sekarang ini belum lagi login. Jika jenis akaun anda membenarkan penggunaan direktori, pastikan anda sudah login dan cuba lagi. + +/doc/index.bml.about=Selamat datang ke tempat simpanan dokumentasi LiveJournal, di mana anda boleh mendapati maklumat tentang kebanyakan topik mengenai servis dan perisian pelayan LiveJournal. Sila pilih satu topik daripada senarai di bawah. + +/doc/index.bml.about.header=Selamat Datang + +/doc/index.bml.docs.faq.about=FAQ atau Soal Jawab mengenai LiveJournal.com + +/doc/index.bml.docs.header=Dokumen + +/doc/index.bml.docs.howto.about=Tip dan helah untuk memperibadikan akaun LiveJournal anda + +/doc/index.bml.docs.server.about=Segala yang anda ingin tahu untuk memasang, mentadbir dan menggodam sebuah susunan LiveJournal. + +/doc/index.bml.docs.server.title=Manual Pelayan LiveJournal + +/doc/index.bml.docs.tour.about=Direkabentuk untuk pelawat baru untuk lebih mengenali laman ini + +/doc/index.bml.docs.tour.title=Lawatan + +/doc/index.bml.title=Dokumentasi + +/doc/index.bml.volunteering.about=Jika anda ingin membantu dalam mendokumentasikan LiveJournal, sila lawati forum-forum berikutnya: + +/doc/index.bml.volunteering.header=Bersukarela + +/doc/index.bml.volunteering.ljsysdoc=Perbincangan mengenai sistem dokumentasi LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=Perbincangan dokumentasi pengguna tamat + +/doc/tour/index.bml.clients.caption<< +Klien LiveJournal adalah aturcara kecil yang beroperasi dalam komputer anda, membenarkan anda mengemaskinikan jurnal anda apabila online, tanpa perlu membuka sebarang tetingkap browser. +Pelbagai klien wujud untuk apa saja platfrom, dan kebanyakannya boleh diperibadikan. +. + +/doc/tour/index.bml.clients.title=Klien-klien + +/doc/tour/index.bml.comms.caption=LiveJournal ialah sebuah komuniti interaktif yang besar, jadi tidak hairanlah jika ramai pengguna yang berkongsi minat. Oleh itu, kami menawarkan kebolehan untuk mencipta komuniti, atau jurnal di mana orang boleh menerbitkan pos. + +/doc/tour/index.bml.comms.title=Komuniti-komuniti + +/doc/tour/index.bml.create.caption=LiveJournal ialah komuniti jurnal berdasarkan keahlian. Laman ini menerangkan apa yang termaktub dalam keahlian itu, kenapa ia penting dan manfaatnya. Laman ini juga mengandungi borang untuk mencipta akaun anda sendiri. + +/doc/tour/index.bml.create.title=Mencipta Akaun + +/doc/tour/index.bml.friends.caption=Anda juga boleh menjejaki sahabat anda melalui kemudahan 'sahabat' kami. Jika anda mendapati sebuah jurnal yang anda fikir menarik, tambahkannya ke senarai sahabat anda, yang membenarkan anda membaca kesemua pos sahabat anda dalam laman yang sama. + +/doc/tour/index.bml.friends.title=Para Sahabat + +/doc/tour/index.bml.intro.caption=Lawatan ini direka untuk pelawat baru supaya lebih mengenali laman ini. Ini akan menunjukkan kepada anda di mana bahagian-bahagian terpenting, dan juga beberapa kemudahan menarik yang lain. + +/doc/tour/index.bml.intro.title=Selamat Datang + +/doc/tour/index.bml.modify.caption=Anda juga boleh menformatkan jurnal anda dalam pelbagai cara, dengan menggunakan stail dan skema warna yang sudah ditentukan. Jadikan jurnal anda seunik yang anda mahu. + +/doc/tour/index.bml.modify.title=Memberikan Sentuhan Peribadi + +/doc/tour/index.bml.nav.next=Berikut --> + +/doc/tour/index.bml.nav.prev=<-- Sebelum + +/doc/tour/index.bml.profile.caption=Ahli LiveJournal digalakkan untuk manambah maklumat tentang diri sendiri dalam profil mereka, supaya kami mendapat gambaran siapa yang menggunakan servis ini dan cara terbaik kami dapat melayan mereka. Tetapi, ini tidak wajib, dan maklumat yang memang perlu untuk menggunakan LiveJournal hanyalah nama, alamat emel dan kata laluan. + +/doc/tour/index.bml.profile.title=Profil-profil + +/doc/tour/index.bml.sitemap.caption=Diharapkan lawatan ini dapat memberikan anda maklumat permulaan yang berguna tentang laman Livejournal dan servisnya. Jika anda memerlukan pertolongan berkaitan LiveJournal, silalah menghubungi jabatan sokongan kami. Jika anda ingin meneroka lagi, sila rujuk peta laman untuk melihat senarai kesemua mukasurat dalam laman ini. + +/doc/tour/index.bml.sitemap.title=Peta Laman + +/doc/tour/index.bml.support.caption=Mukasurat sokongan menyenaraikan bahagian yang membantu menerangkan apa itu LiveJournal, soalan-soalan yang kerap ditanya mengenai laman ini dan maklumat berguna lain tentang servis, syarikat dan komuniti ini secara amnya. + +/doc/tour/index.bml.support.title=Mendapat Bantuan + +/doc/tour/index.bml.title=Lawatan - [[title]] + +/doc/tour/index.bml.update.caption=Mengemaskinikan sebuah LiveJournal ialah teras servis LiveJournal; di sini kami menawarkan kepada ahli peluang untuk berkongsi kehidupan dan pendapat mereka. Mengemaskinikan jurnal adalah mudah. Hanya tulis pos anda dalam kotak yang diberikan dan tekan butang "Kemas kini Jurnal". Kami juga ada menawarkan kemudahan lebih taraf di mukasurat kemas kini kami, seperti kemudahan memeriksa ejaan dan kemudahan memberi maklumat lebih tentang pos anda, seperti musik dan mood semasa anda. + +/doc/tour/index.bml.update.title=Membaui + +/editinfo.bml.allowshowcontact.about=Anda patut membolehkan pilihan ini. Ini membenarkan orang lain untuk berhubung dengan anda dengan menunjukkan alamat emel, nombor ICQ dan nama skrin AOL Instant Messenger anda dalam LiveJournal anda. + +/editinfo.bml.allowshowcontact.email=Jika kelihatan, alamat e-mel yang ingin dipaparkan: + +/editinfo.bml.allowshowcontact.email.actual_only=Alamat sebenar sahaja + +/editinfo.bml.allowshowcontact.email.both=Kedua-duanya (sebenar + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Alamat LiveJournal sahaja + +/editinfo.bml.allowshowcontact.email.neither=Tidak. Jangan tunjuk sebarang alamat e-mel. + +/editinfo.bml.allowshowcontact.email.no_show=Jangan tunjuk alamat e-mel. + +/editinfo.bml.allowshowcontact.email.show=Paparkan alamat e-mel. + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Dengan pilihan di atas, anda boleh pilih untuk menyembunyikan alamat emel anda (dan masih lagi menunjukkan maklumat hubung yang lain), sama ada hanya menunjukkan alamat emel LiveJournal anda (untuk akaun berbayar sahaja), atau alamat sebenar anda atau kedua-duanya sekali. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Dengan pilihan yang di atas, kamu boleh memilih untuk sembunyi alamat emel (dan pada masa yang sama menunjukkan informasi yang lain) + +/editinfo.bml.allowshowcontact.title=Mahu menunjukkan informasi berkaitan dengan kontact di LiveJournal kamu? + +/editinfo.bml.allowshowinfo.about=Pilih opsyen ini jika anda mahu bandar/negeri/negara dan tarikh lahir anda dilihat oleh pengguna lain. + +/editinfo.bml.allowshowinfo.title=Paparkan lokasi & hari jadi? + +/editinfo.bml.autotranslate.about<< +Gunakan opsyen ini untuk memberitahu LiveJournal pengengkodan yang anda telah gunakan ketika menulis pos atau komen sebelum laman itu ditukarkan kepada Unicode. +Jika anda menulis dalam Bahasa Inggeris, pilih 'Western European' di sini. +. + +/editinfo.bml.autotranslate.header=Tukarkan pos-pos lama secara automatik dari: + +/editinfo.bml.bday.title=Hari Jadi + +/editinfo.bml.bday.year.opt=terpulang untuk menulis tahun + +/editinfo.bml.bdayreminders.about=Sila tanda pada kotak tersebut jika anda ingin menerima e-mel mengenai hari jadi sahabat-sahabat anda dari LiveJournal. + +/editinfo.bml.bdayreminders.header=Hantar pengingatan hari jadi kepada saya (kini sedang digantung) + +/editinfo.bml.bio.about=Sini anda boleh menulis sedikit tentang diri anda. Ini akan terbit di dalam laman Maklumat Pengguna anda. + +/editinfo.bml.bio.header=Mengenai Anda + +/editinfo.bml.blockrobots.about<< +Jika anda pilih opsyen ini, robot-robot akan diberitahu untuk pergi. +Tidak semua robot menghormati arahan ini. +. + +/editinfo.bml.blockrobots.header=Halang Robot/Lelabah daripada mengindekskan jurnal anda. + +/editinfo.bml.chat.msnusername.title=Kata Pengguna MSN + +/editinfo.bml.chat.yahooid.title=ID Yahoo! + +/editinfo.bml.city.title=Bandar + +/editinfo.bml.country.choose=Pilih Negara + +/editinfo.bml.country.title=Negara + +/editinfo.bml.donotlog=Tidak + +/editinfo.bml.email.title=E-mel + +/editinfo.bml.enableboards.about=Pilih opsyen ini jika anda mahu orang lain diberi kebenaran untuk menjawab pos anda. + +/editinfo.bml.enableboards.header=Benarkan papan mesej + +/editinfo.bml.encoding.about=Jangan risau tentang ini. Secara amnya, hanya pengguna antarabangsa yang menulis dalam beberapa bahasa yang perlu membuat penukaran di sini. + +/editinfo.bml.encoding.header=Pilihan Pengengkodan + +/editinfo.bml.error.day.notinmonth=Hari tidak sah untuk bulan itu. + +/editinfo.bml.error.day.outofrange=Tarikh lahir tidak sah. Sila catatkan hari dari 1-31 + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Anda tidak boleh menginput sebuah alamat emel @[[domain]]. +Inputkan alamat sebenar anda di dalam ruang ini. +Jika anda pengguna berbayar, alamat [[user]]@[[domain]] anda akan dihantar ke alamat sebenar anda. +Untuk memilih alamat emel yang mana (atau kedua-duanya) yang akan ditunjuk kepada semua, lihat opsyen di bawah opsyen 'Tunjukkan Maklumat Hubungan anda'. +. + +/editinfo.bml.error.email.none=Anda mesti beri alamat emel anda + +/editinfo.bml.error.email.no_space<< +Ruang kosong tidak dibenarkan dalam sebuah alamat emel. +Jika anda menggunakan AOL, sila ingat bahawa alamat emel anda ialah nama skrin anda dengan semua ruang kosong dibuang, diikuti oleh @aol.com +. + +/editinfo.bml.error.excessive_int=Maaf, anda telah menyenaraikan terlalu banyak minit. Hadnya ialah 150, tetapi anda telah menyenaraikan sebanyak [[intcount]]. Sebarang perubahan yang anda telah buat kepada minat anda tidak disimpan. Pergi balik dan potong senarai anda, kemudian simpan semula. + +/editinfo.bml.error.invalidbio=Bio anda yang tersimpan mempunyai aksara tidak sah. Anda harus lawati Laman Penukaran untuk menukar bio anda kepada Unicode. + +/editinfo.bml.error.invalidints=Senarai minat anda yang tersimpan mempunyai aksara tidak sah. Anda harus lawati Laman Penukaran untuk menukar bio anda kepada Unicode. + +/editinfo.bml.error.invalidname=Nama anda mempunyai aksara tidak sah. Anda harus lawati Laman Penukaran untuk menukar bio anda kepada Unicode. + +/editinfo.bml.error.locale.country_ne_state=Anda telah menyatakan United States sebagai negara anda, tetapi anda menaib sebuah negeri bukan US di ruang 'negeri lain'. + +/editinfo.bml.error.locale.invalid_country=Entah bagaimana anda telah memilih negara tidak sah. + +/editinfo.bml.error.locale.state_ne_country=Anda menyatakan sebuah negara bukan US tetapi memilih sebuah negeri dalam US. + +/editinfo.bml.error.locale.zip_ne_state<< +Zipkod anda tidak sepadan dengan negeri yang anda pilih. +Sama ada betulkan maklumat itu, atau padam satu atau kedua-dua ruang negeri dan zipkod. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Anda telah menginputkan zipkod tetapi tidak memilih United States sebagai negara anda. +Kami hanya mengumpul maklumat zipkod daripada mereka yang menetap di dalam US. +Pergi balik dan padam zipkod atau pilih United States sebagai negara anda. +. + +/editinfo.bml.error.month.outofrange=Bulan lahir tidak sah. Inputkan sebuah bulan dari 1-12. (Jan - Dis) + +/editinfo.bml.error.noname=Nama anda diperlukan. Sekurang-kurangnya berikan nama pertama anda, atau nama samaran. + +/editinfo.bml.error.tm.require.number=Jika anda ingin menggunakan perkhidmatan SMS, anda mesti sertakan nombor telefon anda. + +/editinfo.bml.error.tm.require_provider<< +Jika anda ingin menggunakan perkhidmatan SMS, anda harus pilih penyedia servis (service provider) anda. + +Jika penyedia servis anda tidak disenaraikan, sila hubungi kami dengan maklumat tentang kemudahan SMS servis anda supaya kami boleh menyediakan sokongan untuknya. +. + +/editinfo.bml.error.year.notenoughdigits=Tahun lahir tidak sah. Sila inputkan tahun 4 digit. + +/editinfo.bml.error.year.outofrange=Tahun lahir tidak sah. + +/editinfo.bml.finished.about=Bila selesai, tekan butang 'Simpan Penukaran' di bawah: + +/editinfo.bml.finished.header=Selesai? + +/friends/add.bml.btn.add=Tambah [[Pengguna]] + +/friends/add.bml.btn.modify=Mengubah + +/friends/add.bml.btn.remove=Pindah + +/friends/add.bml.colors.header=Warna + +/friends/add.bml.colors.hover=Letakkan tetikus di atas warna untuk nama warnanya + +/friends/add.bml.colors.text=Kamu boleh memilih warna yang akan mewakili [[pengguna]] dalam sahabat + +/friends/add.bml.confirm.header=Tambah [[pengguna]] sebagai sahabat? + +/friends/add.bml.confirm.text=Untuk menambah [[pengguna]] dalam sahabat, tekan butang di bawah. + +/index.bml.boldcreate=Reka LiveJournal anda! + +/index.bml.frank.image.alt=Frank, kambing maskot LiveJournal. + +/index.bml.frank.logo="Baaaaah", kata Frank. + +/login.bml.login.forget=Terlupa? + +/login.bml.login.otheropts=Pilihan lain: + +/support/faqbrowse.bml.backfaq=Kembali ke Soal Jawab. + +/support/faqbrowse.bml.backsupport=Kembali ke bahagian bantuan. + +/support/faqbrowse.bml.lastupdated=Tarikh kemaskini terakhir: + +/talkpost.bml.allowedhtml=HTML yang dibenarkan + +/talkpost.bml.error.cannotreplynopost=Anda tidak dibenarkan membalas pos yang tidak wujud. + +/talkpost.bml.error.nocommentsjournal=Pengguna tidak membenarkan komen di dalam jurnalnya. + +/talkpost.bml.error.nocommentspost=Pengguna tidak membenarkan komen untuk pos ini. + +/talkpost.bml.error.noreplypost=Pos yang ingin dibalas tidak dijumpai (telah padam?) + +/talkpost.bml.loganonip=Pengumuman! Pengguna ini telah memilih untuk merekod alamat IP oleh pembalas "anonymous". + +/talkpost.bml.opt.noautoformat=Jangan format secara automatik: + +/talkpost.bml.opt.noimage=Tiada Gambar + +/talkpost.bml.opt.preview=Previu + +/talkpost.bml.opt.subject=Perkara + +/talkpost.bml.opt.submit=Pos Komen + +/talkpost.bml.paraformat=Perenggan akan diformat secara automatik. + +/talkpost.bml.postresponse=Hantar komen sebagai maklum balas: + +/talkpost.bml.title=Hantar Komen + +/talkpost_do.bml.error.badpassword=Password yang salah telah diberikan untuk nama pengguna ini. Anda boleh mendapatkan semula password anda di sini jika terlupa. + +/talkpost_do.bml.error.badusername=Nama pengguna LiveJournal yang diberikan tidak wujud. Anda boleh dapatkan kembali nama pengguna anda di sini jika anda sudah terlupa, atau anda boleh mengepos sebagai "Anonymous". + +/talkread.bml.fromip=(dari [[ip]]) + +/talkread.bml.noreplies=Tiada balasan + +/talkread.bml.nosubject=(tiada perkara) + +/talkread.bml.replysuspended=(Maklum balas dari pengguna yang telah digantung keahliannya) + +/talkread.bml.title=Baca Komen + +btn.search=Cari + +dystopia.hello_anonymous=Selamat datang ke LiveJournal! + +dystopia.nav.findint=Berdasarkan Minat + +dystopia.nav.findrandom=Rambang + +dystopia.nav.findregion=Berdasarkan Rantau + +dystopia.nav.home=Laman Utama + +dystopia.nav.journalcalendar=Kalendar + +dystopia.nav.journalfriends=Sahabat + +dystopia.nav.journalinfo=Maklumat Pengguna + +dystopia.nav.journalrecent=Terkini + +dystopia.nav.updatejournal=Kemaskini Jurnal + +dystopia.navhead.findusers=Cari Pengguna Lain + +dystopia.navhead.journal=Jurnal Anda + +dystopia.navhead.welcome=Selamat Datang! + +dystopia.search.icq=Nombor ICQ + +dystopia.search.int=Minat + +Email=E-mel + +error.username_notfound=Nama pengguna tidak ditemui. + +langname.be=Bahasa Belarus + +langname.da=Bahasa Denmark + +langname.de=Bahasa Jerman + +langname.en=Bahasa Inggeris + +langname.en_GB=Bahasa Inggeris (UK) + +langname.en_LJ=Bahasa Inggeris + +langname.eo=Bahasa Esperanto + +langname.es=Bahasa Sepanyol + +langname.fi=Bahasa Finland + +langname.fr=Bahasa Perancis + +langname.ga=Bahasa Irish + +langname.gd=Bahasa Gaelic + +langname.he=Bahasa Hebrew + +langname.hu=Bahasa Hungary + +langname.is=Bahasa Iceland + +langname.ja=Bahasa Jepun + +langname.ms=Bahasa Melayu + +langname.nl=Bahasa Belanda + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Harap maaf + +talk.anonwrote=Seseorang menulis, + +talk.anonwrote_comm=Seseorang menulis di [[commlink]], + +talk.commentsread=Baca komen + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_malay + diff --git a/ljcom/bin/upgrading/nb.dat b/ljcom/bin/upgrading/nb.dat new file mode 100644 index 0000000..d387ef0 --- /dev/null +++ b/ljcom/bin/upgrading/nb.dat @@ -0,0 +1,889 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Om du vil slette eller angre sletting av din dagbok, så gjøres det her. Om du sletter dagboken har du 30 dager på deg å angre slettingen. Etter 30 dager vil dagboken forsvinne for godt og det vil ikke være mulig å få den tilbake. + +/accountstatus.bml.journalstatus.head=Status for dagbokaktivering + +/accountstatus.bml.journalstatus.select.activated=Aktivert + +/accountstatus.bml.journalstatus.select.deleted=Slettet + +/accountstatus.bml.journalstatus.select.suspended=Fryst + +/accountstatus.bml.title=Kontostatus + +/allpics.bml.current=Gjeldende ikoner + +/allpics.bml.default=Standard + +/allpics.bml.edit2=Du er kanskje interessert i å redigere dine nøkkelord eller laste opp et nytt bilde. + +/allpics.bml.error.noparam=Du må skrive et brukernavn. + +/allpics.bml.keywords=Nøkkelord: + +/allpics.bml.nopics.text.other=Denne brukeren har ikke lastet opp noen ikoner. + +/allpics.bml.nopics.text2=Du har ikke lastet opp noen ikoner. For å laste opp et, gå hit. + +/allpics.bml.nopics.title=Ingen ikoner + +/allpics.bml.pics=Her er ikonene til [[bruker]]. + +/allpics.bml.title=Ikoner + +/changepassword.bml.btn.proceed=Fortsett + +/changepassword.bml.changepassword.header=Bytt passord + +/changepassword.bml.changepassword.instructions=Fyll ut skjemaet nedenfor for å bytte passord. Om du ønsker hjelp til å velge et godt passord og holde kontoen din trygg, les denne OBS-artikkelen. + +/changepassword.bml.email.body<< +Ditt passord har blitt byttet for [[sitename]]. + +Om du skulle miste det, gå til: + +  [[siteroot]]/lostinfo.bml + +Vennlig hilsen, +[[sitename]] sine utviklere + +[[siteroot]] +. + +/changepassword.bml.email.subject=Byttet passord + +/changepassword.bml.error.badcheck=Passordbytte feilet: [[error]] + +/changepassword.bml.error.badnewpassword=De to passordene du skrev for å bekrefte byttet stemmer ikke overens. Du kan ha skrevet feil bekreftelsesfeltet. Prøv å skrive passordet og bekreftelsen inn på ny. + +/changepassword.bml.error.badoldpassword=Ditt nåværende passord er ikke riktig. + +/changepassword.bml.error.blankpassword=Ditt nye passord kan ikke være tomt. + +/changepassword.bml.error.changetestaccount=Kan ikke endre testkontoets passord. + +/changepassword.bml.error.characterlimit=Passord kan ikke ha flere enn 30 tegn. + +/changepassword.bml.error.invaliduser=Brukeren [[user]] eksisterer ikke. Er du sikker på at du skrev brukernavnet rett? + +/changepassword.bml.error.mustenterusername=Du må skrive inn ditt brukernavn. + +/changepassword.bml.error.nonascii=Passord kan kun inneholde ASCII-tegn (latinsk alfabet). Vennligst bruk kun ASCII-godkjente tegn. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Du kan ikke bytte passord før din e-postadresse er bekreftet. + +/changepassword.bml.newpassword=Nytt passord: + +/changepassword.bml.newpasswordagain=Nytt passord (bekreftelse): + +/changepassword.bml.oldpassword=Nåværende passord: + +/changepassword.bml.proceed.instructions=Trykk knappen nedenfor og passordet blir endret til det nye passordet. Du vil motta en bekreftelse per e-post. + +/changepassword.bml.success.text=Ditt passord er endret til ditt nye passord, og en e-post er sendt med bekreftelse. + +/changepassword.bml.title=Endre passord + +/community/index.bml.title=Samfunnsenter + +/community/join.bml.button.join=Melde inn i samfunn + +/community/join.bml.label.addtofriends=Legg "[[maintainer]]" til din venneliste.
          + +/community/join.bml.label.allowposting=Dette samfunnet tillater posting fra alle dets medlemmer, så du har nå lov å poste i det. Hvis du allerede har en LiveJournal-klient åpen må du logge ut og inn igjen for at listen over dagbøker og samfunn du kan poste i, skal oppdateres. + +/community/join.bml.label.auth=Selv om du nå er listet som et medlem, tillater dette samfunnet kun posting av tillatte brukere. Kontakt en av bestyrerene dersom du ønsker å skrive egne oppføringer. Nedenfor er en liste over bestyrere for dette samfunnet: [[admins]] + +/community/join.bml.label.banned=Dette samfunnets bestyrer(e) har nektet deg fra å delta. + +/community/join.bml.label.closed=Dette samfunnet er lukket. Om du ønsker å melde deg inn må du kontakte en bestyrer. Neden er en liste over bestyrere for dette samfunnet: [[admins]] + +/community/join.bml.label.commlogged=Du er pålogget som en delt konto/samfunn, og ikke din personlige konto. + +/community/join.bml.label.errorcomminfo=Angitt informasjon for samfunnet ditt er ugyldig. + +/community/join.bml.label.expls=Trykk på knappen nedenfor for å melde deg inn i "[[maintainer]]"-samfunnet. Fjern haken fra boksen nedenfor dersom du ønsker å delta i samfunnet uten å legge det til din venneliste. + +/community/join.bml.label.loginfirst=For å melde deg inn i et samfunn må du først logge på. + +/community/join.bml.label.membernow=Du er nå et medlem i [[commname]] + +/community/join.bml.label.sure=Er du sikker? + +/community/join.bml.success=Vellykket + +/community/join.bml.title=Melde inn i samfunn + +/community/leave.bml.button.leave=Melde ut av samfunn + +/community/leave.bml.label.buttontoleave=Trykk knappen nedenfor for å forlate "[[commname]]". + +/community/leave.bml.label.infoerror=Angitt informasjon for samfunnet er ugyldig. + +/community/leave.bml.label.logoutfirst=For å melde deg ut av et samfunn må du først logge på. + +/community/leave.bml.label.removed=Du har nå forlatt [[commname]] + +/community/leave.bml.label.removefromfriends=Også fjerne "[[user]]" fra din venneliste. + +/community/leave.bml.success=Vellykket + +/community/leave.bml.sure=Er du sikker? + +/community/leave.bml.title=Forlat samfunn + +/community/manage.bml.commlist.actions=Handlinger + +/community/manage.bml.commlist.actmembers=[Medlemmer] + +/community/manage.bml.commlist.actmembers2=Medlemmer + +/community/manage.bml.commlist.actsettings=[Valg] + +/community/manage.bml.commlist.actsettings2=Valg + +/community/manage.bml.commlist.header=Dine samfunn + +/community/manage.bml.commlist.none=Du er ikke bestyrer av noen samfunn. + +/community/manage.bml.commlist.text=Her er samfunnene du bestyrer eller assisterer i: + +/community/manage.bml.commlist.title=Navn: + +/community/manage.bml.commlist.username=Brukernavn + +/community/manage.bml.create.header=Opprett et samfunn + +/community/manage.bml.create.text=Du kan også opprette et nytt samfunn. + +/community/manage.bml.title=Samfunnstyring + +/community/members.bml.error.alreadyadded=[[user]] ble ikke lagt til fordi de allerede hadde tilgang til dette samfunnet. + +/community/members.bml.error.alreadysent=[[user]] kunne ikke legges til fordi de ikke har svart på bekreftelsen som ble sendt som e-post den [[datetime]]. Vennligst vent til de har svart. + +/community/members.bml.error.invaliduser=Kan ikke legge til samfunn eller syndicated konto: [[user]] + +/community/members.bml.error.noaccess=Kun samfunnsbestyrere kan tilpasse medlemskapslister. Du er ikke en bestyrer i samfunn [[comm]]. + +/community/members.bml.error.noattr=Ingen atributter valgt for bruker: [[user]] + +/community/members.bml.error.nocomm=Samfunnet finnes ikke. + +/community/members.bml.error.nouser=Brukeren eksisterer ikke: [[user]] + +/community/members.bml.key.admin=Bestyrer + +/community/members.bml.key.member=Medlem + +/community/members.bml.key.moderate=Moderatør + +/community/members.bml.key.post=Tilgang til å oppdatere + +/community/members.bml.key.preapprove=Ikke moderert + +/community/members.bml.manage2=Tilpass samfunn + +/community/members.bml.name=Samfunnets navn: [[name]] + +/community/members.bml.nextlink=(Neste side...) + +/community/members.bml.prevlink=(Forrige side...) + +/community/members.bml.settings=[Valg] + +/community/members.bml.success.header=Vellykket + +/community/members.bml.success.message=Dine tilpasninger ble vellykket lagret. + +/community/members.bml.success.return=Gå tilbake til listen + +/community/members.bml.title=Samfunnsmedlemmer + +/community/members.bml.update=Oppdater valg + +/community/moderate.bml.approve.button=Ja, godta + +/community/moderate.bml.approve.header=Godta denne oppføringen? + +/community/moderate.bml.approve.preapprove=Legg også [[user]] til listen av forhåndsgodkjente brukere for dette samfunnet. + +/community/moderate.bml.approve.text=Er du sikker på at du vil godkjenne denne oppføringen? + +/community/moderate.bml.brlist.actions=Handlinger + +/community/moderate.bml.brlist.subject=Emnet begynner + +/community/moderate.bml.brlist.time=Tid + +/community/moderate.bml.brlist.view=Vis + +/community/moderate.bml.browse.empty=Moderasjonskøen er tom. + +/community/moderate.bml.browse.header=Moderer samfunn + +/community/moderate.bml.browse.text=Her er moderasjonskøen for samfunnet [[link]] + +/community/moderate.bml.choice.approve=Godkjenn + +/community/moderate.bml.choice.reject=Avvis + +/community/moderate.bml.error.noaccess=Du modererer ikke samfunn [[comm]]. + +/community/moderate.bml.error.noentry=Oppføringen finnes ikke (den er kanskje allerede håndtert av en annen moderatør). + +/community/moderate.bml.error.nolist=Du modererer ingen samfunn. + +/community/moderate.bml.error.notfound=Samfunnskontoen finnes ikke. + +/community/moderate.bml.manage=Tilpass samfunn + +/community/moderate.bml.moderate=Moderer dette samfunnet + +/community/moderate.bml.modlist.actions=Handlinger + +/community/moderate.bml.modlist.actmodempty=[Moderer] + +/community/moderate.bml.modlist.actmoderate=Moderer + +/community/moderate.bml.modlist.count=Kølengde + +/community/moderate.bml.modlist.header=Moderer samfunn + +/community/moderate.bml.modlist.title=Tittel + +/community/moderate.bml.modlist.username=Brukernavn + +/community/moderate.bml.posted.appheader=Forhåndsgodjent + +/community/moderate.bml.posted.apptext=Brukeren [[user]] ble også lagt til listen over forhåndsgodkjente brukere av dette samfunnet. + +/community/moderate.bml.posted.header=Vellykket + +/community/moderate.bml.posted.proterror=Denne oppføringen ble ikke postet grunnet protokoll-feil: [[err]] + +/community/moderate.bml.posted.text=Oppdateringen var vellykket. + +/community/moderate.bml.reject.button=Ja, avvis + +/community/moderate.bml.reject.header=Avvis denne oppføringen? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=Du kan også beskrive til innsenderen hvorfor du avviste oppføringen. Forklaringen vil bli sendt per e-post. + +/community/moderate.bml.reject.text=Er du sikker på at du vil avvise denne oppføringen? + +/community/moderate.bml.rejected.header=Avvist + +/community/moderate.bml.rejected.text=Oppføringen er avvist. + +/community/moderate.bml.title=Moderer samfunn + +/community/search.bml.button.clear=Tilbakestill + +/community/search.bml.button.search=Søk! + +/community/search.bml.checkbox.onlywithpics=Kun samfunn med bilder + +/community/search.bml.label.byinterest=Etter interesse + +/community/search.bml.label.bylocation=Etter område + +/community/search.bml.label.bytime=Etter sist oppdatert i dagbok + +/community/search.bml.label.city=By: + +/community/search.bml.label.country=Land: + +/community/search.bml.label.displayoptions=Visningsalternativer + +/community/search.bml.label.hasmember=Har medlem + +/community/search.bml.label.othercriteria=Andre kriterier + +/community/search.bml.label.outputformat=Visningsformat + +/community/search.bml.label.records=Oppføringer per side: + +/community/search.bml.label.searchcomm=Søk gjennom samfunn + +/community/search.bml.label.selecriteria=Fyll ut kriterier nedenfor som du ønsker å bruke for å søke etter samfunn. Resultatene du får er krysningspunktet mellom alle søkekriterier. Med andre ord så betyr hvert avkrysningsfelt "AND", ikke "OR". + +/community/search.bml.label.sortmethod=Sorteringsmetode: + +/community/search.bml.label.stateprovince=Stat/fylke: + +/community/search.bml.label.updated=Sist oppdatert i + +/community/search.bml.sel.bypicture=Etter bilde + +/community/search.bml.sel.communityname=Samfunnsnavn + +/community/search.bml.sel.commview=Samfunnsvisning + +/community/search.bml.sel.day=dag + +/community/search.bml.sel.month=måned + +/community/search.bml.sel.simple=Enkel + +/community/search.bml.sel.updatetime=Oppdater tiden + +/community/search.bml.sel.username=Brukernavn + +/community/search.bml.sel.week=uke + +/community/search.bml.title=Samfunnsøk + +/community/settings.bml.button.changecommunity=Oppdater valg + +/community/settings.bml.button.createcommunity=Opprett samfunn + +/community/settings.bml.error.badpassword=Ugyldig passord for samfunnet + +/community/settings.bml.error.hasentries=Denne kontoen har allerede oppføringer og kan ikke gjøres om. + +/community/settings.bml.error.maintainertype=Bestyrerkonto må være en person, ikke en annen delt konto. + +/community/settings.bml.error.noaccess=Kun samfunnsbestyrere kan tilpasse samfunnet. Du er ikke en bestyrer av samfunn [[comm]]. + +/community/settings.bml.error.notcomm=Ikke en samfunnskonto. + +/community/settings.bml.error.notfound=Samfunnskontoen finnes ikke. + +/community/settings.bml.error.samenames=Bestyrerkonto og samfunnskonto kan ikke være den samme. + +/community/settings.bml.label.anybodycan=Alle medlemmer
          Alle kan poste øyeblikkelig når de har meldt seg inn. + +/community/settings.bml.label.changeheader=Tilpass samfunnsvalg + +/community/settings.bml.label.changetext=Her kan du tilpasse valgene for samfunn du bestyrer eller eier. + +/community/settings.bml.label.commchanged=Dine samfunnsvalg er lagret. + +/community/settings.bml.label.commcreate=Dette er kontoen du ønsker å gjøre om til et samfunn. Det må allerede være opprettet, men bør ikke være i bruk av noen, siden mange forskjellige personer potensielt kan poste i den i fremtiden. + +/community/settings.bml.label.commcreated=Ditt samfunn er nå opprettet. + +/community/settings.bml.label.commheader=Samfunnskonto + +/community/settings.bml.label.comminfo=Samfunnsinfo + +/community/settings.bml.label.commopts=Samfunnsvalg + +/community/settings.bml.label.commsite=Samfunnsvevsted + +/community/settings.bml.label.community=Samfunn: + +/community/settings.bml.label.createheader=Opprett samfunn + +/create.bml.age.check.question=Er du under 13 år? + +/create.bml.age.check.yes=Ja, jeg er under 13 år. + +/create.bml.age.head=Alder + +/create.bml.btn.create=Opprett dagbok + +/create.bml.btn.proceed=Fortsett... + +/create.bml.clusterselect.cluster=Cluster: + +/create.bml.clusterselect.clusternum=Gruppe [[number]] + +/create.bml.clusterselect.head=Gruppe Valg + +/create.bml.clusterselect.nocluster=Ingen Gruppe + +/create.bml.clusterselect.text=Vennligst velg den gruppen du ønsker å lage denne kontoen i. Merk: Dette er kun en debugging/test funksjon. I bruk, vil brukere ikke velge dette eller vite noe om det. + +/create.bml.create.head=Opprett en Ny Dagbok + +/create.bml.create.text=Å opprette en ny Livejournal-konto er enkelt, bare følg instruksjonene nedenfor! + +/create.bml.email.head=Din epost adresse + +/create.bml.email.input.head=Epost Adresse: + +/create.bml.error.coppa.under13=Beklager, på grunn av COPPA restriksjoner, kan du ikke bruke Livejournal tjenester når du er under 13 år. Vennligst kom tilbake på din 13nde bursdag. + +/create.bml.error.email.blank=Du må skrive inn din epost adresse. + +/create.bml.error.email.lj_domain=Du kan ikke bruke et [[domain]] alias når du lager en konto. Vennligst bruk en annen epost addresse. + +/create.bml.error.email.nospaces=Du kan ikke ha mellomrom i din epost adresse. Om du bruker AOL, husk på at din Internet Epost adresse er ditt skjermnavn med alle mellomrom tatt vekk, og at den ender med @aol.com + +/create.bml.error.password.asciionly=Du kan kun bruke ASCII symboler i passord. + +/create.bml.error.password.blank=Du må velge et passord. + +/create.bml.error.password.nomatch=Passordene er ikke de samme. + +/create.bml.error.postrequired=POST påkrevd + +/create.bml.error.username.blank=Vennligst skriv inn et navn og kallenavn/alias. + +/create.bml.error.username.inuse=Brukernavnet du valgte er allerede tatt, vennligst velg et annet. + +/create.bml.error.username.iscode=Brukernavn ser ut til å være en invitasjons kode, ikke et brukernavn. + +/create.bml.error.username.mustenter=Du må velge et brukernavn. + +/create.bml.error.username.reserved=Beklager, dette brukernavnet er reservert. + +/create.bml.initial.friend.news=LiveJournal nyheter og hendelser + +/create.bml.initialfriends=Legg disse dagbøkene til din venneliste for å holde deg oppdatert rundt nyheter på nettstedet. + +/create.bml.name.head=Ditt Navn + +/create.bml.name.input.head=Navn: + +/create.bml.name.text=Hva er navnet ditt eller et kallenavn? Dette vil komme opp på toppen av dagboken din, og i bruker katalogen om du skulle velge å være oppført i den. Du trenger ikke bruke fullt navn eller ditt ordentlige navn. + +/create.bml.password.head=Passord + +/create.bml.password.input.head1=Passord: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Passord igjen: + +/create.bml.password.text=Velg et passord. + +/create.bml.proceed.btn.proceed=Fortsett... + +/create.bml.proceed.warning=Klikk Fortsett kun en gang!! + +/create.bml.success.btn.enterinfo=Skriv inn personlig informasjon + +/create.bml.success.head=Suksess! + +/create.bml.success.text1|staleness=1 +/create.bml.success.text1=Din dagbok har blitt lagd. Viktig registrasjons detaljer har blitt sent til [[email]], eposten inneholder instruksjoner. Merk:Du har syv dager til å bekrefte din dagbok konto. Om du ikke har satt den opp innen 7 dager vil brukernavnet [[username]] automatisk bli slettet og noen andre kan registrere det. + +/create.bml.success.text2=Din Dagbok vil komme på: + +/create.bml.success.text3=Vennligst ta deg tid til å fylle inn litt informasjon om deg selv. Mesteparten er valgfritt, men det gir oss en ide om hvem som bruker Livejournal. + +/create.bml.title=Lag ny Dagbok + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=For å lage en ny konto, skriv inn konto aktivasjons kode: + +/create.bml.useacctcodes.welcome=Velkommen + +/create.bml.username.box.head=Brukernavn: + +/create.bml.username.forpaidaccts=Eller, for betalte kontoer: + +/create.bml.username.head=Brukernavn: + +/create.bml.username.ljaddress=Din Dagbok vil komme på disse adressene: + +/create.bml.username.text=Hver [[sitename]] bruker må ha sitt eget unike brukernavn. Ditt brukernavn er det som vises i adressen til din dagbok, og som du også bruker til å logge inn til [[sitename]] server. Det vises også når du skriver kommentarer i andre folks dagbok. + +/create.bml.username.username=brukernavn + +/customize/index.bml.s1=Det gamle stilsystemet tilpasses gjennom Tilpass dagboken-siden. + +/customize/index.bml.title=Tilpass dagbok + +/editinfo.bml.allowshowcontact.about=Du bør ha dette alternativet aktivert. Det lar andre mennesker kontakte deg ved å vise e-postadressen din, ICQ-nummeret ditt eller AOL Instant Messenger skjermnavnet ditt. + +/editinfo.bml.allowshowcontact.email=Om synlig, e-postadresse du vil vise: + +/editinfo.bml.allowshowcontact.email.actual_only=Kun egentlig adresse + +/editinfo.bml.allowshowcontact.email.both=Begge (egentlig + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Kun LiveJournal-adressen + +/editinfo.bml.allowshowcontact.email.neither=Ingen. Skjul min e-postadresse. + +/editinfo.bml.allowshowcontact.email.no_show=Ikke vis e-postadresse + +/editinfo.bml.allowshowcontact.email.show=Vis e-postadresse + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Med valget ovenfor, kan du også velge å skjule epost adressen din (men fremdeles vise annen kontakt informasjon), kun vise din Livejournal epost adresse (kun for betalte kontoer), kun vise din ordentelige adresse, eller vise begge. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Med valget ovenfor, kan du også velge å skjule din epost adresse (men fremdeles vise annen kontakt informasjon). + +/editinfo.bml.allowshowcontact.title=Vise din kontaktinformasjon på LiveJournal? + +/editinfo.bml.allowshowinfo.about=Skru på denne om du vil vise by/fylke/land og fødselsdato til andre brukere. + +/editinfo.bml.allowshowinfo.title=Vise område & bursdag? + +/editinfo.bml.autotranslate.about<< +Bruk dette alternativet for å fortelle LiveJournal hvilken koding vi skal anta tidligere poster er skrevet i, før vi byttet til Unicode. + +Dersom du skriver på norsk eller engelsk, kan du godt velge "Western European" her. +. + +/editinfo.bml.autotranslate.header|staleness=1 +/editinfo.bml.autotranslate.header=Automatisk oversette eldre oppføringer fra: + +/editinfo.bml.bday.title=Bursdag + +/editinfo.bml.bday.year.opt=år er valgfritt + +/editinfo.bml.bdayreminders.about=Dersom du vil ha e-post som påminner deg om bursdagen til vennene dine på LiveJournal, sett hake her. + +/editinfo.bml.bdayreminders.header|staleness=1 +/editinfo.bml.bdayreminders.header=Send meg bursdagspåminnelser + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=Her kan du skrive en kort biografi om deg selv. Denne vil dukke opp på brukerinformasjonssiden din. + +/editinfo.bml.bio.header=Om deg + +/editinfo.bml.blockrobots.about|staleness=1 +/editinfo.bml.blockrobots.about=Om du setter hake her, vil søkemotorer la din journal i fred. Ikke alle søkemotorer respekterer reglene, men de mest populære gjør det. + +/editinfo.bml.blockrobots.header=Bloker roboter og søkemotorer fra å indeksere journalen din + +/editinfo.bml.city.title=By + +/editinfo.bml.country.choose=Velg et land + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Ikke + +/editinfo.bml.email.title=E-post + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=Sett kryss her om du vil at andre skal kunne kommentere journaloppføringene du poster (stilen du har satt må også støtte dette). + +/editinfo.bml.enableboards.header=Aktiver diskusjonstavler + +/editinfo.bml.encoding.about=For brukere som skriver på flere språk og må ta internasjonale hensyn. + +/editinfo.bml.encoding.header=Alternativer for koding + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Du kan ikke anngi en @[[domain]] e-postadresse. +Skriv din egentlige e-postadresse i dette feltet. +Om du har en betalt konto, vil e-post sendt [[user]]@[[domain]] videresendes til din egentlige adresse. +For å velge hvilken e-postadresse (eller begge) som vises offentlig, se alternativet nedenfor under "Vis kontaktinformasjon" +. + +/editinfo.bml.error.email.no_space<< +Ingen mellomrom er tillatt i en e-postadresse. +Dersom du bruker AOL, husk at din e-postadresse for internett er skjermnavnet ditt med alle mellomrom fjernet, fulgt av @aol.com +. + +/editinfo.bml.error.excessive_int<< +Beklager, men du har angitt for mange interesser. Høyeste antall er 150, men du har angitt [[intcount]]. +Endringer du gjorde i din interesseliste ble ikke lagret. Gå tilbake, fjern noen interesser og prøv igjen. +. + +/editinfo.bml.error.invalidbio=Din lagrede biografi inneholder ugyldige tegn. Du må besøke tegnoversettelse for å konvertere til Unicode. + +/editinfo.bml.error.invalidints=Din interesseliste inneholder ugyldige tegn. Du må besøke tegnoversettelse for å konverte til Unicode. + +/editinfo.bml.error.invalidname=Navnet ditt inneholder ugyldige tegn. Du må besøke tegnoversettelse for å konvertere til Unicode. + +/editinfo.bml.error.locale.country_ne_state=Du valgte United States som land, men du skrev en ikke-amerikansk stat i "Annen stat"-feltet. + +/editinfo.bml.error.locale.invalid_country=På et eller annet hvis klarte du å velge et ugyldig land. + +/editinfo.bml.error.locale.state_ne_country=Du spesifiserte et annet land enn amerika, men valgte en amerikansk stat. + +/editinfo.bml.error.locale.zip_ne_state=Din ZIP-kode stemmer ikke med den staten du valgte. Korriger eller ta vekk ugyldige verdier fra stat og postnummerfeltene. + +/editinfo.bml.error.locale.zip_requires_us|staleness=1 +/editinfo.bml.error.locale.zip_requires_us=Du fylte ut en ZIP-kode, men valgte ikke Amerika som ditt land. Vi tar bare i mot ZIP-koder fra amerikanske borgere. Vennligst gå tilbake og fjern ZIP-koden, eller velg Amerika som ditt land. + +/editinfo.bml.error.tm.require.number=Dersom du vil motta SMS eller Mobilpost må du anngi ditt telefonnummer. + +/editinfo.bml.error.tm.require_provider|staleness=1 +/editinfo.bml.error.tm.require_provider=Om du vil bruke SMS eller Mobilpost må du velge mobilleverandøren din. Dersom din ikke finnes på listen, kontakt oss, så kan vil legge til støtte for den. + +/editinfo.bml.finished.about=Når du er ferdig, trykk "Lagre endringer" nedenfor. + +/editinfo.bml.finished.header=Ferdig? + +/editinfo.bml.finished.save_button=Lagre endringer + +/editinfo.bml.gender.title=Kjønn + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Sett kryss her dersom du vil ha e-postvarsling når noen kommenterer dine journaloppføringer. + +/editinfo.bml.getreplies.header=Motta diskusjonstavlesvar + +/editinfo.bml.hidefriendof.about=Om du setter kryss her, skjuler du listen over hvem som lister deg som venn på din brukerinformasjonsside. + +/editinfo.bml.hidefriendof.header=Skjul "venn av"-liste + +/editinfo.bml.howhear.about<< +Bare for nysgjerrighetens skyld, hvor hørte du om [[sitename]] fra? +Var det en spesiell person fyller du ut brukernavnet deres. Om det var fra en annen kilde/artikkel/lenke/nettside vær snill å beskrive den. +. + +/editinfo.bml.howhear.header=Nysgjerrighet + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Sett kryss her dersom e-postklienten din støtter HTML-formatert e-post. Mange klienter prøver å støtte det, men feiler totalt. +Om du fjerner krysset, vil LiveJournal bare sende e-post i ren tekst. +. + +/editinfo.bml.htmlemail.header=Send HTML Eposter + +/editinfo.bml.int.about<< +Om du ønsker at andre skal kunne søke i katalogen og finne deg via interesse, skriv inn nedenfor alt du er interesert i, separer med komma. +Korte En-ords setninger er best. Tommelregel: Du skulle kunne putte inn interessen i en setning som "Jeg liker _______". Når du referer til et adjektiv, bruk flertalls form. "Jeg liker DVDer" istedetfor "Jeg liker DVD". +. + +/editinfo.bml.int.ex.bad=DÅRLIG Eksempel: Jeg liker masse forskjellige grupper og å se filmer og snakke med venner og gå på diskotek. Den slags kan gå i bio'en din ovenfor. + +/editinfo.bml.int.ex.good=GODTEksampel: sykling, skigåing, datamaskiner, dvder, mp3er, ost, kvinner + +/editinfo.bml.int.header=Interesser + +/editinfo.bml.login.enterinfo=Skriv inn brukernavn og passord for å endre din person informasjon: + +/editinfo.bml.login.forgot.header=Glemt noe? + +/editinfo.bml.login.forgot.recover=Om du har glemt ditt brukernavn eller passord, få det tilbake her!. + +/editinfo.bml.logip.always=Alltid + +/editinfo.bml.logip.anon_only=Kun anonyme postere + +/editinfo.bml.logip.header=Logg IP adresse av folk som kommenterer? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Om du er redd for at spam-roboter vil finne din epost adresse på Livejournal, tikk av dette valget og din epost adresse vil bli modifisert slik at den ikke kan bli funnet av epost-søkende roboter. + +/editinfo.bml.name.title=Navn + +/editinfo.bml.optional=Valgfri + +/friends/index.bml.title=Vennelistetilpassing + +/index.bml.boldcreate=Opprett din egen LiveJournal! + +/index.bml.frank.image.alt=Frank, LiveJournal sin maskottgeit + +/index.bml.frank.logo="Bæææ", sier Frank. + +/index.bml.meta.desc=LiveJournal.com er et sted du kan dele dine tanker med verden. + +/index.bml.meta.keywords=dagbok, journal, online journal, dagbøker, skriving, online dagbok, nettbasert dagbok, elektronisk dagbok, personlig dagbok + +/interests.bml.findsim.searchwait=Vennligst Merk: Søk vil ta flere sekunder. Vennligst vent. + +/interests.bml.findsim_do.account.notallowed=Beklager, din konto type kan ikke bruke dette verktøyet. + +/interests.bml.findsim_do.magic=Magisk Liste + +/interests.bml.findsim_do.magic.head=Magisk Liste + +/lostinfo.bml.enter_username=Skriv inn ditt brukernavn: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Om du har mistet passordet ditt, skriv inn brukernavnet ditt og valgfritt også epost adressen du ønsker passordet sent til. Merk, denne epost adressen må være en du har brukt på Livejournal før og hatt bekreftet. Om du lar epost feltet være blankt, vil det bli sent til din nåværende adresse. + +/lostinfo.bml.lostpassword.title=Misted passordet ditt? + +/lostinfo.bml.lostusername.text=Om du har misted brukernavnet ditt, skriv inn epost adressen din og vi vil sende deg brukernavnet. + +/lostinfo.bml.lostusername.title=Mistet brukernavnet ditt? + +/lostinfo.bml.title=Mistet informasjon + +/lostinfo_do.bml.error.no_usernames_for_email=Ingen brukernavn for denne epost adressen: [[adress]]. + +/lostinfo_do.bml.error1.text=Du brukte aldri denne epost adressen med denne kontoen, eller det var aldri bekreftet. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Dette er en autogenerert epost. Du trenger ikke svare på den. *** + + +. + +/lostinfo_do.bml.lostpasswordmail.part2=For å bekrefte din epost adresse, gå her: + +/modify_do.bml.colortheme.color.head2=(#rrggbb eller navn) + +/modify_do.bml.colortheme.customcolors=Valgfrie farger + +/modify_do.bml.domainalias.domainname=Domene navn: + +/modify_do.bml.domainalias.example=Eksempel: min-dagbok.com + +/modify_do.bml.moodicons.select=Velg Humør Ikoner: + +/modify_do.bml.overrides.warning=DETTE ER IKKE HVOR DU OPPDATERER DAGBOKEN DIN!! + +/support/faqbrowse.bml.backfaq=Tilbake til OBS-seksjonen. + +/support/faqbrowse.bml.backsupport=Tilbake til support-sidene. + +/support/faqbrowse.bml.lastupdated=Sist Oppdatert: + +btn.search=Søk + +dystopia.btn.login=LOGG PÅ + +dystopia.hello_anonymous=Velkommen til LiveJournal! + +dystopia.hello_loggedin=Hei, [[username]]! + +dystopia.nav.createjournal=Opprett en journal + +dystopia.nav.developer=Utviklerområdet + +dystopia.nav.download=Last ned + +dystopia.nav.editentries=Rediger oppføringer + +dystopia.nav.editfriends=Dine venner + +dystopia.nav.editpassword=Ditt passord + +dystopia.nav.editpics=Dine ikoner + +dystopia.nav.editstyle=Tilpass stil + +dystopia.nav.faq=LiveJournal OBS + +dystopia.nav.findcomm=Etter gruppe + +dystopia.nav.finddir=Katalogsøk + +dystopia.nav.findint=Etter interesse + +dystopia.nav.findrandom=Tilfeldig + +dystopia.nav.findregion=Etter område + +dystopia.nav.home=Hjem + +dystopia.nav.journalcalendar=Kalender + +dystopia.nav.journalfriends=Venner + +dystopia.nav.journalinfo=Brukerinformasjon + +dystopia.nav.journalrecent=Siste + +dystopia.nav.legalcoppa=Barnevern + +dystopia.nav.legalprivacy=Personvern + +dystopia.nav.legaltos=Tjenestebetingelser + +dystopia.nav.login=Logg på + +dystopia.nav.logout=Logg ut + +dystopia.nav.lostinfo=Mistet passordet + +dystopia.nav.memories=Minner + +dystopia.nav.modifyjournal=Tilpass din journal + +dystopia.nav.news=Nyheter + +dystopia.nav.paidaccts=Betalkontoer + +dystopia.nav.personalinfo=Personinformasjon + +dystopia.nav.support=Har du et spørsmål? + +dystopia.nav.updatejournal=Oppdater dagbok + +dystopia.navhead.findusers=Finn brukere + +dystopia.navhead.help=Hjelp og support + +dystopia.navhead.journal=Din Journal + +dystopia.navhead.legal=Lovinformasjon + +dystopia.navhead.settings=Dine Valg + +dystopia.navhead.welcome=Velkommen! + +dystopia.search.icq=ICQ-nummer + +dystopia.search.int=Interesse + +dystopia.search.region=Område + +dystopia.searchlj=Søk i LiveJournal + +Email=E-post + +Help=Hjelp + +langname.da=Dansk + +langname.de=Tysk + +langname.en=Engelsk + +langname.en_GB=Engelsk (Storbritannia) + +langname.en_LJ=Engelsk - LJ + +langname.es=Spansk + +langname.fi=Finsk + +langname.fr=Fransk + +langname.ga=Irsk + +langname.gd=Gelisk + +langname.he=Hebraisk + +langname.is=Islandsk + +langname.ja=Japansk + +langname.nb=Norsk bokmål + +langname.nl=Nederlandsk + +langname.nn=Nynorsk + +langname.pl=Polsk + +langname.pt=Portugisisk + +langname.ru=Russisk + +langname.sv=Svensk + +Password=Passord + +talk.commentpermlink=lenke til denne kommentaren + +talk.commentpost=Kommenter denne + +talk.commentsread=Les kommentarer + +talk.parentlink=Forelder + +talk.replytothis=Svar på denne + +talk.somebodywrote=[[realname]] ([[userlink]]) skrev, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) skrev i [[commlink]], + +talk.threadlink=Tråd + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_norsk + +Username=Brukernavn + diff --git a/ljcom/bin/upgrading/nl.dat b/ljcom/bin/upgrading/nl.dat new file mode 100644 index 0000000..d6aec18 --- /dev/null +++ b/ljcom/bin/upgrading/nl.dat @@ -0,0 +1,2934 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Verander status + +/accountstatus.bml.error.db=Er is een database fout opgetreden bij het verwerken van je verzoek + +/accountstatus.bml.error.invalid=Ongeldig status type + +/accountstatus.bml.journalstatus.about=Als je je dagboek wil verwijderen of het verwijderen ongedaan wilt maken (opnieuw activeren), kan je dat hier doen. Nadat je je dagboek verwijderd hebt, heb je 30 dagen om dit ongedaan te maken, mocht je van idee veranderen. Na 30 dagen zal het dagboek definitief verwijderd worden en is er geen manier meer om dit ongedaan te maken. + +/accountstatus.bml.journalstatus.head=Dagboek Activatie Toestand + +/accountstatus.bml.journalstatus.select.activated=Geactiveerd + +/accountstatus.bml.journalstatus.select.deleted=Verwijderd + +/accountstatus.bml.journalstatus.select.head=Toestand: + +/accountstatus.bml.journalstatus.select.suspended=Geschorst + +/allpics.bml.current=Huidige plaatjes + +/allpics.bml.default=Standaard + +/allpics.bml.error.noparam=Je moet een gebruikersparameter opgeven. + +/allpics.bml.keywords=Sleutelwoorden: + +/allpics.bml.nopics.text.other=Deze gebruiker heeft nog geen gebruikersplaatjes geupload. + +/allpics.bml.nopics.text2=Je hebt geen plaatjes geupload. Om er eentje te uploaden, ga naar hier. + +/allpics.bml.nopics.title=Geen plaatjes beschikbaar + +/allpics.bml.pics=Hieronder zie je de gebruikersplaatjes voor gebruiker [[user]]. + +/allpics.bml.title=Gebruikersplaatjes + +/approve.bml.comm.text<< +Je bent toegevoegd aan [[comm]]. +Klik hier om de gemeenschap aan je vriendenlijst toe te voegen. +. + +/approve.bml.commjoin.text<< +Je hebt het lidmaatschapsverzoek van [[user]] voor [[comm]] goedgekeurd. +Klik hier om naar de ledenlijst van deze gemeenschap te gaan en de opties voor deze gebruiker in te stellen. +. + +/approve.bml.error.actionperformed=Deze bewerking is al uitgevoerd. + +/approve.bml.error.approving=Er is een fout opgetreden bij het goedkeuren van dit verzoek tot lidmaatschap. + +/approve.bml.error.internerr.invalidaction=Interne fout: ongeldige bewerking. + +/approve.bml.error.unknownactiontype=Onbekende bewerking + +/changepassword.bml.btn.proceed=Ga verder + +/changepassword.bml.changepassword.header=Verander paswoord + +/changepassword.bml.changepassword.instructions|staleness=1 +/changepassword.bml.changepassword.instructions=Vul het formulier hieronder in om je paswoord te veranderen. + +/changepassword.bml.email.body<< +Je paswoord is veranderd op [[sitename]]. + +Om het terug te vinden als je het ooit vergeet, ga je naar: + + [[siteroot]]/lostinfo.bml + + +met vriendelijke groeten, +[[sitename]] Team + +[[siteroot]] +. + +/changepassword.bml.email.subject=Verandering paswoord + +/changepassword.bml.error.badcheck=Fout nieuw paswoord: [[error]] + +/changepassword.bml.error.badnewpassword|staleness=1 +/changepassword.bml.error.badnewpassword=Je paswoorden zijn niet hetzelfde. Typ ze allebei opnieuw... je hebt een typfout gemaakt in een van de twee. + +/changepassword.bml.error.badoldpassword=Je oude paswoord is niet juist. + +/changepassword.bml.error.blankpassword=Je nieuwe paswoord kan niet leeg zijn. + +/changepassword.bml.error.changetestaccount=Kan het paswoord van de testaccount niet veranderen. + +/changepassword.bml.error.characterlimit=Paswoorden zijn beperkt tot maximum 30 karakters + +/changepassword.bml.error.invaliduser=Ongeldige gebruiker [[user]]. Deze gebruiker bestaat niet. Ben je zeker dat je de naam correct hebt getypt? + +/changepassword.bml.error.mustenterusername=Je moet je gebruikersnaam intypen. + +/changepassword.bml.error.nonascii=Paswoorden zijn beperkt tot ASCII karakters en symbolen. Kies aub een paswoord dat enkel ASCII karakters gebruikt. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Je kan je paswoord niet veranderen als je huidig e-mailadres niet gevalideert is. + +/changepassword.bml.newpassword=Nieuw paswoord: + +/changepassword.bml.newpasswordagain=Nieuw paswoord (nogmaals): + +/changepassword.bml.oldpassword=Oud paswoord: + +/changepassword.bml.proceed.instructions=Klik op onderstaande knop en je paswoord zal veranderd worden. Je krijgt ook een e-mail die de verandering meld. + +/changepassword.bml.success.text=Je paswoord is veranderd en er is een e-mail naar jouw gestuurd ter herinnering. + +/changepassword.bml.title=Verander paswoord + +/community/index.bml.title=Groepen centrum + +/community/join.bml.button.join=Word lid van deze groep + +/community/join.bml.label.addtofriends=Voeg "[[maintainer]]" toe aan vriendenlijst.
          + +/community/join.bml.label.allowposting=Deze groep is zo ingesteld dat alle leden berichten kunnen plaatsen, dus vanaf nu kun je berichten plaatsen in deze groep. Wanneer je reeds een LiveJournal client geopened hebt op je computer en je reeds bent ingelogd, moet je eerst uitloggen en herinloggen voor deze groep voorkomt in de lijst van dagboeken waarin je berichten kunt plaatsen. + +/community/join.bml.label.auth=Hoewel je nu lid bent van deze groep kun je zelf nog geen berichten plaatsen aangezien alleen daartoe gemachtigde gebruikers dit kunnen. Contacteer een van de moderatoren wanneer je ook berichten wil kunnen plaatsen. Hier is de lijst van moderatoren van deze groep: [[admins]] + +/community/join.bml.label.banned=The moderator(en) van deze groep heeft je toegang tot de groep verboden. + +/community/join.bml.label.closed=Dit is een gesloten groep. Wanneer je geinteresseerd bent om lid te worden, neem dan contact op met een van de moderatoren. Hier is de lijst van moderatoren: [[admins]] + +/community/join.bml.label.commlogged=Je bent nu ingelogd op een groepsaccount, niet op je persoonlijke account. + +/community/join.bml.label.errorcomminfo=Bepaalde informatie over de groep is niet geldig. + +/community/join.bml.label.expls=Klik op onderstaande knop om lid te worden van de "[[maintainer]]" groep. Vink het vinkje hierbeneden AF wanneer je lid wilt worden van deze groep, maar de berichten niet op je vriendenpagina wilt laten verschijnen. + +/community/join.bml.label.loginfirst=Om lid te kunnen worden van een groep moet je eerst inloggen. + +/community/join.bml.label.membernow=Je bent nu lid van de [[commname]] groep + +/community/join.bml.label.sure=Weet je het zeker? + +/community/join.bml.success=Gelukt + +/community/join.bml.title=Lid worden + +/community/leave.bml.button.leave=De groep verlaten + +/community/leave.bml.label.buttontoleave=Klik op onderstaande knop om de "[[commname]]" groep te verlaten. + +/community/leave.bml.label.infoerror=Bepaalde informatie over de groep is niet geldig. + +/community/leave.bml.label.logoutfirst=Om een groep te kunnen verlaten moet je eerst inloggen. + +/community/leave.bml.label.removed=Je bent nu verwijderd van de ledenlijst van de [[commname]] groep + +/community/leave.bml.label.removefromfriends=Verwijder "[[user]]" ook van vriendenlijst. + +/community/leave.bml.success=Gelukt + +/community/leave.bml.sure=Weet je het zeker? + +/community/leave.bml.title=Verlaat de groep + +/community/manage.bml.commlist.actinfo=Groepsinfo + +/community/manage.bml.commlist.actions=Acties + +/community/manage.bml.commlist.actmembers=[Leden] + +/community/manage.bml.commlist.actmembers2=Leden + +/community/manage.bml.commlist.actsettings=[Instellingen] + +/community/manage.bml.commlist.actsettings2=Instellingen + +/community/manage.bml.commlist.header=Jouw groepen + +/community/manage.bml.commlist.none=Je beheert geen groepen. + +/community/manage.bml.commlist.text=Hier zijn de groepen die je beheert of mee beheert: + +/community/manage.bml.commlist.title=Titel + +/community/manage.bml.commlist.username=Gebruikersnaam + +/community/manage.bml.create.header=Maak een groep + +/community/manage.bml.create.text=Je kan ook een nieuwe groep maken. + +/community/manage.bml.title=Groepsbeheer + +/community/members.bml.error.alreadyadded=[[user]] werd niet toegevoegd omdat hij/zij al toegang heeft tot deze groep. + +/community/members.bml.error.alreadysent=[[user]] werd niet toegevoegd omdat hem/haar al een bevestigingsmail gestuurd werd op: [[datetime]]. Wacht aub tot hij/zij antwoord. + +/community/members.bml.error.noaccess=Enkel moderatoren van de groep kunnen ledenlijsten veranderen. Je bent geen moderator van groep [[comm]]. + +/community/members.bml.error.nocomm=Groep niet gevonden + +/community/members.bml.error.nouser=Gebruiker bestaat niet: [[user]] + +/community/members.bml.key.admin=Beheerder + +/community/members.bml.key.member=Lid + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Berichten plaatsen + +/community/members.bml.manage2=Beheer groepen + +/community/members.bml.name=Groepsnaam: [[name]] + +/community/members.bml.nextlink=(Volgende pagina...) + +/community/members.bml.prevlink=(Vorige pagina...) + +/community/members.bml.settings=[Instellingen] + +/community/members.bml.success.header=Succes + +/community/members.bml.success.message=Je veranderingen werden opgeslagen. + +/community/members.bml.success.return=Keer terug naar de lijst + +/community/members.bml.title=Groepsleden + +/community/members.bml.update=Pas instellingen aan + +/community/moderate.bml.approve.button=Ja ik keur dit goed + +/community/moderate.bml.approve.header=Dit bericht goedkeuren? + +/community/moderate.bml.approve.text=Ben je zeker dat je dit bericht wil goedkeuren? + +/community/moderate.bml.brlist.actions=Acties + +/community/moderate.bml.brlist.poster=Auteur + +/community/moderate.bml.brlist.subject=Begin van het onderwerp + +/community/moderate.bml.brlist.time=Tijd + +/community/moderate.bml.brlist.view=Bekijk + +/community/moderate.bml.choice.approve=Goedkeuren + +/community/moderate.bml.choice.reject=Afkeuren + +/community/moderate.bml.error.notfound=Groepsaccount niet gevonden. + +/community/moderate.bml.manage=Beheer groepen + +/community/moderate.bml.modlist.actions=Acties + +/community/moderate.bml.modlist.title=Titel + +/community/moderate.bml.modlist.username=Gebruikersnaam + +/community/moderate.bml.posted.header=Succes + +/community/moderate.bml.posted.proterror=Het bericht werd niet toegevoegd wegens protocol fout: [[err]] + +/community/moderate.bml.posted.text=Het bericht werd toegevoegd. + +/community/moderate.bml.reject.button=Ja, keur het af + +/community/moderate.bml.reject.header=Dit bericht afkeuren? + +/community/moderate.bml.reject.reason|staleness=1 +/community/moderate.bml.reject.reason=Je kan ook aan de auteur je redenen voor het afkeuren van zijn/haar bericht uitleggen. Dit zal naar de auteur gestuurd worden in een e-mail. + +/community/moderate.bml.reject.text=Ben je zeker dat je dit bericht wil afkeuren? + +/community/moderate.bml.rejected.header=Afgekeurd + +/community/moderate.bml.rejected.text=Het bericht is afgekeurd. + +/community/search.bml.button.clear=Velden leegmaken + +/community/search.bml.button.search=Zoek! + +/community/search.bml.checkbox.onlywithpics=Alleen groepen met plaatjes + +/community/search.bml.label.byinterest=Op interesse + +/community/search.bml.label.bylocation=Op plaats + +/community/search.bml.label.bytime=Op dagboek aangepassings-tijd + +/community/search.bml.label.city=Plaats: + +/community/search.bml.label.country=Land: + +/community/search.bml.label.displayoptions=Weergave opties + +/community/search.bml.label.hasmember=Heeft als lid + +/community/search.bml.label.othercriteria=Andere criteria + +/community/search.bml.label.outputformat=Output formaat: + +/community/search.bml.label.records=Aantal records per pagina: + +/community/search.bml.label.searchcomm=Zoek in groepen + +/community/search.bml.label.selecriteria=Specificeer de zoekcriteria dat je wilt gebruiken om groepen te vinden. In de resultaten worden alle zoekcriteria verwerkt. Met andere woorden, elke vakje dat je aanvinkt betekend "EN", niet "OF". + +/community/search.bml.label.sortmethod=Sorteermethode: + +/community/search.bml.label.stateprovince=Staat/Provincie: + +/community/search.bml.label.updated=Geupdate in de laatste + +/community/search.bml.sel.bypicture=Op plaatje + +/community/search.bml.sel.communityname=Groepsnaam + +/community/search.bml.sel.commview=Groepsaanzicht + +/community/search.bml.sel.day=dag + +/community/search.bml.sel.month=maand + +/community/search.bml.sel.simple=Eenvoudig + +/community/search.bml.sel.updatetime=Tijd + +/community/search.bml.sel.username=Gebruikersnaam + +/community/search.bml.title=Zoek in groepen + +/community/settings.bml.button.changecommunity=Pas instellingen aan + +/community/settings.bml.button.createcommunity=Maak groep + +/community/settings.bml.error.badpassword=Ongeldig groepspaswoord + +/community/settings.bml.error.hasentries=Deze account heeft al berichten en kan niet verwijderd worden. + +/community/settings.bml.error.maintainertype=Beheerder account moet een persoon zijn, geen andere gedeelde account. + +/community/settings.bml.error.noaccess=Enkel moderatoren van de groep kunnen groepsinstellingen veranderen. Je bent geen moderator van groep [[comm]]. + +/community/settings.bml.error.notcomm=Geen groepsaccount. + +/community/settings.bml.error.notfound=Groepsaccount niet gevonden. + +/community/settings.bml.error.samenames=Beheerder account en groepsaccount kunnen niet dezelfde zijn. + +/community/settings.bml.label.anybodycan=Alle leden
          Iedereen kan onmiddelijk berichten plaatsen, eens ze lid zijn. + +/community/settings.bml.label.changeheader=Verander groepsinstellingen + +/community/settings.bml.label.changetext=Hier kan je de instellingen veranderen voor de groep waarvan je eigenaar of moderator bent. + +/community/settings.bml.label.commchanged=Je groepsinstellingen zijn veranderd. + +/community/settings.bml.label.commcreate=Dit is het account dat je in een groep wil veranderen. Het moet reeds aangemaakt zijn, maar het zou nog niet in gebruik mogen zijn door iemand omdat hierna misschien vele verschillende mensen er berichten in zullen kunnen plaatsen. + +/community/settings.bml.label.commcreated=Je groep is nu aangemaakt. + +/community/settings.bml.label.commheader=Groepsaccount + +/community/settings.bml.label.comminfo=Groepsinfo + +/community/settings.bml.label.commopts=Groepsopties + +/community/settings.bml.label.commsite=Groepswebsite + +/community/settings.bml.label.community=Groep: + +/community/settings.bml.label.createheader=Maak groep aan + +/community/settings.bml.label.createtext=Hier kan je een groepsaccount aanmaken. Een groep is een speciaal type account waar andere gebruikers lid van kunnen worden, en er berichten in plaatsen. Voor een voorbeeld van een groep, kijk naar nederland. + +/community/settings.bml.label.howoperates=Kies hoe je groep werkt. Je kan deze later veranderen. + +/community/settings.bml.label.maintainer=Beheerder: + +/community/settings.bml.label.membership=Lidmaatschap + +/community/settings.bml.label.nmcan=Niet-Leden kunnen berichten plaatsen
          Gebruikers kunnen berichten plaatsen in deze groep zonder er lid van te moeten worden. + +/community/settings.bml.label.nmcant=Niet-Leden kunnen geen berichten plaatsen
          Gebruikers moeten lid worden van deze groep om berichten te kunnen plaatsen. + +/community/settings.bml.label.nmheader|staleness=1 +/community/settings.bml.label.nmheader=Bericht van een niet-lid + +/community/settings.bml.label.nmtext=Kunnen gebruikers berichten plaatsen in deze groep zonder lid te worden? + +/community/settings.bml.label.openmemb=Open groep
          Iedereen kan lid worden zonder toestemming nodig te hebben. + +/community/settings.bml.label.password=Paswoord: + +/community/settings.bml.label.postaccess=Berichten plaatsen + +/community/settings.bml.label.rellinks=Relevante links: + +/community/settings.bml.label.selcan=Geselecteerde leden
          Enkel bepaalde leden kunnen berichten plaatsen, eens ze toegang gekregen hebben van de moderator. + +/community/settings.bml.label.username=Gebruikersnaam: + +/community/settings.bml.label.whocanjoin=Wie kan lid worden van je groep? + +/community/settings.bml.label.whocanpost=Wie kan berichten plaatsen in deze groep? + +/community/settings.bml.manage2=Beheer groepen + +/community/settings.bml.members=[Leden] + +/community/settings.bml.name=Groepnaam: [[name]] + +/community/settings.bml.success=Succes + +/community/settings.bml.title.create=Maak groep aan + +/community/settings.bml.title.modify=Groepsinstellingen + +/create.bml.age.check.question=Ben je jonger dan 13 jaar? + +/create.bml.age.check.yes=Ja, ik ben jonger dan 13 jaar. + +/create.bml.age.check2.question=Ben je ouder dan 13 jaar? + +/create.bml.age.check2.yes=Ja ik ben ouder dan 13 jaar. + +/create.bml.age.head=Leeftijd + +/create.bml.btn.create=Dagboek maken + +/create.bml.btn.proceed=Ga verder... + +/create.bml.captcha.answer=Antwoord: + +/create.bml.captcha.audiodesc=Typ de cijfers die je hoort in om te bewijzen dat je geen spam robot bent. + +/create.bml.captcha.desc=Typ de letters en cijfers die je hieronder ziet in, om te bewijzen dat je geen spam robot bent. Als je de tekst niet kan lezen, typ dan "AUDIO" om geluidstest te doen. + +/create.bml.clusterselect.head=Cluster selectie + +/create.bml.clusterselect.nocluster=Geen cluster + +/create.bml.clusterselect.text=Selecteer het cluster waarin je dit account wilt aanmaken. Let op: deze optie is er alleen voor debugging/testing. Normaliter zullen gebruikers het cluster niet kunnen kiezen, of hier zelfs maar vanaf weten. + +/create.bml.create.head=Open een nieuw dagboek + +/create.bml.create.text=Het openen van een nieuwe LiveJournal is erg gemakkelijk. Volg gewoon de instructies hieronder! + +/create.bml.email.head=Je e-mailadres + +/create.bml.email.input.head=E-mailadres: + +/create.bml.error.coppa.under13=Helaas, maar vanwege de COPPA wet kun je geen gebruik maken van LiveJournal wanneer je jonger bent dan 13 jaar. Vanaf het moment dat je 13 jaar bent, kun je je eigen LiveJournal openen. + +/create.bml.error.email.blank=Je moet hier je e-mailadres invullen. + +/create.bml.error.email.lj_domain=U kan geen [[domain]] alias gebruiken bij het aanmaken van een account. Vul aub een ander e-mail adres in. + +/create.bml.error.email.nospaces=Spaties zijn ongeldig in een e-mailadres. Wanneer je gebruik maakt van AOL, denk er dan aan dat je Internet E-mailadres bestaat uit je 'screen name' maar dan zonder alle spaties hierin, gevolgt door @aol.com + +/create.bml.error.password.asciionly=Je kunt alleen ASCII symbolen gebruiken in het password. + +/create.bml.error.password.blank=U moet een passwoord invullen. + +/create.bml.error.password.nomatch=Passwoorden zijn niet gelijk. + +/create.bml.error.postrequired=POST vereist. + +/create.bml.error.username.blank=Vul a.u.b. een naam of alias/handle in. + +/create.bml.error.username.inuse=Deze gebruikersnaam is reeds in gebruik; kies een andere. + +/create.bml.error.username.iscode=Het lijkt erop dat de gebruikersnaam een uitnodigingscode is, niet een gebruikersnaam. + +/create.bml.error.username.mustenter=Vul een gebruikersnaam in. + +/create.bml.error.username.reserved=Helaas, deze gebruikersnaam is gereserveerd. + +/create.bml.initial.friend.lj_maintenance=Berichten over geplande & niet geplande werken en onderhoud. + +/create.bml.initial.friend.news=Livejournal nieuws en evenementen + +/create.bml.initialfriends=Voeg deze dagboeken toe aan je vriendenlijst om op de hoogte te blijven van nieuws en informatie over de site. + +/create.bml.initialfriends.heading=Vrienden om mee te beginnen + +/create.bml.name.head=Jouw naam: + +/create.bml.name.input.head=Naam: + +/create.bml.name.text=Wat is je naam of handle? Dit zal bovenaan je dagboek verschijnen, en in het ledenbestand als je zou kiezen om daairn opgenomen te worden. Je bent niet verplicht je volledige naam or zelfs maar je echte naam op te geven. + +/create.bml.password.head=Wachtwoord + +/create.bml.password.input.head1=Wachtwoord: + +/create.bml.password.input.head2|staleness=1 +/create.bml.password.input.head2=Type nogmaals je wachtwoord: + +/create.bml.password.text=Selecteer wachtwoord + +/create.bml.proceed.btn.proceed=Ga verder... + +/create.bml.proceed.warning=Klik slechts één keer op Ga verder!! + +/create.bml.success.btn.enterinfo=Vul persoonlijke informatie in. + +/create.bml.success.head=Gelukt! + +/create.bml.success.text1=Je account is aangemaakt. Belangrijke informatie over je registratie is verstuurd naar [[email]] met verdere instructies. Valideer zeker je account door op de link in de email te klikken. + +/create.bml.success.text2=Je LiveJournal is te vinden op: + +/create.bml.success.text3=Als je wilt kun je hier wat informatie over je zelf invullen. Dit is niet verplicht, maar het geeft ons een beeld van wie LiveJournal gebruiken. + +/create.bml.title=Maak een nieuw dagboek + +/create.bml.tos.error=Je moet de algemene voorwaarden lezen en hiermee akkooord gaan voordat je een account creeert + +/create.bml.tos.haveread=Ik heb de algemene voorwaarden gelezen en ga ermee akkoord. + +/create.bml.tos.heading=Algemene Voorwaarden + +/create.bml.useacctcodes.entercode|staleness=1 +/create.bml.useacctcodes.entercode=Vul hier een account aanmaak code in om een nieuw account aan te maken. + +/create.bml.useacctcodes.welcome=Welkom + +/create.bml.username.box.head=Gebruikersnaam: + +/create.bml.username.charsallowed=Je gebruikersnaam mag enkel kleine letters (a-z), cijfers (0-9) en een underscore (_) bevatten.
          Bovendien mag hij maximum 15 karakters lang zijn. + +/create.bml.username.forpaidaccts=Of, voor betaalde accounts: + +/create.bml.username.head=Gebruikersnaam + +/create.bml.username.ljaddress=Je dagboek is beschikbaar op de volgende URLs + +/create.bml.username.text=Elke [[sitename]] gebruiker heeft zijn/haar eigen specifieke gebruikersnaam. Je gebruikersnaam maakt deel uit van het adres (URL) van je dagboek en je gebruikt hem om in te loggen op de [[sitename]] server. Ook wordt hij gebruikt wanneer je reacties achterlaat in andermans dagboek. + +/create.bml.username.username=gebruikersnaam + +/customize/index.bml.choose=Wil je het oude stijl-systeem gebruiken of het nieuwe? + +/customize/index.bml.choose.header=Kies stijl-systeem + +/customize/index.bml.choose.s1=Oud systeem (S1) + +/customize/index.bml.choose.s2=Nieuw systeem (S2) + +/customize/index.bml.s1=Je kan het oude stijlsysteem bewerken via de Pas dagboek aan pagina. + +/customize/index.bml.s1.header=Je gebruikt S1 + +/doc/index.bml.about=Welkom op de opslagplaats van de documentatie van LiveJournal, waar je informatie kan vinden over de meeste onderwerpen met betrekking tot de LiveJournal service of server software. Kies aub een onderwerp: + +/doc/index.bml.about.header=Welkom + +/doc/index.bml.docs.faq.about=Veelgestelde vragen (FAQ) over LiveJournal.com + +/doc/index.bml.docs.header=Documenten + +/doc/index.bml.docs.howto.about=Tips en truukjes om je te helpen je LiveJournal dagboek aan te passen + +/doc/index.bml.docs.server.about=Alles wat je moet weten om een LiveJournal service te installeren, beheren en hacken. + +/doc/index.bml.docs.server.title=LiveJournal server handboek + +/doc/index.bml.docs.tour.about=Bedoeld om nieuwe bezoekers vertrouwd te maken met de site + +/doc/index.bml.docs.tour.title=Rondleiding + +/doc/index.bml.title=Documentatie + +/doc/index.bml.volunteering.about=Als je wil helpen met de documentatie van LiveJournal, kijk dan eens op de volgende discussiegroepen (waarschijnlijk in het Engels): + +/doc/index.bml.volunteering.header=Vrijwilligerswerk + +/doc/index.bml.volunteering.ljsysdoc=Discussies over het LiveJournal documentatie systeem + +/doc/index.bml.volunteering.ljuserdoc=Eindgebruiker documentatie discussies + +/doc/tour/index.bml.clients.caption<< +LiveJournal clients zijn kleine programmatjes die op je computer draaien, en je toelaten je dagboek aan te passen als je online bent, zonder een browser te openen. +Clients zijn er voor bijna elk platform, en vele er van zijn makkelijk aan te passen aan je wensen. +. + +/doc/tour/index.bml.comms.caption=LiveJournal is een grote interactieve gemeenschap, dus het zal je niet verbazen dat er vele gebruikers zijn met gelijkaardige interesses. Daarom bieden we de mogelijkheid om groepen aan te maken, en dagboeken waarin vele mensen berichten kunnen plaatsen. + +/doc/tour/index.bml.comms.title=Groepen + +/doc/tour/index.bml.create.caption=LiveJournal is een dagboekgemeenschap gebaseert op lidmaatschap. Deze pagina legt uit waarom lid worden belangrijk is, en de voordelen van lidmaatschap. Hij bevat ook een formulier om je eigen account te maken. + +/doc/tour/index.bml.create.title=Een account aanmaken + +/doc/tour/index.bml.friends.caption=Je kan ook op de hoogte blijven van wat je vrienden doen via LiveJournal, door de vrienden functie te gebruiken. Als je een dagboek interessant vindt, voeg het dan toe aan je vriendenlijst, die je toelaat alle berichten van je vrienden vanop één pagina te lezen. + +/doc/tour/index.bml.friends.title=Vrienden + +/doc/tour/index.bml.intro.caption=Deze rondleiding is bedoelt om nieuwe bezoekers vertrouwd te maken met de site. Ze toont je waar de belangrijkste delen zijn, en ook een paar van de meest interessante mogelijkheden. + +/doc/tour/index.bml.intro.title=Welkom + +/doc/tour/index.bml.modify.caption=Het is ook mogelijk om je dagboek op vershillende manieren op te maken, door vooraf gedefiniëerde stijlen en kleurenschema's te gebruiken. Maak je dagboek zo uniek als je wil! + +/doc/tour/index.bml.modify.title=Personalisatie + +/doc/tour/index.bml.nav.next=Volgende --> + +/doc/tour/index.bml.nav.prev=<-- Vorige + +/doc/tour/index.bml.profile.caption=LiveJournal leden worden aangemoedigd om informatie over henzelf toe te voegen aan hun profiel, zodat we er een idee van kunnen krijgen wie de site gebruikt en hoe we hen het best kunnen dienen. Niets van deze informatie is echter verplicht — de enige informatie die nodig is om een LiveJournal te beginnen is een gebruikersnaam, een e-mail adres en een paswoord. + +/doc/tour/index.bml.profile.title=Profielen + +/doc/tour/index.bml.sitemap.caption=Hopelijk heeft deze rondleiding je een beetje nuttige informatie kunnen bieden over de LiveJournal site en service. Als je hulp nodig hebt met iets dat met LiveJournal te maken heeft, contacteer gerust ons ondersteuningsteam. Als je verder wil rondkijken, ga dan naar de kaart van de site om een overzicht te krijgen van alle pagina's op de site. + +/doc/tour/index.bml.sitemap.title=Kaart van de Site + +/doc/tour/index.bml.support.caption=De hulp & ondersteuningspagina geeft je een lijst van pagina's waar je uitleg vind over wat LiveJournal is, veelgestelde vragen (FAQs) over de site, en andere nuttige informatie over de service, het bedrijf en de gemeenschap in z'n geheel. + +/doc/tour/index.bml.support.title=Hulp zoeken + +/doc/tour/index.bml.title=Rondleiding - [[title]] + +/doc/tour/index.bml.update.caption=Berichten plaatsen is de basis van LiveJournal; hier hebben leden een kans om hun leven te delen met anderen en te hun ideëen te vertellen. Een bericht plaatsen is eenvoudig. Schrijf je bericht in het vak en klik op de "Plaats bericht" knop. Uiteraard bieden we nog meer mogelijkheden op onze "Nieuw bericht" pagina, zoals de mogelijkheid om een spellingcontrole te doen (op dit moment enkel voor Engels), en de mogelijkheid bijkomende informatie bij je berichten te zetten, zoals je huidige stemming en muziek. + +/doc/tour/index.bml.update.title=Nieuwe berichten plaatsen + +/editinfo.bml.allowshowcontact.about=Het is gewenst deze optie ingeschakeld te laten. Op deze manier kunnen andere mensen contact met je opnemen via je e-mailadres, ICQ nummer en/of AOL Instant Messenger nickname, aangezien deze alleen zichtbaar zijn op je LiveJournal. + +/editinfo.bml.allowshowcontact.email=Wanneer ingeschakeld, e-mailadres dat wordt gepubliceerd: + +/editinfo.bml.allowshowcontact.email.actual_only=Alleen actuele e-mailadres + +/editinfo.bml.allowshowcontact.email.both=Beiden (actuele + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Alleen het LiveJournal e-mailadres + +/editinfo.bml.allowshowcontact.email.neither=Geen van beiden. Publiceer geen e-mailadres. + +/editinfo.bml.allowshowcontact.email.no_show=Publiceer geen e-mailadres. + +/editinfo.bml.allowshowcontact.email.show=Publiceer e-mailadres + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Met bovenstaande optie kan je kiezen om je e-mail adres te verbergen (maar wel de andere contact informatie te tonen), enkel je LiveJournal e-mailadres te te tonen (enkel voor betaalde accounts), enkel je echte adres te tonen, of beide. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Met bovenstaande optie kan je kiezen om je e-mail adres te verbergen (maar wel de andere contact informatie te tonen). + +/editinfo.bml.allowshowcontact.title=Wil je je contact informatie op je LiveJournal publiceren? + +/editinfo.bml.allowshowinfo.about=Vink deze optie aan wanneer je je locatie en geboortedatum zichtbaar wilt maken aan andere gebruikers. + +/editinfo.bml.allowshowinfo.title=Publiceer plaats & geboortedatum? + +/editinfo.bml.autotranslate.about=Gebruik deze optie om in te stellen welke encoding LiveJournal moet gebruiken bij je berichten en reacties die geplaatst zijn voor de site is omgezet naar Unicode. Wanneer je in het Engels schrijft, kies hier dan "West-Europees" (Western European). + +/editinfo.bml.autotranslate.header=Converteer oudere berichten automatisch van: + +/editinfo.bml.bday.title=Geboortedatum + +/editinfo.bml.bday.year.opt=jaar is optioneel + +/editinfo.bml.bdayreminders.about=Vink dit vakje aan wanneer je per e-mail herinneringen wilt ontvangen in verband met de verjaardagen van je vrienden op LiveJournal + +/editinfo.bml.bdayreminders.header=Stuur me verjaardagsherinneringen (op dit moment buiten werking) + +/editinfo.bml.bio.about=Hier kun je een kleine biografie over jezelf schrijven. Die zal gepubliceerd worden op je gebruikersinfo pagina. + +/editinfo.bml.bio.header=Over mezelf + +/editinfo.bml.blockrobots.about<< +Wanneer je deze optie aanvinkt, worden zoekmachinesrobot's verteld weg te gaan. +Niet alle zoekmachines respecteren de regels. +. + +/editinfo.bml.blockrobots.header=Blokkeer zoekmachinerobot's die je journaal willen indexeren. + +/editinfo.bml.chat.msnusername.title=MSN gebruikersnaam + +/editinfo.bml.city.title=Plaats + +/editinfo.bml.country.choose=Kies een land + +/editinfo.bml.country.title=Land + +/editinfo.bml.donotlog=Nee + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=Vink deze optie aan wanneer je het andere mensen mogelijk wilt maken reacties achter te laten op berichten die je in je dagboek plaatst (de stijl die je kiest moet dit wel ook ondersteunen) + +/editinfo.bml.enableboards.header=Sta reacties toe + +/editinfo.bml.encoding.about=Maak je niet druk om deze zaken. Over het algemeen zullen alleen internationale gebruikers die in meerdere verschillende talen schrijven hier iets hoeven te veranderen. + +/editinfo.bml.encoding.header=Encoding opties + +/editinfo.bml.error.day.notinmonth=Ongeldige dag voor die maand. + +/editinfo.bml.error.day.outofrange=Ongeldige verjaardags-dag. Voer een dag in tussen 1-31. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Het is niet mogelijk hier een @[[domain]] e-mailadres in te vullen. +Vul je actuele e-mailadres in in dit veld. +Wanneer je een betaalde gebruiker bent, wordt alle e-mail dat naar [[user]]@[[domain]] is gestuurd automatisch doorgestuurd naar je actuele e-mailadres. +Om te kiezen welk e-mailadres (of beiden) zichtbaar is voor andere gebruikers, kun je kiezen bij "Pbliceer persoonlijke informatie". +. + +/editinfo.bml.error.email.none=Je moet je email adres opgeven + +/editinfo.bml.error.email.no_space<< +Spaties zijn niet toegestaan in een e-mailadres. +Wanneer je gebruik maakt van AOL, denk eraan dat je e-mailadres hetzelfde is als je screenname zonder spaties gevolgd door @aol.com +. + +/editinfo.bml.error.excessive_int=Helaas, je hebt te veel interesses ingevuld. Je kunt maximaal 150 interesses invullen, maar jij hebt er [[intcount]] ingevuld. Alle veranderingen die je gemaakt hebt werden niet opgeslagen. Ga terug en verwijder de teveel ingevulde interesses, en sla dan opnieuw op. + +/editinfo.bml.error.invalidbio=Je opgeslagen biografie bevat niet-toegestane karakters. Ga naar de conversion page om het om te zetten in Unicode. + +/editinfo.bml.error.invalidints=Je nu opgeslagen interesselijst bevat niet-toegestane karakters. Ga naar de conversion page om het om te zetten in Unicode. + +/editinfo.bml.error.invalidname=Je naam bevat niet-toegestane karakters. Ga naar de conversion page om het om te zetten in Unicode. + +/editinfo.bml.error.locale.country_ne_state=Je hebt de Verenigde Staten ingevuld als land, maar je hebt een niet-amerikaanse staat ingevuld in het andere veld. + +/editinfo.bml.error.locale.invalid_country=Je hebt per ongeluk een ongeldig land gekozen. + +/editinfo.bml.error.locale.state_ne_country=Je hebt niet de Verenigde Staten als land ingevuld, maar je hebt in het veld Staat wel een Amerikaanse staat ingevuld. + +/editinfo.bml.error.locale.zip_ne_state=Je postcode past niet bij de staat die je ingevuld hebt. Verander de informatie, of maak een of beide velden (staat en postcode) leeg. + +/editinfo.bml.error.locale.zip_requires_us<< +Je hebt een postcode ingevoerd, maar niet de VS als land geselecteerd. +We verzamelen alleen postcode informatie van gebruikers in de VS. +Ga a.u.b. terug en verwijder de postcode of stel de VS in als je land. +. + +/editinfo.bml.error.month.outofrange=Ongeldige verjaardagsmaand. Voer een maand in van 1 tot 12 (Jan-Dec). + +/editinfo.bml.error.noname=Je naam is een verplicht veld. Vul minstens je voornaam, een bijnaam of alias/handle in. + +/editinfo.bml.error.tm.require.number=Wanneer je gebruik wilt maken van de sms service, moet je je mobiele telefoonnummer invullen. + +/editinfo.bml.error.tm.require_provider<< +Wanneer je gebruik wilt maken van de sms service moet je de netwerk provider van je mobiele telefoon invullen. +Wanneer deze niet in de lijst staat, neem dan contact met ons op met informatie over hoe de sms service bij jouw provider werkt, zodat we deze kunnen gaan ondersteunen. +. + +/editinfo.bml.error.year.notenoughdigits=Ongeldig geboortejaar. Voor een jaartal in (4 cijfers). + +/editinfo.bml.error.year.outofrange=Ongeldig geboortejaar. + +/editinfo.bml.finished.about=Als je klaar bent, klik dan op de "Veranderingen opslaan" knop hieronder: + +/editinfo.bml.finished.header=Klaar? + +/editinfo.bml.finished.save_button=Veranderingen opslaan + +/editinfo.bml.gender.title=geslacht + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Vink deze optie aan wanneer je per e-mail bericht wilt ontvangen wanneer mensen reacties achterlaten op jouw berichten. + +/editinfo.bml.getreplies.header=Ontvang bericht van geplaatste reacties + +/editinfo.bml.hidefriendof.about=Wanneer je deze optie aanvinkt, zal de lijst van gebruikers die jou op hun vriendlijst hebben staan niet op je gebruikersprofiel pagina getoond worden. + +/editinfo.bml.hidefriendof.header=Verberg "vriend van" lijst + +/editinfo.bml.howhear.about=Puur uit nieuwsgierigheid, hoe heb je voor het eerst van [[sitename]] gehoord? Als het een bepaalde persoon was die je over [[sitename]] vertelde, vul zijn/haar gebruikersnaam in; wanneer je er ergens anders over gelezen hebt, vul dan in waar dit was (krantenartikel/link/andere website). + +/editinfo.bml.howhear.header=Nieuwsgierigheid + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Vink deze optie aan wanneer je weet dat je e-mail programma html in e-mail ondersteunt. +Vele programma's proberen dit, maar maken er een zootje van. +Wanneer je deze optie niet instelt zal LiveJournal je zuiver tekst e-mail sturen. +. + +/editinfo.bml.htmlemail.header=Verstuur HTML e-mail. + +/editinfo.bml.int.about=Wanneer je het andere gebruikers mogelijk wilt maken jou te vinden via zoeken op interessegebied, vul hieronder dan alles in waarin je geinteresseerd bent, gescheiden door komma's. Korte enkelvoudige woorden zijn het beste. Stelregel: Je zou de woorden moeten kunnen invullen in een zien als "Ik hou van ______". Wanneer het woord meervoudig is, gebruik dan de meervoudsvorm. "Ik hou van films" in plaats van "ik hou van film". Vul dan dus films in in de lijst van interesses. + +/editinfo.bml.int.ex.bad=FOUT Voorbeeld: Ik luister naar alle soorten muziek en hou van films kijken, met vrienden kletsen en uitgaan. Dit soort dingen kun je kwijt in je biografie hierboven. + +/editinfo.bml.int.ex.good=GOED Voorbeeld: fietsen, skieën, computers, dvds, uitgaan, lezen + +/editinfo.bml.int.header=Interesses + +/editinfo.bml.login.enterinfo=Vul je gebruikersnaam en wachtwoord in om je persoonlijke informatie te wijzigen. + +/editinfo.bml.login.forgot.header=Iets vergeten? + +/editinfo.bml.login.forgot.recover=Wanneer je je gebruikersnaam of password vergeten ben, kijk dan hier!!. + +/editinfo.bml.logip.always=Altijd + +/editinfo.bml.logip.anon_only=Alleen wanneer men anoniem wil reageren + +/editinfo.bml.logip.header=IP adressen opslaan van mensen die reacties achterlaten? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Als je bang bent dat spam-robots je e-mailadres kunnen terugvinden en verzamelen, vink dan deze optie aan en je e-mailadres word verbrokkeld zodat deze niet gevonden wordt door e-mailverzamelrobots. + +/editinfo.bml.mangleaddress.header=Verbrokkel je gepubliceerde e-mailadres + +/editinfo.bml.name.title=Naam + +/editinfo.bml.newemail.subject=E-mail adres veranderd + +/editinfo.bml.numcomments.about=Vink deze optie aan wanneer je de reactie-URL's wilt verlengen met het aantal reacties zodat het mogelijk is links in je browser te laten zien in een andere kleur. + +/editinfo.bml.numcomments.header=Voeg &nc=xx toe aan reactie URLs + +/editinfo.bml.optional=Optioneel + +/editinfo.bml.opt_in.about<< +Als je wilt weten wanneer we een nieuwe toepassing implementeren in LiveJournal, vink dan deze optie aan. Slechts zelden zul je een e-mail ontvangen, normaal gesproken niet meer dan één of twee keer per maand. +Je e-mailadres is niet zichtbaar voor andere gebruikers, en je kunt deze optie wanneer je maar wilt weer uitschakelen. +. + +/editinfo.bml.opt_in.header=Stuur me LiveJournal nieuws. + +/editinfo.bml.persinfo.disclaimer=Vul hier wat gegevens in over jezelf, ter bevrediging van onze nieuwsgierigheid en voor statistieken. We zullen niets gemeens of vervelends doen met deze informatie, we willen gewoon graag weten wie onze gebruikers zijn en waar jullie vandaan komen. Als je iets invult, vul dan serieuze informatie in. Wanneer je bezorgd bent om je privacy, lees dan onze privacy regelement. + +/editinfo.bml.persinfo.header=Persoonlijke informatie + +/editinfo.bml.screen.all=Allemaal + +/editinfo.bml.screen.anon=Anonieme + +/editinfo.bml.screen.header=Welke antwoorden wilt u standaard afschermen? + +/editinfo.bml.screen.none=Geen + +/editinfo.bml.screen.nonfriends=Van niet-vrienden + +/editinfo.bml.screen.nonmembers=Van niet-leden + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=Beveiliging + +/editinfo.bml.security.visibility.anybody=Iedereen + +/editinfo.bml.security.visibility.everybody=Iedereen + +/editinfo.bml.security.visibility.friends=Alleen voor vrienden + +/editinfo.bml.security.visibility.regusers=Geregistreerde gebruikers + +/editinfo.bml.settings.friendspage.title=Vrienden pagina titel: + +/editinfo.bml.settings.friendspage.title.optional=Optioneel, geef een titel op voor je vriendenpagina. (geen HTML) + +/editinfo.bml.settings.header=LiveJournal instellingen + +/editinfo.bml.settings.journal.subtitle=Dagboek ondertitel: + +/editinfo.bml.settings.journal.subtitle.optional=Optioneel, geef een titel en ondertitel op voor je dagboek. (geen HTML) + +/editinfo.bml.settings.journal.title=Dagboek titel: + +/editinfo.bml.settings.privacy.about=Stel je privacy opties en instellingen hieronder in. + +/editinfo.bml.settings.privacy.header=Privacy opties + +/editinfo.bml.state.other=Of, vul andere staat/provincie/ territory in + +/editinfo.bml.state.title=Staat + +/editinfo.bml.state.us=Verenigde Staten + +/editinfo.bml.success.header=Gelukt! + +/editinfo.bml.success.message=Je informatie en dagboek instellingen en gebruikersprofiel zijn opgeslagen en vernieuwd. + +/editinfo.bml.switch.button=Wissel + +/editinfo.bml.switch.header=Wissel van dagboek + +/editinfo.bml.switch.workwith=Gebruik dagboek: + +/editinfo.bml.title=Persoonlijke informatie aanpassen + +/editinfo.bml.tm.phonenum=Volledig telefoonnummer: + +/editinfo.bml.tm.sec.about=Schakel de mogelijkheid sms berichten te ontvangen in. + +/editinfo.bml.tm.sec.title=Beveiligingsniveau: + +/editinfo.bml.tm.servprov=Servicenetwerkprovider + +/editinfo.bml.tm.title=Sms berichten + +/editinfo.bml.translatemailto.about=Als je er voor gekozen hebt om reacties op jouw berichten en reacties via e-mail te ontvangen, en je e-mail programma kan niet goed met Unicode (UTF-8) berichten omgaan, gebruik dan deze optie om een andere encoding te selecteren. LiveJournal zal dan automatisch de tekst van de reacties vertalen. + +/editinfo.bml.translatemailto.header=Vertaal e-mail reacties naar: + +/editinfo.bml.unbanusers.about=Je hebt de volgende gebruikers verboden reacties achter te laten in jouw dagboek. Vink het hokje aan per gebruikersnaam wanneer je dit verbod wilt opheffen. + +/editinfo.bml.unbanusers.header=Verboden opheffen + +/editinfo.bml.userpic.about=Hieronder is het gebruikersicoon dat je ge-upload hebt om jou voor te stellen op de LiveJournal Site, in je dagboek en de dagboeken van je vrienden. + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Om dit icoon te verwijderen of een nieuw te uploaden, ga hier naartoe. + +/editinfo.bml.userpic.header=Jouw icoon + +/editinfo.bml.userpic.none=geen plaatje ingestuurd + +/editinfo.bml.weblogscom.about=Selecteer deze optie als je wil dat Weblogs.com je dagboek vermeld telkens je een nieuw publiek bericht plaatst. + +/editinfo.bml.weblogscom.header=Verwittig Weblogs.com bij updates + +/editinfo.bml.webpagename.title=Naam van de website + +/editinfo.bml.webpageurl.title=Website URL + +/editinfo.bml.whoreply.header=Wie kan er reageren op jouw berichten? + +/editinfo.bml.zip.title=postcode + +/editinfo.bml.zip.usonly=5-cijferige postcode; alleen voor amerikaanse adressen + +/editjournal.bml.btn.proceed=Ga verder... + +/editjournal.bml.certainday=Bepaalde Dag: + +/editjournal.bml.recententries=recentste berichten + +/editjournal.bml.recententry=Recentste bericht + +/editjournal.bml.title=Pas Berichten Aan + +/editjournal.bml.viewwhat=Welke Berichten Bekijken: + +/editjournal_do.bml.btn.edit=Pas Geselecteerd Bericht Aan + +/editjournal_do.bml.btn.save=Bewaar bericht + +/editjournal_do.bml.continue.head=Klik om door te gaan + +/editjournal_do.bml.continue.text=Klik nadat u een bericht geselecteerd hebt om te aan te passen of te verwijderen op de 'Pas Aan' knop hieronder. + +/editjournal_do.bml.currmood=Huidige stemming: + +/editjournal_do.bml.currmusic=Huidige Muziek: + +/editjournal_do.bml.date=Datum: + +/editjournal_do.bml.default=standaard + +/editjournal_do.bml.edit.text=Dit is het bericht dat je selecteerde om te bewerken. Verander al de informatie die je wil aanpassen, en klik op de knop "Bewaar bericht" onderaan de pagina.

          Om dit bericht te verwijderen, verwijder je alle tekst en klik je op de knop "Bewaar bericht" onderaan de pagina. + +/editjournal_do.bml.error.getting=Er is een fout opgetreden bij het opzoeken van de beichten om te bewerken: + +/editjournal_do.bml.error.modify=Er was een fout bij het veranderen van je dagboek: + +/editjournal_do.bml.error.nofind=Het geslecteerd bericht is niet gevonden. + +/editjournal_do.bml.event=Gebeurtenis: + +/editjournal_do.bml.localtime=Lokale tijd: + +/editjournal_do.bml.noneother=Geen, of andere: + +/editjournal_do.bml.opt.backdate=Het bericht pre-dateren: + +/editjournal_do.bml.opt.backdate.about=zal niet in vriendenpagina verschijnen + +/editjournal_do.bml.opt.nocomments=Laat Geen Commentaar Toe: + +/editjournal_do.bml.opt.noemail=Stuur Commentaar Niet Op Via E-mail: + +/editjournal_do.bml.opt.noformat=Niet automatisch opmaken: + +/editjournal_do.bml.other=Andere: + +/editjournal_do.bml.pickentry.head=Kies een bericht om aan te passen + +/editjournal_do.bml.pickentry.text=Selecteer het bericht dat u wilt aanpassen en klik op de 'Pas Aan' knop onderaan de pagina. + +/editjournal_do.bml.picture=Icoon te gebruiken: + +/editjournal_do.bml.save.head=Klik om op te slaan.... + +/editjournal_do.bml.save.text=Nadat je je bericht bewerkt hebt, druk op "Bewaar bericht". + +/editjournal_do.bml.subject=Onderwerp: (optioneel) + +/editjournal_do.bml.success.delete=Het bericht is verwijderd. + +/editjournal_do.bml.success.edit=Bericht bewerkt. U kan het hier bekijken. + +/editjournal_do.bml.success.head=Gelukt + +/editjournal_do.bml.timeformat=24 uurs tijd + +/editjournal_do.bml.title=Pas Berichten Aan + +/editpics.bml.btn.proceed=Ga verder + +/export.bml.btn.proceed=Ga verder... + +/export.bml.description|staleness=1 +/export.bml.description=Hier kan je je hele dagboek downloaden in een eigen formaat, om zelf een reserve kopie te hebben. + +/export.bml.fields=Velden: + +/export.bml.format.csv=CSV (Comma Separated Values, velden gescheiden door komma's) + +/export.bml.label.field.currents=Huidige stemming & muziek + +/export.bml.label.field.event=Gebeurtenis + +/export.bml.label.field.eventtime=Tijd van de gebeurtenis (op basis van de klok van de gebruiker) + +/export.bml.label.field.itemid=ID Nummer + +/export.bml.label.field.logtime=Log tijd (klok van het livejournal systeem) + +/export.bml.label.field.security=Beveiligingsniveau + +/export.bml.label.field.subject=Onderwerp + +/export.bml.label.format=Formaat: + +/export.bml.label.header=Hoofding (zet veldnamen in de geëxporteerde file) + +/export.bml.label.month=Selecteer maand: + +/export.bml.label.month.year=jjjj: + +/export.bml.label.notranslation=Vertaal niet tussen coderingen + +/export.bml.label.what=Wat exporteren: + +/export.bml.title=Exporteer dagboek + +/export.bml.what.entries=Dagboekberichten + +/friends/add.bml.add.header=Gelukt + +/friends/add.bml.add.text=Gebruiker [[ljuser]] is aan je vriendenlijst toegevoegd. Je kunt je vriendenpagina hier bekijken. + +/friends/add.bml.add.title=Vriend toegevoegd! + +/friends/add.bml.btn.add=Voeg [[user]] toe + +/friends/add.bml.btn.modify=Wijzigen + +/friends/add.bml.btn.remove=Verwijderen + +/friends/add.bml.colors.bg=Achtergrond + +/friends/add.bml.colors.fg=Voorgrond + +/friends/add.bml.colors.header=Kleuren + +/friends/add.bml.colors.hover=(Beweeg je muis over een kleur om te zien wat de naam ervan is) + +/friends/add.bml.colors.text=Je kan ook de kleuren selecteren die met [[user]] geassocieerd zullen worden in je vriendenlijst. + +/friends/add.bml.confirm.header=Voeg [[user]] toe als vriend? + +/friends/add.bml.confirm.text=Klik op de knop hieronder om [[user]] toe te voegen aan je vriendlijst. + +/friends/add.bml.confirm.title=Voeg vriend toe + +/friends/add.bml.error1.header=Je moet eerst inloggen + +/friends/add.bml.error1.text=Om een gebruiker aan je vriendlijst toe te voegen moet je eerst inloggen. Als je nog geen account hebt, kun je er eentje aanmaken om zo je vrienden op de voet te kunnen blijven volgen. + +/friends/add.bml.error1.title=Voeg Vrienden Toe + +/friends/add.bml.error2.text=Ongeldige gebruikersnaam of gebruikersnaam niet opgegeven. Om een vriend toe te voegen, ga naar de Bewerk vriendenlijst pagina. + +/friends/add.bml.error3.text=Je hebt [[user]] al eerder aan je vriendenlijst toegevoegd. Je kunt eventueel de kleuren aanpassen die bij deze vriend op je vriendenpagina verschijnen. + +/friends/add.bml.error3.title=Vriend aanpassen + +/friends/add.bml.groups.header=Vriendengroepen + +/friends/add.bml.groups.nogroup=Je hebt nog geen vriendengroepen gemaakt. + +/friends/add.bml.groups.text=In welke vriendegroep wil je deze gebruiker opslaan? Vriendengroepen kun je gebruiken om je vriendenlijst te filteren en bepaalde berichten in je dagboek zichtbaar te maken aan een selecte groep vrienden. + +/friends/add.bml.remove.header=Gelukt + +/friends/add.bml.remove.text=Gebruiker is van je vriendenlijst verwijderd. Je kunt je vriendenpagina hier bekijken. + +/friends/add.bml.remove.title=Vriend verwijderd! + +/friends/edit.bml.title=Bewerk vriendenlijst + +/friends/editgroups.bml.btn.ge.del=Verwijderen + +/friends/editgroups.bml.btn.ge.new=Nieuw + +/friends/editgroups.bml.btn.ge.ren=Hernoemen + +/friends/editgroups.bml.btn.gs.private=Privé + +/friends/editgroups.bml.btn.gs.public=Publiek + +/friends/editgroups.bml.btn.mv.down=Omhoog + +/friends/editgroups.bml.btn.mv.up=Omlaag + +/friends/editgroups.bml.confirm.delete=Ben je zeker dat je deze vriendengroep wil verwijderen? + +/friends/editgroups.bml.done.btn=Veranderingen opslaan + +/friends/editgroups.bml.done.header=Klaar? + +/friends/editgroups.bml.done.text=Als je klaar bent, klik dan op de "Veranderingen opslaan" knop hieronder: + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Je hebt het maximum van 30 vriendengroepen bereikt. Als je een of meer groepen hebt verwijderd maar die veranderingen nog niet opgeslagen hebt, doe dat dan nu, en kom dan terug naar hier en herlaad de pagina. Dan zal je nieuwe vriendengroepen kunnen maken. + +/friends/editgroups.bml.error.text=De sewrver gaf het volgende foutbericht terug: + +/friends/editgroups.bml.group.public=(publiek) + +/friends/editgroups.bml.ingroup=In groep: + +/friends/editgroups.bml.ingroup.not=Niet in groep: + +/friends/editgroups.bml.prompt.newname=Geef de naam voor de nieuwe vriendengroep: + +/friends/editgroups.bml.prompt.rename=Verander de naam van deze vriendengroep in: + +/friends/editgroups.bml.saved.header=Bewaard + +/friends/editgroups.bml.saved.text=Je vriendengroepen zijn nu opgeslagen. + +/friends/editgroups.bml.text|staleness=1 +/friends/editgroups.bml.text<< +Deze pagina laat je toe vriendengroepen te maken en te bewerken. Vriendengroepen worden gebruikt om berichten te beveiligen en om je vriendenpagina te filteren. +Deze pagina heeft Javascript nodig om te kunnen werken. +. + +/friends/editgroups.bml.text.sec<< +Beveiligings opmerking: Als je een groep wil verwijderen en een nieuwe aanmaken, doe dat dan niet door een groep te hernoemen en dan te bewerken. +Als je dit doet, worden alle je vroegere berichten die de oude groep kon zien ook zichtbaar voor de nieuwe groep. +. + +/friends/editgroups.bml.title=Pas je vriendengroepen aan + +/friends/editgroups.bml.yourgroups=Je vriendengroepen: + +/friends/edit_do.bml.addfriends.head=Voeg vrienden toe + +/friends/edit_do.bml.addfriends.text=Vul de namen van je vrienden in in de vakken hieronder, en kies de achtergrond en voorgrond kleuren die je met hen wil associeren... + +/friends/edit_do.bml.background=Achtergrond + +/friends/edit_do.bml.bgcolor=Achtergrond Kleur: + +/friends/edit_do.bml.btn.close=Sluiten + +/friends/edit_do.bml.btn.save=Veranderingen opslaan + +/friends/edit_do.bml.btn.toggle=Voorbeeldvenster Aan/Uit + +/friends/edit_do.bml.done.head=Klaar? + +/friends/edit_do.bml.done.text=Als je klaar bent, klik dan op de "Veranderingen opslaan" knop hieronder: + +/friends/edit_do.bml.error.updating=Er is een fout opgetreden bij het bewerken van je vriendenlijst: + +/friends/edit_do.bml.fellowfriends.head=Gemeenschappelijke vrienden + +/friends/edit_do.bml.fellowfriends.text=De volgende mensen hebben je als hun vriend opgegeven... Je zou hen ook aan je vriendenlijst kunnen toevoegen. Maar dit is vooral ter referentie zodat je ook hun LiveJournal gebruikersnamen kent. Je bent helemaal niet verplicht ze aan je lijst toe te voegen. + +/friends/edit_do.bml.foreground=Voorgrond + +/friends/edit_do.bml.friend=Vriend + +/friends/edit_do.bml.hover=Hou de muiswijzer boven een kleur om de naam te zien. + +/friends/edit_do.bml.mrcolor=Mr. Kleurvoorbeeld + +/friends/edit_do.bml.name=Naam + +/friends/edit_do.bml.needmore=Als je meer vrienden wil toevoegen dan er hier plaats is, bewaar de veranderingen hieronder, en kom dan terug om er meer toe te voegen. + +/friends/edit_do.bml.nofriends.head=Geen vrienden? + +/friends/edit_do.bml.nofriends.text=U heeft op dit moment geen vrienden gedefinieerd. Maar we zijn er zeker van dat u een paar vrienden heeft! :) Vul hun namen hieronder in... + +/friends/edit_do.bml.opt.delete=Uitvegen? + +/friends/edit_do.bml.success.head=Gelukt + +/friends/edit_do.bml.success.text=Je vriendenlijst is aangepast. Je kan je aangepaste vrienden pagina hier bekijken. + +/friends/edit_do.bml.textcolor=Tekst Kleur: + +/friends/edit_do.bml.title=Bewerk je vriendenlijst + +/friends/edit_do.bml.user=Gebruiker + +/friends/edit_do.bml.viewer=Kleuren voorbeeld + +/friends/edit_do.bml.yourfriends.head=Je vrienden + +/friends/edit_do.bml.yourfriends.text=Je hebt op dit moment de volgende vrienden gedefinieerd: + +/friends/filter.bml.editgroups=Om je vriendengroupen aan te passen, ga naar [[link]]. + +/friends/filter.bml.select=Selecteer de vriendengroep(en) die je op je vriendenpagina wil zien. + +/friends/filter.bml.select.header=Selecteer groepen + +/friends/index.bml.title=Vrienden + +/friends/popwithfriends.bml.count=Aantal + +/friends/popwithfriends.bml.user=Gebruiker + +/index.bml.boldcreate=Open je eigen LiveJournal! + +/index.bml.frank.image.alt=Frank de geit, de LiveJournal mascotte. + +/index.bml.frank.logo="Mèèèèèh", zegt Frank. + +/index.bml.meta.desc=LiveJournal is een plaats op het internet waar je je gedachten kunt delen met de rest van de wereld. + +/index.bml.meta.keywords=dagboek, journaal, online journaal, dagboeken, schrijven, online dagboek, webdagboek + +/interests.bml.add.added.head=Toegevoegd! + +/interests.bml.add.added.text=Deze interesse is toegevoegd aan je lijst. + +/interests.bml.add.btn.text=Voeg [[interest]] toe + +/interests.bml.add.confirm.head=bevestig + +/interests.bml.add.confirm.text=Om [[interest]] toe te voegen als interesse, klik op de knop. + +/interests.bml.add.toomany.head=Helaas.. + +/interests.bml.add.toomany.text=Je hebt reeds [[maxinterests]] interesses in je lijstje. + +/interests.bml.addint=Als u hier ook geinteresseerd in bent en aan de lijst toegevoegd wil worden, klik hier. + +/interests.bml.btn.switch=Wissel + +/interests.bml.communities.head=Relevante Groepen + +/interests.bml.communities.text=De volgende groepen zijn ook geinteresseerd in "[[interest]]". + +/interests.bml.count=Aantal + +/interests.bml.enmasse.body.other=Dit zijn de interesses van [[user]]. Selecteer de interesses die je wil toevoegen aan je eigen interesses en deselecteer de interesses die je wil verwijderen. Als je klaar bent, klik dan op "Veranderingen opslaan". + +/interests.bml.enmasse.body.other_authas=Dit zijn de interesses van [[user]]. Selecteer de interesses die je wil toevoegen aan die van [[target]] en deselecteer de interesses die je wil verwijderen. Als je klaar bent, klik dan op "Veranderingen opslaan". + +/interests.bml.enmasse.body.you=Deselecteer de interesses die je wil verwijderen. Als je klaar bent, klik dan op "Veranderingen opslaan". + +/interests.bml.enmasse.btn=Toon lijst + +/interests.bml.enmasse.header=Toevoegen/Verwijderen interesses + +/interests.bml.enmasse.intro=Verander je interesses op basis van die van: + +/interests.bml.error.add.mustlogin=Je moet ingelogd zijn om op deze manier een interesse toe te kunnen voegen. + +/interests.bml.error.enmasse.mustlogin=Je moet ingelogd zijn om dit te gebruiken + +/interests.bml.error.enmasse.noaccess=Je hebt geen toegang tot het dagboek [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Interesse werd niet gevonden. + +/interests.bml.error.nointerests=De geselecteerde gebruiker bestaat niet of heeft geen interesses opgegeven. + +/interests.bml.findsim.searchwait=Let Op: Het zoeken zal een aantal seconden duren. Even geduld aub. + +/interests.bml.findsim_do.account.notallowed=Sorry, je account type laat je niet toe deze mogelijkheid te gebruiken. + +/interests.bml.findsim_do.magic=Magische
          Index + +/interests.bml.findsim_do.magic.head=Magische Index? + +/interests.bml.findsim_do.magic.text=Voor elke overeenkomende gebruiker wordt een migische index berekend, die een weging is van 2 factoren: het aantal gelijke interesses, en wat extra punten voor het delen van een weinig voorkomende interesse. + +/interests.bml.findsim_do.nomatch.head=Geen overeenstemming + +/interests.bml.findsim_do.nomatch.text=Er zijn geen gebruikers die overeenstemmen met [[user]]. + +/interests.bml.findsim_do.notdefined=Gebruiker [[user]] heeft geen interesses ingevuld. + +/interests.bml.findsim_do.similar.head=Gelijkaardige Gebruikers + +/interests.bml.findsim_do.similar.text=De volgende gebruikers hebben het meest in overeenstemming met [[user]] + +/interests.bml.finished.about=Als je klaar bent, klik dan op de "Veranderingen opslaan" knop hieronder: + +/interests.bml.finished.header=Klaar? + +/interests.bml.finished.save_button=Veranderingen opslaan + +/interests.bml.interest=Interesse + +/interests.bml.interested.btn.find=Vind + +/interests.bml.interested.in|staleness=1 +/interests.bml.interested.in=Vind mensen geinteresseerd in: + +/interests.bml.interests.findsim=Vind gebruikers met interesses gelijkend op die van: + +/interests.bml.interests.head=Interesses + +/interests.bml.interests.text=Dit zijn enkele leuke dingen die je kan doen met interesses. + +/interests.bml.interests.viewpop=Bekijk populaire interesses + +/interests.bml.login.enterinfo=Vul je naam en paswoord in om je interesses te veranderen. + +/interests.bml.login.proceed=Ga verder... + +/interests.bml.match=[[count]] overeenkomst: + +/interests.bml.matches=[[count]] overeenkomsten: + +/interests.bml.morestuff=Nog meer leuke dingen vindt u op de interesses pagina. + +/interests.bml.nointerests.text=Heb je geen interesses ingesteld? Voeg er enkele toe door naar de Persoonlijke informatie aanpassen pagina te gaan. + +/interests.bml.popular.head=Populaire Interesses + +/interests.bml.popular.text=Dit zijn de meest populaire interesses. + +/interests.bml.results.added=De interesses die je selecteerde zijn aan je interesselijst toegevoegd. + +/interests.bml.results.both=De interesses die je selecteerde zijn aan je interesselijst toegevoegd, en degene die je deslecteerde zijn verwijderd. + +/interests.bml.results.deleted=De interesses die je deselecteerde zijn uit je interesselijst verwijderd. + +/interests.bml.results.goback=Je kan ook teruggaan naar het profiel van [[user]] dat je aan het bekijken was. + +/interests.bml.results.header=Resultaten + +/interests.bml.results.message=Bekijk je aangepaste profiel pagina. + +/interests.bml.results.nothing=Je hebt niets veranderd. + +/interests.bml.results.toomany<< +Je hebt teveel interesses geselecteerd om toe te voegen. Je kan maximaal [[intcount]] interesses hebben. Geen van de geselecteerde interesses zijn toegevoegd aan je interesselijst. +Je kan teruggaan en opnieuw proberen, en minder toe te voegen interesses selecteren. +. + +/interests.bml.title=Interesses + +/interests.bml.toomany.body=Er zijn [[intcount]] mensen en/of groepen met deze interesse. Een lijst zal niet getoond worden. + +/interests.bml.toomany.head=Veel overeenkomsten + +/interests.bml.users.head=Geinteresseerde gebruikers + +/interests.bml.users.text=De volgende gebruikers zijn geinteresseerd in [[interest]]. + +/legal/index.bml.about.header=Overzicht + +/legal/index.bml.docs.coppa.about=De amerikaanse "Children's Online Privacy Protection Act" (afgekort: COPPA) regelt het online verzamelen en gebruiken van persoonlijk informatie verstrekt door en betreffende kinderen onder 13 jaar. Onze COPPA pagina legt ons standpunt met betrekking tot deze wet uit, en legt uit hoe COPPA problemen te behandelen. + +/legal/index.bml.docs.header=Docmenten + +/legal/index.bml.docs.privacy.about=Het Privacy Beleid geeft informatie over welke gegevens verzameld worden van onze gebruikers en wat we met deze gegevens doen. + +/legal/privacy.bml.title=Privacy Beleid + +/login.bml.bindip.label=Verbinden aan IP adres: + +/login.bml.bindip.no=Nee (werkt met alle internetverbindingen) + +/login.bml.bindip.yes=Ja (veiliger) + +/login.bml.error.mustenterusername=U moet een gebruikersnaam opgeven. + +/login.bml.expire.btn.neverexpire=Laat je login NOOIT aflopen + +/login.bml.expire.btn.sessiononly=Laat je login alfopen wanneer de BROWSER SLUIT + +/login.bml.expire.neverexpire.text=Je login zal nooit aflopen, dus als je aan een publieke computer zit, of op een school, bibliotheek, of een andere plaats waar anderen deze computer kort na jouw zullen gebruiken, zorg er dan zeker voor dat je uitlogt als je gedaan hebt! Of, verander je login om af te lopen als de browser sluit: + +/login.bml.expire.sessiononly.text=Je login zal aflopen als je je browser sluit. Als dit je eigen computer is en je bent de enige gebruiker, dan wil je misschien je login zo instellen dat hij nooit afloopt: + +/login.bml.links.link1=Jouw vrienden pagina. + +/login.bml.links.link2=Uw te-doen lijst. + +/login.bml.links.text=In de toekomst zal deze pagina allerlei links en relevante informatie bevatten, maar hier zijn al enkele links die u misschien wilt bezoeken: + +/login.bml.loggedin.head=Inglogd! + +/login.bml.loggedin.text=Je bent nu ingelogd. + +/login.bml.login.btn.changeopts=Verander opties + +/login.bml.login.btn.login=Log In... + +/login.bml.login.expiration=Aflopen: + +/login.bml.login.forget=Vergeten? + +/login.bml.login.head=Inloggen + +/login.bml.login.never=Nooit + +/login.bml.login.otheropts=Andere Opties: + +/login.bml.login.password=Paswoord: + +/login.bml.login.text1=Om in te loggen op [[sitename]], vul je gebruikersnaam en paswoord hieronder in. Nieuwe Gebruikers: Om een account aan te maken, ga naar hier. + +/login.bml.login.text2|staleness=1 +/login.bml.login.text2=Je kan ook opgeven wanneer je login afloopt. Standaard loopt je login af als je je browser sluit, dit is het beste op publieke computers. Als je echter de enige gebruiker van jouw computer bent en niemand anders daar aan kan, kan je kiezen om altijd ingelogd te blijven. + +/login.bml.login.username=Gebruikersnaam: + +/login.bml.login.whenbrowsercloses=Als browser sluit + +/login.bml.logout.btn=Log uit + +/login.bml.title=Inloggen + +/login.bml.whylogin.benefit1=Je moet je gebruikersnaam/paswoord nergens op de site meer invullen. + +/login.bml.whylogin.benefit2=Je kan "beschermde" ("protected") berichten zien van vrienden die je daar toegang tot gegeven hebben. + +/login.bml.whylogin.benefit3=Vele mogelijkheden zijn enkel zichtbaar of toegangkelijk als je ingelogd bent. + +/login.bml.whylogin.head=Waarom Inloggen? + +/login.bml.whylogin.text=Hier zijn enkele van de voordelen van inloggen: + +/logout.bml.already.head=Reeds uitgelogd + +/logout.bml.already.text=Je bent reeds uitgelogd. + +/logout.bml.killall.btn=Doe al mijn sessies aflopen + +/logout.bml.killall.head=Andere sessies + +/logout.bml.killall.text=Je hebt andere actieve sessies. Will je al je sessies laten aflopen, en niet enkel deze? (Lees deze FAQ voor meer informatie.) + +/logout.bml.loggedout.already=Reeds uitgelogd. + +/logout.bml.loggedout.head=Uitgelogd + +/logout.bml.loggedout.killedall=Al je sessies zijn beëindigd. + +/logout.bml.loggedout.success=Uitgelogd. + +/logout.bml.loggedout.text=Je bent nu uitgelogd. + +/logout.bml.logout.btn=Log uit + +/logout.bml.logout.head=Log uit? + +/logout.bml.logout.text=Klik op de knop hieronder om uit te loggen. + +/logout.bml.title=Uitloggen + +/lostinfo.bml.btn.proceed=Ga verder + +/lostinfo.bml.enter_email=Vul je e-mailadres in: + +/lostinfo.bml.enter_email_optional=e-mailadres: (optioneel) + +/lostinfo.bml.enter_username=Vul je gebruikersnaam in: + +/lostinfo.bml.lostpassword.text|staleness=1 +/lostinfo.bml.lostpassword.text=Wanneer je je wachtwoord vergeten bent, vul hier je gebruikersnaam in en indien mogelijk ook het e-mailadres waar je het password heen wilt laten sturen. Denk eraan dat het e-mailadres dat je hier invult bekent moet zijn bij LiveJournal en is gevalideerd. Als je het e-mailadresveld leeg laat, zal je password verstuurd woorden naar de actuele e-mailadres dat ingevuld is bij je gebruikersinformatie. + +/lostinfo.bml.lostpassword.title=Paswoord vergeten? + +/lostinfo.bml.lostusername.text=Als je je gebruikersnaam vergeten bent, vul dan je e-mailadres in en we sturen je dan per e-mail je gebruikersnaam toe. + +/lostinfo.bml.lostusername.title=Gebruikersnaam vergeten? + +/lostinfo.bml.title=Vergeten informatie + +/lostinfo_do.bml.error.no_usernames_for_email=Geen gebruikers geregisteerd op dit e-mailadres: [[address]]. + +/lostinfo_do.bml.error1.text=Je hebt dit e-mailadres niet eerder gebruikt samen met dit account, of het is niet eerder goedgekeurd/gevalideerd. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< + *** Dit is een automatisch verstuurde email. Je moet hier niet op antwoorden. *** + + Dit is de herinnering aan het paswoord die je vroeg aan [[sitename]]. + Hieronder staat je gebruikersnaam, paswoord en het e-mail adres waarop je dagboek geregistreerd staat. + + Gebruikersnaam: [[username]] + Paswoord: [[password]] + E-mail Adres: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Om je adres te valideren, ga naar hier: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Deze informatie werd aangevraagd op de website vanop [[remoteip]]. + +Als je deze informatie niet aangevraagd had, geen paniek. Tenslotte ben jij de enige persoon die deze e-mail ziet, en niet de andere. Het is best mogelijk dat de gebruiker die de aanvraag deed zich vergist heeft en gelooft dat hij of zij deze gebruikersnaam heeft. Het is ook mogelijk dat iemand een typfout maakte in zijn gebruikersnaam of e-mail adres. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4=Als je echt denkt dat je account niet veilig is, lees dan http://www.livejournal.com/support/faqbrowse.bml?faqid=117 voor informatie over hoe je die opnieuw veilig kan maken. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Handige links: + + Je LiveJournal: + [[journalurl]] + + Werk je dagboek online bij: + [[updateurl]] + +met vriendelijke groeten, +het LiveJournal team + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Paswoord vergeten + +/lostinfo_do.bml.password_mailed.text=Gelukt. Je paswoord is verstuurd. + +/lostinfo_do.bml.password_mailed.title=Paswoord verstuurd! + +/lostinfo_do.bml.title=Vergeten informatie + +/lostinfo_do.bml.username_mailed.text=Gelukt. Je gebruikersnaam is verstuurd. + +/lostinfo_do.bml.username_mailed.title=Gebruikersnaam is verstuurd! + +/modify.bml.title=Pas Dagboek Aan + +/modify_do.bml.availablestyles.head=Beschikbare Stijlen + +/modify_do.bml.availablestyles.userstyles=Gebruikersstijlen: + +/modify_do.bml.colortheme.about=Hier kan je selecteren welk kleuren patroon zal toegepast worden op de layout opties die je hierboven kiest. Of, als je de kleuren niet goed vindt, stel je eigen kleuren in! + +/modify_do.bml.colortheme.area.head=Plaats waar de kleur gebruikt wordt + +/modify_do.bml.colortheme.color.head1=Kleur + +/modify_do.bml.colortheme.color.head2=(#rrggbb of naam) + +/modify_do.bml.colortheme.customcolors=Eigen kleuren + +/modify_do.bml.colortheme.defaulttheme=Standaard patroon + +/modify_do.bml.colortheme.head=Kleuren Patroon + +/modify_do.bml.domainalias.about=Wanneer je een domeinnaam hebt geregistreerd (of wanneer je dit van plan bent) kun je het zo instellen dat het automatisch je livejournal opent. Vul hier je domeinnaam in: + +/modify_do.bml.domainalias.domainname=Domeinnaam: + +/modify_do.bml.domainalias.example=Vorbeeld: mijn-journal.com + +/modify_do.bml.domainalias.head=Domein Aliasing + +/modify_do.bml.domainalias.helptext|staleness=1 +/modify_do.bml.domainalias.helptext=Dit werkt alleen wanneer je domeinnaam DNS naar IP adres van [[sitenaam]] wijst. + +/modify_do.bml.done.btn.savechanges=Veranderingen opslaan + +/modify_do.bml.done.head=Klaar? + +/modify_do.bml.done.text=Als je klaar bent, klik dan op de "Veranderingen opslaan" knop hieronder: + +/modify_do.bml.error.dupdomainalias=Een andere gebruiker heeft reeds dit domeinnaam in gebruik. + +/modify_do.bml.error.stylenotavailable=Een van de geselecteerde stijlen is niet beschikbaar. Dit komt ofwel omdat iemand de stijl gedelete heeft, of omdat u er een gekozen heeft waar u geen toegang tot hebt. + +/modify_do.bml.friends.about=Dit zijn de opties die bepalen hoe je vrienden pagina eruit ziet. + +/modify_do.bml.friends.head=Vrienden Pagina + +/modify_do.bml.friends.opt.usesharedpic.about=Deze optie bepaalt welk icoon je ziet op je vrienden pagina als een gebruiker een bericht schrijft in een gedeeld dagboek of een groepsdagboek. Als je dit aanvinkt, zal je het icoon van de groep zien. Als je het niet aanvinkt, zal je het persoonlijk icoon zien van de persoon die het bericht schreef. + +/modify_do.bml.friends.opt.usesharedpic.head=Gebruik het icoon van een groepsdagboek in plaats van het icoon van de schrijver + +/modify_do.bml.journaloptions.about=Hier kan je het uitzicht van je LiveJournal pagina's aanpassen. Als je benieuwd bent hoe alles werkt, lees dan de ontwikkelaars informatie. Anders zullen we aannemen dat je genoeg hebt aan de basisopties hieronder: + +/modify_do.bml.journaloptions.head=Dagboek Opties + +/modify_do.bml.journalstatus.about=Als je jouw dagboek wil verwijderen of het verwijderen ongedaan wilt maken (opnieuw activeren), kan je dat hier doen. Nadat je jouw dagboek verwijderd hebt, heb je 30 dagen om dit ongedaan te maken, mocht je van idee veranderen. Na 30 dagen zal het dagboek definitief verwijderd worden en is er geen manier meer om dit ongedaan te maken. + +/modify_do.bml.journalstatus.head=Dagboek Activatie Toestand + +/modify_do.bml.journalstatus.select.activated=Geactiveerd + +/modify_do.bml.journalstatus.select.deleted=Verwijderd + +/modify_do.bml.journalstatus.select.head=Toestand: + +/modify_do.bml.journalstatus.select.suspended=Geschorst + +/modify_do.bml.moodicons.about=Als je in je dagboek schrijft kan je ook je huidige stemming opgeven. Verschillende gebruikers hebben verschillende sets stemmingsicoontjes opgestuurd die je kan gebruiken. Of, selecteer "Geen" als je helemaal geen icoontjes naast je stemming wilt. (Je moet de "huidige stemming" mogelijkheid natuurlijk niet gebruiken.) + +/modify_do.bml.moodicons.head=Stemmingsicoontjes + +/modify_do.bml.moodicons.opt.forcefriends.about=Forceer dit stemmingspatroon voor alle vrienden op je vrienden pagina. + +/modify_do.bml.moodicons.personal=Persoonlijke patronen: + +/modify_do.bml.moodicons.preview=voorbeeld + +/modify_do.bml.moodicons.select=Kies de stemmingsiconen set: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Je kan deze sectie negeren. Ze dient om zeer specifieke dingen aan de layout van je pagina aan te passen. Zie ontwikkelaars informatie voor details. Merk ook op dat deze 'overrides' enkel dienen om een of twee dingen uit een stijl te veranderen. Als je alles wil veranderen, heb je maak je eigen stijl nodig. + +/modify_do.bml.overrides.head=Stijl 'Overrides' + +/modify_do.bml.overrides.note=Merk op dat niet alle stijl variabelen handmatig aangepast kunnen worden. Zie de documentatie voor meer details. + +/modify_do.bml.overrides.warning=DIT IS NIET DE PLAATS OM UW DAGBOEK IN TE TYPEN!! + +/modify_do.bml.pagelayoutstyle.about=Hier stelt u in hoe uw dagboek op het scherm wordt opgemaakt. + +/modify_do.bml.pagelayoutstyle.head=Pagina Opmaak Stijl + +/modify_do.bml.pagelayoutstyle.warning=Uw account type laat u slechts toe te keizen uit een klein aantal standaard stijlen. + +/modify_do.bml.success.head=Gelukt + +/modify_do.bml.success.text=Uw dagboek instellingen zijn aangepast. U kan uw dagboek hier bekijken. + +/paidaccounts/index.bml.costs.header=En, hoeveel kost dit nu? + +/paidaccounts/index.bml.costs.rates=De bedragen zijn als volgt: + +/paidaccounts/index.bml.costs.rates.amount.header=Bedrag + +/paidaccounts/index.bml.costs.rates.inexpensive<< +Dit is maar iets meer dan $2 per maand voor het jaarabonnement. +Nauwelijks een aanslag op je portemonnaie dus. +Het meest vervelende van het aanschaffen van een betaald account is waarschijnlijk het opzoeken van je portemonnaie, je creditcard eruit vissen, en je informatie invullen. +. + +/paidaccounts/index.bml.costs.rates.time.header=Periode + +/paidaccounts/index.bml.features.header=Wat voor toffe mogelijkheden krijg ik allemaal? + +/paidaccounts/index.bml.title=Over betaalde accounts + +/paidaccounts/index.bml.whypay.argument<< +Nee, natuurlijk is dit niet zo gek. Moeten betalen voor het gebruikmaken van web services is vervelend, dat vinden wij ook. +Dat is de reden waarom bijna alle functionaliteiten van LiveJournal beschikbaar zijn zonder dat je hiervoor hoeft te betalen. +Maar, wanneer je tevreden bent over de service die je krijgt van LiveJournal, kun je door middel van het aanschaffen van een betaald account je steun tonen. +. + +/paidaccounts/index.bml.whypay.header=Moet ik betalen om LiveJournal te kunnen gebruiken? + +/paidaccounts/index.bml.whypay.no_ads=Het kost veel geld websites draaiende te houden (denk aan serverruimte, bandbreedte, hardware) en dit lijkt ons een betere manier om aan geld te komen om dit alles te kunnen betalen, dan door jullie dood te gooien met pop-ups en reclame. + +/paidaccounts/index.bml.your_username=gebruikersnaam + +/paidaccounts/usepaypal.bml.delivery.badformat=Onjuist afleveringsdatum formaat. Het moet van deze vorm zijn: jjjj-mm-dd of jjjj-mm-dd uu:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Aflevering kan niet in het verleden gebeuren. Om onmiddleijk af te leveren, laat het afleveringsdatum vak leeg. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Afleveringsdatum kan niet verder dan een maand in de toekomst zijn. + +/pay/index.bml.deliverydate.details=Formaat: jjjj-mm-dd uu:mm (GMT tijd)
          (leeg laten als je geen verlate leveringsdatum wil) + +/pay/index.bml.deliverydate.label=Leveringsdatum: + +/pay/index.bml.gift.anonymous=Anoniem cadeau + +/register.bml.email.body|staleness=1 +/register.bml.email.body<< +Dit is de bevestigingsemail waar je om gevraagd had. +Ga om het je account te bevestigen naar: + +[[conflink]] + +Het is mogelijk dat je deze link naar je browser moet kopieren. + +Met vriendelijke groet, +[[sitename]] +[[siteroot]] +. + +/register.bml.email.subject=Bevestig E-mail + +/register.bml.error.invalidcode=Ongeldige bevestigingscode + +/register.bml.error.usernotfound=Gebruiker niet gevonden + +/register.bml.new.body=Bedankt! Je e-mailadres is bevestigd. Misschien wil je nou een van de volgende dingen doen. + +/register.bml.new.editinfo=Verander je informatie -- vul je profiel in en stel je instellingen in. + +/register.bml.new.header=Succes + +/register.bml.new.login=Log in -- zodat je niet overal je gebruikersnaam en wachtwoord in hoeft te vullen + +/site/goat.bml.image.alt=Frank de geit, de LiveJournal mascotte. + +/site/goat.bml.image.caption="Mèèèèèh", zegt Frank. + +/site/goat.bml.meet.header=Dit is Frank + +/site/goat.bml.title=Frank de geit + +/suggestions/index.bml.welcome.title=Welkom! + +/support/encodings.bml.edit.header=Ik kan mijn berichten niet aanpassen via de LiveJournal website! + +/support/encodings.bml.editcl.header=Ik kan mijn berichten niet veranderen in mijn client programma! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Ik kan mijn vriendengroepen niet veranderen in mijn client programma! + +/support/encodings.bml.groups.text=groep bewerken pagina en dan je client programma gebruiken. p?> + +/support/encodings.bml.overview.header=Waar gaat dit allemaal over? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Nog geen stap verder? + +/support/encodings.bml.still.text=Ondersteunings deel. p?> + +/support/faqbrowse.bml.backfaq=Terug naar de FAQ. + +/support/faqbrowse.bml.backsupport=Terug naar het ondersteunings deel + +/support/faqbrowse.bml.error.nofaq=De opgegeven FAQ bestaat niet. + +/support/faqbrowse.bml.lastupdated=Laatst toegevoegd: + +/support/see_overrides.bml.error.nos1=Deze gebruiker gebruikt S1 niet. + +/support/see_overrides.bml.header=Overrides voor : + +/support/see_overrides.bml.title=Gebruikers overrides + +/talkmulti.bml.deleted.body=De reacties zijn verwijderd. Je kan de rest van de reacties hier bekijken. + +/talkmulti.bml.deleted.title=Reacties verwijderd + +/talkmulti.bml.error.comms_deleted=Een van de reacties is verwijderd sinds je het geselecteerd hebt. Ga voor de zekerheid terug en probeer het dan nogmaals. + +/talkmulti.bml.error.inconsistent_data=De ingevoerde gegevens zijn niet consistent. + +/talkmulti.bml.error.invalid=Ongeldige parameters meegegeven. + +/talkmulti.bml.error.invalid_mode=Je hebt geen actie geselecteerd. Ga terug en kies of je de reacties wil afschermen, hun afscherming opheffen, of ze wil verwijderen. + +/talkmulti.bml.error.login=Je bent niet ingelogd. + +/talkmulti.bml.error.none_selected=Je hebt geen reacties geslecteerd. + +/talkmulti.bml.error.privs.delete=Je hebt niet het recht om deze reacties te verwijderen. + +/talkmulti.bml.error.privs.screen=Je hebt niet het recht om deze reacties af te schermen. + +/talkmulti.bml.error.privs.unscreen=Je hebt niet het recht om de afscherming van deze reacties ongedaan te maken. + +/talkmulti.bml.screened.body=De reacties zijn afgeschermd. Je kan ze hier bekijken. + +/talkmulti.bml.screened.title=Reacties afgeschermd + +/talkmulti.bml.title.delete=Meerdere reacties verwijderen + +/talkmulti.bml.title.screen=Meerdere reacties afschermen + +/talkmulti.bml.title.unscreen=Afschermen meerdere reacties ongedaan maken + +/talkmulti.bml.unscreened.body=De afscherming van de reacties is ongedaan gemaakt. Je kan ze hier bekijken. + +/talkmulti.bml.unscreened.title=Afscherming reacties ongedaan gemaakt + +/talkpost.bml.allowedhtml=toegestane HTML + +/talkpost.bml.error.cannotreplynopost=Het is niet mogelijk een niet-bestaand bericht te beantwoorden + +/talkpost.bml.error.nocommentsjournal=De gebruiker heeft de mogelijkheid reacties achter te laten in zijn/haar journaal uitgeschakeld + +/talkpost.bml.error.nocommentspost=De gebruiker heeft de mogelijkheid een reactie achter te laten bij dit bericht uitgeschakeld. + +/talkpost.bml.error.noreplypost=Te beantwoorden bericht niet gevonden (verwijderd?) + +/talkpost.bml.error.noreply_deleted=Deze reactie is verwijderd. Je kan er niet op antwoorden. + +/talkpost.bml.error.noreply_screened=Deze reactie wordt afgeschermd en je hebt geen rechten het te kunnen lezen of erop te reageren. + +/talkpost.bml.label.picturetouse=Gebruikersplaatje dat je wilt gebruiken: + +/talkpost.bml.loganonip=Let op! Deze gebruiker heeft de optie ingeschakeld IP adressen van anonieme berichtenplaatsers bij te houden. + +/talkpost.bml.loginq=Inloggen? + +/talkpost.bml.logyourip=Let op! De gebruiker heeft de optie ingeschakeld dat je IP adres bijhoudt wanneer je een bericht achterlaat. + +/talkpost.bml.nosubjecthtml=Geen HTML toegestaan in het onderwerp + +/talkpost.bml.opt.anonymous=Anoniem + +/talkpost.bml.opt.defpic=(standaard) + +/talkpost.bml.opt.friendsonly=- de gebruiker heeft de antwoordmogelijkheid voor anonieme en niet-vrienden gebruikers uitgeschakeld. Je kunt hier berichten achterlaten wanneer [[username]] je opneemt in zijn/haar vriendenlijst."; + +/talkpost.bml.opt.from=Van: + +/talkpost.bml.opt.ljuser=LiveJournal gebruiker: + +/talkpost.bml.opt.loggedin=Ingelogd als gebruiker: [[username]] + +/talkpost.bml.opt.message=Bericht: + +/talkpost.bml.opt.noanonpost=- deze gebruiker heeft de mogelijk anoniem te reageren, uitgeschakeld. + +/talkpost.bml.opt.noautoformat=Niet automatisch opmaken: + +/talkpost.bml.opt.noimage=Geen plaatje + +/talkpost.bml.opt.preview=Bekijk voorbeeld + +/talkpost.bml.opt.spellcheck=Controleer spelling voor het plaatsen (op dit moment altijd met Engels woordenboek) + +/talkpost.bml.opt.subject=Onderwerp: + +/talkpost.bml.opt.submit=Reageer op dit bericht + +/talkpost.bml.opt.willscreen=(zal afgeschermd worden) + +/talkpost.bml.opt.willscreenfriend=(zal afgeschermd worden als het geen vriend is) + +/talkpost.bml.paraformat=Paragrafen worden automatisch gestandariseerd. + +/talkpost.bml.postresponse=Reageer naar aanleiding van bericht: + +/talkpost.bml.title=Reageer op dit bericht + +/talkpost.bml.usermismatch<< +Je hebt een gebruikersnaam ingegeven, maar je hebt de optie "LiveJournal gebruiker" niet geselecteerd. + +Maak aub het gebruikersnaam vak leeg of selecteer de "LiveJournal gebruiker" optie en probeer opnieuw. +. + +/talkpost.bml.warnscreened=Let op: Deze reactie is afgeshermd. Wanneer je erop reageert wordt het automatisch weer zichtbaar. + +/talkpost_do.bml.error.badpassword=Password niet juist voor deze gebruiker. Je kunt je password opnieuw hier herstellen voor het geval je het vergeten bent. + +/talkpost_do.bml.error.badusername=De LiveJournal gebruikersnaam die je ingevuld hebt, bestaat niet. Je kunt hier je gebruikersnaam herstellen wanneer je hem vergeten bent, of je kunt anoniem een bericht achterlaten. + +/talkpost_do.bml.error.banned=Je bent niet gemachtigd te reageren op berichten in dit dagboek. + +/talkpost_do.bml.error.blankmessage=Het bericht was leeg. + +/talkpost_do.bml.error.confused_identity=Je hebt een gebruikersnaam ingevuld, maar selecteerde de optie anoniem te reageren of als huidig ingelogde gebruiker. Ga terug en kies hoe je werkelijk wilt reageren. + +/talkpost_do.bml.error.deleted=Het dagboek is verwijderd. Je kan geen berichten plaatsen. + +/talkpost_do.bml.error.friendsonly=Alleen vrienden van [[user]] kunnen reacties achterlaten in dit dagboek. + +/talkpost_do.bml.error.lostcookie=Het lijkt erop dat je login cookie verdwenen is? + +/talkpost_do.bml.error.manybytes=Helaas, maar je reactie op [[current]] overtreft het maximaal aantal bytes van [[limit]]. Ga terug, verkort je bericht, en probeer het opnieuw te plaatsen. + +/talkpost_do.bml.error.manychars=Helaas, maar je reactie op [[current]] overtreft het maximaal aantal karakters van [[limit]]. Ga terug, verkort je bericht, en probeer het opnieuw te plaatsen. + +/talkpost_do.bml.error.mustlogin=Je moet ofwel zijn ingelogd, ofwel een gebruikersnaam en password invoeren voor je kunt reageren op dit beveiligde bericht. + +/talkpost_do.bml.error.noanon=Het is niet mogelijk anoniem te reageren in dit dagboek. + +/talkpost_do.bml.error.noauth=Je bent niet gemachtigd te reageren op dit beschermde bericht. + +/talkpost_do.bml.error.nocomments=Gebruiker heeft de mogelijkheid te reageren op dit bericht uitgeschakeld. + +/talkpost_do.bml.error.noparent=Je kunt niet reageren op een onbestaande reactie. + +/talkpost_do.bml.error.notafriend=Helaas, [[user]] heeft jou niet op zijn/haar vriendenlijst staan, en heeft de optie "Alleen voor vrienden" ingeschakeld waardoor alleen vrienden kunnen reageren in zijn/haar dagboek.. + +/talkpost_do.bml.error.nousername=Je hebt geen LiveJournal gebruikersnaam ingevuld. Je kunt ervoor kiezen anoniem een bericht achter te laten wanneer je niet beschikt over een LiveJournal gebruikersaccount. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Helaas, je bent niet gemachtigd te reageren op andermans dagboek totdat je e-mailadres is gevalideert. Wanneer je de e-mail waarmee je je e-mailadres kunt confirmeren bent kwijt geraakt, kun je deze nogmaals laten zenden vanaf de Verloren informatie pagina. + +/talkpost_do.bml.error.postshared=Het is niet mogelijk een bericht te plaatsen via een gedeelt- of groepsaccount. Gedeelde accounts representeren meerdere mensen als groep, geen individuelen. + +/talkpost_do.bml.error.screened=Je heb niet genoeg rechten om te reageren op deze afgeschermde reactie. + +/talkpost_do.bml.error.suspended=Je dagboek is geschorst. Je kunt geen berichten plaatsen. + +/talkpost_do.bml.error.testacct=Test accounts kunnen alleen gebruikt worden in test account dagboeken. + +/talkpost_do.bml.opt.preview=Voorbeeld + +/talkpost_do.bml.preview=Zo zal je bericht er uit zien. Met het formulier hieronder kan je je bericht bewerken, of het opslagen zoals het nu is. + +/talkpost_do.bml.preview.subject=Onderwerp: + +/talkpost_do.bml.preview.submit=Bewaren + +/talkpost_do.bml.preview.title=Voorbeeld bekijken + +/talkpost_do.bml.success.loggedin=Je bent nu ingelogd. + +/talkpost_do.bml.success.message=Je reactie is opgeslagen. Je kunt ze hier bekijken. + +/talkpost_do.bml.success.screened.comm=Uw reactie werd toegevoegd. In overeenstemming met de instellingen van deze groep, werd ze afgeschermd. Ze zal alleen zichtbaar zijn voor u en de moderatoren totdat die ervoor kiezen om voor deze reactie de afscherming op te heffen. U kan uw reactie hier bekijken. + +/talkpost_do.bml.success.screened.user=Uw reactie werd toegevoegd. In overeenstemming met de instellingen van dit dagboek, werd ze afgeschermd. Ze zal alleen zichtbaar zijn voor u en de eigenaar van het dagboek totdat die ervoor kiest om voor deze reactie de afscherming op te heffen. U kan uw reactie hier bekijken. + +/talkpost_do.bml.success.title=Gelukt + +/talkpost_do.bml.success.unscreened=Let op, de afgeschermde reactie waar je zojuist op hebt gereageerd is nu weer zichtbaar voor iedereen. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Reageer op dit bericht + +/talkread.bml.anonuser=(Anoniem) + +/talkread.bml.confirm.action=Ben je zeker dat je de geselecteerde reactie wil verwijderen? + +/talkread.bml.deletedpost=(Verwijderd bericht) + +/talkread.bml.deleteduser=(Verwijderde gebruiker: [[username]]) + +/talkread.bml.fromip=(van [[ip]]) + +/talkread.bml.noreplies=Geen reacties + +/talkread.bml.nosubject=(geen onderwerp) + +/talkread.bml.replysuspended=(Reactie van een geschorste gebruiker) + +/talkread.bml.screenedpost=(Afgeschermd bericht) + +/talkread.bml.select=Selecteer + +/talkread.bml.subjectdeleted=[verwijderd] + +/talkread.bml.talkmulti.delete=Verwijderen + +/talkread.bml.talkmulti.des=Gezamelijke actie op de geselecteerde reacties: + +/talkread.bml.talkmulti.screen=Afschermen + +/talkread.bml.talkmulti.submit=Voer actie uit + +/talkread.bml.talkmulti.unscreen=Afscherming ongedaan maken + +/talkread.bml.title=Lees reacties + +/talkscreen.bml.error.login=Je moet ingelogd zijn om met afgeschermde reacties te werken. + +/talkscreen.bml.error.privs.screen=Je hebt niet het recht om deze reactie af te schermen. + +/talkscreen.bml.error.privs.unscreen=Je hebt niet het recht om de afscherming van deze reactie ongedaan te maken. + +/talkscreen.bml.screen.doit=Ja, scherm deze reactie af. + +/talkscreen.bml.screen.sure.body=Bent u zeker dat u deze reactie wil afschermen? + +/talkscreen.bml.screen.sure.title=Deze reactie afschermen? + +/talkscreen.bml.screened.body|staleness=1 +/talkscreen.bml.screened.body=De reactie werd afgeschermd. + +/talkscreen.bml.screened.title=Gelukt + +/talkscreen.bml.title=Afgeschermde reactie + +/talkscreen.bml.unscreen.doit=Ja, maak de afscherming van deze reactie ongedaan. + +/talkscreen.bml.unscreen.sure.body=Bent u zeker dat u de afscherming van deze reactie ongedaan wilt maken? + +/talkscreen.bml.unscreen.sure.title=Afscherming van deze reactie ongedaan maken? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=De afscherming van deze reactie werd ongedaan gemaakt. + +/talkscreen.bml.unscreened.title=Gelukt + +/tools/emailmanage.bml.address.current.title=Huidig adres + +/tools/emailmanage.bml.address.old.text=Dit is een lijst van e-mail adressen die ooit met je account gebruikt zijn geweest, en het moment waarop ze werden gedesactiveerd als primair email adres. Vink degene aan die u wil verwijderen. + +/tools/emailmanage.bml.address.old.title=Vorig adres + +/tools/emailmanage.bml.delete_selected=Verwijder de geselecteerde. + +/tools/emailmanage.bml.log.deleted.title=Veranderingen opgeslagen + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Je lijst van herinneringen is aangepast. + +/tools/memadd.bml.body.added.header=Gelukt + +/tools/memadd.bml.description=Omschrijving: + +/tools/memadd.bml.description.text<< +Geef dit bericht een beschrijving om het aan te herkennen. Om dit bericht uit uw lijst herinneringen te verwijderen, geef een lege beschrijving. + +. + +/tools/memadd.bml.error.deleted.body=Het bericht dat beschreven was als "[[desc]]" is uit je lijst van herinneringswaardige berichten verwijderd. + +/tools/memadd.bml.error.deleted.title=Herinnering verwijderd + +/tools/memadd.bml.error.entry_deleted=Dit dagboek bestaat niet meer. Herinnering is verwijderd. + +/tools/memadd.bml.error.fivekeywords=Je kunt maximaal 5 trefwoorden/catagorieën aangeven per herinnering. + +/tools/memadd.bml.error.invalid_security=Foute of ontbrekende beveiligingsoptie. + +/tools/memadd.bml.error.login=Je moet zijn ingelogd wil je van deze mogelijkheid gebruikmaken. Login en je komt vanzelf op deze pagina terug. + +/tools/memadd.bml.error.maxsize=Dit trefwoord overschrijdt de maximale grootte: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Om een bericht aan uw lijst van herinneringen toe te voegen, moet u een beschrijving opgeven. +Om een herinnering te verwijderen, can u die bewerken en de beschrijving verwijderen, maar u had dit bericht nog niet in uw herinneringen staan. +. + +/tools/memadd.bml.error.nodescription.title=Geen omschrijving + +/tools/memadd.bml.form.submit=Invoeren + +/tools/memadd.bml.keywords=Sleutelwoorden + +/tools/memadd.bml.keywords.example=Voorbeel: Grappig, romantisch + +/tools/memadd.bml.keywords.select=Of je kunt één of meerdere trefwoorden kiezen die je al eerder hebt gebruikt. + +/tools/memadd.bml.keywords.text=Waarom wil je je dit bericht herinneren? Vul maximum 5 trefwoorden of catagorieën in gescheiden door kommas, om deze herinnering later gemakkelijk terug te vinden. + +/tools/memadd.bml.login.enterinfo=Vul de gebruikersnaam en het paswoord in van de account waarin u de herinnering wil bewaren. + +/tools/memadd.bml.login.forgot.header=Iets vergeten? + +/tools/memadd.bml.login.forgot.recover=Als u uw gebruikersnaam of paswoord vergeten bent, vind ze hier terug. + +/tools/memadd.bml.multiple_selections=Houd de "control" toets ingedrukt terwijl je de trefwoorden aan het selecteren bent, om meer dan één sleutelwoord te selecteren. + +/tools/memadd.bml.security.friendsonly=Alleen voor vrienden + +/tools/memadd.bml.security.private=Privé + +/tools/memadd.bml.security.public=Publiek + +/tools/memadd.bml.title=Aan Herinneringen toevoegen + +/tools/memadd.bml.title.added=Toegevoegd + +/tools/memadd.bml.title.deleted=Verwijderd + +/tools/memadd.bml.title.edit_memory=Pas deze herinnering aan + +/tools/memadd.bml.whocansee<< +Wie kunnen zien dat jij dit bericht wilt herinneren? +Iedereen, alleen de gebruikers op je vrienden lijst, of alleen jijzelf? +. + +/tools/memories.bml.back=Terug + +/tools/memories.bml.body.keyword<< + + +[[user]]
          als herinnering heeft opgeslagen. p?> +. + +/tools/memories.bml.body.list_categories<< + + + +[[user]]
          berichten ter herinnering heeft opgeslagen. p?> +. + +/tools/memories.bml.body.memorable=Dit is een lijst van berichten zonder categorie die gebruiker [[user]] herinneringswaardig vond. + +/tools/memories.bml.edit=Aanpassen + +/tools/memories.bml.error.noentries.body<< +Dit is mogelijk wanneer:
            +
          1. de gebruiker geen berichten ter herinnering heeft opgeslagen,
          2. +
          3. de gebruiker de ter herinnering opgeslagen berichten beschermd heeft opgeslagen en jij hiertoe geen toegang hebt, of
          4. +
          5. de gebruiker geen berichten ter herinnering heeft opgeslagen onder sleutelwoorden die passen binnen je zoekcriterium.
          +. + +/tools/memories.bml.error.noentries.title=Geen herinneringen gevonden. + +/tools/memories.bml.filter.all=Alle herinneringen + +/tools/memories.bml.filter.other=Alleen andere berichten + +/tools/memories.bml.filter.own=Enkel '[[user]]' berichten + +/tools/memories.bml.form.switch=Wissel + +/tools/memories.bml.title.keyword=Herinneringswaardige [[keyword]] berichten + +/tools/memories.bml.title.memorable=Herinneringswaardige berichten + +/tools/memories.bml.uncategorized=Zonder categorie + +/update.bml.altpost=Dagboek om dit in te plaatsen: + +/update.bml.btn.update=Plaats bericht + +/update.bml.currmood=Huidige stemming: + +/update.bml.currmusic=Huidige muziek: + +/update.bml.date=Datum: + +/update.bml.default=standaard + +/update.bml.defaultjournal=([[user]]) -- standaard + +/update.bml.error.login=Fout bij het inloggen: + +/update.bml.error.update=Fout bij het plaatsen in uw dagboek: + +/update.bml.event=Gebeurtenis: + +/update.bml.full=Volledige Aanpassingspagina + +/update.bml.localtime=Lokale tijd: + +/update.bml.loggingin=Inloggen op de server... + +/update.bml.noneother=Geen, of andere: + +/update.bml.note|staleness=1 +/update.bml.note=Let op: De tijd hoerboven is die van onze server. Corrigeer deze naar uw tijdszone voor u het bericht plaatst. + +/update.bml.opt.backdate=Het bericht pre-dateren: + +/update.bml.opt.backdate.about=zal niet in vriendenpagina verschijnen + +/update.bml.opt.defpic=(standaard) + +/update.bml.opt.nocomments=Laat geen commentaar toe: + +/update.bml.opt.noemail=Stuur commentaar niet op via E-mail: + +/update.bml.opt.noformat=Niet automatisch opmaken: + +/update.bml.opt.spellcheck=Controleer spelling voor het plaatsen (op dit moment altijd met Engels woordenboek) + +/update.bml.options=Optionele instellingen + +/update.bml.other=Andere: + +/update.bml.picture=Icoon te gebruiken: + +/update.bml.security.custom=Aangepast... + +/update.bml.security.friends=Vrienden + +/update.bml.security.head=Beveiligingsniveau: + +/update.bml.security.private=Privé + +/update.bml.security.public=Publiek + +/update.bml.servermsg=Verder heeft de server nog een bericht voor u: + +/update.bml.simple=Dit is de eenvoudige pagina. Voor meer opties, klik hier. + +/update.bml.spellchecked=Uw bericht op spelling gecontroleerd: + +/update.bml.subject|staleness=1 +/update.bml.subject=Onderwerp: (optioneel, voor gebruik bij langere berichten) + +/update.bml.timeformat=24 uurs tijd + +/update.bml.title=Nieuw Bericht + +/update.bml.title.readonly=Enkel-lezen modus + +/update.bml.update.head=Plaats een nieuw bericht + +/update.bml.update.success=Nieuw bericht geplaatst. Je kan je aangepast dagboek hier bekijken. + +/update.bml.updating=Bericht aan het plaatsen... + +/userinfo.bml.about.comm=Over: + +/userinfo.bml.about.user=Biografie: + +/userinfo.bml.body.leave= U kan eender wanneer de groep verlaten. + +/userinfo.bml.comminfo.body=Hier is de informatie over de "[[commname]]" groep op LiveJournal. + +/userinfo.bml.comminfo.name=Groepsinformatie + +/userinfo.bml.date.never=Nooit. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Fout gevormde gebruikersnaam. + +/userinfo.bml.error.notloggedin=Als je je eigen profiel wil bekijken, moet je inloggen. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Bekeken door: + +/userinfo.bml.friendof.hidden=(verborgen) + +/userinfo.bml.friendof.syndreadcount=Aantal Lezers + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Vriend van: + +/userinfo.bml.friends.comm=Leden + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Vrienden + +/userinfo.bml.label.addbuddy=Voeg Buddy toe + +/userinfo.bml.label.adduser=Voeg gebruiker toe + +/userinfo.bml.label.birthdate=Geboortedatum: + +/userinfo.bml.label.clientsused=Clients gebruikt: + +/userinfo.bml.label.comments=Commentaren: + +/userinfo.bml.label.composted=Geplaatst: [[num]] - + +/userinfo.bml.label.comreceived= Ontvangen: [[num]] + +/userinfo.bml.label.datecreated=Aangemaakt op: + +/userinfo.bml.label.dateupdated=Geupdate op: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.interests=Interesses + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] interesses niet getoond + +/userinfo.bml.label.journalentrs=Dagboek berichten: + +/userinfo.bml.label.location=Plaats: + +/userinfo.bml.label.memberof=Lid van + +/userinfo.bml.label.memories=Herinneringen: + +/userinfo.bml.label.moredetails=(meer details...) + +/userinfo.bml.label.msnusername=MSN gebruikersnaam: + +/userinfo.bml.label.name=Naam: + +/userinfo.bml.label.nofriends=Geen opgegeven. + +/userinfo.bml.label.reqfinduser=Alleen gebruikers met een 'finduser'priv kunnen gebruikers opzoeken via hun userid. + +/userinfo.bml.label.sendmessage=Stuur bericht + +/userinfo.bml.label.shared=Berichten plaatsen: + +/userinfo.bml.label.supportpoints=Hulp punten: + +/userinfo.bml.label.textmessage=Text
          bericht
          : + +/userinfo.bml.label.todo=To-Do Lijst + +/userinfo.bml.label.user=Gebruiker: + +/userinfo.bml.label.viewfriends=Bekijk vrienden + +/userinfo.bml.label.viewmembers=Bekijk leden + +/userinfo.bml.membership.body=Om lid te worden van deze groep, klik hier. + +/userinfo.bml.memories.entries=[[count]] berichten + +/userinfo.bml.memories.entry=[[count]] bericht + +/userinfo.bml.monitor.comm=Volg groep + +/userinfo.bml.monitor.user=Voeg deze gebruiker toe aan je vrienden lijst. + +/userinfo.bml.nonexist.body=De gebruikersnaam [[user]] is op dit moment niet geregistreerd. + +/userinfo.bml.nonexist.name=Unbekende gebruiker + +/userinfo.bml.sendmessage.body=Stuur [[user]] een text berichtje
          op zijn/haar gsm/pager. + +/userinfo.bml.syn.last.never=Nooit + +/userinfo.bml.syn.lastcheck=Laatst gecontroleerd: + +/userinfo.bml.syn.nextcheck=Volgende controle: + +/userinfo.bml.syn.parseerror=Foutboodschap: + +/userinfo.bml.tellafriend=Vertel het aan een Vriend! + +/userinfo.bml.timeupdate.dayago=1 dag geleden + +/userinfo.bml.timeupdate.daysago=[[num]] dagen geleden + +/userinfo.bml.timeupdate.hourago=1 uur geleden + +/userinfo.bml.timeupdate.hoursago=[[num]] uren geleden + +/userinfo.bml.timeupdate.minuteago=1 minuut geleden + +/userinfo.bml.timeupdate.minutesago=[[num]] minuten geleden + +/userinfo.bml.timeupdate.secondago=1 seconde geleden + +/userinfo.bml.timeupdate.secondsago=[[num]] seconden geleden + +/userinfo.bml.timeupdate.weekago=1 week geleden + +/userinfo.bml.timeupdate.weeksago=[[num]] weken geleden + +/userinfo.bml.title=Gebruikersinfo + +/userinfo.bml.title.communityinfo=Groepsinfo + +/userinfo.bml.userinfo.body=Hier is de gebruikersinformatie voor [[username]]. Als u deze gebruiker bent, kan u deze informatie aanpassen (of kiezen wat publiek is) op de Gebruikersinfo pagina. + +/userinfo.bml.userinfo.name=Gebruikersinformatie + +BML.parse_multipart.toolarge=Upload te groot | Upload too large + +BML.parse_multipart.unknowntype=Onbekende inhoud | Unknown content type + +btn.search=Zoeken + +date.day.friday.long=Vrijdag + +date.day.friday.short=Vr + +date.day.monday.long=Maandag + +date.day.monday.short=Ma + +date.day.saturday.long=Zaterdag + +date.day.saturday.short=Za + +date.day.sunday.long=Zondag + +date.day.sunday.short=Zo + +date.day.thursday.long=Donderdag + +date.day.thursday.short=Do + +date.day.tuesday.long=Dinsdag + +date.day.tuesday.short=Di + +date.day.wednesday.long=Woensdag + +date.day.wednesday.short=Wo + +date.month.august.long=Augustus + +date.month.february.long=Februari + +date.month.january.long=Januari + +date.month.july.long=Juli + +date.month.june.long=Juni + +date.month.march.long=Maart + +date.month.march.short=Mrt + +date.month.may.long=Mei + +date.month.may.short=Mei + +date.month.october.long=Oktober + +date.month.october.short=Okt + +dystopia.btn.login=INLOGGEN + +dystopia.hello_anonymous=Welkom op LiveJournal! + +dystopia.hello_loggedin=Hallo, [[username]]! + +dystopia.nav.createjournal=Open een dagboek + +dystopia.nav.developer=Ontwikkel Gebied + +dystopia.nav.editentries=Pas bericht aan + +dystopia.nav.editfriends=Vrienden + +dystopia.nav.editpassword=Wachtwoord + +dystopia.nav.editpics=Plaatjes + +dystopia.nav.editstyle=Verander je stijl + +dystopia.nav.findcomm=Op groep + +dystopia.nav.finddir=Ledenbestand doorzoeken + +dystopia.nav.findint=Op interesse + +dystopia.nav.findrandom=Willekeurig + +dystopia.nav.findregion=Op regio + +dystopia.nav.home=Start + +dystopia.nav.journalcalendar=Kalender + +dystopia.nav.journalfriends=Vrienden + +dystopia.nav.journalinfo=Gebruikersinfo + +dystopia.nav.journalrecent=Recent + +dystopia.nav.legalprivacy=Privacy + +dystopia.nav.legaltos=Wat biedt onze service + +dystopia.nav.login=Inloggen + +dystopia.nav.logout=Uitloggen + +dystopia.nav.lostinfo=Wachtwoord vergeten + +dystopia.nav.memories=Herinneringen + +dystopia.nav.modifyjournal=Pas dagboek aan + +dystopia.nav.news=Nieuws + +dystopia.nav.paidaccts=Betaalde accounts + +dystopia.nav.personalinfo=Persoonlijke info + +dystopia.nav.sitemap=Kaart van de Site + +dystopia.nav.support=Heb je een vraag? + +dystopia.nav.updatejournal=Nieuw bericht + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=128 + +dystopia.navhead.findusers=Zoek gebruikers + +dystopia.navhead.help=Hulp & Ondersteuning + +dystopia.navhead.journal=Jouw dagboek + +dystopia.navhead.legal=Legaal + +dystopia.navhead.settings=Instellingen + +dystopia.navhead.welcome=Welkom! + +dystopia.search.icq=ICQ nummer + +dystopia.search.int=Interesse + +dystopia.search.msn=MSN gebruikersnaam + +dystopia.search.region=Regio + +dystopia.searchlj=Zoek op Livejournal naar: + +Email=E-mail + +email.newacct.body<< +Proficiat, je hebt een nieuwe LiveJournal account! + +Om het aanmaken van je dagboek te voltooien en je e-mailadres te verifiëren, ga naar hier: + + [[regurl]] + +Je dagboek vind je op deze URL: + + [[siteroot]]/users/[[username]]/ + +en ook: + + [[siteroot]]/~[[username]]/ + +Hieronder vind je je LiveJournal gebruikersnaam en paswoord: + + Username: [[username]] + Password: [[password]] + +Je kan naar [[siteroot]]/ gaan om in te loggen met je account, nieuwe berichten in je dagboek te plaatsen, en je dagboek opties aan te passen, maar we raden aan een LiveJournal client te downloaden. Dat is de gemakkelijkste manier om nieuwe berichten in je dagboek te plaatsen, en er zijn clients beschikbaar voor vele platformen! Je vindt ze op: + + [[siteroot]]/download/ + +Beginnen op LiveJournal kan een beetje moeilijk zijn als je er niemand kent. Breng een bezoekje aan http://newbies.livejournal.com voor slim en behulpzaam advies... met een beetje geluk ben je in geen tijd een LiveJournal pro! + +We hopen dat je LiveJournal net zo leuk vindt als wij het vinden om het voor je te maken. Als je vragen hebt over het gebruik van LiveJournal, ga dan naar de hulp en ondersteuningspagina's op: + + [[siteroot]]/support/ + +Daar vind je het antwoord op bijna elke mogelijke vraag over LiveJournal. + +Ons doel is LiveJournal absoluut fantastisch te maken... als er iets is dat we kunnen doen om het eenvoudiger, krachtiger, aanpasbaarder, of hoe dan ook beter te maken, laat het ons weten! We maken deze site niet om er geld aan te verdienen. We zijn geen dot-com bedrijf gestart met risico-kapitaal dat zo snel mogelijk op de beurs wil... deze site wordt gemaakt door alle mensen die hem gebruiken. Laat ons weten wat je ervan wil maken. + +Als je vragen hebt, kan ons ondersteuningsteam je meestal binnen de 24 uur een antwoord geven. + +Veel plezier ermee! + +[[sitename]] Team +[[siteroot]]/ +. + +email.newacct.subject=Welcome bij LiveJournal + +error.badpassword=Foutief password. + +error.dberror=Er was een database fout: + +error.deleted.name=Verwijderd + +error.deleted.text=Dit dagboek is verwijderd. Als u [[user]] bent, heeft u 30 dagen vanaf het moment van verwijderen om de verwijdering ongedaan te maken. Na 30 dagen zullen we alle inhoud permanent verwijderen van onze servers. + +error.deleted.title=Verwijderde account + +error.ipbanned=Uw IP adres is tijdelijk van de site verbannen wegens het overschrijden van het maximum aantal mislukte logins. + +error.malformeduser=Fout gevormde gebruikersnaam. + +error.nobutton=Niet op een knop geduwd? + +error.nodb=De database is tijdelijk buiten gebruik. + +error.nodbmaintenance=Dit gedeelte van de database is tijdelijk niet beschikbaar in verband met onderhoud. Probeer het over enkele minuten nogmaals. + +error.noentry=Dit bericht bestaat niet. + +error.nojournal=Onbekend dagboek + +error.noremote=Je moet inloggen om deze pagina te gebruiken. + +error.procrequest=Er was een fout bij het verwerken van uw aanvraag: + +error.purged.name=Verwijderd + +error.purged.text=Dit dagboek is verwijderd en uitgeveegd. + +error.purged.title=Uitgeveegde account + +error.suspended.name=Geschorst + +error.suspended.text=Deze account is tijdelijk of permanent geschorst. Als jij [[user]] bent, kijk dan naar de FAQ getiteld Mijn account is geschorst! Hoe krijg ik die terug? voor meer informatie. Merk op dat om de privacy van onze gebruikers te beschermen, [[sitename]] de redenen voor eender welke schorsing enkel kan bespreken met de eigenaar van de account. + +error.suspended.title=Geschorste account + +error.tempdisabled=Dit is tijdelijk uitgeschakeld. + +error.unknownmode=onbekende modus. + +error.usernameinvalid=De gebrukersnaam bevat foutieve karakters + +error.usernamelong=De gebruikersnaam is te lang, het mag maximaal 15 karakters bevatten. + +error.username_notfound=Gebruikersnaam niet gevonden + +Help=Hulp + +label.security.custom=Aangepast... + +label.security.friends=Vrienden + +label.security.head=Beveiligingsniveau: + +label.security.private=Privé + +label.security.public=Publiek + +label.switch.button=Wisselen + +label.switch.header=Verwissel van dagboek + +label.switch.workwith=Werk met dagboek: + +langname.be=Wit-russisch + +langname.da=Deens + +langname.de=Duits + +langname.en=Engels + +langname.en_GB=Engels (UK) + +langname.en_LJ=Engels (LJ) + +langname.es=Spaans + +langname.et=Ests + +langname.fi=Fins + +langname.fr=Frans + +langname.ga=Iers + +langname.gd=Keltisch + +langname.he=Hebreeuws + +langname.hu=Hongaars + +langname.is=Ijslands + +langname.it=Italiaans + +langname.ja=Japans + +langname.la=Latijn + +langname.lv=Lets + +langname.ms=Maleisisch + +langname.nb=Noors Bokmål + +langname.nl=Nederlands + +langname.nn=Noors Nynorsk + +langname.pl=Pools + +langname.pt=Portugees + +langname.ru=Russisch + +langname.sv=Zweeds + +langname.tr=Turks + +langname.zh=Chinees (vereenvoudigd) + +ljlib.pageofpages=Pagina [[page]] van [[total]] + +lostinfo.head=Iets vergeten? + +lostinfo.text=Als u uw gebruikersnaam of paswoord vergeten bent, vind ze hier terug. + +Password=Wachtwoord + +password.max30=Paswoorden mogen niet langer zijn dan 30 karakters. + +portal.bdays.count.des=Standaard worden de 5 vrienden met de eerstkomende verjaardagen getoond. + +portal.bdays.count.name=Verjaardagen te tonen + +portal.bdays.portalname=Verjaardagen + +portal.bdays.portaltitle=Verjaardagen + +portal.goat.name=Site mascotte + +portal.goattext.des=Wat wil je dat je geit zegt? Het enige wat geiten echt menen is 'Mèèèèèèh', maar je kan doen alsof je geit iets anders zegt als je dat echt wil. + +portal.goattext.name=Geit tekst + +portal.login.portalname=Inlog vak + +portal.memories.entriesnoun=berichten + +portal.memories.entrynoun=bericht + +portal.memories.portalname=Herinneringswaardige berichten + +portal.memories.portaltitle=Herinneringswaardige berichten + +portal.ministats.active=Actief: + +portal.ministats.title=Gebruikersstatistieken + +portal.ministats.total=Totaal: + +portal.misbehaved.des=Je wou dit echt niet aanzetten. Geiten die niet zindelijk zijn brengen alleen maar problemen met zich mee. + +portal.misbehaved.name=Geit met slecht gedrag + +portal.popfaq.portalname=10 meestbekeken FAQs + +portal.popfaq.portaltitle=10 meestbekeken FAQs + +portal.randuser.count.des=Standaard wordt 1 willekeurige gebruiker getoond, maar je kan er tot 10 vertikaal in de smalle kolommen hebben of 5 horizontaal in een brede kolom. + +portal.randuser.count.name=Aantal willekeurige gebruikers te tonen + +portal.randuser.error.tableempty=Er zijn geen willekeurige gebruikers. Contacteer de admin. + +portal.randuser.hidename.des=Standaard wordt de willekeurige gebruikersnaam getoond. Vink dit vakje aan om die te verwijderen. + +portal.randuser.hidename.name=Verberg naam + +portal.randuser.hidepic.des=Standaard wordt het willekeurige gebruikersplaatje getoond, als er een is. Vink dit aan om het te verwijderen. + +portal.randuser.hidepic.name=Verberg gebruikersplaatje + +portal.randuser.portalname=Willekeurige gebruiker + +portal.randuser.portaltitle=Willekeurige gebruiker + +portal.randuser.portaltitleplural=Willekeurige gebruiker + +portal.recent.error.noentries=Sorry. Geen berichten. + +portal.recent.error.notsetup=Je moet dit vak nog configureren. Klik op het plus symbool om het dagboek dat je hier wil bekijken in te stellen. + +portal.recent.error.userstatus=Gebruiker heeft zijn/haar account verwijderd of opgeschort. + +portal.recent.items.description=Standaard wordt enkel het meest recente bericht getoond. + +portal.recent.items.name=Aantal berichten te tonen + +portal.recent.journal.description=Van welk dagboek wil je de recente berichte zien? + +portal.recent.journal.name=Dagboek + +portal.recent.nosubject=(Geen onderwerp) + +portal.recent.portaltitle=Recente berichten vak + +portal.recent.showtext.description=Standaard worden enkel de onderwerpen getoond + +portal.recent.showtext.name=Toon ook tekst + +portal.stats.journalentyest=Dagboek berichten gisteren + +portal.stats.portalname=Site statistieken + +portal.stats.portaltitle=Statistieken + +portal.stats.totalusers=Tatool aantal gebruikers + +portal.update.mode.des=Volledige mode geeft je een hoop extra opties ... zoals berichten plaatsen in groepen en je huidige stemming, muziek en gebruikersplaatje instellen. Eenvoudige mode is leuker als je die mogelijkheden niet gebruikt en ze dus liever niet ziet. + +portal.update.mode.full=Volledig + +portal.update.mode.simple=Eenvoudig + +portal.update.portalname=Nieuw bericht + +portal.update.portaltitle=Plaats een nieuw bericht + +protocol.bad_password=Het gekozen password is te makkelijk. We raden je aan je password te veranderen. Doe je dit niet dan loop je het risico dat je dagboek gekraakt wordt. Ga naar[[siteroot]]/changepassword.bml om je password te veranderen. + +protocol.hello_test=Hallo Test Account! + +protocol.mail_bouncing=Op dit moment gebruik je een foutief e-mailadres. Alle e-mail die naar dit adres verstuurd wordt, bounced en komt retour. [[sitename]] werkt alleen als je gebruik maakt van een werkend e-mailadres. Ga naar [[siteroot]]/support/faqbrowse.bml?faqid=19 om te lezen hoe je je e-mailadres kan veranderen. + +protocol.must_revalidate=Je moet je nieuwe e-mailadres nog valideren. Je oude e-mailadres was in orde, maar omdat je een ander e-mailadres hebt opgegeven, moet je deze eerst nog valideren. Doe je dit niet, dan kun je geen gebruik maken van alle features van [[sitename]]. Ga naar [[siteroot]]/support/faqbrowse.bml?faqid=11 voor meer informatie over e-mailvalidatie. + +protocol.not_validated=Uw email adres werd nog niet gevalideerd. U kan [[sitename]] blijven gebruiken, maar als u uw adres niet valideert, zal u geen toegang hebben tot alle functies van de site. Voor meer informatie, kijk in de instructies die u werden toegestuurd toen u uw dagboek aanmaakte, of bezoek [[siteroot]]/support/faqbrowse.bml?faqid=11 voor meer informatie. + +protocol.old_win32_client=Er zijn inmiddels significant nieuwere Windows Livejournal Clients beschikbaar. We raden je aan je oude versie te upgraden. Ga naar [[siteroot]]/download/ voor meer informatie en om een nieuwere client te downloaden. + +protocol.readonly=Je account staat op dit moment tijdelijk in alleen-lezen mode. Bepaalde handelingen zullen gedurende enkele minuten niet werken. + +talk.anonwrote=Iemand anders schreef, + +talk.anonwrote_comm=Iemand schreef in [[commlink]], + +talk.btn.preview=Bekijk voorbeeld + +talk.commentpost=Laat een bericht achter + +talk.commentsread=Lees berichten + +talk.curname_Mood=stemming: + +talk.curname_Music=muziek: + +talk.error.bogusargs=Verkeerde argumenten + +talk.error.comm_deleted=Deze reactie is verwijderd. + +talk.error.deleted=Dit dagboek is verwijderd. + +talk.error.deleted.title=Verwijderd + +talk.error.mustlogin=Je moet eerst inloggen wil je dit bericht kunnen bekijken. + +talk.error.nocomment=Deze reactie bestaat niet. + +talk.error.noentry=Dit bericht bestaat niet. + +talk.error.nosuchjournal=Dit journaal bestaat niet. + +talk.error.notauthorised=Je bent niet gemachtigd dit beveiligde bericht te bekijken. + +talk.error.suspended=Dit account/deze gebruiker is geschorst. + +talk.error.suspended.title=Geschorst + +talk.parentlink=Kop + +talk.readsimilar=Lees vergelijkbare berichten: + +talk.replytothis=Beantwoord dit bericht + +talk.somebodywrote=[[realname]] ([[userlink]]) schreef, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) schreef in [[commlink]], + +talk.spellcheck=Controleer spelling bij voorbeeld (op dit moment altijd met Engels woordenboek) + +talk.threadlink=Staart + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_nederlands + +Username=Gebruikersnaam + +userpic.inactive=Niet actief + +xcolibur.greeting.anon=Welkom op LiveJournal! + +xcolibur.greeting.logged_in=Welkom, [[name]]! [[logout]] + +xcolibur.login=Inloggen? + +xcolibur.logout=Uitloggen? + +xcolibur.nav.about=Over + +xcolibur.nav.about.general=Algemeen + +xcolibur.nav.about.paidaccounts=Betaalde accounts + +xcolibur.nav.about.press=Pers + +xcolibur.nav.about.sitenews=Site nieuws + +xcolibur.nav.about.stats=Statistieken + +xcolibur.nav.footer.sitemap=Kaart van de Site + +xcolibur.nav.help=Hulp + +xcolibur.nav.help.ask=Stel een vraag + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Paswoord vergeten + +xcolibur.nav.journal=Dagboek + +xcolibur.nav.journal.archive=Archief + +xcolibur.nav.journal.edit.entries=Berichten bewerken + +xcolibur.nav.journal.friends=Vrienden + +xcolibur.nav.journal.memories=Herinneringen + +xcolibur.nav.journal.update=Nieuw bericht + +xcolibur.nav.manage=Aanpassen + +xcolibur.nav.manage.community=Groepen + +xcolibur.nav.manage.customize=Stijl + +xcolibur.nav.manage.entries=Berichten + +xcolibur.nav.manage.friends=Vrienden + +xcolibur.nav.manage.password=Paswoord + +xcolibur.nav.manage.pics=Gebruikersplaatjes + +xcolibur.nav.search=Zoeken + +xcolibur.nav.search.directory=Regio + +xcolibur.nav.search.directory.search=Geavanceerd + +xcolibur.nav.search.interests=Interesse + +xcolibur.nav.search.random=Willekeurig + +xcolibur.nav.title=Navigeer: + +xcolibur.nav.welcome=Welkom + +xcolibur.nav.welcome.create=Een account aanmaken + +xcolibur.nav.welcome.login=Inloggen + +xcolibur.nav.welcome.update=Je dagboek aanpassen + +xcolibur.search=Zoek: + +xcolibur.search.category=Categorie: + +xcolibur.search.icq=ICQ Nummer + +xcolibur.search.int=Interesse + +xcolibur.search.msn=MSN gebruikersnaam + +xcolibur.search.region=Regio + diff --git a/ljcom/bin/upgrading/nn.dat b/ljcom/bin/upgrading/nn.dat new file mode 100644 index 0000000..06c718e --- /dev/null +++ b/ljcom/bin/upgrading/nn.dat @@ -0,0 +1 @@ +;; -*- coding: utf-8 -*- diff --git a/ljcom/bin/upgrading/pl.dat b/ljcom/bin/upgrading/pl.dat new file mode 100644 index 0000000..a1be99d --- /dev/null +++ b/ljcom/bin/upgrading/pl.dat @@ -0,0 +1,4298 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Zmień Status + +/accountstatus.bml.error.nochange.expunged=To konto zostało usuniętę z systemu. + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Nie można zmienić statusu dziennika z zawieszonego. + +/accountstatus.bml.header.success=Sukces + +/accountstatus.bml.journalstatus.about=Jeśli chcesz usunąć lub przywrócić swój dziennik, możesz to zrobić tutaj. Kiedy usuniesz dziennik, masz jeszcze 30 dni na zmianę zdania. Po 30 dniach dziennik zostanie skasowany permanentnie i nie będzie już sposobu na odzyskanie go. + +/accountstatus.bml.journalstatus.head=Status Aktywności Dziennika + +/accountstatus.bml.journalstatus.select.activated=Aktywny + +/accountstatus.bml.journalstatus.select.deleted=Usunięty + +/accountstatus.bml.journalstatus.select.head=Status: + +/accountstatus.bml.journalstatus.select.suspended=Zawieszony + +/accountstatus.bml.message.success=Status Twojego dziennika został pomyślnie zmieniony na [[statusvis]]. + +/accountstatus.bml.title=Status Konta + +/allpics.bml.current=Obecne Obrazki + +/allpics.bml.default=Domyślny + +/allpics.bml.edit2=Może zainteresuje Cię możliwość edycji słów kluczowych Twoich obrazków lub załadowania nowego obrazka. + +/allpics.bml.error.noparam=Brakuje parametru "użytkownik". + +/allpics.bml.keywords=Słowa kluczowe: + +/allpics.bml.nopics.text.other=Ten użytkownik nie załadował żadnych obrazków użytkownika. + +/allpics.bml.nopics.text2=Nie masz załadowanych obrazków. Aby jakiś załadować, wejdź tutaj. + +/allpics.bml.nopics.title=Brak Obrazków + +/allpics.bml.pics=Oto obrazki użytkownika [[user]]. + +/allpics.bml.title=Obrazki Użytkownika + +/approve.bml.comm.success=Sukces + +/approve.bml.comm.text<< +Zostałaś/eś dodana/y do [[comm]]. +Kliknij tutaj, żeby dodać tę grupę do swojej listy przyjaciół. +. + +/approve.bml.error.internerr.invalidaction=Wewnętrzny błąd: nieprawidłowa akcja. + +/approve.bml.error.invalidargument=Podano nieprawidłowy argument. + +/approve.bml.error.unknownactiontype=Nieznany typ operacji + +/approve.bml.shared.success=Sukces + +/birthdays.bml.title=Urodziny + +/changepassword.bml.btn.proceed=Kontynuuj + +/changepassword.bml.changepassword.header=Zmiana Hasła + +/changepassword.bml.changepassword.instructions=Wypełnij poniższy formularz, by zmienić swoje hasło. Jeśli potrzebujesz pomocy przy wyborze dobrego hasła i utrzymaniu bezpieczeństwa konta, przeczytaj to. + +/changepassword.bml.email.body<< +Twoje hasło na [[sitename]] zostało zmienione. + +Aby odzyskać je w przyszłości, wejdź na: + + [[siteroot]]/lostinfo.bml + +Pozdrowienia, +Drużyna [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Zmiana Hasła + +/changepassword.bml.error.badcheck=Niepoprawne nowe hasło: [[error]] + +/changepassword.bml.error.badnewpassword=Twoje nowe hasło i jego powtórzenie nie pasują do siebie. Może zrobiłaś/eś literówkę. Wpisz ponownie hasło i jego powtórzeie. + +/changepassword.bml.error.badoldpassword=Twoje stare hasło nie jest poprawne. + +/changepassword.bml.error.blankpassword=Twoje nowe hasło nie może być puste. + +/changepassword.bml.error.changetestaccount=Nie można zmienić hasła konta testowego. + +/changepassword.bml.error.characterlimit=Hasła są ograniczone do maksymalnie 30 znaków. + +/changepassword.bml.error.invaliduser=Nieprawidłowy użytkownik [[user]]. Taki użytkownik nie istnieje. Czy na pewno wpisałaś/eś nazwę poprawnie? + +/changepassword.bml.error.mustenterusername=Musisz wpisać swoją nazwę użytkownika. + +/changepassword.bml.error.nonascii=Hasła są ograniczone do symboli ASCII. Prosimy, wymyśl hasło, które nie zawiera symboli nie-ASCII. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Nie możesz zmienić hasła, jeśli Twój obecny adres email nie został potwierdzony. + +/changepassword.bml.newpassword=Nowe Hasło: + +/changepassword.bml.newpasswordagain=Nowe Hasło (ponownie): + +/changepassword.bml.oldpassword=Stare Hasło: + +/changepassword.bml.proceed.instructions=Wcziśnij poniższy przycisk, a Twoje hasło zostanie zmienione. Otrzymasz także email informujący o zmianie hasła. + +/changepassword.bml.success.text=Twoje hasło zostało zmienione i został wysłany email przypominający Ci o zmianie hasła. + +/changepassword.bml.title=Zmiana Hasła + +/community/index.bml.main<< + + + + +Pokoju Nowych, gdzie znajdziesz odpowiedzi na wszelkie swoje pytania. Odwiedź , porozglądaj się trochę, a już wkrótce zaczniesz się tu poruszać ze swobodą starego bywalca! +p?> + + +
          +Dodaj do swojej strony przyjaciół, by być poinformowana/y o wszystkich sprawach istotnych dla całej społeczności LiveJournal.
          +Dodaj do swojej strony przyjaciół, by wiedzieć, na kiedy planowane są naprawy strony, i by poznać powody nieplanowanych przerw w serwisie. +p?> + + +AIM, ICQ, Yahoo!, MSN czy Jabber. Jeśli Ty też korzystasz z któregoś z tych komunikatorów, podaj namiary na siebie w swoich ustawieniach danych osobistych. Jesli masz Konto Płatne, możesz też włączyć możliwość odbierania wiadomości tekstowych na swoim telefonie komórkowym lub pagerze. +p?> + + +Konta Płatnego. Jest też, rzecz jasna, masa innych sposobów, w jakie możesz nam pomóc. +

          +LiveJournal to projekt Open Source; jeśli masz doświadczenie z językami programowania lub aplikacjami serwerowymi, możesz zajrzeć do Grupy Rozwoju LiveJournal, . Jeśli masz pomysły, w jaki sposób możnaby ulepszyć LiveJournal, zajrzyj do Obszaru Sugestii LiveJournal, . Jeśli chcesz pomóc w czymkolwiek, odwiedź Grupę Spraw Biznesu LiveJournal, . Jeśli lubisz pomagać ludziom, odwiedź naszą centralę pomocy technicznej i pomóż rozwiązać czyjś problem. Jeśli dobrze radzisz sobie z grafiką, odwiedź Grupę Artystyczną LiveJournal, . +p?> + + +Anime do buddyzmu Zen, od Astronomii po Zim. Znajdziesz też grupy regionalne dla ludzi z różnych miejsc na całym świecie. Bardzo możliwe, że istnieje grupa dla ludzi z Twojego miejsca zamieszkania! +p?> + + +Odpowiedź FAQ, która dokładie wyjaśnia, jak możesz utworzyć swoją własną grupę. Są też dwie Kategorie FAQ (Generalne FAQ Grup i FAQ o Zarządzaniu Grupami), w których znajdziesz w zasadzie wszystkie informacje, których możesz potrzebować w związku z grupami. Jeśli potrzebujesz jeszcze dodatkowych informacji, możesz w tej sprawie zamieścić prośbę o pomoc. +p?> + + + + + + + +Napisz do Jesse Proulx, () szefa Grup. +p?> +. + +/community/index.bml.title=Centrala Grup + +/community/join.bml.button.join=Przyłącz się do Grupy + +/community/join.bml.label.addtofriends=Dodaj "[[maintainer]]" do listy przyjaciół.
          + +/community/join.bml.label.allowposting=Ta grupa umożliwia tworzenie wpisów wszystkim członkom, więc teraz masz dostęp do tej funkcji. Jeśli masz w tej chwili otwartego klienta LiveJournal na swoim komputerze, musisz się z niego wylogować i zalogować jeszcze raz aby ta grupa pojawiła się na liście dzienników, w których możesz zamieszczać wpisy. + +/community/join.bml.label.auth=Chociaż jesteś już na liście członków, ta grupa zezwala na zamieszczanie wpisów tylko autoryzowanym użytkownikom. Skontaktuj się z którymś z zarządzających, jeśli chcesz mieć możliwość zamieszczania wpisów. Poniżej znajduje się lista zarządzających tą grupą: [[admins]] + +/community/join.bml.label.banned=Zarządzający tą grupą zakazał/zakazali Ci przyłączyć się do niej. + +/community/join.bml.label.closed=To jest grupa zamknięta. Jeśli interesuje Cię przyłączenie się do niej, skontaktuj się z jednym z jej zarządzających. Poniżej znajduje się lista zarządzających tą grupą: [[admins]] + +/community/join.bml.label.commlogged=Jesteś zalogowana/y na konto wspólne/grypy, a nie swoje konto osobiste. + +/community/join.bml.label.errorcomminfo=Podane informacje gupy nie są poprawne. + +/community/join.bml.label.expls=Kliknij przycisk poniżej, by dołączyć do grupy "[[maintainer]]". Odznacz kratkę poniżej, jeżeli chcesz dołączyć do grupy, ale nie chcesz widzieć jej wpisów na swojej stronie przyjaćiół. + +/community/join.bml.label.loginfirst=Musisz się zalogować, by dołączyć do grupy. + +/community/join.bml.label.membernow=Należysz teraz do grupy [[commname]] + +/community/join.bml.label.sure=Na pewno? + +/community/join.bml.reqsubmitted.body=Twoje podanie o dołączenie do grupy zostało wysłane do zarządzających: + +/community/join.bml.reqsubmitted.title=Podanie o dołączenie do grupy zostało wysłane + +/community/join.bml.success=Sukces + +/community/join.bml.title=Dołącz do Grupy + +/community/leave.bml.button.leave=Opuść Grupę + +/community/leave.bml.label.buttontoleave=Wciśnij przycisk poniżej aby opuścić grupę "[[commname]]". + +/community/leave.bml.label.infoerror=Wpisane dane grupy nie są poprawne. + +/community/leave.bml.label.logoutfirst=Aby opuścić grupę, musisz się zalogować. + +/community/leave.bml.label.removed=Zostałeś usunięty/a z grupy [[commname]] + +/community/leave.bml.label.removefromfriends=Usuń także użytkownika "[[user]]" z listy przyjaciół. + +/community/leave.bml.success=Sukces + +/community/leave.bml.sure=Na pewno? + +/community/leave.bml.title=Opuść Grupę + +/community/manage.bml.commlist.actions=Działania + +/community/manage.bml.commlist.actmembers=[Członkowie] + +/community/manage.bml.commlist.actmembers2=Członkowie + +/community/manage.bml.commlist.actsettings=[Ustawienia] + +/community/manage.bml.commlist.actsettings2=Ustawienia + +/community/manage.bml.commlist.header=Twoje grupy + +/community/manage.bml.commlist.none=Nie zarządzasz żadnymi grupami. + +/community/manage.bml.commlist.text=Oto grupy, ktorymi zarządzasz lub współzarządzasz: + +/community/manage.bml.commlist.title=Tytuł + +/community/manage.bml.commlist.username=Nazwa Użytkownika + +/community/manage.bml.create.header=Utwórz grupę + +/community/manage.bml.create.text=Możesz także utworzyć nową grupę. + +/community/manage.bml.joinmail.save=Zachowaj Ustawienia + +/community/manage.bml.title=Zarządzanie Grupami + +/community/members.bml.error.alreadyadded=Użytkownik [[user]] nie został dodany, ponieważ ma już dostęp do tej grupy. + +/community/members.bml.error.alreadysent=Użytkownik [[user]] nie mógł zostać dodany, ponieważ został już wysłany do niego email z potwierdzeniem o: [[datetime]]. Poczekaj na odpowiedź tego użytkownika. + +/community/members.bml.error.invaliduser=Nie można dodać grupy lub kąta zrzeszającego: [[user]] + +/community/members.bml.error.noaccess=Tylko zarządzający grupami mają możliwość edytowania listy członków. Nie jesteś zarządzającym grupy [[comm]]. + +/community/members.bml.error.noattr=Nie wybrano żadnych atrybutów dla użytkownika: [[user]] + +/community/members.bml.error.nocomm=Grupy nie znaleziono. + +/community/members.bml.error.nouser=Użytkownik nie istnieje: [[user]] + +/community/members.bml.key.admin=Zarządzający + +/community/members.bml.key.member=Członek + +/community/members.bml.key.moderate=Moderator + +/community/members.bml.key.post=Możliwość Zamieszczania + +/community/members.bml.key.preapprove=Nie kontrolowana + +/community/members.bml.manage2=Zarządzaj grupami + +/community/members.bml.name=Nazwa Grupy: [[name]] + +/community/members.bml.nextlink=(Następna strona...) + +/community/members.bml.prevlink=(Poprzednia strona...) + +/community/members.bml.settings=[Ustawienia] + +/community/members.bml.success.header=Sukces + +/community/members.bml.success.message=Twoje zmany zostały zapisane. + +/community/members.bml.success.return=Powrót do listy + +/community/members.bml.title=Członkowie Grupy + +/community/members.bml.update=Uaktualnij ustawienia + +/community/moderate.bml.approve.button=Tak, zatwierdzić + +/community/moderate.bml.approve.header=Zatwierdzić ten wpis? + +/community/moderate.bml.approve.preapprove=Dodaj także użytkownika [[user]] do listy z góry zatwierdzanych użytkowników w tej grupie. + +/community/moderate.bml.approve.text=Czy na pewno chcesz zatwierdzić ten wpis? + +/community/moderate.bml.brlist.actions=Działania + +/community/moderate.bml.brlist.poster=Zamieszczający + +/community/moderate.bml.brlist.subject=Temat zaczyna się + +/community/moderate.bml.brlist.time=Temat + +/community/moderate.bml.brlist.view=Zobacz + +/community/moderate.bml.browse.empty=Kolejka do zatwierdzania jest pusta. + +/community/moderate.bml.browse.header=Kontroluj Grupę + +/community/moderate.bml.browse.text=Oto kolejka wpisów do zatwierdzenia dla grupy [[link]] + +/community/moderate.bml.choice.approve=Zatwierdź + +/community/moderate.bml.choice.reject=Odrzuć + +/community/moderate.bml.error.noaccess=Nie jesteś moderatorem grupy [[comm]]. + +/community/moderate.bml.error.noentry=Wpis nie został znaleziony (być może zajął się nim już inny moderator). + +/community/moderate.bml.error.nolist=Nie jesteś moderatorem żadnych grup. + +/community/moderate.bml.error.notfound=Konto grupy nie znalezione. + +/community/moderate.bml.manage=Zarządzaj grupami + +/community/moderate.bml.moderate=Kontroluj tę grupę + +/community/moderate.bml.modlist.actions=Działania + +/community/moderate.bml.modlist.actmodempty=[Kontroluj] + +/community/moderate.bml.modlist.actmoderate=Kontroluj + +/community/moderate.bml.modlist.count=Długość kolejki + +/community/moderate.bml.modlist.header=Kontroluj Grupy + +/community/moderate.bml.modlist.title=Tytuł + +/community/moderate.bml.modlist.username=Nazwa Użytkownika + +/community/moderate.bml.posted.appheader=Z Góry Zatwierdzone + +/community/moderate.bml.posted.apptext=Dodatkowo, użytkownik [[user]] został dodany do listy użytkowników, których wpisy do tej grupy są z góry zatwierdzone. + +/community/moderate.bml.posted.header=Sukces + +/community/moderate.bml.posted.proterror=Wpis nie został zamieszczony z powodu błędu: [[err]] + +/community/moderate.bml.posted.text=Wpis został zamieszczony. + +/community/moderate.bml.reject.button=Tak, odrzuć + +/community/moderate.bml.reject.header=Odrzucić ten wpis? + +/community/moderate.bml.reject.reason=Możesz też wyjaśnić zamieszczającemu powody, dla których odrzuciłaś/eś jego wpis. Zostaną one wysłane do niego mailem. + +/community/moderate.bml.reject.text=Czy na pewno chcesz odrzucić ten wpis? + +/community/moderate.bml.rejected.header=Odrzucony + +/community/moderate.bml.rejected.text=Ten wpis został odrzucony + +/community/moderate.bml.title=Zarządzanie Grupą + +/community/pending.bml.no=Nie + +/community/pending.bml.yes=Tak + +/community/search.bml.button.clear=Wyczyść Formularz + +/community/search.bml.button.search=Szukaj! + +/community/search.bml.checkbox.onlywithpics=Tylko grupy posiadające obrazki + +/community/search.bml.label.byinterest=Według Zainteresowań + +/community/search.bml.label.bylocation=Według Położenia na Świecie + +/community/search.bml.label.bytime=Według Czasu Aktualizacji + +/community/search.bml.label.city=Miasto: + +/community/search.bml.label.country=Państwo: + +/community/search.bml.label.displayoptions=Opcje Wyświetlania + +/community/search.bml.label.hasmember=Należy do niej + +/community/search.bml.label.othercriteria=Inne Kryteria + +/community/search.bml.label.outputformat=Format Wyników: + +/community/search.bml.label.records=Ilość wyników na stronę: + +/community/search.bml.label.searchcomm=Przeszukaj Grupy + +/community/search.bml.label.selecriteria=Wybież kryteria, według których chcesz szukać grup. Rezultat jest iloczynem logicznym wszystkich kryteriów. Innymi słowy, każda kratka oznacza "ORAZ", a nie "LUB". + +/community/search.bml.label.sortmethod=Metoda Sortowania: + +/community/search.bml.label.stateprovince=Stan/Prowincja: + +/community/search.bml.label.updated=Uaktualniono w ostatnim + +/community/search.bml.sel.bypicture=Według Obrazka + +/community/search.bml.sel.communityname=Nazwa Grupy + +/community/search.bml.sel.commview=Widok Grupy + +/community/search.bml.sel.day=dniu + +/community/search.bml.sel.month=miesiącu + +/community/search.bml.sel.simple=Prosty + +/community/search.bml.sel.updatetime=Czas Aktualizacji + +/community/search.bml.sel.username=Nazwa Użytkownika + +/community/search.bml.sel.week=tygodniu + +/community/search.bml.title=Szukanie Grup + +/community/settings.bml.button.changecommunity=Uaktualnij Ustawienia + +/community/settings.bml.button.createcommunity=Utwórz Grupę + +/community/settings.bml.error.badpassword=Nieprawidłowe hasło grupy + +/community/settings.bml.error.hasentries=To konto ma już wpisy i nie może zostać przekonwertowane. + +/community/settings.bml.error.maintainertype=Konto zarządzającego grupą musi być kontem osobistym, nie może być innym dziennikiem wspólnym. + +/community/settings.bml.error.noaccess=Tylko zarządzający grupami mogą edytować ustawienia grup. Nie jesteś zarządzającym grupy [[comm]]. + +/community/settings.bml.error.notcomm=To nie jest konto grupy. + +/community/settings.bml.error.notfound=Konto grupy nie znalezione. + +/community/settings.bml.error.samenames=Konto zarządzającego i konto grupy nie mogą być te same. + +/community/settings.bml.label.anybodycan=Wszyscy Członkowie
          Każdy może zamieszczać wpisy zaraz po przyłączeniu się do grupy. + +/community/settings.bml.label.changeheader=Znień Ustawienia Grupy + +/community/settings.bml.label.changetext=Tu możesz zmieniać ustawienia grupy, którą posiadasz lub którą zarządzasz. + +/community/settings.bml.label.closedmemb2=Ograniczone Członkostwo
          Nikt nie może dołączyć do tej grupy. + +/community/settings.bml.label.commchanged=Ustawienia Twojej grupy zostały zmienione. + +/community/settings.bml.label.commcreate=To jest konto, które chcesz zamienić w grupę. Musi ono być już utworzone, ale nie powinno być w użyciu jako konto indywidualne, ponieważ po zamianie w grupę mnóstwo innych ludzi będzie potencjalnie mogło zamieszczać wpisy w tym dzienniku. + +/community/settings.bml.label.commcreated=Twoja grupa jest już ustawiona. + +/community/settings.bml.label.commheader=Konto Grupy + +/community/settings.bml.label.comminfo=Info grupy + +/community/settings.bml.label.commopts=Opcje Grupy + +/community/settings.bml.label.commsite=Strona internetowa grupy + +/community/settings.bml.label.community=Grupa: + +/community/settings.bml.label.createheader=Utwórz Grupę + +/community/settings.bml.label.createtext=Tutaj możesz utworzyć konto grupy, Grupa to specjalny dziennik, do którego mogą przyłączać się inni i zamieszczać w nim wpisy. Przykładem grupy jest Seattle Party Community. + +/community/settings.bml.label.howoperates=Wybierz, jak ma funkcjonować Twoja grupa. Możesz to zmienić później. + +/community/settings.bml.label.maintainer=Zarządzający: + +/community/settings.bml.label.maintainer.login=Jeśli to nie jest konto zarządzającego, zaloguj się na inne. + +/community/settings.bml.label.membership=Członkowstwo + +/community/settings.bml.label.modheader=Zarządzanie + +/community/settings.bml.label.modis=Kontrolowana
          Nowe wpisy muszą być zatwierdzane przez moderatora. + +/community/settings.bml.label.modisnt=Nie Kontrolowana
          Nowe wpisy pokazują się natychmiast. + +/community/settings.bml.label.modtext=Czy wpisy do tej grupy są kontrolowane? + +/community/settings.bml.label.nmcan=Nie-Członkowie Mogą Zamieszczać
          Użytkownicy mogą zamieszczać w tej grupie bez przyłączania się do niej. + +/community/settings.bml.label.nmcant=Nie-Członkowie Nie Mogą Zamieszczać
          Użytkownicy muszą przyłączyć się do tej grupy, żeby w niej zamieszczać. + +/community/settings.bml.label.nmheader=Zamieszczanie Wpisów Przez Nie-Członków + +/community/settings.bml.label.nmtext=Czy użytkownicy mogą zamieszczać w tej grupie bez przyłączania się do niej? + +/community/settings.bml.label.openmemb=Otwatre Członkowstwo
          Każdy może przyłączyć się do tej grupy bez potwierdzenia zarządzającego. + +/community/settings.bml.label.password=Hasło: + +/community/settings.bml.label.postaccess=Dostęp Do Zamieszczania + +/community/settings.bml.label.rellinks=Istotne linki: + +/community/settings.bml.label.selcan=Wybrani Członkowie
          Tylko niektórzy członkowie mają prawo do zamieszczania wpisów, nadane przez zarządzającego. + +/community/settings.bml.label.username=Nazwa Użytkownika: + +/community/settings.bml.label.whocanjoin=Kto może przyłączyć sie do Twojej grupy? + +/community/settings.bml.label.whocanpost=Kto może zamieszczać w tej grupie? + +/community/settings.bml.manage2=Zarządzaj grupami + +/community/settings.bml.members=[Członkowie] + +/community/settings.bml.name=Nazwa grupy: [[name]] + +/community/settings.bml.success=Sukces + +/community/settings.bml.title.create=Utwórz Grupę + +/community/settings.bml.title.modify=Ustawienia Grupy + +/create.bml.age.check.question=Czy masz mniej niż 13 lat? + +/create.bml.age.check.yes=Tak, mam mniej niż 13 lat. + +/create.bml.age.check2.question=Czy masz ponad 13 lat? + +/create.bml.age.check2.yes=Tak, mam ponad 13 lat. + +/create.bml.age.head=Wiek + +/create.bml.btn.create=Utwórz Dziennik + +/create.bml.btn.proceed=Kontynuuj... + +/create.bml.captcha.answer=Odpowiedź: + +/create.bml.captcha.audiodesc=Wystukaj liczby, które słyszysz, by udowodnić, że nie jesteś automatem spamującym: + +/create.bml.captcha.desc=Wystukaj litery i cyfry, które widzisz poniżej, by udowodnić, że nie jesteś automatem spamującym. Jeśli nie jesteś w stanie odczytać tekstu, zamiast tego wpisz "AUDIO" i poddaj się testowi dźwiękowemu. + +/create.bml.captcha.invalid=Nieprawidłowa odpowiedź. Spróbuj jeszcze raz. + +/create.bml.captcha.play=Odtwórz dźwięk + +/create.bml.captcha.prove=Udowodnij, że jesteś człowiekiem + +/create.bml.clusterselect.cluster=Klaster: + +/create.bml.clusterselect.clusternum=Klaster [[number]] + +/create.bml.clusterselect.head=Wybór Klastra + +/create.bml.clusterselect.nocluster=Brak Klastra + +/create.bml.clusterselect.text=Wybież klaster, na którym chciałbyś założyć to konto. Informacja: Jest to wyłącznie opcja do testowania/debugowania. W efekcie użytkownicy nie będą tego wybierać ani nic o tym wiedzieć. + +/create.bml.create.head=Tworzenie Nowego Dziennika + +/create.bml.create.text=Tworzenie nowego LiveJournala jest proste, wystarczy wykonywać wszystkie podane instrukcje! + +/create.bml.email.head=Twój adres e-mail + +/create.bml.email.input.head=Adres E-mail: + +/create.bml.email.text2=Dla potwierdzenia i z powodów bezpieczeństwa potrzebny jest nam Twój adres email. Nigdy, w żadnych okolicznościach, nie zostanie on sprzedany lub oddany spamerom. Nienawidzimy spamu ponad wszystko. Przeczytaj o naszej polityce prywatności, jeśli chcesz wiedzieć więcej. + +/create.bml.error.coppa.under13=Przykro nam, ale z powodu ograniczeń COPPA nie możesz używać LiveJournal przed ukończeniem 13 roku życia. Serdecznie zapraszamy w Twoje 13 urodziny. + +/create.bml.error.email.blank=Musisz wpisać swój adres e-mail. + +/create.bml.error.email.lj_domain=Nie możesz używać aliasu [[domain]] przy tworzeniu konta. Podaj inny adres email. + +/create.bml.error.email.nospaces=Adres e-mail nie może zawierać spacji. Jeśli używasz AOL, pamiętaj, że twój adres e-mail to twoje "screen name" pozbawione spacji z końcówką @aol.com + +/create.bml.error.password.asciionly=Hasło może zawierać jedynie symbole ASCII. + +/create.bml.error.password.blank=Musisz podać hasło. + +/create.bml.error.password.nomatch=Hasła się nie zgadzają. + +/create.bml.error.postrequired=Wymagany WPIS. + +/create.bml.error.username.blank=Prosimy podać imię lub ksywkę. + +/create.bml.error.username.inuse=Nazwa użytkownika jest zajęta, prosimy wybrać inną. + +/create.bml.error.username.iscode=Nazwa użytkownika wydaje się być kodem zaproszenia, a nie nazwą użytkownika. + +/create.bml.error.username.mustenter=Musisz wpisać nazwę użytkownika. + +/create.bml.error.username.reserved=Przykro nam, ta nazwa użytkownika jest zarezerwowana. + +/create.bml.initial.friend.lj_maintenance=Raporty o planowanych i nieplanowanych awariach strony i naprawach. + +/create.bml.initial.friend.news=Nowości i wydarzenia na LiveJournal + +/create.bml.initialfriends=Dodaj te dzienniki do swojej listy przyjaciół by być na bierząco ze wszystkim, co dzieje się w naszym serwisie. + +/create.bml.initialfriends.heading=Przyjaciele na Początek + +/create.bml.name.head=Twoje Imię + +/create.bml.name.input.head=Imię: + +/create.bml.name.text=Jakie się nazywasz? Twoje imię będzie się pojawiało na górze Twojego dziennika i w katalogu użytkowników, jeżeli zechcesz się w nim znaleźć. Nie musisz podawać pełnego imienia, ani nawet prawdziwego. + +/create.bml.password.head=Hasło + +/create.bml.password.input.head1=Hasło: + +/create.bml.password.input.head2=Wpisz hasło ponownie: + +/create.bml.password.text=Wybierz hasło. + +/create.bml.proceed.btn.proceed=Kontynuuj... + +/create.bml.proceed.warning=Wciśnij Kuntynuuj tylko raz!! + +/create.bml.success.btn.enterinfo=Wpisz Osobiste Informacje + +/create.bml.success.head=Sukces! + +/create.bml.success.text1=Twój dziennik został utworzony. Ważne informacje dotyczące rejestracji, zawierające dalsze instrukcje, zostały przesłane na [[email]]. Potwierdź utworzenie swojego konta poprzez kliknięcie na link wysłany do Ciebie w emailu. + +/create.bml.success.text2=Twój LiveJournal będzie dostępny pod adresem: + +/create.bml.success.text3=Prosimy, poświęć teraz chwilkę czasu na wpisanie informacji o sobie. Większość jest opcjonalna, ale chcielibyśmy mieć ogólne pojęcie o tym, kto używa LiveJournal. + +/create.bml.title=Stwórz Nowy Dziennik + +/create.bml.tos.error=Musisz przeczytać i zaakceptować zasady użytkowania, zanim utworzysz konto. + +/create.bml.tos.haveread=Przeczytałam/em i akceptuję Zasady Użytkowania. + +/create.bml.tos.heading=Zasady Użytkowania + +/create.bml.tos.p1.2=Zanim będziesz mogła/mógł kontunuować, musisz przeczytać i zaakceptować nasze Zasady Użytkowania. + +/create.bml.useacctcodes.entercode=Aby utworzyć nowe konto, wpisz poniżej kod-zaproszenie. Więcej informacji na ten temat znajdziesz tutaj + +/create.bml.useacctcodes.welcome=Witaj + +/create.bml.username.box.head=Nazwa Użytkownika: + +/create.bml.username.charsallowed=Twoja nazwa użytkownika może składać się tylko z małyc liter (a-z, bez polskich znaków), cyfr (0-9) oraz znaku podkreślenia (_).
          Poza tym nie może składać się z więcej niż 15 znaków. + +/create.bml.username.forpaidaccts=Lub, dla płatnych kont: + +/create.bml.username.head=Nazwa Użytkownika + +/create.bml.username.ljaddress=Twój dziennik będzie dostępny pod tymi adresami: + +/create.bml.username.text=Kasżdy użytkownik [[sitename]] musi mieć swoją własną, niepowtarzalną nazwę użytkownika. Twoja nazwa użytkownika pojawia się w adresie Twojego dziennika, używasz jej też do logowania się na serwer [[sitename]]. Pokazuje się też wówczas, gdy zamieszczasz komentarze do dzienników innych ludzi. + +/create.bml.username.username=nazwa użytkownika + +/customize/index.bml.change=Zmień + +/customize/index.bml.choose=Chcesz używać starego czy nowego systemu stylów? + +/customize/index.bml.choose.header=Wybierz system stylów + +/customize/index.bml.choose.s1=Stary system (S1) + +/customize/index.bml.choose.s2=Nowy system (S2) + +/customize/index.bml.error.cant_generate_user_layer=Nie udało się wygenerować warstwy użytkownika + +/customize/index.bml.error.fail_create_style=Nie udało się utworzyć nowego stylu. + +/customize/index.bml.error.not_your_layout=To nie Twój układ strony. + +/customize/index.bml.error.not_your_theme=To nie Twój zestaw + +/customize/index.bml.previews=(Podgląd) + +/customize/index.bml.s1=Stary system stylów jest konfigurowany przez stronę Modyfikacji Dziennika. + +/customize/index.bml.s1.header=Przy Użyciu S1 + +/customize/index.bml.s2.advanced.denied=Tylko posiadacze kont płatnych, permanentnych i wcześnie utworzonych mogą korzystać z zaawansowanego obszaru zmiany wyglądu dziennika. Dowiedz się więcej na temat korzyści z posiadania konta płatnego. + +/customize/index.bml.s2.advanced.header=Zaawansowane Ustawienia Wyglądu + +/customize/index.bml.s2.advanced.permitted=Aby utworzyć nowe warstwy i style od zera, odwiedź obszarzaawansowanej zmiany wyglądu dziennika. + +/customize/index.bml.s2.customize=Poniższe ustawienia zależą od układu strony. + +/customize/index.bml.s2.customize.header=Krok 2: Personalizuj Układ Strony + +/customize/index.bml.s2.customize.language=Poniższe języki w pełni lub częściowo współpracują z tym stylem. + +/customize/index.bml.s2.customize.language.custom=(Własny) + +/customize/index.bml.s2.customize.language.header=Język + +/customize/index.bml.s2.customize.settings=Jeśli chcesz bardziej zmienić wygląd swojego dziennika, tutaj możesz poprawiać poszczególne ustawienia, by dziennik wyglądał dokładnie tak, jak chcesz. + +/customize/index.bml.s2.customize.settings.delete=Usuń Własne Zmiany + +/customize/index.bml.s2.customize.settings.edit=Edytuj Dostosowanie Dziennika + +/customize/index.bml.s2.customize.settings.header=Zmień Poszczególne Ustawienia + +/customize/index.bml.s2.customize.settings.new=Dostosuj Wygląd Dziennika + +/customize/index.bml.s2.customize.themes=Wybierz z poniższych opcjonalnych zestawów dla tego układu strony. + +/customize/index.bml.s2.customize.themes.default=(Domyślny Układ Strony) + +/customize/index.bml.s2.customize.themes.header=Zestawy + +/customize/index.bml.s2.layout=Wybierz swój układ strony. Ponieważ wybór zestawów i własne modyfikacje zależą od Twojego układu strony, zmiana tego ustawienia spowoduje, że już wprowadzone zmiany zostaną pominięte. + +/customize/index.bml.s2.layout.header=Krok Pierwszy: Układ Strony + +/customize/index.bml.s2.related.editinfo.about=Ustaw tytuł swojego dziennika i różne opcje. + +/customize/index.bml.s2.related.header=Strony Powiązane Tematycznie + +/customize/index.bml.s2.related.links.about=Niektóre style mogą zawierać Twoją listę linków. + +/customize/index.bml.s2.related.modify.about=Wybierz zestaw ikon nastrojów dla swojego dziennika. + +/customize/index.bml.title=Dostosuj Wygląd Dziennika + +/delcomment.bml.changeoptions=Uwaga: Na stronie [[link]] możesz wybrać, czy komentarze zamieszczać mogą wszyscy, zarejestrowani użytkownicy, czy tylko przyjaciele. + +/delcomment.bml.confirm.banuser=Odbierz użytkownikowi [[user]] możliwość komentowania w swoim dzienniku. + +/delcomment.bml.confirm.body=Czy na pewno chcesz usunąć ten komentarz? + +/delcomment.bml.confirm.head=Usunąć ten komentarz? + +/delcomment.bml.confirm.spam=Oznacz ten komentarz jako spam + +/delcomment.bml.confirm.submit=Usuń Komentarz + +/delcomment.bml.error.alreadydeleted=Wskazany komentarz został już usunięty! + +/delcomment.bml.error.cantdelete=Komentarz może zostać usunięty tylko przez swojego autora lub przez właściciela dziennika. + +/delcomment.bml.error.cantdelete.comm=Komentarz może zostać usunięty tylko przez swojego autora, przez autora danego wpisu lub przez zarządzającego grupą. + +/delcomment.bml.error.invalidtype=Nieprawidłowy rodzaj komentarza. Ta strona zajmuje się tylko komentarzami do wpisów do dziennika. + +/delcomment.bml.error.nocomment=Wskazany komentarz nie istnieje. + +/delcomment.bml.success.andban=Komentarz został usunięty, a użytkownikowi [[user]] została odebrana możliwość komentowania w Twoim dzienniku. + +/delcomment.bml.success.head=Usunięty + +/delcomment.bml.success.noban=Komentarz został usunięty. + +/delcomment.bml.success.spam=Dodatkowo administratorzy strony zostali poinformowani, że ten komentarz był spamem. Dziękujemy za zgłoszenie tego. + +/delcomment.bml.title=Usuń Komentarz + +/developer/index.bml.clients=A więc chcesz utworzyć lub ulepszyć klienta LiveJournal na swoim komputerze? Świetnie! Poniżej znajdziesz niezbędne informacje na temat tego, jak działa LiveJournal. + +/developer/index.bml.clients.header=Pisanie Klientów LiveJournal + +/developer/index.bml.clients.links<< +
          +
          Server LiveJournal<->Protokół Klientów
          +
          Dowiedz się, jak klient LiveJournal na Twoim komputerze komunikuje się z serverem LiveJournal i vice versa. + Zrozumienie tej komunikacji to podstawowa rzecz, jaka jest konieczna przed rozpoczęciem pisania lub ulepszania klienta LiveJournal na Twojej platformie.
          +
          Kompletna Dokumentacja Protokołów
          +
          Wszelkie możliwe protokoły i metody.
          +
          Lista Klientów
          +
          Lista większości klientów używanych do łączenia się z LiveJournal. Większość z tych klientów jest open source, a wszystkie mogą być używane bezpłatnie. To najlepsze miejsce, by znaleźć przykłady do własnego klienta.
          +. + +/developer/index.bml.dbschema=Interesuje CiÄ™ ukÅ‚ad bazy danych? SQL użyty do tworzenia wszystkich tabel i zapeÅ‚niania ich jest doÅ‚Ä…czony do kodu serwera. + +/developer/index.bml.dbschema.header=UkÅ‚ad Bazy Danych + +/developer/index.bml.embedding=Chcesz, by Twój dziennik byÅ‚ integralnÄ… częściÄ… Twojej strony osobistej? Jest na to kilka sposobów, w zależnoÅ›ci od tego, jakÄ… kontrolÄ™ masz nad swoim serwerem. Musisz siÄ™ tym martwić jednak tylko wtedy, jeÅ›li nie chcesz, by www.livejournal.com pojawiaÅ‚o siÄ™ w adresie URL Twojego dziennika. + +/developer/index.bml.embedding.header=WÅ‚Ä…czanie LiveJournal do Strony Osobistej + +/developer/index.bml.notice.header=Uwaga + +/developer/index.bml.notice1=NastÄ™pujÄ…ce informacje sÄ… skierowane tylko do programistów i zaawansowanych użytkowników. JeÅ›li chcesz używać LiveJournala jedynie po to, by prowadzić swój dziennik, to Å›wietnie! Normalni użytkownicy nie muszÄ… siÄ™ tym przejmować. + +/developer/index.bml.styles=Nie podoba Ci siÄ™ to, jak wyglÄ…da Twój dziennik? Bez obaw! Wszystko daje siÄ™ dostosować, a jeÅ›li przeczytasz poniższÄ… dokumentacjÄ™, bÄ™dziesz wiedzieć wszystko, czego potrzebujesz, by nadać swoim stronom taki wyglÄ…d, jakiego chcesz. + +/developer/index.bml.styles.header=Dostosowywanie wyglÄ…du dziennika LiveJournal + +/developer/index.bml.styles.s1.header=System Stylów 1 + +/developer/index.bml.styles.s1.system=System Stylów + +/developer/index.bml.styles.s1.varlist=Lista Zmiennych + +/developer/index.bml.styles.s1.varlist.about=Alfabetyczny spis wszystkich zmiennych, które możesz dostosowywać. + +/developer/index.bml.styles.s1.views=Typy Widoku + +/developer/index.bml.styles.s1.views.about=Lista różnych sposobów, na jakie możesz oglÄ…dać swój dziennik, i opis każdego z nich. + +/developer/index.bml.styles.s2.header=System Stylów 2 + +/developer/index.bml.styles.s2.layerbrowse=PrzeglÄ…darka Warstw S2 + +/developer/index.bml.styles.s2.manual=Instrukcja ObsÅ‚ugi S2 + +/developer/index.bml.styles.s2.manual.about=ZrozumiaÅ‚e informacje dotyczÄ…ce używania S2 na LiveJournal. + +/directory.bml.browse.country.desc=Wybierz kraj, z którego dzienniki chcesz czytać... + +/directory.bml.browse.country.title=PrzeglÄ…daj Dzienniki WedÅ‚ug Krajów + +/directory.bml.browse.usa.desc=Kliknij na stan USA, by czytać dzienniki z tego stanu, lub kliknij na nazwÄ™ kraju poniżej, by czytać dzienniki z tego kraju. + +/directory.bml.browse.usa.title=PrzeglÄ…daj Dzienniki WedÅ‚ug Stanu USA + +/directory.bml.error.accounttype=Przykro nam, Twój typ konta nie zezwala na korzystanie z katalogu, lub nie jesteÅ› w tej chwili zalogowana/y. JeÅ›li Twój typ konta pozwala na korzystanie z katalogu, zaloguj siÄ™ i spróbuj ponownie. + +/directory.bml.navcrap.matches=[[count]] wyniki/ów + +/directory.bml.navcrap.xofy=Strona [[curpage]] z [[totpages]] (wyniki [[reca]]-[[recb]]) + +/directory.bml.search.monkey=Setki wytrenowanych maÅ‚pek biegajÄ… wÅ‚aÅ›nie tu i tam, by znaleźć dla Ciebie wyniki wyszukiwania. Prosimy czekać. + +/directory.bml.search.new=Nowe Wyszukiwanie + +/directory.bml.search.title=Wyszukiwanie + +/directory.bml.user=Użytkownik + +/doc/index.bml.about=Witaj w dziale dokumentacji LiveJournal. Możesz tu znaleźć informacje na wiÄ™kszość tematów zwiÄ…zanych z usÅ‚ugami i oprogramowaniem LiveJournal. Wybierz temat: + +/doc/index.bml.about.header=Witaj + +/doc/index.bml.docs.faq.about=CzÄ™sto Zadawane Pytania o LiveJournal.com + +/doc/index.bml.docs.header=Dokumenty + +/doc/index.bml.docs.howto.about=Porady i triki do modyfikacji Twojego konta na LiveJournal + +/doc/index.bml.docs.server.about=Wszystko, co musisz wiedzieć, by zainstalować, administrować i zhakować setup LiveJournal + +/doc/index.bml.docs.server.title=PodrÄ™cznik Serwera LiveJournal + +/doc/index.bml.docs.tour.about=Zaprojektowane dla nowych odwiedzajÄ…cych, by mogli zaznajomić siÄ™ ze stronÄ… + +/doc/index.bml.docs.tour.title=Zwiedzanie + +/doc/index.bml.title=Dokumentacja + +/doc/index.bml.volunteering.about=JeÅ›li chcesz pomagać nam z dokumentacjÄ… LiveJournal, zajrzyj do poniższych grup: + +/doc/index.bml.volunteering.header=Ochotnicy + +/doc/index.bml.volunteering.ljsysdoc=Dyskusje dotyczÄ…ce systemu dokumentacji LiveJournal + +/doc/index.bml.volunteering.ljuserdoc=Dyskusje na temat dokumentacji dla użytkownika + +/doc/tour/index.bml.clients.caption<< +Klienty LiveJournal to maÅ‚e programy uruchamiane na Twoim komputerze, które pozwalajÄ… Ci uaktualniać swój dziennik, kiedy tylko jesteÅ› w sieci, bez potrzeby otwierania okna przeglÄ…darki. +Klienty sÄ… dostÄ™pne dla praktycznie każdego rodzaju komputera z dowolnym systemem i Å‚atwo można je dostosowywać do wÅ‚asnych potrzeb. +. + +/doc/tour/index.bml.clients.title=Klienty + +/doc/tour/index.bml.comms.caption=LiveJournal to duże, interaktywne stowarzyszenie, wiÄ™c nie jest niespodziankÄ…, że ma wielu czÅ‚onków z podobnymi zainteresowaniami. Z tego powodu oferujemy możliwość tworzenia grup, lub dzienników, do których wpisy może zamieszczać wiele użytkowników. + +/doc/tour/index.bml.comms.title=Grupy + +/doc/tour/index.bml.create.caption=LiveJournal to stowarzyszenie oparte na czÅ‚onkowstwie. Ta strona wyjaÅ›nia, co pociÄ…ga za sobÄ… czÅ‚onkowstwo, czemu czÅ‚onkowstwo jest ważne i jakie sÄ… z niego korzyÅ›ci. Zawiera także formularz do utworzenia konta. + +/doc/tour/index.bml.create.title=Tworzenie Konta + +/doc/tour/index.bml.friends.caption=Możesz także Å›ledzić przez LiveJournal, co porabiajÄ… Twoi przyjaciele, korzystajÄ…c z wbudowanego dodatku "przyjaciół". JeÅ›li znajdziesz dziennik, który CiÄ™ zainteresuje, dodaj go do swojej listy przyjaciół. Umożliwi Ci to czytanie wpisów ze wszystkich interesujÄ…cych CiÄ™ dzienników na jednej, wspólnej stronie. + +/doc/tour/index.bml.friends.title=Przyjaciele + +/doc/tour/index.bml.intro.caption=Ta "trasa zwiedzania" zostaÅ‚a zaprojektowana, by nowi odwiedzajÄ…cy mogli siÄ™ zaznajomić z naszÄ… stronÄ…. Zobaczysz, gdzie znajdujÄ… siÄ™ najważniejsze dziaÅ‚y, i dowiesz siÄ™ o interesujÄ…cych dodatkach. + +/doc/tour/index.bml.intro.title=Witaj + +/doc/tour/index.bml.modify.caption=Masz też możliwość ksztaÅ‚towania swojego dziennika na wiele różnych sposobów, przy pomocy stylów oraz zestawów kolorów. UczyÅ„ swój dziennik tak wyjÄ…tkowym, jak tylko zechcesz! + +/doc/tour/index.bml.modify.title=Personalizacja Dziennika + +/doc/tour/index.bml.nav.next=Dalej --> + +/doc/tour/index.bml.nav.prev=<-- Wróć + +/doc/tour/index.bml.profile.caption=ZachÄ™camy czÅ‚onków LiveJournal do podawania informacji o sobie w swoich profilach. Daje nam to pojÄ™cie o tym, kto korzysta ze strony i jak najlepiej obsÅ‚użyć naszych użytkowników. Jakkolwiek, nic z tego nie jest obowiÄ…zkowe — jedyne informacje konieczne do rozpoczÄ™cia korzystania z LiveJournal to nazwa konta, adres email oraz hasÅ‚o. + +/doc/tour/index.bml.profile.title=Profile + +/doc/tour/index.bml.sitemap.caption=Mamy nadziejÄ™, że ta "wycieczka" daÅ‚a Ci trochÄ™ pomocnych informacji na temat strony i serwisu LiveJournal. JeÅ›li potrzebujesz pomocy w czymkolwiek zwiÄ…zanym z LiveJournal, skontaktuj siÄ™ z naszym dziaÅ‚em wsparcia. JeÅ›li chcesz zwiedzać dalej, wejdź na naszÄ… mapÄ™ strony, by zobaczyć spis wszystkich naszych stron. + +/doc/tour/index.bml.sitemap.title=Mapa Strony + +/doc/tour/index.bml.support.caption=Strona wsparcia podaje linki do stron wyjaÅ›niajÄ…cych, czym jest LiveJournal, do czÄ™sto zadawanych pytaÅ„ i do wielu innych pomocnych informacji na temat naszego serwisu, firmy oraz stowarzyszenia ogółem. + +/doc/tour/index.bml.support.title=Uzyskiwanie Pomocy + +/doc/tour/index.bml.title=Zwiedzanie - [[title]] + +/doc/tour/index.bml.update.caption=Uaktualnianie dzienników jest esencjÄ… serwisu LiveJournal. Tutaj umożliwiamy użytkownikom dzielenie siÄ™ przeżyciami i wyrażenie swoich myÅ›li. Uaktualnianie dziennika jest Å‚atwe, po prostu wpisuje siÄ™ tekst w odpowiednim okienku i klika siÄ™ przycisk "Uaktualnij Dziennik". OczywiÅ›cie oferujemy też bardziej skomplikowane opcje na stronie uaktualniania dziennika, takie jak możliwość sprawdzenia pisowni oraz możliwość podawania dodatkowych informacji na temat wpisów, takich jak muzyka czy nastrój w danym momencie. + +/doc/tour/index.bml.update.title=Uaktualnianie + +/editinfo.bml.advanced.about=Nie przejmuj siÄ™ tym, jeÅ›li nie wiesz co to jest. + +/editinfo.bml.advanced.title=Zaawansowane Opcje + +/editinfo.bml.allowshowcontact.about=PowinnaÅ›/PowinieneÅ› pozostawić tÄ™ opcjÄ™ wÅ‚Ä…czonÄ…. DziÄ™ki temu inni ludzie mogÄ… skonaktować siÄ™ z TobÄ… - Twój adres e-mail, numer ICQ i screenname na AOL Instant Messangerze sÄ… podane w Twoim profilu. + +/editinfo.bml.allowshowcontact.email=JeÅ›li widoczny, pokazywany bÄ™dzie Twój adres e-mail: + +/editinfo.bml.allowshowcontact.email.actual_only=Tylko rzeczywisty adres + +/editinfo.bml.allowshowcontact.email.both=Oba (prawdziwy + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Tylko adres LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=Å»aden. Nie pokazuj adresu e-mail. + +/editinfo.bml.allowshowcontact.email.no_show=Nie pokazuj żadnych adresów e-mail + +/editinfo.bml.allowshowcontact.email.show=Pokaż adres e-mail + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Razem z powyższymi opcjami możesz wybrać, żebyÅ›my ukryli Twój adres e-mail (nadal pokazujÄ…c Twoje pozostaÅ‚e informacje kontaktowe), pokazywali tylko Twój adres LiveJournal (tylko konta pÅ‚atne), tylko Twój prawdziwy adres, lub oba. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Razem z powyższymi opcjami możesz wybrać, żebyÅ›my ukryli Twój adres e-mail (nadal pokazujÄ…c Twoje pozostaÅ‚e informacje kontaktowe). + +/editinfo.bml.allowshowcontact.title=Pokazywać Twoje informacje kontaktowe na LiveJournal? + +/editinfo.bml.allowshowinfo.about=WÅ‚Ä…cz to, jeÅ›li chcesz, aby Twoje miasto/stan/paÅ„stwo oraz data urodzenia byÅ‚y widoczne dla innych użtykowników. + +/editinfo.bml.allowshowinfo.title=Pokazywać poÅ‚ożenie i datÄ™ urodzenia? + +/editinfo.bml.autotranslate.about<< +Użyj tej opcji, aby poinformować LiveJournal, jakie kodowanie byÅ‚o używane w Twoich wpisach i komentarzach, zanim nasza strona zostaÅ‚a przekonwertowana na Unicode. +JeÅ›li piszesz po angielsku, wybierz "Western European". +. + +/editinfo.bml.autotranslate.header=Auto-konwertuj starsze wpisy z: + +/editinfo.bml.bday.title=Data Urodzenia + +/editinfo.bml.bday.year.opt=rok jest opcjonalny + +/editinfo.bml.bdayreminders.about=JeÅ›li chcesz otrzymywać maile przypominajÄ…ce Ci o urodzinach przyjaciół na LiveJournal, zaznacz tÄ™ kratkÄ™. + +/editinfo.bml.bdayreminders.header=WysyÅ‚ajcie mi e-maile przypominajÄ…ce o urodzinach (obecnie nieaktywne) + +/editinfo.bml.bio.about=Tutaj możesz wpisać swojÄ… mini-biografiÄ™. BÄ™dzie ona widoczna na Twojej stronie Info Użytkownika. + +/editinfo.bml.bio.header=O Tobie + +/editinfo.bml.blockrobots.about<< +JeÅ›li zaznaczysz tÄ™ opcjÄ™, bÄ™dziemy mówić robotom, żeby sobie poszÅ‚y. +Nie wszystkie roboty szanujÄ… zasady. +. + +/editinfo.bml.blockrobots.header=Nie pozwalaj robotom/pajÄ…kom na indeksowanie Twojego dziennika + +/editinfo.bml.chat.icquin.title=Numer ICQ + +/editinfo.bml.chat.msnusername.title=Nazwa Użytkownika MSN + +/editinfo.bml.city.title=Miasto + +/editinfo.bml.country.choose=Wybierz paÅ„stwo + +/editinfo.bml.country.title=PaÅ„stwo + +/editinfo.bml.donotlog=Nie + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=Zaznacz, jeżeli chcesz, aby inni mogli odpowiadać na wpisy w Twoim dzienniku. + +/editinfo.bml.enableboards.header=WÅ‚Ä…cz strony z komentarzami + +/editinfo.bml.encoding.about=Nie przejmuj siÄ™ tym za bardzo. Generalnie tylko miÄ™dzynarodowi użytkownicy, którzy piszÄ… w kilku jÄ™zykach, muszÄ… cokolwiek tu zmieniać. + +/editinfo.bml.encoding.header=Opcje Kodowania + +/editinfo.bml.error.day.notinmonth=NieprawidÅ‚owy dzieÅ„ dla tego miesiÄ…ca. + +/editinfo.bml.error.day.outofrange=NieprawidÅ‚owy dzieÅ„ urodzin. Podaj dzieÅ„ od 1 do 31. + +/editinfo.bml.error.email.lj_domain<< +Nie możesz podać adresu @[[domain]]. +W tym polu podaj swój prawdziwy adres e-mail. +JeÅ›li masz pÅ‚atne konto, Twój adres [[user]]@[[domain]] jest tylko aliasem dla prawdziwego adresu. +Aby wybrać, który z adresów e-mail bÄ™dzie pokazywany publicznie, ustaw to w rubryce "Pokazuj informacje kontaktowe". +. + +/editinfo.bml.error.email.none=Musisz podać swój adres email + +/editinfo.bml.error.email.no_space=Adres e-mail nie może zawierać spacji. Jeżeli jesteÅ› użytkownikiem AOL pamiÄ™taj, że twój adres e-mail to twój screen name pozbawiony spacji, z koÅ„cówkÄ… @aol.com + +/editinfo.bml.error.excessive_int=Przykro nam, ale wpisaÅ‚eÅ› zbyt wiele zainteresowaÅ„. Limit wynosi 150, a wpisaÅ‚eÅ› ich [[intcount]]. Zmiany, które wprowadziÅ‚eÅ› do swojej listy zainteresowaÅ„, nie zostaÅ‚y zachowane. Wróć do poprzedniej strony i skróć listÄ™ zainteresowaÅ„, a nastÄ™pnie zachowaj jÄ… ponownie. + +/editinfo.bml.error.invalidbio=Twoja biografia zawiera nieprawidÅ‚owe znaki. Musisz odwiedzić stronÄ™ konwersji aby przekonwertować jÄ… na Unicode. + +/editinfo.bml.error.invalidints=Twoja obecna lista zainteresowaÅ„ zawiera nieprawidÅ‚owe znaki. Musisz odwiedzić stronÄ™ konwersji aby przekonwertować jÄ… na Unicode. + +/editinfo.bml.error.invalidname=Twoja nazwa zawiera niepoprawne znaki. Musisz odwiedzić stronÄ™ konwersji aby przekonwertować jÄ… na Unicode. + +/editinfo.bml.error.locale.country_ne_state=UstawiÅ‚aÅ›/eÅ› Stany Zjednoczone jako swój kraj, ale wpisaÅ‚aÅ›/eÅ› stan spoza USA w polu "inny stan". + +/editinfo.bml.error.locale.invalid_country=JakimÅ› cudem wybraÅ‚aÅ›/eÅ› nieistniejÄ…cy kraj. + +/editinfo.bml.error.locale.state_ne_country=UstawiÅ‚aÅ›/eÅ› kraj inny niż USA, ale wybraÅ‚aÅ›/eÅ› stan należący do USA. + +/editinfo.bml.error.locale.zip_ne_state<< +Twój kod pocztowy nie należy do Stanu, który wybraÅ‚aÅ›/eÅ›. +Albo popraw informacje, albo usuÅ„ dane z obu pól, nazwÄ™ stanu i kod pocztowy. +. + +/editinfo.bml.error.locale.zip_requires_us<< +WpisaÅ‚aÅ›/eÅ› kod pocztowy, ale nie wybraÅ‚aÅ›/eÅ› Stanów Zjednoczonych jako swojego kraju. +Zbieramy informacje tylko o kodach ludzi ze Stanów. +Prosimy, cofnij siÄ™ i usuÅ„ podany kod pocztowy, lub wybierz USA jako swój kraj. +. + +/editinfo.bml.error.month.outofrange=NieprawidÅ‚owy miesiÄ…c urodzin. Podaj miesiÄ…c od 1 do 12 (styczeÅ„-grudzieÅ„) + +/editinfo.bml.error.noname=Twoje imiÄ™ jest polem koniecznym do wypeÅ‚nienia. Podaj przynajmniej swoje pierwsze imiÄ™ lub ksywkÄ™. + +/editinfo.bml.error.tm.require.number=JeÅ›li chcesz korzystać z wiadomoÅ›ci tekstowych, musisz podać swój numer telefonu. + +/editinfo.bml.error.tm.require_provider<< +JeÅ›li masz zamiar używać wiadomoÅ›ci tekstowych, musisz wybrać swojego usÅ‚ugodawcÄ™. + +JeÅ›li Twój dostawca nie jest na naszej liÅ›cie, skontaktuj siÄ™ z nami z informacjÄ…, jak funkcjonuje Twój system wiadomoÅ›ci tekstowych, abyÅ›my mogli dodać obsÅ‚ugÄ™ tego systemu. +. + +/editinfo.bml.error.year.notenoughdigits=Niepoprawny rok urodzenia. Podaj czterocyfrowy rok. + +/editinfo.bml.error.year.outofrange=Niepoprawny rok urodzenia. + +/editinfo.bml.finished.about=Kiedy skoÅ„czysz, wciÅ›nij przycisk i zapisz zmiany: + +/editinfo.bml.finished.header=Gotowe? + +/editinfo.bml.finished.save_button=Zapisz Zmiany + +/editinfo.bml.foafurl.title=ZewnÄ™trzny FOAF URL: + +/editinfo.bml.gender.title=PÅ‚eć + +/editinfo.bml.getreplies.about|staleness=1 +/editinfo.bml.getreplies.about=Zaznacz, jeżeli chcesz otrzymywać e-mailem informacje, gdy ktoÅ› odpowie na Twoje wpisy lub komentarze. + +/editinfo.bml.getreplies.header=Otrzymuj odpowiedzi na wpisy + +/editinfo.bml.getselfemails.about=Zaznacz, jeÅ›li chcesz otrzymywać e-mail za każdym razem, gdy zamieÅ›cisz komentarz w prywatnym dzienniku lub w grupie. Nie bÄ™dziesz dostawać e-mailem swoich komentarzy anonimowych. + +/editinfo.bml.getselfemails.header=Otrzymuj e-mailem zamieszczone przez siebie komentarze + +/editinfo.bml.hidefriendof.about=JeÅ›li zaznaczysz tÄ™ opcjÄ™, lista ludzi, którzy majÄ… CiÄ™ na swojej liÅ›cie przyjaciół bÄ™dzie ukrywana w Twoim profilu. + +/editinfo.bml.hidefriendof.header=Ukryj listÄ™ "Należy do przyjaciół..." + +/editinfo.bml.howhear.about<< +Tak z ciekawoÅ›ci, gdzie usÅ‚yszaÅ‚eÅ› o [[sitename]]? +JeÅ›li od jakiejÅ› osoby na LiveJournal, wpisz jej nazwÄ™ użytkownika; jeÅ›li z innego źródÅ‚a/artykuÅ‚u/odnoÅ›nika/strony - wpisz odpowiedniÄ… informacjÄ™. +. + +/editinfo.bml.howhear.header=Z ciekawoÅ›ci... + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Zaznacz tÄ™ ocjÄ™, jeÅ›li Twój program do e-maili w peÅ‚ni obsÅ‚uguje HTML. +Wiele klientów stara siÄ™ obsÅ‚użyć ten format, ale efekty sÄ… dość koszmarne. +JeÅ›li odznaczysz tÄ™ opcjÄ™, LiveJournal bÄ™dzie Ci wysyÅ‚aÅ‚ jedynie wiadomoÅ›ci tekstowe. +. + +/editinfo.bml.htmlemail.header=WysyÅ‚aj E-maile z HTML + +/editinfo.bml.int.about=JeÅ›li chcesz, by inni ludzie mogli odnaleźć CiÄ™ w katalogu, szukajÄ…c wedÅ‚ug zainteresowaÅ„, wpisz poniżej listÄ™ rzeczy, które CiÄ™ interesujÄ…, rozdzielonÄ… przecinkami. Najlepiej używaj krótkich wyrażeÅ„ (jedno sÅ‚owo). Ogólna reguÅ‚a: wpisuj zainteresowania tak, by można je byÅ‚o wstawić w zdanie "LubiÄ™ _______" (Lub "I like _______", jeÅ›li piszesz po angielsku). OdnoszÄ…c siÄ™ do rzeczowników, używaj dla jednorodnoÅ›ci form liczby mnogiej, np. "LubiÄ™ komputery", a nie "LubiÄ™ komputer". + +/editinfo.bml.int.ex.bad=ZÅY PrzykÅ‚ad: LubiÄ™ mnóstwo zespołów, chodzić do kina i rozmawiać z przyjaciółmi i chodzić do pubów. To wszystko idzie do Twojej biografii. + +/editinfo.bml.int.ex.good=DOBRY PrzykÅ‚ad: rowery górskie, narty, komputery, dvd, mp3, ser, kobiety + +/editinfo.bml.int.header=Zainteresowania + +/editinfo.bml.login.enterinfo=Wpisz swojÄ… nazwÄ™ użytkownika i hasÅ‚o aby zmodyfikować swoje informacje osobiste. + +/editinfo.bml.login.forgot.header=ZapomniaÅ‚aÅ›/eÅ› czegoÅ›? + +/editinfo.bml.login.forgot.recover=JeÅ›li zapomniaÅ‚aÅ›/eÅ› nazwy użytkownika lub hasÅ‚a, odzyskaj je tutaj!. + +/editinfo.bml.logip.always=Zawsze + +/editinfo.bml.logip.anon_only=Tylko anonimowych komentatorów + +/editinfo.bml.logip.header=Logować adresy IP osób komentujÄ…cych? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=JeÅ›li boisz siÄ™, że roboty zbierajÄ…ce masowo maile znajdÄ… Twój adres na LiveJournal (i bÄ™dziesz dostawać spam), zaznacz tÄ™ opcjÄ™, a Twój adres e-mail zostanie zmodyfikowany tak, aby nie mógÅ‚ zostać odnaleziony przez roboty. + +/editinfo.bml.mangleaddress.header=Pomieszaj pokazywany adres e-mail + +/editinfo.bml.name.title=ImiÄ™ + +/editinfo.bml.newemail.subject=Zmieniony Adres Email + +/editinfo.bml.numcomments.about=Zaznacz tÄ™ opcjÄ™, jeżeli chcesz dodać liczbÄ™ komentarzy do URLi tak, aby Twoja przeglÄ…darka mogÅ‚a pokazywać linki w innym kolorze. + +/editinfo.bml.numcomments.header=Dodaj &nc=xx do URLi komentarzy + +/editinfo.bml.optional=Opcjonalne + +/editinfo.bml.opt_in.about<< +JeÅ›li chcesz być informowana/y, gdy dodamy jakiÄ…Å› fajnÄ… nowÄ… opcjÄ™ do LiveJournal, zaznacz tÄ™ kratkÄ™. +Maile te nie bÄ™dÄ… przychodziÅ‚y zbyt czÄ™sto, zwykle nie częściej niż raz lub dwa razy w miesiÄ…cu. +Twój adres e-mail nie bÄ™dzie widoczny dla innych użytkowników, możesz też wyÅ‚Ä…czyć tÄ™ opcjÄ™ w dowolnym momencie. +. + +/editinfo.bml.opt_in.header=WysyÅ‚ajcie mi nowinki o LiveJournal. + +/editinfo.bml.persinfo.disclaimer=Wpisz trochÄ™ informacji o sobie, dla zaspokojenia naszej ciekawoÅ›ci i dla celów statystycznych. Nie zrobimy z tymi informacjami nic zÅ‚ego ani wkurzajÄ…cego, chcelibyÅ›my jedynie wiedzieć, kim sÄ… nasi użytkownicy. Prosimy o poprawne wypeÅ‚nianie. JeÅ›li siÄ™ tym martwisz, możesz przeczytać o naszej polityce przywatnoÅ›ci. + +/editinfo.bml.persinfo.header=Dane Osobiste + +/editinfo.bml.screen.all=Wszystkie + +/editinfo.bml.screen.anon=Anonimowe + +/editinfo.bml.screen.header=Które odpowiedzi majÄ… być domyÅ›lnie monitorowane? + +/editinfo.bml.screen.none=Å»adne + +/editinfo.bml.screen.nonfriends=Od nie-przyjaciół + +/editinfo.bml.screen.nonmembers=Od nie-użytkowników + +/editinfo.bml.security.header=Kto może oglÄ…dać Twoje informacje kontaktowe? + +/editinfo.bml.security.visibility.anybody=Każdy + +/editinfo.bml.security.visibility.everybody=Wszyscy + +/editinfo.bml.security.visibility.friends=Tylko przyjaciele + +/editinfo.bml.security.visibility.regusers=Zarejestrowani Użytkownicy + +/editinfo.bml.settings.friendspage.title=TytuÅ‚ Strony Przyjaciół: + +/editinfo.bml.settings.friendspage.title.optional=Opcjonalnie podaj tytuÅ‚ dla swojej strony przyjaciół. (bez HTML) + +/editinfo.bml.settings.header=Opcje LiveJournal + +/editinfo.bml.settings.journal.subtitle=PodtytuÅ‚ Dziennika: + +/editinfo.bml.settings.journal.subtitle.optional=Opcjonalnie podaj tytuÅ‚ i podtytuÅ‚ dla swojego dziennika. (bez HTML) + +/editinfo.bml.settings.journal.title=TytuÅ‚ Dziennika: + +/editinfo.bml.settings.privacy.about=Poniżej wybierz swoje osobiste ustawienia prywatnoÅ›ci i preferencje. + +/editinfo.bml.settings.privacy.header=Opcje PrywatnoÅ›ci + +/editinfo.bml.state.other=Alternatywnie, wpisz inny stan/prowincjÄ™/terytorium + +/editinfo.bml.state.title=Stan + +/editinfo.bml.state.us=Stany USA + +/editinfo.bml.stylemine.about=Zaznacz tÄ™ opcjÄ™, jeÅ›li chcesz widzieć strone z komentarzami w stylu swojego dziennika, gdy klikasz na linki ze swojej strony przyjaciół. + +/editinfo.bml.stylemine.header=Pokazywać strony z komentarzami w stylu Twojego dziennika? + +/editinfo.bml.success.header=Sukces! + +/editinfo.bml.success.message=Twoje informacje i ustawienia dziennika oraz profil zostaÅ‚y uaktualnione. + +/editinfo.bml.switch.button=PrzeÅ‚Ä…cz + +/editinfo.bml.switch.header=PrzeÅ‚Ä…cz Dziennik + +/editinfo.bml.switch.workwith=Pracuj z dziennikiem: + +/editinfo.bml.title=Edytuj Osobiste Informacje + +/editinfo.bml.tm.details=szczegóły + +/editinfo.bml.tm.phonenum=PeÅ‚ny numer telefonu: + +/editinfo.bml.tm.sec.about=Pozwól innym użytkownikom wysyÅ‚ać Ci wiadomoÅ›ci tekstowe. + +/editinfo.bml.tm.sec.title=Poziom ZabezpieczeÅ„: + +/editinfo.bml.tm.servprov=UsÅ‚ugodawca + +/editinfo.bml.tm.title=WiadomoÅ›ci Tekstowe + +/editinfo.bml.translatemailto.about=JeÅ›li wybierzesz opcjÄ™ otrzymywania powiadomieÅ„ o komentarzach pocztÄ… e-mail, a Twój klient poczty nie obsÅ‚uguje za dobrze wiadomuÅ›ci w Unicode (UTF-8), skorzystaj z tej opcji i wybierz inne kodowanie, na które LiveJournal automatycznie przetÅ‚umaczy tekst wysyÅ‚anych do Ciebie komentarzy. + +/editinfo.bml.translatemailto.header=PrzetÅ‚umacz zawiadomienia e-mail na: + +/editinfo.bml.unbanusers.about=Poniższi użytkownicy majÄ… zakaz zamieszczania wpisów w Twoim dzienniku. Zaznacz okienko przy ich nazwie użytkownika, aby przywrócić im tÄ™ możliwość. + +/editinfo.bml.unbanusers.header=Odbanuj Użytkowników + +/editinfo.bml.userpic.about=Poniżej znajduje siÄ™ zaÅ‚adowany przez Ciebie, maÅ‚y obrazek, reprezentujÄ…cy CiÄ™ na LiveJournal, na Twojej strone i na stronach Twoich przyjaciół: + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Aby usunąć ten obrazek, lub zaÅ‚adować nowy, wejdź tutaj. + +/editinfo.bml.userpic.header=Twój Obrazek + +/editinfo.bml.userpic.none=brak zaÅ‚adowanych obnrazków + +/editinfo.bml.weblogscom.about=Zaznacz tÄ™ opcjÄ™, jeÅ›li chcesz, by Weblogs.com umieszczaÅ‚ Twój dziennik na swojej liÅ›cie, kiedy zamieÅ›cisz nowy wpis publiczny. + +/editinfo.bml.weblogscom.header=Zawiadamiaj Weblogs.com o wpisach + +/editinfo.bml.webpagename.title=Nazwa Strony + +/editinfo.bml.webpageurl.title=Adres Strony + +/editinfo.bml.whoreply.header=Kto może odpowiadać na Twoje wpisy? + +/editinfo.bml.zip.title=Kod pocztowy + +/editinfo.bml.zip.usonly=5-znakowy kod pocztowy; tylko dla mieszkaÅ„ców USA + +/editjournal.bml.btn.proceed=Kontynuuj... + +/editjournal.bml.certainday=Konkretny DzieÅ„: + +/editjournal.bml.desc=Skorzystaj z poniższego formularza, by odnaleźć wpis, który chcesz edytować. + +/editjournal.bml.in=W grupie: + +/editjournal.bml.recententries=ostatnich wpisów + +/editjournal.bml.recententry=Ostatni wpis + +/editjournal.bml.title=Edytuj Wpisy do Dziennika + +/editjournal.bml.viewwhat=Które Wpisy Pokazać: + +/editjournal_do.bml.body=Edytuj pola Twojego wpisu do dziennika, które chcesz zmienić, i zapisz zmiany klikajÄ…c na przycisk u doÅ‚u strony. Możesz też usunąć caÅ‚y wpis klikajÄ…c przycisk "UsuÅ„". + +/editjournal_do.bml.btn.delete=UsuÅ„ Wpis do Dziennika + +/editjournal_do.bml.btn.edit=Edytuj Wybrany Wpis + +/editjournal_do.bml.btn.preview=PodglÄ…d Wpisu + +/editjournal_do.bml.btn.save=Zapisz + +/editjournal_do.bml.continue.head=WciÅ›nij, by kontunuować... + +/editjournal_do.bml.continue.text=Gdy wybierzesz element do edycji, wciÅ›nij przycisk poniżej. + +/editjournal_do.bml.currmood=Obecny Nastrój: + +/editjournal_do.bml.currmusic=Obecna Muzyka: + +/editjournal_do.bml.date=Data: + +/editjournal_do.bml.default=domyÅ›lny + +/editjournal_do.bml.delete.confirm=Czy na pewno chcesz usunąć ten wpis? + +/editjournal_do.bml.edit.text=To jest wpis do dziennika, który wybraÅ‚aÅ›/eÅ› do edytowania. Wprowadź swoje zmiany i kliknij przycisk "Zapisz" u doÅ‚u strony.

          Aby usunąć wpis, skasuj cały tekst z pola wpisu i kliknij "Zapisz". + +/editjournal_do.bml.error.getting=Pojawił się błąd podczas sprowadzania wpisów do edycji: + +/editjournal_do.bml.error.modify=Podczas modyfikowania Twojego dziennika pojawił się błąd: + +/editjournal_do.bml.error.nofind=Wybrany wpis nie został znaleziony. + +/editjournal_do.bml.event=Wydarzenie: + +/editjournal_do.bml.localtime=Lokalny Czas: + +/editjournal_do.bml.noneother=Żaden, lub inny: + +/editjournal_do.bml.opt.backdate=Wpis datowany wstecz: + +/editjournal_do.bml.opt.backdate.about=nie pokaże się na stronie przyjaciół + +/editjournal_do.bml.opt.nocomments=Wyłącz Komentarze: + +/editjournal_do.bml.opt.noemail=Nie e-mailuj Komentarzy: + +/editjournal_do.bml.opt.noformat=Nie autoformatuj: + +/editjournal_do.bml.other=Inny: + +/editjournal_do.bml.pickentry.head=Wybierz wpis, który chcesz edytować + +/editjournal_do.bml.pickentry.text=Wybierz element, który chcesz edytować i wciśnij przycisk na dole strony. + +/editjournal_do.bml.picture=Użyj obrazka: + +/editjournal_do.bml.preview.header=Podgląd Wpisu + +/editjournal_do.bml.save.head=Wciśnij, aby zachować... + +/editjournal_do.bml.save.text=Kiedy skończysz edytować swój wpis, wciśnij Zachowaj. + +/editjournal_do.bml.subject=Temat: (opcjonalny) + +/editjournal_do.bml.success.delete=Wpis został usunięty. + +/editjournal_do.bml.success.edit=Wpis został zmodyfikowany. Możesz go zobaczyć tutaj. + +/editjournal_do.bml.success.head=Sukces + +/editjournal_do.bml.timeformat=24-godzinny czas + +/editjournal_do.bml.title=Edytuj Wpisy do Dziennika + +/editpics.bml.btn.proceed=Kontunuuj + +/editpics.bml.btn.save=Zapisz Zmiany + +/editpics.bml.curpics=Obecne Obrazki + +/editpics.bml.curpics.desc=Oto obrazki, które załadowałaś/eś w przeszłości. Możesz do nich przypisać słowa kluczowe, by móc ich potem według nich używać, możesz też wybrać obrazek domyślny lub kasować stare obrazki. Aby załadować nowy obrazek, skorzystaj z formularza u dołu strony. + +/editpics.bml.error.badurl=Adres obrazka, który ma zostać załadowany, nie wygląda poprawnie. Powinien zaczynać się od http:// + +/editpics.bml.error.filetoolarge=Obrazek jest zbyt duży. Rozmiar pliku nie może przekraczać [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Rozmiary Twojego obrazka ([[imagesize]]) przekraczają dopuszczalną wielkość. Twój obrazek może mieć nie więcej niż 100x100 pikseli wielkości. Użyj programu do edycji zdjęć/obrazków, by zmniejszyć rozmiary swojego obrazka. + +/editpics.bml.error.invalidimage=Niepoprawny plik graficzny. + +/editpics.bml.error.keywords=Użyłaś/eś słowa kluczowego "[[ekw]]" dla więcej niż jednego obrazka. Jeden z nich został wybrany losowo, ale możliwe, że nie ten, który chciałaś/eś. Możesz się cofnąć i to poprawić. + +/editpics.bml.error.toomanypics2=Masz już maksymalną dla siebie liczbę [[maxpics]] obrazków. Nie możesz załadować tego obrazka, póki nie usuniesz któregoś z już załadowanych. + +/editpics.bml.error.unsupportedtype=Pliki typu [[filetype]] nie są akceptowane. Możesz załadować wyłącznie pliki GIF, PNG lub JPG. Niemal wszystkie programy do edycji zdjęć/obrazków mogą Ci pomóc przekonwertować ten obrazek do właściwego formatu pliku. + +/editpics.bml.error.urlerror=Pojawił się błąd podczas próby załadowania Twojego obrazka. + +/editpics.bml.fromfile=Z Pliku: + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=k + +/editpics.bml.fromurl=Z adresu URL: + +/editpics.bml.kilobytes=kb + +/editpics.bml.label.default=Domyślny: + +/editpics.bml.label.delete=Usuń: + +/editpics.bml.label.keywords=Słowa kluczowe: + +/editpics.bml.makedefault=Wybierz ten obrazek jako domyślny + +/editpics.bml.nodefault=Bez Domyślnego Obrazka + +/editpics.bml.noneupload=Nie masz załadowanych obrazków. Aby załadować obrazek, skorzystaj z poniższego formularza. + +/editpics.bml.nopics=Brak Obrazków + +/editpics.bml.restriction.fileformat=Plik musi być formatu PNG, GIF lub JPG + +/editpics.bml.restriction.filesize=Rozmiar pliku nie może przekraczać 40kb + +/editpics.bml.restriction.imagesize=Wymiary obrazka nie mogą przekraczać 100x100 pikseli + +/editpics.bml.title=Edytuj Obrazki Użytkownika + +/editpics.bml.uploaddesc=Skorzystaj z poniższego formularza, aby załadować nowy obrazek. + +/editpics.bml.uploadheader=Załaduj Nowy Obrazek + +/export.bml.btn.proceed=Kontynuuj... + +/export.bml.description=Ta strona umożliwia Ci ściągnięcie całego Twojego dziennika jako kopii zapasowej. Po więcej informacji na temat tworzenia kopii zapasowej, wejdź tutaj. + +/export.bml.fields=Pola: + +/export.bml.label.encoding=Kodowanie: + +/export.bml.label.field.allowmask=Dopuść Maskę + +/export.bml.label.field.currents=Obecny Nastrój i Muzyka + +/export.bml.label.field.event=Wydarzenie + +/export.bml.label.field.eventtime=Czas Wydarzenia (z zegara użytkownika) + +/export.bml.label.field.itemid=Numer Identyfikacyjny + +/export.bml.label.field.logtime=Czas Zamieszczenia (z zegara systemu) + +/export.bml.label.field.security=Poziom Zabezpieczeń + +/export.bml.label.field.subject=Temat + +/export.bml.label.format=Format: + +/export.bml.label.header=Nagłówek + +/export.bml.label.month=Wybierz miesiąc: + +/export.bml.label.month.year=rrrr: + +/export.bml.label.notranslation=Nie tłumacz pomiędzy kodowaniami + +/export.bml.label.what=Eksportować: + +/export.bml.title=Eksportuj Dziennik + +/export.bml.what.entries=Wpisy do dziennika + +/export_do.bml.error.encoding=Wybrano niewłaściwe kodowanie + +/friends/add.bml.add.header=Sukces + +/friends/add.bml.add.text=Użytkownik [[user]] został dodany do Twojej listy przyjaciół. Możesz zobaczyć swoją stronę przyjaciół tutaj. + +/friends/add.bml.add.title=Przyjaciel Dodany! + +/friends/add.bml.btn.add=Dodaj [[user]] + +/friends/add.bml.btn.modify=Modyfikuj + +/friends/add.bml.btn.remove=Usuń + +/friends/add.bml.colors.bg=Tło + +/friends/add.bml.colors.fg=Pierwszy Plan + +/friends/add.bml.colors.header=Kolory + +/friends/add.bml.colors.hover=(Najedź myszką na kolor, aby zobaczyć jego nazwę) + +/friends/add.bml.colors.text=Opcjonalnie możesz wybrać kolory, które będą reprezentować [[user]] na Twojej liście przyjaciół. + +/friends/add.bml.confirm.header=Dodać [[user]] do listy przyjaciół? + +/friends/add.bml.confirm.text=Aby dodać [[user]] do swojej listy przyjaciół, kliknij przycisk poniżej. + +/friends/add.bml.confirm.title=Dodaj Przyjaciela + +/friends/add.bml.error1.header=Najpierw się Zaloguj + +/friends/add.bml.error1.text=Aby dodać użytkownika do swojej listy przyjaciół, musisz się najpierw zalogować. Jeśli jeszcze nie posiadasz konta na LiveJournal, możesz je stworzyć tutaj, aby móc czytać wpisy swoich przyjaciół z własnej strony przyjaciół. + +/friends/add.bml.error1.title=Dodaj Przyjaciela + +/friends/add.bml.error2.text=Niepoprawna lub nieistniejąca nazwa użytkownika. Aby dodać przyjaciela, wejdź na stronę edycji przyjaciół. + +/friends/add.bml.error3.text=Użytkownik [[user]] znajduje się już na Twojej liście przyjaciół. Możesz tutaj zmienić reprezentujące go kolory. + +/friends/add.bml.error3.title=Modyfikuj Przyjaciela + +/friends/add.bml.groups.header=Grupy Przyjaciół + +/friends/add.bml.groups.nogroup=Nie ma ustawionych grup przyjaciół. + +/friends/add.bml.groups.text=W jakich grupach przyjaciół chcesz umieścić tego użytkownika? Grupy przyjaciół służą do filtrowania Twojego widoku przyjaciół oraz umożliwiają Ci kontrolę nad tym, którzy użytkonicy mogą czytać dane wpisy do Twojego dziennika. + +/friends/add.bml.remove.header=Sukces + +/friends/add.bml.remove.text=Użytkownik został usunięty z Twojej listy przyjaciół. Możesz zobaczyć swoją stronę przyjaciół tutaj. + +/friends/add.bml.remove.title=Przyjaciel Usunięty! + +/friends/edit.bml.title=Edytuj Przyjaciół + +/friends/editgroups.bml.btn.ge.del=Usuń + +/friends/editgroups.bml.btn.ge.new=Nowa + +/friends/editgroups.bml.btn.ge.ren=Zmień nazwę + +/friends/editgroups.bml.btn.gs.private=Prywatna + +/friends/editgroups.bml.btn.gs.public=Publiczna + +/friends/editgroups.bml.btn.mv.down=Przesuń w dół + +/friends/editgroups.bml.btn.mv.up=Przesuń w górę + +/friends/editgroups.bml.confirm.delete=Czy na pewno chcesz usunąć tę grupę przyjaciół? + +/friends/editgroups.bml.done.btn=Zapisz Zmiany + +/friends/editgroups.bml.done.header=Gotowe? + +/friends/editgroups.bml.done.text=Kiedy skończysz, wciśnij poniższy przycisk, by zapisać zmiany. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Masz już maksymalną ilość 30 możliwych grup przyjaciół. Jeśli usunęłaś/usunąłeś jedną lub więcej grup, ale jeszcze nie zapisałaś/eś zmian, zrób to teraz, a potem wróć na tę stronę i przeładuj ją. Będziesz mieć wtedy możliwość tworzenia nowych grup przyjaciół. + +/friends/editgroups.bml.error.text=Serwer zgłosił następujący błąd: + +/friends/editgroups.bml.group.public=(publiczna) + +/friends/editgroups.bml.ingroup=W grupie: + +/friends/editgroups.bml.ingroup.not=Nie w grupie: + +/friends/editgroups.bml.prompt.newname=Podaj nazwę dla nowej grupy przyjaciół: + +/friends/editgroups.bml.prompt.rename=Zmień nazwę tej grupy przyjaciół na: + +/friends/editgroups.bml.saved.header=Zapisane + +/friends/editgroups.bml.saved.text=Twoje grupy przyjaciół zostały zapisane. + +/friends/editgroups.bml.text<< +Ta strona pozwala Ci edytować swoje grupy przyjaciół. Grupy przyjaciół są używane do ustawiania zabezpieczeń dla wpisów lub do filtrowania strony przyjaciół.Jeśli potrzebujesz pomocy z grupami przyjaciół, wejdź tutaj. + +Aby ta strona działała, potrzebny jest JavaScrpit. +. + +/friends/editgroups.bml.text.sec=Uwaga odnośnie bezpieczeństwa: Jeśli chcesz usunąć grupę i utworzyć nową, nie rób tego po prostu zmieniając nazwę istniejącej grupy i edytując jej. Jeśli tak zrobisz, wszystkie Twoje dawne wpisy zrobione dla starej grupy będą dostępne dla użytkowników z nowej grupy. + +/friends/editgroups.bml.title=Edytuj Grupy Przyjaciół + +/friends/editgroups.bml.yourgroups=Twoje grupy przyjaciół: + +/friends/edit_do.bml.addfriends.head=Dodaj Przyjaciół + +/friends/edit_do.bml.addfriends.text=Wpisz nazwy użytkowników Twoich przyjaciół na LiveJournal w poniższe pola i wybierz, jakie kolory pierwszego planu i tła mają być z nimi związane... + +/friends/edit_do.bml.background=Tło + +/friends/edit_do.bml.bgcolor=Kolor Tła: + +/friends/edit_do.bml.btn.close=Zamknij + +/friends/edit_do.bml.btn.save=Zapisz Zmiany + +/friends/edit_do.bml.btn.toggle=Przełącz Okno Podglądu + +/friends/edit_do.bml.done.head=Gotowe? + +/friends/edit_do.bml.done.text=Kiedy skończysz, wciśnij przycisk poniżej... + +/friends/edit_do.bml.error.updating=Podczas uaktualniania Twojej listy przyjaciół pojawił się błąd: + +/friends/edit_do.bml.fellowfriends.head=Przyjaciele + +/friends/edit_do.bml.fellowfriends.text=Te osoby dodały Cię do swojej listy przyjaciół... Być może też zechcesz dodać ich do swojej listy. Ten spis to tylko podpowiedź dla Ciebie, nie masz żadnego obowiązku, aby dodawać te osoby do swojej listy. + +/friends/edit_do.bml.foreground=Pierwszy Plan + +/friends/edit_do.bml.friend=Przyjaciel + +/friends/edit_do.bml.hover=Najedź myszką na kolor, by zobaczyć jego nazwę + +/friends/edit_do.bml.mrcolor=Pan Wyświetlacz Kolorów + +/friends/edit_do.bml.name=Imię/Ksywka + +/friends/edit_do.bml.needmore=Jeśli chcesz dodać więcej przyjaciół niż jest miejsca na formularzu, zapisz zmiany i wróć na tę stronę jeszcze raz, aby dodać pozostałych. + +/friends/edit_do.bml.nofriends.head=Brak Przyjaciół? + +/friends/edit_do.bml.nofriends.text=Nie masz zdefiniowanych żadnych przyjaciół. Jesteśmy jednak pewni, że masz kilku! :) Poprostu wpisz ich LiveJournalowe imiona poniżej... + +/friends/edit_do.bml.opt.addtolist=Dodaj przyjaciela + +/friends/edit_do.bml.opt.delete=Usunąć? + +/friends/edit_do.bml.success.head=Sukces + +/friends/edit_do.bml.success.text=Twoja lista przyjaciół została uaktualniona. Możesz zobaczyć swoją uaktualnioną stronę przyjaciół tutaj. + +/friends/edit_do.bml.textcolor=Kolor Tekstu: + +/friends/edit_do.bml.title=Edytuj Przyjaciół + +/friends/edit_do.bml.user=Użytkownik + +/friends/edit_do.bml.viewer=Wyświetlacz Kolorów + +/friends/edit_do.bml.yourfriends.head=Twoi Przyjaciele + +/friends/edit_do.bml.yourfriends.text=Masz zdefiniowanych następujących przyjaciół: + +/friends/filter.bml.editgroups=Jeśli chcesz edytować swoje grupy przyjaciół, wejdź na stronę [[link]]. + +/friends/filter.bml.error.nogroups=Nie możesz filtrować strony przyjaciół, zanim nie stworzysz grup przyjaciół. + +/friends/filter.bml.error.nogroups.header=Brak Zdefiniowanych Grup + +/friends/filter.bml.reset=Wyczyść + +/friends/filter.bml.select=Zaznacz grupę/y przyjaciół, których dzienniki chcesz oglądać ze swojej strony przyjaciół. + +/friends/filter.bml.select.header=Wybierz Grupy + +/friends/filter.bml.submit=Zobacz! + +/friends/filter.bml.title=Filtr Przyjaciół + +/friends/index.bml.about<< +Ta strona pozwala Ci zarządzać swoją listą przyjaciół. +Dodając innych użytkowników do swojej listy przyjaciół, możesz w prosty sposób śledzić ich wpisy do dziennika ze swojej strony przyjaciół. Możesz do swojej listy przyjaciół dodawać także dzienniki grup oraz stron zrzeszonych, by czytać ich wpisy ze swojej strony przyaciół. +. + +/friends/index.bml.edit.about=Dodawaj lub usuwaj użytkowników ze swojej listy przyjaciół lub edytuj przypisane im kolory. + +/friends/index.bml.editgroups.about=Twórz, edytuj lub usuwaj podgrupy swojej listy przyjaciół. + +/friends/index.bml.filter=Poniższe grupy przyjaciół mogą zostać użyte do filtrowania Twojej strony przyjaciół: możesz wybrać grupę, której wpisy chcesz zobaczyć. Grupy mogą być też wykorzystywane do ustawiania zabezpieczeń przy wpisach (zobacz poniżej). + +/friends/index.bml.filter.about=Filtruj swoją stronę przyjaciół w oparciu o podgrupy. + +/friends/index.bml.groups=Dodatkowo możesz ustawić podgrupy przyjaciół. + +/friends/index.bml.security=Twoja lista przyjaciół służy też do tworzenia wpisów z ograniczonym dostępem. Możesz dowiedzieć się więcej o liście przyjaciół i zabezpieczeniach na Przyjaciele i Poziomy Zabezpieczeń. + +/friends/index.bml.security.custom=Przy wpisach z własnymi ustawieniami bezpieczeńswa możesz wybrać, która z grup Twoich przyjaciół może zobaczyć Twój wpis. Niestety nie wszystkie klienty obsługują tę opcję. + +/friends/index.bml.security.header=Bezpieczeństwo + +/friends/index.bml.security.only=Przy ustawieniu "Tylko dla Przyjaciół" wszyscy użytkownicy z Twojej listy przyjaciół mogą czytać Twój wpis. + +/friends/index.bml.title=Narzędzia Przyjaciół + +/friends/index.bml.tools=Narzędzia + +/friends/popwithfriends.bml.account_type=Przykro nam, Twój typ konta nie zezwala na korzystanie z tego narzędzia. + +/friends/popwithfriends.bml.count=Licznik + +/friends/popwithfriends.bml.exclude_own=Opcjonalnie, możesz nie brać pod uwagę swoich przyjaciół. + +/friends/popwithfriends.bml.include_own=Opcjonalnie, możesz wziąć pod uwagę swoich przyjaciół. + +/friends/popwithfriends.bml.intro=Poniżsi użytkownicy są często na listach przyjaciół Twoich przyjaciół, ale nie na Twojej. + +/friends/popwithfriends.bml.intro_own=Poniżsi użytkownicy są często na listach przyjaciół Twoich przyjaciół. Ta lista bierze pod uwagę także Twoich przyjaciół. + +/friends/popwithfriends.bml.no_users=Brak Użytkowników + +/friends/popwithfriends.bml.title=Użytkownicy Popularni Wśród Twoich Przyjaciół + +/friends/popwithfriends.bml.user=Użytkownik + +/go.bml.defaulttitle=Błąd + +/index.bml.about.header=O LiveJournal + +/index.bml.boldcreate=Utwórz swój własny LiveJournal! + +/index.bml.frank.image.alt=Frank, LiveJournalowy kozioł-maskotka. + +/index.bml.frank.logo="Beeeee!", powiada Frank. + +/index.bml.learnmore.header=Chcesz wiedzieć więcej? + +/index.bml.meta.desc=LiveJournal.com to miejsce, gdzie możesz dzielić się swoimi myślami ze światem. + +/index.bml.meta.keywords=pamiętnik, dziennik, internetowy dziennik, pisanie, blog, weblog + +/index.bml.post=Statystyki + +/index.bml.post.hour=Na godzinę: + +/index.bml.post.latest=Najświeższe Wpisy + +/index.bml.post.min=Na minutę: + +/interests.bml.add.added.head=Dodano! + +/interests.bml.add.added.text=Zainteresowanie zostało dodane do Twojej listy. + +/interests.bml.add.btn.text=Dodaj [[interest]] + +/interests.bml.add.confirm.head=Potwierdź + +/interests.bml.add.confirm.text=Aby dodać [[interest]] do listy zainteresowań, kliknij przycisk poniżej. + +/interests.bml.add.toomany.head=Przykro nam... + +/interests.bml.add.toomany.text=Masz już [[maxinterests]] zapisanych zainteresowań. + +/interests.bml.addint=Jeśli Ciebie również to interesuje i chcesz znaleźć się na tej liście, kliknij tutaj. + +/interests.bml.btn.switch=Przełącz + +/interests.bml.communities.head=Odpowiadające Grupy + +/interests.bml.communities.text=Następujące grupy również interesuje "[[interest]]". + +/interests.bml.count=Ilość + +/interests.bml.enmasse.body.other=Poniżej znajduje się lista zainteresowań użytkownika [[user]]. Zaznacz zainteresowania, które chcesz dodać do swojej własnej listy i odznacz te, które chcesz z niej usunąć. Kiedy skończysz, kliknij "Zapisz Zmiany". + +/interests.bml.enmasse.body.other_authas=Poniżej znajduje się lista zainteresowań użytkownika [[user]]. Zaznacz zainteresowania, które chcesz dodać do listy dziennika [[target]] i odznacz te, które chcesz z niej usunąć. Kiedy skończysz, kliknij "Zapisz Zmiany". + +/interests.bml.enmasse.body.you<< +Odznacz zainteresowania, które chcesz usunąć. +Kiedy skończysz, kliknij "Zapisz Zmiany". +. + +/interests.bml.enmasse.btn=Pokaż listę + +/interests.bml.enmasse.header=Dodawaj/Usuwaj zainteresowania + +/interests.bml.enmasse.intro=Modyfikuj swoje zainteresowanie na podstawie zainteresowań: + +/interests.bml.error.add.mustlogin=Musisz być zalogowany/a, aby dodać zainteresowanie w ten sposób. + +/interests.bml.error.enmasse.mustlogin=Musisz się zalogować, by móc korzystać z tego narzędzia. + +/interests.bml.error.enmasse.noaccess=Nie wydajesz się mieć dostępu do dziennika [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Zainteresowanie nie zostało znalezione. + +/interests.bml.error.nointerests=Wybrany użytkownik nie istnieje, lub istnieje, ale nie ma na swojej liście żadnych zainteresowań. + +/interests.bml.findsim.searchwait=Uwaga: wyszukiwanie potrwa kilka sekund. Cierpliwości. + +/interests.bml.findsim_do.account.notallowed=Przykro nam, ale Twój typ konta nie pozwala Ci na używanie tego narzędzia. + +/interests.bml.findsim_do.magic=Magiczna
          Liczba + +/interests.bml.findsim_do.magic.head=Magiczna Liczba? + +/interests.bml.findsim_do.magic.text=Każdemu pasującemu użytkownikowi przydzielona zostaje magiczna liczba, będąca średnią ważoną dwóch czynników: liczby pasujących zainteresowań i dodatkowych punktów za posiadanie tych samych rzadkich zainteresowań. + +/interests.bml.findsim_do.nomatch.head=Brak Pasujących Użytkowników + +/interests.bml.findsim_do.nomatch.text=Nie ma użytkowników podobnych do [[user]]. + +/interests.bml.findsim_do.notdefined=Użytkownik [[user]] nie ma zdefiniowanych zainteresowań. + +/interests.bml.findsim_do.similar.head=Podobni Użytkownicy + +/interests.bml.findsim_do.similar.text=Oto lista użytkowników najbadziej podobnych do [[user]] + +/interests.bml.finished.about=Kiedy skończysz, wciśnij przycisk "Zapisz Zmiany" poniżej: + +/interests.bml.finished.header=Gotowe? + +/interests.bml.finished.save_button=Zachowaj Zmiany + +/interests.bml.interest=Zainteresowanie + +/interests.bml.interested.btn.find=Znajdź + +/interests.bml.interested.in=Znajdź osoby i grupy z danym zainteresowaniem: + +/interests.bml.interests.findsim=Znajdź użytkowników o zainteresowaniach podobnych do zainteresowań użytkownika: + +/interests.bml.interests.head=Zainteresowania + +/interests.bml.interests.text=Oto kilka fajnych rzeczy, które można robić z zainteresowaniami. + +/interests.bml.interests.viewpop=Pokaż popularne zainteresowania + +/interests.bml.login.enterinfo=Podaj swoją nazwę użytkownika i hasło, aby modyfikować swoje zainteresowania. + +/interests.bml.login.proceed=Kontynuuj... + +/interests.bml.match=Liczba trafień: [[count]] + +/interests.bml.matches=Liczba trafień: [[count]] + +/interests.bml.morestuff=Więcej bajerków czeka na stronie zainteresowań. + +/interests.bml.nointerests.text=Nie masz na liście żadnych zainteresowań? Dodaj parę na Stronie Edycji Osobistych Informacji i Ustawień. + +/interests.bml.popular.head=Popularne Zainteresowania + +/interests.bml.popular.text=Oto najbardziej popularne zainteresowania. + +/interests.bml.results.added=Zaznaczone zainteresowania zostały dodane do Twojej listy zainteresowań. + +/interests.bml.results.both=Zaznaczone zainteresowania zostały dodane do Twojej listy zainteresowań, a te, które odznaczyłaś/eś, zostały z niej usunięte. + +/interests.bml.results.deleted=Odznaczone zainteresowania zostały usunięte z Twojej listy zainteresowań. + +/interests.bml.results.del_and_toomany=Odznaczone zainteresowania zostały usunięte z Twojej listy zainteresowań. Niestety, zaznaczyłaś/eś zbyt wiele zainteresowań do dodania. Możesz mieć na liście w sumie tylko [[intcount]] zainteresowań. Żadne z zaznaczonych zainteresowań nie zostało dodane do Twojej listy. Możesz cofnąć się i spróbować ponownie, zaznaczając mniejszą ilość zainteresowań do dodania. + +/interests.bml.results.goback=Możesz cofnąć się do profilu użytkownika [[user]], który wcześniej oglądałeś. + +/interests.bml.results.header=Wyniki + +/interests.bml.results.message=Zobacz swój uaktualniony profil użytkownika. + +/interests.bml.results.nothing=Nie dokonałaś/eś żadnych zmian. + +/interests.bml.results.toomany=Zaznaczyłaś/eś zbyt wiele zainteresowań do dodania. Możesz mieć w sumie tylko [[intcount]] zainteresowań. Żadne z zaznaczonych zainteresowań nie zostało dodane do Twojej listy. Możesz cofnąć się i spróbować ponownie, zaznaczając mniejszą ilość zainteresowań do dodania. + +/interests.bml.title=Zainteresowania + +/interests.bml.toomany.body=[[intcount]] osób i grup dzieli to zainteresowanie. Lista nie zostanie pokazana. + +/interests.bml.toomany.head=Wiele trafień + +/interests.bml.users.head=Zainteresowani użytkownicy + +/interests.bml.users.text=Następujący użytkownicy mają na liście swoich zainteresowań [[interest]]. + +/invite/index.bml.code=Kod + +/invite/index.bml.error=Błąd + +/invite/index.bml.genmore=Generuj więcej kodów + +/invite/index.bml.how_detail=W oparciu o pewne czynniki, istniejący użytkownicy mogą zaprosić pewną ilość osób do przyłączenia się do naszej strony. Aby kogoś zaprosić, musisz wygenerować kod zaproszenie i przekazać go danej osobie. + +/invite/index.bml.how_header=Jak to działa? + +/invite/index.bml.invite_header=Zaproszenia? + +/invite/index.bml.none=Brak + +/invite/index.bml.redeemed=Wykorzystany przez + +/invite/index.bml.title=Zapraszaj innych na LiveJournal... + +/invite/index.bml.unused=Niewykorzystany + +/invite/index.bml.use=użyj + +/legal/index.bml.about<< +LiveJournal jest poświęcony oferowaniu stabilnych i terściwych usług członkom ze wszystkich grup społecznych i narodów, więc mamy kilka zasad, które ustaliliśmy, aby to było możliwe. Poniższe dokumenty zawierają rozsądne warunki i informacje dotyczące tego, co zamierzamy robić dla Twojego dobra i jakich postaw spodziewamy się po użytkownikach w stosunku do nas i do innych osób. LiveJournal funkcjonuje najlepiej, gdy członkowie przestrzegają tych zasad. Oto najważniejsze z nich: +
            +
          • Nie przeÅ›laduj i nie wykorzystuj innych; nie groź nikomu.
          • +
          • Nie krzywdź w żaden sposób niepeÅ‚noletnich.
          • +
          • Nie spamuj naszej strony, ani żadnego z kont.
          • +
          • Nie zamieszczaj materiaÅ‚u chronionego prawem autorskim bez zgody autora.
          • +
          • Nie Å‚am zasad prywatnoÅ›ci innych użytkowników.
          • +
          • Nie Å‚am w żaden sposób prawa USA ani swoich praw lokalnych.
          • +
          +PeÅ‚na lista reguÅ‚ znajduje siÄ™ poniżej: +. + +/legal/index.bml.about.header=Zasady Ogólne + +/legal/index.bml.docs.coppa.about=Akt Ochroniy Prywatnośći Dzieci w Internecie (COPPA) reguluje zbieranie i wykorzystywanie osobistych informacji podawanych przez i dotyczÄ…cych dzieci poniżej trzynastego roku życia. Nasza strona COPPA okreÅ›la naszÄ… postawÄ™ wobec tego prawa i wyjaÅ›nia, jak radzić sobie ze sprawami zwiÄ…zanymi z COPPA. + +/legal/index.bml.docs.header=Dokumenty + +/legal/index.bml.docs.privacy.about=Nasza Polityka PrywatnoÅ›ci okreÅ›la, jakie informacje zbieramy od naszych użytkowników i jak wykorzystujemy te informacje. + +/legal/index.bml.docs.tos.about=Zasady Użytkowania okreÅ›lajÄ… naszÄ… politykÄ™ wobec użytkowników a także generalne zasady i warunki czÅ‚onkowstwa. CzÅ‚onkowstwo i/lub korzystanie z naszych usÅ‚ug wymaga zgody na przestrzeganie tych zasad, jak i wszystkich pozostaÅ‚ych warunków użytkowania. + +/legal/index.bml.title=Informacje Prawne + +/legal/privacy.bml.title=Polityka PrywatnoÅ›ci + +/legal/tos.bml.title=Zasady Użytkowania + +/login.bml.bindip.label=Przypisz do adresu IP: + +/login.bml.bindip.no=Nie (dziaÅ‚a ze wszystkimi ISP) + +/login.bml.bindip.yes=Tak (bezpieczniejsza opcja) + +/login.bml.error.mustenterusername=Musisz podać nazwÄ™ użytkownika. + +/login.bml.expire.btn.neverexpire=Zaloguj NA STAÅE + +/login.bml.expire.btn.sessiononly=WYLOGUJ po zamkniÄ™ciu przeglÄ…darki + +/login.bml.expire.neverexpire.text=JesteÅ› zalogowana/y na staÅ‚e, wiÄ™c jeÅ›li korzystasz z Internetu w miejscu publicznym, w szkole, bibliotece, lub w innym miejscu, gdzie wkrótce po tobie inne osoby bÄ™dÄ… korzystać z tego komputera, koniecznie wyloguj siÄ™, gdy tylko skoÅ„czysz korzystać z LiveJournal! Możesz także wybrać opcjÄ™ automatycznego wylogowania po zamkniÄ™ciu przeglÄ…darki: + +/login.bml.expire.sessiononly.text=Zostaniesz wylogowana/y po zamkniÄ™ciu przeglÄ…darki. JeÅ›li korzystasz ze swojego wÅ‚asnego komputera i jesteÅ› jedynÄ… osobÄ…, która go używa, możesz bezpiecznie zalogować siÄ™ na staÅ‚e: + +/login.bml.links.head=Linki + +/login.bml.links.link1=Twoja strona przyjaciół. + +/login.bml.links.link2=Twoja lista rzeczy do zrobienia. + +/login.bml.links.text=W przyszÅ‚oÅ›ci ta strona zapeÅ‚ni siÄ™ wszelkiego rodzaju przydatnymi Å‚Ä…czami i informacjami, a na razie może zechcesz odwiedzić któreÅ› z tych miejsc: + +/login.bml.loggedin.head=Zalogowany/a! + +/login.bml.loggedin.text=JesteÅ› teraz zalogowany/a. + +/login.bml.login.btn.changeopts=ZmieÅ„ Ustawienia + +/login.bml.login.btn.login=Zaloguj siÄ™... + +/login.bml.login.expiration=WygaÅ›niÄ™cie: + +/login.bml.login.forget=Zapomniane hasÅ‚o? + +/login.bml.login.head=Zaloguj + +/login.bml.login.never=Nigdy + +/login.bml.login.otheropts=Inne Opcje: + +/login.bml.login.password=HasÅ‚o: + +/login.bml.login.text1=Aby siÄ™ zalogować na [[sitename]], wpisz poniżej swojÄ… nazwÄ™ użytkownika i hasÅ‚o. Do Nowych Użytkowników: Aby utworzyć nowe konto, wejdź tutaj. + +/login.bml.login.text2=Możesz również okreÅ›lić, kiedy wygasa Twój login. DomyÅ›lnie login wygasa, gdy zamykasz przeglÄ…darkÄ™. Jest to najlepsze rozwiÄ…zanie dla komputerów publicznych. Jeżeli jedak jesteÅ› jedynym użytkownikiem Twojego komputera i nikt inny nie ma do niego dostÄ™pu, możesz wybrać permanentne zalogowanie. Po wiÄ™cej informacji na temat tej i innych opcji logowania wejdź tutaj. + +/login.bml.login.username=Nazwa Użytkownika: + +/login.bml.login.whenbrowsercloses=Po zamkniÄ™ciu przeglÄ…darki + +/login.bml.logout.btn=Wyloguj SiÄ™ + +/login.bml.title=Logowanie + +/login.bml.whylogin.benefit1=Nie bÄ™dziesz musiaÅ‚/a podawać swojej nazwy użytkownika i hasÅ‚a już w żadnym innym miejscu na stronie. + +/login.bml.whylogin.benefit2=BÄ™dziesz móc oglÄ…dać "chronione" wpisy Twoich przyjaciół, gdy dadzÄ… Ci do nich dostÄ™p. + +/login.bml.whylogin.benefit3=Wiele opcji jest widocznych jedynie po zalogowaniu. + +/login.bml.whylogin.head=Po co siÄ™ logować? + +/login.bml.whylogin.text=Oto kilka zalet logowania siÄ™: + +/logout.bml.already.head=Już wylogowana/y + +/logout.bml.already.text=JesteÅ› już wylogowana/y. + +/logout.bml.killall.btn=ZakoÅ„cz wszystkie moje sesje + +/logout.bml.killall.head=Inne sesje + +/logout.bml.killall.text=Masz inne aktywne sesje. Czy chcesz zakoÅ„czyć wszystkie sesje poza obecnÄ…? (Zobacz to FAQ po wiÄ™cej informacji.) + +/logout.bml.loggedout.already=Już wylogowany. + +/logout.bml.loggedout.head=Wylogowana/y + +/logout.bml.loggedout.killedall=Wszystkie Twoje sesje zostaÅ‚y zakoÅ„czone. + +/logout.bml.loggedout.success=Wylogowany + +/logout.bml.loggedout.text=JesteÅ› teraz wylogowana/y. + +/logout.bml.logout.btn=Wyloguj siÄ™. + +/logout.bml.logout.head=Wylogować? + +/logout.bml.logout.text=Kliknij poniższy przycisk, by siÄ™ wylogować. + +/logout.bml.title=Wyloguj + +/lostinfo.bml.btn.proceed=Kontynuuj + +/lostinfo.bml.enter_email=Podaj swój adres e-mail: + +/lostinfo.bml.enter_email_optional=Adres e-mail: (opcjonalny) + +/lostinfo.bml.enter_username=Podaj swojÄ… nazwÄ™ użytkownika: + +/lostinfo.bml.error.no_email=Musisz podać adres email by móc odzyskać swojÄ… nazwÄ™ użytkownika. + +/lostinfo.bml.lostpassword.text=JeÅ›li zgubiÅ‚aÅ›/eÅ› hasÅ‚o, podaj swojÄ… nazwÄ™ użytkownika i - opcjonalnie - adres email, na który chcesz, abyÅ›my wysÅ‚ali hasÅ‚o. JeÅ›li chcesz, by hasÅ‚o zostaÅ‚o wysÅ‚ane na adres używany z kontem wczeÅ›niej, musi to być adres, który zostaÅ‚ potwierdzony. JeÅ›li pozostawisz pole e-mail puste, hasÅ‚o zostanie wysÅ‚ane na Twój obecny adres. + +/lostinfo.bml.lostpassword.title=Zagubione hasÅ‚o? + +/lostinfo.bml.lostusername.text=JeÅ›li zgubiÅ‚aÅ›/eÅ› swojÄ… nazwÄ™ użytkownika, wprowadź swój adres e-mail, a wyÅ›lemy Ci nazwÄ™ użytkownika. + +/lostinfo.bml.lostusername.title=Zagubiona nazwa użytkownika? + +/lostinfo.bml.title=Zagubione Informacje + +/lostinfo_do.bml.error.no_usernames_for_email=Brak nazw użytkownika dla adresu: [[address]] . + +/lostinfo_do.bml.error1.text=Nigdy nie użyto tego adresu e-mail z tym kontem, lub adres ten nigdy nie zostaÅ‚ potwierdzony. + +/lostinfo_do.bml.lostpasswordmail.part1|staleness=1 +/lostinfo_do.bml.lostpasswordmail.part1<< +*** To jest email wysyÅ‚any automatycznie. Nie musisz na niego odpowiadać. *** + +Oto przypominacz hasÅ‚a zamówiony przez Ciebie na [[sitename]]. +Poniżej znajduje siÄ™ Twoja nazwa użytkownika, hasÅ‚o i adres email, pod którym zarejestrowane jest Twoje konto. + + Nazwa użytkownika: [[username]] + HasÅ‚o: [[password]] + Adres Email: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Aby potwierdzić swój adres email, wejdź tutaj: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Te informacje zostaÅ‚y zamówione na naszej stronie z [[remoteip]]. + +JeÅ›li to nie Ty zamówiÅ‚aÅ›/eÅ› emaila z hasÅ‚em, nie panikuj. W koÅ„cu to do Ciebie dotarÅ‚ ten email, a nie do kogoÅ› innego. Możliwe, że użytkownik, który zamówiÅ‚ ten przypominacz, popeÅ‚niÅ‚ bÅ‚Ä…d i wierzy, że Twoja nazwa użytkownika należy do niego. Możliwe też, że ktoÅ› zrobiÅ‚ literówkÄ™ wpisujÄ…c swojÄ… nazwÄ™ użytkownika lub adres email. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +Jesli na prawdÄ™ uważasz, że Twoje konto nie jest bezpieczne, przeczytaj + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +by dowiedzieć ziÄ™, co możesz zrobić, by zwiÄ™kszyć bezpieczeÅ„stwo. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Przydatne Å‚Ä…cza: + + Twój LiveJournal: + [[journalurl]] + + Uaktualnij swój dziennik z sieci: + [[updateurl]] + +Pozdrowienia, +Zespół LiveJournal + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Zagubione hasÅ‚o + +/lostinfo_do.bml.password_mailed.text=Sukces. Twoje hasÅ‚o zostaÅ‚o wysÅ‚ane. + +/lostinfo_do.bml.password_mailed.title=HasÅ‚o wysÅ‚ane! + +/lostinfo_do.bml.title=Zagubione Informacje + +/lostinfo_do.bml.username_mailed.text=Sukces. Twoja nazwa użytkownika zostaÅ‚a wysÅ‚ana. + +/lostinfo_do.bml.username_mailed.title=Nazwa użytkownika wysÅ‚ana! + +/manage/index.bml.about=ZarzÄ…dzanie kontem jest proste. Po prostu wybierz to, co CiÄ™ interesuje, z poniższych kategorii. + +/manage/index.bml.communities=Utwórz wÅ‚asne grupy i zarzÄ…dzaj nimi: + +/manage/index.bml.communities.create.about=Utwórz nowÄ… grupÄ™ + +/manage/index.bml.communities.header=Grupy + +/manage/index.bml.communities.manage.about=ZarzÄ…dzaj ustawieniami swoich grup i ich czÅ‚onkami + +/manage/index.bml.customization=ZarzÄ…dzaj wyglÄ…dem swoich stron dziennika: + +/manage/index.bml.customization.advanced=Zaawansowana Zmiana WyglÄ…du Dziennika + +/manage/index.bml.customization.advanced.about=PrzeglÄ…daj, twórz i edytuj swoje ustawienia strony i style S2 + +/manage/index.bml.customization.customize=Zmiana WyglÄ…du Dziennika + +/manage/index.bml.customization.customize.about=ZmieÅ„ wyglÄ…d swojego dziennika + +/manage/index.bml.customization.header=Dostosowywanie WyglÄ…du Dziennika + +/manage/index.bml.customization.links=Lista Linków + +/manage/index.bml.customization.links.about=Utwórz listÄ™ linków, która ma siÄ™ pojawiać w Twoim dzienniku + +/manage/index.bml.customization.modify.about=Modyfikuj sposób wyÅ›wietlania Twojego dziennika + +/manage/index.bml.customization.s1.header=System Stylów S1 + +/manage/index.bml.customization.s2.header=System Stylów S2 + +/manage/index.bml.entries=Pracuj z wpisami w Twoim dzienniku: + +/manage/index.bml.entries.edit.about=Edytuj lub usuwaj swoje wpisy do dziennika + +/manage/index.bml.entries.header=Wpisy do Dziennika + +/manage/index.bml.entries.memories.about=PrzeglÄ…daj swoje wspomnienia i modyfikuj je + +/manage/index.bml.friends=ZarzÄ…dzaj swojÄ… listÄ… przyjaciół i grupami przyjaciół lub filtruj swojÄ… stronÄ™ przyjaciół przy pomocy grup: + +/manage/index.bml.friends.edit.about=Dodawaj lub usuwaj użytkowników ze swojej listy przyjaciół, lub zmieniaj reprezentujÄ…ce ich kolory. + +/manage/index.bml.friends.filter=Filtruj StronÄ™ Przyjaciół + +/manage/index.bml.friends.filter.about=Filtruj listÄ™ przyjaciół, by oglÄ…dać wpisy konkretnej grupy przyjaciół + +/manage/index.bml.friends.groups.about=Utwórz, edytuj lub usuwaj podgrupy swojej listy przyjaciół + +/manage/index.bml.friends.header=Przyjaciele + +/manage/index.bml.information=Wybierz, jakie informacje majÄ… pokazywać siÄ™ o Twoim koncie: + +/manage/index.bml.information.changepass=ZmieÅ„ HasÅ‚o Konta + +/manage/index.bml.information.changepass.about=ZmieÅ„ hasÅ‚o dostÄ™pu do Twojego konta + +/manage/index.bml.information.editinfo.about=Edytuj informacje o swoim koncie oraz różne opcje + +/manage/index.bml.information.emailpost=Ustawienia Bramki Email + +/manage/index.bml.information.emailpost.about=ZarzÄ…dzaj swoimi adresami email i PINem do zamieszczania przez email + +/manage/index.bml.information.header=Informacje o Koncie + +/manage/index.bml.information.siteopts.about=Wybierz preferowany ukÅ‚ad strony i jÄ™zyk + +/manage/index.bml.information.status=Status Konta + +/manage/index.bml.information.status.about=Ustaw status aktywnoÅ›ci swojego konta (skasuj lub przywróć swoje konto) + +/manage/index.bml.login=Poniższe linki zabiorÄ… CiÄ™ do stron, gdzie bÄ™dÄ… od Ciebie wymagane login i hasÅ‚o. Aby oszczÄ™dzić sobie czasu, możesz siÄ™ od razu zalogować. + +/manage/index.bml.title=ZarzÄ…dzaj Kontami + +/manage/index.bml.userpictures=ZaÅ‚aduj obrazki dla swojego konta i zarzÄ…dzaj nimi: + +/manage/index.bml.userpictures.edit.about=ZaÅ‚aduj Obrazki Użytkownika i ZarzÄ…dzaj Nimi + +/manage/index.bml.userpictures.header=Obrazki Użytkownika + +/manage/links.bml.about=Użyj poniższego formularza, aby utworzyć listÄ™ linków pojawiajÄ…cych siÄ™ w Twoim dzienniku. Linki pojawiÄ… siÄ™ tylko, jeÅ›li Twoj system stylów S2 ma takÄ… opcjÄ™. + +/manage/links.bml.about.blank=Aby utworzyć pustÄ… linijkÄ™, wpisz "-" w miejsce tytuÅ‚u. + +/manage/links.bml.about.heading=Aby utworzyć nagłówek, wpisz tytuÅ‚ bez adresu URL. + +/manage/links.bml.about.reorder=Aby zmienić kolejność linków na liÅ›cie, zmieÅ„ liczbÄ™ porzÄ…dkowÄ… po lewej (części dziesiÄ…te sÄ… w porzÄ…dku). + +/manage/links.bml.error.s2required=Lista linków jest dostÄ™pna tylko dla niektórych stylów systemu S2. Aby zmienić system stylów na S2, wejdź na stronÄ™ [[link]]. + +/manage/links.bml.error.s2required.header=Wymagany S2 + +/manage/links.bml.success=Sukces! Twoje linki zostaÅ‚y zapisane. + +/manage/links.bml.title=Lista Linków + +/manage/phonepost.bml.delete=UsuÅ„ Ustawienia + +/manage/phonepost.bml.error.inuse=NieprawidÅ‚owy PIN, spróbuj innego + +/manage/phonepost.bml.error.phone.length=Twój numer telefonu musi skÅ‚adać siÄ™ z conajmniej 10 cyfr. + +/manage/phonepost.bml.error.pin=Twój PIN musi skÅ‚adać siÄ™ z cyfr. + +/manage/phonepost.bml.phone=Autoryzowany Numer Telefonu: + +/manage/phonepost.bml.pin=Indywidualny Numer Identyfikacyjny PIN: + +/manage/phonepost.bml.pin.help=zalecane 4-6 znaków + +/manage/phonepost.bml.save=Zapisz Ustawienia + +/manage/phonepost.bml.saved=Zapisane + +/manage/phonepost.bml.success.text=Twoje ustawienia telefonu zostaÅ‚y zachowane. + +/manage/phonepost.bml.title=Ustawienia Zamieszczania Przez Telefon + +/manage/phonepost.bml.transcribers.help=Edytuj Grupy Przyjaciół + +/manage/pubkey.bml.successhead=Sukces + +/manage/siteopts.bml.btn.lang=PrzeÅ‚Ä…cz JÄ™zyk + +/manage/siteopts.bml.btn.scheme=PrzeÅ‚Ä…cz Schemat + +/manage/siteopts.bml.head.lang=Wybierz Swój JÄ™zyk + +/manage/siteopts.bml.head.scheme=Wybierz Preferowany Schemat + +/manage/siteopts.bml.title=PrzeglÄ…daj Preferencje + +/modify.bml.title=Modyfikuj Dziennik + +/modify_do.bml.availablestyles.head=DostÄ™pne Style + +/modify_do.bml.availablestyles.userstyles=Style Użytkownika: + +/modify_do.bml.colortheme.about=Tutaj możesz wybrać, jaki schemat kolorów zostanie zastosowany do powyższych opcji. JeÅ›li nie podobajÄ… Ci siÄ™ proponowane kolory, wybierz swoje wÅ‚asne! + +/modify_do.bml.colortheme.area.head=Obszar Użytkowy + +/modify_do.bml.colortheme.color.head1=Kolor + +/modify_do.bml.colortheme.color.head2=(#rrggbb lub nazwa) + +/modify_do.bml.colortheme.customcolors=WÅ‚asne Kolory + +/modify_do.bml.colortheme.defaulttheme=DomyÅ›lny Schemat + +/modify_do.bml.colortheme.head=Schemat Kolorów + +/modify_do.bml.domainalias.about=JeÅ›li zarejestrowaÅ‚aÅ›/eÅ› już wÅ‚asnÄ… domenÄ™ (lub planujesz to zrobić) i chcesz, aby automatycznie Å‚adowaÅ‚ siÄ™ z niej Twój LiveJournal, podaj jej nazwÄ™ tutaj: + +/modify_do.bml.domainalias.domainname=Nazwa domeny: + +/modify_do.bml.domainalias.example=PrzykÅ‚adowo: moj-dziennik.pl + +/modify_do.bml.domainalias.head=Aliasowanie Domen + +/modify_do.bml.domainalias.helptext|staleness=1 +/modify_do.bml.domainalias.helptext=Aby to zadziaÅ‚aÅ‚o, DNS nazwy Twojej domeny musi wskazywać na IP [[sitename]]. + +/modify_do.bml.done.btn.savechanges=Zapisz Zmiany + +/modify_do.bml.done.head=Zrobione? + +/modify_do.bml.done.text=Gdy skoÅ„czysz, wciÅ›nij przycisk poniżej... + +/modify_do.bml.error.dupdomainalias=Inny użytkownik już zarejestrowaÅ‚ siÄ™ pod tym aliasem. + +/modify_do.bml.error.stylenotavailable=Jeden z wybranych przez Ciebie stylów nie jest dostÄ™pny. Być może ktoÅ› go wÅ‚aÅ›nie wykasowaÅ‚, lub nie masz prawa dostÄ™pu do tego stylu. + +/modify_do.bml.friends.about=Te opcje sÅ‚użą do kontroli wyglÄ…du Twojej strony przyjaciół. + +/modify_do.bml.friends.head=Widok Przyjaciół + +/modify_do.bml.friends.opt.usesharedpic.about=Ta opcja pomaga Ci wybrać, jaki obrazek pokazuje siÄ™ na Twojej stronie przyjaciół, gdy ktoÅ› zamieszcza wpis w dzienniku grupy. JeÅ›li jÄ… zaznaczysz, bÄ™dziesz widzieć domyÅ›lnÄ… ikonÄ™ tej grupy. JeÅ›li pozostawisz jÄ… niezaznaczonÄ…, to pojawiać siÄ™ bÄ™dzie obrazek osoby zamieszczajÄ…cej dany wpis. + +/modify_do.bml.friends.opt.usesharedpic.head=Używaj obrazków grup/wspólnych dzienników zamiast obrazków osób zamieszczajÄ…cych wpisy + +/modify_do.bml.journaloptions.about=Tutaj możesz dostosowywać do swoich upodobaÅ„ wyglÄ…d swoich stron na LiveJournal. JeÅ›li bardzo ciekawi CiÄ™, jak to wszystko dziaÅ‚a, przeczytaj informacje o rozwoju. W innym razie zakÅ‚adamy, że satysfakcjonujÄ… CiÄ™ podstawowe opcje podane poniżej: + +/modify_do.bml.journaloptions.head=Opcje Dziennika + +/modify_do.bml.journalstatus.about=JeÅ›li chcesz usunąć swój dziennik lub cofnąć jego usuniÄ™cie, możesz zrobić to tutaj. Kiedy usuniesz dziennik, bÄ™dziesz mieć 30 dni, aby cofnąć swojÄ… decyzjÄ™. Po 30 dniach Twój dziennik zostanie permanentnie usuniÄ™ty i nie bÄ™dzie już sposobu na jego odzyskanie. + +/modify_do.bml.journalstatus.head=Status Aktywacji Dziennika + +/modify_do.bml.journalstatus.select.activated=Aktywny + +/modify_do.bml.journalstatus.select.deleted=UsuniÄ™ty + +/modify_do.bml.journalstatus.select.suspended=Zawieszony + +/modify_do.bml.moodicons.about=ZamieszczajÄ…c wpisy do dziennika, możesz okreÅ›lić swój nastrój w danej chwili. Różni użytkownicy przysyÅ‚ali nam różne zestawy ikon nastrojów, z których możesz korzystać. Możesz też wybrać opcjÄ™ "None", jeÅ›li nie chcesz żadnych ikon przy swoich nastrojach. (w zasadzie możesz w ogóle nie używać opcji Obecnego Nastroju.) + +/modify_do.bml.moodicons.head=Ikony Nastrojów + +/modify_do.bml.moodicons.opt.forcefriends.about=WymuÅ› ten zestaw ikon na wszystkich przyjacioÅ‚ach na Twojej liÅ›cie przyjaciół + +/modify_do.bml.moodicons.personal=Osobiste Schematy: + +/modify_do.bml.moodicons.preview=podglÄ…d + +/modify_do.bml.moodicons.select=Wybierz zestaw ikon nastrojów: + +/modify_do.bml.overrides.about|staleness=1 +/modify_do.bml.overrides.about=Możesz zignorować tÄ™ sekcjÄ™. Opcja ta sÅ‚uży do zmiany bardzo specyficznych drobiazgów w wyglÄ…dzie Twojej strony. Zobacz sekcjÄ™ rozwoju, jeÅ›li interesujÄ… CiÄ™ szczegóły. Uwaga: Nadpisywać da siÄ™ tylko jednÄ… lub dwie rzeczy w każdym stylu. JeÅ›li chcesz nadpisać wszystko, musisz stworzyć wÅ‚asny styl. + +/modify_do.bml.overrides.box.head=Nadpisywanie: + +/modify_do.bml.overrides.head=Nadpisywanie Stylów + +/modify_do.bml.overrides.note=Zauważ, że nie wszystkie zmienne stylów mogÄ… zostać nadpisane. Zajrzyj do dokumentacji, jeÅ›li interesujÄ… CiÄ™ szczegóły.
          Musisz wiedzieć, że jeÅ›li spróbujesz edytować swoje nadpisywania i użyÅ‚aÅ›/eÅ› taga, który nie jest dozwolony w nagłówku dokumentu – na przykÅ‚ad <DIV>, <SPAN>, <IMG>, i wiele innych tagów – ten tag zostanie zdemontowany. Jedynymi elementami HTML, które mogÄ… zostać użyte w nadpisywaniu *_HEAD, sÄ… te, których można używać w nagłówku dokumentu HTML. OgraniczajÄ… siÄ™ one do <title>, <base>, <style>, <link> i <meta>. + +/modify_do.bml.overrides.warning=TO NIE TUTAJ WPISUJESZ TREŚĆ SWOJEGO DZIENNIKA!! + +/modify_do.bml.pagelayoutstyle.about=To ustawienie kontroluje, jak Twój dziennik jest ustawiony na ekranie. + +/modify_do.bml.pagelayoutstyle.head=Styl Strony + +/modify_do.bml.pagelayoutstyle.warning=Twój typ konta pozwala tylko Ci na wybieranie miÄ™dzy niewielkÄ… liczbÄ… domyÅ›lnych stylów. + +/modify_do.bml.success.head=Sukces + +/modify_do.bml.success.text=Ustawienia Twojego dziennika zostaÅ‚y uaktualnione. Możesz zobaczyć swój dziennik tutaj. + +/paidaccounts/index.bml.costs.header=No to ile to kosztuje? + +/paidaccounts/index.bml.costs.rates=Oto ceny: + +/paidaccounts/index.bml.costs.rates.amount.header=Kwota + +/paidaccounts/index.bml.costs.rates.inexpensive=To tylko okoÅ‚o $2 miesiÄ™cznie w skali roku. Nie nadszarpnie to za bardzo Twoich funduszy. Najprawdopodobniej najbardziej nieprzyjemne bÄ™dzie wyjÄ™cie portfela, znalezienie karty kredytowej i wpisanie potrzebnych danych do komputera. + +/paidaccounts/index.bml.costs.rates.time.header=Czas + +/paidaccounts/index.bml.features|staleness=1 +/paidaccounts/index.bml.features<< +
          Aby okazać wdzięczność użytkownikom, którzy nas wspomogli, mamy kilka dodatków, które są dostępne wyłącznie dla posiadaczy kont płatnych. Te dodatki to między innymi:
          + +
          Nowość! Zamieszczanie przez Email
          +
          Właściciele kont płanych mogą zamieszczać w swoich dziennikach i w grupach szybko i bezpiecznie poprzez naszą bramkę emailową.
          + +
          Zmiana WyglÄ…du Twojego Dziennika
          +
          Dodatkowo do podstawowej możliwości wyboru stylu dla Twojego dziennika i kolorów, możesz też tworzyć własne style, korzystając z dowolnych tagów HTML. Umożliwi Ci to też tworzenie własnego stylu, który będzie pasował do Twojej strony internetowej, do której możesz go z łatwością włączyć, nigdy nie zdradzając, że korzystasz z LiveJournal.com jako Twojego mechanizmu do prowadzenia dziennika.
          + +
          Ankiety
          +
          Posiadacze kont płatnych mają możliwość tworzenia automatycznych ankiet w swoich własnych dziennikach oraz w dziennikach wszelkich grup, do których należą i mogą zamieszczać.
          + +
          Więcej Obrazków Użytkownika
          +
          Konta płatne mogą mieć przypisanych 15 obrazków użytkownika, w przeciwieństwie do 3 dozwolonych dla kont darmowych.
          + +
          Alias Emailowy LiveJournal.com
          +
          Konta płatne distają adres emailowy LiveJournal.com ([[username]]@livejournal.com), który można wyłączyć lub włączyć.
          + +
          Przeszukiwanie Katalogu
          +
          Konta płatne mają dostęp do katalogu, w którym mogą szukać innych użytkowników.
          + +
          Subdomena LiveJournal.com
          +
          Zamiast długiego adresu http://www.livejournal.com/users/[[username]]/, Twój dziennik będzie też dostępny pod http://[[username]].livejournal.com/, któcej i bardziej bezpośrednio.
          + +
          Zrzeszanie
          +
          Posiadacze kont płatnych mogą subskrybować źródła RSS, które na LiveJournal przyjmują formę kont zrzeszających. Konta płatne mogą wtkorzystać na to aż do 20 punktów.
          + +
          Wiadomości Tekstowe
          +
          Konta płatne mają dostęp do opcji wiadomości tekstowych, która pozwala im otrzymywać wiadomości tekstowe na komórkę bądź pager przez interfejs LiveJournal.
          + +
          Więcej Miejsca w Rzeczach-do-Zrobienia
          +
          Właściciele kont płatnych mogą ustawić do 150 elementów na swojej liście rzeczy-do-zrobienia i mogą dla każdego z nich ustawiać inne poziomy zabezpieczeń.
          + +
          Widok RSS
          +
          Widok RSS dla konta płatnego użytkownika zawiera pełen tekst wpisów zamiast krótkich podsumowań.
          + +
          WÅ‚Ä…czanie do Strony Osobistej
          +
          Właściciele kont płatnych mają dostęp do pełnego zakresu opcji związanych z włączaniem dziennika do swojej osobistej strony internetowej, jak zostało to wyjaśnione na stronie "Włączanie do Strony Osobistej".
          + +
          Przypisanie Domeny
          +
          Płacący użytkownicy mogą przypisać dziennikowi własny adres, tak by ich własna domena wskazywała na ich dziennik.
          + +
          Więcej...
          +
          Kompletną listę korzyści płynących z posiadania Konta Płatnego znajdziesztutaj.
          +. + +/paidaccounts/index.bml.features.header=Więc jakie dodatki dostanę? + +/paidaccounts/index.bml.title=O Kontach Płatnych + +/paidaccounts/index.bml.whypay.argument=Oczywiście, że nie. Płacenie za serwisy internetowe jest denerwujące, zdajemy sobie z tego sprawę. Dlatego też prawie wszystkie funkcje LiveJournal są dostępne za darmo. Jakkolwiek, jeśli zadowala Cię nasz serwis, możesz okazać nam swoje wsparcie i nabyć konto płatne. + +/paidaccounts/index.bml.whypay.header=Czy muszę płacić za LiveJournal? + +/paidaccounts/index.bml.whypay.no_ads=Prowadzenie strony internetowej pochłania pieniądze (na serwery, pomieszczenia dla nich oraz łącza), a nam lepszym pomysłem wydaje się ściąganie opłat za konta, niż zalewanie Was bannerami, reklamówkami i spamem. + +/paidaccounts/index.bml.your_username=twoja_nazwa_użytkownika + +/paidaccounts/usepaypal.bml.delivery.badformat=Niepoprawny format daty dostarczenia. Musi on być w formie rrrr-mm-dd lub rrrr-mm-dd gg:mm. + +/paidaccounts/usepaypal.bml.delivery.past=Data dostarczenia nie może być z przeszłości. Aby dostarczyć natychmiast, zostaw to pole puste. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Data dostarczenia nie może być później niż miesiąc od chwili obecnej. + +/pay/index.bml.deliverydate.details=W formacie rrrr-mm-dd hh:mm (czas strefy GMT)
          (nie wpisuj nic, jeśli dostarczyć bez opóźnienia) + +/pay/index.bml.deliverydate.label=Data Dostarczenia: + +/pay/index.bml.gift.anonymous=Anonimowy podarunek + +/poll/create.bml.button.editpoll=Edytuj Ankietę + +/poll/create.bml.button.insert=Dołącz + +/poll/create.bml.button.postpoll=Zamieść Ankietę + +/poll/create.bml.button.preview=Podejrzyj Ankietę + +/poll/create.bml.button.seecode=Zobacz Kod + +/poll/create.bml.button.startover=Zacznij Od Nowa + +/poll/create.bml.elements.limitreached=Limit elementów został osiągnięty + +/poll/create.bml.error.accttype=Twój typ konta nie pozwala na tworzenie automatycznych ankiet. + +/poll/create.bml.error.allitemsblank=Wszystkie pola nie mogą być puste + +/poll/create.bml.error.notext=Musisz podać tekst pytania + +/poll/create.bml.insertquestion=Tutaj wpisz pytanie: + +/poll/create.bml.options=Opcje: + +/poll/create.bml.pollname=Nazwa Ankiety: (opcjonalna) + +/poll/create.bml.preview.desc=Poniżej znajduje się podgląd Twojej ankiety. Dokładnie tak będzie wyglądała, gdy zamieścisz ją w swoim dzienniku. Użyj przycisków poniżej, by cofnąć się i wprowadzić zmiany, lub by zamieścić ankietę w swoim dzienniku. + +/poll/create.bml.preview.options=Opcje + +/poll/create.bml.question=Pytanie: + +/poll/create.bml.questionnum=Pytanie nr [[num]] + +/poll/create.bml.type.scale=Skala + +/poll/create.bml.type.text=Pole tekstowe + +/poll/create.bml.whoview=Kto może oglądać wyniki tej ankiety? + +/poll/create.bml.whovote=Kto może wypełnić tę ankietę? + +/poll/index.bml.discuss=Omawiaj Wyniki + +/poll/index.bml.filloutpoll=Wypełnij Ankietę + +/poll/index.bml.pollnotfound=Ankieta nie znaleziona. + +/poll/index.bml.submitted.text=Twoje odpowiedzi zostały dodane do wyników ankiety. + +/poll/index.bml.submitted.title=Dodane! + +/poll/index.bml.title=Ankieta + +/poll/index.bml.viewresults=Zobacz Wyniki Ankiety + +/press/staff.bml.administration=Obsługa + +/press/staff.bml.administration.about=LiveJournal.com zaczął działać w 1999 roku jako projekt Brada Fitzpatricka i przez pierwsze dwa lata swojego istnienia był podtrzymywany przez dużą grupę lojalnych ochotników. Chocaż nadal wiele spraw na LiveJournal.com jest załatwianych przez drużyny ochotników, mamy obecnie również małą grupę stałych pracowników, którzy kontrolują wszystkie operacje: + +/press/staff.bml.avva.title=Starszy Programista + +/press/staff.bml.back2=Z powrotem do obszaru Prasowego + +/press/staff.bml.bradfitz.quip=Skup się na produkcie, a nie na zarabianiu pieniędzy. + +/press/staff.bml.bradfitz.title=Prezes / Główny Programista + +/press/staff.bml.contact=Jeśli potrzebujesz się skontaktować z którymś z nas, wyślij emaila na webmaster@livejournal.com. + +/press/staff.bml.denisep.quip=Będę to miała dla ciebie na następny czwartek. + +/press/staff.bml.denisep.title=Związki z Ochotnikami / Specjalista od Użyteczności + +/press/staff.bml.jproulx.quip=Geek to User Liaison + +/press/staff.bml.jproulx.title=Nadzorca Strony / Relacje z Prasą + +/press/staff.bml.lisa.title=Administrator Systemów + +/press/staff.bml.ryanfitz.title=Płatności + +/press/staff.bml.sandy.title=Konta i Administracja + +/press/staff.bml.title=Płatny Personel + +/press/staff.bml.whitaker.quip=Co dalej? + +/press/staff.bml.whitaker.title=Stażysta + +/register.bml.ask.body=Kliknij w poniższy przycisk, aby wysłał email potwierdzający na [[email]]. + +/register.bml.ask.button=Wyślij + +/register.bml.ask.header=Potwierdź Adres Email + +/register.bml.email.body|staleness=1 +/register.bml.email.body<< +To jest email potwierdzający, który zamówiłaś/eś. +Aby potwierdzić swoje konto, wejdź na adres: + + [[conflink]] + +Być może będziesz musiał(a) skopiować i wkleić ten adres do swojej przeglądarki. + +Z pozdrowieniami, +[[sitename]] +[[siteroot]] +. + +/register.bml.email.subject=Potwierdź Adres Email + +/register.bml.error.invalidcode=Nieprawidłowy kod potwierdzający. + +/register.bml.error.usernotfound=Użytkownik nie znaleziony. + +/register.bml.new.body=Dziękujemy! Twój adres email został zweryfikowany. Może Cię teraz zainteresować któraś z poniższych rzeczy: + +/register.bml.new.editinfo=Edytuj Informacje -- Wypełnij swój profil użytkownika i wybierz różne ustawienia. + +/register.bml.new.header=Sukces + +/register.bml.new.login=Zaloguj się -- Aby nie było potrzeby wszędzie podawać nazwy użytkownika i hasła. + +/register.bml.new.modify=Modyfikuj Dziennik -- Zmieniaj wygląd swojego dziennika. + +/register.bml.new.update=Uaktualnij Dziennik -- Pisz w swoim dzienniku. + +/register.bml.sent.body=Email potwierdzający został wysłany na adres [[email]]. Aby zakończyć proces potwierdzania, musisz wejść na adres podany w tym emailu. + +/register.bml.sent.header=Sukces + +/register.bml.title=Potwierdź Adres Email + +/register.bml.trans.body=Twój nowy adres email został potwierdzony. + +/register.bml.trans.header=Sukces + +/rename/index.bml.does=Przemianowanie konta spowoduje tylko zmianę nazwy użytkownkia. Wszystko inne - płatny lub permanentny status konta, przywileje użytkownika, dane osobiste, przyjaciele i inne informacje związane z kontem pozostaną bez zmian i będą związane z nową nazwą. Wszystkie istniejące komentarze oraz wpisy w dziennikach grup również będą wyświetlane z nową nazwą użytkownika. + +/rename/index.bml.heading.cost=Koszt + +/rename/index.bml.heading.details=Szczegóły + +/rename/use.bml.error.readit=Przeczytaj powyższy akapit. + +/rename/use.bml.error.username=Nieprawidłowa nazwa użytkownika. + +/rename/use.bml.error.usernametaken=Ta nazwa użytkownika jest już zajęta. + +/rename/use.bml.heading.changes=Zmiany + +/rename/use.bml.heading.success=Sukces + +/rename/use.bml.heading.sure=Czy jesteś pewien/pewna? + +/site/contract.bml.promise=Obiecujemy zawsze i niezmiennie: + +/site/contract.bml.promise.account=Honorować status każdego konta + +/site/contract.bml.promise.account.about=Konta permanentne będą honorowane przez cały czas istnienia naszej strony. Konta płatne pozostaną kontami płatnymi aż do czasu wygaśnięcia terminu płatności, lub dłużej, jeśli zostaną odnowione. Konta wcześnie utworzone będą miały zawsze dostęp do płatnych dodatków, które były darmowe we wczesnych czasach istnienia naszej strony. (status kont ważny z wyjątkiem kont zawieszonych w wyniku pogwałcenia Zasad Użytkowania) + +/site/contract.bml.promise.ads=Pozostać serwisem wolnym od reklam + +/site/contract.bml.promise.ads.about=Być może dlatego, że jest to jedna z najbardziej drażniących rzeczy, lub dlatego, że nie daje wielkich pieniędzy, w każdym razie obiecujemy nigdy nie oferować przestrzeni na reklamy w naszym serwisie i na naszych stronach. + +/site/contract.bml.promise.community=Pracować w społeczności i dla społeczności + +/site/contract.bml.promise.community.about=Obiecujemy, że będziemy informować Was o zmianach w miarę naszych możliwości i bez narzucania się. Obiecujemy prowadzić interes bazując na sugestiach społeczności LiveJournal i pamiętając zawsze przede wszystkim o dobru tej społeczności. + +/site/contract.bml.promise.opensource=Wspierać ruch Free Software + +/site/contract.bml.promise.opensource.about=Całość kodu potrzebnego do przeprowadzenia kompletnej, w wysokim stopniu dostosowywalnej do potrzeb instalacji LiveJournal jest dostępna publicznie. Obiecujemy, że ten kod źródłowy pozostanie darmowy i w pełni dostępny, dzięki czemu możemy oddać coś z powrotem społeczności Free Software. + +/site/contract.bml.promise.spam=Nigdy nie wysyłać użytkownikom niechcianych emaili + +/site/contract.bml.promise.spam.about=Silnie wierzymy, że spam nie ma prawa bytu w internecie, i obiecujemy nigdy nie wysyłać Wam żadnych emaili bez Waszej wyraźnej zgody. Obiecujemy nigdy nie sprzedać nikomu list adresów email użytkowników ani żadnych danych osobistych i obiecujemy nigdy nie wysyłać Wam spamu w imieniu jakichkolwiek osób trzecich. + +/site/contract.bml.promise.uptime=Utrzymać godny zaufania czas nieprzerwanego działania, w granicach technicznych możliwości + +/site/contract.bml.promise.uptime.about=Staramy się, by wszystko działało jak najlepiej dla wszystkich, zwłaszcza, że sami także korzystamy z tego serwisu. Niestety jednak zdarza się, że serwery się zawieszają, będziemy jednak planować naprzód najlepiej, jak się da, by tego unikać. + +/site/contract.bml.promisetoyou=My na liveJournal staramy się, by nasz serwis był dla naszych użytkowników tak przyjemny, jak to tylko możliwe, więc zebraliśmy listę obietnic, których zobowiązujemy się dotrzymać. + +/site/contract.bml.promisetoyou.header=Nasza Obietnica dla Was + +/site/contract.bml.title=Kontrakt Społeczny + +/site/goat.bml.image.alt=Frank, LiveJournalowy kozioł-maskotka. + +/site/goat.bml.image.caption="Beee," powiada Frank. + +/site/goat.bml.meet.body=To jest Frank. Frank jest maskotką LiveJournal.com. Pomaga nam w programowaniu, gdy mamy tyły, a od czasu do czasu odpowiada na prośby o wsparcie techniczne. Frank jest na prawdę wszechstronny... czasem nawet robi za ogrodnika. Kiedy trawa jest już za wysoka, wołamy "Hej, Frank! Obiadek! Pojedz sobie trawniczek!". To na prawdę świetny układ. + +/site/goat.bml.meet.header=Poznaj Franka + +/site/goat.bml.title=Frank Kozioł + +/styles/create_do.bml.success.head=Sukces + +/styles/index.bml.about.header=Tworzenie i Używanie Własnych Stylów + +/styles/index.bml.nav.browse=Przeglądarka Stylów + +/styles/index.bml.nav.browse.about=Przeglądarka stylów pozwala Ci przeglądać publiczne style utworzone przez innych użytkowników. + +/styles/index.bml.nav.create=Utwórz nowy styl + +/styles/index.bml.nav.create.about=Utwórz nowy styl od zera lub oprzyj swój nowy styl na już istniejącym stylu publicznym. + +/styles/index.bml.nav.edit=Edytuj lub usuń istniejący styl + +/styles/index.bml.nav.edit.about=Możesz edytować wyącznie style przypisane do Twojego konta. Aby modyfikować styl systemowy, musisz najpierw utworzyć własny styl bazujący na danym stylu systemowym. + +/styles/index.bml.nav.modify=Modyfikuj swoje konto + +/styles/index.bml.title=Własne Style + +/suggestions/index.bml.howto.text|staleness=1 +/suggestions/index.bml.howto.text<< +
          +
          Sprawdż wcześniejsze sugestie
          +Najpierw przeczytaj wcześniejsze sugestie, by upewnić się, że coś podobnego nie było wcześniej sugerowane. Jeśli było, możesz przeczytać komentarze do danego wpisu. Czasami może wyglądać na to, że coś zostało zignorowane, ale tak na prawdę możliwe jest, że jest już przez kogoś kodowane. Czasami sugestie są odrzucane lub przesuwane na później z różnych powodów. +
          +
          Nie znalazłaś/eś swojego pomysłu? Podziel się nim z nami!
          +Dla wszystkich sugestii wypełniony musi zostać formularz. Upewnij się, że wypełniłaś/eś wszystkie pola formularza, w przeciwnym razie Twój pomysł może nie zostać wzięty pod uwagę. Kiedy już go zamieścisz, nie możesz go edytować, więc upewnij się, że informacje są pełne. Dodatkowo pamiętaj, że generator sugestii nie dodaje linii rozdzielających, więc możesz używać taga <br>, by robić odstępy między akapitami. To sprawi, że Twoja sugestia będzie bardziej czytelna. +
          +
          Zamieść to!
          +Możesz dodać grupę do swojej listy przyjaciół klikając tutaj. Kiedy jakaś sugestia zostanie zamieszczona, ludzie będą nad nią dyskutować. Jeśli uznamy, że to dobry pomysł, zostanie on dodany do listy celów i zadań programistów, i zostanie wykonany, gdy tylko znajdzie się na to czas. Nie wszystkie sugestie zostaną zrealizowane natychmiast, więc miej cierpliwość.
          +. + +/suggestions/index.bml.howto.title=Jak zrobić sugestię? + +/suggestions/index.bml.info.text|staleness=1 +/suggestions/index.bml.info.text<< +Czujesz, że możesz wnieść coś w realizację swojej sugestii? Obserwuj lub przyłączyć się do poniższych grup: +
          +
          Forum Deweloperów LiveJournal -- o sprawach technicznych.
          +
          +
          Forum Biznesowe LiveJournal -- generalnie o interesach LiveJournal i tym podobnych.
          +
          +
          Forum Dokumentacji dla Użytkowników LiveJournal -- dyskusje o i edytowanie większości dokumentaczji dla użytkowników.
          +
          +
          Forum Artystyczne LiveJournal -- dyskusje i dzielenie się obrazkami, ikonami nastrojów, zestawami kolorów itp.
          +
          +
          +Pamiętaj, że ludzie, którzy zajmują się zmianami i modyfikacjami na LiveJournal, są użytkownikami takimi jak Ty. Te rzeczy mogą zajmować dużo czasu, a im więcej możesz przy nich pomóc, tym więcej uda się osiągnąć. +. + +/suggestions/index.bml.info.title=Inne Informacje + +/suggestions/index.bml.rules|staleness=1 +/suggestions/index.bml.rules<< +Należy pamiętać o kilku rzeczach: +
            +
          • Wiele sugestii zostaÅ‚o już zgÅ‚oszonych i przedyskutowanych, ale po prostu nie sÄ… one jeszcze zrealizowane. Upewnij siÄ™, że nie zamieszczasz duplikatu. +
          • Atakowanie innych nie bÄ™dzie akceptowane. Wszyscy majÄ… różne pomysÅ‚y dotyczÄ…ce tego, jak powinien dziaÅ‚ać LiveJournal; pamiÄ™taj, że promowanie wÅ‚asnych pomysłów jest dobre, ale atakowanie cudzych opinii nie jest. +
          • BÄ…dź w swojej sugestii tak konkretna/y, jak to tylko możliwe. Sugestia, która zawiera szczegółowe notatki dotyczÄ…ce realizacji, ma wiÄ™ksze szanse na przyjÄ™cie, niż maÅ‚o konkretna. Nie musisz wiedzieć jak siÄ™ programuje; spróbuj siÄ™ po prostu zastanowić, na co jeszcze może wpÅ‚ynąć Twój pomysÅ‚, i wymieÅ„ wszystkie problemy, jakie w zwiÄ…zku z tym przyjdÄ… Ci do gÅ‚owy. +
          • Najpierw przeczytaj FAQ by dowiedzieć siÄ™, czy Twój pomysÅ‚ nie zostaÅ‚ już zrealizowany, lub czy jakiÅ› istniejÄ…cy element strony nie potrafi robić tego, co chcesz. +
          • JeÅ›li chcesz zadać pytanie dotyczÄ…ce funkcjonowania LiveJournal, nie masz pewnoÅ›ci, czy coÅ› istnieje, czy nie, lub jeÅ›li masz problem, nie zamieszczaj sugestii. Zamiast tego zadaj pytanie we Wsparciu. +
          +. + +/suggestions/index.bml.title=Obszar Sugestii + +/suggestions/index.bml.welcome.text=Sugestie użytkowników są ważne dla LiveJournal. Jeśli masz jakiś pomysł, który wydaje Ci się ciekawy, wykonaj poniższą procedurę, by dać o nim znać ludziom, którzy prowadzą stronę. + +/suggestions/index.bml.welcome.title=Witaj! + +/support/append_request.bml.back.requests=Z powrotem do listy nierozwiązanych problemów. + +/support/append_request.bml.back.support=Z powrotem do obszaru wsparcia. + +/support/append_request.bml.logged.title=Sukces + +/support/append_request.bml.login.required=Aby pomagać ludziom, musisz się najpierw zalogować. + +/support/encodings.bml.edit.header=Nie mogę edytować swoich wpisów poprzez interfejs na stronie! + +/support/encodings.bml.edit.text<< +Krótka odpowiedź:
          (odnosząca się do Ciebie, jeśli piszesz po angielsku): Wejdź na swoją stronę osobistych ustawień. Znajdź na niej (na dole strony) opcję o nazwie Auto-tłumacz starsze wpisy z:. Wybierz z listy "Western European (Windows)" i zachowaj ustawienia. Twoje wpisy powinny teraz dać się edytować. p?> + +Długa odpowiedź: Aby móc edytować wpisy nie-Unicode, LiveJournal musi wiedzieć, w jaki sposób wpis został zakodowany. Dla użytkowników posługujących się angielskim i językami zachodnio-europejskimi, odpowiednim kodowaniem powinno być "Western European (ISO)". Użytkownicy piszący w innych językach powinni wybrać inne, odpowiednie dla siebie kodowanie; jeśli nie znajduje się ono na podanej liście, skontaktuj się ze Wsparciem i wyjaśnij problem. p?> + + +. + +/support/encodings.bml.editcl.header=Nie mogę edytować swoich wpisów poprzez swojego klienta! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Nie mogę edytować swojej listy przyjaciół poprzez swojego klienta! + +/support/encodings.bml.groups.text=stronie edycji grup, a potem korzystać już ze swojego klienta. + +/support/encodings.bml.overview.header=O co tu właściwie chodzi? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=Ciągle w kropce? + +/support/encodings.bml.still.text=Obszarze Wsparcia. p?> + +/support/encodings.bml.title=Kodowanie + +/support/faqbrowse.bml.backfaq=Powrót do często zadawanych pytań. + +/support/faqbrowse.bml.backsupport=Powrót do obszaru wsparcia. + +/support/faqbrowse.bml.edit.faq=Edytuj to FAQ + +/support/faqbrowse.bml.error.nofaq=Wybrane FAQ nie istnieje. + +/support/faqbrowse.bml.lastupdated=Ostatnio Uaktualniany: + +/support/faqbrowse.bml.title_num=Pytanie FAQ nr [[num]] + +/support/see_overrides.bml.error.noprivs=Tylko użytkownicy z przywilejami "supportviewscreened" lub "supporthelp" mogą oglądać kody nadpisywania innych użytkowników. + +/support/see_overrides.bml.error.nos1=Ten użytkownik nie używa S1. + +/support/see_overrides.bml.header=Kody nadpisywania użytkownika : + +/support/see_overrides.bml.nooverrides=Nie ma kodów nadpisywania dla użytkownika . + +/support/see_overrides.bml.title=Kody Nadpisywania Użytkownika + +/syn/index.bml.account=Konto: + +/syn/index.bml.add=Dodaj Źródło + +/syn/index.bml.add.pop.text=Poniżej znajdują się niektóre popularne źródła, których w tej chwili nie obserwujesz: + +/syn/index.bml.add.pop.title=Dodaj Pupularne Źródło + +/syn/index.bml.add.selected=Dodaj Wybrane + +/syn/index.bml.back=Powrót + +/syn/index.bml.error.unknown=Nieznany Błąd + +/syn/index.bml.feed.url=URL Źródła: + +/syn/index.bml.invalid.accountname=Nieprawidłowa nazwa konta + +/syn/index.bml.invalid.inuse.text=Ta nazwa konta jest już w użyciu. + +/syn/index.bml.invalid.inuse.title=Nazwa użytkownika w użyciu. + +/syn/index.bml.invalid.notexist=Nie istnieje konto zrzeszone o tej nazwie. + +/syn/index.bml.invalid.reserved=Ta nazwa konta jest zarezerwowana. Wybierz inną nazwę konta. + +/syn/index.bml.invalid.url=Wpisany przez Ciebie URL nie jest poprawny. Upewnij się, że wpisałeś/aś URL poprawnie i spróbuj jeszcze raz. + +/syn/index.bml.remove=Usuń Zaznaczone + +/syn/index.bml.table.account=Konto + +/syn/index.bml.table.feed=Źródło + +/syn/index.bml.table.watchers=Obserwujących + +/syn/index.bml.title=Zrzeszanie + +/syn/index.bml.using.title=Używanie [[sitename]] do zrzeszania z innymi stronami + +/syn/list.bml.feedurl=URL Źródła + +/syn/list.bml.numreaders=Liczba czytelników + +/syn/list.bml.username=Nazwa Konta + +/talkmulti.bml.deleted.body=Komentarze zostały usunięte. Tutaj możesz zobaczyć resztę wątku. + +/talkmulti.bml.deleted.title=Komentarze usunięte + +/talkmulti.bml.error.comms_deleted=Jeden z komentarzy został usunięty od czasu, kiedy go zaznaczyłaś/eś. Z przyczyn bezpieczeństwa cofnij się i spróbuj ponownie. + +/talkmulti.bml.error.inconsistent_data=Podane dane są sprzeczne. + +/talkmulti.bml.error.invalid=Wybrano nieprawidłowe parametry. + +/talkmulti.bml.error.invalid_mode=Nie zaznaczono żadnej akcji. Cofnij się, i wybierz, czy chcesz ekranować komentarze, zdjąć z nich ekran czy je usunąć. + +/talkmulti.bml.error.login=Nie jesteś zalogowana/y. + +/talkmulti.bml.error.none_selected=Nie zaznaczono żadnych komentarzy. + +/talkmulti.bml.error.privs.delete=Nie masz pozwolenia na usunięcie tych komentarzy. + +/talkmulti.bml.error.privs.screen=Nie masz pozwolenia na ekranowanie tych komentarzy. + +/talkmulti.bml.error.privs.unscreen=Nie masz pozwolenia na zdjęcie ekranu z tych komentarzy. + +/talkmulti.bml.screened.body=Komentarze zostały monitorowane. Możesz je zobaczyć tutaj. + +/talkmulti.bml.screened.title=Komentarze monitorowane + +/talkmulti.bml.title.delete=Usuń Wiele Komentarzy + +/talkmulti.bml.title.screen=Ekranuj Wiele Komentarzy + +/talkmulti.bml.title.unscreen=Zdejmij Ekran z Wielu Komentarzy + +/talkmulti.bml.unscreened.body=Został zdjęty ekran z komentarzy. Możesz je zobaczyć tutaj. + +/talkmulti.bml.unscreened.title=Zdjęto ekran z komentarzy + +/talkpost.bml.allowedhtml=Dozwolony HTML + +/talkpost.bml.error.cannotreplynopost=Nie możesz odpowiedzieć na nieistniejący wpis + +/talkpost.bml.error.nocommentsjournal=Użytkownik nie pozwala na komentowanie w swoim dzienniku. + +/talkpost.bml.error.nocommentspost=Użytkownik nie pozwala na komentowanie tego konkretnego wpisu. + +/talkpost.bml.error.noreplypost=Odpowiedź na wpis nie znaleziona (usunięta?) + +/talkpost.bml.error.noreply_deleted=Ten komentarz został usunięty. Nie możesz na niego odpowiedzieć. + +/talkpost.bml.error.noreply_screened=Ten komentarz jest monitorowany i nie masz pozwolenia na jego czytanie lub odpowiadanie na niego. + +/talkpost.bml.label.picturetouse=użyj obrazka: + +/talkpost.bml.loganonip=Uwaga! Ten użytkownik włączył funkcję, która zapisuje adresy IP anonimowych komentatorów. + +/talkpost.bml.loginq=Zalogować? + +/talkpost.bml.logyourip=Uwaga! Ten użytkownik włączył funkcję, która zapisuje adresy IP osób zamieszczających komentarze. + +/talkpost.bml.nosubjecthtml=W temacie nie wolno stosować HTML + +/talkpost.bml.opt.anonymous=Osoby Anonimowej + +/talkpost.bml.opt.defpic=(domyślny) + +/talkpost.bml.opt.friendsonly=- ten użytkownik nie pozwala na komentowanie przez osoby, anonimowe oraz spoza przyjaciół. Możesz komentować, jeśli jesteś na liście przyjaciół [[username]]. + +/talkpost.bml.opt.from=Od: + +/talkpost.bml.opt.ljuser=Użytkownika LiveJournal + +/talkpost.bml.opt.loggedin=Zalogowanego użytkownika: [[username]] + +/talkpost.bml.opt.message=Wiadomość: + +/talkpost.bml.opt.noanonpost=- ten użytkownik nie zezwala na anonimowe komentowanie. + +/talkpost.bml.opt.noautoformat=Nie auto-formatuj: + +/talkpost.bml.opt.noimage=Bez Obrazka + +/talkpost.bml.opt.preview=Podgląd + +/talkpost.bml.opt.spellcheck=Sprawdź pisownię przed zamieszczeniem + +/talkpost.bml.opt.subject=Temat: + +/talkpost.bml.opt.submit=Zamieść Komentarz + +/talkpost.bml.opt.willscreen=(będzie monitorowany) + +/talkpost.bml.opt.willscreenfriend=(będzie monitorowany, jeśli nie przyjaciel) + +/talkpost.bml.paraformat=Akapity będą domyślnie automatycznie sformatowane. + +/talkpost.bml.postresponse=Zamieść komentarz w odpowiedzi: + +/talkpost.bml.title=Zamieść Komentarz + +/talkpost.bml.usermismatch<< +Podałaś/eś nazwę użytkownika, ale odznaczyłaś/eś opcję "użytkownik LiveKournal". + +Albo wyczyść pole z nazwą użytkownika, albo wybierz odpowiedni tryb zamieszczania i spróbuj ponownie. +. + +/talkpost.bml.warnscreened=Uwaga: Ten komentarz jest monitorowany. Odpowiedź na niego automatycznie zdejmie z niego ekranowanie i sprawi, że będzie widoczny. + +/talkpost_do.bml.error.badpassword=Niepoprawne hasło dla podanej nazwy użytkownika. Możesz odzyskać zapomniane hasło tutaj. + +/talkpost_do.bml.error.badusername=Podana nazwa użytkownika nie istnieje na LiveJournal. Możesz odzyskać zapomnianą nazwę użytkownika tutaj lub możesz zamieścić komentarz anonimowy. + +/talkpost_do.bml.error.banned=Nie masz uprawnień do komentowania w dzienniku tego użytkownika. + +/talkpost_do.bml.error.blankmessage=Twoja wiadomość była pusta. Prosimy, wpisz coś w pole wiadomości. + +/talkpost_do.bml.error.confused_identity=Wpisałaś/eś nazwę użytkownika, ale wybrałaś/eś opcję komentarza anonimowego lub osoby obecnie zalogowanej. Cofnij się i zdecyduj, co w rzeczywistości chcesz zrobić. + +/talkpost_do.bml.error.deleted=Twój dziennik został usunięty. Nie możesz zamieszczać komentarzy. + +/talkpost_do.bml.error.friendsonly=Tylko przyjaciele [[user]] mogą komentować w tym dzienniku. + +/talkpost_do.bml.error.lostcookie=Zdaje się, że Twoje cookie zalogowania zniknęło...? + +/talkpost_do.bml.error.manybytes=Przykro nam, ale Twój komentarz o wielkości [[current]] brzekracza maksymalną dozwoloną wielkość [[limit]]. Prosimy, cofnij się, skróć swoją wiadomość i spróbuj zamieścić ją ponownie. + +/talkpost_do.bml.error.manychars=Przykro nam, ale Twój komentarz o długości [[current]] znaków przekracza maksymalną liczbę [[limit]] znaków. Prosimy, cofnij się, skróć swoją wiadomość i spróbuj zamieścić ją ponownie. + +/talkpost_do.bml.error.mustlogin=Musisz się zalogować aby móc odpowiedzieć na ten chroniony wpis. + +/talkpost_do.bml.error.noanon=Nie możesz zamieścić anonimowego komentarza w dzienniku tego użytkownika. + +/talkpost_do.bml.error.noauth=Nie masz uprawnień, by odpowiedzieć na ten chroniony wpis. + +/talkpost_do.bml.error.nocomments=Użytkownik nie umożliwił komentowania tego wpisu. + +/talkpost_do.bml.error.noparent=Nie da się odpowiedzieć na nie istniejący komentarz. + +/talkpost_do.bml.error.notafriend=Przykro nam, ale nie znajdujesz się na liście przyjaciół [[user]], a ten użytkownik wybrał opcję, by tylko przyjaciele mogli komentować jego wpisy do dziennika. + +/talkpost_do.bml.error.nousername=Nie wpisałaś/eś swojej nazwy użytkownika. Możesz zamieścić komentarz anonimowo, jeśli nie posiadasz konta na LiveJournal. + +/talkpost_do.bml.error.noverify=Przykro nam, ale nie możesz zamieszczać komentarzy w dziennikach innych osób, póki Twój adres email nie zostanie potwierdzony. Jeśli straciłaś/eś email z potwierdzeniem, może on zostać do Ciebie wysłany ponownie. + +/talkpost_do.bml.error.postshared=Nie możesz komentować używając konta grupy. Konta wspólne reprezentują grupę osób, a nie tylko jednego człowieka. + +/talkpost_do.bml.error.screened=Nie masz pozwolenia, by odpowiadać na ten monitorowany komentarz. + +/talkpost_do.bml.error.suspended=Twój dziennik został zawieszony. Nie wolno Ci zamieszczać komentarzy. + +/talkpost_do.bml.error.testacct=Konta testowe mogą być używane wyłącznie w dziennikach testowych. + +/talkpost_do.bml.opt.preview=Podgląd + +/talkpost_do.bml.preview=Poniżej możesz zobaczyć, jak będzie wyglądała Twoja wiadomość, jesli ją teraz zamieścisz. Możesz edytować swój komentarz poniżej lub zapisać go bez zmian. + +/talkpost_do.bml.preview.subject=Temat: + +/talkpost_do.bml.preview.submit=Potwierdź + +/talkpost_do.bml.preview.title=Podgląd + +/talkpost_do.bml.success.loggedin=Jesteś teraz zalogowana/y. + +/talkpost_do.bml.success.message=Twój komentarz został dodany. Możesz go zobaczyć tutaj. + +/talkpost_do.bml.success.screened.comm=Twój komentarz został dodany. Zgodnie z ustawieniami tej grupy, został on zapisany jako komentarz monitorowany i będzie widoczny tylko dla zarządzających tą grupą, póki nie zdejmą z niego ekranu. Możesz zobaczyć swój komentarz tutaj. + +/talkpost_do.bml.success.screened.comm.anon=Twój anonimowy komentarz został dodany. Zgodnie z ustawieniami tej grupy, został on monitorowany i będzie widoczny tylko dla zarządzających grupą, póki nie zdecydują się oni na zdjęcie ekranu. Możesz wrócić do wątku klikając tutaj. + +/talkpost_do.bml.success.screened.user=Twój komentarz został dodany. Zgodnie z ustawieniami tego dziennika został on zapisany jako komentarz monitorowany i będzie widoczny tylko dla właściciela dziennika, póki nie zdejmie z niego ekranu. Możesz zobaczyć swój komentarz tutaj. + +/talkpost_do.bml.success.screened.user.anon=Twój anonimowy komentarz został dodany. Zgodnie z ustawieniami tego dziennika, został on monitorowany i będzie widoczny tylko dla właściciela dziennika, póki nie zdecyduje się on na zdjęcie ekranu. Możesz wrócić do wątku klikając tutaj. + +/talkpost_do.bml.success.title=Sukces + +/talkpost_do.bml.success.unscreened=Dodatkowo z monitorowanego komentarza, na który odpowiedziałaś/eś, został zdjęty ekran i jest on teraz widoczny. + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Komentarz Zamieszczony + +/talkpost_do.bml.title.preview=Podgląd Komentarza + +/talkread.bml.anonuser=(Anonimowy) + +/talkread.bml.confirm.action=Czy na pewno chcesz usunąć zaznaczone komentarze? + +/talkread.bml.deletedpost=(Wpis usunięty) + +/talkread.bml.deleteduser=(Użytkownik usunięty: [[username]]) + +/talkread.bml.fromip=(z [[ip]]) + +/talkread.bml.noreplies=Brak odpowiedzi + +/talkread.bml.nosubject=(bez tematu) + +/talkread.bml.replysuspended=(Odpowiedź od zawieszonego użytkownika) + +/talkread.bml.screenedpost=(Wpis Monitorowany) + +/talkread.bml.select=Zaznacz + +/talkread.bml.subjectdeleted=[usunięty] + +/talkread.bml.talkmulti.delete=Usuń + +/talkread.bml.talkmulti.des=Masowa operacja na wybranych komentarzach: + +/talkread.bml.talkmulti.screen=Ekranuj + +/talkread.bml.talkmulti.submit=Wykonaj + +/talkread.bml.talkmulti.unscreen=Zdejmij Ekran + +/talkread.bml.title=Czytaj Komentarze + +/talkscreen.bml.error.login=Musisz się zalogować, by móc pracować z monitorowanymi komentarzami. + +/talkscreen.bml.error.privs.screen=Nie masz pozwolenia na ekranowanie tego komentarza. + +/talkscreen.bml.error.privs.unscreen=Nie masz pozwolenia na zdjęcie ekranu z tego komentarza. + +/talkscreen.bml.screen.doit=Tak, ekranuj ten komentarz. + +/talkscreen.bml.screen.sure.body=Na pewno chcesz ekranować ten komentarz? + +/talkscreen.bml.screen.sure.title=Ekranować ten komentarz? + +/talkscreen.bml.screened.body=Ten komentarz został monitorowany. + +/talkscreen.bml.screened.title=Sukces + +/talkscreen.bml.title=Monitorowany Komentarz + +/talkscreen.bml.unscreen.doit=Tak, zdejmij ekran z tego komentarza + +/talkscreen.bml.unscreen.sure.body=Na pewno chcesz usunąć ekran z tego komentarza? + +/talkscreen.bml.unscreen.sure.title=Usunąć ekran z tego komentarza? + +/talkscreen.bml.unscreened.body|staleness=1 +/talkscreen.bml.unscreened.body=Ekran został usunięty z tego komentarza. + +/talkscreen.bml.unscreened.title=Sukces + +/tools/emailmanage.bml.address.current.title=Obecny Adres + +/tools/emailmanage.bml.address.old.none=Brak + +/tools/emailmanage.bml.address.old.text=Poniżej znajduje się lista adresów email, które były używane z Twoim kontem, wraz z datami ich deaktywacji jako głównego adresu email. Zaznacz te, które chcesz usunąć z listy. + +/tools/emailmanage.bml.address.old.title=Poprzednie Adresy + +/tools/emailmanage.bml.delete_selected=Usuń Zaznaczone + +/tools/emailmanage.bml.desc.notfirst=Ta strona pozwala Ci usunąć tylko te adresy email, które były używane po tym, kiedy użyłaś/eś swojego obecnie potwierdzonego adresu email poraz pierwszy. W szczególności, oznacza to, że ktoś, kto zaatakuje Twoje konto, nie będzie mógł usunąć z tej listy Twojego oryginalnego adresu email. + +/tools/emailmanage.bml.desc.title=Opis + +/tools/emailmanage.bml.log.deleted=Usunięto: [[email]], [[time]] + +/tools/emailmanage.bml.log.deleted.title=Zmiany Zapisane + +/tools/emailmanage.bml.notvalidated.text|staleness=1 +/tools/emailmanage.bml.notvalidated.text=Aby móc korzystać z tego narzędzia, musisz mieć potwierdzony swój obecny adres email: [[email]]. Jesli straciłaś/eś email potwierdzający, może on zostać wysłany do Ciebie ponownie. Po potwierdzeniu adresu email możesz wrócić tutaj. + +/tools/emailmanage.bml.notvalidated.title=Email nie potwierdzony + +/tools/emailmanage.bml.title=Zarządzanie Adresami Email + +/tools/memadd.bml.add_previous<< + + +. + +/tools/memadd.bml.body.added.body=Twoja lista wspomnień została uaktualniona. + +/tools/memadd.bml.body.added.header=Sukces + +/tools/memadd.bml.description=Opis: + +/tools/memadd.bml.description.text<< +Nadaj temu wspomnieniu swój opis, by je potem łatwiej odnaleźć. + Jeśli chcesz usunąć ten wpis ze swojej listy wspomnień, zostaw to pole puste. +. + +/tools/memadd.bml.error.deleted.body=Wpis, który znajdował się wcześniej na Twojej liście wspomnień opisany jako "[[desc]]", został usunięty z Twojej listy. + +/tools/memadd.bml.error.deleted.title=Wspomnienie usunięte + +/tools/memadd.bml.error.entry_deleted=Wpis do dziennika już nie istnieje. Wspomnienie zostało usunięte. + +/tools/memadd.bml.error.fivekeywords=Tylko 5 słów kluczowych/kategorii może zostać przypisanych do jednego wspomnienia. + +/tools/memadd.bml.error.invalid_security=Niepoprawna lub brakująca opcja bezpieczeństwa. + +/tools/memadd.bml.error.login=Musisz się zalogować, by korzystać z tego narzędzia. Zaloguj się, a autumatyczie wrócisz w to miejsce. + +/tools/memadd.bml.error.maxsize=To słowo kluczowe przekracza dozwoloną wielkość: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Aby dodać wpis do swojej listy wspomnień, musisz dać mu jakiś opis. +Aby usunąć wpis, możesz edytować go i usunąć opis, ale ten wpis nie znajdował się wcześniej na Twojej liście. +. + +/tools/memadd.bml.error.nodescription.title=Brak opisu + +/tools/memadd.bml.form.reset=Resetuj + +/tools/memadd.bml.form.submit=Wyślij formularz + +/tools/memadd.bml.keywords=Słowa kluczowe: + +/tools/memadd.bml.keywords.example=Przykład: Zabawny, Zakręcony, Romantyczny + +/tools/memadd.bml.keywords.select=Możesz też wybrać spośród słów kluczowych wykorzystanych przez siebie już wcześniej: + +/tools/memadd.bml.keywords.text=Dlaczego ten wpis jest godny wspominania? Wpisz do pięciu słów kluczowych lub kategorii oddzielonych przecinkami, by móc łatwiej odnaleźć go w przyszłości. + +/tools/memadd.bml.login.enterinfo=Wpisz nazwę użytkownika i hasło konta, do którego listy wspomnień ten wpis ma zostać dodany. + +/tools/memadd.bml.login.forgot.header=Zapomniałaś/eś czegoś? + +/tools/memadd.bml.login.forgot.recover=Jeśli nie pamiętasz swojej nazwy użytkownika lub hasła, odzyskaj je tutaj! + +/tools/memadd.bml.multiple_selections=Aby zaznaczyć więcej niż jedno słowo kluczowe z listy, przytrzymaj klawisz 'Control' (Ctrl) klikając na słowa. + +/tools/memadd.bml.security=Bezpieczeństwo: + +/tools/memadd.bml.security.friendsonly=Tylko dla przyjaciół + +/tools/memadd.bml.security.private=Prywatne + +/tools/memadd.bml.security.public=Publiczne + +/tools/memadd.bml.title=Dodaj do Wspomnień + +/tools/memadd.bml.title.added=Dodano + +/tools/memadd.bml.title.add_memory=Dodaj Wpis do Wspomnień + +/tools/memadd.bml.title.deleted=Usunięto + +/tools/memadd.bml.title.edit_memory=Edytuj Wspomnienie + +/tools/memadd.bml.whocansee<< +Kto może zobaczyć, że ten wpis został oznaczony jako Twoje wspomnienie? + Wszyscy, tylko osoby z Twojej listy przyjaciół, czy tylko Ty? +. + +/tools/memories.bml.back=Z powrotem + +/tools/memories.bml.body.keyword<< + +[[user]] oznaczonych przez niego słowem kluczowym "[[keyword]]". p?> +. + +/tools/memories.bml.body.list_categories<< + +[[user]] pogrupował(a) swoje wspomnienia. p?> +. + +/tools/memories.bml.body.memorable=Poniżej znajduje się lista niepogrupowanych i nieoznaczonych wpomnień użytkownika [[user]]. + +/tools/memories.bml.delete.deleted.head=Sukces + +/tools/memories.bml.delete.deleted.title=Skasowane Wspomnienia + +/tools/memories.bml.delete.error.noneselected=Nie zaznaczyłeś żadnego Wspomnienia do skasowania. + +/tools/memories.bml.edit=edytuj + +/tools/memories.bml.error.noentries.body<< +Może tak być ponieważ:
            +
          1. użytkownik nie zdefiniował żadnych wspomnień
          2. +
          3. wspomnienia tego użytkownika są chronione i nie masz do nich dostępu, lub
          4. +
          5. ten użytkownik nie ma żadnych wspomnień, które odpowiadałyby z Twoim kryteriom wyszukiwania.
          6. +. + +/tools/memories.bml.error.noentries.title=Nie odnaleziono żadnych wspomnień. + +/tools/memories.bml.filter.all=Wszystkie wspomnienia + +/tools/memories.bml.filter.other=Tylko wpisy innych użytkowników + +/tools/memories.bml.filter.own=Tylko wpisy '[[user]]' + +/tools/memories.bml.form.filter=Filtruj wpisy według: + +/tools/memories.bml.form.sort=Sortuj wpisy według: + +/tools/memories.bml.form.switch=Przełącz + +/tools/memories.bml.login=Aby zobaczyć własne wspomnienia, zaloguj się. + +/tools/memories.bml.sort.description=Opisu + +/tools/memories.bml.sort.journal=Dziennika + +/tools/memories.bml.sort.orderadded=Kolejności Dodawania + +/tools/memories.bml.title.keyword=Wspomnienia [[keyword]] + +/tools/memories.bml.title.memorable=Wspomnienia + +/tools/memories.bml.uncategorized=Bez Kategorii + +/update.bml.altpost=Uaktualniany dziennik: + +/update.bml.btn.preview=Podgląd + +/update.bml.btn.update=Uaktualnij Dziennik + +/update.bml.currmood=Obecny Nastrój: + +/update.bml.currmusic=Obecna Muzyka: + +/update.bml.date=Data: + +/update.bml.default=domyślny + +/update.bml.defaultjournal=([[user]]) -- domyślny + +/update.bml.error.cantpost=Przykro nam, nie możesz w tej chwili nic zamieścić. + +/update.bml.error.disabled=Twój typ konta nie pozwala na zamieszczanie. + +/update.bml.error.disabled.title=Wyłączona możliwość zamieszczania. + +/update.bml.error.login=Błąd podczas logowania: + +/update.bml.error.nopass=Podaj Hasło + +/update.bml.error.update=Błąd podczas uaktualniania dziennika: + +/update.bml.event=Wydarzenie: + +/update.bml.full=Pełna Strona Uaktualniania + +/update.bml.htmlokay.norich=(możesz korzystać z tagów HTML; nowe linijki domyślnie będą formatowane jako <br>) + +/update.bml.htmlokay.rich=(możesz korzystać z tagów HTML; nowe linijki domyślnie będą formatowane jako <br> - możesz też skorzystać z modułu wzbogaconego tekstu.) + +/update.bml.htmlokay.rte_nosupport=(Przykro nam, Twoja przeglądarka nie obsługuje obecnie naszego środowiska wzbogaconego tekstu.) + +/update.bml.localtime=Lokalny czas: + +/update.bml.loggedinas=Jesteś obecnie zalogowana/y jako [[user]].
            aby zamieÅ›cić jako inny użytkownik, cliknij tutaj. + +/update.bml.loggingin=Logowanie na serwer... + +/update.bml.noneother=Å»aden, lub inny: + +/update.bml.note=Uwaga: Czas/data powyżej jest z naszego serwera. Popraw go odpowiednio do swojej strefy czasowej przed zamieszczeniem wpisu. + +/update.bml.opt.backdate=Wpis Datowany Wstecz: + +/update.bml.opt.backdate.about=nie pokaże siÄ™ na stronach przyjaciół + +/update.bml.opt.defpic=(domyÅ›lny) + +/update.bml.opt.nocomments=Nie Pozwól Na Komentarze: + +/update.bml.opt.noemail=Nie E-Mailuj Komentarzy: + +/update.bml.opt.noformat=Nie auto-formatuj: + +/update.bml.opt.spellcheck=Sprawdź pisowniÄ™ przed zamieszczeniem wpisu + +/update.bml.options=Ustawienia Opcjonalne + +/update.bml.other=Inny: + +/update.bml.password=HasÅ‚o: + +/update.bml.picture=Obrazek: + +/update.bml.preview.header=PodglÄ…d + +/update.bml.security.custom=WÅ‚asny... + +/update.bml.security.friends=Dla Przyjaciół + +/update.bml.security.head=Poziom BezpieczeÅ„stwa: + +/update.bml.security.private=Prywatny + +/update.bml.security.public=Publiczny + +/update.bml.servermsg=Serwer ma dla Ciebie wiadomość: + +/update.bml.simple=Patrzysz na stronÄ™ uproszczonÄ…. JeÅ›li chcesz mieć wiÄ™cej opcji, wejdź tutaj. + +/update.bml.spellchecked=Twój wpis ze sprawdzonymi bÅ‚Ä™dami: + +/update.bml.subject=Temat (opcjonalny) + +/update.bml.timeformat=Czas - 24 godziny + +/update.bml.title=Uaktualnij Dziennik + +/update.bml.title.readonly=Tryb tylko do odczytu + +/update.bml.update.head=Uaktualnij swój Dziennik... + +/update.bml.update.success=Dziennik uaktualniony. Możesz go zobaczyć tutaj. + +/update.bml.updating=Uaktualnianie dziennika... + +/update.bml.username=Nazwa Użytkownika: + +/uploadpic.bml.error.unsupportedtype=Pliki typu [[filetype]] nie sÄ… przyjmowane. Możesz zaÅ‚adować tylko pliki GIF, PNG lub JPG. Prawie wszystkie programy do obróbki zdjęć/obrazków mogÄ… przekonwertować Twój obrazek na inny typ pliku. + +/userinfo.bml.about.comm=Opis: + +/userinfo.bml.about.user=Biografia: + +/userinfo.bml.body.leave=Możesz opuÅ›cić grupÄ™ w dowolnym momencie. + +/userinfo.bml.comminfo.body=Poniżej znajdujÄ… siÄ™ informacje o grupie "[[commname]]" na LiveJournal. + +/userinfo.bml.comminfo.name=Info Grupy + +/userinfo.bml.date.never=Nigdy. + +/userinfo.bml.error.malfname|staleness=1 +/userinfo.bml.error.malfname=Źle utworzona nazwa użytkownika. + +/userinfo.bml.error.notloggedin=JeÅ›li chcesz zobaczyć swój profil użytkownika, musisz siÄ™ zalogować. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Obserwowana przez: + +/userinfo.bml.friendof.hidden=(ukryta) + +/userinfo.bml.friendof.syndreadcount=Ilość Czytelników + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Należy do przyjaciół: + +/userinfo.bml.friends.comm=CzÅ‚onkowie + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Przyjaciele + +/userinfo.bml.label.addbuddy=Dodaj Przyjaciela + +/userinfo.bml.label.adduser=Dodaj Użytkownika + +/userinfo.bml.label.aolim=AOL IM: + +/userinfo.bml.label.birthdate=Data Urodzenia: + +/userinfo.bml.label.clientsused=Używane oprogramowanie: + +/userinfo.bml.label.comments=Komentarze: + +/userinfo.bml.label.composted=Zamieszczone: [[num]] - + +/userinfo.bml.label.comreceived=Otrzymane: [[num]] + +/userinfo.bml.label.datecreated=Data Utworzenia: + +/userinfo.bml.label.dateupdated=Data Uaktualnienia: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=Email: + +/userinfo.bml.label.frpeople=Ludzie + +/userinfo.bml.label.icquin=ICQ UIN: + +/userinfo.bml.label.interests=Zainteresowania + +/userinfo.bml.label.interests.modifyyours=Modyfikuj swoje + +/userinfo.bml.label.interests.removesome=UsuÅ„ niektóre + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] zainteresowania nie pokazane + +/userinfo.bml.label.jabber=Jabber: + +/userinfo.bml.label.journalentrs=Wpisy do Dziennika: + +/userinfo.bml.label.location=Lokacja: + +/userinfo.bml.label.memberof=CzÅ‚onek grup + +/userinfo.bml.label.memories=Wspomnienia + +/userinfo.bml.label.moredetails=(wiÄ™cej szczegółów...) + +/userinfo.bml.label.msnusername=Nazwa Użytkownika MSN + +/userinfo.bml.label.name=ImiÄ™/Nazwa: + +/userinfo.bml.label.nofriends=Brak. + +/userinfo.bml.label.post=Zamieść w "[[journal]]" + +/userinfo.bml.label.postalt=Uaktualnij swój dziennik + +/userinfo.bml.label.reqfinduser=Tylko użytkownicy z uprawnieniami 'finduser' mogÄ… wyszukiwać użytkowników przez userid. + +/userinfo.bml.label.searchjournal=Przeszukaj Ten Dziennik + +/userinfo.bml.label.sendmessage=WyÅ›lij Wiadomość + +/userinfo.bml.label.shared=DostÄ™p Do Zamieszczania Wpisów: + +/userinfo.bml.label.supportpoints=Punkty za Wsparcie + +/userinfo.bml.label.syndicatedfrom=ZwiÄ…zane z: + +/userinfo.bml.label.syndicatedstatus=Status Zrzeszenia: + +/userinfo.bml.label.textmessage=Tekstowa
            Wiadomość
            : + +/userinfo.bml.label.todo=Lista Rzeczy-Do-Zrobienia + +/userinfo.bml.label.user=Użytkownik: + +/userinfo.bml.label.viewfriends=Zobacz Przyjaciół + +/userinfo.bml.label.viewmembers=Zobacz Członków + +/userinfo.bml.label.website=Strona Internetowa: + +/userinfo.bml.label.yahooid=ID Yahoo!: + +/userinfo.bml.membership.body=Aby przyłączyć się do tej grupy, kliknij tutaj. + +/userinfo.bml.memories.entries=Ilość wpisów: [[count]] + +/userinfo.bml.memories.entry=Ilość wpisów: [[count]] + +/userinfo.bml.monitor.comm=Monitoruj Grupę + +/userinfo.bml.monitor.user=Dodaj tego użytkownika do swojej listy przyjaciół + +/userinfo.bml.nonexist.body=Nazwa użytkownika [[user]] nie jest obecnie zarejestrowana. + +/userinfo.bml.nonexist.name=Nie znany użytkownik + +/userinfo.bml.sendmessage.body=Wyślij użytkownikowi [[user]] wiadomość tekstową
            na jego telefon komórkowy/pager. + +/userinfo.bml.syn.last.never=Nigdy + +/userinfo.bml.syn.lastcheck=Ostatnio sprawdzany: + +/userinfo.bml.syn.nextcheck=Kolejne sprawdzenie: + +/userinfo.bml.syn.parseerror=Wiadomość o BÅ‚Ä™dzie: + +/userinfo.bml.syndinfo.body=JeÅ›li chcesz, by artykuÅ‚y z tej zrzeszonej strony pojawiaÅ‚y siÄ™ na Twojej stronie przyjaciół, możesz dodać ten dziennik do swojej listy przyjaciół. + +/userinfo.bml.syndinfo.name=ZrzeszajÄ…cy Dziennik + +/userinfo.bml.tellafriend=Powiedz Przyjacielowi! + +/userinfo.bml.timeupdate.dayago=1 dzieÅ„ temu + +/userinfo.bml.timeupdate.daysago=[[num]] dni temu + +/userinfo.bml.timeupdate.hourago=1 godzinÄ™ temu + +/userinfo.bml.timeupdate.hoursago=[[num]] godzin(y) temu + +/userinfo.bml.timeupdate.minuteago=1 minutÄ™ temu + +/userinfo.bml.timeupdate.minutesago=[[num]] minut(y) temu + +/userinfo.bml.timeupdate.secondago=1 sekundÄ™ temu + +/userinfo.bml.timeupdate.secondsago=[[num]]sekund(y) temu + +/userinfo.bml.timeupdate.weekago=1 tydzieÅ„ temu + +/userinfo.bml.timeupdate.weeksago=[[num]] tygodni(e) temu + +/userinfo.bml.title=Info Użytkownika + +/userinfo.bml.title.communityinfo=Info Grupy + +/userinfo.bml.title.syndicated=Zrzeszone Konto + +/userinfo.bml.userinfo.body=Poniżej znajdujÄ… siÄ™ informacje o użytkowniku [[username]]. JeÅ›li jesteÅ› tym użytkownikiem, możesz edytować swoje informacje (lub wybrać, które z nich majÄ… być pokazywane publicznie) na stronie Edycji Danych. + +/userinfo.bml.userinfo.name=Informacje o Użytkowniku + +bml.badcontent.body=Jeden lub wiÄ™cej bÅ‚Ä™dów nastÄ…piÅ‚o podczas wysyÅ‚ania Twojego formularza. Zalecamy wrócić, poprawić potrzebne informacje i ponownie wysÅ‚ać dane. + +bml.needlogin.body2=Musisz siÄ™ zalogować, by zobaczyć tÄ… stronÄ™. + +BML.parse_multipart.parse=BÅ‚Ä…d przy Å‚adowaniu + +BML.parse_multipart.toolarge=Zbyt duży upload + +BML.parse_multipart.unknowntype=Nie znany typ zawartoÅ›ci + +btn.search=Szukaj + +crumb.about=O LiveJournal + +crumb.abusereport=ZgÅ‚oÅ› Nadużycie + +crumb.acctstatus=Status Konta + +crumb.addfriend=Dodaj Przyjaciela + +crumb.advsearch=Zaawansowane + +crumb.banners=Bannery Reklamowe + +crumb.birthdays=Urodziny + +crumb.changepass=ZmieÅ„ HasÅ‚o + +crumb.commsearch=Wyszukiwanie Grup + +crumb.createcommunity=Utwórz GrupÄ™ + +crumb.createjournal=Utwórz Dziennik + +crumb.createstyle=Utwórz Styl + +crumb.customize=Ustawienia S2 + +crumb.delcomment=UsuÅ„ Komentarz + +crumb.download=ÅšciÄ…gnij Program + +crumb.editentries=Edytuj Wpisy + +crumb.editentries_do=Edytuj Wpis + +crumb.editfriendgrps=Edytuj Grupy Przyjaciół + +crumb.editfriends=Edytuj Przyjaciół + +crumb.editpics=Obrazki Użytkownika + +crumb.editstyle=Edytuj Styl + +crumb.emailgateway=Bramka Emailowa + +crumb.emailmanage=ZarzÄ…dzanie Adresami Email + +crumb.faq=CzÄ™sto Zadawane Pytania + +crumb.filemanager=ZarzÄ…dzanie Plikami + +crumb.friends=NarzÄ™dzia Przyjaciół + +crumb.friendsfilter=Filtr Przyjaciół + +crumb.goat=O Franku + +crumb.itsfree=Za darmo? + +crumb.joincomm=PrzyÅ‚Ä…cz siÄ™ do Grupy + +crumb.latestposts=Najnowsze Wpisy + +crumb.layerbrowse=PrzeglÄ…darka Publicznych Styli + +crumb.leavecomm=Opuść GrupÄ™ + +crumb.legal=Informacje Prawne + +crumb.linkslist=Twoje Linki + +crumb.login=Zaloguj + +crumb.logout=Wyloguj + +crumb.lostinfo=Zagubione Dane + +crumb.manage=ZarzÄ…dzaj Kontami + +crumb.managecommunity=ZarzÄ…dzanie Grupami + +crumb.memories=Wspomnienia + +crumb.modify=Ustawienia Dziennika + +crumb.news=NowoÅ›ci + +crumb.paidaccounts=Konta PÅ‚atne + +crumb.privacy=Polityka PrywatnoÅ›ci + +crumb.search=Szukaj + +crumb.searchinterests=WedÅ‚ug ZainteresowaÅ„ + +crumb.searchregion=WedÅ‚ug Regionu + +crumb.sitemap=Mapa Strony + +crumb.siteopts=PrzeglÄ…daj Preferencje + +crumb.sizechart=Rozpiska Rozmiarów + +crumb.stats=Statystyki + +crumb.store=Sklepik LiveJournal + +crumb.storeitem=Zobacz Szczegóły + +crumb.styles=Style + +crumb.suggview=Sugestie + +crumb.textmessage=WyÅ›lij Wiadomość TekstowÄ… + +crumb.todo=Lista Rzeczy Do Zrobienia + +crumb.update=Uaktualnij Dziennik + +crumb.yourstyles=Twoje Style + +date.day.friday.long=PiÄ…tek + +date.day.friday.short=Pt + +date.day.monday.long=PoniedziaÅ‚ek + +date.day.monday.short=Pon + +date.day.saturday.long=Sobota + +date.day.saturday.short=Sob + +date.day.sunday.long=Niedziela + +date.day.sunday.short=Nie + +date.day.thursday.long=Czwartek + +date.day.thursday.short=Czw + +date.day.tuesday.long=Wtorek + +date.day.tuesday.short=Wt + +date.day.wednesday.long=Åšroda + +date.day.wednesday.short=Åšr + +date.month.april.long=KwiecieÅ„ + +date.month.april.short=KwiecieÅ„ + +date.month.august.long=SierpieÅ„ + +date.month.august.short=SierpieÅ„ + +date.month.december.long=GrudzieÅ„ + +date.month.december.short=GrudzieÅ„ + +date.month.february.long=Luty + +date.month.february.short=Luty + +date.month.january.long=StyczeÅ„ + +date.month.january.short=StyczeÅ„ + +date.month.july.long=Lipiec + +date.month.july.short=Lipiec + +date.month.june.long=Czerwiec + +date.month.june.short=Czerwiec + +date.month.march.long=Marzec + +date.month.march.short=Marzec + +date.month.may.long=Maj + +date.month.may.short=Maj + +date.month.november.long=Listopad + +date.month.november.short=Listopad + +date.month.october.long=Październik + +date.month.october.short=Październik + +date.month.september.long=WrzesieÅ„ + +date.month.september.short=WrzesieÅ„ + +dystopia.btn.login=ZALOGUJ + +dystopia.hello_anonymous=Witaj na LiveJournal! + +dystopia.hello_loggedin=Witaj, [[username]]! + +dystopia.nav.createjournal=Utwórz Dziennik + +dystopia.nav.developer=Obszar Rozwoju + +dystopia.nav.download=ÅšciÄ…gnij + +dystopia.nav.editentries=Edytuj Wpisy + +dystopia.nav.editfriends=Twoi Przyjaciele + +dystopia.nav.editpassword=Twoje HasÅ‚o + +dystopia.nav.editpics=Twoje Obrazki + +dystopia.nav.editstyle=Edytuj Styl + +dystopia.nav.faq=CzÄ™ste Pytania - FAQ + +dystopia.nav.findcomm=WedÅ‚ug Grup + +dystopia.nav.finddir=Poprzez Katalog + +dystopia.nav.findint=WedÅ‚ug ZainteresowaÅ„ + +dystopia.nav.findrandom=Przypadkowo + +dystopia.nav.findregion=WedÅ‚ug Regionu + +dystopia.nav.home=Strona Główna + +dystopia.nav.journalcalendar=Kalendarz + +dystopia.nav.journalfriends=Przyjaciele + +dystopia.nav.journalinfo=Twój Profil + +dystopia.nav.journalrecent=Ostatnie Wpisy + +dystopia.nav.legalprivacy=Polityka PrywatnoÅ›ci + +dystopia.nav.legaltos=Zasady Użytkowania + +dystopia.nav.login=Zaloguj + +dystopia.nav.logout=Wyloguj + +dystopia.nav.lostinfo=Zapomniane HasÅ‚o + +dystopia.nav.memories=Wspomnienia + +dystopia.nav.modifyjournal=Modyfikuj Dziennik + +dystopia.nav.news=NowoÅ›ci + +dystopia.nav.paidaccts=Konta PÅ‚atne + +dystopia.nav.paymentarea=Obszar PÅ‚atnoÅ›ci + +dystopia.nav.personalinfo=Dane Osobiste + +dystopia.nav.sitemap=Mapa Strony + +dystopia.nav.siteopts=PrzeglÄ…daj Opcje + +dystopia.nav.support=Masz pytanie? + +dystopia.nav.updatejournal=Uaktualnij Dziennik + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=150 + +dystopia.navhead.findusers=Szukaj Użytkowników + +dystopia.navhead.help=Pomoc i Wsparcie + +dystopia.navhead.journal=Twój Dziennik + +dystopia.navhead.legal=Strona Prawna + +dystopia.navhead.settings=Twoje Ustawienia + +dystopia.navhead.welcome=Witaj! + +dystopia.search.icq=Numer ICQ + +dystopia.search.int=Zainteresowanie + +dystopia.search.msn=Nazwa Użytkownika MSN + +dystopia.searchlj=Szukaj na LiveJournal: + +Email=E-mail + +email.newacct.body<< +Gratulacje, masz nowe konto na LiveJournal! + +Aby dokoÅ„czyć proces tworzenia konta i potwierdzić swój adres email, wejdź tutaj: + + [[regurl]] + +Adres URL, pod którym znajduje siÄ™ Twój nowy dziennik, to: + + [[siteroot]]/users/[[username]]/ + +oraz: + + [[siteroot]]/~[[username]]/ + +Poniżej znajduje siÄ™ Twoja nazwa użytkownika oraz hasÅ‚o na LiveJournal: + + Nazwa Użytkownika: [[username]] + HasÅ‚o: [[password]] + +Możesz wejść na [[siteroot]]/ by zalogować siÄ™ na swoje konto, tworzyć nowe wpisy +do dziennika i zmieniać swoje opcje, ale polecamy Å›ciÄ…gniÄ™cie klienta +LiveJournal. Jest to najprostsza metoda uaktualniania dziennika, a klienty +dostÄ™pne sÄ… dla wielu różnych platform! Możesz znaleźć klienta na: + + [[siteroot]]/download/ + +Może być Ci trudno siÄ™ rozkrÄ™cić na LiveJournal, jeÅ›li nie znasz nikogo. Wejdź na +http://newbies.livejournal.com po różnego rodzaju porady... Przy odrobinie +szczęścia wkrótce staniesz siÄ™ LiveJournalowym guru! + +Mamy nadziejÄ™, że LiveJournal spodoba Ci siÄ™ tak bardzo, jak nam podoba siÄ™ +dawanie go ludziom. JeÅ›li masz jakiekolwiek pytania dotyczÄ…ce tego, jak +korzysać z LiveJournal, odwiedź obszar wsparcia na stronie: + + [[siteroot]]/support/ + +Tam znajdziesz odpowiedzi na praktycznie wszystkie pytania, jakie tylko +można zadać na temat LiveJournal. + +Naszym celem jest sprawić, by LiveJournal byÅ‚ absolutnie w dechÄ™. JeÅ›li jest coÅ›, +co możemy zrobić, by staÅ‚ siÄ™ prostszy w obsÅ‚udze, fajniejszy, bardziej +dostosowywalny do potrzeb indywidualnych użytkowników, cokolwiek... daj nam +znać. Nie prowadzimy tej strony, żeby robic kasÄ™. TÄ™ strone prowadzÄ… ci sami +ludzie, którzy z niej korzystajÄ…. Powiedz nam, czego oczekujesz. + +JeÅ›li masz pytania, grupa wsparcia odpowie Ci na nie zwykle w czasie krótszym +niż 24 godziny. + +Dobrej zabawy! + +Drużyna [[sitename]] +[[siteroot]]/ +. + +email.newacct.subject=Witaj na LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=BÅ‚Ä…d + +error.badpassword=Niepoprawne HasÅ‚o. + +error.dberror=PojawiÅ‚ siÄ™ bÅ‚Ä…d bazy danych: + +error.deleted.name=UsuniÄ™te + +error.deleted.text=Ten dziennik zostaÅ‚ usuniÄ™ty. JeÅ›li jesteÅ› [[user]], masz 30 dni czasu od momentu usuniÄ™cia konta na to, aby je przywrócić. Po 30 dniach to konto zostanie na zawsze usuniÄ™te z serwerów LiveJournal. + +error.deleted.title=Konto Usuniete. + +error.expiredchal=Okno logowania wygasÅ‚o. ProszÄ™ spróbować jeszcze raz. + +error.invalidauth=Nie udaÅ‚o siÄ™ zidentyfikować CiÄ™ jako wskazanego użytkownika. + +error.ipbanned=Twój adres IP ma tymczasowy ban za przekroczenie iloÅ›ci bÅ‚Ä™dnych logowaÅ„. + +error.malformeduser=Źle utworzona nazwa użytkownika. + +error.nobutton=Przycisk nie wciÅ›niÄ™ty? + +error.nodb=Baza danych chwilowo nie dostÄ™pna. + +error.nodbmaintenance=Ta część bazy danych jest chwilowo niedostÄ™pna z powodu zrzÄ…dzania. Spróbuj ponownie za kilka minut. + +error.noentry=Nie istnieje taki wpis. + +error.nojournal=Nieznany Dziennik + +error.noremote=Musisz siÄ™ zalogować, by móc korzystać z tej strony. + +error.procrequest=PojawiÅ‚ siÄ™ bÅ‚Ä…d podczas wykonywania Twojego polecenia: + +error.purged.name=UsuniÄ™te + +error.purged.text=Ten dziennik zostaÅ‚ bezpowrotnie usuniÄ™ty. + +error.purged.title=Oczyszczone Konto + +error.suspended.name=Zawieszone + +error.suspended.text=To konto zostaÅ‚o zawieszone czasowo lub permanentnie. Jesli to Ty jesteÅ› [[user]], prosimy, zajrzyj FAQ pod tytuÅ‚em Moje konto zostaÅ‚o zawieszone! Jak mogÄ™ je odzyskać? po wiÄ™cej informacji. Prosimy, zauważ, że ze wzglÄ™du na poszanowanie prywatnoÅ›ci naszych użytkowników, [[sitename]] nie może dyskutować na temat powodów zawieszenia konta z kimkolwiek innym, niż wÅ‚aÅ›ciciel tego konta. + +error.suspended.title=Zawieszone Konto + +error.tempdisabled=Chwilowo niesprawne. + +error.unknownmode=Nieznany tryb. + +error.usernameinvalid=Nazwa użytkownika zawiera niepoprawne znaki. + +error.usernamelong=Nazwa użytkownika zbyt dÅ‚uga; maksymalnie 15 znaków. + +error.username_notfound=Nazwa użytkownika nie znaleziona. + +Help=Pomoc + +label.screening.all=Wszystkie Komentarze + +label.screening.anonymous=Tylko Anonimowe + +label.screening.default=DomyÅ›lne + +label.screening.header=Monitorowane Komentarze: + +label.security.custom=WÅ‚asny... + +label.security.friends=Dla Przyjaciół + +label.security.head=Poziom BezpieczeÅ„stwa: + +label.security.members=CzÅ‚onkowie + +label.security.private=Prywatny + +label.security.public=Publiczny + +label.switch.button=PrzeÅ‚Ä…cz + +label.switch.header=PrzeÅ‚Ä…cz Dziennik + +label.switch.workwith=Pracuj z dziennikiem: + +langname.be=BiaÅ‚oruski + +langname.da=DuÅ„ski + +langname.de=Niemiecki + +langname.en=Angielski + +langname.en_GB=Ankielski, Wielka Brytania + +langname.en_LJ=Angielski + +langname.es=HiszpaÅ„ski + +langname.et=EstoÅ„ski + +langname.fi=FiÅ„ski + +langname.fr=Francuski + +langname.ga=Irlandzki + +langname.gd=Celtycki + +langname.he=Hebrajski + +langname.hu=WÄ™gierski + +langname.is=Islandzki + +langname.it=WÅ‚oski + +langname.ja=JapoÅ„ski + +langname.la=Åacina + +langname.lv=Litewski + +langname.ms=Malajski + +langname.nb=Norweski BokmÃ¥l + +langname.nl=Niderlandzki + +langname.nn=Norweski Nynorsk + +langname.pl=Polski + +langname.pt=Portugalski + +langname.ru=Rosyjski + +langname.sv=Szwedzki + +langname.tr=Turecki + +langname.uk=UkraiÅ„ski + +langname.zh=ChiÅ„ski Uproszczony + +ljcom.account.feature.styles=Twórz/edytuj style + +ljcom.account.free=Konto Darmowe + +ljcom.account.paid=Konto PÅ‚atne + +ljcom.accounttype=Typ Konta + +ljcom.badpass.email=Twoje hasÅ‚o nie może bazować na Twoim adresie email. + +ljcom.badpass.realname=Twoje hasÅ‚o nie może bazować na Twoim prawdziwym imieniu. + +ljcom.badpass.username=Twoje hasÅ‚o nie może bazować na Twojej nazwie użytkownika. + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=MiÄ™dzynarodowy DzieÅ„ [[name]] Meetup + +ljcom.meetup.moreinfo=(wiÄ™cej informacji) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Chcesz spotkać ludzi ze swojej okolicy w realu żeby podyskutować na ten temat? Zajrzyj na [[link]]! + +ljcom.userinfo.accounttype=Typ konta + +ljcom.userinfo.paiduser=Użytkownik PÅ‚acÄ…cy + +ljcom.userinfo.types.early=Konto WczeÅ›nie Utworzone + +ljcom.userinfo.types.free=Konto Darmowe + +ljcom.userinfo.types.paid=Konto PÅ‚atne + +ljcom.userinfo.types.paid_early=Konto PÅ‚atne, poprzednio Konto WczeÅ›nie Utworzone + +ljcom.userinfo.types.paid_early_expiring=Konto PÅ‚atne wygasajÄ…ce [[paiduntil]], poprzednio Konto WczeÅ›nie Utworzone + +ljcom.userinfo.types.paid_expiring=Konto PÅ‚atne wygasajÄ…ce [[paiduntil]] + +ljcom.userinfo.types.permanent=Konto Permanentne + +ljcom.userinfo.types.permanent_early=Konto Permanentne, poprzednio Konto WczeÅ›nie Utworzone + +ljlib.pageofpages=Strona [[page]] z [[total]] + +lostinfo.head=ZapomniaÅ‚aÅ›/eÅ› czegoÅ›? + +lostinfo.text=JeÅ›li nie pamiÄ™tasz swojej nazwy użytkownika lub hasÅ‚a, odzyskaj je tutaj. + +lynx.nav.friends=Przyjaciele + +lynx.nav.help=Wsparcie Techniczne + +lynx.nav.login=Zaloguj + +lynx.nav.logout=Wyloguj + +lynx.nav.recent=Ostatnie Wpisy + +lynx.nav.sitemap=Mapa Strony + +lynx.nav.siteopts=PrzeglÄ…daj Opcje + +lynx.nav.update=Uaktualnij Dziennik + +Password=HasÅ‚o + +password.max30=HasÅ‚a nie mogÄ… skÅ‚adać siÄ™ z wiÄ™cej niż 30 znaków. + +poll.security.friends=Przyjaciele + +poll.viewanswers=Zobacz Odpowiedzi + +portal.bdays.count.des=DomyÅ›lnie pokazywać siÄ™ bÄ™dzie 5 Twoich przyjaciół z nadchodzÄ…cymi urodzinami. + +portal.bdays.count.name=Pokazywane Urodziny + +portal.bdays.portalname=Urodziny + +portal.bdays.portaltitle=Urodziny + +portal.goat.name=Maskotka Strony + +portal.goattext.des=Co ma mówić Twój kozioÅ‚? Jedyne, co tak na prawdÄ™ potrafiÄ… mówić kozÅ‚y, to "Beee", ale możesz udawać, że Twój kozioÅ‚ potrafi coÅ› wiÄ™cej, jeÅ›li na prawdÄ™ tego chcesz. + +portal.goattext.name=Koźli Tekst + +portal.login.portalname=Okno Logowania + +portal.memories.entriesnoun=wpisy/ów + +portal.memories.entrynoun=wpis + +portal.memories.portalname=Wspomnienia + +portal.memories.portaltitle=Wspomnienia + +portal.ministats.active=Aktywni: + +portal.ministats.title=Statystyki Użytkowników + +portal.ministats.total=Ogółem: + +portal.misbehaved.des=Tak na prawdÄ™ nie chcesz tego zaznaczyć. KozÅ‚y, które nie sÄ… trenowane, to tylko kÅ‚opoty. + +portal.misbehaved.name=Niewychowany KozioÅ‚ + +portal.newtolj.name=ÅÄ…cza Strony + +portal.popfaq.portalname=10 Najczęściej Czytanych FAQ + +portal.popfaq.portaltitle=10 Najczęściej Czytanych FAQ + +portal.randuser.count.des=DomyÅ›lnie pokazywany jest jeden losowy użytkownik, ale możesz mieć do 10 pionowo w wÄ…skiej kolumnie lub 5 poziomo w szerokiej kolumnie + +portal.randuser.count.name=Ilość pokazywanych losowych użytkowników + +portal.randuser.error.tableempty=Nie ma losowych użytkowników. Skontaktuj siÄ™ z administratorem. + +portal.randuser.hidename.des=DomyÅ›lnie pokazuje siÄ™ nazwa losowego użytkownika. Zaznacz, by to usunąć. + +portal.randuser.hidename.name=Ukryj NazwÄ™ + +portal.randuser.hidepic.des=DomyÅ›lnie pokazuje siÄ™ obrazek losowego użytkonika. Zaznacz, by to usunąć. + +portal.randuser.hidepic.name=Ukryj Obrazek Użytkownika + +portal.randuser.portalname=Losowy Użytkownik + +portal.randuser.portaltitle=Losowy Użytkownik + +portal.randuser.portaltitleplural=Losowi Użytkownicy + +portal.recent.error.noentries=Brak wpisów, przepraszamy. + +portal.recent.error.notsetup=Musisz skonfigurować to okno. Kliknij symbol plusa, żeby ustawić dziennik, który chcesz tu oglÄ…dać. + +portal.recent.error.userstatus=Konto zostaÅ‚o usuniÄ™te lub zawieszone. + +portal.recent.items.description=DomyÅ›lnie pokazywany jest tylko najbardziej aktualny wpis. + +portal.recent.items.name=Ilość pokazywanych wpisów + +portal.recent.journal.description=Z jakiego dziennika chcesz oglÄ…dać wpisy? + +portal.recent.journal.name=Dziennik + +portal.recent.nosubject=(Bez Tematu) + +portal.recent.permlink=ÅÄ…cze + +portal.recent.portalname=Widok Ostatniego Wpisu + +portal.recent.portaltitle=Okno Ostatniego Wpisu + +portal.recent.showtext.description=DomyÅ›lnie bÄ™dÄ… siÄ™ pokazywać tylko tematy. + +portal.recent.showtext.name=CaÅ‚y Tekst + +portal.stats.journalentyest=Wpisów zamieszczonych wczoraj + +portal.stats.portalname=Statystyki Strony + +portal.stats.portaltitle=Statystyki + +portal.stats.totalusers=CaÅ‚kowita liczba użytkowników + +portal.update.mode.des=PeÅ‚ny tryb uaktualniania dziennika daje Ci mnóstwo dodatkownych opcji zamieszczania, takich jak zamieszczanie do grup i ustawianie obecnego nastroju, muzyki i obrazka. Tryb prosty jest lepszy, jeÅ›li rzadko korzystasz z tych opcji i wolisz na nie nie patrzeć. + +portal.update.mode.full=PeÅ‚ny + +portal.update.mode.name=Tryb + +portal.update.mode.simple=Prosty + +portal.update.portalname=Uaktualnianie Dziennika + +portal.update.portaltitle=Uaktualnij Dziennik + +protocol.bad_password=Twoje hasÅ‚o jest zbyt proste do odgadniÄ™cia. Zalecana jest zmiana hasÅ‚a, w innym wypadku konto może zostać zaatakowane. Wejdź na stronÄ™ [[siteroot]]/changepassword.bml by zmienić swoje hasÅ‚o. + +protocol.hello_test=Witaj, Konto Testowe! + +protocol.mail_bouncing=Obecnie używasz zÅ‚ego adresu e-mail. Poczta, którÄ… próbujemy do Ciebie wysÅ‚ać, powraca. [[sitename]] wymaga dziaÅ‚ajÄ…cego adresu e-mail do peÅ‚nego funkcjonowania. Wejdź na [[siteroot]]/support/faqbrowse.bml?faqid=19 by przeczytać, jak zmienić adres e-mail. + +protocol.modpost=Twój wpis zostaÅ‚ umieszczony w kolejce kontrolnej. Zostanie zatwierdzony lub odrzucony przez jednego z moderatorów. + +protocol.must_revalidate=Musisz zaktywować swój adres e-mail. Twój poprzedni adres byÅ‚ dobry, ale zostaÅ‚ zmieniony i teraz musisz potwierdzić swój nowy adres. JeÅ›li tego nie zrobisz, nie bÄ™dziesz mieć dostÄ™pu do wszystkich funkcji [[sitename]]. Na stronie [[siteroot]]/support/faqbrowse.bml?faqid=11znajdziesz wiÄ™cej informacji. + +protocol.not_validated=Twój adres e-mail nie zostaÅ‚ zaktywowany. Możesz dalej korzystać z [[sitename]], ale jeÅ›li nie zaktywujesz swojego adresu e-mail, nie bÄ™dziesz mieć dostÄ™pu do wszystkich funkcji strony. Przeczytaj instrukcje wysÅ‚ane do Ciebie mailem po utworzeniu konta, lub wejdź na stronÄ™ [[siteroot]]/support/faqbrowse.bml?faqid=11 po wiÄ™cej informacji. + +protocol.old_win32_client=SÄ… znacznie nowsze klienty LiveJournal Windows, zalecamy uaktualnienie. Wejdź na stronÄ™ [[siteroot]]/download/ by Å›ciÄ…gnąć nowszego klienta. + +protocol.readonly=Twoje konto jest chwilowo w trybie tylko-do-odczytu. Niektóre funkcje nie bÄ™dÄ… dziaÅ‚ać przez kilka minut. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Przykro nam + +talk.anonwrote=KtoÅ› napisaÅ‚, + +talk.anonwrote_comm=KtoÅ› napisaÅ‚ w [[commlink]], + +talk.btn.preview=PodglÄ…d + +talk.commentpost=Zamieść nowy komentarz + +talk.commentsread=Czytaj komentarze + +talk.curname_Mood=Obecny nastrój: + +talk.curname_Music=Obecna muzyka: + +talk.error.bogusargs=Podrobione argumenty + +talk.error.comm_deleted=Ten komentarz zostaÅ‚ usuniÄ™ty. + +talk.error.deleted=Ten dziennik jest usuniÄ™ty. + +talk.error.deleted.title=UsuniÄ™ty + +talk.error.mustlogin=Musisz siÄ™ zalogować, by móc zobaczyć ten chroniony wpis. + +talk.error.nocomment=Ten komentarz nie istnieje. + +talk.error.noentry=Nie ma takiego wpisu. + +talk.error.nojournal=BÅ‚Ä…d: nie udaÅ‚o siÄ™ okreÅ›lić dziennika z podanych argumentów. + +talk.error.nosuchjournal=Nie istnieje taki dziennik + +talk.error.notauthorised=Nie masz uprawnieÅ„ do odczytania tego chronionego wpisu. + +talk.error.suspended=Ten dziennik/użytkownik jest zawieszony. + +talk.error.suspended.title=Zawieszony + +talk.parentlink=WÄ…tek główny + +talk.readsimilar=Czytaj podobne wpisy do dziennika: + +talk.replytothis=Odpowiedz + +talk.somebodywrote=[[realname]] ([[userlink]]) napisaÅ‚(a), + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) napisaÅ‚(a) w [[commlink]], + +talk.spellcheck=Sprawdź pisowniÄ™ w podglÄ…dzie + +talk.threadlink=WÄ…tek + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_polski + +Username=Nazwa użytkownika + +userpic.inactive=Nieaktywne + +xcolibur.greeting.anon=Witaj na LiveJournal! + +xcolibur.greeting.logged_in=Witaj, [[name]]! [[logout]] + +xcolibur.login=Zalogować? + +xcolibur.logout=Wylogować? + +xcolibur.nav.about=Informacje + +xcolibur.nav.about.download=ÅšciÄ…gnij + +xcolibur.nav.about.general=Informacje Ogólne + +xcolibur.nav.about.paidaccounts=Konta PÅ‚atne + +xcolibur.nav.about.press=Prasa + +xcolibur.nav.about.sitenews=NowoÅ›ci + +xcolibur.nav.about.stats=Statystyki + +xcolibur.nav.footer.sitemap=Mapa Strony + +xcolibur.nav.help=Pomoc + +xcolibur.nav.help.ask=Zadaj Pytanie + +xcolibur.nav.help.contact=Info Kontaktowe + +xcolibur.nav.help.faq=FAQ + +xcolibur.nav.help.lostpassword=Odzyskaj HasÅ‚o + +xcolibur.nav.home=Strona Główna + +xcolibur.nav.journal=Dziennik + +xcolibur.nav.journal.archive=Archiwum + +xcolibur.nav.journal.edit.entries=Edytuj Wpisy + +xcolibur.nav.journal.friends=Przyjaciele + +xcolibur.nav.journal.memories=Wspomnienia + +xcolibur.nav.journal.recent=Ostatnie Wpisy + +xcolibur.nav.journal.update=Uaktualnij + +xcolibur.nav.manage=ZarzÄ…dzaj + +xcolibur.nav.manage.community=Grupy + +xcolibur.nav.manage.customize=WyglÄ…d Dziennika + +xcolibur.nav.manage.entries=Wpisy + +xcolibur.nav.manage.friends=Przyjaciele + +xcolibur.nav.manage.password=HasÅ‚o + +xcolibur.nav.manage.pics=Ikony Użytkownika + +xcolibur.nav.manage.styles=Style + +xcolibur.nav.search=Szukaj + +xcolibur.nav.search.directory.search=Zaawansowane + +xcolibur.nav.search.interests=Zainteresowania + +xcolibur.nav.search.random=Losowo + +xcolibur.nav.siteopts=PrzeglÄ…daj Opcje + +xcolibur.nav.title=Nawigacja: + +xcolibur.nav.welcome=Witaj + +xcolibur.nav.welcome.create=Utwórz Konto + +xcolibur.nav.welcome.login=Login + +xcolibur.nav.welcome.update=Uaktualnij Swój Dziennik + +xcolibur.search=Szukaj: + +xcolibur.search.category=Kategoria: + +xcolibur.search.icq=Numer ICQ + +xcolibur.search.int=Zainteresowanie + +xcolibur.search.msn=Nazwa Użytkownika MSN + +xcolibur.upgrade=PodnieÅ› Status Swojego Konta + diff --git a/ljcom/bin/upgrading/pt.dat b/ljcom/bin/upgrading/pt.dat new file mode 100644 index 0000000..53c8741 --- /dev/null +++ b/ljcom/bin/upgrading/pt.dat @@ -0,0 +1,2430 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.header.success=Sucesso + +/accountstatus.bml.journalstatus.about=Se você quiser deletar ou recuperar seu journal deletado, o lugar para fazê-lo é aqui. Assim que você deletar seu journal, você terá 30 dias para recuperá-lo, se por acaso mudar de idéia. Após 30 dias, o journal será permanentemente deletado e não haverá jeito de recuperá-lo. + +/accountstatus.bml.journalstatus.head=Status de Ativação do Journal + +/accountstatus.bml.journalstatus.select.activated=Ativado + +/accountstatus.bml.journalstatus.select.deleted=Deletado + +/accountstatus.bml.journalstatus.select.suspended=Suspenso + +/accountstatus.bml.title=Status da Conta + +/allpics.bml.current=Imagens Atuais + +/allpics.bml.default=Padrão + +/allpics.bml.edit2=Você pode editar as palavras-chave de sua imagem ou carregar uma nova imagem. + +/allpics.bml.error.noparam=Você precisa especificar um parâmetro de usuário. + +/allpics.bml.keywords=Palavras-Chave: + +/allpics.bml.nopics.text.other=Este usuário ainda não carregou nenhuma imagem. + +/allpics.bml.nopics.text2=Você não tem nenhuma imagem. Para carregar uma, clique aqui. + +/allpics.bml.nopics.title=Nenhuma Imagem + +/allpics.bml.pics=Aqui estão as imagens de [[user]]. + +/allpics.bml.title=Imagens do Usuário + +/approve.bml.comm.success=Sucesso + +/approve.bml.comm.text<< +Foi adicionado á [[comm]]. + +Clique aqui para adicionar a comunidade á sua lista de amigos. +. + +/approve.bml.error.actionperformed=Essa acção já foi executada + +/approve.bml.error.internerr.invalidaction=Erro Interno: acção inválida + +/approve.bml.error.invalidargument=Argumento dado inválido + +/approve.bml.error.unknownactiontype=Acção tipo desconhecido + +/approve.bml.shared.success=Sucesso + +/approve.bml.shared.text<< +Foi-lhe dado acesso a escrever em [[shared]]. +Clique aqui para adicionar o jornal partilhado á sua lista de amigos. +. + +/approve.bml.title=Acção Aprovada + +/birthdays.bml.description=Abaixo estão as datas de aniversário de toda a gente que você listou como amigo. + +/birthdays.bml.title=Aniversários + +/changepassword.bml.btn.proceed=Continuar + +/changepassword.bml.changepassword.header=Trocar senha + +/changepassword.bml.changepassword.instructions=Preencha o formulário abaixo para mudar a sua senha. Para obter ajuda ao escolher uma boa senha e manter sua conta segura, veja este FAQ. + +/changepassword.bml.email.body=Sua senha foi alterada + +/changepassword.bml.email.subject=Trocar Senha + +/changepassword.bml.error.badcheck=Senha nova inválida: [[error]] + +/changepassword.bml.error.badnewpassword=A confirmação da sua nova senha não é igual à sua nova senha. Você deve ter cometido um erro ao digitar. Por favor digite e confirme sua nova senha novamente. + +/changepassword.bml.error.badoldpassword=Sua senha antiga não está correta. + +/changepassword.bml.error.blankpassword=Sua nova senha não pode ser em branco. + +/changepassword.bml.error.changetestaccount=Não é possível trocar a senha para a conta de teste. + +/changepassword.bml.error.characterlimit=As senhas devem ter no máximo 30 caracteres + +/changepassword.bml.error.invaliduser=Usuário [[user]] inválido. Esse usuário não existe. Você tem certeza que digitou corretamente? + +/changepassword.bml.error.mustenterusername=Você deve entrar com seu nome de usuário. + +/changepassword.bml.error.nonascii=Senhas devem ter somente símbolos ASCII. Por favor, escolha uma senha que não use nenhum símbolo que não seja ASCII. + +/changepassword.bml.error.notvalidated|staleness=1 +/changepassword.bml.error.notvalidated=Você não pode trocar sua senha se seu e-mail atual não foi validado. + +/changepassword.bml.newpassword=Nova Senha: + +/changepassword.bml.newpasswordagain=Nova Senha (de novo): + +/changepassword.bml.oldpassword=Senha Antiga: + +/changepassword.bml.proceed.instructions=Aperte o botão abaixo e sua senha será modificada. Você receberá também um e-mail, notificando a troca de senha. + +/changepassword.bml.success.text=Sua senha foi modificada e um e-mail foi enviado para você com uma mensagem lembrete. + +/changepassword.bml.title=Trocar Senha + +/community/index.bml.main<< + + + + +O Saguão dos 'Novatos', onde você vai encontrar respostas para muitas das perguntas que você pode ter. Visite , explore um pouco, e você logo se tornará um especialista! +p?> + + +
            +Adicione à sua página de amigos para manter-se atualizado sobre eventos e questões relevantes para a comunidade inteira do LiveJournal.
            +Adicione à sua página de amigos para manter-se informado quando planejamos interromper o serviço para manutenções, e relatórios de interrupções não planejadas. +p?> + + +AIM, ICQ, Yahoo!, MSN, ou Jabber. Se você também, assegure-se de listá-lis em suas informações pessoais. Se você tiver uma Conta Paga, você também pode habilitar seu celular ou pager para receber mensagens de texto. +p?> + + +Conta Paga. Há, claro, muitas outras maneiras de ajudar. +O LiveJournal é um projeto Open Source; se você tem experiência com linguagens de programação ou aplicações de servidores você pode dar uma olhada na Comunidade de Desenvolvimento do LiveJournal, . Se você tem idéias de como o LiveJournal pode ser melhor, dê uma olhada na Ãrea de Sugestões do LiveJournal, . Se você gostaria de ajudar com qualquer coisa, visite a Comunidade de Negócios de LiveJournal, . Se você gosta de ajudar as pessoas, visite nosso centro de suporte técnico e ajude alguém. Se você gostar de design gráfico, dê uma olhada na Comunidade de Arte do LiveJournal, . +p?> + + +Anime até Budismo Zen, de Astronomia a Zim. Você também encontrará comunidades regionais para todos os lugares do mundo. Provavelmente também existe uma comunidade do LiveJournal para o lugar onde você vive. +p?> + + +FAQ que explicará como criar sua própria comunidade. Existem também duas Categorias de FAQ (FAQs sobre Comunidades em geral e FAQs sobre administração de Comunidades) cobrindo praticamente tudo o que você precisará saber sobre comunidades. Se você ainda necessitar de mais informações, sinta-se à vontade para submeter uma requisição de suporte. +p?> + + + + +
              +
            • Dê uma olhada na Comunidade de Anúncios ()
            • +
            • Dê uma olhada na Comunidade de Procura ()
            • +
            + + +Mande um e-mail para Jesse Proulx, () o Diretor de Comunidades. +p?> + +. + +/community/index.bml.title=Central da Comunidade + +/community/join.bml.button.join=Entrar na Comunidade + +/community/join.bml.label.addtofriends=Adicionar "[[maintainer]]" a lista de Amigos.
            + +/community/join.bml.label.allowposting=Todos os membros têm permissão para escrever nesta comunidade, então você agora também pode escrever nela. Se você já tiver seu cliente do LiveJournal aberto em seu computador, terá de fazer o logout e novamente o login para que esta comunidade apareça na lista de journals em que você pode escrever. + +/community/join.bml.label.auth=Apesar de você ser agora um membro, esta comunidade permite que apenas membros autorizados escrevam nela. Entre em contato com um dos moderadores se você deseja esta autorização. Segue abaixo a lista de moderadores desta comunidade: [[admins]] + +/community/join.bml.label.banned=O moderador dessa comunidade impediu a sua entrada. + +/community/join.bml.label.closed=Essa é uma comunidade fechada. Se você está interessado em entrar nela, por favor, entre em contato com um de seus moderadores. Abaixo está a lista de moderadores dessa comunidade: [[admins]] + +/community/join.bml.label.commlogged=Você está conectado com uma conta compartilhada ou de comunidade, não com a sua conta pessoal + +/community/join.bml.label.errorcomminfo=A informação da comunidade especificada não é válida. + +/community/join.bml.label.expls=Clique no botão abaixo para entrar na comunidade "[[maintainer]]". Não marque o quadrado abaixo se você deseja entrar na comunidade sem ler seus textos na sua página de amigos. + +/community/join.bml.label.loginfirst=Para entrar em uma comunidade você precisa primeiro se conectar. + +/community/join.bml.label.membernow=Você agora é membro da Comunidade [[commname]]. + +/community/join.bml.label.sure=Está certo disso? + +/community/join.bml.success=Sucesso + +/community/join.bml.title=Junte-se à Comunidade + +/community/leave.bml.button.leave=Sair da Comunidade + +/community/leave.bml.label.buttontoleave=Aperte o botão para sair da comunidade "[[commname]]" + +/community/leave.bml.label.infoerror=A informação da comunidade especificada não é válida. + +/community/leave.bml.label.logoutfirst=Para sair de uma comunidade você precisa primeiro fazer login. + +/community/leave.bml.label.removed=Você saiu da Comunidade [[commname]] + +/community/leave.bml.label.removefromfriends=Retire também "[[user]]" da lista de amigos. + +/community/leave.bml.success=Sucesso + +/community/leave.bml.sure=Você tem certeza? + +/community/leave.bml.title=Deixar Comunidade + +/community/manage.bml.commlist.actions=Ações + +/community/manage.bml.commlist.actmembers=[Membros] + +/community/manage.bml.commlist.actmembers2=Membros + +/community/manage.bml.commlist.actsettings=[Ajustes] + +/community/manage.bml.commlist.actsettings2=Ajustes + +/community/manage.bml.commlist.header=Suas comunidades + +/community/manage.bml.commlist.none=Você não é moderador de nenhuma comunidade.<í> + +/community/manage.bml.commlist.text=Aqui estão as comunidades que você modera: + +/community/manage.bml.commlist.title=Título + +/community/manage.bml.commlist.username=Nome do usuário + +/community/manage.bml.create.header=Crie uma comunidade + +/community/manage.bml.create.text=Você pode também criar uma nova comunidade. + +/community/manage.bml.title=Administração da Comunidade + +/community/members.bml.error.alreadyadded=[[user]] não foi adicionado porque ele(ela) já tem acesso a essa comunidade. + +/community/members.bml.error.alreadysent=[[user]] não foi adicionado porque já lhe foi enviado o e-mail de confirmação em: [[datetime]]. Favor esperar pela sua resposta. + +/community/members.bml.error.invaliduser=Não é possível adicionar comunidade ou conta sindicalizada: [[user]] + +/community/members.bml.error.noaccess=Somente os moderadores da comunidade podem editar listas de membros. Você não é um moderador da comunidade [[comm]]. + +/community/members.bml.error.noattr=Não há atributos selecionados para o usuário: [[user]] + +/community/members.bml.error.nocomm=Comunidade não encontrada. + +/community/members.bml.error.nouser=Este usuário não existe: [[user]] + +/community/members.bml.key.admin=Administrador + +/community/members.bml.key.member=Membros + +/community/members.bml.key.moderate=Moderador + +/community/members.bml.key.post=Acesso para postagem + +/community/members.bml.key.preapprove=Não-moderado + +/community/members.bml.manage2=Administrar comunidades + +/community/members.bml.name=Nome da comunidade: [[name]] + +/community/members.bml.nextlink=(Próxima página...) + +/community/members.bml.prevlink=(Página anterior...) + +/community/members.bml.settings=[Configurações] + +/community/members.bml.success.header=Sucesso + +/community/members.bml.success.message=Suas mudanças foram salvas. + +/community/members.bml.success.return=Voltar à lista + +/community/members.bml.title=Membros da Comunidade + +/community/members.bml.update=Atualizar configurações + +/community/moderate.bml.approve.button=Sim, aprove. + +/community/moderate.bml.approve.header=Aprovar este texto? + +/community/moderate.bml.approve.preapprove=Além disso, adicione [[user]] à lista de usuários pré-aprovados desta comunidade. + +/community/moderate.bml.approve.text=Tem certeza que deseja aprovar este texto? + +/community/moderate.bml.brlist.actions=Ações + +/community/moderate.bml.brlist.poster=Escritor + +/community/moderate.bml.brlist.subject=Assunto começa + +/community/moderate.bml.brlist.time=Hora + +/community/moderate.bml.brlist.view=Visualizar + +/community/moderate.bml.browse.empty=A fila de moderação está vazia. + +/community/moderate.bml.browse.header=Moderar Comunidade + +/community/moderate.bml.browse.text=Aqui está a fila de moderação para a comunidade [[link]] + +/community/moderate.bml.choice.approve=Aprovar + +/community/moderate.bml.choice.reject=Rejeitar + +/community/moderate.bml.error.noaccess=Você não modera a comunidade [[comm]]. + +/community/moderate.bml.error.noentry=Texto não encontrado (talvez já tenha sido arrumado por outro moderador). + +/community/moderate.bml.error.nolist=Você não modera nenhuma comunidade. + +/community/moderate.bml.error.notfound=Conta de comunidade não encontrada. + +/community/moderate.bml.manage=Administrar comunidades + +/community/moderate.bml.moderate=Moderar esta comunidade + +/community/moderate.bml.modlist.actions=Ações + +/community/moderate.bml.modlist.actmodempty=[Moderar] + +/community/moderate.bml.modlist.actmoderate=Moderar + +/community/moderate.bml.modlist.count=Tamanho da fila + +/community/moderate.bml.modlist.header=Moderar Comunidades + +/community/moderate.bml.modlist.title=Título + +/community/moderate.bml.modlist.username=Nome de usuário + +/community/moderate.bml.posted.appheader=Pré-aprovado + +/community/moderate.bml.posted.apptext=Além disso, o usuário [[user]] foi adicionado à lista de usuários pré-aprovados desta comunidade. + +/community/moderate.bml.posted.header=Sucesso + +/community/moderate.bml.posted.proterror=O texto não foi postado por causa deste erro de protocolo: [[err]] + +/community/moderate.bml.posted.text=O texto foi postado com sucesso. + +/community/moderate.bml.reject.button=Sim, rejeite. + +/community/moderate.bml.reject.header=Rejeitar este texto? + +/community/moderate.bml.reject.reason=Você pode também explicar ao escritor as suas razões para rejeitar seu texto. Elas serão enviadas ao utilizador por e-mail. + +/community/moderate.bml.reject.text=Tem certeza que deseja rejeitar este texto? + +/community/moderate.bml.rejected.header=Rejeitado + +/community/moderate.bml.rejected.text=O texto foi rejeitado. + +/community/moderate.bml.title=Moderação de Comunidade + +/community/search.bml.button.clear=Limpar Formulário + +/community/search.bml.button.search=Procurar! + +/community/search.bml.checkbox.onlywithpics=Apenas comunidades com fotos + +/community/search.bml.label.byinterest=Por interesse + +/community/search.bml.label.bylocation=Por Local + +/community/search.bml.label.bytime=Por Horário de Atualização do Journal + +/community/search.bml.label.city=Cidade: + +/community/search.bml.label.country=País: + +/community/search.bml.label.displayoptions=Mostrar Opções + +/community/search.bml.label.hasmember=Tem Membros + +/community/search.bml.label.othercriteria=Outros critérios + +/community/search.bml.label.outputformat=Mostrar Como: + +/community/search.bml.label.records=Registros por página: + +/community/search.bml.label.searchcomm=Buscar Comunidades + +/community/search.bml.label.selecriteria=Selecione os critérios abaixo pelos quais você deseja encontrar comunidades. Os resultados são a intersecção de todos os critérios de busca. Em outras palavras, cada quadrado em que você clicar significa "E", não "OU". + +/community/search.bml.label.sortmethod=Método de ordenação: + +/community/search.bml.label.stateprovince=Estado: + +/community/search.bml.label.updated=Atualizado no último + +/community/search.bml.sel.bypicture=Por Foto + +/community/search.bml.sel.communityname=Nome da Comunidade + +/community/search.bml.sel.commview=Ver Comunidade + +/community/search.bml.sel.day=dia + +/community/search.bml.sel.month=mês + +/community/search.bml.sel.simple=Simples + +/community/search.bml.sel.updatetime=Atualizar Hora + +/community/search.bml.sel.username=Nome do Usuário + +/community/search.bml.sel.week=semana + +/community/search.bml.title=Procurar Comunidade + +/community/settings.bml.button.changecommunity=Modificar Configurações + +/community/settings.bml.button.createcommunity=Criar Comunidade + +/community/settings.bml.error.badpassword=Senha da comunidade inválida + +/community/settings.bml.error.hasentries=Essa conta já possui textos e não pode ser convertida. + +/community/settings.bml.error.maintainertype=O mantenedor da conta deve ser uma pessoa, não outra conta compartilhada. + +/community/settings.bml.error.noaccess=Somente os mantenedores de comunidades podem editar as configurações da comunidade. Você não é um mantenedor da comunidade [[comm]]. + +/community/settings.bml.error.notcomm=Essa não é uma uma conta de comunidade. + +/community/settings.bml.error.notfound=Conta de comunidade não encontrada. + +/community/settings.bml.error.samenames=A conta do mantenedor e da comunidade não podem ser a mesma. + +/community/settings.bml.label.anybodycan=Todos os Membros
            Qualquer pessoa pode postar imediatamente após se tornar membro. + +/community/settings.bml.label.changeheader=Modificar Configurações de Comunidade + +/community/settings.bml.label.changetext=Aqui você pode modificar as configurações para a comunidade que você modera. + +/community/settings.bml.label.commchanged=As configurações da sua comunidade foram modificadas. + +/community/settings.bml.label.commcreate=Essa é a conta que você quer transformar em uma comunidade. Ela deve ter sido criada anteriormente, mas não pode ainda estar em uso por uma pessoa, porque, após isso, muitas pessoas diferentes podem potencialmente postar nela. + +/community/settings.bml.label.commcreated=Sua comunidade já está criada. + +/community/settings.bml.label.commheader=Conta de Comunidade + +/community/settings.bml.label.comminfo=Informações sobre a comunidade + +/community/settings.bml.label.commopts=Opções da Comunidade + +/community/settings.bml.label.commsite=Website da comunidade + +/community/settings.bml.label.community=Comunidade: + +/community/settings.bml.label.createheader=Criar Comunidade + +/community/settings.bml.label.createtext=Aqui você pode criar uma conta de comunidade. Uma comunidade é um tipo especial de conta em que outros usuários podem postar. Para ver um exemplo de comunidade, veja a Comunidade de Festa de Seattle. + +/community/settings.bml.label.howoperates=Escolha como sua comunidade funciona. Você pode modificar isso mais tarde. + +/community/settings.bml.label.maintainer=Moderador: + +/community/settings.bml.label.maintainer.login=Se essa não é a conta do moderador, faça login como outra pessoa. + +/community/settings.bml.label.membership=Associação + +/community/settings.bml.label.modheader=Moderador + +/community/settings.bml.label.modis=Moderada
            Novos textos devem ser aprovados por um moderador. + +/community/settings.bml.label.modisnt=Não moderada
            Novos textos aparecem imediatamente. + +/community/settings.bml.label.modtext=As inscrições para essa comunidade são moderadas? + +/community/settings.bml.label.nmcan=Não-Membros Podem Postar
            Usuários podem postar nessa comunidade sem ter que participar dela. + +/community/settings.bml.label.nmcant=Não-Membros Não Podem Postar
            Usuários têm que participar da comunidade para postar nela. + +/community/settings.bml.label.nmheader=Post de Não-Membros + +/community/settings.bml.label.nmtext=Usuários podem postar nesta comunidade sem precisar associar-se à ela? + +/community/settings.bml.label.openmemb=Associação Aberta
            Qualquer pessoa pode associar-se, aprovação não é necessária. + +/community/settings.bml.label.password=Senha: + +/community/settings.bml.label.postaccess=Acesso para Escrever + +/community/settings.bml.label.rellinks=Links relevantes: + +/community/settings.bml.label.selcan=Membros Seletos
            Somente alguns membros podem postar nesta comunidade, assim que lhes for dado acesso pela conta mantenedora. + +/community/settings.bml.label.username=Nome do Usuário: + +/community/settings.bml.label.whocanjoin=Quem pode participar da sua comunidade? + +/community/settings.bml.label.whocanpost=Quem pode postar nesta comunidade? + +/community/settings.bml.manage2=Gerenciar comunidades + +/community/settings.bml.members=[Membros] + +/community/settings.bml.name=Nome da comunidade: [[name]] + +/community/settings.bml.success=Sucesso + +/community/settings.bml.title.create=Criar Comunidade + +/community/settings.bml.title.modify=Configurações da Comunidade + +/create.bml.age.check.question=Você tem menos de 13 anos? + +/create.bml.age.check.yes=Sim, eu tenho menos de 13 anos. + +/create.bml.age.check2.question=Você tem mais de 13 anos de idade? + +/create.bml.age.check2.yes=Sim, eu tenho mais que 13 anos de idade. + +/create.bml.age.head=Idade + +/create.bml.btn.create=Criar Journal + +/create.bml.btn.proceed=Continuar... + +/create.bml.captcha.answer=Responder + +/create.bml.captcha.audiodesc=Digite os números que você ouvir para provar que você não é um robô de spam + +/create.bml.captcha.desc=Digite as letras e números que você vê abaixo, para provar que você não é um robô de spam. Se você não conseguir ler o texto, digite "AUDIO" e faça o teste de áudio no lugar do escrito. + +/create.bml.captcha.invalid=Resposta do desafio anterior inválida. Tente outro desagio. + +/create.bml.captcha.play=Toque o som + +/create.bml.captcha.prove=Prove que você é humano + +/create.bml.clusterselect.cluster=Grupo + +/create.bml.clusterselect.clusternum=Grupo [[número]] + +/create.bml.clusterselect.head=Seleção de Grupo + +/create.bml.clusterselect.nocluster=Nenhum Grupo + +/create.bml.clusterselect.text=Por favor selecione o grupo em que você quer criar esta conta. Observação: esta é somente uma opção de teste. Na apresentação, usuários não escolherão isso, ou saber qualquer coisa a respeito. + +/create.bml.create.head=Criando um novo Journal + +/create.bml.create.text=Criar um LiveJournal é fácil, basta seguir as instruções abaixo! + +/create.bml.email.head=Seu e-mail + +/create.bml.email.input.head=E-mail: + +/create.bml.email.text2=Por razões de segurança necessitamos do seu endereço de e-mail. Jamais, em qualquer circunstância será dado ou vendido a "spammers". Detesta-mos isso acima de tudo. Por favor leia a nossa política de privacidade para mais informações. + +/create.bml.error.coppa.under13=Desculpe, devido às restrições da COPPA, você não pode usar os serviços do LiveJournal até completar 13 anos. Por favor volte no seu 13º aniversário. + +/create.bml.error.email.blank=Você deve fornecer o seu e-mail. + +/create.bml.error.email.lj_domain=Você não pode usar um disfarce de [[domínio]] quando cria uma conta. Por favor registre um endereço de e-mail diferente. + +/create.bml.error.email.nospaces=Espaços não são permitidos no endereço de e-mail. Se você usa AOL, lembre-se que seu endereço de e-mail para internet é seu nome de usuário sem nenhum espaço, seguido de @aol.com + +/create.bml.error.password.asciionly=Você só pode usar caracteres ASCII na sua senha. + +/create.bml.error.password.blank=Você deve digitar uma senha. + +/create.bml.error.password.nomatch=As senhas não conferem. + +/create.bml.error.postrequired=POST necessário. + +/create.bml.error.username.blank=Por favor insira um nome ou apelido. + +/create.bml.error.username.inuse=Nome do usuário utilizado por outra pessoa; por favor selecione outro nome do usuário diferente. + +/create.bml.error.username.iscode=O nome de usuário aparenta ser um código de convite, não um nome de usuário. + +/create.bml.error.username.mustenter=Você deve inserir um nome de usuário. + +/create.bml.error.username.reserved=Desculpe, este nome de usuário está reservado. + +/create.bml.initial.friend.news=Notícias e eventos do Livejournal + +/create.bml.initialfriends=Adicione estes journals à sua lista de amigos para ficar sempre atualizado com notícias e informações sobre o site. + +/create.bml.name.head=Seu Nome + +/create.bml.name.input.head=Nome: + +/create.bml.name.text=Qual é seu nome ou apelido? Ele aparecerá no topo de seu journal, no diretório de usuários caso você decida aparecer na listagem. Você não precisa inserir seu nome completo e nem seu nome real. + +/create.bml.password.head=Senha + +/create.bml.password.input.head1=Senha: + +/create.bml.password.input.head2=Confirme sua senha: + +/create.bml.password.text=Escolha uma senha. + +/create.bml.proceed.btn.proceed=Prossiga... + +/create.bml.proceed.warning=Só pressione Prosseguir uma vez!! + +/create.bml.success.btn.enterinfo=Entre Suas Informações Pessoais + +/create.bml.success.head=Sucesso! + +/create.bml.success.text1=Seu journal foi criado. Informações importantes sobre o registro foram enviadas para [[email]] contendo mais instruções. Assegure-se de confirmar a criação do seu journal clicando no link enviado para você no e-mail. + +/create.bml.success.text2=Seu LiveJournal estará disponível em: + +/create.bml.success.text3=Agora, por favor gaste um tempinho para preencher informações sobre você. É opcional, mas dá uma idéia de quem está utilizando o LiveJournal. + +/create.bml.title=Criar um novo Journal + +/create.bml.tos.error=Você deve ler e concordar com os termos de uso antes de criar uma conta. + +/create.bml.tos.haveread=Eu li e concordo com os Termos de Uso. + +/create.bml.tos.heading=Termos de Uso + +/create.bml.tos.p1.2=Antes de continuar tem que ler e concordar com as Regras de Serviço. + +/create.bml.useacctcodes.entercode=Para criar uma nova conta, digite o código de criação aqui. Para mais informações, veja Como eu crio uma conta? + +/create.bml.useacctcodes.welcome=Bem-vindo(a) + +/create.bml.username.box.head=Nome do usuário + +/create.bml.username.charsallowed=Seu nome de usuário deve conter somente letras minúsculas (a-z), dígitos (0-9) e a barra sublinhada (_).
            Além disso, ele não deve ultrapassar 15 caracteres. + +/create.bml.username.forpaidaccts=Ou, para contas pagas: + +/create.bml.username.head=Nome do usuário + +/create.bml.username.ljaddress=Seu journal poderá ser visitado através desses endereços: + +/create.bml.username.text=Cada usuário de [[sitename]] deve ter seu próprio nome de usuário. Seu nome de usuário aparece no endereço do seu journal e é o que você usa para entrar no servidor [[sitename]]. Ele também aparece quando você deixa comentários no journal de outras pessoas. + +/create.bml.username.username=nome do usuário + +/customize/index.bml.change=Modificar + +/customize/index.bml.choose=Você quer usar o sistema de estilos antigo, ou o novo? + +/customize/index.bml.choose.header=Escolha o sistema de estilos + +/customize/index.bml.choose.s1=Sistema antigo (S1) + +/customize/index.bml.choose.s2=Sistema novo (S2) + +/customize/index.bml.error.cant_generate_user_layer=Não foi possível gerar camada de usuário. + +/customize/index.bml.error.fail_create_style=Falha ao criar novo estilo. + +/customize/index.bml.error.not_your_layout=Não é seu layout. + +/customize/index.bml.error.not_your_theme=Não é seu tema + +/customize/index.bml.previews=(Exemplos) + +/customize/index.bml.s1=O sistema antigo de estilos é configurado através da página Modificar Journal. + +/customize/index.bml.s1.header=Utilizando S1 + +/customize/index.bml.s2.advanced.denied=Somente quem tem contas pagas, permanentes ou de "pioneiros" podem usar a área de personalização avançada. Descubra os benefícios de ter uma conta paga. + +/customize/index.bml.s2.advanced.header=Personalizações Avançadas + +/customize/index.bml.s2.advanced.permitted=Para criar novas camadas e estilos do zero, visite o centro de personalização avançada. + +/customize/index.bml.s2.customize.header=Segundo passo: Personalizar Layout + +/customize/index.bml.s2.customize.language=As seguintes linguagens são totalmente ou parcialmente suportadas por este layout. + +/customize/index.bml.s2.customize.language.custom=(Personalizado) + +/customize/index.bml.s2.customize.language.header=Linguagem + +/customize/index.bml.s2.customize.settings=Se você quiser personalizar seu journal ainda mais, aqui vocês pode modificar definições individuais para deixar o visual do seu journal do jeito que quiser. + +/customize/index.bml.s2.customize.settings.delete=Remover Personalizações + +/customize/index.bml.s2.customize.settings.delete.confirm=Tem certeza de que deseja remover as customizações? + +/customize/index.bml.s2.customize.settings.edit=Editar Personalizações + +/customize/index.bml.s2.customize.settings.header=Modificar Configurações Individuais + +/customize/index.bml.s2.customize.settings.new=Personalizar + +/customize/index.bml.s2.customize.themes=Escolha um entre os temas deste layout a seguir. + +/customize/index.bml.s2.customize.themes.default=(Padrão do Layout) + +/customize/index.bml.s2.customize.themes.header=Temas + +/customize/index.bml.s2.layout=Defina seu layout. A seleção de temas e modificações personalizadas dependem do seu layout, então esta definição descarta todas as outras edições que você tenha feito. + +/customize/index.bml.s2.layout.header=Passo 1: Layout + +/customize/index.bml.s2.related.editinfo.about=Defina os títulos de seu journal e as várias opções. + +/customize/index.bml.s2.related.header=Páginas Relacionadas + +/customize/index.bml.s2.related.links.about=Alguns estilos podem incluir a lista de links que você gerencia. + +/customize/index.bml.s2.related.modify.about=Defina o jogo de ícones de humores de seu journal + +/customize/index.bml.title=Personalizar Journal + +/delcomment.bml.changeoptions=Nota: Da página de [[link]], você pode escolher se quer que todos
            , usuários registrados ou somente amigos possam deixar comentários. + +/delcomment.bml.confirm.banuser=Proibir que [[usuário]] deixe comentários em seu journal + +/delcomment.bml.confirm.body=Tem certeza que deseja deletar este comentário? + +/delcomment.bml.confirm.head=Deletar este comentário? + +/delcomment.bml.confirm.spam=Marque este comentário como lixo + +/delcomment.bml.confirm.submit=Deletar Comentário + +/delcomment.bml.error.alreadydeleted=O comentário especificado já foi deletado. + +/delcomment.bml.error.cantdelete=Um comentário só pode ser deletado por seu autor ou pelo dono do journal. + +/delcomment.bml.error.cantdelete.comm=Um comentário só pode ser deletado por seu autor, o autor do post, ou um moderador da comunidade. + +/delcomment.bml.error.invalidtype=Tipo de comentário inválido. Esta página só aceita comentários em posts. + +/delcomment.bml.error.nocomment=Esse comentário não esiste. + +/delcomment.bml.success.andban=O comentário foi apagado, e o utilizdor [[user]] foi proibido de comentar no teu jornal. + +/delcomment.bml.success.head=Apagado + +/delcomment.bml.success.noban=O comentário foi apagado. + +/delcomment.bml.success.spam=Adicionalmente, os administradores deste site foram notificados que este comentário é lixo. Agradecemos a sua notificação. + +/delcomment.bml.title=Apagar Comentário + +/developer/index.bml.clients=Você quer criar ou melhorar um cliente o LiveJournal para a sua plataforma? Maravilhoso! Abaixo alguns recursos para ajudá-lo a saber como o LiveJournal funciona. + +/developer/index.bml.clients.header=Escrevendo Clientes para o LiveJournal + +/developer/index.bml.clients.links<< +
            +
            Servidor do Livejournal<->Protocolo Cliente
            +
            Aprenda como clientes do Livejournal no seu desktop conversam com o servidor do Livejournal e vice versa. Entender isso é a primeira coisa que você precisa fazer antes de desenvolver ou melhorar um cliente para a sua plataforma.
            +
            Documentação Completa do Protocolo
            +
            Todos os modos do protocolo & métodos.
            +
            Lista de Clientes
            +
            Uma lista de clientes mais utilizados para conectar-se ao Livejournal. A maioria destes clientes é de código aberto, e todos eles são grátis. Este é um lugar legal para pegar exemplos para o seu cliente.
            +
            + +. + +/developer/index.bml.code.header=Repositório do Código Fonte do Livejournal + +/developer/index.bml.dbschema<< +Curioso sobre o schema da base de dados? +O SQL para criar todas as tabelas e populá-las está incluído no código do servidor. +. + +/developer/index.bml.dbschema.header=Schema do Banco de Dados + +/developer/index.bml.notice.header=Nota + +/developer/index.bml.notice1=As informações seguintes são somente para programadores e usuários avançados. Se você somente quer utilizar Livejournal para manter o seu journal, legal! Usuários normais não têm que se preocupar com essas coisas. + +/developer/index.bml.notice2=Dito isso, o conteúdo abaixo é dividido em duas seções: informações de como modificar a aparência das páginas do LiveJournal, e informações de como escrever clientes LiveJournal para o servidor do LiveJournal. + +/developer/index.bml.styles=Não gosta da maneira que seu jornal é apresentado? Não tenha medo... o seu journal pode ser personalizado... leia a documentação abaixo e você irá saber tudo o que é preciso para o seu journal ser apresentado da maneira que você quer. + +/developer/index.bml.styles.header=Alterando a aparência de um LiveJournal + +/developer/index.bml.styles.s1.header=Sistema de Estilos 1 + +/developer/index.bml.styles.s1.system=Sistema de Estilos + +/developer/index.bml.styles.s1.system.about=Visão Geral de como o primeiro estilo do sistema é configurado. + +/developer/index.bml.styles.s1.varlist=Lista Variável. + +/developer/index.bml.styles.s1.varlist.about=Lista em ordem alfabética de todas as variáveis que você pode personalizar. + +/developer/index.bml.styles.s1.views=Tipos de Visualização + +/developer/index.bml.styles.s1.views.about=Uma lista com os diferentes tipos de maneiras que você pode ver seu jornal, e detalhes de cada um. + +/developer/index.bml.styles.s2.header=Estilo do Sistema 2 + +/developer/index.bml.styles.s2.layerbrowse=Navegador de Camadas S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Uma Lista completa das camadas S2 que compoem o sistema denominado S2. O importante aqui são as camadas do núcleo, que definem as variáveis de base, funções, e classes que fazem o S2 uma poderosa linguagem de design. + +/developer/index.bml.styles.s2.manual=O manual de S2 + +/developer/index.bml.styles.s2.manual.about=Informação detalhada sobre como usar o S2 no LiveJournal. + +/developer/index.bml.title=Informações para Desenvolvedores + +/directory.bml.browse.country.desc=Escolha um país para ler LJournals desse país... + +/directory.bml.browse.country.title=Procurar journals por país + +/directory.bml.browse.usa.desc=Clique num Estado dos EUA para ler journals deste Estado, ou clique em um país para ler journals de lá. + +/directory.bml.browse.usa.title=Procurar Jornais por estado dos EUA + +/directory.bml.open=Aberto + +/directory.bml.search.monkey=Centenas de macacos amestrados estão correndo atrás dos seus resultados. Por favor, espere um pouquinho. + +/directory.bml.search.title=A procurar + +/directory.bml.user=Utilizador + +/doc/index.bml.about.header=Bem vindo + +/doc/index.bml.docs.faq.about=Perguntas Frequentes acerca do Livejournal.com + +/doc/index.bml.docs.guides.title=Guias + +/doc/index.bml.docs.header=Documentos + +/doc/index.bml.docs.howto.about=Truques e dicas para ajudar a modificar a sua conta do LiveJournal + +/doc/index.bml.docs.server.title=Manual do Servidor do LiveJournal + +/doc/index.bml.title=Documentação + +/doc/index.bml.volunteering.about=Se você gostaria de ajudar a documentação do Livejournal, verifique os seguintes fórums + +/doc/index.bml.volunteering.ljsysdoc=Discussões sobre o sistema de documentação do LiveJournal + +/doc/tour/index.bml.clients.caption<< +Os clientes do LiveJournal são pequenos programas que pode usar no seu computador e que permitem actualizar o seu jornal quando estiver online sem que para isso necessite de um browser. +Os Clientes estão disponíveis para qualquer plataforma e muitos deles podem ser fácilmente modificados. +. + +/doc/tour/index.bml.clients.title=Clientes + +/doc/tour/index.bml.comms.caption=LiveJournal é uma grande comunidade interativa, então não seria surpresa que existam muitos membros com interesses parecidos. Para esse fim, nós oferecemos a possibilidade de criar comunidades, ou journals na qual muitas pessoas podem postar. + +/doc/tour/index.bml.comms.title=Comunidades + +/doc/tour/index.bml.create.title=Criando uma Conta + +/doc/tour/index.bml.friends.title=Amigos + +/doc/tour/index.bml.intro.title=Bem vindo + +/doc/tour/index.bml.modify.title=Personalizando + +/doc/tour/index.bml.nav.next=Próximo --> + +/doc/tour/index.bml.nav.prev=<-- Anterior + +/doc/tour/index.bml.sitemap.title=Mapa do Site + +/doc/tour/index.bml.support.title=Pedir Ajuda + +/editinfo.bml.advanced.about=Não te procupes com isto se não sabes o que isto é. + +/editinfo.bml.advanced.title=Opções Avançadas + +/editinfo.bml.allowshowcontact.about<< +Você deve selecionar essa opção se quiser que outras pessoas possam entrar em contato com você por e-mail, ICQ ou AOL Instant Messenger, +todos direto do LiveJournal. +. + +/editinfo.bml.allowshowcontact.email=Meu endereço de e-mail que deve ser publicado: + +/editinfo.bml.allowshowcontact.email.actual_only=Somente o meu e-mail comum + +/editinfo.bml.allowshowcontact.email.both=Ambos (comum + [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Somente o e-mail do LiveJournal + +/editinfo.bml.allowshowcontact.email.neither=Nenhum. Não mostre nenhum dos meus e-mails + +/editinfo.bml.allowshowcontact.email.no_show=Não mostre o meu e-mail + +/editinfo.bml.allowshowcontact.email.show=Mostre o meu e-mail + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Com esta opção podes optar por esconder o teu endereço de e-mail (No entanto ainda serão mostrados os teus outros contactos) + +/editinfo.bml.allowshowcontact.title=Mostrar os seus meios de contato no seu LiveJournal? + +/editinfo.bml.allowshowinfo.about=Selecione essa opção se você quiser que sua cidade/estado/país e aniversário sejam visíveis para outros usuários. + +/editinfo.bml.allowshowinfo.title=Mostrar cidade & aniversário? + +/editinfo.bml.autotranslate.about<< +Nessa opção você deve dizer ao LiveJournal qual codificação assumir para os seus textos e comentários que foram postados antes do site ter sido convertido para a opção Unicode. +Se você escreve em Inglês ou Português, escolha a opção "Western European". +. + +/editinfo.bml.autotranslate.header=Converter textos antigos de: + +/editinfo.bml.bday.title=Aniversário + +/editinfo.bml.bday.year.opt=O ano é opcional + +/editinfo.bml.bdayreminders.about=Se você quiser receber um e-mail para lembrar os aniversários de seus amigos do LiveJournal, selecione essa opção. + +/editinfo.bml.bdayreminders.header=Me lembre sobre os aniversários (atualmente desabilitado) + +/editinfo.bml.bio.about|staleness=1 +/editinfo.bml.bio.about=Aqui você deve escrever um pequena biografia que vai aparecer na sua página de informação de usuário. + +/editinfo.bml.bio.header=Sobre Você + +/editinfo.bml.blockrobots.about=Se optar por selecionar esta opção, será pedido a todos os "robôs" para se irem embora. Porém nem todos esses "robôs" respeiam as regras. + +/editinfo.bml.chat.msnusername.title=Nome do Usuário MSN + +/editinfo.bml.city.title=Cidade + +/editinfo.bml.country.choose=Escolha um país + +/editinfo.bml.country.title=País + +/editinfo.bml.donotlog=Não + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about|staleness=1 +/editinfo.bml.enableboards.about=Selecione essa opção se você quiser que outros usuários comentem os textos do seu journal. (o estilo de journal que você utiliza deve ser capaz de suportar isso) + +/editinfo.bml.enableboards.header=Liberar quadros de mensagens + +/editinfo.bml.encoding.about=Não se preocupe com isso. Em geral, somente usuários internacionais que escrevem em várias línguas diferentes vão precisar fazer alguma modificação aqui. + +/editinfo.bml.encoding.header=Opções de codificação + +/editinfo.bml.error.day.notinmonth=Dia inválido para aquele mês. + +/editinfo.bml.error.day.outofrange=Dia de nascimento inválido. Entre com um dia entre 1-31. + +/editinfo.bml.error.email.lj_domain|staleness=1 +/editinfo.bml.error.email.lj_domain<< +Você não pode colocar um e-mail @[[domain]]. +Coloque o seu endereço de e-mail verdadeiro nesse campo. +Se você tem uma conta paga, seu endereço [[user]]@[[domain]] vai repassar suas mensagens para o seu endereço de e-mail verdadeiro. +Para escolher quais dos seus e-mails você quer que seja mostrado publicamente, leia a opção "Mostrar seus meios de contato no seu LiveJournal?" abaixo. +. + +/editinfo.bml.error.email.none=Você deve fornecer um e-mail + +/editinfo.bml.error.excessive_int=Desculpe, você listou muitos interesses. O limite é 150, mas você listou [[intcount]]. Todas as mudanças que você fez nos seus interesses não foram salvas. Volte e diminua sua lista, depois tente salvar de novo. + +/editinfo.bml.error.invalidbio=Sua biografia contém caracteres inválidos. Você deve visitar a página de conversão para convertê-la para Unicode. + +/editinfo.bml.error.invalidname=Seu nome contém caracteres inválidos. Você deve visitar a página de conversão para convertê-lo para Unicode. + +/editinfo.bml.error.locale.invalid_country=Escolheste um país inválido. + +/editinfo.bml.error.month.outofrange=Mês de aniversário incorrecto. Introduza um número entre 1 - 12 (Jan-Dez) + +/editinfo.bml.error.year.notenoughdigits=Ano de nascimento inválido. Digite um ano de 4 dígitos. + +/editinfo.bml.error.year.outofrange=Ano de nascimento inválido. + +/editinfo.bml.finished.about=Qunado finalizado, aperte o botão "Salvar Alterações" abaixo. + +/editinfo.bml.finished.header=Acabou? + +/editinfo.bml.finished.save_button=Salvar Alterações + +/editinfo.bml.gender.title=Sexo + +/editinfo.bml.hidefriendof.about=Se você marcar aqui, a lista de pessoas que listam você como amigo fica escondida na sua página de perfil. + +/editinfo.bml.hidefriendof.header=Ocular a lista "Amigo de" + +/editinfo.bml.howhear.about|staleness=1 +/editinfo.bml.howhear.about=Só por curiosidade, onde você ouviu falar sobre o [[sitename]]? Se foi por meio de um usuário, escreva o nome dele, se foi por meio de outras fonte/artigo/link/website, insira a informação necessária. + +/editinfo.bml.howhear.header=Curiosidade + +/editinfo.bml.htmlemail.about|staleness=1 +/editinfo.bml.htmlemail.about<< +Marque aqui se o seu programa de e-mail suporta completamente HTML. +Muitos clientes tentam suportá-la mas falham horrivelmente. +Se você não marcar, o LiveJournal irá enviar somente e-mails texto. +. + +/editinfo.bml.htmlemail.header=Enviar e-mails HTML + +/editinfo.bml.int.ex.bad=MAU Exemplo: Eu gosto de muitas bandas e de assitir filmes e de conversar com meus amigos e de sair. As informações no seu perfil vão aparecer dessa maneira. + +/editinfo.bml.int.ex.good=BOM Exemplo: ciclismo, esqui, computadores, dvds, mp3s, queijo, mulheres + +/editinfo.bml.int.header=Interesses + +/editinfo.bml.login.enterinfo=Entre com seu nome do usuário e senha para modificar suas informações pessoais. + +/editinfo.bml.login.forgot.header=Esqueceu alguma coisa? + +/editinfo.bml.login.forgot.recover=Se você esqueceu seu nome de usuário ou senha, clique aqui!. + +/editinfo.bml.logip.always=Sempre + +/editinfo.bml.logip.anon_only=Somente de anônimos + +/editinfo.bml.logip.header=Logar o endereço IP de pessoas respondendo? + +/editinfo.bml.mangleaddress.about|staleness=1 +/editinfo.bml.mangleaddress.about=Se você teme que robôs de spam encontrarão seu e-mail no LiveJournal, selecione essa opção. Seu e-mail será modificado de forma a não ser encontrado por robôs que coletam e-mails. + +/editinfo.bml.name.title=Nome + +/editinfo.bml.newemail.subject=E-mail Modificado + +/editinfo.bml.numcomments.header=Adicionar &nc=xx nas URLs de comentários + +/editinfo.bml.optional=Opcional + +/editinfo.bml.opt_in.header=Me mande notícias do LiveJournal + +/editinfo.bml.persinfo.header=Informação Pessoal + +/editinfo.bml.screen.all=Todos + +/editinfo.bml.screen.anon=Anônimo + +/editinfo.bml.security.header|staleness=1 +/editinfo.bml.security.header=Segurança + +/editinfo.bml.security.visibility.anybody=Qulaquer um + +/editinfo.bml.security.visibility.everybody=Todo mundo + +/editinfo.bml.security.visibility.friends=Só meus Amigos + +/editinfo.bml.security.visibility.regusers=Usuários registrados + +/editinfo.bml.settings.header=Opções do LiveJournal + +/editinfo.bml.state.other=Ou digite outro estado/província/território + +/editinfo.bml.state.title=Estado + +/editinfo.bml.state.us=Estados dos EUA + +/editinfo.bml.success.header=Sucesso! + +/editinfo.bml.switch.button=Trocar + +/editinfo.bml.switch.header=Trocar Journal + +/editinfo.bml.switch.workwith=Trabalhar com o Journal: + +/editinfo.bml.title=Editar Informações Pessoais + +/editinfo.bml.tm.details=detalhes + +/editinfo.bml.translatemailto.header=Passar as notificações de e-mail para: + +/editinfo.bml.userpic.about=Você pode ver a miniatura da figura que você adicionou para te representar no site do LiveJournal, no seu próprio journal e nos journals dos seus amigos. + +/editinfo.bml.userpic.edit|staleness=1 +/editinfo.bml.userpic.edit=Para deletar essa imagem ou adicionar uma nova vá aqui + +/editinfo.bml.userpic.header=Sua Imagem + +/editinfo.bml.userpic.none=nenhuma imagem adicionada + +/editinfo.bml.webpagename.title=Nome da Página + +/editinfo.bml.webpageurl.title=URL da Página + +/editinfo.bml.whoreply.header=Quem pode responder os seus textos? + +/editinfo.bml.zip.title=Código postal + +/editinfo.bml.zip.usonly=Código Postal de 5 dígitos, somente residentes dos EUA + +/editjournal.bml.btn.proceed=Prosseguir... + +/editjournal.bml.certainday=Dia específico: + +/editjournal.bml.recententries=textos mais recentes + +/editjournal.bml.recententry=Texto mais recente + +/editjournal.bml.title=Editar Textos + +/editjournal.bml.viewwhat=Ver esses textos: + +/editjournal_do.bml.btn.edit=Editar texto selecionado + +/editjournal_do.bml.btn.save=Salvar texto + +/editjournal_do.bml.continue.head=Pressione para continuar... + +/editjournal_do.bml.continue.text=Depois de selecionar um item para editar ou deletar, pressione o botão Editar abaixo. + +/editjournal_do.bml.currmood|staleness=1 +/editjournal_do.bml.currmood=Humor Atual: + +/editjournal_do.bml.currmusic=Música Atual: + +/editjournal_do.bml.date=Data: + +/editjournal_do.bml.default=padrão + +/editjournal_do.bml.edit.text|staleness=2 +/editjournal_do.bml.edit.text=Edite os campos do seu texto que você quer modificar e pressione o botão de salvar no fim da página. Para deletar um texto, apague todo o texto e pressione salvar... O texto será deletado. + +/editjournal_do.bml.error.getting=Houve um erro ao tentar editar os textos: + +/editjournal_do.bml.error.modify=Ocorreu um erro ao modificar o seu journal: + +/editjournal_do.bml.error.nofind=Não foi possível encontrar o texto selecionado. + +/editjournal_do.bml.event=Evento: + +/editjournal_do.bml.localtime=Hora local: + +/editjournal_do.bml.opt.nocomments=Proibir Comentários: + +/editjournal_do.bml.opt.noemail=Não enviar comentários por e-mail: + +/editjournal_do.bml.opt.noformat=Não formatar automaticamente: + +/editjournal_do.bml.other=Outro: + +/editjournal_do.bml.pickentry.head=Escolha um texto para editar + +/editjournal_do.bml.pickentry.text=Selecione qual item você quer editar e pressione o botão no fim da página. + +/editjournal_do.bml.picture=Figura: + +/editjournal_do.bml.save.head=Pressione para salvar... + +/editjournal_do.bml.save.text=Quando você terminar a edição do seu texto, pressione Salvar + +/editjournal_do.bml.subject=Assunto: (opcional) + +/editjournal_do.bml.success.delete=Texto deletado. + +/editjournal_do.bml.success.edit=Texto modificado. Você pode vê-lo aqui. + +/editjournal_do.bml.success.head=Sucesso + +/editjournal_do.bml.timeformat=24 horas + +/editjournal_do.bml.title=Editar textos do Journal + +/editpics.bml.btn.proceed=Prosseguir + +/editpics.bml.error.badurl=O endereço para a figura a ser enviada não parece correto. Ele deve começar com http:// + +/editpics.bml.error.filetoolarge=A imagen enviada é muito grande. O tamanho do arquivo não pode exceder [[maxsize]]. + +/editpics.bml.error.invalidimage=Arquivo de imagem inválido. + +/editpics.bml.error.toomanypics2=Você já atingiu o limite de [[maxpics]] imagens. Você não pode fazer upload desta figura antes de apagar alguma existente. + +/editpics.bml.error.unsupportedtype=Arquivos do tipo [[filetype]] não são suportados. Você só pode fazer upload de arquivos GIF, PNG ou JPG. Quase todos os programas de edição de imagem/foto podem fazer essa conversão para você. + +/editpics.bml.error.urlerror=Ocorreu um erro ao carregar sua imagem. + +/editpics.bml.restriction.fileformat=O formato da imagem deve ser PNG, GIF ou JPG + +/editpics.bml.restriction.filesize=O tamanho da imagem deve ser menor de 40k + +/editpics.bml.restriction.imagesize=A dimensão da imagem não pode ser maior que 100x100 pixels + +/editpics.bml.uploadheader=Fazer upload de uma nova figura + +/export.bml.btn.proceed=Prosseguir... + +/export.bml.label.encoding=Codificação: + +/export.bml.label.field.currents=Humor Atual & Música + +/export.bml.label.field.event=Evento + +/export.bml.label.field.security=Nível de Segurança + +/export.bml.label.field.subject=Título + +/export.bml.label.month.year=aaaa: + +/export.bml.title=Exportar o Jornal + +/export.bml.what.entries=Textos do journal + +/export_do.bml.error.encoding=Código Selecionado Inválido + +/friends/add.bml.add.header=Sucesso + +/friends/add.bml.add.text|staleness=2 +/friends/add.bml.add.text=O usuário foi adicionado para a sua lista de Amigos. Você pode ver a sua Página de Amigos aqui + +/friends/add.bml.add.title=Amigo Adicionado! + +/friends/add.bml.btn.add=Adicionar [[user]] + +/friends/add.bml.btn.modify=Modificar + +/friends/add.bml.btn.remove=Remover + +/friends/add.bml.colors.bg=Cor de Fundo + +/friends/add.bml.colors.fg=Cor da Letra + +/friends/add.bml.colors.header=Cores + +/friends/add.bml.colors.hover=Passe o mouse em cima da cor para ver o nome dela + +/friends/add.bml.colors.text=Opcionalmente você também pode selecionar as cores que representam [[user]] na sua lista de amigos. + +/friends/add.bml.confirm.header=Adicionar [[user]] como um amigo? + +/friends/add.bml.confirm.text=Para adicionar [[user]] para a sua lista de Amigos, aperte o botão abaixo. + +/friends/add.bml.confirm.title=Adicionar Amigo + +/friends/add.bml.error1.header=Faça Login Primeiro + +/friends/add.bml.error1.text<< +Para adicionar um usuário para sua lista de amigos você deve primeiro fazer login. Se você ainda não possui uma conta você pode criar uma para rastrear os journals dos seus amigos. + +. + +/friends/add.bml.error1.title=Adicionar Amigo + +/friends/add.bml.error2.text=Nome do usuário inválido ou faltando. Para adicionar um amigo, vá para a página de editar amigos page. + +/friends/add.bml.error3.text=Você já tem [[user]] listado como seu amigo. No entanto, você pode modificar as cores que você escolheu para representá-lo(a). + +/friends/add.bml.error3.title=Modificar Amigo + +/friends/add.bml.groups.header=Grupos de Amigos + +/friends/add.bml.groups.nogroup=Não existem grupos de amigos criados. + +/friends/add.bml.remove.header=Sucesso + +/friends/add.bml.remove.text=O usuário foi removido da sua lista de amigos. Você pode ver sua página de amigos aqui. + +/friends/add.bml.remove.title=Amigo Removido! + +/friends/edit.bml.title=Editar Amigos + +/friends/editgroups.bml.btn.ge.del=Apagar + +/friends/editgroups.bml.btn.ge.new=Novo + +/friends/editgroups.bml.btn.ge.ren=Renomear + +/friends/editgroups.bml.btn.gs.private=Privado + +/friends/editgroups.bml.btn.gs.public=Público + +/friends/editgroups.bml.btn.mv.down=Para baixo + +/friends/editgroups.bml.btn.mv.up=Para Cima + +/friends/editgroups.bml.confirm.delete=Tem a certeza que deseja apagar esta lista de amigos? + +/friends/editgroups.bml.done.btn=Salvar Modificações + +/friends/editgroups.bml.done.header=Acabado? + +/friends/editgroups.bml.done.text=Quando acabares, carrega no botão abaixo para gravar o que mudaste. + +/friends/edit_do.bml.addfriends.head=Adicionar Amigos + +/friends/index.bml.editgroups.about=Crie, edite ou delete subgrupos de amigos. + +/friends/index.bml.filter|staleness=1 +/friends/index.bml.filter=Estes grupos de amigos podem ser utilizados para filtrar sua lista de amigos: você pode ver um grupo específico de amigos. + +/friends/index.bml.filter.about|staleness=1 +/friends/index.bml.filter.about=Filtre sua lista de amigos de acordo com subgrupos específicos. + +/friends/index.bml.groups=Além disso, subgrupos de amigos podem ser especificados. + +/friends/index.bml.security=Sua lista de amigos é também utilizada para posts com acesso restrito. Você pode descobrir mais coisas sobre segurança em lista de amigos em Amigos & Níveis de Segurança. + +/friends/index.bml.security.custom=Com posts "Customizados", você pode especificar quais grupos de amigos podem ver seu post. No entanto, nem todos os clientes suportam atualmente esse nível de segurança customizado. + +/friends/index.bml.security.header=Segurança + +/friends/index.bml.security.only|staleness=1 +/friends/index.bml.security.only=Com posts "Somente-Amigos", todos os outros usuários que pertençam à sua lista de amigos podem ver seu post. + +/friends/index.bml.title=Ferramentas da página de Amigos + +/friends/index.bml.tools=Ferramentas + +/friends/popwithfriends.bml.account_type=Desculpe, seu tipo de conta não permito que você utilize esta ferramenta. + +/friends/popwithfriends.bml.user=Usuário + +/index.bml.boldcreate=Crie seu próprio LiveJournal! + +/index.bml.frank.image.alt=Esse é Frank, o mascote do LiveJournal. + +/index.bml.frank.logo="Baaaaah", diz Frank. + +/index.bml.meta.desc=LiveJournal.com é um lugar onde você pode compartilhar suas idéias com o mundo. + +/index.bml.meta.keywords=diário, jornal, jornal online, diários, escrita, diário online, diário de rede + +/interests.bml.add.added.head=Adicionado! + +/interests.bml.add.added.text=Seu interesse foi adicionado à sua lista. + +/interests.bml.add.btn.text=Adicionar [[interest]] + +/interests.bml.add.confirm.head=Confirmar + +/interests.bml.add.confirm.text=Para adicionar [[interest]] como um interesse, clique no botão abaixo. + +/interests.bml.add.toomany.head=Desculpe... + +/interests.bml.add.toomany.text=Você já tem [[maxinterests]] interesses definidos. + +/interests.bml.addint=Se você também está interessado nisso e gostaria de ser adicionado para essa lista, clique aqui. + +/interests.bml.btn.switch=Trocar + +/interests.bml.communities.head=Comunidades Relevantes + +/interests.bml.communities.text=As seguintes comunidades também se interessam por "[[interest]]". + +/interests.bml.enmasse.body.other=Abaixo estão os interesses de [[user]]. Marque os interesses que você gostaria de adicionar para você mesmo, e desmarque os interesses que você gostaria de remover. Quando você terminar, clique em "Salvar Modificações". + +/interests.bml.enmasse.body.other_authas=Abaixo estão os interesses de [[user]]. Marque os interesses que você gostaria de adicionar para [[target]], e desmarque os interesses que você gostaria de remover. Quando você terminar, clique em "Salvar Modificações". + +/interests.bml.enmasse.btn=Mostrar lista + +/interests.bml.enmasse.header=Adicionar/Remover interesses + +/interests.bml.enmasse.intro=Modificar seus interesses baseado nos de: + +/interests.bml.error.add.mustlogin=Você tem que estar conectado para adicionar um interesse desse modo. + +/interests.bml.results.header=Resultados + +/interests.bml.users.text|staleness=1 +/interests.bml.users.text=Os seguintes usuários também se interessam por [[interest]]. + +/legal/index.bml.docs.header=Documentos + +/legal/index.bml.title=Informações Legais + +/legal/privacy.bml.title=Política de Privacidade + +/login.bml.loggedin.head=O login foi feito com sucesso! + +/login.bml.loggedin.text=O login foi feito com sucesso. + +/login.bml.login.btn.changeopts=Mudar Opções + +/login.bml.login.btn.login=Fazer login... + +/login.bml.login.expiration=Expira em: + +/login.bml.login.head=Fazer login + +/login.bml.login.never=Nunca + +/login.bml.logout.btn=Fazer Log Out + +/login.bml.title=Fazer Log In + +/login.bml.whylogin.head=Porque fazer login? + +/logout.bml.already.head=J + +/logout.bml.already.text=Você já se deslogou. + +/logout.bml.killall.btn=Expirar todas as minhas sessões + +/logout.bml.killall.head=Outras sessões + +/logout.bml.killall.text=Você tem outras sessões ativas. Você quer que todas as suas sessões expirem, e não somente esta? (Veja este FAQ para mais informações.) + +/logout.bml.loggedout.already=Já deslogado. + +/logout.bml.loggedout.head=Deslogado. + +/logout.bml.loggedout.success=Deslogado. + +/logout.bml.loggedout.text=Você foi deslogado. + +/logout.bml.logout.btn=Deslogar + +/lostinfo.bml.btn.proceed=Prossiga + +/lostinfo.bml.enter_email=Digite seu endereço de email: + +/lostinfo.bml.enter_email_optional=Endereço de email: (opcional) + +/lostinfo.bml.enter_username=Digite seu nome de usuário + +/lostinfo.bml.lostpassword.title|staleness=1 +/lostinfo.bml.lostpassword.title=Perdeu sua senha? + +/lostinfo.bml.lostusername.title|staleness=1 +/lostinfo.bml.lostusername.title=Perdeu seu nome de usuário? + +/lostinfo.bml.title=Informações Perdidas + +/lostinfo_do.bml.error.no_usernames_for_email=Não há usuários para esse endereço de email: [[address]] . + +/lostinfo_do.bml.password_mailed.text=Sucesso. Sua senha foi enviada. + +/lostinfo_do.bml.password_mailed.title=Senha enviada! + +/manage/index.bml.information.changepass=Mudar a Senha da Conta + +/manage/index.bml.information.changepass.about=Mudar a Senha da sua Conta + +/manage/index.bml.information.editinfo.about=Edite as informações da sua conta e várias outras opções + +/manage/index.bml.information.siteopts.about=Selecione seu layout preferido & língua + +/manage/phonepost.bml.error.inuse=PIN inválido, por favor tente outro + +/manage/phonepost.bml.error.pin=O teu PIN tem que ser composto por números + +/manage/phonepost.bml.pin.help=Recomenda-se de 4 a 6 dígitos + +/manage/phonepost.bml.saved=Gravado + +/manage/siteopts.bml.btn.lang=Mudar de Língua + +/manage/siteopts.bml.head.lang=Escolha a Sua Língua + +/modify.bml.title=Modificar Journal + +/modify_do.bml.availablestyles.head=Estilos Disponíveis + +/modify_do.bml.availablestyles.userstyles=Estilos de Usuários: + +/modify_do.bml.colortheme.area.head=Ãrea Utilizada + +/modify_do.bml.colortheme.color.head1=Cor + +/modify_do.bml.colortheme.color.head2=(#rrggbb ou nome) + +/modify_do.bml.colortheme.customcolors=Cores Personalizadas + +/modify_do.bml.done.btn.savechanges=Salvar as Alterações + +/modify_do.bml.done.head=Pronto? + +/modify_do.bml.done.text=Quando terminado, pressione o botão "Salvar Alterações" abaixo... + +/modify_do.bml.journaloptions.head=Opções do Journal + +/modify_do.bml.journalstatus.select.activated=Activado + +/modify_do.bml.journalstatus.select.deleted=Apagado + +/modify_do.bml.journalstatus.select.suspended=Suspenso + +/modify_do.bml.success.head=Sucesso + +/multisearch.bml.formaterror=Erro de Formatação + +/multisearch.bml.noaddress.text=Não escreveste um endereço de email + +/multisearch.bml.noaddress.title=Sem Endereço + +/multisearch.bml.nointerest.text=Não adicionaste um Interesse + +/multisearch.bml.nointerest.title=Sem Interesses + +/multisearch.bml.nomatch.text=Não há resultados para os critérios que tu especificaste. + +/multisearch.bml.region.head=Procurar por Região + +/paidaccounts/index.bml.costs.header=Bem, Quanto é que custa? + +/paidaccounts/index.bml.costs.rates=Os preços: + +/paidaccounts/index.bml.costs.rates.amount.header=Custo + +/paidaccounts/index.bml.costs.rates.time.header=Período + +/paidaccounts/index.bml.features.header=O que é que eu vou obter? + +/paidaccounts/index.bml.title=Acerca das Contas Pagas + +/paidaccounts/index.bml.whypay.header=Tenho que pagar para usar o LiveJournal? + +/site/contract.bml.promisetoyou.header=Nossa Promessa Para Você + +/site/contract.bml.title=Contrato Social + +/support/append_request.bml.bounce.toomany=Só pode enviar para cinco endereços de e-mail. Especificaste mais do que cinco. + +/support/append_request.bml.closed.title=Fechado + +/support/append_request.bml.invalid.blank=A tua mensagem está vazia. Por favor escreva qualquer coisa no caixa de texto. + +/support/append_request.bml.invalid.nocat=Não parace existir essa categoria. + +/support/append_request.bml.logged.title=Sucesso + +/support/encodings.bml.overview.header=Afinal de contas para que é isto tudo? + +/support/encodings.bml.still.header=Ainda encravado? + +/support/encodings.bml.still.text=Ãrea de Suporte. p?> + +/support/encodings.bml.title=Codificações + +/support/faqbrowse.bml.backfaq=Volte para as Perguntas Frequentes. + +/support/faqbrowse.bml.backsupport=Volte para a área de suporte. + +/support/faqbrowse.bml.error.nofaq=O FAQ especificado não existe. + +/support/faqbrowse.bml.lastupdated=Última atualização: + +/support/faqbrowse.bml.title_num=Questão do FAQ número [[num]] + +/talkmulti.bml.deleted.title=Comentários removidos + +/talkmulti.bml.error.comms_deleted=Um dos comentários foi removido desde que você o selecionou. Por questões de segurança, por favor volte e tente novamente. + +/talkmulti.bml.error.inconsistent_data=Os dados informados são inconsistentes + +/talkmulti.bml.screened.title=Comentários Escondidos + +/talkmulti.bml.title.delete=Apagar Vários Comentários + +/talkmulti.bml.title.screen=Esconder Vários Comentários + +/talkpost.bml.allowedhtml=HTML Permitida + +/talkpost.bml.error.cannotreplynopost=Você não pode responder a um texto não-existente + +/talkpost.bml.error.nocommentsjournal=Usuário desabilitou comentários em seu journal. + +/talkpost.bml.error.nocommentspost=Usuário desabiltou comentários nesse post. + +/talkpost.bml.error.noreplypost=Post a ser respondido não foi encontrado. (deletado?) + +/talkpost.bml.error.noreply_deleted=Não pode responder porque o comentário foi apagado + +/talkpost.bml.loganonip=Atenção!Esse usuário habilitou a opção que cadastra o endereço IP de comentários anônimos. + +/talkpost.bml.loginq=Fazer login? + +/talkpost.bml.logyourip=Atenção! Esse usuário habilitou a opção que cadastra seu endereço IP ao comentar. + +/talkpost.bml.nosubjecthtml=Não é permitido HTML no título + +/talkpost.bml.opt.anonymous=Anônimo + +/talkpost.bml.opt.defpic=(padrão) + +/talkpost.bml.opt.friendsonly=- esse usuário desabilitou comentários anônimos e de usuários não-amigos. Você pode comentar se [[username]] o tem listado como Amigo."; + +/talkpost.bml.opt.from=De: + +/talkpost.bml.opt.ljuser=Usuário do LiveJournal: + +/talkpost.bml.opt.loggedin=Usuário Conectado [[username]] + +/talkpost.bml.opt.message=Mensagem + +/talkpost.bml.opt.noanonpost=- esse usuário desabilitou comentários anônimos. + +/talkpost.bml.opt.noautoformat=Não auto-formatar: + +/talkpost.bml.opt.noimage=Sem Imagem + +/talkpost.bml.opt.preview=Prever + +/talkpost.bml.opt.subject=Assunto: + +/talkpost.bml.opt.submit=Comentar + +/talkpost.bml.opt.willscreen=(vai ficar como comentário oculto) + +/talkpost.bml.opt.willscreenfriend=(vai ficar como comentário oculto se não for amigo) + +/talkpost.bml.paraformat=Os parágrafos serão automaticamente formatados. + +/talkpost.bml.postresponse=Responda com um comentário + +/talkpost.bml.title=Comente + +/talkpost_do.bml.error.badpassword=Senha incorreta para o usuário em questão. Se você esqueceu sua senha, pode recuperá-la aqui + +/talkpost_do.bml.error.badusername=O nome de usuário fornecido por você não consta no LiveJournal. Você pode recuperar seu nome de usuário aqui caso você o tenha esquecido, ou pode escolher postar como anônimo. + +/talkpost_do.bml.error.banned=Você não tem permissão para comentar no journal deste usuário. + +/talkpost_do.bml.error.blankmessage=Sua mensagem estava em branco. Por favor digite algo no campo de mensagem. + +/talkpost_do.bml.error.confused_identity=Você inseriu um nome de usuário, mas escolheu postar anonimamente ou como o usuário conectado no momento. Volte e decida o que você realmente quer fazer. + +/talkpost_do.bml.error.deleted=Seu journal foi deletado. Você não pode deixar comentários. + +/talkpost_do.bml.error.friendsonly=Apenas Amigos de [[user]] podem comentar nesse journal. + +/talkpost_do.bml.error.lostcookie=Seu cookie de login desapareceu? + +/talkpost_do.bml.error.manybytes=Desculpe, mas seu comentário de [[current]] excedeu o limite máximo de [[limit]] bytes de comprimento. Por favor volte, encurte-o e tente postá-lo de novo. + +/talkpost_do.bml.error.manychars=Desculpe, mas seu comentário de [[current]] caracteres excedeu o limite máximo de [[limit]] caracteres de comprimeto. Por favor volte, encurte-o e tente postá-lo de novo. + +/talkpost_do.bml.error.mustlogin=Você tem que estar conectado ou usando um nome de usuário e senha para responder a esse texto protegido. + +/talkpost_do.bml.error.noanon=Você não pode comentar anonimamente no journal desse usuário. + +/talkpost_do.bml.error.noauth=Você não está autorizado a responder esse texto, ele é protegido. + +/talkpost_do.bml.error.nocomments=Usuário desabilitou comentários nesse texto. + +/talkpost_do.bml.error.noparent=Não pode responder a uma comentário que não existe. + +/talkpost_do.bml.error.notafriend=Desculpe, o usuário [[user]] não te lista como amigo, e ele(a) escolheu a opção "somente para amigos" para quem pode comentar em seu journal. + +/talkpost_do.bml.error.nousername=Você não digitou seu nome de usuário do LiveJournal. Você pode comentar como "Anônimo" se não possui uma conta no LiveJournal. + +/talkpost_do.bml.error.noverify|staleness=1 +/talkpost_do.bml.error.noverify=Desculpe, você não está autorizado(a) a deixar comentários nos journals de outras pessoas até verificarmos seu endereço de email. Se você perdeu o email confirmando a verificação dele, você pode recebê-lo novamente na página de informações perdidas. + +/talkpost_do.bml.error.postshared=Você não pode postar com uma conta compartilhada ou comunitária. Contas partilhadas representam grupos de pessoas, e não pessoas individuais. + +/talkpost_do.bml.error.suspended=Seu journal foi suspenso. Você não pode publicar comentários. + +/talkpost_do.bml.error.testacct=Contas de teste só podem ser usadas em journals de teste. + +/talkpost_do.bml.preview|staleness=1 +/talkpost_do.bml.preview=Abaixo está a visualização do seu texto. Clique em "retornar" no seu navegador para modificá-lo ou, se estiver satisfeito, prossiga para postá-lo. + +/talkpost_do.bml.preview.subject=Assunto: + +/talkpost_do.bml.preview.submit=Enviar + +/talkpost_do.bml.preview.title=Ver + +/talkpost_do.bml.success.loggedin=Você está conectado. + +/talkpost_do.bml.success.message=Seu comentário foi adicionado com sucesso! Você pode vê-lo aqui + +/talkpost_do.bml.success.title=Sucesso + +/talkpost_do.bml.title|staleness=2 +/talkpost_do.bml.title=Deixar comentário + +/talkread.bml.anonuser=(Anônimo) + +/talkread.bml.deletedpost=(Texto Deletado) + +/talkread.bml.deleteduser=(Usuário Deletado: [[username]]) + +/talkread.bml.fromip=(de [[ip]]) + +/talkread.bml.noreplies=Nenhuma resposta + +/talkread.bml.nosubject=(sem assunto) + +/talkread.bml.replysuspended=(Resposta de um usuário suspenso) + +/talkread.bml.subjectdeleted=[deletado] + +/talkread.bml.title=Ler Comentários + +/tools/emailmanage.bml.desc.title=Descrição: + +/tools/emailmanage.bml.log.deleted=Removido: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Modificações Salvas + +/tools/emailmanage.bml.notvalidated.title=E-mail não validado + +/tools/memadd.bml.body.added.header=Sucesso + +/tools/memadd.bml.description=Descrição: + +/tools/memadd.bml.description.text<< +Use uma descrição para este texto que você possa utilizar para lembrar-se mais tarde. +Para remover este texto da sua lista de textos memoráveis, entre com uma descrição em branco. +. + +/tools/memadd.bml.error.deleted.body=O texto descrito anteriormente como "[[desc]]" foi removido da sua lista de textos memoráveis. + +/tools/memadd.bml.error.maxsize=Essa palavra-chave excede o tamanho máximo permitido: "[[keyword]]" + +/tools/memadd.bml.keywords=Palavras-chave: + +/tools/memadd.bml.keywords.example=Exemplo: Engraçado, Estranho, Romântico + +/tools/memadd.bml.keywords.select=Ou você pode selecionar palavars-chave já existentes: + +/tools/memadd.bml.keywords.text|staleness=2 +/tools/memadd.bml.keywords.text<< +Por que esse texto é memorável? +Digite até cinco palavras-chave ou categorias para que você possa encontrá-lo mais facilmente no futuro. +. + +/tools/memadd.bml.multiple_selections=Pressione 'Control' e segure para selecionar mais de uma palavra-chave. + +/tools/memadd.bml.security.friendsonly=Somente Amigos + +/tools/memadd.bml.security.private=Particular + +/tools/memadd.bml.security.public=Público + +/tools/memadd.bml.title=Adicionar às minhas Memórias + +/tools/memadd.bml.title.added=Adicionado + +/tools/memadd.bml.title.deleted=Deletado + +/tools/memadd.bml.title.edit_memory=Editar o texto memorável + +/tools/memadd.bml.whocansee<< +Quem pode ver que esse texto está em suas Memórias? +Qualquer um, só os seus Amigos ou só você? +. + +/tools/memories.bml.back=Voltar + +/tools/memories.bml.body.keyword|staleness=2 +/tools/memories.bml.body.keyword<< +(=H1 [[keyword]] H1=) + (=P Essa é a lista de"[[keyword]]" textos do journal que o usuário [[user]] colocou em suas Memórias. P=) + +. + +/tools/memories.bml.body.list_categories|staleness=2 +/tools/memories.bml.body.list_categories<< +(=H1 Textos Memoráveis H1=) + (=P Essa é a lista de categorias em que o usuário [[user]] separou os seus textos. P=) + +. + +/tools/memories.bml.body.memorable=Essa é uma lista de textos não-categorizados que o usuário [[user]] considera memoráveis. + +/tools/memories.bml.edit=editar + +/tools/memories.bml.error.noentries.title=Nenhuma Memória encontrada. + +/tools/memories.bml.filter.all=Todas as Memórias + +/tools/memories.bml.filter.other=Somente outros textos + +/tools/memories.bml.filter.own=Somente textos de '[[user]]' + +/tools/memories.bml.form.switch=Trocar + +/tools/memories.bml.sort.description=Descrição + +/tools/memories.bml.title.keyword=Textos [[keyword]] Memoráveis + +/tools/memories.bml.title.memorable=Textos Memoráveis + +/tools/memories.bml.uncategorized=Sem categoria + +/update.bml.date=Data: + +/update.bml.error.login=Problemas ao fazer login + +/update.bml.localtime=Horário local: + +/update.bml.loggingin=Fazendo login com o servidor + +/update.bml.opt.defpic=(padrão) + +/update.bml.other=Outros: + +/update.bml.security.friends=Amigos + +/update.bml.security.head=Nível de Segurança: + +/update.bml.security.private=Privado + +/update.bml.security.public=Público + +/update.bml.servermsg=O servidor tem uma mensagem para si: + +/update.bml.title.readonly=Modo Ler-Apenas + +/update.bml.update.head=Atualizar o seu Journal... + +/update.bml.update.success|staleness=1 +/update.bml.update.success=Atualização completa. Você pode ver o seu journal atualizado aqui + +/update.bml.updating=Atualizando o journal... + +/update.bml.username=Nome de Utilizador: + +/userinfo.bml.about.comm|staleness=1 +/userinfo.bml.about.comm=Sobre + +/userinfo.bml.about.user|staleness=1 +/userinfo.bml.about.user=Biografia + +/userinfo.bml.body.leave=Você pode sair da comunidade quando quiser. + +/userinfo.bml.comminfo.name=Informações da Comunidade + +/userinfo.bml.date.never=Nunca. + +/userinfo.bml.friendof.comm|staleness=2 +/userinfo.bml.friendof.comm=Visto por + +/userinfo.bml.friendof.hidden=(escondido) + +/userinfo.bml.friendof.user|staleness=2 +/userinfo.bml.friendof.user=Amigo(a) de + +/userinfo.bml.friends.comm=Membros + +/userinfo.bml.friends.user|staleness=2 +/userinfo.bml.friends.user=Amigos + +/userinfo.bml.label.addbuddy=Adicionar buddy + +/userinfo.bml.label.adduser=Adicionar usuário + +/userinfo.bml.label.aolim=Nome de Tela do AIM: + +/userinfo.bml.label.birthdate=Data de nascimento: + +/userinfo.bml.label.clientsused=Clientes utilizados: + +/userinfo.bml.label.comments=Comentários: + +/userinfo.bml.label.composted=Feitos: [[num]] - + +/userinfo.bml.label.comreceived=Recebidos: [[num]] + +/userinfo.bml.label.datecreated=Data de criação: + +/userinfo.bml.label.dateupdated=Data de atualização: + +/userinfo.bml.label.email|staleness=1 +/userinfo.bml.label.email=E-mail: + +/userinfo.bml.label.icquin=UIN do ICQ: + +/userinfo.bml.label.interests=Interesses + +/userinfo.bml.label.journalentrs=Textos postados: + +/userinfo.bml.label.location=Localização: + +/userinfo.bml.label.memberof=Membro de: + +/userinfo.bml.label.memories=Memórias: + +/userinfo.bml.label.moredetails=(mais detalhes...) + +/userinfo.bml.label.name=Nome: + +/userinfo.bml.label.nofriends=nada listado + +/userinfo.bml.label.post=Escrever em "[[journal]]" + +/userinfo.bml.label.sendmessage=Enviar mensagem + +/userinfo.bml.label.shared|staleness=2 +/userinfo.bml.label.shared=Acesso a Journals compartilhados: + +/userinfo.bml.label.user=Usuário: + +/userinfo.bml.label.viewfriends=Ver Amigos + +/userinfo.bml.label.viewmembers=Ver Membros + +/userinfo.bml.label.yahooid=ID do Yahoo! + +/userinfo.bml.monitor.comm=Monitorar Comunidade + +/userinfo.bml.monitor.user=Adicionar esse usuário à sua lista de amigos + +/userinfo.bml.nonexist.name=Usuário desconhecido + +/userinfo.bml.title=Perfil do Usuário + +/userinfo.bml.title.communityinfo=Informações da Comunidade + +/userinfo.bml.userinfo.name=Informação sobre o usuário + +btn.search=Pesquisa + +crumb.about=Acerca do LiveJournal + +crumb.abusereport=Informar Abuso + +crumb.acctfeatures=Características por Tipo de Conta + +crumb.addfriend=Adicionar Amigo + +crumb.banners=Banners Publucitários + +crumb.birthdays=Aniversários + +crumb.changepass=Mudar Password + +crumb.privacy=Política de Privacidade + +crumb.register=Validar Email + +crumb.search=Procurar + +crumb.searchinterests=Por Interesse + +crumb.searchregion=Por Região + +crumb.setpgpkey=Chave Pública + +crumb.singles=Solteiros do LiveJournal + +crumb.singlesopts=Modificar Disponibilidades. + +crumb.singlessearch=Procurar por Solteiros + +crumb.sitemap=Mapa do Site + +crumb.siteopts=Verificar Preferências + +crumb.stats=Estatísticas + +crumb.store=Loja do LiveJournal + +crumb.styles=Estilos + +crumb.yourstyles=Os teus Estilos + +date.day.friday.long=Sexta + +date.day.friday.short=Sex + +date.day.monday.long=Segunda + +date.day.monday.short=Seg + +date.day.saturday.long=Sábado + +date.day.saturday.short=Sáb + +date.day.sunday.long=Domingo + +date.day.sunday.short=Dom + +date.day.thursday.long=Quinta + +date.day.thursday.short=Qui + +date.day.tuesday.long=Terça + +date.day.tuesday.short=Ter + +date.day.wednesday.long=Quarta + +date.day.wednesday.short=Qua + +date.month.april.long=Abril + +date.month.april.short=Abr + +date.month.august.long=Agosto + +date.month.august.short=Ago + +date.month.december.long=Dezembro + +date.month.december.short=Dez + +date.month.february.long=Fevereiro + +date.month.february.short=Fev + +date.month.january.long=Janeiro + +date.month.july.long=Julho + +date.month.june.long=Junho + +date.month.march.long=Março + +date.month.may.long=Maio + +date.month.may.short=Mai + +date.month.november.long=Novembro + +date.month.october.long=Outubro + +date.month.october.short=Out + +date.month.september.long=Setembro + +date.month.september.short=Set + +dystopia.btn.login=ENTRAR + +dystopia.hello_anonymous=Bem vindo ao LiveJournal! + +dystopia.hello_loggedin=Olá, [[username]]! + +dystopia.nav.createjournal=Crie um novo Journal + +dystopia.nav.developer=Programadores + +dystopia.nav.download=Faça o download + +dystopia.nav.editentries=Editar textos + +dystopia.nav.editfriends=Seus Amigos + +dystopia.nav.editpassword=Sua Senha + +dystopia.nav.editpics=Suas Imagens + +dystopia.nav.editstyle=Alterar Estilo + +dystopia.nav.faq=Dúvidas & Dicas + +dystopia.nav.findcomm=Por Comunidades + +dystopia.nav.finddir=Pesquisar Diretório + +dystopia.nav.findint=Por Interesse + +dystopia.nav.findrandom=Ao Acaso + +dystopia.nav.findregion=Por Região + +dystopia.nav.home=Página Inicial + +dystopia.nav.journalcalendar=Calendário + +dystopia.nav.journalfriends=Amigos + +dystopia.nav.journalinfo=Perfil do Usuário + +dystopia.nav.journalrecent=Mais Recentes + +dystopia.nav.legalcoppa="COPPA" + +dystopia.nav.legalprivacy=Privacidade + +dystopia.nav.legaltos=Termos de Serviço + +dystopia.nav.login=Acesso + +dystopia.nav.logout=Sair + +dystopia.nav.lostinfo=Perdeu sua senha? + +dystopia.nav.memories=Memórias + +dystopia.nav.modifyjournal=Modificar Journal + +dystopia.nav.news=Novidades + +dystopia.nav.paidaccts=Contas Pagas + +dystopia.nav.paymentarea=Ãrea de Pagamento + +dystopia.nav.personalinfo=Perfil Pessoal + +dystopia.nav.sitemap=Mapa do Site + +dystopia.nav.support=Tem uma dúvida? + +dystopia.nav.updatejournal=Atualizar + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=130 + +dystopia.navhead.findusers=Buscar Usuários + +dystopia.navhead.help=Ajuda & Suporte + +dystopia.navhead.journal=Seu Journal + +dystopia.navhead.legal=Questões Legais + +dystopia.navhead.settings=Preferências + +dystopia.navhead.welcome=Bem Vindo! + +dystopia.search.aolim=Nome de Tela do AIM + +dystopia.search.icq=Número do ICQ + +dystopia.search.int=Interesse + +dystopia.search.region=Região + +dystopia.search.yahoo=ID do Yahoo! + +dystopia.searchlj=Pesquisar LiveJournal: + +email.newacct.subject=Bem vindo ao LiveJournal + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Erro + +error.badpassword=Senha Incorreta + +error.deleted.name=Apagado + +error.deleted.title=Conta Apagada + +error.nodb=Database não disponível temporariamente. + +error.nodbmaintenance=Esta parte da database está temporariamente fora do ar para manutenção. Tente novemente em alguns minutos. + +error.noentry=Não existe tal texto no journal. + +error.nojournal=Journal Desconhecido + +error.purged.name=Apagado + +error.suspended.name=Suspenso + +error.suspended.title=Conta Suspensa + +error.unknownmode=Modo desconhecido. + +error.usernameinvalid=Nome do usuário contem caracteres inválidos. + +error.usernamelong=Nome de Utilizador demasiado longo, No máximo use 15 caracteres + +error.username_notfound=Nome de usuário não encontrado. + +Help=Ajuda + +label.screening.all=Todos os comentários + +label.screening.anonymous=Apenas Anónimos + +label.security.friends=Amigos + +label.security.head=Nível de Segurança: + +label.security.private=Privado + +label.security.public=Público + +label.switch.button=Trocar + +label.switch.header=Trocar Journal + +label.switch.workwith=Trabalhar com o Journal: + +langname.be=Bielo-russo + +langname.da=Dinamarquês + +langname.de=Alemão + +langname.en=Inglês + +langname.en_GB=Inglês Britânico + +langname.en_LJ=Inglês + +langname.es=Espanhol + +langname.et=Estónio + +langname.fi=Finlandês + +langname.fr=Francês + +langname.ga=Irlandês + +langname.gd=Galês + +langname.he=Hebraico + +langname.hu=Húngaro + +langname.is=Islandês + +langname.it=Italiano + +langname.ja=Japonês + +langname.lv=Letónio + +langname.ms=Malasiano + +langname.nb=Norueguês BokmÃ¥l + +langname.nl=Holandês + +langname.nn=Norueguês Nynorsk + +langname.pl=Polonês + +langname.pt=Português + +langname.ru=Russo + +langname.sv=Sueco + +langname.tr=Turco + +langname.uk=Ucraniano + +langname.zh=Chinês Simplificado + +ljcom.account.feature.limit=Limitado + +ljcom.account.feature.search=Procurar no Directório + +ljcom.account.free=Conta Grátis + +ljcom.account.paid=Conta Paga + +ljcom.account.paid12=Pago para 12 Meses ($25 USD) + +ljcom.account.paid2=Pago para 2 Meses ($5 USD) + +ljcom.account.paid6=Pago para 6 Meses ($15 USD) + +ljcom.accounttype=Tipo de Conta + +ljcom.badpass.email=Sua senha não pode ser baseada no seu e-mail. + +ljcom.badpass.realname=Sua senha não pode ser baseada no seu nome. + +ljcom.badpass.username=A sua password não pode ser baseada no teu "username" + +ljcom.meetup.moreinfo=(mais informação) + +ljcom.userinfo.accounttype=Tipo de conta + +ljcom.userinfo.paiduser=Utilizador com Conta Paga + +ljcom.userinfo.types.free=Conta Grátis + +ljcom.userinfo.types.paid=Conta Paga + +ljcom.userinfo.types.permanent=Conta Permanente + +ljlib.pageofpages=Pagina [[page]] de [[total]] + +lostinfo.head=Esqueceu-se de alguma coisa? + +lostinfo.text=Se esqueceste o teu username ou a tua password, recupere-os aqui. + +lynx.nav.friends=Amigos + +lynx.nav.help=Suporte Técnico + +lynx.nav.recent=Entradas recentes + +Password=Senha + +password.max30=As senhas não podem conter mais de 30 caracteres. + +portal.bdays.portalname=Aniversários + +portal.bdays.portaltitle=Aniversários + +portal.goat.name=Mascote do Site + +portal.ministats.active=Activos: + +portal.newtolj.name=Links do Site + +portal.popfaq.portalname=Os 10 FAQs Mais Vistos + +portal.popfaq.portaltitle=Os 10 FAQs Mais Vistos + +portal.randuser.count.name=Número de Utilizadores a sorte a mostrar + +portal.randuser.error.tableempty=Não detectou qualquer user a sorte. Por favor, Contacte a Administração. + +portal.randuser.hidename.name=Esconder Nome + +portal.randuser.hidepic.name=Esconder a Imagem do Utilizador + +portal.recent.error.noentries=Lamento. Não há textos. + +portal.stats.portalname=Estatísticas do Site + +portal.stats.portaltitle=Estatísticas + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Desculpe + +talk.anonwrote=Alguém escreveu, + +talk.anonwrote_comm=Alguém escreveu em [[commlink]], + +talk.commentpost=Deixe um novo comentário + +talk.commentsread=Ler comentários + +talk.curname_Mood=Humor atual: + +talk.curname_Music=Música atual: + +talk.error.bogusargs=Argumentos bogusM + +talk.error.deleted.title=Apagado + +talk.error.mustlogin=Você precisa estar conectado para visualizar este texto protegido. + +talk.error.nocomment=Esse comentário não existe. + +talk.error.noentry=Essa entrada não existe + +talk.error.nojournal=Erro: impossível determinar journal a partir destes argumentos. + +talk.error.nosuchjournal=Esse journal não existe + +talk.error.notauthorised=Você não está autorizado a ver esse texto protegido. + +talk.error.suspended=Esse journal/usuário está suspenso. + +talk.error.suspended.title=Suspenso + +talk.parentlink=Principal + +talk.readsimilar=Ler entradas similares: + +talk.replytothis=Responder + +talk.somebodywrote=[[realname]] ([[userlink]]) escreveu, + +talk.somebodywrote_comm=[[realname]] ([[userlink]]) escreveu em [[commlink]], + +talk.spellcheck=Verificar ortografia antes de salvar + +talk.threadlink=Linha de discussão + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_portugues + +Username=Nome do usuário + +xcolibur.greeting.anon=Bem Vindo ao LiveJournal! + +xcolibur.greeting.logged_in=Bem vindo, [[name]]! [[logout]] + +xcolibur.login=Fazer Login? + +xcolibur.nav.about=Sobre + +xcolibur.nav.about.general=Informações Gerais + +xcolibur.nav.about.paidaccounts=Contas Pagas + +xcolibur.nav.about.sitenews=Novidades do Site + +xcolibur.nav.about.stats=Estatísticas + +xcolibur.nav.footer.sitemap=Mapa do Site + +xcolibur.nav.help=Ajuda + +xcolibur.nav.help.ask=Faça uma Pergunta + +xcolibur.nav.help.lostpassword=Perdeu Password? + +xcolibur.nav.journal.archive=Arquivo + +xcolibur.nav.journal.friends=Amigos + +xcolibur.nav.journal.info=Informações + +xcolibur.nav.journal.memories=Memórias + +xcolibur.nav.journal.recent=Recente + +xcolibur.nav.manage.community=Comunidades + +xcolibur.nav.manage.friends=Amigos + +xcolibur.nav.manage.info=Informações + +xcolibur.nav.manage.password=Senha + +xcolibur.nav.manage.pics=Fotos dos Usuários + +xcolibur.nav.manage.styles=Estilos + +xcolibur.nav.search=Procura + +xcolibur.nav.search.directory=Região + +xcolibur.nav.search.directory.search=Avançado + +xcolibur.nav.search.interests=Interesses + +xcolibur.nav.search.random=à sorte + +xcolibur.nav.title=Navegar: + +xcolibur.nav.welcome=Bem Vindo + +xcolibur.nav.welcome.create=Crie uma Conta + +xcolibur.search=Procura: + +xcolibur.search.aolim=Nome de Tela do AIM + +xcolibur.search.category=Categoria: + +xcolibur.search.icq=UIN do ICQ + +xcolibur.search.int=Interesse + +xcolibur.search.region=Região + +xcolibur.search.yahoo=ID do Yahoo! + diff --git a/ljcom/bin/upgrading/pt_BR.dat b/ljcom/bin/upgrading/pt_BR.dat new file mode 100644 index 0000000..1dd1b5c --- /dev/null +++ b/ljcom/bin/upgrading/pt_BR.dat @@ -0,0 +1,36 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.journalstatus.about=Se você quiser deletar ou recuperar seu journal deletado, o lugar para fazê-lo é aqui. Assim que você deletar seu journal, você terá 30 dias para recuperá-lo, se por acaso mudar de idéia. Após 30 dias, o journal será permanentemente deletado e não haverá maneira de recuperá-lo. + +/allpics.bml.edit2=Você pode estar interessado em editar as palavras-chave da sua imagem ou fazer upload de uma nova imagem. + +/allpics.bml.error.noparam=Você precisa especificar um usuário como parâmetro. + +/allpics.bml.nopics.text.other=Este usuário ainda não fez upload de nenhuma imagem. + +/allpics.bml.nopics.text2=Você não tem nenhuma imagem. Para fazer upload de uma, clique aqui. + +/approve.bml.comm.text<< +Você foi adicionado à comunidade [[comm]]. +Clique aqui para adicionar a comunidade à sua lista de amigos. +. + +/approve.bml.error.actionperformed=Essa ação já foi executada + +/approve.bml.error.internerr.invalidaction=Erro Interno: ação inválida + +/approve.bml.error.invalidargument=Argumento inválido + +/approve.bml.error.unknownactiontype=Tipo de ação desconhecido + +/approve.bml.title=Ação Aprovada + +/birthdays.bml.description=Abaixo estão as datas de aniversário de todas as pessoas na sua lista de amigos. + +/changepassword.bml.btn.proceed=Prosseguir + +/changepassword.bml.changepassword.instructions=Preencha o formulário abaixo para mudar sua senha. Para obter ajuda ao escolher uma boa senha e manter sua conta segura, veja este FAQ. + +/changepassword.bml.email.subject=Troca de Senha + +/changepassword.bml.error.badcheck=Nova senha inválida: [[error]] + diff --git a/ljcom/bin/upgrading/ru.dat b/ljcom/bin/upgrading/ru.dat new file mode 100644 index 0000000..f567395 --- /dev/null +++ b/ljcom/bin/upgrading/ru.dat @@ -0,0 +1,5240 @@ +;; -*- coding: utf-8 -*- +/accountstatus.bml.btn.status|notes=Submit button for form +/accountstatus.bml.btn.status=Изменить ÑÑ‚Ð°Ñ‚ÑƒÑ + +/accountstatus.bml.error.db=Ошибка базы данных во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ вашего запроÑа + +/accountstatus.bml.error.invalid=ÐедейÑтвительный тип ÑтатуÑа + +/accountstatus.bml.error.nochange.expunged=Этот аккаунт удален из ÑиÑтемы + +/accountstatus.bml.error.nochange.suspend|notes=You can't change a journal to be unsuspended. This message is for users who attempt to do so. +/accountstatus.bml.error.nochange.suspend=Ð’Ñ‹ не можете изменить ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐµÐ³Ð¾ журнала - он оÑталÑÑ Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ð¼ + +/accountstatus.bml.header.success=ПолучилоÑÑŒ + +/accountstatus.bml.journalstatus.about=ЕÑли вы хотите удалить ваш журнал, либо воÑÑтановить его, то вы на правильной Ñтранице. ПоÑле того, как вы удалите ваш журнал, у Ð²Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ 30 дней на то, чтобы передумать и воÑÑтановить его. По иÑтечении Ñтого Ñрока, журнал будет окончательно и беÑповоротно удалён, так что воÑÑтановить его уже не удаÑÑ‚ÑÑ. + +/accountstatus.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð°: + +/accountstatus.bml.journalstatus.select.activated=Ðктивен + +/accountstatus.bml.journalstatus.select.deleted=Удалён + +/accountstatus.bml.journalstatus.select.head=СтатуÑ: + +/accountstatus.bml.journalstatus.select.suspended=Заморожен + +/accountstatus.bml.message.nochange=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐµÐ³Ð¾ журнала оÑталÑÑ [[statusvis]]. + +/accountstatus.bml.message.success=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐµÐ³Ð¾ журнала уÑпешно изменен на [[statusvis]]. + +/accountstatus.bml.title=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° + +/allpics.bml.current=ИмеющиеÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ + +/allpics.bml.default=Картинка по умолчанию + +/allpics.bml.edit2=Ð’Ñ‹ можете редактировать ключевые Ñлова к картинкам или закачать новую картинку. + +/allpics.bml.error.noparam=Вам необходимо указать Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/allpics.bml.keywords=Ключевые Ñлова: + +/allpics.bml.nopics.text.other=Этот пользователь не загрузил ни одной картинки. + +/allpics.bml.nopics.text2=Ð’Ñ‹ не закачали ни одной картинки. Это можно Ñделать здеÑÑŒ. + +/allpics.bml.nopics.title=Ðет картинок + +/allpics.bml.pics=Это картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. + +/allpics.bml.title=Картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/approve.bml.comm.success=ПолучилоÑÑŒ + +/approve.bml.comm.text<< +Ð’Ñ‹ добавлены к [[comm]]. +Ðажмите здеÑÑŒ, чтобы добавить ÑообщеÑтво к ÑпиÑку ваших друзей. +. + +/approve.bml.commjoin.text=Ð’Ñ‹ одобрили Ð·Ð°Ð¿Ñ€Ð¾Ñ [[user]] о вÑтуплении в [[comm]]. Ðажмите здеÑÑŒ, чтобы увидеть ÑпиÑок членов данного ÑообщеÑтва и определить другие привилегии Ñтого пользователÑ. + +/approve.bml.error.actionperformed=Это дейÑтвие уже выполнено + +/approve.bml.error.approving<< +Во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑÑа Ð¾Ð´Ð¾Ð±Ñ€ÐµÐ½Ð¸Ñ Ñтого запроÑа о вÑтуплении в ÑообщeÑтво произошла ошибка. + +. + +/approve.bml.error.internerr.invalidaction=Ошибка: неизвеÑтное дейÑтвие + +/approve.bml.error.invalidargument=Ðеправильный тип дейÑÑ‚Ð²Ð¸Ñ + +/approve.bml.error.unknownactiontype=ÐеизвеÑтный тип дейÑÑ‚Ð²Ð¸Ñ + +/approve.bml.shared.success=ПолучилоÑÑŒ + +/approve.bml.shared.text<< +Теперь вы можете пиÑать в [[shared]]. +Ðажмите здеÑÑŒ, чтобы добавить журнал к ÑпиÑку ваших друзей. +. + +/approve.bml.title=Подтверждение дейÑÑ‚Ð²Ð¸Ñ + +/birthdays.bml.description=Внизу находÑÑ‚ÑÑ Ð”Ð½Ð¸ Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚ÐµÑ…, кого вы выбрали в качеÑтве друзей + +/birthdays.bml.title=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +/changepassword.bml.btn.proceed=Продолжить + +/changepassword.bml.changepassword.header=Сменить пароль + +/changepassword.bml.changepassword.instructions=Чтобы изменить ваш пароль, заполните форму внизу. Эта Ñправка поможет вам в выборе хорошего Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¸ Ñохранении вашего аккаунта в безопаÑноÑти. + +/changepassword.bml.email.body<< +Ваш пароль на Ñайте [[sitename]] был изменен. + +Чтобы воÑÑтановить его в будущем, зайдите на Ñтраницу: + +[[siteroot]]/lostinfo.bml + +C пламенным приветом, +Команда [[sitename]] + +[[siteroot]] +. + +/changepassword.bml.email.subject=Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ + +/changepassword.bml.error.badcheck=Ðеверный новый пароль: [[error]] + +/changepassword.bml.error.badnewpassword=Ваше новое подтверждение Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ ÑоответÑтвует вашему новому паролю. Ð’Ñ‹ могли допуÑтить ошибку при наборе. ПожалуйÑта, наберите и подтверждите Ñвой новый пароль еще раз. + +/changepassword.bml.error.badoldpassword=Ваш Ñтарый пароль неверен. + +/changepassword.bml.error.blankpassword=Ðовый пароль не может быть пуÑтым. + +/changepassword.bml.error.changetestaccount=ÐÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ пароль теÑтового журнала. + +/changepassword.bml.error.characterlimit=Пароль не может быть длиннее 30 Ñимволов. + +/changepassword.bml.error.invaliduser=Ðепрравильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. Пользователь Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем не ÑущеÑтвует. Ð’Ñ‹ уверены, что набрали Ð¸Ð¼Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾? + +/changepassword.bml.error.mustenterusername=Ðеобходимо ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/changepassword.bml.error.nonascii=Символы Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ принадлежать таблице ASCII. Выберите пароль, не Ñодержащий не-ASCII-Ñимволов. + +/changepassword.bml.error.notvalidated=Ð’Ñ‹ не можете изменить пароль, пока ваш текущий Ð°Ð´Ñ€ÐµÑ e-mail не подтверждён. ожалуйÑта, поÑмотите инÑтрукции о том, как Ñто Ñделать здеÑÑŒ. + +/changepassword.bml.newpassword=Ðовый пароль: + +/changepassword.bml.newpasswordagain=Ðовый пароль (ещё раз): + +/changepassword.bml.oldpassword=Старый пароль: + +/changepassword.bml.proceed.instructions=Ðажмите кнопку "Продолжить", чтобы изменить пароль. Ð’Ñ‹ также получите e-mail Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸ÐµÐ¼ о Ñмене паролÑ. + +/changepassword.bml.relogin=К тому же вы вышли из вÑех ÑущеÑтвовавших ÑеÑÑий. Вам придетÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ опÑÑ‚ÑŒ до того, как вы Ñможете продолжить. + +/changepassword.bml.success.text=Ваш пароль был изменен. Вам был отправлен e-mail Ñ Ð¸Ð·Ð²ÐµÑ‰ÐµÐ½Ð¸ÐµÐ¼. + +/changepassword.bml.title=Сменить пароль + +/community/index.bml.main<< + + + + +ÑообщеÑтво Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ‡ÐºÐ¾Ð² или ÑообщеÑтво поддержки ЖЖ, где вы узнаете ответы на многие вопроÑÑ‹. + p?> + + +
            +Чтобы узнавать о новых ÑобытиÑÑ… и о том, какие проблемы ÑтоÑÑ‚ перед вÑем ÑообщеÑтвом Живого Журнала, добавьте в ленту друзей .
            +Чтобы Ð²Ð¾Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÑŒ информацию о плановых отключениÑÑ… или незапланированных перебоÑÑ… в работе ÑервиÑа, добавьте в ленту друзей ÑообщеÑтво . +

            +ЕÑли вы не понимаете по-английÑки, то узнавать новоÑти и полезную информацию вы можете в ÑообщеÑтве . +p?> + + +AIM, ICQ, Yahoo!, MSN или Jabber. ЕÑли вы тоже, укажите их в личной информации. ЕÑли у Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¹ аккаунт, вы можете наÑтроить получение Ñообщений на Ñвой Ñотовый телефон или пейджер. +p?> + + +платный аккаунт. Ðо, конечно, еÑÑ‚ÑŒ и множеÑтво других ÑпоÑобов помочь Ñайту. +

            +Живой Журнал – Ñто проект Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ иÑходным кодом, и еÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ опыт Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñерверных приложений, вы можете обратитьÑÑ Ð² СообщеÑтво разработки Живого Журнала, . ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ мыÑли, как улучшить Живой Журнал, поделитеÑÑŒ ими в Книге предложений, . ЕÑли вы хотите помочь хоть чем-нибудь, отправлÑйтеÑÑŒ в Деловое ÑообщеÑтво Живого Журнала, . ЕÑли вам нравитÑÑ Ñ€ÐµÑˆÐ°Ñ‚ÑŒ проблемы других людей, предлагаем вам помочь кому-нибудь в центре поддержки. ЕÑли вы разбираетеÑÑŒ в дизайне, поÑетите ХудожеÑтвенное ÑообщеÑтво Живого Журнала, . +p?> + + +Ð°Ð½Ð¸Ð¼Ñ Ð´Ð¾ Японии, от автомобилей и до ÑÑ…Ñ‚. СущеÑтвуют также ÑообщеÑтва по Ñтранам и регионам. Возможно, даже еÑÑ‚ÑŒ ÑообщеÑтво Ð´Ð»Ñ Ñ‚ÐµÑ…, кто живёт в вашем городе! +p?> + + +данной Ñправке вы можете узнать, как Ñоздать ÑобÑтвенное ÑообщеÑтво. Кроме того, в Ñправочнике еÑÑ‚ÑŒ две категории, в которых ÑодержатÑÑ Ð¾Ñ‚Ð²ÐµÑ‚Ñ‹ практичеÑки на любые вопроÑÑ‹ про ÑообщеÑтва: ÐžÐ±Ñ‰Ð°Ñ Ñправка про ÑообщеÑтва и Управление ÑообщеÑтвами. ЕÑли вы вÑÑ‘ же не нашли ответа на Ñвой вопроÑ, вы можете задать его на Ñтранице помощи. +p?> + + + + +
              +
            • ПоиÑк ÑообщеÑтв
            • +
            • ПоÑмотреть журнал рекламы ÑообщеÑтв()
            • +
            • ПоÑмотреть журнал поиÑка ÑообщеÑтв()
            • +
            + + +Ðапишите Jesse Proulx, () директору по работе Ñ ÑообщеÑтвом. +p?> + +. + +/community/index.bml.title=Центр СообщеÑтва + +/community/join.bml.button.join=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +/community/join.bml.error.already.member=Ð’Ñ‹ уже ÑвлÑетеÑÑŒ членом Ñтого ÑообщеÑтва. + +/community/join.bml.error.closed=Это ÑообщеÑтво больше не принимает новых членов. ЕÑли вы хотите в него вÑтупить, пожалуйÑта, напишите одному из Ñмотрителей: + +/community/join.bml.error.statusvis.body=Ðккаунт, в который вы хотите зайти, не активирован. + +/community/join.bml.error.statusvis.title=Ðевозможно вÑтупить в ÑообщеÑтво + +/community/join.bml.label.addtofriends=Добавить "[[maintainer]]" в ленту друзей.
            + +/community/join.bml.label.allowposting=Это ÑообщеÑтво открыто и принимает ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ вÑех Ñвоих учаÑтников, поÑтому теперь и вы можете отправлÑÑ‚ÑŒ запиÑи в журнал ÑообщеÑтва. ЕÑли у Ð²Ð°Ñ Ð·Ð°Ð¿ÑƒÑ‰ÐµÐ½Ð° программа-клиент, вам доÑтаточно выйти из дневника и Ñнова войти в него, чтобы Ð¸Ð¼Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ ÑообщеÑтва поÑвилоÑÑŒ в ÑпиÑке журналов, доÑтупных вам Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸ Ñвоих запиÑей. + +/community/join.bml.label.auth=ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° то, что вы ÑвлÑетеÑÑŒ учаÑтником Ñтого ÑообщеÑтва, вы не можете пиÑать. ЕÑли вы хотите получить право пиÑать в Ñто ÑообщеÑтво, ÑвÑжитеÑÑŒ Ñ Ð¾Ð´Ð½Ð¸Ð¼ из его Ñмотрителей. Ðиже приведён их ÑпиÑок: [[admins]] + +/community/join.bml.label.banned=Смотритель Ñтого ÑообщеÑтва запрещает вам приÑоединÑÑ‚ÑŒÑÑ Ðº ÑообщеÑтву. + +/community/join.bml.label.closed=Это закрытое ÑообщеÑтво. ЕÑли вы хотите приÑоединитьÑÑ Ðº нему, ÑвÑжитеÑÑŒ, пожалуйÑта, Ñ Ð¾Ð´Ð½Ð¸Ð¼ из его Ñмотрителей. Ðиже приведён их ÑпиÑок: [[admins]] + +/community/join.bml.label.commlogged=Ð’Ñ‹ вошли в ÑиÑтему иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑообщеÑтва, а не под вашим перÑональным именем пользователÑ. + +/community/join.bml.label.errorcomminfo=Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве некорректна. + +/community/join.bml.label.expls=Ðажмите на кнопку внизу, чтобы приÑоединитьÑÑ Ðº ÑообщеÑтву "[[maintainer]]". Уберите галочку в поле внизу, еÑли вы хотите приÑоединитьÑÑ Ðº ÑообщеÑтву, но не хотите видеть запиÑи оттуда в Ñвоей ленте друзей. + +/community/join.bml.label.loginfirst=Чтобы приÑоединитьÑÑ Ðº ÑообщеÑтву, вы должны вначале войти в ÑиÑтему. + +/community/join.bml.label.membernow=Теперь вы ÑвлÑетеÑÑŒ учаÑтником ÑообщеÑтва [[commname]] + +/community/join.bml.label.sure=Ð’Ñ‹ уверены? + +/community/join.bml.reqsubmitted.body=Ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° вÑтупление в ÑообщеÑтво отправлен ÑмотрителÑм + +/community/join.bml.reqsubmitted.title=Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° вÑтупление в ÑообщеÑтво отправлен + +/community/join.bml.request.body=ÑообщеÑтво не открытое. ПожалуйÑта, подтвердите, что вы хотите приÑоединитьÑÑ Ð½Ð°Ð¶Ð°Ð² ÑÑылку внизу. + +/community/join.bml.request.reason=ÐеобÑзательно: укажите причину, по которой вы хотите вÑтупить в ÑообщеÑтво: + +/community/join.bml.request.title=Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾ вÑтуплении + +/community/join.bml.success=УÑпешное завершение + +/community/join.bml.title=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +/community/leave.bml.button.leave=Покинуть ÑообщеÑтво + +/community/leave.bml.label.buttontoleave=Ðажмите на кнопку внизу, чтобы покинуть ÑообщеÑтво "[[commname]]". + +/community/leave.bml.label.infoerror=Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве некорректна. + +/community/leave.bml.label.logoutfirst=Чтобы покинуть ÑообщеÑтво, вы должны вначале войти в ÑиÑтему. + +/community/leave.bml.label.removed=Теперь вы иÑключены из ÑообщеÑтва [[commname]] + +/community/leave.bml.label.removefromfriends=Также удалить "[[user]]" из ÑпиÑка друзей. + +/community/leave.bml.success=Ð’Ñ‹ уÑпешно покинули ÑообщеÑтво + +/community/leave.bml.sure=Ð’Ñ‹ уверены? + +/community/leave.bml.title=Покинуть ÑообщеÑтво + +/community/manage.bml.commlist.actinfo=Инфо + +/community/manage.bml.commlist.actions=ДейÑтвиÑ: + +/community/manage.bml.commlist.actmembers=[УчаÑтники] + +/community/manage.bml.commlist.actmembers2=УчаÑтники + +/community/manage.bml.commlist.actpending|notes=This is appended to /community/manage.bml.commlist.actmembers2 when there are pending people. +/community/manage.bml.commlist.actpending=, [[num]] ожидающие Ð¿Ð¾Ð´Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ + +/community/manage.bml.commlist.actsettings=[ÐаÑтройки] + +/community/manage.bml.commlist.actsettings2=ÐаÑтройки + +/community/manage.bml.commlist.header=Ваши ÑообщеÑтва + +/community/manage.bml.commlist.moderation=ÐаходитÑÑ Ð² очереди на модерирование + +/community/manage.bml.commlist.moderation.num=[[[num]]в очереди] + +/community/manage.bml.commlist.none=Ð’Ñ‹ не управлÑете никакими ÑообщеÑтвами. + +/community/manage.bml.commlist.text=ЗдеÑÑŒ перечиÑлены ÑообщеÑтва, которыми вы управлÑете или помогаете управлÑÑ‚ÑŒ: + +/community/manage.bml.commlist.title=Ðазвание + +/community/manage.bml.commlist.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/community/manage.bml.create.header=Создать ÑообщеÑтво + +/community/manage.bml.create.text=Также вы можете Ñоздать новое ÑообщеÑтво. + +/community/manage.bml.joinmail.body=СообщеÑтва Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ членÑтвом имеют Ñледующие возможноÑти Ñообщений по email: + +/community/manage.bml.joinmail.email.all=ПриÑылать email каждый раз, когда кто-то хочет вÑтупить + +/community/manage.bml.joinmail.email.digest<< +ПриÑылать раз в день email Ñо ÑпиÑком желающих вÑтупить + +. + +/community/manage.bml.joinmail.email.none=Ðе приÑылать email, Ñ Ð±ÑƒÐ´Ñƒ иÑпользовать Ñту Ñтраницу Ð´Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации новых запроÑов + +/community/manage.bml.joinmail.save=Сохранить наÑтройки + +/community/manage.bml.joinmail.title=ÐдминиÑтративные возможноÑти + +/community/manage.bml.title=Управление ÑообщеÑтвами + +/community/members.bml.error.alreadyadded=[[user]] не был добавлен, поÑкольку уже имеет доÑтуп в ÑообщеÑтво. + +/community/members.bml.error.alreadysent=[[user]] не может быть добавлен, поÑкольку [[datetime]] ему было выÑлано подтверждающее пиÑьмо. Подождите ответа. + +/community/members.bml.error.invaliduser=Ðе могу добавить транÑлируемый аккаунт или ÑообщеÑтво: [[user]] + +/community/members.bml.error.noaccess=Только Ñмотрители ÑообщеÑтва могут редактировать ÑпиÑок его учаÑтников. Ð’Ñ‹ не ÑвлÑетеÑÑŒ Ñмотрителем ÑообщеÑтва [[comm]]. + +/community/members.bml.error.noattr=Ðе выбран ни один атрибут Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] + +/community/members.bml.error.nocomm=СообщеÑтво не найдено + +/community/members.bml.error.nouser=Такого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ ÑущеÑтвует: [[user]] + +/community/members.bml.key.admin=Смотритель + +/community/members.bml.key.member=УчаÑтник + +/community/members.bml.key.moderate=Модератор + +/community/members.bml.key.post=Может пиÑать + +/community/members.bml.key.preapprove=Ðе модерируетÑÑ + +/community/members.bml.key.user=Пользователь + +/community/members.bml.manage2=Управление ÑообщеÑтвами + +/community/members.bml.name=Ðазвание ÑообщеÑтва: [[name]] + +/community/members.bml.nextlink=(Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница...) + +/community/members.bml.prevlink=(ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница...) + +/community/members.bml.settings=[ÐаÑтройки] + +/community/members.bml.success.header=Ð’Ñ‹ Ñделали Ñто! + +/community/members.bml.success.message=Сделанные вами Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑƒÑпешно Ñохранены. + +/community/members.bml.success.return=ВернутьÑÑ Ðº ÑпиÑку + +/community/members.bml.title=УчаÑтники ÑообщеÑтва + +/community/members.bml.update=Обновить наÑтройки + +/community/moderate.bml.approve.button=Да, одобрить + +/community/moderate.bml.approve.header=Одобрить Ñту запиÑÑŒ? + +/community/moderate.bml.approve.preapprove=Добавить также Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок немодерируемых учаÑтников. + +/community/moderate.bml.approve.text=Ð’Ñ‹ уверены, что одобрÑете Ñту запиÑÑŒ? + +/community/moderate.bml.brlist.actions=ДейÑÑ‚Ð²Ð¸Ñ + +/community/moderate.bml.brlist.poster=Ðвтор + +/community/moderate.bml.brlist.subject=Ðачало заголовка + +/community/moderate.bml.brlist.time=Ð’Ñ€ÐµÐ¼Ñ + +/community/moderate.bml.brlist.view=ПоÑмотреть + +/community/moderate.bml.browse.empty=Очередь на модерацию пуÑта. + +/community/moderate.bml.browse.header=Модерировать ÑообщеÑтво + +/community/moderate.bml.browse.text=СпиÑок запиÑей Ð´Ð»Ñ Ð¼Ð¾Ð´ÐµÑ€Ð°Ñ†Ð¸Ð¸ в ÑообщеÑтве [[link]] + +/community/moderate.bml.choice.approve=Одобрить + +/community/moderate.bml.choice.reject=Отклонить + +/community/moderate.bml.error.noaccess=Ð’Ñ‹ не ÑвлÑетеÑÑŒ модератором ÑообщеÑтва [[comm]]. + +/community/moderate.bml.error.noentry=ЗапиÑÑŒ не найдена (видимо обработана другим модератором). + +/community/moderate.bml.error.nolist=Ð’Ñ‹ не ÑвлÑетеÑÑŒ модератором ни одного ÑообщеÑтва. + +/community/moderate.bml.error.notfound=Ðккаунт ÑообщеÑтва не найден + +/community/moderate.bml.manage=Управление ÑообщеÑтвами + +/community/moderate.bml.moderate=Модерировать ÑообщеÑтво + +/community/moderate.bml.modlist.actions=ДейÑÑ‚Ð²Ð¸Ñ + +/community/moderate.bml.modlist.actmodempty=[Модерировать] + +/community/moderate.bml.modlist.actmoderate=Модерировать + +/community/moderate.bml.modlist.count=Размер очереди + +/community/moderate.bml.modlist.header=Модерировать ÑообщеÑтва + +/community/moderate.bml.modlist.title=Заголовок + +/community/moderate.bml.modlist.username=Пользователь + +/community/moderate.bml.posted.appheader=Ðемодерируемое + +/community/moderate.bml.posted.apptext=[[user]] также был добавлен к ÑпиÑку немодерируемых пользователей. + +/community/moderate.bml.posted.header=Лепота + +/community/moderate.bml.posted.proterror=ЗапиÑÑŒ не была добавлена из за ошибки протокола: [[err]] + +/community/moderate.bml.posted.text=ЗапиÑÑŒ была уÑпешно добавлена + +/community/moderate.bml.reject.button=Да, отклонить + +/community/moderate.bml.reject.header=Отклонить Ñту запиÑÑŒ? + +/community/moderate.bml.reject.reason=Ð’Ñ‹ также можете объÑÑнить причину, по которой вы отклонили данную запиÑÑŒ. Пользователь получит Ñто объÑÑнение по e-mail. + +/community/moderate.bml.reject.text=Ð’Ñ‹ уверены, что хотите отклонить Ñту запиÑÑŒ? + +/community/moderate.bml.rejected.header=Отклонена + +/community/moderate.bml.rejected.text=ЗапиÑÑŒ была отклонена. + +/community/moderate.bml.title=Модерирование ÑообщеÑтва + +/community/pending.bml.approve.title=Подвердить вÑтупление в чены ÑообщеÑтва? + +/community/pending.bml.no=Ðет + +/community/pending.bml.nopending.body=Ðикто не ожидает зачиÑÐ»ÐµÐ½Ð¸Ñ Ð² ÑообщеÑтво. + +/community/pending.bml.nopending.title=Ðикто не ждет Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ + +/community/pending.bml.success.added=Ð’Ñ‹ добавили [[num]] [[?num|person|persons]] человек к членам Ñтого ÑообщеÑтва + +/community/pending.bml.success.ignored=[[num]] [[?num|request is|requests are]] вÑе еще ожидают Ñ€ÐµÑˆÐµÐ½Ð¸Ñ + +/community/pending.bml.success.previous=[[num]] [[?num|request has|requests have]] не обработаны, поÑкольку они больше не ожидают утверждениÑ. Другой Ñмотритель уже обработал [[?num|it|them]]. + +/community/pending.bml.success.rejected=Ð’Ñ‹ отказали [[num]] [[?num|request|requests]] во вÑтуплении в Ñто ÑообщÑтво + +/community/pending.bml.title=Ожидают зачиÑÐ»ÐµÐ½Ð¸Ñ Ð² члены ÑообщеÑтва + +/community/pending.bml.yes=Да + +/community/search.bml.button.clear=ОчиÑтить форму + +/community/search.bml.button.search=ИÑкать! + +/community/search.bml.checkbox.onlywithpics=Только ÑообщеÑтва Ñ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ°Ð¼Ð¸ + +/community/search.bml.label.byinterest=По интереÑам + +/community/search.bml.label.bylocation=По меÑтоположению + +/community/search.bml.label.bytime=По времени поÑледнего Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ + +/community/search.bml.label.city=Город: + +/community/search.bml.label.country=Страна: + +/community/search.bml.label.displayoptions=Показывать + +/community/search.bml.label.hasmember=По учаÑтнику + +/community/search.bml.label.othercriteria=По другому критерию + +/community/search.bml.label.outputformat=Формат вывода: + +/community/search.bml.label.records=Ðа Ñтранице: + +/community/search.bml.label.searchcomm=Ðайти ÑообщеÑтва + +/community/search.bml.label.selecriteria=Выберите критерий, по которому хотите найти ÑообщеÑтво. Ð’Ñ‹ получите переÑечение результатов поиÑка по вÑем выбранным критериÑм. Другими Ñловами, критерии объединÑÑŽÑ‚ÑÑ Ð¿Ð¾ принципу "И", а не "ИЛИ". + +/community/search.bml.label.sortmethod=Сортировать: + +/community/search.bml.label.stateprovince=Штат/ПровинциÑ: + +/community/search.bml.label.updated=ПоÑледний раз обновлÑлоÑÑŒ в течение + +/community/search.bml.sel.bypicture=По картинке + +/community/search.bml.sel.communityname=По названию ÑообщеÑтва + +/community/search.bml.sel.commview=Вид ÑообщеÑтва + +/community/search.bml.sel.day=Ð´Ð½Ñ + +/community/search.bml.sel.month=меÑÑца + +/community/search.bml.sel.simple=ПроÑтой + +/community/search.bml.sel.updatetime=По времени Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ + +/community/search.bml.sel.username=По имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/community/search.bml.sel.week=недели + +/community/search.bml.title=ПоиÑк ÑообщеÑтва + +/community/settings.bml.button.changecommunity=Обновить наÑтройки + +/community/settings.bml.button.createcommunity=Создать ÑообщеÑтво + +/community/settings.bml.error.badpassword=Ðеверный пароль к ÑообщеÑтву + +/community/settings.bml.error.hasentries=Ð’ Ñтом журнале уже еÑÑ‚ÑŒ запиÑи и его тип не может быть изменён. + +/community/settings.bml.error.maintainertype=Ðккаунт ÑÐ¾Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ ÑообщеÑтва должен быть чаÑтным, а не общеÑтвенным. + +/community/settings.bml.error.noaccess=Только Ñмотрители ÑообщеÑтва могут редактировать наÑтройки ÑообщеÑтва. Ð’Ñ‹ не ÑвлÑетеÑÑŒ Ñмотрителем ÑообщеÑтва [[comm]], + +/community/settings.bml.error.notcomm=Это не аккаунт ÑообщеÑтва. + +/community/settings.bml.error.notfound=Ðе указано Ð¸Ð¼Ñ ÑообщеÑтва. + +/community/settings.bml.error.samenames=Ðккаунты ÑÐ¼Ð¾Ñ‚Ñ€Ð¸Ñ‚ÐµÐ»Ñ Ð¸ ÑообщеÑтва не должны быть одним и тем же аккаунтом. + +/community/settings.bml.label.anybodycan=Ð’Ñе учаÑтники
            Кто угодно может пиÑать в Ñто ÑообщеÑтво Ñразу поÑле вÑтуплениÑ. + +/community/settings.bml.label.changeheader=Изменить наÑтройки ÑообщеÑтва + +/community/settings.bml.label.changetext=ЗдеÑÑŒ можно изменить наÑтройки принадлежащего вам ÑообщеÑтва или ÑообщеÑтва, Ñмотрителем которого вы ÑвлÑетеÑÑŒ. + +/community/settings.bml.label.closedmemb2=Закрытое ÑообщеÑтво
            Больше никто не может в него вÑтупить . + +/community/settings.bml.label.commchanged=ÐаÑтройки ÑообщеÑтва изменены. + +/community/settings.bml.label.commcreate=Это аккаунт, который вы пожелали превратить в ÑообщеÑтво. Он должен быть предварительно Ñоздан, но не должен иÑпользоватьÑÑ ÐºÐµÐ¼-то перÑонально, так как множеÑтво разных людей потенциально Ñмогут оÑтавлÑÑ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð² Ñтом журнале. + +/community/settings.bml.label.commcreated=СообщеÑтво Ñоздано. + +/community/settings.bml.label.commheader=Ðккаунт ÑообщеÑтва + +/community/settings.bml.label.comminfo=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/community/settings.bml.label.commopts=ÐаÑтройки ÑообщеÑтва + +/community/settings.bml.label.commsite=Сайт ÑообщеÑтва + +/community/settings.bml.label.community=СообщеÑтво: + +/community/settings.bml.label.createheader=Создать ÑообщеÑтво + +/community/settings.bml.label.createtext=ЗдеÑÑŒ вы можете Ñоздать ÑообщеÑтво. СообщеÑтво - Ñто Ñпециальный вид аккаунта, который позволÑет людÑм приÑоединÑÑ‚ÑŒÑÑ Ð¸ пиÑать в него. Ðапример, поÑмотрите на ÑообщеÑтво поддержки руÑÑкого ЖЖ. + +/community/settings.bml.label.howoperates=Выберите режим Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑообщеÑтва. Ð’Ñ‹ можете изменить Ñти наÑтройки позже. + +/community/settings.bml.label.maintainer=Смотритель: + +/community/settings.bml.label.maintainer.login=ЕÑли Ñто не Ð¸Ð¼Ñ Ð±ÑƒÐ´ÑƒÑ‰ÐµÐ³Ð¾ ÑмотрителÑ, войдите под другим. + +/community/settings.bml.label.managepage=Управление ÑообщеÑтвом - добавить членов ÑообщеÑтва, разрешить оÑтавлÑÑ‚ÑŒ запиÑи, назначить модераторов и Ñ‚.п. + +/community/settings.bml.label.membership=УчаÑтие + +/community/settings.bml.label.moderatedmemb=Модерируемое ÑообщеÑтво
            ЗапроÑÑ‹ о вÑтуплении приÑылаютÑÑ Ð²Ð°Ð¼ по еmail Ð´Ð»Ñ ÑƒÑ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ. + +/community/settings.bml.label.modheader=ÐœÐ¾Ð´ÐµÑ€Ð°Ñ†Ð¸Ñ + +/community/settings.bml.label.modis=Модерируемое
            Ðовые запиÑи должны быть одобрены модератором. + +/community/settings.bml.label.modisnt=Ðемодерируемое
            Ðовые запиÑи ÑтановÑÑ‚ÑÑ Ð²Ð¸Ð´Ð½Ñ‹ Ñразу. + +/community/settings.bml.label.modtext=Модерируемое ли Ñто ÑообщеÑтво? + +/community/settings.bml.label.nmcan=Ð’Ñе могут пиÑать
            Пользователи могут пиÑать в Ñто ÑообщеÑтво даже не приÑоединÑÑÑÑŒ к нему. + +/community/settings.bml.label.nmcant=Только учаÑтники могут пиÑать
            Пользователи могут пиÑать в Ñто ÑообщеÑтво только Ñтав его учаÑтниками. + +/community/settings.bml.label.nmheader=ДоÑтуп Ð´Ð»Ñ Ð½Ðµ-учаÑтников + +/community/settings.bml.label.nmtext=Можно ли пиÑать в Ñто ÑообщеÑтво, не приÑоединÑÑÑÑŒ к нему? + +/community/settings.bml.label.openmemb=Свободное учаÑтие
            Ð’Ñе желающие могут приÑоединитьÑÑ Ðº Ñтому ÑообщеÑтву. + +/community/settings.bml.label.password=Пароль: + +/community/settings.bml.label.postaccess=Кто может пиÑать + +/community/settings.bml.label.rellinks=Важные ÑÑылки: + +/community/settings.bml.label.selcan=Только избранные
            Только некоторые учаÑтники ÑообщеÑтва могут в него пиÑать, получив предварительно на Ñто разрешение ÑмотрителÑ. + +/community/settings.bml.label.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/community/settings.bml.label.whocanjoin=Кто может приÑоединитьÑÑ Ðº Ñтому ÑообщеÑтву? + +/community/settings.bml.label.whocanpost=Кто может пиÑать в Ñто ÑообщеÑтво? + +/community/settings.bml.manage2=Управление ÑообщеÑтвами + +/community/settings.bml.members=[УчаÑтники] + +/community/settings.bml.name=Ðазвание ÑообщеÑтва: [[name]] + +/community/settings.bml.success=Ð’Ñ‹ проÑто молодец! + +/community/settings.bml.title.create=Создать ÑообщеÑтво + +/community/settings.bml.title.modify=ÐаÑтройки ÑообщеÑтва + +/create.bml.age.check.question=Вам меньше 13-ти лет? + +/create.bml.age.check.yes=Да, мне меньше 13-ти лет. + +/create.bml.age.check2.question=Ð’Ñ‹ Ñтарше 13 лет? + +/create.bml.age.check2.yes=Да, мне больше 13 лет. + +/create.bml.age.head=ВозраÑÑ‚ + +/create.bml.btn.create=Создать журнал + +/create.bml.btn.proceed=Продолжить... + +/create.bml.captcha.answer=Ответ: + +/create.bml.captcha.audiodesc=Чтобы доказать, что журнал региÑтрирует не робот, наберите цифры, которые вы уÑлышали: + +/create.bml.captcha.desc=Ðам нужно убедитьÑÑ, что журнал региÑтрирует не робот. ПожалуйÑта, наберите буквы и цифры, которые вы видите на картинке. ЕÑли вы не можете прочитать текÑÑ‚, наберите Ñлово "AUDIO" и пройдите звуковой теÑÑ‚. + +/create.bml.captcha.invalid=Ðеправильный ответ. Попробуйте еще раз. + +/create.bml.captcha.play=ВоÑпроизведение звука + +/create.bml.captcha.prove=Проверим, что вы – не робот-киберÑквоттер + +/create.bml.clusterselect.cluster=КлаÑтер: + +/create.bml.clusterselect.clusternum=КлаÑтер [[number]] + +/create.bml.clusterselect.head=Выбор клаÑтера + +/create.bml.clusterselect.nocluster=Без клаÑтера + +/create.bml.clusterselect.text=Выберите клаÑтер, в котором хотите Ñоздать пользователÑ. Внимание: Эта наÑтройка только Ð´Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸/теÑтированиÑ. Реальные пользователи не Ñмогут выбрать Ñту наÑтройку и ничего не будут знать о ней. + +/create.bml.create.head=Создание нового журнала + +/create.bml.create.text=Создать новый журнал легко, проÑто Ñледуйте инÑтрукциÑм. + +/create.bml.email.head=Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты + +/create.bml.email.input.head=E-mail адреÑ: + +/create.bml.email.text2=Из Ñоображений безопаÑноÑти нам требуетÑÑ Ð²Ð°Ñˆ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты. Ðикогда и ни при каких обÑтоÑтельÑтвах он не будет продан или иным ÑпоÑобам передан Ñпаммерам. Мы и Ñами их ненавидим. Чтобы узнать подробноÑти, прочтите наше положение о конфиденциальноÑти. + +/create.bml.error.coppa.under13=Извините, но из-за ограничений COPPA (Ðкта о защите детей в Ñети, дейÑтвующего в СШÐ), вы не можете пользоватьÑÑ Ð–Ð¸Ð²Ñ‹Ð¼ Журналом, пока вам не иÑполнитÑÑ 13 лет. ПожалуйÑта, возвращайтеÑÑŒ на ваш тринадцатый день рождениÑ. + +/create.bml.error.email.blank=Ð’Ñ‹ должны указать Ñвой Ð°Ð´Ñ€ÐµÑ e-mail. + +/create.bml.error.email.lj_domain=Ð’Ñ‹ не можете иÑпользовать e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ð° [[domain]]. Введите другой Ð°Ð´Ñ€ÐµÑ e-mail. + +/create.bml.error.email.nospaces=Ð’ e-mail адреÑе Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать пробелы. ЕÑли вы пользователь AOL, учтите, что ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð² интернете -- Ñто ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² AOL без пробелов, за которым Ñледует @aol.com + +/create.bml.error.password.asciionly=Ð’ пароле можно иÑпользовать только Ñимволы ASCII (Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать кириллицу). + +/create.bml.error.password.blank=Ð’Ñ‹ должны ввеÑти пароль. + +/create.bml.error.password.nomatch=Пароли не Ñовпадают. + +/create.bml.error.postrequired=Ðужно иÑпользовать метод POST. + +/create.bml.error.username.blank=ПожалуйÑта, введите имÑ, название или пÑевдоним. + +/create.bml.error.username.inuse=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ занÑто; пожалуйÑта, выберите другое имÑ. + +/create.bml.error.username.iscode=КажетÑÑ, вмеÑто имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð²Ñ‹ ввели приглаÑительный код. + +/create.bml.error.username.mustenter=Ð’Ñ‹ должны ввеÑти имÑ. + +/create.bml.error.username.reserved=Извините, Ñто Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°Ñ€ÐµÐ·ÐµÑ€Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¾. + +/create.bml.errors.label=ПожалуйÑта, иÑправьте Ñледующие проблемы и Ñохраните Ñнова + +/create.bml.initial.friend.lj_maintenance=Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ запланированных и незапланированных отключениÑÑ…, а также профилактике. + +/create.bml.initial.friend.news=ÐовоÑти и ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала + +/create.bml.initialfriends=Добавьте Ñти журналы в ÑпиÑок ваших друзей, чтобы быть в курÑе новоÑтей и информации Ñайта. + +/create.bml.initialfriends.heading=Ð”Ñ€ÑƒÐ·ÑŒÑ Ð½Ð¾Ð²Ð¸Ñ‡ÐºÐ° + +/create.bml.name.head=Ваше Ð¸Ð¼Ñ + +/create.bml.name.input.head=ИмÑ: + +/create.bml.name.text=Как Ð²Ð°Ñ Ð·Ð¾Ð²ÑƒÑ‚? Это Ð¸Ð¼Ñ Ð±ÑƒÐ´ÐµÑ‚ показано в заголовке вашего журнала и в каталоге пользователей, еÑли вы хотите, чтобы Ð²Ð°Ñ Ñ‚ÑƒÐ´Ð° добавили. Ð’Ñ‹ не обÑзаны указывать полное или даже Ñвоё наÑтоÑщее имÑ. + +/create.bml.password.head=Пароль + +/create.bml.password.input.head1=Пароль: + +/create.bml.password.input.head2= Повторите пароль: + +/create.bml.password.text=Выберите пароль. + +/create.bml.proceed.btn.proceed=Продолжить... + +/create.bml.proceed.warning=Ðажмите Продолжить только один раз!!! + +/create.bml.success.btn.enterinfo=Введите личные данные + +/create.bml.success.head=УÑпешно + +/create.bml.success.text1=Ваш журнал Ñоздан. Ðа ваш Ð°Ð´Ñ€ÐµÑ [[email]] выÑлана Ð²Ð°Ð¶Ð½Ð°Ñ Ñ€ÐµÐ³Ð¸ÑÑ‚Ñ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¸ дальнейшие инÑтрукции. Ðе забудьте подтвердить Ñоздание нового журнала, Ð¿Ñ€Ð¾Ð¹Ð´Ñ Ð¿Ð¾ ÑÑылке, ÑодержащейÑÑ Ð² пиÑьме. + +/create.bml.success.text2=Ваш Живой Журнал доÑтупен по адреÑу: + +/create.bml.success.text3=ПожалуйÑта, заполните небольшую анкету о Ñебе. Ð’ оÑновном, Ñто необÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, но так мы получаем предÑтавление о том, кто пользуетÑÑ Ð–Ð¸Ð²Ñ‹Ð¼ Журналом. + +/create.bml.title=Создание нового журнала + +/create.bml.tos.error=Ð’Ñ‹ должны прочитать и ÑоглаÑитьÑÑ Ñ ÑƒÑловиÑми предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг перед тем, как Ñоздавать аккаунт. + +/create.bml.tos.haveread=Я прочёл уÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг и ÑоглаÑен Ñ Ð½Ð¸Ð¼Ð¸. + +/create.bml.tos.heading=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг + +/create.bml.tos.p1.2=Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации вы должны ознакомитьÑÑ Ð¸ ÑоглаÑитьÑÑ Ñ Ð£ÑловиÑми предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг. + +/create.bml.useacctcodes.entercode=Введите код Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ пользователÑ. Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации Ñмотрите: Как мне Ñоздать новый аккаунт? + +/create.bml.useacctcodes.welcome=Добро пожаловать + +/create.bml.username.box.head=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/create.bml.username.charsallowed=Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¼Ð¾Ð¶ÐµÑ‚ ÑоÑтоÑÑ‚ÑŒ только из Ñтрочных букв (a-z), цифр (0-9), и знака Ð¿Ð¾Ð´Ñ‡ÐµÑ€ÐºÐ¸Ð²Ð°Ð½Ð¸Ñ (_).
            Длина имени не может быть больше 15 Ñимволов. + +/create.bml.username.forpaidaccts=Или, Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ñ… пользователей: + +/create.bml.username.head=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/create.bml.username.ljaddress=Ваш журнал будет находитьÑÑ Ð¿Ð¾ Ñтим адреÑам: + +/create.bml.username.text=У каждого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[sitename]] должно быть уникальное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ñ€Ð¸ÑутÑтвует в адреÑе, по которому раÑположен ваш журнал, и должно иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему. Его также видно, когда вы оÑтавлÑете комментарии в других журналах. + +/create.bml.username.username=имÑ_Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/customize/index.bml.change=Изменить + +/customize/index.bml.choose=Ð’Ñ‹ хотите иÑпользовать Ñтарую ÑиÑтему или новую? + +/customize/index.bml.choose.header=Выбрать ÑиÑтему Ñтилей + +/customize/index.bml.choose.s1=Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÑиÑтема (S1) + +/customize/index.bml.choose.s2=ÐÐ¾Ð²Ð°Ñ ÑиÑтема (S2) + +/customize/index.bml.error.cant_generate_user_layer=Ðе могу Ñгенерировать Ñлой Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/customize/index.bml.error.fail_create_style=Ðевозможно Ñодать новый Ñтиль + +/customize/index.bml.error.not_your_layout=Ðе ваша Ñхема. + +/customize/index.bml.error.not_your_theme=Ðе Ваша тема + +/customize/index.bml.error.no_core_parent=ОтÑуÑтвует начавший тему? + +/customize/index.bml.previews=(Предварительный проÑмотр) + +/customize/index.bml.s1=Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÑиÑтема Ñтилей наÑтраиваетÑÑ Ñ‡ÐµÑ€ÐµÐ· Ñтраницу Изменить журнал. + +/customize/index.bml.s1.header=ИÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ S1 + +/customize/index.bml.s2.advanced.denied=Только пользователи Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼Ð¸ и поÑтоÑнными аккаунтами, а также ранние пользователи могут иÑпользовать раÑширенные наÑтройки. О преимущеÑтвах платного аккаунта. + +/customize/index.bml.s2.advanced.header=РаÑширенные наÑтройки + +/customize/index.bml.s2.advanced.permitted=Создать новые Ñхемы и Ñтили Ñ Ð½ÑƒÐ»Ñ Ð¼Ð¾Ð¶Ð½Ð¾ на Ñтранице раÑширенных наÑтроек. + +/customize/index.bml.s2.customize=Эти параметры завиÑÑÑ‚ от Ñхемы. + +/customize/index.bml.s2.customize.header=Шаг 2: Изменить вид Ñтраницы + +/customize/index.bml.s2.customize.language=Эти Ñзыки полноÑтью или чаÑтично поддерживаютÑÑ Ð´Ð°Ð½Ð½Ð¾Ð¹ Ñхемой. + +/customize/index.bml.s2.customize.language.custom=Изменить + +/customize/index.bml.s2.customize.language.header=Язык + +/customize/index.bml.s2.customize.settings=ЕÑли Ð’Ñ‹ хотите еще больше изменить вид Ñвоего журнала, здеÑÑŒ вы можете подкрутить отдельные параметры, пока не получите то, что Вам нужно. + +/customize/index.bml.s2.customize.settings.delete=Удалить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/customize/index.bml.s2.customize.settings.delete.confirm=Vy tochno hotite udalit' jeti nastrojki? + +/customize/index.bml.s2.customize.settings.edit=Редактировать наÑтройки + +/customize/index.bml.s2.customize.settings.header=Изменить отдельные параметры + +/customize/index.bml.s2.customize.settings.new=ÐаÑтроить + +/customize/index.bml.s2.customize.themes=Ð’Ñ‹ можете выбрать одну из Ñледующих тем Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ Ñхемы. + +/customize/index.bml.s2.customize.themes.default=(По умолчанию Ð´Ð»Ñ Ñхемы) + +/customize/index.bml.s2.customize.themes.header=Темы + +/customize/index.bml.s2.layout=Выберите Ñхему. Выбрав новую Ñхему, вы потерÑете вÑе другие изменениÑ, которые могли Ñделать, так как набор доÑтупных тем и отдельные наÑтройки завиÑÑÑ‚ от выбранной Ñхемы. + +/customize/index.bml.s2.layout.header=Шаг 1: Схема + +/customize/index.bml.s2.related.editinfo.about=УÑтановите название Вашего журнала и другие ÑвойÑтва. + +/customize/index.bml.s2.related.header=СвÑзанные Ñтраницы. + +/customize/index.bml.s2.related.links.about=Ðекоторые Ñтили могут включатÑÑ Ð² Ваш ÑпиÑок ÑÑылок. + +/customize/index.bml.s2.related.modify.about=УÑтановите набор изображений наÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ журнала. + +/customize/index.bml.title=Оформление журнала + +/delcomment.bml.changeoptions=Внимание: Ðа Ñтранице "[[link]]" вы можете выбрать, разрешаете ли вы вÑем, зарегиÑтрированным пользователÑм, или только друзьÑм комментировать ваши запиÑи. + +/delcomment.bml.confirm.banuser=Заблокировать [[user]] возможноÑÑ‚ÑŒ комментариев в вашем журнале + +/delcomment.bml.confirm.body=Ð’Ñ‹ точно хотите удалить Ñтот комментарий? + +/delcomment.bml.confirm.head=Удалить Ñтот комментарий? + +/delcomment.bml.confirm.spam=Отметить Ñтот комментарий как Ñпам + +/delcomment.bml.confirm.submit=Удалить комментарий + +/delcomment.bml.error.alreadydeleted=Этот комментарий уже удален + +/delcomment.bml.error.cantdelete=Комментарий может быть удален только его автором или автором журнала + +/delcomment.bml.error.cantdelete.comm=Комментарий может быть удален только его автором или автором запиÑи в журнале или Ñмотрителем ÑообщеÑтва + +/delcomment.bml.error.invalidtype=Ðеправильный тип комментариÑ. Ð”Ð°Ð½Ð½Ð°Ñ Ñтраница иÑпользуетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸ÐµÐ² к запиÑÑм в журнале. + +/delcomment.bml.error.nocomment=Этот комментарий не ÑущеÑтвует. + +/delcomment.bml.success.andban=Комментарий удален, и пользователь [[user]] лишён права оÑтавлÑÑ‚ÑŒ комментарии в вашем журнале. + +/delcomment.bml.success.head=Удалено + +/delcomment.bml.success.noban=Комментарий удален + +/delcomment.bml.success.spam=ÐдминиÑтраторы Ñайта извещены о том, что данный комментарий - Ñпам. СпаÑибо за Ñообщение. + +/delcomment.bml.title=Удаление ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/developer/index.bml.clients<< +Итак, Ð’Ñ‹ хотите улучшить программу-клиент Живого Журнала Ð´Ð»Ñ Ð’Ð°ÑˆÐµÐ¹ платформы? Замечательно! +ЗдеÑÑŒ Ð’Ñ‹ найдете информацию, нужную Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы разобратьÑÑ ÐºÐ°Ðº работает Живой Журнал. +. + +/developer/index.bml.clients.header=Как напиÑать программу-клиент Ð´Ð»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала + +/developer/index.bml.clients.links<< +
            +
            Протокол клиент<->Ñервер Живого Журнала
            +
            Узнайте, как клиент ЖЖ на вашем компьютере "общаетÑÑ" Ñ Ñервером ЖЖ и наоборот. + УÑвойте Ñто, прежде чем начнете разрабатывать или уÑовершенÑтвовать программу-клиента под Вашу платформу.
            +
            ÐŸÐ¾Ð»Ð½Ð°Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð°
            +
            Ð’Ñе другие режимы и ÑвойÑтва протокола.
            +
            СпиÑок клиентов
            +
            СпиÑок почти вÑех клиентов Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð’Ð°ÑˆÐ¸Ð¼ ЖЖ. Ð”Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð½Ñтва Ñтих клиентов доÑтупен иÑходный код, и вÑе они беÑплатны! Это то меÑто, где можно взÑÑ‚ÑŒ пример Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ Вашего будущего клиента ЖЖ.
            +
            +. + +/developer/index.bml.code<< +ЕÑли вы хотите увидеть Живой Журнал изнутри и понÑÑ‚ÑŒ как работают некоторые программы-клиенты, поÑетите Ñтраницу Код. + +. + +/developer/index.bml.code.header=Ðрхив кода Живого Журнала + +/developer/index.bml.dbschema<< +ИнтереÑует Ñтруктура базы данных? +Ðабор SQL комманд, Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ Ð½Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñех таблиц включен вмеÑте Ñ ÐºÐ¾Ð´Ð¾Ð¼ Ñервера. +. + +/developer/index.bml.dbschema.header=Схема базы данных + +/developer/index.bml.embedding<< +Хотите вÑтроить Ваш ЖЖ в Ñвой Ñайт? СущеÑтвует +неÑколько ÑпоÑобов оÑущеÑтвить Ñто, в завиÑимоÑти от того, какие привелегии Ð’Ñ‹ имеете Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ð¼ Ñайтом. Ð’ Ñтом и заключаетÑÑ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð°, конешно, еÑли только Ð’Ñ‹ не против ÑÑылки www.livejournal.com в вашем ЖЖ. + +. + +/developer/index.bml.embedding.header=Как включить ÑÑылку на Живой Журнал на вашей Ñтранице + +/developer/index.bml.notice.header=ОбъÑвление + +/developer/index.bml.notice1=Эта Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð° только Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸Ñтов и продвинутых пользователей. ЕÑли Ð’Ñ‹ проÑто хотите иÑпользовать Живой журнал Ð´Ð»Ñ Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ дневника, отлично! Обычный пользователь может не беÑпокоитьÑÑ Ð¾Ð± Ñтих штуках и Ñпать Ñпокойно. + +/developer/index.bml.notice2=Содержание Ñтой Ñекции поделено на две чаÑти: в первой Ð’Ñ‹ найдете информацию, как оформить Ñтраницы вашего Живого Журнала, а во второй - как пиÑать программы-клиенты Живого Журнала Ð´Ð»Ñ Ð½Ð°ÑˆÐµÐ³Ð¾ Ñервера + +/developer/index.bml.styles=Вам не нравитÑÑ Ð²Ð¸Ð´ Вашего Живого Журнала? Ðе беÑпокойтеÑÑŒ, вÑе можно изменить. ЕÑли вы прочитаете инÑтрукции, Ð’Ñ‹ узнаете вÑе необходимое Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы Ваш Живой Журнал выглÑдел в точноÑти так, как Вам хотелоÑÑŒ бы. + +/developer/index.bml.styles.header=Оформление Живого Журнала + +/developer/index.bml.styles.s1.header=СиÑтема Стилей 1 + +/developer/index.bml.styles.s1.system=СиÑтема ÑÑ‚Ð¸Ð»Ñ + +/developer/index.bml.styles.s1.system.about=Общий обзор уÑтройÑтва первой ÑиÑтемы Ñтилей. + +/developer/index.bml.styles.s1.varlist=СпиÑок переменных + +/developer/index.bml.styles.s1.varlist.about=Ðлфавитный ÑпиÑок вÑех параметров, которые можно изменить + +/developer/index.bml.styles.s1.views=ПоÑмотреть типы + +/developer/index.bml.styles.s1.views.about=СпиÑок различных ÑпоÑобов, которыми вы можете проÑматривать ваш журнал, Ñ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð¸ÐµÐ¼ деталей каждого из них. + +/developer/index.bml.styles.s2.header=СиÑтема Стилей 2 + +/developer/index.bml.styles.s2.layerbrowse=ПроÑмотрщик уровней S2 + +/developer/index.bml.styles.s2.layerbrowse.about=Полный ÑпиÑок общедоÑтупных уровней S2, включающий ÑиÑтемные Ñтили. ЗдеÑÑŒ важны базовые уровни, которые определÑÑŽÑ‚ переменные, функции и клаÑÑÑ‹, делающие S2 мощным Ñзыком Ð´Ð»Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ð°. + +/developer/index.bml.styles.s2.manual=РуководÑтво по S2 + +/developer/index.bml.styles.s2.manual.about=ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± иÑпользовании ÑиÑтемы Ñтилей S2 в ЖЖ + +/developer/index.bml.title=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð² + +/directory.bml.browse.country.desc=Выберите Ñтрану, чтобы увидеть журналы, авторы которых в ней находÑÑ‚ÑÑ. + +/directory.bml.browse.country.title=Показать журналы ÑоответÑтвенно Ñтране + +/directory.bml.browse.usa.desc=Ðажмите на штат СШРили на название Ñтраны из ÑпиÑка, приведенного под картой, чтобы увидеть журналы из выбранного штата или Ñтраны. + +/directory.bml.browse.usa.title=Показать журналы ÑоответÑтвенно штату СШР+ +/directory.bml.error.accounttype=К Ñожалению, ваш аккаунт не позволÑет производить поиÑк в каталоге, или же вы не вошли в ÑиÑтему. ЕÑли ваш аккаунт позволÑет работу Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼, убедитеÑÑŒ, что вы вошли в ÑиÑтему и попробуйте ещё раз. + +/directory.bml.navcrap.matches=Ðайдено: [[count]] + +/directory.bml.navcrap.xofy=Показана Ñтраница [[curpage]] из [[totpages]] (Ñ [[reca]] по [[recb]] запиÑÑŒ) + +/directory.bml.open<< +Открыть + +. + +/directory.bml.post<< +ÐапиÑать +ÐапиÑать +. + +/directory.bml.search.monkey=Выше вы можете видеть трёх вошек, которые в данный момент выполнÑÑŽÑ‚ поиÑк по вашему запроÑу. Ждите ответа. + +/directory.bml.search.new=Ðовый Ð·Ð°Ð¿Ñ€Ð¾Ñ + +/directory.bml.search.overflow=Ð’ результатах поиÑка выводитÑÑ Ð½Ðµ более [[count]] журналов. ПожалуйÑта, уточните Ñвой запроÑ. + +/directory.bml.search.title=ПоиÑк + +/directory.bml.update=Обновить + +/directory.bml.user=Пользователь + +/doc/index.bml.about=Добро пожаловать в хранилище документации Живого Журнала. ЗдеÑÑŒ вы можете найти информацию практичеÑки обо вÑём, что каÑаетÑÑ ÑервиÑов и программного обеÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ñервера Живого Журнала. ПожалуйÑта, выберите интереÑующую Ð²Ð°Ñ Ñ‚ÐµÐ¼Ñƒ: + +/doc/index.bml.about.header=Добро пожаловать + +/doc/index.bml.docs.faq.about=ВопроÑÑ‹ о LiveJournal.com и ответы на них + +/doc/index.bml.docs.faq.title=Справка ЖЖ + +/doc/index.bml.docs.guides.about=ИнформациÑ, Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ðº ВопроÑам и ответам + +/doc/index.bml.docs.guides.title=ИнÑтрукции + +/doc/index.bml.docs.header=Документы + +/doc/index.bml.docs.howto.about=Советы о переделке Ñвоего Живого Журнала + +/doc/index.bml.docs.server.about=Ð’ÑÑ‘, что нужно знать об уÑтановке, админиÑтрировании и тонкой наÑтройке Ñервера Живого Журнала + +/doc/index.bml.docs.server.title=РуководÑтво по Ñерверу Живого Журнала + +/doc/index.bml.docs.tour.about=Ð”Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ‡ÐºÐ¾Ð², которые хотÑÑ‚ узнать больше о Ñайте + +/doc/index.bml.docs.tour.title=Ознакомление + +/doc/index.bml.title=Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ + +/doc/index.bml.volunteering.about=ЕÑли вы хотите помочь в ÑоÑтавлении документации Живого Журнала, обратитеÑÑŒ в Ñледующие форумы: + +/doc/index.bml.volunteering.header=Ð”Ð¾Ð±Ñ€Ð¾Ð²Ð¾Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒ + +/doc/index.bml.volunteering.ljsysdoc=ОбÑуждение ÑиÑтемы Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала + +/doc/index.bml.volunteering.ljuserdoc=ОбÑуждение документации Ð´Ð»Ñ ÐºÐ¾Ð½ÐµÑ‡Ð½Ñ‹Ñ… пользователей + +/doc/tour/index.bml.clients.caption<< +Программы-клиенты Живого Журнала -- небольшие по объему программы, работающие на вашем компьютере. Они дают вам возможноÑÑ‚ÑŒ в любое удобное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑÑ‚ÑŒ ваш журнал без иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°. + +Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ ÑущеÑтвуют клиенты практичеÑки Ð´Ð»Ñ Ð²Ñех платформ, и многие из них очень проÑÑ‚Ñ‹ в наÑтройке и ÑкÑплуатации. +. + +/doc/tour/index.bml.clients.title=Программы-клиенты + +/doc/tour/index.bml.comms.caption=Живой Журнал Ñам по Ñебе -- огромное интерактивное ÑообщеÑтво, поÑтому Ð´Ð»Ñ Ð²Ð°Ñ, вероÑтно, не будет Ñюрпризом, что множеÑтво других пользователей имеют интереÑÑ‹, Ñхожие Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸. Ðа данный момент мы предлагаем возможноÑÑ‚ÑŒ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð² ÑообщеÑтва по интереÑам, либо Ñоздание Ñпециализированных журналов общего доÑтупа. + +/doc/tour/index.bml.comms.title=СообщеÑтва + +/doc/tour/index.bml.create.caption=Живой Журнал -- ÑообщеÑтво, оÑнованное на региÑтрации учаÑтников. Ðа данной Ñтранице объÑÑнÑетÑÑ, что такое региÑтрациÑ, почему она важна и какие преимущеÑтва она даёт. Ðа ней вы также найдёте форму Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ аккаунта. + +/doc/tour/index.bml.create.title=Создание аккаунта + +/doc/tour/index.bml.friends.caption=Ð’Ñ‹ можете Ñледить за ÑобытиÑми, о которых пишут в Ñвоих журналах ваши друзьÑ, Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ функции Живого Журнала "СпиÑок друзей". ЕÑли какой-то журнал показалÑÑ Ð²Ð°Ð¼ заÑлуживающим Ð²Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ -- добавьте его в Ñвой ÑпиÑок друзей. Это даÑÑ‚ вам возможноÑÑ‚ÑŒ читать вÑе интереÑующие Ð²Ð°Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñ‹ на одной Ñтранице. + +/doc/tour/index.bml.friends.title=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/doc/tour/index.bml.intro.caption=Этот путеводитель адреÑован новым пользователÑм и предназначен Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ Ð–Ð¸Ð²Ñ‹Ð¼ Журналом. Вам будет раÑÑказано, где раÑположены наиболее важные разделы, а также дана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ функциÑÑ… и возможноÑÑ‚ÑÑ…, которые могут вам пригодитьÑÑ. + +/doc/tour/index.bml.intro.title=Добро пожаловать! + +/doc/tour/index.bml.modify.caption=Оформить ваш журнал вы можете разными ÑпоÑобами, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ñтроенную ÑиÑтему Ñтилей и заранее определенные цветовые Ñхемы. Сделайте ваш журнал уникальным! + +/doc/tour/index.bml.modify.title=ПерÑÐ¾Ð½Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ + +/doc/tour/index.bml.nav.next=Далее --> + +/doc/tour/index.bml.nav.prev=<-- ВернутьÑÑ + +/doc/tour/index.bml.profile.caption=Ðами приветÑтвуетÑÑ Ð¿Ñ€Ð°ÐºÑ‚Ð¸ÐºÐ° Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñми Живого Журнала Ñтранички Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ о Ñебе: Ñто даёт нам предÑтавление о нашей аудитории, на базе которого мы развиваем и улучшаем ÑервиÑ. Тем не менее, Ñта практика не ÑвлÑетÑÑ Ð¾Ð±Ñзательной -- Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы иÑпользовать Живой Журнал, от Ð²Ð°Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ Ð»Ð¸ÑˆÑŒ Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, e-mail и пароль. + +/doc/tour/index.bml.profile.title=ПерÑÐ¾Ð½Ð°Ð»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/doc/tour/index.bml.sitemap.caption=Мы надеемÑÑ, что Ñтот путеводитель помог вам в знакомÑтве Ñ ÑервиÑами Живого Журнала. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации обо вÑем, что каÑаетÑÑ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала, вы в любой момент можете обратитьÑÑ Ðº Ñтраницам Ñлужбы техничеÑкой поддержки. ЕÑли вы захотите иÑÑледовать Живой Журнал более подробно -- обратите внимание на карту Ñайта. + +/doc/tour/index.bml.sitemap.title=Карта Ñайта + +/doc/tour/index.bml.support.caption=Ðа Ñтраницах Ñлужбы поддержки вы найдете ответы на чаÑто задаваемые вопроÑÑ‹ о Живом Журнале и множеÑтво другой полезной информации о ÑервиÑе, компании и ÑообщеÑтве в целом. + +/doc/tour/index.bml.support.title=Помощь + +/doc/tour/index.bml.title=Ознакомление - [[title]] + +/doc/tour/index.bml.update.caption=Добавление новых запиÑей -- Ñто Ñуть предоÑтавлÑемого Живым Журналом ÑервиÑа. ЗдеÑÑŒ наши пользователи могут поделитьÑÑ ÑобытиÑми Ñвоей жизни, раÑÑказать о том, что их волнует. Добавить новую запиÑÑŒ очень проÑто: доÑтаточно впиÑать текÑÑ‚ в окошко на Ñтранице и нажать кнопку "Добавить запиÑÑŒ". Конечно, мы предлагаем и раÑширенные возможноÑти, такие как: возможноÑÑ‚ÑŒ проверки правопиÑаниÑ; возможноÑÑ‚ÑŒ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ информации к Ñвоим запиÑÑм, например, какую музыку вы Ñлушаете или какое у Ð²Ð°Ñ Ð½Ð°Ñтроение в данный момент. + +/doc/tour/index.bml.update.title=Добавление новых запиÑей + +/editinfo.bml.advanced.about=ЕÑли вы не знаете, что Ñто такое, не обращайте вниманиÑ. + +/editinfo.bml.advanced.title=Дополнительные наÑтройки + +/editinfo.bml.allowshowcontact.about=Эту наÑтройку лучше оÑтавить включённой. Ð’ Ñтом Ñлучае другие пользователи Ñмогут ÑвÑзатьÑÑ Ñ Ð²Ð°Ð¼Ð¸, узнав Ð°Ð´Ñ€ÐµÑ e-mail, номер ICQ или Ð¸Ð¼Ñ AOL Instant Messenger в вашем Живом Журнале. + +/editinfo.bml.allowshowcontact.email=Отображение e-mail адреÑа: + +/editinfo.bml.allowshowcontact.email.actual_only=Только дейÑтвительный e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.both=Оба (дейÑтвительный и [[domain]]) + +/editinfo.bml.allowshowcontact.email.lj_only=Только e-mail Ð°Ð´Ñ€ÐµÑ Ð² Живом Журнале + +/editinfo.bml.allowshowcontact.email.neither=Ðе показывать никакой e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.no_show=Ðе показывать e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.show=Показывать e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.allowshowcontact.email.withdomainaddr=Ð’Ñ‹ можете никому не показывать ваш Ð°Ð´Ñ€ÐµÑ e-mail (при Ñтом вÑÑ Ð¾ÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ выводитьÑÑ). Также можно выводить только адреÑ, предоÑтавленный Живым Журналом (доÑтупно только платным пользователÑм), наÑтоÑщий адреÑ, либо показывать и тот, и другой одновременно. + +/editinfo.bml.allowshowcontact.email.withoutdomainaddr=Ð’Ñ‹ можете никому не показывать ваш Ð°Ð´Ñ€ÐµÑ e-mail (при Ñтом вÑÑ Ð¾ÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ выводитьÑÑ). + +/editinfo.bml.allowshowcontact.title=Показывать контактную информацию в вашем Живом Журнале? + +/editinfo.bml.allowshowinfo.about=ПоÑтавьте флаг, еÑли хотите, чтобы другие пользователи могли видеть, где вы живёте (город, регион, Ñтрану) и когда вы родилиÑÑŒ. + +/editinfo.bml.allowshowinfo.title=Показывать меÑто жительÑтва и день рождениÑ? + +/editinfo.bml.autotranslate.about<< +ИÑпользуйте Ñту наÑтройку, чтобы указать Живому Журналу, в какой кодировке были Ñделаны ваши запиÑи и комментарии до перехода Ñайта на Юникод. +ЕÑли вы пишете по-руÑÑки, ваша прежнÑÑ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ°, Ñкорее вÑего, "Cyrillic (Windows)" (возможно, "Cyrillic (KOI8)"). +. + +/editinfo.bml.autotranslate.header=ÐвтоматичеÑки перекодировать Ñтарые запиÑи из кодировки: + +/editinfo.bml.bday.title=День Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +/editinfo.bml.bday.year.opt=год — необÑзательно + +/editinfo.bml.bdayreminders.about=ЕÑли вы хотите получать Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ днÑÑ… Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ñ… друзей по Живому Журналу, отметьте Ñтот пункт. + +/editinfo.bml.bdayreminders.header=ПриÑылать Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ днÑÑ… Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ (отключено) + +/editinfo.bml.bio.about=ЗдеÑÑŒ вы можете ввеÑти Ñвою мини-биографию. Она будет показана на вашей Ñтраничке "О пользователе". + +/editinfo.bml.bio.header=О Ð²Ð°Ñ + +/editinfo.bml.blockrobots.about<< +ЕÑли вы поÑтавите здеÑÑŒ галочку, поиÑковым роботам будет дано указание не индекÑировать Ñодержимое вашего журнала. +Ðо учтите, что не вÑе роботы подчинÑÑŽÑ‚ÑÑ Ñтим правилам. +. + +/editinfo.bml.blockrobots.header=Запретить поиÑковыми ÑиÑтемам индекÑирование моего журнала + +/editinfo.bml.chat.msnusername.title=Ð˜Ð¼Ñ Ð² MSN + +/editinfo.bml.city.title=Город + +/editinfo.bml.country.choose=Выберите Ñтрану + +/editinfo.bml.country.title=Страна + +/editinfo.bml.donotlog=Ðет + +/editinfo.bml.email.title=E-mail + +/editinfo.bml.enableboards.about=ПоÑтавьте галочку, еÑли хотите, чтобы люди могли оÑтавлÑÑ‚ÑŒ комментарии к вашим запиÑÑм. + +/editinfo.bml.enableboards.header=Включить комментарии + +/editinfo.bml.encoding.about=Эти наÑтройки Ñтоит менÑÑ‚ÑŒ только в том Ñлучае, еÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ какие-то проблемы Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ°Ð¼Ð¸, Ñ Ð¿Ñ€Ð¾Ñ‡Ñ‚ÐµÐ½Ð¸ÐµÐ¼ Ñтарых журнальных запиÑей или пиÑем, приÑылаемых Живым Журналом. + +/editinfo.bml.encoding.header=ÐаÑтройка кодировок + +/editinfo.bml.error.day.notinmonth=Ðеправильный день Ð´Ð»Ñ Ñтого меÑÑца + +/editinfo.bml.error.day.outofrange=Ðеправильный день. Введите чиÑло от 1 до 31. + +/editinfo.bml.error.email.lj_domain<< +E-mail Ð°Ð´Ñ€ÐµÑ @[[domain]] вводить запрещено. +Ð’Ñ‹ должны ввеÑти в Ñтой Ñтроке Ñвой наÑтоÑщий адреÑ. +ЕÑли вы платный пользователь, пиÑьма по адреÑу [[user]]@[[domain]] будут перенаправлÑÑ‚ÑŒÑÑ Ð½Ð° ваш наÑтоÑщий адреÑ. +Ð’ наÑтройке "Показывать контактную информацию" также можно указать, какой (какие) e-mail адреÑ(а) вы хотите Ñделать видимым(и) другим пользователÑм. +. + +/editinfo.bml.error.email.none=Ð’Ñ‹ должны указать Ñвой Ð°Ð´Ñ€ÐµÑ e-mail + +/editinfo.bml.error.email.no_space<< +Ð’ e-mail адреÑах пробелы запрещены. +ЕÑли вы пользователь AOL, учтите, что ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð² интернете -- Ñто ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² AOL без пробелов, за которым Ñледует @aol.com +. + +/editinfo.bml.error.excessive_int<< +Извините, вы указали Ñлишком много интереÑов. Их может быть не больше 150, а у Ð²Ð°Ñ — [[intcount]]. +Ð’Ñе изменениÑ, Ñделанные в интереÑах, Ñохранены не будут. ВернитеÑÑŒ и Ñократите ÑпиÑок, поÑле чего попробуйте Ñохранить ещё раз. +. + +/editinfo.bml.error.invalidbio=ТекÑÑ‚ вашей биографии Ñодержит неправильные Ñимволы. ПоÑетите Ñтраницу перекодировки, чтобы Ñконвертировать его в Юникод. + +/editinfo.bml.error.invalidints=СпиÑок ваших интереÑов Ñодержит неправильные Ñимволы. ПоÑетите Ñтраницу перекодировки, чтобы Ñконвертировать его в Юникод. + +/editinfo.bml.error.invalidname=Ваше Ð¸Ð¼Ñ Ñодержит неправильные Ñимволы. ПоÑетите Ñтраницу перекодировки, чтобы Ñконвертировать его в Юникод. + +/editinfo.bml.error.locale.country_ne_state=Ð’Ñ‹ указали СШР(United States) в качеÑтве вашей Ñтраны, но ввели штат в поле "другой штат", а не из ÑпиÑка штатов СШÐ. + +/editinfo.bml.error.locale.invalid_country=Каким-то образом вы выбрали неÑущеÑтвующую Ñтрану. + +/editinfo.bml.error.locale.state_ne_country=Ð’Ñ‹ указали Ñтрану, отличную от СШÐ, но выбрали штат из ÑпиÑка штатов СШÐ. + +/editinfo.bml.error.locale.zip_ne_state<< +Почтовый Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ ÑоответÑтвует выбранному штату. +ИÑправьте информацию или Ñотрите одно из полей штата и почтового индекÑа, или оба Ñтих полÑ. +. + +/editinfo.bml.error.locale.zip_requires_us<< +Ð’Ñ‹ ввели почтовый индекÑ, но вы не выбрали СШРв качеÑтве Ñвоей Ñтраны. +Мы храним только почтовые индекÑÑ‹ людей, проживающих в СШÐ. +ПожалуйÑта, вернитеÑÑŒ и либо Ñотрите почтовый индекÑ, либо выберите СШРв качеÑтве Ñвоей Ñтраны. +. + +/editinfo.bml.error.month.outofrange=Ðеправильный меÑÑц. Введите чиÑло от 1 до 12. + +/editinfo.bml.error.noname=Ваше Ð¸Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ð¾ быть указано. Укажите по меньшей мере проÑто Ð¸Ð¼Ñ Ð¸Ð»Ð¸ пÑевдоним. + +/editinfo.bml.error.tm.require.number=ЕÑли вы хотите пользоватьÑÑ ÑƒÑлугой текÑтовых Ñообщений, вы должны ввеÑти Ñвой номер телефона. + +/editinfo.bml.error.tm.require_provider<< +ЕÑли вы хотите пользоватьÑÑ ÑƒÑлугой текÑтовых Ñообщений, вы должны указать Ñвоего поÑтавщика уÑлуг. +ЕÑли ваш поÑтавщик не указан, пожалуйÑта, Ñообщите нам, как наÑтроить Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ уÑлугу текÑтовых Ñообщений, чтобы мы могли добавить его в наш ÑпиÑок. +. + +/editinfo.bml.error.year.notenoughdigits=Ðеправильный год. Введите четыре цифры. + +/editinfo.bml.error.year.outofrange=Ðеправильный год. + +/editinfo.bml.finished.about=Когда закончите, нажмите кнопку "Сохранить изменениÑ" ниже: + +/editinfo.bml.finished.header=Готово? + +/editinfo.bml.finished.save_button=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/editinfo.bml.foafurl.about=Ð’Ñ‹ точно хотите удалить Ñти наÑтройки? + +/editinfo.bml.foafurl.title=Внешний интернет-Ð°Ð´Ñ€ÐµÑ FOAF + +/editinfo.bml.gender.title=Пол + +/editinfo.bml.getreplies.about=ПоÑтавьте флаг, еÑли хотите получать по почте ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾Ð± ответах на ваши запиÑи или комментарии. + +/editinfo.bml.getreplies.header=Получать комментарии по почте + +/editinfo.bml.getselfemails.about=ПоÑтавьте галочку, еÑли вы хотите получать e-mail поÑле каждого вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð² журналах пользователей или ÑообщеÑтв. Ваши анонимные комментарии ÑопровождатÑÑ e-mail не будут. + +/editinfo.bml.getselfemails.header=Получать Ñвои ÑобÑтвенные комментарии по e-mail + +/editinfo.bml.hidefriendof.about=ЕÑли вы уÑтановите Ñтот флаг, ÑпиÑок людей, добавивших Ð²Ð°Ñ Ð² друзьÑ, не будет выводитьÑÑ Ð½Ð° вашей Ñтранице "О пользователе". + +/editinfo.bml.hidefriendof.header=СпрÑтать ÑпиÑок "Ð’ друзьÑÑ… у" + +/editinfo.bml.howhear.about<< +Cкажите, пожалуйÑта, откуда вы узнали о [[sitename]]. +ЕÑли вам о нем Ñообщил пользователь, введите его имÑ, еÑли вы получили информацию из другого иÑточника (газеты, веб-Ñайта и Ñ‚.п.), введите ÑоответÑтвующие названиÑ. +. + +/editinfo.bml.howhear.header=Любопытно + +/editinfo.bml.htmlemail.about=EÑли ваша Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° корректно показывает пиÑьма в формате HTML, можете поÑтавить Ñту галочку. Ðекоторые почтовые программы отображают такие пиÑьма в плохо читаемом виде, и, еÑли вы уберёте галочку, Живой Журнал будет поÑылать вам проÑтые текÑтовые ÑообщениÑ. + +/editinfo.bml.htmlemail.header=ПоÑылать пиÑьма в формате HTML + +/editinfo.bml.imagelinks.about=Заменители картинок полезны, еÑли вы находитеÑÑŒ в ЖЖ на рабочем меÑте или у Ð²Ð°Ñ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾Ðµ Ñоединение; они замeнÑÑŽÑ‚ картинки их адреÑами. Картинки какого размерa вы бы хотели бы замеÑтить заменителÑми? + +/editinfo.bml.imagelinks.header=ИÑпользовать заменители картинок на Ñтранице друзей + +/editinfo.bml.imagelinks.size.all=ИÑпользовать заменители картинок вмеÑто любых картинок + +/editinfo.bml.imagelinks.size.custom=Выбрать: иÑпользовать заменители картинок вмеÑто картинок больше [[width]]x[[height]] + +/editinfo.bml.imagelinks.size.medium=ИÑпользовать заменители картинок вмеÑто больших картинок (больше [[width]]x[[height]]) + +/editinfo.bml.imagelinks.size.small=ИÑпользовать заменители картинок вмеÑто картинок Ñреднего размера (больше [[width]]x[[height]]) + +/editinfo.bml.int.about<< +ЕÑли хотите, чтобы другие люди могли найти Ð²Ð°Ñ Ð² каталоге по вашим интереÑам, перечиÑлите ниже вÑÑ‘, чем вы интереÑуетеÑÑŒ, разделÑÑ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑÑ‹ запÑтыми. +Лучше вÑего иÑпользовать короткие Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð² одно Ñлово. ПроÑтое правило: ваш Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ впиÑыватьÑÑ Ð² предложение "Мне нравитÑÑ/нравÑÑ‚ÑÑ __________". Ð”Ð»Ñ ÑущеÑтвительных иÑпользуйте множеÑтвенное чиÑло, именительный падеж ("женщины", а не "женщина" или "женщин") (кроме Ñлучаев, когда множеÑтвенное чиÑло не употреблÑетÑÑ), Ð´Ð»Ñ Ð³Ð»Ð°Ð³Ð¾Ð»Ð¾Ð² — неопределённую форму ("танцевать"). +. + +/editinfo.bml.int.ex.bad=ПЛОХОЙ пример: Я люблю Ñлушать разные группы, Ñмотреть кино, ходить по клубам и болтать Ñ Ð´Ñ€ÑƒÐ·ÑŒÑми Такой текÑÑ‚ лучше напиÑать в вашей биографии (Ñм. выше). + +/editinfo.bml.int.ex.good=ХОРОШИЙ пример: музыка, женщины, ÑекÑ, компьютеры, кошки, пÑÐ¸Ñ…Ð¾Ð»Ð¾Ð³Ð¸Ñ + +/editinfo.bml.int.header=ИнтереÑÑ‹ + +/editinfo.bml.login.enterinfo=Чтобы изменить личную информацию, введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. + +/editinfo.bml.login.forgot.header=Что-то забыли? + +/editinfo.bml.login.forgot.recover=ЕÑли вы забыли Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, можете воÑÑтановить их здеÑÑŒ. + +/editinfo.bml.logip.always=Ð’Ñегда + +/editinfo.bml.logip.anon_only=Только анонимных пользователей + +/editinfo.bml.logip.header=ЗапиÑывать IP-адреÑа отвечающих людей? + +/editinfo.bml.mangleaddress.about=ЕÑли вы опаÑаетеÑÑŒ, что ÑпаммерÑкие программы могут найти ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð² Живом Журнале, отметьте Ñтот флаг, и тогда ваш Ð°Ð´Ñ€ÐµÑ Ð±ÑƒÐ´ÐµÑ‚ изменён так, чтобы роботы, Ñобирающие адреÑа, не могли его обнаружить. + +/editinfo.bml.mangleaddress.header=ИÑказить показываемый e-mail Ð°Ð´Ñ€ÐµÑ + +/editinfo.bml.mutualfriends.about=Эта наÑтройка добавит новый ÑпиÑок к вашей Ñтранице "О пользователе": взаимные друзьÑ. Ð’ Ñто ÑпиÑке будут перечиÑлены те, кто занеÑен в ваш ÑпиÑок друзей и одновременно включил Ð²Ð°Ñ Ð² их ÑпиÑок друзей. + +/editinfo.bml.mutualfriends.header=Показать взaимных друзей на Ñтранице "О пользователе" + +/editinfo.bml.name.title=Ð˜Ð¼Ñ + +/editinfo.bml.newemail.body2<< +Ð’Ñ‹ только что изменили Ð°Ð´Ñ€ÐµÑ Ð²Ð°ÑˆÐµÐ³Ð¾ [[sitename]] аккаунта "[[username]]". Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ, пожалуйÑта, поÑетите Ñту Ñтраницу: + +[[conflink]] + +С наилучшими пожеланиÑми, +Команда [[sitename]] +[[sitelink]] + +. + +/editinfo.bml.newemail.subject=ÐÐ´Ñ€ÐµÑ e-mail изменен. + +/editinfo.bml.numcomments.about=Отметьте Ñтот флаг, еÑли хотите, чтобы к URL-адреÑам добавлÑлоÑÑŒ чиÑло оÑтавленных комментариев. Ð’ Ñтом Ñлучае, еÑли чиÑло комментариев изменилоÑÑŒ Ñ Ñ‚ÐµÑ… пор, как вы поÑледний раз заходили на Ñтраницу, браузер, возможно, покажет ÑÑылку другим цветом. + +/editinfo.bml.numcomments.header=ДобавлÑÑ‚ÑŒ &nc=xx к URL-адреÑам Ñтраниц Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñми + +/editinfo.bml.optional=необÑзательно + +/editinfo.bml.opt_in.about<< +Отметьте Ñтот флаг, еÑли хотите вÑегда узнавать о поÑвлении в Живом Журнале новых интереÑных возможноÑтей. +Эти пиÑьма будут приходить довольно редко, врÑд ли чаще одного-двух раз в меÑÑц. Ваш Ð°Ð´Ñ€ÐµÑ Ð½Ðµ будет виден другим пользователÑм, и вы вÑегда можете отключить Ñту возможноÑÑ‚ÑŒ. +. + +/editinfo.bml.opt_in.header=ПриÑылать мне новоÑти Живого Журнала + +/editinfo.bml.persinfo.disclaimer<< +Будьте добры, заполните небольшую анкету о Ñебе Ð´Ð»Ñ Ñбора ÑтатиÑтики. +Мы не ÑобираемÑÑ Ð¸Ñпользовать полученную информацию Ñ ÐºÐ°ÐºÐ¸Ð¼Ð¸-либо Ñомнительными целÑми, мы проÑто хотим знать, кто наши пользователи и откуда они. ПоÑтому, пожалуйÑта, не указывайте ложную информацию. ЕÑли вы ÑомневаетеÑÑŒ, прочтите наше положение о конфиденциальноÑти. +. + +/editinfo.bml.persinfo.header=Ð›Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/editinfo.bml.screen.all=Ð’Ñе + +/editinfo.bml.screen.anon=Ðнонимные + +/editinfo.bml.screen.header=Чьи ответы вы хотите Ñкрывать Ñразу? + +/editinfo.bml.screen.none=Ðичьи + +/editinfo.bml.screen.nonfriends=ÐапиÑанные не друзьÑми + +/editinfo.bml.screen.nonmembers=ÐапиÑанные не членами ÑообщеÑтва + +/editinfo.bml.security.header=Кто может видеть: + +/editinfo.bml.security.visibility.anybody=Ð’Ñе + +/editinfo.bml.security.visibility.everybody=Ð’Ñе + +/editinfo.bml.security.visibility.friends=Только Ð´Ñ€ÑƒÐ·ÑŒÑ + +/editinfo.bml.security.visibility.regusers=Только зарегиÑтрированные пользователи + +/editinfo.bml.settings.friendspage.title=Заголовок ленты друзей: + +/editinfo.bml.settings.friendspage.title.optional=ЕÑли хотите, введите заголовок Ð´Ð»Ñ Ñтраниц Ñвоей ленты друзей (без HTML) + +/editinfo.bml.settings.header=ÐаÑтройки Живого Журнала + +/editinfo.bml.settings.journal.subtitle=Подзаголовок журнала: + +/editinfo.bml.settings.journal.subtitle.optional=ЕÑли хотите, введите заголовок и подзаголовок Ñвоего журнала (без HTML) + +/editinfo.bml.settings.journal.title=Заголовок журнала: + +/editinfo.bml.settings.privacy.about=Далее Ñледуют наÑтройки и предпочтениÑ, Ñлужащие обеÑпечению вашей уединённоÑти и анонимноÑти. + +/editinfo.bml.settings.privacy.header=ÐаÑтройки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð´Ð¾Ñтупа + +/editinfo.bml.state.other=Или введите штат/провинцию/облаÑÑ‚ÑŒ другого гоÑударÑтва + +/editinfo.bml.state.title=Штат + +/editinfo.bml.state.us=Штаты СШР+ +/editinfo.bml.stylemine.about=ПоÑтавьте галочку, чтобы видеть Ñтраницы комментариев в Ñтиле вашего журнала при переходе по ÑÑылкам Ñ Ð²Ð°ÑˆÐµÐ¹ ленты друзей. + +/editinfo.bml.stylemine.header=Форматировать комментарии в Ñтиле вашего журнала? + +/editinfo.bml.success.header=УÑпешно + +/editinfo.bml.success.message=Ваша Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, наÑтройки журнала и Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±Ñ‹Ð»Ð¸ уÑпешно изменены. + +/editinfo.bml.switch.button=Выбрать + +/editinfo.bml.switch.header=Выбрать другой журнал + +/editinfo.bml.switch.workwith=С каким журналом работать: + +/editinfo.bml.title=Изменение личных наÑтроек + +/editinfo.bml.tm.details=подробнее + +/editinfo.bml.tm.phonenum=Полный номер телефона: + +/editinfo.bml.tm.sec.about=Разрешить другим пользователÑм отправление текÑтовых Ñообщений. + +/editinfo.bml.tm.sec.title=Кто может отправлÑÑ‚ÑŒ: + +/editinfo.bml.tm.servprov=ПоÑтавщик уÑлуг: + +/editinfo.bml.tm.title=ТекÑтовые ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ + +/editinfo.bml.translatemailto.about=ЕÑли вы хотите получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ комментариÑÑ… на ваш e-mail, но ваш почтовый клиент не поддерживает или плохо поддерживает Юникод (UTF-8), укажите здеÑÑŒ другую кодировку, и Живой Журнал будет автоматичеÑки перекодировать текÑÑ‚ комментариев перед отправлением пиÑем. + +/editinfo.bml.translatemailto.header=Перекодировать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ Ñлектронной почте в: + +/editinfo.bml.unbanusers.about=Ð’Ñ‹ запретили комментировать ваши запиÑи нижеприведенным пользователÑм (заблокировали их). ПоÑтавьте флаги напротив имён тех пользователей, которых вы хотите разблокировать. + +/editinfo.bml.unbanusers.header=Разблокировать пользователей + +/editinfo.bml.userpic.about=Ðиже показана Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð°Ñ Ð²Ð°Ð¼Ð¸ картинка, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð²Ñюду на Ñайте Ñтоит Ñ€Ñдом Ñ Ð²Ð°ÑˆÐ¸Ð¼ именем: в вашем ÑобÑтвенном Живом Журнале и в журналах ваших друзей. + +/editinfo.bml.userpic.edit=Удалить Ñту картинку или загрузить новую можно здеÑÑŒ. + +/editinfo.bml.userpic.header=Ваша картинка + +/editinfo.bml.userpic.none=картинка не загружена + +/editinfo.bml.weblogscom.about=Включите, еÑли хотите, чтобы Ñайт Weblogs.com вноÑил ваш журнал в ÑпиÑок обновлений при добавлении новых общедоÑтупных запиÑей. + +/editinfo.bml.weblogscom.header=УведомлÑÑ‚ÑŒ Weblogs.com об изменениÑÑ… + +/editinfo.bml.webpagename.title=Ðазвание веб-Ñтраницы + +/editinfo.bml.webpageurl.title=ÐÐ´Ñ€ÐµÑ Ð²ÐµÐ±-Ñтраницы + +/editinfo.bml.whoreply.header=Кто может отвечать на ваши запиÑи? + +/editinfo.bml.zip.title=Почтовый Ð¸Ð½Ð´ÐµÐºÑ + +/editinfo.bml.zip.usonly=Ð¸Ð½Ð´ÐµÐºÑ Ð¸Ð· 5-ти цифр; только Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð¶Ð¸Ð²Ð°ÑŽÑ‰Ð¸Ñ… в СШР+ +/editjournal.bml.btn.proceed=Продолжить... + +/editjournal.bml.certainday=За определённый день: + +/editjournal.bml.desc=ПожалуйÑта, иÑпользуйте форму внизу Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° запиÑи, которую вы хотите редактировать. + +/editjournal.bml.in=Ð’ ÑообщеÑтве + +/editjournal.bml.recententries=Ñамые новые запиÑи + +/editjournal.bml.recententry=Ð¡Ð°Ð¼Ð°Ñ Ð½Ð¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ + +/editjournal.bml.title=Редактировать запиÑи + +/editjournal.bml.viewwhat=Какие запиÑи: + +/editjournal_do.bml.body=Отредактируйте то, что хотите, поÑле чего нажмите на кнопку "Сохранить" внизу Ñтраницы, или нажмите на кнопку "Удалить", чтобы удалить запиÑÑŒ. + +/editjournal_do.bml.btn.delete=Удалить запиÑÑŒ из журнала + +/editjournal_do.bml.btn.edit=Редактировать выбранную запиÑÑŒ + +/editjournal_do.bml.btn.preview=Предварительный проÑмотр запиÑи + +/editjournal_do.bml.btn.save=Сохранить запиÑÑŒ + +/editjournal_do.bml.continue.head=Ðажмите Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶ÐµÐ½Ð¸Ñ... + +/editjournal_do.bml.continue.text=ПоÑле того, как вы выберете запиÑÑŒ Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ удалениÑ, нажмите кнопку "Редактировать выбранную запиÑÑŒ". + +/editjournal_do.bml.currmood=ÐаÑтроение: + +/editjournal_do.bml.currmusic=Музыка: + +/editjournal_do.bml.date=Дата + +/editjournal_do.bml.default=по умолчанию + +/editjournal_do.bml.delete.confirm=Ð’Ñ‹ дейÑтвительно хотите удалить Ñту запиÑÑŒ? + +/editjournal_do.bml.edit.text=Перед вами запиÑÑŒ, которую вы выбрали Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. Отредактируйте запиÑÑŒ по Ñвоему уÑмотрению и нажмите кнопку "Сохранить запиÑÑŒ" внизу Ñтраницы.

            Ð”Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи проÑто удалите веÑÑŒ текÑÑ‚ и нажмите "Сохранить запиÑÑŒ". ЗапиÑÑŒ будет удалена. + +/editjournal_do.bml.error.getting=Ошибка при выборе запиÑей Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ: + +/editjournal_do.bml.error.modify=Ошибка при редактировании журнала: + +/editjournal_do.bml.error.nofind=Ðевозможно найти выбранную запиÑÑŒ в журнале. + +/editjournal_do.bml.event=Событие: + +/editjournal_do.bml.localtime=МеÑтное времÑ: + +/editjournal_do.bml.noneother=Ðи одно из Ñтих, или другое: + +/editjournal_do.bml.opt.backdate=ЗапиÑÑŒ задним чиÑлом: + +/editjournal_do.bml.opt.backdate.about=Ðе будет поÑвлÑÑ‚ÑŒÑÑ Ð² лентах друзей + +/editjournal_do.bml.opt.nocomments=Запретить комментировать запиÑÑŒ: + +/editjournal_do.bml.opt.noemail=Ðе отправлÑÑ‚ÑŒ комментарии по e-mail: + +/editjournal_do.bml.opt.noformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/editjournal_do.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/editjournal_do.bml.other=Другое: + +/editjournal_do.bml.pickentry.head=Выберите запиÑÑŒ Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. + +/editjournal_do.bml.pickentry.text=Выберите запиÑÑŒ, которую Ð’Ñ‹ хотите отредактировать и нажмите кнопку "Редактировать выбранную запиÑÑŒ" внизу Ñтраницы. + +/editjournal_do.bml.picture=Ваша картинка: + +/editjournal_do.bml.preview.header=Предварительный проÑмотр запиÑи + +/editjournal_do.bml.preview.text=Это внешний вид вашей будущей запиÑи в журнале. ИÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ„Ð¾Ñ€Ð¼Ñƒ внизу, вы можете редактировать запиÑÑŒ или запиÑать ее в нынешнем виде. + +/editjournal_do.bml.save.head=Ðажмите, чтобы Ñохранить... + +/editjournal_do.bml.save.text=ПоÑле того, как вы закончите редактировать ваши запиÑи, нажмите кнопку "Сохранить". + +/editjournal_do.bml.spellchecked=Ваша Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ: + +/editjournal_do.bml.subject=Тема: (не обÑзательно) + +/editjournal_do.bml.success.delete=ЗапиÑÑŒ в журнале удалена. + +/editjournal_do.bml.success.edit=ЗапиÑÑŒ в журнале отредактирована. Ð’Ñ‹ можете поÑмотреть ее здеÑÑŒ. + +/editjournal_do.bml.success.head=ЗапиÑÑŒ уÑпешно отредактирована. + +/editjournal_do.bml.timeformat=Ð’Ñ€ÐµÐ¼Ñ Ð² 24-чаÑовом формате + +/editjournal_do.bml.title=Редактировать запиÑи журнала + +/editpics.bml.btn.proceed=Продолжить + +/editpics.bml.btn.save=Сохранить наÑтройки + +/editpics.bml.curpics=ИмеющиеÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¸ + +/editpics.bml.curpics.desc=ЗдеÑÑŒ показаны загруженные ранее картинки. Ð’Ñ‹ можете указать, какую из них иÑпользовать по умолчанию, удалить ненужные или назначить картинкам ключевые Ñлова. Чтобы загрузить новую картинку, иÑпользуйте форму внизу Ñтраницы. + +/editpics.bml.error.badurl=ÐÐ´Ñ€ÐµÑ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ указан неправильно. Он должен начинатьÑÑ Ñ http:// + +/editpics.bml.error.filetoolarge=Слишом большой файл изображениÑ. МакÑимальный размер файла -- [[maxsize]]. + +/editpics.bml.error.imagetoolarge=Размер Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ([[imagesize]]) Ñлишком большой, он не может быть больше 100x100 точек. Ð’Ñ‹ можете уменьшить изображение в графичеÑком редакторе. + +/editpics.bml.error.invalidimage=Ðеверный файл изображениÑ. + +/editpics.bml.error.keywords=Ð’Ñ‹ иÑпользовали ключевое Ñлово "[[ekw]]" Ð´Ð»Ñ Ð½ÐµÑкольких картинок Ñразу, и оно было назначено одной картинке, Ñлучайно выбранной из них. ВероÑтно, Ñто не та, которую подразумевали вы, поÑтому можете вернутьÑÑ Ð¸ иÑправить ключевые Ñлова. + +/editpics.bml.error.toomanypics2=МакÑимально разрешённое вам чиÑло картинок ([[maxpics]]) уже загружено. Удалите одну из Ñтарых картинок, чтобы загрузить новую. + +/editpics.bml.error.toomanypics3=У Ð²Ð°Ñ Ñ…Ñ€Ð°Ð½Ð¸Ñ‚ÑÑ Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ðµ вам количеÑтво картинок - [[max]] [[?max|picture|pictures]]. Ð’Ñ‹ не Ñможете загрузить дополнительные картинки, пока не удалите одну или неÑколько из имеющихÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½Ð¾Ðº. + +/editpics.bml.error.unsupportedtype=Файлы типа [[filetype]] не поддерживаютÑÑ. Ð’Ñ‹ можете загрузить файлы только Ñледующих типов: GIF, PNG или JPG. Преобразовать файл в одним из Ñтих типов можно практичеÑки в любом графичеÑком редакторе. + +/editpics.bml.error.urlerror=При загрузке Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка. + +/editpics.bml.fromfile=Из файла + +/editpics.bml.fromfile.key|notes=Enter here a lower-case version of the letter you underlined in ".fromfile". This is the shortcut key for the fromfile option. +/editpics.bml.fromfile.key=Ñ„ + +/editpics.bml.fromurl=Из Сети: + +/editpics.bml.fromurl.key|notes=Enter here a lower-case version of the letter you underlined in ".fromurl". This is the shortcut key for the fromurl option. +/editpics.bml.fromurl.key=Ñ + +/editpics.bml.kilobytes= килобайт + +/editpics.bml.label.default=По умолчанию: + +/editpics.bml.label.delete=Удалить: + +/editpics.bml.label.keywords=Ключевые Ñлова: + +/editpics.bml.makedefault=Сделать картинкой по умолчанию + +/editpics.bml.makedefault.key|notes=Enter here a lower-case version of the letter you underlined in ".makedefault". This is the shortcut key for the makedefault option. +/editpics.bml.makedefault.key=у + +/editpics.bml.nodefault=Ðе назначать картинку по умолчанию + +/editpics.bml.noneupload=Ð’Ñ‹ не загрузили ни одной картинки. Ð’Ñ‹ можете загрузить их Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ приведённой ниже формы. + +/editpics.bml.nopics=Картинок нет + +/editpics.bml.piclimitstatus=У Ð²Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ¶ÐµÐ½Ð¾ из положенных + +/editpics.bml.restriction.fileformat=Файл должен быть формата PNG, GIF или JPG + +/editpics.bml.restriction.filesize=Размер файла должен быть меньше 40 килобайт + +/editpics.bml.restriction.imagesize=Размеры Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ быть не более 100x100 точек + +/editpics.bml.title=Редактировать картинки + +/editpics.bml.uploaddesc=ИÑпользуйте форму внизу Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ новой картинки + +/editpics.bml.uploadheader=Загрузить новую картинку + +/export.bml.btn.proceed=Продолжить... + +/export.bml.description=ЗдеÑÑŒ вы можете Ñохранить резервную копию Ñвоего журнала в выбранном формате. Подробную информацию о резервном копировании Ñвоего журнала, читайте в Справке. + +/export.bml.fields=ПолÑ: + +/export.bml.format.csv=CSV (Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· запÑтую) + +/export.bml.label.encoding=Кодировка: + +/export.bml.label.field.allowmask=МаÑка прав доÑтупа + +/export.bml.label.field.currents=ÐаÑтроение и музыка + +/export.bml.label.field.event=Событие + +/export.bml.label.field.eventtime=Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи (по чаÑам пользователÑ) + +/export.bml.label.field.itemid=Ðомер ID + +/export.bml.label.field.logtime=Ð’Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ³Ð¸Ñтрации (по чаÑам ÑиÑтемы) + +/export.bml.label.field.security=Уровень безопаÑноÑти + +/export.bml.label.field.subject=Тема + +/export.bml.label.format=Форматирование: + +/export.bml.label.header=Заголовок + +/export.bml.label.month=МеÑÑц: + +/export.bml.label.month.month=мм: + +/export.bml.label.month.year=гггг: + +/export.bml.label.notranslation=Ðе изменÑÑ‚ÑŒ кодировку + +/export.bml.label.what=Что ÑкÑпортировать: + +/export.bml.title=ЭкÑпортировать веÑÑŒ журнал + +/export.bml.what.entries=ЗапиÑи в дневнике + +/export_do.bml.error.encoding= Выбрана Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ° + +/friends/add.bml.add.header=УÑпешно + +/friends/add.bml.add.text=Пользователь [[user]] был добавлен в ваш ÑпиÑок друзей. Свою ленту друзей вы можете поÑмотреть здеÑÑŒ. + +/friends/add.bml.add.title=Добавление в ÑпиÑок друзей + +/friends/add.bml.btn.add=Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] + +/friends/add.bml.btn.modify=Изменить + +/friends/add.bml.btn.remove=Удалить + +/friends/add.bml.colors.bg=Цвет фона + +/friends/add.bml.colors.fg=Цвет букв + +/friends/add.bml.colors.header=Цвета + +/friends/add.bml.colors.hover=(Подведите курÑор к цвету, чтобы увидеть его название во вÑплывающей подÑказке) + +/friends/add.bml.colors.text=Ð’Ñ‹ можете также выбрать цвета, которыми пользователь [[user]] будет предÑтавлен в вашей ленте друзей. + +/friends/add.bml.confirm.header=Добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок друзей? + +/friends/add.bml.confirm.syn.header=Добавить транÑлируемую ленту [[user]] в ÑпиÑок друзей? + +/friends/add.bml.confirm.syn.title=Добавить транÑлируемую ленту + +/friends/add.bml.confirm.text=Чтобы добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] в ÑпиÑок друзей, нажмите кнопку: + +/friends/add.bml.confirm.title=Добавить друга + +/friends/add.bml.error1.header=Сперва войдите в ÑиÑтему + +/friends/add.bml.error1.text=Прежде чем добавить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² Ñвой ÑпиÑок друзей, вы должны войти в Живой Журнал под Ñвоим именем Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ паролем. ЕÑли у Ð²Ð°Ñ ÐµÑ‰Ñ‘ нет журнала, то вы можете Ñоздать его, чтобы читать чужие запиÑи в Ñвоей ленте друзей. + +/friends/add.bml.error1.title=Добавление друга + +/friends/add.bml.error2.text=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¾Ñ‚ÑутÑтвует или было введено неправильно. Добавить друга вы можете на Ñтранице Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑпиÑка друзей. + +/friends/add.bml.error3.text=Пользователь [[user]] уже добавлен в ваш ÑпиÑок друзей. Ðо вы можете изменить цвета, которыми отображаетÑÑ ÐµÐ³Ð¾ Ð¸Ð¼Ñ Ð² вашей ленте друзей (а также ÑпиÑок групп, в которые он входит). + +/friends/add.bml.error3.title=ВнеÑти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/add.bml.groups.header=Группы друзей + +/friends/add.bml.groups.nogroup=Группы друзей не заданы. + +/friends/add.bml.groups.text=Ð’ какие группы друзей вы хотите добавить Ñтого пользователÑ? Группы друзей иÑпользуютÑÑ Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ Ñообщений в ленте друзей, а также Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ выÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð°Ð² проÑмотра журнальных запиÑей. + +/friends/add.bml.remove.header=УÑпешно + +/friends/add.bml.remove.text=Пользователь был удалён из ÑпиÑка ваших друзей. Свою ленту друзей вы можете поÑмотреть здеÑÑŒ. + +/friends/add.bml.remove.title=Удаление из ÑпиÑка друзей + +/friends/edit.bml.title=Редактировать ÑпиÑок друзей + +/friends/editgroups.bml.btn.ge.del=Удалить + +/friends/editgroups.bml.btn.ge.new=Создать + +/friends/editgroups.bml.btn.ge.ren=Переименовать + +/friends/editgroups.bml.btn.gs.private=ÐŸÑ€Ð¸Ð²Ð°Ñ‚Ð½Ð°Ñ + +/friends/editgroups.bml.btn.gs.public=ОбщедоÑÑ‚ÑƒÐ¿Ð½Ð°Ñ + +/friends/editgroups.bml.btn.mv.down=Подвинуть вниз + +/friends/editgroups.bml.btn.mv.up=Подвинуть вверх + +/friends/editgroups.bml.confirm.delete=Ð’Ñ‹ уверены, что хотите удалить группу друзей? + +/friends/editgroups.bml.done.btn=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/editgroups.bml.done.header=Готово? + +/friends/editgroups.bml.done.text=Когда вÑе будет готово, Ñохраните изменениÑ, нажав раÑположенную ниже кнопку. + +/friends/editgroups.bml.error.max30|notes=It is important for the JavaScript on this page to work that this string remains a single line without linebreaks. Additionally, it must not contain any quotation marks. +/friends/editgroups.bml.error.max30=Ð’Ñ‹ доÑтигли предельного количеÑтва из 30 групп друзей. ЕÑли вы удалили одну или неÑколько групп, но не Ñохранили изменениÑ, Ñделайте Ñто ÑейчаÑ, вернитеÑÑŒ на Ñту Ñтраницу и перезагрузите её. ПоÑле Ñтого вы Ñможете Ñоздавать новые группы. + +/friends/editgroups.bml.error.text=Сервер вернул Ñообщение об ошибке: + +/friends/editgroups.bml.group.public=(общедоÑтупнаÑ) + +/friends/editgroups.bml.ingroup=ВходÑÑ‚ в группу: + +/friends/editgroups.bml.ingroup.not=Ðе входÑÑ‚ в группу: + +/friends/editgroups.bml.prompt.newname=Ðазвание новой группы: + +/friends/editgroups.bml.prompt.rename=Переименовать Ñту группу в: + +/friends/editgroups.bml.saved.header=Сохранено + +/friends/editgroups.bml.saved.text=Ваши группы друзей уÑпешно Ñохранены. + +/friends/editgroups.bml.text<< +Ðа Ñтой Ñтранице вы можете редактировать группы Ñвоих друзей. Группы друзей предназначены Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа к запиÑÑм, а также Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð¾Ð³Ð¾ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð»ÐµÐ½Ñ‚Ñ‹ друзей. Это подробно опиÑано в вопроÑе "Что такое наÑтраиваемые группы друзей? Как ими пользоватьÑÑ?". + +Ð”Ð»Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð¾Ð¹ работы Ñтой Ñтраницы у Ð²Ð°Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть включен JavaScript. +. + +/friends/editgroups.bml.text.sec=Обратите внимание: ЕÑли вы хотите удалить группу и Ñделать новую, не делайте Ñтого поÑредÑтвом Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ ÑущеÑтвующей и удалениÑ/Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² неё пользователей. ЕÑли вы поÑтупите подобным образом, то вÑе запиÑи, доÑтупные "Ñтарой" группе, будут также доÑтупны и "новой". + +/friends/editgroups.bml.title=Редактирование групп друзей + +/friends/editgroups.bml.yourgroups=Ваши группы друзей: + +/friends/edit_do.bml.addfriends.head=Добавить друзей + +/friends/edit_do.bml.addfriends.text=Введите имена пользователей ваших друзей по Живому Журналу в Ð¿Ð¾Ð»Ñ Ð²Ð²Ð¾Ð´Ð°, раÑположенные ниже, поÑле чего выберите, какие цвета будут аÑÑоциированны Ñ Ð½Ð¸Ð¼Ð¸... + +/friends/edit_do.bml.background=Фон + +/friends/edit_do.bml.bgcolor=Цвет фона: + +/friends/edit_do.bml.btn.close=Закрыть + +/friends/edit_do.bml.btn.save=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/friends/edit_do.bml.btn.toggle=Открыть окно проÑмотра + +/friends/edit_do.bml.done.head=Ð’ÑÑ‘? + +/friends/edit_do.bml.done.text=Когда закончите, нажмите на кнопку "Сохранить изменениÑ", раÑположенную ниже... + +/friends/edit_do.bml.error.updating=Во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑпиÑка друзей произошла ошибка: + +/friends/edit_do.bml.fellowfriends.head=Ð’ друзьÑÑ… + +/friends/edit_do.bml.fellowfriends.text<< +Эти люди занеÑли Ð²Ð°Ñ Ð² Ñвои ÑпиÑки друзей. ЕÑли хотите, вы тоже можете добавить их в Ñвой ÑпиÑок. Ð”Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð° только Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ удобÑтва, чтобы вы тоже знали их имена и вам не обÑзательно добавлÑÑ‚ÑŒ каждого из них. + +. + +/friends/edit_do.bml.foreground=Передний план + +/friends/edit_do.bml.friend=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/friends/edit_do.bml.hover=Ðаведите курÑор мыши на нужный цвет, чтобы узнать его название + +/friends/edit_do.bml.mrcolor=МиÑтер ПроÑмотрщик Цветов + +/friends/edit_do.bml.name=Ð˜Ð¼Ñ + +/friends/edit_do.bml.needmore=ЕÑли здеÑÑŒ не хватает Ñтрочек Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы добавить вÑех друзей, которых вы хотите, проÑто Ñохраните Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ вернитеÑÑŒ на Ñту Ñтраницу Ñнова. + +/friends/edit_do.bml.nofriends.head=Ðет друзей? + +/friends/edit_do.bml.nofriends.text=Увы, у Ð²Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½Ðµ задано ни одного друга. ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° Ñто, мы уверены, что у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ неÑколько друзей :) Введите же имена их журналов здеÑÑŒ... + +/friends/edit_do.bml.opt.addtolist=Добавить в Ð´Ñ€ÑƒÐ·ÑŒÑ + +/friends/edit_do.bml.opt.delete=Удалить? + +/friends/edit_do.bml.success.head=ИÑполнено + +/friends/edit_do.bml.success.text=Ваш ÑпиÑок друзей изменён. Ð’Ñ‹ можете увидеть обновлённую ленту друзей здеÑÑŒ. + +/friends/edit_do.bml.textcolor=Цвет текÑта: + +/friends/edit_do.bml.title=Изменить ÑпиÑок друзей + +/friends/edit_do.bml.user=Пользователь + +/friends/edit_do.bml.viewer=ПроÑмотрщик цветов + +/friends/edit_do.bml.yourfriends.head=Ваши Ð´Ñ€ÑƒÐ·ÑŒÑ + +/friends/edit_do.bml.yourfriends.text=Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñƒ Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ñледующие друзьÑ: + +/friends/filter.bml.editgroups=ЕÑли вы хотите отредактировать ÑпиÑок групп ваших друзей [[link]] + +/friends/filter.bml.error.nogroups=Ð’Ñ‹ не можете фильтровать ÑпиÑок друзей, поÑкольку Ñначала вам надо завеÑти группы друзей. + +/friends/filter.bml.error.nogroups.header=Группы не указаны + +/friends/filter.bml.reset=ОчиÑтить + +/friends/filter.bml.select=Отметьте группу(-Ñ‹) друзей, которую вы хотите видеть в Ñвоей ленте друзей. + +/friends/filter.bml.select.header=Выбрать группы + +/friends/filter.bml.submit=Показать! + +/friends/filter.bml.title=Фильтр Друзей + +/friends/index.bml.about=Ðа Ñтой Ñтранице вы можете управлÑÑ‚ÑŒ Ñвоим ÑпиÑком друзей. Добавив других пользователей к Ñтому ÑпиÑку, вы Ñможете легко Ñледить, что проиÑходит в их жизни, через Ñвою ленту друзей. ДрузьÑми могут быть не только индивидуальные пользователи: добавлÑÑ‚ÑŒ можно и ÑообщеÑтва, и RSS-потоки. + +/friends/index.bml.edit.about=Добавление, изменение или удаление пользователей из вашего ÑпиÑка друзей, а также изменение цветовых ÑоответÑтвий друзей. + +/friends/index.bml.editgroups.about=Создание, изменение или удаление групп друзей. + +/friends/index.bml.filter=Группы друзей можно иÑпользовать Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ð¸ ÑпиÑка друзей: Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра можно выбирать отдельную группу. Также их можно иÑпользовать Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупом к запиÑÑм (Ñм. ниже). + +/friends/index.bml.filter.about=Фильтровать ÑпиÑок друзей по заданным группам. + +/friends/index.bml.groups=Кроме того, можно задавать группы друзей. + +/friends/index.bml.security=Ваш ÑпиÑок друзей также иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ñ‹Ð¼ доÑтупом. Ð’Ñ‹ можете подробнее узнать про ограничение доÑтупа через ÑпиÑкок друзей, тут: Ð”Ñ€ÑƒÐ·ÑŒÑ Ð¸ Уровни ДоÑтупа. + +/friends/index.bml.security.custom=При Ñоздании запиÑи, вы можете выбрать группу друзей, которые Ñмогут прочитать Ñту запиÑÑŒ. Ðо не вÑе программы-клиенты поддерживают наÑтройку групп друзей. + +/friends/index.bml.security.header=БезопаÑноÑÑ‚ÑŒ + +/friends/index.bml.security.only=ЗапиÑи "Только Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹" будут видны вÑем вашим друзьÑм. + +/friends/index.bml.title=ÐаÑтройка ÑпиÑка друзей + +/friends/index.bml.tools=ИнÑтрументы + +/friends/popwithfriends.bml.account_type=Извините, но ваш тип аккаунта не позволÑет иÑпользовать Ñтот ÑервиÑ. + +/friends/popwithfriends.bml.count=Сколько? + +/friends/popwithfriends.bml.exclude_own=Ð’Ñ‹ можете также иÑключить Ñвоих друзей из ÑпиÑка. + +/friends/popwithfriends.bml.include_own=Ð’Ñ‹ можете также включить Ñвоих друзей в ÑпиÑок. + +/friends/popwithfriends.bml.intro=Эти пользователи добавлены многими вашими друзьÑми, но не добавлены вами. + +/friends/popwithfriends.bml.intro_own=Эти пользователи добавлены многими вашими друзьÑми. СпиÑок также включает тех, кого добавили и вы. + +/friends/popwithfriends.bml.no_users=Ðет пользователей + +/friends/popwithfriends.bml.title=ПопулÑрные Ñреди ваших друзей пользователи + +/friends/popwithfriends.bml.user=Пользователь + +/go.bml.defaultbody=Ðе заданы параметры + +/go.bml.defaulttitle=Ошибка. + +/go.bml.error.noentry.next=Это поÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ, поÑле нее запиÑей нет. + +/go.bml.error.noentry.prev=Это Ð¿ÐµÑ€Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ, до нее запиÑей нет + +/go.bml.error.noentrytitle=ЗапиÑÑŒ отÑуÑÑ‚Ñтвует + +/go.bml.error.redirkey=Ðеправильный redir_key. + +/go.bml.error.usernotfound=Пользователь не найден + +/index.bml.about.header=О Живом Журнале + +/index.bml.about.joining<< +Это беÑплатный Ñайт. Пользователи могут Ñтать платными пользователÑми Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… возможноÑтей. + +. + +/index.bml.about.us=Живой Журнал - Ñто проÑÑ‚Ð°Ñ Ð² обращении (но очень Ð¼Ð¾Ñ‰Ð½Ð°Ñ Ð¸ легко Ð°Ð´Ð°Ð¿Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ð°Ñ Ðº вашим потребноÑÑ‚Ñм) программа Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ð¸ ваших текÑтов в интернете (блогинга), оÑÐ½Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° открытом иÑходном коде. + +/index.bml.boldcreate=Создать Ñвой Журнал! + +/index.bml.frank.image.alt=Козёл ФрÑнк, талиÑман Живого Журнала. + +/index.bml.frank.logo="Ме-е-е", Ñказал ФрÑнк. + +/index.bml.learnmore.header=Хотите узнать больше о Живом Журнале? + +/index.bml.learnmore.text=ПожалуйÑта, прочитайте опиÑание возможноÑтей ЖЖ . УбедилиÑÑŒ? Создайте ваш личный Живой Журнал! + +/index.bml.meta.desc=Живой Журнал -- Ñто меÑто, где вы можете поделитьÑÑ Ñвоими мыÑлÑми Ñо вÑем миром. + +/index.bml.meta.keywords=дневник, журнал, онлайн-журнал, дневники, пиÑательÑтво, онлайн-дневники, веб-дневник + +/index.bml.news.text=ПоÑледние новоÑти ЖЖ: + +/index.bml.news.title=ПоÑледние новоÑти + +/index.bml.post=Ð–Ð¸Ð²Ð°Ñ ÑтатиÑтика + +/index.bml.post.hour=За чаÑ: + +/index.bml.post.latest=Свежие запиÑи + +/index.bml.post.min=За минуту: + +/interests.bml.add.added.head=Добавлено! + +/interests.bml.add.added.text=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ Ð±Ñ‹Ð» добавлен к ÑпиÑку ваших интереÑов. + +/interests.bml.add.btn.text=Добавить [[interest]] + +/interests.bml.add.confirm.head=Подтверждение + +/interests.bml.add.confirm.text=Чтобы добавить [[interest]] к ÑпиÑку интереÑов, нажмите на кнопку ниже. + +/interests.bml.add.toomany.head=Извините... + +/interests.bml.add.toomany.text=У Ð²Ð°Ñ ÑƒÐ¶Ðµ определено макÑимальное количеÑтво ([[maxinterests]]) интереÑов. + +/interests.bml.addint=ЕÑли вы хотите добавить Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ Ð² Ñвой ÑпиÑок интереÑов, нажмите тут. + +/interests.bml.btn.switch=Выбрать + +/interests.bml.communities.head=ЗаинтереÑованные ÑообщеÑтва + +/interests.bml.communities.text=Следующие ÑообщеÑтва также заинтереÑованы в "[[interest]]". + +/interests.bml.count=Кол-во + +/interests.bml.enmasse.body.other=Ðиже показаны интереÑÑ‹ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. Пометьте галочками те интереÑÑ‹, которые вы хотите добавить к ÑобÑтвенным, и уберите галочки у тех, которые вы хотите удалить из Ñвоих интереÑов. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.body.other_authas=Ðиже показаны интереÑÑ‹ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. Пометьте галочками те интереÑÑ‹, которые вы хотите добавить к интереÑам [[target]], и уберите галочки у тех, которые вы хотите удалить. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.body.you=Уберите галочки у тех интереÑов, которые вы хотите удалить. По окончании нажмите "Сохранить изменениÑ". + +/interests.bml.enmasse.btn=Показать ÑпиÑок + +/interests.bml.enmasse.header=Добавление/удаление интереÑов + +/interests.bml.enmasse.intro=Изменить ÑпиÑок Ñвоих интереÑов, взÑв за оÑнову интереÑÑ‹ пользователÑ: + +/interests.bml.error.add.mustlogin=Ð’Ñ‹ должны войти в ÑиÑтему, чтобы добавить интереÑ. + +/interests.bml.error.enmasse.mustlogin=Чтобы воÑпользоватьÑÑ Ñтой возможноÑтью, вы должны войти в ÑиÑтему. + +/interests.bml.error.enmasse.noaccess=У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к журналу [[user]]. + +/interests.bml.error.findsim_do.intnotfound=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ðµ был найден. + +/interests.bml.error.nointerests=Выбранный пользователь не ÑущеÑтвует, либо он не указал никаких интереÑов. + +/interests.bml.findsim.searchwait=Обратите внимание: ПоиÑк займет неÑколько Ñекунд. Потерпите. + +/interests.bml.findsim_do.account.notallowed=Извините, ваш тип аккаунта не позволÑет иÑпользовать Ñту возможноÑÑ‚ÑŒ. + +/interests.bml.findsim_do.magic=Волшебное
            чиÑло + +/interests.bml.findsim_do.magic.head=Что такое Волшебное чиÑло? + +/interests.bml.findsim_do.magic.text=Ð”Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пользователÑ, Ñравниваемого Ñ Ð²Ð°Ð¼Ð¸, вычиÑлÑетÑÑ Ð²Ð¾Ð»ÑˆÐµÐ±Ð½Ð¾Ðµ чиÑло, на которое ÑоÑтоит из двух чаÑтей: проÑтого чиÑла Ñовпадений интереÑов и некоторых дополнительных очков за Ñовпадение редких интереÑов. + +/interests.bml.findsim_do.nomatch.head=Ðичего не найдено + +/interests.bml.findsim_do.nomatch.text=Ðет пользователей, Ñходных Ñ [[user]]. + +/interests.bml.findsim_do.notdefined=Пользователь [[user]] не указал Ñвои интереÑÑ‹. + +/interests.bml.findsim_do.similar.head=Сходные пользователи + +/interests.bml.findsim_do.similar.text=Ðиже Ñледуют наиболее Ñходные Ñ [[user]] пользователи + +/interests.bml.finished.about=Когда закончите, нажмите кнопку "Сохранить изменениÑ" ниже: + +/interests.bml.finished.header=Готово? + +/interests.bml.finished.save_button=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/interests.bml.interest=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +/interests.bml.interested.btn.find=ПоиÑк + +/interests.bml.interested.in=Ðайти людей и ÑообщеÑтва, заинтереÑованных в: + +/interests.bml.interests.findsim=Ðайти пользователей Ñ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑами, похожими на интереÑÑ‹ пользователÑ: + +/interests.bml.interests.head=ИнтереÑÑ‹ + +/interests.bml.interests.text=Вот какие забавные вещи можно Ñделать Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ интереÑами. + +/interests.bml.interests.viewpop=ПроÑмотреть популÑрные интереÑÑ‹ + +/interests.bml.login.enterinfo=Чтобы изменить Ñвои интереÑÑ‹, введите Ð¸Ð¼Ñ Ð¸ пароль. + +/interests.bml.login.proceed=Продолжить... + +/interests.bml.match=[[count]] Ñовпадение: + +/interests.bml.matches=[[count]] Ñовпадений: + +/interests.bml.morestuff=Другие интереÑные возможноÑти -- на Ñтранице интереÑов. + +/interests.bml.nointerests.text=Ðе указали ни одного интереÑа? Ð’Ñ‹ можете добавить Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ Ð½Ð° Ñтранице Личной информации. + +/interests.bml.popular.disabled=Извините, возможноÑÑ‚ÑŒ Ñмотреть популÑрные интереÑÑ‹ отключена. + +/interests.bml.popular.head=ПопулÑрные интереÑÑ‹ + +/interests.bml.popular.text=Ðиже указаны наиболее популÑрные интереÑÑ‹. + +/interests.bml.results.added=Выбранные интереÑÑ‹ были добавлены к ÑпиÑку ваших интереÑов. + +/interests.bml.results.both=Выбранные вами интереÑÑ‹ были добавлены в ваш ÑпиÑок, а отменённые были удалены. + +/interests.bml.results.deleted=Отменённые вами интереÑÑ‹ были удалены из вашего ÑпиÑка. + +/interests.bml.results.del_and_toomany=ИнтереÑÑ‹, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… вы ÑнÑли отметку, были удалены из вашего ÑпиÑка. Тем не менее, вы хотите добавить Ñлишком много интереÑов. Общее количеÑтво ваших интереÑов не может превышать [[intcount]]. Ðи один из выбранных интереÑов не был добавлен к вашему ÑпиÑку. Попробуйте вернутьÑÑ Ð½Ð°Ð·Ð°Ð´ и попытатьÑÑ Ñнова, выбрав меньшее чиÑло интереÑов Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ. + +/interests.bml.results.goback=Ð’Ñ‹ можете вернутьÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾ к Ñтранице информации о пользователе [[user]], Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ вы пришли. + +/interests.bml.results.header=Результаты + +/interests.bml.results.message=ПоÑмотреть обновлённую Ñтраницу Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹. + +/interests.bml.results.nothing=Ð’Ñ‹ ничего не изменили. + +/interests.bml.results.toomany=Ð’Ñ‹ хотите добавить Ñлишком много интереÑов. Общее количеÑтво ваших интереÑов не может превышать [[intcount]]. Ðи один из выбранных интереÑов не был добавлен к вашему ÑпиÑку. Попробуйте вернутьÑÑ Ð½Ð°Ð·Ð°Ð´ и попытатьÑÑ Ñнова, выбрав меньшее чиÑло интереÑов. + +/interests.bml.title=ИнтереÑÑ‹ + +/interests.bml.toomany.body=[[intcount]] людей и/или ÑообщеÑтв заинтереÑованы в Ñтом. СпиÑок не будет показан. + +/interests.bml.toomany.head=Ðайдено Ñлишком много запиÑей + +/interests.bml.users.head=ЗаинтереÑованные пользователи + +/interests.bml.users.text=Следующие пользователи также заинтереÑованы в [[interest]]. + +/invite/index.bml.code=Код + +/invite/index.bml.error=Ошибка + +/invite/index.bml.genmore=Сгенерировать дополнительные коды + +/invite/index.bml.how_detail=ПриглаÑительные коды отменены, поÑтому их генерирование отключено. + +/invite/index.bml.how_header=Как Ñто уÑтроено? + +/invite/index.bml.invite_header=ПриглашениÑ? + +/invite/index.bml.none=Ðи одного + +/invite/index.bml.redeemed=ИÑпользован + +/invite/index.bml.title=ПриглаÑи друзей приÑоединитьÑÑ Ðº Живому Журналу + +/invite/index.bml.unused=ÐеиÑпользован + +/invite/index.bml.use=ИÑпользовать + +/invite/index.bml.why_codes=Чтобы поддерживать Живой Журнал, контролировать его роÑÑ‚ и предупреждать его неправильное иÑпользование, в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð°ÐºÐºÑƒÐ½Ñ‚Ð° вам нужно за него заплатить или получить приглаÑительный код от уже ÑущеÑтвующего пользователÑ.Это правило веедено Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы улучшить уÑÐ»Ð¾Ð²Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð² ÑущеÑтвующих журналов за Ñчет небольшого неудобÑтва, которое иÑпытывают новые члены. + +/legal/index.bml.about<< +Живой Журнал должен производить неизменное и приÑтное впечатление на Ñвоих пользователей незавиÑимо от их проиÑÑ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ национальноÑти. Ð”Ð»Ñ Ñтого на Ñайте ÑущеÑтвуют правила поведениÑ. +Документы, приведенные здеÑÑŒ, Ñодержат ÑоответÑтвующие уÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ информацию отноÑительно политики нашей работы и наших ожиданий от Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… пользователей. Когда наши пользователи придерживаютÑÑ Ð¿Ñ€Ð°Ð²Ð¸Ð», Живой Журнал работает наилучшим образом. +Вот неÑколько важных моментов: +
              +
            • ВоздержитеÑÑŒ от раздражениÑ, оÑкорблений или угроз в Ð°Ð´Ñ€ÐµÑ Ð¾Ñтальных пользователей.
            • +
            • ВоздержитеÑÑŒ от любых оÑкорблении в Ð°Ð´Ñ€ÐµÑ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð½Ñтв.
            • +
            • ВоздержитеÑÑŒ от беÑполезных Ñообщений в Ð°Ð´Ñ€ÐµÑ Ñайта или любого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° Ñтом Ñайте.
            • +
            • Ðе публикуйте защищенные авторÑким правом документы без разрешениÑ.
            • +
            • Ðе вторгайтеÑÑŒ в личную Ñферу оÑтальных пользователей.
            • +
            • Ðе нарушайте закон РФ или ваши меÑтные законы.
            • +
            + +Полный ÑпиÑок правил приведен ниже: +. + +/legal/index.bml.about.header=Обзор + +/legal/index.bml.docs.coppa.about=ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Children's Online Privacy Protection Act (COPPA) в Ñвоих поÑтановлениÑÑ… регламентирует Ñбор и иÑпользование личной информации, предоÑтавлÑемой лицами и отноÑÑщейÑÑ Ðº лицам, не доÑтигшим 13 лет. Ðаш раздел, поÑвÑщенный COPPA, объÑÑнÑет нашу позицию в отношении данного правового документа и нюанÑÑ‹ работы Ñ ÐµÐ³Ð¾ положениÑми. + +/legal/index.bml.docs.header=Документы + +/legal/index.bml.docs.privacy.about=Положение о конфиденциальноÑти раÑÑказывает, какую информацию мы получаем от наших пользователей и как мы ее иÑпользуем. + +/legal/index.bml.docs.tos.about=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг определÑÑŽÑ‚ правила пользованиÑ, а также оÑновные Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ уÑÐ»Ð¾Ð²Ð¸Ñ Ñ‡Ð»ÐµÐ½Ñтва. ЧленÑтво и/или иÑпользование ÑиÑтемы подтверждают ÑоглаÑие Ñледовать Ñтим и другим уÑловиÑм. + +/legal/index.bml.title=ÐŸÑ€Ð°Ð²Ð¾Ð²Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/legal/privacy.bml.title=Положение о конфиденциальноÑти + +/legal/tos.bml.title=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑƒÑлуг + +/login.bml.bindip.label=ПривÑзать к IP-адреÑу: + +/login.bml.bindip.no=Ðет (работает Ð´Ð»Ñ Ð»ÑŽÐ±Ð¾Ð³Ð¾ провайдера) + +/login.bml.bindip.yes=Да (безопаÑнее) + +/login.bml.error.mustenterusername=Ð’Ñ‹ должны ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/login.bml.expire.btn.neverexpire=УÑтановите Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ ÐÐВСЕГДР+ +/login.bml.expire.btn.sessiononly=УÑтановите Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ ТОЛЬКО ÐРТЕКУЩИЙ СЕÐÐС + +/login.bml.expire.neverexpire.text=Срок дейÑÑ‚Ð²Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не иÑтечет, поÑтому еÑли вы пользуетеÑÑŒ публичным интернет-терминалом, выходите в интернет из школы, библиотеки или другого меÑта, где люди в Ñкором времени могут воÑпользоватьÑÑ Ñтим компьютером, убедитеÑÑŒ, что вы вышли из ÑиÑтемы поÑле Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹! Или же Ñмените Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ только на текущий ÑеанÑ, то еÑÑ‚ÑŒ до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°. + +/login.bml.expire.sessiononly.text=Ваша Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ дейÑтвовать до Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°. ЕÑли Ñто ваш личный компьютер и вы единÑтвенный пользователь, то вы можете уÑтановить Ñрок дейÑÑ‚Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ навÑегда: + +/login.bml.links.head=СÑылки + +/login.bml.links.link1=Ваша лента друзей. + +/login.bml.links.link2=Ваш ÑпиÑок задач. + +/login.bml.links.text=Ð’ будущем, на Ñтой Ñтранице будут вÑевозможные ÑÑылки и Ð²Ð°Ð¶Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, но пока что тут вÑего неÑколько ÑÑылок, которые могут вам пригодитьÑÑ: + +/login.bml.loggedin.head=Ð’Ñ‹ вошли в ÑиÑтему! + +/login.bml.loggedin.text=Ð’Ñ‹ вошли в ÑиÑтему под Ñвоим именем Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ паролем. + +/login.bml.login.btn.changeopts=Изменить наÑтройки + +/login.bml.login.btn.login=Вход в ÑиÑтему... + +/login.bml.login.expiration=Срок Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸: + +/login.bml.login.forget=Забыли? + +/login.bml.login.head=Вход + +/login.bml.login.never=Ðикогда + +/login.bml.login.otheropts=Другие опции: + +/login.bml.login.password=Пароль: + +/login.bml.login.text1=Чтобы войти в [[sitename]], введите ниже ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. Ðовые пользователи: Чтобы Ñоздать Ñвой журнал, нажмите Ñюда. + +/login.bml.login.text2=Ð’Ñ‹ также можете указать Ñрок Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ авторизации. По умолчанию Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´ÐµÐ¹Ñтвительна до момента Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð°, что ÑвлÑетÑÑ Ð»ÑƒÑ‡ÑˆÐ¸Ð¼ вариантом Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… компьютеров. Однако, еÑли вы единÑтвенный пользователь компьютера, и больше никто не имеет к нему доÑтупа -- вы можете выбрать вариант беÑÑрочной авторизации. Подробнее об Ñтой и других наÑтройках можно прочитать в Ñтатье Ñправки "ÐаÑтройки при входе в ÑиÑтему". + +/login.bml.login.text3=[[username]], вы вошли в [[sitename]]. ПутешеÑтвие по Ñайту можно начать Ñ ÐµÐ³Ð¾ карты. + +/login.bml.login.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/login.bml.login.whenbrowsercloses=ПоÑле Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° + +/login.bml.logout.btn=Выйти + +/login.bml.title=Вход в ÑиÑтему + +/login.bml.whylogin.benefit1=Вам больше не нужно будет вводить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ/пароль вÑюду на Ñайте. + +/login.bml.whylogin.benefit2=Ð’Ñ‹ Ñможете проÑматривать "защищенные" запиÑи в журналах ваших друзей, которые дали вам доÑтуп Ð´Ð»Ñ Ð¸Ñ… чтениÑ. + +/login.bml.whylogin.benefit3=ПоÑле входа в ÑиÑтему Вам Ñтанут видны и доÑтупны многие дополнительные функции. + +/login.bml.whylogin.head=Зачем входить в ÑиÑтему? + +/login.bml.whylogin.text=Вот неÑколько оÑновных преимущеÑтв входа в ÑиÑтему: + +/logout.bml.already.head=Ð’Ñ‹ уже вышли из ÑиÑтемы + +/logout.bml.already.text=Ð’Ñ‹ уже вышли из ÑиÑтемы + +/logout.bml.killall.btn=Завершить вÑе ÑеанÑÑ‹ + +/logout.bml.killall.head=Другие ÑеанÑÑ‹ + +/logout.bml.killall.text=У Ð²Ð°Ñ ÐµÑÑ‚ÑŒ другие активные ÑеанÑÑ‹. Хотите ли вы завершить не только данный ÑеанÑ, но и вÑе оÑтальные ÑеанÑÑ‹? (Подробнее Ñм. Ñправку). + +/logout.bml.loggedout.already=Ð’Ñ‹ уже вышли из ÑиÑтемы. + +/logout.bml.loggedout.head=Выход из ÑиÑтемы + +/logout.bml.loggedout.killedall=Ð’Ñе ÑеанÑÑ‹ завершены. + +/logout.bml.loggedout.success=Ð’Ñ‹ вышли из ÑиÑтемы. + +/logout.bml.loggedout.text=Ð’Ñ‹ уÑпешно вышли из ÑиÑтемы. + +/logout.bml.logout.btn=Выход + +/logout.bml.logout.head=Выйти? + +/logout.bml.logout.text=Ðажмите кнопку, чтобы выйти из ÑиÑтемы. + +/logout.bml.title=Выход + +/lostinfo.bml.btn.proceed=Продолжить + +/lostinfo.bml.enter_email=Введите Ñвой e-mail адреÑ: + +/lostinfo.bml.enter_email_optional=E-mail адреÑ: (необÑзательный) + +/lostinfo.bml.enter_username=Введите ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/lostinfo.bml.error.no_email=Чтобы воÑÑтановить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, вы должны ввеÑти Ð°Ð´Ñ€ÐµÑ Ñлектронной почты. + +/lostinfo.bml.error.purged=Ðевозможно воÑÑтановит пароль Ð´Ð»Ñ ÑƒÐ´Ð°Ð»Ñ‘Ð½Ð½Ð¾Ð³Ð¾ аккаунта, так как он уже окончательно удалён. + +/lostinfo.bml.error.renamed=ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð¾ÑÑтановить пароль Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ аккаунта. + +/lostinfo.bml.error.syndicated=Ðккаунт, пароль которого вы пытаетеÑÑŒ получить, транÑлируемый. У аккаунта данного типа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½ÐµÑ‚. + +/lostinfo.bml.error.sysbanned=Ваш аккаунт не имеет полномочий Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾ почте. + +/lostinfo.bml.lostpassword.text=ЕÑли вы забыли Ñвой пароль, введите ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸, необÑзательно, e-mail адреÑ, на который будет выÑлан пароль. Указанный е-mail Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть предварительно подтвержден. ЕÑли вы оÑтавите поле e-mail пуÑтым, пароль будет выÑлан вам на текущий адреÑ. + +/lostinfo.bml.lostpassword.title=Забыли пароль? + +/lostinfo.bml.lostusername.text=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, введите Ñвой e-mail Ð°Ð´Ñ€ÐµÑ Ð¸ мы вышлем вам ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. + +/lostinfo.bml.lostusername.title=Забыли Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ? + +/lostinfo.bml.title=Ð—Ð°Ð±Ñ‹Ñ‚Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/lostinfo_do.bml.error.no_usernames_for_email=Ðет пользователÑ(ей) Ñ Ñ‚Ð°ÐºÐ¸Ð¼ email адреÑом: [[address]] . + +/lostinfo_do.bml.error1.text=Ð’Ñ‹ никогда не иÑпользовали Ñтот email Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñтого аккаунта или Ð°Ð´Ñ€ÐµÑ Ð½Ðµ был подтвержден. + +/lostinfo_do.bml.lostpasswordmail.part1<< +*** Это пиÑьмо было поÑлано автоматичеÑки. Ðе отвечайте на него. *** + +Ð’Ñ‹ запрашивали утерÑнный пароль Ñ [[sitename]]. +Далее Ñледуют Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, пароль и e-mail, +на которые зарегиÑтрирован ваш журнал. + + Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: [[username]] + Пароль: [[password]] + ÐÐ´Ñ€ÐµÑ e-mail: [[emailadr]] +. + +/lostinfo_do.bml.lostpasswordmail.part2=Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ e-mail адреÑа нажмите Ñюда: + +/lostinfo_do.bml.lostpasswordmail.part3<< +Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð±Ñ‹Ð»Ð° запрошена Ñ IP-адреÑа [[remoteip]]. + +ЕÑли вы не терÑли Ñвой пароль - не переживайте. По крайней мере, +Ñто пиÑьмо пришло к вам, а не к кому-то другому. Возможно, произошла +накладка и какой-то пользователь отправил Ñтот запроÑ, +думаÑ, что данный аккаунт принадлежит ему. Также возможно, что +кто-то проÑто Ñделал опечатку в имени или адреÑе e-mail. +. + +/lostinfo_do.bml.lostpasswordmail.part4|notes=Site-local text. For 'en', it's blank. +/lostinfo_do.bml.lostpasswordmail.part4<< +ЕÑли вы дейÑтвительно полагаете, что вашему аккаунту может что-то +угрожать, прочтите информацию + http://www.livejournal.com/support/faqbrowse.bml?faqid=117 +о том, как обеÑпечить его безопаÑноÑÑ‚ÑŒ. +. + +/lostinfo_do.bml.lostpasswordmail.part5<< +Полезные ÑÑылки: + + Ваш Живой Журнал: + [[journalurl]] + + Сделать запиÑÑŒ в журнал: + [[updateurl]] + +С уважением, +команда Живого Журнала + +[[rooturl]] +. + +/lostinfo_do.bml.lostpasswordmail.subject=Забытый пароль + +/lostinfo_do.bml.password_mailed.text=ПоздравлÑем. Ваш пароль был выÑлан вам по e-mail. + +/lostinfo_do.bml.password_mailed.title=Пароль выÑлан! + +/lostinfo_do.bml.title=Ð—Ð°Ð±Ñ‹Ñ‚Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/lostinfo_do.bml.username_mailed.text=ПоздравлÑем. Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð»Ð¾ выÑлано вам по e-mail. + +/lostinfo_do.bml.username_mailed.title=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð²Ñ‹Ñлано! + +/manage/index.bml.about=УправлÑÑ‚ÑŒ Ñвоим журналом легко. ПроÑто выберите нужный пункт ниже: + +/manage/index.bml.communities=Создайте ÑообщеÑтва и управлÑйте ими: + +/manage/index.bml.communities.create.about=Создать новое ÑообщеÑтво + +/manage/index.bml.communities.header=СообщеÑтва + +/manage/index.bml.communities.manage.about=ПоменÑÑ‚ÑŒ наÑтройки и ÑпиÑок учаÑтников ÑообщеÑтва + +/manage/index.bml.customization=Измените внешний вид Ñтраниц Ñвоего журнала: + +/manage/index.bml.customization.advanced=РаÑширенные возможноÑти + +/manage/index.bml.customization.advanced.about=ПроÑмотреть, Ñоздать или изменить Ñхемы и Ñтили в ÑиÑтеме S2 + +/manage/index.bml.customization.customize=Оформление журнала + +/manage/index.bml.customization.customize.about=ÐаÑтроить внешний вид журнала и преключитьÑÑ Ð¼ÐµÐ¶Ð´Ñƒ S1 и S2 + +/manage/index.bml.customization.header=Оформление + +/manage/index.bml.customization.links=СпиÑок ÑÑылок + +/manage/index.bml.customization.links.about=Создать ÑпиÑок ÑÑылок, отображаемых в журнале + +/manage/index.bml.customization.modify.about=Изменить внешний вид журнала + +/manage/index.bml.customization.s1.header=СиÑтема Ñтилей S1 + +/manage/index.bml.customization.s2.header=СиÑтема Ñтилей S2 + +/manage/index.bml.entries=Работайте Ñ Ð·Ð°Ð¿Ð¸ÑÑми, Ñделанными в вашем журнале: + +/manage/index.bml.entries.edit.about=Редактировать или удалить запиÑи в журнале + +/manage/index.bml.entries.header=ЗапиÑи в журнале + +/manage/index.bml.entries.memories.about=ПроÑмотреть и изменить избранные запиÑи + +/manage/index.bml.friends=УправлÑйте ÑпиÑком и группами друзей или отфильтруйте ленту друзей ÑоглаÑно выбранным группам: + +/manage/index.bml.friends.edit.about=Добавить или удалить пользователей в ÑпиÑке друзей; изменить цвет, которым они обозначены. + +/manage/index.bml.friends.filter=Страница фильтров Ð´Ð»Ñ Ð»ÐµÐ½Ñ‚Ñ‹ друзей + +/manage/index.bml.friends.filter.about=Отобрать пользователей из ÑпиÑка друзей и показать определенную группу + +/manage/index.bml.friends.groups.about=Создать, отредактировать или удалить подгруппу из ÑпиÑка друзей + +/manage/index.bml.friends.header=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/manage/index.bml.information=Выберите, какие данные будут отображатьÑÑ Ð² вашем журнале: + +/manage/index.bml.information.changepass=Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ + +/manage/index.bml.information.changepass.about=Изменить пароль к Ñвоему журналу + +/manage/index.bml.information.editinfo.about=Редактировать личные данные и разные наÑтройки + +/manage/index.bml.information.emailpost=ÐаÑтройки email-шлюза + +/manage/index.bml.information.emailpost.about=Управление email-адреÑами и ПИÐ-кодами Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñей через email + +/manage/index.bml.information.header=Данные журнала + +/manage/index.bml.information.siteopts.about=Выбрать желаемую Ñхему и Ñзык Ñайта + +/manage/index.bml.information.status=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° + +/manage/index.bml.information.status.about=ПоменÑÑ‚ÑŒ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° (удалить или отменить удаление) + +/manage/index.bml.login=ÐижеÑледующие ÑÑылки ведут на Ñтраницы, где требуетÑÑ Ð¸Ð¼Ñ Ð¸ пароль. Чтобы не делать Ñто каждый раз, вы можете заранее войти в ÑиÑтему. + +/manage/index.bml.title=Управление журналами + +/manage/index.bml.userpictures=Загрузите или измените картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² Ñвоем журнале: + +/manage/index.bml.userpictures.edit.about=Загрузить или изменить картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/manage/index.bml.userpictures.header=Картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/manage/links.bml.about<< +ИÑпользуйте форму внизу Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑпиÑка ÑÑылок, которые будут видны в вашем журнале. СÑылки будут видны, еÑли Ñта возможноÑÑ‚ÑŒ поддерживаетÑÑ Ð²Ð°ÑˆÐµÐ¼ S2 Ñтилем. + +. + +/manage/links.bml.about.blank=Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑка Ñтроки введите "-" в заголовке. + +/manage/links.bml.about.heading=Чтобы Ñоздать подзаголовок раздела, введите заголовок без адреÑа. + +/manage/links.bml.about.reorder<< +Чтобы поменÑÑ‚ÑŒ раÑположение ÑÑылок в ÑпиÑке, измените порÑдковые номера Ñлева от них (можно вводить и деÑÑтичные дроби). + +. + +/manage/links.bml.error.s2required=СпиÑок ÑÑылок доÑтупен только в ÑтилÑÑ… S2. Чтобы переключитьÑÑ Ð² S2, Ñмотрите Ñтраницу [[link]]. + +/manage/links.bml.error.s2required.header=Ðеобходим Ñтиль S2 + +/manage/links.bml.success=Ваши ÑÑылки Ñохранены! + +/manage/links.bml.title=СпиÑок ÑÑылок + +/manage/phonepost.bml.delete=Удалить наÑтройки + +/manage/phonepost.bml.deleted=Ваша Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была удалена + +/manage/phonepost.bml.deleted.header=Удалено + +/manage/phonepost.bml.error.inuse=Ðеправильный PIN-код, иÑправьте, пожалуйÑта. + +/manage/phonepost.bml.error.phone.length=Ð’ вашем номере телефона должно быть менее 10 цифр. + +/manage/phonepost.bml.error.pin=Ваш ПИРдолжен быть цифровым. + +/manage/phonepost.bml.error.transcription=Указана Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð° друзей + +/manage/phonepost.bml.intro.loggedin<< +запиÑи по телефону, нашишите ваш номер телефона и ПИÐ-код ниже. p?> +Положение о конфиденциальноÑти). +Ð’ можете звонить и Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ номера, но тогда вам будет нужно ввеÑти авторизованный номер прежде, чем вы Ñможете запиÑать аудиозапиÑÑŒ. p?> + + +. + +/manage/phonepost.bml.intro.loggedout=Члены могут войти в Живой Журнал и изменить наÑтройки ÐудиозапиÑейздеÑÑŒ: + +/manage/phonepost.bml.phone=Санкционированный номер телефона: + +/manage/phonepost.bml.phone.help=(515)555-5555 + +/manage/phonepost.bml.pin= ПИÐ-код + +/manage/phonepost.bml.pin.help=Желательно, длиной от 4 до 6 цифр + +/manage/phonepost.bml.save=Сохранить наÑтройки + +/manage/phonepost.bml.saved=Сохранен + +/manage/phonepost.bml.success.moreinfo=Чтобы больше узнать о том, как запиÑывать аудиозапиÑи по телефону, Ñмотрите раздел Ñправки Как мне помеÑтить в журнал аудиозапиÑÑŒ по телефону?. + +/manage/phonepost.bml.success.text=ÐаÑтройки вашего телефона Ñохранены + +/manage/phonepost.bml.title=ÐаÑтройки при Ñоздании запиÑей по телефону + +/manage/phonepost.bml.transcribers=Утвержденные операторы + +/manage/phonepost.bml.transcribers.help=Редактировать группы друзей + +/manage/pubkey.bml.error.invalidkey=Этот PGP/GPG ключ не выглÑдит правильным . + +/manage/pubkey.bml.error.notconfigured= ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñтого Ñайта не поддерживает PGP. + +/manage/pubkey.bml.header=PGP/GPG ключ + +/manage/pubkey.bml.info=ÐŸÑƒÐ±Ð»Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ открытого ключа позволит другим пользователÑм увидеть его через вашу Ñтраницу О пользователе, и вы Ñможете пиÑать через email-шлюз Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ идентифицированных email. ИнÑтрукции на Ñтранице + +/manage/pubkey.bml.pastekey=Ð’Ñтавьте ваш полный ключ (ascii уÑиленный формат) в форму внизу + +/manage/pubkey.bml.save=Сохранить + +/manage/pubkey.bml.successhead=Готово + +/manage/pubkey.bml.successtext=Ваш открытый ключ Ñохранен. Ð’Ñ‹ можете eго увидеть здеÑÑŒ. + +/manage/pubkey.bml.title=Задать открытый ключ + +/manage/pubkey.bml.whatis=Ð’Ñ‹ не знаете, что такое открытый ключ? ÐуждаетеÑÑŒ в помощи по переноÑу вашего ключа? Читайте дополнительную информацию о PGP и GPG. + +/manage/siteopts.bml.btn.lang=ПоменÑÑ‚ÑŒ Ñзык + +/manage/siteopts.bml.btn.scheme=ПоменÑÑ‚ÑŒ Ñхему + +/manage/siteopts.bml.head.lang=Выберите Ñзык + +/manage/siteopts.bml.head.scheme=Выберите Ñхему + +/manage/siteopts.bml.scheme.preview=[ПроÑмотр [[title]] Ñхемы] + +/manage/siteopts.bml.title=ÐаÑтройки Ñайта + +/meme.bml.meme.disabled=ÐдминиÑтратор Ñайта отключил Ñту возможноÑÑ‚ÑŒ. + +/modify.bml.title=Изменение журнала + +/modify_do.bml.availablestyles.head=ДоÑтупные Ñтили + +/modify_do.bml.availablestyles.userstyles=Стили пользователÑ: + +/modify_do.bml.colortheme.about=ЗдеÑÑŒ вы можете выбрать цветовую гамму, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ иÑпользоватьÑÑ Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¼Ð¸ выше компоновками Ñтраниц. ЕÑли вам не нравÑÑ‚ÑÑ Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ðµ цветовые ÑочетаниÑ, выберите Ñвои ÑобÑтвенные. + +/modify_do.bml.colortheme.area.head=ОблаÑÑ‚ÑŒ иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ + +/modify_do.bml.colortheme.color.head1=Цвет + +/modify_do.bml.colortheme.color.head2=(цвет в виде #rrggbb или его название) + +/modify_do.bml.colortheme.customcolors=Произвольные цвета + +/modify_do.bml.colortheme.defaulttheme=Гамма по умолчанию + +/modify_do.bml.colortheme.head=Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° + +/modify_do.bml.domainalias.about=ЕÑли у Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑÑ‚ÑŒ Ñвоё зарегиÑтрированное доменное Ð¸Ð¼Ñ (или еÑли вы планируете таковое завеÑти) и хотите, чтобы по его адреÑу открывалÑÑ Ð²Ð°Ñˆ Живой Журнал, введите его здеÑÑŒ: + +/modify_do.bml.domainalias.domainname=Доменное имÑ: + +/modify_do.bml.domainalias.example=Ðапример: my-journal.com + +/modify_do.bml.domainalias.head=Совмещение доменных имён + +/modify_do.bml.domainalias.helptext=Чтобы Ñта возможноÑÑ‚ÑŒ заработала, вы также должны наÑтроить IP-Ð°Ð´Ñ€ÐµÑ DNS вашего домена так, чтобы он указывал на [[sitename]]. Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации читайте Справку. + +/modify_do.bml.done.btn.savechanges=Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/modify_do.bml.done.head=Готово? + +/modify_do.bml.done.text=Когда закончите, нажмите кнопку "Сохранить изменениÑ" ниже: + +/modify_do.bml.error.dupdomainalias=Указанное вами альтернативное доменное Ð¸Ð¼Ñ ÑƒÐ¶Ðµ зарегиÑтрировано другим пользователем. + +/modify_do.bml.error.stylenotavailable=Один из выбранных вами Ñтилей недоÑтупен. Причиной Ñтого может быть или еÑли кто-то удалил Ñтиль, или еÑли вы выбрали Ñтиль, который вы не имеете права иÑпользовать. + +/modify_do.bml.friends.about=Эти наÑтройки влиÑÑŽÑ‚ на то, как выглÑдит ваша лента друзей. + +/modify_do.bml.friends.head=Лента друзей + +/modify_do.bml.friends.opt.usesharedpic.about=Этот флаг определÑет чью картинку вы видите в Ñвоей ленте друзей, когда пользователь помещает запиÑÑŒ в ÑовмеÑтно иÑпользуемый журнал или журнал ÑообщеÑтва. ЕÑли вы уÑтановите флаг, вы будете видеть картинку ÑообщеÑтва. ЕÑли вы уберёте флаг, вы будете видеть картинку пользователÑ, оÑтавившего запиÑÑŒ. + +/modify_do.bml.friends.opt.usesharedpic.head=Показывать картинки ÑовмеÑтно иÑпользуемых журналов вмеÑто картинок пользователей, оÑтавлÑющих там запиÑи. + +/modify_do.bml.journaloptions.about=ЗдеÑÑŒ вы можете переделать внешний вид Ñтраниц вашего Живого Журнала. ЕÑли вам интереÑно как вÑÑ‘ Ñто работает, читайте информацию Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð². Однако мы предполагаем, что в большинÑтве Ñлучаев доÑтаточно оÑновных наÑтроек, приведённых ниже: + +/modify_do.bml.journaloptions.head=ÐаÑтройки Журнала + +/modify_do.bml.journalstatus.about=ЗдеÑÑŒ вы можете удалить или воÑÑтановить Ñвой журнал. С момента ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ 30 дней, чтобы передумать и воÑÑтановить его. По иÑтечении 30 дней, журнал будет удалён навÑегда и воÑÑтановлению подлежать не будет. + +/modify_do.bml.journalstatus.head=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ñти журнала + +/modify_do.bml.journalstatus.select.activated=Ðктивен + +/modify_do.bml.journalstatus.select.deleted=Удалён + +/modify_do.bml.journalstatus.select.head=СоÑтоÑние: + +/modify_do.bml.journalstatus.select.suspended=Заморожен + +/modify_do.bml.moodicons.about=ÐŸÐ¾Ð¼ÐµÑ‰Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в журнал, вы можете указать Ñвое текущее наÑтроение. Разные пользователи Ñоздали множеÑтво наборов Ñо значками наÑтроений. Их можете иÑпользовать и вы. ЕÑли вы не хотите, чтобы Ñ€Ñдом Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ наÑтроениÑми были картинки (или еÑли вы вообще не хотите пользоватьÑÑ Ñтой возможноÑтью), выберите "(None)". + +/modify_do.bml.moodicons.head=Значки наÑтроений + +/modify_do.bml.moodicons.opt.forcefriends.about=ИÑпользовать Ñтот набор Ð´Ð»Ñ Ð²Ñех пользователей в вашей ленте друзей. + +/modify_do.bml.moodicons.personal=ПерÑональные темы: + +/modify_do.bml.moodicons.preview=проÑмотр + +/modify_do.bml.moodicons.select=Выберите набор значков наÑтроений: + +/modify_do.bml.overrides.about=Вам необÑзательно что-то менÑÑ‚ÑŒ в Ñтом разделе. Он предназначен Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… ÑпецифичеÑких деталей в компоновке ваших Ñтраниц. Более Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ÑодержитÑÑ Ð² разделе Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð². Учтите, что перекрывающими кодами вы можете переопределить лишь некоторые фрагменты Ñтилей. ЕÑли вы хотите переопределить вÑÑ‘, вам Ñледует Ñоздать Ñвой ÑобÑтвенный Ñтиль. + +/modify_do.bml.overrides.box.head=Перекрывающие коды: + +/modify_do.bml.overrides.head=Переопределение ÑÑ‚Ð¸Ð»Ñ + +/modify_do.bml.overrides.note=Учтите, что не вÑе переменные ÑÑ‚Ð¸Ð»Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть переопределены. Дополнительную информацию Ñмотрите в документации. Также, обратите внимание, что еÑли вы, Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÑ Ð¿ÐµÑ€ÐµÐºÑ€Ñ‹Ð²Ð°ÑŽÑ‰Ð¸Ðµ коды, иÑпользовали Ñ‚Ñг, не разрешённый в заголовке HTML-документа (например, <DIV>, <SPAN>, <IMG> и многие другие), то Ñтот Ñ‚Ñг будет вырезан. Ð’ перекрывающих кодах вида *_HEAD могут быть иÑпользованы только те Ñлементы HTML, которые разрешены в заголовке HTML-документа. Это Ñ‚Ñги: <title>, <base>, <style>, <link>, и <meta>. + +/modify_do.bml.overrides.warning=ЭТО ÐЕ ТО МЕСТО, ГДЕ МОЖÐО ПИСÐТЬ Ð’ СВОЙ ЖУРÐÐЛ! + +/modify_do.bml.pagelayoutstyle.about=Эта наÑтройка определÑет как ваш журнал раÑполагаетÑÑ Ð½Ð° Ñтранице. + +/modify_do.bml.pagelayoutstyle.head=Стиль компоновки Ñтраницы + +/modify_do.bml.pagelayoutstyle.warning=Ваш тип Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет выбирать Ñреди небольшого количеÑтва Ñтилей. + +/modify_do.bml.success.head=УÑпешно + +/modify_do.bml.success.text=ÐаÑтройки вашего журнала обновлены. Ð’Ñ‹ можете поÑмотреть Ñвой журнал здеÑÑŒ. + +/multisearch.bml.formaterror=Ошиибка Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ + +/multisearch.bml.noaddress.text=Ð’Ñ‹ не указали email Ð°Ð´Ñ€ÐµÑ + +/multisearch.bml.noaddress.title=Ðет адреÑа + +/multisearch.bml.nointerest.text=Ð’Ñ‹ не указали Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ + +/multisearch.bml.nointerest.title=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ oÑ‚ÑуÑтвует + +/multisearch.bml.nomatch.text=ПоиÑк по заданным вами параметрам безрезультатен + +/multisearch.bml.nomatch.title=Совпадений нет + +/multisearch.bml.region.bodytext<< +Ð’Ñ‹ можете проводить поиÑк по региону в Ñледующих форматах: +
              +
            • Страна
            • +
            • Город*
            • +
            • Город, штат
            • +
            • Штат, Ñтрана
            • +
            • Город, штат, Ñтрана
            • +
            +ПримечаниÑ: +
              +
            • *поиÑк Ñ Ð¸Ñпользованием только Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð³Ð¾Ñ€Ð¾Ð´Ð° или города + штата по умолчанию подразумевает СШÐ.
            • +
            • Страна может определÑÑ‚ÑŒÑÑ Ð»Ð¸Ð±Ð¾ названием Ñтраны, либо двухбуквенным кодом Ñтраны.
            • +
            +ЕÑли вы хотите иÑпользовать другой тип поиÑка, поÑмотрите поиÑк по директориÑм. +. + +/multisearch.bml.region.head=ПоиÑк по региону + +/paidaccounts/index.bml.costs.header=И Ñколько Ñто Ñтоит? + +/paidaccounts/index.bml.costs.rates=РаÑценки Ñледующие: + +/paidaccounts/index.bml.costs.rates.amount.header=СтоимоÑÑ‚ÑŒ + +/paidaccounts/index.bml.costs.rates.inexpensive=Таким образом, при оплате за год получаетÑÑ Ñ‡ÑƒÑ‚ÑŒ больше двух долларов СШРв меÑÑц. Ð’Ñ€Ñд ли Ñ‚Ð°ÐºÐ°Ñ Ñ‚Ñ€Ð°Ñ‚Ð° Ñильно ударит Ð²Ð°Ñ Ð¿Ð¾ карману. Самое Ñложное, что вам придётÑÑ Ñделать, Ñто доÑтать кошелёк, вытащить кредитную карту и ввеÑти ваши данные. + +/paidaccounts/index.bml.costs.rates.time.header=ПродолжительноÑÑ‚ÑŒ + +/paidaccounts/index.bml.features<< +
            Чтобы выразить нашу признательноÑÑ‚ÑŒ пользователÑм, которые помогают ЖЖ, пользователи, оплатившие Ñвои журналы, получат дополнительные возможноÑти. ВозможноÑти перечиÑленные здеÑÑŒ - только чаÑÑ‚ÑŒ вÑех возможноÑтей, доÑтупных платным пользователÑм:
            + +
            Ðовое! Создание запиÑей через email
            +
            Платные пользователи могут быÑтро и безопаÑно Ñоздавать запиÑи в журналах и ÑообщеÑтвах, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð½Ð°Ñˆ email шлюз.
            + +
            ÐаÑтройка внешнего вида журнала
            +
            Ð’ дополнение к выбору ÑÑ‚Ð¸Ð»Ñ Ð¸ цветовой гаммы Ñвоего дневника, вы Ñможете Ñоздать ÑобÑтвенный Ñтиль, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð»ÑŽÐ±Ñ‹Ðµ коды HTML. Ð’Ñ‹ также Ñможете Ñоздать Ñтиль, полноÑтью ÑоответÑтвующий дизайну ÑобÑтвенного Ñайтa, который вы затем Ñможете легко вÑтроить в вашу домашнюю Ñтраницу. И тогда никто не узнает, что вы иÑпользуете LiveJournal.com как механизм Ð´Ð»Ñ Ñвоего дневника.
            + +
            ОпроÑÑ‹
            +
            Платные пользователи могут Ñоздавать oпроÑÑ‹ в Ñвоих журналах, а также в ÑообщеÑтвах, в которые они могут пиÑать.
            + +
            Больше картинок пользователÑ
            +
            Платные пользователи могут загрузить до 15 ÑобÑтвенных картинок. Ð’ то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº обычные пользователи - только 3.
            + +
            ÐÐ´Ñ€ÐµÑ Ñлектронной почты на LiveJournal.com
            +
            Платные пользователи получают Ð°Ð´Ñ€ÐµÑ Ñлектронной почты на LiveJournal.com ([[username]]@livejournal.com), который может быть включен или выключен.
            + +
            ПоиÑк по каталогу
            +
            Платные пользователи получают доÑтуп к каталогу Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка других пользователей.
            + +
            СобÑтвенное доменное имÑ
            +
            ВмеÑто адреÑа +http://www.livejournal.com/users/[[username]]/, ваш журнал будет также доÑтупен по адреÑу +http://[[username]].livejournal.com/, более короткому и менее официальному.
            + +
            Syndication
            +
            Paid accounts have the ability to create new syndicated accounts, which are RSS feeds that are incarnated on LiveJournal.
            + +
            ТранÑлÑциÑ
            +
            Пользователи Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼Ð¸ аккаунтами могут Ñоздавать новые транÑлируемые журналы, предÑтавлÑющие Ñобой отображаемые в Живом Журнале RSS-потоки.
            + +
            ТекÑтовые ÑообщениÑ
            +
            Платные пользователи получают возможноÑÑ‚ÑŒ принимать текÑтовые ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð° ÑобÑтвенный мобильный телефон или пейджер, поÑланные через Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала.
            + +
            Больше To-Do запиÑей
            +
            Платные пользователи могут Ñделать до 150 запиÑей "СпиÑок дел" (To-Do) и могут иÑпользовать различные уровни безопаÑноÑти Ð´Ð»Ñ Ñтих запиÑей.
            + +
            Ð’Ñтраивание
            +
            Платные пользователи получают доÑтуп ко вÑем наÑтройкам вÑÑ‚Ñ€Ð°Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° в Ñвою домашнюю Ñтраницу. Ð’Ñе наÑтройки перечиÑлены на Ñтранице "Ð’Ñтраивание".
            + +
            Перенаправление доменов
            +
            Платные пользователи могут уÑтановить перенаправление Ñо Ñвоих доменов на Ñвой Живой Журнал.
            + +
            Подробнее...
            +
            Чтобы узнать вÑе преимущеÑтва платных аккаунтов, прочтите Ñтатью "Какие преимущеÑтва еÑÑ‚ÑŒ у платных пользователей?".
            +. + +/paidaccounts/index.bml.features.header=Так какие замечательные возможноÑти Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ñƒ? + +/paidaccounts/index.bml.title=О платных пользователÑÑ… + +/paidaccounts/index.bml.whypay.argument=БезуÑловно нет. Мы ÑоглаÑны, что плата за пользование веб-ÑервиÑами раздражает. ПоÑтому практичеÑки вÑе возможноÑти Живого Журнала доÑтупны вÑем и беÑплатно. Однако, еÑли вам нравитÑÑ ÑервиÑ, который мы Ð´Ð»Ñ Ð²Ð°Ñ Ñделали, окажите нам поддержку и Ñтаньте платным пользователем. + +/paidaccounts/index.bml.whypay.header=Я должен платить за пользование Живым Журналом? + +/paidaccounts/index.bml.whypay.no_ads=Ðа поддержку вебÑайтов нужны деньги (за Ñервера, их размещение и траффик), и нам кажетÑÑ, лучше дать вам возможноÑÑ‚ÑŒ заплатить за ÑервиÑ, чем раздражать Ð²Ð°Ñ Ð²Ñплывающими рекламными баннерами, почтовыми раÑÑылками (Ñпамом) и Ñ‚.д. + +/paidaccounts/index.bml.your_username=ваше_имÑ_Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/paidaccounts/usepaypal.bml.delivery.badformat=Ðеправильный формат даты доÑтавки. Введите дату в виде гггг-мм-дд или гггг-мм-дд чч:мм + +/paidaccounts/usepaypal.bml.delivery.past=Дата доÑтавки не может быть в прошлом. ЕÑли хотите, чтобы доÑтавка произошла мгновенно - оÑтавьте поле пуÑтым. + +/paidaccounts/usepaypal.bml.delivery.toofuture=Дата доÑтавки не может быть более чем на меÑÑц в будущем. + +/pay/index.bml.deliverydate.details=Формат гггг-мм-дд чч:мм (по Гринвичу)
            (оÑтавьте пуÑтым Ð´Ð»Ñ Ð¼Ð³Ð½Ð¾Ð²ÐµÐ½Ð½Ð¾Ð¹ доÑтавки) + +/pay/index.bml.deliverydate.label=Дата доÑтавки: + +/pay/index.bml.gift.anonymous=Ðнонимный подарок + +/poll/create.bml.button.editpoll=Редактировать Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.button.insert=Ð’Ñтавить + +/poll/create.bml.button.postpoll=Опубликовать Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.button.preview=Предварительный проÑмотр опроÑа + +/poll/create.bml.button.seecode=ПроÑмотреть код + +/poll/create.bml.button.startover=Ðачать Ñначала + +/poll/create.bml.elements.limitreached=ИÑпользовано макÑимальное количеÑтво возможных Ñлементов + +/poll/create.bml.error.accttype=Ваш тип аккаунта не позволÑет Ñоздавать опроÑÑ‹. + +/poll/create.bml.error.allitemsblank=Ð’Ñе Ñтрочки не могут быть незаполненными + +/poll/create.bml.error.notext=Вам придетÑÑ ÑƒÑ‚Ð¾Ñ‡Ð½Ð¸Ñ‚ÑŒ ваш Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/create.bml.error.parsing=Ошибка при анализе опроÑа: + +/poll/create.bml.error.pqmaxlengthinvalid=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° атрибута lj-pq тегов должна быть чиÑлом от [[min]] до [[max]]. + +/poll/create.bml.error.pqsizeinvalid=Ðтрибут размера lj-pq текÑта дожен быть целым чиÑлом от [[min]] до [[max]]. + +/poll/create.bml.error.scalemaxlessmin=Значение "от" должно быть меньше Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ "до" + +/poll/create.bml.error.scalemininvalid=Увеличение на шкале должно быть минимум [[min]]. + +/poll/create.bml.error.scaletoobig=Лимит [[max]] выборов (до-от)/количеÑтво >20 + +/poll/create.bml.error.texttoolong=ТекÑÑ‚ варианта Ñлишком длинный и был укорочен + +/poll/create.bml.haserrors=Ð’ вашем опроÑе обнаружена одна или неÑколько ошибок. Прокрутите Ñтраницу вниз, чтобы увидеть подробноÑти. + +/poll/create.bml.insertquestion=Введите ваш Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð·Ð´ÐµÑÑŒ: + +/poll/create.bml.options=Варианты: + +/poll/create.bml.options.limitreached=Вами доÑтигнут лимит количеÑтва вариантов + +/poll/create.bml.pollname=Ðазвание опроÑа: + +/poll/create.bml.preview.desc=Внизу находитÑÑ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ð¹ проÑмотр вашего опроÑа. Он будет выглÑдеть точно так же и в вашем журнале. ИÑпользуйте кнопки, чтобы вернутьÑÑ Ðº предыдущей Ñтранице и внеÑти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð½Ð¸Ñ Ð¸Ð»Ð¸ чтобы помеÑтить Ð¾Ð¿Ñ€Ð¾Ñ Ð²Ð°Ñˆ журнал. + +/poll/create.bml.preview.options=Варианты: + +/poll/create.bml.properties=ХарактериÑтики опроÑа: + +/poll/create.bml.question=ВопроÑ: + +/poll/create.bml.questionnum=Ð’Ð¾Ð¿Ñ€Ð¾Ñ #[[num]] + +/poll/create.bml.questions=ВопроÑÑ‹ Ð´Ð»Ñ Ð¾Ð¿Ñ€Ð¾Ñа + +/poll/create.bml.title=Создание опроÑа + +/poll/create.bml.type.check=Check Boxes + +/poll/create.bml.type.drop=Drop-down box + +/poll/create.bml.type.radio=Radio Buttons + +/poll/create.bml.type.scale=Scale + +/poll/create.bml.type.text=Text entry + +/poll/create.bml.whoview=Кому можно видеть Ñтот опроÑ? + +/poll/create.bml.whovote=Кому можно голоÑовать в Ñтом опроÑе? + +/poll/index.bml.discuss=ОбÑудить результаты + +/poll/index.bml.error.cantview=Извините, вам не разрешено видеть Ñтот опроÑ. + +/poll/index.bml.error.postdeleted=ÐÐ°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ удалена, Ð¾Ð¿Ñ€Ð¾Ñ Ð½ÐµÐ´Ð¾Ñтупен. + +/poll/index.bml.filloutpoll=Заполнить Ð¾Ð¿Ñ€Ð¾Ñ + +/poll/index.bml.gotocreate=Это приглашение принÑÑ‚ÑŒ учаÑтие в опроÑе. Ð’Ñ‹ наткнулиÑÑŒ на Ñтраницу, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½Ð¸Ñ‡ÐµÐ¼ не занÑта. ЕÑли хотите, вы можете Ñоздать новый опроÑ. + +/poll/index.bml.pollnotfound=ÐžÐ¿Ñ€Ð¾Ñ Ð½Ðµ найден. + +/poll/index.bml.submitted.head=СпаÑибо + +/poll/index.bml.submitted.text=Ваши ответы на вопроÑÑ‹ отправлены. + +/poll/index.bml.submitted.title=Отправлено! + +/poll/index.bml.title=ÐžÐ¿Ñ€Ð¾Ñ + +/poll/index.bml.viewresults=Показать результаты опроÑа + +/press/staff.bml.accountserv=БухгалтерÑÐºÐ°Ñ Ñлужба + +/press/staff.bml.administration=Управление проектом + +/press/staff.bml.administration.about=LiveJournal.com был запущен в 1999 году как перÑональный проект БрÑда Фицпатрика, и в течение двух лет поддерживалÑÑ Ð²ÐµÑ€Ð½Ñ‹Ð¼Ð¸ и преданными добровольцами. ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° то, что неÑколько команд добровольцев продолжают работу над проектом, у Ð½Ð°Ñ Ñ‚ÐµÐ¿ÐµÑ€ÑŒ еÑÑ‚ÑŒ небольшое количеÑтво ответÑтвенных работников, наблюдающих за их деÑтельноÑтью. + +/press/staff.bml.avva.title=Старший разработчик + +/press/staff.bml.back2=Обратно в раздел Ð´Ð»Ñ Ð¿Ñ€ÐµÑÑÑ‹ + +/press/staff.bml.bradfitz.quip=СоÑредоточитьÑÑ Ð½Ð° задаче, а не на деньгах. + +/press/staff.bml.bradfitz.title=Президент / Ведущий разработчик + +/press/staff.bml.contact=ЕÑли вам надо ÑвÑзатьÑÑ Ñ ÐºÐµÐ¼-то из наÑ, пишите по адреÑу webmaster@livejournal.com. + +/press/staff.bml.custserv=ОбÑлуживание клиентов/ИÑÑледование юзабилити + +/press/staff.bml.david.title=Стажёр + +/press/staff.bml.denisep.quip=Будет готово к Ñледующему четвергу. + +/press/staff.bml.denisep.title=Работа Ñ Ð´Ð¾Ð±Ñ€Ð¾Ð²Ð¾Ð»ÑŒÑ†Ð°Ð¼Ð¸ / СпециалиÑÑ‚ по иÑпользуемоÑти + +/press/staff.bml.deveiant.title=Удаленный разработчик + +/press/staff.bml.developers=Разработчики + +/press/staff.bml.evan.title=ЗаÑлуженный хакер + +/press/staff.bml.ferrell.title=Менеджер по работе Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð°Ð¼Ð¸ + +/press/staff.bml.jproulx.quip=ÐеÑти Ñвет в маÑÑÑ‹ + +/press/staff.bml.jproulx.title=Работа Ñ ÑообщеÑтвом / СвÑзи Ñ Ð¿Ñ€ÐµÑÑой + +/press/staff.bml.kevin.title=Веб-маÑтер и дизайнер + +/press/staff.bml.lisa.title=СиÑтемный админиÑтратор + +/press/staff.bml.mahlon.quip=Ук! Уук! + +/press/staff.bml.mahlon.title=Kодер + +/press/staff.bml.nick.title=СиÑтемный админиÑтратор + +/press/staff.bml.ryanfitz.title=Платежные ÑиÑтемы + +/press/staff.bml.sandy.title=Ð‘ÑƒÑ…Ð³Ð°Ð»Ñ‚ÐµÑ€Ð¸Ñ Ð¸ делопроизводÑтво + +/press/staff.bml.smithy.title=Хакер-подмаÑтерьe + +/press/staff.bml.sysadmin=СиÑтемные админиÑтраторы + +/press/staff.bml.title=Ведущие ÑпециалиÑÑ‚Ñ‹ + +/press/staff.bml.whitaker.quip=Что ещё? + +/press/staff.bml.whitaker.title=Удаленный разработчик + +/pubkey.bml.error.notconfigured=Этот Ñайт не Ñконфигурирован Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ PGP. + +/pubkey.bml.error.nousername=Ðе указано Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/pubkey.bml.info.desc=Ðе знаете, что такое открытый ключ? Прочитайте дополнительную информацию о PGP и GPG. + +/pubkey.bml.info.head<< +Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +. + +/pubkey.bml.info.upload=Хотите загрузить ваш ключ? Ðажмите здеÑÑŒ. + +/pubkey.bml.label=Открытый ключ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]: + +/pubkey.bml.nokey=[[user]] пока не загрузил открытый ключ. + +/pubkey.bml.title=Показать открытый ключ + +/register.bml.ask.body=Ðажмите на кнопку внизу, чтобы поÑлал подверждающий email [[email]]. + +/register.bml.ask.button=ПоÑлать + +/register.bml.ask.header=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.asterisk.comment=(аккаунты, отмеченные * еще не подверждены) + +/register.bml.email.body<< +Это подтверждающий еmail, который вы запроÑили. +Ð”Ð»Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ аккаунта, пожалуйÑта, откройте Ñтраницу: + + [[conflink]] + +Возможно, вам придетÑÑ Ñкопировать Ñтот Ð°Ð´Ñ€ÐµÑ Ð¸ вÑтавить его в окошко вашего браузера. + +ИÑкренне ваш +[[sitename]] +[[sitelink]] +. + +/register.bml.email.subject=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.error.invalidcode=Ðеправильный подтверждающий код + +/register.bml.error.useralreadyvalidated=ÐÐ´Ñ€ÐµÑ Ð¿Ð¾Ñ‡Ñ‚Ñ‹ [[user]] уже был подтверждён. + +/register.bml.error.usernotfound=Пользователеь не найден + +/register.bml.new.body=СпаÑибо! Ваш email Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½. Теперь вам может быть интереÑно Ñделать Ñледующее: + +/register.bml.new.editinfo=Редактировать информацию -- Заполните анкету Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ выберите наÑтройки. + +/register.bml.new.header=ПолучилоÑÑŒ! + +/register.bml.new.login=Login -- И вам не придетÑÑ Ð¿Ð¾Ð²Ñюду вводить ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. + +/register.bml.new.modify=Изменить журнал -- Изменить внешний вид вашего журнала + +/register.bml.new.update=ÐÐ¾Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ -- ÐапиÑать в вашем журнале + +/register.bml.sent.body=Еmail, подтверждающий региÑтрацию, был поÑлан . Ð”Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтрации вам нужно нажать на ÑÑылку в email. + +/register.bml.sent.header=ПолучилоÑÑŒ! + +/register.bml.title=Подтвердить email Ð°Ð´Ñ€ÐµÑ + +/register.bml.trans.body=Ваш новый email Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½ + +/register.bml.trans.header=ПолучилоÑÑŒ + +/rename/index.bml.does=Измeненение Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° изменÑет только Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ. Ð’Ñе оÑтальное - ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¿Ð¾ÑтоÑнного или платного пользователÑ, привилегии пользователÑ, Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ, Ð´Ñ€ÑƒÐ·ÑŒÑ Ð¸ другие данные, ÑвÑзанные Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð¾Ð¼ - оÑтанутÑÑ Ñ‚ÐµÐ¼Ð¸ же и будут Ñоединены Ñ Ð½Ð¾Ð²Ñ‹Ð¼ именем пользователÑ. Ð’Ñе ÑущеÑтвующие комментарии в других журналах и запиÑи в ÑоообщеÑтвах покажут новое название. + +/rename/index.bml.faqurl=Дополнительную информацию о процеÑÑе Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ найти в ВопроÑах о переименовании. + +/rename/index.bml.fee=Изменение имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала платное - [[fee]] + +/rename/index.bml.heading.cost=СтоимоÑÑ‚ÑŒ + +/rename/index.bml.heading.details<< +ПодробноÑти + + +. + +/rename/index.bml.heading.how<< +Как купить + +. + +/rename/index.bml.option=Ð’Ñ‹ можете либо перенаправить от Ñтарого Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ðº новому названию или отметить Ñтарое как удаленное. Ð’Ñ‹ можете разрешить тем, кто Ð·Ð°Ð½ÐµÑ Ð²Ð°Ñ Ð² ÑпиÑок друзей, оÑтавить ваше новое Ð¸Ð¼Ñ Ð² Ñтом ÑпиÑке или убрать его из ÑпиÑков друзей вÑех пользователей. + +/rename/index.bml.options.buy=Купить Купон + +/rename/index.bml.options.buy.desc=Купить Купон Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ + +/rename/index.bml.options.use=ИÑпользовать Купон + +/rename/index.bml.options.use.desc=ИÑпользовать Купон Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ + +/rename/index.bml.redeem=Сначала вы должны купить Купон Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ, который будет поÑлан вам по е-mail. ПоÑле Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÐšÑƒÐ¿Ð¾Ð½Ð° вы Ñможете переименовать аккаунт. Оплата Купонов не возвращаетÑÑ, но вы можете передать Купон любому пользователю. То еÑÑ‚ÑŒ вы можете купить Купон Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ пользовательÑ. + +/rename/index.bml.reserve=. + +/rename/index.bml.title=Служба Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð¾Ð² + +/rename/index.bml.whatrename=Ð’Ñ‹ можете переименовать только личный аккаунт, но не управлÑемое вами ÑообщеÑтво + +/rename/use.bml.changes=Следующие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ Ñделаны поÑле переименованиÑ: + +/rename/use.bml.changes.move="[[newuser]]" будет препровожден "[[exname]]" + +/rename/use.bml.changes.rename="[[oldname]]" будет измененно на "[[newuser]]" + +/rename/use.bml.confirm=ПоÑле того, как вы нажмете "Rename", вы не Ñможете отменить изменение. Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ð²ÐµÐ´Ð¸Ñ‚Ðµ Ñлово "[[confirmword]]" в графу внизу. + +/rename/use.bml.confirm.click=Ртеперь нажимите 'Rename': + +/rename/use.bml.error.allocating=Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð½Ð°Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð¾Ñа конечнoго аккаунтa + +/rename/use.bml.error.badpass=Пароли Ñтарого и нового имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ Ñовпадают + +/rename/use.bml.error.differentusername=Ð’Ñ‹ не были загружены как данный пользователь когда вы открыли Ñту форму + +/rename/use.bml.error.login=Ðо Ñначла вам нужно войти + +/rename/use.bml.error.readit=Прочитайте параграф, который находитÑÑ Ð²Ñ‹ÑˆÐµ + +/rename/use.bml.error.reserved=Ошибка. Ð’Ñ‹ пытаетеÑÑŒ изменить зарезервированное название аккаунта. + +/rename/use.bml.error.same=Это Ð¸Ð¼Ñ Ñ‚Ð°ÐºÐ¾Ðµ же как ваше Ñтарое Ð¸Ð¼Ñ + +/rename/use.bml.error.token=ÐедейÑтвительный Купон + +/rename/use.bml.error.type=Только обычные аккаунты, но не аккаунты ÑообщеÑтв могут быть переименованы + +/rename/use.bml.error.unknown=ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° вÑе еще здеÑÑŒ + +/rename/use.bml.error.usedtoken=Этот купон уже иÑпользован. + +/rename/use.bml.error.username=Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/rename/use.bml.error.usernametaken=Это Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ занÑто + +/rename/use.bml.heading.changes=Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + +/rename/use.bml.heading.success=ПолучилоÑÑŒ! + +/rename/use.bml.heading.sure=Ð’Ñ‹ уверены? + +/rename/use.bml.intent=Эта Ñтраница предназначена Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ аккунта поÑле того, как вы прочитали введение и купили купон Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ + +/rename/use.bml.label.desired=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, которое вам нужно: + +/rename/use.bml.label.proceed=Продолжить... + +/rename/use.bml.label.rename=Переименовать + +/rename/use.bml.label.token=Купон + +/rename/use.bml.label.username=Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/rename/use.bml.options=ВозможноÑти при переименовании: + +/rename/use.bml.options.delfriends=Удалить вÑех пользователелй из ÑпиÑка друзей и выйти из вÑех ÑообщеÑтв + +/rename/use.bml.options.forward=Ðвтоматичеки перенеÑти пользователей из [[oldname]] в новое название аккаунта + +/rename/use.bml.options.keepfriends=ОÑтавить вÑех пользователей и вÑе ÑообщеÑтва в ÑпиÑке друзей + +/rename/use.bml.options.keepself=ОÑтавить вÑех в ÑпиÑке друзей + +/rename/use.bml.options.removeself=Убрать вÑех подрÑд из ÑпиÑка друзей + +/rename/use.bml.options.unlink=Ðе поддерживать ÑвÑзь между [[oldname]] и новым журналом + +/rename/use.bml.success.login=Теперь вам придетÑÑ Ð¾Ð¿ÑÑ‚ÑŒ войти + +/rename/use.bml.success.moved="[[newuser]]" был препровожден "[[exname]]" + +/rename/use.bml.success.renamed="[[olduser]]" был переименован, и теперь он "[[newuser]]" + +/rename/use.bml.success.usernamerenamed=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð½Ð¾ + +/rename/use.bml.title=ИÑпользовать Купон Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ + +/site/contract.bml.promise=Мы обÑзуемÑÑ: + +/site/contract.bml.promise.account=Уважать ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ аккаунта + +/site/contract.bml.promise.account.about=ПоÑтоÑнные аккаунты ÑохранÑÑŽÑ‚ÑÑ Ð´Ð¾ тех пор, пока ÑущеÑтвует Ñайт. Платные аккаунты оÑтаютÑÑ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼Ð¸ до иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ñрока дейÑтвиÑ, еÑли не будут заранее продлены. Ðккаунты ранних пользователей получают доÑтуп к платным возможноÑÑ‚Ñм, которые были доÑтупны беÑплатно в период Ð·Ð°Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñайта. (Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° не ÑохранÑетÑÑ Ð² Ñлучае Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ ÐµÐ³Ð¾ дейÑÑ‚Ð²Ð¸Ñ Ð¸Ð·-за Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñ Ð£Ñловий пользованиÑ.) + +/site/contract.bml.promise.ads=ОÑтаватьÑÑ Ñвободными от рекламы + +/site/contract.bml.promise.ads.about=Быть может, Ñто наше больное меÑтно, или же она проÑто не приноÑила большого дохода -- в любом Ñлучае мы обÑзуемÑÑ, что реклама никогда не будет размещатьÑÑ Ð½Ð° нашем Ñервере и на Ñтраницах Ñайта. + +/site/contract.bml.promise.community=Работать Ñ ÑообщеÑтвом и Ð´Ð»Ñ ÑообщеÑтва + +/site/contract.bml.promise.community.about=Мы обÑзуемÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ‚Ð¸Ð²Ð½Ð¾, но ненавÑзчиво информировать Ð²Ð°Ñ Ð¾ любых изменениÑÑ…. Мы обÑзуемÑÑ Ð²ÐµÑти бизнеÑ, оÑновываÑÑÑŒ на пожеланиÑÑ… и в интереÑах ÑообщеÑтва Живого Журнала. + +/site/contract.bml.promise.opensource=Поддерживать движение за Ñвободное программное обеÑпечение + +/site/contract.bml.promise.opensource.about=ВеÑÑŒ иÑходный код, необходимый Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ наÑтраиваемой инÑталлÑции Живого Журнала, доÑтупен публично. Мы обещаем, что Ñтот код вÑегда будет открытым и Ñвободным, Ñто — наш вклад в поддержку Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð·Ð° Ñвободное программное обеÑпечение. + +/site/contract.bml.promise.spam=Ðикогда не приÑылать вам неÑанкционированную Ñлектронную почту + +/site/contract.bml.promise.spam.about=Мы убеждены, что Ñпаму не меÑто в интернете, и мы обещаем никогда не приÑылать вам Ñлектронные пиÑьма без вашего Ñвного или подразумеваемого ÑоглаÑиÑ. Мы обÑзуемÑÑ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не продавать ÑпиÑки Ñлектронных адреÑов или личную информацию пользователей и обÑзуемÑÑ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не производить неÑанкционированные раÑÑылки от третьих лиц. + +/site/contract.bml.promise.uptime=Ðадёжно поддерживать ÑиÑтему в рабочем ÑоÑтоÑнии в пределах техничеÑких возможноÑтей + +/site/contract.bml.promise.uptime.about=Мы ÑтараемÑÑ, чтобы ÑÐµÑ€Ð²Ð¸Ñ Ð±Ñ‹Ð» доÑтупен вÑем в любое времÑ, оÑобенно потому, что мы и Ñами им пользуемÑÑ. К Ñожалению, завиÑÐ°Ð½Ð¸Ñ Ñерверов неизбежны, но мы ÑтараемÑÑ Ð½Ð°Ð¸Ð»ÑƒÑ‡ÑˆÐ¸Ð¼ образом Ñпланировать работу ÑиÑтемы, чтобы избежать их. + +/site/contract.bml.promisetoyou=Мы, команда Живого Журнала, ÑтараемÑÑ, чтобы каждому человеку было приÑтно пользоватьÑÑ Ð½Ð°ÑˆÐ¸Ð¼ ÑервиÑом, поÑтому мы Ñобрали ÑпиÑок обÑзательÑтв, которые вÑегда будут ÑоблюдатьÑÑ. + +/site/contract.bml.promisetoyou.header=Ðаши обÑзательÑтва + +/site/contract.bml.title=ОбщеÑтвенный договор + +/site/goat.bml.image.alt=Козёл ФрÑнк, талиÑман Живого Журнала. + +/site/goat.bml.image.caption="Ме-е-е," – Ñказал ФрÑнк. + +/site/goat.bml.meet.body=Это ФрÑнк, талиÑман Живого Журнала. Иногда он помогает нам Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ¼, еÑли Ñами мы не уÑпеваем, иногда отвечает на запроÑÑ‹ в Ñлужбу техничеÑкой поддержки. ФрÑнк универÑален... иногда он даже работает по дому. Когда трава на лужайке выраÑтает Ñлишком выÑокой, доÑтаточно намекнуть: "Эй, ФрÑнк! Пода обедать! Обглодай-ка газон!". И вÑе довольны. + +/site/goat.bml.meet.header=ПознакомьтеÑÑŒ Ñ Ð¤Ñ€Ñнком + +/site/goat.bml.title=Козёл ФрÑнк + +/styles/create.bml.choosebase=Выберите начальный Ñтиль, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ вы начнете и редактируйте: + +/styles/create.bml.createstyle.head=Создать Ñтиль + +/styles/create.bml.createstyle.text=ЗдеÑÑŒ вы можете Ñоздать ваш ÑобÑтвенный Ñтиль, который может быть вÑтроен в ваш журнал на вашей домашней Ñтранице или, еÑли хотите, Ñделан общедоÑтупнум Ñтилем и иÑпользован другими людьми. Вам придетÑÑ Ñ€Ð°Ð±Ð¾Ð°Ñ‚ÑŒ здеÑÑŒ, а не в Ñекции перекрывающихÑÑ ÐºÐ¾Ð´Ð¾Ð². Только пользователи Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¼ аккaунтом могут Ñоздавать ÑобÑтвенные Ñтили. + +/styles/create.bml.enterstyleid=Или введите номер внеÑиÑтемного общедоÑтупного ÑÑ‚Ð¸Ð»Ñ (ID): + +/styles/create.bml.noneorother=(Ðикакой или один из перечиÑленных ниже:) + +/styles/create.bml.selecttype.head=Выберите тип ÑÑ‚Ð¸Ð»Ñ + +/styles/create.bml.submit=Создать Ñтиль + +/styles/create.bml.title=Создать Ñтиль + +/styles/create_do.bml.editstyle<< +Редактировать Ñтиль +Редактировать Ñтиль +. + +/styles/create_do.bml.error.accounttype=Тип вашего аккунта не позволÑет вам Ñоздавать новые Ñтили + +/styles/create_do.bml.error.invalidview=Ð’Ñ‹ не выбрали правильный тип ÑÑ‚Ð¸Ð»Ñ + +/styles/create_do.bml.error.stylenotfound=Стиль, на котором вы базируете Ñвой новый Ñтиль ([[baseid]]), не ÑущеÑтвует + +/styles/create_do.bml.error.stylenotpublic=Стиль, на котором вы базируете Ñвой новый Ñтиль ([[baseid]]), не общедоÑтупный, вы не можете его Ñкопировать. + +/styles/create_do.bml.success.head=ПолучилоÑÑŒ + +/styles/create_do.bml.success.text=Ваш Ñтиль Ñоздан и временоо назван [[des]]. Ð’Ñ‹ можете начать его редактирование нажатием клавиши внизу + +/styles/create_do.bml.title=Создать Ñтиль + +/styles/index.bml.about<< +

            Данный раздел Ñайта позволÑет Ñоздавать, редактировать и удалÑÑ‚ÑŒ наÑтраиваемые Ñтили S1. Это позволÑет изменить вид вашего журнала, в ÑоответÑтвии Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ потребноÑÑ‚Ñми. Ð’Ñ‹ можете Ñделать журнал неотличимым от Ñвоего Ñайта или проÑто Ñделать его отличным от других журналов.

            + +

            Ð’Ñ‹ можете Ñоздать вÑтраиваемые Ñтили, которые позволÑÑŽÑ‚ добавить только запиÑи из журнала Ð´Ð»Ñ Ð²ÑÑ‚Ñ€Ð°Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° в другой Ñайт, вмеÑто ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ Ñтраницы.

            + +

            Больше информации о ÑиÑтеме Ñтилей, вы прочитаете в документации по ÑтилÑм из +раздела Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð².

            + +

            Обратите внимание, что только платные пользователи +могут Ñоздавать и иÑпользовать Ñвои Ñтили. БеÑплатные пользователи могут выбрать один из Ñтандартных Ñтилей Живого Журнала, Ñделать Ñто можно на Ñтранице +Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð–ÑƒÑ€Ð½Ð°Ð»Ð°.

            +. + +/styles/index.bml.about.header=Создание и иÑпользование наÑтраиваемых Ñтилей + +/styles/index.bml.nav.browse=ПроÑмотрщик Ñтилей + +/styles/index.bml.nav.browse.about=ПроÑмотрщик Ñтилей позволÑет проÑмотреть открытые Ñтили, Ñозданные другими пользователÑми. + +/styles/index.bml.nav.create=Создать новый Ñтиль + +/styles/index.bml.nav.create.about=Создание нового ÑÑ‚Ð¸Ð»Ñ "Ñ Ð½ÑƒÐ»Ñ" или на оÑнове одного из ÑущеÑтвующих открытых Ñтилей. + +/styles/index.bml.nav.edit=Редактирование или Удаление ÑущеÑтвующего ÑÑ‚Ð¸Ð»Ñ + +/styles/index.bml.nav.edit.about=Ð’Ñ‹ можете редактировать только ÑобÑтвенные Ñтили. Чтобы изменить ÑиÑтемный Ñтиль, вы Ñначала должны Ñоздать ÑобÑтвенный Ñтиль, оÑнованный на одном из ÑиÑтемных Ñтилей. + +/styles/index.bml.nav.modify=Изменение вашего аккаунта + +/styles/index.bml.nav.modify.about=Измените Ñтиль по умолчанию Ð´Ð»Ñ Ñвоего аккаунта, в одной из ÑиÑтем готовых Ñтилей. + +/styles/index.bml.title=ÐаÑтраиваемые Ñтили + +/suggestions/index.bml.howto.text<< +
            +
            Проверьте предшеÑтвующие предложениÑ
            +Вначале, прочитайте предыдущие предложениÑ, чтобы удоÑтоверитьÑÑ, что что-то подобное не предлагалоÑÑŒ ранее. ЕÑли такое предложение было, вы можете прочитать комментарии к Ñтой запиÑи. Иногда, какое-то предложение может выглÑдеть как проигнорированное, но на Ñамом деле мы над ним работаем. Иногда идеи отклонÑÑŽÑ‚ÑÑ Ð¸Ð»Ð¸ откладываютÑÑ Ð¸Ð·-за других дел. +
            +
            Ðе можете найти Ñвою идею? ПоделитеÑÑŒ ею Ñ Ð½Ð°Ð¼Ð¸!
            +Шаблон должен иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ñех предложений. УбедитеÑÑŒ, что заполнили вÑе Ð¿Ð¾Ð»Ñ Ð² шаблоне, а также проверьте правильноÑÑ‚ÑŒ заполнениÑ, прежде чем отправить предложение. Генератор предложений не добавлÑет переводы Ñтрок автоматичеÑки, поÑтому вы должны иÑпользовать Ñ‚Ñг <br> Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ð¾Ð´Ð° Ñтроки. Это Ñделает ваше предложение более легким Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ.
            +
            Отправьте Его!
            +Ð’Ñ‹ можете добавить ÑообщеÑтво в Ñвой ÑпиÑок Друзей здеÑÑŒ. Как только предложение отправлено, люди начинают его обÑуждать. ЕÑли нам понравитÑÑ Ñта идеÑ, мы добавим её в ÑпиÑок проектов разработчиков и начнем работать, как только поÑвитÑÑ Ð²Ñ€ÐµÐ¼Ñ. Ðе вÑе Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾ÑущеÑтвлÑÑŽÑ‚ÑÑ Ð½ÐµÐ¼ÐµÐ´Ð»ÐµÐ½Ð½Ð¾, поÑтому наберитеÑÑŒ терпениÑ. +
            +. + +/suggestions/index.bml.howto.title=Как мне внеÑти Ñвоё предложение? + +/suggestions/index.bml.info.text<< +ЧувÑтвуете, что можете оказать помощь в оÑущеÑтвлении Ñвоих предложений? Ðе ÑтеÑнÑйтеÑÑŒ 'наблюдать' или приÑоединÑÑ‚ÑŒÑÑ Ðº ÑообщеÑтвам ниже: +
            +
            Форум разработчиков Живого Журнала -- разговоры про техничеÑкие детали.
            +
            +
            БизнеÑ-форум Живого Журнала -- разговоры о возможноÑÑ‚ÑÑ… бизнеÑа Живого Журнала и ÑвÑзанных облаÑÑ‚ÑÑ….
            +
            +
            Форум по документации Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала -- обÑуждение и редактирование большинÑтва форм документации Ð´Ð»Ñ ÐºÐ¾Ð½ÐµÑ‡Ð½Ð¾Ð³Ð¾ пользователÑ.
            +
            +
            ХудожеÑтвенный форум Живого Журнала -- обÑуждение и раÑпроÑтранение иконок, тем наÑтроений, цветовых тем и картинок пользователей.
            +
            +
            +ПожалуйÑта помните, что люди, оÑущеÑтвлÑющие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð² Живом Журнале, такие же как и вы. ОÑущеÑтвление предложений требует времени, и чем больше вы нам будете помогать, тем больше мы Ñможем Ñделать. +. + +/suggestions/index.bml.info.title=ОÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +/suggestions/index.bml.rules<< +ПожалуйÑта, имейте в виду что: +
              +
            • Многие Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑƒÐ¶Ðµ Ñделаны и обÑуждаютÑÑ, но еще не воплощены в реальноÑÑ‚ÑŒ. УбедитеÑÑŒ, что не повторÑете чью-то идею. +
            • Личные оÑÐºÐ¾Ñ€Ð±Ð»ÐµÐ½Ð¸Ñ (флейм) будут удалены. Каждый человек имеет Ñвоё мнение о том, как должен выглÑдить Живой Журнал; помните, что продвижение вашего Ð¼Ð½ÐµÐ½Ð¸Ñ - абÑолютно нормально, но оÑкорбление чужого Ð¼Ð½ÐµÐ½Ð¸Ñ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтимо. +
            • ОпиÑывайте Ñвоё предложение наиболее детально. Предложение, Ñодержащее наиболее детальную информацию о его воплощении, будет оÑущеÑтвлено Ñ Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ вероÑтноÑтью, чем предложение, не имеющее детального опиÑаниÑ. Ð’Ñ‹ необÑзательно должны знать, как оÑущеÑтвить Ñто техничеÑки; попробуйте поразмыÑлить, что затронет ваше предложение и какие проблемы могут возникнуть. +
            • УбедитÑÑŒ, что прочитали Ñправку, чтобы узнать какие идеи уже воплощены или какие чаÑти Ñайта могут иÑпользоватьÑÑ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… нужд. +
            • ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð¿Ð¾ функционированию Живого Журнала, вы не уверены в ÑущеÑтвовании какой-то возможноÑти или ÑтолкнулиÑÑŒ Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¾Ð¹ - не отправлÑйте предложение. ВмеÑто Ñтого ÑпроÑите Центр поддержки. +
            +. + +/suggestions/index.bml.title=МеÑто Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹ + +/suggestions/index.bml.welcome.text=ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ -- Ð²Ð°Ð¶Ð½Ð°Ñ ÑˆÑ‚ÑƒÐºÐ° Ð´Ð»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала. ЕÑли у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ дельные предложениÑ, то пройдите Ñти процедуры, чтобы привлечь внимание разработчиков Ñтого Ñайта. + +/suggestions/index.bml.welcome.title=Добро пожаловать! + +/support/append_request.bml.back.requests=ВернутьÑÑ Ðº ÑпиÑку проÑьб. + +/support/append_request.bml.back.support=ВернутьÑÑ Ð² Поддержку. + +/support/append_request.bml.bounce.noemail=Ðе указан email Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + +/support/append_request.bml.bounce.notauth=Ð’Ñ‹ не имеете права перенаправить Ñтот Ð·Ð°Ð¿Ñ€Ð¾Ñ + +/support/append_request.bml.bounce.toomany=Ð’Ñ‹ можете отправить Ñообщение макÑимум по пÑти адреÑам. Ð’Ñ‹ указали больше пÑти. + +/support/append_request.bml.bounced.success= + +/support/append_request.bml.closed.text=Эта проÑьба о помощи уже закрыта + +/support/append_request.bml.closed.title=Закрыто + +/support/append_request.bml.internal.approve=Чтобы утвердить ответ, вам нужно выбрать "Internal Comment / Action" и, желательно, обьÑÑнить, почему вы утвердили ответ. + +/support/append_request.bml.internal.changecat=Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ð¸, в которую отнеÑена проÑьба, вам нужно выбрать "Internal Comment / Action" и, желательно, обьÑÑнить, почему вы ее изменÑете. + +/support/append_request.bml.internal.changesum=Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÑ€Ð°Ñ‚ÐºÐ¾Ð³Ð¾ Ð¸Ð·Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñьбы, вам нужно выбрать "Internal Comment / Action" и ввеÑти новое изложение. + +/support/append_request.bml.internal.touch=Чтобы изменить ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð°Ð¿Ñ€Ð¾Ñа, вам нужно выбрать "Internal Comment / Action" и объÑÑнить, зачем вы его менÑете. + +/support/append_request.bml.invalid.blank=Ваша запиÑÑŒ пуÑтаÑ. ПожалуйÑта, напишите хоть что-нибудь в теле пиÑьма. + +/support/append_request.bml.invalid.noanswer=Ðа утверждение был направлен неправильный Ñкрытый ответ. + +/support/append_request.bml.invalid.nocat=Эта ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ Ð½Ðµ ÑущеÑтвует + +/support/append_request.bml.invalid.noid=Ð”Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñтого Ð´ÐµÐ¹Ñ‚Ð²Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼ идентификационный номер проÑьбы о техничеÑкой поддержке. + +/support/append_request.bml.invalid.type=Ðеправильный тип ответа + +/support/append_request.bml.logged.text=Ваше дейÑтвие/комментарий/ответ зарегиÑтрирован. СпаÑибо. + +/support/append_request.bml.logged.title=Сделано + +/support/append_request.bml.login.required=Чтобы помочь другим, вы должны login + +/support/append_request.bml.successlinks<< + +. + +/support/append_request.bml.title=Изменить комментарий/ответ + +/support/append_request.bml.unknown.request=ÐеизвеÑтный тип запроÑа техничеÑкой поддержки + +/support/encodings.bml.edit.header=Я не могу редактировать Ñвои запиÑи через веб-интерфейÑ! + +/support/encodings.bml.edit.text<< +Кратко: (Ð´Ð»Ñ Ñ‚ÐµÑ…, кто ведёт журнал по-руÑÑки): Зайдите на +Ñтраницу личных наÑтроек. Внизу Ñтраницы найдите наÑтройку под названием ÐвтоматичеÑки перекодировать Ñтарые запиÑи из кодировки. Выберите +из выпадающего ÑпиÑка "Cyrillic (Windows)" и Ñохраните наÑтройки. ПоÑле Ñтого ваши запиÑи должны редактироватьÑÑ ÑƒÑпешно. p?> + +Подробно: Чтобы разрешить редактирование Ñтарой неюникодной запиÑи, Живой Журнал должен знать в какой кодировке Ñта запиÑÑŒ была Ñделана. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹, пишущих по-английÑки или на других западноевропейÑких Ñзыках, Ñта кодировка, как правило, "Western European (Windows)", но еÑли кавычки и другие мета-Ñимволы показываютÑÑ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾, попробуйте "Western European (ISO)". Пользователи, пишущие на других Ñзыках, должны выбрать Ñвою кодировку; Ð´Ð»Ñ Ñ€ÑƒÑÑкоÑзычных пользователей Ñто Ñкорее вÑего "Cyrillic (Windows)", возможно "Cyrillic (KOI8)"; еÑли Ð½ÑƒÐ¶Ð½Ð°Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ° отÑутÑтвует в предложенном ÑпиÑке, обратитеÑÑŒ в Ñлужбу поддержки и объÑÑните проблему. p?> + + + +. + +/support/encodings.bml.editcl.header=Я не могу редактировать запиÑи через клиентÑкую программу! + +/support/encodings.bml.editcl.text= + +/support/encodings.bml.groups.header=Я не могу редактировать ÑпиÑок друзей в клиентÑкой программе! + +/support/encodings.bml.groups.text<< +Ñтранице Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¿, чтобы оÑтавить в названиÑÑ… только ASCII Ñимволы, а затем воÑпользоватьÑÑ Ð¸Ð¼ÐµÑŽÑ‰ÐµÐ¹ÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ñкой программой. p?> + +. + +/support/encodings.bml.overview.header=К чему Ñто вÑÑ‘? + +/support/encodings.bml.overview.text<< + + + +. + +/support/encodings.bml.still.header=По-прежнему в затруднении? + +/support/encodings.bml.still.text=Службе поддержки. p?> + +/support/encodings.bml.title=Кодировки + +/support/faqbrowse.bml.backfaq=ВернутьÑÑ Ð½Ð° Ñтраницу вопроÑов и ответов. + +/support/faqbrowse.bml.backfaqcat=Перейти на уровень выше. + +/support/faqbrowse.bml.backsupport=ВернутьÑÑ Ð² раздел "Помощь". + +/support/faqbrowse.bml.edit.faq=Править Ñту Ñправку + +/support/faqbrowse.bml.error.nofaq=Такого вопроÑа в Справке ЖЖ нет. + +/support/faqbrowse.bml.lastupdated=ПоÑледний раз обновлен: + +/support/faqbrowse.bml.title_cat=Справка - [[catname]] + +/support/faqbrowse.bml.title_num=Ð’Ð¾Ð¿Ñ€Ð¾Ñ Ð½Ð¾Ð¼ÐµÑ€ [[num]] + +/support/help.bml.interim<< + + + + +Getting +Started category in HelpScreening's memories +is an especially good place for new +volunteers to get information. p?> + + + +
            • Be professional and courteous.
            • +
            • Don't contact people submitting requests outside the Support +board to discuss their request or give them information.
            • +
            • Keep information in Support requests private.
            • +
            • Don't copy other people's answers.
            + + + +, but +please wait until there is an approved answer in the request. p?> + + + + + +Support +board. p?> +. + +/support/see_overrides.bml.error.noprivs=Только пользователи Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸Ñми supportviewscreened или supporthelp privilege могут увидеть перекрывающие коды других пользователей. + +/support/see_overrides.bml.error.nos1=Этот пользователь не иÑпользует S1. + +/support/see_overrides.bml.header=Перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ : + +/support/see_overrides.bml.nooverrides=Пользователь не иÑпользует перекрывающие коды. + +/support/see_overrides.bml.title=Перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/syn/index.bml.account=Ðккаунт + +/syn/index.bml.add=Добавить ленту + +/syn/index.bml.add.byurl.text=Добавить транÑлируемую ленту к ÑпиÑку друзей, впечатав веб-Ð°Ð´Ñ€ÐµÑ Ð»ÐµÐ½Ñ‚Ñ‹ внизу: + +/syn/index.bml.add.byurl.title=Добавить транÑлируемую ленту по веб-адреÑу + +/syn/index.bml.add.pop.text=Ðекоторые популÑрные ленты, за которыми вы не Ñледите + +/syn/index.bml.add.pop.title=Добавить популÑрную ленту + +/syn/index.bml.add.selected=Добавить выбранное + +/syn/index.bml.back=Обратно + +/syn/index.bml.create=Создать транÑлируемую ленту + +/syn/index.bml.create.name=Добавленный веб-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ транÑлируетÑÑ Ñайтом. Ðапишите название аккаунта, который будет иÑпользован Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½ÑÐ»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ ленты. + +/syn/index.bml.error.nocreate=Добавленный веб-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ транÑлируетÑÑ Ñайтом. Ваш тип аккаунта не позволÑет Ñоздавать новые транÑлируемые ленты. + +/syn/index.bml.error.unknown=ÐеизвеÑтный тип ошибки + +/syn/index.bml.feed.url=Интернет-Ð°Ð´Ñ€ÐµÑ Ñ‚Ñ€Ð°Ð½Ñлируемого потока + +/syn/index.bml.invalid.accountname=Ðеправильное название журнала + +/syn/index.bml.invalid.cantadd=Ð’Ñ‹ не можете добавить RSS-поток Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñайта + +/syn/index.bml.invalid.http.text=Удалить комментарий + +/syn/index.bml.invalid.http.title=Ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ + +/syn/index.bml.invalid.inuse.text=Это название журнала уже иÑпользуетÑÑ + +/syn/index.bml.invalid.inuse.title=Это Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ иÑпользуетÑÑ + +/syn/index.bml.invalid.needname.text=Чтобы добавить транÑлируемый аккаунт, который пока не открыт, вернитеÑÑŒ и дайте ему название + +/syn/index.bml.invalid.needname.title=Ðеобходимо название аккунта + +/syn/index.bml.invalid.needurl=Ðужно ввеÑти Ð¸Ð¼Ñ Ñ‚Ñ€Ð°Ð½Ñлируемого аккаунта или Ð°Ð´Ñ€ÐµÑ Ñ‚Ñ€Ð°Ð½Ñлируемой ленты Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾. + +/syn/index.bml.invalid.notexist=ТранÑлируемого аккаунта Ñ Ñ‚Ð°ÐºÐ¸Ð¼ названием не ÑущеÑтвует + +/syn/index.bml.invalid.notrss.text=Заданный интернет-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ Ñодержит данных в формате XML + +/syn/index.bml.invalid.notrss.title=Данные не в формате XML + +/syn/index.bml.invalid.port=ÐеÑтандартный номер порта не разрешен + +/syn/index.bml.invalid.reserved=ÐедопуÑтимое название аккаунта. ПожалуйÑта, выберите другое нзвание. + +/syn/index.bml.invalid.submission=ÐÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° переÑылки + +/syn/index.bml.invalid.url=ÐдреÑ, который вы ввели — ошибочный. Проверьте URL, который вы ввели и попробуйте Ñнова. + +/syn/index.bml.loginrequired.text=Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñвоими транÑлируемыми аккаунтами, Ñначала нужно Войти. + +/syn/index.bml.loginrequired.title=Введите пароль + +/syn/index.bml.promo.text=ЕÑли вы хотите увидеть ÑпиÑок транÑлируемых журналов, которые пользователи когда-то рекламировали, вы можете открыть, , где помещаютÑÑ Ð¾Ð±ÑŒÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¾ Ñоздаваеых и наблюдаемых лентах + +/syn/index.bml.remove=Удалить отмеченное + +/syn/index.bml.table.account=Ðккаунт + +/syn/index.bml.table.feed=Лента + +/syn/index.bml.table.watchers=ЧиÑло читателей + +/syn/index.bml.title=ТранÑлÑÑ†Ð¸Ñ + +/syn/index.bml.user.nomatch=Данные автора ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð½Ðµ Ñовпадают Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ заполнившего анкету. + +/syn/index.bml.using.text=ЗдеÑÑŒ вы можете добавить транÑлируемые ленты (RSS) Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… Ñайтов к вашему ÑпиÑку друзей, и вам больше не нужно будет поÑещать деÑÑтки Ñайтов каждый день. + +/syn/index.bml.using.title=ИÑпользовать [[sitename]] Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² транÑлируемую ленту + +/syn/list.bml.error.nofeeds=Ошибка: Ðе один из транÑлируемых потоков не обновлÑлÑÑ Ð² течение поÑледних Ñуток. + +/syn/list.bml.feeddesc=ОпиÑание ленты + +/syn/list.bml.feedurl=ÐÐ´Ñ€ÐµÑ Ð»ÐµÐ½Ñ‚Ñ‹ + +/syn/list.bml.numreaders=ЧиÑло читателей + +/syn/list.bml.title=ТранÑлируемые аккаунты + +/syn/list.bml.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +/syn/list.bml.xml_icon.alt=[Смотреть иÑходный поток] + +/talkmulti.bml.deleted.body=Комментарии были удалены. Ð’Ñ‹ можете увидеть оÑтавшиеÑÑ Ð·Ð´ÐµÑьздеÑьздеÑькартинкой: + +/talkpost.bml.loganonip=Обратите внимание! Этот пользователь включил опцию ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ IP-адреÑов тех, кто пишет анонимно. + +/talkpost.bml.loginq=Войти? + +/talkpost.bml.logyourip=Обратите внимание! Этот пользователь включил опцию ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ IP-адреÑов пишущих комментарии к его журналу. + +/talkpost.bml.nosubjecthtml=HTML Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в теме ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ + +/talkpost.bml.opt.anonymous=анонимно + +/talkpost.bml.opt.defpic=(по умолчанию) + +/talkpost.bml.opt.friendsonly=- Ñтот пользователь отключил возможноÑÑ‚ÑŒ пиÑать к его журналу комментарии вÑем не-друзьÑм или анонимно. Ð’Ñ‹ Ñможете пиÑать здеÑÑŒ еÑли [[username]] включит Ð²Ð°Ñ Ð² Ñвои друзьÑ. + +/talkpost.bml.opt.from=Как: + +/talkpost.bml.opt.ljuser=пользователь ЖЖ: + +/talkpost.bml.opt.loggedin=как [[username]] + +/talkpost.bml.opt.message=Сообщение: + +/talkpost.bml.opt.noanonpost=- Ñтот пользователь отключил возможноÑÑ‚ÑŒ пиÑать комментарии анонимно + +/talkpost.bml.opt.noautoformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/talkpost.bml.opt.noimage=Без значка + +/talkpost.bml.opt.preview=Предварительный проÑмотр + +/talkpost.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/talkpost.bml.opt.subject=Тема: + +/talkpost.bml.opt.submit=Добавить комментарий + +/talkpost.bml.opt.willscreen=(комментарий будет Ñкрыт) + +/talkpost.bml.opt.willscreenfriend=(комментарий будет Ñкрыт, еÑли вы не в ÑпиÑке друзей) + +/talkpost.bml.paraformat=По умолчанию текÑÑ‚ будет отформатирован. + +/talkpost.bml.postresponse=Добавить комментарий: + +/talkpost.bml.title=Добавление ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/talkpost.bml.usermismatch<< +Ð’Ñ‹ ввели Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, но не выбрали режим "пользователь ЖЖ". + +ПожалуйÑта, либо очиÑтите поле имени, либо выберите нужный режим и попробуйте Ñнова. +. + +/talkpost.bml.warnscreened=Внимание: Этот комментарий Ñкрыт. ÐžÑ‚Ð²ÐµÑ‡Ð°Ñ Ð½Ð° него, вы автоматичеÑки раÑкроете его и Ñделаете видимым. + +/talkpost_do.bml.error.badpassword=Введённый Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ неверен. ЕÑли вы забыли Ñвой пароль, то можете воÑÑтановить его здеÑÑŒ. + +/talkpost_do.bml.error.badusername=Указанный пользователь Живого Журнала не ÑущеÑтвует. ЕÑли вы забыли Ñвоё Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, вы можете воÑÑтановить его здеÑÑŒ или вы можете оÑтавить комментарий анонимно. + +/talkpost_do.bml.error.banned=Ð’Ñ‹ не можете пиÑать комментарии в журнале Ñтого пользователÑ. + +/talkpost_do.bml.error.blankmessage=Ваше Ñообщение пуÑто. ПожалуйÑта, введите хоть что-нибудь в поле ÑообщениÑ. + +/talkpost_do.bml.error.confused_identity=Ð’Ñ‹ ввели Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, но выбрали режим анонимного ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ Ð¸Ð»Ð¸ как текущий пользователь. ВернитеÑÑŒ назад и решите, как вы вÑÑ‘-таки хотите отправить комментарий. + +/talkpost_do.bml.error.deleted=Ваш журнал был удален. Ð’Ñ‹ не можете пиÑать ÑообщениÑ. + +/talkpost_do.bml.error.friendsonly=Только Ð´Ñ€ÑƒÐ·ÑŒÑ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]] могут оÑтавлÑÑ‚ÑŒ запиÑи в Ñтом журнале. + +/talkpost_do.bml.error.lostcookie=КажетÑÑ, ваш cookie Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ЖЖ потерÑлÑÑ. + +/talkpost_do.bml.error.manybytes=Извините, но длина вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ ([[current]]) превыÑила макÑимальную длину в байтах ([[limit]]). ПожалуйÑта, вернитеÑÑŒ назад, укоротите его и попробуйте ещё раз. + +/talkpost_do.bml.error.manychars=Извините, но длина вашего ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ ([[current]]) превыÑила макÑимальную длину в Ñимволах ([[limit]]). ПожалуйÑта, вернитеÑÑŒ назад, укоротите его и попробуйте ещё раз. + +/talkpost_do.bml.error.mustlogin=Чтобы оÑтавить комментарий к Ñтой защищённой запиÑи, вы должны войти под Ñвоим именем и паролем. + +/talkpost_do.bml.error.noanon=Ð’Ñ‹ не можете оÑтавлÑÑ‚ÑŒ анонимные комментарии в Ñтом журнале. + +/talkpost_do.bml.error.noauth=Вам запрещено оÑтавлÑÑ‚ÑŒ комментарии к Ñтой защищённой запиÑи. + +/talkpost_do.bml.error.nocomments=Ðвтор запретил комментировать Ñту запиÑÑŒ. + +/talkpost_do.bml.error.noparent=ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð²ÐµÑ‚Ð¸Ñ‚ÑŒ на неÑущеÑтвующий комментарий. + +/talkpost_do.bml.error.notafriend=Извините, пользователь [[user]] не добавил Ð²Ð°Ñ Ð² Ñвой ÑпиÑок друзей, а оÑтавлÑÑ‚ÑŒ комментарии в его журнале могут только друзьÑ. + +/talkpost_do.bml.error.nousername=Ð’Ñ‹ не ввели никакого имени Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала. ЕÑли у Ð²Ð°Ñ Ð½ÐµÑ‚ Ñвоего аккаунта в Живом Журнале, вы можете оÑтавить комментарий анонимно. + +/talkpost_do.bml.error.noverify=Извините, но вы не можете оÑтавлÑÑ‚ÑŒ комментарии в чужих журналах, пока ваш Ð°Ð´Ñ€ÐµÑ e-mail не проверен. ЕÑли вы потерÑли пиÑьмо подтверждениÑ, вы можете повторно поÑлать его Ñебе. + +/talkpost_do.bml.error.postshared=Ð’Ñ‹ не можете оÑтавлÑÑ‚ÑŒ комментарии под ÑовмеÑтно иÑпользуемым именем или именем ÑообщеÑтва. СовмеÑтно иÑпользуемые аккаунты предÑтавлÑÑŽÑ‚ группу людей, а не отдельного человека. + +/talkpost_do.bml.error.screened=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав отвечать на Ñтот Ñкрытый комментарий. + +/talkpost_do.bml.error.suspended=Ваш журнал заморожен. Ð’Ñ‹ не можете оÑтавлÑÑ‚ÑŒ комментарии. + +/talkpost_do.bml.error.testacct=ТеÑтовые аккаунты можно иÑпользовать только в теÑтовых журналах. + +/talkpost_do.bml.opt.preview=Предварительный проÑмотр + +/talkpost_do.bml.preview=Вот как будет выглÑдеть ваш комментарий. Ð’Ñ‹ можете продолжить его редактирование в форме внизу Ñтраницы, или отправить в текущем виде. + +/talkpost_do.bml.preview.subject=Тема: + +/talkpost_do.bml.preview.submit=Отправить + +/talkpost_do.bml.preview.title=ПроÑмотр + +/talkpost_do.bml.success.loggedin=Ð’Ñ‹ вошли в ЖЖ. + +/talkpost_do.bml.success.message=Ваш комментарий добавлен. Ð’Ñ‹ можете поÑмотреть его здеÑÑŒ. + +/talkpost_do.bml.success.screened.comm=Ваш комментарий добавлен. СоглаÑно наÑтройкам Ñтого ÑообщеÑтва, он был помечен как Ñкрытый и будет виден только вам и ÑмотрителÑм ÑообщеÑтва, пока они не решат его раÑкрыть. Ð’Ñ‹ можете увидеть Ñвой комментарий здеÑÑŒ. + +/talkpost_do.bml.success.screened.comm.anon=Ваш анонимный комментарий был добавлен. СоглаÑно правилам данного ÑообщеÑтва, он был Ñкрыт и будет видим только ÑмотрителÑм ÑообщеÑтва до тех пор, пока они не решат раÑкрыть его. Ð’Ñ‹ можете вернутьÑÑ Ðº ветке обÑуждениÑ. + +/talkpost_do.bml.success.screened.user=Ваш комментарий добавлен. СоглаÑно наÑтройкам Ñтого журнала, он был помечен как Ñкрытый и будет виден только вам и хозÑину журнала, пока он не решит его раÑкрыть. Ð’Ñ‹ можете увидеть Ñвой комментарий здеÑÑŒ. + +/talkpost_do.bml.success.screened.user.anon=Ваш анонимный комментарий был добавлен. СоглаÑно наÑтройкам данного журнала, он был Ñкрыт и будет видим только владельцу журнала до тех пор, пока он не решит раÑкрыть его. Ð’Ñ‹ можете вернутьÑÑ Ðº ветке обÑуждениÑ. + +/talkpost_do.bml.success.title=Сообщение уÑпешно добавлено + +/talkpost_do.bml.success.unscreened=Кроме того, Ñкрытый комментарий, на который вы отвечали, теперь раÑкрыт и будет виден вÑем. + +/talkpost_do.bml.title=Комментарий добавлен + +/talkpost_do.bml.title.error=Комментарий не был добавлен + +/talkpost_do.bml.title.preview=Предварительный проÑмотр ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸Ñ + +/talkread.bml.anonuser=(Ðнонимно) + +/talkread.bml.confirm.action=Ð’Ñ‹ уверены, что хотите удалить выделенные комментарии? + +/talkread.bml.deletedpost=(Комментарий удалён) + +/talkread.bml.deleteduser=(Пользователь [[username]] удалён) + +/talkread.bml.fromip=(от [[ip]]) + +/talkread.bml.noreplies=Комментариев нет + +/talkread.bml.nosubject=(без темы) + +/talkread.bml.replysuspended=(Ответ от Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ð¼ аккаунтом) + +/talkread.bml.screenedpost=(Скрытый комментарий) + +/talkread.bml.select=Выбрать + +/talkread.bml.subjectdeleted=[удалено] + +/talkread.bml.talkmulti.delete=Удалить + +/talkread.bml.talkmulti.des=Ð“Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð°Ð´ выбранными комментариÑми: + +/talkread.bml.talkmulti.screen=Скрыть + +/talkread.bml.talkmulti.submit=Выполнить + +/talkread.bml.talkmulti.unscreen=РаÑкрыть + +/talkread.bml.title=Комментарии + +/talkscreen.bml.error.login=Чтобы работать Ñо Ñкрытыми комментариÑми, вы должны войти под Ñвоим именем и паролем. + +/talkscreen.bml.error.privs.screen=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав Ñкрывать Ñтот комментарий. + +/talkscreen.bml.error.privs.unscreen=У Ð²Ð°Ñ Ð½ÐµÑ‚ прав раÑкрывать Ñтот комментарий. + +/talkscreen.bml.screen.doit=Да, Ñкрыть Ñтот комментарий + +/talkscreen.bml.screen.sure.body=Ð’Ñ‹ уверены, что хотите Ñкрыть Ñтот комментарий? + +/talkscreen.bml.screen.sure.title=Скрыть Ñтот комментарий? + +/talkscreen.bml.screened.body=Комментарий Ñкрыт. Ð’Ñ‹ можете его увидеть here. + +/talkscreen.bml.screened.title=Ð’Ñе в порÑдке! + +/talkscreen.bml.title=Скрытый комментарий + +/talkscreen.bml.unscreen.doit=Да, раÑкрыть Ñтот комментарий + +/talkscreen.bml.unscreen.sure.body=Ð’Ñ‹ уверены, что хотите раÑкрыть Ñтот комментарий? + +/talkscreen.bml.unscreen.sure.title=РаÑкрыть Ñтот комментарий? + +/talkscreen.bml.unscreened.body=Комментарий раÑкрыт. Ð’Ñ‹ можете его увидеть здеÑÑŒ. + +/talkscreen.bml.unscreened.title=Ð’Ñе в порÑдке! + +/tools/emailmanage.bml.address.current.title=Текущий Ð°Ð´Ñ€ÐµÑ + +/tools/emailmanage.bml.address.old.none=Ðет адреÑа + +/tools/emailmanage.bml.address.old.text=Ðиже Ñледует ÑпиÑок адреÑов, которые иÑпользовалиÑÑŒ вашим журналом, и даты, когда они переÑтавали быть оÑновным адреÑом. Пометьте те из них, которые вы хотели бы удалить. + +/tools/emailmanage.bml.address.old.title=Предыдущие адреÑа + +/tools/emailmanage.bml.delete_selected=Удалить выбранные + +/tools/emailmanage.bml.desc.notfirst=Ðа Ñтой Ñтранице вы можете удалить только те адреÑа e-mail, которые иÑпользовалиÑÑŒ поÑле того, как вы подтвердили Ñвой текущий адреÑ. Ð’ чаÑтноÑти Ñто означает, что злоумышленник не Ñможет удалить ваш Ñамый первый адреÑ. + +/tools/emailmanage.bml.desc.text=Ðа Ñтой Ñтранице вы можете удалить адреÑа e-mail, которые иÑпользовалиÑÑŒ вашим журналом. Ðа удалённые адреÑа больше Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ выÑлать забытый пароль. Это может помочь, еÑли кто-то узнал ваш пароль и приÑвоил ваш журнал. ПроÑто запроÑите новый пароль на ваш Ñтарый Ð°Ð´Ñ€ÐµÑ e-mail, измените его обратно на Ñвой и удалите Ð°Ð´Ñ€ÐµÑ e-mail злоумышленника. + +/tools/emailmanage.bml.desc.title=ОпиÑание + +/tools/emailmanage.bml.log.deleted=Удалён: [[email]] @ [[time]] + +/tools/emailmanage.bml.log.deleted.title=Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñохранены + +/tools/emailmanage.bml.notvalidated.text=Ваш текущий Ð°Ð´Ñ€ÐµÑ Ñлектронной почты [[email]] должен быть проверен, чтобы вы могли иÑпользовать Ñтот ÑервиÑ. ЕÑли вы потерÑли пиÑьмо подтверждениÑ, вы можете повторно поÑлать его Ñебе. ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñвоего адреÑа, вы можете вернутьÑÑ Ð½Ð° Ñту Ñтраницу. + +/tools/emailmanage.bml.notvalidated.title=Ваш email-Ð°Ð´Ñ€ÐµÑ Ð½Ðµ подтверждён + +/tools/emailmanage.bml.title=Управление адреÑами e-mail + +/tools/memadd.bml.add_previous<< + + + +. + +/tools/memadd.bml.body.added.body=Ваш ÑпиÑок избранных запиÑей был обновлен. + +/tools/memadd.bml.body.added.header=Удачно + +/tools/memadd.bml.description=ОпиÑание: + +/tools/memadd.bml.description.text<< +Дайте опиÑание Ñтой запиÑи, Ñ Ð½Ð¸Ð¼ она будет Ñохранена в ÑпиÑке. +Удалите опиÑание, чтобы удалить запиÑÑŒ из избранного. +. + +/tools/memadd.bml.error.deleted.body=ЗапиÑÑŒ, ранее Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ ÐºÐ°Ðº "[[desc]]" была удалена из избранного. + +/tools/memadd.bml.error.deleted.title=ЗапиÑÑŒ удалена + +/tools/memadd.bml.error.entry_deleted=ЗапиÑÑŒ больше не ÑущеÑтвует. Отметка в избранном удалена. + +/tools/memadd.bml.error.fivekeywords=Ð”Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи избранного можно указать только 5 ключевых Ñлов или категорий. + +/tools/memadd.bml.error.invalid_security=ÐедейÑтвительный или отÑутÑтвующий параметр наÑтроек безопаÑноÑти. + +/tools/memadd.bml.error.login=Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтой функции вы должны ввеÑти Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль. ПоÑле ввода Ñтих данных вы Ñнова окажетеÑÑŒ здеÑÑŒ. + +/tools/memadd.bml.error.maxsize=Это ключевое Ñлово превышает макÑимально допуÑтимый размер: "[[keyword]]" + +/tools/memadd.bml.error.nodescription.body<< +Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы добавить запиÑÑŒ в избранное, вам нужно указать ее опиÑание. +Чтобы удалить запиÑÑŒ из избранного, вы можете удалить опиÑание, но ÑÐµÐ¹Ñ‡Ð°Ñ Ñта запиÑÑŒ не была добавлена в избранное. +. + +/tools/memadd.bml.error.nodescription.title=Ðет опиÑÐ°Ð½Ð¸Ñ + +/tools/memadd.bml.form.reset=ОчиÑтить + +/tools/memadd.bml.form.submit=Добавить + +/tools/memadd.bml.keywords=Ключевые Ñлова: + +/tools/memadd.bml.keywords.example=Пример: ВеÑёлое, Свихнутое, РомантичеÑкое + +/tools/memadd.bml.keywords.select=Ð’Ñ‹ можете также указать ключевые Ñлова, иÑпользованные вами ранее. + +/tools/memadd.bml.keywords.text=Почему вы хотите добавить Ñту запиÑÑŒ в избранное? Введите до пÑти разделённых запÑтыми ключевых Ñлов или категорий, по которым Ñможете найти данную запиÑÑŒ позже. + +/tools/memadd.bml.login.enterinfo=Введите Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль того аккаунта, куда хотите добавить запиÑÑŒ в избранное. + +/tools/memadd.bml.login.forgot.header=Забыли что-нибудь? + +/tools/memadd.bml.login.forgot.recover=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, воÑÑтановите их здеÑÑŒ. + +/tools/memadd.bml.multiple_selections=Чтобы выбрать неÑколько Ñлементов Ñразу, нажмите и держите клавишу "Control" и щелкайте по ключевым Ñловам. + +/tools/memadd.bml.security=БезопаÑноÑÑ‚ÑŒ: + +/tools/memadd.bml.security.friendsonly=Только Ð´Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹ + +/tools/memadd.bml.security.private=Личное + +/tools/memadd.bml.security.public=Открытое + +/tools/memadd.bml.title=Добавление в избранное + +/tools/memadd.bml.title.added=Добавлено + +/tools/memadd.bml.title.add_memory=Добавить запиÑÑŒ в избранное + +/tools/memadd.bml.title.deleted=Удалено + +/tools/memadd.bml.title.edit_memory=Редактирование запиÑи избранного + +/tools/memadd.bml.whocansee<< +Кому можно читать Ñту запиÑÑŒ в вашем избранном? +Ð’Ñем, только друзьÑм или никому, кроме ваÑ? +. + +/tools/memadd.bml.whocansee.comm=Кто может видеть, что вы занеÑли Ñту запиÑÑŒ в Избранное? Ð’Ñе, только члены ÑообщеÑтва или модераторы ÑообщеÑтва? + +/tools/memories.bml.back=Ðазад + +/tools/memories.bml.body.keyword<< + + +[[user]], в опиÑании которых вÑтречаетÑÑ Ñлово "[[keyword]]". p?> +. + +/tools/memories.bml.body.list_categories<< + + +[[user]] помеÑтил Ñвои избранные запиÑи. p?> +. + +/tools/memories.bml.body.memorable=Это неÑортированный ÑпиÑок избранного Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ [[user]]. + +/tools/memories.bml.delete=Удалить из Избранного + +/tools/memories.bml.delete.confirm=Ð’Ñ‹ ÑобираетеÑÑŒ удалить запиÑÑŒ из Избраннго. Ð’Ñ‹ точно хотите Ñто Ñделать? + +/tools/memories.bml.delete.deleted.head=ПолучилоÑÑŒ + +/tools/memories.bml.delete.deleted.text=ЗапиÑи из Избранного были удалены. Ð’Ñ‹ можете вернутьÑÑ Ðº ÑпиÑку. + +/tools/memories.bml.delete.deleted.title=ЗапиÑи из Избранного удалены + +/tools/memories.bml.delete.error.dberror=Во Ð²Ñ€ÐµÐ¼Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐ¸Ñ… запиÑей произошел Ñбой в базе данных. Тип ошибки - [[error]] . ПожалуйÑта, попробуйте еще раз + +/tools/memories.bml.delete.error.noneselected=Ð’Ñ‹ не выбрали ни одной запиÑи Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ + +/tools/memories.bml.edit=редактировать + +/tools/memories.bml.error.noentries.body<< +Это могло произойти потому, что:
              +
            1. пользователь не добавлÑл никакие запиÑи в избранное,
            2. +
            3. избранное Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð¾, и у Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к нему или
            4. +
            5. в избранном Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½ÐµÑ‚ запиÑей, ÑоответÑтвующих вашему критерию.
            +. + +/tools/memories.bml.error.noentries.title=СпиÑок избранных запиÑей пуÑÑ‚. + +/tools/memories.bml.filter.all=Ð’Ñе избранное + +/tools/memories.bml.filter.other=Только запиÑи других пользователей + +/tools/memories.bml.filter.own=Только запиÑи Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ "[[user]]" + +/tools/memories.bml.form.filter=Отобрать запиÑи по: + +/tools/memories.bml.form.sort=Сортировать запиÑи по: + +/tools/memories.bml.form.switch=Выбрать + +/tools/memories.bml.login=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы увидеть ваше Избранное, пожалуйÑта, войдите + +/tools/memories.bml.plur_entry=вÑего [[num]] + +/tools/memories.bml.sort.description=ОпиÑанию + +/tools/memories.bml.sort.journal=Журналу + +/tools/memories.bml.sort.orderadded=Времени Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + +/tools/memories.bml.title.keyword=Избранные запиÑи Ñ ÐºÐ»ÑŽÑ‡ÐµÐ²Ñ‹Ð¼ Ñловом [[keyword]] + +/tools/memories.bml.title.memorable=Избранные запиÑи + +/tools/memories.bml.uncategorized=ÐеупорÑдоченное + +/update.bml.altpost=Ð’ какой журнал помеÑтить запиÑÑŒ: + +/update.bml.btn.preview=Предварительный проÑмотр + +/update.bml.btn.update=ÐапиÑать в журнал + +/update.bml.currmood=Текущее наÑтроение: + +/update.bml.currmusic=Играет музыка: + +/update.bml.date=Дата: + +/update.bml.default=по умолчанию + +/update.bml.defaultjournal=([[user]]) - по умолчанию + +/update.bml.error.cantpost=Извините, в данный момент добавить запиÑÑŒ нельзÑ. + +/update.bml.error.disabled=Ð’Ñ‹ не можете добавить запиÑÑŒ Ñ Ð²Ð°ÑˆÐ¸Ð¼ типом аккаунта. + +/update.bml.error.disabled.title=Добавление запиÑей отключено + +/update.bml.error.login=Ошибка при входе: + +/update.bml.error.nopass=Введите пароль + +/update.bml.error.update=Ошибка при запиÑи: + +/update.bml.event=Событие: + +/update.bml.full=Полный вариант + +/update.bml.htmlokay.norich=(Ð”Ð»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¾ иÑпользовать теги HTML. Учтите, что новые Ñтроки будут автоматичеÑки отформатированы тегом <br>) + +/update.bml.htmlokay.rich=(Ð”Ð»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¾ иÑпользовать теги HTML (учтите, что новые Ñтроки будут автоматичеÑки отформатированы тегом <br>). ЕÑли Ð’Ñ‹ не знаете HTML - можете иÑпользовать наш визуальный редактор) + +/update.bml.htmlokay.rte_nosupport=(Извините, ваш браузер не поддерживает rich text формат) + +/update.bml.localtime=МеÑтное времÑ: + +/update.bml.loggedinas=Ð’Ñ‹ на Ñайте под именем [[user]].
            Чтобы Ñделать запиÑÑŒ под другим именем, нажмите здеÑÑŒ. + +/update.bml.loggingin=Вход на Ñервер... + +/update.bml.noneother=ПуÑто, или другое: + +/update.bml.note=Обратите внимание: Ð’Ñ€ÐµÐ¼Ñ Ð¸ дата, напиÑанные выше по-умолчанию выбираютÑÑ Ð½Ð°ÑˆÐ¸Ð¼ Ñервером. ИÑправьте их Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ временной зоны. + +/update.bml.opt.backdate=ЗапиÑÑŒ задним чиÑлом: + +/update.bml.opt.backdate.about=не показывать в лентах друзей + +/update.bml.opt.defpic=(по умолчанию) + +/update.bml.opt.nocomments=Отменить комментарии: + +/update.bml.opt.noemail=Ðе приÑылать комментарии: + +/update.bml.opt.noformat=Ðе выполнÑÑ‚ÑŒ автоформатирование: + +/update.bml.opt.spellcheck=Проверить правопиÑание перед отправкой (английÑкое) + +/update.bml.options=ÐаÑтройки + +/update.bml.other=Другое: + +/update.bml.password=Пароль: + +/update.bml.picture=Картинка: + +/update.bml.preview.header=Предварительный проÑмотр + +/update.bml.preview.text=Так ваша запиÑÑŒ будет выглÑдеть в журнале. ИÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ„Ð¾Ñ€Ð¼Ñƒ внизу, вы можете редактировать запиÑÑŒ или отоÑлать ее в нынешнем виде. + +/update.bml.security.custom=Выборочно... + +/update.bml.security.friends=Ð”Ð»Ñ Ð´Ñ€ÑƒÐ·ÐµÐ¹ + +/update.bml.security.head=Уровень доÑтупа: + +/update.bml.security.private=Личное + +/update.bml.security.public=Открытое + +/update.bml.servermsg=Да, у Ñервера еÑÑ‚ÑŒ Ð´Ð»Ñ Ð²Ð°Ñ Ñообщение: + +/update.bml.simple=Это упрощенный вид Ñтраницы. Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… возможноÑтей по редактированию ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð°Ð¶Ð¼Ð¸Ñ‚Ðµ здеÑÑŒ. + +/update.bml.spellchecked=Ваша запиÑÑŒ Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐµÐ½Ð½Ð¾Ð¹ орфографией: + +/update.bml.subject=Тема: (необÑзательно) + +/update.bml.timeformat=24-чаÑовое Ð²Ñ€ÐµÐ¼Ñ + +/update.bml.title=ÐапиÑать + +/update.bml.title.readonly=Только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ + +/update.bml.update.alternate=ЕÑли вы не хотите уÑтановить программу-клиент Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ компьютера не Ñоздана, вы можете иÑпользовать Ñту Ñтраницу Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Живого Журнала. Ð’Ñ‹ также можете иÑпользовать ее во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð½Ð¸ÐºÑƒÐ» или еÑли вы работаете не на машине, которую иÑпользуете поÑтоÑнно. ЕÑли у Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ‹Ð¹ аккаунт, вы можете обновить ваш журнал по email, по телефону или Ñоздать опроÑÑ‹. + +/update.bml.update.head=Добавить запиÑÑŒ в журнал... + +/update.bml.update.success=ЗапиÑÑŒ обновлена. Ð’Ñ‹ можете увидеть ваш обновленный журнал здеÑÑŒ. + +/update.bml.updating=Отправка запиÑи... + +/update.bml.username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: + +/uploadpic.bml.error.unsupportedtype=Данный тип файлов ([[filetype]]) не поддерживаетÑÑ. Картинки должны быть в формате GIF, PNG или JPG. ПрактичеÑки любой графичеÑкий редактор может преобразовать вашу картинку к одному из Ñтих типов. + +/userinfo.bml.about.comm=ОпиÑание: + +/userinfo.bml.about.user=БиографиÑ: + +/userinfo.bml.body.leave=Ð’Ñ‹ можете покинуть ÑообщеÑтво в любое времÑ. + +/userinfo.bml.comminfo.body=Ðиже указана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве ЖЖ "[[commname]]". + +/userinfo.bml.comminfo.name=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/userinfo.bml.date.never=Ðикогда. + +/userinfo.bml.error.malfname=Ðеправильно ÑоÑтавленное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ: Ñлишком длинное или Ñодержит недопуÑтимые знаки + +/userinfo.bml.error.notloggedin=ЕÑли вы хотите увидеть Ñвою Ñтраницу Ñ Ð¿ÐµÑ€Ñональной информацией, вам надо войти в ÑиÑтему. + +/userinfo.bml.friendof.comm=Читают: + +/userinfo.bml.friendof.hidden=(Ñкрыто) + +/userinfo.bml.friendof.syndreadcount=КоличеÑтво читателей + +/userinfo.bml.friendof.user=Ð’ друзьÑÑ… у: + +/userinfo.bml.friends.comm=УчаÑтники + +/userinfo.bml.friends.user=Ð”Ñ€ÑƒÐ·ÑŒÑ + +/userinfo.bml.label.addbuddy=Добавить + +/userinfo.bml.label.adduser=Добавить + +/userinfo.bml.label.alsofriendof=Также в друзьÑÑ… у: + +/userinfo.bml.label.birthdate=Дата рождениÑ: + +/userinfo.bml.label.clientsused=ИÑпользованные клиенты: + +/userinfo.bml.label.comments=Комментариев: + +/userinfo.bml.label.composted=ÐапиÑано: [[num]] - + +/userinfo.bml.label.comreceived=Получено: [[num]] + +/userinfo.bml.label.datecreated=Дата ÑозданиÑ: + +/userinfo.bml.label.dateupdated=ПоÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ: + +/userinfo.bml.label.email=ÐÐ´Ñ€ÐµÑ e-mail: + +/userinfo.bml.label.frcommunity=СообщеÑтва + +/userinfo.bml.label.frpeople=Люди + +/userinfo.bml.label.frsyndication2=ТранÑлируемые ленты + +/userinfo.bml.label.icquin=Ðомер ICQ: + +/userinfo.bml.label.interests=ИнтереÑÑ‹ + +/userinfo.bml.label.interests.modifyyours=Изменить Ð²Ð°ÑˆÐ¸ + +/userinfo.bml.label.interests.removesome=Удалить + +/userinfo.bml.label.intsnotshown=... [[intnotshown]] интереÑов не показано + +/userinfo.bml.label.journalentrs=ЗапиÑей в журнале: + +/userinfo.bml.label.location=МеÑтоположение: + +/userinfo.bml.label.memberof=СоÑтоит в + +/userinfo.bml.label.memories=Избранное: + +/userinfo.bml.label.moredetails=(подробнее...) + +/userinfo.bml.label.msnusername=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ MSN: + +/userinfo.bml.label.mutual=Взаимные друзьÑ: + +/userinfo.bml.label.name=ИмÑ: + +/userinfo.bml.label.nofriends=ОтÑутÑтвуют. + +/userinfo.bml.label.post=ÐапиÑать в "[[journal]]" + +/userinfo.bml.label.postalt=Сделать новую запиÑÑŒ + +/userinfo.bml.label.reqfinduser=Только пользователи Ñ Ð¿Ñ€Ð¸Ð²Ð¸Ð»ÐµÐ³Ð¸ÐµÐ¹ "findpriv" могут иÑкать пользователей по идентификатору. + +/userinfo.bml.label.searchjournal=ПоиÑк в Ñтом журнале + +/userinfo.bml.label.sendmessage=ПоÑлать Ñообщение + +/userinfo.bml.label.shared=ДоÑтуп на добавление запиÑей: + +/userinfo.bml.label.supportpoints=Баллы помощника + +/userinfo.bml.label.syndicatedfrom=ТранÑлируетÑÑ Ð¸Ð·: + +/userinfo.bml.label.syndicatedstatus=СоÑтоÑние транÑлÑции: + +/userinfo.bml.label.textmessage=ТекÑтовое
            Ñообщение
            : + +/userinfo.bml.label.todo=СпиÑок задач + +/userinfo.bml.label.user=Пользователь: + +/userinfo.bml.label.viewfriends=СпиÑок друзей + +/userinfo.bml.label.viewmembers=СпиÑок учаÑтников + +/userinfo.bml.label.website=Сайт: + +/userinfo.bml.label.yahooid=Ð˜Ð¼Ñ Ð² Yahoo!: + +/userinfo.bml.membership.body=Чтобы приÑоединитьÑÑ Ðº Ñтому ÑообщеÑтву, нажмите здеÑÑŒ. + +/userinfo.bml.membership.paidmembers=ПоÑле того как ваш платный аккаунт Ñоздан, вы можете приÑоединитьÑÑ Ðº ÑообщеÑтву платных пользователей. + +/userinfo.bml.memories.entries=[[count]] запиÑей + +/userinfo.bml.memories.entry=[[count]] запиÑÑŒ + +/userinfo.bml.monitor.comm=Добавить ÑообщеÑтво в вашу ленту друзей + +/userinfo.bml.monitor.user=Добавить Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð² вашу ленту друзей + +/userinfo.bml.nonexist.body=ÐŸÐ¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ [[user]] не ÑущеÑтвует. Ð’Ñ‹ уж извините. + +/userinfo.bml.nonexist.name=ÐеизвеÑтный пользователь + +/userinfo.bml.sendmessage.body=ПоÑлать [[user]] текÑтовое Ñообщение
            на его/ее мобильный/пейджер. + +/userinfo.bml.syn.last.never=Ðикогда + +/userinfo.bml.syn.lastcheck=ПоÑледнÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.nextcheck=Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: + +/userinfo.bml.syn.parseerror=Сообщение об ошибке: + +/userinfo.bml.syndinfo.body=ЕÑли вы хотели бы чтобы Ñтатьи Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾, поддерживающего транÑлÑцию, Ñайта поÑвлÑлиÑÑŒ в вашей ленте друзей, добавьте Ñтот журнал к Ñвоему ÑпиÑку друзей. + +/userinfo.bml.syndinfo.name=ТранÑлируемый журнал + +/userinfo.bml.tellafriend=Сообщить другу! + +/userinfo.bml.timeupdate.dayago=один день назад + +/userinfo.bml.timeupdate.daysago=прошло дней: [[num]] + +/userinfo.bml.timeupdate.hourago=один Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´ + +/userinfo.bml.timeupdate.hoursago=прошло чаÑов: [[num]] + +/userinfo.bml.timeupdate.minuteago=одну минуту назад + +/userinfo.bml.timeupdate.minutesago=прошло минут: [[num]] + +/userinfo.bml.timeupdate.secondago=одну Ñекунду назад + +/userinfo.bml.timeupdate.secondsago=прошло Ñекунд: [[num]] + +/userinfo.bml.timeupdate.weekago=одну неделю назад + +/userinfo.bml.timeupdate.weeksago=прошло недель: [[num]] + +/userinfo.bml.title=О пользователе + +/userinfo.bml.title.communityinfo=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑообщеÑтве + +/userinfo.bml.title.syndicated=ТранÑлÑционный Ðккаунт + +/userinfo.bml.userinfo.body=Ðиже указана Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ пользователе [[username]]. ЕÑли вы ÑвлÑетеÑÑŒ Ñтим пользователем, то можете отредактировать её (или выбрать, какую информацию показывать общеÑтвенноÑти) на Ñтранице Редактировать личную информацию. + +/userinfo.bml.userinfo.name=О пользователе + +bml.badcontent.body<< + +При обработке вашего запроÑа произошла одна или неÑколько ошибок. ПoжалуйÑта, вернитеÑÑŒ на предыдущую Ñтраницу, Ñделайте необходимые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ отошлите ваши данные еще раз. +. + +bml.badinput.body=Ваш браузер поÑлал текÑÑ‚, который не ÑвлÑетÑÑ Ñ‚ÐµÐºÑтом в требуемом формате UTF-8. Это могло ÑлучиитьÑÑ Ð¸Ð·-за того, что вы заÑтавили ваш браузер открыть предыдущую Ñтраницу в формате, отличном отUTF-8. Ðльтернативно Ñто может быть вызвано неполадкой в браузере. ЕÑли вы не можете ничего Ñделать в Ñтой Ñитуации, напишите нам. + +bml.badinput.head=Введены неправильные данные в Unicode + +bml.needlogin.body2=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы увидеть Ñту Ñтраницу, вы должны войти в журнал. + +bml.needlogin.head=Ðеобходимо войти + +BML.parse_multipart.parse=Ошибка разбора загруженной на Ñервер информации + +BML.parse_multipart.toolarge=Загрузка на Ñервер Ñлишком большого объема информации + +BML.parse_multipart.unknowntype=ÐеизвеÑтный тип информации + +btn.search=ПоиÑк + +crumb.about=О Живом Журнале + +crumb.abusereport=Сообщить о нарушении правил + +crumb.acctfeatures=ВозможноÑти разных типов аккаунтов + +crumb.acctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° + +crumb.addfriend=Добавить друга + +crumb.addtodo=Добавить в Сделать + +crumb.advcustomize=Выбрать дополнительные наÑтройки S2 + +crumb.advsearch= Продвинутый + +crumb.banners=Баннеры + +crumb.birthdays=Дни рождений + +crumb.changepass=Изменить пароль + +crumb.code=Код Живого Журнала + +crumb.commmembers=Члены ÑообщеÑтва + +crumb.commpending=Ожидают зачиÑÐ»ÐµÐ½Ð¸Ñ + +crumb.commsearch=ПоиÑк ÑообщеÑтва + +crumb.community=Центр СообщеÑтва + +crumb.contract=Ðаш ОбщеÑтвенный договор + +crumb.contributors=УчаÑтники + +crumb.createcommunity=Создать СообщеÑтво + +crumb.createjournal=Создать журнал + +crumb.createstyle=Создать Ñтиль + +crumb.customize=ÐаÑтройки S2 + +crumb.delcomment=Удалить комментарий + +crumb.download=Загрузить программу-клиент + +crumb.editentries=Редактировать запиÑи + +crumb.editentries_do=Редактировать запиÑÑŒ + +crumb.editfriendgrps=Редактировать группы друзей + +crumb.editfriends=Редактировать ÑпиÑок друзей + +crumb.editinfo=О пользователе + +crumb.editpics=Кaртинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +crumb.editstyle=Редактировать Ñтиль + +crumb.emailgateway=Email шлюз + +crumb.emailmanage=Управление email + +crumb.encodings=О кодировках + +crumb.export=ПеренеÑти журнал + +crumb.faq=ВопроÑÑ‹ и ответы + +crumb.feedstersearch=ПоиÑк в журнале + +crumb.filemanager=Управление файлами + +crumb.friends= Редактировать друзей + +crumb.friendsfilter=Фильтр друзей + +crumb.goat=О ФрÑнке + +crumb.home=Домой + +crumb.itsfree=БеÑплатно? + +crumb.joincomm=ПриÑоединитьÑÑ Ðº ÑообщеÑтву + +crumb.latestposts=Свежие запиÑи + +crumb.layerbrowse=ПроÑмотр общедоÑтупного ÑÐ»Ð¾Ñ + +crumb.leavecomm=Выйти из ÑообщеÑтва + +crumb.legal=ÐŸÑ€Ð°Ð²Ð¾Ð²Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +crumb.linkslist=Ваши закладки + +crumb.login=Вход + +crumb.logout=Выход + +crumb.lostinfo=УтерÑÐ½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +crumb.manage=Управление аккаунтами + +crumb.managecommunity=Управление ÑообщеÑтвом + +crumb.meme=ПоиÑк избранного + +crumb.memories=Избранное + +crumb.moderate=Модерирование ÑообщеÑтва + +crumb.modify=ÐаÑтройки журнала + +crumb.moodlist=Показать наÑтроение + +crumb.news=ÐовоÑти + +crumb.paidaccounts=Платные аккаунты + +crumb.paidacctstatus=Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð»Ð°Ñ‚Ð½Ð¾Ð³Ð¾ аккаунта + +crumb.phonepostsettings=ЗапиÑÑŒ по телефону + +crumb.popfaq=ЧаÑто задаваемые вопроÑÑ‹ + +crumb.press=Уголок преÑÑÑ‹ Живого Журнала + +crumb.pressarticles=О Живом Журнале пишет преÑÑа + +crumb.preview=ПроÑмотр внешнего вида + +crumb.privacy=Положение о конфиденциальноÑти + +crumb.register=Подтвердить email + +crumb.search=ПоиÑк + +crumb.searchinterests=По интереÑам + +crumb.searchregion=По региону + +crumb.seeoverrides=Показать перекрывающие коды Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +crumb.setpgpkey=Открытый ключ + +crumb.singles=Одинокие Живого Журнала + +crumb.singlesopts=Изменить доÑтупноÑÑ‚ÑŒ + +crumb.singlessearch=ПоиÑк вашей половинки + +crumb.sitemap=Карта Ñайта + +crumb.siteopts=Показать наÑтройки + +crumb.sizechart=Таблица размеров + +crumb.staff=Ðачальники + +crumb.stats=СтатиÑтика + +crumb.store=Магазин Живого Журнала + +crumb.storeitem=Показать подробное опиÑание + +crumb.styles=Стили + +crumb.suggestions=Генератор предложений + +crumb.suggview=ÐŸÑ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + +crumb.support=Поддержка + +crumb.supportact=ЗапроÑите ответ + +crumb.supportappend=Добавить к запроÑу + +crumb.supporthelp=Форум ЗапроÑов + +crumb.supportnotify=ÐаÑтройки ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ + +crumb.supportscores=Ðаибольшее количеÑтво очков + +crumb.supportsubmit=ПоÑлать Ð·Ð°Ð¿Ñ€Ð¾Ñ + +crumb.textmessage=ПоÑлать текÑтовое Ñообщение + +crumb.themes=ПроÑмотреть гаммы + +crumb.todo=СпиÑок задaч + +crumb.tos=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ð±ÑÐ»ÑƒÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ + +crumb.unsubscribe=Отменить подпиÑку + +crumb.update=ÐапиÑать в журнал + +crumb.utf8convert=Конвертер UTF-8 + +crumb.yourlayers=Ваши Ñлои + +crumb.yourstyles=Ваши Ñтили + +date.day.friday.long=ПÑтница + +date.day.friday.short=Пт + +date.day.monday.long=Понедельник + +date.day.monday.short=Пн + +date.day.saturday.long=Суббота + +date.day.saturday.short=Сб + +date.day.sunday.long=ВоÑкреÑенье + +date.day.sunday.short=Ð’Ñ + +date.day.thursday.long=Четверг + +date.day.thursday.short=Чт + +date.day.tuesday.long=Вторник + +date.day.tuesday.short=Ð’Ñ‚ + +date.day.wednesday.long=Среда + +date.day.wednesday.short=Ср + +date.month.april.long=Ðпрель + +date.month.april.short=Ðпр + +date.month.august.long=ÐвгуÑÑ‚ + +date.month.august.short=Ðвг + +date.month.december.long=Декабрь + +date.month.december.short=Дек + +date.month.february.long=Февраль + +date.month.february.short=Фев + +date.month.january.long=Январь + +date.month.january.short=Янв + +date.month.july.long=Июль + +date.month.july.short=Июл + +date.month.june.long=Июнь + +date.month.june.short=Июн + +date.month.march.long=Март + +date.month.march.short=Мар + +date.month.may.long=Май + +date.month.may.short=Май + +date.month.november.long=ÐоÑбрь + +date.month.november.short=ÐÐ¾Ñ + +date.month.october.long=ОктÑбрь + +date.month.october.short=Окт + +date.month.september.long=СентÑбрь + +date.month.september.short=Сен + +dystopia.btn.login=ВХОД + +dystopia.hello_anonymous=Добро пожаловать в Живой Журнал! + +dystopia.hello_loggedin=Привет, [[username]]! + +dystopia.nav.contact=Контактный Ð°Ð´Ñ€ÐµÑ + +dystopia.nav.createjournal=Создать Журнал + +dystopia.nav.developer=Разработчикам + +dystopia.nav.download=Загрузка + +dystopia.nav.editentries=Редактировать + +dystopia.nav.editfriends=Ваши Ð´Ñ€ÑƒÐ·ÑŒÑ + +dystopia.nav.editpassword=Ваш пароль + +dystopia.nav.editpics=Ваши картинки + +dystopia.nav.editstyle=Свой Ñтиль + +dystopia.nav.faq=Справка ЖЖ + +dystopia.nav.findcomm=По ÑообщеÑтву + +dystopia.nav.finddir=ПоиÑк по каталогу + +dystopia.nav.findint=По интереÑам + +dystopia.nav.findrandom=Случайно + +dystopia.nav.findregion=По региону + +dystopia.nav.home=Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница + +dystopia.nav.journalcalendar=Календарь + +dystopia.nav.journalfriends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +dystopia.nav.journalinfo=О пользователе + +dystopia.nav.journalrecent=Свежие запиÑи + +dystopia.nav.legalprivacy=БезопаÑноÑÑ‚ÑŒ + +dystopia.nav.legaltos=УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ + +dystopia.nav.login=Вход + +dystopia.nav.logout=Выход + +dystopia.nav.lostinfo=Ðапомнить пароль + +dystopia.nav.memories=Избранное + +dystopia.nav.modifyjournal=Изменить журнал + +dystopia.nav.news=ÐовоÑти + +dystopia.nav.paidaccts=Оплата + +dystopia.nav.paymentarea=Платежи + +dystopia.nav.personalinfo=ПерÑональные + +dystopia.nav.sitemap=Карта Ñайта + +dystopia.nav.siteopts=ÐаÑтройки Ñайта + +dystopia.nav.support=Задать Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +dystopia.nav.updatejournal=ÐапиÑать + +dystopia.nav.width|notes=Some languages require the bar on the left to be wider. Feel free to keep the default value. +dystopia.nav.width=130 + +dystopia.navhead.findusers=Ðайти пользователей + +dystopia.navhead.help=Справка и помощь + +dystopia.navhead.journal=Ваш журнал + +dystopia.navhead.legal=Правовое + +dystopia.navhead.settings=Ваши наÑтройки + +dystopia.navhead.welcome=Добро пожаловать! + +dystopia.search.icq=Ðомер ICQ + +dystopia.search.int=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +dystopia.search.msn=Ð˜Ð¼Ñ Ð² MSN + +dystopia.search.region=Регион + +dystopia.searchlj=Ðайти в ЖЖ: + +Email=Email + +email.newacct.body<< +ПоздравлÑем, теперь у Ð’Ð°Ñ ÐµÑÑ‚ÑŒ Живой Журнал! + +Чтобы завершить процедуру региÑтрации и подтвердить ваш e-mail, нажмите на ÑÑылку: + +[[regurl]] + +Ваш журнал находитÑÑ Ð¿Ð¾ адреÑу: + +[[siteroot]]/users/[[username]]/ + +или: + +[[siteroot]]/~[[username]]/ + +Вот Ваши Ð¸Ð¼Ñ Ð¸ пароль Ð´Ð»Ñ Ð–Ð¸Ð²Ð¾Ð³Ð¾ Журнала: + +ИмÑ: [[username]] +Пароль: [[password]] + +Теперь Ð’Ñ‹ можете открыть Ñайт [[siteroot]]/ и получить доÑтуп к Ñвоему журналу, добавить в него запиÑи и наÑтроить его конфигурацию и внешний вид. Мы рекомендуем загрузить программу-клиент. КлиентÑкие программы ÑущеÑтвуют под различные операционные ÑиÑтемы и платформы и дают возможноÑÑ‚ÑŒ наиболее проÑто и быÑтро делать запиÑи в Вашем журнале. Загрузить их можно Ñо Ñтраницы: + +[[siteroot]]/download/ + +Ðачинать Ñ Ð½ÑƒÐ»Ñ Ð²Ñегда нелегко, оÑобенно еÑли Ð’Ñ‹ не знакомы Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ пользователÑми. ПоÑетите ÑообщеÑтво http://newbies.livejournal.com -- и Вам помогут Ñ Ð¿ÐµÑ€Ð²Ñ‹Ð¼Ð¸ шагами. Ðемного удачи -- и Ð’Ñ‹ быÑтро Ñтанете наÑтоÑщим ЖЖ-профи! + +ÐадеемÑÑ, что Живой Журнал доÑтавит Вам немало удовольÑтвиÑ, подобно тому, как нам доÑтавлÑет удовольÑтвие работа над ним. ЕÑли у Ð’Ð°Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÑƒÑ‚ какие-либо вопроÑÑ‹ отноÑительно Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð–Ð–, обратитеÑÑŒ в Ñлужбу техничеÑкой поддержки по адреÑу: + +[[siteroot]]/support/ + +Там Ð’Ñ‹ Ñможете получить ответы на практичеÑки любые вопроÑÑ‹ о Живом Журнале. + +Ðаша цель -- Ñделать ЖЖ Ñамым лучшим! ЕÑли Ð’Ñ‹ видите ÑпоÑоб Ñделать Живой Журнал проще, удобнее, мощнее, разнообразнее -- Ñообщите нам. Мы делаем Ñто не ради денег. Мы не компаниÑ-однодневка, оÑÐ½Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° венчурные ÑредÑтва Ñ Ñ†ÐµÐ»ÑŒÑŽ раÑкрутитьÑÑ Ð¸ продать акции. Этот Ñайт живет Ð±Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ Ð»ÑŽÐ´Ñм, которые им пользуютÑÑ. ЕÑли мы Ñможем Ñделать его лучше Ð±Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ Ð’Ð°Ð¼ -- мы будем только рады. + + +ЕÑли у Ð’Ð°Ñ Ð¾ÑталиÑÑŒ какие-то вопроÑÑ‹, Ñлужба поддержки обычно отвечает на них в течение 24 чаÑов или даже быÑтрее. + +ÐаÑлаждайтеÑÑŒ! + +Команда [[sitename]] +[[siteroot]]/ +. + +email.newacct.subject=Добро пожаловать в Живой Журнал + +Error|notes=typically used inside an H1 tag to announce an error. +Error=Ошибка + +error.badpassword=Ðеверный пароль. + +error.code.comm_not_comm=Этот аккаунт не ÑвлÑетÑÑ ÑообщеÑтвом + +error.code.comm_not_found=СообщеÑтво не найдено + +error.code.comm_not_member=Пользователь не ÑвлÑетÑÑ Ñ‡Ð»ÐµÐ½Ð¾Ð¼ данного ÑообщеÑтва + +error.dberror=Произошла ошибка в работе базы данных: + +error.deleted.name=Удалено + +error.deleted.text=Этот журнал был удален. ЕÑли вы [[user]], то у Ð²Ð°Ñ ÐµÑÑ‚ÑŒ 30 дней Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы отменить удаление журнала. ПоÑле 30 дней мы навÑегда удалим Ñодержимое вашего журнала Ñо вÑех наших Ñерверов. + +error.deleted.title=Удаленный аккаунт + +error.expiredchal=Ваше Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ иÑтекло. ПожалуйÑта, загрузитеÑÑŒ еще раз. + +error.invalidauth=Ð’Ñ‹ не можете войти Ñ Ð¿Ð°Ñ€Ð¾Ð»ÐµÐ¼ Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +error.ipbanned=Ваш IP-Ð°Ð´Ñ€ÐµÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ заблокирован за превышение Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ñ‡Ð¸Ñла неудачных попыток входа. + +error.malformeduser=Ðеправильное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +error.nobutton=Ðе нажата кнопка? + +error.nodb=База данных временно недоÑтупна. + +error.nodbmaintenance=Эта чаÑÑ‚ÑŒ базы данных временно на обÑлуживании. Попробуйте ещё раз через неÑколько минут. + +error.noentry=Ðет такой запиÑи в журнале. + +error.nojournal=ÐеизвеÑтный Журнал + +error.noremote=Вам придётÑÑ Ð²Ð¾Ð¹Ñ‚Ð¸ в ЖЖ чтобы можно было работать Ñ Ñтой Ñтраницей. + +error.procrequest=Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ вашего запроÑа: + +error.purged.name=Удален + +error.purged.text=Этот журнал был удален вмеÑте Ñо вÑем его Ñодержимым. + +error.purged.title=Удаленный аккаунт + +error.suspended.name=Заморожен + +error.suspended.text=Этот журнал был заморожен (временно или навÑегда). ЕÑли вы [[user]], дополнительную информацию вы можете получить в Ñтатье Справки: Мой аккаунт был заморожен! Что Ñ Ð¼Ð¾Ð³Ñƒ Ñделать, чтобы вернуть его? Учтите, что по ÑоображениÑм конфиденциальноÑти [[sitename]] не может обÑуждать причины, по которым аккаунт был заморожен, Ñ ÐºÐµÐ¼ бы то ни было кроме владельца аккаунта. + +error.suspended.title=Замороженный аккаунт + +error.tempdisabled=Временно не работает. + +error.unknownmode=ÐеизвеÑтный режим + +error.usernameinvalid=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñодержит неразрешённые Ñимволы. + +error.usernamelong=Слишком длинное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ, макÑимум 15 Ñимволов. + +error.username_notfound=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ найдено + +Help=Помощь + +label.screening.all=Ð’Ñе комментарии + +label.screening.anonymous=Только анонимные + +label.screening.default=По умолчанию + +label.screening.header=Скрыть комментарии: + +label.screening.none=Ðе Ñкрывать ничего + +label.screening.nonfriends=От тех, кто не в ÑпиÑке друзей + +label.security.custom=Выборочно... + +label.security.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +label.security.head=Уровень доÑтупа: + +label.security.maintainers=Смотрители + +label.security.members=Члены + +label.security.private=Личное + +label.security.public=Ð”Ð»Ñ Ð²Ñех + +label.switch.button=Переключить + +label.switch.header=Выбрать журнал + +label.switch.workwith=С каким журналом работать: + +langname.be=БелоруÑÑкий + +langname.da=ДатÑкий + +langname.de=Ðемецкий + +langname.en=ÐнглийÑкий + +langname.en_GB=ÐнглийÑкий (ВеликобританиÑ) + +langname.en_LJ=ÐнглийÑкий + +langname.eo=ЭÑперанто + +langname.es=ИÑпанÑкий + +langname.et=ЭÑтонÑкий + +langname.fi=ФинÑкий + +langname.fr=ФранцузÑкий + +langname.ga=ИрландÑкий + +langname.gd=ГальÑкий + +langname.he=Иврит + +langname.hi=Хинди + +langname.hu=ВенгерÑкий + +langname.is=ИÑландÑкий + +langname.it=ИтальÑнÑкий + +langname.ja=ЯпонÑкий + +langname.la=Латынь + +langname.lv=ЛатышÑкий + +langname.ms=МалайÑкий + +langname.nb=ÐорвежÑкий - BokmÃ¥l + +langname.nl=ГолландÑкий + +langname.nn=ÐорвежÑкий - Nynorsk + +langname.pl=ПольÑкий + +langname.pt=ПортугальÑкий + +langname.ru=РуÑÑкий + +langname.sv=ШведÑкий + +langname.tr=Турецкий + +langname.uk=УкраинÑкий + +langname.zh=КитайÑкий (упрощенный) + +ljcom.account.feature=ВозможноÑÑ‚ÑŒ + +ljcom.account.feature.email=ÐÐ´Ñ€ÐµÑ email в Живом Журнале + +ljcom.account.feature.full2=ПодробноÑти можно найти на Ñтранице. + +ljcom.account.feature.limit=ограничено + +ljcom.account.feature.ownblog=Ваш дневник/веблог + +ljcom.account.feature.search=ПоиÑк по каталогу + +ljcom.account.feature.styles=Создание/редактирование Ñтилей + +ljcom.account.feature.syn=Лента друзей и импорт новоÑтей в формате RSS + +ljcom.account.free=БеÑплатный аккаунт + +ljcom.account.paid=Платный аккаунт + +ljcom.account.paid12=Оплата за 12 меÑÑцев ($25 USD) + +ljcom.account.paid2=Оплата за 2 меÑÑца ($5 USD) + +ljcom.account.paid6=Оплата за 6 меÑÑцев ($15 USD) + +ljcom.accounttype=Тип аккаунта + +ljcom.badpass.email=Ваш пароль не может быть оÑнован на вашем e-mail'е. + +ljcom.badpass.realname=Ваше наÑтоÑщее Ð¸Ð¼Ñ Ð½Ðµ может быть чаÑтью вашего Ð¿Ð°Ñ€Ð¾Ð»Ñ + +ljcom.badpass.username=Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ может быть чаÑтью вашего Ð¿Ð°Ñ€Ð¾Ð»Ñ + +ljcom.meetup.head=Meetup! + +ljcom.meetup.link|notes=This string will be inserted into the [[link]] variable in ljcom.meetup.text. +ljcom.meetup.link=Meetup в вашем городе + +ljcom.meetup.moreinfo=(больше информации) + +ljcom.meetup.text|notes=[[link]] will be replaced with the contents of ljcom.meetup.link. +ljcom.meetup.text=Хотите вÑтретитьÑÑ Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ пользователÑми в реальной жизни? Узнайте когда будет [[link]]! + +ljcom.menu.upgrade=Обновите Ñвой аккаунт + +ljcom.userinfo.accounttype=Тип аккаунта + +ljcom.userinfo.paiduser=Платный пользователь + +ljcom.userinfo.types.early=Коренной пользователь + +ljcom.userinfo.types.free=БеÑплатный аккаунт + +ljcom.userinfo.types.paid=Платный аккаунт + +ljcom.userinfo.types.paid_early=Платный аккаунт, до Ñтого -- Ранний пользователь + +ljcom.userinfo.types.paid_early_expiring=Платный аккаунт, заканчиваетÑÑ [[paiduntil]], до Ñтого был Ранним пользователем + +ljcom.userinfo.types.paid_expiring=Платный аккаунт, заканчиваетÑÑ [[paiduntil]] + +ljcom.userinfo.types.permanent=ПоÑтоÑнный аккаунт, + +ljcom.userinfo.types.permanent_early=ПоÑтоÑнный аккаунт, до Ñтого -- Ранний пользователь + +ljlib.pageofpages=[[page]]-Ñ Ñтраница из [[total]] + +lostinfo.head=Забыли что-нибудь? + +lostinfo.text=ЕÑли вы забыли ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль, воÑÑтановите их здеÑÑŒ. + +lynx.nav.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +lynx.nav.help=ТехничеÑÐºÐ°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ° + +lynx.nav.home=Домой + +lynx.nav.login=Войти + +lynx.nav.logout=Выход + +lynx.nav.recent=Свежие запиÑи + +lynx.nav.sitemap=Карта Ñайта + +lynx.nav.siteopts=ПроÑмотреть ÑпиÑок возможноcтей + +lynx.nav.update=ÐапиÑать + +Password=Пароль + +password.max30=Пароль не может быть длинее 30 Ñимволов + +poll.dberror=Ошибка в базе данных: [[errmsg]] + +poll.dberror.items=Ошибка базы данных при вÑтавке: [[errmsg]] + +poll.dberror.questions=Ошибка базы данных при вÑтавке вопроÑов: [[errmsg]] + +poll.error.badmaxlength=МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° атрибута на lj-pq Ñ‚Ñгах текÑта должна быть целым чиÑлом от 1 до 255. + +poll.error.badsize=Ðтрибут размера на Ñ‚Ñгах текÑта должен быть целым чиÑлом от 1 до 100. + +poll.error.cantview=Ошибка: вам не разрешен доÑтуп к результатам Ñтого опроÑа. + +poll.error.cantvote=Извините, вам не разрешено голоÑовать в Ñтогм опроÑе. + +poll.error.missingljpoll=Ð’Ñе lj-pq Ñ‚Ñги дожны находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ внешних Ñ‚Ñгов lj-опроÑа. + +poll.error.missingljpq=Ð’Ñе lj-pi Ñ‚Ñги дожны находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ внешних lj-pq Ñ‚Ñгов + +poll.error.nested=Ð’Ñ‹ не можете вкладывать [[tag]] Ñ‚Ñги друг в друга. Может, вы забыли закрыть один из них? + +poll.error.noentry=Ошибка: данный Ð¾Ð¿Ñ€Ð¾Ñ Ð½Ðµ приÑоединен к Ñтой запиÑи в журнале + +poll.error.noitems=Ð’ нетекÑтовой вопроÑе должна быть по меньшей мере одна чаÑÑ‚ÑŒ. + +poll.error.noitemstext=lj-pq теги типа 'текÑÑ‚' не могут Ñодержать чаÑти опроÑа. + +poll.error.nopollid=Ðе хватает параметра pollid. + +poll.error.noquestions=Ð’ опроÑе должен быть по меньшей мере один вопроÑ. + +poll.error.notext=Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы указать о чем вопроÑ, необходим текÑÑ‚ внутри lj-pq Ñ‚Ñга. + +poll.error.pitoolong=ТекÑÑ‚ внутри Ñ‚Ñга должен быть от 1 до 255 знаков. Длина вашего + +poll.error.pollnotfound=Ошибка: Ð¾Ð¿Ñ€Ð¾Ñ #[[num]] не найден + +poll.error.questionnotfound=Ошибка: такого вопроÑа нет. + +poll.error.scalefromlessto=Значение "от" должно быть меньше Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ "до" + +poll.error.scaleincrement=Увеличение шкалы должно быть не меньше 1. + +poll.error.scaletoobig=Ваша шкала вревышает лимит в 20 выборов (до-от)/через >20 + +poll.error.tagnotopen=Ð’Ñ‹ не можете закрыть [[tag]] Ñ‚Ñг, который не был открыт + +poll.error.truncated=...укорочен + +poll.error.unknownpqtype=ÐеизвеÑтный шрифт на lj-pq Ñ‚Ñге. + +poll.error.unlockedtag=Ðезакрытый [[tag]] Ñ‚Ñг + +poll.error.whoview=Можно видеть (whoview) должно быть "вÑем" ('all'), "друзьÑм" ('friends') или "никому"('none') + +poll.error.whovote=Можно голоÑовать (whovote) должно быть "вÑем" ('all') или "друзьÑм" ('friends') + +poll.pollnum=ÐžÐ¿Ñ€Ð¾Ñ #[[num]] + +poll.scaleanswers<< +Среднее [[mean]] Срединное значение: [[median]] Ð¡Ñ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° [[stddev]] + + +. + +poll.security=Открыт:[[whovote]], результаты видны:[[whoview]] + +poll.security.all<< +Ð’Ñем + +. + +poll.security.friends<< +ДрузьÑм + +. + +poll.security.none=Ðикому + +poll.submit=ОтоÑлать Ð¾Ð¿Ñ€Ð¾Ñ + +poll.viewanswers=Показать ответы + +portal.bdays.count.des=По умолчанию показываютÑÑ Ð±Ð»Ð¸Ð¶Ð°Ð¹ÑˆÐ¸Ðµ дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ 5-ти друзей. + +portal.bdays.count.name=Сколько дней Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ + +portal.bdays.portalname=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +portal.bdays.portaltitle=Дни Ñ€Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ + +portal.goat.name=ТалиÑман Ñайта + +portal.goattext.des=Рчего ещё вы хотите уÑлышать от козла? Ðа Ñамом деле, козлы говорÑÑ‚ только "Ме-е-е", хотÑ, еÑли очень хотите, можете предÑтавить Ñебе, что он говорит что-то другое. + +portal.goattext.name=Козлиный текÑÑ‚ + +portal.login.portalname=Вход + +portal.memories.entriesnoun=запиÑи + +portal.memories.entrynoun=запиÑÑŒ + +portal.memories.portalname=ПамÑтные запиÑи + +portal.memories.portaltitle=ПамÑтные запиÑи + +portal.ministats.active=Пишущих: + +portal.ministats.title=Пользователи + +portal.ministats.total=Ð’Ñего: + +portal.misbehaved.des=ЗдеÑÑŒ галочку Ñтавить не Ñтоит. От недреÑÑированных козлов одни неприÑтноÑти. + +portal.misbehaved.name=ÐепоÑлушный козёл + +portal.newtolj.name=СÑылки по Ñайту + +portal.popfaq.portalname=10 Ñамых популÑрных вопроÑов Ñправки ЖЖ + +portal.popfaq.portaltitle=10 Ñамых популÑрных вопроÑов Ñправки ЖЖ + +portal.randuser.count.des=По умолчанию будет показан 1 Ñлучайный пользователь, но выможете показать до 10 по вертикали в узких колонках, либо до 5 по горизонтали в широкой колонке. + +portal.randuser.count.name=ЧиÑло Ñлучайных пользователей + +portal.randuser.error.tableempty=Случайных пользователей не найдено. СвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором. + +portal.randuser.hidename.des=По умолчанию выводитÑÑ Ð¸Ð¼Ñ Ñлучайного пользователÑ. Отметьте галочку, еÑли хотите ÑпрÑтать его. + +portal.randuser.hidename.name=Скрыть Ð¸Ð¼Ñ + +portal.randuser.hidepic.des=По умолчанию выводитÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ° Ñлучайного пользователÑ. ЕÑли хотите ÑпрÑтать её, отметьте галочку. + +portal.randuser.hidepic.name=Скрыть картинки Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +portal.randuser.portalname=Случайный пользователь + +portal.randuser.portaltitle=Случайный пользователь + +portal.randuser.portaltitleplural=Случайные пользователи + +portal.recent.error.noentries=ПроÑтите. Ðет запиÑей. + +portal.recent.error.notsetup=Ð’Ñ‹ должны наÑтроить Ñто окно. Ðажмите на Ñимвол плюÑа и выберите журнал, который вы хотели бы видеть в Ñтом окне. + +portal.recent.error.userstatus=Дневник Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ð» удалён или заморожен. + +portal.recent.items.description=По умолчанию отображаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ ÑÐ°Ð¼Ð°Ñ Ð¿Ð¾ÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑŒ. + +portal.recent.items.name=Сколько показывать + +portal.recent.journal.description=ЗапиÑи какого дневника вы хотите видеть? + +portal.recent.journal.name=Дневник + +portal.recent.nosubject=(Без темы) + +portal.recent.permlink=СÑылка + +portal.recent.portalname=Свежие запиÑи + +portal.recent.portaltitle=Свежие запиÑи + +portal.recent.showtext.description=По умолчанию отображаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ заголовки + +portal.recent.showtext.name=Показывать текÑÑ‚ + +portal.stats.journalentyest=Вчерашние запиÑи + +portal.stats.portalname=СтатиÑтика Ñайта + +portal.stats.portaltitle=СтатиÑтика + +portal.stats.totalusers=Ð’Ñего пользователей + +portal.update.mode.des=РаÑширенный режим предоÑтавлÑет множеÑтво дополнительных наÑтроек, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ добавлÑÑ‚ÑŒ запиÑи в дневники ÑообщеÑтв, возможноÑÑ‚ÑŒ выбрать текущее наÑтроение, музыку и картинку. ПроÑтой режим удобнее, еÑли вы врÑд ли воÑпользуетеÑÑŒ Ñтими возможноÑÑ‚Ñми и предпочли бы не видеть их ÑовÑем. + +portal.update.mode.full=РаÑширенный + +portal.update.mode.name=Режим + +portal.update.mode.simple=ПроÑтой + +portal.update.portalname=Добавление запиÑи + +portal.update.portaltitle=Добавьте запиÑÑŒ в Ñвой дневник + +protocol.bad_password=Ваш пароль Ñлишком проÑтой, его легко угадать или подобрать. Мы рекомендуем вам Ñменить пароль, в противном Ñлучае ваш журнал может быть взломан. Зайдите на Ñтраницу [[siteroot]]/changepassword.bml , чтобы Ñменить пароль. + +protocol.hello_test=ЗдравÑтвуйте, Пробный Пользователь! + +protocol.mail_bouncing=Ð’ наÑтоÑщий момент ваш e-mail не работает. ПиÑьма, отправленные вам, возвращаютÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾. Чтобы продолжать иÑпользовать [[sitename]], вам нужен работающий e-mail. Зайдите на Ñтраницу [[siteroot]]/support/faqbrowse.bml?faqid=19 , чтобы узнать, как Ñменить Ñвой Ð°Ð´Ñ€ÐµÑ e-mail. + +protocol.modpost=Ваша запиÑÑŒ была помещена в очередь на модерирование. Она будет принÑта или отклонена одним из модераторов ÑообщеÑтва. + +protocol.must_revalidate=Ваш новый e-mail Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть подвержден. Старый был в порÑдке, но поÑкольку вы его Ñменили - вы должны подтвердить новый адреÑ. Ðе Ñделав Ñтого, вы не получите доÑтупа ко вÑем функциÑм [[sitename]]. Подробнее - по адреÑу [[siteroot]]/support/faqbrowse.bml?faqid=11 . + +protocol.not_validated=Ваш e-mail Ð°Ð´Ñ€ÐµÑ Ð½Ðµ был подвержден. Ð’Ñ‹ можете продолжать иÑпользовать [[sitename]], но до тех пор, пока Ð°Ð´Ñ€ÐµÑ Ð½Ðµ подтвержден, вы не получите доÑтупа ко вÑем функциÑм Ñайта. ОбратитеÑÑŒ к инÑтрукции, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° выÑлана вам при Ñоздании журнала, или по адреÑу [[siteroot]]/support/faqbrowse.bml?faqid=11 . + +protocol.old_win32_client=Мы рекомендуем вам обновить клиентÑкую программу на более новую верÑию. Чтобы Ñкачать ее, перейдите на Ñтраницу [[siteroot]]/download/ . + +protocol.readonly=Ваш журнал временно находитÑÑ Ð² режиме запрета запиÑи. Ðекоторые команды будут недоÑтупны в течение неÑкольких минут. + +Sorry|notes=typically used to announce that the requested action can't be done. +Sorry=Извините + +talk.anonwrote=Ðекто напиÑал, + +talk.anonwrote_comm=Ðекто напиÑал в [[commlink]], + +talk.btn.preview=ПроÑмотр + +talk.commentpermlink=ÑÑылка + +talk.commentpost=Добавить комментарий + +talk.commentsread=Читать комментарии + +talk.curname_Mood=ÐаÑтроение: + +talk.curname_Music=Музыка: + +talk.error.bogusargs=Ðеверные аргументы + +talk.error.comm_deleted=Комментарий был удалён. + +talk.error.deleted=Этот журнал удалён. + +talk.error.deleted.title=Удалён + +talk.error.mustlogin=Чтобы Ñмотреть Ñту защищённую запиÑÑŒ, вы должны войти в ЖЖ под Ñвоим именем и паролем. + +talk.error.nocomment=Комментарий не ÑущеÑтвует. + +talk.error.noentry=Ðет такой запиÑи. + +talk.error.nojournal=Ошибка: по аргументам невозможно уÑтановить журнал. + +talk.error.nosuchjournal=Ðет такого журнала + +talk.error.notauthorised=У Ð²Ð°Ñ Ð½ÐµÑ‚ полномочий Ñмотреть Ñту защищённую запиÑÑŒ. + +talk.error.suspended=Этот журнал/комментатор заморожен. + +talk.error.suspended.title=Заморожен + +talk.parentlink=Уровень выше + +talk.readsimilar=Читать похожие журнальные запиÑи: + +talk.replytothis=Ответить + +talk.somebodywrote=Пишет [[realname]] ([[userlink]]) + +talk.somebodywrote_comm=Пишет [[realname]] ([[userlink]]) в [[commlink]] + +talk.spellcheck=Проверка правопиÑÐ°Ð½Ð¸Ñ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ñмотра + +talk.threadlink=Ветвь диÑкуÑÑии + +thislang.community|notes=Name of community you use to discuss the translation for this language. +thislang.community=lj_russian + +Username=Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ + +userpic.inactive=Ðеактивна + +xcolibur.greeting.anon=Добро пожаловать в Живой Журнал! + +xcolibur.greeting.logged_in=Привет, [[name]]! [[logout]] + +xcolibur.login=Вход + +xcolibur.logout=Выход + +xcolibur.nav.about=О Ñайте + +xcolibur.nav.about.download=Загрузка + +xcolibur.nav.about.general=ÐžÐ±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +xcolibur.nav.about.paidaccounts=Оплата + +xcolibur.nav.about.press=ПреÑÑа + +xcolibur.nav.about.sitenews=ÐовоÑти + +xcolibur.nav.about.stats=СтатиÑтика + +xcolibur.nav.footer.sitemap=Карта Ñайта + +xcolibur.nav.help=Помощь + +xcolibur.nav.help.ask=Задать Ð²Ð¾Ð¿Ñ€Ð¾Ñ + +xcolibur.nav.help.contact=Контакты и Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ + +xcolibur.nav.help.faq=Справка ЖЖ + +xcolibur.nav.help.lostpassword=Забыли пароль? + +xcolibur.nav.home=Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница + +xcolibur.nav.journal=Журнал + +xcolibur.nav.journal.archive=Календарь + +xcolibur.nav.journal.edit.entries=Редактировать запиÑи + +xcolibur.nav.journal.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +xcolibur.nav.journal.info=О пользователе + +xcolibur.nav.journal.memories=Избранное + +xcolibur.nav.journal.recent=Свежие запиÑи + +xcolibur.nav.journal.update=ÐапиÑать + +xcolibur.nav.manage=Редактировать + +xcolibur.nav.manage.community=СообщеÑтва + +xcolibur.nav.manage.customize=Оформление + +xcolibur.nav.manage.entries=ЗапиÑи + +xcolibur.nav.manage.friends=Ð”Ñ€ÑƒÐ·ÑŒÑ + +xcolibur.nav.manage.info=О пользователе + +xcolibur.nav.manage.password=Сменить пароль + +xcolibur.nav.manage.pics=Картинки + +xcolibur.nav.manage.styles=Стили + +xcolibur.nav.search=ПоиÑк + +xcolibur.nav.search.directory=По региону + +xcolibur.nav.search.directory.search=По каталогу + +xcolibur.nav.search.interests=По интереÑам + +xcolibur.nav.search.random=Случайно + +xcolibur.nav.siteopts=ÐаÑтройки Ñайта + +xcolibur.nav.title=БыÑтрый переход: + +xcolibur.nav.welcome=Добро пожаловать + +xcolibur.nav.welcome.create=Создать журнал + +xcolibur.nav.welcome.login=Вход + +xcolibur.nav.welcome.update=Добавить запиÑÑŒ + +xcolibur.search=Ðайти в ЖЖ: + +xcolibur.search.category=Что именно: + +xcolibur.search.icq=Ðомер ICQ + +xcolibur.search.int=Ð˜Ð½Ñ‚ÐµÑ€ÐµÑ + +xcolibur.search.msn=Ð˜Ð¼Ñ Ð² MSN + +xcolibur.search.region=Регион + +xcolibur.upgrade=Стань платным пользователем + diff --git a/ljcom/bin/upgrading/s2layers-local.dat b/ljcom/bin/upgrading/s2layers-local.dat new file mode 100644 index 0000000..6f9e198 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers-local.dat @@ -0,0 +1,39 @@ +################################################################ +# LiveJournal.com's non-free (not GPL) layers. You can use the +# source to learn from, but not copy. +################################################################ +# base filename layer type parent + +3column/layout layout core1 +3column/themes theme+ 3column/layout + +anovelconundrum/layout layout core1 +anovelconundrum/themes theme+ anovelconundrum/layout + +boxer/layout layout core1 +boxer/themes theme+ boxer/layout + +component/layout layout core1 +component/themes theme+ component/layout + +cuteness/layout layout core1 + +flexiblesquares/layout layout core1 +flexiblesquares/themes theme+ flexiblesquares/layout + +nebula/layout layout core1 +nebula/themes theme+ nebula/layout + +opal/layout layout core1 +opal/themes theme+ opal/layout + +smoothsailing/layout layout core1 +smoothsailing/themes theme+ smoothsailing/layout + +tranquilityii/layout layout core1 +tranquilityii/themes theme+ tranquilityii/layout + +unearthed/layout layout core1 +unearthed/themes theme+ unearthed/layout + +s2layers-ljcomint.dat INCLUDE diff --git a/ljcom/bin/upgrading/s2layers/3column/layout.s2 b/ljcom/bin/upgrading/s2layers/3column/layout.s2 new file mode 100644 index 0000000..befd9b0 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/3column/layout.s2 @@ -0,0 +1,1102 @@ +layerinfo "type" = "layout"; +layerinfo "name" = "3 column"; +layerinfo author_name = "Louise (unfloopy)"; +layerinfo author_email = "unfloopy@gmail.com"; +layerinfo des = "3 column layout by Louise (/~unfloopy)."; +layerinfo redist_uniq = "3column/layout"; + +################################## PROPERTIES #################################### + +propgroup prez = "Presentation"; +propgroup prez { + property bool show_entry_userpic { des = "Always display userpic?"; } + property use use_shared_pic; + property use view_entry_disabled; + property int page_recent_items { des = "Recent Entries: Number of Posts"; } + set page_recent_items = 10; + property int page_friends_items{ des = "Friends Page: Number of Posts"; } + set page_friends_items= 20; + set show_entry_userpic = true; +} + +propgroup text = "Text"; +propgroup text { + property string t_forward { des = "Entries Navigation: Forward link"; } + set t_forward = " forward >"; + property string t_back { des = "Entries Navigation: Back link"; } + set t_back = "< back "; + property string t_post_comment{ des = "Entries Navigation: Post A Comment text"; } + set t_post_comment= "reply"; + property string t_reply_back{ des = "Entries Navigation: Comments text"; } + set t_reply_back= "comments"; + property string t_perma{ des = "Entries Navigation: Perma Link text"; } + set t_perma= "link"; + property string t_divider { des = "Entries Navigation: Links divider"; } + set t_divider = " "; + property string t_comment_reply{ des = "Comments Navigation: Reply text"; } + set t_comment_reply= "reply"; + property string t_read_comments{ des = "Comments Navigation: Read Comments"; } + set t_read_comments= "#"; + property string t_view_recent{ des = "Navigation Bar: The Recent Entries Item"; } + set t_view_recent = "recent"; + property string t_view_archive{ des = "Navigation Bar: The Archive Item"; } + set t_view_archive= "archive"; + property string t_view_userinfo { des = "Navigation Bar: The Userinfo Item"; } + set t_view_userinfo = "userinfo"; + property string t_view_friends{ des = "Navigation Bar: The Friends Item"; } + set t_view_friends= "friends"; + property string t_nosubject{ des = "No Subject Text"; } + set t_nosubject= "(no subject)"; + property string t_noentries_day{ des = "Text for a day without posts"; } + set t_noentries_day= "I didn't post on this day. Sorry!"; + property string t_meta_music{ des = "Music Text"; } + set t_meta_music= "current song"; + property string t_meta_mood { des = "Mood Text"; } + set t_meta_mood= "current mood"; + property string t_view_month{ des = "Archive Navigation: View Subjects link text"; } + set t_view_month= "view all"; + property string t_read_comments_friends{ des = "Friends Page: Read Comments"; } + set t_read_comments_friends= "#"; + property string links_header { des = "Links header"; } + set links_header = "links"; + property string about_title { des = "About box title"; } + set about_title= "about"; + property string nav_title { des = "Navigation title"; } + set nav_title= "navigate"; + property string blurb_title { des = "Blurb Title"; note = "Only used if you enter some blurb text below."; } + set blurb_title= "blurb"; + property string blurb_text { des = "Blurb Text"; + note = "You can write here about anything you want. It'll be displayed in a box on your journal pages."; } + set blurb_text= ""; + +} + +propgroup images = "Images"; +propgroup images { + property string bg_image { des = "Background Image URL [optional]"; } + set bg_image = ""; + property string bg_repeat { des = "Background Image Repeat"; values = "repeat|Tile image|no-repeat|Do not tile image"; } + set bg_repeat = "repeat"; + property string header_image { des = "Header: Image URL [optional]"; note = "If you set this, you must also enter the height of your image below."; } + set header_image = ""; + property string header_height { des = "Header: Height"; note = "You must set this if you've entered a header image URL above."; } + set header_height = "0px"; + property string i_comment { des = "Icon: Comments"; note = "If you don't set this, a default image will be used."; } + set i_comment = ""; + property string i_perma { des = "Icon: PermaLink"; note = "If you don't set this, a default image will be used."; } + set i_perma = ""; + property string i_mem { des = "Icon: Add To Memories"; note = "If you don't set this, a default image will be used."; } + set i_mem = ""; + property string i_leave { des = "Icon: Leave A Comment"; note = "If you don't set this, a default image will be used."; } + set i_leave = ""; + property string i_edit { des = "Icon: Edit Entry"; note = "If you don't set this, a default image will be used."; } + set i_edit = ""; +} + +propgroup stylesheet = "Styles"; +propgroup stylesheet { + property string font_size { des = "Overall: Text Size"; } + set font_size = "8pt"; + property string font_family { des = "Overall: Font Family"; } + set font_family = "Arial"; + property string link_weight { des = "Overall: Link Weight"; values = "normal|Normal|bold|Bold"; } + set link_weight = "normal"; + property string link_side_w { des = "Sidebar: Link weight"; values = "normal|Normal|bold|Bold"; } + set link_side_w = "normal"; + property string side_h_size { des = "Sidebar: Header Font Size"; } + set entries_size = "9pt"; + property string entries_size { des = "Entries: Text Size"; } + set c_sub_size = "10pt"; + property string sub_size { des = "Entries: Subject Text Size"; } + set side_h_size = "13px"; + property string c_sub_size { des = "Comments: Subject Text Size"; } + set sub_size = "15pt"; +} + +propgroup colors = "Color"; +propgroup colors { + property Color color_bg { des = "Background Color"; } + set color_bg = "#E6CABE"; + property Color font_color { des = "Overall: Font Color"; } + set font_color = "#4B3730"; + property Color link_color { des = "Overall: Link Color"; } + set link_color = "#78534B"; + property Color link_hover { des = "Overall: Link Hover Color"; } + set link_hover = "#78534B"; + property Color link_side { des = "Sidebar: Link color"; } + set link_side = "#4B3730"; + property Color link_side_h { des = "Sidebar: Link hover color"; } + set link_side_h = "#4B3730"; + property Color side_bg { des = "Sidebar: Background color"; } + set side_bg = "#E6CABE"; + property Color side_t_color { des = "Sidebar: Text color"; } + set side_t_color = "#4B3730"; + property Color side_border { des = "Sidebar: Borders"; } + set side_border = "#DAB5AC"; + property Color side_h_color { des = "Sidebar: Header Color"; } + set side_h_color = "#333333"; + property Color side_h_border { des = "Sidebar: Header Border"; } + set side_h_border = "#333333"; + property Color side_h_bg { des = "Sidebar: Header Background"; } + set side_h_bg = "#DAB5AC"; + property Color entries_bg { des = "Entries: Background color"; } + set entries_bg = "#E6CABE"; + property Color entries_border { des = "Entries: Border color"; } + set entries_border = "#DAB5AC"; + property Color button_bg { des = "Entries: Buttons background"; } + set button_bg = "#E6CABE"; + property Color button_bg_h { des = "Entries: Buttons Background hover"; } + set button_bg_h = "#ECD7C7"; + property Color entries_font_color { des = "Entries: Font Color"; } + set entries_font_color = "#4B3730"; + property Color sub_color { des = "Entries: Subject Color"; } + set sub_color = "#78534B"; + property Color c_sub_color { des = "Comments: Subject Text Color"; } + set c_sub_color = "#4B3730"; + property Color c_sub_bg { des = "Comments: Subject Background"; } + set c_sub_bg = "#DAB5AC"; +} + +set tags_aware = true; +property string i_tags { des = "Icon: Edit Tags"; } + +####################################### STYLESHEET ####################################### + +function print_stylesheet () {""" +body { background: $*color_bg; font: $*font_size $*font_family; color: $*font_color; +"""; if (clean_url($*bg_image) != "") { + """ background-image: url('$*bg_image'); + background-repeat: $*bg_repeat; +"""; } """ } +a { color: $*link_color; font-weight: $*link_weight; } +a:hover { color: $*link_hover; font-weight: $*link_weight; } +h1{ color: $*sub_color; font-size: $*sub_size; text-align:left; padding:5px; margin:0px; border-bottom: 1px dashed $*entries_border; } +h2{ border: 1px solid $*side_h_border; font-size: $*side_h_size; text-align:center; margin:3px 0px; padding:0px; background-color: $*side_h_bg; color: $*side_h_color; } +h3{ color: $*sub_color; text-align:left; font: bold arial; padding:5px; margin:0px; border-top: solid 1px $*entries_border;} +ul.links{ margin: 1px 0px; padding: 3px; color: $*side_t_color; list-style-type:none; } +li.links { margin-left: 5px; } +li.links a{ text-decoration:none; } +li.links_header{ font: 11px; border-bottom: 1px solid $*side_t_color; padding-top:7px; } + +#container{position:absolute; top: $*header_height;} +#leftbar{ position:absolute; top: 10px; left: 10px; width: 170px;} +#rightbar{ position:absolute; top: 10px; right: 0px; width: 170px;} +#leftbar a, #rightbar a {color: $*link_side; font-weight: $*link_side_w;} +#leftbar a:hover, #rightbar a:hover {color: $*link_side_h; } +#entries{ position:relative; margin: 10px 170px 10px 180px; text-align:center; background: $*entries_bg; border: 3px double $*entries_border; padding: 10px; } +#readme { text-align:justify; padding: 2px; } +#header { position:absolute; width: 100%; top: 0px; left: 0px; height: $*header_height; +"""; if (clean_url($*header_image) != "") { + """ background-image: url('$*header_image'); + background-repeat: no-repeat; background-position: center; +"""; } """ } + +div.entrylinks { font: 8pt Verdana; text-align:right; padding:2px 10px 2px 10px; line-height:20px; margin-bottom:0px; margin-top:5px; border-top: 1px dashed $*entries_border; } +div.entrylinks a { background-color: $*button_bg; text-decoration:none; margin:2px; padding:2px; } +div.entrylinks a:hover {background-color: $*button_bg_h;} +div.entrylinks img { border:0px; text-decoration:none; } +div.entry{ margin-bottom:35px;} + +.entrytext{ font: $*entries_size Arial; text-align:justify; color: $*entries_font_color; } +.aboutentry{ text-align: left; margin-right:10px; } +.userpic{ margin:5px; } +.sidebox{ border: 3px double $*side_border; background: $*side_bg; margin: 10px; padding:5px; } +.userpic2{ position:relative; float:left; padding: 5px; margin:0px 0px 0px 0px;} +.userpic_reply{ position:relative; float:left; padding: 5px;} +.moodpic{ position:relative; float:right; padding: 0px; padding-left: 5px; margin:0px; margin-top: -10px; margin-right: -5px; } +.calendarActive{ font-weight:bold; } +.blurb { color: $*side_t_color; } +.nosubject { font-style:italic; } +.replyform { text-align:left; clear: both; } +.replyform textarea { width: 100% ! important; } +.comment_postedby { text-align:left; font-weight:bold; } +.comment_date{ text-align:left; } +.comment_subject { color: $*c_sub_color; background: $*c_sub_bg; font: $*c_sub_size; font-weight:bold; letter-spacing:1.5px; text-align:left; padding:3px; margin-right: 0;} +.comment_wrapper{ border: 1px solid $*entries_border; background: $*entries_bg; padding:5px; margin: 0px 0px 5px 0px; } +.comment_info { width:95%; } +.comment_links { text-align:right; padding:3px; margin:0px; border-top: 1px dashed $*entries_border; } +.comment_links a { padding:2px; text-decoration:none; } +.comment_child { margin: 0px 0px 0px 20px; } +.minicomment {padding: 4px; border: 1px solid $*entries_border; } +.minicommentholder { border: 1px solid $*entries_border; } + +"""; } + +############################# FUNCTIONS ######################################## + +function prop_init() +{ + if ($*i_comment == "") { $*i_comment = "$*IMGDIR/style/3column/comments.gif"; } + if ($*i_perma == "") { $*i_perma = "$*IMGDIR/style/3column/permalink.gif"; } + if ($*i_mem == "") { $*i_mem = "$*IMGDIR/style/3column/memories.gif"; } + if ($*i_leave == "") { $*i_leave = "$*IMGDIR/style/3column/leavecomment.gif"; } + if ($*i_edit == "") { $*i_edit = "$*IMGDIR/style/3column/editentry.gif"; } + if ($*i_tags == "") { $*i_tags = "$*IMGDIR/style/3column/edittags.gif"; } +} + +function generateDots (string un) : string { + var string dots; + if($un != "") { + foreach var string s ($un) { + if($s == "a" or $s == "c" or $s == "e" or $s == "f" or $s == "h" or $s == "k" or $s == "m" or $s == "n" or $s == "p" or $s == "r" or $s == "t" or $s == "v" or $s == "x" or $s == "z") { + $dots = $dots + ":"; + } elseif($s == " ") { + + $dots = $dots + " "; + } else { + $dots = $dots + "."; + } + } + } + return $dots; +} + +function print_linkbox (string header, string text) { + """ + + """; + +} + +function box_item (string text) : string { + return """$text\n"""; +} + +function print_box (string header, string text) { + """ + + """; + +} + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function Page::lay_print_userpic() { + if(defined $.journal.default_pic) { + """ +
            +$.journal.name +
            + """; + } +} + + +function Page::print_linklist() { + if (size $.linklist <= 0) { + return; + } + + var string links; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + $links = $links + """"""; + } else { + $links = $links + box_item(""""""); + } + } + } + + print_linkbox($*links_header, $links); +} + +function Page::lay_print_calendar () { + var YearMonth m = $this->get_latest_month(); + var string mon = $m->month_format(); + var string text; + $text = """ + """; + foreach var YearWeek w ($m.weeks) { + $text = $text + """ + """; + if($w.pre_empty > 0) { + foreach var int empty (1..$w.pre_empty) { + $text = $text + """ + """; + } + } + foreach var YearDay d ($w.days) { + if($d.num_entries > 0) { + $text = $text + """ + """; + } else { + $text = $text + """ + """; + } + } + $text = $text + "\n"; + } + $text = $text + "
             $d.day$d.day
            "; + print_box($mon, $text); +} + + +function Page::lay_print_subnav () { } + +function RecentPage::lay_print_subnav () { + var string back; + if($.nav.backward_url != "") { + $back = """$*t_back"""; + } else { + $back = " "; + } + var string forward; + if($.nav.forward_url != "") { + $forward = """$*t_forward"""; + } else { + $forward = " "; + } + + var int start = $.nav.skip; + var int end = $.nav.skip + size $.entries; + var string text = "$start - $end"; + """ +
            $back | $text | $forward
            + """; +} + +function FriendsPage::lay_make_username (Entry e) { + var Friend f = $.friends{$e.journal.username}; + var string url = $e.poster->base_url(); + """ + $e.poster.username + """; + if($e.poster.username != $e.journal.username) { + """ $e.journal"""; + } + +} +function EntryPage::print_body() { + """ """; + $this->print_entry($.entry); + if ($this.multiform_on) { + $this->print_multiform_start(); + } + + if ($.entry.comments.count > 0) { + """ +

            Comments

            + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($.entry.comments.enabled) { + $this->print_comments($.comments); + } + + + if ($.entry.comments.count > 0) { + """ +
            + """; + + $.entry.comments->print(); + + """ +
            + """; + } + + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + if ($this.multiform_on and ($.entry.comments.count > 0)) { + """ +
            + """; + $this->print_multiform_actionline(); + """ +
            + """; + $this->print_multiform_end(); + } + """ """; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + } +} + +function EntryPage::print_comment(Comment c) { + var string datetime; + $datetime = $c.time->date_format("long")+", " + $c.time->time_format(); + var string picword; + if (defined $c.userpic and $*comment_userpic_style !="off") { + $picword = $c.metadata{"picture_keyword"}; + } + var string parent; + var string thread; + if($c.parent_url != "") { + $parent = """$*text_comment_parent$*t_divider"""; + } + if($c.thread_url != "") { + $thread = """$*text_comment_thread$*t_divider"""; + } + var string subjecticon; + if (defined $c.subject_icon) { + $subjecticon = """"""; + } + var string ip; + if ($c.metadata{"poster_ip"}) { + $ip = """   """ + $c.metadata{"poster_ip"}; + } + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string poster_name; $poster_name= $c.poster.name; + var string pic; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $pic = """ + $picword"""; + } + + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
            + + +
            +
            Posted by: $poster_name ($poster) $ip
            +
            Posted at: $subjecticon $datetime
            + """; + + if ($.multiform_on) { + """
            """; + $c->print_multiform_check(); + """
            + """; + } + + """ +
            $c.subject
            $pic
            + +

            $c.text

            + + """; + + if ((size $c.replies) > 0 and $c.replies[0].full == false) { + """
            \n"""; + $this->print_comments($c.replies); + "
            \n"; + } + + """ +
            + """; + if ((size $c.replies) > 0 and $c.replies[0].full == true) { + """
            """; + $this->print_comments($c.replies); + """
            """; + } + +} + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string subj = $c.subject != "" ? $c.subject : """$*t_nosubject"""; + var string indent = ($c.depth - 1) * 25 + "px"; + """ +
            +
            $poster - $subj
            + """; + $this->print_comments($c.replies); +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ +
            + """; + print lang_page_of_pages($.current, $.total); + " — "; + foreach var int i (1..$.total) { + if ($i == $.current) { """[$i]"""; + + } else { + var string url_of = $this->url_of($i); + "[$i]"; + } + } + """
            """; +} +function Page::print_entry (Entry e) { + # Print an anchor + print """"""; + # Get the right time and date of the post + var string time = $e.time->time_format(); + var string date = $e.time->date_format("long"); + # Get the Locked or Private icon, if needed. + var string security; + if ($e.security != "") { + $security = """"""; + } + + var UserLite name; + var string pname; + var string poster_name; $poster_name= $e.poster.name; + var string poster = defined $e.poster ? $e.poster->as_string() : "$*text_poster_anonymous"; + var bool show_name = ($.view == "friends" or $e.poster.username != $.journal.username or $.view == "entry") ? true : false; + var bool show_pic = (defined $e.userpic and ($.view == "friends" or $*show_entry_userpic or $e.poster.username != $e.journal.username or $.view == "entry")) ? true : false; + + if ($.view == "friends"){ """ + +
            + """; if($show_pic) { + """ +
            +$e.poster.name [userpic] +
            """; } """ + +
            $security $e.subject
            +
            """; + if($e.poster.username != $e.journal.username) { + """ in $e.journal
            """; + } """ by $poster_name ($poster)
            +
            at $date ($time)"""; + + $e->print_metadata(); """ +
            + + +

            $e.text

            + +
            """; + + } else { + +if($show_pic) { + """ +
            +$e.poster.name [userpic] +
            + """; + } """ + +
            +

            $e.subject

            +
            $security $date ($time) +"""; + + $e->print_metadata(); + + """ +
            +
            +

            $e.text

            +
            + +
            + """; + } +} + + +function CommentInfo::print() { + if ($.enabled) { + if ($.count > 0 or $.screened) { + $this->print_readlink(); + } + $this->print_postlink(); + } +} + +function CommentInfo::print_postlink() { + var Page p = get_page(); + """$*t_post_comment $*t_divider """; +} + +function CommentInfo::print_readlink { + var Page p = get_page(); + ""+ + get_plural_phrase($.count, $p.view == "friends" ? + "t_read_comments_friends" : "t_read_comments")+ + "\"$*t_divider"; +} + +function DayPage::lay_print_subnav () { + var string back; + if($.prev_url != "") { + $back = """$*t_back"""; + } else { + $back = " "; + } + var string forward; + if($.next_url != "") { + $forward = """$*t_forward"""; + } else { + $forward = " "; + } + + var string text = $.date->date_format("long"); + + """ +
            $back | $text | $forward
            + """; + +} + + + +############################# REPLY PAGE ######################################### + +function ReplyPage::print_body() { + + var EntryLite e = $.replyto; + var string poster = defined $e.poster ? $e.poster->as_string() : "$*text_poster_anonymous"; + var string datetime; + var string time = $e.time->time_format(); + var string date = $e.time->date_format("long"); + + var UserLite name; + """ +
            +

            $date

            """; +if(defined $e.userpic and $*comment_userpic_style != "off") { + $name = $e.poster; + """
            """; + if (defined $e.userpic or (defined $e.userpic and $.view == "entry" and $*show_entry_userpic)) { + """"""; + } + """
            """; + } """ + +

            $e.subject

            +
            +

            $e.text

            + +
            + """; + $.form->print(); + """ +
            + """; +} + +function Entry::print_metadata() { + var string caption; + var string val; + var Image i; + print $this->get_tags_text(); + if (size $.metadata == 0) { return; } + foreach var string k ($.metadata) { + $caption = $k; + $val = $.metadata{$k}; + if ($k == "music") { + $caption = $*t_meta_music; + } + elseif ($k == "mood") { + $caption = $*t_meta_mood; + if (defined $.mood_icon) { + $i = $.mood_icon; + $val = """
            $val
            $val"""; + } + } + println """
            $caption: $val"""; + } +} + + +################################ VIEWS ######################################### + +function RecentPage::print_body () { + """ +
            + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """ +
            + """; +} + + +function DayPage::print_body() { + + """
            """; + if ($.has_entries) { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + "

            $*t_noentries_day

            "; + } + """
            """; + +} + +function MonthPage::view_title : string { + return $.date->date_format($*lang_fmt_month_long); +} + +function MonthPage::print_body { + ""; + $.redir->print_hiddens(); + var string back; + var string forward; + if ($.prev_url != "") { $back = """$*t_back"""; } + if ($.next_url != "") { $forward = """$*t_forward"""; } + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
            + + + + + + +
            $back$select$forward
            +
            + """; + ""; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + +
            +
            + +
            +
            + """; + $d->print_subjectlist(); + """ +
            +
            +
            + + """; + } + } +} + +function MonthDay::print_subjectlist() { + + foreach var Entry e ($.entries) { + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + """ $*t_nosubject"""; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "t_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
            \n"; + } +} + +function YearPage::print_body { + $this->print_year_links(); + """
            """; + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + """
            """; +} + +function YearPage::print_year_links() { + """
            """; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """$y.year"""; + } else { + """$*t_divider$y.year$*t_divider"""; + } + } + """
            """; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """ + +
            +
            + + +
            +
            + + """; + + foreach var int d (weekdays()) { + """ + + """; + } + """ + + """; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + """ +
            $*lang_dayname_short[$d]
            +
            +
            + """; + +} + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + """ + +
            $day
            + """; + if ($d.num_entries > 0) { + var string num = $d.num_entries < 10 ? " " + string($d.num_entries) : string($d.num_entries); + """ + + """; + } else { + """ +
            -
            + """; + +} + """ + + """; + } + """ + + """; +} + +# Override the view names to be all short and lowercase-like +function lang_viewname(string viewid) [notags] : string +"Get some words representing a view" +{ + if ($viewid == "recent") { return $*t_view_recent; } + if ($viewid == "archive") { return $*t_view_archive; } + if ($viewid == "friends") { return $*t_view_friends; } + if ($viewid == "day") { return "day"; } + if ($viewid == "month") { return "month"; } + if ($viewid == "userinfo") { return $*t_view_userinfo; } + if ($viewid == "entry") { return "read comments"; } + if ($viewid == "reply") { return "post comment"; } + return "Unknown View"; +} + +############################## COMMON HTML ############################################ + +function Page::print () { + + var string title = $this->title(); + + """ + + + + $title + + """; + + $this->print_head(); + + + if ($*external_stylesheet) { + println """"""; + } + else { + println """"""; + } + + """ + + + + +
            + + +
            +"""; + $this->lay_print_subnav(); + $this->print_body(); + $this->lay_print_subnav(); + """ + +
            + +
            + + + + +"""; +$this->print_linklist(); +""" + +
            + +
            + + + + + +"""; +$this->lay_print_calendar(); +""" + +
            + +
            + +
            + + + """; +} diff --git a/ljcom/bin/upgrading/s2layers/3column/themes.s2 b/ljcom/bin/upgrading/s2layers/3column/themes.s2 new file mode 100644 index 0000000..886bba9 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/3column/themes.s2 @@ -0,0 +1,233 @@ +#NEWLAYER: 3column/blue +layerinfo "type" = "theme"; +layerinfo "name" = "Blue"; +layerinfo "redist_uniq" = "3column/blue"; + +set color_bg = "#e9f3fa"; +set font_color = "#0d446b"; +set link_color = "#0d446b"; +set link_hover = "#0d446b"; +set link_side = "#0d446b"; +set link_side_h = "#0d446b"; +set side_bg = "#e9f3fa"; +set entries_bg = "#e9f3fa"; +set entries_border = "#0d446b"; +set side_t_color = "#0d446b"; +set button_bg = "#e9f3fa"; +set button_bg_h = "#b0cce0"; +set entries_font_color = "#0d446b"; +set side_border = "#0d446b"; +set c_sub_color = "#b0cce0"; +set c_sub_bg = "#0d446b"; +set side_h_color = "#0d446b"; +set side_h_border = "#0d446b"; +set side_h_bg = "#b0cce0"; +set sub_color = "#0d446b"; + +#NEWLAYER: 3column/dark +layerinfo "type" = "theme"; +layerinfo "name" = "Dark"; +layerinfo "redist_uniq" = "3column/dark"; + +set color_bg = "#000000"; +set font_color = "#c0c0c0"; +set link_color = "#202020"; +set link_hover = "#FFFFFF"; +set link_side = "#95432D"; +set link_side_h = "#BA7625"; +set side_bg = "#000000"; +set side_t_color = "C0C0C0"; +set side_border = "#000000"; +set side_h_color = "#C0C0C0"; +set side_h_border = "#C0C0C0"; +set side_h_bg = "#000000"; +set entries_bg = "#58494E"; +set entries_border = "#FFFFFF"; +set button_bg = "#FFFFFF"; +set button_bg_h = "#c0c0c0"; +set entries_font_color = "#000000"; +set c_sub_color = "#000000"; +set c_sub_bg = "#ffffff"; +set sub_color = "#C0C0C0"; + +#NEWLAYER: 3column/earth +layerinfo "type" = "theme"; +layerinfo "name" = "Earth"; +layerinfo "redist_uniq" = "3column/earth"; + +set color_bg = "#ECECEA"; +set font_color = "#4F4637"; +set link_color = "#4F4637"; +set link_hover = "#1D4629"; +set link_side = "#7B6E59"; +set link_side_h = "#1D4629"; +set side_bg = "#DBCEB9"; +set side_t_color = "4F4637"; +set side_border = "#7B6E59"; +set side_h_color = "#ECECEA"; +set side_h_border = "#ECECEA"; +set side_h_bg = "#7B6E59"; +set entries_bg = "#AB9F8B"; +set entries_border = "#7B6E59"; +set button_bg = "#ECECEA"; +set button_bg_h = "#4F4637"; +set entries_font_color = "#4F4637"; +set c_sub_color = "#4F4637"; +set c_sub_bg = "#ECECEA"; +set sub_color = "#4F4637"; + +#NEWLAYER: 3column/unnamed +layerinfo "type" = "theme"; +layerinfo "name" = "Unnamed"; +layerinfo "redist_uniq" = "3column/unnamed"; + +set color_bg = "#E5D5C6"; +set font_color = "#000000"; +set link_color = "#202020"; +set link_hover = "#000000"; +set link_side = "#95432D"; +set link_side_h = "#D63C3C"; +set side_bg = "#E5D5C6"; +set side_t_color = "#000000"; +set side_border = "#E5D5C6"; +set side_h_color = "#000000"; +set side_h_border = "#000000"; +set side_h_bg = "#E5D5C6"; +set entries_bg = "#E5D5C6"; +set entries_border = "#E5D5C6"; +set button_bg = "#E5D5C6"; +set button_bg_h = "#ccab8a"; +set entries_font_color = "#000000"; +set c_sub_color = "#ccab8a"; +set c_sub_bg = "#E5D5C6"; +set sub_color = "#000000"; + +#NEWLAYER: 3column/greenenvy +layerinfo "type" = "theme"; +layerinfo "name" = "Green of Envy"; +layerinfo "redist_uniq" = "3column/greenenvy"; + +set color_bg = "#d8ece7"; +set font_color = "#1b2d29"; +set link_color = "#1b2d29"; +set link_hover = "#1b2d29"; +set link_side = "#1b2d29"; +set link_side_h = "#1b2d29"; +set side_bg = "#d8ece7"; +set entries_bg = "#d8ece7"; +set entries_border = "#1b2d29"; +set side_t_color = "#1b2d29"; +set button_bg = "#d8ece7"; +set button_bg_h = "#b1d5cb"; +set entries_font_color = "#1b2d29"; +set side_border = "#1b2d29"; +set c_sub_color = "#b1d5cb"; +set c_sub_bg = "#1b2d29"; +set side_h_color = "#1b2d29"; +set side_h_border = "#1b2d29"; +set side_h_bg = "#b1d5cb"; +set sub_color = "#1b2d29"; + +#NEWLAYER: 3column/blackwhite +layerinfo "type" = "theme"; +layerinfo "name" = "Black and White"; +layerinfo "redist_uniq" = "3column/blackwhite"; + +set color_bg = "#FFFFFF"; +set font_color = "#808080"; +set link_color = "#808080"; +set link_hover = "#202020"; +set link_side = "#c0c0c0"; +set link_side_h = "#FFFFFF"; +set side_bg = "#000000"; +set side_t_color = "808080"; +set side_border = "#ffffff"; +set side_h_color = "#c0c0c0"; +set side_h_border = "#c0c0c0"; +set side_h_bg = "#808080"; +set entries_bg = "#ffffff"; +set entries_border = "#000000"; +set button_bg = "#c0c0c0"; +set button_bg_h = "#808080"; +set entries_font_color = "#000000"; +set c_sub_color = "#ffffff"; +set c_sub_bg = "#000000"; +set sub_color = "#202020"; + +#NEWLAYER: 3column/agentorange +layerinfo "type" = "theme"; +layerinfo "name" = "Agent Orange"; +layerinfo "redist_uniq" = "3column/agentorange"; + +set color_bg = "#f7e6d3"; +set font_color = "#582604"; +set link_color = "#582604"; +set link_hover = "#582604"; +set link_side = "#582604"; +set link_side_h = "#582604"; +set side_bg = "#f7e6d3"; +set entries_bg = "#f7e6d3"; +set entries_border = "#582604"; +set side_t_color = "#582604"; +set button_bg = "#f7e6d3"; +set button_bg_h = "#e0c7aa"; +set entries_font_color = "#582604"; +set side_border = "#582604"; +set c_sub_color = "#e0c7aa"; +set c_sub_bg = "#582604"; +set side_h_color = "#582604"; +set side_h_border = "#582604"; +set side_h_bg = "#e0c7aa"; +set sub_color = "#b64c06"; + +#NEWLAYER: 3column/purple +layerinfo "type" = "theme"; +layerinfo "name" = "Purple"; +layerinfo "redist_uniq" = "3column/purple"; + +set color_bg = "#e8cff1"; +set font_color = "#410458"; +set link_color = "#410458"; +set link_hover = "#410458"; +set link_side = "#410458"; +set link_side_h = "#410458"; +set side_bg = "#e8cff1"; +set entries_bg = "#e8cff1"; +set entries_border = "#410458"; +set side_t_color = "#410458"; +set button_bg = "#e8cff1"; +set button_bg_h = "#d1aae0"; +set entries_font_color = "#410458"; +set side_border = "#410458"; +set c_sub_color = "#d1aae0"; +set c_sub_bg = "#410458"; +set side_h_color = "#410458"; +set side_h_border = "#410458"; +set side_h_bg = "#d1aae0"; +set sub_color = "#410458"; + +#NEWLAYER: 3column/mellowyellow +layerinfo "type" = "theme"; +layerinfo "name" = "Mellow Yellow"; +layerinfo "redist_uniq" = "3column/mellowyellow"; + +set color_bg = "#f8f6da"; +set font_color = "#42331e"; +set link_color = "#42331e"; +set link_hover = "#8d452f"; +set link_side = "#8d452f"; +set link_side_h = "#42331e"; +set side_bg = "#f2c98e"; +set entries_bg = "#f8f6da"; +set entries_border = "#42331e"; +set side_t_color = "#42331e"; +set button_bg = "#f2c98e"; +set button_bg_h = "#e8c098"; +set entries_font_color = "#42331e"; +set side_border = "#42331e"; +set c_sub_color = "#42331e"; +set c_sub_bg = "#f2c98e"; +set side_h_color = "#333333"; +set side_h_border = "#333333"; +set side_h_bg = "#f8f6da"; +set sub_color = "#d39945"; diff --git a/ljcom/bin/upgrading/s2layers/anovelconundrum/layout.s2 b/ljcom/bin/upgrading/s2layers/anovelconundrum/layout.s2 new file mode 100644 index 0000000..9792cb9 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/anovelconundrum/layout.s2 @@ -0,0 +1,999 @@ +# -*-s2-*- + +layerinfo "type" = "layout"; +layerinfo "name" = "A Novel Conundrum"; +layerinfo "source_viewable" = 1; +layerinfo "redist_uniq" = "anovelconundrum/layout"; +layerinfo "author_name" = "taion"; + +propgroup colors { + property Color page_back { + des = "Page background"; + } + property Color entry_text { + des = "Entry text color"; + } + property Color text_weaker { + des = "Weaker text color"; + } + property Color page_link { + des = "Link color"; + } + property Color page_vlink { + des = "Visited link color"; + } + property Color page_alink { + des = "Active link color"; + } +} + +# From my last e-mail with Taion, the plan was to rasterize the leading fonts so that +# appearance issues could be avoided. However, I don't have access to many of the fonts +# that he tested with, so I'll have to put that off for later. + +# You will need access to Microsoft provided fonts for most accurate rendering, but +# we are working on specifying usable alternatives that are cross platform friendly. +propgroup fonts { + property use font_base; + property string font_fallback { + des = "Alternative font style"; + } + property string font_type { + des = "Body font type"; + note = "General font class for body text"; + } + property int font_size { + des = "Body font size (points)"; + } + property int font_leading { + des = "Body font leading (points)"; + } + property string title_letterspacing { + des = "Letterspacing in titles"; + } + property bool title_smallcaps { + des = "Smallcaps in titles"; + } + property bool title_underline { + des = "Underlined titles"; + } + property string font_flourish_base { + des = "Font face for decorative flourishes"; + } + property string font_flourish_fallback { + des = "Alternate font face for decorative flourishes"; + } + property string font_flourish_type { + des = "Font type for decorative flourishes"; + } + property string font_secondary_base { + des = "Font face for secondary text"; + } + property string font_secondary_fallback { + des = "Alternate font face for secondary text"; + } + property string font_secondary_type { + des = "Font type for secondary text"; + } + property int font_secondary_size { + des = "Secondary font size (points)"; + note = "For best results, match optical x-height with the body font"; + } + property string flourish_rm { + des = "Right margin for flourishes"; + } + property string dc_rm { + des = "Right margin for drop caps"; + } +} + +propgroup presentation { + property string dingbar_url { + des = "URL to spacer image between portions of content"; + note = "A default will be chosen for you if left blank."; + } + + property use page_recent_items; + property use page_friends_items; + + property string body_width { + des = "Text body width"; + } + + property int dcLen { + des = "Minimum length in characters before using drop caps"; + } + + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { + des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; + } + property string page_background_image { + des = "URL to an image to be used for the page background"; + } + property use external_stylesheet; +} + +propgroup text { + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property string text_dingbar_alt { + des = "Alternative text for dingbar images"; + noui = 1; + } +} + +# Set default colors +set entry_text = "#000000"; +set text_weaker = "#666666"; +set page_link = "#000000"; +set page_vlink = "#666666"; +set page_alink = "#333333"; +set page_back = "#F5F5DC"; + +set body_width = "35em"; +set dcLen = 200; +set show_entrynav_icons = true; +set page_background_image = ""; + +set font_base = "Palatino Linotype"; +set font_fallback = "Book Antiqua"; +set font_type = "serif"; +set font_flourish_base = "Edwardian Script ITC\", \"Edwardian Script ITC Semi-Expanded"; +set font_flourish_fallback = "Zapfino\", \"Viner Hand ITC"; +set font_flourish_type = "cursive"; +set font_secondary_base = "Frutiger Linotype"; +set font_secondary_fallback = "Tahoma"; +set font_secondary_type = "sans-serif"; +set font_size = 10; +set font_leading = 14; +set title_smallcaps = true; +set title_underline = false; +set title_letterspacing = "0.08em"; +set font_secondary_size = 9; +set flourish_rm = "0.093em"; +set dc_rm = "0.2em"; +set dingbar_url = ""; + +set text_poster_anonymous = "an anonymous reader"; +set text_dingbar_alt = "* * *"; +set text_view_recent = "Entries"; +set text_view_friends = "Friends"; +set text_view_archive = "Archive"; +set text_view_userinfo = "Profile"; + +function prop_init() { + var PalItem start = PalItem(0, $*entry_text); + var PalItem end = PalItem(13, $*page_back); + if ($*dingbar_url == "") { $*dingbar_url = palimg_gradient("anovelconundrum/dingbar.gif", $start, $end); } +} + +function print_stylesheet() { + print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : ""; +""" +body { + margin-top: 1in; + margin-bottom: 0.6in; +} + +body, td, h2, .caption, h1, h3 { +"""; +if ($*font_base != "" or $*font_fallback != "" or $*font_type != "") { + "font-family: "; + if ($*font_base != "") { + "\"$*font_base\""; + if ($*font_fallback != "" or $*font_type != "") { + ", "; + } + } + if ($*font_fallback != "") { + "\"$*font_fallback\""; + if ($*font_type != "") { + ", "; + } + } + if ($*font_type != "") { + "$*font_type"; + } + ";\n"; +} +""" + font-size: ${*font_size}pt; + line-height: ${*font_leading}pt; + font-weight: normal; +} + +.caption, h1, h3 { +"""; if($*title_smallcaps) {""" + font-variant: small-caps; + text-transform: lowercase; +"""; } +""" letter-spacing: $*title_letterspacing; +} +h1 { font-size: 16pt; } +h3 { font-size: 12pt; } +h2, .noul, .ult { + font-style: italic; + margin: 0px; +} + +.caption { +"""; if($*title_underline) {""" + text-decoration: underline; +"""; } +""" } + +.flourish, .bodyl:first-letter { +"""; +if ($*font_flourish_base != "" or $*font_flourish_fallback != "" or $*font_flourish_type != "") { + "font-family: "; + if ($*font_flourish_base != "") { + "\"$*font_flourish_base\""; + if ($*font_flourish_fallback != "" or $*font_flourish_type != "") { + ", "; + } + } + if ($*font_flourish_fallback != "") { + "\"$*font_flourish_fallback\""; + if ($*font_flourish_type != "") { + ", "; + } + } + if ($*font_flourish_type != "") { + "$*font_flourish_type"; + } + ";\n"; +} +""" +} + +.flourish { + margin-right: ${*flourish_rm}; + z-index: 1; + font-size: 34pt; + position: relative; + top: 0.1em; + text-transform: uppercase; +} + +.sfon, .index, .author, select, input { +"""; +if ($*font_secondary_base != "" or $*font_secondary_fallback != "" or $*font_secondary_type != "") { + "font-family: "; + if ($*font_secondary_base != "") { + "\"$*font_secondary_base\""; + if ($*font_secondary_fallback != "" or $*font_secondary_type != "") { + ", "; + } + } + if ($*font_secondary_fallback != "") { + "\"$*font_secondary_fallback\""; + if ($*font_secondary_type != "") { + ", "; + } + } + if ($*font_secondary_type != "") { + "$*font_secondary_type"; + } + ";\n"; +} +""" font-size: ${*font_secondary_size}pt; + line-height: ${*font_leading}pt; +} + +.index { + width: 10em; + margin-right: 1.2em; +} + +.bodybox { width: $*body_width; } + +.body, .bodyl, .bodyns { + text-align: justify; +} +.bodyl:first-letter { + font-size: """ + (2* $*font_leading) + """pt; + margin-bottom: -""" + $*font_size + """pt; + margin-right: ${*dc_rm}; + float: left; + border-bottom: none; + text-transform: uppercase; + line-height: """ + (2* $*font_leading) + """pt; +} +.bodyns:first-line, .sc, small, .sct { +"""; if($*title_smallcaps) {""" + font-variant: small-caps; + text-transform: lowercase; +"""; } + if($*title_underline) {""" + text-decoration: underline; +"""; } +""" letter-spacing: 0.05em; +} + +.sct { + letter-spacing: $*title_letterspacing; + text-align: center; +} + +.author { + float: right; + text-align: center; + margin-left: 1.5em; + margin-bottom: 0.5em; +} + +.ywp { + width: 2em; + margin-left: 0.5em; + margin-right: 0.5em; +} + +blockquote { + margin-top: ${*font_leading}pt; + margin-bottom: ${*font_leading}pt; + margin-left: 2em; +} + +tt, pre, textarea { +font-family: "Lucida Console", monospace; +font-size:"""+ ((${*font_size}*4)/5) + """pt; +} + +a {text-decoration: none;} +.body a, .bodyl a, .bodyns a, .bodynsl a, .author a, .ult a, .uts a { border-bottom: 1px dotted; } +.ljuser a, a img, .smallbar a, .noul a { border-bottom: none; } +a:hover, .ljuser a:hover { border-bottom: 1px solid; } + +p { + text-indent: 1.5em; + margin: 0px; + padding: 0px; +} + +blockquote + p { text-indent: 0px; } + +.uts { + font-size: 80%; + font-style: italic; + text-align: center; + line-height: """ + $*font_size + """pt; + margin-bottom: """ + ($*font_leading-$*font_size) + """pt; +} + +.smallbar { + font-size: 80%; + font-style: italic; + text-align: center; + line-height: """ + (2*$*font_leading) + """pt; + clear: right; +} + +.ljcomsel { + position: relative; + top: 0.75pt; + height: 7.5pt; + padding-left: 1pt; +} +input#username, input#password { margin-right: 0.5em; } + +.bs { + margin-top: """ + (2*$*font_leading) + """pt; + margin-bottom: """ + (2*$*font_leading) + """pt; + text-align: center; + line-height: ${*font_leading}pt; +} +"""; +} + +function find_lpar(string t) : int { + foreach var int i (reverse (0 .. ($t->length()-1))) { + if($t->substr($i,1)=="(") { return $i; } + } + return -1; +} + +function render_title(string t, int len) { + foreach var int i (0 .. ($len-1)) { + var string pc = $t->substr($i-1,1); + var string cc = $t->substr($i,1); + if($cc==" ") { " · "; } + elseif( $i > 0 and $pc != " ") { "$cc"; } + elseif ($cc=="A" or $cc=="B" or $cc=="C" or $cc=="D" or $cc=="E" or $cc=="F" or $cc=="G" or $cc=="H" or $cc=="I" or $cc=="J" or $cc=="K" or $cc=="L" or $cc=="M" or $cc=="N" or $cc=="O" or $cc=="P" or $cc=="Q" or $cc=="R" or $cc=="S" or $cc=="T" or $cc=="U" or $cc=="V" or $cc=="W" or $cc=="X" or $cc=="Y" or $cc=="Z") { + "$cc"; + } + else { "$cc"; } + } +} + +function render_body(string t) { + var int str=0; + var bool par=false; + var bool pars=false; + $str = ($t->substr(0,6) == "
            " ? 6 : 0); + if($t->substr(0,3) == "

            ") { $str = 3; $pars=true; } + foreach var int i ($str .. ($t->length()-1)) { + if($t->substr($i,12) == "

            ") { + $str=$i+12; + if($par) { "

            "; } + else { "

            "; $par=true; } + } + elseif($pars and $t->substr($i,4) == "

            ") { $str=$i+4; $pars=false; } + elseif($i >= $str) { print $t->substr($i,1); } + } + if($par) { "

            "; } +} + +function display_title(Page p) { + var string dtitle = $p.global_title; + var string stitle = $p->view_title(); + $stitle = ($p.view == "recent" ? $p.global_subtitle : $stitle); + var int lenm=$stitle->length()-1; + var int i=$dtitle->length()+1; + if ($dtitle == "") { + $dtitle = $p.journal.name; + $i=$dtitle->length()+1; + } + if ($p.view == "friends") { + $dtitle = $p->view_title(); + $i=find_lpar($dtitle); + if($i==-1) { $i = $lenm+2; } + } + +"""
            +

            """; render_title($dtitle,$i-1); """

            """; +if($p.view != "friends" and $stitle != "") { """

            $stitle

            """; } +elseif($p.view == "friends" and $i<$lenm) { "

            " + $dtitle->substr($i+1,($lenm-$i)-1) + "

            "; } +"""
            """; +} + +function Page::print() { + var string title = $this->title(); + + var string links; + var bool firstlink = true; + foreach var string v ($.views_order) { + if ($firstlink == false) { + $links = "$links · "; + } + else { + $firstlink = false; + } + $links = $links + (""+lang_viewname($v)+""); + } + +"""\n\n\n"""; + + if ($*external_stylesheet) { + println """"""; + } else { + println """"; + } + $this->print_head(); + +"""$title + +"""; +display_title($this); +"""
            +

            $links

            +
            +"""; +$this->print_body(); +""" + + +"""; +} + +function print_entry(Page p, Entry e) { + var string date=$e.time->date_format("short"); + var string time=$e.time->time_format(); + """ + + + + + +"""; + + if ($p.view == "entry" and $*show_entrynav_icons) + { +""" +"""; + } +"
            $*text_dingbar_alt
            """; +""" $time
            + $date


            + """; + $e.comments->print(); + +"""
            +
            +
            """; + + if (defined $e.userpic) { + """
            """; + } + elseif ($e.poster.journal_type == "C") { + """
            """; + + } + elseif ($e.poster.journal_type == "Y") { + """
            """; + } + else { + """
            """; + } + "base_url() + "/\">$e.poster.username"; + if ($e.security != "") { + $e.security_icon->print(); + } + if ($e.poster.username != $e.journal.username and $e.journal.journal_type =="C") { +""",
            + +base_url() + """/">$e.journal.username"""; + } + + var string subject=$e.subject; + if($p.view=="entry") { $subject=""; } +"""
            +
            + $subject +
            """; + if ($subject == "" and $p.view!="entry") {"
            ";} + elseif ($e.text->length() > $*dcLen) {"
            ";} + else {"
            ";} + render_body($e.text); + var string metadata; + if ($e.metadata) { + $metadata = "
            "; + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { + $text = $*text_meta_mood; + } elseif ($k == "music") { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "$val $val"; + } + $metadata = """$metadata\n + """; + } + $metadata = """$metadata
            $text:
            $val
            """; + } + """$metadata
            $*text_dingbar_alt
            """; + $e->print_linkbar(); +"""
            "; +} # print_entry(Page,Entry,Color,Color) + +function Entry::print_linkbar() { + ## There's no point in showing previous/next links on pages which show + ## multiple entries anyway, so we only print them on EntryPage and ReplyPage. + + var Page p = get_page(); + var Link link; + var bool show_interentry = ($p.view == "entry" or $p.view == "reply"); + + "

            "; + if ($show_interentry) { + var Link prev = $this->get_link("nav_prev"); + """$prev.caption · """; + } + + if ($p.view == "entry" and $.comments.enabled) { + if ($.comments.maxcomments) { + "Maximum Comments Reached"; + } else { + "Leave a Comment"; + } + " · "; + } + + var int i=0; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + if($link.caption != "") { + if($i>0) { " · "; } + "$link.caption"; + $i++; + } + } + + if ($show_interentry) { + var Link next = $this->get_link("nav_next"); + """ · $next.caption"""; + } + "

            "; +} + +function Page::print_entry(Entry e) { + print_entry($this, $e); +} + +function FriendsPage::print_entry(Entry e) { + print_entry($this, $e); +} + + +function RecentPage::print_body() { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +""" +
            $*text_dingbar_alt
            +

            +"""; + + # go forward/backward if possible + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + var string sep; + var string back; + var string forward; + if ($.nav.backward_url != "") { + $back = """Previous"""; + } + if ($.nav.forward_url != "") { + $forward = """Next"""; + } + if ($back != "" and $forward != "") { $sep = " · "; } + "$back$sep$forward"; + } + "

            "; +} + +function CommentInfo::print() { + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); "
            "; + } + $this->print_postlink(); +} + +function YearPage::print_year_links() { + """
            + $*text_dingbar_alt +
            Years

            """; + + var bool d=false; + foreach var YearYear y ($.years) { + if($d) { " · "; } + else { $d=true; } + if ($y.displayed) { + "$y.year"; + } else { + "$y.year"; + } + } + "

            "; +} + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) { return; } + + """
            + +
            +"""; + print $m->month_format(); + """ + +
            + +"""; + foreach var int d (weekdays()) { + "\n"; + } + ""; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + """
            "+$*lang_dayname_short[$d]+"
            """; +} + +function YearWeek::print() { + ""; + if ($.pre_empty) { ""; } + foreach var YearDay d ($.days) { + """
            $d.day
            """; + if ($d.num_entries) { + """"""; + } else { + " "; + } + "
            "; + } + if ($.post_empty) { ""; } + ""; +} + +function DayPage::print_body() { + if (not $.has_entries) { print "
            " + ehtml($*text_noentries_day) + "
            "; } + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + """
            + $*text_dingbar_alt +
            """; + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + """

            $tprev · $tnext

            """; + +} + +function MonthPage::print_body() { + """
            + $*text_dingbar_alt +
            """; + "
            "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + "
            "; + print lang_ordinal($d.day); + ":
            \n
            "; + $d->print_subjectlist(); + "
            \n"; + } + } + "
            \n"; + """
            + $*text_dingbar_alt +
            """; + "
            "; + $.redir->print_hiddens(); + if ($.prev_url != "") { " "; } + if (size $.months > 1) { + "\n"; + } + if ($.next_url != "") { " \n"; } + "
            "; +} + +function EntryPage::print_body() { + print_entry($this, $.entry); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + + $this->print_multiform_start(); + "
            "; + "
            "; + $this->print_comments($.comments); + "
            "; + + $.comment_pages->print(); + + if ($*show_entrynav_icons) { + """
            + $*text_dingbar_alt +
            """; + """
            """; + $.entry->print_linkbar(); + """
            """; + } + + if ($this.multiform_on) {""" +
            + $*text_dingbar_alt +
            +
            """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
            "; + } + } +} + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """
            + $*text_dingbar_alt +
            """; + "
            "; + "
            "; + "

            " + lang_page_of_pages($.current, $.total) + "

            "; + var string url_prev = $this->url_of($.current - 1); + "
            "; + if ($.current != 1) { + print ""; + } else { + print "☜"; + } + print " "; + foreach var int i (1..$.total) { + if ($i == $.current) { "$i"; } + else { + var string url_of = $this->url_of($i); + "$i"; + } + if ($i != $.total) { ", "; } + } + " "; + var string url_next = $this->url_of($.current + 1); + if ($.current != $.total) { + print ""; + } else { + print "☞"; + } + "
            "; +} + +function EntryPage::print_comments(Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if($c.depth==1) { + ""; + """
            + $*text_dingbar_alt +
            """; + " + + + """; +} + +function DayPage::lay_viewspec_nav() { + """ + + + + """; +} + +function MonthPage::lay_viewspec_nav() { + """ + + + + """; +} + +function RecentPage::lay_viewspec_nav() { + """ + + + + """; + +} + + +############################################# +# +# Top Navigation +# +############################################# + +function print_nav(Page p) { + + # figure out the width of each table cell in the navigation based on total page width + var int blank = $*page_width - 512; + if($p.journal.website_url) { + $blank = $blank - 102; + } + + """ + + +
            "; + } + var int indent = ($c.depth - 1) * 21; + "
            \n"; + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + "
            "; + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + ""; + "
            1? " style='margin-top:${*font_leading}pt;'" : "") + ">"; + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + "[User Picture]"; + } + + ### From, date, etc + "
            "; + if ($c.screened) { "(Screened) "; } + "On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + ""; + if ($c.depth == 1) { "commented"; } + else { "replied"; } + ":
            "; + + print (defined $c.subject_icon or $c.subject != "") ? "
            $c.subject_icon $c.subject
            " : ""; + + "
            "; + render_body($c.text); + print "
            "; + if ($c.frozen) { + "Replies Frozen"; + } else { + "Reply"; + } + if ($c.parent_url != "") { " · Parent"; } + if ($c.thread_url != "") { " · Thread"; } + $c->print_linkbar(); + if ($this.multiform_on) { + " · "; + ""; + $c->print_multiform_check(); + } + "
            "; +} + + +function EntryPage::print_comment_partial(Comment c) { + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + var bool subj = $c.subject != ""; + "
            "; + "— On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + if($subj) { """replied, “$c.subject”"""; } + else { """posted a reply"""; } + ".
            "; +} + +function Comment::print_linkbar() { + var Link link; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + ($link.caption != "") ? " · $link.caption" : ""; + } +} + +function ReplyPage::print_body() { + var bool ent = $.replyto.permalink_url == $.entry.permalink_url; + + if($ent) { + print_entry($this, $.entry); + } + else { + """
            + $*text_dingbar_alt +
            """; + + var EntryLite c = $.replyto; + var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous; + "
            "; + + if (defined $c.userpic and $*comment_userpic_style != "off") { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + "[User Picture]"; + + } + + ### From, date, etc + + "
            "; + "On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster "; + if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; } + "commented:
            "; + + print ($c.subject != "") ? "
            $c.subject
            " : ""; + + "
            "; + render_body($c.text); + "
            "; + } + + """
            + $*text_dingbar_alt +
            """; + ""; + """
            + $*text_dingbar_alt +
            """; + + if (not $.entry.comments.enabled) { + print "
            $*text_reply_nocomments
            "; + return; + } + + + "

            Reply " + ($ent ? "to this entry" : "to this comment") + ":

            "; + $.form->print(); + "
            "; +} diff --git a/ljcom/bin/upgrading/s2layers/anovelconundrum/themes.s2 b/ljcom/bin/upgrading/s2layers/anovelconundrum/themes.s2 new file mode 100644 index 0000000..79e516b --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/anovelconundrum/themes.s2 @@ -0,0 +1,179 @@ +#NEWLAYER: anovelconundrum/renaissance +layerinfo "type" = "theme"; +layerinfo "name" = "Renaissance"; +layerinfo "redist_uniq" = "anovelconundrum/renaissance"; + +set font_secondary_fallback = ""; +set font_secondary_size = 10; +set font_secondary_type = "serif"; +set font_leading = 12; +set page_back = "#FAF2C8"; +set font_fallback = ""; +set font_secondary_base = "Garamond"; +set font_base = "Garamond"; + +#NEWLAYER: anovelconundrum/modern +layerinfo "type" = "theme"; +layerinfo "name" = "Modern"; +layerinfo "redist_uniq" = "anovelconundrum/modern"; + +set font_leading = 14; +set page_back = "#F5F5E8"; +set font_fallback = ""; +set font_base = "Georgia"; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.1em"; +set dcLen = 5000; + +#NEWLAYER: anovelconundrum/clippy +layerinfo "type" = "theme"; +layerinfo "name" = "Clippy"; +layerinfo "redist_uniq" = "anovelconundrum/clippy"; + +set font_leading = 13; +set page_back = "#FFFFFF"; +set font_fallback = "Times"; +set font_base = "Times New Roman"; +set font_secondary_base = "Helvetica"; +set font_secondary_fallback = "Arial"; +set font_secondary_type = "sans-serif"; +set font_secondary_size = 8; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.1em"; +set flourish_rm = "0.08em"; +set dcLen = 99999; +set body_width = "65ex"; + +#NEWLAYER: anovelconundrum/childsplay +layerinfo "type" = "theme"; +layerinfo "name" = "Child's Play"; +layerinfo "redist_uniq" = "anovelconundrum/childsplay"; + +set page_back = "#FFE6FF"; +set font_base = "Comic Sans"; +set font_fallback = "Chalkboard"; +set font_type = "cursive"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.08em"; +set dcLen = 1000; + +#NEWLAYER: anovelconundrum/laketahoe +layerinfo "type" = "theme"; +layerinfo "name" = "Lake Tahoe"; +layerinfo "redist_uniq" = "anovelconundrum/laketahoe"; + +set page_back = "#E6E6FF"; +set font_base = "Tahoma"; +set font_fallback = "Verdana"; +set font_type = "sans-serif"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.14em"; +set flourish_rm = "0.08em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/deardiary +layerinfo "type" = "theme"; +layerinfo "name" = "Dear Diary"; +layerinfo "redist_uniq" = "anovelconundrum/deardiary"; + +set page_back = "#f9f7d6"; +set font_base = "Lucida Handwriting"; +set font_fallback = ""; +set font_type = "cursive"; +set font_leading = 16; +set body_width = "38em"; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/scribal +layerinfo "type" = "theme"; +layerinfo "name" = "Scribal"; +layerinfo "redist_uniq" = "anovelconundrum/scribal"; + +set page_back = "#FAF2C8"; +set font_base = "Lucida Calligraphy"; +set font_fallback = ""; +set font_type = "cursive"; +set font_leading = 15; +set title_smallcaps = false; +set title_underline = true; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; + +#NEWLAYER: anovelconundrum/glossy +layerinfo "type" = "theme"; +layerinfo "name" = "Glossy Magazine"; +layerinfo "redist_uniq" = "anovelconundrum/glossy"; + +set page_back = "#F4FBFF"; +set font_base = "Lucida Bright"; +set font_fallback = "Georgia"; +set font_type = "serif"; +set font_secondary_base = "Lucida Sans"; +set font_secondary_fallback = ""; +set font_secondary_type = "sans-serif"; +set font_secondary_size = 9; +set font_flourish_base = "Agency FB"; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.08em"; +set flourish_rm = "0.02em"; +set dcLen = 1200; + +#NEWLAYER: anovelconundrum/retro +layerinfo "type" = "theme"; +layerinfo "name" = "Retrossential"; +layerinfo "redist_uniq" = "anovelconundrum/retro"; + +set page_back = "#f9f9e3"; +set font_base = "Rockwell"; +set font_fallback = ""; +set font_type = "serif"; +set font_size = 11; +set font_secondary_base = ""; +set font_secondary_fallback = ""; +set font_secondary_type = ""; +set font_secondary_size = 10; +set font_flourish_base = ""; +set font_flourish_fallback = ""; +set font_flourish_type = ""; +set flourish_rm = "0.05em"; +set dc_rm = "0.12em"; +set flourish_rm = "0.05em"; +set dcLen = 500; diff --git a/ljcom/bin/upgrading/s2layers/boxer/boxer.jpg b/ljcom/bin/upgrading/s2layers/boxer/boxer.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9299e77bf752a8accddab1d1438ef424f96d513b GIT binary patch literal 12699 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 literal 0 HcmV?d00001 diff --git a/ljcom/bin/upgrading/s2layers/boxer/layout.s2 b/ljcom/bin/upgrading/s2layers/boxer/layout.s2 new file mode 100644 index 0000000..20cbfae --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/boxer/layout.s2 @@ -0,0 +1,1988 @@ +# -*-s2-*- + +# Copyright (c) 2003-2005 Danga Interactive. All rights reserved. +# +# NOTICE: The Boxer style is not licensed for general use, and may not be +# used in any production sites. We provide the source to The Boxer so that our +# users and designers can learn the proper way to extend and customize the +# style. + +layerinfo type = "layout"; +layerinfo name = "The Boxer"; +layerinfo author_name = "Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo redist_uniq = "boxer/layout"; +layerinfo previews = "boxer/boxer.jpg"; +layerinfo source_viewable = 0; +layerinfo is_public = 0; + +############################################# +# +# Properties +# +############################################# + +propgroup presentation = "Presentation"; +propgroup presentation { + property int page_width { + des = "Page Width"; + note = "Set in pixels what you want the page width to be."; + min = 400; + } + + property string page_align { + des = "Page Alignment"; + values = "left|Left|center|Center|right|Right"; + } + + property use text_view_recent; + property use text_view_friends; + property use text_view_month; + property use text_view_archive; + + property use linklist_support; + + property string links_name { + des = "Links Title"; + } + + + property string links_divider { + des = "Links Divider"; + note = "This appears between each link to seperate them."; + } + + property use page_recent_items; + property use page_friends_items; + + + property string my_date { + des = "Date format"; + note = "Choose the date format that will appear by each entry and each comment, followed by the time."; + values = "short|2/5/80|med|Feb. 5th, 1980|med_day|Tue, Feb. 5th, 1980|long|February 5th, 1980|long_day|Tuesday, February 5th, 1980"; + } + + property bool color_forms { + des = "Form Elements"; + note = "Select Yes to use customized form elements."; + } + + property bool show_mini_calendar { + des = "Enable Mini-Calendar"; + } + + property bool show_entry_userpic { + des = "Recent userpics"; + note = "Select this if you want your userpic to show up on each entry of your Recent page."; + } + + property use use_shared_pic; + +} + +propgroup color = "Colors"; +propgroup colors { + property Color bg_color { + des = "Background Color"; + } + + property Color color_nav_bg { + des = "Navigation Background"; + note = "This is the base color for the navigation bar. After selecting a color, select if you want that color to get darker or lighter (from left to right)."; + } + + property string nav_scale { + des = "Navigation Background Progression"; + note = "Select if you want the background of the navigation to get lighter, darker or all the same color starting from the color you selected above."; + values = "lighter|Lighter|darker|Darker|same|Same"; + } + + property Color nav_link { + des = "Navigation Text Color"; + } + + property Color info_bg { + des = "Info Background"; + note = "The background to the area where the user information and calendar are presented."; + } + + property Color info_font { + des = "Info Font"; + note = "The color of the font for the text in the information area."; + } + + property Color info_link { + des = "Info Link Color"; + } + + property Color info_link_visited { + des = "Visited Info Link Color"; + note = "The color of a visited link in the info section."; + } + + property Color entry_bg { + des = "Entry Background"; + note = "The background color for each entry."; + } + + property Color entry_font { + des = "Entry Font"; + note = "The font color for color for entry text."; + } + + property Color entry_link { + des = "Entry Link Color"; + } + + property Color entry_link_visited { + des = "Visited Entry Link Color"; + note = "The color of a visited link in the entries section."; + } + + + # Non-visible properties go here. + + property Color nav1_bg { noui = 1; } + property Color nav2_bg { noui = 1; } + property Color nav3_bg { noui = 1; } + property Color nav4_bg { noui = 1; } + property Color nav5_bg { noui = 1; } + property Color nav6_bg { noui = 1; } + property Color nav7_bg { noui = 1; } + property string backarrow { noui = 1; } + property string forwardarrow { noui = 1; } + property string leave_comment { noui = 1; } + property string comment { noui = 1; } + property string memories { noui = 1; } + property string edit { noui = 1; } + property string mail { noui = 1; } + property string delete { noui = 1; } + property string screen { noui = 1; } + property string unscreen { noui = 1; } + property string freeze { noui = 1; } + property string unfreeze { noui = 1; } + property string parent { noui = 1; } + property int half_width { noui = 1; } + property int half_width_pixel { noui = 1; } + property bool show_links { noui = 1; } + property string bg_pattern { noui = 1; } +} + +propgroup background = "Background"; +propgroup Background { + + property string page_background_pattern { + des = "Background Pattern"; + note = "Select a premade background or enter a background image below"; + values = "none|None|background-horz-stripes.gif|Horizontal Stripes|background-vert-stripes.gif|Vertical Stripes|background-diag-stripes.gif|Diagnal Stripes|background-diamond.gif|Diamonds|background-hearts.gif|Hearts|background-lg-boxes.gif|Large Boxes|background-stitched.gif|Stitched"; + } + + property string page_background_image { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + + property string background_repeat { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + + property string background_position { + des = "Background image position"; + note = "Does not apply if Background Image Repeat is set to 'Repeat'."; + values = "top|Top|top left|Top-left|top right|Top-right|center|Center|center left|Center-left|center right|Center-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + + property string background_scrolling { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + +} + +propgroup fontsettings = "Font Settings"; +propgroup fontsettings { + + property string font_family { + des = "Font Family"; + note = "The default font to use for all journal pages."; + values = "Arial, sans-serif|Arial|Tahoma, sans-serif|Tahoma|Verdana, sans-serif|Verdana|Trebuchet MS, sans-serif|Trebuchet MS|Georgia, serif|Georgia|Times New Romans, serif|Times New Roman|sans-serif|sans-serif|serif|serif"; + } + + + property string font_size { + des = "Adjust font size"; + values = "small|Small|normal|Normal|large|Large|larger|Larger|hulk|Hulk!"; + } + + property int lineheight { + des = "Line Height"; + note = "This specifies the distance between each text line on all pages."; + } + + property string underline_links { + des = "Show link underline"; + values = "no|No|yes|Yes|hover|Only on mouse over"; + } + + +} + + +# setting layout +set page_width = 667; +set page_align = "center"; +set text_view_recent = "Recent Entries"; +set text_view_friends = "Friends Entries"; +set text_view_userinfo = "User Info"; +set text_view_month = "Calendar"; +set links_name = "Links"; +set linklist_support = true; +set links_divider = "/"; +set my_date = "long_day"; +set color_forms = false; +set show_mini_calendar = true; +set view_entry_disabled = false; +set show_entry_userpic = false; +set tags_aware = true; + +# setting colors +set nav_scale = "darker"; +set bg_color = "#f1ede2"; +set info_bg = "#d3ccc1"; +set color_nav_bg = "#da712b"; +set nav_link = "#ffffff"; +set entry_bg = "#275974"; +set entry_font = "#bfcadd"; +set entry_link = "#efe397"; +set entry_link_visited = "#f0ffc0"; +set info_font = "#9a927e"; +set info_link = "#ffffff"; +set info_link_visited = "#ffffff"; + +# setting Background +set page_background_pattern = "background-diamond.gif"; +set background_repeat = "repeat"; +set background_position = "center"; +set background_scrolling = "scroll"; + +# setting Font_Settings +set font_family = "Trebuchet MS, sans-serif"; +set lineheight = 17; +set font_size = "normal"; +set underline_links = "hover"; + +############################################# +# +# Printing +# +############################################# + + + + +############################################# +# +# Forward and back nav functions +# +############################################# + +function Page::lay_viewspec_nav() { + """ +
            + + + + + + + + + + """; + if($p.journal.website_url) { + """ + + + """; + } + + $p->lay_viewspec_nav(); + + if($blank > 0) { + """ + + + """; + } + """ + +
            + """; + +} + +############################################# +# +# Mini-calendar +# +############################################# + +function print_calendar_day_top(string style) { + """ + + + + + + + + + + + + + + +
            + """; + +} + +function print_calendar_day_bottom() { + """
            + + """; +} + +function print_active_day(YearDay day) { + + var string style = "calendarcontent"; + var string dayentry; + + if($day.num_entries > 0) { + $style = "calendarcontentactive"; + $dayentry = """$day.date.day"""; + } else { + $dayentry = "" + $day.date.day; + } + + print_calendar_day_top($style); + print $dayentry; + print_calendar_day_bottom(); + +} + +function print_inactive_day(int day) { + var string style = "calendarcontent"; + print_calendar_day_top($style); + print " "; + print_calendar_day_bottom(); +} + +function print_calendar(Page p) { + + var YearMonth y = $p->get_latest_month(); + + var string m = $y->month_format(); + + var YearWeek[] w = $y.weeks; + + var bool multiple = false; + if($p.journal.default_pic) { + $multiple = true; + } elseif($*linklist_support and size $p.linklist > 0) { + $multiple = true; + } + + if($multiple) { + """ + $m + + + """; + } else { + """ +
            + + + + """; + } + + foreach var YearWeek weeks ($w) { + var YearDay[] d = $weeks.days; + if($multiple) { + var int pre = $weeks.pre_empty; + if($pre > 0) { + foreach var int num (1..$pre) { + print_inactive_day($num); + } + } + } + foreach var YearDay days ($d) { + print_active_day($days); + } + if($multiple) { + var int post = $weeks.post_empty; + if($post > 0) { + foreach var int num (1..$post) { + print_inactive_day($num); + } + } + } + + if($multiple) { + print ""; + } + + } + """ + +
            $m
            + """; + + + +} + + +############################################# +# +# Built-in Links +# +############################################# + +function Page::print_linklist() { + + if (size $.linklist <= 0) { + return; + } elseif (not $*linklist_support) { + return; + } + + var int link_width = $*page_width - 290; + """ + $*links_name + """; + var bool slash = false; + foreach var UserLink l ($.linklist) { + if ($l.title) { + if ($l.is_heading) { + "$l.title "; + $slash = false; + } else { + if($slash) { + """ $*links_divider """; + } + """ $l.title """; + $slash = true; + } + } else { + "
            "; + } + } + """ + + """; + +} + +############################################# +# +# Print and Print Bodies +# +############################################# + +function Page::print() { + + var string title = $this->title(); + + """ + + + + + """; + $this->print_head(); + """ + $title + + +
            + + """; + + print_nav($this); + + + """ + + + + + + + +
            +
            $title
            + +
            + + """; + + + var bool linkl = false; + if(size $.linklist > 0) { $linkl = true; } + if(not $*linklist_support) { $linkl = false; } + + var bool box = false; + if($.journal.default_pic) { $box = true; } + if($*show_mini_calendar) { $box = true; } + if($linkl) { $box = true; } + + if($box) { + """ + + + """; + + if($.journal.default_pic) { + """ + + """; + if($linkl or $*show_mini_calendar) { + """ + + """; + } + } + + $this->print_linklist(); + if($*show_mini_calendar) { + if($linkl) { + """ + + """; + } + """ + + """; + } + """ + +
            + """; + + print_calendar($this); + + """ +
            + + + + """; + } + + $this->print_body(); + + print_nav($this); + + """ +
            + + + """; +} + + +############## +# recent page +############## + +function RecentPage::print_body { + foreach var Entry e ($.entries) { + $this->print_entry($e); + } +} + + +############################################# +# +# Print Entries +# +############################################# + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) { + + var int entry_page_width = $*page_width; + var int entry_half_width = $entry_page_width / 2; + var bool userpic_view = false; + + if($p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username or $*show_entry_userpic) { + $userpic_view = true; + } + + if($p.view != "friends" and $*show_entry_userpic) { + $bgcolor = $*entry_bg; + $fgcolor = $*entry_font; + } + + + if($userpic_view) { + var string url = $e.journal->base_url(); + var string url2 = $e.poster->base_url(); + $entry_page_width = $*page_width - 122; + $entry_half_width = $entry_page_width / 2; + + """ + + + + + + +
            + """; + if($e.journal.username != $e.poster.username) { + """$e.poster.username:
            """; + } + """ + $e.journal.username + """; + + + if($e.userpic) { + """
            $e.journal.username"""; + } + + """ +
            $e.journal.name
            + """; + } + + """ + + + + + + + + + + + +
            + """; + + if ($e.security) { print "
            $e.security_icon
            "; } + + """ +
            + + + + + + + +
            + """; + + print $e.time->date_format($*my_date); + print " " + $e.time->time_format(); + + + """ +
            +
            +
            """; + + if($e.subject) { + """ +
            $e.subject

            + """; + } + + + var string metadata; + + if ($e.metadata) { + foreach var string k ($e.metadata) { + var string text = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { $text = $*text_meta_mood; } + if ($k == "music") { $text = $*text_meta_music; } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = " $val"; + } + $metadata = $metadata + """$text: $val
            """; + } + } + + var string tags; + if ($e.tags) { + var int tcount = 0; + var string user = $e.journal.username; + $tags = """Tags: """; + foreach var Tag t ($e.tags) { + $tags = """$tags"""; + $tcount++; + if ($tcount != size $e.tags) { $tags = """$tags, """; } + } + $tags = "$tags
            "; + } + + if (not $hide_text) { print "
            $e.text

            "; print "$tags $metadata"; } + + """

            """; + + $e.comments->print(); + """"""; $p->print_reply_link({"target" => "topcomments", "img_url" => $*leave_comment, "img_width" => "20", "img_height" => "21", "img_align" => "middle", "alt" => "Reply", "title" => "Reply"}); ""; + + var Link mem; + $mem = $e->get_link("mem_add"); + if(defined $mem) { + """ + Add to Memories + """; + } + + var Link lnk; + $lnk = $e->get_link("edit_entry"); + if(defined $lnk) { + """ + Edit entry + """; + } + + var Link tag; + $lnk = $e->get_link("edit_tags"); + if(defined $tag) { + """ + Edit entry + """; + } + + var Link tell; + $tell = $e->get_link("tell_friend"); + if(defined $tell) { + """ + Email this entry to a friend + """; + $p->print_reply_container({"target"=>"topcomments"}); + } + + """ +

            +
            + + + + """; + + if($userpic_view) { + """ +
            + """; + } +} + + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function FriendsPage::print_entry (Entry e) { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +############################################# +# +# Reply Page +# +############################################# + +function ReplyPage::print_body () { + + if (not $.entry.comments.enabled) { + """ + + + + + + +
            + + + + + + + +
             
            +
            +
            +

            $*text_reply_nocomments

            +
            +
            + """; + return; + } + + + """ + + + + + + + + + + +
            """; + + + if ($.entry.security) { print "
            $.entry.security_icon
            "; } + + """
            + + + + + + + +
            """; + + + print $.replyto.time->date_format($*my_date); + print " " + $.replyto.time->time_format(); + + + """
            +
            +
            + """; + if($.replyto.subject) { + """ +

            $.replyto.subject

            + """; + } + + + var string metadata; + + if ($.entry.metadata) { + foreach var string k ($.entry.metadata) { + var string text = $k; + var string val = $.entry.metadata{$k}; + if ($k == "mood") { $text = $*text_meta_mood; } + if ($k == "music") { $text = $*text_meta_music; } + if ($k == "mood" and defined $.entry.mood_icon) { + var Image i = $.entry.mood_icon; + $val = " $val"; + } + $metadata = $metadata + """$text $val
            """; + } + } + + print "

            $.replyto.text

            "; print "

            $metadata

            "; + + """ +
            + + Comment + Add to Memories + """; + + if(viewer_is_owner()) { + """ + Edit entry + """; + } + """ + Email this entry to a friend + +
            +
            + + + + + +
            + """; + $.form->print(); + """ +
            + """; +} + + +############################################# +# +# Entry Page +# +############################################# + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + """ + + +
            + """; + + print lang_page_of_pages($.current, $.total); + + """
            """; + + foreach var int i (1..$.total) { + if ($i == $.current) { "[$i] "; } + else { + var string url_of = $this->url_of($i); + """[$i] """; + } + } + print "
            "; +} + +function EntryPage::print_body () { + + set_handler("screen_comment_#", [ [ "set_image", "sus_#", "$*unscreen", ], ]); + set_handler("unscreen_comment_#", [ [ "set_image", "sus_#", "$*screen", ], ]); + set_handler("freeze_comment_#", [ [ "set_image", "fuf_#", "$*unfreeze", ], ]); + set_handler("unfreeze_comment_#", [ [ "set_image", "fuf_#", "$*freeze", ], ]); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) { + $this->print_multiform_start(); + $this->print_comments($.comments); + + if ($this.multiform_on) { + """ + + +
            Mass Action
            + """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
            "; + } + + } +} + + +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + foreach var Comment c ($cs) { + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + $this->print_comments($c.replies); + } +} + +function EntryPage::print_comment_partial (Comment c) { + var int count = $c.depth / 7; # get how many times greater is the depth than our 8 color choices + $count = $count + (($count*10%10 >= 5) ? 1 : 0); # round that number + + var int subtract = $count * 7; # figure out how many times we need to subtract 8 from the depth + + var Color mybg; + + var int multiplier = (($c.depth - 1) - $subtract) * 15; + + var int sidewidth = 122 + ($c.depth - 1) * 25; + var int entry_page_width = $*page_width - $sidewidth; + var int entry_half_width = $entry_page_width / 2; + + if($*nav_scale == "darker") { + $mybg = $*color_nav_bg->darker($multiplier); + } else { + $mybg = $*color_nav_bg->lighter($multiplier); + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + + """ + + + + + + +

            $subj - $poster
            +
            + """; +} + +function EntryPage::print_comment (Comment c) { + + var int count = $c.depth / 7; # get how many times greater is the depth than our 8 color choices + $count = $count + (($count*10%10 >= 5) ? 1 : 0); # round that number + + var int subtract = $count * 7; # figure out how many times we need to subtract 8 from the depth + + var Color mybg; + + var int multiplier = (($c.depth - 1) - $subtract) * 15; + + if($*nav_scale == "darker") { + $mybg = $*color_nav_bg->darker($multiplier); + } else { + $mybg = $*color_nav_bg->lighter($multiplier); + } + + var string poster; + var string url; + if(defined $c.poster) { + $poster = $c.poster.name; + $url = $c.poster->base_url(); + } else { + $poster = "(Anonymous)"; + } + var string sub_icon; + + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + var string ip; + if ($c.metadata{"poster_ip"}) { $ip = " (" + $c.metadata{"poster_ip"} + ")"; } + + var int sidewidth = 122 + ($c.depth - 1) * 25; + var int entry_page_width = $*page_width - $sidewidth; + var int entry_half_width = $entry_page_width / 2; + + + """ + + + + + """; + } else { + """ +
            $poster + """; + } + """ + + + +
            $c.poster.username + """; + + if(defined $c.userpic) { + """
            $c.poster.username"""; + } + + if($c.journal) { + """ +
            $poster
            + + + + + + + +
            $sub_icon $ip + + + + + + + +
            + """; + + print $c.time->date_format($*my_date); + print " " + $c.time->time_format(); + if ($this.multiform_on) { + $c->print_multiform_check(); + } + + """ +
            +
            +
            """; + + if($c.subject) { + """ +
            $c.subject

            + """; + } + """ +

            $c.text


            """; + + if (not $c.frozen) { + """"""; $c->print_reply_link({"img_url" => $*leave_comment, "img_width" => "20", "img_height" => "21", "img_align" => "middle", "alt" => "Reply", "title" => "Reply"}); ""; + } else { + """ +Frozen"""; + + } + + """Thread + """; + + if ($c.parent_url != "") { """ Parent """; } + var Link lnk; + $lnk = $c->get_link("delete_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("screen_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("unscreen_comment"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("freeze_thread"); if($lnk) { """ $lnk.caption\n"""; } + $lnk = $c->get_link("unfreeze_thread"); if($lnk) { """ $lnk.caption\n"""; } + + $c->print_reply_container(); """ + + +
            +
            +
            + """; + +} + + +############################################# +# +# Calendar Pages +# +############################################# + +### Day view + +function DayPage::print_body() { + if ($.has_entries) { + """ + + + + +
            +
            + + """; + print $.date->date_format("long"); + """ +
            +
            + """; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } else { + """ + + + + +
            +
            + + """; + print $.date->date_format("long"); + """ +
            +
            + + + + +
            $*text_noentries_day
            + """; + } +} + +### Month View + +function MonthPage::print_body { + """ + + + + +
            +
            + + """; + "
            "; + $.redir->print_hiddens(); + if (size $.months > 1) { + """ + \n"""; + } + "
            \n
            "; + "
            \n"; + """ +
            +
            + """; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + + """ + + + + +
            +
            + + + + +
            + """; + $d->print_subjectlist(); + """ +
            + """; + + } + } +} + +### Year View +function YearPage::print_year_links () +{ + """ + + + + +
            +
            Years: + + """; + var int count = 0; + + foreach var YearYear y ($.years) { + if($count != 0) { + " | "; + } + $count = $count + 1; + if ($y.displayed) { + " $y.year "; + } else { + """ $y.year """; + } + } + + """ +
            +
            + """; +} + +function YearPage::print_body { + $this->print_year_links(); + var bool toggle = false; + """ + + + """; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + """"; + if($toggle) { + """ + + + + """; + $toggle = false; + } else { + $toggle = true; + """ + + """; + } + } + } + if($toggle) { + """ + + """; + } + """ + +
            """; + $this->print_month($m); + "
             
            + """; +} + +function YearPage::print_month (YearMonth m) { + """ + + + + +
            + + + + +
            + + + """; + + foreach var int d (weekdays()) { + " "; + } + + """ + + """; + + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + + """ +
            " + $*lang_dayname_short[$d] + "
            +
            + """; + +} + + +############################################# +# +# Comment Links +# +############################################# + +function CommentInfo::print_readlink { + var Page p = get_page(); + var string count; + if($.count > 0) { + $count = "" + $.count; + } else { + $count = ""; + } + + + """$countComment"""; +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + $this->print_readlink(); +} + + + +############################################# +# +# Property Initialization +# +############################################# +function prop_init() { + + # initialize the colors of the navigation bar. + $*nav1_bg = $*color_nav_bg; + + if($*nav_scale == "lighter") { + $*nav2_bg = $*nav1_bg->lighter(10); + $*nav3_bg = $*nav1_bg->lighter(20); + $*nav4_bg = $*nav1_bg->lighter(30); + $*nav5_bg = $*nav1_bg->lighter(40); + $*nav6_bg = $*nav1_bg->lighter(50); + $*nav7_bg = $*nav1_bg->lighter(70); + } elseif($*nav_scale == "darker") { + $*nav2_bg = $*nav1_bg->darker(10); + $*nav3_bg = $*nav1_bg->darker(20); + $*nav4_bg = $*nav1_bg->darker(30); + $*nav5_bg = $*nav1_bg->darker(40); + $*nav6_bg = $*nav1_bg->darker(50); + $*nav7_bg = $*nav1_bg->darker(70); + } else { + $*nav2_bg = $*color_nav_bg; + $*nav3_bg = $*color_nav_bg; + $*nav4_bg = $*color_nav_bg; + $*nav5_bg = $*color_nav_bg; + $*nav6_bg = $*color_nav_bg; + $*nav7_bg = $*color_nav_bg; + } + + # change the colors of the graphics using palimg + var Color dk_arrow = $*nav6_bg->darker(50); + + $*backarrow = palimg_modify("boxer/back.gif", [PalItem(0, $dk_arrow), PalItem(1, $*nav_link)]); + $*forwardarrow = palimg_modify("boxer/forward.gif", [PalItem(0, $dk_arrow), PalItem(1, $*nav_link)]); + + # tint the icons + + var Color entry_bg_tint; + var int entry_lightness = $*entry_bg->lightness(); + + if($entry_lightness > 120) { + $entry_bg_tint = $*entry_bg->lighter(); + } else { + $entry_bg_tint = $*entry_font; + } + + $*leave_comment = palimg_tint("boxer/leave_comment.gif", $entry_bg_tint); + $*comment = palimg_tint("boxer/comment.gif", $entry_bg_tint); + $*edit = palimg_tint("boxer/edit.gif", $entry_bg_tint); + $*memories = palimg_tint("boxer/memories.gif", $entry_bg_tint); + $*mail = palimg_tint("boxer/mail.gif", $entry_bg_tint); + $*delete = palimg_tint("boxer/delete.gif", $entry_bg_tint); + $*screen = palimg_tint("boxer/screen.gif", $entry_bg_tint); + $*unscreen = palimg_tint("boxer/unscreen.gif", $entry_bg_tint); + $*freeze = palimg_tint("boxer/freeze.gif", $entry_bg_tint); + $*unfreeze = palimg_tint("boxer/unfreeze.gif", $entry_bg_tint); + $*parent = palimg_tint("boxer/parent.gif", $entry_bg_tint); + + # background pattern + + var Color bg_lt = $*bg_color->lighter(); + var Color bg_dk = $*bg_color->darker(); + + if($*page_background_pattern != "" and $*page_background_pattern != "none") { + $*bg_pattern = palimg_modify("boxer/$*page_background_pattern", [PalItem(1, $bg_lt), PalItem(0, $bg_dk)]); + } + + $*half_width = $*page_width / 2; + $*half_width_pixel = $*half_width - 1; + +} + + + +############################################# +# +# Stylesheet +# +############################################# + +function appended_to_stylesheet() { + +} + +function print_stylesheet () { + + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + + + """ + body { + background-color: $*bg_color; + """; + + if(clean_url($*page_background_image) != "") { + """ + background-image: url("$*page_background_image"); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_scrolling; + """; + } elseif ($*page_background_pattern != "none" and $*page_background_pattern != "") { + """ + background-image: url("$*bg_pattern"); + background-attachment: $*background_scrolling; + """; + } + + """ + font-family: $*font_family; + line-height: """; print $*lineheight; """px; + font-size: """; print 12 + $inc; """px; + color: $*entry_font; + margin-top: 2px; + } + + tr, td { + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + + + + a { + color: $*entry_link; + """; + if($*underline_links != "yes") { "text-decoration: none;"; } + """ + } + + """; + if($*underline_links == "hover") { + " a:hover { text-decoration: underline;}"; + } + + """ + + a:visited { + color: $*entry_link_visited; + } + + a:visited.link { + color: $*info_link_visited; + } + + a:visited.subtitle { + color: $*info_link_visited; + } + + a.nav, a:visited.nav { + text-decoration: none; + color: $*nav_link; + } + + a.link { + color: $*info_link; + } + + + a.dayentry, a:visited.dayentry { + color: $*info_bg; + text-decoration: none; + } + + a.comments, a:visited.comments { + color: $*entry_font; + text-decoration: none; + font-weight: bold; + } + + + + .nav1 { + background-color: $*nav1_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav2 { + background-color: $*nav2_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav3 { + background-color: $*nav3_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav4 { + background-color: $*nav4_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav5 { + background-color: $*nav5_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav6 { + background-color: $*nav6_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + margin-right: 2px; + } + + .nav7 { + background-color: $*nav7_bg; + } + + .info { + background-color: $*info_bg; + padding-left: 16px; + padding-right: 16px; + padding-top: 16px; + padding-bottom: 16px; + color: $*info_font; + } + + .title { + font-size: """; print 18 + $inc; """px; + font-weight: bold; + } + + .subtitle { + font-size: """; print 14 + $inc; """px; + font-weight: bold; + color: $*info_link; + } + + .new { + margin-top: 2px; + } + + .entry { + background-color: $*entry_bg; + + } + + .newentry { + margin-top: 2px; + padding-left: 5px; + padding-top: 5px; + padding-right: 5px; + padding-bottom: 5px; + background-color: $*entry_bg; + } + + .entrycontent { + padding-left: 20px; + padding-right: 20px; + padding-bottom: 6px; + padding-top: 6px; + line-height: 18px; + } + + .date { + background-color: $*entry_font; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 5px; + padding-left: 5px; + color: $*entry_bg; + } + + .entryinfo, a.entryinfo, a:visited.entryinfo { + color: $*entry_bg; + } + + + + .bgcolor { + background-color: $*bg_color; + } + + .icon { + margin-right: 10px; + } + + .calendarborder { + background-color: $*info_font;; + } + + .calendarcontent { + padding-top: 2px; + padding-left: 1px; + padding-bottom: 2px; + padding-right: 2px; + font-family: Tahoma, sans-serif; + font-size: """; print 8 + $inc; """px; + color: $*info_font; + } + + .calendarcontentactive { + padding-top: 2px; + padding-left: 1px; + padding-bottom: 2px; + padding-right: 2px; + font-family: Tahoma, sans-serif; + font-size: """; print 8 + $inc; """px; + background-color: $*info_font; + color: $*info_bg; + } + + """; + + if($*color_forms) { + """ + .infoform { + background-color: $*info_bg; + color: $*info_font; + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + input, select, submit, textarea { + background-color: $*entry_font; + color: $*entry_bg; + font-family: $*font_family;; + font-size: """; print 12 + $inc; """px; + } + + """; + } + + appended_to_stylesheet(); +} + +############################################# +# +# Theme Preview +# +############################################# + + +function print_theme_preview () +{ + + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + +var int bigsize = $*page_width + 100; + """ + + + + +
            + + + + + + + + + + + + + + + + + + +
            Recent EntriesFriends EntriesCalendarMemoriesMy Website
            + + + + + +
            +
            Lou Reed
            + +
            + + + + + + + +
            + + + + + + + +
            8/10/06 12:09 am
            +
            +
            +

            $*text_reply_nocomments

            +
            +
            + +
            + """; +} diff --git a/ljcom/bin/upgrading/s2layers/boxer/themes.s2 b/ljcom/bin/upgrading/s2layers/boxer/themes.s2 new file mode 100644 index 0000000..bab3382 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/boxer/themes.s2 @@ -0,0 +1,225 @@ +#NEWLAYER: boxer/lipstick +layerinfo "type" = "theme"; +layerinfo "name" = "Lipstick"; +layerinfo redist_uniq = "boxer/lipstick"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#B46F60"; +set entry_link = "#ffeae5"; +set entry_bg = "#eebbaf"; +set nav_scale = "darker"; +set info_font = "#A55745"; +set bg_color = "#fac7bb"; +set entry_font = "#A55745"; +set info_link_visited = "#ffeae5"; +set page_background_pattern = "background-hearts.gif"; +set entry_link_visited = "#ffffff"; +set info_bg = "#e5a799"; +set info_link = "#FFF9F8"; + + +#NEWLAYER: boxer/greyskies +layerinfo "type" = "theme"; +layerinfo "name" = "Grey Skies"; +layerinfo redist_uniq = "boxer/greyskies"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#9aaeb6"; +set entry_link = "#997D63"; +set entry_bg = "#f2eae2"; +set nav_scale = "lighter"; +set info_font = "#627a84"; +set bg_color = "#dde1e3"; +set entry_font = "#7f97a0"; +set info_link_visited = "#CEDBDF"; +set page_background_pattern = "background-vert-stripes.gif"; +set entry_link_visited = "#b4a18f"; +set info_bg = "#8c9ca2"; +set info_link = "#b9c7cc"; + +#NEWLAYER: boxer/eggplant +layerinfo "type" = "theme"; +layerinfo "name" = "Eggplant"; +layerinfo redist_uniq = "boxer/eggplant"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#4e6559"; +set entry_link = "#9FAE8D"; +set entry_bg = "#635A48"; +set nav_scale = "lighter"; +set info_font = "#899BA3"; +set bg_color = "#9fae8d"; +set entry_font = "#E7DFCF"; +set info_link_visited = "#b9c7cc"; +set entry_link_visited = "#A6B2AC"; +set info_bg = "#464640"; +set info_link = "#b9c7cc"; + + +#NEWLAYER: boxer/lonelyturquoise +layerinfo "type" = "theme"; +layerinfo "name" = "Lonely Turquoise"; +layerinfo redist_uniq = "boxer/lonelyturquoise"; +layerinfo "source_viewable" = 0; +set page_background_pattern = "background-lg-boxes.gif"; +set color_nav_bg = "#7f7f7f"; +set entry_link_visited = "#ededed"; +set entry_link = "#ffffff"; +set entry_bg = "#ABABAB"; +set info_font = "#000000"; +set info_bg = "#00b1ae"; +set bg_color = "#ffffff"; +set entry_font = "#363636"; +set info_link = "#006260"; + + +#NEWLAYER: boxer/legallypink +layerinfo "type" = "theme"; +layerinfo "name" = "Legally Pink"; +layerinfo redist_uniq = "boxer/legallypink"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#ff089b"; +set entry_link_visited = "#70086F"; +set entry_link = "#4D0870"; +set entry_bg = "#ec008c"; +set nav_scale = "lighter"; +set info_font = "#ec008c"; +set bg_color = "#f49ac1"; +set entry_font = "#fbdbee"; +set info_link_visited = "#CE1182"; +set page_background_pattern = "background-hearts.gif"; +set info_bg = "#ffadde"; +set info_link = "#E3026A"; + +#NEWLAYER: boxer/greybrowngreen +layerinfo "type" = "theme"; +layerinfo "name" = "Grey Brown Green"; +layerinfo redist_uniq = "boxer/greybrowngreen"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#2f372e"; +set entry_link = "#212919"; +set entry_bg = "#586C44"; +set nav_scale = "lighter"; +set info_font = "#A1926C"; +set bg_color = "#000000"; +set entry_font = "#D9E1D2"; +set info_link_visited = "#B1AD9B"; +set entry_link_visited = "#2C3F28"; +set info_bg = "#433a1e"; +set info_link = "#B1AD9B"; + +#NEWLAYER: boxer/precious +layerinfo "type" = "theme"; +layerinfo "name" = "Precious"; +layerinfo redist_uniq = "boxer/precious"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#A17682"; +set entry_link = "#0F486E"; +set entry_bg = "#c6cfd5"; +set nav_scale = "lighter"; +set info_font = "#F7FDFC"; +set bg_color = "#d9e1d9"; +set entry_font = "#6C7982"; +set info_link_visited = "#E4ECEB"; +set entry_link_visited = "#3F6A86"; +set info_bg = "#a2b2b1"; +set info_link = "#E4ECEB"; + +#NEWLAYER: boxer/purple +layerinfo "type" = "theme"; +layerinfo "name" = "Purple"; +layerinfo redist_uniq = "boxer/purple"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#78629C"; +set entry_link = "#F9F5FC"; +set entry_bg = "#62536C"; +set nav_scale = "lighter"; +set info_font = "#A38FA3"; +set bg_color = "#8B77A9"; +set entry_font = "#DCD3E2"; +set info_link_visited = "#A799BF"; +set entry_link_visited = "#ffffff"; +set info_bg = "#472B47"; +set info_link = "#A799BF"; + +#NEWLAYER: boxer/green +layerinfo "type" = "theme"; +layerinfo "name" = "Green"; +layerinfo redist_uniq = "boxer/green"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#748A25"; +set entry_link = "#EAF9D4"; +set entry_bg = "#748A25"; +set nav_scale = "lighter"; +set info_font = "#004C3C"; +set bg_color = "#254634"; +set entry_font = "#E2EED0"; +set info_link_visited = "#00EEBC"; +set entry_link_visited = "#EAF9D4"; +set info_bg = "#0E9B7D"; +set info_link = "#61EFD1"; + +#NEWLAYER: boxer/purpange +layerinfo "type" = "theme"; +layerinfo "name" = "Purpange"; +layerinfo redist_uniq = "boxer/purpange"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#151e1a"; +set nav_scale = "lighter"; +set entry_link = "#ffffff"; +set entry_bg = "#E7513E"; +set info_font = "#f6cab7"; +set bg_color = "#ffffff"; +set entry_font = "#FDE9E6"; +set info_link_visited = "#afe900"; +set page_background_pattern = "background-stitched.gif"; +set entry_link_visited = "#ffffff"; +set info_bg = "#91125f"; +set info_link = "#afe900"; + +#NEWLAYER: boxer/purplesalmon +layerinfo "type" = "theme"; +layerinfo "name" = "Purple Salmon"; +layerinfo redist_uniq = "boxer/purplesalmon"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#AA6B90"; +set entry_link = "#633F4B"; +set entry_bg = "#CEADB8"; +set nav_scale = "same"; +set info_font = "#F0B4AA"; +set bg_color = "#151E1A"; +set entry_font = "#6D5B61"; +set info_link_visited = "#7E3D33"; +set entry_link_visited = "#633F4B"; +set info_bg = "#D26E5E"; +set info_link = "#7E3D33"; + +#NEWLAYER: boxer/refriedtribute +layerinfo "type" = "theme"; +layerinfo "name" = "Refried Tribute"; +layerinfo redist_uniq = "boxer/refriedtribute"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#666666"; +set entry_link = "#336699"; +set entry_bg = "#e6e6e6"; +set info_font = "#999966"; +set bg_color = "#ffffff"; +set entry_font = "#656565"; +set info_link_visited = "#4d4d4d"; +set page_background_pattern = "none"; +set entry_link_visited = "#336699"; +set info_bg = "#cccc99"; +set info_link = "#666666"; + +#NEWLAYER: boxer/blue +layerinfo "type" = "theme"; +layerinfo "name" = "Blue"; +layerinfo redist_uniq = "boxer/blue"; +layerinfo "source_viewable" = 0; +set color_nav_bg = "#3A6A74"; +set entry_link = "#E0DFCE"; +set entry_bg = "#4F7B8A"; +set info_font = "#908F78"; +set bg_color = "#435754"; +set entry_font = "#E7EEF0"; +set info_link_visited = "#5D5C50"; +set entry_link_visited = "#E0DFCE"; +set info_bg = "#E0DFCE"; +set info_link = "#4E5964"; diff --git a/ljcom/bin/upgrading/s2layers/component/component.jpg b/ljcom/bin/upgrading/s2layers/component/component.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c24108da4b02a63dec44eda30a19fa1b889f609f GIT binary patch literal 9585 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 HlZpQYSxnGu literal 0 HcmV?d00001 diff --git a/ljcom/bin/upgrading/s2layers/component/layout.s2 b/ljcom/bin/upgrading/s2layers/component/layout.s2 new file mode 100644 index 0000000..9873f94 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/component/layout.s2 @@ -0,0 +1,2806 @@ +# -*-s2-*- + +# Copyright (c) 2003-2005 Danga Interactive. All rights reserved. +# +# NOTICE: The Component style is not licensed for general use, and may not be +# used in any production sites. We provide the source to Component so that our +# users and designers can learn the proper way to extend and customize the +# style. + +layerinfo type = "layout"; +layerinfo name = "Component"; +layerinfo author_name = "Kevin Phillips"; +layerinfo author_email = "xevinx@livejournal.com"; +layerinfo redist_uniq = "component/layout"; +layerinfo previews = "component/component.jpg"; +layerinfo source_viewable = 0; + + +############################################# +# +# Properties +# +############################################# + + + +propgroup layout = "Layout"; +propgroup layout { + property string comp_state { + des = "Component Position"; + values = "right|Right|left|Left|none|None"; + note = "Components are the boxes on the side of the layout."; + } + property bool comp_friends { + des = "Enable Friends View Components"; + note = "Select No if you don't want components on your friends page."; + } + + property bool comp_navbar { + des = "Enable Navigation Component"; + note = "Select Yes if you want the main navigation to be in a component instead of the top bar. If components are not active, the navigation will remain at the top regardless of this value."; + } + property bool show_profile { + des = "Enable Profile"; + note = "Select Yes to make the profile component visible."; + } + property bool show_calendar { + des = "Enable Mini-Calendar"; + note = "Select Yes to make the mini-calendar component visible."; + } + + property bool icalendar { + des = "Enable Interactive Mini-Calendar"; + note = "Select Yes to enable forward and back buttons on the mini-calendar. Uses inline frames and javascript."; + } + + property bool show_links { + des = "Enable Links"; + note = "Select Yes to make the links component visible."; + } + + property bool show_summary { + des = "Enable Page Summary"; + note = "Select Yes to make the page summary component visible."; + } + property bool show_free_text { + des = "Enable Free Text"; + note = "Select Yes to show the free text component. The text that will be shown in this component needs to be added below."; + } + property string free_text { + des = "Free Text Component"; + note = "Add text that will appear in the Free Text component if it is enabled. Good for poetry, friends only warnings, general descriptions. HTML is disabled in all properties."; + rows = 10; + cols = 25; + } + + property string first_position { + des = "First Component"; + note = "Select what component you want to be on the top. Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string second_position { + des = "Second Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string third_position { + des = "Third Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string fourth_position { + des = "Fourth Component"; + note = "Only applies if component is activated."; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string fifth_position { + des = "Fifth Component"; + note = "Only applies if component is activated"; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } + + property string sixth_position { + des = "Sixth Component"; + note = "Only applies if component is activated"; + values = "none|None|navigation_order|Navigation|profile_order|Profile|calendar_order|Calendar|links_order|Links|free_text_order|Free Text|summary_order|Page Summary"; + } +} + +set comp_friends = true; +set first_position = "navigation_order"; +set second_position = "profile_order"; +set third_position = "calendar_order"; +set fourth_position = "links_order"; +set fifth_position = "free_text_order"; +set sixth_position = "summary_order"; +set comp_navbar = false; +set comp_state = "right"; +set show_calendar = true; +set show_profile = true; +set show_links = true; +set show_summary = false; +set show_free_text = false; +set icalendar = true; + +propgroup colors = "Colors"; +propgroup colors { + + property string topnavcolor { noui = 1; } + property string backarrow { noui = 1; } + property string forwardarrow { noui = 1; } + property string backarrow2 { noui = 1; } + property string forwardarrow2 { noui = 1; } + property string ctl { noui = 1; } + property string ctr { noui = 1; } + property string cbl { noui = 1; } + property string cbr { noui = 1; } + property string url { noui = 1; } + property string mem_img { noui = 1; } + property string edit_img { noui = 1; } + property string tellfriend_img { noui = 1; } + property string tags_img { noui = 1; } + property Color outside_border { noui = 1; } + property Color inside_border { noui = 1; } + property Color system_border { noui = 1; } + + property Color main_bgcolor { + des = "Page background"; + s1color = "page_back"; + } + + property Color entry_bgcolor { + des = "Entry background"; + note = "Background color of each entry."; + } + + property Color entry_fgcolor { + des = "Entry font"; + note = "Font color for text that will appear on top of 'Entry background color'."; + s1color = "page_text"; + } + + property Color entry_link { + des = "Main link"; + note = "Font color of any links that appear within each journal entry or within each component. Should be visible on Entry Background Color and Component Background Color."; + } + + property Color entry_link_visited { + des = "Main visited link"; + note = "Font color of any visited links that appear within each journal entry or within each component. Should be visible on Entry Background Color and Component Background Color."; + } + + property Color comp_bgcolor { + des = "Component background"; + note = "Background color of all component boxes."; + } + + property Color comp_fgcolor { + des = "Component font"; + note = "Font color for text that will appear on top of 'Component background color'. (leave blank to use 'Entry font color')"; + } + + + property Color header_bgcolor { + des = "Header background"; + note = "Background color of all component headers."; + } + + property Color header_fgcolor { + des = "Header font"; + note = "Font color for text that will appear on top of 'Component header background color'. (leave blank to use 'Entry font color')"; + } + + property Color header_fgcolor_lt { + des = "Header font alternative"; + note = "Font color used for information that deserves a different accent, like the date and journal sub-title. {leave blank to use 'Component font color')"; + } + + property Color header_link { + des = "Header link"; + note = "Font color of any links that appear within each component header. For example, the navigation. (leave blank to use 'Main link')"; + } + + property Color comments_bgcolor { + des = "Comments header"; + note = "Background color of the header information for each comment."; + } + + property Color comments_screened_bgcolor { + des = "Screened comments header"; + note = "Background color of the header information for each screened comment."; + } + + + property Color calendar_inactive { + des = "Calendar inactive background"; + note = "Background color of inactive dates on calendar component."; + } + + property Color calendar_active { + des = "Calendar active background"; + note = "Background color of active dates on calendar component."; + } + + property Color calendar_fgcolor { + des = "Calendar inactive font"; + note = "Color of font on each inactive calendar date. Appears on top of 'Calendar inactive background'. (leave blank to use 'Entry font color')"; + } + + property Color calendar_link { + des = "Calendar active font"; + note = "Color of font on each active calendar date. Appears on top of 'Calendar active background'. (leave blank to use 'Main link')."; + } +} + +set main_bgcolor = "#ffffff"; +set entry_bgcolor = "#ffffff"; +set entry_fgcolor = "#6D6D6D"; +set entry_link = "#333333"; +set entry_link_visited = "#555555"; +set comp_bgcolor = "#F4F4F4"; +set header_bgcolor = "#e5e5e5"; +set header_fgcolor = "#4D4D4D"; +set comments_bgcolor = "#E5E5E5"; +set comments_screened_bgcolor = "#ECECEC"; +set calendar_inactive = "#C8C8C8"; +set calendar_active = "#DFDFDF"; + +set outside_border = "#7f7f7f"; +set inside_border = "#ffffff"; +set system_border = "#cccccc"; + + +propgroup presentation = "Presentation"; +propgroup presentation { + + property use page_recent_items; + property use page_friends_items; + + property string page_background_image { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Only the default component background image will change colors as they are set in the Color properties (http://www.livejournal.com/palimg/component/bg.gif)."; + } + + property string background_repeat { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + + property string background_position { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + + property string background_scrolling { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + + property string font_size { + des = "Adjust font size"; + values = "small|Small|normal|Normal|large|Large|larger|Larger|hulk|Hulk!"; + } + + property string underline_links { + des = "Show link underline"; + values = "no|No|yes|Yes|hover|Only on mouse over"; + } + + property use view_entry_disabled; + + property bool show_entry_userpic { + des = "Recent userpics"; + note = "Select this if you want your userpic to show up on each entry of your Recent page."; + } + + property use use_shared_pic; + + property bool show_entrynav_icons { + des = "Enable Entry icons"; + note = "Toggle to show the memory, edit, etc icons on the Entry View page."; + } + + property bool show_recentnav_icons { + des = "Enable Recent View icons"; + note = "Toggle to show the memory, edit, etc icons on the Recent and Friend's View page."; + } + + property int lineheight { + des = "Line Height"; + note = "This specifies the distance between each text line on all pages."; + } + + property string path { + noui = 1; + } + + property string font_family { + des = "Font Family"; + note = "The default font to use for all journal pages."; + values = "Arial, sans-serif|Arial|Tahoma, sans-serif|Tahoma|Verdana, sans-serif|Verdana|Trebuchet MS, sans-serif|Trebuchet|Georgia, serif|Georgia|Times New Romans, serif|Times New Roman|sans-serif|sans-serif|serif|serif"; + } + + property bool color_forms { + des = "Form Elements"; + note = "Select No to disable the customized form elements."; + } + + property string base_font { noui = 1; } + property bool show_entrypage_userpic { noui = 1; } + +} +set font_family = "Arial, sans-serif"; +set lineheight = 22; +set show_entry_userpic = false; +set font_size = "normal"; +set background_repeat = "repeat"; +set background_position = "center"; +set background_scrolling = "scroll"; +set page_recent_items = 10; +set page_friends_items = 10; +set page_background_image = "http://www.livejournal.com/palimg/component/bg.gif"; +set view_entry_disabled = false; +set show_entrynav_icons = true; +set show_recentnav_icons = true; +set underline_links = "hover"; +set color_forms = true; +set base_font = ""; +set show_entrypage_userpic = true; + +propgroup Text { + + property use text_post_comment; + property use text_read_comments; + property use text_reply_back; + + property string comment_divider { + des = "Comment divider"; + note = "This is the text that divides the read comments and the post comments. For example 'OR' as in 'read 2 comments OR leave a comment'."; + } + + property use text_post_comment_friends; + property use text_read_comments_friends; + property string profile_text { + des = "Profile Component Title"; + maxlength = 50; + } + + property string page_summary_text { + des = "Page Summary Title"; + } + + property string links_text { + des = "Links Component Title"; + } + property string calendar_text { + des = "Calendar Component Title"; + note = "This is for the title of the component box, not the link to the calendar from the navigation. This title will only be visible if the Interactive mini-calendar is on. Otherwise the title of the component will be the current month and year."; + } + property string free_text_text { + des = "Free Text Component Title"; + } + + property string nav_entries_text { + des = "Navigation Recent Entries Text"; + maxlength = 50; + } + property string nav_friends_text { + des = "Navigation Friends View Text"; + maxlength = 50; + } + property string nav_calendar_text { + des = "Navigation Calendar Text"; + note = "This is the text for the link to the calendar from the navigation, not the title of the calendar component."; + maxlength = 50; + } + property string nav_info_text { + des = "Navigation User Info Text"; + maxlength = 50; + } + + property string nav_text_forward { + des = "Navigation Forward Text"; + note = "The text that appears in the navigation component or header when the user can navigate forward."; + } + + property string nav_text_back { + des = "Navigation Back Text"; + note = "The text that appears in the navigation component or header when the user can navigate back."; + } + + property use text_meta_mood; + property use text_meta_music; + property use text_permalink; + +} + + +set free_text_text = "About this journal"; +set calendar_text = "calendar"; +set nav_entries_text = "entries"; +set nav_friends_text = "friends"; +set nav_calendar_text = "calendar"; +set nav_info_text = "user info"; +set page_summary_text = "Page Summary"; +set links_text = "links"; +set profile_text = "profile"; +set comment_divider = "or"; +set nav_text_forward = "Next"; +set nav_text_back = "Previous"; +set tags_aware = true; + + +############################################# +# +# Stylesheet +# +############################################# + +function print_stylesheet () +{ + var int inc; + if($*font_size == "normal") { + $inc = 0; + } elseif($*font_size == "small") { + $inc = -1; + } elseif($*font_size == "large") { + $inc = 1; + } elseif($*font_size == "larger") { + $inc = 2; + } else { + $inc = 3; + } + + """ + body { background-color: $*main_bgcolor; +"""; + + if(clean_url($*page_background_image) != "") { + """ + background-image: url("$*page_background_image"); + background-repeat: $*background_repeat; + background-position: $*background_position; + background-attachment: $*background_scrolling; + """; + } + +""" + margin-top: 0px; margin-left: 0px; + margin-right: 0px; + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + color: $*entry_fgcolor; + } + + td, tr { + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + color: $*entry_fgcolor; + line-height: """; print $*lineheight; """px; + } + + a { + color: $*entry_link; + """; + if($*underline_links != "yes") { "text-decoration: none;"; } + """ + } + + a:visited { + color: $*entry_link_visited; + } + + a.calendarLink { + color: $*calendar_link; + } + + a.header { + color: $*header_link; + } + a.headerLinks { + color: $*header_link; + } + + """; + if($*underline_links == "hover") { + " a:hover { text-decoration: underline;}"; + } + $*topnavcolor = clean_url($*topnavcolor); + + if ($*color_forms) { + """ + select { + font-family: $*font_family; + font-size: """; print 11 + $inc; """px; + background-color: $*comp_bgcolor; + } + + input { + line-height: normal; + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + } + + textarea { + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + } + """; + } + + """ + + .subject { font-weight: bold; } + .small { margin-top: 3px;} + + .header { + background-image: url("$*topnavcolor"); + background-repeat: repeat-x; + height: 25px; + } + + .userTitle { + font-size: """; print 18 + ($inc * 2); """px; + text-weight: bolder; + color: $*header_fgcolor; + line-height: 17px; + } + + .userSubTitle { + font-size: """; print 12 + $inc; """px; + color: $*header_fgcolor_lt; + line-height: """; print $*lineheight; """px; + } + + .header-item { + padding-left: 15px; + position: relative; + top: 5px; + } + + .dkLine { background-color: $*outside_border; } + .ltLine { background-color: $*inside_border; } + .medLine { background-color: $*system_border; } + .divLine { background-color: $*header_fgcolor; } + .tabBg { background-color: $*header_bgcolor; } + + .entryDate { + font-size: """; print 11 + $inc; """px; + color: $*header_fgcolor_lt; + } + + .entryHolderBg { + background-color: $*comp_bgcolor; + color: $*comp_fgcolor; + padding-top: 7px; + padding-right: 7px; + padding-left: 7px; + padding-bottom: 7px; + } + + .entry { + padding-top: 7px; + padding-right: 7px; + padding-left: 7px; + padding-bottom: 7px; + background-color: $*entry_bgcolor; + font-size: """; print 12 + $inc; """px; + } + + .entryHeader { + font-size: """; print 12 + $inc; """px; + font-weight: bold; + } + + .entryComments { + font-size: """; print 11 + $inc; """px; + margin-top: 8px; + margin-left: 8px; + color: $*comp_fgcolor; + } + + .entryDash { + background-color: $*system_border; + width: 100%; + height: 1px; + } + + .sideHeader { + font-size: """; print 11 + $inc; """px; + color: $*header_fgcolor; + } + + .comp { margin-bottom: 3px; } + + .compBg { background-color: $*comp_bgcolor; } + + .compContent { + padding-left: 6px; + padding-right: 6px; + padding-bottom: 6px; + padding-top: 3px; + line-height: 18px; + color: $*comp_fgcolor; + } + + .compFont { + color: $*comp_fgcolor; + } + + .compList { + line-height: """; + + print $*lineheight - 2; + + """px; + padding-left: 6px; + } + + .userPic { border-color: $*system_border; } + + .shortLine { + width: 20px; + background-color: $*system_border; + margin-bottom: 1px; + } + + .calendarInactive { + background-color: $*calendar_inactive; + font-size: 9px; + letter-spacing: 2px; + color: $*calendar_fgcolor; + } + + .calendarActive { + color: $*calendar_link; + background-color: $*calendar_active; + font-size: 9px; + letter-spacing: 2px; + } + + """; +} + + +function prop_init() { + + $*path = "http://www.livejournal.com"; + + $*outside_border = $*header_bgcolor->darker(50); + $*inside_border = $*header_bgcolor->lighter(); + $*system_border = $*comp_bgcolor->darker(); + + if($*page_background_image == "http://www.livejournal.com/palimg/component/bg.gif") { + $*page_background_image = palimg_modify("component/bg.gif", [PalItem(0, $*system_border)]); + } + $*topnavcolor = palimg_tint("component/top-bg.gif", $*header_bgcolor); + $*forwardarrow = palimg_modify("component/forward.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*backarrow = palimg_modify("component/back.gif", [PalItem(1, $*inside_border), PalItem(0, $*outside_border)]); + $*forwardarrow2 = palimg_modify("component/forwardarrow.gif", [PalItem(1, $*inside_border), PalItem(0, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*backarrow2 = palimg_modify("component/backarrow.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border)]); + $*ctl = palimg_modify("component/curve-top-left.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*ctr = palimg_modify("component/curve-top-right.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*cbl = palimg_modify("component/curve-bottom-left.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*cbr = palimg_modify("component/curve-bottom-right.gif", [PalItem(0, $*inside_border), PalItem(1, $*outside_border), PalItem(2, $*header_bgcolor)]); + $*mem_img = palimg_modify("component/btn_memories.gif", [PalItem(10, $*inside_border), PalItem(14, $*outside_border)]); + $*tellfriend_img = palimg_modify("component/btn_tellfriend.gif", [PalItem(3, $*inside_border), PalItem(2, $*outside_border)]); + $*edit_img = palimg_modify("component/btn_edit.gif", [PalItem(12, $*inside_border), PalItem(14, $*outside_border)]); + $*tags_img = palimg_modify("component/btn_tags.gif", [PalItem(12, $*inside_border), PalItem(14, $*outside_border)]); + + if($*comp_fgcolor.as_string == "") { $*comp_fgcolor = $*entry_fgcolor; } + if($*header_fgcolor.as_string == "") { $*header_fgcolor = $*entry_fgcolor; } + if($*header_fgcolor_lt.as_string == "") { $*header_fgcolor_lt = $*header_fgcolor; } + if($*header_link.as_string == "") { $*header_link = $*entry_link; } + if($*calendar_fgcolor.as_string == "") { $*calendar_fgcolor = $*entry_fgcolor; } + if($*calendar_link.as_string == "") { $*calendar_link = $*entry_link; } + +} + + + + +############################################# +# +# Navigation +# +############################################# + +function Page::lay_viewspec_nav() { + # Intentionally blank +} + +function RecentPage::lay_viewspec_nav() { + # FIXME: There is currently no decent way to i18nize this + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.forward_url != "") { + if($side) { + $forward_link = $forward_link + """
            + """; + } else { + $forward_link = $forward_link + """$*nav_text_forward $*nav_text_forward"""; + } + } + if ($.nav.backward_url != "") { + if($side) { + $back_link = $back_link + """
            + """; + } else { + $back_link = $back_link + """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function EntryPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + var Link forward = $.entry->get_link("nav_next"); + var Link backward = $.entry->get_link("nav_prev"); + + if (defined $forward or defined $backward) { + if (defined $forward) { + if($side) { + $forward_link = """
            + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if (defined $backward) { + if($side) { + $back_link = """
            + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function ReplyPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + var Link forward = $.entry->get_link("nav_next"); + var Link backward = $.entry->get_link("nav_prev"); + + if (defined $forward or defined $backward) { + if (defined $forward) { + if($side) { + $forward_link = """
            + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if (defined $backward) { + if($side) { + $back_link = """
            + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + +function DayPage::lay_viewspec_nav() { + var string forward_link = ""; + var string back_link = ""; + var bool side = true; + + if($*comp_state == "none" or $*comp_navbar == false or ($.view == "friends" and $*comp_friends == false)) { $side = false; } + + if ($.prev_url != "" or $.next_url != "") { + if ($.next_url != "") { + if($side) { + $forward_link = """
            + """; + } else { + $forward_link = """$*nav_text_forward $*nav_text_forward"""; + } + } + if ($.prev_url != "") { + if($side) { + $back_link = """
            + """; + } else { + $back_link = """$*nav_text_back $*nav_text_back"""; + } + } + if($*comp_navbar) { + "$forward_link $back_link"; + } else { + "$back_link $forward_link"; + } + } +} + + +function print_bottom_nav(RecentPage p) { + if ($p.nav.forward_url != "" or $p.nav.backward_url != "") { + """ +
            + + + + + + + + + + + + + + + + + + + + + + + + + + +
            +
            + """; + + if($p.nav.backward_url != "") { + """$*nav_text_back $*nav_text_back """; + } + + if($p.nav.forward_url != "" and $p.nav.backward_url != "") { + """     """; + } + + if ($p.nav.forward_url != "") { + """$*nav_text_forward $*nav_text_forward"""; + } + + """ +
            +
            + """; + } +} + + + +############################################# +# +# Common snippets of HTML in print statements +# +############################################# + +# Top of the table for each comment +function print_content_top() { + """ + + + + +
            + + + + + + + + + + + + + + + + +
            + """; + +} + +# Bottom of the table for each comment +function print_content_bottom() { + """ +
            +
            +
            + """; +} + + +# Top of the table to each new thread +function print_comment_bottom() { + """ + + + + +
            + """; +} + +# Bottom of the table to each new thread +function print_comment_top() { + """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +"""; +} + +############################################# +# +# Component Setups +# +############################################# + +#### PAGE SUMMARY #### +function Page::lay_entry_nav (Entry e) : string { + var string line; + var string link = "item"; + var string subject = ($e.subject != "") ? " $e.subject" : """ $*text_nosubject"""; + if($.view == "friends") { $line = "$e.poster : "; $link = $e.journal.username; } + if($e.journal.username != $e.poster.username) { $line = $line + " $e.journal : "; } + $line = """
            $line $subject
            """; + return $line; +} + +function Page::lay_print_summary () { +} + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function EntryPage:: lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Comment e ($.comments) { + if($sep) { + $text = $text + """ +
            +
            + """; + } + var string subject = ($e.subject != "") ? " $e.subject" : """$*text_nosubject"""; + var string poster = defined $e.poster ? $e.poster->as_string() : "Anonymous"; + $text = $text + """
            $poster $subject"""; + $sep = true; + var int num = num_comments_in_thread($e.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + "
            "; + } + print $text; + print_comp_footer(); +} + + +function MonthPage::lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + if($sep) { + $text = $text + """ +
            +
            + """; + } + var string day = lang_ordinal($d.day); + $text = $text + """"""; + $sep = true; + } + } + print $text; + print_comp_footer(); +} + +function DayPage::lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Entry e ($.entries) { + if($sep) { + $text = $text + """ +
            +
            + """; + } + $text = $text + $this->lay_entry_nav($e); + $sep = true; + } + print $text; + print_comp_footer(); +} + + + +function RecentPage:: lay_print_summary () { + print_comp_header($*page_summary_text); + var string text; + var bool sep = false; + foreach var Entry e ($.entries) { + if($sep) { + $text = $text + """ +
            +
            + """; + } + $text = $text + $this->lay_entry_nav($e); + $sep = true; + } + print $text; + print_comp_footer(); +} + + +#### TYPE #### +function print_free_text(Page p) { + print_comp_header($*free_text_text); + """ +
            + """; +} + +# Top of lt gray table +function print_system_box_top() { + """ + + + + + + + + + +
            + """; +} + +# Bottom of lt gray table +function print_system_box_bottom() { + """ +
            + """; +} + +function print_spacer() { + """"""; +} + + +# prints out tab header with $content being the text in it + +function print_entry_header(string content) { + var int cspan = 1; + var int cspan2 = 4; + var int cspan3 = 5; + +""" + + + + + + + + + + + + + + + + + + + + + + +
            + +
            +"""; +} + +# couldn't use the print above because comp column must be all one table for width issues +# this starts a comp with $content being its header + +function print_comp_header(string content) { + +""" +
            +"""; + print safe $content; +""" +
            +"""; +} + +# this ends a comp +function print_comp_footer() { +""" +
            + + + +
            """; + + print $*free_text; + + """
            """; + print_comp_footer(); +} + +#### LINKS #### + +function print_link(string link, string name) { + print safe ""; + if($name != "") { print safe "$name"; } else { "no name"; } +} + + + +function Page::print_linklist() { + + if (size $.linklist <= 0) { + return; + } + + + var string endHTML = """ +
            +
            + """; + + + var int count = 0; + + foreach var UserLink l ($.linklist) { + $count = $count + 1; + if ($l.title) { + if ($l.is_heading) { + if($count != 1) { + "
            "; + } + "
            $l.title
            "; + } else { + print_link($l.url, $l.title); + } + + if($count != size $.linklist) { + print $endHTML; + } + + } else { + "
            "; + } + } + +} + + +function print_links(Page p) { + + print_comp_header($*links_text); + + """ + + + + + + +
            + """; + + $p->print_linklist(); + + """ +
            + """; + + print_comp_footer(); +} + + +#### CALENDAR COMPONENT #### +function print_calendar(Page p) { + +var YearMonth m = $p->get_latest_month(); + +if($m.has_entries) { + + var string month = $m->month_format(); + var string header = ""; + if($*icalendar) { + $header = "$*calendar_text"; + } else { + $header = "$month"; + } + print_comp_header($header); + + if($*icalendar) { + + """ +
            +
            + """; + + } + + if($*icalendar) { + var int lastm; + $lastm = $m.month - 1; + var int lasty; + $lasty = $m.year; + var string journal; + $journal = $p.base_url; + var string link; + + if($lastm == 0) { + $lasty = $m.year - 1; + $lastm = 12; + } + + var string myM; + if($lastm < 10) { $myM = "0" + $lastm; } + else { $myM = string($lastm); } + + $link = $journal + "/" + $lasty + "/" + $myM + "/"; + + """ + + + + + + + + + + """; + + } else { + """
            \"Back\"$month
            """; + } + + + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + ""; + } + foreach var YearDay d ($theDays) { + var int num = $d.num_entries; + if($num > 0) { + ""; + } else { + ""; + } + } + ""; + } + + + """ +
            \"\"$d.date.day$d.date.day
            +"""; + if($*icalendar) { + + "
            "; + } + print_comp_footer(); + } +} + +#### PROFILE COMPONENT #### +function print_profile(Page p) { + + + var string jtype; + + var string comphead = "$*profile_text"; + print_comp_header($comphead); + + """"""; + + if($p.journal.default_pic) { + """ + + + + + """; + } + +""" + + +
            +
            +
            +
            $p.journal.name +
            +
            +
            + + """; + + "
            User: $p.journal
            "; + + if($p.journal.name) { + "
            Name: $p.journal.name
            "; + } + + if($p.journal.website_url) { + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + "
            Website: $website_name
            "; + } + +""" +
            +"""; + + print_comp_footer(); + +} + + +#### PROFILE COMPONENT #### +function print_nav_comp (Page p) { + var string title = $p->title(); + var string website = ""; + if($p.journal.website_url) { + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + $website = "
            \"\"
            \n"; + $website = $website + " \n"; + } + + +""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            + +
            + +
            + +
            + + $website"""; + $p->lay_viewspec_nav(); + """
            + + + + + + +"""; +} + +function print_my_components (Page p) { + if($p.view == "friends" and $*comp_friends == false) { + return; + } + if($*comp_state != "none") { +""" + + +"""; + + if($*first_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*first_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*first_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*first_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*first_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*first_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*second_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*second_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*second_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*second_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*second_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*second_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*third_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*third_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*third_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*third_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*third_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*third_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + if($*fourth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*fourth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*fourth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*fourth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*fourth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*fourth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + + if($*fifth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*fifth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*fifth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*fifth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*fifth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*fifth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + + if($*sixth_position == "navigation_order") { + if($*comp_navbar) { + print_nav_comp($p); + } + } elseif ($*sixth_position == "profile_order") { + if($*show_profile) { + print_profile($p); + } + } elseif($*sixth_position == "calendar_order") { + if($*show_calendar) { + print_calendar($p); + } + } elseif($*sixth_position == "links_order") { + if($*show_links and size $p.linklist > 0) { + print_links($p); + } + } elseif($*sixth_position == "free_text_order") { + if($*show_free_text) { + print_free_text($p); + } + } elseif($*sixth_position == "summary_order") { + if($*show_summary) { + $p->lay_print_summary(); + } + } + + "
            \n "; + } +} + +############################################# +# +# Entries +# +############################################# + +function print_my_entries (Page p, string title) { + +""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            +
            +"""; + +print safe $title; + +""" +
            + """; + + if($p.global_subtitle != "") { +"
            $p.global_subtitle
            "; + } + + """ + +
            + + + +
            + """; + + $p->print_body(); + + """ + + """; +} + +function page_layout(Page p) { + + var string title = $p->title(); + + var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name; + var string website = ($p.journal.website_url != "" ? "$website_name" : ""); + +""" + + + + + """; + $p->print_head(); + """ + $title + + +"""; + if($*comp_state == "none" or $*comp_navbar == false or ($p.view == "friends" and $*comp_friends == false)) { + +""" +
            + $*nav_entries_text + $*nav_friends_text + $*nav_calendar_text + $*nav_info_text + $website +"""; + + $p->lay_viewspec_nav(); + + "
            "; + + } + +""" +
            + + + + +"""; + if($*comp_state == "right" or $*comp_state == "none") { + print_my_entries($p, $title); + } elseif($*comp_state == "left") { + print_my_components($p); + } +""" + +"""; + + if($*comp_state == "right") { + print_my_components($p); + } elseif($*comp_state == "left") { + print_my_entries($p, $title); + } +""" + + +
            + + + +"""; +} + +function Page::print () { + page_layout($this); +} + + +function Page::lay_print_linkbar() : bool { + return false; +} + +function Entry::lay_print_linkbar() : bool { + var Page p = get_page(); + if (($*show_entrynav_icons and $p.view == "entry") or ($*show_recentnav_icons and ($p.view == "recent" or $p.view == "friends"))) { + print "
            "; + var Link link; + var string icon; + foreach var string k ($.link_keyseq) { + $link = $this->get_link($k); + if($link) { + if($k == "edit_entry") { $icon = $*edit_img; } + elseif($k == "mem_add") { $icon = $*mem_img; } + elseif($k == "tell_friend") { $icon = $*tellfriend_img; } + elseif($k == "edit_tags") { $icon = $*tags_img; } + if ($icon != "") { print "\"$link.caption\"
            "; } + } + $icon = ""; + } + print "
            "; + return true; + } else { + return false; + } +} + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string time = $e.time->time_format(); + var string userpic = (defined $e.userpic ? "\"$e.poster.username\"" : ""); + + var string header = ""; + if (($p.view != "entry" and $e.new_day) or $p.view == "entry") { + $header = "$time " + $e.time->date_format("long") + ""; + } else { + $header = "$time " + $e.time->date_format("long"); + } + if ($e.security) { $header = $e.security_icon + "   " + $header; } + var string link = ($p.view == "friends") ? $e.journal.username : "item"; +""" + + +"""; + print_entry_header($header); + + var string fgstyle = "class=\"userpic\""; + var string bgstyle; + if($p.view == "friends") { + $fgstyle = "style=\"border-color: $fgcolor;\""; + $bgstyle = "style=\"padding-top: 3px; padding-left: 3px; padding-right: 3px; padding-bottom: 3px; background-color: $bgcolor;\""; + } + + +""" + + + +"""; + if($p.view == "friends" or $p.journal_type == "c" or $e.poster.username != $e.journal.username or ($p.view == "entry" and $*show_entrypage_userpic)) { + """"""; + } elseif($*show_entry_userpic and (($p.view == "entry" and ($*show_entrypage_userpic == false)) == false)) { + """"""; + } + var int cs = 4; + var bool test = $e->lay_print_linkbar(); + if($test) { $cs = 5; } + +""" + + + + + +
            """; + + if(defined $e.userpic) { + """"""; + } +""" $e.journal"""; + + if($e.journal.username != $e.poster.username) { + print "
            $e.poster"; + } + +"""
            """; + if(defined $e.userpic) { + """
            $e.poster.username
            """; + } +"""
            + + + + + + + """; + + # Subject + if($e.subject != "") { + """ + + + + + +"""; + + } + + if (not $hide_text) + { + # Entry + """ + + + + + + """; + } + + """ + + + + + +
            +
            $e.subject
            +"""; + if($e.text != "") { + "
            \"\"
            "; + } +""" +
            +
            + $e.text +"""; + if (size $e.tags or size $e.metadata) { print "

            "; } + if ($e.tags) { + var int tcount = 0; + "Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + "
            "; + } + + if (size $e.metadata) + { + foreach var string k ($e.metadata) + { + var string key = $k; + var string val = $e.metadata{$k}; + if ($k == "mood") { $key = $*text_meta_mood; } + if ($k == "music") { $key = $*text_meta_music; } + if ($k == "mood" and defined $e.mood_icon) + { + var Image i = $e.mood_icon; + $val = " $val"; + } + "$key: $val
            "; + } + } + if (size $e.tags or size $e.metadata) { print "

            "; } +""" +
            +
            + """; + + # Comments + "
            "; + $e.comments->print(); + """ +
            +
            + +
            + """; + +} + +function CommentInfo::print() +{ + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); " $*comment_divider "; + } + $this->print_postlink(); +} + +function Page::print_entry (Entry e) +{ + print_entry($this, $e, null Color, null Color, false); +} + +function RecentPage::print_body +{ + + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + print_bottom_nav($this); + +} + + +function FriendsPage::print_entry (Entry e) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor, false); +} + +function FriendsPage::print_body +{ + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + + print_bottom_nav($this); +} + + +############################################# +# +# Calendar: +# Year, Month, Week, and Day View +# +############################################# + + +function YearPage::print_year_links () +{ + print_system_box_top(); + "Year: "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + " ($y.year) "; + } else { + " ($y.year) "; + } + } + print_system_box_bottom(); + print_spacer(); +} + +function YearPage::print_body { + $this->print_year_links(); + var bool toggle = false; + "\n \n "; + foreach var YearMonth m ($.months) { + if ($m.has_entries) { + "\n "; + if($toggle) { + "\n "; + $toggle = false; + } else { + $toggle = true; + } + } + } + "\n \n
            "; + $this->print_month($m); + "\n
            "; +} + +# prints out the multiple month calendar view +function YearPage::print_month(YearMonth m) +{ + var string header; + $header = $header + ""; + $header = $header + $m->month_format(); + $header = $header + ""; + print_entry_header($header); + print_comment_top(); + "\n "; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + "\n
            \n "; + print_comment_bottom(); +} + +function YearWeek::print() { + "\n "; + if ($.pre_empty) { "\n "; } + foreach var YearDay d ($.days) + { + if ($d.num_entries) { + "\n $d.day"; + ""; + } else { + "\n $d.day"; + "
             "; + } + "\n"; + } + if ($.post_empty) { "\n "; } + "\n "; +} + + +# Has two views. A normal one, and one for the iCalendar. +function MonthPage::print() { + + if($*icalendar and $.args{"ical"} == "true") { + var string title = $this->title(); + var MonthDay[] theM = $this.days; + """ + + + + + + $.head_content + $title + + + + + \n \n \n "; + + var int count = 1; + var int first = 0; + var int colspan = 0; + foreach var MonthDay d ($theM) { + if($first == 0) { + $first = $d.date->day_of_week(); + $count = $first; + $colspan = $first - 1; + } + if($d.day == 1) { + if($first > 1) { + """ \n"""; + } + } + if($count == 8) { + " \n"; + $count = 1; + } + if($d.has_entries) { + " "; + } else { + " "; + } + + $count ++; + + } + + + """ + +
            """; + + if ($.prev_url != "") { "\"Back\""; } + ""; + var string current = $.date->date_format($*lang_fmt_month_long); + var int mm = $.date.month; + var string mms; + if($mm < 10) { + $mms = "0" + $mm; + } else { + $mms = string($mm); + } + + "$current"; + ""; + if ($.next_url != "") { "\"Forward\""; } + "
            $d.date.day$d.date.day
            + + + """; + } else { + page_layout($this); + } +} + +function MonthPage::print_body() { + "
            "; + $.redir->print_hiddens(); + print_system_box_top(); + """ + + + + +
            + """; + if ($.prev_url != "") { "\"Back\"\n"; } + ""; + if (size $.months > 1) { + "\n"; + } + ""; + if ($.next_url != "") { "\n\"Forward\"\n"; } + """ +
            + """; + print_system_box_bottom(); + print_spacer(); + + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + var string head = """"""; + $head = $head + ""; + $head = $head + lang_ordinal($d.day); + $head = $head + ""; + print_entry_header($head); + $d->print_subjectlist(); + print_spacer(); + } + } + "
            "; + +} + +function MonthDay::print_subjectlist() { + print_comment_top(); + foreach var Entry e ($.entries) { + print_content_top(); + print $e.time->time_format("short") + ": "; + if ($e.poster.username != $e.journal.username) { + $e.poster->print(); " "; + } + "$e.security_icon"; + if ($e.subject != "") { + " $e.subject"; + } else { + " ($*text_nosubject)"; + } + if ($e.comments.count > 0) { + " - " + get_plural_phrase($e.comments.count, "text_read_comments"); + } + if ($e.comments.screened) { + " $*text_month_screened_comments"; + } + "
            \n"; + print_content_bottom(); + } + print_comment_bottom(); +} + +### Day + +function DayPage::print_body () +{ + + if (not $.has_entries) { + var string sub = $.date->date_format("med"); + + print_system_box_top(); + "
            $*text_noentries_day
            "; + print_system_box_bottom(); + + } else { + + var int count = 0; + var string[] myarray; + + foreach var Entry e ($.entries) { + $this->print_entry($e); + } + + } +} + + + + + + + + + +############################################# +# +# Entry and Comments +# +############################################# + +function ItemRange::print() { + if ($.all_subitems_displayed) { return; } + "
            "; + print lang_page_of_pages($.current, $.total); + "
            "; + foreach var int i (1..$.total) { + if ($i == $.current) { + "[$i] "; + } else { + var string url_of = $this->url_of($i); + """[$i] """; + } + } +} + +function EntryPage::print_body () +{ + set_handler("unscreen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comments_bgcolor", ], + ]); + set_handler("screen_comment_#", [ + [ "style_bgcolor", "cmtbar#", "$*comments_screened_bgcolor", ], + ]); + + print_entry($this, $.entry, null Color, null Color, $.viewing_thread); + if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + """ + + + + + + + + + + +
            Comments + """; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } + """ +
            + """; + print_spacer(); + + if ($.comment_pages.total_subitems > 0) { + $this->print_comments($.comments); + } +""" + + + + + +
            + + + + + + + + + + + +
            +"""; + + $.entry.comments->print(); + +""" + +"""; + if ($.comment_pages.total_subitems > 0) { + $.comment_pages->print(); + } +""" +
            + + +
            +"""; + if ($this.multiform_on) { +""" + + + + + + + + + +
            +"""; + "

            Mass Action

            "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "
            "; +"""
            +"""; + } + } +} + + +# Top of the table for each comment +function print_comment_content_top(Comment c) { + + var int indent = ($c.depth - 1) * 25; + + """ + + + + + +
            + + + + + + + + + + + + + + + + +
            + """; + +} + +# Bottom of the table for each comment +function print_comment_content_bottom() { + """ +
            +
            +
            + """; + "\n\n\n\n"; +} + +# partial entries such as collapsed and screened. +function EntryPage::print_comment_partial (Comment c) { + if($c.depth == 1) { + var Comment[] replies; + $replies = $c.replies; + var int count = 0; + foreach var Comment reply ($replies) { + $count ++; + } + var string head; + if($count > 0) { + $head = "Thread started by a screened user"; + } else { + $head = "Comment by screened user"; + } + print_entry_header($head); + print_comment_top(); + } + var string content; + if($c.screened) { + $content = "Screened comment"; + } else { + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string subj = $c.subject != "" ? $c.subject : $*text_nosubject; + $content = "$subj - $poster"; + } + print_comment_content_top($c); + "$content"; + print_comment_content_bottom(); +} + +# called from entry page. loops through entries and runs EntryPage::print_comment +function EntryPage::print_comments (Comment[] cs) { + if (size $cs == 0) { return; } + var bool first = true; + foreach var Comment c ($cs) { + if($c.depth == 1) { + if($first != true) { + print_comment_bottom(); + } else { + $first = false; + } + } + if ($c.full) { + $this->print_comment($c); + } else { + $this->print_comment_partial($c); + } + $this->print_comments($c.replies); + } +} + +# Runs for every entry found +function EntryPage::print_comment (Comment c) { + var Color background; var Color color; + + $color = $*entry_fgcolor; + + if ($c.screened) { + $background = $*comments_screened_bgcolor; + } else { + $background = $*comments_bgcolor; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "(Anonymous)"; + var string sub_icon; + if (defined $c.subject_icon) { + $sub_icon = $c.subject_icon->as_string(); + } + + if ($c.depth == 1) { + var string poster_name = defined $c.poster ? $c.poster.name : "Anonymous"; + + var Comment[] replies; + $replies = $c.replies; + var int count = 0; + foreach var Comment reply ($replies) { + $count ++; + } + + var string head; + + if($count > 0) { + $head = "Thread started by $poster_name"; + } else { + $head = "Comment by $poster_name"; + } + print_entry_header($head); + print_comment_top(); + } + + print ""; + print_comment_content_top($c); + + "\n\n
            \n"; + " \n \n"; + var int td = 6; + if (defined $c.userpic and $*comment_userpic_style != "off") { + $td = 7; + var int w = $c.userpic.width; + var int h = $c.userpic.height; + # WARNING: this will later be done by the system (it'll be a + # constructional property), so don't copy this hack into your + # layout layers or you'll be messed up later. + if ($*comment_userpic_style == "small") { + $w = $w / 2; + $h = $h / 2; + } + " \n"; + } + " \n"; + " \n"; + + "\n \n"; + " \n \n \n
            \"$c.poster.username\"From: $posterDate: " + $c.time->date_format("long") + " - " + $c.time->time_format() + ""; + + # action links (screen, unscreen, delete, freeze, etc) + foreach var string k ($c.link_keyseq) { + var Link link = $c->get_link($k); + if ($link) { + " $link "; + } + } + + " ($*text_permalink)
            "; + if (defined $c.subject_icon or $c.subject != "") { "

            $c.subject_icon $c.subject

            \n"; } + if ($c.metadata{"poster_ip"}) { " (IP Address: " + $c.metadata{"poster_ip"} + ")
            "; } + + if ($this.multiform_on) { + " "; + $c->print_multiform_check(); + } + + "
            \n
            \n"; + "
            $c.text
            \n"; + "
            "; + if ($c.frozen) { + "(Replies frozen) "; + } else { + "(Reply to this) "; + } + if ($c.parent_url != "") { "(Parent) "; } + if ($c.thread_url != "") { "(Thread) "; } + "
            \n"; + print_comment_content_bottom(); + +} + +# The ReplyPage is without any comments...just the item being replied to and form. +function ReplyPage::print_body () +{ + var string time = $.replyto.time->time_format(); + + if (not $.entry.comments.enabled) + { + print "

            $*text_reply_nocomments_header

            $*text_reply_nocomments

            "; + return; + } + + var string posttime = "$time " + $.replyto.time->date_format("med"); + if ($.entry.security) { $posttime = $.entry.security_icon + "   " + $posttime; } + var string subject = ($.replyto.subject ? "$.replyto.subject" : ""); + var string poster = defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + var string pic = ""; + if (defined $.replyto.userpic) { $pic = "
            \"$.replyto.poster.username\"
            "; } + + print_entry_header($posttime); + +""" + + + + + + + + + + + +
            $pic
            $poster
            +
            + + + + + + +"""; + if($subject != "") { + +""" + + + + + +"""; + + } + + +""" + + + + + + + + + + + + +
            +
            $subject
            +"""; + + if($.replyto.text != "") { + "
            \"\"
            "; + } + +""" +
            +
            $.replyto.text
            +
            + +
            + +
            + +"""; + print_system_box_top(); + "

            Reply

            "; + $.form->print(); + print_system_box_bottom(); + +} + + + +############################################# +# +# Preview +# +############################################# + + +function print_theme_preview () +{ + """ + + + + +
            + + + + + + + + + + + + + + + + + + + + + + + +
            +
            Component Header
            +
            + + + + + +
            + + + + + + + + + + + + + + + + +
            +

            Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.

            +
            +
            +
            + """; +} diff --git a/ljcom/bin/upgrading/s2layers/component/themes.s2 b/ljcom/bin/upgrading/s2layers/component/themes.s2 new file mode 100644 index 0000000..4b96ccc --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/component/themes.s2 @@ -0,0 +1,187 @@ +#NEWLAYER: component/aquatic +layerinfo "type" = "theme"; +layerinfo "name" = "Aquatic"; +layerinfo redist_uniq = "component/aquatic"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#515151"; +set comp_bgcolor = "#51ada6"; +set header_link = "#ffffff"; +set entry_link = "#0C5D57"; +set entry_bgcolor = "#ffffff"; +set header_fgcolor = "#c7d1cc"; +set main_bgcolor = "#51ada6"; +set calendar_active = "#318D86"; +set header_bgcolor = "#0e3b4a"; +set calendar_inactive = "#ffffff"; +set comp_fgcolor = "#F7FEFF"; + +#NEWLAYER: component/bluetiful +layerinfo "type" = "theme"; +layerinfo "name" = "Bluetiful"; +layerinfo redist_uniq = "component/bluetiful"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#606060"; +set comp_bgcolor = "#f4f4f4"; +set header_link = "#f7fcfb"; +set entry_link = "#2d3679"; +set entry_bgcolor = "#eff5ff"; +set header_fgcolor = "#327192"; +set main_bgcolor = "#a2c5e3"; +set header_bgcolor = "#6da6c4"; +set comments_bgcolor = "#84b5d2"; + +#NEWLAYER: component/darkness +layerinfo "type" = "theme"; +layerinfo "name" = "Darkness"; +layerinfo redist_uniq = "component/darkness"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#22620e"; +set calendar_fgcolor = "#5b6c7a"; +set calendar_active = "#5b6c7a"; +set calendar_inactive = "#adbac5"; +set comp_fgcolor = "#dadde0"; +set entry_fgcolor = "#dddcd6"; +set comp_bgcolor = "#758491"; +set entry_link = "#adb6be"; +set header_link = "#c7ccd1"; +set entry_bgcolor = "#32343d"; +set main_bgcolor = "#71837A"; +set header_fgcolor = "#c7d1cc"; +set header_bgcolor = "#728d80"; +set comments_bgcolor = "#5a5a5a"; + +#NEWLAYER: component/jedicloak +layerinfo "type" = "theme"; +layerinfo "name" = "Jedi Cloak"; +layerinfo redist_uniq = "component/jedicloak"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#F1EDE5"; +set comp_bgcolor = "#988b67"; +set header_link = "#dddbd6"; +set entry_link = "#615020"; +set entry_bgcolor = "#ada386"; +set comments_screened_bgcolor = "#a29f97"; +set header_fgcolor = "#bcb59f"; +set main_bgcolor = "#6e5845"; +set calendar_active = "#817452"; +set header_bgcolor = "#6e6449"; +set calendar_inactive = "#988b67"; +set comp_fgcolor = "#383325"; +set comments_bgcolor = "#948B6F"; + +#NEWLAYER: component/mellow +layerinfo "type" = "theme"; +layerinfo "name" = "Mellow"; +layerinfo redist_uniq = "component/mellow"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#D6C8CC"; +set page_background_image = ""; +set calendar_active = "#D9E1D9"; +set calendar_inactive = "#A2B2B1"; +set comp_fgcolor = "878D8D"; +set entry_fgcolor = "#355351"; +set comp_bgcolor = "#C6CFD5"; +set entry_link = "#6B7F8D"; +set header_link = "6B7F8D"; +set entry_bgcolor = "#A2B2B1"; +set main_bgcolor = "#D6C8CC"; +set header_fgcolor = "#96A891"; +set header_bgcolor = "#D9E1D9"; +set comments_bgcolor = "#BCC4C3"; + +#NEWLAYER: component/mocha +layerinfo "type" = "theme"; +layerinfo "name" = "Mocha"; +layerinfo redist_uniq = "component/mocha"; +layerinfo "source_viewable" = 0; +set page_background_image = ""; +set entry_fgcolor = "#807C75"; +set comp_bgcolor = "#b1bbb4"; +set comp_fgcolor = "#78746e"; +set header_link = "#716C53"; +set entry_link = "#67716a"; +set entry_bgcolor = "#ebe6d1"; +set comments_screened_bgcolor = "#b2c9b9"; +set header_fgcolor = "#7a6f43"; +set main_bgcolor = "#d8d0ae"; +set calendar_active = "#8da193"; +set header_bgcolor = "#d8d0ae"; +set calendar_inactive = "#d3e1d7"; +set comments_bgcolor = "#dbdedc"; + +#NEWLAYER: component/orangesoda +layerinfo "type" = "theme"; +layerinfo "name" = "Orange Soda"; +layerinfo redist_uniq = "component/orangesoda"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#8a5b33"; +set comp_bgcolor = "#c4bd8e"; +set header_link = "#FFFFFF"; +set entry_link = "#613815"; +set entry_bgcolor = "#dbd7b9"; +set comments_screened_bgcolor = "#cbc9b9"; +set header_fgcolor = "#d7d2af"; +set main_bgcolor = "#cd9338"; +set calendar_active = "#cd9338"; +set header_bgcolor = "#c6710a"; +set calendar_inactive = "#dbd7b9"; +set comments_bgcolor = "#e4deb5"; + +#NEWLAYER: component/pinkelephants +layerinfo "type" = "theme"; +layerinfo "name" = "Pink Elephants"; +layerinfo redist_uniq = "component/pinkelephants"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#e29994"; +set page_background_image = ""; +set calendar_active = "#a8a8a7"; +set calendar_inactive = "#e29994"; +set comp_fgcolor = "#ad5a55"; +set entry_fgcolor = "#ffffff"; +set comp_bgcolor = "#f7b3ae"; +set entry_link = "#777776"; +set header_link = "#FFFFFF"; +set entry_bgcolor = "#a8a8a7"; +set main_bgcolor = "#e29994"; +set header_fgcolor = "#ad5a55"; +set header_bgcolor = "#e29994"; +set comments_bgcolor = "#9c9c9c"; + +#NEWLAYER: component/sugarspice +layerinfo "type" = "theme"; +layerinfo "name" = "Sugar and Spice"; +layerinfo redist_uniq = "component/sugarspice"; +layerinfo "source_viewable" = 0; +set entry_fgcolor = "#927DAD"; +set comp_bgcolor = "#D5EBFA"; +set header_link = "#6e5593"; +set entry_link = "#759EBA"; +set entry_bgcolor = "#D5E9D7"; +set comments_screened_bgcolor = "#BEC9BF"; +set header_fgcolor = "#6E5593"; +set main_bgcolor = "#FCD9C4"; +set calendar_active = "#FCD9C4"; +set header_bgcolor = "#D4CAE1"; +set calendar_inactive = "#D4CAE1"; +set comp_fgcolor = "AA9ABF"; +set comments_bgcolor = "#B9DABC"; + +#NEWLAYER: component/greensuperhero +layerinfo "type" = "theme"; +layerinfo "name" = "That Green Superhero"; +layerinfo redist_uniq = "component/greensuperhero"; +layerinfo "source_viewable" = 0; +set comments_screened_bgcolor = "#c99bd7"; +set page_background_image = ""; +set calendar_active = "#bc6ed4"; +set calendar_inactive = "#c99bd7"; +set comp_fgcolor = "#bc87cb"; +set entry_fgcolor = "#424242"; +set comp_bgcolor = "#efefe1"; +set entry_link = "#027040"; +set header_link = "#ffffff"; +set entry_bgcolor = "#e4ede9"; +set main_bgcolor = "#16b16c"; +set header_fgcolor = "#d0efe2"; +set header_bgcolor = "#049957"; +set comments_bgcolor = "#bed8cc"; diff --git a/ljcom/bin/upgrading/s2layers/cuteness/layout.s2 b/ljcom/bin/upgrading/s2layers/cuteness/layout.s2 new file mode 100644 index 0000000..71b5823 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/cuteness/layout.s2 @@ -0,0 +1,1534 @@ +layerinfo "type" = "layout"; +layerinfo "name" = "Cuteness Attack"; +layerinfo "des" = "OMFG Kittens and Flowers"; +layerinfo "author_name" = "Andy Mai"; +layerinfo "redist_uniq" = "cuteness/layout"; + +# First style from our new design intern Andy, based loosely on Tranquility II +# +# Todo: index layout images and use palimg_tint/gradient instead of just pink +# Todo: minor gap between "Comments {#}" heading and comments +# Todo: Add different face outlines +# Todo: Add themes + +# PROPERTIES: STYLES +propgroup Style { + # odd + property Color c_header_background { des = "Header Background Color"; } + property Color c_header_border { des = "Header Border Color"; } + # page + property Color c_page_background { des = "Page Background Color"; } + property string c_page_background_img { des = "Page Background Image"; note = "If left blank, an appropriate default will be chosen for you."; } + property string c_page_background_position { des = "Page Background Position (i.e Top Left)"; } + property string c_page_background_repeat { des = "Repeat Background"; values = "no-repeat|No|repeat-x|Repeat Horizontally|repeat-y|Repeat Vertically| |Tile"; } + property string c_page_background_attach { des = "Background Attachment"; values = "fixed|Fixed|scroll|Scroll"; } + property Color c_page_title { des = "Page Title color"; } + property Color c_page_text { des = "Page Text color"; } + property Color c_page_link { des = "Page Link color"; } + property Color c_page_link_visited { des = "Page Visited Link Color"; } + property Color c_page_link_hover { des = "Page Hover Link Color"; } + property Color c_page_link_active { des = "Page Active Link Color"; } + # menu + property Color c_menu_link { des = "Side Menu Link Color"; } + property Color c_menu_link_visited { des = "Side Menu Visited Link Color"; } + property Color c_menu_link_hover { des = "Side Menu Hover Link Color"; } + property Color c_menu_link_active { des = "Side Menu Active Link Color"; } + property Color c_menu_text_color { des = "Side Menu Text Color"; } + property Color c_menu_header_color { des = "Side Menu Header Color"; } + property Color c_menu_current { des = "Current Menu Item color"; } + # entry + property Color c_entry_background { des = "Entry Background Color"; } + property Color c_entry_link { des = "Entry Link Color"; } + property Color c_entry_link_visited { des = "Entry Visited Link Color"; } + property Color c_entry_link_hover { des = "Entry Hover Link Color"; } + property Color c_entry_link_active { des = "Entry Active Link Color"; } + property Color c_entry_text_color { des = "Entry Text Color"; } + property Color c_entry_title_color { des = "Entry Title Color"; } + property Color c_entry_border { des = "Entry Bottom Border Color"; } + # metadata + property Color c_meta_background { des = "Entry Metadata Background Color"; } + property Color c_meta_link { des = "Entry Metadata Link Color"; } + property Color c_meta_link_visited { des = "Entry metadata visited link color"; } + property Color c_meta_link_hover { des = "Entry Metadata Hover Link Color"; } + property Color c_meta_link_active { des = "Entry Metadata Active Link Color"; } + property Color c_meta_text_color { des = "Entry Metadata Text Color"; } + # footer + property Color c_footer_background { des = "Page Footer Background Color"; } + property Color c_footer_link { des = "Page Footer Link Color"; } + property Color c_footer_link_visited { des = "Page Footer Visited Link Color"; } + property Color c_footer_link_hover { des = "Page Footer Hover Link Color"; } + property Color c_footer_link_active { des = "Page Footer Active Link Color"; } + property Color c_footer_text_color { des = "Page Footer Text Color"; } + # comments + property Color c_comment_one_link { des = "Comment Link Color"; } + property Color c_comment_one_link_visited { des = "Comment Visited Link Color"; } + property Color c_comment_one_link_hover { des = "Comment Hover Link Color"; } + property Color c_comment_one_link_active { des = "Comment Active Link Color"; } + property Color c_comment_one_text_color { des = "Comment Text Color"; } + property Color c_comment_one_title_color { des = "Comment Title Color"; } + property Color c_comment_one_background { des = "Comment Bar Background Color"; } + property Color c_comment_one_border { des = "Comment Bottom Border Color"; } + property Color c_comment_screened_link { des = "Comment Screened Link Color"; } + property Color c_comment_screened_link_visited { des = "Comment Screened Visited Link Color"; } + property Color c_comment_screened_link_hover { des = "Comment Screened Hover Link Color"; } + property Color c_comment_screened_link_active { des = "Comment Screened Active Link Color"; } + property Color c_comment_screened_text_color { des = "Comment Screened Text Color"; } + property Color c_comment_screened_title_color { des = "Comment Screened Title Color"; } + property Color c_comment_screened_background { des = "Comment Screened Background Color"; } + property Color c_comment_screened_border { des = "Comment Screened Bottom Border Color"; } +} + + +# PROPERTIES: FONTS +propgroup Fonts { + # page + property string f_page { des = "Generic Main Page Font"; } + property string f_page_size { des = "Main Page Font Size"; } + property string f_page_title { des = "Main Page Title Font"; } + property string f_page_title_size { des = "Main Page Title Font Size"; } + property string f_page_link { des = "Generic Font for Page Links"; } + property string f_page_link_size { des = "Page Link Font Size"; } + # menu + property string f_menu_link { des = "Menu Link Font"; } + property string f_menu_link_size { des = "Menu Fink Font Size"; } + property string f_menu { des = "Menu Font"; } + property string f_menu_size { des = "Menu Font Size"; } + property string f_menu_header { des = "Menu Title Font"; } + property string f_menu_header_size { des = "Menu Title Font Size"; } + property string f_menu_current { des = "Current Menu Item Font"; } + property string f_menu_current_size { des = "Current Menu Item Font Size"; } + # entry + property string f_entry { des = "Entry Font"; } + property string f_entry_size { des = "Entry Font Size"; } + property string f_entry_link { des = "Entry Link Font"; } + property string f_entry_link_size { des = "Entry Link Font Size"; } + property string f_entry_title { des = "Entry Title Font"; } + property string f_entry_title_size { des = "Entry Title Font Size"; } + # metadata + property string f_meta { des = "Entry metadata font"; } + property string f_meta_size { des = "Entry metadata font size"; } + property string f_meta_link { des = "Entry metadata link font"; } + property string f_meta_link_size { des = "Entry metadata link font size"; } + # footer + property string f_footer { des = "Footer font"; } + property string f_footer_size { des = "Footer font size"; } + property string f_footer_link { des = "Footer link font"; } + property string f_footer_link_size { des = "Footer link font size"; } + # comments + property string f_comment { des = "Comment font"; } + property string f_comment_size { des = "Comment font size"; } + property string f_comment_title { des = "Comment title font"; } + property string f_comment_title_size { des = "Comment title font size"; } + property string f_comment_link { des = "Comment link font"; } + property string f_comment_link_size { des = "Comment link font size"; } +} + + +# PROPERTIES: PRESENTATION +propgroup Format { + property string face { des = "Choose a face style"; values = "cute|Cute Eyes|square|Square Eyes|dizzy|Dizzy|doll|Doll Face|happy|Happy|japanese|Japanese Style|curious|Curious"; note = "Choose wisely, you do not wish to see a permanent scowl!"; } + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property use use_shared_pic; + property use comment_userpic_style; + property bool show_entrynav_icons { des = "Toggle to show the next, memory, edit, etc icons on the entry view page"; } + property string time_format { des = "Format for the time"; example = "%%hh%%:%%min%%:%%sec%% %%a%%m"; } + property string date_format { des = "Format for the date"; example = "%%m%%/%%d%%/%%yy%%"; } + property bool menu_disable_summary { des = "Disable menu summary view"; } + property string css_style_overrides { des = "include any CSS here to override the default CSS"; } +} + + +# PROPERTIES: TEXT +propgroup Text { + property string text_page_title { des = "Title of your Live Journal"; } + property string text_summary_header { des = "Menu text header"; } + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_meta_music; + property use text_meta_mood; + property use text_permalink; + property use text_reply_nocomments_header; + property use text_reply_nocomments; + property use text_comment_from; + property use text_comment_ipaddr; + property use text_comment_parent; + property use text_comment_reply; + property use text_comment_thread; + property use text_nosubject; + property use text_post_comment; + property use text_post_comment_friends; + property use text_max_comments; + property use text_view_month; + property string text_comment_anonymous { des = "Text to substitute for anonymous commenters"; } + property string text_comment_viewall { des = "Text for view all comments"; } + property string text_links_header { des = "Sidebar links header text"; } + property string text_links_spacer { des = "String to act as links list spacer";} +} + + +# ------------------------------- +# default property settings +# ------------------------------- +# Style +set c_header_background = ""; +set c_header_border = ""; +set c_page_title = "#ffb2c7"; +set c_page_background = "#f7f0f3"; +set c_page_background_img = ""; +set c_page_background_position = "bottom"; +set c_page_background_repeat = "repeat-x"; +set c_page_background_attach = "fixed"; +set c_page_text = "#9F74A5"; +set c_page_link = "#9F74A5"; +set c_page_link_visited = "#9F74A5"; +set c_page_link_hover = "#c47a8e"; +set c_page_link_active = "#c47a8e"; +set c_menu_link = "#9F74A5"; +set c_menu_link_visited = "#9F74A5"; +set c_menu_link_hover = "#c47a8e"; +set c_menu_link_active = "#9F74A5"; +set c_menu_text_color = "#fff"; +set c_menu_header_color = "#fff"; +set c_menu_current = "#9F74A5"; +set c_entry_background = "#fff"; +set c_entry_link = "#9F74A5"; +set c_entry_link_visited = "#9F74A5"; +set c_entry_link_hover = "#c47a8e"; +set c_entry_link_active = "#9F74A5"; +set c_entry_text_color = "#9F74A5"; +set c_entry_title_color = "#9F74A5"; +set c_entry_border = "#ccc"; +set c_meta_background = "#fff"; +set c_meta_link = "#9F74A5"; +set c_meta_link_visited = "#9F74A5"; +set c_meta_link_hover = "#c47a8e"; +set c_meta_link_active = "#9F74A5"; +set c_meta_text_color = "#9F74A5"; +set c_footer_background = "#333"; +set c_footer_link = "#9F74A5"; +set c_footer_link_visited = "#9F74A5"; +set c_footer_link_hover = "#c47a8e"; +set c_footer_link_active = "#9F74A5"; +set c_footer_text_color = "#9F74A5"; +set c_comment_one_link = "#9F74A5"; +set c_comment_one_link_visited = "#9F74A5"; +set c_comment_one_link_hover = "#c47a8e"; +set c_comment_one_link_active = "#9F74A5"; +set c_comment_one_text_color = "#9F74A5"; +set c_comment_one_title_color = "#9F74A5"; +set c_comment_one_background = "#fff"; +set c_comment_one_border = "#f7f0f3"; +set c_comment_screened_link = "#9F74A5"; +set c_comment_screened_link_visited = "#9F74A5"; +set c_comment_screened_link_hover = "#c47a8e"; +set c_comment_screened_link_active = "#9F74A5"; +set c_comment_screened_text_color = "#333"; +set c_comment_screened_title_color = "#333"; +set c_comment_screened_background = "#fff"; +set c_comment_screened_border = "#999"; + +# FONTS +set f_page = "Tahoma, Verdana, san-serif"; +set f_page_title = "Arial Black, Arial, Verdana, San-serif"; +set f_page_title_size = "250%"; +set f_page_size = "12px"; +set f_page_link = "Tahoma, Verdana, san-serif"; +set f_page_link_size = "100%"; +set f_menu_link = "Verdana, Helvetica, sans-serif"; +set f_menu_link_size = "80%"; +set f_menu = "Verdana, Helvetica, sans-serif"; +set f_menu_size = "100%"; +set f_menu_header = "Tahoma, Verdana, san-serif"; +set f_menu_header_size = "120%"; +set f_menu_current = "Verdana, Helvetica, sans-serif"; +set f_menu_current_size = "80%"; +set f_entry = "Tahoma, Verdana, san-serif"; +set f_entry_size = "100%"; +set f_entry_link = "Tahoma, Verdana, san-serif"; +set f_entry_link_size = "100%"; +set f_entry_title = "Tahoma, Verdana, san-serif"; +set f_entry_title_size = "125%"; +set f_meta = "Verdana, Helvetica, sans-serif"; +set f_meta_size = "80%"; +set f_meta_link = "Verdana, Helvetica, sans-serif"; +set f_meta_link_size = "100%"; +set f_footer = "GTahoma, Verdana, san-serif"; +set f_footer_size = "100%"; +set f_footer_link = "Tahoma, Verdana, san-serif"; +set f_footer_link_size = "100%"; +set f_comment = "Tahoma, Verdana, san-serif"; +set f_comment_size = "100%"; +set f_comment_title = "Georgia, serif"; +set f_comment_title_size = "130%"; +set f_comment_link = "Georgia, serif"; +set f_comment_link_size = "100%"; + +# OTHER +set face = "cute"; +set show_entrynav_icons = true; +set time_format = "%%hh%%:%%min%% %%a%%m"; +set date_format = "%%mon%%. %%dayord%%, %%yyyy%%"; +set menu_disable_summary = false; +set css_style_overrides = ""; + +# TEXT +set text_page_title = "My LiveJournal"; +set text_meta_music = "music"; +set text_links_header = "links"; +set text_meta_mood = "mood"; +set text_read_comments = "{#}"; +set text_read_comments_friends = "{#}"; +set text_comment_anonymous = "anonymous"; +set text_comment_viewall = "view all comments"; +set text_links_header = "Links"; +set text_summary_header = "Menu"; +set text_links_spacer = "_______________"; + + + +# ======================================== +# METHODS +# ======================================== + + +# ------------------------------- +# prop_init +# ------------------------------- + +function prop_init() { + if ($*c_page_background_img == "") { $*c_page_background_img = "$*IMGDIR/style/cuteness/bg-pink.gif"; } + + # Determine which "face" to use + if ($*face == "cute") { + $*face = "$*IMGDIR/style/cuteness/face-cute.gif"; + } elseif ($*face == "square") { + $*face = "$*IMGDIR/style/cuteness/face-square.gif"; + } elseif ($*face == "dizzy") { + $*face = "$*IMGDIR/style/cuteness/face-dizzy.gif"; + } elseif ($*face == "doll") { + $*face = "$*IMGDIR/style/cuteness/face-doll.gif"; + } elseif ($*face == "happy") { + $*face = "$*IMGDIR/style/cuteness/face-happy.gif"; + } elseif ($*face == "japanese") { + $*face = "$*IMGDIR/style/cuteness/face-japanese.gif"; + } elseif ($*face == "curious") { + $*face = "$*IMGDIR/style/cuteness/face-curious.gif"; + } +} + +# ------------------------------- +# stylesheet +# ------------------------------- +function print_stylesheet ( ) +{ + """ + @media screen, print { + * { + margin: 0; + padding: 0; + } + hr { + display: none; + } + + html>body { + background-color: $*c_page_background; + background-image: url($*c_page_background_img); + background-position: $*c_page_background_position; + background-repeat: $*c_page_background_repeat; + background-attachment: $*c_page_background_attach; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + } + + body { + background-color: $*c_page_background; + background-image: url($*c_page_background_img); + background-position: $*c_page_background_position; + background-repeat: $*c_page_background_repeat; + background-attachment: $*c_page_background_attach; + font-family: $*f_page; + font-size: $*f_page_size; + line-height: 125%; + color: $*c_page_text; + margin-top: 30px; + } + a { + font-family: $*f_page_link; + font-size: $*f_page_link_size; + color: $*c_page_link; + text-decoration: none; + } + a:visited { color: $*c_page_link_visited; } + a:hover, a:visited:hover { color: $*c_page_link_hover; text-decoration: underline; } + a:active { color: $*c_page_link_active; } + a img { border: none; } + a.comm { + background: transparent url($*IMGDIR/community.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + a.user { + background: transparent url($*IMGDIR/userinfo.gif) no-repeat; + padding-left: 19px; + padding-bottom: 7px; + } + p { + margin: 5px; + padding: 5px; + } + + + form { + display: inline; + margin-left: 00px; + padding: 0px; + width: 425px; + } + + + input, select, textarea { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + padding: 2px; + margin: 3px; + } + + #container { + position: relative; + width: 700px; + margin: 0 auto; + text-align: left; + } + html>body #header { + position: absolute; + margin-top: 65px; + margin-left: 5px; + z-index: 5; + background-color: $*c_header_background; + } + + #header { + position: absolute; + margin-top: 50px; + margin-left: -180px; + z-index: 5; + padding: 10px; + background-color: $*c_header_background; + } + + #header h1 { + font-family: $*f_page_title; + font-size: $*f_page_title_size; + color: $*c_page_title; + } + + #face { + position: absolute; + width: 203px; + height: 197px; + background-image: url($*face); + background-repeat: no-repeat; + z-index: 10; + margin-left: 290px; + margin-top: -10px; + } + + html>body #face { + position: absolute; + width: 203px; + height: 197px; + background-image: url($*face); + background-repeat: no-repeat; + z-index: 10; + margin-left: 485px; + margin-top: 10px; + } + + + #comments h3 img { + border: 5px solid #f7f0f3; + background-color: #fff; + } + + + + #userpicbg { + position: relative; + background-image: url($*IMGDIR/style/cuteness/userpicbg.gif); + background-repeat: no-repeat; + width: 163px; + height: 169px; + margin-left: 5px; + } + + html>body #userpicbg img { + padding-top: 43px; + padding-right: 10px; + } + + #userpicbg img { + padding-top: 23px; + padding-right: 10px; + } + + .ind-entry h3.userpic img { + float: left; + margin-top: 10px; + } + + #menu { + position: relative; + float: left; + font-family: $*f_menu; + font-size: $*f_menu_size; + color: $*c_menu_text_color; + padding: 4px; + margin-top: 80px; + + } + + #menu-links { + background-image: url($*IMGDIR/style/cuteness/menubg.gif); + background-repeat: no-repeat; + margin-left: -10px; + margin-top: 5px; + width: 164px; + height: 179px; + padding-left: 30px; + padding-top: 3px; + } + html>body #content { + position: relative; + margin-top: 5px; + margin-left: 160px; + width: 532px; + z-index: 4; + } + + #content { + position: relative; + margin-top: -475px; + margin-left: 160px; + width: 532px; + z-index: 4; + } + + #entries { + position: relative; + background-image: url($*IMGDIR/style/cuteness/entry-bg.gif); + background-repeat: repeat-y; + width: 532px; + + } + + #entriesbg { + position: relative; + background-image: url($*IMGDIR/style/cuteness/content-header.gif); + background-position: top left; + background-repeat: no-repeat; + margin-left: 1px; + width: 532px; + } + + #entries-content { + position: relative; + padding-top: 130px; + width: 532px; + } + + #menu h2 { + margin: 20px 0; + font-family: $*f_menu_header; + font-size: $*f_menu_header_size; + color: $*c_menu_header_color; + } + #menu h2.userpic { + text-align: center; + } + #menu a { + font-family: $*f_menu_link; + font-size: $*f_menu_link_size; + color: $*c_menu_link; + } + #menu a:visited { color: $*c_menu_link_visited; } + #menu a:hover, #menu a:visited:hover { color: $*c_menu_link_hover; } + #menu a:active { color: $*c_menu_link_active; } + #menu ul { + margin: 3px; + list-style: none; + } + #menu ul li { + margin: 3px; + padding: 2px; + list-style: none; + } + #menu ul li.active { + font-family: $*f_menu_current; + font-size: $*f_menu_current_size; + color: $*c_menu_current; + font-weight: bold; + } + + #content h2 { + margin: 20px 0; + } + #entries, #comments { + margin: 10px; + } + + #entrybottom { + position: relative; + background-image: url($*IMGDIR/style/cuteness/entry-bottombg.gif); + background-repeat: no-repeat; + width: 528px; + height: 47px; + margin-left: 11px; + margin-top: -10px; + } + + #comment-info { + background-color: #f7f0f3; + } + + #comments div.entry-item { + padding: 5px; + } + + #comments div.ind-comment-one { + border: 2px solid $*c_comment_one_border; + background-color: $*c_comment_one_background; + + } + + .ljtaglist { + margin-left: 10px; + } + + .ind-entry { + width: 440px; + border-bottom: 1px solid $*c_entry_border; + margin-left: 25px; + padding: 10px; + } + .ind-entry h3 img, .ind-comment-one h3 img, .ind-comment-two h3 img, .ind-comment-screened h3 img { + position: relative; + float: right; + padding: 5px; + } + .ind-entry h2 { + font-family: $*f_entry_title; + font-size: $*f_entry_title_size; + color: $*c_entry_title_color; + margin: 20px 0px; + line-height: 140%; + } + .ind-entry h4, .ind-comment-one h4, .ind-comment-two h4, .ind-comment-screened h4 { + font-family: $*f_meta; + font-size: $*f_meta_size; + color: $*c_meta_text_color; + } + + .ind-entry h4 a, .ind-comment-one h4 a, .ind-comment-two h4 a, .ind-comment-screened h4 a { + font-family: $*f_meta_link; + font-size: $*f_meta_link_size; + color: $*c_meta_link; + text-decoration: underline; + } + .ind-entry h4 a:visited, .ind-comment-one h4 a:visited, .ind-comment-two h4 a:visited, .ind-comment-screened h4 a:visited { color: $*c_meta_link_visited; } + .ind-entry h4 a:hover, .ind-comment-one h4 a:hover, .ind-comment-two h4 a:hover, .ind-comment-screened h4 a:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:visited:hover, .ind-comment-one h4 a:visited:hover, .ind-comment-two h4 a:visited:hover, .ind-comment-screened h4 a:visited:hover { color: $*c_meta_link_hover; } + .ind-entry h4 a:active, .ind-comment-one h4 a:active, .ind-comment-two h4 a:active, .ind-comment-screened h4 a:active { color: $*c_meta_link_active; } + .ind-entry div.entry-item, .ind-entry div.month-entries { + font-family: $*f_entry; + font-size: $*f_entry_size; + color: $*c_entry_text_color; + margin: 15px 0px; + } + .ind-entry div.entry-item a, .ind-entry div.month-entries a { + font-family: $*f_entry_link; + font-size: $*f_entry_link_size; + color: $*c_entry_link; + text-decoration: underline; + } + .ind-entry div.entry-item a:visited, .ind-entry div.month-entries a:visited { color: $*c_entry_link_visited; } + .ind-entry div.entry-item a:hover, .ind-entry div.entry-item a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.month-entries a:hover, .ind-entry div.month-entries a:visited:hover { color: $*c_entry_link_hover; } + .ind-entry div.entry-item a:active, .ind-entry div.month-entries a:active { color: $*c_entry_link_active; } + + .ind-comment-one, .ind-comment-two, .ind-comment-screened { + margin: 10px 0; + padding: 5px; + } + .ind-comment-screened { background-color: $*c_comment_screened_background; border-bottom: 1px solid $*c_comment_screened_border; } + + .ind-comment-one h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_one_title_color; + margin: 20px 0px; + } + .ind-comment-one div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_one_text_color; + margin: 15px 0px; + } + .ind-comment-one div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_one_link; + text-decoration: underline; + } + .ind-comment-one div.entry-item a:visited { color: $*c_comment_one_link_visited; } + .ind-comment-one div.entry-item a:hover, .ind-comment-one div.entry-item a:visited:hover { color: $*c_comment_one_link_hover; } + .ind-comment-one div.entry-item a:active { color: $*c_comment_one_link_active; } + + + .ind-comment-screened h2 { + font-family: $*f_comment_title; + font-size: $*f_comment_title_size; + color: $*c_comment_screened_title_color; + margin: 20px 0px; + } + .ind-comment-screened div.entry-item { + font-family: $*f_comment; + font-size: $*f_comment_size; + color: $*c_comment_screened_text_color; + margin: 10px 0px; + } + .ind-comment-screened div.entry-item a { + font-family: $*f_comment_link; + font-size: $*f_comment_link_size; + color: $*c_comment_screened_link; + text-decoration: underline; + } + .ind-comment-screened div.entry-item a:visited { color: $*c_comment_screened_link_visited; } + .ind-comment-screened div.entry-item a:hover, .ind-comment-screened div.entry-item a:visited:hover { color: $*c_comment_screened_link_hover; } + .ind-comment-screened div.entry-item a:active { color: $*c_comment_screened_link_active; } + + #comments { + width: 425px; + margin-left: 40px; + } + + .month-entries { + margin: 10px 0; + } + .month-entries ul { + list-style: none; + margin: 10px; + } + .month-entries ul li { + list-style: none; + padding: 3px; + } + + + #footer { + position: relative; + font-family: $*f_footer; + font-size: $*f_footer_size; + color: $*c_footer_text_color; + background-image: url($*IMGDIR/style/cuteness/footerbg.gif); + background-repeat: no-repeat; + width: 508px; + height: 53px; + margin-top: 20px; + } + #footer p { + padding-top: 10px; + padding-left: 30px; + vertical-align: middle; + } + #footer a { + font-family: $*f_footer_link; + font-size: $*f_footer_link_size; + color: $*c_footer_link; + } + #footer a:visited { color: $*c_footer_link_visited; } + #footer a:hover, #footer a:visited:hover { color: $*c_footer_link_hover; } + #footer a:active { color: $*c_footer_link_active; } + } + + @media print { + #menu { + display: none; + } + #content { + margin-left: 0px; + } + #entries, .ind-entry, .ind-comment, #footer, #header { + border: none; + } + + } + + $*css_style_overrides + + """; +} + + +# ------------------------------- +# user pic main page +# ------------------------------- +function Page::lay_top_userpic ( ) +{ + var Image up_img = $.journal.default_pic; + if ( defined $up_img ) { + print "

            \"$.journal.name\"

            "; + } +} + + +# ------------------------------- +# returns a permalink link based on +# the url passed +# ------------------------------- +function get_permalink ( string url ) : string +{ + return("$*text_permalink"); +} + + + +# ------------------------------- +# prints the user's 'link-list' +# ------------------------------- +function Page::print_linklist ( ) +{ + + if ( size $.linklist > 0 ) { + print "

            $*text_links_header

            "; + print "
              "; + foreach var UserLink l ( $.linklist ) { + if ( $l.title == "spacer" ) { + print "
            • $*text_links_spacer
            • "; + } elseif ($l.is_heading) { + print "
            • $l.title
            • "; + } elseif ( $l.title ) { + print "
            • $l.title
            • "; + } + } + print "
            "; + print "
            "; + } +} + + +# ------------------------------- +# prints the LJ specific links (recent, friends, etc) +# ------------------------------- +function print_lj_links ( Page p ) +{ + var string links; + $links = $links + ($p.view == "recent" ? "
          7. $*text_view_recent
          8. " : "
          9. $*text_view_recent
          10. "); + if ( $p.journal_type == "C" ) { + $links = $links + ($p.view == "friends" ? "
          11. $*text_view_friends_comm
          12. " : "
          13. $*text_view_friends_comm
          14. "); + } else { + $links = $links + ($p.view == "friends" ? "
          15. $*text_view_friends
          16. " : "
          17. $*text_view_friends
          18. "); + } + $links = $links + ($p.view == "archive" ? "
          19. $*text_view_archive
          20. " : "
          21. $*text_view_archive
          22. "); + $links = $links + "
          23. $*text_view_userinfo
          24. "; + $links = $links + ($p.journal.website_url != "" ? "
          25. lower() + "\">" + $p.journal.website_name->lower() + "
          26. " : ""); + + print "
              "; + print $links; + print "
            "; + print "
            "; +} + +function Page::lay_sidebar_view_summary() : string +{ + return(""); +} + + +# ------------------------------- +# main page layout +# ------------------------------- +function Page::print ( ) +{ + var string title = $this->title(); + + # generate page id: + var string current_view = $.view; + if ( $.view == "month" or $.view == "day" ) { + $current_view = "archive"; + } + if ( $.view == "entry" or $.view == "reply" ) { + $current_view = "recent"; + } + + # begin main page html: + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + $this->print_head(); + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$*text_page_title\n"; + print "\n"; + print "\n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "

            $*text_page_title

            \n"; + print "
            "; + print "
            \n"; + print "
            \n"; + + print "
            \n"; + print "
            \n"; + $this->lay_top_userpic(); + print "\n"; + print "
            \n"; + print "
            \n"; + print "

            $*text_summary_header

            \n"; + print_lj_links($this); + print "
            \n"; + print "\n"; + print "
            \n"; + print "
            \n"; + $this->print_body(); + print "
            \n"; + print "
            \n"; + print "\n"; + print "\n"; +} + + +# ------------------------------- +# main page display entries and +# footer +# ------------------------------- +function RecentPage::print_body ( ) +{ + + + # print all entries + print "
            \n"; + print "
            \n"; + print "
            \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + + var string range = "most recent entries"; + if ( $.nav.skip > 0 ) { + $range = "$.nav.skip entries back"; + } + + print "

            "; + print "viewing: $range
            "; + # go forward/backward if possible + if ( $.nav.forward_url != "" or $.nav.backward_url != "" ) { + var string sep; + var string back; + var string forward; + if ( $.nav.backward_url != "" ) { + $back = "earlier"; + } + if ( $.nav.forward_url != "" ) { + $forward = "later"; + } + if ( $back != "" and $forward != "" ) { + $sep = " | "; + } + print "go: $back$sep$forward
            "; + } + print "

            "; + +} + + +# ------------------------------- +# entry view (show comments) +# ------------------------------- +function EntryPage::print_body ( ) +{ + print "
            \n"; + print "
            \n"; + print "
            \n"; + $this->print_entry ( $.entry ); + if ( $.entry.comments.enabled ) { + print "
            "; + print "

            Comments {$.entry.comments.count}

            "; + + if ( $.comment_pages.total_subitems > 0 ) { + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + $.comment_pages->print(); + $this->print_comments($.comments); + if ( $this.multiform_on ) { + $this->print_multiform_actionline(); + $this->print_multiform_end(); + } + } + print "
            "; + + } + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + print "

            "; + print "$*text_post_comment\n"; + print "

            "; +} + + +# ------------------------------- +# day view +# ------------------------------- +function DayPage::print_body ( ) +{ + if ( not $.has_entries ) { + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "

            " + $.date->date_format("long") + "

            "; + print "

            $*text_noentries_day

            "; + print "
            "; + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + print "
            "; + } else { + print "
            \n"; + print "
            \n"; + print "
            \n"; + foreach var Entry e ( $.entries ) { + $this->print_entry($e); + } + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + } + + var string tprev = ehtml($*text_day_prev); + var string tnext = ehtml($*text_day_next); + + print "

            "; + print "« $*text_day_prev | $*text_day_next »"; + print "

            "; +} + + +# ------------------------------- +# year view +# ------------------------------- +function YearPage::print_body ( ) +{ + print "
            \n"; + print "
            \n"; + print "
            \n"; + $this->print_year_links(); + foreach var YearMonth m ($.months) { + $this->print_month($m); + } + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; +} + + +# ------------------------------- +# display an entry (all views ) +# ------------------------------- +function print_entry ( Page p, Entry e ) +{ + # get date/time + var string datetime; + $datetime = $e.time->date_format($*date_format) + " | " + $e.time->time_format($*time_format); + + # get metadata + var string metadata; + if ( $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string text = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $text = $*text_meta_mood; + } elseif ( $k == "music" ) { + $text = $*text_meta_music; + } + if ( $k == "mood" and defined $e.mood_icon ) { + var Image i = $e.mood_icon; + $val = "\"$val\" $val"; + } + $metadata = "$metadata\n$text: $val
            "; + } + } + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( $p.view == "friends" or $p.journal_type == "C" or $e.poster.username != $e.journal.username ) { + if ( $e.poster.username != $e.journal.username ) { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username in base_url() + "\" title=\"$e.journal.username\" >$e.journal.username"; + } else { + $poster = "base_url() + "\" title=\"$e.poster.username\">$e.poster.username"; + } + $poster = "posted by: $poster"; + if ( defined $e.userpic ) { + $userpic = "

            \"$e.journal.username\"

            "; + } + } + + # print the entry now: + print "
            "; + + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + + print "

            "; + if ( $e.security != "" ) { + $e.security_icon->print(); + print " "; + } + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + print "

            "; + + print "

            "; + if ( $p.view == "entry" and $*show_entrynav_icons ) { + var string item_link = ""; + foreach var string key (["nav_prev","nav_next"]) { + var Link link = $e->get_link($key); + if ( $link ) { + if ( $key == "nav_prev" ) { + $item_link = $item_link + "lower() + "\">« " + $link.caption->lower() + " | "; + } elseif ( $key == "nav_next" ) { + $item_link = $item_link + "lower() + "\">" + $link.caption->lower() + " »"; + } + } + } + print $item_link; + print "
            "; + } + print "$datetime
            "; + print "$metadata"; + if ( $poster != "" ) { + print "$poster"; + } + print "

            "; + + print "
            $e.text
            \n"; + + print "

            "; + print get_permalink($e.permalink_url); + if ( $p.view != "entry" and $p.view != "reply" ) { + print " | "; + $e.comments->print(); + } elseif ( $e.comments.enabled ) { + print " | "; + $e.comments->print_postlink(); + } + var Link tmp; + if ( viewer_is_owner() and $p.view != "friends" ) { + $tmp = $e->get_link("edit_entry"); + print " | $tmp.caption"; + } + $tmp = $e->get_link("mem_add"); + print " | $tmp.caption"; + print "

            "; + print "
            "; + print "
            "; +} + + +# ------------------------------- +# entry wrapper for main page +# ------------------------------- +function Page::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +# ------------------------------- +# entry wrapper for friends page +# ------------------------------- +function FriendsPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + +function EntryPage::print_entry ( Entry e ) +{ + print_entry($this, $e); +} + + + +# ------------------------------- +# comments +# ------------------------------- +function CommentInfo::print ( ) +{ + if ( not $.enabled ) { + return; + } + + $this->print_postlink(); + if ( $.count > 0 or $.screened ) { + print " "; + print ""; + $this->print_readlink(); + print ""; + } +} + + +# ------------------------------- +# comment post link +# ------------------------------- +function CommentInfo::print_postlink ( ) +{ + var Page p = get_page(); + var string linktext = ( $p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment ); + if ( $.maxcomments ) { + "$*text_max_comments"; + } else { + "$linktext"; + } +} + + +# ------------------------------- +# print comment +# ------------------------------- +function EntryPage::print_comment ( Comment c ) +{ + var string comment_class = ""; + if ( $c.screened ) { + $comment_class = "ind-comment-screened"; + } elseif ( $c.depth % 2 == 0 ) { + $comment_class = "ind-comment-two"; + } else { + $comment_class = "ind-comment-one"; + } + + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_comment_anonymous"; + var string poster_text = defined $c.poster ? $c.poster.name : "$*text_comment_anonymous"; + var string sub_icon; + var int indent = (($c.depth - 1) * 5); + if ( defined $c.subject_icon ) { + $sub_icon = $c.subject_icon->as_string(); + } + + print "
            \n"; + + var string userpic; + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + $userpic = "

            \"$poster_text\"

            "; + } + var string commentdate = $c.time->date_format($*date_format) + " - " + $c.time->time_format($*time_format); + + + + # subject: + if ( $c.subject == "" ) { + print ""; + } else { + print "

            $c.subject_icon $c.subject

            "; + } + + print "
            "; + print "

            "; + #userpic + print "$userpic\n"; + print "From: $poster
            \n"; + print "Date: $commentdate
            \n"; + if ( $c.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $c.metadata{"poster_ip"} + "
            "; + } + print get_permalink($c.permalink_url) + "\n"; + var Link lnk; + $lnk = $c->get_link("delete_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("screen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + $lnk = $c->get_link("unscreen_comment"); + if ( $lnk.caption != "" ) { print " [lower() + "\">" + $lnk.caption->lower() + "]"; } + print "


            \n"; + + if ( $this.multiform_on ) { + print ""; + $c->print_multiform_check(); + } + + print "
            $c.text
            \n"; + print "

            "; + print "$*text_comment_reply"; + if ( $c.parent_url != "" ) { print " | $*text_comment_parent"; } + if ( $c.thread_url != "" ) { print " | $*text_comment_thread"; } + print "

            "; + print "
            \n\n"; + print "
            "; + + +} + +# ------------------------------- +# print tags list page form +# ------------------------------- +function TagsPage::print_body ( ) +{ + """ +
            +
            +

            Visible Tags

            +
              + """; + + foreach var TagDetail td ($.tags) { + var string uses = get_plural_phrase($td.use_count, "text_tag_uses"); + print """
            • $td.name - $uses
            • """; + } + + """ +
            +
            +
            + """; +} + +# ------------------------------- +# print reply form page +# ------------------------------- +function ReplyPage::print_body ( ) +{ + if ( not $.entry.comments.enabled ) { + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            "; + print "

            $*text_reply_nocomments_header

            "; + print "$*text_reply_nocomments"; + print "
            "; + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + + } else { + print "
            \n"; + print "
            \n"; + print "
            \n"; + # get date + var string datetime; + $datetime = $.replyto.time->date_format($*date_format) + " | " + $.replyto.time->time_format($*time_format); + + # get any extra user info (if posting to community, etc) + var string poster = ""; + var string userpic = ""; + if ( defined $.replyto.poster ) { + $poster = "base_url() + "\" title=\"$.replyto.poster.username\">$.replyto.poster.username"; + if ( defined $.replyto.userpic ) { + $userpic = "

            \"$.replyto.poster.username\"

            "; + } + } else { + $poster = "$*text_comment_anonymous"; + } + + + # print the entry now: + print "
            "; + # print icon (if needed) + if ( $userpic != "" ) { + print "$userpic"; + } + print "

            "; + if ( $.replyto.subject == "" ) { + print ""; + } else { + print "$.replyto.subject"; + } + print "

            "; + + print "

            \n"; + print "$datetime
            "; + print "$*text_comment_from: $poster"; + if ( $.replyto.metadata{"poster_ip"} ) { + print "$*text_comment_ipaddr " + $.replyto.metadata{"poster_ip"} + "
            "; + } + print "

            "; + print "
            $.replyto.text
            \n"; + print "

            "; + print get_permalink($.replyto.permalink_url) + " | $*text_comment_viewall\n"; + print "

            "; + print "
            \n"; + print "
            "; + print "
            \n"; + print "

            Reply

            \n"; + $.form->print(); + print "
            "; + print "
            "; + print "
            "; + print "
            "; + print "
            \n"; + print "
            "; + } +} + + +# ------------------------------- +# print available years +# ------------------------------- +function YearPage::print_year_links ( ) +{ + print "
            \n"; + print "

            "; + print "available years:
            "; + foreach var YearYear y ($.years) { + if ($y.displayed) { + print "$y.year "; + } else { + print "$y.year "; + } + } + print "

            "; + +} + + +# ------------------------------- +# print available month +# ------------------------------- +function YearPage::print_month ( YearMonth m ) +{ + if ( not $m.has_entries ) { + return; + } + + + print "

            " + $m->month_format() + "

            \n"; + print "

            $*text_view_month

            "; + print "
            "; + foreach var YearWeek w ( $m.weeks ) { + foreach var YearDay d ( $w.days ) { + if ( $d.num_entries > 0 ) { + var string date = $d.date->date_format("%%dayord%%"); + print "$date {$d.num_entries}
            \n"; + } + } + } + print "
            \n"; + print "
            \n"; + print "
            "; +} + + +# ------------------------------- +# month view +# ------------------------------- +function MonthPage::print_body ( ) +{ + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "

            " + $.date->date_format($*lang_fmt_month_long) + "

            "; + + print "
            "; + $.redir->print_hiddens(); + if ( $.prev_url != "" ) { + print "[«]\n"; + } + if ( size $.months > 1 ) { + print "\n"; + } + if ( $.next_url != "" ) { + print "\n[»]\n"; + } + print "


            "; + + # print dates: + foreach var MonthDay d ( $.days ) { + if ( $d.has_entries ) { + print "
            \n"; + print "" + lang_ordinal($d.day) + "
            "; + print "
              "; + foreach var Entry e ( $d.entries ) { + print "
            • "; + print "" + $e.time->time_format("short") + " "; + if ( $e.poster.username != $e.journal.username ) { + $e.poster->print(); " : "; + } + "$e.security_icon "; + if ( $e.subject == "" ) { + print "$*text_nosubject"; + } else { + print "$e.subject"; + } + if ( $e.comments.count > 0 ) { + print " {" + $e.comments.count + "}"; + } + print "
            • "; + } + print "
            "; + print "
            "; + print "
            "; + } + } + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            \n"; + print "
            "; + print "
            "; + +} diff --git a/ljcom/bin/upgrading/s2layers/flexiblesquares/layout.s2 b/ljcom/bin/upgrading/s2layers/flexiblesquares/layout.s2 new file mode 100644 index 0000000..04dd629 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/flexiblesquares/layout.s2 @@ -0,0 +1,2076 @@ +# ----------------------------------- +# LAYER INFO +# ----------------------------------- +layerinfo type = "layout"; +layerinfo name = "Flexible Squares"; +layerinfo lang = "en"; +layerinfo author_name = "Yati Mansor"; +layerinfo redist_uniq = "flexiblesquares/layout"; + +# ----------------------------------- +# PROPGROUPS +# ----------------------------------- + + +### PRESENTATION +propgroup presentation = "Presentation"; +propgroup presentation +{ + property use page_recent_items; + property use page_friends_items; + property use view_entry_disabled; + property bool show_entry_userpic + { + des = "Show user picture icons with each of your entries?"; + } + property string userpic_position + { + des = "Set the user picture position for each entry"; + values = "left|Left|right|Right"; + } + property bool use_friends_colours + { + des = "Use friends colours when viewing friends list?"; + } + set show_entry_userpic = true; + set userpic_position = "left"; + set use_friends_colours = true; + property use use_shared_pic; + property string page_alignment + { + des = "Set page alignment"; + values= "right|Right|center|Center|left|Left"; + } + set page_alignment = "center"; + property int journal_width + { + des = "Journal width"; + note = "Journal width can be set in either percentage of the browser window or in pixels (see next option)"; + min = 1; + } + property string journal_width_unit + { + des = "Unit of journal width"; + note = "Journal width can be set either in percentage of the browser window or in pixels"; + values = "%|%|px|px"; + } + set journal_width = 80; + set journal_width_unit = "%"; + +} + + +### SIDEBAR +propgroup sidebar = "Sidebar"; +propgroup sidebar +{ + property bool show_sidebar + { + des = "Show the sidebar?"; + } + set show_sidebar = true; + property string sidebar_position + { + des="Set sidebar position"; + values="left|Left|right|Right"; + } + set sidebar_position="right"; + property bool show_default_userpic + { + des = "Show the default user picture on the sidebar?"; + } + set show_default_userpic = true; + property bool show_blurb + { + des = "Show the blurb/free text in the sidebar?"; + } + property string text_sidebar_blurb + { + des = "Title of the blurb sidebar box"; + } + property string sidebar_blurb { + des = "Text to be added to the sidebar"; + note = "Appears in the sidebar 'Blurb'"; + rows = 10; + cols = 25; + } + set show_blurb = true; + set text_sidebar_blurb = "Blurb"; + property bool show_linklist + { + des = "Show the link list in the sidebar?"; + } + property string text_sidebar_links + { + des = "Title of the links sidebar box"; + } + set show_linklist = true; + set text_sidebar_links = "Links"; + property bool show_calendar + { + des = "Show the calendar in the sidebar?"; + } + set show_calendar = true; + property int sidebar_width + { + des = "Set sidebar width, in pixels"; + min = 0; + } + set sidebar_width = 160; + property string sidebar_order_1 + { + des = "First box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_2 + { + des = "Second box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_3 + { + des = "Third box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + property string sidebar_order_4 + { + des = "Fourth box in the sidebar"; + values = "userpic|Default Userpic|blurb|Blurb|linklist|Link List|calendar|Calendar"; + } + set sidebar_order_1 = "userpic"; + set sidebar_order_2 = "blurb"; + set sidebar_order_3 = "linklist"; + set sidebar_order_4 = "calendar"; +} + + +### BACKGROUND +propgroup background = "Background"; +propgroup background +{ + property string page_background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none)."; + } + property string page_background_repeat + { + des = "Background image repeat"; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string page_background_position + { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + property string page_background_scrolling + { + des = "Background image scrolling"; + note = "Not supported in all browsers, but allows for the background image to be in a fixed position when scrolling."; + values = "scroll|Scroll|fixed|Fixed"; + } + set page_background_image = ""; + set page_background_repeat = "repeat"; + set page_background_position = "center"; + set page_background_scrolling = "scroll"; +} + + + +### FONTS +propgroup fonts = "Fonts"; +propgroup fonts +{ + property string font_unit + { + des = "Font unit"; + values = "pt|Points|px|Pixels|em|Em"; + } + set font_unit = "px"; + property string main_font + { + des = "Preferred/base font"; + maxlength = 25; + size = 10; + example = "Tahoma"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int main_font_size + { + des = "Base font size"; + } + set main_font = "Verdana"; + set main_font_fallback = "sans-serif"; + set main_font_size= 11; + property string content_font + { + des = "Font for the entry/date/entry subject"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int content_font_size + { + des = "Entry/date/subject font size"; + } + property int date_font_size + { + des = "Date font size"; + } + property int subject_font_size + { + des = "Subject font size"; + } + set content_font = "Verdana"; + set content_font_fallback = "sans-serif"; + set content_font_size= 11; + set date_font_size= 11; + set subject_font_size= 11; + + + property string sidebar_font + { + des = "Font for the sidebar"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string sidebar_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int sidebar_font_size + { + des = "Sidebar font size"; + } + + set sidebar_font = "Verdana"; + set sidebar_font_fallback = "sans-serif"; + set sidebar_font_size= 11; + + property string header_footer_font + { + des = "Font for the header and footer"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string header_footer_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int header_footer_font_size + { + des = "Header and footer font size"; + } + + set header_footer_font = "Verdana"; + set header_footer_font_fallback = "sans-serif"; + set header_footer_font_size= 11; + + property string title_font + { + des = "Font for the title and subtitle"; + maxlength = 25; + size = 10; + example = "Verdana"; + note = "Leave blank for your browser's default font"; + } + property string title_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property int title_font_size + { + des = "Title font size"; + } + property int subtitle_font_size + { + des = "Subtitle font size"; + } + set title_font = "Verdana"; + set title_font_fallback = "sans-serif"; + set title_font_size= 11; + set subtitle_font_size= 11; +} + + +### COLOURS +propgroup colors = "Colours"; +propgroup colors +{ + property Color page_bgcolor + { + des = "Background color for the page"; + } + property Color page_fgcolor + { + des = "Text color for the page"; + } + property Color content_bgcolor + { + des = "Background color for box containing the main contents of the page"; + } + + property Color outer_table_bgcolor + { + des = "Background color of the outer table"; + } + + property Color entry_bgcolor + { + des = "Background color of the entries"; + } + property Color entry_fgcolor + { + des = "Text color of the entries"; + } + property Color border_color + { + des = "Border color of the content and header/footer boxes"; + } + + property Color entrytitle_bgcolor + { + des = "Background color of the subject, date and comment links"; + } + + property Color sidebar_header_bgcolor + { + des = "Background color for the headers in the sidebar"; + } + + property Color sidebar_fgcolor + { + des = "Text color for the sidebar"; + } + + property Color header_footer_bgcolor + { + des = "Background color of the header and footer"; + } + + property Color header_footer_fgcolor + { + des = "Text color for the header and footer"; + } + + property Color subject_fgcolor + { + des = "Text color for the subject of the entries"; + } + + property Color date_fgcolor + { + des = "Text color for the date of the entries"; + } + + set page_bgcolor = "#99AECE"; + set page_fgcolor = "#000000"; + set content_bgcolor = "#C2CDE0"; + set entry_bgcolor = "#D4DCE8"; + set entry_fgcolor = "#000000"; + set border_color = "#999999"; + set entrytitle_bgcolor = "#919BAD"; + set outer_table_bgcolor = "#A9B3C4"; + set sidebar_fgcolor = "#000000"; + set sidebar_header_bgcolor = "#919BAD"; + set header_footer_bgcolor = "#D4DCE8"; + set header_footer_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + set date_fgcolor = "#000000"; + + property Color link_color + { + des = "Link color for both visited and unvisited links"; + } + + property Color link_hover_color + { + des = "Link color on hover"; + } + + property Color comments_link_color + { + des = "Link color for visited and unvisited comment links"; + } + + property Color comments_link_hover + { + des = "Link color for comment links on hover"; + } + + property Color sidebar_link_color + { + des = "Link color for visited and unvisited sidebar links"; + } + + property Color sidebar_link_hover + { + des = "Link color for sidebar links on hover"; + } + + property Color header_footer_link_color + { + des = "Link color for visited and unvisited links for the header and footer"; + } + + property Color header_footer_link_hover + { + des = "Link color for comment links on hover for the header and footer"; + } + + + set link_color = "#5674B9"; + set link_hover_color = "#7AA1F8"; + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#B0B9C8"; + set sidebar_link_color = "#5674B9"; + set sidebar_link_hover = "#7AA1F8"; + set header_footer_link_color = "#5674B9"; + set header_footer_link_hover = "#7AA1F8"; +} + + +### TEXT +propgroup text = "Text"; +propgroup text +{ + property use text_meta_music; + property use text_meta_mood; + + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + + property use text_website_default_name; + property use text_view_recent; + property use text_view_friends; + property use text_view_userinfo; + property use text_view_archive; + set text_view_archive = "Archive"; + set text_view_friends = "Friends"; + set text_view_recent = "Recent Entries"; + set text_view_userinfo = "User Info"; + set text_website_default_name = "Website"; + + property use text_nosubject; + property string text_edit + { + des = "Text for an entry's edit link"; + } + property string text_memories + { + des = "Text to add an entry to the memories"; + } + property string text_previous_entry + { + des = "Text to link to the previous entry"; + } + property string text_next_entry + { + des = "Text to link to the next entry"; + } + set text_nosubject = "(no subject)"; + set text_permalink = "Link"; + set text_edit = "Edit"; + set text_memories = "Mem"; + set text_next_entry = "Next"; + set text_previous_entry = "Previous"; + + property use text_skiplinks_back; + property use text_skiplinks_forward; + set text_skiplinks_back = "go earlier"; + set text_skiplinks_forward = "go later"; +} + + + +### STYLESHEET OPTIONS +propgroup stylesheet = "Stylesheet"; +propgroup stylesheet +{ + property bool external_stylesheet + { + des = "Use linked stylesheet"; + } + property string external_stylesheet_url + { + des="External stylesheet URL"; + } + set external_stylesheet = true; +} + + + +# ----------------------------------- +# STYLESHEET +# ----------------------------------- + + +function css_font_family(string base, string fallback) : string +{ + var string return; + if ($base != "" or $fallback != "none") { + $return = $return + "font-family: "; + if ($base != "") { + $return = $return + "\"$base\""; + if ($fallback != "none") { + $return = $return + ", "; + } + } + if ($fallback != "none") { + $return = $return + $fallback; + } + } + return $return; +} + +function print_stylesheet () +{ + var string body_font_family = css_font_family($*main_font, $*main_font_fallback); + var string content_font_family = css_font_family($*content_font, $*content_font_fallback); + var string sidebar_font_family = css_font_family($*sidebar_font, $*sidebar_font_fallback); + var string header_footer_font_family = css_font_family($*header_footer_font, $*header_footer_font_fallback); + var string title_font_family = css_font_family($*title_font, $*title_font_fallback); + var string body_background = ""; + if ($*page_background_image != "") { + $body_background = """ + background-image: url("$*page_background_image"); + background-repeat: $*page_background_repeat; + background-position: $*page_background_position; + background-attachment: $*page_background_scrolling; + """; + } + + var string page_align = ""; + var string body_align = ""; + if ($*page_alignment == "left") + { + $page_align = "margin-left: 20px; margin-right: auto"; + } + if ($*page_alignment == "right") + { + $page_align = "margin-left: auto; margin-right: 20px"; + $body_align = "text-align: right"; + } + if ($*page_alignment == "center") + { + $page_align = "margin-left: auto; margin-right: auto"; + $body_align = "text-align: center"; + } + + var string maincontent_prop = ""; + var string sidebar_prop = ""; + var int float_margin = $*sidebar_width + 20; + if ($*show_sidebar and $*sidebar_position == "right") + { + $maincontent_prop = "margin-right: ${float_margin}px;"; + $sidebar_prop = "float: right;"; + + } + + if ($*show_sidebar and $*sidebar_position == "left") + { + $maincontent_prop = "margin-left: ${float_margin}px;"; + $sidebar_prop = "float: left;"; + } + if (not $*show_sidebar) + { + $maincontent_prop = ""; + } + + var string sidebar_pos = ""; + if ($*sidebar_position == "left") + { + $sidebar_pos = "clear: right"; + } + if ($*sidebar_position == "right") + { + $sidebar_pos = "clear: left"; + } + + print """ + + body { + background-color: $*page_bgcolor; + $body_background + $body_align; + color: $*page_fgcolor; + $body_font_family; + font-size: $*main_font_size$*font_unit; + margin: 20px 0 20px 0; + } + + a, a:link, a:visited { + color: $*link_color; + text-decoration: none; + } + + a:hover { + color: $*link_hover_color; + text-decoration: underline; + } + + p, td, blockquote { + font-size: $*content_font_size$*font_unit; + } + + code, kbd, pre, tt { + font-family: monospace; + } + + #content + { + width: $*journal_width$*journal_width_unit; + $page_align; + background-color: $*outer_table_bgcolor; + border-width: 1px; + border-style: solid; + border-color: $*border_color; + padding: 15px; + } + + #maincontent { + margin-top: 15px; + $content_font_family; + font-size: $*content_font_size$*font_unit; + background-color: $*content_bgcolor; + color: $*page_fgcolor; + border-style: solid; + border-color: $*border_color; + border-width: 1px; + $maincontent_prop + text-align: left; + } + + #sidebar { + + padding-top: 15px; + margin-top: 15px; + background-color: $*content_bgcolor; + border-color: $*border_color; + border-width: 1px; + border-style: solid; + font-size: $*sidebar_font_size$*font_unit; + $sidebar_font_family; + color: $*sidebar_fgcolor; + width: ${*sidebar_width}px; + $sidebar_prop + text-align: left; + } + + #header { + width: 100%; + padding: 10px 0px 20px 0px; + margin: 0px; + text-align: center; + $header_footer_font_family; + font-size: $*header_footer_font_size$*font_unit; + font-weight: bold; + letter-spacing: 2px; + border-style: solid; + border-color: $*border_color; + border-width: 1px; + background-color: $*header_footer_bgcolor; + color: $*header_footer_fgcolor; + } + + #footer { + width: 100%; + text-align: center; + $header_footer_font_family; + font-size: $*header_footer_font_size$*font_unit; + font-weight: bold; + letter-spacing: 1px; + background-color: $*header_footer_bgcolor; + color: $*header_footer_fgcolor; + border-color: $*border_color; + border-width: 1px; + border-style: solid; + z-index: 100; + clear: both; + } + + /* header -- links to views; title of journal; subtitle of journal */ + + div#header a, div#header a:link, div#header a:visited, div#footer a, div#footer a:link, div#footer a:visited { + color: $*header_footer_link_color; + } + + div#header a:hover, div#footer a:hover { + color: $*header_footer_link_hover; + text-decoration: none; + } + + ul.navheader + { + padding: 0px; + margin: 0px; + } + + ul.navheader li { + display: inline; + padding: 0 3px 0 3px; + } + + .title { + $title_font_family; + font-size: $*title_font_size$*font_unit; + font-weight: normal; + line-height: 200%; + top: 10px; + } + + .subtitle{ + $title_font_family; + font-size: $*subtitle_font_size$*font_unit; + font-weight: normal; + top: 10px; + } + + + /* sidebar */ + + div#sidebar a, div#sidebar a:link, div#sidebar a:visited{ + color: $*sidebar_link_color; + } + + div#sidebar a:hover { + color: $*sidebar_link_hover; + text-decoration: none; + } + + .defaultuserpic { + text-align: center; + } + + .sbarheader { + padding: 0px 5px 0px 5px; + } + + .sbarbody { + padding: 0px 5px 0px 5px; + } + + .sbarbody2 { + padding: 0 15px 0 15px; + } + + table.calendar { + margin-right: auto; + margin-left: auto; + } + + .sbarcalendar { + border-color: $*page_fgcolor; + border-width: 1px; + border-style: solid; + text-align: center; + $sidebar_font_family; + font-size: $*sidebar_font_size$*font_unit; + } + + .sbarcalendarposts { + border-color: $*page_fgcolor; + border-width: 1px; + border-style: solid; + background-color: $*entry_bgcolor; + text-align: center; + $sidebar_font_family; + font-size: $*sidebar_font_size$*font_unit; + } + + ul.sbarlist + { + padding-left: 0px; + margin-left: 0px; + list-style: none; + } + + li.sbaritem + { + padding-left: 15px; + list-style: none; + } + + li.sbartitle + { + padding-left: 15px; + list-style: none; + border-style: solid; + border-width: 1px; + border-color: $*border_color; + background-color: $*sidebar_header_bgcolor; + margin-bottom: 10px; + margin-top: 10px; + } + + + /* maincontent */ + + .subcontent { + } + + .entry { + margin: 0px 10px 10px 30px; + padding: 10px; + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + $content_font_family; + font-size: $*content_font_size$*font_unit; + text-align: left; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .entry ul li + { + padding-left: 5px; + margin-left: 15px; + } + + .entry ol li + { + padding-left: 5px; + margin-left: 15px; + } + + .userpic { + position: relative; + float: $*userpic_position; + background-color: $*entry_bgcolor; + padding: 5px; + margin: 10px; + z-index: 15; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .userpicfriends { + position: relative; + float: $*userpic_position; + padding: 5px; + margin: 10px; + text-align: center; + border-style: solid; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + $content_font_family; + font-size: $*content_font_size$*font_unit; + z-index: 15; + } + + .date { + line-height: 200%; + top: 5px; + color: $*date_fgcolor; + $content_font_family; + font-size: $*date_font_size$*font_unit; + } + + .subject { + font-weight: bold; + padding: 10px; + color: $*subject_fgcolor; + $content_font_family; + font-size: $*subject_font_size$*font_unit; + } + + .subject a, .subject a:link, .subject a:visited { + color: $*comments_link_color; + } + + .subject a:hover { + color: $*comments_link_hover; + } + + .datesubject { + background-color: $*entrytitle_bgcolor; + padding: 5px; + } + + .currents, .currentmood, .currentmusic { + $content_font_family; + font-size: $*content_font_size$*font_unit; + } + + .comments { + $content_font_family; + font-size: $*content_font_size$*font_unit; + text-align: right; + background-color: $*entrytitle_bgcolor; + padding: 0px 5px 0px 5px; + position: relative; + top: 15px; + } + + div.comments a, div.comments a:link, div.comments a:visited{ + color: $*comments_link_color; + } + + div.comments a:hover { + color: $*comments_link_hover; + text-decoration: none; + } + + + /* maincontent -- entry, reply pages */ + + .datesubjectcomment { + background-color: $*entrytitle_bgcolor; + padding: 5px; + margin-top: 20px; + } + + .userpiccomment { + position: relative; + border-width: 5px; + border-style: solid; + border-color: $*entry_bgcolor; + background-color: $*entry_bgcolor; + top: -30px; + left: 0px; + padding: 5px; + margin: 10px 10px -20px 10px; + z-index: 15; + float: $*userpic_position; + border-width: 1px; + border-color: $*entrytitle_bgcolor; + border-style: solid; + } + + .box { + border-style: solid; + border-width: 1px 0px 0px 0px; + border-color: $*border_color; + padding: 10px; + $sidebar_pos; + } + + input, textarea { + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + } + + textarea.textbox { + width: 100% !important; + } + + .reply { + position: relative; + margin: 20px 30px 10px 30px; + padding: 25px 10px 10px 10px; + text-align: left; + $content_font_family; + font-size: $*content_font_size$*font_unit; + line-height: 125%; + background-color: $*entry_bgcolor; + color: $*entry_fgcolor; + } + + .replytosubject { + font-weight: bold; + } + + + .commentreply { + position: relative; + margin: 10px; + font-size: $*content_font_size$*font_unit; + $content_font_family; + color: $*entry_fgcolor; + } + + .commentbox { + + border-color: $*border_color; + border-width: 1px; + border-style: solid; + padding: 10px; + margin: 10px; + background-color: $*entry_bgcolor; + } + + .datesubjectcomment a:link, .datesubjectcomment a:visited { + color: $*comments_link_color; + } + + .datesubjectcomment a:hover { + color: $*comments_link_hover; + } + + .commentboxpartial { + border-color: $*border_color; + border-width: 1px; + border-style: solid; + padding: 10px; + margin: 10px; + background-color: $*entry_bgcolor; + } + + .commentinfo { + background-color: $*entry_bgcolor; + margin-top: 10px; + width: 100%; + } + + + /* maincontent -- year/achive pages */ + + ul.year { + text-align: center; + padding-bottom: 40px; + } + + ul.year li { + display: inline; + } + + table.yeartable { + margin-left: auto; + margin-right: auto; + } + + table.yeartable td.yeardate, table.yeartable td.yearday { + border-width: 1px; + border-style: solid; + border-color: $*border_color; + } + + table.yeartable td.yearday { + background-color: $*entry_bgcolor; + text-align: center; + } + + td.yearmonth { + border-style: none; + } + + + /* footer */ + + ul.navfooter{ + padding: 0px; + margin: 0px; + } + + ul.navfooter li { + display: inline; + margin: 0 5px 0 5px; + } + + + .clearfoot { + clear: both; + } + + + /* misc */ + + .clear { + height: 15px; + } + + .skiplinks { + text-align: center; + } + + .headerimage { + /* for formatting header image */ + } + + .separator{ + /* for formatting separators between entries */ + height: 35px; + } + """; +} + +function print_custom_stylesheet() +{ + # override +} + +# ----------------------------------- +# SIDEBAR +# ----------------------------------- + + +function print_sidebar_box(string title, string body) +{ + + print safe """ +
              $title$body
            + """; + +} + + +function print_userpic () { + var Page p= get_page(); + var Image up_img = $p.journal.default_pic; + if (defined $up_img) { + """
            + $p.journal.name +
            """; + } +} + + + +function print_sidebar_calendar() +{ + var string calendar; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """
            """; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + $calendar = $calendar + ""; + var YearDay[] theDays = $w.days; + var int pre = $w.pre_empty; + if($pre > 0) { + $calendar = $calendar + """"""; + } + foreach var YearDay d ($theDays) { + if ($d.num_entries) { + $calendar = $calendar + """"""; + } else { + $calendar = $calendar + """"""; + } + } + $calendar = $calendar + "\n"; + } + $calendar = $calendar + "
             $d.day$d.day
            "; + } + $month = """
            • $month
            """; + if ($calendar != "") { + print $month; + print $calendar; + } +} + + +function print_sidebar_blurb () +{ + var string blurb_title = ""; + if ($*text_sidebar_blurb == "") + { + $blurb_title = ""; + } + else + { + $blurb_title = """
            • $*text_sidebar_blurb
            """; + } + var string blurb = ""; + $blurb = """
            $*sidebar_blurb
            """; + + if ($*show_blurb and ($*sidebar_blurb != "")) + { + print $blurb_title; + print $blurb; + } +} + +function print_sidebar_linklist() +{ + var Page p = get_page(); + if (size $p.linklist <= 0) + { + return; + } + elseif (not $*linklist_support) + { + return; + } + + var string list = ""; + foreach var UserLink l ($p.linklist) + { + if ($l.title) { + if ($l.is_heading) + { + $list = $list + """
          27. $l.title
          28. """; + } + else + { + $list = $list + """
          29. $l.title
          30. """; + } + } + else + { + $list = $list; + } + } + + var string list_title = ""; + if ($*text_sidebar_links != "") + { + $list_title = """
          31. $*text_sidebar_links
          32. """; + } + else + { + $list_title = ""; + } + print_sidebar_box($list_title, $list); +} + +function sidebar_order(string order) +{ + if ($order == "userpic" and $*show_default_userpic) + { + print_userpic(); + } + if ($order == "blurb" and $*show_blurb) + { + print_sidebar_blurb(); + } + if ($order == "linklist" and $*show_linklist) + { + print_sidebar_linklist(); + } + if ($order == "calendar" and $*show_calendar) + { + print_sidebar_calendar(); + } +} + +function print_sidebar() +{ + sidebar_order($*sidebar_order_1); + sidebar_order($*sidebar_order_2); + sidebar_order($*sidebar_order_3); + sidebar_order($*sidebar_order_4); +} + + + +# ----------------------------------- +# PAGE +# ----------------------------------- + +# Header +function Page::lay_print_header() +"Prints header" +{ + var Page page = get_page(); + var string title = $this->title(); + + print """ + +"""; +} + +# Footer +function Page::lay_print_footer() +{ + """ +
             
            + """; +} + + + +function Page::print () { + var Page page = get_page(); + var string title = $this->title(); + + """ + + + + $title"""; + $this->print_head(); + if ($*external_stylesheet and $*external_stylesheet_url !="") + { + println """"""; + } + elseif ($*external_stylesheet) + { + println """"""; + } + else + { + println """"; + } + + $this->print_custom_head(); + """ + + + +
            +
            + """; + $this->lay_print_header(); + + if ($*show_sidebar) + { + """ + + """; + } + """ +
            """; + $this->print_body(); + " +
            "; + $this->lay_print_footer(); + "
            + + "; +} + + + + +function Entry::print_linkbar() +{ + # Links (memories, edit, prev, next) + var Page p = get_page(); + var Link prev; + var Link edit; + var Link mem; + var Link next; + if ($p.view == "entry" or $p.view == "reply") + { + $prev = $this->get_link("nav_prev"); + $edit = $this->get_link("edit_entry"); + $mem = $this->get_link("mem_add"); + $next = $this->get_link("nav_next"); + """ +
             
            + +
             
            """; + } + +} + + +function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor) +{ + $e->print_linkbar(); + + + # Userpic + + var string userpic = ""; + if ($*show_entry_userpic) + { + if ($p.view == "friends" or $p.view == "entry") + { + if (defined $e.userpic) + { + $userpic = $userpic + """$e.poster.name"; + } + } + elseif ($p.journal_type == "C" and $p.view == "recent") + { + if (defined $e.userpic) + { + $userpic = $userpic + """$e.poster.name"""; + } + } + else + { + if (defined $e.userpic) + { + $userpic = $userpic + """
            $e.poster.name
            """; + } + } + } + print """ +
            + """; + if (($p.view == "recent" and $p.journal_type != "C" ) or $p.view == "day") + { + print """$userpic"""; + } + else + { + if ($p.view == "recent" and $p.journal_type == "C" ) + { + """
            """; + } + else + { + """
            """; + } + print """$userpic"""; + + + # Poster + + if ($p.view == "friends" or $p.view == "entry") + { + var UserLite linkto; + $linkto = $e.poster; + #print "$e.poster.username"; + """
            base_url() + "\">"; + "$linkto.username"; + } + elseif ($p.journal_type == "C" and $p.view == "recent") + { + var UserLite linkto; + $linkto = $e.poster; + #print "$e.poster.username"; + """
            base_url() + "\">"; + "$linkto.username"; + } + if (($p.view == "friends" or $p.view == "entry") and $e.poster.username != $e.journal.username) + { + var UserLite linkto; + $linkto = $e.journal; + """
            [base_url() + "\">"; + "$linkto.username]"; + } + if ($p.view == "recent" and $p.journal_type == "C") + { + print "
            "; + } + if ($p.view != "recent" and $p.view != "day") + { + print """
            """; + } + } + + + # Date, time, subject + + var string time = ""; + $time = $time + """ @ """; + $time = $time + $e.time->time_format("short"); + var string date = ""; + $date = $date + $e.time->date_format("long_day"); + """ +
            """; + print $e.time->date_format("%%dd%% %%month%% %%yyyy%%"); + "$time +
            "; + """ +
            """; + if ($e.security != "") + { + $e.security_icon->print(); + } + """ + $e.subject   +
            +
            + """; + + """ +
            +
            $e.text
            """; + + # Currents + + var string currents =""; + $e->print_metadata(); + + # Comments + + """ +
             
            +
            """; + if ($p.view != "entry" or $p.view != "reply") + { + $e.comments->print(); + } + elseif ($e.comments.enabled) + { + $e.comments->print_postlink(); + } + else + { + " "; + } + """ +
            +
            +
            + +
            +
             
            """; +} + + +function Page::print_entry(Entry e) { + print_entry($this, $e, null Color, null Color); +} + + +function FriendsPage::print_entry (Entry e) +{ + if ($*use_friends_colours) + { + var Friend f = $.friends{$e.journal.username}; + print_entry($this, $e, $f.bgcolor, $f.fgcolor); + } + else + { + print_entry($this, $e, $*entry_bgcolor, $*entry_fgcolor); + } +} + +function EntryPage::print_entry(Entry e) { + print_entry($this, $e, $*entry_bgcolor, $*entry_fgcolor); +} + +function Entry::print_metadata() { + if (size $.metadata) + { + print """
             
             
            +
            """; + var string currents; + foreach var string k ($.metadata) + { + var string text = $k; + var string val = $.metadata{$k}; + if ($k == "mood") + { + $text = $*text_meta_mood; + } + elseif ($k == "music") + { + $text = $*text_meta_music; + } + if ($k == "mood" and defined $.mood_icon) + { + var Image i = $.mood_icon; + $val = " $val"; + } + $currents = $currents + """
            $text: $val
            """; + } + $currents = $currents + "
            "; + println "$currents"; + } +} + + +function RecentPage::lay_print_footer() +{ + var string range = "most recent entries"; + var string sep; + var string back; + var string forward; + + if ($.nav.skip > 0) + { + $range = "$.nav.skip entries back"; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") + { + if ($.nav.backward_url != "") + { + $back = """
          33. $*text_skiplinks_back
          34. """; + } + if ($.nav.forward_url != "") + { + $forward = """
          35. $*text_skiplinks_forward
          36. """; + } + } + """ +
             
            + +
             
            + """; +} + +function RecentPage::print_body +{ + foreach var Entry e ($.entries) + { + $this->print_entry($e); + } +} + + +function EntryPage::print_body() +{ + $this->print_entry($.entry); + if ($.multiform_on and $.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + $this->print_multiform_start(); + } + if ($.entry.comments.enabled) + { + """ +
            + +
            """; + $.comment_pages->print(); + """ + ( Post a new comment ) +
            """; + $this->print_comments($.comments); + """ +
            """; + } + + if ($this.multiform_on and $.entry.comments.enabled and $.entry.comments.count > 0) + { + """ +
            """; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + """ +
            + ( Post a new comment )"""; + $.comment_pages->print(); + """ +
            +
            +
            """; + } +} + + + +# ----------------------------------- +# ENTRY +# ----------------------------------- + +function EntryPage::print_comments( Comment[] comments ) +{ + if ( size $comments == 0 ) + { + return; + } + + foreach var Comment c ( $comments ) + { + var int indent = ($c.depth - 1) * 30; + var string partialcomment = $c.full ? "" : "partial"; + var string margin = ""; + if ($*userpic_position == "left") + { + $margin = "right"; + } + else + { + $margin = "left"; + } + + """"""; + """
            \n"""; + if ( $c.full ) + { + $this->print_comment( $c ); + } + else + { + $this->print_comment_partial( $c ); + } + "
            "; + $this->print_comments( $c.replies ); + } +} + + +function EntryPage::print_comment (Comment comment) { + + var string subject = $comment.subject ? $comment.subject : $*text_nosubject; + var string date = $comment.time->date_format(); + var string poster = isnull $comment.poster ? $*text_poster_anonymous : $comment.poster->as_string(); + + #Comment Userpic + if (defined $comment.userpic and $*show_entry_userpic) + { + var int w = $comment.userpic.width; + var int h = $comment.userpic.height; + var string alt = $comment.metadata{"picture_keyword"}; + if ($*comment_userpic_style == "small") + { + $w = $w / 2; + $h = $h / 2; + } + if ($alt != "") + { + $alt = ": " + $alt; + } + """ +
            + $comment.poster.name$alt"""; + print """$poster on """; + print $comment.time->date_format("long") + " - " + $comment.time->time_format(); + } + else + { + print """ +
            $poster on """; + print $comment.time->date_format("long") + " - " + $comment.time->time_format(); + } + if (defined $comment.subject_icon or $comment.subject != "") + { + print "
            $comment.subject_icon $comment.subject" + "
            "; + } + if ($comment.metadata{"poster_ip"}) + { + print "
            " + $*text_comment_ipaddr + "(" + $comment.metadata{"poster_ip"} + ")" + "
            "; + } + "
            "; + + print """ +
            $comment.text
            \n"""; + var string alignlinks = ""; + if ($*userpic_position == "left") + { + $alignlinks = "right"; + } + else + { + $alignlinks = "left"; + } + "
            "; + + if ($comment.frozen) + { + "($*text_comment_frozen)"; + } + else + { + "($*text_comment_reply) "; + } + + if ($comment.parent_url != "") + { + "($*text_comment_parent) "; + } + + if ($comment.thread_url != "") + { + """($*text_comment_thread) """; + } + + "($*text_permalink)"; + + + """
            """; + if ($this.multiform_on) + { + """"""; + $comment->print_multiform_check(); + } + $comment->print_linkbar(); + + + "
            \n"; +} + +function EntryPage::print_comment_partial( Comment c ) +{ + var string subject = $c.subject ? $c.subject : $*text_nosubject; + var string date = $c.time->date_format("long") + " - " + $c.time->time_format(); + var string poster = isnull $c.poster ? $*text_poster_anonymous : $c.poster->as_string(); + + """$subject - $poster on $date"""; +} + +# ----------------------------------- +# DAY +# ----------------------------------- + + +function DayPage::print_body() { + """ +
             
            + +
             
            """; + if ($.has_entries) + { + foreach var Entry e ($.entries) + { + $this->print_entry($e); + } + } + else { + """

            $*text_noentries_day

            """; + } + """ +
             
            + +
             
            + """; +} + +function CommentInfo::print() { + if (not $.enabled) { return; } + if ($.count > 0 or $.screened) { + $this->print_readlink(); + " | "; + } + $this->print_postlink(); +} + + +# ----------------------------------- +# REPLY +# ----------------------------------- + + +function ReplyPage::print_body +{ + if (not $.entry.comments.enabled) + { + print " +

            $*text_reply_nocomments_header

            +

            $*text_reply_nocomments

            "; + return; + } + + $.entry->print_linkbar(); + + """
            """; + if (defined $.replyto.userpic) + { + print """
            $.replyto.userpic
            """; + } + + var string poster = isnull $.replyto.poster ? $*text_poster_anonymous : $.replyto.poster->as_string(); + var Page p; + print """ +
            +
            """; + print $.replyto.poster.name + " ("; + print $poster + ") "; + print "wrote"; + if ($.journal_type == "C") + { + print " in "; + print $.replyto.journal; + print " "; + } + print " "+lang_at_datetime($.replyto.time); + + print """ +
            +
            $.replyto.subject
            +
            +
            $.replyto.text
            +
            +
             
            +
            +
            ( Read comments )
            + Post a comment in response:
            """; + $.form->print(); + " +
            + "; +} + + + +# ----------------------------------- +# MONTH +# ----------------------------------- + +function MonthPage::print_body { + "
            +

            "; + $.redir->print_hiddens(); + if ($.prev_url != "") + { + "[<<<]\n"; + } + if (size $.months > 1) + { + "\n"; + } + if ($.next_url != "") + { + "\n[>>>]\n"; + } + """ +
            \n +

            +
            +
            """; + foreach var MonthDay d ($.days) + { + if ($d.has_entries) + { + "
            "; + print lang_ordinal($d.day); + "
            \n
            "; + $d->print_subjectlist(); + "
            \n"; + } + } + "
            +
            +
            "; +} + + + + +# ----------------------------------- +# YEAR +# ----------------------------------- + + +function YearPage::print_body +{ + $this->print_year_links(); + foreach var YearMonth m ($.months) + { + $this->print_month($m); + } +} + +function YearPage::print_year_links() { + """
              \n"""; + foreach var YearYear y ($.years) { + if ($y.displayed) { + """
            • $y.year
            • \n"""; + } else { + """
            • $y.year
            • \n"""; + } + } + """
            \n"""; +} + + +function YearPage::print_month(YearMonth m) { + if (not $m.has_entries) + { + return; + } + """\n + + + \n"""; + foreach var int d (weekdays()) { + """\n"; + } + "\n"; + foreach var YearWeek w ($m.weeks) { + $w->print(); + } + "
            """; + print $m->month_format(); + """$*text_view_month
            """+$*lang_dayname_short[$d]+"
            +


            "; +} + +function YearWeek::print() +{ + """\n"""; + if ($.pre_empty > 0) + { + """ \n"""; + } + foreach var YearDay d ($.days) + { + """\n"""; + """
            $d.day
            \n"""; + if ($d.num_entries > 0) + { + """\n"""; + } + else + { + """
             
            """; + } + """\n"""; + } + if ($.post_empty > 0) + { + """ \n"""; + } + ""; +} + + diff --git a/ljcom/bin/upgrading/s2layers/flexiblesquares/themes.s2 b/ljcom/bin/upgrading/s2layers/flexiblesquares/themes.s2 new file mode 100644 index 0000000..bd785cc --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/flexiblesquares/themes.s2 @@ -0,0 +1,615 @@ +#NEWLAYER: flexiblesquares/autumn +layerinfo "redist_uniq" = "flexiblesquares/autumn"; +layerinfo "type" = "theme"; +layerinfo "name" = "Autumn"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#351805"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#6a3106"; + + set entry_bgcolor = "#eee293"; + set entry_fgcolor = "#661f0c"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#8b4e1d"; + + set outer_table_bgcolor = "#c47b51"; + + set sidebar_header_bgcolor = "#8b4e1d"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#eee293"; + set header_footer_fgcolor = "#661f0c"; + + set link_color = "#608729"; + set link_hover_color = "#661f0c"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#c47b51"; + + set sidebar_link_color = "#608729"; + set sidebar_link_hover = "#eee293"; + + set header_footer_link_color = "#608729"; + set header_footer_link_hover = "#661f0c"; + +#NEWLAYER: flexiblesquares/blackwhite +layerinfo "redist_uniq" = "flexiblesquares/blackwhite"; +layerinfo "type" = "theme"; +layerinfo "name" = "Black and White and Red All Over"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#cccccc"; + set page_fgcolor = "#ff0000"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#cc0000"; + + set outer_table_bgcolor = "#666666"; + + set sidebar_header_bgcolor = "#cc0000"; + set sidebar_fgcolor = "#ffffff"; + + set header_footer_bgcolor = "#000000"; + set header_footer_fgcolor = "#cc0000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#999999"; + set link_hover_color = "#000000"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#999999"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#ffffff"; + set header_footer_link_hover = "#999999"; + +#NEWLAYER: flexiblesquares/freshpaint +layerinfo "redist_uniq" = "flexiblesquares/freshpaint"; +layerinfo "type" = "theme"; +layerinfo "name" = "Fresh Paint"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#993366"; + set page_fgcolor = "#006633"; + + set content_bgcolor = "#ff9933"; + + set entry_bgcolor = "#ffff99"; + set entry_fgcolor = "#000000"; + + set border_color = "#6699cc"; + + set entrytitle_bgcolor = "#ccff66"; + + set outer_table_bgcolor = "#330033"; + + set sidebar_header_bgcolor = "#ccff66"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffff99"; + set header_footer_fgcolor = "#006633"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#993333"; + set link_hover_color = "#330033"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#330033"; + + set sidebar_link_color = "#993333"; + set sidebar_link_hover = "#330033"; + + set header_footer_link_color = "#993333"; + set header_footer_link_hover = "#330033"; + +#NEWLAYER: flexiblesquares/nautical +layerinfo "redist_uniq" = "flexiblesquares/nautical"; +layerinfo "type" = "theme"; +layerinfo "name" = "Nautical"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#bad2f6"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#213659"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#d4e2f8"; + + set entrytitle_bgcolor = "#f0ef8e"; + + set outer_table_bgcolor = "#335288"; + + set sidebar_header_bgcolor = "#f0ef8e"; + set sidebar_fgcolor = "#7fa1d5"; + + set header_footer_bgcolor = "#213659"; + set header_footer_fgcolor = "#f0ef8e"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#7fa1d5"; + set link_hover_color = "#000000"; + + set comments_link_color = "#335288"; + set comments_link_hover = "#7fa1d5"; + + set sidebar_link_color = "#f0ef8e"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#7fa1d5"; + set header_footer_link_hover = "#ffffff"; + +#NEWLAYER: flexiblesquares/machine +layerinfo "redist_uniq" = "flexiblesquares/machine"; +layerinfo "type" = "theme"; +layerinfo "name" = "Machine"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#C1C1C1"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#000000"; + set entry_fgcolor = "#cbd3d8"; + + set border_color = "#7e8997"; + + set entrytitle_bgcolor = "#555a60"; + + set outer_table_bgcolor = "#000000"; + + set sidebar_header_bgcolor = "#555a60"; + set sidebar_fgcolor = "#C1C1C1"; + + set header_footer_bgcolor = "#000000"; + set header_footer_fgcolor = "#C1C1C1"; + + set date_fgcolor = "#C1C1C1"; + set subject_fgcolor = "#C1C1C1"; + + set link_color = "#8797a0"; + set link_hover_color = "#ffffff"; + + set comments_link_color = "#8797a0"; + set comments_link_hover = "#ffffff"; + + set sidebar_link_color = "#8797a0"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#8797a0"; + set header_footer_link_hover = "#ffffff"; + +#NEWLAYER: flexiblesquares/pastelspring +layerinfo "redist_uniq" = "flexiblesquares/pastelspring"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pastel Spring"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#ffffff"; + set page_fgcolor = "#993333"; + + set content_bgcolor = "#ffffcc"; + + set entry_bgcolor = "#ffffff"; + set entry_fgcolor = "#000000"; + + set border_color = "#ebccb1"; + + set entrytitle_bgcolor = "#ebccb1"; + + set outer_table_bgcolor = "#dae3b2"; + + set sidebar_header_bgcolor = "#ebccb1"; + set sidebar_fgcolor = "#993333"; + + set header_footer_bgcolor = "#ffffff"; + set header_footer_fgcolor = "#9FA876"; + + set date_fgcolor = "#993333"; + set subject_fgcolor = "#993333"; + + set link_color = "#9d7980"; + set link_hover_color = "#000000"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#ffffff"; + + set sidebar_link_color = "#9d7980"; + set sidebar_link_hover = "#9FA876"; + + set header_footer_link_color = "#9F3E3E"; + set header_footer_link_hover = "#ebccb1"; + +#NEWLAYER: flexiblesquares/pinkpunk +layerinfo "redist_uniq" = "flexiblesquares/pinkpunk"; +layerinfo "type" = "theme"; +layerinfo "name" = "Pink Punk"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#cc0066"; + + set content_bgcolor = "#000000"; + + set entry_bgcolor = "#ffccff"; + set entry_fgcolor = "#000000"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#ff6699"; + + set outer_table_bgcolor = "#cc0066"; + + + set sidebar_header_bgcolor = "#ff6699"; + set sidebar_fgcolor = "#ffccff"; + + set header_footer_bgcolor = "#ffccff"; + set header_footer_fgcolor = "#000000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#6666cc"; + set link_hover_color = "#ff6699"; + + set comments_link_color = "#ffccff"; + set comments_link_hover = "#6666cc"; + + set sidebar_link_color = "#6666cc"; + set sidebar_link_hover = "#ff6699"; + + set header_footer_link_color = "#6666cc"; + set header_footer_link_hover = "#ff6699"; + +#NEWLAYER: flexiblesquares/purpleperiwinkle +layerinfo "redist_uniq" = "flexiblesquares/purpleperiwinkle"; +layerinfo "type" = "theme"; +layerinfo "name" = "Purple Periwinkle"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#2f0b31"; + set page_fgcolor = "#2f0b31"; + + set content_bgcolor = "#671368"; + + set entry_bgcolor = "#f4a3e9"; + set entry_fgcolor = "#2f0b31"; + + set border_color = "#2f0b31"; + + set entrytitle_bgcolor = "#9488d8"; + + set outer_table_bgcolor = "#a13ea7"; + + set sidebar_header_bgcolor = "#9488d8"; + set sidebar_fgcolor = "#DADADA"; + + set header_footer_bgcolor = "#f4a3e9"; + set header_footer_fgcolor = "#2f0b31"; + + set date_fgcolor = "#2f0b31"; + set subject_fgcolor = "#2f0b31"; + + set link_color = "#dc039d"; + set link_hover_color = "#7e025a"; + + set comments_link_color = "#7e025a"; + set comments_link_hover = "#f4a3e9"; + + set sidebar_link_color = "#dc039d"; + set sidebar_link_hover = "#FFCCCC"; + + set header_footer_link_color = "#dc039d"; + set header_footer_link_hover = "#7e025a"; + +#NEWLAYER: flexiblesquares/grays +layerinfo "redist_uniq" = "flexiblesquares/grays"; +layerinfo "type" = "theme"; +layerinfo "name" = "Grays"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#111111"; + set page_fgcolor = "#ffffff"; + + set content_bgcolor = "#333333"; + + set entry_bgcolor = "#666666"; + set entry_fgcolor = "#ffffff"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#000000"; + + set outer_table_bgcolor = "#222222"; + + set sidebar_header_bgcolor = "#000000"; + set sidebar_fgcolor = "#ffffff"; + + set header_footer_bgcolor = "#666666"; + set header_footer_fgcolor = "#ffffff"; + + set date_fgcolor = "#ffffff"; + set subject_fgcolor = "#ffffff"; + + set link_color = "#ffcc33"; + set link_hover_color = "#ff9933"; + + set comments_link_color = "#ffcc33"; + set comments_link_hover = "#ff9933"; + + set sidebar_link_color = "#ffcc33"; + set sidebar_link_hover = "#ff9933"; + + set header_footer_link_color = "#ffcc33"; + set header_footer_link_hover = "#ff9933"; + +#NEWLAYER: flexiblesquares/lemongrapetang +layerinfo "redist_uniq" = "flexiblesquares/lemongrapetang"; +layerinfo "type" = "theme"; +layerinfo "name" = "Lemon Grapefruit Tangerine"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#ffff66"; + set page_fgcolor = "#993333"; + + set content_bgcolor = "#cc3333"; + + set entry_bgcolor = "#ffffcc"; + set entry_fgcolor = "#000000"; + + set border_color = "#ff9999"; + + set entrytitle_bgcolor = "#ff9933"; + + set outer_table_bgcolor = "#ffcc33"; + + set sidebar_header_bgcolor = "#ff9933"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffffcc"; + set header_footer_fgcolor = "#993333"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#ff9999"; + set link_hover_color = "#993333"; + + set comments_link_color = "#993333"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#ff9999"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#ff9999"; + set header_footer_link_hover = "#993333"; + +#NEWLAYER: flexiblesquares/tanteal +layerinfo "redist_uniq" = "flexiblesquares/tanteal"; +layerinfo "type" = "theme"; +layerinfo "name" = "Tan and Teal"; +layerinfo author_name = "sub_divided/cyrnelle"; + + set page_bgcolor = "#003333"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#cc9966"; + + set entry_bgcolor = "#ffffcc"; + set entry_fgcolor = "#000000"; + + set border_color = "#ffffff"; + + set entrytitle_bgcolor = "#996633"; + + set outer_table_bgcolor = "#ffcc99"; + + set sidebar_header_bgcolor = "#996633"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ffffcc"; + set header_footer_fgcolor = "#000000"; + + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + set link_color = "#993333"; + set link_hover_color = "#603913"; + + set comments_link_color = "#ffffcc"; + set comments_link_hover = "#000000"; + + set sidebar_link_color = "#993333"; + set sidebar_link_hover = "#000000"; + + set header_footer_link_color = "#993333"; + set header_footer_link_hover = "#000000"; + +#NEWLAYER: flexiblesquares/gentledawn +layerinfo "redist_uniq" = "flexiblesquares/gentledawn"; +layerinfo "type" = "theme"; +layerinfo "name" = "Gentle Dawn"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#747D86"; + set page_fgcolor = "#605734"; + + set content_bgcolor = "#FCCA7D"; + + set entry_bgcolor = "#FFD3B9"; + set entry_fgcolor = "#605734"; + + set border_color = "#908350"; + + set entrytitle_bgcolor = "#BAA969"; + + set outer_table_bgcolor = "#DABD63"; + + set sidebar_header_bgcolor = "#BAA969"; + set sidebar_fgcolor = "#605734"; + + set header_footer_bgcolor = "#FFD3B9"; + set header_footer_fgcolor = "#605734"; + + + set link_color = "#7E858D"; + set link_hover_color = "#C68DA5"; + + set comments_link_color = "#FFFFFF"; + set comments_link_hover = "#605734"; + + set sidebar_link_color = "#7E858D"; + set sidebar_link_hover = "#C68DA5"; + + set header_footer_link_color = "#7E858D"; + set header_footer_link_hover = "#C68DA5"; + +#NEWLAYER: flexiblesquares/icyblue +layerinfo "redist_uniq" = "flexiblesquares/icyblue"; +layerinfo "type" = "theme"; +layerinfo "name" = "Icy Blue"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#C6C2F8"; + set page_fgcolor = "#4F4D65"; + + set content_bgcolor = "#D3DCFC"; + + set entry_bgcolor = "#DDEFFF"; + set entry_fgcolor = "#4F4D65"; + + set border_color = "#FFFFFF"; + + set entrytitle_bgcolor = "#FFFFFF"; + set date_fgcolor = "#4F4D65"; + set subject_fgcolor = "#4F4D65"; + + + set outer_table_bgcolor = "#CED2FA"; + + set sidebar_header_bgcolor = "#FFFFFF"; + set sidebar_fgcolor = "#4F4D65"; + + set header_footer_bgcolor = "#FFFFFF"; + set header_footer_fgcolor = "#4F4D65"; + + + set link_color = "#5DABAA"; + set link_hover_color = "#779595"; + + set comments_link_color = "#5DABAA"; + set comments_link_hover = "#779595"; + + set sidebar_link_color = "#5DABAA"; + set sidebar_link_hover = "#779595"; + + set header_footer_link_color = "#5DABAA"; + set header_footer_link_hover = "#779595"; + +#NEWLAYER: flexiblesquares/chocolatemilkshake +layerinfo "redist_uniq" = "flexiblesquares/chocolatemilkshake"; +layerinfo "type" = "theme"; +layerinfo "name" = "Chocolate Milkshake"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#746E4A"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#BEA16D"; + + set entry_bgcolor = "#ECD6B2"; + set entry_fgcolor = "#000000"; + + set border_color = "#FFFFFF"; + + set entrytitle_bgcolor = "#867A52"; + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + + set outer_table_bgcolor = "#A18D5F"; + + set sidebar_header_bgcolor = "#867A52"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#ECD6B2"; + set header_footer_fgcolor = "#000000"; + + + set link_color = "#867A52"; + set link_hover_color = "#790000"; + + set comments_link_color = "#ECD6B2"; + set comments_link_hover = "#790000"; + + set sidebar_link_color = "#790000"; + set sidebar_link_hover = "#ECD6B2"; + + set header_footer_link_color = "#867A52"; + set header_footer_link_hover = "#790000"; + + + +#NEWLAYER: flexiblesquares/eclipse +layerinfo "redist_uniq" = "flexiblesquares/eclipse"; +layerinfo "type" = "theme"; +layerinfo "name" = "Eclipse"; +layerinfo author_name = "Yati Mansor"; + + set page_bgcolor = "#000000"; + set page_fgcolor = "#000000"; + + set content_bgcolor = "#EEA802"; + + set entry_bgcolor = "#FBE274"; + set entry_fgcolor = "#000000"; + + set border_color = "#000000"; + + set entrytitle_bgcolor = "#CA5D00"; + set date_fgcolor = "#000000"; + set subject_fgcolor = "#000000"; + + + set outer_table_bgcolor = "#921800"; + + set sidebar_header_bgcolor = "#CA5D00"; + set sidebar_fgcolor = "#000000"; + + set header_footer_bgcolor = "#EEA802"; + set header_footer_fgcolor = "#000000"; + + + set link_color = "#790000"; + set link_hover_color = "#000000"; + + set comments_link_color = "#ECD6B2"; + set comments_link_hover = "#790000"; + + set sidebar_link_color = "#790000"; + set sidebar_link_hover = "#ffffff"; + + set header_footer_link_color = "#790000"; + set header_footer_link_hover = "#ffffff"; diff --git a/ljcom/bin/upgrading/s2layers/nebula/layout.s2 b/ljcom/bin/upgrading/s2layers/nebula/layout.s2 new file mode 100644 index 0000000..48047c4 --- /dev/null +++ b/ljcom/bin/upgrading/s2layers/nebula/layout.s2 @@ -0,0 +1,1690 @@ +# -*-s2-*- + + +## -- n e b u l a ! -- ###################################################### + +layerinfo type = "layout"; +layerinfo name = "Nebula"; +layerinfo redist_uniq = "nebula/layout"; + +layerinfo author_name = "jc"; +layerinfo author_email = "jc@livejournal.com"; +layerinfo des = "A simple but incredibly flexible design with sidebar, that can look as simple or as complicated as you like."; +layerinfo lang = "en"; + + +## -- p r o p e r t i e s -- ################################################ + +propgroup colors = "Colors"; +propgroup colors { + property Color col_weaker_fg { + des = "Default text color for the page"; + note = "This only really affects the calendar strip, although it is used elsewhere. Text color on content areas is more important."; + } + property Color col_weak_fg { + des = "Text color on content areas"; + } + property Color col_stronger_fg { + des = "Text color on headers"; + } + property Color col_strong_fg { + des = "Text color on menus"; + } + property Color col_neutral_fg { + des = "Text color on titles"; + } + + property Color col_cmtbarone_fg { + des = "Text color on comment bars"; + } + property Color col_cmtbartwo_fg { + des = "Text color on alternating comment bars"; + } + property Color col_cmtbarscrn_fg { + des = "Text color for screened comments"; + } + + + property Color col_entry_link { + des = "Link color in entries"; + } + property Color col_entry_vlink { + des = "Visited link color in entries"; + } + + property Color col_sidebar_link { + des = "Link color in sidebar"; + } + property Color col_sidebar_vlink { + des = "Visited link color in sidebar"; + } + + property string img_delete { noui = 1; } + property string img_screen { noui = 1; } + property string img_unscreen { noui = 1; } + property string img_freeze { noui = 1; } + property string img_unfreeze { noui = 1; } +} + +set col_weaker_fg = "#000000"; +set col_weak_fg = "#ffffff"; +set col_neutral_fg = "#550301"; +set col_strong_fg = "#5b4b26"; +set col_stronger_fg = "#5b4b26"; +set col_cmtbarone_fg = "#ffffff"; +set col_cmtbartwo_fg = "#ffffff"; +set col_cmtbarscrn_fg = "#ffffff"; +set col_sidebar_link = "#000000"; +set col_entry_link = "#000000"; +set col_entry_vlink = "#000000"; +set col_sidebar_vlink = "#000000"; + +propgroup backgrounds = "Backgrounds"; +propgroup backgrounds { + property Color col_weaker_bg { + des = "Default background color for the page"; + } + property Color col_weak_bg { + des = "Background color on content areas"; + } + property Color col_stronger_bg { + des = "Background color on headers"; + } + property Color col_strong_bg { + des = "Background color on menus"; + } + property Color col_neutral_bg { + des = "Background color on titles"; + } + property Color col_entry_bg { + des = "Background color on entries"; + } + property Color col_border { + des = "Color for content area borders"; + note = "Content areas affected include sidebar boxes and the mini calendar."; + } + property string background_image + { + des = "Background image"; + note = "URL to an image to be used for the page background (leave blank for none). Page texture won't be used if an image is defined."; + } + property string background_repeat { + des = "Background image repeat"; + note = "This does not affect whether your background scrolls with the page. That option is coming up next."; + values = "repeat|Repeat|no-repeat|Don't repeat|repeat-x|Repeat across only|repeat-y|Repeat down only"; + } + property string background_attachment { + des = "Should the background image scroll with the page?"; + values = "scroll|Yes|fixed|No"; + } + property string background_position { + des = "Background image position"; + note = "Does not apply if background image is repeating in both directions."; + values = "center|Center|center left|Center-left|center right|Center-right|top|Top|top left|Top-left|top right|Top-right|bottom|Bottom|bottom left|Bottom-left|bottom right|Bottom-right|left|Left|right|Right"; + } + set background_image = ""; + set background_repeat = "repeat"; + set background_position = "center"; + set background_attachment = "scroll"; + + property string pres_txtr_bg { + des = "Texture to use for page background"; + note = "Won't be used if a background image is defined above."; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property string pres_txtr_h { + des = "Texture to use for page header"; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property string pres_txtr_c { + des = "Texture to use for main content areas"; + values = "none|None|brushed_metal.png|Brushed Metal|burlap.png|Burlap|camouflage.png|Camouflage|canvas.png|Canvas|chalk.png|Chalk|cork.png|Cork|fibers.png|Fibers|floral.png|Floral|ice.png|Ice|manila.png|Manila|marble.png|Marble|paper.png|Paper|ridge.png|Ridge|rough.png|Rough|stucco.png|Stucco|terracotta.png|Terracotta|type.png|Type|wavy.png|Wavy"; + } + property Color col_cmtbarone_bg { + des = "Background color for comment bars"; + } + property Color col_cmtbartwo_bg { + des = "Background color for alternating comment bars"; + } + property Color col_cmtbarscrn_bg { + des = "Background color for screened comment bars"; + } +} + + +set col_weaker_bg = "#effe8f"; +set col_weak_bg = "#5b4b26"; +set col_neutral_bg = "#000000"; +set col_strong_bg = "#fbe46a"; +set col_stronger_bg = "#fbe46a"; +set col_cmtbarone_bg = "#e2c956"; +set col_cmtbartwo_bg = "#afb13e"; +set col_cmtbarscrn_bg = "#fcda3e"; +set col_entry_bg = "#977e3b"; +set col_border = "#000000"; + +propgroup fonts { + property string main_font { + des = "Preferred Font"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string main_font_fallback { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + + property string header_font + { + des = "Font for the top header box"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string header_font_fallback + { + des = "Alternative font style"; + values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default"; + note = "This general style will serve as a fallback if your preferred font is unavailable."; + } + property string header_font_size { noui = 1; } + + property string content_font + { + des = "Font for the content boxes"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string content_font_fallback { noui = 1; } + + property string subheading_font + { + des = "Font for subheadings"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string subheading_font_fallback { noui = 1; } + + property string entryheading_font + { + des = "Font for entry headings"; + maxlength = 25; + size = 10; + example = "Arial"; + note = "Leave blank for your browser's default font"; + } + property string entryheading_font_fallback { noui = 1; } +} + +set main_font = "Georgia"; +set main_font_fallback = "serif"; +set header_font = "Georgia"; +set header_font_fallback = "serif"; +set header_font_size = "2em"; +set content_font = "Georgia"; +set content_font_fallback = "sans-serif"; +set subheading_font = "Arial"; +set subheading_font_fallback = "sans-serif"; +set entryheading_font = "Georgia"; +set entryheading_font_fallback = "sans-serif"; + +propgroup pres = "Presentation"; +propgroup pres { + property int summary_items { + des = "Summary Items"; + note="Maximum number of items in the Page Summary list. Set to 0 to turn off the Page Summary. Set to 100 to show all available items."; + } + + property bool pres_show_entry_list { + des = "Show links to entries on page?"; + } + property string pres_page_width { + des = "Page Width"; + note = "The width of the total page content, including the sidebar."; + values = "90%|90%|80%|80%|70%|70%|60%|60%|50%|50%|40%|40%"; + } + property string pres_page_align { + des = "Page Alignment"; + values = "left|Left|center|Center|right|Right"; + } + property string pres_sidebar_width { + des = "Sidebar Width"; + note = "How much of the page width is taken up by the sidebar."; + values = "30%|30%|25%|25%|20%|20%|15%|15%"; + } + property string pres_sidebar_align { + des = "Which side of the page should the sidebar show up on?"; + values = "left|Left|right|Right"; + } + property string header_image { + des = "URL of image to be used as page header"; + example = "http://example.com/your_image.jpg"; + } + property bool pres_show_cal { + des = "Show calendar strip on journal pages?"; + } + property bool show_entry_userpic { + des = "Show entry-specific userpic next to each entry?"; + } + property bool pres_use_gradients { + des = "Use gradients when displaying entry headers and sidebar boxes?"; + } + property use comment_userpic_style; + property use use_shared_pic; + property use page_recent_items; + property use page_friends_items; +} +set show_entry_userpic = true; +set pres_show_cal = true; +set pres_sidebar_align = "left"; +set pres_show_entry_list = true; +set pres_page_width = "80%"; +set pres_sidebar_width = "20%"; +set pres_txtr_bg = "none"; +set pres_txtr_h = "none"; +set pres_txtr_c = "none"; +set pres_page_align = "center"; +set summary_items = 100; +set pres_use_gradients = true; + +propgroup text { + property string text_date_format { + des = "Date format:"; + example = "%%yyyy%%.%%mm%%.%%dd%%"; + } + property string text_time_format { + des = "Time format:"; + example = "%%HH%%:%%min%%"; + } + property string text_navigation { + des = "Navigation menu title"; + } + property string text_navigation_extra { + des = "Page-specific navigation menu title"; + example = "This page"; + } + property string page_summary_title { + des = "Page Summary menu title"; + } + property string text_entry_plural { + des = "Text to describe entries in month view"; + format = "plurals"; + example = "1 entry // # entries"; + } + + property use text_nosubject; + property use text_meta_mood; + property use text_meta_music; + property use text_noentries_day; + property use text_max_comments; + property string text_comment_from { + des = "Text to indicate when comment was posted"; + example = "at"; + maxlength = "20"; + } + property use text_comment_date; + property use text_comment_ipaddr; + property use text_comment_frozen; + property use text_reply_nocomments_header; + property use text_reply_nocomments; +} +propgroup linktext = "Link text"; +propgroup linktext { + property string text_view_memories { + des = "View memories"; + } + property string text_add_mem { + des = "Add to memories"; + } + property string text_edit_entry { + des = "Edit entry"; + } + property string text_edit_tags { + des = "Edit tags"; + } + property use text_view_recent; + property use text_view_friends; + property use text_view_archive; + property use text_view_userinfo; + property use text_permalink; + property use text_post_comment; + property use text_read_comments; + property use text_post_comment_friends; + property use text_read_comments_friends; + property use text_reply_back; + property use text_comment_reply; + property use text_comment_parent; + property use text_comment_thread; + property string text_link_separator { + des = "Text or image to separate links with"; + note = "If you use a URL of an image (starting with 'http://'), Nebula will use the image as a separator. It helps to use a small image for this purpose, and your image might break if the URL contains any spaces."; + example = "&nbsp;|&nbsp; or http://www.example.com/your_image.jpg"; + } + +} +set text_date_format = "%%yyyy%%.%%mm%%.%%dd%%"; +set text_time_format = "%%HH%%:%%min%%"; +set text_view_memories = "Memories"; +set text_add_mem = "Add to Memories"; +set page_summary_title = "Summary"; +set text_entry_plural = "1 entry // # entries"; +set text_edit_entry = "Edit"; +set text_edit_tags = "Tags"; +set tags_aware = true; +set text_link_separator = "  "; +set text_navigation = "Navigation"; +set text_navigation_extra = "This page"; +set text_comment_from = ""; +set text_comment_date = "at"; + + +## -- p r o p e r t y h a n d l e r s -- ################################## + +function prop_init () { + var int entry_lightness = $*col_weaker_bg->lightness(); + var Color col_entry_bg_tint = $entry_lightness > 120 ? $*col_weaker_bg->lighter(): $*col_weaker_fg; + + # these shouldn't be limited to a The Boxer subfolder + $*img_delete = palimg_tint("boxer/delete.gif", $col_entry_bg_tint); + $*img_screen = palimg_tint("boxer/screen.gif", $col_entry_bg_tint); + $*img_unscreen = palimg_tint("boxer/unscreen.gif", $col_entry_bg_tint); + $*img_freeze = palimg_tint("boxer/freeze.gif", $col_entry_bg_tint); + $*img_unfreeze = palimg_tint("boxer/unfreeze.gif", $col_entry_bg_tint); + + # textures! lovely textures. + if ($*pres_txtr_bg != "none") { $*pres_txtr_bg = palimg_tint("textures/$*pres_txtr_bg", $*col_stronger_fg, $*col_weaker_bg); } + + var Color hfg = "#ffffff"; + if ($*pres_txtr_h != "none") { $*pres_txtr_h = palimg_tint("textures/$*pres_txtr_h", $hfg, $*col_stronger_bg); } + + if ($*pres_txtr_c != "none") { $*pres_txtr_c = palimg_tint("textures/$*pres_txtr_c", $*col_weaker_fg, $*col_weak_bg); } + +} + + +## -- s t y l e s h e e t f u n c t i o n s -- ############################ + +function appended_to_stylesheet() { + # This function intentionally left blank. Override in user layer. +} + +function print_stylesheet () { + + var string pres_sidebar_boxbg; + var string pres_minical_boxbg; + var string pres_page_margins; + + # figure out the shade applied to weekends on the MiniCal + var int minical_lightness = $*col_strong_bg->lightness(); + var Color col_minical_weekend = $minical_lightness > 120 ? $*col_strong_bg->darker(50) : $*col_strong_bg->lighter(50); + + # figuring out the widths and margins the ghetto way + var int width_page = int($*pres_page_width); + var int width_sidebar = int($*pres_sidebar_width); + var int width_content = $width_page - $width_sidebar - 5; + var int width_margin = 100 - $width_page; + + if ($*pres_page_align == "center") { + var string str_width_margin = string($width_margin / 2); + $pres_page_margins = "margin-left: $str_width_margin%;"; + } else { + var string str_width_margin = string($width_margin); + $pres_page_margins = "margin-$*pres_page_align: $str_width_margin%;"; + } + var string pres_content_width = string($width_content) + "%"; + + # death to IE + var string pres_sidebar_width_ie = string($width_sidebar - 3) + "%"; + var string pres_content_width_ie = string($width_content - 3) + "%"; + + # another ghetto method to align the sidebar properly + var string pres_sidebar_opp = $*pres_sidebar_align == "left" ? "right" : "left"; + + + # gradients! lovely gradients. + if ($*pres_use_gradients) { + var Color col_black = "#000000"; + var Color col_white = "#ffffff"; + # Let's determine some colours first + var int tmp_boxborder_lightness = $*col_border->lightness(); + var Color tmp_boxborder_avg = $tmp_boxborder_lightness > 120 ? $*col_border->darker(70) : $*col_border->lighter(70); + var string tmp_gstart = $tmp_boxborder_avg.as_string->substr(1, 6); + var string tmp_gend = $*col_strong_bg.as_string->substr(1, 6); + + # Now to generate the gradients + $pres_sidebar_boxbg = "background: url($*PALIMGROOT/shadow/t.gif/pt$tmp_gstart$tmp_gend) repeat-x;"; + $pres_minical_boxbg = "background: $*col_strong_bg url($*PALIMGROOT/shadow/b.gif/pt$tmp_gstart$tmp_gend) repeat-x scroll bottom;"; + } else { + $pres_minical_boxbg = "background-color: $*col_strong_bg;"; + } + + +""" + body { + margin: 0; + padding: 0; + font-family: $*main_font, $*main_font_fallback; + font-size: 0.75em; +"""; + if (clean_url($*background_image) != "") { + """ background-image: url('$*background_image'); + background-position: $*background_position; + background-repeat: $*background_repeat; + background-attachment: $*background_attachment; + """; + } elseif ($*pres_txtr_bg != "none") { """ background: url($*pres_txtr_bg);"""; } +""" + background-color: $*col_weaker_bg; + color: $*col_weaker_fg; + } + #mainContainer { + width: $*pres_page_width; + $pres_page_margins + min-width: 300px; + } + #header { + padding: 0 1em; + min-height: 110px; + margin: 0 0 10px 0; +"""; + if ($*pres_txtr_h != "none") { """ background: url($*pres_txtr_h);"""; } +""" + background-color: $*col_stronger_bg; + color: $*col_stronger_fg; + } + #header h1 { + margin: 0 0 -10px 0; + padding: 15px 0; + } + #header a { + font-family: $*header_font, $*header_font_fallback; + font-size: $*header_font_size; + text-decoration: none; + color: $*col_stronger_fg; + } + #header p { + color: $*col_neutral_fg; + font-size: 18px; + font-style: italic; + margin: 0 0 0 20px; + } + #content { + float: $pres_sidebar_opp; + background-color: $*col_weak_bg; + color: $*col_weak_fg; + padding: 5px; + margin: 20px 1% 20px 1%; +"""; + if ($*pres_txtr_c != "none") { """ background: url($*pres_txtr_c);"""; } +""" + width: $pres_content_width; + voice-family: "\"}\""; + voice-family:inherit; + width: $pres_content_width_ie; + } + html>body #content { + width: $pres_content_width_ie; + } + #content p { + margin-top: 0px; + margin-bottom: 0px; + padding: 8px; + } + #sideBar { + float: $*pres_sidebar_align; + padding: 5px; + margin: 20px 1% 20px 1%; + background-color: $*col_weak_bg; + color: $*col_weak_fg; +"""; + if ($*pres_txtr_c != "none") { """background: url($*pres_txtr_c);"""; } +""" + width: $*pres_sidebar_width; + voice-family: "\"}\""; + voice-family:inherit; + width: $pres_sidebar_width_ie; + } + html>body #sideBar { + width: $pres_sidebar_width_ie; + } + #sideBarHeader { + min-height: 100px; + background-color: $*col_stronger_bg; + color: $*col_stronger_fg; +"""; + if ($*pres_txtr_h != "none") { """background: url($*pres_txtr_h);"""; } +""" + vertical-align: bottom; + margin-bottom: 10px; + } + #sideBar h4 { + color: $*col_neutral_fg; + text-transform: uppercase; + font-weight: normal; + font-family: $*subheading_font, $*subheading_font_fallback; + display: block; + text-align: center; + padding: 5px; + padding-bottom: 0; + $pres_sidebar_boxbg + } + #sideBar ul { + margin: 0 0 1em 1em; + padding: 0; + list-style-type: none; + } + .sideBarBox { + border: 2px solid $*col_border; + margin-bottom: 5px; + background-color: $*col_strong_bg; + color: $*col_strong_fg; + } + .sideBarBox a, .sideBarBox a:active { + color: $*col_sidebar_link; + } + .sideBarBox a:visited { + color: $*col_sidebar_vlink; + } + .sideBarBox h5 { + font-family: $*subheading_font, $*subheading_font_fallback; + margin: 10px 0 0 0; + } + .sideBarUpi { + margin: 0; + padding: 2px; + } + + .entry { + padding: 5px; + background-color: $*col_entry_bg; + font-family: $*content_font, $*content_font_fallback; + } + .entry a { + color: $*col_entry_link; + } + .entry a:visited { + color: $*col_entry_vlink; + } + .entry h3 { + font-family: $*entryheading_font, $*entryheading_font_fallback; + font-size: 1.5em; + padding: 3px; + margin: 10px 0; + } + .entryBar { + clear: both; + overflow: auto; + font-size: 0.9em; + } + .entryText { + margin-top: 5px; + margin-bottom: 5px; + } + .entryFooter { + padding-top: 1em; + } + .commentsInfo { + float: right; + } + form#postform textarea { + width: 100%; max-width: 99%; + } + form#postform input { + max-width: 100%; + } + + .commentBoxOne { + border: 5px solid $*col_cmtbarone_bg; + } + .commentBoxTwo { + border: 5px solid $*col_cmtbartwo_bg; + } + .commentBoxScreened { + border: 5px solid $*col_cmtbarscrn_bg; + } + .commentBoxOne .commentInfo { + background-color: $*col_cmtbarone_bg; + color: $*col_cmtbarone_fg; + } + .commentBoxTwo .commentInfo { + background-color: $*col_cmtbartwo_bg; + color: $*col_cmtbartwo_fg; + } + .commentBoxScreened .commentInfo { + background-color: $*col_cmtbarscrn_bg; + color: $*col_cmtbarscrn_fg; + } + .commentBoxOne, .commentBoxTwo, .commentBoxScreened { + background-color: $*col_weak_bg; + color: $*col_weak_fg; + border-right: none; + border-bottom: none; + width: 99%; + } + .commentBoxOne a, .commentBoxTwo a, .commentBoxScreened a { + color: $*col_entry_link; + } + .commentBoxOne a:visited, .commentBoxTwo a:visited, .commentBoxScreened a:visited { + color: $*col_entry_vlink; + } + .commentUpi { + float: left; + margin-right: 10px; + margin-bottom: 10px; + } + .commentUpi img { + border: 0; + } + .commentInfo { + width: 100%; + vertical-align: bottom; + padding-botttom: 5px; + background-color: #ccf; + } + .commentButs { + vertical-align: bottom; + text-align: right; + } + .commentText { + padding-top: 5px; + padding-left: 5px; + } + .commentLinks { + clear: both; + margin-left: 5px; + } + + #footer { + float: left; + width: """+$pres_content_width+"""px; + font-size: 0.8em; + margin-top: 10px; + margin-bottom: 10px; + } + + h2, h3, h4 { + margin-top: 0; + } + a { + color: $*col_entry_link; + text-decoration: none; + } + a:hover { + text-decoration: underline; + } + a:visited { + color: $*col_entry_vlink; + } + .userpic { + float: right; + margin-left: 5px; + margin-bottom: 5px; + } + div.entrysub h3 { + margin: 0; + } + div.MiniCalContainer { + border: 2px solid $*col_border; + width: 98%; + height: 3em; + overflow: auto; + margin-top: 10px; + margin-left: 1%; + $pres_minical_boxbg + } + .MiniCalDayPosts { + font-weight: bold; + } + td.MiniCalWeekend { + background-color: $col_minical_weekend; + } + td.MiniCalDay, td.MiniCalDayPosts { + font-family: Trebuchet, Verdana, sans-serif; + font-size: 0.95em; + color: $*col_strong_fg; + } + .MiniCalDay a, .MiniCalDay a:active, .MiniCalDayPosts a, .MiniCalDayPosts a:active { + color: $*col_sidebar_link; + } + .MiniCalDay a:visited, .MiniCalDayPosts a:visited { + color: $*col_sidebar_vlink; + } + .monthWrapper { + display: table; + border: 1px solid black; + width: 100%; + } + .monthRow { + display: table-row; + border: 1px solid black; + } + .monthCell, .monthDay { + display: table-cell; + border: 1px solid black; + padding: 3px; + } + .monthDay { + font-family: $*subheading_font, $*subheading_font_fallback; + font-size: 2em; + text-align: right; + } + #cal a { + text-decoration: none; + color: $*col_entry_link; + } + .calrow { + clear: both; + font-family: Arial, sans-serif; + } + + .calempty { + width: 24px; + font-size: 11px; + margin: 1px; + float: left; + } + .calactitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + background-color: white; + border-right: 1px solid black; + border-bottom: 1px solid black; + } + .calDayEntries { + font-size: 1.5em; + font-weight: bold; + } + .calDay, .calDayEntries, .bigday { + font-family: $*subheading_font, $*subheading_font_fallback; + text-align: center; + vertical-align: middle; + } + .bigday { + font-weight: bold; + } + .cal td { + padding: 3px; + } + .calinitem { + float: left; + margin: 1px; + width: 23px; + font-size: 11px; + text-align: center; + border-right: 1px solid black; + border-bottom: 1px solid black; + } + +"""; + appended_to_stylesheet(); +} + + +## -- i m a g e l i n k s e p a r a t o r -- ############################ + +function separator() : string { + # Would do this in prop_init, except you can't use HTML in + # $* variables. Poo. + if ($*text_link_separator->starts_with("http://")) { + return " \" "; + } else { + return $*text_link_separator; + } +} + +## -- p r i n t l i n k l i s t -- ######################################## + +function linklist() : string { + var string return = ""; + var Page p = get_page(); + if (size $p.linklist <= 0) { + return ""; + } + var bool section_open = false; + $return = $return + "
            \n"; + var int count = 0; + foreach var UserLink l ($p.linklist) { + $count = $count + 1; + if ($l.title) { + if ($l.is_heading) { + if ($section_open) { + $return = $return + "
        \n
    \n"; + } + $return = $return + """
    \n

    $l.title

    \n
      \n"""; + $section_open = true; + } else { + if ($count == 1) { + $return = $return + """
      \n

       

      \n
        \n"""; + } + $return = $return + """
      • $l.title
      • \n"""; + } + } + } + $return = $return + "
      \n
      \n"; + return $return; +} + + +## -- p a g e s u m m a r i e s -- ######################################## + +function num_comments_in_thread (Comment[] comments) : int { + var int total = 0; + foreach var Comment c ($comments) { + $total = $total + 1; + if (size $c.replies > 0) { + $total = $total + num_comments_in_thread($c.replies); + } + } + return $total; +} + +function Page::lay_entry_nav (Entry e) : string { + + var string date = $e.time->date_format($*text_date_format); + var string time = $e.time->time_format($*text_time_format); + var string line; + var string subject = ($e.subject != "") ? " $e.subject" : """ $*text_nosubject"""; + var string j = ($.view == "friends" and $e.journal.username != $e.poster.username) ? " in $e.journal: " : ""; + var string item = ($.view == "friends" or $e.journal.username != $e.poster.username) ? "
      $date @ $time
      " + $e.poster->as_string() + "$j " : "
      $date @ $time
      "; + $line = """
    • $item $subject
    • \n"""; + + return $line; +} + +function Page::lay_print_summary () { } + +function RecentPage::lay_print_summary () { + var int count = $*summary_items; + if ($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + if($count > 0) { + $text = $text + $this->lay_entry_nav($e); + } + $count = $count - 1; + } + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + print $text; + } +} + +function EntryPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + $text = $this->lay_entry_nav($.entry); + $count = $count - 1; + + foreach var Comment c ($.comments) { + if($count > 0) { + var string subject = ($c.subject != "") ? $c.subject : """$*text_nosubject """; + $text = $text + """
    • $c.poster: $subject"""; + var int num = num_comments_in_thread($c.replies); + if($num > 0) { + $text = $text + " [+" + string($num) + "] "; + } + $text = $text + """
    • \n"""; + } + $count = $count - 1; + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + if($count != ($*summary_items - 1)) { + print $text; + } + } +} + +function DayPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string text; + foreach var Entry e ($.entries) { + $text = $text + $this->lay_entry_nav($e); + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • \n"""; + } + print $text; + } +} + + +function MonthPage::lay_print_summary () { + var int count = $*summary_items; + if($count == 0) { return; } + + var string entrytext = "1 entry // # entries"; + var string text; + foreach var MonthDay d ($.days) { + if($count > 0) { + var string day = lang_ordinal($d.day); + if ($d.has_entries) { + var string entries = get_plural_phrase($d.num_entries, "text_entry_plural"); + $text = $text + """
    • $day [$entries]
    • \n"""; + } + } + } + + if($text != "") { + if($count < 0) { + $count = $count * -1; + $text = $text + """
    • +$count more
    • """; + } + print $text; + } +} + + +## -- e x t r a n a v i g a t i o n l i n k s -- ######################## + +function Page::lay_nav_links() : string[] { + var string[] ret = []; + return $ret; +} + +function RecentPage::lay_nav_links() : string[] { + var string[] ret = []; var int i = 0; + if (viewer_is_owner()) { + $ret[$i] = """Update Journal"""; $i++; + } + if ($.nav.forward_url != "" or $.nav.backward_url != "") { + if ($.nav.backward_url != "") { + var string previous = get_plural_phrase($.nav.backward_count, "text_skiplinks_back"); + $ret[$i] = """$previous"""; $i++; + } + if ($.nav.forward_url != "") { + var string next = get_plural_phrase($.nav.forward_count, "text_skiplinks_forward"); + $ret[$i] = """$next"""; $i++; + } + } + return $ret; +} + +function EntryPage::lay_nav_links() : string[] { + var string[] ret; var int i = 0; + var Link prev = $.entry->get_link("nav_prev"); + var Link next = $.entry->get_link("nav_next"); + + if ($prev.url != "" or $next.url != "") { + if ($prev.url != "") { + $ret[$i] = """$prev.caption"""; $i++; + } + if ($next.url != "") { + $ret[$i] = """$next.caption"""; + } + } + return $ret; +} + +function YearPage::lay_nav_links() : string[] { + var string[] ret; var int i = 0; + foreach var YearYear y ($.years) { + if ($y.displayed) { + $ret[$i] = """$y.year\n"""; + } else { + $ret[$i] = """$y.year\n"""; + } + $i++; + } + return $ret; +} + +function MonthPage::lay_nav_links() : string[] { + var string[] ret = []; var int i; + var string links = ""; + if ($.prev_url != "") { $ret[$i] = """"""+$.prev_date->date_format($*lang_fmt_month_long)+""""""; $i++; } + if ($.next_url != "") { $ret[$i] = """"""+$.next_date->date_format($*lang_fmt_month_long)+""""""; $i++; } + + return $ret; +} + +function DayPage::lay_nav_links() : string[] { + var string[] ret = []; + $ret[0] = """$*text_day_prev"""; + $ret[1] = """$*text_day_next"""; + return $ret; +} + + +## -- p r i n t s i d e b a r -- ########################################## + +function Page::lay_print_sidebar() { + var Page p = get_page(); + + var string userpic; + var Image up_img = $.journal.default_pic; + if (defined $up_img) { + $userpic = """
      +
      +
      +
      +
      + """; + } + var string website; + if ($.journal.website_url != "") { + $website = """
    • $.journal.website_name
    • \n"""; + } + + """ + + """; +} + + +## -- p r i n t c a l e n d a r -- ######################################## + +function print_calendar() : string { + var string calendar = ""; + var Page p = get_page(); + var YearMonth m = $p->get_latest_month(); + var string month = $m->month_format(); + if($m.has_entries) { + $calendar = """ +
      + + + """; + var YearWeek[] theWeeks = $m.weeks; + foreach var YearWeek w ($theWeeks) { + var YearDay[] theDays = $w.days; + var int start = $w.pre_empty; + foreach var YearDay d ($theDays) { + $start = $start + 1; + $calendar = $calendar + "\n "; + } else { + $calendar = $calendar + """MiniCalDay">""" + $d.day->zeropad(2) + ""; + } + } + } + $calendar = $calendar + "\n \n
      $month  """ + $d.day->zeropad(2) + "
      \n
      \n"; + } + if ($calendar == "") { + return "Nothing to see here."; + } + return $calendar; +} + + +## -- p r i n t p a g e -- ################################################ + +function Page::print () +{ + var string title = $this->title(); + var string headerimg = $*header_image ? "" : ""; + + # HEAD + """\n + + + + + """; + $this->print_head(); + """ + + $title + + """; + + # BODY + """ + + +
      + """; + if ($*pres_show_cal and $this.view != "friends") { + print print_calendar(); + } + + if ($*pres_sidebar_align == "left") { + $this->lay_print_sidebar(); + } + """ + +
      + + + + """; + + $this->print_body(); + + var string[] submenu = $this->lay_nav_links(); + if (size $submenu > 0) { + "
      "; + foreach var string subitem ($submenu) { + print """$subitem  """; + } + "
      "; + } + "
      "; + + if ($*pres_sidebar_align == "right") { + $this->lay_print_sidebar(); + } +"
      "; +""" + +"""; +} + + +## -- p r i n t e n t r y -- ############################################## + +function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) +{ + var string date = $e.time->date_format($*text_date_format); + var string time = $e.time->time_format($*text_time_format); + var string entrybarstyle = ""; + var string h3style = ""; + var string link_separator = separator(); + + if ($bgcolor and $fgcolor) { + if ($e.subject->length() > 0 and $p.view == "friends" and $*pres_use_gradients) { + var Color gbg = $fgcolor->average($bgcolor); + var string gstart = $gbg.as_string->substr(1, 6); + var string gend = $bgcolor.as_string->substr(1, 6); + var string gradient = "$*PALIMGROOT/shadow/t.gif/pt" + $gstart + $gend; + $entrybarstyle = " style=\"background: url($gradient) repeat-x;\""; + $h3style = " style=\"background-color: $bgcolor; color: $fgcolor;\""; + } else { + if (not defined $bgcolor) { + $bgcolor = $*col_border; + } + } + } else { + if (not defined $bgcolor) { + $bgcolor = $*col_border; + } + } + + "\n \n
      \n
      \n"; + if (defined $e.userpic and ($*show_entry_userpic or $p.view == "friends")) { + "
      \n "; + print $e.userpic->as_string(); + "\n
      \n"; + } + if ( $e.subject ) { + " $e.subject\n"; + } + + " Posted $e.security "; + if ($e.poster.username != $e.journal.username) { + if ($e.journal.journal_type == "C" or $e.journal.journal_type == "S") { "by " + $e.poster->as_string(); } + if ($p.view == "friends") { " in " + $e.journal->as_string(); } + } else { + if ($p.view == "friends") { + if ($e.journal.journal_type == "Y") { + "in "; + } else { + "by "; + } + print $e.journal->as_string(); + } + } + " on $date at $time\n"; + + if ( not $hide_text ) { + # current mood, music etc + if ( size $e.metadata ) { + foreach var string k ( $e.metadata ) { + var string key = $k; + var string val = $e.metadata{$k}; + if ( $k == "mood" ) { + $key = $*text_meta_mood; + } elseif ( $k == "music" ) { + $key = $*text_meta_music; + } + if ($k == "mood" and defined $e.mood_icon) { + var Image i = $e.mood_icon; + $val = "\"\" $val"; + } + "
      \n $key: $val\n"; + } + } + # entry tags (why isn't this in $e.metadata?) + if ($e.tags) { + var int tcount = 0; + "
      Tags: "; + foreach var Tag t ($e.tags) { + """"""; + $tcount++; + if ($tcount != size $e.tags) { ", "; } + } + ""; + } + "
      \n
      \n "; + # entry text! + print $e.text;"\n
      \n"; + "
      \n"; + $e.comments->print(); + + var Link l = new Link; + var int c = 0; + var string ca = ""; + foreach var string ls ($e.link_keyseq) { + $l = $e->get_link($ls); + if (defined $l) { + if ($c > 0) { print $link_separator; } + # Need a switch/case statement here, or core + # string properties for the following link text + if ($ls == "mem_add") { $ca = $*text_add_mem; } + elseif ($ls == "edit_tags") { $ca = $*text_edit_tags; } + elseif ($ls == "edit_entry") { $ca = $*text_edit_entry; } + else { $ca = $l.caption; } + """$ca """; + $c++; + } + } + "
      "; + + } + "

      "; +} + +function Page::print_entry ( Entry e ) +{ + print_entry( $this, $e, null Color, null Color, false ); +} + +function FriendsPage::print_entry ( Entry e ) +{ + var Friend f = $.friends{$e.journal.username}; + print_entry( $this, $e, $f.bgcolor, $f.fgcolor, false ); +} + +function RecentPage::print_body { + foreach var Entry e ( $.entries ) { + $this->print_entry( $e ); + } +} + +function FriendsPage::print_body +{ + foreach var Entry e ( $.entries ) { + $this->print_entry( $e ); + } +} + +## -- p r i n t c o m m e n t i n f o -- ################################ + +function CommentInfo::print () +{ + var Page p = get_page(); + var string link_separator = separator(); + + "
      \n "; + if ( not $.enabled ) { + "$*text_permalink"; + "\n
      "; + return; + } + if ( $.count > 0 or $.screened and $p.view != "entry") { + $this->print_readlink(); + } else { + "$*text_permalink"; + } + "$link_separator"; $this->print_postlink(); + "\n
    "; +} + + +## -- p r i n t e n t r y p a g e -- #################################### + +function EntryPage::print_body () +{ + +# disabled until someone can figure out why these guys aren't working +# set_handler("unscreen_comment_#", [ [ "set_class", "cmtbox#", "commentBoxOne", ], ]); +# set_handler("screen_comment_#", [ [ "set_class", "cmtbox#", "commentBoxScreened", ], ]); + + print_entry ( $this, $.entry, null Color, null Color, $.viewing_thread ); + if ( $.entry.comments.enabled and $.comment_pages.total_subitems > 0) + { + print "

    Comments:


    "; + if ( $this.multiform_on ) { + $this->print_multiform_start(); + } + if ( $.comment_pages.total_subitems > 0 ) { + $.comment_pages->print(); + $this->print_comments( $.comments ); + } + if ($this.multiform_on) { + print "

    Mass Action:

    "; + $this->print_multiform_actionline(); + $this->print_multiform_end(); + "

    "; + } + "
    "; + } +} + + +## -- p r i n t e n t r y c o m m e n t -- ############################## + +function EntryPage::print_comment ( Comment c ) +{ + var string userpic; + var string boxclass = ""; + var string boxheight = ""; + var string poster = defined $c.poster ? $c.poster->as_string() : "$*text_poster_anonymous"; + var string sub_icon = defined $c.subject_icon ? $c.subject_icon->as_string() : "" ; + + if ( $c.screened ) { + $boxclass = "commentBoxScreened"; + } else { + $boxclass = $c.depth % 2 ? "commentBoxOne" : "commentBoxTwo"; + } + + if ( defined $c.userpic and $*comment_userpic_style != "off" ) { + var int w = $c.userpic.width; + var int h = $c.userpic.height; + if ( $*comment_userpic_style == "small" ) { + $w = $w / 2; + $h = $h / 2; + } + $userpic = "
    \"$c.poster.name\"
    "; + } + """ + +
    + $userpic + "; + if ( $c.subject != "" ) { print "

    $c.subject $c.subject_icon

    "; } + "
    $c.text
    "; + "
    "; + if ( $this.multiform_on ) { + "
    "; + $c->print_multiform_check(); + "
    "; + } + if ( $c.frozen ) { + print $*text_comment_frozen + " :: "; + } else { + "($*text_comment_reply) "; + } + if ( $c.parent_url != "" ) { + "($*text_comment_parent) "; + } + if ( $c.thread_url != "" ) { + "($*text_comment_thread) "; + } + "
    \n\n"; +} + + +## -- p r i n t r e p l y p a g e -- #################################### + +function ReplyPage::print_body () +{ + if ( not $.entry.comments.enabled ) { + "$*text_reply_nocomments_header
    $*text_reply_nocomments"; + return; + } + + var string time = $.replyto.time->time_format($*text_time_format); + var string date = $.replyto.time->date_format($*text_date_format); + """
    """; + if (defined $.replyto.userpic) { + """
    """; + } + if ( $.replyto.subject ) { print "

    $.replyto.subject

    "; } + "Posted by "; + print defined $.replyto.poster ? $.replyto.poster->as_string() : "(Anonymous)"; + " on $date at $time
    "; + "
    "; + print $.replyto.text + "
    "; + """

    "; + """
    """; + var string what = $.replyto.permalink_url == $.entry.permalink_url ? "entry" : "comment" ; + "

    Reply to this $what:

    "; + $.form->print(); + "
    "; +} + + +## -- p r i n t m o n t h p a g e -- #################################### + +function MonthPage::print_body { + "
    "; + $.redir->print_hiddens(); + var string select; + if (size $.months > 1) { + $select = "\n"; + } + + """ +
    $select
    + """; + "
    "; + "
    "; + foreach var MonthDay d ($.days) { + if ($d.has_entries) { + """ + + +
    + +
    +
    + """; + $d->print_subjectlist(); + """ +
    +
    +
    + + """; + } + } + "
    "; +} + + +## -- p r i n t y e a r p a g e -- ###################################### + +function YearWeek::print() { + """ + + """; + if ($.pre_empty > 0) { + """ + + """; + } + + foreach var YearDay d ($.days) { + var string day = zeropad($d.day, 2); + ""; + if ($d.num_entries > 0) { + var string num = string($d.num_entries); + """ +